From bdb0103c57bdf43f3c783442799d5a9be3005fc3 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Tue, 27 Nov 2018 10:31:16 +0800 Subject: [PATCH 0001/1060] dv: fix the flickered problem [1/1] PD#SWPL-1207 Problem: fix the filckered problem when playing transition video in sdr tv Solution: when dv core2 don't run, the reset can't be executed Verify: r321 Change-Id: I719325f1722589e02a40d46442258b0d1e3feb17 Signed-off-by: Yi Zhou --- drivers/amlogic/media/osd/osd_hw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 44482063bcbd..2195be48f13b 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -7931,6 +7931,19 @@ static void osd_basic_update_disp_geometry(u32 index) osd_hw.src_data[index].h - 1) & 0x1fff) << 16; VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk0_cfg_w2, data32); buffer_h = ((data32 >> 16) & 0x1fff) - (data32 & 0x1fff) + 1; + if (osd_hw.osd_meson_dev.has_dolby_vision) { + VSYNCOSD_WR_MPEG_REG( + DOLBY_CORE2A_SWAP_CTRL1, + ((buffer_w + 0x40) << 16) + | (buffer_h + 0x80 + 0)); + VSYNCOSD_WR_MPEG_REG( + DOLBY_CORE2A_SWAP_CTRL2, + (buffer_w << 16) | (buffer_h + 0)); + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + update_graphic_width_height(buffer_w, buffer_h); +#endif + } data32 = VSYNCOSD_RD_MPEG_REG(osd_reg->osd_ctrl_stat); data32 &= ~0x1ff008;//0x1ff00e; data32 |= osd_hw.gbl_alpha[index] << 12; From 66594ea081fb0076baa6712f11197333efb3bc43 Mon Sep 17 00:00:00 2001 From: "shuanglong.wang" Date: Thu, 17 Jan 2019 17:58:00 +0800 Subject: [PATCH 0002/1060] video: video peek do not post video start event [1/1] PD#SWPL-4317 Problem: for video peek, before audio post audio start, video may have rended. Solution: do not post video start for video peek, all wait for audio start to start pcr Verify: verify by p212 Change-Id: If5656154e30613164465f84c44d3fd1ee386d654 Signed-off-by: shuanglong.wang --- drivers/amlogic/media/video_sink/video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 4a88ab2b588a..ecb9c19e6ff3 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -7761,6 +7761,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) put_user(video_onoff_state, (u32 __user *)argp); break; } + case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED: put_user(first_frame_toggled, (u32 __user *)argp); break; From 12b784cf990c6e31c51aa91baa48d211236fee51 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Tue, 15 Jan 2019 11:08:52 +0800 Subject: [PATCH 0003/1060] hdmitx: eliminate the work of sdr effect when choosing hdr [1/1] PD#SWPL-4079 Problem: hdr->sdr must have 1.5s delay, when switching from sdr->hdr the work queue can't be eliminated in time. Solution: eliminate the work of sdr effect when choosing hdr Verify: u212 Change-Id: I4c1d5467a58253ffa2fa12dfbac7f504d0388a00 Signed-off-by: Yi Zhou --- drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 16f9a16bac3a..0e5cd174f410 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -1236,6 +1236,10 @@ static void hdr_work_func(struct work_struct *work) CONF_AVI_BT2020, hdev->colormetry); msleep(1500);/*delay 1.5s*/ + if (hdev->hdr_transfer_feature != T_BT709 || + hdev->hdr_color_feature != C_BT709) + return; + hdev->HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); hdev->hdmi_current_hdr_mode = 0; hdmitx_sdr_hdr_uevent(hdev); From 3e1723e1f37b54c4daa026188c83c9c0a060b6f8 Mon Sep 17 00:00:00 2001 From: Jian Wang Date: Fri, 1 Feb 2019 16:08:05 +0800 Subject: [PATCH 0004/1060] video: fixed video peek get first frame toggled err [1/1] PD#SWPL-4048 Problem: video peek can not get first frame toggled on 64bit Solution: add the cmd to amvideo_compat_ioctl Verify: verify on p212 Change-Id: I6933f305382d636f5f98f4bf19fddcf6ce9471c1 Signed-off-by: Jian Wang --- drivers/amlogic/media/video_sink/video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index ecb9c19e6ff3..7b2d667ff569 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -7831,6 +7831,7 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_VSYNC_UPINT: case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR: case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: + case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED: case AMSTREAM_IOC_SET_VIDEOPEEK: return amvideo_ioctl(file, cmd, arg); default: From 790f0fe510fa077effcf099c4ce3875e523eeaf1 Mon Sep 17 00:00:00 2001 From: "shuanglong.wang" Date: Sun, 24 Feb 2019 15:45:02 +0800 Subject: [PATCH 0005/1060] video: set vpp super_scaler default to 0 [1/1] PD#SWPL-5113 Problem: video flash when resolution change from 4K to 640x480 Solution: temporary solution for video flash for u212 Verify: verify by u212 Change-Id: I8b7ec009bf599032c7bff5f80b72b557403355da Signed-off-by: shuanglong.wang --- drivers/amlogic/media/video_sink/video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 7b2d667ff569..edef27181f01 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -10506,6 +10506,8 @@ static int __init video_init(void) cur_dispbuf = NULL; cur_dispbuf2 = NULL; amvideo_register_client(&amvideo_notifier); + /* set supoer_scaler to false default*/ + super_scaler = false; #ifdef FIQ_VSYNC /* enable fiq bridge */ From 299f31a83bf39870bba5dc8f604baf16c1075d96 Mon Sep 17 00:00:00 2001 From: Yingwei Long Date: Thu, 28 Feb 2019 20:01:24 +0800 Subject: [PATCH 0006/1060] tsync: do not operate tsync_mode_switch before first video toggled [1/1] PD#SWPL-5131 Problem: Some stream in tunnel mode, first audio pts is large than AV_DISCONTINUE_THREDHOLD_MAX(60s). In audio_hw it will check pcr and apts diff, so large difference between pcr and apts will lead sync mode from amster to vmaster(egg:SYNC-HEVC-59FPS-DDP51) Solution: do not operate tsync_mode_switch before first video toggled Verify: verify by franklin Change-Id: Icec2de71ea8f838146444aa3ea880f76ed8e0f13 Signed-off-by: Yingwei Long --- drivers/amlogic/media/frame_sync/tsync.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index df091fe34171..2b41eb182cbf 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -1155,8 +1155,9 @@ int tsync_set_apts(unsigned int pts) t = timestamp_vpts_get(); else t = timestamp_pcrscr_get(); + /* do not switch tsync mode until first video toggled. */ if ((abs(oldpts - pts) > tsync_av_threshold_min) && - (!get_vsync_pts_inc_mode())) { /* is discontinue */ + (timestamp_firstvpts_get() > 0)) { /* is discontinue */ apts_discontinue = 1; tsync_mode_switch('A', abs(pts - t), pts - oldpts); /*if in VMASTER ,just wait */ From 4bd9477282ce927549b7b4d2fa6331e7fc529686 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 1 Mar 2019 21:48:35 +0800 Subject: [PATCH 0007/1060] audio: audio glitch at tdm startup [1/1] PD#SWPL-5219 Problem: audio glitch at tdm startup Solution: Pad 0 data to clear the remaining data in the module. Verify: Local tested. Change-Id: Iab526c6893a32030799567b57e05e7bb11b8fea0 Signed-off-by: Shuai Li --- sound/soc/amlogic/auge/spdif.c | 3 +++ sound/soc/amlogic/auge/tdm.c | 34 +++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 5db566dd196a..6b831e4b0f92 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -1186,6 +1186,9 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "S/PDIF Playback disable\n"); + memset(substream->runtime->dma_area, + 0, substream->runtime->dma_bytes); + mdelay(3); aml_frddr_enable(p_spdif->fddr, 0); } else { dev_info(substream->pcm->card->dev, "S/PDIF Capture disable\n"); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 1e2b55b9837e..c93cd14eb51d 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -512,16 +512,6 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, { struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); - /* share buffer trigger */ - if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - && p_tdm->chipinfo - && p_tdm->chipinfo->same_src_fn - && (p_tdm->samesource_sel >= 0) - && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { - sharebuffer_trigger(cmd, p_tdm->samesource_sel); - } - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -543,6 +533,14 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback enable\n"); + /* share buffer trigger */ + if (p_tdm->chipinfo + && p_tdm->chipinfo->same_src_fn + && (p_tdm->samesource_sel >= 0) + && (aml_check_sharebuffer_valid(p_tdm->fddr, + p_tdm->samesource_sel))) { + sharebuffer_trigger(cmd, p_tdm->samesource_sel); + } aml_frddr_enable(p_tdm->fddr, 1); } else { dev_info(substream->pcm->card->dev, "tdm capture enable\n"); @@ -563,16 +561,26 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, break; } - aml_tdm_enable(p_tdm->actrl, - substream->stream, p_tdm->id, false); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback stop\n"); + memset(substream->runtime->dma_area, + 0, substream->runtime->dma_bytes); + mdelay(3); aml_frddr_enable(p_tdm->fddr, 0); + /* share buffer trigger */ + if (p_tdm->chipinfo + && p_tdm->chipinfo->same_src_fn + && (p_tdm->samesource_sel >= 0) + && (aml_check_sharebuffer_valid(p_tdm->fddr, + p_tdm->samesource_sel))) { + sharebuffer_trigger(cmd, p_tdm->samesource_sel); + } } else { dev_info(substream->pcm->card->dev, "tdm capture stop\n"); aml_toddr_enable(p_tdm->tddr, 0); } + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, false); break; default: return -EINVAL; From b11abbcd104d248b20d10fb08b7be2052dcb7838 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 22 Feb 2019 12:57:33 +0800 Subject: [PATCH 0008/1060] audio: fix samesource clk after play DDP [1/1] PD#SWPL-4331 Problem: Same source clk doesn't recover to 48K after playback 192k DDP stream. Solution: Add ways to recover the clk. Verify: Local verified Change-Id: If410d9ca04446c35bafebe2913b01e19b5fee224 Signed-off-by: Shuai Li --- MAINTAINERS | 1 + sound/soc/amlogic/auge/spdif.c | 46 +++++++++++++++++++++---------- sound/soc/amlogic/auge/spdif.h | 31 +++++++++++++++++++++ sound/soc/amlogic/auge/spdif_hw.c | 2 +- sound/soc/amlogic/auge/tdm.c | 4 +++ 5 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 sound/soc/amlogic/auge/spdif.h diff --git a/MAINTAINERS b/MAINTAINERS index ceaa88a5c4ec..a37b89cfa903 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13800,6 +13800,7 @@ F: arch/arm/boot/dts/amlogic> ANLOGIC AUDIO M: Xing Wang +M: Shuai Li F: arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts F: arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts F: arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 6b831e4b0f92..c107d96117e3 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -39,12 +39,10 @@ #include "audio_utils.h" #include "resample.h" #include "resample_hw.h" +#include "spdif.h" #define DRV_NAME "aml_spdif" -#define SPDIF_A 0 -#define SPDIF_B 1 - /* Debug by PTM when bringup */ /*#define __PTM_SPDIF_CLK__*/ @@ -54,7 +52,7 @@ /*#define __SPDIFIN_AUDIO_TYPE_HW__*/ struct spdif_chipinfo { - unsigned int id; + enum SPDIF_ID id; /* add ch_cnt to ch_num */ bool chnum_en; @@ -93,7 +91,7 @@ struct aml_spdif { /* external connect */ struct extcon_dev *edev; - unsigned int id; + enum SPDIF_ID id; struct spdif_chipinfo *chipinfo; unsigned int clk_cont; /* CONTINUOUS CLOCK */ @@ -125,6 +123,7 @@ struct aml_spdif { /* last value for pc, pd */ int pc_last; int pd_last; + bool on; }; static const struct snd_pcm_hardware aml_spdif_hardware = { @@ -167,6 +166,20 @@ static const char *const spdifin_samplerate[] = { "192000" }; +struct aml_spdif *spdif_priv[SPDIF_ID_CNT]; +int spdif_set_audio_clk(enum SPDIF_ID id, + struct clk *clk_src, int rate, bool same) +{ + if (spdif_priv[id]->on && same) { + pr_debug("spdif priority"); + return 0; + } + + clk_set_parent(spdif_priv[id]->clk_spdifout, clk_src); + clk_set_rate(spdif_priv[id]->clk_spdifout, rate); + return 0; +} + static int spdifin_samplerate_get_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -667,6 +680,7 @@ static int aml_spdif_open(struct snd_pcm_substream *substream) snd_soc_set_runtime_hwparams(substream, &aml_spdif_hardware); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + p_spdif->on = 1; p_spdif->fddr = aml_audio_register_frddr(dev, p_spdif->actrl, aml_spdif_ddr_isr, substream); @@ -712,6 +726,7 @@ static int aml_spdif_close(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { aml_audio_unregister_frddr(p_spdif->dev, substream); + p_spdif->on = 0; } else { aml_audio_unregister_toddr(p_spdif->dev, substream); free_irq(p_spdif->irq_spdifin, p_spdif); @@ -725,7 +740,7 @@ static int aml_spdif_close(struct snd_pcm_substream *substream) } /* clear extcon status */ - if (p_spdif->id == 0) { + if (p_spdif->id == SPDIF_A) { extcon_set_state(p_spdif->edev, EXTCON_SPDIFIN_SAMPLERATE, 0); @@ -871,7 +886,7 @@ static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd) pr_debug("%s spdif_%s, clk continuous:%d\n", __func__, - (p_spdif->id == 0) ? "a":"b", + (p_spdif->id == SPDIF_A) ? "a":"b", p_spdif->clk_cont); /* keep frddr when probe, after spdif_frddr_init done @@ -927,7 +942,7 @@ static int aml_dai_spdif_startup( if (p_spdif->clk_cont) { pr_info("spdif_%s keep clk continuous\n", - (p_spdif->id == 0) ? "a":"b"); + (p_spdif->id == SPDIF_A) ? "a":"b"); return 0; } /* enable clock gate */ @@ -1000,7 +1015,7 @@ static void aml_dai_spdif_shutdown( if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (p_spdif->clk_cont) { pr_info("spdif_%s keep clk continuous\n", - (p_spdif->id == 0) ? "a":"b"); + (p_spdif->id == SPDIF_A) ? "a":"b"); return; } @@ -1037,10 +1052,10 @@ static int aml_dai_spdif_prepare( struct iec958_chsts chsts; switch (p_spdif->id) { - case 0: + case SPDIF_A: dst = SPDIFOUT_A; break; - case 1: + case SPDIF_B: dst = SPDIFOUT_B; break; default: @@ -1259,8 +1274,10 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif) mpll_freq = p_spdif->sysclk_freq * 58 / 2; /* 96k */ #endif clk_set_rate(p_spdif->sysclk, mpll_freq); - clk_set_rate(p_spdif->clk_spdifout, - p_spdif->sysclk_freq); + //clk_set_rate(p_spdif->clk_spdifout, + // p_spdif->sysclk_freq); + spdif_set_audio_clk(p_spdif->id, + p_spdif->sysclk, p_spdif->sysclk_freq, 0); ret = clk_prepare_enable(p_spdif->sysclk); if (ret) { @@ -1355,7 +1372,7 @@ static int aml_spdif_parse_of(struct platform_device *pdev) int ret = 0; /* clock for spdif in */ - if (p_spdif->id == 0) { + if (p_spdif->id == SPDIF_A) { /* clock gate */ p_spdif->gate_spdifin = devm_clk_get(dev, "gate_spdifin"); if (IS_ERR(p_spdif->gate_spdifin)) { @@ -1548,6 +1565,7 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) dev_warn_once(dev, "check whether to update spdif chipinfo\n"); + spdif_priv[aml_spdif->id] = aml_spdif; pr_debug("%s, spdif ID = %u\n", __func__, aml_spdif->id); /* get audio controller */ diff --git a/sound/soc/amlogic/auge/spdif.h b/sound/soc/amlogic/auge/spdif.h new file mode 100644 index 000000000000..d6e6ba0f8af4 --- /dev/null +++ b/sound/soc/amlogic/auge/spdif.h @@ -0,0 +1,31 @@ +/* + * sound/soc/amlogic/auge/spdif.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __AML_SPDIF_H__ +#define __AML_SPDIF_H__ +#include + +enum SPDIF_ID { + SPDIF_A, + SPDIF_B, + SPDIF_ID_CNT +}; + +int spdif_set_audio_clk(enum SPDIF_ID id, + struct clk *clk_src, int rate, bool same); + +#endif diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index d83fb6afda9a..de1f103b0b55 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -486,7 +486,7 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, /* clk for spdif_b is always on */ /*if (!spdif_id)*/ - spdifout_clk_ctrl(spdif_id, /*is_enable*/true); + //spdifout_clk_ctrl(spdif_id, /*is_enable*/true); if (is_enable) spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index c93cd14eb51d..cc7e9435a637 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -40,6 +40,7 @@ #include "tdm_hw.h" #include "sharebuffer.h" #include "vad.h" +#include "spdif.h" /*#define __PTM_TDM_CLK__*/ @@ -393,6 +394,9 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, p_tdm->samesource_sel))) { sharebuffer_prepare(substream, fr, p_tdm->samesource_sel); + /* sharebuffer default uses spdif_a */ + spdif_set_audio_clk(SPDIF_A, p_tdm->clk, + runtime->rate*128, 1); } /* i2s source to hdmix */ From f04b7e5b313c763e422421fdab86ca90d4778629 Mon Sep 17 00:00:00 2001 From: Zhuo Wang Date: Fri, 20 Jul 2018 11:10:50 +0800 Subject: [PATCH 0009/1060] ethernet: handle tx timeout PD# 169839 After do suspend/resume circularly, sometimes ethernet can't recover from suspend. Add a phy reset when every resume. Change-Id: Id03223a9c62f4dcab1cdfbc4805cc3b4c0212cf5 Signed-off-by: Shen Liu --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3e77065811c8..35ce8e105346 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -124,6 +124,8 @@ static void stmmac_exit_fs(struct net_device *dev); #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) +static struct workqueue_struct *moniter_tx_wq; +static struct delayed_work moniter_tx_worker; /** * stmmac_verify_args - verify the driver parameters. * Description: it checks the driver parameters and set a default in case of @@ -1451,8 +1453,9 @@ static void stmmac_tx_err(struct stmmac_priv *priv) priv->hw->desc->init_tx_desc(&priv->dma_tx[i], priv->mode, (i == DMA_TX_SIZE - 1)); - priv->dirty_tx = 0; - priv->cur_tx = 0; + //priv->dirty_tx = 0; + //priv->cur_tx = 0; + priv->cur_tx = priv->dirty_tx; netdev_reset_queue(priv->dev); priv->hw->dma->start_tx(priv->ioaddr); @@ -1875,6 +1878,7 @@ static int stmmac_open(struct net_device *dev) napi_enable(&priv->napi); netif_start_queue(dev); + queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); return 0; lpiirq_error: @@ -2717,12 +2721,14 @@ static int stmmac_poll(struct napi_struct *napi, int budget) * netdev structure and arrange for the device to be reset to a sane state * in order to transmit a new packet. */ +unsigned int timeout_err; static void stmmac_tx_timeout(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); /* Clear Tx resources and restart transmitting again */ stmmac_tx_err(priv); + timeout_err = 1; } /** @@ -3260,6 +3266,21 @@ static int stmmac_hw_init(struct stmmac_priv *priv) return 0; } +struct stmmac_priv *priv_monitor; +static void moniter_tx_handler(struct work_struct *work) +{ + if (priv_monitor) { + if (timeout_err) { + pr_info("recover eth\n"); + stmmac_release(priv_monitor->dev); + stmmac_open(priv_monitor->dev); + timeout_err = 0; + } + } else { + pr_info("device not init yet!\n"); + } + queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); +} /** * stmmac_dvr_probe * @device: device pointer @@ -3278,6 +3299,8 @@ int stmmac_dvr_probe(struct device *device, struct net_device *ndev = NULL; struct stmmac_priv *priv; + moniter_tx_wq = create_singlethread_workqueue("eth_moniter_tx_wq"); + INIT_DELAYED_WORK(&moniter_tx_worker, moniter_tx_handler); ndev = alloc_etherdev(sizeof(struct stmmac_priv)); if (!ndev) return -ENOMEM; @@ -3429,6 +3452,7 @@ int stmmac_dvr_probe(struct device *device, ret = gmac_create_sysfs( mdiobus_get_phy(priv->mii, priv->plat->phy_addr), priv->ioaddr); #endif + priv_monitor = priv; return ret; error_netdev_register: @@ -3499,6 +3523,7 @@ int stmmac_suspend(struct device *dev) struct stmmac_priv *priv = netdev_priv(ndev); unsigned long flags; + cancel_delayed_work_sync(&moniter_tx_worker); if (!ndev || !netif_running(ndev)) return 0; @@ -3604,7 +3629,6 @@ int stmmac_resume(struct device *dev) stmmac_init_tx_coalesce(priv); stmmac_set_rx_mode(ndev); - #ifdef CONFIG_AMLOGIC_ETH_PRIVE netif_device_attach(ndev); #endif @@ -3617,6 +3641,8 @@ int stmmac_resume(struct device *dev) if (priv->phydev) phy_start(priv->phydev); + queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); + timeout_err = 1; return 0; } EXPORT_SYMBOL_GPL(stmmac_resume); From 6c0aa55c7a6ee4640f2fa7473d4dc18c086e99fc Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Mon, 11 Mar 2019 15:55:09 +0800 Subject: [PATCH 0010/1060] hdmitx: sync hdmi_audio uevent to hdmi hpd Change-Id: I39512030f058ab9c72ee4c779f3b692898440271 Signed-off-by: Luan Yuan --- .../media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 14 +------------- .../media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 2 -- .../amlogic/media/vout/hdmi_tx/hdmi_tx_module.h | 1 - 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 0e5cd174f410..269cf9cdee5a 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -3839,17 +3839,6 @@ static void clear_hdr_info(struct hdmitx_dev *hdev) } } -static void hdmitx_aud_hpd_plug_handler(struct work_struct *work) -{ - int st; - struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, - struct hdmitx_dev, work_aud_hpd_plug); - - st = hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0); - pr_info("hdmitx_aud_hpd_plug_handler state:%d\n", st); - extcon_set_state_sync(hdmitx_extcon_audio, EXTCON_DISP_HDMI, st); -} - static void hdmitx_hpd_plugout_handler(struct work_struct *work) { struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, @@ -3890,6 +3879,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->hpd_state = 0; hdmitx_notify_hpd(hdev->hpd_state); extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 0); + extcon_set_state_sync(hdmitx_extcon_audio, EXTCON_DISP_HDMI, 0); mutex_unlock(&setclk_mutex); } @@ -3948,8 +3938,6 @@ static int hdmi_task_handle(void *data) hdmitx_hpd_plugin_handler); INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugout, hdmitx_hpd_plugout_handler); - INIT_DELAYED_WORK(&hdmitx_device->work_aud_hpd_plug, - hdmitx_aud_hpd_plug_handler); INIT_WORK(&hdmitx_device->work_internal_intr, hdmitx_internal_intr_handler); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 61bb649f3860..26aa5cb9fae4 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -688,8 +688,6 @@ static irqreturn_t intr_handler(int irq, void *dev) } /* HPD falling */ if (dat_top & (1 << 2)) { - queue_delayed_work(hdev->hdmi_wq, - &hdev->work_aud_hpd_plug, 2 * HZ); hdev->hdmitx_event |= HDMI_TX_HPD_PLUGOUT; hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN; hdev->rhpd_state = 0; diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 173d0220b45b..e23ae907eaf7 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -300,7 +300,6 @@ struct hdmitx_dev { struct pinctrl_state *pinctrl_default; struct delayed_work work_hpd_plugin; struct delayed_work work_hpd_plugout; - struct delayed_work work_aud_hpd_plug; struct delayed_work work_rxsense; struct work_struct work_internal_intr; struct work_struct work_hdr; From 5b78bf24f0a07bfd245afd5b594808118cdd4ea6 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 18 Dec 2018 13:15:36 +0800 Subject: [PATCH 0011/1060] osd: fix some fence issue [2/2] PD#SWPL-3348 Problem: fix some fence issue Solution: 1. add blank operation to FBIOPUT_OSD_SYNC_RENDER_ADD 2. move canvas_config to osd_setting_blend Verify: verify by franklin Change-Id: I5d1ebb697ff542e5c36dab0dae9b322ec4e1fa16 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 40 +++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 2195be48f13b..85090b3f1cbd 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1059,7 +1059,7 @@ static int sync_render_layers_fence(u32 index, u32 yres, fence_map->cmd = LAYER_SYNC; fence_map->layer_map[index].fb_index = index; /* layer_map[index].enable will update if have blank ioctl */ - fence_map->layer_map[index].enable = 1; + fence_map->layer_map[index].enable = request->op; fence_map->layer_map[index].in_fd = request->in_fen_fd; if (request->shared_fd < 0) fence_map->layer_map[index].buf_file = NULL; @@ -4084,6 +4084,10 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) osd_hw.in_fd[index] = layer_map->in_fd; osd_hw.buffer_alloc[index] = 1; osd_hw.enable[index] = layer_map->enable; + if (osd_hw.enable[index] == 0) { + osd_log_dbg(MODULE_BASE, "osd%d: blanked\n", index); + return; + } osd_hw.osd_afbcd[index].enable = (layer_map->afbc_inter_format & AFBC_EN) >> 31; if (layer_map->plane_alpha == 0xff) @@ -4149,12 +4153,10 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) /*ext_addr is no crop, so height = * layer_map->src_h + layer_map->src_y */ - canvas_config(osd_hw.fb_gem[index].canvas_idx, - ext_addr, - layer_map->byte_stride, - layer_map->src_h + layer_map->src_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + osd_hw.fb_gem[index].addr = ext_addr; + osd_hw.fb_gem[index].width = layer_map->byte_stride; + osd_hw.fb_gem[index].height = + layer_map->src_h + layer_map->src_y; osd_hw.screen_base[index] = ext_addr; osd_hw.screen_size[index] = layer_map->byte_stride * layer_map->src_h; @@ -4252,7 +4254,7 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) static void osd_pan_display_layers_fence( struct osd_layers_fence_map_s *fence_map) { - int i = 0, index = 0; + int i = 0; int ret; int osd_count = osd_hw.osd_meson_dev.osd_count - 1; /* osd_count need -1 when VIU2 enable */ @@ -4275,7 +4277,6 @@ static void osd_pan_display_layers_fence( osd_hw.hdr_used = fence_map->hdr_mode; for (i = 0; i < osd_count; i++) { layer_map = &fence_map->layer_map[i]; - index = layer_map->fb_index; if (i != layer_map->fb_index) { osd_hw.screen_base[i] = 0; osd_hw.screen_size[i] = 0; @@ -7421,6 +7422,13 @@ static int osd_setting_order(void) struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[i]; update = is_freescale_para_changed(i); + if (!osd_hw.osd_afbcd[i].enable) + canvas_config(osd_hw.fb_gem[i].canvas_idx, + osd_hw.fb_gem[i].addr, + osd_hw.fb_gem[i].width, + osd_hw.fb_gem[i].height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); osd_hw.reg[OSD_COLOR_MODE].update_func(i); if (!osd_hw.dim_layer[i]) { VSYNCOSD_WR_MPEG_REG(osd_reg->osd_dimm_ctrl, @@ -7715,6 +7723,13 @@ static void osd_setting_old_hwc(void) static u32 osd_enable; spin_lock_irqsave(&osd_lock, lock_flags); + if (!osd_hw.osd_afbcd[index].enable) + canvas_config(osd_hw.fb_gem[index].canvas_idx, + osd_hw.fb_gem[index].addr, + osd_hw.fb_gem[index].width, + osd_hw.fb_gem[index].height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); osd_hw.reg[OSD_COLOR_MODE].update_func(index); freescale_update = set_old_hwc_freescale(index); /* geometry and freescale need update with ioctl */ @@ -7746,6 +7761,13 @@ static void osd_setting_viu2(void) { int index = OSD4; + if (!osd_hw.osd_afbcd[index].enable) + canvas_config(osd_hw.fb_gem[index].canvas_idx, + osd_hw.fb_gem[index].addr, + osd_hw.fb_gem[index].width, + osd_hw.fb_gem[index].height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); osd_hw.reg[OSD_COLOR_MODE].update_func(index); /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); From 7265728f055b71c6f1a73f43d096de40e4bac07c Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Wed, 26 Dec 2018 18:55:36 +0800 Subject: [PATCH 0012/1060] vpp: sr: disable core0 and core1 scaler latch [1/1] PD#SWPL-3144 Problem: The latch function cause the super scaler size asynchronous Solution: Disable sr core0 and core1 scaler latch Verify: T962x2 x301 board test pass Change-Id: Iecbcc3e0c751093b6515f7b46973eca2157cd349 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 13 +++++++++++-- .../linux/amlogic/media/registers/regs/vpp_regs.h | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index edef27181f01..5227d3540ffb 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -10324,10 +10324,19 @@ static int __init video_early_init(void) DMC_AM0_CHAN_CTRL, 0x8ff403cf); - /* force bypass dolby for TL1. There is no dolby function */ - if (is_meson_tl1_cpu()) + if (is_meson_tl1_cpu()) { + /* force bypass dolby for TL1, no dolby function */ WRITE_VCBUS_REG_BITS( DOLBY_PATH_CTRL, 0xf, 0, 6); + /* disable latch for sr core0/1 scaler */ + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SYNC_CTRL, 1, 8, 1); + WRITE_VCBUS_REG_BITS( + SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1); + } + if (is_meson_g12b_cpu()) + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SYNC_CTRL, 1, 8, 1); return 0; } diff --git a/include/linux/amlogic/media/registers/regs/vpp_regs.h b/include/linux/amlogic/media/registers/regs/vpp_regs.h index c82b4bad29fe..7daba0912eb6 100644 --- a/include/linux/amlogic/media/registers/regs/vpp_regs.h +++ b/include/linux/amlogic/media/registers/regs/vpp_regs.h @@ -245,5 +245,8 @@ #define OSD1_BLEND_SRC_CTRL 0x1dfd #define OSD2_BLEND_SRC_CTRL 0x1dfe +/* after g12b */ +#define SRSHARP0_SHARP_SYNC_CTRL 0x3eb0 +#define SRSHARP1_SHARP_SYNC_CTRL 0x3fb0 #endif From c7faed0c5577443788b3ea80cec036f8b84f2670 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 16 Nov 2018 00:38:41 +0800 Subject: [PATCH 0013/1060] video: vpp: add vd afbc YUV 422/444 support for tl1 [1/1] PD#172587 Problem: Bringup TL1 vidoe driver. TL1 need support YUV422/444 AFBC. TL1 need check afbc source from decode or vdin. TL1 need afbc compress loss mode. Solution: Merge from branch bringup/amlogic-4.9/tl1-20181111. Verify: verify on tl1 Change-Id: I0af62e7638db4e1c349df874ccffdeddcaa715af Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 323 +++++++++++------- .../amlogic/media/registers/regs/viu_regs.h | 13 + include/linux/amlogic/media/vfm/vframe.h | 4 + 3 files changed, 210 insertions(+), 130 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 5227d3540ffb..3f1144c38441 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -1837,7 +1837,7 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, } #endif -static void zoom_display_horz(int hscale) +static void zoom_display_horz(struct vframe_s *vf, int hscale) { u32 ls = 0, le = 0, rs = 0, re = 0; #ifdef TV_REVERSE @@ -1845,7 +1845,7 @@ static void zoom_display_horz(int hscale) #endif #ifdef TV_3D_FUNCTION_OPEN if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_horz_pos(cur_dispbuf, cur_frame_par->vpp_3d_mode, &ls, + zoom_get_horz_pos(vf, cur_frame_par->vpp_3d_mode, &ls, &le, &rs, &re); } else { ls = rs = zoom_start_x_lines; @@ -1881,6 +1881,13 @@ static void zoom_display_horz(int hscale) int l_aligned; int r_aligned; int h_skip = cur_frame_par->hscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && (vf->type & VIDTYPE_VIU_444)) + c_skip = 1; + if ((zoom_start_x_lines > 0) || (zoom_end_x_lines < ori_end_x_lines)) { l_aligned = round_down(ori_start_x_lines, 32); @@ -1891,7 +1898,7 @@ static void zoom_display_horz(int hscale) } VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_W, (((r_aligned - l_aligned) / h_skip) << 16) | - ((r_aligned / 2 - l_aligned / 2) / h_skip)); + ((r_aligned / c_skip - l_aligned / c_skip) / h_skip)); VSYNC_WR_MPEG_REG(AFBC_MIF_HOR_SCOPE, ((l_aligned / 32) << 16) | @@ -1951,7 +1958,7 @@ static void zoom_display_horz(int hscale) 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } -static void vd2_zoom_display_horz(int hscale) +static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) { u32 ls, le, rs, re; #ifdef TV_REVERSE @@ -1964,6 +1971,12 @@ static void vd2_zoom_display_horz(int hscale) int l_aligned; int r_aligned; int h_skip = cur_frame_par->hscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && (vf->type & VIDTYPE_VIU_444)) + c_skip = 1; if ((zoom2_start_x_lines > 0) || (zoom2_end_x_lines < ori2_end_x_lines)) { @@ -1975,7 +1988,7 @@ static void vd2_zoom_display_horz(int hscale) } VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_W, (((r_aligned - l_aligned) / h_skip) << 16) | - ((r_aligned / 2 - l_aligned / 2) / h_skip)); + ((r_aligned / c_skip - l_aligned / c_skip) / h_skip)); VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_HOR_SCOPE, ((l_aligned / 32) << 16) | @@ -2034,14 +2047,14 @@ static void vd2_zoom_display_horz(int hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } -static void zoom_display_vert(void) +static void zoom_display_vert(struct vframe_s *vf) { u32 ls, le, rs, re; /*if (platform_type == 1) {*/ if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_vert_pos(cur_dispbuf, + zoom_get_vert_pos(vf, cur_frame_par->vpp_3d_mode, &ls, &le, &rs, &re); } else { @@ -2060,7 +2073,7 @@ static void zoom_display_vert(void) } */ - if ((cur_dispbuf) && (cur_dispbuf->type & VIDTYPE_MVC)) { + if ((vf) && (vf->type & VIDTYPE_MVC)) { if (is_need_framepacking_output()) { VSYNC_WR_MPEG_REG( VD1_IF0_LUMA_Y0 + cur_dev->viu_off, @@ -2152,13 +2165,21 @@ static void zoom_display_vert(void) int ori_t_aligned; int ori_b_aligned; int v_skip = cur_frame_par->vscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && ((vf->type & VIDTYPE_VIU_444) + || (vf->type & VIDTYPE_VIU_422))) + c_skip = 1; + t_aligned = round_down(zoom_start_y_lines, 4); b_aligned = round_up(zoom_end_y_lines + 1, 4); ori_t_aligned = round_down(ori_start_y_lines, 4); ori_b_aligned = round_up(ori_end_y_lines + 1, 4); VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_H, - (b_aligned - t_aligned) / 2 / v_skip); + (b_aligned - t_aligned) / c_skip / v_skip); VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, ((t_aligned / 4) << 16) | @@ -2186,7 +2207,7 @@ static void zoom_display_vert(void) } } -static void vd2_zoom_display_vert(void) +static void vd2_zoom_display_vert(struct vframe_s *vf) { u32 ls, le, rs, re; @@ -2221,6 +2242,14 @@ static void vd2_zoom_display_vert(void) int ori_t_aligned; int ori_b_aligned; int v_skip = cur_frame_par->vscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && ((vf->type & VIDTYPE_VIU_444) + || (vf->type & VIDTYPE_VIU_422))) + c_skip = 1; + t_aligned = round_down(zoom2_start_y_lines, 4); b_aligned = round_up(zoom2_end_y_lines + 1, 4); @@ -2229,7 +2258,7 @@ static void vd2_zoom_display_vert(void) /* TODO: afbc setting only support 420 for now */ VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H, - (b_aligned - t_aligned) / 2 / v_skip); + (b_aligned - t_aligned) / c_skip / v_skip); VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE, ((t_aligned / 4) << 16) | @@ -3157,20 +3186,31 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) r |= 0xcc; #ifdef TV_REVERSE if (reverse) - r |= (1<<26)|(1<<27); + r |= (1<<26) | (1<<27); #endif if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ if (type & VIDTYPE_SCATTER) r |= (1<<29); VSYNC_WR_MPEG_REG(AFBC_MODE, r); - VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0x1700); + + r = 0x1700; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (vf && (vf->source_type + != VFRAME_SOURCE_TYPE_HDMI)) + r |= (1 << 19); /* dos_uncomp */ + } + VSYNC_WR_MPEG_REG(AFBC_ENABLE, r); r = 0x100; - /* need check the vf->type 444/422/420 */ - /* current use 420 as default for tl1 */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) - r |= (2 << 12); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } VSYNC_WR_MPEG_REG(AFBC_CONV_CTRL, r); u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; @@ -3180,61 +3220,60 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0x80 << (u + 10) | 0x80 << v); /* chroma formatter */ - /* TODO: afbc setting only cover 420 for now */ -/* -#ifdef TV_REVERSE - if (reverse) { + + r = 0; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() + if (is_meson_txlx_package_962X() && !is_dolby_vision_stb_mode() - && is_dolby_vision_on()) - VSYNC_WR_MPEG_REG( - AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - else -#endif - VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - (0xc << VFORMATTER_INIPHASE_BIT) | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); + && is_dolby_vision_on()) { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; } else #endif -*/ - { -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() - && !is_dolby_vision_stb_mode() - && is_dolby_vision_on()) - VSYNC_WR_MPEG_REG( - AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - else -#endif - VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | (0xc << VFORMATTER_INIPHASE_BIT) | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; } + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + AFBCDEC_IQUANT_ENABLE, 0); + } + vd1_path_select(true); VSYNC_WR_MPEG_REG( @@ -3703,8 +3742,14 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) static const u32 vpat[MAX_VSKIP_COUNT + 1] = { 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; u32 u, v; - u32 type = vf->type, bit_mode = 0; + u32 type, bit_mode = 0; + if (!vf) { + pr_err("vd2_set_dcu vf is NULL\n"); + return; + } + + type = vf->type; pr_debug("set dcu for vd2 %p, type:0x%x\n", vf, type); last_el_w = (vf->type & VIDTYPE_COMPRESS) ? @@ -3724,20 +3769,31 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) #ifdef TV_REVERSE if (reverse) - r |= (1<<26)|(1<<27); + r |= (1<<26) | (1<<27); #endif if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ if (type & VIDTYPE_SCATTER) r |= (1<<29); VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r); - VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0x1700); + + r = 0x1700; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (vf && (vf->source_type + != VFRAME_SOURCE_TYPE_HDMI)) + r |= (1 << 19); /* dos_uncomp */ + } + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, r); r = 0x100; - /* need check the vf->type 444/422/420 */ - /* current use 420 as default for tl1 */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) - r |= (2 << 12); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r); u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; @@ -3746,67 +3802,73 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0x3FF00000 | /*Y,bit20+*/ 0x80 << (u + 10) | 0x80 << v); + /* chroma formatter */ - /* TODO: afbc setting only cover 420 for now */ -#ifdef TV_REVERSE - if (reverse) { + r = HFORMATTER_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() + if (is_meson_txlx_package_962X() && !is_dolby_vision_stb_mode() && is_dolby_vision_on()) { - VSYNC_WR_MPEG_REG( - VD2_AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else -#endif - VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, - (is_dolby_vision_on() ? - HFORMATTER_REPEAT : - HFORMATTER_RRT_PIXEL0) | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (is_dolby_vision_on() ? - (0xc << VFORMATTER_INIPHASE_BIT) : 0) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else { -#endif -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() - && !is_dolby_vision_stb_mode() - && is_dolby_vision_on()) { - VSYNC_WR_MPEG_REG( - VD2_AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else -#endif - VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, - (is_dolby_vision_on() ? - HFORMATTER_REPEAT : - HFORMATTER_RRT_PIXEL0) | + r |= HFORMATTER_REPEAT | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (is_dolby_vision_on() ? - (0xc << VFORMATTER_INIPHASE_BIT) : 0) | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); -#ifdef TV_REVERSE - } + VFORMATTER_EN; + } else #endif + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, 0); + } + vd2_path_select(true); VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, 0); @@ -6074,11 +6136,12 @@ SET_FILTER: zoom_start_x_lines = cur_frame_par->VPP_hd_start_lines_; zoom_end_x_lines = cur_frame_par->VPP_hd_end_lines_; - zoom_display_horz(cur_frame_par->hscale_skip_count); + zoom_display_horz(cur_dispbuf, + cur_frame_par->hscale_skip_count); zoom_start_y_lines = zoom_start_y; zoom_end_y_lines = zoom_end_y; - zoom_display_vert(); + zoom_display_vert(cur_dispbuf); if (is_dolby_vision_enable() && cur_dispbuf2) { zoom2_start_x_lines = ori2_start_x_lines; zoom2_end_x_lines = ori2_end_x_lines; @@ -6086,8 +6149,8 @@ SET_FILTER: zoom2_end_y_lines = ori2_end_y_lines; correct_vd2_mif_size_for_DV( cur_frame_par, cur_dispbuf); - vd2_zoom_display_horz(0); - vd2_zoom_display_vert(); + vd2_zoom_display_horz(cur_dispbuf2, 0); + vd2_zoom_display_vert(cur_dispbuf2); } } /*vpp input size setting*/ diff --git a/include/linux/amlogic/media/registers/regs/viu_regs.h b/include/linux/amlogic/media/registers/regs/viu_regs.h index 20d5df4647a6..9f0299c49089 100644 --- a/include/linux/amlogic/media/registers/regs/viu_regs.h +++ b/include/linux/amlogic/media/registers/regs/viu_regs.h @@ -213,5 +213,18 @@ #define G12_VD1_IF0_GEN_REG3 0x3216 #define G12_VD2_IF0_GEN_REG3 0x3236 +/* TL1 */ +#define AFBCDEC_IQUANT_ENABLE 0x1af2 +#define AFBCDEC_IQUANT_LUT_1 0x1af3 +#define AFBCDEC_IQUANT_LUT_2 0x1af4 +#define AFBCDEC_IQUANT_LUT_3 0x1af5 +#define AFBCDEC_IQUANT_LUT_4 0x1af6 + +#define VD2_AFBCDEC_IQUANT_ENABLE 0x3192 +#define VD2_AFBCDEC_IQUANT_LUT_1 0x3193 +#define VD2_AFBCDEC_IQUANT_LUT_2 0x3194 +#define VD2_AFBCDEC_IQUANT_LUT_3 0x3195 +#define VD2_AFBCDEC_IQUANT_LUT_4 0x3196 + #endif diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index c2936f3f3eca..2a62b6735824 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -45,6 +45,7 @@ #define VIDTYPE_PIC 0x200000 #define VIDTYPE_SCATTER 0x400000 #define VIDTYPE_VD2 0x800000 +#define VIDTYPE_COMPRESS_LOSS 0x1000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 @@ -280,18 +281,21 @@ struct vframe_pic_mode_s { #define BITDEPTH_Y8 (0 << BITDEPTH_Y_SHIFT) #define BITDEPTH_Y9 (1 << BITDEPTH_Y_SHIFT) #define BITDEPTH_Y10 (2 << BITDEPTH_Y_SHIFT) +#define BITDEPTH_Y12 (3 << BITDEPTH_Y_SHIFT) #define BITDEPTH_YMASK (3 << BITDEPTH_Y_SHIFT) #define BITDEPTH_U_SHIFT 10 #define BITDEPTH_U8 (0 << BITDEPTH_U_SHIFT) #define BITDEPTH_U9 (1 << BITDEPTH_U_SHIFT) #define BITDEPTH_U10 (2 << BITDEPTH_U_SHIFT) +#define BITDEPTH_U12 (3 << BITDEPTH_U_SHIFT) #define BITDEPTH_UMASK (3 << BITDEPTH_U_SHIFT) #define BITDEPTH_V_SHIFT 12 #define BITDEPTH_V8 (0 << BITDEPTH_V_SHIFT) #define BITDEPTH_V9 (1 << BITDEPTH_V_SHIFT) #define BITDEPTH_V10 (2 << BITDEPTH_V_SHIFT) +#define BITDEPTH_V12 (3 << BITDEPTH_V_SHIFT) #define BITDEPTH_VMASK (3 << BITDEPTH_V_SHIFT) #define BITDEPTH_MASK (BITDEPTH_YMASK | BITDEPTH_UMASK | BITDEPTH_VMASK) From 35687181a1e84f5f5681b74575d945a6dd1afcd1 Mon Sep 17 00:00:00 2001 From: "wenfeng.guo" Date: Mon, 12 Nov 2018 11:15:24 +0800 Subject: [PATCH 0014/1060] sr: add support for tl1 [1/1] PD#172587 Problem: Add sr driver support for tl1 Solution: add sr driver support for tl1 fix horizontal line when play video on 4K screen Verify: TL1 X301 Change-Id: I422f27eb5cf12f69dc57de295425536671e2df38 Signed-off-by: wenfeng.guo --- drivers/amlogic/media/video_sink/video.c | 17 ++- drivers/amlogic/media/video_sink/vpp.c | 129 +++++++++++++++---- include/linux/amlogic/media/video_sink/vpp.h | 7 +- 3 files changed, 123 insertions(+), 30 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 3f1144c38441..9e019f2e9644 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -1358,9 +1358,13 @@ static void vpp_settings_h(struct vpp_frame_par_s *framePtr) r3 = framePtr->VPP_hsc_endp - framePtr->VPP_hsc_startp; if ((framePtr->supscl_path == CORE0_PPS_CORE1) || - (framePtr->supscl_path == CORE1_AFTER_PPS)) + (framePtr->supscl_path == CORE1_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r3 >>= framePtr->supsc1_hori_ratio; - if (framePtr->supscl_path == CORE0_AFTER_PPS) + if ((framePtr->supscl_path == CORE0_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r3 >>= framePtr->supsc0_hori_ratio; if (platform_type == 1) { @@ -1636,9 +1640,12 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) ((r & VPP_REGION_MASK) << VPP_REGION4_BIT)); if ((framePtr->supscl_path == CORE0_PPS_CORE1) || - (framePtr->supscl_path == CORE1_AFTER_PPS)) + (framePtr->supscl_path == CORE1_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r >>= framePtr->supsc1_vert_ratio; - if (framePtr->supscl_path == CORE0_AFTER_PPS) + if ((framePtr->supscl_path == CORE0_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r >>= framePtr->supsc0_vert_ratio; VSYNC_WR_MPEG_REG(VPP_VSC_REGION4_ENDP + cur_dev->vpp_off, r); @@ -6627,7 +6634,7 @@ SET_FILTER: VPP_VD1_PREBLEND | VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | - 7); + 0xf); if ((vpp_misc_set & VPP_VD2_PREBLEND) && (vpp_misc_set & VPP_VD1_PREBLEND)) set_value |= VPP_PREBLEND_EN; diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index f165f4305455..17d138499af4 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -408,6 +408,7 @@ module_param(force_filter_mode, int, 0664); bool super_scaler = true; static unsigned int sr_support; static u32 sr_reg_offt; +static u32 sr_reg_offt2; /*for tl1*/ static unsigned int super_debug; module_param(super_debug, uint, 0664); MODULE_PARM_DESC(super_debug, "super_debug"); @@ -1726,7 +1727,7 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, tmp_data = sharpness1_sr2_ctrl_32d7; else tmp_data = VSYNC_RD_MPEG_REG( - SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt); + SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt2);/*0xc80*/ if (is_meson_gxtvbb_cpu() || (((tmp_data >> 5)&0x1) != (reg_srscl1_vert_ratio&0x1)) || (((tmp_data >> 4)&0x1) != (reg_srscl1_hori_ratio&0x1)) || @@ -1742,7 +1743,7 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, tmp_data |= (((~(reg_srscl1_hori_ratio&0x1))&0x1) << 0); if (sr0_sr1_refresh) { VSYNC_WR_MPEG_REG( - SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt, + SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt2,/*0xc80*/ tmp_data); sharpness1_sr2_ctrl_32d7 = tmp_data; } @@ -1764,17 +1765,20 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, if (sr_support & SUPER_CORE1_SUPPORT) { if (get_cpu_type() != MESON_CPU_MAJOR_ID_GXTVBB) tmp_data2 = VSYNC_RD_MPEG_REG( - SRSHARP1_SHARP_HVSIZE); + SRSHARP1_SHARP_HVSIZE + sr_reg_offt2); if (is_meson_gxtvbb_cpu() || (tmp_data != tmp_data2)) { VSYNC_WR_MPEG_REG( - SRSHARP1_SHARP_HVSIZE, tmp_data); + SRSHARP1_SHARP_HVSIZE + sr_reg_offt2, tmp_data); if (is_meson_gxtvbb_cpu()) sharpness1_sr2_ctrl_3280 = tmp_data; } } /*ve input size setting*/ - if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || + (is_meson_tl1_cpu() && + ((scaler_path_sel == PPS_CORE0_CORE1) || + (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1)))) tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | (reg_srscl0_vsize & 0x1fff); else @@ -1785,7 +1789,7 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, VSYNC_WR_MPEG_REG(VPP_VE_H_V_SIZE, tmp_data); /*chroma blue stretch size setting*/ if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu()) { tmp_data = (((vpp_postblend_out_width & 0x1fff) << 16) | (vpp_postblend_out_height & 0x1fff)); VSYNC_WR_MPEG_REG(VPP_OUT_H_V_SIZE, tmp_data); @@ -1814,7 +1818,23 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, data_path_chose = 6; else data_path_chose = 5; - if ((scaler_path_sel == CORE0_PPS_CORE1) || + if (is_meson_tl1_cpu()) { + if (scaler_path_sel == CORE0_PPS_CORE1) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 3, 1); + } else if (scaler_path_sel == CORE0_CORE1_PPS) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 3, 1); + + } else if (scaler_path_sel == PPS_CORE0_CORE1) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 1, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 3, 1); + + } else if (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 1, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 3, 1); + } + } else if ((scaler_path_sel == CORE0_PPS_CORE1) || (scaler_path_sel == CORE1_BEFORE_PPS) || (scaler_path_sel == CORE0_BEFORE_PPS)) { if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) @@ -1970,12 +1990,16 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, /*patch for width align 2*/ if (super_scaler && (width_out%2) && - (((next_frame_par->supscl_path == CORE0_AFTER_PPS) && + ((((next_frame_par->supscl_path == CORE0_AFTER_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc0_hori_ratio) || (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || (next_frame_par->supscl_path == CORE0_CORE1_PPS) || (next_frame_par->supscl_path == CORE1_AFTER_PPS) || - (next_frame_par->supscl_path == CORE0_BEFORE_PPS)) && + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc1_hori_ratio))) { temp = next_frame_par->VPP_hsc_endp; if (++temp >= vinfo->width) { @@ -1983,15 +2007,35 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, (next_frame_par->VPP_hsc_startp < next_frame_par->VPP_hsc_endp)) next_frame_par->VPP_hsc_startp--; - else if (next_frame_par->supscl_path == - CORE0_AFTER_PPS) { + else if (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio && + next_frame_par->supsc1_hori_ratio) { + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_hori_ratio = 0; + next_frame_par->supsc1_vert_ratio = 0; + next_frame_par->VPP_hsc_endp++; + } else if ((next_frame_par->supscl_path == + CORE0_AFTER_PPS) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio)) { next_frame_par->supsc0_enable = 0; next_frame_par->supsc0_hori_ratio = 0; next_frame_par->supsc0_vert_ratio = 0; } else if ((next_frame_par->supscl_path == CORE1_AFTER_PPS) || (next_frame_par->supscl_path == - CORE0_PPS_CORE1)) { + CORE0_PPS_CORE1) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_hori_ratio)) { next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_hori_ratio = 0; next_frame_par->supsc1_vert_ratio = 0; @@ -2003,12 +2047,16 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, /*patch for height align 2*/ if (super_scaler && (height_out%2) && - (((next_frame_par->supscl_path == CORE0_AFTER_PPS) && + ((((next_frame_par->supscl_path == CORE0_AFTER_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc0_vert_ratio) || (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || (next_frame_par->supscl_path == CORE0_CORE1_PPS) || (next_frame_par->supscl_path == CORE1_AFTER_PPS) || - (next_frame_par->supscl_path == CORE0_BEFORE_PPS)) && + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc1_vert_ratio))) { temp = next_frame_par->VPP_vsc_endp; if (++temp >= vinfo->height) { @@ -2016,15 +2064,35 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, (next_frame_par->VPP_vsc_startp < next_frame_par->VPP_vsc_endp)) next_frame_par->VPP_vsc_startp--; - else if (next_frame_par->supscl_path == - CORE0_AFTER_PPS) { + else if (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio && + next_frame_par->supsc1_vert_ratio) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + next_frame_par->VPP_vsc_endp++; + } else if ((next_frame_par->supscl_path == + CORE0_AFTER_PPS) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio)) { next_frame_par->supsc0_enable = 0; next_frame_par->supsc0_hori_ratio = 0; next_frame_par->supsc0_vert_ratio = 0; } else if ((next_frame_par->supscl_path == CORE1_AFTER_PPS) || (next_frame_par->supscl_path == - CORE0_PPS_CORE1)) { + CORE0_PPS_CORE1) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_vert_ratio)) { next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_hori_ratio = 0; next_frame_par->supsc1_vert_ratio = 0; @@ -2047,6 +2115,15 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, height_out >> next_frame_par->supsc0_vert_ratio; next_frame_par->spsc0_w_in = width_out >> next_frame_par->supsc0_hori_ratio; + } else if ((next_frame_par->supscl_path == PPS_CORE0_CORE1) + || (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)){/*tl1*/ + next_frame_par->spsc0_h_in = + (height_out >> next_frame_par->supsc0_vert_ratio) >> + next_frame_par->supsc1_vert_ratio; + next_frame_par->spsc0_w_in = + (width_out >> next_frame_par->supsc0_hori_ratio) >> + next_frame_par->supsc1_hori_ratio; } else { next_frame_par->spsc0_h_in = src_height; next_frame_par->spsc0_w_in = src_width; @@ -2054,7 +2131,9 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, if ((next_frame_par->supscl_path == CORE0_PPS_CORE1) || (next_frame_par->supscl_path == CORE0_CORE1_PPS) || (next_frame_par->supscl_path == CORE1_AFTER_PPS) || - (next_frame_par->supscl_path == CORE0_BEFORE_PPS)) { + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) { next_frame_par->spsc1_h_in = (height_out >> next_frame_par->supsc1_vert_ratio); next_frame_par->spsc1_w_in = @@ -2662,7 +2741,7 @@ void vpp_super_scaler_support(void) sr_support |= SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || - is_meson_txlx_cpu()) { + is_meson_txlx_cpu() || is_meson_tl1_cpu()) { sr_support |= SUPER_CORE0_SUPPORT; sr_support |= SUPER_CORE1_SUPPORT; } else { @@ -2673,12 +2752,16 @@ void vpp_super_scaler_support(void) sr_support &= ~SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; } - scaler_path_sel = SCALER_PATH_MAX; - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { sr_reg_offt = 0xc00; - else + sr_reg_offt2 = 0x00; + } else if (is_meson_tl1_cpu()) { + sr_reg_offt = 0xc00; + sr_reg_offt2 = 0xc80; + } else { sr_reg_offt = 0; + sr_reg_offt2 = 0x00; + } } /*for gxlx only have core1 which will affact pip line*/ void vpp_bypass_ratio_config(void) diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index b4293104c838..8f2c7db79ec9 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -159,14 +159,17 @@ extern bool reverse; extern bool platform_type; enum select_scaler_path_e { - CORE0_PPS_CORE1 = 0, - CORE0_CORE1_PPS, + CORE0_PPS_CORE1 = 0, /*CORE0_PPS_CORE1_POSTBLEND*/ + CORE0_CORE1_PPS, /*CORE0_PPS_POSTBLEND_CORE1*/ /*gxlx only have core1,support below two mode*/ CORE1_BEFORE_PPS, CORE1_AFTER_PPS, /*txhd only have core0,support below two mode*/ CORE0_BEFORE_PPS, CORE0_AFTER_PPS, + /*tl1 have core0/core1, support below mode*/ + PPS_CORE0_CORE1, + PPS_CORE0_POSTBLEND_CORE1, SCALER_PATH_MAX, }; /* From e0c058f59f522a8ff8d15b81b46a797c740f6415 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Wed, 16 Jan 2019 05:12:00 +0800 Subject: [PATCH 0015/1060] vpp: add two layers support for each chips [1/6] PD#SWPL-85 Problem: Need support two video layers feature Solution: 1.Add vd2 mif config 2.Add vd2 pps calculation and config 3.Add vd2 axis/crop/screen mode interface by sysfs and ioctl 4.Add layer query/alloc/free interface Verify: Verify on U212 Change-Id: I71fc9ab2ae0230c3e84c4b790e77d2c790951642 Signed-off-by: Brian Zhu --- drivers/amlogic/media/deinterlace/di_pps.h | 1 + drivers/amlogic/media/osd/osd_hw.c | 1 + .../media/video_processor/ppmgr/ppmgr_drv.c | 2 +- .../media/video_processor/ppmgr/ppmgr_vpp.c | 7 +- drivers/amlogic/media/video_sink/video.c | 4347 +++++++++++------ .../amlogic/media/video_sink/video_keeper.c | 202 +- drivers/amlogic/media/video_sink/video_priv.h | 91 + drivers/amlogic/media/video_sink/vpp.c | 1471 +++--- .../amlogic/media/registers/regs/vpp_regs.h | 3 + include/linux/amlogic/media/utils/amstream.h | 30 +- .../linux/amlogic/media/vfm/vframe_receiver.h | 1 + .../linux/amlogic/media/video_sink/video.h | 75 +- include/linux/amlogic/media/video_sink/vpp.h | 159 +- 13 files changed, 4166 insertions(+), 2224 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/di_pps.h b/drivers/amlogic/media/deinterlace/di_pps.h index b78a020bd4fb..9ec789eb3b8e 100644 --- a/drivers/amlogic/media/deinterlace/di_pps.h +++ b/drivers/amlogic/media/deinterlace/di_pps.h @@ -18,6 +18,7 @@ #ifndef DI_PPS_H #define DI_PPS_H #include +#include #if 0 #define VPP_FLAG_WIDEMODE_MASK 0x0000000F #define VPP_FLAG_INTERLACE_OUT 0x00000010 diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 85090b3f1cbd..ff8cdeafb87a 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -54,6 +54,7 @@ #endif #ifdef CONFIG_AMLOGIC_MEDIA_VIDEO +#include #include #endif #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c index d33d14898795..72471596fbf6 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c @@ -31,11 +31,11 @@ #include #include #include +#include #include "ppmgr_log.h" #include "ppmgr_pri.h" #include "ppmgr_dev.h" -#include #define PPMGRDRV_INFO(fmt, args...) pr_info("PPMGRDRV: info: "fmt"", ## args) #define PPMGRDRV_DBG(fmt, args...) pr_debug("PPMGRDRV: dbg: "fmt"", ## args) diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index d9560b43fd9e..664ad0bcead9 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -46,7 +46,6 @@ #include #include #include -#include /*#include "../amports/video.h"*/ #include /*#include "../amports/vdec_reg.h"*/ @@ -2755,7 +2754,6 @@ static int process_vf_adjust(struct vframe_s *vf, /* extern int get_tv_process_type(struct vframe_s *vf); */ /* #endif */ static struct task_struct *task; -/* extern int video_property_notify(int flag); */ /* extern struct vframe_s *get_cur_dispbuf(void); */ /* extern enum platform_type_t get_platform_type(void); */ @@ -2835,7 +2833,10 @@ static int ppmgr_task(void *data) continue; process_vf_change(vf, context, &ge2d_config); - video_property_notify(2); + vf_notify_receiver( + PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED, + NULL); vfq_lookup_start(&q_ready); vf = vfq_peek(&q_ready); diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 9e019f2e9644..8cbff548b8a5 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -81,7 +81,6 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); #define DISPLAY_CANVAS_MAX_INDEX2 0x15 #include "../common/rdma/rdma.h" #endif -#include #include #include @@ -91,6 +90,9 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND #include #endif + +#define VIDEO_PIP + static u32 osd_vpp_misc; static u32 osd_vpp_misc_mask; static bool update_osd_vpp_misc; @@ -183,16 +185,22 @@ static const struct vframe_receiver_op_s video_vf_receiver = { static struct vframe_receiver_s video_vf_recv; -#define RECEIVER4OSD_NAME "amvideo4osd" -static int video4osd_receiver_event_fun(int type, void *data, void *); +#ifdef VIDEO_PIP +#define RECEIVERPIP_NAME "videopip" +static int pip_receiver_event_fun(int type, void *data, void *); -static const struct vframe_receiver_op_s video4osd_vf_receiver = { - .event_cb = video4osd_receiver_event_fun +static const struct vframe_receiver_op_s videopip_vf_receiver = { + .event_cb = pip_receiver_event_fun }; -static struct vframe_receiver_s video4osd_vf_recv; +static struct vframe_receiver_s videopip_vf_recv; -static struct vframe_provider_s *osd_prov; +static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par; +static struct vpp_frame_par_s pip_frame_parms[2]; +static struct vframe_s *cur_pipbuf; +static struct vframe_s local_pip; +static int _videopip_set_disable(u32 val); +#endif static struct device *amvideo_dev; static struct device *amvideo_poll_dev; @@ -238,10 +246,6 @@ static u32 hdmiin_frame_check_cnt; #define BRIDGE_IRQ_SET() WRITE_CBUS_REG(ISA_TIMERC, 1) #endif - - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - #define VD1_MEM_POWER_ON() \ do { \ unsigned long flags; \ @@ -283,22 +287,14 @@ static u32 hdmiin_frame_check_cnt; vpu_mem_power_off_count = VPU_MEM_POWEROFF_DELAY; \ spin_unlock_irqrestore(&delay_work_lock, flags); \ } while (0) -#else -#define VD1_MEM_POWER_ON() -#define VD2_MEM_POWER_ON() -#define PROT_MEM_POWER_ON() -#define VD1_MEM_POWER_OFF() -#define VD2_MEM_POWER_OFF() -#define PROT_MEM_POWER_OFF() -#endif #define VIDEO_LAYER_ON() \ do { \ unsigned long flags; \ spin_lock_irqsave(&video_onoff_lock, flags); \ video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ - video_enabled = 1;\ - video_status_saved = 1;\ + video_enabled = 1; \ + video_status_saved = 1; \ spin_unlock_irqrestore(&video_onoff_lock, flags); \ } while (0) @@ -307,8 +303,8 @@ static u32 hdmiin_frame_check_cnt; unsigned long flags; \ spin_lock_irqsave(&video_onoff_lock, flags); \ video_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ - video_enabled = 0;\ - video_status_saved = 0;\ + video_enabled = 0; \ + video_status_saved = 0; \ spin_unlock_irqrestore(&video_onoff_lock, flags); \ } while (0) @@ -317,6 +313,8 @@ static u32 hdmiin_frame_check_cnt; unsigned long flags; \ spin_lock_irqsave(&video2_onoff_lock, flags); \ video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + video2_enabled = 1; \ + video2_status_saved = 1; \ spin_unlock_irqrestore(&video2_onoff_lock, flags); \ } while (0) @@ -325,6 +323,8 @@ static u32 hdmiin_frame_check_cnt; unsigned long flags; \ spin_lock_irqsave(&video2_onoff_lock, flags); \ video2_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ + video2_enabled = 0; \ + video2_status_saved = 0; \ spin_unlock_irqrestore(&video2_onoff_lock, flags); \ } while (0) @@ -334,21 +334,12 @@ static u32 hdmiin_frame_check_cnt; VIDEO_LAYER_ON(); \ } while (0) -#if 0 /*TV_3D_FUNCTION_OPEN*/ -#define EnableVideoLayer2() \ - do { \ - VD2_MEM_POWER_ON(); \ - SET_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD2_PREBLEND | VPP_PREBLEND_EN | \ - (0x1ff << VPP_VD2_ALPHA_BIT)); \ - } while (0) -#else #define EnableVideoLayer2() \ do { \ VD2_MEM_POWER_ON(); \ VIDEO_LAYER2_ON(); \ } while (0) -#endif + #define VSYNC_EnableVideoLayer2() \ do { \ VD2_MEM_POWER_ON(); \ @@ -360,8 +351,7 @@ static u32 hdmiin_frame_check_cnt; #define DisableVideoLayer() \ do { \ CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD1_PREBLEND | VPP_VD2_PREBLEND|\ - VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND); \ + VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND); \ if (!legacy_vpp) { \ WRITE_VCBUS_REG( \ VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); \ @@ -369,13 +359,11 @@ static u32 hdmiin_frame_check_cnt; WRITE_VCBUS_REG(AFBC_ENABLE, 0);\ VIDEO_LAYER_OFF(); \ VD1_MEM_POWER_OFF(); \ - video_prot.video_started = 0; \ if (debug_flag & DEBUG_FLAG_BLACKOUT) { \ pr_info("DisableVideoLayer()\n"); \ } \ } while (0) -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ #define DisableVideoLayer_NoDelay() \ do { \ CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ @@ -390,28 +378,15 @@ static u32 hdmiin_frame_check_cnt; pr_info("DisableVideoLayer_NoDelay()\n"); \ } \ } while (0) -#else -#define DisableVideoLayer_NoDelay() DisableVideoLayer() -#endif -#if 0 /*TV_3D_FUNCTION_OPEN */ + #define DisableVideoLayer2() \ do { \ CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD2_PREBLEND | VPP_PREBLEND_EN | \ - (0x1ff << VPP_VD2_ALPHA_BIT)); \ - WRITE_VCBUS_REG(VD2_AFBC_ENABLE, 0); \ - VD2_MEM_POWER_OFF(); \ - } while (0) -#else -#define DisableVideoLayer2() \ - do { \ - CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD2_POSTBLEND | VPP_VD2_PREBLEND | \ - (0x1ff << VPP_VD2_ALPHA_BIT)); \ + VPP_VD2_POSTBLEND | VPP_VD2_PREBLEND); \ VIDEO_LAYER2_OFF(); \ VD2_MEM_POWER_OFF(); \ } while (0) -#endif + #define DisableVideoLayer_PREBELEND() \ do { CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ VPP_VD1_PREBLEND | VPP_VD2_PREBLEND); \ @@ -421,13 +396,6 @@ static u32 hdmiin_frame_check_cnt; } \ } while (0) -#ifndef CONFIG_AM_VIDEO2 -#define DisableVPP2VideoLayer() \ - CLEAR_VCBUS_REG_MASK(VPP2_MISC, \ - VPP_VD1_PREBLEND | VPP_VD2_PREBLEND | \ - VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND) - -#endif /*********************************************************/ #if DEBUG_TMP static struct switch_dev video1_state_sdev = { @@ -436,16 +404,15 @@ static struct switch_dev video1_state_sdev = { }; #endif +static DEFINE_MUTEX(video_layer_mutex); +static u32 layer_cap; + +static struct disp_info_s glayer_info[MAX_VD_LAYERS]; #define MAX_ZOOM_RATIO 300 -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - #define VPP_PREBLEND_VD_V_END_LIMIT 2304 -#else -#define VPP_PREBLEND_VD_V_END_LIMIT 1080 -#endif #define DUR2PTS(x) ((x) - ((x) >> 4)) #define DUR2PTS_RM(x) ((x) & 0xf) @@ -458,11 +425,9 @@ static int vpts_chase_counter; static int vpts_chase_pts_diff; #endif - static int step_enable; static int step_flag; - /*seek values on.video_define.h*/ static int debug_flag; int get_video_debug_flags(void) @@ -547,10 +512,7 @@ struct video_pm_state_s { int mem_pd_vd1; int mem_pd_vd2; int mem_pd_di_post; - int mem_pd_prot2; - int mem_pd_prot3; }; - #endif #define PTS_LOGGING @@ -631,11 +593,9 @@ bool is_dolby_vision_stb_mode(void) #endif static struct amvideocap_req *capture_frame_req; -static struct video_prot_s video_prot; -static u32 video_angle; u32 get_video_angle(void) { - return video_angle; + return glayer_info[0].angle; } EXPORT_SYMBOL(get_video_angle); @@ -818,7 +778,7 @@ static void video_debugfs_exit(void) int video_scaler_notify(int flag) { video_scaler_mode = flag; - video_property_changed = true; + video_property_changed = 1; return 0; } @@ -834,6 +794,8 @@ u32 amvideo_get_scaler_para(int *x, int *y, int *w, int *h, u32 *ratio) void amvideo_set_scaler_para(int x, int y, int w, int h, int flag) { + struct disp_info_s *layer = &glayer_info[0]; + mutex_lock(&video_module_mutex); if (w < 2) w = 0; @@ -847,9 +809,13 @@ void amvideo_set_scaler_para(int x, int y, int w, int h, int flag) content_top = y; content_w = w; content_h = h; - } else - vpp_set_video_layer_position(x, y, w, h); - video_property_changed = true; + } else { + layer->layer_left = x; + layer->layer_top = y; + layer->layer_width = w; + layer->layer_height = h; + } + video_property_changed = 1; mutex_unlock(&video_module_mutex); } @@ -899,6 +865,13 @@ static u32 disp_canvas[2][2]; static u32 rdma_canvas_id; static u32 next_rdma_canvas_id = 1; +#ifdef VIDEO_PIP +static u32 pip_rdma_canvas_id; +static u32 pip_next_rdma_canvas_id = 1; +static struct vframe_s *pip_rdma_buf; +static struct vframe_s *pipbuf_to_put; +#endif + #define DISPBUF_TO_PUT_MAX 8 static struct vframe_s *dispbuf_to_put[DISPBUF_TO_PUT_MAX]; static int dispbuf_to_put_num; @@ -939,9 +912,6 @@ static u32 ori2_end_x_lines; static u32 ori2_start_y_lines; static u32 ori2_end_y_lines; -/* wide settings */ -static u32 wide_setting; - /* black out policy */ #if defined(CONFIG_JPEGLOGO) static u32 blackout; @@ -951,9 +921,29 @@ static u32 blackout = 1; static u32 force_blackout; /* disable video */ + +#ifdef VIDEO_PIP +static u32 pip_frame_count; +static u32 disable_videopip = VIDEO_DISABLE_FORNEXT; +static int pip_property_changed; +static u32 pip_frame_ready_to_set; +static u32 pip_global_output = 1; +#if 0 +static u32 pip_v_skip; +static u32 pip_h_skip; +static u32 pip_start_x_lines; +static u32 pip_end_x_lines; +static u32 pip_start_y_lines; +static u32 pip_end_y_lines; +#endif +static u32 pip_loop; +#endif + static u32 disable_video = VIDEO_DISABLE_NONE; static u32 video_enabled __nosavedata; +static u32 video2_enabled __nosavedata; static u32 video_status_saved __nosavedata; +static u32 video2_status_saved __nosavedata; static u32 hold_video; u32 get_video_enabled(void) @@ -984,20 +974,6 @@ void update_cur_dispbuf(void *buf) { cur_dispbuf = buf; } -int get_video0_frame_info(struct vframe_s *vf) -{ - unsigned long flags; - int ret = -1; - - spin_lock_irqsave(&lock, flags); - if (is_vpp_postblend() && cur_dispbuf && vf) { - *vf = *cur_dispbuf; - ret = 0; - } - spin_unlock_irqrestore(&lock, flags); - return ret; -} -EXPORT_SYMBOL(get_video0_frame_info); static struct vframe_s vf_local, vf_local2; static u32 vsync_pts_inc; @@ -1146,6 +1122,58 @@ void safe_disble_videolayer(void) /*********************************************************/ +#ifdef VIDEO_PIP +static inline struct vframe_s *pip_vf_peek(void) +{ + if (pip_loop) + return cur_dispbuf; + return vf_peek(RECEIVERPIP_NAME); +} + +static inline struct vframe_s *pip_vf_get(void) +{ + struct vframe_s *vf = NULL; + + if (pip_loop) + return cur_dispbuf; + + vf = vf_get(RECEIVERPIP_NAME); + + if (vf) { + /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */ + atomic_set(&vf->use_cnt, 1); + } + return vf; + +} + +#if 0 +static int pip_vf_get_states(struct vframe_states *states) +{ + int ret = -1; + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + ret = vf_get_states_by_name(RECEIVERPIP_NAME, states); + spin_unlock_irqrestore(&lock, flags); + return ret; +} +#endif + +static inline void pip_vf_put(struct vframe_s *vf) +{ + struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP_NAME); + + if (pip_loop) + return; + + if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) { + vf_put(vf, RECEIVERPIP_NAME); + /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */ + } +} +#endif + static inline struct vframe_s *video_vf_peek(void) { struct vframe_s *vf = vf_peek(RECEIVER_NAME); @@ -1345,6 +1373,23 @@ int ext_frame_capture_poll(int endflags) } #endif +static void update_layer_info(u8 layer_id) +{ + struct disp_info_s *layer; + + if (layer_id >= MAX_VD_LAYERS) + return; + + if (layer_id == 0) { + layer = &glayer_info[0]; + layer->reverse = reverse; + layer->proc_3d_type = process_3d_type; + } else if (layer_id == 1) { + layer = &glayer_info[1]; + layer->reverse = reverse; + layer->proc_3d_type = 0; + } +} static void vpp_settings_h(struct vpp_frame_par_s *framePtr) { @@ -1367,81 +1412,74 @@ static void vpp_settings_h(struct vpp_frame_par_s *framePtr) (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r3 >>= framePtr->supsc0_hori_ratio; - if (platform_type == 1) { - x_lines = zoom_end_x_lines / (framePtr->hscale_skip_count + 1); - if (process_3d_type & MODE_3D_OUT_TB) { - /* vd1 and vd2 do pre blend */ - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + x_lines = zoom_end_x_lines / (framePtr->hscale_skip_count + 1); + if (process_3d_type & MODE_3D_OUT_TB) { + /* vd1 and vd2 do pre blend */ + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((zoom_end_x_lines) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((zoom_end_x_lines) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, - ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << - VPP_VD1_START_BIT) | (((zoom_end_x_lines) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + cur_dev->vpp_off, ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else if (process_3d_type & MODE_3D_OUT_LR) { - /* vd1 and vd2 do pre blend */ - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + } else if (process_3d_type & MODE_3D_OUT_LR) { + /* vd1 and vd2 do pre blend */ + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((x_lines >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, ((((x_lines + 1) >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((x_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + cur_dev->vpp_off, ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else{ - if (!legacy_vpp) { - x_lines = (zoom_end_x_lines - - zoom_start_x_lines + 1) - / (framePtr->hscale_skip_count + 1); - VSYNC_WR_MPEG_REG( + } else{ + if (!legacy_vpp) { + x_lines = (zoom_end_x_lines - + zoom_start_x_lines + 1) + / (framePtr->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG( VPP_PREBLEND_VD1_H_START_END, ((0 & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((x_lines - 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) - << VPP_VD1_START_BIT) | - ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) - << VPP_VD1_END_BIT)); - - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_hd_start_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - ((framePtr->VPP_hd_end_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } - } else { - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_VD1_H_START_END + cur_dev->vpp_off, ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_hd_start_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - ((framePtr->VPP_hd_end_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_hd_start_lines_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_START_BIT) | + ((framePtr->VPP_hd_end_lines_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + } } + VSYNC_WR_MPEG_REG(VPP_HSC_REGION12_STARTP + cur_dev->vpp_off, (0 << VPP_REGION1_BIT) | @@ -1474,12 +1512,14 @@ static void vd2_settings_h(struct vframe_s *vf) VPP_hd_start_lines_ = 0; VPP_hd_end_lines_ = ((vf->type & VIDTYPE_COMPRESS) ? vf->compWidth : vf->width) - 1; - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END + - cur_dev->vpp_off, - ((VPP_hd_start_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - ((VPP_hd_end_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + + cur_dev->vpp_off, + ((VPP_hd_start_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + ((VPP_hd_end_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } } @@ -1491,6 +1531,7 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) u32 v_phase; u32 v_skip_flag = 0; int x, y, w, h; + struct disp_info_s *layer = &glayer_info[0]; r = framePtr->VPP_vsc_endp - framePtr->VPP_vsc_startp; afbc_enble_flag = 0; @@ -1506,7 +1547,11 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) else { afbc_enble_flag = READ_VCBUS_REG(AFBC_ENABLE) & 0x100; v_phase = vpp_filter->vpp_vsc_start_phase_step; - vpp_get_video_layer_position(&x, &y, &w, &h); + + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; if (v_phase * (framePtr->vscale_skip_count + 1) > 0x1000000) { if ((afbc_enble_flag) && (y < 0)) { if ((framePtr->VPP_vsc_endp < 0x250) || @@ -1532,34 +1577,33 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) } } - if (platform_type == 1) { - y_lines = zoom_end_y_lines / (framePtr->vscale_skip_count + 1); - if (process_3d_type & MODE_3D_OUT_TB) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, + y_lines = zoom_end_y_lines / (framePtr->vscale_skip_count + 1); + if (process_3d_type & MODE_3D_OUT_TB) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((y_lines >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG( + VSYNC_WR_MPEG_REG( VPP_BLEND_VD2_V_START_END, ((((y_lines + 1) >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else if (process_3d_type & MODE_3D_OUT_LR) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, + } else if (process_3d_type & MODE_3D_OUT_LR) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((zoom_end_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END, + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END, ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((zoom_end_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - if ((framePtr->VPP_post_blend_vd_v_end_ - - framePtr->VPP_post_blend_vd_v_start_ + 1) > - VPP_PREBLEND_VD_V_END_LIMIT) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + } else { + if ((framePtr->VPP_post_blend_vd_v_end_ - + framePtr->VPP_post_blend_vd_v_start_ + 1) > + VPP_PREBLEND_VD_V_END_LIMIT) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + cur_dev->vpp_off, ((framePtr->VPP_post_blend_vd_v_start_ & VPP_VD_SIZE_MASK) << @@ -1567,72 +1611,36 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) ((framePtr->VPP_post_blend_vd_v_end_ & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + } else { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + cur_dev->vpp_off, ((0 & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((VPP_PREBLEND_VD_V_END_LIMIT - 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - - if (is_need_framepacking_output()) { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - (((((framePtr->VPP_vd_end_lines_ - - framepacking_blank + 1) / 2) + framepacking_blank) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - } - } else { - if ((framePtr->VPP_post_blend_vd_v_end_ - - framePtr->VPP_post_blend_vd_v_start_ + 1) > - VPP_PREBLEND_VD_V_END_LIMIT) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_post_blend_vd_v_start_ - & VPP_VD_SIZE_MASK) << - VPP_VD1_START_BIT) | - ((framePtr->VPP_post_blend_vd_v_end_ & - VPP_VD_SIZE_MASK) - << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + - cur_dev->vpp_off, - ((0 & VPP_VD_SIZE_MASK) << - VPP_VD1_START_BIT) | - (((VPP_PREBLEND_VD_V_END_LIMIT - 1) & - VPP_VD_SIZE_MASK) << - VPP_VD1_END_BIT)); - } - if (is_need_framepacking_output()) { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - (((((framePtr->VPP_vd_end_lines_ - +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((framePtr->VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } + if (is_need_framepacking_output()) { + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + (((((framePtr->VPP_vd_end_lines_ - framepacking_blank + 1) / 2) + framepacking_blank) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((framePtr->VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } } VSYNC_WR_MPEG_REG(VPP_VSC_REGION12_STARTP + cur_dev->vpp_off, 0); VSYNC_WR_MPEG_REG(VPP_VSC_REGION34_STARTP + cur_dev->vpp_off, @@ -1674,15 +1682,19 @@ static void vd2_settings_v(struct vframe_s *vf) } #ifdef TV_3D_FUNCTION_OPEN - static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey; + struct disp_info_s *layer = &glayer_info[0]; if (!vf) return; - vpp_get_video_source_crop(&crop_sy, &crop_sx, &crop_ey, &crop_ex); + + crop_sy = layer->crop_top; + crop_sx = layer->crop_left; + crop_ey = layer->crop_bottom; + crop_ex = layer->crop_right; switch (vpp_3d_mode) { case VPP_3D_MODE_LR: @@ -1728,8 +1740,12 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey, height; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_video_source_crop(&crop_sy, &crop_sx, &crop_ey, &crop_ex); + crop_sy = layer->crop_top; + crop_sx = layer->crop_left; + crop_ey = layer->crop_bottom; + crop_ex = layer->crop_right; if (vf->type & VIDTYPE_INTERLACE) height = vf->height >> 1; @@ -1937,32 +1953,37 @@ static void zoom_display_horz(struct vframe_s *vf, int hscale) ((r_aligned - l_aligned) << 16)); } - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_X0 + cur_dev->viu_off, - (ls << VDIF_PIC_START_BIT) | - (le << VDIF_PIC_END_BIT)); +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_X0 + cur_dev->viu_off, - (ls / 2 << VDIF_PIC_START_BIT) | - (le / 2 << VDIF_PIC_END_BIT)); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X0 + cur_dev->viu_off, + (ls / 2 << VDIF_PIC_START_BIT) | + (le / 2 << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_X1 + cur_dev->viu_off, - (rs << VDIF_PIC_START_BIT) | - (re << VDIF_PIC_END_BIT)); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_X1 + cur_dev->viu_off, - (rs / 2 << VDIF_PIC_START_BIT) | - (re / 2 << VDIF_PIC_END_BIT)); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X1 + cur_dev->viu_off, + (rs / 2 << VDIF_PIC_START_BIT) | + (re / 2 << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VIU_VD2_FMT_W + cur_dev->viu_off, - (((zoom_end_x_lines - zoom_start_x_lines + - 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | - (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + - 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_W + cur_dev->viu_off, + (((zoom_end_x_lines - zoom_start_x_lines + + 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | + (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); + } } static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) @@ -1977,7 +1998,7 @@ static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { int l_aligned; int r_aligned; - int h_skip = cur_frame_par->hscale_skip_count + 1; + int h_skip = hscale + 1; int c_skip = 2; /* After TL1, afbc supports 420/422/444*/ @@ -2059,26 +2080,14 @@ static void zoom_display_vert(struct vframe_s *vf) u32 ls, le, rs, re; - /*if (platform_type == 1) {*/ - if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_vert_pos(vf, - cur_frame_par->vpp_3d_mode, &ls, - &le, &rs, &re); - } else { - ls = rs = zoom_start_y_lines; - le = re = zoom_end_y_lines; - } - /*} else { - if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_vert_pos(cur_dispbuf, - cur_frame_par->vpp_3d_mode, &ls, - &le, &rs, &re); - } else { - ls = rs = zoom_start_y_lines; - le = re = zoom_end_y_lines; - } + if (process_3d_type & MODE_3D_ENABLE) { + zoom_get_vert_pos(vf, + cur_frame_par->vpp_3d_mode, &ls, + &le, &rs, &re); + } else { + ls = rs = zoom_start_y_lines; + le = re = zoom_end_y_lines; } -*/ if ((vf) && (vf->type & VIDTYPE_MVC)) { if (is_need_framepacking_output()) { @@ -2142,8 +2151,11 @@ static void zoom_display_vert(struct vframe_s *vf) VD1_IF0_CHROMA_Y1 + cur_dev->viu_off, ((rs / 2) << VDIF_PIC_START_BIT) | ((re / 2) << VDIF_PIC_END_BIT)); - if (platform_type == 1) { - /* vd2 */ + +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { VSYNC_WR_MPEG_REG( VD2_IF0_LUMA_Y0 + cur_dev->viu_off, (ls << VDIF_PIC_START_BIT) | @@ -2214,7 +2226,7 @@ static void zoom_display_vert(struct vframe_s *vf) } } -static void vd2_zoom_display_vert(struct vframe_s *vf) +static void vd2_zoom_display_vert(struct vframe_s *vf, int vscale) { u32 ls, le, rs, re; @@ -2248,7 +2260,7 @@ static void vd2_zoom_display_vert(struct vframe_s *vf) int b_aligned; int ori_t_aligned; int ori_b_aligned; - int v_skip = cur_frame_par->vscale_skip_count + 1; + int v_skip = vscale + 1; int c_skip = 2; /* After TL1, afbc supports 420/422/444*/ @@ -2454,609 +2466,6 @@ static void vsync_video_pattern(void) } #endif -/* for sdr/hdr/single dv switch with dual dv */ -static u32 last_el_status; -/* for dual dv switch with different el size */ -static u32 last_el_w; -bool has_enhanced_layer(struct vframe_s *vf) -{ - struct provider_aux_req_s req; - - if (!vf) - return 0; - if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) - return 0; - if (!is_dolby_vision_on()) - return 0; - - req.vf = vf; - req.bot_flag = 0; - req.aux_buf = NULL; - req.aux_size = 0; - req.dv_enhance_exist = 0; - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); - return req.dv_enhance_exist; -} -u32 property_changed_true; - -static u64 func_div(u64 number, u32 divid) -{ - u64 tmp = number; - - do_div(tmp, divid); - return tmp; -} - -static void vsync_toggle_frame(struct vframe_s *vf) -{ - u32 first_picture = 0; - unsigned long flags = 0; - bool vf_with_el = false; - bool force_toggle = false; - long long *clk_array; - - if (vf == NULL) - return; - frame_count++; - toggle_count++; - - if (is_dolby_vision_enable()) - vf_with_el = has_enhanced_layer(vf); - -#ifdef PTS_TRACE_DEBUG -#ifdef PTS_TRACE_START - if (pts_trace_his_rd < 16) { -#endif - pts_trace_his[pts_trace_his_rd] = pts_trace; - pts_his[pts_trace_his_rd] = vf->pts; - scr_his[pts_trace_his_rd] = timestamp_pcrscr_get(); - pts_trace_his_rd++; - if (pts_trace_his_rd >= 16) - pts_trace_his_rd = 0; -#ifdef PTS_TRACE_START - } -#endif -#endif - -#ifdef PTS_LOGGING - if (pts_escape_vsync == 1) { - pts_trace++; - pts_escape_vsync = 0; - } - vsync_video_pattern(); - pre_pts_trace = pts_trace; -#endif - -#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) - pts_trace = 0; -#endif - - ori_start_x_lines = 0; - ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? - vf->compWidth : vf->width) - 1; - ori_start_y_lines = 0; - ori_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? - vf->compHeight : vf->height) - 1; - if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) { - u32 pcr = timestamp_pcrscr_get(); - u32 vpts = timestamp_vpts_get(); - u32 apts = timestamp_apts_get(); - - pr_info("%s pts:%d.%06d pcr:%d.%06d vpts:%d.%06d apts:%d.%06d\n", - __func__, (vf->pts) / 90000, - ((vf->pts) % 90000) * 1000 / 90, (pcr) / 90000, - ((pcr) % 90000) * 1000 / 90, (vpts) / 90000, - ((vpts) % 90000) * 1000 / 90, (apts) / 90000, - ((apts) % 90000) * 1000 / 90); - } - - if (trickmode_i || trickmode_fffb) - trickmode_duration_count = trickmode_duration; - - if (vf->early_process_fun) { - if (vf->early_process_fun(vf->private_data, vf) == 1) { - /* video_property_changed = true; */ - first_picture = 1; - } - } else { -#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE - if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) != 0) { - /* check mif enable status, disable post di */ - VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); - VSYNC_WR_MPEG_REG(DI_POST_SIZE, - (32 - 1) | ((128 - 1) << 16)); - VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, - READ_VCBUS_REG(DI_IF1_GEN_REG) & - 0xfffffffe); - } -#endif - } - - timer_count = 0; - if ((vf->width == 0) && (vf->height == 0)) { - amlog_level(LOG_LEVEL_ERROR, - "Video: invalid frame dimension\n"); - return; - } - - if (hold_video) { - if ((cur_dispbuf != vf) - && (vf->source_type != VFRAME_SOURCE_TYPE_OSD)) { - new_frame_count++; - if (vf->pts != 0) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - vf->pts, timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_set(vf->pts); - last_frame_duration = vf->duration; - } else if (last_frame_duration) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - timestamp_vpts_get() + - DUR2PTS(cur_dispbuf->duration), - timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_inc(DUR2PTS - (last_frame_duration)); - - vpts_remainder += - DUR2PTS_RM(last_frame_duration); - if (vpts_remainder >= 0xf) { - vpts_remainder -= 0xf; - timestamp_vpts_inc(-1); - } - } - video_vf_put(vf); - return; - } - } - - if ((cur_dispbuf) && (cur_dispbuf != &vf_local) && (cur_dispbuf != vf) - && (video_property_changed != 2)) { - if (cur_dispbuf->source_type == VFRAME_SOURCE_TYPE_OSD) { - if (osd_prov && osd_prov->ops && osd_prov->ops->put) { - osd_prov->ops->put(cur_dispbuf, - osd_prov->op_arg); - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info( - "[v4o]pre vf is osd,put it\n"); - } - } - first_picture = 1; - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info( - "[v4o] pre vf is osd, clear it to NULL\n"); - } - } else { - new_frame_count++; - if (new_frame_count == 1) - first_picture = 1; -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if (is_vsync_rdma_enable()) { -#ifdef RDMA_RECYCLE_ORDERED_VFRAMES - if (dispbuf_to_put_num < DISPBUF_TO_PUT_MAX) { - dispbuf_to_put[dispbuf_to_put_num] = - cur_dispbuf; - dispbuf_to_put_num++; - } else - video_vf_put(cur_dispbuf); -#else - if (cur_rdma_buf == cur_dispbuf) { - dispbuf_to_put[0] = cur_dispbuf; - dispbuf_to_put_num = 1; - } else - video_vf_put(cur_dispbuf); -#endif - } else { - int i; - - for (i = 0; i < dispbuf_to_put_num; i++) { - if (dispbuf_to_put[i]) { - video_vf_put( - dispbuf_to_put[i]); - dispbuf_to_put[i] = NULL; - } - dispbuf_to_put_num = 0; - } - video_vf_put(cur_dispbuf); - } -#else - video_vf_put(cur_dispbuf); -#endif - if (debug_flag & DEBUG_FLAG_LATENCY) { - vf->ready_clock[3] = sched_clock(); - pr_info("video toggle latency %lld ms," - "video get latency %lld ms," - "vdin put latency %lld ms," - "first %lld ms.\n", - func_div(vf->ready_clock[3], 1000), - func_div(vf->ready_clock[2], 1000), - func_div(vf->ready_clock[1], 1000), - func_div(vf->ready_clock[0], 1000)); - cur_dispbuf->ready_clock[4] = sched_clock(); - clk_array = cur_dispbuf->ready_clock; - pr_info("video put latency %lld ms," - "video toggle latency %lld ms," - "video get latency %lld ms," - "vdin put latency %lld ms," - "first %lld ms.\n", - func_div(*(clk_array + 4), 1000), - func_div(*(clk_array + 3), 1000), - func_div(*(clk_array + 2), 1000), - func_div(*(clk_array + 1), 1000), - func_div(*clk_array, 1000)); - } - } - - } else - first_picture = 1; - - if (video_property_changed) { - property_changed_true = 2; - video_property_changed = false; - first_picture = 1; - } - if (property_changed_true > 0) { - property_changed_true--; - first_picture = 1; - } - - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - if (first_picture) { - pr_info - ("[video4osd] first %s picture {%d,%d} pts:%x,\n", - (vf->source_type == - VFRAME_SOURCE_TYPE_OSD) ? "OSD" : "", vf->width, - vf->height, vf->pts); - } - } - /* switch buffer */ - post_canvas = vf->canvas0Addr; - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && - (vf->type & VIDTYPE_COMPRESS)) { - VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4); - VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4); - } - if ((vf->canvas0Addr != 0) -#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE - && ((DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) == 0) - /* check di_post_viu_link */ -#endif - ) { - -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if (vf->canvas0Addr != (u32)-1) { - canvas_copy(vf->canvas0Addr & 0xff, - disp_canvas_index[rdma_canvas_id][0]); - canvas_copy((vf->canvas0Addr >> 8) & 0xff, - disp_canvas_index[rdma_canvas_id][1]); - canvas_copy((vf->canvas0Addr >> 16) & 0xff, - disp_canvas_index[rdma_canvas_id][2]); - } else { - vframe_canvas_set(&vf->canvas0_config[0], - vf->plane_num, - &disp_canvas_index[rdma_canvas_id][0]); - } - if (!vf_with_el) { - if (vf->canvas1Addr != (u32)-1) { - canvas_copy(vf->canvas1Addr & 0xff, - disp_canvas_index[rdma_canvas_id][3]); - canvas_copy((vf->canvas1Addr >> 8) & 0xff, - disp_canvas_index[rdma_canvas_id][4]); - canvas_copy((vf->canvas1Addr >> 16) & 0xff, - disp_canvas_index[rdma_canvas_id][5]); - } else { - vframe_canvas_set(&vf->canvas1_config[0], - vf->plane_num, - &disp_canvas_index[rdma_canvas_id][3]); - } - } - - VSYNC_WR_MPEG_REG( - VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - if (platform_type == 0) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - } - } else { - if (!vf_with_el) - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode == 1)) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - } - } - if (cur_frame_par - && (process_3d_type & MODE_3D_ENABLE) - && (process_3d_type & MODE_3D_TO_2D_R) - && (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1) - && !vf_with_el) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - } - /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1,*/ - /*disp_canvas[rdma_canvas_id][1]); */ - next_rdma_canvas_id = rdma_canvas_id ? 0 : 1; -#else - canvas_copy(vf->canvas0Addr & 0xff, disp_canvas_index[0]); - canvas_copy((vf->canvas0Addr >> 8) & 0xff, - disp_canvas_index[1]); - canvas_copy((vf->canvas0Addr >> 16) & 0xff, - disp_canvas_index[2]); - canvas_copy(vf->canvas1Addr & 0xff, disp_canvas_index[3]); - canvas_copy((vf->canvas1Addr >> 8) & 0xff, - disp_canvas_index[4]); - canvas_copy((vf->canvas1Addr >> 16) & 0xff, - disp_canvas_index[5]); - if (platform_type == 0) { - VSYNC_WR_MPEG_REG( - VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - VSYNC_WR_MPEG_REG( - VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[0]); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[1]); - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[1]); - } - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode == 1)) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[0]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[0]); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[1]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[1]); - } - /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 +*/ - /*cur_dev->viu_off, disp_canvas[0]); */ - /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 +*/ - /*cur_dev->viu_off, disp_canvas[1]); */ - } -#endif - } - /* set video PTS */ - if (cur_dispbuf != vf) { - if (vf->source_type != VFRAME_SOURCE_TYPE_OSD) { - if (vf->pts != 0) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - vf->pts, timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_set(vf->pts); - } else if (cur_dispbuf) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - timestamp_vpts_get() + - DUR2PTS(cur_dispbuf->duration), - timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_inc(DUR2PTS - (cur_dispbuf->duration)); - - vpts_remainder += - DUR2PTS_RM(cur_dispbuf->duration); - if (vpts_remainder >= 0xf) { - vpts_remainder -= 0xf; - timestamp_vpts_inc(-1); - } - } - } else { - first_picture = 1; - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info( - "[v4o] cur vframe is osd, do not set PTS\n"); - } - } - vf->type_backup = vf->type; - } - - if (cur_dispbuf && vf && - (cur_dispbuf->ratio_control & - DISP_RATIO_ADAPTED_PICMODE) && - (cur_dispbuf->ratio_control == - vf->ratio_control) && - memcmp(&cur_dispbuf->pic_mode, &vf->pic_mode, - sizeof(struct vframe_pic_mode_s))) - force_toggle = true; - - if ((last_process_3d_type != process_3d_type) - || (last_el_status != vf_with_el)) - force_toggle = true; - - /* enable new config on the new frames */ - if (first_picture || force_toggle || - (cur_dispbuf && - ((cur_dispbuf->bufWidth != vf->bufWidth) || - (cur_dispbuf->width != vf->width) || - (cur_dispbuf->height != vf->height) || - (cur_dispbuf->bitdepth != vf->bitdepth) || - (cur_dispbuf->trans_fmt != vf->trans_fmt) || - (cur_dispbuf->ratio_control != vf->ratio_control) || - ((cur_dispbuf->type_backup & VIDTYPE_INTERLACE) != - (vf->type_backup & VIDTYPE_INTERLACE)) || - (cur_dispbuf->type != vf->type)))) { - last_process_3d_type = process_3d_type; - atomic_inc(&video_sizechange); - wake_up_interruptible(&amvideo_sizechange_wait); - amlog_mask(LOG_MASK_FRAMEINFO, - "%s %dx%d ar=0x%x\n", - ((vf->type & VIDTYPE_TYPEMASK) == - VIDTYPE_INTERLACE_TOP) ? "interlace-top" - : ((vf->type & VIDTYPE_TYPEMASK) - == VIDTYPE_INTERLACE_BOTTOM) - ? "interlace-bottom" : "progressive", vf->width, - vf->height, vf->ratio_control); -#ifdef TV_3D_FUNCTION_OPEN - amlog_mask(LOG_MASK_FRAMEINFO, - "%s trans_fmt=%u\n", __func__, vf->trans_fmt); - -#endif - next_frame_par = (&frame_parms[0] == next_frame_par) ? - &frame_parms[1] : &frame_parms[0]; - - vpp_set_filters(process_3d_type, wide_setting, vf, - next_frame_par, vinfo, - (is_dolby_vision_on() && - is_dolby_vision_stb_mode())); - - /* apply new vpp settings */ - frame_par_ready_to_set = 1; - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) - && !is_meson_mtvd_cpu()) { - if (((vf->width > 1920) && (vf->height > 1088)) || - ((vf->type & VIDTYPE_COMPRESS) && - (vf->compWidth > 1920) && - (vf->compHeight > 1080))) { - if (vpu_clk_level == 0) { - vpu_clk_level = 1; - - spin_lock_irqsave(&lock, flags); - vpu_delay_work_flag |= - VPU_DELAYWORK_VPU_CLK; - spin_unlock_irqrestore(&lock, flags); - } - } else { - if (vpu_clk_level == 1) { - vpu_clk_level = 0; - - spin_lock_irqsave(&lock, flags); - vpu_delay_work_flag |= - VPU_DELAYWORK_VPU_CLK; - spin_unlock_irqrestore(&lock, flags); - } - } - } - /* #endif */ - - } - last_el_status = vf_with_el; - - if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && - ((!property_changed_true) || (vf != cur_dispbuf))) { - if (disable_video == VIDEO_DISABLE_FORNEXT) { - EnableVideoLayer(); - disable_video = VIDEO_DISABLE_NONE; - } - if (first_picture && (disable_video != VIDEO_DISABLE_NORMAL)) { - EnableVideoLayer(); - - if ((vf->type & VIDTYPE_MVC) || - (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) - EnableVideoLayer2(); - else if (cur_dispbuf2 && - !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) - VD2_MEM_POWER_ON(); - else if (vf_with_el) - EnableVideoLayer2(); - else if (need_disable_vd2) - DisableVideoLayer2(); - } - } - if (cur_dispbuf && (cur_dispbuf->type != vf->type)) { - if ((vf->type & VIDTYPE_MVC) || - (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) - EnableVideoLayer2(); - else { - if (cur_dispbuf2 && - !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) - VD2_MEM_POWER_ON(); - else if (vf_with_el) - EnableVideoLayer2(); - else if (need_disable_vd2) - DisableVideoLayer2(); - } - } - cur_dispbuf = vf; - if (first_picture) { - frame_par_ready_to_set = 1; - first_frame_toggled = 1; - -#ifdef VIDEO_PTS_CHASE - av_sync_flag = 0; -#endif - } - if (cur_dispbuf != &vf_local) - video_keeper_new_frame_notify(); - - if ((vf != &vf_local) && (vf) && !vsync_pts_aligned) { -#ifdef PTS_TRACE_DEBUG - pr_info("####timestamp_pcrscr_get() = 0x%x, vf->pts = 0x%x, vsync_pts_inc = %d\n", - timestamp_pcrscr_get(), vf->pts, vsync_pts_inc); -#endif - if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc)) - && ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) { - /*vsync_pts_align = vsync_pts_inc / 4 - */ - /* (timestamp_pcrscr_get() - vf->pts);*/ - vsync_pts_align = 0; - vsync_pts_aligned = true; -#ifdef PTS_TRACE_DEBUG - pts_trace_his_rd = 0; - pr_info("####vsync_pts_align set to %d\n", - vsync_pts_align); -#endif - } - } -} static inline void vd1_path_select(bool afbc) { u32 misc_off = cur_dev->vpp_off; @@ -3160,6 +2569,1394 @@ static inline void vd2_path_select(bool afbc) } } +#ifdef VIDEO_PIP +s32 config_vd_pps( + u8 layer_id, + struct vpp_frame_par_s *cur_frame_par, + struct scaler_setting_s *setting, + const struct vinfo_s *info) +{ + struct vppfilter_mode_s *vpp_filter; + + if (!cur_frame_par || !info || !setting) + return -1; + + vpp_filter = &cur_frame_par->vpp_filter; + setting->frame_par = cur_frame_par; + setting->id = layer_id; + setting->misc_reg_offt = 0; + /* enable pps as default */ + setting->sc_top_enable = true; + setting->sc_h_enable = true; + setting->sc_v_enable = true; + + if ((vpp_filter->vpp_hsc_start_phase_step == 0x1000000) + && (vpp_filter->vpp_vsc_start_phase_step == 0x1000000) + && (vpp_filter->vpp_hsc_start_phase_step == + vpp_filter->vpp_hf_start_phase_step) + && !vpp_filter->vpp_pre_vsc_en + && !vpp_filter->vpp_pre_hsc_en + && !cur_frame_par->supsc0_enable + && !cur_frame_par->supsc1_enable + && bypass_pps) + setting->sc_top_enable = false; + + /* old chip: vd2 has no pps */ + if ((legacy_vpp || is_meson_tl1_cpu()) + && (setting->id != 0)) + setting->sc_top_enable = false; + + setting->vinfo_width = info->width; + setting->vinfo_height = info->height; + return 0; +} + +static inline void vd2_scaler_setting( + struct scaler_setting_s *setting) +{ + u32 misc_off, i; + u32 r1, r2, r3; + struct vpp_frame_par_s *frame_par; + struct vppfilter_mode_s *vpp_filter; + + if (legacy_vpp || !setting + || !setting->frame_par + || is_meson_tl1_cpu()) + return; + + frame_par = setting->frame_par; + misc_off = setting->misc_reg_offt; + vpp_filter = &frame_par->vpp_filter; + + if (setting->sc_top_enable) { + u32 sc_misc_val; + + sc_misc_val = VPP_SC_TOP_EN | VPP_SC_V1OUT_EN; + if (setting->sc_h_enable) { + sc_misc_val |= (((vpp_filter->vpp_pre_hsc_en & 1) + << VPP_SC_PREHORZ_EN_BIT) + | VPP_SC_HORZ_EN); + sc_misc_val |= ((vpp_filter->vpp_horz_coeff[0] & 7) + << VPP_SC_HBANK_LENGTH_BIT); + } + + if (setting->sc_v_enable) { + sc_misc_val |= (((vpp_filter->vpp_pre_vsc_en & 1) + << VPP_SC_PREVERT_EN_BIT) + | VPP_SC_VERT_EN); + sc_misc_val |= ((vpp_filter->vpp_pre_vsc_en & 1) + << VPP_LINE_BUFFER_EN_BIT); + sc_misc_val |= ((vpp_filter->vpp_vert_coeff[0] & 7) + << VPP_SC_VBANK_LENGTH_BIT); + } + VSYNC_WR_MPEG_REG( + VD2_SC_MISC + misc_off, + sc_misc_val); + } else { + setting->sc_v_enable = false; + setting->sc_h_enable = false; + VSYNC_WR_MPEG_REG_BITS( + VD2_SC_MISC + misc_off, + 0, VPP_SC_TOP_EN_BIT, + VPP_SC_TOP_EN_WID); + } + + /* horitontal filter settings */ + if (setting->sc_h_enable) { + if (vpp_filter->vpp_horz_coeff[1] & 0x8000) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_HORZ | VPP_COEF_9BIT); + } else { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_HORZ); + } + for (i = 0; i < + (vpp_filter->vpp_horz_coeff[1] & 0xff); i++) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF + misc_off, + vpp_filter->vpp_horz_coeff[i + 2]); + } + r1 = frame_par->VPP_hsc_linear_startp + - frame_par->VPP_hsc_startp; + r2 = frame_par->VPP_hsc_linear_endp + - frame_par->VPP_hsc_startp; + r3 = frame_par->VPP_hsc_endp + - frame_par->VPP_hsc_startp; + + VSYNC_WR_MPEG_REG_BITS( + VD2_HSC_PHASE_CTRL + misc_off, + frame_par->VPP_hf_ini_phase_, + VPP_HSC_TOP_INI_PHASE_BIT, + VPP_HSC_TOP_INI_PHASE_WID); + + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION12_STARTP + misc_off, + (0 << VPP_REGION1_BIT) | + ((r1 & VPP_REGION_MASK) + << VPP_REGION2_BIT)); + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION34_STARTP + misc_off, + ((r2 & VPP_REGION_MASK) + << VPP_REGION3_BIT) | + ((r3 & VPP_REGION_MASK) + << VPP_REGION4_BIT)); + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION4_ENDP + misc_off, r3); + + VSYNC_WR_MPEG_REG( + VD2_HSC_START_PHASE_STEP + misc_off, + vpp_filter->vpp_hf_start_phase_step); + + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION1_PHASE_SLOPE + misc_off, + vpp_filter->vpp_hf_start_phase_slope); + + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION3_PHASE_SLOPE + misc_off, + vpp_filter->vpp_hf_end_phase_slope); + } + + /* vertical filter settings */ + if (setting->sc_v_enable) { + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_VERT); + for (i = 0; i < vpp_filter->vpp_vert_coeff[1]; i++) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF + misc_off, + vpp_filter->vpp_vert_coeff[i + 2]); + } + + /* vertical chroma filter settings */ + if (vpp_filter->vpp_vert_chroma_filter_en) { + const u32 *pCoeff = + vpp_filter->vpp_vert_chroma_coeff; + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_VERT_CHROMA + |VPP_COEF_SEP_EN); + for (i = 0; i < pCoeff[1]; i++) + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF + misc_off, + pCoeff[i + 2]); + } + + r1 = frame_par->VPP_vsc_endp + - frame_par->VPP_vsc_startp; + VSYNC_WR_MPEG_REG( + VD2_VSC_REGION12_STARTP + misc_off, 0); + + VSYNC_WR_MPEG_REG( + VD2_VSC_REGION34_STARTP + misc_off, + ((r1 & VPP_REGION_MASK) + << VPP_REGION3_BIT) | + ((r1 & VPP_REGION_MASK) + << VPP_REGION4_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_VSC_REGION4_ENDP + misc_off, r1); + + VSYNC_WR_MPEG_REG( + VD2_VSC_START_PHASE_STEP + misc_off, + vpp_filter->vpp_vsc_start_phase_step); + } + + VSYNC_WR_MPEG_REG( + VPP_VD2_HDR_IN_SIZE + misc_off, + (frame_par->VPP_pic_in_height_ << 16) + | frame_par->VPP_line_in_length_); +} + +s32 config_vd_blend( + u8 layer_id, + struct vpp_frame_par_s *cur_frame_par, + struct vframe_s *vf, + u32 layer_alpha, + struct blend_setting_s *setting) +{ + /* u32 type = 0; */ + u32 vskip, hskip; + + if (!cur_frame_par || !setting || !vf) + return -1; + + setting->frame_par = cur_frame_par; + setting->id = layer_id; + setting->misc_reg_offt = 0; + + setting->layer_alpha = layer_alpha; + setting->preblend_h_start = 0; + setting->preblend_h_end = 4096; + if ((cur_frame_par->VPP_post_blend_vd_v_end_ - + cur_frame_par->VPP_post_blend_vd_v_start_ + 1) + > VPP_PREBLEND_VD_V_END_LIMIT) { + setting->preblend_v_start = + cur_frame_par->VPP_post_blend_vd_v_start_; + setting->preblend_v_end = + cur_frame_par->VPP_post_blend_vd_v_end_; + } else { + setting->preblend_v_start = 0; + setting->preblend_v_end = + VPP_PREBLEND_VD_V_END_LIMIT - 1; + } + + setting->preblend_h_size = + cur_frame_par->VPP_line_in_length_; + + /* old chip, vd2 has no scaler, so only can use mif setting */ + if ((setting->id != 0) && + (legacy_vpp || is_meson_tl1_cpu())) { + vskip = cur_frame_par->vscale_skip_count; + hskip = cur_frame_par->hscale_skip_count; + + setting->postblend_h_start = + cur_frame_par->VPP_hd_start_lines_; + setting->postblend_h_end = + cur_frame_par->VPP_hd_start_lines_ + + (cur_frame_par->VPP_line_in_length_ >> hskip) - 1; + setting->postblend_v_start = + cur_frame_par->VPP_vd_start_lines_; + setting->postblend_v_end = + cur_frame_par->VPP_vd_start_lines_ + + (cur_frame_par->VPP_pic_in_height_ >> vskip) - 1; + setting->postblend_h_size = + cur_frame_par->VPP_post_blend_h_size_; + } else { + setting->postblend_h_start = + cur_frame_par->VPP_hsc_startp; + setting->postblend_h_end = + cur_frame_par->VPP_hsc_endp; + setting->postblend_v_start = + cur_frame_par->VPP_vsc_startp; + setting->postblend_v_end = + cur_frame_par->VPP_vsc_endp; + setting->postblend_h_size = + cur_frame_par->VPP_post_blend_h_size_; + } + + if (!legacy_vpp) { + u32 temp_h = cur_frame_par->VPP_pic_in_height_; + + temp_h <<= 16; + setting->preblend_h_size |= temp_h; + + temp_h = + cur_frame_par->VPP_post_blend_vd_v_end_ + 1; + temp_h <<= 16; + setting->postblend_h_size |= temp_h; + } + +#if 0 + /* TODO: need remove this work around check for afbc */ + type = vf->type; + if (cur_frame_par->nocomp) + type &= ~VIDTYPE_COMPRESS; + + if (type & VIDTYPE_COMPRESS) { + u32 v_phase; + struct vppfilter_mode_s *vpp_filter = + &cur_frame_par->vpp_filter; + v_phase = vpp_filter->vpp_vsc_start_phase_step; + v_phase *= (cur_frame_par->vscale_skip_count + 1); + if ((v_phase > 0x1000000) && + (layer->disp_info.layer_top < 0)) { + if ((cur_frame_par->VPP_vsc_endp > 0x6) && + ((cur_frame_par->VPP_vsc_endp < 0x250) + || (cur_frame_par->VPP_vsc_endp < + cur_frame_par->VPP_post_blend_vd_v_end_/2))) { + setting->postblend_v_end -= 6; + } + } + } +#endif + return 0; +} + +static inline void vd2_vpp_blend_setting( + struct blend_setting_s *setting) +{ + u32 misc_off; + u32 vd_size_mask = VPP_VD_SIZE_MASK; + + if (!setting) + return; + + /* g12a change to 13 bits */ + if (!legacy_vpp) + vd_size_mask = 0x1fff; + + misc_off = 0; + + /* vd2 preblend size should be same postblend size */ + /* preblend setting */ + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + misc_off, + ((setting->postblend_h_start & vd_size_mask) + << VPP_VD1_START_BIT) | + ((setting->postblend_h_end & vd_size_mask) + << VPP_VD1_END_BIT)); + + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_V_START_END + misc_off, + ((setting->postblend_v_start & vd_size_mask) + << VPP_VD1_START_BIT) | + ((setting->postblend_v_end & vd_size_mask) + << VPP_VD1_END_BIT)); +} + +static inline void proc_vd2_vsc_phase_per_vsync( + struct vpp_frame_par_s *frame_par, + struct vframe_s *vf, + u32 vout_type) +{ + struct f2v_vphase_s *vphase; + u32 misc_off, vin_type; + struct vppfilter_mode_s *vpp_filter; + + if (legacy_vpp || is_meson_tl1_cpu() + || !frame_par || !vf) + return; + + vpp_filter = &frame_par->vpp_filter; + misc_off = 0; + vin_type = vf->type & VIDTYPE_TYPEMASK; + /* vertical phase */ + vphase = &frame_par->VPP_vf_ini_phase_ + [vpp_phase_table[vin_type] + [vout_type]]; + VSYNC_WR_MPEG_REG( + VD2_VSC_INI_PHASE + misc_off, + ((u32) (vphase->phase) << 8)); + + if (vphase->repeat_skip >= 0) { + /* skip lines */ + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + skip_tab[vphase->repeat_skip], + VPP_PHASECTL_INIRCVNUMT_BIT, + VPP_PHASECTL_INIRCVNUM_WID + + VPP_PHASECTL_INIRPTNUM_WID); + } else { + /* repeat first line */ + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + 4, + VPP_PHASECTL_INIRCVNUMT_BIT, + VPP_PHASECTL_INIRCVNUM_WID); + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + 1 - vphase->repeat_skip, + VPP_PHASECTL_INIRPTNUMT_BIT, + VPP_PHASECTL_INIRPTNUM_WID); + } + + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); +} + +static void pip_toggle_frame(struct vframe_s *vf) +{ + u32 first_picture = 0; + + if (vf == NULL) + return; + + ori2_start_x_lines = 0; + ori2_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + ori2_start_y_lines = 0; + ori2_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + + if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) + pr_info("%s()\n", __func__); + + if ((vf->width == 0) && (vf->height == 0)) { + amlog_level(LOG_LEVEL_ERROR, + "Video: invalid frame dimension\n"); + return; + } + if (cur_pipbuf + && (cur_pipbuf != &local_pip) + && (cur_pipbuf != vf)) { + pip_frame_count++; + if (pip_frame_count == 1) + first_picture = 1; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { + if (pip_rdma_buf == cur_pipbuf) + pipbuf_to_put = cur_pipbuf; + else + pip_vf_put(cur_pipbuf); + } else { + if (pipbuf_to_put) { + pip_vf_put( + pipbuf_to_put); + pipbuf_to_put = NULL; + } + pip_vf_put(cur_pipbuf); + } +#else + pip_vf_put(cur_pipbuf); +#endif + } else if (!cur_pipbuf + || (cur_pipbuf == &local_pip)) + first_picture = 1; + + /* switch buffer */ + if (vf->type & VIDTYPE_COMPRESS) { + VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR, + vf->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR, + vf->compBodyAddr>>4); + } + if (vf->canvas0Addr != 0) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (vf->canvas0Addr != (u32)-1) { + canvas_copy(vf->canvas0Addr & 0xff, + disp_canvas_index[pip_rdma_canvas_id][3]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[pip_rdma_canvas_id][4]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[pip_rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas0_config[0], + vf->plane_num, + &disp_canvas_index[pip_rdma_canvas_id][3]); + } + + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[pip_rdma_canvas_id][1]); + + pip_next_rdma_canvas_id = pip_rdma_canvas_id ? 0 : 1; +#endif + } + + if (pip_property_changed) { + first_picture = 1; + pip_property_changed = 0; + } + if (cur_pipbuf != vf) + vf->type_backup = vf->type; + + /* enable new config on the new frames */ + if ((first_picture) || (cur_pipbuf && + ((cur_pipbuf->bufWidth != vf->bufWidth) || + (cur_pipbuf->width != vf->width) || + (cur_pipbuf->height != vf->height) || + (cur_pipbuf->bitdepth != vf->bitdepth) || + (cur_pipbuf->trans_fmt != vf->trans_fmt) || + (cur_pipbuf->ratio_control != vf->ratio_control) || + ((cur_pipbuf->type_backup & VIDTYPE_INTERLACE) != + (vf->type_backup & VIDTYPE_INTERLACE)) || + (cur_pipbuf->type != vf->type)))) { + int iret; + + /* apply new vpp settings */ + nextpip_frame_par = + (&pip_frame_parms[0] == nextpip_frame_par) ? + &pip_frame_parms[1] : &pip_frame_parms[0]; + + update_layer_info(1); + if (legacy_vpp || is_meson_tl1_cpu()) + iret = vpp_set_filters_no_scaler( + &glayer_info[1], vf, + nextpip_frame_par, vinfo); + else + iret = vpp_set_filters( + &glayer_info[1], vf, + nextpip_frame_par, vinfo, + true); + + if (iret == VppFilter_Success_and_Changed) + pip_property_changed = 1; + + pip_frame_ready_to_set = 1; + } + + if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && + (!pip_property_changed || (vf != cur_pipbuf))) { + if (disable_videopip == VIDEO_DISABLE_FORNEXT) { + EnableVideoLayer2(); + disable_videopip = VIDEO_DISABLE_NONE; + } + if (first_picture && + (disable_videopip != + VIDEO_DISABLE_NORMAL)) { + EnableVideoLayer2(); + } + } + cur_pipbuf = vf; + if (first_picture) + pip_frame_ready_to_set = 1; +} + +static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) +{ + u32 r; + u32 vphase, vini_phase; + u32 pat, loop; + static const u32 vpat[MAX_VSKIP_COUNT + 1] = { + 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + u32 u, v; + u32 type, bit_mode = 0; + + if (!vf || !frame_par) { + pr_err("pip_set_dcu vf is NULL\n"); + return; + } + + type = vf->type; + pr_debug("pip_set_dcu %p, type:0x%x\n", vf, type); + + if (frame_par->nocomp) + type &= ~VIDTYPE_COMPRESS; + + if (type & VIDTYPE_COMPRESS) { + r = (3 << 24) | + (vpp_hold_line << 16) | + ((legacy_vpp ? 1 : 2) << 14) | /* burst1 */ + (vf->bitdepth & BITDEPTH_MASK); + + if (frame_par->hscale_skip_count) + r |= 0x33; + if (frame_par->vscale_skip_count) + r |= 0xcc; + +#ifdef TV_REVERSE + if (reverse) + r |= (1<<26) | (1<<27); +#endif + if (vf->bitdepth & BITDEPTH_SAVING_MODE) + r |= (1<<28); /* mem_saving_mode */ + if (type & VIDTYPE_SCATTER) + r |= (1<<29); + VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r); + + r = 0x1700; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (vf && (vf->source_type + != VFRAME_SOURCE_TYPE_HDMI)) + r |= (1 << 19); /* dos_uncomp */ + } + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, r); + + r = 0x100; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + VSYNC_WR_MPEG_REG(VD2_AFBC_DEC_DEF_COLOR, + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ + r = HFORMATTER_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; +#if 0 /* def CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */ + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + r |= HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + } else +#endif + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, 0); + } + + vd2_path_select(true); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + + cur_dev->viu_off, 0); + return; + } + + if ((vf->bitdepth & BITDEPTH_Y10) && + (!frame_par->nocomp)) { + if (vf->type & VIDTYPE_VIU_444) { + bit_mode = 2; + } else { + if (vf->bitdepth & FULL_PACK_422_MODE) + bit_mode = 3; + else + bit_mode = 1; + } + } else { + bit_mode = 0; + } + vd2_path_select(false); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (bit_mode & 0x3), 8, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG3 + cur_dev->viu_off, + (bit_mode&0x3), 8, 2); + } + if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1)) + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + if (type & VIDTYPE_VIU_NV21) + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 1, 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 0, 0, 1); + + r = (3 << VDIF_URGENT_BIT) | + (vpp_hold_line << VDIF_HOLD_LINES_BIT) | + VDIF_FORMAT_SPLIT | + VDIF_CHRO_RPT_LAST | VDIF_ENABLE; + /* | VDIF_RESET_ON_GO_FIELD;*/ + if (debug_flag & DEBUG_FLAG_GOFIELD_MANUL) + r |= 1<<7; /*for manul triggle gofiled.*/ + + if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0) + r |= VDIF_SEPARATE_EN; + else { + if (type & VIDTYPE_VIU_422) + r |= VDIF_FORMAT_422; + else { + r |= VDIF_FORMAT_RGB888_YUV444 | + VDIF_DEMUX_MODE_RGB_444; + } + } + + if (frame_par->hscale_skip_count) + r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; + + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, r); + +#ifdef TV_REVERSE + if (reverse) { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0xf, 2, 4); + } else { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0, 2, 4); + } +#endif + + /* chroma formatter */ + if (type & VIDTYPE_VIU_444) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_1_1); + } else if (type & VIDTYPE_VIU_FIELD) { + vini_phase = 0xc << VFORMATTER_INIPHASE_BIT; + vphase = ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT; + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && + (vf->height >= 2160) && + (type & VIDTYPE_VIU_422)) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } + + if (is_meson_txlx_cpu() + || is_meson_g12a_cpu() + || is_meson_g12b_cpu()) + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + 1, 29, 1); + + /* LOOP/SKIP pattern */ + pat = vpat[frame_par->vscale_skip_count]; + + if (type & VIDTYPE_VIU_FIELD) { + loop = 0; + + if (type & VIDTYPE_INTERLACE) + pat = vpat[frame_par->vscale_skip_count >> 1]; + } else if (type & VIDTYPE_MVC) { + loop = 0x11; + pat = 0x80; + } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + loop = 0x11; + pat <<= 4; + } else + loop = 0; + + VSYNC_WR_MPEG_REG( + VD2_IF0_RPT_LOOP + cur_dev->viu_off, + (loop << VDIF_CHROMA_LOOP1_BIT) | + (loop << VDIF_LUMA_LOOP1_BIT) | + (loop << VDIF_CHROMA_LOOP0_BIT) | + (loop << VDIF_LUMA_LOOP0_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); +} +#endif + +/* for sdr/hdr/single dv switch with dual dv */ +static u32 last_el_status; +/* for dual dv switch with different el size */ +static u32 last_el_w; +bool has_enhanced_layer(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + + if (!vf) + return 0; + if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) + return 0; + if (!is_dolby_vision_on()) + return 0; + + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + return req.dv_enhance_exist; +} +u32 property_changed_true; + +static u64 func_div(u64 number, u32 divid) +{ + u64 tmp = number; + + do_div(tmp, divid); + return tmp; +} + +static void vsync_toggle_frame(struct vframe_s *vf) +{ + u32 first_picture = 0; + unsigned long flags = 0; + bool vf_with_el = false; + bool force_toggle = false; + long long *clk_array; + bool is_mvc = false; + + if (vf == NULL) + return; + frame_count++; + toggle_count++; + + if (vf->type & VIDTYPE_MVC) + is_mvc = true; + + if (is_dolby_vision_enable()) + vf_with_el = has_enhanced_layer(vf); + +#ifdef PTS_TRACE_DEBUG +#ifdef PTS_TRACE_START + if (pts_trace_his_rd < 16) { +#endif + pts_trace_his[pts_trace_his_rd] = pts_trace; + pts_his[pts_trace_his_rd] = vf->pts; + scr_his[pts_trace_his_rd] = timestamp_pcrscr_get(); + pts_trace_his_rd++; + if (pts_trace_his_rd >= 16) + pts_trace_his_rd = 0; +#ifdef PTS_TRACE_START + } +#endif +#endif + +#ifdef PTS_LOGGING + if (pts_escape_vsync == 1) { + pts_trace++; + pts_escape_vsync = 0; + } + vsync_video_pattern(); + pre_pts_trace = pts_trace; +#endif + +#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) + pts_trace = 0; +#endif + + ori_start_x_lines = 0; + ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + ori_start_y_lines = 0; + ori_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) { + u32 pcr = timestamp_pcrscr_get(); + u32 vpts = timestamp_vpts_get(); + u32 apts = timestamp_apts_get(); + + pr_info("%s pts:%d.%06d pcr:%d.%06d vpts:%d.%06d apts:%d.%06d\n", + __func__, (vf->pts) / 90000, + ((vf->pts) % 90000) * 1000 / 90, (pcr) / 90000, + ((pcr) % 90000) * 1000 / 90, (vpts) / 90000, + ((vpts) % 90000) * 1000 / 90, (apts) / 90000, + ((apts) % 90000) * 1000 / 90); + } + + if (trickmode_i || trickmode_fffb) + trickmode_duration_count = trickmode_duration; + + if (vf->early_process_fun) { + if (vf->early_process_fun(vf->private_data, vf) == 1) { + /* video_property_changed = true; */ + first_picture = 1; + } + } else { +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) != 0) { + /* check mif enable status, disable post di */ + VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); + VSYNC_WR_MPEG_REG(DI_POST_SIZE, + (32 - 1) | ((128 - 1) << 16)); + VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, + READ_VCBUS_REG(DI_IF1_GEN_REG) & + 0xfffffffe); + } +#endif + } + + timer_count = 0; + if ((vf->width == 0) && (vf->height == 0)) { + amlog_level(LOG_LEVEL_ERROR, + "Video: invalid frame dimension\n"); + return; + } + + if (hold_video) { + if (cur_dispbuf != vf) { + new_frame_count++; + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_set(vf->pts); + last_frame_duration = vf->duration; + } else if (last_frame_duration) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_inc(DUR2PTS + (last_frame_duration)); + + vpts_remainder += + DUR2PTS_RM(last_frame_duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + video_vf_put(vf); + return; + } + } + + if ((cur_dispbuf) && (cur_dispbuf != &vf_local) && (cur_dispbuf != vf) + && (video_property_changed != 2)) { + new_frame_count++; + if (new_frame_count == 1) + first_picture = 1; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { +#ifdef RDMA_RECYCLE_ORDERED_VFRAMES + if (dispbuf_to_put_num < DISPBUF_TO_PUT_MAX) { + dispbuf_to_put[dispbuf_to_put_num] = + cur_dispbuf; + dispbuf_to_put_num++; + } else + video_vf_put(cur_dispbuf); +#else + if (cur_rdma_buf == cur_dispbuf) { + dispbuf_to_put[0] = cur_dispbuf; + dispbuf_to_put_num = 1; + } else + video_vf_put(cur_dispbuf); +#endif + } else { + int i; + + for (i = 0; i < dispbuf_to_put_num; i++) { + if (dispbuf_to_put[i]) { + video_vf_put( + dispbuf_to_put[i]); + dispbuf_to_put[i] = NULL; + } + dispbuf_to_put_num = 0; + } + video_vf_put(cur_dispbuf); + } +#else + video_vf_put(cur_dispbuf); +#endif + if (debug_flag & DEBUG_FLAG_LATENCY) { + vf->ready_clock[3] = sched_clock(); + pr_info( + "video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n", + func_div(vf->ready_clock[3], 1000), + func_div(vf->ready_clock[2], 1000), + func_div(vf->ready_clock[1], 1000), + func_div(vf->ready_clock[0], 1000)); + cur_dispbuf->ready_clock[4] = sched_clock(); + clk_array = cur_dispbuf->ready_clock; + pr_info("video put latency %lld ms, video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n", + func_div(*(clk_array + 4), 1000), + func_div(*(clk_array + 3), 1000), + func_div(*(clk_array + 2), 1000), + func_div(*(clk_array + 1), 1000), + func_div(*clk_array, 1000)); + } + } else + first_picture = 1; + + if (video_property_changed) { + property_changed_true = 2; + video_property_changed = 0; + first_picture = 1; + } + if (property_changed_true > 0) { + property_changed_true--; + first_picture = 1; + } + + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && first_picture) + pr_info("first picture {%d,%d} pts:%x,\n", + vf->width, vf->height, vf->pts); + + /* switch buffer */ + post_canvas = vf->canvas0Addr; + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && + (vf->type & VIDTYPE_COMPRESS)) { + VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4); + } + if ((vf->canvas0Addr != 0) +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + && ((DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) == 0) + /* check di_post_viu_link */ +#endif + ) { + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (vf->canvas0Addr != (u32)-1) { + canvas_copy(vf->canvas0Addr & 0xff, + disp_canvas_index[rdma_canvas_id][0]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][1]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][2]); + } else { + vframe_canvas_set(&vf->canvas0_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][0]); + } + if (is_mvc) { + if (vf->canvas1Addr != (u32)-1) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[rdma_canvas_id][3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas1_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][3]); + } + } + + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode == 1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + } + if (cur_frame_par + && (process_3d_type & MODE_3D_ENABLE) + && (process_3d_type & MODE_3D_TO_2D_R) + && (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1) + && is_mvc) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } + next_rdma_canvas_id = rdma_canvas_id ? 0 : 1; +#else + canvas_copy(vf->canvas0Addr & 0xff, disp_canvas_index[0]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[1]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[2]); + if (is_mvc) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[5]); + } + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode == 1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); + } +#endif + } + /* set video PTS */ + if (cur_dispbuf != vf) { + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_set(vf->pts); + } else if (cur_dispbuf) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_inc(DUR2PTS + (cur_dispbuf->duration)); + + vpts_remainder += + DUR2PTS_RM(cur_dispbuf->duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + vf->type_backup = vf->type; + } + + if (cur_dispbuf && vf && + (cur_dispbuf->ratio_control & + DISP_RATIO_ADAPTED_PICMODE) && + (cur_dispbuf->ratio_control == + vf->ratio_control) && + memcmp(&cur_dispbuf->pic_mode, &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + + if ((last_process_3d_type != process_3d_type) + || (last_el_status != vf_with_el)) + force_toggle = true; + + /* enable new config on the new frames */ + if (first_picture || force_toggle || + (cur_dispbuf && + ((cur_dispbuf->bufWidth != vf->bufWidth) || + (cur_dispbuf->width != vf->width) || + (cur_dispbuf->height != vf->height) || + (cur_dispbuf->bitdepth != vf->bitdepth) || + (cur_dispbuf->trans_fmt != vf->trans_fmt) || + (cur_dispbuf->ratio_control != vf->ratio_control) || + ((cur_dispbuf->type_backup & VIDTYPE_INTERLACE) != + (vf->type_backup & VIDTYPE_INTERLACE)) || + (cur_dispbuf->type != vf->type)))) { + int iret; + + last_process_3d_type = process_3d_type; + atomic_inc(&video_sizechange); + wake_up_interruptible(&amvideo_sizechange_wait); + amlog_mask(LOG_MASK_FRAMEINFO, + "%s %dx%d ar=0x%x\n", + ((vf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) ? "interlace-top" + : ((vf->type & VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_BOTTOM) + ? "interlace-bottom" : "progressive", vf->width, + vf->height, vf->ratio_control); +#ifdef TV_3D_FUNCTION_OPEN + amlog_mask(LOG_MASK_FRAMEINFO, + "%s trans_fmt=%u\n", __func__, vf->trans_fmt); + +#endif + next_frame_par = (&frame_parms[0] == next_frame_par) ? + &frame_parms[1] : &frame_parms[0]; + + update_layer_info(0); + iret = vpp_set_filters( + &glayer_info[0], vf, + next_frame_par, vinfo, + (is_dolby_vision_on() && + is_dolby_vision_stb_mode())); + + if (iret == VppFilter_Success_and_Changed) + video_property_changed = 1; + + /* apply new vpp settings */ + frame_par_ready_to_set = 1; + + if (((vf->width > 1920) && (vf->height > 1088)) || + ((vf->type & VIDTYPE_COMPRESS) && + (vf->compWidth > 1920) && + (vf->compHeight > 1080))) { + if (vpu_clk_level == 0) { + vpu_clk_level = 1; + spin_lock_irqsave(&lock, flags); + vpu_delay_work_flag |= + VPU_DELAYWORK_VPU_CLK; + spin_unlock_irqrestore(&lock, flags); + } + } else { + if (vpu_clk_level == 1) { + vpu_clk_level = 0; + spin_lock_irqsave(&lock, flags); + vpu_delay_work_flag |= + VPU_DELAYWORK_VPU_CLK; + spin_unlock_irqrestore(&lock, flags); + } + } + } + last_el_status = vf_with_el; + + if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && + ((!property_changed_true) || (vf != cur_dispbuf))) { + if (disable_video == VIDEO_DISABLE_FORNEXT) { + EnableVideoLayer(); + disable_video = VIDEO_DISABLE_NONE; + } + if (first_picture && (disable_video != VIDEO_DISABLE_NORMAL)) { + EnableVideoLayer(); + if ((vf->type & VIDTYPE_MVC) || + (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) + EnableVideoLayer2(); + else if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else if (need_disable_vd2) + DisableVideoLayer2(); + } + } + if (cur_dispbuf && (cur_dispbuf->type != vf->type)) { + if ((vf->type & VIDTYPE_MVC) || + (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) + EnableVideoLayer2(); + else { + if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else if (need_disable_vd2) + DisableVideoLayer2(); + } + } + cur_dispbuf = vf; + if (first_picture) { + frame_par_ready_to_set = 1; + first_frame_toggled = 1; + +#ifdef VIDEO_PTS_CHASE + av_sync_flag = 0; +#endif + } + if (cur_dispbuf != &vf_local) + video_keeper_new_frame_notify(); + + if ((vf != &vf_local) && (vf) && !vsync_pts_aligned) { +#ifdef PTS_TRACE_DEBUG + pr_info("####timestamp_pcrscr_get() = 0x%x, vf->pts = 0x%x, vsync_pts_inc = %d\n", + timestamp_pcrscr_get(), vf->pts, vsync_pts_inc); +#endif + if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc)) + && ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) { + /*vsync_pts_align = vsync_pts_inc / 4 - */ + /* (timestamp_pcrscr_get() - vf->pts);*/ + vsync_pts_align = 0; + vsync_pts_aligned = true; +#ifdef PTS_TRACE_DEBUG + pts_trace_his_rd = 0; + pr_info("####vsync_pts_align set to %d\n", + vsync_pts_align); +#endif + } + } +} + static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) { u32 r; @@ -3169,13 +3966,17 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; u32 u, v; u32 type, bit_mode = 0; - bool vf_with_el = false; + bool is_mvc = false; if (vf == NULL) { pr_info("viu_set_dcu vf NULL, return\n"); return; } + type = vf->type; + if (type & VIDTYPE_MVC) + is_mvc = true; + pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { if (frame_par->nocomp) @@ -3305,7 +4106,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VSYNC_WR_MPEG_REG_BITS( G12_VD1_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS( G12_VD2_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); @@ -3314,7 +4115,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VD1_IF0_GEN_REG3 + cur_dev->viu_off, (bit_mode & 0x3), 8, 2); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS( VD2_IF0_GEN_REG3 + cur_dev->viu_off, @@ -3353,15 +4154,14 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VDIF_DEMUX_MODE_RGB_444; } } - if (is_dolby_vision_enable()) - vf_with_el = has_enhanced_layer(vf); + if (frame_par->hscale_skip_count) r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; /*enable go field reset default according to vlsi*/ r |= VDIF_RESET_ON_GO_FIELD; VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + cur_dev->viu_off, r); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VD2_IF0_GEN_REG + cur_dev->viu_off, r); @@ -3374,38 +4174,20 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 + cur_dev->viu_off, 0, 0, 1); } -#if HAS_VPU_PROT - if (has_vpu_prot()) { - if (use_prot) { - if (vf->video_angle == 2) { - VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 - + - cur_dev->viu_off, - 0xf, 2, 4); - } else { - VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 - + - cur_dev->viu_off, - 0, 2, 4); - } - } - } -#else #ifdef TV_REVERSE if (reverse) { VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + cur_dev->viu_off), 0xf, 2, 4); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + cur_dev->viu_off), 0xf, 2, 4); } else { VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + cur_dev->viu_off), 0, 2, 4); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + cur_dev->viu_off), 0, 2, 4); } -#endif #endif } /* #endif */ @@ -3414,7 +4196,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) if (type & VIDTYPE_VIU_444) { VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_1_1); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_1_1); } else if (type & VIDTYPE_VIU_FIELD) { @@ -3455,7 +4237,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_RRT_PIXEL0 | @@ -3471,7 +4253,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase | vformatter); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | @@ -3489,7 +4271,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VFORMATTER_RPTLINE0_EN | vini_phase | vphase | vformatter); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | @@ -3506,7 +4288,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (0xe << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | (0xa << @@ -3521,7 +4303,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | @@ -3555,7 +4337,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); } - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | @@ -3602,7 +4384,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (loop << VDIF_LUMA_LOOP1_BIT) | (loop << VDIF_CHROMA_LOOP0_BIT) | (loop << VDIF_LUMA_LOOP0_BIT)); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VD2_IF0_RPT_LOOP + cur_dev->viu_off, (loop << VDIF_CHROMA_LOOP1_BIT) | @@ -3620,8 +4402,6 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) pat = 0; else pat = 0x88; - } - if (!vf_with_el) { VSYNC_WR_MPEG_REG( VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); VSYNC_WR_MPEG_REG( @@ -3632,46 +4412,14 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); } - if (platform_type == 0) { - /* picture 0/1 control */ - if (((type & VIDTYPE_INTERLACE) == 0) && - ((type & VIDTYPE_VIU_FIELD) == 0) && - ((type & VIDTYPE_MVC) == 0)) { - /* progressive frame in two pictures */ + /* picture 0/1 control */ + if ((((type & VIDTYPE_INTERLACE) == 0) && + ((type & VIDTYPE_VIU_FIELD) == 0) && + ((type & VIDTYPE_MVC) == 0)) || + (frame_par->vpp_2pic_mode & 0x3)) { + /* progressive frame in two pictures */ + if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) { VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, (2 << 26) | /* two pic mode */ - (2 << 24) | /* use own last line */ - (2 << 8) | /* toggle pic 0 and 1, use pic0 first */ - (0x01)); /* loop pattern */ - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, - (2 << 26) | /* two pic mode */ - (2 << 24) | /* use own last line */ - (2 << 8) | /* toggle pic 0 and 1, use pic0 first */ - (0x01)); /* loop pattern */ - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } - } - } else { - /* picture 0/1 control */ - if ((((type & VIDTYPE_INTERLACE) == 0) && - ((type & VIDTYPE_VIU_FIELD) == 0) && - ((type & VIDTYPE_MVC) == 0)) || - (frame_par->vpp_2pic_mode & 0x3)) { - /* progressive frame in two pictures */ - if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, (2 << 26) | /* two pic mode */ (2 << 24) | @@ -3680,7 +4428,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) /* toggle pic 0 and 1, use pic1 first*/ (0x01)); /* loop pattern */ - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, (2 << 26) | /* two pic mode */ (2 << 24) | @@ -3689,53 +4437,52 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) /* toggle pic 0 and 1,use pic1 first */ (0x01)); /* loop pattern */ - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, (2 << 26) | - /* two pic mode */ - (2 << 24) | - /* use own last line */ - (2 << 8) | - /* toggle pic 0 and 1, use pic0 first */ - (0x01)); - /* loop pattern */ - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, (2 << 26) | - /* two pic mode */ - (2 << 24) | - /* use own last line */ - (2 << 8) | - /* toggle pic 0 and 1, use pic0 first */ - (0x01)); - /* loop pattern */ - } - } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { - /*FA LR/TB output , do nothing*/ } else { - if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (2 << 8) | + /* toggle pic 0 and 1, use pic0 first */ + (0x01)); + /* loop pattern */ + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (2 << 8) | + /* toggle pic 0 and 1, use pic0 first */ + (0x01)); + /* loop pattern */ + } + } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { + /*FA LR/TB output , do nothing*/ + } else { + if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + if (is_mvc) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - } - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + } + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } + if (is_mvc) { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); } } } @@ -4148,8 +4895,6 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } } -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - static int detect_vout_type(void) { int vout_type = VOUT_TYPE_PROG; @@ -4175,37 +4920,6 @@ static int detect_vout_type(void) return vout_type; } -#else -static int detect_vout_type(void) -{ -#if defined(CONFIG_AM_TCON_OUTPUT) - return VOUT_TYPE_PROG; -#else - int vout_type; - int encp_enable = READ_VCBUS_REG(ENCP_VIDEO_EN) & 1; - - if (encp_enable) { - if (READ_VCBUS_REG(ENCP_VIDEO_MODE) & (1 << 12)) { - /* 1080I */ - if (READ_VCBUS_REG(VENC_ENCP_LINE) < 562) - vout_type = VOUT_TYPE_TOP_FIELD; - - else - vout_type = VOUT_TYPE_BOT_FIELD; - - } else - vout_type = VOUT_TYPE_PROG; - - } else { - vout_type = (READ_VCBUS_REG(VENC_STATA) & 1) ? - VOUT_TYPE_BOT_FIELD : VOUT_TYPE_TOP_FIELD; - } - - return vout_type; -#endif -} -#endif - #ifdef INTERLACE_FIELD_MATCH_PROCESS static inline bool interlace_field_type_need_match(int vout_type, struct vframe_s *vf) @@ -4785,29 +5499,27 @@ static inline bool video_vf_dirty_put(struct vframe_s *vf) if (!vf->frame_dirty) return false; if (cur_dispbuf != vf) { - if (vf->source_type != VFRAME_SOURCE_TYPE_OSD) { - if (vf->pts != 0) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts to vf->pts:0x%x,scr:0x%x,abs_scr: 0x%x\n", - vf->pts, timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - timestamp_vpts_set(vf->pts); - } else if (cur_dispbuf) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts inc:0x%x,scr: 0x%x, abs_scr: 0x%x\n", - timestamp_vpts_get() + - DUR2PTS(cur_dispbuf->duration), - timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - timestamp_vpts_inc( - DUR2PTS(cur_dispbuf->duration)); + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to vf->pts:0x%x,scr:0x%x,abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_set(vf->pts); + } else if (cur_dispbuf) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc:0x%x,scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_inc( + DUR2PTS(cur_dispbuf->duration)); - vpts_remainder += - DUR2PTS_RM(cur_dispbuf->duration); - if (vpts_remainder >= 0xf) { - vpts_remainder -= 0xf; - timestamp_vpts_inc(-1); - } + vpts_remainder += + DUR2PTS_RM(cur_dispbuf->duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); } } } @@ -5195,7 +5907,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) vinfo->sync_duration_num; vsync_pts_inc_scale = vinfo->sync_duration_den; vsync_pts_inc_scale_base = vinfo->sync_duration_num; - video_property_changed = true; + video_property_changed = 1; pr_info("Change to video 0\n"); } } else { @@ -5207,7 +5919,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) vinfo->sync_duration_num; vsync_pts_inc_scale = vinfo->sync_duration_den; vsync_pts_inc_scale_base = vinfo->sync_duration_num; - video_property_changed = true; + video_property_changed = 1; pr_info("Change to video 1\n"); } } @@ -5253,7 +5965,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) if ((vf) && ((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0)) { if ((old_vmode != new_vmode) || (debug_flag == 8)) { debug_flag = 1; - video_property_changed = true; + video_property_changed = 1; pr_info("detect vout mode change!!!!!!!!!!!!\n"); old_vmode = new_vmode; } @@ -5418,25 +6130,21 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) goto exit; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if (is_vsync_rdma_enable()) + if (is_vsync_rdma_enable()) { rdma_canvas_id = next_rdma_canvas_id; - else { - if (rdma_enable_pre) { - /*do not write register directly before RDMA is done */ - /*#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TV */ - if (is_meson_mtvd_cpu()) { - if (debug_flag & DEBUG_FLAG_RDMA_WAIT_1) { - while - ( - ((READ_VCBUS_REG(ENCL_INFO_READ) >> 16) - & 0x1fff) < 50); - } - } - /* #endif */ +#ifdef VIDEO_PIP + pip_rdma_canvas_id = pip_next_rdma_canvas_id; +#endif + } else { + if (rdma_enable_pre) goto exit; - } + rdma_canvas_id = 0; next_rdma_canvas_id = 1; +#ifdef VIDEO_PIP + pip_rdma_canvas_id = 0; + pip_next_rdma_canvas_id = 1; +#endif } for (i = 0; i < dispbuf_to_put_num; i++) { @@ -5446,21 +6154,13 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } dispbuf_to_put_num = 0; } -#endif - - if (osd_prov && osd_prov->ops && osd_prov->ops->get) { - vf = osd_prov->ops->get(osd_prov->op_arg); - if (vf) { - vf->source_type = VFRAME_SOURCE_TYPE_OSD; - vsync_toggle_frame(vf); - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info - ("[video4osd] toggle osd_vframe {%d,%d}\n", - vf->width, vf->height); - } - goto SET_FILTER; - } +#ifdef VIDEO_PIP + if (pipbuf_to_put) { + pip_vf_put(pipbuf_to_put); + pipbuf_to_put = NULL; } +#endif +#endif if ((!cur_dispbuf) || (cur_dispbuf == &vf_local)) { @@ -5509,7 +6209,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } vsync_toggle_frame(cur_dispbuf); } else - video_property_changed = false; + video_property_changed = 0; } else { goto SET_FILTER; } @@ -5782,6 +6482,21 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) #endif SET_FILTER: +#ifdef VIDEO_PIP + vf = pip_vf_peek(); + /* setting video display property in underflow mode */ + if ((!vf) && cur_pipbuf && (pip_property_changed)) + pip_toggle_frame(cur_pipbuf); + if (vf) { + vf = pip_vf_get(); + if (vf) { + if (!vf->frame_dirty) + pip_toggle_frame(vf); + else + pip_vf_put(vf); + } + } +#endif #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) amvecm_on_vs( (cur_dispbuf != &vf_local) @@ -5918,183 +6633,260 @@ SET_FILTER: last_el_status = 0; } } - { -#if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { - if (cur_dispbuf->type & VIDTYPE_COMPRESS) { - /*SET_VCBUS_REG_MASK(VIU_MISC_CTRL0,*/ - /*VIU_MISC_AFBC_VD1);*/ - VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 + - cur_dev->viu_off, 1, 20, 1); - } else { - /*CLEAR_VCBUS_REG_MASK(VIU_MISC_CTRL0,*/ - /*VIU_MISC_AFBC_VD1);*/ - VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 + - cur_dev->viu_off, 0, 20, 1); - } - } + + if (cur_frame_par && + cur_frame_par->hscale_skip_count) { + VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ +#ifdef VIDEO_PIP + if (!cur_pipbuf) #endif - - if (platform_type == 1) { - if (cur_frame_par && cur_frame_par->hscale_skip_count) { - VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL + - cur_dev->viu_off, 1, 20, 1); - /* HFORMATTER_EN */ - VSYNC_WR_MPEG_REG_BITS(VIU_VD2_FMT_CTRL + - cur_dev->viu_off, 1, 20, 1); - /* HFORMATTER_EN */ - } - if (process_3d_type & MODE_3D_OUT_FA_MASK) { - if (toggle_3d_fa_frame == OUT_FA_A_FRAME) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - } else if (OUT_FA_B_FRAME == - toggle_3d_fa_frame) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } else if (toggle_3d_fa_frame == - OUT_FA_BANK_FRAME) { - /* output a banking frame */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 0, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 0, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - } - } - if ((process_3d_type & MODE_3D_OUT_TB) - || (process_3d_type & MODE_3D_OUT_LR)) { - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode & - VPP_PIC1_FIRST)) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - } -/* - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,15,1);//VPP_VD2_PREBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,6,1);//PREBLEND enable must be set! - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0x1ff, - *VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set - */ - } - -/* - *else{ - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0,15,1);//VPP_VD2_PREBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0,6,1);//PREBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set - *} - */ + VSYNC_WR_MPEG_REG_BITS(VIU_VD2_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ } - /* vertical phase */ - vphase = - &cur_frame_par->VPP_vf_ini_phase_ + if (process_3d_type & MODE_3D_OUT_FA_MASK) { + if (toggle_3d_fa_frame == OUT_FA_A_FRAME) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + } else if (OUT_FA_B_FRAME == + toggle_3d_fa_frame) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else if (toggle_3d_fa_frame == + OUT_FA_BANK_FRAME) { + /* output a banking frame */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 0, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 0, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + } + } + if ((process_3d_type & MODE_3D_OUT_TB) + || (process_3d_type & MODE_3D_OUT_LR)) { + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode & + VPP_PIC1_FIRST)) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + } + } + /* vertical phase */ + vphase = &cur_frame_par->VPP_vf_ini_phase_ [vpp_phase_table[vin_type] [vout_type]]; - VSYNC_WR_MPEG_REG(VPP_VSC_INI_PHASE + cur_dev->vpp_off, - ((u32) (vphase->phase) << 8)); + VSYNC_WR_MPEG_REG( + VPP_VSC_INI_PHASE + cur_dev->vpp_off, + ((u32) (vphase->phase) << 8)); - if (vphase->repeat_skip >= 0) { - /* skip lines */ - VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + if (vphase->repeat_skip >= 0) { + /* skip lines */ + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + cur_dev->vpp_off, skip_tab[vphase->repeat_skip], VPP_PHASECTL_INIRCVNUMT_BIT, VPP_PHASECTL_INIRCVNUM_WID + VPP_PHASECTL_INIRPTNUM_WID); - - } else { - /* repeat first line */ - VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + } else { + /* repeat first line */ + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + cur_dev->vpp_off, 4, VPP_PHASECTL_INIRCVNUMT_BIT, VPP_PHASECTL_INIRCVNUM_WID); - VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + cur_dev->vpp_off, 1 - vphase->repeat_skip, VPP_PHASECTL_INIRPTNUMT_BIT, VPP_PHASECTL_INIRPTNUM_WID); - } - if (platform_type == 1) { - if (force_3d_scaler == 3 && - cur_frame_par && - cur_frame_par->vpp_3d_scale) { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 3, - VPP_PHASECTL_DOUBLELINE_BIT, 2); - } else if (force_3d_scaler == 1 && - cur_frame_par && - cur_frame_par->vpp_3d_scale) { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 1, - VPP_PHASECTL_DOUBLELINE_BIT, - VPP_PHASECTL_DOUBLELINE_WID); - } else if (force_3d_scaler == 2 && - cur_frame_par && - cur_frame_par->vpp_3d_scale) { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 2, - VPP_PHASECTL_DOUBLELINE_BIT, 2); - } else { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 0, - VPP_PHASECTL_DOUBLELINE_BIT, 2); - } - } + } + if (force_3d_scaler == 3 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 3, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } else if (force_3d_scaler == 1 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 1, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); + } else if (force_3d_scaler == 2 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 2, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 0, + VPP_PHASECTL_DOUBLELINE_BIT, 2); } } +#ifdef VIDEO_PIP + if (pip_frame_ready_to_set) + curpip_frame_par = nextpip_frame_par; + + if (cur_pipbuf) { + int need_afbc = (cur_pipbuf->type & VIDTYPE_COMPRESS); + int afbc_need_reset = + video2_enabled && + need_afbc && + (!(READ_VCBUS_REG(VD2_AFBC_ENABLE) & 0x100)); + /*video on && afbc is off && is compress frame.*/ + if (pip_frame_ready_to_set || afbc_need_reset) + pip_set_dcu(curpip_frame_par, cur_pipbuf); + + if (cur_pipbuf && curpip_frame_par) { + if (curpip_frame_par->hscale_skip_count) { + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ + } + proc_vd2_vsc_phase_per_vsync( + curpip_frame_par, cur_pipbuf, vout_type); + } + } + + if (pip_frame_ready_to_set) { +#if 0 + u32 h_size, v_size; + + if (pip_start_x_lines < pip_end_x_lines) + h_size = pip_end_x_lines - pip_start_x_lines + 1; + else + h_size = ori2_end_x_lines - ori2_start_x_lines + 1; + + if (pip_start_y_lines < pip_end_y_lines) + v_size = pip_end_y_lines - pip_start_y_lines + 1; + else + v_size = ori2_end_y_lines - ori2_start_y_lines + 1; + + zoom2_start_x_lines = ori2_start_x_lines; + zoom2_end_x_lines = ori2_end_x_lines; + zoom2_start_y_lines = ori2_start_y_lines; + zoom2_end_y_lines = ori2_end_y_lines; + + if (h_size < (zoom2_end_x_lines - zoom2_start_x_lines + 1)) + zoom2_end_x_lines = zoom2_start_x_lines + h_size - 1; + else if (h_size > (zoom2_end_x_lines - zoom2_start_x_lines + 1)) + h_size = zoom2_end_x_lines - zoom2_start_x_lines + 1; + + if (v_size < (zoom2_end_y_lines - zoom2_start_y_lines + 1)) + zoom2_end_y_lines = zoom2_start_y_lines + v_size - 1; + else if (v_size > (zoom2_end_y_lines - zoom2_start_y_lines + 1)) + v_size = (zoom2_end_y_lines - zoom2_start_y_lines + 1); + + if (vinfo) { + if (pip_start_x_lines + h_size > vinfo->width) { + h_size = vinfo->width - pip_start_x_lines; + zoom2_end_x_lines = + zoom2_start_x_lines + h_size - 1; + } + if (pip_start_y_lines + v_size > vinfo->height) { + v_size = vinfo->height - pip_start_y_lines; + zoom2_end_y_lines = + zoom2_start_y_lines + v_size - 1; + } + } +#endif + struct scaler_setting_s local_pps; + struct blend_setting_s local_blend; + struct vpp_frame_par_s *par = curpip_frame_par; + + if (cur_pipbuf->type & VIDTYPE_INTERLACE) { + if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) { + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> 1; + zoom2_end_y_lines = + ((par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } else { + zoom2_start_y_lines = + par->VPP_vd_start_lines_; + zoom2_end_y_lines = + par->VPP_vd_end_lines_; + } + } else { + if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) { + zoom2_start_y_lines = + par->VPP_vd_start_lines_; + zoom2_end_y_lines = + par->VPP_vd_end_lines_; + } else { + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> 1; + zoom2_end_y_lines = + ((par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } + } + zoom2_start_x_lines = + par->VPP_hd_start_lines_; + zoom2_end_x_lines = + par->VPP_hd_end_lines_; + config_vd_pps( + 1, par, &local_pps, vinfo); + config_vd_blend( + 1, par, cur_pipbuf, + (legacy_vpp ? 0x1ff : 0x100), &local_blend); + vd2_scaler_setting(&local_pps); + vd2_zoom_display_horz( + cur_pipbuf, + par->hscale_skip_count); + vd2_zoom_display_vert( + cur_pipbuf, + par->vscale_skip_count); + vd2_vpp_blend_setting(&local_blend); + pip_frame_ready_to_set = 0; + } +#endif if (((frame_par_ready_to_set) || (frame_par_force_to_set)) && (cur_frame_par)) { @@ -6156,8 +6948,10 @@ SET_FILTER: zoom2_end_y_lines = ori2_end_y_lines; correct_vd2_mif_size_for_DV( cur_frame_par, cur_dispbuf); - vd2_zoom_display_horz(cur_dispbuf2, 0); - vd2_zoom_display_vert(cur_dispbuf2); + vd2_zoom_display_horz(cur_dispbuf2, + cur_frame_par->hscale_skip_count); + vd2_zoom_display_vert(cur_dispbuf2, + cur_frame_par->vscale_skip_count); } } /*vpp input size setting*/ @@ -6437,6 +7231,17 @@ SET_FILTER: (VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND)) vpp_misc_set |= VPP_POSTBLEND_EN; } + +#ifdef VIDEO_PIP + if (cur_pipbuf && (video2_enabled == 1) + && ((vpp_misc_save & VPP_VD2_POSTBLEND) == 0) + && (video2_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { + vpp_misc_set |= + VPP_VD2_POSTBLEND | + VPP_POSTBLEND_EN; + } +#endif + if ((video_enabled == 1) && ((vpp_misc_save & VPP_VD1_POSTBLEND) == 0) && (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { vpp_misc_set |= @@ -6457,7 +7262,7 @@ SET_FILTER: VPP_VSC_START_PHASE_STEP + cur_dev->vpp_off); if ((vpp_filter->vpp_hf_start_phase_step != h_phase_step) || (vpp_filter->vpp_vsc_start_phase_step != v_phase_step)) { - video_property_changed = true; + video_property_changed = 1; /*pr_info("frame info register rdma write fail!\n");*/ } } @@ -6535,7 +7340,13 @@ SET_FILTER: else vpp_misc_set |= VPP_VD2_PREBLEND | VPP_PREBLEND_EN; - +#ifdef VIDEO_PIP + if (cur_pipbuf) { + vpp_misc_set &= + ~(VPP_PREBLEND_EN | VPP_VD2_PREBLEND); + vpp_misc_set |= VPP_VD2_POSTBLEND; + } +#endif /* g12a has no alpha overflow check in hardware */ if (!legacy_vpp) vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT); @@ -6548,7 +7359,8 @@ SET_FILTER: pr_info("VsyncEnableVideoLayer2\n"); } else if (video2_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { vpp_misc_set &= ~(VPP_VD2_PREBLEND | - VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); + VPP_VD2_POSTBLEND | VPP_PREBLEND_EN + | (0x1ff << VPP_VD2_ALPHA_BIT)); video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; video_onoff_time = jiffies_to_msecs(jiffies); @@ -6566,6 +7378,11 @@ SET_FILTER: VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | VPP_PREBLEND_EN); +#ifdef VIDEO_PIP + /* should keep video2 display */ + if (cur_pipbuf && video2_enabled) + vpp_misc_set |= VPP_VD2_POSTBLEND; +#endif } else { video_enabled = video_status_saved; } @@ -6573,11 +7390,24 @@ SET_FILTER: if (!video_enabled && (vpp_misc_set & VPP_VD1_POSTBLEND)) vpp_misc_set &= ~(VPP_VD1_PREBLEND | - VPP_VD2_PREBLEND | - VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | VPP_PREBLEND_EN); +#ifdef VIDEO_PIP + if (pip_global_output == 0) { + video2_enabled = 0; + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND); + } else { + video2_enabled = video2_status_saved; + } + + if (!video2_enabled && + (vpp_misc_set & VPP_VD2_POSTBLEND)) + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND); +#endif + if (!legacy_vpp) { u32 set_value = 0; @@ -6591,6 +7421,14 @@ SET_FILTER: VPP_PREBLEND_EN | VPP_POSTBLEND_EN | 0xf); + + /* if vd2 is bottom layer, need remove alpha for vd2 */ + if (((vpp_misc_set & VPP_VD1_POSTBLEND) == 0) + && (vpp_misc_set & VPP_VD2_POSTBLEND)) { + vpp_misc_set &= ~(0x1ff << VPP_VD2_ALPHA_BIT); + vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT); + } + vpp_misc_save &= ((1 << 29) | VPP_CM_ENABLE | (0x1ff << VPP_VD2_ALPHA_BIT) | @@ -6617,7 +7455,7 @@ SET_FILTER: if (vpp_misc_set & VPP_VD2_POSTBLEND) set_value = ((1 << 20) | - (1 << 16) | /* post bld premult*/ + (0 << 16) | /* post bld premult*/ (2 << 8)); /* post src */ else if (vpp_misc_set & VPP_VD2_PREBLEND) set_value = @@ -6626,6 +7464,7 @@ SET_FILTER: VSYNC_WR_MPEG_REG( VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, set_value); + set_value = vpp_misc_set; set_value &= ((1 << 29) | VPP_CM_ENABLE | @@ -6652,6 +7491,37 @@ SET_FILTER: /*vpp_misc_set maybe have same,but need off.*/ /* if vd1 off, disable vd2 also */ +#ifdef VIDEO_PIP + if (video2_off_req && cur_pipbuf) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + if (cur_pipbuf && (cur_pipbuf == &local_pip)) + cur_pipbuf = NULL; + } else if (!cur_pipbuf && + (video2_off_req || video1_off_req)) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + last_el_w = 0; + last_el_status = 0; + if (cur_dispbuf2 && (cur_dispbuf2 == &vf_local2)) + cur_dispbuf2 = NULL; + need_disable_vd2 = false; + } +#else if (video2_off_req || video1_off_req) { if ((debug_flag & DEBUG_FLAG_BLACKOUT) && video2_off_req) @@ -6669,6 +7539,8 @@ SET_FILTER: cur_dispbuf2 = NULL; need_disable_vd2 = false; } +#endif + if (video1_off_req) { /* * video layer off, swith off afbc, @@ -6699,6 +7571,9 @@ SET_FILTER: } #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA cur_rdma_buf = cur_dispbuf; +#ifdef VIDEO_PIP + pip_rdma_buf = cur_pipbuf; +#endif /* vsync_rdma_config(); */ vsync_rdma_process(); if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { @@ -6842,7 +7717,9 @@ int get_current_vscale_skip_count(struct vframe_s *vf) int ret = 0; static struct vpp_frame_par_s frame_par; - vpp_set_filters(process_3d_type, wide_setting, vf, &frame_par, vinfo, + vpp_set_filters( + &glayer_info[0], + vf, &frame_par, vinfo, (is_dolby_vision_on() && is_dolby_vision_stb_mode())); ret = frame_par.vscale_skip_count; @@ -6919,9 +7796,30 @@ static void video_vf_unreg_provider(void) vsync_freerun = 0; vsync_pts_align = 0; vsync_pts_aligned = false; - video_prot.video_started = 0; + +#ifdef VIDEO_PIP + if (pip_loop) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + cur_pipbuf->video_angle = 0; + } + pip_frame_count = 0; + } +#endif spin_unlock_irqrestore(&lock, flags); +#ifdef VIDEO_PIP + if (pip_loop) { + disable_videopip = VIDEO_DISABLE_FORNEXT; + DisableVideoLayer2(); + } +#endif + if (blackout | force_blackout) { safe_disble_videolayer(); try_free_keep_video(1); @@ -7031,10 +7929,16 @@ static int get_display_info(void *data) s32 w, h, x, y; struct vdisplay_info_s *info_para = (struct vdisplay_info_s *)data; const struct vinfo_s *info = get_current_vinfo(); + struct disp_info_s *layer = &glayer_info[0]; if ((!cur_frame_par) || (!info)) return -1; - vpp_get_video_layer_position(&x, &y, &w, &h); + + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; + if ((w == 0) || (w > info->width)) w = info->width; if ((h == 0) || (h > info->height)) @@ -7150,25 +8054,68 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) #endif } else if (type == VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO) { get_display_info(data); - } + } else if (type == VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED) + video_property_changed = 1; return 0; } -static int video4osd_receiver_event_fun(int type, void *data, - void *private_data) +#ifdef VIDEO_PIP +static void pip_vf_unreg_provider(void) { - if (type == VFRAME_EVENT_PROVIDER_UNREG) { - osd_prov = NULL; - if (debug_flag & DEBUG_FLAG_BLACKOUT) - pr_info("[video4osd] clear osd_prov\n"); - } else if (type == VFRAME_EVENT_PROVIDER_REG) { - osd_prov = vf_get_provider(RECEIVER4OSD_NAME); + ulong flags; - if (debug_flag & DEBUG_FLAG_BLACKOUT) - pr_info("[video4osd] set osd_prov\n"); + /* atomic_set(&video_unreg_flag, 1); */ + while (atomic_read(&video_inirq_flag) > 0) + schedule(); + spin_lock_irqsave(&lock, flags); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + cur_pipbuf->video_angle = 0; } + pip_frame_count = 0; + spin_unlock_irqrestore(&lock, flags); + + disable_videopip = VIDEO_DISABLE_FORNEXT; + DisableVideoLayer2(); +} + +static void pip_vf_light_unreg_provider(void) +{ + ulong flags; + + spin_lock_irqsave(&lock, flags); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + } + spin_unlock_irqrestore(&lock, flags); +} + +static int pip_receiver_event_fun( + int type, void *data, void *private_data) +{ + if (type == VFRAME_EVENT_PROVIDER_UNREG) + pip_vf_unreg_provider(); + else if (type == VFRAME_EVENT_PROVIDER_RESET) + pip_vf_light_unreg_provider(); + else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) + pip_vf_light_unreg_provider(); + else if (type == VFRAME_EVENT_PROVIDER_REG) + pip_vf_light_unreg_provider(); return 0; } +#endif unsigned int get_post_canvas(void) { @@ -7218,33 +8165,49 @@ int _video_set_disable(u32 val) if ((disable_video == VIDEO_DISABLE_FORNEXT) && cur_dispbuf && (cur_dispbuf != &vf_local)) - video_property_changed = true; + video_property_changed = 1; try_free_keep_video(0); } else { if (cur_dispbuf && (cur_dispbuf != &vf_local)) { EnableVideoLayer(); - video_property_changed = true; + video_property_changed = 1; } } return 0; } -static void _set_video_crop(int *p) +static void _set_video_crop( + struct disp_info_s *layer, int *p) { int last_l, last_r, last_t, last_b; int new_l, new_r, new_t, new_b; - vpp_get_video_source_crop(&last_t, &last_l, &last_b, &last_r); - vpp_set_video_source_crop(p[0], p[1], p[2], p[3]); - vpp_get_video_source_crop(&new_t, &new_l, &new_b, &new_r); + if (!layer) + return; + + last_t = layer->crop_top; + last_l = layer->crop_left; + last_b = layer->crop_bottom; + last_r = layer->crop_right; + + new_t = layer->crop_top = p[0]; + new_l = layer->crop_left = p[1]; + new_b = layer->crop_bottom = p[2]; + new_r = layer->crop_right = p[3]; if ((new_t != last_t) || (new_l != last_l) - || (new_b != last_b) || (new_r != last_r)) { - video_property_changed = true; + || (new_b != last_b) || (new_r != last_r)) { + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif } } -static void _set_video_window(int *p) +static void _set_video_window( + struct disp_info_s *layer, int *p) { int w, h; int *parsed = p; @@ -7253,10 +8216,13 @@ static void _set_video_window(int *p) #ifdef TV_REVERSE int temp, temp1; const struct vinfo_s *info = get_current_vinfo(); +#endif - /* pr_info(KERN_DEBUG "%s: %u*/ - /*get vinfo(%d,%d).\n", __func__, __LINE__,*/ - /*info->width, info->height); */ + if (!layer) + return; + +#ifdef TV_REVERSE + /* FIXME: use layer info */ if (reverse) { temp = parsed[0]; temp1 = parsed[1]; @@ -7266,7 +8232,12 @@ static void _set_video_window(int *p) parsed[3] = info->height - temp1 - 1; } #endif - vpp_get_video_layer_position(&last_x, &last_y, &last_w, &last_h); + + last_x = layer->layer_left; + last_y = layer->layer_top; + last_w = layer->layer_width; + last_h = layer->layer_height; + if (parsed[0] < 0 && parsed[2] < 2) { parsed[2] = 2; parsed[0] = 0; @@ -7296,19 +8267,31 @@ static void _set_video_window(int *p) } else #endif { - if ((w == 1) && (h == 1)) { - w = h = 0; - vpp_set_video_layer_position(parsed[0], parsed[1], 0, - 0); - } else if ((w > 0) && (h > 0)) { - vpp_set_video_layer_position(parsed[0], parsed[1], w, - h); + if ((w > 0) && (h > 0)) { + if ((w == 1) && (h == 1)) { + w = 0; + h = 0; + } + layer->layer_left = parsed[0]; + layer->layer_top = parsed[1]; + layer->layer_width = w; + layer->layer_height = h; } } - vpp_get_video_layer_position(&new_x, &new_y, &new_w, &new_h); + + new_x = layer->layer_left; + new_y = layer->layer_top; + new_w = layer->layer_width; + new_h = layer->layer_height; + if ((last_x != new_x) || (last_y != new_y) - || (last_w != new_w) || (last_h != new_h)) { - video_property_changed = true; + || (last_w != new_w) || (last_h != new_h)) { + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif } } #if ENABLE_UPDATE_HDR_FROM_USER @@ -7433,6 +8416,47 @@ static void set_omx_pts(u32 *p) mutex_unlock(&omx_mutex); } +static int alloc_layer(u32 layer_id) +{ + int ret = -EINVAL; + + if (layer_id == 0) { + if (layer_cap & LAYER0_BUSY) { + ret = -EBUSY; + } else if (layer_cap & LAYER0_AVAIL) { + ret = 0; + layer_cap |= LAYER0_BUSY; + } + } else if (layer_id == 1) { + if (layer_cap & LAYER1_BUSY) { + ret = -EBUSY; + } else if (layer_cap & LAYER1_AVAIL) { + ret = 0; + layer_cap |= LAYER1_BUSY; + } + } + return ret; +} + +static int free_layer(u32 layer_id) +{ + int ret = -EINVAL; + + if (layer_id == 0) { + if ((layer_cap & LAYER0_BUSY) + && (layer_cap & LAYER0_AVAIL)) { + ret = 0; + layer_cap &= ~LAYER0_BUSY; + } + } else if (layer_id == 1) { + if ((layer_cap & LAYER1_BUSY) + && (layer_cap & LAYER1_AVAIL)) { + ret = 0; + layer_cap &= ~LAYER1_BUSY; + } + } + return ret; +} /********************************************************* * /dev/amvideo APIs @@ -7440,29 +8464,25 @@ static void set_omx_pts(u32 *p) */ static int amvideo_open(struct inode *inode, struct file *file) { + file->private_data = NULL; return 0; } static int amvideo_poll_open(struct inode *inode, struct file *file) { + file->private_data = NULL; return 0; } static int amvideo_release(struct inode *inode, struct file *file) { - if (blackout | force_blackout) { - /* DisableVideoLayer();*/ - /*don't need it ,it have problem on pure music playing */ - } + file->private_data = NULL; return 0; } static int amvideo_poll_release(struct inode *inode, struct file *file) { - if (blackout | force_blackout) { - /* DisableVideoLayer();*/ - /*don't need it ,it have problem on pure music playing */ - } + file->private_data = NULL; return 0; } @@ -7470,6 +8490,30 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) { long ret = 0; void __user *argp = (void __user *)arg; + struct disp_info_s *layer = &glayer_info[0]; + u32 layer_id; + + switch (cmd) { + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_SET_PIP_ZORDER: + layer = &glayer_info[1]; + break; + default: + break; + } + + if (file->private_data) + layer = (struct disp_info_s *)file->private_data; switch (cmd) { case AMSTREAM_IOC_SET_HDR_INFO:{ @@ -7584,19 +8628,32 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: case AMSTREAM_IOC_GET_VIDEO_DISABLE: - put_user(disable_video, (u32 __user *)argp); + if (layer->layer_id == 0) + put_user(disable_video, (u32 __user *)argp); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + put_user(disable_videopip, (u32 __user *)argp); +#endif break; - case AMSTREAM_IOC_SET_VIDEO_DISABLE:{ - u32 val; + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEO_DISABLE: + { + u32 val; - if (copy_from_user(&val, argp, sizeof(u32)) == 0) - ret = _video_set_disable(val); - else - ret = -EFAULT; + if (copy_from_user(&val, argp, sizeof(u32)) == 0) { + if (layer->layer_id == 0) + ret = _video_set_disable(val); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + ret = _videopip_set_disable(val); +#endif + } else + ret = -EFAULT; + } break; - } case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT: put_user(enable_video_discontinue_report, (u32 __user *)argp); @@ -7606,10 +8663,12 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) enable_video_discontinue_report = (arg == 0) ? 0 : 1; break; - case AMSTREAM_IOC_GET_VIDEO_AXIS:{ + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEO_AXIS: + { int axis[4]; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER - if (video_scaler_mode) { + if (video_scaler_mode && (layer->layer_id == 0)) { axis[0] = content_left; axis[1] = content_top; axis[2] = content_w; @@ -7617,10 +8676,10 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } else #endif { - vpp_get_video_layer_position( - &axis[0], &axis[1], - &axis[2], - &axis[3]); + axis[0] = layer->layer_left; + axis[1] = layer->layer_top; + axis[2] = layer->layer_width; + axis[3] = layer->layer_height; } axis[2] = axis[0] + axis[2] - 1; @@ -7631,21 +8690,27 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; - case AMSTREAM_IOC_SET_VIDEO_AXIS:{ + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEO_AXIS: + { int axis[4]; if (copy_from_user(axis, argp, sizeof(axis)) == 0) - _set_video_window(axis); + _set_video_window(layer, axis); else ret = -EFAULT; } break; - case AMSTREAM_IOC_GET_VIDEO_CROP:{ + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_VIDEO_CROP: + { int crop[4]; { - vpp_get_video_source_crop(&crop[0], &crop[1], - &crop[2], &crop[3]); + crop[0] = layer->crop_top; + crop[1] = layer->crop_left; + crop[2] = layer->crop_bottom; + crop[3] = layer->crop_right; } if (copy_to_user(argp, &crop[0], sizeof(crop)) != 0) @@ -7653,30 +8718,40 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; - case AMSTREAM_IOC_SET_VIDEO_CROP:{ + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEO_CROP: + { int crop[4]; if (copy_from_user(crop, argp, sizeof(crop)) == 0) - _set_video_crop(crop); + _set_video_crop(layer, crop); else ret = -EFAULT; } break; + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: case AMSTREAM_IOC_GET_SCREEN_MODE: - if (copy_to_user(argp, &wide_setting, sizeof(u32)) != 0) + if (copy_to_user(argp, &layer->wide_mode, sizeof(u32)) != 0) ret = -EFAULT; break; - case AMSTREAM_IOC_SET_SCREEN_MODE:{ + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_SCREEN_MODE: + { u32 mode; if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { if (mode >= VIDEO_WIDEOPTION_MAX) ret = -EINVAL; - else if (mode != wide_setting) { - wide_setting = mode; - video_property_changed = true; + else if (mode != layer->wide_mode) { + layer->wide_mode = mode; + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif } } else ret = -EFAULT; @@ -7750,7 +8825,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) process_3d_type = type; if (mvc_flag) process_3d_type |= MODE_3D_MVC; - video_property_changed = true; + video_property_changed = 1; if ((process_3d_type & MODE_3D_FA) && cur_dispbuf && !cur_dispbuf->trans_fmt) @@ -7803,15 +8878,32 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) vsync_slow_factor = arg; break; + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: - if (arg != 0) - video_global_output = 1; - else - video_global_output = 0; + if (layer->layer_id == 0) { + if (arg != 0) + video_global_output = 1; + else + video_global_output = 0; + } +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) { + if (arg != 0) + pip_global_output = 1; + else + pip_global_output = 0; + } +#endif break; + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: - put_user(video_global_output, (u32 __user *)argp); + if (layer->layer_id == 0) + put_user(video_global_output, (u32 __user *)argp); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + put_user(pip_global_output, (u32 __user *)argp); +#endif break; case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: { @@ -7840,6 +8932,54 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) videopeek = true; nopostvideostart = true; break; + + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_GET_ZORDER: + break; + + case AMSTREAM_IOC_SET_PIP_ZORDER: + case AMSTREAM_IOC_SET_ZORDER: + break; + + case AMSTREAM_IOC_QUERY_LAYER: + mutex_lock(&video_layer_mutex); + put_user(layer_cap, (u32 __user *)argp); + mutex_unlock(&video_layer_mutex); + ret = 0; + break; + + case AMSTREAM_IOC_ALLOC_LAYER: + if (copy_from_user(&layer_id, argp, sizeof(u32)) == 0) { + if (layer_id >= MAX_VD_LAYERS) { + ret = -EINVAL; + } else { + mutex_lock(&video_layer_mutex); + if (file->private_data) { + ret = -EBUSY; + } else { + ret = alloc_layer(layer_id); + if (!ret) + file->private_data = + (void *)&glayer_info[layer_id]; + } + mutex_unlock(&video_layer_mutex); + } + } else + ret = -EFAULT; + break; + + case AMSTREAM_IOC_FREE_LAYER: + mutex_lock(&video_layer_mutex); + if (!file->private_data) { + ret = -EINVAL; + } else { + ret = free_layer(layer->layer_id); + if (!ret) + file->private_data = NULL; + } + mutex_unlock(&video_layer_mutex); + break; + default: return -EINVAL; } @@ -7881,6 +9021,23 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR: case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_SET_PIP_ZORDER: + case AMSTREAM_IOC_GET_ZORDER: + case AMSTREAM_IOC_SET_ZORDER: + case AMSTREAM_IOC_QUERY_LAYER: + case AMSTREAM_IOC_ALLOC_LAYER: + case AMSTREAM_IOC_FREE_LAYER: arg = (unsigned long) compat_ptr(arg); case AMSTREAM_IOC_TRICKMODE: case AMSTREAM_IOC_VPAUSE: @@ -8002,12 +9159,13 @@ static int parse_para(const char *para, int para_num, int *result) return count; } -static void set_video_crop(const char *para) +static void set_video_crop( + struct disp_info_s *layer, const char *para) { int parsed[4]; if (likely(parse_para(para, 4, parsed) == 4)) - _set_video_crop(parsed); + _set_video_crop(layer, parsed); amlog_mask(LOG_MASK_SYSFS, "video crop=>x0:%d,y0:%d,x1:%d,y1:%d\n ", parsed[0], parsed[1], parsed[2], parsed[3]); @@ -8016,19 +9174,23 @@ static void set_video_crop(const char *para) static void set_video_speed_check(const char *para) { int parsed[2]; + struct disp_info_s *layer = &glayer_info[0]; - if (likely(parse_para(para, 2, parsed) == 2)) - vpp_set_video_speed_check(parsed[0], parsed[1]); + if (likely(parse_para(para, 2, parsed) == 2)) { + layer->speed_check_height = parsed[0]; + layer->speed_check_width = parsed[1]; + } amlog_mask(LOG_MASK_SYSFS, "video speed_check=>h:%d,w:%d\n ", parsed[0], parsed[1]); } -static void set_video_window(const char *para) +static void set_video_window( + struct disp_info_s *layer, const char *para) { int parsed[4]; if (likely(parse_para(para, 4, parsed) == 4)) - _set_video_window(parsed); + _set_video_window(layer, parsed); amlog_mask(LOG_MASK_SYSFS, "video=>x0:%d,y0:%d,x1:%d,y1:%d\n ", parsed[0], parsed[1], parsed[2], parsed[3]); @@ -8041,13 +9203,14 @@ static ssize_t video_3d_scale_store(struct class *cla, #ifdef TV_3D_FUNCTION_OPEN u32 enable; int r; + struct disp_info_s *layer = &glayer_info[0]; r = kstrtouint(buf, 0, &enable); if (r < 0) return -EINVAL; - vpp_set_3d_scale(enable); - video_property_changed = true; + layer->vpp_3d_scale = enable ? true : false; + video_property_changed = 1; amlog_mask(LOG_MASK_SYSFS, "%s:%s 3d scale.\n", __func__, enable ? "enable" : "disable"); #endif @@ -8070,7 +9233,7 @@ static ssize_t video_sr_store(struct class *cla, if (likely(parse_para(buf, 1, parsed) == 1)) { if (super_scaler != (parsed[0] & 0x1)) { super_scaler = parsed[0] & 0x1; - video_property_changed = true; + video_property_changed = 1; } } mutex_unlock(&video_module_mutex); @@ -8082,8 +9245,12 @@ static ssize_t video_crop_show(struct class *cla, struct class_attribute *attr, char *buf) { u32 t, l, b, r; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_video_source_crop(&t, &l, &b, &r); + t = layer->crop_top; + l = layer->crop_left; + b = layer->crop_bottom; + r = layer->crop_right; return snprintf(buf, 40, "%d %d %d %d\n", t, l, b, r); } @@ -8091,9 +9258,11 @@ static ssize_t video_crop_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { + struct disp_info_s *layer = &glayer_info[0]; + mutex_lock(&video_module_mutex); - set_video_crop(buf); + set_video_crop(layer, buf); mutex_unlock(&video_module_mutex); @@ -8226,6 +9395,8 @@ static ssize_t video_axis_show(struct class *cla, char *buf) { int x, y, w, h; + struct disp_info_s *layer = &glayer_info[0]; + #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER if (video_scaler_mode) { x = content_left; @@ -8235,7 +9406,10 @@ static ssize_t video_axis_show(struct class *cla, } else #endif { - vpp_get_video_layer_position(&x, &y, &w, &h); + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; } return snprintf(buf, 40, "%d %d %d %d\n", x, y, x + w - 1, y + h - 1); } @@ -8244,9 +9418,11 @@ static ssize_t video_axis_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { + struct disp_info_s *layer = &glayer_info[0]; + mutex_lock(&video_module_mutex); - set_video_window(buf); + set_video_window(layer, buf); mutex_unlock(&video_module_mutex); @@ -8257,8 +9433,10 @@ static ssize_t video_global_offset_show(struct class *cla, struct class_attribute *attr, char *buf) { int x, y; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_global_offset(&x, &y); + x = layer->global_offset_x; + y = layer->global_offset_y; return snprintf(buf, 40, "%d %d\n", x, y); } @@ -8268,12 +9446,14 @@ static ssize_t video_global_offset_store(struct class *cla, const char *buf, size_t count) { int parsed[2]; + struct disp_info_s *layer = &glayer_info[0]; mutex_lock(&video_module_mutex); if (likely(parse_para(buf, 2, parsed) == 2)) { - vpp_set_global_offset(parsed[0], parsed[1]); - video_property_changed = true; + layer->global_offset_x = parsed[0]; + layer->global_offset_y = parsed[1]; + video_property_changed = 1; amlog_mask(LOG_MASK_SYSFS, "video_offset=>x0:%d,y0:%d\n ", @@ -8289,7 +9469,10 @@ static ssize_t video_zoom_show(struct class *cla, struct class_attribute *attr, char *buf) { - u32 r = vpp_get_zoom_ratio(); + u32 r; + struct disp_info_s *layer = &glayer_info[0]; + + r = layer->zoom_ratio; return snprintf(buf, 40, "%d\n", r); } @@ -8300,14 +9483,15 @@ static ssize_t video_zoom_store(struct class *cla, { unsigned long r; int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; ret = kstrtoul(buf, 0, (unsigned long *)&r); if (ret < 0) return -EINVAL; - if ((r <= MAX_ZOOM_RATIO) && (r != vpp_get_zoom_ratio())) { - vpp_set_zoom_ratio(r); - video_property_changed = true; + if ((r <= MAX_ZOOM_RATIO) && (r != layer->zoom_ratio)) { + layer->zoom_ratio = r; + video_property_changed = 1; } return count; @@ -8316,6 +9500,7 @@ static ssize_t video_zoom_store(struct class *cla, static ssize_t video_screen_mode_show(struct class *cla, struct class_attribute *attr, char *buf) { + struct disp_info_s *layer = &glayer_info[0]; static const char * const wide_str[] = { "normal", "full stretch", "4-3", "16-9", "non-linear", "normal-noscaleup", @@ -8324,9 +9509,10 @@ static ssize_t video_screen_mode_show(struct class *cla, "16-9 combined", "Custom AR", "AFD" }; - if (wide_setting < ARRAY_SIZE(wide_str)) { - return sprintf(buf, "%d:%s\n", wide_setting, - wide_str[wide_setting]); + if (layer->wide_mode < ARRAY_SIZE(wide_str)) { + return sprintf(buf, "%d:%s\n", + layer->wide_mode, + wide_str[layer->wide_mode]); } else return 0; } @@ -8337,14 +9523,16 @@ static ssize_t video_screen_mode_store(struct class *cla, { unsigned long mode; int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; ret = kstrtoul(buf, 0, (unsigned long *)&mode); if (ret < 0) return -EINVAL; - if ((mode < VIDEO_WIDEOPTION_MAX) && (mode != wide_setting)) { - wide_setting = mode; - video_property_changed = true; + if ((mode < VIDEO_WIDEOPTION_MAX) + && (mode != layer->wide_mode)) { + layer->wide_mode = mode; + video_property_changed = 1; } return count; @@ -8913,7 +10101,12 @@ static ssize_t video_nonlinear_factor_show(struct class *cla, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", vpp_get_nonlinear_factor()); + u32 factor; + struct disp_info_s *layer = &glayer_info[0]; + + factor = vpp_get_nonlinear_factor(layer); + + return sprintf(buf, "%d\n", factor); } static ssize_t video_nonlinear_factor_store(struct class *cla, @@ -8922,13 +10115,14 @@ static ssize_t video_nonlinear_factor_store(struct class *cla, { int r; u32 factor; + struct disp_info_s *layer = &glayer_info[0]; r = kstrtoint(buf, 0, &factor); if (r < 0) return -EINVAL; - if (vpp_set_nonlinear_factor(factor) == 0) - video_property_changed = true; + if (vpp_set_nonlinear_factor(layer, factor) == 0) + video_property_changed = 1; return count; } @@ -9028,8 +10222,10 @@ static ssize_t video_speed_check_show(struct class *cla, struct class_attribute *attr, char *buf) { u32 h, w; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_video_speed_check(&h, &w); + h = layer->speed_check_height; + w = layer->speed_check_width; return snprintf(buf, 40, "%d %d\n", h, w); } @@ -9038,9 +10234,7 @@ static ssize_t video_speed_check_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { - set_video_speed_check(buf); - return strnlen(buf, count); } @@ -9061,7 +10255,7 @@ static ssize_t threedim_mode_store(struct class *cla, process_3d_type = type; if (mvc_flag) process_3d_type |= MODE_3D_MVC; - video_property_changed = true; + video_property_changed = 1; if ((process_3d_type & MODE_3D_FA) && cur_dispbuf && !cur_dispbuf->trans_fmt) /*notify di 3d mode is frame alternative mode,1*/ @@ -9557,11 +10751,11 @@ static ssize_t video_layer1_state_show(struct class *cla, void set_video_angle(u32 s_value) { - if ((s_value <= 3) && (video_angle != s_value)) { - video_angle = s_value; - video_prot.angle_changed = 1; - video_prot.video_started = 1; - pr_info("video_prot angle:%d\n", video_angle); + struct disp_info_s *layer = &glayer_info[0]; + + if ((s_value <= 3) && (layer->angle != s_value)) { + layer->angle = s_value; + pr_info("video angle:%d\n", layer->angle); } } EXPORT_SYMBOL(set_video_angle); @@ -9569,7 +10763,9 @@ EXPORT_SYMBOL(set_video_angle); static ssize_t video_angle_show(struct class *cla, struct class_attribute *attr, char *buf) { - return snprintf(buf, 40, "%d\n", video_angle); + struct disp_info_s *layer = &glayer_info[0]; + + return snprintf(buf, 40, "%d\n", layer->angle); } static ssize_t video_angle_store(struct class *cla, @@ -9741,6 +10937,323 @@ static ssize_t video_inuse_store(struct class *class, return count; } +#ifdef VIDEO_PIP +static int _videopip_set_disable(u32 val) +{ + if (val > VIDEO_DISABLE_FORNEXT) + return -EINVAL; + + disable_videopip = val; + + if (disable_videopip != VIDEO_DISABLE_NONE) { + DisableVideoLayer2(); + + if ((disable_videopip == VIDEO_DISABLE_FORNEXT) + && cur_pipbuf && (cur_pipbuf != &local_pip)) + pip_property_changed = 1; + } else { + if (cur_pipbuf && (cur_pipbuf != &local_pip)) + EnableVideoLayer2(); + } + + return 0; +} + +static ssize_t videopip_axis_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + int x0, y0, x1, y1; + struct disp_info_s *layer = &glayer_info[1]; + + x0 = layer->layer_left; + y0 = layer->layer_top; + x1 = layer->layer_width + x0 - 1; + y1 = layer->layer_height + y0 - 1; + return snprintf(buf, 40, "%d %d %d %d\n", x0, y0, x1, y1); +} + +static ssize_t videopip_axis_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[1]; + + mutex_lock(&video_module_mutex); + + set_video_window(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t videopip_crop_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 t, l, b, r; + struct disp_info_s *layer = &glayer_info[1]; + + t = layer->crop_top; + l = layer->crop_left; + b = layer->crop_bottom; + r = layer->crop_right; + return snprintf(buf, 40, "%d %d %d %d\n", t, l, b, r); +} + +static ssize_t videopip_crop_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[1]; + + mutex_lock(&video_module_mutex); + + set_video_crop(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t videopip_disable_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", disable_videopip); +} + +static ssize_t videopip_disable_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + + int r; + int val; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%s)\n", __func__, buf); + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + if (_videopip_set_disable(val) < 0) + return -EINVAL; + + return count; +} + +static ssize_t videopip_screen_mode_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[1]; + static const char * const wide_str[] = { + "normal", "full stretch", "4-3", "16-9", "non-linear", + "normal-noscaleup", + "4-3 ignore", "4-3 letter box", "4-3 pan scan", "4-3 combined", + "16-9 ignore", "16-9 letter box", "16-9 pan scan", + "16-9 combined", "Custom AR", "AFD" + }; + + if (layer->wide_mode < ARRAY_SIZE(wide_str)) { + return sprintf(buf, "%d:%s\n", + layer->wide_mode, + wide_str[layer->wide_mode]); + } else + return 0; +} + +static ssize_t videopip_screen_mode_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned long mode; + int ret = 0; + struct disp_info_s *layer = &glayer_info[1]; + + ret = kstrtoul(buf, 0, (unsigned long *)&mode); + if (ret < 0) + return -EINVAL; + + if ((mode < VIDEO_WIDEOPTION_MAX) + && (mode != layer->wide_mode)) { + layer->wide_mode = mode; + pip_property_changed = 1; + } + return count; +} + +static ssize_t videopip_loop_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", pip_loop); +} + +static ssize_t videopip_loop_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + pip_loop = val; + return count; +} + +static ssize_t videopip_global_output_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", pip_global_output); +} + +static ssize_t videopip_global_output_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &pip_global_output); + if (r < 0) + return -EINVAL; + + pr_info("%s(%d)\n", __func__, pip_global_output); + + return count; +} + +static ssize_t videopip_state_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + ssize_t len = 0; + struct vppfilter_mode_s *vpp_filter = NULL; + + if (!curpip_frame_par) + return len; + vpp_filter = &curpip_frame_par->vpp_filter; + len += sprintf(buf + len, + "zoom2_start_x_lines:%u.zoom2_end_x_lines:%u.\n", + zoom2_start_x_lines, zoom2_end_x_lines); + len += sprintf(buf + len, + "zoom2_start_y_lines:%u.zoom2_end_y_lines:%u.\n", + zoom2_start_y_lines, zoom2_end_y_lines); + len += sprintf(buf + len, "frame parameters: pic_in_height %u.\n", + curpip_frame_par->VPP_pic_in_height_); + len += sprintf(buf + len, + "frame parameters: VPP_line_in_length_ %u.\n", + curpip_frame_par->VPP_line_in_length_); + len += sprintf(buf + len, "vscale_skip_count %u.\n", + curpip_frame_par->vscale_skip_count); + len += sprintf(buf + len, "hscale_skip_count %u.\n", + curpip_frame_par->hscale_skip_count); + len += sprintf(buf + len, "supscl_path %u.\n", + curpip_frame_par->supscl_path); + len += sprintf(buf + len, "supsc0_enable %u.\n", + curpip_frame_par->supsc0_enable); + len += sprintf(buf + len, "supsc1_enable %u.\n", + curpip_frame_par->supsc1_enable); + len += sprintf(buf + len, "supsc0_hori_ratio %u.\n", + curpip_frame_par->supsc0_hori_ratio); + len += sprintf(buf + len, "supsc1_hori_ratio %u.\n", + curpip_frame_par->supsc1_hori_ratio); + len += sprintf(buf + len, "supsc0_vert_ratio %u.\n", + curpip_frame_par->supsc0_vert_ratio); + len += sprintf(buf + len, "supsc1_vert_ratio %u.\n", + curpip_frame_par->supsc1_vert_ratio); + len += sprintf(buf + len, "spsc0_h_in %u.\n", + curpip_frame_par->spsc0_h_in); + len += sprintf(buf + len, "spsc1_h_in %u.\n", + curpip_frame_par->spsc1_h_in); + len += sprintf(buf + len, "spsc0_w_in %u.\n", + curpip_frame_par->spsc0_w_in); + len += sprintf(buf + len, "spsc1_w_in %u.\n", + curpip_frame_par->spsc1_w_in); + len += sprintf(buf + len, "video_input_w %u.\n", + curpip_frame_par->video_input_w); + len += sprintf(buf + len, "video_input_h %u.\n", + curpip_frame_par->video_input_h); + len += sprintf(buf + len, "clk_in_pps %u.\n", + curpip_frame_par->clk_in_pps); + len += + sprintf(buf + len, "hscale phase step 0x%x.\n", + vpp_filter->vpp_hsc_start_phase_step); + len += + sprintf(buf + len, "vscale phase step 0x%x.\n", + vpp_filter->vpp_vsc_start_phase_step); + len += + sprintf(buf + len, "pps pre hsc enable %d.\n", + vpp_filter->vpp_pre_hsc_en); + len += + sprintf(buf + len, "pps pre vsc enable %d.\n", + vpp_filter->vpp_pre_vsc_en); + len += + sprintf(buf + len, "hscale filter coef %d.\n", + vpp_filter->vpp_horz_filter); + len += + sprintf(buf + len, "vscale filter coef %d.\n", + vpp_filter->vpp_vert_filter); + len += + sprintf(buf + len, "vpp_vert_chroma_filter_en %d.\n", + vpp_filter->vpp_vert_chroma_filter_en); + len += + sprintf(buf + len, "post_blend_vd_h_start 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_h_start_); + len += + sprintf(buf + len, "post_blend_vd_h_end 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_h_end_); + len += + sprintf(buf + len, "post_blend_vd_v_start 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_v_start_); + len += + sprintf(buf + len, "post_blend_vd_v_end 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_v_end_); + len += + sprintf(buf + len, "VPP_hd_start_lines_ 0x%x.\n", + curpip_frame_par->VPP_hd_start_lines_); + len += + sprintf(buf + len, "VPP_hd_end_lines_ 0x%x.\n", + curpip_frame_par->VPP_hd_end_lines_); + len += + sprintf(buf + len, "VPP_vd_start_lines_ 0x%x.\n", + curpip_frame_par->VPP_vd_start_lines_); + len += + sprintf(buf + len, "VPP_vd_end_lines_ 0x%x.\n", + curpip_frame_par->VPP_vd_end_lines_); + len += + sprintf(buf + len, "VPP_hsc_startp 0x%x.\n", + curpip_frame_par->VPP_hsc_startp); + len += + sprintf(buf + len, "VPP_hsc_endp 0x%x.\n", + curpip_frame_par->VPP_hsc_endp); + len += + sprintf(buf + len, "VPP_vsc_startp 0x%x.\n", + curpip_frame_par->VPP_vsc_startp); + len += + sprintf(buf + len, "VPP_vsc_endp 0x%x.\n", + curpip_frame_par->VPP_vsc_endp); + return len; +} + +#endif + static struct class_attribute amvideo_class_attrs[] = { __ATTR(axis, 0664, @@ -9775,9 +11288,9 @@ static struct class_attribute amvideo_class_attrs[] = { video_disable_show, video_disable_store), __ATTR(video_global_output, - 0664, - video_global_output_show, - video_global_output_store), + 0664, + video_global_output_show, + video_global_output_store), __ATTR(hold_video, 0664, video_hold_show, @@ -9901,6 +11414,33 @@ static struct class_attribute amvideo_class_attrs[] = { __ATTR_RO(fps_info), __ATTR_RO(video_layer1_state), __ATTR_RO(pic_mode_info), +#ifdef VIDEO_PIP + __ATTR(axis_pip, + 0664, + videopip_axis_show, + videopip_axis_store), + __ATTR(crop_pip, + 0664, + videopip_crop_show, + videopip_crop_store), + __ATTR(disable_videopip, + 0664, + videopip_disable_show, + videopip_disable_store), + __ATTR(screen_mode_pip, + 0664, + videopip_screen_mode_show, + videopip_screen_mode_store), + __ATTR(videopip_loop, + 0664, + videopip_loop_show, + videopip_loop_store), + __ATTR(pip_global_output, + 0664, + videopip_global_output_show, + videopip_global_output_store), + __ATTR_RO(videopip_state), +#endif __ATTR_NULL }; @@ -10045,10 +11585,8 @@ int vout_notify_callback(struct notifier_block *block, unsigned long cmd, new_vmode = vinfo->mode; break; case VOUT_EVENT_OSD_PREBLEND_ENABLE: - vpp_set_osd_layer_preblend(para); break; case VOUT_EVENT_OSD_DISP_AXIS: - vpp_set_osd_layer_position(para); break; } return 0; @@ -10077,10 +11615,8 @@ int vout2_notify_callback(struct notifier_block *block, unsigned long cmd, spin_unlock_irqrestore(&lock, flags); break; case VOUT_EVENT_OSD_PREBLEND_ENABLE: - vpp_set_osd_layer_preblend(para); break; case VOUT_EVENT_OSD_DISP_AXIS: - vpp_set_osd_layer_position(para); break; } return 0; @@ -10291,20 +11827,6 @@ static int __init video_early_init(void) u32 cur_hold_line; -#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */ -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) - WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); - else - WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x77f, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#if 0 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESONG9TV */ - WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x800, VPP_OFIFO_SIZE_BIT, - VPP_OFIFO_SIZE_WID); -#endif -#endif /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#else if (!legacy_vpp) { WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x1000, VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); @@ -10313,12 +11835,10 @@ static int __init video_early_init(void) } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff, VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#endif -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ WRITE_VCBUS_REG(VPP_PREBLEND_VD1_H_START_END, 4096); WRITE_VCBUS_REG(VPP_BLEND_VD2_H_START_END, 4096); -#endif + if (is_meson_txl_cpu() || is_meson_txlx_cpu()) { /* fifo max size on txl :128*3=384[0x180] */ WRITE_VCBUS_REG( @@ -10327,27 +11847,9 @@ static int __init video_early_init(void) VD2_IF0_LUMA_FIFO_SIZE + cur_dev->viu_off, 0x180); } -#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */ - CLEAR_VCBUS_REG_MASK(VPP_VSC_PHASE_CTRL, - VPP_PHASECTL_TYPE_INTERLACE); - SET_VCBUS_REG_MASK(VPP_MISC, VPP_OUT_SATURATE); - WRITE_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off, 0x08080808); -#endif - #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 -#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */ - CLEAR_VCBUS_REG_MASK(VPP2_VSC_PHASE_CTRL, - VPP_PHASECTL_TYPE_INTERLACE); - SET_VCBUS_REG_MASK(VPP2_MISC, VPP_OUT_SATURATE); - WRITE_VCBUS_REG(VPP2_HOLD_LINES, 0x08080808); -#endif -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x800, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#else - WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x780, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#endif + VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); /* *WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 1, 12, 2); *select vdisp_mmc_arb for VIU2_OSD1 request @@ -10389,11 +11891,15 @@ static int __init video_early_init(void) vpp_hold_line = cur_hold_line; /* Temp force set dmc */ - if (!legacy_vpp) + if (!legacy_vpp) { WRITE_DMCREG( DMC_AM0_CHAN_CTRL, 0x8ff403cf); - + /* for vd1 & vd2 dummy alpha*/ + WRITE_VCBUS_REG( + VPP_POST_BLEND_DUMMY_ALPHA, + 0x7fffffff); + } if (is_meson_tl1_cpu()) { /* force bypass dolby for TL1, no dolby function */ WRITE_VCBUS_REG_BITS( @@ -10531,7 +12037,7 @@ static struct platform_driver amvideom_driver = { static int __init video_init(void) { - int r = 0; + int r = 0, i; /* *#ifdef CONFIG_ARCH_MESON1 *ulong clk = clk_get_rate(clk_get_sys("clk_other_pll", NULL)); @@ -10661,6 +12167,33 @@ static int __init video_init(void) goto err5; } + for (i = 0; i < MAX_VD_LAYERS; i++) { + vpp_disp_info_init(&glayer_info[i], i); + glayer_info[i].wide_mode = 1; + } + + if (legacy_vpp) + layer_cap = + LAYER1_AFBC | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else if (is_meson_tl1_cpu()) + layer_cap = + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else + layer_cap = + LAYER1_AFBC | + LAYER1_SCALER | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + init_waitqueue_head(&amvideo_trick_wait); init_waitqueue_head(&amvideo_sizechange_wait); #if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ @@ -10710,9 +12243,13 @@ static int __init video_init(void) NULL); vf_reg_receiver(&video_vf_recv); - vf_receiver_init(&video4osd_vf_recv, RECEIVER4OSD_NAME, - &video4osd_vf_receiver, NULL); - vf_reg_receiver(&video4osd_vf_recv); +#ifdef VIDEO_PIP + vf_receiver_init( + &videopip_vf_recv, RECEIVERPIP_NAME, + &videopip_vf_receiver, NULL); + vf_reg_receiver(&videopip_vf_recv); +#endif + #if DEBUG_TMP switch_dev_register(&video1_state_sdev); switch_set_state(&video1_state_sdev, 0); @@ -10753,7 +12290,9 @@ static void __exit video_exit(void) video_debugfs_exit(); vf_unreg_receiver(&video_vf_recv); - vf_unreg_receiver(&video4osd_vf_recv); +#ifdef VIDEO_PIP + vf_unreg_receiver(&videopip_vf_recv); +#endif DisableVideoLayer(); DisableVideoLayer2(); diff --git a/drivers/amlogic/media/video_sink/video_keeper.c b/drivers/amlogic/media/video_sink/video_keeper.c index 1dbfcd4ba6b8..ad8b02b50411 100644 --- a/drivers/amlogic/media/video_sink/video_keeper.c +++ b/drivers/amlogic/media/video_sink/video_keeper.c @@ -145,8 +145,9 @@ static int ge2d_store_frame_YUV444(u32 cur_index) yaddr = keep_phy_addr(keep_y_addr); canvas_config(ydupindex, - (ulong) yaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) yaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); canvas_read(ydupindex, &cd); src_index = y_index; @@ -194,8 +195,9 @@ static int ge2d_store_frame_YUV444(u32 cur_index) return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, - 0, 0, cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); return 0; } @@ -226,11 +228,13 @@ static int ge2d_store_frame_NV21(u32 cur_index) canvas_read(y_index, &cs0); canvas_read(u_index, &cs1); canvas_config(ydupindex, - (ulong) yaddr, - cs0.width, cs0.height, CANVAS_ADDR_NOWRAP, cs0.blkmode); + (ulong) yaddr, + cs0.width, cs0.height, + CANVAS_ADDR_NOWRAP, cs0.blkmode); canvas_config(udupindex, - (ulong) uaddr, - cs1.width, cs1.height, CANVAS_ADDR_NOWRAP, cs1.blkmode); + (ulong) uaddr, + cs1.width, cs1.height, + CANVAS_ADDR_NOWRAP, cs1.blkmode); canvas_read(ydupindex, &cd); src_index = ((y_index & 0xff) | ((u_index << 8) & 0x0000ff00)); @@ -280,8 +284,9 @@ static int ge2d_store_frame_NV21(u32 cur_index) return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs0.width, cs0.height, - 0, 0, cs0.width, cs0.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs0.width, cs0.height, + 0, 0, cs0.width, cs0.height); return 0; } @@ -322,8 +327,10 @@ static int ge2d_store_frame_YUV420(u32 cur_index) yaddr = keep_phy_addr(keep_y_addr); canvas_config(ydupindex, - (ulong) yaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) yaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + canvas_read(ydupindex, &cd); ge2d_config.dst_planes[0].addr = cd.addr; ge2d_config.dst_planes[0].w = cd.width; @@ -371,8 +378,9 @@ static int ge2d_store_frame_YUV420(u32 cur_index) pr_info("++ge2d configing error.\n"); return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, 0, 0, - cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); /* U data */ ge2d_config.alu_const_color = 0; @@ -393,8 +401,10 @@ static int ge2d_store_frame_YUV420(u32 cur_index) uaddr = keep_phy_addr(keep_u_addr); canvas_config(udupindex, - (ulong) uaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) uaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + canvas_read(udupindex, &cd); ge2d_config.dst_planes[0].addr = cd.addr; ge2d_config.dst_planes[0].w = cd.width; @@ -442,8 +452,9 @@ static int ge2d_store_frame_YUV420(u32 cur_index) pr_info("++ge2d configing error.\n"); return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, 0, 0, - cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); /* operation top line */ /* V data */ @@ -465,8 +476,10 @@ static int ge2d_store_frame_YUV420(u32 cur_index) vaddr = keep_phy_addr(keep_v_addr); canvas_config(vdupindex, - (ulong) vaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) vaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + ge2d_config.dst_planes[0].addr = cd.addr; ge2d_config.dst_planes[0].w = cd.width; ge2d_config.dst_planes[0].h = cd.height; @@ -513,14 +526,14 @@ static int ge2d_store_frame_YUV420(u32 cur_index) pr_info("++ge2d configing error.\n"); return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, 0, 0, - cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); return 0; } static void ge2d_keeplastframe_block(int cur_index, int format) { - /* u32 cur_index; */ u32 y_index, u_index, v_index; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA u32 y_index2, u_index2, v_index2; @@ -579,10 +592,9 @@ static void ge2d_keeplastframe_block(int cur_index, int format) video_module_unlock(); } - #endif -#define FETCHBUF_SIZE (64*1024) /*DEBUG_TMP*/ +#define FETCHBUF_SIZE (64*1024) /*DEBUG_TMP*/ static int canvas_dup(ulong dst, ulong src_paddr, ulong size) { void *src_addr = codec_mm_phys_to_virt(src_paddr); @@ -636,13 +648,14 @@ static int alloc_keep_buffer(void) flags = CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_FOR_VDECODER; #endif if ((flags & CODEC_MM_FLAGS_FOR_VDECODER) && - codec_mm_video_tvp_enabled())/*TVP TODO for MULTI*/ + codec_mm_video_tvp_enabled()) + /*TVP TODO for MULTI*/ flags |= CODEC_MM_FLAGS_TVP; if (!keep_y_addr) { keep_y_addr = codec_mm_alloc_for_dma( - MEM_NAME, - PAGE_ALIGN(Y_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + MEM_NAME, + PAGE_ALIGN(Y_BUFFER_SIZE)/PAGE_SIZE, 0, flags); if (!keep_y_addr) { pr_err("%s: failed to alloc y addr\n", __func__); goto err1; @@ -651,8 +664,8 @@ static int alloc_keep_buffer(void) if (!keep_u_addr) { keep_u_addr = codec_mm_alloc_for_dma( - MEM_NAME, - PAGE_ALIGN(U_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + MEM_NAME, + PAGE_ALIGN(U_BUFFER_SIZE)/PAGE_SIZE, 0, flags); if (!keep_u_addr) { pr_err("%s: failed to alloc u addr\n", __func__); goto err1; @@ -661,8 +674,8 @@ static int alloc_keep_buffer(void) if (!keep_v_addr) { keep_v_addr = codec_mm_alloc_for_dma( - MEM_NAME, - PAGE_ALIGN(V_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + MEM_NAME, + PAGE_ALIGN(V_BUFFER_SIZE)/PAGE_SIZE, 0, flags); if (!keep_v_addr) { pr_err("%s: failed to alloc v addr\n", __func__); goto err1; @@ -680,7 +693,6 @@ static int alloc_keep_buffer(void) return -ENOMEM; } - /* *flags,used per bit: *deflaut free alloced keeper buffer. @@ -708,7 +720,6 @@ void try_free_keep_video(int flags) mutex_unlock(&video_keeper_mutex); } EXPORT_SYMBOL(try_free_keep_video); - #endif static void video_keeper_update_keeper_mem( @@ -730,6 +741,7 @@ static void video_keeper_update_keeper_mem( *id = ret; } } + static int video_keeper_frame_keep_locked( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf_el) @@ -795,6 +807,7 @@ void video_keeper_new_frame_notify(void) } return; } + static unsigned int vf_keep_current_locked( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf_el) @@ -809,28 +822,28 @@ static unsigned int vf_keep_current_locked( return 0; } - if (cur_dispbuf->source_type == VFRAME_SOURCE_TYPE_OSD) { - pr_info("keep exit is osd\n"); - return 0; - } - if (get_video_debug_flags() & DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { pr_info("keep exit is skip current\n"); return 0; } #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE - ext_frame_capture_poll(1); /*pull if have capture end frame */ + ext_frame_capture_poll(1); /*pull if have capture end frame */ #endif + if (get_blackout_policy()) { pr_info("keep exit is skip current\n"); return 0; } + if (VSYNC_RD_MPEG_REG(DI_IF1_GEN_REG) & 0x1) { pr_info("keep exit is di\n"); return 0; } - ret = video_keeper_frame_keep_locked(cur_dispbuf, + ret = video_keeper_frame_keep_locked( + cur_dispbuf, cur_dispbuf_el); if (ret) { /*keeped ok with codec keeper!*/ @@ -844,34 +857,34 @@ static unsigned int vf_keep_current_locked( } #endif - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && - (cur_dispbuf->type & VIDTYPE_COMPRESS)) { + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { /* todo: duplicate compressed video frame */ pr_info("keep exit is skip VIDTYPE_COMPRESS\n"); return -1; } cur_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + - get_video_cur_dev()->viu_off); + get_video_cur_dev()->viu_off); y_index = cur_index & 0xff; u_index = (cur_index >> 8) & 0xff; v_index = (cur_index >> 16) & 0xff; canvas_read(y_index, &cd); - if ((cd.width * cd.height) <= 2048 * 1088 && - !keep_y_addr) { + if ((cd.width * cd.height) <= 2048 * 1088 + && !keep_y_addr) { alloc_keep_buffer(); } if (!keep_y_addr - || (cur_dispbuf->type & VIDTYPE_VIU_422) == VIDTYPE_VIU_422) { + || (cur_dispbuf->type & VIDTYPE_VIU_422) + == VIDTYPE_VIU_422) { /* no support VIDTYPE_VIU_422... */ pr_info("%s:no support VIDTYPE_VIU_422\n", __func__); return -1; } - if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) { - pr_info("%s keep_y_addr=%p %x\n", __func__, (void *)keep_y_addr, - canvas_get_addr(y_index)); + pr_info("%s keep_y_addr=%p %x\n", + __func__, (void *)keep_y_addr, + canvas_get_addr(y_index)); } if ((cur_dispbuf->type & VIDTYPE_VIU_422) == VIDTYPE_VIU_422) { @@ -886,21 +899,20 @@ static unsigned int vf_keep_current_locked( return -1; } if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cd.width) * (cd.height))) { + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cd.width) * (cd.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); #else canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); #endif if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) pr_info("%s: VIDTYPE_VIU_422\n", __func__); - } */ } else if ((cur_dispbuf->type & VIDTYPE_VIU_444) == VIDTYPE_VIU_444) { @@ -916,17 +928,17 @@ static unsigned int vf_keep_current_locked( ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_YUV444); #else if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cd.width) * (cd.height))) { + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cd.width) * (cd.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); #else canvas_update_addr(y_index, - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); #endif } #endif @@ -936,7 +948,7 @@ static unsigned int vf_keep_current_locked( canvas_read(y_index, &cs0); canvas_read(u_index, &cs1); if ((Y_BUFFER_SIZE < (cs0.width * cs0.height)) - || (U_BUFFER_SIZE < (cs1.width * cs1.height))) { + || (U_BUFFER_SIZE < (cs1.width * cs1.height))) { pr_info("## [%s::%d] error: yuv data size larger", __func__, __LINE__); return -1; @@ -945,21 +957,21 @@ static unsigned int vf_keep_current_locked( ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_NV21); #else if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cs0.width * cs0.height)) - && canvas_dup(keep_phy_addr(keep_u_addr), - canvas_get_addr(u_index), - (cs1.width * cs1.height))) { + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cs0.width * cs0.height)) + && canvas_dup(keep_phy_addr(keep_u_addr), + canvas_get_addr(u_index), + (cs1.width * cs1.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[0][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); canvas_update_addr(disp_canvas_index[1][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); #else canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); @@ -976,13 +988,13 @@ static unsigned int vf_keep_current_locked( canvas_read(v_index, &cs2); if ((Y_BUFFER_SIZE < (cs0.width * cs0.height)) - || (U_BUFFER_SIZE < (cs1.width * cs1.height)) - || (V_BUFFER_SIZE < (cs2.width * cs2.height))) { + || (U_BUFFER_SIZE < (cs1.width * cs1.height)) + || (V_BUFFER_SIZE < (cs2.width * cs2.height))) { pr_info("## [%s::%d] error: yuv data size larger than buf size: %x,%x,%x, %x,%x, %x,%x, %x,%x,\n", - __func__, __LINE__, Y_BUFFER_SIZE, - U_BUFFER_SIZE, V_BUFFER_SIZE, cs0.width, - cs0.height, cs1.width, cs1.height, cs2.width, - cs2.height); + __func__, __LINE__, Y_BUFFER_SIZE, + U_BUFFER_SIZE, V_BUFFER_SIZE, cs0.width, + cs0.height, cs1.width, cs1.height, cs2.width, + cs2.height); return -1; } #ifdef CONFIG_GE2D_KEEP_FRAME @@ -990,28 +1002,28 @@ static unsigned int vf_keep_current_locked( #else if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && /*must not the same address */ - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cs0.width * cs0.height)) - && canvas_dup(keep_phy_addr(keep_u_addr), - canvas_get_addr(u_index), - (cs1.width * cs1.height)) + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cs0.width * cs0.height)) + && canvas_dup(keep_phy_addr(keep_u_addr), + canvas_get_addr(u_index), + (cs1.width * cs1.height)) && canvas_dup(keep_phy_addr(keep_v_addr), - canvas_get_addr(v_index), - (cs2.width * cs2.height))) { + canvas_get_addr(v_index), + (cs2.width * cs2.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[0][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); canvas_update_addr(disp_canvas_index[1][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); canvas_update_addr(disp_canvas_index[0][2], - keep_phy_addr(keep_v_addr)); + keep_phy_addr(keep_v_addr)); canvas_update_addr(disp_canvas_index[1][2], - keep_phy_addr(keep_v_addr)); + keep_phy_addr(keep_v_addr)); #else canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); @@ -1038,8 +1050,8 @@ unsigned int vf_keep_current( unsigned int ret; mutex_lock(&video_keeper_mutex); - ret = vf_keep_current_locked(cur_dispbuf, - cur_dispbuf2); + ret = vf_keep_current_locked( + cur_dispbuf, cur_dispbuf2); mutex_unlock(&video_keeper_mutex); return ret; } diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h index cca1ddf66398..446a8a9e2399 100644 --- a/drivers/amlogic/media/video_sink/video_priv.h +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -17,6 +17,9 @@ #ifndef VIDEO_PRIV_HEADER_HH #define VIDEO_PRIV_HEADER_HH + +#include + #define DEBUG_FLAG_BLACKOUT 0x1 #define DEBUG_FLAG_PRINT_TOGGLE_FRAME 0x2 #define DEBUG_FLAG_PRINT_RDMA 0x4 @@ -38,10 +41,97 @@ #define VIDEO_DISABLE_NORMAL 1 #define VIDEO_DISABLE_FORNEXT 2 +#define VIDEO_NOTIFY_TRICK_WAIT 0x01 +#define VIDEO_NOTIFY_PROVIDER_GET 0x02 +#define VIDEO_NOTIFY_PROVIDER_PUT 0x04 +#define VIDEO_NOTIFY_FRAME_WAIT 0x08 +#define VIDEO_NOTIFY_POS_CHANGED 0x10 + struct video_dev_s { int vpp_off; int viu_off; }; + +struct mif_pos_s { + u32 id; + u32 vd_reg_offt; + u32 afbc_reg_offt; + + /* frame original size */ + u32 src_w; + u32 src_h; + + /* mif start - end lines */ + u32 start_x_lines; + u32 end_x_lines; + u32 start_y_lines; + u32 end_y_lines; + + /* left and right eye position, skip flag. */ + /* And if non 3d case, left eye = right eye */ + u32 l_hs_luma; + u32 l_he_luma; + u32 l_hs_chrm; + u32 l_he_chrm; + u32 r_hs_luma; + u32 r_he_luma; + u32 r_hs_chrm; + u32 r_he_chrm; + u32 h_skip; + u32 l_vs_luma; + u32 l_ve_luma; + u32 l_vs_chrm; + u32 l_ve_chrm; + u32 r_vs_luma; + u32 r_ve_luma; + u32 r_vs_chrm; + u32 r_ve_chrm; + u32 v_skip; + + bool reverse; + + bool skip_afbc; +}; + +struct scaler_setting_s { + u32 id; + u32 misc_reg_offt; + + bool sc_h_enable; + bool sc_v_enable; + bool sc_top_enable; + + u32 vinfo_width; + u32 vinfo_height; + /* u32 VPP_pic_in_height_; */ + /* u32 VPP_line_in_length_; */ + + struct vpp_frame_par_s *frame_par; +}; + +struct blend_setting_s { + u32 id; + u32 misc_reg_offt; + + u32 layer_alpha; + + u32 preblend_h_start; + u32 preblend_h_end; + u32 preblend_v_start; + u32 preblend_v_end; + + u32 preblend_h_size; + + u32 postblend_h_start; + u32 postblend_h_end; + u32 postblend_v_start; + u32 postblend_v_end; + + u32 postblend_h_size; + + struct vpp_frame_par_s *frame_par; +}; + void safe_disble_videolayer(void); void update_cur_dispbuf(void *buf); @@ -54,6 +144,7 @@ struct vframe_s *get_cur_dispbuf(void); int get_video_debug_flags(void); int _video_set_disable(u32 val); u32 get_video_enabled(void); +struct device *get_video_device(void); #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE int ext_frame_capture_poll(int endflags); diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 17d138499af4..5eda6a083f2e 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -18,21 +18,12 @@ #include #include #include -/* #include */ #include - #include - #include #include #include -#include -#include -/*#include */ - -#include - #include "videolog.h" /* #define CONFIG_VIDEO_LOG */ #ifdef CONFIG_VIDEO_LOG @@ -42,6 +33,10 @@ #include #include +#include "video_priv.h" + +#define MAX_NONLINEAR_FACTOR 0x40 + /* vpp filter coefficients */ #define COEF_BICUBIC 0 #define COEF_3POINT_TRIANGLE 1 @@ -56,13 +51,21 @@ #define COEF_NULL 0xff #define TOTAL_FILTERS 10 -#define MAX_NONLINEAR_FACTOR 0x40 - #define VPP_SPEED_FACTOR 0x110ULL #define SUPER_SCALER_V_FACTOR 100 #define PPS_FRAC_BITS 24 #define PPS_INT_BITS 4 +struct filter_info_s { + u32 cur_vert_filter; + u32 cur_horz_filter; + u32 last_vert_filter; + u32 last_horz_filter; + u32 scaler_filter_cnt; +}; + +static struct filter_info_s gfilter[MAX_VD_LAYERS]; + const u32 vpp_filter_coefs_bicubic_sharp[] = { 3, 33 | 0x8000, @@ -248,8 +251,8 @@ MODULE_PARM_DESC(vpp_filter_fix, "vpp_filter_fix"); module_param(vpp_filter_fix, uint, 0664); #define MAX_COEFF_LEVEL 5 -uint num_coeff_level = MAX_COEFF_LEVEL; -uint vert_coeff_settings[MAX_COEFF_LEVEL] = { +static uint num_coeff_level = MAX_COEFF_LEVEL; +static uint vert_coeff_settings[MAX_COEFF_LEVEL] = { /* in:out */ COEF_BICUBIC, /* ratio < 1 */ @@ -269,7 +272,7 @@ uint vert_coeff_settings[MAX_COEFF_LEVEL] = { /* this setting is most smooth */ }; -uint horz_coeff_settings[MAX_COEFF_LEVEL] = { +static uint horz_coeff_settings[MAX_COEFF_LEVEL] = { /* in:out */ COEF_BICUBIC, /* ratio < 1 */ @@ -334,40 +337,40 @@ MODULE_PARM_DESC(vert_coeff_settings, "\n vert_coeff_settings\n"); module_param_array(horz_coeff_settings, uint, &num_coeff_level, 0664); MODULE_PARM_DESC(horz_coeff_settings, "\n horz_coeff_settings\n"); -bool vert_chroma_filter_en = true; +static bool vert_chroma_filter_en = true; module_param(vert_chroma_filter_en, bool, 0664); MODULE_PARM_DESC(vert_chroma_filter_en, "enable vertical chromafilter\n"); -bool vert_chroma_filter_force_en; +static bool vert_chroma_filter_force_en; module_param(vert_chroma_filter_force_en, bool, 0664); MODULE_PARM_DESC(vert_chroma_filter_force_en, "force enable vertical chromafilter\n"); -uint vert_chroma_filter_limit = 480; +static uint vert_chroma_filter_limit = 480; module_param(vert_chroma_filter_limit, uint, 0664); MODULE_PARM_DESC(vert_chroma_filter_limit, "vertical chromafilter limit\n"); -uint num_chroma_filter = TOTAL_FILTERS; +static uint num_chroma_filter = TOTAL_FILTERS; module_param_array(chroma_filter_table, uint, &num_chroma_filter, 0664); MODULE_PARM_DESC(chroma_filter_table, "\n chroma_filter_table\n"); -uint cur_vert_chroma_filter; +static uint cur_vert_chroma_filter; MODULE_PARM_DESC(cur_vert_chroma_filter, "cur_vert_chroma_filter"); module_param(cur_vert_chroma_filter, int, 0444); -uint cur_vert_filter; +static uint cur_vert_filter; MODULE_PARM_DESC(cur_vert_filter, "cur_vert_filter"); module_param(cur_vert_filter, int, 0444); -uint cur_horz_filter; +static uint cur_horz_filter; MODULE_PARM_DESC(cur_horz_filter, "cur_horz_filter"); module_param(cur_horz_filter, int, 0444); -uint cur_skip_line; +static uint cur_skip_line; MODULE_PARM_DESC(cur_skip_line, "cur_skip_line"); module_param(cur_skip_line, int, 0444); -unsigned int super_scaler_v_ratio = 133; +static unsigned int super_scaler_v_ratio = 133; MODULE_PARM_DESC(super_scaler_v_ratio, "super_scaler_v_ratio"); module_param(super_scaler_v_ratio, uint, 0664); @@ -375,31 +378,11 @@ static u32 skip_policy = 0x81; module_param(skip_policy, uint, 0664); MODULE_PARM_DESC(skip_policy, "\n skip_policy\n"); -unsigned int scaler_filter_cnt_limit = 10; +static unsigned int scaler_filter_cnt_limit = 10; MODULE_PARM_DESC(scaler_filter_cnt_limit, "scaler_filter_cnt_limit"); module_param(scaler_filter_cnt_limit, uint, 0664); -static uint last_vert_filter; -static uint last_horz_filter; -static uint scaler_filter_cnt; - -static u32 vpp_wide_mode; -static u32 vpp_zoom_ratio = 100; -static s32 vpp_zoom_center_x, vpp_zoom_center_y; -static u32 nonlinear_factor = MAX_NONLINEAR_FACTOR / 2; -static u32 osd_layer_preblend; -static s32 video_layer_top, video_layer_left, video_layer_width, - video_layer_height; -static u32 video_source_crop_top, video_source_crop_left, - video_source_crop_bottom, video_source_crop_right; -static u32 video_crop_top_resv, video_crop_left_resv, - video_crop_bottom_resv, video_crop_right_resv; -static s32 video_layer_global_offset_x, video_layer_global_offset_y; -static s32 osd_layer_top, osd_layer_left, osd_layer_width, osd_layer_height; -static u32 video_speed_check_width = 1800, video_speed_check_height = 1400; - #ifdef TV_3D_FUNCTION_OPEN -static bool vpp_3d_scale; static int force_filter_mode = 1; MODULE_PARM_DESC(force_filter_mode, "force_filter_mode"); module_param(force_filter_mode, int, 0664); @@ -446,15 +429,15 @@ static unsigned int sr0_sr1_refresh = 1; module_param(sr0_sr1_refresh, uint, 0664); MODULE_PARM_DESC(sr0_sr1_refresh, "sr0_sr1_refresh"); -bool pre_scaler_en = true; +static bool pre_scaler_en = true; module_param(pre_scaler_en, bool, 0664); MODULE_PARM_DESC(pre_scaler_en, "pre_scaler_en"); -unsigned int force_vskip_cnt; +static unsigned int force_vskip_cnt; MODULE_PARM_DESC(force_vskip_cnt, "force_vskip_cnt"); module_param(force_vskip_cnt, uint, 0664); -unsigned int disable_adapted; +static unsigned int disable_adapted; MODULE_PARM_DESC(disable_adapted, "disable_adapted"); module_param(disable_adapted, uint, 0664); @@ -554,13 +537,15 @@ static void f2v_get_vertical_phase(u32 zoom_ratio, /* * V-shape non-linear mode */ -static void -calculate_non_linear_ratio(unsigned int middle_ratio, - unsigned int width_out, - struct vpp_frame_par_s *next_frame_par) +static void calculate_non_linear_ratio( + unsigned int nonlinear_factor, + unsigned int middle_ratio, + unsigned int width_out, + struct vpp_frame_par_s *next_frame_par) { unsigned int diff_ratio; - struct vppfilter_mode_s *vpp_filter = &next_frame_par->vpp_filter; + struct vppfilter_mode_s *vpp_filter = + &next_frame_par->vpp_filter; diff_ratio = middle_ratio * nonlinear_factor; vpp_filter->vpp_hf_start_phase_step = (middle_ratio << 6) - diff_ratio; @@ -589,23 +574,23 @@ calculate_non_linear_ratio(unsigned int middle_ratio, * (1.25 * 3840 / 1920) for 1080p mode. */ #define MIN_RATIO_1000 1250 -unsigned int min_skip_ratio = MIN_RATIO_1000; +static unsigned int min_skip_ratio = MIN_RATIO_1000; MODULE_PARM_DESC(min_skip_ratio, "min_skip_ratio"); module_param(min_skip_ratio, uint, 0664); -unsigned int max_proc_height = 2160; +static unsigned int max_proc_height = 2160; MODULE_PARM_DESC(max_proc_height, "max_proc_height"); module_param(max_proc_height, uint, 0664); -unsigned int cur_proc_height; +static unsigned int cur_proc_height; MODULE_PARM_DESC(cur_proc_height, "cur_proc_height"); module_param(cur_proc_height, uint, 0444); -unsigned int cur_skip_ratio; +static unsigned int cur_skip_ratio; MODULE_PARM_DESC(cur_skip_ratio, "cur_skip_ratio"); module_param(cur_skip_ratio, uint, 0444); -unsigned int cur_vf_type; +static unsigned int cur_vf_type; MODULE_PARM_DESC(cur_vf_type, "cur_vf_type"); module_param(cur_vf_type, uint, 0444); -unsigned int custom_ar; +static unsigned int custom_ar; MODULE_PARM_DESC(custom_ar, "custom_ar"); module_param(custom_ar, uint, 0664); @@ -627,13 +612,16 @@ module_param(custom_ar, uint, 0664); *So need adjust bypass_ratio; */ -static int -vpp_process_speed_check(s32 width_in, - s32 height_in, - s32 height_out, - s32 height_screen, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo, struct vframe_s *vf) +static int vpp_process_speed_check( + u32 layer_id, + s32 width_in, + s32 height_in, + s32 height_out, + s32 height_screen, + u32 video_speed_check_width, + u32 video_speed_check_height, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo, struct vframe_s *vf) { u32 cur_ratio, bpp = 1; int min_ratio_1000 = 0; @@ -642,12 +630,16 @@ vpp_process_speed_check(s32 width_in, u32 width_out = 0; u32 vpu_clk = 0, max_height = 2160; /* 4k mode */ - if (vf) + if (!vf) + return SPEED_CHECK_DONE; + + /* store the debug info for legacy */ + if (layer_id == 0) cur_vf_type = vf->type; - else - return 0; + if (force_vskip_cnt == 0xff)/*for debug*/ return SPEED_CHECK_DONE; + if (next_frame_par->vscale_skip_count < force_vskip_cnt) return SPEED_CHECK_VSKIP; @@ -726,39 +718,45 @@ vpp_process_speed_check(s32 width_in, if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { cur_ratio = div_u64((u64)height_in * - (u64)vinfo->height * - 1000, - height_out * max_height); + (u64)vinfo->height * + 1000, + height_out * max_height); /* di process first, need more a bit of ratio */ if (vf->type & VIDTYPE_PRE_INTERLACE) cur_ratio = (cur_ratio * 105) / 100; if ((next_frame_par->vscale_skip_count > 0) && (vf->type & VIDTYPE_VIU_444)) cur_ratio = cur_ratio * 2; - cur_skip_ratio = cur_ratio; + + /* store the debug info for legacy */ + if (layer_id == 0) + cur_skip_ratio = cur_ratio; + if ((cur_ratio > min_ratio_1000) && - (vf->source_type != VFRAME_SOURCE_TYPE_TUNER) && - (vf->source_type != VFRAME_SOURCE_TYPE_CVBS)) + (vf->source_type != + VFRAME_SOURCE_TYPE_TUNER) && + (vf->source_type != + VFRAME_SOURCE_TYPE_CVBS)) return SPEED_CHECK_VSKIP; } if (vf->type & VIDTYPE_VIU_422) { /*TODO vpu */ - if (height_out == 0 - || div_u64((u64)VPP_SPEED_FACTOR * - (u64)width_in * - (u64)height_in * - (u64)vinfo->sync_duration_num * - (u64)vtotal, - height_out * - vinfo->sync_duration_den * - bypass_ratio) > clk_in_pps) + if (height_out == 0 || + div_u64((u64)VPP_SPEED_FACTOR * + (u64)width_in * + (u64)height_in * + (u64)vinfo->sync_duration_num * + (u64)vtotal, + height_out * + vinfo->sync_duration_den * + bypass_ratio) > clk_in_pps) return SPEED_CHECK_VSKIP; else return SPEED_CHECK_DONE; } else { /*TODO vpu */ - if (height_out == 0 - || div_u64((u64)VPP_SPEED_FACTOR * + if (height_out == 0 || + div_u64((u64)VPP_SPEED_FACTOR * (u64)width_in * (u64)height_in * (u64)vinfo->sync_duration_num * @@ -770,16 +768,15 @@ vpp_process_speed_check(s32 width_in, /* 4K down scaling to non 4K > 30hz,*/ /*skip lines for memory bandwidth */ else if ((((vf->type & VIDTYPE_COMPRESS) - == 0) || (next_frame_par->nocomp)) - && - (height_in > 2048) && - (height_out < 2048) && - (vinfo->sync_duration_num > - (30 * vinfo->sync_duration_den)) && - (get_cpu_type() != - MESON_CPU_MAJOR_ID_GXTVBB) && - (get_cpu_type() != - MESON_CPU_MAJOR_ID_GXM)) + == 0) || (next_frame_par->nocomp)) + && (height_in > 2048) + && (height_out < 2048) + && (vinfo->sync_duration_num > + (30 * vinfo->sync_duration_den)) + && (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXTVBB) + && (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXM)) return SPEED_CHECK_VSKIP; else return SPEED_CHECK_DONE; @@ -787,8 +784,8 @@ vpp_process_speed_check(s32 width_in, } else if (next_frame_par->hscale_skip_count == 0) { /*TODO vpu */ if (div_u64(VPP_SPEED_FACTOR * width_in * - vinfo->sync_duration_num * height_screen, - vinfo->sync_duration_den * 256) + vinfo->sync_duration_num * height_screen, + vinfo->sync_duration_den * 256) > get_vpu_clk()) return SPEED_CHECK_HSKIP; else @@ -818,8 +815,9 @@ vpp_process_speed_check(s32 width_in, return SPEED_CHECK_VSKIP; } -static void -vpp_set_filters2(u32 process_3d_type, u32 width_in, +static int vpp_set_filters_internal( + struct disp_info_s *input, + u32 width_in, u32 height_in, u32 wid_out, u32 hei_out, @@ -854,35 +852,68 @@ vpp_set_filters2(u32 process_3d_type, u32 width_in, u32 screen_aspect = 0; bool skip_policy_check = true; u32 vskip_step; + s32 video_layer_global_offset_x, video_layer_global_offset_y; + u32 video_source_crop_top, video_source_crop_left; + u32 video_source_crop_bottom, video_source_crop_right; + u32 vpp_zoom_ratio, nonlinear_factor; + u32 speed_check_width, speed_check_height; + s32 video_layer_top, video_layer_left; + s32 video_layer_width, video_layer_height; + u32 cur_custom_ar; +#ifdef TV_REVERSE + bool reverse = false; +#endif + int ret = VppFilter_Success; + u32 vert_chroma_filter; + struct filter_info_s *cur_filter; + s32 vpp_zoom_center_x, vpp_zoom_center_y; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - if (likely(w_in > - (video_source_crop_left + video_source_crop_right))) { - w_in -= video_source_crop_left; - w_in -= video_source_crop_right; - h_crop_enable = true; - } + if (!input) + return VppFilter_Fail; - if (likely(h_in > - (video_source_crop_top + video_source_crop_bottom))) { - h_in -= video_source_crop_top; - h_in -= video_source_crop_bottom; - v_crop_enable = true; - } + cur_filter = &gfilter[input->layer_id]; + cur_custom_ar = input->custom_ar; + vpp_zoom_ratio = input->zoom_ratio; + vpp_zoom_center_x = input->zoom_center_x; + vpp_zoom_center_y = input->zoom_center_y; + speed_check_width = input->speed_check_width; + speed_check_height = input->speed_check_height; + nonlinear_factor = input->nonlinear_factor; + video_layer_global_offset_x = input->global_offset_x; + video_layer_global_offset_y = input->global_offset_y; + + video_layer_top = input->layer_top; + video_layer_left = input->layer_left; + video_layer_width = input->layer_width; + video_layer_height = input->layer_height; +#ifdef TV_REVERSE + reverse = input->reverse; +#endif + + if (vf->type & VIDTYPE_MVC) { + video_source_crop_left = 0; + video_source_crop_right = 0; + video_source_crop_top = 0; + video_source_crop_bottom = 0; } else { - if (likely(w_in > - (video_source_crop_left + video_source_crop_right))) { - w_in -= video_source_crop_left; - w_in -= video_source_crop_right; - h_crop_enable = true; - } + video_source_crop_left = input->crop_left; + video_source_crop_right = input->crop_right; + video_source_crop_top = input->crop_top; + video_source_crop_bottom = input->crop_bottom; + } - if (likely(h_in > - (video_source_crop_top + video_source_crop_bottom))) { - h_in -= video_source_crop_top; - h_in -= video_source_crop_bottom; - v_crop_enable = true; - } + if (likely(w_in > + (video_source_crop_left + video_source_crop_right))) { + w_in -= video_source_crop_left; + w_in -= video_source_crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (video_source_crop_top + video_source_crop_bottom))) { + h_in -= video_source_crop_top; + h_in -= video_source_crop_bottom; + v_crop_enable = true; } #ifndef TV_3D_FUNCTION_OPEN @@ -900,7 +931,7 @@ vpp_set_filters2(u32 process_3d_type, u32 width_in, #ifdef TV_3D_FUNCTION_OPEN else if ((next_frame_par->vpp_3d_mode == VPP_3D_MODE_LA) - && (process_3d_type & MODE_3D_ENABLE)) + && (input->proc_3d_type & MODE_3D_ENABLE)) vskip_step = 2; #endif else @@ -908,6 +939,7 @@ vpp_set_filters2(u32 process_3d_type, u32 width_in, RESTART: aspect_factor = (vpp_flags & VPP_FLAG_AR_MASK) >> VPP_FLAG_AR_BITS; + /* don't use input->wide_mode */ wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; /* keep 8 bits resolution for aspect conversion */ @@ -924,22 +956,22 @@ RESTART: aspect_factor = 0x90; wide_mode = VIDEO_WIDEOPTION_NORMAL; } else if ((wide_mode >= VIDEO_WIDEOPTION_4_3_IGNORE) - && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { + && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { if (aspect_factor != 0xc0) fill_match = false; orig_aspect = aspect_factor; screen_aspect = 0xc0; } else if ((wide_mode >= VIDEO_WIDEOPTION_16_9_IGNORE) - && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { + && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { if (aspect_factor != 0x90) fill_match = false; orig_aspect = aspect_factor; screen_aspect = 0x90; } else if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { - if (custom_ar != 0) - aspect_factor = custom_ar & 0x3ff; + if (cur_custom_ar != 0) + aspect_factor = cur_custom_ar & 0x3ff; wide_mode = VIDEO_WIDEOPTION_NORMAL; } else if (wide_mode == VIDEO_WIDEOPTION_AFD) { if (aspect_factor == 0x90) @@ -964,9 +996,6 @@ RESTART: width_out * h_in * aspect_ratio_out); } - if (osd_layer_preblend) - aspect_factor = 0x100; - height_after_ratio = (h_in * aspect_factor) >> 8; /* @@ -975,43 +1004,28 @@ RESTART: * it will override the input width_out/height_out for * ratio calculations, a.k.a we have a window for video content */ - if (osd_layer_preblend) { - if ((osd_layer_width == 0) || (osd_layer_height == 0)) { - video_top = 0; - video_left = 0; - video_width = width_out; - video_height = height_out; - - } else { - video_top = osd_layer_top; - video_left = osd_layer_left; - video_width = osd_layer_width; - video_height = osd_layer_height; - } + video_top = video_layer_top; + video_left = video_layer_left; + video_width = video_layer_width; + video_height = video_layer_height; + if ((video_top == 0) && (video_left == 0) && (video_width <= 1) + && (video_height <= 1)) { + /* special case to do full screen display */ + video_width = width_out; + video_height = height_out; } else { - video_top = video_layer_top; - video_left = video_layer_left; - video_width = video_layer_width; - video_height = video_layer_height; - if ((video_top == 0) && (video_left == 0) && (video_width <= 1) - && (video_height <= 1)) { - /* special case to do full screen display */ + if ((video_layer_width < 16) + && (video_layer_height < 16)) { + /* + *sanity check to move + *video out when the target size is too small + */ video_width = width_out; video_height = height_out; - } else { - if ((video_layer_width < 16) - && (video_layer_height < 16)) { - /* - *sanity check to move - *video out when the target size is too small - */ - video_width = width_out; - video_height = height_out; - video_left = width_out * 2; - } - video_top += video_layer_global_offset_y; - video_left += video_layer_global_offset_x; + video_left = width_out * 2; } + video_top += video_layer_global_offset_y; + video_left += video_layer_global_offset_x; } /*aspect ratio match */ @@ -1062,8 +1076,7 @@ RESTART: } ratio_x = screen_ratio_x * w_in / video_width; - ratio_y = - screen_ratio_y * h_in / orig_aspect * + ratio_y = screen_ratio_y * h_in / orig_aspect * screen_aspect / video_height; } else { screen_width = video_width * vpp_zoom_ratio / 100; @@ -1082,9 +1095,10 @@ RESTART: ratio_y = (height_after_ratio << 18) / screen_height; if (super_debug) - pr_info("height_after_ratio=%d,%d,%d,%d,%d\n", - height_after_ratio, ratio_x, ratio_y, - aspect_factor, wide_mode); + pr_info("layer%d: height_after_ratio=%d,%d,%d,%d,%d\n", + input->layer_id, + height_after_ratio, ratio_x, ratio_y, + aspect_factor, wide_mode); if (wide_mode == VIDEO_WIDEOPTION_NORMAL) { ratio_x = ratio_y = max(ratio_x, ratio_y); @@ -1125,26 +1139,16 @@ RESTART: ini_vphase = vpp_zoom_center_y & 0xff; /* screen position for source */ -#ifdef TV_REVERSE - start = - video_top + (video_height + 1) / 2 - ((h_in << 17) + - (vpp_zoom_center_y << 10) + - (ratio_y >> 1)) / ratio_y; + start = video_top + (video_height + 1) / 2 - + ((h_in << 17) + + (vpp_zoom_center_y << 10) + + (ratio_y >> 1)) / ratio_y; end = ((h_in << 18) + (ratio_y >> 1)) / ratio_y + start - 1; if (super_debug) - pr_info("top:start =%d,%d,%d,%d %d,%d,%d\n", + pr_info("layer%d: top:start =%d,%d,%d,%d %d,%d,%d\n", + input->layer_id, start, end, video_top, video_height, h_in, ratio_y, vpp_zoom_center_y); -#else - start = - video_top + video_height / 2 - ((h_in << 17) + - (vpp_zoom_center_y << 10)) / ratio_y; - end = (h_in << 18) / ratio_y + start - 1; - if (super_debug) - pr_info("top:start =%d,%d,%d,%d %d,%d,%d\n", - start, end, video_top, - video_height, h_in, ratio_y, vpp_zoom_center_y); -#endif #ifdef TV_REVERSE if (reverse) { @@ -1154,10 +1158,8 @@ RESTART: temp = (-start * ratio_y) >> 18; next_frame_par->VPP_vd_end_lines_ = h_in - 1 - temp; - } else next_frame_par->VPP_vd_end_lines_ = h_in - 1; - } else { if (start < video_top) { temp = ((video_top - start) * ratio_y) >> 18; @@ -1166,8 +1168,7 @@ RESTART: } else next_frame_par->VPP_vd_end_lines_ = h_in - 1; } - temp = - next_frame_par->VPP_vd_end_lines_ - + temp = next_frame_par->VPP_vd_end_lines_ - (video_height * ratio_y >> 18); next_frame_par->VPP_vd_start_lines_ = (temp >= 0) ? temp : 0; } else @@ -1177,7 +1178,6 @@ RESTART: if (start < 0) { temp = (-start * ratio_y) >> 18; next_frame_par->VPP_vd_start_lines_ = temp; - } else next_frame_par->VPP_vd_start_lines_ = 0; temp_height = min((video_top + video_height - 1), @@ -1186,15 +1186,12 @@ RESTART: if (start < video_top) { temp = ((video_top - start) * ratio_y) >> 18; next_frame_par->VPP_vd_start_lines_ = temp; - } else next_frame_par->VPP_vd_start_lines_ = 0; temp_height = min((video_top + video_height - 1), (vinfo->height - 1)) - video_top + 1; } - - temp = - next_frame_par->VPP_vd_start_lines_ + + temp = next_frame_par->VPP_vd_start_lines_ + (temp_height * ratio_y >> 18); next_frame_par->VPP_vd_end_lines_ = (temp <= (h_in - 1)) ? temp : (h_in - 1); @@ -1226,15 +1223,14 @@ RESTART: if (start >= end) { /* nothing to display */ next_frame_par->VPP_vsc_startp = 0; - next_frame_par->VPP_vsc_endp = 0; - } else { next_frame_par->VPP_vsc_startp = - (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? (start >> 1) : start; - + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (start >> 1) : start; next_frame_par->VPP_vsc_endp = - (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? (end >> 1) : end; + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (end >> 1) : end; } /* set filter co-efficients */ @@ -1260,27 +1256,16 @@ RESTART: next_frame_par->VPP_hf_ini_phase_ = vpp_zoom_center_x & 0xff; /* screen position for source */ -#ifdef TV_REVERSE - start = - video_left + (video_width + 1) / 2 - ((w_in << 17) + - (vpp_zoom_center_x << 10) + - (ratio_x >> 1)) / ratio_x; + start = video_left + (video_width + 1) / 2 - ((w_in << 17) + + (vpp_zoom_center_x << 10) + + (ratio_x >> 1)) / ratio_x; end = ((w_in << 18) + (ratio_x >> 1)) / ratio_x + start - 1; if (super_debug) - pr_info("left:start =%d,%d,%d,%d %d,%d,%d\n", + pr_info("layer%d: left:start =%d,%d,%d,%d %d,%d,%d\n", + input->layer_id, start, end, video_left, video_width, w_in, ratio_x, vpp_zoom_center_x); -#else - start = - video_left + video_width / 2 - ((w_in << 17) + - (vpp_zoom_center_x << 10)) / - ratio_x; - end = (w_in << 18) / ratio_x + start - 1; - if (super_debug) - pr_info("left:start =%d,%d,%d,%d %d,%d,%d\n", - start, end, video_left, - video_width, w_in, ratio_x, vpp_zoom_center_x); -#endif + /* calculate source horizontal clip */ #ifdef TV_REVERSE if (reverse) { @@ -1324,8 +1309,7 @@ RESTART: temp_width = min((video_left + video_width - 1), (vinfo->width - 1)) - video_left + 1; } - temp = - next_frame_par->VPP_hd_start_lines_ + + temp = next_frame_par->VPP_hd_start_lines_ + (temp_width * ratio_x >> 18); next_frame_par->VPP_hd_end_lines_ = (temp <= (w_in - 1)) ? temp : (w_in - 1); @@ -1364,9 +1348,10 @@ RESTART: } if ((wide_mode == VIDEO_WIDEOPTION_NONLINEAR) && (end > start)) { - calculate_non_linear_ratio(ratio_x, end - start, - next_frame_par); - + calculate_non_linear_ratio( + nonlinear_factor, + ratio_x, end - start, + next_frame_par); next_frame_par->VPP_hsc_linear_startp = next_frame_par->VPP_hsc_linear_endp = (start + end) / 2; } @@ -1381,6 +1366,7 @@ RESTART: || !next_frame_par->hscale_skip_count) && (!(vpp_flags & VPP_FLAG_VSCALE_DISABLE))) { int skip = vpp_process_speed_check( + input->layer_id, (next_frame_par->VPP_hd_end_lines_ - next_frame_par->VPP_hd_start_lines_ + 1) / (next_frame_par->hscale_skip_count + 1), @@ -1391,6 +1377,8 @@ RESTART: next_frame_par->VPP_vsc_startp + 1), vinfo->height >> ((vpp_flags & VPP_FLAG_INTERLACE_OUT) ? 1 : 0), + speed_check_width, + speed_check_height, next_frame_par, vinfo, vf); @@ -1412,7 +1400,9 @@ RESTART: (vf->canvas0Addr != 0) && (next_frame_par->vscale_skip_count > 1) && (!next_frame_par->nocomp)) { - pr_info("Try DW buffer for compressed frame scaling.\n"); + pr_info( + "layer%d: Try DW buffer for compressed frame scaling.\n", + input->layer_id); /* for VIDTYPE_COMPRESS, check if we can use double write * buffer when primary frame can not be scaled. @@ -1422,7 +1412,6 @@ RESTART: h_in = height_in = vf->height; next_frame_par->hscale_skip_count = 0; next_frame_par->vscale_skip_count = 0; - goto RESTART; } @@ -1457,40 +1446,43 @@ RESTART: /* coeff selection before skip and apply pre_scaler */ filter->vpp_vert_filter = coeff(vert_coeff_settings, - filter->vpp_vsc_start_phase_step * - (next_frame_par->vscale_skip_count + 1), - 1, - ((vf->type_original & VIDTYPE_TYPEMASK) - != VIDTYPE_PROGRESSIVE), - vf->combing_cur_lev); + filter->vpp_vsc_start_phase_step * + (next_frame_par->vscale_skip_count + 1), + 1, + ((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE), + vf->combing_cur_lev); + filter->vpp_vert_coeff = filter_table[filter->vpp_vert_filter]; /* when local interlace or AV or ATV */ /* TODO: add 420 check for local */ if (vert_chroma_filter_force_en || (vert_chroma_filter_en - && (((vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) - && (((vf->type_original & VIDTYPE_TYPEMASK) != VIDTYPE_PROGRESSIVE) || - (vf->height < vert_chroma_filter_limit))) - || (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) - || (vf->source_type == VFRAME_SOURCE_TYPE_TUNER)))) { - cur_vert_chroma_filter - = chroma_filter_table[filter->vpp_vert_filter]; - filter->vpp_vert_chroma_coeff - = filter_table[cur_vert_chroma_filter]; + && (((vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) + && (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) + || (vf->height < vert_chroma_filter_limit))) + || (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) + || (vf->source_type == VFRAME_SOURCE_TYPE_TUNER)))) { + vert_chroma_filter = + chroma_filter_table[filter->vpp_vert_filter]; + filter->vpp_vert_chroma_coeff = + filter_table[vert_chroma_filter]; filter->vpp_vert_chroma_filter_en = true; } else { - cur_vert_chroma_filter = COEF_NULL; + vert_chroma_filter = COEF_NULL; filter->vpp_vert_chroma_filter_en = false; } + /* avoid hscaler fitler adjustion affect on picture shift*/ filter->vpp_horz_filter = coeff(horz_coeff_settings, - filter->vpp_hf_start_phase_step, - next_frame_par->VPP_hf_ini_phase_, - ((vf->type_original & VIDTYPE_TYPEMASK) - != VIDTYPE_PROGRESSIVE), - vf->combing_cur_lev); + filter->vpp_hf_start_phase_step, + next_frame_par->VPP_hf_ini_phase_, + ((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE), + vf->combing_cur_lev); /*for gxl cvbs out index*/ if ((vinfo->mode == VMODE_CVBS) && //DEBUG_TMP (filter->vpp_hf_start_phase_step == (1 << 24))) @@ -1514,9 +1506,8 @@ RESTART: filter->vpp_vsc_start_phase_step >>= 1; ratio_y >>= 1; f2v_get_vertical_phase(ratio_y, ini_vphase, - next_frame_par->VPP_vf_ini_phase_, - vpp_flags & VPP_FLAG_INTERLACE_OUT); - + next_frame_par->VPP_vf_ini_phase_, + vpp_flags & VPP_FLAG_INTERLACE_OUT); } else filter->vpp_pre_vsc_en = 0; @@ -1544,13 +1535,13 @@ RESTART: filter->vpp_vert_filter = vert_scaler_filter; } if (vert_chroma_filter_force_en && - vert_chroma_scaler_filter <= COEF_3D_FILTER) { - cur_vert_chroma_filter = vert_chroma_scaler_filter; - filter->vpp_vert_chroma_coeff - = filter_table[cur_vert_chroma_filter]; - filter->vpp_vert_chroma_filter_en = true; + (vert_chroma_scaler_filter <= COEF_3D_FILTER)) { + vert_chroma_filter = vert_chroma_scaler_filter; + filter->vpp_vert_chroma_coeff = + filter_table[vert_chroma_filter]; + filter->vpp_vert_chroma_filter_en = true; } else { - cur_vert_chroma_filter = COEF_NULL; + vert_chroma_filter = COEF_NULL; filter->vpp_vert_chroma_filter_en = false; } @@ -1559,90 +1550,44 @@ RESTART: filter->vpp_horz_filter = horz_scaler_filter; } -#ifdef TV_3D_FUNCTION_OPEN +#ifdef TV_3D_FUNCTION_OPEN /* final stage for 3D filter overwrite */ if ((next_frame_par->vpp_3d_scale) && force_filter_mode) { filter->vpp_vert_coeff = filter_table[COEF_3D_FILTER]; filter->vpp_vert_filter = COEF_3D_FILTER; } #endif - if ((last_vert_filter != filter->vpp_vert_filter) || - (last_horz_filter != filter->vpp_horz_filter)) { - last_vert_filter = filter->vpp_vert_filter; - last_horz_filter = filter->vpp_horz_filter; - scaler_filter_cnt = 0; + + if ((cur_filter->last_vert_filter != filter->vpp_vert_filter) || + (cur_filter->last_horz_filter != filter->vpp_horz_filter)) { + cur_filter->last_vert_filter = filter->vpp_vert_filter; + cur_filter->last_horz_filter = filter->vpp_horz_filter; + cur_filter->scaler_filter_cnt = 0; } else { - scaler_filter_cnt++; + cur_filter->scaler_filter_cnt++; } - if ((scaler_filter_cnt >= scaler_filter_cnt_limit) && - ((cur_vert_filter != filter->vpp_vert_filter) || - (cur_horz_filter != filter->vpp_horz_filter))) { - video_property_notify(1); - cur_vert_filter = filter->vpp_vert_filter; - cur_horz_filter = filter->vpp_horz_filter; - scaler_filter_cnt = scaler_filter_cnt_limit; + if ((cur_filter->scaler_filter_cnt >= + scaler_filter_cnt_limit) && + ((cur_filter->cur_vert_filter != + filter->vpp_vert_filter) || + (cur_filter->cur_horz_filter != + filter->vpp_horz_filter))) { + cur_filter->cur_vert_filter = filter->vpp_vert_filter; + cur_filter->cur_horz_filter = filter->vpp_horz_filter; + cur_filter->scaler_filter_cnt = scaler_filter_cnt_limit; + ret = VppFilter_Success_and_Changed; } - cur_skip_line = next_frame_par->vscale_skip_count; -#if HAS_VPU_PROT - if (has_vpu_prot()) { - if (get_prot_status()) { - s32 tmp_height = - (((s32) next_frame_par->VPP_vd_end_lines_ + - 1) << 18) / tmp_ratio_y; - s32 tmp_top = 0; - s32 tmp_bottom = 0; - -/* pr_info("height_out %d video_height %d\n", height_out, video_height); */ -/* pr_info("vf1 %d %d %d %d vs %d %d\n", next_frame_par->VPP_hd_start_lines_,*/ -/* next_frame_par->VPP_hd_end_lines_, */ -/* next_frame_par->VPP_vd_start_lines_, next_frame_par->VPP_vd_end_lines_, */ -/* next_frame_par->hscale_skip_count, next_frame_par->vscale_skip_count); */ - if ((s32) video_height > tmp_height) { - tmp_top = (s32) video_top + - (((s32) video_height - tmp_height) >> 1); - } else - tmp_top = (s32) video_top; - tmp_bottom = tmp_top + - (((s32) next_frame_par->VPP_vd_end_lines_ + 1) << 18) / - (s32) tmp_ratio_y; - if (tmp_bottom > (s32) height_out - && tmp_top < (s32) height_out) { - s32 tmp_end = - (s32) next_frame_par->VPP_vd_end_lines_ - - ((tmp_bottom - - (s32) height_out) * - (s32) tmp_ratio_y >> 18); - if (tmp_end < - (s32) next_frame_par->VPP_vd_end_lines_) { - next_frame_par->VPP_vd_end_lines_ = - tmp_end; - } - - } else if (tmp_bottom > (s32) height_out - && tmp_top >= (s32) height_out) - next_frame_par->VPP_vd_end_lines_ = 1; - next_frame_par->VPP_vd_end_lines_ = - next_frame_par->VPP_vd_end_lines_ - - h_in / height_out; - if ((s32) next_frame_par->VPP_vd_end_lines_ < - (s32) next_frame_par->VPP_vd_start_lines_) { - next_frame_par->VPP_vd_end_lines_ = - next_frame_par->VPP_vd_start_lines_; - } - if ((s32) next_frame_par->VPP_hd_end_lines_ < - (s32) next_frame_par->VPP_hd_start_lines_) { - next_frame_par->VPP_hd_end_lines_ = - next_frame_par->VPP_hd_start_lines_; - } -/* pr_info("tmp_top %d tmp_bottom %d tmp_height %d\n",*/ -/* tmp_top, tmp_bottom, tmp_height); */ -/* pr_info("vf2 %d %d %d %d\n", next_frame_par->VPP_hd_start_lines_,*/ -/* next_frame_par->VPP_hd_end_lines_, */ -/* next_frame_par->VPP_vd_start_lines_, next_frame_par->VPP_vd_end_lines_); */ - } + /* store the debug info for legacy */ + if (input->layer_id == 0) { + cur_vert_filter = cur_filter->cur_vert_filter; + cur_horz_filter = cur_filter->cur_horz_filter; + cur_vert_chroma_filter = vert_chroma_filter; + cur_skip_line = + next_frame_par->vscale_skip_count; } -#endif + + return ret; } /* *VPP_SRSHARP0_CTRL:0x1d91 @@ -1650,19 +1595,20 @@ RESTART: *[1]if sharpness is enable or vscaler is enable,must set to 1, *sharpness1;reg can only to be w on gxtvbb;which is fix after txl */ -int vpp_set_super_scaler_regs(int scaler_path_sel, - int reg_srscl0_enable, - int reg_srscl0_hsize, - int reg_srscl0_vsize, - int reg_srscl0_hori_ratio, - int reg_srscl0_vert_ratio, - int reg_srscl1_enable, - int reg_srscl1_hsize, - int reg_srscl1_vsize, - int reg_srscl1_hori_ratio, - int reg_srscl1_vert_ratio, - int vpp_postblend_out_width, - int vpp_postblend_out_height) +int vpp_set_super_scaler_regs( + int scaler_path_sel, + int reg_srscl0_enable, + int reg_srscl0_hsize, + int reg_srscl0_vsize, + int reg_srscl0_hori_ratio, + int reg_srscl0_vert_ratio, + int reg_srscl1_enable, + int reg_srscl1_hsize, + int reg_srscl1_vsize, + int reg_srscl1_hori_ratio, + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height) { int tmp_data = 0; @@ -1673,94 +1619,101 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP0_CTRL); if (sr0_sr1_refresh) { if (reg_srscl0_hsize > SUPER_CORE0_WIDTH_MAX) { - if (((tmp_data >> 1)&0x1) != 0) + if (((tmp_data >> 1) & 0x1) != 0) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 0, 1, 1); } else { - if (((tmp_data >> 1)&0x1) != 1) + if (((tmp_data >> 1) & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 1, 1, 1); } - if ((tmp_data&0x1) != 1) + if ((tmp_data & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 1, 0, 1); } tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP1_CTRL); if (sr0_sr1_refresh) { - if (((tmp_data >> 1)&0x1) != 1) + if (((tmp_data >> 1) & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP1_CTRL, 1, 1, 1); - if ((tmp_data&0x1) != 1) + if ((tmp_data & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP1_CTRL, 1, 0, 1); } /* core0 config */ tmp_data = VSYNC_RD_MPEG_REG( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt); if (sr0_sr1_refresh) { - if (((tmp_data >> 5)&0x1) != (reg_srscl0_vert_ratio&0x1)) + if (((tmp_data >> 5) & 0x1) != (reg_srscl0_vert_ratio&0x1)) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, reg_srscl0_vert_ratio&0x1, 5, 1); - if (((tmp_data >> 4)&0x1) != (reg_srscl0_hori_ratio&0x1)) + if (((tmp_data >> 4) & 0x1) != (reg_srscl0_hori_ratio&0x1)) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, reg_srscl0_hori_ratio&0x1, 4, 1); if (reg_srscl0_hsize > SUPER_CORE0_WIDTH_MAX) { - if (((tmp_data >> 2)&0x1) != 0) + if (((tmp_data >> 2) & 0x1) != 0) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, 0, 2, 1); } else { - if (((tmp_data >> 2)&0x1) != 1) + if (((tmp_data >> 2) & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, 1, 2, 1); } - if ((tmp_data & 0x1) == (reg_srscl0_hori_ratio&0x1)) + if ((tmp_data & 0x1) == (reg_srscl0_hori_ratio & 0x1)) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, - ((~(reg_srscl0_hori_ratio&0x1))&0x1), 0, 1); + ((~(reg_srscl0_hori_ratio & 0x1)) & 0x1), 0, 1); } /* core1 config */ if (sr_support & SUPER_CORE1_SUPPORT) { - if (is_meson_gxtvbb_cpu()) - tmp_data = sharpness1_sr2_ctrl_32d7; - else - tmp_data = VSYNC_RD_MPEG_REG( - SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt2);/*0xc80*/ - if (is_meson_gxtvbb_cpu() || - (((tmp_data >> 5)&0x1) != (reg_srscl1_vert_ratio&0x1)) || - (((tmp_data >> 4)&0x1) != (reg_srscl1_hori_ratio&0x1)) || - ((tmp_data & 0x1) == (reg_srscl1_hori_ratio&0x1)) || - (((tmp_data >> 2)&0x1) != 1)) { - tmp_data = tmp_data & (~(1 << 5)); - tmp_data = tmp_data & (~(1 << 4)); - tmp_data = tmp_data & (~(1 << 2)); - tmp_data = tmp_data & (~(1 << 0)); - tmp_data |= ((reg_srscl1_vert_ratio&0x1) << 5); - tmp_data |= ((reg_srscl1_hori_ratio&0x1) << 4); - tmp_data |= (1 << 2); - tmp_data |= (((~(reg_srscl1_hori_ratio&0x1))&0x1) << 0); - if (sr0_sr1_refresh) { - VSYNC_WR_MPEG_REG( - SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt2,/*0xc80*/ - tmp_data); - sharpness1_sr2_ctrl_32d7 = tmp_data; + if (is_meson_gxtvbb_cpu()) + tmp_data = sharpness1_sr2_ctrl_32d7; + else + tmp_data = VSYNC_RD_MPEG_REG( + SRSHARP1_SHARP_SR2_CTRL + + sr_reg_offt2); /*0xc80*/ + if (is_meson_gxtvbb_cpu() || + (((tmp_data >> 5) & 0x1) != + (reg_srscl1_vert_ratio & 0x1)) || + (((tmp_data >> 4) & 0x1) != + (reg_srscl1_hori_ratio & 0x1)) || + ((tmp_data & 0x1) == + (reg_srscl1_hori_ratio & 0x1)) || + (((tmp_data >> 2) & 0x1) != 1)) { + tmp_data = tmp_data & (~(1 << 5)); + tmp_data = tmp_data & (~(1 << 4)); + tmp_data = tmp_data & (~(1 << 2)); + tmp_data = tmp_data & (~(1 << 0)); + tmp_data |= ((reg_srscl1_vert_ratio & 0x1) << 5); + tmp_data |= ((reg_srscl1_hori_ratio & 0x1) << 4); + tmp_data |= (1 << 2); + tmp_data |= + (((~(reg_srscl1_hori_ratio & 0x1)) & 0x1) << 0); + if (sr0_sr1_refresh) { + VSYNC_WR_MPEG_REG( + SRSHARP1_SHARP_SR2_CTRL + + sr_reg_offt2, /*0xc80*/ + tmp_data); + sharpness1_sr2_ctrl_32d7 = tmp_data; + } } } - } /* size config */ tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | - (reg_srscl0_vsize & 0x1fff); + (reg_srscl0_vsize & 0x1fff); tmp_data2 = VSYNC_RD_MPEG_REG( SRSHARP0_SHARP_HVSIZE + sr_reg_offt); if (tmp_data != tmp_data2) - VSYNC_WR_MPEG_REG(SRSHARP0_SHARP_HVSIZE + sr_reg_offt, - tmp_data); + VSYNC_WR_MPEG_REG( + SRSHARP0_SHARP_HVSIZE + sr_reg_offt, + tmp_data); tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | - (reg_srscl1_vsize & 0x1fff); + (reg_srscl1_vsize & 0x1fff); if (sr_support & SUPER_CORE1_SUPPORT) { if (get_cpu_type() != MESON_CPU_MAJOR_ID_GXTVBB) @@ -1860,9 +1813,11 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, return 0; } -static void vpp_set_super_scaler(const struct vinfo_s *vinfo, - struct vpp_frame_par_s *next_frame_par, - bool bypass_sr0, bool bypass_sr1) +static void vpp_set_super_scaler( + u32 vpp_wide_mode, + const struct vinfo_s *vinfo, + struct vpp_frame_par_s *next_frame_par, + bool bypass_sr0, bool bypass_sr1) { unsigned int hor_sc_multiple_num, ver_sc_multiple_num, temp; u32 width_out = next_frame_par->VPP_hsc_endp - @@ -1889,14 +1844,14 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, /* step1: judge core0&core1 vertical enable or disable*/ if (ver_sc_multiple_num >= 2*SUPER_SCALER_V_FACTOR) { next_frame_par->supsc0_vert_ratio = - ((src_width < SUPER_CORE0_WIDTH_MAX/2) && + ((src_width < SUPER_CORE0_WIDTH_MAX / 2) && (sr_support & SUPER_CORE0_SUPPORT)) ? 1 : 0; next_frame_par->supsc1_vert_ratio = ((width_out < SUPER_CORE1_WIDTH_MAX) && - (src_width < SUPER_CORE1_WIDTH_MAX/2) && + (src_width < SUPER_CORE1_WIDTH_MAX / 2) && (sr_support & SUPER_CORE1_SUPPORT)) ? 1 : 0; if (next_frame_par->supsc0_vert_ratio && - (ver_sc_multiple_num < 4*SUPER_SCALER_V_FACTOR)) + (ver_sc_multiple_num < 4 * SUPER_SCALER_V_FACTOR)) next_frame_par->supsc1_vert_ratio = 0; next_frame_par->supsc0_enable = next_frame_par->supsc0_vert_ratio ? 1 : 0; @@ -1912,15 +1867,15 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, if ((hor_sc_multiple_num >= 2) && (vpp_wide_mode != VIDEO_WIDEOPTION_NONLINEAR)) { if ((src_width > SUPER_CORE0_WIDTH_MAX) || - ((src_width > SUPER_CORE0_WIDTH_MAX/2) && + ((src_width > SUPER_CORE0_WIDTH_MAX / 2) && next_frame_par->supsc0_vert_ratio) || - (((src_width << 1) > SUPER_CORE1_WIDTH_MAX/2) && + (((src_width << 1) > SUPER_CORE1_WIDTH_MAX / 2) && next_frame_par->supsc1_vert_ratio)) next_frame_par->supsc0_hori_ratio = 0; else if (sr_support & SUPER_CORE0_SUPPORT) next_frame_par->supsc0_hori_ratio = 1; if (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX) || - (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX/2) && + (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX / 2) && next_frame_par->supsc1_vert_ratio) || (next_frame_par->supsc0_hori_ratio && (hor_sc_multiple_num < 4))) @@ -1951,7 +1906,7 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, } /* option add patch */ if ((ver_sc_multiple_num <= super_scaler_v_ratio) && - (src_height >= SUPER_CORE0_WIDTH_MAX/2) && + (src_height >= SUPER_CORE0_WIDTH_MAX / 2) && (src_height <= 1088) && (ver_sc_multiple_num > SUPER_SCALER_V_FACTOR) && (vinfo->height >= 2000)) { @@ -2117,7 +2072,7 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, width_out >> next_frame_par->supsc0_hori_ratio; } else if ((next_frame_par->supscl_path == PPS_CORE0_CORE1) || (next_frame_par->supscl_path == - PPS_CORE0_POSTBLEND_CORE1)){/*tl1*/ + PPS_CORE0_POSTBLEND_CORE1)){ /*tl1*/ next_frame_par->spsc0_h_in = (height_out >> next_frame_par->supsc0_vert_ratio) >> next_frame_par->supsc1_vert_ratio; @@ -2181,15 +2136,15 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->supsc1_vert_ratio; } if (super_debug) { - pr_info("spsc0_w_in=%u, spsc0_h_in=%u, spsc1_w_in=%u, spsc1_h_in=%u.\n", + pr_info("layer0: spsc0_w_in=%u, spsc0_h_in=%u, spsc1_w_in=%u, spsc1_h_in=%u.\n", next_frame_par->spsc0_w_in, next_frame_par->spsc0_h_in, next_frame_par->spsc1_w_in, next_frame_par->spsc1_h_in); - pr_info("supsc0_hori=%d,supsc1_hori=%d,supsc0_v=%d,supsc1_v=%d\n", + pr_info("layer0: supsc0_hori=%d,supsc1_hori=%d,supsc0_v=%d,supsc1_v=%d\n", next_frame_par->supsc0_hori_ratio, next_frame_par->supsc1_hori_ratio, next_frame_par->supsc0_vert_ratio, next_frame_par->supsc1_vert_ratio); - pr_info("VPP_hd_start_lines= %d,%d,%d,%d, %d,%d,%d,%d, %d,%d\n", + pr_info("layer0: VPP_hd_start_lines= %d,%d,%d,%d, %d,%d,%d,%d, %d,%d\n", next_frame_par->VPP_hd_start_lines_, next_frame_par->VPP_hd_end_lines_, next_frame_par->VPP_vd_start_lines_, @@ -2202,8 +2157,10 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->VPP_vsc_endp); } } + #ifdef TV_3D_FUNCTION_OPEN -void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) +void get_vpp_3d_mode( + u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) { switch (trans_fmt) { case TVIN_TFMT_3D_LRH_OLOR: @@ -2231,19 +2188,20 @@ void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) break; } } -static void -vpp_get_video_source_size(u32 *src_width, u32 *src_height, + +static void vpp_get_video_source_size( + u32 *src_width, u32 *src_height, u32 process_3d_type, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par) { if ((process_3d_type & MODE_3D_AUTO) || - (((process_3d_type & MODE_3D_TO_2D_R) || - (process_3d_type & MODE_3D_TO_2D_L) || - (process_3d_type & MODE_3D_LR_SWITCH) || - (process_3d_type & MODE_FORCE_3D_TO_2D_TB) || - (process_3d_type & MODE_FORCE_3D_TO_2D_LR)) && - (process_3d_type & MODE_3D_ENABLE))) { + (((process_3d_type & MODE_3D_TO_2D_R) || + (process_3d_type & MODE_3D_TO_2D_L) || + (process_3d_type & MODE_3D_LR_SWITCH) || + (process_3d_type & MODE_FORCE_3D_TO_2D_TB) || + (process_3d_type & MODE_FORCE_3D_TO_2D_LR)) && + (process_3d_type & MODE_3D_ENABLE))) { if (vf->trans_fmt) { if (process_3d_type & MODE_3D_TO_2D_MASK) *src_height = vf->left_eye.height; @@ -2289,7 +2247,7 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, } } else if ((process_3d_type & MODE_3D_LR) || - (process_3d_type & MODE_FORCE_3D_LR)) { + (process_3d_type & MODE_FORCE_3D_LR)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; if (process_3d_type & MODE_3D_TO_2D_MASK) { *src_width = vf->width >> 1; @@ -2305,7 +2263,7 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, } } else if ((process_3d_type & MODE_3D_TB) || - (process_3d_type & MODE_FORCE_3D_TB)) { + (process_3d_type & MODE_FORCE_3D_TB)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; if (process_3d_type & MODE_3D_TO_2D_MASK) { *src_width = vf->width; @@ -2344,12 +2302,11 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, next_frame_par->vpp_3d_scale = 0; } } else if ((process_3d_type & MODE_3D_FA) - || (process_3d_type & MODE_FORCE_3D_FA_LR) - || (process_3d_type & MODE_FORCE_3D_FA_TB)) { + || (process_3d_type & MODE_FORCE_3D_FA_LR) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; if (process_3d_type & MODE_3D_TO_2D_MASK) { - if (process_3d_type & MODE_FORCE_3D_FA_TB) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; *src_width = vf->width; @@ -2414,8 +2371,408 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, } } #endif -void -vpp_set_filters(u32 process_3d_type, u32 wide_mode, + +static int vpp_set_filters_no_scaler_internal( + struct disp_info_s *input, + u32 width_in, + u32 height_in, + u32 wid_out, + u32 hei_out, + const struct vinfo_s *vinfo, + u32 vpp_flags, + struct vpp_frame_par_s *next_frame_par, struct vframe_s *vf) +{ + s32 start, end; + s32 video_top, video_left, temp; + u32 video_width, video_height; + u32 ratio_x = 0; + u32 ratio_y = 0; + u32 ratio_tmp = 0; + int temp_width; + int temp_height; + struct vppfilter_mode_s *filter = &next_frame_par->vpp_filter; + u32 wide_mode; + s32 height_shift = 0; + u32 w_in = width_in; + u32 h_in = height_in; + bool h_crop_enable = false, v_crop_enable = false; + bool skip_policy_check = true; + u32 vskip_step; + s32 video_layer_global_offset_x, video_layer_global_offset_y; + u32 video_source_crop_top, video_source_crop_left; + u32 video_source_crop_bottom, video_source_crop_right; + s32 video_layer_top, video_layer_left; + s32 video_layer_width, video_layer_height; +#ifdef TV_REVERSE + bool reverse = false; +#endif + int ret = VppFilter_Success; + + if (!input) + return VppFilter_Fail; + + video_layer_global_offset_x = input->global_offset_x; + video_layer_global_offset_y = input->global_offset_y; + + video_layer_top = input->layer_top; + video_layer_left = input->layer_left; + video_layer_width = input->layer_width; + video_layer_height = input->layer_height; +#ifdef TV_REVERSE + reverse = input->reverse; +#endif + + if (vf->type & VIDTYPE_MVC) { + video_source_crop_left = 0; + video_source_crop_right = 0; + video_source_crop_top = 0; + video_source_crop_bottom = 0; + } else { + video_source_crop_left = input->crop_left; + video_source_crop_right = input->crop_right; + video_source_crop_top = input->crop_top; + video_source_crop_bottom = input->crop_bottom; + } + + if (likely(w_in > + (video_source_crop_left + video_source_crop_right))) { + w_in -= video_source_crop_left; + w_in -= video_source_crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (video_source_crop_top + video_source_crop_bottom))) { + h_in -= video_source_crop_top; + h_in -= video_source_crop_bottom; + v_crop_enable = true; + } + + next_frame_par->vscale_skip_count = 0; + next_frame_par->hscale_skip_count = 0; + next_frame_par->nocomp = false; + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->vscale_skip_count++; + if (vpp_flags & VPP_FLAG_INTERLACE_OUT) + height_shift++; + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + vskip_step = 2; + else + vskip_step = 1; + +RESTART: + /* don't use input->wide_mode */ + wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + + /* + *if we have ever set a cropped display area for video layer + * (by checking video_layer_width/video_height), then + * it will override the input width_out/height_out for + * ratio calculations, a.k.a we have a window for video content + */ + video_top = video_layer_top; + video_left = video_layer_left; + video_width = video_layer_width; + video_height = video_layer_height; + if ((video_top == 0) && (video_left == 0) && (video_width <= 1) + && (video_height <= 1)) { + /* special case to do full screen display */ + video_width = video_layer_width; + video_height = video_layer_height; + } else { + video_top += video_layer_global_offset_y; + video_left += video_layer_global_offset_x; + } + + ratio_x = (1 << 18); + ratio_y = (1 << 18); + + /* screen position for source */ + start = video_top + (video_height + 1) / 2 - + ((h_in << 17) + + (ratio_y >> 1)) / ratio_y; + end = ((h_in << 18) + (ratio_y >> 1)) / ratio_y + start - 1; + if (super_debug) + pr_info("layer%d: top:start =%d,%d,%d,%d %d,%d\n", + input->layer_id, + start, end, video_top, + video_height, h_in, ratio_y); + +#ifdef TV_REVERSE + if (reverse) { + /* calculate source vertical clip */ + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } + temp = next_frame_par->VPP_vd_end_lines_ - + (video_height * ratio_y >> 18); + next_frame_par->VPP_vd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)); + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)) - video_top + 1; + } + temp = next_frame_par->VPP_vd_start_lines_ + + (temp_height * ratio_y >> 18); + next_frame_par->VPP_vd_end_lines_ = + (temp <= (h_in - 1)) ? temp : (h_in - 1); + } + + if (v_crop_enable) { + next_frame_par->VPP_vd_start_lines_ += video_source_crop_top; + next_frame_par->VPP_vd_end_lines_ += video_source_crop_top; + } + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->VPP_vd_start_lines_ &= ~1; + + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_pic_in_height_ / + (next_frame_par->vscale_skip_count + 1); + /* + *find overlapped region between + *[start, end], [0, height_out-1], + *[video_top, video_top+video_height-1] + */ + start = max(start, max(0, video_top)); + end = min(end, min((s32)(vinfo->height - 1), + (s32)(video_top + video_height - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_vsc_startp = 0; + next_frame_par->VPP_vsc_endp = 0; + } else { + next_frame_par->VPP_vsc_startp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (start >> 1) : start; + next_frame_par->VPP_vsc_endp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (end >> 1) : end; + } + + /* set filter co-efficients */ + ratio_y <<= height_shift; + ratio_tmp = ratio_y / (next_frame_par->vscale_skip_count + 1); + ratio_y = ratio_tmp; + + filter->vpp_vsc_start_phase_step = 0x1000000; + + /* horizontal */ + filter->vpp_hf_start_phase_slope = 0; + filter->vpp_hf_end_phase_slope = 0; + filter->vpp_hf_start_phase_step = 0x1000000; + + next_frame_par->VPP_hsc_linear_startp = next_frame_par->VPP_hsc_startp; + next_frame_par->VPP_hsc_linear_endp = next_frame_par->VPP_hsc_endp; + + filter->vpp_hsc_start_phase_step = 0x1000000; + next_frame_par->VPP_hf_ini_phase_ = 0; + + /* screen position for source */ + start = video_left + (video_width + 1) / 2 - + ((w_in << 17) + (ratio_x >> 1)) / ratio_x; + end = ((w_in << 18) + (ratio_x >> 1)) / ratio_x + start - 1; + if (super_debug) + pr_info("layer%d: left:start =%d,%d,%d,%d %d,%d\n", + input->layer_id, + start, end, video_left, + video_width, w_in, ratio_x); + + /* calculate source horizontal clip */ +#ifdef TV_REVERSE + if (reverse) { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } + temp = next_frame_par->VPP_hd_end_lines_ - + (video_width * ratio_x >> 18); + next_frame_par->VPP_hd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)); + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)) - video_left + 1; + } + temp = next_frame_par->VPP_hd_start_lines_ + + (temp_width * ratio_x >> 18); + next_frame_par->VPP_hd_end_lines_ = + (temp <= (w_in - 1)) ? temp : (w_in - 1); + } + + if (h_crop_enable) { + next_frame_par->VPP_hd_start_lines_ += video_source_crop_left; + next_frame_par->VPP_hd_end_lines_ += video_source_crop_left; + } + + next_frame_par->VPP_line_in_length_ = + next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + /* + *find overlapped region between + * [start, end], [0, width_out-1], + * [video_left, video_left+video_width-1] + */ + start = max(start, max(0, video_left)); + end = min(end, + min((s32)(vinfo->width - 1), + (s32)(video_left + video_width - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_hsc_startp = 0; + next_frame_par->VPP_hsc_endp = 0; + /* avoid mif set wrong or di out size overflow */ + next_frame_par->VPP_hd_start_lines_ = 0; + next_frame_par->VPP_hd_end_lines_ = 0; + next_frame_par->VPP_line_in_length_ = 0; + } else { + next_frame_par->VPP_hsc_startp = start; + next_frame_par->VPP_hsc_endp = end; + } + + /* + *check the painful bandwidth limitation and see + * if we need skip half resolution on source side for progressive + * frames. + */ + /* check vskip and hskip */ + if (((next_frame_par->vscale_skip_count < MAX_VSKIP_COUNT) + || !next_frame_par->hscale_skip_count) + && (!(vpp_flags & VPP_FLAG_VSCALE_DISABLE))) { + int skip = SPEED_CHECK_DONE; + + if (skip == SPEED_CHECK_VSKIP) { + u32 next_vskip = + next_frame_par->vscale_skip_count + vskip_step; + + if (next_vskip <= MAX_VSKIP_COUNT) { + next_frame_par->vscale_skip_count = next_vskip; + goto RESTART; + } else + next_frame_par->hscale_skip_count = 1; + } else if (skip == SPEED_CHECK_HSKIP) + next_frame_par->hscale_skip_count = 1; + } + + if ((vf->type & VIDTYPE_COMPRESS) && + (vf->canvas0Addr != 0) && + (next_frame_par->vscale_skip_count > 1) && + (!next_frame_par->nocomp)) { + pr_info( + "layer%d: Try DW buffer for compressed frame scaling.\n", + input->layer_id); + + /* for VIDTYPE_COMPRESS, check if we can use double write + * buffer when primary frame can not be scaled. + */ + next_frame_par->nocomp = true; + w_in = width_in = vf->width; + h_in = height_in = vf->height; + next_frame_par->hscale_skip_count = 0; + next_frame_par->vscale_skip_count = 0; + goto RESTART; + } + + if ((skip_policy & 0xf0) && (skip_policy_check == true)) { + skip_policy_check = false; + if (skip_policy & 0x40) { + next_frame_par->vscale_skip_count = skip_policy & 0xf; + goto RESTART; + } else if (skip_policy & 0x80) { + if ((((vf->width >= 4096) && + (!(vf->type & VIDTYPE_COMPRESS))) || + (vf->flag & VFRAME_FLAG_HIGH_BANDWIDTH)) + && (next_frame_par->vscale_skip_count == 0)) { + next_frame_par->vscale_skip_count = + skip_policy & 0xf; + goto RESTART; + } + } + } + + next_frame_par->video_input_h = next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->video_input_h = next_frame_par->video_input_h / + (next_frame_par->vscale_skip_count + 1); + next_frame_par->video_input_w = next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + next_frame_par->video_input_w = next_frame_par->video_input_w / + (next_frame_par->hscale_skip_count + 1); + + filter->vpp_hsc_start_phase_step = 0x1000000; + + /* apply line skip */ + if (next_frame_par->hscale_skip_count) { + filter->vpp_hf_start_phase_step >>= 1; + filter->vpp_hsc_start_phase_step >>= 1; + next_frame_par->VPP_line_in_length_ >>= 1; + } + + return ret; +} + +int vpp_set_filters( + struct disp_info_s *input, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo, @@ -2425,9 +2782,22 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, u32 src_height = 0; u32 vpp_flags = 0; u32 aspect_ratio = 0; + u32 process_3d_type; + u32 wide_mode; + int ret = VppFilter_Fail; + struct disp_info_s local_input; + + if (!input) + return ret; WARN_ON(vinfo == NULL); + /* use local var to avoid the input data be overwriten */ + memcpy(&local_input, input, sizeof(struct disp_info_s)); + + process_3d_type = local_input.proc_3d_type; + wide_mode = local_input.wide_mode; + next_frame_par->VPP_post_blend_vd_v_start_ = 0; next_frame_par->VPP_post_blend_vd_h_start_ = 0; @@ -2455,9 +2825,10 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, next_frame_par->vpp_3d_scale = 0; } next_frame_par->trans_fmt = vf->trans_fmt; - get_vpp_3d_mode(process_3d_type, next_frame_par->trans_fmt, + get_vpp_3d_mode(process_3d_type, + next_frame_par->trans_fmt, &next_frame_par->vpp_3d_mode); - if (vpp_3d_scale) + if (local_input.vpp_3d_scale) next_frame_par->vpp_3d_scale = 1; amlog_mask(LOG_MASK_VPP, "%s: src_width %u,src_height %u.\n", __func__, src_width, src_height); @@ -2500,42 +2871,39 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, src_height = vf->height; } #endif - if (vf->type & VIDTYPE_MVC) { - video_source_crop_top = 0; - video_source_crop_left = 0; - video_source_crop_bottom = 0; - video_source_crop_right = 0; - } else { - video_source_crop_top = video_crop_top_resv; - video_source_crop_left = video_crop_left_resv; - video_source_crop_bottom = video_crop_bottom_resv; - video_source_crop_right = video_crop_right_resv; - } if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) && !disable_adapted) { if (vf->pic_mode.screen_mode != 0xff) wide_mode = vf->pic_mode.screen_mode; - if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { - /* from wss, need add global setting */ - video_source_crop_top += vf->pic_mode.vs; - video_source_crop_left += vf->pic_mode.hs; - video_source_crop_bottom += vf->pic_mode.ve; - video_source_crop_right += vf->pic_mode.he; - } else { - /* from PQ database, final setting */ - video_source_crop_top = vf->pic_mode.vs; - video_source_crop_left = vf->pic_mode.hs; - video_source_crop_bottom = vf->pic_mode.ve; - video_source_crop_right = vf->pic_mode.he; - } + if (vf->pic_mode.AFD_enable && (vf->ratio_control & DISP_RATIO_INFOFRAME_AVAIL)) wide_mode = VIDEO_WIDEOPTION_AFD; - if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) - custom_ar = vf->pic_mode.custom_ar; + if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { + if (!custom_ar) + local_input.custom_ar = custom_ar; + else + local_input.custom_ar = + vf->pic_mode.custom_ar; + } + if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { + /* from wss, need add global setting */ + local_input.crop_top += vf->pic_mode.vs; + local_input.crop_left += vf->pic_mode.hs; + local_input.crop_bottom += vf->pic_mode.ve; + local_input.crop_right += vf->pic_mode.he; + } else { + /* from PQ database, final setting */ + local_input.crop_top = vf->pic_mode.vs; + local_input.crop_left = vf->pic_mode.hs; + local_input.crop_bottom = vf->pic_mode.ve; + local_input.crop_right = vf->pic_mode.he; + } } - vpp_wide_mode = wide_mode; + + /* don't restore the wide mode */ + /* input->wide_mode = wide_mode; */ vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); if (vinfo->field_height != vinfo->height) @@ -2544,193 +2912,136 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; - vpp_set_filters2(process_3d_type, src_width, src_height, + + ret = vpp_set_filters_internal( + &local_input, src_width, src_height, vinfo->width, vinfo->height, vinfo, vpp_flags, next_frame_par, vf); + /*config super scaler after set next_frame_par is calc ok for pps*/ - vpp_set_super_scaler(vinfo, next_frame_par, - (bypass_sr | bypass_spscl0), - (bypass_sr | bypass_spscl1)); + if (local_input.layer_id == 0) + vpp_set_super_scaler( + wide_mode, + vinfo, next_frame_par, + (bypass_sr | bypass_spscl0), + (bypass_sr | bypass_spscl1)); + return ret; } -void prot_get_parameter(u32 wide_mode, - struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo) +int vpp_set_filters_no_scaler( + struct disp_info_s *input, + struct vframe_s *vf, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo) { u32 src_width = 0; u32 src_height = 0; u32 vpp_flags = 0; u32 aspect_ratio = 0; - u32 process_3d_type = VPP_3D_MODE_NULL; + u32 wide_mode; + int ret = VppFilter_Fail; + struct disp_info_s local_input; + + if (!input) + return ret; WARN_ON(vinfo == NULL); + /* use local var to avoid the input data be overwriten */ + memcpy(&local_input, input, sizeof(struct disp_info_s)); + /* wide_mode = local_input.wide_mode; */ + wide_mode = VIDEO_WIDEOPTION_NORMAL; next_frame_par->VPP_post_blend_vd_v_start_ = 0; next_frame_par->VPP_post_blend_vd_h_start_ = 0; next_frame_par->VPP_postproc_misc_ = 0x200; - - /* check force ratio change flag in display buffer also - * if it exist then it will override the settings in display side - */ - if (vf->ratio_control & DISP_RATIO_FORCECONFIG) { - if ((vf->ratio_control & DISP_RATIO_CTRL_MASK) == - DISP_RATIO_KEEPRATIO) { - if (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) - wide_mode = VIDEO_WIDEOPTION_NORMAL; - } else { - if (wide_mode == VIDEO_WIDEOPTION_NORMAL) - wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; - } - if (vf->ratio_control & DISP_RATIO_FORCE_NORMALWIDE) - wide_mode = VIDEO_WIDEOPTION_NORMAL; - else if (vf->ratio_control & DISP_RATIO_FORCE_FULL_STRETCH) - wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; + next_frame_par->vscale_skip_count = 0; + next_frame_par->hscale_skip_count = 0; + if (vf->type & VIDTYPE_COMPRESS) { + src_width = vf->compWidth; + src_height = vf->compHeight; + } else { + src_width = vf->width; + src_height = vf->height; } - - aspect_ratio = (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) - >> DISP_RATIO_ASPECT_RATIO_BIT; +#ifdef TV_3D_FUNCTION_OPEN + next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 0; + next_frame_par->trans_fmt = vf->trans_fmt; +#endif if (vf->type & VIDTYPE_INTERLACE) vpp_flags = VPP_FLAG_INTERLACE_IN; - if (vf->ratio_control & DISP_RATIO_PORTRAIT_MODE) - vpp_flags |= VPP_FLAG_PORTRAIT_MODE; + if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) + && !disable_adapted) { + if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { + /* from wss, need add global setting */ + local_input.crop_top += vf->pic_mode.vs; + local_input.crop_left += vf->pic_mode.hs; + local_input.crop_bottom += vf->pic_mode.ve; + local_input.crop_right += vf->pic_mode.he; + } else { + /* from PQ database, final setting */ + local_input.crop_top = vf->pic_mode.vs; + local_input.crop_left = vf->pic_mode.hs; + local_input.crop_bottom = vf->pic_mode.ve; + local_input.crop_right = vf->pic_mode.he; + } + } - if (vf->type & VIDTYPE_VSCALE_DISABLE) - vpp_flags |= VPP_FLAG_VSCALE_DISABLE; + aspect_ratio = + (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) + >> DISP_RATIO_ASPECT_RATIO_BIT; - src_width = vf->width; - src_height = vf->height; - - vpp_wide_mode = wide_mode; + /* don't restore the wide mode */ + /* input->wide_mode = wide_mode; */ vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); if (vinfo->field_height != vinfo->height) vpp_flags |= VPP_FLAG_INTERLACE_OUT; - next_frame_par->VPP_post_blend_vd_v_end_ = - vinfo->field_height - 1; - next_frame_par->VPP_post_blend_vd_h_end_ = - vinfo->width - 1; + next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; + next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; - vpp_set_filters2(process_3d_type, src_width, src_height, - vinfo->width, vinfo->height, - vinfo, vpp_flags, next_frame_par, vf); + ret = vpp_set_filters_no_scaler_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); + return ret; } - -void vpp_set_osd_layer_preblend(u32 *enable) -{ - osd_layer_preblend = *enable; -} - -void vpp_set_osd_layer_position(s32 *para) -{ - if (IS_ERR_OR_NULL(¶[3])) { - pr_info("para[3] is null\n"); - return; - } - if (para[2] < 2 || para[3] < 2) - return; - - osd_layer_left = para[0]; - osd_layer_top = para[1]; - osd_layer_width = para[2]; - osd_layer_height = para[3]; -} - -void vpp_set_video_source_crop(u32 t, u32 l, u32 b, u32 r) -{ - video_crop_top_resv = t; - video_crop_left_resv = l; - video_crop_bottom_resv = b; - video_crop_right_resv = r; -} - -void vpp_get_video_source_crop(u32 *t, u32 *l, u32 *b, u32 *r) -{ - *t = video_crop_top_resv; - *l = video_crop_left_resv; - *b = video_crop_bottom_resv; - *r = video_crop_right_resv; -} - -void vpp_set_video_layer_position(s32 x, s32 y, s32 w, s32 h) -{ - if ((w < 0) || (h < 0)) - return; - - video_layer_left = x; - video_layer_top = y; - video_layer_width = w; - video_layer_height = h; -} - -void vpp_get_video_layer_position(s32 *x, s32 *y, s32 *w, s32 *h) -{ - *x = video_layer_left; - *y = video_layer_top; - *w = video_layer_width; - *h = video_layer_height; -} - -void vpp_set_global_offset(s32 x, s32 y) -{ - video_layer_global_offset_x = x; - video_layer_global_offset_y = y; -} - -void vpp_get_global_offset(s32 *x, s32 *y) -{ - *x = video_layer_global_offset_x; - *y = video_layer_global_offset_y; -} - -s32 vpp_set_nonlinear_factor(u32 f) +s32 vpp_set_nonlinear_factor( + struct disp_info_s *info, u32 f) { if (f < MAX_NONLINEAR_FACTOR) { - nonlinear_factor = f; + info->nonlinear_factor = f; return 0; } return -1; } -u32 vpp_get_nonlinear_factor(void) +u32 vpp_get_nonlinear_factor( + struct disp_info_s *info) { - return nonlinear_factor; + return info->nonlinear_factor; } -void vpp_set_zoom_ratio(u32 r) +void vpp_disp_info_init( + struct disp_info_s *info, u8 id) { - vpp_zoom_ratio = r; + if (info) { + memset(info, 0, sizeof(struct disp_info_s)); + info->nonlinear_factor = MAX_NONLINEAR_FACTOR / 2; + info->zoom_ratio = 100; + info->speed_check_width = 1800; + info->speed_check_height = 1400; + info->layer_id = id; + memset(&gfilter[id], 0, sizeof(struct filter_info_s)); + } } -u32 vpp_get_zoom_ratio(void) -{ - return vpp_zoom_ratio; -} - -void vpp_set_video_speed_check(u32 h, u32 w) -{ - video_speed_check_height = h; - video_speed_check_width = w; -} - -void vpp_get_video_speed_check(u32 *h, u32 *w) -{ - *h = video_speed_check_height; - *w = video_speed_check_width; -} - -#ifdef TV_3D_FUNCTION_OPEN -void vpp_set_3d_scale(bool enable) -{ - vpp_3d_scale = enable; -} -#endif - void vpp_super_scaler_support(void) { if (is_meson_gxlx_cpu()) { diff --git a/include/linux/amlogic/media/registers/regs/vpp_regs.h b/include/linux/amlogic/media/registers/regs/vpp_regs.h index 7daba0912eb6..b59bc6ca27ff 100644 --- a/include/linux/amlogic/media/registers/regs/vpp_regs.h +++ b/include/linux/amlogic/media/registers/regs/vpp_regs.h @@ -245,6 +245,9 @@ #define OSD1_BLEND_SRC_CTRL 0x1dfd #define OSD2_BLEND_SRC_CTRL 0x1dfe +#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968 +#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969 + /* after g12b */ #define SRSHARP0_SHARP_SYNC_CTRL 0x3eb0 #define SRSHARP1_SHARP_SYNC_CTRL 0x3fb0 diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index 5b44f40ec3b6..d845ae174179 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -91,6 +91,31 @@ #define AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT _IOW((_A_M), 0x22, int) #define AMSTREAM_IOC_GET_VIDEO_LAYER1_ON _IOR((_A_M), 0x23, int) +#define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT _IOR((_A_M), 0x2b, int) +#define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT _IOW((_A_M), 0x2c, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_DISABLE _IOR((_A_M), 0x2d, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_DISABLE _IOW((_A_M), 0x2e, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_AXIS _IOR((_A_M), 0x2f, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_AXIS _IOW((_A_M), 0x30, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_CROP _IOR((_A_M), 0x31, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_CROP _IOW((_A_M), 0x32, int) +#define AMSTREAM_IOC_GET_PIP_SCREEN_MODE _IOR((_A_M), 0x33, int) +#define AMSTREAM_IOC_SET_PIP_SCREEN_MODE _IOW((_A_M), 0x34, int) +#define AMSTREAM_IOC_GET_PIP_ZORDER _IOW((_A_M), 0x35, unsigned int) +#define AMSTREAM_IOC_SET_PIP_ZORDER _IOW((_A_M), 0x36, unsigned int) + +#define AMSTREAM_IOC_GET_ZORDER _IOW((_A_M), 0x37, unsigned int) +#define AMSTREAM_IOC_SET_ZORDER _IOW((_A_M), 0x38, unsigned int) + +#define AMSTREAM_IOC_QUERY_LAYER _IOW((_A_M), 0x39, unsigned int) +#define AMSTREAM_IOC_ALLOC_LAYER _IOW((_A_M), 0x3a, unsigned int) +#define AMSTREAM_IOC_FREE_LAYER _IOW((_A_M), 0x3b, unsigned int) + +/* VPP.3D IOCTL command list^M */ +#define AMSTREAM_IOC_SET_3D_TYPE _IOW((_A_M), 0x3c, unsigned int) +#define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) +#define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) + #define AMSTREAM_IOC_APTS _IOR((_A_M), 0x40, int) #define AMSTREAM_IOC_VPTS _IOR((_A_M), 0x41, int) #define AMSTREAM_IOC_PCRSCR _IOR((_A_M), 0x42, int) @@ -108,11 +133,6 @@ #define AMSTREAM_IOC_SET_VIDEO_CROP _IOW((_A_M), 0x4e, int) #define AMSTREAM_IOC_PCRID _IOW((_A_M), 0x4f, int) -/* VPP.3D IOCTL command list^M */ -#define AMSTREAM_IOC_SET_3D_TYPE _IOW((_A_M), 0x3c, unsigned int) -#define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) -#define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) - #define AMSTREAM_IOC_SUB_NUM _IOR((_A_M), 0x50, int) #define AMSTREAM_IOC_SUB_INFO _IOR((_A_M), 0x51, int) #define AMSTREAM_IOC_GET_BLACKOUT_POLICY _IOR((_A_M), 0x52, int) diff --git a/include/linux/amlogic/media/vfm/vframe_receiver.h b/include/linux/amlogic/media/vfm/vframe_receiver.h index eac4cd806c30..74ed8487f554 100644 --- a/include/linux/amlogic/media/vfm/vframe_receiver.h +++ b/include/linux/amlogic/media/vfm/vframe_receiver.h @@ -39,6 +39,7 @@ #define VFRAME_EVENT_PROVIDER_FR_HINT 13 #define VFRAME_EVENT_PROVIDER_FR_END_HINT 14 #define VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO 15 +#define VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED 16 enum receviver_start_e { RECEIVER_STATE_NULL = -1, diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 548fcea8d7fa..8ef253825495 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -17,7 +17,19 @@ #ifndef VIDEO_H #define VIDEO_H -#include "vpp.h" + +#define MAX_VD_LAYERS 2 + +#define LAYER1_BUSY (1 << 11) +#define LAYER1_AFBC (1 << 10) +#define LAYER1_SCALER (1 << 9) +#define LAYER1_AVAIL (1 << 8) +#define LAYER0_BUSY (1 << 3) +#define LAYER0_AFBC (1 << 2) +#define LAYER0_SCALER (1 << 1) +#define LAYER0_AVAIL (1 << 0) + +#define LAYER_BITS_SHFIT 8 enum { VIDEO_WIDEOPTION_NORMAL = 0, @@ -39,16 +51,6 @@ enum { VIDEO_WIDEOPTION_MAX = 16 }; -extern bool pre_scaler_en; -extern bool super_scaler; -#define VIDEO_NOTIFY_TRICK_WAIT 0x01 -#define VIDEO_NOTIFY_PROVIDER_GET 0x02 -#define VIDEO_NOTIFY_PROVIDER_PUT 0x04 -#define VIDEO_NOTIFY_FRAME_WAIT 0x08 -#define VIDEO_NOTIFY_POS_CHANGED 0x10 - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - /* TODO: move to register headers */ #define VPP_VADJ2_BLMINUS_EN (1 << 3) #define VPP_VADJ2_EN (1 << 2) @@ -160,7 +162,7 @@ extern bool super_scaler; #define VPP_PHASECTL_TYPE_INTERLACE (1<<16) #define VPP_PHASECTL_VSL0B (1<<15) #define VPP_PHASECTL_DOUBLELINE_BIT 17 -#define VPP_PHASECTL_DOUBLELINE_WID 1 +#define VPP_PHASECTL_DOUBLELINE_WID 2 #define VPP_PHASECTL_INIRPTNUM_MASK 0x3 #define VPP_PHASECTL_INIRPTNUM_WID 2 #define VPP_PHASECTL_INIRPTNUMB_BIT 13 @@ -207,11 +209,7 @@ extern bool super_scaler; #define VPP_FORCE_FIELD_BOTTOM (1 << 16) #define VPP_FOURCE_GO_FIELD (1 << 15) #define VPP_FOURCE_GO_LINE (1 << 14) -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ #define VPP_OFIFO_SIZE_WID 13 -#else -#define VPP_OFIFO_SIZE_WID 12 -#endif /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ #define VPP_OFIFO_SIZE_MASK 0xfff #define VPP_OFIFO_SIZE_BIT 0 @@ -226,44 +224,6 @@ extern bool super_scaler; #define VPP_COEF_INDEX_MASK 0x7f #define VPP_COEF_INDEX_BIT 0 -#define P_VFIFO2VD_LINE_TOP_START P_ENCP_VFIFO2VD_LINE_TOP_START -#endif - -#if 0 /* MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8 */ -#define READ_VCBUS_REG(r) READ_CBUS_REG(r) -#define WRITE_VCBUS_REG(r, val) WRITE_CBUS_REG(r, val) -#define WRITE_VCBUS_REG_BITS(r, val, from, size) \ - WRITE_CBUS_REG_BITS(r, val, from, size) -#define SET_VCBUS_REG_MASK(r, mask) SET_CBUS_REG_MASK(r, mask) -#define CLEAR_VCBUS_REG_MASK(r, mask) CLEAR_CBUS_REG_MASK(r, mask) -#endif - -#ifdef CONFIG_CLK81_DFS -extern int check_and_set_clk81(void); -#endif - -#ifdef CONFIG_GAMMA_PROC -extern int gamma_adjust(void); -#endif -#ifdef CONFIG_SCREEN_ON_EARLY -extern void osd_resume_early(void); -extern void vout_pll_resume_early(void); -extern void resume_vout_early(void); -extern int power_key_pressed; -#endif - -#ifdef CONFIG_AM_VIDEO2 -extern void set_clone_frame_rate(unsigned int frame_rate, unsigned int delay); -#endif -extern struct vframe_provider_s *vf_get_provider_by_name( - const char *provider_name); - -extern void prot_get_parameter(u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo); -u32 get_blackout_policy(void); -int get_video0_frame_info(struct vframe_s *vf); - #define AMVIDEO_UPDATE_OSD_MODE 0x00000001 #ifdef CONFIG_AMLOGIC_MEDIA_VIDEO int amvideo_notifier_call_chain(unsigned long val, void *v); @@ -275,8 +235,11 @@ static inline int amvideo_notifier_call_chain(unsigned long val, void *v) #endif int query_video_status(int type, int *value); -int get_video0_frame_info(struct vframe_s *vf); -struct device *get_video_device(void); +u32 set_blackout_policy(int policy); +u32 get_blackout_policy(void); +void set_video_angle(u32 s_value); +u32 get_video_angle(void); extern unsigned int DI_POST_REG_RD(unsigned int addr); extern int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len); + #endif /* VIDEO_H */ diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index 8f2c7db79ec9..62ee86a70ae9 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -17,8 +17,13 @@ #ifndef VPP_H #define VPP_H + #include -#include + +#define TV_3D_FUNCTION_OPEN +#define TV_REVERSE + +extern bool super_scaler; #define VPP_FLAG_WIDEMODE_MASK 0x0000000F #define VPP_FLAG_INTERLACE_OUT 0x00000010 @@ -43,6 +48,12 @@ #define SPEED_CHECK_HSKIP 1 #define SPEED_CHECK_VSKIP 2 +enum vppfilter_state_e { + VppFilter_Fail = -1, + VppFilter_Success = 0, + VppFilter_Success_and_Changed, +}; + enum f2v_vphase_type_e { F2V_IT2IT = 0, F2V_IB2IB, @@ -54,7 +65,7 @@ enum f2v_vphase_type_e { F2V_IB2P, F2V_P2P, F2V_TYPE_MAX -}; /* frame to video conversion type */ +}; /* frame to video conversion type */ struct f2v_vphase_s { s8 repeat_skip; @@ -142,21 +153,34 @@ struct vpp_frame_par_s { }; -#if 1 +struct disp_info_s { + u8 layer_id; -/* - *(MESON_CPU_TYPE==MESON_CPU_TYPE_MESON6TV)|| - *(MESON_CPU_TYPE==MESON_CPU_TYPE_MESONG9TV) - */ -#define TV_3D_FUNCTION_OPEN -#endif + u32 angle; + u32 custom_ar; -#define TV_REVERSE + bool reverse; + u32 proc_3d_type; + bool vpp_3d_scale; + u32 nonlinear_factor; -#ifdef TV_REVERSE -extern bool reverse; -#endif -extern bool platform_type; + u32 wide_mode; + u32 zoom_ratio; + s32 zoom_center_x; + s32 zoom_center_y; + s32 layer_top; + s32 layer_left; + s32 layer_width; + s32 layer_height; + u32 crop_top; + u32 crop_left; + u32 crop_bottom; + u32 crop_right; + s32 global_offset_x; + s32 global_offset_y; + u32 speed_check_width; + u32 speed_check_height; +}; enum select_scaler_path_e { CORE0_PPS_CORE1 = 0, /*CORE0_PPS_CORE1_POSTBLEND*/ @@ -187,7 +211,6 @@ enum select_scaler_path_e { #ifdef TV_3D_FUNCTION_OPEN - /*cmd use for 3d operation*/ #define MODE_3D_DISABLE 0x00000000 #define MODE_3D_ENABLE 0x00000001 @@ -222,11 +245,16 @@ enum select_scaler_path_e { #define MODE_3D_OUT_FA_MASK \ (MODE_3D_OUT_FA_L_FIRST | \ - MODE_3D_OUT_FA_R_FIRST|MODE_3D_OUT_FA_LB_FIRST|MODE_3D_OUT_FA_RB_FIRST) + MODE_3D_OUT_FA_R_FIRST | \ + MODE_3D_OUT_FA_LB_FIRST | \ + MODE_3D_OUT_FA_RB_FIRST) #define MODE_3D_TO_2D_MASK \ - (MODE_3D_TO_2D_L|MODE_3D_TO_2D_R|MODE_3D_OUT_FA_MASK | \ - MODE_FORCE_3D_TO_2D_LR | MODE_FORCE_3D_TO_2D_TB) + (MODE_3D_TO_2D_L | \ + MODE_3D_TO_2D_R | \ + MODE_3D_OUT_FA_MASK | \ + MODE_FORCE_3D_TO_2D_LR | \ + MODE_FORCE_3D_TO_2D_TB) #define VPP_3D_MODE_NULL 0x0 #define VPP_3D_MODE_LR 0x1 @@ -240,78 +268,49 @@ enum select_scaler_path_e { #define VPP_PIC0_FIRST 0x0 #define VPP_PIC1_FIRST 0x8 -extern -void vpp_set_3d_scale(bool enable); -extern -void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode); +extern void get_vpp_3d_mode(u32 process_3d_type, + u32 trans_fmt, u32 *vpp_3d_mode); #endif -extern void -vpp_set_filters(u32 process_3d_type, u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo, - bool bypass_sr); +extern int vpp_set_filters( + struct disp_info_s *input, + struct vframe_s *vf, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo, + bool bypass_sr); -extern void vpp_set_video_source_crop(u32 t, u32 l, u32 b, u32 r); +extern int vpp_set_filters_no_scaler( + struct disp_info_s *input, + struct vframe_s *vf, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo); -extern void vpp_get_video_source_crop(u32 *t, u32 *l, u32 *b, u32 *r); +extern s32 vpp_set_nonlinear_factor( + struct disp_info_s *info, u32 f); -extern void vpp_set_video_layer_position(s32 x, s32 y, s32 w, s32 h); +extern u32 vpp_get_nonlinear_factor( + struct disp_info_s *info); -extern void vpp_get_video_layer_position(s32 *x, s32 *y, s32 *w, s32 *h); - -extern void vpp_set_global_offset(s32 x, s32 y); - -extern void vpp_get_global_offset(s32 *x, s32 *y); - -extern void vpp_set_zoom_ratio(u32 r); - -extern u32 vpp_get_zoom_ratio(void); - -extern void vpp_set_osd_layer_preblend(u32 *enable); - -extern void vpp_set_osd_layer_position(s32 *para); - -extern s32 vpp_set_nonlinear_factor(u32 f); - -extern u32 vpp_get_nonlinear_factor(void); - -extern void vpp_set_video_speed_check(u32 h, u32 w); - -extern void vpp_get_video_speed_check(u32 *h, u32 *w); +extern void vpp_disp_info_init( + struct disp_info_s *info, u8 id); extern void vpp_super_scaler_support(void); extern void vpp_bypass_ratio_config(void); -#ifdef CONFIG_AM_VIDEO2 -extern void -vpp2_set_filters(u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo); - -extern void vpp2_set_video_layer_position(s32 x, s32 y, s32 w, s32 h); - -extern void vpp2_get_video_layer_position(s32 *x, s32 *y, s32 *w, s32 *h); - -extern void vpp2_set_zoom_ratio(u32 r); - -extern u32 vpp2_get_zoom_ratio(void); -#endif -extern int video_property_notify(int flag); - -extern int vpp_set_super_scaler_regs(int scaler_path_sel, - int reg_srscl0_enable, - int reg_srscl0_hsize, - int reg_srscl0_vsize, - int reg_srscl0_hori_ratio, - int reg_srscl0_vert_ratio, - int reg_srscl1_enable, - int reg_srscl1_hsize, - int reg_srscl1_vsize, - int reg_srscl1_hori_ratio, - int reg_srscl1_vert_ratio, - int vpp_postblend_out_width, - int vpp_postblend_out_height); +extern int vpp_set_super_scaler_regs( + int scaler_path_sel, + int reg_srscl0_enable, + int reg_srscl0_hsize, + int reg_srscl0_vsize, + int reg_srscl0_hori_ratio, + int reg_srscl0_vert_ratio, + int reg_srscl1_enable, + int reg_srscl1_hsize, + int reg_srscl1_vsize, + int reg_srscl1_hori_ratio, + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height); #endif /* VPP_H */ From 5e154f5a29b3e409a7c8d90f03782f70e1a93398 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 18 Jan 2019 03:25:21 +0800 Subject: [PATCH 0016/1060] vpp: add osd and video zorder control [2/6] PD#SWPL-85 Problem: Upper layer need control osd and video layer zorder Solution: 1.Add video layer zorder interface by sysfs and ioctl 2.Switch the osd and video layer order in vsync Verify: Verify on U212 Change-Id: Ic50e81784b865cc57e4ab9a63d74806f7a8721cf Signed-off-by: Brian Zhu --- drivers/amlogic/media/osd/osd_backup.c | 6 +- drivers/amlogic/media/osd/osd_hw.c | 58 ++++-- drivers/amlogic/media/osd/osd_hw.h | 1 + drivers/amlogic/media/video_sink/video.c | 207 +++++++++++++++++-- include/linux/amlogic/media/video_sink/vpp.h | 4 + 5 files changed, 233 insertions(+), 43 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_backup.c b/drivers/amlogic/media/osd/osd_backup.c index 64d9cd965f87..9ad324fe651a 100644 --- a/drivers/amlogic/media/osd/osd_backup.c +++ b/drivers/amlogic/media/osd/osd_backup.c @@ -1538,7 +1538,11 @@ static s32 get_recovery_item_g12a(u32 addr, u32 *value, u32 *mask) u32 regmask = table->mask; u32 real_value = osd_reg_read(addr); - if ((real_value & regmask) + if (enable_vd_zorder && + (addr == OSD2_BLEND_SRC_CTRL)) { + ret = 1; + table->recovery = 0; + } else if ((real_value & regmask) == (table->val & regmask)) { ret = 1; *mask = regmask; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index ff8cdeafb87a..90ff468756a2 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -447,6 +447,10 @@ static unsigned int supsend_delay; module_param(supsend_delay, uint, 0664); MODULE_PARM_DESC(supsend_delay, "supsend_delay"); +int enable_vd_zorder = 1; +MODULE_PARM_DESC(enable_vd_zorder, "\n enable_vd_zorder\n"); +module_param(enable_vd_zorder, uint, 0664); + static int vsync_enter_line_max; static int vsync_exit_line_max; static int vsync_line_threshold = 950; @@ -4955,14 +4959,16 @@ static void osd_update_enable(u32 index) if (osd_hw.enable[index] == ENABLE) postbld_src_sel = (index == 0) ? 3 : 4; if (index == 0) - VSYNCOSD_WR_MPEG_REG(OSD1_BLEND_SRC_CTRL, + VSYNCOSD_WR_MPEG_REG( + OSD1_BLEND_SRC_CTRL, (0 & 0xf) << 0 | (0 & 0x1) << 4 | (postbld_src_sel & 0xf) << 8 | (0 & 0x1) << 16| (1 & 0x1) << 20); - else if (index == 1) - VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL, + else if ((index == 1) && (!enable_vd_zorder)) + VSYNCOSD_WR_MPEG_REG( + OSD2_BLEND_SRC_CTRL, (0 & 0xf) << 0 | (0 & 0x1) << 4 | (postbld_src_sel & 0xf) << 8 | @@ -7245,12 +7251,15 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) (0 << 16) | (1 & 0x1) << 20); /* vpp osd2 blend ctrl */ - VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL, - (0 & 0xf) << 0 | - (0 & 0x1) << 4 | - (blend_reg->postbld_src4_sel & 0xf) << 8 | - (0 << 16) | - (1 & 0x1) << 20); + if (!enable_vd_zorder) + VSYNCOSD_WR_MPEG_REG( + OSD2_BLEND_SRC_CTRL, + (0 & 0xf) << 0 | + (0 & 0x1) << 4 | + (blend_reg->postbld_src4_sel & 0xf) + << 8 | + (0 << 16) | + (1 & 0x1) << 20); VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE, blend_reg->osd_blend_blend0_size); @@ -7531,12 +7540,16 @@ static void osd_setting_default_hwc(void) (postbld_osd1_premult & 0x1) << 16| (1 & 0x1) << 20); /* vpp osd2 blend ctrl */ - VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL, - (0 & 0xf) << 0 | - (0 & 0x1) << 4 | - (postbld_src4_sel & 0xf) << 8 | - (postbld_osd2_premult & 0x1) << 16 | - (1 & 0x1) << 20); + if (!enable_vd_zorder) + VSYNCOSD_WR_MPEG_REG( + OSD2_BLEND_SRC_CTRL, + (0 & 0xf) << 0 | + (0 & 0x1) << 4 | + (postbld_src4_sel & 0xf) + << 8 | + (postbld_osd2_premult & 0x1) + << 16 | + (1 & 0x1) << 20); /* Do later: different format select different dummy_data */ /* used default dummy data */ @@ -9027,15 +9040,19 @@ void osd_suspend_hw(void) osd_reg_read(VIU_OSD_BLEND_CTRL); osd_hw.reg_status_save1 = osd_reg_read(OSD1_BLEND_SRC_CTRL); - osd_hw.reg_status_save2 = - osd_reg_read(OSD2_BLEND_SRC_CTRL); + osd_hw.reg_status_save3 = osd_reg_read(VPP_RDARB_REQEN_SLV); osd_hw.reg_status_save4 = osd_reg_read(VPU_MAFBC_SURFACE_CFG); osd_reg_clr_mask(VIU_OSD_BLEND_CTRL, 0xf0000); osd_reg_clr_mask(OSD1_BLEND_SRC_CTRL, 0xf0f); - osd_reg_clr_mask(OSD2_BLEND_SRC_CTRL, 0xf0f); + if (!enable_vd_zorder) { + osd_hw.reg_status_save2 = + osd_reg_read(OSD2_BLEND_SRC_CTRL); + osd_reg_clr_mask( + OSD2_BLEND_SRC_CTRL, 0xf0f); + } osd_reg_clr_mask(VPP_RDARB_REQEN_SLV, rdarb_reqen_slv); osd_reg_write(VPU_MAFBC_SURFACE_CFG, 0); @@ -9090,8 +9107,9 @@ void osd_resume_hw(void) osd_hw.reg_status_save); osd_reg_write(OSD1_BLEND_SRC_CTRL, osd_hw.reg_status_save1); - osd_reg_write(OSD2_BLEND_SRC_CTRL, - osd_hw.reg_status_save2); + if (!enable_vd_zorder) + osd_reg_write(OSD2_BLEND_SRC_CTRL, + osd_hw.reg_status_save2); osd_reg_write(VPP_RDARB_REQEN_SLV, osd_hw.reg_status_save3); osd_reg_write(VPU_MAFBC_SURFACE_CFG, diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index 61c14dc12b84..874c97813387 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -30,6 +30,7 @@ extern int int_viu_vsync; extern int int_viu2_vsync; extern struct hw_para_s osd_hw; +extern int enable_vd_zorder; #ifdef CONFIG_HIBERNATION extern void osd_freeze_hw(void); diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 8cbff548b8a5..18cd54c1d4e5 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -410,6 +410,8 @@ static u32 layer_cap; static struct disp_info_s glayer_info[MAX_VD_LAYERS]; +static u32 reference_zorder = 128; + #define MAX_ZOOM_RATIO 300 #define VPP_PREBLEND_VD_V_END_LIMIT 2304 @@ -5864,6 +5866,45 @@ void set_hdr_to_frame(struct vframe_s *vf) } #endif +static int vpp_zorder_check(void) +{ + int force_flush = 0; + u32 layer0_sel = 0; /* vd1 */ + u32 layer1_sel = 1; /* vd2 */ + + if (legacy_vpp) + return 0; + + if (glayer_info[1].zorder < glayer_info[0].zorder) { + layer0_sel = 1; + layer1_sel = 0; + if ((glayer_info[0].zorder >= reference_zorder) + && (glayer_info[1].zorder < reference_zorder)) + layer0_sel++; + } else { + layer0_sel = 0; + layer1_sel = 1; + if ((glayer_info[1].zorder >= reference_zorder) + && (glayer_info[0].zorder < reference_zorder)) + layer1_sel++; + } + + glayer_info[0].cur_sel_port = layer0_sel; + glayer_info[1].cur_sel_port = layer1_sel; + + if ((glayer_info[0].cur_sel_port != + glayer_info[0].last_sel_port) || + (glayer_info[1].cur_sel_port != + glayer_info[1].last_sel_port)) { + force_flush = 1; + glayer_info[0].last_sel_port = + glayer_info[0].cur_sel_port; + glayer_info[1].last_sel_port = + glayer_info[1].cur_sel_port; + } + return force_flush; +} + #ifdef FIQ_VSYNC void vsync_fisr_in(void) #else @@ -7410,6 +7451,7 @@ SET_FILTER: if (!legacy_vpp) { u32 set_value = 0; + int force_flush = vpp_zorder_check(); vpp_misc_set &= ((1 << 29) | VPP_CM_ENABLE | @@ -7439,31 +7481,60 @@ SET_FILTER: VPP_PREBLEND_EN | VPP_POSTBLEND_EN | 0xf); - if (vpp_misc_set != vpp_misc_save) { - /* vd1 need always enable pre bld */ - if (vpp_misc_set & VPP_VD1_POSTBLEND) - set_value = - ((1 << 16) | /* post bld premult*/ - (1 << 8) | /* post src */ - (1 << 4) | /* pre bld premult*/ - (1 << 0)); /* pre bld src 1 */ - VSYNC_WR_MPEG_REG( - VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, - set_value); + if ((vpp_misc_set != vpp_misc_save) + || force_flush) { + u32 port_val[3] = {0, 0, 0}; + u32 vd1_port, vd2_port, icnt; + u32 post_blend_reg[3] = { + VD1_BLEND_SRC_CTRL, + VD2_BLEND_SRC_CTRL, + OSD2_BLEND_SRC_CTRL + }; - set_value = 0; + /* just reset the select port */ + if ((glayer_info[0].cur_sel_port > 2) + || (glayer_info[1].cur_sel_port > 2)) { + glayer_info[0].cur_sel_port = 0; + glayer_info[1].cur_sel_port = 1; + } + + vd1_port = glayer_info[0].cur_sel_port; + vd2_port = glayer_info[1].cur_sel_port; + + /* post bld premult*/ + port_val[0] |= (1 << 16); + + /* vd2 path sel */ if (vpp_misc_set & VPP_VD2_POSTBLEND) - set_value = - ((1 << 20) | - (0 << 16) | /* post bld premult*/ - (2 << 8)); /* post src */ + port_val[1] |= (1 << 20); + else + port_val[1] &= ~(1 << 20); + + /* osd2 path sel */ + port_val[2] |= (1 << 20); + + if (vpp_misc_set & VPP_VD1_POSTBLEND) { + /* post src */ + port_val[vd1_port] |= (1 << 8); + port_val[0] |= + ((1 << 4) | /* pre bld premult*/ + (1 << 0)); /* pre bld src 1 */ + } else + port_val[0] &= ~0xff; + + if (vpp_misc_set & VPP_VD2_POSTBLEND) + /* post src */ + port_val[vd2_port] |= (2 << 8); else if (vpp_misc_set & VPP_VD2_PREBLEND) - set_value = + port_val[1] |= ((1 << 4) | /* pre bld premult*/ (2 << 0)); /* pre bld src 1 */ - VSYNC_WR_MPEG_REG( - VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, - set_value); + + for (icnt = 0; icnt < 3; icnt++) + VSYNC_WR_MPEG_REG( + post_blend_reg[icnt] + + cur_dev->vpp_off, + port_val[icnt]); set_value = vpp_misc_set; set_value &= @@ -8935,10 +9006,26 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_GET_PIP_ZORDER: case AMSTREAM_IOC_GET_ZORDER: + put_user(layer->zorder, (u32 __user *)argp); break; case AMSTREAM_IOC_SET_PIP_ZORDER: - case AMSTREAM_IOC_SET_ZORDER: + case AMSTREAM_IOC_SET_ZORDER:{ + u32 zorder, new_prop = 0; + + if (copy_from_user(&zorder, argp, sizeof(u32)) == 0) { + if (layer->zorder != zorder) + new_prop = 1; + layer->zorder = zorder; + if ((layer->layer_id == 0) && new_prop) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if ((layer->layer_id == 1) && new_prop) + pip_property_changed = 1; +#endif + } else + ret = -EFAULT; + } break; case AMSTREAM_IOC_QUERY_LAYER: @@ -10937,6 +11024,36 @@ static ssize_t video_inuse_store(struct class *class, return count; } +static ssize_t video_zorder_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[0]; + + return sprintf(buf, "%d\n", layer->zorder); +} + +static ssize_t video_zorder_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int zorder; + int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; + + ret = kstrtoint(buf, 0, &zorder); + if (ret < 0) + return -EINVAL; + + if (zorder != layer->zorder) { + layer->zorder = zorder; + video_property_changed = 1; + } + return count; +} + #ifdef VIDEO_PIP static int _videopip_set_disable(u32 val) { @@ -11032,7 +11149,6 @@ static ssize_t videopip_disable_store( struct class_attribute *attr, const char *buf, size_t count) { - int r; int val; @@ -11138,6 +11254,36 @@ static ssize_t videopip_global_output_store( return count; } +static ssize_t videopip_zorder_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[1]; + + return sprintf(buf, "%d\n", layer->zorder); +} + +static ssize_t videopip_zorder_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int zorder; + int ret = 0; + struct disp_info_s *layer = &glayer_info[1]; + + ret = kstrtoint(buf, 0, &zorder); + if (ret < 0) + return -EINVAL; + + if (zorder != layer->zorder) { + layer->zorder = zorder; + pip_property_changed = 1; + } + return count; +} + static ssize_t videopip_state_show( struct class *cla, struct class_attribute *attr, @@ -11401,6 +11547,10 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, video_inuse_show, video_inuse_store), + __ATTR(video_zorder, + 0664, + video_zorder_show, + video_zorder_store), __ATTR_RO(frame_addr), __ATTR_RO(frame_canvas_width), __ATTR_RO(frame_canvas_height), @@ -11439,6 +11589,10 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, videopip_global_output_show, videopip_global_output_store), + __ATTR(videopip_zorder, + 0664, + videopip_zorder_show, + videopip_zorder_store), __ATTR_RO(videopip_state), #endif __ATTR_NULL @@ -11899,6 +12053,8 @@ static int __init video_early_init(void) WRITE_VCBUS_REG( VPP_POST_BLEND_DUMMY_ALPHA, 0x7fffffff); + WRITE_VCBUS_REG_BITS( + VPP_MISC1, 0x100, 0, 9); } if (is_meson_tl1_cpu()) { /* force bypass dolby for TL1, no dolby function */ @@ -12167,9 +12323,13 @@ static int __init video_init(void) goto err5; } + /* make vd1 below vd2 */ for (i = 0; i < MAX_VD_LAYERS; i++) { vpp_disp_info_init(&glayer_info[i], i); glayer_info[i].wide_mode = 1; + glayer_info[i].zorder = reference_zorder - 2 + i; + glayer_info[i].cur_sel_port = i; + glayer_info[i].last_sel_port = i; } if (legacy_vpp) @@ -12463,6 +12623,9 @@ module_param(toggle_count, uint, 0664); MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n"); module_param(vpp_hold_line, uint, 0664); +MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n"); +module_param(reference_zorder, uint, 0664); + MODULE_DESCRIPTION("AMLOGIC video output driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Yao "); diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index 62ee86a70ae9..577c5bb561dc 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -180,6 +180,10 @@ struct disp_info_s { s32 global_offset_y; u32 speed_check_width; u32 speed_check_height; + + u32 zorder; + u32 cur_sel_port; + u32 last_sel_port; }; enum select_scaler_path_e { From bb32e6440c701f025c2c8e46448cc711cd6bc3eb Mon Sep 17 00:00:00 2001 From: jintao xu Date: Wed, 16 Jan 2019 10:14:49 +0800 Subject: [PATCH 0017/1060] omx: add two layer support [3/6] PD#SWPL-85 Problem: Need support two video layers feature Solution: 1: Add videosync. 2: amlvideo support multi-instance Verify: U212 Change-Id: I3570fad361ba5bd388dd46c51a66da056fa7a1fd Signed-off-by: jintao xu Signed-off-by: Luan Yuan Conflicts: MAINTAINERS drivers/amlogic/media/deinterlace/deinterlace_hw.c --- MAINTAINERS | 8 + arch/arm/configs/meson64_a32_defconfig | 1 + arch/arm64/configs/meson64_defconfig | 1 + .../arm64/configs/meson64_smarthome_defconfig | 1 + .../media/deinterlace/deinterlace_hw.c | 6 +- drivers/amlogic/media/video_processor/Kconfig | 2 +- .../amlogic/media/video_processor/Makefile | 1 + .../video_processor/video_dev/amlvideo.c | 33 +- .../media/video_processor/videosync/Kconfig | 11 + .../media/video_processor/videosync/Makefile | 3 + .../media/video_processor/videosync/vfp.h | 112 ++ .../video_processor/videosync/videosync.c | 1249 +++++++++++++++++ .../video_processor/videosync/videosync.h | 141 ++ drivers/amlogic/media/video_sink/video.c | 2 + include/linux/amlogic/major.h | 1 + .../linux/amlogic/media/video_sink/video.h | 2 +- 16 files changed, 1556 insertions(+), 18 deletions(-) create mode 100644 drivers/amlogic/media/video_processor/videosync/Kconfig create mode 100644 drivers/amlogic/media/video_processor/videosync/Makefile create mode 100644 drivers/amlogic/media/video_processor/videosync/vfp.h create mode 100644 drivers/amlogic/media/video_processor/videosync/videosync.c create mode 100644 drivers/amlogic/media/video_processor/videosync/videosync.h diff --git a/MAINTAINERS b/MAINTAINERS index a37b89cfa903..f63a2fd700d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14743,6 +14743,14 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c F: drivers/amlogic/media/common/vfm/vfm.c F: include/linux/amlogic/media/camera/* +AMLOGIC VIDEOSYNC +M: Jintao Xu +F: drivers/amlogic/media/video_processor/videosync/Kconfig +F: drivers/amlogic/media/video_processor/videosync/Makefile +F: drivers/amlogic/media/video_processor/videosync/vfp.h +F: drivers/amlogic/media/video_processor/videosync/videosync.h +F: drivers/amlogic/media/video_processor/videosync/videosync.c + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 9cb58f83311c..8f2827140c23 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -321,6 +321,7 @@ CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER=y CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_PIC_DEC=y +CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 2391a66e7af7..233545a5ca92 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -317,6 +317,7 @@ CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER=y CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_PIC_DEC=y +CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y diff --git a/arch/arm64/configs/meson64_smarthome_defconfig b/arch/arm64/configs/meson64_smarthome_defconfig index 4493f96cc2b9..4434cfd8a44c 100644 --- a/arch/arm64/configs/meson64_smarthome_defconfig +++ b/arch/arm64/configs/meson64_smarthome_defconfig @@ -280,6 +280,7 @@ CONFIG_AMLOGIC_POST_PROCESS_MANAGER=y CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER=y CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y +CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 31b8fefd460a..86e93e26b528 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -972,9 +972,9 @@ bool afbc_is_supported(void) /*currently support txlx and g12a*/ if (is_meson_txlx_cpu() - || is_meson_g12a_cpu()) - ret = true; - + || is_meson_g12a_cpu() + /*|| is_meson_tl1_cpu()*/) + ret = false; return ret; } diff --git a/drivers/amlogic/media/video_processor/Kconfig b/drivers/amlogic/media/video_processor/Kconfig index e86e8eb2b8e9..ef42224d59d8 100644 --- a/drivers/amlogic/media/video_processor/Kconfig +++ b/drivers/amlogic/media/video_processor/Kconfig @@ -17,7 +17,7 @@ source "drivers/amlogic/media/video_processor/video_dev/Kconfig" source "drivers/amlogic/media/video_processor/ppmgr/Kconfig" source "drivers/amlogic/media/video_processor/ionvideo/Kconfig" source "drivers/amlogic/media/video_processor/pic_dev/Kconfig" - +source "drivers/amlogic/media/video_processor/videosync/Kconfig" endif endmenu diff --git a/drivers/amlogic/media/video_processor/Makefile b/drivers/amlogic/media/video_processor/Makefile index 53464584c7d2..354b2478a554 100644 --- a/drivers/amlogic/media/video_processor/Makefile +++ b/drivers/amlogic/media/video_processor/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_AMLOGIC_V4L_VIDEO2) += video_dev/ obj-$(CONFIG_AMLOGIC_POST_PROCESS_MANAGER) += ppmgr/ obj-$(CONFIG_AMLOGIC_IONVIDEO) += ionvideo/ obj-$(CONFIG_AMLOGIC_PIC_DEC) += pic_dev/ +obj-$(CONFIG_AMLOGIC_VIDEOSYNC) += videosync/ \ No newline at end of file diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo.c index 252fa95fed95..35fac2ada33e 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo.c @@ -70,6 +70,8 @@ AMLVIDEO_MINOR_VERSION, AMLVIDEO_RELEASE) #define RECEIVER_NAME "amlvideo" #define PROVIDER_NAME "amlvideo" +#define RECEIVER_NAME_PIP "aml_video" +#define PROVIDER_NAME_PIP "aml_video" #define AMLVIDEO_POOL_SIZE 16 /*extern bool omx_secret_mode;*/ @@ -82,11 +84,12 @@ MODULE_AUTHOR("amlogic-sh"); MODULE_LICENSE("GPL"); /* static u32 vpts_remainder; */ static unsigned int video_nr_base = 10; +static unsigned int video_nr_base_second = 23; /* module_param(video_nr_base, uint, 0644); */ /* MODULE_PARM_DESC(video_nr_base, "videoX start number, 10 is defaut"); */ #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -static unsigned int n_devs = 1; +static unsigned int n_devs = 2; #else static unsigned int n_devs = 1; #endif @@ -887,7 +890,10 @@ static int __init amlvideo_create_instance(int inst) vfd->dev_debug = debug; vfd->v4l2_dev = &dev->v4l2_dev; dev->amlvideo_v4l_num = inst * 10 + video_nr_base; - + if (inst == 0) + dev->amlvideo_v4l_num = video_nr_base; + else + dev->amlvideo_v4l_num = (inst - 1) + video_nr_base_second; /* //////////////////////////////////////// */ /* vfd->v4l2_dev = &dev->v4l2_dev; */ /* //////////////////////////////////////// */ @@ -898,18 +904,19 @@ static int __init amlvideo_create_instance(int inst) goto rel_vdev; dev->inst = inst; -#if 0 - snprintf(dev->vf_receiver_name, AMLVIDEO_VF_NAME_SIZE, - (0) ? RECEIVER_NAME : RECEIVER_NAME ".%x", - inst & 0xff); - snprintf(dev->vf_provider_name, AMLVIDEO_VF_NAME_SIZE, - (0) ? PROVIDER_NAME : PROVIDER_NAME ".%x", - inst & 0xff); -#else - memcpy(dev->vf_receiver_name, RECEIVER_NAME, sizeof(RECEIVER_NAME)); - memcpy(dev->vf_provider_name, PROVIDER_NAME, sizeof(PROVIDER_NAME)); -#endif + if (inst != 0) { + snprintf(dev->vf_receiver_name, AMLVIDEO_VF_NAME_SIZE, + RECEIVER_NAME_PIP ".%x", inst & 0xff); + + snprintf(dev->vf_provider_name, AMLVIDEO_VF_NAME_SIZE, + PROVIDER_NAME_PIP ".%x", inst & 0xff); + } else { + memcpy(dev->vf_receiver_name, RECEIVER_NAME, + sizeof(RECEIVER_NAME)); + memcpy(dev->vf_provider_name, PROVIDER_NAME, + sizeof(PROVIDER_NAME)); + } vf_receiver_init(&dev->video_vf_recv, dev->vf_receiver_name, diff --git a/drivers/amlogic/media/video_processor/videosync/Kconfig b/drivers/amlogic/media/video_processor/videosync/Kconfig new file mode 100644 index 000000000000..cfaead140a94 --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/Kconfig @@ -0,0 +1,11 @@ +menu "Amlogic videosync support" + +config AMLOGIC_VIDEOSYNC + tristate "amlogic videosync device support" + select VIDEO_DEV + default n + + ---help--- + Select to enable "Amlogic videosync support. + +endmenu diff --git a/drivers/amlogic/media/video_processor/videosync/Makefile b/drivers/amlogic/media/video_processor/videosync/Makefile new file mode 100644 index 000000000000..072e532f09a2 --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/Makefile @@ -0,0 +1,3 @@ +asflags-y=-mfloat-abi=softfp -mfpu=neon + +obj-$(CONFIG_AMLOGIC_VIDEOSYNC) += videosync.o diff --git a/drivers/amlogic/media/video_processor/videosync/vfp.h b/drivers/amlogic/media/video_processor/videosync/vfp.h new file mode 100644 index 000000000000..4460d320d22e --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/vfp.h @@ -0,0 +1,112 @@ +/* + * drivers/amlogic/media/video_processor/videosync/vfp.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __VFP_H_ +#define __VFP_H_ + +struct vfq_s { + int rp; + int wp; + int size; + int pre_rp; + int pre_wp; + struct vframe_s **pool; +}; + +static inline void vfq_lookup_start(struct vfq_s *q) +{ + q->pre_rp = q->rp; + q->pre_wp = q->wp; +} +static inline void vfq_lookup_end(struct vfq_s *q) +{ + q->rp = q->pre_rp; + q->wp = q->pre_wp; +} + +static inline void vfq_init(struct vfq_s *q, u32 size, struct vframe_s **pool) +{ + q->rp = q->wp = 0; + q->size = size; + q->pool = pool; +} + +static inline bool vfq_empty(struct vfq_s *q) +{ + return q->rp == q->wp; +} + +static inline bool vfq_full(struct vfq_s *q) +{ + bool ret = (((q->wp+1) % q->size) == q->rp); + return ret; +} + +static inline void vfq_push(struct vfq_s *q, struct vframe_s *vf) +{ + int wp = q->wp; + + /*ToDo*/ + smp_mb(); + + q->pool[wp] = vf; + + /*ToDo*/ + smp_wmb(); + + q->wp = (wp == (q->size - 1)) ? 0 : (wp + 1); +} + +static inline struct vframe_s *vfq_pop(struct vfq_s *q) +{ + struct vframe_s *vf; + int rp; + + if (vfq_empty(q)) + return NULL; + + rp = q->rp; + + /*ToDo*/ + smp_rmb(); + + vf = q->pool[rp]; + + /*ToDo*/ + smp_mb(); + + q->rp = (rp == (q->size - 1)) ? 0 : (rp + 1); + + return vf; +} + +static inline struct vframe_s *vfq_peek(struct vfq_s *q) +{ + return (vfq_empty(q)) ? NULL : q->pool[q->rp]; +} + +static inline int vfq_level(struct vfq_s *q) +{ + int level = q->wp - q->rp; + + if (level < 0) + level += q->size; + + return level; +} + +#endif /* __VFP_H_ */ diff --git a/drivers/amlogic/media/video_processor/videosync/videosync.c b/drivers/amlogic/media/video_processor/videosync/videosync.c new file mode 100644 index 000000000000..af95be662d22 --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/videosync.c @@ -0,0 +1,1249 @@ +/* + * drivers/amlogic/media/video_processor/videosync/videosync.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#define DEBUG + +#include "videosync.h" +#include +#include +#include +#include +#include + + +#define VIDEOSYNC_DEVICE_NAME "videosync" +#define RECEIVER_NAME "videosync" +#define PROVIDER_NAME "videosync" + +static bool videosync_inited;/*false*/ +static bool show_nosync;/*false*/ +static bool smooth_sync_enable; +static int enable_video_discontinue_report = 1; +static u32 system_time_scale_base = 1; +static s32 system_time_inc_adj;/*?*/ +static u32 vsync_pts_inc;/*?*/ +static u32 omx_version = 2; +static u32 vp_debug_flag; +static bool no_render;/* default: false */ +static bool async_mode;/* default: false */ +static u32 video_early_threshold = 900; /* default: 900=>10ms */ + + +/* video freerun mode */ +#define FREERUN_NONE 0 /* no freerun mode */ +#define FREERUN_NODUR 1 /* freerun without duration */ +#define FREERUN_DUR 2 /* freerun with duration */ +#define M_PTS_SMOOTH_MAX 45000 +#define M_PTS_SMOOTH_MIN 2250 +#define M_PTS_SMOOTH_ADJUST 900 +#define DURATION_GCD 750 + +static int omx_pts_interval_upper = 11000; +static int omx_pts_interval_lower = -5500; +#define DUR2PTS(x) ((x) - ((x) >> 4)) + +#define PRINT_ERROR 0X0 +#define PRINT_QUEUE_STATUS 0X0001 +#define PRINT_TIMESTAMP 0X0002 +#define PRINT_OTHER 0X0004 + +static struct videosync_dev *vp_dev; + +static int vp_print(char *name, int debug_flag, const char *fmt, ...) +{ + if ((vp_debug_flag & debug_flag) + || (debug_flag == PRINT_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + + va_start(args, fmt); + len = sprintf(buf, "[%s]", name); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} + +static u32 ts_pcrscr_get(struct videosync_s *dev_s) +{ + u32 sys_time = 0; + /*unsigned long flags;*/ + sys_time = dev_s->system_time; + return sys_time; +} + +static void ts_pcrscr_set(struct videosync_s *dev_s, u32 pts) +{ + dev_s->system_time = pts; + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "ts_pcrscr_set sys_time %d\n", dev_s->system_time); +} + +static void ts_pcrscr_enable(struct videosync_s *dev_s, u32 enable) +{ + dev_s->system_time_up = enable; +} +static u32 ts_pcrscr_enable_state(struct videosync_s *dev_s) +{ + return dev_s->system_time_up; +} + +void videosync_pcrscr_update(s32 inc, u32 base) +{ + int i = 0; + u32 r; + /*unsigned long flags;*/ + struct videosync_s *dev_s; + u32 current_omx_pts; + int diff; + + if (!videosync_inited) + return; + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s && dev_s->active_state == VIDEOSYNC_ACTIVE) { + if (system_time_scale_base != base) { + dev_s->system_time_scale_remainder = + dev_s->system_time_scale_remainder * + base / system_time_scale_base; + system_time_scale_base = base; + } + if (dev_s->system_time_up) { + dev_s->system_time += + div_u64_rem(90000ULL * inc, base, &r) + + system_time_inc_adj; + dev_s->system_time_scale_remainder += r; + if (dev_s->system_time_scale_remainder + >= system_time_scale_base) { + dev_s->system_time++; + dev_s->system_time_scale_remainder + -= system_time_scale_base; + } + vp_print(dev_s->vf_receiver_name, PRINT_OTHER, + "update sys_time %d, system_time_scale_base %d, inc %d\n", + dev_s->system_time, + system_time_scale_base, + inc); + } + + /*check if need to correct pcr by omx_pts*/ + current_omx_pts = dev_s->omx_pts; + diff = dev_s->system_time - current_omx_pts; + + if ((diff - omx_pts_interval_upper) > 0 + || (diff - omx_pts_interval_lower) < 0) { + vp_print(dev_s->vf_receiver_name, + PRINT_TIMESTAMP, + "sys_time=%d, omx_pts=%d, diff=%d\n", + dev_s->system_time, + current_omx_pts, + diff); + ts_pcrscr_set(dev_s, + current_omx_pts + DURATION_GCD); + } + } + } +} + + +/* ----------------------------------------------------------------- + * videosync operations + * ----------------------------------------------------------------- + */ +static struct vframe_s *videosync_vf_peek(void *op_arg) +{ + struct vframe_s *vf = NULL; + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + vf = vfq_peek(&dev_s->ready_q); + return vf; +} + +static struct vframe_s *videosync_vf_get(void *op_arg) +{ + struct vframe_s *vf = NULL; + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + vf = vfq_pop(&dev_s->ready_q); + if (vf) { + dev_s->cur_dispbuf = vf; + dev_s->first_frame_toggled = 1; + } + return vf; +} + +static void videosync_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + if (vf != NULL) { + vf_put(vf, dev_s->vf_receiver_name); + dev_s->put_frame_count++; + } else { + vp_print(dev_s->vf_receiver_name, 0, + "videosync_vf_put: NULL!\n"); + } +} + +static int videosync_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static int videosync_buffer_states(struct videosync_buffer_states *states, + void *op_arg) +{ + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + states->buf_ready_num = vfq_level(&dev_s->ready_q); + states->buf_queued_num = vfq_level(&dev_s->queued_q); + states->total_num = dev_s->get_frame_count; + return 0; +} + +static int videosync_buffer_states_vf(struct vframe_states *states, + void *op_arg) +{ + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + states->vf_pool_size = VIDEOSYNC_S_POOL_SIZE; + states->buf_recycle_num = 0; + states->buf_free_num = VIDEOSYNC_S_POOL_SIZE + - vfq_level(&dev_s->ready_q) + - vfq_level(&dev_s->queued_q); + states->buf_avail_num = vfq_level(&dev_s->ready_q) + + vfq_level(&dev_s->queued_q); + + return 0; +} + +static const struct vframe_operations_s v4lvideo_vf_provider = { + .peek = videosync_vf_peek, + .get = videosync_vf_get, + .put = videosync_vf_put, + .event_cb = videosync_event_cb, + .vf_states = videosync_buffer_states_vf, +}; + +static void videosync_register(struct videosync_s *dev_s) +{ + vf_provider_init(&dev_s->video_vf_prov, + dev_s->vf_provider_name, + &v4lvideo_vf_provider, dev_s); + vf_reg_provider(&dev_s->video_vf_prov); + vf_notify_receiver(dev_s->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, + NULL); +} + +static void videosync_unregister(struct videosync_s *dev_s) +{ + vf_unreg_provider(&dev_s->video_vf_prov); +} + +static ssize_t dump_queue_state_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_buffer_states states; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + if (videosync_buffer_states(&states, dev_s) == 0) { + ret += sprintf(buf + ret, + "\n#------ %s state ------#\n", + dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "queued_q_size=%d\n", + states.buf_queued_num); + ret += sprintf(buf + ret, + "ready_q_size=%d\n", + states.buf_ready_num); + ret += sprintf(buf + ret, + "total frame count=%d\n", + states.total_num); + } + } + } + return ret; +} + +static ssize_t dump_pts_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + ret += sprintf(buf + ret, + "%s: ", dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "omx_pts=%d, ", dev_s->omx_pts); + ret += sprintf(buf + ret, + "system_time=%d\n", dev_s->system_time); + } + } + return ret; +} + +static ssize_t dump_get_put_framecount_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + ret += sprintf(buf + ret, + "%s: ", dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "get_frame_count=%d, put_frame_count=%d\n", + dev_s->get_frame_count, + dev_s->put_frame_count); + } + } + return ret; +} + +static ssize_t dump_rect_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + ret += sprintf(buf + ret, + "%s: ", dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "rect = [%d,%d,%d,%d], ", + dev_s->rect.left, + dev_s->rect.top, + dev_s->rect.width, + dev_s->rect.height); + ret += sprintf(buf + ret, + "zorder = %d\n", dev_s->zorder); + } + } + return ret; +} + +static struct class_attribute videosync_class_attrs[] = { + __ATTR_RO(dump_queue_state), + __ATTR_RO(dump_pts), + __ATTR_RO(dump_get_put_framecount), + __ATTR_RO(dump_rect), + __ATTR_NULL +}; +static struct class videosync_class = { + .name = "videosync", + .class_attrs = videosync_class_attrs, +}; + + +int videosync_assign_map(char **receiver_name, int *inst) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst == *inst) { + *receiver_name = dev_s->vf_receiver_name; + pr_info("videosync_assign_map %s %p\n", + dev_s->vf_receiver_name, dev_s); + mutex_unlock(&vp_dev->vp_mutex); + return 0; + } + } + mutex_unlock(&vp_dev->vp_mutex); + return -ENODEV; +} + +int videosync_alloc_map(int *inst) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst >= 0 && (!dev_s->mapped)) { + dev_s->mapped = true; + *inst = dev_s->inst; + pr_info("videosync_alloc_map %d OK\n", dev_s->inst); + mutex_unlock(&vp_dev->vp_mutex); + return 0; + } + } + mutex_unlock(&vp_dev->vp_mutex); + return -ENODEV; +} + +void videosync_release_map(int inst) +{ + + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst == inst && (dev_s->mapped)) { + dev_s->mapped = false; + pr_info("videosync_release_map %d OK\n", inst); + break; + } + } + mutex_unlock(&vp_dev->vp_mutex); +} +void videosync_release_map_force(struct videosync_priv_s *priv) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst == priv->vp_id && (dev_s->mapped)) { + dev_s->mapped = false; + pr_info("videosync_release_map_force %d OK\n", + priv->vp_id); + break; + } + } + mutex_unlock(&vp_dev->vp_mutex); +} + +static int videosync_open(struct inode *inode, struct file *file) +{ + struct videosync_priv_s *priv = NULL; + + pr_info("videosync_open\n"); + priv = kzalloc(sizeof(struct videosync_priv_s), GFP_KERNEL); + if (priv == NULL) { + pr_err("kzalloc videosync_priv_s failed!"); + } else { + priv->vp_id = -1; + priv->dev_s = NULL; + file->private_data = priv; + } + return 0; +} + +static int videosync_release(struct inode *inode, struct file *file) +{ + struct videosync_priv_s *priv = NULL; + + pr_info("videosync_release\n"); + if (file && file->private_data) { + priv = file->private_data; + + /*check if map released.*/ + videosync_release_map_force(priv); + + kfree(priv); + priv = NULL; + file->private_data = NULL; + } + + return 0; +} + +static int set_omx_pts(u32 *p) +{ + struct videosync_s *dev_s = NULL; + int ret = 0; + u32 tmp_pts = p[0]; + /*u32 vision = p[1];*/ + u32 set_from_hwc = p[2]; + u32 frame_num = p[3]; + u32 not_reset = p[4]; + u32 dev_id = p[6]; + + if (dev_id < VIDEOSYNC_S_COUNT) + dev_s = &vp_dev->video_prov[dev_id]; + + if (dev_s != NULL && dev_s->mapped) { + mutex_lock(&dev_s->omx_mutex); + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "set omx_pts %d, hwc %d, not_reset %d, frame_num\n", + tmp_pts, set_from_hwc, not_reset, frame_num); + if (not_reset == 0) + dev_s->omx_pts = tmp_pts; + + mutex_unlock(&dev_s->omx_mutex); + + ts_pcrscr_enable(dev_s, 1); + } else { + ret = -EFAULT; + pr_err("[%s]cannot find dev_id %d device\n", + dev_s->vf_receiver_name, dev_id); + } + + return ret; + +} +static int set_omx_zorder(u32 *p) +{ + struct videosync_s *dev_s = NULL; + int ret = 0; + u32 dev_id = p[5]; + /*32 tmp_pts = p[6];*/ + + if (dev_id < VIDEOSYNC_S_COUNT) + dev_s = &vp_dev->video_prov[dev_id]; + + if (dev_s != NULL && dev_s->mapped) { + dev_s->zorder = p[0]; + dev_s->rect.left = p[1]; + dev_s->rect.top = p[2]; + dev_s->rect.width = p[3]; + dev_s->rect.height = p[4]; + + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "set zorder %d: %d %d %d %d\n", + p[0], p[1], p[2], p[3], p[4]); + + } else { + ret = -EFAULT; + pr_err("[%s]cannot find dev_id %d device\n", + dev_s->vf_receiver_name, dev_id); + } + + return ret; + +} + +static long videosync_ioctl(struct file *file, + unsigned int cmd, + ulong arg) +{ + long ret = 0; + void __user *argp = (void __user *)arg; + struct videosync_priv_s *priv = NULL; + + switch (cmd) { + case VIDEOSYNC_IOC_ALLOC_ID:{ + u32 videosync_id = 0; + + ret = videosync_alloc_map(&videosync_id); + if (ret != 0) + break; + put_user(videosync_id, (u32 __user *)argp); + pr_info("alloc-id %d\n", videosync_id); + + if (file && file->private_data) { + priv = file->private_data; + priv->vp_id = videosync_id; + priv->dev_s = &vp_dev->video_prov[videosync_id]; + pr_info("get dev_s %p\n", priv->dev_s); + } + } + break; + case VIDEOSYNC_IOC_FREE_ID:{ + u32 videosync_id; + + get_user(videosync_id, (u32 __user *)argp); + pr_info("free-id %d\n", videosync_id); + videosync_release_map(videosync_id); + } + break; + + case VIDEOSYNC_IOC_SET_FREERUN_MODE: + if (arg > FREERUN_DUR) + ret = -EFAULT; + else { + if (file && file->private_data) { + priv = file->private_data; + if (priv && priv->dev_s) + priv->dev_s->freerun_mode = arg; + else + ret = -EFAULT; + } else { + ret = -EFAULT; + } + } + break; + + case VIDEOSYNC_IOC_GET_FREERUN_MODE: + if (file && file->private_data) { + priv = file->private_data; + if (priv && priv->dev_s) + put_user(priv->dev_s->freerun_mode, + (u32 __user *)argp); + else + ret = -EFAULT; + + } else + ret = -EFAULT; + + break; + case VIDEOSYNC_IOC_SET_OMX_VPTS:{ + u32 pts[7]; + + if (copy_from_user(pts, argp, sizeof(pts)) == 0) + ret = set_omx_pts(pts); + + } + break; + case VIDEOSYNC_IOC_SET_OMX_ZORDER:{ + u32 zorder[7]; + + if (copy_from_user(zorder, argp, sizeof(zorder)) == 0) + ret = set_omx_zorder(zorder); + + } + break; + case VIDEOSYNC_IOC_GET_OMX_VPTS: + if (file && file->private_data) { + priv = file->private_data; + if (priv && priv->dev_s) + put_user(priv->dev_s->omx_pts, + (u32 __user *)argp); + else + ret = -EFAULT; + } else { + ret = -EFAULT; + } + break; + case VIDEOSYNC_IOC_GET_OMX_VERSION: + put_user(omx_version, (u32 __user *)argp); + pr_info("get omx_version %d\n", omx_version); + break; + default: + pr_info("ioctl invalid cmd 0x%x\n", cmd); + return -EINVAL; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long videosync_compat_ioctl(struct file *file, + unsigned int cmd, + ulong arg) +{ + long ret = 0; + + ret = videosync_ioctl(file, cmd, (ulong)compat_ptr(arg)); + return ret; +} +#endif + +static void clear_queued_queue(struct videosync_s *dev_s) +{ + struct vframe_s *vf = NULL; + + vp_print(dev_s->vf_receiver_name, PRINT_QUEUE_STATUS, + "clear_queued_queue: size %d!\n", vfq_level(&dev_s->queued_q)); + + vf = vfq_pop(&dev_s->queued_q); + while (vf) { + vf_put(vf, dev_s->vf_receiver_name); + vf = vfq_pop(&dev_s->queued_q); + } + +} + +static void clear_ready_queue(struct videosync_s *dev_s) +{ + struct vframe_s *vf = NULL; + + vp_print(dev_s->vf_receiver_name, PRINT_QUEUE_STATUS, + "clear_ready_queue: size %d!\n", + vfq_level(&dev_s->ready_q)); + vf = vfq_pop(&dev_s->ready_q); + while (vf) { + vf_put(vf, dev_s->vf_receiver_name); + vf = vfq_pop(&dev_s->ready_q); + } +} + +static inline bool omx_vpts_expire(struct vframe_s *cur_vf, + struct vframe_s *next_vf, + struct videosync_s *dev_s) + +{ + u32 pts = next_vf->pts; +#ifdef VIDEO_PTS_CHASE + u32 vid_pts, scr_pts; +#endif + u32 systime; + u32 adjust_pts, org_vpts; + /*u32 dur_pts = 0;*/ + + if (dev_s->freerun_mode == FREERUN_NODUR) + return true; + + if (next_vf->duration == 0) + return true; + + systime = ts_pcrscr_get(dev_s); + + if (no_render) + dev_s->first_frame_toggled = 1; /*just for debug, not render*/ + + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "sys_time=%d, vf->pts=%d, diff=%d\n", + systime, pts, (int)(systime - pts)); + + if (0) { + pts = + timestamp_vpts_get() + + (cur_vf ? DUR2PTS(cur_vf->duration) : 0); + } + /* check video PTS discontinuity */ + else if (ts_pcrscr_enable_state(dev_s) > 0 && + (enable_video_discontinue_report) && + (dev_s->first_frame_toggled) && + (abs(systime - pts) > tsync_vpts_discontinuity_margin()) && + ((next_vf->flag & VFRAME_FLAG_NO_DISCONTINUE) == 0 + || tsync_vpts_discontinuity_margin() <= 90000)) { + + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "discontinue, systime = %d, next_vf->pts = %d\n", + systime, next_vf->pts); + return true; + } + + if (0/*smooth_sync_enable*/) { + org_vpts = timestamp_vpts_get(); + if ((abs(org_vpts + vsync_pts_inc - systime) < + M_PTS_SMOOTH_MAX) + && (abs(org_vpts + vsync_pts_inc - systime) > + M_PTS_SMOOTH_MIN)) { + + if (!dev_s->video_frame_repeat_count) { + dev_s->vpts_ref = org_vpts; + dev_s->video_frame_repeat_count++; + } + + if ((int)(org_vpts + vsync_pts_inc - systime) > 0) { + adjust_pts = + dev_s->vpts_ref + (vsync_pts_inc - + M_PTS_SMOOTH_ADJUST) * + dev_s->video_frame_repeat_count; + } else { + adjust_pts = + dev_s->vpts_ref + (vsync_pts_inc + + M_PTS_SMOOTH_ADJUST) * + dev_s->video_frame_repeat_count; + } + + return (int)(adjust_pts - pts) >= 0; + } + + if (dev_s->video_frame_repeat_count) { + dev_s->vpts_ref = 0; + dev_s->video_frame_repeat_count = 0; + } + } + + return (systime + video_early_threshold) > pts; + +} + +void videosync_sync(struct videosync_s *dev_s) +{ + int ready_q_size = 0; + struct vframe_s *vf; + + if (smooth_sync_enable) { + if (dev_s->video_frame_repeat_count) + dev_s->video_frame_repeat_count++; + } + + vf = vfq_peek(&dev_s->queued_q); + + while (vf) { + if (omx_vpts_expire(dev_s->cur_dispbuf, vf, dev_s) + || show_nosync) { + + vf = vfq_pop(&dev_s->queued_q); + if (vf) { + if (async_mode) { + if (vfq_level(&dev_s->ready_q) > 0) + clear_ready_queue(dev_s); + } + + vfq_push(&dev_s->ready_q, vf); + ready_q_size = vfq_level(&dev_s->ready_q); + vp_print(dev_s->vf_receiver_name, + PRINT_QUEUE_STATUS, + "add pts %d index 0x%x to ready_q, size %d\n", + vf->pts, vf->index, ready_q_size); + + vf_notify_receiver( + dev_s->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + if (ready_q_size > VIDEOSYNC_S_POOL_SIZE - 1) { + vp_print(dev_s->vf_receiver_name, + PRINT_QUEUE_STATUS, + "ready_q full!\n"); + break; + } + } + + vf = vfq_peek(&dev_s->queued_q); + if (!vf) + break; + } else { + break; + } + } + +} + + +static void prepare_queued_queue(struct videosync_dev *dev) +{ + int i = 0; + struct videosync_s *dev_s; + struct vframe_s *vf; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + if (vfq_full(&dev_s->queued_q)) { + pr_info("[%s]queued_q full!\n", + dev_s->vf_receiver_name); + continue; + } + + if (vf_peek(dev_s->vf_receiver_name)) { + vf = vf_get(dev_s->vf_receiver_name); + if (vf) { + vfq_push(&dev_s->queued_q, vf); + dev_s->get_frame_count++; + vp_print(dev_s->vf_receiver_name, + PRINT_QUEUE_STATUS, + "add pts %d index 0x%x to queued_q, size %d\n", + vf->pts, + vf->index, + vfq_level(&dev_s->queued_q)); + } + } else { + vp_print(dev_s->vf_receiver_name, PRINT_OTHER, + "peek failed %d\n"); + } + } + +} +static void prepare_ready_queue(struct videosync_dev *dev) +{ + int i = 0; + struct videosync_s *dev_s; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + if (vfq_full(&dev_s->ready_q)) { + pr_info("[%s]ready_q full!\n", dev_s->vf_receiver_name); + continue; + } + + videosync_sync(dev_s); + + if (no_render) + clear_ready_queue(dev_s);/*just for debug, not render*/ + + } + +} + +static void reinit_dev_s(struct videosync_s *dev_s) +{ + dev_s->get_frame_count = 0; + dev_s->put_frame_count = 0; + dev_s->system_time_up = 0; + dev_s->system_time = 0; + dev_s->first_frame_toggled = 0; + dev_s->freerun_mode = 0; + dev_s->system_time_scale_remainder = 0; + dev_s->omx_pts = 0; + dev_s->vpts_ref = 0; + dev_s->video_frame_repeat_count = 0; + dev_s->rect.top = 0; + dev_s->rect.left = 0; + dev_s->rect.width = 0; + dev_s->rect.height = 0; + dev_s->zorder = 0; +} +static int videosync_receiver_event_fun(int type, void *data, + void *private_data) +{ + struct videosync_s *dev_s = (struct videosync_s *)private_data; + unsigned long flags = 0; + struct videosync_dev *dev; + unsigned long time_left; + + if (type == VFRAME_EVENT_PROVIDER_UNREG) { + pr_info("videosync: try to unreg %p, %s\n", + dev_s, dev_s->vf_receiver_name); + dev = (struct videosync_dev *)dev_s->dev; + + spin_lock_irqsave(&dev->dev_s_num_slock, flags); + --dev->active_dev_s_num; + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + + videosync_unregister(dev_s); + dev_s->receiver_register = false; + + if (dev_s->active_state == VIDEOSYNC_ACTIVE) { + dev_s->active_state = VIDEOSYNC_INACTIVE_REQ; + time_left = wait_for_completion_timeout( + &dev_s->inactive_done, + msecs_to_jiffies(100)); + if (time_left == 0) + pr_err("videosync: unreg timeout\n"); + } + clear_ready_queue(dev_s); + clear_queued_queue(dev_s); + + /*tsync_avevent(VIDEO_STOP, 0);*/ + pr_info("videosync: unreg %p, %s\n", + dev_s, dev_s->vf_receiver_name); + } else if (type == VFRAME_EVENT_PROVIDER_REG) { + //omx_secret_mode = false; + struct videosync_dev *dev = (struct videosync_dev *)dev_s->dev; + + reinit_dev_s(dev_s); + //videosync_register(dev_s); + dev_s->receiver_register = true; + dev_s->active_state = VIDEOSYNC_ACTIVE; + + spin_lock_irqsave(&dev->dev_s_num_slock, flags); + ++dev->active_dev_s_num; + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + + vfq_init(&dev_s->queued_q, VIDEOSYNC_S_POOL_SIZE + 1, + &dev_s->videosync_pool_queued[0]); + vfq_init(&dev_s->ready_q, VIDEOSYNC_S_POOL_SIZE + 1, + &dev_s->videosync_pool_ready[0]); + + init_completion(&dev_s->inactive_done); + complete(&dev->thread_active); + pr_info("videosync: reg %p, %s\n", + dev_s, dev_s->vf_receiver_name); + } else if (type == VFRAME_EVENT_PROVIDER_VFRAME_READY) { + + } else if (type == VFRAME_EVENT_PROVIDER_START) { + videosync_register(dev_s); + pr_info("videosync: start %p, %s\n", + dev_s, dev_s->vf_receiver_name); + } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { + struct videosync_buffer_states states; + + videosync_buffer_states(&states, dev_s); + if (states.buf_queued_num + states.buf_ready_num > 0) + return RECEIVER_ACTIVE; + + vp_print(dev_s->vf_receiver_name, 0, + "buf queue empty!!\n"); + return RECEIVER_ACTIVE;/*return RECEIVER_INACTIVE;*/ + } + return 0; +} + +static const struct file_operations videosync_fops = { + + .owner = THIS_MODULE, + .open = videosync_open, + .release = videosync_release, + .unlocked_ioctl = videosync_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = videosync_compat_ioctl, +#endif + .poll = NULL, +}; + +static const struct vframe_receiver_op_s videosync_vf_receiver = { + .event_cb = videosync_receiver_event_fun, +}; + +static const struct videosync_operations_s videosync_vf_provider = { + .peek = videosync_vf_peek, + .get = videosync_vf_get, + .put = videosync_vf_put, + .event_cb = videosync_event_cb, + .buffer_states = videosync_buffer_states, +}; + +static int __init videosync_create_instance(int inst) +{ + struct videosync_s *dev_s; + + dev_s = &vp_dev->video_prov[inst]; + dev_s->dev = vp_dev; + dev_s->fd_num = 0; + dev_s->ops = &videosync_vf_provider; + dev_s->active_state = VIDEOSYNC_INACTIVE; + pr_info("videosync_create_instance dev_s %p,dev_s->dev %p\n", + dev_s, dev_s->dev); + + /* initialize locks */ + mutex_init(&dev_s->omx_mutex); + spin_lock_init(&dev_s->timestamp_lock); + + dev_s->inst = inst; + dev_s->index = inst; + dev_s->mapped = true; + snprintf(dev_s->vf_receiver_name, VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE, + RECEIVER_NAME ".%x", inst & 0xff); + snprintf(dev_s->vf_provider_name, VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE, + PROVIDER_NAME ".%x", inst & 0xff); + + pr_info("videosync_create_instance reg %s\n", + dev_s->vf_receiver_name); + + vf_receiver_init(&dev_s->vp_vf_receiver, + dev_s->vf_receiver_name, + &videosync_vf_receiver, dev_s); + + vf_reg_receiver(&dev_s->vp_vf_receiver); + + return 0; + +} + +static void __init videosync_destroy_instance(int inst) +{ + pr_info("videosync_destroy_instance %s\n", + vp_dev->video_prov[inst].vf_receiver_name); + vf_unreg_receiver(&vp_dev->video_prov[inst].vp_vf_receiver); +} + + +static void videosync_thread_tick(struct videosync_dev *dev) +{ + int i = 0; + struct videosync_s *dev_s; + unsigned long flags = 0; + unsigned long time_left; + + if (!dev) + return; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE_REQ) { + dev_s->active_state = VIDEOSYNC_INACTIVE; + complete(&dev_s->inactive_done); + } + } + + vp_print(RECEIVER_NAME, PRINT_OTHER, + "active num %d\n", dev->active_dev_s_num); + + spin_lock_irqsave(&dev->dev_s_num_slock, flags); + if (dev->active_dev_s_num > 0) { + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + prepare_queued_queue(dev); + prepare_ready_queue(dev); + usleep_range(7000, 8000); + } else { + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + vp_print(RECEIVER_NAME, PRINT_OTHER, + "videosync: no active dev, thread go to sleep\n"); + time_left = wait_for_completion_timeout(&dev->thread_active, + msecs_to_jiffies(500)); + if (time_left == 0) + pr_err("videosync: thread_tick timeout\n"); + } +} + +static void videosync_sleep(struct videosync_dev *dev) +{ + videosync_thread_tick(dev); + try_to_freeze(); +} + +static int videosync_thread(void *data) +{ + struct videosync_dev *dev = (struct videosync_dev *)data; + + pr_info("videosync_thread started\n"); + + set_freezable(); + + while (!kthread_should_stop()) + videosync_sleep(dev); + + pr_info("videosync_thread exit\n"); + return 0; +} + + +static int __init videosync_init(void) +{ + int ret = -1, i; + struct device *devp; + + ret = class_register(&videosync_class); + if (ret < 0) + return ret; + ret = register_chrdev(VIDEOSYNC_MAJOR, "videosync", &videosync_fops); + if (ret < 0) { + pr_err("Can't allocate major for videosync device\n"); + goto error1; + } + + devp = device_create(&videosync_class, + NULL, + MKDEV(VIDEOSYNC_MAJOR, 0), + NULL, + VIDEOSYNC_DEVICE_NAME); + if (IS_ERR(devp)) { + pr_err("failed to create videosync device node\n"); + ret = PTR_ERR(devp); + return ret; + } + + vp_dev = kzalloc(sizeof(*vp_dev), GFP_KERNEL); + if (!vp_dev) + return -ENOMEM; + + vp_dev->video_prov = kzalloc( + VIDEOSYNC_S_COUNT * sizeof(struct videosync_s), + GFP_KERNEL); + if (!vp_dev->video_prov) + return -ENOMEM; + + mutex_init(&vp_dev->vp_mutex); + spin_lock_init(&vp_dev->dev_s_num_slock); + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + ret = videosync_create_instance(i); + if (ret) { + pr_err("videosync: error %d while create instance\n", + ret); + goto error1; + } + } + + init_completion(&vp_dev->thread_active); + vp_dev->kthread = kthread_run(videosync_thread, vp_dev, "videosync"); + videosync_inited = true; + return ret; + +error1: + kfree(vp_dev); + vp_dev = NULL; + unregister_chrdev(VIDEOSYNC_MAJOR, "videosync"); + class_unregister(&videosync_class); + return ret; +} + +static void __exit videosync_exit(void) +{ + int i, ret; + + complete(&vp_dev->thread_active); + + if (vp_dev->kthread) { + ret = kthread_stop(vp_dev->kthread); + if (ret < 0) + pr_info("%s, kthread_stop return %d.\n", __func__, ret); + vp_dev->kthread = NULL; + } + videosync_inited = false; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) + videosync_destroy_instance(i); + + kfree(vp_dev->video_prov); + vp_dev->video_prov = NULL; + + kfree(vp_dev); + vp_dev = NULL; + + device_destroy(&videosync_class, MKDEV(VIDEOSYNC_MAJOR, 0)); + unregister_chrdev(VIDEOSYNC_MAJOR, VIDEOSYNC_DEVICE_NAME); + class_unregister(&videosync_class); +} + +module_init(videosync_init); +module_exit(videosync_exit); + +MODULE_PARM_DESC(smooth_sync_enable, "\n smooth_sync_enable\n"); +module_param(smooth_sync_enable, bool, 0664); + +MODULE_PARM_DESC(vp_debug_flag, "\n vp_debug_flag\n"); +module_param(vp_debug_flag, uint, 0664); + +MODULE_PARM_DESC(show_nosync, "\n show_nosync\n"); +module_param(show_nosync, bool, 0664); + +MODULE_PARM_DESC(no_render, "\n no_render\n"); +module_param(no_render, bool, 0664); + +MODULE_PARM_DESC(async_mode, "\n async_mode\n"); +module_param(async_mode, bool, 0664); + +MODULE_PARM_DESC(video_early_threshold, "\n video_early_threshold\n"); +module_param(video_early_threshold, uint, 0664); + diff --git a/drivers/amlogic/media/video_processor/videosync/videosync.h b/drivers/amlogic/media/video_processor/videosync/videosync.h new file mode 100644 index 000000000000..98bad9f651ae --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/videosync.h @@ -0,0 +1,141 @@ +/* + * drivers/amlogic/media/video_processor/videosync/videosync.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _VIDEOSYNC_H +#define _VIDEOSYNC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vfp.h" +#include + +#define VIDEOSYNC_S_COUNT 1 + +#define VIDEOSYNC_ACTIVE 0 +#define VIDEOSYNC_INACTIVE_REQ 1 +#define VIDEOSYNC_INACTIVE 2 + +struct videosync_priv_s { + int vp_id; /* reserved */ + struct videosync_s *dev_s; +}; + +struct videosync_dev { + struct videosync_s *video_prov; + struct task_struct *kthread; + struct completion thread_active; + struct mutex vp_mutex; + spinlock_t dev_s_num_slock; + u32 active_dev_s_num; +}; +extern bool omx_secret_mode; + +#define VIDEOSYNC_IOC_MAGIC 'P' +#define VIDEOSYNC_IOC_ALLOC_ID _IOR(VIDEOSYNC_IOC_MAGIC, 0x00, int) +#define VIDEOSYNC_IOC_FREE_ID _IOW(VIDEOSYNC_IOC_MAGIC, 0x01, int) +#define VIDEOSYNC_IOC_SET_FREERUN_MODE _IOW(VIDEOSYNC_IOC_MAGIC, 0x02, int) +#define VIDEOSYNC_IOC_GET_FREERUN_MODE _IOR(VIDEOSYNC_IOC_MAGIC, 0x03, int) +#define VIDEOSYNC_IOC_SET_OMX_VPTS _IOW(VIDEOSYNC_IOC_MAGIC, 0x04, unsigned int) +#define VIDEOSYNC_IOC_GET_OMX_VPTS _IOR(VIDEOSYNC_IOC_MAGIC, 0x05, unsigned int) +#define VIDEOSYNC_IOC_GET_OMX_VERSION \ + _IOR(VIDEOSYNC_IOC_MAGIC, 0x06, unsigned int) +#define VIDEOSYNC_IOC_SET_OMX_ZORDER \ + _IOW(VIDEOSYNC_IOC_MAGIC, 0x07, unsigned int) + +#define VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE 32 +#define VIDEOSYNC_S_POOL_SIZE 16 +#define VIDEOSYNC_VF_NAME_SIZE 32 + +extern int videosync_assign_map(char **receiver_name, int *inst); + +struct videosync_buffer_states { + int buf_ready_num; + int buf_queued_num; + int total_num; +}; + +struct videosync_operations_s { + struct vframe_s *(*peek)(void *op_arg); + struct vframe_s *(*get)(void *op_arg); + void (*put)(struct vframe_s *, void *op_arg); + int (*event_cb)(int type, void *data, void *private_data); + int (*buffer_states)(struct videosync_buffer_states *states, + void *op_arg); +}; + +struct display_area { + u32 left; + u32 top; + u32 width; + u32 height; +}; +struct videosync_s { + void *dev; + int index; + int fd_num; + char vf_receiver_name[VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE]; + int inst; + bool mapped; + bool receiver_register; + struct vframe_receiver_s vp_vf_receiver; + struct vfq_s queued_q; + struct vfq_s ready_q; + struct vframe_s *videosync_pool_queued[VIDEOSYNC_S_POOL_SIZE + 1]; + struct vframe_s *videosync_pool_ready[VIDEOSYNC_S_POOL_SIZE + 1]; + int active_state; + const struct videosync_operations_s *ops; + struct completion inactive_done; + struct vframe_s *cur_dispbuf; + spinlock_t timestamp_lock; + struct mutex omx_mutex; + u32 system_time_up; + u32 system_time; + u32 system_time_scale_remainder; + u32 omx_pts; + u32 vpts_ref; + u32 video_frame_repeat_count; + u32 freerun_mode; + u32 first_frame_toggled; + u32 get_frame_count; + u32 put_frame_count; + void *op_arg; + char *name; + struct display_area rect; + u32 zorder; + struct vframe_provider_s video_vf_prov; + char vf_provider_name[VIDEOSYNC_VF_NAME_SIZE]; +}; + + +#endif + diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 18cd54c1d4e5..2491109e6752 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -6112,6 +6112,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) timestamp_pcrscr_inc_scale(vsync_pts_inc_scale, vsync_pts_inc_scale_base); timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor); + videosync_pcrscr_update(vsync_pts_inc_scale, + vsync_pts_inc_scale_base); } else if (vsync_slow_factor > 1000) { u32 inc = (vsync_slow_factor / 1000) * vsync_pts_inc / 1000; diff --git a/include/linux/amlogic/major.h b/include/linux/amlogic/major.h index 1ce50430bb88..dbdf49510892 100644 --- a/include/linux/amlogic/major.h +++ b/include/linux/amlogic/major.h @@ -30,6 +30,7 @@ #define VFM_MAJOR (14+(AML_BASE)) #define IONVIDEO_MAJOR (15+(AML_BASE)) #define VAD_MAJOR (16+(AML_BASE)) +#define VIDEOSYNC_MAJOR (17+(AML_BASE)) /* *#define UIO_MAJOR 4+(AML_BASE) *#define USB_DEV_EP_MAJOR 5+(AML_BASE) diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 8ef253825495..56cdaefc22fa 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -241,5 +241,5 @@ void set_video_angle(u32 s_value); u32 get_video_angle(void); extern unsigned int DI_POST_REG_RD(unsigned int addr); extern int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len); - +extern void videosync_pcrscr_update(s32 inc, u32 base); #endif /* VIDEO_H */ From 411475113d1a803ac22eb5397dc4225c5f5ade75 Mon Sep 17 00:00:00 2001 From: jintao xu Date: Thu, 31 Jan 2019 19:15:24 +0800 Subject: [PATCH 0018/1060] omx: add print into level control [1/1] PD#SWPL-85 Problem: print into level control Solution: print into level control Verify: U212 Change-Id: Ib0fdc02f26e75c20e48171bca5ebef072947d78c Signed-off-by: jintao xu --- drivers/amlogic/media/video_processor/videosync/videosync.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_processor/videosync/videosync.c b/drivers/amlogic/media/video_processor/videosync/videosync.c index af95be662d22..9f4c3dff8245 100644 --- a/drivers/amlogic/media/video_processor/videosync/videosync.c +++ b/drivers/amlogic/media/video_processor/videosync/videosync.c @@ -959,7 +959,8 @@ static int videosync_receiver_event_fun(int type, void *data, &dev_s->inactive_done, msecs_to_jiffies(100)); if (time_left == 0) - pr_err("videosync: unreg timeout\n"); + vp_print(RECEIVER_NAME, PRINT_OTHER, + "videosync: unreg timeout\n"); } clear_ready_queue(dev_s); clear_queued_queue(dev_s); @@ -1112,7 +1113,8 @@ static void videosync_thread_tick(struct videosync_dev *dev) time_left = wait_for_completion_timeout(&dev->thread_active, msecs_to_jiffies(500)); if (time_left == 0) - pr_err("videosync: thread_tick timeout\n"); + vp_print(RECEIVER_NAME, PRINT_OTHER, + "videosync: thread_tick timeout\n"); } } From c701adb055e641573a4d5de342585195a15f039d Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Tue, 8 Jan 2019 17:02:34 +0800 Subject: [PATCH 0019/1060] di: aptimise di flow, add some protection [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-3976 Problem: To prevent “stall when access DDR through memory interface†Solution: 1.aptimise NRWR register access flow 2.add arb on/off and status check 3.add reset protect 4.add nr_en disable before arb status check 5.add nr_write_done sel 6.modify VPU_WRARB_MODE_L2C1 from vlsi feijun's suggest Verify: tl1, txlx Change-Id: Ifb0f4f0502d957ffb2b07805575c27f4166d5717 Signed-off-by: Yong Qin Signed-off-by: Luan Yuan Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c --- .../amlogic/media/common/vpu/vpu_power_init.c | 3 +- .../amlogic/media/deinterlace/deinterlace.c | 10 +- .../media/deinterlace/deinterlace_hw.c | 149 +++++++++++++++++- .../media/deinterlace/deinterlace_hw.h | 4 + drivers/amlogic/media/deinterlace/register.h | 11 +- .../amlogic/media/registers/regs/vpp_regs.h | 4 + 6 files changed, 174 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/media/common/vpu/vpu_power_init.c b/drivers/amlogic/media/common/vpu/vpu_power_init.c index 07c5c848e638..7858607f5320 100644 --- a/drivers/amlogic/media/common/vpu/vpu_power_init.c +++ b/drivers/amlogic/media/common/vpu/vpu_power_init.c @@ -60,7 +60,8 @@ void vpu_module_init_config(void) vpu_vcbus_write(VPU_RDARB_MODE_L1C1, 0x210000); vpu_vcbus_write(VPU_RDARB_MODE_L1C2, 0x10000); vpu_vcbus_write(VPU_RDARB_MODE_L2C1, 0x900000); - vpu_vcbus_write(VPU_WRARB_MODE_L2C1, 0x20000); + /*from vlsi feijun*/ + vpu_vcbus_write(VPU_WRARB_MODE_L2C1, 0x170000/*0x20000*/); if (vpu_debug_print_flag) VPUPR("%s finish\n", __func__); diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 4a0afc00e6e7..597d781c7feb 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-12-04a"; +static const char version_s[] = "2019-02-27a"; static int bypass_state = 1; static int bypass_all; @@ -3350,7 +3350,7 @@ static bool pps_en; module_param_named(pps_en, pps_en, bool, 0644); static unsigned int pps_position = 1; module_param_named(pps_position, pps_position, uint, 0644); -static unsigned int pre_enable_mask = 3; +static unsigned int pre_enable_mask = 3;/*bit0:ma bit1:mc*/ module_param_named(pre_enable_mask, pre_enable_mask, uint, 0644); static unsigned char pre_de_buf_config(void) @@ -4265,6 +4265,10 @@ static irqreturn_t de_irq(int irq, void *dev_instance) trace_di_pre("PRE-IRQ-0", di_pre_stru.field_count_for_cont, di_pre_stru.irq_time[0]); + /*add from valsi wang.feng*/ + di_arb_sw(false); + di_arb_sw(true); + if (mcpre_en) { get_mcinfo_from_reg_in_irq(); if ((is_meson_gxlx_cpu() && @@ -6143,6 +6147,8 @@ static void di_reg_process_irq(void) de_devp->flags |= DI_VPU_CLKB_SET; enable_di_pre_mif(false, mcpre_en); di_pre_gate_control(true, mcpre_en); + di_rst_protect(true);/*2019-01-22 by VLSI feng.wang*/ + di_pre_nr_wr_done_sel(true); nr_gate_control(true); } else { /* if mcdi enable DI_CLKG_CTRL should be 0xfef60000 */ diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 86e93e26b528..8796b2584593 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -642,13 +642,34 @@ static void set_di_nrwr_mif(struct DI_SIM_MIF_s *nrwr_mif, /* wr ext en from gxtvbb */ RDMA_WR_BITS(DI_NRWR_Y, 1, 15, 1); RDMA_WR_BITS(DI_NRWR_Y, 3, 30, 2); + #if 0 RDMA_WR(DI_NRWR_CTRL, nrwr_mif->canvas_num| (urgent<<16)| 2<<26 | 1<<30); + #endif RDMA_WR_BITS(DI_NRWR_Y, nrwr_mif->bit_mode&0x1, 14, 1); + #if 0 if ((nrwr_mif->bit_mode&0x3) == 0x3) RDMA_WR_BITS(DI_NRWR_CTRL, 0x3, 22, 2); + #endif + + /*fix 1080i crash when di work on low speed*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL) && + ((nrwr_mif->bit_mode&0x3) == 0x3)) { + RDMA_WR(DI_NRWR_CTRL, nrwr_mif->canvas_num| + (urgent<<16)| + 3<<22 | + 1<<24 | + 2<<26 |/*burst_lim 1->2 2->4*/ + 1<<30); /* urgent bit 16 */ + } else { + RDMA_WR(DI_NRWR_CTRL, nrwr_mif->canvas_num| + (urgent<<16)| + 1<<24 | + 2<<26 |/*burst_lim 1->2 2->4*/ + 1<<30); /* urgent bit 16 */ + } } void di_interrupt_ctrl(unsigned char ma_en, @@ -3333,6 +3354,130 @@ void di_post_gate_control(bool gate) } } + +void di_async_reset(void) /*2019-01-17 add for debug*/ +{ + /*wrmif async reset*/ + RDMA_WR_BITS(VIUB_SW_RESET, 1, 14, 1); + RDMA_WR_BITS(VIUB_SW_RESET, 0, 14, 1); +} + +void di_pre_rst_frame(void) +{ + RDMA_WR(DI_PRE_CTRL, Rd(DI_PRE_CTRL) | (1 << 31)); +} + +void di_pre_nr_enable(bool on) +{ + if (on) + RDMA_WR_BITS(DI_PRE_CTRL, 1, 0, 1); + else + RDMA_WR_BITS(DI_PRE_CTRL, 0, 0, 1); +} + +void di_pre_nr_wr_done_sel(bool on) +{ + if (on) /*wait till response finish*/ + RDMA_WR_BITS(DI_CANVAS_URGENT0, 1, 8, 1); + else + RDMA_WR_BITS(DI_CANVAS_URGENT0, 0, 0, 1); + +} + +void di_rst_protect(bool on) +{ + if (on) + RDMA_WR_BITS(DI_NRWR_Y, 1, 15, 1); + else + RDMA_WR_BITS(DI_NRWR_Y, 0, 15, 1); +} + +/*bit 10,12,16,18 [3:1]*/ +/*#define PRE_ID_MASK (0x5140e) */ +#define PRE_ID_MASK (0x51400) + +/*bit 8,10,14,16*/ +#define PRE_ID_MASK_TL1 (0x14500) + +bool di_pre_idle(void) +{ + bool ret = false; + + if (is_meson_tl1_cpu()) { + if ((RDMA_RD(VPU_ARB_DBG_STAT_L1C1_TL1) & + PRE_ID_MASK_TL1) == PRE_ID_MASK_TL1) + ret = true; + } else { + if ((RDMA_RD(VPU_ARB_DBG_STAT_L1C1) & + PRE_ID_MASK) == PRE_ID_MASK) + ret = true; + } + + return ret; +} + +void di_arb_sw(bool on) +{ + int i; + u32 REG_VPU_WRARB_REQEN_SLV_L1C1; + u32 REG_VPU_RDARB_REQEN_SLV_L1C1; + u32 REG_VPU_ARB_DBG_STAT_L1C1; + u32 WRARB_onval; + u32 WRARB_offval; + + if (is_meson_tl1_cpu()) { + REG_VPU_WRARB_REQEN_SLV_L1C1 = VPU_WRARB_REQEN_SLV_L1C1_TL1; + REG_VPU_RDARB_REQEN_SLV_L1C1 = VPU_RDARB_REQEN_SLV_L1C1_TL1; + REG_VPU_ARB_DBG_STAT_L1C1 = VPU_ARB_DBG_STAT_L1C1_TL1; + if (on) + WRARB_onval = 0x3f; + else + WRARB_offval = 0x3e; + } else { + REG_VPU_WRARB_REQEN_SLV_L1C1 = VPU_WRARB_REQEN_SLV_L1C1; + REG_VPU_RDARB_REQEN_SLV_L1C1 = VPU_RDARB_REQEN_SLV_L1C1; + REG_VPU_ARB_DBG_STAT_L1C1 = VPU_ARB_DBG_STAT_L1C1; + if (on) + WRARB_onval = 0x3f; + else + WRARB_offval = 0x2b; + } + + if (on) { + RDMA_WR(REG_VPU_WRARB_REQEN_SLV_L1C1, WRARB_onval); + RDMA_WR(REG_VPU_RDARB_REQEN_SLV_L1C1, 0xffff); + } else { + /*close arb:*/ + RDMA_WR(REG_VPU_WRARB_REQEN_SLV_L1C1, WRARB_offval); + RDMA_WR(REG_VPU_RDARB_REQEN_SLV_L1C1, 0xf1f1); + + di_pre_nr_enable(false); /*by Feijun*/ + /*check status*/ + if (!di_pre_idle()) { + pr_err("di:err1:0x[%x]\n", + RDMA_RD(REG_VPU_ARB_DBG_STAT_L1C1)); + for (i = 0; i < 9; i++) { + if (di_pre_idle()) + break; + } + + if (!di_pre_idle()) { + di_pre_rst_frame(); + + for (i = 0; i < 9; i++) { + if (di_pre_idle()) + break; + } + if (!di_pre_idle()) + pr_err("di:err2\n"); + + } + } + if (di_pre_idle()) + di_async_reset(); + } +} + /* * enable/disable mc pre mif mcinfo&mv */ @@ -3434,10 +3579,10 @@ static void di_pre_data_mif_ctrl(bool enable) } #endif /* nrwr no clk gate en=0 */ - RDMA_WR_BITS(DI_NRWR_CTRL, 0, 24, 1); + /*RDMA_WR_BITS(DI_NRWR_CTRL, 0, 24, 1);*/ } else { /* nrwr no clk gate en=1 */ - RDMA_WR_BITS(DI_NRWR_CTRL, 1, 24, 1); + /*RDMA_WR_BITS(DI_NRWR_CTRL, 1, 24, 1);*/ /* nr wr req en =0 */ RDMA_WR_BITS(DI_PRE_CTRL, 0, 0, 1); /* disable input mif*/ diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index d6b44d529836..17622be59b4a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -197,4 +197,8 @@ extern int di_print(const char *fmt, ...); extern void di_patch_post_update_mc(void); extern void di_patch_post_update_mc_sw(unsigned int cmd, bool on); +extern void di_rst_protect(bool on); +extern void di_pre_nr_wr_done_sel(bool on); +extern void di_arb_sw(bool on); + #endif diff --git a/drivers/amlogic/media/deinterlace/register.h b/drivers/amlogic/media/deinterlace/register.h index adeedbbe1b46..cc73dc2a7cf8 100644 --- a/drivers/amlogic/media/deinterlace/register.h +++ b/drivers/amlogic/media/deinterlace/register.h @@ -43,8 +43,15 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, unsigned int val, unsigned int start, unsigned int len); #define HHI_VPU_CLKB_CNTL 0x83 -#define VPU_WRARB_REQEN_SLV_L1C1 ((0x2795)) /* << 2) + 0xd0100000) */ -#define VPU_ARB_DBG_STAT_L1C1 ((0x27b4)) /* << 2) + 0xd0100000) */ + +#define VPU_WRARB_REQEN_SLV_L1C1 0x2795 +#define VPU_RDARB_REQEN_SLV_L1C1 0x2791 +#define VPU_ARB_DBG_STAT_L1C1 0x27b4 + +#define VPU_WRARB_REQEN_SLV_L1C1_TL1 0x2055 +#define VPU_RDARB_REQEN_SLV_L1C1_TL1 0x2051 +#define VPU_ARB_DBG_STAT_L1C1_TL1 0x205a + #define VIUB_SW_RESET 0x2001 #define VIUB_SW_RESET0 0x2002 diff --git a/include/linux/amlogic/media/registers/regs/vpp_regs.h b/include/linux/amlogic/media/registers/regs/vpp_regs.h index b59bc6ca27ff..af2df4329063 100644 --- a/include/linux/amlogic/media/registers/regs/vpp_regs.h +++ b/include/linux/amlogic/media/registers/regs/vpp_regs.h @@ -251,5 +251,9 @@ /* after g12b */ #define SRSHARP0_SHARP_SYNC_CTRL 0x3eb0 #define SRSHARP1_SHARP_SYNC_CTRL 0x3fb0 + +#define VPU_RDARB_MODE_L2C1 0x279d +#define VPU_WRARB_MODE_L2C1 0x27a2 + #endif From 5f62f5e3be7445b8ecd3ce758dcbcd935bae8bea Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 14 Jan 2019 16:50:12 +0800 Subject: [PATCH 0020/1060] cec: ceca register access fail [1/1] PD#SWPL-4133 Problem: cec a register access fail and cause watchdog reboot Solution: reduce wait counter, and check clk register Verify: P215 Change-Id: Ic9d97e1eca9428ffd0c4a6bfe008cd9d8303075b Signed-off-by: Yong Qin Signed-off-by: Luan Yuan Conflicts: drivers/amlogic/cec/hdmi_ao_cec.h --- drivers/amlogic/cec/hdmi_ao_cec.c | 374 +++++++++++++++++++----------- drivers/amlogic/cec/hdmi_ao_cec.h | 5 +- 2 files changed, 240 insertions(+), 139 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index c2f5c688db18..931ef1e55622 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -93,6 +93,7 @@ struct cec_wakeup_t { /* global struct for tx and rx */ struct ao_cec_dev { + bool proble_finish; unsigned long dev_type; struct device_node *node; unsigned int port_num; /*total input hdmi port number*/ @@ -181,17 +182,77 @@ static unsigned int cec_msg_dbg_en; static unsigned char msg_log_buf[128] = { 0 }; +static const char * const cec_reg_name1[] = { + "CEC_TX_MSG_LENGTH", + "CEC_TX_MSG_CMD", + "CEC_TX_WRITE_BUF", + "CEC_TX_CLEAR_BUF", + "CEC_RX_MSG_CMD", + "CEC_RX_CLEAR_BUF", + "CEC_LOGICAL_ADDR0", + "CEC_LOGICAL_ADDR1", + "CEC_LOGICAL_ADDR2", + "CEC_LOGICAL_ADDR3", + "CEC_LOGICAL_ADDR4", + "CEC_CLOCK_DIV_H", + "CEC_CLOCK_DIV_L" +}; + +static const char * const cec_reg_name2[] = { + "CEC_RX_MSG_LENGTH", + "CEC_RX_MSG_STATUS", + "CEC_RX_NUM_MSG", + "CEC_TX_MSG_STATUS", + "CEC_TX_NUM_MSG" +}; + +static const char * const ceca_reg_name3[] = { + "STAT_0_0", + "STAT_0_1", + "STAT_0_2", + "STAT_0_3", + "STAT_1_0", + "STAT_1_1", + "STAT_1_2" +}; + +#if 1 +unsigned int waiting_aocec_free(unsigned int r) +{ + unsigned int cnt = 0; + int ret = true; + char *s; + + while (readl(cec_dev->cec_reg + r) & (1<<23)) { + if (cnt++ >= 3500) { + pr_info("waiting aocec %x free time out %d\n", r, cnt); + s = kmalloc(2048, GFP_KERNEL); + dump_cecrx_reg(s); + CEC_ERR("%s\n", s); + kfree(s); + if (cec_dev->proble_finish) + cec_hw_reset(CEC_A); + ret = false; + break; + } + } + + return ret; +} +#else #define waiting_aocec_free(r) \ do {\ unsigned long cnt = 0;\ while (readl(cec_dev->cec_reg + r) & (1<<23)) {\ if (cnt++ == 3500) { \ pr_info("waiting aocec %x free time out\n", r);\ - cec_hw_reset(CEC_A);\ + if (cec_dev->proble_finish) \ + cec_hw_reset(CEC_A);\ break;\ } \ } \ } while (0) +#endif static void cec_set_reg_bits(unsigned int addr, unsigned int value, unsigned int offset, unsigned int len) @@ -210,14 +271,20 @@ unsigned int aocec_rd_reg(unsigned long addr) unsigned long flags; spin_lock_irqsave(&cec_dev->cec_reg_lock, flags); - waiting_aocec_free(AO_CEC_RW_REG); + if (!waiting_aocec_free(AO_CEC_RW_REG)) { + spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); + return 0; + } data32 = 0; data32 |= 0 << 16; /* [16] cec_reg_wr */ data32 |= 0 << 8; /* [15:8] cec_reg_wrdata */ data32 |= addr << 0; /* [7:0] cec_reg_addr */ writel(data32, cec_dev->cec_reg + AO_CEC_RW_REG); - waiting_aocec_free(AO_CEC_RW_REG); + if (!waiting_aocec_free(AO_CEC_RW_REG)) { + spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); + return 0; + } data32 = ((readl(cec_dev->cec_reg + AO_CEC_RW_REG)) >> 24) & 0xff; spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); return data32; @@ -229,7 +296,10 @@ void aocec_wr_reg(unsigned long addr, unsigned long data) unsigned long flags; spin_lock_irqsave(&cec_dev->cec_reg_lock, flags); - waiting_aocec_free(AO_CEC_RW_REG); + if (!waiting_aocec_free(AO_CEC_RW_REG)) { + spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); + return; + } data32 = 0; data32 |= 1 << 16; /* [16] cec_reg_wr */ data32 |= data << 8; /* [15:8] cec_reg_wrdata */ @@ -661,74 +731,156 @@ int cecrx_hw_init(void) return 0; } */ -static int dump_cecrx_reg(char *b) + +int dump_cecrx_reg(char *b) { int i = 0, s = 0; unsigned char reg; unsigned int reg32; + unsigned int chiptype; - if (!cec_dev->plat_data->ee_to_ao) { - reg32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL); - s += sprintf(b + s, "HHI_32K_CLK_CNTL: 0x%08x\n", reg32); - reg32 = hdmirx_rd_top(TOP_EDID_ADDR_CEC); - s += sprintf(b + s, "TOP_EDID_ADDR_CEC: 0x%08x\n", reg32); - reg32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL); - s += sprintf(b + s, "TOP_EDID_GEN_CNTL: 0x%08x\n", reg32); - reg32 = hdmirx_cec_read(DWC_AUD_CEC_IEN); - s += sprintf(b + s, "DWC_AUD_CEC_IEN: 0x%08x\n", reg32); - reg32 = hdmirx_cec_read(DWC_AUD_CEC_ISTS); - s += sprintf(b + s, "DWC_AUD_CEC_ISTS: 0x%08x\n", reg32); - reg32 = hdmirx_cec_read(DWC_DMI_DISABLE_IF); - s += sprintf(b + s, "DWC_DMI_DISABLE_IF: 0x%08x\n", reg32); - reg32 = hdmirx_rd_top(TOP_CLK_CNTL); - s += sprintf(b + s, "TOP_CLK_CNTL: 0x%08x\n", reg32); + chiptype = get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR); + if ((ee_cec == CEC_A) && (chiptype >= MESON_CPU_MAJOR_ID_GXBB)) { + if (cec_dev->plat_data->ee_to_ao) { + reg32 = readl(cec_dev->cec_reg + AO_CEC_CLK_CNTL_REG0); + s += sprintf(b + s, "AO_CEC_CLK_CNTL_REG0:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CEC_CLK_CNTL_REG1); + s += sprintf(b + s, "AO_CEC_CLK_CNTL_REG1:0x%08x\n", + reg32); + } else { + reg32 = readl(cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); + s += sprintf(b + s, "AO_RTC_ALT_CLK_CNTL0:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL1); + s += sprintf(b + s, "AO_RTC_ALT_CLK_CNTL1:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CRT_CLK_CNTL1); + s += sprintf(b + s, "AO_CRT_CLK_CNTL1:0x%08x\n", + reg32); + } + } + reg32 = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + s += sprintf(b + s, "AO_RTI_PWR_CNTL_REG0: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CEC_GEN_CNTL); + s += sprintf(b + s, "AO_CEC_GEN_CNTL: 0x%08x\n", + reg32); + + if (ee_cec == CEC_B) { + if (!cec_dev->plat_data->ee_to_ao) { + reg32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL); + s += sprintf(b + s, "HHI_32K_CLK_CNTL: 0x%08x\n", + reg32); + reg32 = hdmirx_rd_top(TOP_EDID_ADDR_CEC); + s += sprintf(b + s, "TOP_EDID_ADDR_CEC: 0x%08x\n", + reg32); + reg32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL); + s += sprintf(b + s, "TOP_EDID_GEN_CNTL: 0x%08x\n", + reg32); + reg32 = hdmirx_cec_read(DWC_AUD_CEC_IEN); + s += sprintf(b + s, "DWC_AUD_CEC_IEN: 0x%08x\n", + reg32); + reg32 = hdmirx_cec_read(DWC_AUD_CEC_ISTS); + s += sprintf(b + s, "DWC_AUD_CEC_ISTS: 0x%08x\n", + reg32); + reg32 = hdmirx_cec_read(DWC_DMI_DISABLE_IF); + s += sprintf(b + s, "DWC_DMI_DISABLE_IF: 0x%08x\n", + reg32); + reg32 = hdmirx_rd_top(TOP_CLK_CNTL); + s += sprintf(b + s, "TOP_CLK_CNTL: 0x%08x\n", + reg32); + } else { + reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG0: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); + s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG1: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_GEN_CNTL); + s += sprintf(b + s, "AO_CECB_GEN_CNTL: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_RW_REG); + s += sprintf(b + s, "AO_CECB_RW_REG: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN); + s += sprintf(b + s, "AO_CECB_INTR_MASKN:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_STAT); + s += sprintf(b + s, "AO_CECB_INTR_STAT: 0x%08x\n", + reg32); + } + + s += sprintf(b + s, "CEC MODULE REGS:\n"); + s += sprintf(b + s, "CEC_CTRL = 0x%02x\n", + hdmirx_cec_read(0x1f00)); + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) + s += sprintf(b + s, "CEC_CTRL2 = 0x%02x\n", + hdmirx_cec_read(0x1f04)); + s += sprintf(b + s, "CEC_MASK = 0x%02x\n", + hdmirx_cec_read(0x1f08)); + s += sprintf(b + s, "CEC_ADDR_L = 0x%02x\n", + hdmirx_cec_read(0x1f14)); + s += sprintf(b + s, "CEC_ADDR_H = 0x%02x\n", + hdmirx_cec_read(0x1f18)); + s += sprintf(b + s, "CEC_TX_CNT = 0x%02x\n", + hdmirx_cec_read(0x1f1c)); + s += sprintf(b + s, "CEC_RX_CNT = 0x%02x\n", + hdmirx_cec_read(0x1f20)); + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) + s += sprintf(b + s, "CEC_STAT0 = 0x%02x\n", + hdmirx_cec_read(0x1f24)); + s += sprintf(b + s, "CEC_LOCK = 0x%02x\n", + hdmirx_cec_read(0x1fc0)); + s += sprintf(b + s, "CEC_WKUPCTRL = 0x%02x\n", + hdmirx_cec_read(0x1fc4)); + + s += sprintf(b + s, "%s", "RX buffer:"); + for (i = 0; i < 16; i++) { + reg = (hdmirx_cec_read(0x1f80 + i * 4) & 0xff); + s += sprintf(b + s, " %02x", reg); + } + s += sprintf(b + s, "\n"); + + s += sprintf(b + s, "%s", "TX buffer:"); + for (i = 0; i < 16; i++) { + reg = (hdmirx_cec_read(0x1f40 + i * 4) & 0xff); + s += sprintf(b + s, " %02x", reg); + } + s += sprintf(b + s, "\n"); } else { - reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG0: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); - s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG1: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_GEN_CNTL); - s += sprintf(b + s, "AO_CECB_GEN_CNTL: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_RW_REG); - s += sprintf(b + s, "AO_CECB_RW_REG: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN); - s += sprintf(b + s, "AO_CECB_INTR_MASKN: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_STAT); - s += sprintf(b + s, "AO_CECB_INTR_STAT: 0x%08x\n", reg32); + s += sprintf(b + s, "TX buffer:\n"); + for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) + s += sprintf(b + s, "%2d:%2x\n", i, + aocec_rd_reg(i)); + + for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) { + s += sprintf(b + s, "%s:%2x\n", + cec_reg_name1[i], aocec_rd_reg(i + 0x10)); + } + + s += sprintf(b + s, "RX buffer:\n"); + for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) + s += sprintf(b + s, "%2d:%2x\n", i, + aocec_rd_reg(i + 0x80)); + + for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) { + s += sprintf(b + s, "%s:%2x\n", + cec_reg_name2[i], aocec_rd_reg(i + 0x90)); + } + + if (cec_dev->plat_data->ceca_sts_reg) { + for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) { + s += sprintf(b + s, "%s:%2x\n", + ceca_reg_name3[i], aocec_rd_reg(i + 0xA0)); + } + } } - s += sprintf(b + s, "CEC MODULE REGS:\n"); - s += sprintf(b + s, "CEC_CTRL = 0x%02x\n", hdmirx_cec_read(0x1f00)); - if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) - s += sprintf(b + s, "CEC_CTRL2 = 0x%02x\n", - hdmirx_cec_read(0x1f04)); - s += sprintf(b + s, "CEC_MASK = 0x%02x\n", hdmirx_cec_read(0x1f08)); - s += sprintf(b + s, "CEC_ADDR_L = 0x%02x\n", hdmirx_cec_read(0x1f14)); - s += sprintf(b + s, "CEC_ADDR_H = 0x%02x\n", hdmirx_cec_read(0x1f18)); - s += sprintf(b + s, "CEC_TX_CNT = 0x%02x\n", hdmirx_cec_read(0x1f1c)); - s += sprintf(b + s, "CEC_RX_CNT = 0x%02x\n", hdmirx_cec_read(0x1f20)); - if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) - s += sprintf(b + s, "CEC_STAT0 = 0x%02x\n", - hdmirx_cec_read(0x1f24)); - s += sprintf(b + s, "CEC_LOCK = 0x%02x\n", hdmirx_cec_read(0x1fc0)); - s += sprintf(b + s, "CEC_WKUPCTRL = 0x%02x\n", hdmirx_cec_read(0x1fc4)); - - s += sprintf(b + s, "%s", "RX buffer:"); - for (i = 0; i < 16; i++) { - reg = (hdmirx_cec_read(0x1f80 + i * 4) & 0xff); - s += sprintf(b + s, " %02x", reg); - } - s += sprintf(b + s, "\n"); - - s += sprintf(b + s, "%s", "TX buffer:"); - for (i = 0; i < 16; i++) { - reg = (hdmirx_cec_read(0x1f40 + i * 4) & 0xff); - s += sprintf(b + s, " %02x", reg); - } - s += sprintf(b + s, "\n"); return s; } + /*--------------------- END of EE CEC --------------------*/ void aocec_irq_enable(bool enable) @@ -1374,6 +1526,11 @@ static void ao_ceca_init(void) udelay(200); reg |= (1 << 30); writel(reg, cec_dev->cec_reg + AO_CEC_CLK_CNTL_REG0); + + reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + reg |= (0x01 << 14);/* enable the crystal clock*/ + writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + } else { reg = (0 << 31) | (0 << 30) | @@ -1385,22 +1542,16 @@ static void ao_ceca_init(void) ((11-1) << 12) | ((8-1) << 0); writel(reg, cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL1); - + udelay(100); /*enable clk in*/ reg = readl(cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); reg |= (1 << 31); writel(reg, cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); /*enable clk out*/ - udelay(200); + udelay(100); reg |= (1 << 30); writel(reg, cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); - } - if (cec_dev->plat_data->ee_to_ao) { - reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - reg |= (0x01 << 14);/* enable the crystal clock*/ - writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - } else { reg = readl(cec_dev->cec_reg + AO_CRT_CLK_CNTL1); reg |= (0x800 << 16);/* select cts_rtc_oscin_clk */ writel(reg, cec_dev->cec_reg + AO_CRT_CLK_CNTL1); @@ -2019,75 +2170,10 @@ static ssize_t port_num_show(struct class *cla, return sprintf(buf, "%d\n", cec_dev->port_num); } -static const char * const cec_reg_name1[] = { - "CEC_TX_MSG_LENGTH", - "CEC_TX_MSG_CMD", - "CEC_TX_WRITE_BUF", - "CEC_TX_CLEAR_BUF", - "CEC_RX_MSG_CMD", - "CEC_RX_CLEAR_BUF", - "CEC_LOGICAL_ADDR0", - "CEC_LOGICAL_ADDR1", - "CEC_LOGICAL_ADDR2", - "CEC_LOGICAL_ADDR3", - "CEC_LOGICAL_ADDR4", - "CEC_CLOCK_DIV_H", - "CEC_CLOCK_DIV_L" -}; - -static const char * const cec_reg_name2[] = { - "CEC_RX_MSG_LENGTH", - "CEC_RX_MSG_STATUS", - "CEC_RX_NUM_MSG", - "CEC_TX_MSG_STATUS", - "CEC_TX_NUM_MSG" -}; - -static const char * const ceca_reg_name3[] = { - "STAT_0_0", - "STAT_0_1", - "STAT_0_2", - "STAT_0_3", - "STAT_1_0", - "STAT_1_1", - "STAT_1_2" -}; - - static ssize_t dump_reg_show(struct class *cla, struct class_attribute *attr, char *b) { - int i, s = 0; - - if (ee_cec == CEC_B) - return dump_cecrx_reg(b); - - s += sprintf(b + s, "TX buffer:\n"); - for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) - s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i)); - - for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) { - s += sprintf(b + s, "%s:%2x\n", - cec_reg_name1[i], aocec_rd_reg(i + 0x10)); - } - - s += sprintf(b + s, "RX buffer:\n"); - for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) - s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i + 0x80)); - - for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) { - s += sprintf(b + s, "%s:%2x\n", - cec_reg_name2[i], aocec_rd_reg(i + 0x90)); - } - - if (cec_dev->plat_data->ceca_sts_reg) { - for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) { - s += sprintf(b + s, "%s:%2x\n", - ceca_reg_name3[i], aocec_rd_reg(i + 0xA0)); - } - } - - return s; + return dump_cecrx_reg(b); } static ssize_t arc_port_show(struct class *cla, @@ -2368,7 +2454,10 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, CEC_ERR("wb cecb reg:0x%x val:0x%x\n", addr, val); hdmirx_cec_write(addr, val); } else if (token && strncmp(token, "dump", 4) == 0) { - dump_reg(); + token = kmalloc(2048, GFP_KERNEL); + dump_cecrx_reg(token); + CEC_ERR("%s\n", token); + kfree(token); } else if (token && strncmp(token, "status", 6) == 0) { cec_dump_info(); } else if (token && strncmp(token, "rao", 3) == 0) { @@ -2622,6 +2711,8 @@ void cec_dump_info(void) struct hdmi_port_info *port; CEC_ERR("driver date:%s\n", CEC_DRIVER_VERSION); + CEC_ERR("chip type:0x%x\n", + get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR)); CEC_ERR("cec sel:%d\n", ee_cec); CEC_ERR("cec_num:%d\n", cec_dev->cec_num); CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); @@ -3062,6 +3153,7 @@ static int aml_cec_probe(struct platform_device *pdev) cec_dev->tx_dev = get_hdmitx_device(); cec_dev->cpu_type = get_cpu_type(); cec_dev->node = pdev->dev.of_node; + cec_dev->proble_finish = false; phy_addr_test = 0; CEC_ERR("cec driver date:%s\n", CEC_DRIVER_VERSION); cec_dbg_init(); @@ -3093,9 +3185,14 @@ static int aml_cec_probe(struct platform_device *pdev) /*get compatible matched device, to get chip related data*/ of_id = of_match_device(aml_cec_dt_match, &pdev->dev); - if (of_id != NULL) + if (of_id != NULL) { cec_dev->plat_data = (struct cec_platform_data_s *)of_id->data; - else + CEC_ERR("compatible:%s\n", of_id->compatible); + CEC_ERR("cecb_ver:0x%x\n", cec_dev->plat_data->cecb_ver); + CEC_ERR("line_reg:0x%x\n", cec_dev->plat_data->line_reg); + CEC_ERR("line_bit:0x%x\n", cec_dev->plat_data->line_bit); + CEC_ERR("ee_to_ao:0x%x\n", cec_dev->plat_data->ee_to_ao); + } else CEC_ERR("unable to get matched device\n"); cec_node_val_init(); @@ -3373,6 +3470,7 @@ static int aml_cec_probe(struct platform_device *pdev) cec_irq_enable(true); CEC_ERR("%s success end\n", __func__); + cec_dev->proble_finish = true; return 0; tag_cec_msg_alloc_err: diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 779d58c3f984..4b54245fc586 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,7 +19,8 @@ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2019/1/7\n" + +#define CEC_DRIVER_VERSION "Ver 2019/1/14\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" @@ -538,4 +539,6 @@ extern void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en); extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); extern void cec_clear_all_logical_addr(unsigned int cec_sel); +extern int dump_cecrx_reg(char *b); + #endif /* __AO_CEC_H__ */ From 603701319da36acafb2405359c27b6ba1290cc3d Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Wed, 19 Dec 2018 11:32:30 +0800 Subject: [PATCH 0021/1060] bt656: fix bt656 bugs [1/1] PD#OTT-1022 Problem: bt656 can not work well. Solution: 1. add clock control 2. fix bt656 id bug Verify: G12A U200 Change-Id: I2aaecee33fd590497d5a11cf3618fc07264f02a5 Signed-off-by: Xuhua Zhang --- drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c index dc45d7568e61..0feac45d341b 100644 --- a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c +++ b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c @@ -1127,14 +1127,16 @@ static int amvdec_656in_probe(struct platform_device *pdev) BT656PR("%s: start probe .\n", __func__); - if (is_meson_gxtvbb_cpu() || - is_meson_gxl_cpu() || is_meson_gxm_cpu()) { + if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || + is_meson_gxm_cpu() || is_meson_g12a_cpu() || + is_meson_g12b_cpu() || is_meson_tl1_cpu()) { hw_cnt = 1; } else if (is_meson_gxbb_cpu()) { hw_cnt = 2; } else { hw_cnt = 0; } + if (hw_cnt == 0) { BT656ERR("no bt656 support for current chip\n"); return -EFAULT; @@ -1241,10 +1243,9 @@ static int amvdec_656in_probe(struct platform_device *pdev) if (IS_ERR(devp->gate_bt656_pclk)) { BT656ERR("%s: cannot get clk_gate_bt656_pclk1 !!!\n", __func__); - ret = -ENOENT; - goto fail_get_clktree; + //ret = -ENOENT; + //goto fail_get_clktree; } - /* set regmap */ BT656PR("%s: bt656[%d] start get ioremap .\n", __func__, devp->index); @@ -1278,7 +1279,7 @@ static int amvdec_656in_probe(struct platform_device *pdev) * &am656_decoder_ops_s, &am656_machine_ops, pdev->id); */ if (!tvin_frontend_init(&devp->frontend, &am656_decoder_ops_s, - &am656_machine_ops, devp->index)) { + &am656_machine_ops, devp->index-1)) { BT656PR("%s: tvin_frontend_init done :%d\n", __func__, devp->index); if (tvin_reg_frontend(&devp->frontend)) { From c72605771849e4892b246949d54d7dec8519338c Mon Sep 17 00:00:00 2001 From: Jian Hu Date: Tue, 18 Dec 2018 17:07:20 +0800 Subject: [PATCH 0022/1060] clk: g12a: add bt656 clock [1/1] PD#SWPL-3359 Problem: the bt656 clocks were missing Solution: 1.add bt656 clocks 2.fix several errors for media clocks Verify: test passed on u200 Change-Id: Iff69e790c78335930d6b2ea54f7544aca464e1fb Signed-off-by: Jian Hu --- drivers/amlogic/clk/g12a/g12a.h | 2 +- drivers/amlogic/clk/g12a/g12a_clk_media.c | 84 +++++++++++++++++-- include/dt-bindings/clock/amlogic,g12a-clkc.h | 8 +- 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h index 40b9174e5a13..525b1fa43ccc 100644 --- a/drivers/amlogic/clk/g12a/g12a.h +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -117,7 +117,7 @@ #define HHI_SYS1_PLL_CNTL5 0x394 /* 0xe5 offset in data sheet */ #define HHI_SYS1_PLL_CNTL6 0x398 /* 0xe6 offset in data sheet */ /*****************/ - +#define HHI_BT656_CLK_CNTL 0x3d4 /* 0xf5 offset in data sheet */ #define HHI_SPICC_CLK_CNTL 0x3dc /* 0xf7 offset in data sheet */ /* AO registers*/ #define AO_RTI_PWR_CNTL_REG0 0x10 /* 0x4 offset in data sheet */ diff --git a/drivers/amlogic/clk/g12a/g12a_clk_media.c b/drivers/amlogic/clk/g12a/g12a_clk_media.c index a4371eb41711..c7377060d304 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk_media.c +++ b/drivers/amlogic/clk/g12a/g12a_clk_media.c @@ -734,13 +734,13 @@ static struct clk_mux vapb_mux = { }; static struct clk_hw *vapb_clk_hws[] = { - [CLKID_VPU_P0_MUX - CLKID_VPU_P0_MUX] = &vapb_p0_mux.hw, - [CLKID_VPU_P0_DIV - CLKID_VPU_P0_MUX] = &vapb_p0_div.hw, - [CLKID_VPU_P0_GATE - CLKID_VPU_P0_MUX] = &vapb_p0_gate.hw, - [CLKID_VPU_P1_MUX - CLKID_VPU_P0_MUX] = &vapb_p1_mux.hw, - [CLKID_VPU_P1_DIV - CLKID_VPU_P0_MUX] = &vapb_p1_div.hw, - [CLKID_VPU_P1_GATE - CLKID_VPU_P0_MUX] = &vapb_p1_gate.hw, - [CLKID_VPU_MUX - CLKID_VPU_P0_MUX] = &vapb_mux.hw, + [CLKID_VAPB_P0_MUX - CLKID_VAPB_P0_MUX] = &vapb_p0_mux.hw, + [CLKID_VAPB_P0_DIV - CLKID_VAPB_P0_MUX] = &vapb_p0_div.hw, + [CLKID_VAPB_P0_GATE - CLKID_VAPB_P0_MUX] = &vapb_p0_gate.hw, + [CLKID_VAPB_P1_MUX - CLKID_VAPB_P0_MUX] = &vapb_p1_mux.hw, + [CLKID_VAPB_P1_DIV - CLKID_VAPB_P0_MUX] = &vapb_p1_div.hw, + [CLKID_VAPB_P1_GATE - CLKID_VAPB_P0_MUX] = &vapb_p1_gate.hw, + [CLKID_VAPB_MUX - CLKID_VAPB_P0_MUX] = &vapb_mux.hw, }; static struct clk_gate ge2d_gate = { @@ -768,7 +768,7 @@ static struct clk_mux vpu_clkb_tmp_mux = { .name = "vpu_clkb_tmp_mux", .ops = &clk_mux_ops, .parent_names = vpu_clkb_tmp_parent_names, - .num_parents = 8, + .num_parents = ARRAY_SIZE(vpu_clkb_tmp_parent_names), .flags = CLK_GET_RATE_NOCACHE, }, }; @@ -822,7 +822,7 @@ static struct clk_gate vpu_clkb_gate = { .bit_idx = 8, .lock = &clk_lock, .hw.init = &(struct clk_init_data) { - .name = "vpu_clkb_tmp_gate", + .name = "vpu_clkb_gate", .ops = &clk_gate_ops, .parent_names = (const char *[]){ "vpu_clkb_div" }, .num_parents = 1, @@ -943,6 +943,56 @@ static struct clk_hw *vpu_clkc_hws[] = { [CLKID_VPU_CLKC_MUX - CLKID_VPU_CLKC_P0_MUX] = &vpu_clkc_mux.hw, }; +/* cts_bt656 */ +static const char * const bt656_parent_names[] = { "fclk_div2", +"fclk_div3", "fclk_div5", "fclk_div7" }; + +static struct clk_mux bt656_mux = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "bt656_mux", + .ops = &clk_mux_ops, + .parent_names = bt656_parent_names, + .num_parents = ARRAY_SIZE(bt656_parent_names), + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider bt656_div = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "bt656_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "bt656_mux" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_gate bt656_gate = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "bt656_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "bt656_div" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_hw *bt656_clk_hws[] = { + [0] = &bt656_mux.hw, + [1] = &bt656_div.hw, + [2] = &bt656_gate.hw, +}; void meson_g12a_media_init(void) { @@ -1024,6 +1074,22 @@ void meson_g12a_media_init(void) vpu_clkc_p1_gate.reg = clk_base + (unsigned long)(vpu_clkc_p1_gate.reg); vpu_clkc_mux.reg = clk_base + (unsigned long)(vpu_clkc_mux.reg); + /* bt656 clk */ + bt656_mux.reg = clk_base + (unsigned long)(bt656_mux.reg); + bt656_div.reg = clk_base + (unsigned long)(bt656_div.reg); + bt656_gate.reg = clk_base + (unsigned long)(bt656_gate.reg); + + clks[CLKID_BT656_COMP] = clk_register_composite(NULL, + "bt656_composite", + bt656_parent_names, ARRAY_SIZE(bt656_parent_names), + bt656_clk_hws[0], &clk_mux_ops, + bt656_clk_hws[1], &clk_divider_ops, + bt656_clk_hws[2], &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_BT656_COMP])) + panic("%s: %d clk_register_composite bt656_composite error\n", + __func__, __LINE__); + + clks[CLKID_DSI_MEAS_COMP] = clk_register_composite(NULL, "dsi_meas_composite", g12a_meas_parent_names, 8, diff --git a/include/dt-bindings/clock/amlogic,g12a-clkc.h b/include/dt-bindings/clock/amlogic,g12a-clkc.h index 6cf7109d2397..5d0da79ab6f3 100644 --- a/include/dt-bindings/clock/amlogic,g12a-clkc.h +++ b/include/dt-bindings/clock/amlogic,g12a-clkc.h @@ -249,8 +249,12 @@ #define CLKID_VPU_CLKC_P1_GATE (CLKID_MEDIA_BASE + 67) #define CLKID_VPU_CLKC_P1_COMP (CLKID_MEDIA_BASE + 68) #define CLKID_VPU_CLKC_MUX (CLKID_MEDIA_BASE + 69) +#define CLKID_BT656_MUX (CLKID_MEDIA_BASE + 70) +#define CLKID_BT656_DIV (CLKID_MEDIA_BASE + 71) +#define CLKID_BT656_GATE (CLKID_MEDIA_BASE + 72) +#define CLKID_BT656_COMP (CLKID_MEDIA_BASE + 73) -#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 70) +#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 74) #define CLKID_SPICC0_MUX (CLKID_MISC_BASE + 0) #define CLKID_SPICC0_DIV (CLKID_MISC_BASE + 1) #define CLKID_SPICC0_GATE (CLKID_MISC_BASE + 2) @@ -259,7 +263,7 @@ #define CLKID_SPICC1_DIV (CLKID_MISC_BASE + 5) #define CLKID_SPICC1_GATE (CLKID_MISC_BASE + 6) #define CLKID_SPICC1_COMP (CLKID_MISC_BASE + 7) -#define CLKID_TS_COMP (CLKID_MISC_BASE + 8) +#define CLKID_TS_COMP (CLKID_MISC_BASE + 8) /*gpio 12M/24M */ #define CLKID_24M (CLKID_MISC_BASE + 9) From a91f210194ec03ae33a4ed7fe5662c266735ebde Mon Sep 17 00:00:00 2001 From: Bichao Zheng Date: Fri, 15 Feb 2019 16:34:28 +0800 Subject: [PATCH 0023/1060] gpio_led: g12a: give up using led-trigger cpu0 [1/1] PD#SWPL-4876 Problem: 32bit will operate led-trigger cpu0 in cpu idle enter/exit causing system led flashing. Solution: give up using led-trigger cpu0. Verify: g12a_u211 g12a_u212 Change-Id: I106a4fe0e35923919f5bbc34113fa73a4ca28577 Signed-off-by: Bichao Zheng Signed-off-by: Luan Yuan Conflicts: arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts --- arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts | 2 -- .../boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 2 -- arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts | 2 -- arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 -- .../arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts | 2 -- .../boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 2 -- arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts | 2 -- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 -- .../boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts | 2 -- 28 files changed, 56 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index 03a40b29b100..a411b2f739c5 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -167,8 +167,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 70a6efda37fc..05174860d62e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -171,8 +171,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 4441fcc9b185..0b38e1b2aa36 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -149,8 +149,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index a960b7439f0e..831d29630f45 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index f533037eb344..05fd700357c2 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index c3e236146c7b..7d821fa26a33 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -188,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index cd970a2bbb0c..9952476b0424 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -189,8 +189,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 231f350a8064..f3480dc20aa5 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -177,8 +177,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index a3ae0f1f1cfb..69d17f5c926c 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -167,8 +167,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index 58073e20078b..56d98e6cc852 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -188,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index aed00d038bc7..5c7824cd91b7 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -193,8 +193,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index f3fd8d376006..89b9b149491d 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -167,8 +167,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 83937103b82e..c79d77064d3c 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -193,8 +193,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index b1b2676c8b2b..cc4f10695891 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -159,8 +159,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index bda0c8a24e39..77e0504f3e7f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -165,8 +165,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 1fe4278e5257..eff237c73647 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -165,8 +165,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 1b5bb0f0155b..3c79d049f01a 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -149,8 +149,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index bbbbb344343b..c7118a465172 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 927ef1bb2e29..a87ba00450e5 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index d45f54b86f3d..d84451ffcd90 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -188,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index c463f06ac21a..31390b856b8a 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -189,8 +189,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 88edd7a1e77a..723cc701a3a1 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -177,8 +177,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index c2ac3e54fafe..b05d3e8f4f72 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -167,8 +167,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index 83da45b4fdb6..c36e1df7de56 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -188,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 80821091057e..02662aac9d9f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -189,8 +189,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 0d3a73079a8e..09a878dba49b 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -167,8 +167,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 5d81dd3c4217..3e12ebcd6088 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -193,8 +193,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 6a304e48ccf0..e087c6b04fd9 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -159,8 +159,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; From 6f9b3340a2db6351d05f74fe4d9aafb497198357 Mon Sep 17 00:00:00 2001 From: Ruixuan Li Date: Tue, 8 Jan 2019 18:33:59 +0800 Subject: [PATCH 0024/1060] emmc: modify dtb malloc method [1/1] PD#SWPL-3951 Problem: buffer malloc for dtb may failed Solution: malloc may sleep to wait for enough memory Verify: pass on p212 Change-Id: Ib4c266c17140d2a6abf2aea6c02b2ff591f0fe08 Signed-off-by: Ruixuan Li --- drivers/amlogic/mmc/emmc_partitions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/mmc/emmc_partitions.c b/drivers/amlogic/mmc/emmc_partitions.c index 076f90aa1f39..12b11e52dedc 100644 --- a/drivers/amlogic/mmc/emmc_partitions.c +++ b/drivers/amlogic/mmc/emmc_partitions.c @@ -274,7 +274,7 @@ int amlmmc_dtb_read(struct mmc_card *card, memset(buf, 0x0, len); start_blk = MMC_DTB_PART_OFFSET; - buffer = kmalloc(CONFIG_DTB_SIZE, GFP_KERNEL); + buffer = kmalloc(CONFIG_DTB_SIZE, GFP_KERNEL|__GFP_RECLAIM); if (!buffer) return -ENOMEM; From db61a3d4777b91df232892e9a867fb4c4e8f9d3e Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 3 Jan 2019 15:50:50 +0800 Subject: [PATCH 0025/1060] ge2d: add ge2d dma_buf support [1/2] PD#SWPL-4036 Problem: don't support dma_buf Solution: add ge2d dma_buf support Verify: test pass on w400 Change-Id: I1277d04fb30753e579d5edc5f46f2406dc27217a Signed-off-by: Pengcheng Chen Signed-off-by: Luan Yuan --- MAINTAINERS | 5 + drivers/amlogic/media/common/ge2d/Makefile | 3 +- .../amlogic/media/common/ge2d/ge2d_dmabuf.c | 634 +++++++++++++++++ .../amlogic/media/common/ge2d/ge2d_dmabuf.h | 81 +++ drivers/amlogic/media/common/ge2d/ge2d_main.c | 261 +++++++ drivers/amlogic/media/common/ge2d/ge2d_wq.c | 637 ++++++++++++++++++ drivers/amlogic/media/common/ge2d/ge2d_wq.h | 5 + include/linux/amlogic/media/ge2d/ge2d.h | 80 +++ 8 files changed, 1705 insertions(+), 1 deletion(-) create mode 100644 drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c create mode 100644 drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h diff --git a/MAINTAINERS b/MAINTAINERS index f63a2fd700d4..ee27f3a2ea37 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14743,6 +14743,11 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c F: drivers/amlogic/media/common/vfm/vfm.c F: include/linux/amlogic/media/camera/* +AMLOGIC multimedia +M: Pengcheng Chen +F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h + AMLOGIC VIDEOSYNC M: Jintao Xu F: drivers/amlogic/media/video_processor/videosync/Kconfig diff --git a/drivers/amlogic/media/common/ge2d/Makefile b/drivers/amlogic/media/common/ge2d/Makefile index 666b3f396535..c5ad76327c0b 100644 --- a/drivers/amlogic/media/common/ge2d/Makefile +++ b/drivers/amlogic/media/common/ge2d/Makefile @@ -5,7 +5,8 @@ ge2d-objs = bitblt.o \ ge2d_wq.o \ stretchblt.o \ ge2d_main.o \ - blend.o + blend.o \ + ge2d_dmabuf.o obj-$(CONFIG_AMLOGIC_MEDIA_GE2D) += ge2d.o ccflags-y += -Iinclude/linux/media/ge2d/ diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c new file mode 100644 index 000000000000..e5d6b658dcbc --- /dev/null +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -0,0 +1,634 @@ +/* + * drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ge2d_log.h" +#include "ge2d_dmabuf.h" + +/* dma free*/ +static void aml_dma_put(void *buf_priv) +{ + struct aml_dma_buf *buf = buf_priv; + + if (!atomic_dec_and_test(&buf->refcount)) { + ge2d_log_dbg("aml_dma_put, refcont=%d\n", + atomic_read(&buf->refcount)); + return; + } + if (buf->sgt_base) { + sg_free_table(buf->sgt_base); + kfree(buf->sgt_base); + } + dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, + buf->attrs); + put_device(buf->dev); + kfree(buf); + ge2d_log_dbg("aml_dma_put free!\n"); +} + +static void *aml_dma_alloc(struct device *dev, unsigned long attrs, + unsigned long size, enum dma_data_direction dma_dir, + gfp_t gfp_flags) +{ + struct aml_dma_buf *buf; + + if (WARN_ON(!dev)) + return (void *)(-EINVAL); + + buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL); + if (!buf) + return NULL; + + if (attrs) + buf->attrs = attrs; + buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, + gfp_flags, buf->attrs); + if (!buf->cookie) { + dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); + kfree(buf); + return NULL; + } + + if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) + buf->vaddr = buf->cookie; + + /* Prevent the device from being released while the buffer is used */ + buf->dev = get_device(dev); + buf->size = size; + buf->dma_dir = dma_dir; + + atomic_inc(&buf->refcount); + ge2d_log_dbg("aml_dma_alloc, refcont=%d\n", + atomic_read(&buf->refcount)); + + return buf; +} + +static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) +{ + struct aml_dma_buf *buf = buf_priv; + int ret; + + if (!buf) { + pr_err("No buffer to map\n"); + return -EINVAL; + } + + /* + * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to + * map whole buffer + */ + vma->vm_pgoff = 0; + + ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, + buf->dma_addr, buf->size, buf->attrs); + + if (ret) { + pr_err("Remapping memory failed, error: %d\n", ret); + return ret; + } + ge2d_log_dbg("mapped dma addr 0x%08lx at 0x%08lx, size %d\n", + (unsigned long)buf->dma_addr, vma->vm_start, + buf->size); + return 0; +} + +/*********************************************/ +/* DMABUF ops for exporters */ +/*********************************************/ +struct aml_attachment { + struct sg_table sgt; + enum dma_data_direction dma_dir; +}; + +static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, + struct dma_buf_attachment *dbuf_attach) +{ + struct aml_attachment *attach; + unsigned int i; + struct scatterlist *rd, *wr; + struct sg_table *sgt; + struct aml_dma_buf *buf = dbuf->priv; + int ret; + + attach = kzalloc(sizeof(*attach), GFP_KERNEL); + if (!attach) + return -ENOMEM; + + sgt = &attach->sgt; + /* Copy the buf->base_sgt scatter list to the attachment, as we can't + * map the same scatter list to multiple attachments at the same time. + */ + ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL); + if (ret) { + kfree(attach); + return -ENOMEM; + } + + rd = buf->sgt_base->sgl; + wr = sgt->sgl; + for (i = 0; i < sgt->orig_nents; ++i) { + sg_set_page(wr, sg_page(rd), rd->length, rd->offset); + rd = sg_next(rd); + wr = sg_next(wr); + } + + attach->dma_dir = DMA_NONE; + dbuf_attach->priv = attach; + + return 0; +} + +static void aml_dmabuf_ops_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *db_attach) +{ + struct aml_attachment *attach = db_attach->priv; + struct sg_table *sgt; + + if (!attach) + return; + + sgt = &attach->sgt; + + /* release the scatterlist cache */ + if (attach->dma_dir != DMA_NONE) + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + sg_free_table(sgt); + kfree(attach); + db_attach->priv = NULL; + +} + +static struct sg_table *aml_dmabuf_ops_map( + struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir) +{ + struct aml_attachment *attach = db_attach->priv; + /* stealing dmabuf mutex to serialize map/unmap operations */ + struct mutex *lock = &db_attach->dmabuf->lock; + struct sg_table *sgt; + + mutex_lock(lock); + + sgt = &attach->sgt; + /* return previously mapped sg table */ + if (attach->dma_dir == dma_dir) { + mutex_unlock(lock); + return sgt; + } + + /* release any previous cache */ + if (attach->dma_dir != DMA_NONE) { + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + attach->dma_dir = DMA_NONE; + } + + /* mapping to the client with new direction */ + sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + dma_dir); + if (!sgt->nents) { + pr_err("failed to map scatterlist\n"); + mutex_unlock(lock); + return (void *)(-EIO); + } + + attach->dma_dir = dma_dir; + + mutex_unlock(lock); + return sgt; +} + +static void aml_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach, + struct sg_table *sgt, enum dma_data_direction dma_dir) +{ + /* nothing to be done here */ +} + +static void aml_dmabuf_ops_release(struct dma_buf *dbuf) +{ + /* drop reference obtained in vb2_dc_get_dmabuf */ + aml_dma_put(dbuf->priv); +} + +static void *aml_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL; +} + +static void *aml_dmabuf_ops_vmap(struct dma_buf *dbuf) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr; +} + +static int aml_dmabuf_ops_mmap(struct dma_buf *dbuf, + struct vm_area_struct *vma) +{ + return aml_dma_mmap(dbuf->priv, vma); +} + +static struct dma_buf_ops ge2d_dmabuf_ops = { + .attach = aml_dmabuf_ops_attach, + .detach = aml_dmabuf_ops_detach, + .map_dma_buf = aml_dmabuf_ops_map, + .unmap_dma_buf = aml_dmabuf_ops_unmap, + .kmap = aml_dmabuf_ops_kmap, + .kmap_atomic = aml_dmabuf_ops_kmap, + .vmap = aml_dmabuf_ops_vmap, + .mmap = aml_dmabuf_ops_mmap, + .release = aml_dmabuf_ops_release, +}; + +static struct sg_table *get_base_sgt(struct aml_dma_buf *buf) +{ + int ret; + struct sg_table *sgt; + + sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sgt) + return NULL; + + ret = dma_get_sgtable(buf->dev, sgt, buf->cookie, + buf->dma_addr, buf->size); + if (ret < 0) { + dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); + kfree(sgt); + return NULL; + } + return sgt; +} + +static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) +{ + struct aml_dma_buf *buf = buf_priv; + struct dma_buf *dbuf; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + exp_info.ops = &ge2d_dmabuf_ops; + exp_info.size = buf->size; + exp_info.flags = flags; + exp_info.priv = buf; + + if (!buf->sgt_base) + buf->sgt_base = get_base_sgt(buf); + + if (WARN_ON(!buf->sgt_base)) + return NULL; + + dbuf = dma_buf_export(&exp_info); + if (IS_ERR(dbuf)) + return NULL; + + /* dmabuf keeps reference to vb2 buffer */ + atomic_inc(&buf->refcount); + ge2d_log_dbg("get_dmabuf, refcount=%d\n", + atomic_read(&buf->refcount)); + return dbuf; +} + +/* ge2d dma-buf api.h*/ +static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) +{ + int i; + int found = 0; + + for (i = 0; i < AML_MAX_DMABUF; i++) { + if (buffer->gd_buffer[i].alloc) + continue; + else { + ge2d_log_dbg("find_empty_dma_buffer i=%d\n", i); + found = 1; + break; + } + } + if (found) + return i; + else + return -1; +} + +void *ge2d_dma_buffer_create(void) +{ + int i; + struct aml_dma_buffer *buffer; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return NULL; + + mutex_init(&buffer->lock); + for (i = 0; i < AML_MAX_DMABUF; i++) { + buffer->gd_buffer[i].mem_priv = NULL; + buffer->gd_buffer[i].index = 0; + buffer->gd_buffer[i].alloc = 0; + } + return buffer; +} + +void ge2d_dma_buffer_destroy(struct aml_dma_buffer *buffer) +{ + kfree(buffer); +} + +int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct ge2d_dmabuf_req_s *ge2d_req_buf) +{ + void *buf; + unsigned int size; + int index; + + if (WARN_ON(!dev)) + return (-EINVAL); + if (!ge2d_req_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + size = PAGE_ALIGN(ge2d_req_buf->len); + if (size == 0) + return (-EINVAL); + + index = find_empty_dma_buffer(buffer); + if ((index < 0) || (index >= AML_MAX_DMABUF)) { + pr_err("no empty buffer found\n"); + return (-ENOMEM); + } + + buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir, + GFP_HIGHUSER | __GFP_ZERO); + if (!buf) + return (-ENOMEM); + + mutex_lock(&(buffer->lock)); + buffer->gd_buffer[index].mem_priv = buf; + buffer->gd_buffer[index].index = index; + buffer->gd_buffer[index].alloc = 1; + mutex_unlock(&(buffer->lock)); + ge2d_req_buf->index = index; + return 0; +} + +int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index) +{ + struct aml_dma_buf *buf; + + if (!buffer) + return (-EINVAL); + if ((index < 0) || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + aml_dma_put(buf); + return 0; +} + +int ge2d_dma_buffer_export(struct aml_dma_buffer *buffer, + struct ge2d_dmabuf_exp_s *ge2d_exp_buf) +{ + struct aml_dma_buf *buf; + struct dma_buf *dbuf; + int ret, index; + unsigned int flags; + + if (!ge2d_exp_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + index = ge2d_exp_buf->index; + if ((index < 0) || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + flags = ge2d_exp_buf->flags; + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + + dbuf = get_dmabuf(buf, flags & O_ACCMODE); + if (IS_ERR_OR_NULL(dbuf)) { + pr_err("failed to export buffer %d\n", index); + return -EINVAL; + } + ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE); + if (ret < 0) { + pr_err("buffer %d, failed to export (%d)\n", + index, ret); + dma_buf_put(dbuf); + return ret; + } + + ge2d_log_dbg("buffer %d,exported as %d descriptor\n", + index, ret); + ge2d_exp_buf->fd = ret; + return 0; +} + +int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg) +{ + long ret = -1; + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { + pr_err("error input param"); + return -EINVAL; + } + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + + dbuf = dma_buf_get(fd); + if (dbuf == NULL) { + pr_err("failed to get dma buffer"); + return -EINVAL; + } + + d_att = dma_buf_attach(dbuf, dev); + if (d_att == NULL) { + pr_err("failed to set dma attach"); + goto attach_err; + } + + sg = dma_buf_map_attachment(d_att, dir); + if (sg == NULL) { + pr_err("failed to get dma sg"); + goto map_attach_err; + } + + ret = dma_buf_begin_cpu_access(dbuf, dir); + if (ret != 0) { + pr_err("failed to access dma buff"); + goto access_err; + } + + vaddr = dma_buf_vmap(dbuf); + if (vaddr == NULL) { + pr_err("failed to vmap dma buf"); + goto vmap_err; + } + cfg->dbuf = dbuf; + cfg->attach = d_att; + cfg->vaddr = vaddr; + cfg->sg = sg; + return ret; + +vmap_err: + dma_buf_end_cpu_access(dbuf, dir); + +access_err: + dma_buf_unmap_attachment(d_att, sg, dir); + +map_attach_err: + dma_buf_detach(dbuf, d_att); + +attach_err: + dma_buf_put(dbuf); + + return ret; +} + +int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) +{ + struct sg_table *sg_table; + struct page *page; + int ret; + + ret = ge2d_dma_buffer_map(cfg); + if (ret < 0) { + pr_err("gdc_dma_buffer_map failed\n"); + return ret; + } + if (cfg->sg) { + sg_table = cfg->sg; + page = sg_page(sg_table->sgl); + *addr = PFN_PHYS(page_to_pfn(page)); + ret = 0; + } + ge2d_dma_buffer_unmap(cfg); + return ret; +} + +void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg) +{ + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL + || cfg->dbuf == NULL || cfg->vaddr == NULL + || cfg->attach == NULL || cfg->sg == NULL) { + pr_err("Error input param"); + return; + } + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + dbuf = cfg->dbuf; + vaddr = cfg->vaddr; + d_att = cfg->attach; + sg = cfg->sg; + + dma_buf_vunmap(dbuf, vaddr); + + dma_buf_end_cpu_access(dbuf, dir); + + dma_buf_unmap_attachment(d_att, sg, dir); + + dma_buf_detach(dbuf, d_att); + + dma_buf_put(dbuf); +} + +void ge2d_dma_buffer_dma_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + ge2d_log_dbg("ge2d_dma_buffer_dma_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if (buf->size > 0) + dma_sync_single_for_device(buf->dev, buf->dma_addr, + buf->size, DMA_TO_DEVICE); + dma_buf_put(dmabuf); +} + +void ge2d_dma_buffer_cache_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + ge2d_log_dbg("ge2d_dma_buffer_cache_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if (buf->size > 0) + dma_sync_single_for_device(buf->dev, buf->dma_addr, + buf->size, DMA_FROM_DEVICE); + dma_buf_put(dmabuf); +} + + diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h new file mode 100644 index 000000000000..85dc94b5d19f --- /dev/null +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h @@ -0,0 +1,81 @@ +/* + * drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _GE2D_DMABUF_H_ +#define _GE2D_DMABUF_H_ + +#include +#include +#include + +/* Amlogic Headers */ +#include + +#define AML_MAX_DMABUF 32 + +struct aml_dma_buf { + struct device *dev; + void *cookie; + void *vaddr; + unsigned int size; + enum dma_data_direction dma_dir; + unsigned long attrs; + unsigned int index; + dma_addr_t dma_addr; + atomic_t refcount; + struct sg_table *sgt_base; + /* DMABUF related */ + struct dma_buf_attachment *db_attach; +}; + +struct aml_dma_buf_priv { + void *mem_priv; + int index; + unsigned int alloc; + struct dma_buf *dbuf; +}; + +struct aml_dma_buffer { + struct mutex lock; + struct aml_dma_buf_priv gd_buffer[AML_MAX_DMABUF]; +}; + +struct aml_dma_cfg { + int fd; + void *dev; + void *vaddr; + struct dma_buf *dbuf; + struct dma_buf_attachment *attach; + struct sg_table *sg; + enum dma_data_direction dir; +}; + + +void *ge2d_dma_buffer_create(void); +void ge2d_dma_buffer_destroy(struct aml_dma_buffer *buffer); +int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct ge2d_dmabuf_req_s *ge2d_req_buf); +int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index); +int ge2d_dma_buffer_export(struct aml_dma_buffer *buffer, + struct ge2d_dmabuf_exp_s *ge2d_exp_buf); +int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg); +void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg); +int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr); +void ge2d_dma_buffer_dma_flush(struct device *dev, int fd); +void ge2d_dma_buffer_cache_flush(struct device *dev, int fd); +#endif diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 666f675f1e61..7a768ce8a5be 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_COMPAT @@ -47,6 +48,7 @@ #include "ge2dgen.h" #include "ge2d_log.h" #include "ge2d_wq.h" +#include "ge2d_dmabuf.h" #define GE2D_CLASS_NAME "ge2d" #define MAX_GE2D_CLK 500000000 @@ -210,6 +212,197 @@ static int ge2d_open(struct inode *inode, struct file *file) return 0; } +static int ge2d_ioctl_config_ex_mem(struct ge2d_context_s *context, + unsigned int cmd, unsigned long args) +{ + struct config_para_ex_memtype_s *ge2d_config_ex_mem; + struct config_ge2d_para_ex_s ge2d_para_config; + int ret = 0; +#ifdef CONFIG_COMPAT + struct compat_config_para_ex_memtype_s __user *uf_ex_mem; + struct compat_config_ge2d_para_ex_s __user *uf_ge2d_para; + int r = 0; + int i, j; +#endif + void __user *argp = (void __user *)args; + + memset(&ge2d_para_config, 0, sizeof(struct config_ge2d_para_ex_s)); + switch (cmd) { + case GE2D_CONFIG_EX_MEM: + ret = copy_from_user(&ge2d_para_config, argp, + sizeof(struct config_ge2d_para_ex_s)); + ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype); + ret = ge2d_context_config_ex_mem(context, ge2d_config_ex_mem); + break; +#ifdef CONFIG_COMPAT + case GE2D_CONFIG_EX32_MEM: + uf_ge2d_para = (struct compat_config_ge2d_para_ex_s *)argp; + r |= get_user(ge2d_para_config.para_config_memtype.ge2d_magic, + &uf_ge2d_para->para_config_memtype.ge2d_magic); + ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype); + + if (ge2d_para_config.para_config_memtype.ge2d_magic + == sizeof(struct config_para_ex_memtype_s)) { + struct config_para_ex_ion_s *pge2d_config_ex; + + uf_ex_mem = + (struct compat_config_para_ex_memtype_s *)argp; + pge2d_config_ex = + &(ge2d_config_ex_mem->_ge2d_config_ex); + r = copy_from_user( + &pge2d_config_ex->src_para, + &uf_ex_mem->_ge2d_config_ex.src_para, + sizeof(struct src_dst_para_ex_s)); + r |= copy_from_user( + &pge2d_config_ex->src2_para, + &uf_ex_mem->_ge2d_config_ex.src2_para, + sizeof(struct src_dst_para_ex_s)); + r |= copy_from_user( + &pge2d_config_ex->dst_para, + &uf_ex_mem->_ge2d_config_ex.dst_para, + sizeof(struct src_dst_para_ex_s)); + r |= copy_from_user(&pge2d_config_ex->src_key, + &uf_ex_mem->_ge2d_config_ex.src_key, + sizeof(struct src_key_ctrl_s)); + r |= copy_from_user(&pge2d_config_ex->src2_key, + &uf_ex_mem->_ge2d_config_ex.src2_key, + sizeof(struct src_key_ctrl_s)); + + r |= get_user(pge2d_config_ex->src1_cmult_asel, + &uf_ex_mem->_ge2d_config_ex.src1_cmult_asel); + r |= get_user(pge2d_config_ex->src2_cmult_asel, + &uf_ex_mem->_ge2d_config_ex.src2_cmult_asel); + r |= get_user(pge2d_config_ex->alu_const_color, + &uf_ex_mem->_ge2d_config_ex.alu_const_color); + r |= get_user(pge2d_config_ex->src1_gb_alpha_en, + &uf_ex_mem->_ge2d_config_ex.src1_gb_alpha_en); + r |= get_user(pge2d_config_ex->src1_gb_alpha, + &uf_ex_mem->_ge2d_config_ex.src1_gb_alpha); +#ifdef CONFIG_GE2D_SRC2 + r |= get_user(pge2d_config_ex->src2_gb_alpha_en, + &uf_ex_mem->_ge2d_config_ex.src2_gb_alpha_en); + r |= get_user(pge2d_config_ex->src2_gb_alpha, + &uf_ex_mem->_ge2d_config_ex.src2_gb_alpha); +#endif + r |= get_user(pge2d_config_ex->op_mode, + &uf_ex_mem->_ge2d_config_ex.op_mode); + r |= get_user(pge2d_config_ex->bitmask_en, + &uf_ex_mem->_ge2d_config_ex.bitmask_en); + r |= get_user(pge2d_config_ex->bytemask_only, + &uf_ex_mem->_ge2d_config_ex.bytemask_only); + r |= get_user(pge2d_config_ex->bitmask, + &uf_ex_mem->_ge2d_config_ex.bitmask); + r |= get_user(pge2d_config_ex->dst_xy_swap, + &uf_ex_mem->_ge2d_config_ex.dst_xy_swap); + r |= get_user(pge2d_config_ex->hf_init_phase, + &uf_ex_mem->_ge2d_config_ex.hf_init_phase); + r |= get_user(pge2d_config_ex->hf_rpt_num, + &uf_ex_mem->_ge2d_config_ex.hf_rpt_num); + r |= get_user(pge2d_config_ex->hsc_start_phase_step, + &uf_ex_mem->_ge2d_config_ex + .hsc_start_phase_step); + r |= get_user(pge2d_config_ex->hsc_phase_slope, + &uf_ex_mem->_ge2d_config_ex.hsc_phase_slope); + r |= get_user(pge2d_config_ex->vf_init_phase, + &uf_ex_mem->_ge2d_config_ex.vf_init_phase); + r |= get_user(pge2d_config_ex->vf_rpt_num, + &uf_ex_mem->_ge2d_config_ex.vf_rpt_num); + r |= get_user(pge2d_config_ex->vsc_start_phase_step, + &uf_ex_mem->_ge2d_config_ex + .vsc_start_phase_step); + r |= get_user(pge2d_config_ex->vsc_phase_slope, + &uf_ex_mem->_ge2d_config_ex.vsc_phase_slope); + r |= get_user( + pge2d_config_ex->src1_vsc_phase0_always_en, + &uf_ex_mem->_ge2d_config_ex + .src1_vsc_phase0_always_en); + r |= get_user( + pge2d_config_ex->src1_hsc_phase0_always_en, + &uf_ex_mem->_ge2d_config_ex + .src1_hsc_phase0_always_en); + r |= get_user( + pge2d_config_ex->src1_hsc_rpt_ctrl, + &uf_ex_mem->_ge2d_config_ex.src1_hsc_rpt_ctrl); + r |= get_user( + pge2d_config_ex->src1_vsc_rpt_ctrl, + &uf_ex_mem->_ge2d_config_ex.src1_vsc_rpt_ctrl); + + for (i = 0; i < 4; i++) { + struct config_planes_ion_s *psrc_planes; + + psrc_planes = + &pge2d_config_ex->src_planes[i]; + r |= get_user(psrc_planes->addr, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].addr); + r |= get_user(psrc_planes->w, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].w); + r |= get_user(psrc_planes->h, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].h); + r |= get_user(psrc_planes->shared_fd, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].shared_fd); + } + + for (i = 0; i < 4; i++) { + struct config_planes_ion_s *psrc2_planes; + + psrc2_planes = + &pge2d_config_ex->src2_planes[i]; + r |= get_user(psrc2_planes->addr, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].addr); + r |= get_user(psrc2_planes->w, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].w); + r |= get_user(psrc2_planes->h, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].h); + r |= get_user(psrc2_planes->shared_fd, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].shared_fd); + } + + for (j = 0; j < 4; j++) { + struct config_planes_ion_s *pdst_planes; + + pdst_planes = + &pge2d_config_ex->dst_planes[j]; + r |= get_user(pdst_planes->addr, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].addr); + r |= get_user(pdst_planes->w, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].w); + r |= get_user(pdst_planes->h, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].h); + r |= get_user(pdst_planes->shared_fd, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].shared_fd); + } + + r |= get_user(ge2d_config_ex_mem->src1_mem_alloc_type, + &uf_ex_mem->src1_mem_alloc_type); + r |= get_user(ge2d_config_ex_mem->src2_mem_alloc_type, + &uf_ex_mem->src2_mem_alloc_type); + r |= get_user(ge2d_config_ex_mem->dst_mem_alloc_type, + &uf_ex_mem->dst_mem_alloc_type); + + } + if (r) { + pr_err("GE2D_CONFIG_EX32 get parameter failed .\n"); + return -EFAULT; + } + ret = ge2d_context_config_ex_mem(context, ge2d_config_ex_mem); + break; +#endif + } + return ret; +} + static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) { struct ge2d_context_s *context = NULL; @@ -217,6 +410,8 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) struct ge2d_para_s para; struct config_para_ex_s ge2d_config_ex; struct config_para_ex_ion_s ge2d_config_ex_ion; + struct ge2d_dmabuf_req_s ge2d_req_buf; + struct ge2d_dmabuf_exp_s ge2d_exp_buf; int ret = 0; #ifdef CONFIG_COMPAT struct compat_config_para_s __user *uf; @@ -226,12 +421,15 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) int i, j; #endif int cap_mask = 0; + int index = 0, dma_fd; void __user *argp = (void __user *)args; context = (struct ge2d_context_s *)filp->private_data; memset(&ge2d_config, 0, sizeof(struct config_para_s)); memset(&ge2d_config_ex, 0, sizeof(struct config_para_ex_s)); memset(&ge2d_config_ex_ion, 0, sizeof(struct config_para_ex_ion_s)); + memset(&ge2d_req_buf, 0, sizeof(struct ge2d_dmabuf_req_s)); + memset(&ge2d_exp_buf, 0, sizeof(struct ge2d_dmabuf_exp_s)); #ifdef CONFIG_AMLOGIC_MEDIA_GE2D_MORE_SECURITY switch (cmd) { case GE2D_CONFIG: @@ -538,6 +736,39 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) case GE2D_SET_COEF: case GE2D_ANTIFLICKER_ENABLE: break; + case GE2D_REQUEST_BUFF: + ret = copy_from_user(&ge2d_req_buf, argp, + sizeof(struct ge2d_dmabuf_req_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; + case GE2D_EXP_BUFF: + ret = copy_from_user(&ge2d_exp_buf, argp, + sizeof(struct ge2d_dmabuf_exp_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; + case GE2D_FREE_BUFF: + ret = copy_from_user(&index, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; + case GE2D_SYNC_DEVICE: + case GE2D_SYNC_CPU: + ret = copy_from_user(&dma_fd, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; case GE2D_CONFIG_OLD: case GE2D_CONFIG_EX_OLD: case GE2D_SRCCOLORKEY_OLD: @@ -568,6 +799,12 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) #endif ret = ge2d_context_config_ex_ion(context, &ge2d_config_ex_ion); break; + case GE2D_CONFIG_EX_MEM: +#ifdef CONFIG_COMPAT + case GE2D_CONFIG_EX32_MEM: +#endif + ret = ge2d_ioctl_config_ex_mem(context, cmd, args); + break; case GE2D_SET_COEF: ge2d_wq_set_scale_coef(context, args & 0xff, args >> 16); break; @@ -744,6 +981,27 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) para.dst_rect.x, para.dst_rect.y, para.dst_rect.w, para.dst_rect.h); break; + case GE2D_REQUEST_BUFF: + ret = ge2d_buffer_alloc(&ge2d_req_buf); + if (ret == 0) + ret = copy_to_user(argp, &ge2d_req_buf, + sizeof(struct ge2d_dmabuf_req_s)); + break; + case GE2D_EXP_BUFF: + ret = ge2d_buffer_export(&ge2d_exp_buf); + if (ret == 0) + ret = copy_to_user(argp, &ge2d_exp_buf, + sizeof(struct ge2d_dmabuf_exp_s)); + break; + case GE2D_FREE_BUFF: + ret = ge2d_buffer_free(index); + break; + case GE2D_SYNC_DEVICE: + ge2d_buffer_dma_flush(dma_fd); + break; + case GE2D_SYNC_CPU: + ge2d_buffer_cache_flush(dma_fd); + break; } return ret; } @@ -961,6 +1219,9 @@ static int ge2d_probe(struct platform_device *pdev) (void *)res.start, (int)resource_size(&res)); } } + ret = of_reserved_mem_device_init(&(pdev->dev)); + if (ret < 0) + ge2d_log_info("reserved mem init failed\n"); ret = ge2d_wq_init(pdev, irq, clk_gate); diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index a35947df88de..66ce8a1dacde 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -41,6 +41,7 @@ #include "ge2d_io.h" #include "ge2d_reg.h" #include "ge2d_wq.h" +#include "ge2d_dmabuf.h" #include "osd_io.h" #include "osd_hw.h" @@ -928,6 +929,49 @@ static int build_ge2d_addr_config_ion( return ret; } +static int build_ge2d_addr_config_dma( + struct config_planes_ion_s *plane, + unsigned int format, + unsigned int *addr, + unsigned int *stride, + unsigned int dir + ) +{ + int ret = -1; + int bpp_value = bpp(format); + unsigned long addr_temp = 0; + + bpp_value /= 8; + ge2d_log_dbg("build_ge2d_addr_config_ion bpp_value=%d\n", + bpp_value); + if (plane) { + if (plane[0].shared_fd) { + struct aml_dma_cfg cfg; + + cfg.fd = plane[0].shared_fd; + cfg.dev = &(ge2d_manager.pdev->dev); + cfg.dir = dir; + ret = ge2d_dma_buffer_get_phys(&cfg, &addr_temp); + if (ret != 0) + return ret; + } + plane[0].addr += addr_temp; + if (plane[0].addr) { + *addr = plane[0].addr; + *stride = plane[0].w * bpp_value; + ret = 0; + } + /* not support multi-src_planes */ + if ((plane[1].addr) || + (plane[2].addr) || + (plane[3].addr)) { + ge2d_log_info("ge2d not support NV21 mode\n"); + ret = -1; + } + } + return ret; +} + static int build_ge2d_config_ex(struct config_planes_s *plane, unsigned int format, unsigned int *canvas_index, @@ -1066,6 +1110,84 @@ static int build_ge2d_config_ex_ion(struct config_planes_ion_s *plane, } return ret; } +static int build_ge2d_config_ex_dma(struct config_planes_ion_s *plane, + unsigned int format, + unsigned int *canvas_index, + int index, + unsigned int *r_offset, + unsigned int dir) +{ + int bpp_value = bpp(format); + int ret = -1; + unsigned long addr; + + bpp_value /= 8; + index &= 0xff; + if (plane) { + if (plane[0].shared_fd) { + struct aml_dma_cfg cfg; + + cfg.fd = plane[0].shared_fd; + cfg.dev = &(ge2d_manager.pdev->dev); + cfg.dir = dir; + ret = ge2d_dma_buffer_get_phys(&cfg, &addr); + ge2d_log_info("phys: addr=%lx\n", addr); + if (ret != 0) + return ret; + + plane[0].addr += addr; + *canvas_index = index; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[0].addr, + plane[0].w * bpp_value, + plane[0].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + ret = 0; + } + /* multi-src_planes */ + if (plane[1].addr) { + plane[1].addr += plane[0].addr; + *canvas_index |= index << 8; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[1].addr, + plane[1].w * bpp_value, + plane[1].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + if (plane[2].addr) { + plane[2].addr += plane[0].addr; + *canvas_index |= index << 16; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[2].addr, + plane[2].w * bpp_value, + plane[2].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + if (plane[3].addr) { + plane[3].addr += plane[0].addr; + *canvas_index |= index << 24; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[3].addr, + plane[3].w * bpp_value, + plane[3].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + } + return ret; +} + int ge2d_context_config_ex(struct ge2d_context_s *context, struct config_para_ex_s *ge2d_config) { @@ -1814,6 +1936,516 @@ int ge2d_context_config_ex_ion(struct ge2d_context_s *context, return 0; } +int ge2d_context_config_ex_mem(struct ge2d_context_s *context, + struct config_para_ex_memtype_s *ge2d_config_mem) +{ + struct src_dst_para_s tmp; + unsigned int index = 0; + unsigned int alloc_canvas_offset = 0; + struct ge2d_src1_gen_s *src1_gen_cfg; + struct ge2d_src2_dst_data_s *src2_dst_data_cfg; + struct ge2d_src2_dst_gen_s *src2_dst_gen_cfg; + struct ge2d_dp_gen_s *dp_gen_cfg; + struct ge2d_cmd_s *ge2d_cmd_cfg; + int top, left, width, height; + unsigned int src_addr = 0, src2_addr = 0, dst_addr = 0; + unsigned int src_stride = 0, src2_stride = 0, dst_stride = 0; + struct config_para_ex_ion_s *ge2d_config; + + ge2d_config = &(ge2d_config_mem->_ge2d_config_ex); + /* setup src and dst */ + switch (ge2d_config->src_para.mem_type) { + case CANVAS_OSD0: + case CANVAS_OSD1: + if (setup_display_property(&tmp, + (ge2d_config->src_para.mem_type == CANVAS_OSD0) ? + OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0) + return -1; + ge2d_config->src_para.canvas_index = tmp.canvas_index; + ge2d_config->src_para.format = tmp.ge2d_color_index; + src_addr = tmp.phy_addr; + src_stride = tmp.stride; + + ge2d_log_dbg("ge2d: src1-->type: osd%d, format: 0x%x !!\n", + ge2d_config->src_para.mem_type - CANVAS_OSD0, + ge2d_config->src_para.format); + + top = ge2d_config->src_para.top; + left = ge2d_config->src_para.left; + width = ge2d_config->src_para.width; + height = ge2d_config->src_para.height; + if ((left + width > tmp.xres) || + (top + height > tmp.yres)) { + ge2d_log_dbg("ge2d src error: out of range\n"); + return -1; + } + ge2d_config->src_para.width = tmp.xres; + ge2d_config->src_para.height = tmp.yres; + ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src_addr, + src_stride, + ge2d_config->src_para.format); + break; + case CANVAS_ALLOC: + top = ge2d_config->src_para.top; + left = ge2d_config->src_para.left; + width = ge2d_config->src_para.width; + height = ge2d_config->src_para.height; + if ((left + width > ge2d_config->src_planes[0].w) + || (top + height > ge2d_config->src_planes[0].h)) { + ge2d_log_dbg("ge2d error: src alloc, out of range\n"); + return -1; + } + if (ge2d_meson_dev.canvas_status == 1) { + if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_addr_config_ion( + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &src_addr, + &src_stride) < 0) + return -1; + ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src_addr, + src_stride, + ge2d_config->src_para.format); + } else if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_addr_config_dma( + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &src_addr, + &src_stride, + DMA_TO_DEVICE) < 0) + return -1; + ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src_addr, + src_stride, + ge2d_config->src_para.format); + } + } else { + if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_config_ex_ion( + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset) < 0) + return -1; + ge2d_config->src_para.canvas_index = index; + ge2d_log_dbg("ge2d ion alloc canvas index:0x%x, format:0x%x\n", + index, ge2d_config->src_para.format); + } else if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_config_ex_dma( + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset, + DMA_TO_DEVICE) < 0) + return -1; + ge2d_config->src_para.canvas_index = index; + ge2d_log_dbg("ge2d dma alloc canvas index:0x%x, format:0x%x\n", + index, ge2d_config->src_para.format); + } + } + break; + default: + break; + } + + switch (ge2d_config->src2_para.mem_type) { + case CANVAS_OSD0: + case CANVAS_OSD1: + if (setup_display_property(&tmp, + (ge2d_config->src2_para.mem_type == CANVAS_OSD0) ? + OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0) + return -1; + ge2d_config->src2_para.canvas_index = tmp.canvas_index; + ge2d_config->src2_para.format = tmp.ge2d_color_index; + src2_addr = tmp.phy_addr; + src2_stride = tmp.stride; + + ge2d_log_dbg("ge2d: src2-->type: osd%d, format: 0x%x !!\n", + ge2d_config->src2_para.mem_type - CANVAS_OSD0, + ge2d_config->src2_para.format); + + top = ge2d_config->src2_para.top; + left = ge2d_config->src2_para.left; + width = ge2d_config->src2_para.width; + height = ge2d_config->src2_para.height; + if ((left + width > tmp.xres) || (top + height > tmp.yres)) { + ge2d_log_dbg("ge2d error: src2: osd%d, out of range\n", + ge2d_config->src2_para.mem_type - CANVAS_OSD0); + return -1; + } + ge2d_config->src2_para.width = tmp.xres; + ge2d_config->src2_para.height = tmp.yres; + ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src2_addr, + src2_stride, + ge2d_config->src2_para.format); + break; + case CANVAS_ALLOC: + top = ge2d_config->src2_para.top; + left = ge2d_config->src2_para.left; + width = ge2d_config->src2_para.width; + height = ge2d_config->src2_para.height; + if ((left + width > ge2d_config->src2_planes[0].w) + || (top + height > ge2d_config->src2_planes[0].h)) { + ge2d_log_dbg("ge2d error: src2: alloc, out of range\n"); + return -1; + } + /*if (ge2d_config->src2_planes[0].addr == + * ge2d_config->src_planes[0].addr) + * index = ge2d_config->src_para.canvas_index; + * else + */ + if (ge2d_meson_dev.canvas_status == 1) { + if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_addr_config_ion( + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &src2_addr, + &src2_stride) < 0) + return -1; + ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src2_addr, + src2_stride, + ge2d_config->src2_para.format); + } else if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_addr_config_dma( + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &src2_addr, + &src2_stride, + DMA_TO_DEVICE) < 0) + return -1; + ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src2_addr, + src2_stride, + ge2d_config->src2_para.format); + } + } else { + if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_config_ex_ion( + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset) < 0) + return -1; + ge2d_config->src2_para.canvas_index = index; + ge2d_log_dbg("ge2d src2 ion alloc, canvas index:0x%x,format:0x%x\n", + index, ge2d_config->src2_para.format); + } else if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_config_ex_dma( + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset, + DMA_TO_DEVICE) < 0) + return -1; + ge2d_config->src2_para.canvas_index = index; + ge2d_log_dbg("ge2d src2 dma alloc, canvas index:0x%x,format:0x%x\n", + index, ge2d_config->src2_para.format); + } + } + break; + default: + break; + } + + switch (ge2d_config->dst_para.mem_type) { + case CANVAS_OSD0: + case CANVAS_OSD1: + if (setup_display_property(&tmp, + (ge2d_config->dst_para.mem_type == CANVAS_OSD0) ? + OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0) + return -1; + ge2d_config->dst_para.canvas_index = tmp.canvas_index; + ge2d_config->dst_para.format = tmp.ge2d_color_index; + dst_addr = tmp.phy_addr; + dst_stride = tmp.stride; + + ge2d_log_dbg("ge2d: dst-->type: osd%d, format: 0x%x !!\n", + ge2d_config->dst_para.mem_type - CANVAS_OSD0, + ge2d_config->dst_para.format); + + top = ge2d_config->dst_para.top; + left = ge2d_config->dst_para.left; + width = ge2d_config->dst_para.width; + height = ge2d_config->dst_para.height; + if ((left + width > tmp.xres) || (top + height > tmp.yres)) { + ge2d_log_dbg("ge2d error: dst: osd%d, out of range\n", + ge2d_config->dst_para.mem_type - CANVAS_OSD0); + return -1; + } + ge2d_config->dst_para.width = tmp.xres; + ge2d_config->dst_para.height = tmp.yres; + ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n", + dst_addr, + dst_stride, + ge2d_config->dst_para.format); + break; + case CANVAS_ALLOC: + top = ge2d_config->dst_para.top; + left = ge2d_config->dst_para.left; + width = ge2d_config->dst_para.width; + height = ge2d_config->dst_para.height; + if ((left + width > ge2d_config->dst_planes[0].w) + || (top + height > ge2d_config->dst_planes[0].h)) { + ge2d_log_dbg("ge2d error: dst: alloc, out of range\n"); + return -1; + } + /*if (ge2d_config->dst_planes[0].addr == + * ge2d_config->src_planes[0].addr) + * index = ge2d_config->src_para.canvas_index; + * else if (ge2d_config->dst_planes[0].addr == + * ge2d_config->src2_planes[0].addr) + * index = ge2d_config->src2_para.canvas_index; + * else + */ + if (ge2d_meson_dev.canvas_status == 1) { + if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_addr_config_ion( + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &dst_addr, + &dst_stride) < 0) + return -1; + ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + dst_addr, + dst_stride, + ge2d_config->dst_para.format); + } else if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_addr_config_dma( + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &dst_addr, + &dst_stride, + DMA_FROM_DEVICE) < 0) + return -1; + ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + dst_addr, + dst_stride, + ge2d_config->dst_para.format); + } + } else { + if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_config_ex_ion( + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset) < 0) + return -1; + ge2d_config->dst_para.canvas_index = index; + ge2d_log_dbg("ge2d: dst ion alloc, index:0x%x, format:0x%x\n", + index, ge2d_config->dst_para.format); + } else if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_config_ex_dma( + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset, + DMA_FROM_DEVICE) < 0) + return -1; + ge2d_config->dst_para.canvas_index = index; + ge2d_log_dbg("ge2d: dst dma alloc, index:0x%x, format:0x%x\n", + index, ge2d_config->dst_para.format); + } + } + break; + default: + break; + } + + ge2dgen_rendering_dir(context, ge2d_config->src_para.x_rev, + ge2d_config->src_para.y_rev, + ge2d_config->dst_para.x_rev, + ge2d_config->dst_para.y_rev, + ge2d_config->dst_xy_swap); + ge2dgen_const_color(context, ge2d_config->alu_const_color); + + ge2dgen_src(context, ge2d_config->src_para.canvas_index, + ge2d_config->src_para.format, + src_addr, + src_stride); + ge2dgen_src_clip(context, ge2d_config->src_para.left, + ge2d_config->src_para.top, + ge2d_config->src_para.width, + ge2d_config->src_para.height); + ge2dgen_src_key(context, ge2d_config->src_key.key_enable, + ge2d_config->src_key.key_color, + ge2d_config->src_key.key_mask, + ge2d_config->src_key.key_mode); +#ifdef CONFIG_GE2D_SRC2 + ge2dgent_src_gbalpha(context, ge2d_config->src1_gb_alpha, + ge2d_config->src2_gb_alpha); +#else + ge2dgent_src_gbalpha(context, ge2d_config->src1_gb_alpha, 0); +#endif + ge2dgen_src_color(context, ge2d_config->src_para.color); + + ge2dgen_src2(context, ge2d_config->src2_para.canvas_index, + ge2d_config->src2_para.format, + src2_addr, + src2_stride); + ge2dgen_src2_clip(context, ge2d_config->src2_para.left, + ge2d_config->src2_para.top, + ge2d_config->src2_para.width, + ge2d_config->src2_para.height); + + ge2dgen_dst(context, ge2d_config->dst_para.canvas_index, + ge2d_config->dst_para.format, + dst_addr, + dst_stride); + ge2dgen_dst_clip(context, ge2d_config->dst_para.left, + ge2d_config->dst_para.top, + ge2d_config->dst_para.width, + ge2d_config->dst_para.height, + DST_CLIP_MODE_INSIDE); + + src1_gen_cfg = ge2d_wq_get_src_gen(context); + src1_gen_cfg->fill_mode = ge2d_config->src_para.fill_mode; + src1_gen_cfg->chfmt_rpt_pix = 0; + src1_gen_cfg->cvfmt_rpt_pix = 0; + /* src1_gen_cfg->clipx_start_ex = 0; */ + /* src1_gen_cfg->clipx_end_ex = 1; */ + /* src1_gen_cfg->clipy_start_ex = 1; */ + /* src1_gen_cfg->clipy_end_ex = 1; */ + + src2_dst_data_cfg = ge2d_wq_get_dst_data(context); + src2_dst_data_cfg->src2_def_color = ge2d_config->src2_para.color; + + src2_dst_gen_cfg = ge2d_wq_get_dst_gen(context); + src2_dst_gen_cfg->src2_fill_mode = ge2d_config->src2_para.fill_mode; + + dp_gen_cfg = ge2d_wq_get_dp_gen(context); + + dp_gen_cfg->src1_vsc_phase0_always_en = + ge2d_config->src1_hsc_phase0_always_en; + dp_gen_cfg->src1_hsc_phase0_always_en = + ge2d_config->src1_vsc_phase0_always_en; + if ((context->config.v_scale_coef_type == FILTER_TYPE_GAU0) || + (context->config.v_scale_coef_type == FILTER_TYPE_GAU0_BOT) || + (context->config.v_scale_coef_type == FILTER_TYPE_GAU1) || + (context->config.h_scale_coef_type == FILTER_TYPE_GAU0) || + (context->config.h_scale_coef_type == FILTER_TYPE_GAU0_BOT) || + (context->config.h_scale_coef_type == FILTER_TYPE_GAU1)) { + /* 1bit, 0: using minus, 1: using repeat data */ + dp_gen_cfg->src1_hsc_rpt_ctrl = ge2d_config->src1_hsc_rpt_ctrl; + /* 1bit, 0: using minus 1: using repeat data */ + dp_gen_cfg->src1_vsc_rpt_ctrl = ge2d_config->src1_vsc_rpt_ctrl; + } else { + /* 1bit, 0: using minus, 1: using repeat data */ + dp_gen_cfg->src1_hsc_rpt_ctrl = 1; + /* 1bit, 0: using minus 1: using repeat data */ + dp_gen_cfg->src1_vsc_rpt_ctrl = 1; + } + dp_gen_cfg->src1_gb_alpha = ge2d_config->src1_gb_alpha & 0xff; + dp_gen_cfg->src1_gb_alpha_en = ge2d_config->src1_gb_alpha_en & 1; +#ifdef CONFIG_GE2D_SRC2 + dp_gen_cfg->src2_gb_alpha = ge2d_config->src2_gb_alpha & 0xff; + dp_gen_cfg->src2_gb_alpha_en = ge2d_config->src2_gb_alpha_en & 1; +#endif + dp_gen_cfg->src2_key_en = ge2d_config->src2_key.key_enable; + dp_gen_cfg->src2_key_mode = ge2d_config->src2_key.key_mode; + dp_gen_cfg->src2_key = ge2d_config->src2_key.key_color; + dp_gen_cfg->src2_key_mask = ge2d_config->src2_key.key_mask; + + dp_gen_cfg->bitmask_en = ge2d_config->bitmask_en; + dp_gen_cfg->bitmask = ge2d_config->bitmask; + dp_gen_cfg->bytemask_only = ge2d_config->bytemask_only; + + ge2d_cmd_cfg = ge2d_wq_get_cmd(context); + + ge2d_cmd_cfg->src1_fill_color_en = ge2d_config->src_para.fill_color_en; + + ge2d_cmd_cfg->src2_x_rev = ge2d_config->src2_para.x_rev; + ge2d_cmd_cfg->src2_y_rev = ge2d_config->src2_para.y_rev; + ge2d_cmd_cfg->src2_fill_color_en = + ge2d_config->src2_para.fill_color_en; +#ifdef CONFIG_GE2D_SRC2 + ge2d_cmd_cfg->src2_cmult_ad = ge2d_config->src2_cmult_ad; +#endif + + ge2d_cmd_cfg->vsc_phase_slope = ge2d_config->vsc_phase_slope; + ge2d_cmd_cfg->vsc_ini_phase = ge2d_config->vf_init_phase; + ge2d_cmd_cfg->vsc_phase_step = ge2d_config->vsc_start_phase_step; + ge2d_cmd_cfg->vsc_rpt_l0_num = ge2d_config->vf_rpt_num; + + /* let internal decide */ + ge2d_cmd_cfg->hsc_phase_slope = ge2d_config->hsc_phase_slope; + ge2d_cmd_cfg->hsc_ini_phase = ge2d_config->hf_init_phase; + ge2d_cmd_cfg->hsc_phase_step = ge2d_config->hsc_start_phase_step; + ge2d_cmd_cfg->hsc_rpt_p0_num = ge2d_config->hf_rpt_num; + ge2d_cmd_cfg->src1_cmult_asel = ge2d_config->src1_cmult_asel; + ge2d_cmd_cfg->src2_cmult_asel = ge2d_config->src2_cmult_asel; + context->config.update_flag = UPDATE_ALL; + /* context->config.src1_data.ddr_burst_size_y = 3; */ + /* context->config.src1_data.ddr_burst_size_cb = 3; */ + /* context->config.src1_data.ddr_burst_size_cr = 3; */ + /* context->config.src2_dst_data.ddr_burst_size= 3; */ + + return 0; +} + +int ge2d_buffer_alloc(struct ge2d_dmabuf_req_s *ge2d_req_buf) +{ + struct device *dev; + + dev = &(ge2d_manager.pdev->dev); + return ge2d_dma_buffer_alloc(ge2d_manager.buffer, + dev, ge2d_req_buf); +} + +int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf) +{ + return ge2d_dma_buffer_export(ge2d_manager.buffer, ge2d_exp_buf); +} + +int ge2d_buffer_free(int index) +{ + return ge2d_dma_buffer_free(ge2d_manager.buffer, index); + +} + +void ge2d_buffer_dma_flush(int dma_fd) +{ + struct device *dev; + + dev = &(ge2d_manager.pdev->dev); + ge2d_dma_buffer_dma_flush(dev, dma_fd); +} + +void ge2d_buffer_cache_flush(int dma_fd) +{ + struct device *dev; + + dev = &(ge2d_manager.pdev->dev); + ge2d_dma_buffer_cache_flush(dev, dma_fd); +} + struct ge2d_context_s *create_ge2d_work_queue(void) { int i; @@ -1933,6 +2565,9 @@ int ge2d_wq_init(struct platform_device *pdev, INIT_LIST_HEAD(&ge2d_manager.process_queue); ge2d_manager.last_wq = NULL; ge2d_manager.ge2d_thread = NULL; + ge2d_manager.buffer = ge2d_dma_buffer_create(); + if (!ge2d_manager.buffer) + return -1; ge2d_clk_config(true); ge2d_soft_rst(); ge2d_gen_cfg.interrupt_ctrl = 0x02; @@ -1966,6 +2601,8 @@ int ge2d_wq_deinit(void) } ge2d_irq = -1; clk_disable_unprepare(ge2d_clk); + ge2d_dma_buffer_destroy(ge2d_manager.buffer); + ge2d_manager.buffer = NULL; ge2d_manager.pdev = NULL; return 0; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.h b/drivers/amlogic/media/common/ge2d/ge2d_wq.h index 00b7a2952648..2fd067836211 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.h @@ -34,4 +34,9 @@ extern int ge2d_wq_init(struct platform_device *pdev, int irq, struct clk *clk); extern int ge2d_wq_deinit(void); +int ge2d_buffer_alloc(struct ge2d_dmabuf_req_s *ge2d_req_buf); +int ge2d_buffer_free(int index); +int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf); +void ge2d_buffer_dma_flush(int dma_fd); +void ge2d_buffer_cache_flush(int dma_fd); #endif diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index dbd935ad61dc..bf5c591d765f 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -27,6 +27,12 @@ #include #endif +enum ge2d_memtype_s { + AML_GE2D_MEM_ION, + AML_GE2D_MEM_DMABUF, + AML_GE2D_MEM_INVALID, +}; + #define MAX_BITBLT_WORK_CONFIG 4 #define MAX_GE2D_CMD 32 /* 64 */ @@ -610,6 +616,12 @@ struct ge2d_config_s { unsigned int update_flag; }; +struct ge2d_dma_buf_s { + dma_addr_t paddr; + void *vaddr; + int len; +}; + enum ge2d_src_dst_e { OSD0_OSD0 = 0, OSD0_OSD1, @@ -663,6 +675,7 @@ struct ge2d_manager_s { struct ge2d_context_s *last_wq; struct task_struct *ge2d_thread; struct ge2d_event_s event; + struct aml_dma_buffer *buffer; int irq_num; int ge2d_state; int process_queue_state; @@ -949,6 +962,56 @@ struct compat_config_para_ex_ion_s { struct compat_config_planes_ion_s dst_planes[4]; }; #endif + +struct config_para_ex_memtype_s { + int ge2d_magic; + struct config_para_ex_ion_s _ge2d_config_ex; + /* memtype*/ + unsigned int src1_mem_alloc_type; + unsigned int src2_mem_alloc_type; + unsigned int dst_mem_alloc_type; +}; + +struct config_ge2d_para_ex_s { + union { + struct config_para_ex_ion_s para_config_ion; + struct config_para_ex_memtype_s para_config_memtype; + }; +}; + + +#ifdef CONFIG_COMPAT +struct compat_config_para_ex_memtype_s { + int ge2d_magic; + struct compat_config_para_ex_ion_s _ge2d_config_ex; + /* memtype*/ + unsigned int src1_mem_alloc_type; + unsigned int src2_mem_alloc_type; + unsigned int dst_mem_alloc_type; +}; + +struct compat_config_ge2d_para_ex_s { + union { + struct compat_config_para_ex_ion_s para_config_ion; + struct compat_config_para_ex_memtype_s para_config_memtype; + }; +}; +#endif + +/* for ge2d dma buf define */ +struct ge2d_dmabuf_req_s { + int index; + unsigned int len; + unsigned int dma_dir; +}; + +struct ge2d_dmabuf_exp_s { + int index; + unsigned int flags; + int fd; +}; +/* end of ge2d dma buffer define */ + struct ge2d_device_data_s { int ge2d_rate; int src2_alp; @@ -990,6 +1053,21 @@ extern struct ge2d_device_data_s ge2d_meson_dev; _IOW(GE2D_IOC_MAGIC, 0x03, struct compat_config_para_ex_ion_s) #endif +#define GE2D_REQUEST_BUFF _IOW(GE2D_IOC_MAGIC, 0x04, struct ge2d_dmabuf_req_s) +#define GE2D_EXP_BUFF _IOW(GE2D_IOC_MAGIC, 0x05, struct ge2d_dmabuf_exp_s) +#define GE2D_FREE_BUFF _IOW(GE2D_IOC_MAGIC, 0x06, int) + +#define GE2D_CONFIG_EX_MEM \ + _IOW(GE2D_IOC_MAGIC, 0x07, struct config_ge2d_para_ex_s) + +#ifdef CONFIG_COMPAT +#define GE2D_CONFIG_EX32_MEM \ + _IOW(GE2D_IOC_MAGIC, 0x07, struct compat_config_ge2d_para_ex_s) +#endif + +#define GE2D_SYNC_DEVICE _IOW(GE2D_IOC_MAGIC, 0x08, int) +#define GE2D_SYNC_CPU _IOW(GE2D_IOC_MAGIC, 0x09, int) + extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg); extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg); extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg); @@ -1010,6 +1088,8 @@ extern int ge2d_context_config_ex(struct ge2d_context_s *context, struct config_para_ex_s *ge2d_config); extern int ge2d_context_config_ex_ion(struct ge2d_context_s *context, struct config_para_ex_ion_s *ge2d_config); +extern int ge2d_context_config_ex_mem(struct ge2d_context_s *context, + struct config_para_ex_memtype_s *ge2d_config_mem); extern struct ge2d_context_s *create_ge2d_work_queue(void); extern int destroy_ge2d_work_queue(struct ge2d_context_s *wq); extern int ge2d_wq_remove_config(struct ge2d_context_s *wq); From 89e8007404f9eb9f702124c044f0e5bca6a4b0f2 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Fri, 11 Jan 2019 10:54:46 +0800 Subject: [PATCH 0026/1060] gdc: add gdc dma_buf input/output support [2/2] PD#SWPL-4036 Problem: gdc don't support export dma_buf Solution: add gdc dma_buf input/output support Verify: test pass on w400 Change-Id: I67a60ede01e5c01630a00fbae2821430a870c2b8 Signed-off-by: Pengcheng Chen Signed-off-by: Luan Yuan Conflicts: MAINTAINERS --- MAINTAINERS | 6 + drivers/amlogic/media/gdc/Makefile | 4 +- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 636 +++++++++++++++++ drivers/amlogic/media/gdc/app/gdc_dmabuf.h | 79 +++ drivers/amlogic/media/gdc/app/gdc_main.c | 16 +- drivers/amlogic/media/gdc/app/gdc_module.c | 656 +++++++++++++----- drivers/amlogic/media/gdc/inc/api/gdc_api.h | 120 +++- .../amlogic/media/gdc/inc/gdc/gdc_config.h | 12 +- .../amlogic/media/gdc/inc/sys/system_log.h | 23 +- .../media/gdc/src/fw_lib/acamera_gdc.c | 150 ++-- .../media/gdc/src/platform/system_gdc_io.c | 20 +- 11 files changed, 1436 insertions(+), 286 deletions(-) create mode 100644 drivers/amlogic/media/gdc/app/gdc_dmabuf.c create mode 100644 drivers/amlogic/media/gdc/app/gdc_dmabuf.h diff --git a/MAINTAINERS b/MAINTAINERS index ee27f3a2ea37..093639ebc281 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14748,6 +14748,12 @@ M: Pengcheng Chen F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h +AMLOGIC GDC DRIVER +M: Pengcheng Chen +F: drivers/amlogic/media/gdc/app/gdc_dmabuf.c +F: drivers/amlogic/media/gdc/app/gdc_dmabuf.h +F: drivers/amlogic/media/gdc/src/platform/system_log.c + AMLOGIC VIDEOSYNC M: Jintao Xu F: drivers/amlogic/media/video_processor/videosync/Kconfig diff --git a/drivers/amlogic/media/gdc/Makefile b/drivers/amlogic/media/gdc/Makefile index 5892420dac39..d0d4b2725e5d 100644 --- a/drivers/amlogic/media/gdc/Makefile +++ b/drivers/amlogic/media/gdc/Makefile @@ -1,8 +1,8 @@ FW_SRC := src/fw_lib/acamera_gdc.c \ src/platform/system_gdc_io.c \ - src/platform/system_log.c \ app/gdc_main.c \ - app/gdc_module.c + app/gdc_module.c \ + app/gdc_dmabuf.c FW_SRC_OBJ := $(FW_SRC:.c=.o) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c new file mode 100644 index 000000000000..2f4fe5989ee1 --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -0,0 +1,636 @@ +/* + * drivers/amlogic/media/gdc/app/gdc_dmabuf.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "system_log.h" +#include "gdc_dmabuf.h" + +/* dma free*/ +static void aml_dma_put(void *buf_priv) +{ + struct aml_dma_buf *buf = buf_priv; + + if (!atomic_dec_and_test(&buf->refcount)) { + gdc_log(LOG_INFO, "aml_dma_put, refcont=%d\n", + atomic_read(&buf->refcount)); + return; + } + if (buf->sgt_base) { + sg_free_table(buf->sgt_base); + kfree(buf->sgt_base); + } + dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, + buf->attrs); + put_device(buf->dev); + kfree(buf); + gdc_log(LOG_INFO, "aml_dma_put free!\n"); +} + +static void *aml_dma_alloc(struct device *dev, unsigned long attrs, + unsigned long size, enum dma_data_direction dma_dir, + gfp_t gfp_flags) +{ + struct aml_dma_buf *buf; + + if (WARN_ON(!dev)) + return (void *)(-EINVAL); + + buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL); + if (!buf) + return NULL; + + if (attrs) + buf->attrs = attrs; + buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, + gfp_flags, buf->attrs); + if (!buf->cookie) { + dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); + kfree(buf); + return NULL; + } + + if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) + buf->vaddr = buf->cookie; + + /* Prevent the device from being released while the buffer is used */ + buf->dev = get_device(dev); + buf->size = size; + buf->dma_dir = dma_dir; + + atomic_inc(&buf->refcount); + gdc_log(LOG_INFO, "aml_dma_alloc, refcont=%d\n", + atomic_read(&buf->refcount)); + + return buf; +} + +static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) +{ + struct aml_dma_buf *buf = buf_priv; + int ret; + + if (!buf) { + pr_err("No buffer to map\n"); + return -EINVAL; + } + + /* + * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to + * map whole buffer + */ + vma->vm_pgoff = 0; + + ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, + buf->dma_addr, buf->size, buf->attrs); + + if (ret) { + pr_err("Remapping memory failed, error: %d\n", ret); + return ret; + } + gdc_log(LOG_INFO, "mapped dma addr 0x%08lx at 0x%08lx, size %d\n", + (unsigned long)buf->dma_addr, vma->vm_start, + buf->size); + return 0; +} + +/*********************************************/ +/* DMABUF ops for exporters */ +/*********************************************/ +struct aml_attachment { + struct sg_table sgt; + enum dma_data_direction dma_dir; +}; + +static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, + struct dma_buf_attachment *dbuf_attach) +{ + struct aml_attachment *attach; + unsigned int i; + struct scatterlist *rd, *wr; + struct sg_table *sgt; + struct aml_dma_buf *buf = dbuf->priv; + int ret; + + attach = kzalloc(sizeof(*attach), GFP_KERNEL); + if (!attach) + return -ENOMEM; + + sgt = &attach->sgt; + /* Copy the buf->base_sgt scatter list to the attachment, as we can't + * map the same scatter list to multiple attachments at the same time. + */ + ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL); + if (ret) { + kfree(attach); + return -ENOMEM; + } + + rd = buf->sgt_base->sgl; + wr = sgt->sgl; + for (i = 0; i < sgt->orig_nents; ++i) { + sg_set_page(wr, sg_page(rd), rd->length, rd->offset); + rd = sg_next(rd); + wr = sg_next(wr); + } + + attach->dma_dir = DMA_NONE; + dbuf_attach->priv = attach; + + return 0; +} + +static void aml_dmabuf_ops_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *db_attach) +{ + struct aml_attachment *attach = db_attach->priv; + struct sg_table *sgt; + + if (!attach) + return; + + sgt = &attach->sgt; + + /* release the scatterlist cache */ + if (attach->dma_dir != DMA_NONE) + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + sg_free_table(sgt); + kfree(attach); + db_attach->priv = NULL; + +} + +static struct sg_table *aml_dmabuf_ops_map( + struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir) +{ + struct aml_attachment *attach = db_attach->priv; + /* stealing dmabuf mutex to serialize map/unmap operations */ + struct mutex *lock = &db_attach->dmabuf->lock; + struct sg_table *sgt; + + mutex_lock(lock); + + sgt = &attach->sgt; + /* return previously mapped sg table */ + if (attach->dma_dir == dma_dir) { + mutex_unlock(lock); + return sgt; + } + + /* release any previous cache */ + if (attach->dma_dir != DMA_NONE) { + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + attach->dma_dir = DMA_NONE; + } + + /* mapping to the client with new direction */ + sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + dma_dir); + if (!sgt->nents) { + pr_err("failed to map scatterlist\n"); + mutex_unlock(lock); + return (void *)(-EIO); + } + + attach->dma_dir = dma_dir; + + mutex_unlock(lock); + return sgt; +} + +static void aml_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach, + struct sg_table *sgt, enum dma_data_direction dma_dir) +{ + /* nothing to be done here */ +} + +static void aml_dmabuf_ops_release(struct dma_buf *dbuf) +{ + /* drop reference obtained in vb2_dc_get_dmabuf */ + aml_dma_put(dbuf->priv); +} + +static void *aml_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL; +} + +static void *aml_dmabuf_ops_vmap(struct dma_buf *dbuf) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr; +} + +static int aml_dmabuf_ops_mmap(struct dma_buf *dbuf, + struct vm_area_struct *vma) +{ + return aml_dma_mmap(dbuf->priv, vma); +} + +static struct dma_buf_ops gdc_dmabuf_ops = { + .attach = aml_dmabuf_ops_attach, + .detach = aml_dmabuf_ops_detach, + .map_dma_buf = aml_dmabuf_ops_map, + .unmap_dma_buf = aml_dmabuf_ops_unmap, + .kmap = aml_dmabuf_ops_kmap, + .kmap_atomic = aml_dmabuf_ops_kmap, + .vmap = aml_dmabuf_ops_vmap, + .mmap = aml_dmabuf_ops_mmap, + .release = aml_dmabuf_ops_release, +}; + +static struct sg_table *get_base_sgt(struct aml_dma_buf *buf) +{ + int ret; + struct sg_table *sgt; + + sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sgt) + return NULL; + + ret = dma_get_sgtable(buf->dev, sgt, buf->cookie, + buf->dma_addr, buf->size); + if (ret < 0) { + dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); + kfree(sgt); + return NULL; + } + return sgt; +} + +static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) +{ + struct aml_dma_buf *buf = buf_priv; + struct dma_buf *dbuf; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + exp_info.ops = &gdc_dmabuf_ops; + exp_info.size = buf->size; + exp_info.flags = flags; + exp_info.priv = buf; + + if (!buf->sgt_base) + buf->sgt_base = get_base_sgt(buf); + + if (WARN_ON(!buf->sgt_base)) + return NULL; + + dbuf = dma_buf_export(&exp_info); + if (IS_ERR(dbuf)) + return NULL; + + /* dmabuf keeps reference to vb2 buffer */ + atomic_inc(&buf->refcount); + gdc_log(LOG_INFO, "get_dmabuf, refcount=%d\n", + atomic_read(&buf->refcount)); + + return dbuf; +} + +/* ge2d dma-buf api.h*/ +static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) +{ + int i; + int found = 0; + + for (i = 0; i < AML_MAX_DMABUF; i++) { + if (buffer->gd_buffer[i].alloc) + continue; + else { + gdc_log(LOG_INFO, "find_empty_dma_buffer i=%d\n", i); + found = 1; + break; + } + } + if (found) + return i; + else + return -1; +} + +void *gdc_dma_buffer_create(void) +{ + int i; + struct aml_dma_buffer *buffer; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return NULL; + + mutex_init(&buffer->lock); + for (i = 0; i < AML_MAX_DMABUF; i++) { + buffer->gd_buffer[i].mem_priv = NULL; + buffer->gd_buffer[i].index = 0; + buffer->gd_buffer[i].alloc = 0; + } + return buffer; +} + +void gdc_dma_buffer_destroy(struct aml_dma_buffer *buffer) +{ + kfree(buffer); +} + +int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct gdc_dmabuf_req_s *gdc_req_buf) +{ + void *buf; + unsigned int size; + int index; + + if (WARN_ON(!dev)) + return (-EINVAL); + if (!gdc_req_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + size = PAGE_ALIGN(gdc_req_buf->len); + if (size == 0) + return (-EINVAL); + + index = find_empty_dma_buffer(buffer); + if ((index < 0) || (index >= AML_MAX_DMABUF)) { + pr_err("no empty buffer found\n"); + return (-ENOMEM); + } + + buf = aml_dma_alloc(dev, 0, size, gdc_req_buf->dma_dir, + GFP_HIGHUSER | __GFP_ZERO); + if (!buf) + return (-ENOMEM); + + mutex_lock(&(buffer->lock)); + buffer->gd_buffer[index].mem_priv = buf; + buffer->gd_buffer[index].index = index; + buffer->gd_buffer[index].alloc = 1; + mutex_unlock(&(buffer->lock)); + gdc_req_buf->index = index; + return 0; +} + +int gdc_dma_buffer_free(struct aml_dma_buffer *buffer, int index) +{ + struct aml_dma_buf *buf; + + if (!buffer) + return (-EINVAL); + if ((index) < 0 || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + aml_dma_put(buf); + return 0; +} + +int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, + struct gdc_dmabuf_exp_s *gdc_exp_buf) +{ + struct aml_dma_buf *buf; + struct dma_buf *dbuf; + int ret, index; + unsigned int flags; + + if (!gdc_exp_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + index = gdc_exp_buf->index; + if ((index) < 0 || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + flags = gdc_exp_buf->flags; + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + + dbuf = get_dmabuf(buf, flags & O_ACCMODE); + if (IS_ERR_OR_NULL(dbuf)) { + pr_err("failed to export buffer %d\n", index); + return -EINVAL; + } + ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE); + if (ret < 0) { + pr_err("buffer %d, failed to export (%d)\n", + index, ret); + dma_buf_put(dbuf); + return ret; + } + + gdc_log(LOG_INFO, "buffer %d,exported as %d descriptor\n", + index, ret); + gdc_exp_buf->fd = ret; + return 0; +} + +int gdc_dma_buffer_map(struct aml_dma_cfg *cfg) +{ + long ret = -1; + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { + pr_err("error input param"); + return -EINVAL; + } + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + + dbuf = dma_buf_get(fd); + if (dbuf == NULL) { + pr_err("failed to get dma buffer"); + return -EINVAL; + } + + d_att = dma_buf_attach(dbuf, dev); + if (d_att == NULL) { + pr_err("failed to set dma attach"); + goto attach_err; + } + + sg = dma_buf_map_attachment(d_att, dir); + if (sg == NULL) { + pr_err("failed to get dma sg"); + goto map_attach_err; + } + + ret = dma_buf_begin_cpu_access(dbuf, dir); + if (ret != 0) { + pr_err("failed to access dma buff"); + goto access_err; + } + + vaddr = dma_buf_vmap(dbuf); + if (vaddr == NULL) { + pr_err("failed to vmap dma buf"); + goto vmap_err; + } + cfg->dbuf = dbuf; + cfg->attach = d_att; + cfg->vaddr = vaddr; + cfg->sg = sg; + + return ret; + +vmap_err: + dma_buf_end_cpu_access(dbuf, dir); + +access_err: + dma_buf_unmap_attachment(d_att, sg, dir); + +map_attach_err: + dma_buf_detach(dbuf, d_att); + +attach_err: + dma_buf_put(dbuf); + + return ret; +} + +int gdc_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) +{ + struct sg_table *sg_table; + struct page *page; + int ret; + + ret = gdc_dma_buffer_map(cfg); + if (ret < 0) { + pr_err("gdc_dma_buffer_map failed\n"); + return ret; + } + if (cfg->sg) { + sg_table = cfg->sg; + page = sg_page(sg_table->sgl); + *addr = PFN_PHYS(page_to_pfn(page)); + ret = 0; + } + gdc_dma_buffer_unmap(cfg); + return ret; +} + +void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg) +{ + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL + || cfg->dbuf == NULL || cfg->vaddr == NULL + || cfg->attach == NULL || cfg->sg == NULL) { + pr_err("Error input param"); + return; + } + + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + dbuf = cfg->dbuf; + vaddr = cfg->vaddr; + d_att = cfg->attach; + sg = cfg->sg; + + dma_buf_vunmap(dbuf, vaddr); + + dma_buf_end_cpu_access(dbuf, dir); + + dma_buf_unmap_attachment(d_att, sg, dir); + + dma_buf_detach(dbuf, d_att); + + dma_buf_put(dbuf); +} + +void gdc_dma_buffer_dma_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + gdc_log(LOG_INFO, "gdc_dma_buffer_dma_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if (buf->size > 0) + dma_sync_single_for_device(buf->dev, buf->dma_addr, + buf->size, DMA_TO_DEVICE); + dma_buf_put(dmabuf); +} + +void gdc_dma_buffer_cache_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + gdc_log(LOG_INFO, "gdc_dma_buffer_cache_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if (buf->size > 0) + dma_sync_single_for_device(buf->dev, buf->dma_addr, + buf->size, DMA_FROM_DEVICE); + dma_buf_put(dmabuf); +} diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h new file mode 100644 index 000000000000..6de1d577fe11 --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h @@ -0,0 +1,79 @@ +/* + * drivers/amlogic/media/gdc/app/gdc_dmabuf.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _GDC_DMABUF_H_ +#define _GDC_DMABUF_H_ + +#include +#include +#include + + +#define AML_MAX_DMABUF 32 + +struct aml_dma_buf { + struct device *dev; + void *cookie; + void *vaddr; + unsigned int size; + enum dma_data_direction dma_dir; + unsigned long attrs; + unsigned int index; + dma_addr_t dma_addr; + atomic_t refcount; + struct sg_table *sgt_base; + /* DMABUF related */ + struct dma_buf_attachment *db_attach; +}; + +struct aml_dma_buf_priv { + void *mem_priv; + int index; + unsigned int alloc; + struct dma_buf *dbuf; +}; + +struct aml_dma_buffer { + struct mutex lock; + struct aml_dma_buf_priv gd_buffer[AML_MAX_DMABUF]; +}; + +struct aml_dma_cfg { + int fd; + void *dev; + void *vaddr; + struct dma_buf *dbuf; + struct dma_buf_attachment *attach; + struct sg_table *sg; + enum dma_data_direction dir; +}; + + +void *gdc_dma_buffer_create(void); +void gdc_dma_buffer_destroy(struct aml_dma_buffer *buffer); +int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct gdc_dmabuf_req_s *gdc_req_buf); +int gdc_dma_buffer_free(struct aml_dma_buffer *buffer, int index); +int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, + struct gdc_dmabuf_exp_s *gdc_exp_buf); +int gdc_dma_buffer_map(struct aml_dma_cfg *cfg); +void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg); +int gdc_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr); +void gdc_dma_buffer_dma_flush(struct device *dev, int fd); +void gdc_dma_buffer_cache_flush(struct device *dev, int fd); +#endif diff --git a/drivers/amlogic/media/gdc/app/gdc_main.c b/drivers/amlogic/media/gdc/app/gdc_main.c index c6d631169821..538416dd9bb0 100644 --- a/drivers/amlogic/media/gdc/app/gdc_main.c +++ b/drivers/amlogic/media/gdc/app/gdc_main.c @@ -25,27 +25,27 @@ irqreturn_t interrupt_handler_next(int irq, void *param) { //handle the start of frame with gdc_process - struct gdc_settings *gdc_settings = (struct gdc_settings *)param; + struct gdc_cmd_s *gdc_cmd = (struct gdc_cmd_s *)param; - gdc_get_frame(gdc_settings); + gdc_get_frame(gdc_cmd); return IRQ_HANDLED; } -int gdc_run(struct gdc_settings *g) +int gdc_run(struct gdc_cmd_s *g) { gdc_stop(g); - LOG(LOG_INFO, "Done gdc load..\n"); + gdc_log(LOG_INFO, "Done gdc load..\n"); //initialise the gdc by the first configuration if (gdc_init(g) != 0) { - LOG(LOG_ERR, "Failed to initialise GDC block"); + gdc_log(LOG_ERR, "Failed to initialise GDC block"); return -1; } - LOG(LOG_INFO, "Done gdc config..\n"); + gdc_log(LOG_INFO, "Done gdc config..\n"); switch (g->gdc_config.format) { case NV12: @@ -70,10 +70,10 @@ int gdc_run(struct gdc_settings *g) g->v_base_addr); break; default: - LOG(LOG_ERR, "Error config format\n"); + gdc_log(LOG_ERR, "Error config format\n"); break; } - LOG(LOG_DEBUG, "call gdc process\n"); + gdc_log(LOG_DEBUG, "call gdc process\n"); return 0; } diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 040218d9ac0e..e0f1dade368f 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -43,8 +43,10 @@ #include //gdc configuration sequence #include "gdc_config.h" +#include "gdc_dmabuf.h" -struct meson_gdc_dev_t *g_gdc_dev; +unsigned int gdc_log_level; +struct gdc_manager_s gdc_manager; static const struct of_device_id gdc_dt_match[] = { {.compatible = "amlogic, g12b-gdc"}, @@ -55,19 +57,19 @@ MODULE_DEVICE_TABLE(of, gdc_dt_match); ////// static int meson_gdc_open(struct inode *inode, struct file *file) { - struct meson_gdc_dev_t *gdc_dev = g_gdc_dev; + struct meson_gdc_dev_t *gdc_dev = gdc_manager.gdc_dev; struct mgdc_fh_s *fh = NULL; char ion_client_name[32]; int rc = 0; fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (fh == NULL) { - LOG(LOG_DEBUG, "devm alloc failed\n"); + gdc_log(LOG_DEBUG, "devm alloc failed\n"); return -ENOMEM; } get_task_comm(fh->task_comm, current); - LOG(LOG_DEBUG, "%s, %d, call from %s\n", + gdc_log(LOG_DEBUG, "%s, %d, call from %s\n", __func__, __LINE__, fh->task_comm); file->private_data = fh; @@ -78,7 +80,7 @@ static int meson_gdc_open(struct inode *inode, struct file *file) fh->gdev = gdc_dev; - LOG(LOG_CRIT, "Success open\n"); + gdc_log(LOG_CRIT, "Success open\n"); return rc; } @@ -102,7 +104,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh->i_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; - LOG(LOG_ERR, "Failed to release input buff\n"); + gdc_log(LOG_ERR, "Failed to release input buff\n"); } fh->i_kaddr = NULL; @@ -117,7 +119,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh->o_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; - LOG(LOG_ERR, "Failed to release output buff\n"); + gdc_log(LOG_ERR, "Failed to release output buff\n"); } fh->o_kaddr = NULL; @@ -132,7 +134,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh->c_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; - LOG(LOG_ERR, "Failed to release config buff\n"); + gdc_log(LOG_ERR, "Failed to release config buff\n"); } fh->c_kaddr = NULL; @@ -144,9 +146,9 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh = NULL; if (ret == 0) - LOG(LOG_CRIT, "Success release\n"); + gdc_log(LOG_CRIT, "Success release\n"); else - LOG(LOG_ERR, "Error release\n"); + gdc_log(LOG_ERR, "Error release\n"); return ret; } @@ -159,7 +161,7 @@ static long meson_gdc_set_buff(void *f_fh, struct mgdc_fh_s *fh = NULL; if (f_fh == NULL || cma_pages == NULL || len == 0) { - LOG(LOG_ERR, "Error input param\n"); + gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } @@ -188,7 +190,7 @@ static long meson_gdc_set_buff(void *f_fh, fh->c_len = len; break; default: - LOG(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); + gdc_log(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); ret = -EINVAL; break; } @@ -197,51 +199,51 @@ static long meson_gdc_set_buff(void *f_fh, } static long meson_gdc_set_input_addr(uint32_t start_addr, - struct gdc_settings *gs) + struct gdc_cmd_s *gdc_cmd) { - struct gdc_config *gc = NULL; + struct gdc_config_s *gc = NULL; - if (gs == NULL || start_addr == 0) { - LOG(LOG_ERR, "Error input param\n"); + if (gdc_cmd == NULL || start_addr == 0) { + gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } - gc = &gs->gdc_config; + gc = &gdc_cmd->gdc_config; switch (gc->format) { case NV12: - gs->y_base_addr = start_addr; - gs->uv_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->uv_base_addr = start_addr + gc->input_y_stride * gc->input_height; break; case YV12: - gs->y_base_addr = start_addr; - gs->u_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = start_addr + gc->input_y_stride * gc->input_height; - gs->v_base_addr = gs->u_base_addr + + gdc_cmd->v_base_addr = gdc_cmd->u_base_addr + gc->input_c_stride * gc->input_height / 2; break; case Y_GREY: - gs->y_base_addr = start_addr; - gs->u_base_addr = 0; - gs->v_base_addr = 0; + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = 0; + gdc_cmd->v_base_addr = 0; break; case YUV444_P: - gs->y_base_addr = start_addr; - gs->u_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = start_addr + gc->input_y_stride * gc->input_height; - gs->v_base_addr = gs->u_base_addr + + gdc_cmd->v_base_addr = gdc_cmd->u_base_addr + gc->input_c_stride * gc->input_height; break; case RGB444_P: - gs->y_base_addr = start_addr; - gs->u_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = start_addr + gc->input_y_stride * gc->input_height; - gs->v_base_addr = gs->u_base_addr + + gdc_cmd->v_base_addr = gdc_cmd->u_base_addr + gc->input_c_stride * gc->input_height; break; default: - LOG(LOG_ERR, "Error config format\n"); + gdc_log(LOG_ERR, "Error config format\n"); return -EINVAL; break; } @@ -254,7 +256,7 @@ static void meson_gdc_dma_flush(struct device *dev, size_t size) { if (dev == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return; } @@ -266,7 +268,7 @@ static void meson_gdc_cache_flush(struct device *dev, size_t size) { if (dev == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return; } @@ -285,7 +287,7 @@ static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg) enum dma_data_direction dir; if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return -EINVAL; } @@ -295,31 +297,31 @@ static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg) dbuf = dma_buf_get(fd); if (dbuf == NULL) { - LOG(LOG_ERR, "Failed to get dma buffer"); + gdc_log(LOG_ERR, "Failed to get dma buffer"); return -EINVAL; } d_att = dma_buf_attach(dbuf, dev); if (d_att == NULL) { - LOG(LOG_ERR, "Failed to set dma attach"); + gdc_log(LOG_ERR, "Failed to set dma attach"); goto attach_err; } sg = dma_buf_map_attachment(d_att, dir); if (sg == NULL) { - LOG(LOG_ERR, "Failed to get dma sg"); + gdc_log(LOG_ERR, "Failed to get dma sg"); goto map_attach_err; } ret = dma_buf_begin_cpu_access(dbuf, dir); if (ret != 0) { - LOG(LOG_ERR, "Failed to access dma buff"); + gdc_log(LOG_ERR, "Failed to access dma buff"); goto access_err; } vaddr = dma_buf_vmap(dbuf); if (vaddr == NULL) { - LOG(LOG_ERR, "Failed to vmap dma buf"); + gdc_log(LOG_ERR, "Failed to vmap dma buf"); goto vmap_err; } @@ -359,7 +361,7 @@ static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL || cfg->dbuf == NULL || cfg->vaddr == NULL || cfg->attach == NULL || cfg->sg == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return; } @@ -382,21 +384,19 @@ static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) dma_buf_put(dbuf); } -static long meson_gdc_init_dma_addr(struct gdc_settings *gs) +static long meson_gdc_init_dma_addr(struct mgdc_fh_s *fh, + struct gdc_settings *gs) { long ret = -1; struct gdc_dma_cfg *dma_cfg = NULL; - struct gdc_config *gc = NULL; - struct mgdc_fh_s *fh = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; - if (gs == NULL || gs->fh == NULL) { - LOG(LOG_ERR, "Error input param\n"); + if (fh == NULL || gs == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } - gc = &gs->gdc_config; - fh = gs->fh; - switch (gc->format) { case NV12: dma_cfg = &fh->y_dma_cfg; @@ -407,11 +407,11 @@ static long meson_gdc_init_dma_addr(struct gdc_settings *gs) ret = meson_gdc_dma_map(dma_cfg); if (ret != 0) { - LOG(LOG_ERR, "Failed to get map dma buff"); + gdc_log(LOG_ERR, "Failed to get map dma buff"); return ret; } - gs->y_base_addr = virt_to_phys(dma_cfg->vaddr); + gdc_cmd->y_base_addr = virt_to_phys(dma_cfg->vaddr); dma_cfg = &fh->uv_dma_cfg; memset(dma_cfg, 0, sizeof(*dma_cfg)); @@ -421,11 +421,11 @@ static long meson_gdc_init_dma_addr(struct gdc_settings *gs) ret = meson_gdc_dma_map(dma_cfg); if (ret != 0) { - LOG(LOG_ERR, "Failed to get map dma buff"); + gdc_log(LOG_ERR, "Failed to get map dma buff"); return ret; } - gs->uv_base_addr = virt_to_phys(dma_cfg->vaddr); + gdc_cmd->uv_base_addr = virt_to_phys(dma_cfg->vaddr); break; case Y_GREY: dma_cfg = &fh->y_dma_cfg; @@ -436,35 +436,31 @@ static long meson_gdc_init_dma_addr(struct gdc_settings *gs) ret = meson_gdc_dma_map(dma_cfg); if (ret != 0) { - LOG(LOG_ERR, "Failed to get map dma buff"); + gdc_log(LOG_ERR, "Failed to get map dma buff"); return ret; } - - gs->y_base_addr = virt_to_phys(dma_cfg->vaddr); - gs->uv_base_addr = 0; + gdc_cmd->y_base_addr = virt_to_phys(dma_cfg->vaddr); + gdc_cmd->uv_base_addr = 0; break; default: - LOG(LOG_ERR, "Error image format"); + gdc_log(LOG_ERR, "Error image format"); break; } return ret; } -static void meson_gdc_deinit_dma_addr(struct gdc_settings *gs) +static void meson_gdc_deinit_dma_addr(struct mgdc_fh_s *fh) { struct gdc_dma_cfg *dma_cfg = NULL; - struct gdc_config *gc = NULL; - struct mgdc_fh_s *fh = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; - if (gs == NULL || gs->fh == NULL) { - LOG(LOG_ERR, "Error input param\n"); + if (fh == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); return; } - gc = &gs->gdc_config; - fh = gs->fh; - switch (gc->format) { case NV12: dma_cfg = &fh->y_dma_cfg; @@ -478,169 +474,410 @@ static void meson_gdc_deinit_dma_addr(struct gdc_settings *gs) meson_gdc_dma_unmap(dma_cfg); break; default: - LOG(LOG_ERR, "Error image format"); + gdc_log(LOG_ERR, "Error image format"); break; } } +static int gdc_buffer_alloc(struct gdc_dmabuf_req_s *gdc_req_buf) +{ + struct device *dev; + + dev = &(gdc_manager.gdc_dev->pdev->dev); + return gdc_dma_buffer_alloc(gdc_manager.buffer, + dev, gdc_req_buf); +} + +static int gdc_buffer_export(struct gdc_dmabuf_exp_s *gdc_exp_buf) +{ + return gdc_dma_buffer_export(gdc_manager.buffer, gdc_exp_buf); +} + +static int gdc_buffer_free(int index) +{ + return gdc_dma_buffer_free(gdc_manager.buffer, index); + +} + +static void gdc_buffer_dma_flush(int dma_fd) +{ + struct device *dev; + + dev = &(gdc_manager.gdc_dev->pdev->dev); + gdc_dma_buffer_dma_flush(dev, dma_fd); +} + +static void gdc_buffer_cache_flush(int dma_fd) +{ + struct device *dev; + + dev = &(gdc_manager.gdc_dev->pdev->dev); + gdc_dma_buffer_cache_flush(dev, dma_fd); +} + +static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret = -1; + unsigned long addr; + struct aml_dma_cfg cfg; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + + switch (gc->format) { + case NV12: + if (gs_ex->input_buffer.plane_number == 1) { + cfg.fd = gs_ex->input_buffer.y_base_fd; + cfg.dev = &fh->gdev->pdev->dev; + cfg.dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(&cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr failed\n"); + return -EINVAL; + } + gdc_log(LOG_INFO, "1 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + } else if (gs_ex->input_buffer.plane_number == 2) { + cfg.fd = gs_ex->input_buffer.y_base_fd; + cfg.dev = &fh->gdev->pdev->dev; + cfg.dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(&cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + + cfg.fd = gs_ex->input_buffer.uv_base_fd; + cfg.dev = &fh->gdev->pdev->dev; + cfg.dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(&cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.uv_base_fd); + return -EINVAL; + } + gdc_cmd->uv_base_addr = addr; + gdc_log(LOG_INFO, "2 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + gdc_log(LOG_INFO, "2 plane get input addr=%x\n", + gdc_cmd->uv_base_addr); + } + break; + case Y_GREY: + cfg.fd = gs_ex->input_buffer.y_base_fd; + cfg.dev = &(fh->gdev->pdev->dev); + cfg.dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(&cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.shared_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + gdc_cmd->uv_base_addr = 0; + break; + default: + gdc_log(LOG_ERR, "Error image format"); + break; + } + return 0; +} + +static long gdc_process_ex_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret; + unsigned long addr = 0; + size_t len; + struct aml_dma_cfg cfg; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + memcpy(&(gdc_cmd->gdc_config), &(gs_ex->gdc_config), + sizeof(struct gdc_config_s)); + gdc_cmd->fh = fh; + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d failed\n", + gs_ex->output_buffer.shared_fd); + return -EINVAL; + } + } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + /* dma alloc */ + cfg.fd = gs_ex->output_buffer.y_base_fd; + cfg.dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg.dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(&cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, "dma import out fd %d failed\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + + } + gdc_log(LOG_INFO, "%s, output addr=%lx\n", __func__, addr); + gdc_cmd->base_gdc = 0; + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->config_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import config fd %d failed\n", + gs_ex->config_buffer.shared_fd); + return -EINVAL; + } + } else if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + /* dma alloc */ + cfg.fd = gs_ex->config_buffer.y_base_fd; + cfg.dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg.dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(&cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, "dma import config fd %d failed\n", + gs_ex->config_buffer.shared_fd); + return -EINVAL; + } + } + gdc_cmd->gdc_config.config_addr = addr; + gdc_log(LOG_INFO, "%s, config addr=%lx\n", __func__, addr); + + if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d failed\n", + gs_ex->input_buffer.shared_fd); + return -EINVAL; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr failed\n"); + return -EINVAL; + } + } else if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + /* dma alloc */ + gdc_process_input_dma_info(fh, gs_ex); + } + gdc_log(LOG_INFO, "%s, input addr=%x\n", + __func__, fh->gdc_cmd.y_base_addr); + mutex_lock(&fh->gdev->d_mutext); + #if 1 + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); + #endif + ret = gdc_run(gdc_cmd); + if (ret < 0) + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); + + ret = wait_for_completion_timeout(&fh->gdev->d_com, + msecs_to_jiffies(40)); + if (ret == 0) + gdc_log(LOG_ERR, "gdc timeout\n"); + + gdc_stop(gdc_cmd); + #if 0 + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_buffer_cache_flush(gs_ex->output_buffer.shared_fd); + #endif + mutex_unlock(&fh->gdev->d_mutext); + return 0; +} + static long meson_gdc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - long ret = 0; + long ret = -1; size_t len; struct mgdc_fh_s *fh = file->private_data; - struct gdc_settings *gs = &fh->gs; - struct gdc_config *gc = &gs->gdc_config; + struct gdc_settings gs; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; struct gdc_buf_cfg buf_cfg; struct page *cma_pages = NULL; + struct gdc_settings_ex gs_ex; + struct gdc_dmabuf_req_s gdc_req_buf; + struct gdc_dmabuf_exp_s gdc_exp_buf; ion_phys_addr_t addr; + int index, dma_fd; void __user *argp = (void __user *)arg; switch (cmd) { case GDC_PROCESS: - ret = copy_from_user(gs, argp, sizeof(*gs)); + ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) { - LOG(LOG_ERR, "copy from user failed\n"); + gdc_log(LOG_ERR, "copy from user failed\n"); return -EINVAL; } - LOG(LOG_DEBUG, "sizeof(gs)=%zu, magic=%d\n", - sizeof(*gs), gs->magic); + gdc_log(LOG_DEBUG, "sizeof(gs)=%zu, magic=%d\n", + sizeof(gs), gs.magic); //configure gdc config, buffer address and resolution ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs->out_fd, &addr, &len); + gs.out_fd, &addr, &len); if (ret < 0) { - LOG(LOG_ERR, "import out fd %d failed\n", gs->out_fd); + gdc_log(LOG_ERR, + "import out fd %d failed\n", gs.out_fd); return -EINVAL; } + memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, + sizeof(struct gdc_config_s)); + gdc_cmd->buffer_addr = addr; + gdc_cmd->buffer_size = len; - gs->buffer_addr = addr; - gs->buffer_size = len; - - gs->base_gdc = 0; - gs->current_addr = gs->buffer_addr; + gdc_cmd->base_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; ret = meson_ion_share_fd_to_phys(fh->ion_client, gc->config_addr, &addr, &len); if (ret < 0) { - LOG(LOG_ERR, "import config fd failed\n"); + gdc_log(LOG_ERR, "import config fd failed\n"); return -EINVAL; } gc->config_addr = addr; ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs->in_fd, &addr, &len); + gs.in_fd, &addr, &len); if (ret < 0) { - LOG(LOG_ERR, "import in fd %d failed\n", gs->in_fd); + gdc_log(LOG_ERR, "import in fd %d failed\n", gs.in_fd); return -EINVAL; } - ret = meson_gdc_set_input_addr(addr, gs); + ret = meson_gdc_set_input_addr(addr, gdc_cmd); if (ret != 0) { - LOG(LOG_ERR, "set input addr failed\n"); + gdc_log(LOG_ERR, "set input addr failed\n"); return -EINVAL; } - gs->fh = fh; - + gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); - ret = gdc_run(gs); + ret = gdc_run(gdc_cmd); if (ret < 0) - LOG(LOG_ERR, "gdc process ret = %ld\n", ret); + gdc_log(LOG_ERR, "gdc process ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, msecs_to_jiffies(40)); if (ret == 0) - LOG(LOG_ERR, "gdc timeout\n"); + gdc_log(LOG_ERR, "gdc timeout\n"); - gdc_stop(gs); + gdc_stop(gdc_cmd); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_RUN: - ret = copy_from_user(gs, argp, sizeof(*gs)); + ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) - LOG(LOG_ERR, "copy from user failed\n"); + gdc_log(LOG_ERR, "copy from user failed\n"); - gs->buffer_addr = fh->o_paddr; - gs->buffer_size = fh->o_len; + memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, + sizeof(struct gdc_config_s)); + gdc_cmd->buffer_addr = fh->o_paddr; + gdc_cmd->buffer_size = fh->o_len; - gs->base_gdc = 0; - gs->current_addr = gs->buffer_addr; + gdc_cmd->base_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; gc->config_addr = fh->c_paddr; - ret = meson_gdc_set_input_addr(fh->i_paddr, gs); + ret = meson_gdc_set_input_addr(fh->i_paddr, gdc_cmd); if (ret != 0) { - LOG(LOG_ERR, "set input addr failed\n"); + gdc_log(LOG_ERR, "set input addr failed\n"); return -EINVAL; } - gs->fh = fh; - + gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->i_paddr, fh->i_len); meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->c_paddr, fh->c_len); - ret = gdc_run(gs); + ret = gdc_run(gdc_cmd); if (ret < 0) - LOG(LOG_ERR, "gdc process failed ret = %ld\n", ret); + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, msecs_to_jiffies(40)); if (ret == 0) - LOG(LOG_ERR, "gdc timeout\n"); + gdc_log(LOG_ERR, "gdc timeout\n"); - gdc_stop(gs); + gdc_stop(gdc_cmd); meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_HANDLE: - ret = copy_from_user(gs, argp, sizeof(*gs)); + ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) - LOG(LOG_ERR, "copy from user failed\n"); + gdc_log(LOG_ERR, "copy from user failed\n"); - gs->buffer_addr = fh->o_paddr; - gs->buffer_size = fh->o_len; + memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, + sizeof(struct gdc_config_s)); + gdc_cmd->buffer_addr = fh->o_paddr; + gdc_cmd->buffer_size = fh->o_len; - gs->base_gdc = 0; - gs->current_addr = gs->buffer_addr; + gdc_cmd->base_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; gc->config_addr = fh->c_paddr; - gs->fh = fh; - + gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); - ret = meson_gdc_init_dma_addr(gs); + ret = meson_gdc_init_dma_addr(fh, &gs); if (ret != 0) { mutex_unlock(&fh->gdev->d_mutext); - LOG(LOG_ERR, "Failed to init dma addr"); + gdc_log(LOG_ERR, "Failed to init dma addr"); return ret; } meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->c_paddr, fh->c_len); - ret = gdc_run(gs); + ret = gdc_run(gdc_cmd); if (ret < 0) - LOG(LOG_ERR, "gdc process failed ret = %ld\n", ret); + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, msecs_to_jiffies(40)); if (ret == 0) - LOG(LOG_ERR, "gdc timeout\n"); + gdc_log(LOG_ERR, "gdc timeout\n"); - gdc_stop(gs); + gdc_stop(gdc_cmd); meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); - meson_gdc_deinit_dma_addr(gs); + meson_gdc_deinit_dma_addr(fh); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_REQUEST_BUFF: ret = copy_from_user(&buf_cfg, argp, sizeof(buf_cfg)); if (ret < 0 || buf_cfg.type >= GDC_BUFF_TYPE_MAX) { - LOG(LOG_ERR, "Error user param\n"); + gdc_log(LOG_ERR, "Error user param\n"); return ret; } @@ -656,17 +893,77 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, &fh->gdev->pdev->dev, cma_pages, buf_cfg.len >> PAGE_SHIFT); - LOG(LOG_ERR, "Failed to set buff\n"); + gdc_log(LOG_ERR, "Failed to set buff\n"); return ret; } } else { - LOG(LOG_ERR, "Failed to alloc dma buff\n"); + gdc_log(LOG_ERR, "Failed to alloc dma buff\n"); return -ENOMEM; } break; + case GDC_PROCESS_EX: + ret = copy_from_user(&gs_ex, argp, sizeof(gs_ex)); + if (ret < 0) + gdc_log(LOG_ERR, "copy from user failed\n"); + memcpy(&gdc_cmd->gdc_config, &gs_ex.gdc_config, + sizeof(struct gdc_config_s)); + gdc_process_ex_info(fh, &gs_ex); + break; + case GDC_REQUEST_DMA_BUFF: + ret = copy_from_user(&gdc_req_buf, argp, + sizeof(struct gdc_dmabuf_req_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + ret = gdc_buffer_alloc(&gdc_req_buf); + if (ret == 0) + ret = copy_to_user(argp, &gdc_req_buf, + sizeof(struct gdc_dmabuf_req_s)); + break; + case GDC_EXP_DMA_BUFF: + ret = copy_from_user(&gdc_exp_buf, argp, + sizeof(struct gdc_dmabuf_exp_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + ret = gdc_buffer_export(&gdc_exp_buf); + if (ret == 0) + ret = copy_to_user(argp, &gdc_exp_buf, + sizeof(struct gdc_dmabuf_exp_s)); + break; + case GDC_FREE_DMA_BUFF: + ret = copy_from_user(&index, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + ret = gdc_buffer_free(index); + break; + case GDC_SYNC_DEVICE: + ret = copy_from_user(&dma_fd, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + gdc_buffer_dma_flush(dma_fd); + break; + case GDC_SYNC_CPU: + ret = copy_from_user(&dma_fd, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + gdc_buffer_cache_flush(dma_fd); + break; default: - LOG(LOG_ERR, "unsupported cmd 0x%x\n", cmd); + gdc_log(LOG_ERR, "unsupported cmd 0x%x\n", cmd); + return -EINVAL; break; } @@ -685,28 +982,28 @@ static int meson_gdc_mmap(struct file *file_p, switch (fh->mmap_type) { case INPUT_BUFF_TYPE: ret = remap_pfn_range(vma, vma->vm_start, - fh->i_paddr >> PAGE_SHIFT, - buf_len, vma->vm_page_prot); - if (ret != 0) - LOG(LOG_ERR, "Failed to mmap input buffer\n"); + fh->i_paddr >> PAGE_SHIFT, + buf_len, vma->vm_page_prot); + if (ret != 0) + gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; case OUTPUT_BUFF_TYPE: - ret = remap_pfn_range(vma, vma->vm_start, - fh->o_paddr >> PAGE_SHIFT, - buf_len, vma->vm_page_prot); - if (ret != 0) - LOG(LOG_ERR, "Failed to mmap input buffer\n"); + ret = remap_pfn_range(vma, vma->vm_start, + fh->o_paddr >> PAGE_SHIFT, + buf_len, vma->vm_page_prot); + if (ret != 0) + gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; case CONFIG_BUFF_TYPE: - ret = remap_pfn_range(vma, vma->vm_start, - fh->c_paddr >> PAGE_SHIFT, - buf_len, vma->vm_page_prot); - if (ret != 0) - LOG(LOG_ERR, "Failed to mmap input buffer\n"); + ret = remap_pfn_range(vma, vma->vm_start, + fh->c_paddr >> PAGE_SHIFT, + buf_len, vma->vm_page_prot); + if (ret != 0) + gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; default: - LOG(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); + gdc_log(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); break; } @@ -746,7 +1043,7 @@ static ssize_t gdc_reg_show(struct device *dev, static ssize_t gdc_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); return len; } static DEVICE_ATTR(gdc_reg, 0554, gdc_reg_show, gdc_reg_store); @@ -754,19 +1051,43 @@ static DEVICE_ATTR(gdc_reg, 0554, gdc_reg_show, gdc_reg_store); static ssize_t firmware1_show(struct device *dev, struct device_attribute *attr, char *buf) { - LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); return 1; } static ssize_t firmware1_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); //gdc_fw_init(); return 1; } static DEVICE_ATTR(firmware1, 0664, firmware1_show, firmware1_store); +static ssize_t loglevel_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + len += sprintf(buf+len, "%d\n", gdc_log_level); + return len; +} + +static ssize_t loglevel_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + int res = 0; + int ret = 0; + + ret = kstrtoint(buf, 0, &res); + pr_info("log_level: %d->%d\n", gdc_log_level, res); + gdc_log_level = res; + + return len; +} + +static DEVICE_ATTR(loglevel, 0664, loglevel_show, loglevel_store); + irqreturn_t gdc_interrupt_handler(int irq, void *param) { struct meson_gdc_dev_t *gdc_dev = param; @@ -789,34 +1110,34 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!gdc_res) { - LOG(LOG_ERR, "Error, no IORESOURCE_MEM DT!\n"); + gdc_log(LOG_ERR, "Error, no IORESOURCE_MEM DT!\n"); return -ENOMEM; } if (init_gdc_io(pdev->dev.of_node) != 0) { - LOG(LOG_ERR, "Error on mapping gdc memory!\n"); + gdc_log(LOG_ERR, "Error on mapping gdc memory!\n"); return -ENOMEM; } of_reserved_mem_device_init(&(pdev->dev)); - device_create_file(&pdev->dev, &dev_attr_gdc_reg); - device_create_file(&pdev->dev, &dev_attr_firmware1); - gdc_dev = devm_kzalloc(&pdev->dev, sizeof(*gdc_dev), GFP_KERNEL); if (gdc_dev == NULL) { - LOG(LOG_DEBUG, "devm alloc gdc dev failed\n"); + gdc_log(LOG_DEBUG, "devm alloc gdc dev failed\n"); return -ENOMEM; } gdc_dev->pdev = pdev; + gdc_dev->misc_dev.minor = meson_gdc_dev.minor; + gdc_dev->misc_dev.name = meson_gdc_dev.name; + gdc_dev->misc_dev.fops = meson_gdc_dev.fops; spin_lock_init(&gdc_dev->slock); gdc_dev->irq = platform_get_irq(pdev, 0); if (gdc_dev->irq < 0) { - LOG(LOG_DEBUG, "cannot find irq for gdc\n"); + gdc_log(LOG_DEBUG, "cannot find irq for gdc\n"); return -EINVAL; } @@ -831,9 +1152,9 @@ static int gdc_platform_probe(struct platform_device *pdev) iowrite32((3<<25)|(1<<24)|(0<<16)|(3<<9)|(1<<8)|(0<<0), clk_cntl); pd_cntl = of_iomap(pdev->dev.of_node, 2); reg_value = ioread32(pd_cntl); - LOG(LOG_DEBUG, "pd_cntl=%x\n", reg_value); + gdc_log(LOG_DEBUG, "pd_cntl=%x\n", reg_value); reg_value = reg_value & (~(3<<18)); - LOG(LOG_DEBUG, "pd_cntl=%x\n", reg_value); + gdc_log(LOG_DEBUG, "pd_cntl=%x\n", reg_value); iowrite32(reg_value, pd_cntl); #endif @@ -844,18 +1165,39 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_interrupt_handler, IRQF_SHARED, "gdc", gdc_dev); if (rc != 0) - LOG(LOG_ERR, "cannot create irq func gdc\n"); + gdc_log(LOG_ERR, "cannot create irq func gdc\n"); - g_gdc_dev = gdc_dev; + gdc_manager.buffer = gdc_dma_buffer_create(); + gdc_manager.gdc_dev = gdc_dev; + rc = misc_register(&gdc_dev->misc_dev); + if (rc < 0) { + dev_err(&pdev->dev, + "misc_register() for minor %d failed\n", + gdc_dev->misc_dev.minor); + } + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_gdc_reg); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_firmware1); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_loglevel); - return misc_register(&meson_gdc_dev); + platform_set_drvdata(pdev, gdc_dev); + return rc; } static int gdc_platform_remove(struct platform_device *pdev) { - device_remove_file(&pdev->dev, &dev_attr_gdc_reg); - device_remove_file(&pdev->dev, &dev_attr_firmware1); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_gdc_reg); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_firmware1); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_loglevel); + + gdc_dma_buffer_destroy(gdc_manager.buffer); + gdc_manager.gdc_dev = NULL; misc_deregister(&meson_gdc_dev); return 0; diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index 2f3fb8feec64..942bd4052fb7 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -21,13 +21,19 @@ #include #include +enum gdc_memtype_s { + AML_GDC_MEM_ION, + AML_GDC_MEM_DMABUF, + AML_GDC_MEM_INVALID, +}; + struct gdc_buf_cfg { uint32_t type; unsigned long len; }; // each configuration addresses and size -struct gdc_config { +struct gdc_config_s { uint32_t format; uint32_t config_addr; //gdc config address uint32_t config_size; //gdc config size in 32bit @@ -41,13 +47,27 @@ struct gdc_config { uint32_t output_c_stride; //gdc output uv stride }; +struct gdc_buffer_info { + unsigned int mem_alloc_type; + unsigned int plane_number; + union { + unsigned int y_base_fd; + unsigned int shared_fd; + }; + union { + unsigned int uv_base_fd; + unsigned int u_base_fd; + }; + unsigned int v_base_fd; +}; + // overall gdc settings and state struct gdc_settings { uint32_t magic; //writing/reading to gdc base address, currently not read by api uint32_t base_gdc; //array of gdc configuration and sizes - struct gdc_config gdc_config; + struct gdc_config_s gdc_config; //update this index for new config //int gdc_config_total; //start memory to write gdc output framse @@ -88,6 +108,28 @@ struct gdc_settings { int32_t v_base_fd; }; +struct gdc_settings_ex { + uint32_t magic; + struct gdc_config_s gdc_config; + struct gdc_buffer_info input_buffer; + struct gdc_buffer_info config_buffer; + struct gdc_buffer_info output_buffer; +}; + +/* for gdc dma buf define */ +struct gdc_dmabuf_req_s { + int index; + unsigned int len; + unsigned int dma_dir; +}; + +struct gdc_dmabuf_exp_s { + int index; + unsigned int flags; + int fd; +}; +/* end of gdc dma buffer define */ + #define GDC_IOC_MAGIC 'G' #define GDC_PROCESS _IOW(GDC_IOC_MAGIC, 0x00, struct gdc_settings) #define GDC_PROCESS_NO_BLOCK _IOW(GDC_IOC_MAGIC, 0x01, struct gdc_settings) @@ -95,6 +137,14 @@ struct gdc_settings { #define GDC_REQUEST_BUFF _IOW(GDC_IOC_MAGIC, 0x03, struct gdc_settings) #define GDC_HANDLE _IOW(GDC_IOC_MAGIC, 0x04, struct gdc_settings) +#define GDC_PROCESS_EX _IOW(GDC_IOC_MAGIC, 0x05, struct gdc_settings_ex) +#define GDC_REQUEST_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x06, struct gdc_dmabuf_req_s) +#define GDC_EXP_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x07, struct gdc_dmabuf_exp_s) +#define GDC_FREE_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x08, int) +#define GDC_SYNC_DEVICE _IOW(GDC_IOC_MAGIC, 0x09, int) +#define GDC_SYNC_CPU _IOW(GDC_IOC_MAGIC, 0x0a, int) + + enum { INPUT_BUFF_TYPE = 0x1000, OUTPUT_BUFF_TYPE, @@ -121,6 +171,40 @@ struct gdc_dma_cfg { enum dma_data_direction dir; }; +struct gdc_cmd_s { + //writing/reading to gdc base address, currently not read by api + uint32_t base_gdc; + //array of gdc configuration and sizes + struct gdc_config_s gdc_config; + //update this index for new config + //int gdc_config_total; + //start memory to write gdc output framse + uint32_t buffer_addr; + //size of memory output frames to determine + //if it is enough and can do multiple write points + uint32_t buffer_size; + //current output address of gdc + uint32_t current_addr; + //set when expecting an interrupt from gdc + int32_t is_waiting_gdc; + + //input address for y and u, v planes + uint32_t y_base_addr; + union { + uint32_t uv_base_addr; + uint32_t u_base_addr; + }; + uint32_t v_base_addr; + + //when inititialised this callback will be called + //to update frame buffer addresses and offsets + void (*get_frame_buffer)(uint32_t y_base_addr, + uint32_t uv_base_addr, + uint32_t y_line_offset, + uint32_t uv_line_offset); + void *fh; +}; + /** * Configure the output gdc configuration * @@ -128,30 +212,30 @@ struct gdc_dma_cfg { * * More than one gdc settings can be accessed by index to a gdc_config_t. * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * @param gdc_config_num - selects the current gdc config to be applied * * @return 0 - success * -1 - fail. */ -int gdc_init(struct gdc_settings *gdc_settings); +int gdc_init(struct gdc_cmd_s *gdc_cmd); /** * This function stops the gdc block * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * */ -void gdc_stop(struct gdc_settings *gdc_settings); +void gdc_stop(struct gdc_cmd_s *gdc_cmd); /** * This function starts the gdc block * * Writing 0->1 transition is necessary for trigger * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * */ -void gdc_start(struct gdc_settings *gdc_settings); +void gdc_start(struct gdc_cmd_s *gdc_cmd); /** * This function points gdc to @@ -160,7 +244,7 @@ void gdc_start(struct gdc_settings *gdc_settings); * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -171,20 +255,20 @@ void gdc_start(struct gdc_settings *gdc_settings); * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process(struct gdc_settings *gdc_settings, +int gdc_process(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t uv_base_addr); -int gdc_process_yuv420p(struct gdc_settings *gdc_settings, +int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr); -int gdc_process_y_grey(struct gdc_settings *gdc_settings, +int gdc_process_y_grey(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr); -int gdc_process_yuv444p(struct gdc_settings *gdc_settings, +int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr); -int gdc_process_rgb444p(struct gdc_settings *gdc_settings, +int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr); @@ -198,12 +282,12 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, * * Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * * @return 0 - success * -1 - unexpected interrupt from GDC. */ -int gdc_get_frame(struct gdc_settings *gdc_settings); +int gdc_get_frame(struct gdc_cmd_s *gdc_cmd); /** * This function points gdc to its input resolution @@ -212,12 +296,12 @@ int gdc_get_frame(struct gdc_settings *gdc_settings); * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_run(struct gdc_settings *g); +int gdc_run(struct gdc_cmd_s *g); int32_t init_gdc_io(struct device_node *dn); diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h index db8c9b7fb94e..9cab803561fe 100644 --- a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -22,10 +22,17 @@ #include #include #include +#include #include "system_gdc_io.h" #include "gdc_api.h" -struct gdc_settings; +struct gdc_cmd_s; + +struct gdc_manager_s { + struct aml_dma_buffer *buffer; + struct meson_gdc_dev_t *gdc_dev; +}; + struct meson_gdc_dev_t { struct platform_device *pdev; void *reg_base; @@ -35,6 +42,7 @@ struct meson_gdc_dev_t { struct mutex d_mutext; struct completion d_com; int irq; + struct miscdevice misc_dev; }; struct mgdc_fh_s { @@ -43,7 +51,7 @@ struct mgdc_fh_s { struct meson_gdc_dev_t *gdev; char task_comm[32]; struct ion_client *ion_client; - struct gdc_settings gs; + struct gdc_cmd_s gdc_cmd; uint32_t mmap_type; dma_addr_t i_paddr; dma_addr_t o_paddr; diff --git a/drivers/amlogic/media/gdc/inc/sys/system_log.h b/drivers/amlogic/media/gdc/inc/sys/system_log.h index e9f0bc24d8f9..cae4ee0f2405 100644 --- a/drivers/amlogic/media/gdc/inc/sys/system_log.h +++ b/drivers/amlogic/media/gdc/inc/sys/system_log.h @@ -20,36 +20,27 @@ //changeable logs #include -#define FW_LOG_LEVEL LOG_ERR +extern unsigned int gdc_log_level; enum log_level_e { - LOG_NOTHING, - LOG_EMERG, - LOG_ALERT, + LOG_NO_THING, LOG_CRIT, LOG_ERR, LOG_WARNING, - LOG_NOTICE, LOG_INFO, LOG_DEBUG, - LOG_IRQ, LOG_MAX }; -extern const char *const gdc_log_level[LOG_MAX]; - -#define FILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) - #if 1 -#define LOG(level, fmt, arg...) \ +#define gdc_log(level, fmt, ...) \ do { \ - if ((level) <= FW_LOG_LEVEL) \ - pr_info("%s: %s(%d) %s: " fmt "\n",\ - FILE, __func__, __LINE__, \ - gdc_log_level[level], ## arg); \ + if (level <= gdc_log_level) \ + pr_info("%s: "fmt, __func__, ##__VA_ARGS__); \ } while (0) + #else -#define LOG(...) +#define gdc_log(...) #endif #endif // __SYSTEM_LOG_H__ diff --git a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c index 83a988ea5cd5..e86cff5b9b6d 100644 --- a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c +++ b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c @@ -36,32 +36,32 @@ * * More than one gdc settings can be accessed by index to a gdc_config_t. * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param gdc_config_num - selects the current gdc config to be applied * * @return 0 - success * -1 - fail. */ -int gdc_init(struct gdc_settings *gdc_settings) +int gdc_init(struct gdc_cmd_s *gdc_cmd) { - gdc_settings->is_waiting_gdc = 0; - gdc_settings->current_addr = gdc_settings->buffer_addr; + gdc_cmd->is_waiting_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; - if ((gdc_settings->gdc_config.output_width == 0) - || (gdc_settings->gdc_config.output_height == 0)) { - LOG(LOG_ERR, "Wrong GDC output resolution.\n"); + if ((gdc_cmd->gdc_config.output_width == 0) + || (gdc_cmd->gdc_config.output_height == 0)) { + gdc_log(LOG_ERR, "Wrong GDC output resolution.\n"); return -1; } //stop gdc gdc_start_flag_write(0); //set the configuration address and size to the gdc block - gdc_config_addr_write(gdc_settings->gdc_config.config_addr); - gdc_config_size_write(gdc_settings->gdc_config.config_size); + gdc_config_addr_write(gdc_cmd->gdc_config.config_addr); + gdc_config_size_write(gdc_cmd->gdc_config.config_size); //set the gdc output resolution - gdc_dataout_width_write(gdc_settings->gdc_config.output_width); - gdc_dataout_height_write(gdc_settings->gdc_config.output_height); + gdc_dataout_width_write(gdc_cmd->gdc_config.output_width); + gdc_dataout_height_write(gdc_cmd->gdc_config.output_height); return 0; } @@ -69,12 +69,12 @@ int gdc_init(struct gdc_settings *gdc_settings) /** * This function stops the gdc block * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * */ -void gdc_stop(struct gdc_settings *gdc_settings) +void gdc_stop(struct gdc_cmd_s *gdc_cmd) { - gdc_settings->is_waiting_gdc = 0; + gdc_cmd->is_waiting_gdc = 0; gdc_start_flag_write(0); } @@ -83,14 +83,14 @@ void gdc_stop(struct gdc_settings *gdc_settings) * * Writing 0->1 transition is necessary for trigger * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * */ -void gdc_start(struct gdc_settings *gdc_settings) +void gdc_start(struct gdc_cmd_s *gdc_cmd) { gdc_start_flag_write(0); //do a stop for sync gdc_start_flag_write(1); - gdc_settings->is_waiting_gdc = 1; + gdc_cmd->is_waiting_gdc = 1; } /** @@ -100,7 +100,7 @@ void gdc_start(struct gdc_settings *gdc_settings) * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -111,27 +111,27 @@ void gdc_start(struct gdc_settings *gdc_settings) * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process(struct gdc_settings *gdc_settings, +int gdc_process(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t uv_base_addr) { - uint32_t gdc_out_base_addr = gdc_settings->current_addr; - uint32_t input_width = gdc_settings->gdc_config.input_width; - uint32_t input_height = gdc_settings->gdc_config.input_height; - uint32_t output_height = gdc_settings->gdc_config.output_height; - uint32_t i_y_line_offset = gdc_settings->gdc_config.input_y_stride; - uint32_t i_uv_line_offset = gdc_settings->gdc_config.input_c_stride; - uint32_t o_y_line_offset = gdc_settings->gdc_config.output_y_stride; - uint32_t o_uv_line_offset = gdc_settings->gdc_config.output_c_stride; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; + uint32_t input_width = gdc_cmd->gdc_config.input_width; + uint32_t input_height = gdc_cmd->gdc_config.input_height; + uint32_t output_height = gdc_cmd->gdc_config.output_height; + uint32_t i_y_line_offset = gdc_cmd->gdc_config.input_y_stride; + uint32_t i_uv_line_offset = gdc_cmd->gdc_config.input_c_stride; + uint32_t o_y_line_offset = gdc_cmd->gdc_config.output_y_stride; + uint32_t o_uv_line_offset = gdc_cmd->gdc_config.output_c_stride; - if (gdc_settings->is_waiting_gdc) { + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -152,7 +152,7 @@ int gdc_process(struct gdc_settings *gdc_settings, gdc_data2out_addr_write(gdc_out_base_addr); gdc_data2out_line_offset_write(o_uv_line_offset); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -164,7 +164,7 @@ int gdc_process(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -175,27 +175,27 @@ int gdc_process(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_yuv420p(struct gdc_settings *gdc_settings, +int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; uint32_t input_u_stride = gc->input_c_stride; uint32_t input_v_stride = gc->input_c_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } ///// - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); //already set in gdc_init //uint32_t output_width = gc->output_width; @@ -231,7 +231,7 @@ int gdc_process_yuv420p(struct gdc_settings *gdc_settings, gdc_out_base_addr += output_height * output_u_stride / 2; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -244,7 +244,7 @@ int gdc_process_yuv420p(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are Y plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -253,25 +253,25 @@ int gdc_process_yuv420p(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_y_grey(struct gdc_settings *gdc_settings, +int gdc_process_y_grey(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; uint32_t output_stride = gc->output_y_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -283,7 +283,7 @@ int gdc_process_y_grey(struct gdc_settings *gdc_settings, gdc_data1out_addr_write(gdc_out_base_addr); gdc_data1out_line_offset_write(output_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -295,7 +295,7 @@ int gdc_process_y_grey(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -306,11 +306,11 @@ int gdc_process_y_grey(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_yuv444p(struct gdc_settings *gdc_settings, +int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; @@ -321,15 +321,15 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, uint32_t output_u_stride = gc->output_c_stride; uint32_t output_v_stride = gc->output_c_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -358,7 +358,7 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, gdc_out_base_addr += output_height * output_u_stride; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -370,7 +370,7 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are R\G\B plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input R base address @@ -383,11 +383,11 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_rgb444p(struct gdc_settings *gdc_settings, +int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; @@ -398,15 +398,15 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, uint32_t output_u_stride = gc->output_c_stride; uint32_t output_v_stride = gc->output_c_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -435,7 +435,7 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, gdc_out_base_addr += output_height * output_u_stride; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -449,21 +449,21 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, * * Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * * @return 0 - success * -1 - unexpected interrupt from GDC. */ -int gdc_get_frame(struct gdc_settings *gdc_settings) +int gdc_get_frame(struct gdc_cmd_s *gdc_cmd) { - struct mgdc_fh_s *fh = gdc_settings->fh; + struct mgdc_fh_s *fh = gdc_cmd->fh; uint32_t y; uint32_t y_offset; uint32_t uv; uint32_t uv_offset; - if (!gdc_settings->is_waiting_gdc) { - LOG(LOG_CRIT, "Unexpected interrupt from GDC.\n"); + if (!gdc_cmd->is_waiting_gdc) { + gdc_log(LOG_CRIT, "Unexpected interrupt from GDC.\n"); return -1; } //// @@ -471,17 +471,17 @@ int gdc_get_frame(struct gdc_settings *gdc_settings) wake_up_interruptible(&fh->irq_queue); //pass the frame buffer parameters if callback is available - if (gdc_settings->get_frame_buffer) { + if (gdc_cmd->get_frame_buffer) { y = gdc_data1out_addr_read(); y_offset = gdc_data1out_line_offset_read(); uv = gdc_data2out_addr_read(); uv_offset = gdc_data2out_line_offset_read(); - gdc_settings->get_frame_buffer(y, + gdc_cmd->get_frame_buffer(y, uv, y_offset, uv_offset); } //done of the current frame and stop gdc block - gdc_stop(gdc_settings); + gdc_stop(gdc_cmd); //spin_unlock_irqrestore(&gdev->slock, flags); return 0; } diff --git a/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c b/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c index 378789fcbf53..fcb09ab321c6 100644 --- a/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c +++ b/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c @@ -30,7 +30,7 @@ int32_t init_gdc_io(struct device_node *dn) pr_info("reg base = %p\n", p_hw_base); if (!p_hw_base) { - LOG(LOG_DEBUG, "failed to map register, %p\n", p_hw_base); + gdc_log(LOG_DEBUG, "failed to map register, %p\n", p_hw_base); return -1; } @@ -39,28 +39,32 @@ int32_t init_gdc_io(struct device_node *dn) void close_gdc_io(struct device_node *dn) { - LOG(LOG_DEBUG, "IO functionality has been closed"); + gdc_log(LOG_DEBUG, "IO functionality has been closed"); } uint32_t system_gdc_read_32(uint32_t addr) { uint32_t result = 0; - if (p_hw_base == NULL) - LOG(LOG_ERR, "Failed to base address %d\n", addr); + if (p_hw_base == NULL) { + gdc_log(LOG_ERR, "Failed to base address %d\n", addr); + return 0; + } result = ioread32(p_hw_base + addr); - LOG(LOG_DEBUG, "r [0x%04x]= %08x\n", addr, result); + gdc_log(LOG_DEBUG, "r [0x%04x]= %08x\n", addr, result); return result; } void system_gdc_write_32(uint32_t addr, uint32_t data) { - if (p_hw_base == NULL) - LOG(LOG_ERR, "Failed to write %d to addr %d\n", data, addr); + if (p_hw_base == NULL) { + gdc_log(LOG_ERR, "Failed to write %d to addr %d\n", data, addr); + return; + } void *ptr = (void *)(p_hw_base + addr); iowrite32(data, ptr); - LOG(LOG_DEBUG, "w [0x%04x]= %08x\n", addr, data); + gdc_log(LOG_DEBUG, "w [0x%04x]= %08x\n", addr, data); } From a316fc1418cb81d3c8e423e9099ec0406582b348 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Thu, 17 Jan 2019 19:42:45 +0800 Subject: [PATCH 0027/1060] Kconfig: fix errorly select meson8b for ARMv8 AARCH32 [1/1] PD#SWPL-4320 Problem: The meson8b and arm64_a32 are both selected in Kconfig, which is quite misleading Solution: Disable meson8b when arm64_a32 is selected Verify: Locally passed for Ampere Change-Id: I93f55239ea90bf8cf6b96e108b6fd4a239de32b4 Signed-off-by: Jiamin Ma --- arch/arm/boot/Makefile | 4 ++++ arch/arm/mach-meson/Kconfig | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 30fd2ed93978..e6aca688be20 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -21,6 +21,10 @@ ifeq ($(CONFIG_MACH_MESON8B),y) include $(srctree)/arch/arm/mach-meson/Makefile.boot endif +ifeq ($(CONFIG_ARM64_A32),y) +include $(srctree)/arch/arm/mach-meson/Makefile.boot +endif + include $(srctree)/arch/arm/boot/dts/Makefile # Note: the following conditions must always be true: diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index 44a995ce3cc4..cda1cc1ee69e 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -12,17 +12,17 @@ if ARCH_MESON config MACH_MESON6 bool "Amlogic Meson6 (8726MX) SoCs support" - default ARCH_MESON + default !ARM64_A32 select MESON6_TIMER config MACH_MESON8 bool "Amlogic Meson8 SoCs support" - default ARCH_MESON + default !ARM64_A32 select MESON6_TIMER config MACH_MESON8B bool "Amlogic Meson8b SoCs support" - default ARCH_MESON + default !ARM64_A32 config ARM64_A32 tristate "ARMV8 Run in A32" From 42a557a29c9c44945d1c64c28a7284707ee5b100 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Fri, 18 Jan 2019 13:30:52 +0800 Subject: [PATCH 0028/1060] osd: fix osd_reverse casued afbc decode error [1/1] PD#SWPL-4335 Problem: osd_reverse casued afbc decode error Solution: add afbc prefect reverse when osd_reverse Verify: verify by tl1 Change-Id: I11730121e62935683480f42db7c43365bc91bf31 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 33 ++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 90ff468756a2..1fe25dff54cf 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -3905,6 +3905,7 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { @@ -4024,6 +4025,7 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) if (color_mode) osd_hw.reg[OSD_COLOR_MODE].update_func(index); osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || (osd_hw.free_scale_enable[index] @@ -4980,18 +4982,35 @@ static void osd_update_enable(u32 index) static void osd_update_disp_osd_reverse(u32 index) { - if (osd_hw.osd_reverse[index] == REVERSE_TRUE) + if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 3, 28, 2); - else if (osd_hw.osd_reverse[index] == REVERSE_X) + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 3, 0, 2); + } else if (osd_hw.osd_reverse[index] == REVERSE_X) { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 1, 28, 2); - else if (osd_hw.osd_reverse[index] == REVERSE_Y) + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 1, 0, 2); + } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 2, 28, 2); - else + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 2, 0, 2); + } else { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 0, 28, 2); + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 0, 0, 2); + } remove_from_update_list(index, DISP_OSD_REVERSE); } @@ -7465,6 +7484,7 @@ static int osd_setting_order(void) } osd_hw.reg[DISP_GEOMETRY].update_func(i); osd_hw.reg[OSD_GBL_ALPHA].update_func(i); + osd_hw.reg[DISP_OSD_REVERSE].update_func(i); if (update || osd_update_window_axis) { osd_set_scan_mode(i); osd_hw.reg @@ -7748,6 +7768,7 @@ static void osd_setting_old_hwc(void) freescale_update = set_old_hwc_freescale(index); /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { @@ -7785,6 +7806,7 @@ static void osd_setting_viu2(void) osd_hw.reg[OSD_COLOR_MODE].update_func(index); /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if (!osd_hw.osd_display_debug) osd_hw.reg[OSD_ENABLE] .update_func(index); @@ -9968,6 +9990,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) plane_map->phy_addr; osd_hw.reg[OSD_COLOR_MODE].update_func(index); osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { @@ -9999,6 +10022,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) osd_cursor_move(plane_map); osd_hw.reg[OSD_COLOR_MODE].update_func(index); osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_enable != osd_hw.enable[index]) && (suspend_flag == false)) { osd_hw.enable[index] = osd_enable; @@ -10039,6 +10063,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) osd_hw.reg[OSD_COLOR_MODE].update_func(index); if (!osd_hw.hwc_enable) { osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { From 590dd9e9ece200013e01011f8a690b6d649eb201 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Tue, 15 Jan 2019 15:31:13 +0800 Subject: [PATCH 0029/1060] dv: close afbc2 when playing sources with unnecessary el [1/1] PD#SWPL-915 Problem: DOLBY only sets the enhancement for the first frame -> Vd sets cur_dispubf2 according to enhance -> codec_mm keeps the last frame according to cur_dispbuf2, so it fails -> AFBC2 access to the released content causes the trigger. Solution: close afbc2 Verify: r321 Change-Id: I03c431a6ea11b8aabf97b1f0b21f717024be2f62 Signed-off-by: Yi Zhou --- drivers/amlogic/media/video_sink/video.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 2491109e6752..3c3e356ca473 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -3891,6 +3891,11 @@ static void vsync_toggle_frame(struct vframe_s *vf) } } } + + /* if el is unnecessary, afbc2 need to be closed */ + if ((last_el_status == 1) && (vf_with_el == 0)) + need_disable_vd2 = 1; + last_el_status = vf_with_el; if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && From 7a3de9b85cf0a645c23894930b708c7eff167500 Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Wed, 2 Jan 2019 13:36:09 +0800 Subject: [PATCH 0030/1060] defconfig: arm: code score is low by Antutu benchmark [1/1] PD#SWPL-3704 Problem: 32bit code score is low by Antutu benchmark. PD#SWPL-3704 Solution: enable CONFIG_SCHED_WALT CONFIG_CGROUP_SCHEDTUNE CONFIG_SCHED_TUNE referenced by arm64 Verify: w400 Change-Id: I6f461020b0fb0e42be94f1c66f5c38defb2c6ea1 Signed-off-by: Hanjie Lin --- arch/arm/configs/meson64_a32_defconfig | 3 +++ include/trace/events/sched.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 8f2827140c23..f40ccea1e14f 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -3,6 +3,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_SCHED_WALT=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y @@ -16,9 +17,11 @@ CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHEDTUNE=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_BPF=y +CONFIG_SCHED_TUNE=y CONFIG_DEFAULT_USE_ENERGY_AWARE=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index f5780473a5c1..efe4abd4a993 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -999,7 +999,11 @@ TRACE_EVENT(walt_update_task_ravg, __entry->cs = rq->curr_runnable_sum; __entry->ps = rq->prev_runnable_sum; __entry->util = rq->prev_runnable_sum << SCHED_CAPACITY_SHIFT; +#if defined(CONFIG_AMLOGIC_MODIFY) && defined(CONFIG_ARM64_A32) + div_u64(__entry->util, walt_ravg_window); +#else do_div(__entry->util, walt_ravg_window); +#endif __entry->curr_window = p->ravg.curr_window; __entry->prev_window = p->ravg.prev_window; __entry->nt_cs = rq->nt_curr_runnable_sum; From 4d64dc6e9b44deabb1f4cd58982e47067b843f47 Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Fri, 14 Dec 2018 19:39:58 +0800 Subject: [PATCH 0031/1060] perf_event: aml pmu interrupts routing on g12b [1/1] PD#SWPL-3088 Problem: g12b big-little cluster is different from other SoC with pmu interrupts and registers. software modifications must adapt to the difference. Solution: modify Verify: u200 w400 Change-Id: If9217c1025dff5c17d51790f8c216e31b7d6532b Signed-off-by: Hanjie Lin Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/mesonaxg.dtsi | 19 +- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 18 +- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 16 +- arch/arm/boot/dts/amlogic/mesongxl.dtsi | 17 +- .../arm/boot/dts/amlogic/mesongxl_sei210.dtsi | 17 +- arch/arm/boot/dts/amlogic/mesongxm.dtsi | 17 +- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 1658 ----------------- arch/arm/boot/dts/amlogic/mesontxl.dtsi | 1536 --------------- arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 17 +- arch/arm/include/asm/hardirq.h | 4 - arch/arm/include/asm/perf_event.h | 47 - arch/arm/kernel/perf_event_v7.c | 286 +-- arch/arm/kernel/smp.c | 23 - arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 19 +- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 22 +- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 12 +- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 18 +- .../boot/dts/amlogic/mesongxl_sei210.dtsi | 13 +- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 13 +- arch/arm64/boot/dts/amlogic/mesontxl.dtsi | 1536 --------------- arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 17 +- arch/arm64/include/asm/hardirq.h | 4 - arch/arm64/include/asm/perf_event.h | 44 - arch/arm64/kernel/perf_event.c | 285 +-- arch/arm64/kernel/smp.c | 25 - drivers/perf/arm_pmu.c | 518 +++++ include/linux/perf/arm_pmu.h | 93 + include/linux/smp.h | 7 - 28 files changed, 749 insertions(+), 5552 deletions(-) delete mode 100644 arch/arm/boot/dts/amlogic/mesontl1.dtsi delete mode 100644 arch/arm/boot/dts/amlogic/mesontxl.dtsi delete mode 100644 arch/arm64/boot/dts/amlogic/mesontxl.dtsi diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index 0c9b2c5e905e..4c61c2d5be99 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -119,24 +119,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; - gic: interrupt-controller@2c001000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 1be1e4e34299..99b85bb7df7f 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -155,21 +155,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 0ef83d40bf6a..c0b5e085e44c 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -196,7 +196,7 @@ }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -215,9 +215,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; + compatible = "arm,cortex-a15-pmu"; + clusterb-enabled; + interrupts = , + ; + reg = <0xff634680 0x4>, + <0xff6347c0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index a220ea1c4fd3..a3c2f4e29bf5 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -134,19 +134,14 @@ arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xc8834400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xc8834400 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi index 9f4e451d488d..53d782398b99 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -115,7 +115,7 @@ }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -133,12 +133,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xc8834400 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index 91a1e260630b..a0a01d08676a 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -205,7 +205,7 @@ }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -223,12 +223,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xc8834400 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi deleted file mode 100644 index ed116df1b2bb..000000000000 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ /dev/null @@ -1,1658 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/mesontl1.dtsi - * - * Copyright (C) 2018 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mesong12a-bifrost.dtsi" - -/ { - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - cpus:cpus { - #address-cells = <1>; - #size-cells = <0>; - #cooling-cells = <2>;/* min followed by max */ - CPU0:cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x0>; - //timer=<&timer_a>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU1:cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x1>; - //timer=<&timer_b>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU2:cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x2>; - //timer=<&timer_c>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU3:cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x0 0x3>; - //timer=<&timer_d>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - timer_bc { - compatible = "arm, meson-bc-timer"; - reg = <0xffd0f190 0x4 0xffd0f194 0x4>; - timer_name = "Meson TimerF"; - clockevent-rating =<300>; - clockevent-shift =<20>; - clockevent-features =<0x23>; - interrupts = <0 60 1>; - bit_enable =<16>; - bit_mode =<12>; - bit_resolution =<0>; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0xffc01000 0x1000>, - <0xffc02000 0x0100>; - interrupts = ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - scpi_clocks { - compatible = "arm, scpi-clks"; - - scpi_dvfs: scpi_clocks@0 { - compatible = "arm, scpi-clk-indexed"; - #clock-cells = <1>; - clock-indices = <0>; - clock-output-names = "vcpu"; - }; - }; - - secmon { - compatible = "amlogic, secmon"; - memory-region = <&secmon_reserved>; - in_base_func = <0x82000020>; - out_base_func = <0x82000021>; - reserve_mem_size = <0x00300000>; - }; - - securitykey { - compatible = "amlogic, securitykey"; - status = "okay"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - - cpu_iomap { - compatible = "amlogic, iomap"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - io_cbus_base { - reg = <0xffd00000 0x101000>; - }; - io_apb_base { - reg = <0xffe01000 0x19f000>; - }; - io_aobus_base { - reg = <0xff800000 0x100000>; - }; - io_vapb_base { - reg = <0xff900000 0x200000>; - }; - io_hiu_base { - reg = <0xff63c000 0x2000>; - }; - }; - - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; - - meson_suspend: pm { - compatible = "amlogic, pm"; - /*gxbaby-suspend;*/ - status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; - }; - - cpuinfo { - compatible = "amlogic, cpuinfo"; - status = "okay"; - cpuinfo_cmd = <0x82000044>; - }; - - reboot { - compatible = "amlogic,reboot"; - sys_reset = <0x84000009>; - sys_poweroff = <0x84000008>; - }; - - ram-dump { - compatible = "amlogic, ram_dump"; - status = "okay"; - }; - - vpu { - compatible = "amlogic, vpu-tl1"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <7>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ - }; - - pinctrl_aobus: pinctrl@ff800014 { - compatible = "amlogic,meson-tl1-aobus-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio_ao: ao-bank@ff800014 { - reg = <0xff800014 0x8>, - <0xff800024 0x14>, - <0xff80001c 0x8>; - reg-names = "mux", "gpio", "drive-strength"; - gpio-controller; - #gpio-cells = <2>; - }; - - aoceca_mux:aoceca_mux { - mux { - groups = "cec_ao_a"; - function = "cec_ao"; - }; - }; - - aocecb_mux:aocecb_mux { - mux { - groups = "cec_ao_b"; - function = "cec_ao"; - }; - }; - }; - - pinctrl_periphs: pinctrl@ff6346c0 { - compatible = "amlogic,meson-tl1-periphs-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio: banks@ff6346c0 { - reg = <0xff6346c0 0x40>, - <0xff6344e8 0x18>, - <0xff634520 0x18>, - <0xff634440 0x4c>, - <0xff634740 0x1c>; - reg-names = "mux", - "pull", - "pull-enable", - "gpio", - "drive-strength"; - gpio-controller; - #gpio-cells = <2>; - }; - - - hdmirx_a_mux:hdmirx_a_mux { - mux { - groups = "hdmirx_a_hpd", "hdmirx_a_det", - "hdmirx_a_sda", "hdmirx_a_sck"; - function = "hdmirx_a"; - }; - }; - - hdmirx_b_mux:hdmirx_b_mux { - mux { - groups = "hdmirx_b_hpd", "hdmirx_b_det", - "hdmirx_b_sda", "hdmirx_b_sck"; - function = "hdmirx_b"; - }; - }; - - hdmirx_c_mux:hdmirx_c_mux { - mux { - groups = "hdmirx_c_hpd", "hdmirx_c_det", - "hdmirx_c_sda", "hdmirx_c_sck"; - function = "hdmirx_c"; - }; - }; - - }; - - wdt: watchdog@0xffd0f0d0 { - compatible = "amlogic, meson-wdt"; - status = "okay"; - default_timeout=<10>; - reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ - reset_watchdog_time=<2>; - shutdown_timeout=<10>; - firmware_timeout=<6>; - suspend_timeout=<6>; - reg = <0xffd0f0d0 0x10>; - clock-names = "xtal"; - clocks = <&xtal>; - }; - - jtag { - compatible = "amlogic, jtag"; - status = "disabled"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - hiubus: hiubus@ff63c000 { - compatible = "simple-bus"; - reg = <0xff63c000 0x2000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xff63c000 0x2000>; - - clkc: clock-controller@0 { - compatible = "amlogic,tl1-clkc"; - #clock-cells = <1>; - reg = <0x0 0x3fc>; - }; - };/* end of hiubus*/ - - audiobus: audiobus@0xff600000 { - compatible = "amlogic, audio-controller", "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xff600000 0x10000>; - ranges = <0x0 0xff600000 0x10000>; - - clkaudio:audio_clocks { - compatible = "amlogic, tl1-audio-clocks"; - #clock-cells = <1>; - reg = <0x0 0xb0>; - }; - - ddr_manager { - compatible = "amlogic, tl1-audio-ddr-manager"; - interrupts = < - GIC_SPI 148 IRQ_TYPE_EDGE_RISING - GIC_SPI 149 IRQ_TYPE_EDGE_RISING - GIC_SPI 150 IRQ_TYPE_EDGE_RISING - GIC_SPI 48 IRQ_TYPE_EDGE_RISING - GIC_SPI 152 IRQ_TYPE_EDGE_RISING - GIC_SPI 153 IRQ_TYPE_EDGE_RISING - GIC_SPI 154 IRQ_TYPE_EDGE_RISING - GIC_SPI 49 IRQ_TYPE_EDGE_RISING - >; - interrupt-names = - "toddr_a", "toddr_b", "toddr_c", - "toddr_d", - "frddr_a", "frddr_b", "frddr_c", - "frddr_d"; - }; - };/* end of audiobus*/ - - /* Sound iomap */ - aml_snd_iomap { - compatible = "amlogic, snd-iomap"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - pdm_bus { - reg = <0xFF601000 0x400>; - }; - audiobus_base { - reg = <0xFF600000 0x1000>; - }; - audiolocker_base { - reg = <0xFF601400 0x400>; - }; - eqdrc_base { - reg = <0xFF602000 0x2000>; - }; - reset_base { - reg = <0xFFD01000 0x1000>; - }; - vad_base { - reg = <0xFF601800 0x800>; - }; - }; - - cbus: cbus@ffd00000 { - compatible = "simple-bus"; - reg = <0xffd00000 0x27000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xffd00000 0x27000>; - - clk-measure@18004 { - compatible = "amlogic,tl1-measure"; - reg = <0x18004 0x4 0x1800c 0x4>; - }; - - i2c0: i2c@1f000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1f000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c1: i2c@1e000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1e000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c2: i2c@1d000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1d000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c3: i2c@1c000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1c000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - gpio_intc: interrupt-controller@f080 { - compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-tl1-gpio-intc"; - reg = <0xf080 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = - <64 65 66 67 68 69 70 71>; - status = "okay"; - }; - - pwm_ab: pwm@1b000 { - compatible = "amlogic,tl1-ee-pwm"; - reg = <0x1b000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - /* default xtal 24m clkin0-clkin2 and - * clkin1-clkin3 should be set the same - */ - status = "disabled"; - }; - - pwm_cd: pwm@1a000 { - compatible = "amlogic,tl1-ee-pwm"; - reg = <0x1a000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_ef: pwm@19000 { - compatible = "amlogic,tl1-ee-pwm"; - reg = <0x19000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - spicc0: spi@13000 { - compatible = "amlogic,meson-tl1-spicc", - "amlogic,meson-g12a-spicc"; - reg = <0x13000 0x44>; - interrupts = ; - clocks = <&clkc CLKID_SPICC0>, - <&clkc CLKID_SPICC0_COMP>; - clock-names = "core", "comp"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spicc1: spi@15000 { - compatible = "amlogic,meson-tl1-spicc", - "amlogic,meson-g12a-spicc"; - reg = <0x15000 0x44>; - interrupts = ; - clocks = <&clkc CLKID_SPICC1>, - <&clkc CLKID_SPICC1_COMP>; - clock-names = "core", "comp"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - }; - - aobus: aobus@ff800000 { - compatible = "simple-bus"; - reg = <0xff800000 0xb000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xff800000 0xb000>; - - cpu_version { - reg = <0x220 0x4>; - }; - - aoclkc: clock-controller@0 { - compatible = "amlogic,tl1-aoclkc"; - #clock-cells = <1>; - reg = <0x0 0x1000>; - }; - - pwm_AO_ab: pwm@7000 { - compatible = "amlogic,tl1-ao-pwm"; - reg = <0x7000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_AO_cd: pwm@2000 { - compatible = "amlogic,tl1-ao-pwm"; - reg = <0x2000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - uart_AO: serial@3000 { - compatible = "amlogic, meson-uart"; - reg = <0x3000 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <1>; - fifosize = < 64 >; - //pinctrl-names = "default"; - //pinctrl-0 = <&ao_a_uart_pins>; - /* 0 not support; 1 support */ - support-sysrq = <0>; - }; - - remote: rc@8040 { - compatible = "amlogic, aml_remote"; - reg = <0x8040 0x44>, - <0x8000 0x20>; - status = "okay"; - protocol = ; - interrupts = ; - pinctrl-names = "default"; - pinctrl-0 = <&remote_pins>; - map = <&custom_maps>; - max_frame_time = <200>; - }; - - i2c_AO: i2c@5000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x05000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c_AO_slave:i2c_slave@6000 { - compatible = "amlogic, meson-i2c-slave"; - status = "disabled"; - reg = <0x0 0x6000 0x0 0x20>; - interrupts = ; - pinctrl-names="default"; - pinctrl-0=<&i2c_ao_slave_pins>; - }; - };/* end of aobus */ - - ion_dev { - compatible = "amlogic, ion_dev"; - status = "okay"; - memory-region = <&ion_cma_reserved>; - };/* end of ion_dev*/ - }; /* end of soc*/ - - custom_maps: custom_maps { - mapnum = <3>; - map0 = <&map_0>; - map1 = <&map_1>; - map2 = <&map_2>; - map_0: map_0{ - mapname = "amlogic-remote-1"; - customcode = <0xfb04>; - release_delay = <80>; - size = <44>; /*keymap size*/ - keymap = ; - }; - - map_1: map_1{ - mapname = "amlogic-remote-2"; - customcode = <0xfe01>; - release_delay = <80>; - size = <53>; - keymap = ; - }; - - map_2: map_2{ - mapname = "amlogic-remote-3"; - customcode = <0xbd02>; - release_delay = <80>; - size = <17>; - keymap = ; - }; - }; - - sd_emmc_c: emmc@ffe07000 { - status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; - reg = <0xffe07000 0x800>; - interrupts = <0 191 1>; - pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; - pinctrl-0 = <&emmc_clk_cmd_pins>; - pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - /* mmc-ddr-1_8v; */ - /* mmc-hs200-1_8v; */ - - max-frequency = <200000000>; - non-removable; - disable-wp; - emmc { - pinname = "emmc"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - /*caps defined in dts*/ - tx_delay = <0>; - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; - card_type = <1>; - /* 1:mmc card(include eMMC), - * 2:sd card(include tSD) - */ - }; - }; - - sd_emmc_b: sd@ffe05000 { - status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; - reg = <0xffe05000 0x800>; - interrupts = <0 190 1>; - - pinctrl-names = "sd_all_pins", - "sd_clk_cmd_pins", - "sd_1bit_pins", - "sd_clk_cmd_uart_pins", - "sd_1bit_uart_pins", - "sd_to_ao_uart_pins", - "ao_to_sd_uart_pins", - "sd_to_ao_jtag_pins", - "ao_to_sd_jtag_pins"; - pinctrl-0 = <&sd_all_pins>; - pinctrl-1 = <&sd_clk_cmd_pins>; - pinctrl-2 = <&sd_1bit_pins>; - pinctrl-3 = <&sd_to_ao_uart_clr_pins - &sd_clk_cmd_pins &ao_to_sd_uart_pins>; - pinctrl-4 = <&sd_to_ao_uart_clr_pins - &sd_1bit_pins &ao_to_sd_uart_pins>; - pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - disable-wp; - sd { - pinname = "sd"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; - jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; - gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; - card_type = <5>; - /* 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card - */ - }; - }; - - spifc: spifc@ffd14000 { - compatible = "amlogic,aml-spi-nor"; - status = "disabled"; - - reg = <0x0 0xffd14000 0x0 0x80>; - pinctrl-names = "default"; - pinctrl-0 = <&spifc_all_pins>; - clock-names = "core"; - clocks = <&clkc CLKID_CLK81>; - - spi-nor@0 { - compatible = "jedec,spi-nor"; - spifc-frequency = <40000000>; - read-capability = <4>;/* dual read 1_1_2 */ - spifc-io-width = <4>; - }; - }; - - slc_nand: nand-controller@0xFFE07800 { - compatible = "amlogic, aml_mtd_nand"; - status = "okay"; - reg = <0x0 0xFFE07800 0x0 0x200>; - interrupts = <0 34 1>; - - pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; - pinctrl-0 = <&all_nand_pins>; - pinctrl-1 = <&all_nand_pins>; - pinctrl-2 = <&nand_cs_pins>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>; - clock-names = "core", "clkin"; - - device_id = <0>; - /*fip/tpl configurations, must be same - *with uboot if bl_mode was set as 1 - *bl_mode: 0 compact mode;1 descrete mode - *if bl_mode was set as 1,fip configuration will work - */ - bl_mode = <1>; - /*copy count of fip*/ - fip_copies = <4>; - /*size of each fip copy*/ - fip_size = <0x200000>; - nand_clk_ctrl = <0xFFE07000>; - /*partions defined in dts*/ - }; - - mesonstream { - compatible = "amlogic, codec, streambuf"; - status = "okay"; - clocks = <&clkc CLKID_U_PARSER - &clkc CLKID_DEMUX - &clkc CLKID_AHB_ARB0 - &clkc CLKID_DOS - &clkc CLKID_VDEC_MUX - &clkc CLKID_HCODEC_MUX - &clkc CLKID_HEVC_MUX - &clkc CLKID_HEVCF_MUX>; - clock-names = "parser_top", - "demux", - "ahbarb0", - "vdec", - "clk_vdec_mux", - "clk_hcodec_mux", - "clk_hevc_mux", - "clk_hevcb_mux"; - }; - - vcodec-dec { - compatible = "amlogic, vcodec-dec"; - status = "okay"; - }; - - vdec { - compatible = "amlogic, vdec"; - status = "okay"; - interrupts = <0 3 1 - 0 23 1 - 0 32 1 - 0 43 1 - 0 44 1 - 0 45 1>; - interrupt-names = "vsync", - "demux", - "parser", - "mailbox_0", - "mailbox_1", - "mailbox_2"; - }; - - canvas: canvas { - compatible = "amlogic, meson, canvas"; - status = "okay"; - reg = <0xff638000 0x2000>; - }; - - codec_io: codec_io { - compatible = "amlogic, codec_io"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base{ - reg = <0xffd00000 0x100000>; - }; - io_dos_base{ - reg = <0xff620000 0x10000>; - }; - io_hiubus_base{ - reg = <0xff63c000 0x2000>; - }; - io_aobus_base{ - reg = <0xff800000 0x10000>; - }; - io_vcbus_base{ - reg = <0xff900000 0x40000>; - }; - io_dmc_base{ - reg = <0xff638000 0x2000>; - }; - io_efuse_base{ - reg = <0xff630000 0x2000>; - }; - }; - - rdma { - compatible = "amlogic, meson-tl1, rdma"; - status = "okay"; - interrupts = <0 89 1>; - interrupt-names = "rdma"; - }; - - meson_fb: fb { - compatible = "amlogic, meson-tl1"; - memory-region = <&logo_reserved>; - status = "disabled"; - interrupts = <0 3 1 - 0 56 1 - 0 89 1>; - interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; - /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ - display_mode_default = "1080p60hz"; - scale_mode = <1>; - /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ - display_size_default = <1920 1080 1920 2160 32>; - /*1920*1080*4*3 = 0x17BB000*/ - clocks = <&clkc CLKID_VPU_CLKC_MUX>; - clock-names = "vpu_clkc"; - }; - - ge2d { - compatible = "amlogic, ge2d-g12a"; - status = "okay"; - interrupts = <0 146 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xff940000 0x10000>; - }; - - meson-amvideom { - compatible = "amlogic, amvideom"; - status = "okay"; - interrupts = <0 3 1>; - interrupt-names = "vsync"; - }; - - vdac { - compatible = "amlogic, vdac-tl1"; - status = "okay"; - }; - - dmc_monitor { - compatible = "amlogic, dmc_monitor"; - status = "okay"; - reg_base = <0xff638800>; - interrupts = ; - }; - - efuse: efuse{ - compatible = "amlogic, efuse"; - read_cmd = <0x82000030>; - write_cmd = <0x82000031>; - get_max_cmd = <0x82000033>; - key = <&efusekey>; - clocks = <&clkc CLKID_EFUSE>; - clock-names = "efuse_clk"; - status = "disabled"; - }; - - efusekey:efusekey{ - keynum = <4>; - key0 = <&key_0>; - key1 = <&key_1>; - key2 = <&key_2>; - key3 = <&key_3>; - key_0:key_0{ - keyname = "mac"; - offset = <0>; - size = <6>; - }; - key_1:key_1{ - keyname = "mac_bt"; - offset = <6>; - size = <6>; - }; - key_2:key_2{ - keyname = "mac_wifi"; - offset = <12>; - size = <6>; - }; - key_3:key_3{ - keyname = "usid"; - offset = <18>; - size = <16>; - }; - }; - - audio_data: audio_data { - compatible = "amlogic, audio_data"; - query_licence_cmd = <0x82000050>; - status = "disabled"; - }; -}; /* end of / */ - -&pinctrl_aobus { - sd_to_ao_uart_clr_pins: sd_to_ao_uart_clr_pins { - mux { - groups = "GPIOAO_0", - "GPIOAO_1", - "GPIOAO_2", - "GPIOAO_3", - "GPIOAO_4", - "GPIOAO_5", - "GPIOAO_6", - "GPIOAO_7", - "GPIOAO_8", - "GPIOAO_9", - "GPIOAO_10", - "GPIOAO_11", - "GPIOE_0", - "GPIOE_1", - "GPIOE_2", - "GPIO_TEST_N"; - function = "gpio_aobus"; - }; - }; - - sd_to_ao_uart_pins: sd_to_ao_uart_pins { - mux { - groups = "uart_ao_a_tx", - "uart_ao_a_rx", - "uart_ao_a_cts", - "uart_ao_a_rts"; - function = "uart_ao_a"; - bias-pull-up; - input-enable; - }; - }; - - remote_pins:remote_pin { - mux { - groups = "remote_input_ao"; - function = "remote_input_ao"; - }; - }; - - pwm_ao_a_pins: pwm_ao_a { - mux { - groups = "pwm_ao_a"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_a_hiz_pins: pwm_ao_a_hiz { - mux { - groups = "pwm_ao_a_hiz"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_b_pins: pwm_ao_b { - mux { - groups = "pwm_ao_b"; - function = "pwm_ao_b"; - }; - }; - - pwm_ao_c_pins1: pwm_ao_c_pins1 { - mux { - groups = "pwm_ao_c_4"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_c_pins2: pwm_ao_c_pins2 { - mux { - groups = "pwm_ao_c_6"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_c_hiz_pins1: pwm_ao_c_hiz1 { - mux { - groups = "pwm_ao_c_hiz_4"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_c_hiz_pins2: pwm_ao_c_hiz2 { - mux { - groups = "pwm_ao_c_hiz_7"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_d_pins1: pwm_ao_d_pins1 { - mux { - groups = "pwm_ao_d_5"; - function = "pwm_ao_d"; - }; - }; - - pwm_ao_d_pins2: pwm_ao_d_pins2 { - mux { - groups = "pwm_ao_d_10"; - function = "pwm_ao_d"; - }; - }; - - pwm_ao_d_pins3: pwm_ao_d_pins3 { - mux { - groups = "pwm_ao_d_e"; - function = "pwm_ao_d"; - }; - }; - - pwm_a_e2: pwm_a_e2 { - mux { - groups = "pwm_a_e2"; - function = "pwm_a_e2"; - }; - }; - - i2c_ao_2_pins:i2c_ao_2 { - mux { - groups = "i2c_ao_sck_2", - "i2c_ao_sda_3"; - function = "i2c_ao"; - }; - }; - - i2c_ao_e_pins:i2c_ao_e { - mux { - groups = "i2c_ao_sck_e", - "i2c_ao_sda_e"; - function = "i2c_ao"; - }; - }; - - i2c_ao_slave_pins:i2c_ao_slave { - mux { - groups = "i2c_ao_slave_sck", - "i2c_ao_slave_sda"; - function = "i2c_ao_slave"; - }; - }; -}; - -&pinctrl_periphs { - /* sdemmc portC */ - emmc_clk_cmd_pins: emmc_clk_cmd_pins { - mux { - groups = "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - emmc_conf_pull_up: emmc_conf_pull_up { - mux { - groups = "emmc_nand_d7", - "emmc_nand_d6", - "emmc_nand_d5", - "emmc_nand_d4", - "emmc_nand_d3", - "emmc_nand_d2", - "emmc_nand_d1", - "emmc_nand_d0", - "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - emmc_conf_pull_done: emmc_conf_pull_done { - mux { - groups = "emmc_nand_ds"; - function = "emmc"; - input-enable; - bias-pull-down; - drive-strength = <3>; - }; - }; - - /* sdemmc portB */ - sd_clk_cmd_pins: sd_clk_cmd_pins { - mux { - groups = "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - sd_all_pins: sd_all_pins { - mux { - groups = "sdcard_d0", - "sdcard_d1", - "sdcard_d2", - "sdcard_d3", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - sd_1bit_pins: sd_1bit_pins { - mux { - groups = "sdcard_d0", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - ao_to_sd_uart_pins: ao_to_sd_uart_pins { - mux { - groups = "uart_ao_a_rx_c", - "uart_ao_a_tx_c", - "uart_ao_a_rx_w3", - "uart_ao_a_tx_w2", - "uart_ao_a_rx_w7", - "uart_ao_a_tx_w6", - "uart_ao_a_rx_w11", - "uart_ao_a_tx_w10"; - function = "uart_ao_a_ee"; - bias-pull-up; - input-enable; - }; - }; - - all_nand_pins: all_nand_pins { - mux { - groups = "emmc_nand_d0", - "emmc_nand_d1", - "emmc_nand_d2", - "emmc_nand_d3", - "emmc_nand_d4", - "emmc_nand_d5", - "emmc_nand_d6", - "emmc_nand_d7", - "nand_ce0", - "nand_ale", - "nand_cle", - "nand_wen_clk", - "nand_ren_wr"; - function = "nand"; - input-enable; - drive-strength = <3>; - }; - }; - - nand_cs_pins:nand_cs { - mux { - groups = "nand_ce0"; - function = "nand"; - drive-strength = <3>; - }; - }; - - /* sdemmc portA */ - sdio_clk_cmd_pins: sdio_clk_cmd_pins { - mux { - groups = "sdio_clk", - "sdio_cmd"; - function = "sdio"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - sdio_all_pins: sdio_all_pins { - mux { - groups = "sdio_d0", - "sdio_d1", - "sdio_d2", - "sdio_d3", - "sdio_clk", - "sdio_cmd"; - function = "sdio"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - spifc_cs_pin:spifc_cs_pin { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_pulldown: spifc_pulldown { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - bias-pull-down; - }; - }; - - spifc_pullup: spifc_pullup { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_all_pins: spifc_all_pins { - mux { - groups = "nor_d", - "nor_q", - "nor_c", - "nor_hold", - "nor_wp"; - function = "nor"; - input-enable; - bias-pull-down; - }; - }; - - pwm_a_pins: pwm_a { - mux { - groups = "pwm_a"; - function = "pwm_a"; - }; - }; - - pwm_b_pins1: pwm_b_pins1 { - mux { - groups = "pwm_b_c"; - function = "pwm_b"; - }; - }; - - pwm_b_pins2: pwm_b_pins2 { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - - pwm_c_pins1: pwm_c_pins1 { - mux { - groups = "pwm_c_dv"; - function = "pwm_c"; - }; - }; - - pwm_c_pins2: pwm_c_pins2 { - mux { - groups = "pwm_c_h"; - function = "pwm_c"; - }; - }; - - pwm_c_pins3: pwm_c_pins3 { - mux { - groups = "pwm_c_z"; - function = "pwm_c"; - }; - }; - - pwm_d_pins1: pwm_d_pins1 { - mux { - groups = "pwm_d_dv"; - function = "pwm_d"; - }; - }; - - pwm_d_pins2: pwm_d_pins2 { - mux { - groups = "pwm_d_z"; - function = "pwm_d"; - }; - }; - - pwm_e_pins1: pwm_e1 { - mux { - groups = "pwm_e_dv"; - function = "pwm_e"; - }; - }; - - pwm_e_pins2: pwm_e2 { - mux { - groups = "pwm_e_z"; - function = "pwm_e"; - }; - }; - - pwm_f_pins1: pwm_f_pins1 { - mux { - groups = "pwm_f_dv"; - function = "pwm_f"; - }; - }; - - pwm_f_pins2: pwm_f_pins2 { - mux { - groups = "pwm_f_z"; - function = "pwm_f"; - }; - }; - - i2c0_c_pins:i2c0_c { - mux { - groups = "i2c0_sda_c", - "i2c0_sck_c"; - function = "i2c0"; - }; - }; - - i2c0_dv_pins:i2c0_dv { - mux { - groups = "i2c0_sda_dv", - "i2c0_sck_dv"; - function = "i2c0"; - }; - }; - - i2c1_z_pins:i2c1_z { - mux { - groups = "i2c1_sda_z", - "i2c1_sck_z"; - function = "i2c1"; - }; - }; - - i2c1_h_pins:i2c1_h { - mux { - groups = "i2c1_sda_h", - "i2c1_sck_h"; - function = "i2c1"; - }; - }; - - i2c2_h_pins:i2c2_h { - mux { - groups = "i2c2_sda_h", - "i2c2_sck_h"; - function = "i2c2"; - }; - }; - - i2c2_z_pins:i2c2_z { - mux { - groups = "i2c2_sda_z", - "i2c2_sck_z"; - function = "i2c2"; - }; - }; - - i2c3_h1_pins:i2c3_h1 { - mux { - groups = "i2c3_sda_h1", - "i2c3_sck_h0"; - function = "i2c3"; - }; - }; - - i2c3_h20_pins:i2c3_h3 { - mux { - groups = "i2c3_sda_h20", - "i2c3_sck_h19"; - function = "i2c3"; - }; - }; - - i2c3_dv_pins:i2c3_dv { - mux { - groups = "i2c3_sda_dv", - "i2c3_sck_dv"; - function = "i2c3"; - }; - }; - - i2c3_c_pins:i2c3_c { - mux { - groups = "i2c3_sda_c", - "i2c3_sck_c"; - function = "i2c3"; - }; - }; - - spicc0_pins_h: spicc0_pins_h { - mux { - groups = "spi0_mosi_h", - "spi0_miso_h", - "spi0_clk_h"; - function = "spi0"; - drive-strength = <1>; - }; - }; - - spicc1_pins_dv: spicc1_pins_dv { - mux { - groups = "spi1_mosi_dv", - "spi1_miso_dv", - "spi1_clk_dv"; - function = "spi1"; - drive-strength = <1>; - }; - }; -}; diff --git a/arch/arm/boot/dts/amlogic/mesontxl.dtsi b/arch/arm/boot/dts/amlogic/mesontxl.dtsi deleted file mode 100644 index 9cb47c6bcc9b..000000000000 --- a/arch/arm/boot/dts/amlogic/mesontxl.dtsi +++ /dev/null @@ -1,1536 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/mesontxl.dtsi - * - * Copyright (C) 2018 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "mesongxbb-gpu-mali450.dtsi" -#include - -/ { - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - cpus:cpus { - #address-cells = <1>; - #size-cells = <0>; - #cooling-cells = <2>; - - /*cpu-map { - cluster0:cluster0 { - core0 { - cpu = <&CPU0>; - }; - core1 { - cpu = <&CPU1>; - }; - core2 { - cpu = <&CPU2>; - }; - core3 { - cpu = <&CPU3>; - }; - }; - };*/ - - CPU0:cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU1:cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x1>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU2:cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x2>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU3:cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x3>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - idle-states { - entry-method = "arm,psci"; -/* - CPU_SLEEP_0: cpu-sleep-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; - local-timer-stop; - entry-latency-us = <3000>; - exit-latency-us = <3000>; - min-residency-us = <8000>; - }; -*/ - - SYSTEM_SLEEP_0: system-sleep-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0020000>; - local-timer-stop; - entry-latency-us = <0x3fffffff>; - exit-latency-us = <0x40000000>; - min-residency-us = <0xffffffff>; - }; - - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - timer_bc: timer@c1109990 { - compatible = "arm, meson-bc-timer"; - reg = <0xc1109990 0x4 0xc1109994 0x4>; - timer_name = "Meson TimerF"; - clockevent-rating = <300>; - clockevent-shift = <20>; - clockevent-features = <0x23>; - interrupts = <0 60 1>; - bit_enable = <16>; - bit_mode = <12>; - bit_resolution = <0>; - }; - - pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = , - , - , - ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0xc4301000 0x1000>, - <0xc4302000 0x0100>; - interrupts = ; - }; - - clocks { - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; - }; - - cpu_iomap { - compatible = "amlogic, iomap"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base { - reg = <0xc1100000 0x100000>; - }; - io_apb_base { - reg = <0xd0000000 0x100000>; - }; - io_aobus_base { - reg = <0xc8100000 0x100000>; - }; - io_vapb_base { - reg = <0xd0100000 0x100000>; - }; - io_hiu_base { - reg = <0xc883c000 0x2000>; - }; - }; - - cpuinfo { - compatible = "amlogic, cpuinfo"; - cpuinfo_cmd = <0x82000044>; - }; - - ram-dump { - compatible = "amlogic, ram_dump"; - status = "okay"; - }; - - securitykey { - compatible = "amlogic, securitykey"; - status = "okay"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - - mailbox: mhu@c883c400 { - compatible = "amlogic, meson_mhu"; - reg = <0xc883c400 0x4c>, /* MHU registers */ - <0xc8013000 0x800>; /* Payload area */ - interrupts = <0 209 1>, /* low priority interrupt */ - <0 210 1>; /* high priority interrupt */ - #mbox-cells = <1>; - mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; - mboxes = <&mailbox 0 &mailbox 1>; - }; - - scpi_clocks { - compatible = "arm, scpi-clks"; - - scpi_dvfs: scpi_clocks@0 { - compatible = "arm, scpi-clk-indexed"; - #clock-cells = <1>; - clock-indices = <0>; - clock-output-names = "vcpu"; - }; - - }; - - pinctrl_aobus: pinctrl@c8100014{ - compatible = "amlogic,meson-txl-aobus-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio_ao: ao-bank@c8100014{ - reg = <0xc8100014 0x8>, - <0xc810002c 0x4>, - <0xc8100024 0x8>; - reg-names = "mux", "pull", "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - pinctrl_periphs: pinctrl@c88344b0{ - compatible = "amlogic,meson-txl-periphs-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio: banks@c88344b0{ - reg = <0xc88344b0 0x28>, - <0xc88344e8 0x14>, - <0xc8834520 0x14>, - <0xc8834430 0x40>; - reg-names = "mux", - "pull", - "pull-enable", - "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - dwc3: dwc3@c9000000 { - compatible = "synopsys, dwc3"; - status = "disable"; - reg = <0xc9000000 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy>, <&usb3_phy>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - }; - - usb2_phy: usb2phy@d0078000 { - compatible = "amlogic, amlogic-new-usb2"; - status = "disable"; - portnum = <4>; - reg = <0xd0078000 0x80 - 0xc1104408 0x4>; - }; - - usb3_phy: usb3phy@d0078080 { - compatible = "amlogic, amlogic-new-usb3"; - status = "disable"; - portnum = <0>; - reg = <0xd0078080 0x20>; - }; - - dwc2_a: dwc2_a@c9100000 { - compatible = "amlogic, dwc2"; - status = "disable"; - reg = <0xc9100000 0x40000>; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "gxl"; - phy-reg = <0xd0078000>; - phy-reg-size = <0xa0>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR - &clkc CLKID_USB1>; - clock-names = "usb_general", - "usb1", - "usb1_to_ddr"; - }; - - ethmac: ethernet@0xc9410000 { - compatible = "amlogic, gxbb-eth-dwmac"; - status = "disable"; - reg = <0xc9410000 0x10000 - 0xc8834540 0x8 - 0xc8834558 0xc - 0xc1104484 0x4>; - interrupts = <0 8 1 - 0 9 1>; - phy-mode= "rmii"; - mc_val_internal_phy = <0x1800>; - mc_val_external_phy = <0x1621>; - interrupt-names = "macirq", - "phyirq"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - internal_phy=<1>; - }; - - saradc: saradc { - compatible = "amlogic,meson-txl-saradc"; - status = "okay"; - #io-channel-cells = <1>; - clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; - clock-names = "xtal", "saradc_clk"; - interrupts = ; - reg = <0xc8100600 0x38>; - }; - - jtag { - compatible = "amlogic, jtag"; - status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_3 0 - &gpio_ao GPIOAO_4 0 - &gpio_ao GPIOAO_5 0 - &gpio_ao GPIOAO_7 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; - }; - - meson_suspend: pm { - compatible = "amlogic, pm"; - status = "okay"; - reg = <0xc81000a8 0x4>, - <0xc810023c 0x4>; - }; - - reboot { - compatible = "amlogic,reboot"; - sys_reset = <0x84000009>; - sys_poweroff = <0x84000008>; - }; - - rtc { - compatible = "amlogic, aml_vrtc"; - alarm_reg_addr = <0xc81000a8>; - timer_e_addr = <0xc1109988>; - init_date = "2018/01/01"; - status = "okay"; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - cbus: bus@c1100000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc1100000 0x100000>; - ranges = <0x0 0xc1100000 0x100000>; - - meson_clk_msr@875c{ - compatible = "amlogic, gxl_measure"; - reg = <0x875c 0x4 - 0x8764 0x4>; - }; - - /*i2c-A*/ - i2c0: i2c@8500 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x8500 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-B*/ - i2c1: i2c@87c0 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x87c0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-C*/ - i2c2: i2c@87e0 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x87e0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-D*/ - i2c3: i2c@8d20 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x8d20 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_ab: pwm@8550 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x8550 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_cd: pwm@8640 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x8640 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_ef: pwm@86c0 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x86c0 0x1c>; - #pwm-cells = <3>; - status = "disabled"; - }; - - spicc: spi@8d80 { - compatible = "amlogic,meson-txl-spicc", - "amlogic,meson-txlx-spicc"; - reg = <0x8d80 0x3c>; - interrupts = ; - clocks = <&clkc CLKID_SPICC0>; - clock-names = "core"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - uart_A: serial@84c0 { - compatible = "amlogic, meson-uart"; - reg = <0x84c0 0x18>; - interrupts = <0 26 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART0>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 128 >; - pinctrl-names = "default"; - pinctrl-0 = <&a_uart_pins>; - }; - - uart_B: serial@84dc { - compatible = "amlogic, meson-uart"; - reg = <0x84dc 0x18>; - interrupts = <0 75 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART1>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&b_uart_pins>; - }; - - uart_C: serial@8700 { - compatible = "amlogic, meson-uart"; - reg = <0x8700 0x18>; - interrupts = <0 93 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART2>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&c_uart_pins>; - }; - - gpio_intc: interrupt-controller@9880 { - compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-txl-gpio-intc"; - reg = <0x9880 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = - <64 65 66 67 68 69 70 71>; - status = "okay"; - }; - - wdt_ee: watchdog@98d0 { - compatible = "amlogic, meson-wdt"; - status = "okay"; - default_timeout=<10>; - reset_watchdog_method=<1>;/*0:sysfs,1:kernel*/ - reset_watchdog_time=<2>; - shutdown_timeout=<10>; - firmware_timeout=<6>; - suspend_timeout=<6>; - reg = <0x98d0 0x10>; - clock-names = "xtal"; - clocks = <&xtal>; - }; - - }; /* end of cbus */ - - aobus: bus@c8100000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc8100000 0x100000>; - ranges = <0x0 0xc8100000 0x100000>; - - cpu_version { - reg=<0x220 0x4>; - }; - - aoclkc: clock-controller@0 { - compatible = "amlogic,txl-aoclkc"; - #clock-cells = <1>; - reg = <0x0 0x1000>; - }; - - uart_AO: serial@4c0 { - compatible = "amlogic, meson-uart"; - reg = <0x4c0 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <1>; - fifosize = < 64 >; - pinctrl-names = "default"; - /*pinctrl-0 = <&ao_uart_pins>;*/ - /* 0 not support;1 support */ - support-sysrq = <0>; - }; - - uart_AO_B: serial@04e0 { - compatible = "amlogic, meson-uart"; - reg = <0x04e0 0x18>; - interrupts = <0 197 1>; - status = "disabled"; - clocks = <&xtal>; - clock-names = "clk_uart"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_b_uart_pins>; - }; - - i2c_AO: i2c@0500 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0500 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_aoab: pwm@0550 { - compatible = "amlogic,txl-ao-pwm"; - reg = <0x0550 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - remote:rc@0580 { - compatible = "amlogic, aml_remote"; - dev_name = "meson-remote"; - reg = <0x0580 0x44>, - <0x0480 0x20>; - status = "okay"; - protocol = ; - interrupts = <0 196 1>; - pinctrl-names = "default"; - pinctrl-0 = <&remote_pins>; - map = <&custom_maps>; - max_frame_time = <200>; - }; - }; /* end of aobus*/ - - periphs: periphs@c8834000 { - compatible = "simple-bus"; - reg = <0xc8834000 0x2000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xc8834000 0x2000>; - - rng { - compatible = "amlogic,meson-rng"; - reg = <0x0 0x4>; - quality = /bits/ 16 <1000>; - }; - };/* end of periphs */ - - hiubus: bus@c883c000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc883c000 0x2000>; - ranges = <0x0 0xc883c000 0x2000>; - - clkc: clock-controller@0 { - compatible = "amlogic,txl-clkc"; - #clock-cells = <1>; - reg = <0x0 0x3fc>; - }; - };/* end of hiubus*/ - - }; /* end of soc*/ - - custom_maps: custom_maps { - mapnum = <3>; - map0 = <&map_0>; - map1 = <&map_1>; - map2 = <&map_2>; - map_0: map_0{ - mapname = "amlogic-remote-1"; - customcode = <0xfb04>; - release_delay = <80>; - size = <44>; /*keymap size*/ - keymap = ; - }; - - map_1: map_1{ - mapname = "amlogic-remote-2"; - customcode = <0xfe01>; - release_delay = <80>; - size = <53>; - keymap = ; - }; - - map_2: map_2{ - mapname = "amlogic-remote-3"; - customcode = <0xbd02>; - release_delay = <80>; - size = <17>; - keymap = ; - }; - }; - - aocec: aocec@0xc8100000 { - compatible = "amlogic, aocec-txl"; - status = "okay"; - vendor_name = "Amlogic"; /* Max Chars: 8 */ - /* Refer to the following URL at: - * http://standards.ieee.org/develop/regauth/oui/oui.txt - */ - vendor_id = <0x000000>; - product_desc = "TXL"; /* Max Chars: 16 */ - cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <3>; - ee_cec; - arc_port_mask = <0x2>; - interrupts = <0 56 1 - 0 199 1>; - interrupt-names = "hdmi_aocecb","hdmi_aocec"; - pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocec>; - reg = <0xc810023c 0x4 - 0xc8100000 0x200 - 0xda83e000 0x10 - 0xc883c000 0x400>; - reg-names = "ao_exit","ao","hdmirx","hhi"; - }; - - canvas: canvas{ - compatible = "amlogic, meson, canvas"; - dev_name = "amlogic-canvas"; - status = "okay"; - reg = <0xc8838000 0x2000>; - }; - - codec_io: codec_io { - compatible = "amlogic, codec_io"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base{ - reg = <0xC1100000 0x100000>; - }; - io_dos_base{ - reg = <0xc8820000 0x10000>; - }; - io_hiubus_base{ - reg = <0xc883c000 0x2000>; - }; - io_aobus_base{ - reg = <0xc8100000 0x100000>; - }; - io_vcbus_base{ - reg = <0xd0100000 0x40000>; - }; - io_dmc_base{ - reg = <0xc8838000 0x400>; - }; - }; - - vpu { - compatible = "amlogic, vpu-txl"; - dev_name = "vpu"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <7>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ - }; - - ge2d { - compatible = "amlogic, ge2d-txl"; - status = "okay"; - interrupts = <0 146 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xd0160000 0x10000>; - }; - - meson-amvideom { - compatible = "amlogic, amvideom"; - status = "okay"; - interrupts = <0 3 1>; - interrupt-names = "vsync"; - }; - - mesonstream { - compatible = "amlogic, codec, streambuf"; - status = "okay"; - clocks = <&clkc CLKID_DOS_PARSER - &clkc CLKID_DEMUX - &clkc CLKID_DOS - &clkc CLKID_CLK81 - &clkc CLKID_VDEC_MUX - &clkc CLKID_HCODEC_MUX - &clkc CLKID_HEVC_MUX>; - clock-names = "parser_top", - "demux", - "vdec", - "clk_81", - "clk_vdec_mux", - "clk_hcodec_mux", - "clk_hevc_mux"; - }; - - codec_mm { - compatible = "amlogic, codec, mm"; - status = "okay"; - memory-region = <&codec_mm_cma &codec_mm_reserved>; - }; - - vdec { - compatible = "amlogic, vdec"; - status = "okay"; - interrupts = <0 3 1 - 0 23 1 - 0 32 1 - 0 43 1 - 0 44 1 - 0 45 1>; - interrupt-names = "vsync", - "demux", - "parser", - "mailbox_0", - "mailbox_1", - "mailbox_2"; - }; - - amvenc_avc { - compatible = "amlogic, amvenc_avc"; - status = "okay"; - //memory-region = <&amvenc_avc_reserved>; - //memory-region = <&avc_cma_reserved>; - interrupts = <0 45 1>; - interrupt-names = "mailbox_2"; - }; - - rdma { - compatible = "amlogic, meson, rdma"; - dev_name = "amlogic-rdma"; - status = "okay"; - interrupts = <0 89 1>; - interrupt-names = "rdma"; - }; - - audio_data: audio_data { - compatible = "amlogic, audio_data"; - query_licence_cmd = <0x82000050>; - status = "disabled"; - }; - - efuse: efuse { - compatible = "amlogic, efuse"; - read_cmd = <0x82000030>; - write_cmd = <0x82000031>; - get_max_cmd = <0x82000033>; - key = <&efusekey>; - clocks = <&clkc CLKID_EFUSE>; - clock-names = "efuse_clk"; - status = "disabled"; - }; - - efusekey:efusekey { - keynum = <4>; - key0 = <&key_0>; - key1 = <&key_1>; - key2 = <&key_2>; - key3 = <&key_3>; - key_0:key_0 { - keyname = "mac"; - offset = <0>; - size = <6>; - }; - key_1:key_1 { - keyname = "mac_bt"; - offset = <6>; - size = <6>; - }; - key_2:key_2 { - keyname = "mac_wifi"; - offset = <12>; - size = <6>; - }; - key_3:key_3 { - keyname = "usid"; - offset = <18>; - size = <16>; - }; - }; - - cpu_ver_name { - compatible = "amlogic, cpu-major-id-txl"; - status = "okay"; - }; - - ddr_bandwidth { - compatible = "amlogic, ddr-bandwidth"; - status = "okay"; - reg = <0xc8838000 0x100 - 0xc8837000 0x100>; - interrupts = <0 52 1>; - interrupt-names = "ddr_bandwidth"; - }; - dmc_monitor { - compatible = "amlogic, dmc_monitor"; - status = "okay"; - reg_base = <0xda838400>; - interrupts = <0 51 1>; - }; - - vdac { - compatible = "amlogic, vdac-txl"; - status = "okay"; - }; -}; /* end of / */ - -&gpu{ - /*gpu max freq is 750M*/ - tbl = <&clk285_cfg &clk400_cfg &clk500_cfg &clk666_cfg &clk750_cfg>; -}; - -&pinctrl_aobus { - - pwm_ao_a_ao3_pins: pwm_ao_a_ao3 { - mux { - groups = "pwm_ao_a_ao3"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_a_ao7_pins: pwm_ao_a_ao7 { - mux { - groups = "pwm_ao_a_ao7"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_b_ao8_pins: pwm_ao_b_ao8 { - mux { - groups = "pwm_ao_b_ao8"; - function = "pwm_ao_b"; - }; - }; - - pwm_ao_b_ao9_pins: pwm_ao_b_ao9 { - mux { - groups = "pwm_ao_b_ao9"; - function = "pwm_ao_b"; - }; - }; - - remote_pins:remote_pin { - mux { - groups = "remote_in"; - function = "ir_in"; - }; - - }; - - sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { - mux { - groups = "GPIOAO_0", - "GPIOAO_1"; - function = "gpio_aobus"; - }; - }; - - sd_to_ao_uart_pins:sd_to_ao_uart_pins { - mux { - groups = "uart_tx_ao_a", - "uart_rx_ao_a"; - function = "uart_ao_a"; - bias-pull-up; - input-enable; - }; - }; - - i2c_AO_pins:i2c_AO { - mux { - groups = "i2c_sck_ao", - "i2c_sda_ao"; - function = "i2c_ao"; - }; - }; - - ao_uart_pins:ao_uart { - mux { - groups = "uart_tx_ao_a", - "uart_rx_ao_a"; - function = "uart_ao_a"; - }; - }; - - ao_b_uart_pins:ao_b_uart { - mux { - groups = "uart_tx_ao_b_ao4", - "uart_rx_ao_b_ao5"; - function = "uart_ao_b"; - }; - }; - - hdmitx_aocec: ao_cec { - mux { - groups = "ao_cec"; - function = "ao_cec"; - }; - }; - - hdmitx_aocecb: ao_cecb { - mux { - groups = "ee_cec"; - function = "ee_cec"; - }; - }; -}; - -&pinctrl_periphs { - - pwm_a_z5_pins: pwm_a_z5 { - mux { - groups = "pwm_a_z"; - function = "pwm_a"; - }; - }; - - pwm_a_dv2_pins: pwm_a_dv2 { - mux { - groups = "pwm_a_dv"; - function = "pwm_a"; - }; - }; - - pwm_b_z6_pins: pwm_b_z6 { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - - pwm_b_dv3_pins: pwm_b_dv3 { - mux { - groups = "pwm_b_dv"; - function = "pwm_b"; - }; - }; - - pwm_c_z7_pins: pwm_c_z7 { - mux { - groups = "pwm_c"; - function = "pwm_c"; - }; - }; - - pwm_d_z4_pins: pwm_d_z4 { - mux { - groups = "pwm_d_z4"; - function = "pwm_d"; - }; - }; - - pwm_d_z19_pins: pwm_d_z19 { - mux { - groups = "pwm_d_z19"; - function = "pwm_d"; - }; - }; - - pwm_e_h4_pins: pwm_e_h4 { - mux { - groups = "pwm_e_h4"; - function = "pwm_e"; - }; - }; - - pwm_e_h8_pins: pwm_e_h8 { - mux { - groups = "pwm_e_h8"; - function = "pwm_e"; - }; - }; - - pwm_f_h9_pins: pwm_f_h9 { - mux { - groups = "pwm_f_h"; - function = "pwm_f"; - }; - }; - - pwm_f_clk_pins: pwm_f_clk { - mux { - groups = "pwm_f_clk"; - function = "pwm_f"; - }; - }; - - pwm_vs_dv2_pins: pwm_vs_dv2 { - mux { - groups = "pwm_vs_dv2"; - function = "pwm_vs"; - }; - }; - - pwm_vs_dv3_pins: pwm_vs_dv3 { - mux { - groups = "pwm_vs_dv3"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z4_pins: pwm_vs_z4 { - mux { - groups = "pwm_vs_z4"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z6_pins: pwm_vs_z6 { - mux { - groups = "pwm_vs_z6"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z7_pins: pwm_vs_z7 { - mux { - groups = "pwm_vs_z7"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z19_pins: pwm_vs_z19 { - mux { - groups = "pwm_vs_z19"; - function = "pwm_vs"; - }; - }; - - ao_to_sd_uart_clr_pins:ao_to_sd_uart_clr_pins { - mux { - groups = "sdcard_d2", - "sdcard_d3"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - sd_1bit_pins:sd_1bit_pins { - mux { - groups = "sdcard_d0", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - ao_to_sd_uart_pins:ao_to_sd_uart_pins { - mux { - groups = "uart_tx_ao_a_c4", - "uart_rx_ao_a_c5"; - function = "uart_ao_a_ee"; - bias-pull-up; - input-enable; - }; - }; - - emmc_clk_cmd_pins:emmc_clk_cmd_pins { - mux { - groups = "emmc_cmd", - "emmc_clk"; - function = "emmc"; - input-enable; - bias-pull-up; - }; - }; - - - emmc_conf_pull_up:emmc_conf_pull_up { - mux { - groups = "emmc_nand_d07", - "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - }; - }; - - emmc_conf_pull_done:emmc_conf_pull_done { - mux { - groups = "emmc_ds"; - function = "emmc"; - input-enable; - bias-pull-down; - }; - }; - - spifc_cs_pin:spifc_cs_pin { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_pulldown: spifc_pulldown { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - bias-pull-down; - }; - }; - - spifc_pullup: spifc_pullup { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_all_pins: spifc_all_pins { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - input-enable; - bias-pull-down; - }; - }; - - sd_clk_cmd_pins:sd_clk_cmd_pins{ - mux { - groups = "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - sd_all_pins:sd_all_pins{ - mux { - groups = "sdcard_d0", - "sdcard_d1", - "sdcard_d2", - "sdcard_d3", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - hdmirx_a_mux:hdmirx_a_mux { - mux { - groups = "hdmirx_hpd_a", "hdmirx_det_a", - "hdmirx_sda_a", "hdmirx_sck_a"; - function = "hdmirx_a"; - }; - }; - - hdmirx_b_mux:hdmirx_b_mux { - mux { - groups = "hdmirx_hpd_b", "hdmirx_det_b", - "hdmirx_sda_b", "hdmirx_sck_b"; - function = "hdmirx_b"; - }; - }; - - hdmirx_c_mux:hdmirx_c_mux { - mux { - groups = "hdmirx_hpd_c", "hdmirx_det_c", - "hdmirx_sda_c", "hdmirx_sck_c"; - function = "hdmirx_c"; - }; - }; - - hdmirx_d_mux:hdmirx_d_mux { - mux { - groups = "hdmirx_hpd_d", "hdmirx_det_d", - "hdmirx_sda_d", "hdmirx_sck_d"; - function = "hdmirx_d"; - }; - }; - - i2c0_z_pins:i2c0_z { - mux { - groups = "i2c0_sda", - "i2c0_sck"; - function = "i2c0"; - }; - }; - - i2c1_dv_pins:i2c1_z { - mux { - groups = "i2c1_sda", - "i2c1_sck"; - function = "i2c1"; - }; - }; - - i2c2_h_pins:i2c2_h { - mux { - groups = "i2c2_sda", - "i2c2_sck"; - function = "i2c2"; - }; - }; - - i2c3_z_pins:i2c3_z { - mux { - groups = "i2c3_sda", - "i2c3_sck"; - function = "i2c3"; - }; - }; - - a_uart_pins:a_uart { - mux { - groups = "uart_tx_a", - "uart_rx_a", - "uart_cts_a", - "uart_rts_a"; - function = "uart_a"; - }; - }; - - b_uart_pins:b_uart { - mux { - groups = "uart_tx_b", - "uart_rx_b"; - function = "uart_b"; - }; - }; - - c_uart_pins:c_uart { - mux { - groups = "uart_tx_c", - "uart_rx_c"; - function = "uart_c"; - }; - }; - - lcd_vbyone_pins: lcd_vbyone_pin { - mux { - groups = "vx1_lockn","vx1_htpdn"; - function = "vbyone"; - }; - }; - - atvdemod_agc_pins: atvdemod_agc_pins { - mux { - groups = "atv_if_agc"; - function = "atv"; - }; - }; - - dtvdemod_agc_pins: dtvdemod_agc_pins { - mux { - groups = "dtv_if_agc"; - function = "dtv"; - }; - }; - - spicc_pins: spicc { - mux { - groups = "spi_miso_a", - "spi_mosi_a", - "spi_clk_a"; - function = "spi_a"; - }; - }; -}; diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 6db6187ca2fa..2d22f28fdedc 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -134,19 +134,14 @@ arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index f81292dbc46e..3d7351c844aa 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h @@ -5,11 +5,7 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#define NR_IPI 8 -#else #define NR_IPI 7 -#endif typedef struct { unsigned int __softirq_pending; diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 0142b04a4a0f..2501bd0977e6 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -29,51 +29,4 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); (regs)->ARM_sp = current_stack_pointer; \ (regs)->ARM_cpsr = SVC_MODE; \ } - -#ifdef CONFIG_AMLOGIC_MODIFY - -extern void armv8pmu_handle_irq_ipi(void); - -struct amlpmu_fixup_cpuinfo { - int irq_num; - - int fix_done; - - unsigned long irq_cnt; - unsigned long empty_irq_cnt; - - unsigned long irq_time; - unsigned long empty_irq_time; - - unsigned long last_irq_cnt; - unsigned long last_empty_irq_cnt; - - unsigned long last_irq_time; - unsigned long last_empty_irq_time; -}; - -struct amlpmu_fixup_context { - struct amlpmu_fixup_cpuinfo __percpu *cpuinfo; - - /* struct arm_pmu */ - void *dev; - - /* sys_cpu_status0 reg */ - unsigned int *sys_cpu_status0; - - /* - * In main pmu irq route wait for other cpu fix done may cause lockup, - * when lockup we disable main irq for a while. - * relax_timer will enable main irq again. - */ - struct hrtimer relax_timer; - - /* dts prop */ - unsigned int sys_cpu_status0_offset; - unsigned int sys_cpu_status0_pmuirq_mask; - unsigned int relax_timer_ns; - unsigned int max_wait_cnt; -}; -#endif - #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index e811beb08e87..836efdda3d80 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -18,10 +18,6 @@ #ifdef CONFIG_CPU_V7 -#ifdef CONFIG_AMLOGIC_MODIFY -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#endif - #include #include #include @@ -32,19 +28,6 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - - /* * Common ARMv7 event types * @@ -963,160 +946,13 @@ static void armv7pmu_disable_event(struct perf_event *event) } #ifdef CONFIG_AMLOGIC_MODIFY -static struct amlpmu_fixup_context amlpmu_fixup_ctx; - -static enum hrtimer_restart amlpmu_relax_timer_func(struct hrtimer *timer) -{ - struct amlpmu_fixup_cpuinfo *ci; - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("enable cpu0_irq %d again, irq cnt = %lu\n", - ci->irq_num, - ci->irq_cnt); - enable_irq(ci->irq_num); - - return HRTIMER_NORESTART; -} - - -static void amlpmu_relax_timer_start(int other_cpu) -{ - struct amlpmu_fixup_cpuinfo *ci; - int cpu; - - cpu = smp_processor_id(); - WARN_ON(cpu != 0); - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("wait cpu %d fixup done timeout, main cpu irq cnt = %lu\n", - other_cpu, - ci->irq_cnt); - - if (hrtimer_active(&amlpmu_fixup_ctx.relax_timer)) { - pr_alert("relax_timer already active, return!\n"); - return; - } - - disable_irq_nosync(ci->irq_num); - - hrtimer_start(&amlpmu_fixup_ctx.relax_timer, - ns_to_ktime(amlpmu_fixup_ctx.relax_timer_ns), - HRTIMER_MODE_REL); -} +#include static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev); -void armv8pmu_handle_irq_ipi(void) +void amlpmu_handle_irq_ipi(void *arg) { - int cpu = smp_processor_id(); - - WARN_ON(cpu == 0); - WARN_ON(!amlpmu_fixup_ctx.dev); - - armv7pmu_handle_irq(-1, amlpmu_fixup_ctx.dev); -} - -static int aml_pmu_fix(void) -{ - int i; - int cpu; - int pmuirq_val; - struct amlpmu_fixup_cpuinfo *ci; - - int max_wait_cnt = amlpmu_fixup_ctx.max_wait_cnt; - - pmuirq_val = readl(amlpmu_fixup_ctx.sys_cpu_status0); - pmuirq_val &= amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask; - - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { - if (pmuirq_val & (1<fix_done = 0; - - /* aml pmu IPI will set fix_done to 1 */ - mb(); - - smp_send_aml_pmu(cpu); - - for (i = 0; i < max_wait_cnt; i++) { - if (READ_ONCE(ci->fix_done)) - break; - - udelay(1); - } - - if (i == amlpmu_fixup_ctx.max_wait_cnt) - amlpmu_relax_timer_start(cpu); - - return 0; - } - } - } - - return 1; -} - -static void aml_pmu_fix_stat_account(int is_empty_irq) -{ - int freq; - unsigned long time = jiffies; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - - ci->irq_cnt++; - ci->irq_time = time; - if (!ci->last_irq_cnt) { - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq) { - ci->empty_irq_cnt++; - ci->empty_irq_time = time; - if (!ci->last_empty_irq_cnt) { - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } - } - - if (time_after(ci->irq_time, ci->last_irq_time + HZ)) { - freq = ci->irq_cnt - ci->last_irq_cnt; - freq = freq * HZ / (ci->irq_time - ci->last_irq_time); - pr_debug("irq_cnt = %lu, irq_last_cnt = %lu, freq = %d\n", - ci->irq_cnt, - ci->last_irq_cnt, - freq); - - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq && - time_after(ci->empty_irq_time, ci->last_empty_irq_time + HZ)) { - - freq = ci->empty_irq_cnt - ci->last_empty_irq_cnt; - freq *= HZ; - freq /= (ci->empty_irq_time - ci->last_empty_irq_time); - pr_debug("empty_irq_cnt = %lu, freq = %d\n", - ci->empty_irq_cnt, - freq); - - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } + armv7pmu_handle_irq(-1, amlpmu_ctx.pmu); } #endif @@ -1129,47 +965,25 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) struct pt_regs *regs; int idx; -#ifdef CONFIG_AMLOGIC_MODIFY - int cpu; - int is_empty_irq = 0; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - ci->irq_num = irq_num; - amlpmu_fixup_ctx.dev = dev; - cpu = smp_processor_id(); -#endif - /* * Get and reset the IRQ flags */ pmnc = armv7_pmnc_getreset_flags(); #ifdef CONFIG_AMLOGIC_MODIFY - ci->fix_done = 1; -#endif - + /* amlpmu have routed the interrupt successfully, return IRQ_HANDLED */ + if (amlpmu_handle_irq(cpu_pmu, + irq_num, + armv7_pmnc_has_overflowed(pmnc))) + return IRQ_HANDLED; +#else /* * Did an overflow occur? */ -#ifdef CONFIG_AMLOGIC_MODIFY - if (!armv7_pmnc_has_overflowed(pmnc)) { - is_empty_irq = 1; - - if (cpu == 0) - is_empty_irq = aml_pmu_fix(); - } - - aml_pmu_fix_stat_account(is_empty_irq); - - /* txlx have some empty pmu irqs, so return IRQ_HANDLED */ - if (is_empty_irq) - return IRQ_HANDLED; -#else if (!armv7_pmnc_has_overflowed(pmnc)) return IRQ_NONE; - #endif + /* * Handle the counter(s) overflow(s) */ @@ -2224,88 +2038,8 @@ static const struct pmu_probe_info armv7_pmu_probe_table[] = { { /* sentinel value */ } }; -#ifdef CONFIG_AMLOGIC_MODIFY -static int amlpmu_fixup_init(struct platform_device *pdev) -{ - int ret; - void __iomem *base; - - amlpmu_fixup_ctx.cpuinfo = __alloc_percpu( - sizeof(struct amlpmu_fixup_cpuinfo), 2 * sizeof(void *)); - if (!amlpmu_fixup_ctx.cpuinfo) { - pr_err("alloc percpu failed\n"); - return -ENOMEM; - } - - base = of_iomap(pdev->dev.of_node, 0); - if (IS_ERR(base)) { - pr_err("of_iomap() failed, base = %p\n", base); - return PTR_ERR(base); - } - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_offset", - &amlpmu_fixup_ctx.sys_cpu_status0_offset); - if (ret) { - pr_err("read sys_cpu_status0_offset failed, ret = %d\n", ret); - return 1; - } - pr_debug("sys_cpu_status0_offset = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_offset); - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_pmuirq_mask", - &amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - if (ret) { - pr_err("read sys_cpu_status0_pmuirq_mask failed, ret = %d\n", - ret); - return 1; - } - pr_debug("sys_cpu_status0_pmuirq_mask = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - - - ret = of_property_read_u32(pdev->dev.of_node, - "relax_timer_ns", - &amlpmu_fixup_ctx.relax_timer_ns); - if (ret) { - pr_err("read prop relax_timer_ns failed, ret = %d\n", ret); - return 1; - } - pr_debug("relax_timer_ns = %u\n", amlpmu_fixup_ctx.relax_timer_ns); - - - ret = of_property_read_u32(pdev->dev.of_node, - "max_wait_cnt", - &amlpmu_fixup_ctx.max_wait_cnt); - if (ret) { - pr_err("read prop max_wait_cnt failed, ret = %d\n", ret); - return 1; - } - pr_debug("max_wait_cnt = %u\n", amlpmu_fixup_ctx.max_wait_cnt); - - - base += (amlpmu_fixup_ctx.sys_cpu_status0_offset << 2); - amlpmu_fixup_ctx.sys_cpu_status0 = base; - pr_debug("sys_cpu_status0 = %p\n", amlpmu_fixup_ctx.sys_cpu_status0); - - - hrtimer_init(&amlpmu_fixup_ctx.relax_timer, - CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - amlpmu_fixup_ctx.relax_timer.function = amlpmu_relax_timer_func; - - return 0; -} -#endif - static int armv7_pmu_device_probe(struct platform_device *pdev) { -#ifdef CONFIG_AMLOGIC_MODIFY - if (amlpmu_fixup_init(pdev)) - return 1; -#endif - return arm_pmu_device_probe(pdev, armv7_pmu_of_device_ids, armv7_pmu_probe_table); } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index a116c7e981bd..e41f7f67c995 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -51,10 +51,6 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#endif - #define CREATE_TRACE_POINTS #include @@ -79,9 +75,6 @@ enum ipi_msg_type { IPI_CPU_STOP, IPI_IRQ_WORK, IPI_COMPLETION, - #ifdef CONFIG_AMLOGIC_MODIFY - IPI_AML_PMU, - #endif IPI_CPU_BACKTRACE, /* * SGI8-15 can be reserved by secure firmware, and thus may @@ -525,9 +518,6 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { S(IPI_CPU_STOP, "CPU stop interrupts"), S(IPI_IRQ_WORK, "IRQ work interrupts"), S(IPI_COMPLETION, "completion interrupts"), -#ifdef CONFIG_AMLOGIC_MODIFY - S(IPI_AML_PMU, "AML pmu cross interrupts"), -#endif }; static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) @@ -536,13 +526,6 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) __smp_cross_call(target, ipinr); } -#ifdef CONFIG_AMLOGIC_MODIFY -void smp_send_aml_pmu(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_AML_PMU); -} -#endif - void show_ipi_list(struct seq_file *p, int prec) { unsigned int cpu, i; @@ -706,12 +689,6 @@ void handle_IPI(int ipinr, struct pt_regs *regs) printk_nmi_exit(); break; -#ifdef CONFIG_AMLOGIC_MODIFY - case IPI_AML_PMU: - armv8pmu_handle_irq_ipi(); - break; -#endif - default: pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index 14759a6ef0e3..f708ac673ddb 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -119,24 +119,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xff634400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; - gic: interrupt-controller@2c001000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 9d1b4bb7db53..8cc27c512b8c 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -155,21 +155,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xff634400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -1759,7 +1755,7 @@ max-duty-cycle = <1250>; /* Voltage Duty-Cycle */ voltage-table = <1022000 0>, - <1011000 3>, + <1011000 3>, <1001000 6>, <991000 10>, <981000 13>, diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index db8954b1bcda..8625f5c00df4 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -215,9 +215,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; + clusterb-enabled; + interrupts = , + ; + reg = <0x0 0xff634680 0x0 0x4>, + <0x0 0xff6347c0 0x0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 643a922dd599..5f5f4e97672a 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -119,21 +119,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xc8834400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xc8834400 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi index a66605342869..ef80ea74d5a3 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -133,12 +133,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xc8834400 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 22cbefdd4a4c..45c499073ac7 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -223,12 +223,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xc8834400 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm64/boot/dts/amlogic/mesontxl.dtsi b/arch/arm64/boot/dts/amlogic/mesontxl.dtsi deleted file mode 100644 index 10332dfbbe35..000000000000 --- a/arch/arm64/boot/dts/amlogic/mesontxl.dtsi +++ /dev/null @@ -1,1536 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/mesontxl.dtsi - * - * Copyright (C) 2018 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "mesongxbb-gpu-mali450.dtsi" -#include - -/ { - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - cpus:cpus { - #address-cells = <2>; - #size-cells = <0>; - #cooling-cells = <2>; - - cpu-map { - cluster0:cluster0 { - core0 { - cpu = <&CPU0>; - }; - core1 { - cpu = <&CPU1>; - }; - core2 { - cpu = <&CPU2>; - }; - core3 { - cpu = <&CPU3>; - }; - }; - }; - - CPU0:cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x0>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU1:cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x1>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU2:cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x2>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU3:cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x3>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - idle-states { - entry-method = "arm,psci"; -/* - CPU_SLEEP_0: cpu-sleep-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; - local-timer-stop; - entry-latency-us = <3000>; - exit-latency-us = <3000>; - min-residency-us = <8000>; - }; -*/ - - SYSTEM_SLEEP_0: system-sleep-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0020000>; - local-timer-stop; - entry-latency-us = <0x3fffffff>; - exit-latency-us = <0x40000000>; - min-residency-us = <0xffffffff>; - }; - - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - timer_bc: timer@c1109990 { - compatible = "arm, meson-bc-timer"; - reg = <0x0 0xc1109990 0x0 0x4 0x0 0xc1109994 0x0 0x4>; - timer_name = "Meson TimerF"; - clockevent-rating = <300>; - clockevent-shift = <20>; - clockevent-features = <0x23>; - interrupts = <0 60 1>; - bit_enable = <16>; - bit_mode = <12>; - bit_resolution = <0>; - }; - - pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = , - , - , - ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0x0 0xc4301000 0 0x1000>, - <0x0 0xc4302000 0 0x0100>; - interrupts = ; - }; - - clocks { - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; - }; - - cpu_iomap { - compatible = "amlogic, iomap"; - #address-cells=<2>; - #size-cells=<2>; - ranges; - io_cbus_base { - reg = <0x0 0xc1100000 0x0 0x100000>; - }; - io_apb_base { - reg = <0x0 0xd0000000 0x0 0x100000>; - }; - io_aobus_base { - reg = <0x0 0xc8100000 0x0 0x100000>; - }; - io_vapb_base { - reg = <0x0 0xd0100000 0x0 0x100000>; - }; - io_hiu_base { - reg = <0x0 0xc883c000 0x0 0x2000>; - }; - }; - - cpuinfo { - compatible = "amlogic, cpuinfo"; - cpuinfo_cmd = <0x82000044>; - }; - - ram-dump { - compatible = "amlogic, ram_dump"; - status = "okay"; - }; - - securitykey { - compatible = "amlogic, securitykey"; - status = "okay"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - - mailbox: mhu@c883c400 { - compatible = "amlogic, meson_mhu"; - reg = <0x0 0xc883c400 0x0 0x4c>, /* MHU registers */ - <0x0 0xc8013000 0x0 0x800>; /* Payload area */ - interrupts = <0 209 1>, /* low priority interrupt */ - <0 210 1>; /* high priority interrupt */ - #mbox-cells = <1>; - mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; - mboxes = <&mailbox 0 &mailbox 1>; - }; - - scpi_clocks { - compatible = "arm, scpi-clks"; - - scpi_dvfs: scpi_clocks@0 { - compatible = "arm, scpi-clk-indexed"; - #clock-cells = <1>; - clock-indices = <0>; - clock-output-names = "vcpu"; - }; - - }; - - pinctrl_aobus: pinctrl@c8100014{ - compatible = "amlogic,meson-txl-aobus-pinctrl"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio_ao: ao-bank@c8100014{ - reg = <0x0 0xc8100014 0x0 0x8>, - <0x0 0xc810002c 0x0 0x4>, - <0x0 0xc8100024 0x0 0x8>; - reg-names = "mux", "pull", "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - pinctrl_periphs: pinctrl@c88344b0{ - compatible = "amlogic,meson-txl-periphs-pinctrl"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio: banks@c88344b0{ - reg = <0x0 0xc88344b0 0x0 0x28>, - <0x0 0xc88344e8 0x0 0x14>, - <0x0 0xc8834520 0x0 0x14>, - <0x0 0xc8834430 0x0 0x40>; - reg-names = "mux", - "pull", - "pull-enable", - "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - dwc3: dwc3@c9000000 { - compatible = "synopsys, dwc3"; - status = "disable"; - reg = <0x0 0xc9000000 0x0 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy>, <&usb3_phy>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - }; - - usb2_phy: usb2phy@d0078000 { - compatible = "amlogic, amlogic-new-usb2"; - status = "disable"; - portnum = <4>; - reg = <0x0 0xd0078000 0x0 0x80 - 0x0 0xc1104408 0x0 0x4>; - }; - - usb3_phy: usb3phy@d0078080 { - compatible = "amlogic, amlogic-new-usb3"; - status = "disable"; - portnum = <0>; - reg = <0x0 0xd0078080 0x0 0x20>; - }; - - dwc2_a: dwc2_a@c9100000 { - compatible = "amlogic, dwc2"; - status = "disable"; - reg = <0x0 0xc9100000 0x0 0x40000>; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "gxl"; - phy-reg = <0xd0078000>; - phy-reg-size = <0xa0>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR - &clkc CLKID_USB1>; - clock-names = "usb_general", - "usb1", - "usb1_to_ddr"; - }; - - ethmac: ethernet@0xc9410000 { - compatible = "amlogic, gxbb-eth-dwmac"; - status = "disable"; - reg = <0x0 0xc9410000 0x0 0x10000 - 0x0 0xc8834540 0x0 0x8 - 0x0 0xc8834558 0x0 0xc - 0x0 0xc1104484 0x0 0x4>; - interrupts = <0 8 1 - 0 9 1>; - phy-mode= "rmii"; - mc_val_internal_phy = <0x1800>; - mc_val_external_phy = <0x1621>; - interrupt-names = "macirq", - "phyirq"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - internal_phy=<1>; - }; - - saradc: saradc { - compatible = "amlogic,meson-txl-saradc"; - status = "okay"; - #io-channel-cells = <1>; - clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; - clock-names = "xtal", "saradc_clk"; - interrupts = ; - reg = <0x0 0xc8100600 0x0 0x38>; - }; - - jtag { - compatible = "amlogic, jtag"; - status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_3 0 - &gpio_ao GPIOAO_4 0 - &gpio_ao GPIOAO_5 0 - &gpio_ao GPIOAO_7 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; - }; - - meson_suspend: pm { - compatible = "amlogic, pm"; - status = "okay"; - reg = <0x0 0xc81000a8 0x0 0x4>, - <0x0 0xc810023c 0x0 0x4>; - }; - - reboot { - compatible = "amlogic,reboot"; - sys_reset = <0x84000009>; - sys_poweroff = <0x84000008>; - }; - - rtc { - compatible = "amlogic, aml_vrtc"; - alarm_reg_addr = <0xc81000a8>; - timer_e_addr = <0xc1109988>; - init_date = "2018/01/01"; - status = "okay"; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - cbus: bus@c1100000 { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - reg = <0x0 0xc1100000 0x0 0x100000>; - ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>; - - meson_clk_msr@875c{ - compatible = "amlogic, gxl_measure"; - reg = <0x0 0x875c 0x0 0x4 - 0x0 0x8764 0x0 0x4>; - }; - - /*i2c-A*/ - i2c0: i2c@8500 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0 0x8500 0x0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-B*/ - i2c1: i2c@87c0 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0 0x87c0 0x0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-C*/ - i2c2: i2c@87e0 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0 0x87e0 0x0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-D*/ - i2c3: i2c@8d20 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0 0x8d20 0x0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_ab: pwm@8550 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x0 0x8550 0x0 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_cd: pwm@8640 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x0 0x8640 0x0 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_ef: pwm@86c0 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x0 0x86c0 0x0 0x1c>; - #pwm-cells = <3>; - status = "disabled"; - }; - - spicc: spi@8d80 { - compatible = "amlogic,meson-txl-spicc", - "amlogic,meson-txlx-spicc"; - reg = <0x0 0x8d80 0x0 0x3c>; - interrupts = ; - clocks = <&clkc CLKID_SPICC0>; - clock-names = "core"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - uart_A: serial@84c0 { - compatible = "amlogic, meson-uart"; - reg = <0x0 0x84c0 0x0 0x18>; - interrupts = <0 26 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART0>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 128 >; - pinctrl-names = "default"; - pinctrl-0 = <&a_uart_pins>; - }; - - uart_B: serial@84dc { - compatible = "amlogic, meson-uart"; - reg = <0x0 0x84dc 0x0 0x18>; - interrupts = <0 75 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART1>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&b_uart_pins>; - }; - - uart_C: serial@8700 { - compatible = "amlogic, meson-uart"; - reg = <0x0 0x8700 0x0 0x18>; - interrupts = <0 93 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART2>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&c_uart_pins>; - }; - - gpio_intc: interrupt-controller@9880 { - compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-txl-gpio-intc"; - reg = <0x0 0x9880 0x0 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = - <64 65 66 67 68 69 70 71>; - status = "okay"; - }; - - wdt_ee: watchdog@98d0 { - compatible = "amlogic, meson-wdt"; - status = "okay"; - default_timeout=<10>; - reset_watchdog_method=<1>;/*0:sysfs,1:kernel*/ - reset_watchdog_time=<2>; - shutdown_timeout=<10>; - firmware_timeout=<6>; - suspend_timeout=<6>; - reg = <0x0 0x98d0 0x0 0x10>; - clock-names = "xtal"; - clocks = <&xtal>; - }; - - }; /* end of cbus */ - - aobus: bus@c8100000 { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - reg = <0x0 0xc8100000 0x0 0x100000>; - ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>; - - cpu_version { - reg=<0x0 0x220 0x0 0x4>; - }; - - aoclkc: clock-controller@0 { - compatible = "amlogic,txl-aoclkc"; - #clock-cells = <1>; - reg = <0x0 0x0 0x0 0x1000>; - }; - - uart_AO: serial@4c0 { - compatible = "amlogic, meson-uart"; - reg = <0x0 0x4c0 0x0 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <1>; - fifosize = < 64 >; - pinctrl-names = "default"; - /*pinctrl-0 = <&ao_uart_pins>;*/ - /* 0 not support;1 support */ - support-sysrq = <0>; - }; - - uart_AO_B: serial@04e0 { - compatible = "amlogic, meson-uart"; - reg = <0x0 0x04e0 0x0 0x18>; - interrupts = <0 197 1>; - status = "disabled"; - clocks = <&xtal>; - clock-names = "clk_uart"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_b_uart_pins>; - }; - - i2c_AO: i2c@0500 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0 0x0500 0x0 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_aoab: pwm@0550 { - compatible = "amlogic,txl-ao-pwm"; - reg = <0x0 0x0550 0x0 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - remote:rc@0580 { - compatible = "amlogic, aml_remote"; - dev_name = "meson-remote"; - reg = <0x0 0x0580 0x00 0x44>, - <0x0 0x0480 0x00 0x20>; - status = "okay"; - protocol = ; - interrupts = <0 196 1>; - pinctrl-names = "default"; - pinctrl-0 = <&remote_pins>; - map = <&custom_maps>; - max_frame_time = <200>; - }; - }; /* end of aobus*/ - - periphs: periphs@c8834000 { - compatible = "simple-bus"; - reg = <0x0 0xc8834000 0x0 0x2000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>; - - rng { - compatible = "amlogic,meson-rng"; - reg = <0x0 0x0 0x0 0x4>; - quality = /bits/ 16 <1000>; - }; - };/* end of periphs */ - - hiubus: bus@c883c000 { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - reg = <0x0 0xc883c000 0x0 0x2000>; - ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>; - - clkc: clock-controller@0 { - compatible = "amlogic,txl-clkc"; - #clock-cells = <1>; - reg = <0x0 0x0 0x0 0x3fc>; - }; - };/* end of hiubus*/ - - }; /* end of soc*/ - - custom_maps: custom_maps { - mapnum = <3>; - map0 = <&map_0>; - map1 = <&map_1>; - map2 = <&map_2>; - map_0: map_0{ - mapname = "amlogic-remote-1"; - customcode = <0xfb04>; - release_delay = <80>; - size = <44>; /*keymap size*/ - keymap = ; - }; - - map_1: map_1{ - mapname = "amlogic-remote-2"; - customcode = <0xfe01>; - release_delay = <80>; - size = <53>; - keymap = ; - }; - - map_2: map_2{ - mapname = "amlogic-remote-3"; - customcode = <0xbd02>; - release_delay = <80>; - size = <17>; - keymap = ; - }; - }; - - aocec: aocec@0xc8100000 { - compatible = "amlogic, aocec-txl"; - status = "okay"; - vendor_name = "Amlogic"; /* Max Chars: 8 */ - /* Refer to the following URL at: - * http://standards.ieee.org/develop/regauth/oui/oui.txt - */ - vendor_id = <0x000000>; - product_desc = "TXL"; /* Max Chars: 16 */ - cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <3>; - ee_cec; - arc_port_mask = <0x2>; - interrupts = <0 56 1 - 0 199 1>; - interrupt-names = "hdmi_aocecb","hdmi_aocec"; - pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocec>; - reg = <0x0 0xc810023c 0x0 0x4 - 0x0 0xc8100000 0x0 0x200 - 0x0 0xda83e000 0x0 0x10 - 0x0 0xc883c000 0x0 0x400>; - reg-names = "ao_exit","ao","hdmirx","hhi"; - }; - - canvas: canvas{ - compatible = "amlogic, meson, canvas"; - dev_name = "amlogic-canvas"; - status = "okay"; - reg = <0x0 0xc8838000 0x0 0x2000>; - }; - - codec_io: codec_io { - compatible = "amlogic, codec_io"; - status = "okay"; - #address-cells=<2>; - #size-cells=<2>; - ranges; - io_cbus_base{ - reg = <0x0 0xC1100000 0x0 0x100000>; - }; - io_dos_base{ - reg = <0x0 0xc8820000 0x0 0x10000>; - }; - io_hiubus_base{ - reg = <0x0 0xc883c000 0x0 0x2000>; - }; - io_aobus_base{ - reg = <0x0 0xc8100000 0x0 0x100000>; - }; - io_vcbus_base{ - reg = <0x0 0xd0100000 0x0 0x40000>; - }; - io_dmc_base{ - reg = <0x0 0xc8838000 0x0 0x400>; - }; - }; - - vpu { - compatible = "amlogic, vpu-txl"; - dev_name = "vpu"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <7>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ - }; - - ge2d { - compatible = "amlogic, ge2d-txl"; - status = "okay"; - interrupts = <0 146 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0x0 0xd0160000 0x0 0x10000>; - }; - - meson-amvideom { - compatible = "amlogic, amvideom"; - status = "okay"; - interrupts = <0 3 1>; - interrupt-names = "vsync"; - }; - - mesonstream { - compatible = "amlogic, codec, streambuf"; - status = "okay"; - clocks = <&clkc CLKID_DOS_PARSER - &clkc CLKID_DEMUX - &clkc CLKID_DOS - &clkc CLKID_CLK81 - &clkc CLKID_VDEC_MUX - &clkc CLKID_HCODEC_MUX - &clkc CLKID_HEVC_MUX>; - clock-names = "parser_top", - "demux", - "vdec", - "clk_81", - "clk_vdec_mux", - "clk_hcodec_mux", - "clk_hevc_mux"; - }; - - codec_mm { - compatible = "amlogic, codec, mm"; - status = "okay"; - memory-region = <&codec_mm_cma &codec_mm_reserved>; - }; - - vdec { - compatible = "amlogic, vdec"; - status = "okay"; - interrupts = <0 3 1 - 0 23 1 - 0 32 1 - 0 43 1 - 0 44 1 - 0 45 1>; - interrupt-names = "vsync", - "demux", - "parser", - "mailbox_0", - "mailbox_1", - "mailbox_2"; - }; - - amvenc_avc { - compatible = "amlogic, amvenc_avc"; - status = "okay"; - //memory-region = <&amvenc_avc_reserved>; - //memory-region = <&avc_cma_reserved>; - interrupts = <0 45 1>; - interrupt-names = "mailbox_2"; - }; - - rdma { - compatible = "amlogic, meson, rdma"; - dev_name = "amlogic-rdma"; - status = "okay"; - interrupts = <0 89 1>; - interrupt-names = "rdma"; - }; - - audio_data: audio_data { - compatible = "amlogic, audio_data"; - query_licence_cmd = <0x82000050>; - status = "disabled"; - }; - - efuse: efuse { - compatible = "amlogic, efuse"; - read_cmd = <0x82000030>; - write_cmd = <0x82000031>; - get_max_cmd = <0x82000033>; - key = <&efusekey>; - clocks = <&clkc CLKID_EFUSE>; - clock-names = "efuse_clk"; - status = "disabled"; - }; - - efusekey:efusekey { - keynum = <4>; - key0 = <&key_0>; - key1 = <&key_1>; - key2 = <&key_2>; - key3 = <&key_3>; - key_0:key_0 { - keyname = "mac"; - offset = <0>; - size = <6>; - }; - key_1:key_1 { - keyname = "mac_bt"; - offset = <6>; - size = <6>; - }; - key_2:key_2 { - keyname = "mac_wifi"; - offset = <12>; - size = <6>; - }; - key_3:key_3 { - keyname = "usid"; - offset = <18>; - size = <16>; - }; - }; - - cpu_ver_name { - compatible = "amlogic, cpu-major-id-txl"; - status = "okay"; - }; - - ddr_bandwidth { - compatible = "amlogic, ddr-bandwidth"; - status = "okay"; - reg = <0x0 0xc8838000 0x0 0x100 - 0x0 0xc8837000 0x0 0x100>; - interrupts = <0 52 1>; - interrupt-names = "ddr_bandwidth"; - }; - dmc_monitor { - compatible = "amlogic, dmc_monitor"; - status = "okay"; - reg_base = <0xda838400>; - interrupts = <0 51 1>; - }; - - vdac { - compatible = "amlogic, vdac-txl"; - status = "okay"; - }; -}; /* end of / */ - -&gpu{ - /*gpu max freq is 750M*/ - tbl = <&clk285_cfg &clk400_cfg &clk500_cfg &clk666_cfg &clk750_cfg>; -}; - -&pinctrl_aobus { - - pwm_ao_a_ao3_pins: pwm_ao_a_ao3 { - mux { - groups = "pwm_ao_a_ao3"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_a_ao7_pins: pwm_ao_a_ao7 { - mux { - groups = "pwm_ao_a_ao7"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_b_ao8_pins: pwm_ao_b_ao8 { - mux { - groups = "pwm_ao_b_ao8"; - function = "pwm_ao_b"; - }; - }; - - pwm_ao_b_ao9_pins: pwm_ao_b_ao9 { - mux { - groups = "pwm_ao_b_ao9"; - function = "pwm_ao_b"; - }; - }; - - remote_pins:remote_pin { - mux { - groups = "remote_in"; - function = "ir_in"; - }; - - }; - - sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { - mux { - groups = "GPIOAO_0", - "GPIOAO_1"; - function = "gpio_aobus"; - }; - }; - - sd_to_ao_uart_pins:sd_to_ao_uart_pins { - mux { - groups = "uart_tx_ao_a", - "uart_rx_ao_a"; - function = "uart_ao_a"; - bias-pull-up; - input-enable; - }; - }; - - i2c_AO_pins:i2c_AO { - mux { - groups = "i2c_sck_ao", - "i2c_sda_ao"; - function = "i2c_ao"; - }; - }; - - ao_uart_pins:ao_uart { - mux { - groups = "uart_tx_ao_a", - "uart_rx_ao_a"; - function = "uart_ao_a"; - }; - }; - - ao_b_uart_pins:ao_b_uart { - mux { - groups = "uart_tx_ao_b_ao4", - "uart_rx_ao_b_ao5"; - function = "uart_ao_b"; - }; - }; - - hdmitx_aocec: ao_cec { - mux { - groups = "ao_cec"; - function = "ao_cec"; - }; - }; - - hdmitx_aocecb: ao_cecb { - mux { - groups = "ee_cec"; - function = "ee_cec"; - }; - }; -}; - -&pinctrl_periphs { - - pwm_a_z5_pins: pwm_a_z5 { - mux { - groups = "pwm_a_z"; - function = "pwm_a"; - }; - }; - - pwm_a_dv2_pins: pwm_a_dv2 { - mux { - groups = "pwm_a_dv"; - function = "pwm_a"; - }; - }; - - pwm_b_z6_pins: pwm_b_z6 { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - - pwm_b_dv3_pins: pwm_b_dv3 { - mux { - groups = "pwm_b_dv"; - function = "pwm_b"; - }; - }; - - pwm_c_z7_pins: pwm_c_z7 { - mux { - groups = "pwm_c"; - function = "pwm_c"; - }; - }; - - pwm_d_z4_pins: pwm_d_z4 { - mux { - groups = "pwm_d_z4"; - function = "pwm_d"; - }; - }; - - pwm_d_z19_pins: pwm_d_z19 { - mux { - groups = "pwm_d_z19"; - function = "pwm_d"; - }; - }; - - pwm_e_h4_pins: pwm_e_h4 { - mux { - groups = "pwm_e_h4"; - function = "pwm_e"; - }; - }; - - pwm_e_h8_pins: pwm_e_h8 { - mux { - groups = "pwm_e_h8"; - function = "pwm_e"; - }; - }; - - pwm_f_h9_pins: pwm_f_h9 { - mux { - groups = "pwm_f_h"; - function = "pwm_f"; - }; - }; - - pwm_f_clk_pins: pwm_f_clk { - mux { - groups = "pwm_f_clk"; - function = "pwm_f"; - }; - }; - - pwm_vs_dv2_pins: pwm_vs_dv2 { - mux { - groups = "pwm_vs_dv2"; - function = "pwm_vs"; - }; - }; - - pwm_vs_dv3_pins: pwm_vs_dv3 { - mux { - groups = "pwm_vs_dv3"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z4_pins: pwm_vs_z4 { - mux { - groups = "pwm_vs_z4"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z6_pins: pwm_vs_z6 { - mux { - groups = "pwm_vs_z6"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z7_pins: pwm_vs_z7 { - mux { - groups = "pwm_vs_z7"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z19_pins: pwm_vs_z19 { - mux { - groups = "pwm_vs_z19"; - function = "pwm_vs"; - }; - }; - - ao_to_sd_uart_clr_pins:ao_to_sd_uart_clr_pins { - mux { - groups = "sdcard_d2", - "sdcard_d3"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - sd_1bit_pins:sd_1bit_pins { - mux { - groups = "sdcard_d0", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - ao_to_sd_uart_pins:ao_to_sd_uart_pins { - mux { - groups = "uart_tx_ao_a_c4", - "uart_rx_ao_a_c5"; - function = "uart_ao_a_ee"; - bias-pull-up; - input-enable; - }; - }; - - emmc_clk_cmd_pins:emmc_clk_cmd_pins { - mux { - groups = "emmc_cmd", - "emmc_clk"; - function = "emmc"; - input-enable; - bias-pull-up; - }; - }; - - - emmc_conf_pull_up:emmc_conf_pull_up { - mux { - groups = "emmc_nand_d07", - "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - }; - }; - - emmc_conf_pull_done:emmc_conf_pull_done { - mux { - groups = "emmc_ds"; - function = "emmc"; - input-enable; - bias-pull-down; - }; - }; - - spifc_cs_pin:spifc_cs_pin { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_pulldown: spifc_pulldown { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - bias-pull-down; - }; - }; - - spifc_pullup: spifc_pullup { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_all_pins: spifc_all_pins { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - input-enable; - bias-pull-down; - }; - }; - - sd_clk_cmd_pins:sd_clk_cmd_pins{ - mux { - groups = "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - sd_all_pins:sd_all_pins{ - mux { - groups = "sdcard_d0", - "sdcard_d1", - "sdcard_d2", - "sdcard_d3", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - hdmirx_a_mux:hdmirx_a_mux { - mux { - groups = "hdmirx_hpd_a", "hdmirx_det_a", - "hdmirx_sda_a", "hdmirx_sck_a"; - function = "hdmirx_a"; - }; - }; - - hdmirx_b_mux:hdmirx_b_mux { - mux { - groups = "hdmirx_hpd_b", "hdmirx_det_b", - "hdmirx_sda_b", "hdmirx_sck_b"; - function = "hdmirx_b"; - }; - }; - - hdmirx_c_mux:hdmirx_c_mux { - mux { - groups = "hdmirx_hpd_c", "hdmirx_det_c", - "hdmirx_sda_c", "hdmirx_sck_c"; - function = "hdmirx_c"; - }; - }; - - hdmirx_d_mux:hdmirx_d_mux { - mux { - groups = "hdmirx_hpd_d", "hdmirx_det_d", - "hdmirx_sda_d", "hdmirx_sck_d"; - function = "hdmirx_d"; - }; - }; - - i2c0_z_pins:i2c0_z { - mux { - groups = "i2c0_sda", - "i2c0_sck"; - function = "i2c0"; - }; - }; - - i2c1_dv_pins:i2c1_z { - mux { - groups = "i2c1_sda", - "i2c1_sck"; - function = "i2c1"; - }; - }; - - i2c2_h_pins:i2c2_h { - mux { - groups = "i2c2_sda", - "i2c2_sck"; - function = "i2c2"; - }; - }; - - i2c3_z_pins:i2c3_z { - mux { - groups = "i2c3_sda", - "i2c3_sck"; - function = "i2c3"; - }; - }; - - a_uart_pins:a_uart { - mux { - groups = "uart_tx_a", - "uart_rx_a", - "uart_cts_a", - "uart_rts_a"; - function = "uart_a"; - }; - }; - - b_uart_pins:b_uart { - mux { - groups = "uart_tx_b", - "uart_rx_b"; - function = "uart_b"; - }; - }; - - c_uart_pins:c_uart { - mux { - groups = "uart_tx_c", - "uart_rx_c"; - function = "uart_c"; - }; - }; - - lcd_vbyone_pins: lcd_vbyone_pin { - mux { - groups = "vx1_lockn","vx1_htpdn"; - function = "vbyone"; - }; - }; - - atvdemod_agc_pins: atvdemod_agc_pins { - mux { - groups = "atv_if_agc"; - function = "atv"; - }; - }; - - dtvdemod_agc_pins: dtvdemod_agc_pins { - mux { - groups = "dtv_if_agc"; - function = "dtv"; - }; - }; - - spicc_pins: spicc { - mux { - groups = "spi_miso_a", - "spi_mosi_a", - "spi_clk_a"; - function = "spi_a"; - }; - }; -}; diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 11424d09e16d..ff12477ed816 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -134,19 +134,14 @@ arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xff634400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h index 9745a1d52418..8740297dac77 100644 --- a/arch/arm64/include/asm/hardirq.h +++ b/arch/arm64/include/asm/hardirq.h @@ -20,11 +20,7 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#define NR_IPI 7 -#else #define NR_IPI 6 -#endif typedef struct { unsigned int __softirq_pending; diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index 11185b42b060..b963c3bbd437 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -92,50 +92,6 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); } -#ifdef CONFIG_AMLOGIC_MODIFY -extern void armv8pmu_handle_irq_ipi(void); - -struct amlpmu_fixup_cpuinfo { - int irq_num; - - int fix_done; - - unsigned long irq_cnt; - unsigned long empty_irq_cnt; - - unsigned long irq_time; - unsigned long empty_irq_time; - - unsigned long last_irq_cnt; - unsigned long last_empty_irq_cnt; - - unsigned long last_irq_time; - unsigned long last_empty_irq_time; -}; - -struct amlpmu_fixup_context { - struct amlpmu_fixup_cpuinfo __percpu *cpuinfo; - - /* struct arm_pmu */ - void *dev; - - /* sys_cpu_status0 reg */ - unsigned int *sys_cpu_status0; - - /* - * In main pmu irq route wait for other cpu fix done may cause lockup, - * when lockup we disable main irq for a while. - * relax_timer will enable main irq again. - */ - struct hrtimer relax_timer; - - /* dts prop */ - unsigned int sys_cpu_status0_offset; - unsigned int sys_cpu_status0_pmuirq_mask; - unsigned int relax_timer_ns; - unsigned int max_wait_cnt; -}; -#endif #endif diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 30ba8cf00977..9c49326793ef 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -19,10 +19,6 @@ * along with this program. If not, see . */ -#ifdef CONFIG_AMLOGIC_MODIFY -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#endif - #include #include #include @@ -34,18 +30,6 @@ #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - /* * ARMv8 PMUv3 Performance Events handling code. * Common event types (some are defined in asm/perf_event.h). @@ -766,161 +750,13 @@ static void armv8pmu_disable_event(struct perf_event *event) } #ifdef CONFIG_AMLOGIC_MODIFY - -static struct amlpmu_fixup_context amlpmu_fixup_ctx; - -static enum hrtimer_restart amlpmu_relax_timer_func(struct hrtimer *timer) -{ - struct amlpmu_fixup_cpuinfo *ci; - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("enable cpu0_irq %d again, irq cnt = %lu\n", - ci->irq_num, - ci->irq_cnt); - enable_irq(ci->irq_num); - - return HRTIMER_NORESTART; -} - - -static void amlpmu_relax_timer_start(int other_cpu) -{ - struct amlpmu_fixup_cpuinfo *ci; - int cpu; - - cpu = smp_processor_id(); - WARN_ON(cpu != 0); - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("wait cpu %d fixup done timeout, main cpu irq cnt = %lu\n", - other_cpu, - ci->irq_cnt); - - if (hrtimer_active(&amlpmu_fixup_ctx.relax_timer)) { - pr_alert("relax_timer already active, return!\n"); - return; - } - - disable_irq_nosync(ci->irq_num); - - hrtimer_start(&amlpmu_fixup_ctx.relax_timer, - ns_to_ktime(amlpmu_fixup_ctx.relax_timer_ns), - HRTIMER_MODE_REL); -} +#include static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev); -void armv8pmu_handle_irq_ipi(void) +void amlpmu_handle_irq_ipi(void *arg) { - int cpu = smp_processor_id(); - - WARN_ON(cpu == 0); - WARN_ON(!amlpmu_fixup_ctx.dev); - - armv8pmu_handle_irq(-1, amlpmu_fixup_ctx.dev); -} - -static int aml_pmu_fix(void) -{ - int i; - int cpu; - int pmuirq_val; - struct amlpmu_fixup_cpuinfo *ci; - - int max_wait_cnt = amlpmu_fixup_ctx.max_wait_cnt; - - pmuirq_val = readl(amlpmu_fixup_ctx.sys_cpu_status0); - pmuirq_val &= amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask; - - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { - if (pmuirq_val & (1<fix_done = 0; - - /* aml pmu IPI will set fix_done to 1 */ - mb(); - - smp_send_aml_pmu(cpu); - - for (i = 0; i < max_wait_cnt; i++) { - if (READ_ONCE(ci->fix_done)) - break; - - udelay(1); - } - - if (i == amlpmu_fixup_ctx.max_wait_cnt) - amlpmu_relax_timer_start(cpu); - - return 0; - } - } - } - - return 1; -} - -static void aml_pmu_fix_stat_account(int is_empty_irq) -{ - int freq; - unsigned long time = jiffies; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - - ci->irq_cnt++; - ci->irq_time = time; - if (!ci->last_irq_cnt) { - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq) { - ci->empty_irq_cnt++; - ci->empty_irq_time = time; - if (!ci->last_empty_irq_cnt) { - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } - } - - if (time_after(ci->irq_time, ci->last_irq_time + HZ)) { - freq = ci->irq_cnt - ci->last_irq_cnt; - freq = freq * HZ / (ci->irq_time - ci->last_irq_time); - pr_debug("irq_cnt = %lu, irq_last_cnt = %lu, freq = %d\n", - ci->irq_cnt, - ci->last_irq_cnt, - freq); - - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq && - time_after(ci->empty_irq_time, ci->last_empty_irq_time + HZ)) { - - freq = ci->empty_irq_cnt - ci->last_empty_irq_cnt; - freq *= HZ; - freq /= (ci->empty_irq_time - ci->last_empty_irq_time); - pr_debug("empty_irq_cnt = %lu, freq = %d\n", - ci->empty_irq_cnt, - freq); - - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } + armv8pmu_handle_irq(-1, amlpmu_ctx.pmu); } #endif @@ -933,42 +769,21 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) struct pt_regs *regs; int idx; -#ifdef CONFIG_AMLOGIC_MODIFY - int cpu; - int is_empty_irq = 0; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - ci->irq_num = irq_num; - amlpmu_fixup_ctx.dev = dev; - cpu = smp_processor_id(); -#endif - /* * Get and reset the IRQ flags */ pmovsr = armv8pmu_getreset_flags(); #ifdef CONFIG_AMLOGIC_MODIFY - ci->fix_done = 1; -#endif + /* amlpmu have routed the interrupt already, so return IRQ_HANDLED */ + if (amlpmu_handle_irq(cpu_pmu, + irq_num, + armv8pmu_has_overflowed(pmovsr))) + return IRQ_HANDLED; +#else /* * Did an overflow occur? */ -#ifdef CONFIG_AMLOGIC_MODIFY - if (!armv8pmu_has_overflowed(pmovsr)) { - is_empty_irq = 1; - - if (cpu == 0) - is_empty_irq = aml_pmu_fix(); - } - - aml_pmu_fix_stat_account(is_empty_irq); - - /* txlx have some empty pmu irqs, so return IRQ_HANDLED */ - if (is_empty_irq) - return IRQ_HANDLED; -#else if (!armv8pmu_has_overflowed(pmovsr)) return IRQ_NONE; #endif @@ -1014,9 +829,6 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) return IRQ_HANDLED; } - - - static void armv8pmu_start(struct arm_pmu *cpu_pmu) { unsigned long flags; @@ -1308,87 +1120,8 @@ static const struct pmu_probe_info armv8_pmu_probe_table[] = { }; -#ifdef CONFIG_AMLOGIC_MODIFY -static int amlpmu_fixup_init(struct platform_device *pdev) -{ - int ret; - void __iomem *base; - - amlpmu_fixup_ctx.cpuinfo = __alloc_percpu( - sizeof(struct amlpmu_fixup_cpuinfo), 2 * sizeof(void *)); - if (!amlpmu_fixup_ctx.cpuinfo) { - pr_err("alloc percpu failed\n"); - return -ENOMEM; - } - - base = of_iomap(pdev->dev.of_node, 0); - if (IS_ERR(base)) { - pr_err("of_iomap() failed, base = %p\n", base); - return PTR_ERR(base); - } - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_offset", - &amlpmu_fixup_ctx.sys_cpu_status0_offset); - if (ret) { - pr_err("read sys_cpu_status0_offset failed, ret = %d\n", ret); - return 1; - } - pr_debug("sys_cpu_status0_offset = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_offset); - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_pmuirq_mask", - &amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - if (ret) { - pr_err("read sys_cpu_status0_pmuirq_mask failed, ret = %d\n", - ret); - return 1; - } - pr_debug("sys_cpu_status0_pmuirq_mask = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - - - ret = of_property_read_u32(pdev->dev.of_node, - "relax_timer_ns", - &amlpmu_fixup_ctx.relax_timer_ns); - if (ret) { - pr_err("read prop relax_timer_ns failed, ret = %d\n", ret); - return 1; - } - pr_debug("relax_timer_ns = %u\n", amlpmu_fixup_ctx.relax_timer_ns); - - - ret = of_property_read_u32(pdev->dev.of_node, - "max_wait_cnt", - &amlpmu_fixup_ctx.max_wait_cnt); - if (ret) { - pr_err("read prop max_wait_cnt failed, ret = %d\n", ret); - return 1; - } - pr_debug("max_wait_cnt = %u\n", amlpmu_fixup_ctx.max_wait_cnt); - - - base += (amlpmu_fixup_ctx.sys_cpu_status0_offset << 2); - amlpmu_fixup_ctx.sys_cpu_status0 = base; - pr_debug("sys_cpu_status0 = %p\n", amlpmu_fixup_ctx.sys_cpu_status0); - - - hrtimer_init(&amlpmu_fixup_ctx.relax_timer, - CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - amlpmu_fixup_ctx.relax_timer.function = amlpmu_relax_timer_func; - - return 0; -} -#endif - static int armv8_pmu_device_probe(struct platform_device *pdev) { -#ifdef CONFIG_AMLOGIC_MODIFY - if (amlpmu_fixup_init(pdev)) - return 1; -#endif if (acpi_disabled) return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids, NULL); diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index f30ec481fa7a..9edc7228a870 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -55,10 +55,6 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#endif - #ifdef CONFIG_AMLOGIC_VMAP #include #endif @@ -84,12 +80,7 @@ enum ipi_msg_type { IPI_CPU_STOP, IPI_TIMER, IPI_IRQ_WORK, -#ifdef CONFIG_AMLOGIC_MODIFY - IPI_WAKEUP, - IPI_AML_PMU -#else IPI_WAKEUP -#endif }; #ifdef CONFIG_ARM64_VHE @@ -775,9 +766,6 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { S(IPI_TIMER, "Timer broadcast interrupts"), S(IPI_IRQ_WORK, "IRQ work interrupts"), S(IPI_WAKEUP, "CPU wake-up interrupts"), -#ifdef CONFIG_AMLOGIC_MODIFY - S(IPI_AML_PMU, "AML pmu cross interrupts"), -#endif }; static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) @@ -786,13 +774,6 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) __smp_cross_call(target, ipinr); } -#ifdef CONFIG_AMLOGIC_MODIFY -void smp_send_aml_pmu(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_AML_PMU); -} -#endif - void show_ipi_list(struct seq_file *p, int prec) { unsigned int cpu, i; @@ -911,12 +892,6 @@ void handle_IPI(int ipinr, struct pt_regs *regs) break; #endif -#ifdef CONFIG_AMLOGIC_MODIFY - case IPI_AML_PMU: - armv8pmu_handle_irq_ipi(); - break; -#endif - default: pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); break; diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index f51759da76f2..9fd30396ea45 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -1013,6 +1013,517 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu) return 0; } + +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#include + +struct amlpmu_context amlpmu_ctx; + +static enum hrtimer_restart amlpmu_relax_timer_func(struct hrtimer *timer) +{ + struct amlpmu_context *ctx = &amlpmu_ctx; + struct amlpmu_cpuinfo *ci; + + ci = per_cpu_ptr(ctx->cpuinfo, 0); + + pr_info("enable cpu0_irq %d again, irq cnt = %lu\n", + ci->irq_num, + ci->valid_irq_cnt); + enable_irq(ci->irq_num); + + return HRTIMER_NORESTART; +} + +void amlpmu_relax_timer_start(int other_cpu) +{ + struct amlpmu_cpuinfo *ci; + int cpu; + struct amlpmu_context *ctx = &amlpmu_ctx; + + cpu = smp_processor_id(); + WARN_ON(cpu != 0); + + ci = per_cpu_ptr(ctx->cpuinfo, 0); + + pr_warn("wait cpu %d fixup done timeout, main cpu irq cnt = %lu\n", + other_cpu, + ci->valid_irq_cnt); + + if (hrtimer_active(&ctx->relax_timer)) { + pr_alert("relax_timer already active, return!\n"); + return; + } + + disable_irq_nosync(ci->irq_num); + + hrtimer_start(&ctx->relax_timer, + ns_to_ktime(ctx->relax_timer_ns), + HRTIMER_MODE_REL); +} + +static void amlpmu_fix_setup_affinity(int irq) +{ + int cluster_index = 0; + int cpu; + int affinity_cpu = -1; + struct amlpmu_cpuinfo *ci = NULL; + struct amlpmu_context *ctx = &amlpmu_ctx; + s64 latest_next_stamp = S64_MAX; + + if (irq == ctx->irqs[0]) + cluster_index = 0; + else if (ctx->clusterb_enabled && irq == + ctx->irqs[1]) + cluster_index = 1; + else { + pr_err("amlpmu_fix_setup_affinity() bad irq = %d\n", irq); + return; + } + + /* + * find latest next_predicted_stamp cpu for affinity cpu + * if no cpu have predict time, select first cpu of cpumask + * todo: + * - if a cpu predict failed for continuous N times, + * try add some punishment. + * - if no cpu have predicted time, try recently most used cpu + * for affinity + * - try to keep and promote prediction accuracy + */ + for_each_cpu_and(cpu, + &ctx->cpumasks[cluster_index], + cpu_possible_mask) { + ci = per_cpu_ptr(ctx->cpuinfo, cpu); + //pr_info("cpu = %d, ci->next_predicted_stamp.tv64 = %lld\n", + // cpu, ci->next_predicted_stamp.tv64); + if (ci->next_predicted_stamp.tv64 && + ci->next_predicted_stamp.tv64 < latest_next_stamp) { + latest_next_stamp = ci->next_predicted_stamp.tv64; + affinity_cpu = cpu; + } + } + + if (affinity_cpu == -1) { + affinity_cpu = cpumask_first(&ctx->cpumasks[cluster_index]); + pr_debug("used first cpu: %d, cluster: 0x%lx\n", + affinity_cpu, + *cpumask_bits(&ctx->cpumasks[cluster_index])); + } else + pr_debug("find affinity cpu: %d, next_predicted_stamp: %lld\n", + affinity_cpu, + latest_next_stamp); + + if (irq_set_affinity(irq, cpumask_of(affinity_cpu))) + pr_err("irq_set_affinity() failed irq: %d, affinity_cpu: %d\n", + irq, + affinity_cpu); +} + +/* + * on pmu interrupt generated cpu, @irq_num is valid + * on other cpus(called by AML_PMU_IPI), @irq_num is -1 + */ +static int amlpmu_irq_fix(int irq_num) +{ + int i; + int cpu; + int cur_cpu; + int pmuirq_val; + int cluster_index = 0; + int fix_success = 0; + struct amlpmu_cpuinfo *ci; + struct amlpmu_context *ctx = &amlpmu_ctx; + struct call_single_data csd_stack; + int max_wait_cnt = ctx->max_wait_cnt; + + csd_stack.func = amlpmu_handle_irq_ipi; + csd_stack.info = NULL; + + cur_cpu = smp_processor_id(); + + if (irq_num == ctx->irqs[0]) + cluster_index = 0; + else if (ctx->clusterb_enabled && irq_num == ctx->irqs[1]) + cluster_index = 1; + else { + pr_err("amlpmu_irq_fix() bad irq = %d\n", irq_num); + return fix_success; + } + + if (!cpumask_test_cpu(cur_cpu, &ctx->cpumasks[cluster_index])) { + pr_warn("amlpmu_irq_fix() cur_cpu %d not in cluster: 0x%lx\n", + cur_cpu, + *cpumask_bits(&ctx->cpumasks[cluster_index])); + } + + pmuirq_val = readl(ctx->regs[cluster_index]); + pmuirq_val &= 0xf; + pmuirq_val <<= ctx->first_cpus[cluster_index]; + + pr_debug("amlpmu_irq_fix() val=0x%0x, first_cpu=%d, cluster=0x%lx\n", + readl(ctx->regs[cluster_index]), + ctx->first_cpus[cluster_index], + *cpumask_bits(&ctx->cpumasks[cluster_index])); + + for_each_cpu_and(cpu, + &ctx->cpumasks[cluster_index], + cpu_possible_mask) { + if (pmuirq_val & (1<cpuinfo, cpu); + WRITE_ONCE(ci->fix_done, 0); + WRITE_ONCE(ci->fix_overflowed, 0); + + csd_stack.flags = 0; + smp_call_function_single_async(cpu, &csd_stack); + + for (i = 0; i < max_wait_cnt; i++) { + if (READ_ONCE(ci->fix_done)) + break; + + udelay(1); + } + + if (i == ctx->max_wait_cnt) { + pr_err("wait for cpu %d done timeout\n", + cpu); + //amlpmu_relax_timer_start(cpu); + } + + if (READ_ONCE(ci->fix_overflowed)) + fix_success++; + } + } + + return fix_success; +} + +static void amlpmu_update_stats(int irq_num, + int has_overflowed, + int fix_success) +{ + int freq; + int i; + ktime_t stamp; + unsigned long time = jiffies; + struct amlpmu_cpuinfo *ci; + struct amlpmu_context *ctx = &amlpmu_ctx; + + ci = this_cpu_ptr(ctx->cpuinfo); + + if (!has_overflowed && !fix_success) { + pr_debug("empty_irq_cnt: %lu\n", ci->empty_irq_cnt); + ci->empty_irq_cnt++; + ci->empty_irq_time = time; + } + + if (fix_success) { + /* send IPI success */ + pr_debug("fix_irq_cnt: %lu, fix_success = %d\n", + ci->fix_irq_cnt, + fix_success); + ci->fix_irq_cnt++; + ci->fix_irq_time = time; + } + + if (has_overflowed) { + ci->valid_irq_cnt++; + ci->valid_irq_time = time; + + stamp = ktime_get(); + ci->stamp_deltas[ci->valid_irq_cnt % MAX_DELTA_CNT] = + stamp.tv64 - ci->last_stamp.tv64; + ci->last_stamp = stamp; + + /* update avg_delta if it's valid */ + ci->avg_delta = 0; + for (i = 0; i < MAX_DELTA_CNT; i++) + ci->avg_delta += ci->stamp_deltas[i]; + + ci->avg_delta /= MAX_DELTA_CNT; + for (i = 0; i < MAX_DELTA_CNT; i++) { + if (ci->stamp_deltas[i] > ci->avg_delta * 3/2 || + ci->stamp_deltas[i] < ci->avg_delta / 2) { + ci->avg_delta = 0; + break; + } + } + if (ci->avg_delta) + ci->next_predicted_stamp.tv64 = + ci->last_stamp.tv64 + ci->avg_delta; + else + ci->next_predicted_stamp.tv64 = 0; + + pr_debug("irq_num = %d, valid_irq_cnt = %lu\n", + irq_num, + ci->valid_irq_cnt); + pr_debug("cur_delta = %lld, avg_delta = %lld, next = %lld\n", + ci->stamp_deltas[ci->valid_irq_cnt % MAX_DELTA_CNT], + ci->avg_delta, + ci->next_predicted_stamp.tv64); + } + + if (time_after(ci->valid_irq_time, ci->last_valid_irq_time + 2*HZ)) { + freq = ci->empty_irq_cnt - ci->last_empty_irq_cnt; + freq *= HZ; + freq /= (ci->empty_irq_time - ci->last_empty_irq_time); + pr_info("######## empty_irq_cnt: %lu - %lu = %lu, freq = %d\n", + ci->empty_irq_cnt, + ci->last_empty_irq_cnt, + ci->empty_irq_cnt - ci->last_empty_irq_cnt, + freq); + + ci->last_empty_irq_cnt = ci->empty_irq_cnt; + ci->last_empty_irq_time = ci->empty_irq_time; + + + freq = ci->fix_irq_cnt - ci->last_fix_irq_cnt; + freq *= HZ; + freq /= (ci->fix_irq_time - ci->last_fix_irq_time); + pr_info("######## fix_irq_cnt: %lu - %lu = %lu, freq = %d\n", + ci->fix_irq_cnt, + ci->last_fix_irq_cnt, + ci->fix_irq_cnt - ci->last_fix_irq_cnt, + freq); + + ci->last_fix_irq_cnt = ci->fix_irq_cnt; + ci->last_fix_irq_time = ci->fix_irq_time; + + + freq = ci->valid_irq_cnt - ci->last_valid_irq_cnt; + freq *= HZ; + freq /= (ci->valid_irq_time - ci->last_valid_irq_time); + pr_info("######## valid_irq_cnt: %lu - %lu = %lu, freq = %d\n", + ci->valid_irq_cnt, + ci->last_valid_irq_cnt, + ci->valid_irq_cnt - ci->last_valid_irq_cnt, + freq); + + ci->last_valid_irq_cnt = ci->valid_irq_cnt; + ci->last_valid_irq_time = ci->valid_irq_time; + } +} + +int amlpmu_handle_irq(struct arm_pmu *cpu_pmu, int irq_num, int has_overflowed) +{ + int cpu; + int fix_success = 0; + struct amlpmu_cpuinfo *ci; + struct amlpmu_context *ctx = &amlpmu_ctx; + + ci = this_cpu_ptr(ctx->cpuinfo); + ci->irq_num = irq_num; + cpu = smp_processor_id(); + + pr_debug("amlpmu_handle_irq() irq_num = %d, overflowed = %d\n", + irq_num, has_overflowed); + + /* + * if current cpu is not overflowed, it's possible some other + * cpus caused the pmu interrupt. + * so if current cpu is interrupt generated cpu(irq_num != -1), + * call aml_pmu_fix() try to send IPI to other cpus and waiting + * for fix_done. + */ + if (!has_overflowed && irq_num != -1) + fix_success = amlpmu_irq_fix(irq_num); + + /* + * valid_irq, fix_irq and empty_irq status + * avg_delta time account to predict next interrupt time + */ + amlpmu_update_stats(irq_num, has_overflowed, fix_success); + + /* + * armv*pmu_getreset_flags() will clear interrupt. If current + * interrupt is IPI fix(irq_num = -1), interrupt generated cpu + * now is waiting for ci->fix_done=1(clear interrupt). + * we must set ci->fix_done to 1 after amlpmu_stat_account(), + * because interrupt generated cpu need this predict time info + * to setup interrupt affinity. + */ + if (irq_num == -1) { + WRITE_ONCE(ci->fix_overflowed, has_overflowed); + /* fix_overflowed must before fix_done */ + mb(); + WRITE_ONCE(ci->fix_done, 1); + } + + /* only interrupt generated cpu need setup affinity */ + if (irq_num != -1) + amlpmu_fix_setup_affinity(irq_num); + + /* + * when a pmu interrupt generated, if current cpu is not + * overflowed and some other cpus succeed in handling the + * interrupt by IPIs return true. + */ + return !has_overflowed && fix_success; +} + +static int amlpmu_init(struct platform_device *pdev, struct arm_pmu *pmu) +{ + int cpu; + int ret = 0; + int irq; + u32 cpumasks[MAX_CLUSTER_NR] = {0}; + struct amlpmu_context *ctx = &amlpmu_ctx; + struct amlpmu_cpuinfo *ci; + + memset(ctx, 0, sizeof(*ctx)); + + ctx->cpuinfo = __alloc_percpu_gfp( + sizeof(struct amlpmu_cpuinfo), + SMP_CACHE_BYTES, + GFP_KERNEL | __GFP_ZERO); + if (!ctx->cpuinfo) { + pr_err("alloc percpu failed\n"); + ret = -ENOMEM; + goto free; + } + + for_each_possible_cpu(cpu) { + ci = per_cpu_ptr(ctx->cpuinfo, cpu); + ci->last_valid_irq_time = INITIAL_JIFFIES; + ci->last_fix_irq_time = INITIAL_JIFFIES; + ci->last_empty_irq_time = INITIAL_JIFFIES; + } + + ctx->pmu = pmu; + + if (of_property_read_bool(pdev->dev.of_node, "clusterb-enabled")) + ctx->clusterb_enabled = 1; + + pr_info("clusterb_enabled = %d\n", ctx->clusterb_enabled); + + ret = of_property_read_u32_array(pdev->dev.of_node, + "cpumasks", + cpumasks, + ctx->clusterb_enabled ? MAX_CLUSTER_NR : 1); + if (ret) { + pr_err("read prop cpumasks failed, ret = %d\n", ret); + ret = -EINVAL; + goto free; + } + pr_info("cpumasks 0x%0x, 0x%0x\n", cpumasks[0], cpumasks[1]); + + ret = of_property_read_u32(pdev->dev.of_node, + "relax-timer-ns", + &ctx->relax_timer_ns); + if (ret) { + pr_err("read prop relax-timer-ns failed, ret = %d\n", ret); + ret = -EINVAL; + goto free; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "max-wait-cnt", + &ctx->max_wait_cnt); + if (ret) { + pr_err("read prop max-wait-cnt failed, ret = %d\n", ret); + ret = -EINVAL; + goto free; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + pr_err("get clusterA irq failed, %d\n", irq); + ret = -EINVAL; + goto free; + } + ctx->irqs[0] = irq; + pr_info("cluster A irq = %d\n", irq); + + ctx->regs[0] = of_iomap(pdev->dev.of_node, 0); + if (IS_ERR(ctx->regs[0])) { + pr_err("of_iomap() clusterA failed, base = %p\n", ctx->regs[0]); + ret = PTR_ERR(ctx->regs[0]); + goto free; + } + + cpumask_clear(&ctx->cpumasks[0]); + memcpy(cpumask_bits(&ctx->cpumasks[0]), + &cpumasks[0], + sizeof(cpumasks[0])); + if (!cpumask_intersects(&ctx->cpumasks[0], cpu_possible_mask)) { + pr_err("bad cpumasks[0] 0x%x\n", cpumasks[0]); + ret = -EINVAL; + goto free; + } + ctx->first_cpus[0] = cpumask_first(&ctx->cpumasks[0]); + + amlpmu_fix_setup_affinity(ctx->irqs[0]); + + hrtimer_init(&ctx->relax_timer, + CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + ctx->relax_timer.function = amlpmu_relax_timer_func; + + if (!ctx->clusterb_enabled) + return 0; + + irq = platform_get_irq(pdev, 1); + if (irq < 0) { + pr_err("get clusterB irq failed, %d\n", irq); + ret = -EINVAL; + goto free; + } + ctx->irqs[1] = irq; + pr_info("cluster B irq = %d\n", irq); + + + ctx->regs[1] = of_iomap(pdev->dev.of_node, 1); + if (IS_ERR(ctx->regs[1])) { + pr_err("of_iomap() clusterA failed, base = %p\n", ctx->regs[1]); + ret = PTR_ERR(ctx->regs[1]); + goto free; + } + + cpumask_clear(&ctx->cpumasks[1]); + memcpy(cpumask_bits(&ctx->cpumasks[1]), + &cpumasks[1], + sizeof(cpumasks[1])); + if (!cpumask_intersects(&ctx->cpumasks[1], cpu_possible_mask)) { + pr_err("bad cpumasks[1] 0x%x\n", cpumasks[1]); + ret = -EINVAL; + goto free; + } else if (cpumask_intersects(&ctx->cpumasks[0], &ctx->cpumasks[1])) { + pr_err("cpumasks intersect 0x%x : 0x%x\n", + cpumasks[0], + cpumasks[1]); + ret = -EINVAL; + goto free; + } + ctx->first_cpus[1] = cpumask_first(&ctx->cpumasks[1]); + + amlpmu_fix_setup_affinity(ctx->irqs[1]); + + return 0; + +free: + if (ctx->cpuinfo) + free_percpu(ctx->cpuinfo); + + if (ctx->regs[0]) + iounmap(ctx->regs[0]); + + if (ctx->regs[1]) + iounmap(ctx->regs[1]); + + return ret; +} + +#endif + int arm_pmu_device_probe(struct platform_device *pdev, const struct of_device_id *of_table, const struct pmu_probe_info *probe_table) @@ -1029,6 +1540,13 @@ int arm_pmu_device_probe(struct platform_device *pdev, return -ENOMEM; } +#ifdef CONFIG_AMLOGIC_MODIFY + if (amlpmu_init(pdev, pmu)) { + pr_err("amlpmu_init() failed\n"); + return 1; + } +#endif + armpmu_init(pmu); pmu->plat_device = pdev; diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index 8462da266089..e3c724ba22fd 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h @@ -162,6 +162,99 @@ int arm_pmu_device_probe(struct platform_device *pdev, #define ARMV8_PMU_PDEV_NAME "armv8-pmu" +#ifdef CONFIG_AMLOGIC_MODIFY +#define MAX_DELTA_CNT 4 +struct amlpmu_cpuinfo { + int irq_num; + + /* + * In interrupt generated cpu(affinity cpu) + * If pmu no overflowed, then we need to send IPI to some other cpus to + * fix it. And before send IPI, set corresponding cpu's fix_done and + * fix_overflowed to zero, in corresponding cpu's IPI interrupt will set + * fix_done to inform source cpu and if indeed pmu overflowed then also + * set fix_overflowed to 1, then inerrupt generated cpu can feel that. + */ + int fix_done; + int fix_overflowed; + + /* for interrupt affinity prediction */ + ktime_t last_stamp; + s64 stamp_deltas[MAX_DELTA_CNT]; + s64 avg_delta; + ktime_t next_predicted_stamp; + + /* + * irq state account of this cpu + * + * - valid_irq_cnt: + * valid irq cnt.(pmu overflow happened) + * - fix_irq_cnt: + * when this cpu is pmu interrupt generated affinity cpu, a pmu + * interrupt if cpu affinity predict failed so no pmu overflow + * happened and succeeded send IPI to other cpu, then it's a send + * fix irq. So the lower is better. + * - empty_irq_cnt: + * when this cpu is pmu interrupt generated affinity cpu, a pmu + * interrupt that no overflow happened and also no fix IPI sended to + * other cpus, then it's a empty irq. + * when this cpu is not affinity cpu, a IPI interrupt(pmu fix from + * affinity cpu) that no pmu overflow happened, it's a empty irq. + * + * attention: + * A interrupt can be a valid_irq and also a fix_irq. + */ + unsigned long valid_irq_cnt; + unsigned long fix_irq_cnt; + unsigned long empty_irq_cnt; + + unsigned long valid_irq_time; + unsigned long fix_irq_time; + unsigned long empty_irq_time; + + unsigned long last_valid_irq_cnt; + unsigned long last_fix_irq_cnt; + unsigned long last_empty_irq_cnt; + + unsigned long last_valid_irq_time; + unsigned long last_fix_irq_time; + unsigned long last_empty_irq_time; +}; + + +#define MAX_CLUSTER_NR 2 +struct amlpmu_context { + struct amlpmu_cpuinfo __percpu *cpuinfo; + + /* struct arm_pmu */ + struct arm_pmu *pmu; + + int clusterb_enabled; + + unsigned int __iomem *regs[MAX_CLUSTER_NR]; + int irqs[MAX_CLUSTER_NR]; + struct cpumask cpumasks[MAX_CLUSTER_NR]; + int first_cpus[MAX_CLUSTER_NR]; + + /* + * In main pmu irq route wait for other cpu fix done may cause lockup, + * when lockup we disable main irq for a while. + * relax_timer will enable main irq again. + */ + struct hrtimer relax_timer; + + unsigned int relax_timer_ns; + unsigned int max_wait_cnt; +}; + +extern struct amlpmu_context amlpmu_ctx; + +int amlpmu_handle_irq(struct arm_pmu *cpu_pmu, int irq_num, int has_overflowed); + +/* defined int arch/arm(64)/kernel/perf_event(_v7).c */ +void amlpmu_handle_irq_ipi(void *arg); +#endif + #endif /* CONFIG_ARM_PMU */ #endif /* __ARM_PMU_H__ */ diff --git a/include/linux/smp.h b/include/linux/smp.h index c9b5fb366422..acba97e0eeab 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -73,13 +73,6 @@ extern void smp_send_stop(void); */ extern void smp_send_reschedule(int cpu); -#ifdef CONFIG_AMLOGIC_MODIFY -/* - * sends a 'aml pmu' event to another CPU: - */ -extern void smp_send_aml_pmu(int cpu); -#endif - /* * Prepare machine for booting other CPUs. */ From 5620ae8cff462a1ae510cdcb80a66164ccbc694c Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 25 Jan 2019 13:27:59 +0800 Subject: [PATCH 0032/1060] vpp: force vd2 using preblend when playing mvc [1/1] PD#SWPL-3381 Problem: vd2 used postblend as default after g12a chip Solution: force vd2 using preblend when playing mvc Verify: Locally on u212 Change-Id: Ia7fab8ad70ed1e58b7ade241828afab288b94bec Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 3c3e356ca473..48914144bf8c 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -7379,7 +7379,9 @@ SET_FILTER: if (is_dolby_vision_on()) vpp_misc_set &= ~(VPP_VD2_PREBLEND | VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); - else if (process_3d_type) + else if (process_3d_type || + (cur_dispbuf && + (cur_dispbuf->type & VIDTYPE_MVC))) vpp_misc_set |= VPP_VD2_PREBLEND | VPP_PREBLEND_EN; else if (!legacy_vpp) From 9ab75d4617f0a4fa9ce6cc1380541aba7183c699 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 18 Jan 2019 15:33:52 +0800 Subject: [PATCH 0033/1060] ge2d: reset alloc flag when free dma buffer [1/2] PD#SWPL-4354 Problem: alloc flag is not correct when free dma buffer Solution: reset alloc flag when free dma buffer Verify: test pass on g12a-u200 Change-Id: I4aea27f38ebda72cfe77183423600c918b836d7c Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index e5d6b658dcbc..5225e72d91ea 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -416,6 +416,7 @@ int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index) return (-EINVAL); } aml_dma_put(buf); + buffer->gd_buffer[index].alloc = 0; return 0; } From acd7ddb6ca9f60e5c64eb3408b2bc8cacaf17cac Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Tue, 22 Jan 2019 17:16:17 +0800 Subject: [PATCH 0034/1060] gdc: reset alloc flag when free dma buffer [2/2] PD#SWPL-4354 Problem: alloc flag is not correct when free dma buffer Solution: reset alloc flag when free dma buffer Verify: test pass on g12a-u200 Change-Id: Idfc0be5b394d18799232f6239b3f6c6df9181ce0 Signed-off-by: Jian Cao --- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 2f4fe5989ee1..1ade0e4b7567 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -418,6 +418,7 @@ int gdc_dma_buffer_free(struct aml_dma_buffer *buffer, int index) return (-EINVAL); } aml_dma_put(buf); + buffer->gd_buffer[index].alloc = 0; return 0; } From 6363b2985b26e37af5a69678d1d8b8c8542c429a Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Tue, 22 Jan 2019 14:25:58 +0800 Subject: [PATCH 0035/1060] cpufreq: add more syspll freq info [1/1] PD#SWPL-4035 Problem: add more syspll freq info. Solution: add more syspll freq info. Verify: g12a_u200, verify pass Change-Id: I3e2a587f5ebaa20126e6ad5c37bd9d2730a75125 Signed-off-by: Hong Guo --- drivers/amlogic/clk/g12a/g12a.h | 5 +++++ drivers/amlogic/clk/tl1/tl1.h | 4 ++++ drivers/amlogic/cpufreq/meson-cpufreq.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h index 525b1fa43ccc..488d1f64a968 100644 --- a/drivers/amlogic/clk/g12a/g12a.h +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -143,8 +143,11 @@ static const struct pll_rate_table g12a_pll_rate_table[] = { PLL_RATE(1104000000ULL, 184, 1, 2), /*DCO=4416M*/ PLL_RATE(1200000000ULL, 200, 1, 2), /*DCO=4800M*/ PLL_RATE(1296000000ULL, 216, 1, 2), /*DCO=5184M*/ + PLL_RATE(1302000000ULL, 217, 1, 2), /*DCO=5208M*/ PLL_RATE(1398000000ULL, 233, 1, 2), /*DCO=5592M*/ + PLL_RATE(1404000000ULL, 234, 1, 2), /*DCO=5616M*/ PLL_RATE(1494000000ULL, 249, 1, 2), /*DCO=5976M*/ + PLL_RATE(1500000000ULL, 125, 1, 1), /*DCO=3000M*/ PLL_RATE(1512000000ULL, 126, 1, 1), /*DCO=3024M*/ PLL_RATE(1608000000ULL, 134, 1, 1), /*DCO=3216M*/ PLL_RATE(1704000000ULL, 142, 1, 1), /*DCO=3408M*/ @@ -163,7 +166,9 @@ static const struct pll_rate_table g12a_pll_rate_table[] = { PLL_RATE(2016000000ULL, 168, 1, 1), /*DCO=4032M*/ PLL_RATE(2100000000ULL, 175, 1, 1), /*DCO=4200M*/ PLL_RATE(2196000000ULL, 183, 1, 1), /*DCO=4392M*/ + PLL_RATE(2208000000ULL, 184, 1, 1), /*DCO=4416M*/ PLL_RATE(2292000000ULL, 191, 1, 1), /*DCO=4584M*/ + PLL_RATE(2304000000ULL, 192, 1, 1), /*DCO=4608M*/ PLL_RATE(2400000000ULL, 200, 1, 1), /*DCO=4800M*/ PLL_RATE(2496000000ULL, 208, 1, 1), /*DCO=4992M*/ PLL_RATE(2592000000ULL, 216, 1, 1), /*DCO=5184M*/ diff --git a/drivers/amlogic/clk/tl1/tl1.h b/drivers/amlogic/clk/tl1/tl1.h index 92d899658554..e3a7b56dbdc3 100644 --- a/drivers/amlogic/clk/tl1/tl1.h +++ b/drivers/amlogic/clk/tl1/tl1.h @@ -158,6 +158,7 @@ static const struct pll_rate_table tl1_pll_rate_table[] = { PLL_RATE(1104000000ULL, 184, 1, 2), /*DCO=4416M*/ PLL_RATE(1200000000ULL, 200, 1, 2), /*DCO=4800M*/ PLL_RATE(1296000000ULL, 216, 1, 2), /*DCO=5184M*/ + PLL_RATE(1302000000ULL, 217, 1, 2), /*DCO=5208M*/ PLL_RATE(1398000000ULL, 233, 1, 2), /*DCO=5592M*/ PLL_RATE(1494000000ULL, 249, 1, 2), /*DCO=5976M*/ PLL_RATE(1512000000ULL, 126, 1, 1), /*DCO=3024M*/ @@ -167,10 +168,13 @@ static const struct pll_rate_table tl1_pll_rate_table[] = { PLL_RATE(1896000000ULL, 158, 1, 1), /*DCO=3792M*/ PLL_RATE(1908000000ULL, 159, 1, 1), /*DCO=3816M*/ PLL_RATE(1920000000ULL, 160, 1, 1), /*DCO=3840M*/ + PLL_RATE(2004000000ULL, 167, 1, 1), /*DCO=4008M*/ PLL_RATE(2016000000ULL, 168, 1, 1), /*DCO=4032M*/ PLL_RATE(2100000000ULL, 175, 1, 1), /*DCO=4200M*/ PLL_RATE(2196000000ULL, 183, 1, 1), /*DCO=4392M*/ + PLL_RATE(2208000000ULL, 184, 1, 1), /*DCO=4416M*/ PLL_RATE(2292000000ULL, 191, 1, 1), /*DCO=4584M*/ + PLL_RATE(2304000000ULL, 192, 1, 1), /*DCO=4608M*/ PLL_RATE(2400000000ULL, 200, 1, 1), /*DCO=4800M*/ PLL_RATE(2496000000ULL, 208, 1, 1), /*DCO=4992M*/ PLL_RATE(2592000000ULL, 216, 1, 1), /*DCO=5184M*/ diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index ce9b432f9f5e..7069c122c743 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -574,7 +574,7 @@ __setup("max_freq_a73=", get_max_freq_a73); static int meson_cpufreq_exit(struct cpufreq_policy *policy) { struct device *cpu_dev; - struct sprd_cpufreq_driver_data *cpufreq_data; + struct meson_cpufreq_driver_data *cpufreq_data; int cur_cluster = topology_physical_package_id(policy->cpu); cpufreq_data = policy->driver_data; From 610d7a40571dc3f7e12b5ea22bb9be243438a6e6 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Wed, 9 Jan 2019 17:42:52 +0800 Subject: [PATCH 0036/1060] mailbox: mailbox: add chip performance info read from efuse [2/2] PD#SWPL-4035 Problem: cpu driver need read efuse data Solution: add interface to read data Verify: g12a_skt Change-Id: Ia5d74c3fa057d06426b4277652e508714400a30f Signed-off-by: Shunzhou Jiang --- drivers/amlogic/mailbox/scpi_protocol.c | 88 +++++++++++++++++++++++++ include/linux/amlogic/scpi_protocol.h | 11 +++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/mailbox/scpi_protocol.c b/drivers/amlogic/mailbox/scpi_protocol.c index 20f05c10b454..22883ee98e59 100644 --- a/drivers/amlogic/mailbox/scpi_protocol.c +++ b/drivers/amlogic/mailbox/scpi_protocol.c @@ -60,6 +60,42 @@ enum scpi_error_codes { SCPI_ERR_MAX }; +static int scpi_freq_map_table[] = { + 0, + 0, + 1200, + 1300, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 0 +}; +static int scpi_volt_map_table[] = { + 0, + 0, + 900, + 910, + 920, + 930, + 940, + 950, + 960, + 970, + 980, + 990, + 1000, + 1010, + 1020, + 0 +}; struct scpi_data_buf { int client_id; @@ -559,3 +595,55 @@ u8 scpi_get_ethernet_calc(void) return buf.eth_calc; } EXPORT_SYMBOL_GPL(scpi_get_ethernet_calc); + +int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol) +{ + struct scpi_data_buf sdata; + struct mhu_data_buf mdata; + u8 index = 0; + int ret; + + struct __packed { + u32 status; + u8 pfm_info[4]; + } buf; + + SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_NONE, + SCPI_CMD_GET_CPUINFO, index, buf); + if (scpi_execute_cmd(&sdata)) + return -EPERM; + + switch (type) { + case SCPI_CPUINFO_VERSION: + ret = buf.pfm_info[0]; + break; + case SCPI_CPUINFO_CLUSTER0: + index = (buf.pfm_info[1] >> 4) & 0xf; + *freq = scpi_freq_map_table[index]; + index = buf.pfm_info[1] & 0xf; + *vol = scpi_volt_map_table[index]; + ret = 0; + break; + case SCPI_CPUINFO_CLUSTER1: + index = (buf.pfm_info[2] >> 4) & 0xf; + *freq = scpi_freq_map_table[index]; + index = buf.pfm_info[2] & 0xf; + *vol = scpi_volt_map_table[index]; + ret = 0; + break; + case SCPI_CPUINFO_SLT: + index = (buf.pfm_info[3] >> 4) & 0xf; + *freq = scpi_freq_map_table[index]; + index = buf.pfm_info[3] & 0xf; + *vol = scpi_volt_map_table[index]; + ret = 0; + break; + default: + *freq = 0; + *vol = 0; + ret = -1; + break; + }; + return ret; +} +EXPORT_SYMBOL_GPL(scpi_get_cpuinfo); diff --git a/include/linux/amlogic/scpi_protocol.h b/include/linux/amlogic/scpi_protocol.h index 804dcf2278c7..1fe5a19eb67d 100644 --- a/include/linux/amlogic/scpi_protocol.h +++ b/include/linux/amlogic/scpi_protocol.h @@ -71,12 +71,21 @@ enum scpi_std_cmd { SCPI_CMD_WAKEUP_REASON_GET = 0x30, SCPI_CMD_WAKEUP_REASON_CLR = 0X31, SCPI_CMD_GET_ETHERNET_CALC = 0x32, + SCPI_CMD_GET_CPUINFO = 0x33, SCPI_CMD_GET_CEC1 = 0xB4, SCPI_CMD_GET_CEC2 = 0xB5, SCPI_CMD_COUNT }; +enum scpi_get_pfm_type { + SCPI_CPUINFO_CLUSTER0, + SCPI_CPUINFO_CLUSTER1, + SCPI_CPUINFO_VERSION, + SCPI_CPUINFO_SLT, + SCPI_CPUINFO_NUMS +}; + struct scpi_opp_entry { u32 freq_hz; u32 volt_mv; @@ -88,7 +97,6 @@ struct scpi_dvfs_info { struct scpi_opp_entry *opp; } __packed; - unsigned long scpi_clk_get_val(u16 clk_id); int scpi_clk_set_val(u16 clk_id, unsigned long rate); int scpi_dvfs_get_idx(u8 domain); @@ -104,4 +112,5 @@ int scpi_get_wakeup_reason(u32 *wakeup_reason); int scpi_clr_wakeup_reason(void); int scpi_get_cec_val(enum scpi_std_cmd index, u32 *p_cec); u8 scpi_get_ethernet_calc(void); +int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol); #endif /*_SCPI_PROTOCOL_H_*/ From 17e06ce936f7dbffd468ae7f7d16e5c483683ee8 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Tue, 27 Nov 2018 14:42:57 +0800 Subject: [PATCH 0037/1060] osd: osd: screen blank after boot logo [1/1] PD#172587 Problem: screen blank after boot logo Solution: correct default display information Verify: verified on tl1 ref board Change-Id: I94237b5241eacee6965bfe4ea0426bb8e9f494f1 Signed-off-by: Jian Cao osd: tl1 hold line fix needn't shift workaround [1/1] PD#172587 Problem: tl1 hold line fix needn't shift workaround. Solution: remove shift workaround int tl1 Verify: verified by x301 Change-Id: I96d99758ba6f93622c34a8e69c4a3f769fdfad49 Signed-off-by: pengcheng chen usb: bringup usb for tl1 [1/1] PD#172587 Problem: bringup usb for tl1 Solution: bringup usb for tl1. disable usb device sof interrupt for tl1. Verify: verify on tl1 skt. Change-Id: Ifbcd3b406145ac39709ff2df795544086277f00e Signed-off-by: Yue Wang Signed-off-by: Luan Yuan Conflicts: arch/arm/boot/dts/amlogic/mesontl1.dtsi --- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 2083 +++++++++++++++++ arch/arm/boot/dts/amlogic/tl1_pxp.dts | 21 + drivers/amlogic/media/osd/osd.h | 1 + drivers/amlogic/media/osd/osd_hw.c | 16 +- drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c | 10 +- .../usb/dwc_otg/310/dwc_otg_pcd_intr.c | 2 +- .../usb/dwc_otg/310/dwc_otg_pcd_linux.c | 4 +- drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c | 30 +- drivers/usb/host/xhci-hub.c | 28 +- drivers/usb/host/xhci-ring.c | 24 +- drivers/usb/host/xhci.c | 4 + include/linux/amlogic/usb-v2.h | 1 + 12 files changed, 2189 insertions(+), 35 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/mesontl1.dtsi diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi new file mode 100644 index 000000000000..e08b0710512a --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -0,0 +1,2083 @@ +/* + * arch/arm/boot/dts/amlogic/mesontl1.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" + +/ { + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus:cpus { + #address-cells = <1>; + #size-cells = <0>; + #cooling-cells = <2>;/* min followed by max */ + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x0>; + //timer=<&timer_a>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x1>; + //timer=<&timer_b>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x2>; + //timer=<&timer_c>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x0 0x3>; + //timer=<&timer_d>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg = <0xffd0f190 0x4 0xffd0f194 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating =<300>; + clockevent-shift =<20>; + clockevent-features =<0x23>; + interrupts = <0 60 1>; + bit_enable =<16>; + bit_mode =<12>; + bit_resolution =<0>; + }; + + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + interrupts = ; + reg = <0xff634400 0x1000>; + + /* addr = base + offset << 2 */ + sys_cpu_status0_offset = <0xa0>; + + sys_cpu_status0_pmuirq_mask = <0xf>; + + /* default 10ms */ + relax_timer_ns = <10000000>; + + /* default 10000us */ + max_wait_cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xffc01000 0x1000>, + <0xffc02000 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + scpi_clocks { + compatible = "arm, scpi-clks"; + + scpi_dvfs: scpi_clocks@0 { + compatible = "arm, scpi-clk-indexed"; + #clock-cells = <1>; + clock-indices = <0>; + clock-output-names = "vcpu"; + }; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "okay"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@ff63c400 { + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffd7000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + io_cbus_base { + reg = <0xffd00000 0x101000>; + }; + io_apb_base { + reg = <0xffe01000 0x19f000>; + }; + io_aobus_base { + reg = <0xff800000 0x100000>; + }; + io_vapb_base { + reg = <0xff900000 0x200000>; + }; + io_hiu_base { + reg = <0xff63c000 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + meson_suspend: pm { + compatible = "amlogic, pm"; + /*gxbaby-suspend;*/ + status = "okay"; + reg = <0xff8000a8 0x4>, + <0xff80023c 0x4>; + }; + + cpuinfo { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + reboot { + compatible = "amlogic,reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "okay"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + vpu { + compatible = "amlogic, vpu-tl1"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014 { + compatible = "amlogic,meson-tl1-aobus-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio_ao: ao-bank@ff800014 { + reg = <0xff800014 0x8>, + <0xff800024 0x14>, + <0xff80001c 0x8>; + reg-names = "mux", "gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + aoceca_mux:aoceca_mux { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocecb_mux:aocecb_mux { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + }; + + pinctrl_periphs: pinctrl@ff6346c0 { + compatible = "amlogic,meson-tl1-periphs-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio: banks@ff6346c0 { + reg = <0xff6346c0 0x40>, + <0xff6344e8 0x18>, + <0xff634520 0x18>, + <0xff634440 0x4c>, + <0xff634740 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + + hdmirx_a_mux:hdmirx_a_mux { + mux { + groups = "hdmirx_a_hpd", "hdmirx_a_det", + "hdmirx_a_sda", "hdmirx_a_sck"; + function = "hdmirx_a"; + }; + }; + + hdmirx_b_mux:hdmirx_b_mux { + mux { + groups = "hdmirx_b_hpd", "hdmirx_b_det", + "hdmirx_b_sda", "hdmirx_b_sck"; + function = "hdmirx_b"; + }; + }; + + hdmirx_c_mux:hdmirx_c_mux { + mux { + groups = "hdmirx_c_hpd", "hdmirx_c_det", + "hdmirx_c_sda", "hdmirx_c_sck"; + function = "hdmirx_c"; + }; + }; + + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000 + 0xff658000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <1>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0xffe09080 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ + /** 0x2: amlogic-v2 phy **/ + phy-interface = <0x2>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic,meson-tl1-wdt"; + status = "okay"; + reg = <0xffd0f0d0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "disabled"; + select = "apao"; /* disable/apao/apee */ + jtagao-gpios = <&gpio_ao GPIOAO_6 0 + &gpio_ao GPIOAO_7 0 + &gpio_ao GPIOAO_8 0 + &gpio_ao GPIOAO_9 0>; + jtagee-gpios = <&gpio GPIOC_0 0 + &gpio GPIOC_1 0 + &gpio GPIOC_4 0 + &gpio GPIOC_5 0>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1021000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1021000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0xff63c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff63c000 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,tl1-clkc"; + #clock-cells = <1>; + reg = <0x0 0x3fc>; + }; + };/* end of hiubus*/ + + audiobus: audiobus@0xff600000 { + compatible = "amlogic, audio-controller", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff600000 0x10000>; + ranges = <0x0 0xff600000 0x10000>; + + clkaudio:audio_clocks { + compatible = "amlogic, tl1-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0xb0>; + }; + + ddr_manager { + compatible = "amlogic, tl1-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 48 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; + }; + };/* end of audiobus*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF601000 0x400>; + }; + audiobus_base { + reg = <0xFF600000 0x1000>; + }; + audiolocker_base { + reg = <0xFF601400 0x400>; + }; + eqdrc_base { + reg = <0xFF602000 0x2000>; + }; + reset_base { + reg = <0xFFD01000 0x1000>; + }; + vad_base { + reg = <0xFF601800 0x800>; + }; + }; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0xffd00000 0x27000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xffd00000 0x27000>; + + clk-measure@18004 { + compatible = "amlogic,tl1-measure"; + reg = <0x18004 0x4 0x1800c 0x4>; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1f000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1e000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1d000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1c000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-tl1-gpio-intc"; + reg = <0xf080 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x1b000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x1a000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x19000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x13000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x15000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0xff800000 0xb000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff800000 0xb000>; + + cpu_version { + reg = <0x220 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,tl1-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x1000>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x7000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x2000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + //pinctrl-names = "default"; + //pinctrl-0 = <&ao_a_uart_pins>; + /* 0 not support; 1 support */ + support-sysrq = <0>; + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins1>; + }; + + remote: rc@8040 { + compatible = "amlogic, aml_remote"; + reg = <0x8040 0x44>, + <0x8000 0x20>; + status = "okay"; + protocol = ; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; + }; + + meson_irblaster: irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + interrupts = <0 198 1>; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x05000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x6000 0x20>; + interrupts = ; + pinctrl-names="default"; + pinctrl-0=<&i2c_ao_slave_pins>; + }; + };/* end of aobus */ + + ion_dev { + compatible = "amlogic, ion_dev"; + status = "okay"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + }; /* end of soc*/ + + custom_maps: custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <44>; /*keymap size*/ + keymap = ; + }; + + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe07000 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + spifc: spifc@ffd14000 { + compatible = "amlogic,aml-spi-nor"; + status = "disabled"; + + reg = <0xffd14000 0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&spifc_all_pins>; + clock-names = "core"; + clocks = <&clkc CLKID_CLK81>; + + spi-nor@0 { + compatible = "jedec,spi-nor"; + spifc-frequency = <40000000>; + read-capability = <4>;/* dual read 1_1_2 */ + spifc-io-width = <4>; + }; + }; + + slc_nand: nand-controller@0xFFE07800 { + compatible = "amlogic, aml_mtd_nand"; + status = "disabled"; + reg = <0xFFE07800 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + *with uboot if bl_mode was set as 1 + *bl_mode: 0 compact mode;1 descrete mode + *if bl_mode was set as 1,fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy*/ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts*/ + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + status = "okay"; + clocks = <&clkc CLKID_U_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vcodec-dec { + compatible = "amlogic, vcodec-dec"; + status = "okay"; + }; + + vdec { + compatible = "amlogic, vdec"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + canvas: canvas { + compatible = "amlogic, meson, canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + io_efuse_base{ + reg = <0xff630000 0x2000>; + }; + }; + + rdma { + compatible = "amlogic, meson-tl1, rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: fb { + compatible = "amlogic, meson-tl1"; + memory-region = <&logo_reserved>; + status = "disabled"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + ionvideo { + compatible = "amlogic, ionvideo"; + status = "okay"; + }; + + amlvideo { + compatible = "amlogic, amlvideo"; + status = "okay"; + }; + + vdac { + compatible = "amlogic, vdac-tl1"; + status = "okay"; + }; + + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff638800>; + interrupts = ; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + }; +}; /* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins: sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1", + "GPIOAO_2", + "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_6", + "GPIOAO_7", + "GPIOAO_8", + "GPIOAO_9", + "GPIOAO_10", + "GPIOAO_11", + "GPIOE_0", + "GPIOE_1", + "GPIOE_2", + "GPIO_TEST_N"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins: sd_to_ao_uart_pins { + mux { + groups = "uart_ao_a_tx", + "uart_ao_a_rx", + "uart_ao_a_cts", + "uart_ao_a_rts"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins1: pwm_ao_c_hiz1 { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins2: pwm_ao_c_hiz2 { + mux { + groups = "pwm_ao_c_hiz_7"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_e2"; + }; + }; + + i2c_ao_2_pins:i2c_ao_2 { + mux { + groups = "i2c_ao_sck_2", + "i2c_ao_sda_3"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_e_pins:i2c_ao_e { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_slave_pins:i2c_ao_slave { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_a_rx", + "uart_ao_a_tx"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins1:ao_b_uart1 { + mux { + groups = "uart_ao_b_tx_2", + "uart_ao_b_rx_3"; + function = "uart_ao_b"; + }; + }; + + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_b_tx_8", + "uart_ao_b_rx_9"; + function = "uart_ao_b"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins: emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up: emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done: emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins: sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins: sd_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_1bit_pins: sd_1bit_pins { + mux { + groups = "sdcard_d0", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins: ao_to_sd_uart_pins { + mux { + groups = "uart_ao_a_rx_c", + "uart_ao_a_tx_c", + "uart_ao_a_rx_w3", + "uart_ao_a_tx_w2", + "uart_ao_a_rx_w7", + "uart_ao_a_tx_w6", + "uart_ao_a_rx_w11", + "uart_ao_a_tx_w10"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr"; + function = "nand"; + input-enable; + drive-strength = <3>; + }; + }; + + nand_cs_pins:nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + drive-strength = <3>; + }; + }; + + /* sdemmc portA */ + sdio_clk_cmd_pins: sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins: sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spifc_cs_pin:spifc_cs_pin { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_pulldown: spifc_pulldown { + mux { + groups = "nor_d", + "nor_q", + "nor_c"; + function = "nor"; + bias-pull-down; + }; + }; + + spifc_pullup: spifc_pullup { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_all_pins: spifc_all_pins { + mux { + groups = "nor_d", + "nor_q", + "nor_c", + "nor_hold", + "nor_wp"; + function = "nor"; + input-enable; + bias-pull-down; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_c"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_dv"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_h"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_dv"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_e_pins1: pwm_e1 { + mux { + groups = "pwm_e_dv"; + function = "pwm_e"; + }; + }; + + pwm_e_pins2: pwm_e2 { + mux { + groups = "pwm_e_z"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_dv"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + i2c0_c_pins:i2c0_c { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c0_dv_pins:i2c0_dv { + mux { + groups = "i2c0_sda_dv", + "i2c0_sck_dv"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_z_pins:i2c1_z { + mux { + groups = "i2c1_sda_z", + "i2c1_sck_z"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_h_pins:i2c1_h { + mux { + groups = "i2c1_sda_h", + "i2c1_sck_h"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_h_pins:i2c2_h { + mux { + groups = "i2c2_sda_h", + "i2c2_sck_h"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_z_pins:i2c2_z { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h1_pins:i2c3_h1 { + mux { + groups = "i2c3_sda_h1", + "i2c3_sck_h0"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h20_pins:i2c3_h3 { + mux { + groups = "i2c3_sda_h20", + "i2c3_sck_h19"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_dv_pins:i2c3_dv { + mux { + groups = "i2c3_sda_dv", + "i2c3_sck_dv"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_c_pins:i2c3_c { + mux { + groups = "i2c3_sda_c", + "i2c3_sck_c"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spicc0_pins_h: spicc0_pins_h { + mux { + groups = "spi0_mosi_h", + "spi0_miso_h", + "spi0_clk_h"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins_dv: spicc1_pins_dv { + mux { + groups = "spi1_mosi_dv", + "spi1_miso_dv", + "spi1_clk_dv"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_a_tx", + "uart_a_rx", + "uart_a_cts", + "uart_a_rts"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_b_tx", + "uart_b_rx"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_c_tx", + "uart_c_rx"; + function = "uart_c"; + }; + }; + +}; diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index aacb76768dc4..d073d021f4f9 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -849,6 +849,27 @@ }; }; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 751fdc06a5f0..f6b658e1c228 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -750,6 +750,7 @@ struct hw_para_s { u32 hw_rdma_en; u32 blend_bypass; u32 hdr_used; + u32 workaround_line; u32 basic_urgent; u32 two_ports; u32 afbc_err_cnt; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 1fe25dff54cf..c62d11dbd947 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -6102,12 +6102,12 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) if (!blending) return; if (osd_hw.hdr_used) - workaround_line = 1; + workaround_line = osd_hw.workaround_line; else { if (blending->layer_cnt == 2) workaround_line = 0; else - workaround_line = 1; + workaround_line = osd_hw.workaround_line; } layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -6537,9 +6537,10 @@ static void osd_setting_blend0_input(u32 index, struct hw_osd_blending_s *blending) { struct layer_blend_s *layer_blend; - u32 workaround_line = 1; + u32 workaround_line = 0; /* for g12a blend shift issue */ + workaround_line = osd_hw.workaround_line; layer_blend = &(blending->layer_blend); if (index == OSD1) { @@ -8477,9 +8478,16 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.disp_info.position_x = 0; osd_hw.disp_info.position_y = 0; osd_hw.disp_info.position_w = 1920; - osd_hw.disp_info.background_h = 1080; + osd_hw.disp_info.position_h = 1080; osd_hw.vinfo_width = 1920; osd_hw.vinfo_height = 1080; + if ((osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12A) || + (osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B)) + osd_hw.workaround_line = 1; + else + osd_hw.workaround_line = 0; for (idx = 0; idx < osd_hw.osd_meson_dev.osd_count; idx++) { osd_hw.premult_en[idx] = 0; osd_hw.osd_afbcd[idx].format = COLOR_INDEX_32_ABGR; diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c index 4601a813ea4f..f0e4e5caa9d7 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c @@ -6249,8 +6249,11 @@ int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if, return -DWC_E_INVALID; } if (val > - (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { - DWC_WARN("Value is larger then power-on FIFO size\n"); + (DWC_READ_REG32 + (&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { + if (DWC_READ_REG32 + (&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16) + DWC_WARN("Value is larger then power-on FIFO size\n"); if (dwc_otg_param_initialized (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) DWC_ERROR @@ -6313,7 +6316,8 @@ int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if, int32_t val, return -DWC_E_INVALID; } if (val > txfifosize.b.depth) { - DWC_WARN("Value is larger then power-on FIFO size\n"); + if (txfifosize.b.depth) + DWC_WARN("Value is larger then power-on FIFO size\n"); if (dwc_otg_param_initialized (core_if->core_params->dev_tx_fifo_size[fifo_num])) DWC_ERROR diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c index ecfc09be3ba1..4b9fb07478b5 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c @@ -1064,7 +1064,7 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *pcd) DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); #ifdef CONFIG_AMLOGIC_USB3PHY - if (GET_CORE_IF(pcd)->phy_interface == 0) { + if (GET_CORE_IF(pcd)->phy_interface != 1) { speed = get_device_speed(GET_CORE_IF(pcd)); if (speed != USB_SPEED_HIGH) { gintsts.d32 = 0; diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c index 72276e79bdc8..6ba3f1676201 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c @@ -1267,7 +1267,7 @@ int dwc_usb_change(struct notifier_block *nb, if (value) { DWC_DEBUGPL(DBG_PCDV, "start usb device\n"); dwc_otg_enable_global_interrupts(otg_dev->core_if); - if (otg_dev->core_if->phy_interface == 0) + if (otg_dev->core_if->phy_interface != 0) dwc_otg_enable_device_interrupts(otg_dev->core_if); otg_dev->pcd->core_if->pcd_cb->start(otg_dev->pcd); } else { @@ -1275,7 +1275,7 @@ int dwc_usb_change(struct notifier_block *nb, dwc_otg_disable_global_interrupts(otg_dev->core_if); /* Disable all interrupts. */ - if (otg_dev->core_if->phy_interface == 0) + if (otg_dev->core_if->phy_interface != 0) DWC_WRITE_REG32(&global_regs->gintmsk, 0); otg_dev->pcd->core_if->pcd_cb->stop(otg_dev->pcd); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index 46a42249dd14..82fc567f8b52 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -38,6 +38,10 @@ void set_usb_phy_host_tuning(int port, int default_val) if (!g_phy2_v2) return; + + if (g_phy2_v2->phy_version == 1) + return; + if (port > g_phy2_v2->portnum) return; if (default_val == g_phy2_v2->phy_cfg_state[port]) @@ -63,6 +67,10 @@ void set_usb_phy_device_tuning(int port, int default_val) if (!g_phy2_v2) return; + + if (g_phy2_v2->phy_version == 1) + return; + if (port > g_phy2_v2->portnum) return; if (default_val == g_phy2_v2->phy_cfg_state[port]) @@ -111,10 +119,15 @@ static int amlogic_new_usb2_init(struct usb_phy *x) union u2p_r0_v2 reg0; union u2p_r1_v2 reg1; u32 val; + u32 temp = 0; + u32 portnum = phy->portnum; + + while (portnum--) + temp = temp | (1 << (16 + portnum)); val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); - writel((val | (0x3 << 16)), (void __iomem *) + writel((val | temp), (void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); amlogic_new_usbphy_reset_v2(phy); @@ -183,11 +196,16 @@ static void amlogic_new_usb2phy_shutdown(struct usb_phy *x) { struct amlogic_usb_v2 *phy = phy_to_amlusb(x); u32 val; + u32 temp = 0; + u32 cnt = phy->portnum; + + while (cnt--) + temp = temp | (1 << (16 + cnt)); /* set usb phy to low power mode */ val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); - writel((val & (~(0x3 << 16))), (void __iomem *) + writel((val & (~temp)), (void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); phy->suspend_flag = 1; @@ -204,6 +222,7 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) void __iomem *reset_base = NULL; void __iomem *phy_cfg_base[4]; int portnum = 0; + int phy_version = 0; const void *prop; int i = 0; int retval; @@ -218,6 +237,12 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) return -ENOMEM; } + prop = of_get_property(dev->of_node, "version", NULL); + if (prop) + phy_version = of_read_ulong(prop, 1); + else + phy_version = 0; + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); phy_base = devm_ioremap_resource(dev, phy_mem); if (IS_ERR(phy_base)) @@ -308,6 +333,7 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) phy->pll_setting[6] = pll_setting[6]; phy->pll_setting[7] = pll_setting[7]; phy->suspend_flag = 0; + phy->phy_version = phy_version; for (i = 0; i < portnum; i++) { phy->phy_cfg[i] = phy_cfg_base[i]; /* set port default tuning state */ diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 840351d5b27b..dae41a3f1e04 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -944,7 +944,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, struct xhci_command *command, if (!virt_dev) return -EINVAL; if (!command) - command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); + command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); if (!command) return -ENOMEM; @@ -980,7 +980,6 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, { __le32 __iomem **port_array; u32 temp; - unsigned long flags = 0; port_array = xhci->usb2_ports; temp = readl(port_array[index]); @@ -994,14 +993,6 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, /* Power off */ writel(temp & ~PORT_POWER, port_array[index]); } - - spin_unlock_irqrestore(&xhci->lock, flags); - temp = usb_acpi_power_manageable(hcd->self.root_hub, - index); - if (temp) - usb_acpi_set_power_state(hcd->self.root_hub, - index, on); - spin_lock_irqsave(&xhci->lock, flags); } @@ -1070,7 +1061,6 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, __le32 __iomem **port_array = xhci->usb2_ports; /* 15 second delay per the test spec */ - spin_unlock_irqrestore(&xhci->lock, flags); xhci_err(xhci, "into suspend\n"); spin_lock_irqsave(&xhci->lock, flags); @@ -1091,6 +1081,7 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, temp = readl(port_array[wIndex]); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) || (temp & PORT_PLS_MASK) >= XDEV_U3) { + spin_unlock_irqrestore(&xhci->lock, flags); xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n"); return -1; } @@ -1098,6 +1089,7 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, slot_id = xhci_find_slot_id_by_port(hcd, xhci, wIndex + 1); if (!slot_id) { + spin_unlock_irqrestore(&xhci->lock, flags); xhci_warn(xhci, "slot_id is zero\n"); return -1; } @@ -1122,11 +1114,15 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, temp = readl(port_array[wIndex]); xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); xhci_dbg(xhci, "PORTSC %04x\n", temp); - if (temp & PORT_RESET) + if (temp & PORT_RESET) { + spin_unlock_irqrestore(&xhci->lock, flags); return -1; + } if ((temp & PORT_PLS_MASK) == XDEV_U3) { - if ((temp & PORT_PE) == 0) + if ((temp & PORT_PE) == 0) { + spin_unlock_irqrestore(&xhci->lock, flags); return -1; + } xhci_set_link_state(xhci, port_array, wIndex, XDEV_RESUME); @@ -1138,6 +1134,7 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, } xhci_ring_device(xhci, slot_id); + spin_unlock_irqrestore(&xhci->lock, flags); return 0; } #endif @@ -1426,8 +1423,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, else if (test_mode == 5) xhci_port_set_test_mode(xhci, test_mode, wIndex); - else + else { + spin_unlock_irqrestore(&xhci->lock, flags); retval = xhci_test_suspend_resume(hcd, wIndex); + spin_lock_irqsave(&xhci->lock, flags); + } break; #endif default: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 08b719d7daed..40d2804ede72 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3398,16 +3398,22 @@ int xhci_test_single_step(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_td *td; unsigned long flags = 0; + spin_lock_irqsave(&xhci->lock, flags); + ep_ring = xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) + if (!ep_ring) { + spin_unlock_irqrestore(&xhci->lock, flags); return -EINVAL; + } /* * Need to copy setup packet into setup TRB, so we can't use the setup * DMA address. */ - if (!urb->setup_packet) + if (!urb->setup_packet) { + spin_unlock_irqrestore(&xhci->lock, flags); return -EINVAL; + } /* 1 TRB for setup, 1 for status */ num_trbs = 2; @@ -3421,8 +3427,10 @@ int xhci_test_single_step(struct xhci_hcd *xhci, gfp_t mem_flags, ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, mem_flags); - if (ret < 0) + if (ret < 0) { + spin_unlock_irqrestore(&xhci->lock, flags); return ret; + } urb_priv = urb->hcpriv; td = urb_priv->td[0]; @@ -3527,14 +3535,12 @@ int xhci_test_single_step(struct xhci_hcd *xhci, gfp_t mem_flags, giveback_first_trb(xhci, slot_id, ep_index, 0, start_cycle, start_trb); - /* 15 second delay per the test spec */ - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_err(xhci, "step 3\n"); - msleep(15000); - spin_lock_irqsave(&xhci->lock, flags); + /* 15 second delay per the test spec */ + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_err(xhci, "step 3\n"); + msleep(15000); return 0; - } #endif diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8127950cc487..f273d6743791 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1455,14 +1455,18 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) && (setup->wIndex != 0x0)) { if ((((setup->wIndex)>>8) & 0xff) == 7) { setup->wIndex = 0; + spin_unlock_irqrestore(&xhci->lock, flags); ret = xhci_test_single_step(xhci, GFP_ATOMIC, urb, slot_id, ep_index, 1); + spin_lock_irqsave(&xhci->lock, flags); } else if ((((setup->wIndex)>>8)&0xff) == 8) { setup->wIndex = 0; + spin_unlock_irqrestore(&xhci->lock, flags); ret = xhci_test_single_step(xhci, GFP_ATOMIC, urb, slot_id, ep_index, 2); + spin_lock_irqsave(&xhci->lock, flags); } } else #endif diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index b0be4770ec26..f3e8f0857d1e 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -179,6 +179,7 @@ struct amlogic_usb_v2 { int portnum; int suspend_flag; + int phy_version; struct clk *clk; }; From 714d504ffe4cb2099184d15a48adfc3e3dd2bd26 Mon Sep 17 00:00:00 2001 From: Kaifu Hu Date: Thu, 20 Dec 2018 13:20:53 +0800 Subject: [PATCH 0038/1060] dv: dolby vision support on t962x [1/1] PD#SWPL-3318 Problem: Android P not support dolby vision on t962x Solution: Porting code support dolby vision Verify: t962x/r311 Change-Id: I85afd05d2cb21a7105ea345f07e7e581bba5e927 Signed-off-by: Kaifu Hu --- .../amdolby_vision/amdolby_vision.c | 242 ++++++++++++++++-- .../amdolby_vision/amdolby_vision.h | 2 +- 2 files changed, 228 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index d4d1c5861d7b..bc928e59aeb8 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -51,7 +51,9 @@ #include #include #include /* for parse_para_pq */ +#include #include +#include DEFINE_SPINLOCK(dovi_lock); @@ -576,6 +578,204 @@ struct TargetDisplayConfig def_tgt_display_cfg = { 0, /* chip_nolvl5 */ {0, 0, 0, 0, 0, 0, 0, 0} /* padding[8] */ }; +struct TargetDisplayConfig def_tgt_display_cfg_ll = { + 4095, /* gain */ + 0, /* offset */ + 39322, /* gamma */ + 2, /* eotf */ + 12, /* bitDepth */ + 0, /* rangeSpec */ + 42, /* diagSize */ + 2873, /* maxPq */ + 263, /* minPq */ + 2048, /* mSWeight */ + 16380, /* mSEdgeWeight */ + 0, /* minPQBias */ + 0, /* midPQBias */ + 0, /* maxPQBias */ + 0, /* trimSlopeBias */ + 0, /* trimOffsetBias */ + 0, /* trimPowerBias */ + 0, /* msWeightBias */ + 0, /* brightness */ + 0, /* contrast */ + 0, /* chromaWeightBias */ + 0, /* saturationGainBias */ + 2048, /* chromaWeight */ + 2048, /* saturationGain */ + 655, /* crossTalk */ + 0, /* tuningMode */ + 0, /* reserved0 */ + 0, /* dbgExecParamsPrintPeriod */ + 0, /* dbgDmMdPrintPeriod */ + 0, /* dbgDmCfgPrintPeriod */ + 2873, /* maxPq_dupli */ + 263, /* minPq_dupli */ + 12288, /* keyWeight */ + 24576, /* intensityVectorWeight */ + 24576, /* chromaVectorWeight */ + 0, /* chip_fpga_lowcomplex */ + { + -245, + -208, + -171, + -130, + -93, + -56, + -19, + 20, + 57, + 94, + 131, + 172, + 209, + 246, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + -3685, + -3070, + -2456, + -1842, + -1228, + -613, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 1, /* gdEnable */ + 4452, /* gdWMin */ + 165150720, /* gdWMax */ + 26214400, /* gdWMm */ + 20114920, /* gdWDynRngSqrt */ + 4096, /* gdWeightMean */ + 4096, /* gdWeightStd */ + 0, /* gdDelayMilliSec_hdmi */ + 1, /* gdRgb2YuvExt */ + { + {5967, 20067, 2026}, + {-3289, -11061, 14350}, + {14350, -13034, -1316} + }, /* gdM33Rgb2Yuv[3][3] */ + 15, /* gdM33Rgb2YuvScale2P */ + 1, /* gdRgb2YuvOffExt */ + {2048, 16384, 16384},/* gdV3Rgb2YuvOff[3] */ + 2152296, /* gdUpBound */ + 341634, /* gdLowBound */ + 0, /* lastMaxPq */ + 114, /*gdWMinPq */ + 2873, /*gdWMaxPq */ + 2081, /*gdWMmPq */ + 0, /*gdTriggerPeriod */ + 0, /* gdTriggerLinThresh */ + 0, /* gdDelayMilliSec_ott */ +#ifdef V1_5 + {0, 0, 0, 0, 0, 0}, +#else + {0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + }, +#ifdef V1_5 + {36, 23, 83, 181, 139, 88, 101}, + {0, 0, 0, 0, 0}, +#endif + 28049, /* min_lin */ + 165150720, /* max_lin */ + 0, /* backlight_scaler */ + 28049, /* min_lin_dupli */ + 165150720, /* max_lin_dupli */ + { + /* lms2RgbMat[3][3] */ + { + {17486, -13950, 560}, + {-4081, 8776, -599}, + {257, -562, 4401} + }, + 12, /* lms2RgbMatScale */ + {128, 128, 128}, /* whitePoint */ + 7, /* whitePointScale */ + {0, 0, 0} /* reserved[3] */ + }, + 0, /* reserved00 */ + 0, /* brightnessPreservation */ + 81920, /* iintensityVectorWeight */ + 24576, /* ichromaVectorWeight */ + 0, /* isaturationGainBias */ + 0, /* chip_12b_ocsc */ + 0, /* chip_512_tonecurve */ + 0, /* chip_nolvl5 */ + {0, 0, 0, 0, 0, 0, 0, 0} /* padding[8] */ +}; + #else struct TargetDisplayConfig def_tgt_display_cfg = { 2048, /* gain */ @@ -2479,7 +2679,7 @@ void enable_dolby_vision(int enable) /* 12->10 before vadj2*/ /* 10->12 after gainoff */ VSYNC_WR_MPEG_REG( - VPP_DAT_CONV_PARA1, 0x08000800); + VPP_DAT_CONV_PARA1, 0x20002000); WRITE_VPP_REG(0x33e7, 0xb); } else { /* bypass all video effect */ @@ -2493,7 +2693,7 @@ void enable_dolby_vision(int enable) /* 12->10 before vadj2*/ /* 10->12 after gainoff */ VSYNC_WR_MPEG_REG( - VPP_DAT_CONV_PARA1, 0x08000800); + VPP_DAT_CONV_PARA1, 0x20002000); } VSYNC_WR_MPEG_REG( VPP_DUMMY_DATA1, @@ -4572,6 +4772,10 @@ int dolby_vision_parse_metadata( u32 graphic_min = 50; /* 0.0001 */ u32 graphic_max = 100; /* 1 */ int ret_flags = 0; + int ret = -1; + + memset(&req, 0, (sizeof(struct provider_aux_req_s))); + memset(&el_req, 0, (sizeof(struct provider_aux_req_s))); if (!dolby_vision_enable) return -1; @@ -4895,8 +5099,18 @@ int dolby_vision_parse_metadata( /* TV core */ if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (src_format != ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format) + pq_config_set_flag = false; if (!pq_config_set_flag) { - memcpy(&(((struct pq_config_s *) + if ((dolby_vision_flags & FLAG_FORCE_DOVI_LL) + || (req.low_latency == 1)) + memcpy(&(((struct pq_config_s *) + pq_config_fake)->target_display_config), + &def_tgt_display_cfg_ll, + sizeof(def_tgt_display_cfg_ll)); + else + memcpy(&(((struct pq_config_s *) pq_config_fake)->target_display_config), &def_tgt_display_cfg, sizeof(def_tgt_display_cfg)); @@ -5031,7 +5245,7 @@ int dolby_vision_parse_metadata( (struct tv_dovi_setting_s *)tv_dovi_setting, frame_count, debug_dolby); el_mode = el_flag; - return 0; /* setting updated */ + ret = 0; /* setting updated */ } else { ((struct tv_dovi_setting_s *) tv_dovi_setting)->video_width = 0; @@ -5039,7 +5253,7 @@ int dolby_vision_parse_metadata( tv_dovi_setting)->video_height = 0; pr_dolby_error("tv_control_path() failed\n"); } - return -1; + return ret; } /* STB core */ @@ -5368,8 +5582,8 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) if (dolby_vision_flags & FLAG_SINGLE_STEP) /* wait fake el for "step" */ return 1; - else - dolby_vision_flags |= FLAG_SINGLE_STEP; + + dolby_vision_flags |= FLAG_SINGLE_STEP; } if (dolby_vision_flags & FLAG_CERTIFICAION) { @@ -5996,16 +6210,14 @@ int register_dv_functions(const struct dolby_vision_func_s *func) dolby_vision_run_mode_delay = RUN_MODE_DELAY; pq_config = vmalloc(sizeof(struct pq_config_s)); - if (pq_config == NULL) { - pr_info("[amdolby_vision] vmalloc failed for pq_config_s error!\n"); - return -1; - } + if (!pq_config) + return -ENOMEM; + pq_config_fake = (struct pq_config_s *)pq_config; dovi_setting = vmalloc(sizeof(struct tv_dovi_setting_s)); - if (dovi_setting == NULL) { - pr_info("[amdolby_vision] vmalloc failed for tv_dovi_setting_s error!\n"); - return -1; - } + if (!dovi_setting) + return -ENOMEM; + tv_dovi_setting = (struct tv_dovi_setting_s *)dovi_setting; /* adjust core2 setting to work around fixing with 1080p24hz */ if (is_meson_txlx()) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h index 7aee3dffd2ed..a6ad2c6f695b 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h @@ -20,7 +20,7 @@ #define V1_5 #define V2_4 /* driver version */ -#define DRIVER_VER "20181009" +#define DRIVER_VER "20181220" #include From 3b1a8384c0dacc1150a5e418f2b0bfd1d90d70e5 Mon Sep 17 00:00:00 2001 From: yuehu mi Date: Thu, 17 Jan 2019 20:51:44 +0800 Subject: [PATCH 0039/1060] usb: remove usbphy reset 500ms wait [1/1] PD#SWPL-4949 Problem: kernel slow startup Solution: remove usbphy reset 500ms wait Verify: marconi platform insert U disk, power on boot verify OK Change-Id: Ieb01e59ad428f98c3df303c7b3bee28397970c74 Signed-off-by: yuehu mi --- drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c index e862717202c3..0b4e372a0a89 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c @@ -30,7 +30,6 @@ int amlogic_new_usbphy_reset_v2(struct amlogic_usb_v2 *phy) { static int init_count; - int i = 0; if (!init_count) { init_count++; @@ -39,8 +38,6 @@ int amlogic_new_usbphy_reset_v2(struct amlogic_usb_v2 *phy) else writel((readl(phy->reset_regs) | (0x1 << 2)), phy->reset_regs); - for (i = 0; i < 1000; i++) - udelay(500); } return 0; From eaadc628dd61b9fcc9e1daea111ed444a652cc0d Mon Sep 17 00:00:00 2001 From: Qiufang Dai Date: Wed, 23 Jan 2019 21:39:38 +0800 Subject: [PATCH 0040/1060] cpuversion: add SoC rev api [1/2] PD#SWPL-4582 Problem: Need api to distinguish G12B revB Solution: Add rev A/B/C api Verify: W400 Change-Id: I5cf82fcfc513f621513914cf83d18fe5c5ec081d Signed-off-by: Qiufang Dai --- include/linux/amlogic/cpu_version.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index 3aef138e0a6a..5fce9f051df8 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -15,6 +15,9 @@ * */ +/* + * All of these api should be call after early_initcall stage + */ #ifndef __PLAT_MESON_CPU_H #define __PLAT_MESON_CPU_H @@ -199,4 +202,20 @@ static inline bool is_meson_txlx_package_962E(void) { return is_meson_txlx_cpu() && package_id_is(0x20); } + +static inline bool is_meson_rev_a(void) +{ + return (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == 0xA); +} + +static inline bool is_meson_rev_b(void) +{ + return (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == 0xB); +} + +static inline bool is_meson_rev_c(void) +{ + return (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == 0xC); +} + #endif From 0fed2b7bc8578ca389bd439409eb2f2e327f2cda Mon Sep 17 00:00:00 2001 From: "he.he" Date: Fri, 25 Jan 2019 15:44:08 +0800 Subject: [PATCH 0041/1060] usb: check SoC rev [1/2] PD#SWPL-4582 Problem: Need to check Soc rev to distinguish G12B revB. Solution: Check Soc rev set version and phy-interface for g12b revB. Test: make w400 bootimage Verify: pass on W400 Change-Id: I338d7f0eed7bb61660625343404f756f0edf0d54 Signed-off-by: he.he --- drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c | 6 ++++++ drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c index d4ea8162d0ec..3ce109bf851f 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c @@ -71,6 +71,7 @@ #include #include #include +#include #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND #include #endif @@ -1058,6 +1059,11 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) if (prop) phy_interface = of_read_ulong(prop, 1); + if (is_meson_g12b_cpu()) { + if (!is_meson_rev_a()) + phy_interface = 2; + } + dwc_otg_module_params.host_rx_fifo_size = dwc_otg_module_params.data_fifo_size / 2; DWC_PRINTF("dwc_otg: %s: type: %d speed: %d, ", s_clock_name, port_type, port_speed); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index 82fc567f8b52..787da97d9a7d 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "phy-aml-new-usb-v2.h" struct amlogic_usb_v2 *g_phy2_v2; @@ -243,6 +244,11 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) else phy_version = 0; + if (is_meson_g12b_cpu()) { + if (!is_meson_rev_a()) + phy_version = 1; + } + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); phy_base = devm_ioremap_resource(dev, phy_mem); if (IS_ERR(phy_base)) From bf4746e9cc789db3b2406fe8f59ddfadcac27f2e Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Mon, 14 Jan 2019 17:07:48 +0800 Subject: [PATCH 0042/1060] osd: add g12b revb to check osd shift workaround [1/1] PD#SWPL-4582 Problem: g12b revb fix osd blend shift issue Solution: add g12b revb to remove shift workaround Verify: verify by g12b revb Change-Id: I6cefba0b5b5cce35d928edafdc359adff0165866 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_backup.c | 2 +- drivers/amlogic/media/osd/osd_hw.c | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_backup.c b/drivers/amlogic/media/osd/osd_backup.c index 9ad324fe651a..8209c6e206b8 100644 --- a/drivers/amlogic/media/osd/osd_backup.c +++ b/drivers/amlogic/media/osd/osd_backup.c @@ -648,7 +648,7 @@ static struct reg_item osd3_afbcd_recovery_table_g12a[] = { 0x0, 0x0000ffff, 1 }, { - VPU_MAFBC_PREFETCH_CFG_S1, 0x0, 3, 1 + VPU_MAFBC_PREFETCH_CFG_S2, 0x0, 3, 1 } }; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index c62d11dbd947..9877afcda693 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -33,7 +33,7 @@ #include #include #include - +#include /* Android Headers */ /* Amlogic sync headers */ @@ -4441,12 +4441,8 @@ static void osd_update_disp_freescale_enable(u32 index) else vf_bank_len = 4; - if (osd_hw.hwc_enable && (index == OSD1) - && ((osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12A) || - (osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12B))) - shift_workaround = 1; + if (osd_hw.hwc_enable && (index == OSD1)) + shift_workaround = osd_hw.workaround_line; #ifndef NEW_PPS_PHASE if (osd_hw.bot_type == 1) { @@ -6398,7 +6394,7 @@ static void osd_set_freescale(u32 index, struct layer_blend_reg_s *blend_reg; u32 width, height; u32 src_height; - u32 workaround_line = 1; + u32 workaround_line = osd_hw.workaround_line; layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -6583,12 +6579,12 @@ static void osd_setting_blend1_input(u32 index, /* for g12a blend shift issue */ if (osd_hw.hdr_used) - workaround_line = 1; + workaround_line = osd_hw.workaround_line; else { if (blending->layer_cnt == 2) workaround_line = 0; else - workaround_line = 1; + workaround_line = osd_hw.workaround_line; } layer_blend = &(blending->layer_blend); @@ -8481,13 +8477,13 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.disp_info.position_h = 1080; osd_hw.vinfo_width = 1920; osd_hw.vinfo_height = 1080; + osd_hw.workaround_line = 0; if ((osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12A) || - (osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12B)) + ((osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B) && + is_meson_rev_a())) osd_hw.workaround_line = 1; - else - osd_hw.workaround_line = 0; for (idx = 0; idx < osd_hw.osd_meson_dev.osd_count; idx++) { osd_hw.premult_en[idx] = 0; osd_hw.osd_afbcd[idx].format = COLOR_INDEX_32_ABGR; From 3db9388b5059b2b391c6b4f03f38fbbefd86c842 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Mon, 25 Feb 2019 20:02:11 +0800 Subject: [PATCH 0043/1060] dv: remove g12b ver B from the status of SDR mode [1/1] PD#SWPL-4582 Problem: g12 verA has a hardware bug.Therefore,dv cores must keep working even if under sdr mode Solution: g12B verB has fixed this bug, so remove this chip id Verify: verify by g12b revb Change-Id: Ice1aa1364319fa12d5a896fdfd106450f1a04d3d Signed-off-by: Yi Zhou --- .../media/enhancement/amdolby_vision/amdolby_vision.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index bc928e59aeb8..95655f5b1df5 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -3712,8 +3712,9 @@ static int dolby_vision_policy_process( *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; mode_change = 1; } - } else if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { - /*g12 has a hardware bug. Therefore, dv cores + } else if ((is_meson_g12b_cpu() && is_meson_rev_a()) || + is_meson_g12a_cpu()) { + /*g12 verA has a hardware bug.Therefore,dv cores *must keep working even if under sdr mode */ if (dolby_vision_mode != From f2385277a5528f2d8b9defec7bc378992819f7cf Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Wed, 20 Feb 2019 09:38:02 +0800 Subject: [PATCH 0044/1060] rdma: used line_n_int to trigger osd, dv and hdr rdma [1/2] PD#SWPL-4582 Problem: g12b revb osd blend shift issue still exist when dv and hdr enable/disable Solution: used line_n_int to trigger osd, dv and hdr rdma, this workaround can fix shift issue Verify: verify by g12b revb Change-Id: Ie9747b2f7aaa3a7997245f82d15831c4c3da41cf Signed-off-by: Pengcheng Chen --- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 2 +- drivers/amlogic/media/common/rdma/rdma.c | 367 +++++++--- drivers/amlogic/media/common/rdma/rdma.h | 9 +- drivers/amlogic/media/common/rdma/rdma_mgr.c | 35 +- .../amdolby_vision/amdolby_vision.c | 679 +++++++++--------- .../amdolby_vision/amdolby_vision.h | 12 +- drivers/amlogic/media/osd/osd.h | 1 + drivers/amlogic/media/osd/osd_fb.c | 35 +- drivers/amlogic/media/osd/osd_hw.c | 18 +- drivers/amlogic/media/osd/osd_hw.h | 2 + drivers/amlogic/media/osd/osd_rdma.c | 54 +- drivers/amlogic/media/osd/osd_rdma.h | 3 + include/linux/amlogic/media/rdma/rdma_mgr.h | 8 + 14 files changed, 779 insertions(+), 448 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index c0b5e085e44c..5a51224e02e4 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1360,7 +1360,7 @@ }; rdma{ - compatible = "amlogic, meson, rdma"; + compatible = "amlogic, meson-g12b, rdma"; dev_name = "amlogic-rdma"; status = "okay"; interrupts = <0 89 1>; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 8625f5c00df4..74b706c976cb 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1370,7 +1370,7 @@ }; rdma{ - compatible = "amlogic, meson, rdma"; + compatible = "amlogic, meson-g12b, rdma"; dev_name = "amlogic-rdma"; status = "okay"; interrupts = <0 89 1>; diff --git a/drivers/amlogic/media/common/rdma/rdma.c b/drivers/amlogic/media/common/rdma/rdma.c index 83d3420e3902..21fece89cea2 100644 --- a/drivers/amlogic/media/common/rdma/rdma.c +++ b/drivers/amlogic/media/common/rdma/rdma.c @@ -47,140 +47,225 @@ #define Wr_reg_bits(adr, val, start, len) \ WRITE_VCBUS_REG_BITS(adr, val, start, len) -static int vsync_rdma_handle; -static int irq_count; -static int enable; -static int cur_enable; -static int pre_enable_; -static int debug_flag; -static int vsync_cfg_count; -static u32 force_rdma_config; -static bool first_config; -static bool rdma_done; +#define RDMA_NUM 2 +static int second_rdma_feature; +static int rdma_num = RDMA_NUM; +static int vsync_rdma_handle[RDMA_NUM]; +static int irq_count[RDMA_NUM]; +static int enable[RDMA_NUM]; +static int cur_enable[RDMA_NUM]; +static int pre_enable_[RDMA_NUM]; +static int debug_flag[RDMA_NUM]; +static int vsync_cfg_count[RDMA_NUM]; +static u32 force_rdma_config[RDMA_NUM]; +static bool first_config[RDMA_NUM]; +static bool rdma_done[RDMA_NUM]; static void vsync_rdma_irq(void *arg); +static void line_n_int_rdma_irq(void *arg); struct rdma_op_s vsync_rdma_op = { vsync_rdma_irq, NULL }; +struct rdma_op_s line_n_int_rdma_op = { + line_n_int_rdma_irq, + NULL +}; -void vsync_rdma_config(void) +static void set_rdma_trigger_line(void) +{ + int trigger_line; + + switch (aml_read_vcbus(VPU_VIU_VENC_MUX_CTRL) & 0x3) { + case 0: + trigger_line = aml_read_vcbus(ENCL_VIDEO_VAVON_ELINE) + - aml_read_vcbus(ENCL_VIDEO_VSO_BLINE); + break; + case 1: + if ((aml_read_vcbus(ENCI_VIDEO_MODE) & 1) == 0) + trigger_line = 260; /* 480i */ + else + trigger_line = 310; /* 576i */ + break; + case 2: + if (aml_read_vcbus(ENCP_VIDEO_MODE) & (1 << 12)) + trigger_line = aml_read_vcbus(ENCP_DE_V_END_EVEN); + else + trigger_line = aml_read_vcbus(ENCP_VIDEO_VAVON_ELINE) + - aml_read_vcbus(ENCP_VIDEO_VSO_BLINE); + break; + case 3: + trigger_line = aml_read_vcbus(ENCT_VIDEO_VAVON_ELINE) + - aml_read_vcbus(ENCT_VIDEO_VSO_BLINE); + break; + } + aml_write_vcbus(VPP_INT_LINE_NUM, trigger_line); +} + +void _vsync_rdma_config(int rdma_type) { int iret = 0; - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[rdma_type] & 0xf; - if (vsync_rdma_handle <= 0) + if (vsync_rdma_handle[rdma_type] <= 0) return; /* first frame not use rdma */ - if (!first_config) { - cur_enable = enable; - pre_enable_ = enable_; - first_config = true; - rdma_done = false; + if (!first_config[rdma_type]) { + cur_enable[rdma_type] = enable[rdma_type]; + pre_enable_[rdma_type] = enable_; + first_config[rdma_type] = true; + rdma_done[rdma_type] = false; return; } /* if rdma mode changed, reset rdma */ - if (pre_enable_ != enable_) { - rdma_clear(vsync_rdma_handle); - force_rdma_config = 1; + if (pre_enable_[rdma_type] != enable_) { + rdma_clear(vsync_rdma_handle[rdma_type]); + force_rdma_config[rdma_type] = 1; } - if (force_rdma_config) - rdma_done = true; + if (force_rdma_config[rdma_type]) + rdma_done[rdma_type] = true; if (enable_ == 1) { - if (rdma_done) + if (rdma_done[rdma_type]) iret = rdma_watchdog_setting(0); else iret = rdma_watchdog_setting(1); } else { /* not vsync mode */ iret = rdma_watchdog_setting(0); - force_rdma_config = 1; + force_rdma_config[rdma_type] = 1; } - rdma_done = false; + rdma_done[rdma_type] = false; if (iret) - force_rdma_config = 1; + force_rdma_config[rdma_type] = 1; iret = 0; - if (force_rdma_config) { + if (force_rdma_config[rdma_type]) { if (enable_ == 1) { - iret = rdma_config(vsync_rdma_handle, - RDMA_TRIGGER_VSYNC_INPUT); + if (rdma_type == VSYNC_RDMA) + iret = rdma_config(vsync_rdma_handle[rdma_type], + RDMA_TRIGGER_VSYNC_INPUT); + else if (rdma_type == LINE_N_INT_RDMA) { + set_rdma_trigger_line(); + iret = rdma_config(vsync_rdma_handle[rdma_type], + RDMA_TRIGGER_LINE_INPUT); + } if (iret) - vsync_cfg_count++; + vsync_cfg_count[rdma_type]++; } else if (enable_ == 2) /*manually in cur vsync*/ - rdma_config(vsync_rdma_handle, + rdma_config(vsync_rdma_handle[rdma_type], RDMA_TRIGGER_MANUAL); else if (enable_ == 3) ; else if (enable_ == 4) - rdma_config(vsync_rdma_handle, + rdma_config(vsync_rdma_handle[rdma_type], RDMA_TRIGGER_DEBUG1); /*for debug*/ else if (enable_ == 5) - rdma_config(vsync_rdma_handle, + rdma_config(vsync_rdma_handle[rdma_type], RDMA_TRIGGER_DEBUG2); /*for debug*/ else if (enable_ == 6) ; if (!iret) - force_rdma_config = 1; + force_rdma_config[rdma_type] = 1; else - force_rdma_config = 0; + force_rdma_config[rdma_type] = 0; } - pre_enable_ = enable_; - cur_enable = enable; + pre_enable_[rdma_type] = enable_; + cur_enable[rdma_type] = enable[rdma_type]; } + +void vsync_rdma_config(void) +{ + _vsync_rdma_config(VSYNC_RDMA); + if (second_rdma_feature && + is_meson_g12b_revb()) + _vsync_rdma_config(LINE_N_INT_RDMA); +} + EXPORT_SYMBOL(vsync_rdma_config); +void _vsync_rdma_config_pre(int rdma_type) +{ + int enable_ = cur_enable[rdma_type] & 0xf; + + if (vsync_rdma_handle[rdma_type] == 0) + return; + if (enable_ == 3)/*manually in next vsync*/ + rdma_config(vsync_rdma_handle[rdma_type], 0); + else if (enable_ == 6) + rdma_config(vsync_rdma_handle[rdma_type], 0x101); /*for debug*/ +} + void vsync_rdma_config_pre(void) { - int enable_ = cur_enable & 0xf; - - if (vsync_rdma_handle == 0) - return; - if (enable_ == 3)/*manually in next vsync*/ - rdma_config(vsync_rdma_handle, 0); - else if (enable_ == 6) - rdma_config(vsync_rdma_handle, 0x101); /*for debug*/ + _vsync_rdma_config_pre(VSYNC_RDMA); + if (second_rdma_feature && + is_meson_g12b_revb()) + _vsync_rdma_config_pre(LINE_N_INT_RDMA); } EXPORT_SYMBOL(vsync_rdma_config_pre); static void vsync_rdma_irq(void *arg) { int iret; - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; if (enable_ == 1) { /*triggered by next vsync*/ - iret = rdma_config(vsync_rdma_handle, + iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA], RDMA_TRIGGER_VSYNC_INPUT); if (iret) - vsync_cfg_count++; + vsync_cfg_count[VSYNC_RDMA]++; } else - iret = rdma_config(vsync_rdma_handle, 0); - pre_enable_ = enable_; + iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA], 0); + pre_enable_[VSYNC_RDMA] = enable_; if ((!iret) || (enable_ != 1)) - force_rdma_config = 1; + force_rdma_config[VSYNC_RDMA] = 1; else - force_rdma_config = 0; - rdma_done = true; - irq_count++; + force_rdma_config[VSYNC_RDMA] = 0; + rdma_done[VSYNC_RDMA] = true; + irq_count[VSYNC_RDMA]++; return; } +static void line_n_int_rdma_irq(void *arg) +{ + int iret; + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + if (enable_ == 1) { + /*triggered by next vsync*/ + //set_rdma_trigger_line(); + iret = rdma_config(vsync_rdma_handle[LINE_N_INT_RDMA], + RDMA_TRIGGER_LINE_INPUT); + if (iret) + vsync_cfg_count[LINE_N_INT_RDMA]++; + } else + iret = rdma_config(vsync_rdma_handle[LINE_N_INT_RDMA], 0); + pre_enable_[LINE_N_INT_RDMA] = enable_; + + if ((!iret) || (enable_ != 1)) + force_rdma_config[LINE_N_INT_RDMA] = 1; + else + force_rdma_config[LINE_N_INT_RDMA] = 0; + rdma_done[VSYNC_RDMA] = true; + irq_count[VSYNC_RDMA]++; +} + u32 VSYNC_RD_MPEG_REG(u32 adr) { - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; u32 read_val = Rd(adr); - if ((enable_ != 0) && (vsync_rdma_handle > 0)) - read_val = rdma_read_reg(vsync_rdma_handle, adr); + if ((enable_ != 0) && (vsync_rdma_handle[VSYNC_RDMA] > 0)) + read_val = rdma_read_reg(vsync_rdma_handle[VSYNC_RDMA], adr); return read_val; } @@ -188,13 +273,13 @@ EXPORT_SYMBOL(VSYNC_RD_MPEG_REG); int VSYNC_WR_MPEG_REG(u32 adr, u32 val) { - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; - if ((enable_ != 0) && (vsync_rdma_handle > 0)) { - rdma_write_reg(vsync_rdma_handle, adr, val); + if ((enable_ != 0) && (vsync_rdma_handle[VSYNC_RDMA] > 0)) { + rdma_write_reg(vsync_rdma_handle[VSYNC_RDMA], adr, val); } else { Wr(adr, val); - if (debug_flag & 1) + if (debug_flag[VSYNC_RDMA] & 1) pr_info("VSYNC_WR(%x)<=%x\n", adr, val); } return 0; @@ -203,27 +288,94 @@ EXPORT_SYMBOL(VSYNC_WR_MPEG_REG); int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len) { - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; - if ((enable_ != 0) && (vsync_rdma_handle > 0)) { - rdma_write_reg_bits(vsync_rdma_handle, adr, val, start, len); + if ((enable_ != 0) && (vsync_rdma_handle[VSYNC_RDMA] > 0)) { + rdma_write_reg_bits(vsync_rdma_handle[VSYNC_RDMA], + adr, val, start, len); } else { u32 read_val = Rd(adr); u32 write_val = (read_val & ~(((1L<<(len))-1)<<(start))) |((unsigned int)(val) << (start)); Wr(adr, write_val); - if (debug_flag & 1) + if (debug_flag[VSYNC_RDMA] & 1) pr_info("VSYNC_WR(%x)<=%x\n", adr, write_val); } return 0; } EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_BITS); +u32 _VSYNC_RD_MPEG_REG(u32 adr) +{ + u32 read_val = 0; + + if (second_rdma_feature && is_meson_g12b_revb()) { + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + read_val = Rd(adr); + + if ((enable_ != 0) && + (vsync_rdma_handle[LINE_N_INT_RDMA] > 0)) + read_val = rdma_read_reg + (vsync_rdma_handle[LINE_N_INT_RDMA], adr); + } else { + read_val = VSYNC_RD_MPEG_REG(adr); + } + return read_val; +} +EXPORT_SYMBOL(_VSYNC_RD_MPEG_REG); + +int _VSYNC_WR_MPEG_REG(u32 adr, u32 val) +{ + if (second_rdma_feature && is_meson_g12b_revb()) { + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + if ((enable_ != 0) && + (vsync_rdma_handle[LINE_N_INT_RDMA] > 0)) { + rdma_write_reg + (vsync_rdma_handle[LINE_N_INT_RDMA], adr, val); + } else { + Wr(adr, val); + if (debug_flag[LINE_N_INT_RDMA] & 1) + pr_info("VSYNC_WR(%x)<=%x\n", adr, val); + } + } else { + VSYNC_WR_MPEG_REG(adr, val); + } + return 0; +} +EXPORT_SYMBOL(_VSYNC_WR_MPEG_REG); + +int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + if (second_rdma_feature && is_meson_g12b_revb()) { + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + if ((enable_ != 0) && + (vsync_rdma_handle[LINE_N_INT_RDMA] > 0)) { + rdma_write_reg_bits + (vsync_rdma_handle[LINE_N_INT_RDMA], + adr, val, start, len); + } else { + u32 read_val = Rd(adr); + u32 write_val = (read_val & ~(((1L<<(len))-1)<<(start))) + |((unsigned int)(val) << (start)); + Wr(adr, write_val); + if (debug_flag[LINE_N_INT_RDMA] & 1) + pr_info("VSYNC_WR(%x)<=%x\n", adr, write_val); + } + } else { + VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); + } + return 0; +} +EXPORT_SYMBOL(_VSYNC_WR_MPEG_REG_BITS); + bool is_vsync_rdma_enable(void) { bool ret; - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; ret = (enable_ != 0); return ret; @@ -232,53 +384,88 @@ EXPORT_SYMBOL(is_vsync_rdma_enable); void enable_rdma_log(int flag) { - if (flag) - debug_flag |= 0x1; - else - debug_flag &= (~0x1); + if (flag) { + debug_flag[VSYNC_RDMA] |= 0x1; + debug_flag[LINE_N_INT_RDMA] |= 0x1; + } else { + debug_flag[VSYNC_RDMA] &= (~0x1); + debug_flag[LINE_N_INT_RDMA] &= (~0x1); + } } EXPORT_SYMBOL(enable_rdma_log); void enable_rdma(int enable_flag) { - enable = enable_flag; + enable[VSYNC_RDMA] = enable_flag; + enable[LINE_N_INT_RDMA] = enable_flag; } EXPORT_SYMBOL(enable_rdma); -struct rdma_op_s *get_rdma_ops(void) +struct rdma_op_s *get_rdma_ops(int rdma_type) { - return &vsync_rdma_op; + if (rdma_type == VSYNC_RDMA) + return &vsync_rdma_op; + else if (rdma_type == LINE_N_INT_RDMA) + return &line_n_int_rdma_op; + else + return NULL; } -void set_rdma_handle(int handle) +void set_rdma_handle(int rdma_type, int handle) { - vsync_rdma_handle = handle; + vsync_rdma_handle[rdma_type] = handle; pr_info("%s video rdma handle = %d.\n", __func__, - vsync_rdma_handle); + vsync_rdma_handle[rdma_type]); + +} + +u32 is_line_n_rdma_enable(void) +{ + return second_rdma_feature; } static int __init rdma_init(void) { - cur_enable = 0; - enable = 1; - force_rdma_config = 1; + second_rdma_feature = 0; + if (is_meson_g12b_revb()) + second_rdma_feature = 1; + + cur_enable[VSYNC_RDMA] = 0; + enable[VSYNC_RDMA] = 1; + force_rdma_config[VSYNC_RDMA] = 1; + + if (second_rdma_feature) { + cur_enable[LINE_N_INT_RDMA] = 0; + enable[LINE_N_INT_RDMA] = 1; + force_rdma_config[LINE_N_INT_RDMA] = 1; + } + return 0; } module_init(rdma_init); -MODULE_PARM_DESC(enable, "\n enable\n"); -module_param(enable, uint, 0664); +MODULE_PARM_DESC(second_rdma_feature, + "\n second_rdma_feature enable\n"); +module_param(second_rdma_feature, uint, 0664); -MODULE_PARM_DESC(irq_count, "\n irq_count\n"); -module_param(irq_count, uint, 0664); +MODULE_PARM_DESC(enable, + "\n vsync rdma enable\n"); +module_param_array(enable, uint, &rdma_num, 0664); -MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); -module_param(debug_flag, uint, 0664); +MODULE_PARM_DESC(irq_count, + "\n vsync rdma irq_count\n"); +module_param_array(irq_count, uint, &rdma_num, 0664); -MODULE_PARM_DESC(vsync_cfg_count, "\n vsync_cfg_count\n"); -module_param(vsync_cfg_count, uint, 0664); +MODULE_PARM_DESC(debug_flag, + "\n vsync rdma debug_flag\n"); +module_param_array(debug_flag, uint, &rdma_num, 0664); -MODULE_PARM_DESC(force_rdma_config, "\n force_rdma_config\n"); -module_param(force_rdma_config, uint, 0664); +MODULE_PARM_DESC(vsync_cfg_count, + "\n vsync rdma vsync_cfg_count\n"); +module_param_array(vsync_cfg_count, uint, &rdma_num, 0664); + +MODULE_PARM_DESC(force_rdma_config, + "\n vsync rdma force_rdma_config\n"); +module_param_array(force_rdma_config, uint, &rdma_num, 0664); diff --git a/drivers/amlogic/media/common/rdma/rdma.h b/drivers/amlogic/media/common/rdma/rdma.h index 8c98077ddff8..7a3c0a750df5 100644 --- a/drivers/amlogic/media/common/rdma/rdma.h +++ b/drivers/amlogic/media/common/rdma/rdma.h @@ -17,6 +17,11 @@ #ifndef RDMA_VSYNC_H_ #define RDMA_VSYNC_H_ + +enum { + VSYNC_RDMA, + LINE_N_INT_RDMA, +}; void vsync_rdma_config(void); void vsync_rdma_config_pre(void); bool is_vsync_rdma_enable(void); @@ -25,7 +30,7 @@ void enable_rdma_log(int flag); void enable_rdma(int enable_flag); extern int rdma_watchdog_setting(int flag); int rdma_init2(void); -struct rdma_op_s *get_rdma_ops(void); -void set_rdma_handle(int handle); +struct rdma_op_s *get_rdma_ops(int rdma_type); +void set_rdma_handle(int rdma_type, int handle); #endif diff --git a/drivers/amlogic/media/common/rdma/rdma_mgr.c b/drivers/amlogic/media/common/rdma/rdma_mgr.c index c9502de22142..cf15d3adf26e 100644 --- a/drivers/amlogic/media/common/rdma/rdma_mgr.c +++ b/drivers/amlogic/media/common/rdma/rdma_mgr.c @@ -825,11 +825,19 @@ MODULE_PARM_DESC(trace_reg, "\n trace_addr\n"); module_param(trace_reg, ushort, 0664); static struct rdma_device_data_s rdma_meson = { + .cpu_type = CPU_NORMAL, + .rdma_ver = RDMA_VER_1, + .trigger_mask_len = 8, +}; + +static struct rdma_device_data_s rdma_g12b = { + .cpu_type = CPU_G12B, .rdma_ver = RDMA_VER_1, .trigger_mask_len = 8, }; static struct rdma_device_data_s rdma_tl1 = { + .cpu_type = CPU_NORMAL, .rdma_ver = RDMA_VER_2, .trigger_mask_len = 16, }; @@ -839,6 +847,10 @@ static const struct of_device_id rdma_dt_match[] = { .compatible = "amlogic, meson, rdma", .data = &rdma_meson, }, + { + .compatible = "amlogic, meson-g12b, rdma", + .data = &rdma_g12b, + }, { .compatible = "amlogic, meson-tl1, rdma", .data = &rdma_tl1, @@ -846,6 +858,15 @@ static const struct of_device_id rdma_dt_match[] = { {}, }; +u32 is_meson_g12b_revb(void) +{ + if (rdma_meson_dev.cpu_type == CPU_G12B && + is_meson_rev_b()) + return 1; + else + return 0; +} + /* static int __devinit rdma_probe(struct platform_device *pdev) */ static int rdma_probe(struct platform_device *pdev) { @@ -880,7 +901,8 @@ static int rdma_probe(struct platform_device *pdev) pr_err("dev %s NOT found\n", __func__); return -ENODEV; } - pr_info("%s,ver:%d, len:%d\n", __func__, + pr_info("%s,cpu_type:%d, ver:%d, len:%d\n", __func__, + rdma_meson_dev.cpu_type, rdma_meson_dev.rdma_ver, rdma_meson_dev.trigger_mask_len); switch_vpu_mem_pd_vmod(VPU_RDMA, VPU_MEM_POWER_ON); @@ -933,9 +955,16 @@ static int rdma_probe(struct platform_device *pdev) info->rdma_dev = pdev; - handle = rdma_register(get_rdma_ops(), NULL, RDMA_TABLE_SIZE); - set_rdma_handle(handle); + handle = rdma_register(get_rdma_ops(VSYNC_RDMA), + NULL, RDMA_TABLE_SIZE); + set_rdma_handle(VSYNC_RDMA, handle); + if (is_meson_g12b_revb()) { + pr_info("g12b revb!!!!\n"); + handle = rdma_register(get_rdma_ops(LINE_N_INT_RDMA), + NULL, RDMA_TABLE_SIZE); + set_rdma_handle(LINE_N_INT_RDMA, handle); + } return 0; } diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index 95655f5b1df5..0170c3f392a5 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -1323,52 +1323,52 @@ static int stb_dolby_core1_set( DOLBY_TV_CLKGATE_CTRL, 0x2800); if (reset) { if (!dolby_vision_core1_on) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + _VSYNC_WR_MPEG_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); } else reset = 0; } if (!bl_enable) - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x446); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, 0); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x446); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, 0); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, ((hsize + 0x80) << 16) | (vsize + 0x40)); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) composer_enable = 0; - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, /* el dly 3, bl dly 1 after de*/ (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); if (el_enable && (dolby_vision_mask & 1)) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); if (dolby_vision_core1_on && !bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); else if (dolby_vision_core1_on && bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1394,31 +1394,31 @@ static int stb_dolby_core1_set( bypass_flag; if (dolby_vision_on_count < dolby_vision_run_mode_delay) { run_mode |= 1; - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else if (dolby_vision_on_count == dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, 0); } } if (reset) - VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + _VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); /* 962e work around to fix the uv swap issue when bl:el = 1:1 */ if (el_41_mode) - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x6); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x6); else - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0xa); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0xa); /* axi dma for reg table */ reg_size = prepare_stb_dolby_core1_reg( @@ -1439,14 +1439,14 @@ static int stb_dolby_core1_set( } if (reset) { /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x00000080 | (reg_size << 23)); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); /* dma3:23-12 cvm size */ - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80100000 | dma_start_line); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } tv_dovi_setting_update_flag = true; @@ -1513,62 +1513,62 @@ static int tv_dolby_core1_set( DOLBY_TV_CLKGATE_CTRL, 0x2800); if (reset) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + _VSYNC_WR_MPEG_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); } if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) composer_enable = 0; - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, /* el dly 3, bl dly 1 after de*/ (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, ((hsize + 0x80) << 16 | (vsize + 0x40))); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); + _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); /*0x2c2d0:5-4-1-3-2-0*/ - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); if ((hdmi) && (!hdr10)) - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); else - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); /* bypass dither */ - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); if (src_chroma_format == 2) - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); else if (src_chroma_format == 1) - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); /* input 12 or 10 bit */ - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); if (el_enable && (dolby_vision_mask & 1)) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); if (dolby_vision_core1_on && !bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); else if (dolby_vision_core1_on && bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1579,27 +1579,27 @@ static int tv_dolby_core1_set( run_mode = tv_run_mode(vsize, hdmi, hdr10, el_41_mode); if (dolby_vision_on_count < dolby_vision_run_mode_delay) { run_mode = (run_mode & 0xfffffffc) | 1; - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else if (dolby_vision_on_count == dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, 0); } } ((struct tv_dovi_setting_s *)tv_dovi_setting)->core1_reg_lut[1] = 0x0000000100000000 | run_mode; if (reset) - VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + _VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); if (!dolby_vision_on) { WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); @@ -1610,12 +1610,12 @@ static int tv_dolby_core1_set( WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } if (reset) { - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80000000 | dma_start_line); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } tv_dovi_setting_update_flag = true; @@ -1703,23 +1703,24 @@ static int dolby_core1_set( if (is_meson_g12() && frame_count == 1 && dolby_vision_core1_on == 0) { pr_dolby_dbg("((%s %d, register DOLBY_PATH_CTRL: %x))\n", - __func__, __LINE__, VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); - if ((VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x1) != 0) { + __func__, __LINE__, + _VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + if ((_VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x1) != 0) { pr_dolby_dbg("BL is disable for 1st frame.Re-enable BL\n"); - VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, 0, 0, 1); + _VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, 0, 0, 1); pr_dolby_dbg("((%s %d, enable_bl, DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + _VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); } if (el_enable) { - if ((VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x10) != 0) { + if ((_VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x10) != 0) { pr_dolby_dbg("((%s %d enable el))\n", __func__, __LINE__); - VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, + _VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, 0, 1, 1); pr_dolby_dbg("((%s %d, enable_el, DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + _VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); } } } @@ -1737,8 +1738,8 @@ static int dolby_core1_set( reset = true; if ((!dolby_vision_on || reset) && bl_enable) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); reset = true; } @@ -1750,40 +1751,40 @@ static int dolby_core1_set( if (bl_enable && el_enable && (dolby_vision_mask & 1)) { if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, /* vd2 to core1 */ 0, 1, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); } else { if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, /* vd2 to core1 */ 1, 1, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); } - VSYNC_WR_MPEG_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); - /* VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); + /* _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL1, ((hsize + 0x80) << 16) | (vsize + 0x40)); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 4, 4); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 2, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 4, 4); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 2, 1); /* bypass composer to get 12bit when SDR and HDR source */ #ifndef V2_4 @@ -1799,9 +1800,9 @@ static int dolby_core1_set( if (el_41_mode) bypass_flag |= 1 << 3; - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, 0x70 | bypass_flag); /* bypass CVM and/or CSC */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, 0x70 | bypass_flag); /* for delay */ if (dm_count == 0) count = 24; @@ -1811,7 +1812,7 @@ static int dolby_core1_set( if (reset || (p_core1_dm_regs[i] != last_dm[i])) - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE1_REG_START + 6 + i, p_core1_dm_regs[i]); @@ -1823,12 +1824,12 @@ static int dolby_core1_set( if (reset || (p_core1_comp_regs[i] != last_comp[i])) - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE1_REG_START + 6 + 44 + i, p_core1_comp_regs[i]); /* metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 3, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 3, 1); if (lut_count == 0) count = 256 * 5; @@ -1836,79 +1837,79 @@ static int dolby_core1_set( count = lut_count; if (count && (set_lut || reset)) { if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + _VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, 2, 2, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); if (lut_endian) for (i = 0; i < count; i += 4) { - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+3]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+2]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+1]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i]); } else for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i]); if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + _VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, 0, 2, 2); } if (dolby_vision_on_count <= dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); } else { if (dolby_vision_on_count > dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VD1_CLIP_MISC1, 0); } if (dolby_vision_core1_on && !bypass_core1) { if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 0, 0, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); } else if (dolby_vision_core1_on && bypass_core1) { if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1916,12 +1917,12 @@ static int dolby_core1_set( } if (is_meson_g12()) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, (el_41_mode ? (0x3 << 4) : (0x0 << 4)) | bl_enable | composer_enable << 1 | el_41_mode << 2); else /* enable core1 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); @@ -1953,8 +1954,8 @@ static int dolby_core2_set( return 0; if (!dolby_vision_on || force_reset_core2) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, (1 << 10)); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, (1 << 10)); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); force_reset_core2 = false; reset = true; } @@ -1965,37 +1966,37 @@ static int dolby_core2_set( if (stb_core_setting_update_flag & FLAG_CHANGE_TC2) set_lut = true; - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); if (is_meson_gxm() || is_meson_g12() || reset) { - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, ((hsize + g_htotal_add) << 16) | (vsize + g_vtotal_add + g_vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL2, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL2, (hsize << 16) | (vsize + g_vsize_add)); } - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL3, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL3, (g_hwidth << 16) | g_vwidth); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL4, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL4, (g_hpotch << 16) | g_vpotch); if (is_meson_txlx_stbmode() || force_stb_mode) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); else if (is_meson_g12()) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); else - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); if (need_skip_cvm(1)) bypass_flag |= 1 << 0; - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, 2 | bypass_flag); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, 2 | bypass_flag); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); if (dm_count == 0) count = 24; @@ -2005,7 +2006,7 @@ static int dolby_core2_set( if (reset || (p_core2_dm_regs[i] != last_dm[i])) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE2A_REG_START + 6 + i, p_core2_dm_regs[i]); set_lut = true; @@ -2015,7 +2016,7 @@ static int dolby_core2_set( set_lut = false; /* core2 metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 3, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 3, 1); if (lut_count == 0) count = 256 * 5; @@ -2023,32 +2024,32 @@ static int dolby_core2_set( count = lut_count; if (count && (set_lut || reset)) { if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, + _VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, 2, 2, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); if (lut_endian) for (i = 0; i < count; i += 4) { - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+3]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+2]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+1]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i]); } else for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i]); /* core2 lookup table program done */ if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_CORE2A_CLKGATE_CTRL, 0, 2, 2); } /* enable core2 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); return 0; } @@ -2115,61 +2116,61 @@ static int dolby_core3_set( is_meson_g12()) { if (new_dovi_setting.dovi_ll_enable && new_dovi_setting.diagnostic_enable == 0) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 3, 6, 2); /* post matrix */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_MATRIX_CTRL, 1, 0, 1); /* post matrix */ } else { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 0, 6, 2); /* post matrix */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_MATRIX_CTRL, 0, 0, 1); /* post matrix */ } } else if (is_meson_txlx_stbmode() || force_stb_mode) { if (pps_state == 2) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 1, 0, 1); /* skip pps/dither/cm */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x08000800); } else if (pps_state == 1) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 0, 0, 1); /* enable pps/dither/cm */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x20002000); } if (new_dovi_setting.dovi_ll_enable && new_dovi_setting.diagnostic_enable == 0) { /*bypass gainoff to vks */ /*enable wn tp vks*/ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 0, 2, 1); - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x8000800); - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_MATRIX_CTRL, 1, 0, 1); /* post matrix */ } else { /* bypass wm tp vks*/ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 1, 2, 1); - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 0, 1, 1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); if (is_meson_txlx_tvmode()) enable_rgb_to_yuv_matrix_for_dvll( 0, NULL, 12); else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_MATRIX_CTRL, 0, 0, 1); } @@ -2187,27 +2188,27 @@ static int dolby_core3_set( 1, &p_core3_dm_regs[18], 12); #endif - VSYNC_WR_MPEG_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL1, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL1, ((hsize + htotal_add) << 16) | (vsize + vtotal_add + vsize_add + vsize_hold * 2)); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL2, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL2, (hsize << 16) | (vsize + vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL3, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL3, (0x80 << 16) | vsize_hold); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL4, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL4, (0x04 << 16) | vsize_hold); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); if (cur_dv_mode != DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0); else - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0x10000000); /* swap UV */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 5, 7); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 4); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 2, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 5, 7); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 4); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 2); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 2, 1); /* Control Register, address 0x04 2:0 RW */ /* Output_operating mode*/ /* 00- IPT 12 bit 444 bypass Dolby Vision output*/ @@ -2215,8 +2216,8 @@ static int dolby_core3_set( /* 02- HDR10 output, RGB 10 bit 444 PQ*/ /* 03- Deep color SDR, RGB 10 bit 444 Gamma*/ /* 04- SDR, RGB 8 bit 444 Gamma*/ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); /* for delay */ if (dm_count == 0) @@ -2226,7 +2227,7 @@ static int dolby_core3_set( for (i = 0; i < count; i++) if (reset || (p_core3_dm_regs[i] != last_dm[i])) - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE3_REG_START + 0x6 + i, p_core3_dm_regs[i]); /* from addr 0x18 */ @@ -2235,29 +2236,29 @@ static int dolby_core3_set( for (i = 0; i < count; i++) { #ifdef FORCE_HDMI_META if ((i == 20) && (p_core3_md_regs[i] == 0x5140a3e)) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, (p_core3_md_regs[i] & 0xffffff00) | 0x80); else #endif - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, p_core3_md_regs[i]); } for (; i < 30; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); /* from addr 0x90 */ /* core3 metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 3, 1); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 3, 1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE3_DIAG_CTRL, diag_mode); if ((dolby_vision_flags & FLAG_CERTIFICAION) && !(dolby_vision_flags & FLAG_DISABLE_CRC)) - VSYNC_WR_MPEG_REG(0x36fb, 1); + _VSYNC_WR_MPEG_REG(0x36fb, 1); /* enable core3 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); + _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); return 0; } @@ -2401,16 +2402,16 @@ static void osd_bypass(int bypass) static uint32_t osd_backup_mtx; if (bypass) { - osd_backup_ctrl = VSYNC_RD_MPEG_REG(VIU_OSD1_CTRL_STAT); - osd_backup_eotf = VSYNC_RD_MPEG_REG(VIU_OSD1_EOTF_CTL); - osd_backup_mtx = VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); - VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); - VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); + osd_backup_ctrl = _VSYNC_RD_MPEG_REG(VIU_OSD1_CTRL_STAT); + osd_backup_eotf = _VSYNC_RD_MPEG_REG(VIU_OSD1_EOTF_CTL); + osd_backup_mtx = _VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); + _VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); + _VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); + _VSYNC_WR_MPEG_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); } else { - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, osd_backup_mtx); - VSYNC_WR_MPEG_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); - VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, osd_backup_mtx); + _VSYNC_WR_MPEG_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); + _VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); } } @@ -2428,42 +2429,42 @@ static void video_effect_bypass(int bypass) if (bypass) { if (!is_video_effect_bypass) { viu_eotf_ctrl_backup = - VSYNC_RD_MPEG_REG(VIU_EOTF_CTL); + _VSYNC_RD_MPEG_REG(VIU_EOTF_CTL); xvycc_lut_ctrl_backup = - VSYNC_RD_MPEG_REG(XVYCC_LUT_CTL); + _VSYNC_RD_MPEG_REG(XVYCC_LUT_CTL); inv_lut_ctrl_backup = - VSYNC_RD_MPEG_REG(XVYCC_INV_LUT_CTL); + _VSYNC_RD_MPEG_REG(XVYCC_INV_LUT_CTL); vpp_vadj_backup = - VSYNC_RD_MPEG_REG(VPP_VADJ_CTRL); + _VSYNC_RD_MPEG_REG(VPP_VADJ_CTRL); vpp_gainoff_backup = - VSYNC_RD_MPEG_REG(VPP_GAINOFF_CTRL0); + _VSYNC_RD_MPEG_REG(VPP_GAINOFF_CTRL0); vpp_ve_enable_ctrl_backup = - VSYNC_RD_MPEG_REG(VPP_VE_ENABLE_CTRL); + _VSYNC_RD_MPEG_REG(VPP_VE_ENABLE_CTRL); xvycc_vd1_rgb_ctrst_backup = - VSYNC_RD_MPEG_REG(XVYCC_VD1_RGB_CTRST); + _VSYNC_RD_MPEG_REG(XVYCC_VD1_RGB_CTRST); is_video_effect_bypass = true; } - VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, 0); - VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, 0); - VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, 0); - VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, 0); - VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, 0); - VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, 0); + _VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, 0); + _VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, 0); + _VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, 0); + _VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, 0); + _VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, 0); + _VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, 0); + _VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, 0); } else if (is_video_effect_bypass) { - VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, + _VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, viu_eotf_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, + _VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, xvycc_lut_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, + _VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, inv_lut_ctrl_backup); - VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, + _VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, vpp_vadj_backup); - VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, + _VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, vpp_gainoff_backup); - VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, + _VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, vpp_ve_enable_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, + _VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, xvycc_vd1_rgb_ctrst_backup); } } @@ -2477,54 +2478,54 @@ static void osd_path_enable(int on) if (!on) { enable_osd_path(0, 0); - VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, 0); - VSYNC_WR_MPEG_REG(VIU_OSD1_OETF_CTL, 0); + _VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, 0); + _VSYNC_WR_MPEG_REG(VIU_OSD1_OETF_CTL, 0); } else { enable_osd_path(1, -1); if ((hdr_osd_reg.viu_osd1_eotf_ctl & 0x80000000) != 0) { addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( addr_port, 0); for (i = 0; i < 16; i++) - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->r_map[i * 2] | (lut->r_map[i * 2 + 1] << 16)); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->r_map[EOTF_LUT_SIZE - 1] | (lut->g_map[0] << 16)); for (i = 0; i < 16; i++) - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->g_map[i * 2 + 1] | (lut->b_map[i * 2 + 2] << 16)); for (i = 0; i < 16; i++) - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->b_map[i * 2] | (lut->b_map[i * 2 + 1] << 16)); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->b_map[EOTF_LUT_SIZE - 1]); /* load eotf matrix */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_EOTF_COEF00_01, hdr_osd_reg.viu_osd1_eotf_coef00_01); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_EOTF_COEF02_10, hdr_osd_reg.viu_osd1_eotf_coef02_10); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_EOTF_COEF11_12, hdr_osd_reg.viu_osd1_eotf_coef11_12); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_EOTF_COEF20_21, hdr_osd_reg.viu_osd1_eotf_coef20_21); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_EOTF_COEF22_RS, hdr_osd_reg.viu_osd1_eotf_coef22_rs); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_EOTF_CTL, hdr_osd_reg.viu_osd1_eotf_ctl); } @@ -2533,82 +2534,82 @@ static void osd_path_enable(int on) addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; data_port = VIU_OSD1_OETF_LUT_DATA_PORT; for (i = 0; i < 20; i++) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( addr_port, i); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->or_map[i * 2] | (lut->or_map[i * 2 + 1] << 16)); } - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( addr_port, 20); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->or_map[41 - 1] | (lut->og_map[0] << 16)); for (i = 0; i < 20; i++) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( addr_port, 21 + i); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->og_map[i * 2 + 1] | (lut->og_map[i * 2 + 2] << 16)); } for (i = 0; i < 20; i++) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( addr_port, 41 + i); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->ob_map[i * 2] | (lut->ob_map[i * 2 + 1] << 16)); } - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( addr_port, 61); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( data_port, lut->ob_map[41 - 1]); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_OETF_CTL, hdr_osd_reg.viu_osd1_oetf_ctl); } } - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_PRE_OFFSET0_1, hdr_osd_reg.viu_osd1_matrix_pre_offset0_1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_PRE_OFFSET2, hdr_osd_reg.viu_osd1_matrix_pre_offset2); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF00_01, hdr_osd_reg.viu_osd1_matrix_coef00_01); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF02_10, hdr_osd_reg.viu_osd1_matrix_coef02_10); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF11_12, hdr_osd_reg.viu_osd1_matrix_coef11_12); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF20_21, hdr_osd_reg.viu_osd1_matrix_coef20_21); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF22_30, hdr_osd_reg.viu_osd1_matrix_coef22_30); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF31_32, hdr_osd_reg.viu_osd1_matrix_coef31_32); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COEF40_41, hdr_osd_reg.viu_osd1_matrix_coef40_41); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_COLMOD_COEF42, hdr_osd_reg.viu_osd1_matrix_colmod_coef42); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_OFFSET0_1, hdr_osd_reg.viu_osd1_matrix_offset0_1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_OFFSET2, hdr_osd_reg.viu_osd1_matrix_offset2); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VIU_OSD1_MATRIX_CTRL, hdr_osd_reg.viu_osd1_matrix_ctrl); } @@ -2628,18 +2629,18 @@ void enable_dolby_vision(int enable) if (enable) { if (!dolby_vision_on) { dolby_ctrl_backup = - VSYNC_RD_MPEG_REG(VPP_DOLBY_CTRL); + _VSYNC_RD_MPEG_REG(VPP_DOLBY_CTRL); viu_misc_ctrl_backup = - VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1); + _VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1); vpp_matrix_backup = - VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); + _VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); vpp_dummy1_backup = - VSYNC_RD_MPEG_REG(VPP_DUMMY_DATA1); + _VSYNC_RD_MPEG_REG(VPP_DUMMY_DATA1); if (is_meson_txlx()) { vpp_data_conv_para0_backup = - VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA0); + _VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA0); vpp_data_conv_para1_backup = - VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA1); + _VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA1); setting_update_count = 0; } if (is_meson_txlx_tvmode() && !force_stb_mode) { @@ -2652,13 +2653,13 @@ void enable_dolby_vision(int enable) } if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -2666,7 +2667,7 @@ void enable_dolby_vision(int enable) } if (dolby_vision_flags & FLAG_CERTIFICAION) { /* bypass dither/PPS/SR/CM, EO/OE */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 3, 0, 2); /* bypass all video effect */ video_effect_bypass(1); @@ -2674,11 +2675,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); WRITE_VPP_REG(0x33e7, 0xb); } else { @@ -2688,18 +2689,18 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DUMMY_DATA1, 0x80200); /* osd rgb to yuv, vpp out yuv to rgb */ - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0x81); + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0x81); pr_dolby_dbg("Dolby Vision TV core turn on\n"); } else if (is_meson_txlx_stbmode() || force_stb_mode) { @@ -2708,29 +2709,29 @@ void enable_dolby_vision(int enable) memset(dma_vaddr, 0x0, size); osd_bypass(1); if (dolby_vision_mask & 4) - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, 1, 3, 1); /* core3 enable */ if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ dolby_vision_core1_on = false; } - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, (((dolby_vision_mask & 1) && dovi_setting_video_flag) ? 0 : 1), 16, 1); /* core1 */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, ((dolby_vision_mask & 2) ? 0 : 1), 18, 1); /* core2 */ @@ -2738,7 +2739,7 @@ void enable_dolby_vision(int enable) /* bypass dither/PPS/SR/CM*/ /* bypass EO/OE*/ /* bypass vadj2/mtx/gainoff */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 7, 0, 3); /* bypass all video effect */ video_effect_bypass(1); @@ -2746,11 +2747,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); } else { /* bypass all video effect */ @@ -2759,19 +2760,19 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x80200); if (is_meson_txlx_tvmode()) - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 1); + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 1); else - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); #ifdef V2_4 if (((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) @@ -2782,17 +2783,17 @@ void enable_dolby_vision(int enable) u32 *reg = (u32 *)&dovi_setting.dm_reg3; /* input u12 -0x800 to s12 */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x8000800); /* bypass vadj */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VADJ_CTRL, 0); /* bypass gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_GAINOFF_CTRL0, 0); /* enable wm tp vks*/ /* bypass gainoff to vks */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 2); enable_rgb_to_yuv_matrix_for_dvll( 1, ®[18], 12); @@ -2805,36 +2806,36 @@ void enable_dolby_vision(int enable) pr_dolby_dbg("Dolby Vision STB cores turn on\n"); } else if (is_meson_g12()) { if (dolby_vision_mask & 4) - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, 1, 3, 1); /* core3 enable */ else - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* bypass core3 */ - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x0); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, + _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x0); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, + _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x0); if (dolby_vision_mask & 2) - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 0, 2, 1);/*core2 enable*/ else - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 1, 2, 1);/*core2 bypass*/ if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 0, 0, 1); /* core1 */ dolby_vision_core1_on = true; } else { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); /* core1 */ @@ -2844,7 +2845,7 @@ void enable_dolby_vision(int enable) /* bypass dither/PPS/SR/CM*/ /* bypass EO/OE*/ /* bypass vadj2/mtx/gainoff */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 7, 0, 3); /* bypass all video effect */ video_effect_bypass(1); @@ -2852,11 +2853,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); } else { /* bypass all video effect */ @@ -2865,15 +2866,15 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x80200); #ifdef V2_4 if (((dolby_vision_mode == @@ -2885,17 +2886,17 @@ void enable_dolby_vision(int enable) u32 *reg = (u32 *)&dovi_setting.dm_reg3; /* input u12 -0x800 to s12 */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA1, 0x8000800); /* bypass vadj */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VADJ_CTRL, 0); /* bypass gainoff */ - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_GAINOFF_CTRL0, 0); /* enable wm tp vks*/ /* bypass gainoff to vks */ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 2); enable_rgb_to_yuv_matrix_for_dvll( 1, ®[18], @@ -2909,7 +2910,7 @@ void enable_dolby_vision(int enable) #endif pr_dolby_dbg("Dolby Vision G12a turn on\n"); } else { - VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, /* cm_datx4_mode */ (0x0<<21) | /* reg_front_cti_bit_mode */ @@ -2929,7 +2930,7 @@ void enable_dolby_vision(int enable) (0x3<<8) | /* vpp_uns2s_mode 7:0 */ 0x1f); - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* 23-20 ext mode */ (0 << 2) | @@ -2943,13 +2944,13 @@ void enable_dolby_vision(int enable) 18, 6); if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -2959,8 +2960,8 @@ void enable_dolby_vision(int enable) if ((dolby_vision_flags & FLAG_BYPASS_VPP) || (dolby_vision_flags & FLAG_CERTIFICAION)) video_effect_bypass(1); - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); /* disable osd effect and shadow mode */ osd_path_enable(0); #ifdef V2_4 @@ -2972,7 +2973,7 @@ void enable_dolby_vision(int enable) dovi_setting.dovi_ll_enable) { u32 *reg = (u32 *)&dovi_setting.dm_reg3; - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 3, 6, 2); /* post matrix */ enable_rgb_to_yuv_matrix_for_dvll( @@ -2989,7 +2990,7 @@ void enable_dolby_vision(int enable) if (!dolby_vision_core1_on && (dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ @@ -2997,7 +2998,7 @@ void enable_dolby_vision(int enable) } else if (dolby_vision_core1_on && (!(dolby_vision_mask & 1) || !dovi_setting_video_flag)){ - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -3012,7 +3013,7 @@ void enable_dolby_vision(int enable) } else { if (dolby_vision_on) { if (is_meson_txlx_tvmode() && !force_stb_mode) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, /* vd2 connect to vpp */ (1 << 1) | @@ -3035,13 +3036,13 @@ void enable_dolby_vision(int enable) pr_dolby_dbg("Dolby Vision TV core turn off\n"); } else if (is_meson_txlx_stbmode() || force_stb_mode) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 16, 3); - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* core3 disable */ osd_bypass(0); #ifdef V2_4 @@ -3063,19 +3064,19 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision STB cores turn off\n"); } else if (is_meson_g12()) { - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x1); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, + _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x1); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, + _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x1); - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 0, 3); - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* core3 disable */ #ifdef V2_4 if (p_funcs) /* destroy ctx */ @@ -3096,13 +3097,13 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision G12a turn off\n"); } else { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 16, 3); - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, 0, 16, 1); /* core3 disable */ /* enable osd effect and*/ /* use default shadow mode */ @@ -3126,56 +3127,56 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision turn off\n"); } - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 3 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 3 << 9); + _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); if (is_meson_txlx()) { - VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA0, + _VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA0, vpp_data_conv_para0_backup); - VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA1, + _VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA1, vpp_data_conv_para1_backup); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_TV_CLKGATE_CTRL, 0x2414); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE2A_CLKGATE_CTRL, 0x4); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE3_CLKGATE_CTRL, 0x414); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, + _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); } if (is_meson_gxm() || is_meson_g12()) { - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE1_CLKGATE_CTRL, 0x55555555); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE2A_CLKGATE_CTRL, 0x55555555); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( DOLBY_CORE3_CLKGATE_CTRL, 0x55555555); } - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_VD1_CLIP_MISC1, 0); video_effect_bypass(0); - VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + _VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, dolby_ctrl_backup); /* always vd2 to vpp and bypass core 1 */ viu_misc_ctrl_backup |= - (VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 2); - VSYNC_WR_MPEG_REG(VIU_MISC_CTRL1, + (_VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 2); + _VSYNC_WR_MPEG_REG(VIU_MISC_CTRL1, viu_misc_ctrl_backup | (3 << 16)); - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, + _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, vpp_matrix_backup); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, vpp_dummy1_backup); } frame_count = 0; @@ -5759,14 +5760,14 @@ static void bypass_pps_path(u8 pps_state) if (is_meson_txlx_package_962E() || force_stb_mode) { if (pps_state == 2) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 1, 0, 1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x08000800); } else if (pps_state == 1) { - VSYNC_WR_MPEG_REG_BITS( + _VSYNC_WR_MPEG_REG_BITS( VPP_DOLBY_CTRL, 0, 0, 1); - VSYNC_WR_MPEG_REG( + _VSYNC_WR_MPEG_REG( VPP_DAT_CONV_PARA0, 0x20002000); } } @@ -5832,7 +5833,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, && (setting_update_count == 1) && (crc_read_delay == 1)) { /* work around to enable crc for frame 0 */ - VSYNC_WR_MPEG_REG(0x36fb, 1); + _VSYNC_WR_MPEG_REG(0x36fb, 1); crc_read_delay++; } else { crc_read_delay++; diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h index a6ad2c6f695b..d1bd610590c7 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h @@ -624,14 +624,14 @@ struct dolby_vision_func_s { extern int register_dv_functions(const struct dolby_vision_func_s *func); extern int unregister_dv_functions(void); #ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA -#define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) -#define VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) -#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ +#define _VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) +#define _VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) +#define _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ WRITE_VPP_REG_BITS(adr, val, start, len) #else -extern int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); -extern u32 VSYNC_RD_MPEG_REG(u32 adr); -extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); +extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +extern u32 _VSYNC_RD_MPEG_REG(u32 adr); +extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); #endif #endif diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index f6b658e1c228..0857e8fc7ab2 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -755,6 +755,7 @@ struct hw_para_s { u32 two_ports; u32 afbc_err_cnt; u32 viu_type; + u32 line_n_rdma; struct hw_debug_s osd_debug; int out_fence_fd; int in_fd[HW_OSD_COUNT]; diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index 6b8227cf5460..d1b6278ddf87 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -46,6 +46,7 @@ #include #include #include +#include /* Amlogic Headers */ #include #include @@ -59,6 +60,7 @@ #include "osd_log.h" #include "osd_sync.h" #include "osd_io.h" +#include "osd_rdma.h" static __u32 var_screeninfo[5]; static struct osd_device_data_s osd_meson_dev; @@ -2071,6 +2073,9 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, switch (cmd) { case VOUT_EVENT_MODE_CHANGE: set_osd_logo_freescaler(); + if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B && + is_meson_rev_b()) + set_reset_rdma_trigger_line(); if ((osd_meson_dev.osd_ver == OSD_NORMAL) || (osd_meson_dev.osd_ver == OSD_SIMPLE) || (osd_hw.hwc_enable == 0)) { @@ -3468,6 +3473,33 @@ static ssize_t show_osd_status(struct device *device, fb_info->node, osd_hw.enable[fb_info->node]); } +static ssize_t show_osd_line_n_rdma( + struct device *device, struct device_attribute *attr, + char *buf) +{ + int line_n_rdma; + + line_n_rdma = osd_get_line_n_rdma(); + + return snprintf(buf, PAGE_SIZE, "0x%x\n", line_n_rdma); +} + +static ssize_t store_osd_line_n_rdma( + struct device *device, struct device_attribute *attr, + const char *buf, size_t count) +{ + int line_n_rdma; + int ret = 0; + + ret = kstrtoint(buf, 0, &line_n_rdma); + if (ret < 0) + return -EINVAL; + + osd_set_line_n_rdma(line_n_rdma); + + return count; +} + static inline int str2lower(char *str) { while (*str != '\0') { @@ -3678,7 +3710,8 @@ static struct device_attribute osd_attrs[] = { show_osd_plane_alpha, store_osd_plane_alpha), __ATTR(osd_status, 0444, show_osd_status, NULL), - + __ATTR(osd_line_n_rdma, 0644, + show_osd_line_n_rdma, store_osd_line_n_rdma), }; static struct device_attribute osd_attrs_viu2[] = { diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 9877afcda693..320c3ce516f2 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -2071,6 +2071,22 @@ u32 osd_get_gbl_alpha_hw(u32 index) return osd_hw.gbl_alpha[index]; } +void osd_set_line_n_rdma(u32 line_n_rdma) +{ + if (osd_hw.line_n_rdma != line_n_rdma) { + osd_hw.line_n_rdma = line_n_rdma; + if (osd_hw.line_n_rdma) + enable_line_n_rdma(); + else + enable_vsync_rdma(); + } +} + +u32 osd_get_line_n_rdma(void) +{ + return osd_hw.line_n_rdma; +} + void osd_set_color_key_hw(u32 index, u32 color_index, u32 colorkey) { u8 r = 0, g = 0, b = 0, a = (colorkey & 0xff000000) >> 24; @@ -8669,7 +8685,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, #endif } if (osd_hw.hw_rdma_en) - osd_rdma_enable(1); + osd_rdma_enable(2); } diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index 874c97813387..ce8ec8705f3c 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -216,4 +216,6 @@ void osd_set_rotate(u32 index, u32 osd_rotate); void osd_get_afbc_err_cnt(u32 *err_cnt); void osd_get_dimm_info(u32 index, u32 *osd_dimm_layer, u32 *osd_dimm_color); void osd_set_dimm_info(u32 index, u32 osd_dimm_layer, u32 osd_dimm_color); +u32 osd_get_line_n_rdma(void); +void osd_set_line_n_rdma(u32 line_n_rdma); #endif diff --git a/drivers/amlogic/media/osd/osd_rdma.c b/drivers/amlogic/media/osd/osd_rdma.c index f1d08ca33e4a..164d6412968d 100644 --- a/drivers/amlogic/media/osd/osd_rdma.c +++ b/drivers/amlogic/media/osd/osd_rdma.c @@ -33,7 +33,7 @@ #include #include #include - +#include /* Local Headers */ #include "osd.h" #include "osd_io.h" @@ -47,6 +47,7 @@ #include #endif #endif +#define RDMA_TRIGGER_LINE_INPUT (1 << 5) #if 0 #ifndef CONFIG_AMLOGIC_MEDIA_RDMA @@ -1085,9 +1086,19 @@ static int start_osd_rdma(char channel) data32 &= ~(1 << inc_bit); osd_reg_write(RDMA_ACCESS_AUTO, data32); #else - rdma_config(channel, - RDMA_TRIGGER_VSYNC_INPUT - | RDMA_AUTO_START_MASK); + if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B && + is_meson_rev_b()) { + set_reset_rdma_trigger_line(); + rdma_config(channel, RDMA_TRIGGER_LINE_INPUT | + RDMA_AUTO_START_MASK); + osd_hw.line_n_rdma = 1; + + } else { + rdma_config(channel, + RDMA_TRIGGER_VSYNC_INPUT + | RDMA_AUTO_START_MASK); + osd_hw.line_n_rdma = 0; + } #endif return 1; } @@ -1113,6 +1124,41 @@ static int stop_rdma(char channel) return 0; } +void enable_line_n_rdma(void) +{ + unsigned long flags; + + osd_log_info("%s\n", __func__); + rdma_clear(OSD_RDMA_CHANNEL_INDEX); + spin_lock_irqsave(&rdma_lock, flags); + OSD_RDMA_STATUS_CLEAR_REJECT; + osd_reg_write(START_ADDR, table_paddr); + osd_reg_write(END_ADDR, table_paddr - 1); + item_count = 0; + spin_unlock_irqrestore(&rdma_lock, flags); + reset_rdma_table(); + rdma_config(OSD_RDMA_CHANNEL_INDEX, + RDMA_TRIGGER_LINE_INPUT | + RDMA_AUTO_START_MASK); +} + +void enable_vsync_rdma(void) +{ + unsigned long flags; + + osd_log_info("%s\n", __func__); + rdma_clear(OSD_RDMA_CHANNEL_INDEX); + spin_lock_irqsave(&rdma_lock, flags); + OSD_RDMA_STATUS_CLEAR_REJECT; + osd_reg_write(START_ADDR, table_paddr); + osd_reg_write(END_ADDR, table_paddr - 1); + item_count = 0; + spin_unlock_irqrestore(&rdma_lock, flags); + reset_rdma_table(); + rdma_config(OSD_RDMA_CHANNEL_INDEX, + RDMA_TRIGGER_VSYNC_INPUT + | RDMA_AUTO_START_MASK); +} void osd_rdma_interrupt_done_clear(void) { diff --git a/drivers/amlogic/media/osd/osd_rdma.h b/drivers/amlogic/media/osd/osd_rdma.h index 4e78e4f11c83..b1e5e4e6f4c4 100644 --- a/drivers/amlogic/media/osd/osd_rdma.h +++ b/drivers/amlogic/media/osd/osd_rdma.h @@ -69,4 +69,7 @@ extern int rdma_reset_tigger_flag; extern int rdma_mgr_irq_request; extern void osd_rdma_interrupt_done_clear(void); extern int osd_rdma_uninit(void); +void set_reset_rdma_trigger_line(void); +void enable_line_n_rdma(void); +void enable_vsync_rdma(void); #endif diff --git a/include/linux/amlogic/media/rdma/rdma_mgr.h b/include/linux/amlogic/media/rdma/rdma_mgr.h index 20207501aeee..8aeae1fd7075 100644 --- a/include/linux/amlogic/media/rdma/rdma_mgr.h +++ b/include/linux/amlogic/media/rdma/rdma_mgr.h @@ -24,6 +24,7 @@ struct rdma_op_s { }; #define RDMA_TRIGGER_VSYNC_INPUT 0x1 +#define RDMA_TRIGGER_LINE_INPUT (1 << 5) #define RDMA_TRIGGER_MANUAL 0x100 #define RDMA_TRIGGER_DEBUG1 0x101 #define RDMA_TRIGGER_DEBUG2 0x102 @@ -34,11 +35,18 @@ enum rdma_ver_e { RDMA_VER_2, }; +enum cpu_ver_e { + CPU_G12B, + CPU_NORMAL, +}; + struct rdma_device_data_s { + enum cpu_ver_e cpu_type; enum rdma_ver_e rdma_ver; u32 trigger_mask_len; }; +u32 is_meson_g12b_revb(void); /* * rdma_read_reg(), rdma_write_reg(), rdma_clear() can only be called * after rdma_register() is called and From de61151bac7e377eaaeaa2f29f284adae6063cb5 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Wed, 27 Feb 2019 02:05:40 -0500 Subject: [PATCH 0045/1060] hdr: used line_n_int to trigger osd rdma [2/2] PD#SWPL-4582 Problem: g12b revb osd blend shift issue still exist when hdr enable/disable Solution: used line_n_int to trigger osd hdr rdma, this workaround can fix shift issue Verify: verify by g12b revb Change-Id: I062c31dbb5729463bae539e2ea25281d715665c9 Signed-off-by: MingLiang Dong --- .../amlogic/media/enhancement/amvecm/amcsc.c | 5 +- .../media/enhancement/amvecm/set_hdr2_v0.c | 276 ++++++++++++++++-- .../media/enhancement/amvecm/set_hdr2_v0.h | 12 + 3 files changed, 258 insertions(+), 35 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.c b/drivers/amlogic/media/enhancement/amvecm/amcsc.c index 08953ccfe8ec..1b1391130b1b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.c @@ -6521,9 +6521,8 @@ int amvecm_matrix_process( toggle_frame = 0; /* when sdr mode change */ if ((vinfo->hdr_info.hdr_support & 0x4) && - ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXL) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A))) + ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) && + (vinfo->viu_color_fmt != COLOR_FMT_RGB444))) if (((sdr_process_mode != 1) && (sdr_mode > 0)) || ((sdr_process_mode > 0) && (sdr_mode == 0))) null_vf_cnt = toggle_frame; diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index 79b40afc160f..05cec1c9313c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -1137,9 +1137,60 @@ void set_hdr_matrix( if (hdr_mtx_param == NULL) return; - VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_mtx_param->mtx_on, 13, 1); + + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 13, 1); + else + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 13, 1); if (mtx_sel & HDR_IN_MTX) { + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + for (i = 0; i < 15; i++) + mtx[i] = hdr_mtx_param->mtx_in[i]; + _VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL, + hdr_mtx_param->mtx_on); + /*yuv in*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 4, 1); + + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_only, + 16, 1); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1); + /*mtx in en*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 14, 1); + + _VSYNC_WR_MPEG_REG(MATRIXI_COEF00_01, + (mtx[0 * 3 + 0] << 16) | + (mtx[0 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF02_10, + (mtx[0 * 3 + 2] << 16) | + (mtx[1 * 3 + 0] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF11_12, + (mtx[1 * 3 + 1] << 16) | + (mtx[1 * 3 + 2] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF20_21, + (mtx[2 * 3 + 0] << 16) | + (mtx[2 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF22, + mtx[2 * 3 + 2]); + _VSYNC_WR_MPEG_REG(MATRIXI_OFFSET0_1, + (yuv2rgbpos[0] << 16) | + (yuv2rgbpos[1] & 0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_OFFSET2, + yuv2rgbpos[2]); + _VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET0_1, + (yuv2rgbpre[0] << 16) | + (yuv2rgbpre[1] & 0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET2, + yuv2rgbpre[2]); + + return; + } for (i = 0; i < 15; i++) mtx[i] = hdr_mtx_param->mtx_in[i]; VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL, hdr_mtx_param->mtx_on); @@ -1170,14 +1221,13 @@ void set_hdr_matrix( (yuv2rgbpre[0] << 16)|(yuv2rgbpre[1] & 0xFFF)); VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET2, yuv2rgbpre[2]); - } else if (mtx_sel & HDR_GAMUT_MTX) { for (i = 0; i < 9; i++) gmut_coef[i/3][i%3] = hdr_mtx_param->mtx_gamut[i]; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (hdr_mtx_param->p_sel & HDR_BYPASS) && (module_sel & OSD1_HDR)) gmut_shift = 10; @@ -1191,7 +1241,7 @@ void set_hdr_matrix( adpscl_mode = 1; for (i = 0; i < 3; i++) { if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (hdr_mtx_param->p_sel & HDR_BYPASS) && (module_sel & OSD1_HDR)) adpscl_enable[i] = 1; @@ -1234,51 +1284,145 @@ void set_hdr_matrix( /*gamut mode: 1->gamut before ootf*/ /*2->gamut after ootf*/ /*other->disable gamut*/ + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 2, 6, 2); + + _VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); + _VSYNC_WR_MPEG_REG(GMUT_COEF0, + (gmut_coef[0][1] & 0xffff) << 16 | + (gmut_coef[0][0] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF1, + (gmut_coef[1][0] & 0xffff) << 16 | + (gmut_coef[0][2] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF2, + (gmut_coef[1][2] & 0xffff) << 16 | + (gmut_coef[1][1] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF3, + (gmut_coef[2][1] & 0xffff) << 16 | + (gmut_coef[2][0] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF4, + gmut_coef[2][2] & 0xffff); + + _VSYNC_WR_MPEG_REG(CGAIN_COEF0, + c_gain_lim_coef[1] << 16 | + c_gain_lim_coef[0]); + _VSYNC_WR_MPEG_REG(CGAIN_COEF1, c_gain_lim_coef[2] | + 0x400 << 16); + + _VSYNC_WR_MPEG_REG(ADPS_CTRL, + adpscl_enable[2] << 6 | + adpscl_enable[1] << 5 | + adpscl_enable[0] << 4 | + adpscl_mode); + _VSYNC_WR_MPEG_REG(ADPS_ALPHA0, + adpscl_alpha[1]<<16 | adpscl_alpha[0]); + _VSYNC_WR_MPEG_REG(ADPS_ALPHA1, + adpscl_shift[0] << 24 | + adpscl_shift[1] << 20 | + adpscl_shift[2] << 16 | + adpscl_alpha[2]); + _VSYNC_WR_MPEG_REG(ADPS_BETA0, + adpscl_beta_s[0] << 20 | adpscl_beta[0]); + _VSYNC_WR_MPEG_REG(ADPS_BETA1, + adpscl_beta_s[1] << 20 | adpscl_beta[1]); + _VSYNC_WR_MPEG_REG(ADPS_BETA2, + adpscl_beta_s[2] << 20 | adpscl_beta[2]); + _VSYNC_WR_MPEG_REG(ADPS_COEF0, + adpscl_ys_coef[1] << 16 | + adpscl_ys_coef[0]); + _VSYNC_WR_MPEG_REG(ADPS_COEF1, + adpscl_ys_coef[2]); + + return; + } VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 2, 6, 2); - VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); - VSYNC_WR_MPEG_REG(GMUT_COEF0, + VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); + VSYNC_WR_MPEG_REG(GMUT_COEF0, (gmut_coef[0][1] & 0xffff) << 16 | (gmut_coef[0][0] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF1, + VSYNC_WR_MPEG_REG(GMUT_COEF1, (gmut_coef[1][0] & 0xffff) << 16 | (gmut_coef[0][2] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF2, + VSYNC_WR_MPEG_REG(GMUT_COEF2, (gmut_coef[1][2] & 0xffff) << 16 | (gmut_coef[1][1] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF3, + VSYNC_WR_MPEG_REG(GMUT_COEF3, (gmut_coef[2][1] & 0xffff) << 16 | (gmut_coef[2][0] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF4, + VSYNC_WR_MPEG_REG(GMUT_COEF4, gmut_coef[2][2] & 0xffff); - VSYNC_WR_MPEG_REG(CGAIN_COEF0, + VSYNC_WR_MPEG_REG(CGAIN_COEF0, c_gain_lim_coef[1] << 16 | c_gain_lim_coef[0]); - VSYNC_WR_MPEG_REG(CGAIN_COEF1, c_gain_lim_coef[2] | + VSYNC_WR_MPEG_REG(CGAIN_COEF1, c_gain_lim_coef[2] | 0x400 << 16); - VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 | - adpscl_enable[1] << 5 | - adpscl_enable[0] << 4 | - adpscl_mode); + VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 | + adpscl_enable[1] << 5 | + adpscl_enable[0] << 4 | + adpscl_mode); VSYNC_WR_MPEG_REG(ADPS_ALPHA0, adpscl_alpha[1]<<16 | adpscl_alpha[0]); VSYNC_WR_MPEG_REG(ADPS_ALPHA1, adpscl_shift[0] << 24 | - adpscl_shift[1] << 20 | - adpscl_shift[2] << 16 | - adpscl_alpha[2]); - VSYNC_WR_MPEG_REG(ADPS_BETA0, + adpscl_shift[1] << 20 | + adpscl_shift[2] << 16 | + adpscl_alpha[2]); + VSYNC_WR_MPEG_REG(ADPS_BETA0, adpscl_beta_s[0] << 20 | adpscl_beta[0]); - VSYNC_WR_MPEG_REG(ADPS_BETA1, + VSYNC_WR_MPEG_REG(ADPS_BETA1, adpscl_beta_s[1] << 20 | adpscl_beta[1]); - VSYNC_WR_MPEG_REG(ADPS_BETA2, + VSYNC_WR_MPEG_REG(ADPS_BETA2, adpscl_beta_s[2] << 20 | adpscl_beta[2]); - VSYNC_WR_MPEG_REG(ADPS_COEF0, + VSYNC_WR_MPEG_REG(ADPS_COEF0, adpscl_ys_coef[1] << 16 | adpscl_ys_coef[0]); - VSYNC_WR_MPEG_REG(ADPS_COEF1, adpscl_ys_coef[2]); - + VSYNC_WR_MPEG_REG(ADPS_COEF1, adpscl_ys_coef[2]); } else if (mtx_sel & HDR_OUT_MTX) { + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + for (i = 0; i < 15; i++) + mtx[i] = hdr_mtx_param->mtx_out[i]; + _VSYNC_WR_MPEG_REG(CGAIN_OFFT, + (rgb2yuvpos[2] << 16) | rgb2yuvpos[1]); + _VSYNC_WR_MPEG_REG(MATRIXO_EN_CTRL, + hdr_mtx_param->mtx_on); + /*yuv in*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 4, 1); + + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_only, + 16, 1); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1); + /*mtx out en*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 15, 1); + + _VSYNC_WR_MPEG_REG(MATRIXO_COEF00_01, + (mtx[0 * 3 + 0] << 16) | + (mtx[0 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF02_10, + (mtx[0 * 3 + 2] << 16) | + (mtx[1 * 3 + 0] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF11_12, + (mtx[1 * 3 + 1] << 16) | + (mtx[1 * 3 + 2] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF20_21, + (mtx[2 * 3 + 0] << 16) | + (mtx[2 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF22, + mtx[2 * 3 + 2]); + _VSYNC_WR_MPEG_REG(MATRIXO_OFFSET0_1, + (rgb2yuvpos[0] << 16) | (rgb2yuvpos[1]&0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_OFFSET2, + rgb2yuvpos[2]); + _VSYNC_WR_MPEG_REG(MATRIXO_PRE_OFFSET0_1, + (rgb2yuvpre[0] << 16)|(rgb2yuvpre[1]&0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_PRE_OFFSET2, + rgb2yuvpre[2]); + return; + } for (i = 0; i < 15; i++) mtx[i] = hdr_mtx_param->mtx_out[i]; VSYNC_WR_MPEG_REG(CGAIN_OFFT, @@ -1312,7 +1456,6 @@ void set_hdr_matrix( VSYNC_WR_MPEG_REG(MATRIXO_PRE_OFFSET2, rgb2yuvpre[2]); } - } void set_eotf_lut( @@ -1353,7 +1496,18 @@ void set_eotf_lut( for (i = 0; i < HDR2_EOTF_LUT_SIZE; i++) lut[i] = hdr_lut_param->eotf_lut[i]; + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 3, 1); + if (!hdr_lut_param->lut_on) + return; + + _VSYNC_WR_MPEG_REG(eotf_lut_addr_port, 0x0); + for (i = 0; i < HDR2_EOTF_LUT_SIZE; i++) + _VSYNC_WR_MPEG_REG(eotf_lut_data_port, lut[i]); + return; + } VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 3, 1); if (!hdr_lut_param->lut_on) @@ -1403,6 +1557,23 @@ void set_ootf_lut( for (i = 0; i < HDR2_OOTF_LUT_SIZE; i++) lut[i] = hdr_lut_param->ogain_lut[i]; + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 1, 1); + + if (!hdr_lut_param->lut_on) + return; + + _VSYNC_WR_MPEG_REG(ootf_lut_addr_port, 0x0); + for (i = 0; i < HDR2_OOTF_LUT_SIZE / 2; i++) + _VSYNC_WR_MPEG_REG(ootf_lut_data_port, + (lut[i * 2 + 1] << 16) + + lut[i * 2]); + _VSYNC_WR_MPEG_REG(ootf_lut_data_port, lut[148]); + + return; + } + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 1, 1); if (!hdr_lut_param->lut_on) @@ -1455,6 +1626,29 @@ void set_oetf_lut( for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) lut[i] = hdr_lut_param->oetf_lut[i]; + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 2, 1); + + if (!hdr_lut_param->lut_on) + return; + + _VSYNC_WR_MPEG_REG(oetf_lut_addr_port, 0x0); + for (i = 0; i < HDR2_OETF_LUT_SIZE / 2; i++) { + if (hdr_lut_param->bitdepth == 10) + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, + ((lut[i * 2 + 1] >> 2) << 16) + + (lut[i * 2] >> 2)); + else + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, + (lut[i * 2 + 1] << 16) + + lut[i * 2]); + } + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + + return; + } + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 2, 1); if (!hdr_lut_param->lut_on) @@ -1470,8 +1664,8 @@ void set_oetf_lut( VSYNC_WR_MPEG_REG(oetf_lut_data_port, (lut[i * 2 + 1] << 16) + lut[i * 2]); - } - VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + } + VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); } void set_c_gain( @@ -1515,6 +1709,24 @@ void set_c_gain( /*cgain mode: 0->y domin*/ /*cgain mode: 1->rgb domin, use r/g/b max*/ + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_lut_param->cgain_en, 12, 1); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_lut_param->cgain_en, 0, 1); + + if (!hdr_lut_param->cgain_en) + return; + + _VSYNC_WR_MPEG_REG(cgain_lut_addr_port, 0x0); + for (i = 0; i < HDR2_CGAIN_LUT_SIZE / 2; i++) + _VSYNC_WR_MPEG_REG(cgain_lut_data_port, + (lut[i * 2 + 1] << 16) + lut[i * 2]); + _VSYNC_WR_MPEG_REG(cgain_lut_data_port, lut[64]); + return; + } + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 12, 1); VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 0, 1); @@ -1586,7 +1798,7 @@ void hdr_func(enum hdr_module_sel module_sel, if (hdr_process_select & HDR_BYPASS) { /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (module_sel & OSD1_HDR)) { for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) { hdr_lut_param.oetf_lut[i] = oe_y_lut_bypass[i]; @@ -1643,7 +1855,7 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.bitdepth = bit_depth; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (module_sel & OSD1_HDR)) hdr_lut_param.cgain_en = LUT_ON; else @@ -1698,7 +1910,7 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.bitdepth = bit_depth; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (module_sel & OSD1_HDR)) hdr_lut_param.cgain_en = LUT_ON; else @@ -1711,7 +1923,7 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_mtx_param.mtx_only = HDR_ONLY; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (hdr_process_select & HDR_BYPASS) && (module_sel & OSD1_HDR)) { for (i = 0; i < 15; i++) { diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h index 935d3d359c84..1dfd863a6b0a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h @@ -147,3 +147,15 @@ enum mtx_csc_e { extern void mtx_setting(enum vpp_matrix_e mtx_sel, enum mtx_csc_e mtx_csc, int mtx_on); + +#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +#define _VSYNC_WR_MPEG_REG(adr, val) WRITE_VCBUS_REG(adr, val) +#define _VSYNC_RD_MPEG_REG(adr) READ_VCBUS_REG(adr) +#define _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + WRITE_VCBUS_REG_BITS(adr, val, start, len) +#else +extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, + u32 val, u32 start, u32 len); +extern u32 _VSYNC_RD_MPEG_REG(u32 adr); +extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); +#endif From 0378a935d9bf9f9ceb66077252d30d8fc13c0401 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Tue, 19 Feb 2019 13:01:57 +0800 Subject: [PATCH 0046/1060] dts: g12b: copy g12b dts [1/1] PD#SWPL-5020 Problem: copy g12b dts. Solution: copy. Verify: local. Change-Id: Ibd6423bd0cc99e98bf1d6359068f9f0719ad177f Signed-off-by: Jianxiong Pan Signed-off-by: Hong Guo Signed-off-by: Luan Yuan Conflicts: arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts --- .../devicetree/bindings/arm/idle-states.txt | 2 +- MAINTAINERS | 7 + arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 41 +- .../arm/boot/dts/amlogic/g12b_a311d_skt_a.dts | 1387 +++++++++ arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 41 +- .../boot/dts/amlogic/g12b_a311d_w400_a.dts | 1311 ++++++++ .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 41 +- .../amlogic/g12b_a311d_w400_buildroot_a.dts | 1446 +++++++++ .../g12b_a311d_w400_buildroot_vccktest.dts | 35 +- .../g12b_a311d_w400_buildroot_vccktest_a.dts | 1341 +++++++++ arch/arm/boot/dts/amlogic/g12b_pxp.dts | 41 +- arch/arm/boot/dts/amlogic/g12b_pxp_a.dts | 737 +++++ arch/arm/boot/dts/amlogic/mesong12b_a.dtsi | 2637 +++++++++++++++++ .../arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 41 +- .../boot/dts/amlogic/g12b_a311d_skt_a.dts | 1387 +++++++++ .../boot/dts/amlogic/g12b_a311d_w400.dts | 41 +- .../boot/dts/amlogic/g12b_a311d_w400_a.dts | 1311 ++++++++ .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 41 +- .../amlogic/g12b_a311d_w400_buildroot_a.dts | 1445 +++++++++ .../g12b_a311d_w400_buildroot_vccktest.dts | 35 +- .../g12b_a311d_w400_buildroot_vccktest_a.dts | 1341 +++++++++ .../dts/amlogic/g12b_a311x_w411_buildroot.dts | 1463 +++++++++ .../amlogic/g12b_a311x_w411_buildroot_a.dts | 1444 +++++++++ arch/arm64/boot/dts/amlogic/g12b_pxp.dts | 41 +- arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts | 736 +++++ arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 2637 +++++++++++++++++ 26 files changed, 20923 insertions(+), 107 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts create mode 100644 arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts create mode 100644 arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts create mode 100644 arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts create mode 100644 arch/arm/boot/dts/amlogic/g12b_pxp_a.dts create mode 100644 arch/arm/boot/dts/amlogic/mesong12b_a.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts create mode 100644 arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt index b8e41c148a3c..a470c29a76e3 100644 --- a/Documentation/devicetree/bindings/arm/idle-states.txt +++ b/Documentation/devicetree/bindings/arm/idle-states.txt @@ -489,7 +489,7 @@ cpus { CPU15: cpu@100010101 { device_type = "cpu"; - compatible = "arm,cortex-a53"; + compatible = "arm,cortex-a73","arm,armv8"; reg = <0x1 0x10101>; enable-method = "psci"; cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 diff --git a/MAINTAINERS b/MAINTAINERS index 093639ebc281..1216efa728e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14762,6 +14762,13 @@ F: drivers/amlogic/media/video_processor/videosync/vfp.h F: drivers/amlogic/media/video_processor/videosync/videosync.h F: drivers/amlogic/media/video_processor/videosync/videosync.c +AMLOGIC G12B_A DTS +M: Jianxiong Pan +F: arch/arm/boot/dts/amlogic/g12b*_a.dts +F: arch/arm/boot/dts/amlogic/mesong12b.dtsi +F: arch/arm64/boot/dts/amlogic/g12b*_a.dts +F: arch/arm64/boot/dts/amlogic/mesong12b.dtsi + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index d707eb07f111..7e048d39bfe2 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -699,43 +700,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts new file mode 100644 index 000000000000..9924f15ed81a --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -0,0 +1,1387 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "menu", "vol-", "vol+", "esc", "home"; + key_num = <5>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <139 114 115 1 102>; + key_val = <0 143 266 389 512>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "disabled"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &dummy_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_0"; + reg = <0x48>; + status = "disabled"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_1"; + reg = <0x49>; + status = "disabled"; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <4>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index af55b1cb15e4..5f9faebc091d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -667,43 +668,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts new file mode 100644 index 000000000000..de5c38234da0 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -0,0 +1,1311 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + goodix,cfg-group0 = [ + 41 00 04 58 02 05 0C 00 02 54 07 + 0F 50 2D 03 05 00 00 00 00 40 00 + 04 20 10 F3 AA 07 28 0A 2C 2E 7C + 06 00 00 00 C9 03 24 00 01 00 00 + 00 00 FF 5D 66 98 32 28 64 94 C5 + 02 08 00 00 01 91 2C 00 8A 34 00 + 8A 3F 00 7E 4C 00 78 5B 00 78 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 02 04 06 08 0A 0C 0E 10 12 + 14 FF FF FF FF 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 02 04 06 08 0A 0C 1D 1E 1F 20 21 + 22 24 26 FF FF FF FF FF FF FF FF + FF FF FF 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 E3 01]; + }; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index c79d77064d3c..4b1e5640e567 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -762,43 +763,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts new file mode 100644 index 000000000000..c84d2203719b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -0,0 +1,1446 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index cc4f10695891..f24ef24a1f4e 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -735,55 +736,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1011000>; + opp-microvolt = <771000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <801000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts new file mode 100644 index 000000000000..c999018d5e4d --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -0,0 +1,1341 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1896000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1011000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp.dts b/arch/arm/boot/dts/amlogic/g12b_pxp.dts index e3c62014853e..610d41a937cb 100644 --- a/arch/arm/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12b_pxp.dts @@ -21,6 +21,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -401,43 +402,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts b/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts new file mode 100644 index 000000000000..96d4f3364f43 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts @@ -0,0 +1,737 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_pxp_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0xd000000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x0 0x30000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "disabled"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "disabled"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "disabled"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "disabled"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "disabled"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + /*compatible = "amlogic, g12a-sound-card";*/ + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&pwm_ab { + status = "okay"; +}; + + +&audiobus { + aml_tdma: tdma { + /*compatible = "amlogic, g12a-snd-tdma";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + /*compatible = "amlogic, g12a-snd-tdmb";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + aml_tdmc: tdmc { + /*compatible = "amlogic, g12a-snd-tdmc";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + aml_spdif: spdif { + /*compatible = "amlogic, g12a-snd-spdif-a";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "disabled"; + }; + aml_spdif_b: spdif_b { + /*compatible = "amlogic, g12a-snd-spdif-b";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_b>; + status = "disabled"; + }; + aml_pdm: pdm { + /*compatible = "amlogic, g12a-snd-pdm";*/ + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_PM_KEEP_POWER", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi new file mode 100644 index 000000000000..f022bbc6a020 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -0,0 +1,2637 @@ +/* + * arch/arm/boot/dts/amlogic/mesong12b_a.dtsi + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include "g12b-sched-energy.dtsi" + +/ { + cpus:cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + cluster1:cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + core2 { + cpu = <&CPU4>; + }; + core3 { + cpu = <&CPU5>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x101>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU4:cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x102>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU5:cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x103>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <8000>; + exit-latency-us = <8000>; + min-residency-us = <20000>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + local-timer-stop; + entry-latency-us = <9000>; + exit-latency-us = <9000>; + min-residency-us = <25000>; + }; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0xffd0f190 0x4 0xffd0f194 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + clusterb-enabled; + interrupts = , + ; + reg = <0xff634680 0x4>, + <0xff6347c0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xffc01000 0x1000>, + <0xffc02000 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + meson_suspend:pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + reg = <0xff8000a8 0x4>, + <0xff80023c 0x4>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + clear_range = <0x05100000 0x200000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffe7000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base { + reg = <0xffd00000 0x26000>; + }; + io_apb_base { + reg = <0xffe01000 0x7f000>; + }; + io_aobus_base { + reg = <0xff800000 0xb000>; + }; + io_vapb_base { + reg = <0xff900000 0x50000>; + }; + io_hiu_base { + reg = <0xff63c000 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu { + compatible = "amlogic, vpu-g12b"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0xff800014 0x8>, + <0xff800024 0x14>, + <0xff80001c 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0xff6346c0 0x40>, + <0xff6344e8 0x18>, + <0xff634520 0x18>, + <0xff634440 0x4c>, + <0xff634740 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0xffe09080 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0xffd0f0d0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0xffd00000 0x26000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xffd00000 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-g12a-gpio-intc"; + reg = <0xf080 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, gxl_measure"; + reg = <0x18004 0x4 + 0x1800c 0x4>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x1b000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x1a000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x19000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1f000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1e000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1d000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1c000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x13000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x15000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0xff800000 0xb000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff800000 0xb000>; + + cpu_version { + reg=<0x220 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,g12b-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x320>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x7000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x2000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x05000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x6000 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0xff634400 0x400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff634400 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0xff63c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff63c000 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,g12b-clkc-1"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + clkc_b: clock-controller@1 { + compatible = "amlogic,g12b-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xff642000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0xff642000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff642000 0x2000>; + clkaudio: audio_clocks { + compatible = "amlogic, g12a-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, g12a-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "frddr_a", "frddr_b", "frddr_c"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0xff808040 0x44>, /*Multi-format IR controller*/ + <0xff808000 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfc000000 0x400000 + 0xff648000 0x2000 + 0xfc400000 0x200000 + 0xff646000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B + */ + ic_type = <11>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 147 1>; + interrupt-names = "galcore"; + reg = <0xff100000 0x800 + 0xff000000 0x400000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-g12a"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "G12B"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400 + 0xFF634400 0x26>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-g12b"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + io_efuse_base{ + reg = <0xff630000 0x2000>; + }; + }; + + gdc:gdc { + #address-cells=<1>; + #size-cells=<1>; + status = "ok"; + compatible = "amlogic, g12b-gdc"; + reg = <0xFF950000 0x0000100 + 0xFF63C16C 0x0000004 + 0xFF63C100 0x0000004>; + interrupts = <0 144 1>; + interrupt-names = "GDC"; + clocks = <&clkc CLKID_GDC_CORE_CLK_COMP + &clkc CLKID_GDC_AXI_CLK_COMP >; + clock-names = "core","axi"; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_reg_base{ + reg = <0xff610000 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: meson-fb { + compatible = "amlogic, meson-g12b"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0xff80014c 0x10>, + <0xff800040 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "disabled"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0xffe07000 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0xffe03000 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0xFFE07800 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <120>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpufreq_cool_cluster1 { + min_state = <1000000>; + dyn_coeff = <460>; + cluster_id = <1>; + gpu_pp = <2>; + node_name = "cpufreq_cool1"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + cpucore_cool_cluster1 { + min_state = <0>; + dyn_coeff = <0>; + cluster_id = <1>; + gpu_pp = <2>; + node_name = "cpucore_cool1"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpufreq_cool1:cpufreq_cool1 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool1:cpucore_cool1 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map0 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 10>; + contribution = <1024>; + }; + cpufreq_cooling_map1 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool1 0 9>; + contribution = <1024>; + }; + cpucore_cooling_map0 { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 1>; + contribution = <1024>; + }; + cpucore_cooling_map1 { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool1 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF640000 0x2000>; + }; + audiobus_base { + reg = <0xFF642000 0x2000>; + }; + audiolocker_base { + reg = <0xFF64A000 0x2000>; + }; + eqdrc_base { + reg = <0xFF656000 0x1800>; + }; + reset_base { + reg = <0xFFD01000 0x1000>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + vddcpu1: pwmab_a-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_a_e2>; + pwms = <&pwm_ab MESON_PWM_0 1250 0>; + regulator-name = "vddcpu1"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + isp_sc: isp-sc@ff655400 { + compatible = "amlogic, isp-sc"; + reg = <0xff655400 0x00001000>; + reg-names = "isp_sc"; + interrupts = <0 17 0>; + interrupt-names = "isp_sc"; + }; + + isp: isp@ff140000 { + compatible = "arm, isp"; + reg = <0xff140000 0x00040000>; + reg-names = "ISP"; + interrupts = <0 142 4>; + interrupt-names = "ISP"; + temper-buf-size = <24>; + clocks = <&clkc CLKID_MIPI_ISP_CLK_COMP>, + <&clkc CLKID_MIPI_CSI_PHY_CLK0_COMP>; + clock-names = "cts_mipi_isp_clk_composite", + "cts_mipi_csi_phy_clk0_composite"; + link-device = <&isp_sc>; + }; + + adapter: isp-adapter@ff650000 { + compatible = "amlogic, isp-adapter"; + reg = <0xff650000 0x00006000>; + reg-names = "adapter"; + interrupts = <0 179 0>; + interrupt-names = "adapter-irq"; + }; + + phycsi: phy-csi@ff650000 { + compatible = "amlogic, phy-csi"; + reg = <0xff650000 0x00002000>, + <0xff652000 0x00002000>, + <0xff63c300 0x00000100>, + <0xff654000 0x00000100>, + <0xff654400 0x00000100>; + reg-names = "csi2_phy0", "csi2_phy1", "aphy_reg", + "csi0_host", "csi1_host"; + interrupts = <0 41 0>, + <0 42 0>, + <0 72 0>, + <0 74 0>, + <0 87 0>, + <0 88 0>; + interrupt-names = "phy0-irq", + "phy1-irq", + "csi-host0-intr2", + "csi-host0-intr1", + "csi-host1-intr2", + "csi-host1-intr1"; + link-device = <&adapter>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0xff630218 0x4>; /*RNG_USR_DATA*/ + mem_size = <0 0x100000>; + status = "okay"; + }; +};/* end of / */ + +&pinctrl_aobus { + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_gpioe"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_b_pins3: pwm_b_pins3 { + mux { + groups = "pwm_b_h"; + function = "pwm_b"; + }; + }; + + pwm_b_pins4: pwm_b_pins4 { + mux { + groups = "pwm_b_z0"; + function = "pwm_b"; + }; + }; + + pwm_b_pins5: pwm_b_pins5 { + mux { + groups = "pwm_b_z13"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_c_pins4: pwm_c_pins4 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_d_pins3: pwm_d_pins3 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_d_pins4: pwm_d_pins4 { + mux { + groups = "pwm_d_a4"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + pwm_f_pins3: pwm_f_pins3 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + pwm_f_pins4: pwm_f_pins4 { + mux { + groups = "pwm_f_a11"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + irblaster_pins2:irblaster_pins2 { + mux { + groups = "remote_out_h"; + function = "remote_out"; + }; + }; + + irblaster_pins3:irblaster_pins3 { + mux { + groups = "remote_out_z"; + function = "remote_out"; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&gpu{ + system-coherency = <0>; + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index fa545c35feed..75d1231c6140 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -699,43 +700,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts new file mode 100644 index 000000000000..c93c993808c2 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -0,0 +1,1387 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "menu", "vol-", "vol+", "esc", "home"; + key_num = <5>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <139 114 115 1 102>; + key_val = <0 143 266 389 512>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "disabled"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &dummy_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_0"; + reg = <0x48>; + status = "disabled"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_1"; + reg = <0x49>; + status = "disabled"; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <4>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 30a09e5013bf..ed4a731e89d2 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -667,43 +668,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts new file mode 100644 index 000000000000..266185faf1c3 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -0,0 +1,1311 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + clear-map; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + goodix,cfg-group0 = [ + 41 00 04 58 02 05 0C 00 02 54 07 + 0F 50 2D 03 05 00 00 00 00 40 00 + 04 20 10 F3 AA 07 28 0A 2C 2E 7C + 06 00 00 00 C9 03 24 00 01 00 00 + 00 00 FF 5D 66 98 32 28 64 94 C5 + 02 08 00 00 01 91 2C 00 8A 34 00 + 8A 3F 00 7E 4C 00 78 5B 00 78 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 02 04 06 08 0A 0C 0E 10 12 + 14 FF FF FF FF 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 02 04 06 08 0A 0C 1D 1E 1F 20 21 + 22 24 26 FF FF FF FF FF FF FF FF + FF FF FF 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 E3 01]; + }; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 3e12ebcd6088..edf4017fb5a9 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -761,43 +762,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts new file mode 100644 index 000000000000..f6628233f2b5 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -0,0 +1,1445 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index e087c6b04fd9..00047a2c5d8f 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -735,55 +736,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1011000>; + opp-microvolt = <771000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <801000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts new file mode 100644 index 000000000000..ce65118752ba --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -0,0 +1,1341 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1896000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1011000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts new file mode 100644 index 000000000000..a06643eb8022 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -0,0 +1,1463 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x5000000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + // vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16+4 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + /* vdin1 CMA pool */ + // vdin1_cma_reserved:linux,vdin1_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x3c00000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x1800000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "wificonfig"; + key_code = <139>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "disabled"; + key_name = "vol-", "vol+", "enter", "wificonfig"; + key_num = <4>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28 139>; + key_val = <143 266 389 0>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <14>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <731000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <731000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <731000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; + ircut: ircut { + compatible = "amlogic, ircut"; + status = "okay"; + filter1-gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; + filter2-gpios = <&gpio GPIOH_7 GPIO_ACTIVE_HIGH>; + light_in-gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; + alarm-gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_HIGH>; + }; + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + mem_alloc = <24>; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +//}; + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_tx_b_8", + "uart_ao_rx_b_9"; + function = "uart_ao_b"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { +// memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { +// memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + /*if card have no switch gpio, + * remove all relative to vol_switch + */ + vol_switch = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + vol_switch_18 = <1>; /* 1 = high, 0 = low */ + vol_switch_delay = <150>; /* Uint: ms*/ + + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", +// "MMC_CAP_UHS_SDR12", +// "MMC_CAP_UHS_SDR25", +// "MMC_CAP_UHS_SDR50", +// "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + //gpio-vbus-power = "GPIOH_6"; + //gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + //conflict with isp i2c + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; + + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; +&uart_AO_B { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins2>; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts new file mode 100644 index 000000000000..963e2a06de8d --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -0,0 +1,1444 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x5000000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + // vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16+4 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + /* vdin1 CMA pool */ + // vdin1_cma_reserved:linux,vdin1_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x3c00000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x1800000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "wificonfig"; + key_code = <139>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "disabled"; + key_name = "vol-", "vol+", "enter", "wificonfig"; + key_num = <4>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28 139>; + key_val = <143 266 389 0>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <14>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; + ircut: ircut { + compatible = "amlogic, ircut"; + status = "okay"; + filter1-gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; + filter2-gpios = <&gpio GPIOH_7 GPIO_ACTIVE_HIGH>; + light_in-gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; + alarm-gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_HIGH>; + }; + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +//}; + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_tx_b_8", + "uart_ao_rx_b_9"; + function = "uart_ao_b"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { +// memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { +// memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + /*if card have no switch gpio, + * remove all relative to vol_switch + */ + vol_switch = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + vol_switch_18 = <1>; /* 1 = high, 0 = low */ + vol_switch_delay = <150>; /* Uint: ms*/ + + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", +// "MMC_CAP_UHS_SDR12", +// "MMC_CAP_UHS_SDR25", +// "MMC_CAP_UHS_SDR50", +// "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + //gpio-vbus-power = "GPIOH_6"; + //gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + //conflict with isp i2c + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; + + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; +&uart_AO_B { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins2>; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts index 6386b1423b23..0707e9bfb17e 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts @@ -21,6 +21,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -400,43 +401,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <731000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <731000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <731000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <741000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <771000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <801000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <821000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <851000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <901000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts new file mode 100644 index 000000000000..88df858d346b --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts @@ -0,0 +1,736 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "disabled"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "disabled"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "disabled"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "disabled"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "disabled"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + /*compatible = "amlogic, g12a-sound-card";*/ + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&pwm_ab { + status = "okay"; +}; + + +&audiobus { + aml_tdma: tdma { + /*compatible = "amlogic, g12a-snd-tdma";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + /*compatible = "amlogic, g12a-snd-tdmb";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + aml_tdmc: tdmc { + /*compatible = "amlogic, g12a-snd-tdmc";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + aml_spdif: spdif { + /*compatible = "amlogic, g12a-snd-spdif-a";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "disabled"; + }; + aml_spdif_b: spdif_b { + /*compatible = "amlogic, g12a-snd-spdif-b";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_b>; + status = "disabled"; + }; + aml_pdm: pdm { + /*compatible = "amlogic, g12a-snd-pdm";*/ + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_PM_KEEP_POWER", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi new file mode 100644 index 000000000000..5e5b58561126 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -0,0 +1,2637 @@ +/* + * arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include "g12b-sched-energy.dtsi" + +/ { + cpus:cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + cluster1:cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + core2 { + cpu = <&CPU4>; + }; + core3 { + cpu = <&CPU5>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x101>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU4:cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x102>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU5:cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x103>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <8000>; + exit-latency-us = <8000>; + min-residency-us = <20000>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + local-timer-stop; + entry-latency-us = <9000>; + exit-latency-us = <9000>; + min-residency-us = <25000>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0x0 0xffd0f190 0x0 0x4 0x0 0xffd0f194 0x0 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,armv8-pmuv3"; + clusterb-enabled; + interrupts = , + ; + reg = <0x0 0xff634680 0x0 0x4>, + <0x0 0xff6347c0 0x0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + meson_suspend:pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + reg = <0x0 0xff8000a8 0x0 0x4>, + <0x0 0xff80023c 0x0 0x4>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + clear_range = <0x05100000 0x200000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ + <0x0 0xfffe7000 0x0 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base { + reg = <0x0 0xffd00000 0x0 0x26000>; + }; + io_apb_base { + reg = <0x0 0xffe01000 0x0 0x7f000>; + }; + io_aobus_base { + reg = <0x0 0xff800000 0x0 0xb000>; + }; + io_vapb_base { + reg = <0x0 0xff900000 0x0 0x50000>; + }; + io_hiu_base { + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu { + compatible = "amlogic, vpu-g12b"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8 + 0x0 0xff64c000 0x0 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0x0 0xff800014 0x0 0x8>, + <0x0 0xff800024 0x0 0x14>, + <0x0 0xff80001c 0x0 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0x0 0xff6346c0 0x0 0x40>, + <0x0 0xff6344e8 0x0 0x18>, + <0x0 0xff634520 0x0 0x18>, + <0x0 0xff634440 0x0 0x4c>, + <0x0 0xff634740 0x0 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x100 + 0x0 0xff636000 0x0 0x2000 + 0x0 0xff63a000 0x0 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0x0 0xffe09080 0x0 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0x0 0xffd0f0d0 0x0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0x0 0xff809000 0x0 0x48>; + }; + + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x26000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-g12a-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, gxl_measure"; + reg = <0x0 0x18004 0x0 0x4 + 0x0 0x1800c 0x0 0x4>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x13000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x15000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0xb000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0xb000>; + + cpu_version { + reg=<0x0 0x220 0x0 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,g12b-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x320>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0x6000 0x0 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0x0 0xff634400 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff634400 0x0 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,g12b-clkc-1"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + clkc_b: clock-controller@1 { + compatible = "amlogic,g12b-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xff642000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0x0 0xff642000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>; + clkaudio: audio_clocks { + compatible = "amlogic, g12a-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, g12a-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "frddr_a", "frddr_b", "frddr_c"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0x0 0xff808040 0x00 0x44>, /*Multi-format IR controller*/ + <0x0 0xff808000 0x00 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd22000 0x0 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfc000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfc400000 0x0 0x200000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B + */ + ic_type = <11>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 147 1>; + interrupt-names = "galcore"; + reg = <0x0 0xff100000 0x0 0x800 + 0x0 0xff000000 0x0 0x400000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-g12a"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "G12B"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400 + 0x0 0xFF634400 0x0 0x26>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-g12b"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base{ + reg = <0x0 0xffd00000 0x0 0x100000>; + }; + io_dos_base{ + reg = <0x0 0xff620000 0x0 0x10000>; + }; + io_hiubus_base{ + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + io_aobus_base{ + reg = <0x0 0xff800000 0x0 0x10000>; + }; + io_vcbus_base{ + reg = <0x0 0xff900000 0x0 0x40000>; + }; + io_dmc_base{ + reg = <0x0 0xff638000 0x0 0x2000>; + }; + io_efuse_base{ + reg = <0x0 0xff630000 0x0 0x2000>; + }; + }; + + gdc:gdc { + #address-cells=<2>; + #size-cells=<2>; + status = "ok"; + compatible = "amlogic, g12b-gdc"; + reg = <0 0xFF950000 0 0x0000100 + 0 0xFF63C16C 0 0x0000004 + 0 0xFF63C100 0 0x0000004>; + interrupts = <0 144 1>; + interrupt-names = "GDC"; + clocks = <&clkc CLKID_GDC_CORE_CLK_COMP + &clkc CLKID_GDC_AXI_CLK_COMP >; + clock-names = "core","axi"; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_reg_base{ + reg = <0x0 0xff610000 0x0 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: meson-fb { + compatible = "amlogic, meson-g12b"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0xff80014c 0x0 0x10>, + <0x0 0xff800040 0x0 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "disabled"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0x0 0xffe03000 0x0 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <120>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpufreq_cool_cluster1 { + min_state = <1000000>; + dyn_coeff = <460>; + cluster_id = <1>; + gpu_pp = <2>; + node_name = "cpufreq_cool1"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + cpucore_cool_cluster1 { + min_state = <0>; + dyn_coeff = <0>; + cluster_id = <1>; + gpu_pp = <2>; + node_name = "cpucore_cool1"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpufreq_cool1:cpufreq_cool1 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool1:cpucore_cool1 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map0 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 10>; + contribution = <1024>; + }; + cpufreq_cooling_map1 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool1 0 9>; + contribution = <1024>; + }; + cpucore_cooling_map0 { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 1>; + contribution = <1024>; + }; + cpucore_cooling_map1 { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool1 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF640000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + audiolocker_base { + reg = <0x0 0xFF64A000 0x0 0x2000>; + }; + eqdrc_base { + reg = <0x0 0xFF656000 0x0 0x1800>; + }; + reset_base { + reg = <0x0 0xFFD01000 0x0 0x1000>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + vddcpu1: pwmab_a-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_a_e2>; + pwms = <&pwm_ab MESON_PWM_0 1250 0>; + regulator-name = "vddcpu1"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff630218 0x0 0x4>; + quality = /bits/ 16 <1000>; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x100 + 0x0 0xff638c00 0x0 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + isp_sc: isp-sc@ff655400 { + compatible = "amlogic, isp-sc"; + reg = <0x0 0xff655400 0x0 0x00001000>; + reg-names = "isp_sc"; + interrupts = <0 17 0>; + interrupt-names = "isp_sc"; + }; + + isp: isp@ff140000 { + compatible = "arm, isp"; + reg = <0x0 0xff140000 0x0 0x00040000>; + reg-names = "ISP"; + interrupts = <0 142 4>; + interrupt-names = "ISP"; + temper-buf-size = <24>; + clocks = <&clkc CLKID_MIPI_ISP_CLK_COMP>, + <&clkc CLKID_MIPI_CSI_PHY_CLK0_COMP>; + clock-names = "cts_mipi_isp_clk_composite", + "cts_mipi_csi_phy_clk0_composite"; + link-device = <&isp_sc>; + }; + + adapter: isp-adapter@ff650000 { + compatible = "amlogic, isp-adapter"; + reg = <0x0 0xff650000 0x0 0x00006000>; + reg-names = "adapter"; + interrupts = <0 179 0>; + interrupt-names = "adapter-irq"; + }; + + phycsi: phy-csi@ff650000 { + compatible = "amlogic, phy-csi"; + reg = <0x0 0xff650000 0x0 0x00002000>, + <0x0 0xff652000 0x0 0x00002000>, + <0x0 0xff63c300 0x0 0x00000100>, + <0x0 0xff654000 0x0 0x00000100>, + <0x0 0xff654400 0x0 0x00000100>; + reg-names = "csi2_phy0", "csi2_phy1", "aphy_reg", + "csi0_host", "csi1_host"; + interrupts = <0 41 0>, + <0 42 0>, + <0 72 0>, + <0 74 0>, + <0 87 0>, + <0 88 0>; + interrupt-names = "phy0-irq", + "phy1-irq", + "csi-host0-intr2", + "csi-host0-intr1", + "csi-host1-intr2", + "csi-host1-intr1"; + link-device = <&adapter>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0xff630218 0x0 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; +};/* end of / */ + +&pinctrl_aobus { + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_gpioe"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_b_pins3: pwm_b_pins3 { + mux { + groups = "pwm_b_h"; + function = "pwm_b"; + }; + }; + + pwm_b_pins4: pwm_b_pins4 { + mux { + groups = "pwm_b_z0"; + function = "pwm_b"; + }; + }; + + pwm_b_pins5: pwm_b_pins5 { + mux { + groups = "pwm_b_z13"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_c_pins4: pwm_c_pins4 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_d_pins3: pwm_d_pins3 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_d_pins4: pwm_d_pins4 { + mux { + groups = "pwm_d_a4"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + pwm_f_pins3: pwm_f_pins3 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + pwm_f_pins4: pwm_f_pins4 { + mux { + groups = "pwm_f_a11"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + irblaster_pins2:irblaster_pins2 { + mux { + groups = "remote_out_h"; + function = "remote_out"; + }; + }; + + irblaster_pins3:irblaster_pins3 { + mux { + groups = "remote_out_z"; + function = "remote_out"; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&gpu{ + system-coherency = <0>; + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ From dab67a6df58d8ed40bf06c373515e226a6f504af Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Mon, 25 Feb 2019 16:41:15 +0800 Subject: [PATCH 0047/1060] dts: fix amlogic-dt-id error in g12b dts. [1/1] PD#SWPL-5020 Problem: amlogic-dt-id error in g12b dts. Solution: specify amlogic-dt-id by dts name. Verify: local test. Change-Id: I11a737ec61221c2dc9fcd4e3761c380ac5b5044b Signed-off-by: Jianxiong Pan --- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_pxp.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_pxp_a.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_pxp.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 7e048d39bfe2..89a20424f3c4 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -23,7 +23,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_b"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts index 9924f15ed81a..c1e044928497 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -23,7 +23,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_a"; + amlogic-dt-id = "g12b_skt_a"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp.dts b/arch/arm/boot/dts/amlogic/g12b_pxp.dts index 610d41a937cb..553477d5a71a 100644 --- a/arch/arm/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12b_pxp.dts @@ -21,7 +21,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_b"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts b/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts index 96d4f3364f43..593d51b6b906 100644 --- a/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts @@ -21,7 +21,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_a"; + amlogic-dt-id = "g12b_skt_a"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 75d1231c6140..b8a937f62565 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -23,7 +23,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_b"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts index c93c993808c2..1ce3d622b959 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -23,7 +23,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_a"; + amlogic-dt-id = "g12b_skt_a"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index a06643eb8022..3946e6c84178 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -21,7 +21,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_b"; + amlogic-dt-id = "g12b_w411_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index 963e2a06de8d..b72068d9ee14 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -21,7 +21,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_a"; + amlogic-dt-id = "g12b_w411_a"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts index 0707e9bfb17e..db484a40b905 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts @@ -21,7 +21,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_b"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts index 88df858d346b..b1e9088a1665 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts @@ -21,7 +21,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12b_w400_a"; + amlogic-dt-id = "g12b_skt_a"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; From dba7aff98c372b6dcf1d849935a8a1ae01e46b83 Mon Sep 17 00:00:00 2001 From: "pan.yang" Date: Mon, 4 Mar 2019 02:29:15 -0500 Subject: [PATCH 0048/1060] dts: add new frequency for A53 core at all g12b RevB dts [1/1] PD#SWPL-5020 Problem: need 1.9G for A53 core in g12b RevB. Solution: add 1.9G frequency for A53 core in RevB dts. Verify: local test. Change-Id: Ic4085c05b3b9d18f759720e3d268d5e4629faba7 Signed-off-by: pan.yang --- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 4 ++++ arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 4 ++++ .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 4 ++++ arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 4 ++++ arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts | 4 ++++ .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 4 ++++ .../dts/amlogic/g12b_a311x_w411_buildroot.dts | 16 ++++++++++++++++ 7 files changed, 40 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 89a20424f3c4..3a4a933f1127 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -692,6 +692,10 @@ opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <981000>; }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 5f9faebc091d..9a6d701abf96 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -660,6 +660,10 @@ opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <981000>; }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 4b1e5640e567..b833409eb43d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -755,6 +755,10 @@ opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <981000>; }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index b8a937f62565..7ac576879a5b 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -692,6 +692,10 @@ opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <981000>; }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index ed4a731e89d2..9a70c6a09ca3 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -660,6 +660,10 @@ opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <981000>; }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index edf4017fb5a9..8d820f050782 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -754,6 +754,10 @@ opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <981000>; }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index 3946e6c84178..694dafc0cb48 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -735,6 +735,22 @@ opp-hz = /bits/ 64 <1512000000>; opp-microvolt = <791000>; }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; }; cpu_opp_table1: cpu_opp_table1 { From 7c26012c556728c4b4b8392e66ce330fbf2f044e Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Tue, 26 Feb 2019 14:57:44 +0800 Subject: [PATCH 0049/1060] dts: g12b: modify sched-energy dts for w400 revision-b [1/1] PD#SWPL-5020 Problem: modify sched-energy dts for w400 revision-b Solution: modify dts Verify: local. Change-Id: I6686abc10bf07ec0e601eb9a72b7657ca3e1d991 Signed-off-by: Hanjie Lin --- .../boot/dts/amlogic/g12b-sched-energy-a.dtsi | 87 +++++++++++++++++++ .../boot/dts/amlogic/g12b-sched-energy.dtsi | 14 ++- arch/arm/boot/dts/amlogic/mesong12b_a.dtsi | 2 +- .../boot/dts/amlogic/g12b-sched-energy-a.dtsi | 87 +++++++++++++++++++ .../boot/dts/amlogic/g12b-sched-energy.dtsi | 14 ++- arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 2 +- 6 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi diff --git a/arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi b/arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi new file mode 100644 index 000000000000..184be9d06b57 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi @@ -0,0 +1,87 @@ + +/ { + energy-costs { + CPU_COST_A73: core-cost0 { + busy-cost-data = < + 54 17 + 135 110 + 270 202 + 360 264 + 540 396 + 648 470 + 755 557 + 816 620 + 868 699 + 920 759 + /*1024 1024*/ + >; + idle-cost-data = < + 5 + 0 + 0 + >; + }; + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 465 116 + 503 135 + 535 162 + 567 184 + 599 224 + 631 279 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + CLUSTER_COST_A73: cluster-cost0 { + busy-cost-data = < + 54 17 + 135 20 + 270 25 + 360 27 + 540 35 + 648 40 + 755 49 + 816 57 + 868 54 + 920 64 + /*1024 79*/ + >; + idle-cost-data = < + 10 + 10 + 0 + >; + }; + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 465 19 + 503 23 + 535 26 + 567 31 + 599 36 + 631 42 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi b/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi index 796f592ae9f7..9177949abde1 100644 --- a/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi +++ b/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi @@ -13,7 +13,11 @@ 816 620 868 699 920 759 - /*1024 1024*/ + 972 819 + 1030 887 + 1088 937 + 1134 976 + 1192 1048 >; idle-cost-data = < 5 @@ -33,6 +37,7 @@ 503 135 535 162 567 184 + 599 224 631 279 >; idle-cost-data = < @@ -53,7 +58,11 @@ 816 57 868 54 920 64 - /*1024 79*/ + 972 75 + 1030 86 + 1088 97 + 1134 108 + 1192 110 >; idle-cost-data = < 10 @@ -73,6 +82,7 @@ 503 23 535 26 567 31 + 599 36 631 42 >; idle-cost-data = < diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi index f022bbc6a020..9e6514fa6ccc 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -27,7 +27,7 @@ #include #include #include "mesong12a-bifrost.dtsi" -#include "g12b-sched-energy.dtsi" +#include "g12b-sched-energy-a.dtsi" / { cpus:cpus { diff --git a/arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi b/arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi new file mode 100644 index 000000000000..184be9d06b57 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi @@ -0,0 +1,87 @@ + +/ { + energy-costs { + CPU_COST_A73: core-cost0 { + busy-cost-data = < + 54 17 + 135 110 + 270 202 + 360 264 + 540 396 + 648 470 + 755 557 + 816 620 + 868 699 + 920 759 + /*1024 1024*/ + >; + idle-cost-data = < + 5 + 0 + 0 + >; + }; + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 465 116 + 503 135 + 535 162 + 567 184 + 599 224 + 631 279 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + CLUSTER_COST_A73: cluster-cost0 { + busy-cost-data = < + 54 17 + 135 20 + 270 25 + 360 27 + 540 35 + 648 40 + 755 49 + 816 57 + 868 54 + 920 64 + /*1024 79*/ + >; + idle-cost-data = < + 10 + 10 + 0 + >; + }; + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 465 19 + 503 23 + 535 26 + 567 31 + 599 36 + 631 42 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi b/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi index 796f592ae9f7..9177949abde1 100644 --- a/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi +++ b/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi @@ -13,7 +13,11 @@ 816 620 868 699 920 759 - /*1024 1024*/ + 972 819 + 1030 887 + 1088 937 + 1134 976 + 1192 1048 >; idle-cost-data = < 5 @@ -33,6 +37,7 @@ 503 135 535 162 567 184 + 599 224 631 279 >; idle-cost-data = < @@ -53,7 +58,11 @@ 816 57 868 54 920 64 - /*1024 79*/ + 972 75 + 1030 86 + 1088 97 + 1134 108 + 1192 110 >; idle-cost-data = < 10 @@ -73,6 +82,7 @@ 503 23 535 26 567 31 + 599 36 631 42 >; idle-cost-data = < diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index 5e5b58561126..7b712f3abbdc 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -27,7 +27,7 @@ #include #include #include "mesong12a-bifrost.dtsi" -#include "g12b-sched-energy.dtsi" +#include "g12b-sched-energy-a.dtsi" / { cpus:cpus { From 2be000d51eb7d519822530abb2a8bd6515077a67 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Fri, 22 Feb 2019 17:18:36 +0800 Subject: [PATCH 0050/1060] clk: g12a/g12b: fix syspll overflow when freq larger than 2.1g [1/1] PD#SWPL-5076 Problem: syspll overflow Solution: div 1000 when round rate Verify: test pass on g12a skt/w400 Change-Id: I021a1e8fd1280b27e21e5b4c8983b91fb89e84ba Signed-off-by: Shunzhou Jiang --- drivers/amlogic/clk/g12a/g12a_clk-pll.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 858a088f4daf..194ba7dc1769 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -179,14 +179,23 @@ static long meson_g12a_pll_round_rate(struct clk_hw *hw, unsigned long rate, struct meson_clk_pll *pll = to_meson_clk_pll(hw); const struct pll_rate_table *rate_table = pll->rate_table; int i; + u64 ret_rate = 0; for (i = 0; i < pll->rate_count; i++) { - if (rate <= rate_table[i].rate) - return rate_table[i].rate; + if (rate <= rate_table[i].rate) { + ret_rate = rate_table[i].rate; + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "sys1_pll")) + do_div(ret_rate, 1000); + return ret_rate; + } } /* else return the smallest value */ - return rate_table[0].rate; + ret_rate = rate_table[0].rate; + if (!strcmp(clk_hw_get_name(hw), "sys_pll")) + do_div(ret_rate, 1000); + return ret_rate; } static const struct pll_rate_table *meson_g12a_get_pll_settings @@ -233,6 +242,9 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (parent_rate == 0 || rate == 0) return -EINVAL; + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "sys1_pll")) + rate *= 1000; old_rate = rate; From a709ba67b05127d888deb7c1d203db940f1d0284 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 1 Mar 2019 03:16:45 +0800 Subject: [PATCH 0051/1060] vpp: sr: correct the sr core0 enable switch operation [1/1] PD#SWPL-5113 Problem: SR core0 enable switch register is latched as default. It will cause the screen flicker when operating this bit in vsync. Because the frame size will be out of sync with back-end module. Solution: 1. For g12a, no latch ctrl. So did not disable sr core2 enable bit. 2. For g12b/tl1, disable the latch function. Verify: Verified on U212/w400/x301 Change-Id: I54027b71ef8a6066004b3bd32ed1633b4bfa351c Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 4 ++-- drivers/amlogic/media/video_sink/vpp.c | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 48914144bf8c..ba244948b1fe 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -12071,13 +12071,13 @@ static int __init video_early_init(void) DOLBY_PATH_CTRL, 0xf, 0, 6); /* disable latch for sr core0/1 scaler */ WRITE_VCBUS_REG_BITS( - SRSHARP0_SHARP_SYNC_CTRL, 1, 8, 1); + SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); WRITE_VCBUS_REG_BITS( SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1); } if (is_meson_g12b_cpu()) WRITE_VCBUS_REG_BITS( - SRSHARP0_SHARP_SYNC_CTRL, 1, 8, 1); + SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); return 0; } diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 5eda6a083f2e..d2f781268848 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1614,11 +1614,16 @@ int vpp_set_super_scaler_regs( int tmp_data = 0; int tmp_data2 = 0; unsigned int data_path_chose; + int sr_core0_max_width = SUPER_CORE0_WIDTH_MAX; + + /* just work around for g12a not to disable sr core2 bit2 */ + if (is_meson_g12a_cpu() && (reg_srscl0_vert_ratio == 0)) + sr_core0_max_width = SUPER_CORE0_WIDTH_MAX << 1; /* top config */ tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP0_CTRL); if (sr0_sr1_refresh) { - if (reg_srscl0_hsize > SUPER_CORE0_WIDTH_MAX) { + if (reg_srscl0_hsize > sr_core0_max_width) { if (((tmp_data >> 1) & 0x1) != 0) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 0, 1, 1); @@ -1650,7 +1655,7 @@ int vpp_set_super_scaler_regs( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, reg_srscl0_hori_ratio&0x1, 4, 1); - if (reg_srscl0_hsize > SUPER_CORE0_WIDTH_MAX) { + if (reg_srscl0_hsize > sr_core0_max_width) { if (((tmp_data >> 2) & 0x1) != 0) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, From ad90827872c45e3ca2a6e0c3cb7ec075384c74de Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Fri, 1 Feb 2019 09:45:46 +0800 Subject: [PATCH 0052/1060] clk: g12a/g12b: update pcie clk parameter for jitter [1/1] PD#SWPL-4745 Problem: update pcie parameter for jitter Solution: clear pcie clk parameter Verify: test pass on g12a skt/w400 Change-Id: I354d643c412c37fb6c99fc49ac5bd70ab12be008 Signed-off-by: Shunzhou Jiang --- drivers/amlogic/clk/g12a/g12a_clk-pll.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 194ba7dc1769..0f67ff3eccb2 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -51,10 +51,10 @@ /* G12A */ //#define G12A_PCIE_PLL_CNTL 0x400106c8 -#define G12A_PCIE_PLL_CNTL0_0 0x20090496 -#define G12A_PCIE_PLL_CNTL0_1 0x30090496 -#define G12A_PCIE_PLL_CNTL0_2 0x34090496 -#define G12A_PCIE_PLL_CNTL0_3 0x14090496 +#define G12A_PCIE_PLL_CNTL0_0 0x28060464 +#define G12A_PCIE_PLL_CNTL0_1 0x38060464 +#define G12A_PCIE_PLL_CNTL0_2 0x3c060464 +#define G12A_PCIE_PLL_CNTL0_3 0x1c060464 #define G12A_PCIE_PLL_CNTL1 0x00000000 #define G12A_PCIE_PLL_CNTL2 0x00001100 #define G12A_PCIE_PLL_CNTL2_ 0x00001000 @@ -64,10 +64,10 @@ #define G12A_PCIE_PLL_CNTL5 0x68000048 #define G12A_PCIE_PLL_CNTL5_ 0x68000068 -#define G12B_PCIE_PLL_CNTL0_0 0x200c04c8 -#define G12B_PCIE_PLL_CNTL0_1 0x300c04c8 -#define G12B_PCIE_PLL_CNTL0_2 0x340c04c8 -#define G12B_PCIE_PLL_CNTL0_3 0x140c04c8 +#define G12B_PCIE_PLL_CNTL0_0 0x28060464 +#define G12B_PCIE_PLL_CNTL0_1 0x38060464 +#define G12B_PCIE_PLL_CNTL0_2 0x3c060464 +#define G12B_PCIE_PLL_CNTL0_3 0x1c060464 #define G12B_PCIE_PLL_CNTL1 0x00000000 #define G12B_PCIE_PLL_CNTL2 0x00001100 #define G12B_PCIE_PLL_CNTL2_ 0x00001000 From c78cd4b9fb2ca6dc2deb28cbd0fc1b4ec89d96dd Mon Sep 17 00:00:00 2001 From: Nan Li Date: Fri, 1 Feb 2019 09:59:00 +0800 Subject: [PATCH 0053/1060] emmc: optimize the conditions of fixdiv calc [1/1] PD#SWPL-4857 Problem: fixdiv calc Affect the use of other chips Solution: Adjust the usage conditions for the fixdiv calc func, witch pdata->calc_f from dts. Verify: verify by g12b Change-Id: I9598e2a24f76c76f4312c2694029fe4bb0f534d4 Signed-off-by: Nan Li --- drivers/amlogic/mmc/aml_sd_emmc.c | 2 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 12 +++++++----- include/linux/amlogic/aml_sd_emmc_internal.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 71a5a47a80e1..c512a80f2fbc 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -1064,7 +1064,7 @@ static int aml_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) } -static void aml_mmc_clk_switch_off(struct amlsd_platform *pdata) +void aml_mmc_clk_switch_off(struct amlsd_platform *pdata) { u32 vcfg = 0; struct sd_emmc_config *conf = (struct sd_emmc_config *)&vcfg; diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index a5e4b2a5dfee..0f03a6a7c4ad 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -174,7 +174,7 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, #ifdef SD_EMMC_CLK_CTRL if (clk_ios == 0) { - aml_mmc_clk_switch_off(host); + aml_mmc_clk_switch_off(pdata); return ret; } @@ -260,10 +260,12 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, /* (re)start clock, if non-zero */ if (clk_ios) { - vclkc = readl(host->base + SD_EMMC_CLOCK_V3); - pdata->clk_lay.source - = clk_get_rate(host->cfg_div_clk) * clkc->div; - pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); + if (pdata->calc_f) { + vclkc = readl(host->base + SD_EMMC_CLOCK_V3); + pdata->clk_lay.source + = clk_get_rate(host->cfg_div_clk) * clkc->div; + pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); + } vcfg = readl(host->base + SD_EMMC_CFG); conf->stop_clk = 0; diff --git a/include/linux/amlogic/aml_sd_emmc_internal.h b/include/linux/amlogic/aml_sd_emmc_internal.h index a63caf11129f..e28f9c306129 100644 --- a/include/linux/amlogic/aml_sd_emmc_internal.h +++ b/include/linux/amlogic/aml_sd_emmc_internal.h @@ -16,8 +16,8 @@ */ #ifndef __AML_SD_EMMC_INTERNAL_H__ - #define __AML_SD_EMMC_INTERNAL_H__ + extern int aml_emmc_clktree_init(struct amlsd_host *host); extern int meson_mmc_clk_init_v3(struct amlsd_host *host); From 6748aa83cae77f9902a778e13b62c9abbfba6b53 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Mon, 28 Jan 2019 10:18:11 +0800 Subject: [PATCH 0054/1060] config: replace stack protector config [1/1] PD#SWPL-4617 Problem: CONFIG_CC_STACKPROTECTOR_STRONG will increase stack size for some large functions and may cause stack overflow problems or increase real stack usage after we have enabled VMAP STACK config. But direct remove it from defconfig will cause CTS fail. Solution: using CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC for real stack protect config Verify: p212 Change-Id: I1ccba2ef6ab5ea6f2987af2986e0cf222da1a7c7 Signed-off-by: Tao Zeng --- Makefile | 2 +- arch/Kconfig | 5 +++++ arch/arm64/configs/meson64_defconfig | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b656d5962a9f..a5d29b9dd573 100644 --- a/Makefile +++ b/Makefile @@ -765,7 +765,7 @@ ifdef CONFIG_CC_STACKPROTECTOR_REGULAR stackp-flag := -fstack-protector stackp-name := REGULAR else -ifdef CONFIG_CC_STACKPROTECTOR_STRONG +ifdef CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC stackp-flag := -fstack-protector-strong stackp-name := STRONG else diff --git a/arch/Kconfig b/arch/Kconfig index 2fa953f81ffb..20fd67d7d01c 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -450,6 +450,11 @@ config CC_STACKPROTECTOR_REGULAR by about 0.3%. config CC_STACKPROTECTOR_STRONG + bool "Strong" + help + Since this config will increase stack size. We repleace it + +config CC_STACKPROTECTOR_STRONG_AMLOGIC bool "Strong" select CC_STACKPROTECTOR help diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 233545a5ca92..54e134d37179 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -30,6 +30,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y From acb5a6afd269a8d2275519265d5194d0ca8253a4 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Wed, 30 Jan 2019 00:13:45 +0800 Subject: [PATCH 0055/1060] vpp: disable sr scale up when vskip > 2 [1/1] PD#TV-2331 Problem: SR insert unnecessary scale up to make scale down ratio too larger. Solution: disable SR core0 which is before pps when mif vskip is > 2 Verify: Locally on X301 Change-Id: I810fbae20f337e6eeb0a8e88d9758f78ad224254 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/vpp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index d2f781268848..2535a42d695b 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1927,6 +1927,14 @@ static void vpp_set_super_scaler( next_frame_par->supsc0_hori_ratio = 0; next_frame_par->supsc0_vert_ratio = 0; } + + /* much vskip case, no need super scale up */ + if (next_frame_par->vscale_skip_count >= 2) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + } + if (bypass_sr1 || !(sr_support & SUPER_CORE1_SUPPORT)) { next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_hori_ratio = 0; From e153d06eb35210db89e06a95246d7ab1d18b1800 Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Mon, 18 Feb 2019 20:03:16 +0800 Subject: [PATCH 0056/1060] perf: arm: enable pmuserenr [1/1] PD#SWPL-4673 Problem: userspace can't access perf monitor cnt with "mrc ... c9,c13,0" Solution: actually userspace should check perf monitor cnt access permissions first before use, so this is a workround. enable pmuserenr with "mcr ... c9,c14,0" in several places: 1, perf probe 2, cpu idle (state>0) exit 3, cpu online 4, system resume after suspend Verify: u212 Change-Id: Ib09682d1d47545dfef8b088283ddbbf390630d3e Signed-off-by: Hanjie Lin --- arch/arm/include/asm/perf_event.h | 5 ++ arch/arm/kernel/cpuidle.c | 18 ++++++- arch/arm/kernel/perf_event_v7.c | 86 +++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 2501bd0977e6..6241c4d9de6a 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -29,4 +29,9 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); (regs)->ARM_sp = current_stack_pointer; \ (regs)->ARM_cpsr = SVC_MODE; \ } + +#ifdef CONFIG_AMLOGIC_MODIFY +void enable_pmuserenr(void); +#endif + #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c index a3308ad1a024..b802508813a2 100644 --- a/arch/arm/kernel/cpuidle.c +++ b/arch/arm/kernel/cpuidle.c @@ -13,6 +13,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#endif extern struct of_cpuidle_method __cpuidle_method_of_table[]; @@ -51,9 +54,22 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev, */ int arm_cpuidle_suspend(int index) { +#ifdef CONFIG_AMLOGIC_MODIFY + int ret; + int cpu = smp_processor_id(); + + ret = cpuidle_ops[cpu].suspend(index); + + if (index > 0) { + pr_debug("arm_cpuidle_suspend(%d) exit\n", index); + enable_pmuserenr(); + } + return ret; +#else int cpu = smp_processor_id(); return cpuidle_ops[cpu].suspend(index); +#endif } /** @@ -135,7 +151,7 @@ static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu) * this cpu, * -ENOENT if it fails to find an 'enable-method' property, * -ENXIO if the HW reports a failure or a misconfiguration, - * -ENOMEM if the HW report an memory allocation failure + * -ENOMEM if the HW report an memory allocation failure */ int __init arm_cpuidle_init(int cpu) { diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 836efdda3d80..2cfc7f030076 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -28,6 +28,10 @@ #include #include +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#endif + /* * Common ARMv7 event types * @@ -2038,8 +2042,86 @@ static const struct pmu_probe_info armv7_pmu_probe_table[] = { { /* sentinel value */ } }; +#ifdef CONFIG_AMLOGIC_MODIFY +#if 0 +static int read_pmuserenr(void) +{ + int val = -1; + + asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (val):: "memory"); + return val; +} +#endif + +void enable_pmuserenr(void) +{ + //pr_emerg("enable_pmuserenr() start, val = %d\n", read_pmuserenr()); + asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (1) : "memory"); + //pr_emerg("enable_pmuserenr() end, val = %d\n", read_pmuserenr()); +} + +static void enable_pmuserenr_single(void *info) +{ + enable_pmuserenr(); +} + +static void enable_pmuserenr_all(void) +{ + pr_info("enable_pmuserenr_all() start\n"); + + enable_pmuserenr_single(NULL); + smp_call_function_many(cpu_possible_mask, + enable_pmuserenr_single, + NULL, + 1); + + pr_info("enable_pmuserenr_all() end\n"); +} + +static int pmu_user_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + pr_debug("cpu online callback\n"); + enable_pmuserenr(); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block pmu_user_notify = { + &pmu_user_callback, + NULL, + 0 +}; + +static int armv7_pmu_resume(struct platform_device *pdev) +{ + pr_debug("armv7_pmu_resume()\n"); + enable_pmuserenr(); + return 0; +} + +static int armv7_pmu_suspend(struct platform_device *pdev, + pm_message_t state) +{ + pr_debug("armv7_pmu_suspend()\n"); + return 0; +} +#endif + static int armv7_pmu_device_probe(struct platform_device *pdev) { +#ifdef CONFIG_AMLOGIC_MODIFY + enable_pmuserenr_all(); + __register_cpu_notifier(&pmu_user_notify); +#endif + return arm_pmu_device_probe(pdev, armv7_pmu_of_device_ids, armv7_pmu_probe_table); } @@ -2050,6 +2132,10 @@ static struct platform_driver armv7_pmu_driver = { .of_match_table = armv7_pmu_of_device_ids, }, .probe = armv7_pmu_device_probe, +#ifdef CONFIG_AMLOGIC_MODIFY + .suspend = armv7_pmu_suspend, + .resume = armv7_pmu_resume, +#endif }; static int __init register_armv7_pmu_driver(void) From cff1d2abfc830a2cd50c7776febc526c127a4f39 Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Thu, 31 Jan 2019 10:58:01 +0800 Subject: [PATCH 0057/1060] sched: eas: add sched-energy support for gxm [1/1] PD#SWPL-4651 Problem: Kernel 32bit Support for S912(kernel 4.9) Solution: add arm/arm64 sched-energy dts Verify: q201 Change-Id: I13077632b730d5f2b1427b3d9bee9ff24031cfcd Signed-off-by: Hanjie Lin --- .../boot/dts/amlogic/gxm-sched-energy.dtsi | 68 +++++++++++++++++++ arch/arm/boot/dts/amlogic/mesongxm.dtsi | 17 +++++ .../boot/dts/amlogic/gxm-sched-energy.dtsi | 68 +++++++++++++++++++ arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 17 +++++ 4 files changed, 170 insertions(+) create mode 100644 arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi diff --git a/arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi b/arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi new file mode 100644 index 000000000000..30fca0951f28 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi @@ -0,0 +1,68 @@ +/ { + energy-costs { + CPU_COST_A53_HS: core-cost0 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 503 135 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CLUSTER_COST_A53_HS: cluster-cost0 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 503 23 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + }; +}; diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index a0a01d08676a..d4e5245b936a 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -26,6 +26,7 @@ #include #include #include "mesongxm-gpu-t82x.dtsi" +#include "gxm-sched-energy.dtsi" / { cpus:cpus { #address-cells = <1>; @@ -69,6 +70,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -83,6 +86,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -97,6 +102,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -111,6 +118,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -125,6 +134,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -139,6 +150,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -152,6 +165,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -166,6 +181,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; diff --git a/arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi b/arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi new file mode 100644 index 000000000000..30fca0951f28 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi @@ -0,0 +1,68 @@ +/ { + energy-costs { + CPU_COST_A53_HS: core-cost0 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 503 135 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CLUSTER_COST_A53_HS: cluster-cost0 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 503 23 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 45c499073ac7..ef1e45ccbe03 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -26,6 +26,7 @@ #include #include #include "mesongxm-gpu-t82x.dtsi" +#include "gxm-sched-energy.dtsi" / { cpus:cpus { #address-cells = <2>; @@ -69,6 +70,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -83,6 +86,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -97,6 +102,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -111,6 +118,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -125,6 +134,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -139,6 +150,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -152,6 +165,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -166,6 +181,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; From 85aba15a901a518794b2fdf43df8e9e4d52abf01 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 15 Feb 2019 10:39:14 +0800 Subject: [PATCH 0058/1060] audio: remove unused PDM controls which cause panic [1/1] PD#SWPL-3907 Problem: PDM controls are dynamically added or removed. This will bring in panic. Solution: Remove the unused controls. Verify: Need stress test. Change-Id: I69f63a0516e0812e9abb86e42f091ecb496004d4 Signed-off-by: Shuai Li --- sound/soc/amlogic/auge/pdm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index d4ef74f0e7b1..bf92cacb75ea 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -185,7 +185,7 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = { pdm_dclk_get_enum, pdm_dclk_set_enum), }; - +#if 0 static int pdm_mute_val_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -327,7 +327,7 @@ __error: return err; } - +#endif static irqreturn_t aml_pdm_isr_handler(int irq, void *data) { struct snd_pcm_substream *substream = @@ -830,13 +830,13 @@ int aml_pdm_dai_startup(struct snd_pcm_substream *substream, pr_err("Can't enable pcm clk_pdm_dclk clock: %d\n", ret); goto err; } - +#if 0 if (p_pdm->chipinfo && p_pdm->chipinfo->mute_fn) { struct snd_card *card = cpu_dai->component->card->snd_card; pdm_running_create_controls(card, p_pdm); } - +#endif return 0; err: pr_err("failed enable clock\n"); @@ -847,12 +847,13 @@ void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); - +#if 0 if (p_pdm->chipinfo && p_pdm->chipinfo->mute_fn) { struct snd_card *card = cpu_dai->component->card->snd_card; pdm_running_destroy_controls(card, p_pdm); } +#endif /* disable clock and gate */ clk_disable_unprepare(p_pdm->clk_pdm_dclk); From 0e2090b5cf8407555057f8ffaf290d5217de9e6b Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Mon, 18 Feb 2019 21:56:29 +0800 Subject: [PATCH 0059/1060] vpp: correct the vpp dummy reg for g12a/g12b/tl1 [1/1] PD#TV-1565 Problem: After g12a chip, vpp post dummy reg was changed. The test_screen/rgb_screen sysfs did not work. Solution: Use the correct vpp post dummy reg for those chip Verify: Verified on X301 and W400 Change-Id: I1cb718a1f7040804b63d0197de0bb6aafe233357 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index ba244948b1fe..b55ed351561d 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -10109,7 +10109,11 @@ static ssize_t video_test_screen_store(struct class *cla, #endif /* show test screen YUV blend*/ - if (is_meson_gxm_cpu() || + if (!legacy_vpp) + WRITE_VCBUS_REG( + VPP_POST_BLEND_BLEND_DUMMY_DATA, + test_screen & 0x00ffffff); + else if (is_meson_gxm_cpu() || (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX)) /* bit width change to 10bit in gxm, 10/12 in txlx*/ WRITE_VCBUS_REG(VPP_DUMMY_DATA1, @@ -10175,7 +10179,11 @@ static ssize_t video_rgb_screen_store(struct class *cla, #endif /* show test screen YUV blend*/ yuv_eight = rgb2yuv(rgb_screen & 0x00ffffff); - if (is_meson_gxtvbb_cpu()) { + if (!legacy_vpp) { + WRITE_VCBUS_REG( + VPP_POST_BLEND_BLEND_DUMMY_DATA, + yuv_eight & 0x00ffffff); + } else if (is_meson_gxtvbb_cpu()) { WRITE_VCBUS_REG(VPP_DUMMY_DATA1, rgb_screen & 0x00ffffff); } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { From 0757937741fac10420e6b1d00f230d73b5e0e9bc Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Tue, 19 Feb 2019 13:42:16 +0800 Subject: [PATCH 0060/1060] perf: fix sys_cpu_status0 reg error dts [1/1] PD#SWPL-4843 Problem: CtsSimpleperfTestCases 1 Fail on p231 Solution: gxl,gxm,txl perf sys_cpu_status0 reg config error modify it Verify: p212 Change-Id: Ie6e8747e8e4f02734bd7883ce6dcbc3fd3d28829 Signed-off-by: Hanjie Lin Signed-off-by: Luan Yuan Conflicts: arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm64/boot/dts/amlogic/mesontxl.dtsi --- arch/arm/boot/dts/amlogic/mesongxl.dtsi | 2 +- arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi | 2 +- arch/arm/boot/dts/amlogic/mesongxm.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index a3c2f4e29bf5..b3c787f8484a 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -136,7 +136,7 @@ compatible = "arm,cortex-a15-pmu"; /* clusterb-enabled; */ interrupts = ; - reg = <0xc8834400 0x4>; + reg = <0xc8834680 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; diff --git a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi index 53d782398b99..dfe090d26025 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -138,7 +138,7 @@ compatible = "arm,cortex-a15-pmu"; /* clusterb-enabled; */ interrupts = ; - reg = <0xc8834400 0x4>; + reg = <0xc8834680 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index d4e5245b936a..37d28d35e718 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -245,7 +245,7 @@ compatible = "arm,cortex-a15-pmu"; /* clusterb-enabled; */ interrupts = ; - reg = <0xc8834400 0x4>; + reg = <0xc8834680 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 5f5f4e97672a..a997334c8441 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -124,7 +124,7 @@ compatible = "arm,armv8-pmuv3"; /* clusterb-enabled; */ interrupts = ; - reg = <0x0 0xc8834400 0x0 0x4>; + reg = <0x0 0xc8834680 0x0 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi index ef80ea74d5a3..efaa61bd1434 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -138,7 +138,7 @@ compatible = "arm,armv8-pmuv3"; /* clusterb-enabled; */ interrupts = ; - reg = <0x0 0xc8834400 0x0 0x4>; + reg = <0x0 0xc8834680 0x0 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index ef1e45ccbe03..92bd78b11daf 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -245,7 +245,7 @@ compatible = "arm,armv8-pmuv3"; /* clusterb-enabled; */ interrupts = ; - reg = <0x0 0xc8834400 0x0 0x4>; + reg = <0x0 0xc8834680 0x0 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; From 6268a80f935c9609ca4c0dac81b24038095cb957 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Mon, 18 Feb 2019 16:44:22 +0800 Subject: [PATCH 0061/1060] license: add missing license header [1/1] PD#SWPL-4728 Problem: Missing license header Solution: Add correct license header Verify: Compling passed Change-Id: I291a41172f9ecf2cde7f7705e99ecb20567c9c8f Signed-off-by: Jiamin Ma --- arch/arm/mach-meson/hotplug-asm.S | 17 +++++++++++ drivers/amlogic/input/remote/rc_common.h | 16 ++++++++-- .../focaltech_touch/focaltech_flash.h | 29 +++++++++++-------- .../focaltech_upgrade_common.h | 29 +++++++++++-------- .../touchscreen/goodix_gt9xx/gt9xx_firmware.h | 28 +++++++++++------- .../amvecm/arch/vpp_keystone_regs.h | 17 +++++++++++ .../media/enhancement/amvecm/bitdepth.c | 17 +++++++++++ .../media/enhancement/amvecm/bitdepth.h | 17 +++++++++++ .../media/enhancement/amvecm/cm2_adj.h | 17 +++++++++++ .../amvecm/dnlp_algorithm/dnlp_alg.h | 16 ++++++++++ .../media/enhancement/amvecm/dnlp_cal.c | 17 +++++++++++ .../media/enhancement/amvecm/dnlp_cal.h | 16 ++++++++++ .../enhancement/amvecm/keystone_correction.c | 17 +++++++++++ .../enhancement/amvecm/keystone_correction.h | 17 +++++++++++ .../media/enhancement/amvecm/local_contrast.c | 17 ++++++++++- .../media/enhancement/amvecm/set_hdr2_v0.c | 19 ++++++++++-- .../media/enhancement/amvecm/set_hdr2_v0.h | 17 +++++++++++ drivers/amlogic/secure_monitor/flash_mutex.S | 17 +++++++++++ .../usb/dwc_otg/310/common_port/dwc_mem.c | 18 +++++++++++- .../usb/dwc_otg/310/common_port/dwc_modpow.h | 17 +++++++++-- .../dwc_otg/310/common_port/dwc_notifier.c | 17 +++++++++++ .../dwc_otg/310/common_port/dwc_notifier.h | 17 +++++++++++ .../amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h | 17 +++++++++++ include/dt-bindings/clock/meson8b-clkc.h | 15 +++++++++- include/dt-bindings/iio/adc/amlogic-saradc.h | 15 +++++++++- include/dt-bindings/input/meson_rc.h | 16 ++++++++++ include/linux/amlogic/debug_lockup.h | 17 +++++++++++ include/linux/amlogic/dhd_buf.h | 17 +++++++++++ .../media/amdolbyvision/dolby_vision.h | 17 +++++++++++ include/linux/meson_ion.h | 17 +++++++++++ include/trace/events/meson_atrace.h | 15 +++++++++- sound/soc/amlogic/meson/dmic.h | 17 +++++++++++ 32 files changed, 524 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-meson/hotplug-asm.S b/arch/arm/mach-meson/hotplug-asm.S index 1871afa6df56..cc172d243389 100644 --- a/arch/arm/mach-meson/hotplug-asm.S +++ b/arch/arm/mach-meson/hotplug-asm.S @@ -1,3 +1,20 @@ +/* + * arch/arm/mach-meson/hotplug-asm.S + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #include #include diff --git a/drivers/amlogic/input/remote/rc_common.h b/drivers/amlogic/input/remote/rc_common.h index 762a972c94ea..34203557c19b 100644 --- a/drivers/amlogic/input/remote/rc_common.h +++ b/drivers/amlogic/input/remote/rc_common.h @@ -1,10 +1,20 @@ /* - * include/uapi/linux/rc_common.h from the kernel directory, but it can be used - * in kernel and user space. + * drivers/amlogic/input/remote/rc_common.h * - * Written by Amlogic + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. * */ + #ifndef _UAPI_RC_COMMON_H_ #define _UAPI_RC_COMMON_H_ diff --git a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h index 53eed3e731b1..95a8a5422d9e 100644 --- a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h +++ b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h @@ -1,15 +1,20 @@ -/************************************************************************ -* Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved. -* -* File Name: focaltech_flash.h -* -* Author: fupeipei -* -* Created: 2016-08-07 -* -* Abstract: -* -************************************************************************/ +/* + * drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef __LINUX_FOCALTECH_FLASH_H__ #define __LINUX_FOCALTECH_FLASH_H__ diff --git a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h index 8b522b250b2e..a94ef90db532 100755 --- a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h +++ b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h @@ -1,15 +1,20 @@ -/************************************************************************ -* Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved. -* -* File Name: focaltech_upgrade_common.h -* -* Author: fupeipei -* -* Created: 2016-08-16 -* -* Abstract: -* -************************************************************************/ +/* + * focaltech_upgrade_common.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef __LINUX_FOCALTECH_UPGRADE_COMMON_H__ #define __LINUX_FOCALTECH_UPGRADE_COMMON_H__ diff --git a/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h b/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h index e36d0afa6732..f2ce16eb6d57 100644 --- a/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h +++ b/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h @@ -1,14 +1,20 @@ -/* Copyright Statement: -*This firmware are protected under relevant copyright laws,this information contained -*herein is confidential and proprietary to Goodix. -* -* Copyright (C) 2010 - 2016 Goodix. Ltd. -* -*WARNING:The GTP_COMPATIBLE_MODE part of this file was generated by the specialized tools, -*please do not modify it manually! -* -*/ - +/* + * drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef _GT9XX_FIRMWARE_H_ #define _GT9XX_FIRMWARE_H_ diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h index 0e82be8b6ef3..fb401c329cbb 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef VPP_KEYSTONE_REGS_H #define VPP_KEYSTONE_REGS_H diff --git a/drivers/amlogic/media/enhancement/amvecm/bitdepth.c b/drivers/amlogic/media/enhancement/amvecm/bitdepth.c index 558fffb092fa..ffabe341e99f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/bitdepth.c +++ b/drivers/amlogic/media/enhancement/amvecm/bitdepth.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/bitdepth.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #include #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/bitdepth.h b/drivers/amlogic/media/enhancement/amvecm/bitdepth.h index 3b663770bec3..54cdce396fe2 100644 --- a/drivers/amlogic/media/enhancement/amvecm/bitdepth.h +++ b/drivers/amlogic/media/enhancement/amvecm/bitdepth.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/bitdepth.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef BITDEPTH_H_ #define BITDEPTH_H_ diff --git a/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h b/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h index af816406600e..1745b50c42ee 100644 --- a/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h +++ b/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/cm2_adj.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef __CM2_ADJ__ #define __CM2_ADJ__ diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h b/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h index 4b9dd616573b..ca26aedf78e5 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h @@ -1,3 +1,19 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ #ifndef __AM_DNLP_AGL_H #define __AM_DNLP_AGL_H diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c index 299e4f4083c8..13510c28a948 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #include #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h index 6c3a99e9c6cd..ece185b1a3b5 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h @@ -1,3 +1,19 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ #ifndef __AM_DNLP_CAL_H #define __AM_DNLP_CAL_H diff --git a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c index 645bcf0ff95d..b88d85584778 100644 --- a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c +++ b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/keystone_correction.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #include #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h index 633aff4ad966..62dfc30c2ce0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h +++ b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/keystone_correction.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef _KEYSTONE_CORRECTION_H_ #define _KEYSTONE_CORRECTION_H_ diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 5f110182a041..75a627e845fb 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -1,5 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/local_contrast.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ -/* #include */ #include #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index 05cec1c9313c..91f51f113f9f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -1,7 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ - - -/* Standard Linux headers */ #include #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h index 1dfd863a6b0a..f9cd50c6371f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #include #ifndef MAX diff --git a/drivers/amlogic/secure_monitor/flash_mutex.S b/drivers/amlogic/secure_monitor/flash_mutex.S index aa8989977374..164841ac2800 100644 --- a/drivers/amlogic/secure_monitor/flash_mutex.S +++ b/drivers/amlogic/secure_monitor/flash_mutex.S @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/secure_monitor/flash_mutex.S + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + @ This file was created from a .asm file @ using the ads2gas.pl script. .equ DO1STROUNDING, 0 diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c index cf2c39940a02..5f882237daf9 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c @@ -1,4 +1,20 @@ -/* Memory Debugging */ +/* + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifdef DWC_DEBUG_MEMORY #include "dwc_os.h" diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h index 64f00c276e71..54cbdd210e54 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h @@ -1,7 +1,20 @@ /* - * dwc_modpow.h - * See dwc_modpow.c for license and changes + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * */ + #ifndef _DWC_MODPOW_H #define _DWC_MODPOW_H diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c index 8382ef230fe6..3b189ea965f1 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifdef DWC_NOTIFYLIB #include "dwc_notifier.h" diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h index 952f40ddc17a..0c182a5d91d1 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef __DWC_NOTIFIER_H__ #define __DWC_NOTIFIER_H__ diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h index 37f5edff15f6..6518a03297e5 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef _DWC_OS_DEP_H_ #define _DWC_OS_DEP_H_ diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h index d507af316c57..deba850570c6 100644 --- a/include/dt-bindings/clock/meson8b-clkc.h +++ b/include/dt-bindings/clock/meson8b-clkc.h @@ -1,5 +1,18 @@ /* - * Meson8b clock tree IDs + * include/dt-bindings/clock/meson8b-clkc.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * */ /* diff --git a/include/dt-bindings/iio/adc/amlogic-saradc.h b/include/dt-bindings/iio/adc/amlogic-saradc.h index 7611426912af..5d3769ca452c 100644 --- a/include/dt-bindings/iio/adc/amlogic-saradc.h +++ b/include/dt-bindings/iio/adc/amlogic-saradc.h @@ -1,5 +1,18 @@ /* - * This header provides constants for configuring the AMLOGIC SAR ADC + * include/dt-bindings/iio/adc/amlogic-saradc.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * */ #ifndef _DT_BINDINGS_IIO_ADC_AMLOGIC_H diff --git a/include/dt-bindings/input/meson_rc.h b/include/dt-bindings/input/meson_rc.h index c572dba2bb39..382b8b9ad4b8 100644 --- a/include/dt-bindings/input/meson_rc.h +++ b/include/dt-bindings/input/meson_rc.h @@ -1,3 +1,19 @@ +/* + * include/dt-bindings/input/meson_rc.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ #ifndef _DT_BINDINGS_INPUT_MESON_RC_H #define _DT_BINDINGS_INPUT_MESON_RC_H diff --git a/include/linux/amlogic/debug_lockup.h b/include/linux/amlogic/debug_lockup.h index 353e71cae8c7..24c0f55e6afd 100644 --- a/include/linux/amlogic/debug_lockup.h +++ b/include/linux/amlogic/debug_lockup.h @@ -1,3 +1,20 @@ +/* + * include/linux/amlogic/debug_lockup.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef __debug_lockup_h_ #define __debug_lockup_h_ diff --git a/include/linux/amlogic/dhd_buf.h b/include/linux/amlogic/dhd_buf.h index 9822f5a1a80c..7ba9de6ec668 100644 --- a/include/linux/amlogic/dhd_buf.h +++ b/include/linux/amlogic/dhd_buf.h @@ -1,3 +1,20 @@ +/* + * include/linux/amlogic/dhd_buf.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef _BCMDHD_BUF_H #define _BCMDHD_BUF_H int bcmdhd_init_wlan_mem(void); diff --git a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h index 370c01000bf2..f8a2ceb62f7f 100644 --- a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h +++ b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h @@ -1,3 +1,20 @@ +/* + * include/linux/amlogic/media/amdolbyvision/dolby_vision.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef _DV_H_ #define _DV_H_ diff --git a/include/linux/meson_ion.h b/include/linux/meson_ion.h index ce19cb0753be..7d68d3d5c518 100644 --- a/include/linux/meson_ion.h +++ b/include/linux/meson_ion.h @@ -1 +1,18 @@ +/* + * include/linux/meson_ion.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #include "../../drivers/amlogic/media/common/ion_dev/meson_ion.h" diff --git a/include/trace/events/meson_atrace.h b/include/trace/events/meson_atrace.h index 84009695511f..935ac94c70ec 100644 --- a/include/trace/events/meson_atrace.h +++ b/include/trace/events/meson_atrace.h @@ -1,5 +1,18 @@ /* - * meson_atrace.h + * include/trace/events/meson_atrace.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * */ /* diff --git a/sound/soc/amlogic/meson/dmic.h b/sound/soc/amlogic/meson/dmic.h index 69afdf5a9b17..15540fdfd644 100644 --- a/sound/soc/amlogic/meson/dmic.h +++ b/sound/soc/amlogic/meson/dmic.h @@ -1,3 +1,20 @@ +/* + * sound/soc/amlogic/meson/dmic.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + #ifndef __DMIC_H__ #define __DMIC_H__ From b733bc4cbd91986bb783f1811abe3dce35d059dc Mon Sep 17 00:00:00 2001 From: Guosong Zhou Date: Tue, 19 Feb 2019 01:43:42 -0500 Subject: [PATCH 0062/1060] camera: config adapter buffer size from dts [1/2] PD#SWPL-4934 Problem: kernel panic when adjust adapter memory size Solution: config adapter buffer size from dts Verify: verify by w411 Change-Id: Ie66cf57e870e140dd63516672c7f90f7d9ddda72 Signed-off-by: Guosong Zhou --- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 1 + arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 5a51224e02e4..af8d789785f3 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1886,6 +1886,7 @@ reg-names = "adapter"; interrupts = <0 179 0>; interrupt-names = "adapter-irq"; + mem_alloc = <48>; }; phycsi: phy-csi@ff650000 { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 74b706c976cb..9e04275a5d03 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1896,6 +1896,7 @@ reg-names = "adapter"; interrupts = <0 179 0>; interrupt-names = "adapter-irq"; + mem_alloc = <48>; }; phycsi: phy-csi@ff650000 { From 1147493d9b6467c6a8c57b6a67158255fc97a39f Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Tue, 20 Nov 2018 12:37:30 +0800 Subject: [PATCH 0063/1060] hdmitx: add rx latency info [1/4] PD#SWPL-2456 Problem: Lack the latency info of RX Solution: Add the latency info of RX Verify: T962E/R321 Change-Id: I480398466753dd93ca6e908d39157acadff6879f Signed-off-by: Zongdong Jiao --- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 109 +++++++++++++++++- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 31 ++--- .../media/vout/hdmi_tx/hdmi_tx_module.h | 8 +- include/linux/amlogic/media/vout/vinfo.h | 10 ++ 4 files changed, 138 insertions(+), 20 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index 0a90ec50ec93..f26fd5bd6860 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -1403,6 +1403,40 @@ static void hdmitx_edid_4k2k_parse(struct rx_cap *pRXCap, unsigned char *dat, } } +static void get_latency(struct rx_cap *pRXCap, unsigned char *val) +{ + if (val[0] == 0) + pRXCap->vLatency = LATENCY_INVALID_UNKNOWN; + else if (val[0] == 0xFF) + pRXCap->vLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->vLatency = (val[0] - 1) * 2; + + if (val[1] == 0) + pRXCap->aLatency = LATENCY_INVALID_UNKNOWN; + else if (val[1] == 0xFF) + pRXCap->aLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->aLatency = (val[1] - 1) * 2; +} + +static void get_ilatency(struct rx_cap *pRXCap, unsigned char *val) +{ + if (val[0] == 0) + pRXCap->i_vLatency = LATENCY_INVALID_UNKNOWN; + else if (val[0] == 0xFF) + pRXCap->i_vLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->i_vLatency = val[0] * 2 - 1; + + if (val[1] == 0) + pRXCap->i_aLatency = LATENCY_INVALID_UNKNOWN; + else if (val[1] == 0xFF) + pRXCap->i_aLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->i_aLatency = val[1] * 2 - 1; +} + static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, unsigned char *BlockBuf) { @@ -1477,10 +1511,22 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, if (count > 7) { tmp = BlockBuf[offset+7]; idx = offset + 8; - if (tmp & (1<<6)) + if (tmp & (1<<6)) { + unsigned char val[2]; + + val[0] = BlockBuf[idx]; + val[1] = BlockBuf[idx + 1]; + get_latency(pRXCap, val); idx += 2; - if (tmp & (1<<7)) + } + if (tmp & (1<<7)) { + unsigned char val[2]; + + val[0] = BlockBuf[idx]; + val[1] = BlockBuf[idx + 1]; + get_ilatency(pRXCap, val); idx += 2; + } if (tmp & (1<<5)) { idx += 1; /* valid 4k */ @@ -1916,6 +1962,7 @@ next: } else dump_dtd_info(t); } + static void hdrinfo_to_vinfo(struct vinfo_s *info, struct rx_cap *pRXCap) { unsigned int k, l; @@ -1956,6 +2003,15 @@ static void hdrinfo_to_vinfo(struct vinfo_s *info, struct rx_cap *pRXCap) info->hdr_info.hdr_support); } +static void rxlatency_to_vinfo(struct vinfo_s *info, struct rx_cap *rx) +{ + if (!info || !rx) + return; + info->rx_latency.vLatency = rx->vLatency; + info->rx_latency.aLatency = rx->aLatency; + info->rx_latency.i_vLatency = rx->i_vLatency; + info->rx_latency.i_aLatency = rx->i_aLatency; +} int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) { @@ -2153,8 +2209,10 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) if (info) { if (!((strncmp(info->name, "480cvbs", 7) == 0) || (strncmp(info->name, "576cvbs", 7) == 0) || - (strncmp(info->name, "null", 4) == 0))) + (strncmp(info->name, "null", 4) == 0))) { hdrinfo_to_vinfo(info, pRXCap); + rxlatency_to_vinfo(info, pRXCap); + } } return 0; @@ -2671,6 +2729,51 @@ int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, pos += snprintf(buffer+pos, buffer_len-pos, "MaxTMDSClock2 %d MHz\n", pRXCap->Max_TMDS_Clock2 * 5); } + + pos += snprintf(buffer+pos, buffer_len-pos, "vLatency: "); + if (pRXCap->vLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->vLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, + " %d\n", pRXCap->vLatency); + + pos += snprintf(buffer+pos, buffer_len-pos, "aLatency: "); + if (pRXCap->aLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->aLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, " %d\n", + pRXCap->aLatency); + + pos += snprintf(buffer+pos, buffer_len-pos, "i_vLatency: "); + if (pRXCap->i_vLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->i_vLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, " %d\n", + pRXCap->i_vLatency); + + pos += snprintf(buffer+pos, buffer_len-pos, "i_aLatency: "); + if (pRXCap->i_aLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->i_aLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, " %d\n", + pRXCap->i_aLatency); + if (pRXCap->colorimetry_data) pos += snprintf(buffer+pos, buffer_len-pos, "ColorMetry: 0x%x\n", pRXCap->colorimetry_data); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 269cf9cdee5a..bf12bc25ac11 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -440,6 +440,16 @@ static void hdrinfo_to_vinfo(struct vinfo_s *info, struct hdmitx_dev *hdev) info->hdr_info.hdr_support); } +static void rxlatency_to_vinfo(struct vinfo_s *info, struct rx_cap *rx) +{ + if (!info || !rx) + return; + info->rx_latency.vLatency = rx->vLatency; + info->rx_latency.aLatency = rx->aLatency; + info->rx_latency.i_vLatency = rx->i_vLatency; + info->rx_latency.i_aLatency = rx->i_aLatency; +} + static int set_disp_mode_auto(void) { int ret = -1; @@ -465,8 +475,10 @@ static int set_disp_mode_auto(void) if (!((strncmp(info->name, "480cvbs", 7) == 0) || (strncmp(info->name, "576cvbs", 7) == 0) || - (strncmp(info->name, "null", 4) == 0))) + (strncmp(info->name, "null", 4) == 0))) { hdrinfo_to_vinfo(info, hdev); + rxlatency_to_vinfo(info, &hdev->RXCap); + } hdmi_physcial_size_update(hdev); @@ -487,6 +499,7 @@ static int set_disp_mode_auto(void) return -1; } strncpy(mode, info->name, sizeof(mode)); + mode[31] = '\0'; if (strstr(mode, "fp")) { int i = 0; @@ -3821,21 +3834,13 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) mutex_unlock(&setclk_mutex); } -static void clear_hdr_info(struct hdmitx_dev *hdev) +static void clear_rx_vinfo(struct hdmitx_dev *hdev) { struct vinfo_s *info = hdmitx_get_current_vinfo(); - unsigned int i; if (info) { - info->hdr_info.hdr_support = 0; - for (i = 0; i < 4; i++) - memset(&(info->hdr_info.dynamic_info[i]), - 0, sizeof(struct hdr_dynamic)); - info->hdr_info.colorimetry_support = 0; - info->hdr_info.lumi_max = 0; - info->hdr_info.lumi_avg = 0; - info->hdr_info.lumi_min = 0; - pr_info(SYS "clear RX hdr info\n"); + memset(&info->hdr_info, 0, sizeof(info->hdr_info)); + memset(&info->rx_latency, 0, sizeof(info->rx_latency)); } } @@ -3871,7 +3876,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; hdev->HWOp.CntlMisc(hdev, MISC_ESM_RESET, 0); - clear_hdr_info(hdev); + clear_rx_vinfo(hdev); rx_edid_physical_addr(0, 0, 0, 0); hdmitx_edid_clear(hdev); hdmi_physcial_size_update(hdev); diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index e23ae907eaf7..0d76db1d1152 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -130,10 +130,10 @@ struct rx_cap { unsigned char edid_version; unsigned char edid_revision; unsigned char ColorDeepSupport; - unsigned int Video_Latency; - unsigned int Audio_Latency; - unsigned int Interlaced_Video_Latency; - unsigned int Interlaced_Audio_Latency; + unsigned int vLatency; + unsigned int aLatency; + unsigned int i_vLatency; + unsigned int i_aLatency; unsigned int threeD_present; unsigned int threeD_Multi_present; unsigned int hdmi_vic_LEN; diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h index dfafcaf6d2a6..8a5720f05b3b 100644 --- a/include/linux/amlogic/media/vout/vinfo.h +++ b/include/linux/amlogic/media/vout/vinfo.h @@ -233,6 +233,15 @@ struct vinfo_base_s { enum color_fmt_e viu_color_fmt; }; +#define LATENCY_INVALID_UNKNOWN 0 +#define LATENCY_NOT_SUPPORT 0xffff +struct rx_av_latency { + unsigned int vLatency; + unsigned int aLatency; + unsigned int i_vLatency; + unsigned int i_aLatency; +}; + struct vinfo_s { char *name; enum vmode_e mode; @@ -254,6 +263,7 @@ struct vinfo_s { enum viu_mux_e viu_mux; struct master_display_info_s master_display_info; struct hdr_info hdr_info; + struct rx_av_latency rx_latency; struct vout_device_s *vout_device; }; From d281f43b28d005488b157c6f4cb2d7708eedc5ec Mon Sep 17 00:00:00 2001 From: Jihong Sui Date: Mon, 21 Jan 2019 16:52:35 +0800 Subject: [PATCH 0064/1060] deinterlace: modify suspend function [1/1] PD#SWPL-4196 Problem: atv suspend/resume, DI deadlock causing hangup Solution: add unreg process and clear timer/tasklet Verify: tl1 Change-Id: Id50de8649455f0a2f77ad2fcb585bf233d5c362f Signed-off-by: Jihong Sui --- .../amlogic/media/deinterlace/deinterlace.c | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 597d781c7feb..01606e87d643 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -6705,14 +6705,16 @@ light_unreg: pr_err("[DI] reg event device hasn't resumed\n"); return -1; } - bypass_state = 0; - di_pre_stru.reg_req_flag = 1; - pr_dbg("%s: vframe provider reg %s\n", __func__, - provider_name); if (reg_flag) { pr_err("[DI] no muti instance.\n"); return -1; } + pr_info("%s: vframe provider reg %s\n", __func__, + provider_name); + + bypass_state = 0; + di_pre_stru.reg_req_flag = 1; + trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); di_pre_stru.reg_req_flag_cnt = 0; while (di_pre_stru.reg_req_flag) { @@ -7750,6 +7752,29 @@ static void di_shutdown(struct platform_device *pdev) } #ifdef CONFIG_PM + +static void di_clear_for_suspend(struct di_dev_s *di_devp) +{ + pr_info("%s\n", __func__); + + di_unreg_process();/*have flag*/ + if (di_pre_stru.unreg_req_flag_irq) + di_unreg_process_irq(); + +#ifdef CONFIG_CMA + if (di_pre_stru.cma_release_req) { + pr_info("\tcma_release\n"); + atomic_set(&di_devp->mem_flag, 0); + di_cma_release(di_devp); + di_pre_stru.cma_release_req = 0; + di_pre_stru.cma_alloc_done = 0; + } +#endif + hrtimer_cancel(&di_pre_hrtimer); + tasklet_kill(&di_pre_tasklet); //ary.sui + tasklet_disable(&di_pre_tasklet); + pr_info("%s end\n", __func__); +} static int save_init_flag; /* must called after lcd */ static int di_suspend(struct device *dev) @@ -7759,9 +7784,13 @@ static int di_suspend(struct device *dev) di_devp = dev_get_drvdata(dev); di_devp->flags |= DI_SUSPEND_FLAG; + + di_clear_for_suspend(di_devp);//add + /* fix suspend/resume crash problem */ save_init_flag = init_flag; init_flag = 0; +#if 0 /*2019-01-18*/ if (di_pre_stru.di_inp_buf) { if (vframe_in[di_pre_stru.di_inp_buf->index]) { vf_put(vframe_in[di_pre_stru.di_inp_buf->index], @@ -7771,7 +7800,7 @@ static int di_suspend(struct device *dev) VFRAME_EVENT_RECEIVER_PUT, NULL); } } - +#endif if (!is_meson_txlx_cpu()) switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, @@ -7787,10 +7816,21 @@ static int di_resume(struct device *dev) struct di_dev_s *di_devp = NULL; di_devp = dev_get_drvdata(dev); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) clk_prepare_enable(di_devp->vpu_clkb); init_flag = save_init_flag; di_devp->flags &= ~DI_SUSPEND_FLAG; + /*2018-01-18*/ + pr_info("%s\n", __func__); + tasklet_init(&di_pre_tasklet, pre_tasklet, + (unsigned long)(&di_pre_stru)); + tasklet_disable(&di_pre_tasklet); + hrtimer_init(&di_pre_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + di_pre_hrtimer.function = di_pre_hrtimer_func; + hrtimer_start(&di_pre_hrtimer, ms_to_ktime(10), HRTIMER_MODE_REL); + tasklet_enable(&di_pre_tasklet); + /************/ pr_info("di: resume module\n"); return 0; } From 30770a23ca2742649ca3c91a6aadafb80b37f4f3 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Tue, 19 Feb 2019 14:57:21 +0800 Subject: [PATCH 0065/1060] dts: fix the warnings when compiling the g12a device tree. [1/1] PD#SWPL-4967 Problem: warning when compiling the g12a device tree. Solution: fix the warning. Verify: locall. Change-Id: I1f93c788d1914441e48305c04330701bfd718b87 Signed-off-by: Jianxiong Pan --- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 99b85bb7df7f..01d7cb2733dc 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1028,9 +1028,9 @@ interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; device_type = "pci"; - ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 /* downstream I/O */ - 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + 0x82000000 0xfc700000 0x0 0xfc700000 0 0x1900000>; /* non-prefetchable memory */ num-lanes = <1>; pcie-num = <1>; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 8cc27c512b8c..654f58ccaf98 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -157,10 +157,10 @@ }; arm_pmu { - compatible = "arm,cortex-a15-pmu"; + compatible = "arm,armv8-pmuv3"; /* clusterb-enabled; */ interrupts = ; - reg = <0xff634680 0x4>; + reg = <0x0 0xff634680 0x0 0x4>; cpumasks = <0xf>; /* default 10ms */ relax-timer-ns = <10000000>; From c11c4434847aa88f88cc1688535618d5c3c6e682 Mon Sep 17 00:00:00 2001 From: "changqing.gao" Date: Thu, 21 Feb 2019 17:19:06 +0800 Subject: [PATCH 0066/1060] mm: The first 1MB mem is wasted for CPU series coming after TXLX [1/1] PD#SWPL-3744 Problem: For the previous Amlogic CPU series(before TXLX), the CPU booting vector locates at physical address starting from 0x00. To avoid influencing cpu booting procedure, we have to reserve the first 1MB physical memory. But it has changed since TXLX, the normal text section can safely use 0~1M physical address. So it's no need to reserve the first 1MB in DTS. Solution: Change the starting address of usable memory from 0x100000 to 0x0 for CPU series coming after TXLX. Verify: Locally on W400 Change-Id: I2df7859a38feca48abd58459e8b231ee15ada9e2 Signed-off-by: changqing.gao Signed-off-by: Luan Yuan Conflicts: arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts --- arch/arm/boot/dts/amlogic/atom.dts | 2 +- arch/arm/boot/dts/amlogic/axg_a113d_skt.dts | 2 +- arch/arm/boot/dts/amlogic/axg_pxp.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_pxp.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 2 +- .../dts/amlogic/g12a_s905d2_skt_buildroot.dts | 2 +- .../amlogic/g12a_s905d2_u200_buildroot.dts | 2 +- .../g12a_s905d2_u200_buildroot_vccktest.dts | 2 +- .../g12a_s905d2_u200_drm_buildroot.dts | 2 +- .../arm/boot/dts/amlogic/g12a_s905x2_u211.dts | 2 +- .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 2 +- .../amlogic/g12a_s905x2_u211_buildroot.dts | 2 +- .../amlogic/g12a_s905x2_u212_buildroot.dts | 2 +- .../arm/boot/dts/amlogic/g12a_s905y2_u220.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 +- .../g12b_a311d_w400_buildroot_vccktest.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_pxp.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 2 +- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 2 +- .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 1651 ----------------- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 2 +- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 2 +- arch/arm64/boot/dts/amlogic/atom.dts | 2 +- arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/axg_pxp.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_pxp.dts | 2 +- .../boot/dts/amlogic/g12a_s905d2_skt.dts | 2 +- .../dts/amlogic/g12a_s905d2_skt_buildroot.dts | 2 +- .../amlogic/g12a_s905d2_u200_buildroot.dts | 2 +- .../g12a_s905d2_u200_buildroot_vccktest.dts | 2 +- .../g12a_s905d2_u200_drm_buildroot.dts | 2 +- .../boot/dts/amlogic/g12a_s905x2_u211.dts | 2 +- .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 2 +- .../amlogic/g12a_s905x2_u211_buildroot.dts | 2 +- .../amlogic/g12a_s905x2_u212_buildroot.dts | 2 +- .../boot/dts/amlogic/g12a_s905y2_u220.dts | 2 +- .../arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 +- .../g12b_a311d_w400_buildroot_vccktest.dts | 2 +- .../dts/amlogic/g12b_a311x_w411_buildroot.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_pxp.dts | 2 +- .../boot/dts/amlogic/txlx_t962e_r321.dts | 2 +- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 2 +- .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 2 +- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 2 +- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 2 +- .../boot/dts/amlogic/txlx_t962x_r314.dts | 2 +- 50 files changed, 49 insertions(+), 1700 deletions(-) delete mode 100644 arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts diff --git a/arch/arm/boot/dts/amlogic/atom.dts b/arch/arm/boot/dts/amlogic/atom.dts index 0b453304c69e..b2a9b477dc26 100644 --- a/arch/arm/boot/dts/amlogic/atom.dts +++ b/arch/arm/boot/dts/amlogic/atom.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts index 96e74c949c3a..a43193324bcf 100644 --- a/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts @@ -36,7 +36,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/axg_pxp.dts b/arch/arm/boot/dts/amlogic/axg_pxp.dts index 702352d18124..297963d0ab9a 100644 --- a/arch/arm/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm/boot/dts/amlogic/axg_pxp.dts @@ -32,7 +32,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_pxp.dts b/arch/arm/boot/dts/amlogic/g12a_pxp.dts index 28c98cb1b4c1..4973402c90e9 100644 --- a/arch/arm/boot/dts/amlogic/g12a_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12a_pxp.dts @@ -37,7 +37,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index c511bb41f9a4..352ea71789db 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 6955c4592030..88c7dfb9b1de 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 0b38e1b2aa36..c5ee01e0e39b 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index 831d29630f45..bc7730e015e4 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 05fd700357c2..84f951fd0125 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index 7d821fa26a33..36244523e044 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 9952476b0424..fcd2ebb724e1 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 69d17f5c926c..e999e2ccbd40 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 89b9b149491d..a3281e845dab 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index a734db686b5f..48895fca044a 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 3a4a933f1127..155a1edede8e 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index b833409eb43d..985a67248d71 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index f24ef24a1f4e..fcdffd350d5d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp.dts b/arch/arm/boot/dts/amlogic/g12b_pxp.dts index 553477d5a71a..463a91c3a509 100644 --- a/arch/arm/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12b_pxp.dts @@ -38,7 +38,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 140070b93c3c..5d17e01ac778 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 355d25ee4d92..6ba4dc1de331 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 6ddf8823143f..60a75be67010 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 48ac144d59e7..c99e90f27afb 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts deleted file mode 100644 index 8a65f4161541..000000000000 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ /dev/null @@ -1,1651 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/dts-v1/; -#include -#include - -#include "mesontxlx.dtsi" -#include "partition_mbox_normal.dtsi" -#include "mesontxlx_r311-panel.dtsi" - -/ { - model = "Amlogic"; - amlogic-dt-id = "txlx_t962x_r311-1g"; - compatible = "amlogic, txlx"; - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - serial0 = &uart_AO; - serial1 = &uart_A; - serial2 = &uart_B; - serial3 = &uart_C; - serial4 = &uart_AO_B; - spi0 = &spicc0; - spi1 = &spicc1; - }; - - ion_dev { - compatible = "amlogic, ion_dev"; - memory-region = <&ion_reserved>; - }; - - memory@00000000 { - device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - /* global autoconfigured region for contiguous allocations */ - ramoops@0x07400000 { - compatible = "ramoops"; - reg = <0x07400000 0x00100000>; - record-size = <0x8000>; - console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; - }; - secmon_reserved:linux,secmon { - compatible = "shared-dma-pool"; - reusable; - size = <0x400000>; - alignment = <0x400000>; - alloc-ranges = <0x05000000 0x400000>; - }; - - //secos_reserved:linux,secos { - // status = "disabled"; - // compatible = "amlogic, aml_secos_memory"; - // reg = <0x0 0x05300000 0x0 0x2000000>; - // no-map; - //}; - - - - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x800000>; - alignment = <0x400000>; - alloc-ranges = <0x3f800000 0x800000>; - }; - - //carveout_reserved:linux,carveout-reserve { - // compatible = "amlogic, idev-mem"; - // size = <0x0 0x1000>; - //}; - - - codec_mm_cma:linux,codec_mm_cma { - compatible = "shared-dma-pool"; - reusable; - /* ion_codec_mm max can alloc size 80M*/ - size = <0xd000000>; - alignment = <0x400000>; - linux,contiguous-region; - alloc-ranges = <0x30000000 0x10000000>; - }; - ion_reserved:linux,ion-dev { - compatible = "shared-dma-pool"; - reusable; - size = <0x4C00000>; - alignment = <0x400000>; - alloc-ranges = <0x0 0x30000000>; - }; - - /*di CMA pool */ - di_cma_reserved:linux,di_cma { - compatible = "shared-dma-pool"; - reusable; - /* buffer_size = 3621952(yuv422 8bit) - * | 4736064(yuv422 10bit) - * | 4179008(yuv422 10bit full pack mode) - * 10x3621952=34.6M(0x23) support 8bit - * 10x4736064=45.2M(0x2e) support 12bit - * 10x4179008=40M(0x28) support 10bit - */ - size = <0x02800000>; - alignment = <0x400000>; - alloc-ranges = <0x30000000 0x10000000>; - }; - - /* POST PROCESS MANAGER */ - ppmgr_reserved:linux,ppmgr { - compatible = "amlogic, ppmgr_memory"; - size = <0x0>; - }; - - picdec_cma_reserved:linux,picdec { - compatible = "shared-dma-pool"; - reusable; - size = <0x0>; - alignment = <0x0>; - linux,contiguous-region; - }; - - /* codec shared reserved */ - codec_mm_reserved:linux,codec_mm_reserved { - compatible = "amlogic, codec-mm-reserved"; - size = <0x0>; - alignment = <0x100000>; - //no-map; - }; - - demod_cma_reserved:linux,demod_cma { - compatible = "shared-dma-pool"; - reusable; - /* 5M */ - size = <0x0800000>; - alignment = <0x400000>; - alloc-ranges = <0x0 0x30000000>; - }; - - /* vdin1 CMA pool */ - vdin1_cma_reserved:linux,vdin1_cma { - compatible = "shared-dma-pool"; - linux,phandle = <5>; - reusable; - /* 1920x1080x2x4 =16+4 M */ - size = <0x01400000>; - alignment = <0x400000>; - alloc-ranges = <0x0 0x30000000>; - }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; - }; - - amlogic_battery:dummy-battery { - compatible = "amlogic, dummy-battery"; - status = "disabled"; - }; - - amlogic_charger:dummy-charger { - compatible = "amlogic, dummy-charger"; - status = "disabled"; - }; - - /* for external keypad */ - adc_keypad { - compatible = "amlogic, adc_keypad"; - status = "okay"; - key_name = "power","up","down","enter","left","right","home"; - key_num = <7>; - io-channels = <&saradc SARADC_CH2>, - <&saradc SARADC_CH3>; - io-channel-names = "key-chan-2", "key-chan-3"; - key_chan = ; - key_code = <116 103 108 28 105 106 102>; - key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 - key_tolerance = <40 40 40 40 40 40 40>; - }; - - gpioleds { - compatible = "gpio-leds"; - status = "okay"; - - sys { - label = "sysled"; - gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; - default-state = "on"; /* keep/on/off */ - linux,default-trigger = "none"; - }; - - }; - - pwmleds { - compatible = "pwm-leds"; - status = "disabled"; - pinctrl-names = "default"; - pinctrl-0 = <&pwmleds_pins>; - - sys { - active-low; - label = "sysled"; - max-brightness = <255>; - pwms = <&pwm_AO_ab 0 50000 0>; - }; - }; - - ethmac: ethernet@0xff3f0000 { - compatible = "amlogic, gxbb-eth-dwmac"; - status = "okay"; - reg = <0xff3f0000 0x10000 - 0xff634540 0x8 - 0xff634558 0xc - 0xffd01084 0x4>; - interrupts = <0 8 1 - 0 9 1>; - - phy-mode= "rmii"; - mc_val_internal_phy = <0x1804>; - mc_val_external_phy = <0x1621>; - interrupt-names = "macirq", - "phyirq"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - internal_phy = <1>; - }; - - vout { - compatible = "amlogic, vout"; - dev_name = "vout"; - status = "okay"; - fr_auto_policy = <0>; - }; - - meson-fb { - compatible = "amlogic, meson-txlx"; - memory-region = <&logo_reserved>; - dev_name = "meson-fb"; - status = "okay"; - interrupts = <0 3 1 - 0 89 1>; - interrupt-names = "viu-vsync", "rdma"; - mem_size = <0x00800000 0x01800000 0x00100000>; - /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ - display_mode_default = "1080p60hz"; - /* 0:VPU free scale 1:OSD free scale 2:OSD super scale */ - scale_mode = <1>; - /* 1920*1080*4*3 = 0x17BB000 */ - display_size_default = <1920 1080 1920 3240 32>; - pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ - logo_addr = "0x3f800000"; - }; - - ge2d { - compatible = "amlogic, ge2d-txlx"; - dev_name = "ge2d"; - status = "okay"; - interrupts = <0 150 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xff940000 0x10000>; - }; - - codec_io { - compatible = "amlogic, codec_io"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base{ - reg = <0xffd00000 0x100000>; - }; - io_dos_base{ - reg = <0xff620000 0x10000>; - }; - io_hiubus_base{ - reg = <0xff63c000 0x2000>; - }; - io_aobus_base{ - reg = <0xff800000 0x10000>; - }; - io_vcbus_base{ - reg = <0xff900000 0x40000>; - }; - io_dmc_base{ - reg = <0xff638000 0x2000>; - }; - }; - - codec_mm { - compatible = "amlogic, codec, mm"; - memory-region = <&codec_mm_cma &codec_mm_reserved>; - dev_name = "codec_mm"; - status = "okay"; - }; - - mesonstream { - compatible = "amlogic, codec, streambuf"; - dev_name = "mesonstream"; - status = "okay"; - clocks = <&clkc CLKID_DOS_PARSER - &clkc CLKID_DEMUX - &clkc CLKID_DOS - &clkc CLKID_CLK81 - &clkc CLKID_VDEC_MUX - &clkc CLKID_HCODEC_MUX - &clkc CLKID_HEVC_MUX>; - clock-names = "parser_top", - "demux", - "vdec", - "clk_81", - "clk_vdec_mux", - "clk_hcodec_mux", - "clk_hevc_mux"; - }; - - vdec { - compatible = "amlogic, vdec"; - dev_name = "vdec.0"; - status = "okay"; - interrupts = <0 3 1 - 0 23 1 - 0 32 1 - 0 43 1 - 0 44 1 - 0 45 1>; - interrupt-names = "vsync", - "demux", - "parser", - "mailbox_0", - "mailbox_1", - "mailbox_2"; - }; - - meson-amvideom { - compatible = "amlogic, amvideom"; - dev_name = "amvideom"; - status = "okay"; - interrupts = <0 3 1>; - interrupt-names = "vsync"; - }; - - - - amvideocap { - compatible = "amlogic, amvideocap"; - dev_name = "amvideocap.0"; - status = "disabled"; - max_size = <8>;//8M - }; - - picdec { - compatible = "amlogic, picdec"; - memory-region = <&picdec_cma_reserved>; - dev_name = "picdec"; - status = "okay"; - }; - - ppmgr { - compatible = "amlogic, ppmgr"; - memory-region = <&ppmgr_reserved>; - dev_name = "ppmgr"; - status = "okay"; - }; - - deinterlace { - compatible = "amlogic, deinterlace"; - status = "okay"; - /* 0:use reserved; 1:use cma; 2:use cma as reserved */ - flag_cma = <1>; - //memory-region = <&di_reserved>; - memory-region = <&di_cma_reserved>; - interrupts = <0 46 1 - 0 6 1>; - interrupt-names = "de_irq"; - clocks = <&clkc CLKID_VPU_MUX>, - <&clkc CLKID_FCLK_DIV4>, - <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; - clock-names = "vpu_mux", - "fclk_div4", - "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; - clock-range = <250 500>; - /* buffer-size = <3621952>;(yuv422 8bit) */ - buffer-size = <4179008>;/*yuv422 fullpack*/ - /* reserve-iomap = "true"; */ - /* if enable nr10bit, set nr10bit-support to 1 */ - nr10bit-support = <1>; - }; - ionvideo { - compatible = "amlogic, ionvideo"; - dev_name = "ionvideo"; - status = "okay"; - }; - - amlvideo { - compatible = "amlogic, amlvideo"; - dev_name = "amlvideo"; - status = "okay"; - }; - - amlvideo2_0 { - compatible = "amlogic, amlvideo2"; - dev_name = "amlvideo2"; - status = "okay"; - amlvideo2_id = <0>; - cma_mode = <1>; - }; - - amlvideo2_1 { - compatible = "amlogic, amlvideo2"; - dev_name = "amlvideo2"; - status = "okay"; - amlvideo2_id = <1>; - cma_mode = <1>; - }; - - hdmirx { - compatible = "amlogic, hdmirx_txlx"; - #address-cells=<1>; - #size-cells=<1>; - dev_name = "hdmirx"; - status = "okay"; - pinctrl-names = "hdmirx_pins"; - pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux - &hdmirx_c_mux &hdmirx_d_mux>; - repeat = <0>; - interrupts = <0 56 1>; - clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, - <&clkc CLKID_HDMIRX_CFG_COMP>, - <&clkc CLKID_HDMIRX_ACR_COMP>, - <&clkc CLKID_HDMIRX_AUDMEAS_COMP>, - <&xtal>, - <&clkc CLKID_FCLK_DIV5>, - <&clkc CLKID_FCLK_DIV7>, - <&clkc CLKID_HDCP22_SKP_COMP>, - <&clkc CLKID_HDCP22_ESM_COMP>; - // <&clkc CLK_AUD_PLL2FS>, - // <&clkc CLK_AUD_PLL4FS>, - // <&clkc CLK_AUD_OUT>; - clock-names = "hdmirx_modet_clk", - "hdmirx_cfg_clk", - "hdmirx_acr_ref_clk", - "hdmirx_audmeas_clk", - "xtal", - "fclk_div5", - "fclk_div7", - "hdcp_rx22_skp", - "hdcp_rx22_esm"; - // "hdmirx_aud_pll2fs", - // "hdmirx_aud_pll4f", - // "clk_aud_out"; - hdmirx_id = <0>; - en_4k_2_2k = <0>; - hpd_low_cec_off = <1>; - /* bit4: enable feature, bit3~0: port number */ - disable_port = <0x0>; - reg = <0xffd26000 0xa00000 - 0xff63C000 0x2000 - 0xffe0d000 0x2000 - 0xff63e000 0x2000 - 0x0 0x0 - 0xff634400 0x2000 - 0xff646000 0x2000>; - }; - - vdin0 { - compatible = "amlogic, vdin"; - /*memory-region = <&vdin0_cma_reserved>;*/ - dev_name = "vdin0"; - status = "okay"; - reserve-iomap = "true"; - /*bit0:(1:share with codec_mm;0:cma alone)*/ - /*bit8:(1:alloc in discontinus way;0:alone in continuous way)*/ - flag_cma = <0x101>; - /* MByte, if 10bit disable: 64M(YUV422), - * if 10bit enable: 64*1.5 = 96M(YUV422) - * if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M - * if support 4K2K-YUV444-10bit-WR:3840*2160*4*6 ~= 190M - * if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M - * if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M - * if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M - */ - cma_size = <190>; - interrupts = <0 83 1>; - rdma-irq = <2>; - clocks = <&clkc CLKID_FCLK_DIV5>, - <&clkc CLKID_VDIN_MEAS_COMP>; - clock-names = "fclk_div5", "cts_vdin_meas_clk"; - vdin_id = <0>; - /* vdin write mem color depth support: - * bit0:support 8bit - * bit1:support 9bit - * bit2:support 10bit - * bit3:support 12bit - * bit4:support yuv422 10bit full pack mode (from txl new add) - * bit8:use 8bit at 4k_50/60hz_10bit - * bit9:use 10bit at 4k_50/60hz_10bit - */ - tv_bit_mode = <0x215>; - }; - - vdin1 { - compatible = "amlogic, vdin"; - memory-region = <&vdin1_cma_reserved>; - dev_name = "vdin1"; - status = "okay"; - reserve-iomap = "true"; - flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ - interrupts = <0 85 1>; - rdma-irq = <4>; - clocks = <&clkc CLKID_FCLK_DIV5>, - <&clkc CLKID_VDIN_MEAS_COMP>; - clock-names = "fclk_div5", "cts_vdin_meas_clk"; - vdin_id = <1>; - /* vdin write mem color depth support: - * bit0:support 8bit - * bit1:support 9bit - * bit2:support 10bit - * bit3:support 12bit - */ - tv_bit_mode = <1>; - }; - - tvafe { - compatible = "amlogic, tvafe-txlx"; - /*memory-region = <&tvafe_cma_reserved>;*/ - dev_name = "tvafe"; - status = "okay"; - flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ - cma_size = <5>;/*MByte*/ - reg = <0xff642000 0x2000>;/*tvafe reg base*/ - reserve-iomap = "true"; - tvafe_id = <0>; - //pinctrl-names = "default"; - /*!!particular sequence, no more and no less!!!*/ - tvafe_pin_mux = < - 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ - 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ - 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ - 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ - >; - clocks = <&clkc CLKID_DAC_CLK>; - clock-names = "vdac_clk_gate"; - }; - - vbi { - compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; - dev_name = "vbi"; - status = "okay"; - interrupts = <0 83 1>; - reserve-iomap = "true"; - }; - - tvafe_avin_detect { - compatible = "amlogic, tvafe_avin_detect"; - dev_name = "tvafe_avin_detect"; - status = "okay"; - device_mask = <1>;/*bit0:ch1;bit1:ch2*/ - interrupts = <0 12 1>, - <0 13 1>; - }; - - amlvecm { - compatible = "amlogic, vecm"; - dev_name = "aml_vecm"; - status = "okay"; - gamma_en = <1>;/*1:enabel ;0:disable*/ - wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ - wb_sel = <1>;/*1:mtx ;0:gainoff*/ - vlock_en = <1>;/*1:enable;0:disable*/ - vlock_mode = <0x4>; - /* vlock work mode: - *bit0:auto ENC - *bit1:auto PLL - *bit2:manual PLL - *bit3:manual ENC - *bit4:manual soft ENC - *bit5:manual MIX PLL ENC - */ - vlock_pll_m_limit = <1>; - vlock_line_limit = <3>; - }; - amdolby_vision { - compatible = "amlogic, dolby_vision_txlx"; - dev_name = "aml_amdolby_vision_driver"; - status = "okay"; - tv_mode = <1>;/*1:enabel ;0:disable*/ - }; - amvenc_avc { - compatible = "amlogic, amvenc_avc"; - //memory-region = <&amvenc_avc_reserved>; - //memory-region = <&avc_cma_reserved>; - dev_name = "amvenc_avc"; - status = "okay"; - interrupts = <0 45 1>; - interrupt-names = "mailbox_2"; - }; - - tuner: tuner { - status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; - /* NO_SHARE_XTAL(0) - * SLAVE_XTAL_SHARE(1) - */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ - }; - - atv-demod { - compatible = "amlogic, atv-demod"; - status = "okay"; - tuner = <&tuner>; - btsc_sap_mode = <1>; - /* pinctrl-names="atvdemod_agc_pins"; */ - /* pinctrl-0=<&atvdemod_agc_pins>; */ - reg = <0xff640000 0x2000 /* demod reg */ - 0xff63c000 0x2000 /* hiu reg */ - 0xff634000 0x2000 /* periphs reg */ - 0xff648000 0x2000>; /* audio reg */ - reg_23cf = <0x88188832>; - /*default:0x88188832;r840 on haier:0x48188832*/ - }; - - bt-dev { - compatible = "amlogic, bt-dev"; - dev_name = "bt-dev"; - status = "okay"; - power_down_disable = <1>; - gpio_reset = <&gpio_ao GPIOAO_8 GPIO_ACTIVE_HIGH>; - //gpio_en = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; - }; - - rtc { - compatible = "amlogic, aml_vrtc"; - alarm_reg_addr = <0xff8000a8>; - timer_e_addr = <0xffd0f188>; - init_date = "2015/01/01"; - status = "okay"; - }; - - wifi { - compatible = "amlogic, aml_wifi"; - dev_name = "aml_wifi"; - status = "okay"; - interrupt_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; - interrupts = <0 68 4>; - irq_trigger_type = "GPIO_IRQ_HIGH"; - dhd_static_buf; - power_on_pin = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&wifi_32k_pins>; - pwm_config = <&wifi_pwm_conf>; - }; - - wifi_pwm_conf: wifi_pwm_conf { - pwm_channel1_conf { - pwms = <&pwm_cd MESON_PWM_1 30541 0>; - duty-cycle = <15270>; - times = <10>; - }; - pwm_channel2_conf { - pwms = <&pwm_cd MESON_PWM_3 30500 0>; - duty-cycle = <15250>; - times = <12>; - }; - }; - - sd_emmc_c: emmc@ffe07000 { - status = "okay"; - compatible = "amlogic, meson-mmc-txlx"; - reg = <0xffe07000 0x2000>; - interrupts = <0 218 1>; - pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; - pinctrl-0 = <&emmc_clk_cmd_pins>; - pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - mmc-ddr-1_8v; - mmc-hs200-1_8v; - - max-frequency = <200000000>; - non-removable; - disable-wp; - emmc { - status = "disabled"; - pinname = "emmc"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - caps = "MMC_CAP_8_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_1_8V_DDR", - "MMC_CAP_HW_RESET", - "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; - f_min = <400000>; - f_max = <200000000>; - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; - card_type = <1>; - /* 1:mmc card(include eMMC), - * 2:sd card(include tSD) - */ - }; - }; - - sd_emmc_b: sd@ffe05000 { - status = "okay"; - compatible = "amlogic, meson-mmc-txlx"; - reg = <0xffe05000 0x2000>; - interrupts = <0 217 1>; - pinctrl-names = "sd_all_pins", - "sd_clk_cmd_pins", - "sd_1bit_pins", - "sd_clk_cmd_uart_pins", - "sd_1bit_uart_pins", - "sd_to_ao_uart_pins", - "ao_to_sd_uart_pins", - "ao_to_sd_jtag_pins", - "sd_to_ao_jtag_pins"; - pinctrl-0 = <&sd_all_pins>; - pinctrl-1 = <&sd_clk_cmd_pins>; - pinctrl-2 = <&sd_1bit_pins>; - pinctrl-3 = <&sd_to_ao_uart_clr_pins - &sd_clk_cmd_pins &ao_to_sd_uart_pins>; - pinctrl-4 = <&sd_to_ao_uart_clr_pins - &sd_1bit_pins &ao_to_sd_uart_pins>; - pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - pinctrl-7 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - pinctrl-8 = <&sd_all_pins &sd_to_ao_uart_pins>; - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - max-frequency = <100000000>; - disable-wp; - sd { - status = "disabled"; - pinname = "sd"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED"; - /* "MMC_CAP_UHS_SDR12", - * "MMC_CAP_UHS_SDR25", - * "MMC_CAP_UHS_SDR50", - * "MMC_CAP_UHS_SDR104"; - */ - f_min = <400000>; - f_max = <200000000>; - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio GPIOC_4 GPIO_ACTIVE_HIGH>; - jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; - gpio_cd = <&gpio GPIOH_10 GPIO_ACTIVE_HIGH>; - card_type = <5>; - /* 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card - * 5:NON sdio device(means sd/mmc card) - */ - }; - }; - - unifykey { - compatible = "amlogic, unifykey"; - status = "okay"; - - unifykey-num = <20>; - unifykey-index-0 = <&keysn_0>; - unifykey-index-1 = <&keysn_1>; - unifykey-index-2 = <&keysn_2>; - unifykey-index-3 = <&keysn_3>; - unifykey-index-4 = <&keysn_4>; - unifykey-index-5 = <&keysn_5>; - unifykey-index-6 = <&keysn_6>; - unifykey-index-7 = <&keysn_7>; - unifykey-index-8 = <&keysn_8>; - unifykey-index-9 = <&keysn_9>; - unifykey-index-10= <&keysn_10>; - unifykey-index-11 = <&keysn_11>; - unifykey-index-12 = <&keysn_12>; - unifykey-index-13 = <&keysn_13>; - unifykey-index-14 = <&keysn_14>; - unifykey-index-15 = <&keysn_15>; - unifykey-index-16 = <&keysn_16>; - unifykey-index-17 = <&keysn_17>; - unifykey-index-18 = <&keysn_18>; - unifykey-index-19 = <&keysn_19>; - - keysn_0: key_0{ - key-name = "usid"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_1:key_1{ - key-name = "mac"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_2:key_2{ - key-name = "hdcp"; - key-device = "secure"; - key-type = "sha1"; - key-permit = "read","write","del"; - }; - keysn_3:key_3{ - key-name = "secure_boot_set"; - key-device = "efuse"; - key-permit = "write"; - }; - keysn_4:key_4{ - key-name = "mac_bt"; - key-device = "normal"; - key-permit = "read","write","del"; - key-type = "mac"; - }; - keysn_5:key_5{ - key-name = "mac_wifi"; - key-device = "normal"; - key-permit = "read","write","del"; - key-type = "mac"; - }; - keysn_6:key_6{ - key-name = "hdcp2_tx"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_7:key_7{ - key-name = "hdcp2_rx"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_8:key_8{ - key-name = "widevinekeybox"; - key-device = "secure"; - key-type = "sha1"; - key-permit = "read","write","del"; - }; - keysn_9:key_9{ - key-name = "deviceid"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_10:key_10{ - key-name = "hdcp22_fw_private"; - key-device = "secure"; - key-permit = "read","write","del"; - }; - keysn_11:key_11{ - key-name = "hdcp22_rx_private"; - key-device = "secure"; - key-permit = "read","write","del"; - }; - keysn_12:key_12{ - key-name = "hdcp22_rx_fw"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_13:key_13{ - key-name = "hdcp14_rx"; - key-device = "normal"; - key-type = "sha1"; - key-permit = "read","write","del"; - }; - keysn_14:key_14{ - key-name = "prpubkeybox";// PlayReady - key-device = "secure"; - key-permit = "read","write","del"; - }; - keysn_15:key_15{ - key-name = "prprivkeybox";// PlayReady - key-device = "secure"; - key-permit = "read","write","del"; - }; - keysn_16:key_16{ - key-name = "lcd"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_17:key_17{ - key-name = "lcd_extern"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_18:key_18{ - key-name = "backlight"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_19:key_19{ - key-name = "attestationkeybox";// attestation key - key-device = "secure"; - key-permit = "read","write","del"; - }; - }; /* End unifykey */ - - cvbsout { - compatible = "amlogic, cvbsout-txlx"; - dev_name = "cvbsout"; - status = "disabled"; - clocks = <&clkc CLKID_VCLK2_ENCI - &clkc CLKID_VCLK2_VENCI0 - &clkc CLKID_VCLK2_VENCI1 - &clkc CLKID_DAC_CLK>; - clock-names = "venci_top_gate", - "venci_0_gate", - "venci_1_gate", - "vdac_clk_gate"; - - /* performance: reg_address, reg_value */ - performance = <0x1b56 0x343 - 0x1b05 0xf4 - 0x1c59 0xfc48 - 0x1b12 0x8c00 - 0xffff 0x0>; /* ending flag */ - }; - - amhdmitx: amhdmitx { - compatible = "amlogic, amhdmitx"; - dev_name = "amhdmitx"; - status = "disabled"; - pinctrl-names="default", "hdmitx_i2c"; - pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; - pinctrl-1=<&hdmitx_hpd_gpio &i2c2_h_pins>; - /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ - interrupts = <0 57 1>; - interrupt-names = "hdmitx_hpd"; - /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM - * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD - */ - ic_type = <6>; - //gpio_i2c_en = <0>; - //repeater_tx = <0x1>; - //#address-cells = <2>; - //#size-cells = <2>; - //ranges; - }; - - i2c_gpio: i2c_gpio { - compatible = "i2c-gpio"; - dev_name = "i2c-gpio"; - status = "disabled"; - i2c-gpio,delay-us = <10>; /* 50 kHz */ - gpios = <&gpio GPIOH_2 0 - &gpio GPIOH_3 0>; - #address-cells = <2>; - #size-cells = <2>; - i2c-gpio,timeout-ms = <10>; - i2c_gpio_edid: i2c_gpio_edid { - compatible = "i2c-gpio"; - reg = <0x50 0x0 0x0 0x0>; - }; - }; - - aocec: aocec { - compatible = "amlogic, aocec-txlx"; - device_name = "aocec"; - status = "okay"; - vendor_name = "Amlogic"; /* Max Chars: 8 */ - /* Refer to the following URL at: - * http://standards.ieee.org/develop/regauth/oui/oui.txt - */ - vendor_id = <0x000000>; - product_desc = "TXLX"; /* Max Chars: 16 */ - cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <4>; - /*ee_cec;*/ - arc_port_mask = <0x2>; - interrupts = <0 205 1 - 0 199 1>; - interrupt-names = "hdmi_aocecb","hdmi_aocec"; - pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocecb>; - reg = <0xFF80023c 0x4 - 0xFF800000 0x400>; - reg-names = "ao_exit","ao"; - }; - - - canvas { - compatible = "amlogic, meson, canvas"; - dev_name = "amlogic-canvas"; - status = "okay"; - reg = <0xff638000 0x2000>; - }; - - rdma { - compatible = "amlogic, meson, rdma"; - dev_name = "amlogic-rdma"; - status = "okay"; - interrupts = <0 89 1>; - interrupt-names = "rdma"; - }; - - dwc3: dwc3@ff500000 { - compatible = "synopsys, dwc3"; - status = "okay"; - reg = <0xff500000 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy>, <&usb3_phy>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - }; - - usb2_phy: usb2phy@ffe09000 { - compatible = "amlogic, amlogic-new-usb2"; - status = "okay"; - portnum = <4>; - reg = <0xffe09000 0x80 - 0xffd01008 0x4>; - }; - - usb3_phy: usb3phy@ffe09080 { - compatible = "amlogic, amlogic-new-usb3"; - status = "okay"; - portnum = <0>; - reg = <0xffe09080 0x20>; - }; - - dwc2_a { - compatible = "amlogic, dwc2"; - device_name = "dwc2_a"; - reg = <0xff400000 0x40000>; - status = "okay"; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "gxl"; - /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ - controller-type = <1>; - phy-reg = <0xffe09000>; - phy-reg-size = <0xa0>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR>; - clock-names = "usb_general", - "usb1"; - }; - - /* Sound iomap */ - aml_snd_iomap { - compatible = "amlogic, meson-snd-iomap"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_audin_base { - reg = <0xffd03000 0x100000>; - }; - io_aiu_base { - reg = <0xFFCFFC00 0x100000>; - }; - io_eqdrc_base { - reg = <0xFFCFF000 0x100000>; - }; - io_hiu_reset_base { - reg = <0xFFCFCC00 0x100000>; - }; - io_isa_base { - reg = <0xFFD05800 0x100000>; - }; - }; - - /* AUDIO DEVICES */ - i2s_dai: I2S { - #sound-dai-cells = <0>; - /* config mpll whether same with audin */ - clocks = <&clkc CLKID_MPLL3>, - <&clkc CLKID_AMCLK_COMP>, - <&clkc CLKID_AIU_GLUE>, - <&clkc CLKID_I2S_OUT>, - <&clkc CLKID_AMCLK_MEASURE>, - <&clkc CLKID_AIFIFO2>, - <&clkc CLKID_MIXER>, - <&clkc CLKID_MIXER_IFACE>, - <&clkc CLKID_ADC>, - <&clkc CLKID_AIU_TOP>, - <&clkc CLKID_AOCLK_GATE>, - <&clkc CLKID_I2S_SPDIF>, - <&clkc CLKID_DAC_CLK>; - clock-names = "mpll", - "mclk", - "top_glue", - "i2s_out", - "amclk_measure", - "aififo2", - "aud_mixer", - "mixer_reg", - "adc", - "top_level", - "aoclk", - "aud_in", - "vdac_clk"; - compatible = "amlogic, aml-i2s-dai"; - }; - - i2s2_dai: I2S2 { - #sound-dai-cells = <0>; - /* config mpll whether same with aiu */ - clocks = <&clkc CLKID_MPLL2>, - <&clkc CLKID_AUDIN_MCLK_COMP>, - <&clkc CLKID_AUDIN_SCLK_COMP>, - <&clkc CLKID_AUDIN_LRCLK_COMP>; - clock-names = "audin_mpll", - "audin_mclk", - "audin_sclk", - "audin_lrclk"; - compatible = "amlogic, aml-i2s2-dai"; - }; - - spdif_dai: SPDIF { - #sound-dai-cells = <0>; - compatible = "amlogic, aml-spdif-dai"; - clocks = <&clkc CLKID_MPLL1>, - <&clkc CLKID_IEC958_INT_COMP>, - <&clkc CLKID_AMCLK_COMP>, - <&clkc CLKID_IEC958_MUX>, - <&clkc CLKID_CLK81>, - <&clkc CLKID_IEC958>, - <&clkc CLKID_IEC958_GATE>; - clock-names = - "mpll1", - "i958", - "mclk", - "spdif", - "clk_81", - "iec958", - "iec958_amclk"; - }; - - pcm_dai: PCM { - #sound-dai-cells = <0>; - compatible = "amlogic, aml-pcm-dai"; - pinctrl-names = "audio_pcm"; - /* disable pcm pin mux temporary, enable it if necessary */ - /*pinctrl-0 = <&aml_audio_pcm>;*/ - clocks = <&clkc CLKID_MPLL0>, - <&clkc CLKID_PCM_MCLK_COMP>, - <&clkc CLKID_PCM_SCLK_COMP>; - clock-names = "mpll0", "pcm_mclk", "pcm_sclk"; - pcm_mode = <1>; /* 0=slave mode, 1=master mode */ - }; - - i2s_plat: i2s_platform { - compatible = "amlogic, aml-i2s"; - interrupts = <0 29 1>; - }; - - pcm_plat: pcm_platform { - compatible = "amlogic, aml-pcm"; - }; - - spdif_codec: spdif_codec{ - #sound-dai-cells = <0>; - compatible = "amlogic, aml-spdif-codec"; - pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute"; - pinctrl-0 = <&audio_spdif_out_pins>; - pinctrl-1 = <&audio_spdif_out_mute_pins>; - }; - - pcm_codec: pcm_codec{ - #sound-dai-cells = <0>; - compatible = "amlogic, pcm2BT-codec"; - }; - /* end of AUDIO DEVICES */ - - /* AUDIO board specific */ - dummy_codec:dummy{ - #sound-dai-cells = <0>; - compatible = "amlogic, aml_dummy_codec"; - status = "okay"; - }; - - amlogic_codec:txlx_acodec{ - #sound-dai-cells = <0>; - compatible = "amlogic, txlx_acodec"; - reg = <0xFF632000 0x1c>; - status = "okay"; - }; - - aml_snd_tv { - compatible = "amlogic, txlx-snd-tv"; - status = "okay"; - aml-sound-card,format = "i2s"; - aml_sound_card,name = "AML-TVAUDIO"; - pinctrl-names = "audio_i2s"; - pinctrl-0 = <&aml_audio_i2s>; - /*avout mute gpio*/ - mute_gpio-gpios = <&gpio GPIODV_5 GPIO_ACTIVE_HIGH>; - /*analog amp mute*/ - /*amp_mute_gpio-gpios = <&gpio GPIOZ_18 GPIO_ACTIVE_LOW>;*/ - aux_dev = <&tas5707>; - cpu_list = <&cpudai0 &cpudai1 &cpudai2 &cpudai3>; - codec_list = <&codec0 &codec1 &codec2 &codec3>; - plat_list = <&i2s_plat &i2s_plat &pcm_plat &i2s_plat>; - cpudai0: cpudai0 { - sound-dai = <&i2s_dai>; - }; - cpudai1: cpudai1 { - sound-dai = <&spdif_dai>; - }; - cpudai2: cpudai2 { - sound-dai = <&pcm_dai>; - }; - cpudai3: cpudai3 { - sound-dai = <&i2s2_dai>; - }; - codec0: codec0 { - sound-dai = <&amlogic_codec>; - }; - codec1: codec1 { - sound-dai = <&spdif_codec>; - }; - codec2: codec2 { - sound-dai = <&pcm_codec>; - }; - codec3: codec3 { - sound-dai = <&dummy_codec>; - }; - Channel_Mask { - /*i2s has 4 pins, 8channel, mux output*/ - Speaker0_Channel_Mask = "i2s_2/3"; - DAC0_Channel_Mask = "i2s_4/5"; - DAC1_Channel_Mask = "i2s_4/5"; - EQ_DRC_Channel_Mask = "i2s_2/3"; - Spdif_samesource_Channel_Mask = "i2s_0/1"; - }; - }; - - amaudio2 { - compatible = "amlogic, aml_amaudio2"; - status = "okay"; - interrupts = <0 48 1>; - }; - /* end of AUDIO board specific */ - - - aml_sensor0: aml-sensor@0 { - compatible = "amlogic, aml-thermal"; - device_name = "thermal"; - status = "okay"; - #thermal-sensor-cells = <1>; - cooling_devices { - cpufreq_cool_cluster0 { - min_state = <1000000>; - dyn_coeff = <140>; - cluster_id = <0>; - node_name = "cpus"; - device_type = "cpufreq"; - }; - cpucore_cool_cluster0 { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "cpu_core_cluster0"; - device_type = "cpucore"; - }; - gpufreq_cool { - min_state = <400>; - dyn_coeff = <437>; - cluster_id = <0>; - node_name = "mali"; - device_type = "gpufreq"; - }; - gpucore_cool { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "thermal_gpu_cores"; - device_type = "gpucore"; - }; - }; - cpu_cluster0:cpu_core_cluster0 { - #cooling-cells = <2>; /* min followed by max */ - }; - gpucore:thermal_gpu_cores { - #cooling-cells = <2>; /* min followed by max */ - }; - }; - - dvb { - compatible = "amlogic, dvb"; - dev_name = "dvb"; - status = "okay"; - fe0_mode = "internal"; - fe0_tuner = <&tuner>; - /*"parallel","serial","disable"*/ - ts2 = "parallel"; - ts2_control = <0>; - ts2_invert = <0>; - interrupts = <0 23 1 - 0 5 1 - 0 53 1 - 0 19 1 - 0 25 1 - 0 18 1 - 0 24 1>; - interrupt-names = "demux0_irq", - "demux1_irq", - "demux2_irq", - "dvr0_irq", - "dvr1_irq", - "dvrfill0_fill", - "dvrfill1_flush"; - clocks = <&clkc CLKID_DEMUX - &clkc CLKID_ASYNC_FIFO - &clkc CLKID_AHB_ARB0 - &clkc CLKID_DOS_PARSER>; - clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; - }; - aml_dtv_demod { - compatible = "amlogic, ddemod-txlx"; - dev_name = "aml_dtv_demod"; - status = "okay"; - - //pinctrl-names="dtvdemod_agc"; - //pinctrl-0=<&dtvdemod_agc>; - - - clocks = <&clkc CLKID_DAC_CLK>; - clock-names = "vdac_clk_gate"; - - - reg = <0xff644000 0x2000 /*dtv demod base*/ - 0xff63c000 0x2000 /*hiu reg base*/ - 0xff800000 0x1000 /*io_aobus_base*/ - 0xffd01000 0x1000 /*reset*/ - >; - /*move from dvbfe*/ - dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? - spectrum = <1>; - cma_flag = <1>; - cma_mem_size = <8>; - memory-region = <&demod_cma_reserved>;//<&demod_reserved>; - }; - dvbfe { - compatible = "amlogic, dvbfe"; - dev_name = "dvbfe"; - status = "disabled"; - dtv_demod0 = "AMLDEMOD"; - fe0_dtv_demod = <0>; - fe0_ts = <2>; - fe0_dev = <0>; - dtv_demod0_mem = <0>; - dtv_demod0_spectrum = <1>; - dtv_demod0_cma_flag = <1>; - dtv_demod0_cma_mem_size = <8>; - memory-region = <&demod_cma_reserved>;//<&demod_reserved>; - tuner0 = "si2151_tuner"; - tuner0_i2c_adap_id = <2>; - tuner0_i2c_addr = <0x60>; - //tuner0_reset_value = <0>; - //tuner0_reset_gpio = "GPIOY_10" ; /*GPIOX_8 76*/ - fe0_tuner = <0>; - atv_demod0 = "aml_atv_demod"; - fe0_atv_demod = <0>; - }; - - thermal-zones { - soc_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <2150>; - - thermal-sensors = <&aml_sensor0 3>; - - trips { - switch_on: trip-point@0 { - temperature = <70000>; - hysteresis = <1000>; - type = "passive"; - }; - control: trip-point@1 { - temperature = <80000>; - hysteresis = <1000>; - type = "passive"; - }; - hot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - critical: trip-point@3 { - temperature = <260000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - cpufreq_cooling_map { - trip = <&control>; - cooling-device = <&cpus 0 4>; - contribution = <1024>; - }; - cpucore_cooling_map { - trip = <&control>; - cooling-device = <&cpu_cluster0 0 3>; - contribution = <1024>; - }; - gpufreq_cooling_map { - trip = <&control>; - cooling-device = <&gpu 0 4>; - contribution = <1024>; - }; - gpucore_cooling_map { - trip = <&control>; - cooling-device = <&gpucore 0 2>; - contribution = <1024>; - }; - }; - }; - }; - -}; /* end of / */ - -&i2c2 { - status = "okay"; - pinctrl-names="default"; - pinctrl-0=<&i2c2_h_pins>; - - tas5707: tas5707@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - codec_name = "tas5707"; - reg = <0x1B>; - reset_pin = <&gpio GPIODV_4 GPIO_ACTIVE_LOW>; - eq_enable = <0>; - drc_enable = <0>; - status = "okay"; - }; - - lcd_extern_i2c0: lcd_extern_i2c@0 { - compatible = "lcd_ext, i2c"; - dev_name = "i2c_T5800Q"; - reg = <0x1c>; - status = "okay"; - }; - - lcd_extern_i2c1: lcd_extern_i2c@1 { - compatible = "lcd_ext, i2c"; - dev_name = "i2c_ANX6862"; - reg = <0x20>; - status = "okay"; - }; - - lcd_extern_i2c2: lcd_extern_i2c@2 { - compatible = "lcd_ext, i2c"; - dev_name = "i2c_ANX7911"; - reg = <0x74>; - status = "okay"; - }; -}; - -&i2c1 { - status = "okay"; - clock-frequency = <300000>; - pinctrl-names="default"; - pinctrl-0=<&i2c1_dv_pins>; -}; - -&pinctrl_periphs { - /*i2s*/ - aml_audio_i2s: aml_audio_i2s { - mux { - groups = "i2s_mclk_h", - "i2s_sclk_h", - "i2s_lrclk_h", - "i2s_dout01_h6"; - function = "i2s"; - }; - }; - /*spdif*/ - audio_spdif_out_pins: audio_spdif_out_pins { - mux { - groups = "spdif_out_dv"; - function = "spdif_out"; - }; - }; - audio_spdif_out_mute_pins: audio_spdif_out_mute_pins { - mux { - groups = "GPIODV_6"; - function = "gpio_periphs"; - }; - }; - /*pcm*/ - aml_audio_pcm: aml_audio_pcm { - mux { - groups = - "pcm_clk_a_dv", - "pcm_fs_a_dv", - "pcm_in_a_dv", - "pcm_out_a_dv"; - function = "pcm_a"; - }; - }; - - /*lcd_extern*/ - lcd_extern_off_pins:lcd_extern_off_pin { - mux { - pins = "GPIOH_2", - "GPIOH_3"; - function = "gpio_periphs"; - /*output-high;*/ - output-low; - /*input-enable;*/ - }; - }; - - /*backlight*/ - bl_pwm_on_pins:bl_pwm_on_pin { - mux { - pins = "pwm_b"; - function = "pwm_b"; - }; - }; - bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { - mux { - pins = "pwm_vs_z6"; - function = "pwm_vs"; - }; - }; - bl_pwm_off_pins:bl_pwm_off_pin { - mux { - pins = "GPIOZ_6"; - function = "gpio_periphs"; - output-low; - }; - }; - bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { - mux { - pins = "pwm_b"; - function = "pwm_b"; - }; - }; - bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { - mux { - pins = "pwm_c_z"; - function = "pwm_c"; - }; - }; - bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { - mux { - pins = "pwm_vs_z6"; - function = "pwm_vs"; - }; - }; - bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { - mux { - pins = "pwm_vs_z7"; - function = "pwm_vs"; - }; - }; - bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { - mux { - pins = "GPIOZ_6", - "GPIOZ_7"; - function = "gpio_periphs"; - output-low; - }; - }; -}; - -&uart_A { - status = "okay"; -}; - -&audio_data{ - status = "okay"; -}; - -&pwm_AO_ab { - status = "okay"; -}; - -&pwm_ab { - status = "okay"; -}; - -&pwm_cd { - status = "okay"; -}; - -&spicc0 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&spi_a_pins>; - cs-gpios = <&gpio GPIOZ_3 0>; -}; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index eccb9cb8b13f..3d775920a9e7 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 53cc709a26a9..67c3077bd97a 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x5ff00000>; + linux,usable-memory = <0x0 0x60000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index 2fa541ea61b0..647052c5c84d 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts index 0a92bca20d2c..e9f86802b3cc 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -36,7 +36,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/axg_pxp.dts b/arch/arm64/boot/dts/amlogic/axg_pxp.dts index 37955492625d..b120496f41aa 100644 --- a/arch/arm64/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/axg_pxp.dts @@ -32,7 +32,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_pxp.dts b/arch/arm64/boot/dts/amlogic/g12a_pxp.dts index dc0e5ac104f4..7613b14ac751 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_pxp.dts @@ -37,7 +37,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index 5700547f0188..ae4f0904cb88 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 5c48f26ba772..51b104354a24 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 3c79d049f01a..190540c6a746 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index c7118a465172..5b288e80018e 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index a87ba00450e5..7caa5ec0bcb5 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index d84451ffcd90..c9342b18c85a 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 31390b856b8a..24074bec433f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index b05d3e8f4f72..36241d6eb24b 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 09a878dba49b..dd8d37ef4aa8 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index 1af01b2b46d7..d2a56ed14063 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 7ac576879a5b..514c0173bd4a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 8d820f050782..573189496d02 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 00047a2c5d8f..8f00163b5ce1 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index 694dafc0cb48..cb70d1aca034 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts index db484a40b905..c1960ce0ba5a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts @@ -38,7 +38,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index abf3c56be82f..2382792628c0 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 71ae1696fa1c..503e35b48481 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index fbe808f93aef..e9c8d700c1c7 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index b3b9a8acf7b4..30be795a013b 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index b838d0966d7b..c3593f28c298 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 8cc857ebfb41..231de7001847 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x5ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x60000000>; }; reserved-memory { From 8c7156c18a8632e863ad453533052077fe4c6c61 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Fri, 15 Feb 2019 20:07:42 +0800 Subject: [PATCH 0067/1060] printk: fix print_time bug when run dmesg [1/1] PD#SWPL-4900 Problem: printk_prefix() passes NULL buf to print_time() to get the length of the time prefix; when printk times are enable, the current code just return "snprint(NULL, 0, "[%5lu.000000]", (unsigned long)ts)" but in the SMP case, we add cpu core id at the end of time prefix, the format is "[%5lu, %06lu@%d]", this gives a wrong size(shorter). this will make buf get out of boundary, when run dmesg. Solution: replace [%5lu.000000] with [%5lu.000000@0] Verify: g12a-u200 Change-Id: Ic74b9f466b5af5aac7e6569a1afc7a46d9594050 Signed-off-by: Jianxiong Pan --- kernel/printk/printk.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2eb60968ddf9..5527d850b896 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1199,7 +1199,11 @@ static size_t print_time(u64 ts, char *buf) rem_nsec = do_div(ts, 1000000000); if (!buf) +#ifdef CONFIG_AMLOGIC_MODIFY + return snprintf(NULL, 0, "[%5lu.000000@0] ", (unsigned long)ts); +#else return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts); +#endif #if defined(CONFIG_SMP) && defined(CONFIG_AMLOGIC_DRIVER) return sprintf(buf, "[%5lu.%06lu@%d] ", From dc462ccc261f474b6d3cca4b2043055008a7b1f8 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Thu, 24 Jan 2019 09:46:06 +0800 Subject: [PATCH 0068/1060] clk: g12a: clear pcie cntl5 for save power [1/1] PD#SWPL-4583 Problem: cntl5 caused power increase Solution: clear pcie cntl5 when pcie clk disabled Verify: test pass on g12a skt Change-Id: I495590af2ccb81eb5ae90c86008679def8673a70 Signed-off-by: Shunzhou Jiang --- drivers/amlogic/clk/g12a/g12a_clk-pll.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 0f67ff3eccb2..505a6aa81024 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -536,6 +536,11 @@ static void meson_g12a_pll_disable(struct clk_hw *hw) writel(readl(pll->base + p->reg_off) & (~MESON_PLL_ENABLE), pll->base + p->reg_off); + if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { + writel(0x20000060, + pll->base + p->reg_off + 0x14); + } + if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); } From 1aa232bc2f5ec3bc540816c73f2dd0f06e454786 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Thu, 15 Nov 2018 17:37:14 +0800 Subject: [PATCH 0069/1060] osd: osd: screen blank when boot [1/1] PD#172587 Problem: screen blank when boot Solution: modify free_scale_switch Verify: verified on tl1 dev board Change-Id: I3c53e832c83c71bd8e98f71fcd654865a467df3c Signed-off-by: Jian Cao --- drivers/amlogic/media/osd/osd_fb.c | 15 ++++++++-- drivers/amlogic/media/osd/osd_hw.c | 44 ++++++++++++++++-------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index d1b6278ddf87..c4c434eeb240 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -3052,9 +3052,18 @@ static ssize_t free_scale_switch(struct device *device, ret = kstrtoint(buf, 0, &res); free_scale_enable = res; - osd_switch_free_scale( - (fb_info->node == DEV_OSD0) ? DEV_OSD1 : DEV_OSD0, - 0, 0, fb_info->node, 1, free_scale_enable); + + if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) + osd_switch_free_scale( + (fb_info->node == DEV_OSD0) ? DEV_OSD0 : DEV_OSD1, + 1, free_scale_enable, fb_info->node, 1, + free_scale_enable); + else + osd_switch_free_scale( + (fb_info->node == DEV_OSD0) ? DEV_OSD1 : DEV_OSD0, + 0, 0, fb_info->node, 1, + free_scale_enable); + osd_log_info("free_scale_switch to fb%d, mode: 0x%x\n", fb_info->node, free_scale_enable); return count; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 320c3ce516f2..054fceaccfb8 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -3018,8 +3018,6 @@ void osd_switch_free_scale( int i = 0; int count = (pxp_mode == 1)?3:WAIT_AFBC_READY_COUNT; - if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) - return; osd_log_info("osd[%d] enable: %d scale:0x%x (%s)\n", pre_index, pre_enable, pre_scale, current->comm); osd_log_info("osd[%d] enable: %d scale:0x%x (%s)\n", @@ -3036,16 +3034,17 @@ void osd_switch_free_scale( if (i > 0) osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", next_index, i); - h_enable = (pre_scale & 0xffff0000 ? 1 : 0); - v_enable = (pre_scale & 0xffff ? 1 : 0); - osd_hw.free_scale[pre_index].h_enable = h_enable; - osd_hw.free_scale[pre_index].v_enable = v_enable; - osd_hw.free_scale_enable[pre_index] = pre_scale; - osd_hw.free_scale_backup[pre_index].h_enable = h_enable; - osd_hw.free_scale_backup[pre_index].v_enable = v_enable; - osd_hw.free_scale_enable_backup[pre_index] = pre_scale; - osd_hw.enable[pre_index] = pre_enable; - + if (pre_index != next_index) { + h_enable = (pre_scale & 0xffff0000 ? 1 : 0); + v_enable = (pre_scale & 0xffff ? 1 : 0); + osd_hw.free_scale[pre_index].h_enable = h_enable; + osd_hw.free_scale[pre_index].v_enable = v_enable; + osd_hw.free_scale_enable[pre_index] = pre_scale; + osd_hw.free_scale_backup[pre_index].h_enable = h_enable; + osd_hw.free_scale_backup[pre_index].v_enable = v_enable; + osd_hw.free_scale_enable_backup[pre_index] = pre_scale; + osd_hw.enable[pre_index] = pre_enable; + } h_enable = (next_scale & 0xffff0000 ? 1 : 0); v_enable = (next_scale & 0xffff ? 1 : 0); osd_hw.free_scale[next_index].h_enable = h_enable; @@ -3066,14 +3065,16 @@ void osd_switch_free_scale( osd_afbc_dec_enable = 0; osd_hw.reg[OSD_GBL_ALPHA].update_func(next_index); } - - osd_hw.reg[OSD_COLOR_MODE].update_func(pre_index); - if (pre_scale) - osd_hw.reg[OSD_FREESCALE_COEF].update_func(pre_index); - osd_hw.reg[DISP_GEOMETRY].update_func(pre_index); - osd_hw.reg[DISP_FREESCALE_ENABLE].update_func(pre_index); - osd_hw.reg[OSD_ENABLE].update_func(pre_index); - + if (pre_index != next_index) { + osd_hw.reg[OSD_COLOR_MODE].update_func(pre_index); + if (pre_scale) + osd_hw.reg[OSD_FREESCALE_COEF]. + update_func(pre_index); + osd_hw.reg[DISP_GEOMETRY].update_func(pre_index); + osd_hw.reg[DISP_FREESCALE_ENABLE]. + update_func(pre_index); + osd_hw.reg[OSD_ENABLE].update_func(pre_index); + } osd_hw.reg[OSD_COLOR_MODE].update_func(next_index); if (next_scale) osd_hw.reg @@ -3085,7 +3086,8 @@ void osd_switch_free_scale( spin_unlock_irqrestore(&osd_lock, lock_flags); osd_wait_vsync_hw(); } else { - osd_enable_hw(pre_index, pre_enable); + if (pre_index != next_index) + osd_enable_hw(pre_index, pre_enable); osd_enable_hw(next_index, next_enable); } } From c7f3e2191bf161df53118f19b68d02b5ff1a81e3 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 26 Feb 2019 17:08:35 +0800 Subject: [PATCH 0070/1060] osd: move wait hw vsync for afbc when phy_addr==0 only before chip g12A [1/1] PD#SWPL-5148 Problem: bootvideo stuck when starting to play Solution: wait hw vsync for afbc when phy_addr==0 only before chip g12A Verify: tl1 Change-Id: I883c8f6699729854a852fc70c22b5629aa025c60 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 35 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 054fceaccfb8..a0b6c476b7c2 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -2812,17 +2812,18 @@ void osd_enable_hw(u32 index, u32 enable) add_to_update_list(index, OSD_GBL_ALPHA); add_to_update_list(index, DISP_GEOMETRY); osd_wait_vsync_hw(); - } - while ((index == 0) && osd_hw.osd_afbcd[index].enable && + while ((index == 0) && osd_hw.osd_afbcd[index].enable && (osd_hw.osd_afbcd[index].phy_addr == 0) && enable && (i < count)) { - osd_wait_vsync_hw(); - i++; + osd_wait_vsync_hw(); + i++; + } + if (i > 0) + osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", + index, i); } - if (i > 0) - osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", - index, i); + osd_hw.enable[index] = enable; if (get_osd_hwc_type() != OSD_G12A_NEW_HWC) { add_to_update_list(index, OSD_ENABLE); @@ -3024,16 +3025,18 @@ void osd_switch_free_scale( next_index, next_enable, next_scale, current->comm); if (osd_hw.free_scale_mode[pre_index] || osd_hw.free_scale_mode[next_index]) { - while ((next_index == OSD1) - && osd_hw.osd_afbcd[next_index].enable - && (osd_hw.osd_afbcd[next_index].phy_addr == 0) - && next_enable && (i < count)) { - osd_wait_vsync_hw(); - i++; + if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) { + while ((next_index == OSD1) + && osd_hw.osd_afbcd[next_index].enable + && (osd_hw.osd_afbcd[next_index].phy_addr == 0) + && next_enable && (i < count)) { + osd_wait_vsync_hw(); + i++; + } + if (i > 0) + osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", + next_index, i); } - if (i > 0) - osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", - next_index, i); if (pre_index != next_index) { h_enable = (pre_scale & 0xffff0000 ? 1 : 0); v_enable = (pre_scale & 0xffff ? 1 : 0); From 9010a8d8e6c493f7ffd22db8f05c791030fd1653 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Thu, 20 Dec 2018 16:59:53 +0800 Subject: [PATCH 0071/1060] tee: add swapping of the fw for the tee loading. [3/7] PD#SWPL-2367 Problem: can not playback hevc after update video fw. Solution: add swapping of the fw for the tee loading. Verify: p212,u212 Change-Id: I698e43ba8e71060f85be4b468c4c61d625f46d4a Signed-off-by: Nanxin Qin --- drivers/amlogic/tee/tee.c | 4 ++-- include/linux/amlogic/tee.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/tee/tee.c b/drivers/amlogic/tee/tee.c index 2d2e2245d112..2e51e184a508 100644 --- a/drivers/amlogic/tee/tee.c +++ b/drivers/amlogic/tee/tee.c @@ -162,7 +162,7 @@ static CLASS_ATTR(api_version, 0644, tee_api_version_show, * index: firmware index * vdec: vdec type(0: compatible, 1: legency vdec, 2: HEVC vdec) */ -int tee_load_video_fw(uint32_t index, uint32_t vdec) +int tee_load_video_fw(uint32_t index, uint32_t vdec, bool is_swap) { struct arm_smccc_res res; long cpu; @@ -177,7 +177,7 @@ int tee_load_video_fw(uint32_t index, uint32_t vdec) } arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW, - index, vdec, 0, 0, 0, 0, 0, &res); + index, vdec, is_swap, 0, 0, 0, 0, &res); if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) == MESON_CPU_MAJOR_ID_G12B) diff --git a/include/linux/amlogic/tee.h b/include/linux/amlogic/tee.h index 46a518c02a39..0c620489d15a 100644 --- a/include/linux/amlogic/tee.h +++ b/include/linux/amlogic/tee.h @@ -20,6 +20,6 @@ extern bool tee_enabled(void); extern int is_secload_get(void); -extern int tee_load_video_fw(uint32_t index, uint32_t vdec); +extern int tee_load_video_fw(uint32_t index, uint32_t vdec, bool is_swap); #endif /* __TEE_H__ */ From 2fe25c729baa19e7cb2e4b5e1de21e7a6822ae0c Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Sun, 27 Jan 2019 01:21:20 +0800 Subject: [PATCH 0072/1060] tee: add an interface for the teeload with swapping. [1/1] PD#SWPL-2367 Problem: building err and issue of compatibility. Solution: 1. fixed building err without merging media_modules 2. add a new api tee_load_video_fw_swap Verify: p212,u212 Change-Id: Ifeedf2f3fa04b2427dccf2ac3940bad6860362d6 Signed-off-by: Nanxin Qin --- drivers/amlogic/tee/tee.c | 13 ++++++++++++- include/linux/amlogic/tee.h | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/tee/tee.c b/drivers/amlogic/tee/tee.c index 2e51e184a508..b10634f238b4 100644 --- a/drivers/amlogic/tee/tee.c +++ b/drivers/amlogic/tee/tee.c @@ -162,7 +162,7 @@ static CLASS_ATTR(api_version, 0644, tee_api_version_show, * index: firmware index * vdec: vdec type(0: compatible, 1: legency vdec, 2: HEVC vdec) */ -int tee_load_video_fw(uint32_t index, uint32_t vdec, bool is_swap) +static int tee_load_firmware(uint32_t index, uint32_t vdec, bool is_swap) { struct arm_smccc_res res; long cpu; @@ -184,8 +184,19 @@ int tee_load_video_fw(uint32_t index, uint32_t vdec, bool is_swap) set_cpus_allowed_ptr(current, cpu_all_mask); return res.a0; } + +int tee_load_video_fw(uint32_t index, uint32_t vdec) +{ + return tee_load_firmware(index, vdec, false); +} EXPORT_SYMBOL(tee_load_video_fw); +int tee_load_video_fw_swap(uint32_t index, uint32_t vdec, bool is_swap) +{ + return tee_load_firmware(index, vdec, is_swap); +} +EXPORT_SYMBOL(tee_load_video_fw_swap); + bool tee_enabled(void) { struct arm_smccc_res res; diff --git a/include/linux/amlogic/tee.h b/include/linux/amlogic/tee.h index 0c620489d15a..224dde5cb3ee 100644 --- a/include/linux/amlogic/tee.h +++ b/include/linux/amlogic/tee.h @@ -20,6 +20,7 @@ extern bool tee_enabled(void); extern int is_secload_get(void); -extern int tee_load_video_fw(uint32_t index, uint32_t vdec, bool is_swap); +extern int tee_load_video_fw(uint32_t index, uint32_t vdec); +extern int tee_load_video_fw_swap(uint32_t index, uint32_t vdec, bool is_swap); #endif /* __TEE_H__ */ From c8634b77b585d8c1cc447c062d36bc0652047ce0 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Sat, 2 Mar 2019 20:52:35 +0800 Subject: [PATCH 0073/1060] vpp: refresh the vd/osd blend ctrl when enable/disable video [1/1] PD#SWPL-4932 Problem: The vd/osd blend ctrl is not correct when disable video Solution: Refresh the vd/osd blend ctrl for that case Verify: Verified on tl1 Change-Id: I6a7bfc58c810279cdfbf55f3d6a51e94890b4899 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index b55ed351561d..a433cd11d9d3 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -5936,6 +5936,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) int video2_off_req = 0; struct vframe_s *cur_dispbuf_back = cur_dispbuf; static struct vframe_s *pause_vf; + int force_flush = 0; if (debug_flag & DEBUG_FLAG_VSYNC_DONONE) return IRQ_HANDLED; @@ -7338,6 +7339,7 @@ SET_FILTER: pr_info("VsyncEnableVideoLayer\n"); vpu_delay_work_flag |= VPU_VIDEO_LAYER1_CHANGED; + force_flush = 1; } else if (video_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { vpp_misc_set &= ~(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND); @@ -7357,6 +7359,7 @@ SET_FILTER: if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("VsyncDisableVideoLayer\n"); video1_off_req = 1; + force_flush = 1; } spin_unlock_irqrestore(&video_onoff_lock, flags); @@ -7407,6 +7410,7 @@ SET_FILTER: if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("VsyncEnableVideoLayer2\n"); + force_flush = 1; } else if (video2_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { vpp_misc_set &= ~(VPP_VD2_PREBLEND | VPP_VD2_POSTBLEND | VPP_PREBLEND_EN @@ -7417,6 +7421,7 @@ SET_FILTER: if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("VsyncDisableVideoLayer2\n"); video2_off_req = 1; + force_flush = 1; } spin_unlock_irqrestore(&video2_onoff_lock, flags); } @@ -7460,7 +7465,7 @@ SET_FILTER: if (!legacy_vpp) { u32 set_value = 0; - int force_flush = vpp_zorder_check(); + force_flush |= vpp_zorder_check(); vpp_misc_set &= ((1 << 29) | VPP_CM_ENABLE | From b421eebcf66f4a9f1b395c9f68f759a3f151f71d Mon Sep 17 00:00:00 2001 From: Peng Yixin Date: Sat, 16 Feb 2019 10:23:57 +0800 Subject: [PATCH 0074/1060] media_module: add function to statistics drop frame on video layer [1/1] PD#SWPL-1885 Problem: We need a function to statistics drop frame. Solution: Add a function to statistics drop frame. Verify: Verified U212 Change-Id: I30b429c2f3710c5c8d0da6ec083060c9cc3e61ad Signed-off-by: Peng Yixin --- drivers/amlogic/media/video_sink/video.c | 120 ++++++++++++++++++ drivers/amlogic/media/video_sink/video_priv.h | 2 + 2 files changed, 122 insertions(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index a433cd11d9d3..fef950f282f7 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -122,6 +122,12 @@ struct platform_resource_s { int mem_end; }; #endif + +struct video_frame_detect_s { + u32 interrupt_count; + u32 start_receive_count; +}; + static int debugflags; static int output_fps; static u32 omx_pts; @@ -146,6 +152,7 @@ static bool omx_drop_done; static bool video_start_post; static bool videopeek; static bool nopostvideostart; +static struct video_frame_detect_s video_frame_detect; /*----omx_info bit0: keep_last_frame, bit1~31: unused----*/ static u32 omx_info = 0x1; @@ -241,6 +248,25 @@ static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; static u32 hdmiin_frame_check; static u32 hdmiin_frame_check_cnt; + +/*frame_detect_flag: 1 enable, 0 disable */ +/*frame_detect_time: */ +/* How often "frame_detect_receive_count" and */ +/* "frame_detect_drop_count" are updated, suggested set 1(s) */ +/*frame_detect_fps: Set fps based on the video file, */ +/* If the FPS is 60, set it to 60000. */ +/*frame_detect_receive_count: */ +/* The number of frame that should be obtained during the test time. */ +/*frame_detect_drop_count: */ +/* The number of frame lost during test time. */ + + +static u32 frame_detect_flag; +static u32 frame_detect_time = 1; +static u32 frame_detect_fps = 60000; +static u32 frame_detect_receive_count; +static u32 frame_detect_drop_count; + #ifdef FIQ_VSYNC #define BRIDGE_IRQ INT_TIMER_C #define BRIDGE_IRQ_SET() WRITE_CBUS_REG(ISA_TIMERC, 1) @@ -5937,10 +5963,82 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) struct vframe_s *cur_dispbuf_back = cur_dispbuf; static struct vframe_s *pause_vf; int force_flush = 0; + static u32 interrupt_count; if (debug_flag & DEBUG_FLAG_VSYNC_DONONE) return IRQ_HANDLED; + if (frame_detect_flag == 1 && + receive_frame_count && + frame_detect_time && + !atomic_read(&video_unreg_flag)) { + struct vinfo_s *video_info; + + video_info = get_current_vinfo(); + if (video_frame_detect.interrupt_count == 0) { + interrupt_count = 0; + video_frame_detect.interrupt_count = + frame_detect_time * + video_info->sync_duration_num / + video_info->sync_duration_den; + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("sync_duration_num = %d\n", + video_info->sync_duration_num); + pr_info("sync_duration_den = %d\n", + video_info->sync_duration_den); + } + video_frame_detect.start_receive_count = + receive_frame_count; + } + + interrupt_count++; + + if (interrupt_count == video_frame_detect.interrupt_count + 1) { + u32 receive_count; + u32 expect_frame_count; + + receive_count = receive_frame_count - + video_frame_detect.start_receive_count; + expect_frame_count = + video_frame_detect.interrupt_count * + frame_detect_fps * + video_info->sync_duration_den / + video_info->sync_duration_num / + 1000; + + if (receive_count < expect_frame_count) { + frame_detect_drop_count += + expect_frame_count - + receive_count; + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("drop_count = %d\n", + expect_frame_count - + receive_count); + } + frame_detect_receive_count += + expect_frame_count; + } else + frame_detect_receive_count += receive_count; + + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("expect count = %d\n", + expect_frame_count); + pr_info("receive_count = %d, time = %ds\n", + receive_count, + frame_detect_time); + pr_info("interrupt_count = %d\n", + video_frame_detect.interrupt_count); + pr_info("frame_detect_drop_count = %d\n", + frame_detect_drop_count); + pr_info("frame_detect_receive_count = %d\n", + frame_detect_receive_count); + } + interrupt_count = 0; + memset(&video_frame_detect, 0, + sizeof(struct video_frame_detect_s)); + } + } + #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 const char *dev_id_s = (const char *)dev_id; int dev_id_len = strlen(dev_id_s); @@ -7844,6 +7942,10 @@ static void video_vf_unreg_provider(void) atomic_set(&video_unreg_flag, 1); while (atomic_read(&video_inirq_flag) > 0) schedule(); + memset(&video_frame_detect, 0, + sizeof(struct video_frame_detect_s)); + frame_detect_drop_count = 0; + frame_detect_receive_count = 0; spin_lock_irqsave(&lock, flags); #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA @@ -12609,6 +12711,24 @@ module_param(receive_frame_count, int, 0664); MODULE_PARM_DESC(display_frame_count, "\n display_frame_count\n"); module_param(display_frame_count, int, 0664); +module_param(frame_detect_time, uint, 0664); +MODULE_PARM_DESC(frame_detect_time, "\n frame_detect_time\n"); + +module_param(frame_detect_flag, uint, 0664); +MODULE_PARM_DESC(frame_detect_flag, "\n frame_detect_flag\n"); + +module_param(frame_detect_fps, uint, 0664); +MODULE_PARM_DESC(frame_detect_fps, "\n frame_detect_fps\n"); + +module_param(frame_detect_receive_count, uint, 0664); +MODULE_PARM_DESC(frame_detect_receive_count, "\n frame_detect_receive_count\n"); + +module_param(frame_detect_drop_count, uint, 0664); +MODULE_PARM_DESC(frame_detect_drop_count, "\n frame_detect_drop_count\n"); + + + + MODULE_PARM_DESC(bypass_pps, "\n pps_bypass\n"); module_param(bypass_pps, bool, 0664); diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h index 446a8a9e2399..f540771c45aa 100644 --- a/drivers/amlogic/media/video_sink/video_priv.h +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -31,6 +31,8 @@ #define DEBUG_FLAG_GOFIELD_MANUL 0x100000 #define DEBUG_FLAG_LATENCY 0x200000 #define DEBUG_FLAG_PTS_TRACE 0x400000 +#define DEBUG_FLAG_FRAME_DETECT 0x800000 + /*for video.c's static int debug_flag;*/ #define VOUT_TYPE_TOP_FIELD 0 From 7759da094d51dd15af95ef4ad6971daf080f38c2 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 13 Mar 2019 14:05:34 +0800 Subject: [PATCH 0075/1060] di: play 1080i timing always print di err[1/1] PD#SWPL-5807 Problem: 1080i always print di err,modify di pre idle register define are wrong Solution: 1.modify register define according g12a Verify: g12a Change-Id: I13400d8b18e0e85894ba8d10afc0ae119874aab4 Signed-off-by: Yong Qin Signed-off-by: Luan Yuan Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c --- .../amlogic/media/deinterlace/deinterlace.c | 2 +- .../media/deinterlace/deinterlace_hw.c | 20 +++++++++---------- drivers/amlogic/media/deinterlace/register.h | 11 +++------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 01606e87d643..9c12e063b761 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-02-27a"; +static const char version_s[] = "2019-03-14a"; static int bypass_state = 1; static int bypass_all; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 8796b2584593..a8b7c89d0f51 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -3403,12 +3403,12 @@ bool di_pre_idle(void) { bool ret = false; - if (is_meson_tl1_cpu()) { - if ((RDMA_RD(VPU_ARB_DBG_STAT_L1C1_TL1) & + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if ((RDMA_RD(DI_ARB_DBG_STAT_L1C1) & PRE_ID_MASK_TL1) == PRE_ID_MASK_TL1) ret = true; } else { - if ((RDMA_RD(VPU_ARB_DBG_STAT_L1C1) & + if ((RDMA_RD(DI_ARB_DBG_STAT_L1C1_OLD) & PRE_ID_MASK) == PRE_ID_MASK) ret = true; } @@ -3425,18 +3425,18 @@ void di_arb_sw(bool on) u32 WRARB_onval; u32 WRARB_offval; - if (is_meson_tl1_cpu()) { - REG_VPU_WRARB_REQEN_SLV_L1C1 = VPU_WRARB_REQEN_SLV_L1C1_TL1; - REG_VPU_RDARB_REQEN_SLV_L1C1 = VPU_RDARB_REQEN_SLV_L1C1_TL1; - REG_VPU_ARB_DBG_STAT_L1C1 = VPU_ARB_DBG_STAT_L1C1_TL1; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + REG_VPU_WRARB_REQEN_SLV_L1C1 = DI_WRARB_REQEN_SLV_L1C1; + REG_VPU_RDARB_REQEN_SLV_L1C1 = DI_RDARB_REQEN_SLV_L1C1; + REG_VPU_ARB_DBG_STAT_L1C1 = DI_ARB_DBG_STAT_L1C1; if (on) WRARB_onval = 0x3f; else WRARB_offval = 0x3e; } else { - REG_VPU_WRARB_REQEN_SLV_L1C1 = VPU_WRARB_REQEN_SLV_L1C1; - REG_VPU_RDARB_REQEN_SLV_L1C1 = VPU_RDARB_REQEN_SLV_L1C1; - REG_VPU_ARB_DBG_STAT_L1C1 = VPU_ARB_DBG_STAT_L1C1; + REG_VPU_WRARB_REQEN_SLV_L1C1 = DI_WRARB_REQEN_SLV_L1C1_OLD; + REG_VPU_RDARB_REQEN_SLV_L1C1 = DI_RDARB_REQEN_SLV_L1C1_OLD; + REG_VPU_ARB_DBG_STAT_L1C1 = DI_ARB_DBG_STAT_L1C1_OLD; if (on) WRARB_onval = 0x3f; else diff --git a/drivers/amlogic/media/deinterlace/register.h b/drivers/amlogic/media/deinterlace/register.h index cc73dc2a7cf8..5ce602d7f00c 100644 --- a/drivers/amlogic/media/deinterlace/register.h +++ b/drivers/amlogic/media/deinterlace/register.h @@ -44,14 +44,9 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, #define HHI_VPU_CLKB_CNTL 0x83 -#define VPU_WRARB_REQEN_SLV_L1C1 0x2795 -#define VPU_RDARB_REQEN_SLV_L1C1 0x2791 -#define VPU_ARB_DBG_STAT_L1C1 0x27b4 - -#define VPU_WRARB_REQEN_SLV_L1C1_TL1 0x2055 -#define VPU_RDARB_REQEN_SLV_L1C1_TL1 0x2051 -#define VPU_ARB_DBG_STAT_L1C1_TL1 0x205a - +#define DI_WRARB_REQEN_SLV_L1C1_OLD 0x2795 +#define DI_RDARB_REQEN_SLV_L1C1_OLD 0x2791 +#define DI_ARB_DBG_STAT_L1C1_OLD 0x27b4 #define VIUB_SW_RESET 0x2001 #define VIUB_SW_RESET0 0x2002 From 5f51997badadaa4ee25a9da262fe9bee6ecbea9c Mon Sep 17 00:00:00 2001 From: Kai Song Date: Wed, 13 Feb 2019 10:12:39 +0800 Subject: [PATCH 0076/1060] codec_mm: Fix cma clear and rebuild map for codec_mm. [1/1] PD#172483 Problem: To avoid A73 core speculative data loading from protected memory, which triggers SError fault, the mapping of the protected region should be cleared. In codec_mm driver, the page structure pointer used to clear the mapping is wrong. Although the memory is allocated from CMA, because we are using CMA_res mode the address from CMA_res_pool is actually a physical address, similar as reserved memory case. As a result, the mapping to protected address is not cleared. Solution: 1.Add "mem->from_flags == AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES" case processing. Verify: Run YTTV and there is no SError crash after the fix. Change-Id: Ia912337c1d7d5a55800fc55ad1d61016f9710f4d Signed-off-by: Kai Song --- .../amlogic/media/common/codec_mm/codec_mm.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index c6dabedcb13f..17dc5948df7d 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -1099,8 +1099,14 @@ int codec_mm_extpool_pool_alloc( CODEC_MM_FLAGS_FOR_LOCAL_MGR | CODEC_MM_FLAGS_CMA); if (mem) { + struct page *mm = mem->mem_handle; + + if (mem->from_flags == + AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES) + mm = phys_to_page( + (unsigned long)mm); if (for_tvp) { - cma_mmu_op(mem->mem_handle, + cma_mmu_op(mm, mem->page_count, 0); } @@ -1109,7 +1115,7 @@ int codec_mm_extpool_pool_alloc( mem); if (ret < 0) { if (for_tvp) { - cma_mmu_op(mem->mem_handle, + cma_mmu_op(mm, mem->page_count, 1); } @@ -1160,7 +1166,13 @@ static int codec_mm_extpool_pool_release(struct extpool_mgt_s *tvp_pool) slot_mem_size = gen_pool_size(gpool); gen_pool_destroy(tvp_pool->gen_pool[i]); if (tvp_pool->mm[i]) { - cma_mmu_op(tvp_pool->mm[i]->mem_handle, + struct page *mm = tvp_pool->mm[i]->mem_handle; + + if (tvp_pool->mm[i]->from_flags == + AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES) + mm = phys_to_page( + (unsigned long)mm); + cma_mmu_op(mm, tvp_pool->mm[i]->page_count, 1); codec_mm_release(tvp_pool->mm[i], From 052dfa5f936a0ea927413f0238878aa17ad023f9 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Wed, 13 Feb 2019 10:34:30 +0800 Subject: [PATCH 0077/1060] dv: hang when home during DoVi playback [1/1] PD#SWPL-4406 Problem: SDR meta size > 0 during DoVi to SDR transition Solution: fixed SDR meta size to 0 for SDR Verify: u212 Change-Id: I92129163da0df9c81bb508ce56b78268fbd87a2e Signed-off-by: Yi Zhou --- .../media/enhancement/amdolby_vision/amdolby_vision.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index 0170c3f392a5..fb51c0682f21 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -5499,8 +5499,12 @@ int dolby_vision_parse_metadata( new_dovi_setting.video_height = h << 16; flag = p_funcs->control_path( src_format, dst_format, - comp_buf[currentId], total_comp_size, - md_buf[currentId], total_md_size, + comp_buf[currentId], + ((src_format == FORMAT_DOVI) + || (src_format == FORMAT_DOVI_LL)) ? total_comp_size : 0, + md_buf[currentId], + ((src_format == FORMAT_DOVI) + || (src_format == FORMAT_DOVI_LL)) ? total_md_size : 0, pri_mode, src_bdp, 0, SIG_RANGE_SMPTE, /* bit/chroma/range */ graphic_min, From b9922e3ba3852b2e2a924972b8016e257a38a6c8 Mon Sep 17 00:00:00 2001 From: Zhuo Wang Date: Tue, 5 Mar 2019 13:45:26 +0800 Subject: [PATCH 0078/1060] ethernet: remove internal_phy_remove [1/1] PD#SWPL-5478 Problem: system will crash rately if not init success Solution: remote internal_phy_remove function for chip later then g12a Verify: verify on u200 board Change-Id: Id6c3bf77c2a448aee9675deff47dc106206146d6 Signed-off-by: Zhuo Wang --- drivers/amlogic/ethernet/phy/amlogic.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/amlogic/ethernet/phy/amlogic.c b/drivers/amlogic/ethernet/phy/amlogic.c index e94026241a55..4db2444ec9bd 100644 --- a/drivers/amlogic/ethernet/phy/amlogic.c +++ b/drivers/amlogic/ethernet/phy/amlogic.c @@ -386,7 +386,6 @@ static struct phy_driver amlogic_internal_driver[] = { .read_status = genphy_read_status, .suspend = genphy_suspend, .resume = genphy_resume, - .remove = internal_phy_remove, } }; module_phy_driver(amlogic_internal_driver); From e2ea57ad7326e3b4e1f6fab2dd34cd56a19a80a3 Mon Sep 17 00:00:00 2001 From: Jian Hu Date: Mon, 4 Mar 2019 20:01:08 +0800 Subject: [PATCH 0079/1060] clkmsr: axg: delete hard code which added during bringup [1/1] PD#SWPL-5356 Problem: when cat clkmsr node in sysfs, i2c bus does not work Solution: delete hard code Verify: verify on axg s400 Change-Id: Ib01f251f4b77685db5a57df395f1c1a75620c07b Signed-off-by: Jian Hu --- drivers/amlogic/clk/clk_measure.c | 42 +++---------------------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/drivers/amlogic/clk/clk_measure.c b/drivers/amlogic/clk/clk_measure.c index ce5b13dda679..1ca3ef02362f 100644 --- a/drivers/amlogic/clk/clk_measure.c +++ b/drivers/amlogic/clk/clk_measure.c @@ -50,10 +50,6 @@ static DEFINE_SPINLOCK(clk_measure_lock); #define CLKMSR_DEVICE_NAME "clkmsr" unsigned int clk_msr_index = 0xff; -#define AUDIO_FLAG BIT(16) -#define HHI_GEN_CLK_CNTL 0x8a -#define AO_RTI_PIN_MUX_REG1 0x18 -unsigned int audio_index; struct meson_clkmsr_data { const char * const *clk_table; @@ -164,36 +160,6 @@ static unsigned int meson_clk_util_ring_msr(unsigned int clk_mux) } -static unsigned int axg_clk_util_clk_msr(unsigned int clk_mux) -{ - unsigned int clk_val; - - if (clk_mux&AUDIO_FLAG) { - /*for audio*/ - /*set gen_clk_out: cts_msr_clk*/ - aml_write_hiubus(HHI_GEN_CLK_CNTL, 0xc800); - /*msr_clk_mux_sel*/ - writel_relaxed(((clk_mux&0xff)<<20)|(1<<19), msr_clk_reg0); - /*pinmux for GEN_CLK_EE*/ - aml_write_aobus(AO_RTI_PIN_MUX_REG1, 0x402230); - audio_index = clk_mux; - } else { - /*clear gen_clk_out: cts_msr_clk*/ - aml_write_hiubus(HHI_GEN_CLK_CNTL, 0x0); - /*measure clk*/ - clk_val = gxbb_clk_util_clk_msr(clk_mux); - /*for audio*/ - /*set gen_clk_out: cts_msr_clk*/ - aml_write_hiubus(HHI_GEN_CLK_CNTL, 0xc800); - /*msr_clk_mux_sel*/ - writel_relaxed(((audio_index&0xff)<<20)|(1<<19), msr_clk_reg0); - /*pinmux for GEN_CLK_EE*/ - aml_write_aobus(AO_RTI_PIN_MUX_REG1, 0x402230); - return clk_val; - } - return 0; -} - int m8b_clk_measure(struct seq_file *s, void *what, unsigned int index) { static const char * const clk_table[] = { @@ -603,11 +569,11 @@ int axg_clk_measure(struct seq_file *s, void *what, unsigned int index) if (index == 0xff) { for (i = 0; i < len; i++) seq_printf(s, "[%2d][%10d]%s\n", - i, axg_clk_util_clk_msr(i), + i, gxbb_clk_util_clk_msr(i), clk_table[i]); return 0; } - seq_printf(s, "[%10d]%s\n", axg_clk_util_clk_msr(index), + seq_printf(s, "[%10d]%s\n", gxbb_clk_util_clk_msr(index), clk_table[index]); clk_msr_index = 0xff; return 0; @@ -1218,10 +1184,8 @@ int meson_clk_measure(unsigned int clk_mux) case MESON_CPU_MAJOR_ID_TXLX: case MESON_CPU_MAJOR_ID_G12A: case MESON_CPU_MAJOR_ID_G12B: - clk_val = gxbb_clk_util_clk_msr(clk_mux); - break; case MESON_CPU_MAJOR_ID_AXG: - clk_val = axg_clk_util_clk_msr(clk_mux); + clk_val = gxbb_clk_util_clk_msr(clk_mux); break; default: pr_info("Unsupported chip clk measure\n"); From 708fc13c89bcdfb21f580a461b00010c1956b946 Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Wed, 23 Jan 2019 20:04:29 +0800 Subject: [PATCH 0080/1060] media_module: vdec [1/1] PD#OTT-1699 Problem: not support multi-vdec user data read Solution: Add getting available user data vdec interface Verify: Verified U212 Change-Id: I9ec65367935ac42a83808db23f2fb08f694e1483 Signed-off-by: Rong Zhang --- include/linux/amlogic/media/utils/amstream.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index d845ae174179..33663827f34f 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -141,13 +141,16 @@ #define AMSTREAM_IOC_UD_POC _IOR((_A_M), 0x55, int) #define AMSTREAM_IOC_UD_FLUSH_USERDATA _IOR((_A_M), 0x56, int) -#define AMSTREAM_IOC_UD_BUF_READ _IOR((_A_M), 0x57, struct userdata_param_t) +#define AMSTREAM_IOC_UD_BUF_READ _IOR((_A_M), 0x57, int) #define AMSTREAM_IOC_GET_SCREEN_MODE _IOR((_A_M), 0x58, int) #define AMSTREAM_IOC_SET_SCREEN_MODE _IOW((_A_M), 0x59, int) #define AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT _IOR((_A_M), 0x5a, int) #define AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT _IOW((_A_M), 0x5b, int) +#define AMSTREAM_IOC_UD_AVAILABLE_VDEC _IOR((_A_M), 0x5c, unsigned int) +#define AMSTREAM_IOC_GET_VDEC_ID _IOR((_A_M), 0x5d, int) + /* * #define AMSTREAM_IOC_UD_BUF_STATUS _IOR((_A_M), * 0x5c, struct userdata_buf_state_t) @@ -491,7 +494,7 @@ struct userdata_param_t { uint32_t instance_id; /*input, 0~9*/ uint32_t buf_len; /*input*/ uint32_t data_size; /*output*/ - unsigned long long pbuf_addr; /*input*/ + void *pbuf_addr; /*input*/ struct userdata_meta_info_t meta_info; /*output*/ }; From 233b86888588ed4c4cedd9d1538c1409c9cd8dec Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Wed, 30 Jan 2019 11:42:22 +0800 Subject: [PATCH 0081/1060] codec_mm: fixed some issues of the mem operation. [1/2] PD#SWPL-3593 Problem: the memory data might be discordant. Solution: 1. opitimize the mem mapping and change the page type to nocache. 2. modified the way of flush mem which from lowmem or highmem. Verify: x301 Change-Id: I82351c235915c98a86fd201c2ff3994e4d2085ec Signed-off-by: Nanxin Qin --- .../amlogic/media/common/codec_mm/codec_mm.c | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index 17dc5948df7d..4461f65066ee 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -326,44 +326,43 @@ static void *codec_mm_search_vaddr(unsigned long phy_addr) u8 *codec_mm_vmap(ulong addr, u32 size) { u8 *vaddr = NULL; - ulong phys = addr; - u32 offset = phys & ~PAGE_MASK; - u32 npages = PAGE_ALIGN(size) / PAGE_SIZE; struct page **pages = NULL; + u32 i, npages, offset = 0; + ulong phys, page_start; pgprot_t pgprot; - int i; - if (!PageHighMem(phys_to_page(phys))) - return phys_to_virt(phys); + if (!PageHighMem(phys_to_page(addr))) + return phys_to_virt(addr); - if (offset) - npages++; + /*No cache*/ + pgprot = pgprot_noncached(PAGE_KERNEL); - pages = vmalloc(sizeof(struct page *) * npages); + offset = offset_in_page(addr); + page_start = addr - offset; + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); if (!pages) return NULL; for (i = 0; i < npages; i++) { - pages[i] = phys_to_page(phys); - phys += PAGE_SIZE; + phys = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(phys >> PAGE_SHIFT); } - /*nocache*/ - pgprot = pgprot_writecombine(PAGE_KERNEL); - vaddr = vmap(pages, npages, VM_MAP, pgprot); if (!vaddr) { pr_err("the phy(%lx) vmaped fail, size: %d\n", - addr - offset, npages << PAGE_SHIFT); - vfree(pages); + page_start, npages << PAGE_SHIFT); + kfree(pages); return NULL; } - vfree(pages); + kfree(pages); if (debug_mode & 0x20) { pr_info("[HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", - __func__, addr, vaddr + offset, npages << PAGE_SHIFT); + __func__, page_start, vaddr, npages << PAGE_SHIFT); } return vaddr + offset; @@ -374,7 +373,8 @@ void codec_mm_unmap_phyaddr(u8 *vaddr) { void *addr = (void *)(PAGE_MASK & (ulong)vaddr); - vunmap(addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(addr); } EXPORT_SYMBOL(codec_mm_unmap_phyaddr); @@ -874,14 +874,19 @@ void codec_mm_dma_flush(void *vaddr, phy_addr = page_to_phys(vmalloc_to_page(vaddr)) + offset_in_page(vaddr); if (phy_addr && PageHighMem(phys_to_page(phy_addr))) - flush_cache_vunmap(phy_addr, phy_addr + size); + flush_cache_vmap(phy_addr, phy_addr + size); return; } /* only apply to the lowmem. */ dma_addr = dma_map_single(mgt->dev, vaddr, size, dir); - if (dma_addr) - dma_unmap_single(mgt->dev, dma_addr, size, dir); + if (dma_mapping_error(mgt->dev, dma_addr)) { + pr_err("dma map %d bytes error\n", size); + return; + } + + dma_sync_single_for_device(mgt->dev, dma_addr, size, dir); + dma_unmap_single(mgt->dev, dma_addr, size, dir); } EXPORT_SYMBOL(codec_mm_dma_flush); From c7f60c626769d94f1d7424a9970e91214f7118ed Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Tue, 12 Mar 2019 20:35:54 +0800 Subject: [PATCH 0082/1060] codec_mm: changes the prot of pages to PAGE_KERNEL. [2/2] PD#SWPL-4597 Problem: Probabilistic full-screen display mosaic after seek 8K H265 Solution: alloc mem area with the cached which from the vmap. this way can improve the efficiency of I/O. Change-Id: Icf18b9cd57bdc54f832aa827a535399939b28611 Signed-off-by: Nanxin Qin --- drivers/amlogic/media/common/codec_mm/codec_mm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index 4461f65066ee..33466a84ceaa 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -329,14 +329,11 @@ u8 *codec_mm_vmap(ulong addr, u32 size) struct page **pages = NULL; u32 i, npages, offset = 0; ulong phys, page_start; - pgprot_t pgprot; + pgprot_t pgprot = PAGE_KERNEL; if (!PageHighMem(phys_to_page(addr))) return phys_to_virt(addr); - /*No cache*/ - pgprot = pgprot_noncached(PAGE_KERNEL); - offset = offset_in_page(addr); page_start = addr - offset; npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); @@ -874,7 +871,8 @@ void codec_mm_dma_flush(void *vaddr, phy_addr = page_to_phys(vmalloc_to_page(vaddr)) + offset_in_page(vaddr); if (phy_addr && PageHighMem(phys_to_page(phy_addr))) - flush_cache_vmap(phy_addr, phy_addr + size); + dma_sync_single_for_device(mgt->dev, + phy_addr, size, dir); return; } From da866de6ea9adaa50256d6ab604b8c3ef1943d54 Mon Sep 17 00:00:00 2001 From: tao zeng Date: Fri, 30 Nov 2018 18:01:31 +0800 Subject: [PATCH 0083/1060] mm: optimize thread stack usage on ARMv7 [1/1] PD#SWPL-2681 Problem: Kernel stack usage is large when running many tasks. Solution: Map kernel stack to module space and handle page-fault for stack fault. This can save about 50% memory of stack usage Verify: p212 Change-Id: Ie894bc8f00cb525ddf8ac63c6d99d9c6e937fdc0 Signed-off-by: tao zeng --- arch/arm/configs/meson64_a32_defconfig | 1 - arch/arm/include/asm/assembler.h | 4 + arch/arm/include/asm/memory.h | 17 ++ arch/arm/include/asm/ptrace.h | 7 + arch/arm/include/asm/thread_info.h | 17 ++ arch/arm/kernel/asm-offsets.c | 9 + arch/arm/kernel/entry-armv.S | 89 ++++++ arch/arm/kernel/entry-header.S | 13 + arch/arm/kernel/head-common.S | 4 + arch/arm/kernel/setup.c | 20 ++ arch/arm/kernel/smp.c | 9 + arch/arm/kernel/suspend.c | 39 +++ arch/arm/kernel/unwind.c | 41 +++ drivers/amlogic/memory_ext/Kconfig | 1 - drivers/amlogic/memory_ext/vmap_stack.c | 371 ++++++++++++++++++++++-- fs/namespace.c | 11 + include/linux/amlogic/vmap_stack.h | 30 +- include/linux/sched.h | 10 + kernel/fork.c | 11 +- 19 files changed, 656 insertions(+), 48 deletions(-) diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index f40ccea1e14f..7b040427d660 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -30,7 +30,6 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y -CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 7d727506096f..dc53f286905b 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -208,6 +208,10 @@ THUMB( mov \rd, sp ) THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT ) mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT +#ifdef CONFIG_AMLOGIC_VMAP + add \rd, \rd, #TI_THREAD_SIZE + sub \rd, \rd, #TI_THREAD_INFO_SIZE +#endif .endm /* diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index bde40c41c574..508cee7161da 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -33,18 +33,34 @@ #ifdef CONFIG_MMU +#ifdef CONFIG_AMLOGIC_VMAP +/* + * TASK_SIZE - the maximum size of a user space task. + * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area + */ +#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_64M)) +#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) +#else /* CONFIG_AMLOGIC_VMAP */ /* * TASK_SIZE - the maximum size of a user space task. * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area */ #define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M)) #define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) +#endif /* CONFIG_AMLOGIC_VMAP */ /* * The maximum size of a 26-bit user space task. */ #define TASK_SIZE_26 (UL(1) << 26) +#ifdef CONFIG_AMLOGIC_VMAP +#ifndef CONFIG_THUMB2_KERNEL +#define MODULES_VADDR (PAGE_OFFSET - SZ_64M) +#else +#define MODULES_VADDR (PAGE_OFFSET - SZ_8M) +#endif +#else /* CONFIG_AMLOGIC_VMAP */ /* * The module space lives between the addresses given by TASK_SIZE * and PAGE_OFFSET - it must be within 32MB of the kernel text. @@ -55,6 +71,7 @@ /* smaller range for Thumb-2 symbols relocation (2^24)*/ #define MODULES_VADDR (PAGE_OFFSET - SZ_8M) #endif +#endif /* CONFIG_AMLOGIC_VMAP */ #if TASK_SIZE > MODULES_VADDR #error Top of user space clashes with start of module space diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index e9c9a117bd25..61bdfc358b75 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -164,9 +164,16 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) return regs->ARM_sp; } +#ifdef CONFIG_AMLOGIC_VMAP +#define current_pt_regs(void) ({ (struct pt_regs *) \ + ((current_stack_pointer | (THREAD_SIZE - 1)) - 7 - \ + THREAD_INFO_SIZE) - 1; \ +}) +#else #define current_pt_regs(void) ({ (struct pt_regs *) \ ((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \ }) +#endif #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index df8420672c7e..f01c1eb8000d 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -18,7 +18,15 @@ #define THREAD_SIZE_ORDER 1 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) +#ifdef CONFIG_AMLOGIC_VMAP +#define THREAD_INFO_SIZE (sizeof(struct thread_info)) +#define THREAD_INFO_OFFSET (THREAD_SIZE - THREAD_INFO_SIZE) +#define THREAD_START_SP (THREAD_SIZE - 8 - THREAD_INFO_SIZE) +#define VMAP_RESERVE_SIZE (8 + 4 * 4) +#define VMAP_BACK_SP 12 +#else #define THREAD_START_SP (THREAD_SIZE - 8) +#endif #ifndef __ASSEMBLY__ @@ -88,11 +96,20 @@ register unsigned long current_stack_pointer asm ("sp"); */ static inline struct thread_info *current_thread_info(void) __attribute_const__; +#ifdef CONFIG_AMLOGIC_VMAP +static inline struct thread_info *current_thread_info(void) +{ + return (struct thread_info *) + (((current_stack_pointer & ~(THREAD_SIZE - 1)) + + THREAD_INFO_OFFSET)); +} +#else static inline struct thread_info *current_thread_info(void) { return (struct thread_info *) (current_stack_pointer & ~(THREAD_SIZE - 1)); } +#endif #define thread_saved_pc(tsk) \ ((unsigned long)(task_thread_info(tsk)->cpu_context.pc)) diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 608008229c7d..365842d8a811 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -183,5 +183,14 @@ int main(void) #ifdef CONFIG_VDSO DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store)); #endif + +#ifdef CONFIG_AMLOGIC_VMAP + DEFINE(TI_THREAD_START_SP, THREAD_START_SP); + DEFINE(TI_VMAP_BACK_SP, VMAP_BACK_SP); + DEFINE(TI_VMAP_RESERVE_LEN, VMAP_RESERVE_SIZE); + DEFINE(TI_THREAD_SIZE, THREAD_SIZE); + DEFINE(TI_THREAD_INFO_SIZE, sizeof(struct thread_info)); +#endif + return 0; } diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 9f157e7c51e7..bd77d9ce82a7 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -39,6 +39,12 @@ * Interrupt handling. */ .macro irq_handler +#ifdef CONFIG_AMLOGIC_VMAP + mov r8, sp /* back up sp */ + mov r0, sp + bl irq_stack_entry /* switch IRQ stack */ + mov sp, r0 +#endif #ifdef CONFIG_MULTI_IRQ_HANDLER ldr r1, =handle_arch_irq mov r0, sp @@ -48,6 +54,9 @@ arch_irq_handler_default #endif 9997: +#ifdef CONFIG_AMLOGIC_VMAP + mov sp, r8 /* switch stack back to task stack */ +#endif .endm .macro pabt_helper @@ -149,10 +158,24 @@ ENDPROC(__und_invalid) #define SPFIX(code...) #endif +#ifdef CONFIG_AMLOGIC_VMAP + .macro svc_entry, stack_hole=0, trace=1, uaccess=1, vmap=0 +#else .macro svc_entry, stack_hole=0, trace=1, uaccess=1 +#endif UNWIND(.fnstart ) UNWIND(.save {r0 - pc} ) +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + /* keep using stack of abt mode */ + str sp, [r0, #TI_VMAP_BACK_SP] + sub sp, r0, #(SVC_REGS_SIZE + \stack_hole - 4) + .else sub sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4) + .endif +#else /* !CONFIG_AMLOGIC_VMAP */ + sub sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4) +#endif /* CONFIG_AMLOGIC_VMAP */ #ifdef CONFIG_THUMB2_KERNEL SPFIX( str r0, [sp] ) @ temporarily saved SPFIX( mov r0, sp ) @@ -167,7 +190,15 @@ ENDPROC(__und_invalid) ldmia r0, {r3 - r5} add r7, sp, #S_SP - 4 @ here for interlock avoidance mov r6, #-1 @ "" "" "" "" +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + ldr r2, [sp, #(TI_VMAP_BACK_SP + SVC_REGS_SIZE - 4)] + .else add r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4) + .endif +#else + add r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4) +#endif SPFIX( addeq r2, r2, #4 ) str r3, [sp, #-4]! @ save the "real" r0 copied @ from the exception stack @@ -185,7 +216,44 @@ ENDPROC(__und_invalid) @ stmia r7, {r2 - r6} +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + /* + * get fault task thread info + */ + ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] + mrc p15, 0, r1, c6, c0, 0 @ get FAR + bl pmd_check + mov tsk, r0 + mov tsk, tsk, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT + mov tsk, tsk, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT + add tsk, tsk, #TI_THREAD_SIZE + sub tsk, tsk, #TI_THREAD_INFO_SIZE + + /* + * copy some important member of thread_info from current + * task to vmap stack + */ + ldr r0, [tsk, #TI_FLAGS] + ldr r1, [tsk, #TI_PREEMPT] + str r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_FLAGS)] + str r1, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_PREEMPT)] + + ldr r0, [tsk, #TI_ADDR_LIMIT] + ldr r1, [tsk, #TI_TASK] + str r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_ADDR_LIMIT)] + str r1, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_TASK)] + + ldr r0, [tsk, #TI_CPU] + ldr r1, [tsk, #TI_CPU_DOMAIN] + str r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_CPU)] + str r1, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_CPU_DOMAIN)] + .else get_thread_info tsk + .endif +#else + get_thread_info tsk +#endif ldr r0, [tsk, #TI_ADDR_LIMIT] mov r1, #TASK_SIZE str r1, [tsk, #TI_ADDR_LIMIT] @@ -205,7 +273,28 @@ ENDPROC(__und_invalid) .align 5 __dabt_svc: +#ifdef CONFIG_AMLOGIC_VMAP + svc_entry uaccess=0, vmap=1 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mov r2, sp + uaccess_disable ip @ disable userspace access + bl handle_vmap_fault + cmp r0, #0 + bne .L__dabt_svc_next + /* handled by vmap fault handler */ + svc_exit r5, vmap=1 @ return from exception +.L__dabt_svc_next: + /* re-build context for normal abort handler */ + ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] + sub r0, #SVC_REGS_SIZE + mov r1, sp + mov r2, #SVC_REGS_SIZE + bl memcpy /* copy back sp */ + mov sp, r0 +#else svc_entry uaccess=0 +#endif mov r2, sp dabt_helper THUMB( ldr r5, [sp, #S_PSR] ) @ potentially updated CPSR diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index fa7c6e5c17e7..0b692a3da507 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -197,7 +197,11 @@ .endm +#ifdef CONFIG_AMLOGIC_VMAP + .macro svc_exit, rpsr, irq = 0, vmap = 0 +#else .macro svc_exit, rpsr, irq = 0 +#endif /* CONFIG_AMLOGIC_VMAP */ .if \irq != 0 @ IRQs already off #ifdef CONFIG_TRACE_IRQFLAGS @@ -224,7 +228,16 @@ msr spsr_cxsf, \rpsr #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) @ We must avoid clrex due to Cortex-A15 erratum #830321 +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] + sub r0, r0, #4 @ uninhabited address + .else sub r0, sp, #4 @ uninhabited address + .endif +#else + sub r0, sp, #4 @ uninhabited address +#endif /* CONFIG_AMLOGIC_VMAP */ strex r1, r2, [r0] @ clear the exclusive monitor #endif ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 7e662bdd5cb3..d37d58602d77 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -119,7 +119,11 @@ __mmap_switched_data: #else .long 0 @ r7 #endif +#ifdef CONFIG_AMLOGIC_VMAP + .long init_thread_union + TI_THREAD_START_SP @ sp +#else .long init_thread_union + THREAD_START_SP @ sp +#endif .size __mmap_switched_data, . - __mmap_switched_data __FINIT diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6d1b6074dd4d..dfcb653f46a6 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -62,6 +62,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_VMAP +#include +#endif #ifdef CONFIG_AMLOGIC_CPU_INFO #include #endif @@ -520,6 +523,17 @@ static void __init elf_hwcap_fixup(void) elf_hwcap &= ~HWCAP_SWP; } +#ifdef CONFIG_AMLOGIC_VMAP +static void __init fixup_init_thread_union(void) +{ + void *p; + + p = (void *)((unsigned long)&init_thread_union + THREAD_INFO_OFFSET); + memcpy(p, &init_thread_union, THREAD_INFO_SIZE); + memset(&init_thread_union, 0, THREAD_INFO_SIZE); +} +#endif + /* * cpu_init - initialise one CPU. * @@ -583,6 +597,9 @@ void notrace cpu_init(void) "I" (offsetof(struct stack, fiq[0])), PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); +#ifdef CONFIG_AMLOGIC_VMAP + __setup_vmap_stack(cpu); +#endif #endif } @@ -605,6 +622,9 @@ void __init smp_setup_processor_id(void) */ set_my_cpu_offset(0); +#ifdef CONFIG_AMLOGIC_VMAP + fixup_init_thread_union(); +#endif pr_info("Booting Linux on physical CPU 0x%x\n", mpidr); } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e41f7f67c995..2764133c3e51 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -357,11 +357,20 @@ void arch_cpu_idle_dead(void) * cpu initialisation. There's some initialisation which needs * to be repeated to undo the effects of taking the CPU offline. */ +#ifdef CONFIG_AMLOGIC_VMAP + __asm__("mov sp, %0\n" + " mov fp, #0\n" + " b secondary_start_kernel" + : + : "r" (task_stack_page(current) + THREAD_SIZE - 8 - + THREAD_INFO_SIZE)); +#else __asm__("mov sp, %0\n" " mov fp, #0\n" " b secondary_start_kernel" : : "r" (task_stack_page(current) + THREAD_SIZE - 8)); +#endif } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 134f0d432610..d80cb970d9f8 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -11,6 +11,10 @@ #include #include +#ifdef CONFIG_AMLOGIC_VMAP +#include +#endif + extern int __cpu_suspend(unsigned long, int (*)(unsigned long), u32 cpuid); extern void cpu_resume_mmu(void); @@ -49,6 +53,27 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) #define idmap_pgd NULL #endif +#ifdef CONFIG_AMLOGIC_VMAP +void copy_pgd(void) +{ + unsigned long index; + pgd_t *pgd_c = NULL, *pgd_k, *pgd_i; + unsigned long size; + + /* + * sync pgd of current task and idmap_pgd from init mm + */ + index = pgd_index(TASK_SIZE); + pgd_c = cpu_get_pgd() + index; + pgd_i = idmap_pgd + index; + pgd_k = init_mm.pgd + index; + size = (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t); + pr_debug("pgd:%p, pgd_k:%p, pdg_i:%p\n", + pgd_c, pgd_k, pgd_i); + memcpy(pgd_c, pgd_k, size); + memcpy(pgd_i, pgd_k, size); +} +#endif /* * This is called by __cpu_suspend() to save the state, and do whatever * flushing is required to ensure that when the CPU goes to sleep we have @@ -58,7 +83,21 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) { u32 *ctx = ptr; +#ifdef CONFIG_AMLOGIC_VMAP + if (likely(is_vmap_addr((unsigned long)ptr))) { + struct page *page = vmalloc_to_page(ptr); + unsigned long offset; + + offset = (unsigned long)ptr & (PAGE_SIZE - 1); + *save_ptr = (page_to_phys(page) + offset); + pr_debug("%s, ptr:%p, page:%lx, save_ptr:%x\n", + __func__, ptr, page_to_pfn(page), *save_ptr); + copy_pgd(); + } else + *save_ptr = virt_to_phys(ptr); +#else *save_ptr = virt_to_phys(ptr); +#endif /* This must correspond to the LDM in cpu_resume() assembly */ *ptr++ = virt_to_phys(idmap_pgd); diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 314cfb232a63..6faf21c723cf 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_VMAP +#include +#endif #include #include @@ -468,6 +471,20 @@ int unwind_frame(struct stackframe *frame) return URC_OK; } +#ifdef CONFIG_AMLOGIC_VMAP +static void dump_backtrace_entry_fp(unsigned long where, unsigned long fp, + unsigned long sp) +{ + signed long fp_size = 0; + + fp_size = fp - sp + 4; + if (fp_size < 0 || !fp) + fp_size = 0; + pr_info("[%08lx+%4ld][<%08lx>] %pS\n", + fp, fp_size, where, (void *)where); +} +#endif + void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; @@ -504,9 +521,33 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) unsigned long where = frame.pc; urc = unwind_frame(&frame); + #ifdef CONFIG_AMLOGIC_VMAP + if (urc < 0) { + int keep = 0; + + /* continue search for irq stack */ + if (on_irq_stack(frame.sp, raw_smp_processor_id())) { + unsigned long *prev_fp; + + prev_fp = (unsigned long *)(frame.fp - 12); + if (frame.fp >= TASK_SIZE) { + keep = 1; + frame.fp = prev_fp[0]; + frame.sp = prev_fp[1]; + frame.lr = prev_fp[2]; + frame.pc = prev_fp[3]; + } + } + if (!keep) + break; + } + where = frame.lr; + dump_backtrace_entry_fp(where, frame.fp, frame.sp); + #else if (urc < 0) break; dump_backtrace_entry(where, frame.pc, frame.sp - 4); + #endif } } diff --git a/drivers/amlogic/memory_ext/Kconfig b/drivers/amlogic/memory_ext/Kconfig index fc411738cb5a..e5a1f2d250c6 100644 --- a/drivers/amlogic/memory_ext/Kconfig +++ b/drivers/amlogic/memory_ext/Kconfig @@ -43,7 +43,6 @@ config AMLOGIC_VMAP bool "Amlogic kernel stack" depends on AMLOGIC_MEMORY_EXTEND depends on !KASAN - depends on 64BIT default y help This config is used to enable amlogic kernel stack diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index 511cfc73616a..ea3dacb839ba 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -50,8 +50,21 @@ static unsigned char vmap_shrink_enable; static atomic_t vmap_stack_size; static struct aml_vmap *avmap; +#ifdef CONFIG_ARM64 DEFINE_PER_CPU(unsigned long [THREAD_SIZE/sizeof(long)], vmap_stack) __aligned(16); +#else +static unsigned long irq_stack1[(THREAD_SIZE/sizeof(long))] + __aligned(THREAD_SIZE); +static void *irq_stack[NR_CPUS] = { + irq_stack1, /* only assign 1st irq stack ,other need alloc */ +}; +static unsigned long vmap_stack1[(THREAD_SIZE/sizeof(long))] + __aligned(THREAD_SIZE); +static void *vmap_stack[NR_CPUS] = { + vmap_stack1, /* only assign 1st vmap stack ,other need alloc */ +}; +#endif void update_vmap_stack(int diff) { @@ -65,7 +78,146 @@ int get_vmap_stack_size(void) } EXPORT_SYMBOL(get_vmap_stack_size); -static int is_vmap_addr(unsigned long addr) +#ifdef CONFIG_ARM64 +bool on_vmap_stack(unsigned long sp, int cpu) +{ + /* variable names the same as kernel/stacktrace.c */ + unsigned long low = (unsigned long)per_cpu(vmap_stack, cpu); + unsigned long high = low + THREAD_START_SP; + + return (low <= sp && sp <= high); +} +#endif + +#ifdef CONFIG_ARM +void notrace __setup_vmap_stack(unsigned long cpu) +{ + void *stack; + +#ifdef CONFIG_THUMB2_KERNEL +#define TAG "r" +#else +#define TAG "I" +#endif + stack = vmap_stack[cpu]; + if (!stack) { + stack = kmalloc(THREAD_SIZE, GFP_ATOMIC | __GFP_ZERO); + WARN_ON(!stack); + vmap_stack[cpu] = stack; + irq_stack[cpu] = kmalloc(THREAD_SIZE, GFP_ATOMIC | __GFP_ZERO); + WARN_ON(!irq_stack[cpu]); + } + + pr_info("cpu %ld, vmap stack:[%lx-%lx]\n", + cpu, (unsigned long)stack, + (unsigned long)stack + THREAD_START_SP); + pr_info("cpu %ld, irq stack:[%lx-%lx]\n", + cpu, (unsigned long)irq_stack[cpu], + (unsigned long)irq_stack[cpu] + THREAD_START_SP); + stack += THREAD_SIZE; + stack -= sizeof(struct thread_info); + /* + * reserve 24 byte for r0, lr, spsr, sp_svc and 8 bytes gap + */ + stack -= (24); + asm volatile ( + "msr cpsr_c, %1 \n" + "mov sp, %0 \n" + "msr cpsr_c, %2 \n" + : + : "r" (stack), + TAG(PSR_F_BIT | PSR_I_BIT | ABT_MODE), + TAG(PSR_F_BIT | PSR_I_BIT | SVC_MODE) + : "memory", "cc" + ); +} + +int on_irq_stack(unsigned long sp, int cpu) +{ + unsigned long sp_irq; + + sp_irq = (unsigned long)irq_stack[cpu]; + if ((sp & ~(THREAD_SIZE - 1)) == (sp_irq & ~(THREAD_SIZE - 1))) + return 1; + return 0; +} + +unsigned long notrace irq_stack_entry(unsigned long sp_irq) +{ + int cpu = raw_smp_processor_id(); + + if (!on_irq_stack(sp_irq, cpu)) { + unsigned long sp = (unsigned long)irq_stack[cpu]; + void *src, *dst; + + /* + * copy some data to irq stack + */ + src = current_thread_info(); + dst = (void *)(sp + THREAD_INFO_OFFSET); + memcpy(dst, src, offsetof(struct thread_info, cpu_context)); + sp_irq = (unsigned long)dst - 8; + } + return sp_irq; +} + +unsigned long notrace pmd_check(unsigned long addr, unsigned long far) +{ + unsigned int index; + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + if (addr < TASK_SIZE) + return addr; + + index = pgd_index(addr); + + pgd = cpu_get_pgd() + index; + pgd_k = init_mm.pgd + index; + + if (pgd_none(*pgd_k)) + goto bad_area; + if (!pgd_present(*pgd)) + set_pgd(pgd, *pgd_k); + + pud = pud_offset(pgd, addr); + pud_k = pud_offset(pgd_k, addr); + + if (pud_none(*pud_k)) + goto bad_area; + if (!pud_present(*pud)) + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, addr); + pmd_k = pmd_offset(pud_k, addr); + +#ifdef CONFIG_ARM_LPAE + /* + * Only one hardware entry per PMD with LPAE. + */ + index = 0; +#else + /* + * On ARM one Linux PGD entry contains two hardware entries (see page + * tables layout in pgtable.h). We normally guarantee that we always + * fill both L1 entries. But create_mapping() doesn't follow the rule. + * It can create inidividual L1 entries, so here we have to call + * pmd_none() check for the entry really corresponded to address, not + * for the first of pair. + */ + index = (addr >> SECTION_SHIFT) & 1; +#endif + if (pmd_none(pmd_k[index])) + goto bad_area; + + copy_pmd(pmd, pmd_k); +bad_area: + return addr; +} +#endif + +int is_vmap_addr(unsigned long addr) { unsigned long start, end; @@ -96,6 +248,50 @@ static struct page *get_vmap_cached_page(int *remain) return page; } +static struct page *check_pte_exist(unsigned long addr) +{ + struct mm_struct *mm; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + mm = &init_mm; + + pgd = pgd_offset(mm, addr); + + if (pgd_none(*pgd)) + return NULL; + + if (pgd_bad(*pgd)) + return NULL; + + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) + return NULL; + + if (pud_bad(*pud)) + return NULL; + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) + return NULL; + + if (pmd_bad(*pmd)) + return NULL; + + pte = pte_offset_kernel(pmd, addr); + if (pte_none(*pte)) + return NULL; +#ifdef CONFIG_ARM64 + return pte_page(*pte); +#elif defined(CONFIG_ARM) + return pte_page(pte_val(*pte)); +#else + return NULL; /* not supported */ +#endif +} + static int vmap_mmu_set(struct page *page, unsigned long addr, int set) { pgd_t *pgd = NULL; @@ -121,16 +317,22 @@ static int vmap_mmu_set(struct page *page, unsigned long addr, int set) goto nomem; } - pte = pte_offset_map(pmd, addr); + pte = pte_offset_kernel(pmd, addr); if (set) set_pte_at(&init_mm, addr, pte, mk_pte(page, PAGE_KERNEL)); else pte_clear(&init_mm, addr, pte); - pte_unmap(pte); flush_tlb_kernel_range(addr, addr + PAGE_SIZE); +#ifdef CONFIG_ARM64 D("add:%lx, pgd:%p %llx, pmd:%p %llx, pte:%p %llx\n", addr, pgd, pgd_val(*pgd), pmd, pmd_val(*pmd), pte, pte_val(*pte)); +#elif defined(CONFIG_ARM) + D("add:%lx, pgd:%p %x, pmd:%p %x, pte:%p %x\n", + addr, pgd, (unsigned int)pgd_val(*pgd), + pmd, (unsigned int)pmd_val(*pmd), + pte, pte_val(*pte)); +#endif return 0; nomem: E("allocation page talbe failed, G:%p, U:%p, M:%p, T:%p", @@ -140,10 +342,16 @@ nomem: static int stack_floor_page(unsigned long addr) { + unsigned long pos; + + pos = addr & (THREAD_SIZE - 1); /* * stack address must align to THREAD_SIZE */ - return ((addr & (THREAD_SIZE - 1)) < PAGE_SIZE); + if (THREAD_SIZE_ORDER > 1) + return pos < PAGE_SIZE; + else + return pos < (PAGE_SIZE / 4); } static int check_addr_up_flow(unsigned long addr) @@ -153,17 +361,17 @@ static int check_addr_up_flow(unsigned long addr) * rage(aligned to THREAD_SIZE) but next page of this * addr is not mapped */ - if (stack_floor_page(addr) && - !vmalloc_to_page((const void *)(addr + PAGE_SIZE))) + if (stack_floor_page(addr) && !check_pte_exist(addr + PAGE_SIZE)) return 1; return 0; } -#if DEBUG -static void dump_backtrace_entry(unsigned long ip, unsigned long fp) +static void dump_backtrace_entry(unsigned long ip, unsigned long fp, + unsigned long sp) { unsigned long fp_size = 0; +#ifdef CONFIG_ARM64 if (fp >= VMALLOC_START) { fp_size = *((unsigned long *)fp) - fp; /* fp cross IRQ or vmap stack */ @@ -172,29 +380,94 @@ static void dump_backtrace_entry(unsigned long ip, unsigned long fp) } pr_info("[%016lx+%4ld][<%p>] %pS\n", fp, fp_size, (void *) ip, (void *) ip); +#elif defined(CONFIG_ARM) + if (fp >= TASK_SIZE) { + fp_size = fp - sp + 4; + /* fp cross IRQ or vmap stack */ + if (fp_size >= THREAD_SIZE) + fp_size = 0; + } + pr_info("[%08lx+%4ld][<%p>] %pS\n", + fp, fp_size, (void *) ip, (void *) ip); +#endif } -static void show_fault_stack(unsigned long addr, struct pt_regs *regs) +static noinline void show_fault_stack(unsigned long addr, struct pt_regs *regs) { struct stackframe frame; +#ifdef CONFIG_ARM64 frame.fp = regs->regs[29]; frame.sp = addr; frame.pc = (unsigned long)regs->regs[30]; +#elif defined(CONFIG_ARM) + frame.fp = regs->ARM_fp; + frame.sp = regs->ARM_sp; + frame.pc = (unsigned long)regs->uregs[15]; +#endif - pr_info("Call trace:\n"); + pr_info("Addr:%lx, Call trace:\n", addr); +#ifdef CONFIG_ARM64 pr_info("[%016lx+%4ld][<%p>] %pS\n", addr, frame.fp - addr, (void *)regs->pc, (void *) regs->pc); +#elif defined(CONFIG_ARM) + pr_info("[%08lx+%4ld][<%p>] %pS\n", + addr, frame.fp - addr, (void *)regs->uregs[15], + (void *) regs->uregs[15]); +#endif while (1) { int ret; - dump_backtrace_entry(frame.pc, frame.fp); + dump_backtrace_entry(frame.pc, frame.fp, frame.sp); + #ifdef CONFIG_ARM64 ret = unwind_frame(current, &frame); + #elif defined(CONFIG_ARM) + ret = unwind_frame(&frame); + #endif if (ret < 0) break; } } + +static void check_sp_fault_again(struct pt_regs *regs) +{ + unsigned long sp = 0, addr; + struct page *page; + int cache; + +#ifdef CONFIG_ARM + sp = regs->ARM_sp; +#elif defined(CONFIG_ARM64) + sp = regs->sp; #endif + addr = sp - sizeof(*regs); + + if (sp && ((addr & PAGE_MASK) != (sp & PAGE_MASK))) { + /* + * will fault when we copy back context, so handle + * it first + */ + E("fault again, sp:%lx, addr:%lx\n", sp, addr); + page = get_vmap_cached_page(&cache); + WARN_ON(!page); + vmap_mmu_set(page, addr, 1); + update_vmap_stack(1); + if ((THREAD_SIZE_ORDER > 1) && stack_floor_page(addr)) { + E("task:%d %s, stack near overflow, addr:%lx\n", + current->pid, current->comm, addr); + show_fault_stack(addr, regs); + } + + /* cache is not enough */ + if (cache <= (VMAP_CACHE_PAGE / 2)) + mod_delayed_work(system_highpri_wq, &avmap->mwork, 0); + + D("map page:%5lx for addr:%lx\n", page_to_pfn(page), addr); + #if DEBUG + show_fault_stack(addr, regs); + #endif + } +} /* * IRQ should *NEVER* been opened in this handler @@ -205,28 +478,54 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr, struct page *page; int cache = 0; - if (!is_vmap_addr(addr)) + if (!is_vmap_addr(addr)) { + check_sp_fault_again(regs); return -EINVAL; + } D("addr:%lx, esr:%x, task:%5d %s\n", addr, esr, current->pid, current->comm); +#ifdef CONFIG_ARM64 D("pc:%pf, %llx, lr:%pf, %llx, sp:%llx, %lx\n", (void *)regs->pc, regs->pc, (void *)regs->regs[30], regs->regs[30], regs->sp, current_stack_pointer); +#elif defined(CONFIG_ARM) + D("pc:%pf, %lx, lr:%pf, %lx, sp:%lx, %lx\n", + (void *)regs->uregs[15], regs->uregs[15], + (void *)regs->uregs[14], regs->uregs[14], regs->uregs[13], + current_stack_pointer); +#endif if (check_addr_up_flow(addr)) { E("address %lx out of range\n", addr); + #ifdef CONFIG_ARM64 E("PC is:%llx, %pf, LR is:%llx %pf\n", regs->pc, (void *)regs->pc, regs->regs[30], (void *)regs->regs[30]); + #elif defined(CONFIG_ARM) + E("PC is:%lx, %pf, LR is:%lx %pf\n", + regs->uregs[15], (void *)regs->uregs[15], + regs->uregs[14], (void *)regs->uregs[14]); + #endif E("task:%d %s, stack:%p, %lx\n", current->pid, current->comm, current->stack, current_stack_pointer); - dump_stack(); + show_fault_stack(addr, regs); + check_sp_fault_again(regs); return -ERANGE; } +#ifdef CONFIG_ARM + page = check_pte_exist(addr); + if (page) { + D("task:%d %s, page:%lx mapped for addr:%lx\n", + current->pid, current->comm, page_to_pfn(page), addr); + check_sp_fault_again(regs); + return -EINVAL; + } +#endif + /* * allocate a new page for vmap */ @@ -234,10 +533,10 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr, WARN_ON(!page); vmap_mmu_set(page, addr, 1); update_vmap_stack(1); - if ((THREAD_SIZE_ORDER > 1) && stack_floor_page(addr)) { + if ((THREAD_SIZE_ORDER > 1) && stack_floor_page(addr)) { E("task:%d %s, stack near overflow, addr:%lx\n", current->pid, current->comm, addr); - dump_stack(); + show_fault_stack(addr, regs); } /* cache is not enough */ @@ -248,7 +547,6 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr, #if DEBUG show_fault_stack(addr, regs); #endif - return 0; } EXPORT_SYMBOL(handle_vmap_fault); @@ -344,6 +642,17 @@ void aml_account_task_stack(struct task_struct *tsk, int account) unsigned long stack = (unsigned long)task_stack_page(tsk); struct page *first_page; + if (unlikely(!is_vmap_addr(stack))) { + /* stack get from kmalloc */ + first_page = virt_to_page((void *)stack); + mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, + THREAD_SIZE / 1024 * account); + + memcg_kmem_update_page_stat(first_page, MEMCG_KERNEL_STACK_KB, + account * (THREAD_SIZE / 1024)); + update_vmap_stack(account * (THREAD_SIZE / PAGE_SIZE)); + return; + } stack += STACK_TOP_PAGE_OFF; first_page = vmalloc_to_page((void *)stack); mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, @@ -379,13 +688,18 @@ void *aml_stack_alloc(int node, struct task_struct *tsk) avmap->start_bit = bitmap_no + 1; /* next idle address space */ if (bitmap_no >= MAX_TASKS) { spin_unlock_irqrestore(&avmap->vmap_lock, flags); - E("BITMAP FULL!!!\n"); - return NULL; + /* + * if vmap address space is full, we still need to try + * to get stack from kmalloc + */ + addr = (unsigned long)kmalloc(THREAD_SIZE, GFP_KERNEL); + E("BITMAP FULL, kmalloc task stack:%lx\n", addr); + return (void *)addr; } bitmap_set(avmap->bitmap, bitmap_no, 1); spin_unlock_irqrestore(&avmap->vmap_lock, flags); - page = alloc_page(THREADINFO_GFP | __GFP_ZERO); + page = alloc_page(THREADINFO_GFP | __GFP_ZERO | __GFP_HIGHMEM); if (!page) { spin_lock_irqsave(&avmap->vmap_lock, flags); bitmap_clear(avmap->bitmap, bitmap_no, 1); @@ -400,6 +714,7 @@ void *aml_stack_alloc(int node, struct task_struct *tsk) map_addr = addr + STACK_TOP_PAGE_OFF; vmap_mmu_set(page, map_addr, 1); update_vmap_stack(1); + D("bit idx:%5ld, start:%5ld, addr:%lx, page:%lx\n", bitmap_no, raw_start, addr, page_to_pfn(page)); @@ -413,6 +728,12 @@ void aml_stack_free(struct task_struct *tsk) struct page *page; unsigned long flags; + if (unlikely(!is_vmap_addr(stack))) { + /* stack get from kmalloc */ + kfree((void *)stack); + return; + } + addr = stack + STACK_TOP_PAGE_OFF; for (; addr >= stack; addr -= PAGE_SIZE) { page = vmalloc_to_page((const void *)addr); @@ -458,7 +779,7 @@ static void page_cache_maintain_work(struct work_struct *work) INIT_LIST_HEAD(&head); for (i = 0; i < VMAP_CACHE_PAGE - cnt; i++) { - page = alloc_page(GFP_KERNEL | __GFP_HIGH); + page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (!page) { E("get page failed, allocated:%d, cnt:%d\n", i, cnt); break; @@ -483,10 +804,9 @@ arch_initcall(start_thread_work); void __init thread_stack_cache_init(void) { int i; - unsigned long addr; struct page *page; - page = alloc_pages(GFP_KERNEL, VMAP_CACHE_PAGE_ORDER); + page = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, VMAP_CACHE_PAGE_ORDER); if (!page) return; @@ -505,8 +825,8 @@ void __init thread_stack_cache_init(void) pr_info("%s, vmap:%p, bitmap:%p, cache page:%lx\n", __func__, avmap, avmap->bitmap, page_to_pfn(page)); avmap->root_vm = __get_vm_area_node(VM_STACK_AREA_SIZE, - VM_STACK_AREA_SIZE, - 0, VMALLOC_START, VMALLOC_END, + VMAP_ALIGN, + 0, VMAP_ADDR_START, VMAP_ADDR_END, NUMA_NO_NODE, GFP_KERNEL, __builtin_return_address(0)); if (!avmap->root_vm) { @@ -530,7 +850,9 @@ void __init thread_stack_cache_init(void) avmap->cached_pages = VMAP_CACHE_PAGE; INIT_DELAYED_WORK(&avmap->mwork, page_cache_maintain_work); +#ifdef CONFIG_ARM64 for_each_possible_cpu(i) { + unsigned long addr; addr = (unsigned long)per_cpu_ptr(vmap_stack, i); pr_info("cpu %d, vmap_stack:[%lx-%lx]\n", i, addr, addr + THREAD_START_SP); @@ -538,5 +860,6 @@ void __init thread_stack_cache_init(void) pr_info("cpu %d, irq_stack: [%lx-%lx]\n", i, addr, addr + THREAD_START_SP); } +#endif register_shrinker(&vmap_shrinker); } diff --git a/fs/namespace.c b/fs/namespace.c index 77b46bf40f09..6224ff52544b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2734,6 +2734,17 @@ static long exact_copy_from_user(void *to, const void __user * from, if (!access_ok(VERIFY_READ, from, n)) return n; +#ifdef CONFIG_AMLOGIC_VMAP + /* addr from kernel space and in vmalloc range, avoid overflow */ + if (is_vmalloc_or_module_addr((void *)from)) { + unsigned long old = n; + + n = strlen(from) + 1; + pr_info("addr:%p is in kernel, size fix %ld->%ld, data:%s\n", + from, old, n, (char *)from); + } +#endif + while (n) { if (__get_user(c, f)) { memset(t, 0, n); diff --git a/include/linux/amlogic/vmap_stack.h b/include/linux/amlogic/vmap_stack.h index 1b4081ed2461..a5e001aca6d9 100644 --- a/include/linux/amlogic/vmap_stack.h +++ b/include/linux/amlogic/vmap_stack.h @@ -20,7 +20,18 @@ #define STACK_SHRINK_THRESHOLD (PAGE_SIZE + 1024) #define STACK_SHRINK_SLEEP (HZ) +#ifdef CONFIG_64BIT #define VM_STACK_AREA_SIZE SZ_512M +#define VMAP_ADDR_START VMALLOC_START +#define VMAP_ADDR_END VMALLOC_END +#define VMAP_ALIGN VM_STACK_AREA_SIZE +#else +/* currently support max 6144 tasks on 32bit */ +#define VM_STACK_AREA_SIZE (SZ_64M - SZ_16M) +#define VMAP_ADDR_START MODULES_VADDR +#define VMAP_ADDR_END MODULES_END +#define VMAP_ALIGN SZ_64M +#endif #define STACK_TOP_PAGE_OFF (THREAD_SIZE - PAGE_SIZE) @@ -34,33 +45,28 @@ #define CACHE_MAINTAIN_DELAY (HZ) struct aml_vmap { + spinlock_t vmap_lock; unsigned int start_bit; int cached_pages; struct vm_struct *root_vm; unsigned long *bitmap; struct list_head list; - spinlock_t vmap_lock; - spinlock_t page_lock; struct delayed_work mwork; + spinlock_t page_lock; }; extern int handle_vmap_fault(unsigned long addr, unsigned int esr, struct pt_regs *regs); -extern DEFINE_PER_CPU(unsigned long [THREAD_SIZE/sizeof(long)], vmap_stack); -static inline bool on_vmap_stack(unsigned long sp, int cpu) -{ - /* variable names the same as kernel/stacktrace.c */ - unsigned long low = (unsigned long)per_cpu(vmap_stack, cpu); - unsigned long high = low + THREAD_START_SP; - - return (low <= sp && sp <= high); -} - +extern bool on_vmap_stack(unsigned long sp, int cpu); extern void __setup_vmap_stack(unsigned long off); extern void update_vmap_stack(int diff); extern int get_vmap_stack_size(void); +extern int is_vmap_addr(unsigned long addr); extern void aml_stack_free(struct task_struct *tsk); extern void *aml_stack_alloc(int node, struct task_struct *tsk); extern void aml_account_task_stack(struct task_struct *tsk, int account); +#ifdef CONFIG_ARM +extern int on_irq_stack(unsigned long sp, int cpu); +#endif #endif /* __VMAP_STACK_H__ */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 4634a6ddef1d..197dfd6b847c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3344,7 +3344,13 @@ static inline unsigned long *end_of_stack(const struct task_struct *task) #elif !defined(__HAVE_THREAD_FUNCTIONS) +#ifdef CONFIG_AMLOGIC_VMAP +#define task_thread_info(task) \ + ((struct thread_info *)(((unsigned long)(task)->stack) + \ + THREAD_INFO_OFFSET)) +#else #define task_thread_info(task) ((struct thread_info *)(task)->stack) +#endif #define task_stack_page(task) ((void *)(task)->stack) static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) @@ -3364,11 +3370,15 @@ static inline void setup_thread_stack(struct task_struct *p, struct task_struct */ static inline unsigned long *end_of_stack(struct task_struct *p) { +#ifdef CONFIG_AMLOGIC_VMAP + return p->stack; +#else /* CONFIG_AMLOGIC_VMAP */ #ifdef CONFIG_STACK_GROWSUP return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; #else return (unsigned long *)(task_thread_info(p) + 1); #endif +#endif /* CONFIG_AMLOGIC_VMAP */ } #endif diff --git a/kernel/fork.c b/kernel/fork.c index 91063407507f..bac18408acf3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -484,21 +484,12 @@ int __weak arch_dup_task_struct(struct task_struct *dst, return 0; } -#ifdef CONFIG_AMLOGIC_VMAP -static bool first_magic __read_mostly; -#endif - void set_task_stack_end_magic(struct task_struct *tsk) { unsigned long *stackend; stackend = end_of_stack(tsk); -#ifdef CONFIG_AMLOGIC_VMAP - if (unlikely(!first_magic)) { - *stackend = STACK_END_MAGIC; /* for overflow detection */ - first_magic = 1; - } -#else +#ifndef CONFIG_AMLOGIC_VMAP *stackend = STACK_END_MAGIC; /* for overflow detection */ #endif } From f8474c5788d782a29180e0693f3f18d1e79bc79a Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Fri, 15 Feb 2019 14:17:36 +0800 Subject: [PATCH 0084/1060] mm: close vmap stack print for armv7 [1/1] PD#SWPL-2681 Problem: If cpu support idle/hotplug, there are many vmap stack prints: [ 74.096973@1] cpu 1, vmap stack:[e8e90000-e8e91de0] [ 74.097084@1] cpu 1, irq stack:[e8e92000-e8e93de0] [ 74.105901@3] cpu 3, vmap stack:[e8ee0000-e8ee1de0] [ 74.105984@3] cpu 3, irq stack:[e8ee2000-e8ee3de0] Solution: Close these debug print Verify: P212 Change-Id: I000df1f0952328af9f359f20341eb0fe88590056 Signed-off-by: Tao Zeng --- drivers/amlogic/memory_ext/vmap_stack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index ea3dacb839ba..94beb263edc3 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -108,10 +108,10 @@ void notrace __setup_vmap_stack(unsigned long cpu) WARN_ON(!irq_stack[cpu]); } - pr_info("cpu %ld, vmap stack:[%lx-%lx]\n", + pr_debug("cpu %ld, vmap stack:[%lx-%lx]\n", cpu, (unsigned long)stack, (unsigned long)stack + THREAD_START_SP); - pr_info("cpu %ld, irq stack:[%lx-%lx]\n", + pr_debug("cpu %ld, irq stack:[%lx-%lx]\n", cpu, (unsigned long)irq_stack[cpu], (unsigned long)irq_stack[cpu] + THREAD_START_SP); stack += THREAD_SIZE; From 5a52d45e68b08b59b5e37b91bdd4fc07c6257203 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Thu, 31 Jan 2019 16:41:15 +0800 Subject: [PATCH 0085/1060] debug: fail to show active cpu stacks [1/1] PD#SWPL-4718 Problem: The task stack address is not saved to irq_stack_ptr-0x08, so when switching from irq stack to task stack, we can not obtain the right task stack address Solution: save task stack address to irq_stack_ptr-0x08 Verify: Locally on Ampere Change-Id: I8ad9a45cee33681cc00de3a0bb264dbd9f1b859f Signed-off-by: Jiamin Ma --- arch/arm64/kernel/entry.S | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a2ccd33d5aee..3530d705ae05 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -359,10 +359,8 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 * Add a dummy stack frame, this non-standard format is fixed up * by unwind_frame() */ -#ifndef CONFIG_AMLOGIC_VMAP /* we need get right stack of el1_preempt */ stp x29, x19, [sp, #-16]! mov x29, sp -#endif /* !CONFIG_AMLOGIC_VMAP */ 9998: .endm From a1aca2c97baa91ff3a715226ebf7dee4f786f841 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Tue, 19 Feb 2019 18:19:27 +0800 Subject: [PATCH 0086/1060] debug: fail to show active cpu stacks [1/1] PD#SWPL-4718 Problem: Will have "PC=0, LR=0" issue when try to show active cpu stacks via sysrq Solution: Save the addr of current interrupted task's context to the interrupt stack first, so that we can easily obtain pt_regs later Verify: Locally on Ampere Change-Id: I1cc5095e0ec356bed90f76cdf9af1b2617ce7834 Signed-off-by: Jiamin Ma --- arch/arm/kernel/entry-armv.S | 4 +++ arch/arm/kernel/unwind.c | 36 ++++++++++++++++--------- drivers/amlogic/memory_ext/vmap_stack.c | 19 ++++++++----- include/linux/amlogic/vmap_stack.h | 4 +++ 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index bd77d9ce82a7..51c5758fdcea 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -47,7 +47,11 @@ #endif #ifdef CONFIG_MULTI_IRQ_HANDLER ldr r1, =handle_arch_irq +#ifdef CONFIG_AMLOGIC_VMAP + mov r0, r8 +#else mov r0, sp +#endif badr lr, 9997f ldr pc, [r1] #else diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 6faf21c723cf..6f7d0e469286 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -46,6 +46,7 @@ #include #ifdef CONFIG_AMLOGIC_VMAP #include +#include #endif #include @@ -524,25 +525,36 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) #ifdef CONFIG_AMLOGIC_VMAP if (urc < 0) { int keep = 0; + int cpu; + unsigned long addr; + struct pt_regs *pt_regs; + cpu = raw_smp_processor_id(); /* continue search for irq stack */ - if (on_irq_stack(frame.sp, raw_smp_processor_id())) { - unsigned long *prev_fp; + if (on_irq_stack(frame.sp, cpu)) { + unsigned long sp_irq; - prev_fp = (unsigned long *)(frame.fp - 12); - if (frame.fp >= TASK_SIZE) { - keep = 1; - frame.fp = prev_fp[0]; - frame.sp = prev_fp[1]; - frame.lr = prev_fp[2]; - frame.pc = prev_fp[3]; - } + keep = 1; + sp_irq = (unsigned long)irq_stack[cpu]; + addr = *((unsigned long *)(sp_irq + + THREAD_INFO_OFFSET - 8 - + sizeof(addr))); + pt_regs = (struct pt_regs *)addr; + frame.fp = pt_regs->ARM_fp; + frame.sp = pt_regs->ARM_sp; + frame.lr = pt_regs->ARM_lr; + frame.pc = pt_regs->ARM_pc; } if (!keep) break; } - where = frame.lr; - dump_backtrace_entry_fp(where, frame.fp, frame.sp); + where = frame.pc; + /* + * The last "where" may be an invalid one, + * rechecking it + */ + if (kernel_text_address(where)) + dump_backtrace_entry_fp(where, frame.fp, frame.sp); #else if (urc < 0) break; diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index 94beb263edc3..664ab24b3251 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -56,7 +56,7 @@ DEFINE_PER_CPU(unsigned long [THREAD_SIZE/sizeof(long)], vmap_stack) #else static unsigned long irq_stack1[(THREAD_SIZE/sizeof(long))] __aligned(THREAD_SIZE); -static void *irq_stack[NR_CPUS] = { +void *irq_stack[NR_CPUS] = { irq_stack1, /* only assign 1st irq stack ,other need alloc */ }; static unsigned long vmap_stack1[(THREAD_SIZE/sizeof(long))] @@ -142,23 +142,29 @@ int on_irq_stack(unsigned long sp, int cpu) return 0; } -unsigned long notrace irq_stack_entry(unsigned long sp_irq) +unsigned long notrace irq_stack_entry(unsigned long sp) { int cpu = raw_smp_processor_id(); - if (!on_irq_stack(sp_irq, cpu)) { - unsigned long sp = (unsigned long)irq_stack[cpu]; + if (!on_irq_stack(sp, cpu)) { + unsigned long sp_irq = (unsigned long)irq_stack[cpu]; void *src, *dst; /* * copy some data to irq stack */ src = current_thread_info(); - dst = (void *)(sp + THREAD_INFO_OFFSET); + dst = (void *)(sp_irq + THREAD_INFO_OFFSET); memcpy(dst, src, offsetof(struct thread_info, cpu_context)); sp_irq = (unsigned long)dst - 8; + /* + * save start addr of the interrupted task's context + */ + sp_irq = sp_irq - sizeof(sp); + *((unsigned long *)sp_irq) = sp; + return sp_irq; } - return sp_irq; + return sp; } unsigned long notrace pmd_check(unsigned long addr, unsigned long far) @@ -403,6 +409,7 @@ static noinline void show_fault_stack(unsigned long addr, struct pt_regs *regs) #elif defined(CONFIG_ARM) frame.fp = regs->ARM_fp; frame.sp = regs->ARM_sp; + frame.lr = regs->ARM_lr; frame.pc = (unsigned long)regs->uregs[15]; #endif diff --git a/include/linux/amlogic/vmap_stack.h b/include/linux/amlogic/vmap_stack.h index a5e001aca6d9..a8aa35ffdd04 100644 --- a/include/linux/amlogic/vmap_stack.h +++ b/include/linux/amlogic/vmap_stack.h @@ -55,6 +55,10 @@ struct aml_vmap { spinlock_t page_lock; }; +#ifndef CONFIG_ARM64 +extern void *irq_stack[NR_CPUS]; +#endif + extern int handle_vmap_fault(unsigned long addr, unsigned int esr, struct pt_regs *regs); From 944505c2ae0ab107bf9663377be36b144a86ca09 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Fri, 20 Jul 2018 16:11:40 -0700 Subject: [PATCH 0087/1060] ANDROID: sdcardfs: Change current->fs under lock PD#SWPL-5666 Problem: STS test fail testPocCVE_2018_9515 Solution: bug: 111641492 from security Verify: U212 Change-Id: I79e9894f94880048edaf0f7cfa2d180f65cbcf3b Reported-by: Jann Horn Signed-off-by: Daniel Rosenberg --- fs/sdcardfs/inode.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 84df23ac0d5f..57bdc686094f 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -95,8 +95,10 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, err = -ENOMEM; goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); if (err) goto out; @@ -110,7 +112,9 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, fixup_lower_ownership(dentry, dentry->d_name.name); out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); free_fs_struct(copied_fs); out_unlock: unlock_dir(lower_parent_dentry); @@ -316,8 +320,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode unlock_dir(lower_parent_dentry); goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); if (err) { @@ -377,7 +383,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } } out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); + free_fs_struct(copied_fs); out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); From f79cd19013cafbc963936572abec8040a19b6fc9 Mon Sep 17 00:00:00 2001 From: "deng.liu" Date: Thu, 14 Mar 2019 19:42:45 +0800 Subject: [PATCH 0088/1060] common: NN API implementation [1/3] PD#SWPL-86 Problem: Android tensorflow lite ,NN API implementation Solution: NN API implementation Verify: Local on galilei Change-Id: I699a53b3fa2fd199cea7ef4db2f439ef49536a9c Signed-off-by: deng.liu --- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 12 ++++++++++++ arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts | 12 ++++++++++++ arch/arm/boot/dts/amlogic/mesong12b.dtsi | 2 +- arch/arm/boot/dts/amlogic/mesong12b_a.dtsi | 2 +- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 9a6d701abf96..88b7280ef6c5 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -147,6 +147,18 @@ size = <0x04000000>; alignment = <0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; gpioleds { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index de5c38234da0..ba7f622976a3 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -147,6 +147,18 @@ size = <0x04000000>; alignment = <0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; gpioleds { diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index af8d789785f3..fe69fd8da2b6 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1130,7 +1130,7 @@ <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; clock-names = "cts_vipnanoq_axi_clk_composite", "cts_vipnanoq_core_clk_composite"; - interrupts = <0 147 1>; + interrupts = <0 147 4>; interrupt-names = "galcore"; reg = <0xff100000 0x800 0xff000000 0x400000>; diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi index 9e6514fa6ccc..3b5feeef2171 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -1139,7 +1139,7 @@ <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; clock-names = "cts_vipnanoq_axi_clk_composite", "cts_vipnanoq_core_clk_composite"; - interrupts = <0 147 1>; + interrupts = <0 147 4>; interrupt-names = "galcore"; reg = <0xff100000 0x800 0xff000000 0x400000>; From 2853271e8f9c0084bd8c2de8b7f59cdedaaad59d Mon Sep 17 00:00:00 2001 From: Rongjun Chen Date: Thu, 29 Nov 2018 18:40:14 +0800 Subject: [PATCH 0089/1060] wifi: change mem size to support multi wifi [2/2] PD#SWPL-2210 Problem: multi wifi not support Solution: add multi wifi support Verify: ampere Change-Id: Iea32268fd081a71a1ade00e56a2dcecd975da849 Signed-off-by: Rongjun Chen --- drivers/amlogic/wifi/dhd_static_buf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/wifi/dhd_static_buf.c b/drivers/amlogic/wifi/dhd_static_buf.c index 27480d43f2d2..5a5ccd3ec2f4 100644 --- a/drivers/amlogic/wifi/dhd_static_buf.c +++ b/drivers/amlogic/wifi/dhd_static_buf.c @@ -73,9 +73,9 @@ enum dhd_prealloc_index { #define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) #define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024) #define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) -#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (898 * 1024) +#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1280 * 1024) #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) -#define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024) +#define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (67 * 1024) #ifdef CONFIG_64BIT #define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2) #else From 898c624453fb009a1e1c2fbc87dbb2018be27b6d Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Mon, 21 Jan 2019 00:19:47 +0800 Subject: [PATCH 0090/1060] vpp: disable vd2 again if the last vframe is MVC [1/1] PD#SWPL-4003 Problem: VD2 keep displaying after keep last frame for mvc streaming Solution: check the last frame type and disable vd2 again Verify: verify by tl1 Change-Id: Ia2b598331e8f65c02974d41c498408bee40a407e Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index fef950f282f7..dc2830b98564 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -998,6 +998,7 @@ static const struct vinfo_s *vinfo; static struct vframe_s *cur_dispbuf; static struct vframe_s *cur_dispbuf2; static bool need_disable_vd2; +static bool last_mvc_status; void update_cur_dispbuf(void *buf) { cur_dispbuf = buf; @@ -3920,7 +3921,11 @@ static void vsync_toggle_frame(struct vframe_s *vf) /* if el is unnecessary, afbc2 need to be closed */ if ((last_el_status == 1) && (vf_with_el == 0)) - need_disable_vd2 = 1; + need_disable_vd2 = true; + + if (((vf->type & VIDTYPE_MVC) == 0) + && last_mvc_status) + need_disable_vd2 = true; last_el_status = vf_with_el; @@ -3959,6 +3964,11 @@ static void vsync_toggle_frame(struct vframe_s *vf) } } cur_dispbuf = vf; + if (cur_dispbuf && (cur_dispbuf->type & VIDTYPE_MVC)) + last_mvc_status = true; + else + last_mvc_status = false; + if (first_picture) { frame_par_ready_to_set = 1; first_frame_toggled = 1; From 842ee1f5083049e149caa4ec199011b3358bd55a Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Thu, 14 Mar 2019 10:55:36 +0800 Subject: [PATCH 0091/1060] cpufreq: set fixpll to 1G when cpufreq init. [1/1] PD#SWPL-5392 Problem: set fixpll to 1G when cpufreq init. Solution: set fixpll to 1G when cpufreq init. Verify: test pass on A311D-W400 Change-Id: I65eb70b86eca5192f8d153ac59a24a03d6018421 Signed-off-by: Hong Guo --- drivers/amlogic/cpufreq/meson-cpufreq.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index 7069c122c743..6341825ba722 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -407,6 +407,14 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) goto free_clk; } + /*setting low_freq_clk_p to 1G,default 24M*/ + ret = clk_set_rate(low_freq_clk_p, mid_rate * 1000); + if (ret) { + pr_err("%s: error in setting low_freq_clk_p rate!\n", + __func__); + return ret; + } + high_freq_clk_p = of_clk_get_by_name(np, HIGH_FREQ_CLK_PARENT); if (IS_ERR(high_freq_clk_p)) { pr_err("%s: Failed to get high parent for cpu: %d,cluster: %d\n", From 3dc9c2b00baf8939a37f816d002a13a79c37f717 Mon Sep 17 00:00:00 2001 From: Luan Yuan Date: Mon, 1 Apr 2019 13:42:57 +0800 Subject: [PATCH 0092/1060] config: replace stack protector config [1/1] PD#SWPL-4617 Problem: CONFIG_CC_STACKPROTECTOR_STRONG will increase stack size for some large functions and may cause stack overflow problems or increase real stack usage after we have enabled VMAP STACK config. But direct remove it from defconfig will cause CTS fail. Solution: using CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC for real stack protect config Verify: p212 Change-Id: Ic7d205459523f6156b1014f139b4da31068165ae Signed-off-by: Luan Yuan --- arch/arm/configs/meson64_a32_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 7b040427d660..f40ccea1e14f 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -30,6 +30,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y From 77ba1b150da46e55505d6203b35b75fe7de21254 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Tue, 26 Feb 2019 10:19:07 +0800 Subject: [PATCH 0093/1060] sdio: set sdio hs mode co_phase [1/1] PD#SWPL-5152 Problem: Setup time in sdio highspeed mode of g12a is inconsistent with the protocol standard. Solution: set co_phase = 2. Verify: u212 Change-Id: Ifc4576ce83c810c2ae5cbd57fe53d12959a9acca Signed-off-by: Nan Li --- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 0f03a6a7c4ad..730b5d8908ea 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -343,7 +343,8 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->core_phase = para->hs2.core_phase; clkc->tx_phase = para->hs2.tx_phase; } else if (timing == MMC_TIMING_SD_HS) { - if (aml_card_type_non_sdio(pdata)) + if (aml_card_type_non_sdio(pdata) + || (host->data->chip_type == MMC_CHIP_G12A)) clkc->core_phase = para->sd_hs.core_phase; if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; From 7867770d8a705db28dd872425daadd967f4917ae Mon Sep 17 00:00:00 2001 From: "he.he" Date: Tue, 19 Feb 2019 14:50:29 +0800 Subject: [PATCH 0094/1060] usb: revB usb EL compliance test [2/1] PD#SWPL-4941 Problem: EL27,28,29,31 failed in the el compliance test. tl1 frameworks test result(USB20CV) failed. Solution: Change the parameters (0x10 and 0x38) of usb phy to solve the el failed problem and modified the dwc_otg_pcd_handle_enum_done_intr function to solve the USB20CV failed problem. Verify: verify on revB Test: Pass Change-Id: I9d7dc6472f95c6bcdf2c031222db4fed25be8a13 Signed-off-by: he.he --- drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h | 1 + .../usb/dwc_otg/310/dwc_otg_pcd_intr.c | 24 ++++++++------- drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c | 29 +++++++++++++------ drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c | 13 +++++++++ drivers/usb/core/message.c | 8 +++-- 5 files changed, 54 insertions(+), 21 deletions(-) diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h index ba54785315d1..38a153f4c8b7 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h @@ -274,6 +274,7 @@ void dwc_otg_iso_buffer_done(dwc_otg_pcd_t *pcd, dwc_otg_pcd_ep_t *ep, void *req_handle); extern void do_test_mode(void *data); +extern int aml_new_usb_get_mode(void); #ifdef CONFIG_AMLOGIC_USB3PHY extern void set_usb_phy_device_tuning(int port, int default_val); #endif diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c index 4b9fb07478b5..3382a6a1260d 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c @@ -1065,18 +1065,21 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *pcd) #ifdef CONFIG_AMLOGIC_USB3PHY if (GET_CORE_IF(pcd)->phy_interface != 1) { - speed = get_device_speed(GET_CORE_IF(pcd)); - if (speed != USB_SPEED_HIGH) { - gintsts.d32 = 0; - gintsts.b.enumdone = 1; - DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> - core_global_regs->gintsts, gintsts.d32); - DWC_DEBUGPL(DBG_PCD, "false speed emun\n"); - return 1; + if (GET_CORE_IF(pcd)->controller_type == USB_OTG) { + speed = get_device_speed(GET_CORE_IF(pcd)); + if ((speed != USB_SPEED_HIGH) && + (aml_new_usb_get_mode() != 1)) { + gintsts.d32 = 0; + gintsts.b.enumdone = 1; + DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> + core_global_regs->gintsts, gintsts.d32); + DWC_DEBUGPL(DBG_PCD, "false speed emun\n"); + return 1; + } } set_usb_phy_device_tuning(1, 0); - } +} #endif if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { @@ -1558,7 +1561,8 @@ static inline void do_get_status(dwc_otg_pcd_t *pcd) } break; } else { - *status = 0x1; /* Self powered */ + *status = 0x0; /* bus powered */ + //*status = 0x1; /* Self powered */ *status |= pcd->remote_wakeup_enable << 1; break; } diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index 787da97d9a7d..e2b55e8d8e07 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -40,7 +40,7 @@ void set_usb_phy_host_tuning(int port, int default_val) if (!g_phy2_v2) return; - if (g_phy2_v2->phy_version == 1) + if (g_phy2_v2->phy_version) return; if (port > g_phy2_v2->portnum) @@ -69,7 +69,7 @@ void set_usb_phy_device_tuning(int port, int default_val) if (!g_phy2_v2) return; - if (g_phy2_v2->phy_version == 1) + if (g_phy2_v2->phy_version) return; if (port > g_phy2_v2->portnum) @@ -91,7 +91,6 @@ void set_usb_phy_device_tuning(int port, int default_val) g_phy2_v2->phy_cfg_state[port] = default_val; } - void set_usb_pll(struct amlogic_usb_v2 *phy, void __iomem *reg) { /* TO DO set usb PLL */ @@ -102,11 +101,23 @@ void set_usb_pll(struct amlogic_usb_v2 *phy, void __iomem *reg) writel((0x10000000 | (phy->pll_setting[0])), reg + 0x40); /* PHY Tune */ - writel(phy->pll_setting[3], reg + 0x50); - writel(phy->pll_setting[4], reg + 0x10); - /* Recovery analog status */ - writel(0, reg + 0x38); - writel(phy->pll_setting[5], reg + 0x34); + if (g_phy2_v2) { + if (g_phy2_v2->phy_version == 2) { + /**g12b revB don't need set 0x10 ,0x38 and 0x34**/ + writel(phy->pll_setting[3], reg + 0x50); + writel(0x70000, reg + 0x34); + } else { + writel(phy->pll_setting[3], reg + 0x50); + writel(phy->pll_setting[4], reg + 0x10); + writel(0, reg + 0x38); + writel(phy->pll_setting[5], reg + 0x34); + } + } else { + writel(phy->pll_setting[3], reg + 0x50); + writel(phy->pll_setting[4], reg + 0x10); + writel(0, reg + 0x38); + writel(phy->pll_setting[5], reg + 0x34); + } writel(TUNING_DISCONNECT_THRESHOLD, reg + 0xC); } @@ -246,7 +257,7 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) if (is_meson_g12b_cpu()) { if (!is_meson_rev_a()) - phy_version = 1; + phy_version = 2; } phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c index 3f360b589a79..727cdd845306 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c @@ -124,6 +124,19 @@ void aml_new_usb_v2_init(void) } EXPORT_SYMBOL(aml_new_usb_v2_init); +int aml_new_usb_get_mode(void) +{ + union usb_r5_v2 r5 = {.d32 = 0}; + + r5.d32 = readl(usb_new_aml_regs_v2.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) + return 0; + else + return 1; +} +EXPORT_SYMBOL(aml_new_usb_get_mode); + + static void cr_bus_addr(unsigned int addr) { union phy3_r4 phy_r4 = {.d32 = 0}; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7e235d1b7c07..13c1a5901ef5 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -2224,8 +2224,12 @@ free_interfaces: device_enable_async_suspend(&intf->dev); ret = device_add(&intf->dev); #ifdef CONFIG_AMLOGIC_USB - if (((&intf->dev)->driver) == NULL) - dev_err(&dev->dev, "Unsupported device\n"); + if (((&intf->dev)->driver) == NULL) { + if (intf->cur_altsetting->desc.bInterfaceClass == 0x09) + dev_err(&dev->dev, "Unsupported the hub\n"); + else + dev_err(&dev->dev, "Unsupported device\n"); + } #endif if (ret != 0) { dev_err(&dev->dev, "device_add(%s) --> %d\n", From 1f4a78dab5e5cd676b39eb1db51f010db50640cd Mon Sep 17 00:00:00 2001 From: long yu Date: Wed, 6 Mar 2019 14:21:48 +0800 Subject: [PATCH 0095/1060] storage: emmc: Compatible with G12B revA and revB [1/1] PD#SWPL-5575 Problem: not Compatible with G12B version a and b Solution: add revA match-data Verify: G12B-W400 RevA and RevB Change-Id: Iee09861f7b162ee0660ea12dab60a238a9ae6be5 Signed-off-by: long yu --- arch/arm/boot/dts/amlogic/mesong12b_a.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 2 +- drivers/amlogic/mmc/aml_sd_emmc.c | 29 ++++++++++++++++++++ include/linux/amlogic/sd.h | 3 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi index 3b5feeef2171..69b03f6bdbd3 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -1406,7 +1406,7 @@ sd_emmc_c: emmc@ffe07000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12b"; + compatible = "amlogic, meson-mmc-g12b-a"; reg = <0xffe07000 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index 7b712f3abbdc..d76692bbb909 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -1406,7 +1406,7 @@ sd_emmc_c: emmc@ffe07000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12b"; + compatible = "amlogic, meson-mmc-g12b-a"; reg = <0x0 0xffe07000 0x0 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index c512a80f2fbc..9541344ba9ad 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3569,6 +3569,31 @@ static struct meson_mmc_data mmc_data_g12a = { .sdmmc.sdr104.tx_phase = 0, }; +static struct meson_mmc_data mmc_data_g12b_a = { + .chip_type = MMC_CHIP_G12B_A, + .port_a_base = 0xffe03000, + .port_b_base = 0xffe05000, + .port_c_base = 0xffe07000, + .pinmux_base = 0xff634400, + .clksrc_base = 0xff63c000, + .ds_pin_poll = 0x3a, + .ds_pin_poll_en = 0x48, + .ds_pin_poll_bit = 13, + .sdmmc.init.core_phase = 3, + .sdmmc.init.tx_phase = 0, + .sdmmc.init.rx_phase = 0, + .sdmmc.calc.core_phase = 0, + .sdmmc.calc.tx_phase = 2, + .sdmmc.hs.core_phase = 1, + .sdmmc.ddr.core_phase = 2, + .sdmmc.ddr.tx_phase = 0, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs2.tx_phase = 0, + .sdmmc.sd_hs.core_phase = 2, + .sdmmc.sdr104.core_phase = 2, + .sdmmc.sdr104.tx_phase = 0, +}; + static struct meson_mmc_data mmc_data_g12b = { .chip_type = MMC_CHIP_G12B, .port_a_base = 0xffe03000, @@ -3665,6 +3690,10 @@ static const struct of_device_id meson_mmc_of_match[] = { .compatible = "amlogic, meson-mmc-tl1", .data = &mmc_data_tl1, }, + { + .compatible = "amlogic, meson-mmc-g12b-a", + .data = &mmc_data_g12b_a, + }, {} }; diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 9fa73a8a99bf..245866dd711c 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -188,9 +188,10 @@ enum mmc_chip_e { MMC_CHIP_GXLX = 0x26, MMC_CHIP_TXHD = 0x27, MMC_CHIP_G12A = 0x28, - MMC_CHIP_G12B = 0x29, + MMC_CHIP_G12B_A = 0x29, MMC_CHIP_GXLX2 = 0x2a, MMC_CHIP_TL1 = 0X2b, + MMC_CHIP_G12B = 0x29b, }; struct mmc_phase { From 828cf3649a98289c7be057702c4b2be38b230243 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Mon, 11 Mar 2019 19:46:30 +0800 Subject: [PATCH 0096/1060] dts: commit dts for SM1 bringup [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: commit dts for SM1 bringup Verify: PxP Change-Id: Id117d7ff130c67feb8ca04657d8a4ad463793fed Signed-off-by: zhiqiang liang Signed-off-by: Jianxiong Pan Signed-off-by: Luan Yuan Conflicts: MAINTAINERS --- MAINTAINERS | 10 +- .../boot/dts/amlogic/mesonsm1-bifrost.dtsi | 128 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2590 +++++++++++++++++ arch/arm/boot/dts/amlogic/sm1_pxp.dts | 729 +++++ .../boot/dts/amlogic/mesongsm1-bifrost.dtsi | 128 + arch/arm64/boot/dts/amlogic/mesongsm1.dtsi | 2590 +++++++++++++++++ arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 729 +++++ scripts/amlogic/mk_dtb_gx.sh | 2 + 8 files changed, 6905 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi create mode 100644 arch/arm/boot/dts/amlogic/mesonsm1.dtsi create mode 100644 arch/arm/boot/dts/amlogic/sm1_pxp.dts create mode 100644 arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/mesongsm1.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/sm1_pxp.dts mode change 100755 => 100644 scripts/amlogic/mk_dtb_gx.sh diff --git a/MAINTAINERS b/MAINTAINERS index 1216efa728e8..6c718b4d4d7a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13800,7 +13800,6 @@ F: arch/arm/boot/dts/amlogic> ANLOGIC AUDIO M: Xing Wang -M: Shuai Li F: arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts F: arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts F: arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -14769,6 +14768,15 @@ F: arch/arm/boot/dts/amlogic/mesong12b.dtsi F: arch/arm64/boot/dts/amlogic/g12b*_a.dts F: arch/arm64/boot/dts/amlogic/mesong12b.dtsi +AMLOGIC SM1 DTS +M: Zhiqiang Liang +F: arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi +F: arch/arm64/boot/dts/amlogic/mesongsm1.dtsi +F: arch/arm64/boot/dts/amlogic/sm1_pxp.dts +F: arch/arm/boot/dts/amlogic/mesongsm1-bifrost.dtsi +F: arch/arm/boot/dts/amlogic/mesongsm1.dtsi +F: arch/arm/boot/dts/amlogic/sm1_pxp.dts + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi new file mode 100644 index 000000000000..5875d72c4bb7 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi @@ -0,0 +1,128 @@ +/* + * arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + + gpu:bifrost { + compatible = "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; + #cooling-cells = <2>; /* min followed by max */ + reg = <0xFFE40000 0x04000>, /*mali APB bus base address*/ + <0xFFD01000 0x01000>, /*reset register*/ + <0xFF800000 0x01000>, /*aobus for gpu pmu domain*/ + <0xFF63c000 0x01000>, /*hiubus for gpu clk cntl*/ + <0xFFD01000 0x01000>; /*reset register*/ + interrupt-parent = <&gic>; + interrupts = <0 160 4>, <0 161 4>, <0 162 4>; + interrupt-names = "GPU", "MMU", "JOB"; + /* ACE-Lite = 0; ACE = 1; No-coherency = 31; */ + /* system-coherency = <31>; */ + + num_of_pp = <2>; + sc_mpp = <1>; /* number of shader cores used most of time. */ + clocks = <&clkc CLKID_GPU_MUX &clkc CLKID_GP0_PLL>; + clock-names = "gpu_mux","gp0_pll"; + + + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs850_cfg + &dvfs850_cfg>; + + dvfs125_cfg:clk125_cfg { + clk_freq = <125000000>; + clk_parent = "fclk_div4"; + clkp_freq = <500000000>; + clk_reg = <0xA03>; + voltage = <1150>; + keep_count = <5>; + threshold = <30 120>; + }; + + dvfs250_cfg:dvfs250_cfg { + clk_freq = <250000000>; + clk_parent = "fclk_div4"; + clkp_freq = <500000000>; + clk_reg = <0xA01>; + voltage = <1150>; + keep_count = <5>; + threshold = <80 170>; + }; + + dvfs285_cfg:dvfs285_cfg { + clk_freq = <285714285>; + clk_parent = "fclk_div7"; + clkp_freq = <285714285>; + clk_reg = <0xE00>; + voltage = <1150>; + keep_count = <5>; + threshold = <100 190>; + }; + + dvfs400_cfg:dvfs400_cfg { + clk_freq = <400000000>; + clk_parent = "fclk_div5"; + clkp_freq = <400000000>; + clk_reg = <0xC00>; + voltage = <1150>; + keep_count = <5>; + threshold = <152 207>; + }; + + dvfs500_cfg:dvfs500_cfg { + clk_freq = <500000000>; + clk_parent = "fclk_div4"; + clkp_freq = <500000000>; + clk_reg = <0xA00>; + voltage = <1150>; + keep_count = <5>; + threshold = <180 220>; + }; + + dvfs666_cfg:dvfs666_cfg { + clk_freq = <666666666>; + clk_parent = "fclk_div3"; + clkp_freq = <666666666>; + clk_reg = <0x800>; + voltage = <1150>; + keep_count = <5>; + threshold = <210 236>; + }; + + dvfs800_cfg:dvfs800_cfg { + clk_freq = <800000000>; + clk_parent = "fclk_div2p5"; + clkp_freq = <800000000>; + clk_reg = <0x600>; + voltage = <1150>; + keep_count = <5>; + threshold = <230 255>; + }; + + dvfs850_cfg:dvfs850_cfg { + clk_freq = <846000000>; + clk_parent = "gp0_pll"; + clkp_freq = <846000000>; + clk_reg = <0x200>; + voltage = <1150>; + keep_count = <5>; + threshold = <230 255>; + }; + }; + +};/* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi new file mode 100644 index 000000000000..745d38015293 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -0,0 +1,2590 @@ +/* + * arch/arm/boot/dts/amlogic/mesonsm1.dtsi + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesonsm1-bifrost.dtsi" + +/ { + cpus:cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x3>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci-0.2"; + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <5000>; + exit-latency-us = <5000>; + min-residency-us = <15000>; + }; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0xffd0f190 0x4 0xffd0f194 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xffc01000 0x1000>, + <0xffc02000 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + meson_suspend:pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + reg = <0xff8000a8 0x4>, + <0xff80023c 0x4>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffe7000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base { + reg = <0xffd00000 0x26000>; + }; + io_apb_base { + reg = <0xffe01000 0x7f000>; + }; + io_aobus_base { + reg = <0xff800000 0xb000>; + }; + io_vapb_base { + reg = <0xff900000 0x50000>; + }; + io_hiu_base { + reg = <0xff63c000 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2015/01/01"; + status = "okay"; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu { + compatible = "amlogic, vpu-g12a"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0xff800014 0x8>, + <0xff800024 0x14>, + <0xff80001c 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0xff6346c0 0x40>, + <0xff6344e8 0x18>, + <0xff634520 0x18>, + <0xff634440 0x4c>, + <0xff634740 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disable"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disable"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f49e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disable"; + reg = <0xffe09080 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disable"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0xffd0f0d0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "okay"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0xffd00000 0x26000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xffd00000 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-g12a-gpio-intc"; + reg = <0xf080 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, gxl_measure"; + reg = <0x18004 0x4 + 0x1800c 0x4>; + ringctrl = <0xff6345fc>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x1b000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x1a000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x19000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1f000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1e000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1d000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1c000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x13000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x15000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0xff800000 0xb000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff800000 0xb000>; + + cpu_version { + reg=<0x220 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,g12a-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x320>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x7000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x2000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x05000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x6000 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0xff634400 0x400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff634400 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0xff63c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff63c000 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,g12a-clkc"; + #clock-cells = <1>; + reg = <0x0 0x320>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xff642000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0xff642000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff642000 0x2000>; + clkaudio: audio_clocks { + compatible = "amlogic, g12a-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, g12a-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "frddr_a", "frddr_b", "frddr_c"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0xff808040 0x44>, /*Multi-format IR controller*/ + <0xff808000 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + led_blink = <1>; + led_blink_frq = <100>; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfc000000 0x400000 + 0xff648000 0x2000 + 0xfc400000 0x200000 + 0xff646000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A + */ + ic_type = <10>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + aocec: aocec { + compatible = "amlogic, aocec-g12a"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "G12A"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + cec_version = <5>;/*5:1.4;6:2.0*/ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400 + 0xFF634400 0x26>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-g12a"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + io_efuse_base{ + reg = <0xff630000 0x2000>; + }; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_CLK81 + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_81", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_reg_base{ + reg = <0xff610000 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: meson-fb { + compatible = "amlogic, meson-g12a"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0xff80014c 0x10>, + <0xff800040 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "okay"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0xffe07000 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + co_phase = <3>; + calc_f = <1>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b1:sd1@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + sd_emmc_b2:sd2@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins", + "sdio_noclr_all_pins", + "sdio_noclr_clk_cmd_pins", + "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_x_clr_pins &sd_all_pins>; + pinctrl-1 = <&sdio_x_clr_pins &sd_clk_cmd_pins>; + pinctrl-2 = <&sdio_x_clr_pins &sd_1bit_pins>; + pinctrl-3 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sdio_x_clr_pins + &sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins + &sd_clr_noall_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sdio_x_en_pins + &sd_clr_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins + &sd_clr_noall_pins &ao_to_sd_uart_pins>; + pinctrl-9 = <&sd_clr_noall_pins + &sdio_x_en_pins &sdio_x_all_pins>; + pinctrl-10 = <&sd_clr_noall_pins + &sdio_x_en_pins &sdio_x_clk_cmd_pins>; + pinctrl-11 = <&sd_clr_all_pins + &sdio_x_en_pins &sdio_x_all_pins>; + pinctrl-12 = <&sd_clr_all_pins + &sdio_x_en_pins &sdio_x_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 5:NON sdio device(means sd/mmc card) + */ + }; + + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 5:NON sdio device(means sd/mmc card) + */ + }; + }; + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0xffe03000 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /* max_req_size = <0x20000>; */ /**128KB*/ + max_req_size = <0x400>; + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + dmode = "pio"; + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0xFFE07800 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + meson_cooldev: meson-cooldev@0 { + status = "disabled"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <2150>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF640000 0x2000>; + }; + audiobus_base { + reg = <0xFF642000 0x2000>; + }; + audiolocker_base { + reg = <0xFF64A000 0x2000>; + }; + eqdrc_base { + reg = <0xFF642800 0x1800>; + }; + reset_base { + reg = <0xFFD01000 0x1000>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0xff630218 0x4>; /*RNG_USR_DATA*/ + mem_size = <0 0x100000>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + cpu_ver_name { + compatible = "amlogic, cpu-major-id-g12a"; + }; +};/* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_clr_all_pins:sd_clr_all_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + mux1 { + groups = "GPIOC_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + sd_clr_noall_pins:sd_clr_noall_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_4", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_x_clk_cmd_pins:sdio_x_clk_cmd_pins { + mux { + groups = "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_all_pins:sdio_x_all_pins { + mux { + groups = "GPIOX_0", + "GPIOX_1", + "GPIOX_2", + "GPIOX_3", + "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_en_pins:sdio_x_en_pins { + mux { + groups = "sdio_dummy"; + function = "sdio"; + bias-pull-up; + output-high; + }; + }; + + sdio_x_clr_pins:sdio_x_clr_pins { + mux { + groups = "GPIOV_0"; + function = "gpio_periphs"; + bias-pull-up; + output-low; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + /*dvb_p_ts1_pins: dvb_p_ts1_pins { + * tsin_b { + * groups = "tsin_b_sop_z", + * "tsin_b_valid_z", + * "tsin_b_clk_z", + * "tsin_b_din0_z", + * "tsin_b_din1", + * "tsin_b_din2", + * "tsin_b_din3", + * "tsin_b_din4", + * "tsin_b_din5", + * "tsin_b_din6", + * "tsin_b_din7"; + * function = "tsin_b"; + * }; + *}; + */ + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc0_pins_c: spicc0_pins_c { + mux { + groups = "spi0_mosi_c", + "spi0_miso_c", + "spi0_ss0_c", + "spi0_clk_c"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + drive-strength = <3>; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&pinctrl_aobus { + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts new file mode 100644 index 000000000000..78cdd87d2b59 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -0,0 +1,729 @@ +/* + * arch/arm/boot/dts/amlogic/sm1_pxp.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <981000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; + }; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_b>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b1 { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_PM_KEEP_POWER", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi b/arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi new file mode 100644 index 000000000000..99fe15160ede --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi @@ -0,0 +1,128 @@ +/* + * arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + + gpu:bifrost { + compatible = "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; + #cooling-cells = <2>; /* min followed by max */ + reg = <0 0xFFE40000 0 0x04000>, /*mali APB bus base address*/ + <0 0xFFD01000 0 0x01000>, /*reset register*/ + <0 0xFF800000 0 0x01000>, /*aobus for gpu pmu domain*/ + <0 0xFF63c000 0 0x01000>, /*hiubus for gpu clk cntl*/ + <0 0xFFD01000 0 0x01000>; /*reset register*/ + interrupt-parent = <&gic>; + interrupts = <0 160 4>, <0 161 4>, <0 162 4>; + interrupt-names = "GPU", "MMU", "JOB"; + /* ACE-Lite = 0; ACE = 1; No-coherency = 31; */ + /* system-coherency = <31>; */ + + num_of_pp = <2>; + sc_mpp = <1>; /* number of shader cores used most of time. */ + clocks = <&clkc CLKID_GPU_MUX &clkc CLKID_GP0_PLL>; + clock-names = "gpu_mux","gp0_pll"; + + + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs850_cfg + &dvfs850_cfg>; + + dvfs125_cfg:clk125_cfg { + clk_freq = <125000000>; + clk_parent = "fclk_div4"; + clkp_freq = <500000000>; + clk_reg = <0xA03>; + voltage = <1150>; + keep_count = <5>; + threshold = <30 120>; + }; + + dvfs250_cfg:dvfs250_cfg { + clk_freq = <250000000>; + clk_parent = "fclk_div4"; + clkp_freq = <500000000>; + clk_reg = <0xA01>; + voltage = <1150>; + keep_count = <5>; + threshold = <80 170>; + }; + + dvfs285_cfg:dvfs285_cfg { + clk_freq = <285714285>; + clk_parent = "fclk_div7"; + clkp_freq = <285714285>; + clk_reg = <0xE00>; + voltage = <1150>; + keep_count = <5>; + threshold = <100 190>; + }; + + dvfs400_cfg:dvfs400_cfg { + clk_freq = <400000000>; + clk_parent = "fclk_div5"; + clkp_freq = <400000000>; + clk_reg = <0xC00>; + voltage = <1150>; + keep_count = <5>; + threshold = <152 207>; + }; + + dvfs500_cfg:dvfs500_cfg { + clk_freq = <500000000>; + clk_parent = "fclk_div4"; + clkp_freq = <500000000>; + clk_reg = <0xA00>; + voltage = <1150>; + keep_count = <5>; + threshold = <180 220>; + }; + + dvfs666_cfg:dvfs666_cfg { + clk_freq = <666666666>; + clk_parent = "fclk_div3"; + clkp_freq = <666666666>; + clk_reg = <0x800>; + voltage = <1150>; + keep_count = <5>; + threshold = <210 236>; + }; + + dvfs800_cfg:dvfs800_cfg { + clk_freq = <800000000>; + clk_parent = "fclk_div2p5"; + clkp_freq = <800000000>; + clk_reg = <0x600>; + voltage = <1150>; + keep_count = <5>; + threshold = <230 255>; + }; + + dvfs850_cfg:dvfs850_cfg { + clk_freq = <846000000>; + clk_parent = "gp0_pll"; + clkp_freq = <846000000>; + clk_reg = <0x200>; + voltage = <1150>; + keep_count = <5>; + threshold = <230 255>; + }; + }; + +};/* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesongsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesongsm1.dtsi new file mode 100644 index 000000000000..e59ce391cbf2 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesongsm1.dtsi @@ -0,0 +1,2590 @@ +/* + * arch/arm64/boot/dts/amlogic/mesonsm1.dtsi + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesongsm1-bifrost.dtsi" + +/ { + cpus:cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci-0.2"; + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <5000>; + exit-latency-us = <5000>; + min-residency-us = <15000>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0x0 0xffd0f190 0x0 0x4 0x0 0xffd0f194 0x0 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,armv8-pmuv3"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + meson_suspend:pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + reg = <0x0 0xff8000a8 0x0 0x4>, + <0x0 0xff80023c 0x0 0x4>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ + <0x0 0xfffe7000 0x0 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base { + reg = <0x0 0xffd00000 0x0 0x26000>; + }; + io_apb_base { + reg = <0x0 0xffe01000 0x0 0x7f000>; + }; + io_aobus_base { + reg = <0x0 0xff800000 0x0 0xb000>; + }; + io_vapb_base { + reg = <0x0 0xff900000 0x0 0x50000>; + }; + io_hiu_base { + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2015/01/01"; + status = "okay"; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu { + compatible = "amlogic, vpu-g12a"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8 + 0x0 0xff64c000 0x0 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0x0 0xff800014 0x0 0x8>, + <0x0 0xff800024 0x0 0x14>, + <0x0 0xff80001c 0x0 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0x0 0xff6346c0 0x0 0x40>, + <0x0 0xff6344e8 0x0 0x18>, + <0x0 0xff634520 0x0 0x18>, + <0x0 0xff634440 0x0 0x4c>, + <0x0 0xff634740 0x0 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disable"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disable"; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x100 + 0x0 0xff636000 0x0 0x2000 + 0x0 0xff63a000 0x0 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f49e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disable"; + reg = <0x0 0xffe09080 0x0 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disable"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0x0 0xffd0f0d0 0x0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "okay"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0x0 0xff809000 0x0 0x48>; + }; + + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "disabled"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "disabled"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x26000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-g12a-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, gxl_measure"; + reg = <0x0 0x18004 0x0 0x4 + 0x0 0x1800c 0x0 0x4>; + ringctrl = <0xff6345fc>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x0 0x13000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x0 0x15000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0xb000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0xb000>; + + cpu_version { + reg=<0x0 0x220 0x0 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,g12a-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x320>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0x6000 0x0 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0x0 0xff634400 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff634400 0x0 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,g12a-clkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x320>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xff642000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0x0 0xff642000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>; + clkaudio: audio_clocks { + compatible = "amlogic, g12a-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, g12a-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "frddr_a", "frddr_b", "frddr_c"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0x0 0xff808040 0x00 0x44>, /*Multi-format IR controller*/ + <0x0 0xff808000 0x00 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + led_blink = <1>; + led_blink_frq = <100>; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd22000 0x0 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfc000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfc400000 0x0 0x200000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A + */ + ic_type = <10>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + aocec: aocec { + compatible = "amlogic, aocec-g12a"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "G12A"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + cec_version = <5>;/*5:1.4;6:2.0*/ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400 + 0x0 0xFF634400 0x0 0x26>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-g12a"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base{ + reg = <0x0 0xffd00000 0x0 0x100000>; + }; + io_dos_base{ + reg = <0x0 0xff620000 0x0 0x10000>; + }; + io_hiubus_base{ + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + io_aobus_base{ + reg = <0x0 0xff800000 0x0 0x10000>; + }; + io_vcbus_base{ + reg = <0x0 0xff900000 0x0 0x40000>; + }; + io_dmc_base{ + reg = <0x0 0xff638000 0x0 0x2000>; + }; + io_efuse_base{ + reg = <0x0 0xff630000 0x0 0x2000>; + }; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_CLK81 + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_81", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_reg_base{ + reg = <0x0 0xff610000 0x0 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: meson-fb { + compatible = "amlogic, meson-g12a"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0xff80014c 0x0 0x10>, + <0x0 0xff800040 0x0 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "okay"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + co_phase = <3>; + calc_f = <1>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b1:sd1@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + sd_emmc_b2:sd2@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins", + "sdio_noclr_all_pins", + "sdio_noclr_clk_cmd_pins", + "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_x_clr_pins &sd_all_pins>; + pinctrl-1 = <&sdio_x_clr_pins &sd_clk_cmd_pins>; + pinctrl-2 = <&sdio_x_clr_pins &sd_1bit_pins>; + pinctrl-3 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sdio_x_clr_pins + &sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins + &sd_clr_noall_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sdio_x_en_pins + &sd_clr_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins + &sd_clr_noall_pins &ao_to_sd_uart_pins>; + pinctrl-9 = <&sd_clr_noall_pins + &sdio_x_en_pins &sdio_x_all_pins>; + pinctrl-10 = <&sd_clr_noall_pins + &sdio_x_en_pins &sdio_x_clk_cmd_pins>; + pinctrl-11 = <&sd_clr_all_pins + &sdio_x_en_pins &sdio_x_all_pins>; + pinctrl-12 = <&sd_clr_all_pins + &sdio_x_en_pins &sdio_x_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 5:NON sdio device(means sd/mmc card) + */ + }; + + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 5:NON sdio device(means sd/mmc card) + */ + }; + }; + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12a"; + reg = <0x0 0xffe03000 0x0 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /* max_req_size = <0x20000>; */ /**128KB*/ + max_req_size = <0x400>; + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + dmode = "pio"; + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + meson_cooldev: meson-cooldev@0 { + status = "disabled"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <2150>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF640000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + audiolocker_base { + reg = <0x0 0xFF64A000 0x0 0x2000>; + }; + eqdrc_base { + reg = <0x0 0xFF642800 0x0 0x1800>; + }; + reset_base { + reg = <0x0 0xFFD01000 0x0 0x1000>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x100 + 0x0 0xff638c00 0x0 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0xff630218 0x0 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0x0 0xff63e000 0x0 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff630218 0x0 0x4>; + quality = /bits/ 16 <1000>; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + cpu_ver_name { + compatible = "amlogic, cpu-major-id-g12a"; + }; +};/* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_clr_all_pins:sd_clr_all_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + mux1 { + groups = "GPIOC_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + sd_clr_noall_pins:sd_clr_noall_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_4", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_x_clk_cmd_pins:sdio_x_clk_cmd_pins { + mux { + groups = "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_all_pins:sdio_x_all_pins { + mux { + groups = "GPIOX_0", + "GPIOX_1", + "GPIOX_2", + "GPIOX_3", + "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_en_pins:sdio_x_en_pins { + mux { + groups = "sdio_dummy"; + function = "sdio"; + bias-pull-up; + output-high; + }; + }; + + sdio_x_clr_pins:sdio_x_clr_pins { + mux { + groups = "GPIOV_0"; + function = "gpio_periphs"; + bias-pull-up; + output-low; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + /*dvb_p_ts1_pins: dvb_p_ts1_pins { + * tsin_b { + * groups = "tsin_b_sop_z", + * "tsin_b_valid_z", + * "tsin_b_clk_z", + * "tsin_b_din0_z", + * "tsin_b_din1", + * "tsin_b_din2", + * "tsin_b_din3", + * "tsin_b_din4", + * "tsin_b_din5", + * "tsin_b_din6", + * "tsin_b_din7"; + * function = "tsin_b"; + * }; + *}; + */ + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc0_pins_c: spicc0_pins_c { + mux { + groups = "spi0_mosi_c", + "spi0_miso_c", + "spi0_ss0_c", + "spi0_clk_c"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + drive-strength = <3>; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&pinctrl_aobus { + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts new file mode 100644 index 000000000000..3b74c6e0c2a1 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -0,0 +1,729 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_pxp.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesongsm1.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <981000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; + }; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_b>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b1 { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_PM_KEEP_POWER", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + +&defendkey { + status = "okay"; +}; + diff --git a/scripts/amlogic/mk_dtb_gx.sh b/scripts/amlogic/mk_dtb_gx.sh old mode 100755 new mode 100644 index 28fb3d515729..1fc3549c688f --- a/scripts/amlogic/mk_dtb_gx.sh +++ b/scripts/amlogic/mk_dtb_gx.sh @@ -36,6 +36,8 @@ make ARCH=arm64 axg_s420_v03.dtb || echo "Compile dtb Fail !!" make ARCH=arm64 g12a_pxp.dtb || echo "Compile dtb Fail!!" +make ARCH=arm64 sm1_pxp.dtb || echo "Compile dtb Fail!!" + make ARCH=arm64 g12a_s905d2_skt.dtb || echo "Compile dtb Fail!!" make ARCH=arm64 g12b_pxp.dtb || echo "Compile dtb Fail!!" From 9d05213fd4562e884ca365b5c73663ccd199488e Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Tue, 12 Mar 2019 15:20:22 +0800 Subject: [PATCH 0097/1060] dts: rename dts for SM1 bringup [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: rename dts for SM1 bringup Verify: PxP Change-Id: I991b6a0fb65cf9a03c6cb75a1ad8823a067e6bdd Signed-off-by: zhiqiang liang Signed-off-by: Jianxiong Pan --- MAINTAINERS | 4 ++-- .../amlogic/{mesongsm1-bifrost.dtsi => mesonsm1-bifrost.dtsi} | 0 arch/arm64/boot/dts/amlogic/{mesongsm1.dtsi => mesonsm1.dtsi} | 2 +- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename arch/arm64/boot/dts/amlogic/{mesongsm1-bifrost.dtsi => mesonsm1-bifrost.dtsi} (100%) rename arch/arm64/boot/dts/amlogic/{mesongsm1.dtsi => mesonsm1.dtsi} (99%) diff --git a/MAINTAINERS b/MAINTAINERS index 6c718b4d4d7a..328b61594fbe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14773,8 +14773,8 @@ M: Zhiqiang Liang F: arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi F: arch/arm64/boot/dts/amlogic/mesongsm1.dtsi F: arch/arm64/boot/dts/amlogic/sm1_pxp.dts -F: arch/arm/boot/dts/amlogic/mesongsm1-bifrost.dtsi -F: arch/arm/boot/dts/amlogic/mesongsm1.dtsi +F: arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi +F: arch/arm/boot/dts/amlogic/mesonsm1.dtsi F: arch/arm/boot/dts/amlogic/sm1_pxp.dts HARDKERNEL S922D odroidn2 diff --git a/arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi similarity index 100% rename from arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi rename to arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi diff --git a/arch/arm64/boot/dts/amlogic/mesongsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi similarity index 99% rename from arch/arm64/boot/dts/amlogic/mesongsm1.dtsi rename to arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index e59ce391cbf2..3d53f8bc07fa 100644 --- a/arch/arm64/boot/dts/amlogic/mesongsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -26,7 +26,7 @@ #include #include #include -#include "mesongsm1-bifrost.dtsi" +#include "mesonsm1-bifrost.dtsi" / { cpus:cpus { diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index 3b74c6e0c2a1..2235dfd91a47 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -17,7 +17,7 @@ /dts-v1/; -#include "mesongsm1.dtsi" +#include "mesonsm1.dtsi" / { model = "Amlogic"; From 42d085b06de778bf4116358c80858b2a4ff4ec35 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Wed, 13 Mar 2019 11:14:11 +0800 Subject: [PATCH 0098/1060] dts: modify dts for SM1 bringup with SMP [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: modify dts for SM1 bringup with smp Verify: PxP Change-Id: Ie83ad7434acfb8c6232a8e373dfc63ef0ba9b87e Signed-off-by: zhiqiang liang --- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 10 +++++----- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 2 +- drivers/amlogic/media/deinterlace/deinterlace.c | 3 ++- scripts/amlogic/mk_dtb_gx.sh | 0 4 files changed, 8 insertions(+), 7 deletions(-) mode change 100644 => 100755 scripts/amlogic/mk_dtb_gx.sh diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 3d53f8bc07fa..91d55eb74570 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -55,7 +55,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -73,7 +73,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -91,7 +91,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x2>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -109,7 +109,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x3>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -732,7 +732,7 @@ fifosize = < 64 >; pinctrl-names = "default"; /*pinctrl-0 = <&ao_uart_pins>;*/ - support-sysrq = <0>; /* 0 not support*/ + support-sysrq = <1>; /* 0 not support*/ }; uart_AO_B: serial@4000 { diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index 2235dfd91a47..f09451563a8b 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -436,7 +436,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 9c12e063b761..0d33bf1a7004 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -7625,13 +7625,14 @@ static int di_probe(struct platform_device *pdev) vf_reg_receiver(&di_vf_recv); vf_provider_init(&di_vf_prov, VFM_NAME, &deinterlace_vf_provider, NULL); active_flag = 1; + sema_init(&di_sema, 1); ret = request_irq(di_devp->pre_irq, &de_irq, IRQF_SHARED, "pre_di", (void *)"pre_di"); if (di_devp->post_wr_support) { ret = request_irq(di_devp->post_irq, &post_irq, IRQF_SHARED, "post_di", (void *)"post_di"); } - sema_init(&di_sema, 1); + //sema_init(&di_sema, 1); di_sema_init_flag = 1; di_hw_init(pulldown_enable, mcpre_en); set_di_flag(); diff --git a/scripts/amlogic/mk_dtb_gx.sh b/scripts/amlogic/mk_dtb_gx.sh old mode 100644 new mode 100755 From 5eeeac52c035126b18621b75eb3c7bc0ce4c11a4 Mon Sep 17 00:00:00 2001 From: Jiyu Yang Date: Wed, 13 Mar 2019 10:30:06 +0800 Subject: [PATCH 0099/1060] dts: use mesong12a-bifrost instead [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: commit dts for SM1 bringup Verify: PxP Change-Id: Ifdbc751e2fa9ecb3d747c114ac820ab60021294d Signed-off-by: Jiyu Yang --- MAINTAINERS | 2 - .../boot/dts/amlogic/mesonsm1-bifrost.dtsi | 128 ------------------ arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- .../boot/dts/amlogic/mesonsm1-bifrost.dtsi | 128 ------------------ arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- 5 files changed, 2 insertions(+), 260 deletions(-) delete mode 100644 arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi delete mode 100644 arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi diff --git a/MAINTAINERS b/MAINTAINERS index 328b61594fbe..ddeb0271391f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14770,10 +14770,8 @@ F: arch/arm64/boot/dts/amlogic/mesong12b.dtsi AMLOGIC SM1 DTS M: Zhiqiang Liang -F: arch/arm64/boot/dts/amlogic/mesongsm1-bifrost.dtsi F: arch/arm64/boot/dts/amlogic/mesongsm1.dtsi F: arch/arm64/boot/dts/amlogic/sm1_pxp.dts -F: arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi F: arch/arm/boot/dts/amlogic/mesonsm1.dtsi F: arch/arm/boot/dts/amlogic/sm1_pxp.dts diff --git a/arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi deleted file mode 100644 index 5875d72c4bb7..000000000000 --- a/arch/arm/boot/dts/amlogic/mesonsm1-bifrost.dtsi +++ /dev/null @@ -1,128 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/ { - - gpu:bifrost { - compatible = "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; - #cooling-cells = <2>; /* min followed by max */ - reg = <0xFFE40000 0x04000>, /*mali APB bus base address*/ - <0xFFD01000 0x01000>, /*reset register*/ - <0xFF800000 0x01000>, /*aobus for gpu pmu domain*/ - <0xFF63c000 0x01000>, /*hiubus for gpu clk cntl*/ - <0xFFD01000 0x01000>; /*reset register*/ - interrupt-parent = <&gic>; - interrupts = <0 160 4>, <0 161 4>, <0 162 4>; - interrupt-names = "GPU", "MMU", "JOB"; - /* ACE-Lite = 0; ACE = 1; No-coherency = 31; */ - /* system-coherency = <31>; */ - - num_of_pp = <2>; - sc_mpp = <1>; /* number of shader cores used most of time. */ - clocks = <&clkc CLKID_GPU_MUX &clkc CLKID_GP0_PLL>; - clock-names = "gpu_mux","gp0_pll"; - - - tbl = <&dvfs285_cfg - &dvfs400_cfg - &dvfs500_cfg - &dvfs666_cfg - &dvfs850_cfg - &dvfs850_cfg>; - - dvfs125_cfg:clk125_cfg { - clk_freq = <125000000>; - clk_parent = "fclk_div4"; - clkp_freq = <500000000>; - clk_reg = <0xA03>; - voltage = <1150>; - keep_count = <5>; - threshold = <30 120>; - }; - - dvfs250_cfg:dvfs250_cfg { - clk_freq = <250000000>; - clk_parent = "fclk_div4"; - clkp_freq = <500000000>; - clk_reg = <0xA01>; - voltage = <1150>; - keep_count = <5>; - threshold = <80 170>; - }; - - dvfs285_cfg:dvfs285_cfg { - clk_freq = <285714285>; - clk_parent = "fclk_div7"; - clkp_freq = <285714285>; - clk_reg = <0xE00>; - voltage = <1150>; - keep_count = <5>; - threshold = <100 190>; - }; - - dvfs400_cfg:dvfs400_cfg { - clk_freq = <400000000>; - clk_parent = "fclk_div5"; - clkp_freq = <400000000>; - clk_reg = <0xC00>; - voltage = <1150>; - keep_count = <5>; - threshold = <152 207>; - }; - - dvfs500_cfg:dvfs500_cfg { - clk_freq = <500000000>; - clk_parent = "fclk_div4"; - clkp_freq = <500000000>; - clk_reg = <0xA00>; - voltage = <1150>; - keep_count = <5>; - threshold = <180 220>; - }; - - dvfs666_cfg:dvfs666_cfg { - clk_freq = <666666666>; - clk_parent = "fclk_div3"; - clkp_freq = <666666666>; - clk_reg = <0x800>; - voltage = <1150>; - keep_count = <5>; - threshold = <210 236>; - }; - - dvfs800_cfg:dvfs800_cfg { - clk_freq = <800000000>; - clk_parent = "fclk_div2p5"; - clkp_freq = <800000000>; - clk_reg = <0x600>; - voltage = <1150>; - keep_count = <5>; - threshold = <230 255>; - }; - - dvfs850_cfg:dvfs850_cfg { - clk_freq = <846000000>; - clk_parent = "gp0_pll"; - clkp_freq = <846000000>; - clk_reg = <0x200>; - voltage = <1150>; - keep_count = <5>; - threshold = <230 255>; - }; - }; - -};/* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 745d38015293..4917771df1da 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -26,7 +26,7 @@ #include #include #include -#include "mesonsm1-bifrost.dtsi" +#include "mesong12a-bifrost.dtsi" / { cpus:cpus { diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi deleted file mode 100644 index 99fe15160ede..000000000000 --- a/arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi +++ /dev/null @@ -1,128 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/mesonsm1-bifrost.dtsi - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/ { - - gpu:bifrost { - compatible = "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; - #cooling-cells = <2>; /* min followed by max */ - reg = <0 0xFFE40000 0 0x04000>, /*mali APB bus base address*/ - <0 0xFFD01000 0 0x01000>, /*reset register*/ - <0 0xFF800000 0 0x01000>, /*aobus for gpu pmu domain*/ - <0 0xFF63c000 0 0x01000>, /*hiubus for gpu clk cntl*/ - <0 0xFFD01000 0 0x01000>; /*reset register*/ - interrupt-parent = <&gic>; - interrupts = <0 160 4>, <0 161 4>, <0 162 4>; - interrupt-names = "GPU", "MMU", "JOB"; - /* ACE-Lite = 0; ACE = 1; No-coherency = 31; */ - /* system-coherency = <31>; */ - - num_of_pp = <2>; - sc_mpp = <1>; /* number of shader cores used most of time. */ - clocks = <&clkc CLKID_GPU_MUX &clkc CLKID_GP0_PLL>; - clock-names = "gpu_mux","gp0_pll"; - - - tbl = <&dvfs285_cfg - &dvfs400_cfg - &dvfs500_cfg - &dvfs666_cfg - &dvfs850_cfg - &dvfs850_cfg>; - - dvfs125_cfg:clk125_cfg { - clk_freq = <125000000>; - clk_parent = "fclk_div4"; - clkp_freq = <500000000>; - clk_reg = <0xA03>; - voltage = <1150>; - keep_count = <5>; - threshold = <30 120>; - }; - - dvfs250_cfg:dvfs250_cfg { - clk_freq = <250000000>; - clk_parent = "fclk_div4"; - clkp_freq = <500000000>; - clk_reg = <0xA01>; - voltage = <1150>; - keep_count = <5>; - threshold = <80 170>; - }; - - dvfs285_cfg:dvfs285_cfg { - clk_freq = <285714285>; - clk_parent = "fclk_div7"; - clkp_freq = <285714285>; - clk_reg = <0xE00>; - voltage = <1150>; - keep_count = <5>; - threshold = <100 190>; - }; - - dvfs400_cfg:dvfs400_cfg { - clk_freq = <400000000>; - clk_parent = "fclk_div5"; - clkp_freq = <400000000>; - clk_reg = <0xC00>; - voltage = <1150>; - keep_count = <5>; - threshold = <152 207>; - }; - - dvfs500_cfg:dvfs500_cfg { - clk_freq = <500000000>; - clk_parent = "fclk_div4"; - clkp_freq = <500000000>; - clk_reg = <0xA00>; - voltage = <1150>; - keep_count = <5>; - threshold = <180 220>; - }; - - dvfs666_cfg:dvfs666_cfg { - clk_freq = <666666666>; - clk_parent = "fclk_div3"; - clkp_freq = <666666666>; - clk_reg = <0x800>; - voltage = <1150>; - keep_count = <5>; - threshold = <210 236>; - }; - - dvfs800_cfg:dvfs800_cfg { - clk_freq = <800000000>; - clk_parent = "fclk_div2p5"; - clkp_freq = <800000000>; - clk_reg = <0x600>; - voltage = <1150>; - keep_count = <5>; - threshold = <230 255>; - }; - - dvfs850_cfg:dvfs850_cfg { - clk_freq = <846000000>; - clk_parent = "gp0_pll"; - clkp_freq = <846000000>; - clk_reg = <0x200>; - voltage = <1150>; - keep_count = <5>; - threshold = <230 255>; - }; - }; - -};/* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 91d55eb74570..2e0b1fdc1ef5 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -26,7 +26,7 @@ #include #include #include -#include "mesonsm1-bifrost.dtsi" +#include "mesong12a-bifrost.dtsi" / { cpus:cpus { From 5e2986774d55f884ff3abf43df7ab56533f89955 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Fri, 15 Mar 2019 15:07:16 +0800 Subject: [PATCH 0100/1060] dts: add the partition info for sm1 bringup [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: add the partition info Verify: PxP Change-Id: I779369d92780f9380cb634a90cabb012df11859d Signed-off-by: zhiqiang liang --- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index f09451563a8b..493771e9062e 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" / { model = "Amlogic"; From c2bb5b174ae8b8761dbb8debaded3f10424b70b9 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Mon, 18 Mar 2019 14:53:06 +0800 Subject: [PATCH 0101/1060] dts: sm1: add sm1_s905d3_ac200 and sm1_s905d3_skt dts. [1/1] PD#SWPL-5865 Problem: add sm1 dts. Solution: copy from g12a_s905d2_u200.dts. Verify: no. Change-Id: Idcd997d2c1a52a247c55ad41b557941314dfcb2c Signed-off-by: Jianxiong Pan --- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 1608 +++++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 1608 +++++++++++++++++ .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 1606 ++++++++++++++++ .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 1606 ++++++++++++++++ 4 files changed, 6428 insertions(+) create mode 100644 arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts create mode 100644 arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts create mode 100644 arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts create mode 100644 arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts new file mode 100644 index 000000000000..185e11233a8c --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -0,0 +1,1608 @@ +/* + * arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesong12a_skt-panel.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0xffe02000 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&tlv320adc3101_32 &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* + * dai link for i2s to hdmix, + * Notice to select a tdm lane not used by hw + */ + /* + * aml-audio-card,dai-link@6 { + * format = "i2s"; + * mclk-fs = <256>; + * //continuous-clock; + * //bitclock-inversion; + * //frame-inversion; + * bitclock-master = <&aml_i2s2hdmi>; + * frame-master = <&aml_i2s2hdmi>; + * suffix-name = "alsaPORT-i2s2hdmi"; + * cpu { + * sound-dai = <&aml_i2s2hdmi>; + * dai-tdm-slot-tx-mask = <1 1>; + * dai-tdm-slot-num = <2>; + * dai-tdm-slot-width = <32>; + * system-clock-frequency = <12288000>; + * }; + * codec { + * sound-dai = <&dummy_codec>; + * }; + * }; + */ + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "disabled"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts new file mode 100644 index 000000000000..125416d03aa2 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -0,0 +1,1608 @@ +/* + * arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesong12a_skt-panel.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0xffe02000 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&tlv320adc3101_32 &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* + * dai link for i2s to hdmix, + * Notice to select a tdm lane not used by hw + */ + /* + * aml-audio-card,dai-link@6 { + * format = "i2s"; + * mclk-fs = <256>; + * //continuous-clock; + * //bitclock-inversion; + * //frame-inversion; + * bitclock-master = <&aml_i2s2hdmi>; + * frame-master = <&aml_i2s2hdmi>; + * suffix-name = "alsaPORT-i2s2hdmi"; + * cpu { + * sound-dai = <&aml_i2s2hdmi>; + * dai-tdm-slot-tx-mask = <1 1>; + * dai-tdm-slot-num = <2>; + * dai-tdm-slot-width = <32>; + * system-clock-frequency = <12288000>; + * }; + * codec { + * sound-dai = <&dummy_codec>; + * }; + * }; + */ + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "disabled"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts new file mode 100644 index 000000000000..a01631db7e3c --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -0,0 +1,1606 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesong12a_skt-panel.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&tlv320adc3101_32 &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* + * dai link for i2s to hdmix, + * Notice to select a tdm lane not used by hw + */ + /* + * aml-audio-card,dai-link@6 { + * format = "i2s"; + * mclk-fs = <256>; + * //continuous-clock; + * //bitclock-inversion; + * //frame-inversion; + * bitclock-master = <&aml_i2s2hdmi>; + * frame-master = <&aml_i2s2hdmi>; + * suffix-name = "alsaPORT-i2s2hdmi"; + * cpu { + * sound-dai = <&aml_i2s2hdmi>; + * dai-tdm-slot-tx-mask = <1 1>; + * dai-tdm-slot-num = <2>; + * dai-tdm-slot-width = <32>; + * system-clock-frequency = <12288000>; + * }; + * codec { + * sound-dai = <&dummy_codec>; + * }; + * }; + */ + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>; + //<&cpu_opp_table1>, + //<&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "disabled"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts new file mode 100644 index 000000000000..c97834312825 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -0,0 +1,1606 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesong12a_skt-panel.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&tlv320adc3101_32 &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* + * dai link for i2s to hdmix, + * Notice to select a tdm lane not used by hw + */ + /* + * aml-audio-card,dai-link@6 { + * format = "i2s"; + * mclk-fs = <256>; + * //continuous-clock; + * //bitclock-inversion; + * //frame-inversion; + * bitclock-master = <&aml_i2s2hdmi>; + * frame-master = <&aml_i2s2hdmi>; + * suffix-name = "alsaPORT-i2s2hdmi"; + * cpu { + * sound-dai = <&aml_i2s2hdmi>; + * dai-tdm-slot-tx-mask = <1 1>; + * dai-tdm-slot-num = <2>; + * dai-tdm-slot-width = <32>; + * system-clock-frequency = <12288000>; + * }; + * codec { + * sound-dai = <&dummy_codec>; + * }; + * }; + */ + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>; + //<&cpu_opp_table1>, + //<&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "disabled"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + From a2f4b8bbec58275397cdd446f4859054e3d05347 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Mon, 18 Mar 2019 21:01:31 +0800 Subject: [PATCH 0102/1060] dts: add the chipid for sm1 bringup [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: add the chipid Verify: PxP Change-Id: I7164a4fff39932f81de1b5c4404f1ad0d878484c Signed-off-by: zhiqiang liang --- include/linux/amlogic/cpu_version.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index 5fce9f051df8..716ee796d8cc 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -34,6 +34,7 @@ #define MESON_CPU_MAJOR_ID_G12A 0x28 #define MESON_CPU_MAJOR_ID_G12B 0x29 +#define MESON_CPU_MAJOR_ID_SM1 0x2B #define MESON_CPU_MAJOR_ID_TL1 0x2E From 13bbcc7c54e16673efcadeb48705dc2c69e24caa Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Mon, 18 Mar 2019 22:50:37 +0800 Subject: [PATCH 0103/1060] dts: modify the dts for skt and ac200 board [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: modify the dts for skt and ac200 board Verify: AC200 Change-Id: I5e5d52329d7a190ad2b4bd967be837b4ae91ea11 Signed-off-by: zhiqiang liang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 ++-- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 4 ++-- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 ++-- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 4917771df1da..3dc204e1ddb9 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1176,7 +1176,7 @@ ge2d { compatible = "amlogic, ge2d-g12a"; dev_name = "ge2d"; - status = "okay"; + status = "disabled"; interrupts = <0 146 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 185e11233a8c..57f6e996d805 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1391,7 +1391,7 @@ }; &dwc3 { - status = "okay"; + status = "disabled"; }; &usb2_phy_v2 { @@ -1408,7 +1408,7 @@ }; &dwc2_a { - status = "okay"; + status = "disabled"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 125416d03aa2..8ea7ee2d280f 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1391,7 +1391,7 @@ }; &dwc3 { - status = "okay"; + status = "disabled"; }; &usb2_phy_v2 { @@ -1408,7 +1408,7 @@ }; &dwc2_a { - status = "okay"; + status = "disabled"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 2e0b1fdc1ef5..45c5633ca5dd 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1176,7 +1176,7 @@ ge2d { compatible = "amlogic, ge2d-g12a"; dev_name = "ge2d"; - status = "okay"; + status = "disabled"; interrupts = <0 146 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index a01631db7e3c..20d086b4d370 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1389,7 +1389,7 @@ }; &dwc3 { - status = "okay"; + status = "disabled"; }; &usb2_phy_v2 { @@ -1406,7 +1406,7 @@ }; &dwc2_a { - status = "okay"; + status = "disabled"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index c97834312825..391e79210b35 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1389,7 +1389,7 @@ }; &dwc3 { - status = "okay"; + status = "disalbed"; }; &usb2_phy_v2 { @@ -1406,7 +1406,7 @@ }; &dwc2_a { - status = "okay"; + status = "disalbed"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; From 313c060f48fcd1684a4e53b3e902995fc7419e99 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Wed, 20 Mar 2019 15:00:40 +0800 Subject: [PATCH 0104/1060] cpu: add the cpuid check interface [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: add the cpuid check interface Verify: AC200 Change-Id: Ifa7dd8fb0b6ec621411652acf6b799e69c4069b7 Signed-off-by: zhiqiang liang --- include/linux/amlogic/cpu_version.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index 716ee796d8cc..c658c74707f9 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -189,6 +189,11 @@ static inline bool is_meson_tl1_cpu(void) return get_cpu_type() == MESON_CPU_MAJOR_ID_TL1; } +static inline bool is_meson_sm1_cpu(void) +{ + return get_cpu_type() == MESON_CPU_MAJOR_ID_SM1; +} + static inline bool cpu_after_eq(unsigned int id) { return get_cpu_type() >= id; From 67af651ca20a4b33d33c20aeaaec7f9d316b4faa Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Fri, 22 Mar 2019 14:04:22 +0800 Subject: [PATCH 0105/1060] dts: arm: disable cpu idle [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: cpu idle has not ready, disable it Verify: AC200 Change-Id: I5dd4bf8d2940587b10b8c85ff64122ce931bfb85 Signed-off-by: Hanjie Lin --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 3dc204e1ddb9..40345e1d5360 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -55,7 +55,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -73,7 +73,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x1>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -91,7 +91,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x2>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -109,7 +109,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x3>; enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0>; +// cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; From 083839506b61f7866c6be7de4abb61c9e45cf9a4 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Fri, 22 Mar 2019 14:48:48 +0800 Subject: [PATCH 0106/1060] dts: add dts-id for sm1 and g12a_u200. [1/1] PD#SWPL-5865 Problem: add dts-id for sm1 and g12a. Solution: sm1_ac200_2g g12a_u200_1g g12a_u200_2g Verify: no test. Change-Id: Id09b2b811529d11b85898e5f3e83f558dc7ba5f6 Signed-off-by: Jianxiong Pan --- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 1 + arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 1 + arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 1 + arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 1 + arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 1 + arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts | 1 + arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 1 + arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 1 + arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 1 + arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 1 + 10 files changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index 352ea71789db..13a598ad6933 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_skt_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index a411b2f739c5..304aadfc63eb 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 05174860d62e..edb6fd926c36 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 57f6e996d805..759471b83c8c 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "sm1_ac200_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 8ea7ee2d280f..1dcc06171499 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "sm1_skt_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index ae4f0904cb88..ff07f1e90624 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_skt_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index 77e0504f3e7f..f3743f85dc1e 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index eff237c73647..19b35d5f8b23 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 20d086b4d370..b58c7a834dd7 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "sm1_ac200_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 391e79210b35..3986d59945ef 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "sm1_skt_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; From df3bdac2967775cce8250911b7ee6308d49ee5f0 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Fri, 22 Mar 2019 20:41:15 +0800 Subject: [PATCH 0107/1060] di: add di for sm1 bringup [1/1] PD#SWPL-5865 Problem: SM1 bring up Solution: add the chipid Verify: sm Change-Id: I9b738efea210b4fb3deb2dab9de6a443aabadb53 Signed-off-by: Yong Qin Signed-off-by: Luan Yuan Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c drivers/amlogic/media/deinterlace/deinterlace_dbg.c drivers/amlogic/media/deinterlace/deinterlace_hw.c drivers/amlogic/media/deinterlace/nr_drv.c --- .../amlogic/media/deinterlace/deinterlace.c | 31 +++++++++++++------ .../media/deinterlace/deinterlace_dbg.c | 4 ++- .../media/deinterlace/deinterlace_hw.c | 16 +++++++--- drivers/amlogic/media/deinterlace/nr_drv.c | 12 ++++--- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 0d33bf1a7004..71a043f75a9a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-14a"; +static const char version_s[] = "2019-02-26a sm1 buring up test"; static int bypass_state = 1; static int bypass_all; @@ -5099,7 +5099,8 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { di_post_read_reverse_irq(overturn, mc_pre_flag, post_blend_en ? mcpre_en : false); /* disable mc for first 2 fieldes mv unreliable */ @@ -5880,7 +5881,8 @@ static void di_unreg_process_irq(void) afbc_reg_sw(false); di_hw_uninit(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() - || is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + || is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu()) { di_pre_gate_control(false, mcpre_en); nr_gate_control(false); } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { @@ -5892,7 +5894,8 @@ static void di_unreg_process_irq(void) if (mirror_disable) { di_hw_disable(mcpre_en); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() - || is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + || is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu()) { enable_di_post_mif(GATE_OFF); di_post_gate_control(false); di_top_gate_control(false, false); @@ -6004,7 +6007,9 @@ static void di_pre_size_change(unsigned short width, is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu()) film_mode_win_config(width, height); } if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) @@ -6436,7 +6441,9 @@ static int di_task_handle(void *data) #endif } } - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || + is_meson_sm1_cpu()) { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, de_devp->clkb_max_rate); @@ -7383,7 +7390,9 @@ static void set_di_flag(void) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu()) { mcpre_en = true; mc_mem_alloc = true; pulldown_enable = false; @@ -7400,7 +7409,9 @@ static void set_di_flag(void) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu()) { full_422_pack = true; } @@ -7411,7 +7422,9 @@ static void set_di_flag(void) full_422_pack = false; } post_hold_line = - (is_meson_g12a_cpu() || is_meson_g12b_cpu())?10:17; + (is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || + is_meson_sm1_cpu())?10:17; } else { post_hold_line = 8; /*2019-01-10: from VLSI feijun*/ mcpre_en = false; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index 5f5c7fdb2b18..63f6102111f2 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -253,7 +253,9 @@ void dump_di_reg_g12(void) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu()) base_addr = 0xff900000; else base_addr = 0xd0100000; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index a8b7c89d0f51..fc9c0dac6a4c 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -466,7 +466,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) unsigned short fifo_size_di = 0xc0; switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() - || is_meson_g12a_cpu() || is_meson_g12b_cpu()) + || is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu()) di_top_gate_control(true, true); else if (is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_gxlx_cpu()) @@ -479,7 +480,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_tl1_cpu()) { /* vpp fifo max size on txl :128*3=384[0x180] */ /* di fifo max size on txl :96*3=288[0x120] */ fifo_size_vpp = 0x180; @@ -510,7 +512,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_tl1_cpu()) { di_pre_gate_control(true, true); di_post_gate_control(true); } @@ -527,8 +530,9 @@ void di_hw_init(bool pd_enable, bool mc_enable) mc_di_param_init(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12a_cpu() || is_meson_sm1_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu()) { di_pre_gate_control(false, true); di_post_gate_control(false); di_top_gate_control(false, false); @@ -1000,7 +1004,9 @@ bool afbc_is_supported(void) } +#define AFBC_DEC_SEL (eAFBC_DEC1) void enable_afbc_input(struct vframe_s *vf) + { unsigned int r, u, v, w_aligned, h_aligned; unsigned int out_height = 0; diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index 4d93d465f2aa..55483bc4a99b 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -353,7 +353,8 @@ static void linebuffer_config(unsigned short width) static void nr2_config(unsigned short width, unsigned short height) { if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu()) { DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 2, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 15, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 17, 1); @@ -402,7 +403,8 @@ void nr_all_config(unsigned short width, unsigned short height, if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) cue_config(nr_param.pcue_parm, field_type); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu()) { linebuffer_config(width); nr4_config(nr_param.pnr4_parm, width, height); } @@ -782,7 +784,8 @@ void nr_process_in_irq(void) if (dnr_en) dnr_process(&dnr_param); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() - || is_meson_g12a_cpu()) { + || is_meson_g12a_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu()) { noise_meter_process(nr_param.pnr4_parm, nr_param.frame_count); luma_enhancement_process(nr_param.pnr4_parm, nr_param.frame_count); @@ -1130,7 +1133,8 @@ void nr_hw_init(void) void nr_gate_control(bool gate) { if (!is_meson_txlx_cpu() && !is_meson_g12a_cpu() - && !is_meson_g12b_cpu()) + && !is_meson_g12b_cpu() && !is_meson_sm1_cpu() + && !is_meson_tl1_cpu()) return; if (gate) { /* enable nr auto gate */ From 49e335e4c980ae86458abc56d050904d5fa49f72 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Wed, 20 Mar 2019 15:24:46 +0800 Subject: [PATCH 0108/1060] usb: modify usb dts for sm1 [1/1] PD#SWPL-5385 Problem: SM1 bring up Solution: modify usb dts for SM1 bringup Verify: g12a Test: pass Change-Id: Ie6f2925315ce12b3ad2964cf85aa3f4cee4bf2a7 Signed-off-by: Yue Wang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 24 ++++-- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 +- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 8 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 24 ++++-- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 +- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 8 +- drivers/amlogic/clk/g12a/g12a_clk-pll.c | 3 +- drivers/amlogic/pci/pcie-amlogic-v2.c | 83 ++++++++++++++++--- drivers/amlogic/pci/pcie-amlogic.h | 2 + drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c | 58 +++++++++++++ drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c | 76 ++++++++++++++++- drivers/usb/dwc3/core.c | 12 +++ include/linux/amlogic/usb-v2.h | 3 + 13 files changed, 271 insertions(+), 38 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 40345e1d5360..97183ea87513 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -374,21 +374,28 @@ reg = <0xffe09000 0x80 0xffd01008 0x100 0xff636000 0x2000 - 0xff63a000 0x2000>; + 0xff63a000 0x2000 + 0xff8000e8 0x10 + 0xff63c100 0x4>; pll-setting-1 = <0x09400414>; pll-setting-2 = <0x927E0000>; - pll-setting-3 = <0xac5f49e5>; + pll-setting-3 = <0xac5f69e5>; pll-setting-4 = <0xfe18>; pll-setting-5 = <0x8000fff>; pll-setting-6 = <0x78000>; pll-setting-7 = <0xe0004>; pll-setting-8 = <0xe000c>; + version = <2>; + pwr-ctl = <1>; }; usb3_phy_v2: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3-v2"; status = "disable"; - reg = <0xffe09080 0x20>; + reg = <0xffe09080 0x20 + 0xff8000e8 0x10 + 0xff63c100 0x4 + 0xffd01008 0x100>; phy-reg = <0xff646000>; phy-reg-size = <0x2000>; usb2-phy-reg = <0xffe09000>; @@ -396,6 +403,7 @@ interrupts = <0 16 4>; clocks = <&clkc CLKID_PCIE_PLL>; clock-names = "pcie_refpll"; + pwr-ctl = <1>; }; dwc2_a: dwc2_a@ff400000 { @@ -418,7 +426,7 @@ phy-reg = <0xffe09000>; phy-reg-size = <0xa0>; /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ - phy-interface = <0x0>; + phy-interface = <0x2>; clocks = <&clkc CLKID_USB_GENERAL &clkc CLKID_USB1_TO_DDR>; clock-names = "usb_general", @@ -1015,8 +1023,11 @@ 0xff648000 0x2000 0xfc400000 0x200000 0xff646000 0x2000 - 0xffd01080 0x10>; - reg-names = "elbi", "cfg", "config", "phy", "reset"; + 0xffd01080 0x10 + 0xff8000e8 0x8 + 0xff63c100 0x4>; + reg-names = "elbi", "cfg", "config", "phy", + "reset", "pwr", "hii"; interrupts = <0 221 0>; #interrupt-cells = <1>; bus-range = <0x0 0xff>; @@ -1043,6 +1054,7 @@ pcie-apb-rst-bit = <15>; pcie-phy-rst-bit = <14>; pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 759471b83c8c..3e83a30603a1 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1392,7 +1392,7 @@ }; &dwc3 { - status = "disabled"; + status = "okay"; }; &usb2_phy_v2 { @@ -1409,7 +1409,7 @@ }; &dwc2_a { - status = "disabled"; + status = "okay"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 1dcc06171499..03bcbba7abe9 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1392,7 +1392,7 @@ }; &dwc3 { - status = "disabled"; + status = "okay"; }; &usb2_phy_v2 { @@ -1402,14 +1402,14 @@ &usb3_phy_v2 { status = "okay"; - portnum = <1>; + portnum = <0>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; }; &dwc2_a { - status = "disabled"; + status = "okay"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; @@ -1596,7 +1596,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "disable"; + status = "okay"; }; &meson_cooldev { diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 45c5633ca5dd..f2a7761491df 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -374,21 +374,28 @@ reg = <0x0 0xffe09000 0x0 0x80 0x0 0xffd01008 0x0 0x100 0x0 0xff636000 0x0 0x2000 - 0x0 0xff63a000 0x0 0x2000>; + 0x0 0xff63a000 0x0 0x2000 + 0x0 0xff8000e8 0x0 0x10 + 0x0 0xff63c100 0x0 0x4>; pll-setting-1 = <0x09400414>; pll-setting-2 = <0x927E0000>; - pll-setting-3 = <0xac5f49e5>; + pll-setting-3 = <0xac5f69e5>; pll-setting-4 = <0xfe18>; pll-setting-5 = <0x8000fff>; pll-setting-6 = <0x78000>; pll-setting-7 = <0xe0004>; pll-setting-8 = <0xe000c>; + version = <2>; + pwr-ctl = <1>; }; usb3_phy_v2: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3-v2"; status = "disable"; - reg = <0x0 0xffe09080 0x0 0x20>; + reg = <0x0 0xffe09080 0x0 0x20 + 0x0 0xff8000e8 0x0 0x10 + 0x0 0xff63c100 0x0 0x4 + 0x0 0xffd01008 0x0 0x100>; phy-reg = <0xff646000>; phy-reg-size = <0x2000>; usb2-phy-reg = <0xffe09000>; @@ -396,6 +403,7 @@ interrupts = <0 16 4>; clocks = <&clkc CLKID_PCIE_PLL>; clock-names = "pcie_refpll"; + pwr-ctl = <1>; }; dwc2_a: dwc2_a@ff400000 { @@ -418,7 +426,7 @@ phy-reg = <0xffe09000>; phy-reg-size = <0xa0>; /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ - phy-interface = <0x0>; + phy-interface = <0x2>; clocks = <&clkc CLKID_USB_GENERAL &clkc CLKID_USB1_TO_DDR>; clock-names = "usb_general", @@ -1015,8 +1023,11 @@ 0x0 0xff648000 0x0 0x2000 0x0 0xfc400000 0x0 0x200000 0x0 0xff646000 0x0 0x2000 - 0x0 0xffd01080 0x0 0x10>; - reg-names = "elbi", "cfg", "config", "phy", "reset"; + 0x0 0xffd01080 0x0 0x10 + 0x0 0xff8000e8 0x0 0x8 + 0x0 0xff63c100 0x0 0x4>; + reg-names = "elbi", "cfg", "config", "phy", + "reset", "pwr", "hii"; interrupts = <0 221 0>; #interrupt-cells = <1>; bus-range = <0x0 0xff>; @@ -1043,6 +1054,7 @@ pcie-apb-rst-bit = <15>; pcie-phy-rst-bit = <14>; pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index b58c7a834dd7..dbf8a837568f 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1390,7 +1390,7 @@ }; &dwc3 { - status = "disabled"; + status = "okay"; }; &usb2_phy_v2 { @@ -1407,7 +1407,7 @@ }; &dwc2_a { - status = "disabled"; + status = "okay"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 3986d59945ef..0ea4e99fe1ab 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1390,7 +1390,7 @@ }; &dwc3 { - status = "disalbed"; + status = "okay"; }; &usb2_phy_v2 { @@ -1400,14 +1400,14 @@ &usb3_phy_v2 { status = "okay"; - portnum = <1>; + portnum = <0>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; }; &dwc2_a { - status = "disalbed"; + status = "okay"; /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ controller-type = <3>; }; @@ -1594,7 +1594,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "disable"; + status = "okay"; }; &meson_cooldev { diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 505a6aa81024..318079b29224 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -271,7 +271,8 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, cntlbase = pll->base + p->reg_off; if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) { + if ((get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) || + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1))) { writel(G12A_PCIE_PLL_CNTL0_0, cntlbase + (unsigned long)(0*4)); writel(G12A_PCIE_PLL_CNTL0_1, diff --git a/drivers/amlogic/pci/pcie-amlogic-v2.c b/drivers/amlogic/pci/pcie-amlogic-v2.c index 527ed2843b49..8b9454f8ccd5 100644 --- a/drivers/amlogic/pci/pcie-amlogic-v2.c +++ b/drivers/amlogic/pci/pcie-amlogic-v2.c @@ -51,6 +51,7 @@ struct amlogic_pcie { u32 pm_enable; u32 device_attch; u32 rst_mod; + u32 pwr_ctl; }; #define to_amlogic_pcie(x) container_of(x, struct amlogic_pcie, pp) @@ -679,6 +680,31 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, return 0; } +static void power_switch_to_pcie(struct pcie_phy *phy) +{ + u32 val; + + writel(readl(phy->power_base) & (~(0x1<<18)), phy->power_base); + + writel(readl(phy->hhi_mem_pd_base) & (~(0xf<<26)), + phy->hhi_mem_pd_base); + udelay(100); + + val = readl((void __iomem *)(unsigned long)phy->reset_base); + writel((val & (~(0x1<<12))), + (void __iomem *)(unsigned long)phy->reset_base); + udelay(100); + + writel(readl(phy->power_base+0x4) & (~(0x1<<18)), + phy->power_base + 0x4); + + val = readl((void __iomem *)(unsigned long)phy->reset_base); + writel((val | (0x1<<12)), + (void __iomem *)(unsigned long)phy->reset_base); + udelay(100); +} + + static int __init amlogic_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -690,6 +716,8 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) struct resource *phy_base; struct resource *cfg_base; struct resource *reset_base; + struct resource *power_base = NULL; + struct resource *hhi_mem_pd_base = NULL; int ret; int pcie_num = 0; int num_lanes = 0; @@ -703,6 +731,7 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) int pcie_apb_rst_bit = 0; int pcie_phy_rst_bit = 0; int pcie_ctrl_a_rst_bit = 0; + u32 pwr_ctl = 0; dev_info(&pdev->dev, "amlogic_pcie_probe!\n"); @@ -757,6 +786,49 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) pp->lanes = 0; pp->lanes = num_lanes; + ret = of_property_read_u32(np, "pwr-ctl", &pwr_ctl); + if (ret) + amlogic_pcie->pwr_ctl = 0; + else + amlogic_pcie->pwr_ctl = pwr_ctl; + + if (pwr_ctl) { + power_base = platform_get_resource_byname( + pdev, IORESOURCE_MEM, "pwr"); + if (power_base) { + amlogic_pcie->phy->power_base = + ioremap(power_base->start, + resource_size(power_base)); + if (IS_ERR(amlogic_pcie->phy->power_base)) + return PTR_ERR(amlogic_pcie->phy->power_base); + } + + hhi_mem_pd_base = platform_get_resource_byname( + pdev, IORESOURCE_MEM, "hii"); + if (hhi_mem_pd_base) { + amlogic_pcie->phy->hhi_mem_pd_base = + ioremap(hhi_mem_pd_base->start, + resource_size(hhi_mem_pd_base)); + if (IS_ERR(amlogic_pcie->phy->hhi_mem_pd_base)) + return PTR_ERR(amlogic_pcie-> + phy->hhi_mem_pd_base); + } + } + + if (!amlogic_pcie->phy->reset_base) { + reset_base = platform_get_resource_byname( + pdev, IORESOURCE_MEM, "reset"); + amlogic_pcie->phy->reset_base = devm_ioremap_resource( + dev, reset_base); + if (IS_ERR(amlogic_pcie->phy->reset_base)) { + ret = PTR_ERR(amlogic_pcie->phy->reset_base); + return ret; + } + } + + if (pwr_ctl) + power_switch_to_pcie(amlogic_pcie->phy); + if (!amlogic_pcie->phy->phy_base) { phy_base = platform_get_resource_byname( pdev, IORESOURCE_MEM, "phy"); @@ -783,17 +855,6 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) amlogic_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); - if (!amlogic_pcie->phy->reset_base) { - reset_base = platform_get_resource_byname( - pdev, IORESOURCE_MEM, "reset"); - amlogic_pcie->phy->reset_base = devm_ioremap_resource( - dev, reset_base); - if (IS_ERR(amlogic_pcie->phy->reset_base)) { - ret = PTR_ERR(amlogic_pcie->phy->reset_base); - goto fail_pcie; - } - } - /* RESET0[1,2,6,7] = 0*/ if (!amlogic_pcie->phy->reset_state) { if (amlogic_pcie->rst_mod == 0) { diff --git a/drivers/amlogic/pci/pcie-amlogic.h b/drivers/amlogic/pci/pcie-amlogic.h index d3fca8199e3a..88a6b871e042 100644 --- a/drivers/amlogic/pci/pcie-amlogic.h +++ b/drivers/amlogic/pci/pcie-amlogic.h @@ -162,6 +162,8 @@ struct pcie_phy { u32 reset_state; void __iomem *phy_base; /* DT 1st resource */ void __iomem *reset_base;/* DT 3nd resource */ + void __iomem *power_base; + void __iomem *hhi_mem_pd_base; }; diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index e2b55e8d8e07..1dc5072c1131 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -223,6 +223,26 @@ static void amlogic_new_usb2phy_shutdown(struct usb_phy *x) phy->suspend_flag = 1; } +void power_switch_to_usb(struct amlogic_usb_v2 *phy) +{ + /* Powerup usb_comb */ + writel(readl(phy->power_base) & (~(0x1<<17)), phy->power_base); + writel(readl(phy->hhi_mem_pd_base) & (~(0x3<<30)), + phy->hhi_mem_pd_base); + udelay(100); + + writel((readl(phy->reset_regs + (0x21 * 4 - 0x8)) & ~(0x1 << 2)), + phy->reset_regs + (0x21 * 4 - 0x8)); + + udelay(100); + writel(readl(phy->power_base+0x4) & (~(0x1<<17)), + phy->power_base + 0x4); + + writel((readl(phy->reset_regs + (0x21 * 4 - 0x8)) | (0x1 << 2)), + phy->reset_regs + (0x21 * 4 - 0x8)); + udelay(100); +} + static int amlogic_new_usb2_probe(struct platform_device *pdev) { struct amlogic_usb_v2 *phy; @@ -230,15 +250,20 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) struct resource *phy_mem; struct resource *reset_mem; struct resource *phy_cfg_mem[4]; + struct resource *power_mem = NULL; + struct resource *hhi_mem_pd_mem = NULL; void __iomem *phy_base; void __iomem *reset_base = NULL; void __iomem *phy_cfg_base[4]; + void __iomem *power_base = NULL; + void __iomem *hhi_mem_pd_base = NULL; int portnum = 0; int phy_version = 0; const void *prop; int i = 0; int retval; u32 pll_setting[8]; + u32 pwr_ctl = 0; prop = of_get_property(dev->of_node, "portnum", NULL); if (prop) @@ -284,6 +309,32 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) } } + prop = of_get_property(dev->of_node, "pwr-ctl", NULL); + if (prop) + pwr_ctl = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + if (pwr_ctl) { + power_mem = platform_get_resource + (pdev, IORESOURCE_MEM, 2 + portnum); + if (power_mem) { + power_base = ioremap(power_mem->start, + resource_size(power_mem)); + if (IS_ERR(power_base)) + return PTR_ERR(power_base); + } + + hhi_mem_pd_mem = platform_get_resource + (pdev, IORESOURCE_MEM, 3 + portnum); + if (hhi_mem_pd_mem) { + hhi_mem_pd_base = ioremap(hhi_mem_pd_mem->start, + resource_size(hhi_mem_pd_mem)); + if (IS_ERR(hhi_mem_pd_base)) + return PTR_ERR(hhi_mem_pd_base); + } + } + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); if (!phy) return -ENOMEM; @@ -351,12 +402,19 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) phy->pll_setting[7] = pll_setting[7]; phy->suspend_flag = 0; phy->phy_version = phy_version; + phy->pwr_ctl = pwr_ctl; for (i = 0; i < portnum; i++) { phy->phy_cfg[i] = phy_cfg_base[i]; /* set port default tuning state */ phy->phy_cfg_state[i] = 1; } + if (pwr_ctl) { + phy->power_base = power_base; + phy->hhi_mem_pd_base = hhi_mem_pd_base; + power_switch_to_usb(phy); + } + usb_add_phy_dev(&phy->phy); platform_set_drvdata(pdev, phy); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c index 727cdd845306..0f1839b5ae41 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c @@ -145,7 +145,6 @@ static void cr_bus_addr(unsigned int addr) phy_r4.b.phy_cr_data_in = addr; writel(phy_r4.d32, g_phy_v2->phy3_cfg_r4); - phy_r4.b.phy_cr_cap_addr = 0; writel(phy_r4.d32, g_phy_v2->phy3_cfg_r4); phy_r4.b.phy_cr_cap_addr = 1; @@ -312,6 +311,7 @@ static int amlogic_new_usb3_init(struct usb_phy *x) p3_r2.b.phy_tx_vboost_lvl = 0x4; writel(p3_r2.d32, phy->phy3_cfg_r2); udelay(2); + /* * WORKAROUND: There is SSPHY suspend bug due to * which USB enumerates @@ -482,13 +482,44 @@ static bool device_is_available(const struct device_node *device) return false; } +static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) +{ + u32 val; + + writel(readl(phy->power_base) & (~(0x1<<18)), phy->power_base); + + writel(readl(phy->hhi_mem_pd_base) & (~(0xf<<26)), + phy->hhi_mem_pd_base); + udelay(100); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val & (~(0x1<<12))), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + udelay(100); + + writel(readl(phy->power_base+0x4) & (~(0x1<<18)), + phy->power_base + 0x4); + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val | (0x1<<12)), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + udelay(100); +} + static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) { struct amlogic_usb_v2 *phy; struct device *dev = &pdev->dev; struct resource *phy_mem; - void __iomem *phy_base; + struct resource *power_mem = NULL; + struct resource *hhi_mem_pd_mem = NULL; + struct resource *reset_mem; + void __iomem *phy_base; void __iomem *phy3_base; + void __iomem *power_base = NULL; + void __iomem *hhi_mem_pd_base = NULL; + void __iomem *reset_base = NULL; unsigned int phy3_mem; unsigned int phy3_mem_size = 0; void __iomem *usb2_phy_base; @@ -504,6 +535,7 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) int otg = 0; int ret; struct device_node *tsi_pci; + u32 pwr_ctl = 0; gpio_name = of_get_property(dev->of_node, "gpio-vbus-power", NULL); if (gpio_name) { @@ -554,6 +586,38 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) if (!phy3_base) return -ENOMEM; + prop = of_get_property(dev->of_node, "pwr-ctl", NULL); + if (prop) + pwr_ctl = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + if (pwr_ctl) { + power_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (power_mem) { + power_base = ioremap(power_mem->start, + resource_size(power_mem)); + if (IS_ERR(power_base)) + return PTR_ERR(power_base); + } + + hhi_mem_pd_mem = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (hhi_mem_pd_mem) { + hhi_mem_pd_base = ioremap(hhi_mem_pd_mem->start, + resource_size(hhi_mem_pd_mem)); + if (IS_ERR(hhi_mem_pd_base)) + return PTR_ERR(hhi_mem_pd_base); + } + + reset_mem = platform_get_resource(pdev, IORESOURCE_MEM, 3); + if (reset_mem) { + reset_base = ioremap(reset_mem->start, + resource_size(reset_mem)); + if (IS_ERR(reset_base)) + return PTR_ERR(reset_base); + } + } + retval = of_property_read_u32 (dev->of_node, "usb2-phy-reg", &usb2_phy_mem); if (retval < 0) @@ -615,9 +679,16 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) phy->phy.flags = AML_USB3_PHY_DISABLE; phy->vbus_power_pin = gpio_vbus_power_pin; phy->usb_gpio_desc = usb_gd; + phy->pwr_ctl = pwr_ctl; /* set the phy from pcie to usb3 */ if (phy->portnum > 0) { + if (phy->pwr_ctl) { + phy->power_base = power_base; + phy->hhi_mem_pd_base = hhi_mem_pd_base; + phy->reset_regs = reset_base; + power_switch_to_pcie(phy); + } writel((readl(phy->phy3_cfg) | (3<<5)), phy->phy3_cfg); udelay(100); @@ -634,6 +705,7 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) ret = PTR_ERR(phy->clk); return ret; } + phy->phy.flags = AML_USB3_PHY_ENABLE; } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index abd1c3ae8153..a0846a1546fd 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -760,6 +760,7 @@ static int dwc3_core_init(struct dwc3 *dwc) ret = dwc3_phy_setup(dwc); if (ret) goto err0; + #ifdef CONFIG_AMLOGIC_USB reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); reg |= DWC3_GUCTL_NAKPERENHHS; @@ -1554,7 +1555,9 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); #endif static struct platform_driver dwc3_driver = { +#ifndef CONFIG_AMLOGIC_USB .probe = dwc3_probe, +#endif .remove = dwc3_remove, #ifdef CONFIG_AMLOGIC_USB .shutdown = dwc3_shutdown, @@ -1567,7 +1570,16 @@ static struct platform_driver dwc3_driver = { }, }; +#ifdef CONFIG_AMLOGIC_USB +/* AMLOGIC DWC3 driver does not allow module unload */ +static int __init amlogic_dwc3_init(void) +{ + return platform_driver_probe(&dwc3_driver, dwc3_probe); +} +late_initcall(amlogic_dwc3_init); +#else module_platform_driver(dwc3_driver); +#endif MODULE_ALIAS("platform:dwc3"); MODULE_AUTHOR("Felipe Balbi "); diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index f3e8f0857d1e..dc3774e4ef13 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -169,6 +169,8 @@ struct amlogic_usb_v2 { void __iomem *phy3_cfg_r4; void __iomem *phy3_cfg_r5; void __iomem *usb2_phy_cfg; + void __iomem *power_base; + void __iomem *hhi_mem_pd_base; u32 pll_setting[8]; int phy_cfg_state[4]; /* Set VBus Power though GPIO */ @@ -180,6 +182,7 @@ struct amlogic_usb_v2 { int portnum; int suspend_flag; int phy_version; + int pwr_ctl; struct clk *clk; }; From 0ebb4fc6e88550b889aea24a2ed7590ef58d1f41 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Wed, 6 Mar 2019 14:10:20 +0800 Subject: [PATCH 0109/1060] clk: sm1: add clk driver [1/1] PD#SWPL-5407 Problem: sm1 not have clk driver Solution: add clk driver Verify: PxP Change-Id: Id48257d88ef200fd4adb309bf2e4ada1be407753 Signed-off-by: Shunzhou Jiang --- .../bindings/clock/amlogic,meson-clkc.txt | 3 + MAINTAINERS | 4 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 14 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 14 +- drivers/amlogic/clk/Makefile | 1 + drivers/amlogic/clk/g12a/g12a.c | 15 + drivers/amlogic/clk/g12a/g12a_ao.c | 1 + drivers/amlogic/clk/g12a/g12a_clk-pll.c | 4 +- drivers/amlogic/clk/sm1/Makefile | 5 + drivers/amlogic/clk/sm1/sm1.c | 292 ++++++++++++++++++ drivers/amlogic/clk/sm1/sm1.h | 33 ++ include/dt-bindings/clock/amlogic,g12a-clkc.h | 14 +- 12 files changed, 390 insertions(+), 10 deletions(-) create mode 100644 drivers/amlogic/clk/sm1/Makefile create mode 100644 drivers/amlogic/clk/sm1/sm1.c create mode 100644 drivers/amlogic/clk/sm1/sm1.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt index 651860382060..d9b8a3da5da5 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt @@ -22,6 +22,9 @@ Required Properties: "amlogic,tl1-clkc" - for tl1 ee clock "amlogic,tl1-aoclkc" - for tl1 ao clock "amlogic,tl1-measure" - for tl1 clock measurement + "amlogic,sm1-clkc-1" - for sm1 ee part1 clock + "amlogic,sm1-clkc-2" - for sm1 ee part2 clock + "amlogic,sm1-aoclkc" - for sm1 ao clock - reg: physical base address of the clock controller and length of memory mapped region. diff --git a/MAINTAINERS b/MAINTAINERS index ddeb0271391f..9a4a24b77293 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14775,6 +14775,10 @@ F: arch/arm64/boot/dts/amlogic/sm1_pxp.dts F: arch/arm/boot/dts/amlogic/mesonsm1.dtsi F: arch/arm/boot/dts/amlogic/sm1_pxp.dts +AMLOGIC SM1 CLOCK DRIVERS +M: Shunzhou Jiang +F: drivers/amlogic/clk/sm1/* + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 97183ea87513..20f121e16243 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -673,9 +673,9 @@ }; aoclkc: clock-controller@0 { - compatible = "amlogic,g12a-aoclkc"; + compatible = "amlogic,sm1-aoclkc"; #clock-cells = <1>; - reg = <0x0 0x320>; + reg = <0x0 0x3dc>; }; pwm_AO_ab: pwm@7000 { @@ -773,9 +773,15 @@ ranges = <0x0 0xff63c000 0x2000>; clkc: clock-controller@0 { - compatible = "amlogic,g12a-clkc"; + compatible = "amlogic,sm1-clkc-1"; #clock-cells = <1>; - reg = <0x0 0x320>; + reg = <0x0 0x3dc>; + }; + + clkc_b: clock-controller@1 { + compatible = "amlogic,sm1-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; }; };/* end of hiubus*/ diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index f2a7761491df..46b412ae9090 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -673,9 +673,9 @@ }; aoclkc: clock-controller@0 { - compatible = "amlogic,g12a-aoclkc"; + compatible = "amlogic,sm1-aoclkc"; #clock-cells = <1>; - reg = <0x0 0x0 0x0 0x320>; + reg = <0x0 0x0 0x0 0x3dc>; }; pwm_AO_ab: pwm@7000 { @@ -773,9 +773,15 @@ ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; clkc: clock-controller@0 { - compatible = "amlogic,g12a-clkc"; + compatible = "amlogic,sm1-clkc-1"; #clock-cells = <1>; - reg = <0x0 0x0 0x0 0x320>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + + clkc_b: clock-controller@1 { + compatible = "amlogic,sm1-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; }; };/* end of hiubus*/ diff --git a/drivers/amlogic/clk/Makefile b/drivers/amlogic/clk/Makefile index 77fdb66e5b07..95486a70024a 100644 --- a/drivers/amlogic/clk/Makefile +++ b/drivers/amlogic/clk/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_AMLOGIC_GX_CLK) += txl/ obj-$(CONFIG_AMLOGIC_GX_CLK) += g12a/ obj-$(CONFIG_AMLOGIC_GX_CLK) += g12b/ obj-$(CONFIG_AMLOGIC_GX_CLK) += tl1/ +obj-$(CONFIG_AMLOGIC_GX_CLK) += sm1/ obj-$(CONFIG_AMLOGIC_M8B_CLK) += m8b/ diff --git a/drivers/amlogic/clk/g12a/g12a.c b/drivers/amlogic/clk/g12a/g12a.c index 9cf950f9f241..ba683ead35fd 100644 --- a/drivers/amlogic/clk/g12a/g12a.c +++ b/drivers/amlogic/clk/g12a/g12a.c @@ -970,6 +970,20 @@ static void __init g12a_clkc_init(struct device_node *np) __func__); goto iounmap; } + + if (of_property_read_bool(np, "own-dsu-clk")) { + if (clks[CLKID_DSU_CLK]) { + clk_set_parent(clks[CLKID_DSU_CLK], + clks[CLKID_CPU_CLK]); + /* set sm1_dsu_pre_clk to 1.5G, gp1 pll is 1.5G */ + clk_set_rate(clks[CLKID_DSU_PRE_CLK], 1500000000); + clk_prepare_enable(clks[CLKID_DSU_PRE_CLK]); + /* set sm1_dsu_pre_clk as dsu_pre's parent */ + clk_set_parent(clks[CLKID_DSU_CLK], + clks[CLKID_DSU_PRE_CLK]); + } + } + pr_debug("%s: cpu clk register notifier ok!", __func__); ret = of_clk_add_provider(np, of_clk_src_onecell_get, @@ -988,4 +1002,5 @@ iounmap: CLK_OF_DECLARE(g12a, "amlogic,g12a-clkc", g12a_clkc_init); CLK_OF_DECLARE(g12b, "amlogic,g12b-clkc-1", g12a_clkc_init); +CLK_OF_DECLARE(sm1, "amlogic,sm1-clkc-1", g12a_clkc_init); diff --git a/drivers/amlogic/clk/g12a/g12a_ao.c b/drivers/amlogic/clk/g12a/g12a_ao.c index 6ea40b9d4be8..40319856b59e 100644 --- a/drivers/amlogic/clk/g12a/g12a_ao.c +++ b/drivers/amlogic/clk/g12a/g12a_ao.c @@ -145,5 +145,6 @@ static void __init g12a_aoclkc_init(struct device_node *np) CLK_OF_DECLARE(g12a, "amlogic,g12a-aoclkc", g12a_aoclkc_init); CLK_OF_DECLARE(g12b, "amlogic,g12b-aoclkc", g12a_aoclkc_init); +CLK_OF_DECLARE(sm1, "amlogic,sm1-aoclkc", g12a_aoclkc_init); diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 318079b29224..2b9a8e5ca0cd 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -364,7 +364,8 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, writel(G12A_PLL_CNTL6, cntlbase + (unsigned long)(6*4)); udelay(10); - } else if (!strcmp(clk_hw_get_name(hw), "gp0_pll")) { + } else if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "gp1_pll")) { writel((readl(cntlbase) | MESON_PLL_RESET) & (~MESON_PLL_ENABLE), cntlbase); writel(G12A_GP0_PLL_CNTL1, @@ -488,6 +489,7 @@ static int meson_g12a_pll_enable(struct clk_hw *hw) } if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "gp1_pll") || !strcmp(clk_hw_get_name(hw), "hifi_pll") || !strcmp(clk_hw_get_name(hw), "pcie_pll") || !strcmp(clk_hw_get_name(hw), "sys_pll") diff --git a/drivers/amlogic/clk/sm1/Makefile b/drivers/amlogic/clk/sm1/Makefile new file mode 100644 index 000000000000..e36dd8e5ef2d --- /dev/null +++ b/drivers/amlogic/clk/sm1/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Meson SM1 clk +# + +obj-$(CONFIG_AMLOGIC_GX_CLK) += sm1.o diff --git a/drivers/amlogic/clk/sm1/sm1.c b/drivers/amlogic/clk/sm1/sm1.c new file mode 100644 index 000000000000..18698c42cf3c --- /dev/null +++ b/drivers/amlogic/clk/sm1/sm1.c @@ -0,0 +1,292 @@ +/* + * drivers/amlogic/clk/sm1/sm1.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../clkc.h" +#include "../g12a/g12a.h" +#include "sm1.h" + +static struct meson_clk_pll sm1_gp1_pll = { + .m = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 16, + .width = 3, + }, + .rate_table = g12a_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "gp1_pll", + .ops = &meson_g12a_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_mux sm1_dsu_pre_src_clk_mux0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x3, + .shift = 0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_src0", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "xtal", "fclk_div2", + "fclk_div3", "gp1_pll" }, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_src_clk_mux1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x3, + .shift = 16, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_src1", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "xtal", "fclk_div2", + "fclk_div3", "gp1_pll" }, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider sm1_dsu_clk_div0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .shift = 4, + .width = 5, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_clk_div0", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "dsu_pre_src0" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_divider sm1_dsu_clk_div1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .shift = 20, + .width = 5, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_clk_div1", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "dsu_pre_src1" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_clk_mux0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 2, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre0", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre_src0", + "dsu_clk_div0",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_clk_mux1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 18, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre1", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre_src1", + "dsu_clk_div1",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_post_clk_mux = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 10, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_post", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre0", + "dsu_pre1",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_clk = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 11, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_clk", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre_post", + "sys_pll",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_clk = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL6, + .mask = 0x1, + .shift = 11, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_clk", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "cpu_clk", + "dsu_pre_clk",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct meson_clk_pll *const sm1_clk_plls[] = { + &sm1_gp1_pll, +}; + +static struct clk_hw *sm1_clk_hws[] = { + [CLKID_GP1_PLL - CLKID_SM1_ADD_BASE] = &sm1_gp1_pll.hw, + [CLKID_DSU_PRE_SRC0 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_src_clk_mux0.hw, + [CLKID_DSU_PRE_SRC1 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_src_clk_mux1.hw, + [CLKID_DSU_CLK_DIV0 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_clk_div0.hw, + [CLKID_DSU_CLK_DIV1 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_clk_div1.hw, + [CLKID_DSU_PRE_MUX0 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_clk_mux0.hw, + [CLKID_DSU_PRE_MUX1 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_clk_mux1.hw, + [CLKID_DSU_PRE_POST_MUX - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_post_clk_mux.hw, + [CLKID_DSU_PRE_CLK - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_clk.hw, + [CLKID_DSU_CLK - CLKID_SM1_ADD_BASE] = &sm1_dsu_clk.hw, +}; + +static void __init sm1_clkc_init(struct device_node *np) +{ + int ret = 0, clkid, i; + + if (!clk_base) + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("%s: Unable to map clk base\n", __func__); + return; + } + for (i = 0; i < ARRAY_SIZE(sm1_clk_plls); i++) + sm1_clk_plls[i]->base = clk_base; + + sm1_dsu_pre_src_clk_mux0.reg = clk_base + + (unsigned long)sm1_dsu_pre_src_clk_mux0.reg; + sm1_dsu_pre_src_clk_mux1.reg = clk_base + + (unsigned long)sm1_dsu_pre_src_clk_mux1.reg; + sm1_dsu_clk_div0.reg = clk_base + + (unsigned long)sm1_dsu_clk_div0.reg; + sm1_dsu_clk_div1.reg = clk_base + + (unsigned long)sm1_dsu_clk_div1.reg; + sm1_dsu_pre_clk_mux0.reg = clk_base + + (unsigned long)sm1_dsu_pre_clk_mux0.reg; + sm1_dsu_pre_clk_mux1.reg = clk_base + + (unsigned long)sm1_dsu_pre_clk_mux1.reg; + sm1_dsu_pre_post_clk_mux.reg = clk_base + + (unsigned long)sm1_dsu_pre_post_clk_mux.reg; + sm1_dsu_pre_clk.reg = clk_base + + (unsigned long)sm1_dsu_pre_clk.reg; + sm1_dsu_clk.reg = clk_base + + (unsigned long)sm1_dsu_clk.reg; + if (!clks) { + clks = kzalloc(NR_CLKS*sizeof(struct clk *), GFP_KERNEL); + if (!clks) { + pr_err("%s: alloc clks fail!", __func__); + return; + } + clk_numbers = NR_CLKS; + } + + /* + * register all clks + */ + + for (clkid = 0; clkid < ARRAY_SIZE(sm1_clk_hws); clkid++) { + if (sm1_clk_hws[clkid]) { + clks[clkid + CLKID_SM1_ADD_BASE] + = clk_register(NULL, sm1_clk_hws[clkid]); + if (IS_ERR(clks[clkid + CLKID_SM1_ADD_BASE])) { + pr_err("%s: failed to register %s\n", __func__, + clk_hw_get_name(sm1_clk_hws[clkid])); + goto iounmap; + } + } + } + + if (clks[CLKID_CPU_CLK]) { + if (!of_property_read_bool(np, "own-dsu-clk")) + return; + /* set cpu clk as dsu_clk's parent*/ + clk_set_parent(sm1_dsu_clk.hw.clk, clks[CLKID_CPU_CLK]); + /* set sm1_dsu_pre_clk to 1.5G, gp1 pll is 1.5G */ + clk_set_rate(sm1_dsu_pre_clk.hw.clk, 1500000000); + clk_prepare_enable(sm1_dsu_pre_clk.hw.clk); + /* set sm1_dsu_pre_clk as dsu_clk's parent */ + clk_set_parent(sm1_dsu_clk.hw.clk, sm1_dsu_pre_clk.hw.clk); + } + return; + +iounmap: + iounmap(clk_base); + pr_info("%s: %d: ret: %d\n", __func__, __LINE__, ret); +} + +CLK_OF_DECLARE(sm1, "amlogic,sm1-clkc-2", sm1_clkc_init); + + diff --git a/drivers/amlogic/clk/sm1/sm1.h b/drivers/amlogic/clk/sm1/sm1.h new file mode 100644 index 000000000000..d937329277bd --- /dev/null +++ b/drivers/amlogic/clk/sm1/sm1.h @@ -0,0 +1,33 @@ +/* + * drivers/amlogic/clk/sm1/sm1.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __SM1_H +#define __SM1_H + +/* + * Clock controller register offsets + * + * Register offsets from the data sheet are listed in comment blocks below. + * Those offsets must be multiplied by 4 before adding them to the base address + * to get the right value + */ + +#define HHI_GP1_PLL_CNTL0 0x60 /* 0x18 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL5 0x21C /* 0x87 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL6 0x220 /* 0x88 offset in data sheet */ + +#endif /* __SM1_H */ diff --git a/include/dt-bindings/clock/amlogic,g12a-clkc.h b/include/dt-bindings/clock/amlogic,g12a-clkc.h index 5d0da79ab6f3..3e9d81e0a82d 100644 --- a/include/dt-bindings/clock/amlogic,g12a-clkc.h +++ b/include/dt-bindings/clock/amlogic,g12a-clkc.h @@ -293,7 +293,19 @@ #define CLKID_MIPI_CSI_PHY_MUX (CLKID_G12B_ADD_BASE + 16) #define CLKID_SYS1_PLL (CLKID_G12B_ADD_BASE + 17) -#define CLKID_AO_BASE (CLKID_G12B_ADD_BASE + 18) +#define CLKID_SM1_ADD_BASE (CLKID_G12B_ADD_BASE + 18) +#define CLKID_GP1_PLL (CLKID_SM1_ADD_BASE + 0) +#define CLKID_DSU_PRE_SRC0 (CLKID_SM1_ADD_BASE + 1) +#define CLKID_DSU_PRE_SRC1 (CLKID_SM1_ADD_BASE + 2) +#define CLKID_DSU_CLK_DIV0 (CLKID_SM1_ADD_BASE + 3) +#define CLKID_DSU_CLK_DIV1 (CLKID_SM1_ADD_BASE + 4) +#define CLKID_DSU_PRE_MUX0 (CLKID_SM1_ADD_BASE + 5) +#define CLKID_DSU_PRE_MUX1 (CLKID_SM1_ADD_BASE + 6) +#define CLKID_DSU_PRE_POST_MUX (CLKID_SM1_ADD_BASE + 7) +#define CLKID_DSU_PRE_CLK (CLKID_SM1_ADD_BASE + 8) +#define CLKID_DSU_CLK (CLKID_SM1_ADD_BASE + 9) + +#define CLKID_AO_BASE (CLKID_SM1_ADD_BASE + 10) #define CLKID_AO_CLK81 (CLKID_AO_BASE + 0) #define CLKID_SARADC_MUX (CLKID_AO_BASE + 1) #define CLKID_SARADC_DIV (CLKID_AO_BASE + 2) From b72c94a820ea0d16c0b1c5bd69ba3c76250a0ed9 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Tue, 19 Mar 2019 15:13:53 +0800 Subject: [PATCH 0110/1060] clk: sm1: add clk measure driver [2/2] PD#SWPL-5407 Problem: sm1 support clk measure Solution: support clk measure Verify: ac200 Change-Id: If87c7c0bc53c8e2bcbf58a685f9ef7ac75462a70 Signed-off-by: Shunzhou Jiang --- drivers/amlogic/clk/clk_measure.c | 138 ++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/drivers/amlogic/clk/clk_measure.c b/drivers/amlogic/clk/clk_measure.c index 1ca3ef02362f..8473964233e4 100644 --- a/drivers/amlogic/clk/clk_measure.c +++ b/drivers/amlogic/clk/clk_measure.c @@ -1492,10 +1492,148 @@ static const struct meson_clkmsr_data tl1_data = { .clk_msr_function = gxbb_clk_util_clk_msr, }; +static const char * const sm1_table[] = { + [127] = "clk_csi2_data ", + [126] = "csi_phy0_clk_out ", + [125] = "earcrx_pll_test_clk ", + [124] = "earcx_pll_(dmac)_clk ", + [123] = "audio_resampled_clk ", + [122] = "mod_audio_pdm_dclk_o ", + [121] = "audio_spdifin_mst_clk ", + [120] = "audio_spdifout_mst_clk ", + [119] = "audio_spdifout_b_mst_clk ", + [118] = "audio_pdm_sysclk ", + [117] = "audio_resampleA_clk ", + [116] = "audio_tdmin_a_sclk ", + [115] = "audio_tdmin_b_sclk ", + [114] = "audio_tdmin_c_sclk ", + [113] = "audio_tdmin_lb_sclk ", + [112] = "audio_tdmout_a_sclk ", + [111] = "audio_tdmout_b_sclk ", + [110] = "audio_tdmout_c_sclk ", + [109] = "c_alocker_out_clk ", + [108] = "c_alocker_in_clk ", + [107] = "au_dac_clk_g128x ", + [106] = "ephy_test_clk ", + [105] = "arm_ring_osc_clk_out[16] ", + [104] = "arm_ring_osc_clk_out[15] ", + [103] = "arm_ring_osc_clk_out[14] ", + [102] = "arm_ring_osc_clk_out[13] ", + [101] = "arm_ring_osc_clk_out[12] ", + [100] = "arm_ring_osc_clk_out[11] ", + [99] = "arm_ring_osc_clk_out[10] ", + [98] = "cts_ts_clk ", + [97] = "cts_vpu_clkb_tmp ", + [96] = "cts_vpu_clkb ", + [95] = "eth_phy_plltxclk ", + [94] = "eth_phy_rxclk ", + [93] = "vad_clk ", + [92] = "nna_axi_clk ", + [91] = "nna_core_clk ", + [90] = "cts_hdmitx_sys_clk ", + [89] = "HDMI_CLK_TODIG ", + [88] = "csi2_adapt_clk ", + [87] = "mipi_csi_phy_clk ", + [86] = "arm_ring_osc_clk_out[9] ", + [85] = "arm_ring_osc_clk_out[8] ", + [84] = "co_tx_clk ", + [83] = "co_rx_clk ", + [82] = "cts_ge2d_clk ", + [81] = "cts_vapbclk ", + [80] = "rng_ring_osc_clk[3] ", + [79] = "rng_ring_osc_clk[2] ", + [78] = "rng_ring_osc_clk[1] ", + [77] = "rng_ring_osc_clk[0] ", + [76] = "arm_ring_osc_clk_out[7] ", + [75] = "cts_hevcf_clk ", + [74] = "arm_ring_osc_clk_out[6] ", + [73] = "cts_pwm_C_clk ", + [72] = "cts_pwm_D_clk ", + [71] = "cts_pwm_E_clk ", + [70] = "cts_pwm_F_clk ", + [69] = "cts_hdcp22_skpclk ", + [68] = "cts_hdcp22_esmclk ", + [67] = "cts_dsi_phy_clk ", + [66] = "cts_vid_lock_clk ", + [65] = "cts_spicc_0_clk ", + [64] = "cts_spicc_1_clk ", + [63] = "cts_dsi_meas_clk ", + [62] = "cts_hevcb_clk ", + [61] = "gpio_clk_msr ", + [60] = "arm_ring_osc_clk_out[5] ", + [59] = "cts_hcodec_clk ", + [58] = "cts_wave420l_bclk ", + [57] = "cts_wave420l_cclk ", + [56] = "cts_wave420l_aclk ", + [55] = "vid_pll_div_clk_out ", + [54] = "cts_vpu_clkc ", + [53] = "cts_sd_emmc_clk_A ", + [52] = "cts_sd_emmc_clk_B ", + [51] = "cts_sd_emmc_clk_C ", + [50] = "mp3_clk_out ", + [49] = "mp2_clk_out ", + [48] = "mp1_clk_out ", + [47] = "ddr_dpll_pt_clk ", + [46] = "cts_vpu_clk ", + [45] = "cts_pwm_A_clk ", + [44] = "cts_pwm_B_clk ", + [43] = "fclk_div5 ", + [42] = "mp0_clk_out ", + [41] = "mac_eth_rx_clk_rmii ", + [40] = "arm_ring_osc_clk_out[4] ", + [39] = "cts_bt656_clk0 ", + [38] = "cts_vdin_meas_clk ", + [37] = "cts_cdac_clk_c ", + [36] = "cts_hdmi_tx_pixel_clk ", + [35] = "cts_mali_clk ", + [34] = "eth_mppll_50m_ckout ", + [33] = "1'b0 ", + [32] = "cts_vdec_clk ", + [31] = "mpll_clk_test_out ", + [30] = "pcie_clk_inn ", + [29] = "pcie_clk_inp ", + [28] = "cts_sar_adc_clk ", + [27] = "co_clkin_to_mac ", + [26] = "sc_clk_int ", + [25] = "cts_eth_clk_rmii ", + [24] = "cts_eth_clk125Mhz ", + [23] = "mpll_clk_50m ", + [22] = "mac_eth_phy_ref_clk ", + [21] = "lcd_an_clk_ph3 ", + [20] = "rtc_osc_clk_out ", + [19] = "lcd_an_clk_ph2 ", + [18] = "sys_cpu_clk_div16 ", + [17] = "sys_pll_div16 ", + [16] = "cts_FEC_CLK_2 ", + [15] = "cts_FEC_CLK_1 ", + [14] = "cts_FEC_CLK_0 ", + [13] = "mod_tcon_clko ", + [12] = "hifi_pll_clk ", + [11] = "mac_eth_tx_clk ", + [10] = "cts_vdac_clk ", + [9] = "cts_encl_clk ", + [8] = "cts_encp_clk ", + [7] = "clk81 ", + [6] = "cts_enci_clk ", + [5] = "gp1_pll_clk ", + [4] = "gp0_pll_clk ", + [3] = "am_ring_osc_clk_out_ee[3]", + [2] = "am_ring_osc_clk_out_ee[2]", + [1] = "am_ring_osc_clk_out_ee[1]", + [0] = "am_ring_osc_clk_out_ee[0]", +}; + +static const struct meson_clkmsr_data sm1_data = { + .clk_table = sm1_table, + .table_size = ARRAY_SIZE(sm1_table), + .clk_msr_function = gxbb_clk_util_clk_msr, +}; + static const struct of_device_id meson_clkmsr_dt_match[] = { { .compatible = "amlogic, gxl_measure",}, { .compatible = "amlogic, m8b_measure",}, { .compatible = "amlogic,tl1-measure", .data = &tl1_data }, + { .compatible = "amlogic, sm1-measure", .data = &sm1_data }, {}, }; From fc2267b2101df335536f8ac9976eb321a35ebc0a Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Wed, 20 Mar 2019 15:33:25 +0800 Subject: [PATCH 0111/1060] clk: sm1: add clk measure driver [1/2] PD#SWPL-5407 Problem: sm1 support clk measure Solution: support clk measure Verify: ac200 Change-Id: I43c74375c16fee73037a1df4e4531c429e1229fd Signed-off-by: Shunzhou Jiang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 20f121e16243..5cde488a9144 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -534,7 +534,7 @@ }; meson_clk_msr { - compatible = "amlogic, gxl_measure"; + compatible = "amlogic, sm1-measure"; reg = <0x18004 0x4 0x1800c 0x4>; ringctrl = <0xff6345fc>; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 46b412ae9090..97bb11763ecb 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -534,7 +534,7 @@ }; meson_clk_msr { - compatible = "amlogic, gxl_measure"; + compatible = "amlogic, sm1-measure"; reg = <0x0 0x18004 0x0 0x4 0x0 0x1800c 0x0 0x4>; ringctrl = <0xff6345fc>; From c3ec245a76333fec7db236863113d23271f7e83a Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Fri, 22 Mar 2019 19:09:42 +0800 Subject: [PATCH 0112/1060] clk: sm1: add sm1 special clk [1/1] PD#SWPL-5407 Problem: not include sm1 special defined clk Solution: add this clk Verify: sm1_skt Change-Id: Iaf20aebe377d077d95eb053f7eea99473e3ac45d Signed-off-by: Shunzhou Jiang --- drivers/amlogic/clk/g12a/g12a.c | 4 +- drivers/amlogic/clk/g12a/g12a.h | 4 + drivers/amlogic/clk/g12a/g12a_clk-pll.c | 113 ++++++------------ drivers/amlogic/clk/sm1/sm1.c | 39 +++++- include/dt-bindings/clock/amlogic,g12a-clkc.h | 9 +- 5 files changed, 86 insertions(+), 83 deletions(-) diff --git a/drivers/amlogic/clk/g12a/g12a.c b/drivers/amlogic/clk/g12a/g12a.c index ba683ead35fd..c9c8f3295fe2 100644 --- a/drivers/amlogic/clk/g12a/g12a.c +++ b/drivers/amlogic/clk/g12a/g12a.c @@ -175,8 +175,8 @@ static struct meson_clk_pll g12a_hifi_pll = { .shift = 16, .width = 2, }, - .rate_table = g12a_pll_rate_table, - .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .rate_table = g12a_hifi_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_hifi_pll_rate_table), .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "hifi_pll", diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h index 488d1f64a968..0329c8d9443c 100644 --- a/drivers/amlogic/clk/g12a/g12a.h +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -228,4 +228,8 @@ static const struct pll_rate_table g12a_pcie_pll_rate_table[] = { PLL_RATE(100000000, 150, 0, 9), { /* sentinel */ }, }; + +static const struct pll_rate_table g12a_hifi_pll_rate_table[] = { + PLL_RATE(666000000ULL, 222, 1, 3), /*DCO=5328M*/ +}; #endif /* __G12A_H */ diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 2b9a8e5ca0cd..f82d5938127e 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -64,19 +64,6 @@ #define G12A_PCIE_PLL_CNTL5 0x68000048 #define G12A_PCIE_PLL_CNTL5_ 0x68000068 -#define G12B_PCIE_PLL_CNTL0_0 0x28060464 -#define G12B_PCIE_PLL_CNTL0_1 0x38060464 -#define G12B_PCIE_PLL_CNTL0_2 0x3c060464 -#define G12B_PCIE_PLL_CNTL0_3 0x1c060464 -#define G12B_PCIE_PLL_CNTL1 0x00000000 -#define G12B_PCIE_PLL_CNTL2 0x00001100 -#define G12B_PCIE_PLL_CNTL2_ 0x00001000 -#define G12B_PCIE_PLL_CNTL3 0x10058e00 -#define G12B_PCIE_PLL_CNTL4 0x000100c0 -#define G12B_PCIE_PLL_CNTL4_ 0x008100c0 -#define G12B_PCIE_PLL_CNTL5 0x68000048 -#define G12B_PCIE_PLL_CNTL5_ 0x68000068 - #define G12A_SYS_PLL_CNTL1 0x00000000 #define G12A_SYS_PLL_CNTL2 0x00000000 #define G12A_SYS_PLL_CNTL3 0x48681c00 @@ -89,7 +76,7 @@ #define G12A_SYS1_PLL_CNTL4 0x88770290 #define G12A_SYS1_PLL_CNTL5 0x39272000 -#define G12A_GP0_PLL_CNTL1 0x00000000 +#define G12A_GP0_PLL_CNTL1 0x00007800 #define G12A_GP0_PLL_CNTL2 0x00000000 #define G12A_GP0_PLL_CNTL3 0x48681c00 #define G12A_GP0_PLL_CNTL4 0x33771290 @@ -271,66 +258,34 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, cntlbase = pll->base + p->reg_off; if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { - if ((get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) || - ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1))) { - writel(G12A_PCIE_PLL_CNTL0_0, - cntlbase + (unsigned long)(0*4)); - writel(G12A_PCIE_PLL_CNTL0_1, - cntlbase + (unsigned long)(0*4)); - writel(G12A_PCIE_PLL_CNTL1, - cntlbase + (unsigned long)(1*4)); - writel(G12A_PCIE_PLL_CNTL2, - cntlbase + (unsigned long)(2*4)); - writel(G12A_PCIE_PLL_CNTL3, - cntlbase + (unsigned long)(3*4)); - writel(G12A_PCIE_PLL_CNTL4, - cntlbase + (unsigned long)(4*4)); - writel(G12A_PCIE_PLL_CNTL5, - cntlbase + (unsigned long)(5*4)); - writel(G12A_PCIE_PLL_CNTL5_, - cntlbase + (unsigned long)(5*4)); - udelay(20); - writel(G12A_PCIE_PLL_CNTL4_, - cntlbase + (unsigned long)(4*4)); - udelay(10); - /*set pcie_apll_afc_start bit*/ - writel(G12A_PCIE_PLL_CNTL0_2, - cntlbase + (unsigned long)(0*4)); - writel(G12A_PCIE_PLL_CNTL0_3, - cntlbase + (unsigned long)(0*4)); - udelay(10); - writel(G12A_PCIE_PLL_CNTL2_, - cntlbase + (unsigned long)(2*4)); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12B) { - writel(G12B_PCIE_PLL_CNTL0_0, - cntlbase + (unsigned long)(0*4)); - writel(G12B_PCIE_PLL_CNTL0_1, - cntlbase + (unsigned long)(0*4)); - writel(G12B_PCIE_PLL_CNTL1, - cntlbase + (unsigned long)(1*4)); - writel(G12B_PCIE_PLL_CNTL2, - cntlbase + (unsigned long)(2*4)); - writel(G12B_PCIE_PLL_CNTL3, - cntlbase + (unsigned long)(3*4)); - writel(G12B_PCIE_PLL_CNTL4, - cntlbase + (unsigned long)(4*4)); - writel(G12B_PCIE_PLL_CNTL5, - cntlbase + (unsigned long)(5*4)); - writel(G12B_PCIE_PLL_CNTL5_, - cntlbase + (unsigned long)(5*4)); - udelay(20); - writel(G12B_PCIE_PLL_CNTL4_, - cntlbase + (unsigned long)(4*4)); - udelay(10); - /*set pcie_apll_afc_start bit*/ - writel(G12B_PCIE_PLL_CNTL0_2, - cntlbase + (unsigned long)(0*4)); - writel(G12B_PCIE_PLL_CNTL0_3, - cntlbase + (unsigned long)(0*4)); - udelay(10); - writel(G12B_PCIE_PLL_CNTL2_, - cntlbase + (unsigned long)(2*4)); - } + writel(G12A_PCIE_PLL_CNTL0_0, + cntlbase + (unsigned long)(0*4)); + writel(G12A_PCIE_PLL_CNTL0_1, + cntlbase + (unsigned long)(0*4)); + writel(G12A_PCIE_PLL_CNTL1, + cntlbase + (unsigned long)(1*4)); + writel(G12A_PCIE_PLL_CNTL2, + cntlbase + (unsigned long)(2*4)); + writel(G12A_PCIE_PLL_CNTL3, + cntlbase + (unsigned long)(3*4)); + writel(G12A_PCIE_PLL_CNTL4, + cntlbase + (unsigned long)(4*4)); + writel(G12A_PCIE_PLL_CNTL5, + cntlbase + (unsigned long)(5*4)); + writel(G12A_PCIE_PLL_CNTL5_, + cntlbase + (unsigned long)(5*4)); + udelay(20); + writel(G12A_PCIE_PLL_CNTL4_, + cntlbase + (unsigned long)(4*4)); + udelay(10); + /*set pcie_apll_afc_start bit*/ + writel(G12A_PCIE_PLL_CNTL0_2, + cntlbase + (unsigned long)(0*4)); + writel(G12A_PCIE_PLL_CNTL0_3, + cntlbase + (unsigned long)(0*4)); + udelay(10); + writel(G12A_PCIE_PLL_CNTL2_, + cntlbase + (unsigned long)(2*4)); goto OUT; } else if (!strcmp(clk_hw_get_name(hw), "sys_pll")) { writel((readl(cntlbase) | MESON_PLL_RESET) @@ -384,15 +339,15 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, } else if (!strcmp(clk_hw_get_name(hw), "hifi_pll")) { writel((readl(cntlbase) | MESON_PLL_RESET) & (~MESON_PLL_ENABLE), cntlbase); - writel(G12A_GP0_PLL_CNTL1, + writel(G12A_HIFI_PLL_CNTL1, cntlbase + (unsigned long)(1*4)); - writel(G12A_GP0_PLL_CNTL2, + writel(G12A_HIFI_PLL_CNTL2, cntlbase + (unsigned long)(2*4)); - writel(G12A_GP0_PLL_CNTL3, + writel(G12A_HIFI_PLL_CNTL3, cntlbase + (unsigned long)(3*4)); - writel(G12A_GP0_PLL_CNTL4, + writel(G12A_HIFI_PLL_CNTL4, cntlbase + (unsigned long)(4*4)); - writel(G12A_GP0_PLL_CNTL5, + writel(G12A_HIFI_PLL_CNTL5, cntlbase + (unsigned long)(5*4)); writel(G12A_PLL_CNTL6, cntlbase + (unsigned long)(6*4)); diff --git a/drivers/amlogic/clk/sm1/sm1.c b/drivers/amlogic/clk/sm1/sm1.c index 18698c42cf3c..0cb8fd2f75d6 100644 --- a/drivers/amlogic/clk/sm1/sm1.c +++ b/drivers/amlogic/clk/sm1/sm1.c @@ -176,7 +176,7 @@ static struct clk_mux sm1_dsu_pre_clk = { static struct clk_mux sm1_dsu_clk = { .reg = (void *)HHI_SYS_CPU_CLK_CNTL6, .mask = 0x1, - .shift = 11, + .shift = 27, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "dsu_clk", @@ -192,6 +192,24 @@ static struct meson_clk_pll *const sm1_clk_plls[] = { &sm1_gp1_pll, }; +static MESON_GATE(sm1_csi_dig, HHI_GCLK_MPEG1, 18); +static MESON_GATE(sm1_nna, HHI_GCLK_MPEG1, 19); +static MESON_GATE(sm1_parser1, HHI_GCLK_MPEG1, 28); +static MESON_GATE(sm1_csi_host, HHI_GCLK_MPEG2, 16); +static MESON_GATE(sm1_csi_adpat, HHI_GCLK_MPEG2, 17); +static MESON_GATE(sm1_temp_sensor, HHI_GCLK_MPEG2, 22); +static MESON_GATE(sm1_csi_phy, HHI_GCLK_MPEG2, 29); + +static struct clk_gate *sm1_clk_gates[] = { + &sm1_csi_dig, + &sm1_nna, + &sm1_parser1, + &sm1_csi_host, + &sm1_csi_adpat, + &sm1_temp_sensor, + &sm1_csi_phy, +}; + static struct clk_hw *sm1_clk_hws[] = { [CLKID_GP1_PLL - CLKID_SM1_ADD_BASE] = &sm1_gp1_pll.hw, [CLKID_DSU_PRE_SRC0 - CLKID_SM1_ADD_BASE] = @@ -211,6 +229,20 @@ static struct clk_hw *sm1_clk_hws[] = { [CLKID_DSU_PRE_CLK - CLKID_SM1_ADD_BASE] = &sm1_dsu_pre_clk.hw, [CLKID_DSU_CLK - CLKID_SM1_ADD_BASE] = &sm1_dsu_clk.hw, + [CLKID_CSI_DIG_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_dig.hw, + [CLKID_NNA_CLK - CLKID_SM1_ADD_BASE] = + &sm1_nna.hw, + [CLKID_PARSER1_CLK - CLKID_SM1_ADD_BASE] = + &sm1_parser1.hw, + [CLKID_CSI_HOST_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_host.hw, + [CLKID_CSI_ADPAT_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_adpat.hw, + [CLKID_TEMP_SENSOR_CLK - CLKID_SM1_ADD_BASE] = + &sm1_temp_sensor.hw, + [CLKID_CSI_PHY_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_phy.hw, }; static void __init sm1_clkc_init(struct device_node *np) @@ -244,6 +276,11 @@ static void __init sm1_clkc_init(struct device_node *np) + (unsigned long)sm1_dsu_pre_clk.reg; sm1_dsu_clk.reg = clk_base + (unsigned long)sm1_dsu_clk.reg; + + /* Populate base address for gates */ + for (i = 0; i < ARRAY_SIZE(sm1_clk_gates); i++) + sm1_clk_gates[i]->reg = clk_base + + (unsigned long)sm1_clk_gates[i]->reg; if (!clks) { clks = kzalloc(NR_CLKS*sizeof(struct clk *), GFP_KERNEL); if (!clks) { diff --git a/include/dt-bindings/clock/amlogic,g12a-clkc.h b/include/dt-bindings/clock/amlogic,g12a-clkc.h index 3e9d81e0a82d..4084205b8e30 100644 --- a/include/dt-bindings/clock/amlogic,g12a-clkc.h +++ b/include/dt-bindings/clock/amlogic,g12a-clkc.h @@ -304,8 +304,15 @@ #define CLKID_DSU_PRE_POST_MUX (CLKID_SM1_ADD_BASE + 7) #define CLKID_DSU_PRE_CLK (CLKID_SM1_ADD_BASE + 8) #define CLKID_DSU_CLK (CLKID_SM1_ADD_BASE + 9) +#define CLKID_CSI_DIG_CLK (CLKID_SM1_ADD_BASE + 10) +#define CLKID_NNA_CLK (CLKID_SM1_ADD_BASE + 11) +#define CLKID_PARSER1_CLK (CLKID_SM1_ADD_BASE + 12) +#define CLKID_CSI_HOST_CLK (CLKID_SM1_ADD_BASE + 13) +#define CLKID_CSI_ADPAT_CLK (CLKID_SM1_ADD_BASE + 14) +#define CLKID_TEMP_SENSOR_CLK (CLKID_SM1_ADD_BASE + 15) +#define CLKID_CSI_PHY_CLK (CLKID_SM1_ADD_BASE + 16) -#define CLKID_AO_BASE (CLKID_SM1_ADD_BASE + 10) +#define CLKID_AO_BASE (CLKID_SM1_ADD_BASE + 17) #define CLKID_AO_CLK81 (CLKID_AO_BASE + 0) #define CLKID_SARADC_MUX (CLKID_AO_BASE + 1) #define CLKID_SARADC_DIV (CLKID_AO_BASE + 2) From f0b50e854cf545c616f6d68d41a07cf5e6387751 Mon Sep 17 00:00:00 2001 From: Qianggui Song Date: Fri, 8 Mar 2019 15:40:42 +0800 Subject: [PATCH 0113/1060] irqchip: sm1 support double-edge gpio irq trigger [1/1] PD#SWPL-5395 Problem: sm1 support double-edge trigger, current code do not support. Solution: add relatvie bitmask to support this function. Verify: ptm & sm1_skt Change-Id: I48ebc9b38db868f946c49b6fd5f98d427b2669df Signed-off-by: Qianggui Song --- .../amlogic,meson-gpio-intc.txt | 1 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- drivers/amlogic/irqchip/irq-meson-gpio.c | 30 +++++++++++++++++-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt index 4dfe69f26186..3f305fdf4f94 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt @@ -19,6 +19,7 @@ Required properties: “amlogic,meson-g12a-gpio-intc†for G12A SoCs (S905D2, S905X2, S905Y2) “amlogic,meson-txl-gpio-intc†for TXL SoCs (T950, T952, T960, T962) “amlogic,meson-tl1-gpio-intc†for TL1 SoCs (T962X2) + “amlogic,meson-sm1-gpio-intc†for SM1 SoCs (S905D3, S905X3, S905Y3) - interrupt-parent : a phandle to the GIC the interrupts are routed to. Usually this is provided at the root level of the device tree as it is common to most of the SoC. diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 5cde488a9144..e1a5651c670e 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -524,7 +524,7 @@ gpio_intc: interrupt-controller@f080 { compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-g12a-gpio-intc"; + "amlogic,meson-sm1-gpio-intc"; reg = <0xf080 0x10>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 97bb11763ecb..92da5f6ccdbf 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -524,7 +524,7 @@ gpio_intc: interrupt-controller@f080 { compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-g12a-gpio-intc"; + "amlogic,meson-sm1-gpio-intc"; reg = <0x0 0xf080 0x0 0x10>; interrupt-controller; #interrupt-cells = <2>; diff --git a/drivers/amlogic/irqchip/irq-meson-gpio.c b/drivers/amlogic/irqchip/irq-meson-gpio.c index a875b218f026..d353df4abff9 100644 --- a/drivers/amlogic/irqchip/irq-meson-gpio.c +++ b/drivers/amlogic/irqchip/irq-meson-gpio.c @@ -40,11 +40,13 @@ #define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x))) #define REG_EDGE_POL_EDGE(x) BIT(x) #define REG_EDGE_POL_LOW(x) BIT(16 + (x)) +#define REG_EDGE_BOTH_EDGE(x) BIT(8 + (x)) #define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8) #define REG_FILTER_SEL_SHIFT(x) ((x) * 4) struct meson_gpio_irq_params { unsigned int nr_hwirq; + u8 support_double_edge; }; static const struct meson_gpio_irq_params meson8_params = { @@ -83,6 +85,11 @@ static const struct meson_gpio_irq_params tl1_params = { .nr_hwirq = 102, }; +static const struct meson_gpio_irq_params sm1_params = { + .nr_hwirq = 100, + .support_double_edge = 1, +}; + static const struct of_device_id meson_irq_gpio_matches[] = { { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, @@ -93,11 +100,13 @@ static const struct of_device_id meson_irq_gpio_matches[] = { { .compatible = "amlogic,meson-g12a-gpio-intc", .data = &g12a_params }, { .compatible = "amlogic,meson-txl-gpio-intc", .data = &txl_params }, { .compatible = "amlogic,meson-tl1-gpio-intc", .data = &tl1_params }, + { .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params }, { } }; struct meson_gpio_irq_controller { unsigned int nr_hwirq; + u8 support_double_edge; void __iomem *base; u32 channel_irqs[NUM_CHANNEL]; DECLARE_BITMAP(channel_map, NUM_CHANNEL); @@ -200,8 +209,16 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl, */ type &= IRQ_TYPE_SENSE_MASK; - if (type == IRQ_TYPE_EDGE_BOTH) - return -EINVAL; + if (type == IRQ_TYPE_EDGE_BOTH) { + if (!ctl->support_double_edge) + return -EINVAL; + val |= REG_EDGE_BOTH_EDGE(idx); + spin_lock(&ctl->lock); + meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, + REG_EDGE_BOTH_EDGE(idx), val); + spin_unlock(&ctl->lock); + return 0; + } if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) val |= REG_EDGE_POL_EDGE(idx); @@ -211,6 +228,14 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl, spin_lock(&ctl->lock); + /* Double-edge has priority over all others. If a double-edge gpio + * changes to another method's, we need to reset the corresponding bit + * of double-edge register. + */ + if (ctl->support_double_edge) + meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, + REG_EDGE_BOTH_EDGE(idx), 0); + meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, REG_EDGE_POL_MASK(idx), val); @@ -369,6 +394,7 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node, params = match->data; ctl->nr_hwirq = params->nr_hwirq; + ctl->support_double_edge = params->support_double_edge; ret = of_property_read_variable_u32_array(node, "amlogic,channel-interrupts", From fde8e31088c60c538dc3ac59e95ed71f2f2828dd Mon Sep 17 00:00:00 2001 From: Huan Biao Date: Tue, 19 Mar 2019 15:53:11 +0800 Subject: [PATCH 0114/1060] thermal: dts: enable sm1 thermal [1/1] PD#SWPL-6071 Problem: enable thermal for sm1 Solution: enable thermal for sm1 Verify: test pass on sm1_skt Change-Id: I54fd4431bec1a48135da0b0b9c05cd53d4055a56 Signed-off-by: Huan Biao --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 8 ++++---- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index e1a5651c670e..18597b5ba10a 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1593,7 +1593,7 @@ }; meson_cooldev: meson-cooldev@0 { - status = "disabled"; + status = "okay"; compatible = "amlogic, meson-cooldev"; device_name = "mcooldev"; cooling_devices { @@ -1695,9 +1695,9 @@ }; }; ddr_thermal: ddr_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <2150>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 92da5f6ccdbf..221bb694cb44 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -476,7 +476,7 @@ p_tsensor: p_tsensor@ff634594 { compatible = "amlogic, r1p1-tsensor"; device_name = "meson-pthermal"; - status = "disabled"; + status = "okay"; reg = <0x0 0xff634800 0x0 0x50>, <0x0 0xff800268 0x0 0x4>; cal_type = <0x1>; @@ -494,7 +494,7 @@ d_tsensor: d_tsensor@ff800228 { compatible = "amlogic, r1p1-tsensor"; device_name = "meson-dthermal"; - status = "disabled"; + status = "okay"; reg = <0x0 0xff634c00 0x0 0x50>, <0x0 0xff800230 0x0 0x4>; cal_type = <0x1>; @@ -1593,7 +1593,7 @@ }; meson_cooldev: meson-cooldev@0 { - status = "disabled"; + status = "okay"; compatible = "amlogic, meson-cooldev"; device_name = "mcooldev"; cooling_devices { @@ -1695,9 +1695,9 @@ }; }; ddr_thermal: ddr_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <2150>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { From cb5e04d84f632a02df3ad22c49e6cc70394fd49d Mon Sep 17 00:00:00 2001 From: Qiang Li Date: Tue, 19 Mar 2019 14:44:14 +0800 Subject: [PATCH 0115/1060] sdcard: sm1: add sdcard support. [1/2] PD#SWPL-5409 Problem: sm1 sdcard failed. Solution: change sm1 sdcard high speed mode co_phase. Verify: SM1_AC200 Change-Id: I295c6fac2594e611bf278f83a97bb503fb8bb13b Signed-off-by: Qiang Li Signed-off-by: Jianxiong Pan --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 90 ++----------------- arch/arm/boot/dts/amlogic/sm1_pxp.dts | 10 +-- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 31 +------ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 4 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 90 ++----------------- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 14 +-- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 35 +------- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 35 +------- drivers/amlogic/mmc/aml_sd_emmc.c | 29 ++++++ include/linux/amlogic/sd.h | 1 + 10 files changed, 58 insertions(+), 281 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 18597b5ba10a..702c8d22b981 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1352,7 +1352,7 @@ sd_emmc_c: emmc@ffe07000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; + compatible = "amlogic, meson-mmc-sm1"; reg = <0xffe07000 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; @@ -1391,9 +1391,9 @@ }; }; - sd_emmc_b1:sd1@ffe05000 { + sd_emmc_b:sd@ffe05000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; + compatible = "amlogic, meson-mmc-sm1"; reg = <0xffe05000 0x800>; interrupts = <0 190 1>; @@ -1447,88 +1447,10 @@ }; }; - sd_emmc_b2:sd2@ffe05000 { - status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; - reg = <0xffe05000 0x800>; - interrupts = <0 190 4>; - - pinctrl-names = "sd_all_pins", - "sd_clk_cmd_pins", - "sd_1bit_pins", - "sd_clk_cmd_uart_pins", - "sd_1bit_uart_pins", - "sd_to_ao_uart_pins", - "ao_to_sd_uart_pins", - "sd_to_ao_jtag_pins", - "ao_to_sd_jtag_pins", - "sdio_noclr_all_pins", - "sdio_noclr_clk_cmd_pins", - "sdio_all_pins", - "sdio_clk_cmd_pins"; - pinctrl-0 = <&sdio_x_clr_pins &sd_all_pins>; - pinctrl-1 = <&sdio_x_clr_pins &sd_clk_cmd_pins>; - pinctrl-2 = <&sdio_x_clr_pins &sd_1bit_pins>; - pinctrl-3 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins - &sd_clk_cmd_pins &ao_to_sd_uart_pins>; - pinctrl-4 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins - &sd_1bit_pins &ao_to_sd_uart_pins>; - pinctrl-5 = <&sdio_x_clr_pins - &sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-6 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins - &sd_clr_noall_pins &ao_to_sd_uart_pins>; - pinctrl-7 = <&sdio_x_en_pins - &sd_clr_all_pins &sd_to_ao_uart_pins>; - pinctrl-8 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins - &sd_clr_noall_pins &ao_to_sd_uart_pins>; - pinctrl-9 = <&sd_clr_noall_pins - &sdio_x_en_pins &sdio_x_all_pins>; - pinctrl-10 = <&sd_clr_noall_pins - &sdio_x_en_pins &sdio_x_clk_cmd_pins>; - pinctrl-11 = <&sd_clr_all_pins - &sdio_x_en_pins &sdio_x_all_pins>; - pinctrl-12 = <&sd_clr_all_pins - &sdio_x_en_pins &sdio_x_clk_cmd_pins>; - - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - disable-wp; - sd { - pinname = "sd"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; - jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; - gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; - card_type = <5>; - /* 3:sdio device(ie:sdio-wifi), - * 5:NON sdio device(means sd/mmc card) - */ - }; - - sdio { - pinname = "sdio"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - card_type = <3>; - /* 3:sdio device(ie:sdio-wifi), - * 5:NON sdio device(means sd/mmc card) - */ - }; - }; sd_emmc_a:sdio@ffe03000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; + compatible = "amlogic, meson-mmc-sm1"; reg = <0xffe03000 0x800>; interrupts = <0 189 4>; @@ -1552,13 +1474,11 @@ sdio { pinname = "sdio"; ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - /* max_req_size = <0x20000>; */ /**128KB*/ - max_req_size = <0x400>; + max_req_size = <0x20000>; /**128KB*/ card_type = <3>; /* 3:sdio device(ie:sdio-wifi), * 4:SD combo (IO+mem) card */ - dmode = "pio"; }; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index 78cdd87d2b59..3aeb950847b1 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -705,18 +705,12 @@ */ tv_bit_mode = <1>; }; -&sd_emmc_b1 { +&sd_emmc_b { status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_PM_KEEP_POWER", - "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + "MMC_CAP_SD_HIGHSPEED"; f_min = <400000>; f_max = <200000000>; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 3e83a30603a1..64bb3293b000 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1470,8 +1470,8 @@ }; }; -&sd_emmc_b1 { - status = "disabled"; +&sd_emmc_b { + status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", @@ -1481,33 +1481,6 @@ }; }; -&sd_emmc_b2 { - status = "disabled"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED"; - - f_min = <400000>; - f_max = <50000000>; - }; - - sdio { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_CAP_UHS_SDR104", - "MMC_PM_KEEP_POWER", - "MMC_CAP_SDIO_IRQ"; - - f_min = <400000>; - f_max = <200000000>; - }; -}; &sd_emmc_a { status = "disabled"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 03bcbba7abe9..0161331b64f8 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1470,8 +1470,8 @@ }; }; -&sd_emmc_b1 { - status = "disabled"; +&sd_emmc_b { + status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 221bb694cb44..01fbf94c5c91 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1352,7 +1352,7 @@ sd_emmc_c: emmc@ffe07000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; + compatible = "amlogic, meson-mmc-sm1"; reg = <0x0 0xffe07000 0x0 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; @@ -1391,9 +1391,9 @@ }; }; - sd_emmc_b1:sd1@ffe05000 { + sd_emmc_b:sd@ffe05000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; + compatible = "amlogic, meson-mmc-sm1"; reg = <0x0 0xffe05000 0x0 0x800>; interrupts = <0 190 1>; @@ -1447,88 +1447,10 @@ }; }; - sd_emmc_b2:sd2@ffe05000 { - status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; - reg = <0x0 0xffe05000 0x0 0x800>; - interrupts = <0 190 4>; - - pinctrl-names = "sd_all_pins", - "sd_clk_cmd_pins", - "sd_1bit_pins", - "sd_clk_cmd_uart_pins", - "sd_1bit_uart_pins", - "sd_to_ao_uart_pins", - "ao_to_sd_uart_pins", - "sd_to_ao_jtag_pins", - "ao_to_sd_jtag_pins", - "sdio_noclr_all_pins", - "sdio_noclr_clk_cmd_pins", - "sdio_all_pins", - "sdio_clk_cmd_pins"; - pinctrl-0 = <&sdio_x_clr_pins &sd_all_pins>; - pinctrl-1 = <&sdio_x_clr_pins &sd_clk_cmd_pins>; - pinctrl-2 = <&sdio_x_clr_pins &sd_1bit_pins>; - pinctrl-3 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins - &sd_clk_cmd_pins &ao_to_sd_uart_pins>; - pinctrl-4 = <&sdio_x_clr_pins &sd_to_ao_uart_clr_pins - &sd_1bit_pins &ao_to_sd_uart_pins>; - pinctrl-5 = <&sdio_x_clr_pins - &sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-6 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins - &sd_clr_noall_pins &ao_to_sd_uart_pins>; - pinctrl-7 = <&sdio_x_en_pins - &sd_clr_all_pins &sd_to_ao_uart_pins>; - pinctrl-8 = <&sdio_x_en_pins &sd_to_ao_uart_clr_pins - &sd_clr_noall_pins &ao_to_sd_uart_pins>; - pinctrl-9 = <&sd_clr_noall_pins - &sdio_x_en_pins &sdio_x_all_pins>; - pinctrl-10 = <&sd_clr_noall_pins - &sdio_x_en_pins &sdio_x_clk_cmd_pins>; - pinctrl-11 = <&sd_clr_all_pins - &sdio_x_en_pins &sdio_x_all_pins>; - pinctrl-12 = <&sd_clr_all_pins - &sdio_x_en_pins &sdio_x_clk_cmd_pins>; - - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - disable-wp; - sd { - pinname = "sd"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; - jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; - gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; - card_type = <5>; - /* 3:sdio device(ie:sdio-wifi), - * 5:NON sdio device(means sd/mmc card) - */ - }; - - sdio { - pinname = "sdio"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - card_type = <3>; - /* 3:sdio device(ie:sdio-wifi), - * 5:NON sdio device(means sd/mmc card) - */ - }; - }; sd_emmc_a:sdio@ffe03000 { status = "disabled"; - compatible = "amlogic, meson-mmc-g12a"; + compatible = "amlogic, meson-mmc-sm1"; reg = <0x0 0xffe03000 0x0 0x800>; interrupts = <0 189 4>; @@ -1552,13 +1474,11 @@ sdio { pinname = "sdio"; ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - /* max_req_size = <0x20000>; */ /**128KB*/ - max_req_size = <0x400>; + max_req_size = <0x20000>; /**128KB*/ card_type = <3>; /* 3:sdio device(ie:sdio-wifi), * 4:SD combo (IO+mem) card */ - dmode = "pio"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index 493771e9062e..ab80a59aec2a 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -706,24 +706,18 @@ */ tv_bit_mode = <1>; }; -&sd_emmc_b1 { + +&sd_emmc_b { status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_PM_KEEP_POWER", - "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + "MMC_CAP_SD_HIGHSPEED"; f_min = <400000>; - f_max = <200000000>; + f_max = <50000000>; }; }; - &defendkey { status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index dbf8a837568f..e1c072131fb5 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1461,15 +1461,15 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; + /*caps2 = "MMC_CAP2_HS200";*/ /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <200000000>; + f_max = <50000000>; }; }; -&sd_emmc_b1 { - status = "disabled"; +&sd_emmc_b { + status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", @@ -1479,33 +1479,6 @@ }; }; -&sd_emmc_b2 { - status = "disabled"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED"; - - f_min = <400000>; - f_max = <50000000>; - }; - - sdio { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_CAP_UHS_SDR104", - "MMC_PM_KEEP_POWER", - "MMC_CAP_SDIO_IRQ"; - - f_min = <400000>; - f_max = <200000000>; - }; -}; &sd_emmc_a { status = "disabled"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 0ea4e99fe1ab..59c68b89a515 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1461,15 +1461,15 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; + /*caps2 = "MMC_CAP2_HS200";*/ /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <200000000>; + f_max = <50000000>; }; }; -&sd_emmc_b1 { - status = "disabled"; +&sd_emmc_b { + status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", @@ -1479,33 +1479,6 @@ }; }; -&sd_emmc_b2 { - status = "disabled"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED"; - - f_min = <400000>; - f_max = <50000000>; - }; - - sdio { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_CAP_UHS_SDR104", - "MMC_PM_KEEP_POWER", - "MMC_CAP_SDIO_IRQ"; - - f_min = <400000>; - f_max = <200000000>; - }; -}; &sd_emmc_a { status = "disabled"; diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 9541344ba9ad..7c05f5d1f93b 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3641,6 +3641,31 @@ static struct meson_mmc_data mmc_data_tl1 = { .sdmmc.sdr104.core_phase = 2, }; +static struct meson_mmc_data mmc_data_sm1 = { + .chip_type = MMC_CHIP_SM1, + .port_a_base = 0xffe03000, + .port_b_base = 0xffe05000, + .port_c_base = 0xffe07000, + .pinmux_base = 0xff634400, + .clksrc_base = 0xff63c000, + .ds_pin_poll = 0x3a, + .ds_pin_poll_en = 0x48, + .ds_pin_poll_bit = 13, + .sdmmc.init.core_phase = 3, + .sdmmc.init.tx_phase = 0, + .sdmmc.init.rx_phase = 0, + .sdmmc.calc.core_phase = 0, + .sdmmc.calc.tx_phase = 2, + .sdmmc.hs.core_phase = 3, + .sdmmc.ddr.core_phase = 2, + .sdmmc.ddr.tx_phase = 0, + .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.tx_phase = 0, + .sdmmc.hs4.tx_delay = 0, + .sdmmc.sd_hs.core_phase = 3, + .sdmmc.sdr104.core_phase = 2, + .sdmmc.sdr104.tx_phase = 0, +}; static const struct of_device_id meson_mmc_of_match[] = { { .compatible = "amlogic, meson-mmc-gxbb", @@ -3694,6 +3719,10 @@ static const struct of_device_id meson_mmc_of_match[] = { .compatible = "amlogic, meson-mmc-g12b-a", .data = &mmc_data_g12b_a, }, + { + .compatible = "amlogic, meson-mmc-sm1", + .data = &mmc_data_sm1, + }, {} }; diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 245866dd711c..bcd815bb69b2 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -192,6 +192,7 @@ enum mmc_chip_e { MMC_CHIP_GXLX2 = 0x2a, MMC_CHIP_TL1 = 0X2b, MMC_CHIP_G12B = 0x29b, + MMC_CHIP_SM1 = 0X2C, }; struct mmc_phase { From 4f5bcc03d3ecb004af98fb67fbc1f8fba49c149b Mon Sep 17 00:00:00 2001 From: Qiang Li Date: Wed, 20 Mar 2019 11:15:04 +0800 Subject: [PATCH 0116/1060] sdcard: sm1: fix dts problem. [2/2] PD#SWPL-5409 Problem: dts compile error. Solution: delect sd_emmc_b2 node. Verify: SM1_AC200 Change-Id: Ib3965a083fdc3f95a5c0a9de37bff98c898d0993 Signed-off-by: Qiang Li --- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 28 -------------------- 1 file changed, 28 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 0161331b64f8..91a6eabb22e3 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1481,34 +1481,6 @@ }; }; -&sd_emmc_b2 { - status = "disabled"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED"; - - f_min = <400000>; - f_max = <50000000>; - }; - - sdio { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_CAP_UHS_SDR104", - "MMC_PM_KEEP_POWER", - "MMC_CAP_SDIO_IRQ"; - - f_min = <400000>; - f_max = <200000000>; - }; -}; - &sd_emmc_a { status = "disabled"; sdio { From 6e654b3a51284db1e131026b81e7dc9284396222 Mon Sep 17 00:00:00 2001 From: Qiang Li Date: Wed, 20 Mar 2019 23:21:45 +0800 Subject: [PATCH 0117/1060] dts: sm1: dts enable sdio node. [1/1] PD#SWPL-5409 Problem: dts sdio node disable. Solution: dts enable sdio node. Verify: SM1_AC200 Change-Id: Ifd33de0f08adb202af07eee13db8894fdf0c77fa Signed-off-by: Qiang Li --- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 64bb3293b000..dde4fb24fcbf 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1483,7 +1483,7 @@ &sd_emmc_a { - status = "disabled"; + status = "okay"; sdio { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 91a6eabb22e3..859dc4038b23 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1482,7 +1482,7 @@ }; &sd_emmc_a { - status = "disabled"; + status = "okay"; sdio { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index e1c072131fb5..5967c5bae0ab 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1481,7 +1481,7 @@ &sd_emmc_a { - status = "disabled"; + status = "okay"; sdio { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 59c68b89a515..a5624db65931 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1481,7 +1481,7 @@ &sd_emmc_a { - status = "disabled"; + status = "okay"; sdio { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", From eaf6e42abdece80fc2c3364347d9aa778999fb58 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Tue, 19 Mar 2019 19:26:04 +0800 Subject: [PATCH 0118/1060] media: add codec support for SM1 [1/1] PD#SWPL-2867 Problem: bringup codec for SM1. Solution: add the register ops for SM1 Verify: Verified on SM1-AC200 Change-Id: I31db8f0b5816d67664e8161b3dc73574909afe31 Signed-off-by: Jian Cao --- drivers/amlogic/media/common/arch/registers/register_ops_m8.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c index 2d51a44ba976..d8372c8a4eb6 100644 --- a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c +++ b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c @@ -32,6 +32,7 @@ MESON_CPU_MAJOR_ID_G12A, \ MESON_CPU_MAJOR_ID_G12B, \ MESON_CPU_MAJOR_ID_TL1, \ + MESON_CPU_MAJOR_ID_SM1, \ 0} #define REGISTER_FOR_GXCPU {\ MESON_CPU_MAJOR_ID_GXBB, \ @@ -44,6 +45,7 @@ MESON_CPU_MAJOR_ID_G12A, \ MESON_CPU_MAJOR_ID_G12B, \ MESON_CPU_MAJOR_ID_TL1, \ + MESON_CPU_MAJOR_ID_SM1, \ 0} int codec_apb_read(unsigned int reg) { From 2556b66fdace39373128cce0c9cb287afad7220e Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Wed, 20 Mar 2019 10:36:09 +0800 Subject: [PATCH 0119/1060] osd: add osd SM1 feature [1/1] PD#SWPL-6106 Problem: bring up osd for SM1 Solution: add osd SM1 feature Verify: Verified on SM1-AC200 Change-Id: I5cba13f7539e48f6cba1ca0fb3abcaad2ba8494d Signed-off-by: Pengcheng Chen --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 4 ++-- drivers/amlogic/media/osd/osd.h | 1 + drivers/amlogic/media/osd/osd_fb.c | 19 +++++++++++++++++++ drivers/amlogic/media/osd/osd_hw.c | 7 +++++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 702c8d22b981..62bc499adae1 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1322,8 +1322,8 @@ interrupt-names = "rdma"; }; - meson_fb: meson-fb { - compatible = "amlogic, meson-g12a"; + meson_fb: fb { + compatible = "amlogic, meson-sm1"; memory-region = <&logo_reserved>; dev_name = "meson-fb"; status = "disable"; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 01fbf94c5c91..be404101fee9 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1322,8 +1322,8 @@ interrupt-names = "rdma"; }; - meson_fb: meson-fb { - compatible = "amlogic, meson-g12a"; + meson_fb: fb { + compatible = "amlogic, meson-sm1"; memory-region = <&logo_reserved>; dev_name = "meson-fb"; status = "disable"; diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 0857e8fc7ab2..cc2e8fbe7cfc 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -277,6 +277,7 @@ enum cpuid_type_e { __MESON_CPU_MAJOR_ID_G12A, __MESON_CPU_MAJOR_ID_G12B, __MESON_CPU_MAJOR_ID_TL1, + __MESON_CPU_MAJOR_ID_SM1, __MESON_CPU_MAJOR_ID_UNKNOWN, }; diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index c4c434eeb240..724cf8ecf064 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -4080,6 +4080,21 @@ static struct osd_device_data_s osd_tl1 = { .has_viu2 = 1, }; +static struct osd_device_data_s osd_sm1 = { + .cpu_id = __MESON_CPU_MAJOR_ID_SM1, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 1, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, +}; + static const struct of_device_id meson_fb_dt_match[] = { { .compatible = "amlogic, meson-gxbb", @@ -4126,6 +4141,10 @@ static const struct of_device_id meson_fb_dt_match[] = { .compatible = "amlogic, meson-tl1", .data = &osd_tl1, }, + { + .compatible = "amlogic, meson-sm1", + .data = &osd_sm1, + }, {}, }; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index a0b6c476b7c2..ba70c9b8319b 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1679,6 +1679,7 @@ static u32 osd_get_hw_reset_flag(void) case __MESON_CPU_MAJOR_ID_G12A: case __MESON_CPU_MAJOR_ID_G12B: case __MESON_CPU_MAJOR_ID_TL1: + case __MESON_CPU_MAJOR_ID_SM1: { int i, afbc_enable = 0; @@ -5051,7 +5052,8 @@ static void osd_update_disp_osd_rotate(u32 index) const struct vinfo_s *vinfo; int out_y_crop_start, out_y_crop_end; - if (osd_hw.osd_meson_dev.cpu_id < __MESON_CPU_MAJOR_ID_G12B) + if (osd_hw.osd_meson_dev.cpu_id < __MESON_CPU_MAJOR_ID_G12B || + osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_SM1) return; src_fmt = get_viu2_src_format(); src_data.x = 0; @@ -8400,7 +8402,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.hw_rdma_en = 1; } else if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) { osd_hw.hw_cursor_en = 0; - osd_hw.hw_rdma_en = 1; + if (osd_hw.osd_meson_dev.has_rdma) + osd_hw.hw_rdma_en = 1; /* g12a and g12b need delay */ supsend_delay = 50; } From e64430f9f4ef0d59f6824cfa30f31934403c7408 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Mon, 4 Mar 2019 18:57:46 +0800 Subject: [PATCH 0120/1060] hdmitx: hdmitx bringup for sm1 [1/1] PD#SWPL-5408 Problem: hdmitx bringup for sm1 Solution: hdmitx bringup for sm1, add chip id Verify: sm1 ptm Change-Id: I804dec4b743c660b180b7061d110ab76b9ec0468 Signed-off-by: Yi Zhou --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 8 ++++---- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 8 ++++---- .../amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 8 ++++++++ .../amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h | 7 +++++++ drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c | 6 ++++++ drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c | 3 +++ include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h | 1 + 7 files changed, 33 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 62bc499adae1..b52ed4d16a28 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1085,11 +1085,11 @@ /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ interrupts = <0 57 1>; interrupt-names = "hdmitx_hpd"; - /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM - * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD - * 10:G12A + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B 12:SM1 */ - ic_type = <10>; + ic_type = <12>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index be404101fee9..ba5246620ff5 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1085,11 +1085,11 @@ /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ interrupts = <0 57 1>; interrupt-names = "hdmitx_hpd"; - /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM - * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD - * 10:G12A + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B 12:SM1 */ - ic_type = <10>; + ic_type = <12>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 26aa5cb9fae4..775e291de9f3 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -150,6 +150,7 @@ int hdmitx_hpd_hw_op(enum hpd_op cmd) return hdmitx_hpd_hw_op_txlx(cmd); case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: return hdmitx_hpd_hw_op_g12a(cmd); default: break; @@ -173,6 +174,7 @@ int read_hpd_gpio(void) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: return read_hpd_gpio_txlx(); default: break; @@ -196,6 +198,7 @@ int hdmitx_ddc_hw_op(enum ddc_op cmd) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: return hdmitx_ddc_hw_op_txlx(cmd); default: break; @@ -419,6 +422,7 @@ static unsigned int hdmitx_get_format(void) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: ret = hdmitx_get_format_txlx(); break; case MESON_CPU_ID_GXBB: @@ -465,6 +469,7 @@ void hdmitx_sys_reset(void) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: hdmitx_sys_reset_txlx(); break; case MESON_CPU_ID_GXBB: @@ -2008,6 +2013,7 @@ static void set_phy_by_mode(unsigned int mode) switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: switch (mode) { case 1: /* 5.94/4.5/3.7Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65c4); @@ -2883,6 +2889,7 @@ static int hdmitx_cntl(struct hdmitx_dev *hdev, unsigned int cmd, switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 1, 29, 1); udelay(50); hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0, 28, 1); @@ -4366,6 +4373,7 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: for (i = 0; i < 4; i++) { hd_write_reg(P_HHI_HDMI_PHY_CNTL1, 0x0390000f); hd_write_reg(P_HHI_HDMI_PHY_CNTL1, 0x0390000e); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h index 596292525948..d5b95e8883c6 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h @@ -79,6 +79,10 @@ int hdmitx_hdcp_opr(unsigned int val); /* intr_maskn: MASK_N, one bit per interrupt source. * 1=Enable interrupt source; 0=Disable interrupt source. Default 0. + * [ 8] hdcp_topology_err + * [ 7] rxsense_fall + * [ 6] rxsense_rise + * [ 5] err_i2c_timeout * [ 4] hdcp22_rndnum_err * [ 3] nonce_rfrsh_rise * [ 2] hpd_fall_intr @@ -185,6 +189,7 @@ int hdmitx_hdcp_opr(unsigned int val); #define HDMITX_TOP_I2C_BUSY_CNT_STAT (TOP_OFFSET_MASK + 0x029) #define HDMITX_TOP_HDCP22_BSOD (TOP_SEC_OFFSET_MASK + 0x02A) #define HDMITX_TOP_DDC_CNTL (TOP_OFFSET_MASK + 0x02B) +#define HDMITX_TOP_DISABLE_NULL (TOP_OFFSET_MASK + 0x030) #define HDMITX_TOP_REVOCMEM_ADDR_S (TOP_OFFSET_MASK + 0x2000 >> 2) #define HDMITX_TOP_REVOCMEM_ADDR_E (TOP_OFFSET_MASK + 0x365E >> 2) @@ -921,6 +926,8 @@ int hdmitx_hdcp_opr(unsigned int val); /* [ 1] Rsvd for read-only ksv_mem_access */ /* [ 0] ksv_mem_request */ #define HDMITX_DWC_A_KSVMEMCTRL (DWC_OFFSET_MASK + 0x5016) +#define HDMITX_DWC_A_BSTATUS_HI (DWC_OFFSET_MASK + 0x5017) +#define HDMITX_DWC_A_BSTATUS_LO (DWC_OFFSET_MASK + 0x5018) #define HDMITX_DWC_HDCP_BSTATUS_0 (TOP_OFFSET_MASK + 0x2000) #define HDMITX_DWC_HDCP_BSTATUS_1 (TOP_OFFSET_MASK + 0x2001) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c index 7b4613a7c319..d215ca4e73a2 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c @@ -165,6 +165,7 @@ void hdmitx_set_cts_hdcp22_clk(struct hdmitx_dev *hdev) case MESON_CPU_ID_GXM: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: default: hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); break; @@ -441,6 +442,7 @@ static void set_hpll_clk_out(unsigned int clk) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_g12a_hpll_clk_out(frac_rate, clk); break; default: @@ -458,6 +460,7 @@ static void set_hpll_sspll(enum hdmi_vic vic) switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_sspll_g12a(vic); break; case MESON_CPU_ID_GXBB: @@ -503,6 +506,7 @@ static void set_hpll_od1(unsigned int div) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_od1_g12a(div); break; default: @@ -541,6 +545,7 @@ static void set_hpll_od2(unsigned int div) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_od2_g12a(div); break; default: @@ -579,6 +584,7 @@ static void set_hpll_od3(unsigned int div) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_od3_g12a(div); break; default: diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c index cb5f40b2e36f..7440ed5f1511 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c @@ -165,6 +165,7 @@ void init_reg_map(unsigned int type) switch (type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: map = reg_maps_g12a; for (i = 0; i < REG_IDX_END; i++) { map[i].p = ioremap(map[i].phy_addr, map[i].size); @@ -252,6 +253,7 @@ unsigned int hd_read_reg(unsigned int addr) case MESON_CPU_ID_GXM: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: default: val = readl(TO_PMAP_ADDR(addr)); break; @@ -301,6 +303,7 @@ void hd_write_reg(unsigned int addr, unsigned int val) case MESON_CPU_ID_GXM: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: default: writel(val, TO_PMAP_ADDR(addr)); break; diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 0d76db1d1152..7c8082885d7a 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -42,6 +42,7 @@ #define MESON_CPU_ID_TXHD 9 #define MESON_CPU_ID_G12A 10 #define MESON_CPU_ID_G12B 11 +#define MESON_CPU_ID_SM1 12 /***************************** From 8b59174fecfd809126b2c73b3b9265fd3f9ed95c Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Mon, 18 Mar 2019 16:53:42 +0800 Subject: [PATCH 0121/1060] dv: dv bringup for sm1 [1/1] PD#SWPL-5408 Problem: dv bringup for sm1 Solution: dv bringup for sm1, add chip id Verify: sm1 ptm Change-Id: Ifbf175cb5c495949f5e4bd02b98690f08239a735 Signed-off-by: Yi Zhou --- arch/arm/boot/dts/amlogic/sm1_pxp.dts | 2 +- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- .../amlogic/media/enhancement/amdolby_vision/amdolby_vision.c | 4 ++++ 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index 3aeb950847b1..2a9a9293109b 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -237,7 +237,7 @@ tx_op_color_primary = <0>; }; amdolby_vision { - compatible = "amlogic, dolby_vision_g12a"; + compatible = "amlogic, dolby_vision_sm1"; dev_name = "aml_amdolby_vision_driver"; status = "okay"; tv_mode = <0>;/*1:enabel ;0:disable*/ diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index dde4fb24fcbf..6437c2c316cc 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -514,7 +514,7 @@ }; amdolby_vision { - compatible = "amlogic, dolby_vision_g12a"; + compatible = "amlogic, dolby_vision_sm1"; dev_name = "aml_amdolby_vision_driver"; status = "okay"; tv_mode = <0>;/*1:enabel ;0:disable*/ diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 859dc4038b23..e2403fb1872f 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -514,7 +514,7 @@ }; amdolby_vision { - compatible = "amlogic, dolby_vision_g12a"; + compatible = "amlogic, dolby_vision_sm1"; dev_name = "aml_amdolby_vision_driver"; status = "okay"; tv_mode = <0>;/*1:enabel ;0:disable*/ diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index ab80a59aec2a..727d2031e884 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -238,7 +238,7 @@ tx_op_color_primary = <0>; }; amdolby_vision { - compatible = "amlogic, dolby_vision_g12a"; + compatible = "amlogic, dolby_vision_sm1"; dev_name = "aml_amdolby_vision_driver"; status = "okay"; tv_mode = <0>;/*1:enabel ;0:disable*/ diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 5967c5bae0ab..907c4ca716ed 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -512,7 +512,7 @@ }; amdolby_vision { - compatible = "amlogic, dolby_vision_g12a"; + compatible = "amlogic, dolby_vision_sm1"; dev_name = "aml_amdolby_vision_driver"; status = "okay"; tv_mode = <0>;/*1:enabel ;0:disable*/ diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index a5624db65931..9c2c69cc5ff1 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -512,7 +512,7 @@ }; amdolby_vision { - compatible = "amlogic, dolby_vision_g12a"; + compatible = "amlogic, dolby_vision_sm1"; dev_name = "aml_amdolby_vision_driver"; status = "okay"; tv_mode = <0>;/*1:enabel ;0:disable*/ diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index fb51c0682f21..d578896b2020 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -6645,6 +6645,10 @@ static const struct of_device_id amlogic_dolby_vision_match[] = { .compatible = "amlogic, dolby_vision_g12b", .data = &dolby_vision_g12, }, + { + .compatible = "amlogic, dolby_vision_sm1", + .data = &dolby_vision_g12, + }, {}, }; From e4193b64767d9604917d8c23ed82b701516285d2 Mon Sep 17 00:00:00 2001 From: Tao Guo Date: Wed, 16 Jan 2019 17:11:54 +0800 Subject: [PATCH 0122/1060] debug: add atrace support [1/1] PD#SWPL-4956 Problem: Need atrace to debug multimedia issue Solution: Add atrace functions Verify: P212 Change-Id: Ieee441fc75b6f83e8e8a22350a402ec7e77f1134 Signed-off-by: Tao Guo --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9a4a24b77293..0fc2a5b1e697 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14512,6 +14512,7 @@ F: drivers/amlogic/defendkey/* AMLOGIC DEBUG M: Jianxin Pan +M: Tao Guo F: drivers/amlogic/debug/* AMLOGIC G12A spdif channel status From a5385dc5c9090f3f5adf56fc765ae518f0c28bff Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Wed, 20 Mar 2019 17:37:08 +0800 Subject: [PATCH 0123/1060] ge2d: change ge2d to independent power [1/1] PD#SWPL-5391 Problem: change ge2d to independent power Solution: add independent power switch Verify: verified on SM1-AC200 board Change-Id: Ifce980fc88753db63317c11bc1126e492b677a64 Signed-off-by: Jian Cao --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 4 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 4 +- drivers/amlogic/media/common/ge2d/ge2d_io.h | 43 +++++++++++++++++ drivers/amlogic/media/common/ge2d/ge2d_main.c | 46 +++++++++++++++++++ drivers/amlogic/media/common/ge2d/ge2d_wq.c | 28 +++++++++++ drivers/amlogic/media/common/ge2d/ge2d_wq.h | 1 + include/linux/amlogic/media/ge2d/ge2d.h | 23 ++++++++++ 7 files changed, 145 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index b52ed4d16a28..7e94732ca98a 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1192,9 +1192,9 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; dev_name = "ge2d"; - status = "disabled"; + status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index ba5246620ff5..e0889d9a3d5d 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1192,9 +1192,9 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; dev_name = "ge2d"; - status = "disabled"; + status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/drivers/amlogic/media/common/ge2d/ge2d_io.h b/drivers/amlogic/media/common/ge2d/ge2d_io.h index 55f5b7505ccc..f8a3cb173202 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_io.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_io.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "ge2d_log.h" @@ -129,5 +130,47 @@ static inline void ge2d_reg_set_bits(uint32_t reg, (((value) & ((1L << (len)) - 1)) << (start)))); } +static void ge2d_hiu_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_hiubus(_reg, ((aml_read_hiubus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} +static void ge2d_ao_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_aobus(_reg, ((aml_read_aobus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} + +static void ge2d_c_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_cbus(_reg, ((aml_read_cbus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} + +static inline void ge2d_set_bus_bits(unsigned int bus_type, + unsigned int reg, unsigned int val, + unsigned int start, unsigned int len) +{ + switch (bus_type) { + case CBUS_BASE: + ge2d_c_setb(reg, val, start, len); + break; + case AOBUS_BASE: + ge2d_ao_setb(reg, val, start, len); + break; + case HIUBUS_BASE: + ge2d_hiu_setb(reg, val, start, len); + break; + default: + ge2d_log_err("unsupported bus type\n"); + break; + } +} #endif diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 7a768ce8a5be..459e164e8688 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -39,6 +39,7 @@ /* Amlogic Headers */ #include #include +#include #include #include #ifdef CONFIG_AMLOGIC_ION @@ -52,6 +53,7 @@ #define GE2D_CLASS_NAME "ge2d" #define MAX_GE2D_CLK 500000000 +#define HHI_MEM_PD_REG0 0x40 struct ge2d_device_s { char name[20]; @@ -1032,6 +1034,26 @@ static int ge2d_release(struct inode *inode, struct file *file) return -1; } +static struct ge2d_ctrl_s default_poweron_ctrl[] = { + /* power up ge2d */ + {AOBUS_BASE, AO_RTI_GEN_PWR_SLEEP0, 0, 19, 1, 0}, + /* Power up memory */ + {HIUBUS_BASE, HHI_MEM_PD_REG0, 0, 18, 8, 100}, + /* remove isolation */ + {AOBUS_BASE, AO_RTI_GEN_PWR_ISO0, 0, 19, 1, 0} + }; +static struct ge2d_ctrl_s default_poweroff_ctrl[] = { + /* add isolation */ + {AOBUS_BASE, AO_RTI_GEN_PWR_ISO0, 1, 19, 1, 0}, + /* Power down memory */ + {HIUBUS_BASE, HHI_MEM_PD_REG0, 0xff, 18, 8, 0}, + /* power down ge2d */ + {AOBUS_BASE, AO_RTI_GEN_PWR_SLEEP0, 1, 19, 1, 0} + }; + +struct ge2d_power_table_s default_poweron_table = {3, default_poweron_ctrl}; +struct ge2d_power_table_s default_poweroff_table = {3, default_poweroff_ctrl}; + static struct ge2d_device_data_s ge2d_gxl = { .ge2d_rate = 400000000, .src2_alp = 0, @@ -1039,6 +1061,7 @@ static struct ge2d_device_data_s ge2d_gxl = { .deep_color = 0, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_gxm = { @@ -1048,6 +1071,7 @@ static struct ge2d_device_data_s ge2d_gxm = { .deep_color = 0, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_txl = { @@ -1057,6 +1081,7 @@ static struct ge2d_device_data_s ge2d_txl = { .deep_color = 1, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_txlx = { @@ -1066,6 +1091,7 @@ static struct ge2d_device_data_s ge2d_txlx = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_axg = { @@ -1075,6 +1101,7 @@ static struct ge2d_device_data_s ge2d_axg = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_g12a = { @@ -1084,6 +1111,19 @@ static struct ge2d_device_data_s ge2d_g12a = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, +}; + +static struct ge2d_device_data_s ge2d_sm1 = { + .ge2d_rate = 500000000, + .src2_alp = 1, + .canvas_status = 0, + .deep_color = 1, + .hang_flag = 1, + .fifo = 1, + .has_self_pwr = 1, + .poweron_table = &default_poweron_table, + .poweroff_table = &default_poweroff_table, }; static const struct of_device_id ge2d_dt_match[] = { @@ -1111,6 +1151,10 @@ static const struct of_device_id ge2d_dt_match[] = { .compatible = "amlogic, ge2d-g12a", .data = &ge2d_g12a, }, + { + .compatible = "amlogic, ge2d-sm1", + .data = &ge2d_sm1, + }, {}, }; @@ -1171,6 +1215,7 @@ static int ge2d_probe(struct platform_device *pdev) goto failed1; } ge2d_log_info("clock clk_ge2d source %p\n", clk); + ge2d_pwr_config(true); clk_prepare_enable(clk); clk_vapb0 = devm_clk_get(&pdev->dev, "clk_vapb_0"); @@ -1240,6 +1285,7 @@ static int ge2d_remove(struct platform_device *pdev) ge2d_log_info("%s\n", __func__); ge2d_wq_deinit(); remove_ge2d_device(); + ge2d_pwr_config(false); return 0; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index 66ce8a1dacde..bc6fab6d6759 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Amlogic Headers */ #include @@ -45,6 +46,7 @@ #include "osd_io.h" #include "osd_hw.h" + #define OSD1_CANVAS_INDEX 0x40 #define OSD2_CANVAS_INDEX 0x43 #define OSD3_CANVAS_INDEX 0x41 @@ -118,6 +120,32 @@ static const int default_ge2d_color_lut[] = { GE2D_FORMAT_S32_ARGB,/* BPP_TYPE_32_ARGB=32, */ }; +void ge2d_pwr_config(bool enable) +{ + int i, table_size; + struct ge2d_ctrl_s tmp; + struct ge2d_ctrl_s *power_table; + + if (ge2d_meson_dev.has_self_pwr) { + if (enable) { + power_table = ge2d_meson_dev.poweron_table->power_btale; + table_size = ge2d_meson_dev.poweron_table->table_size; + } else { + power_table = + ge2d_meson_dev.poweroff_table->power_btale; + table_size = ge2d_meson_dev.poweroff_table->table_size; + } + + for (i = 0; i < table_size; i++) { + tmp = power_table[i]; + ge2d_set_bus_bits(tmp.bus_type, tmp.reg, tmp.val, + tmp.start, tmp.len); + if (tmp.udelay > 0) + udelay(tmp.udelay); + } + } +} + static int ge2d_clk_config(bool enable) { if (ge2d_clk == NULL) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.h b/drivers/amlogic/media/common/ge2d/ge2d_wq.h index 2fd067836211..ae81fe7e95d7 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.h @@ -39,4 +39,5 @@ int ge2d_buffer_free(int index); int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf); void ge2d_buffer_dma_flush(int dma_fd); void ge2d_buffer_cache_flush(int dma_fd); +void ge2d_pwr_config(bool enable); #endif diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index bf5c591d765f..883342ee9980 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -1012,6 +1012,26 @@ struct ge2d_dmabuf_exp_s { }; /* end of ge2d dma buffer define */ +enum { + CBUS_BASE, + AOBUS_BASE, + HIUBUS_BASE, +}; + +struct ge2d_ctrl_s { + unsigned int bus_type; + unsigned int reg; + unsigned int val; + unsigned int start; + unsigned int len; + unsigned int udelay; +}; + +struct ge2d_power_table_s { + unsigned int table_size; + struct ge2d_ctrl_s *power_btale; +}; + struct ge2d_device_data_s { int ge2d_rate; int src2_alp; @@ -1019,6 +1039,9 @@ struct ge2d_device_data_s { int deep_color; int hang_flag; int fifo; + int has_self_pwr; + struct ge2d_power_table_s *poweron_table; + struct ge2d_power_table_s *poweroff_table; }; extern struct ge2d_device_data_s ge2d_meson_dev; From feead68f338b25c9c7297725eb41b49c4164137c Mon Sep 17 00:00:00 2001 From: "cancan.chang" Date: Mon, 25 Mar 2019 18:42:53 +0800 Subject: [PATCH 0124/1060] NNA: add NNA support on sm1 [1/1] PD#SWPL-5380 Problem: sm1 not support NNA now. Solution: add NNA support. Verify: sm1_ac200 & sm1_skt Change-Id: I3de566bbc730ef69f26160ad9f915ac92b4f2e2b Signed-off-by: Cancan Chang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 24 ++++ .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 3 + arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 3 + arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 24 ++++ .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 3 + .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 3 + drivers/amlogic/clk/sm1/sm1.c | 122 +++++++++++++++++- 7 files changed, 181 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 7e94732ca98a..c3ca37290f24 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1097,6 +1097,30 @@ }; }; + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 186 4>; + interrupt-names = "galcore"; + reg = <0xff100000 0x800 + /*reg base value:0xff100000 */ + 0xff000000 0x400000 + /*Sram bse value:0xff000000*/ + 0xff63c118 0x0 + 0xff63c11c 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0xff8000e8 0x0 + 0xff8000ec 0x0 + /*0xff8000e8,0xff8000e8 :ao regs*/ + 0xffd01088 0x0 + /*0xffd01088:reset reg*/ + >; + }; aocec: aocec { compatible = "amlogic, aocec-g12a"; device_name = "aocec"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 6437c2c316cc..ea55d9eb6bbc 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -160,6 +160,9 @@ }; }; + galcore { + status = "okay"; + }; gpioleds { compatible = "gpio-leds"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index e2403fb1872f..162173d3bedb 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -160,6 +160,9 @@ }; }; + galcore { + status = "okay"; + }; gpioleds { compatible = "gpio-leds"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index e0889d9a3d5d..c5905187cab4 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1097,6 +1097,30 @@ }; }; + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 186 4>; + interrupt-names = "galcore"; + reg = <0x0 0xff100000 0x0 0x800 + /*reg base value:0xff100000 */ + 0x0 0xff000000 0x0 0x400000 + /*Sram bse value:0xff000000*/ + 0x0 0xff63c118 0x0 0x0 + 0x0 0xff63c11c 0x0 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0x0 0xff8000e8 0x0 0x0 + 0x0 0xff8000ec 0x0 0x0 + /*0xff8000e8,0xff8000e8 :ao regs*/ + 0x0 0xffd01088 0x0 0x0 + /*0xffd01088:reset reg*/ + >; + }; aocec: aocec { compatible = "amlogic, aocec-g12a"; device_name = "aocec"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 907c4ca716ed..2def38ace72a 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -158,6 +158,9 @@ }; }; + galcore { + status = "okay"; + }; gpioleds { compatible = "gpio-leds"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 9c2c69cc5ff1..93823ef42fd3 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -158,6 +158,9 @@ }; }; + galcore { + status = "okay"; + }; gpioleds { compatible = "gpio-leds"; status = "okay"; diff --git a/drivers/amlogic/clk/sm1/sm1.c b/drivers/amlogic/clk/sm1/sm1.c index 0cb8fd2f75d6..9b985abdc917 100644 --- a/drivers/amlogic/clk/sm1/sm1.c +++ b/drivers/amlogic/clk/sm1/sm1.c @@ -55,6 +55,91 @@ static struct meson_clk_pll sm1_gp1_pll = { }, }; +static const char * const media_parent_names[] = { "xtal", + "gp0_pll", "hifi_pll", "fclk_div2p5", "fclk_div3", "fclk_div4", + "fclk_div5", "fclk_div7"}; + +static struct clk_mux cts_vipnanoq_core_clk_mux = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_core_clk_mux", + .ops = &clk_mux_ops, + .parent_names = media_parent_names, + .num_parents = 8, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider cts_vipnanoq_core_clk_div = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_core_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_core_clk_mux" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_gate cts_vipnanoq_core_clk_gate = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "cts_vipnanoq_core_clk_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_core_clk_div" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_mux cts_vipnanoq_axi_clk_mux = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .mask = 0x7, + .shift = 25, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_axi_clk_mux", + .ops = &clk_mux_ops, + .parent_names = media_parent_names, + .num_parents = 8, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider cts_vipnanoq_axi_clk_div = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_axi_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_axi_clk_mux" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_gate cts_vipnanoq_axi_clk_gate = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "cts_vipnanoq_axi_clk_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_axi_clk_div" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; static struct clk_mux sm1_dsu_pre_src_clk_mux0 = { .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, .mask = 0x3, @@ -276,7 +361,18 @@ static void __init sm1_clkc_init(struct device_node *np) + (unsigned long)sm1_dsu_pre_clk.reg; sm1_dsu_clk.reg = clk_base + (unsigned long)sm1_dsu_clk.reg; - + cts_vipnanoq_core_clk_mux.reg = clk_base + + (unsigned long)(cts_vipnanoq_core_clk_mux.reg); + cts_vipnanoq_core_clk_gate.reg = clk_base + + (unsigned long)(cts_vipnanoq_core_clk_gate.reg); + cts_vipnanoq_core_clk_div.reg = clk_base + + (unsigned long)(cts_vipnanoq_core_clk_div.reg); + cts_vipnanoq_axi_clk_mux.reg = clk_base + + (unsigned long)(cts_vipnanoq_axi_clk_mux.reg); + cts_vipnanoq_axi_clk_gate.reg = clk_base + + (unsigned long)(cts_vipnanoq_axi_clk_gate.reg); + cts_vipnanoq_axi_clk_div.reg = clk_base + + (unsigned long)(cts_vipnanoq_axi_clk_div.reg); /* Populate base address for gates */ for (i = 0; i < ARRAY_SIZE(sm1_clk_gates); i++) sm1_clk_gates[i]->reg = clk_base + @@ -305,7 +401,31 @@ static void __init sm1_clkc_init(struct device_node *np) } } } + clks[CLKID_VNANOQ_CORE_CLK_COMP] = clk_register_composite(NULL, + "cts_vipnanoq_core_clk_composite", + media_parent_names, 8, + &cts_vipnanoq_core_clk_mux.hw, + &clk_mux_ops, + &cts_vipnanoq_core_clk_div.hw, + &clk_divider_ops, + &cts_vipnanoq_core_clk_gate.hw, + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_VNANOQ_CORE_CLK_COMP])) + panic("%s: %d register cts_vipnanoq_core_clk_composite error\n", + __func__, __LINE__); + clks[CLKID_VNANOQ_AXI_CLK_COMP] = clk_register_composite(NULL, + "cts_vipnanoq_axi_clk_composite", + media_parent_names, 8, + &cts_vipnanoq_axi_clk_mux.hw, + &clk_mux_ops, + &cts_vipnanoq_axi_clk_div.hw, + &clk_divider_ops, + &cts_vipnanoq_axi_clk_gate.hw, + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_VNANOQ_AXI_CLK_COMP])) + panic("%s: %d register cts_vipnanoq_axi_clk_composite error\n", + __func__, __LINE__); if (clks[CLKID_CPU_CLK]) { if (!of_property_read_bool(np, "own-dsu-clk")) return; From 1e602ac0cadce3eda81f912fd0080e007212d3c4 Mon Sep 17 00:00:00 2001 From: "cancan.chang" Date: Fri, 29 Mar 2019 18:00:49 +0800 Subject: [PATCH 0125/1060] usb: add NN power control [1/1] PD#SWPL-5380 Problem: add NN power control Solution: add NN power control Verify: sm1 Test: pass Change-Id: I729d782181490fc31b0b18bb27718ad12b3937c0 Signed-off-by: cancan.chang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 3 --- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 3 --- 2 files changed, 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index c3ca37290f24..bc6e1886dbea 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1114,9 +1114,6 @@ 0xff63c118 0x0 0xff63c11c 0x0 /*0xff63c118,0xff63c11c :nanoq mem regs*/ - 0xff8000e8 0x0 - 0xff8000ec 0x0 - /*0xff8000e8,0xff8000e8 :ao regs*/ 0xffd01088 0x0 /*0xffd01088:reset reg*/ >; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index c5905187cab4..b9a9b9e281ef 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1114,9 +1114,6 @@ 0x0 0xff63c118 0x0 0x0 0x0 0xff63c11c 0x0 0x0 /*0xff63c118,0xff63c11c :nanoq mem regs*/ - 0x0 0xff8000e8 0x0 0x0 - 0x0 0xff8000ec 0x0 0x0 - /*0xff8000e8,0xff8000e8 :ao regs*/ 0x0 0xffd01088 0x0 0x0 /*0xffd01088:reset reg*/ >; From 0d81c81a5f48e961516d02bc5b6392cc4f31b629 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 14 Mar 2019 12:30:44 +0800 Subject: [PATCH 0126/1060] vpu: add vpu support for sm1 [1/1] PD#SWPL-5857 Problem: sm1 is a new chip Solution: add sm1 support for vpu driver Verify: pxp Change-Id: I88966a26fb4f8f90620081c4d9a86ad21a6e03fc Signed-off-by: Evoke Zhang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 4 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 4 +- drivers/amlogic/media/common/vpu/vpu.c | 45 +++++++- drivers/amlogic/media/common/vpu/vpu.h | 3 + drivers/amlogic/media/common/vpu/vpu_ctrl.h | 75 ++++++++++++- drivers/amlogic/media/common/vpu/vpu_module.h | 2 +- .../amlogic/media/common/vpu/vpu_power_init.c | 25 ++++- drivers/amlogic/media/common/vpu/vpu_reg.h | 3 +- include/linux/amlogic/media/vpu/vpu.h | 100 +++++++++--------- 9 files changed, 198 insertions(+), 63 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index bc6e1886dbea..8614d97c3af5 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -278,8 +278,8 @@ sys_poweroff = <0x84000008>; }; - vpu { - compatible = "amlogic, vpu-g12a"; + vpu: vpu { + compatible = "amlogic, vpu-sm1"; dev_name = "vpu"; status = "okay"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index b9a9b9e281ef..1aa62dd2f608 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -278,8 +278,8 @@ sys_poweroff = <0x84000008>; }; - vpu { - compatible = "amlogic, vpu-g12a"; + vpu: vpu { + compatible = "amlogic, vpu-sm1"; dev_name = "vpu"; status = "okay"; clocks = <&clkc CLKID_VAPB_MUX>, diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index d7f3cffa5a4a..1ff826f67286 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -39,7 +39,8 @@ /* v04: add g12a support */ /* v05: add txl support */ /* v20180925: add tl1 support */ -#define VPU_VERION "v20180925" +/* v20190314: add sm1 support */ +#define VPU_VERION "v20190314" int vpu_debug_print_flag; static spinlock_t vpu_mem_lock; @@ -1107,9 +1108,9 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state) static int vpu_resume(struct platform_device *pdev) { + set_vpu_clk(vpu_conf.clk_level); VPUPR("resume clk: %uHz(0x%x)\n", get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL))); - set_vpu_clk(vpu_conf.clk_level); return 0; } #endif @@ -1232,6 +1233,7 @@ static struct vpu_data_s vpu_data_gxb = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1257,6 +1259,7 @@ static struct vpu_data_s vpu_data_gxtvbb = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1282,6 +1285,7 @@ static struct vpu_data_s vpu_data_gxl = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1308,6 +1312,7 @@ static struct vpu_data_s vpu_data_gxm = { .module_init_table_cnt = sizeof(vpu_module_init_gxm) / sizeof(struct vpu_ctrl_s), .module_init_table = vpu_module_init_gxm, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1333,6 +1338,7 @@ static struct vpu_data_s vpu_data_txl = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1359,6 +1365,7 @@ static struct vpu_data_s vpu_data_txlx = { .module_init_table_cnt = sizeof(vpu_module_init_txlx) / sizeof(struct vpu_ctrl_s), .module_init_table = vpu_module_init_txlx, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1384,6 +1391,7 @@ static struct vpu_data_s vpu_data_axg = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1409,6 +1417,7 @@ static struct vpu_data_s vpu_data_g12a = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1434,6 +1443,7 @@ static struct vpu_data_s vpu_data_g12b = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1459,9 +1469,36 @@ static struct vpu_data_s vpu_data_tl1 = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_tl1, }; +static struct vpu_data_s vpu_data_sm1 = { + .chip_type = VPU_CHIP_SM1, + .chip_name = "sm1", + .clk_level_dft = CLK_LEVEL_DFT_G12A, + .clk_level_max = CLK_LEVEL_MAX_G12A, + .fclk_div_table = fclk_div_table_g12a, + + .gp_pll_valid = 0, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 1, + .mem_pd_reg3_valid = 1, + .mem_pd_reg4_valid = 1, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_sm1) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_g12a) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_sm1, + .clk_gate_table = vpu_clk_gate_g12a, + + .module_init_table_cnt = 0, + .module_init_table = NULL, + .hdmi_iso_table = vpu_hdmi_iso_sm1, + .reset_table = vpu_reset_txlx, +}; + static const struct of_device_id vpu_of_table[] = { { .compatible = "amlogic, vpu-gxbb", @@ -1503,6 +1540,10 @@ static const struct of_device_id vpu_of_table[] = { .compatible = "amlogic, vpu-tl1", .data = &vpu_data_tl1, }, + { + .compatible = "amlogic, vpu-sm1", + .data = &vpu_data_sm1, + }, {}, }; diff --git a/drivers/amlogic/media/common/vpu/vpu.h b/drivers/amlogic/media/common/vpu/vpu.h index 997f96c9c8ea..b0f1d86fa2f4 100644 --- a/drivers/amlogic/media/common/vpu/vpu.h +++ b/drivers/amlogic/media/common/vpu/vpu.h @@ -36,10 +36,12 @@ enum vpu_chip_e { VPU_CHIP_G12A, VPU_CHIP_G12B, VPU_CHIP_TL1, + VPU_CHIP_SM1, VPU_CHIP_MAX, }; #define VPU_REG_END 0xffff +#define VPU_HDMI_ISO_CNT_MAX 5 #define VPU_RESET_CNT_MAX 10 struct fclk_div_s { @@ -87,6 +89,7 @@ struct vpu_data_s { unsigned int module_init_table_cnt; struct vpu_ctrl_s *module_init_table; + struct vpu_ctrl_s *hdmi_iso_table; struct vpu_reset_s *reset_table; }; diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h index ca0eb494511b..79e3f00ce790 100644 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.h +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -394,7 +394,7 @@ static struct vpu_ctrl_s vpu_mem_pd_tl1[] = { {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, {VPU_VIU2_OSD_ROT, HHI_VPU_MEM_PD_REG2, 0x3, 22, 2}, - {VPU_VI_DIPRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 0, 16}, {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, @@ -404,6 +404,60 @@ static struct vpu_ctrl_s vpu_mem_pd_tl1[] = { {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, }; +static struct vpu_ctrl_s vpu_mem_pd_sm1[] = { + /* vpu module, reg, val, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0x3, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 0x3, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 0x3, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 0x3, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 0x3, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 0x3, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 0x3, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 0x3, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 0x3, 20, 2}, + {VPU_AFBC_DEC1, HHI_VPU_MEM_PD_REG0, 0x3, 22, 2}, + {VPU_VIU_DI_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 24, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 0x3, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 0x3, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 0x3, 30, 2}, + {VPU_VIU2, HHI_VPU_MEM_PD_REG1, 0xf, 0, 4}, + {VPU_VKSTONE, HHI_VPU_MEM_PD_REG1, 0x3, 4, 2}, + {VPU_DOLBY_CORE3, HHI_VPU_MEM_PD_REG1, 0x3, 6, 2}, + {VPU_DOLBY0, HHI_VPU_MEM_PD_REG1, 0x3, 8, 2}, + {VPU_DOLBY1A, HHI_VPU_MEM_PD_REG1, 0x3, 10, 2}, + {VPU_DOLBY1B, HHI_VPU_MEM_PD_REG1, 0x3, 12, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 0x3, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 0x3, 16, 2}, + {VPU_VD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 18, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, + {VPU_LS_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, + {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, + {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG2, 0x3, 2, 2}, + {VPU_VIU_OSD3, HHI_VPU_MEM_PD_REG2, 0x3, 4, 2}, + {VPU_VIU_OSD4, HHI_VPU_MEM_PD_REG2, 0x3, 6, 2}, + {VPU_MAIL_AFBCD, HHI_VPU_MEM_PD_REG2, 0x3, 8, 2}, + {VPU_VD1_SCALE, HHI_VPU_MEM_PD_REG2, 0x3, 10, 2}, + {VPU_OSD_BLD34, HHI_VPU_MEM_PD_REG2, 0x3, 12, 2}, + {VPU_PRIME_DOLBY_RAM, HHI_VPU_MEM_PD_REG2, 0x3, 14, 2}, + {VPU_VD2_OFIFO, HHI_VPU_MEM_PD_REG2, 0x3, 16, 2}, + {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, + {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, + {VPU_VIU2, HHI_VPU_MEM_PD_REG2, 0x3, 22, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, + {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 0, 16}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, + {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4, 0x3, 0, 2}, + {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4, 0x3, 2, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, +}; + /* ******************************************************* */ /* VPU clock gate table */ /* ******************************************************* */ @@ -579,7 +633,22 @@ static struct vpu_ctrl_s vpu_clk_gate_g12a[] = { }; /* ******************************************************* */ -/* VPU module init table */ +/* VPU_HDMI ISO */ +/* ******************************************************* */ +static struct vpu_ctrl_s vpu_hdmi_iso_gxb[] = { + /* reg, val, bit, len */ + {AO_RTI_GEN_PWR_SLEEP0, 1, 9, 1}, + {VPU_REG_END, 0, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_hdmi_iso_sm1[] = { + /* reg, val, bit, len */ + {AO_RTI_GEN_PWR_ISO0, 1, 8, 1}, + {VPU_REG_END, 0, 0, 0}, +}; + +/* ******************************************************* */ +/* VPU module init table */ /* ******************************************************* */ static struct vpu_ctrl_s vpu_module_init_gxm[] = { /* 0, reg, val, bit, len */ @@ -603,7 +672,7 @@ static struct vpu_ctrl_s vpu_module_init_txlx[] = { }; /* ******************************************************* */ -/* VPU reset table */ +/* VPU reset table */ /* ******************************************************* */ static struct vpu_reset_s vpu_reset_gx[] = { /* reg, mask */ diff --git a/drivers/amlogic/media/common/vpu/vpu_module.h b/drivers/amlogic/media/common/vpu/vpu_module.h index 30f0cd9b0401..0e089f47c80b 100644 --- a/drivers/amlogic/media/common/vpu/vpu_module.h +++ b/drivers/amlogic/media/common/vpu/vpu_module.h @@ -40,6 +40,7 @@ static char *vpu_mod_table[] = { "di_post", "viu_sharpness_line_buffer", + "viu2", "viu2_osd1", "viu2_osd2", "viu2_vd1", @@ -77,7 +78,6 @@ static char *vpu_mod_table[] = { "ds", "lut3d", "viu2_osd_rotation", - "vi_dipre", "rdma", "axi_wr1", diff --git a/drivers/amlogic/media/common/vpu/vpu_power_init.c b/drivers/amlogic/media/common/vpu/vpu_power_init.c index 7858607f5320..21ccce7f6c9e 100644 --- a/drivers/amlogic/media/common/vpu/vpu_power_init.c +++ b/drivers/amlogic/media/common/vpu/vpu_power_init.c @@ -124,7 +124,17 @@ void vpu_power_on(void) } /* Remove VPU_HDMI ISO */ - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 0, 9, 1); /* [9] VPU_HDMI */ + ctrl_table = vpu_conf.data->hdmi_iso_table; + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, 0, _bit, _len); + i++; + } if (vpu_debug_print_flag) VPUPR("%s finish\n", __func__); @@ -140,12 +150,23 @@ void vpu_power_off(void) /* Power down VPU_HDMI */ /* Enable Isolation */ - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 1, 9, 1); /* ISO */ + ctrl_table = vpu_conf.data->hdmi_iso_table; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = ctrl_table[i].val; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } udelay(20); /* power down memories */ cnt = vpu_conf.data->mem_pd_table_cnt; ctrl_table = vpu_conf.data->mem_pd_table; + i = 0; while (i < cnt) { if (ctrl_table[i].vmod == VPU_MOD_MAX) break; diff --git a/drivers/amlogic/media/common/vpu/vpu_reg.h b/drivers/amlogic/media/common/vpu/vpu_reg.h index 4bac30b96647..d21cf9583726 100644 --- a/drivers/amlogic/media/common/vpu/vpu_reg.h +++ b/drivers/amlogic/media/common/vpu/vpu_reg.h @@ -28,7 +28,8 @@ * ********************************* */ -#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2) +#define AO_RTI_GEN_PWR_SLEEP0 (0x03a << 2) +#define AO_RTI_GEN_PWR_ISO0 (0x03b << 2) /* HHI bus */ #define HHI_GP1_PLL_CNTL 0x16 diff --git a/include/linux/amlogic/media/vpu/vpu.h b/include/linux/amlogic/media/vpu/vpu.h index 674b44bacb5f..3fa09153af76 100644 --- a/include/linux/amlogic/media/vpu/vpu.h +++ b/include/linux/amlogic/media/vpu/vpu.h @@ -22,24 +22,25 @@ /* VPU module define */ /* ************************************************ */ enum vpu_mod_e { - VPU_VIU_OSD1 = 0, /* reg0[1:0] //common */ - VPU_VIU_OSD2, /* reg0[3:2] //common */ - VPU_VIU_VD1, /* reg0[5:4] //common */ - VPU_VIU_VD2, /* reg0[7:6] //common */ - VPU_VIU_CHROMA, /* reg0[9:8] //common */ - VPU_VIU_OFIFO, /* reg0[11:10] //common */ - VPU_VIU_SCALE, /* reg0[13:12] //common */ - VPU_VIU_OSD_SCALE, /* reg0[15:14] //common */ - VPU_VIU_VDIN0, /* reg0[17:16] //common */ - VPU_VIU_VDIN1, /* reg0[19:18] //common */ - VPU_VIU_SRSCL, /* reg0[21:20] //GXBB, GXTVBB, TXLX */ - VPU_VIU_OSDSR, /* reg0[23:22] //GXBB */ - VPU_AFBC_DEC1, /* reg0[23:22] //GXTVBB, TXLX */ - VPU_VIU_DI_SCALE, /* reg0[25:24] //G12A */ - VPU_DI_PRE, /* reg0[27:26] //common */ - VPU_DI_POST, /* reg0[29:28] //common */ - VPU_SHARP, /* reg0[31:30] //common */ + VPU_VIU_OSD1 = 0, /* reg0[1:0], common */ + VPU_VIU_OSD2, /* reg0[3:2], common */ + VPU_VIU_VD1, /* reg0[5:4], common */ + VPU_VIU_VD2, /* reg0[7:6], common */ + VPU_VIU_CHROMA, /* reg0[9:8], common */ + VPU_VIU_OFIFO, /* reg0[11:10], common */ + VPU_VIU_SCALE, /* reg0[13:12], common */ + VPU_VIU_OSD_SCALE, /* reg0[15:14], common */ + VPU_VIU_VDIN0, /* reg0[17:16], common */ + VPU_VIU_VDIN1, /* reg0[19:18], common */ + VPU_VIU_SRSCL, /* reg0[21:20], GXBB, GXTVBB, TXLX */ + VPU_VIU_OSDSR, /* reg0[23:22], GXBB */ + VPU_AFBC_DEC1, /* reg0[23:22], GXTVBB, TXLX */ + VPU_VIU_DI_SCALE, /* reg0[25:24], G12A */ + VPU_DI_PRE, /* reg0[27:26], common */ + VPU_DI_POST, /* reg0[29:28], common */ + VPU_SHARP, /* reg0[31:30], common */ + VPU_VIU2, /* reg1[3:0], reg2[23:22], SM1 */ VPU_VIU2_OSD1, /* reg1[1:0] */ VPU_VIU2_OSD2, /* reg1[3:2] */ VPU_VIU2_VD1, /* reg1[5:4] */ @@ -47,42 +48,41 @@ enum vpu_mod_e { VPU_VIU2_OFIFO, /* reg1[9:8] */ VPU_VIU2_SCALE, /* reg1[11:10] */ VPU_VIU2_OSD_SCALE, /* reg1[13:12] */ - VPU_VKSTONE, /* reg1[5:4] //TXLX */ - VPU_DOLBY_CORE3, /* reg1[7:6] //TXLX */ - VPU_DOLBY0, /* reg1[9:8] //TXLX */ - VPU_DOLBY1A, /* reg1[11:10] //TXLX */ - VPU_DOLBY1B, /* reg1[13:12] //TXLX */ - VPU_VPU_ARB, /* reg1[15:14] //GXBB, GXTVBB, GXL, TXLX */ - VPU_AFBC_DEC, /* reg1[17:16] //GXBB, GXTVBB, TXL, TXLX */ - VPU_OSD_AFBCD, /* reg1[19:18] //TXLX */ - VPU_VD2_SCALE, /* reg1[19:18] //G12A */ - VPU_VENCP, /* reg1[21:20] //common */ - VPU_VENCL, /* reg1[23:22] //common */ - VPU_VENCI, /* reg1[25:24] //common */ - VPU_LS_STTS, /* reg1[27:26] //tl1 */ - VPU_LDIM_STTS, /* reg1[29:28] //GXTVBB, GXL, TXL, TXLX */ + VPU_VKSTONE, /* reg1[5:4], TXLX */ + VPU_DOLBY_CORE3, /* reg1[7:6], TXLX */ + VPU_DOLBY0, /* reg1[9:8], TXLX */ + VPU_DOLBY1A, /* reg1[11:10], TXLX */ + VPU_DOLBY1B, /* reg1[13:12], TXLX */ + VPU_VPU_ARB, /* reg1[15:14], GXBB, GXTVBB, GXL, TXLX */ + VPU_AFBC_DEC, /* reg1[17:16], GXBB, GXTVBB, TXL, TXLX */ + VPU_OSD_AFBCD, /* reg1[19:18], TXLX */ + VPU_VD2_SCALE, /* reg1[19:18], G12A */ + VPU_VENCP, /* reg1[21:20], common */ + VPU_VENCL, /* reg1[23:22], common */ + VPU_VENCI, /* reg1[25:24], common */ + VPU_LS_STTS, /* reg1[27:26], tl1 */ + VPU_LDIM_STTS, /* reg1[29:28], GXTVBB, GXL, TXL, TXLX */ VPU_TV_DEC_CVD2, /* reg1[29:28] */ - VPU_XVYCC_LUT, /* reg1[31:30] //GXTVBB, GXL, TXL, TXLX */ - VPU_VD2_OSD2_SCALE, /* reg1[31:30] //G12A */ + VPU_XVYCC_LUT, /* reg1[31:30], GXTVBB, GXL, TXL, TXLX */ + VPU_VD2_OSD2_SCALE, /* reg1[31:30], G12A */ - VPU_VIU_WM, /* reg2[1:0] //GXL, TXL, TXLX */ - VPU_TCON, /* reg2[3:2] //TXHD, TL1 */ - VPU_VIU_OSD3, /* reg2[5:4] //G12A */ - VPU_VIU_OSD4, /* reg2[7:6] //G12A */ - VPU_MAIL_AFBCD, /* reg2[9:8] //G12A */ - VPU_VD1_SCALE, /* reg2[11:10] //G12A */ - VPU_OSD_BLD34, /* reg2[13:12] //G12A */ - VPU_PRIME_DOLBY_RAM, /* reg2[15:14] //G12A */ - VPU_VD2_OFIFO, /* reg2[17:16] //G12A */ - VPU_DS, /* reg2[19:18] //TL1 */ - VPU_LUT3D, /* reg2[21:20] //G12B */ - VPU_VIU2_OSD_ROT, /* reg2[23:22] //G12B */ - VPU_VI_DIPRE, /* reg2[27:24] //TL1 */ - VPU_RDMA, /* reg2[31:30] //G12A */ + VPU_VIU_WM, /* reg2[1:0], GXL, TXL, TXLX */ + VPU_TCON, /* reg2[3:2], TXHD, TL1 */ + VPU_VIU_OSD3, /* reg2[5:4], G12A */ + VPU_VIU_OSD4, /* reg2[7:6], G12A */ + VPU_MAIL_AFBCD, /* reg2[9:8], G12A */ + VPU_VD1_SCALE, /* reg2[11:10], G12A */ + VPU_OSD_BLD34, /* reg2[13:12], G12A */ + VPU_PRIME_DOLBY_RAM, /* reg2[15:14], G12A */ + VPU_VD2_OFIFO, /* reg2[17:16], G12A */ + VPU_DS, /* reg2[19:18], TL1 */ + VPU_LUT3D, /* reg2[21:20], G12B */ + VPU_VIU2_OSD_ROT, /* reg2[23:22], G12B */ + VPU_RDMA, /* reg2[31:30], G12A */ - VPU_AXI_WR1, /* reg4[1:0] //TL1 */ - VPU_AXI_WR0, /* reg4[3:2] //TL1 */ - VPU_AFBCE, /* reg4[5:4] //TL1 */ + VPU_AXI_WR1, /* reg4[1:0], TL1 */ + VPU_AXI_WR0, /* reg4[3:2], TL1 */ + VPU_AFBCE, /* reg4[5:4], TL1 */ VPU_MOD_MAX, From 6a09523adc95910463a95cfec73a7836fac0701f Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 19 Mar 2019 12:38:30 +0800 Subject: [PATCH 0127/1060] vpu: fix mem_pd reg addr mistake [1/1] PD#SWPL-5857 Problem: vpu_mem_pd register address changed Solution: update vpu_mem_pd register address for sm1 Verify: pxp Change-Id: Iefcb190b40a5ac949351a4c88bea502e437cd59f Signed-off-by: Evoke Zhang --- drivers/amlogic/media/common/vpu/vpu.c | 41 ++++++++++++++++----- drivers/amlogic/media/common/vpu/vpu_ctrl.h | 8 ++-- drivers/amlogic/media/common/vpu/vpu_reg.h | 2 + 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index 1ff826f67286..a1dbda03bfe5 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -790,8 +790,16 @@ static ssize_t vpu_mem_debug(struct class *class, struct class_attribute *attr, _reg0 = HHI_VPU_MEM_PD_REG0; _reg1 = HHI_VPU_MEM_PD_REG1; _reg2 = HHI_VPU_MEM_PD_REG2; - _reg3 = HHI_VPU_MEM_PD_REG3; - _reg4 = HHI_VPU_MEM_PD_REG4; + switch (vpu_conf.data->chip_type) { + case VPU_CHIP_SM1: + _reg3 = HHI_VPU_MEM_PD_REG3_SM1; + _reg4 = HHI_VPU_MEM_PD_REG4_SM1; + break; + default: + _reg3 = HHI_VPU_MEM_PD_REG3; + _reg4 = HHI_VPU_MEM_PD_REG4; + break; + } switch (buf[0]) { case 'r': VPUPR("mem_pd0: 0x%08x\n", vpu_hiu_read(_reg0)); @@ -800,9 +808,9 @@ static ssize_t vpu_mem_debug(struct class *class, struct class_attribute *attr, if (vpu_conf.data->mem_pd_reg2_valid) VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg2)); if (vpu_conf.data->mem_pd_reg3_valid) - VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg3)); + VPUPR("mem_pd3: 0x%08x\n", vpu_hiu_read(_reg3)); if (vpu_conf.data->mem_pd_reg4_valid) - VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg4)); + VPUPR("mem_pd4: 0x%08x\n", vpu_hiu_read(_reg4)); break; case 'w': ret = sscanf(buf, "w %u %u", &tmp[0], &tmp[1]); @@ -940,6 +948,7 @@ static ssize_t vpu_print_debug(struct class *class, static ssize_t vpu_debug_info(struct class *class, struct class_attribute *attr, char *buf) { + unsigned int _reg0, _reg1, _reg2, _reg3, _reg4; unsigned int level_max, clk; ssize_t len = 0; int ret; @@ -953,6 +962,20 @@ static ssize_t vpu_debug_info(struct class *class, return len; } + _reg0 = HHI_VPU_MEM_PD_REG0; + _reg1 = HHI_VPU_MEM_PD_REG1; + _reg2 = HHI_VPU_MEM_PD_REG2; + switch (vpu_conf.data->chip_type) { + case VPU_CHIP_SM1: + _reg3 = HHI_VPU_MEM_PD_REG3_SM1; + _reg4 = HHI_VPU_MEM_PD_REG4_SM1; + break; + default: + _reg3 = HHI_VPU_MEM_PD_REG3; + _reg4 = HHI_VPU_MEM_PD_REG4; + break; + } + clk = get_vpu_clk(); level_max = vpu_conf.data->clk_level_max - 1; @@ -972,22 +995,22 @@ static ssize_t vpu_debug_info(struct class *class, len += sprintf(buf+len, "mem_pd:\n" " mem_pd0: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG0)); + vpu_hiu_read(_reg0)); if (vpu_conf.data->mem_pd_reg1_valid) { len += sprintf(buf+len, " mem_pd1: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG1)); + vpu_hiu_read(_reg1)); } if (vpu_conf.data->mem_pd_reg2_valid) { len += sprintf(buf+len, " mem_pd2: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG2)); + vpu_hiu_read(_reg2)); } if (vpu_conf.data->mem_pd_reg3_valid) { len += sprintf(buf+len, " mem_pd3: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG3)); + vpu_hiu_read(_reg3)); } if (vpu_conf.data->mem_pd_reg4_valid) { len += sprintf(buf+len, " mem_pd4: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG4)); + vpu_hiu_read(_reg4)); } #ifdef CONFIG_VPU_DYNAMIC_ADJ diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h index 79e3f00ce790..10302e9a9845 100644 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.h +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -451,10 +451,10 @@ static struct vpu_ctrl_s vpu_mem_pd_sm1[] = { {VPU_VIU2, HHI_VPU_MEM_PD_REG2, 0x3, 22, 2}, {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, - {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 0, 16}, - {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, - {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4, 0x3, 0, 2}, - {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4, 0x3, 2, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3_SM1, 0x3, 0, 16}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3_SM1, 0x3, 16, 16}, + {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4_SM1, 0x3, 0, 2}, + {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4_SM1, 0x3, 2, 2}, {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, }; diff --git a/drivers/amlogic/media/common/vpu/vpu_reg.h b/drivers/amlogic/media/common/vpu/vpu_reg.h index d21cf9583726..903be7d6fdcc 100644 --- a/drivers/amlogic/media/common/vpu/vpu_reg.h +++ b/drivers/amlogic/media/common/vpu/vpu_reg.h @@ -43,6 +43,8 @@ #define HHI_VPU_MEM_PD_REG2 0x4d #define HHI_VPU_MEM_PD_REG3 0x4e #define HHI_VPU_MEM_PD_REG4 0x4c +#define HHI_VPU_MEM_PD_REG3_SM1 0x43 +#define HHI_VPU_MEM_PD_REG4_SM1 0x44 #define HHI_VPU_CLKC_CNTL 0x6d #define HHI_VPU_CLK_CNTL 0x6f From b1162f508a8e96f3ad51c5d834119d92a7031794 Mon Sep 17 00:00:00 2001 From: "Nanxin.Qin" Date: Wed, 20 Mar 2019 15:46:56 +0800 Subject: [PATCH 0128/1060] dts: update chip name. [2/2] PD#SWPL-5261 Problem: update chip name. Solution: the chip name used for media modules. Verify: AC200 Change-Id: I229ca3f991b29fdebf10f98dff5173768b910aaa Signed-off-by: Nanxin.Qin --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 8614d97c3af5..718b3420c234 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1795,7 +1795,7 @@ }; cpu_ver_name { - compatible = "amlogic, cpu-major-id-g12a"; + compatible = "amlogic, cpu-major-id-sm1"; }; };/* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 1aa62dd2f608..6f2504f2fc1b 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1795,7 +1795,7 @@ }; cpu_ver_name { - compatible = "amlogic, cpu-major-id-g12a"; + compatible = "amlogic, cpu-major-id-sm1"; }; };/* end of / */ From 829aee06c450c663c87e754f14eab9ef92f2dc8f Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Wed, 20 Mar 2019 11:26:28 +0800 Subject: [PATCH 0129/1060] cvbs: add cvbs support for sm1 [1/1] PD#SWPL-6112 Problem: need add cvbsout support for sm1 Solution: add cvbsout support for sm1 Verify: sm1 Change-Id: I037fbdb41b823d9ef93a9069f3798f8d38ac5796 Signed-off-by: Nian Jing Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm/boot/dts/amlogic/sm1_pxp.dts | 4 +-- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 +-- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 4 +-- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 4 +-- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 +-- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 4 +-- drivers/amlogic/media/vout/cvbs/cvbs_out.c | 29 ++++++++++++++----- drivers/amlogic/media/vout/cvbs/cvbs_out.h | 2 ++ .../amlogic/media/vout/cvbs/enc_clk_config.c | 9 ++++-- drivers/amlogic/media/vout/vdac/vdac_dev.c | 16 ++++++++-- include/linux/amlogic/media/vout/vdac_dev.h | 1 + 13 files changed, 59 insertions(+), 26 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 718b3420c234..e09ef961774d 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1201,7 +1201,7 @@ }; vdac { - compatible = "amlogic, vdac-g12a"; + compatible = "amlogic, vdac-sm1"; status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index 2a9a9293109b..0e98deac2c2f 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -131,7 +131,7 @@ }; cvbsout { - compatible = "amlogic, cvbsout-g12a"; + compatible = "amlogic, cvbsout-sm1"; dev_name = "cvbsout"; status = "okay"; clocks = <&clkc CLKID_VCLK2_ENCI @@ -145,7 +145,7 @@ clk_path = <0>; /* performance: reg_address, reg_value */ - /* g12a */ + /* sm1 */ performance = <0x1bf0 0x9 0x1b56 0x333 0x1b12 0x8080 diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index ea55d9eb6bbc..7e667e145567 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -175,7 +175,7 @@ }; cvbsout { - compatible = "amlogic, cvbsout-g12a"; + compatible = "amlogic, cvbsout-sm1"; dev_name = "cvbsout"; status = "okay"; clocks = <&clkc CLKID_VCLK2_ENCI @@ -194,7 +194,7 @@ clk_path = <0>; /* performance: reg_address, reg_value */ - /* g12a */ + /* sm1 */ performance = <0x1bf0 0x9 0x1b56 0x333 0x1b12 0x8080 diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 162173d3bedb..bc2ab925b653 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -175,7 +175,7 @@ }; cvbsout { - compatible = "amlogic, cvbsout-g12a"; + compatible = "amlogic, cvbsout-sm1"; dev_name = "cvbsout"; status = "okay"; clocks = <&clkc CLKID_VCLK2_ENCI @@ -194,7 +194,7 @@ clk_path = <0>; /* performance: reg_address, reg_value */ - /* g12a */ + /* sm1 */ performance = <0x1bf0 0x9 0x1b56 0x333 0x1b12 0x8080 diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 6f2504f2fc1b..b522feda104c 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1201,7 +1201,7 @@ }; vdac { - compatible = "amlogic, vdac-g12a"; + compatible = "amlogic, vdac-sm1"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index 727d2031e884..c4fe2ebd03c8 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -132,7 +132,7 @@ }; cvbsout { - compatible = "amlogic, cvbsout-g12a"; + compatible = "amlogic, cvbsout-sm1"; dev_name = "cvbsout"; status = "okay"; clocks = <&clkc CLKID_VCLK2_ENCI @@ -146,7 +146,7 @@ clk_path = <0>; /* performance: reg_address, reg_value */ - /* g12a */ + /* sm1 */ performance = <0x1bf0 0x9 0x1b56 0x333 0x1b12 0x8080 diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 2def38ace72a..6daa7216aec1 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -173,7 +173,7 @@ }; cvbsout { - compatible = "amlogic, cvbsout-g12a"; + compatible = "amlogic, cvbsout-sm1"; dev_name = "cvbsout"; status = "okay"; clocks = <&clkc CLKID_VCLK2_ENCI @@ -192,7 +192,7 @@ clk_path = <0>; /* performance: reg_address, reg_value */ - /* g12a */ + /* sm1 */ performance = <0x1bf0 0x9 0x1b56 0x333 0x1b12 0x8080 diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 93823ef42fd3..5e556d16583a 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -173,7 +173,7 @@ }; cvbsout { - compatible = "amlogic, cvbsout-g12a"; + compatible = "amlogic, cvbsout-sm1"; dev_name = "cvbsout"; status = "okay"; clocks = <&clkc CLKID_VCLK2_ENCI @@ -192,7 +192,7 @@ clk_path = <0>; /* performance: reg_address, reg_value */ - /* g12a */ + /* sm1 */ performance = <0x1bf0 0x9 0x1b56 0x333 0x1b12 0x8080 diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.c b/drivers/amlogic/media/vout/cvbs/cvbs_out.c index cf611fe41040..467535345c92 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.c +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.c @@ -903,15 +903,13 @@ static void cvbs_performance_regs_dump(void) pr_info("vcbus [0x%x] = 0x%x\n", performance_regs_enci[i], cvbs_out_reg_read(performance_regs_enci[i])); } - if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) + if (cvbs_cpu_type() >= CVBS_CPU_TYPE_G12A) size = sizeof(performance_regs_vdac_g12a)/sizeof(unsigned int); else size = sizeof(performance_regs_vdac)/sizeof(unsigned int); pr_info("------------------------\n"); for (i = 0; i < size; i++) { - if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) + if (cvbs_cpu_type() >= CVBS_CPU_TYPE_G12A) pr_info("hiu [0x%x] = 0x%x\n", performance_regs_vdac_g12a[i], cvbs_out_hiu_read(performance_regs_vdac_g12a[i])); @@ -1208,9 +1206,8 @@ static void cvbs_debug_store(char *buf) cvbs_performance_config_dump(); break; case CMD_VP_SET_PLLPATH: - if (cvbs_cpu_type() != CVBS_CPU_TYPE_G12A && - cvbs_cpu_type() != CVBS_CPU_TYPE_G12B) { - print_info("ERR:Only g12a/b chip supported\n"); + if (cvbs_cpu_type() < CVBS_CPU_TYPE_G12A) { + print_info("ERR:Only after g12a/b chip supported\n"); break; } if (argc != 2) { @@ -1449,6 +1446,18 @@ struct meson_cvbsout_data meson_g12b_cvbsout_data = { .name = "meson-g12b-cvbsout", }; +struct meson_cvbsout_data meson_tl1_cvbsout_data = { + .cntl0_val = 0x906001, + .cpu_id = CVBS_CPU_TYPE_TL1, + .name = "meson-tl1-cvbsout", +}; + +struct meson_cvbsout_data meson_sm1_cvbsout_data = { + .cntl0_val = 0x8f6001, + .cpu_id = CVBS_CPU_TYPE_SM1, + .name = "meson-sm1-cvbsout", +}; + static const struct of_device_id meson_cvbsout_dt_match[] = { { .compatible = "amlogic, cvbsout-gxl", @@ -1465,6 +1474,12 @@ static const struct of_device_id meson_cvbsout_dt_match[] = { }, { .compatible = "amlogic, cvbsout-g12b", .data = &meson_g12b_cvbsout_data, + }, { + .compatible = "amlogic, cvbsout-tl1", + .data = &meson_tl1_cvbsout_data, + }, { + .compatible = "amlogic, cvbsout-sm1", + .data = &meson_sm1_cvbsout_data, }, {}, }; diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.h b/drivers/amlogic/media/vout/cvbs/cvbs_out.h index 79f803caedaf..05f6961225e4 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.h +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.h @@ -51,6 +51,8 @@ enum cvbs_cpu_type { CVBS_CPU_TYPE_TXLX = 3, CVBS_CPU_TYPE_G12A = 4, CVBS_CPU_TYPE_G12B = 5, + CVBS_CPU_TYPE_TL1 = 6, + CVBS_CPU_TYPE_SM1 = 7, }; struct meson_cvbsout_data { diff --git a/drivers/amlogic/media/vout/cvbs/enc_clk_config.c b/drivers/amlogic/media/vout/cvbs/enc_clk_config.c index 28b6fc871f51..379e19b2a850 100644 --- a/drivers/amlogic/media/vout/cvbs/enc_clk_config.c +++ b/drivers/amlogic/media/vout/cvbs/enc_clk_config.c @@ -183,7 +183,8 @@ void set_vmode_clk(void) cvbs_out_hiu_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1); udelay(5); } else if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) { + cvbs_cpu_type() == CVBS_CPU_TYPE_G12B || + cvbs_cpu_type() == CVBS_CPU_TYPE_SM1) { if (cvbs_clk_path & 0x1) { pr_info("config g12a gp0_pll\n"); cvbs_out_hiu_write(HHI_GP0_PLL_CNTL0, 0x180204f7); @@ -229,7 +230,8 @@ void set_vmode_clk(void) } if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) { + cvbs_cpu_type() == CVBS_CPU_TYPE_G12B || + cvbs_cpu_type() == CVBS_CPU_TYPE_SM1) { if (cvbs_clk_path & 0x2) cvbs_set_vid1_clk(cvbs_clk_path & 0x1); else @@ -248,7 +250,8 @@ void set_vmode_clk(void) void disable_vmode_clk(void) { if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) { + cvbs_cpu_type() == CVBS_CPU_TYPE_G12B || + cvbs_cpu_type() == CVBS_CPU_TYPE_SM1) { if (cvbs_clk_path & 0x2) disable_vid1_clk_out(); else diff --git a/drivers/amlogic/media/vout/vdac/vdac_dev.c b/drivers/amlogic/media/vout/vdac/vdac_dev.c index b5b3533c20ad..361e7deefb34 100644 --- a/drivers/amlogic/media/vout/vdac/vdac_dev.c +++ b/drivers/amlogic/media/vout/vdac/vdac_dev.c @@ -589,6 +589,11 @@ struct meson_vdac_data meson_tl1_vdac_data = { .name = "meson-tl1-vdac", }; +struct meson_vdac_data meson_sm1_vdac_data = { + .cpu_id = VDAC_CPU_SM1, + .name = "meson-sm1-vdac", +}; + static const struct of_device_id meson_vdac_dt_match[] = { { .compatible = "amlogic, vdac-gxtvbb", @@ -620,6 +625,9 @@ static const struct of_device_id meson_vdac_dt_match[] = { }, { .compatible = "amlogic, vdac-tl1", .data = &meson_tl1_vdac_data, + }, { + .compatible = "amlogic, vdac-sm1", + .data = &meson_sm1_vdac_data, }, {}, }; @@ -701,7 +709,8 @@ static int __exit aml_vdac_remove(struct platform_device *pdev) static int amvdac_drv_suspend(struct platform_device *pdev, pm_message_t state) { - if (s_vdac_data->cpu_id == VDAC_CPU_TXL) + if (s_vdac_data->cpu_id == VDAC_CPU_TXL || + s_vdac_data->cpu_id == VDAC_CPU_TXLX) vdac_hiu_reg_write(HHI_VDAC_CNTL0, 0); pr_info("%s: suspend module\n", __func__); return 0; @@ -720,8 +729,11 @@ static void amvdac_drv_shutdown(struct platform_device *pdev) pr_info("%s: shutdown module\n", __func__); cntl0 = 0x0; - if (is_meson_txl_cpu() || is_meson_txlx_cpu()) + if (s_vdac_data->cpu_id == VDAC_CPU_TXL || + s_vdac_data->cpu_id == VDAC_CPU_TXLX) cntl1 = 0x0; + else if (s_vdac_data->cpu_id == VDAC_CPU_TL1) + cntl1 = 0x80; else cntl1 = 0x8; vdac_set_ctrl0_ctrl1(cntl0, cntl1); diff --git a/include/linux/amlogic/media/vout/vdac_dev.h b/include/linux/amlogic/media/vout/vdac_dev.h index 69031fe1d853..90e409653c5d 100644 --- a/include/linux/amlogic/media/vout/vdac_dev.h +++ b/include/linux/amlogic/media/vout/vdac_dev.h @@ -27,6 +27,7 @@ enum vdac_cpu_type { VDAC_CPU_TXHD = 5, VDAC_CPU_G12AB = 6, VDAC_CPU_TL1 = 7, + VDAC_CPU_SM1 = 8, VDAC_CPU_MAX, }; From 3b8440fedfa4eee0d30479a87dcf080ab9ef63e6 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Thu, 21 Mar 2019 17:43:57 +0800 Subject: [PATCH 0130/1060] power: sm1: add power control driver [1/1] PD#SWPL-6186 Problem: add power control register Solution: avoid same register access at the same time Verify: sm1_skt Change-Id: I0ec61cda9721c1b95a9d78f7884458f442581fe5 Signed-off-by: Shunzhou Jiang Signed-off-by: Luan Yuan --- MAINTAINERS | 5 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 6 + arch/arm/configs/meson64_a32_defconfig | 1 + arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 6 + arch/arm64/configs/meson64_defconfig | 1 + drivers/amlogic/power/Kconfig | 1 - drivers/amlogic/power/Makefile | 1 + drivers/amlogic/power/power_ctrl.c | 181 ++++++++++++++++++++++ include/linux/amlogic/power_ctrl.h | 25 +++ 9 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 drivers/amlogic/power/power_ctrl.c create mode 100644 include/linux/amlogic/power_ctrl.h diff --git a/MAINTAINERS b/MAINTAINERS index 0fc2a5b1e697..75c79383528b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14780,6 +14780,11 @@ AMLOGIC SM1 CLOCK DRIVERS M: Shunzhou Jiang F: drivers/amlogic/clk/sm1/* +AMLOGIC SM1 POWER CTRL DRIVERS +M: Shunzhou Jiang +F: drivers/amlogic/power/power_ctrl.c +F: include/linux/amlogic/power_ctrl.h + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index e09ef961774d..61aba2f91bb3 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -509,6 +509,12 @@ #thermal-sensor-cells = <1>; }; + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0xff8000e8 0x10>, + <0xff63c100 0x10>; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index f40ccea1e14f..2e1cef27d18a 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -361,6 +361,7 @@ CONFIG_AMLOGIC_WDT_MESON_V3=y CONFIG_AMLOGIC_ESM=y CONFIG_AMLOGIC_WIFI=y CONFIG_AMLOGIC_BT_DEVICE=y +CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PCIE=y CONFIG_AMLOGIC_IRBLASTER=y CONFIG_AMLOGIC_IIO=y diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index b522feda104c..05bfb88dad36 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -509,6 +509,12 @@ #thermal-sensor-cells = <1>; }; + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0x0 0xff8000e8 0x0 0x10>, + <0x0 0xff63c100 0x0 0x10>; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 54e134d37179..fac7f2d7fbee 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -355,6 +355,7 @@ CONFIG_AMLOGIC_WDT_MESON_V3=y CONFIG_AMLOGIC_ESM=y CONFIG_AMLOGIC_WIFI=y CONFIG_AMLOGIC_BT_DEVICE=y +CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PCIE=y CONFIG_AMLOGIC_IRBLASTER=y CONFIG_AMLOGIC_IIO=y diff --git a/drivers/amlogic/power/Kconfig b/drivers/amlogic/power/Kconfig index 3c405e2f0ef3..53941f9e38ce 100644 --- a/drivers/amlogic/power/Kconfig +++ b/drivers/amlogic/power/Kconfig @@ -1,6 +1,5 @@ config AMLOGIC_POWER bool "Amloigc power related driver support" - depends on MACH_MESON8B default n help this config enables to use amlogic power management driver diff --git a/drivers/amlogic/power/Makefile b/drivers/amlogic/power/Makefile index 294b54188e4e..ea86bf8f9f8a 100644 --- a/drivers/amlogic/power/Makefile +++ b/drivers/amlogic/power/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_AMLOGIC_PMU) += aml_pmu/ obj-$(CONFIG_AMLOGIC_PMU_OF) += aml_pmu_of_common.o obj-$(CONFIG_AMLOGIC_M8B_DVFS) += aml_dvfs/ +obj-$(CONFIG_AMLOGIC_POWER) += power_ctrl.o diff --git a/drivers/amlogic/power/power_ctrl.c b/drivers/amlogic/power/power_ctrl.c new file mode 100644 index 000000000000..9654f6a5ca6f --- /dev/null +++ b/drivers/amlogic/power/power_ctrl.c @@ -0,0 +1,181 @@ +/* + * drivers/amlogic/power/power_ctrl.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct power_ctrl { + void __iomem *sleep_addr; + void __iomem *iso_addr; + void __iomem *mempd0_addr; + void __iomem *reset_addr_base; + spinlock_t sleep_lock; + spinlock_t iso_lock; + spinlock_t mempd0_lock; +}; + +struct power_ctrl ctrl; +static bool probe_done; + +int power_ctrl_sleep(bool power_on, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val & (~(1 << shift)); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } else { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val | (1 << shift); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_sleep); + +int power_ctrl_iso(bool power_on, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&(ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val & (~(1 << shift)); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } else { + spin_lock_irqsave((&ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val | (1 << shift); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_iso); + +int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&(ctrl.mempd0_lock), flags); + val = readl(ctrl.mempd0_addr); + val = val & (~(mask_val << shift)); + writel(val, ctrl.mempd0_addr); + spin_unlock_irqrestore(&(ctrl.mempd0_lock), flags); + } else { + spin_lock_irqsave((&ctrl.mempd0_lock), flags); + val = readl(ctrl.mempd0_addr); + val = val | (mask_val << shift); + writel(val, ctrl.mempd0_addr); + spin_unlock_irqrestore(&(ctrl.mempd0_lock), flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_mempd0); + +static int amlogic_powerctrl_probe(struct platform_device *pdev) +{ + struct resource *res; + struct device *dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Fail to get power ctrl memory res0\n"); + return -ENXIO; + } + + ctrl.sleep_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(ctrl.sleep_addr)) + return PTR_ERR(ctrl.sleep_addr); + + ctrl.iso_addr = ctrl.sleep_addr + 4; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "Fail to get power ctrl memory res1\n"); + return -ENXIO; + } + ctrl.mempd0_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(ctrl.mempd0_addr)) + return PTR_ERR(ctrl.mempd0_addr); + + spin_lock_init(&ctrl.sleep_lock); + spin_lock_init(&ctrl.iso_lock); + spin_lock_init(&ctrl.mempd0_lock); + + probe_done = 1; + return 0; +} + +static int amlogic_powerctrl_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + devm_iounmap(dev, ctrl.sleep_addr); + devm_iounmap(dev, ctrl.mempd0_addr); + devm_iounmap(dev, ctrl.reset_addr_base); + return 0; +} + +static const struct of_device_id amlogic_powerctrl_match[] = { + { .compatible = "amlogic, sm1-powerctrl", }, + {} +}; + +static struct platform_driver amlogic_powerctrl_driver = { + .driver = { + .name = "amlogic, sm1-powerctrl", + .of_match_table = amlogic_powerctrl_match, + }, + .probe = amlogic_powerctrl_probe, + .remove = amlogic_powerctrl_remove, +}; + +static int __init amlogic_powerctrl_init(void) +{ + return platform_driver_register(&amlogic_powerctrl_driver); +} +arch_initcall(amlogic_powerctrl_init); + +MODULE_AUTHOR("shunzhou jiang + +int power_ctrl_sleep(bool power_on, unsigned int shift); +int power_ctrl_iso(bool power_on, unsigned int shift); +int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift); +#endif /*_POWER_CTRL_H_*/ From bca86db20ee799471f35b5cac4d593b5cae8a8d2 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Fri, 29 Mar 2019 17:32:18 +0800 Subject: [PATCH 0131/1060] usb: add usb power control [1/1] PD#SWPL-6186 Problem: add usb power control Solution: add usb power control Verify: sm1 Test: pass Change-Id: I6c2822105ae02f955e56dc4d64163e8e14a7e329 Signed-off-by: Yue Wang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 24 ++++--- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 25 ++++--- drivers/amlogic/pci/pcie-amlogic-v2.c | 62 +++++++++------- drivers/amlogic/pci/pcie-amlogic.h | 6 +- drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c | 65 ++++++++++------- drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c | 71 +++++++++++-------- include/linux/amlogic/usb-v2.h | 10 ++- 7 files changed, 158 insertions(+), 105 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 61aba2f91bb3..2d2be49d07cc 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -374,9 +374,7 @@ reg = <0xffe09000 0x80 0xffd01008 0x100 0xff636000 0x2000 - 0xff63a000 0x2000 - 0xff8000e8 0x10 - 0xff63c100 0x4>; + 0xff63a000 0x2000>; pll-setting-1 = <0x09400414>; pll-setting-2 = <0x927E0000>; pll-setting-3 = <0xac5f69e5>; @@ -387,14 +385,16 @@ pll-setting-8 = <0xe000c>; version = <2>; pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; }; usb3_phy_v2: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3-v2"; status = "disable"; reg = <0xffe09080 0x20 - 0xff8000e8 0x10 - 0xff63c100 0x4 0xffd01008 0x100>; phy-reg = <0xff646000>; phy-reg-size = <0x2000>; @@ -404,6 +404,10 @@ clocks = <&clkc CLKID_PCIE_PLL>; clock-names = "pcie_refpll"; pwr-ctl = <1>; + u3-ctrl-sleep-shift = <18>; + u3-hhi-mem-pd-shift = <26>; + u3-hhi-mem-pd-mask = <0xf>; + u3-ctrl-iso-shift = <18>; }; dwc2_a: dwc2_a@ff400000 { @@ -1035,11 +1039,9 @@ 0xff648000 0x2000 0xfc400000 0x200000 0xff646000 0x2000 - 0xffd01080 0x10 - 0xff8000e8 0x8 - 0xff63c100 0x4>; + 0xffd01080 0x10>; reg-names = "elbi", "cfg", "config", "phy", - "reset", "pwr", "hii"; + "reset"; interrupts = <0 221 0>; #interrupt-cells = <1>; bus-range = <0x0 0xff>; @@ -1067,6 +1069,10 @@ pcie-phy-rst-bit = <14>; pcie-ctrl-a-rst-bit = <12>; pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 05bfb88dad36..6a16ae6d727c 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -374,9 +374,7 @@ reg = <0x0 0xffe09000 0x0 0x80 0x0 0xffd01008 0x0 0x100 0x0 0xff636000 0x0 0x2000 - 0x0 0xff63a000 0x0 0x2000 - 0x0 0xff8000e8 0x0 0x10 - 0x0 0xff63c100 0x0 0x4>; + 0x0 0xff63a000 0x0 0x2000>; pll-setting-1 = <0x09400414>; pll-setting-2 = <0x927E0000>; pll-setting-3 = <0xac5f69e5>; @@ -387,14 +385,16 @@ pll-setting-8 = <0xe000c>; version = <2>; pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; }; usb3_phy_v2: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3-v2"; status = "disable"; reg = <0x0 0xffe09080 0x0 0x20 - 0x0 0xff8000e8 0x0 0x10 - 0x0 0xff63c100 0x0 0x4 0x0 0xffd01008 0x0 0x100>; phy-reg = <0xff646000>; phy-reg-size = <0x2000>; @@ -404,6 +404,10 @@ clocks = <&clkc CLKID_PCIE_PLL>; clock-names = "pcie_refpll"; pwr-ctl = <1>; + u3-ctrl-sleep-shift = <18>; + u3-hhi-mem-pd-shift = <26>; + u3-hhi-mem-pd-mask = <0xf>; + u3-ctrl-iso-shift = <18>; }; dwc2_a: dwc2_a@ff400000 { @@ -1035,11 +1039,8 @@ 0x0 0xff648000 0x0 0x2000 0x0 0xfc400000 0x0 0x200000 0x0 0xff646000 0x0 0x2000 - 0x0 0xffd01080 0x0 0x10 - 0x0 0xff8000e8 0x0 0x8 - 0x0 0xff63c100 0x0 0x4>; - reg-names = "elbi", "cfg", "config", "phy", - "reset", "pwr", "hii"; + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; interrupts = <0 221 0>; #interrupt-cells = <1>; bus-range = <0x0 0xff>; @@ -1067,6 +1068,10 @@ pcie-phy-rst-bit = <14>; pcie-ctrl-a-rst-bit = <12>; pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; status = "disabled"; }; diff --git a/drivers/amlogic/pci/pcie-amlogic-v2.c b/drivers/amlogic/pci/pcie-amlogic-v2.c index 8b9454f8ccd5..479e445b7e76 100644 --- a/drivers/amlogic/pci/pcie-amlogic-v2.c +++ b/drivers/amlogic/pci/pcie-amlogic-v2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "../drivers/pci/host/pcie-designware.h" #include "pcie-amlogic.h" @@ -684,10 +685,10 @@ static void power_switch_to_pcie(struct pcie_phy *phy) { u32 val; - writel(readl(phy->power_base) & (~(0x1<<18)), phy->power_base); + power_ctrl_sleep(1, phy->pcie_ctrl_sleep_shift); - writel(readl(phy->hhi_mem_pd_base) & (~(0xf<<26)), - phy->hhi_mem_pd_base); + power_ctrl_mempd0(1, phy->pcie_hhi_mem_pd_mask, + phy->pcie_hhi_mem_pd_shift); udelay(100); val = readl((void __iomem *)(unsigned long)phy->reset_base); @@ -695,8 +696,7 @@ static void power_switch_to_pcie(struct pcie_phy *phy) (void __iomem *)(unsigned long)phy->reset_base); udelay(100); - writel(readl(phy->power_base+0x4) & (~(0x1<<18)), - phy->power_base + 0x4); + power_ctrl_iso(1, phy->pcie_ctrl_iso_shift); val = readl((void __iomem *)(unsigned long)phy->reset_base); writel((val | (0x1<<12)), @@ -716,8 +716,6 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) struct resource *phy_base; struct resource *cfg_base; struct resource *reset_base; - struct resource *power_base = NULL; - struct resource *hhi_mem_pd_base = NULL; int ret; int pcie_num = 0; int num_lanes = 0; @@ -732,6 +730,7 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) int pcie_phy_rst_bit = 0; int pcie_ctrl_a_rst_bit = 0; u32 pwr_ctl = 0; + const void *prop; dev_info(&pdev->dev, "amlogic_pcie_probe!\n"); @@ -793,26 +792,37 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) amlogic_pcie->pwr_ctl = pwr_ctl; if (pwr_ctl) { - power_base = platform_get_resource_byname( - pdev, IORESOURCE_MEM, "pwr"); - if (power_base) { - amlogic_pcie->phy->power_base = - ioremap(power_base->start, - resource_size(power_base)); - if (IS_ERR(amlogic_pcie->phy->power_base)) - return PTR_ERR(amlogic_pcie->phy->power_base); - } + prop = of_get_property(dev->of_node, + "pcie-ctrl-sleep-shift", NULL); + if (prop) + amlogic_pcie->phy->pcie_ctrl_sleep_shift = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; - hhi_mem_pd_base = platform_get_resource_byname( - pdev, IORESOURCE_MEM, "hii"); - if (hhi_mem_pd_base) { - amlogic_pcie->phy->hhi_mem_pd_base = - ioremap(hhi_mem_pd_base->start, - resource_size(hhi_mem_pd_base)); - if (IS_ERR(amlogic_pcie->phy->hhi_mem_pd_base)) - return PTR_ERR(amlogic_pcie-> - phy->hhi_mem_pd_base); - } + prop = of_get_property(dev->of_node, + "pcie-hhi-mem-pd-shift", NULL); + if (prop) + amlogic_pcie->phy->pcie_hhi_mem_pd_shift = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "pcie-hhi-mem-pd-mask", NULL); + if (prop) + amlogic_pcie->phy->pcie_hhi_mem_pd_mask = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "pcie-ctrl-iso-shift", NULL); + if (prop) + amlogic_pcie->phy->pcie_ctrl_iso_shift = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; } if (!amlogic_pcie->phy->reset_base) { diff --git a/drivers/amlogic/pci/pcie-amlogic.h b/drivers/amlogic/pci/pcie-amlogic.h index 88a6b871e042..394a33a78663 100644 --- a/drivers/amlogic/pci/pcie-amlogic.h +++ b/drivers/amlogic/pci/pcie-amlogic.h @@ -162,8 +162,10 @@ struct pcie_phy { u32 reset_state; void __iomem *phy_base; /* DT 1st resource */ void __iomem *reset_base;/* DT 3nd resource */ - void __iomem *power_base; - void __iomem *hhi_mem_pd_base; + u32 pcie_ctrl_sleep_shift; + u32 pcie_hhi_mem_pd_mask; + u32 pcie_ctrl_iso_shift; + u32 pcie_hhi_mem_pd_shift; }; diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index 1dc5072c1131..a3e13407de97 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "phy-aml-new-usb-v2.h" struct amlogic_usb_v2 *g_phy2_v2; @@ -226,17 +227,15 @@ static void amlogic_new_usb2phy_shutdown(struct usb_phy *x) void power_switch_to_usb(struct amlogic_usb_v2 *phy) { /* Powerup usb_comb */ - writel(readl(phy->power_base) & (~(0x1<<17)), phy->power_base); - writel(readl(phy->hhi_mem_pd_base) & (~(0x3<<30)), - phy->hhi_mem_pd_base); + power_ctrl_sleep(1, phy->u2_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u2_hhi_mem_pd_mask, phy->u2_hhi_mem_pd_shift); udelay(100); writel((readl(phy->reset_regs + (0x21 * 4 - 0x8)) & ~(0x1 << 2)), phy->reset_regs + (0x21 * 4 - 0x8)); udelay(100); - writel(readl(phy->power_base+0x4) & (~(0x1<<17)), - phy->power_base + 0x4); + power_ctrl_iso(1, phy->u2_ctrl_iso_shift); writel((readl(phy->reset_regs + (0x21 * 4 - 0x8)) | (0x1 << 2)), phy->reset_regs + (0x21 * 4 - 0x8)); @@ -250,13 +249,9 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) struct resource *phy_mem; struct resource *reset_mem; struct resource *phy_cfg_mem[4]; - struct resource *power_mem = NULL; - struct resource *hhi_mem_pd_mem = NULL; void __iomem *phy_base; void __iomem *reset_base = NULL; void __iomem *phy_cfg_base[4]; - void __iomem *power_base = NULL; - void __iomem *hhi_mem_pd_base = NULL; int portnum = 0; int phy_version = 0; const void *prop; @@ -264,6 +259,10 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) int retval; u32 pll_setting[8]; u32 pwr_ctl = 0; + u32 u2_ctrl_sleep_shift = 0; + u32 u2_hhi_mem_pd_shift = 0; + u32 u2_hhi_mem_pd_mask = 0; + u32 u2_ctrl_iso_shift = 0; prop = of_get_property(dev->of_node, "portnum", NULL); if (prop) @@ -316,23 +315,33 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) pwr_ctl = 0; if (pwr_ctl) { - power_mem = platform_get_resource - (pdev, IORESOURCE_MEM, 2 + portnum); - if (power_mem) { - power_base = ioremap(power_mem->start, - resource_size(power_mem)); - if (IS_ERR(power_base)) - return PTR_ERR(power_base); - } + prop = of_get_property(dev->of_node, + "u2-ctrl-sleep-shift", NULL); + if (prop) + u2_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; - hhi_mem_pd_mem = platform_get_resource - (pdev, IORESOURCE_MEM, 3 + portnum); - if (hhi_mem_pd_mem) { - hhi_mem_pd_base = ioremap(hhi_mem_pd_mem->start, - resource_size(hhi_mem_pd_mem)); - if (IS_ERR(hhi_mem_pd_base)) - return PTR_ERR(hhi_mem_pd_base); - } + prop = of_get_property(dev->of_node, + "u2-hhi-mem-pd-shift", NULL); + if (prop) + u2_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u2-hhi-mem-pd-mask", NULL); + if (prop) + u2_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u2-ctrl-iso-shift", NULL); + if (prop) + u2_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; } phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); @@ -410,8 +419,10 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) } if (pwr_ctl) { - phy->power_base = power_base; - phy->hhi_mem_pd_base = hhi_mem_pd_base; + phy->u2_ctrl_sleep_shift = u2_ctrl_sleep_shift; + phy->u2_hhi_mem_pd_shift = u2_hhi_mem_pd_shift; + phy->u2_hhi_mem_pd_mask = u2_hhi_mem_pd_mask; + phy->u2_ctrl_iso_shift = u2_ctrl_iso_shift; power_switch_to_usb(phy); } diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c index 0f1839b5ae41..3c97500bb819 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "phy-aml-new-usb-v2.h" #define HOST_MODE 0 @@ -486,10 +487,8 @@ static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) { u32 val; - writel(readl(phy->power_base) & (~(0x1<<18)), phy->power_base); - - writel(readl(phy->hhi_mem_pd_base) & (~(0xf<<26)), - phy->hhi_mem_pd_base); + power_ctrl_sleep(1, phy->u3_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u3_hhi_mem_pd_mask, phy->u3_hhi_mem_pd_shift); udelay(100); val = readl((void __iomem *) @@ -498,8 +497,8 @@ static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); udelay(100); - writel(readl(phy->power_base+0x4) & (~(0x1<<18)), - phy->power_base + 0x4); + power_ctrl_iso(1, phy->u3_ctrl_iso_shift); + val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); writel((val | (0x1<<12)), (void __iomem *) @@ -512,13 +511,9 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) struct amlogic_usb_v2 *phy; struct device *dev = &pdev->dev; struct resource *phy_mem; - struct resource *power_mem = NULL; - struct resource *hhi_mem_pd_mem = NULL; struct resource *reset_mem; void __iomem *phy_base; void __iomem *phy3_base; - void __iomem *power_base = NULL; - void __iomem *hhi_mem_pd_base = NULL; void __iomem *reset_base = NULL; unsigned int phy3_mem; unsigned int phy3_mem_size = 0; @@ -536,6 +531,10 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) int ret; struct device_node *tsi_pci; u32 pwr_ctl = 0; + u32 u3_ctrl_sleep_shift = 0; + u32 u3_hhi_mem_pd_shift = 0; + u32 u3_hhi_mem_pd_mask = 0; + u32 u3_ctrl_iso_shift = 0; gpio_name = of_get_property(dev->of_node, "gpio-vbus-power", NULL); if (gpio_name) { @@ -593,29 +592,41 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) pwr_ctl = 0; if (pwr_ctl) { - power_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (power_mem) { - power_base = ioremap(power_mem->start, - resource_size(power_mem)); - if (IS_ERR(power_base)) - return PTR_ERR(power_base); - } - - hhi_mem_pd_mem = platform_get_resource(pdev, IORESOURCE_MEM, 2); - if (hhi_mem_pd_mem) { - hhi_mem_pd_base = ioremap(hhi_mem_pd_mem->start, - resource_size(hhi_mem_pd_mem)); - if (IS_ERR(hhi_mem_pd_base)) - return PTR_ERR(hhi_mem_pd_base); - } - - reset_mem = platform_get_resource(pdev, IORESOURCE_MEM, 3); + reset_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (reset_mem) { reset_base = ioremap(reset_mem->start, resource_size(reset_mem)); if (IS_ERR(reset_base)) return PTR_ERR(reset_base); } + + prop = of_get_property(dev->of_node, + "u3-ctrl-sleep-shift", NULL); + if (prop) + u3_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u3-hhi-mem-pd-shift", NULL); + if (prop) + u3_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u3-hhi-mem-pd-mask", NULL); + if (prop) + u3_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u3-ctrl-iso-shift", NULL); + if (prop) + u3_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; } retval = of_property_read_u32 @@ -684,8 +695,10 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) /* set the phy from pcie to usb3 */ if (phy->portnum > 0) { if (phy->pwr_ctl) { - phy->power_base = power_base; - phy->hhi_mem_pd_base = hhi_mem_pd_base; + phy->u3_ctrl_sleep_shift = u3_ctrl_sleep_shift; + phy->u3_hhi_mem_pd_shift = u3_hhi_mem_pd_shift; + phy->u3_hhi_mem_pd_mask = u3_hhi_mem_pd_mask; + phy->u3_ctrl_iso_shift = u3_ctrl_iso_shift; phy->reset_regs = reset_base; power_switch_to_pcie(phy); } diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index dc3774e4ef13..4d5df3a8469c 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -169,8 +169,6 @@ struct amlogic_usb_v2 { void __iomem *phy3_cfg_r4; void __iomem *phy3_cfg_r5; void __iomem *usb2_phy_cfg; - void __iomem *power_base; - void __iomem *hhi_mem_pd_base; u32 pll_setting[8]; int phy_cfg_state[4]; /* Set VBus Power though GPIO */ @@ -183,6 +181,14 @@ struct amlogic_usb_v2 { int suspend_flag; int phy_version; int pwr_ctl; + u32 u2_ctrl_sleep_shift; + u32 u2_hhi_mem_pd_mask; + u32 u2_ctrl_iso_shift; + u32 u2_hhi_mem_pd_shift; + u32 u3_ctrl_sleep_shift; + u32 u3_hhi_mem_pd_mask; + u32 u3_ctrl_iso_shift; + u32 u3_hhi_mem_pd_shift; struct clk *clk; }; From 8d05786f5a7a0c0480fbe475d4eb14a0bcdf43a3 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Thu, 28 Mar 2019 17:42:39 +0800 Subject: [PATCH 0132/1060] ge2d: sm1: add ge2d power control [1/1] PD#SWPL-6186 Problem: add ge2d power control Solution: add ge2d power control Verify: SM1-AC200 board Change-Id: I3ea08c4d800f78e5187b6ae334849db02309ce0e Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_io.h | 14 +++- drivers/amlogic/media/common/ge2d/ge2d_main.c | 25 ++++--- drivers/amlogic/media/common/ge2d/ge2d_wq.c | 72 +++++++++++-------- include/linux/amlogic/media/ge2d/ge2d.h | 7 +- 4 files changed, 73 insertions(+), 45 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_io.h b/drivers/amlogic/media/common/ge2d/ge2d_io.h index f8a3cb173202..f5f69df58ca1 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_io.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_io.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "ge2d_log.h" @@ -154,11 +155,11 @@ static void ge2d_c_setb(unsigned int _reg, unsigned int _value, (((_value)&((1L<<(_len))-1)) << (_start)))); } -static inline void ge2d_set_bus_bits(unsigned int bus_type, +static inline void ge2d_set_pwr_tbl_bits(unsigned int table_type, unsigned int reg, unsigned int val, unsigned int start, unsigned int len) { - switch (bus_type) { + switch (table_type) { case CBUS_BASE: ge2d_c_setb(reg, val, start, len); break; @@ -168,6 +169,15 @@ static inline void ge2d_set_bus_bits(unsigned int bus_type, case HIUBUS_BASE: ge2d_hiu_setb(reg, val, start, len); break; + case GEN_PWR_SLEEP0: + power_ctrl_sleep(val ? 0 : 1, start); + break; + case GEN_PWR_ISO0: + power_ctrl_iso(val ? 0 : 1, start); + break; + case MEM_PD_REG0: + power_ctrl_mempd0(val ? 0 : 1, 0xFF, start); + break; default: ge2d_log_err("unsupported bus type\n"); break; diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 459e164e8688..6481d9c3cbb8 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -54,6 +54,7 @@ #define GE2D_CLASS_NAME "ge2d" #define MAX_GE2D_CLK 500000000 #define HHI_MEM_PD_REG0 0x40 +#define RESET2_LEVEL 0x422 struct ge2d_device_s { char name[20]; @@ -1036,23 +1037,29 @@ static int ge2d_release(struct inode *inode, struct file *file) static struct ge2d_ctrl_s default_poweron_ctrl[] = { /* power up ge2d */ - {AOBUS_BASE, AO_RTI_GEN_PWR_SLEEP0, 0, 19, 1, 0}, + {GEN_PWR_SLEEP0, AO_RTI_GEN_PWR_SLEEP0, 0, 19, 1, 0}, /* Power up memory */ - {HIUBUS_BASE, HHI_MEM_PD_REG0, 0, 18, 8, 100}, + {MEM_PD_REG0, HHI_MEM_PD_REG0, 0, 18, 8, 100}, + /* reset */ + {CBUS_BASE, RESET2_LEVEL, 0, 6, 1, 0}, /* remove isolation */ - {AOBUS_BASE, AO_RTI_GEN_PWR_ISO0, 0, 19, 1, 0} + {GEN_PWR_ISO0, AO_RTI_GEN_PWR_ISO0, 0, 19, 1, 0}, + /* pull up reset */ + {CBUS_BASE, RESET2_LEVEL, 1, 6, 1, 0} }; static struct ge2d_ctrl_s default_poweroff_ctrl[] = { + /* reset */ + {CBUS_BASE, RESET2_LEVEL, 0, 6, 1, 0}, /* add isolation */ - {AOBUS_BASE, AO_RTI_GEN_PWR_ISO0, 1, 19, 1, 0}, + {GEN_PWR_ISO0, AO_RTI_GEN_PWR_ISO0, 1, 19, 1, 0}, /* Power down memory */ - {HIUBUS_BASE, HHI_MEM_PD_REG0, 0xff, 18, 8, 0}, + {MEM_PD_REG0, HHI_MEM_PD_REG0, 0xFF, 18, 8, 0}, /* power down ge2d */ - {AOBUS_BASE, AO_RTI_GEN_PWR_SLEEP0, 1, 19, 1, 0} + {GEN_PWR_SLEEP0, AO_RTI_GEN_PWR_SLEEP0, 1, 19, 1, 0} }; -struct ge2d_power_table_s default_poweron_table = {3, default_poweron_ctrl}; -struct ge2d_power_table_s default_poweroff_table = {3, default_poweroff_ctrl}; +struct ge2d_power_table_s default_poweron_table = {5, default_poweron_ctrl}; +struct ge2d_power_table_s default_poweroff_table = {4, default_poweroff_ctrl}; static struct ge2d_device_data_s ge2d_gxl = { .ge2d_rate = 400000000, @@ -1215,7 +1222,6 @@ static int ge2d_probe(struct platform_device *pdev) goto failed1; } ge2d_log_info("clock clk_ge2d source %p\n", clk); - ge2d_pwr_config(true); clk_prepare_enable(clk); clk_vapb0 = devm_clk_get(&pdev->dev, "clk_vapb_0"); @@ -1285,7 +1291,6 @@ static int ge2d_remove(struct platform_device *pdev) ge2d_log_info("%s\n", __func__); ge2d_wq_deinit(); remove_ge2d_device(); - ge2d_pwr_config(false); return 0; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index bc6fab6d6759..3c9bf8632e86 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -120,6 +120,37 @@ static const int default_ge2d_color_lut[] = { GE2D_FORMAT_S32_ARGB,/* BPP_TYPE_32_ARGB=32, */ }; +static void ge2d_pre_init(void) +{ + struct ge2d_gen_s ge2d_gen_cfg; + + ge2d_gen_cfg.interrupt_ctrl = 0x02; + ge2d_gen_cfg.dp_on_cnt = 0; + ge2d_gen_cfg.dp_off_cnt = 0; + ge2d_gen_cfg.dp_onoff_mode = 0; + ge2d_gen_cfg.vfmt_onoff_en = 0; + /* fifo size control, 00: 512, 01: 256, 10: 128 11: 96 */ + ge2d_gen_cfg.fifo_size = 0; + /* fifo burst control, 00: 24x64, 01: 32x64 + * 10: 48x64, 11:64x64 + */ + ge2d_gen_cfg.burst_ctrl = 0; + ge2d_set_gen(&ge2d_gen_cfg); +} + +static int ge2d_clk_config(bool enable) +{ + if (ge2d_clk == NULL) + return -1; + if (enable) + clk_prepare_enable(ge2d_clk); + else + clk_disable_unprepare(ge2d_clk); + + return 0; +} + + void ge2d_pwr_config(bool enable) { int i, table_size; @@ -128,34 +159,29 @@ void ge2d_pwr_config(bool enable) if (ge2d_meson_dev.has_self_pwr) { if (enable) { - power_table = ge2d_meson_dev.poweron_table->power_btale; + power_table = ge2d_meson_dev.poweron_table->power_table; table_size = ge2d_meson_dev.poweron_table->table_size; } else { power_table = - ge2d_meson_dev.poweroff_table->power_btale; + ge2d_meson_dev.poweroff_table->power_table; table_size = ge2d_meson_dev.poweroff_table->table_size; } for (i = 0; i < table_size; i++) { tmp = power_table[i]; - ge2d_set_bus_bits(tmp.bus_type, tmp.reg, tmp.val, + ge2d_set_pwr_tbl_bits(tmp.table_type, tmp.reg, tmp.val, tmp.start, tmp.len); if (tmp.udelay > 0) udelay(tmp.udelay); } } -} -static int ge2d_clk_config(bool enable) -{ - if (ge2d_clk == NULL) - return -1; + ge2d_clk_config(enable); + if (enable) { - clk_prepare_enable(ge2d_clk); - } else { - clk_disable_unprepare(ge2d_clk); + ge2d_soft_rst(); + ge2d_pre_init(); } - return 0; } static int get_queue_member_count(struct list_head *head) @@ -492,12 +518,12 @@ static int ge2d_monitor_thread(void *data) /* setup current_wq here. */ while (ge2d_manager.process_queue_state != GE2D_PROCESS_QUEUE_STOP) { ret = down_interruptible(&manager->event.cmd_in_sem); - ge2d_clk_config(true); + ge2d_pwr_config(true); while ((manager->current_wq = get_next_work_queue(manager)) != NULL) ge2d_process_work_queue(manager->current_wq); if (!ge2d_dump_reg_enable) - ge2d_clk_config(false); + ge2d_pwr_config(false); } ge2d_log_info("exit ge2d_monitor_thread\n"); return 0; @@ -2566,8 +2592,6 @@ EXPORT_SYMBOL(destroy_ge2d_work_queue); int ge2d_wq_init(struct platform_device *pdev, int irq, struct clk *clk) { - struct ge2d_gen_s ge2d_gen_cfg; - ge2d_manager.pdev = pdev; ge2d_irq = irq; ge2d_clk = clk; @@ -2596,21 +2620,7 @@ int ge2d_wq_init(struct platform_device *pdev, ge2d_manager.buffer = ge2d_dma_buffer_create(); if (!ge2d_manager.buffer) return -1; - ge2d_clk_config(true); - ge2d_soft_rst(); - ge2d_gen_cfg.interrupt_ctrl = 0x02; - ge2d_gen_cfg.dp_on_cnt = 0; - ge2d_gen_cfg.dp_off_cnt = 0; - ge2d_gen_cfg.dp_onoff_mode = 0; - ge2d_gen_cfg.vfmt_onoff_en = 0; - /* fifo size control, 00: 512, 01: 256, 10: 128 11: 96 */ - ge2d_gen_cfg.fifo_size = 0; - /* fifo burst control, 00: 24x64, 01: 32x64 - * 10: 48x64, 11:64x64 - */ - ge2d_gen_cfg.burst_ctrl = 0; - ge2d_set_gen(&ge2d_gen_cfg); - ge2d_clk_config(false); + if (ge2d_start_monitor()) { ge2d_log_err("ge2d create thread error\n"); return -1; diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index 883342ee9980..c3fdd915b454 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -1016,10 +1016,13 @@ enum { CBUS_BASE, AOBUS_BASE, HIUBUS_BASE, + GEN_PWR_SLEEP0, + GEN_PWR_ISO0, + MEM_PD_REG0, }; struct ge2d_ctrl_s { - unsigned int bus_type; + unsigned int table_type; unsigned int reg; unsigned int val; unsigned int start; @@ -1029,7 +1032,7 @@ struct ge2d_ctrl_s { struct ge2d_power_table_s { unsigned int table_size; - struct ge2d_ctrl_s *power_btale; + struct ge2d_ctrl_s *power_table; }; struct ge2d_device_data_s { From ab5470dcb7a160350f947b5a194f8e06a9a35d79 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Mon, 3 Dec 2018 22:04:24 +0800 Subject: [PATCH 0133/1060] vpp: sr: remove the vpp misc operation in sr function [1/1] PD#SWPL-2613 Problem: sr mux in vpp misc is set incorrectly. Solution: move the vpp misc operation together Verify: verify by x301 Change-Id: Ie813e5b04b97a4481c2e45bcf0c8b4c065fb9f69 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 27 ++++++ drivers/amlogic/media/video_sink/vpp.c | 94 +++++++++++++------ .../linux/amlogic/media/video_sink/video.h | 4 + include/linux/amlogic/media/video_sink/vpp.h | 4 + 4 files changed, 100 insertions(+), 29 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index dc2830b98564..963524cc3478 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -7575,6 +7575,33 @@ SET_FILTER: u32 set_value = 0; force_flush |= vpp_zorder_check(); + /* for sr core0, put it between prebld & pps as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE0_SUPPORT)) + if (cur_frame_par->sr0_position) + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + else + vpp_misc_set &= + ~SR0_AFTER_DNLP; + else + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + /* for sr core1, put it before post blend as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE1_SUPPORT)) + if (cur_frame_par->sr1_position) + vpp_misc_set |= + DNLP_SR1_CM; + else + vpp_misc_set &= + ~SR1_AFTER_POSTBLEN; + else + vpp_misc_set |= + DNLP_SR1_CM; + vpp_misc_set &= ((1 << 29) | VPP_CM_ENABLE | (0x1ff << VPP_VD2_ALPHA_BIT) | diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 2535a42d695b..33a014fb0cca 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1776,39 +1776,16 @@ int vpp_set_super_scaler_regs( data_path_chose = 6; else data_path_chose = 5; - if (is_meson_tl1_cpu()) { - if (scaler_path_sel == CORE0_PPS_CORE1) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 3, 1); - } else if (scaler_path_sel == CORE0_CORE1_PPS) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 3, 1); - - } else if (scaler_path_sel == PPS_CORE0_CORE1) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 1, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 3, 1); - - } else if (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 1, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 3, 1); - } - } else if ((scaler_path_sel == CORE0_PPS_CORE1) || - (scaler_path_sel == CORE1_BEFORE_PPS) || - (scaler_path_sel == CORE0_BEFORE_PPS)) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); - else + if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXHD) { + if ((scaler_path_sel == CORE0_PPS_CORE1) || + (scaler_path_sel == CORE1_BEFORE_PPS) || + (scaler_path_sel == CORE0_BEFORE_PPS)) { VSYNC_WR_MPEG_REG_BITS(VPP_VE_ENABLE_CTRL, 0, data_path_chose, 1); - } else { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { - if (scaler_path_sel == CORE0_AFTER_PPS) - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 1, 1); - else - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); - } else + } else { VSYNC_WR_MPEG_REG_BITS(VPP_VE_ENABLE_CTRL, 1, data_path_chose, 1); + } } if (super_scaler == 0) { VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0); @@ -1831,10 +1808,13 @@ static void vpp_set_super_scaler( next_frame_par->VPP_vsc_startp + 1; u32 src_width = next_frame_par->video_input_w; u32 src_height = next_frame_par->video_input_h; + u32 sr_path; /*for sr adjust*/ vpp_super_scaler_support(); + next_frame_par->sr_core_support = sr_support; + hor_sc_multiple_num = (1 << PPS_FRAC_BITS) / next_frame_par->vpp_filter.vpp_hsc_start_phase_step; ver_sc_multiple_num = SUPER_SCALER_V_FACTOR*(1 << PPS_FRAC_BITS)/ @@ -2148,6 +2128,62 @@ static void vpp_set_super_scaler( next_frame_par->VPP_pic_in_height_ <<= next_frame_par->supsc1_vert_ratio; } + + sr_path = next_frame_par->supscl_path; + /* path config */ + if (is_meson_tl1_cpu()) { + if (sr_path == CORE0_PPS_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } else if (sr_path == PPS_CORE0_CORE1) { + next_frame_par->sr0_position = 0; + next_frame_par->sr1_position = 1; + } else if (sr_path == + PPS_CORE0_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 0; + next_frame_par->sr1_position = 0; + } else if (sr_path == + CORE0_PPS_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } + } else if (is_meson_txhd_cpu() + || is_meson_g12a_cpu() + || is_meson_g12b_cpu()) { + if (sr_path == CORE0_BEFORE_PPS) + next_frame_par->sr0_position = 1; + else if (sr_path == CORE0_AFTER_PPS) + next_frame_par->sr0_position = 0; + else + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else if (is_meson_gxlx_cpu()) { + if (sr_path == CORE1_BEFORE_PPS) + next_frame_par->sr1_position = 1; + else if (sr_path == CORE1_AFTER_PPS) + next_frame_par->sr1_position = 0; + else + next_frame_par->sr1_position = 1; + next_frame_par->sr0_position = 0; + } else if (is_meson_txlx_cpu() + || is_meson_txl_cpu() + || is_meson_gxtvbb_cpu()) { + if (sr_path == CORE0_PPS_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } else if (sr_path == + CORE0_PPS_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } + } + if (super_debug) { pr_info("layer0: spsc0_w_in=%u, spsc0_h_in=%u, spsc1_w_in=%u, spsc1_h_in=%u.\n", next_frame_par->spsc0_w_in, next_frame_par->spsc0_h_in, diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 56cdaefc22fa..04cb35bdf12c 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -99,7 +99,11 @@ enum { #define VPP_POST_FG_SEL_MASK (1 << 4) #define VPP_POST_FG_OSD2 (1 << 4) #define VPP_POST_FG_OSD1 (0 << 4) +#define DNLP_SR1_CM (1 << 3) +#define SR1_AFTER_POSTBLEN (0 << 3) #define VPP_FIFO_RESET_DE (1 << 2) +#define PREBLD_SR0_VD1_SCALER (1 << 1) +#define SR0_AFTER_DNLP (0 << 1) #define VPP_OUT_SATURATE (1 << 0) #define VDIF_RESET_ON_GO_FIELD (1<<29) diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index 577c5bb561dc..f61c44dacc4a 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -151,6 +151,9 @@ struct vpp_frame_par_s { bool nocomp; + u8 sr0_position; + u8 sr1_position; + u8 sr_core_support; }; struct disp_info_s { @@ -198,6 +201,7 @@ enum select_scaler_path_e { /*tl1 have core0/core1, support below mode*/ PPS_CORE0_CORE1, PPS_CORE0_POSTBLEND_CORE1, + CORE0_PPS_POSTBLEND_CORE1, SCALER_PATH_MAX, }; /* From d2aa8389e3e1b59a52801d3beb75370f0542a938 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Wed, 20 Mar 2019 00:13:20 +0800 Subject: [PATCH 0134/1060] vpp: sm1: add vpp and sr support [1/1] PD#SWPL-6101 Problem: Need vpp and sr supprt for sm1 Solution: add support for sm1 Verify: test pass on sm1 ac200 Change-Id: I038ceba52a0b47512767e851d0047a3ee36e351c Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 24 ++++++++++---------- drivers/amlogic/media/video_sink/vpp.c | 28 ++++++++++++++++-------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 963524cc3478..c324afd6c154 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -3403,8 +3403,8 @@ static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } if (is_meson_txlx_cpu() - || is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) VSYNC_WR_MPEG_REG_BITS( VIU_VD2_FMT_CTRL + cur_dev->viu_off, 1, 29, 1); @@ -4391,8 +4391,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((is_meson_txlx_cpu() - || is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) && is_dolby_vision_on() && is_dolby_vision_stb_mode() && (vf->source_type == @@ -4853,8 +4853,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((is_meson_txlx_cpu() - || is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) && is_dolby_vision_on() && is_dolby_vision_stb_mode() && (vf->source_type == @@ -7781,8 +7781,8 @@ SET_FILTER: VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* bypass core1 */ - else if (is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + else if (cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); } @@ -12227,7 +12227,7 @@ static int __init video_early_init(void) WRITE_VCBUS_REG_BITS( SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1); } - if (is_meson_g12b_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) WRITE_VCBUS_REG_BITS( SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); return 0; @@ -12386,8 +12386,7 @@ static int __init video_init(void) } #endif - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { cur_dev->viu_off = 0x3200 - 0x1a50; legacy_vpp = false; } @@ -12517,9 +12516,8 @@ static int __init video_init(void) init_waitqueue_head(&amvideo_trick_wait); init_waitqueue_head(&amvideo_sizechange_wait); -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + INIT_WORK(&vpu_delay_work, do_vpu_delay_work); -#endif #ifdef CONFIG_AM_VOUT vout_hook(); diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 33a014fb0cca..5fed63c1d5fb 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1733,7 +1733,10 @@ int vpp_set_super_scaler_regs( } /*ve input size setting*/ - if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || + if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu() || (is_meson_tl1_cpu() && ((scaler_path_sel == PPS_CORE0_CORE1) || (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1)))) @@ -1746,8 +1749,8 @@ int vpp_set_super_scaler_regs( if (tmp_data != tmp_data2) VSYNC_WR_MPEG_REG(VPP_VE_H_V_SIZE, tmp_data); /*chroma blue stretch size setting*/ - if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() + || (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))) { tmp_data = (((vpp_postblend_out_width & 0x1fff) << 16) | (vpp_postblend_out_height & 0x1fff)); VSYNC_WR_MPEG_REG(VPP_OUT_H_V_SIZE, tmp_data); @@ -1928,8 +1931,10 @@ static void vpp_set_super_scaler( next_frame_par->supscl_path = CORE1_BEFORE_PPS; else next_frame_par->supscl_path = CORE1_AFTER_PPS; - } else if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + } else if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { next_frame_par->supscl_path = CORE0_BEFORE_PPS; } else next_frame_par->supscl_path = CORE0_PPS_CORE1; @@ -2152,7 +2157,8 @@ static void vpp_set_super_scaler( } } else if (is_meson_txhd_cpu() || is_meson_g12a_cpu() - || is_meson_g12b_cpu()) { + || is_meson_g12b_cpu() + || is_meson_sm1_cpu()) { if (sr_path == CORE0_BEFORE_PPS) next_frame_par->sr0_position = 1; else if (sr_path == CORE0_AFTER_PPS) @@ -3096,8 +3102,10 @@ void vpp_super_scaler_support(void) if (is_meson_gxlx_cpu()) { sr_support &= ~SUPER_CORE0_SUPPORT; sr_support |= SUPER_CORE1_SUPPORT; - } else if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + } else if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { sr_support |= SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || @@ -3112,7 +3120,9 @@ void vpp_super_scaler_support(void) sr_support &= ~SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; } - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { sr_reg_offt = 0xc00; sr_reg_offt2 = 0x00; } else if (is_meson_tl1_cpu()) { From 6813b14b074af642ed9351f11941418bb6cc937c Mon Sep 17 00:00:00 2001 From: Hang Cheng Date: Fri, 22 Mar 2019 15:58:50 +0800 Subject: [PATCH 0135/1060] cec: add change for sm1 [1/1] PD#SWPL-5419 Problem: cec change for sm1 Solution: add cec change for sm1 Verify: ac200 Change-Id: Ic808e4bd128358b7f10c7f0b21a629d72f1c71cc Signed-off-by: Hang Cheng Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 6 +++--- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 6 +++--- drivers/amlogic/cec/hdmi_ao_cec.c | 11 +++++++++++ drivers/amlogic/cec/hdmi_ao_cec.h | 3 +-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 2d2be49d07cc..93f76586ee3a 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1131,7 +1131,7 @@ >; }; aocec: aocec { - compatible = "amlogic, aocec-g12a"; + compatible = "amlogic, aocec-sm1"; device_name = "aocec"; status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -1139,7 +1139,7 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "G12A"; /* Max Chars: 16 */ + product_desc = "SM1"; /* Max Chars: 16 */ cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ cec_version = <5>;/*5:1.4;6:2.0*/ port_num = <1>; @@ -1154,7 +1154,7 @@ pinctrl-2=<&eecec_b>; reg = <0xFF80023c 0x4 0xFF800000 0x400 - 0xFF634400 0x26>; + 0xFF634400 0x70>; reg-names = "ao_exit","ao","periphs"; }; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 6a16ae6d727c..3f3df5ce69a2 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1130,7 +1130,7 @@ >; }; aocec: aocec { - compatible = "amlogic, aocec-g12a"; + compatible = "amlogic, aocec-sm1"; device_name = "aocec"; status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -1138,7 +1138,7 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "G12A"; /* Max Chars: 16 */ + product_desc = "SM1"; /* Max Chars: 16 */ cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ cec_version = <5>;/*5:1.4;6:2.0*/ port_num = <1>; @@ -1153,7 +1153,7 @@ pinctrl-2=<&eecec_b>; reg = <0x0 0xFF80023c 0x0 0x4 0x0 0xFF800000 0x0 0x400 - 0x0 0xFF634400 0x0 0x26>; + 0x0 0xFF634400 0x0 0x70>; reg-names = "ao_exit","ao","periphs"; }; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 931ef1e55622..bc1ad718c446 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -3089,6 +3089,13 @@ static const struct cec_platform_data_s cec_tl1_data = { .cecb_ver = CECB_VER_2, }; +static const struct cec_platform_data_s cec_sm1_data = { + .line_reg = 1, + .line_bit = 3, + .ee_to_ao = 1, + .ceca_sts_reg = 1, + .cecb_ver = CECB_VER_2, +}; static const struct of_device_id aml_cec_dt_match[] = { { @@ -3111,6 +3118,10 @@ static const struct of_device_id aml_cec_dt_match[] = { .compatible = "amlogic, aocec-tl1", .data = &cec_tl1_data, }, + { + .compatible = "amlogic, aocec-sm1", + .data = &cec_sm1_data, + }, {} }; #endif diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 4b54245fc586..33b0acf1d776 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,8 +19,7 @@ #define __AO_CEC_H__ - -#define CEC_DRIVER_VERSION "Ver 2019/1/14\n" +#define CEC_DRIVER_VERSION "Ver 2019/3/23\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" From 7a021ad2152780e8b06669a0dce162c642240b81 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Fri, 22 Mar 2019 14:09:36 +0800 Subject: [PATCH 0136/1060] CPUFREQ: delete different cpufreq tables for sm1. [1/1] PD#SWPL-6205 Problem: delete different cpufreq tables. Solution: delete different cpufreq tables. Verify: sm1_ac200, verify pass Change-Id: I99142d2f99847f45eafc876a1b2d785a28815e15 Signed-off-by: Hong Guo --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 78 ++++---- arch/arm/boot/dts/amlogic/sm1_pxp.dts | 26 +-- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 184 ++---------------- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 184 ++---------------- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 78 ++++---- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 26 +-- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 184 ++---------------- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 184 ++---------------- 8 files changed, 158 insertions(+), 786 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 93f76586ee3a..626bcbce5e2b 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1705,46 +1705,52 @@ vddcpu0: pwmao_d-regulator { compatible = "pwm-regulator"; - pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; regulator-name = "vddcpu0"; - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; regulator-always-on; - max-duty-cycle = <1250>; + max-duty-cycle = <1500>; /* Voltage Duty-Cycle */ - voltage-table = <1022000 0>, - <1011000 3>, - <1001000 6>, - <991000 10>, - <981000 13>, - <971000 16>, - <961000 20>, - <951000 23>, - <941000 26>, - <931000 30>, - <921000 33>, - <911000 36>, - <901000 40>, - <891000 43>, - <881000 46>, - <871000 50>, - <861000 53>, - <851000 56>, - <841000 60>, - <831000 63>, - <821000 67>, - <811000 70>, - <801000 73>, - <791000 76>, - <781000 80>, - <771000 83>, - <761000 86>, - <751000 90>, - <741000 93>, - <731000 96>, - <721000 100>; + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; status = "okay"; - }; + }; ddr_bandwidth { compatible = "amlogic, ddr-bandwidth"; diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index 0e98deac2c2f..8876b767a274 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -388,47 +388,47 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <790000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <830000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <870000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <890000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <960000>; }; opp10 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <981000>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1010000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 7e667e145567..5097b0a9bc7f 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -753,163 +753,47 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <790000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <830000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <870000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <890000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <960000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - }; - - cpu_opp_table1: cpu_opp_table1 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - }; - - cpu_opp_table2: cpu_opp_table2 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - opp12 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp13 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1010000>; }; }; @@ -922,50 +806,6 @@ }; /* end of / */ -&CPU0 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU1 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU2 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU3 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index bc2ab925b653..b90b074e6052 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -753,163 +753,47 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <790000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <830000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <870000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <890000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <960000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - }; - - cpu_opp_table1: cpu_opp_table1 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - }; - - cpu_opp_table2: cpu_opp_table2 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - opp12 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp13 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1010000>; }; }; @@ -922,50 +806,6 @@ }; /* end of / */ -&CPU0 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU1 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU2 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU3 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 3f3df5ce69a2..eb9b8d1cdc24 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1704,46 +1704,52 @@ vddcpu0: pwmao_d-regulator { compatible = "pwm-regulator"; - pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; regulator-name = "vddcpu0"; - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; regulator-always-on; - max-duty-cycle = <1250>; + max-duty-cycle = <1500>; /* Voltage Duty-Cycle */ - voltage-table = <1022000 0>, - <1011000 3>, - <1001000 6>, - <991000 10>, - <981000 13>, - <971000 16>, - <961000 20>, - <951000 23>, - <941000 26>, - <931000 30>, - <921000 33>, - <911000 36>, - <901000 40>, - <891000 43>, - <881000 46>, - <871000 50>, - <861000 53>, - <851000 56>, - <841000 60>, - <831000 63>, - <821000 67>, - <811000 70>, - <801000 73>, - <791000 76>, - <781000 80>, - <771000 83>, - <761000 86>, - <751000 90>, - <741000 93>, - <731000 96>, - <721000 100>; + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; status = "okay"; - }; + }; ddr_bandwidth { compatible = "amlogic, ddr-bandwidth"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index c4fe2ebd03c8..6b5d1d3dd17c 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -389,47 +389,47 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <790000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <830000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <870000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <890000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <960000>; }; opp10 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <981000>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1010000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 6daa7216aec1..ce852138df89 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -751,163 +751,47 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <790000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <830000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <870000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <890000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <960000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - }; - - cpu_opp_table1: cpu_opp_table1 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - }; - - cpu_opp_table2: cpu_opp_table2 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - opp12 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp13 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1010000>; }; }; @@ -920,50 +804,6 @@ }; /* end of / */ -&CPU0 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>; - //<&cpu_opp_table1>, - //<&cpu_opp_table2>; -}; - -&CPU1 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU2 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU3 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 5e556d16583a..41f03b0186cb 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -751,163 +751,47 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <790000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <830000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <870000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <890000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <960000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - }; - - cpu_opp_table1: cpu_opp_table1 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - }; - - cpu_opp_table2: cpu_opp_table2 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - opp01 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - opp02 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - opp03 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp04 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; - }; - opp05 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; - }; - opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; - }; - opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; - }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <991000>; - }; - opp12 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp13 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1010000>; }; }; @@ -920,50 +804,6 @@ }; /* end of / */ -&CPU0 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>; - //<&cpu_opp_table1>, - //<&cpu_opp_table2>; -}; - -&CPU1 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU2 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - -&CPU3 { - /*set differents table cpufreq max*/ - diff_tables_supply; - hispeed_cpufreq_max = <2100>; - medspeed_cpufreq_max = <1908>; - lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>, - <&cpu_opp_table1>, - <&cpu_opp_table2>; -}; - &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; From 7751ef87b0af7f2417aa189809ef0ec86e150c75 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Mon, 25 Mar 2019 17:08:59 +0800 Subject: [PATCH 0137/1060] CPUFREQ: update cpufreq tables for sm1. [1/1] PD#SWPL-6205 Problem: update cpufreq tables. Solution: update cpufreq tables. Verify: sm1_ac200, verify pass Change-Id: I360264df88981a16267a20896f97c93dbd0e4b37 Signed-off-by: Hong Guo Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/sm1_pxp.dts | 23 +++++++++++-------- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 23 +++++++++++-------- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 23 +++++++++++-------- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 23 +++++++++++-------- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 23 +++++++++++-------- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 23 +++++++++++-------- 6 files changed, 78 insertions(+), 60 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index 8876b767a274..866fd0fa585b 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -381,22 +381,21 @@ }; /* Audio Related end */ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; @@ -408,27 +407,31 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <790000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <830000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <870000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <890000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <960000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1010000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 5097b0a9bc7f..1602807479ef 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -746,22 +746,21 @@ }; /* Audio Related end */ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; @@ -773,27 +772,31 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <790000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <830000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <870000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <890000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <960000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1010000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index b90b074e6052..f2272a2050a9 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -746,22 +746,21 @@ }; /* Audio Related end */ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; @@ -773,27 +772,31 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <790000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <830000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <870000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <890000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <960000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1010000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index 6b5d1d3dd17c..ce1bc570cfab 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -382,22 +382,21 @@ }; /* Audio Related end */ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; @@ -409,27 +408,31 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <790000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <830000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <870000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <890000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <960000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1010000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index ce852138df89..edac39ebfaff 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -744,22 +744,21 @@ }; /* Audio Related end */ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; @@ -771,27 +770,31 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <790000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <830000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <870000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <890000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <960000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1010000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 41f03b0186cb..89370b3b4bd3 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -744,22 +744,21 @@ }; /* Audio Related end */ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <750000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; @@ -771,27 +770,31 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <790000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <830000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <870000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <890000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <960000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1010000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; }; }; From ac352981ad6cf8151976bfc6970d6dda5b577bb8 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Wed, 20 Mar 2019 22:11:44 +0800 Subject: [PATCH 0138/1060] dts: sm1: add sound card config [1/2] PD#SWPL-6151 Problem: sound card for sm1 Solution: add sound card for sm1 Verify: ac200 Change-Id: I1de0cfe1748d401ab0e21b0a244def37b277b1ff Signed-off-by: Xing Wang --- MAINTAINERS | 2 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 38 ++- arch/arm/boot/dts/amlogic/sm1_pxp.dts | 118 +++---- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 300 ++++++----------- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 293 ++++++---------- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 38 ++- arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 118 +++---- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 314 +++++++----------- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 300 ++++++----------- .../dt-bindings/clock/amlogic,sm1-audio-clk.h | 92 +++++ 10 files changed, 701 insertions(+), 912 deletions(-) create mode 100644 include/dt-bindings/clock/amlogic,sm1-audio-clk.h diff --git a/MAINTAINERS b/MAINTAINERS index 75c79383528b..0de44850195b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14682,9 +14682,11 @@ AMLOGIC TL1 AUDIO EXTERANL INPUT/OUTPUT DRIVERS AMLOGIC TL1 NEW EQDRC AMLOGIC TL1 MIXER CONTROLS AMLOGIC TL1 VAD DRIVER +AMLOGIC SM1 SOUND CARD M: Xing Wang #include -#include +#include #include #include #include @@ -800,30 +800,34 @@ memory-region = <&ion_cma_reserved>; };/* end of ion_dev*/ - audiobus: audiobus@0xff642000 { + audiobus: audiobus@0xFF660000 { compatible = "amlogic, audio-controller", "simple-bus"; - reg = <0xff642000 0x2000>; + reg = <0xFF660000 0x4000>; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0xff642000 0x2000>; + ranges = <0x0 0xFF660000 0x4000>; clkaudio: audio_clocks { - compatible = "amlogic, g12a-audio-clocks"; + compatible = "amlogic, sm1-audio-clocks"; #clock-cells = <1>; reg = <0x0 0xb0>; }; ddr_manager { - compatible = "amlogic, g12a-audio-ddr-manager"; + compatible = "amlogic, sm1-audio-ddr-manager"; interrupts = < GIC_SPI 148 IRQ_TYPE_EDGE_RISING GIC_SPI 149 IRQ_TYPE_EDGE_RISING GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING GIC_SPI 152 IRQ_TYPE_EDGE_RISING GIC_SPI 153 IRQ_TYPE_EDGE_RISING GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 50 IRQ_TYPE_EDGE_RISING >; interrupt-names = "toddr_a", "toddr_b", "toddr_c", - "frddr_a", "frddr_b", "frddr_c"; + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; }; };/* end of audiobus*/ @@ -1687,20 +1691,32 @@ #size-cells=<1>; ranges; pdm_bus { - reg = <0xFF640000 0x2000>; + reg = <0xFF661000 0x400>; }; audiobus_base { - reg = <0xFF642000 0x2000>; + reg = <0xFF660000 0x1000>; }; audiolocker_base { - reg = <0xFF64A000 0x2000>; + reg = <0xFF661400 0x400>; }; eqdrc_base { - reg = <0xFF642800 0x1800>; + reg = <0xFF662000 0x1000>; }; reset_base { reg = <0xFFD01000 0x1000>; }; + vad_base { + reg = <0xFF661800 0x400>; + }; + earcrx_cdmc_base { + reg = <0xFF663800 0x30>; + }; + earcrx_dmac_base { + reg = <0xFF663C00 0x20>; + }; + earcrx_top_base { + reg = <0xFF663E00 0x10>; + }; }; vddcpu0: pwmao_d-regulator { diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index 866fd0fa585b..aa65030e9d6c 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -273,10 +273,16 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ tdmacpu: cpu { - sound-dai = <&aml_tdma>; + sound-dai = <&tdma>; dai-tdm-slot-tx-mask = <1 1 1 1 1 1 1 1>; dai-tdm-slot-rx-mask = @@ -296,17 +302,21 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; cpu { - sound-dai = <&aml_tdmb>; + sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { + tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec>; }; }; @@ -317,17 +327,21 @@ continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmc>; - frame-master = <&aml_tdmc>; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; cpu { - sound-dai = <&aml_tdmc>; + sound-dai = <&tdmc>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { + tdmccodec: codec { sound-dai = <&dummy_codec &dummy_codec>; }; }; @@ -335,7 +349,7 @@ aml-audio-card,dai-link@3 { mclk-fs = <64>; cpu { - sound-dai = <&aml_pdm>; + sound-dai = <&pdm>; }; codec { sound-dai = <&pdm_codec>; @@ -345,7 +359,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; cpu { - sound-dai = <&aml_spdif>; + sound-dai = <&spdifa>; system-clock-frequency = <6144000>; }; codec { @@ -355,7 +369,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; cpu { - sound-dai = <&aml_spdif_b>; + sound-dai = <&spdifb>; system-clock-frequency = <6144000>; }; codec { @@ -459,8 +473,8 @@ }; &audiobus { - aml_tdma: tdma { - compatible = "amlogic, g12a-snd-tdma"; + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; dai-tdm-lane-slot-mask-out = <0 1>; @@ -470,10 +484,12 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; }; - aml_tdmb: tdmb { - compatible = "amlogic, g12a-snd-tdmb"; + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 1 1 1>; dai-tdm-clk-sel = <1>; @@ -484,8 +500,8 @@ pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; }; - aml_tdmc: tdmc { - compatible = "amlogic, g12a-snd-tdmc"; + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; #dai-tdm-lane-slot-mask-out = <1 0 1 1>; @@ -497,43 +513,46 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + + status = "okay"; }; - aml_spdif: spdif { - compatible = "amlogic, g12a-snd-spdif-a"; + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; clock-names = "sysclk", "fixed_clk", "gate_spdifin", "gate_spdifout", "clk_spdifin", "clk_spdifout"; interrupts = - ; + ; interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; }; - aml_spdif_b: spdif_b { - compatible = "amlogic, g12a-snd-spdif-b"; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ - &clkaudio CLKID_AUDIO_SPDIFOUTB - &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; clock-names = "sysclk", "gate_spdifout", "clk_spdifout"; - pinctrl-names = "spdif_pins"; - pinctrl-0 = <&spdifout_b>; + status = "okay"; }; - aml_pdm: pdm { - compatible = "amlogic, g12a-snd-pdm"; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM &clkc CLKID_FCLK_DIV3 &clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_PDMIN0 @@ -543,34 +562,15 @@ "dclk_srcpll", "pdm_dclk", "pdm_sysclk"; + pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - - status = "disabled"; - }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 1602807479ef..f75ef1b3a7e1 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -542,32 +542,13 @@ tdmout_index = <1>; status = "okay"; }; - audio_effect:eqdrc{ - /*eq_enable = <1>;*/ - /*drc_enable = <1>;*/ - /* - * 0:tdmout_a - * 1:tdmout_b - * 2:tdmout_c - * 3:spdifout - * 4:spdifout_b - */ - eqdrc_module = <1>; - /* max 0xf, each bit for one lane, usually one lane */ - lane_mask = <0x1>; - /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; - }; + auge_sound { compatible = "amlogic, g12a-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; - aml-audio-card,loopback = <&aml_loopback>; - aml-audio-card,aux-devs = <&amlogic_codec>; /*avout mute gpio*/ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - /*for audio effect ,eqdrc */ - aml-audio-card,effect = <&audio_effect>; aml-audio-card,dai-link@0 { format = "dsp_a"; @@ -575,14 +556,17 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; */ suffix-name = "alsaPORT-pcm"; tdmacpu: cpu { - sound-dai = <&aml_tdma>; + sound-dai = <&tdma>; dai-tdm-slot-tx-mask = <1 1 1 1 1 1 1 1>; dai-tdm-slot-rx-mask = @@ -602,8 +586,10 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ //bitclock-master = <&tdmbcodec>; //frame-master = <&tdmbcodec>; /* suffix-name, sync with android audio hal @@ -611,7 +597,7 @@ */ suffix-name = "alsaPORT-i2s"; cpu { - sound-dai = <&aml_tdmb>; + sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; @@ -637,22 +623,24 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmc>; - frame-master = <&aml_tdmc>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ //suffix-name = "alsaPORT-tdm"; cpu { - sound-dai = <&aml_tdmc>; + sound-dai = <&tdmc>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { - sound-dai = <&tlv320adc3101_32 &dummy_codec>; + tdmccodec: codec { + sound-dai = <&dummy_codec>; }; }; @@ -663,7 +651,7 @@ */ suffix-name = "alsaPORT-pdm"; cpu { - sound-dai = <&aml_pdm>; + sound-dai = <&pdm>; }; codec { sound-dai = <&pdm_codec>; @@ -672,61 +660,43 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; - continuous-clock; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-spdifb2hdmi"; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; cpu { - sound-dai = <&aml_spdif>; + sound-dai = <&spdifa>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { mclk-fs = <128>; continuous-clock; /* suffix-name, sync with android audio hal * what's the dai link used for */ - suffix-name = "alsaPORT-spdif"; + suffix-name = "alsaPORT-spdifb"; cpu { - sound-dai = <&aml_spdif_b>; + sound-dai = <&spdifb>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* - * dai link for i2s to hdmix, - * Notice to select a tdm lane not used by hw - */ - /* - * aml-audio-card,dai-link@6 { - * format = "i2s"; - * mclk-fs = <256>; - * //continuous-clock; - * //bitclock-inversion; - * //frame-inversion; - * bitclock-master = <&aml_i2s2hdmi>; - * frame-master = <&aml_i2s2hdmi>; - * suffix-name = "alsaPORT-i2s2hdmi"; - * cpu { - * sound-dai = <&aml_i2s2hdmi>; - * dai-tdm-slot-tx-mask = <1 1>; - * dai-tdm-slot-num = <2>; - * dai-tdm-slot-width = <32>; - * system-clock-frequency = <12288000>; - * }; - * codec { - * sound-dai = <&dummy_codec>; - * }; - * }; - */ + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; audiolocker: locker { compatible = "amlogic, audiolocker"; @@ -742,7 +712,7 @@ interrupt-names = "irq"; frequency = <49000000>; /* pll */ dividor = <49>; /* locker's parent */ - status = "okay"; + status = "disabled"; }; /* Audio Related end */ @@ -870,22 +840,6 @@ reset_pin = <&gpio GPIOA_5 0>; }; - tlv320adc3101_32: tlv320adc3101_32@32 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x19>; - differential_pair = <1>; - status = "okay"; - }; - - tas5707_36: tas5707_36@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "disabled"; - reset_pin = <&gpio GPIOA_5 0>; - }; - bl_extern_i2c { compatible = "bl_extern, i2c"; dev_name = "lp8556"; @@ -895,8 +849,8 @@ }; &audiobus { - aml_tdma: tdma { - compatible = "amlogic, g12a-snd-tdma"; + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1>; dai-tdm-oe-lane-slot-mask-out = <1 0>; @@ -906,10 +860,12 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; }; - aml_tdmb: tdmb { - compatible = "amlogic, g12a-snd-tdmb"; + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; dai-tdm-lane-slot-mask-out = <1 0 0 0>; @@ -920,6 +876,9 @@ clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + /* * 0: tdmout_a; * 1: tdmout_b; @@ -928,47 +887,38 @@ * 4: spdifout_b; */ samesource_sel = <3>; + + status = "okay"; }; - aml_tdmc: tdmc { - compatible = "amlogic, g12a-snd-tdmc"; + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; #dai-tdm-lane-slot-mask-out = <1 0 1 1>; #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C &clkc CLKID_MPLL2>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; }; - /* copy a useless tdm to output for hdmi, no pinmux */ - aml_i2s2hdmi: i2s2hdmi { - compatible = "amlogic, g12a-snd-tdmc"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-out = <1 1 1 1>; - dai-tdm-clk-sel = <2>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_C - &clkc CLKID_MPLL2>; - clock-names = "mclk", "clk_srcpll"; - - i2s2hdmi = <1>; - - status = "disabled"; - }; - - aml_spdif: spdif { - compatible = "amlogic, g12a-snd-spdif-a"; + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; clock-names = "sysclk", "fixed_clk", "gate_spdifin", "gate_spdifout", "clk_spdifin", "clk_spdifout"; interrupts = @@ -977,22 +927,25 @@ interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; }; - aml_spdif_b: spdif_b { - compatible = "amlogic, g12a-snd-spdif-b"; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ - &clkaudio CLKID_AUDIO_SPDIFOUTB - &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; clock-names = "sysclk", "gate_spdifout", "clk_spdifout"; + status = "okay"; }; - aml_pdm: pdm { - compatible = "amlogic, g12a-snd-pdm"; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM &clkc CLKID_FCLK_DIV3 &clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_PDMIN0 @@ -1002,50 +955,46 @@ "dclk_srcpll", "pdm_dclk", "pdm_sysclk"; + pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ - status = "okay"; - }; - aml_loopback: loopback { - compatible = "amlogic, snd-loopback"; - /* - * 0: out rate = in data rate; - * 1: out rate = loopback data rate; - */ - lb_mode = <0>; - /* datain src - * 0: tdmin_a; - * 1: tdmin_b; - * 2: tdmin_c; - * 3: spdifin; - * 4: pdmin; - */ - datain_src = <4>; - datain_chnum = <8>; - datain_chmask = <0x3f>; - - /* tdmin_lb src - * 0: tdmoutA - * 1: tdmoutB - * 2: tdmoutC - * 3: PAD_tdminA - * 4: PAD_tdminB - * 5: PAD_tdminC - */ - datalb_src = <2>; - datalb_chnum = <8>; - datalb_chmask = <0x3>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; status = "okay"; }; - audioresample: resample { - compatible = "amlogic, g12a-resample"; + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; clocks = <&clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_MCLK_F - &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src * TDMIN_A, 0 @@ -1058,29 +1007,6 @@ * LOOPBACK, 7 */ resample_module = <4>; - status = "okay"; - }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - status = "disabled"; }; }; /* end of audiobus */ @@ -1161,18 +1087,8 @@ }; }; - /* GPIOH_4 */ - /* - * spdifout: spdifout { - * mux { - * groups = "spdif_out_h"; - * function = "spdif_out"; - * }; - *}; - */ - pdmin: pdmin { - mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ groups = "pdm_din0_a", /*"pdm_din1_a",*/ "pdm_din2_a", @@ -1220,7 +1136,7 @@ }; /* end of pinctrl_periphs */ &pinctrl_aobus { spdifout: spdifout { - mux { /* gpiao_10 */ + mux { /* GPIOAO_10 */ groups = "spdif_out_ao"; function = "spdif_out_ao"; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index f2272a2050a9..caaa308c8c90 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -542,32 +542,13 @@ tdmout_index = <1>; status = "okay"; }; - audio_effect:eqdrc{ - /*eq_enable = <1>;*/ - /*drc_enable = <1>;*/ - /* - * 0:tdmout_a - * 1:tdmout_b - * 2:tdmout_c - * 3:spdifout - * 4:spdifout_b - */ - eqdrc_module = <1>; - /* max 0xf, each bit for one lane, usually one lane */ - lane_mask = <0x1>; - /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; - }; + auge_sound { compatible = "amlogic, g12a-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; - aml-audio-card,loopback = <&aml_loopback>; - aml-audio-card,aux-devs = <&amlogic_codec>; /*avout mute gpio*/ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - /*for audio effect ,eqdrc */ - aml-audio-card,effect = <&audio_effect>; aml-audio-card,dai-link@0 { format = "dsp_a"; @@ -575,14 +556,17 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; */ suffix-name = "alsaPORT-pcm"; tdmacpu: cpu { - sound-dai = <&aml_tdma>; + sound-dai = <&tdma>; dai-tdm-slot-tx-mask = <1 1 1 1 1 1 1 1>; dai-tdm-slot-rx-mask = @@ -602,8 +586,10 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ //bitclock-master = <&tdmbcodec>; //frame-master = <&tdmbcodec>; /* suffix-name, sync with android audio hal @@ -611,7 +597,7 @@ */ suffix-name = "alsaPORT-i2s"; cpu { - sound-dai = <&aml_tdmb>; + sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; @@ -637,22 +623,24 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmc>; - frame-master = <&aml_tdmc>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ //suffix-name = "alsaPORT-tdm"; cpu { - sound-dai = <&aml_tdmc>; + sound-dai = <&tdmc>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { - sound-dai = <&tlv320adc3101_32 &dummy_codec>; + tdmccodec: codec { + sound-dai = <&dummy_codec>; }; }; @@ -663,7 +651,7 @@ */ suffix-name = "alsaPORT-pdm"; cpu { - sound-dai = <&aml_pdm>; + sound-dai = <&pdm>; }; codec { sound-dai = <&pdm_codec>; @@ -672,61 +660,43 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; - continuous-clock; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-spdifb2hdmi"; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; cpu { - sound-dai = <&aml_spdif>; + sound-dai = <&spdifa>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { mclk-fs = <128>; continuous-clock; /* suffix-name, sync with android audio hal * what's the dai link used for */ - suffix-name = "alsaPORT-spdif"; + suffix-name = "alsaPORT-spdifb"; cpu { - sound-dai = <&aml_spdif_b>; + sound-dai = <&spdifb>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* - * dai link for i2s to hdmix, - * Notice to select a tdm lane not used by hw - */ - /* - * aml-audio-card,dai-link@6 { - * format = "i2s"; - * mclk-fs = <256>; - * //continuous-clock; - * //bitclock-inversion; - * //frame-inversion; - * bitclock-master = <&aml_i2s2hdmi>; - * frame-master = <&aml_i2s2hdmi>; - * suffix-name = "alsaPORT-i2s2hdmi"; - * cpu { - * sound-dai = <&aml_i2s2hdmi>; - * dai-tdm-slot-tx-mask = <1 1>; - * dai-tdm-slot-num = <2>; - * dai-tdm-slot-width = <32>; - * system-clock-frequency = <12288000>; - * }; - * codec { - * sound-dai = <&dummy_codec>; - * }; - * }; - */ + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; audiolocker: locker { compatible = "amlogic, audiolocker"; @@ -742,7 +712,7 @@ interrupt-names = "irq"; frequency = <49000000>; /* pll */ dividor = <49>; /* locker's parent */ - status = "okay"; + status = "disabled"; }; /* Audio Related end */ @@ -870,22 +840,6 @@ reset_pin = <&gpio GPIOA_5 0>; }; - tlv320adc3101_32: tlv320adc3101_32@32 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x19>; - differential_pair = <1>; - status = "okay"; - }; - - tas5707_36: tas5707_36@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "disabled"; - reset_pin = <&gpio GPIOA_5 0>; - }; - bl_extern_i2c { compatible = "bl_extern, i2c"; dev_name = "lp8556"; @@ -895,8 +849,8 @@ }; &audiobus { - aml_tdma: tdma { - compatible = "amlogic, g12a-snd-tdma"; + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1>; dai-tdm-oe-lane-slot-mask-out = <1 0>; @@ -906,10 +860,12 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; }; - aml_tdmb: tdmb { - compatible = "amlogic, g12a-snd-tdmb"; + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; dai-tdm-lane-slot-mask-out = <1 0 0 0>; @@ -920,6 +876,9 @@ clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + /* * 0: tdmout_a; * 1: tdmout_b; @@ -928,47 +887,38 @@ * 4: spdifout_b; */ samesource_sel = <3>; + + status = "okay"; }; - aml_tdmc: tdmc { - compatible = "amlogic, g12a-snd-tdmc"; + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; #dai-tdm-lane-slot-mask-out = <1 0 1 1>; #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C &clkc CLKID_MPLL2>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; }; - /* copy a useless tdm to output for hdmi, no pinmux */ - aml_i2s2hdmi: i2s2hdmi { - compatible = "amlogic, g12a-snd-tdmc"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-out = <1 1 1 1>; - dai-tdm-clk-sel = <2>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_C - &clkc CLKID_MPLL2>; - clock-names = "mclk", "clk_srcpll"; - - i2s2hdmi = <1>; - - status = "disabled"; - }; - - aml_spdif: spdif { - compatible = "amlogic, g12a-snd-spdif-a"; + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; clock-names = "sysclk", "fixed_clk", "gate_spdifin", "gate_spdifout", "clk_spdifin", "clk_spdifout"; interrupts = @@ -977,22 +927,25 @@ interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; }; - aml_spdif_b: spdif_b { - compatible = "amlogic, g12a-snd-spdif-b"; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ - &clkaudio CLKID_AUDIO_SPDIFOUTB - &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; clock-names = "sysclk", "gate_spdifout", "clk_spdifout"; + status = "okay"; }; - aml_pdm: pdm { - compatible = "amlogic, g12a-snd-pdm"; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM &clkc CLKID_FCLK_DIV3 &clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_PDMIN0 @@ -1002,50 +955,45 @@ "dclk_srcpll", "pdm_dclk", "pdm_sysclk"; + pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; }; - aml_loopback: loopback { - compatible = "amlogic, snd-loopback"; - /* - * 0: out rate = in data rate; - * 1: out rate = loopback data rate; - */ - lb_mode = <0>; + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; - /* datain src - * 0: tdmin_a; - * 1: tdmin_b; - * 2: tdmin_c; - * 3: spdifin; - * 4: pdmin; - */ - datain_src = <4>; - datain_chnum = <8>; - datain_chmask = <0x3f>; + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; - /* tdmin_lb src - * 0: tdmoutA - * 1: tdmoutB - * 2: tdmoutC - * 3: PAD_tdminA - * 4: PAD_tdminB - * 5: PAD_tdminC - */ - datalb_src = <2>; - datalb_chnum = <8>; - datalb_chmask = <0x3>; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; status = "okay"; }; - audioresample: resample { - compatible = "amlogic, g12a-resample"; + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; clocks = <&clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_MCLK_F - &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src * TDMIN_A, 0 @@ -1058,29 +1006,6 @@ * LOOPBACK, 7 */ resample_module = <4>; - status = "okay"; - }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - status = "disabled"; }; }; /* end of audiobus */ @@ -1161,18 +1086,8 @@ }; }; - /* GPIOH_4 */ - /* - * spdifout: spdifout { - * mux { - * groups = "spdif_out_h"; - * function = "spdif_out"; - * }; - *}; - */ - pdmin: pdmin { - mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ groups = "pdm_din0_a", /*"pdm_din1_a",*/ "pdm_din2_a", @@ -1220,7 +1135,7 @@ }; /* end of pinctrl_periphs */ &pinctrl_aobus { spdifout: spdifout { - mux { /* gpiao_10 */ + mux { /* GPIOAO_10 */ groups = "spdif_out_ao"; function = "spdif_out_ao"; }; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index eb9b8d1cdc24..c40bac63e053 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -800,30 +800,34 @@ memory-region = <&ion_cma_reserved>; };/* end of ion_dev*/ - audiobus: audiobus@0xff642000 { + audiobus: audiobus@0xFF660000 { compatible = "amlogic, audio-controller", "simple-bus"; - reg = <0x0 0xff642000 0x0 0x2000>; + reg = <0x0 0xFF660000 0x0 0x4000>; #address-cells = <2>; #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>; + ranges = <0x0 0x0 0x0 0xFF660000 0x0 0x4000>; clkaudio: audio_clocks { - compatible = "amlogic, g12a-audio-clocks"; + compatible = "amlogic, sm1-audio-clocks"; #clock-cells = <1>; reg = <0x0 0x0 0x0 0xb0>; }; ddr_manager { - compatible = "amlogic, g12a-audio-ddr-manager"; + compatible = "amlogic, sm1-audio-ddr-manager"; interrupts = < GIC_SPI 148 IRQ_TYPE_EDGE_RISING GIC_SPI 149 IRQ_TYPE_EDGE_RISING GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING GIC_SPI 152 IRQ_TYPE_EDGE_RISING GIC_SPI 153 IRQ_TYPE_EDGE_RISING GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 50 IRQ_TYPE_EDGE_RISING >; interrupt-names = "toddr_a", "toddr_b", "toddr_c", - "frddr_a", "frddr_b", "frddr_c"; + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; }; };/* end of audiobus*/ @@ -1686,20 +1690,32 @@ #size-cells=<2>; ranges; pdm_bus { - reg = <0x0 0xFF640000 0x0 0x2000>; + reg = <0x0 0xFF661000 0x0 0x400>; }; audiobus_base { - reg = <0x0 0xFF642000 0x0 0x2000>; + reg = <0x0 0xFF660000 0x0 0x1000>; }; audiolocker_base { - reg = <0x0 0xFF64A000 0x0 0x2000>; + reg = <0x0 0xFF661400 0x0 0x400>; }; eqdrc_base { - reg = <0x0 0xFF642800 0x0 0x1800>; + reg = <0x0 0xFF662000 0x0 0x1000>; }; reset_base { reg = <0x0 0xFFD01000 0x0 0x1000>; }; + vad_base { + reg = <0x0 0xFF661800 0x0 0x400>; + }; + earcrx_cdmc_base { + reg = <0x0 0xFF663800 0x0 0x30>; + }; + earcrx_dmac_base { + reg = <0x0 0xFF663C00 0x0 0x20>; + }; + earcrx_top_base { + reg = <0x0 0xFF663E00 0x0 0x10>; + }; }; vddcpu0: pwmao_d-regulator { diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index ce1bc570cfab..d0a57d770b7e 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -274,10 +274,16 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ tdmacpu: cpu { - sound-dai = <&aml_tdma>; + sound-dai = <&tdma>; dai-tdm-slot-tx-mask = <1 1 1 1 1 1 1 1>; dai-tdm-slot-rx-mask = @@ -297,17 +303,21 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; cpu { - sound-dai = <&aml_tdmb>; + sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { + tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec>; }; }; @@ -318,17 +328,21 @@ continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmc>; - frame-master = <&aml_tdmc>; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; cpu { - sound-dai = <&aml_tdmc>; + sound-dai = <&tdmc>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { + tdmccodec: codec { sound-dai = <&dummy_codec &dummy_codec>; }; }; @@ -336,7 +350,7 @@ aml-audio-card,dai-link@3 { mclk-fs = <64>; cpu { - sound-dai = <&aml_pdm>; + sound-dai = <&pdm>; }; codec { sound-dai = <&pdm_codec>; @@ -346,7 +360,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; cpu { - sound-dai = <&aml_spdif>; + sound-dai = <&spdifa>; system-clock-frequency = <6144000>; }; codec { @@ -356,7 +370,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; cpu { - sound-dai = <&aml_spdif_b>; + sound-dai = <&spdifb>; system-clock-frequency = <6144000>; }; codec { @@ -460,8 +474,8 @@ }; &audiobus { - aml_tdma: tdma { - compatible = "amlogic, g12a-snd-tdma"; + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; dai-tdm-lane-slot-mask-out = <0 1>; @@ -471,10 +485,12 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; }; - aml_tdmb: tdmb { - compatible = "amlogic, g12a-snd-tdmb"; + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 1 1 1>; dai-tdm-clk-sel = <1>; @@ -485,8 +501,8 @@ pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; }; - aml_tdmc: tdmc { - compatible = "amlogic, g12a-snd-tdmc"; + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; #dai-tdm-lane-slot-mask-out = <1 0 1 1>; @@ -498,43 +514,46 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + + status = "okay"; }; - aml_spdif: spdif { - compatible = "amlogic, g12a-snd-spdif-a"; + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; clock-names = "sysclk", "fixed_clk", "gate_spdifin", "gate_spdifout", "clk_spdifin", "clk_spdifout"; interrupts = - ; + ; interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; }; - aml_spdif_b: spdif_b { - compatible = "amlogic, g12a-snd-spdif-b"; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ - &clkaudio CLKID_AUDIO_SPDIFOUTB - &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; clock-names = "sysclk", "gate_spdifout", "clk_spdifout"; - pinctrl-names = "spdif_pins"; - pinctrl-0 = <&spdifout_b>; + status = "okay"; }; - aml_pdm: pdm { - compatible = "amlogic, g12a-snd-pdm"; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM &clkc CLKID_FCLK_DIV3 &clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_PDMIN0 @@ -544,34 +563,15 @@ "dclk_srcpll", "pdm_dclk", "pdm_sysclk"; + pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - - status = "disabled"; - }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index edac39ebfaff..a0d27e578c50 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -540,32 +540,13 @@ tdmout_index = <1>; status = "okay"; }; - audio_effect:eqdrc{ - /*eq_enable = <1>;*/ - /*drc_enable = <1>;*/ - /* - * 0:tdmout_a - * 1:tdmout_b - * 2:tdmout_c - * 3:spdifout - * 4:spdifout_b - */ - eqdrc_module = <1>; - /* max 0xf, each bit for one lane, usually one lane */ - lane_mask = <0x1>; - /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; - }; + auge_sound { compatible = "amlogic, g12a-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; - aml-audio-card,loopback = <&aml_loopback>; - aml-audio-card,aux-devs = <&amlogic_codec>; /*avout mute gpio*/ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - /*for audio effect ,eqdrc */ - aml-audio-card,effect = <&audio_effect>; aml-audio-card,dai-link@0 { format = "dsp_a"; @@ -573,14 +554,17 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; */ suffix-name = "alsaPORT-pcm"; tdmacpu: cpu { - sound-dai = <&aml_tdma>; + sound-dai = <&tdma>; dai-tdm-slot-tx-mask = <1 1 1 1 1 1 1 1>; dai-tdm-slot-rx-mask = @@ -600,8 +584,10 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ //bitclock-master = <&tdmbcodec>; //frame-master = <&tdmbcodec>; /* suffix-name, sync with android audio hal @@ -609,7 +595,7 @@ */ suffix-name = "alsaPORT-i2s"; cpu { - sound-dai = <&aml_tdmb>; + sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; @@ -635,22 +621,24 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmc>; - frame-master = <&aml_tdmc>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ //suffix-name = "alsaPORT-tdm"; cpu { - sound-dai = <&aml_tdmc>; + sound-dai = <&tdmc>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { - sound-dai = <&tlv320adc3101_32 &dummy_codec>; + tdmccodec: codec { + sound-dai = <&dummy_codec>; }; }; @@ -661,7 +649,7 @@ */ suffix-name = "alsaPORT-pdm"; cpu { - sound-dai = <&aml_pdm>; + sound-dai = <&pdm>; }; codec { sound-dai = <&pdm_codec>; @@ -670,61 +658,43 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; - continuous-clock; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-spdifb2hdmi"; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; cpu { - sound-dai = <&aml_spdif>; + sound-dai = <&spdifa>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { mclk-fs = <128>; continuous-clock; /* suffix-name, sync with android audio hal * what's the dai link used for */ - suffix-name = "alsaPORT-spdif"; + suffix-name = "alsaPORT-spdifb"; cpu { - sound-dai = <&aml_spdif_b>; + sound-dai = <&spdifb>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* - * dai link for i2s to hdmix, - * Notice to select a tdm lane not used by hw - */ - /* - * aml-audio-card,dai-link@6 { - * format = "i2s"; - * mclk-fs = <256>; - * //continuous-clock; - * //bitclock-inversion; - * //frame-inversion; - * bitclock-master = <&aml_i2s2hdmi>; - * frame-master = <&aml_i2s2hdmi>; - * suffix-name = "alsaPORT-i2s2hdmi"; - * cpu { - * sound-dai = <&aml_i2s2hdmi>; - * dai-tdm-slot-tx-mask = <1 1>; - * dai-tdm-slot-num = <2>; - * dai-tdm-slot-width = <32>; - * system-clock-frequency = <12288000>; - * }; - * codec { - * sound-dai = <&dummy_codec>; - * }; - * }; - */ + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; audiolocker: locker { compatible = "amlogic, audiolocker"; @@ -740,7 +710,7 @@ interrupt-names = "irq"; frequency = <49000000>; /* pll */ dividor = <49>; /* locker's parent */ - status = "okay"; + status = "disabled"; }; /* Audio Related end */ @@ -868,22 +838,6 @@ reset_pin = <&gpio GPIOA_5 0>; }; - tlv320adc3101_32: tlv320adc3101_32@32 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x19>; - differential_pair = <1>; - status = "okay"; - }; - - tas5707_36: tas5707_36@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "disabled"; - reset_pin = <&gpio GPIOA_5 0>; - }; - bl_extern_i2c { compatible = "bl_extern, i2c"; dev_name = "lp8556"; @@ -893,8 +847,8 @@ }; &audiobus { - aml_tdma: tdma { - compatible = "amlogic, g12a-snd-tdma"; + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1>; dai-tdm-oe-lane-slot-mask-out = <1 0>; @@ -904,10 +858,12 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; }; - aml_tdmb: tdmb { - compatible = "amlogic, g12a-snd-tdmb"; + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; dai-tdm-lane-slot-mask-out = <1 0 0 0>; @@ -918,6 +874,9 @@ clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + /* * 0: tdmout_a; * 1: tdmout_b; @@ -926,47 +885,38 @@ * 4: spdifout_b; */ samesource_sel = <3>; + + status = "okay"; }; - aml_tdmc: tdmc { - compatible = "amlogic, g12a-snd-tdmc"; + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; #dai-tdm-lane-slot-mask-out = <1 0 1 1>; #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C &clkc CLKID_MPLL2>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; }; - /* copy a useless tdm to output for hdmi, no pinmux */ - aml_i2s2hdmi: i2s2hdmi { - compatible = "amlogic, g12a-snd-tdmc"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-out = <1 1 1 1>; - dai-tdm-clk-sel = <2>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_C - &clkc CLKID_MPLL2>; - clock-names = "mclk", "clk_srcpll"; - - i2s2hdmi = <1>; - - status = "disabled"; - }; - - aml_spdif: spdif { - compatible = "amlogic, g12a-snd-spdif-a"; + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; clock-names = "sysclk", "fixed_clk", "gate_spdifin", "gate_spdifout", "clk_spdifin", "clk_spdifout"; interrupts = @@ -974,23 +924,26 @@ interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; - pinctrl-0 = <&spdifout &spdifin>; + pinctrl-0 = <&spdifout /* &spdifin */>; + status = "okay"; }; - aml_spdif_b: spdif_b { - compatible = "amlogic, g12a-snd-spdif-b"; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ - &clkaudio CLKID_AUDIO_SPDIFOUTB - &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; clock-names = "sysclk", "gate_spdifout", "clk_spdifout"; + status = "okay"; }; - aml_pdm: pdm { - compatible = "amlogic, g12a-snd-pdm"; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM &clkc CLKID_FCLK_DIV3 &clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_PDMIN0 @@ -1000,50 +953,45 @@ "dclk_srcpll", "pdm_dclk", "pdm_sysclk"; + pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; }; - aml_loopback: loopback { - compatible = "amlogic, snd-loopback"; - /* - * 0: out rate = in data rate; - * 1: out rate = loopback data rate; - */ - lb_mode = <0>; + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; - /* datain src - * 0: tdmin_a; - * 1: tdmin_b; - * 2: tdmin_c; - * 3: spdifin; - * 4: pdmin; - */ - datain_src = <4>; - datain_chnum = <8>; - datain_chmask = <0x3f>; + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; - /* tdmin_lb src - * 0: tdmoutA - * 1: tdmoutB - * 2: tdmoutC - * 3: PAD_tdminA - * 4: PAD_tdminB - * 5: PAD_tdminC - */ - datalb_src = <2>; - datalb_chnum = <8>; - datalb_chmask = <0x3>; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; status = "okay"; }; - audioresample: resample { - compatible = "amlogic, g12a-resample"; + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; clocks = <&clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_MCLK_F - &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src * TDMIN_A, 0 @@ -1056,29 +1004,6 @@ * LOOPBACK, 7 */ resample_module = <4>; - status = "okay"; - }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - status = "disabled"; }; }; /* end of audiobus */ @@ -1134,12 +1059,12 @@ }; tdmout_c:tdmout_c { - mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + mux { /* GPIOA_12, GPIOA_13 */ groups = "tdmc_sclk_a", - "tdmc_fs_a", - "tdmc_dout0_a" - /*, "tdmc_dout2", - * "tdmc_dout3" + "tdmc_fs_a" + /*, "tdmc_dout0_a" + *, "tdmc_dout2" + *, "tdmc_dout3" */; function = "tdmc_out"; }; @@ -1159,23 +1084,13 @@ }; }; - /* GPIOH_4 */ - /* - * spdifout: spdifout { - * mux { - * groups = "spdif_out_h"; - * function = "spdif_out"; - * }; - *}; - */ - pdmin: pdmin { - mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ groups = "pdm_din0_a", - /*"pdm_din1_a",*/ - "pdm_din2_a", - /*"pdm_din3_a",*/ - "pdm_dclk_a"; + "pdm_din1_a", + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; function = "pdm"; }; }; @@ -1216,9 +1131,10 @@ }; /* end of pinctrl_periphs */ + &pinctrl_aobus { spdifout: spdifout { - mux { /* gpiao_10 */ + mux { /* GPIOAO_10 */ groups = "spdif_out_ao"; function = "spdif_out_ao"; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 89370b3b4bd3..50f295f9f27b 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -540,32 +540,13 @@ tdmout_index = <1>; status = "okay"; }; - audio_effect:eqdrc{ - /*eq_enable = <1>;*/ - /*drc_enable = <1>;*/ - /* - * 0:tdmout_a - * 1:tdmout_b - * 2:tdmout_c - * 3:spdifout - * 4:spdifout_b - */ - eqdrc_module = <1>; - /* max 0xf, each bit for one lane, usually one lane */ - lane_mask = <0x1>; - /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; - }; + auge_sound { compatible = "amlogic, g12a-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; - aml-audio-card,loopback = <&aml_loopback>; - aml-audio-card,aux-devs = <&amlogic_codec>; /*avout mute gpio*/ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - /*for audio effect ,eqdrc */ - aml-audio-card,effect = <&audio_effect>; aml-audio-card,dai-link@0 { format = "dsp_a"; @@ -573,14 +554,17 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; */ suffix-name = "alsaPORT-pcm"; tdmacpu: cpu { - sound-dai = <&aml_tdma>; + sound-dai = <&tdma>; dai-tdm-slot-tx-mask = <1 1 1 1 1 1 1 1>; dai-tdm-slot-rx-mask = @@ -600,8 +584,10 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ //bitclock-master = <&tdmbcodec>; //frame-master = <&tdmbcodec>; /* suffix-name, sync with android audio hal @@ -609,7 +595,7 @@ */ suffix-name = "alsaPORT-i2s"; cpu { - sound-dai = <&aml_tdmb>; + sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; @@ -635,22 +621,24 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmc>; - frame-master = <&aml_tdmc>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ //suffix-name = "alsaPORT-tdm"; cpu { - sound-dai = <&aml_tdmc>; + sound-dai = <&tdmc>; dai-tdm-slot-tx-mask = <1 1>; dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { - sound-dai = <&tlv320adc3101_32 &dummy_codec>; + tdmccodec: codec { + sound-dai = <&dummy_codec>; }; }; @@ -661,7 +649,7 @@ */ suffix-name = "alsaPORT-pdm"; cpu { - sound-dai = <&aml_pdm>; + sound-dai = <&pdm>; }; codec { sound-dai = <&pdm_codec>; @@ -670,61 +658,43 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; - continuous-clock; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-spdifb2hdmi"; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; cpu { - sound-dai = <&aml_spdif>; + sound-dai = <&spdifa>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { mclk-fs = <128>; continuous-clock; /* suffix-name, sync with android audio hal * what's the dai link used for */ - suffix-name = "alsaPORT-spdif"; + suffix-name = "alsaPORT-spdifb"; cpu { - sound-dai = <&aml_spdif_b>; + sound-dai = <&spdifb>; system-clock-frequency = <6144000>; }; codec { sound-dai = <&dummy_codec>; }; }; - /* - * dai link for i2s to hdmix, - * Notice to select a tdm lane not used by hw - */ - /* - * aml-audio-card,dai-link@6 { - * format = "i2s"; - * mclk-fs = <256>; - * //continuous-clock; - * //bitclock-inversion; - * //frame-inversion; - * bitclock-master = <&aml_i2s2hdmi>; - * frame-master = <&aml_i2s2hdmi>; - * suffix-name = "alsaPORT-i2s2hdmi"; - * cpu { - * sound-dai = <&aml_i2s2hdmi>; - * dai-tdm-slot-tx-mask = <1 1>; - * dai-tdm-slot-num = <2>; - * dai-tdm-slot-width = <32>; - * system-clock-frequency = <12288000>; - * }; - * codec { - * sound-dai = <&dummy_codec>; - * }; - * }; - */ + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; audiolocker: locker { compatible = "amlogic, audiolocker"; @@ -740,7 +710,7 @@ interrupt-names = "irq"; frequency = <49000000>; /* pll */ dividor = <49>; /* locker's parent */ - status = "okay"; + status = "disabled"; }; /* Audio Related end */ @@ -868,22 +838,6 @@ reset_pin = <&gpio GPIOA_5 0>; }; - tlv320adc3101_32: tlv320adc3101_32@32 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x19>; - differential_pair = <1>; - status = "okay"; - }; - - tas5707_36: tas5707_36@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "disabled"; - reset_pin = <&gpio GPIOA_5 0>; - }; - bl_extern_i2c { compatible = "bl_extern, i2c"; dev_name = "lp8556"; @@ -893,8 +847,8 @@ }; &audiobus { - aml_tdma: tdma { - compatible = "amlogic, g12a-snd-tdma"; + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1>; dai-tdm-oe-lane-slot-mask-out = <1 0>; @@ -904,10 +858,12 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; }; - aml_tdmb: tdmb { - compatible = "amlogic, g12a-snd-tdmb"; + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; dai-tdm-lane-slot-mask-out = <1 0 0 0>; @@ -918,6 +874,9 @@ clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + /* * 0: tdmout_a; * 1: tdmout_b; @@ -926,47 +885,38 @@ * 4: spdifout_b; */ samesource_sel = <3>; + + status = "okay"; }; - aml_tdmc: tdmc { - compatible = "amlogic, g12a-snd-tdmc"; + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; #dai-tdm-lane-slot-mask-out = <1 0 1 1>; #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C &clkc CLKID_MPLL2>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; }; - /* copy a useless tdm to output for hdmi, no pinmux */ - aml_i2s2hdmi: i2s2hdmi { - compatible = "amlogic, g12a-snd-tdmc"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-out = <1 1 1 1>; - dai-tdm-clk-sel = <2>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_C - &clkc CLKID_MPLL2>; - clock-names = "mclk", "clk_srcpll"; - - i2s2hdmi = <1>; - - status = "disabled"; - }; - - aml_spdif: spdif { - compatible = "amlogic, g12a-snd-spdif-a"; + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; clock-names = "sysclk", "fixed_clk", "gate_spdifin", "gate_spdifout", "clk_spdifin", "clk_spdifout"; interrupts = @@ -975,22 +925,25 @@ interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; }; - aml_spdif_b: spdif_b { - compatible = "amlogic, g12a-snd-spdif-b"; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ - &clkaudio CLKID_AUDIO_SPDIFOUTB - &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; clock-names = "sysclk", "gate_spdifout", "clk_spdifout"; + status = "okay"; }; - aml_pdm: pdm { - compatible = "amlogic, g12a-snd-pdm"; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM &clkc CLKID_FCLK_DIV3 &clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_PDMIN0 @@ -1000,50 +953,46 @@ "dclk_srcpll", "pdm_dclk", "pdm_sysclk"; + pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ - status = "okay"; - }; - aml_loopback: loopback { - compatible = "amlogic, snd-loopback"; - /* - * 0: out rate = in data rate; - * 1: out rate = loopback data rate; - */ - lb_mode = <0>; - /* datain src - * 0: tdmin_a; - * 1: tdmin_b; - * 2: tdmin_c; - * 3: spdifin; - * 4: pdmin; - */ - datain_src = <4>; - datain_chnum = <8>; - datain_chmask = <0x3f>; - - /* tdmin_lb src - * 0: tdmoutA - * 1: tdmoutB - * 2: tdmoutC - * 3: PAD_tdminA - * 4: PAD_tdminB - * 5: PAD_tdminC - */ - datalb_src = <2>; - datalb_chnum = <8>; - datalb_chmask = <0x3>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; status = "okay"; }; - audioresample: resample { - compatible = "amlogic, g12a-resample"; + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; clocks = <&clkc CLKID_MPLL3 &clkaudio CLKID_AUDIO_MCLK_F - &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src * TDMIN_A, 0 @@ -1056,29 +1005,6 @@ * LOOPBACK, 7 */ resample_module = <4>; - status = "okay"; - }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - status = "disabled"; }; }; /* end of audiobus */ @@ -1159,18 +1085,8 @@ }; }; - /* GPIOH_4 */ - /* - * spdifout: spdifout { - * mux { - * groups = "spdif_out_h"; - * function = "spdif_out"; - * }; - *}; - */ - pdmin: pdmin { - mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ groups = "pdm_din0_a", /*"pdm_din1_a",*/ "pdm_din2_a", @@ -1218,7 +1134,7 @@ }; /* end of pinctrl_periphs */ &pinctrl_aobus { spdifout: spdifout { - mux { /* gpiao_10 */ + mux { /* GPIOAO_10 */ groups = "spdif_out_ao"; function = "spdif_out_ao"; }; diff --git a/include/dt-bindings/clock/amlogic,sm1-audio-clk.h b/include/dt-bindings/clock/amlogic,sm1-audio-clk.h new file mode 100644 index 000000000000..9ec20b6116f1 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,sm1-audio-clk.h @@ -0,0 +1,92 @@ +/* + * include/dt-bindings/clock/amlogic,sm1-audio-clk.h + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __SM1_AUDIO_CLK_H__ +#define __SM1_AUDIO_CLK_H__ + +/* + * CLKID audio index values + */ +/* Gate En0 */ +#define CLKID_AUDIO_GATE_DDR_ARB 0 +#define CLKID_AUDIO_GATE_PDM 1 +#define CLKID_AUDIO_GATE_TDMINA 2 +#define CLKID_AUDIO_GATE_TDMINB 3 +#define CLKID_AUDIO_GATE_TDMINC 4 +#define CLKID_AUDIO_GATE_TDMINLB 5 +#define CLKID_AUDIO_GATE_TDMOUTA 6 +#define CLKID_AUDIO_GATE_TDMOUTB 7 +#define CLKID_AUDIO_GATE_TDMOUTC 8 +#define CLKID_AUDIO_GATE_FRDDRA 9 +#define CLKID_AUDIO_GATE_FRDDRB 10 +#define CLKID_AUDIO_GATE_FRDDRC 11 +#define CLKID_AUDIO_GATE_TODDRA 12 +#define CLKID_AUDIO_GATE_TODDRB 13 +#define CLKID_AUDIO_GATE_TODDRC 14 +#define CLKID_AUDIO_GATE_LOOPBACKA 15 +#define CLKID_AUDIO_GATE_SPDIFIN 16 +#define CLKID_AUDIO_GATE_SPDIFOUT_A 17 +#define CLKID_AUDIO_GATE_RESAMPLEA 18 +#define CLKID_AUDIO_GATE_RESERVED0 19 +#define CLKID_AUDIO_GATE_TORAM 20 +#define CLKID_AUDIO_GATE_SPDIFOUT_B 21 +#define CLKID_AUDIO_GATE_EQDRC 22 +#define CLKID_AUDIO_GATE_RESERVED1 23 +#define CLKID_AUDIO_GATE_RESERVED2 24 +#define CLKID_AUDIO_GATE_RESERVED3 25 +#define CLKID_AUDIO_GATE_RESAMPLEB 26 +#define CLKID_AUDIO_GATE_TOVAD 27 +#define CLKID_AUDIO_GATE_AUDIOLOCKER 28 +#define CLKID_AUDIO_GATE_SPDIFIN_LB 29 +#define CLKID_AUDIO_GATE_RESERVED4 30 +#define CLKID_AUDIO_GATE_RESERVED5 31 + +/* Gate En1 */ +#define CLKID_AUDIO_GATE_FRDDRD 32 +#define CLKID_AUDIO_GATE_TODDRD 33 +#define CLKID_AUDIO_GATE_LOOPBACKB 34 +#define CLKID_AUDIO_GATE_EARCRX 35 + +#define CLKID_AUDIO_GATE_MAX 36 + +#define MCLK_BASE CLKID_AUDIO_GATE_MAX +#define CLKID_AUDIO_MCLK_A (MCLK_BASE + 0) +#define CLKID_AUDIO_MCLK_B (MCLK_BASE + 1) +#define CLKID_AUDIO_MCLK_C (MCLK_BASE + 2) +#define CLKID_AUDIO_MCLK_D (MCLK_BASE + 3) +#define CLKID_AUDIO_MCLK_E (MCLK_BASE + 4) +#define CLKID_AUDIO_MCLK_F (MCLK_BASE + 5) + +#define CLKID_AUDIO_SPDIFIN (MCLK_BASE + 6) +#define CLKID_AUDIO_SPDIFOUT_A (MCLK_BASE + 7) +#define CLKID_AUDIO_RESAMPLE_A (MCLK_BASE + 8) +#define CLKID_AUDIO_LOCKER_OUT (MCLK_BASE + 9) +#define CLKID_AUDIO_LOCKER_IN (MCLK_BASE + 10) +#define CLKID_AUDIO_PDMIN0 (MCLK_BASE + 11) +#define CLKID_AUDIO_PDMIN1 (MCLK_BASE + 12) +#define CLKID_AUDIO_SPDIFOUT_B (MCLK_BASE + 13) +#define CLKID_AUDIO_RESAMPLE_B (MCLK_BASE + 14) +#define CLKID_AUDIO_SPDIFIN_LB (MCLK_BASE + 15) +#define CLKID_AUDIO_EQDRC (MCLK_BASE + 16) +#define CLKID_AUDIO_VAD (MCLK_BASE + 17) +#define CLKID_EARCTX_CMDC (MCLK_BASE + 18) +#define CLKID_EARCTX_DMAC (MCLK_BASE + 19) +#define CLKID_EARCRX_CMDC (MCLK_BASE + 20) +#define CLKID_EARCRX_DMAC (MCLK_BASE + 21) + +#define NUM_AUDIO_CLKS (MCLK_BASE + 22) +#endif /* __SM1_AUDIO_CLK_H__ */ From ee60fdb6388c5b0b072e56272d220b686fd0564f Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Thu, 21 Mar 2019 22:52:17 +0800 Subject: [PATCH 0139/1060] audio: auge: support av out and amp spk for sm1 [1/2] PD#SWPL-6192 Problem: no sound from av and amp spk Solution: 1) fix tocodec for sm1 2) add no mclk control for ad82584 Verify: ac200 Change-Id: I63f0ec94d2f5b980249ac5c9c810c8e4d8410ea3 Signed-off-by: Xing Wang --- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 6 ++ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 7 +++ .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 6 ++ .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 6 ++ .../linux/amlogic/media/sound/auge_utils.h | 1 + sound/soc/amlogic/auge/audio_utils.c | 14 +++++ sound/soc/codecs/amlogic/ad82584f.c | 16 +++++ sound/soc/codecs/amlogic/ad82584f.h | 1 + sound/soc/codecs/amlogic/aml_codec_t9015.c | 63 ++++++++++++------- 9 files changed, 99 insertions(+), 21 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index f75ef1b3a7e1..3c4c7b17bfd1 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -539,7 +539,11 @@ compatible = "amlogic, aml_codec_T9015"; reg = <0xFF632000 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + status = "okay"; }; @@ -838,6 +842,7 @@ reg = <0x31>; status = "okay"; reset_pin = <&gpio GPIOA_5 0>; + no_mclk; }; bl_extern_i2c { @@ -1134,6 +1139,7 @@ }; /* end of pinctrl_periphs */ + &pinctrl_aobus { spdifout: spdifout { mux { /* GPIOAO_10 */ diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index caaa308c8c90..569a7eda8e9b 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -539,7 +539,11 @@ compatible = "amlogic, aml_codec_T9015"; reg = <0xFF632000 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + status = "okay"; }; @@ -838,6 +842,7 @@ reg = <0x31>; status = "okay"; reset_pin = <&gpio GPIOA_5 0>; + no_mclk; }; bl_extern_i2c { @@ -964,6 +969,7 @@ status = "okay"; }; + earc:earc { compatible = "amlogic, sm1-snd-earc"; #sound-dai-cells = <0>; @@ -1133,6 +1139,7 @@ }; /* end of pinctrl_periphs */ + &pinctrl_aobus { spdifout: spdifout { mux { /* GPIOAO_10 */ diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index a0d27e578c50..bf456881b3cc 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -537,7 +537,11 @@ compatible = "amlogic, aml_codec_T9015"; reg = <0x0 0xFF632000 0x0 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + status = "okay"; }; @@ -836,6 +840,7 @@ reg = <0x31>; status = "okay"; reset_pin = <&gpio GPIOA_5 0>; + no_mclk; }; bl_extern_i2c { @@ -962,6 +967,7 @@ status = "okay"; }; + earc:earc { compatible = "amlogic, sm1-snd-earc"; #sound-dai-cells = <0>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 50f295f9f27b..4a312aeec8d9 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -537,7 +537,11 @@ compatible = "amlogic, aml_codec_T9015"; reg = <0x0 0xFF632000 0x0 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + status = "okay"; }; @@ -836,6 +840,7 @@ reg = <0x31>; status = "okay"; reset_pin = <&gpio GPIOA_5 0>; + no_mclk; }; bl_extern_i2c { @@ -1132,6 +1137,7 @@ }; /* end of pinctrl_periphs */ + &pinctrl_aobus { spdifout: spdifout { mux { /* GPIOAO_10 */ diff --git a/include/linux/amlogic/media/sound/auge_utils.h b/include/linux/amlogic/media/sound/auge_utils.h index 6b21c42745c1..1e4f6fd8d0b2 100644 --- a/include/linux/amlogic/media/sound/auge_utils.h +++ b/include/linux/amlogic/media/sound/auge_utils.h @@ -20,4 +20,5 @@ void auge_acodec_reset(void); void auge_toacodec_ctrl(int tdmout_id); +void auge_toacodec_ctrl_ext(int tdmout_id, int ch0_sel, int ch1_sel); #endif diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 32dca83e41c3..14617d785b52 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -1492,6 +1492,20 @@ void auge_toacodec_ctrl(int tdmout_id) ); } +void auge_toacodec_ctrl_ext(int tdmout_id, int ch0_sel, int ch1_sel) +{ + // TODO: check skew for tl1/sm1 + audiobus_write(EE_AUDIO_TOACODEC_CTRL0, + 1 << 31 + | ((tdmout_id << 2) + ch1_sel) << 20 /* data 1 */ + | ((tdmout_id << 2) + ch0_sel) << 16 /* data 0 */ + | tdmout_id << 12 /* lrclk */ + | 1 << 9 /* Bclk_cap_inv*/ + | tdmout_id << 4 /* bclk */ + | tdmout_id << 0 /* mclk */ + ); +} + void fratv_enable(bool enable) { /* Need reset firstlry ? */ diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index 88fea3497960..8e68ad5393e2 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -808,12 +808,22 @@ static int ad82584f_reg_init(struct snd_soc_codec *codec) } static int ad82584f_init(struct snd_soc_codec *codec) { + struct ad82584f_priv *ad82584f = snd_soc_codec_get_drvdata(codec); + reset_ad82584f_GPIO(codec); dev_info(codec->dev, "ad82584f_init!\n"); ad82584f_reg_init(codec); + /* Bclk system */ + if (ad82584f->pdata->no_mclk) + snd_soc_write(codec, + 0x01, + 0x1 << 7 | /* Bclk system enable */ + 0x1 << 0 /* 64x bclk/fs */ + ); + /*eq and drc*/ ad82584f_set_eq_drc(codec); @@ -945,6 +955,12 @@ static int ad82584f_parse_dt( } ad82584f->pdata->reset_pin = reset_pin; + ad82584f->pdata->no_mclk = of_property_read_bool( + np, + "no_mclk"); + if (ad82584f->pdata->no_mclk) + pr_info("%s mclk is not connected.\n", __func__); + return ret; } diff --git a/sound/soc/codecs/amlogic/ad82584f.h b/sound/soc/codecs/amlogic/ad82584f.h index fd149b8bbf0c..21207cc98632 100644 --- a/sound/soc/codecs/amlogic/ad82584f.h +++ b/sound/soc/codecs/amlogic/ad82584f.h @@ -16,6 +16,7 @@ struct ad82584f_platform_data { int reset_pin; + bool no_mclk; }; #endif diff --git a/sound/soc/codecs/amlogic/aml_codec_t9015.c b/sound/soc/codecs/amlogic/aml_codec_t9015.c index 7d6aee2c6ad0..1ec6891d9912 100644 --- a/sound/soc/codecs/amlogic/aml_codec_t9015.c +++ b/sound/soc/codecs/amlogic/aml_codec_t9015.c @@ -46,7 +46,13 @@ struct aml_T9015_audio_priv { /* codec is used by meson or auge arch */ bool is_auge_arch; + /* tocodec ctrl supports in and out data */ + bool tocodec_inout; + /* attach which tdm when play */ int tdmout_index; + /* channel map */ + int ch0_sel; + int ch1_sel; }; static const struct reg_default t9015_init_list[] = { @@ -72,26 +78,20 @@ static int aml_DAC_Gain_get_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { -#if 0 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - u32 add, val, val1, val2; -#endif - /*TODO: return 0 for tmp, this wolud modified later */ - return 0; -#if 0 - if (codec == NULL) - return -1; + u32 reg_addr = ADC_VOL_CTR_PGA_IN_CONFIG; + u32 val = snd_soc_read(codec, reg_addr); + u32 val1 = (val & (0x1 << DAC_GAIN_SEL_L)) + >> DAC_GAIN_SEL_L; + u32 val2 = (val & (0x1 << DAC_GAIN_SEL_H)) + >> (DAC_GAIN_SEL_H); - add = ADC_VOL_CTR_PGA_IN_CONFIG; - val = snd_soc_read(codec, add); - val1 = (val & (0x1 << DAC_GAIN_SEL_L)) >> DAC_GAIN_SEL_L; - val2 = (val & (0x1 << DAC_GAIN_SEL_H)) >> (DAC_GAIN_SEL_H - 1); + val = val1 | (val2 << 1); - val = val1 | val2; ucontrol->value.enumerated.item[0] = val; + return 0; - #endif } static int aml_DAC_Gain_set_enum( @@ -100,8 +100,8 @@ static int aml_DAC_Gain_set_enum( { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - u32 add = ADC_VOL_CTR_PGA_IN_CONFIG; - u32 val = snd_soc_read(codec, add); + u32 addr = ADC_VOL_CTR_PGA_IN_CONFIG; + u32 val = snd_soc_read(codec, addr); if (ucontrol->value.enumerated.item[0] == 0) { val &= ~(0x1 << DAC_GAIN_SEL_H); @@ -120,7 +120,7 @@ static int aml_DAC_Gain_set_enum( pr_info("It has risk of distortion!\n"); } - snd_soc_write(codec, val, add); + snd_soc_write(codec, addr, val); return 0; } @@ -407,9 +407,15 @@ static int aml_T9015_audio_probe(struct snd_soc_codec *codec) aml_T9015_audio_start_up(codec); aml_T9015_audio_reg_init(codec); - if (T9015_audio && T9015_audio->is_auge_arch) - auge_toacodec_ctrl(T9015_audio->tdmout_index); - else + if (T9015_audio && T9015_audio->is_auge_arch) { + if (T9015_audio->tocodec_inout) + auge_toacodec_ctrl_ext( + T9015_audio->tdmout_index, + T9015_audio->ch0_sel, + T9015_audio->ch1_sel); + else + auge_toacodec_ctrl(T9015_audio->tdmout_index); + } else aml_write_cbus(AIU_ACODEC_CTRL, (1 << 4) |(1 << 6) @@ -546,12 +552,27 @@ static int aml_T9015_audio_codec_probe(struct platform_device *pdev) T9015_audio->is_auge_arch = of_property_read_bool( pdev->dev.of_node, "is_auge_used"); + + T9015_audio->tocodec_inout = of_property_read_bool( + pdev->dev.of_node, + "tocodec_inout"); + of_property_read_u32( pdev->dev.of_node, "tdmout_index", &T9015_audio->tdmout_index); - pr_info("aml_codec_T9015 is used by %s chipset, tdmout:%d\n", + of_property_read_u32( + pdev->dev.of_node, + "ch0_sel", + &T9015_audio->ch0_sel); + + of_property_read_u32( + pdev->dev.of_node, + "ch1_sel", + &T9015_audio->ch1_sel); + + pr_info("T9015 acodec used by %s, tdmout:%d\n", T9015_audio->is_auge_arch ? "auge" : "meson", T9015_audio->tdmout_index); From 8e629de81c8ba1357ce1cdda01ef47b3ae201b2f Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Fri, 29 Mar 2019 17:21:05 +0800 Subject: [PATCH 0140/1060] audio: fixed conflict of SM1-bringup and mainline [1/1] PD#SWPL-6486 Problem: merge to mainline conflict. Solution: add clk change in dts Verify: sm1_ac200, verify pass Change-Id: I37e7317cd795cd8cb9815ff20db49bc8644f0087 Signed-off-by: Zhe Wang --- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 6 ++++-- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 6 ++++-- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 6 ++++-- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 6 ++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 3c4c7b17bfd1..2dac16424fda 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -877,8 +877,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 569a7eda8e9b..4e206be31752 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -877,8 +877,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index bf456881b3cc..00334947f236 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -875,8 +875,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 4a312aeec8d9..dfad850104ed 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -875,8 +875,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; From fbab873d05c491a57d692170350d1ea68e3a182a Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Fri, 15 Mar 2019 15:06:25 +0800 Subject: [PATCH 0141/1060] cpufreq: dts: adjust cpufreq table for g12b [1/1] PD#SWPL-5975 Problem: adjust cpufreq table for g12b Solution: adjust cpufreq table for g12b Verify: test pass on g12b_w400 Change-Id: I037ab2a1718a2aae0f42a15b7d95f163bc77ca85 Signed-off-by: Hong Guo --- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 38 +++++++--------- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 38 +++++++--------- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 38 +++++++--------- .../g12b_a311d_w400_buildroot_vccktest.dts | 44 ++++++++----------- arch/arm/boot/dts/amlogic/g12b_pxp.dts | 34 +++++++------- .../arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 38 +++++++--------- .../boot/dts/amlogic/g12b_a311d_w400.dts | 38 +++++++--------- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 38 +++++++--------- .../g12b_a311d_w400_buildroot_vccktest.dts | 44 ++++++++----------- .../dts/amlogic/g12b_a311x_w411_buildroot.dts | 38 +++++++--------- arch/arm64/boot/dts/amlogic/g12b_pxp.dts | 34 +++++++------- 11 files changed, 189 insertions(+), 233 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 155a1edede8e..932f68f5c110 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -666,35 +666,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -724,43 +720,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 88b7280ef6c5..9dea114c0ad6 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -646,35 +646,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -704,43 +700,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 985a67248d71..57aa35a16a79 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -729,35 +729,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -787,43 +783,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index fcdffd350d5d..4703b7717f8a 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -694,39 +694,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { - opp-hz = /bits/ 64 <1896000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp12 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1001000>; }; }; @@ -756,43 +748,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp.dts b/arch/arm/boot/dts/amlogic/g12b_pxp.dts index 463a91c3a509..f75d525e77e5 100644 --- a/arch/arm/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12b_pxp.dts @@ -368,31 +368,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -422,43 +422,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 514c0173bd4a..47d8ef62c109 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -666,35 +666,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -724,43 +720,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 9a70c6a09ca3..6eac15d75d0f 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -634,35 +634,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -692,43 +688,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 573189496d02..842047aed3ff 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -728,35 +728,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -786,43 +782,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 8f00163b5ce1..fd591ed2c338 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -694,39 +694,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { - opp-hz = /bits/ 64 <1896000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp12 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1001000>; }; }; @@ -756,43 +748,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index cb70d1aca034..fc170d5f074e 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -721,35 +721,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1001000>; }; }; @@ -779,43 +775,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts index c1960ce0ba5a..36f125968f83 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts @@ -367,31 +367,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -421,43 +421,43 @@ }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <731000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <741000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <771000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <801000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <821000>; + opp-microvolt = <911000>; }; opp13 { opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <851000>; + opp-microvolt = <951000>; }; opp14 { opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <901000>; + opp-microvolt = <1011000>; }; }; From 5b4bf69fdb0e8efb51827dcae22d07d7b1b58cd3 Mon Sep 17 00:00:00 2001 From: Huan Biao Date: Tue, 2 Apr 2019 18:56:10 +0800 Subject: [PATCH 0142/1060] thermal: move thermal dts for sm1 [1/1] PD#SWPL-6675 Problem: sm1 thermal dts issue Solution: move thermal dts for dtsi to board dts Verify: test pass on sm1_ac200 Change-Id: I3fa5f2f4b15bc78d322d94402b8d0894fd8cbd35 Signed-off-by: Huan Biao --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 170 ----------------- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 170 +++++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 170 +++++++++++++++++ arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 170 ----------------- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 171 ++++++++++++++++++ .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 170 +++++++++++++++++ 6 files changed, 681 insertions(+), 340 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index d1f63cda9076..dff93695761d 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -477,42 +477,6 @@ reg = <0xff809000 0x48>; }; - p_tsensor: p_tsensor@ff634594 { - compatible = "amlogic, r1p1-tsensor"; - device_name = "meson-pthermal"; - status = "okay"; - reg = <0xff634800 0x50>, - <0xff800268 0x4>; - cal_type = <0x1>; - cal_a = <324>; - cal_b = <424>; - cal_c = <3159>; - cal_d = <9411>; - rtemp = <115000>; - interrupts = <0 35 0>; - clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ - clock-names = "ts_comp"; - #thermal-sensor-cells = <1>; - }; - - d_tsensor: d_tsensor@ff800228 { - compatible = "amlogic, r1p1-tsensor"; - device_name = "meson-dthermal"; - status = "okay"; - reg = <0xff634c00 0x50>, - <0xff800230 0x4>; - cal_type = <0x1>; - cal_a = <324>; - cal_b = <424>; - cal_c = <3159>; - cal_d = <9411>; - rtemp = <115000>; - interrupts = <0 36 0>; - clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ - clock-names = "ts_comp"; - #thermal-sensor-cells = <1>; - }; - power_ctrl: power_ctrl@ff8000e8 { compatible = "amlogic, sm1-powerctrl"; reg = <0xff8000e8 0x10>, @@ -1549,140 +1513,6 @@ /*partions defined in dts */ }; - meson_cooldev: meson-cooldev@0 { - status = "okay"; - compatible = "amlogic, meson-cooldev"; - device_name = "mcooldev"; - cooling_devices { - cpufreq_cool_cluster0 { - min_state = <1000000>; - dyn_coeff = <115>; - cluster_id = <0>; - node_name = "cpufreq_cool0"; - device_type = "cpufreq"; - }; - cpucore_cool_cluster0 { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - gpufreq_cool { - min_state = <400>; - dyn_coeff = <358>; - gpu_pp = <2>; - cluster_id = <0>; - node_name = "gpufreq_cool0"; - device_type = "gpufreq"; - }; - gpucore_cool { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "gpucore_cool0"; - device_type = "gpucore"; - }; - }; - cpufreq_cool0:cpufreq_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - gpufreq_cool0:gpufreq_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - gpucore_cool0:gpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - }; - /*meson cooling devices end*/ - - thermal-zones { - soc_thermal: soc_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <1460>; - thermal-sensors = <&p_tsensor 0>; - trips { - pswitch_on: trip-point@0 { - temperature = <60000>; - hysteresis = <5000>; - type = "passive"; - }; - pcontrol: trip-point@1 { - temperature = <75000>; - hysteresis = <5000>; - type = "passive"; - }; - phot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - pcritical: trip-point@3 { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - cpufreq_cooling_map { - trip = <&pcontrol>; - cooling-device = <&cpufreq_cool0 0 4>; - contribution = <1024>; - }; - cpucore_cooling_map { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 3>; - contribution = <1024>; - }; - gpufreq_cooling_map { - trip = <&pcontrol>; - cooling-device = <&gpufreq_cool0 0 4>; - contribution = <1024>; - }; - gpucore_cooling_map { - trip = <&pcontrol>; - cooling-device = <&gpucore_cool0 0 2>; - contribution = <1024>; - }; - }; - }; - ddr_thermal: ddr_thermal { - polling-delay = <2000>; - polling-delay-passive = <1000>; - sustainable-power = <1460>; - thermal-sensors = <&d_tsensor 1>; - trips { - dswitch_on: trip-point@0 { - temperature = <60000>; - hysteresis = <5000>; - type = "passive"; - }; - dcontrol: trip-point@1 { - temperature = <75000>; - hysteresis = <5000>; - type = "passive"; - }; - dhot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - dcritical: trip-point@3 { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - }; - }; - /*thermal zone end*/ - /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 2dac16424fda..3925f85444c9 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -720,6 +720,176 @@ }; /* Audio Related end */ + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 4e206be31752..73eb22bebb64 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -720,6 +720,176 @@ }; /* Audio Related end */ + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index c40bac63e053..e002a5c425d6 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -477,42 +477,6 @@ reg = <0x0 0xff809000 0x0 0x48>; }; - p_tsensor: p_tsensor@ff634594 { - compatible = "amlogic, r1p1-tsensor"; - device_name = "meson-pthermal"; - status = "okay"; - reg = <0x0 0xff634800 0x0 0x50>, - <0x0 0xff800268 0x0 0x4>; - cal_type = <0x1>; - cal_a = <324>; - cal_b = <424>; - cal_c = <3159>; - cal_d = <9411>; - rtemp = <115000>; - interrupts = <0 35 0>; - clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ - clock-names = "ts_comp"; - #thermal-sensor-cells = <1>; - }; - - d_tsensor: d_tsensor@ff800228 { - compatible = "amlogic, r1p1-tsensor"; - device_name = "meson-dthermal"; - status = "okay"; - reg = <0x0 0xff634c00 0x0 0x50>, - <0x0 0xff800230 0x0 0x4>; - cal_type = <0x1>; - cal_a = <324>; - cal_b = <424>; - cal_c = <3159>; - cal_d = <9411>; - rtemp = <115000>; - interrupts = <0 36 0>; - clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ - clock-names = "ts_comp"; - #thermal-sensor-cells = <1>; - }; - power_ctrl: power_ctrl@ff8000e8 { compatible = "amlogic, sm1-powerctrl"; reg = <0x0 0xff8000e8 0x0 0x10>, @@ -1548,140 +1512,6 @@ /*partions defined in dts */ }; - meson_cooldev: meson-cooldev@0 { - status = "okay"; - compatible = "amlogic, meson-cooldev"; - device_name = "mcooldev"; - cooling_devices { - cpufreq_cool_cluster0 { - min_state = <1000000>; - dyn_coeff = <115>; - cluster_id = <0>; - node_name = "cpufreq_cool0"; - device_type = "cpufreq"; - }; - cpucore_cool_cluster0 { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - gpufreq_cool { - min_state = <400>; - dyn_coeff = <358>; - gpu_pp = <2>; - cluster_id = <0>; - node_name = "gpufreq_cool0"; - device_type = "gpufreq"; - }; - gpucore_cool { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "gpucore_cool0"; - device_type = "gpucore"; - }; - }; - cpufreq_cool0:cpufreq_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - gpufreq_cool0:gpufreq_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - gpucore_cool0:gpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - }; - /*meson cooling devices end*/ - - thermal-zones { - soc_thermal: soc_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <1460>; - thermal-sensors = <&p_tsensor 0>; - trips { - pswitch_on: trip-point@0 { - temperature = <60000>; - hysteresis = <5000>; - type = "passive"; - }; - pcontrol: trip-point@1 { - temperature = <75000>; - hysteresis = <5000>; - type = "passive"; - }; - phot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - pcritical: trip-point@3 { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - cpufreq_cooling_map { - trip = <&pcontrol>; - cooling-device = <&cpufreq_cool0 0 4>; - contribution = <1024>; - }; - cpucore_cooling_map { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 3>; - contribution = <1024>; - }; - gpufreq_cooling_map { - trip = <&pcontrol>; - cooling-device = <&gpufreq_cool0 0 4>; - contribution = <1024>; - }; - gpucore_cooling_map { - trip = <&pcontrol>; - cooling-device = <&gpucore_cool0 0 2>; - contribution = <1024>; - }; - }; - }; - ddr_thermal: ddr_thermal { - polling-delay = <2000>; - polling-delay-passive = <1000>; - sustainable-power = <1460>; - thermal-sensors = <&d_tsensor 1>; - trips { - dswitch_on: trip-point@0 { - temperature = <60000>; - hysteresis = <5000>; - type = "passive"; - }; - dcontrol: trip-point@1 { - temperature = <75000>; - hysteresis = <5000>; - type = "passive"; - }; - dhot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - dcritical: trip-point@3 { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - }; - }; - /*thermal zone end*/ - /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 00334947f236..aec4a1559d22 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -718,6 +718,177 @@ }; /* Audio Related end */ + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index dfad850104ed..8c9b00315d25 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -718,6 +718,176 @@ }; /* Audio Related end */ + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; From 3f4a9226bb6c2f80ce8f314cd7fbdf02b85c54ed Mon Sep 17 00:00:00 2001 From: Chuangcheng Peng Date: Fri, 22 Mar 2019 18:08:48 +0800 Subject: [PATCH 0143/1060] dvb: sm1 bringup add one asyncfifo [2/2] PD#SWPL-5403 Problem: demux add one asyncfifo, need compatile Solution: demux compatile with previous code. Verify: verify at sm1 Change-Id: Iea0b7b5f69d3200062b9e757f2712b98926fb3b9 Signed-off-by: Chuangcheng Peng Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 2 +- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 42 +++++++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 42 +++++++++++++++++++ arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 2 +- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 42 +++++++++++++++++++ .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 42 +++++++++++++++++++ include/uapi/linux/dvb/ca.h | 16 ++++++- 7 files changed, 185 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index dff93695761d..d3578f68a00f 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -235,7 +235,7 @@ #size-cells=<1>; ranges; io_cbus_base { - reg = <0xffd00000 0x26000>; + reg = <0xffd00000 0x26fff>; }; io_apb_base { reg = <0xffe01000 0x7f000>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 3925f85444c9..64b021b802db 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -719,6 +719,48 @@ status = "disabled"; }; /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; p_tsensor: p_tsensor@ff634800 { compatible = "amlogic, r1p1-tsensor"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 73eb22bebb64..3ecd231e25b2 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -719,6 +719,48 @@ status = "disabled"; }; /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; p_tsensor: p_tsensor@ff634800 { compatible = "amlogic, r1p1-tsensor"; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index e002a5c425d6..286e7913be93 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -235,7 +235,7 @@ #size-cells=<2>; ranges; io_cbus_base { - reg = <0x0 0xffd00000 0x0 0x26000>; + reg = <0x0 0xffd00000 0x0 0x26fff>; }; io_apb_base { reg = <0x0 0xffe01000 0x0 0x7f000>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index aec4a1559d22..2abe261bb09e 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -717,6 +717,48 @@ status = "disabled"; }; /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; p_tsensor: p_tsensor@ff634800 { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 8c9b00315d25..ef75f873c773 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -717,6 +717,48 @@ status = "disabled"; }; /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; p_tsensor: p_tsensor@ff634800 { compatible = "amlogic, r1p1-tsensor"; diff --git a/include/uapi/linux/dvb/ca.h b/include/uapi/linux/dvb/ca.h index e7902227ece9..69ef406f730e 100644 --- a/include/uapi/linux/dvb/ca.h +++ b/include/uapi/linux/dvb/ca.h @@ -82,12 +82,26 @@ enum ca_cw_type { CA_CW_AES_EVEN, CA_CW_AES_ODD, CA_CW_AES_EVEN_IV, - CA_CW_AES_ODD_IV + CA_CW_AES_ODD_IV, + CA_CW_DES_EVEN, + CA_CW_DES_ODD, + CA_CW_SM4_EVEN, + CA_CW_SM4_ODD, + CA_CW_SM4_EVEN_IV, + CA_CW_SM4_ODD_IV, + CA_CW_TYPE_MAX +}; + +enum ca_dsc_mode { + CA_DSC_CBC = 1, + CA_DSC_ECB, + CA_DSC_IDSA }; struct ca_descr_ex { unsigned int index; enum ca_cw_type type; + enum ca_dsc_mode mode; int flags; #define CA_CW_FROM_KL 1 unsigned char cw[16]; From 8318004af0f68fecdd0bb1b06e9723c6379646c8 Mon Sep 17 00:00:00 2001 From: "shuanglong.wang" Date: Fri, 22 Mar 2019 10:36:38 +0800 Subject: [PATCH 0144/1060] video: hold frame for non-tunnel mode [1/1] PD#SWPL-6179 Problem: PLAY-AL1-30FPS-HEAAC exist multi short frame every 16.6s Solution: Hold one frame in case occur pattern broken. Problem occur as this, for non-tunnel mode, amlvideo vidioc_dqbuf in omx so fast, then lead decoder buffer quickly pushed to amlvideo queue with only current frame, without next frame. Hold one frame we need next frame and next frame pts after next frame, here we use next frame pts and a crease with duraion as next next frame pts. Verify: verify by u212 Change-Id: Ie98c30791e785abb886aa19a7e930d191f5c2b3e Signed-off-by: shuanglong.wang --- drivers/amlogic/media/video_sink/video.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index c324afd6c154..de38667de8c9 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -563,6 +563,9 @@ static int pts_trace; #define PTS_32_PATTERN_DETECT_RANGE 10 #define PTS_22_PATTERN_DETECT_RANGE 10 #define PTS_41_PATTERN_DETECT_RANGE 2 +#define PTS_32_PATTERN_DURATION 3750 +#define PTS_22_PATTERN_DURATION 3000 + enum video_refresh_pattern { PTS_32_PATTERN = 0, @@ -5027,10 +5030,13 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, { int pattern_range, expected_curr_interval; int expected_prev_interval; + int next_vf_nextpts = 0; /* Dont do anything if we have invalid data */ - if (!next_vf || !next_vf->pts || !next_vf->next_vf_pts_valid) + if (!next_vf || !next_vf->pts) return; + if (next_vf->next_vf_pts_valid) + next_vf_nextpts = next_vf->next_vf_pts; switch (pts_pattern_detected) { case PTS_32_PATTERN: @@ -5047,6 +5053,9 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, default: return; } + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_32_PATTERN_DURATION; break; case PTS_22_PATTERN: if (pre_pts_trace != 2) @@ -5054,6 +5063,9 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, pattern_range = PTS_22_PATTERN_DETECT_RANGE; expected_prev_interval = 2; expected_curr_interval = 2; + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_22_PATTERN_DURATION; break; case PTS_41_PATTERN: /* TODO */ @@ -5076,7 +5088,7 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, if (/*((int)(nextPts + expected_prev_interval * */ /*vsync_pts_inc - next_vf->next_vf_pts) < 0) && */ ((int)(nextPts + (expected_prev_interval + 1) * - vsync_pts_inc - next_vf->next_vf_pts) >= 0)) { + vsync_pts_inc - next_vf_nextpts) >= 0)) { *expired = false; if (pts_log_enable[PTS_32_PATTERN] || pts_log_enable[PTS_22_PATTERN]) @@ -5109,9 +5121,9 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, >= 0) && ((int)(nextPts + vsync_pts_inc * (expected_prev_interval - 1) - - next_vf->next_vf_pts) < 0) && + - next_vf_nextpts) < 0) && ((int)(nextPts + expected_prev_interval * - vsync_pts_inc - next_vf->next_vf_pts) >= 0)) { + vsync_pts_inc - next_vf_nextpts) >= 0)) { *expired = true; if (pts_log_enable[PTS_32_PATTERN] || pts_log_enable[PTS_22_PATTERN]) From a5c117fe9240020d0f0500f1e94bc3fb230690ec Mon Sep 17 00:00:00 2001 From: Liang Ji Date: Thu, 7 Mar 2019 11:08:25 +0800 Subject: [PATCH 0145/1060] avb_ab: add avb check for product product [1/2] PD#SWPL-6168 Problem: avb+abupdate with care map.txt cann't boot up because of check product partition Solution: add avb for product partition in dts Verify: ampere Change-Id: I0310853965340d9b810a89cbf1719f9ba002261d Signed-off-by: Liang Ji --- arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi | 2 +- arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi b/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi index d1154cca4a93..bcbede9eeb58 100644 --- a/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi +++ b/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi @@ -39,7 +39,7 @@ firmware { dev = "/dev/block/product"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,avb"; }; odm { compatible = "android,odm"; diff --git a/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi b/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi index 0ec3f8cf1c82..299febcbb32a 100644 --- a/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi +++ b/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi @@ -39,7 +39,7 @@ firmware { dev = "/dev/block/product"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,avb"; }; odm { compatible = "android,odm"; From 5bd505327f9aee75f493f9fdf05824a82232cc38 Mon Sep 17 00:00:00 2001 From: "deng.liu" Date: Tue, 26 Mar 2019 09:49:22 +0800 Subject: [PATCH 0146/1060] common: NN API implementation,upload 64bit dts [1/1] PD#SWPL-86 Problem: Android tensorflow lite ,NN API implementation Solution: NN API implementation Verify: Local on galilei Change-Id: I7c1a3a68005218544d0a3c7a7360c9ee38fc53de Signed-off-by: deng.liu --- arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts | 11 +++++++++++ arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts | 11 +++++++++++ arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 6eac15d75d0f..4e7c5eb3bba7 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -148,6 +148,17 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; gpioleds { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index 266185faf1c3..10f29ecba703 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -148,6 +148,17 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; gpioleds { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 9e04275a5d03..ea260a3452cc 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1140,7 +1140,7 @@ <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; clock-names = "cts_vipnanoq_axi_clk_composite", "cts_vipnanoq_core_clk_composite"; - interrupts = <0 147 1>; + interrupts = <0 147 4>; interrupt-names = "galcore"; reg = <0x0 0xff100000 0x0 0x800 0x0 0xff000000 0x0 0x400000>; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index d76692bbb909..283acfe4c325 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -1139,7 +1139,7 @@ <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; clock-names = "cts_vipnanoq_axi_clk_composite", "cts_vipnanoq_core_clk_composite"; - interrupts = <0 147 1>; + interrupts = <0 147 4>; interrupt-names = "galcore"; reg = <0x0 0xff100000 0x0 0x800 0x0 0xff000000 0x0 0x400000>; From d0a5a0469ba7c62dba4184c1fb3ecbf7557c7853 Mon Sep 17 00:00:00 2001 From: Hang Cheng Date: Mon, 25 Mar 2019 19:05:54 +0800 Subject: [PATCH 0147/1060] cec: remove func that may cause deadlock [1/1] PD#SWPL-5836 Problem: kernel panic when read cec reg Solution: remove func that might cause sleep in spinlock, so as to avoid deadlock Verify: S805X-P241 Change-Id: I8394f69bdbeff6673c795a221c08ef76164c5bdb Signed-off-by: Hang Cheng Signed-off-by: Luan Yuan --- drivers/amlogic/cec/hdmi_ao_cec.c | 5 ----- drivers/amlogic/cec/hdmi_ao_cec.h | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index bc1ad718c446..caa4269297ea 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -221,15 +221,10 @@ unsigned int waiting_aocec_free(unsigned int r) { unsigned int cnt = 0; int ret = true; - char *s; while (readl(cec_dev->cec_reg + r) & (1<<23)) { if (cnt++ >= 3500) { pr_info("waiting aocec %x free time out %d\n", r, cnt); - s = kmalloc(2048, GFP_KERNEL); - dump_cecrx_reg(s); - CEC_ERR("%s\n", s); - kfree(s); if (cec_dev->proble_finish) cec_hw_reset(CEC_A); ret = false; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 33b0acf1d776..e76e6484ef5a 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,7 +19,7 @@ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2019/3/23\n" +#define CEC_DRIVER_VERSION "Ver 2019/3/25\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" From aa69b47f4d4227940edeb12e07d05a591eeed6a8 Mon Sep 17 00:00:00 2001 From: Luan Yuan Date: Thu, 4 Apr 2019 10:53:25 +0800 Subject: [PATCH 0148/1060] dts: disabled pcie [1/1] PD#SWPL-6662 Problem: bootup spend 25s Solution: disable pcie and enable usb 3.0 Verify: verify by w400 Change-Id: I5ea3526989b4d89cffb4e875487e2b80b5d15f0b Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 4 ++-- arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 9dea114c0ad6..f204efb5ee3c 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -1308,7 +1308,7 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <1>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; @@ -1334,7 +1334,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "okay"; + status = "disable"; }; &saradc { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index ba7f622976a3..e2b300c26bc7 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -1288,7 +1288,7 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <1>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; @@ -1314,7 +1314,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "okay"; + status = "disable"; }; &saradc { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 4e7c5eb3bba7..fd971a1c5220 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -1307,7 +1307,7 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <1>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; @@ -1333,7 +1333,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "okay"; + status = "disable"; }; &saradc { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index 10f29ecba703..587c20e49656 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -1287,7 +1287,7 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <1>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; @@ -1313,7 +1313,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "okay"; + status = "disable"; }; &saradc { From 0c0649823751c0893af3acace1677a3a47d28325 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Thu, 14 Mar 2019 22:22:01 +0800 Subject: [PATCH 0149/1060] amvecm: fix g12a/g12b sharpness0 addr wrong [2/2] PD#SWPL-5919 Problem: add offset for g12a/g12b sharpness0 Solution: db offset for g12a/g12b sharpness0 Verify: u212 Change-Id: I9d800d7c8b4446cb19dc39777bc1f940b0d6124c Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 027c4d0ca4da..1793885cfbd6 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5410,6 +5410,24 @@ static ssize_t amvecm_lc_store(struct class *cls, /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ void init_pq_setting(void) { + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu() || is_meson_txhd_cpu() || + is_meson_tl1_cpu()) + goto tvchip_pq_setting; + else if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + sr_offset[0] = SR0_OFFSET; + /*dnlp off*/ + WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL, 0, + DNLP_EN_BIT, DNLP_EN_WID); + /*sr0 chroma filter bypass*/ + WRITE_VPP_REG(SRSHARP0_SHARP_SR2_CBIC_HCOEF0 + sr_offset[0], + 0x4000); + WRITE_VPP_REG(SRSHARP0_SHARP_SR2_CBIC_VCOEF0 + sr_offset[0], + 0x4000); + } + return; + +tvchip_pq_setting: if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { /*sr0 & sr1 register shfit*/ sr_offset[0] = SR0_OFFSET; @@ -5812,11 +5830,7 @@ static int aml_vecm_probe(struct platform_device *pdev) /* register vout client */ vout_register_client(&vlock_notifier_nb); - /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ - if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || - is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_tl1_cpu()) - init_pq_setting(); + init_pq_setting(); /* #endif */ vpp_get_hist_en(); From 12f4f0d3e23cdd700cbabe4cad87aaf4315614c7 Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Fri, 15 Mar 2019 17:37:04 +0800 Subject: [PATCH 0150/1060] di: TL1 Scrolling subtiltes jitter seriously than p321 [1/1] PD#SWPL-3877 Problem: mcinfo canvas configuration is incorrect Solution: correct canvas config Verify: verified by t962x2_x301 Change-Id: I93958044faed25994d83a53948e226729357d2aa Signed-off-by: zhiwei.yuan Signed-off-by: Luan Yuan --- drivers/amlogic/media/deinterlace/deinterlace.c | 9 +++++++-- .../amlogic/media/deinterlace/deinterlace_hw.c | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 71a043f75a9a..a5ff16b76958 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-02-26a sm1 buring up test"; +static const char version_s[] = "2019-03-18a"; static int bypass_state = 1; static int bypass_all; @@ -2100,7 +2100,8 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) mtn_size = (mtn_width * canvas_height)*4/16; count_size = (mtn_width * canvas_height)*4/16; mv_size = (mv_width * canvas_height)/5; - mc_size = canvas_height; + mc_size = roundup(canvas_height >> 1, canvas_align_width) << 1; + if (mc_mem_alloc) { di_buf_size = nr_size + mtn_size + count_size + mv_size + mc_size; @@ -2153,6 +2154,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) di_buf->canvas_width[NR_CANVAS] = nr_canvas_width; di_buf->canvas_width[MTN_CANVAS] = mtn_canvas_width; di_buf->canvas_width[MV_CANVAS] = mv_canvas_width; + if (prog_flag) { di_buf->canvas_height = canvas_height; di_buf->nr_adr = de_devp->mem_start + @@ -2160,6 +2162,9 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) di_buf->canvas_config_flag = 1; } else { di_buf->canvas_height = (canvas_height>>1); + di_buf->canvas_height = + roundup(di_buf->canvas_height, + canvas_align_width); di_buf->nr_adr = de_devp->mem_start + di_buf_size * i; di_buf->mtn_adr = de_devp->mem_start + diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index fc9c0dac6a4c..c27780b7cc50 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -330,6 +330,11 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, if (!lmv_lock_win_en) return; + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + pr_debug("%s: only support G12A and after chips.\n", __func__); + return; + } + tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); if (tmp == NULL) { di_print("err:di_vmap failed\n"); @@ -340,11 +345,12 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, for (i = 0; i < (vf_height>>1); i++) { lmvs_init(&lines_mv[i], *(mcinfo_vadr+i)); j = i + (vf_height>>1); - lmvs_init(&lines_mv[j], *(mcinfo_vadr+i+272)); + /*288 = (canvas height(1088)/2 align to 64)*/ + lmvs_init(&lines_mv[j], *(mcinfo_vadr+i+288)); if (pr_mcinfo_cnt && j < (vf_height - 10) && j > (vf_height - offset_lmv)) { pr_info("MCINFO[%u]=0x%x\t", j, - *(mcinfo_vadr + i + 272)); + *(mcinfo_vadr + i + 288)); if (i%16 == 0) pr_info("\n"); } @@ -488,6 +494,10 @@ void di_hw_init(bool pd_enable, bool mc_enable) fifo_size_di = 0x120; } + /*enable lock win, suggestion from vlsi zheng.bao*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + lmv_lock_win_en = 1; + DI_Wr(VD1_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); DI_Wr(VD2_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); /* 1a83 is vd2_if0_luma_fifo_size */ @@ -1275,7 +1285,7 @@ void enable_mc_di_pre_g12(struct DI_MC_MIF_s *mcinford_mif, RDMA_WR_BITS(MCINFRD_SCOPE_X, mcinford_mif->size_x, 16, 13); RDMA_WR_BITS(MCINFRD_SCOPE_Y, mcinford_mif->size_y, 16, 13); - RDMA_WR_BITS(MCINFRD_CTRL1, mcvecwr_mif->canvas_num, 16, 8); + RDMA_WR_BITS(MCINFRD_CTRL1, mcinford_mif->canvas_num, 16, 8); RDMA_WR_BITS(MCINFRD_CTRL1, 2, 0, 3); RDMA_WR_BITS(MCVECWR_X, mcvecwr_mif->size_x, 0, 13); From ca503084f31ea4d87c04bd9366e9aeb0ddbaa7ac Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Wed, 20 Mar 2019 15:07:21 +0800 Subject: [PATCH 0151/1060] di: enable lock win will cause green screen [1/1] PD#SWPL-3877 Problem: lock window cause green screen Solution: disable lock win as default Verify: verified by t962x2_x301 Change-Id: I59f3047b9fdd7e4b6ad4750740ddca58bfe8d79a Signed-off-by: zhiwei.yuan --- drivers/amlogic/media/deinterlace/deinterlace_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index c27780b7cc50..3918d70e8680 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -496,7 +496,7 @@ void di_hw_init(bool pd_enable, bool mc_enable) /*enable lock win, suggestion from vlsi zheng.bao*/ if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) - lmv_lock_win_en = 1; + lmv_lock_win_en = 0; DI_Wr(VD1_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); DI_Wr(VD2_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); From f85bff86e2c0a3b06a755b3e4168baece90867e3 Mon Sep 17 00:00:00 2001 From: Jihong Sui Date: Wed, 12 Dec 2018 17:02:09 +0800 Subject: [PATCH 0152/1060] deinterlace: pq: add scene change detection for tl1 [1/1] PD#TV-1361 Problem: Add scene change detection for DM (read part), start from TL1 by VLSI(Zheng.Bao). Solution: 1. add control in function noise_meter_process; 2. add debug information: cat /sys/class/deinterlace/di0/nr4_param 3. set NR2_CUE_MODE[11:10] as 3; (by feijun) Verify: tl1 Change-Id: Ib34d1b403539ba5fe5135d6608bfa2cf27490826 Signed-off-by: Jihong Sui --- .../amlogic/media/deinterlace/deinterlace.c | 1 + drivers/amlogic/media/deinterlace/nr_drv.c | 72 +++++++++++++++++-- drivers/amlogic/media/deinterlace/nr_drv.h | 15 +++- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index a5ff16b76958..3584e544f01a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -6222,6 +6222,7 @@ static void di_reg_process_irq(void) vframe->sig_fmt); di_patch_post_update_mc_sw(DI_MC_SW_REG, true); + cue_int(); if (de_devp->flags & DI_LOAD_REG_FLAG) up(&di_sema); init_flag = 1; diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index 55483bc4a99b..d40177e6b919 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -509,6 +509,18 @@ static void noise_meter_process(struct NR4_PARM_s *nr4_param_p, } else val1 = 64; DI_Wr_reg_bits(NR4_MCNR_MV_CTRL_REG, val1, 4, 8); + /*add for TL1------*/ + if (nr4_param_p->sw_nr4_noise_ctrl_dm_en == 1) { + if (nr4_param_p->sw_nr4_noise_sel == 0) { + val2 = val1 >= nr4_param_p->sw_nr4_noise_thd ? 1 : 0; + } else { + val2 = + field_sad >= nr4_param_p->sw_nr4_noise_thd ? 1 : 0; + } + + DI_Wr_reg_bits(DNR_DM_NR_BLND, val2, 24, 1); + } + /*------------------*/ /* scene change processing */ nr4_param_p->sw_nr4_scene_change_flg[0] = nr4_param_p->sw_nr4_scene_change_flg[1]; @@ -529,6 +541,16 @@ static void noise_meter_process(struct NR4_PARM_s *nr4_param_p, DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 0, 1); else DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 0, 1); + + /*fot TL1 **************/ + if (nr4_param_p->sw_dm_scene_change_en == 1) { + val = field_sad >= nr4_param_p->sw_nr4_scene_change_thd2 + && nr4_param_p->sw_nr4_field_sad[1] + >= nr4_param_p->sw_nr4_scene_change_thd2; + + DI_Wr_reg_bits(DNR_DM_CTRL, val, 12, 1); + } + /***********************/ nr4_param_p->sw_nr4_field_sad[0] = nr4_param_p->sw_nr4_field_sad[1]; nr4_param_p->sw_nr4_field_sad[1] = field_sad; } @@ -572,15 +594,24 @@ static void dnr_process(struct DNR_PARM_s *pDnrPrm) #ifdef DNR_HV_SHIFT int ro_hbof_stat_cnt[32], ro_vbof_stat_cnt[32], i = 0; #endif + int ll, lr; - if (ro_gbs_stat_lr != Rd(DNR_RO_GBS_STAT_LR) || - ro_gbs_stat_ll != Rd(DNR_RO_GBS_STAT_LL) || + if (is_meson_tl1_cpu()) { + ll = Rd(DNR_RO_GBS_STAT_LR); + lr = Rd(DNR_RO_GBS_STAT_LL); + } else { + ll = Rd(DNR_RO_GBS_STAT_LL); + lr = Rd(DNR_RO_GBS_STAT_LR); + + } + if (ro_gbs_stat_lr != lr || + ro_gbs_stat_ll != ll || ro_gbs_stat_rr != Rd(DNR_RO_GBS_STAT_RR) || ro_gbs_stat_dif != Rd(DNR_RO_GBS_STAT_DIF) || ro_gbs_stat_cnt != Rd(DNR_RO_GBS_STAT_CNT)) { - ro_gbs_stat_lr = Rd(DNR_RO_GBS_STAT_LR); - ro_gbs_stat_ll = Rd(DNR_RO_GBS_STAT_LL); + ro_gbs_stat_lr = lr; + ro_gbs_stat_ll = ll; ro_gbs_stat_rr = Rd(DNR_RO_GBS_STAT_RR); ro_gbs_stat_dif = Rd(DNR_RO_GBS_STAT_DIF); ro_gbs_stat_cnt = Rd(DNR_RO_GBS_STAT_CNT); @@ -693,7 +724,13 @@ static void cue_process_irq(void) if (nr_param.frame_count == 5) Wr_reg_bits(NR2_CUE_MODE, 7, 0, 4); } - +void cue_int(void) +{ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (cue_en) + Wr_reg_bits(NR2_CUE_MODE, 3, 10, 2); + } +} static bool glb_fieldck_en = true; module_param_named(glb_fieldck_en, glb_fieldck_en, bool, 0644); @@ -932,6 +969,17 @@ static void nr4_params_init(struct NR4_PARM_s *nr4_parm_p) nr4_params[24].name = "nr4_debug"; nr4_params[24].addr = &(nr4_parm_p->nr4_debug); + nr4_params[25].name = "sw_nr4_noise_thd"; + nr4_params[25].addr = &(nr4_parm_p->sw_nr4_noise_thd); + nr4_params[26].name = "sw_nr4_noise_sel"; + nr4_params[26].addr = &(nr4_parm_p->sw_nr4_noise_sel); + nr4_params[27].name = "sw_nr4_noise_ctrl_dm_en"; + nr4_params[27].addr = &(nr4_parm_p->sw_nr4_noise_ctrl_dm_en); + nr4_params[28].name = "sw_nr4_scene_change_thd2"; + nr4_params[28].addr = &(nr4_parm_p->sw_nr4_scene_change_thd2); + nr4_params[29].name = "sw_dm_scene_change_en"; + nr4_params[29].addr = &(nr4_parm_p->sw_dm_scene_change_en); + }; static ssize_t nr4_param_store(struct device *dev, @@ -1010,6 +1058,20 @@ static void nr4_param_init(struct NR4_PARM_s *nr4_parm_p) nr4_parm_p->sw_nr4_sad2gain_lut[13] = 16; nr4_parm_p->sw_nr4_sad2gain_lut[14] = 14; nr4_parm_p->sw_nr4_sad2gain_lut[15] = 9; + + if (is_meson_tl1_cpu()) { + nr4_parm_p->sw_nr4_noise_thd = 32; + nr4_parm_p->sw_nr4_noise_sel = 0; + nr4_parm_p->sw_nr4_noise_ctrl_dm_en = 0; + nr4_parm_p->sw_nr4_scene_change_thd2 = 80; + nr4_parm_p->sw_dm_scene_change_en = 0; + } else { + nr4_parm_p->sw_nr4_noise_thd = 32; + nr4_parm_p->sw_nr4_noise_sel = 0; + nr4_parm_p->sw_nr4_noise_ctrl_dm_en = 0; + nr4_parm_p->sw_nr4_scene_change_thd2 = 80; + nr4_parm_p->sw_dm_scene_change_en = 0; + } } static void cue_param_init(struct CUE_PARM_s *cue_parm_p) diff --git a/drivers/amlogic/media/deinterlace/nr_drv.h b/drivers/amlogic/media/deinterlace/nr_drv.h index 0ec80d606847..0d0c714e22e0 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.h +++ b/drivers/amlogic/media/deinterlace/nr_drv.h @@ -24,7 +24,7 @@ struct nr_param_s { int *addr; }; -#define NR4_PARAMS_NUM 25 +#define NR4_PARAMS_NUM (30) //25 #define dnr_param_t struct nr_param_s #define nr4_param_t struct nr_param_s @@ -68,6 +68,16 @@ struct NR4_PARM_s { unsigned short width; unsigned short height; unsigned short border_offset; + + unsigned int sw_nr4_noise_thd;//u8 + /*u1, 0: use nr4 global gain, 1: use field sad;*/ + unsigned int sw_nr4_noise_sel; + unsigned int sw_nr4_noise_ctrl_dm_en;//u1 + + /*u8, threshold for scene change*/ + unsigned int sw_nr4_scene_change_thd2; + /*u1, enable dm scene change check*/ + unsigned int sw_dm_scene_change_en; }; struct CUE_PARM_s { @@ -170,5 +180,8 @@ void nr_process_in_irq(void); void nr_all_config(unsigned short nCol, unsigned short nRow, unsigned short type); bool set_nr_ctrl_reg_table(unsigned int addr, unsigned int value); + +extern void cue_int(void); + #endif From 4c29830e9cc9ecd5dc10ca36ccac289f3628a39b Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Wed, 20 Mar 2019 16:44:37 +0800 Subject: [PATCH 0153/1060] di: disable cue for g12a [1/2] PD#SWPL-6142 Problem: disable cue for g12a Solution: disable cue for g12a Verify: U212 Change-Id: I276fa0b8605110b709feaceb6d23d9b566c16a44 Signed-off-by: Bencheng Jing --- drivers/amlogic/media/deinterlace/nr_drv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index d40177e6b919..509117bbbb6b 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -726,7 +726,12 @@ static void cue_process_irq(void) } void cue_int(void) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + /*confirm with vlsi-liuyanling, G12a cue must be disabled*/ + if (is_meson_g12a_cpu()) { + cue_en = false; + cue_glb_mot_check_en = false; + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { if (cue_en) Wr_reg_bits(NR2_CUE_MODE, 3, 10, 2); } From 5d49711c983faece171a80165f96a734fd1492f7 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Mon, 28 Jan 2019 01:36:14 -0500 Subject: [PATCH 0154/1060] hdr: modify hdr gamut mtx for TV [1/1] PD#SWPL-4638 Problem: hdr video, color is light Solution: modify hdr gamut mtx, use bt2020rgb to 709rgb mtx Verify: verified on x301 Change-Id: Ia87493a57196b6a3a87c93535fed325b163cb562 Signed-off-by: MingLiang Dong --- .../media/enhancement/amvecm/set_hdr2_v0.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index 91f51f113f9f..cbaf7f3d1347 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -707,14 +707,14 @@ MODULE_PARM_DESC(hdr2_debug, "\n hdr2_debug\n"); /* gamut 3x3 matrix*/ /*standard 2020rgb->709rgb*/ -/*int ncl_2020_709[9] = {*/ - /*3401, -1204, -149, -255, 2320, -17, -37, -206, 2291};*/ +int ncl_2020_709[9] = { + 3401, -1204, -149, -255, 2320, -17, -37, -206, 2291}; /* dci-p3->709rgb*/ /*int ncl_2020_709[9] = {*/ /*2543, -459, -36, -88, 2133, 3, -41, -161, 2250};*/ /* special primary->709rgb*/ -int ncl_2020_709[9] = { +int ncl_sp_709[9] = { 2684, -489, -147, -201, 2266, -17, -29, -171, 2248}; /*int cl_2020_709[9] =*/ @@ -1970,8 +1970,15 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_mtx_param.mtx_cgain[i] = rgb2ycbcr_709[i]; hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i]; hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i]; - if (i < 9) - hdr_mtx_param.mtx_gamut[i] = ncl_2020_709[i]; + if (i < 9) { + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu()) + hdr_mtx_param.mtx_gamut[i] = + ncl_sp_709[i]; + else + hdr_mtx_param.mtx_gamut[i] = + ncl_2020_709[i]; + } } hdr_mtx_param.mtx_on = MTX_ON; From bf3e51e8da858eccb8fcdbb515c162cc127a965d Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Tue, 26 Mar 2019 08:38:56 -0400 Subject: [PATCH 0155/1060] hdr: TL1 HDR gamut bug fix [1/1] PD#SWPL-5248 Problem: 1. finetune TL1 HDR. 2. workaround fix ootf overwrite 3. workaround fix gamut bug Solution: TL1 HDR gamut bug fix Verify: verify on TL1 Change-Id: Iaf9535f3b6d096967f67ba118ff54eeb2c5c01c5 Signed-off-by: MingLiang Dong --- .../media/enhancement/amvecm/set_hdr2_v0.c | 149 ++++++++++++------ 1 file changed, 97 insertions(+), 52 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index cbaf7f3d1347..f28f66561c79 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -93,22 +93,24 @@ int cgain_lut2[65] = { static int num_eo_y_lut_hdr = 143; int eo_y_lut_hdr[143] = { - 132288, 136832, 165440, 181832, 193440, 202088, 210400, 216476, 221882, - 227920, 231986, 235648, 239639, 243964, 247193, 249698, 252377, 271330, - 285261, 297148, 306377, 314682, 321922, 329204, 334486, 340750, 346085, - 350369, 355325, 360734, 363991, 367697, 371896, 376636, 379400, 382389, - 385731, 389458, 393410, 395711, 398260, 401078, 404188, 407615, 410492, - 412562, 414834, 417322, 420045, 423021, 426127, 427900, 429831, 431934, - 434222, 436709, 439410, 442342, 443945, 445668, 447230, 448187, 449224, - 450344, 451555, 452864, 454277, 455803, 457449, 458988, 459945, 460977, - 462089, 463286, 464576, 465964, 467458, 469066, 470795, 472655, 474655, - 475971, 477126, 478368, 479702, 481136, 482676, 484330, 486107, 488015, - 490063, 491891, 493071, 494339, 495699, 497159, 498727, 500409, 502262, - 504308, 506503, 508381, 509646, 511003, 512460, 512934, 513098, 513279, - 513477, 513691, 513923, 514172, 514438, 514720, 515017, 515328, 515650, - 515981, 516320, 516662, 517006, 517349, 517689, 518022, 518347, 518662, - 518968, 519263, 519549, 519827, 520097, 520363, 520625, 520888, 521155, - 521431, 521727, 522054, 522431, 522871, 523371, 523881, 524287 + 1032192, 1032192, 1032192, 1032192, 16384, 16384, 16384, 16384, + 32768, 32768, 32768, 32768, 40960, 40960, 40960, 49152, 49152, + 73728, 86016, 94208, 100352, 104448, 108544, 112640, 117760, 123904, + 128000, 133632, 137728, 141824, 146944, 150272, 153344, 157440, + 161536, 165248, 167808, 170880, 174208, 177792, 181056, 183360, + 185792, 188480, 191552, 194880, 197536, 199520, 201696, 204128, + 206688, 209568, 212640, 214480, 216336, 218320, 220464, 222832, + 225360, 228112, 230248, 231864, 233608, 235496, 237544, 239752, + 242136, 244712, 246628, 248132, 249748, 251492, 253364, 255388, + 257564, 259908, 262290, 263646, 265106, 266678, 268366, 270182, + 272134, 274230, 276486, 278717, 280017, 281415, 282915, 284525, + 286255, 288113, 290107, 292247, 294545, 295961, 297284, 298705, + 300229, 301866, 303622, 305507, 307530, 309701, 311664, 312915, + 314257, 315698, 317246, 318907, 320690, 322605, 324662, 326871, + 328461, 329735, 331104, 332575, 334155, 335853, 337679, 339642, + 341752, 344021, 345263, 346576, 347989, 349509, 351145, 352907, + 354805, 356848, 359050, 360935, 362214, 363593, 365080, 366684, + 368414, 370283, 372300, 374478, 376832 }; module_param_array(eo_y_lut_hdr, int, &num_eo_y_lut_hdr, 0664); MODULE_PARM_DESC(eo_y_lut_hdr, "\n eo_y_lut_hdr\n"); @@ -245,18 +247,19 @@ int oo_y_lut_hdr_hlg[149] = { static int num_hdr_sdr_lut = 149; int oo_y_lut_hdr_sdr[149] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255 + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2810, + 2635, 2481, 2225, 2020, 1852, 1712, 1593, 1491, 1403, 1325, 1196, + 1092, 1006, 935, 874, 822, 776, 736, 668, 614, 568, 530, 497, 468, + 442, 419, 381, 349, 322, 299, 279, 261, 246, 233, 221, 210, 201, + 192, 184, 177, 170, 164, 158, 153, 148, 143, 139, 135, 131, 128 }; module_param_array(oo_y_lut_hdr_sdr, int, &num_hdr_sdr_lut, 0664); MODULE_PARM_DESC(oo_y_lut_hdr_sdr, "\n num_hdr_sdr_lut\n"); @@ -713,7 +716,11 @@ int ncl_2020_709[9] = { /*int ncl_2020_709[9] = {*/ /*2543, -459, -36, -88, 2133, 3, -41, -161, 2250};*/ -/* special primary->709rgb*/ +/* standard2020->dcip3-d65 8bit*/ +int ncl_2020_p3[9] = { + 368, -96, -16, -16, 275, -3, 1, -8, 263}; + +/*for iptv special primary->709rgb*/ int ncl_sp_709[9] = { 2684, -489, -147, -201, 2266, -17, -29, -171, 2248}; @@ -757,6 +764,16 @@ static int bypass_coeff[15] = { 0, 0, 0, }; +unsigned int _log2(unsigned int value) +{ + unsigned int ret; + + for (ret = 0; value > 1; ret++) + value >>= 1; + + return ret; +} + /*in/out matrix*/ void set_hdr_matrix( enum hdr_module_sel module_sel, @@ -1244,8 +1261,12 @@ void set_hdr_matrix( (hdr_mtx_param->p_sel & HDR_BYPASS) && (module_sel & OSD1_HDR)) gmut_shift = 10; + else if (hdr_mtx_param->p_sel & HDR_SDR) + /*work around for gamut bug*/ + gmut_shift = 0;/*11*/ else - gmut_shift = 11; + /*default 11, set 12 avoid gamut overwrite*/ + gmut_shift = 12; for (i = 0; i < 3; i++) c_gain_lim_coef[i] = @@ -1280,26 +1301,29 @@ void set_hdr_matrix( adpscl_alpha[i] = 10 * in_luma * (1 << adp_scal_shift) / out_luma; - if (hdr_mtx_param->p_sel & HDR_SDR) { - if (i == 0) - adpscl_shift[i] = adp_scal_shift; - else - adpscl_shift[i] = adp_scal_shift - 2; - } else - adpscl_shift[i] = adp_scal_shift; - adpscl_ys_coef[i] = 1 << adp_scal_shift; adpscl_beta_s[i] = 0; adpscl_beta[i] = 0; } + /*shift0 is for x coordinate*/ + adpscl_shift[0] = adp_scal_shift; + /*shift1 is for scale multiple*/ + if (hdr_mtx_param->p_sel & HDR_SDR) + adpscl_shift[1] = adp_scal_shift - + _log2((1 << adp_scal_shift) / oo_y_lut_hdr_sdr[148]); + else + adpscl_shift[1] = adp_scal_shift - 1; + /*shift2 is not used, set default*/ + adpscl_shift[2] = adp_scal_shift; + /*gamut mode: 1->gamut before ootf*/ /*2->gamut after ootf*/ /*other->disable gamut*/ if ((is_meson_g12b_cpu() && is_meson_rev_b()) && (module_sel & OSD1_HDR)) { - _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 2, 6, 2); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 6, 2); _VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); _VSYNC_WR_MPEG_REG(GMUT_COEF0, @@ -1320,8 +1344,8 @@ void set_hdr_matrix( _VSYNC_WR_MPEG_REG(CGAIN_COEF0, c_gain_lim_coef[1] << 16 | c_gain_lim_coef[0]); - _VSYNC_WR_MPEG_REG(CGAIN_COEF1, c_gain_lim_coef[2] | - 0x400 << 16); + _VSYNC_WR_MPEG_REG_BITS(CGAIN_COEF1, + c_gain_lim_coef[2], 0, 12); _VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 | @@ -1349,7 +1373,7 @@ void set_hdr_matrix( return; } - VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 2, 6, 2); + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 6, 2); VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); VSYNC_WR_MPEG_REG(GMUT_COEF0, @@ -1370,8 +1394,8 @@ void set_hdr_matrix( VSYNC_WR_MPEG_REG(CGAIN_COEF0, c_gain_lim_coef[1] << 16 | c_gain_lim_coef[0]); - VSYNC_WR_MPEG_REG(CGAIN_COEF1, c_gain_lim_coef[2] | - 0x400 << 16); + VSYNC_WR_MPEG_REG_BITS(CGAIN_COEF1, c_gain_lim_coef[2], + 0, 12); VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 | adpscl_enable[1] << 5 | @@ -1657,7 +1681,10 @@ void set_oetf_lut( (lut[i * 2 + 1] << 16) + lut[i * 2]); } - _VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + if (hdr_lut_param->bitdepth == 10) + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148] >> 2); + else + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); return; } @@ -1678,7 +1705,11 @@ void set_oetf_lut( (lut[i * 2 + 1] << 16) + lut[i * 2]); } - VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + if (hdr_lut_param->bitdepth == 10) + VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148] >> 2); + else + VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + } void set_c_gain( @@ -1689,32 +1720,39 @@ void set_c_gain( unsigned int cgain_lut_addr_port = 0; unsigned int cgain_lut_data_port = 0; unsigned int hdr_ctrl = 0; + unsigned int cgain_coef1 = 0; unsigned int i = 0; if (module_sel & VD1_HDR) { cgain_lut_addr_port = VD1_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VD1_CGAIN_LUT_DATA_PORT; hdr_ctrl = VD1_HDR2_CTRL; + cgain_coef1 = VD1_HDR2_CGAIN_COEF1; } else if (module_sel & VD2_HDR) { cgain_lut_addr_port = VD2_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VD2_CGAIN_LUT_DATA_PORT; hdr_ctrl = VD2_HDR2_CTRL; + cgain_coef1 = VD2_HDR2_CGAIN_COEF1; } else if (module_sel & OSD1_HDR) { cgain_lut_addr_port = OSD1_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = OSD1_CGAIN_LUT_DATA_PORT; hdr_ctrl = OSD1_HDR2_CTRL; + cgain_coef1 = OSD1_HDR2_CGAIN_COEF1; } else if (module_sel & DI_HDR) { cgain_lut_addr_port = DI_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = DI_CGAIN_LUT_DATA_PORT; hdr_ctrl = DI_HDR2_CTRL; + cgain_coef1 = DI_HDR2_CGAIN_COEF1; } else if (module_sel & VDIN0_HDR) { cgain_lut_addr_port = VDIN0_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VDIN0_CGAIN_LUT_DATA_PORT; hdr_ctrl = VDIN0_HDR2_CTRL; + cgain_coef1 = VDIN0_HDR2_CGAIN_COEF1; } else if (module_sel & VDIN1_HDR) { cgain_lut_addr_port = VDIN1_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VDIN1_CGAIN_LUT_DATA_PORT; hdr_ctrl = VDIN1_HDR2_CTRL; + cgain_coef1 = VDIN1_HDR2_CGAIN_COEF1; } for (i = 0; i < HDR2_CGAIN_LUT_SIZE; i++) @@ -1740,9 +1778,17 @@ void set_c_gain( return; } - VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 12, 1); + /*cgain mode force 0*/ + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 12, 1); VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 0, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (hdr_lut_param->bitdepth == 10) + VSYNC_WR_MPEG_REG_BITS(cgain_coef1, 0x400, 16, 13); + else if (hdr_lut_param->bitdepth == 12) + VSYNC_WR_MPEG_REG_BITS(cgain_coef1, 0x1000, 16, 13); + } + if (!hdr_lut_param->cgain_en) return; @@ -1971,13 +2017,12 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i]; hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i]; if (i < 9) { - if (is_meson_g12a_cpu() || - is_meson_g12b_cpu()) - hdr_mtx_param.mtx_gamut[i] = - ncl_sp_709[i]; - else + if (hdr_process_select & HLG_SDR) hdr_mtx_param.mtx_gamut[i] = ncl_2020_709[i]; + else + hdr_mtx_param.mtx_gamut[i] = + ncl_2020_p3[i]; } } hdr_mtx_param.mtx_on = MTX_ON; From 63559b4984ed63974502854af9c0d0afcd1f23c0 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Mon, 25 Mar 2019 19:19:26 +0800 Subject: [PATCH 0156/1060] hdmitx: fix flash screen when resuming and playing hdr [1/1] PD#SWPL-6169 Problem: when resuming and playing hdr films, flash screen will happen under LG TV Solution: quantization range has changed between UI and playing hdr films. we keep quantization unchanged. Same as MTK. Verify: s905x2 Change-Id: I071abecfba705dbd44d33c2673d4938c39f419cf Signed-off-by: Yi Zhou --- drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index bf12bc25ac11..cdaddc2f1e52 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -1370,9 +1370,6 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data) hdev->hdmi_current_hdr_mode = 3; } - hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, - RGB_RANGE_LIM); - switch (hdev->hdmi_current_hdr_mode) { case 1: /*standard HDR*/ From 570936bd63dd9d79dfe08f083bca6c5d72e18e83 Mon Sep 17 00:00:00 2001 From: "he.he" Date: Tue, 12 Mar 2019 12:52:14 +0800 Subject: [PATCH 0157/1060] USB: amldevread data failed [1/1] PD#SWPL-5292 Problem: g12b-revB, some u disk amldevread test failed. Solution: Changing the register 0x54 to 0x2a, enabled the hs rx idle noise filter, and the abnormal u-disk has no problem in the amldevread test. Verify: g12b revB Change-Id: Ibbf924c93d193d7e40c4d8121a4616a8d1caeaaa Signed-off-by: he.he --- drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index a3e13407de97..6aaf4f997bd8 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -106,6 +106,7 @@ void set_usb_pll(struct amlogic_usb_v2 *phy, void __iomem *reg) if (g_phy2_v2->phy_version == 2) { /**g12b revB don't need set 0x10 ,0x38 and 0x34**/ writel(phy->pll_setting[3], reg + 0x50); + writel(0x2a, reg + 0x54); writel(0x70000, reg + 0x34); } else { writel(phy->pll_setting[3], reg + 0x50); From 9ade8dd69a169ade11f448f4f5712dbb59cf7d08 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Thu, 3 Jan 2019 17:32:28 +0800 Subject: [PATCH 0158/1060] cec: remove print [1/1] PD#SWPL-3750 Problem: when debug on, too more log Solution: delete Verify: verified on android p Change-Id: Iabaaa4fa205da5453a303c98bce8b71b55c5f77b Signed-off-by: Yong Qin --- drivers/amlogic/cec/hdmi_ao_cec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index caa4269297ea..47173ef4d74b 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -2912,7 +2912,7 @@ static long hdmitx_cec_ioctl(struct file *f, if (((cec_dev->port_seq >> i*4) & 0xF) == a) break; } - CEC_INFO("phy port:%d, ui port:%d\n", i, a); + CEC_INFO_L(L_2, "phy port:%d, ui port:%d\n", i, a); if ((tmp & (1 << i)) && (a != 0xF)) tmp = 1; From 380dd74006598be3ed17d68bb12917309a6ef1c8 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Mon, 8 Apr 2019 16:05:48 +0800 Subject: [PATCH 0159/1060] audio: codec: un-mute ad82584 in default [1/1] PD#SWPL-6810 Problem: android version, no sound for spk ad82584 is mute in default. Solution: un-mute ad82584, and add delay for de-pop Verify: ac200 Change-Id: Id78eb77b5e1a0ebed0a16a9b97992c6a07f78cde Signed-off-by: Xing Wang Signed-off-by: Jian Xu --- sound/soc/codecs/amlogic/ad82584f.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index 8e68ad5393e2..c66a18b62512 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -824,11 +824,14 @@ static int ad82584f_init(struct snd_soc_codec *codec) 0x1 << 0 /* 64x bclk/fs */ ); - /*eq and drc*/ + /* eq and drc */ ad82584f_set_eq_drc(codec); - /*unmute,default power-on is mute.*/ - /*snd_soc_write(codec, 0x02, 0x00);*/ + /* for de-pop */ + udelay(100); + + /* unmute, default power-on is mute. */ + snd_soc_write(codec, 0x02, 0x00); return 0; } From 85ff65b99f78215ebb963ddd257f64015aed7d78 Mon Sep 17 00:00:00 2001 From: long yu Date: Mon, 14 Jan 2019 11:23:47 +0800 Subject: [PATCH 0160/1060] storage: emmc: Adjust the tuning mode of controller for HS200 [1/1] PD#SWPL-2634 Problem: eyetest mode is a little unstable Solution: adjust the tuning mode of the fixed adj Verify: R311 Change-Id: I6112e0078bf013d2a4cfe4ff04210f1d15e3439d Signed-off-by: long yu --- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 42 +++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 730b5d8908ea..888e2c4272c7 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -1152,6 +1152,7 @@ static int _aml_sd_emmc_execute_tuning(struct mmc_host *mmc, u32 opcode, int best_win_start, best_win_size; int curr_win_start, curr_win_size; u32 old_dly, d1_dly, dly; + struct para_e *para = &(host->data->sdmmc); if ((host->mem->start == host->data->port_b_base) && host->data->tdma_f) @@ -1180,6 +1181,26 @@ tunning: host->is_tunning = 1; pr_info("%s: clk %d tuning start\n", mmc_hostname(mmc), mmc->actual_clock); + + /*retry adj[clk_div-1] tuning result*/ + if ((clk_div == 5) && (aml_card_type_mmc(pdata))) { + gadjust->adj_delay = clk_div-1; + gadjust->adj_enable = 1; + gadjust->cali_enable = 0; + gadjust->cali_rise = 0; + writel(adjust, host->base + SD_EMMC_ADJUST_V3); + nmatch = aml_sd_emmc_tuning_transfer(mmc, opcode, + blk_pattern, host->blk_test, blksz); + if (nmatch != TUNING_NUM_PER_POINT) { + clkc->core_phase = para->hs2.tx_phase; + clkc->tx_phase = para->hs2.core_phase; + writel(vclk, host->base + SD_EMMC_CLOCK_V3); + pr_info("%s:try clock:0x%x>>>rx_tuning[%d] = %d\n", + mmc_hostname(host->mmc), + readl(host->base + SD_EMMC_CLOCK_V3), + gadjust->adj_delay, nmatch); + } + } for (adj_delay = 0; adj_delay < clk_div; adj_delay++) { gadjust->adj_delay = adj_delay; gadjust->adj_enable = 1; @@ -1359,7 +1380,7 @@ RETRY: return 0; } -int aml_emmc_hs200_timming(struct mmc_host *mmc) +int __attribute__((unused)) aml_emmc_hs200_timming(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); struct amlsd_host *host = pdata->host; @@ -1601,17 +1622,18 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) pdata->intf3 = intf3; aml_sd_emmc_clktest(mmc); err = aml_sdio_timing(mmc, opcode, - &tuning_data, adj_win_start); + &tuning_data, adj_win_start); } } else if (!(pdata->caps2 & MMC_CAP2_HS400)) { - if (mmc->actual_clock >= 200000000) { - intf3 = readl(host->base + SD_EMMC_INTF3); - intf3 |= (1<<22); - writel(intf3, (host->base + SD_EMMC_INTF3)); - pdata->intf3 = intf3; - err = aml_emmc_hs200_timming(mmc); - } else - err = _aml_sd_emmc_execute_tuning(mmc, opcode, + /*if (mmc->actual_clock >= 200000000) { + * intf3 = readl(host->base + SD_EMMC_INTF3); + * intf3 |= (1<<22); + * writel(intf3, (host->base + SD_EMMC_INTF3)); + * pdata->intf3 = intf3; + * err = aml_emmc_hs200_timming(mmc); + *} else + */ + err = _aml_sd_emmc_execute_tuning(mmc, opcode, &tuning_data, adj_win_start); } else { intf3 = readl(host->base + SD_EMMC_INTF3); From 1d1a85fb9df09c8a2250903913e46cb8e78af3a7 Mon Sep 17 00:00:00 2001 From: "ruixuan.li" Date: Tue, 19 Mar 2019 16:54:38 +0800 Subject: [PATCH 0161/1060] sm1: disable emmc calc_f methods [1/1] PD#SWPL-5404 Problem: sm1 usb fixdiv mode set adjust cause error Solution: disable emmc calc_f in dtsi. Verify: test pass on sm1 ac200 Change-Id: I4459bf4faa2141a9e684b1e5bb95fb806eecbbfa Signed-off-by: ruixuan.li --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 1 - arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index d3578f68a00f..521ecc88c3fa 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1381,7 +1381,6 @@ /*caps defined in dts*/ tx_delay = <0>; co_phase = <3>; - calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 286e7913be93..7a5703927030 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1380,7 +1380,6 @@ /*caps defined in dts*/ tx_delay = <0>; co_phase = <3>; - calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; From 4cb6e1da6afd4ddc66c177a2420a0e479a7f5560 Mon Sep 17 00:00:00 2001 From: "ruixuan.li" Date: Wed, 20 Mar 2019 19:06:24 +0800 Subject: [PATCH 0162/1060] sm1: modify 400k co_phase [1/1] PD#SWPL-5404 Problem: emmc report response crc error in high speed mode Solution: modify 400k co_phas Verify: verify on ac200 Change-Id: I8bd0cbeb121e7a35a5f96791449187150e650d9e Signed-off-by: ruixuan.li --- drivers/amlogic/mmc/aml_sd_emmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 7c05f5d1f93b..3196af5a8088 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3604,7 +3604,7 @@ static struct meson_mmc_data mmc_data_g12b = { .ds_pin_poll = 0x3a, .ds_pin_poll_en = 0x48, .ds_pin_poll_bit = 13, - .sdmmc.init.core_phase = 3, + .sdmmc.init.core_phase = 2, .sdmmc.init.tx_phase = 0, .sdmmc.init.rx_phase = 0, .sdmmc.calc.core_phase = 0, From 9aaeff8b06ee4ac53b799d24c6e280e230cb02ba Mon Sep 17 00:00:00 2001 From: "ruixuan.li" Date: Thu, 21 Mar 2019 00:21:10 +0800 Subject: [PATCH 0163/1060] sm1: emmc run hs200 busmode [1/1] PD#SWPL-5404 Problem: emmc report data crc error in hs200 busmode Solution: set hs200 co_phase to 2 and did not reset the hs200 co_phase and tx_phase when adjust tuning is find the error point in sm1 Verify: verify pass on sm1_s905d3_ac200 Change-Id: I56aa8eb666fb55641db75878a3488f66c721bd6d Signed-off-by: ruixuan.li --- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 4 ++-- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 4 ++-- drivers/amlogic/mmc/aml_sd_emmc.c | 2 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 6 ++++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 2abe261bb09e..d67113558abf 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1444,10 +1444,10 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - /*caps2 = "MMC_CAP2_HS200";*/ + caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <50000000>; + f_max = <200000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index ef75f873c773..91af75774434 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1443,10 +1443,10 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - /*caps2 = "MMC_CAP2_HS200";*/ + caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <50000000>; + f_max = <200000000>; }; }; diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 3196af5a8088..ad3cbbd2d6e3 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3659,7 +3659,7 @@ static struct meson_mmc_data mmc_data_sm1 = { .sdmmc.hs.core_phase = 3, .sdmmc.ddr.core_phase = 2, .sdmmc.ddr.tx_phase = 0, - .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.core_phase = 2, .sdmmc.hs2.tx_phase = 0, .sdmmc.hs4.tx_delay = 0, .sdmmc.sd_hs.core_phase = 3, diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 888e2c4272c7..0f02a26407f3 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -1192,8 +1192,10 @@ tunning: nmatch = aml_sd_emmc_tuning_transfer(mmc, opcode, blk_pattern, host->blk_test, blksz); if (nmatch != TUNING_NUM_PER_POINT) { - clkc->core_phase = para->hs2.tx_phase; - clkc->tx_phase = para->hs2.core_phase; + if (host->data->chip_type != MMC_CHIP_SM1) { + clkc->core_phase = para->hs2.tx_phase; + clkc->tx_phase = para->hs2.core_phase; + } writel(vclk, host->base + SD_EMMC_CLOCK_V3); pr_info("%s:try clock:0x%x>>>rx_tuning[%d] = %d\n", mmc_hostname(host->mmc), From ceb8f34335627900107131c8a0267010473128ac Mon Sep 17 00:00:00 2001 From: "huijie.huang" Date: Thu, 28 Feb 2019 19:02:42 +0800 Subject: [PATCH 0164/1060] power: S905Y2 limit cpu and gpu freq to reduce HDMI TX consumption [1/1] PD#SWPL-4653 Problem: optimize the S905Y2 power consumption Solution: limit CPU and GPU frequency, reduce hdmi tx consumption Verify: test pass on u221 Change-Id: I1d95068f8beb5616c9aeea91122b5233e479db8b Signed-off-by: huijie.huang --- .../arm/boot/dts/amlogic/g12a_s905y2_u221.dts | 36 ++++++++++++------- .../boot/dts/amlogic/g12a_s905y2_u221.dts | 36 ++++++++++++------- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index caadd28dbe5d..074b6314c040 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -669,18 +669,20 @@ opp-hz = /bits/ 64 <1512000000>; opp-microvolt = <831000>; }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <871000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; +/* + * opp08 { + * opp-hz = /bits/ 64 <1608000000>; + * opp-microvolt = <871000>; + * }; + * opp09 { + * opp-hz = /bits/ 64 <1704000000>; + * opp-microvolt = <921000>; + * }; + * opp10 { + * opp-hz = /bits/ 64 <1800000000>; + * opp-microvolt = <981000>; + * }; + */ }; cpufreq-meson { @@ -1287,3 +1289,13 @@ status = "okay"; }; +&gpu{ + /*max gpu is 500MHz*/ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg>; +}; + +&amhdmitx { + dongle_mode = <1>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts index cec20dd0bf39..dd44a31e10aa 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -667,18 +667,20 @@ opp-hz = /bits/ 64 <1512000000>; opp-microvolt = <831000>; }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <871000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; +/* + * opp08 { + * opp-hz = /bits/ 64 <1608000000>; + * opp-microvolt = <871000>; + * }; + * opp09 { + * opp-hz = /bits/ 64 <1704000000>; + * opp-microvolt = <921000>; + * }; + * opp10 { + * opp-hz = /bits/ 64 <1800000000>; + * opp-microvolt = <981000>; + * }; + */ }; cpufreq-meson { @@ -1285,3 +1287,13 @@ status = "okay"; }; +&gpu{ + /*max gpu is 500MHz*/ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg>; +}; + +&amhdmitx { + dongle_mode = <1>; +}; From aa4640922aaa6ce64747fe33101613481bfabf61 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Fri, 22 Mar 2019 10:40:43 +0800 Subject: [PATCH 0165/1060] emmc: modify data delay_step [1/1] PD#SWPL-6200 Problem: emmc calibration delay set error. Solution: modify delay_step to 250ps. Verify: verify by s912. Change-Id: I1c0e31ae6bdda8b0f105e12f3efc81b5474376d6 Signed-off-by: Nan Li --- drivers/amlogic/mmc/aml_sd_emmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index ad3cbbd2d6e3..aa294b62f709 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -379,6 +379,8 @@ static int aml_cali_find(struct mmc_host *mmc, struct cali_data *c_data) if (host->data->chip_type == MMC_CHIP_GXBB) delay_step = 125; + else if (host->data->chip_type == MMC_CHIP_GXM) + delay_step = 250; else delay_step = 200; if (mmc->ios.bus_width == 0) From 6806a4d504e77a11fdefae4eff90f7cedf55d190 Mon Sep 17 00:00:00 2001 From: rongrong zhou Date: Wed, 6 Mar 2019 17:59:28 +0800 Subject: [PATCH 0166/1060] ptsserv: fix pts lookup fail issue [3/3] PD#SWPL-3730 Problem: playback not smooth Solution: if p2 lookup fail, set p2 = p Verify: verified by x301 Change-Id: I181eae2ba40edd937df12e0925c2a55c856162ba Signed-off-by: rongrong zhou --- drivers/amlogic/media/frame_sync/ptsserv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/amlogic/media/frame_sync/ptsserv.c b/drivers/amlogic/media/frame_sync/ptsserv.c index dde139fb99eb..82e1213f33ae 100644 --- a/drivers/amlogic/media/frame_sync/ptsserv.c +++ b/drivers/amlogic/media/frame_sync/ptsserv.c @@ -752,6 +752,11 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, p2 = p; } + /* if p2 lookup fail, set p2 = p */ + if (type == PTS_TYPE_VIDEO && p2 && p && + OFFSET_DIFF(offset, p2->offset) > lookup_threshold && + OFFSET_DIFF(offset, p->offset) < lookup_threshold) + p2 = p; } else if (OFFSET_LATER(p->offset, offset)) { list_for_each_entry_continue_reverse(p, &pTable-> From 62b2df20bf381ce06544f2dd4b6618cfe2be7916 Mon Sep 17 00:00:00 2001 From: "xiaoliang.wang" Date: Thu, 4 Apr 2019 10:29:23 +0800 Subject: [PATCH 0167/1060] device: changes for s905x3 ac213 bring up [3/3] PD#SWPL-6970 Problem: for s905x3 ac213 bring up, support multi-dts Solution: s905x3 ac213 bring up Verify: AC213 Change-Id: I4a22f4ce5b927db7d0197028abb12e6b669e7dc8 Signed-off-by: xiaoliang.wang Signed-off-by: Luan Yuan --- MAINTAINERS | 13 + .../arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 2 +- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 2 +- .../arm/boot/dts/amlogic/sm1_s905x3_ac213.dts | 1581 +++++++++++++++++ .../boot/dts/amlogic/g12a_s905x2_u212.dts | 2 +- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 2 +- .../boot/dts/amlogic/sm1_s905x3_ac213.dts | 1566 ++++++++++++++++ 7 files changed, 3164 insertions(+), 4 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts create mode 100644 arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts diff --git a/MAINTAINERS b/MAINTAINERS index 0de44850195b..65b2f189573f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14787,6 +14787,19 @@ M: Shunzhou Jiang F: drivers/amlogic/power/power_ctrl.c F: include/linux/amlogic/power_ctrl.h +AMLOGIC TL1 VAD +M: Wenbiao Zhang +F: include/linux/amlogic/vad_api.h + +AMLOGIC SM1 S905X3 DTS +M: Xiaoliang Wang +F: arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +F: arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +F: arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +F: arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +F: arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +F: arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index 56d98e6cc852..200651b06117 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212"; + amlogic-dt-id = "g12a_u212_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 5c7824cd91b7..5dc478b2361d 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212_1g"; + amlogic-dt-id = "g12a_u212_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts new file mode 100644 index 000000000000..eea8ba3c991b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -0,0 +1,1581 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_ac213_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + }; + + amlogic_battery:dummy-battery { + compatible = "amlogic, dummy-battery"; + status = "disabled"; + }; + + amlogic_charger:dummy-charger { + compatible = "amlogic, dummy-charger"; + status = "disabled"; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + net_red { + label="net_red"; + gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + + net_green { + label="net_green"; + gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + /*dvb { + * compatible = "amlogic, dvb"; + * dev_name = "dvb"; + * + * fe0_mode = "external"; + * fe0_demod = "Atbm8881"; + * fe0_i2c_adap_id = <&i2c2>; + * fe0_demod_i2c_addr = <0xc0>; + * fe0_ts = <1>; + * fe0_reset_value = <0>; + * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; + * + * ts1 = "parallel"; + * ts1_control = <0>; + * ts1_invert = <0>; + * interrupts = <0 23 1 + * 0 5 1 + * 0 21 1 + * 0 19 1 + * 0 25 1 + * 0 18 1 + * 0 24 1>; + * interrupt-names = "demux0_irq", + * "demux1_irq", + * "demux2_irq", + * "dvr0_irq", + * "dvr1_irq", + * "dvrfill0_fill", + * "dvrfill1_flush"; + * pinctrl-names = "p_ts1"; + * pinctrl-0 = <&dvb_p_ts1_pins>; + * clocks = <&clkc CLKID_DEMUX + * &clkc CLKID_AHB_ARB0 + * &clkc CLKID_DOS_PARSER>; + * clock-names = "demux", "ahbarb0", "parser_top"; + *}; + */ + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec /*&ad82584f_62*/>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + spdifout: spdifout { + mux { /* GPIOH_4 */ + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + +}; /* end of pinctrl_periphs */ + +//&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +// }; +//}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins", "internal_gpio_pins"; + pinctrl-0 = <&internal_eth_pins>; + pinctrl-1 = <&internal_gpio_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&saradc { + status = "disabled"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index c36e1df7de56..3b7fea555623 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212"; + amlogic-dt-id = "g12a_u212_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 02662aac9d9f..f7481e0c2f46 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212_1g"; + amlogic-dt-id = "g12a_u212_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts new file mode 100644 index 000000000000..1fc333fdd8fd --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -0,0 +1,1566 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_ac213_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + }; + + amlogic_battery:dummy-battery { + compatible = "amlogic, dummy-battery"; + status = "disabled"; + }; + + amlogic_charger:dummy-charger { + compatible = "amlogic, dummy-charger"; + status = "disabled"; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + net_red { + label="net_red"; + gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + + net_green { + label="net_green"; + gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec /*&ad82584f_62*/>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <115>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1460>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1460>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13 */ + groups = "tdmc_sclk_a", + "tdmc_fs_a" + /*, "tdmc_dout0_a" + *, "tdmc_dout2" + *, "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + spdifout: spdifout { + mux { /* GPIOH_4 */ + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + +}; /* end of pinctrl_periphs */ + +//&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +// }; +//}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&saradc { + status = "disabled"; +}; + +&defendkey { + status = "okay"; +}; + From dd8d807074de984dc18379c2a7ef96e8000e7bc7 Mon Sep 17 00:00:00 2001 From: "renjiang.han" Date: Tue, 12 Mar 2019 20:11:59 +0800 Subject: [PATCH 0168/1060] amvideo2: add keep last frame [1/1] PD#OTT-2452 Problem: Black screen in the middle of the cut. Solution: add keep last frame. Verify: on U212 Change-Id: Ib24f066e0682c7427024a74d9bf8cc9b8a310d62 Signed-off-by: renjiang.han --- drivers/amlogic/media/video_sink/video.c | 148 +++++++++++++++--- .../amlogic/media/video_sink/video_keeper.c | 139 +++++++++++++++- drivers/amlogic/media/video_sink/video_priv.h | 3 + include/linux/amlogic/media/utils/amstream.h | 8 +- .../linux/amlogic/media/video_sink/video.h | 2 + .../amlogic/media/video_sink/video_keeper.h | 5 + 6 files changed, 282 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index de38667de8c9..83c0737952d0 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -206,7 +206,7 @@ static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par; static struct vpp_frame_par_s pip_frame_parms[2]; static struct vframe_s *cur_pipbuf; static struct vframe_s local_pip; -static int _videopip_set_disable(u32 val); +//int _videopip_set_disable(u32 val); #endif static struct device *amvideo_dev; @@ -950,6 +950,7 @@ static u32 blackout; static u32 blackout = 1; #endif static u32 force_blackout; +static u32 blackout_pip; /* disable video */ @@ -981,6 +982,12 @@ u32 get_video_enabled(void) { return video_enabled; } + +u32 get_videopip_enabled(void) +{ + return video2_enabled; +} + /* show first frame*/ static bool show_first_frame_nosync; bool show_first_picture; @@ -1152,7 +1159,12 @@ void safe_disble_videolayer(void) #endif } - +#ifdef VIDEO_PIP +void safe_disble_videolayer2(void) +{ + DisableVideoLayer2(); +} +#endif /*********************************************************/ #ifdef VIDEO_PIP static inline struct vframe_s *pip_vf_peek(void) @@ -3132,6 +3144,8 @@ static void pip_toggle_frame(struct vframe_s *vf) cur_pipbuf = vf; if (first_picture) pip_frame_ready_to_set = 1; + if (cur_pipbuf != &local_pip) + video_pip_keeper_new_frame_notify(); } static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) @@ -8299,6 +8313,7 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) static void pip_vf_unreg_provider(void) { ulong flags; + int keeped = 0; /* atomic_set(&video_unreg_flag, 1); */ while (atomic_read(&video_inirq_flag) > 0) @@ -8317,11 +8332,25 @@ static void pip_vf_unreg_provider(void) pip_frame_count = 0; spin_unlock_irqrestore(&lock, flags); - disable_videopip = VIDEO_DISABLE_FORNEXT; - DisableVideoLayer2(); + if (blackout_pip | force_blackout) { + safe_disble_videolayer2(); + try_free_keep_videopip(1); + } + + if (cur_pipbuf) + keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL); + + if (keeped < 0) {/*keep failed.*/ + pr_info("videopip keep failed, disable video now!\n"); + safe_disble_videolayer2(); + try_free_keep_videopip(1); + } + + /*disable_videopip = VIDEO_DISABLE_FORNEXT;*/ + /*DisableVideoLayer2();*/ } -static void pip_vf_light_unreg_provider(void) +static void pip_vf_light_unreg_provider(int need_keep_frame) { ulong flags; @@ -8336,6 +8365,11 @@ static void pip_vf_light_unreg_provider(void) cur_pipbuf = &local_pip; } spin_unlock_irqrestore(&lock, flags); + if (need_keep_frame) { + if (cur_pipbuf) { + vf_keep_pip_current_locked(cur_pipbuf, NULL); + } + } } static int pip_receiver_event_fun( @@ -8344,11 +8378,11 @@ static int pip_receiver_event_fun( if (type == VFRAME_EVENT_PROVIDER_UNREG) pip_vf_unreg_provider(); else if (type == VFRAME_EVENT_PROVIDER_RESET) - pip_vf_light_unreg_provider(); + pip_vf_light_unreg_provider(1); else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) - pip_vf_light_unreg_provider(); + pip_vf_light_unreg_provider(0); else if (type == VFRAME_EVENT_PROVIDER_REG) - pip_vf_light_unreg_provider(); + pip_vf_light_unreg_provider(0); return 0; } #endif @@ -8373,6 +8407,19 @@ u32 set_blackout_policy(int policy) } EXPORT_SYMBOL(set_blackout_policy); +u32 get_blackout_pip_policy(void) +{ + return blackout_pip | force_blackout; +} +EXPORT_SYMBOL(get_blackout_pip_policy); + +u32 set_blackout_pip_policy(int policy) +{ + blackout_pip = policy; + return 0; +} +EXPORT_SYMBOL(set_blackout_pip_policy); + u8 is_vpp_postblend(void) { if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_VD1_POSTBLEND) @@ -8865,27 +8912,28 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) break; case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + put_user(disable_videopip, (u32 __user *)argp); + break; case AMSTREAM_IOC_GET_VIDEO_DISABLE: - if (layer->layer_id == 0) - put_user(disable_video, (u32 __user *)argp); -#ifdef VIDEO_PIP - else if (layer->layer_id == 1) - put_user(disable_videopip, (u32 __user *)argp); -#endif + put_user(disable_video, (u32 __user *)argp); break; case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + { + u32 val; + + if (copy_from_user(&val, argp, sizeof(u32)) == 0) + ret = _videopip_set_disable(val); + else + ret = -EFAULT; + } + break; case AMSTREAM_IOC_SET_VIDEO_DISABLE: { u32 val; if (copy_from_user(&val, argp, sizeof(u32)) == 0) { - if (layer->layer_id == 0) - ret = _video_set_disable(val); -#ifdef VIDEO_PIP - else if (layer->layer_id == 1) - ret = _videopip_set_disable(val); -#endif + ret = _video_set_disable(val); } else ret = -EFAULT; } @@ -9012,6 +9060,24 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; + case AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY: + if (copy_to_user(argp, &blackout_pip, sizeof(u32)) != 0) + ret = -EFAULT; + break; + + case AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY:{ + u32 mode; + + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { + if (mode > 2) + ret = -EINVAL; + else + blackout_pip = mode; + } else + ret = -EFAULT; + } + break; + case AMSTREAM_IOC_CLEAR_VBUF:{ unsigned long flags; while (atomic_read(&video_inirq_flag) > 0 || @@ -9028,6 +9094,19 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) safe_disble_videolayer(); break; + case AMSTREAM_IOC_CLEAR_PIP_VBUF:{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + cur_pipbuf = NULL; + spin_unlock_irqrestore(&lock, flags); + } + break; + + case AMSTREAM_IOC_CLEAR_VIDEOPIP: + safe_disble_videolayer2(); + break; + case AMSTREAM_IOC_SET_FREERUN_MODE: if (arg > FREERUN_DUR) ret = -EFAULT; @@ -9304,6 +9383,8 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT: case AMSTREAM_IOC_CLEAR_VBUF: case AMSTREAM_IOC_CLEAR_VIDEO: + case AMSTREAM_IOC_CLEAR_PIP_VBUF: + case AMSTREAM_IOC_CLEAR_VIDEOPIP: case AMSTREAM_IOC_SET_FREERUN_MODE: case AMSTREAM_IOC_DISABLE_SLOW_SYNC: case AMSTREAM_IOC_SET_3D_TYPE: @@ -11228,7 +11309,7 @@ static ssize_t video_zorder_store( } #ifdef VIDEO_PIP -static int _videopip_set_disable(u32 val) +int _videopip_set_disable(u32 val) { if (val > VIDEO_DISABLE_FORNEXT) return -EINVAL; @@ -11241,6 +11322,7 @@ static int _videopip_set_disable(u32 val) if ((disable_videopip == VIDEO_DISABLE_FORNEXT) && cur_pipbuf && (cur_pipbuf != &local_pip)) pip_property_changed = 1; + try_free_keep_videopip(0); } else { if (cur_pipbuf && (cur_pipbuf != &local_pip)) EnableVideoLayer2(); @@ -11249,6 +11331,26 @@ static int _videopip_set_disable(u32 val) return 0; } +static ssize_t videopip_blackout_policy_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", blackout_pip); +} + +static ssize_t videopip_blackout_policy_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &blackout_pip); + if (r < 0) + return -EINVAL; + + return count; +} + static ssize_t videopip_axis_show( struct class *cla, struct class_attribute *attr, @@ -11598,6 +11700,10 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, video_blackout_policy_show, video_blackout_policy_store), + __ATTR(blackout_pip_policy, + 0664, + videopip_blackout_policy_show, + videopip_blackout_policy_store), __ATTR(video_seek_flag, 0664, video_seek_flag_show, diff --git a/drivers/amlogic/media/video_sink/video_keeper.c b/drivers/amlogic/media/video_sink/video_keeper.c index ad8b02b50411..1c853201f68c 100644 --- a/drivers/amlogic/media/video_sink/video_keeper.c +++ b/drivers/amlogic/media/video_sink/video_keeper.c @@ -64,10 +64,15 @@ static DEFINE_MUTEX(video_keeper_mutex); static unsigned long keep_y_addr, keep_u_addr, keep_v_addr; static int keep_video_on; +static int keep_video_pip_on; static int keep_id; static int keep_head_id; +static int keep_pip_id; +static int keep_pip_head_id; static int keep_el_id; static int keep_el_head_id; +static int keep_pip_el_id; +static int keep_pip_el_head_id; #define Y_BUFFER_SIZE 0x400000 /* for 1920*1088 */ #define U_BUFFER_SIZE 0x100000 /* compatible with NV21 */ @@ -722,6 +727,28 @@ void try_free_keep_video(int flags) EXPORT_SYMBOL(try_free_keep_video); #endif +void try_free_keep_videopip(int flags) +{ + int free_scatter_keeper = flags & 0x1; + + if (keep_video_pip_on || free_scatter_keeper) { + /*pr_info("disbled keep video before free keep buffer.\n");*/ + keep_video_pip_on = 0; + if (!get_videopip_enabled()) { + /*if not disable video,changed to 2 for */ + pr_info("disbled videopip for next before free keep buffer!\n"); + _videopip_set_disable(VIDEO_DISABLE_FORNEXT); + } else if (get_videopip_enabled()) { + safe_disble_videolayer2(); + } + } + mutex_lock(&video_keeper_mutex); + video_pip_keeper_new_frame_notify(); + free_alloced_keep_buffer(); + mutex_unlock(&video_keeper_mutex); +} +EXPORT_SYMBOL(try_free_keep_videopip); + static void video_keeper_update_keeper_mem( void *mem_handle, int type, int *id) @@ -747,7 +774,6 @@ static int video_keeper_frame_keep_locked( struct vframe_s *cur_dispbuf_el) { int type = MEM_TYPE_CODEC_MM; - if (cur_dispbuf->type & VIDTYPE_SCATTER) type = MEM_TYPE_CODEC_MM_SCATTER; video_keeper_update_keeper_mem( @@ -775,6 +801,41 @@ static int video_keeper_frame_keep_locked( return (keep_id + keep_head_id) > 0; } +static int video_pip_keeper_frame_keep_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + int type = MEM_TYPE_CODEC_MM; + + if (cur_dispbuf) { + if (cur_dispbuf->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + video_keeper_update_keeper_mem( + cur_dispbuf->mem_handle, + type, + &keep_pip_id); + video_keeper_update_keeper_mem( + cur_dispbuf->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_head_id); + } + if (cur_dispbuf_el) { + if (cur_dispbuf_el->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + else + type = MEM_TYPE_CODEC_MM; + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_handle, + type, + &keep_pip_el_id); + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_el_head_id); + } + return (keep_pip_id + keep_pip_head_id) > 0; +} + /* * call in irq. *don't used mutex @@ -795,6 +856,7 @@ void video_keeper_new_frame_notify(void) codec_mm_keeper_unmask_keeper(keep_head_id, 120); keep_head_id = -1; } + if (keep_el_id > 0) { /*wait 80 ms for vsync post.*/ codec_mm_keeper_unmask_keeper(keep_el_id, 120); @@ -808,6 +870,36 @@ void video_keeper_new_frame_notify(void) return; } +void video_pip_keeper_new_frame_notify(void) +{ + if (keep_video_pip_on) { + pr_info("new frame show, pip free keeper\n"); + keep_video_pip_on = 0; + } + if (keep_pip_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_id, 120); + keep_pip_id = -1; + } + if (keep_pip_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_head_id, 120); + keep_pip_head_id = -1; + } + if (keep_pip_el_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_id, 120); + keep_pip_el_id = -1; + } + if (keep_pip_el_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_head_id, 120); + keep_pip_el_head_id = -1; + } + +} + + static unsigned int vf_keep_current_locked( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf_el) @@ -1043,6 +1135,51 @@ static unsigned int vf_keep_current_locked( return 1; } + +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + //u32 cur_index; + //u32 y_index, u_index, v_index; + //struct canvas_s cs0, cs1, cs2, cd; + int ret; + + if (!cur_dispbuf) { + pr_info("keep pip exit without cur_dispbuf\n"); + return 0; + } + + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + pr_info("flag: keep pip exit is skip current\n"); + return 0; + } + +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE + ext_frame_capture_poll(1); /*pull if have capture end frame */ +#endif + + if (get_blackout_pip_policy()) { + pr_info("policy: keep exit is skip current\n"); + return 0; + } + + ret = video_pip_keeper_frame_keep_locked( + cur_dispbuf, + cur_dispbuf_el); + + if (ret) { + /*keeped ok with codec keeper!*/ + pr_info("keep pip buffer on!\n"); + keep_video_pip_on = 1; + return 1; + } + + keep_video_pip_on = 0; + return 0; +} + unsigned int vf_keep_current( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf2) diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h index f540771c45aa..34e19eee7347 100644 --- a/drivers/amlogic/media/video_sink/video_priv.h +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -135,6 +135,7 @@ struct blend_setting_s { }; void safe_disble_videolayer(void); +void safe_disble_videolayer2(void); void update_cur_dispbuf(void *buf); /*for video related files only.*/ @@ -145,7 +146,9 @@ struct vframe_s *get_cur_dispbuf(void); int get_video_debug_flags(void); int _video_set_disable(u32 val); +int _videopip_set_disable(u32 val); u32 get_video_enabled(void); +u32 get_videopip_enabled(void); struct device *get_video_device(void); #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index 33663827f34f..e79e5b2717c1 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -90,6 +90,9 @@ #define AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT _IOR((_A_M), 0x21, int) #define AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT _IOW((_A_M), 0x22, int) #define AMSTREAM_IOC_GET_VIDEO_LAYER1_ON _IOR((_A_M), 0x23, int) +/*video pip IOCTL command list*/ +#define AMSTREAM_IOC_CLEAR_VIDEOPIP _IOW((_A_M), 0x24, int) +#define AMSTREAM_IOC_CLEAR_PIP_VBUF _IO((_A_M), 0x25) #define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT _IOR((_A_M), 0x2b, int) #define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT _IOW((_A_M), 0x2c, int) @@ -156,8 +159,11 @@ * 0x5c, struct userdata_buf_state_t) */ - #define AMSTREAM_IOC_VF_STATUS _IOR((_A_M), 0x60, int) + +#define AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY _IOR((_A_M), 0x62, int) +#define AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY _IOW((_A_M), 0x63, int) + #define AMSTREAM_IOC_CLEAR_VBUF _IO((_A_M), 0x80) #define AMSTREAM_IOC_APTS_LOOKUP _IOR((_A_M), 0x81, int) diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 04cb35bdf12c..6004ec2b5009 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -241,6 +241,8 @@ static inline int amvideo_notifier_call_chain(unsigned long val, void *v) int query_video_status(int type, int *value); u32 set_blackout_policy(int policy); u32 get_blackout_policy(void); +u32 set_blackout_pip_policy(int policy); +u32 get_blackout_pip_policy(void); void set_video_angle(u32 s_value); u32 get_video_angle(void); extern unsigned int DI_POST_REG_RD(unsigned int addr); diff --git a/include/linux/amlogic/media/video_sink/video_keeper.h b/include/linux/amlogic/media/video_sink/video_keeper.h index 159469038621..8794407be2dc 100644 --- a/include/linux/amlogic/media/video_sink/video_keeper.h +++ b/include/linux/amlogic/media/video_sink/video_keeper.h @@ -21,12 +21,17 @@ #include void video_keeper_new_frame_notify(void); +void video_pip_keeper_new_frame_notify(void); void try_free_keep_video(int flags); +void try_free_keep_videopip(int flags); int __init video_keeper_init(void); void __exit video_keeper_exit(void); unsigned int vf_keep_current( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf2); +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el); #endif From b86db58e8e711d3439cb261ff9888142a273aa28 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 20 Mar 2019 18:54:47 +0800 Subject: [PATCH 0169/1060] lcd: add mipi-dsi support for sm1 [2/2] PD#SWPL-6114 Problem: add mipi-dsi support for sm1 Solution: add lcd_chip_sm1 Verify: verify by S905x3 Change-Id: I1b95676ad1300f8cbf859f89b557f680cccff117 Signed-off-by: Evoke Zhang --- MAINTAINERS | 5 + .../boot/dts/amlogic/mesong12a_skt-panel.dtsi | 4 +- .../boot/dts/amlogic/mesonsm1_skt-panel.dtsi | 503 ++++++++++++++++++ .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- .../boot/dts/amlogic/mesonsm1_skt-panel.dtsi | 488 +++++++++++++++++ .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- drivers/amlogic/media/vout/backlight/aml_bl.c | 10 + .../amlogic/media/vout/lcd/lcd_clk_config.c | 2 + drivers/amlogic/media/vout/lcd/lcd_debug.c | 1 + .../media/vout/lcd/lcd_tablet/lcd_drv.c | 2 + drivers/amlogic/media/vout/lcd/lcd_vout.c | 10 + include/linux/amlogic/media/vout/lcd/aml_bl.h | 1 + .../linux/amlogic/media/vout/lcd/lcd_vout.h | 1 + 15 files changed, 1029 insertions(+), 6 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi diff --git a/MAINTAINERS b/MAINTAINERS index 65b2f189573f..d9268b572dc6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14787,6 +14787,11 @@ M: Shunzhou Jiang F: drivers/amlogic/power/power_ctrl.c F: include/linux/amlogic/power_ctrl.h +AMLOGIC SM1 DTS +M: shaochan.liu +F: arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi + AMLOGIC TL1 VAD M: Wenbiao Zhang F: include/linux/amlogic/vad_api.h diff --git a/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi b/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi index 9ee5bcb3a810..bac3b8b8dbb9 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi @@ -34,8 +34,8 @@ "encl_top_gate", "encl_int_gate", "gp0_pll"; - reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */ - 0x0 0xff644000 0x0 0x200>; /* dsi_phy */ + reg = <0xffd07000 0x400 /* dsi_host */ + 0xff644000 0x200>; /* dsi_phy */ interrupts = <0 3 1 0 56 1>; interrupt-names = "vsync","vsync2"; diff --git a/arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi new file mode 100644 index 000000000000..5975ceac5b97 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi @@ -0,0 +1,503 @@ +/* + * arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd{ + compatible = "amlogic, sm1"; + dev_name = "lcd"; + mode = "tablet"; + status = "okay"; + key_valid = <0>; + clocks = <&clkc CLKID_MIPI_DSI_HOST + &clkc CLKID_MIPI_DSI_PHY + &clkc CLKID_DSI_MEAS_COMP + &clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_GP0_PLL>; + clock-names = "dsi_host_gate", + "dsi_phy_gate", + "dsi_meas", + "encl_top_gate", + "encl_int_gate", + "gp0_pll"; + reg = <0xffd07000 0x400 /* dsi_host */ + 0xff644000 0x200>; /* dsi_phy */ + interrupts = <0 3 1 + 0 56 1>; + interrupt-names = "vsync","vsync2"; + pinctrl_version = <2>; /* for uboot */ + + /* power type: + * (0=cpu_gpio, 1=pmu_gpio, 2=signal,3=extern, 0xff=ending) + * power index: + * (point gpios_index, or extern_index,0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + lcd_cpu-gpios = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH + &gpio GPIOZ_8 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOZ_9","GPIOZ_8"; + + lcd_0{ + model_name = "B080XAN01"; + interface = "mipi"; + basic_setting = <768 1024 /*h_active, v_active*/ + 948 1140 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 119 159>; /*screen_widht, screen_height*/ + lcd_timing = <64 56 0 /*hs_width, hs_bp, hs_pol*/ + 50 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clk, 1=htotal, 2=vtotal)*/ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 64843200>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 550 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 1 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + + /* dsi_init: data_type, num, data... */ + dsi_init_on = <0x05 1 0x11 + 0xff 20 /*delay(ms)*/ + 0x05 1 0x29 + 0xff 20 /*delay(ms)*/ + 0xff 0xff>; /*ending*/ + dsi_init_off = <0x05 1 0x28 + 0xff 10 /*delay(ms)*/ + 0x05 1 0x10 + 0xff 10 /*delay(ms)*/ + 0xff 0xff>; /*ending*/ + extern_init = <0xff>; /*0xff for invalid*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 1 0 100 + 0 0 0 10 + 0 0 1 20 + 2 0 0 0 + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 50 + 0 0 0 10 + 0 1 1 100 + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lcd_1{ + model_name = "P070ACB_FT"; + interface = "mipi"; + basic_setting = <600 1024 /*h_active, v_active*/ + 770 1070 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 3 5>; /*screen_widht, screen_height*/ + lcd_timing = <10 80 0 /*hs_width,hs_bp,hs_pol*/ + 6 20 0>; /*vs_width,vs_bp,vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clock,1=htotal,2=vtotal)*/ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 49434000>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 400 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 0 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + /* dsi_init: data_type, num, data... */ + dsi_init_on = < + 0xff 10 + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xf0 3 0 0 10 /* reset low, delay 10ms */ + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xfc 2 0x04 3 /* check_reg, check_cnt */ + 0xff 0xff>; /* ending flag */ + dsi_init_off = <0xff 0xff>; /* ending flag */ + /* extern_init: 0xff for invalid */ + extern_init = <5>; + /* power step: type,index,value,delay(ms) */ + power_on_step = < + 0 1 0 200 /* panel power on */ + 2 0 0 0 + 0xff 0 0 0>; + power_off_step = < + 2 0 0 0 + 0 0 0 20 /* reset low */ + 0 1 1 100 /* panel power off */ + 0xff 0 0 0>; + backlight_index = <0>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + dev_name = "lcd_extern"; + status = "okay"; + i2c_bus = "i2c_bus_0"; + key_valid = <0>; + + extern_0{ + index = <0>; + extern_name = "mipi_default";/*default*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0xff 10 + 0x05 1 0x11 + 0xff 120 /* delay 120ms */ + 0x05 1 0x29 + 0xff 0xff>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xff 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xff 150 /* delay 150ms */ + 0xff 0xff>; /*ending*/ + }; + + extern_1{ + index = <1>; + extern_name = "mipi_default";/*P070ACB_FT*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0x23 2 0xE0 0x00 /* Page 0 */ + 0x23 2 0xE1 0x93 /* PASSWORD */ + 0x23 2 0xE2 0x65 + 0x23 2 0xE3 0xF8 + 0x23 2 0x80 0x03 + 0x23 2 0xE0 0x01 /* Page 01 */ + 0x23 2 0x0C 0x74 /* Set PWRIC */ + 0x23 2 0x17 0x00 /* Set Gamma Power */ + 0x23 2 0x18 0xEF /* VGMP=5.1V */ + 0x23 2 0x19 0x00 + 0x23 2 0x1A 0x00 + 0x23 2 0x1B 0xEF /* VGMN=-5.1V */ + 0x23 2 0x1C 0x00 + 0x23 2 0x1F 0x70 /* Set Gate Power */ + 0x23 2 0x20 0x2D + 0x23 2 0x21 0x2D + 0x23 2 0x22 0x7E + 0x23 2 0x26 0xF3 /* VDDD from IOVCC */ + 0x23 2 0x37 0x09 /* SetPanel */ + 0x23 2 0x38 0x04 /* SET RGBCYC */ + 0x23 2 0x39 0x00 + 0x23 2 0x3A 0x01 + 0x23 2 0x3C 0x90 + 0x23 2 0x3D 0xFF + 0x23 2 0x3E 0xFF + 0x23 2 0x3F 0xFF + 0x23 2 0x40 0x02 /* Set TCON */ + 0x23 2 0x41 0x80 + 0x23 2 0x42 0x99 + 0x23 2 0x43 0x14 + 0x23 2 0x44 0x19 + 0x23 2 0x45 0x5A + 0x23 2 0x4B 0x04 + 0x23 2 0x55 0x02 /* power voltage */ + 0x23 2 0x56 0x01 + 0x23 2 0x57 0x69 + 0x23 2 0x58 0x0A + 0x23 2 0x59 0x0A + 0x23 2 0x5A 0x2E /* VGH = 16.2V */ + 0x23 2 0x5B 0x19 /* VGL = -12V */ + 0x23 2 0x5C 0x15 + 0x23 2 0x5D 0x77 /* Gamma */ + 0x23 2 0x5E 0x56 + 0x23 2 0x5F 0x45 + 0x23 2 0x60 0x38 + 0x23 2 0x61 0x35 + 0x23 2 0x62 0x27 + 0x23 2 0x63 0x2D + 0x23 2 0x64 0x18 + 0x23 2 0x65 0x33 + 0x23 2 0x66 0x34 + 0x23 2 0x67 0x35 + 0x23 2 0x68 0x56 + 0x23 2 0x69 0x45 + 0x23 2 0x6A 0x4F + 0x23 2 0x6B 0x42 + 0x23 2 0x6C 0x40 + 0x23 2 0x6D 0x34 + 0x23 2 0x6E 0x25 + 0x23 2 0x6F 0x02 + 0x23 2 0x70 0x77 + 0x23 2 0x71 0x56 + 0x23 2 0x72 0x45 + 0x23 2 0x73 0x38 + 0x23 2 0x74 0x35 + 0x23 2 0x75 0x27 + 0x23 2 0x76 0x2D + 0x23 2 0x77 0x18 + 0x23 2 0x78 0x33 + 0x23 2 0x79 0x34 + 0x23 2 0x7A 0x35 + 0x23 2 0x7B 0x56 + 0x23 2 0x7C 0x45 + 0x23 2 0x7D 0x4F + 0x23 2 0x7E 0x42 + 0x23 2 0x7F 0x40 + 0x23 2 0x80 0x34 + 0x23 2 0x81 0x25 + 0x23 2 0x82 0x02 + 0x23 2 0xE0 0x02 /* Page2 */ + 0x23 2 0x00 0x53 + /* GIP_L Pin mapping RESET_EVEN */ + 0x23 2 0x01 0x55 /* VSSG_EVEN */ + 0x23 2 0x02 0x55 /* VSSA_EVEN */ + 0x23 2 0x03 0x51 /* STV2_EVEN */ + 0x23 2 0x04 0x77 /* VDD2_EVEN */ + 0x23 2 0x05 0x57 /* VDD1_EVEN */ + 0x23 2 0x06 0x1F + 0x23 2 0x07 0x4F /* CK12 */ + 0x23 2 0x08 0x4D /* CK10 */ + 0x23 2 0x09 0x1F + 0x23 2 0x0A 0x4B /* CK8 */ + 0x23 2 0x0B 0x49 /* CK6 */ + 0x23 2 0x0C 0x1F + 0x23 2 0x0D 0x47 /* CK4 */ + 0x23 2 0x0E 0x45 /* CK2 */ + 0x23 2 0x0F 0x41 /* STV1_EVEN */ + 0x23 2 0x10 0x1F + 0x23 2 0x11 0x1F + 0x23 2 0x12 0x1F + 0x23 2 0x13 0x55 /* VGG */ + 0x23 2 0x14 0x1F + 0x23 2 0x15 0x1F + 0x23 2 0x16 0x52 + /* GIP_R Pin mapping RESET_ODD */ + 0x23 2 0x17 0x55 /* VSSG_ODD */ + 0x23 2 0x18 0x55 /* VSSA_ODD */ + 0x23 2 0x19 0x50 /* STV2_ODD */ + 0x23 2 0x1A 0x77 /* VDD2_ODD */ + 0x23 2 0x1B 0x57 /* VDD1_ODD */ + 0x23 2 0x1C 0x1F + 0x23 2 0x1D 0x4E /* CK11 */ + 0x23 2 0x1E 0x4C /* CK9 */ + 0x23 2 0x1F 0x1F + 0x23 2 0x20 0x4A /* CK7 */ + 0x23 2 0x21 0x48 /* CK5 */ + 0x23 2 0x22 0x1F + 0x23 2 0x23 0x46 /* CK3 */ + 0x23 2 0x24 0x44 /* CK1 */ + 0x23 2 0x25 0x40 /* STV1_ODD */ + 0x23 2 0x26 0x1F + 0x23 2 0x27 0x1F + 0x23 2 0x28 0x1F + 0x23 2 0x29 0x1F + 0x23 2 0x2A 0x1F + 0x23 2 0x2B 0x55 /* VGG */ + 0x23 2 0x2C 0x12 /* GIP_L_GS Pin mapping */ + 0x23 2 0x2D 0x15 + 0x23 2 0x2E 0x15 + 0x23 2 0x2F 0x00 + 0x23 2 0x30 0x37 + 0x23 2 0x31 0x17 + 0x23 2 0x32 0x1F + 0x23 2 0x33 0x08 + 0x23 2 0x34 0x0A + 0x23 2 0x35 0x1F + 0x23 2 0x36 0x0C + 0x23 2 0x37 0x0E + 0x23 2 0x38 0x1F + 0x23 2 0x39 0x04 + 0x23 2 0x3A 0x06 + 0x23 2 0x3B 0x10 + 0x23 2 0x3C 0x1F + 0x23 2 0x3D 0x1F + 0x23 2 0x3E 0x1F + 0x23 2 0x3F 0x15 + 0x23 2 0x40 0x1F + 0x23 2 0x41 0x1F + 0x23 2 0x42 0x13 /* GIP_R_GS Pin mapping */ + 0x23 2 0x43 0x15 + 0x23 2 0x44 0x15 + 0x23 2 0x45 0x01 + 0x23 2 0x46 0x37 + 0x23 2 0x47 0x17 + 0x23 2 0x48 0x1F + 0x23 2 0x49 0x09 + 0x23 2 0x4A 0x0B + 0x23 2 0x4B 0x1F + 0x23 2 0x4C 0x0D + 0x23 2 0x4D 0x0F + 0x23 2 0x4E 0x1F + 0x23 2 0x4F 0x05 + 0x23 2 0x50 0x07 + 0x23 2 0x51 0x11 + 0x23 2 0x52 0x1F + 0x23 2 0x53 0x1F + 0x23 2 0x54 0x1F + 0x23 2 0x55 0x1F + 0x23 2 0x56 0x1F + 0x23 2 0x57 0x15 + 0x23 2 0x58 0x40 /* GIP Timing */ + 0x23 2 0x59 0x00 + 0x23 2 0x5A 0x00 + 0x23 2 0x5B 0x10 + 0x23 2 0x5C 0x14 + 0x23 2 0x5D 0x40 + 0x23 2 0x5E 0x01 + 0x23 2 0x5F 0x02 + 0x23 2 0x60 0x40 + 0x23 2 0x61 0x03 + 0x23 2 0x62 0x04 + 0x23 2 0x63 0x7A + 0x23 2 0x64 0x7A + 0x23 2 0x65 0x74 + 0x23 2 0x66 0x16 + 0x23 2 0x67 0xB4 + 0x23 2 0x68 0x16 + 0x23 2 0x69 0x7A + 0x23 2 0x6A 0x7A + 0x23 2 0x6B 0x0C + 0x23 2 0x6C 0x00 + 0x23 2 0x6D 0x04 + 0x23 2 0x6E 0x04 + 0x23 2 0x6F 0x88 + 0x23 2 0x70 0x00 + 0x23 2 0x71 0x00 + 0x23 2 0x72 0x06 + 0x23 2 0x73 0x7B + 0x23 2 0x74 0x00 + 0x23 2 0x75 0xBC + 0x23 2 0x76 0x00 + 0x23 2 0x77 0x04 + 0x23 2 0x78 0x2C + 0x23 2 0x79 0x00 + 0x23 2 0x7A 0x00 + 0x23 2 0x7B 0x00 + 0x23 2 0x7C 0x00 + 0x23 2 0x7D 0x03 + 0x23 2 0x7E 0x7B + 0x23 2 0xE0 0x04 /* Page4 */ + 0x23 2 0x09 0x11 /* Set RGBCYC2 */ + 0x23 2 0x0E 0x48 + 0x23 2 0x2B 0x2B /* ESD Protect */ + 0x23 2 0x2E 0x44 + 0x23 2 0xE0 0x00 /* Page0 */ + 0x23 2 0xE6 0x02 /* Watch dog */ + 0x23 2 0xE7 0x0C + 0x05 1 0x11 /* sleep out */ + 0xff 120 + 0x05 1 0x29 /* display on */ + 0x05 1 0x35 + 0xFF 20 /* delay(ms) */ + 0xFF 0xFF>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xff 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xff 150 /* delay 150ms */ + 0xff 0xff>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-sm1"; + dev_name = "backlight"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_off"; + pinctrl-0 = <&pwm_f_pins2>; + pinctrl-1 = <&bl_pwm_off_pins>; + pinctrl_version = <2>; /* for uboot */ + bl_pwm_config = <&bl_pwm_conf>; + bl-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOH_4","GPIOH_5"; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /* 1=pwm, 2=pwm_combo, 4=extern */ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_F"; + bl_pwm_attr = <0 /*pwm_method*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 1 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "bl_extern"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <4>; /*1=pwm, 2=pwm_combo, 4=extern*/ + bl_power_attr = <1 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_extern_index = <0>; + }; + }; + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <5>; + pwms = <&pwm_ef MESON_PWM_1 30040 0>; + }; + }; + + bl_extern{ + compatible = "amlogic, bl_extern"; + dev_name = "bl_extern"; + status = "disabled"; + i2c_bus = "i2c_bus_3"; + + extern_0{ + index = <0>; + extern_name = "i2c_lp8556"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x2c>; /*7bit i2c address*/ + dim_max_min = <255 10>; + }; + + extern_1{ + index = <1>; + extern_name = "mipi_lt070me05"; + type = <2>; /*0=i2c, 1=spi, 2=mipi*/ + dim_max_min = <255 10>; + }; + }; +};/* end of panel */ + diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 64b021b802db..1bf365fef27d 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -19,7 +19,7 @@ #include "mesonsm1.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesong12a_skt-panel.dtsi" +#include "mesonsm1_skt-panel.dtsi" / { model = "Amlogic"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 3ecd231e25b2..62b8f5279ff2 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -19,7 +19,7 @@ #include "mesonsm1.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesong12a_skt-panel.dtsi" +#include "mesonsm1_skt-panel.dtsi" / { model = "Amlogic"; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi new file mode 100644 index 000000000000..e12ca025ebc0 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi @@ -0,0 +1,488 @@ +/* + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + */ + +/ { + lcd{ + compatible = "amlogic, lcd-sm1"; + mode = "tablet"; + status = "okay"; + key_valid = <0>; + clocks = <&clkc CLKID_MIPI_DSI_HOST + &clkc CLKID_MIPI_DSI_PHY + &clkc CLKID_DSI_MEAS_COMP + &clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_GP0_PLL>; + clock-names = "dsi_host_gate", + "dsi_phy_gate", + "dsi_meas", + "encl_top_gate", + "encl_int_gate", + "gp0_pll"; + reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */ + 0x0 0xff644000 0x0 0x200>; /* dsi_phy */ + interrupts = <0 3 1 + 0 56 1>; + interrupt-names = "vsync","vsync2"; + pinctrl_version = <2>; /* for uboot */ + + /* power type: + * (0=cpu_gpio, 1=pmu_gpio, 2=signal,3=extern, 0xff=ending) + * power index: + * (point gpios_index, or extern_index,0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + lcd_cpu-gpios = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH + &gpio GPIOZ_8 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOZ_9","GPIOZ_8"; + + lcd_0{ + model_name = "B080XAN01"; + interface = "mipi"; + basic_setting = <768 1024 /*h_active, v_active*/ + 948 1140 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 119 159>; /*screen_widht, screen_height*/ + lcd_timing = <64 56 0 /*hs_width, hs_bp, hs_pol*/ + 50 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clk, 1=htotal, 2=vtotal)*/ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 64843200>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 550 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 1 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + + /* dsi_init: data_type, num, data... */ + dsi_init_on = <0x05 1 0x11 + 0xfd 1 20 /*delay(ms)*/ + 0x05 1 0x29 + 0xfd 1 20 /*delay(ms)*/ + 0xff 0>; /*ending*/ + dsi_init_off = <0x05 1 0x28 + 0xfd 1 10 /*delay(ms)*/ + 0x05 1 0x10 + 0xfd 1 10 /*delay(ms)*/ + 0xff 0>; /*ending*/ + extern_init = <0xff>; /*0xff for invalid*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 1 0 100 + 0 0 0 10 + 0 0 1 20 + 2 0 0 0 + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 50 + 0 0 0 10 + 0 1 1 100 + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lcd_1{ + model_name = "P070ACB_FT"; + interface = "mipi"; + basic_setting = <600 1024 /*h_active, v_active*/ + 770 1070 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 3 5>; /*screen_widht, screen_height*/ + lcd_timing = <10 80 0 /*hs_width,hs_bp,hs_pol*/ + 6 20 0>; /*vs_width,vs_bp,vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clock,1=htotal,2=vtotal)*/ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 49434000>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 400 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 0 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + /* dsi_init: data_type, num, data... */ + dsi_init_on = < + 0xff 10 + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xf0 3 0 0 10 /* reset low, delay 10ms */ + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xfc 2 0x04 3 /* check_reg, check_cnt */ + 0xff 0>; /* ending flag */ + dsi_init_off = <0xff 0>; /* ending flag */ + /* extern_init: 0xff for invalid */ + extern_init = <5>; + /* power step: type,index,value,delay(ms) */ + power_on_step = < + 0 1 0 200 /* panel power on */ + 2 0 0 0 + 0xff 0 0 0>; + power_off_step = < + 2 0 0 0 + 0 0 0 20 /* reset low */ + 0 1 1 100 /* panel power off */ + 0xff 0 0 0>; + backlight_index = <0>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + i2c_bus = "i2c_bus_0"; + key_valid = <0>; + + extern_0{ + index = <0>; + extern_name = "mipi_default";/*default*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0xfd 1 10 + 0x05 1 0x11 + 0xfd 1 120 /* delay 120ms */ + 0x05 1 0x29 + 0xff 0>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xfd 1 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xfd 1 150 /* delay 150ms */ + 0xff 0>; /*ending*/ + }; + + extern_1{ + index = <1>; + extern_name = "mipi_default";/*P070ACB_FT*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0x23 2 0xE0 0x00 /* Page 0 */ + 0x23 2 0xE1 0x93 /* PASSWORD */ + 0x23 2 0xE2 0x65 + 0x23 2 0xE3 0xF8 + 0x23 2 0x80 0x03 + 0x23 2 0xE0 0x01 /* Page 01 */ + 0x23 2 0x0C 0x74 /* Set PWRIC */ + 0x23 2 0x17 0x00 /* Set Gamma Power */ + 0x23 2 0x18 0xEF /* VGMP=5.1V */ + 0x23 2 0x19 0x00 + 0x23 2 0x1A 0x00 + 0x23 2 0x1B 0xEF /* VGMN=-5.1V */ + 0x23 2 0x1C 0x00 + 0x23 2 0x1F 0x70 /* Set Gate Power */ + 0x23 2 0x20 0x2D + 0x23 2 0x21 0x2D + 0x23 2 0x22 0x7E + 0x23 2 0x26 0xF3 /* VDDD from IOVCC */ + 0x23 2 0x37 0x09 /* SetPanel */ + 0x23 2 0x38 0x04 /* SET RGBCYC */ + 0x23 2 0x39 0x00 + 0x23 2 0x3A 0x01 + 0x23 2 0x3C 0x90 + 0x23 2 0x3D 0xFF + 0x23 2 0x3E 0xFF + 0x23 2 0x3F 0xFF + 0x23 2 0x40 0x02 /* Set TCON */ + 0x23 2 0x41 0x80 + 0x23 2 0x42 0x99 + 0x23 2 0x43 0x14 + 0x23 2 0x44 0x19 + 0x23 2 0x45 0x5A + 0x23 2 0x4B 0x04 + 0x23 2 0x55 0x02 /* power voltage */ + 0x23 2 0x56 0x01 + 0x23 2 0x57 0x69 + 0x23 2 0x58 0x0A + 0x23 2 0x59 0x0A + 0x23 2 0x5A 0x2E /* VGH = 16.2V */ + 0x23 2 0x5B 0x19 /* VGL = -12V */ + 0x23 2 0x5C 0x15 + 0x23 2 0x5D 0x77 /* Gamma */ + 0x23 2 0x5E 0x56 + 0x23 2 0x5F 0x45 + 0x23 2 0x60 0x38 + 0x23 2 0x61 0x35 + 0x23 2 0x62 0x27 + 0x23 2 0x63 0x2D + 0x23 2 0x64 0x18 + 0x23 2 0x65 0x33 + 0x23 2 0x66 0x34 + 0x23 2 0x67 0x35 + 0x23 2 0x68 0x56 + 0x23 2 0x69 0x45 + 0x23 2 0x6A 0x4F + 0x23 2 0x6B 0x42 + 0x23 2 0x6C 0x40 + 0x23 2 0x6D 0x34 + 0x23 2 0x6E 0x25 + 0x23 2 0x6F 0x02 + 0x23 2 0x70 0x77 + 0x23 2 0x71 0x56 + 0x23 2 0x72 0x45 + 0x23 2 0x73 0x38 + 0x23 2 0x74 0x35 + 0x23 2 0x75 0x27 + 0x23 2 0x76 0x2D + 0x23 2 0x77 0x18 + 0x23 2 0x78 0x33 + 0x23 2 0x79 0x34 + 0x23 2 0x7A 0x35 + 0x23 2 0x7B 0x56 + 0x23 2 0x7C 0x45 + 0x23 2 0x7D 0x4F + 0x23 2 0x7E 0x42 + 0x23 2 0x7F 0x40 + 0x23 2 0x80 0x34 + 0x23 2 0x81 0x25 + 0x23 2 0x82 0x02 + 0x23 2 0xE0 0x02 /* Page2 */ + 0x23 2 0x00 0x53 + /* GIP_L Pin mapping RESET_EVEN */ + 0x23 2 0x01 0x55 /* VSSG_EVEN */ + 0x23 2 0x02 0x55 /* VSSA_EVEN */ + 0x23 2 0x03 0x51 /* STV2_EVEN */ + 0x23 2 0x04 0x77 /* VDD2_EVEN */ + 0x23 2 0x05 0x57 /* VDD1_EVEN */ + 0x23 2 0x06 0x1F + 0x23 2 0x07 0x4F /* CK12 */ + 0x23 2 0x08 0x4D /* CK10 */ + 0x23 2 0x09 0x1F + 0x23 2 0x0A 0x4B /* CK8 */ + 0x23 2 0x0B 0x49 /* CK6 */ + 0x23 2 0x0C 0x1F + 0x23 2 0x0D 0x47 /* CK4 */ + 0x23 2 0x0E 0x45 /* CK2 */ + 0x23 2 0x0F 0x41 /* STV1_EVEN */ + 0x23 2 0x10 0x1F + 0x23 2 0x11 0x1F + 0x23 2 0x12 0x1F + 0x23 2 0x13 0x55 /* VGG */ + 0x23 2 0x14 0x1F + 0x23 2 0x15 0x1F + 0x23 2 0x16 0x52 + /* GIP_R Pin mapping RESET_ODD */ + 0x23 2 0x17 0x55 /* VSSG_ODD */ + 0x23 2 0x18 0x55 /* VSSA_ODD */ + 0x23 2 0x19 0x50 /* STV2_ODD */ + 0x23 2 0x1A 0x77 /* VDD2_ODD */ + 0x23 2 0x1B 0x57 /* VDD1_ODD */ + 0x23 2 0x1C 0x1F + 0x23 2 0x1D 0x4E /* CK11 */ + 0x23 2 0x1E 0x4C /* CK9 */ + 0x23 2 0x1F 0x1F + 0x23 2 0x20 0x4A /* CK7 */ + 0x23 2 0x21 0x48 /* CK5 */ + 0x23 2 0x22 0x1F + 0x23 2 0x23 0x46 /* CK3 */ + 0x23 2 0x24 0x44 /* CK1 */ + 0x23 2 0x25 0x40 /* STV1_ODD */ + 0x23 2 0x26 0x1F + 0x23 2 0x27 0x1F + 0x23 2 0x28 0x1F + 0x23 2 0x29 0x1F + 0x23 2 0x2A 0x1F + 0x23 2 0x2B 0x55 /* VGG */ + 0x23 2 0x2C 0x12 /* GIP_L_GS Pin mapping */ + 0x23 2 0x2D 0x15 + 0x23 2 0x2E 0x15 + 0x23 2 0x2F 0x00 + 0x23 2 0x30 0x37 + 0x23 2 0x31 0x17 + 0x23 2 0x32 0x1F + 0x23 2 0x33 0x08 + 0x23 2 0x34 0x0A + 0x23 2 0x35 0x1F + 0x23 2 0x36 0x0C + 0x23 2 0x37 0x0E + 0x23 2 0x38 0x1F + 0x23 2 0x39 0x04 + 0x23 2 0x3A 0x06 + 0x23 2 0x3B 0x10 + 0x23 2 0x3C 0x1F + 0x23 2 0x3D 0x1F + 0x23 2 0x3E 0x1F + 0x23 2 0x3F 0x15 + 0x23 2 0x40 0x1F + 0x23 2 0x41 0x1F + 0x23 2 0x42 0x13 /* GIP_R_GS Pin mapping */ + 0x23 2 0x43 0x15 + 0x23 2 0x44 0x15 + 0x23 2 0x45 0x01 + 0x23 2 0x46 0x37 + 0x23 2 0x47 0x17 + 0x23 2 0x48 0x1F + 0x23 2 0x49 0x09 + 0x23 2 0x4A 0x0B + 0x23 2 0x4B 0x1F + 0x23 2 0x4C 0x0D + 0x23 2 0x4D 0x0F + 0x23 2 0x4E 0x1F + 0x23 2 0x4F 0x05 + 0x23 2 0x50 0x07 + 0x23 2 0x51 0x11 + 0x23 2 0x52 0x1F + 0x23 2 0x53 0x1F + 0x23 2 0x54 0x1F + 0x23 2 0x55 0x1F + 0x23 2 0x56 0x1F + 0x23 2 0x57 0x15 + 0x23 2 0x58 0x40 /* GIP Timing */ + 0x23 2 0x59 0x00 + 0x23 2 0x5A 0x00 + 0x23 2 0x5B 0x10 + 0x23 2 0x5C 0x14 + 0x23 2 0x5D 0x40 + 0x23 2 0x5E 0x01 + 0x23 2 0x5F 0x02 + 0x23 2 0x60 0x40 + 0x23 2 0x61 0x03 + 0x23 2 0x62 0x04 + 0x23 2 0x63 0x7A + 0x23 2 0x64 0x7A + 0x23 2 0x65 0x74 + 0x23 2 0x66 0x16 + 0x23 2 0x67 0xB4 + 0x23 2 0x68 0x16 + 0x23 2 0x69 0x7A + 0x23 2 0x6A 0x7A + 0x23 2 0x6B 0x0C + 0x23 2 0x6C 0x00 + 0x23 2 0x6D 0x04 + 0x23 2 0x6E 0x04 + 0x23 2 0x6F 0x88 + 0x23 2 0x70 0x00 + 0x23 2 0x71 0x00 + 0x23 2 0x72 0x06 + 0x23 2 0x73 0x7B + 0x23 2 0x74 0x00 + 0x23 2 0x75 0xBC + 0x23 2 0x76 0x00 + 0x23 2 0x77 0x04 + 0x23 2 0x78 0x2C + 0x23 2 0x79 0x00 + 0x23 2 0x7A 0x00 + 0x23 2 0x7B 0x00 + 0x23 2 0x7C 0x00 + 0x23 2 0x7D 0x03 + 0x23 2 0x7E 0x7B + 0x23 2 0xE0 0x04 /* Page4 */ + 0x23 2 0x09 0x11 /* Set RGBCYC2 */ + 0x23 2 0x0E 0x48 + 0x23 2 0x2B 0x2B /* ESD Protect */ + 0x23 2 0x2E 0x44 + 0x23 2 0xE0 0x00 /* Page0 */ + 0x23 2 0xE6 0x02 /* Watch dog */ + 0x23 2 0xE7 0x0C + 0x05 1 0x11 /* sleep out */ + 0xfd 1 120 + 0x05 1 0x29 /* display on */ + 0x05 1 0x35 + 0xfd 1 20 /* delay(ms) */ + 0xFF 0>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xfd 1 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xfd 1 150 /* delay 150ms */ + 0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-sm1"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_off"; + pinctrl-0 = <&pwm_f_pins2>; + pinctrl-1 = <&bl_pwm_off_pins>; + pinctrl_version = <2>; /* for uboot */ + bl_pwm_config = <&bl_pwm_conf>; + bl-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOH_4","GPIOH_5"; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /* 1=pwm, 2=pwm_combo, 4=extern */ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_F"; + bl_pwm_attr = <0 /*pwm_method*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 1 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "bl_extern"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <4>; /*1=pwm, 2=pwm_combo, 4=extern*/ + bl_power_attr = <1 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_extern_index = <0>; + }; + }; + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <5>; + pwms = <&pwm_ef MESON_PWM_1 30040 0>; + }; + }; + + bl_extern{ + compatible = "amlogic, bl_extern"; + status = "disabled"; + i2c_bus = "i2c_bus_3"; + + extern_0{ + index = <0>; + extern_name = "i2c_lp8556"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x2c>; /*7bit i2c address*/ + dim_max_min = <255 10>; + }; + + extern_1{ + index = <1>; + extern_name = "mipi_lt070me05"; + type = <2>; /*0=i2c, 1=spi, 2=mipi*/ + dim_max_min = <255 10>; + }; + }; +};/* end of panel */ + diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index d67113558abf..158d93847305 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -19,7 +19,7 @@ #include "mesonsm1.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesong12a_skt-panel.dtsi" +#include "mesonsm1_skt-panel.dtsi" / { model = "Amlogic"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 91af75774434..756407c7fcdb 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -19,7 +19,7 @@ #include "mesonsm1.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesong12a_skt-panel.dtsi" +#include "mesonsm1_skt-panel.dtsi" / { model = "Amlogic"; diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index a7286d475260..2d84bdb4916a 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -3231,6 +3231,12 @@ static struct bl_data_s bl_data_tl1 = { .pwm_reg = pwm_reg_txlx, }; +static struct bl_data_s bl_data_sm1 = { + .chip_type = BL_CHIP_SM1, + .chip_name = "sm1", + .pwm_reg = pwm_reg_txlx, +}; + static const struct of_device_id bl_dt_match_table[] = { { .compatible = "amlogic, backlight-gxl", @@ -3264,6 +3270,10 @@ static const struct of_device_id bl_dt_match_table[] = { .compatible = "amlogic, backlight-tl1", .data = &bl_data_tl1, }, + { + .compatible = "amlogic, backlight-sm1", + .data = &bl_data_sm1, + }, {}, }; #endif diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 98e693320662..22adef45c17e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -2666,6 +2666,7 @@ static void lcd_clk_config_chip_init(struct lcd_clk_config_s *cConf) cConf->data = &lcd_clk_data_axg; break; case LCD_CHIP_G12A: + case LCD_CHIP_SM1: if (lcd_drv->lcd_clk_path) cConf->data = &lcd_clk_data_g12a_path1; else @@ -2709,6 +2710,7 @@ int lcd_clk_path_change(int sel) switch (lcd_drv->data->chip_type) { case LCD_CHIP_G12A: case LCD_CHIP_G12B: + case LCD_CHIP_SM1: if (sel) cConf->data = &lcd_clk_data_g12a_path1; else diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 83bf97be80a2..306c216a7473 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -4188,6 +4188,7 @@ int lcd_debug_probe(void) break; case LCD_CHIP_G12A: case LCD_CHIP_G12B: + case LCD_CHIP_SM1: if (lcd_drv->lcd_clk_path) lcd_debug_info_reg = &lcd_debug_info_reg_g12a_clk_path1; else diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index d5d69bbde91a..025e0dbcfa04 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -163,6 +163,7 @@ static void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) switch (lcd_drv->data->chip_type) { case LCD_CHIP_G12A: case LCD_CHIP_G12B: + case LCD_CHIP_SM1: /* HHI_MIPI_CNTL0 */ /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ lcd_hiu_write(HHI_MIPI_CNTL0, @@ -223,6 +224,7 @@ static void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) switch (lcd_drv->data->chip_type) { case LCD_CHIP_G12A: case LCD_CHIP_G12B: + case LCD_CHIP_SM1: lcd_hiu_write(HHI_MIPI_CNTL0, 0); lcd_hiu_write(HHI_MIPI_CNTL1, 0); lcd_hiu_write(HHI_MIPI_CNTL2, 0); diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 14dce115d894..3932e1d880bb 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -1272,6 +1272,12 @@ static struct lcd_data_s lcd_data_tl1 = { .reg_map_table = &lcd_reg_tl1[0], }; +static struct lcd_data_s lcd_data_sm1 = { + .chip_type = LCD_CHIP_SM1, + .chip_name = "sm1", + .reg_map_table = &lcd_reg_axg[0], +}; + static const struct of_device_id lcd_dt_match_table[] = { { .compatible = "amlogic, lcd-gxl", @@ -1305,6 +1311,10 @@ static const struct of_device_id lcd_dt_match_table[] = { .compatible = "amlogic, lcd-tl1", .data = &lcd_data_tl1, }, + { + .compatible = "amlogic, lcd-sm1", + .data = &lcd_data_sm1, + }, {}, }; #endif diff --git a/include/linux/amlogic/media/vout/lcd/aml_bl.h b/include/linux/amlogic/media/vout/lcd/aml_bl.h index 67b65e1072ce..a9424d1ab8de 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_bl.h +++ b/include/linux/amlogic/media/vout/lcd/aml_bl.h @@ -50,6 +50,7 @@ enum bl_chip_type_e { BL_CHIP_G12A, BL_CHIP_G12B, BL_CHIP_TL1, + BL_CHIP_SM1, BL_CHIP_MAX, }; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index ebf689fd44db..ce9a5fecbb8e 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -89,6 +89,7 @@ enum lcd_chip_e { LCD_CHIP_G12A, /* 5 */ LCD_CHIP_G12B, /* 6 */ LCD_CHIP_TL1, /* 7 */ + LCD_CHIP_SM1, /* 8 */ LCD_CHIP_MAX, }; From ffc66934f53b04c7cbd6a6bede5e4faf79a2a8db Mon Sep 17 00:00:00 2001 From: Yingyuan Zhu Date: Wed, 10 Apr 2019 17:27:24 +0800 Subject: [PATCH 0170/1060] AC200: fix home button has no function [1/1] PD#SWPL-6694 Problem: home button has no function in sm1-ac200 Solution: add home button configuration in dst node Verify: test pass on sm1-ac200 Change-Id: I670480c6dfd7f833e737adaddbe5981d84091203 Signed-off-by: Yingyuan Zhu --- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 1bf365fef27d..5289ef021743 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -360,7 +360,7 @@ io-channels = <&saradc SARADC_CH2>; io-channel-names = "key-chan-2"; key_chan = ; - key_code = <114 115 28>; + key_code = <114 115 97>; key_val = <143 266 389>; //val=voltage/1800mV*1023 key_tolerance = <40 40 40>; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 158d93847305..f4da9281a9cf 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -358,7 +358,7 @@ io-channels = <&saradc SARADC_CH2>; io-channel-names = "key-chan-2"; key_chan = ; - key_code = <114 115 28>; + key_code = <114 115 97>; key_val = <143 266 389>; //val=voltage/1800mV*1023 key_tolerance = <40 40 40>; }; From 0031db5360512998ec9358a24d69fd21001b4551 Mon Sep 17 00:00:00 2001 From: Ting Li Date: Mon, 18 Feb 2019 18:45:27 +0800 Subject: [PATCH 0171/1060] picdec: add picdec dev node for u200 u211 u212 w400 sm1 [1/1] PD#SWPL-4551 Problem: ImagePlayer cannot play picture Solution: add picdec dev node for u200 u211 u212 w400 Verify: franklin Change-Id: I35cc28e2ab06367f33a7326ce671b1ee461e6fb1 Signed-off-by: xi an --- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905d2_skt_buildroot.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905d2_u200_buildroot.dts | 15 +++++++++++++++ .../amlogic/g12a_s905d2_u200_drm_buildroot.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 15 +++++++++++++++ .../boot/dts/amlogic/g12a_s905x2_u211_512m.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905x2_u211_buildroot.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905x2_u212_buildroot.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts | 15 +++++++++++++++ .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 15 +++++++++++++++ .../g12b_a311d_w400_buildroot_vccktest.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/sm1_pxp.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905d2_skt_buildroot.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 15 +++++++++++++++ .../boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905d2_u200_buildroot.dts | 15 +++++++++++++++ .../amlogic/g12a_s905d2_u200_drm_buildroot.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts | 15 +++++++++++++++ .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 15 +++++++++++++++ .../boot/dts/amlogic/g12a_s905x2_u211_512m.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905x2_u211_buildroot.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts | 15 +++++++++++++++ .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 15 +++++++++++++++ .../dts/amlogic/g12a_s905x2_u212_buildroot.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts | 15 +++++++++++++++ .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 15 +++++++++++++++ .../g12b_a311d_w400_buildroot_vccktest.dts | 15 +++++++++++++++ 39 files changed, 585 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index 13a598ad6933..773329f29392 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -234,6 +234,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 88c7dfb9b1de..597aafb225dd 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -213,6 +213,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -220,6 +228,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index 304aadfc63eb..fa554b995533 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -246,6 +246,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -253,6 +261,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index edb6fd926c36..d4532a7a0f5b 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -250,6 +250,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -257,6 +265,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index c5ee01e0e39b..97780745706b 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -222,6 +222,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -229,6 +237,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 84f951fd0125..b10b011b5856 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -223,6 +223,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -230,6 +238,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index 36244523e044..28415560c690 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -261,6 +261,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -268,6 +276,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index fcd2ebb724e1..81c3067a015f 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -255,6 +255,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -262,6 +270,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index f3480dc20aa5..819d43cf9320 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -250,6 +250,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -257,6 +265,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index e999e2ccbd40..5b5f62ee59cc 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -234,6 +234,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -241,6 +249,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index 200651b06117..f22f2198188f 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -261,6 +261,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -268,6 +276,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 5dc478b2361d..4c5ee332ebdf 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -259,6 +259,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -266,6 +274,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index a3281e845dab..29097af0de37 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -234,6 +234,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -241,6 +249,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index 48895fca044a..c8e9ea7cfb2e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -220,6 +220,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -227,6 +235,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index 074b6314c040..42028cb5b025 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -212,6 +212,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -219,6 +227,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 57aa35a16a79..116c457c7c1b 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -260,6 +260,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -267,6 +275,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 4703b7717f8a..8b638606b014 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -226,6 +226,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -233,6 +241,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts index aa65030e9d6c..a4c02804c226 100644 --- a/arch/arm/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -166,6 +166,14 @@ 0xffff 0x0>; /* ending flag */ }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -173,6 +181,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 5289ef021743..83039edc1a7b 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -249,6 +249,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -256,6 +264,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 62b8f5279ff2..81f9c60ead73 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -249,6 +249,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -256,6 +264,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts index eea8ba3c991b..e2bba8f92513 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -275,6 +275,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -282,6 +290,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index ff07f1e90624..7a00994bd83e 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -227,6 +227,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -234,6 +242,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 51b104354a24..6aba708b2e58 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -213,6 +213,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -220,6 +228,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index f3743f85dc1e..7ffa10199b20 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -244,6 +244,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -251,6 +259,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 19b35d5f8b23..2f77ce693e97 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -244,6 +244,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -251,6 +259,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 190540c6a746..d2759bd878f3 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -222,6 +222,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -229,6 +237,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 7caa5ec0bcb5..f9bfd6c39e31 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -223,6 +223,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -230,6 +238,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index c9342b18c85a..455971e9cc7f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -261,6 +261,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -268,6 +276,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 24074bec433f..296f931a18c4 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -255,6 +255,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -262,6 +270,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 723cc701a3a1..82c673adf3da 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -250,6 +250,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -257,6 +265,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 36241d6eb24b..cc243a6e552b 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -234,6 +234,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -241,6 +249,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index 3b7fea555623..69a83e54ebfd 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -261,6 +261,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -268,6 +276,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index f7481e0c2f46..d10de9e4196f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -255,6 +255,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -262,6 +270,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index dd8d37ef4aa8..258d55415141 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -234,6 +234,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -241,6 +249,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index d2a56ed14063..af22fb202662 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -220,6 +220,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -227,6 +235,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts index dd44a31e10aa..9a41b8951c6d 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -210,6 +210,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -217,6 +225,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index fd971a1c5220..30b529fdc5c0 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -240,6 +240,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -247,6 +255,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 842047aed3ff..f9e6ba952164 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -260,6 +260,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -274,6 +282,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index fd591ed2c338..b55f74e6c59a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -233,6 +233,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; From 38c6354af3ce197ba008d312385f18c125cf0275 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Fri, 12 Apr 2019 16:55:34 +0800 Subject: [PATCH 0172/1060] SUSPEND: add alarm wakeup function [1/1] PD#SWPL-7062 Problem: add alarm wakeup function. Solution: add alarm wakeup function. Verify: g12b_w400,test pass. Change-Id: I0ad6e373b52bfd8d628ad3c8964637174b5fc643 Signed-off-by: Hong Guo --- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 8 ++++++++ arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index fe69fd8da2b6..fe2386d76e17 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -321,6 +321,14 @@ #clock-cells = <0>; }; + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2019/01/01"; + status = "okay"; + }; + cpu_info { compatible = "amlogic, cpuinfo"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index ea260a3452cc..679cddc6a7ae 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -321,6 +321,14 @@ #clock-cells = <0>; }; + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2019/01/01"; + status = "okay"; + }; + cpu_info { compatible = "amlogic, cpuinfo"; status = "okay"; From 4553bc655829033ef4a67721c5bd79b1933c8498 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 12 Apr 2019 16:58:08 +0800 Subject: [PATCH 0173/1060] hdmitx: fix wrong 420 valid_mode [1/1] PD#SWPL-6896 Problem: In the HF1-31 Iter 03 test, the Rx EDID's max tmds clock is 600MHz, and it doesn't claim that it supports Y420 modes. But echo 2160p60hz,420,8bit > /sys/class/amhdmitx/amhdmitx0/valid_mode 'cat valid_mode' will get 1. Solution: Add Y420 8bit check Verify: G12/U212 Change-Id: I0a128eb33aeb2b4bcbf253eff49e9c5186386af1 Signed-off-by: Zongdong Jiao --- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index f26fd5bd6860..349e14f70086 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -2329,6 +2329,29 @@ const char *hdmitx_edid_vic_to_string(enum hdmi_vic vic) return disp_str; } +static bool is_rx_support_y420(struct hdmitx_dev *hdev) +{ + enum hdmi_vic vic = HDMI_Unknown; + + vic = hdmitx_edid_get_VIC(hdev, "2160p60hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + vic = hdmitx_edid_get_VIC(hdev, "2160p50hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + vic = hdmitx_edid_get_VIC(hdev, "smpte60hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + vic = hdmitx_edid_get_VIC(hdev, "smpte50hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + return 0; +} + /* For some TV's EDID, there maybe exist some information ambiguous. * Such as EDID declears support 2160p60hz(Y444 8bit), but no valid * Max_TMDS_Clock2 to indicate that it can support 5.94G signal. @@ -2469,6 +2492,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, return valid; } if (para->cs == COLORSPACE_YUV420) { + if (!is_rx_support_y420(hdev)) + return 0; if (pRXCap->dc_30bit_420) rx_y420_max_dc = COLORDEPTH_30B; if (pRXCap->dc_36bit_420) From 6e98fc1e66d720cb91b400a8fdb4f3cc1848675d Mon Sep 17 00:00:00 2001 From: Zhongfu Luo Date: Wed, 30 Jan 2019 13:58:10 +0800 Subject: [PATCH 0174/1060] defendkey: TL1: support secure upgrade check [4/4] PD#SWPL-5002 Problem: TL1 need to support defendkey secure upgrade check Solution: 1.modify the way of get random Verify: TL1 skt board verify pass Change-Id: I76b29800de787c5e5b18e023d84c1161c9b1643a Signed-off-by: Zhongfu Luo --- drivers/amlogic/defendkey/defendkey.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/defendkey/defendkey.c b/drivers/amlogic/defendkey/defendkey.c index 1ee1a1c4a1b5..a82f49d4949d 100644 --- a/drivers/amlogic/defendkey/defendkey.c +++ b/drivers/amlogic/defendkey/defendkey.c @@ -36,12 +36,13 @@ #include #include "securekey.h" #include +#include #define DEFENDKEY_DEVICE_NAME "defendkey" #define DEFENDKEY_CLASS_NAME "defendkey" void __iomem *mem_base_virt; unsigned long mem_size; -unsigned long random_virt; +//unsigned long random_virt; struct defendkey_mem { unsigned long base; @@ -201,7 +202,7 @@ static ssize_t defendkey_write(struct file *file, pr_info("defendkey: mem_base_phy:%lx mem_size:%lx mem_base_virt:%p\n", mem_base_phy, mem_size, mem_base_virt); - random = readl((void *)random_virt); + random = get_random_long(); #ifdef CONFIG_ARM64_A32 option_random = (random << 8); @@ -400,7 +401,6 @@ static int aml_defendkey_probe(struct platform_device *pdev) { int ret = -1; u64 val64; - struct resource *res; struct device *devp; @@ -421,19 +421,7 @@ static int aml_defendkey_probe(struct platform_device *pdev) mem_size = val64; if (mem_size > defendkey_rmem.size) { dev_err(&pdev->dev, "Reserved memory is not enough!\n"); - return -EINVAL; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (IS_ERR(res)) { - dev_err(&pdev->dev, "reg: cannot obtain I/O memory region"); - ret = PTR_ERR(res); - goto error1; - } - - random_virt = (unsigned long)devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR((void *)random_virt)) { - ret = PTR_ERR((void *)random_virt); + ret = -EINVAL; goto error1; } From c72ffbf4364aebfaca425099c08125277eeb36d8 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Mon, 18 Mar 2019 19:08:54 +0800 Subject: [PATCH 0175/1060] amvecm: add sharpness0 cvbs table in driver [1/2] PD#OTT-2339 Problem: Testing CVBS Video Index Part FAIL Solution: add sharpness0 cvbs table in driver Verify: U212 Change-Id: I91047de0e852c77e70ad95aad3e6830fde7097f4 Signed-off-by: Bencheng Jing --- .../media/enhancement/amvecm/amcm_regmap.h | 166 ++++++++++++++++++ .../amlogic/media/enhancement/amvecm/amve.c | 8 + .../amlogic/media/enhancement/amvecm/amve.h | 1 + .../amlogic/media/enhancement/amvecm/amvecm.c | 3 +- 4 files changed, 177 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h index 1c2c3d30bf89..bf8a1aa37064 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h @@ -918,6 +918,172 @@ static struct am_regs_s cmreg_enhancement = { } }; +/*sr0 sharpness reg*/ +struct am_regs_s sr0reg_cvbs = { + 109, + { + {REG_TYPE_VCBUS, SHARP0_SHARP_HVSIZE, 0xffffffff, 0x02d00240}, + {REG_TYPE_VCBUS, SHARP0_SHARP_HVBLANK_NUM, 0xffffffff, 0x00001e58}, + {REG_TYPE_VCBUS, SHARP0_NR_GAUSSIAN_MODE, 0xffffffff, 0x00000010}, + {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_L, 0xffffffff, 0x56667ac8}, + {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_H, 0xffffffff, 0x00000004}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_LIMIT, + 0xffffffff, 0x50845e00}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_LIMIT, + 0xffffffff, 0x508d5000}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_LIMIT, + 0xffffffff, 0x3d3d1f00}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_LIMIT, + 0xffffffff, 0x38390c00}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_LPF_MODE, 0xffffffff, 0x22202220}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_LPF_MODE, 0xffffffff, 0x22202220}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_HP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_HP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_BP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BLEND_GAIN, 0xffffffff, 0x38402840}, + {REG_TYPE_VCBUS, SHARP0_NR_ALPY_SSD_GAIN_OFST, + 0xffffffff, 0x0000103e}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_TH_RATE, + 0xffffffff, 0x0a195040}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_LIMIT, + 0xffffffff, 0x3f003f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_TH_RATE, + 0xffffffff, 0x0a195040}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_LIMIT, + 0xffffffff, 0x3f003f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0_MIN_MAX, 0xffffffff, 0x003f003f}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIERR_CORING, + 0xffffffff, 0x00000003}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_TH_RATE, + 0xffffffff, 0x00180014}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_LIMIT, + 0xffffffff, 0x00103f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIN_MAX, 0xffffffff, 0x003f003f}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIERR_CORING, + 0xffffffff, 0x00010001}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_TH_RATE, + 0xffffffff, 0x0018000a}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_LIMIT, + 0xffffffff, 0x00402000}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIN_MAX, 0xffffffff, 0x0000003f}, + {REG_TYPE_VCBUS, SHARP0_PK_FINALGAIN_HP_BP, + 0xffffffff, 0x00001414}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_HORZ_CORE_GAIN, + 0xffffffff, 0x08140214}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_VERT_CORE_GAIN, + 0xffffffff, 0x08140214}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_ADPT_MISC, + 0xffffffff, 0x2806c814}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_STATIC, 0xffffffff, 0x2203f03f}, + {REG_TYPE_VCBUS, SHARP0_PK_NR_ENABLE, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_PK_DRT_SAD_MISC, 0xffffffff, 0x12120018}, + {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xffffffff, 0x00000407}, + {REG_TYPE_VCBUS, SHARP0_TI_DIR_CORE_ALPHA, 0xffffffff, 0x0a00003f}, + {REG_TYPE_VCBUS, SHARP0_CTI_DIR_ALPHA, 0xffffffff, 0x0400003f}, + {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DF_GAIN, 0xffffffff, 0x0c0c0c0c}, + {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DIR_AC_DBG, 0xffffffff, 0x56ee0000}, + {REG_TYPE_VCBUS, SHARP0_HCTI_FLT_CLP_DC, 0xffffffff, 0x05555300}, + {REG_TYPE_VCBUS, SHARP0_HCTI_BST_GAIN, 0xffffffff, 0x050a0a00}, + {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xffffffff, 0x03030303}, + {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, + {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_1, 0xffffffff, 0x4b055014}, + {REG_TYPE_VCBUS, SHARP0_HCTI_OS_MARGIN, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_HLTI_FLT_CLP_DC, 0xffffffff, 0x00152100}, + {REG_TYPE_VCBUS, SHARP0_HLTI_BST_GAIN, 0xffffffff, 0x06060600}, + {REG_TYPE_VCBUS, SHARP0_HLTI_BST_CORE, 0xffffffff, 0x03030303}, + {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, + {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_1, 0xffffffff, 0x66635e24}, + {REG_TYPE_VCBUS, SHARP0_HLTI_OS_MARGIN, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_VLTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, + {REG_TYPE_VCBUS, SHARP0_VLTI_BST_GAIN, 0xffffffff, 0x00202020}, + {REG_TYPE_VCBUS, SHARP0_VLTI_BST_CORE, 0xffffffff, 0x00050503}, + {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, + {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, + {REG_TYPE_VCBUS, SHARP0_VCTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, + {REG_TYPE_VCBUS, SHARP0_VCTI_BST_GAIN, 0xffffffff, 0x00101010}, + {REG_TYPE_VCBUS, SHARP0_VCTI_BST_CORE, 0xffffffff, 0x00050503}, + {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, + {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, + {REG_TYPE_VCBUS, SHARP0_SHARP_3DLIMIT, 0xffffffff, 0x03c0021c}, + /*{REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CTRL, 0xffffffff, 0x0018103c},*/ + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_MISC, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_SR3_SAD_CTRL, 0xffffffff, 0x060606ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL0, 0xffffffff, 0x00000ffc}, + {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL1, 0xffffffff, 0x112020cc}, + {REG_TYPE_VCBUS, SHARP0_DEJ_CTRL, 0xffffffff, 0x0000000f}, + {REG_TYPE_VCBUS, SHARP0_DEJ_ALPHA, 0xffffffff, 0x0f0f4646}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_EN, 0xffffffff, 0x00000037}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_0, + 0xffffffff, 0x0405050c}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_1, + 0xffffffff, 0x01040708}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_2, + 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_OFST, + 0xffffffff, 0x000e000e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_CTRL, + 0xffffffff, 0x1392281c}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_0TO3, + 0xffffffff, 0xffffc81e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_4TO6, + 0xffffffff, 0x001832ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_0TO3, + 0xffffffff, 0xffffc81e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_4TO6, + 0xffffffff, 0x001832ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_MADSAD, + 0xffffffff, 0x00000048}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_VR2MAX, + 0xffffffff, 0xffffec20}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_PARAM0, + 0xffffffff, 0x000a2010}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_THETA, + 0xffffffff, 0xfec96420}, + {REG_TYPE_VCBUS, SHARP0_SATPRT_CTRL, 0xffffffff, 0x00054006}, + {REG_TYPE_VCBUS, SHARP0_SATPRT_DIVM, 0xffffffff, 0x00808080}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_CTRL, 0xffffffff, 0x06e222fa}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_YC_THRD, + 0xffffffff, 0x97659765}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_RANDLUT, + 0xffffffff, 0x00249249}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_PXI_THRD, + 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_Y, 0xffffffff, 0x60a52f20}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_U, 0xffffffff, 0x60a52f27}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_V, 0xffffffff, 0x60a52f22}, + {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_L, + 0xffffffff, 0x56667ac8}, + {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_H, + 0xffffffff, 0x00000004}, + {0} + } +}; + /*sr1 sharpness reg*/ struct am_regs_s sr1reg_sd_scale = { 109, diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index e87b26a6f059..b49f7124509c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -1310,6 +1310,8 @@ void amvecm_3d_sync_process(void) #define SR_NOSCALE_LEVEL 0x10 static void amve_sr_reg_setting(unsigned int adaptive_level) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + goto g12_sr_reg_setting; if (adaptive_level & SR_SD_SCALE_LEVEL) am_set_regmap(&sr1reg_sd_scale); else if (adaptive_level & SR_HD_SCALE_LEVEL) @@ -1326,6 +1328,12 @@ static void amve_sr_reg_setting(unsigned int adaptive_level) am_set_regmap(&sr1reg_cvbs); else if (adaptive_level & SR_NOSCALE_LEVEL) am_set_regmap(&sr1reg_hv_noscale); + return; +g12_sr_reg_setting: + /*for g12a and g12b, load sr0 cvbs table when output cvbs mode*/ + if (adaptive_level & SR_CVBS_LEVEL) + am_set_regmap(&sr0reg_cvbs); + return; } void amve_sharpness_adaptive_setting(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index d90c1e059d68..3a7faee79562 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -155,6 +155,7 @@ extern void amve_sharpness_adaptive_setting(struct vframe_s *vf, extern void amve_sharpness_init(void); extern struct am_regs_s sr1reg_sd_scale; extern struct am_regs_s sr1reg_hd_scale; +extern struct am_regs_s sr0reg_cvbs; extern struct am_regs_s sr1reg_cvbs; extern struct am_regs_s sr1reg_hv_noscale; extern void amvecm_fresh_overscan(struct vframe_s *vf); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 1793885cfbd6..e72b62099bcf 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -1072,7 +1072,8 @@ int amvecm_on_vs( /* add some flag to trigger */ if (vf) { /*gxlx sharpness adaptive setting*/ - if (is_meson_gxlx_cpu()) + if (is_meson_gxlx_cpu() || is_meson_g12a_cpu() + || is_meson_g12b_cpu() || is_meson_sm1_cpu()) amve_sharpness_adaptive_setting(vf, sps_h_en, sps_v_en); amvecm_bricon_process( From 1adbd88135612c62744063b7064dceac0c8fa024 Mon Sep 17 00:00:00 2001 From: Liang Ji Date: Fri, 12 Apr 2019 19:05:39 +0800 Subject: [PATCH 0176/1060] partition: change vendor size [1/2] PD#SWPL-6586 Problem: Android P trunk can not compile 64bit kernel Android P vendor size is not enough, 64bit kernel and isp so etc , the size exceeds 256M Solution: change vendor size from 256M into 320M Verify: galilei Change-Id: Icc7b3d7c8d56f5c361acf9722bba6422b8dc3af2 Signed-off-by: Liang Ji Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi | 4 ++-- arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi | 4 ++-- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi | 2 +- arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi index a78cd67fdc23..d917b8fa3f70 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index d210d928d4a1..3047ed5c0dca 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f2c574203d53..6cbedc415e4f 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 2b8e7304cac6..13e510e4e931 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi index aeb1dee501f9..3b0796a9cf21 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi index a78cd67fdc23..d917b8fa3f70 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index fc5a9b7490f6..8998e7ea6ebe 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi index c64a54e27c17..83409beb1e53 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f2c574203d53..6cbedc415e4f 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 2b8e7304cac6..13e510e4e931 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi index aeb1dee501f9..3b0796a9cf21 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm From c0c9f89eb70c23de698262a6217c79e04b2300b1 Mon Sep 17 00:00:00 2001 From: Luan Yuan Date: Tue, 16 Apr 2019 10:53:45 +0800 Subject: [PATCH 0177/1060] picdec: add picdec dev node for u200 u211 u212 w400 sm1 [1/1] PD#SWPL-4551 Problem: ImagePlayer cannot play picture Solution: add picdec dev node for u200 u211 u212 w400 Verify: franklin Change-Id: I35cc28e2ab06367f33a7326ce671b1ee461e6fb1 Signed-off-by: xi an Signed-off-by: Luan Yuan --- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 15 +++++++++++++++ arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/sm1_pxp.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts | 15 +++++++++++++++ 7 files changed, 105 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index f204efb5ee3c..c55b20e65176 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -247,6 +247,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index e2b300c26bc7..fa74a62a7380 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -247,6 +247,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index 587c20e49656..19b70c2dbbcd 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -247,6 +247,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts index d0a57d770b7e..e0fdc85ab210 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -174,6 +174,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index f4da9281a9cf..4eb5c6f3108e 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -247,6 +247,21 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 756407c7fcdb..02082c476e50 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -247,6 +247,21 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts index 1fc333fdd8fd..4000c820ca63 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -280,6 +280,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; From 4a7c4c071c6e29118db8fcae071fbada408908dc Mon Sep 17 00:00:00 2001 From: Rongjun Chen Date: Fri, 4 Jan 2019 11:55:48 +0800 Subject: [PATCH 0178/1060] WIFI: add mem size for bcm wifi [2/5] PD#SWPL-3773 Problem: wifi open fail issue Solution: add mem size to fix wifi open fail issue Verify: r311 Change-Id: Iab6cd8664026639f5aae108a3bd84faa38708487 Signed-off-by: Rongjun Chen --- drivers/amlogic/wifi/dhd_static_buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/wifi/dhd_static_buf.c b/drivers/amlogic/wifi/dhd_static_buf.c index 5a5ccd3ec2f4..5ab937ee10cc 100644 --- a/drivers/amlogic/wifi/dhd_static_buf.c +++ b/drivers/amlogic/wifi/dhd_static_buf.c @@ -92,7 +92,7 @@ enum dhd_prealloc_index { #define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024) #else #define WLAN_DHD_INFO_BUF_SIZE (16 * 1024) -#define WLAN_DHD_WLFC_BUF_SIZE (24 * 1024) +#define WLAN_DHD_WLFC_BUF_SIZE (29 * 1024) #define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024) #endif /* CONFIG_64BIT */ #define WLAN_DHD_MEMDUMP_SIZE (800 * 1024) From 2afdbdb0a76781e27d488d8f82b80f9d4e9bbcc0 Mon Sep 17 00:00:00 2001 From: Xiaoming Sui Date: Wed, 6 Mar 2019 10:45:32 +0800 Subject: [PATCH 0179/1060] avsync: tsync: fix blackscrean issue when replayed [1/2] PD#TV-2802 Problem: The image is stuck or blackscrean for a few seconds when the DTV stream is replayed. Solution: when audio pts and video pts discontinue, then adjust the pcr source clock. Verify: X301 Change-Id: Id0a74e2d4106a30b426bfa7a4faa70451db9b79e Signed-off-by: Xiaoming Sui --- drivers/amlogic/media/frame_sync/tsync.c | 65 ++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index 2b41eb182cbf..27fb17d435c5 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -829,6 +829,29 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) t = timestamp_apts_get(); else t = timestamp_pcrscr_get(); + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + if (abs(param - oldpts) > tsync_av_threshold_min) { + vpts_discontinue = 1; + if (apts_discontinue == 1) { + apts_discontinue = 0; + vpts_discontinue = 0; + pr_info("set apts->pcrsrc,pcrsrc %x to %x,diff %d\n", + timestamp_pcrscr_get(), + timestamp_apts_get(), + timestamp_apts_get() + - timestamp_pcrscr_get()); + timestamp_pcrscr_set(param); + } else { + pr_info("set para->pcrsrc,pcrsrc %x to %x,diff %d\n", + timestamp_pcrscr_get(), param, + param-timestamp_pcrscr_get()); + timestamp_pcrscr_set( + timestamp_vpts_get()); + } + } + timestamp_vpts_set(param); + break; + } /* *amlog_level(LOG_LEVEL_ATTENTION, *"VIDEO_TSTAMP_DISCONTINUITY, 0x%x, 0x%x\n", t, param); @@ -860,6 +883,29 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) amlog_level(LOG_LEVEL_ATTENTION, "audio discontinue, reset apts, 0x%x\n", param); + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + if (abs(param - oldpts) > tsync_av_threshold_min) { + apts_discontinue = 1; + if (vpts_discontinue == 1) { + pr_info("set para->pcrsrc,pcrsrc from %x to %x,diff %d\n", + timestamp_pcrscr_get(), param, + param-timestamp_pcrscr_get()); + apts_discontinue = 0; + vpts_discontinue = 0; + timestamp_pcrscr_set(param); + } else { + pr_info("set vpts->pcrsrc,pcrsrc from %x to %x,diff %d\n", + timestamp_pcrscr_get(), + timestamp_vpts_get(), + timestamp_vpts_get() + - timestamp_pcrscr_get()); + timestamp_pcrscr_set( + timestamp_vpts_get()); + } + } + timestamp_apts_set(param); + break; + } timestamp_apts_set(param); if (!tsync_enable) { timestamp_apts_set(param); @@ -1132,6 +1178,15 @@ void tsync_set_sync_vdiscont(int syncdiscont) } EXPORT_SYMBOL(tsync_set_sync_vdiscont); +int tsync_set_video_runmode(void) +{ + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + if (vpts_discontinue == 1 || apts_discontinue == 1) + return 1; + } + return 0; +} +EXPORT_SYMBOL(tsync_set_video_runmode); void tsync_set_automute_on(int automute_on) { tsync_automute_on = automute_on; @@ -1155,6 +1210,16 @@ int tsync_set_apts(unsigned int pts) t = timestamp_vpts_get(); else t = timestamp_pcrscr_get(); + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + pr_info("tsync_set_apts %x,diff %d\n", + pts, (int)timestamp_pcrscr_get() - pts); + timestamp_apts_set(pts); + if ((int)(timestamp_apts_get() - t) > 30 * TIME_UNIT90K / 1000 + || (int)(t - timestamp_apts_get()) > + 80 * TIME_UNIT90K / 1000) + timestamp_pcrscr_set(pts); + return 0; + } /* do not switch tsync mode until first video toggled. */ if ((abs(oldpts - pts) > tsync_av_threshold_min) && (timestamp_firstvpts_get() > 0)) { /* is discontinue */ From 72c7e76f373da05e1b9eff19136ec83bacd33ba6 Mon Sep 17 00:00:00 2001 From: Luan Yuan Date: Tue, 16 Apr 2019 19:27:45 +0800 Subject: [PATCH 0180/1060] Revert "partition: change vendor size [1/2]" This reverts commit a219789bb228655a92eb140a192f90a4ce31702a. --- arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi | 4 ++-- arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi | 4 ++-- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi | 2 +- arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi index d917b8fa3f70..a78cd67fdc23 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index 3047ed5c0dca..d210d928d4a1 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index 6cbedc415e4f..f2c574203d53 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 13e510e4e931..2b8e7304cac6 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi index 3b0796a9cf21..aeb1dee501f9 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi index d917b8fa3f70..a78cd67fdc23 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index 8998e7ea6ebe..fc5a9b7490f6 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi index 83409beb1e53..c64a54e27c17 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index 6cbedc415e4f..f2c574203d53 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 13e510e4e931..2b8e7304cac6 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi index 3b0796a9cf21..aeb1dee501f9 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x14000000>; + size = <0x0 0x10000000>; mask = <1>; }; odm:odm From c5e36952918029eeaa051496d6350fac8fc06ef5 Mon Sep 17 00:00:00 2001 From: Luan Yuan Date: Tue, 16 Apr 2019 23:52:09 +0800 Subject: [PATCH 0181/1060] Revert "amvecm: add sharpness0 cvbs table in driver [1/2]" This reverts commit 4001dd156e1897dc078a77cee934298385c71940. --- .../media/enhancement/amvecm/amcm_regmap.h | 166 ------------------ .../amlogic/media/enhancement/amvecm/amve.c | 8 - .../amlogic/media/enhancement/amvecm/amve.h | 1 - .../amlogic/media/enhancement/amvecm/amvecm.c | 3 +- 4 files changed, 1 insertion(+), 177 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h index bf8a1aa37064..1c2c3d30bf89 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h @@ -918,172 +918,6 @@ static struct am_regs_s cmreg_enhancement = { } }; -/*sr0 sharpness reg*/ -struct am_regs_s sr0reg_cvbs = { - 109, - { - {REG_TYPE_VCBUS, SHARP0_SHARP_HVSIZE, 0xffffffff, 0x02d00240}, - {REG_TYPE_VCBUS, SHARP0_SHARP_HVBLANK_NUM, 0xffffffff, 0x00001e58}, - {REG_TYPE_VCBUS, SHARP0_NR_GAUSSIAN_MODE, 0xffffffff, 0x00000010}, - {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_L, 0xffffffff, 0x56667ac8}, - {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_H, 0xffffffff, 0x00000004}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_TH_RATE, - 0xffffffff, 0x14323218}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_LIMIT, - 0xffffffff, 0x50845e00}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_TH_RATE, - 0xffffffff, 0x14323218}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_LIMIT, - 0xffffffff, 0x508d5000}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_TH_RATE, - 0xffffffff, 0x14323218}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_LIMIT, - 0xffffffff, 0x3d3d1f00}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_TH_RATE, - 0xffffffff, 0x14323218}, - {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_LIMIT, - 0xffffffff, 0x38390c00}, - {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_LPF_MODE, 0xffffffff, 0x22202220}, - {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_LPF_MODE, 0xffffffff, 0x22202220}, - {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_HP_CORING, 0xffffffff, 0x00020202}, - {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BP_CORING, 0xffffffff, 0x00020202}, - {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_HP_CORING, 0xffffffff, 0x00020202}, - {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_BP_CORING, 0xffffffff, 0x00020202}, - {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BLEND_GAIN, 0xffffffff, 0x38402840}, - {REG_TYPE_VCBUS, SHARP0_NR_ALPY_SSD_GAIN_OFST, - 0xffffffff, 0x0000103e}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_TH_RATE, - 0xffffffff, 0x0a195040}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_LIMIT, - 0xffffffff, 0x3f003f00}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_TH_RATE, - 0xffffffff, 0x0a195040}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_LIMIT, - 0xffffffff, 0x3f003f00}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP0_MIN_MAX, 0xffffffff, 0x003f003f}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIERR_CORING, - 0xffffffff, 0x00000003}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_TH_RATE, - 0xffffffff, 0x00180014}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_LIMIT, - 0xffffffff, 0x00103f00}, - {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIN_MAX, 0xffffffff, 0x003f003f}, - {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIERR_CORING, - 0xffffffff, 0x00010001}, - {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_TH_RATE, - 0xffffffff, 0x0018000a}, - {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_LIMIT, - 0xffffffff, 0x00402000}, - {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIN_MAX, 0xffffffff, 0x0000003f}, - {REG_TYPE_VCBUS, SHARP0_PK_FINALGAIN_HP_BP, - 0xffffffff, 0x00001414}, - {REG_TYPE_VCBUS, SHARP0_PK_OS_HORZ_CORE_GAIN, - 0xffffffff, 0x08140214}, - {REG_TYPE_VCBUS, SHARP0_PK_OS_VERT_CORE_GAIN, - 0xffffffff, 0x08140214}, - {REG_TYPE_VCBUS, SHARP0_PK_OS_ADPT_MISC, - 0xffffffff, 0x2806c814}, - {REG_TYPE_VCBUS, SHARP0_PK_OS_STATIC, 0xffffffff, 0x2203f03f}, - {REG_TYPE_VCBUS, SHARP0_PK_NR_ENABLE, 0xffffffff, 0x00000000}, - {REG_TYPE_VCBUS, SHARP0_PK_DRT_SAD_MISC, 0xffffffff, 0x12120018}, - {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xffffffff, 0x00000407}, - {REG_TYPE_VCBUS, SHARP0_TI_DIR_CORE_ALPHA, 0xffffffff, 0x0a00003f}, - {REG_TYPE_VCBUS, SHARP0_CTI_DIR_ALPHA, 0xffffffff, 0x0400003f}, - {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DF_GAIN, 0xffffffff, 0x0c0c0c0c}, - {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DIR_AC_DBG, 0xffffffff, 0x56ee0000}, - {REG_TYPE_VCBUS, SHARP0_HCTI_FLT_CLP_DC, 0xffffffff, 0x05555300}, - {REG_TYPE_VCBUS, SHARP0_HCTI_BST_GAIN, 0xffffffff, 0x050a0a00}, - {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xffffffff, 0x03030303}, - {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, - {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_1, 0xffffffff, 0x4b055014}, - {REG_TYPE_VCBUS, SHARP0_HCTI_OS_MARGIN, 0xffffffff, 0x00000000}, - {REG_TYPE_VCBUS, SHARP0_HLTI_FLT_CLP_DC, 0xffffffff, 0x00152100}, - {REG_TYPE_VCBUS, SHARP0_HLTI_BST_GAIN, 0xffffffff, 0x06060600}, - {REG_TYPE_VCBUS, SHARP0_HLTI_BST_CORE, 0xffffffff, 0x03030303}, - {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, - {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_1, 0xffffffff, 0x66635e24}, - {REG_TYPE_VCBUS, SHARP0_HLTI_OS_MARGIN, 0xffffffff, 0x00000000}, - {REG_TYPE_VCBUS, SHARP0_VLTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, - {REG_TYPE_VCBUS, SHARP0_VLTI_BST_GAIN, 0xffffffff, 0x00202020}, - {REG_TYPE_VCBUS, SHARP0_VLTI_BST_CORE, 0xffffffff, 0x00050503}, - {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, - {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, - {REG_TYPE_VCBUS, SHARP0_VCTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, - {REG_TYPE_VCBUS, SHARP0_VCTI_BST_GAIN, 0xffffffff, 0x00101010}, - {REG_TYPE_VCBUS, SHARP0_VCTI_BST_CORE, 0xffffffff, 0x00050503}, - {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, - {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, - {REG_TYPE_VCBUS, SHARP0_SHARP_3DLIMIT, 0xffffffff, 0x03c0021c}, - /*{REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CTRL, 0xffffffff, 0x0018103c},*/ - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF0, - 0xffffffff, 0x00004000}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF1, - 0xffffffff, 0xfc2424fc}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF0, - 0xffffffff, 0x00004000}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF1, - 0xffffffff, 0xfc2424fc}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF0, - 0xffffffff, 0x00004000}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF1, - 0xffffffff, 0xfc2424fc}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF0, - 0xffffffff, 0x00004000}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF1, - 0xffffffff, 0xfc2424fc}, - {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_MISC, 0xffffffff, 0x00000000}, - {REG_TYPE_VCBUS, SHARP0_SR3_SAD_CTRL, 0xffffffff, 0x060606ff}, - {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL0, 0xffffffff, 0x00000ffc}, - {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL1, 0xffffffff, 0x112020cc}, - {REG_TYPE_VCBUS, SHARP0_DEJ_CTRL, 0xffffffff, 0x0000000f}, - {REG_TYPE_VCBUS, SHARP0_DEJ_ALPHA, 0xffffffff, 0x0f0f4646}, - {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_EN, 0xffffffff, 0x00000037}, - {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_0, - 0xffffffff, 0x0405050c}, - {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_1, - 0xffffffff, 0x01040708}, - {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_2, - 0xffffffff, 0x00000000}, - {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_OFST, - 0xffffffff, 0x000e000e}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_CTRL, - 0xffffffff, 0x1392281c}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_0TO3, - 0xffffffff, 0xffffc81e}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_4TO6, - 0xffffffff, 0x001832ff}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_0TO3, - 0xffffffff, 0xffffc81e}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_4TO6, - 0xffffffff, 0x001832ff}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_MADSAD, - 0xffffffff, 0x00000048}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_VR2MAX, - 0xffffffff, 0xffffec20}, - {REG_TYPE_VCBUS, SHARP0_SR3_DERING_PARAM0, - 0xffffffff, 0x000a2010}, - {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_THETA, - 0xffffffff, 0xfec96420}, - {REG_TYPE_VCBUS, SHARP0_SATPRT_CTRL, 0xffffffff, 0x00054006}, - {REG_TYPE_VCBUS, SHARP0_SATPRT_DIVM, 0xffffffff, 0x00808080}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_CTRL, 0xffffffff, 0x06e222fa}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_YC_THRD, - 0xffffffff, 0x97659765}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_RANDLUT, - 0xffffffff, 0x00249249}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_PXI_THRD, - 0xffffffff, 0x00000000}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_Y, 0xffffffff, 0x60a52f20}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_U, 0xffffffff, 0x60a52f27}, - {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_V, 0xffffffff, 0x60a52f22}, - {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_L, - 0xffffffff, 0x56667ac8}, - {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_H, - 0xffffffff, 0x00000004}, - {0} - } -}; - /*sr1 sharpness reg*/ struct am_regs_s sr1reg_sd_scale = { 109, diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index b49f7124509c..e87b26a6f059 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -1310,8 +1310,6 @@ void amvecm_3d_sync_process(void) #define SR_NOSCALE_LEVEL 0x10 static void amve_sr_reg_setting(unsigned int adaptive_level) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) - goto g12_sr_reg_setting; if (adaptive_level & SR_SD_SCALE_LEVEL) am_set_regmap(&sr1reg_sd_scale); else if (adaptive_level & SR_HD_SCALE_LEVEL) @@ -1328,12 +1326,6 @@ static void amve_sr_reg_setting(unsigned int adaptive_level) am_set_regmap(&sr1reg_cvbs); else if (adaptive_level & SR_NOSCALE_LEVEL) am_set_regmap(&sr1reg_hv_noscale); - return; -g12_sr_reg_setting: - /*for g12a and g12b, load sr0 cvbs table when output cvbs mode*/ - if (adaptive_level & SR_CVBS_LEVEL) - am_set_regmap(&sr0reg_cvbs); - return; } void amve_sharpness_adaptive_setting(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index 3a7faee79562..d90c1e059d68 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -155,7 +155,6 @@ extern void amve_sharpness_adaptive_setting(struct vframe_s *vf, extern void amve_sharpness_init(void); extern struct am_regs_s sr1reg_sd_scale; extern struct am_regs_s sr1reg_hd_scale; -extern struct am_regs_s sr0reg_cvbs; extern struct am_regs_s sr1reg_cvbs; extern struct am_regs_s sr1reg_hv_noscale; extern void amvecm_fresh_overscan(struct vframe_s *vf); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index e72b62099bcf..1793885cfbd6 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -1072,8 +1072,7 @@ int amvecm_on_vs( /* add some flag to trigger */ if (vf) { /*gxlx sharpness adaptive setting*/ - if (is_meson_gxlx_cpu() || is_meson_g12a_cpu() - || is_meson_g12b_cpu() || is_meson_sm1_cpu()) + if (is_meson_gxlx_cpu()) amve_sharpness_adaptive_setting(vf, sps_h_en, sps_v_en); amvecm_bricon_process( From ee2f61d3ed4b7f0d39561277059cb9badd591458 Mon Sep 17 00:00:00 2001 From: tao zeng Date: Fri, 26 Oct 2018 17:51:30 +0800 Subject: [PATCH 0182/1060] mm: reduce watermark if free cma is too large [1/1] PD#SWPL-807 Problem: Sometimes driver can't allocation memory under atomic environment. And free pages is enough but they are nearly ALL CMA pages. Solution: Reduce watermark with harf of free cma pages even allocation support CMA. Verify: P212 Change-Id: I8e49768d4384ed064775537754a2b7f09a5bbb7c Signed-off-by: tao zeng --- mm/page_alloc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index cef29ab2bd76..b4ebee8dc6e2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3000,6 +3000,11 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, if (!(alloc_flags & ALLOC_CMA)) #endif free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES); +#ifdef CONFIG_AMLOGIC_CMA + /* avoid free pages in water mark are all CMA */ + else + free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES) / 2; +#endif #endif /* From 6b55204e1b104cba128e6a3f31f1653617b7c80b Mon Sep 17 00:00:00 2001 From: tao zeng Date: Thu, 1 Nov 2018 10:18:16 +0800 Subject: [PATCH 0183/1060] mm: exclude free cma pages when calculate watermark [1/1] PD#SWPL-1210 Problem: Some drivers(eth/wifi) occasionally can't allocate memory under atomic context. From mem status print, there are enough free pages but most of them are CMA. Solution: Exclude free cma pages when calculate water mark. This can push kswapd/compaction work more aggressive. Verify: P212 Change-Id: Ia723f21c0316eff1a38e759ff9f044bb59aa8efa Signed-off-by: tao zeng --- mm/page_alloc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b4ebee8dc6e2..cef29ab2bd76 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3000,11 +3000,6 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, if (!(alloc_flags & ALLOC_CMA)) #endif free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES); -#ifdef CONFIG_AMLOGIC_CMA - /* avoid free pages in water mark are all CMA */ - else - free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES) / 2; -#endif #endif /* From e192c987908c94bef7ac6da3b75224b6c752242e Mon Sep 17 00:00:00 2001 From: Lianlian Zhu Date: Thu, 18 Oct 2018 20:01:18 +0800 Subject: [PATCH 0184/1060] audio: solve av out output level low issue [2/2] PD#SWPL-766 Problem: av output level only 100mv Solution: change the channel map for av out, use orignal pcm for output w/o volume control and postprocess. Verify: verified by r311 Change-Id: Ibeaf0ecfda03f81ff6061dc9c4975049452ba659 Signed-off-by: Lianlian Zhu Signed-off-by: Jian Xu --- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 67c3077bd97a..2e42e3c8e83d 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -1282,8 +1282,8 @@ Channel_Mask { /*i2s has 4 pins, 8channel, mux output*/ Speaker0_Channel_Mask = "i2s_2/3"; - DAC0_Channel_Mask = "i2s_2/3"; - DAC1_Channel_Mask = "i2s_2/3"; + DAC0_Channel_Mask = "i2s_4/5"; + DAC1_Channel_Mask = "i2s_4/5"; EQ_DRC_Channel_Mask = "i2s_2/3"; Spdif_samesource_Channel_Mask = "i2s_0/1"; }; From a5cf243d5d9de285f11a5b0c3c3144e7b91d5e19 Mon Sep 17 00:00:00 2001 From: Peng Yixin Date: Tue, 13 Nov 2018 15:21:30 +0800 Subject: [PATCH 0185/1060] media: fix some coverity error: [1/1] PD#SWPL-2053 Problem: Coverity detected some code defects. Solution: Fixed these code defects. Verify: Verified u212 Change-Id: Ie3c0907c7ee3db94f65f58aa5d5c96812a7fe38c Signed-off-by: Peng Yixin --- drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c index f36336aa9a0d..31ee5d4c1151 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c @@ -2221,6 +2221,7 @@ int codec_mm_scatter_mgt_delay_free_swith( int is_tvp) { struct codec_mm_scatter_mgt *smgt; + unsigned long ret = 0; smgt = codec_mm_get_scatter_mgt(is_tvp); codec_mm_list_lock(smgt); From 32a28ad857abb67d8daee0121b5df740e592d6c1 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Wed, 21 Nov 2018 11:36:37 +0800 Subject: [PATCH 0186/1060] dts: the memory of the reserved 1MB was recovered. [1/1] PD#SWPL-2250 Problem: h265 & vp9 4K playback abnormal because HEVC FRONT & VPU READ2 pollute the phy address of near 0x0. Solution: it's only a temporary modification, the real reason needs to take more time fixed. Verify: U212 Change-Id: I3dcc47f8979960e95c89cf53fe10eadc1a7ae5ad Signed-off-by: Nanxin Qin --- arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index fa554b995533..b92cd056ee71 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index d4532a7a0f5b..36d0fd115c79 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; + linux,usable-memory = <0x100000 0x3ff00000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index f22f2198188f..c9947b73297e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 4c5ee332ebdf..f40d1519d6f6 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; + linux,usable-memory = <0x100000 0x3ff00000>; }; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index 42028cb5b025..ddfb8ffb36bd 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index c55b20e65176..aaa181bc9f71 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { From 1d429745f5d7f18bed8c0f12ab817e3ba4574671 Mon Sep 17 00:00:00 2001 From: Hang Cheng Date: Wed, 14 Nov 2018 16:30:17 +0800 Subject: [PATCH 0187/1060] hdmirx: optimize for audio fifo [1/1] PD#SWPL-2114 Problem: When change audio channel count on VG-877, the subpkts of skipped middle channels are still carried, thus causing afifo overflow Solution: When afifo overflow, then store all audio subpkts(8ch) into afifo, and output 8ch audio from afifo Verify: R321 Change-Id: I4b0933935d3a1aed20be10a7a8d3fe23c3a39323 Signed-off-by: Hang Cheng --- .../media/vin/tvin/hdmirx/hdmi_rx_drv.h | 2 +- .../media/vin/tvin/hdmirx/hdmi_rx_hw.c | 22 +++++++++++++++++++ .../media/vin/tvin/hdmirx/hdmi_rx_hw.h | 1 + .../media/vin/tvin/hdmirx/hdmi_rx_wrapper.c | 6 +++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h index b51798c975f8..d35ea36e5a5d 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h @@ -46,7 +46,7 @@ * * */ -#define RX_VER2 "ver.2018/10/30" +#define RX_VER2 "ver.2018/11/14" /*print type*/ #define LOG_EN 0x01 diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c index c36f4994326a..b4e738def841 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c @@ -1003,6 +1003,28 @@ else return false; } +void rx_afifo_store_all_subpkt(bool all_pkt) +{ + static bool flag = true; + + if (all_pkt) { + if (log_level & AUDIO_LOG) + rx_pr("afifo store all subpkts: %d\n", flag); + /* when afifo overflow, try afifo store + * configuration alternatively + */ + if (flag) + hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, + AFIF_SUBPACKETS, 0); + else + hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, + AFIF_SUBPACKETS, 1); + flag = !flag; + } else + hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, + AFIF_SUBPACKETS, 1); +} + /* * hdmirx_audio_fifo_rst - reset afifo */ diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h index 8c64f4ed22ee..7c7efd3feaae 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h @@ -1171,6 +1171,7 @@ extern void rx_hpd_to_esm_handle(struct work_struct *work); extern void rx_hdcp14_resume(void); extern void hdmirx_load_firm_reset(int type); extern unsigned int hdmirx_packet_fifo_rst(void); +extern void rx_afifo_store_all_subpkt(bool all_pkt); extern unsigned int hdmirx_audio_fifo_rst(void); extern void hdmirx_phy_init(void); extern void hdmirx_hw_config(void); diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c index 8cb5cc3c78b0..bcc318d55c14 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c @@ -444,6 +444,11 @@ static int hdmi_rx_ctrl_irq_handler(void) if (log_level & 0x100) rx_pr("[irq] OVERFL\n"); rx.irq_flag |= IRQ_AUD_FLAG; + /* when afifo overflow in multi-channel case(VG-877), + * then store all subpkts into afifo, 8ch in and 8ch out + */ + if (rx.aud_info.auds_layout) + rx_afifo_store_all_subpkt(true); //if (rx.aud_info.real_sr != 0) //error |= hdmirx_audio_fifo_rst(); } @@ -2257,6 +2262,7 @@ void rx_main_state_machine(void) rx_get_audinfo(&rx.aud_info); hdmirx_config_audio(); rx_aud_pll_ctl(1); + rx_afifo_store_all_subpkt(false); hdmirx_audio_fifo_rst(); rx.stable_timestamp = rx.timestamp; rx_pr("Sig ready\n"); From 8236b06010e4df884aeb6f31e8dace8b911d7931 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Thu, 22 Nov 2018 15:48:53 +0800 Subject: [PATCH 0188/1060] amvecm: pq: lc: update local contrast setting [1/1] PD#172587 Problem: update lc setting Solution: update lc setting add demo mode Verify: verified on ref board x301 Change-Id: Ie1542af5e4d8e4fe2c52bd04db66cbdf9130853f Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 77 ++++---- .../media/enhancement/amvecm/local_contrast.c | 178 ++++++++++++------ .../media/enhancement/amvecm/local_contrast.h | 1 + 3 files changed, 165 insertions(+), 91 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 1793885cfbd6..eb5b58e2deee 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -4903,7 +4903,7 @@ static ssize_t amvecm_debug_store(struct class *cla, amvecm_sharpness_enable(13); pr_info("SR disable\n"); } - } else if (!strncmp(parm[0], "cm", 2)) { + } else if (!strcmp(parm[0], "cm")) { if (!strncmp(parm[1], "enable", 6)) { amcm_enable(); pr_info("enable cm\n"); @@ -5080,42 +5080,42 @@ static ssize_t amvecm_debug_store(struct class *cla, color_mode = 0; vpp_clip_config(mode_sel, color, color_mode); pr_info("vpp_clip_config done!\n"); - } else if (!strcmp(parm[0], "3dlut_set")) { - int *PLut3D; - unsigned int bitdepth; + } else if (!strcmp(parm[0], "3dlut_set")) { + int *PLut3D; + unsigned int bitdepth; - PLut3D = kmalloc(14739 * sizeof(int), GFP_KERNEL); - if (PLut3D == NULL) { - kfree(PLut3D); - goto free_buf; - } - if (parm[1]) { - if (kstrtoul(parm[1], 10, &val) < 0) { - kfree(PLut3D); - goto free_buf; - } - bitdepth = val; - } else { - pr_info("unsupport cmd\n"); - kfree(PLut3D); - goto free_buf; - } - - vpp_lut3d_table_init(PLut3D, bitdepth); - if (!strcmp(parm[2], "enable")) - vpp_set_lut3d(1, 1, PLut3D, 1); - else if (!strcmp(parm[2], "disable")) - vpp_set_lut3d(0, 0, PLut3D, 0); - else - pr_info("unsupprt cmd!\n"); + PLut3D = kmalloc(14739 * sizeof(int), GFP_KERNEL); + if (PLut3D == NULL) { kfree(PLut3D); - } else if (!strcmp(parm[0], "3dlut_dump")) { - if (!strcmp(parm[1], "init_tab")) - dump_plut3d_table(); - else if (!strcmp(parm[1], "reg_tab")) - dump_plut3d_reg_table(); - else - pr_info("unsupprt cmd!\n"); + goto free_buf; + } + if (parm[1]) { + if (kstrtoul(parm[1], 10, &val) < 0) { + kfree(PLut3D); + goto free_buf; + } + bitdepth = val; + } else { + pr_info("unsupport cmd\n"); + kfree(PLut3D); + goto free_buf; + } + + vpp_lut3d_table_init(PLut3D, bitdepth); + if (!strcmp(parm[2], "enable")) + vpp_set_lut3d(1, 1, PLut3D, 1); + else if (!strcmp(parm[2], "disable")) + vpp_set_lut3d(0, 0, PLut3D, 0); + else + pr_info("unsupprt cmd!\n"); + kfree(PLut3D); + } else if (!strcmp(parm[0], "3dlut_dump")) { + if (!strcmp(parm[1], "init_tab")) + dump_plut3d_table(); + else if (!strcmp(parm[1], "reg_tab")) + dump_plut3d_reg_table(); + else + pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "cm_hist")) { if (!parm[1]) { pr_info("miss param1\n"); @@ -5399,6 +5399,13 @@ static ssize_t amvecm_lc_store(struct class *cls, return -EINVAL; } amlc_debug = val; + } else if (!strcmp(parm[0], "lc_demo_mode")) { + if (!strcmp(parm[1], "enable")) + lc_demo_mode = 1; + else if (!strcmp(parm[1], "disable")) + lc_demo_mode = 0; + else + pr_info("unsupprt cmd!\n"); } else pr_info("unsupprt cmd!\n"); diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 75a627e845fb..c64fb14451ca 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -33,7 +33,10 @@ int amlc_debug; } while (0) int lc_en; +int lc_demo_mode; +int lc_en_chflg = 0xff; static int lc_flag = 0xff; +static int lc_szcurve[192]; /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, @@ -96,11 +99,11 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, switch (mtx_csc) { case LC_MTX_RGB_YUV709L: if (mtx_sel & (INP_MTX | OUTP_MTX)) { - WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); - WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99); - WRITE_VPP_REG(matrix_coef11_12, 0x1ea601c2); - WRITE_VPP_REG(matrix_coef20_21, 0x01c21e67); - WRITE_VPP_REG(matrix_coef22, 0x00001fd7); + WRITE_VPP_REG(matrix_coef00_01, 0x1070204); + WRITE_VPP_REG(matrix_coef02_10, 0x640f68); + WRITE_VPP_REG(matrix_coef11_12, 0xed601c2); + WRITE_VPP_REG(matrix_coef20_21, 0x01c20e87); + WRITE_VPP_REG(matrix_coef22, 0x0000fb7); WRITE_VPP_REG(matrix_offset0_1, 0x00400200); } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); @@ -116,10 +119,10 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, break; case LC_MTX_YUV709L_RGB: if (mtx_sel & (INP_MTX | OUTP_MTX)) { - WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); - WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); - WRITE_VPP_REG(matrix_coef11_12, 0x1F261DDD); - WRITE_VPP_REG(matrix_coef20_21, 0x04A80876); + WRITE_VPP_REG(matrix_coef00_01, 0x012a0000); + WRITE_VPP_REG(matrix_coef02_10, 0x198012a); + WRITE_VPP_REG(matrix_coef11_12, 0xf9c0f30); + WRITE_VPP_REG(matrix_coef20_21, 0x12a0204); WRITE_VPP_REG(matrix_coef22, 0x0); WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); } else if (mtx_sel & STAT_MTX) { @@ -166,8 +169,8 @@ static void lc_stts_blk_config(int enable, col_start = 0; h_num = 12; v_num = 8; - blk_height = height / h_num; - blk_width = width / v_num; + blk_height = height / v_num; + blk_width = width / h_num; hend0 = col_start + blk_width - 1; hend1 = hend0 + blk_width; @@ -197,26 +200,26 @@ static void lc_stts_blk_config(int enable, ((((row_start & 0x1fff) << 16) & 0xffff0000) | (col_start & 0x1fff))); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend1 & 0x1fff) | (hend0 & 0x1fff)); + ((hend1 & 0x1fff)<<16) | (hend0 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend1 & 0x1fff) | (vend0 & 0x1fff)); + ((vend1 & 0x1fff)<<16) | (vend0 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend3 & 0x1fff) | (hend2 & 0x1fff)); + ((hend3 & 0x1fff)<<16) | (hend2 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend3 & 0x1fff) | (vend2 & 0x1fff)); + ((vend3 & 0x1fff)<<16) | (vend2 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend5 & 0x1fff) | (hend4 & 0x1fff)); + ((hend5 & 0x1fff)<<16) | (hend4 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend5 & 0x1fff) | (vend4 & 0x1fff)); + ((vend5 & 0x1fff)<<16) | (vend4 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend7 & 0x1fff) | (hend6 & 0x1fff)); + ((hend7 & 0x1fff)<<16) | (hend6 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend7 & 0x1fff) | (vend6 & 0x1fff)); + ((vend7 & 0x1fff)<<16) | (vend6 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend9 & 0x1fff) | (hend8 & 0x1fff)); + ((hend9 & 0x1fff)<<16) | (hend8 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend11 & 0x1fff) | (hend10 & 0x1fff)); + ((hend11 & 0x1fff)<<16) | (hend10 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, h_num); } @@ -275,6 +278,7 @@ static void lc_curve_ctrl_config(int enable, } } + static void lc_blk_bdry_config(unsigned int height, unsigned int width) { width /= 12; @@ -343,14 +347,16 @@ static void lc_top_config(int enable, int h_num, int v_num, /*lc hblank*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 8, 8, 8); - /*lc blend mode*/ - WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 0, 1); + /*lc blend mode,default 1*/ + WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 1, 0, 1); /*lc curve mapping config*/ lc_blk_bdry_config(height, width); /*LC sync ctl*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 16, 1); /*lc enable need set at last*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, enable, 4, 1); + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); } static void lc_disable(void) @@ -358,8 +364,10 @@ static void lc_disable(void) /*lc enable need set at last*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 4, 1); WRITE_VPP_REG_BITS(LC_CURVE_CTRL, 0, 0, 1); + WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); /*lc hist stts enable*/ WRITE_VPP_REG_BITS(LC_STTS_HIST_REGION_IDX, 0, 31, 1); + lc_en_chflg = 0x0; } static void lc_config(int enable, @@ -377,12 +385,19 @@ static void lc_config(int enable, h_num = 12; v_num = 8; - if (vf == NULL) + if (vf == NULL) { + vf_height = 0; + vf_width = 0; return; + } - if ((vf_height == vf->height) || - (vf_width == vf->width)) - return; + if ((vf_height == vf->height) && + (vf_width == vf->width)) { + if (!lc_en_chflg) + lc_en_chflg = 0xff; + else + return; + } vf_height = vf->height; vf_width = vf->width; @@ -399,7 +414,7 @@ static void lc_config(int enable, lc_stts_en(enable, height, width, 0, 0, 1, 1, 4); } -static void read_lc_curve(int *szCurveInfo) +static void read_lc_curve(void) { int blk_hnum; int blk_vnum; @@ -412,12 +427,58 @@ static void read_lc_curve(int *szCurveInfo) WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 1); WRITE_VPP_REG(LC_CURVE_RAM_ADDR, 0); for (i = 0; i < blk_hnum * blk_vnum; i++) { - szCurveInfo[i*2+0] = READ_VPP_REG(LC_CURVE_RAM_DATA); - szCurveInfo[i*2+1] = READ_VPP_REG(LC_CURVE_RAM_DATA); + lc_szcurve[i*2+0] = READ_VPP_REG(LC_CURVE_RAM_DATA); + lc_szcurve[i*2+1] = READ_VPP_REG(LC_CURVE_RAM_DATA); + } + WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 0); +} + +static void lc_demo_wr_curve(int h_num, int v_num) +{ + int i, j; + + for (i = 0; i < v_num; i++) { + for (j = 0; j < h_num / 2; j++) { + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + lc_szcurve[2 * (i * h_num + j) + 0]); + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + lc_szcurve[2 * (i * h_num + j) + 1]); + } + for (j = h_num / 2; j < h_num; j++) { + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + (0|(0<<10)|(512<<20))); + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + (1023|(1023<<10)|(512<<20))); + } } } -static int set_lc_curve(int *szCurveInfo, int binit, int bcheck) +static int lc_demo_check_curve(int h_num, int v_num) +{ + int i, j, temp, flag; + + flag = 0; + for (i = 0; i < v_num; i++) { + for (j = 0; j < h_num / 2; j++) { + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != lc_szcurve[2 * (i * h_num + j) + 0]) + flag = (2 * (i * h_num + j) + 0) | (1 << 31); + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != lc_szcurve[2 * (i * h_num + j) + 1]) + flag = (2 * (i * h_num + j) + 1) | (1 << 31); + } + for (j = h_num / 2; j < h_num; j++) { + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != (0|(0<<10)|(512<<20))) + flag = (2 * (i * h_num + j) + 0) | (1 << 31); + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != (1023|(1023<<10)|(512<<20))) + flag = (2 * (i * h_num + j) + 1) | (1 << 31); + } + } + return flag; +} +static int set_lc_curve(int binit, int bcheck) { int i, h_num, v_num; unsigned int hvTemp; @@ -440,26 +501,32 @@ static int set_lc_curve(int *szCurveInfo, int binit, int bcheck) } } else { WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); - for (i = 0; i < h_num * v_num; i++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - szCurveInfo[2 * i + 0]); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - szCurveInfo[2 * i + 1]); - } + if (lc_demo_mode) + lc_demo_wr_curve(h_num, v_num); + else + for (i = 0; i < h_num * v_num; i++) { + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + lc_szcurve[2 * i + 0]); + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + lc_szcurve[2 * i + 1]); + } } WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); if (bcheck) { WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 1, 0, 1); WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0 | (1 << 31)); - for (i = 0; i < h_num * v_num; i++) { - temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != szCurveInfo[2 * i + 0]) - rflag = (2 * i + 0) | (1 << 31); - temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != szCurveInfo[2 * i + 1]) - rflag = (2 * i + 1) | (1 << 31); - } + if (lc_demo_mode) + rflag = lc_demo_check_curve(h_num, v_num); + else + for (i = 0; i < h_num * v_num; i++) { + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != lc_szcurve[2 * i + 0]) + rflag = (2 * i + 0) | (1 << 31); + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != lc_szcurve[2 * i + 1]) + rflag = (2 * i + 1) | (1 << 31); + } WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); } @@ -489,8 +556,9 @@ void lc_init(void) lc_top_config(0, h_num, v_num, height, width); lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); - if (set_lc_curve(NULL, 1, 0)) + if (set_lc_curve(1, 0)) pr_amlc_dbg("%s: init fail", __func__); } @@ -498,8 +566,6 @@ void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) { - int *szCurveInfo; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) return; @@ -508,22 +574,22 @@ void lc_process(struct vframe_s *vf, return; } - if ((vf == NULL) && (lc_flag == 0xff)) { - lc_disable(); - lc_flag = 0x0; + if (vf == NULL) { + if (lc_flag == 0xff) { + lc_disable(); + lc_flag = 0x0; + } return; } - szCurveInfo = kmalloc(12 * 8 * 2 * sizeof(int), GFP_KERNEL); - lc_config(lc_en, vf, sps_h_en, sps_v_en); - read_lc_curve(szCurveInfo); + read_lc_curve(); + lc_fw_curve_iir(vf); - if (set_lc_curve(szCurveInfo, 0, 1)) + if (set_lc_curve(0, 1)) pr_amlc_dbg("%s: set lc curve fail", __func__); lc_flag = 0xff; - kfree(szCurveInfo); } diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index ad742c8a583d..909b441753d1 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -37,6 +37,7 @@ enum lc_mtx_csc_e { extern int amlc_debug; extern int lc_en; +extern int lc_demo_mode; extern void lc_init(void); extern void lc_process(struct vframe_s *vf, unsigned int sps_h_en, From b587e2aeef1bfc4e3504dfdb03c396672e017dd8 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Tue, 20 Nov 2018 10:30:25 +0800 Subject: [PATCH 0189/1060] osd: osd: reserve vs_ctrl bit for VPP [1/1] PD#172587 Problem: reserve vs_ctrl bit for VPP Solution: Avoid operating VPP_OFIFO_SIZE bit19 on OSD code Verify: verified on t962x2_x301 Change-Id: Ic450d6f64e2349d97d02f0802058b4031564fea4 Signed-off-by: Jian Cao --- drivers/amlogic/media/osd/osd_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index ba70c9b8319b..2976cc5033ef 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -8412,7 +8412,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, /* init vpu fifo control register */ data32 = osd_reg_read(VPP_OFIFO_SIZE); if (osd_hw.osd_meson_dev.osd_ver >= OSD_HIGH_ONE) { - data32 = 0; /* reset value 0xfff0fff */ + data32 &= ~((0xfff << 20) | 0x3fff); data32 |= (osd_hw.osd_meson_dev.vpp_fifo_len) << 20; data32 |= osd_hw.osd_meson_dev.vpp_fifo_len + 1; } else From 7fc8579470e64fbe7a83ce25ca1f87994962468d Mon Sep 17 00:00:00 2001 From: Zhongfu Luo Date: Tue, 27 Nov 2018 13:55:10 +0800 Subject: [PATCH 0190/1060] dts: GXL/TXL: adjust defendkey_reserved location [1/1] PD#SWPL-2539 Problem: defendkey_reserved have influenced on display during the system boot up Solution: adjust defendkey_reserved node location Verify: GXL/TXL skt board verify pass Change-Id: I5cf0245f9653e20224c4e3bab1f6f05527011210 Signed-off-by: Zhongfu Luo --- arch/arm/boot/dts/amlogic/gxl_p212_1g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p212_2g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p230_2g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p231_1g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p231_2g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p241_1g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p400_2g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_p401_2g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts | 6 ++++++ arch/arm/boot/dts/amlogic/gxl_skt.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts | 6 ++++++ arch/arm64/boot/dts/amlogic/gxl_skt.dts | 6 ++++++ 38 files changed, 228 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts index 0edc32403125..b52a95ada940 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts index e7333d8637ae..83f756cd6554 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts @@ -48,6 +48,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts b/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts index 868fa5d4d2a2..15cb38ef8d2a 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts index c03256ed4713..8293c0bf661a 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts @@ -51,6 +51,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts index f8abcbe4568d..c82a7ee49c02 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts index c1944cc88ba5..6a7feaed8911 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts @@ -51,6 +51,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index bdb46750131d..c18a5f767253 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -51,6 +51,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts index 5fdbc780e00e..624d76c95ed3 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts @@ -51,6 +51,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts index 0a35a0dfe4f7..9c33a6f59e20 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts @@ -51,6 +51,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 2365af310a9a..fc41753915de 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -48,6 +48,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts index feab09e7e205..2216c3664a36 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index af46fd2edaec..cbd57822c77c 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts index aa85f76b0ef2..3264adc846d2 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index bd8fa63f3cc1..1d314925243c 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts index 46a4b3276009..f4e0c9b1989e 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts @@ -46,6 +46,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts index 2bb9708797db..44e9b023e0e5 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts @@ -46,6 +46,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts b/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts index 2f447c3deff0..141f7fd0e4e6 100644 --- a/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts index f68747e8b572..de1a6c39970e 100644 --- a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts @@ -51,6 +51,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_skt.dts b/arch/arm/boot/dts/amlogic/gxl_skt.dts index 5ace41afcb84..27af275df244 100644 --- a/arch/arm/boot/dts/amlogic/gxl_skt.dts +++ b/arch/arm/boot/dts/amlogic/gxl_skt.dts @@ -50,6 +50,12 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x08300000 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts index c4767fccfc99..e6d69e7000f8 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts index 46a3d5aadf14..89845aa05623 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts @@ -48,6 +48,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts index 85f64e4ca09b..351bb1b4f383 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index df862e17defe..93f9ab508bda 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts index 353e3d077d64..48305660a903 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts index 101ad78b2091..e41e85bdcbb5 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index 5c38487443f2..2df82971ab30 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts index 7d8d55ab43b9..e634c4f0dcfd 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts index ba85a853779d..d371e29b0a74 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 92f6e7d9ceef..621b53852742 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -48,6 +48,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts index dadb59aed48a..b1a03cfc974e 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index 2a7245aff17a..fc00c40eb486 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts index f569d0799fc5..80f807f48969 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index 6bfe499fead6..5cc454c23746 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts index bb6cc479e20c..797233b66f08 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts @@ -46,6 +46,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts index f316571920da..6232fc7e1d31 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts @@ -46,6 +46,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts index 916f139309e5..ada88fe85398 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts index 5140780d2f7f..d2e010ec5ee5 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts @@ -51,6 +51,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_skt.dts b/arch/arm64/boot/dts/amlogic/gxl_skt.dts index b78105139352..13cd67a6030b 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_skt.dts @@ -50,6 +50,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ + + defendkey_reserved:linux,defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0x08300000 0x0 0x100000>; + }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; From dc4f8f9928429b3dc0b567c240bd5cc5c52fd75d Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Thu, 22 Nov 2018 20:04:48 +0800 Subject: [PATCH 0191/1060] tvin: vdin: hdmirx format change, display exception [1/1] PD#SWPL-2411 Problem: hdmirx input 4096X2160 yuv422 in a short period of time, formate change form yuv422 to yuv444, screen display is exception. Solution: force malloc yuv444 size Verify: Verify on txlx r311 Change-Id: Ie670b9a2b0c1eceffe423a1cf8606e78b6b347cd Signed-off-by: Xuhua Zhang --- drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h index 66aababd2c2e..d97d7675a433 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h @@ -31,8 +31,8 @@ #define VDIN_MIN_SOURCE_BITDEPTH 8 -#define VDIN_YUV444_MAX_CMA_WIDTH 1920 -#define VDIN_YUV444_MAX_CMA_HEIGH 1080 +#define VDIN_YUV444_MAX_CMA_WIDTH 4096 +#define VDIN_YUV444_MAX_CMA_HEIGH 2160 extern const unsigned int vdin_canvas_ids[2][VDIN_CANVAS_MAX_CNT]; extern void vdin_canvas_init(struct vdin_dev_s *devp); From 92492e5ccdc1da7433dbc7a5a4ebd2a1d2bfbc69 Mon Sep 17 00:00:00 2001 From: tao zeng Date: Wed, 21 Nov 2018 12:42:25 +0800 Subject: [PATCH 0192/1060] display: fix logo address missmatch problem [1/1] PD#TV-1083 Problem: When bootimg, logo display become blur due to logo address is not match Solution: Correct CMA address of logo Verify: p321 Change-Id: I3996635c4fc9cee1751c75aff3f8224adb2accde Signed-off-by: tao zeng --- arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts index d961b2423ba8..2549e9ef3526 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -80,7 +80,7 @@ reusable; size = <0x400000>; alignment = <0x400000>; - alloc-ranges = <0x0 0x30000000>; + alloc-ranges = <0x2FC00000 0x400000>; }; codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; @@ -233,7 +233,7 @@ /*1280*720*4*3 = 0xA8C000*/ display_size_default = <1280 720 1280 2160 32>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ - logo_addr = "0x3fc00000"; + logo_addr = "0x2FC00000"; }; picdec { From 6f69cb0290611bdb681751bfe6841714b72aa075 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Thu, 29 Nov 2018 19:16:13 +0800 Subject: [PATCH 0193/1060] vdac: close vdac bandgap for suspend power [1/1] PD#SWPL-2643 Problem: cvbsout electric current 1.97mA when suspend Solution: close bandgap when suspend Verify: verified by x301 Change-Id: I6b87ecd42b0f7876fea18c400f19ddc2d4a7665e Signed-off-by: Nian Jing --- drivers/amlogic/media/vout/vdac/vdac_dev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/amlogic/media/vout/vdac/vdac_dev.c b/drivers/amlogic/media/vout/vdac/vdac_dev.c index 361e7deefb34..9c266930e374 100644 --- a/drivers/amlogic/media/vout/vdac/vdac_dev.c +++ b/drivers/amlogic/media/vout/vdac/vdac_dev.c @@ -712,12 +712,17 @@ static int amvdac_drv_suspend(struct platform_device *pdev, if (s_vdac_data->cpu_id == VDAC_CPU_TXL || s_vdac_data->cpu_id == VDAC_CPU_TXLX) vdac_hiu_reg_write(HHI_VDAC_CNTL0, 0); + else if (s_vdac_data->cpu_id == VDAC_CPU_TL1) + vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 1, 7, 1); pr_info("%s: suspend module\n", __func__); return 0; } static int amvdac_drv_resume(struct platform_device *pdev) { + /*0xbc[7] for bandgap enable: 0:enable,1:disable*/ + if (s_vdac_data->cpu_id == VDAC_CPU_TL1) + vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 0, 7, 1); pr_info("%s: resume module\n", __func__); return 0; } From 3582d2ba3f99f880b6a91384e83e0748a7a0e3aa Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Wed, 28 Nov 2018 11:29:04 +0800 Subject: [PATCH 0194/1060] amvecm: pq: lc: add debug interface [1/1] PD#SWPL-2583 Problem: add debug interface Solution: add lc reg lut dump and write interface add demo mode add dump hist interface add dump curve node interface Verify: x301 Change-Id: I85be40f76f252bbaa2ffc69710cc7158ed91bbc4 Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 225 +++++++++++++++++- .../media/enhancement/amvecm/local_contrast.c | 178 ++++++++++++-- .../media/enhancement/amvecm/local_contrast.h | 19 ++ 3 files changed, 399 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index eb5b58e2deee..dd0c94ff27f8 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5359,6 +5359,131 @@ static ssize_t amvecm_get_hdr_type_store(struct class *cls, return count; } +static void lc_rd_reg(enum lc_reg_lut_e reg_sel) +{ + int i, tmp, tmp1, tmp2; + + switch (reg_sel) { + case SATUR_LUT: + for (i = 0; i < 31 ; i++) { + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i); + tmp1 = (tmp >> 16) & 0xfff; + tmp2 = tmp & 0xfff; + pr_info("reg_lc_satur_lut[%d] =%4d.\n", + 2*i, tmp1); + pr_info("reg_lc_satur_lut[%d] =%4d.\n", + 2*i + 1, tmp2); + } + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_62); + pr_info("reg_lc_satur_lut[62] =%4d.\n", + tmp & 0xfff); + break; + case YMINVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + pr_info("reg_yminVal_lmt[%d] =%4d.\n", + 2*i, tmp1); + pr_info("reg_yminVal_lmt[%d] =%4d.\n", + 2*i + 1, tmp2); + } + break; + case YPKBV_YMAXVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + pr_info("reg_lc_ypkBV_ymaxVal_lmt[%d] =%4d.\n", + 2*i, tmp1); + pr_info("reg_lc_ypkBV_ymaxVal_lmt[%d] =%4d.\n", + 2*i + 1, tmp2); + } + break; + case YPKBV_RAT: + tmp = READ_VPP_REG(LC_CURVE_YPKBV_RAT); + pr_info("reg_lc_ypkBV_ratio[0] =%4d.\n", + (tmp>>24) & 0xff); + pr_info("reg_lc_ypkBV_ratio[1] =%4d.\n", + (tmp>>16) & 0xff); + pr_info("reg_lc_ypkBV_ratio[2] =%4d.\n", + (tmp>>8) & 0xff); + pr_info("reg_lc_ypkBV_ratio[3] =%4d.\n", + tmp & 0xff); + break; + case YPKBV_SLP_LMT: + tmp = READ_VPP_REG(LC_CURVE_YPKBV_SLP_LMT); + pr_info("reg_lc_ypkBV_slope_lmt[0] =%4d.\n", + (tmp>>8) & 0xff); + pr_info("reg_lc_ypkBV_slope_lmt[1] =%4d.\n", + tmp & 0xff); + break; + case CNTST_LMT: + tmp = READ_VPP_REG(LC_CURVE_CONTRAST__LMT_LH); + pr_info("reg_lc_cntstlmt_low[0] =%4d.\n", + (tmp>>24) & 0xff); + pr_info("reg_lc_cntstlmt_high[0] =%4d.\n", + (tmp>>16) & 0xff); + pr_info("reg_lc_cntstlmt_low[1] =%4d.\n", + (tmp>>8) & 0xff); + pr_info("reg_lc_cntstlmt_high[1] =%4d.\n", + tmp & 0xff); + break; + default: + break; + } +} + +static void lc_wr_reg(int *p, enum lc_reg_lut_e reg_sel) +{ + int i, tmp, tmp1, tmp2; + + switch (reg_sel) { + case SATUR_LUT: + for (i = 0; i < 31 ; i++) { + tmp1 = *(p + 2*i); + tmp2 = *(p + 2*i + 1); + tmp = ((tmp1 & 0xfff)<<16) | (tmp2 & 0xfff); + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i, tmp); + } + tmp = (*(p+62)) & 0xfff; + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_62, tmp); + break; + case YMINVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp1 = *(p + 2*i); + tmp2 = *(p + 2*i + 1); + tmp = ((tmp1&0x3ff) << 16) | (tmp2 & 0x3ff); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1 + i, tmp); + } + break; + case YPKBV_YMAXVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp1 = *(p + 2*i); + tmp2 = *(p + 2*i + 1); + tmp = ((tmp1&0x3ff) << 16) | (tmp2 & 0x3ff); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1 + i, tmp); + } + break; + case YPKBV_RAT: + tmp = (*p & 0xff) << 24 | (*(p+1) & 0xff) << 16 | + (*(p+2) & 0xff) << 8 | (*(p+3) & 0xff); + WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, tmp); + break; + case YPKBV_SLP_LMT: + tmp = (*p & 0xff) << 8 | (*(p+1) & 0xff); + WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, tmp); + break; + case CNTST_LMT: + tmp = (*p & 0xff) << 24 | (*(p+1) & 0xff) << 16 | + (*(p+2) & 0xff) << 8 | (*(p+3) & 0xff); + WRITE_VPP_REG(LC_CURVE_CONTRAST__LMT_LH, tmp); + break; + default: + break; + } +} + static ssize_t amvecm_lc_show(struct class *cla, struct class_attribute *attr, char *buf) { @@ -5370,6 +5495,22 @@ static ssize_t amvecm_lc_show(struct class *cla, "echo lc disable > /sys/class/amvecm/lc\n"); len += sprintf(buf+len, "echo lc_dbg value > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_demo_mode enable/disable > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_dump_reg parm1 > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_rd_reg parm1 parm2 > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "parm1: 0x1,0x2,0x4,0x8,0x10,0x20...\n"); + len += sprintf(buf+len, + "parm2: decimal strings, each data width is 4.\n"); + len += sprintf(buf+len, + "echo dump_hist all > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo dump_hist chosen hs he vs ve cnt > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo dump_curve cnt > /sys/class/amvecm/lc\n"); return len; } @@ -5378,6 +5519,8 @@ static ssize_t amvecm_lc_store(struct class *cls, const char *buf, size_t count) { char *buf_orig, *parm[8] = {NULL}; + int reg_lut[63] = {0}; + enum lc_reg_lut_e reg_sel; long val = 0; if (!buf) @@ -5394,10 +5537,8 @@ static ssize_t amvecm_lc_store(struct class *cls, else pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "lc_dbg")) { - if (kstrtoul(parm[1], 16, &val) < 0) { - kfree(buf_orig); - return -EINVAL; - } + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; amlc_debug = val; } else if (!strcmp(parm[0], "lc_demo_mode")) { if (!strcmp(parm[1], "enable")) @@ -5406,11 +5547,85 @@ static ssize_t amvecm_lc_store(struct class *cls, lc_demo_mode = 0; else pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "lc_dump_reg")) { + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; + reg_sel = val; + if (reg_sel == SATUR_LUT) + lc_rd_reg(SATUR_LUT); + else if (reg_sel == YMINVAL_LMT) + lc_rd_reg(YMINVAL_LMT); + else if (reg_sel == YPKBV_YMAXVAL_LMT) + lc_rd_reg(YPKBV_YMAXVAL_LMT); + else if (reg_sel == YPKBV_RAT) + lc_rd_reg(YPKBV_RAT); + else if (reg_sel == YPKBV_SLP_LMT) + lc_rd_reg(YPKBV_SLP_LMT); + else if (reg_sel == CNTST_LMT) + lc_rd_reg(CNTST_LMT); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "lc_wr_reg")) { + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; + reg_sel = val; + if (parm[2] == NULL) + goto free_buf; + str_sapr_to_d(parm[2], reg_lut, 5); + if (reg_sel == SATUR_LUT) + lc_wr_reg(reg_lut, SATUR_LUT); + else if (reg_sel == YMINVAL_LMT) + lc_wr_reg(reg_lut, YMINVAL_LMT); + else if (reg_sel == YPKBV_YMAXVAL_LMT) + lc_wr_reg(reg_lut, YPKBV_YMAXVAL_LMT); + else if (reg_sel == YPKBV_RAT) + lc_wr_reg(reg_lut, YPKBV_RAT); + else if (reg_sel == YPKBV_SLP_LMT) + lc_wr_reg(reg_lut, YPKBV_SLP_LMT); + else if (reg_sel == CNTST_LMT) + lc_wr_reg(reg_lut, CNTST_LMT); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "dump_hist")) { + if (!strcmp(parm[1], "all")) { + /*dump all hist in one frame*/ + lc_hist_prcnt = 1; + amlc_debug = 0x2; + } else if (!strcmp(parm[1], "chosen")) { + /*dump multiple frames in selected area*/ + if (parm[6] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + lc_hist_hs = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + lc_hist_he = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + lc_hist_vs = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + lc_hist_ve = val; + if (kstrtoul(parm[6], 10, &val) < 0) + goto free_buf; + lc_hist_prcnt = val; + amlc_debug = 0x4; + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "dump_curve")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + lc_curve_prcnt = val; } else pr_info("unsupprt cmd!\n"); kfree(buf_orig); return count; + +free_buf: + kfree(buf_orig); + return -EINVAL; } @@ -5916,6 +6131,7 @@ static int __exit aml_vecm_remove(struct platform_device *pdev) cancel_work_sync(&aml_lcd_vlock_param_work); #endif probe_ok = 0; + lc_free(); pr_info("[amvecm.] : amvecm_exit.\n"); return 0; } @@ -5961,6 +6177,7 @@ static void amvecm_shutdown(struct platform_device *pdev) #ifdef CONFIG_AML_LCD aml_lcd_notifier_unregister(&aml_lcd_gamma_nb); #endif + lc_free(); } static const struct of_device_id aml_vecm_dt_match[] = { diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index c64fb14451ca..05b2559b9ffd 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -36,7 +36,7 @@ int lc_en; int lc_demo_mode; int lc_en_chflg = 0xff; static int lc_flag = 0xff; -static int lc_szcurve[192]; +static int *lc_szcurve; /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, @@ -418,31 +418,54 @@ static void read_lc_curve(void) { int blk_hnum; int blk_vnum; - int i; + int i, j; unsigned int dwTemp; + unsigned int temp1, temp2; + if (!lc_szcurve) { + pr_amlc_dbg("%s: lc_szcurve not init!", __func__); + return; + } dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); blk_hnum = (dwTemp >> 8) & 0x1f; blk_vnum = (dwTemp) & 0x1f; WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 1); WRITE_VPP_REG(LC_CURVE_RAM_ADDR, 0); - for (i = 0; i < blk_hnum * blk_vnum; i++) { - lc_szcurve[i*2+0] = READ_VPP_REG(LC_CURVE_RAM_DATA); - lc_szcurve[i*2+1] = READ_VPP_REG(LC_CURVE_RAM_DATA); + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + temp1 = READ_VPP_REG(LC_CURVE_RAM_DATA); + temp2 = READ_VPP_REG(LC_CURVE_RAM_DATA); + lc_szcurve[(i*blk_hnum + j)*6+0] = + temp1 & 0x3ff;/*bit0:9*/ + lc_szcurve[(i*blk_hnum + j)*6+1] = + (temp1>>10) & 0x3ff;/*bit10:19*/ + lc_szcurve[(i*blk_hnum + j)*6+2] = + (temp1>>20) & 0x3ff;/*bit20:29*/ + lc_szcurve[(i*blk_hnum + j)*6+3] = + temp2 & 0x3ff;/*bit0:9*/ + lc_szcurve[(i*blk_hnum + j)*6+4] = + (temp2>>10) & 0x3ff;/*bit10:19*/ + lc_szcurve[(i*blk_hnum + j)*6+5] = + (temp2>>20) & 0x3ff;/*bit20:29*/ + } } WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 0); } static void lc_demo_wr_curve(int h_num, int v_num) { - int i, j; + int i, j, temp1, temp2; for (i = 0; i < v_num; i++) { for (j = 0; j < h_num / 2; j++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - lc_szcurve[2 * (i * h_num + j) + 0]); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - lc_szcurve[2 * (i * h_num + j) + 1]); + temp1 = lc_szcurve[6 * (i * h_num + j) + 0] | + (lc_szcurve[6 * (i * h_num + j) + 1] << 10) | + (lc_szcurve[6 * (i * h_num + j) + 2] << 20); + temp2 = lc_szcurve[6 * (i * h_num + j) + 3] | + (lc_szcurve[6 * (i * h_num + j) + 4] << 10) | + (lc_szcurve[6 * (i * h_num + j) + 5] << 20); + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp1); + WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp2); } for (j = h_num / 2; j < h_num; j++) { WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, @@ -455,16 +478,23 @@ static void lc_demo_wr_curve(int h_num, int v_num) static int lc_demo_check_curve(int h_num, int v_num) { - int i, j, temp, flag; + int i, j, temp, temp1, flag; flag = 0; for (i = 0; i < v_num; i++) { for (j = 0; j < h_num / 2; j++) { temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != lc_szcurve[2 * (i * h_num + j) + 0]) + temp1 = lc_szcurve[6 * (i * h_num + j) + 0] | + (lc_szcurve[6 * (i * h_num + j) + 1] << 10) | + (lc_szcurve[6 * (i * h_num + j) + 2] << 20); + if (temp != temp1) flag = (2 * (i * h_num + j) + 0) | (1 << 31); + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != lc_szcurve[2 * (i * h_num + j) + 1]) + temp1 = lc_szcurve[6 * (i * h_num + j) + 3] | + (lc_szcurve[6 * (i * h_num + j) + 4] << 10) | + (lc_szcurve[6 * (i * h_num + j) + 5] << 20); + if (temp != temp1) flag = (2 * (i * h_num + j) + 1) | (1 << 31); } for (j = h_num / 2; j < h_num; j++) { @@ -483,8 +513,12 @@ static int set_lc_curve(int binit, int bcheck) int i, h_num, v_num; unsigned int hvTemp; int rflag; - int temp; + int temp, temp1; + if (!lc_szcurve) { + pr_amlc_dbg("%s: lc_szcurve not init!", __func__); + return -EINVAL; + } rflag = 0; hvTemp = READ_VPP_REG(SRSHARP1_LC_HV_NUM); h_num = (hvTemp >> 8) & 0x1f; @@ -506,9 +540,13 @@ static int set_lc_curve(int binit, int bcheck) else for (i = 0; i < h_num * v_num; i++) { WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - lc_szcurve[2 * i + 0]); + lc_szcurve[6 * i + 0]| + (lc_szcurve[6 * i + 1]<<10)| + (lc_szcurve[6 * i + 2]<<20)); WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - lc_szcurve[2 * i + 1]); + lc_szcurve[6 * i + 3]| + (lc_szcurve[6 * i + 4]<<10)| + (lc_szcurve[6 * i + 5]<<20)); } } WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); @@ -521,10 +559,16 @@ static int set_lc_curve(int binit, int bcheck) else for (i = 0; i < h_num * v_num; i++) { temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != lc_szcurve[2 * i + 0]) + temp1 = lc_szcurve[6 * i + 0]| + (lc_szcurve[6 * i + 1]<<10)| + (lc_szcurve[6 * i + 2]<<20); + if (temp != temp1) rflag = (2 * i + 0) | (1 << 31); temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != lc_szcurve[2 * i + 1]) + temp1 = lc_szcurve[6 * i + 3]| + (lc_szcurve[6 * i + 4]<<10)| + (lc_szcurve[6 * i + 5]<<20); + if (temp != temp1) rflag = (2 * i + 1) | (1 << 31); } WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); @@ -539,6 +583,81 @@ static void lc_fw_curve_iir(struct vframe_s *vf) return; } +/*print statistics hist and curve, vlsi suggest add*/ +unsigned int lc_hist_vs = 4; +unsigned int lc_hist_ve = 6; +unsigned int lc_hist_hs; +unsigned int lc_hist_he = 11; +unsigned int lc_hist_prcnt; +unsigned int lc_curve_prcnt; +static int *lc_hist; + +static void lc_read_region(void) +{ + int i, j, k; + int data32; + int rgb_min, rgb_max; + int dwTemp, blk_hnum, blk_vnum; + + if (!lc_hist) { + pr_amlc_dbg("%s: lc_hist not init!", __func__); + return; + } + WRITE_VPP_REG_BITS(0x4037, 1, 14, 1); + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; + data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); + + for (i = 0; i < blk_vnum; i++) + for (j = 0; j < blk_hnum; j++) { + data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); + if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && + (j >= lc_hist_hs) && (j <= lc_hist_he) && + (amlc_debug == 0x4)) + pr_info("========[r,c](%2d,%2d)======\n", i, j); + + for (k = 0; k < 17; k++) { + data32 = READ_VPP_REG(LC_STTS_HIST_READ_REGION); + lc_hist[(i*blk_hnum+j)*17 + k] = data32; + if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && + (j >= lc_hist_hs) && (j <= lc_hist_he) + && (amlc_debug == 0x4)) { + /*print chosen hist*/ + if (k == 16) {/*last bin*/ + rgb_min = + (data32 >> 10) & 0x3ff; + rgb_max = (data32) & 0x3ff; + pr_info("[%2d]:%d,%d\n", + k, rgb_min, rgb_max); + } else + pr_info("[%2d]:%d\n", + k, data32); + } + } + } + + if (amlc_debug == 0x2)/*print all hist data*/ + for (i = 0; i < 8*12*17; i++) + pr_info("%x\n", lc_hist[i]); +} + +static void lc_prt_curve(void) +{/*print curve node*/ + int i, j; + int dwTemp, blk_hnum, blk_vnum; + + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; + pr_amlc_dbg("======lc_prt curve node=======\n"); + for (i = 0; i < blk_hnum*blk_vnum; i++) { + for (j = 0; j < 6 ; j++) + pr_amlc_dbg("%d\n", lc_szcurve[i*6 + j]); + pr_amlc_dbg("\n"); + } +} + void lc_init(void) { int h_num, v_num; @@ -552,6 +671,14 @@ void lc_init(void) if (!lc_en) return; + lc_szcurve = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!lc_szcurve) + return; + lc_hist = kzalloc(1632 * sizeof(int), GFP_KERNEL); + if (!lc_hist) { + kfree(lc_szcurve); + return; + } lc_top_config(0, h_num, v_num, height, width); lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); @@ -585,11 +712,24 @@ void lc_process(struct vframe_s *vf, lc_config(lc_en, vf, sps_h_en, sps_v_en); read_lc_curve(); - lc_fw_curve_iir(vf); + + if (lc_curve_prcnt > 0) { /*debug lc curve node*/ + lc_prt_curve(); + lc_curve_prcnt--; + } + if (lc_hist_prcnt > 0) { /*debug hist*/ + lc_read_region(); + lc_hist_prcnt--; + } if (set_lc_curve(0, 1)) pr_amlc_dbg("%s: set lc curve fail", __func__); lc_flag = 0xff; } +void lc_free(void) +{ + kfree(lc_szcurve); + kfree(lc_hist); +} diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index 909b441753d1..12f3b02eb805 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -35,12 +35,31 @@ enum lc_mtx_csc_e { LC_MTX_MAX }; +enum lc_reg_lut_e { + SATUR_LUT = 0x1, + YMINVAL_LMT = 0x2, + YPKBV_YMAXVAL_LMT = 0x4, + YPKBV_RAT = 0x8, + YPKBV_SLP_LMT = 0x10, + CNTST_LMT = 0x20, + MAX_REG_LUT +}; + extern int amlc_debug; extern int lc_en; extern int lc_demo_mode; +extern unsigned int lc_hist_vs; +extern unsigned int lc_hist_ve; +extern unsigned int lc_hist_hs; +extern unsigned int lc_hist_he; +extern unsigned int lc_hist_prcnt; +extern unsigned int lc_curve_prcnt; + + extern void lc_init(void); extern void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en); +extern void lc_free(void); #endif From 1ed022f6b9b46f878736a4e6495fcbcf47bc2cef Mon Sep 17 00:00:00 2001 From: Jiacheng Mei Date: Mon, 3 Dec 2018 11:24:51 +0800 Subject: [PATCH 0195/1060] dts: reduce isp memory usage for buildroot [1/1] PD#SWPL-2512 Problem: isp reserved mem too large Solution: reduce isp mem to 256M Verify: g12b-buildroot Change-Id: I8e18f7618a069b43fa288221bca1943d5c3ebcc2 Signed-off-by: Jiacheng Mei --- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index f9e6ba952164..eb322602c8a2 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -163,7 +163,7 @@ compatible = "shared-dma-pool"; reusable; status = "okay"; - size = <0x0 0x1f000000>; + size = <0x0 0x10000000>; alignment = <0x0 0x400000>; }; From a47d1ee55277b0816a87449b0b2c41465af0f8bc Mon Sep 17 00:00:00 2001 From: Jihong Sui Date: Fri, 30 Nov 2018 15:51:21 +0800 Subject: [PATCH 0196/1060] deinterlace: add NR 5 line set for TL1 [1/1] PD#SWPL-2850 Problem: add NR 5 line set for TL1 Solution: add NR setting Verify: TL1 Change-Id: Iba105103a38ec244190f7cefbe66e7d662c7d0a2 Signed-off-by: Jihong Sui --- drivers/amlogic/media/deinterlace/nr_drv.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index 509117bbbb6b..bd0496fdac41 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -280,7 +280,10 @@ static void dnr_config(struct DNR_PARM_s *dnr_parm_p, DI_Wr(DNR_DM_CTRL, Rd(DNR_DM_CTRL)|(1 << 11)); DI_Wr_reg_bits(DNR_CTRL, dnr_en?1:0, 16, 1); /* dm for sd, hd will slower */ - DI_Wr(DNR_CTRL, 0x1df00); + if (is_meson_tl1_cpu()) + DI_Wr(DNR_CTRL, 0x1df00 | (0x03 << 18)); //5 line + else + DI_Wr(DNR_CTRL, 0x1df00); if (is_meson_gxlx_cpu()) { /* disable chroma dm according to baozheng */ DI_Wr_reg_bits(DNR_DM_CTRL, 0, 8, 1); @@ -1187,7 +1190,10 @@ void nr_hw_init(void) { nr_gate_control(true); - DI_Wr(DNR_CTRL, 0x1df00); + if (is_meson_tl1_cpu()) + DI_Wr(DNR_CTRL, 0x1df00|(0x03<<18));//5 line + else + DI_Wr(DNR_CTRL, 0x1df00); DI_Wr(NR3_MODE, 0x3); DI_Wr(NR3_COOP_PARA, 0x28ff00); DI_Wr(NR3_CNOOP_GAIN, 0x881900); From d3696002269dcf30a454feee75182d6cc79930d3 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Mon, 10 Dec 2018 10:21:09 +0800 Subject: [PATCH 0197/1060] ddr: add bandwidth measure support for TL1 [1/1] PD#SWPL-2980 Problem: ddr bandwidth measure is not enabled on TL1 Solution: Add port config and dtsi for TL1 Verify: t962x2_x301 Change-Id: I1fa932a179586f48e3698c53975b64b204a83731 Signed-off-by: Tao Zeng --- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 9 ++++++ drivers/amlogic/ddr_tool/ddr_bandwidth.c | 6 ++-- drivers/amlogic/ddr_tool/ddr_port_desc.c | 40 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index e08b0710512a..22e12257e5b2 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -1386,6 +1386,15 @@ status = "okay"; }; + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { compatible = "amlogic, dmc_monitor"; status = "okay"; diff --git a/drivers/amlogic/ddr_tool/ddr_bandwidth.c b/drivers/amlogic/ddr_tool/ddr_bandwidth.c index 513ed839bc68..941233529524 100644 --- a/drivers/amlogic/ddr_tool/ddr_bandwidth.c +++ b/drivers/amlogic/ddr_tool/ddr_bandwidth.c @@ -522,7 +522,7 @@ static void ddr_extcon_free(void) * to run, so add __ref to indicate it is okay to call __init function * ddr_find_port_desc */ -static int __ref ddr_bandwidth_probe(struct platform_device *pdev) +static int __init ddr_bandwidth_probe(struct platform_device *pdev) { int r = 0; #ifdef CONFIG_OF @@ -664,13 +664,13 @@ static struct platform_driver ddr_bandwidth_driver = { .of_match_table = aml_ddr_bandwidth_dt_match, #endif }, - .probe = ddr_bandwidth_probe, .remove = ddr_bandwidth_remove, }; static int __init ddr_bandwidth_init(void) { - return platform_driver_register(&ddr_bandwidth_driver); + return platform_driver_probe(&ddr_bandwidth_driver, + ddr_bandwidth_probe); } static void __exit ddr_bandwidth_exit(void) diff --git a/drivers/amlogic/ddr_tool/ddr_port_desc.c b/drivers/amlogic/ddr_tool/ddr_port_desc.c index bce96aae833e..190d4ea72b60 100644 --- a/drivers/amlogic/ddr_tool/ddr_port_desc.c +++ b/drivers/amlogic/ddr_tool/ddr_port_desc.c @@ -421,6 +421,41 @@ static struct ddr_port_desc ddr_port_desc_txhd[] __initdata = { { .port_id = 47, .port_name = "DEMOD" } }; +static struct ddr_port_desc ddr_port_desc_tl1[] __initdata = { + { .port_id = 0, .port_name = "ARM" }, + { .port_id = 1, .port_name = "MALI0" }, + { .port_id = 3, .port_name = "HDCP_HDMI" }, + { .port_id = 4, .port_name = "HEVC FRONT" }, + { .port_id = 5, .port_name = "TEST" }, + { .port_id = 6, .port_name = "USB3.0" }, + { .port_id = 7, .port_name = "DEVICE" }, + { .port_id = 8, .port_name = "HEVC BACK" }, + { .port_id = 16, .port_name = "VPU READ1" }, + { .port_id = 17, .port_name = "VPU READ2" }, + { .port_id = 18, .port_name = "VPU READ3" }, + { .port_id = 19, .port_name = "VPU WRITE1" }, + { .port_id = 20, .port_name = "VPU WRITE2" }, + { .port_id = 21, .port_name = "VDEC" }, + { .port_id = 22, .port_name = "HCODEC" }, + { .port_id = 23, .port_name = "GE2D" }, + /* start of each device */ + { .port_id = 32, .port_name = "SPICC1" }, + { .port_id = 33, .port_name = "USB0" }, + { .port_id = 34, .port_name = "DMA" }, + { .port_id = 35, .port_name = "ARB0" }, + { .port_id = 36, .port_name = "SD_EMMC_B" }, + { .port_id = 37, .port_name = "USB1" }, + { .port_id = 38, .port_name = "AUDIO" }, + { .port_id = 39, .port_name = "AIFIFO" }, + { .port_id = 41, .port_name = "PASER" }, + { .port_id = 42, .port_name = "AO CPU" }, + { .port_id = 43, .port_name = "SD_EMMC_C" }, + { .port_id = 44, .port_name = "SPICC2" }, + { .port_id = 45, .port_name = "ETHERNET" }, + { .port_id = 46, .port_name = "SANA" }, + { .port_id = 47, .port_name = "DEMOD" } +}; + static struct ddr_port_desc *chip_ddr_port; static unsigned char chip_ddr_port_num; @@ -489,6 +524,11 @@ int __init ddr_find_port_desc(int cpu_type, struct ddr_port_desc **desc) desc_size = ARRAY_SIZE(ddr_port_desc_g12b); break; + case MESON_CPU_MAJOR_ID_TL1: + *desc = ddr_port_desc_tl1; + desc_size = ARRAY_SIZE(ddr_port_desc_tl1); + break; + default: return -EINVAL; } From df7c217b7f0d692466a2fc3d5c11dfd707506832 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 31 Oct 2018 13:52:37 +0800 Subject: [PATCH 0198/1060] backlight: ldim: add fault reset handle for iw7027 [1/1] PD#SWPL-1161 Problem: sometims iw7027 work failure, need reset to recovery Solution: add reset handler triggered by fault pin Verify: txlx r311 Change-Id: I9c65f0b982ac5e52ff9bd5e43f9df516df2af184 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/backlight/aml_bl.c | 45 ++++-- .../media/vout/backlight/aml_ldim/iw7027_bl.c | 142 +++++++++++++----- .../vout/backlight/aml_ldim/ldim_dev_drv.c | 23 ++- .../media/vout/backlight/aml_ldim/ldim_drv.c | 1 + .../media/vout/backlight/aml_ldim/ldim_drv.h | 3 +- drivers/amlogic/media/vout/lcd/lcd_common.c | 8 +- .../linux/amlogic/media/vout/lcd/aml_ldim.h | 1 + 7 files changed, 161 insertions(+), 62 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index 2d84bdb4916a..3cd7eceebf9a 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -2288,12 +2288,34 @@ static struct notifier_block aml_bl_off_nb = { .priority = LCD_PRIORITY_POWER_BL_OFF, }; +static inline int aml_bl_pwm_vs_lcd_update(struct bl_pwm_config_s *bl_pwm) +{ + unsigned int cnt; + + if (bl_pwm == NULL) { + BLERR("%s: bl_pwm is null\n", __func__); + return 0; + } + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + if (brightness_bypass) + bl_set_duty_pwm(bl_pwm); + else + aml_bl_update_status(bl_drv->bldev); + } + + return 0; +} + static int aml_bl_lcd_update_notifier(struct notifier_block *nb, unsigned long event, void *data) { struct bl_pwm_config_s *bl_pwm = NULL; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + unsigned int *frame_rate; #endif /* If we aren't interested in this event, skip it immediately */ @@ -2308,13 +2330,8 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, case BL_CTRL_PWM: if (bl_drv->bconf->bl_pwm->pwm_port == BL_PWM_VS) { bl_pwm = bl_drv->bconf->bl_pwm; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); } break; case BL_CTRL_PWM_COMBO: @@ -2322,16 +2339,16 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, bl_pwm = bl_drv->bconf->bl_pwm_combo0; else if (bl_drv->bconf->bl_pwm_combo1->pwm_port == BL_PWM_VS) bl_pwm = bl_drv->bconf->bl_pwm_combo1; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING case BL_CTRL_LOCAL_DIMMING: + if (data) { + frame_rate = (unsigned int *)data; + ldim_drv->vsync_change_flag = + (unsigned char)(*frame_rate); + } if (ldim_drv->pwm_vs_update) ldim_drv->pwm_vs_update(); break; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index 187b7233316c..6c123d1d57c0 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -46,9 +46,11 @@ #define IW7027_REG_CHIPID 0x7f #define IW7027_CHIPID 0x28 -#define IW7027_POWER_ON 0 -#define IW7027_POWER_RESET 1 +#define VSYNC_INFO_FREQUENT 30 + static int iw7027_on_flag; +static unsigned short vsync_cnt; +static unsigned short fault_cnt; static DEFINE_MUTEX(iw7027_spi_mutex); @@ -247,8 +249,6 @@ static int iw7027_hw_init_on(void) unsigned char reg_chk, reg_duty_chk; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - /* step 1: system power_on */ ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_on); @@ -295,8 +295,6 @@ static int iw7027_hw_init_on(void) } LDIMPR("%s: calibration done: [%d] = %x\n", __func__, i, reg_duty_chk); - mutex_unlock(&iw7027_spi_mutex); - return 0; } @@ -304,15 +302,11 @@ static int iw7027_hw_init_off(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); - mutex_unlock(&iw7027_spi_mutex); - return 0; } @@ -387,6 +381,48 @@ static int iw7027_spi_dump_dim(char *buf) return len; } +static int fault_cnt_save; +static int fault_check_cnt; +static int iw7027_fault_handler(unsigned int gpio) +{ + unsigned int val; + + if (gpio >= BL_GPIO_NUM_MAX) + return 0; + + if (fault_check_cnt++ > 200) { /* clear fault flag for a cycle */ + fault_check_cnt = 0; + fault_cnt = 0; + fault_cnt_save = 0; + } + + if (ldim_debug_print) { + if (vsync_cnt == 0) { + LDIMPR("%s: fault_cnt: %d, fault_check_cnt: %d\n", + __func__, fault_cnt, fault_check_cnt); + } + } + + val = ldim_gpio_get(gpio); + if (val == 0) + return 0; + + fault_cnt++; + if (fault_cnt_save != fault_cnt) { + fault_cnt_save = fault_cnt; + LDIMPR("%s: fault_cnt: %d\n", __func__, fault_cnt); + } + if (fault_cnt <= 10) { + iw7027_wreg(bl_iw7027->spi, 0x61, 0x0f); + } else { + iw7027_hw_init_on(); + fault_cnt = 0; + fault_cnt_save = 0; + } + + return -1; +} + static unsigned int dim_max, dim_min; static inline unsigned int iw7027_get_value(unsigned int level) { @@ -397,7 +433,6 @@ static inline unsigned int iw7027_get_value(unsigned int level) return val; } -static int smr_cnt; static int iw7027_smr(unsigned short *buf, unsigned char len) { int i; @@ -405,22 +440,22 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) unsigned short *mapping, num; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (smr_cnt++ >= 30) - smr_cnt = 0; + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; if (iw7027_on_flag == 0) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); return 0; } num = ldim_drv->ldev_conf->bl_regnum; if (len != num) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: data len %d invalid\n", __func__, len); return -1; } if (val_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: val_brightness is null\n", __func__); return -1; } @@ -431,9 +466,16 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) dim_max = ldim_drv->ldev_conf->dim_max; dim_min = ldim_drv->ldev_conf->dim_min; + if (ldim_drv->vsync_change_flag == 50) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd7); + ldim_drv->vsync_change_flag = 0; + } else if (ldim_drv->vsync_change_flag == 60) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd3); + ldim_drv->vsync_change_flag = 0; + } if (bl_iw7027->test_mode) { if (test_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("test_brightness is null\n"); return 0; } @@ -458,18 +500,51 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) iw7027_wregs(bl_iw7027->spi, 0x40, val_brightness, (num * 2)); + if (ldim_drv->ldev_conf->fault_check) + iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + mutex_unlock(&iw7027_spi_mutex); + return 0; } +static int iw7027_check(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + int ret = 0; + + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; + + if (iw7027_on_flag == 0) { + if (vsync_cnt == 0) + LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); + return 0; + } + + mutex_lock(&iw7027_spi_mutex); + + if (ldim_drv->ldev_conf->fault_check) + ret = iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + + mutex_unlock(&iw7027_spi_mutex); + + return ret; +} + static int iw7027_power_on(void) { if (iw7027_on_flag) { LDIMPR("%s: iw7027 is already on, exit\n", __func__); return 0; } + + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); iw7027_on_flag = 1; + vsync_cnt = 0; + fault_cnt = 0; + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -477,8 +552,10 @@ static int iw7027_power_on(void) static int iw7027_power_off(void) { + mutex_lock(&iw7027_spi_mutex); iw7027_on_flag = 0; iw7027_hw_init_off(); + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -492,11 +569,7 @@ static ssize_t iw7027_show(struct class *class, int ret = 0; int i; - if (!strcmp(attr->attr.name, "mode")) { - ret = sprintf(buf, "0x%02x\n", bl->spi->mode); - } else if (!strcmp(attr->attr.name, "speed")) { - ret = sprintf(buf, "%d\n", bl->spi->max_speed_hz); - } else if (!strcmp(attr->attr.name, "test")) { + if (!strcmp(attr->attr.name, "test")) { ret = sprintf(buf, "test mode=%d\n", bl->test_mode); } else if (!strcmp(attr->attr.name, "brightness")) { if (test_brightness == NULL) { @@ -511,13 +584,15 @@ static ssize_t iw7027_show(struct class *class, ret = sprintf(buf, "iw7027 status:\n" "dev_index = %d\n" "on_flag = %d\n" + "fault_cnt = %d\n" "en_on = %d\n" "en_off = %d\n" "cs_hold_delay = %d\n" "cs_clk_delay = %d\n" "dim_max = 0x%03x\n" "dim_min = 0x%03x\n", - ldim_drv->dev_index, iw7027_on_flag, + ldim_drv->dev_index, + iw7027_on_flag, fault_cnt, ldim_drv->ldev_conf->en_gpio_on, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->cs_hold_delay, @@ -546,19 +621,9 @@ static ssize_t iw7027_store(struct class *class, int i; if (!strcmp(attr->attr.name, "init")) { + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); - } else if (!strcmp(attr->attr.name, "mode")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->mode = val; - else - LDIMERR("%s: invalid args\n", __func__); - } else if (!strcmp(attr->attr.name, "speed")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->max_speed_hz = val*1000; - else - LDIMERR("%s: invalid args\n", __func__); + mutex_unlock(&iw7027_spi_mutex); } else if (!strcmp(attr->attr.name, "reg")) { if (buf[0] == 'w') { i = sscanf(buf, "w %x %x", &val, &val2); @@ -605,9 +670,7 @@ static ssize_t iw7027_store(struct class *class, } static struct class_attribute iw7027_class_attrs[] = { - __ATTR(init, 0644, iw7027_show, iw7027_store), - __ATTR(mode, 0644, iw7027_show, iw7027_store), - __ATTR(speed, 0644, iw7027_show, iw7027_store), + __ATTR(init, 0644, NULL, iw7027_store), __ATTR(reg, 0644, iw7027_show, iw7027_store), __ATTR(test, 0644, iw7027_show, iw7027_store), __ATTR(brightness, 0644, iw7027_show, iw7027_store), @@ -623,6 +686,7 @@ static int iw7027_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) ldim_drv->device_power_on = iw7027_power_on; ldim_drv->device_power_off = iw7027_power_off; ldim_drv->device_bri_update = iw7027_smr; + ldim_drv->device_bri_check = iw7027_check; return 0; } @@ -636,6 +700,8 @@ int ldim_dev_iw7027_probe(struct aml_ldim_driver_s *ldim_drv) } iw7027_on_flag = 0; + vsync_cnt = 0; + fault_cnt = 0; bl_iw7027 = kzalloc(sizeof(struct iw7027_s), GFP_KERNEL); if (bl_iw7027 == NULL) { diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index b2c02250cf71..037a3d09e41d 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -321,12 +321,21 @@ static int ldim_pwm_pinmux_ctrl(int status) static int ldim_pwm_vs_update(void) { - struct bl_pwm_config_s *bl_pwm = NULL; + struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.pwm_config; + unsigned int cnt; int ret = 0; - bl_pwm = &ldim_dev_config.pwm_config; - bl_pwm_config_init(bl_pwm); - ldim_set_duty_pwm(bl_pwm); + if (bl_pwm->pwm_port != BL_PWM_VS) + return 0; + + if (ldim_debug_print) + LDIMPR("%s\n", __func__); + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + } return ret; } @@ -466,9 +475,11 @@ static void ldim_dev_config_print(void) LDIMPR("%s:\n", __func__); pr_info("valid_flag = %d\n" - "dev_index = %d\n", + "dev_index = %d\n" + "vsync_change_flag = %d\n", ldim_drv->valid_flag, - ldim_drv->dev_index); + ldim_drv->dev_index, + ldim_drv->vsync_change_flag); if (ldim_drv->ldev_conf == NULL) { LDIMERR("%s: device config is null\n", __func__); return; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index bb5e4e6cb46e..7ec078de3694 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -1745,6 +1745,7 @@ static struct aml_ldim_driver_s ldim_driver = { .valid_flag = 0, /* default invalid, active when bl_ctrl_method=ldim */ .dev_index = 0xff, .static_pic_flag = 0, + .vsync_change_flag = 0, .pinmux_flag = 0xff, .ldim_conf = &ldim_config, .ldev_conf = NULL, diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index dfd58f785a62..0875bde52656 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -24,7 +24,8 @@ /*20180730: algorithm clear up */ /*20180820: pq tooling support, espically optimize some alg parameters */ /*20181101: fix ldim_op_func null mistake, add new spi api support */ -#define LDIM_DRV_VER "20181101" +/*20181203: add 50/60hz change & iw7027 error handle support */ +#define LDIM_DRV_VER "20181203" extern unsigned char ldim_debug_print; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index cbbcac6e6236..5edf84921fcb 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -1066,7 +1066,7 @@ int lcd_vmode_change(struct lcd_config_s *pconf) void lcd_venc_change(struct lcd_config_s *pconf) { - unsigned int htotal, vtotal; + unsigned int htotal, vtotal, frame_rate; htotal = lcd_vcbus_read(ENCL_VIDEO_MAX_PXCNT) + 1; vtotal = lcd_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; @@ -1084,8 +1084,10 @@ void lcd_venc_change(struct lcd_config_s *pconf) pconf->lcd_basic.v_period); } - if (pconf->lcd_basic.v_period != vtotal) - aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, NULL); + frame_rate = (pconf->lcd_timing.sync_duration_num * 100) / + pconf->lcd_timing.sync_duration_den; + frame_rate = (frame_rate + 50) / 100; + aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, &frame_rate); } void lcd_if_enable_retry(struct lcd_config_s *pconf) diff --git a/include/linux/amlogic/media/vout/lcd/aml_ldim.h b/include/linux/amlogic/media/vout/lcd/aml_ldim.h index 72cf7efd8ca8..66380831270f 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_ldim.h +++ b/include/linux/amlogic/media/vout/lcd/aml_ldim.h @@ -92,6 +92,7 @@ struct aml_ldim_driver_s { unsigned char valid_flag; unsigned char dev_index; unsigned char static_pic_flag; + unsigned char vsync_change_flag; unsigned char pinmux_flag; struct ldim_config_s *ldim_conf; From e039ad7179e4cfb390d20fc928936281b10bcc3c Mon Sep 17 00:00:00 2001 From: Wenfeng Guo Date: Fri, 7 Dec 2018 16:12:00 +0800 Subject: [PATCH 0199/1060] deinterlace: open pulldown_enable debug node [1/1] PD#SWPL-3003 Problem: pulldown_enable constraintd by DEBUG_SUPPORT Solution: open pulldown_enable debug node Verify: TL1 Change-Id: Ib0a39a718f5e0f171bf9c1d850912bf4afa6a9d5 Signed-off-by: Wenfeng Guo --- drivers/amlogic/media/deinterlace/deinterlace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 3584e544f01a..355aaa3c22bc 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -7440,6 +7440,8 @@ static void set_di_flag(void) use_2_interlace_buff = 0; di_force_bit_mode = 8; } + if (is_meson_tl1_cpu()) + pulldown_enable = true; if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) intr_mode = 3; if (di_pre_rdma_enable) { @@ -8009,8 +8011,8 @@ module_param_named(overturn, overturn, bool, 0664); module_param_named(queue_print_flag, queue_print_flag, int, 0664); module_param_named(full_422_pack, full_422_pack, bool, 0644); module_param_named(cma_print, cma_print, bool, 0644); -#ifdef DEBUG_SUPPORT module_param_named(pulldown_enable, pulldown_enable, bool, 0644); +#ifdef DEBUG_SUPPORT #ifdef RUN_DI_PROCESS_IN_IRQ module_param_named(input2pre, input2pre, uint, 0664); module_param_named(input2pre_buf_miss_count, input2pre_buf_miss_count, From 970b7d39c8c417484c76859629a121be9f8f4c96 Mon Sep 17 00:00:00 2001 From: Sandy Luo Date: Wed, 12 Dec 2018 17:08:31 +0800 Subject: [PATCH 0200/1060] dts: sync difference between arch32 and arch64 [1/1] PD#SWPL-959 Problem: sync arch32 and arch64 dts. Solution: sync arch32 and arch64 dts. Verify: r311 Change-Id: Id411e7dddad0491b16149fe33847e9e282d81a97 Signed-off-by: Sandy Luo --- arch/arm/boot/dts/amlogic/mesonaxg.dtsi | 8 ++++---- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 2 +- arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index 4c61c2d5be99..3bf899700678 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -51,7 +51,7 @@ CPU0:cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x0>; + reg = <0x0>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -61,7 +61,7 @@ CPU1:cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x1>; + reg = <0x1>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -70,7 +70,7 @@ CPU2:cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x2>; + reg = <0x2>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -80,7 +80,7 @@ CPU3:cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x3>; + reg = <0x3>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index 22e12257e5b2..e524bad70691 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -89,7 +89,7 @@ CPU3:cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a9"; - reg = <0x0 0x3>; + reg = <0x3>; //timer=<&timer_d>; enable-method = "psci"; clocks = <&clkc CLKID_CPU_CLK>, diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 2d22f28fdedc..18996fc85ff2 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -79,7 +79,7 @@ CPU3:cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x3>; + reg = <0x3>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; From aa8f5ff77d4db99c4078a3a1eb35622336a522e2 Mon Sep 17 00:00:00 2001 From: Zhongfu Luo Date: Fri, 7 Dec 2018 18:14:38 +0800 Subject: [PATCH 0201/1060] dts: TXLX: defendkey: support secure upgrade check [3/3] PD#SWPL-2344 Problem: TXLX need to support secure upgrade check Solution: add defendkey support in all TXLX dts Verify: TXLX skt board verify pass Change-Id: Ice348161f0a01698bc40e9fb291d1020f478b1fa Signed-off-by: Zhongfu Luo --- arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 7 +++++++ arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 18996fc85ff2..1c13daa4399a 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -938,6 +938,13 @@ compatible = "amlogic, vdac-txlx"; status = "okay"; }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0xff634500 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; }; /* end of / */ &pinctrl_aobus { diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index ff12477ed816..27a312223f2f 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -938,6 +938,13 @@ compatible = "amlogic, vdac-txlx"; status = "okay"; }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0xff634500 0x0 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; }; /* end of / */ &pinctrl_aobus { From 506c54de4be3bddc941d4c20c23264b0aaf51367 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Tue, 11 Dec 2018 04:16:24 -0500 Subject: [PATCH 0202/1060] amvecm: add color primary get ioctrl [1/1] PD#TV-1463 Problem: new interface Solution: add color primary get ioctrl Verify: verify on TL1 Change-Id: I0d4880b6a224be153e80b3eeb11bb5a0352f9ed5 Signed-off-by: MingLiang Dong --- drivers/amlogic/media/enhancement/amvecm/amcsc.c | 15 +++++++++++++++ drivers/amlogic/media/enhancement/amvecm/amcsc.h | 2 +- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 8 ++++++++ include/linux/amlogic/media/amvecm/amvecm.h | 13 ++++++++++--- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.c b/drivers/amlogic/media/enhancement/amvecm/amcsc.c index 1b1391130b1b..12f5f98e78dc 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.c @@ -3736,6 +3736,21 @@ void get_hdr_source_type(void) hdr_source_type = SDR_SOURCE; } +enum color_primary_e get_color_primary(void) +{ + enum color_primary_e color_pri; + + if (signal_color_primaries == 1) + color_pri = VPP_COLOR_PRI_BT709; + else if (signal_color_primaries == 3) + color_pri = VPP_COLOR_PRI_BT601; + else if (signal_color_primaries == 9) + color_pri = VPP_COLOR_PRI_BT2020; + else + color_pri = VPP_COLOR_PRI_NULL; + return color_pri; +} + static void cal_out_curve(uint panel_luma) { int index; diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.h b/drivers/amlogic/media/enhancement/amvecm/amcsc.h index 1657bb1ec616..b0ccbc040126 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.h @@ -106,7 +106,7 @@ extern int amvecm_hdr_dbg(u32 sel); extern u32 get_video_enabled(void); extern void get_hdr_source_type(void); - +extern enum color_primary_e get_color_primary(void); /*hdr*/ /*#define DBG_BUF_SIZE (1024)*/ diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index dd0c94ff27f8..391ebcf8fcb7 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -1305,6 +1305,7 @@ static long amvecm_ioctl(struct file *file, struct ve_pq_load_s vpp_pq_load; struct ve_pq_table_s *vpp_pq_load_table = NULL; int i = 0; + enum color_primary_e color_pri; if (debug_amvecm & 2) pr_info("[amvecm..] %s: cmd_nr = 0x%x\n", @@ -1555,6 +1556,13 @@ static long amvecm_ioctl(struct file *file, &cur_csc_type, sizeof(enum vpp_matrix_csc_e))) ret = -EFAULT; break; + case AMVECM_IOC_G_COLOR_PRI: + argp = (void __user *)arg; + color_pri = get_color_primary(); + if (copy_to_user(argp, + &color_pri, sizeof(enum color_primary_e))) + ret = -EFAULT; + break; case AMVECM_IOC_S_CSCTYPE: if (copy_from_user(&cur_csc_type, (void __user *)arg, diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index 59e88fe6c5e2..ec6cd649c98e 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -146,12 +146,12 @@ enum pq_table_name_e { #define AMVECM_IOC_VE_NEW_DNLP _IOW(_VE_CM, 0x25, struct ve_dnlp_curve_param_s) #define AMVECM_IOC_G_HIST_BIN _IOW(_VE_CM, 0x26, struct vpp_hist_param_s) #define AMVECM_IOC_G_HDR_METADATA _IOW(_VE_CM, 0x27, struct hdr_metadata_info_s) - +/*vpp get color primary*/ +#define AMVECM_IOC_G_COLOR_PRI _IOR(_VE_CM, 0x28, enum color_primary_e) /* VPP.CM IOCTL command list */ #define AMVECM_IOC_LOAD_REG _IOW(_VE_CM, 0x30, struct am_regs_s) - /* VPP.GAMMA IOCTL command list */ #define AMVECM_IOC_GAMMA_TABLE_EN _IO(_VE_CM, 0x40) #define AMVECM_IOC_GAMMA_TABLE_DIS _IO(_VE_CM, 0x41) @@ -224,6 +224,14 @@ struct am_vdj_mode_s { int contrast2; }; +enum color_primary_e { + VPP_COLOR_PRI_NULL = 0, + VPP_COLOR_PRI_BT601, + VPP_COLOR_PRI_BT709, + VPP_COLOR_PRI_BT2020, + VPP_COLOR_PRI_MAX, +}; + enum vpp_matrix_csc_e { VPP_MATRIX_NULL = 0, VPP_MATRIX_RGB_YUV601 = 0x1, @@ -354,7 +362,6 @@ struct am_pq_parm_s { /* READ_CBUS_REG_BITS(x,start,length) */ /* #endif */ - static inline void WRITE_VPP_REG(uint32_t reg, const uint32_t value) { From 5652f1fed3ab48c4be81e3d3ef11aea3d97ed173 Mon Sep 17 00:00:00 2001 From: Zhongfu Luo Date: Thu, 13 Dec 2018 17:06:23 +0800 Subject: [PATCH 0203/1060] dts: GXL: defendkey: modify reserve memory mode [2/2] PD#SWPL-2100 Problem: GXL need to modify reserve memory mode Solution: remove defendkey reserved memory in GXL dts Verify: GXL skt board verify pass Change-Id: Ie5ed01c6dd8f88c5594d6bc73f13282e535071a2 Signed-off-by: Zhongfu Luo --- arch/arm/boot/dts/amlogic/gxl_p212_1g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p212_2g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p230_2g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p231_1g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p231_2g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p241_1g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p400_2g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_p401_2g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts | 6 ------ arch/arm/boot/dts/amlogic/gxl_skt.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts | 6 ------ arch/arm64/boot/dts/amlogic/gxl_skt.dts | 6 ------ 38 files changed, 228 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts index b52a95ada940..0edc32403125 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_1g.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts index 83f756cd6554..e7333d8637ae 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_1g_buildroot.dts @@ -48,12 +48,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts b/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts index 15cb38ef8d2a..868fa5d4d2a2 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_1g_hd.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts index 8293c0bf661a..c03256ed4713 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts @@ -51,12 +51,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts index c82a7ee49c02..f8abcbe4568d 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_2g_buildroot.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts index 6a7feaed8911..c1944cc88ba5 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts @@ -51,12 +51,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index c18a5f767253..bdb46750131d 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -51,12 +51,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts index 624d76c95ed3..5fdbc780e00e 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts @@ -51,12 +51,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts index 9c33a6f59e20..0a35a0dfe4f7 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts @@ -51,12 +51,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index fc41753915de..2365af310a9a 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -48,12 +48,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts index 2216c3664a36..feab09e7e205 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index cbd57822c77c..af46fd2edaec 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts index 3264adc846d2..aa85f76b0ef2 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index 1d314925243c..bd8fa63f3cc1 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts index f4e0c9b1989e..46a4b3276009 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts @@ -46,12 +46,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts index 44e9b023e0e5..2bb9708797db 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts @@ -46,12 +46,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts b/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts index 141f7fd0e4e6..2f447c3deff0 100644 --- a/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_sei210_1g.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts index de1a6c39970e..f68747e8b572 100644 --- a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts @@ -51,12 +51,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x07400000 0x00100000>; diff --git a/arch/arm/boot/dts/amlogic/gxl_skt.dts b/arch/arm/boot/dts/amlogic/gxl_skt.dts index 27af275df244..5ace41afcb84 100644 --- a/arch/arm/boot/dts/amlogic/gxl_skt.dts +++ b/arch/arm/boot/dts/amlogic/gxl_skt.dts @@ -50,12 +50,6 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x08300000 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts index e6d69e7000f8..c4767fccfc99 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts index 89845aa05623..46a3d5aadf14 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts @@ -48,12 +48,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts index 351bb1b4f383..85f64e4ca09b 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g_hd.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index 93f9ab508bda..df862e17defe 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts index 48305660a903..353e3d077d64 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts index e41e85bdcbb5..101ad78b2091 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index 2df82971ab30..5c38487443f2 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts index e634c4f0dcfd..7d8d55ab43b9 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts index d371e29b0a74..ba85a853779d 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 621b53852742..92f6e7d9ceef 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -48,12 +48,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts index b1a03cfc974e..dadb59aed48a 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index fc00c40eb486..2a7245aff17a 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts index 80f807f48969..f569d0799fc5 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index 5cc454c23746..6bfe499fead6 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts index 797233b66f08..bb6cc479e20c 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts @@ -46,12 +46,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts index 6232fc7e1d31..f316571920da 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts @@ -46,12 +46,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts index ada88fe85398..916f139309e5 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_sei210_1g.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts index d2e010ec5ee5..5140780d2f7f 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts @@ -51,12 +51,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; diff --git a/arch/arm64/boot/dts/amlogic/gxl_skt.dts b/arch/arm64/boot/dts/amlogic/gxl_skt.dts index 13cd67a6030b..b78105139352 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_skt.dts @@ -50,12 +50,6 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - - defendkey_reserved:linux,defendkey { - compatible = "amlogic, defendkey"; - reg = <0x0 0x08300000 0x0 0x100000>; - }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; From a48c7fec05fc31b11bf2f64e9ed137d39242fbbb Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Thu, 29 Nov 2018 14:28:43 +0800 Subject: [PATCH 0204/1060] tvin: vdin: fix vdin CMA layout adaptation [1/1] PD#SWPL-2526 Problem: 1.CMA layout adaptation cause crash 2.vdin buff dump error 3.read_pic error Solution: 1.codec mm has be moved to high memory area, we should map memory use vmap. 2.make vdin high mem and low mem to be compatible when we dump vdin buff. 3.fix read_pic bug. Verify: TXLX R311 Change-Id: I90e4f46ba91d38c6ce0f8bfd65b5c22e6be3b83f Signed-off-by: Xuhua Zhang --- .../amlogic/media/vin/tvin/vdin/vdin_afbce.c | 2 +- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 310 ++++++++++++++---- 2 files changed, 251 insertions(+), 61 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index eaa9d734e4bb..6a058226102c 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -69,7 +69,7 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) char vdin_name[6]; unsigned int mem_size, h_size, v_size; int flags = CODEC_MM_FLAGS_CMA_FIRST|CODEC_MM_FLAGS_CMA_CLEAR| - CODEC_MM_FLAGS_CPU; + CODEC_MM_FLAGS_DMA; unsigned int max_buffer_num = min_buf_num; unsigned int i; /*afbce head need 1036800 byte at most*/ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index cf16fb1f027e..e7341d07bba9 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include /* Local Headers */ @@ -273,7 +274,11 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, struct file *filp = NULL; loff_t pos = 0; void *buf = NULL; - unsigned int i; + unsigned int i, j; + unsigned int span = 0, count = 0; + int highmem_flag; + unsigned long highaddr; + unsigned long phys; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); @@ -288,7 +293,22 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, pr_info("%s:no cma alloc mem!!!\n", __func__); return; } - if (buf_num < devp->canvas_max_num) { + + if (buf_num >= devp->canvas_max_num) { + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + pr_info("buf_num > canvas_max_num, vdin exit dump\n"); + return; + } + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + pr_info("low mem area\n"); if (devp->cma_config_flag == 0x1) buf = codec_mm_phys_to_virt(devp->mem_start + devp->canvas_max_size*buf_num); @@ -307,6 +327,33 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, /*vfs_write(filp, buf, devp->canvas_max_size, &pos);*/ pr_info("write buffer %2d of %2u to %s.\n", buf_num, devp->canvas_max_num, path); + } else { + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + + if (devp->cma_config_flag == 0x1) + phys = devp->mem_start + devp->canvas_max_size*buf_num; + else if (devp->cma_config_flag == 0x101) + phys = devp->vfmem_start[buf_num]; + else if (devp->cma_config_flag == 0x100) + phys = devp->vfmem_start[buf_num]; + else + phys = devp->mem_start + devp->canvas_max_size*buf_num; + + for (j = 0; j < count; j++) { + highaddr = phys + j * devp->canvas_w; + buf = codec_mm_vmap(highaddr, span); + if (!buf) { + pr_info("codec_mm_vmap error\n"); + return; + } + + vfs_write(filp, buf, span, &pos); + codec_mm_unmap_phyaddr(buf); + } + pr_info("high-mem write buffer %2d of %2u to %s.\n", + buf_num, devp->canvas_max_num, path); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -317,15 +364,20 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) { struct file *filp = NULL; loff_t pos = 0; - loff_t i = 0, j = 0; - unsigned int mem_size = 0; + loff_t mem_size = 0; + unsigned int i = 0, j = 0; + unsigned int span = 0; + unsigned int count = 0; + unsigned long highaddr; + unsigned long phys; + int highmem_flag; void *buf = NULL; void *vfbuf[VDIN_CANVAS_MAX_CNT]; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); filp = filp_open(path, O_RDWR|O_CREAT, 0666); - mem_size = devp->canvas_active_w * devp->canvas_h; + mem_size = (loff_t)devp->canvas_active_w * devp->canvas_h; for (i = 0; i < VDIN_CANVAS_MAX_CNT; i++) vfbuf[i] = NULL; if (IS_ERR(filp)) { @@ -337,33 +389,77 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) pr_info("%s:no cma alloc mem!!!\n", __func__); return; } - for (i = 0; i < devp->canvas_max_num; i++) { - pos = mem_size * i; - if (devp->cma_config_flag == 0x1) - buf = codec_mm_phys_to_virt(devp->mem_start + - devp->canvas_max_size*i); - else if (devp->cma_config_flag == 0x101) - vfbuf[i] = codec_mm_phys_to_virt( - devp->vfmem_start[i]); - else if (devp->cma_config_flag == 0x100) - vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); - else - buf = phys_to_virt(devp->mem_start + - devp->canvas_max_size*i); - /*only write active data*/ - for (j = 0; j < devp->canvas_h; j++) { - if (devp->cma_config_flag & 0x100) { - vfs_write(filp, vfbuf[i], - devp->canvas_active_w, &pos); - vfbuf[i] += devp->canvas_w; - } else { - vfs_write(filp, buf, - devp->canvas_active_w, &pos); - buf += devp->canvas_w; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + /*low mem area*/ + pr_info("low mem area\n"); + for (i = 0; i < devp->canvas_max_num; i++) { + pos = mem_size * i; + if (devp->cma_config_flag == 0x1) + buf = codec_mm_phys_to_virt(devp->mem_start + + devp->canvas_max_size*i); + else if (devp->cma_config_flag == 0x101) + vfbuf[i] = codec_mm_phys_to_virt( + devp->vfmem_start[i]); + else if (devp->cma_config_flag == 0x100) + vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); + else + buf = phys_to_virt(devp->mem_start + + devp->canvas_max_size*i); + /*only write active data*/ + for (j = 0; j < devp->canvas_h; j++) { + if (devp->cma_config_flag & 0x100) { + vfs_write(filp, vfbuf[i], + devp->canvas_active_w, &pos); + vfbuf[i] += devp->canvas_w; + } else { + vfs_write(filp, buf, + devp->canvas_active_w, &pos); + buf += devp->canvas_w; + } } + pr_info("write buffer %2d of %2u to %s.\n", + i, devp->canvas_max_num, path); + } + } else { + /*high mem area*/ + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + + for (i = 0; i < devp->canvas_max_num; i++) { + pos = mem_size * i; + if (devp->cma_config_flag == 0x1) { + phys = devp->mem_start + + devp->canvas_max_size*i; + } else if (devp->cma_config_flag == 0x101) + phys = devp->vfmem_start[i]; + else if (devp->cma_config_flag == 0x100) + phys = devp->vfmem_start[i]; + else { + phys = devp->mem_start + + devp->canvas_max_size*i; + } + + for (j = 0; j < count; j++) { + highaddr = phys + j * devp->canvas_w; + buf = codec_mm_vmap(highaddr, span); + if (!buf) { + pr_info("codec_mm_vmap error\n"); + return; + } + + vfs_write(filp, buf, span, &pos); + codec_mm_unmap_phyaddr(buf); + } + pr_info("high-mem write buffer %2d of %2u to %s.\n", + i, devp->canvas_max_num, path); } - pr_info("write buffer %lld of %2u to %s.\n", - i, devp->canvas_max_num, path); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -378,6 +474,14 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, void *buf_head = NULL; void *buf_table = NULL; void *buf_body = NULL; + unsigned long highaddr; + unsigned long phys; + int highmem_flag = 0; + unsigned int span = 0; + unsigned int remain = 0; + unsigned int count = 0; + unsigned int j = 0; + void *vbuf = NULL; unsigned char buff[100]; mm_segment_t old_fs = get_fs(); @@ -392,30 +496,54 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } - if (devp->cma_config_flag == 0x101) { - buf_head = codec_mm_phys_to_virt( - devp->afbce_info->fm_head_paddr[buf_num]); - buf_table = codec_mm_phys_to_virt( - devp->afbce_info->fm_table_paddr[buf_num]); - buf_body = codec_mm_phys_to_virt( - devp->afbce_info->fm_body_paddr[buf_num]); + if (devp->cma_config_flag == 0x101) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + /*low mem area*/ + pr_info("low mem area\n"); + if (devp->cma_config_flag == 0x101) { + buf_head = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = codec_mm_phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } else if (devp->cma_config_flag == 0) { + buf_head = phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } + } else { + /*high mem area*/ + pr_info("high mem area\n"); + buf_head = codec_mm_vmap( + devp->afbce_info->fm_head_paddr[buf_num], + devp->afbce_info->frame_head_size); + + buf_table = codec_mm_vmap( + devp->afbce_info->fm_table_paddr[buf_num], + devp->afbce_info->frame_table_size); pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", devp->afbce_info->fm_head_paddr[buf_num], (devp->afbce_info->fm_table_paddr[buf_num]), devp->afbce_info->fm_body_paddr[buf_num]); - } else if (devp->cma_config_flag == 0) { - buf_head = phys_to_virt( - devp->afbce_info->fm_head_paddr[buf_num]); - buf_table = phys_to_virt( - devp->afbce_info->fm_table_paddr[buf_num]); - buf_body = phys_to_virt( - devp->afbce_info->fm_body_paddr[buf_num]); - - pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->fm_head_paddr[buf_num], - (devp->afbce_info->fm_table_paddr[buf_num]), - devp->afbce_info->fm_body_paddr[buf_num]); } set_fs(KERNEL_DS); @@ -459,7 +587,40 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, pr_info("create %s body error.\n", buff); return; } - vfs_write(filp, buf_body, devp->afbce_info->frame_body_size, &pos); + if (highmem_flag == 0) { + vfs_write(filp, buf_body, + devp->afbce_info->frame_body_size, &pos); + } else { + span = SZ_1M; + count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span); + remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span); + phys = devp->afbce_info->fm_body_paddr[buf_num]; + + for (j = 0; j < count; j++) { + highaddr = phys + j * span; + vbuf = codec_mm_vmap(highaddr, span); + if (!vbuf) { + pr_info("codec_mm_vmap error\n"); + return; + } + + vfs_write(filp, vbuf, span, &pos); + codec_mm_unmap_phyaddr(vbuf); + } + + if (remain) { + span = devp->afbce_info->frame_body_size - remain; + highaddr = phys + span; + vbuf = codec_mm_vmap(highaddr, remain); + if (!vbuf) { + pr_info("codec_mm_vmap1 error\n"); + return; + } + + vfs_write(filp, vbuf, span, &pos); + codec_mm_unmap_phyaddr(vbuf); + } + } pr_info("write buffer %2d of %2u body to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -946,8 +1107,10 @@ static void vdin_write_mem( mm_segment_t old_fs; void *dts = NULL; long val; - int index; + int index, j, span; + int highmem_flag, count; unsigned long addr; + unsigned long highaddr; struct vf_pool *p = devp->vfp; /* vtype = simple_strtol(type, NULL, 10); */ @@ -996,15 +1159,42 @@ static void vdin_write_mem( addr = canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr); /* dts = ioremap(canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr), */ /* real_size); */ - dts = phys_to_virt(addr); - size = vfs_read(filp, dts, devp->canvas_max_size, &pos); - pr_info("warning: %s read %u < %u\n", - __func__, size, devp->canvas_max_size); - vfs_fsync(filp, 0); - iounmap(dts); - filp_close(filp, NULL); - set_fs(old_fs); + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + pr_info("low mem area\n"); + dts = phys_to_virt(addr); + for (j = 0; j < devp->canvas_h; j++) { + vfs_read(filp, dts+(devp->canvas_w*j), + devp->canvas_active_w, &pos); + } + vfs_fsync(filp, 0); + iounmap(dts); + filp_close(filp, NULL); + set_fs(old_fs); + } else { + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + for (j = 0; j < count; j++) { + highaddr = addr + j * devp->canvas_w; + dts = codec_mm_vmap(highaddr, span); + if (!dts) { + pr_info("codec_mm_vmap error\n"); + return; + } + vfs_read(filp, dts, span, &pos); + codec_mm_unmap_phyaddr(dts); + } + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + } + if (vtype == 8) { old_fs = get_fs(); set_fs(KERNEL_DS); @@ -1020,7 +1210,7 @@ static void vdin_write_mem( u8 *c = devp->vfp->dv_buf_ori[index]; pos = 0; - size = vfs_read(md_flip, + size = (unsigned int)vfs_read(md_flip, devp->vfp->dv_buf_ori[index], 4096, &pos); p->dv_buf_size[index] = size; From fc4c5d6c365f032a3ad9cfb8a76826422eb20345 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Thu, 13 Dec 2018 16:41:49 +0800 Subject: [PATCH 0205/1060] tvin: vdin: vdin add afbce write back to memory interface [1/1] PD#SWPL-3200 Problem: vdin add afbce need more debug method. Solution: vdin add read_pic_afbce debug interface Verify: TL1 X301 Change-Id: I45a741ba20409dc25b41ce316b0df0dce9d2dc28 Signed-off-by: Xuhua Zhang --- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index e7341d07bba9..fcaa930b389f 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -1097,6 +1097,93 @@ static void vdin_dump_histgram(struct vdin_dev_s *devp) } } +/*type: 1:nv21 2:yuv422 3:yuv444*/ +static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) +{ + char *md_path_head = "/storage/B8F7-DBD0/afbce/a0_1header.bin"; + char *md_path_body = "/storage/B8F7-DBD0/afbce/a0_1body.bin"; + unsigned int i; + unsigned int size = 0; + long val; + struct file *filp = NULL; + loff_t pos = 0; + mm_segment_t old_fs; + void *head_dts = NULL; + void *body_dts = NULL; + + if (kstrtol(type, 10, &val) < 0) + return; + + if (!devp->curr_wr_vfe) { + devp->curr_wr_vfe = provider_vf_get(devp->vfp); + if (!devp->curr_wr_vfe) { + pr_info("no buffer to write.\n"); + return; + } + } + + i = devp->curr_wr_vfe->af_num; + devp->curr_wr_vfe->vf.type = VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | VIDTYPE_COMPRESS | VIDTYPE_SCATTER; + switch (val) { + case 1: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_NV21; + break; + case 2: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_422; + break; + case 3: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_444; + break; + default: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_422; + break; + } + + devp->curr_wr_vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + devp->curr_wr_vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; + + head_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_head_paddr[i]); + body_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_body_paddr[i]); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + pr_info("head bin file path = %s\n", md_path_head); + filp = filp_open(md_path_head, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_info("read %s error.\n", md_path_head); + return; + } + + size = vfs_read(filp, head_dts, + devp->afbce_info->frame_head_size, &pos); + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + + pos = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pr_info("body bin file path = %s\n", md_path_body); + filp = filp_open(md_path_body, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_info("read %s error.\n", md_path_body); + return; + } + + size = vfs_read(filp, body_dts, + devp->afbce_info->frame_body_size, &pos); + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + + provider_vf_put(devp->curr_wr_vfe, devp->vfp); + devp->curr_wr_vfe = NULL; + vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); +} static void vdin_write_mem( struct vdin_dev_s *devp, char *type, char *path, char *md_path) @@ -1699,6 +1786,11 @@ start_chk: #endif } else if (!strcmp(parm[0], "force_recycle")) { devp->flags |= VDIN_FLAG_FORCE_RECYCLE; + } else if (!strcmp(parm[0], "read_pic_afbce")) { + if (parm[1]) + vdin_write_afbce_mem(devp, parm[1]); + else + pr_err("miss parameters.\n"); } else if (!strcmp(parm[0], "read_pic")) { if (parm[1] && parm[2]) vdin_write_mem(devp, parm[1], parm[2], parm[3]); From 1b1517de6f5870bb38ab89145fa45e9daf2f73b5 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Thu, 13 Dec 2018 16:53:27 +0800 Subject: [PATCH 0206/1060] suspend: power: plug off the secondary cpus for freeze mode [1/1] PD#SWPL-2399 Problem: freeze mode can not kill the secondary cpus Solution: move the cpu kill function before the freeze function Verify: tl1 test success Change-Id: I1da7cb8bcd800b8372fd152490eadd4ef3866ece Signed-off-by: zhiqiang liang --- kernel/power/suspend.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 2d0c99b3f34c..678e8fa9d466 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -360,6 +360,25 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) if (suspend_test(TEST_PLATFORM)) goto Platform_wake; +#ifdef CONFIG_AMLOGIC_MODIFY + error = disable_nonboot_cpus(); + if (error || suspend_test(TEST_CPUS)) { + log_suspend_abort_reason("Disabling non-boot cpus failed"); + goto Enable_cpus; + } + /* + * PM_SUSPEND_FREEZE equals + * frozen processes + suspended devices + idle processors. + * Thus we should invoke freeze_enter() soon after + * all the devices are suspended. + */ + if (state == PM_SUSPEND_FREEZE) { + trace_suspend_resume(TPS("machine_suspend"), state, true); + freeze_enter(); + trace_suspend_resume(TPS("machine_suspend"), state, false); + goto Enable_cpus; + } +#else /* * PM_SUSPEND_FREEZE equals * frozen processes + suspended devices + idle processors. @@ -378,6 +397,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) log_suspend_abort_reason("Disabling non-boot cpus failed"); goto Enable_cpus; } +#endif arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); From 8430f6386cb5fe2da834bd1783f8aa6914ab0594 Mon Sep 17 00:00:00 2001 From: Qiufang Dai Date: Fri, 14 Dec 2018 17:19:28 +0800 Subject: [PATCH 0207/1060] suspend: remote: do not do suspend action under freeze mode [1/1] PD#SWPL-2399 Problem: Miss IR (power) key value when wakeup from freeze. Solution: Do not suspend/resume IR device under freeze mode Verify: x301_tl1 Change-Id: I7bdf0b847fa1a8b96bb2896426e15faf8143e820 Signed-off-by: Qiufang Dai --- drivers/amlogic/input/remote/remote_meson.c | 6 ++++++ include/linux/amlogic/pm.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/amlogic/input/remote/remote_meson.c b/drivers/amlogic/input/remote/remote_meson.c index 9458ee14929c..cba24836aa19 100644 --- a/drivers/amlogic/input/remote/remote_meson.c +++ b/drivers/amlogic/input/remote/remote_meson.c @@ -707,6 +707,9 @@ static int remote_resume(struct device *dev) unsigned long flags; unsigned char cnt; + if (is_pm_freeze_mode()) + return 0; + dev_info(dev, "remote resume\n"); /*resume register config*/ spin_lock_irqsave(&chip->slock, flags); @@ -745,6 +748,9 @@ static int remote_suspend(struct device *dev) { struct remote_chip *chip = dev_get_drvdata(dev); + if (is_pm_freeze_mode()) + return 0; + dev_info(dev, "remote suspend\n"); disable_irq(chip->irqno); return 0; diff --git a/include/linux/amlogic/pm.h b/include/linux/amlogic/pm.h index 2d71273aec3c..dd1d1d3e108f 100644 --- a/include/linux/amlogic/pm.h +++ b/include/linux/amlogic/pm.h @@ -51,6 +51,8 @@ struct early_suspend { extern void register_early_suspend(struct early_suspend *handler); extern void unregister_early_suspend(struct early_suspend *handler); extern unsigned int lgcy_early_suspend_init(void); +extern unsigned int is_pm_freeze_mode(void); + #endif //CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND From 80e3c76bad61e91189c953b665dcd89baa6803cd Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Mon, 10 Dec 2018 17:07:06 +0800 Subject: [PATCH 0208/1060] amvecm: add local contrast iir SW algorithm [1/1] PD#SWPL-2587 Problem: local contrast SW algorithm Solution: add local contrast SW iir algorithm support Verify: x301 Change-Id: I8c80ce3fa5252585d5dd4a15e72beb9c0bfd5d7f Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 91 ++- .../media/enhancement/amvecm/local_contrast.c | 581 ++++++++++++++++-- .../media/enhancement/amvecm/local_contrast.h | 17 +- 3 files changed, 627 insertions(+), 62 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 391ebcf8fcb7..ce3a129b76ce 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5519,6 +5519,20 @@ static ssize_t amvecm_lc_show(struct class *cla, "echo dump_hist chosen hs he vs ve cnt > /sys/class/amvecm/lc\n"); len += sprintf(buf+len, "echo dump_curve cnt > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_osd_setting show > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_osd_setting set xxx ... xxx > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo osd_iir_en val > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo iir_refresh show > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo iir_refresh set xxx ... xxx > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo scene_change_th val > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo irr_dbg_en val > /sys/class/amvecm/lc\n"); return len; } @@ -5596,9 +5610,9 @@ static ssize_t amvecm_lc_store(struct class *cls, pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "dump_hist")) { if (!strcmp(parm[1], "all")) { - /*dump all hist in one frame*/ + /*dump all hist of one frame*/ lc_hist_prcnt = 1; - amlc_debug = 0x2; + amlc_debug = 0x8; } else if (!strcmp(parm[1], "chosen")) { /*dump multiple frames in selected area*/ if (parm[6] == NULL) @@ -5618,13 +5632,83 @@ static ssize_t amvecm_lc_store(struct class *cls, if (kstrtoul(parm[6], 10, &val) < 0) goto free_buf; lc_hist_prcnt = val; - amlc_debug = 0x4; + amlc_debug = 0x6; } else pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "dump_curve")) { if (kstrtoul(parm[1], 10, &val) < 0) goto free_buf; lc_curve_prcnt = val; + } else if (!strcmp(parm[0], "lc_osd_setting")) { + if (!strcmp(parm[1], "show")) { + pr_info("VNUM_STRT_BELOW: %d, VNUM_END_BELOW: %d\n", + vnum_start_below, vnum_end_below); + pr_info("VNUM_STRT_ABOVE: %d, VNUM_END_ABOVE: %d\n", + vnum_start_above, vnum_end_above); + pr_info("INVALID_BLK: %d, MIN_BV_PERCENT_TH: %d\n", + invalid_blk, min_bv_percent_th); + } else if (!strcmp(parm[1], "set")) { + if (parm[7] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + vnum_start_below = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + vnum_end_below = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + vnum_start_above = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + vnum_end_above = val; + if (kstrtoul(parm[6], 10, &val) < 0) + goto free_buf; + invalid_blk = val; + if (kstrtoul(parm[7], 10, &val) < 0) + goto free_buf; + min_bv_percent_th = val; + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "osd_iir_en")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + osd_iir_en = val; + } else if (!strcmp(parm[0], "iir_refresh")) { + if (!strcmp(parm[1], "show")) { + pr_info("current state: alpha1: %d, alpha2: %d, refresh_bit: %d, ts: %d\n", + alpha1, alpha2, refresh_bit, ts); + } else if (!strcmp(parm[1], "set")) { + if (parm[5] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + alpha1 = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + alpha2 = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + refresh_bit = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + ts = val; + pr_info("after setting: alpha1: %d, alpha2: %d, refresh_bit: %d, ts: %d\n", + alpha1, alpha2, refresh_bit, ts); + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "scene_change_th")) { + pr_info("current value: %d\n", scene_change_th); + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + scene_change_th = val; + pr_info("setting value: %d\n", scene_change_th); + } else if (!strcmp(parm[0], "irr_dbg_en")) { + pr_info("current value: %d\n", amlc_iir_debug_en); + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + amlc_iir_debug_en = val; + pr_info("setting value: %d\n", amlc_iir_debug_en); } else pr_info("unsupprt cmd!\n"); @@ -5632,6 +5716,7 @@ static ssize_t amvecm_lc_store(struct class *cls, return count; free_buf: + pr_info("Missing parameters !\n"); kfree(buf_orig); return -EINVAL; } diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 05b2559b9ffd..8aeb10df9a96 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -25,6 +25,12 @@ #include "arch/vpp_regs.h" #include "local_contrast.h" +/*may define in other module*/ +#define CURV_NODES 6 +/*history message delay*/ +#define N 4 +/*hist bin num*/ +#define HIST_BIN 16 int amlc_debug; #define pr_amlc_dbg(fmt, args...)\ do {\ @@ -36,7 +42,39 @@ int lc_en; int lc_demo_mode; int lc_en_chflg = 0xff; static int lc_flag = 0xff; -static int *lc_szcurve; +int osd_iir_en = 1; +int amlc_iir_debug_en; +/*osd related setting */ +int vnum_start_below = 5; +int vnum_end_below = 6; +int vnum_start_above = 1; +int vnum_end_above = 2; +int invalid_blk = 2; +/*u10,7000/21600=0.324*1024=331 */ +int min_bv_percent_th = 331; +/*control the refresh speed*/ +int alpha1 = 32; +int alpha2 = 2; +int refresh_bit = 12; +int ts = 6; +/*need tuning according to real situation ! (0~512)*/ +int scene_change_th = 50; + +/*chose block to get hist*/ +unsigned int lc_hist_vs; +unsigned int lc_hist_ve; +unsigned int lc_hist_hs; +unsigned int lc_hist_he; +/*lc curve data and hist data*/ +static int *lc_szcurve;/*12*8*6+4*/ +static int *curve_nodes_cur; +static int *curve_nodes_pre; +static int *lc_hist;/*12*8*17*/ +static bool lc_malloc_ok; +/*print one or more frame data*/ +unsigned int lc_hist_prcnt; +unsigned int lc_curve_prcnt; + /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, @@ -414,21 +452,11 @@ static void lc_config(int enable, lc_stts_en(enable, height, width, 0, 0, 1, 1, 4); } -static void read_lc_curve(void) +static void read_lc_curve(int blk_vnum, int blk_hnum) { - int blk_hnum; - int blk_vnum; int i, j; - unsigned int dwTemp; unsigned int temp1, temp2; - if (!lc_szcurve) { - pr_amlc_dbg("%s: lc_szcurve not init!", __func__); - return; - } - dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); - blk_hnum = (dwTemp >> 8) & 0x1f; - blk_vnum = (dwTemp) & 0x1f; WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 1); WRITE_VPP_REG(LC_CURVE_RAM_ADDR, 0); for (i = 0; i < blk_vnum; i++) { @@ -459,11 +487,15 @@ static void lc_demo_wr_curve(int h_num, int v_num) for (i = 0; i < v_num; i++) { for (j = 0; j < h_num / 2; j++) { temp1 = lc_szcurve[6 * (i * h_num + j) + 0] | - (lc_szcurve[6 * (i * h_num + j) + 1] << 10) | - (lc_szcurve[6 * (i * h_num + j) + 2] << 20); + (lc_szcurve[6 * + (i * h_num + j) + 1] << 10) | + (lc_szcurve[6 * + (i * h_num + j) + 2] << 20); temp2 = lc_szcurve[6 * (i * h_num + j) + 3] | - (lc_szcurve[6 * (i * h_num + j) + 4] << 10) | - (lc_szcurve[6 * (i * h_num + j) + 5] << 20); + (lc_szcurve[6 * + (i * h_num + j) + 4] << 10) | + (lc_szcurve[6 * + (i * h_num + j) + 5] << 20); WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp1); WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp2); } @@ -515,10 +547,6 @@ static int set_lc_curve(int binit, int bcheck) int rflag; int temp, temp1; - if (!lc_szcurve) { - pr_amlc_dbg("%s: lc_szcurve not init!", __func__); - return -EINVAL; - } rflag = 0; hvTemp = READ_VPP_REG(SRSHARP1_LC_HV_NUM); h_num = (hvTemp >> 8) & 0x1f; @@ -576,37 +604,449 @@ static int set_lc_curve(int binit, int bcheck) return rflag; } - -static void lc_fw_curve_iir(struct vframe_s *vf) +/* + *function: detect osd and provide osd signal status + *output: + * osd_flag_cnt: signal indicate osd exist (process) + * frm_cnt: signal that record the sudden + * moment osd appear or disappear + */ +static int osd_det_func(int *osd_flag_cnt, + int *frm_cnt, + int blk_hist_sum, + int *lc_hist, + int blk_hnum, + int osd_vnum_strt, + int osd_vnum_end) { - if (!vf) - return; + int i, j; + int min_bin_value, min_bin_percent; + int osd_flag; + int valid_blk; + int percent_norm = (1<<10) - 1; + static int osd_hist_cnt; + + osd_flag = 0; + min_bin_value = 0; + + /*1.1, case 1: osd below,e.g. vnum=5,6(0~7)*/ + osd_hist_cnt = 0; + for (i = osd_vnum_strt; i <= osd_vnum_end; i++) {/*two line*/ + for (j = 0; j < blk_hnum; j++) { + min_bin_value = + lc_hist[(i*blk_hnum + j) * + (HIST_BIN + 1) + 0];/*first bin*/ + /*black osd means first bin value very large*/ + min_bin_percent = + (min_bin_value * percent_norm) / + (blk_hist_sum + 1); + if (min_bin_percent > min_bv_percent_th) + osd_hist_cnt++;/*black bin count*/ + if (amlc_debug == 0x2) + pr_info("v2-1:osd_hist_cnt:%d, min_bin_percent:%d, (th:%d)\n", + osd_hist_cnt, + min_bin_percent, + min_bv_percent_th); + } + } + /*how many block osd occupy*/ + valid_blk = (osd_vnum_end - osd_vnum_strt + 1) * blk_hnum - + invalid_blk; + /*we suppose when osd appear, + * 1)it came in certain area, + * 2)and almost all those area are black + */ + if (osd_hist_cnt > valid_blk) + osd_flag_cnt[1] = 1; + else + osd_flag_cnt[1] = 0; + /*detect the moment osd appear and disappear:*/ + osd_flag = ((osd_flag_cnt[1]&(~(osd_flag_cnt[0]))) + + ((~(osd_flag_cnt[1])) & osd_flag_cnt[0]));/*a^b*/ + /*set osd appear and disappear heavy iir time*/ + if (osd_flag && osd_iir_en) + *frm_cnt = 60 * ts; + + /*debug*/ + if ((amlc_iir_debug_en == 10) || (amlc_debug == 0x2)) { + pr_info("osd_log v2:osd_flag_cnt[0]:%d,osd_flag_cnt[1]:%d,osd_flag:%d,frm_cnt:%d\n", + osd_flag_cnt[0], + osd_flag_cnt[1], + osd_flag, + *frm_cnt); + if (*frm_cnt <= 0) + amlc_iir_debug_en = 0; + } + + return 0; } -/*print statistics hist and curve, vlsi suggest add*/ -unsigned int lc_hist_vs = 4; -unsigned int lc_hist_ve = 6; -unsigned int lc_hist_hs; -unsigned int lc_hist_he = 11; -unsigned int lc_hist_prcnt; -unsigned int lc_curve_prcnt; -static int *lc_hist; +/* + *note 1: osd appear in 5,6(0,1,2,...7) line in Vnum = 8 situation + * if Vnum changed, debug osd location, find + * vnum_start_below, vnum_end_below(osd below situation,above situation is same) + * + * note 2: here just consider 2 situation: osd appear below or appear above + * + * function: 2 situation osd detect and provide + * osd status signal(osd_flag_cnt&frm_cnt) + */ +static int osd_detect(int *osd_flag_cnt_above, + int *osd_flag_cnt_below, + int *frm_cnt_above, + int *frm_cnt_below, + int *lc_hist, + int blk_hnum) +{ + int k; + unsigned long blk_hist_sum = 0; -static void lc_read_region(void) + for (k = 0; k < HIST_BIN; k++) + blk_hist_sum += + lc_hist[(0*blk_hnum + 0) * + (HIST_BIN+1) + k];/*use blk[0,0],16bin*/ + /*above situation*/ + osd_det_func(osd_flag_cnt_above,/*out*/ + frm_cnt_above,/*out*/ + blk_hist_sum, + lc_hist, + blk_hnum, + vnum_start_above, + vnum_end_above); + /*below situation*/ + osd_det_func(osd_flag_cnt_below,/*out*/ + frm_cnt_below,/*out*/ + blk_hist_sum, + lc_hist, + blk_hnum, + vnum_start_below, + vnum_end_below); + + return 0; +} + +/*just temporarily define here to avoid grammar error*/ +static int video_scene_change_flag_en; +static int video_scene_change_flag; +/*function: detect global scene change signal + *output: scene_change_flag + */ +int global_scene_change(int *curve_nodes_cur, + int *curve_nodes_pre, + int blk_vnum, + int blk_hnum, + int *osd_flag_cnt_above, + int *osd_flag_cnt_below) +{ + int scene_change_flag; + static int scene_dif[N]; + static int frm_dif[N]; + /*store frame valid block for frm diff calc*/ + static int valid_blk_num[N]; + int frm_dif_osd, vnum_osd; + int addr_curv1; + int apl_cur, apl_pre; + int i, j; + + /*history message delay*/ + for (i = 0; i < N-1; i++) { + scene_dif[i] = scene_dif[i + 1]; + frm_dif[i] = frm_dif[i + 1]; + valid_blk_num[i] = valid_blk_num[i+1]; + } + + if (video_scene_change_flag_en) + scene_change_flag = + video_scene_change_flag;/*2.1 flag from front module*/ + else { + /* 2.2.1 use block APL to calculate frame dif: + * omap[5]: (yminV), minBV, pkBV, maxBV, (ymaxV),ypkBV + */ + frm_dif[N-1] = 0;/*update current result*/ + scene_dif[N-1] = 0; + valid_blk_num[N-1] = 0; + frm_dif_osd = 0; + vnum_osd = 0; + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + apl_cur = curve_nodes_cur[addr_curv1 * + CURV_NODES + 2];/*apl value*/ + apl_pre = curve_nodes_pre[addr_curv1 * + CURV_NODES + 2]; + frm_dif[N-1] += + abs(apl_cur - apl_pre);/*frame motion*/ + + /*when have osd, + * remove them to calc frame motion + */ + if ((osd_flag_cnt_below[1]) && + (i >= vnum_start_below) && + (i <= vnum_end_below)) { + frm_dif_osd += abs(apl_cur - apl_pre); + vnum_osd = + vnum_end_below - + vnum_start_below + 1; + + } + + if ((osd_flag_cnt_above[1]) && + (i >= vnum_start_above) && + (i <= vnum_end_above)) { + frm_dif_osd += abs(apl_cur - apl_pre); + vnum_osd = + vnum_end_above - + vnum_start_above + 1; + } + } + } + /*remove osd to calc frame motion */ + frm_dif[N - 1] = frm_dif[N - 1] - frm_dif_osd; + valid_blk_num[N-1] = (blk_vnum - vnum_osd) * blk_hnum; + /*debug*/ + if ((amlc_debug == 0x4)) { + pr_info("#vnum_osd = %d;\n", vnum_osd); + pr_info("#valid_blk_num[%d] = %d\n", + N-1, valid_blk_num[N-1]); + pr_info("#valid_blk_num[%d] = %d\n", + N-2, valid_blk_num[N-2]); + } + + /*2.2.2motion dif.if motion dif too large, + * we think scene changed + */ + scene_dif[N-1] = abs((frm_dif[N - 1] / (valid_blk_num[N-1]+1)) - + (frm_dif[N - 2] / (valid_blk_num[N-2]+1))); + + if (scene_dif[N-1] > scene_change_th) + scene_change_flag = 1; + else + scene_change_flag = 0; + + /*debug*/ + if ((scene_dif[N-1] > scene_change_th) && amlc_iir_debug_en) { + for (i = 0; i < N; i++) + pr_info(" valid_blk_num[%d] = %d,\n", + i, valid_blk_num[i]); + for (i = 0; i < N; i++) + pr_info(" frm_dif[%d] = %d,\n", + i, frm_dif[i]); + pr_info("\n\n"); + for (i = 0; i < N; i++) + pr_info(" scene_dif[%d] = %d,\n", + i, scene_dif[i]); + pr_info(" scene_change_flag =%d\n\n", + scene_change_flag); + } + } + return scene_change_flag; +} +/* + *function: set tiir alpha based on different situation + *input: scene_change_flag, frm_cnt(frm_cnt_above,frm_cnt_below) + *out:refresh_alpha[96] + */ +int cal_iir_alpha(int *refresh_alpha, + int blk_vnum, + int blk_hnum, + int refresh, + int scene_change_flag, + int frm_cnt_above, + int frm_cnt_below) +{ + int addr_curv1; + int osd_local_p, osd_local_m; + int i, j, k; + + /* 3.1 global scene change,highest priority */ + if (scene_change_flag) {/*only use current curve*/ + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + for (k = 0; k < CURV_NODES; k++) { + addr_curv1 = (i * blk_hnum + j); + refresh_alpha[addr_curv1] = refresh; + } + } + } + } else {/*time domain alpha blend, may need optimize*/ + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + refresh_alpha[addr_curv1] = + alpha1;/*normal iir*/ + } + } + } + + /*3.2 osd situation-1, osd below */ + if ((frm_cnt_below > 0)) { + osd_local_p = max(vnum_start_below - 1, 0); + osd_local_m = min(vnum_end_below + 1, blk_vnum); + + for (i = osd_local_p; i <= osd_local_m; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + /*osd around(-1,osd,+1) use heavy iir*/ + refresh_alpha[addr_curv1] = alpha2; + } + } + } + /*3.2 osd situation-2, osd above */ + if ((frm_cnt_above > 0)) { + osd_local_p = max(vnum_start_below - 1, 0); + osd_local_m = min(vnum_end_below + 1, blk_vnum); + + for (i = osd_local_p; i <= osd_local_m; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + /*osd around use heavy iir*/ + refresh_alpha[addr_curv1] = alpha2; + } + } + } + + return 0; +} +/*function: curve iir process + * out: curve_nodes_cur(after iir) + */ +int cal_curv_iir(int *curve_nodes_cur, + int *curve_nodes_pre, + int *refresh_alpha, + int blk_vnum, + int blk_hnum, + int refresh) +{ + int i, j, k; + int tmap[CURV_NODES]; + int addr_curv1, addr_curv2; + int node_cur, node_pre; + + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + for (k = 0; k < CURV_NODES; k++) { + addr_curv2 = + (i * blk_hnum + j) * CURV_NODES + k; + node_cur =/*u12 calc*/ + (curve_nodes_cur[addr_curv2] << 2); + node_pre = (curve_nodes_pre[addr_curv2] << 2); + tmap[k] = + (node_cur * refresh_alpha[addr_curv1] + + node_pre * + (refresh - refresh_alpha[addr_curv1]) + + (1 << (refresh_bit - 1))) >> + refresh_bit; + /*output the iir result*/ + curve_nodes_cur[addr_curv2] = + (tmap[k] >> 2);/*back to u10*/ + /*delay for next iir*/ + curve_nodes_pre[addr_curv2] = + (tmap[k] >> 2); + } + } + } + return 0; +} + +/* + * attention ! + * note 1: + * video_scene_change_flag_en + * video_scene_change_flag + *should from front module,indicate scene changed; + * + * Note 2: OSD appear location + * vnum_start_below + * vnum_end_below (case1) + * vnum_start_above + * vnum_end_above (case2) + */ + + /* iir algorithm top level path */ +static void lc_fw_curve_iir(struct vframe_s *vf, + int *lc_hist, + int *lc_szcurve, + int blk_vnum, + int blk_hnum) +{ + int i; + int scene_change_flag; + /* osd detect */ + static int frm_cnt_below, frm_cnt_above; + static int osd_flag_cnt_below[2]; + static int osd_flag_cnt_above[2]; + /* alpha blend init */ + int refresh_alpha[96] = {0};/*96=vnum*hnum*/ + int refresh = 1 << refresh_bit; + + if (!vf) + return; + + /* pre: get curve nodes from szCurveInfo and save to curve_nodes_cur*/ + for (i = 0; i < 580; i++)/*12*8*6+4*/ + curve_nodes_cur[i] = lc_szcurve[i]; + + /* pre: osd flag delay*/ + osd_flag_cnt_below[0] = osd_flag_cnt_below[1]; + osd_flag_cnt_above[0] = osd_flag_cnt_above[1]; + + /* step 1: osd detect*/ + osd_detect( + osd_flag_cnt_above,/*out*/ + osd_flag_cnt_below,/*out*/ + &frm_cnt_above,/*out*/ + &frm_cnt_below,/*out: osd case heavy iir time */ + lc_hist, + blk_hnum); + + /*step 2: scene change signal get: two method*/ + scene_change_flag = global_scene_change( + curve_nodes_cur, + curve_nodes_pre, + blk_vnum, + blk_hnum, + osd_flag_cnt_above, + osd_flag_cnt_below); + + /* step 3: set tiir alpha based on different situation */ + cal_iir_alpha(refresh_alpha,/*out*/ + blk_vnum, + blk_hnum, + refresh, + scene_change_flag, + frm_cnt_above, + frm_cnt_below); + + /* step 4: iir filter */ + cal_curv_iir(curve_nodes_cur,/*out: iir-ed curve*/ + /*out: store previous frame curve */ + curve_nodes_pre, + refresh_alpha, + blk_vnum, + blk_hnum, + refresh); + + for (i = 0; i < 580; i++) + lc_szcurve[i] = curve_nodes_cur[i];/*output*/ + + frm_cnt_below--; + if (frm_cnt_below < 0) + frm_cnt_below = 0; + + frm_cnt_above--; + if (frm_cnt_above < 0) + frm_cnt_above = 0; + +} + +static void lc_read_region(int blk_vnum, int blk_hnum) { int i, j, k; int data32; int rgb_min, rgb_max; - int dwTemp, blk_hnum, blk_vnum; - if (!lc_hist) { - pr_amlc_dbg("%s: lc_hist not init!", __func__); - return; - } WRITE_VPP_REG_BITS(0x4037, 1, 14, 1); - dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); - blk_hnum = (dwTemp >> 8) & 0x1f; - blk_vnum = (dwTemp) & 0x1f; data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); for (i = 0; i < blk_vnum; i++) @@ -614,15 +1054,17 @@ static void lc_read_region(void) data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && (j >= lc_hist_hs) && (j <= lc_hist_he) && - (amlc_debug == 0x4)) + (amlc_debug == 0x6) && lc_hist_prcnt) pr_info("========[r,c](%2d,%2d)======\n", i, j); for (k = 0; k < 17; k++) { data32 = READ_VPP_REG(LC_STTS_HIST_READ_REGION); - lc_hist[(i*blk_hnum+j)*17 + k] = data32; + lc_hist[(i*blk_hnum+j)*17 + k] + = data32; if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && (j >= lc_hist_hs) && (j <= lc_hist_he) - && (amlc_debug == 0x4)) { + && (amlc_debug == 0x6) && + lc_hist_prcnt) { /*print chosen hist*/ if (k == 16) {/*last bin*/ rgb_min = @@ -637,9 +1079,11 @@ static void lc_read_region(void) } } - if (amlc_debug == 0x2)/*print all hist data*/ + if ((amlc_debug == 0x8) && lc_hist_prcnt)/*print all hist data*/ for (i = 0; i < 8*12*17; i++) pr_info("%x\n", lc_hist[i]); + if (lc_hist_prcnt > 0) + lc_hist_prcnt--; } static void lc_prt_curve(void) @@ -671,15 +1115,29 @@ void lc_init(void) if (!lc_en) return; + lc_szcurve = kzalloc(580 * sizeof(int), GFP_KERNEL); if (!lc_szcurve) return; - lc_hist = kzalloc(1632 * sizeof(int), GFP_KERNEL); - if (!lc_hist) { + curve_nodes_cur = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!curve_nodes_cur) { kfree(lc_szcurve); return; } - + curve_nodes_pre = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!curve_nodes_pre) { + kfree(lc_szcurve); + kfree(curve_nodes_cur); + return; + } + lc_hist = kzalloc(1632 * sizeof(int), GFP_KERNEL); + if (!lc_hist) { + kfree(lc_szcurve); + kfree(curve_nodes_cur); + kfree(curve_nodes_pre); + return; + } + lc_malloc_ok = 1; lc_top_config(0, h_num, v_num, height, width); lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); @@ -693,14 +1151,21 @@ void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) { + int blk_hnum, blk_vnum, dwTemp; + + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) return; - if (!lc_en) { lc_disable(); return; } - + if (!lc_malloc_ok) { + pr_amlc_dbg("%s: lc malloc fail", __func__); + return; + } if (vf == NULL) { if (lc_flag == 0xff) { lc_disable(); @@ -710,18 +1175,16 @@ void lc_process(struct vframe_s *vf, } lc_config(lc_en, vf, sps_h_en, sps_v_en); - - read_lc_curve(); - lc_fw_curve_iir(vf); - + /*get each block curve*/ + read_lc_curve(blk_vnum, blk_hnum); + /*do time domain iir*/ + lc_fw_curve_iir(vf, lc_hist, + lc_szcurve, blk_vnum, blk_hnum); if (lc_curve_prcnt > 0) { /*debug lc curve node*/ lc_prt_curve(); lc_curve_prcnt--; } - if (lc_hist_prcnt > 0) { /*debug hist*/ - lc_read_region(); - lc_hist_prcnt--; - } + lc_read_region(blk_vnum, blk_hnum); if (set_lc_curve(0, 1)) pr_amlc_dbg("%s: set lc curve fail", __func__); @@ -731,5 +1194,7 @@ void lc_process(struct vframe_s *vf, void lc_free(void) { kfree(lc_szcurve); + kfree(curve_nodes_cur); + kfree(curve_nodes_pre); kfree(lc_hist); } diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index 12f3b02eb805..8564b0442a0a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -54,7 +54,22 @@ extern unsigned int lc_hist_hs; extern unsigned int lc_hist_he; extern unsigned int lc_hist_prcnt; extern unsigned int lc_curve_prcnt; - +extern int osd_iir_en; +extern int amlc_iir_debug_en; +/*osd related setting */ +extern int vnum_start_below; +extern int vnum_end_below; +extern int vnum_start_above; +extern int vnum_end_above; +extern int invalid_blk; +/*u10,7000/21600=0.324*1024=331 */ +extern int min_bv_percent_th; +/*control the refresh speed*/ +extern int alpha1; +extern int alpha2; +extern int refresh_bit; +extern int ts; +extern int scene_change_th; extern void lc_init(void); extern void lc_process(struct vframe_s *vf, From ecb0a2e2472bfcfeead8dc4a3a13ede0abae3f9c Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Sat, 15 Dec 2018 18:03:20 +0800 Subject: [PATCH 0209/1060] amvecm: fix platform boot failed [1/1] PD#SWPL-3276 Problem: platform boot failed except TL1 Solution: protect LC register read and Write Verify: R311&P321 Change-Id: I9b93a1c28cdef43db8f1c5ad46bd6597bc62a1bc Signed-off-by: Bencheng Jing --- drivers/amlogic/media/enhancement/amvecm/local_contrast.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 8aeb10df9a96..871d93af7870 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -1153,9 +1153,6 @@ void lc_process(struct vframe_s *vf, { int blk_hnum, blk_vnum, dwTemp; - dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); - blk_hnum = (dwTemp >> 8) & 0x1f; - blk_vnum = (dwTemp) & 0x1f; if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) return; if (!lc_en) { @@ -1173,7 +1170,9 @@ void lc_process(struct vframe_s *vf, } return; } - + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; lc_config(lc_en, vf, sps_h_en, sps_v_en); /*get each block curve*/ read_lc_curve(blk_vnum, blk_hnum); From 8be18d21bff80d05c590634404cab776829ec81c Mon Sep 17 00:00:00 2001 From: Sandy Luo Date: Mon, 17 Dec 2018 16:12:04 +0800 Subject: [PATCH 0210/1060] dts: tl: add tuner support [1/1] PD#OP-6 Problem: Tuner cann't work on tl1 socket board Solution: add tuner in dts Verify: test pass on tl1 socket board Change-Id: I49d70c3ab3c3747000faf40cd06bdb368231311e Signed-off-by: Sandy Luo --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 5d17e01ac778..02d9534bd109 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -870,8 +870,8 @@ tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c0>; tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(3) */ From cdd8165c07147e520080ec2235b109265dab5391 Mon Sep 17 00:00:00 2001 From: Jian Hu Date: Tue, 18 Dec 2018 16:17:57 +0800 Subject: [PATCH 0211/1060] clk: txl: fix gpu clock can not be changed [1/1] PD#SWPL-2909 Problem: The gpu clock rate can not be changed. Solution: 1.it called meson_init_gpu function which used by txlx in txl clock driver, change it to meson_txl_gpu_init function. 2.the /sys/kernel/debug/aml_clk/clk_test node can not work in txl platform, Initial value for clk_numbers which needed by clk_test driver. Verify: test passed on P321 Change-Id: Iade63691edf5b39325f34abb4789d48d33339329 Signed-off-by: Jian Hu --- drivers/amlogic/clk/txl/txl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/clk/txl/txl.c b/drivers/amlogic/clk/txl/txl.c index c0bc2234bb6d..79941f30ff41 100644 --- a/drivers/amlogic/clk/txl/txl.c +++ b/drivers/amlogic/clk/txl/txl.c @@ -945,7 +945,6 @@ static void __init txl_clkc_init(struct device_node *np) pr_err("%s: Unable to map clk base\n", __func__); return; } - /* Populate base address for PLLs */ for (i = 0; i < ARRAY_SIZE(txl_clk_plls); i++) txl_clk_plls[i]->base = clk_base; @@ -994,6 +993,7 @@ static void __init txl_clkc_init(struct device_node *np) clk_data.clks = clks; clk_data.clk_num = NR_CLKS; + clk_numbers = NR_CLKS; /*register all clks*/ for (clkid = 0; clkid < CLOCK_GATE; clkid++) { @@ -1005,7 +1005,7 @@ static void __init txl_clkc_init(struct device_node *np) meson_txl_sdemmc_init(); meson_txl_media_init(); - meson_init_gpu(); + meson_txl_gpu_init(); parent_hw = clk_hw_get_parent(&txl_cpu_clk.mux.hw); parent_clk = parent_hw->clk; From e0b3f792fb514efb0e8b983ff14e6926daa4d6fc Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Thu, 20 Dec 2018 14:52:26 +0800 Subject: [PATCH 0212/1060] amvecm: malloc local contrast to enable lc function [1/1] PD#SWPL-3419 Problem: enable local contrast function Solution: enable local contrast function Verify: x301 Change-Id: I6a1daa7c82224956614b4da46078efdd66424b82 Signed-off-by: Bencheng Jing --- drivers/amlogic/media/enhancement/amvecm/local_contrast.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 871d93af7870..f690969d9a20 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -1113,9 +1113,6 @@ void lc_init(void) h_num = 12; v_num = 8; - if (!lc_en) - return; - lc_szcurve = kzalloc(580 * sizeof(int), GFP_KERNEL); if (!lc_szcurve) return; @@ -1138,6 +1135,8 @@ void lc_init(void) return; } lc_malloc_ok = 1; + if (!lc_en) + return; lc_top_config(0, h_num, v_num, height, width); lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); From 28427bb2c1b0e4d84529175857c2f8258bb0dc84 Mon Sep 17 00:00:00 2001 From: Jiacheng Mei Date: Mon, 24 Dec 2018 11:00:08 +0800 Subject: [PATCH 0213/1060] amlvideo2: reduce vfq size to avoid mem out-of-bounds [1/1] PD#SWPL-3355 Problem: vfq size large than kmalloc mem Solution: reduce vfq size to kmalloc mem size Verify: T962X-R311 Change-Id: Ibbc0c0219d6f170b4169d76e57419cdeb354f7fe Signed-off-by: Jiacheng Mei --- drivers/amlogic/media/video_processor/video_dev/amlvideo2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 8a582116cbd5..953a22199f43 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -3592,7 +3592,7 @@ static int amlvideo2_thread_tick(struct amlvideo2_fh *fh) if ((node->video_blocking) && (node->amlvideo2_pool_ready != NULL)) { vfq_init(&node->q_ready, - node->amlvideo2_pool_size + 1, + node->amlvideo2_pool_size, (struct vframe_s **)&(node->amlvideo2_pool_ready[0])); node->video_blocking = false; node->tmp_vf = NULL; @@ -5747,7 +5747,7 @@ static int amlvideo2_receiver_event_fun(int type, void *data, case VFRAME_EVENT_PROVIDER_REG: node->video_blocking = false; vfq_init(&node->q_ready, - node->amlvideo2_pool_size + 1, + node->amlvideo2_pool_size, (struct vframe_s **)&(node->amlvideo2_pool_ready[0])); break; case VFRAME_EVENT_PROVIDER_UNREG: @@ -5883,7 +5883,7 @@ static int amlvideo2_create_node(struct platform_device *pdev, int node_id) } if (vid_node->amlvideo2_pool_ready != NULL) { vfq_init(&vid_node->q_ready, - vid_node->amlvideo2_pool_size + 1, + vid_node->amlvideo2_pool_size, (struct vframe_s **)&(vid_node->amlvideo2_pool_ready[0])); } vid_node->context = create_ge2d_work_queue(); From 24e88ebf9cb28d04898958f5a5c9265aee4c2b3b Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Tue, 25 Dec 2018 16:55:09 +0800 Subject: [PATCH 0214/1060] dts: change CMA layout [1/1] PD#SWPL-1909 Problem: On 32bit kernel, codec cma is located in normal zone by "alloc-ranges" parameter with large size. This takse up memory space for kernel and drivers. Sometimes we can see memory allocation fail log but there are still enought free pages. But most of these pages are CMA pages. Solution: Move codec cma location to high memzone. On 32bit, low 768MB memory is normal zone. This change also correct first 1MB memory lost problem for chips later than TXLX Verify: TL1 x301/x309/socket board Change-Id: I2fc62ae8b03143cc91bfecc62c123d1925aac482 Signed-off-by: Sandy Luo Signed-off-by: Tao Zeng --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 02d9534bd109..77fbaa5c00d8 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -66,7 +66,7 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x12000000 0x13400000>; + alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 6ba4dc1de331..ef3f0448d3cd 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -67,7 +67,7 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x12000000 0x13400000>; + alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 60a75be67010..5604ed0ad376 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -66,7 +66,7 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x12000000 0x13400000>; + alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ From 1b786cdda387672f1aa9132fa0231c0ce7637b25 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Thu, 6 Dec 2018 16:58:17 +0800 Subject: [PATCH 0215/1060] lcd: add lcd/power debug node [1/2] PD#SWPL-1005 Problem: add lcd/power debug node Solution: 1,add lcd/power node to control lcd power on/off sequence 2,change old lcd/power to lcd/power_step Verify: verified by t962x_r311 Change-Id: I0b10caa4cbd8f7ce489f3ceef7780dba2e0b00dc Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/lcd/lcd_debug.c | 76 ++++++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 306c216a7473..b908b5594406 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -116,7 +117,8 @@ static const char *lcd_common_usage_str = { " echo ... > debug ; lcd common debug, use 'cat debug' for help\n" " cat debug ; print help information for debug command\n" "\n" -" echo > power ; set power on/off step delay(unit: ms)\n" +" echo <0|1> > power; lcd power control: 0=lcd power off, 1=lcd power on\n" +" echo > power_step ; set power on/off step delay(unit: ms)\n" " cat power ; print lcd power on/off step\n" "\n" " cat key_valid ; print lcd_key_valid setting\n" @@ -252,7 +254,7 @@ static int lcd_power_step_print(struct lcd_config_s *pconf, int status, return len; } -static int lcd_power_info_print(char *buf, int offset) +static int lcd_power_step_info_print(char *buf, int offset) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int len = 0; @@ -1564,7 +1566,7 @@ static ssize_t lcd_debug_store(struct class *class, lcd_info_print(print_buf, 0); lcd_debug_info_print(print_buf); memset(print_buf, 0, PR_BUF_MAX); - lcd_power_info_print(print_buf, 0); + lcd_power_step_info_print(print_buf, 0); lcd_debug_info_print(print_buf); kfree(print_buf); break; @@ -1616,7 +1618,7 @@ static ssize_t lcd_debug_store(struct class *class, lcd_info_print(print_buf, 0); lcd_debug_info_print(print_buf); memset(print_buf, 0, PR_BUF_MAX); - lcd_power_info_print(print_buf, 0); + lcd_power_step_info_print(print_buf, 0); lcd_debug_info_print(print_buf); memset(print_buf, 0, PR_BUF_MAX); lcd_reg_print(print_buf, 0); @@ -2066,6 +2068,49 @@ static ssize_t lcd_debug_resume_store(struct class *class, static ssize_t lcd_debug_power_show(struct class *class, struct class_attribute *attr, char *buf) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int state; + + if ((lcd_drv->lcd_status & BL_STATE_LCD_ON) == 0) { + state = 0; + } else { + if (lcd_drv->lcd_status & BL_STATE_BL_POWER_ON) + state = 1; + else + state = 0; + } + return sprintf(buf, "backlight power state: %d\n", state); +} + +static ssize_t lcd_debug_power_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int ret = 0; + unsigned int temp = 1; + + ret = kstrtouint(buf, 10, &temp); + if (ret) { + LCDERR("invalid data\n"); + return -EINVAL; + } + if (temp) { + mutex_lock(&lcd_drv->power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, NULL); + lcd_if_enable_retry(lcd_drv->lcd_config); + mutex_unlock(&lcd_drv->power_mutex); + } else { + mutex_lock(&lcd_drv->power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL); + mutex_unlock(&lcd_drv->power_mutex); + } + + return count; +} + +static ssize_t lcd_debug_power_step_show(struct class *class, + struct class_attribute *attr, char *buf) { char *print_buf; int n = 0; @@ -2074,7 +2119,7 @@ static ssize_t lcd_debug_power_show(struct class *class, if (print_buf == NULL) return sprintf(buf, "%s: buf malloc error\n", __func__); - lcd_power_info_print(print_buf, 0); + lcd_power_step_info_print(print_buf, 0); n = sprintf(buf, "%s\n", print_buf); kfree(print_buf); @@ -2082,24 +2127,24 @@ static ssize_t lcd_debug_power_show(struct class *class, return n; } -static ssize_t lcd_debug_power_store(struct class *class, +static ssize_t lcd_debug_power_step_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; unsigned int i, delay; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - struct lcd_power_ctrl_s *lcd_power; + struct lcd_power_ctrl_s *lcd_power_step; - lcd_power = lcd_drv->lcd_config->lcd_power; + lcd_power_step = lcd_drv->lcd_config->lcd_power; switch (buf[1]) { case 'n': /* on */ ret = sscanf(buf, "on %d %d", &i, &delay); if (ret == 2) { - if (i >= lcd_power->power_on_step_max) { + if (i >= lcd_power_step->power_on_step_max) { pr_info("invalid power_on step: %d\n", i); return -EINVAL; } - lcd_power->power_on_step[i].delay = delay; + lcd_power_step->power_on_step[i].delay = delay; pr_info("set power_on step %d delay: %dms\n", i, delay); } else { @@ -2110,11 +2155,11 @@ static ssize_t lcd_debug_power_store(struct class *class, case 'f': /* off */ ret = sscanf(buf, "off %d %d", &i, &delay); if (ret == 1) { - if (i >= lcd_power->power_off_step_max) { + if (i >= lcd_power_step->power_off_step_max) { pr_info("invalid power_off step: %d\n", i); return -EINVAL; } - lcd_power->power_off_step[i].delay = delay; + lcd_power_step->power_off_step[i].delay = delay; pr_info("set power_off step %d delay: %dms\n", i, delay); } else { @@ -2725,7 +2770,7 @@ static ssize_t lcd_debug_dump_show(struct class *class, switch (lcd_debug_dump_state) { case LCD_DEBUG_DUMP_INFO: len = lcd_info_print(print_buf, 0); - lcd_power_info_print((print_buf+len), len); + lcd_power_step_info_print((print_buf+len), len); break; case LCD_DEBUG_DUMP_REG: lcd_reg_print(print_buf, 0); @@ -2806,7 +2851,10 @@ static struct class_attribute lcd_debug_class_attrs[] = { lcd_debug_enable_show, lcd_debug_enable_store), __ATTR(resume_type, 0644, lcd_debug_resume_show, lcd_debug_resume_store), - __ATTR(power, 0644, lcd_debug_power_show, lcd_debug_power_store), + __ATTR(power, 0644, lcd_debug_power_show, + lcd_debug_power_store), + __ATTR(power_step, 0644, lcd_debug_power_step_show, + lcd_debug_power_step_store), __ATTR(frame_rate, 0644, lcd_debug_frame_rate_show, lcd_debug_frame_rate_store), __ATTR(fr_policy, 0644, From 2e24b4e2e188b7308d82223efeee7fea4328d007 Mon Sep 17 00:00:00 2001 From: Qianggui Song Date: Mon, 24 Dec 2018 13:35:17 +0800 Subject: [PATCH 0216/1060] ir: add toshiba protocol support [1/1] PD#SWPL-3543 Problem: current driver does not support toshiba ir remote control protocol Solution: add register setting and decode code for toshiba protocol use REMOTE_TYPE_TOSHIBA/REMOTE_TYPE_NEC_TOSHIBA to configure toshiba only/toshiba and nec. Verify: tl1_t962x2_x301 Change-Id: Idad70c3879fad6e8267f0c4d80d2447c34114103 Signed-off-by: Qianggui Song --- drivers/amlogic/input/remote/remote_meson.h | 38 +++++++------ drivers/amlogic/input/remote/remote_regmap.c | 57 ++++++++++++++++++++ include/dt-bindings/input/meson_rc.h | 3 ++ 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/drivers/amlogic/input/remote/remote_meson.h b/drivers/amlogic/input/remote/remote_meson.h index 282664193e25..35950a5fe118 100644 --- a/drivers/amlogic/input/remote/remote_meson.h +++ b/drivers/amlogic/input/remote/remote_meson.h @@ -167,23 +167,27 @@ enum { }; enum remote_reg { - REG_LDR_ACTIVE = 0x00<<2, - REG_LDR_IDLE = 0x01<<2, - REG_LDR_REPEAT = 0x02<<2, - REG_BIT_0 = 0x03<<2, - REG_REG0 = 0x04<<2, - REG_FRAME = 0x05<<2, - REG_STATUS = 0x06<<2, - REG_REG1 = 0x07<<2, - REG_REG2 = 0x08<<2, - REG_DURATN2 = 0x09<<2, - REG_DURATN3 = 0x0a<<2, - REG_FRAME1 = 0x0b<<2, - REG_STATUS1 = 0x0c<<2, - REG_STATUS2 = 0x0d<<2, - REG_REG3 = 0x0e<<2, - REG_FRAME_RSV0 = 0x0f<<2, - REG_FRAME_RSV1 = 0x10<<2 + REG_LDR_ACTIVE = 0x00 << 2, + REG_LDR_IDLE = 0x01 << 2, + REG_LDR_REPEAT = 0x02 << 2, + REG_BIT_0 = 0x03 << 2, + REG_REG0 = 0x04 << 2, + REG_FRAME = 0x05 << 2, + REG_STATUS = 0x06 << 2, + REG_REG1 = 0x07 << 2, + REG_REG2 = 0x08 << 2, + REG_DURATN2 = 0x09 << 2, + REG_DURATN3 = 0x0a << 2, + REG_FRAME1 = 0x0b << 2, + REG_STATUS1 = 0x0c << 2, + REG_STATUS2 = 0x0d << 2, + REG_REG3 = 0x0e << 2, + REG_FRAME_RSV0 = 0x0f << 2, + REG_FRAME_RSV1 = 0x10 << 2, + REG_FILTE = 0x11 << 2, + REG_IRQ_CTL = 0x12 << 2, + REG_WIDTH_NEW = 0x14 << 2, + REG_REPEAT_DET = 0x15 << 2 }; int ir_register_default_config(struct remote_chip *chip, int type); diff --git a/drivers/amlogic/input/remote/remote_regmap.c b/drivers/amlogic/input/remote/remote_regmap.c index 46715687a7e4..2d9f42404247 100644 --- a/drivers/amlogic/input/remote/remote_regmap.c +++ b/drivers/amlogic/input/remote/remote_regmap.c @@ -134,6 +134,53 @@ static struct remote_reg_map regs_default_rc6[] = { {REG_DURATN3, ((51 << 16) | (38 << 0))}, }; +static struct remote_reg_map regs_default_toshiba[] = { + { REG_LDR_ACTIVE, (280 << 16) | (180 << 0)}, + { REG_LDR_IDLE, (280 << 16) | (180 << 0)}, + { REG_LDR_REPEAT, (150 << 16) | (60 << 0)}, + { REG_BIT_0, (72 << 16) | (40 << 0)}, + { REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13}, + { REG_STATUS, (134 << 20) | (90 << 10)}, + { REG_REG1, 0x9f00}, + { REG_REG2, (0x05) | (1 << 24) | (23 << 11)}, + { REG_DURATN2, 0x00}, + { REG_DURATN3, 0x00}, + { REG_REPEAT_DET, (1 << 31) | (0xFA0 << 16) | (10 << 0)}, + { REG_REG3, 0x2AF8}, +}; + +static int ir_toshiba_get_scancode(struct remote_chip *chip) +{ + int code = 0; + int decode_status = 0; + int status = 0; + + remote_reg_read(chip, MULTI_IR_ID, REG_STATUS, &decode_status); + if (decode_status & 0x01) + status |= REMOTE_REPEAT; + chip->decode_status = status; /*set decode status*/ + remote_reg_read(chip, MULTI_IR_ID, REG_FRAME, &code); + remote_dbg(chip->dev, "framecode=0x%x\n", code); + chip->r_dev->cur_hardcode = code; + code = (code >> 16) & 0xff; + return code; + +} + +static int ir_toshiba_get_decode_status(struct remote_chip *chip) +{ + int status = chip->decode_status; + return status; +} + +static u32 ir_toshiba_get_custom_code(struct remote_chip *chip) +{ + u32 custom_code; + + custom_code = (chip->r_dev->cur_hardcode) & 0xffff; + return custom_code; +} + void set_hardcode(struct remote_chip *chip, int code) { remote_dbg(chip->dev, "framecode=0x%x\n", code); @@ -499,6 +546,15 @@ static struct aml_remote_reg_proto reg_rc6 = { .get_custom_code = ir_rc6_get_custom_code, }; +static struct aml_remote_reg_proto reg_toshiba = { + .protocol = REMOTE_TYPE_TOSHIBA, + .name = "TOSHIBA", + .reg_map = regs_default_toshiba, + .reg_map_size = ARRAY_SIZE(regs_default_toshiba), + .get_scancode = ir_toshiba_get_scancode, + .get_decode_status = ir_toshiba_get_decode_status, + .get_custom_code = ir_toshiba_get_custom_code, +}; const struct aml_remote_reg_proto *remote_reg_proto[] = { ®_nec, @@ -509,6 +565,7 @@ const struct aml_remote_reg_proto *remote_reg_proto[] = { ®_rc5, ®_rc6, ®_legacy_nec, + ®_toshiba, NULL }; diff --git a/include/dt-bindings/input/meson_rc.h b/include/dt-bindings/input/meson_rc.h index 382b8b9ad4b8..9aec87f98059 100644 --- a/include/dt-bindings/input/meson_rc.h +++ b/include/dt-bindings/input/meson_rc.h @@ -37,6 +37,7 @@ #define REMOTE_TYPE_XMP_1 0x03 #define REMOTE_TYPE_RC5 0x04 #define REMOTE_TYPE_RC6 0x05 +#define REMOTE_TYPE_TOSHIBA 0x06 /*hardware decode one protocol by using legacy IR controller*/ #define REMOTE_TYPE_LEGACY_NEC 0xff @@ -55,5 +56,7 @@ *2. multi-format IR controller decode other protocol */ #define REMOTE_TYPE_NEC_RC6 ((REMOTE_TYPE_LEGACY_NEC << 8) | REMOTE_TYPE_RC6) +#define REMOTE_TYPE_NEC_TOSHIBA ((REMOTE_TYPE_LEGACY_NEC << 8) | \ + REMOTE_TYPE_TOSHIBA) #endif From 445dbd8d19c08081cc0e1309e3ebc93df13e81c4 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Mon, 17 Dec 2018 20:07:54 +0800 Subject: [PATCH 0217/1060] backlight: add backlight brightness debug function [2/2] PD#SWPL-1005 Problem: add backlight brightness debug function Solution: 1,add brightness_level node to change backlight brightness 2,add brightness_bypass node to change brightness_bypass Verify: verified by t962x_r311 Change-Id: I8faae0d08b2a15fdc5c5a507c0c6815843be59ab Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/backlight/aml_bl.c | 98 +++++++++++++++---- 1 file changed, 77 insertions(+), 21 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index 3cd7eceebf9a..070d0fa7c393 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -68,8 +68,6 @@ MODULE_PARM_DESC(bl_level, "bl_level"); static unsigned int bl_level_uboot; static unsigned int brightness_bypass; -module_param(brightness_bypass, uint, 0664); -MODULE_PARM_DESC(brightness_bypass, "bl_brightness_bypass"); static unsigned char bl_pwm_bypass; /* debug flag */ static unsigned char bl_pwm_duty_free; /* debug flag */ @@ -1213,6 +1211,30 @@ static unsigned int aml_bl_get_level(void) return bl_drv->level; } +static unsigned int aml_bl_update_brightness_level(unsigned int bl_level) +{ + mutex_lock(&bl_level_mutex); + if (bl_level > 255) { + BLPR("0-255 is the valid data\n"); + bl_level = 255; + } + + if (((bl_drv->state & BL_STATE_LCD_ON) == 0) || + ((bl_drv->state & BL_STATE_BL_POWER_ON) == 0)) + bl_level = 0; + + if (bl_level == 0) { + if (bl_drv->state & BL_STATE_BL_ON) + bl_power_off(); + } else { + aml_bl_set_level(bl_level); + if ((bl_drv->state & BL_STATE_BL_ON) == 0) + bl_power_on(); + } + mutex_unlock(&bl_level_mutex); + return 0; +} + static int aml_bl_update_status(struct backlight_device *bd) { int brightness = bd->props.brightness; @@ -1220,30 +1242,12 @@ static int aml_bl_update_status(struct backlight_device *bd) if (brightness_bypass) return 0; - mutex_lock(&bl_level_mutex); - if (brightness < 0) - brightness = 0; - else if (brightness > 255) - brightness = 255; - - if (((bl_drv->state & BL_STATE_LCD_ON) == 0) || - ((bl_drv->state & BL_STATE_BL_POWER_ON) == 0)) - brightness = 0; - + aml_bl_update_brightness_level(brightness); if (bl_debug_print_flag) { BLPR("%s: %u, real brightness: %u, state: 0x%x\n", __func__, bd->props.brightness, brightness, bl_drv->state); } - if (brightness == 0) { - if (bl_drv->state & BL_STATE_BL_ON) - bl_power_off(); - } else { - aml_bl_set_level(brightness); - if ((bl_drv->state & BL_STATE_BL_ON) == 0) - bl_power_on(); - } - mutex_unlock(&bl_level_mutex); return 0; } @@ -3124,6 +3128,54 @@ static ssize_t bl_debug_print_store(struct class *class, return count; } +static ssize_t bl_debug_brightness_bypass_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", brightness_bypass); +} + +static ssize_t bl_debug_brightness_bypass_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + + ret = kstrtouint(buf, 10, &brightness_bypass); + if (ret != 0) { + BLERR("invalid data\n"); + return -EINVAL; + } + return count; +} + +static ssize_t bl_debug_brightness_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", bl_drv->level); +} + +static ssize_t bl_debug_brightness_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int brightness_level = 0; + + ret = kstrtouint(buf, 10, &brightness_level); + if (ret != 0) { + BLERR("invalid data\n"); + return -EINVAL; + } + + if (!brightness_bypass) + brightness_bypass = 1; + + ret = aml_bl_update_brightness_level(brightness_level); + if (ret == 0) + BLPR("brightness %d update ok\n", brightness_level); + else + BLERR("update fail\n"); + return count; +} + static struct class_attribute bl_debug_class_attrs[] = { __ATTR(help, 0444, bl_debug_help, NULL), __ATTR(status, 0444, bl_status_read, NULL), @@ -3134,6 +3186,10 @@ static struct class_attribute bl_debug_class_attrs[] = { __ATTR(key_valid, 0444, bl_debug_key_valid_show, NULL), __ATTR(config_load, 0444, bl_debug_config_load_show, NULL), __ATTR(print, 0644, bl_debug_print_show, bl_debug_print_store), + __ATTR(brightness_bypass, 0644, bl_debug_brightness_bypass_show, + bl_debug_brightness_bypass_store), + __ATTR(brightness_level, 0644, bl_debug_brightness_show, + bl_debug_brightness_store), }; static int aml_bl_creat_class(void) From f5d31c54571a3a4f32b772d76ac6385d2343dd2a Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Tue, 18 Dec 2018 11:31:35 +0800 Subject: [PATCH 0218/1060] lcd: add lcd resume alarm filter function [1/1] PD#SWPL-3362 Problem: add lcd resume alarm filter function Solution: add lcd resume alarm filter function Verify: verified by t962x_r311 Change-Id: Ia4c219c76d253b4ecc16784193dc06a164d7a217 Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/lcd/lcd_vout.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 3932e1d880bb..cab43cb3b124 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -36,6 +36,7 @@ #ifdef CONFIG_OF #include #endif +#include #include #include #include @@ -1419,6 +1420,10 @@ static int lcd_remove(struct platform_device *pdev) static int lcd_resume(struct platform_device *pdev) { + if ((get_resume_method() == RTC_WAKEUP) || + (get_resume_method() == AUTO_WAKEUP)) + return 0; + if ((lcd_driver->lcd_status & LCD_STATUS_VMODE_ACTIVE) == 0) return 0; From f78f1b4e6ceafd24f8342fff468cbb76f2e91dfa Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Wed, 19 Dec 2018 20:45:46 +0800 Subject: [PATCH 0219/1060] tvafe: fix av pal flash issue on some devices [1/1] PD#SWPL-2636 Problem: Picture flash when av connect some dvd or mbox Solution: Modify the vafe ctrl config Verify: verified by x301 Change-Id: Ie6ae659f3f59d7daba680e2bb32112031232c956 Signed-off-by: Nian Jing --- .../media/vin/tvin/tvafe/tvafe_debug.c | 13 +++++------ .../media/vin/tvin/tvafe/tvafe_general.c | 22 ++++++++++--------- .../amlogic/media/vin/tvin/tvafe/tvafe_vbi.c | 12 +++++----- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c index 44993fd201c9..0518189f1b24 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c @@ -450,10 +450,9 @@ static ssize_t tvafereg_store(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) { struct tvafe_dev_s *devp; - unsigned int argn = 0, addr = 0, value = 0, end = 0; + unsigned int argn = 0, addr = 0, value = 0, end = 0, tmp = 0; char *p, *para, *buf_work, cmd = 0; char *argv[3]; - long tmp = 0; devp = dev_get_drvdata(dev); @@ -485,7 +484,7 @@ static ssize_t tvafereg_store(struct device *dev, if (argn < 2) { tvafe_pr_err("syntax error.\n"); } else{ - if (kstrtol(argv[1], 16, &tmp) == 0) + if (kstrtouint(argv[1], 16, &tmp) == 0) addr = tmp; else break; @@ -499,11 +498,11 @@ static ssize_t tvafereg_store(struct device *dev, if (argn < 3) { tvafe_pr_err("syntax error.\n"); } else{ - if (kstrtol(argv[1], 16, &tmp) == 0) + if (kstrtouint(argv[1], 16, &tmp) == 0) value = tmp; else break; - if (kstrtol(argv[2], 16, &tmp) == 0) + if (kstrtouint(argv[2], 16, &tmp) == 0) addr = tmp; else break; @@ -517,11 +516,11 @@ static ssize_t tvafereg_store(struct device *dev, if (argn < 3) { tvafe_pr_err("syntax error.\n"); } else{ - if (kstrtol(argv[1], 16, &tmp) == 0) + if (kstrtouint(argv[1], 16, &tmp) == 0) addr = tmp; else break; - if (kstrtol(argv[2], 16, &tmp) == 0) + if (kstrtouint(argv[2], 16, &tmp) == 0) end = tmp; else break; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index 70c8faacf8e1..0f2cf0d76ec8 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -254,14 +254,16 @@ static enum tvafe_adc_ch_e tvafe_adc_pin_muxing( W_APB_BIT(TVFE_VAFE_CTRL1, 1, VAFE_IN_SEL_BIT, VAFE_IN_SEL_WID); - W_APB_BIT(TVFE_VAFE_CTRL2, 3, 4, 3); + if (tvafe_cpu_type() != CPU_TYPE_TL1) + W_APB_BIT(TVFE_VAFE_CTRL2, 3, 4, 3); ret = TVAFE_ADC_CH_0; } else if (pin == TVAFE_CVBS_IN1) { W_APB_BIT(TVFE_VAFE_CTRL1, 2, VAFE_IN_SEL_BIT, VAFE_IN_SEL_WID); - W_APB_BIT(TVFE_VAFE_CTRL2, 5, 4, 3); + if (tvafe_cpu_type() != CPU_TYPE_TL1) + W_APB_BIT(TVFE_VAFE_CTRL2, 5, 4, 3); ret = TVAFE_ADC_CH_1; } else if (pin == TVAFE_CVBS_IN2) { @@ -450,7 +452,7 @@ static void tvafe_set_cvbs_default(struct tvafe_cvd2_s *cvd2, (port == TVIN_PORT_CVBS2)) { W_APB_REG(TVFE_VAFE_CTRL0, 0x00490710); W_APB_REG(TVFE_VAFE_CTRL1, 0x0000110e); - W_APB_REG(TVFE_VAFE_CTRL2, 0x1fe09fd3); + W_APB_REG(TVFE_VAFE_CTRL2, 0x1fe09f83); } } else { W_APB_REG(TVFE_VAFE_CTRL0, 0x00090b00); @@ -706,19 +708,19 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) adc_pll_lock_cnt++; } while (!R_HIU_BIT(HHI_ADC_PLL_CNTL0_TL1, 31, 1) && (adc_pll_lock_cnt < 10)); - tvafe_pr_info("b0=0x%x", + tvafe_pr_info("b0=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL0_TL1)); - tvafe_pr_info("b1=0x%x", + tvafe_pr_info("b1=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL1_TL1)); - tvafe_pr_info("b2=0x%x", + tvafe_pr_info("b2=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL2_TL1)); - tvafe_pr_info("b3=0x%x", + tvafe_pr_info("b3=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL3_TL1)); - tvafe_pr_info("b4=0x%x", + tvafe_pr_info("b4=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL4_TL1)); - tvafe_pr_info("b5=0x%x", + tvafe_pr_info("b5=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL5_TL1)); - tvafe_pr_info("b6=0x%x", + tvafe_pr_info("b6=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL6_TL1)); } else { diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c index 21a3ee5df45b..2857d8ecf1d3 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c @@ -1378,7 +1378,7 @@ static ssize_t vbi_store(struct device *dev, struct vbi_dev_s *devp = dev_get_drvdata(dev); struct vbi_slicer_s *vbi_slicer; struct vbi_ringbuffer_s *vbi_buffer; - long val; + unsigned int val; int ret = 0; if (!buff || !devp) @@ -1420,13 +1420,13 @@ static ssize_t vbi_store(struct device *dev, tvafe_pr_info("dump satus done!!\n"); } else if (!strncmp(parm[0], "enable_tasklet", strlen("enable_tasklet"))) { - if (kstrtol(parm[1], 10, &val) < 0) + if (kstrtouint(parm[1], 10, &val) < 0) return -EINVAL; devp->tasklet_enable = val; tvafe_pr_info("tasklet_enable:%d\n", devp->tasklet_enable); } else if (!strncmp(parm[0], "data_wmode", strlen("data_wmode"))) { - if (kstrtol(parm[1], 10, &val) < 0) + if (kstrtouint(parm[1], 10, &val) < 0) return -EINVAL; vbi_buffer->data_wmode = val; tvafe_pr_info("data_wmode:%d\n", vbi_buffer->data_wmode); @@ -1450,13 +1450,13 @@ static ssize_t vbi_store(struct device *dev, tvafe_pr_info(" disable vbi function\n"); tvafe_pr_info("stop done!!!\n"); } else if (!strncmp(parm[0], "set_size", strlen("set_size"))) { - if (kstrtol(parm[1], 10, &val) < 0) + if (kstrtouint(parm[1], 10, &val) < 0) return -EINVAL; - vbi_set_buffer_size(devp, (unsigned int)val); + vbi_set_buffer_size(devp, val); tvafe_pr_info(" set buf size to %d\n", vbi_slicer->buffer.size); } else if (!strncmp(parm[0], "set_type", strlen("set_type"))) { - if (kstrtol(parm[1], 16, &val) < 0) + if (kstrtouint(parm[1], 16, &val) < 0) return -EINVAL; vbi_slicer->type = val; vbi_slicer_set(devp, vbi_slicer); From 11fe2d13cdc5ae7f8bc885f4fe6e1d133229db0a Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 21 Dec 2018 11:41:54 +0800 Subject: [PATCH 0220/1060] backlight: ldim_global demo can't power on [1/1] PD#SWPL-3293 Problem: select UHD_2RG_LDIM model_name, then the backlight can't power on. Solution: fix ldim dev_drv add mistake Verify: r311 Change-Id: I7f86d6072524a2a6399a8259dae8c27a89a79b85 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index 037a3d09e41d..455066dc412b 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -1163,7 +1163,7 @@ static int ldim_dev_add_driver(struct aml_ldim_driver_s *ldim_drv) { struct ldim_dev_config_s *ldev_conf = ldim_drv->ldev_conf; int index = ldim_drv->dev_index; - int ret = -1; + int ret = 0; switch (ldim_dev_config.type) { case LDIM_DEV_TYPE_SPI: From 585580816c72c709254ddea2d5c59c83866cd788 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Thu, 6 Dec 2018 16:58:17 +0800 Subject: [PATCH 0221/1060] backlight: add backlight pwm debug node for tvapi [1/1] PD#SWPL-3110 Problem: add backlight pwm debug node for tvapi Solution: 1,change pwm node for pwm main parameters(duty, freq, pol) 2,add pwm_info node to display all pwm state Verify: verified by t962x_r311 Change-Id: Ibd9575412ca9704a0002073679d19c5426c1838c Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/backlight/aml_bl.c | 75 ++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index 070d0fa7c393..c38f5c507c28 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -2550,7 +2550,7 @@ static ssize_t bl_status_read(struct class *class, return len; } -static ssize_t bl_debug_pwm_show(struct class *class, +static ssize_t bl_debug_pwm_info_show(struct class *class, struct class_attribute *attr, char *buf) { struct bl_config_s *bconf = bl_drv->bconf; @@ -2559,7 +2559,7 @@ static ssize_t bl_debug_pwm_show(struct class *class, unsigned int value; ssize_t len = 0; - len = sprintf(buf, "read backlight pwm state:\n"); + len = sprintf(buf, "read backlight pwm info:\n"); switch (bconf->method) { case BL_CTRL_PWM: len += sprintf(buf+len, @@ -2794,6 +2794,76 @@ static ssize_t bl_debug_pwm_show(struct class *class, return len; } +static ssize_t bl_debug_pwm_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_config_s *bconf = bl_drv->bconf; + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + switch (bconf->method) { + case BL_CTRL_PWM: + if (bconf->bl_pwm) { + bl_pwm = bconf->bl_pwm; + len += sprintf(buf+len, + "pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + break; + case BL_CTRL_PWM_COMBO: + if (bconf->bl_pwm_combo0) { + bl_pwm = bconf->bl_pwm_combo0; + len += sprintf(buf+len, + "pwm_0: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + + if (bconf->bl_pwm_combo1) { + bl_pwm = bconf->bl_pwm_combo1; + len += sprintf(buf+len, + "pwm_1: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + break; + default: + break; + } + return len; +} + #define BL_DEBUG_PWM_FREQ 0 #define BL_DEBUG_PWM_DUTY 1 #define BL_DEBUG_PWM_POL 2 @@ -3179,6 +3249,7 @@ static ssize_t bl_debug_brightness_store(struct class *class, static struct class_attribute bl_debug_class_attrs[] = { __ATTR(help, 0444, bl_debug_help, NULL), __ATTR(status, 0444, bl_status_read, NULL), + __ATTR(pwm_info, 0644, bl_debug_pwm_info_show, NULL), __ATTR(pwm, 0644, bl_debug_pwm_show, bl_debug_pwm_store), __ATTR(power, 0644, bl_debug_power_show, bl_debug_power_store), __ATTR(step_on, 0644, bl_debug_step_on_show, bl_debug_step_on_store), From 8d233ed5524258529c5463bc5b336be3d7a78c1d Mon Sep 17 00:00:00 2001 From: Yi Zeng Date: Thu, 27 Dec 2018 14:43:36 +0800 Subject: [PATCH 0222/1060] mtd: nand: support new slc nand [1/1] PD#SWPL-3542 Problem: 2Gb SLC Nand ZDND2G08U3D-IA requested by Marketing aka ZDND2GXXXXX module number Solution: add the nand id and MFR id into amlogic id table adapt it's bad block identification Verify: AXG_S400 Change-Id: I6f0e2caf424e09c1f186beb42a146d92b675f161 Signed-off-by: Yi Zeng --- drivers/amlogic/mtd/nand_flash.c | 13 +++++++++++++ drivers/amlogic/mtd/rsv_manage.c | 3 ++- drivers/mtd/nand/nand_ids.c | 1 + include/linux/mtd/nand.h | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/mtd/nand_flash.c b/drivers/amlogic/mtd/nand_flash.c index 206e615aaaea..9f29f4d6f988 100644 --- a/drivers/amlogic/mtd/nand_flash.c +++ b/drivers/amlogic/mtd/nand_flash.c @@ -288,6 +288,19 @@ struct aml_nand_flash_dev aml_nand_flash_ids[] = { 0, (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + {"Zetta NAND ZDND2GXXXXX 2Gb", + {NAND_MFR_ZETTA, 0xda, 0x90, 0x95, 0x46}, + 2048, + 256, + 0x20000, + 64, + 1, + 20, + 15, + 0, + 0, + (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + {"A revision NAND 1GiB sF1G-A", {NAND_MFR_AMD, 0xf1, 0x80, 0x1d, 0x01, 0xf1}, 2048, diff --git a/drivers/amlogic/mtd/rsv_manage.c b/drivers/amlogic/mtd/rsv_manage.c index 79699363a573..f0ddbc462c17 100644 --- a/drivers/amlogic/mtd/rsv_manage.c +++ b/drivers/amlogic/mtd/rsv_manage.c @@ -324,7 +324,8 @@ int aml_nand_scan_shipped_bbt(struct mtd_info *mtd) if (aml_chip->mfr_type == NAND_MFR_DOSILICON || aml_chip->mfr_type == NAND_MFR_ATO || - aml_chip->mfr_type == NAND_MFR_HYNIX) { + aml_chip->mfr_type == NAND_MFR_HYNIX || + aml_chip->mfr_type == NAND_MFR_ZETTA) { if (col0_oob != 0xFF) { pr_info("factory Bad blk:%llx blk=%d chip=%d\n", (uint64_t)addr, start_blk, i); diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 2af9869a115e..8eda039c87fd 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -182,6 +182,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_SANDISK, "SanDisk"}, {NAND_MFR_INTEL, "Intel"}, {NAND_MFR_ATO, "ATO"}, + {NAND_MFR_ZETTA, "Zetta"}, {0x0, "Unknown"} }; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 838e109107de..43496fb357be 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -929,6 +929,7 @@ static inline void nand_set_controller_data(struct nand_chip *chip, void *priv) #define NAND_MFR_INTEL 0x89 #define NAND_MFR_ATO 0x9b #define NAND_MFR_DOSILICON 0xf8 +#define NAND_MFR_ZETTA 0xba /* add extra flash manufacturer ID Codes */ #if defined(CONFIG_AMLOGIC_NAND) || defined(CONFIG_AMLOGIC_M8B_NAND) From 86393c1ef037dd3324d8ea532ffb1ba2b32e0542 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Thu, 20 Dec 2018 20:16:06 +0800 Subject: [PATCH 0223/1060] tvin: vdin: fix afbce 4k yuv444 display error [1/1] PD#SWPL-3429 Problem: vdin output format is afbce 4k yuv444,it display ghost shadow of image Solution: add afbce comb control Verify: x301 Change-Id: I168f13994a4929bd227ba70b006f259ac0726238 Signed-off-by: Xuhua Zhang --- drivers/amlogic/media/video_sink/video.c | 3 +++ drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c | 6 ++++-- include/linux/amlogic/media/vfm/vframe.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 83c0737952d0..347c92520e55 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -4067,6 +4067,9 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) if (vf && (vf->source_type != VFRAME_SOURCE_TYPE_HDMI)) r |= (1 << 19); /* dos_uncomp */ + + if (type & VIDTYPE_COMB_MODE) + r |= (1 << 20); } VSYNC_WR_MPEG_REG(AFBC_ENABLE, r); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index 97d58d375a3d..0267eb643771 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -4022,9 +4022,11 @@ u32 vdin_get_curr_field_type(struct vdin_dev_s *devp) } format_convert = devp->format_convert; if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV444) || - (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444)) + (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444)) { type |= VIDTYPE_VIU_444; - else if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || + if (devp->afbce_mode == 1) + type |= VIDTYPE_COMB_MODE; + } else if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV422)) type |= VIDTYPE_VIU_422; else if (devp->prop.dest_cfmt == TVIN_NV21) { diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 2a62b6735824..1ca5c71ba285 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -46,6 +46,7 @@ #define VIDTYPE_SCATTER 0x400000 #define VIDTYPE_VD2 0x800000 #define VIDTYPE_COMPRESS_LOSS 0x1000000 +#define VIDTYPE_COMB_MODE 0x2000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 From 02a59dfabc7938a95fe9a4af6c175b86709586f6 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Fri, 21 Dec 2018 13:16:24 +0800 Subject: [PATCH 0224/1060] tvin: vdin: fix afbce 576p color anomaly [1/1] PD#SWPL-3424 Problem: dvd play 576p media, tl1 display color anomaly Solution: encoder use same default color setting with decoder Verify: x301 Change-Id: I8954874ea048b2d9e9b7aa58c883da1f306c4459 Signed-off-by: Xuhua Zhang --- drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index 6a058226102c..f463278d2098 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -412,9 +412,9 @@ void vdin_afbce_config(struct vdin_dev_s *devp) int sblk_num; int uncmp_bits; int uncmp_size; - int def_color_0 = 0; - int def_color_1 = 0; - int def_color_2 = 0; + int def_color_0 = 4095; + int def_color_1 = 2048; + int def_color_2 = 2048; int def_color_3 = 0; int hblksize_out = (devp->h_active + 31) >> 5; int vblksize_out = (devp->v_active + 3) >> 2; From d5795f825f68d084d33af01f0ef04c95046ecae8 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Fri, 21 Dec 2018 18:48:07 +0800 Subject: [PATCH 0225/1060] backlight: pwm combo policy bug with level range [2/2] PD#TV-1488 Problem: when only use one pwm, pwm combo policy has a bug with level range Solution: modify level range check demo when set bl level Verify: verify by T962X2-X301 Change-Id: Ia5a0b12fa96f0f77ed85f6f70ed796203ea32a20 Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/backlight/aml_bl.c | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index c38f5c507c28..64b7ff279585 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -330,11 +330,12 @@ static void bl_gpio_set(int index, int value) } } -static inline unsigned int bl_do_div(unsigned long num, unsigned int den) +static inline unsigned int bl_do_div(unsigned long long num, unsigned int den) { unsigned long long ret = num; do_div(ret, den); + return (unsigned int)ret; } @@ -970,7 +971,7 @@ static unsigned int bl_level_mapping(unsigned int level) static void bl_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned long temp; + unsigned long long temp; if (bl_pwm_bypass) return; @@ -1038,7 +1039,7 @@ static void bl_set_level_pwm(struct bl_pwm_config_s *bl_pwm, unsigned int level) unsigned int max = bl_pwm->level_max; unsigned int pwm_max = bl_pwm->pwm_max; unsigned int pwm_min = bl_pwm->pwm_min; - unsigned long temp; + unsigned long long temp; if (bl_pwm_bypass) return; @@ -1129,7 +1130,6 @@ static void bl_set_level_ldim(unsigned int level) static void aml_bl_set_level(unsigned int level) { - unsigned int temp; struct bl_pwm_config_s *pwm0, *pwm1; if (aml_bl_check_driver()) @@ -1163,26 +1163,27 @@ static void aml_bl_set_level(unsigned int level) case BL_CTRL_PWM_COMBO: pwm0 = bl_drv->bconf->bl_pwm_combo0; pwm1 = bl_drv->bconf->bl_pwm_combo1; - if ((level >= pwm0->level_min) && - (level <= pwm0->level_max)) { - temp = (pwm0->level_min > pwm1->level_min) ? - pwm1->level_max : pwm1->level_min; - if (bl_debug_print_flag) { - BLPR("pwm0 region, level=%u, pwm1_level=%u\n", - level, temp); - } + + if (level >= pwm0->level_max) { + bl_set_level_pwm(pwm0, pwm0->level_max); + } else if ((level > pwm0->level_min) && + (level < pwm0->level_max)) { + if (bl_debug_print_flag) + BLPR("pwm0 region, level=%u\n", level); bl_set_level_pwm(pwm0, level); - bl_set_level_pwm(pwm1, temp); - } else if ((level >= pwm1->level_min) && - (level <= pwm1->level_max)) { - temp = (pwm1->level_min > pwm0->level_min) ? - pwm0->level_max : pwm0->level_min; - if (bl_debug_print_flag) { - BLPR("pwm1 region, level=%u, pwm0_level=%u\n", - level, temp); - } - bl_set_level_pwm(pwm0, temp); + } else { + bl_set_level_pwm(pwm0, pwm0->level_min); + } + + if (level >= pwm1->level_max) { + bl_set_level_pwm(pwm1, pwm1->level_max); + } else if ((level > pwm1->level_min) && + (level < pwm1->level_max)) { + if (bl_debug_print_flag) + BLPR("pwm1 region, level=%u,\n", level); bl_set_level_pwm(pwm1, level); + } else { + bl_set_level_pwm(pwm1, pwm1->level_min); } break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING @@ -1291,7 +1292,7 @@ enum bl_pwm_port_e bl_pwm_str_to_pwm(const char *str) void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm) { unsigned int cnt; - unsigned long temp; + unsigned long long temp; if (bl_debug_print_flag) { BLPR("%s pwm_port %d: freq = %u\n", @@ -2873,7 +2874,7 @@ static void bl_debug_pwm_set(unsigned int index, unsigned int value, int state) { struct bl_config_s *bconf = bl_drv->bconf; struct bl_pwm_config_s *bl_pwm = NULL; - unsigned long temp; + unsigned long long temp; unsigned int pwm_range, temp_duty; if (aml_bl_check_driver()) From 4f599b2559185babeaade764671ce71e2aefd8f7 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Tue, 25 Dec 2018 16:24:04 +0800 Subject: [PATCH 0226/1060] tvafe: fix black border for atv [1/1] PD#SWPL-3573 Problem: appear black border after unplug/plug signal Solution: reset de when nosignal restore acd hsync when signal unstable Verify: verified by x301 Change-Id: Ia9e2e9dfb326061bd3b9b6f9a02be0d935cdf06f Signed-off-by: Nian Jing --- drivers/amlogic/media/vin/tvin/tvafe/tvafe.c | 11 ++++++++++ .../amlogic/media/vin/tvin/tvafe/tvafe_cvd.c | 22 +++++++++++++++---- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 2 -- drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c | 10 ++------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index f9e2416f1aa6..fb5d8f2931dd 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -645,6 +645,17 @@ bool tvafe_is_nosig(struct tvin_frontend_s *fe) if ((port >= TVIN_PORT_CVBS0) && (port <= TVIN_PORT_CVBS3)) { ret = tvafe_cvd2_no_sig(&tvafe->cvd2, &devp->mem); + /*fix black side when config atv snow*/ + if (ret && (port == TVIN_PORT_CVBS3) && + (devp->flags & TVAFE_FLAG_DEV_SNOW_FLAG) && + (tvafe->cvd2.config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) && + (tvafe->cvd2.info.state != TVAFE_CVD2_STATE_FIND)) + tvafe_snow_config_acd(); + else if ((tvafe->cvd2.config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) && + (tvafe->cvd2.info.state == TVAFE_CVD2_STATE_FIND) && + (port == TVIN_PORT_CVBS3)) + tvafe_snow_config_acd_resume(); + /* normal sigal & adc reg error, reload source mux */ if (tvafe->cvd2.info.adc_reload_en && !ret) tvafe_set_source_muxing(port, devp->pinmux); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 610992f3afd4..713ceffbc676 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -1872,15 +1872,15 @@ static void tvafe_cvd2_auto_de(struct tvafe_cvd2_s *cvd2) W_APB_REG(ACD_REG_2E, tmp); scene_colorful_old = 0; if (cvd_dbg_en) - tvafe_pr_info("%s: vlines:%d, de_offset:%d tmp:%x\n", + tvafe_pr_info("%s: lrg vlines:%d, de_offset:%d tmp:%x\n", __func__, l_ave, lines->de_offset, tmp); } } else { if (lines->de_offset > 0) { tmp = ((TVAFE_CVD2_PAL_DE_START - - lines->de_offset) << 16) | + lines->de_offset + 1) << 16) | (288 + TVAFE_CVD2_PAL_DE_START - - lines->de_offset); + lines->de_offset + 1); W_APB_REG(ACD_REG_2E, tmp); scene_colorful_old = 0; if (cvd_dbg_en) @@ -1994,6 +1994,12 @@ static void tvafe_cvd2_reinit(struct tvafe_cvd2_s *cvd2) #ifdef TVAFE_SET_CVBS_PGA_EN tvafe_cvd2_reset_pga(); #endif + /*pali to nosignal,restore default vstart-end after auto de*/ + if (cvd2->config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) { + W_APB_REG(ACD_REG_2E, 0x170137); + if (cvd_dbg_en) + pr_info("[tvafe..] %s: reset auto de.\n", __func__); + } /* init variable */ memset(&cvd2->info, 0, sizeof(struct tvafe_cvd2_info_s)); cvd2->cvd2_init_en = true; @@ -2320,6 +2326,15 @@ inline void tvafe_cvd2_adj_hs(struct tvafe_cvd2_s *cvd2, cvd2->info.hs_adj_level = 0; acd_h = acd_h_back; } + } else { + /*signal unstable,set default value*/ + W_APB_REG(ACD_REG_2D, acd_h_back); + W_APB_BIT(CVD2_ACTIVE_VIDEO_HSTART, cvd_2e, + HACTIVE_START_BIT, HACTIVE_START_WID); + W_APB_BIT(ACD_REG_28, acd_128, 16, 5); + cvd2->info.hs_adj_en = 0; + cvd2->info.hs_adj_level = 0; + acd_h = acd_h_back; } } @@ -2637,7 +2652,6 @@ void tvafe_snow_config_acd(void) /*0x8e035e is debug test result*/ if (acd_h_config) W_APB_REG(ACD_REG_2D, acd_h_config); - acd_h = acd_h_back; } /*only for pal-i*/ void tvafe_snow_config_acd_resume(void) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 43e719ef8576..2ffd0eba9ccd 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -367,8 +367,6 @@ extern void ldim_get_matrix(int *data, int reg_sel); extern void ldim_set_matrix(int *data, int reg_sel); extern void tvafe_snow_config(unsigned int onoff); extern void tvafe_snow_config_clamp(unsigned int onoff); -extern void tvafe_snow_config_acd(void); -extern void tvafe_snow_config_acd_resume(void); extern void vdin_vf_reg(struct vdin_dev_s *devp); extern void vdin_vf_unreg(struct vdin_dev_s *devp); extern void vdin_pause_dec(struct vdin_dev_s *devp); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c index 252a3ab0d2d2..4e5a98c39513 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c @@ -332,11 +332,8 @@ void tvin_smr(struct vdin_dev_s *devp) ++sm_p->state_cnt; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AFE if ((port == TVIN_PORT_CVBS3) && - (devp->flags & VDIN_FLAG_SNOW_FLAG)) { + (devp->flags & VDIN_FLAG_SNOW_FLAG)) tvafe_snow_config_clamp(1); - /*fix black side when config atv snow*/ - tvafe_snow_config_acd(); - } #endif if (sm_ops->nosig(devp->frontend)) { sm_p->exit_nosig_cnt = 0; @@ -475,11 +472,8 @@ void tvin_smr(struct vdin_dev_s *devp) devp->unstable_flag = true; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AFE if ((port == TVIN_PORT_CVBS3) && - (devp->flags & VDIN_FLAG_SNOW_FLAG)) { + (devp->flags & VDIN_FLAG_SNOW_FLAG)) tvafe_snow_config_clamp(0); - /*fix black side when config atv snow*/ - tvafe_snow_config_acd_resume(); - } #endif if (sm_ops->nosig(devp->frontend)) { nosig = true; From 08e8d84006cff7035e75fe1b87400a7ad9248cda Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Thu, 27 Dec 2018 20:58:52 +0800 Subject: [PATCH 0227/1060] audio: fix no sound when atv switch to other source [1/1] PD#SWPL-3440 Problem: ATV switch to other source, such as DTV/HDMI/AV, no sound Solution: ATV switch to other source, atv demond is disabled when audio is reading data, so it's blocked. In normal, ATV sends audio data to FRATV, then FRATV sends data to audio fifo, then to DDR. If ATV stops to send audio data, no interrupt from FRATV to fifo, no data is updated to DDR. When exit from audio atv patch, it's a block signal to wait in_read finished, but ATV is disabled TimeCheckThread will check any routine is blocked, if there is one, signal SIGABRT would rise and cause audio server restart So we make a delay before ATV is disabled to waiting audio data is readed. Verify: x301 Change-Id: I47dc88d2c8565c16c739ffea69a88152fa4d5f13 Signed-off-by: Xing Wang --- drivers/amlogic/atv_demod/atv_demod_ops.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index 029d65229e3a..daa43398c679 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -175,6 +175,8 @@ int atv_demod_leave_mode(struct dvb_frontend *fe) priv->state = ATVDEMOD_STATE_IDEL; priv->standby = true; + usleep_range(30 * 1000, 30 * 1000 + 100); + if (priv->afc.disable) priv->afc.disable(&priv->afc); From 700e4b3c003f11c5bcf627e14d8ccba45ed3aacd Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Sat, 29 Dec 2018 14:57:40 +0800 Subject: [PATCH 0228/1060] lcd: modify lcd/power show debug node [1/1] PD#SWPL-1005 Problem: modify lcd/power show debug node Solution: 1,modify lcd/power node to show lcd power on/off Verify: verified by t962x_r311 Change-Id: Ic2b293ac14a3139b572a2e36ac101f9f54da2139 Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/lcd/lcd_debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index b908b5594406..5665b8ccc2da 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -2072,15 +2072,15 @@ static ssize_t lcd_debug_power_show(struct class *class, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int state; - if ((lcd_drv->lcd_status & BL_STATE_LCD_ON) == 0) { + if ((lcd_drv->lcd_status & LCD_STATUS_ON) == 0) { state = 0; } else { - if (lcd_drv->lcd_status & BL_STATE_BL_POWER_ON) + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) state = 1; else state = 0; } - return sprintf(buf, "backlight power state: %d\n", state); + return sprintf(buf, "lcd power state: %d\n", state); } static ssize_t lcd_debug_power_store(struct class *class, From 243604ec6b937014f5c1da7bbad854c84b44a45c Mon Sep 17 00:00:00 2001 From: Zhiwei Yuan Date: Mon, 24 Dec 2018 20:40:35 +0800 Subject: [PATCH 0229/1060] dtv_demod: TL1 dtmb cma allocate fail after dtmb->dvbc->dtmb by cmd [1/1] PD#TV-1748 Problem: [Hisense-T962X2-P-customer-DTV]:Failed to lock frequency in dtmb system Solution: leave the last mode before enter current mode to release the resources Verify: verified by t962x2_x301 Change-Id: Ibd7e1d4c67f5a5ad2191e0031fdd0b81812c8606 Signed-off-by: Zhiwei Yuan --- drivers/amlogic/media/dtv_demod/aml_demod.c | 1 - drivers/amlogic/media/dtv_demod/amlfrontend.c | 331 +++++------------- .../amlogic/media/dtv_demod/include/depend.h | 18 +- 3 files changed, 92 insertions(+), 258 deletions(-) diff --git a/drivers/amlogic/media/dtv_demod/aml_demod.c b/drivers/amlogic/media/dtv_demod/aml_demod.c index ea2b742f3585..cd823674b1b3 100644 --- a/drivers/amlogic/media/dtv_demod/aml_demod.c +++ b/drivers/amlogic/media/dtv_demod/aml_demod.c @@ -649,7 +649,6 @@ static ssize_t aml_demod_dbg_store(struct file *file, case 1://cmd switch (dbg_md) { case AML_DBG_DVBC_INIT: - Gxtv_Demod_Dvbc_v4_Init(); break; case AML_DBG_ATSC_INIT: demod_set_sys_atsc_v4(); diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 0e9f226f8531..6d6cff629fa3 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -51,8 +51,6 @@ #include #include "demod_func.h" -#include "depend.h" /**/ - #include "amlfrontend.h" /*dma_get_cma_size_int_byte*/ @@ -183,19 +181,21 @@ const char *name_fe_delivery_system[] = { "DVBC_ANNEX_C", "ANALOG", /*19*/ }; -void dbg_delsys(unsigned char id) -{ - if (id <= END_SYS_DELIVERY) - PR_INFO("%s:%s:\n", __func__, name_fe_delivery_system[id]); - else - PR_INFO("%s:%d\n", __func__, id); -} +static const char * const name_fe_n_mode[] = { + "AM_FE_UNKNOWN_N", + "AM_FE_QPSK_N", + "AM_FE_QAM_N", + "AM_FE_OFDM_N", + "AM_FE_ATSC_N", + "AM_FE_DTMB_N", + "AM_FE_ISDBT_N", + "AM_FE_NUM", +}; + static void dtvdemod_vdac_enable(bool on); static void dtvdemod_set_agc_pinmux(int on); - - static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode); static ssize_t dvbc_auto_sym_show(struct class *cls, struct class_attribute *attr, char *buf) @@ -1136,194 +1136,6 @@ static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode) return 0; } -#if 0 -/*TL1*/ -void Gxtv_Demod_Dvbc_v4_Init(void) -{ - //struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_dvbc dvbc; - int nco_rate; - int tmp; - - //printf("frequency point is(KHz):"); - //scanf("%d", &tmp); - //dvbc.ch_freq = tmp; - //dvbc.ch_freq = 474000; - dvbc.ch_freq = 474000; - //dvbc.mode = tmp; - dvbc.mode = 4;// 0=16QAM, 1=32QAM, 2 = 64QAM, 3 = 128QAM, 4 = 256QAM - //dvbc.symb_rate = tmp; - dvbc.symb_rate = 5360;//6875;5056(J.83b 64QAM),5360(J.83b 256QAM) - //ioctl(fd, AML_DEMOD_DVBC_SET_CH, &dvbc); - dvbc.dat0 = 24000; - nco_rate = (24*256)/250+2; - - //app_apb_write_reg(0xf00*4,0x88); - demod_write_reg(DEMOD_TOP_REG0, 0x88); - //app_apb_write_reg(0xf08*4,0x201); - demod_write_reg(DEMOD_TOP_REG8, 0x201); - //app_apb_write_reg(0xf0c*4,0x11); //open write enable - demod_write_reg(DEMOD_TOP_REGC, 0x11); - //app_apb_write_reg(0xe20, - //((app_apb_read_reg(0xe20) &~ 0xff) | (nco_rate & 0xff))); - //app_apb_write_reg(0xe20, (app_apb_read_reg(0xe20) | (1 << 8))); - front_write_reg_v4(0x20, - ((front_read_reg_v4(0x20) & ~0xff) | (nco_rate & 0xff))); - front_write_reg_v4(0x20, (front_read_reg_v4(0x20) | (1 << 8))); - - //dvbc_reg_initial_tmp(&dvbc); - dvbc_reg_initial_tmp_v4(&dvbc); - - //printf("set J.83B(1) OR DVBC(2)"); - tmp = 2; - if (tmp == 1) { - //app_apb_write_reg(reg_reset,0x10f33); - qam_write_reg(0x7, 0x10f33); - //set_j83b_filter_reg(); - set_j83b_filter_reg_v4(); - } else { - //app_apb_write_reg(reg_reset,0xf33); - qam_write_reg(0x7, 0xf33); - } - - #if 0 - printf("select 0~3 mode:"); - scanf("%d", &tmp); - if (tmp == 0) { - //set_dvbc_reg_1(); - set_dvbc_reg_1_v4(); - //set_dvbc_reg_2(); - set_dvbc_reg_2_v4(); - } else if (tmp == 1) { - //set_dvbc_reg_1(); - set_dvbc_reg_1_v4(); - //set_j83b_reg_2(); - set_j83b_reg_2_v4(); - } else if (tmp == 2) { - //set_j83b_reg_1(); - set_j83b_reg_1_v4(); - //set_dvbc_reg_2(); - set_dvbc_reg_2_v4(); - } else if (tmp == 3) { - //set_j83b_reg_1(); - set_j83b_reg_1_v4(); - //set_j83b_reg_2(); - set_j83b_reg_2_v4(); - } - #endif - - #if 0 - app_apb_write_reg(0x48, 0x50e1000); - app_apb_write_reg(0xc0, 0x41f2f69); - #else - qam_write_reg(0x12, 0x50e1000); - qam_write_reg(0x30, 0x41f2f69); - #endif -} - -int uart_error_confirm(int a_0, int a_1) -{ - int flag_out_of_range; - int flag_error; - int flag_zero; - int flag_sta_check; - int st[2]; - int out; - - st[0] = a_0&0xf; - st[1] = (a_0>>4)&0xf; - if (st[1] == 0) - flag_sta_check = ((st[0] == 1) || (st[0] == 2)) ? 0 : 1; - if (st[1] == 1) - flag_sta_check = ((st[0] == 2) || (st[0] == 3)) ? 0 : 1; - if (st[1] == 2) - flag_sta_check = (st[0] == 3) ? 0 : 1; - if (st[1] == 3) - flag_sta_check = (st[0] == 4) ? 0 : 1; - if (st[1] == 4) - flag_sta_check = (st[0] == 6) ? 0 : 1; - if (st[1] == 6) - flag_sta_check = ((st[0] == 4) || (st[0] == 5)) ? 0 : 1; - - flag_zero = (a_0 == 0) ? 1 : 0; - flag_out_of_range = ((a_0 & 0xf) > 6) ? 1 : 0; - flag_error = (((a_0 >> 4) & 0x0fffffff) == (a_1 & 0x0fffffff)) ? 0 : 1; - out = ((flag_out_of_range == 1) || (flag_error == 1) - || (flag_zero == 1)) ? 1 : 0; - return out; -} - -void print_dvbc_result(void) -{ - //int timer1, - int time; - int i, tmp; - //float ftmp; - //struct aml_demod_sts sts; - int status[2], uart_error; - int record = 6, cnt = 0, cur_res = 0; - - //timer1 = read_time_usecond(); - status[0] = status[1] = 0; - time = 1; - i = 0; - while (i < time) { - status[0] = qam_read_reg(0x31); - //if((status[0]&0xf) == 5){ - // timer2=read_time_usecond(); - // printf("\n\n\n\n[sync timer]%d\n",timer2-timer1); - // break; - //} - uart_error = uart_error_confirm(status[0], status[1]); - usleep_range(10000, 10001); - status[1] = status[0]; - i = i + 1; - - //lg add state cnt - cur_res = status[1] & 0xf; - if (cur_res != 6) { - record = cur_res; - } else { - if (record != cur_res) - cnt++; - record = cur_res; - } - - // ioctl(fd, AML_DEMOD_DVBC_GET_CH, &sts); - //tmp = sts.ch_sts; - PR_INFO("sta %08x ulock_n %d ", qam_read_reg(0x6), cnt); - //ftmp = sts.ch_snr; - //ftmp /= 100.0; - //ftmp=(app_apb_read_reg(0x174)&0xfff0)/16/32; - //ftmp=(dvbc_read_reg(0x174)&0xfff0)/16/32; - //PR_INFO("snr %5.2f dB ", ftmp); - PR_INFO("eq status is %d ", qam_read_reg(0x5d)&0xf); - PR_INFO("npn_det %d impdet %d imp_n %d ", - qam_read_reg(0x58)>>20&0x1, qam_read_reg(0x58)>>16&0x3, - qam_read_reg(0x58)&0xffff); - // ftmp = sts.ch_ber; - // ftmp /= 1e6; - // printf("ber %.2e ", ftmp); - // if(ber_avg == 0) - // ber_avg = ftmp; - // ber_avg = ber_avg + (ftmp-ber_avg)/32; - // printf("beravg %.2e ", ber_avg); - tmp = (qam_read_reg(0x33)&0xffff); - //tmp = sts.ch_per; - PR_INFO("per %d ", tmp); - //ftmp=(dvbc_read_reg(0x34)&0xffff)/1e3; - // ftmp = sts.symb_rate; - //PR_INFO("srate %.3f ", ftmp); - //ftmp = (dvbc_read_reg(0x28)&0x7fffff)/1e3; - //PR_INFO("freqoff %.3f kHz ", ftmp); - tmp = (qam_read_reg(0x27)); - //PR_INFO("power %ddb,gain %.3d ", - //((tmp>>22) & 0x1ff)/16.0, tmp & 0x7ff); - PR_INFO("lock sta %x\n", qam_read_reg(0x6)); - } -} -#endif - static void gxtv_demod_dvbt_release(struct dvb_frontend *fe) { @@ -2828,14 +2640,17 @@ void dtmb_cma_release(struct amldtvdemod_device_s *devp) } #endif -static bool enter_mode(int mode) +static bool enter_mode(enum aml_fe_n_mode_t mode) { /*struct aml_fe_dev *dev = fe->dtv_demod;*/ struct amldtvdemod_device_s *devn = dtvdd_devp; int memstart_dtmb; bool ret = true; - PR_INFO("%s:%d\n", __func__, mode); + if (mode < AM_FE_NUM) + PR_INFO("%s:%s\n", __func__, name_fe_n_mode[mode]); + else + PR_ERR("%s:%d\n", __func__, mode); dtvdemod_set_agc_pinmux(1); @@ -2855,20 +2670,20 @@ static bool enter_mode(int mode) if (mode == AM_FE_DTMB_N) { Gxtv_Demod_Dtmb_Init(devn); - if (devn->cma_flag == 1) { - PR_DBG("CMA MODE, cma flag is %d,mem size is %d", - devn->cma_flag, devn->cma_mem_size); - if (dtmb_cma_alloc(devn)) { - memstart_dtmb = devn->mem_start; - } else { - ret = false; - return ret; + if (devn->cma_flag == 1) { + PR_DBG("CMA MODE, cma flag is %d,mem size is %d", + devn->cma_flag, devn->cma_mem_size); + if (dtmb_cma_alloc(devn)) { + memstart_dtmb = devn->mem_start; + } else { + ret = false; + return ret; + } + } else { + memstart_dtmb = devn->mem_start;/*??*/ } - } else { - memstart_dtmb = devn->mem_start;/*??*/ - } devn->act_dtmb = true; dtmb_set_mem_st(memstart_dtmb); @@ -2915,14 +2730,19 @@ static bool enter_mode(int mode) } -static int leave_mode(int mode) +static int leave_mode(enum aml_fe_n_mode_t mode) { /* struct aml_fe_dev *dev = fe->dtv_demod;*/ struct amldtvdemod_device_s *devn = dtvdd_devp; - PR_INFO("%s:\n", __func__); + if (mode < AM_FE_NUM) + PR_INFO("%s:%s\n", __func__, name_fe_n_mode[mode]); + else + PR_ERR("%s:%d\n", __func__, mode); + dtvdd_devp->en_detect = 0; dtvdd_devp->last_delsys = SYS_UNDEFINED; + dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; dtvpll_init_flag(0); /*dvbc_timer_exit();*/ @@ -2938,15 +2758,18 @@ static int leave_mode(int mode) dtmb_cma_release(devn); } #else - if (dtvdd_devp->act_dtmb) { - dtmb_poll_stop(); /*polling mode*/ - /* close arbit */ - demod_write_reg(DEMOD_TOP_REGC, 0x0); - dtvdd_devp->act_dtmb = false; - } - if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { - dtmb_cma_release(devn); - dtvdd_devp->flg_cma_allc = false; + if (mode == AM_FE_DTMB_N) { + if (dtvdd_devp->act_dtmb) { + dtmb_poll_stop(); /*polling mode*/ + /* close arbit */ + demod_write_reg(DEMOD_TOP_REGC, 0x0); + dtvdd_devp->act_dtmb = false; + } + + if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { + dtmb_cma_release(devn); + dtvdd_devp->flg_cma_allc = false; + } } #endif @@ -2958,9 +2781,7 @@ static int leave_mode(int mode) dtvdemod_set_agc_pinmux(0); msleep(200); - return 0; - } /* when can't get ic_config by dts, use this*/ const struct meson_ddemod_data data_gxtvbb = { @@ -3599,10 +3420,13 @@ static int __exit aml_dtvdemod_remove(struct platform_device *pdev) static void aml_dtvdemod_shutdown(struct platform_device *pdev) { + enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode; + pr_info("%s\n", __func__); if (dtvdd_devp->state != DTVDEMOD_ST_IDLE) { - leave_mode(0); + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); dtvdd_devp->state = DTVDEMOD_ST_IDLE; } @@ -3792,6 +3616,7 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) } if (!support) { + #if 0 if (get_dtvpll_init_flag()) { /**/ PR_INFO("delsys:%d is not support!\n", cdelsys); @@ -3801,11 +3626,17 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) dtvdd_devp->last_delsys = SYS_UNDEFINED; dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } + #endif + PR_INFO("delsys:%d is not support!\n", cdelsys); return 0; } - PR_DBG("%s:l=%d,c=%d\n", __func__, ldelsys, cdelsys); - dbg_delsys(cdelsys); + if (ldelsys <= END_SYS_DELIVERY && cdelsys <= END_SYS_DELIVERY) { + PR_DBG("%s:l=%s,c=%s\n", __func__, + name_fe_delivery_system[ldelsys], + name_fe_delivery_system[cdelsys]); + } else + PR_ERR("%s:last=%d,cur=%d\n", __func__, ldelsys, cdelsys); switch (cdelsys) { @@ -3869,29 +3700,36 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) case SYS_DAB: case SYS_TURBO: case SYS_UNDEFINED: + return 0; + #ifdef CONFIG_AMLOGIC_DVB_COMPAT case SYS_ANALOG: -#endif - mode = AM_FE_UNKNOWN_N; if (get_dtvpll_init_flag()) { - PR_INFO("delsys not support!%d=\n", cdelsys); - leave_mode(mode); + PR_INFO("delsys not support : %d\n", cdelsys); + leave_mode(lmode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } + return 0; +#endif } if (mode != AM_FE_UNKNOWN_N) { + if (lmode != AM_FE_UNKNOWN_N) { + leave_mode(lmode); + + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); + } + if (!enter_mode(mode)) { PR_INFO("enter_mode failed,leave!\n"); leave_mode(mode); + if (fe->ops.tuner_ops.release) - fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; + fe->ops.tuner_ops.release(fe); return 0; } } @@ -3899,16 +3737,15 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) if (!get_dtvpll_init_flag()) { PR_INFO("pll is not set!\n"); leave_mode(mode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; return 0; } dtvdd_devp->last_delsys = cdelsys; -#if 1 /*ary add for test*/ PR_INFO("info type:%d", fe->ops.info.type); + if (mode == AM_FE_ATSC_N) fe->ops.info.type = FE_ATSC; else if (mode == AM_FE_OFDM_N) @@ -3922,8 +3759,6 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) fe->ops.tuner_ops.set_config(fe, NULL); -#endif - return 0; } @@ -3954,11 +3789,11 @@ static int aml_dtvdm_sleep(struct dvb_frontend *fe) if (get_dtvpll_init_flag()) { PR_INFO("%s\n", __func__); - leave_mode(nmode); + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } return 0; } @@ -4334,11 +4169,11 @@ static void aml_dtvdm_release(struct dvb_frontend *fe) if (get_dtvpll_init_flag()) { PR_INFO("%s\n", __func__); - leave_mode(nmode); + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } } diff --git a/drivers/amlogic/media/dtv_demod/include/depend.h b/drivers/amlogic/media/dtv_demod/include/depend.h index b594c5b63bc6..c664860e223b 100644 --- a/drivers/amlogic/media/dtv_demod/include/depend.h +++ b/drivers/amlogic/media/dtv_demod/include/depend.h @@ -33,21 +33,21 @@ bool aml_dma_release_contiguous(struct device *dev, struct page *pages, /*void ary_test(void);*/ enum aml_fe_n_mode_t { /*same as aml_fe_mode_t in aml_fe.h*/ - AM_FE_UNKNOWN_N = 0, - AM_FE_QPSK_N = 1, - AM_FE_QAM_N = 2, - AM_FE_OFDM_N = 4, - AM_FE_ATSC_N = 8, + AM_FE_UNKNOWN_N, + AM_FE_QPSK_N, + AM_FE_QAM_N, + AM_FE_OFDM_N, + AM_FE_ATSC_N, /*AM_FE_ANALOG = 16,*/ - AM_FE_DTMB_N = 32, - AM_FE_ISDBT_N = 64 + AM_FE_DTMB_N, + AM_FE_ISDBT_N, + AM_FE_NUM, }; - /*----------------------------------*/ struct aml_exp_func { - int (*leave_mode)(int mode); + int (*leave_mode)(enum aml_fe_n_mode_t mode); }; #endif /*__DEPEND_H__*/ From 3b19be11e0da2b44c3ea6041f0cb3310e25a7ead Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Thu, 27 Dec 2018 19:45:56 +0800 Subject: [PATCH 0230/1060] amvecm: disable gamma init in aml_vecm_probe [1/1] PD#SWPL-3143 Problem: boot logo stretched Solution: disable gamma init in aml_vecm_probe Verify: x301 Change-Id: I01a5bb609536edd2875ecad0613565a8382f9aef Signed-off-by: Bencheng Jing --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index ce3a129b76ce..0f6baf0fed58 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -6054,7 +6054,7 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) } /* init module status */ amvecm_wb_init(wb_en); - amvecm_gamma_init(gamma_en); + amvecm_gamma_init(0); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (!is_dolby_vision_enable()) #endif From 96a3556ea515679dabbbf8c28e304e24c74efbeb Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Thu, 3 Jan 2019 14:57:23 +0800 Subject: [PATCH 0231/1060] lcd: The panel's backlight is not stable with VAD enabled platform [1/1] PD#SWPL-3713 Problem: The panel's backlight is not stable when enter standby mode after do suspend with VAD enabled platform Solution: bypass undefind resume in lcd resume early Verify: verify by t962x2-x301 Change-Id: I8f040de9bebf3ccbdd3b2da3a46540fe676958f6 Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/lcd/lcd_vout.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index cab43cb3b124..959e00fd1d35 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -1420,8 +1420,12 @@ static int lcd_remove(struct platform_device *pdev) static int lcd_resume(struct platform_device *pdev) { + if (lcd_debug_print_flag) + LCDPR("resume method: %d\n", get_resume_method()); + if ((get_resume_method() == RTC_WAKEUP) || - (get_resume_method() == AUTO_WAKEUP)) + (get_resume_method() == AUTO_WAKEUP) || + (get_resume_method() == UDEFINED_WAKEUP)) return 0; if ((lcd_driver->lcd_status & LCD_STATUS_VMODE_ACTIVE) == 0) From aa3f89c79f2bd3a007de3782d31fffda6a757565 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Mon, 31 Dec 2018 22:27:47 -0500 Subject: [PATCH 0232/1060] amvecm: Flash a horizontal line when enable local contrast function [1/1] PD#SWPL-3563 Problem: 1.Flash a horizontal line in the bottom of the screen in HDMI with 4K 50/60Hz signal after enable local contrast function 2.local contrast block is obvious when platform reboot Solution: 1.Local contrast write curve with RDMA 2.lc init reset lc module Verify: verify on TL1 Change-Id: Ifd4218e3688d5b0728a6fcba81558467a1c3e05f Signed-off-by: MingLiang Dong --- .../media/enhancement/amvecm/local_contrast.c | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index f690969d9a20..a79b14d51d5f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -38,7 +38,7 @@ int amlc_debug; pr_info("AMVE: " fmt, ## args);\ } while (0) -int lc_en; +int lc_en = 1; int lc_demo_mode; int lc_en_chflg = 0xff; static int lc_flag = 0xff; @@ -496,13 +496,13 @@ static void lc_demo_wr_curve(int h_num, int v_num) (i * h_num + j) + 4] << 10) | (lc_szcurve[6 * (i * h_num + j) + 5] << 20); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp1); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp2); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, temp1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, temp2); } for (j = h_num / 2; j < h_num; j++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, (0|(0<<10)|(512<<20))); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, (1023|(1023<<10)|(512<<20))); } } @@ -551,37 +551,37 @@ static int set_lc_curve(int binit, int bcheck) hvTemp = READ_VPP_REG(SRSHARP1_LC_HV_NUM); h_num = (hvTemp >> 8) & 0x1f; v_num = hvTemp & 0x1f; - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 1, 0, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 1); /*data sequence: ymin/minBv/pkBv/maxBv/ymaxv/ypkBv*/ if (binit) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); for (i = 0; i < h_num * v_num; i++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, (0|(0<<10)|(512<<20))); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, (1023|(1023<<10)|(512<<20))); } } else { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); if (lc_demo_mode) lc_demo_wr_curve(h_num, v_num); else for (i = 0; i < h_num * v_num; i++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, lc_szcurve[6 * i + 0]| (lc_szcurve[6 * i + 1]<<10)| (lc_szcurve[6 * i + 2]<<20)); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, lc_szcurve[6 * i + 3]| (lc_szcurve[6 * i + 4]<<10)| (lc_szcurve[6 * i + 5]<<20)); } } - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 0); if (bcheck) { - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 1, 0, 1); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0 | (1 << 31)); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0 | (1 << 31)); if (lc_demo_mode) rflag = lc_demo_check_curve(h_num, v_num); else @@ -599,7 +599,7 @@ static int set_lc_curve(int binit, int bcheck) if (temp != temp1) rflag = (2 * i + 1) | (1 << 31); } - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 0); } return rflag; @@ -1137,6 +1137,7 @@ void lc_init(void) lc_malloc_ok = 1; if (!lc_en) return; + lc_top_config(0, h_num, v_num, height, width); lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); @@ -1169,6 +1170,11 @@ void lc_process(struct vframe_s *vf, } return; } + + if (lc_flag == 0) { + lc_flag++; + return; + } dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); blk_hnum = (dwTemp >> 8) & 0x1f; blk_vnum = (dwTemp) & 0x1f; From 9901bddd3f9cb0d23d17d64975d7c8233fc86598 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Tue, 1 Jan 2019 01:30:07 -0500 Subject: [PATCH 0233/1060] amvecm: local contrast default low effect parameters [1/1] PD#SWPL-3779 Problem: local contrast default parameters is too high Solution: local contrast default low effect parameters Verify: verify on TL1 Change-Id: Ib7ec9c03284a68057f8cf245a2be8ad2e81c0af3 Signed-off-by: MingLiang Dong --- .../media/enhancement/amvecm/local_contrast.c | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index a79b14d51d5f..aadeaf023b22 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -53,8 +53,8 @@ int invalid_blk = 2; /*u10,7000/21600=0.324*1024=331 */ int min_bv_percent_th = 331; /*control the refresh speed*/ -int alpha1 = 32; -int alpha2 = 2; +int alpha1 = 512; +int alpha2 = 512; int refresh_bit = 12; int ts = 6; /*need tuning according to real situation ! (0~512)*/ @@ -75,6 +75,31 @@ static bool lc_malloc_ok; unsigned int lc_hist_prcnt; unsigned int lc_curve_prcnt; +/*lc saturation gain, low parameters*/ +static unsigned int lc_satur_gain[63] = { + 51, 104, 158, 213, 269, 325, 382, 440, 498, + 556, 615, 674, 734, 794, 854, 915, 976, 1037, + 1099, 1161, 1223, 1286, 1348, 1411, 1475, 1538, + 1602, 1666, 1730, 1795, 1859, 1924, 1989, 2054, + 2120, 2186, 2251, 2318, 2384, 2450, 2517, 2584, + 2651, 2718, 2785, 2853, 2921, 2988, 3057, 3125, + 3193, 3262, 3330, 3399, 3468, 3537, 3607, 3676, + 3746, 3815, 3885, 3955, 4026 +}; + +/*lc saturation gain, low parameters*/ +/* + *static unsigned int lc_satur_off[63] = { + * 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, + * 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, + * 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, + * 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, + * 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, + * 2816, 2880, 2944, 3008, 3072, 3136, 3200, 3264, + * 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, + * 3840, 3904, 3968, 4032 + *}; + */ /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, @@ -1107,6 +1132,7 @@ void lc_init(void) int h_num, v_num; unsigned int height, width; const struct vinfo_s *vinfo = get_current_vinfo(); + int i, tmp, tmp1, tmp2; height = vinfo->height; width = vinfo->width; @@ -1143,6 +1169,25 @@ void lc_init(void) lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); + /*default LC low parameters*/ + WRITE_VPP_REG(LC_CURVE_CONTRAST_LH, 0x000b000b); + WRITE_VPP_REG(LC_CURVE_CONTRAST_SCL_LH, 0x000b000b); + WRITE_VPP_REG(LC_CURVE_MISC0, 0x00023028); + WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, 0x3e69443c); + WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, 0x00000b33); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1, 0x00440088); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_10_11, 0x02d70310); + + for (i = 0; i < 31 ; i++) { + tmp1 = *(lc_satur_gain + 2 * i); + tmp2 = *(lc_satur_gain + 2 * i + 1); + tmp = ((tmp1 & 0xfff)<<16) | (tmp2 & 0xfff); + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i, tmp); + } + tmp = (*(lc_satur_gain + 62)) & 0xfff; + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_62, tmp); + /*end*/ + if (set_lc_curve(1, 0)) pr_amlc_dbg("%s: init fail", __func__); } From 5ffd77d70dc76eb237cd6a2a80a8faf500c21f6a Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Wed, 2 Jan 2019 05:11:43 -0500 Subject: [PATCH 0234/1060] amvecm: cm parameters curve is wrong after disable/enable [1/1] PD#SWPL-3809 Problem: cm parameters curve is wrong after disable/enable Solution: TV cm parameters from pq db, don't need set by kernel Verify: verify on TL1 Change-Id: I9c87c414e009d04c6a4fdf8caf8e9bb429376d56 Signed-off-by: MingLiang Dong --- drivers/amlogic/media/enhancement/amvecm/amcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm.c b/drivers/amlogic/media/enhancement/amvecm/amcm.c index 7a8ad4cf9f35..5247bdc41609 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcm.c @@ -422,7 +422,10 @@ void cm_latch_process(void) } while (0); if (cm_en && (cm_level_last != cm_level)) { cm_level_last = cm_level; - if ((!is_meson_gxtvbb_cpu()) && (!is_meson_txl_cpu())) + if ((!is_meson_gxtvbb_cpu()) && + (!is_meson_txl_cpu()) && + (!is_meson_txlx_cpu()) && + (!is_meson_tl1_cpu())) amcm_level_sel(cm_level); amcm_enable(); pr_amcm_dbg("\n[amcm..] set cm2 load OK!!!\n"); From 99fbaf7076e3d85bc5fea25af129efeeec0ab5cc Mon Sep 17 00:00:00 2001 From: Guosong Zhou Date: Sat, 29 Dec 2018 03:25:55 -0500 Subject: [PATCH 0235/1060] amlvideo2: fix record apk exit [1/1] PD#SWPL-209 Problem: record apk exit when recording Solution: set right start vdin flag Verify: test pass on P321 Change-Id: I0130b5a898392d75d500987f8087dbe9ab778372 Signed-off-by: Guosong Zhou --- .../media/video_processor/video_dev/amlvideo2.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 953a22199f43..9ce0cbb65b89 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -4719,7 +4719,6 @@ static int amlvideo2_stop_tvin_service(struct amlvideo2_node *node) vops->stop_tvin_service(node->vdin_device_num); } - node->start_vdin_flag = 0; return ret; } @@ -4733,7 +4732,7 @@ static int amlvideo2_start_tvin_service(struct amlvideo2_node *node) vinfo = get_current_vinfo(); - if ((!node->start_vdin_flag) || (node->r_type != AML_RECEIVER_NONE)) + if (node->r_type != AML_RECEIVER_NONE) goto start; if (amlvideo2_dbg_en) @@ -4882,7 +4881,7 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, /* if local queue have vf , should give back to provider */ if (vfq_empty(&node->q_ready)) { - if (amlvideo2_dbg_en) + if (amlvideo2_dbg_en & 4) pr_info("q_ready is empty .\n"); } else { recycle_vf = vfq_pop(&node->q_ready); @@ -4890,12 +4889,12 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, vf_put(recycle_vf, node->recv.name); recycle_vf = vfq_pop(&node->q_ready); } - if (amlvideo2_dbg_en) + if (amlvideo2_dbg_en & 4) pr_info("already flush local vf .\n"); } /*debug provider vf state*/ - if (amlvideo2_dbg_en) { + if (amlvideo2_dbg_en & 4) { ret = vf_get_states(vfp, &states); if (ret == 0) { pr_info("vf_pool_size = %d, buf_free_num = %d .\n", @@ -4913,7 +4912,7 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, if (node->r_type == AML_RECEIVER_NONE) amlvideo2_start_thread(node->fh); - msleep(500); + ret = amlvideo2_start_tvin_service(node); if (ret < 0) { From a4893ac948b7d90bdea985db01250523621c15bb Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Mon, 24 Dec 2018 17:33:51 +0800 Subject: [PATCH 0236/1060] tvafe: add atv format get func [1/1] PD#TV-1586 Problem: no atv format get func Solution: Add atv format get func Verify: verified by x301 Change-Id: Ia43d5a67370d2b025e1b32833a5408a5e7d251d4 Signed-off-by: Nian Jing --- drivers/amlogic/media/vin/tvin/tvafe/tvafe.c | 13 +++++++++++++ .../linux/amlogic/media/frame_provider/tvin/tvin.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index fb5d8f2931dd..6cd3ff361f8b 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -976,6 +976,19 @@ static long tvafe_ioctl(struct file *file, __func__, tvin_sig_fmt_str(fmt)); break; } + case TVIN_IOC_G_AFE_CVBS_STD: + { + enum tvin_sig_fmt_e fmt = TVIN_SIG_FMT_NULL; + + if (tvafe->cvd2.info.state == TVAFE_CVD2_STATE_FIND) + fmt = tvafe->cvd2.config_fmt; + if (copy_to_user(argp, &fmt, + sizeof(enum tvin_sig_fmt_e))) + ret = -EFAULT; + tvafe_pr_info("%s: ioctl get fmt:%s.\n", + __func__, tvin_sig_fmt_str(fmt)); + break; + } default: ret = -ENOIOCTLCMD; break; diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index 3fa257f72802..5a1a561a2286 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -441,6 +441,7 @@ struct tvafe_pin_mux_s { #define TVIN_IOC_S_AFE_CVBS_STD _IOW(_TM_T, 0x1b, enum tvin_sig_fmt_e) #define TVIN_IOC_CALLMASTER_SET _IOW(_TM_T, 0x1c, enum tvin_port_e) #define TVIN_IOC_CALLMASTER_GET _IO(_TM_T, 0x1d) +#define TVIN_IOC_G_AFE_CVBS_STD _IOW(_TM_T, 0x1e, enum tvin_sig_fmt_e) #define TVIN_IOC_LOAD_REG _IOW(_TM_T, 0x20, struct am_regs_s) #define TVIN_IOC_S_AFE_SONWON _IO(_TM_T, 0x22) #define TVIN_IOC_S_AFE_SONWOFF _IO(_TM_T, 0x23) From ab82d56b00e27e6a93d1f0926270459163b1c219 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Wed, 9 Jan 2019 04:22:26 -0500 Subject: [PATCH 0237/1060] amvecm: ioctrl get hist ave error [1/1] PD#TV-1950 Problem: VPP_IN_H_V_SIZE register is removed on TL1 Solution: use preblend size to config hist stts size Verify: verify on TL1 Change-Id: I0afc9fd45f69318b2ebd42424aee20e60400d809 Signed-off-by: MingLiang Dong --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 0f6baf0fed58..67a617756ad7 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -780,8 +780,14 @@ void vpp_get_vframe_hist_info(struct vframe_s *vf) unsigned int hist_height, hist_width; u64 divid; - hist_height = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 0, 13); - hist_width = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 16, 13); + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + /*TL1 remove VPP_IN_H_V_SIZE register*/ + hist_width = READ_VPP_REG_BITS(VPP_PREBLEND_H_SIZE, 0, 13); + hist_height = READ_VPP_REG_BITS(VPP_PREBLEND_H_SIZE, 16, 13); + } else { + hist_height = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 0, 13); + hist_width = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 16, 13); + } if ((hist_height != pre_hist_height) || (hist_width != pre_hist_width)) { From 7a284f41ce6e4ed1a578c5abd45b45a14f3ca080 Mon Sep 17 00:00:00 2001 From: Zhiwei Yuan Date: Wed, 26 Dec 2018 18:11:42 +0800 Subject: [PATCH 0238/1060] dtv_demod: TL1 dvbc search time more than 3 min [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-3555 Problem: {DVB-C}Hisense needs less than 3 minutes for dvb-c search.(5/5,None) Solution: 1.use demod internal state machine to optimize time 2.remove j.83b filter setting in dvbc mode for tl1 & txlx Verify: verified by t962x2_x301&t962x_r311 Change-Id: Ic922e3da727179e2e35a0fc80e52ac7242c54129 Signed-off-by: Zhiwei Yuan --- drivers/amlogic/media/dtv_demod/amlfrontend.c | 86 ++++++++++++++----- drivers/amlogic/media/dtv_demod/dvbc_func.c | 2 +- drivers/amlogic/media/dtv_demod/dvbc_v3.c | 63 +++++++------- 3 files changed, 100 insertions(+), 51 deletions(-) diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 6d6cff629fa3..0bea4d35749c 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -933,8 +933,7 @@ static int gxtv_demod_dvbc_read_status_timer struct aml_demod_sts demod_sts; struct aml_demod_sta demod_sta; int strenth; - - int ilock; + int ilock = 0; /*check tuner*/ if (!timer_tuner_not_enough()) { @@ -944,9 +943,11 @@ static int gxtv_demod_dvbc_read_status_timer return 0; } } + /*demod_sts.ch_sts = qam_read_reg(0x6);*/ demod_sts.ch_sts = dvbc_get_ch_sts(); dvbc_status(&demod_sta, /*&demod_i2c,*/ &demod_sts); + if (demod_sts.ch_sts & 0x1) { ilock = 1; *status = @@ -963,6 +964,7 @@ static int gxtv_demod_dvbc_read_status_timer timer_disable(D_TIMER_DETECT); } } + if (last_lock != ilock) { PR_DBG("%s.\n", ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); @@ -972,6 +974,60 @@ static int gxtv_demod_dvbc_read_status_timer return 0; } +static int demod_dvbc_speed_up(enum fe_status *status) +{ + unsigned int cnt, i, sts, check_ok = 0; + struct aml_demod_sts demod_sts; + const int dvbc_count = 5; + int ilock = 0; + + if (*status == 0) { + for (cnt = 0; cnt < 10; cnt++) { + demod_sts.ch_sts = dvbc_get_ch_sts(); + + if (demod_sts.ch_sts & 0x1) { + /*have signal*/ + *status = + FE_HAS_LOCK | FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC; + ilock = 1; + check_ok = 1; + } else { + for (i = 0; i < dvbc_count; i++) { + sts = dvbc_get_status(); + + if (sts >= 0x3) + break; + + msleep(25); + } + + PR_DBG("[rsj]dvbc_status is 0x%x\n", sts); + + if (sts < 0x3) { + *status = FE_TIMEDOUT; + ilock = 0; + check_ok = 1; + } + } + + if (check_ok == 1) + break; + + msleep(20); + } + } + + if (last_lock != ilock) { + PR_DBG("%s : %s.\n", __func__, + ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); + last_lock = ilock; + } + + return 0; +} + static int gxtv_demod_dvbc_read_ber(struct dvb_frontend *fe, u32 *ber) { /*struct aml_fe_dev *dev = afe->dtv_demod;*/ @@ -1018,7 +1074,6 @@ static int gxtv_demod_dvbc_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) } /*extern int aml_fe_analog_set_frontend(struct dvb_frontend *fe);*/ - static int gxtv_demod_dvbc_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; @@ -1028,7 +1083,6 @@ static int gxtv_demod_dvbc_set_frontend(struct dvb_frontend *fe) PR_INFO("%s\n", __func__); /*timer_set_max(D_TIMER_DETECT, 4000);*/ /*timer_begain(D_TIMER_DETECT);*/ - memset(¶m, 0, sizeof(param)); param.ch_freq = c->frequency / 1000; param.mode = amdemod_qam(c->modulation); @@ -1567,8 +1621,8 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) if (atsc_flag != QAM_AUTO) atsc_flag = QAM_AUTO; /* demod_set_demod_reg(0x502, TXLX_ADC_REG6);*/ - if (!is_ic_ver(IC_VER_TL1)) - dd_tvafe_hiu_reg_write(D_HHI_DEMOD_CLK_CNTL, 0x502); + //sys_clk=167M + dd_tvafe_hiu_reg_write(D_HHI_DEMOD_CLK_CNTL, 0x502); demod_set_mode_ts(Gxtv_Dvbc); param_j83b.ch_freq = c->frequency / 1000; @@ -1589,7 +1643,6 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) ((front_read_reg_v4(0x20) & ~0xff) | (nco_rate & 0xff))); front_write_reg_v4(0x2f, 0x5);//for timeshift mosaic - dd_tvafe_hiu_reg_write(0x1d0, 0x502);//sys_clk=167M } dvbc_set_ch(&demod_status, /*&demod_i2c, */¶m_j83b); @@ -1599,8 +1652,6 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) set_j83b_filter_reg_v4(); qam_write_reg(0x12, 0x50e1000); qam_write_reg(0x30, 0x41f2f69); - //for timeshift mosaic issue - //qam_write_reg(0x84, 0x2190000); } } else if (c->modulation > QAM_AUTO) { @@ -1641,9 +1692,6 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) } } - if (is_ic_ver(IC_VER_TL1)) - return 0; - if ((auto_search_std == 1) && ((c->modulation <= QAM_AUTO) && (c->modulation != QPSK))) { unsigned char s = 0; @@ -1815,11 +1863,6 @@ static int atsc_j83b_detect_first(struct dvb_frontend *fe, enum fe_status *s) for (cnt = 0; cnt < CNT_FIRST; cnt++) { gxtv_demod_atsc_read_status(fe, &cs); - if (is_ic_ver(IC_VER_TL1)) { - *s = cs; - return 0; - } - if (cs != 0x1f) { /*msleep(200);*/ PR_DBG("[j.83b] 1\n"); @@ -2458,9 +2501,8 @@ int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev) return 0; } + #ifdef DVB_CORE_ORI - - static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, enum fe_status *status) { @@ -2471,7 +2513,6 @@ static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, *delay = HZ / 4; -#if 1 if (re_tune) { /*first*/ dtvdd_devp->en_detect = 1; @@ -2481,11 +2522,14 @@ static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, timer_begain(D_TIMER_DETECT); gxtv_demod_dvbc_read_status_timer(fe, status); + if (is_ic_ver(IC_VER_TL1)) + demod_dvbc_speed_up(status); + PR_DBG("tune finish!\n"); return ret; } -#endif + if (!dtvdd_devp->en_detect) { PR_DBGL("tune:not enable\n"); return ret; diff --git a/drivers/amlogic/media/dtv_demod/dvbc_func.c b/drivers/amlogic/media/dtv_demod/dvbc_func.c index ca2ac4e98827..8bbb208c6074 100644 --- a/drivers/amlogic/media/dtv_demod/dvbc_func.c +++ b/drivers/amlogic/media/dtv_demod/dvbc_func.c @@ -331,7 +331,7 @@ int dvbc_set_ch(struct aml_demod_sta *demod_sta, ret = -1; } /* if (ret != 0) return ret; */ - demod_sta->dvb_mode = 0; + //demod_sta->dvb_mode = 0; demod_sta->ch_mode = mode; /* 0:16, 1:32, 2:64, 3:128, 4:256 */ demod_sta->agc_mode = 1; diff --git a/drivers/amlogic/media/dtv_demod/dvbc_v3.c b/drivers/amlogic/media/dtv_demod/dvbc_v3.c index 92bd3ccc007a..3457a51ec07a 100644 --- a/drivers/amlogic/media/dtv_demod/dvbc_v3.c +++ b/drivers/amlogic/media/dtv_demod/dvbc_v3.c @@ -367,8 +367,10 @@ void dvbc_reg_initial(struct aml_demod_sta *demod_sta) /* // configure min symbol_rate fb = 6.95M*/ qam_write_reg(0x12, (qam_read_reg(0x12) & ~(0xff<<8)) | 3400 * 256); + #if 0 if (is_ic_ver(IC_VER_TL1)) qam_write_reg(0x51, (qam_read_reg(0x51)&~(0x1<<28))); + #endif /* configure min symbol_rate fb = 6.95M */ /*dvbc_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */ @@ -432,40 +434,43 @@ void dvbc_reg_initial(struct aml_demod_sta *demod_sta) /* enable irq */ qam_write_reg(0x34, 0x7fff << 3); -#if 1 + /*if (is_meson_txlx_cpu()) {*/ - if (is_ic_ver(IC_VER_TXLX)) { + if (is_ic_ver(IC_VER_TXLX) || (is_ic_ver(IC_VER_TL1))) { /*my_tool setting j83b mode*/ qam_write_reg(0x7, 0x10f33); - /*j83b filter para*/ - qam_write_reg(0x40, 0x3f010201); - qam_write_reg(0x41, 0x0a003a3b); - qam_write_reg(0x42, 0xe1ee030e); - qam_write_reg(0x43, 0x002601f2); - qam_write_reg(0x44, 0x009b006b); - qam_write_reg(0x45, 0xb3a1905); - qam_write_reg(0x46, 0x1c396e07); - qam_write_reg(0x47, 0x3801cc08); - qam_write_reg(0x48, 0x10800a2); - qam_write_reg(0x12, 0x50e1000); - qam_write_reg(0x30, 0x41f2f69); - /*j83b_symbolrate(please see register doc)*/ - qam_write_reg(0x4d, 0x23d125f7); - /*for phase noise case 256qam*/ - qam_write_reg(0x9c, 0x2a232100); - qam_write_reg(0x57, 0x606040d); - /*for phase noise case 64qam*/ - qam_write_reg(0x54, 0x606050d); - qam_write_reg(0x52, 0x346dc); + + if (demod_sta->dvb_mode == Gxtv_Atsc || + is_ic_ver(IC_VER_TXLX)) { + /*j83b filter para*/ + qam_write_reg(0x40, 0x3f010201); + qam_write_reg(0x41, 0x0a003a3b); + qam_write_reg(0x42, 0xe1ee030e); + qam_write_reg(0x43, 0x002601f2); + qam_write_reg(0x44, 0x009b006b); + qam_write_reg(0x45, 0xb3a1905); + qam_write_reg(0x46, 0x1c396e07); + qam_write_reg(0x47, 0x3801cc08); + qam_write_reg(0x48, 0x10800a2); + qam_write_reg(0x12, 0x50e1000); + qam_write_reg(0x30, 0x41f2f69); + /*j83b_symbolrate(please see register doc)*/ + qam_write_reg(0x4d, 0x23d125f7); + /*for phase noise case 256qam*/ + qam_write_reg(0x9c, 0x2a232100); + qam_write_reg(0x57, 0x606040d); + /*for phase noise case 64qam*/ + qam_write_reg(0x54, 0x606050d); + qam_write_reg(0x52, 0x346dc); + } + qam_auto_scan(1); } -#endif - if (!is_ic_ver(IC_VER_TL1)) { - qam_write_reg(0x7, 0x10f23); - qam_write_reg(0x3a, 0x0); - qam_write_reg(0x7, 0x10f33); - qam_write_reg(0x3a, 0x4); - } + + qam_write_reg(0x7, 0x10f23); + qam_write_reg(0x3a, 0x0); + qam_write_reg(0x7, 0x10f33); + qam_write_reg(0x3a, 0x4); /*auto track*/ /* dvbc_set_auto_symtrack(); */ } From da675fd53cade00403669924154b16c29f3811ed Mon Sep 17 00:00:00 2001 From: Zhiwei Yuan Date: Thu, 10 Jan 2019 13:52:36 +0800 Subject: [PATCH 0239/1060] dtv_demod: TXLX ISDB-T can't search channel [1/1] PD#SWPL-3987 Problem: [Einstein]use ISDB-T cannot search any channel Solution: release cma memory at leave_mode for ISDB-t&DVB-T Verify: verified by t962x_r311 Change-Id: I9b79687a4d5270932ab30afaa3e7d2817e900149 Signed-off-by: Zhiwei Yuan --- drivers/amlogic/media/dtv_demod/amlfrontend.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 0bea4d35749c..24a823f0bc75 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -2752,6 +2752,7 @@ static bool enter_mode(enum aml_fe_n_mode_t mode) timer_set_max(D_TIMER_DETECT, 2000); /*reset is 4s*/ timer_set_max(D_TIMER_SET, 4000); + if (devn->cma_flag == 1) { PR_DBG("CMA MODE, cma flag is %d,mem size is %d", devn->cma_flag, @@ -2761,11 +2762,11 @@ static bool enter_mode(enum aml_fe_n_mode_t mode) } else { ret = false; return ret; - } } else { memstart_dtmb = devn->mem_start;/*??*/ } + PR_DBG("[im]memstart is %x\n", memstart_dtmb); dvbt_write_reg((0x10 << 2), memstart_dtmb); } @@ -2792,16 +2793,7 @@ static int leave_mode(enum aml_fe_n_mode_t mode) /*dvbc_timer_exit();*/ if (cci_thread) dvbc_kill_cci_task(); - #if 0 - if (mode == AM_FE_DTMB_N) { - dtmb_poll_stop(); /*polling mode*/ - /* close arbit */ - demod_write_reg(DEMOD_TOP_REGC, 0x0); - if (devn->cma_flag == 1) - dtmb_cma_release(devn); - } - #else if (mode == AM_FE_DTMB_N) { if (dtvdd_devp->act_dtmb) { dtmb_poll_stop(); /*polling mode*/ @@ -2810,12 +2802,16 @@ static int leave_mode(enum aml_fe_n_mode_t mode) dtvdd_devp->act_dtmb = false; } + if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { + dtmb_cma_release(devn); + dtvdd_devp->flg_cma_allc = false; + } + } else if (mode == AM_FE_OFDM_N || mode == AM_FE_ISDBT_N) { if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { dtmb_cma_release(devn); dtvdd_devp->flg_cma_allc = false; } } - #endif adc_set_pll_cntl(0, 0x04, NULL); demod_mode_para = UNKNOWN; From d8ea5e68bff2e834b5b140b8be84d192e5c36d91 Mon Sep 17 00:00:00 2001 From: Dianzhong Huo Date: Thu, 10 Jan 2019 17:06:14 +0800 Subject: [PATCH 0240/1060] galcore: removed reserve memory for galcore driver [1/1] PD#SWPL-4087 Problem: System Memory needs to be optimized. Solution: Removed reserve memory for galcore. Verify: local Change-Id: I4fc1d7690b6beda1055aebe26570a05f28474813 Signed-off-by: Dianzhong Huo --- arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 47d8ef62c109..d1a9d6dff4bc 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -155,7 +155,7 @@ galcore_reserved:linux,galcore { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x1000000>; + size = <0x0 0x0>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index eb322602c8a2..9bc1928e28d8 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -154,7 +154,7 @@ galcore_reserved:linux,galcore { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x1000000>; + size = <0x0 0x0>; alignment = <0x0 0x400000>; linux,contiguous-region; }; From a5f622c6e75e2bd746df8111b565c609693f2c68 Mon Sep 17 00:00:00 2001 From: "qiu.zeng" Date: Wed, 9 Jan 2019 15:09:05 +0800 Subject: [PATCH 0241/1060] BT: bt mac write [1/3] PD#OTT-1590 Problem: bt mac write Solution: Accept the MAC address from uboot and create nodes Verify: Verifying on Public Edition P212 Change-Id: I77ff3543aff937adc07bf3a0933a350c27e9dd20 Signed-off-by: Qiu Zeng --- drivers/amlogic/bluetooth/bt_device.c | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/amlogic/bluetooth/bt_device.c b/drivers/amlogic/bluetooth/bt_device.c index c926f13f7f6f..3d7afc4e687c 100644 --- a/drivers/amlogic/bluetooth/bt_device.c +++ b/drivers/amlogic/bluetooth/bt_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_AM_WIFI_SD_MMC #include #endif @@ -44,6 +45,48 @@ static struct early_suspend bt_early_suspend; #define BT_RFKILL "bt_rfkill" +char bt_addr[18] = ""; +static struct class *bt_addr_class; +static ssize_t bt_addr_show(struct class *cls, + struct class_attribute *attr, char *_buf) +{ + char local_addr[6]; + + if (!_buf) + return -EINVAL; + + if (strlen(bt_addr) == 0) { + local_addr[0] = 0x22; + local_addr[1] = 0x22; + local_addr[2] = prandom_u32(); + local_addr[3] = prandom_u32(); + local_addr[4] = prandom_u32(); + local_addr[5] = prandom_u32(); + sprintf(bt_addr, "%02x:%02x:%02x:%02x:%02x:%02x", + local_addr[0], local_addr[1], local_addr[2], + local_addr[3], local_addr[4], local_addr[5]); + } + + return sprintf(_buf, "%s\n", bt_addr); +} +static ssize_t bt_addr_store(struct class *cls, + struct class_attribute *attr, const char __user *buf, size_t count) +{ + int ret = -EINVAL; + + if (!buf) + return ret; + + snprintf(bt_addr, sizeof(bt_addr), "%s", buf); + + if (bt_addr[strlen(bt_addr)-1] == '\n') + bt_addr[strlen(bt_addr)-1] = '\0'; + + pr_info("bt_addr=%s\n", bt_addr); + return count; +} +static CLASS_ATTR(value, 0644, bt_addr_show, bt_addr_store); + struct bt_dev_runtime_data { struct rfkill *bt_rfk; struct bt_dev_data *pdata; @@ -281,6 +324,9 @@ static int bt_probe(struct platform_device *pdev) #else pdata = (struct bt_dev_data *)(pdev->dev.platform_data); #endif + bt_addr_class = class_create(THIS_MODULE, "bt_addr"); + ret = class_create_file(bt_addr_class, &class_attr_value); + bt_device_init(pdata); if (pdata->power_down_disable == 1) { pdata->power_down_disable = 0; @@ -402,3 +448,21 @@ module_exit(bt_exit); MODULE_DESCRIPTION("bt rfkill"); MODULE_AUTHOR(""); MODULE_LICENSE("GPL"); + +/**************** bt mac *****************/ + +static int __init mac_addr_set(char *line) +{ + + if (line) { + pr_info("try to read bt mac from emmc key!\n"); + strncpy(bt_addr, line, sizeof(bt_addr)-1); + bt_addr[sizeof(bt_addr)-1] = '\0'; + } + + return 1; +} + +__setup("mac_bt=", mac_addr_set); + + From f1cab606e1c66d65f374cb93d491135a5e193e2c Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Fri, 11 Jan 2019 14:32:30 +0800 Subject: [PATCH 0242/1060] amvecm: modify gamma_init to avoid lcd black screen after resume [1/1] PD#SWPL-4101 Problem: lcd black screen after resume Solution: init gamma data Verify: x301 Change-Id: Ibc04a96f00948bc4780c3eb1452bca1c6ae92961 Signed-off-by: Bencheng Jing --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 67a617756ad7..bb2c88ac559c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5798,16 +5798,16 @@ void amvecm_gamma_init(bool en) unsigned int i; unsigned short data[256]; + for (i = 0; i < 256; i++) { + data[i] = i << 2; + video_gamma_table_r.data[i] = data[i]; + video_gamma_table_g.data[i] = data[i]; + video_gamma_table_b.data[i] = data[i]; + } + if (en) { WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1); - - for (i = 0; i < 256; i++) { - data[i] = i << 2; - video_gamma_table_r.data[i] = data[i]; - video_gamma_table_g.data[i] = data[i]; - video_gamma_table_b.data[i] = data[i]; - } amve_write_gamma_table( data, H_SEL_R); From ff3a6f2ecca15d972e3c858621efc7ddf53a7e06 Mon Sep 17 00:00:00 2001 From: long yu Date: Fri, 11 Jan 2019 14:55:35 +0800 Subject: [PATCH 0243/1060] storage: emmc: Set core_phase to 2 for HS200 mode [1/1] PD#TV-2112 Problem: eMMC timing test failed on item tISU Solution: set core_phase to 2 for HS200 busmode Verify: TL1-T962X2_X301 Change-Id: I1025b6b6b66b2591b7a8faca68ff1852eeb9b85c Signed-off-by: long yu --- drivers/amlogic/mmc/aml_sd_emmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index aa294b62f709..fdbd53170c49 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3637,7 +3637,7 @@ static struct meson_mmc_data mmc_data_tl1 = { .sdmmc.init.rx_phase = 0, .sdmmc.hs.core_phase = 1, .sdmmc.ddr.core_phase = 2, - .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.core_phase = 2, .sdmmc.hs4.tx_delay = 0, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, From 5c8fab1dd07413c6e3d39ed1cb98d4a943cba509 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Thu, 10 Jan 2019 10:35:14 +0800 Subject: [PATCH 0244/1060] mm: fix dead loop if signal pending for cma alloc task [1/1] PD#GH-17 Problem: If a task be killed during CMA allocation, then it will abort cma allocation in function compact_unlock_should_abort. But in function aml_cma_alloc_range, it will return -EBUSY. Which cause cma allocation loop won't exit and run again and again. Solution: return -EINT for this case to exit cma allocaion loop. Verify: newman platform Change-Id: I6559bb184fc035ae68c8ccd001407767e1e22f0c Signed-off-by: Tao Zeng --- drivers/amlogic/memory_ext/aml_cma.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/memory_ext/aml_cma.c b/drivers/amlogic/memory_ext/aml_cma.c index 450af9a1439a..1eabadbdbc07 100644 --- a/drivers/amlogic/memory_ext/aml_cma.c +++ b/drivers/amlogic/memory_ext/aml_cma.c @@ -577,6 +577,7 @@ int aml_cma_alloc_range(unsigned long start, unsigned long end) .mode = MIGRATE_SYNC, .page_type = COMPACT_CMA, .ignore_skip_hint = true, + .contended = false, }; INIT_LIST_HEAD(&cc.migratepages); @@ -611,11 +612,8 @@ try_again: outer_start = start; while (!PageBuddy(pfn_to_page(outer_start))) { if (++order >= MAX_ORDER) { - ret = -EBUSY; - try_times++; - if (try_times < 10) - goto try_again; - goto done; + outer_start = start; + break; } outer_start &= ~0UL << order; } @@ -647,7 +645,11 @@ try_again: /* Grab isolated pages from freelists. */ outer_end = isolate_freepages_range(&cc, outer_start, end); if (!outer_end) { - ret = -EBUSY; + if (cc.contended) { + ret = -EINTR; + pr_info("cma_alloc [%lx-%lx] aborted\n", start, end); + } else + ret = -EBUSY; goto done; } From 97bd5986aea90525e095b304b644e623518bf35c Mon Sep 17 00:00:00 2001 From: tao zeng Date: Tue, 27 Nov 2018 12:26:53 +0800 Subject: [PATCH 0245/1060] mm: add cma debug interafce [1/1] PD#GH-17 Problem: sometimes cma allocation failed but it's hard to get failed log and need recompile code. Solution: Add /proc/cma_debug to open cma debug message dynamic. By default, no debug message is printed. If you write a value large than 0 to this node, debug message will be printed. Verify: p212 Change-Id: Ibcfd1d48be5f33f674f09df713dc2e493748c405 Signed-off-by: tao zeng --- drivers/amlogic/memory_ext/aml_cma.c | 115 +++++++++++++++++---------- include/linux/amlogic/aml_cma.h | 12 +++ mm/cma.c | 5 ++ mm/compaction.c | 79 +++++++++++++++++- mm/migrate.c | 25 ++++++ 5 files changed, 195 insertions(+), 41 deletions(-) diff --git a/drivers/amlogic/memory_ext/aml_cma.c b/drivers/amlogic/memory_ext/aml_cma.c index 1eabadbdbc07..7f8b96c9945a 100644 --- a/drivers/amlogic/memory_ext/aml_cma.c +++ b/drivers/amlogic/memory_ext/aml_cma.c @@ -30,11 +30,14 @@ #include #include #include +#include #include #ifdef CONFIG_AMLOGIC_PAGE_TRACE #include #endif /* CONFIG_AMLOGIC_PAGE_TRACE */ +#define MAX_DEBUG_LEVEL 5 + struct work_cma { struct list_head list; unsigned long pfn; @@ -52,6 +55,8 @@ struct cma_pcp { static bool can_boost; static DEFINE_PER_CPU(struct cma_pcp, cma_pcp_thread); +static struct proc_dir_entry *dentry; +int cma_debug_level; DEFINE_SPINLOCK(cma_iso_lock); static atomic_t cma_allocate; @@ -261,6 +266,7 @@ static int aml_alloc_contig_migrate_range(struct compact_control *cc, pfn = isolate_migratepages_range(cc, pfn, end); if (!pfn) { ret = -EINTR; + cma_debug(1, NULL, " iso migrate page fail\n"); break; } tries = 0; @@ -336,7 +342,7 @@ static int cma_boost_work_func(void *cma_data) drain_local_pages(NULL); } if (ret) - pr_debug("%s, failed, ret:%d\n", __func__, ret); + cma_debug(1, NULL, "failed, ret:%d\n", ret); next: complete(&c_work->end); if (kthread_should_stop()) { @@ -441,34 +447,6 @@ int cma_alloc_contig_boost(unsigned long start_pfn, unsigned long count) return ret; } -/* - * Some of these functions are implemented from page_isolate.c - */ -static bool can_free_list_page(struct page *page, struct list_head *list) -{ -#if 0 - unsigned long flags; - bool ret = false; - - if (!spin_trylock_irqsave(&cma_iso_lock, flags)) - return ret; - - if (!(page->flags & PAGE_FLAGS_CHECK_AT_FREE) && - !PageSwapBacked(page) && - (page->lru.next != LIST_POISON1)) { - if (list_empty(&page->lru)) - list_add(&page->lru, list); - else - list_move(&page->lru, list); - ret = true; - } - spin_unlock_irqrestore(&cma_iso_lock, flags); - return ret; -#else - return false; -#endif -} - static int __aml_check_pageblock_isolate(unsigned long pfn, unsigned long end_pfn, bool skip_hwpoisoned_pages, @@ -496,13 +474,7 @@ static int __aml_check_pageblock_isolate(unsigned long pfn, */ pfn++; } else { - /* This page can be freed ? */ - if (!page_count(page)) { - if (can_free_list_page(page, list)) { - pfn++; - continue; - } - } + cma_debug(1, page, " isolate failed\n"); break; } } @@ -581,11 +553,14 @@ int aml_cma_alloc_range(unsigned long start, unsigned long end) }; INIT_LIST_HEAD(&cc.migratepages); + cma_debug(0, NULL, " range [%lx-%lx]\n", start, end); ret = start_isolate_page_range(get_align_pfn_low(start), get_align_pfn_high(end), MIGRATE_CMA, false); - if (ret) + if (ret) { + cma_debug(1, NULL, "ret:%d\n", ret); return ret; + } try_again: /* @@ -600,8 +575,10 @@ try_again: } else ret = aml_alloc_contig_migrate_range(&cc, start, end, 0); - if (ret && ret != -EBUSY) + if (ret && ret != -EBUSY) { + cma_debug(1, NULL, "ret:%d\n", ret); goto done; + } ret = 0; if (!boost_ok) { @@ -633,8 +610,8 @@ try_again: /* Make sure the range is really isolated. */ if (aml_check_pages_isolated(outer_start, end, false)) { - pr_debug("%s check_pages_isolated(%lx, %lx) failed\n", - __func__, outer_start, end); + cma_debug(1, NULL, "check page isolate(%lx, %lx) failed\n", + outer_start, end); try_times++; if (try_times < 10) goto try_again; @@ -650,6 +627,8 @@ try_again: pr_info("cma_alloc [%lx-%lx] aborted\n", start, end); } else ret = -EBUSY; + cma_debug(1, NULL, "iso free range(%lx, %lx) failed\n", + outer_start, end); goto done; } @@ -733,11 +712,67 @@ void aml_cma_free(unsigned long pfn, unsigned int nr_pages) } EXPORT_SYMBOL(aml_cma_free); +void show_page(struct page *page) +{ + unsigned long trace = 0; + + if (!page) + return; +#ifdef CONFIG_AMLOGIC_PAGE_TRACE + trace = get_page_trace(page); +#endif + pr_info("page:%lx, map:%p, f:%lx, m:%d, c:%d, f:%pf\n", + page_to_pfn(page), page->mapping, + page->flags & 0xffffffff, + page_mapcount(page), page_count(page), + (void *)trace); +} + +static int cma_debug_show(struct seq_file *m, void *arg) +{ + seq_printf(m, "level=%d\n", cma_debug_level); + return 0; +} + +static ssize_t cma_debug_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + int arg = 0; + + if (kstrtoint_from_user(buffer, count, 10, &arg)) + return -EINVAL; + + if (arg > MAX_DEBUG_LEVEL) + return -EINVAL; + + cma_debug_level = arg; + return count; +} + +static int cma_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, cma_debug_show, NULL); +} + +static const struct file_operations cma_dbg_file_ops = { + .open = cma_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .write = cma_debug_write, + .release = single_release, +}; + static int __init aml_cma_init(void) { atomic_set(&cma_allocate, 0); atomic_long_set(&nr_cma_allocated, 0); + dentry = proc_create("cma_debug", 0644, NULL, &cma_dbg_file_ops); + if (IS_ERR_OR_NULL(dentry)) { + pr_err("%s, create sysfs failed\n", __func__); + return -1; + } + return 0; } arch_initcall(aml_cma_init); diff --git a/include/linux/amlogic/aml_cma.h b/include/linux/amlogic/aml_cma.h index 4acb96ffb455..621acac67087 100644 --- a/include/linux/amlogic/aml_cma.h +++ b/include/linux/amlogic/aml_cma.h @@ -74,6 +74,7 @@ extern bool cma_page(struct page *page); extern unsigned long get_cma_allocated(void); extern unsigned long get_total_cmapages(void); extern spinlock_t cma_iso_lock; +extern int cma_debug_level; extern int aml_cma_alloc_range(unsigned long start, unsigned long end); extern void aml_cma_free(unsigned long pfn, unsigned int nr_pages); @@ -81,6 +82,7 @@ extern void aml_cma_free(unsigned long pfn, unsigned int nr_pages); extern unsigned long reclaim_clean_pages_from_list(struct zone *zone, struct list_head *page_list); +extern void show_page(struct page *page); unsigned long isolate_freepages_range(struct compact_control *cc, unsigned long start_pfn, unsigned long end_pfn); @@ -91,4 +93,14 @@ isolate_migratepages_range(struct compact_control *cc, struct page *compaction_cma_alloc(struct page *migratepage, unsigned long data, int **result); + +#define cma_debug(l, p, format, args...) \ + { \ + if (l < cma_debug_level) { \ + show_page(p); \ + pr_info("%s, %d "format, __func__, __LINE__, ##args); \ + } \ + } + + #endif /* __AMLOGIC_CMA_H__ */ diff --git a/mm/cma.c b/mm/cma.c index b59c2da8ce01..b4c8aca77982 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -511,6 +511,10 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) pr_debug("%s(cma %p, count %zu, align %d)\n", __func__, (void *)cma, count, align); +#ifdef CONFIG_AMLOGIC_CMA + cma_debug(0, NULL, "(cma %p, count %zu, align %d)\n", + (void *)cma, count, align); +#endif if (!count) return NULL; @@ -572,6 +576,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) #ifdef CONFIG_AMLOGIC_CMA aml_cma_alloc_post_hook(&dummy, count, page); + cma_debug(0, NULL, "return %p\n", page); #endif /* CONFIG_AMLOGIC_CMA */ pr_debug("%s(): returned %p\n", __func__, page); return page; diff --git a/mm/compaction.c b/mm/compaction.c index e35f49150e2b..665760fdc1f2 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -434,14 +434,34 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, * contention, to give chance to IRQs. Abort if fatal signal * pending or async compaction detects need_resched() */ + #ifdef CONFIG_AMLOGIC_CMA + if (!(blockpfn % SWAP_CLUSTER_MAX) + && compact_unlock_should_abort(&cc->zone->lock, flags, + &locked, cc)) { + if (strict) + cma_debug(1, page, "abort, blk:%lx, swap:%ld\n", + blockpfn, SWAP_CLUSTER_MAX); + break; + } + #else if (!(blockpfn % SWAP_CLUSTER_MAX) && compact_unlock_should_abort(&cc->zone->lock, flags, &locked, cc)) break; + #endif nr_scanned++; + #ifdef CONFIG_AMLOGIC_CMA + if (!pfn_valid_within(blockpfn)) { + if (strict) + cma_debug(1, page, "invalid pfn:%lx\n", + blockpfn); + goto isolate_fail; + } + #else if (!pfn_valid_within(blockpfn)) goto isolate_fail; + #endif if (!valid_page) valid_page = page; @@ -459,12 +479,25 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, blockpfn += (1UL << comp_order) - 1; cursor += (1UL << comp_order) - 1; } - + #ifdef CONFIG_AMLOGIC_CMA + if (strict) + cma_debug(1, page, "compound page:%lx\n", + page_to_pfn(page)); + #endif goto isolate_fail; } + #ifdef CONFIG_AMLOGIC_CMA + if (!PageBuddy(page)) { + if (strict) + cma_debug(1, page, " NO buddy page1:%lx\n", + page_to_pfn(page)); + goto isolate_fail; + } + #else if (!PageBuddy(page)) goto isolate_fail; + #endif /* * If we already hold the lock, we can skip some rechecking. @@ -484,19 +517,44 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, */ locked = compact_trylock_irqsave(&cc->zone->lock, &flags, cc); + #ifdef CONFIG_AMLOGIC_CMA + if (!locked) { + if (strict) + cma_debug(1, page, " lock failed:%lx\n", + page_to_pfn(page)); + break; + } + /* Recheck this is a buddy page under lock */ + if (!PageBuddy(page)) { + if (strict) + cma_debug(1, page, " No buddy2:%lx\n", + page_to_pfn(page)); + goto isolate_fail; + } + #else if (!locked) break; /* Recheck this is a buddy page under lock */ if (!PageBuddy(page)) goto isolate_fail; + #endif } /* Found a free page, will break it into order-0 pages */ order = page_order(page); isolated = __isolate_free_page(page, order); + #ifdef CONFIG_AMLOGIC_CMA + if (!isolated) { + if (strict) + cma_debug(1, page, "iso free fail:%lx, o:%d\n", + page_to_pfn(page), order); + break; + } + #else if (!isolated) break; + #endif set_page_private(page, order); total_isolated += isolated; @@ -599,9 +657,17 @@ isolate_freepages_range(struct compact_control *cc, block_end_pfn = min(block_end_pfn, end_pfn); } + #ifdef CONFIG_AMLOGIC_CMA + if (!pageblock_pfn_to_page(block_start_pfn, + block_end_pfn, cc->zone)) { + cma_debug(1, NULL, " no page block\n"); + break; + } + #else if (!pageblock_pfn_to_page(block_start_pfn, block_end_pfn, cc->zone)) break; + #endif isolated = isolate_freepages_block(cc, &isolate_start_pfn, block_end_pfn, &freelist, true); @@ -611,8 +677,15 @@ isolate_freepages_range(struct compact_control *cc, * there are any holes in the block (ie. invalid PFNs or * non-free pages). */ + #ifdef CONFIG_AMLOGIC_CMA + if (!isolated) { + cma_debug(1, NULL, " isolate free page failed\n"); + break; + } + #else if (!isolated) break; + #endif /* * If we managed to isolate pages, it is always (1 << n) * @@ -626,6 +699,10 @@ isolate_freepages_range(struct compact_control *cc, if (pfn < end_pfn) { /* Loop terminated early, cleanup. */ + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(1, NULL, "pfn:%lx, end:%lx, start:%lx\n", + pfn, end_pfn, start_pfn); + #endif release_freepages(&freelist); return 0; } diff --git a/mm/migrate.c b/mm/migrate.c index b810ac1359f0..e5b14b0b5f34 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -415,6 +415,11 @@ int migrate_page_move_mapping(struct address_space *mapping, if (!mapping) { /* Anonymous page without mapping */ + #ifdef CONFIG_AMLOGIC_CMA + if (page_count(page) != expected_count) + cma_debug(2, page, " anon page cnt miss match, e:%d\n", + expected_count); + #endif if (page_count(page) != expected_count) return -EAGAIN; @@ -439,6 +444,10 @@ int migrate_page_move_mapping(struct address_space *mapping, if (page_count(page) != expected_count || radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) { spin_unlock_irq(&mapping->tree_lock); + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(2, page, " anon page cnt miss match, e:%d, p:%d\n", + expected_count, page_has_private(page)); + #endif return -EAGAIN; } @@ -1017,11 +1026,21 @@ static int __unmap_and_move(struct page *page, struct page *newpage, goto out_unlock_both; } } else if (page_mapped(page)) { + #ifdef CONFIG_AMLOGIC_CMA + int ret; + + ret = try_to_unmap(page, + TTU_MIGRATION | TTU_IGNORE_MLOCK | + TTU_IGNORE_ACCESS); + if (ret != SWAP_SUCCESS) + cma_debug(2, page, " unmap failed:%d\n", ret); + #else /* Establish migration ptes */ VM_BUG_ON_PAGE(PageAnon(page) && !PageKsm(page) && !anon_vma, page); try_to_unmap(page, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS); + #endif page_was_mapped = 1; } @@ -1355,6 +1374,9 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, switch(rc) { case -ENOMEM: nr_failed++; + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(2, page, " NO MEM\n"); + #endif goto out; case -EAGAIN: retry++; @@ -1370,6 +1392,9 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, * retried in the next outer loop. */ nr_failed++; + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(2, page, " failed:%d\n", rc); + #endif break; } } From 60930b8a871f824dc1d62db69d86ad9d17b6e4cb Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Thu, 3 Jan 2019 20:36:22 +0800 Subject: [PATCH 0246/1060] ge2d: add support for nv16 [1/1] PD#SWPL-3876 Problem: add support for nv16 Solution: add support for nv16 Verify: verified on g12a-u200 Change-Id: I34c9179ed4fde43b9bd00caa9505ea4c8ee78eb0 Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2dgen.c | 9 ++++++++- include/linux/amlogic/media/ge2d/ge2d.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2dgen.c b/drivers/amlogic/media/common/ge2d/ge2dgen.c index 687b2a675eaf..2fa47aa138b6 100644 --- a/drivers/amlogic/media/common/ge2d/ge2dgen.c +++ b/drivers/amlogic/media/common/ge2d/ge2dgen.c @@ -87,6 +87,8 @@ static inline void _set_dst_format( unsigned int format_src, unsigned int format_dst) { + unsigned int y_yc_ratio; + src2_dst_data_cfg->dst_format_all = format_dst; src2_dst_data_cfg->dst_format = (format_dst >> 8) & 3; src2_dst_data_cfg->dst_endian = (format_dst & GE2D_ENDIAN_MASK) >> @@ -112,6 +114,8 @@ static inline void _set_dst_format( } else dp_gen_cfg->conv_matrix_en = 0; + y_yc_ratio = (format_dst >> 0) & 1; + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ /* for dest is nv21 or nv12 in m6. */ if ((format_dst & GE2D_FORMAT_YUV) && @@ -119,7 +123,10 @@ static inline void _set_dst_format( src2_dst_data_cfg->dst_format = 0; src2_dst_data_cfg->dst_mode_8b_sel = 0; src2_dst_data_cfg->dst2_pixel_byte_width = 1; - src2_dst_data_cfg->dst2_discard_mode = 0xf; + if (y_yc_ratio == 0) + src2_dst_data_cfg->dst2_discard_mode = 0xc; + else + src2_dst_data_cfg->dst2_discard_mode = 0xf; src2_dst_data_cfg->dst2_enable = 1; src2_dst_data_cfg->dst2_color_map = src2_dst_data_cfg->dst_color_map - 5; diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index c3fdd915b454..0f2a0b4532d6 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -240,6 +240,7 @@ enum ge2d_memtype_s { #define GE2D_FMT_M24_YUV420B 0x2001f /* 00_00_0_11_1_11 */ #define GE2D_FMT_M24_YUV420SP 0x20207 +#define GE2D_FMT_M24_YUV422SP 0x20206 /* 01_00_0_00_1_11 nv12 &nv21, only works on m6. */ #define GE2D_FMT_M24_YUV420SPT 0x20217 /* 01_00_0_00_1_11 nv12 &nv21, only works on m6. */ @@ -295,6 +296,7 @@ enum ge2d_memtype_s { #define GE2D_FORMAT_M24_RGB GE2D_FMT_M24_RGB #define GE2D_FORMAT_M24_YUV420T GE2D_FMT_M24_YUV420T #define GE2D_FORMAT_M24_YUV420B GE2D_FMT_M24_YUV420B +#define GE2D_FORMAT_M24_YUV422SP (GE2D_FMT_M24_YUV422SP | GE2D_COLOR_MAP_NV12) #define GE2D_FORMAT_S16_YUV422T (GE2D_FMT_S16_YUV422T | GE2D_COLOR_MAP_YUV422) #define GE2D_FORMAT_S16_YUV422B (GE2D_FMT_S16_YUV422B | GE2D_COLOR_MAP_YUV422) #define GE2D_FORMAT_S24_YUV444T (GE2D_FMT_S24_YUV444T | GE2D_COLOR_MAP_YUV444) From 734352b5e87cd7bae40061d19d071b42de7f5ebb Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Thu, 10 Jan 2019 16:55:53 +0800 Subject: [PATCH 0247/1060] ge2d: fix strechblit issue for GE2D [1/2] PD#SWPL-4075 Problem: dst data is not normal by using strechblit function such as 1920x1080 --> 640x360 Solution: add bit width restriction for horizontal scaler initial phase Verify: verified on g12b-w400 Change-Id: Ibcd85cc08f49254e90100beb952e711736531134 Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 85d5657f0081..497fbf8f9f79 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -977,7 +977,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) ge2d_reg_write(GE2D_HSC_INI_CTRL, (cfg->hsc_rpt_p0_num << 29) | (cfg->hsc_adv_num << 24) | - (cfg->hsc_ini_phase << 0) + ((cfg->hsc_ini_phase & 0xffffff) << 0) ); #else ge2d_reg_write(GE2D_HSC_ADV_CTRL, @@ -986,7 +986,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) ); ge2d_reg_write(GE2D_HSC_INI_CTRL, (cfg->hsc_rpt_p0_num << 29) | - (cfg->hsc_ini_phase << 0) + ((cfg->hsc_ini_phase & 0xffffff) << 0) ); #endif From 2ed15e0b15972dc51f8436f2d31307c8c15fd692 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 11 Jan 2019 14:30:40 +0800 Subject: [PATCH 0248/1060] ge2d: add enhanced hsc adv num support [2/2] PD#SWPL-4075 Problem: add enhanced hsc adv num support Solution: add enhanced hsc adv num support Verify: verified on g12b-w400 Change-Id: I13b52a0b10e8f3830c57ff691ef3472a34cbe89c Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_hw.c | 4 ++-- include/linux/amlogic/media/ge2d/ge2d.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 497fbf8f9f79..3a886ff35a99 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -894,9 +894,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) cfg->hsc_div_length = (124 << 24) / cfg->hsc_phase_step; multo = cfg->hsc_phase_step * cfg->hsc_div_length; -#ifndef CONFIG_GE2D_ADV_NUM cfg->hsc_adv_num = multo >> 24; -#endif cfg->hsc_adv_phase = multo & 0xffffff; } @@ -974,6 +972,8 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) ); if (cfg->hsc_adv_num > 255) cfg->hsc_adv_num = cfg->hsc_adv_num >> 8; + else + cfg->hsc_adv_num = 0; ge2d_reg_write(GE2D_HSC_INI_CTRL, (cfg->hsc_rpt_p0_num << 29) | (cfg->hsc_adv_num << 24) | diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index 0f2a0b4532d6..279c447f4208 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -37,7 +37,7 @@ enum ge2d_memtype_s { #define MAX_BITBLT_WORK_CONFIG 4 #define MAX_GE2D_CMD 32 /* 64 */ -/* #define CONFIG_GE2D_ADV_NUM */ +#define CONFIG_GE2D_ADV_NUM #define CONFIG_GE2D_SRC2 #define GE2D_STATE_IDLE 0 #define GE2D_STATE_RUNNING 1 From 52b3d4e4d26000074bea7dbad629d1214ecde179 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Mon, 14 Jan 2019 01:07:07 -0500 Subject: [PATCH 0249/1060] amvecm: DNLP curve read error [1/1] PD#SWPL-4139 Problem: DNLP curve buffer is not clean Solution: memset dnlp curve buf 0 Verify: verify on TL1 Change-Id: Ibf37a8bfa52cdcb2d8c848c94a0d32d0391c8742 Signed-off-by: MingLiang Dong --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index bb2c88ac559c..12ab50d3ced7 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -1695,9 +1695,11 @@ static void d_convert_str(int num, if (bit_chose == 10) snprintf(buf, sizeof(buf), "%d", num); - if (bit_chose == 16) + else if (bit_chose == 16) snprintf(buf, sizeof(buf), "%x", num); count = strlen(buf); + if (count > 4) + count = 4; for (i = 0; i < count; i++) buf[i + char_bit] = buf[i]; for (i = 0; i < char_bit; i++) @@ -1730,6 +1732,8 @@ static ssize_t amvecm_dnlp_debug_store(struct class *cla, stemp = kmalloc(400, GFP_KERNEL); if (!stemp) return 0; + memset(stemp, 0, 400); + buf_orig = kstrdup(buf, GFP_KERNEL); parse_param_amvecm(buf_orig, (char **)&parm); From 44a8ac06b29b5970f27af8043f4bdb417811499e Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Mon, 14 Jan 2019 04:59:00 -0500 Subject: [PATCH 0250/1060] amvecm: add disable gamma pattern [1/1] PD#TV-2138 Problem: after set gamma pattern, pattern can not resume Solution: add disable gamma pattern cmd Verify: verify on TL1 Change-Id: I5b123dce185c5f80e21b5e5e4a18ad65f7db626b Signed-off-by: MingLiang Dong --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 12ab50d3ced7..7df8181c58c6 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -2775,6 +2775,8 @@ static ssize_t set_gamma_pattern_show(struct class *cla, pr_info("8bit: echo r g b > /sys/class/amvecm/gamma_pattern\n"); pr_info("10bit: echo r g b 0xa > /sys/class/amvecm/gamma_pattern\n"); pr_info(" r g b should be hex\n"); + pr_info("disable gamma pattern:\n"); + pr_info("echo disable > /sys/class/amvecm/gamma_pattern\n"); return 0; } @@ -2804,6 +2806,14 @@ static ssize_t set_gamma_pattern_store(struct class *cls, parm[n++] = token; } + if (!strcmp(parm[0], "disable")) { + vecm_latch_flag |= FLAG_GAMMA_TABLE_R; + vecm_latch_flag |= FLAG_GAMMA_TABLE_G; + vecm_latch_flag |= FLAG_GAMMA_TABLE_B; + kfree(buf_orig); + return count; + } + if (*(parm + 3) != NULL) { if (kstrtol(parm[3], 16, &val) < 0) { kfree(buf_orig); From 656b3db016093c3f572d949b72cb2871136ca43a Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Mon, 14 Jan 2019 18:56:54 +0800 Subject: [PATCH 0251/1060] build: fix build err [1/1] PD#SWPL-4150 Problem: When switch to the toolchain shipped with android P, multipile "-Werror=maybe-uninitialized" error occurs, and the code fail to be compiled Solution: Initialize variables if necessary Verify: Locally on Ampere Change-Id: I280de648914565656831e211539bf41a7dee2b4a Signed-off-by: Jiamin Ma --- drivers/amlogic/media/common/canvas/canvas_mgr.c | 2 +- drivers/amlogic/media/dtv_demod/amlfrontend.c | 4 +++- drivers/media/tuners/xc5000.c | 2 +- kernel/compat.c | 5 +++++ kernel/time/posix-cpu-timers.c | 4 ++++ kernel/time/time.c | 5 +++++ net/unix/af_unix.c | 4 ++++ 7 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index 56ab75ddb3c3..db416df15659 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -375,7 +375,7 @@ canvas_pool_map_show(struct class *class, int ret; int i; ssize_t size = 0; - struct canvas_info info; + struct canvas_info info = {NULL, 0, NULL, 0}; struct canvas_s canvas; if (jiffies - pool->last_cat_map > 5 * HZ) { diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 24a823f0bc75..86fbf09285b6 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -1845,6 +1845,8 @@ static int atsc_j83b_detect_first(struct dvb_frontend *fe, enum fe_status *s) int cnt; int check_ok; + j83b_status = 0; + /*tuner:*/ if (dvb_tuner_delay > 9) msleep(dvb_tuner_delay); @@ -1911,7 +1913,7 @@ static int atsc_j83b_polling(struct dvb_frontend *fe, enum fe_status *s) PR_DBG("+7+"); - + j83b_status = 0; strenth = tuner_get_ch_power(fe); if (strenth < THRD_TUNER_STRENTH_J83) { *s = FE_TIMEDOUT; diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index e6e5e90d8d95..2f44e5c0a6c0 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c @@ -931,7 +931,7 @@ static void xc5000_config_tv(struct dvb_frontend *fe, static int xc5000_set_tv_freq(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; - u16 pll_lock_status; + u16 pll_lock_status = 0; int ret; tune_channel: diff --git a/kernel/compat.c b/kernel/compat.c index 333d364be29d..57ccf3c3d036 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -112,6 +112,11 @@ COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, struct timespec new_ts; struct timezone new_tz; +#ifdef CONFIG_AMLOGIC_MODIFY + new_ts.tv_sec = 0; + new_ts.tv_nsec = 0; +#endif + if (tv) { if (compat_get_timeval(&user_tv, tv)) return -EFAULT; diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 21a27bb73587..1ac61891f2fa 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1222,6 +1222,10 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, { unsigned long long now; +#ifdef CONFIG_AMLOGIC_MODIFY + now = 0; +#endif + WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED); cpu_timer_sample_group(clock_idx, tsk, &now); diff --git a/kernel/time/time.c b/kernel/time/time.c index a5b6d98ea7b1..9c2526a986dc 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -198,6 +198,11 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, struct timespec new_ts; struct timezone new_tz; +#ifdef CONFIG_AMLOGIC_MODIFY + new_ts.tv_sec = 0; + new_ts.tv_nsec = 0; +#endif + if (tv) { if (copy_from_user(&user_tv, tv, sizeof(*tv))) return -EFAULT; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index cecf51a5aec4..f5afd24a8008 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -997,6 +997,10 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct hlist_head *list; struct path path = { NULL, NULL }; +#ifdef CONFIG_AMLOGIC_MODIFY + hash = 0; +#endif + err = -EINVAL; if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) From 74222bc60bc8e929151c89efda2be425d5077277 Mon Sep 17 00:00:00 2001 From: Zhiwei Yuan Date: Mon, 14 Jan 2019 18:38:15 +0800 Subject: [PATCH 0252/1060] dtv_demod: txlx atsc-t loses lock when play video for a long time [1/1] PD#SWPL-3418 Problem: [Einstein]when AC off/on,enter live TV , TV display blank screen and no signal about 5S Solution: use post-eq to track(0x912=0x50) Verify: verified by t962x_r311 Change-Id: I924c55a8f1c92328e4371cb730e1b03bd720457f Signed-off-by: Zhiwei Yuan --- drivers/amlogic/media/dtv_demod/amlfrontend.c | 6 ++++++ drivers/amlogic/media/dtv_demod/atsc_func.c | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 86fbf09285b6..780c4fdedef8 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -1952,6 +1952,9 @@ void atsc_polling(struct dvb_frontend *fe, enum fe_status *status) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; + if (!demod_thread) + return; + if (c->modulation == QPSK) { PR_DBG("mode is qpsk, return;\n"); /*return;*/ @@ -2515,6 +2518,9 @@ static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, *delay = HZ / 4; + if (!demod_thread) + return 0; + if (re_tune) { /*first*/ dtvdd_devp->en_detect = 1; diff --git a/drivers/amlogic/media/dtv_demod/atsc_func.c b/drivers/amlogic/media/dtv_demod/atsc_func.c index d95b1ef53ad2..1c1159624189 100644 --- a/drivers/amlogic/media/dtv_demod/atsc_func.c +++ b/drivers/amlogic/media/dtv_demod/atsc_func.c @@ -565,6 +565,7 @@ if (!field_test_version) { atsc_write_reg(0x54d, 0x08); atsc_write_reg(0x54c, 0x08); atsc_write_reg(0x53b, 0x0e); + atsc_write_reg(0x912, 0x50); } ar_flag = 0; } From ba34b486a6ac0e49521a4f01df5f6028d488fd29 Mon Sep 17 00:00:00 2001 From: "yu.zhang" Date: Wed, 16 Jan 2019 16:48:32 +0800 Subject: [PATCH 0253/1060] dts: add ir cut control GPIO to g12b_a311d_w400_buildroot.dts [1/1] PD#SWPL-4272 Problem: g12b_a311d_w400_buildroot.dts do not include add ir cut control GPIO Solution: add ir cut control GPIO to g12b_a311d_w400_buildroot.dts Verify: g12b_a311d_w400_buildroot Change-Id: I771ea08ad6ab189060079b820a471e059b5eb72a Signed-off-by: yu.zhang --- arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 ++ arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 116c457c7c1b..95913de50b65 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -852,6 +852,8 @@ clocks = <&clkc CLKID_24M>; clock-names = "g12a_24m"; reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; }; iq: iq { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 9bc1928e28d8..bd14cfd777ec 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -851,6 +851,8 @@ clocks = <&clkc CLKID_24M>; clock-names = "g12a_24m"; reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; }; iq: iq { From eca8b14c645335937214ac1c8371f43ea7d7ac65 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Wed, 16 Jan 2019 19:44:40 +0800 Subject: [PATCH 0254/1060] tvin: vdin: fix system crash when dolby vision enable [1/1] PD#SWPL-3353 Problem: system crash when dolby vision enable Solution: 32bit kernel,phy addr to virt interface is changed Verify: Verified on txlx R311 Change-Id: Ie012bdaf7f9dc24acf7a7e03f0db056ff31e578c Signed-off-by: Xuhua Zhang --- .../amlogic/media/vin/tvin/vdin/vdin_ctl.c | 57 +++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index 0267eb643771..9f35315f4454 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -3481,6 +3482,7 @@ void vdin_force_gofiled(struct vdin_dev_s *devp) void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) { unsigned int index, alloc_size; + int highmem_flag; alloc_size = dolby_size_byte*size; devp->dv.dv_dma_vaddr = dma_alloc_coherent(&devp->this_pdev->dev, @@ -3490,21 +3492,45 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) return; } memset(devp->dv.dv_dma_vaddr, 0, alloc_size); + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + for (index = 0; index < size; index++) { devp->vfp->dv_buf_mem[index] = devp->dv.dv_dma_paddr + dolby_size_byte * index; devp->vfp->dv_buf_vmem[index] = devp->dv.dv_dma_vaddr + dolby_size_byte * index; - if ((devp->cma_config_flag & 0x100) && devp->cma_config_en) - devp->vfp->dv_buf_ori[index] = - phys_to_virt(devp->vfmem_start[index] + - devp->vfmem_size - - dolby_size_byte); - else - devp->vfp->dv_buf_ori[index] = - phys_to_virt(devp->mem_start + devp->mem_size - - dolby_size_byte * - (devp->canvas_max_num - index)); + + if (highmem_flag == 0) { + if ((devp->cma_config_flag & 0x100) + && devp->cma_config_en) + devp->vfp->dv_buf_ori[index] = + phys_to_virt(devp->vfmem_start[index] + + devp->vfmem_size - + dolby_size_byte); + else + devp->vfp->dv_buf_ori[index] = + phys_to_virt(devp->mem_start + + devp->mem_size - + dolby_size_byte * + (devp->canvas_max_num - index)); + } else { + if ((devp->cma_config_flag & 0x100) + && devp->cma_config_en) + devp->vfp->dv_buf_ori[index] = + codec_mm_vmap(devp->vfmem_start[index] + + devp->vfmem_size-dolby_size_byte, + dolby_size_byte); + else + devp->vfp->dv_buf_ori[index] = + codec_mm_vmap(devp->mem_start + + devp->mem_size - + dolby_size_byte * + (devp->canvas_max_num - index), + dolby_size_byte); + } pr_info("%s:dv_buf[%d]=0x%p(0x%x,0x%p)\n", __func__, index, devp->vfp->dv_buf_ori[index], devp->vfp->dv_buf_mem[index], @@ -3516,6 +3542,17 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size) { unsigned int alloc_size; + int highmem_flag, index; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + for (index = 0; index < size; index++) { + if (highmem_flag == 1) + codec_mm_unmap_phyaddr(devp->vfp->dv_buf_ori[index]); + } alloc_size = dolby_size_byte*size; if (devp->dv.dv_dma_vaddr) From cf6fc20370eabc90a8b359b3dc7752ce918a3e31 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Fri, 18 Jan 2019 16:50:15 +0800 Subject: [PATCH 0255/1060] tvin: vdin: fix dolby vision memory free print error [1/1] PD#SWPL-3353 Problem: dolby vision memory free print error Solution: dolby vision memory has been free by vdin_cma_release, don't free again. Verify: test pass on R311 Change-Id: Id7108cf17260430c53dff707e843ed7833c8ee7c Signed-off-by: Xuhua Zhang --- drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index 9f35315f4454..6522883a82f5 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -3542,17 +3542,6 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size) { unsigned int alloc_size; - int highmem_flag, index; - - if (devp->cma_config_flag & 0x100) - highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); - else - highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); - - for (index = 0; index < size; index++) { - if (highmem_flag == 1) - codec_mm_unmap_phyaddr(devp->vfp->dv_buf_ori[index]); - } alloc_size = dolby_size_byte*size; if (devp->dv.dv_dma_vaddr) From 556555c1f747525004d61efdb34dfd719e5aeb1b Mon Sep 17 00:00:00 2001 From: Rongjun Chen Date: Wed, 16 Jan 2019 16:27:35 +0800 Subject: [PATCH 0256/1060] wifi: export set_usb_wifi_power [1/1] PD#TV-2088 Problem: wifi can not power in driver Solution: export set_usb_wifi_power Verify: franklin Change-Id: Ic6fb75133533c395cd96e9d82f14427cf40cee96 Signed-off-by: Rongjun Chen --- drivers/amlogic/wifi/wifi_dt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/wifi/wifi_dt.c b/drivers/amlogic/wifi/wifi_dt.c index 8a3219bb6e75..4601edb798a1 100644 --- a/drivers/amlogic/wifi/wifi_dt.c +++ b/drivers/amlogic/wifi/wifi_dt.c @@ -236,7 +236,7 @@ void set_usb_wifi_power(int is_power) { usb_power_control(is_power, WIFI_BIT); } - +EXPORT_SYMBOL(set_usb_wifi_power); static int wifi_power_open(struct inode *inode, struct file *file) { struct cdev *cdevp = inode->i_cdev; From b4eece89e4b44cc0c90eca745e108028244ba018 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Fri, 18 Jan 2019 19:12:44 +0800 Subject: [PATCH 0257/1060] atv_demod: Optimizing ATV auto scan Speed. [1/2] PD#SWPL-4123 Problem: Optimizing ATV auto scan Speed. Solution: optimizing the step of scanning. Verify: verified by x301 Change-Id: I0f616f14488be49be67c40eca7fc9f30108545b8 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_debug.c | 2 ++ drivers/amlogic/atv_demod/atv_demod_ops.c | 21 +++------------------ 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index d85343cae3a7..ff8e6e18d163 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -52,6 +52,8 @@ DEBUGFS_CREATE_NODE(aud_std, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(aud_mode, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(aud_auto, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(aud_reinit, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(aud_mono_only, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(over_threshold, 0640, dentry, u64)\ DEBUGFS_CREATE_NODE(input_amplitude, 0640, dentry, u64)\ DEBUGFS_CREATE_NODE(atvaudio_det_outputmode_en, 0640, dentry, bool)\ diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index daa43398c679..9fd8cad431b6 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -435,7 +435,7 @@ static struct analog_demod_ops atvdemod_ops = { }; -unsigned int tuner_status_cnt = 8; /* 4-->16 test on sky mxl661 */ +unsigned int tuner_status_cnt = 4; /* 4-->16 test on sky mxl661 */ bool slow_mode; @@ -956,7 +956,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) pr_dbg("[%s] slow mode to search the channel\n", __func__); afc_step = ATV_AFC_1_0MHZ; } else if (!slow_mode) { - afc_step = ATV_AFC_2_0MHZ; + afc_step = p->afc_range/* ATV_AFC_2_0MHZ */; } else { pr_dbg("[%s] slow mode to search the channel\n", __func__); afc_step = ATV_AFC_1_0MHZ; @@ -1077,7 +1077,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) auto_search_std, &std_bk, &audio); - pr_dbg("[%s] freq:%d, std_bk:0x%x, audmode:0x%x, search OK.\n", + pr_info("[%s] freq:%d, std_bk:0x%x, audmode:0x%x, search OK.\n", __func__, p->frequency, (unsigned int) std_bk, audio); @@ -1098,21 +1098,6 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) } } - /*avoid sound format is not match after search over */ - if (std_bk != 0 && audio != 0) { - p->std = std_bk; - p->audmode = audio; - - params.frequency = p->frequency; - params.mode = p->afc_range; - params.audmode = p->audmode; - params.std = p->std; - - fe->ops.analog_ops.set_params(fe, ¶ms); - std_bk = 0; - audio = 0; - } - pr_dbg("[%s] freq[analog.std:0x%08x] is[%d] unlock\n", __func__, (uint32_t) p->std, p->frequency); From 912a387486aa836071333117670dd2df8c873352 Mon Sep 17 00:00:00 2001 From: wenbiao zhang Date: Fri, 18 Jan 2019 17:03:54 +0800 Subject: [PATCH 0258/1060] bandwidth: fix wrong bandwidth usage on t950 [1/3] PD#TV-470 Problem: t950 ddr bandwidth usage is error Solution: t950/805x ddr is 16bit, correct the param to get right usage Verify: t950 Change-Id: Ice876f82e5c33e778b3ac9f593e0c163d57d7f3f Signed-off-by: wenbiao zhang --- drivers/amlogic/ddr_tool/ddr_bandwidth.c | 15 +++++++++++---- include/linux/amlogic/aml_ddr_bandwidth.h | 1 + include/linux/amlogic/cpu_version.h | 5 +++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/ddr_tool/ddr_bandwidth.c b/drivers/amlogic/ddr_tool/ddr_bandwidth.c index 941233529524..fcb43354794f 100644 --- a/drivers/amlogic/ddr_tool/ddr_bandwidth.c +++ b/drivers/amlogic/ddr_tool/ddr_bandwidth.c @@ -74,7 +74,7 @@ static void cal_ddr_usage(struct ddr_bandwidth *db, struct ddr_grant *dg) freq = db->ops->get_freq(db); mul = dg->all_grant; mul *= 10000ULL; - mul /= 16; + do_div(mul, db->bytes_per_cycle); cnt = db->clock_count; do_div(mul, cnt); db->total_usage = mul; @@ -203,7 +203,8 @@ static ssize_t threshold_show(struct class *cla, struct class_attribute *attr, char *buf) { return sprintf(buf, "%d\n", - aml_db->threshold / 16 / (aml_db->clock_count / 10000)); + aml_db->threshold / aml_db->bytes_per_cycle + / (aml_db->clock_count / 10000)); } static ssize_t threshold_store(struct class *cla, @@ -218,7 +219,8 @@ static ssize_t threshold_store(struct class *cla, if (val > 10000) val = 10000; - aml_db->threshold = val * 16 * (aml_db->clock_count / 10000); + aml_db->threshold = val * aml_db->bytes_per_cycle + * (aml_db->clock_count / 10000); return count; } @@ -545,6 +547,11 @@ static int __init ddr_bandwidth_probe(struct platform_device *pdev) goto inval; } + if (is_meson_txl_package_950() || is_meson_gxl_package_805X()) + aml_db->bytes_per_cycle = 8; + else + aml_db->bytes_per_cycle = 16; + /* set channel */ if (aml_db->cpu_type < MESON_CPU_MAJOR_ID_GXTVBB) { aml_db->channels = 1; @@ -599,7 +606,7 @@ static int __init ddr_bandwidth_probe(struct platform_device *pdev) #endif aml_db->clock_count = DEFAULT_CLK_CNT; aml_db->mode = MODE_DISABLE; - aml_db->threshold = DEFAULT_THRESHOLD * 16 * + aml_db->threshold = DEFAULT_THRESHOLD * aml_db->bytes_per_cycle * (aml_db->clock_count / 10000); if (aml_db->cpu_type <= MESON_CPU_MAJOR_ID_GXTVBB) aml_db->ops = &gx_ddr_bw_ops; diff --git a/include/linux/amlogic/aml_ddr_bandwidth.h b/include/linux/amlogic/aml_ddr_bandwidth.h index bde095b91e8a..42346db0c6ec 100644 --- a/include/linux/amlogic/aml_ddr_bandwidth.h +++ b/include/linux/amlogic/aml_ddr_bandwidth.h @@ -134,6 +134,7 @@ struct ddr_bandwidth { unsigned short real_ports; char busy; char mode; + char bytes_per_cycle; int mali_port[2]; unsigned int threshold; unsigned int irq_num; diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index c658c74707f9..0d2244c824ac 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -154,6 +154,11 @@ static inline bool is_meson_txl_cpu(void) return get_cpu_type() == MESON_CPU_MAJOR_ID_TXL; } +static inline bool is_meson_txl_package_950(void) +{ + return is_meson_txl_cpu() && package_id_is(0x20); +} + static inline bool is_meson_txlx_cpu(void) { return get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX; From 5189ba87df796e69e9e7a672dfc02f2575d88000 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Wed, 23 Jan 2019 13:12:17 +0800 Subject: [PATCH 0259/1060] tvafe: get cvbs lock status error [1/1] PD#TV-1548 Problem: get cvbs lock status error. Solution: fix h_lock and v_lock status. Verify: verified by x301 Change-Id: Ia5e618c42280e7964399122b9b039a6f0d7da305 Signed-off-by: nengwen.chen --- drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 713ceffbc676..dc3977e7fd91 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -1128,9 +1128,10 @@ enum tvafe_cvbs_video_e tvafe_cvd2_get_lock_status( { enum tvafe_cvbs_video_e cvbs_lock_status = TVAFE_CVBS_VIDEO_HV_UNLOCKED; - if (!cvd2->hw.h_lock && !cvd2->hw.v_lock) + if (!cvd2->hw.h_lock && !cvd2->hw.v_lock) { cvbs_lock_status = TVAFE_CVBS_VIDEO_HV_UNLOCKED; - else if (cvd2->hw.h_lock && cvd2->hw.v_lock) { + lock_cnt = 0; + } else if (cvd2->hw.h_lock && cvd2->hw.v_lock) { cvbs_lock_status = TVAFE_CVBS_VIDEO_HV_LOCKED; lock_cnt++; } else if (cvd2->hw.h_lock) { From 969d6dc4cbf49666f1bf313d5de2ad7931420eee Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Wed, 23 Jan 2019 17:22:39 +0800 Subject: [PATCH 0260/1060] osd: fix display frame offset caused osd display abnormal [1/1] PD#OTT-1663 Problem: display frame offset caused osd display abnormal Solution: remove unnecessary blend dst_data adjust Verify: Locally on raven Change-Id: I38b97f6da750f5edea97416b4d7fc0172dea7466 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 2976cc5033ef..93979cf198e1 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -7363,17 +7363,6 @@ static void uniformization_fb(u32 index, blending->screen_ratio_w; blending->dst_data.h = (osd_hw.dst_data[index].h << OSD_CALC) / blending->screen_ratio_h; - if (osd_hw.dst_data[index].w < osd_hw.disp_info.position_w) - osd_log_err("base dispframe w(%d) must >= position_w(%d)\n", - osd_hw.dst_data[index].w, osd_hw.disp_info.position_w); - if ((blending->dst_data.w + blending->dst_data.x) > - osd_hw.disp_info.background_w) { - blending->dst_data.w = osd_hw.disp_info.background_w - - blending->dst_data.x; - osd_log_info("blending w(%d) must < base fb w(%d)\n", - blending->dst_data.w + blending->dst_data.x, - osd_hw.disp_info.background_w); - } osd_log_dbg2(MODULE_BLEND, "uniformization:osd%d:dst_data:%d,%d,%d,%d\n", index, From 7c61894ee1a712f17f5aed7cd91469f87eb26a2a Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Wed, 23 Jan 2019 19:39:09 +0800 Subject: [PATCH 0261/1060] watchpoint: add watch point driver for cpu [1/1] PD#SWPL-4351 Problem: Our cpu has 4 watch point on each cpu. It can be used for debug purpose. But currently there is no driver support it. Solution: Bring up driver for it. Verify: p212 Change-Id: Ifbcb7f9b77e10fcb03b3c1a5e18f06b1a56ec2f0 Signed-off-by: Tao Zeng --- MAINTAINERS | 2 + arch/arm/kernel/hw_breakpoint.c | 4 + arch/arm64/kernel/hw_breakpoint.c | 10 +- drivers/amlogic/memory_ext/Kconfig | 10 + drivers/amlogic/memory_ext/Makefile | 1 + drivers/amlogic/memory_ext/watch_point.c | 485 +++++++++++++++++++++++ include/linux/amlogic/watch_point.h | 55 +++ 7 files changed, 566 insertions(+), 1 deletion(-) create mode 100644 drivers/amlogic/memory_ext/watch_point.c create mode 100644 include/linux/amlogic/watch_point.h diff --git a/MAINTAINERS b/MAINTAINERS index d9268b572dc6..4399af787aa1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13528,6 +13528,8 @@ F: drivers/amlogic/memory_ext/* F: include/linux/amlogic/ramdump.h F: include/linux/amlogic/vmap_stack.h F: drivers/amlogic/memory_ext/vmap_stack.c +F: drivers/amlogic/memory_ext/watch_point.c +F: include/linux/amlogic/watch_point.h AMLOGIC driver for memory extend M: Tao Zeng diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 25538a935874..bc8f9b1b752c 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -102,7 +102,11 @@ static u8 max_watchpoint_len; WRITE_WB_REG_CASE(OP2, 14, VAL); \ WRITE_WB_REG_CASE(OP2, 15, VAL) +#ifdef CONFIG_AMLOGIC_MODIFY +u32 read_wb_reg(int n) +#else static u32 read_wb_reg(int n) +#endif { u32 val = 0; diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 0798abd4d692..97e9b4d5999b 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -114,7 +114,11 @@ int hw_breakpoint_slots(int type) WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ WRITE_WB_REG_CASE(OFF, 15, REG, VAL) +#ifdef CONFIG_AMLOGIC_MODIFY +u64 read_wb_reg(int reg, int n) +#else static u64 read_wb_reg(int reg, int n) +#endif { u64 val = 0; @@ -129,14 +133,18 @@ static u64 read_wb_reg(int reg, int n) return val; } +#ifndef CONFIG_AMLOGIC_MODIFY NOKPROBE_SYMBOL(read_wb_reg); +#endif static void write_wb_reg(int reg, int n, u64 val) { #ifdef CONFIG_AMLOGIC_VMAP /* avoid write DBGWVR since we use it for special purpose */ - if (reg >= AARCH64_DBG_REG_WVR && reg < AARCH64_DBG_REG_WCR) + if ((reg + n) >= (AARCH64_DBG_REG_WVR + 2) && + (reg + n) < AARCH64_DBG_REG_WCR) { return; + } #endif switch (reg + n) { GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); diff --git a/drivers/amlogic/memory_ext/Kconfig b/drivers/amlogic/memory_ext/Kconfig index e5a1f2d250c6..65fe232527e1 100644 --- a/drivers/amlogic/memory_ext/Kconfig +++ b/drivers/amlogic/memory_ext/Kconfig @@ -58,3 +58,13 @@ config AMLOGIC_SLUB_DEBUG help This option open trace debug for each slub objects. And will give slub objdect allocator information when detected bad objects + +config AMLOGIC_WATCHPOINT + tristate "Amlogic point driver" + depends on HAVE_HW_BREAKPOINT + depends on AMLOGIC_MEMORY_EXTEND + default y + help + This driver export a debug sysfs in order + to using watch point function on ARMv8. + say y to enable Amlogic watch point driver diff --git a/drivers/amlogic/memory_ext/Makefile b/drivers/amlogic/memory_ext/Makefile index 8d3c2666ac00..58406009fb2a 100644 --- a/drivers/amlogic/memory_ext/Makefile +++ b/drivers/amlogic/memory_ext/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_AMLOGIC_CMA) += aml_cma.o obj-$(CONFIG_AMLOGIC_SLUB_DEBUG) += aml_slub_debug.o obj-$(CONFIG_AMLOGIC_RAMDUMP) += ram_dump.o obj-$(CONFIG_AMLOGIC_VMAP) += vmap_stack.o +obj-$(CONFIG_AMLOGIC_WATCHPOINT) += watch_point.o diff --git a/drivers/amlogic/memory_ext/watch_point.c b/drivers/amlogic/memory_ext/watch_point.c new file mode 100644 index 000000000000..35b4a050b613 --- /dev/null +++ b/drivers/amlogic/memory_ext/watch_point.c @@ -0,0 +1,485 @@ +/* + * drivers/amlogic/memory_ext/watch_point.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct aml_watch_points { + struct perf_event * __percpu *wp_event[MAX_WATCH_POINTS]; + perf_overflow_handler_t handler[MAX_WATCH_POINTS]; + int num_watch_points; + struct work_struct replace_work; + spinlock_t lock; +}; + +struct aml_watch_points *awp; + +static void get_cpu_wb_reg(void *info) +{ + unsigned long *p, r; + + p = (unsigned long *)info; + r = *p; + +#ifdef CONFIG_ARM64 + if (r < AARCH64_DBG_REG_WCR) + *p = read_wb_reg(AARCH64_DBG_REG_WVR, r - AARCH64_DBG_REG_WVR); + else + *p = read_wb_reg(AARCH64_DBG_REG_WCR, r - AARCH64_DBG_REG_WCR); +#else + *p = read_wb_reg(r); +#endif +} + +#ifdef CONFIG_ARM +static struct perf_event **wp_flag(struct perf_event **event, int set) +{ + unsigned long tmp; + + tmp = (unsigned long)event; + + if (set) + tmp |= 0x01; + else + tmp &= ~0x01; + return (struct perf_event **)tmp; +} + +static void wp_del(void *data) +{ + struct perf_event *bp; + + bp = (struct perf_event *)data; + bp->pmu->del(bp, PERF_EF_UPDATE); + pr_info("del for wp:%lx, wp:%p\n", + (unsigned long)bp->attr.bp_addr, bp); +} + +static void wp_add(void *data) +{ + struct perf_event *bp; + + bp = (struct perf_event *)data; + bp->pmu->add(bp, PERF_EF_START); + pr_info("add for wp:%lx, wp:%p\n", + (unsigned long)bp->attr.bp_addr, bp); +} +#endif + +static int dump_watch_point_reg(char *buf) +{ + int i, cpu = 0; + unsigned long addr, wvr, wcr; + int len, type, size = 0; + struct perf_event *bp; + + size += sprintf(buf + size, + "idx, addr, type, len, event, handler\n"); + for (i = 0; i < awp->num_watch_points; i++) { + if (awp->wp_event[i]) { + bp = get_cpu_var(*awp->wp_event[i]); + addr = bp->attr.bp_addr; + len = bp->attr.bp_len; + type = bp->attr.bp_type; + put_cpu_var(*awp->wp_event[i]); + } else { + addr = 0; + len = 0; + type = 0; + } + size += sprintf(buf + size, "%2d, %16lx, %x, %x, %p, %pf\n", + i, addr, type, len, awp->wp_event[i], + awp->handler[i]); + } + for_each_online_cpu(cpu) { + size += sprintf(buf + size, "CPU:%d\n", cpu); + for (i = 0; i < awp->num_watch_points; i++) { + #ifdef CONFIG_ARM64 + wvr = AARCH64_DBG_REG_WVR + i; + #else + wvr = ARM_BASE_WVR + i; + #endif + smp_call_function_single(cpu, get_cpu_wb_reg, &wvr, 1); + + #ifdef CONFIG_ARM64 + wcr = AARCH64_DBG_REG_WCR + i; + #else + wcr = ARM_BASE_WCR + i; + #endif + smp_call_function_single(cpu, get_cpu_wb_reg, &wcr, 1); + size += sprintf(buf + size, " WVR:%16lx WCR:%16lx\n", + wvr, wcr); + } + } + return size; +} + +static void wp_replace_back(struct work_struct *data) +{ + int i, cpu; + struct perf_event *bp; + + for (i = 0; i < awp->num_watch_points; i++) { + if (!awp->wp_event[i]) + continue; + #ifdef CONFIG_ARM64 + get_online_cpus(); + for_each_online_cpu(cpu) { + bp = per_cpu(*awp->wp_event[i], cpu); + if (is_default_overflow_handler(bp)) { + bp->overflow_handler = awp->handler[i]; + pr_info("replace handler for wp:%lx\n", + (unsigned long)bp->attr.bp_addr); + } + } + put_online_cpus(); + #else + if (!(((unsigned long)awp->wp_event[i]) & 0x01)) + continue; + + awp->wp_event[i] = wp_flag(awp->wp_event[i], 0); + get_online_cpus(); + for_each_online_cpu(cpu) { + bp = per_cpu(*awp->wp_event[i], cpu); + smp_call_function_single(cpu, wp_add, bp, 1); + } + put_online_cpus(); + #endif + } +} + +static void aml_default_hbp_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) +{ +#ifdef CONFIG_ARM64 + pr_info("watch addr %llx triggerd, pc:%pf, lr:%pf\n", + bp->attr.bp_addr, (void *)regs->pc, + (void *)regs->compat_lr_fiq); + bp->overflow_handler = perf_event_output_forward; + show_regs(regs); + dump_stack(); +#else + struct perf_event * __percpu *event = NULL; + int i, cpu; + + pr_info("watch addr %llx triggerd, pc:%pf, lr:%pf\n", + bp->attr.bp_addr, (void *)regs->ARM_pc, + (void *)regs->ARM_lr); + + for (i = 0; i < awp->num_watch_points; i++) { + if (!awp->wp_event[i]) + continue; + for_each_online_cpu(cpu) { + if (bp == per_cpu(*awp->wp_event[i], cpu)) { + event = awp->wp_event[i]; + break; + } + } + if (event) { + for_each_online_cpu(cpu) { + bp = per_cpu(*event, cpu); + smp_call_function_single(cpu, wp_del, bp, 1); + } + break; + } + } + if (event) + awp->wp_event[i] = wp_flag(awp->wp_event[i], 1); + show_regs(regs); +#endif + schedule_work_on(smp_processor_id(), &awp->replace_work); +} + +/* register a watch pointer */ +int aml_watch_point_register(unsigned long addr, + unsigned int len, + unsigned int type, + perf_overflow_handler_t handle) +{ + int i; + struct perf_event_attr attr; + struct perf_event * __percpu *event; + + if (!awp) + return -ENOMEM; + + /* parameter check */ + if ((len > HW_BREAKPOINT_LEN_8) || (len < HW_BREAKPOINT_LEN_1)) { + pr_err("bad input len:%d\n", len); + return -EINVAL; + } + if (type & ~(HW_BREAKPOINT_W | HW_BREAKPOINT_R)) { + pr_err("bad input type:%d\n", type); + return -EINVAL; + } + + /* check if all watch points are used */ + spin_lock(&awp->lock); + for (i = 0; i < awp->num_watch_points; i++) { + if (!awp->wp_event[i]) { + awp->wp_event[i]++; + break; + } + } + if (i == awp->num_watch_points) { + spin_unlock(&awp->lock); + pr_err("%s, watch point is all used\n", __func__); + return -ENODEV; + } + spin_unlock(&awp->lock); + + hw_breakpoint_init(&attr); + attr.bp_addr = addr; + attr.bp_len = len; + attr.bp_type = type; + if (!handle) + handle = aml_default_hbp_handler; + + event = register_wide_hw_breakpoint(&attr, handle, NULL); + spin_lock(&awp->lock); + if (IS_ERR_OR_NULL(event)) { + awp->wp_event[i] = NULL; + awp->handler[i] = NULL; + } else { + awp->wp_event[i] = event; + awp->handler[i] = handle; + } + spin_unlock(&awp->lock); + + pr_info("watch point[%d], addr:%lx, len:%d, type:%x, event:%p\n", + i, addr, len, type, awp->wp_event[i]); + return awp->wp_event[i] ? 0 : -EINVAL; +} +EXPORT_SYMBOL(aml_watch_point_register); + +/* remove watch point according given address */ +void aml_watch_point_remove(unsigned long addr) +{ + int i; + struct perf_event *bp; + struct perf_event * __percpu *event = NULL; + + if (!awp) + return; + + spin_lock(&awp->lock); + for (i = 0; i < awp->num_watch_points; i++) { + if (awp->wp_event[i]) { + bp = get_cpu_var(*awp->wp_event[i]); + if (bp->attr.bp_addr == addr) { + event = awp->wp_event[i]; + awp->wp_event[i] = NULL; + awp->handler[i] = NULL; + put_cpu_var(*awp->wp_event[i]); + break; + } + put_cpu_var(*awp->wp_event[i]); + } + } + spin_unlock(&awp->lock); + if (event) + unregister_wide_hw_breakpoint(event); +} +EXPORT_SYMBOL(aml_watch_point_remove); + +/* + * force clear a watch point + */ +static void aml_watch_point_clear(int idx) +{ + struct perf_event * __percpu *event = NULL; + + if (idx >= awp->num_watch_points) + return; + + spin_lock(&awp->lock); + if (awp->wp_event[idx]) { + event = awp->wp_event[idx]; + awp->wp_event[idx] = NULL; + awp->handler[idx] = NULL; + } + spin_unlock(&awp->lock); + if (event) + unregister_wide_hw_breakpoint(event); +} + +static ssize_t num_watch_points_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", awp->num_watch_points); +} + +static ssize_t watch_addr_store(struct class *cla, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned long addr; + u32 len = HW_BREAKPOINT_LEN_8; + u32 type = HW_BREAKPOINT_W; + int ret; + + ret = sscanf(buf, "%lx %x %x", &addr, &len, &type); + if (ret < 1) + return -EINVAL; + + ret = aml_watch_point_register(addr, len, type, NULL); + + return count; +} + +static ssize_t clear_store(struct class *cla, + struct class_attribute *attr, const char *buf, size_t count) +{ + int i; + int idx = -1; + + if (kstrtoint(buf, 10, &idx)) + return count; + + if (idx >= awp->num_watch_points) { + pr_err("input index %d out of range:[0 - %d]\n", + idx, awp->num_watch_points); + return -EINVAL; + } + + /* negative value means clear all watch point */ + if (idx < 0) { + for (i = 0; i < awp->num_watch_points; i++) + aml_watch_point_clear(i); + } else { + aml_watch_point_clear(idx); + } + + return count; +} + +static ssize_t dump_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return dump_watch_point_reg(buf); +} + +static struct class_attribute watch_point_attr[] = { + __ATTR(watch_addr, 0664, dump_show, watch_addr_store), + __ATTR_RO(num_watch_points), + __ATTR_WO(clear), + __ATTR_NULL +}; + +static struct class watch_point_class = { + .name = "watch_point", + .class_attrs = watch_point_attr, +}; + +/* + * aml_watch_point_probe only executes before the init process starts + * to run, so add __ref to indicate it is okay to call __init function + * hook_debug_fault_code + */ +static int __init aml_watch_point_probe(struct platform_device *pdev) +{ + int r; + + r = hw_breakpoint_slots(TYPE_DATA); + pr_info("%s, in, wp:%d\n", __func__, r); + if (!r) + return -ENODEV; + + awp = devm_kzalloc(&pdev->dev, sizeof(*awp), GFP_KERNEL); + if (awp == NULL) + return -ENOMEM; + + awp->num_watch_points = r; + r = class_register(&watch_point_class); + if (r) { + pr_err("regist watch_point_class failed\n"); + return -EINVAL; + } + INIT_WORK(&awp->replace_work, wp_replace_back); + + return 0; +} + +static int aml_watch_point_drv_remove(struct platform_device *pdev) +{ + class_unregister(&watch_point_class); + return 0; +} + +static struct platform_driver aml_watch_point_driver = { + .driver = { + .name = "aml_watch_point", + .owner = THIS_MODULE, + }, + .probe = aml_watch_point_probe, + .remove = aml_watch_point_drv_remove, +}; + +static int __init aml_watch_pint_init(void) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc("aml_watch_point", 0); + if (!pdev) { + pr_err("alloc pdev aml_watch_point failed\n"); + return -EINVAL; + } + ret = platform_device_add(pdev); + if (ret) { + pr_err("regist pdev failed, ret:%d\n", ret); + platform_device_del(pdev); + return ret; + } + ret = platform_driver_probe(&aml_watch_point_driver, + aml_watch_point_probe); + if (ret) + platform_device_del(pdev); + return ret; +} + +static void __exit aml_watch_point_uninit(void) +{ + platform_driver_unregister(&aml_watch_point_driver); +} + +arch_initcall(aml_watch_pint_init); +module_exit(aml_watch_point_uninit); +MODULE_DESCRIPTION("amlogic watch point driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/amlogic/watch_point.h b/include/linux/amlogic/watch_point.h new file mode 100644 index 000000000000..f28fa37eb8b4 --- /dev/null +++ b/include/linux/amlogic/watch_point.h @@ -0,0 +1,55 @@ +/* + * include/linux/amlogic/watch_point.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __AML_WATCH_POINT_H__ +#define __AML_WATCH_POINT_H__ + +#include +#include +#include + +#define MAX_WATCH_POINTS 16 + +#ifdef CONFIG_ARM64 +extern u64 read_wb_reg(int reg, int n); +#else +extern u32 read_wb_reg(int n); +#endif + +#ifdef CONFIG_HAVE_HW_BREAKPOINT +extern int aml_watch_point_register(unsigned long addr, + unsigned int len, + unsigned int type, + perf_overflow_handler_t handle); + +extern void aml_watch_point_remove(unsigned long addr); +#else +static inline int aml_watch_point_register(unsigned long addr, + unsigned int len, + unsigned int type, + perf_overflow_handler_t handle) +{ + return -1; +} + +static inline void aml_watch_point_remove(unsigned long addr) +{ + +} +#endif + +#endif From 2c3a29b3f8fb9e6ef3b7b944b2e9160582a69fd7 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 25 Jan 2019 16:40:51 +0800 Subject: [PATCH 0262/1060] ge2d: merge ge2d from amlogic-3.14-dev [1/3] PD#SWPL-4355 Problem: ge2d: fix ge2d bitblt error Solution: merge patch 'fix ge2d bitblt error' from amlogic-3.14-dev(PD#154877) Verify: verified on u200 Change-Id: I4a813810837814931c3cb68f9a0f8a0929b06540 Signed-off-by: pengcheng chen Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_hw.c | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 3a886ff35a99..088af433b6dd 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -901,20 +901,20 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) if (!gaul_filter_used) { rate_w = (widtho * 10) / widthi; rate_h = (heighto * 10) / heighti; - if (rate_w == 10) { + if (rate_h == 10) { /* not scaler case */ - cfg->sc_vsc_en = 1; - cfg->vsc_rpt_l0_num = 1; + cfg->sc_vsc_en = 0; + cfg->vsc_rpt_l0_num = 0; cfg->vsc_ini_phase = 0; ge2d_reg_set_bits(GE2D_SC_MISC_CTRL, ((0 << 1) | (0 << 0)), 8, 2); - } else if (rate_w < 10) { + } else if (rate_h < 10) { /* scaler down case */ cfg->sc_vsc_en = 1; cfg->vsc_rpt_l0_num = 1; - if (rate_w != 0) + if (rate_h != 0) cfg->vsc_ini_phase = - 0x5000000/rate_w - 0x800000; + 0x5000000/rate_h - 0x800000; else cfg->vsc_ini_phase = 0x5000000; } else { @@ -922,23 +922,23 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) cfg->sc_vsc_en = 1; cfg->vsc_rpt_l0_num = 2; cfg->vsc_ini_phase = - 0x800000 + 0x5000000/rate_w; + 0x800000 + 0x5000000/rate_h; } - if (rate_h == 10) { + if (rate_w == 10) { /* not scaler case */ - cfg->sc_hsc_en = 1; - cfg->hsc_rpt_p0_num = 1; + cfg->sc_hsc_en = 0; + cfg->hsc_rpt_p0_num = 0; cfg->hsc_ini_phase = 0; ge2d_reg_set_bits(GE2D_SC_MISC_CTRL, ((0 << 1) | (0 << 0)), 8, 2); - } else if (rate_h < 10) { + } else if (rate_w < 10) { /* scaler down case */ cfg->sc_hsc_en = 1; cfg->hsc_rpt_p0_num = 1; - if (rate_h != 0) + if (rate_w != 0) cfg->hsc_ini_phase = - 0x5000000/rate_h - 0x800000; + 0x5000000/rate_w - 0x800000; else cfg->hsc_ini_phase = 0x5000000; } else { @@ -946,7 +946,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) cfg->sc_hsc_en = 1; cfg->hsc_rpt_p0_num = 2; cfg->hsc_ini_phase = - 0x800000 + 0x5000000/rate_h; + 0x800000 + 0x5000000/rate_w; } /* expand src1/src2 color with 1 */ ge2d_reg_set_bits(GE2D_GEN_CTRL2, 1, 27, 1); From 051cfb75e80c466b1d7adc127d4cb5b3eff8b16c Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 25 Jan 2019 16:45:37 +0800 Subject: [PATCH 0263/1060] ge2d: merge ge2d from amlogic-3.14-dev [2/3] PD#SWPL-4355 Problem: ge2d: play video display mess when used ionvideo Solution: merge patch 'play video display mess when used ionvideo' from amlogic-3.14-dev(PD#155143) Verify: verified on u200 Change-Id: Iaf34fe1d1c7e7637015dadaaf43e201cf28089b7 Signed-off-by: pengcheng chen Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_hw.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 088af433b6dd..079779d359a8 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -903,8 +903,6 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) rate_h = (heighto * 10) / heighti; if (rate_h == 10) { /* not scaler case */ - cfg->sc_vsc_en = 0; - cfg->vsc_rpt_l0_num = 0; cfg->vsc_ini_phase = 0; ge2d_reg_set_bits(GE2D_SC_MISC_CTRL, ((0 << 1) | (0 << 0)), 8, 2); @@ -927,8 +925,6 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) if (rate_w == 10) { /* not scaler case */ - cfg->sc_hsc_en = 0; - cfg->hsc_rpt_p0_num = 0; cfg->hsc_ini_phase = 0; ge2d_reg_set_bits(GE2D_SC_MISC_CTRL, ((0 << 1) | (0 << 0)), 8, 2); From 6087e4d916503f1c5329cd08e7c54596a01ef2bb Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 25 Jan 2019 17:16:05 +0800 Subject: [PATCH 0264/1060] ge2d: merge ge2d from amlogic-3.14-dev [3/3] PD#SWPL-4355 Problem: ge2d: Adjust scaler para when input is nv21 and output is rgb Solution: merge patch 'Adjust scaler para when input is nv21 and output is rgb' from amlogic-3.14-dev(PD#15652) Verify: verified on u200 Change-Id: I199b07d683a01175ec17d4d34be6febd3083920c Signed-off-by: pengcheng chen Signed-off-by: Jian Cao --- drivers/amlogic/media/common/ge2d/ge2d_hw.c | 28 ++++++++++++++++++++- drivers/amlogic/media/common/ge2d/ge2d_wq.c | 5 ++++ include/linux/amlogic/media/ge2d/ge2d.h | 3 +++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 079779d359a8..a9eaba3577a9 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -798,6 +798,32 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) x_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 11, 1); y_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 10, 1); + /* src:yuv , dst: rgb */ + if ((cfg->src1_fmt & GE2D_FORMAT_YUV) && + ((cfg->dst_fmt & GE2D_FORMAT_YUV) == 0)) { + if (x_yc_ratio) { + if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) { + x_extra_bit_start = 3; + x_extra_bit_end = 2; + x_chr_phase = 0x4c; + } else { + x_extra_bit_start = 2; + x_extra_bit_end = 3; + x_chr_phase = 0xc4; + } + } + if (y_yc_ratio) { + if ((cfg->src1_y_rev + cfg->dst_y_rev) == 1) { + y_extra_bit_start = 3; + y_extra_bit_end = 2; + y_chr_phase = 0x4c; + } else { + y_extra_bit_start = 2; + y_extra_bit_end = 3; + y_chr_phase = 0xc4; + } + } + } else { if (x_yc_ratio) { if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) { x_extra_bit_start = 3; @@ -820,8 +846,8 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) y_extra_bit_end = 3; y_chr_phase = 0x4c; } + } } - ge2d_reg_write(GE2D_SRC1_X_START_END, (x_extra_bit_start << 30) | /* x start extra */ ((cfg->src1_x_start & 0x3fff) << 16) | diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index 3c9bf8632e86..ae4816d77a6a 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -1982,6 +1982,11 @@ int ge2d_context_config_ex_ion(struct ge2d_context_s *context, ge2d_cmd_cfg->hsc_rpt_p0_num = ge2d_config->hf_rpt_num; ge2d_cmd_cfg->src1_cmult_asel = ge2d_config->src1_cmult_asel; ge2d_cmd_cfg->src2_cmult_asel = ge2d_config->src2_cmult_asel; + + ge2d_cmd_cfg->src1_fmt = ge2d_config->src_para.format; + ge2d_cmd_cfg->src2_fmt = ge2d_config->src2_para.format; + ge2d_cmd_cfg->dst_fmt = ge2d_config->dst_para.format; + context->config.update_flag = UPDATE_ALL; /* context->config.src1_data.ddr_burst_size_y = 3; */ /* context->config.src1_data.ddr_burst_size_cb = 3; */ diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index 279c447f4208..63dae99453fa 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -548,6 +548,7 @@ struct ge2d_cmd_s { /* unsigned char src1_x_chr_phase; */ /* unsigned char src1_y_chr_phase; */ unsigned char src1_fill_color_en; + unsigned int src1_fmt; int src2_x_start; int src2_y_start; @@ -556,6 +557,7 @@ struct ge2d_cmd_s { unsigned char src2_x_rev; unsigned char src2_y_rev; unsigned char src2_fill_color_en; + unsigned int src2_fmt; int dst_x_start; int dst_y_start; @@ -564,6 +566,7 @@ struct ge2d_cmd_s { unsigned char dst_xy_swap; unsigned char dst_x_rev; unsigned char dst_y_rev; + unsigned int dst_fmt; int sc_prehsc_en; int sc_prevsc_en; From 949fffe24cebaa3e3f6ac34fcf31d929cad869b0 Mon Sep 17 00:00:00 2001 From: Qianggui Song Date: Tue, 22 Jan 2019 14:40:06 +0800 Subject: [PATCH 0265/1060] pinctrl: rename m8b pinmux function gpio to gpio_periphs [1/2] PD#SWPL-4501 Problem: All platforms but m8b use "gpio_periphs" as gpio pinctrl function, that breaks consistency. Solution: rename m8b pinctrl function "gpio" to "gpio_periphs" to make it consistent with code and other platform. ref: https://patchwork.kernel.org/patch/10720219/ Verify: m200 Change-Id: I940d1e30882cc8b042c02022ed3435a659aa3921 Signed-off-by: Qianggui Song --- arch/arm/boot/dts/amlogic/meson8b_m200.dts | 8 ++++---- drivers/amlogic/pinctrl/pinctrl-meson8b.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/meson8b_m200.dts b/arch/arm/boot/dts/amlogic/meson8b_m200.dts index e74829a1c5ad..f701561d0005 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m200.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m200.dts @@ -631,7 +631,7 @@ "GPIOX_3", "GPIOX_8", "GPIOX_9"; - function = "gpio"; + function = "gpio_periphs"; }; }; @@ -653,7 +653,7 @@ "GPIOX_3", "GPIOX_8", "GPIOX_9"; - function = "gpio"; + function = "gpio_periphs"; }; }; @@ -676,7 +676,7 @@ "BOOT_7", "BOOT_8", "BOOT_10"; - function = "gpio"; + function = "gpio_periphs"; }; }; @@ -702,7 +702,7 @@ "BOOT_7", "BOOT_8", "BOOT_10"; - function = "gpio"; + function = "gpio_periphs"; }; }; }; diff --git a/drivers/amlogic/pinctrl/pinctrl-meson8b.c b/drivers/amlogic/pinctrl/pinctrl-meson8b.c index 96f1a2021cc4..b2fe9a009407 100644 --- a/drivers/amlogic/pinctrl/pinctrl-meson8b.c +++ b/drivers/amlogic/pinctrl/pinctrl-meson8b.c @@ -629,7 +629,7 @@ static struct meson_pmx_group meson8b_aobus_groups[] = { GROUP(i2s_lr_clk_in, 0, 14), }; -static const char * const gpio_groups[] = { +static const char * const gpio_periphs_groups[] = { "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4", "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9", "GPIOX_10", "GPIOX_11", "GPIOX_16", "GPIOX_17", "GPIOX_18", @@ -861,7 +861,7 @@ static const char * const tsin_b_groups[] = { }; static struct meson_pmx_func meson8b_cbus_functions[] = { - FUNCTION(gpio), + FUNCTION(gpio_periphs), FUNCTION(sd_a), FUNCTION(sdxc_a), FUNCTION(pcm_a), From 777c539aa87012afd33efa1b90162e289ea3982b Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Fri, 25 Jan 2019 09:51:11 +0800 Subject: [PATCH 0266/1060] osd: rdma write miss caused afbc mosaic [1/1] PD#SWPL-4502 Problem: afbc mosaic when bandwidth is high, root cause is rdma write regs missed. Solution: 1. add vsync line detected, if rdma write nearly vsync, wait vsync needed 2. add rdma write detected, if rdma write missed wait vsync needed 3. add tl1/g12b afbc backup Verify: Locally on tl1 Change-Id: If4fd303c3808525fa44e1118742a3e26830323f5 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 91 +++++++++++++++--------------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 93979cf198e1..b9b3cc0da704 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -108,7 +108,7 @@ static int osd_afbc_dec_enable; static int ext_canvas_id[HW_OSD_COUNT]; static int osd_extra_idx[HW_OSD_COUNT][2]; static bool suspend_flag; - +static u32 rdma_dt_cnt; static void osd_clone_pan(u32 index, u32 yoffset, int debug_flag); static void osd_set_dummy_data(u32 index, u32 alpha); @@ -454,12 +454,15 @@ module_param(enable_vd_zorder, uint, 0664); static int vsync_enter_line_max; static int vsync_exit_line_max; static int vsync_line_threshold = 950; +static int line_threshold = 90; MODULE_PARM_DESC(vsync_enter_line_max, "\n vsync_enter_line_max\n"); module_param(vsync_enter_line_max, uint, 0664); MODULE_PARM_DESC(vsync_exit_line_max, "\n vsync_exit_line_max\n"); module_param(vsync_exit_line_max, uint, 0664); MODULE_PARM_DESC(vsync_line_threshold, "\n vsync_line_threshold\n"); module_param(vsync_line_threshold, uint, 0664); +MODULE_PARM_DESC(line_threshold, "\n line_threshold\n"); +module_param(line_threshold, uint, 0664); static unsigned int osd_filter_coefs_bicubic_sharp[] = { 0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300, @@ -692,26 +695,37 @@ static void f2v_get_vertical_phase( static bool osd_hdr_on; #endif -static int cnt; #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE static int get_encp_line(void) { int enc_line = 0; + int active_line_begin = 0; + unsigned int reg = 0; switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) { case 0: - enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCL_INFO_READ); + active_line_begin = + osd_reg_read(ENCL_VIDEO_VAVON_BLINE); break; case 1: - enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCI_INFO_READ); + active_line_begin = + osd_reg_read(ENCI_VFIFO2VD_LINE_TOP_START); break; case 2: - enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCP_INFO_READ); + active_line_begin = + osd_reg_read(ENCP_VIDEO_VAVON_BLINE); break; case 3: - enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCT_INFO_READ); + active_line_begin = + osd_reg_read(ENCT_VIDEO_VAVON_BLINE); break; } + enc_line = (reg >> 16) & 0x1fff; + enc_line -= active_line_begin; return enc_line; } #endif @@ -720,20 +734,7 @@ static int get_enter_encp_line(void) { int enc_line = 0; - switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) { - case 0: - enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff; - break; - case 1: - enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff; - break; - case 2: - enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff; - break; - case 3: - enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff; - break; - } + enc_line = get_encp_line(); if (enc_line > vsync_enter_line_max) vsync_enter_line_max = enc_line; return enc_line; @@ -743,20 +744,7 @@ static int get_exit_encp_line(void) { int enc_line = 0; - switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) { - case 0: - enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff; - break; - case 1: - enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff; - break; - case 2: - enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff; - break; - case 3: - enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff; - break; - } + enc_line = get_encp_line(); if (enc_line > vsync_exit_line_max) vsync_exit_line_max = enc_line; return enc_line; @@ -1118,11 +1106,10 @@ int osd_sync_request_render(u32 index, u32 yres, { int line; - cnt++; line = get_encp_line(); osd_log_dbg2(MODULE_RENDER, - "enter osd_sync_request_render:cnt=%d,encp line=%d\n", - cnt, line); + "enter osd_sync_request_render:encp line=%d\n", + line); if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V1) osd_hw.hwc_enable = 0; else if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V2) @@ -1144,8 +1131,8 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) line = get_encp_line(); osd_log_dbg2(MODULE_RENDER, - "enter osd_sync_do_hwc:cnt=%d,encp line=%d\n", - cnt, line); + "enter osd_sync_do_hwc:encp line=%d\n", + line); fence_map = kzalloc( sizeof(struct osd_layers_fence_map_s), GFP_KERNEL); if (!fence_map) @@ -7402,6 +7389,7 @@ static void adjust_dst_position(void) static int osd_setting_order(void) { +#define RDMA_DETECT_REG VIU_OSD2_TCOLOR_AG2 int i; struct layer_blend_reg_s *blend_reg; struct hw_osd_blending_s *blending; @@ -7410,6 +7398,7 @@ static int osd_setting_order(void) int line1; int line2; int vinfo_height; + u32 val; blending = &osd_blending; blend_reg = &(blending->blend_reg); @@ -7445,10 +7434,11 @@ static int osd_setting_order(void) line1 = get_enter_encp_line(); vinfo_height = osd_hw.field_out_en ? (osd_hw.vinfo_height * 2) : osd_hw.vinfo_height; - if (line1 >= vinfo_height) { + /* if nearly vsync signal, wait vsync here */ + if (line1 >= vinfo_height * line_threshold / 100) { osd_log_dbg(MODULE_RENDER, - "enter osd_setting_order:cnt=%d,encp line=%d\n", - cnt, line1); + "enter osd_setting_order:encp line=%d\n", + line1); osd_wait_vsync_hw(); line1 = get_enter_encp_line(); } @@ -7519,14 +7509,21 @@ static int osd_setting_order(void) set_blend_reg(blend_reg); save_blend_reg(blend_reg); + /* append RDMA_DETECT_REG at last and detect if rdma missed some regs */ + rdma_dt_cnt++; + VSYNCOSD_WR_MPEG_REG(RDMA_DETECT_REG, rdma_dt_cnt); spin_unlock_irqrestore(&osd_lock, lock_flags); line2 = get_exit_encp_line(); osd_log_dbg2(MODULE_RENDER, - "enter osd_setting_order:cnt=%d,encp line=%d\n", - cnt, line2); - if (line2 < line1) - osd_log_info("osd line %d,%d\n", line1, line2); + "enter osd_setting_order:encp line=%d\n", + line2); osd_wait_vsync_hw(); + val = osd_reg_read(RDMA_DETECT_REG); + /* if missed, need wait vsync */ + if (/*(line2 < line1) || */(val != rdma_dt_cnt)) { + osd_wait_vsync_hw(); + osd_log_dbg(MODULE_RENDER, "osd line %d,%d\n", line1, line2); + } return 0; } @@ -8512,7 +8509,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.afbc_regs_backup = 1; } else { osd_hw.afbc_force_reset = 1; - osd_hw.afbc_regs_backup = 0; + osd_hw.afbc_regs_backup = 1; data32 = osd_reg_read(MALI_AFBCD_TOP_CTRL); osd_reg_write(MALI_AFBCD_TOP_CTRL, data32 | 0x800000); From b1687d5957ef17103c2ff1f676b5f95c55c1e5fa Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Fri, 1 Feb 2019 09:58:04 +0800 Subject: [PATCH 0267/1060] osd: fix buidroot compile error issue [1/1] PD#SWPL-4502 Problem: buidlroot compile error Solution: fix buidroot compile error issue Verify: buildroot make linux-build Change-Id: I0277c2b3f439946ab680f4c34f30c16e31ea6034 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index b9b3cc0da704..fb85cff64e78 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -695,7 +695,6 @@ static void f2v_get_vertical_phase( static bool osd_hdr_on; #endif -#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE static int get_encp_line(void) { int enc_line = 0; @@ -728,7 +727,6 @@ static int get_encp_line(void) enc_line -= active_line_begin; return enc_line; } -#endif static int get_enter_encp_line(void) { From b31b030bf67d9e418c3b9e53177fd7d1459921a1 Mon Sep 17 00:00:00 2001 From: Kaifu Hu Date: Mon, 28 Jan 2019 16:01:19 +0800 Subject: [PATCH 0268/1060] hdmitx: add 3d framepack mode support [1/1] PD#SWPL-4233 Problem: 3D framepacking mode display black screen Solution: Add vinfo 3d flag and hdmitx update when work 3d mode Verify: U212 Change-Id: Ia2b7b25c9ed401dbec2c487ea2a5c6cc1e0d8b8d Signed-off-by: Kaifu Hu --- .../vout/hdmitx/hdmi_common/hdmi_parameters.c | 18 ++++++++++++++++++ .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 14 ++++++++++++++ .../vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c | 4 ++-- .../amlogic/media/vout/vout_serve/vout_serve.c | 7 +++++-- include/linux/amlogic/media/vout/vinfo.h | 8 ++++++++ 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c index 43f1e2d79dd9..0340e8c30f57 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -2753,6 +2753,24 @@ struct vinfo_s *hdmi_get_valid_vinfo(char *mode) /* the string of mode contains char NF */ memset(mode_, 0, sizeof(mode_)); strncpy(mode_, mode, sizeof(mode_)); + + /* skip "f", 1080fp60hz -> 1080p60hz for 3d */ + mode_[31] = '\0'; + if (strstr(mode_, "fp")) { + int i = 0; + + for (; mode_[i]; i++) { + if ((mode_[i] == 'f') && + (mode_[i + 1] == 'p')) { + do { + mode_[i] = mode_[i + 1]; + i++; + } while (mode_[i]); + break; + } + } + } + for (i = 0; i < sizeof(mode_); i++) if (mode_[i] == 10) mode_[i] = 0; diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index cdaddc2f1e52..7bf5d89bf5ac 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -3490,6 +3490,16 @@ static enum vmode_e hdmitx_validate_vmode(char *mode) if (info) { hdmitx_vinfo = info; + hdmitx_vinfo->info_3d = NON_3D; + if (hdmitx_device.flag_3dfp) + hdmitx_vinfo->info_3d = FP_3D; + + if (hdmitx_device.flag_3dtb) + hdmitx_vinfo->info_3d = TB_3D; + + if (hdmitx_device.flag_3dss) + hdmitx_vinfo->info_3d = SS_3D; + hdmitx_vinfo->vout_device = &hdmitx_vdev; return VMODE_HDMI; } @@ -4265,6 +4275,10 @@ static int amhdmitx_device_init(struct hdmitx_dev *hdmi_dev) */ hdmitx_device.hpdmode = 1; + hdmitx_device.flag_3dfp = 0; + hdmitx_device.flag_3dss = 0; + hdmitx_device.flag_3dtb = 0; + if ((init_flag&INIT_FLAG_POWERDOWN) && (hdmitx_device.hpdmode == 2)) hdmitx_device.mux_hpd_if_pin_high_flag = 0; else diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c index dd324960c65d..21f4e9cfd45a 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c @@ -1245,7 +1245,7 @@ static const struct reg_s tvregs_3dfp_1080p60[] = { {P_ENCP_VIDEO_MODE, 0x4040,}, {P_ENCP_VIDEO_MODE_ADV, 0x18,}, - {P_ENCP_VIDEO_MAX_PXCNT, 0x897,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0xABD,}, {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, {P_ENCP_VIDEO_HAVON_END, 0x83F,}, @@ -1325,7 +1325,7 @@ static const struct reg_s tvregs_3dfp_1080p50[] = { {P_ENCP_VIDEO_MODE, 0x4040,}, {P_ENCP_VIDEO_MODE_ADV, 0x18,}, - {P_ENCP_VIDEO_MAX_PXCNT, 0xA4F,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0xABD,}, {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, {P_ENCP_VIDEO_HAVON_END, 0x83F,}, diff --git a/drivers/amlogic/media/vout/vout_serve/vout_serve.c b/drivers/amlogic/media/vout/vout_serve/vout_serve.c index dc897893337e..2978d5edb361 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_serve.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_serve.c @@ -505,14 +505,16 @@ static ssize_t vout_vinfo_show(struct class *class, " fr_adj_type: %d\n" " video_clk: %d\n" " viu_color_fmt: %d\n" - " viu_mux: %d\n\n", + " viu_mux: %d\n" + " 3d_info: %d\n\n", info->name, info->mode, info->width, info->height, info->field_height, info->aspect_ratio_num, info->aspect_ratio_den, info->sync_duration_num, info->sync_duration_den, info->screen_real_width, info->screen_real_height, info->htotal, info->vtotal, info->fr_adj_type, - info->video_clk, info->viu_color_fmt, info->viu_mux); + info->video_clk, info->viu_color_fmt, info->viu_mux, + info->info_3d); len += sprintf(buf+len, "master_display_info:\n" " present_flag %d\n" " features 0x%x\n" @@ -563,6 +565,7 @@ static ssize_t vout_vinfo_show(struct class *class, info->hdr_info.hdr10plus_info.ieeeoui); len += sprintf(buf+len, " application_version: %x\n", info->hdr_info.hdr10plus_info.application_version); + return len; } diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h index 8a5720f05b3b..96cbf12aea5f 100644 --- a/include/linux/amlogic/media/vout/vinfo.h +++ b/include/linux/amlogic/media/vout/vinfo.h @@ -53,6 +53,13 @@ enum vout_fr_adj_type_e { VOUT_FR_ADJ_MAX, }; +enum vinfo_3d_e { + NON_3D = 0, + SS_3D, + FP_3D, + TB_3D, +}; + /*emp : extended metadata type*/ #define VENDOR_SPECIFIC_EM_DATA 0x0 #define COMPRESS_VIDEO_TRAMSPORT 0x1 @@ -258,6 +265,7 @@ struct vinfo_s { u32 video_clk; u32 htotal; u32 vtotal; + enum vinfo_3d_e info_3d; enum vout_fr_adj_type_e fr_adj_type; enum color_fmt_e viu_color_fmt; enum viu_mux_e viu_mux; From de66f5d79907dc1d92d49e66576a274c821c590b Mon Sep 17 00:00:00 2001 From: "jinrong.liao" Date: Tue, 29 Jan 2019 15:23:14 +0800 Subject: [PATCH 0269/1060] audio: enable spdif driver [1/1] PD#SWPL-4223 Problem: Add audio source switch feature for GVA Solution: enable spdif driver in dts Verify: verify by S420 Change-Id: Ia71b27ba95124b84415ec4f532fd344a24633911 Signed-off-by: jinrong.liao --- .../boot/dts/amlogic/axg_s420_v03gva.dts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts index 1b2300f0f4ef..6f3198ecf3f0 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts @@ -441,16 +441,16 @@ }; }; - /*aml-audio-card,dai-link@4 { - * mclk-fs = <128>; - * cpu { - * sound-dai = <&aml_spdif>; - * }; - * codec { - * sound-dai = <&dummy_codec>; - * }; - *}; - */ + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; bt-dev{ From 5df25f96ab0e8b855bd001ab07dced451e4b8065 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Mon, 18 Feb 2019 11:08:23 +0800 Subject: [PATCH 0270/1060] audio: auge: fix hw resample crash when pcm disabled [1/1] PD#SWPL-4387 Problem: system would reboot when carshed by hw resample Solution: actrl of toddr is modified to null pointer, so it leads to crash. fix to pass toddr pointer to function, not fetched by resample module. Verify: x301 Change-Id: I91c30260ee825d843e8ed17304031382b42ac119 Signed-off-by: Xing Wang --- sound/soc/amlogic/auge/ddr_mngr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 4d70dec390cd..ee76da9a38d0 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -504,11 +504,10 @@ void aml_toddr_set_resample_ab(struct toddr *to, int asrc_src_sel, bool enable) } static void aml_resample_enable( + struct toddr *to, struct toddr_attach *p_attach_resample, bool enable) { - struct toddr *to = fetch_toddr_by_src(p_attach_resample->attach_module); - if (!to) return; @@ -587,7 +586,7 @@ static void aml_resample_enable( void aml_set_resample(int id, bool enable, int resample_module) { struct toddr_attach *p_attach_resample; - + struct toddr *to; bool update_running = false; if (id == 0) @@ -599,11 +598,12 @@ void aml_set_resample(int id, bool enable, int resample_module) p_attach_resample->id = id; p_attach_resample->attach_module = resample_module; + to = fetch_toddr_by_src( + p_attach_resample->attach_module); + if (enable) { if ((p_attach_resample->status == DISABLED) || (p_attach_resample->status == READY)) { - struct toddr *to = fetch_toddr_by_src( - p_attach_resample->attach_module); if (!to) { p_attach_resample->status = READY; @@ -620,8 +620,8 @@ void aml_set_resample(int id, bool enable, int resample_module) p_attach_resample->status = DISABLED; } - if (update_running) - aml_resample_enable(p_attach_resample, enable); + if (update_running && to) + aml_resample_enable(to, p_attach_resample, enable); } /* @@ -649,7 +649,7 @@ start_check: else p_attach_resample->status = DISABLED; - aml_resample_enable(p_attach_resample, enable); + aml_resample_enable(to, p_attach_resample, enable); } if ((!resample_b_check) From fa6fdb5ee2bdc106392a15d24b6c31a06f762125 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Sat, 2 Feb 2019 18:00:28 +0800 Subject: [PATCH 0271/1060] ge2d: unmap ge2d dma_buf after ge2d process finished [1/2] PD#SWPL-4839 Problem: have risk of unmap ge2d dma_buf Solution: unmap ge2d dma_buf after ge2d process finished Verify: verify by w400 Change-Id: Ia84786b297f8e95cc9efc038300917c98d6b73f6 Signed-off-by: Pengcheng Chen Signed-off-by: Jian Cao --- .../amlogic/media/common/ge2d/ge2d_dmabuf.c | 4 +- drivers/amlogic/media/common/ge2d/ge2d_wq.c | 111 ++++++++++++++---- include/linux/amlogic/media/ge2d/ge2d.h | 15 +++ 3 files changed, 109 insertions(+), 21 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 5225e72d91ea..046cb1e0f4de 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -515,6 +515,7 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg) cfg->attach = d_att; cfg->vaddr = vaddr; cfg->sg = sg; + ge2d_log_dbg("%s\n", __func__); return ret; vmap_err: @@ -549,7 +550,6 @@ int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) *addr = PFN_PHYS(page_to_pfn(page)); ret = 0; } - ge2d_dma_buffer_unmap(cfg); return ret; } @@ -586,6 +586,8 @@ void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg) dma_buf_detach(dbuf, d_att); dma_buf_put(dbuf); + + ge2d_log_dbg("%s\n", __func__); } void ge2d_dma_buffer_dma_flush(struct device *dev, int fd) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index ae4816d77a6a..e2c420937032 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -389,7 +389,25 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq) pos = pos->next; list_move_tail(&pitem->list, &wq->free_queue); spin_unlock(&wq->lock); - + /* if dma buf detach it */ + if (pitem->config.src_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.src_dma_cfg.dma_cfg); + pitem->config.src_dma_cfg.dma_used = 0; + kfree(pitem->config.src_dma_cfg.dma_cfg); + } + if (pitem->config.src2_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.src2_dma_cfg.dma_cfg); + pitem->config.src2_dma_cfg.dma_used = 0; + kfree(pitem->config.src2_dma_cfg.dma_cfg); + } + if (pitem->config.dst_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.dst_dma_cfg.dma_cfg); + pitem->config.dst_dma_cfg.dma_used = 0; + kfree(pitem->config.dst_dma_cfg.dma_cfg); + } pitem = (struct ge2d_queue_item_s *)pos; } while (pos != head); ge2d_manager.last_wq = wq; @@ -406,6 +424,29 @@ static irqreturn_t ge2d_wq_handle(int irq_number, void *para) return IRQ_HANDLED; } +struct ge2d_dma_cfg_s *ge2d_wq_get_dma_cfg(struct ge2d_context_s *wq, + unsigned int data_type) +{ + struct ge2d_dma_cfg_s *dma_cfg = NULL; + + switch (data_type) { + case AML_GE2D_SRC: + dma_cfg = &wq->config.src_dma_cfg; + break; + case AML_GE2D_SRC2: + dma_cfg = &wq->config.src2_dma_cfg; + break; + case AML_GE2D_DST: + dma_cfg = &wq->config.dst_dma_cfg; + break; + default: + ge2d_log_err("wrong data_type\n"); + break; + } + + return dma_cfg; +} + struct ge2d_src1_data_s *ge2d_wq_get_src_data(struct ge2d_context_s *wq) { return &wq->config.src1_data; @@ -984,11 +1025,13 @@ static int build_ge2d_addr_config_ion( } static int build_ge2d_addr_config_dma( + struct ge2d_context_s *context, struct config_planes_ion_s *plane, unsigned int format, unsigned int *addr, unsigned int *stride, - unsigned int dir + unsigned int dir, + unsigned int data_type ) { int ret = -1; @@ -1000,12 +1043,19 @@ static int build_ge2d_addr_config_dma( bpp_value); if (plane) { if (plane[0].shared_fd) { - struct aml_dma_cfg cfg; + struct ge2d_dma_cfg_s *cfg = NULL; + struct aml_dma_cfg *dma_cfg = NULL; - cfg.fd = plane[0].shared_fd; - cfg.dev = &(ge2d_manager.pdev->dev); - cfg.dir = dir; - ret = ge2d_dma_buffer_get_phys(&cfg, &addr_temp); + cfg = ge2d_wq_get_dma_cfg(context, data_type); + if (!cfg) + return -1; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + dma_cfg->fd = plane[0].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr_temp); if (ret != 0) return ret; } @@ -1164,12 +1214,14 @@ static int build_ge2d_config_ex_ion(struct config_planes_ion_s *plane, } return ret; } -static int build_ge2d_config_ex_dma(struct config_planes_ion_s *plane, +static int build_ge2d_config_ex_dma(struct ge2d_context_s *context, + struct config_planes_ion_s *plane, unsigned int format, unsigned int *canvas_index, int index, unsigned int *r_offset, - unsigned int dir) + unsigned int dir, + unsigned int data_type) { int bpp_value = bpp(format); int ret = -1; @@ -1179,12 +1231,19 @@ static int build_ge2d_config_ex_dma(struct config_planes_ion_s *plane, index &= 0xff; if (plane) { if (plane[0].shared_fd) { - struct aml_dma_cfg cfg; + struct ge2d_dma_cfg_s *cfg = NULL; + struct aml_dma_cfg *dma_cfg = NULL; - cfg.fd = plane[0].shared_fd; - cfg.dev = &(ge2d_manager.pdev->dev); - cfg.dir = dir; - ret = ge2d_dma_buffer_get_phys(&cfg, &addr); + cfg = ge2d_wq_get_dma_cfg(context, data_type); + if (!cfg) + return -1; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + dma_cfg->fd = plane[0].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr); ge2d_log_info("phys: addr=%lx\n", addr); if (ret != 0) return ret; @@ -2071,11 +2130,13 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src1_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_addr_config_dma( + context, &ge2d_config->src_planes[0], ge2d_config->src_para.format, &src_addr, &src_stride, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC) < 0) return -1; ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", src_addr, @@ -2099,13 +2160,15 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src1_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_config_ex_dma( + context, &ge2d_config->src_planes[0], ge2d_config->src_para.format, &index, ALLOC_CANVAS_INDEX + alloc_canvas_offset, &alloc_canvas_offset, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC) < 0) return -1; ge2d_config->src_para.canvas_index = index; ge2d_log_dbg("ge2d dma alloc canvas index:0x%x, format:0x%x\n", @@ -2180,11 +2243,13 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src2_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_addr_config_dma( + context, &ge2d_config->src2_planes[0], ge2d_config->src2_para.format, &src2_addr, &src2_stride, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC2) < 0) return -1; ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", src2_addr, @@ -2208,13 +2273,15 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src2_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_config_ex_dma( + context, &ge2d_config->src2_planes[0], ge2d_config->src2_para.format, &index, ALLOC_CANVAS_INDEX + alloc_canvas_offset, &alloc_canvas_offset, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC2) < 0) return -1; ge2d_config->src2_para.canvas_index = index; ge2d_log_dbg("ge2d src2 dma alloc, canvas index:0x%x,format:0x%x\n", @@ -2292,11 +2359,13 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->dst_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_addr_config_dma( + context, &ge2d_config->dst_planes[0], ge2d_config->dst_para.format, &dst_addr, &dst_stride, - DMA_FROM_DEVICE) < 0) + DMA_FROM_DEVICE, + AML_GE2D_DST) < 0) return -1; ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", dst_addr, @@ -2320,13 +2389,15 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->dst_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_config_ex_dma( + context, &ge2d_config->dst_planes[0], ge2d_config->dst_para.format, &index, ALLOC_CANVAS_INDEX + alloc_canvas_offset, &alloc_canvas_offset, - DMA_FROM_DEVICE) < 0) + DMA_FROM_DEVICE, + AML_GE2D_DST) < 0) return -1; ge2d_config->dst_para.canvas_index = index; ge2d_log_dbg("ge2d: dst dma alloc, index:0x%x, format:0x%x\n", diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index 63dae99453fa..dd2cc301f82d 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -609,6 +609,11 @@ struct ge2d_cmd_s { unsigned char hang_flag; }; +struct ge2d_dma_cfg_s { + int dma_used; + void *dma_cfg; +}; + struct ge2d_config_s { struct ge2d_gen_s gen; struct ge2d_src1_data_s src1_data; @@ -619,6 +624,9 @@ struct ge2d_config_s { unsigned int v_scale_coef_type; unsigned int h_scale_coef_type; unsigned int update_flag; + struct ge2d_dma_cfg_s src_dma_cfg; + struct ge2d_dma_cfg_s src2_dma_cfg; + struct ge2d_dma_cfg_s dst_dma_cfg; }; struct ge2d_dma_buf_s { @@ -627,6 +635,13 @@ struct ge2d_dma_buf_s { int len; }; +enum ge2d_data_type_e { + AML_GE2D_SRC, + AML_GE2D_SRC2, + AML_GE2D_DST, + AML_GE2D_TYPE_INVALID, +}; + enum ge2d_src_dst_e { OSD0_OSD0 = 0, OSD0_OSD1, From c13e3af2210100a0c461460971230cddc75607e6 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Sat, 2 Feb 2019 15:42:04 +0800 Subject: [PATCH 0272/1060] gdc: unmap gdc dma_buf after gdc process stop [2/2] PD#SWPL-4839 Problem: have risk of unmap gdc dma_buf Solution: unmap gdc dma_buf after gdc process stop Verify: verify by w400 Change-Id: If86ac881fd85a5c4b3583567c9748e87149c1d78 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 1 - drivers/amlogic/media/gdc/app/gdc_module.c | 75 +++++++++++-------- .../amlogic/media/gdc/inc/gdc/gdc_config.h | 10 ++- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 1ade0e4b7567..390874a22dab 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -552,7 +552,6 @@ int gdc_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) *addr = PFN_PHYS(page_to_pfn(page)); ret = 0; } - gdc_dma_buffer_unmap(cfg); return ret; } diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index e0f1dade368f..e698bafb1f66 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -520,7 +520,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, { long ret = -1; unsigned long addr; - struct aml_dma_cfg cfg; + struct aml_dma_cfg *cfg = NULL; struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; struct gdc_config_s *gc = &gdc_cmd->gdc_config; @@ -532,10 +532,12 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, switch (gc->format) { case NV12: if (gs_ex->input_buffer.plane_number == 1) { - cfg.fd = gs_ex->input_buffer.y_base_fd; - cfg.dev = &fh->gdev->pdev->dev; - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -550,10 +552,11 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, gdc_log(LOG_INFO, "1 plane get input addr=%x\n", gdc_cmd->y_base_addr); } else if (gs_ex->input_buffer.plane_number == 2) { - cfg.fd = gs_ex->input_buffer.y_base_fd; - cfg.dev = &fh->gdev->pdev->dev; - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -561,11 +564,11 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } gdc_cmd->y_base_addr = addr; - - cfg.fd = gs_ex->input_buffer.uv_base_fd; - cfg.dev = &fh->gdev->pdev->dev; - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane2; + cfg->fd = gs_ex->input_buffer.uv_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -580,10 +583,11 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, } break; case Y_GREY: - cfg.fd = gs_ex->input_buffer.y_base_fd; - cfg.dev = &(fh->gdev->pdev->dev); - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &(fh->gdev->pdev->dev); + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -606,7 +610,7 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, long ret; unsigned long addr = 0; size_t len; - struct aml_dma_cfg cfg; + struct aml_dma_cfg *cfg = NULL; struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; if (fh == NULL || gs_ex == NULL) { @@ -628,10 +632,11 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, } } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - cfg.fd = gs_ex->output_buffer.y_base_fd; - cfg.dev = &(gdc_manager.gdc_dev->pdev->dev); - cfg.dir = DMA_FROM_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.output_cfg; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import out fd %d failed\n", gs_ex->output_buffer.y_base_fd); @@ -655,10 +660,11 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, } } else if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - cfg.fd = gs_ex->config_buffer.y_base_fd; - cfg.dev = &(gdc_manager.gdc_dev->pdev->dev); - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.config_cfg; + cfg->fd = gs_ex->config_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import config fd %d failed\n", gs_ex->config_buffer.shared_fd); @@ -690,10 +696,10 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_log(LOG_INFO, "%s, input addr=%x\n", __func__, fh->gdc_cmd.y_base_addr); mutex_lock(&fh->gdev->d_mutext); - #if 1 + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); - #endif + ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); @@ -704,11 +710,20 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_log(LOG_ERR, "gdc timeout\n"); gdc_stop(gdc_cmd); + mutex_unlock(&fh->gdev->d_mutext); #if 0 if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_cache_flush(gs_ex->output_buffer.shared_fd); #endif - mutex_unlock(&fh->gdev->d_mutext); + if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); + if (gs_ex->input_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + } + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.config_cfg); + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); return 0; } diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h index 9cab803561fe..dbf7300dea08 100644 --- a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -25,7 +25,7 @@ #include #include "system_gdc_io.h" #include "gdc_api.h" - +#include "gdc_dmabuf.h" struct gdc_cmd_s; struct gdc_manager_s { @@ -45,6 +45,13 @@ struct meson_gdc_dev_t { struct miscdevice misc_dev; }; +struct gdc_dma_cfg_t { + struct aml_dma_cfg input_cfg_plane1; + struct aml_dma_cfg input_cfg_plane2; + struct aml_dma_cfg config_cfg; + struct aml_dma_cfg output_cfg; +}; + struct mgdc_fh_s { struct list_head list; wait_queue_head_t irq_queue; @@ -64,6 +71,7 @@ struct mgdc_fh_s { unsigned long c_len; struct gdc_dma_cfg y_dma_cfg; struct gdc_dma_cfg uv_dma_cfg; + struct gdc_dma_cfg_t dma_cfg; }; irqreturn_t interrupt_handler_next(int irq, void *param); From d45bd9b64ac90fb2ab388eba1a2d3b85982a44ae Mon Sep 17 00:00:00 2001 From: Dianzhong Huo Date: Wed, 13 Feb 2019 10:36:29 +0800 Subject: [PATCH 0273/1060] uart: change baud rate minimum value to 2400 [1/1] PD#SH-327 Problem: uart default min baud rate was set 9600, but PTZ PELCO-D and PELCO-P need uart driver support 2400 and 4800 baud rate Solution: change baud rate minimum value to 2400 Verify: Local Change-Id: Iee20ea30a95b89f89a59fab95cecf7d559cbff51 Signed-off-by: Dianzhong Huo --- drivers/amlogic/uart/meson_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/uart/meson_uart.c b/drivers/amlogic/uart/meson_uart.c index 811e362b1920..20ccd0173407 100644 --- a/drivers/amlogic/uart/meson_uart.c +++ b/drivers/amlogic/uart/meson_uart.c @@ -640,7 +640,7 @@ static void meson_uart_set_termios(struct uart_port *port, writel(val, port->membase + AML_UART_CONTROL); spin_unlock_irqrestore(&port->lock, flags); - baud = uart_get_baud_rate(port, termios, old, 9600, 4000000); + baud = uart_get_baud_rate(port, termios, old, 2400, 4000000); meson_uart_change_speed(port, baud); port->read_status_mask = AML_UART_RX_FIFO_OVERFLOW; From 3c7316bfc502a93163438d9aa424e5e0a0d691d7 Mon Sep 17 00:00:00 2001 From: "changqing.gao" Date: Fri, 25 Jan 2019 19:00:05 +0800 Subject: [PATCH 0274/1060] ramdump: support ramdump for g12b/gxl [6/6] PD#SWPL-4350 Problem: ramdump is not enabled on g12b/gxl. Solution: Add ramdump support on g12b/gxl in bl2. Verify: verified on g12b_w400_v1/gxl_p212_v1. Change-Id: I3520fea366af332ef113809560587eeb4db7b6c5 Signed-off-by: changqing.gao --- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 7 +++++++ arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index fe2386d76e17..6fc9d3491594 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -548,6 +548,13 @@ #thermal-sensor-cells = <1>; }; + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 679cddc6a7ae..683eb194c411 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -548,6 +548,13 @@ #thermal-sensor-cells = <1>; }; + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; From 1478e2e6488ebf093ba8bdac66c3435d2e5175fb Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Mon, 18 Feb 2019 14:53:09 +0800 Subject: [PATCH 0275/1060] mm: reclaim for unevictable cma pages [1/1] PD#SWPL-3902 Problem: If cma page is unevictable, migrate it will cost long time. Solution: 1. Recalim unevictable cma file cache pages. 2. Using CMA after first water mark not ok. Verify: einstern Change-Id: I0ecbf5dd535cb034430c4ea623891e7a7ae6e4dd Signed-off-by: Tao Zeng --- drivers/amlogic/memory_ext/aml_cma.c | 11 +++++++++-- include/linux/amlogic/aml_cma.h | 1 + mm/cma.c | 5 ++++- mm/migrate.c | 2 +- mm/page_alloc.c | 13 +++++++++++++ mm/vmscan.c | 3 +++ 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/memory_ext/aml_cma.c b/drivers/amlogic/memory_ext/aml_cma.c index 7f8b96c9945a..563cfb760c0f 100644 --- a/drivers/amlogic/memory_ext/aml_cma.c +++ b/drivers/amlogic/memory_ext/aml_cma.c @@ -101,6 +101,7 @@ EXPORT_SYMBOL(cma_page_count_update); #define RESTRIC_ANON 0 #define ANON_RATIO 60 +bool cma_first_wm_low __read_mostly; bool can_use_cma(gfp_t gfp_flags) { @@ -108,6 +109,9 @@ bool can_use_cma(gfp_t gfp_flags) unsigned long anon_cma; #endif /* RESTRIC_ANON */ + if (unlikely(!cma_first_wm_low)) + return false; + if (cma_forbidden_mask(gfp_flags)) return false; @@ -715,14 +719,17 @@ EXPORT_SYMBOL(aml_cma_free); void show_page(struct page *page) { unsigned long trace = 0; + unsigned long map_flag = -1UL; if (!page) return; #ifdef CONFIG_AMLOGIC_PAGE_TRACE trace = get_page_trace(page); #endif - pr_info("page:%lx, map:%p, f:%lx, m:%d, c:%d, f:%pf\n", - page_to_pfn(page), page->mapping, + if (page->mapping && !((unsigned long)page->mapping & 0x3)) + map_flag = page->mapping->flags; + pr_info("page:%lx, map:%p, mf:%lx, pf:%lx, m:%d, c:%d, f:%pf\n", + page_to_pfn(page), page->mapping, map_flag, page->flags & 0xffffffff, page_mapcount(page), page_count(page), (void *)trace); diff --git a/include/linux/amlogic/aml_cma.h b/include/linux/amlogic/aml_cma.h index 621acac67087..c4727220a133 100644 --- a/include/linux/amlogic/aml_cma.h +++ b/include/linux/amlogic/aml_cma.h @@ -74,6 +74,7 @@ extern bool cma_page(struct page *page); extern unsigned long get_cma_allocated(void); extern unsigned long get_total_cmapages(void); extern spinlock_t cma_iso_lock; +extern bool cma_first_wm_low; extern int cma_debug_level; extern int aml_cma_alloc_range(unsigned long start, unsigned long end); diff --git a/mm/cma.c b/mm/cma.c index b4c8aca77982..589d67d938ea 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -503,6 +503,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) int ret; #ifdef CONFIG_AMLOGIC_CMA int dummy; + unsigned long long tick; #endif /* CONFIG_AMLOGIC_CMA */ if (!cma || !cma->count) @@ -512,6 +513,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) count, align); #ifdef CONFIG_AMLOGIC_CMA + tick = sched_clock(); cma_debug(0, NULL, "(cma %p, count %zu, align %d)\n", (void *)cma, count, align); #endif @@ -576,7 +578,8 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) #ifdef CONFIG_AMLOGIC_CMA aml_cma_alloc_post_hook(&dummy, count, page); - cma_debug(0, NULL, "return %p\n", page); + cma_debug(0, NULL, "return page:%lx, tick:%lld\n", + page ? page_to_pfn(page) : 0, sched_clock() - tick); #endif /* CONFIG_AMLOGIC_CMA */ pr_debug("%s(): returned %p\n", __func__, page); return page; diff --git a/mm/migrate.c b/mm/migrate.c index e5b14b0b5f34..a22bf60ad542 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -445,7 +445,7 @@ int migrate_page_move_mapping(struct address_space *mapping, radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) { spin_unlock_irq(&mapping->tree_lock); #ifdef CONFIG_AMLOGIC_CMA - cma_debug(2, page, " anon page cnt miss match, e:%d, p:%d\n", + cma_debug(2, page, " file page cnt miss match, e:%d, p:%d\n", expected_count, page_has_private(page)); #endif return -EAGAIN; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index cef29ab2bd76..f6ba0d2c1372 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3007,8 +3007,21 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, * are not met, then a high-order request also cannot go ahead * even if a suitable page happened to be free. */ +#ifdef CONFIG_AMLOGIC_CMA + if (free_pages <= min + z->lowmem_reserve[classzone_idx]) { + /* do not using cma until water mark is low */ + if (unlikely(!cma_first_wm_low && free_pages > 0)) { + cma_first_wm_low = true; + pr_info("Now can use cma, free:%ld, wm:%ld\n", + free_pages, + min + z->lowmem_reserve[classzone_idx]); + } + return false; + } +#else if (free_pages <= min + z->lowmem_reserve[classzone_idx]) return false; +#endif /* If this is an order-0 request then the watermark is fine */ if (!order) diff --git a/mm/vmscan.c b/mm/vmscan.c index 7c85bc567f88..75df45923258 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1315,6 +1315,9 @@ static int filecache_need_migrate(struct page *page) if (!PageActive(page) && page_mapcount(page) >= INACTIVE_MIGRATE) return 1; + if (PageUnevictable(page)) + return 0; + return 0; } #endif From a366c846adda16d53ef953a425fc3b2cb6fa3b91 Mon Sep 17 00:00:00 2001 From: Che Song Date: Fri, 22 Feb 2019 11:06:12 +0800 Subject: [PATCH 0276/1060] audio: fix tas5808 no sound [1/1] PD#SWPL-3081 Problem: 1,lack suspend/resume function 2,lack reset pin control Solution: 1,add suspend/resume function 2, add reset pin control Verify: 962x2 Signed-off-by: Che Song Change-Id: I1cb920fdba4ad32048518fdad93e3a5a81039dd9 --- sound/soc/codecs/amlogic/tas5805.c | 156 +++++++++++++++++++++++------ sound/soc/codecs/amlogic/tas5805.h | 10 +- 2 files changed, 136 insertions(+), 30 deletions(-) diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c index 36f11cf2c519..615320e73b89 100644 --- a/sound/soc/codecs/amlogic/tas5805.c +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -24,10 +24,11 @@ #include #include #include +#include #include "tas5805.h" -#define TAS5805M_DRV_NAME "tas5805m" +#define TAS5805M_DRV_NAME "tas5805" #define TAS5805M_RATES (SNDRV_PCM_RATE_8000 | \ SNDRV_PCM_RATE_11025 | \ @@ -227,9 +228,7 @@ const uint32_t tas5805m_volume[] = { struct tas5805m_priv { struct regmap *regmap; - - struct mutex lock; - + struct tas5805m_platform_data *pdata; int vol; int mute; }; @@ -276,9 +275,7 @@ static int tas5805m_vol_locked_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - mutex_lock(&tas5805m->lock); ucontrol->value.integer.value[0] = tas5805m->vol; - mutex_unlock(&tas5805m->lock); return 0; } @@ -339,12 +336,10 @@ static int tas5805m_vol_locked_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - mutex_lock(&tas5805m->lock); tas5805m->vol = ucontrol->value.integer.value[0]; tas5805m_set_volume(codec, tas5805m->vol); - mutex_unlock(&tas5805m->lock); return 0; } @@ -353,7 +348,6 @@ static int tas5805m_mute(struct snd_soc_codec *codec, int mute) { u8 reg03_value = 0; u8 reg35_value = 0; -// struct snd_soc_codec *codec = dai->codec; if (mute) { //mute both left & right channels @@ -380,13 +374,9 @@ static int tas5805m_mute_locked_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - mutex_lock(&tas5805m->lock); - tas5805m->mute = ucontrol->value.integer.value[0]; tas5805m_mute(codec, tas5805m->mute); - mutex_unlock(&tas5805m->lock); - return 0; } @@ -395,11 +385,7 @@ static int tas5805m_mute_locked_get(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - - mutex_lock(&tas5805m->lock); ucontrol->value.integer.value[0] = tas5805m->mute; - mutex_unlock(&tas5805m->lock); - return 0; } @@ -420,6 +406,31 @@ static const struct snd_kcontrol_new tas5805m_vol_control[] = { } }; +static int tas5805m_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + pr_debug("level = %d\n", level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* Full power on */ + break; + + case SND_SOC_BIAS_STANDBY: + break; + + case SND_SOC_BIAS_OFF: + /* The chip runs through the power down sequence for us. */ + break; + } + codec->component.dapm.bias_level = level; + + return 0; +} + static int tas5805m_snd_probe(struct snd_soc_codec *codec) { int ret; @@ -429,8 +440,40 @@ static int tas5805m_snd_probe(struct snd_soc_codec *codec) return ret; } +static int tas5805m_snd_suspend(struct snd_soc_codec *codec) +{ + dev_info(codec->dev, "tas5805m_suspend!\n"); + tas5805m_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int tas5805m_snd_resume(struct snd_soc_codec *codec) +{ + int ret; + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + + dev_info(codec->dev, "tas5805m_snd_resume!\n"); + ret = + regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, + ARRAY_SIZE(tas5805m_init_sequence)); + if (ret != 0) { + dev_err(codec->dev, "Failed to initialize TAS5805M: %d\n", ret); + goto err; + } + + tas5805m_set_volume(codec, tas5805m->vol); + tas5805m_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +err: + return ret; +} + static struct snd_soc_codec_driver soc_codec_tas5805m = { .probe = tas5805m_snd_probe, + .suspend = tas5805m_snd_suspend, + .resume = tas5805m_snd_resume, + .set_bias_level = tas5805m_set_bias_level, }; static const struct snd_soc_dai_ops tas5805m_dai_ops = { @@ -449,28 +492,60 @@ static struct snd_soc_dai_driver tas5805m_dai = { .ops = &tas5805m_dai_ops, }; +static int reset_tas5805m_GPIO(struct device *dev) +{ + struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + int ret = 0; + + if (pdata->reset_pin < 0) + return 0; + + ret = devm_gpio_request_one(dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, + "tas5805m-reset-pin"); + if (ret < 0) + return -1; + + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + mdelay(1); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + mdelay(1); + + return 0; +} + +static int tas5805m_parse_dt( + struct tas5805m_priv *tas5805m, + struct device_node *np) +{ + int ret = 0; + int reset_pin = -1; + + reset_pin = of_get_named_gpio(np, "reset_pin", 0); + if (reset_pin < 0) { + pr_err("%s fail to get reset pin from dts!\n", __func__); + ret = -1; + } else { + pr_info("%s pdata->reset_pin = %d!\n", __func__, + tas5805m->pdata->reset_pin); + } + tas5805m->pdata->reset_pin = reset_pin; + + return ret; +} + static int tas5805m_probe(struct device *dev, struct regmap *regmap) { - struct tas5805m_priv *tas5805m; int ret; - tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL); - if (!tas5805m) - return -ENOMEM; - - dev_set_drvdata(dev, tas5805m); - tas5805m->regmap = regmap; - tas5805m->vol = 100; //100, -10dB - - mutex_init(&tas5805m->lock); - + reset_tas5805m_GPIO(dev); ret = regmap_register_patch(regmap, tas5805m_init_sequence, ARRAY_SIZE(tas5805m_init_sequence)); if (ret != 0) { dev_err(dev, "Failed to initialize TAS5805M: %d\n", ret); goto err; - } ret = @@ -487,16 +562,39 @@ err: } + static int tas5805m_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct regmap *regmap; struct regmap_config config = tas5805m_regmap; + struct tas5805m_priv *tas5805m; + struct tas5805m_platform_data *pdata; + + tas5805m = devm_kzalloc(&i2c->dev, + sizeof(struct tas5805m_priv), GFP_KERNEL); + if (!tas5805m) + return -ENOMEM; regmap = devm_regmap_init_i2c(i2c, &config); if (IS_ERR(regmap)) return PTR_ERR(regmap); + pdata = devm_kzalloc(&i2c->dev, + sizeof(struct tas5805m_platform_data), + GFP_KERNEL); + if (!pdata) { + pr_err("%s failed to kzalloc for tas5805 pdata\n", __func__); + return -ENOMEM; + } + tas5805m->pdata = pdata; + + tas5805m_parse_dt(tas5805m, i2c->dev.of_node); + tas5805m->regmap = regmap; + tas5805m->vol = 100; //100, -10dB + + dev_set_drvdata(&i2c->dev, tas5805m); + return tas5805m_probe(&i2c->dev, regmap); } diff --git a/sound/soc/codecs/amlogic/tas5805.h b/sound/soc/codecs/amlogic/tas5805.h index ba6066204b12..5f3fdeb41b4d 100644 --- a/sound/soc/codecs/amlogic/tas5805.h +++ b/sound/soc/codecs/amlogic/tas5805.h @@ -27,7 +27,10 @@ static const struct reg_sequence tas5805m_init_sequence[] = { {0x00, 0x00}, {0x7f, 0x00}, {0x00, 0x00}, + {0x02, 0x11},//Fsw=384kHz, BD Mode, 1SPW Mode {0x66, 0x85}, + {0x6b, 0x03},//Enable SS + {0x6c, 0x03},//Set Tri-freq to 24Hz, SS range 336~432kHz {0x00, 0x00}, {0x7f, 0x8c}, {0x00, 0x2a}, @@ -1871,10 +1874,15 @@ static const struct reg_sequence tas5805m_init_sequence[] = { {0x00, 0x00}, {0x7f, 0x00}, {0x00, 0x00}, - {0x02, 0x00}, + {0x02, 0x11},//Fsw=384kHz, 1SPW Mode {0x00, 0x00}, {0x7f, 0x00}, {0x00, 0x00}, {0x03, 0x03}, {0x35, 0x11}, }; + +struct tas5805m_platform_data { + int reset_pin; +}; + From 50a702dd9679358f7aa4c5c72c56f086ab340ca8 Mon Sep 17 00:00:00 2001 From: Bichao Zheng Date: Wed, 16 Jan 2019 14:21:43 +0800 Subject: [PATCH 0277/1060] pwm: meson: add relative_duty interface in pwm sysfs [1/1] PD#SWPL-4225 Problem: This interface is added to facilitate debugging the voltage- table in pwm regulator, which can output different percentages of waveforms in a fixed pwm cycle. example: echo 50 100 > sys/class/pwm/pwmchipx/pwmx/relative_duty output 50% duty pwm Solution: add relative_duty interface in pwm sysfs Verify: test pass on tl1_X301_v1 tl1_skt_v1 Change-Id: Icd01e681694b81f3790f7cce8c326db02674a48c Signed-off-by: Bichao Zheng --- drivers/pwm/sysfs.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 0850b11dfd83..4841a049de99 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -223,11 +223,52 @@ static ssize_t capture_show(struct device *child, return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); } +#ifdef CONFIG_AMLOGIC_MODIFY +/* + * This interface is added to facilitate debugging the voltage- + * table in pwm regulator, which can output different percentages + * of waveforms in a fixed pwm cycle. + * example: + * echo 50 100 > sys/class/pwm/pwmchipx/pwmx/relative_duty + * output 50% duty pwm + */ +static ssize_t relative_duty_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; + struct pwm_state state = pwm->state; + int scale, dutycycle, ret; + + ret = sscanf(buf, "%d %d", &dutycycle, &scale); + if (ret != 2) { + pr_err("Can't parse addr and scale,dutycycle:[dutycycle scale]\n"); + return -EINVAL; + } + + if (!scale || dutycycle > scale) { + pr_err("parameter error\n"); + return -EINVAL; + } + + mutex_lock(&export->lock); + pwm_set_relative_duty_cycle(&state, dutycycle, scale); + ret = pwm_apply_state(pwm, &state); + mutex_unlock(&export->lock); + + return ret ? : size; +} +#endif + static DEVICE_ATTR_RW(period); static DEVICE_ATTR_RW(duty_cycle); static DEVICE_ATTR_RW(enable); static DEVICE_ATTR_RW(polarity); static DEVICE_ATTR_RO(capture); +#ifdef CONFIG_AMLOGIC_MODIFY +static DEVICE_ATTR_WO(relative_duty); +#endif static struct attribute *pwm_attrs[] = { &dev_attr_period.attr, @@ -235,6 +276,9 @@ static struct attribute *pwm_attrs[] = { &dev_attr_enable.attr, &dev_attr_polarity.attr, &dev_attr_capture.attr, +#ifdef CONFIG_AMLOGIC_MODIFY + &dev_attr_relative_duty.attr, +#endif NULL }; ATTRIBUTE_GROUPS(pwm); From e8d22d63b157e66d6be59cb926f9bb15712ca453 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Wed, 13 Feb 2019 14:28:18 +0800 Subject: [PATCH 0278/1060] avin: fix avin detect incorrect report [1/1] PD#SWPL-4840 Problem: avin detect compare level setting too high Solution: adjust the compare level to 635mv Verify: x301 Change-Id: I5246482338b3181d98a3836dcff09a3f33da113e Signed-off-by: Nian Jing --- drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c index 60759b13e39e..31fda551713a 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c @@ -56,7 +56,7 @@ static unsigned int dc_level_adj = 4; /*0:635mv; 1:686mv; 2:733mv; 3:776mv; 4:816mv; 5:853mv; 6:887mv; 7:919mv*/ -static unsigned int comp_level_adj = 5; +static unsigned int comp_level_adj; /*0:use internal VDC to bias CVBS_in*/ /*1:use ground to bias CVBS_in*/ From e029b87285f61f5beefa447b9383e3bd1effd087 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Wed, 20 Feb 2019 14:55:29 +0800 Subject: [PATCH 0279/1060] lcd: unify lcd driver frame_rate change function [1/1] PD#SWPL-4680 Problem: unify lcd driver frame_rate change function Solution: create a unified api(lcd_clk_change) to management the function Verify: verify by t962x2-r311 Change-Id: I1ab378aa2556db0636aabe8c20f3b97845b8184f Signed-off-by: Shaochan Liu --- drivers/amlogic/media/vout/lcd/lcd_common.c | 15 ++++++++++++ drivers/amlogic/media/vout/lcd/lcd_common.h | 1 + .../media/vout/lcd/lcd_tablet/lcd_tablet.c | 24 ++----------------- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 12 +--------- .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 24 ++----------------- 5 files changed, 21 insertions(+), 55 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index 5edf84921fcb..68fd109c5bfe 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -1064,6 +1064,21 @@ int lcd_vmode_change(struct lcd_config_s *pconf) } #endif +void lcd_clk_change(struct lcd_config_s *pconf) +{ + switch (pconf->lcd_timing.clk_change) { + case LCD_CLK_PLL_CHANGE: + lcd_clk_generate_parameter(pconf); + lcd_clk_set(pconf); + break; + case LCD_CLK_FRAC_UPDATE: + lcd_clk_update(pconf); + break; + default: + break; + } +} + void lcd_venc_change(struct lcd_config_s *pconf) { unsigned int htotal, vtotal, frame_rate; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index ce93c41ea5e3..9512a7bc809b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -113,6 +113,7 @@ extern int lcd_vlock_param_load_from_unifykey(struct lcd_config_s *pconf, extern void lcd_optical_vinfo_update(void); extern void lcd_timing_init_config(struct lcd_config_s *pconf); extern int lcd_vmode_change(struct lcd_config_s *pconf); +extern void lcd_clk_change(struct lcd_config_s *pconf); extern void lcd_venc_change(struct lcd_config_s *pconf); extern void lcd_if_enable_retry(struct lcd_config_s *pconf); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 50814cce5054..1d2b741dce95 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -192,17 +192,7 @@ static int lcd_framerate_automation_set_mode(void) #endif /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_tablet_config_post_update(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); @@ -1259,17 +1249,7 @@ static void lcd_set_vinfo(unsigned int sync_duration) #endif /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_tablet_config_post_update(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index e2e8f9b13b00..4124b6735c90 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -1663,17 +1663,7 @@ int lcd_tv_driver_change(void) lcd_vbyone_interrupt_enable(0); } - switch (pconf->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(pconf); - lcd_clk_set(pconf); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(pconf); - break; - default: - break; - } + lcd_clk_change(pconf); lcd_venc_change(pconf); if (pconf->lcd_basic.lcd_type == LCD_VBYONE) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index f309f02fadff..bb2f594bbda8 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -445,17 +445,7 @@ static int lcd_framerate_automation_set_mode(void) if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_interrupt_enable(0); /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_wait_stable(); @@ -1360,17 +1350,7 @@ static void lcd_set_vinfo(unsigned int sync_duration) if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_interrupt_enable(0); /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_wait_stable(); From 4129b81198ffa14e501b0bb2b1145312b42d9d00 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Thu, 21 Feb 2019 13:36:09 +0800 Subject: [PATCH 0280/1060] config: fix compile error for axg-s400. [1/1] PD#SWPL-5059 Problem: compile error. Solution: add CONFIG_AMLOGIC_VIDEOSYNC which already exist in 64bit config Verify: locall. Change-Id: I6d35b9388bbe1c28110cfce17f00de2a5b72f08e Signed-off-by: Jianxiong Pan --- arch/arm/configs/meson64_a32_smarthome_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/meson64_a32_smarthome_defconfig b/arch/arm/configs/meson64_a32_smarthome_defconfig index 762fad1e5449..3efa96011b19 100644 --- a/arch/arm/configs/meson64_a32_smarthome_defconfig +++ b/arch/arm/configs/meson64_a32_smarthome_defconfig @@ -553,3 +553,4 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y CONFIG_X509_CERTIFICATE_PARSER=y CONFIG_CRC_T10DIF=y CONFIG_CRC7=y +CONFIG_AMLOGIC_VIDEOSYNC=y From 514fd29c8239f350b5eb9eab989d20070db1dae0 Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Wed, 20 Feb 2019 14:43:10 +0800 Subject: [PATCH 0281/1060] audio: Fix Linein Not work [2/2] PD#SWPL-4737 Problem: HDMI in and Line in use the same device. But their input I2S inskew is not same. Solution: We need use separate skew setting for different source. Verify: A113 Change-Id: I8e306af06d9c9d614c4032f2030dbedb64a7f6df Signed-off-by: yujie.wu --- sound/soc/amlogic/auge/audio_utils.c | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 14617d785b52..85aeb04212e8 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -42,6 +42,7 @@ struct snd_elem_info { static unsigned int loopback_enable; static unsigned int loopback_is_running; static unsigned int datain_datalb_total; +static unsigned int audio_inskew; static const char *const loopback_enable_texts[] = { "Disable", @@ -625,6 +626,51 @@ static int audio_locker_set_enum( return 0; } +static const char *const audio_inskew_texts[] = { + "0", + "1", + "2", + "3", + "4", + "5", + "6", +}; + +static const struct soc_enum audio_inskew_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_inskew_texts), + audio_inskew_texts); + + +static int audio_inskew_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = audio_inskew; + + return 0; +} + +static int audio_inskew_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int reg_in, off_set; + int inskew; + int id; + + id = (ucontrol->value.enumerated.item[0] >> 16) & 0xffff; + inskew = (int)(ucontrol->value.enumerated.item[0] & 0xffff); + audio_inskew = inskew; + off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; + reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * id; + pr_info("id=%d set inskew=%d\n", id, inskew); + audiobus_update_bits(reg_in, 0x7 << 16, inskew << 16); + + return 0; +} + + + #define SND_MIX(xname, type, xenum, xshift, xmask) \ SND_ENUM(xname, type, CTRL0, xenum, xshift, xmask) @@ -925,6 +971,12 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { audio_locker_enum, audio_locker_get_enum, audio_locker_set_enum), + + /* audio inskew */ + SOC_ENUM_EXT("audio inskew set", + audio_inskew_enum, + audio_inskew_get_enum, + audio_inskew_set_enum), }; From fed3bef2db6cecf8c59cc74d1255ddbda503f11d Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Fri, 22 Feb 2019 13:47:22 +0800 Subject: [PATCH 0282/1060] audio: Add binv setting [1/2] PD#SWPL-4733 Problem: The Speaker has noise Solution: The binv is not correct for TDM out c, we will use amixer to set it Verify: A113 Change-Id: I7c8af8e00e3c8834533347947630a6944b7e2136 Signed-off-by: yujie.wu --- sound/soc/amlogic/auge/audio_utils.c | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 85aeb04212e8..16943bc3b841 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -669,6 +669,40 @@ static int audio_inskew_set_enum( return 0; } +static const char *const tdmout_c_binv_texts[] = { + "0", + "1", +}; + +static const struct soc_enum tdmout_c_binv_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tdmout_c_binv_texts), + tdmout_c_binv_texts); + + +static int tdmout_c_binv_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int val; + + val = audiobus_read(EE_AUDIO_CLK_TDMOUT_C_CTRL); + ucontrol->value.enumerated.item[0] = ((val >> 29) & 0x1); + + return 0; +} + +static int tdmout_c_binv_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int binv; + + binv = ucontrol->value.enumerated.item[0]; + audiobus_update_bits(EE_AUDIO_CLK_TDMOUT_C_CTRL, 0x1 << 29, binv << 29); + + return 0; +} + #define SND_MIX(xname, type, xenum, xshift, xmask) \ @@ -977,6 +1011,11 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { audio_inskew_enum, audio_inskew_get_enum, audio_inskew_set_enum), + /* tdmc out binv */ + SOC_ENUM_EXT("tdmout_c binv set", + tdmout_c_binv_enum, + tdmout_c_binv_get_enum, + tdmout_c_binv_set_enum), }; From a022098ae1674b7e1baf39bf5a96e37406d2d893 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Mon, 25 Feb 2019 10:26:58 +0800 Subject: [PATCH 0283/1060] atv_demod: Tuner crashes easily when fast finetune [1/1] PD#SWPL-4421 Problem: Tuner crashes easily when fast fine tune Solution: Delay afc work to prevent tuner crash Verify: verified by x301 Change-Id: I011f7c3f71a30f95a9b7aa371d5fabe71f249051 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_afc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/atv_demod/atv_demod_afc.c b/drivers/amlogic/atv_demod/atv_demod_afc.c index 04edf2009df6..b4647cd0a2f9 100644 --- a/drivers/amlogic/atv_demod/atv_demod_afc.c +++ b/drivers/amlogic/atv_demod/atv_demod_afc.c @@ -263,6 +263,7 @@ static void atv_demod_afc_enable(struct atv_demod_afc *afc) afc->offset = 0; afc->no_sig_cnt = 0; afc->pre_step = 0; + afc->timer_delay_cnt = 20; afc->status = AFC_LOCK_STATUS_NULL; add_timer(&afc->timer); afc->state = true; From 65b4ad448bc5210db85245e6026431a7744813d5 Mon Sep 17 00:00:00 2001 From: Qiang Li Date: Thu, 17 Jan 2019 13:47:23 +0800 Subject: [PATCH 0284/1060] emmc: change the g12a portc emmc hardware reset pin. [1/1] PD#SWPL-4276 Problem: g12a portc emmc hardware reset pin is error. Solution: change the g12a portc emmc hardware reset pin. Verify: g12a_u200 Change-Id: Ifd3be5ae9f19eae9241b21faeceffc07aa70ce86 Signed-off-by: Qiang Li --- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 01d7cb2733dc..3f6f80ed1cb3 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1368,7 +1368,7 @@ calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; card_type = <1>; /* 1:mmc card(include eMMC), * 2:sd card(include tSD) diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 654f58ccaf98..1d540f503002 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -1378,7 +1378,7 @@ calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; card_type = <1>; /* 1:mmc card(include eMMC), * 2:sd card(include tSD) From 8778a0991ca569bfa22000c197804bf97ed34bbe Mon Sep 17 00:00:00 2001 From: "huijie.huang" Date: Tue, 26 Feb 2019 16:00:06 +0800 Subject: [PATCH 0285/1060] audio: auge: fix hw resample crash when pcm disabled [1/1] PD#SWPL-3365 Problem: system would reboot when carshed by hw resample Solution: actrl of toddr is modified to null pointer, so it leads to crash. fix to pass toddr pointer to function, not fetched by resample module. Verify: TL1 socket board Change-Id: I9227ef2e1ca225e72b0408bc694e6a20d623c8a9 Signed-off-by: huijie.huang --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 73 +++++++++++++++++--- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 77fbaa5c00d8..f689dac1f0a4 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -173,11 +173,13 @@ compatible = "amlogic, tl1-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + aml-audio-card,dai-link@0 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; - bitclock-inversion; + continuous-clock; + //bitclock-inversion; //frame-inversion; /* master mode */ bitclock-master = <&tdma>; @@ -188,7 +190,7 @@ * frame-master = <&tdmacodec>; */ /* suffix-name, sync with android audio hal used for */ - suffix-name = "alsaPORT-pcm"; + suffix-name = "alsaPORT-i2s"; tdmacpu: cpu { sound-dai = <&tdma>; dai-tdm-slot-tx-mask = @@ -201,11 +203,13 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&tl1_codec>; + sound-dai = <&ad82584f &tl1_codec>; }; }; aml-audio-card,dai-link@1 { + status = "disabled"; + format = "i2s"; mclk-fs = <256>; //continuous-clock; @@ -218,7 +222,7 @@ //bitclock-master = <&tdmbcodec>; //frame-master = <&tdmbcodec>; /* suffix-name, sync with android audio hal used for */ - suffix-name = "alsaPORT-i2s"; + suffix-name = "alsaPORT-pcm"; cpu { sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; @@ -240,6 +244,8 @@ }; aml-audio-card,dai-link@2 { + status = "disabled"; + format = "i2s"; mclk-fs = <256>; //continuous-clock; @@ -304,6 +310,7 @@ aml-audio-card,dai-link@6 { mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; cpu { sound-dai = <&extn>; system-clock-frequency = <12288000>; @@ -924,15 +931,28 @@ #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; - dai-tdm-lane-slot-mask-out = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; dai-tdm-clk-sel = <0>; clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll"; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdma_mclk &tdmout_a &tdmin_a>; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; status = "okay"; }; @@ -1086,8 +1106,8 @@ asrca: resample@0 { compatible = "amlogic, tl1-resample-a"; - clocks = <&clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_MCLK_F + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src @@ -1102,7 +1122,7 @@ */ resample_module = <3>; - status = "disabled"; + status = "okay"; }; asrcb: resample@1 { @@ -1154,6 +1174,13 @@ */ src = <4>; + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + status = "disabled"; }; }; /* end of audiobus */ @@ -1248,6 +1275,30 @@ status = "okay"; }; +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + &sd_emmc_c { status = "okay"; emmc { From 3fbee01aec7a4e8b8e1799042bd8274a5e41ba6d Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Thu, 21 Feb 2019 20:17:07 +0800 Subject: [PATCH 0286/1060] tvafe: optimize stable time on manual setting [1/1] PD#SWPL-5052 Problem: optimize swith channel time Solution: lower wait time on manual colorfmt setting stable time optimized from 500ms -> 300ms Verify: x301 Change-Id: I7e7d711d1c3ab0630d41e933c53ce34d0025e860 Signed-off-by: Nian Jing --- drivers/amlogic/media/vin/tvin/tvafe/tvafe.c | 3 +++ drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c | 5 +++++ drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h | 3 +++ 3 files changed, 11 insertions(+) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index 6cd3ff361f8b..9192297e4b59 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -323,6 +323,7 @@ void tvafe_dec_start(struct tvin_frontend_s *fe, enum tvin_sig_fmt_e fmt) enum tvin_port_e port = devp->tvafe.parm.port; mutex_lock(&devp->afe_mutex); + manual_flag = 0; if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { tvafe_pr_err("tvafe_dec_start(%d) decode havn't opened\n", @@ -974,6 +975,8 @@ static long tvafe_ioctl(struct file *file, tvafe->cvd2.manual_fmt = fmt; tvafe_pr_info("%s: ioctl set cvd2 manual fmt:%s.\n", __func__, tvin_sig_fmt_str(fmt)); + if (fmt != TVIN_SIG_FMT_NULL) + manual_flag = 1; break; } case TVIN_IOC_G_AFE_CVBS_STD: diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c index 4e5a98c39513..1ac4fbe53744 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c @@ -92,9 +92,11 @@ static int atv_stable_fmt_check_enable; static int atv_prestable_out_cnt = 100; static int other_stable_out_cnt = EXIT_STABLE_MAX_CNT; static int other_unstable_out_cnt = BACK_STABLE_MAX_CNT; +static int manual_unstable_out_cnt = 30; static int other_unstable_in_cnt = UNSTABLE_MAX_CNT; static int nosig_in_cnt = NOSIG_MAX_CNT; static int nosig2_unstable_cnt = EXIT_NOSIG_MAX_CNT; +bool manual_flag; #ifdef DEBUG_SUPPORT module_param(back_nosig_max_cnt, int, 0664); @@ -408,6 +410,9 @@ void tvin_smr(struct vdin_dev_s *devp) (port == TVIN_PORT_CVBS0)) && (devp->flags & VDIN_FLAG_SNOW_FLAG)) unstb_in = sm_p->atv_unstable_out_cnt; + else if ((port == TVIN_PORT_CVBS3) && + manual_flag) + unstb_in = manual_unstable_out_cnt; else if ((port >= TVIN_PORT_HDMI0) && (port <= TVIN_PORT_HDMI7)) unstb_in = sm_p->hdmi_unstable_out_cnt; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h index b3009111cc5b..92fdd32d3013 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h @@ -49,6 +49,9 @@ struct tvin_sm_s { int atv_stable_out_cnt; int hdmi_unstable_out_cnt; }; + +extern bool manual_flag; + void tvin_smr(struct vdin_dev_s *pdev); void tvin_smr_init(int index); void reset_tvin_smr(unsigned int index); From beedfb2abfd813a197fd956431cd24a1825fea71 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Mon, 25 Feb 2019 14:38:27 +0800 Subject: [PATCH 0287/1060] vdin: fix snowflake bottom screen [1/1] PD#SWPL-5129 Problem: cut window need restore when nosignal Solution: restore cutwin when nosignal Verify: verified by r341 Change-Id: If18dbd18df11cce5d1ddb99ee266901b75b065b3 Signed-off-by: Nian Jing --- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 1 + .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 23 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index fcaa930b389f..2303780d425c 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -860,6 +860,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("color_depth_support:0x%x\n", devp->color_depth_support); pr_info("cma_flag:0x%x\n", devp->cma_config_flag); pr_info("auto_cutwindow_en:%d\n", devp->auto_cutwindow_en); + pr_info("cutwindow_cfg:%d\n", devp->cutwindow_cfg); pr_info("auto_ratio_en:%d\n", devp->auto_ratio_en); pr_info("cma_mem_alloc:%d\n", devp->cma_mem_alloc); pr_info("cma_mem_size:0x%x\n", devp->cma_mem_size); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 74993dc3c561..c5f93547e171 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -93,6 +93,7 @@ static unsigned int dv_work_delby; * enable viu_hw_irq for the bandwidth is enough on gxbb/gxtvbb and laters ic */ static bool viu_hw_irq = 1; +static bool de_fmt_flag; #ifdef DEBUG_SUPPORT module_param(canvas_config_mode, int, 0664); @@ -452,6 +453,21 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->canvas_config_mode = canvas_config_mode; /* h_active/v_active will be recalculated by bellow calling */ vdin_set_decimation(devp); + if (de_fmt_flag == 1 && + (devp->prop.vs != 0 || + devp->prop.ve != 0 || + devp->prop.hs != 0 || + devp->prop.he != 0)) { + devp->prop.vs = 0; + devp->prop.ve = 0; + devp->prop.hs = 0; + devp->prop.he = 0; + devp->prop.pre_vs = 0; + devp->prop.pre_ve = 0; + devp->prop.pre_hs = 0; + devp->prop.pre_he = 0; + pr_info("ioctl start dec,restore the cutwin param.\n"); + } vdin_set_cutwin(devp); vdin_set_hvscale(devp); if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) @@ -1995,10 +2011,13 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } if ((devp->parm.info.fmt == TVIN_SIG_FMT_NULL) && - (devp->parm.port == TVIN_PORT_CVBS3)) + (devp->parm.port == TVIN_PORT_CVBS3)) { + de_fmt_flag = 1; fmt = devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; - else + } else { + de_fmt_flag = 0; fmt = devp->parm.info.fmt = parm.info.fmt; + } devp->fmt_info_p = (struct tvin_format_s *)tvin_get_fmt_info(fmt); if (!devp->fmt_info_p) { From b9edd88dd61b6a601cb2a53e58b8149721644c72 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 21 Feb 2019 12:23:45 +0800 Subject: [PATCH 0288/1060] vout: add dummy_panel display mode [1/1] PD#SWPL-5017 Problem: need support dummy lcd for viu1 Solution: add dummp_panel display mode. when need viu1 + viu2 -> encl, and show viu2 data, you can use below setting: echo dump_panel >/sys/class/display/mode echo panel >/sys/class/display2/mode Verify: x301 Change-Id: I8a7fb52e2272fc8f71d682424ff20dc37f02b726 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/lcd/lcd_debug.c | 5 +- .../media/vout/lcd/lcd_tablet/lcd_tablet.c | 3 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 3 +- .../amlogic/media/vout/vout_serve/vout_func.c | 13 +++++ .../amlogic/media/vout/vout_serve/vout_func.h | 1 + .../media/vout/vout_serve/vout_serve.c | 54 +++++++++++++++++++ include/linux/amlogic/media/vout/vinfo.h | 3 +- 7 files changed, 77 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 5665b8ccc2da..b0c4beb0b7f3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -512,12 +512,13 @@ static int lcd_info_print(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "driver version: %s\n" - "panel_type: %s, chip: %d, mode: %s, status: %d\n" + "panel_type: %s, chip: %d, mode: %s, status: %d, viu_sel: %d\n" "key_valid: %d, config_load: %d\n" "fr_auto_policy: %d\n", lcd_drv->version, pconf->lcd_propname, lcd_drv->data->chip_type, - lcd_mode_mode_to_str(lcd_drv->lcd_mode), lcd_drv->lcd_status, + lcd_mode_mode_to_str(lcd_drv->lcd_mode), + lcd_drv->lcd_status, lcd_drv->viu_sel, lcd_drv->lcd_key_valid, lcd_drv->lcd_config_load, lcd_drv->fr_auto_policy); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 1d2b741dce95..56f2647119cb 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -131,7 +131,8 @@ static int lcd_vout_clr_state(int index) struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); lcd_vout_state &= ~(1 << index); - lcd_drv->viu_sel = LCD_VIU_SEL_NONE; + if (lcd_drv->viu_sel == index) + lcd_drv->viu_sel = LCD_VIU_SEL_NONE; return 0; } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index bb2f594bbda8..5f79aea4bec7 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -389,7 +389,8 @@ static int lcd_vout_clr_state(int index) struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); lcd_vout_state &= ~(1 << index); - lcd_drv->viu_sel = LCD_VIU_SEL_NONE; + if (lcd_drv->viu_sel == index) + lcd_drv->viu_sel = LCD_VIU_SEL_NONE; return 0; } diff --git a/drivers/amlogic/media/vout/vout_serve/vout_func.c b/drivers/amlogic/media/vout/vout_serve/vout_func.c index c8661b355196..0ea80a6fac8a 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_func.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_func.c @@ -245,6 +245,19 @@ void vout_func_update_viu(int index) if (clk_bit < 0xff) vout_func_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1); + /* special setting for dummy mode */ + if (index == 1) { + if (vinfo->mode == VMODE_DUMMY_LCD) { + /* viu1 use encl_vsync */ + vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 4, 2); + vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 1, 20, 1); + vout_func_vcbus_setb(VPP_WRBAK_CTRL, 1, 11, 1); + } else { + vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 20, 1); + vout_func_vcbus_setb(VPP_WRBAK_CTRL, 0, 11, 1); + } + } + #if 0 VOUTPR("%s: %d, mux_sel=%d, clk_sel=%d\n", __func__, index, mux_sel, clk_sel); diff --git a/drivers/amlogic/media/vout/vout_serve/vout_func.h b/drivers/amlogic/media/vout/vout_serve/vout_func.h index a7e6d4c07e9b..3ad9a3395120 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_func.h +++ b/drivers/amlogic/media/vout/vout_serve/vout_func.h @@ -36,6 +36,7 @@ #define VPU_VENCX_CLK_CTRL 0x2785 #define VPP_POSTBLEND_H_SIZE 0x1d21 #define VPP2_POSTBLEND_H_SIZE 0x1921 +#define VPP_WRBAK_CTRL 0x1df9 struct vout_cdev_s { dev_t devno; diff --git a/drivers/amlogic/media/vout/vout_serve/vout_serve.c b/drivers/amlogic/media/vout/vout_serve/vout_serve.c index 2978d5edb361..d41b8697bb5b 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_serve.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_serve.c @@ -131,6 +131,24 @@ static struct vinfo_s nulldisp_vinfo[] = { .viu_mux = VIU_MUX_MAX, .vout_device = NULL, }, + { + .name = "dummy_panel", + .mode = VMODE_DUMMY_LCD, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 148500000, + .htotal = 2200, + .vtotal = 1125, + .fr_adj_type = VOUT_FR_ADJ_NONE, + .viu_color_fmt = COLOR_FMT_RGB444, + .viu_mux = VIU_MUX_MAX, + .vout_device = NULL, + }, }; static struct vinfo_s *nulldisp_get_current_info(void) @@ -395,6 +413,41 @@ static ssize_t vout_mode_store(struct class *class, return count; } +static ssize_t vout_dummy_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int tmp[4], sync_duration; + enum vmode_e mode; + int ret; + + mutex_lock(&vout_serve_mutex); + mode = VMODE_DUMMY_LCD; + ret = sscanf(buf, "%d %d %d %d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]); + if (ret == 2) { + nulldisp_vinfo[2].width = tmp[0]; + nulldisp_vinfo[2].height = tmp[1]; + nulldisp_vinfo[2].field_height = tmp[1]; + VOUTPR("set dummy size: %d x %d\n", tmp[0], tmp[1]); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode); + } else if (ret == 4) { + nulldisp_vinfo[2].width = tmp[0]; + nulldisp_vinfo[2].height = tmp[1]; + nulldisp_vinfo[2].field_height = tmp[1]; + nulldisp_vinfo[2].sync_duration_num = tmp[2]; + nulldisp_vinfo[2].sync_duration_den = tmp[3]; + sync_duration = (tmp[2] * 100) / tmp[3]; + VOUTPR("set dummy size: %d x %d, frame_rate: %d.%02dHz\n", + tmp[0], tmp[1], + (sync_duration / 100), (sync_duration % 100)); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode); + } else { + VOUTERR("invalid data\n"); + } + mutex_unlock(&vout_serve_mutex); + + return count; +} + static ssize_t vout_axis_show(struct class *class, struct class_attribute *attr, char *buf) { @@ -571,6 +624,7 @@ static ssize_t vout_vinfo_show(struct class *class, static struct class_attribute vout_class_attrs[] = { __ATTR(mode, 0644, vout_mode_show, vout_mode_store), + __ATTR(dummy, 0644, NULL, vout_dummy_store), __ATTR(axis, 0644, vout_axis_show, vout_axis_store), __ATTR(fr_policy, 0644, vout_fr_policy_show, vout_fr_policy_store), diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h index 96cbf12aea5f..6ef397b9a0cb 100644 --- a/include/linux/amlogic/media/vout/vinfo.h +++ b/include/linux/amlogic/media/vout/vinfo.h @@ -23,7 +23,7 @@ /* the MSB is represent vmode set by vmode_init */ #define VMODE_INIT_BIT_MASK 0x8000 #define VMODE_MODE_BIT_MASK 0xff -#define VMODE_NULL_DISP_MAX 2 +#define VMODE_NULL_DISP_MAX 3 enum vmode_e { VMODE_HDMI = 0, @@ -31,6 +31,7 @@ enum vmode_e { VMODE_LCD, VMODE_NULL, /* null mode is used as temporary witch mode state */ VMODE_INVALID, + VMODE_DUMMY_LCD, VMODE_MAX, VMODE_INIT_NULL, VMODE_MASK = 0xFF, From 5f4655e39edb87baa6b35486a1e98b6039191473 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Fri, 22 Feb 2019 17:18:35 +0800 Subject: [PATCH 0289/1060] reboot: get corrent reboot reason in system panic [1/1] PD#TV-2272 Problem: can't get corrent reboot reason in system panic Solution: get corrent reboot reason in system panic Verify: test pass on T962x2_x301 Change-Id: If0fc95c2807d89542b4ccbc8e3709be20f17b03b Signed-off-by: Hong Guo --- drivers/amlogic/reboot/reboot.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/reboot/reboot.c b/drivers/amlogic/reboot/reboot.c index 6e5cd09ad035..235d12dc4a6a 100644 --- a/drivers/amlogic/reboot/reboot.c +++ b/drivers/amlogic/reboot/reboot.c @@ -154,7 +154,21 @@ static int aml_restart_probe(struct platform_device *pdev) } ret = register_die_notifier(&panic_notifier); - return ret; + if (ret != 0) { + pr_err("%s,register die notifier failed,ret =%d!\n", + __func__, ret); + return ret; + } + + /* Register a call for panic conditions. */ + ret = atomic_notifier_chain_register(&panic_notifier_list, + &panic_notifier); + if (ret != 0) { + pr_err("%s,register panic notifier failed,ret =%d!\n", + __func__, ret); + return ret; + } + return 0; } static const struct of_device_id of_aml_restart_match[] = { From 146ea37258308acdd8047f0939fab3893b7d6e51 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Tue, 15 Jan 2019 13:37:44 +0800 Subject: [PATCH 0290/1060] amvecm: lc: add driver interface for pc tool [1/1] PD#SWPL-3300 Problem: local contrast interface for pc tool Solution: add driver interface for pc tool Verify: tl1 Change-Id: I874ebc6c234f1030fa64a48033580af644550048 Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 171 +++++++++++++++++- .../media/enhancement/amvecm/local_contrast.c | 18 +- .../media/enhancement/amvecm/local_contrast.h | 8 + 3 files changed, 181 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 7df8181c58c6..8fcf0fcdc4b0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5387,9 +5387,14 @@ static ssize_t amvecm_get_hdr_type_store(struct class *cls, return count; } -static void lc_rd_reg(enum lc_reg_lut_e reg_sel) +static void lc_rd_reg(enum lc_reg_lut_e reg_sel, int data_type) { int i, tmp, tmp1, tmp2; + int lut_data[63] = {0}; + char *stemp = NULL; + + if (data_type == 1) + goto dump_as_string; switch (reg_sel) { case SATUR_LUT: @@ -5460,6 +5465,70 @@ static void lc_rd_reg(enum lc_reg_lut_e reg_sel) default: break; } + return; + +dump_as_string: + stemp = kzalloc(300, GFP_KERNEL); + if (!stemp) + return; + switch (reg_sel) { + case SATUR_LUT: + for (i = 0; i < 31 ; i++) { + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i); + tmp1 = (tmp >> 16) & 0xfff; + tmp2 = tmp & 0xfff; + lut_data[2*i] = tmp1; + lut_data[2*i + 1] = tmp2; + } + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_62); + lut_data[62] = tmp & 0xfff; + for (i = 0; i < 63 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + case YMINVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + lut_data[2*i] = tmp1; + lut_data[2*i + 1] = tmp2; + } + for (i = 0; i < 12 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + case YPKBV_YMAXVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + lut_data[2*i] = tmp1; + lut_data[2*i + 1] = tmp2; + } + for (i = 0; i < 12 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + case YPKBV_RAT: + tmp = READ_VPP_REG(LC_CURVE_YPKBV_RAT); + lut_data[0] = (tmp>>24) & 0xff; + lut_data[1] = (tmp>>16) & 0xff; + lut_data[2] = (tmp>>8) & 0xff; + lut_data[3] = tmp & 0xff; + for (i = 0; i < 4 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + default: + break; + } + kfree(stemp); + return; } static void lc_wr_reg(int *p, enum lc_reg_lut_e reg_sel) @@ -5563,10 +5632,16 @@ static ssize_t amvecm_lc_store(struct class *cls, char *buf_orig, *parm[8] = {NULL}; int reg_lut[63] = {0}; enum lc_reg_lut_e reg_sel; + int h, v, i, start_point; long val = 0; + char *stemp = NULL; + int curve_val[6] = {0}; if (!buf) return count; + stemp = kzalloc(100, GFP_KERNEL); + if (!stemp) + return 0; buf_orig = kstrdup(buf, GFP_KERNEL); parse_param_amvecm(buf_orig, (char **)&parm); @@ -5578,6 +5653,8 @@ static ssize_t amvecm_lc_store(struct class *cls, lc_en = 0; else pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "lc_version")) { + pr_info("lc driver version : %s\n", LC_VER); } else if (!strcmp(parm[0], "lc_dbg")) { if (kstrtoul(parm[1], 16, &val) < 0) goto free_buf; @@ -5589,25 +5666,39 @@ static ssize_t amvecm_lc_store(struct class *cls, lc_demo_mode = 0; else pr_info("unsupprt cmd!\n"); - } else if (!strcmp(parm[0], "lc_dump_reg")) { + } else if (!strcmp(parm[0], "dump_lut_data")) { if (kstrtoul(parm[1], 16, &val) < 0) goto free_buf; reg_sel = val; if (reg_sel == SATUR_LUT) - lc_rd_reg(SATUR_LUT); + lc_rd_reg(SATUR_LUT, 0); else if (reg_sel == YMINVAL_LMT) - lc_rd_reg(YMINVAL_LMT); + lc_rd_reg(YMINVAL_LMT, 0); else if (reg_sel == YPKBV_YMAXVAL_LMT) - lc_rd_reg(YPKBV_YMAXVAL_LMT); + lc_rd_reg(YPKBV_YMAXVAL_LMT, 0); else if (reg_sel == YPKBV_RAT) - lc_rd_reg(YPKBV_RAT); + lc_rd_reg(YPKBV_RAT, 0); else if (reg_sel == YPKBV_SLP_LMT) - lc_rd_reg(YPKBV_SLP_LMT); + lc_rd_reg(YPKBV_SLP_LMT, 0); else if (reg_sel == CNTST_LMT) - lc_rd_reg(CNTST_LMT); + lc_rd_reg(CNTST_LMT, 0); else pr_info("unsupprt cmd!\n"); - } else if (!strcmp(parm[0], "lc_wr_reg")) { + } else if (!strcmp(parm[0], "dump_lut_str")) { + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; + reg_sel = val; + if (reg_sel == SATUR_LUT) + lc_rd_reg(SATUR_LUT, 1); + else if (reg_sel == YMINVAL_LMT) + lc_rd_reg(YMINVAL_LMT, 1); + else if (reg_sel == YPKBV_YMAXVAL_LMT) + lc_rd_reg(YPKBV_YMAXVAL_LMT, 1); + else if (reg_sel == YPKBV_RAT) + lc_rd_reg(YPKBV_RAT, 1); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "lc_wr_lut")) { if (kstrtoul(parm[1], 16, &val) < 0) goto free_buf; reg_sel = val; @@ -5729,15 +5820,75 @@ static ssize_t amvecm_lc_store(struct class *cls, goto free_buf; amlc_iir_debug_en = val; pr_info("setting value: %d\n", amlc_iir_debug_en); - } else + } else if (!strcmp(parm[0], "get_blk_region")) { + val = READ_VPP_REG(LC_CURVE_HV_NUM); + h = (val >> 8) & 0x1f; + v = (val) & 0x1f; + if (!strcmp(parm[1], "htotal")) + pr_info("%d\n", h); + else if (!strcmp(parm[1], "vtotal")) + pr_info("%d\n", v); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "get_hist")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + h = val; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + v = val; + if ((h > 11) || (v > 7)) + goto free_buf; + start_point = (12*v+h)*17; + for (i = 0; i < 17; i++) + d_convert_str(lc_hist[start_point + i] >> 4, + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else if (!strcmp(parm[0], "get_curve")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + h = val; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + v = val; + if ((h > 11) || (v > 7)) + goto free_buf; + start_point = (12*v+h)*6; + for (i = 0; i < 6; i++) + d_convert_str(curve_nodes_cur[start_point + i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else if (!strcmp(parm[0], "set_curve")) { + if (parm[3] == NULL) + goto free_buf; + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + h = val; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + v = val; + if ((h > 11) || (v > 7)) + goto free_buf; + start_point = (12*v+h)*6; + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 6; i++) + curve_nodes_cur[start_point + i] + = curve_val[i]; + } else if (!strcmp(parm[0], "stop_refresh")) + lc_curve_fresh = false; + else if (!strcmp(parm[0], "refresh_curve")) + lc_curve_fresh = true; + else pr_info("unsupprt cmd!\n"); kfree(buf_orig); + kfree(stemp); return count; free_buf: pr_info("Missing parameters !\n"); kfree(buf_orig); + kfree(stemp); return -EINVAL; } diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index aadeaf023b22..f8167ac0b120 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -66,14 +66,15 @@ unsigned int lc_hist_ve; unsigned int lc_hist_hs; unsigned int lc_hist_he; /*lc curve data and hist data*/ -static int *lc_szcurve;/*12*8*6+4*/ -static int *curve_nodes_cur; +int *lc_szcurve;/*12*8*6+4*/ +int *curve_nodes_cur; static int *curve_nodes_pre; -static int *lc_hist;/*12*8*17*/ +int *lc_hist;/*12*8*17*/ static bool lc_malloc_ok; /*print one or more frame data*/ unsigned int lc_hist_prcnt; unsigned int lc_curve_prcnt; +bool lc_curve_fresh = true; /*lc saturation gain, low parameters*/ static unsigned int lc_satur_gain[63] = { @@ -1008,10 +1009,11 @@ static void lc_fw_curve_iir(struct vframe_s *vf, if (!vf) return; + if (!lc_curve_fresh) + goto stop_curvefresh; /* pre: get curve nodes from szCurveInfo and save to curve_nodes_cur*/ for (i = 0; i < 580; i++)/*12*8*6+4*/ curve_nodes_cur[i] = lc_szcurve[i]; - /* pre: osd flag delay*/ osd_flag_cnt_below[0] = osd_flag_cnt_below[1]; osd_flag_cnt_above[0] = osd_flag_cnt_above[1]; @@ -1062,7 +1064,11 @@ static void lc_fw_curve_iir(struct vframe_s *vf, frm_cnt_above--; if (frm_cnt_above < 0) frm_cnt_above = 0; + return; +stop_curvefresh: + for (i = 0; i < 580; i++) + lc_szcurve[i] = curve_nodes_cur[i];/*output*/ } static void lc_read_region(int blk_vnum, int blk_hnum) @@ -1171,7 +1177,7 @@ void lc_init(void) /*default LC low parameters*/ WRITE_VPP_REG(LC_CURVE_CONTRAST_LH, 0x000b000b); - WRITE_VPP_REG(LC_CURVE_CONTRAST_SCL_LH, 0x000b000b); + WRITE_VPP_REG(LC_CURVE_CONTRAST_SCL_LH, 0x00000b0b); WRITE_VPP_REG(LC_CURVE_MISC0, 0x00023028); WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, 0x3e69443c); WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, 0x00000b33); @@ -1226,6 +1232,7 @@ void lc_process(struct vframe_s *vf, lc_config(lc_en, vf, sps_h_en, sps_v_en); /*get each block curve*/ read_lc_curve(blk_vnum, blk_hnum); + lc_read_region(blk_vnum, blk_hnum); /*do time domain iir*/ lc_fw_curve_iir(vf, lc_hist, lc_szcurve, blk_vnum, blk_hnum); @@ -1233,7 +1240,6 @@ void lc_process(struct vframe_s *vf, lc_prt_curve(); lc_curve_prcnt--; } - lc_read_region(blk_vnum, blk_hnum); if (set_lc_curve(0, 1)) pr_amlc_dbg("%s: set lc curve fail", __func__); diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index 8564b0442a0a..d9d7a22dba1b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -21,6 +21,9 @@ #include +/*V1.0: Local_contrast Basic function, iir algorithm, debug interface for tool*/ +#define LC_VER "Ref.2019/02/27-V1.0" + enum lc_mtx_sel_e { INP_MTX = 0x1, OUTP_MTX = 0x2, @@ -70,6 +73,11 @@ extern int alpha2; extern int refresh_bit; extern int ts; extern int scene_change_th; +extern bool lc_curve_fresh; +extern int *lc_szcurve;/*12*8*6+4*/ +extern int *curve_nodes_cur; +extern int *lc_hist;/*12*8*17*/ + extern void lc_init(void); extern void lc_process(struct vframe_s *vf, From 0d47835566af236520f323c1546ca789093bc90a Mon Sep 17 00:00:00 2001 From: Nan Li Date: Wed, 27 Feb 2019 14:16:44 +0800 Subject: [PATCH 0291/1060] sdio: set sdio hs mode co_phase [1/1] PD#SWPL-5206 Problem: Setup time in sdio highspeed mode of txlx is inconsistent with the protocol standard. Solution: set co_phase = 2. Verify: r321 Change-Id: I3e5a1bca335faea6397513de772d3ee35ea76d40 Signed-off-by: Nan Li --- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 0f02a26407f3..eac2a066ceb2 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -344,6 +344,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->tx_phase = para->hs2.tx_phase; } else if (timing == MMC_TIMING_SD_HS) { if (aml_card_type_non_sdio(pdata) + || (host->data->chip_type == MMC_CHIP_TXLX) || (host->data->chip_type == MMC_CHIP_G12A)) clkc->core_phase = para->sd_hs.core_phase; if (pdata->calc_f) { From bc24c327e65cb9a5b58c362cc90b1a7097090232 Mon Sep 17 00:00:00 2001 From: Zhuo Wang Date: Fri, 1 Mar 2019 14:35:34 +0800 Subject: [PATCH 0292/1060] ethernet: set RX delay for exphy and leds [1/1] PD#SWPL-5295 Problem: add RX delay for 8211f and add led setup interface Solution: tuning delay and leds Verify: verify on u200 board Change-Id: I45e855894d570fdd976f90fd8f03151ad52a3683 Signed-off-by: Zhuo Wang --- .../net/ethernet/stmicro/stmmac/dwmac-meson.c | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index d3073cdb03db..9910115d12ba 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -34,6 +34,7 @@ /* if it's internal phy we will shutdown analog*/ static unsigned int is_internal_phy; /* Ethernet register for G12A PHY */ +#define REG_ETH_REG1_OFFSET 0x4 #define ETH_PLL_CTL0 0x44 #define ETH_PLL_CTL1 0x48 #define ETH_PLL_CTL2 0x4C @@ -227,10 +228,12 @@ static void __iomem *network_interface_setup(struct platform_device *pdev) return PREG_ETH_REG0; } -static int dwmac_meson_cfg_ctrl(void __iomem *base_addr) +static int dwmac_meson_cfg_ctrl(void __iomem *base_addr, + struct platform_device *pdev) { void __iomem *ETH_PHY_config_addr = base_addr; - + unsigned int led_setting = 0; + unsigned int phy_setting = 0x54147; /*config phyid should between a 0~0xffffffff*/ /*please don't use 44000181, this has been used by internal phy*/ writel(0x33010180, ETH_PHY_config_addr + ETH_PHY_CNTL0); @@ -238,9 +241,16 @@ static int dwmac_meson_cfg_ctrl(void __iomem *base_addr) /*use_phy_smi | use_phy_ip | co_clkin from eth_phy_top*/ writel(0x260, ETH_PHY_config_addr + ETH_PHY_CNTL2); /*led signal is inverted*/ - writel(0x41054147, ETH_PHY_config_addr + ETH_PHY_CNTL1); - writel(0x41014147, ETH_PHY_config_addr + ETH_PHY_CNTL1); - writel(0x41054147, ETH_PHY_config_addr + ETH_PHY_CNTL1); + if (of_property_read_u32(pdev->dev.of_node, + "led_setting", &led_setting)) + led_setting = 0x41; + else + pr_info("load led setting as 0x%x\n", led_setting); + + phy_setting = (led_setting << 24) + (phy_setting & ~(0xff << 24)); + writel(phy_setting, ETH_PHY_config_addr + ETH_PHY_CNTL1); + writel(phy_setting & ~(0x1 << 18), ETH_PHY_config_addr + ETH_PHY_CNTL1); + writel(phy_setting, ETH_PHY_config_addr + ETH_PHY_CNTL1); /*wait phy to reset cause Power Up Reset need 5.2~2.6 ms*/ mdelay(10); return 0; @@ -294,6 +304,7 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) struct pinctrl *pin_ctl; struct resource *res = NULL; u32 mc_val; + u32 cali_val; void __iomem *addr = NULL; void __iomem *REG_ETH_reg0_addr = NULL; void __iomem *ETH_PHY_config_addr = NULL; @@ -357,7 +368,7 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) /*PLL*/ dwmac_meson_cfg_pll(ETH_PHY_config_addr, pdev); dwmac_meson_cfg_analog(ETH_PHY_config_addr, pdev); - dwmac_meson_cfg_ctrl(ETH_PHY_config_addr); + dwmac_meson_cfg_ctrl(ETH_PHY_config_addr, pdev); pin_ctl = devm_pinctrl_get_select (&pdev->dev, "internal_eth_pins"); return REG_ETH_reg0_addr; @@ -376,6 +387,13 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) /*switch to extern phy*/ writel(0x0, ETH_PHY_config_addr + ETH_PHY_CNTL2); + /*set PRG_ETH_REG1 for exphy delay*/ + if (of_property_read_u32(np, "cali_val", &cali_val)) + pr_info("Not set cali_val for REG1\n"); + else + writel(cali_val, REG_ETH_reg0_addr + + REG_ETH_REG1_OFFSET); + pin_ctl = devm_pinctrl_get_select (&pdev->dev, "external_eth_pins"); return REG_ETH_reg0_addr; From 69a7f2403a7b05da02c6973659f3949d3fbf093b Mon Sep 17 00:00:00 2001 From: Hui Zhang Date: Fri, 1 Mar 2019 09:02:26 +0800 Subject: [PATCH 0293/1060] ppmgr: use light reg for video decoder local reset [1/1] PD#SWPL-5014 Problem: ppmgr provider error sometimes in long time run under poor signal Solution: use light reg for video decoder local reset Verify: X301 Change-Id: I1500c9ddfdce76b3e9cb2b24a35cdee765f82d5f Signed-off-by: Hui Zhang --- .../media/common/vfm/vframe_provider.c | 27 +++++++++++++++++++ .../media/video_processor/ppmgr/ppmgr_vpp.c | 2 +- .../linux/amlogic/media/vfm/vframe_provider.h | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/common/vfm/vframe_provider.c b/drivers/amlogic/media/common/vfm/vframe_provider.c index e20806043cb4..af6d1bd24c70 100644 --- a/drivers/amlogic/media/common/vfm/vframe_provider.c +++ b/drivers/amlogic/media/common/vfm/vframe_provider.c @@ -367,6 +367,33 @@ void vf_unreg_provider(struct vframe_provider_s *prov) } } EXPORT_SYMBOL(vf_unreg_provider); +void vf_light_reg_provider(struct vframe_provider_s *prov) +{ + struct vframe_provider_s *p = NULL; + struct vframe_receiver_s *receiver = NULL; + int i; + + for (i = 0; i < MAX_PROVIDER_NUM; i++) { + p = provider_table[i]; + if (p && !strcmp(p->name, prov->name)) { + if (vfm_debug_flag & 1) + pr_err("%s:%s\n", __func__, prov->name); + receiver = vf_get_receiver(prov->name); + if (receiver && receiver->ops + && receiver->ops->event_cb) { + receiver->ops->event_cb( + VFRAME_EVENT_PROVIDER_REG, + (void *)prov->name, + receiver->op_arg); + } else{ + pr_err("%s Error to notify receiver\n", + __func__); + } + break; + } + } +} +EXPORT_SYMBOL(vf_light_reg_provider); void vf_light_unreg_provider(struct vframe_provider_s *prov) { diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index 664ad0bcead9..42cc0a606adc 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -3248,7 +3248,7 @@ SKIP_DETECT: vf_local_init(); vf_light_unreg_provider(&ppmgr_vf_prov); msleep(30); - vf_reg_provider(&ppmgr_vf_prov); + vf_light_reg_provider(&ppmgr_vf_prov); ppmgr_blocking = false; up(&thread_sem); PPMGRVPP_WARN("ppmgr rebuild from light-unregister\n"); diff --git a/include/linux/amlogic/media/vfm/vframe_provider.h b/include/linux/amlogic/media/vfm/vframe_provider.h index 157359a5a021..014f16373fcc 100644 --- a/include/linux/amlogic/media/vfm/vframe_provider.h +++ b/include/linux/amlogic/media/vfm/vframe_provider.h @@ -92,6 +92,7 @@ extern int vf_notify_provider(const char *receiver_name, int event_type, extern int vf_notify_provider_by_name(const char *provider_name, int event_type, void *data); +void vf_light_reg_provider(struct vframe_provider_s *prov); void vf_light_unreg_provider(struct vframe_provider_s *prov); void vf_ext_light_unreg_provider(struct vframe_provider_s *prov); struct vframe_provider_s *vf_get_provider(const char *name); From d7b073f67c164bb0bb3b9e2530c9444daae0da3f Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 26 Feb 2019 18:51:50 +0800 Subject: [PATCH 0294/1060] osd: add afbc source crop support [2/2] PD#OTT-2168 Problem: media control bar can't displayed because afbc source crop not support Solution: add afbc source crop support Verify: verify on raven Change-Id: Ib1f925aeea12ba18d8f976aba8c84f0738c41293 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd.h | 2 ++ drivers/amlogic/media/osd/osd_hw.c | 5 ++++- drivers/amlogic/media/osd/osd_sync.h | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index cc2e8fbe7cfc..bead47117592 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -450,6 +450,8 @@ struct layer_fence_map_s { u32 ext_addr; u32 format; u32 compose_type; + u32 fb_width; + u32 fb_height; u32 src_x; u32 src_y; u32 src_w; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index fb85cff64e78..bd4caefdc64b 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1059,6 +1059,8 @@ static int sync_render_layers_fence(u32 index, u32 yres, fence_map->layer_map[index].ext_addr = phys_addr; fence_map->layer_map[index].format = request->format; fence_map->layer_map[index].compose_type = request->type; + fence_map->layer_map[index].fb_width = request->fb_width; + fence_map->layer_map[index].fb_height = request->fb_height; fence_map->layer_map[index].src_x = request->xoffset; fence_map->layer_map[index].src_y = request->yoffset; fence_map->layer_map[index].src_w = request->width; @@ -4209,7 +4211,8 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) layer_map->byte_stride / 4; //BYTE_32_ALIGNED(layer_map->src_w); osd_hw.osd_afbcd[index].frame_height = - BYTE_8_ALIGNED(layer_map->src_h); + BYTE_8_ALIGNED(layer_map->fb_height); + /*BYTE_8_ALIGNED(layer_map->src_h);*/ osd_hw.screen_base[index] = ext_addr; osd_hw.screen_size[index] = layer_map->afbc_len; diff --git a/drivers/amlogic/media/osd/osd_sync.h b/drivers/amlogic/media/osd/osd_sync.h index 77f754ca68c5..dd8c085bebc1 100644 --- a/drivers/amlogic/media/osd/osd_sync.h +++ b/drivers/amlogic/media/osd/osd_sync.h @@ -88,6 +88,8 @@ struct sync_req_render_s { unsigned char plane_alpha; unsigned char dim_layer; unsigned int dim_color; + int fb_width; + int fb_height; int reserve; }; From 1bf8857cb83271c08ecf1900cbf218780e2f2012 Mon Sep 17 00:00:00 2001 From: Guosong Zhou Date: Fri, 18 Jan 2019 08:30:02 -0500 Subject: [PATCH 0295/1060] amlvideo2: add port_type for TL1 [1/1] PD#SWPL-4080 Problem: tl1 video only port_type changed Solution: add port_type for tl1 Verify: verify by tl1 Change-Id: I73e656703509a507d24f5febe26ab425cf69b61b Signed-off-by: Guosong Zhou --- .../video_processor/video_dev/amlvideo2.c | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 9ce0cbb65b89..288d47948bec 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -961,7 +961,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1323,7 +1324,8 @@ struct amlvideo2_node *node) if (src_width < src_height) cur_angle = (cur_angle + 90) % 360; if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1700,7 +1702,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -2102,7 +2105,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -2502,7 +2506,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -3110,7 +3115,8 @@ int amlvideo2_ge2d_pre_process(struct vframe_s *vf, } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -4787,10 +4793,11 @@ static int amlvideo2_start_tvin_service(struct amlvideo2_node *node) para.dest_vactive = dst_h; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; - if (para.port == TVIN_PORT_VIU1_VIDEO) { - para.dest_hactive = 0; - para.dest_vactive = 0; - } + + if ((para.port == TVIN_PORT_VIU1_VIDEO) || + (para.port == TVIN_PORT_VIU1_WB0_VD1)) + para.cfmt = 1; + if (amlvideo2_dbg_en) { pr_info("node->r_type=%d, node->p_type=%d\n", node->r_type, node->p_type); @@ -5055,14 +5062,13 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) para.dest_vactive = dst_h; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; - if (para.port == TVIN_PORT_VIU1_VIDEO) { + if ((para.port == TVIN_PORT_VIU1_VIDEO) || + (para.port == TVIN_PORT_VIU1_WB0_VD1)) { if (node->ge2d_multi_process_flag) { para.dest_hactive = 384; para.dest_vactive = 216; - } else { - para.dest_hactive = 0; - para.dest_vactive = 0; - } + } else + para.cfmt = 1; } if (amlvideo2_dbg_en) { pr_info("para.h_active: %d, para.v_active: %d,", From efe8d24a06bcd6acbed26cf34a504883637f15d8 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Wed, 27 Feb 2019 19:31:40 +0800 Subject: [PATCH 0296/1060] vbi: add vbi debug print control [1/1] PD#SWPL-5217 Problem: vbi debug print too much Solution: add vbi debug print control Verify: verified by X301 Change-Id: If8848adb077aced68aac6b5443532037ee8dfff3 Signed-off-by: Nian Jing --- .../amlogic/media/vin/tvin/tvafe/tvafe_vbi.c | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c index 2857d8ecf1d3..ee3257828357 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c @@ -87,6 +87,7 @@ module_param(vbi_wakeup_interval, uint, 0664); static unsigned int vcnt = 1; static unsigned int wakeup_cnt; static unsigned int init_cc_data_flag; +static bool vbi_pr_en; static void vbi_hw_reset(struct vbi_dev_s *devp) { @@ -501,7 +502,8 @@ static void force_set_vcnt(unsigned char *rptr) l_val = *rptr & 0xff; h_val = *(rptr+1) & 0xff; vcnt = (h_val << 8) | l_val; - tvafe_pr_info("force set vcnt:0x%x\n", vcnt); + if (vbi_pr_en) + tvafe_pr_info("force set vcnt:0x%x\n", vcnt); } static void set_vbi_new_vcnt(struct vbi_dev_s *devp, unsigned char *rptr) @@ -539,7 +541,8 @@ static void set_vbi_new_vcnt(struct vbi_dev_s *devp, unsigned char *rptr) } vcnt = (h_val << 8) | l_val; - tvafe_pr_info("pre vcnt=0x%x, current vcnt=0x%x\n", temp, vcnt); + if (vbi_pr_en) + tvafe_pr_info("pre vcnt=0x%x, current vcnt=0x%x\n", temp, vcnt); if (vcnt > 0xffff) vcnt = temp; } @@ -559,8 +562,8 @@ static unsigned char *search_vbi_new_addr(struct vbi_dev_s *devp) vaddr = devp->pac_addr_start + paddr - devp->mem_start; temp = (unsigned long)vaddr; vaddr = (unsigned char *)((temp >> 4) << 4); - - tvafe_pr_info("vbi search new addr\n"); + if (vbi_pr_en) + tvafe_pr_info("vbi search new addr\n"); return vaddr; } @@ -599,10 +602,12 @@ static int check_if_sync_cc_data(struct vbi_dev_s *devp, unsigned char *addr) field_data_flag = 0; set_vbi_new_vcnt(devp, new_addr); } - tvafe_pr_info("not find vbi data.\n"); + if (vbi_pr_en) + tvafe_pr_info("not find vbi data.\n"); return -1; } else if (addr > devp->pac_addr_end) { - tvafe_pr_info("vbi ret_addr error.\n"); + if (vbi_pr_en) + tvafe_pr_info("vbi ret_addr error.\n"); return -1; } @@ -1418,6 +1423,12 @@ static ssize_t vbi_store(struct device *dev, vbi_buffer->pread, vbi_buffer->pwrite, vbi_buffer->data_wmode); tvafe_pr_info("dump satus done!!\n"); + } else if (!strncmp(parm[0], "vbi_pr_en", + strlen("vbi_pr_en"))) { + if (kstrtouint(parm[1], 10, &val) < 0) + return -EINVAL; + vbi_pr_en = val; + tvafe_pr_info("vbi_pr_en:%d\n", vbi_pr_en); } else if (!strncmp(parm[0], "enable_tasklet", strlen("enable_tasklet"))) { if (kstrtouint(parm[1], 10, &val) < 0) From 6d479f7caa1105efffcba13610755bd03ab162b2 Mon Sep 17 00:00:00 2001 From: Xingyu Chen Date: Tue, 26 Feb 2019 17:45:31 +0800 Subject: [PATCH 0297/1060] saradc: saradc register initialization is incomplete [1/1] PD#SWPL-4975 Problem: some basic saradc registers are only initialized at bl2 stage, the ADC value is abnormal when bl2 disable saradc init. Solution: to re-initialize the basic saradc registers in kernel. Verify: test pass on w400 and p212 Change-Id: Ie98e8789fd47cc43cafcb49d9862ccccbe1d9b66 Signed-off-by: Xingyu Chen --- drivers/amlogic/iio/adc/meson_saradc.c | 120 +++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index dc58464eb710..a32565d97f0f 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -110,8 +110,8 @@ #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) #define MESON_SAR_ADC_AUX_SW 0x1c - #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan) \ - (GENMASK(10, 8) << (((_chan) - 2) * 2)) + #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ + (8 + (((_chan) - 2) * 3)) #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) @@ -174,6 +174,9 @@ */ #define MESON_SAR_ADC_REG11 0x2c #define MESON_SAR_ADC_REG11_VREF_SEL BIT(0) + #define MESON_SAR_ADC_REG11_EOC BIT(1) + #define MESON_SAR_ADC_REG11_VREF_EN BIT(5) + #define MESON_SAR_ADC_REG11_CMV_SEL BIT(6) #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) #define MESON_SAR_ADC_REG11_CHNL_REGS_EN BIT(30) #define MESON_SAR_ADC_REG11_FIFO_EN BIT(31) @@ -305,9 +308,15 @@ enum vref_select { * * @reg3_ring_counter_disable: to disable continuous ring counter. * gxl and later: 1; others(gxtvbb etc): 0 + * @reg11_vref_en: g12a and later: 0; others(gxl etc): 1 + * @reg11_cmv_sel: g12a and later: 0; others(gxl etc): 1 + * @reg11_eoc: g12a and later: 1; others(gxl etc): 0 */ struct meson_sar_adc_reg_diff { bool reg3_ring_counter_disable; + bool reg11_vref_en; + bool reg11_cmv_sel; + bool reg11_eoc; }; /* @@ -330,6 +339,7 @@ struct meson_sar_adc_data { bool has_chnl_regs; unsigned int resolution; const char *name; + const struct regmap_config *regmap_config; struct meson_sar_adc_reg_diff regs_diff; }; @@ -351,13 +361,27 @@ struct meson_sar_adc_priv { u8 *datum_buf; }; -static const struct regmap_config meson_sar_adc_regmap_config = { +static const struct regmap_config meson_sar_adc_regmap_config_g12a = { .reg_bits = 8, .val_bits = 32, .reg_stride = 4, .max_register = MESON_SAR_ADC_CHNL67, }; +static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_SAR_ADC_REG13, +}; + +static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_SAR_ADC_DELTA_10, +}; + static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); @@ -529,7 +553,7 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); /* map channel index 0 to the channel which we want to read */ - regval = chan->channel << MESON_SAR_ADC_CHAN_LIST_ENTRY_SHIFT(idx), + regval = chan->channel << MESON_SAR_ADC_CHAN_LIST_ENTRY_SHIFT(idx); regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(idx), regval); @@ -835,6 +859,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); int regval, ret; + int i; /* * make sure we start at CH7 input since the other muxes are only used @@ -895,6 +920,55 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, priv->data->regs_diff.reg3_ring_counter_disable)); + + /* + * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW + * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) + */ + regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, + regval); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW); + + regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, + regval); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW); + /* + * set up the input channel muxes in MESON_SAR_ADC_AUX_SW + * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable + * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and + * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. + */ + regval = 0; + for (i = 2; i <= 7; i++) + regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); + regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; + regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; + regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); + + /* must be set to <1> for g12a and later SoCs */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_EOC, + FIELD_PREP(MESON_SAR_ADC_REG11_EOC, + priv->data->regs_diff.reg11_eoc)); + /* select the vref */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_VREF_SEL, @@ -922,9 +996,20 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) return ret; } + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_VREF_EN, + FIELD_PREP(MESON_SAR_ADC_REG11_VREF_EN, + priv->data->regs_diff.reg11_vref_en)); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_CMV_SEL, + FIELD_PREP(MESON_SAR_ADC_REG11_CMV_SEL, + priv->data->regs_diff.reg11_cmv_sel)); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_BANDGAP_EN, MESON_SAR_ADC_REG11_BANDGAP_EN); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, MESON_SAR_ADC_REG3_ADC_EN, MESON_SAR_ADC_REG3_ADC_EN); @@ -1302,8 +1387,12 @@ struct meson_sar_adc_data meson_sar_adc_g12a_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-g12a-saradc", + .regmap_config = &meson_sar_adc_regmap_config_g12a, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_LOW, + .reg11_cmv_sel = BIT_LOW, + .reg11_eoc = BIT_HIGH, }, }; @@ -1313,8 +1402,12 @@ struct meson_sar_adc_data meson_sar_adc_txlx_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-txlx-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1324,8 +1417,12 @@ struct meson_sar_adc_data meson_sar_adc_axg_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-axg-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1335,8 +1432,12 @@ struct meson_sar_adc_data meson_sar_adc_txl_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-txl-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1346,8 +1447,12 @@ struct meson_sar_adc_data meson_sar_adc_gxl_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-gxl-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1357,8 +1462,12 @@ struct meson_sar_adc_data meson_sar_adc_gxm_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-gxm-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1368,6 +1477,7 @@ struct meson_sar_adc_data meson_sar_adc_m8b_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_10BIT, .name = "meson-m8b-saradc", + .regmap_config = &meson_sar_adc_regmap_config_meson8, .regs_diff = { .reg3_ring_counter_disable = BIT_LOW, }, @@ -1443,7 +1553,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return -EINVAL; priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &meson_sar_adc_regmap_config); + priv->data->regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); From 40baea039cb15af025700ad5b1c676fd4626a73a Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Wed, 6 Mar 2019 15:55:43 +0800 Subject: [PATCH 0298/1060] dtv_demod: TL1 dtmb suspend hangup issue [1/1] PD#SWPL-5202 Problem: cma memory is not released when suspend Solution: provide suspend interface to release cma memory Verify: verified by t962x2_x301 Change-Id: I1d808a8a6119a2f385961c4c5bded5ab71c9c9d1 Signed-off-by: zhiwei.yuan --- drivers/amlogic/media/dtv_demod/amlfrontend.c | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 780c4fdedef8..9abd3b30c337 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -3480,6 +3480,25 @@ static void aml_dtvdemod_shutdown(struct platform_device *pdev) } +static int aml_dtvdemod_suspend(struct platform_device *pdev, + pm_message_t state) +{ + enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode; + + PR_INFO("%s, mode = %d\n", __func__, nmode); + + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); + + return 0; +} + +static int aml_dtvdemod_resume(struct platform_device *pdev) +{ + PR_INFO("%s is called\n", __func__); + return 0; +} + static struct platform_driver aml_dtvdemod_driver = { .driver = { .name = "aml_dtv_demod", @@ -3490,6 +3509,10 @@ static struct platform_driver aml_dtvdemod_driver = { .shutdown = aml_dtvdemod_shutdown, .probe = aml_dtvdemod_probe, .remove = __exit_p(aml_dtvdemod_remove), +#ifdef CONFIG_PM + .suspend = aml_dtvdemod_suspend, + .resume = aml_dtvdemod_resume, +#endif }; From e3319342ebe61510c7099fceba442620dbe5ef7e Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Thu, 14 Feb 2019 19:11:36 +0800 Subject: [PATCH 0299/1060] dtv_demod: TXL DTMB losing lock sometimes when playing [1/1] PD#SWPL-4854 Problem: TXL DTMB has losing lock issue Solution: set HHI_DEMOD_CLK_CNTL to 0x301 for TXL Verify: verified by t962_p321 Change-Id: I51b61949b5f9c96b64eae7e0054771ce44dbfd5b Signed-off-by: zhiwei.yuan --- .../media/vin/tvin/tvafe/tvafe_general.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index 0f2cf0d76ec8..cec12d86767c 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -802,7 +802,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) W_HIU_REG(0xf3, 0x00800000); //HHI_AUDPLL_CLK_OUT_CNTL - W_HIU_REG(0x74, 0x501); + W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x501); } else if (tvafe_cpu_type() == CPU_TYPE_TXL || tvafe_cpu_type() == CPU_TYPE_TXLX || @@ -850,7 +850,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) tvafe_pr_info("\n%s: on:%d,module:0x%x,flag:0x%x...\n", __func__, on, module_sel, adc_pll_chg); break; - case ADC_EN_DTV_DEMODPLL: /* dtv demod default*/ + case ADC_EN_DTV_DEMODPLL: /* dtv demod */ if (adc_pll_chg & (ADC_EN_ATV_DEMOD | ADC_EN_TVAFE)) { ret = -4; @@ -873,10 +873,17 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) /*reset*/ W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xca6a2110); W_HIU_REG(HHI_ADC_PLL_CNTL, pDpara->adcpllctl); - if (pDpara->atsc) + if (pDpara->atsc) { W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x507); - else - W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x502); + } else { + /*bugzilla 139044*/ + if (tvafe_cpu_type() == CPU_TYPE_TXL) + W_HIU_REG(HHI_DEMOD_CLK_CNTL, + 0x301); + else + W_HIU_REG(HHI_DEMOD_CLK_CNTL, + 0x502); + } W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); From e9a4e2e44cb03c76fc69dbc07a8bdcdea1b34454 Mon Sep 17 00:00:00 2001 From: Blance Tang Date: Thu, 7 Mar 2019 10:13:41 +0800 Subject: [PATCH 0300/1060] IPC: Disable ad82584f in W411 DTS [1/1] PD#SWPL-5574 Problem: amixer return error due to ad82584f not exist in W411 platform Solution: Disable ad82584f, and remove it from TDM output list Verify: Yes Change-Id: I7fcd5ad31ba57887399c45d67b130e8c3d08e671 Signed-off-by: Blance Tang --- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index fc170d5f074e..bbb0db177569 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -623,7 +623,7 @@ }; tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec - &amlogic_codec &ad82584f_62>; + &amlogic_codec &dummy_codec>; }; }; @@ -916,7 +916,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio GPIOA_5 0>; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index b72068d9ee14..7493fd90e079 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -625,7 +625,7 @@ }; tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec - &amlogic_codec &ad82584f_62>; + &amlogic_codec &dummy_codec>; }; }; @@ -885,7 +885,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio GPIOA_5 0>; }; From 8c4777711c3112971eda3d82666a5e8c4f755915 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Wed, 27 Feb 2019 19:53:49 +0800 Subject: [PATCH 0301/1060] amvecm: Local Contrast ioctrl load interface support [1/4] PD#SWPL-3301 Problem: Local Contrast ioctrl load interface support Solution: add Local Contrast ioctrl load interface Verify: tl1 Change-Id: I1c2ed1f54a1fe85b589f95fe9e49f8c469f3e80d Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amve.c | 14 +++++ .../amlogic/media/enhancement/amvecm/amve.h | 2 + .../amlogic/media/enhancement/amvecm/amvecm.c | 52 ++++++++++++++++++- .../media/enhancement/amvecm/local_contrast.c | 3 ++ .../media/enhancement/amvecm/local_contrast.h | 15 +++++- include/linux/amlogic/media/amvecm/amvecm.h | 8 ++- include/linux/amlogic/media/amvecm/ve.h | 18 +++++++ 7 files changed, 107 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index e87b26a6f059..6bc63d664cf1 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -36,6 +36,7 @@ #include "amve_gamma_table.h" #include #include "dnlp_cal.h" +#include "local_contrast.h" #define pr_amve_dbg(fmt, args...)\ do {\ @@ -766,6 +767,14 @@ void ve_dnlp_latch_process(void) } } +void ve_lc_latch_process(void) +{ + if (vecm_latch_flag & FLAG_VE_LC_CURV) { + vecm_latch_flag &= ~FLAG_VE_LC_CURV; + lc_load_curve(&lc_curve_parm_load); + } +} + void ve_lcd_gamma_process(void) { if (vecm_latch_flag & FLAG_GAMMA_TABLE_EN) { @@ -868,6 +877,11 @@ void ve_new_dnlp_param_update(void) vecm_latch_flag |= FLAG_VE_NEW_DNLP; } +void ve_lc_curve_update(void) +{ + vecm_latch_flag |= FLAG_VE_LC_CURV; +} + static void video_data_limitation(int *val) { if (*val > 1023) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index d90c1e059d68..6963dfe5473c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -110,6 +110,8 @@ extern void ve_lcd_gamma_process(void); extern void lvds_freq_process(void); extern void ve_dnlp_param_update(void); extern void ve_new_dnlp_param_update(void); +extern void ve_lc_curve_update(void); +extern void ve_lc_latch_process(void); extern void ve_ogo_param_update(void); extern void am_set_regmap(struct am_regs_s *p); extern void sharpness_process(struct vframe_s *vf); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 8fcf0fcdc4b0..e93029b5fd4e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -1028,7 +1028,8 @@ void amvecm_video_latch(void) } /* #endif */ pq_user_latch_process(); - + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + ve_lc_latch_process(); } int amvecm_on_vs( @@ -1645,6 +1646,17 @@ static long amvecm_ioctl(struct file *file, ret = amvecm_set_contrast2(vdj_mode_s.contrast2); } break; + case AMVECM_IOC_S_LC_CURVE: + if (copy_from_user(&lc_curve_parm_load, + (void __user *)arg, + sizeof(struct ve_lc_curve_parm_s))) { + pr_amvecm_dbg("lc load curve parm fail\n"); + ret = -EFAULT; + } else { + ve_lc_curve_update(); + pr_amvecm_dbg("lc load curve parm success\n"); + } + break; default: ret = -EINVAL; break; @@ -5581,6 +5593,44 @@ static void lc_wr_reg(int *p, enum lc_reg_lut_e reg_sel) } } +unsigned int lc_saturation_curv[63]; +unsigned int lc_yminval_lmt_curv[12]; +unsigned int lc_ypkbv_ymaxval_lmt_curv[12]; +unsigned int lc_ypkbv_ratio_curv[4]; + +void lc_load_curve(struct ve_lc_curve_parm_s *p) +{ + unsigned int i; + + /*load lc parms*/ + lc_alg_parm.dbg_parm0 = p->param[lc_dbg_parm0]; + lc_alg_parm.dbg_parm1 = p->param[lc_dbg_parm1]; + lc_alg_parm.dbg_parm2 = p->param[lc_dbg_parm2]; + lc_alg_parm.dbg_parm3 = p->param[lc_dbg_parm3]; + lc_alg_parm.dbg_parm4 = p->param[lc_dbg_parm4]; + + /*load lc curve*/ + for (i = 0; i < 63; i++) + lc_saturation_curv[i] = p->ve_lc_saturation[i]; + for (i = 0; i < 12; i++) { + lc_yminval_lmt_curv[i] = + p->ve_lc_yminval_lmt[i]; + lc_ypkbv_ymaxval_lmt_curv[i] = + p->ve_lc_ypkbv_ymaxval_lmt[i]; + } + for (i = 0; i < 4; i++) + lc_ypkbv_ratio_curv[i] = p->ve_lc_ypkbv_ratio[i]; + + /*load lc_staturation curve*/ + lc_wr_reg(lc_saturation_curv, 0x1); + /*load lc_yminval_lmt*/ + lc_wr_reg(lc_yminval_lmt_curv, 0x2); + /*load lc_ypkbv_ymaxval_lmt*/ + lc_wr_reg(lc_ypkbv_ymaxval_lmt_curv, 0x4); + /*load lc_ypkbV_ratio*/ + lc_wr_reg(lc_ypkbv_ratio_curv, 0x8); +} + static ssize_t amvecm_lc_show(struct class *cla, struct class_attribute *attr, char *buf) { diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index f8167ac0b120..cb792d8d429f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -76,6 +76,9 @@ unsigned int lc_hist_prcnt; unsigned int lc_curve_prcnt; bool lc_curve_fresh = true; +struct ve_lc_curve_parm_s lc_curve_parm_load; +struct lc_alg_param_s lc_alg_parm; + /*lc saturation gain, low parameters*/ static unsigned int lc_satur_gain[63] = { 51, 104, 158, 213, 269, 325, 382, 440, 498, diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index d9d7a22dba1b..9a27ace75af3 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -22,7 +22,8 @@ #include /*V1.0: Local_contrast Basic function, iir algorithm, debug interface for tool*/ -#define LC_VER "Ref.2019/02/27-V1.0" +/*V1.1: add ioctrl load interface supprt*/ +#define LC_VER "Ref.2019/03/07-V1.1" enum lc_mtx_sel_e { INP_MTX = 0x1, @@ -48,6 +49,15 @@ enum lc_reg_lut_e { MAX_REG_LUT }; +struct lc_alg_param_s { + unsigned int dbg_parm0; + unsigned int dbg_parm1; + unsigned int dbg_parm2; + unsigned int dbg_parm3; + unsigned int dbg_parm4; +}; + + extern int amlc_debug; extern int lc_en; extern int lc_demo_mode; @@ -77,7 +87,8 @@ extern bool lc_curve_fresh; extern int *lc_szcurve;/*12*8*6+4*/ extern int *curve_nodes_cur; extern int *lc_hist;/*12*8*17*/ - +extern struct ve_lc_curve_parm_s lc_curve_parm_load; +extern struct lc_alg_param_s lc_alg_parm; extern void lc_init(void); extern void lc_process(struct vframe_s *vf, diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index ec6cd649c98e..bcae14831f45 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -32,7 +32,7 @@ #define FLAG_VADJ1_COLOR (1 << 30) #define FLAG_VE_DNLP (1 << 29) #define FLAG_VE_NEW_DNLP (1 << 28) -#define FLAG_RSV27 (1 << 27) +#define FLAG_VE_LC_CURV (1 << 27) #define FLAG_RSV26 (1 << 26) #define FLAG_3D_BLACK_DIS (1 << 25) #define FLAG_3D_BLACK_EN (1 << 24) @@ -214,6 +214,10 @@ enum pc_mode_e { #define AMVECM_IOC_G_PIC_MODE _IOR(_VE_CM, 0x59, struct am_vdj_mode_s) #define AMVECM_IOC_S_PIC_MODE _IOW(_VE_CM, 0x60, struct am_vdj_mode_s) +/*Local contrast command list*/ +#define AMVECM_IOC_S_LC_CURVE _IOW(_VE_CM, 0x62, struct ve_lc_curve_parm_s) + + struct am_vdj_mode_s { int flag; int brightness; @@ -422,11 +426,11 @@ struct hdr_metadata_info_s { extern void vpp_vd_adj1_saturation_hue(signed int sat_val, signed int hue_val, struct vframe_s *vf); extern void amvecm_sharpness_enable(int sel); - extern int metadata_read_u32(uint32_t *value); extern int metadata_wait(struct vframe_s *vf); extern int metadata_sync(uint32_t frame_id, uint64_t pts); extern void amvecm_wakeup_queue(void); +extern void lc_load_curve(struct ve_lc_curve_parm_s *p); #ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA #define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) diff --git a/include/linux/amlogic/media/amvecm/ve.h b/include/linux/amlogic/media/amvecm/ve.h index b891d3a6d550..11ed51009e5c 100644 --- a/include/linux/amlogic/media/amvecm/ve.h +++ b/include/linux/amlogic/media/amvecm/ve.h @@ -159,6 +159,24 @@ struct ve_dnlp_s { unsigned char gamma[64]; }; #endif + +struct ve_lc_curve_parm_s { + unsigned int ve_lc_saturation[63]; + unsigned int ve_lc_yminval_lmt[12]; + unsigned int ve_lc_ypkbv_ymaxval_lmt[12]; + unsigned int ve_lc_ypkbv_ratio[4]; + unsigned int param[100]; +}; + +enum lc_alg_param_e { + lc_dbg_parm0 = 0, + lc_dbg_parm1, + lc_dbg_parm2, + lc_dbg_parm3, + lc_dbg_parm4, + lc_dbg_parm_max, +}; + struct ve_hsvs_s { unsigned char en; unsigned char peak_gain_h1; From 90a6fefda0edb4bf1a08ef1d2fb7fd5a3feaaf67 Mon Sep 17 00:00:00 2001 From: Qianggui Song Date: Wed, 6 Mar 2019 16:41:03 +0800 Subject: [PATCH 0302/1060] ir: ir support both NEC and RC5 [1/1] PD#SWPL-5555 Problem: Current driver does not support both NEC and RC5 Solution: Add a macro to depecit both NEC and RC5 state Verify: X301 Change-Id: I06894d033eabdb22db6e34fc2ad76e0390ef565f Signed-off-by: Qianggui Song --- include/dt-bindings/input/meson_rc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/input/meson_rc.h b/include/dt-bindings/input/meson_rc.h index 9aec87f98059..82646d537023 100644 --- a/include/dt-bindings/input/meson_rc.h +++ b/include/dt-bindings/input/meson_rc.h @@ -56,6 +56,7 @@ *2. multi-format IR controller decode other protocol */ #define REMOTE_TYPE_NEC_RC6 ((REMOTE_TYPE_LEGACY_NEC << 8) | REMOTE_TYPE_RC6) +#define REMOTE_TYPE_NEC_RC5 ((REMOTE_TYPE_LEGACY_NEC << 8) | REMOTE_TYPE_RC5) #define REMOTE_TYPE_NEC_TOSHIBA ((REMOTE_TYPE_LEGACY_NEC << 8) | \ REMOTE_TYPE_TOSHIBA) From 82e23fa9ae0c0fa7f1766ebf5f5a2c416d5669dd Mon Sep 17 00:00:00 2001 From: Daogao Xu Date: Thu, 28 Feb 2019 15:01:10 +0800 Subject: [PATCH 0303/1060] i2c: add retry-process when slave NACK. [1/1] PD#SWPL-4761 Problem: When slave device is busy processing, it is unable to handle the incoming communication attempts. i2c master have to repeatedly attemp communication until the slave sends an ACK after receiving its slave address. Solution: add retry-process when slave NACK. Verify: mesonaxg_s420_32_release Change-Id: Ieb195176cac4b80e223ea6adb502ffd3bc9ef728 Signed-off-by: Daogao Xu --- drivers/amlogic/i2c/i2c-meson-master.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/i2c/i2c-meson-master.c b/drivers/amlogic/i2c/i2c-meson-master.c index 8bd7d4797ed5..b5280102d344 100644 --- a/drivers/amlogic/i2c/i2c-meson-master.c +++ b/drivers/amlogic/i2c/i2c-meson-master.c @@ -110,6 +110,7 @@ struct meson_i2c { int count; int pos; int error; + int retries; spinlock_t lock; struct completion done; @@ -324,6 +325,8 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) if (write) meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count); + + i2c->retries = 0; } static void meson_i2c_stop(struct meson_i2c *i2c) @@ -346,7 +349,6 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) spin_lock(&i2c->lock); - meson_i2c_reset_tokens(i2c); ctrl = readl(i2c->regs + REG_CTRL); dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n", @@ -360,12 +362,15 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) * condition. */ dev_dbg(i2c->dev, "error bit set\n"); - i2c->error = -ENXIO; - i2c->state = STATE_IDLE; - complete(&i2c->done); + if (++i2c->retries >= i2c->adap.retries) { + i2c->error = -ENXIO; + i2c->state = STATE_IDLE; + complete(&i2c->done); + } goto out; } + meson_i2c_reset_tokens(i2c); switch (i2c->state) { case STATE_READ: if (i2c->count > 0) { From 0f87c60f42bf3bfc4cf24b1ae3247d19d264dfb0 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Thu, 7 Mar 2019 17:35:36 +0800 Subject: [PATCH 0304/1060] vpp: support 3D with afbc format [1/1] PD#TV-3042 Problem: 3D function did not support afbc format before Solution: Add the support case which format is afbc. Verify: x301 Change-Id: I38189bfa78eec6ac811fb81631514d7d7b8b3d62 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 305 ++++++++++++++++------- drivers/amlogic/media/video_sink/vpp.c | 107 +++++--- 2 files changed, 274 insertions(+), 138 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 347c92520e55..aa06599a13e5 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -1234,6 +1234,7 @@ static inline struct vframe_s *video_vf_peek(void) static inline struct vframe_s *video_vf_get(void) { struct vframe_s *vf = NULL; + int frame_width, frame_height; vf = vf_get(RECEIVER_NAME); @@ -1244,6 +1245,13 @@ static inline struct vframe_s *video_vf_get(void) vf->disp_pts = 0; vf->disp_pts_us64 = 0; } + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; atomic_set(&vf->use_cnt, 1); /*always to 1,for first get from vfm provider */ @@ -1265,36 +1273,35 @@ static inline struct vframe_s *video_vf_get(void) } if (((process_3d_type & MODE_FORCE_3D_TO_2D_LR) || (process_3d_type & MODE_FORCE_3D_LR) - || (process_3d_type & MODE_FORCE_3D_FA_LR) - ) + || (process_3d_type & MODE_FORCE_3D_FA_LR)) && (!(vf->type & VIDTYPE_MVC)) && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { vf->trans_fmt = TVIN_TFMT_3D_DET_LR; vf->left_eye.start_x = 0; vf->left_eye.start_y = 0; - vf->left_eye.width = vf->width / 2; - vf->left_eye.height = vf->height; + vf->left_eye.width = frame_width / 2; + vf->left_eye.height = frame_height; - vf->right_eye.start_x = vf->width / 2; + vf->right_eye.start_x = frame_width / 2; vf->right_eye.start_y = 0; - vf->right_eye.width = vf->width / 2; + vf->right_eye.width = frame_width / 2; + vf->right_eye.height = frame_height; } if (((process_3d_type & MODE_FORCE_3D_TO_2D_TB) || (process_3d_type & MODE_FORCE_3D_TB) - || (process_3d_type & MODE_FORCE_3D_FA_TB) - ) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) && (!(vf->type & VIDTYPE_MVC)) && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { vf->trans_fmt = TVIN_TFMT_3D_TB; vf->left_eye.start_x = 0; vf->left_eye.start_y = 0; - vf->left_eye.width = vf->width; - vf->left_eye.height = vf->height/2; + vf->left_eye.width = frame_width; + vf->left_eye.height = frame_height/2; vf->right_eye.start_x = 0; - vf->right_eye.start_y = vf->height/2; - vf->right_eye.width = vf->width; - vf->right_eye.height = vf->height/2; + vf->right_eye.start_y = frame_height/2; + vf->right_eye.width = frame_width; + vf->right_eye.height = frame_height/2; } receive_frame_count++; #endif @@ -1730,6 +1737,7 @@ static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey; + int frame_width, frame_height; struct disp_info_s *layer = &glayer_info[0]; if (!vf) @@ -1740,18 +1748,26 @@ static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, crop_ey = layer->crop_bottom; crop_ex = layer->crop_right; + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } + switch (vpp_3d_mode) { case VPP_3D_MODE_LR: /*half width,double height */ *ls = zoom_start_x_lines; *le = zoom_end_x_lines; - *rs = *ls + (vf->width >> 1); - *re = *le + (vf->width >> 1); + *rs = *ls + (frame_width >> 1); + *re = *le + (frame_width >> 1); if (process_3d_type & MODE_3D_OUT_LR) { *ls = zoom_start_x_lines; *le = zoom_end_x_lines >> 1; - *rs = *ls + (vf->width >> 1); - *re = *le + (vf->width >> 1); + *rs = *ls + (frame_width >> 1); + *re = *le + (frame_width >> 1); } break; case VPP_3D_MODE_TB: @@ -1784,17 +1800,29 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey, height; + int frame_width, frame_height; struct disp_info_s *layer = &glayer_info[0]; + if (!vf) + return; + crop_sy = layer->crop_top; crop_sx = layer->crop_left; crop_ey = layer->crop_bottom; crop_ex = layer->crop_right; + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } + if (vf->type & VIDTYPE_INTERLACE) - height = vf->height >> 1; + height = frame_height >> 1; else - height = vf->height; + height = frame_height; switch (vpp_3d_mode) { case VPP_3D_MODE_TB: @@ -1980,17 +2008,22 @@ static void zoom_display_horz(struct vframe_s *vf, int hscale) #ifdef TV_REVERSE if (reverse) { content_w = zoom_end_x_lines - zoom_start_x_lines + 1; - content_l = (r_aligned - zoom_end_x_lines - 1) + - (zoom_start_x_lines - l_aligned); + content_l = (r_aligned - zoom_end_x_lines - 1); content_r = content_l + content_w - 1; VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, (((content_l << 16)) | content_r) / h_skip); } else #endif { - VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, - (((zoom_start_x_lines - l_aligned) << 16) | - (zoom_end_x_lines - l_aligned)) / h_skip); + if (((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_LR)) + && (cur_frame_par->vpp_3d_mode == 1)) { + /* do nothing*/ + } else { + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + (((zoom_start_x_lines - l_aligned) << 16) | + (zoom_end_x_lines - l_aligned)) / h_skip); + } } VSYNC_WR_MPEG_REG(AFBC_SIZE_IN, (VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) & 0xffff) | @@ -2122,7 +2155,7 @@ static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) static void zoom_display_vert(struct vframe_s *vf) { - u32 ls, le, rs, re; + u32 ls = 0, le = 0, rs = 0, re = 0; if (process_3d_type & MODE_3D_ENABLE) { zoom_get_vert_pos(vf, @@ -2244,10 +2277,27 @@ static void zoom_display_vert(struct vframe_s *vf) VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_H, (b_aligned - t_aligned) / c_skip / v_skip); - VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, - ((t_aligned / 4) << 16) | - ((b_aligned / 4) - 1)); + if (((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) + && (cur_frame_par->vpp_3d_mode == 2)) { + int block_h; + block_h = ori_b_aligned - ori_t_aligned; + block_h = block_h / 8; + if (toggle_3d_fa_frame == OUT_FA_B_FRAME) { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + (((ori_t_aligned / 4) + block_h) << 16) | + ((ori_b_aligned / 4) - 1)); + } else { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((ori_t_aligned / 4) << 16) | + ((ori_t_aligned / 4) + block_h - 1)); + } + } else { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((t_aligned / 4) << 16) | + ((b_aligned / 4) - 1)); + } VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE, ((zoom_start_y_lines - t_aligned) << 16) | (zoom_end_y_lines - t_aligned)); @@ -5975,6 +6025,132 @@ static int vpp_zorder_check(void) return force_flush; } +#ifdef TV_3D_FUNCTION_OPEN +inline void switch_3dView_per_vsync(void) +{ + u32 start_aligned, end_aligned, block_len; + u32 FA_enable = process_3d_type & MODE_3D_OUT_FA_MASK; + + if (FA_enable && (toggle_3d_fa_frame == OUT_FA_A_FRAME)) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + if ((process_3d_type & MODE_FORCE_3D_FA_LR) + && (cur_frame_par->vpp_3d_mode == 1)) { + start_aligned = ori_start_x_lines; + end_aligned = ori_end_x_lines + 1; + block_len = + (end_aligned - start_aligned) / 2; + block_len = block_len / + (cur_frame_par->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + (start_aligned << 16) | + (start_aligned + block_len - 1)); + } + if ((process_3d_type & MODE_FORCE_3D_FA_TB) + && (cur_frame_par->vpp_3d_mode == 2)) { + start_aligned = + round_down(ori_start_y_lines, 4); + end_aligned = + round_up(ori_end_y_lines + 1, 4); + block_len = end_aligned - start_aligned; + block_len = block_len / 8; + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((start_aligned / 4) << 16) | + ((start_aligned / 4) + block_len - 1)); + } + } + } else if (FA_enable && + (toggle_3d_fa_frame == OUT_FA_B_FRAME)) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + if ((process_3d_type & MODE_FORCE_3D_FA_LR) + && (cur_frame_par->vpp_3d_mode == 1)) { + start_aligned = ori_start_x_lines; + end_aligned = ori_end_x_lines + 1; + block_len = + (end_aligned - start_aligned) / 2; + block_len = block_len / + (cur_frame_par->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + ((start_aligned + block_len) << 16) | + (end_aligned - 1)); + } + if ((process_3d_type & MODE_FORCE_3D_FA_TB) + && (cur_frame_par->vpp_3d_mode == 2)) { + start_aligned = + round_down(ori_start_y_lines, 4); + end_aligned = + round_up(ori_end_y_lines + 1, 4); + block_len = end_aligned - start_aligned; + block_len = block_len / 8; + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + (((start_aligned / 4) + block_len) << 16) | + ((end_aligned / 4) - 1)); + } + } + } else if (FA_enable && + (toggle_3d_fa_frame == OUT_FA_BANK_FRAME)) { + /* output a banking frame */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 0, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 0, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + } + + if ((process_3d_type & MODE_3D_OUT_TB) + || (process_3d_type & MODE_3D_OUT_LR)) { + if (cur_frame_par->vpp_2pic_mode & + VPP_PIC1_FIRST) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + } + } +} +#endif + #ifdef FIQ_VSYNC void vsync_fisr_in(void) #else @@ -6832,75 +7008,10 @@ SET_FILTER: cur_dev->viu_off, 1, 20, 1); /* HFORMATTER_EN */ } - if (process_3d_type & MODE_3D_OUT_FA_MASK) { - if (toggle_3d_fa_frame == OUT_FA_A_FRAME) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - } else if (OUT_FA_B_FRAME == - toggle_3d_fa_frame) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } else if (toggle_3d_fa_frame == - OUT_FA_BANK_FRAME) { - /* output a banking frame */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 0, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 0, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - } - } - if ((process_3d_type & MODE_3D_OUT_TB) - || (process_3d_type & MODE_3D_OUT_LR)) { - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode & - VPP_PIC1_FIRST)) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - } - } + +#ifdef TV_3D_FUNCTION_OPEN + switch_3dView_per_vsync(); +#endif /* vertical phase */ vphase = &cur_frame_par->VPP_vf_ini_phase_ [vpp_phase_table[vin_type] diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 5fed63c1d5fb..e4325bceca60 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -589,6 +589,9 @@ module_param(cur_skip_ratio, uint, 0444); static unsigned int cur_vf_type; MODULE_PARM_DESC(cur_vf_type, "cur_vf_type"); module_param(cur_vf_type, uint, 0444); +static unsigned int cur_freq_ratio; +MODULE_PARM_DESC(cur_freq_ratio, "cur_freq_ratio"); +module_param(cur_freq_ratio, uint, 0444); static unsigned int custom_ar; MODULE_PARM_DESC(custom_ar, "custom_ar"); @@ -625,6 +628,8 @@ static int vpp_process_speed_check( { u32 cur_ratio, bpp = 1; int min_ratio_1000 = 0; + int freq_ratio = 1; + u32 sync_duration_den = 1; u32 vtotal, htotal = 0, clk_in_pps = 0, clk_vpu = 0, clk_temp; u32 input_time_us = 0, display_time_us = 0, dummy_time_us = 0; u32 width_out = 0; @@ -643,6 +648,9 @@ static int vpp_process_speed_check( if (next_frame_par->vscale_skip_count < force_vskip_cnt) return SPEED_CHECK_VSKIP; + if (vinfo->sync_duration_den > 0) + sync_duration_den = vinfo->sync_duration_den; + if (vf->type & VIDTYPE_PRE_INTERLACE) { if (is_meson_txlx_cpu()) clk_in_pps = 250000000; @@ -690,13 +698,22 @@ static int vpp_process_speed_check( if (clk_temp) dummy_time_us = (vtotal * htotal - height_out * width_out) / clk_temp; - display_time_us = 1000000 * vinfo->sync_duration_den / + display_time_us = 1000000 * sync_duration_den / vinfo->sync_duration_num; if (display_time_us > dummy_time_us) display_time_us = display_time_us - dummy_time_us; if (input_time_us > display_time_us) return SPEED_CHECK_VSKIP; } + + if ((vinfo->sync_duration_num / sync_duration_den) > 60) + freq_ratio = vinfo->sync_duration_num / + sync_duration_den / 60; + + if (freq_ratio < 1) + freq_ratio = 1; + cur_freq_ratio = freq_ratio; + /* #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8) */ if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { if ((width_in <= 0) || (height_in <= 0) || (height_out <= 0) @@ -719,7 +736,7 @@ static int vpp_process_speed_check( MESON_CPU_MAJOR_ID_GXBB) { cur_ratio = div_u64((u64)height_in * (u64)vinfo->height * - 1000, + 1000 * freq_ratio, height_out * max_height); /* di process first, need more a bit of ratio */ if (vf->type & VIDTYPE_PRE_INTERLACE) @@ -748,7 +765,7 @@ static int vpp_process_speed_check( (u64)vinfo->sync_duration_num * (u64)vtotal, height_out * - vinfo->sync_duration_den * + sync_duration_den * bypass_ratio) > clk_in_pps) return SPEED_CHECK_VSKIP; else @@ -762,7 +779,7 @@ static int vpp_process_speed_check( (u64)vinfo->sync_duration_num * (u64)vtotal, height_out * - vinfo->sync_duration_den * 256) + sync_duration_den * 256) > clk_in_pps) return SPEED_CHECK_VSKIP; /* 4K down scaling to non 4K > 30hz,*/ @@ -772,7 +789,7 @@ static int vpp_process_speed_check( && (height_in > 2048) && (height_out < 2048) && (vinfo->sync_duration_num > - (30 * vinfo->sync_duration_den)) + (30 * sync_duration_den)) && (get_cpu_type() != MESON_CPU_MAJOR_ID_GXTVBB) && (get_cpu_type() != @@ -785,7 +802,7 @@ static int vpp_process_speed_check( /*TODO vpu */ if (div_u64(VPP_SPEED_FACTOR * width_in * vinfo->sync_duration_num * height_screen, - vinfo->sync_duration_den * 256) + sync_duration_den * 256) > get_vpu_clk()) return SPEED_CHECK_HSKIP; else @@ -2249,7 +2266,15 @@ static void vpp_get_video_source_size( u32 process_3d_type, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par) { + int frame_width, frame_height; + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } if ((process_3d_type & MODE_3D_AUTO) || (((process_3d_type & MODE_3D_TO_2D_R) || (process_3d_type & MODE_3D_TO_2D_L) || @@ -2293,8 +2318,8 @@ static void vpp_get_video_source_size( break; case TVIN_TFMT_3D_DET_CHESSBOARD: default: - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; next_frame_par->vpp_3d_scale = 0; next_frame_par->vpp_2pic_mode = 0; @@ -2305,15 +2330,15 @@ static void vpp_get_video_source_size( (process_3d_type & MODE_FORCE_3D_LR)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; if (process_3d_type & MODE_3D_TO_2D_MASK) { - *src_width = vf->width >> 1; - *src_height = vf->height; + *src_width = frame_width >> 1; + *src_height = frame_height; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_2pic_mode = 1; } else { - *src_width = vf->width >> 1; - *src_height = vf->height << 1; + *src_width = frame_width >> 1; + *src_height = frame_height << 1; next_frame_par->vpp_2pic_mode = 1; } @@ -2321,38 +2346,38 @@ static void vpp_get_video_source_size( (process_3d_type & MODE_FORCE_3D_TB)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; if (process_3d_type & MODE_3D_TO_2D_MASK) { - *src_width = vf->width; - *src_height = vf->height >> 1; + *src_width = frame_width; + *src_height = frame_height >> 1; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width << 1; - *src_height = vf->height >> 1; + *src_width = frame_width << 1; + *src_height = frame_height >> 1; next_frame_par->vpp_2pic_mode = 1; } else { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_2pic_mode = 1; } if (process_3d_type & MODE_3D_MVC) { - *src_width = vf->width; - *src_height = vf->height << 1; + *src_width = frame_width; + *src_height = frame_height << 1; next_frame_par->vpp_2pic_mode = 2; next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; } } else if (process_3d_type & MODE_3D_LA) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LA; - *src_height = vf->height - 1; - *src_width = vf->width; + *src_height = frame_height - 1; + *src_width = frame_width; next_frame_par->vpp_2pic_mode = 0; next_frame_par->vpp_3d_scale = 1; if (process_3d_type & MODE_3D_TO_2D_MASK) { next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } else if (process_3d_type & MODE_3D_OUT_TB) { - *src_height = vf->height << 1; + *src_height = frame_height << 1; next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width << 1; + *src_width = frame_width << 1; next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } @@ -2364,37 +2389,37 @@ static void vpp_get_video_source_size( if (process_3d_type & MODE_3D_TO_2D_MASK) { if (process_3d_type & MODE_FORCE_3D_FA_TB) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; - *src_width = vf->width; - *src_height = vf->height >> 1; + *src_width = frame_width; + *src_height = frame_height >> 1; } if (process_3d_type & MODE_FORCE_3D_FA_LR) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; - *src_width = vf->width >> 1; - *src_height = vf->height; + *src_width = frame_width >> 1; + *src_height = frame_height; } if (process_3d_type & MODE_3D_MVC) { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; } if (vf->trans_fmt == TVIN_TFMT_3D_FP) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; - *src_width = vf->width; + *src_width = frame_width; *src_height = vf->left_eye.height; } next_frame_par->vpp_2pic_mode = 0; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width << 1; - *src_height = vf->height; + *src_width = frame_width << 1; + *src_height = frame_height; next_frame_par->vpp_2pic_mode = 2; } else { - *src_width = vf->width; - *src_height = vf->height << 1; + *src_width = frame_width; + *src_height = frame_height << 1; next_frame_par->vpp_2pic_mode = 2; } } else { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; next_frame_par->vpp_2pic_mode = 0; next_frame_par->vpp_3d_scale = 0; @@ -2421,8 +2446,8 @@ static void vpp_get_video_source_size( } /*avoid dividing 0 error */ if (*src_width == 0 || *src_height == 0) { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; } } #endif From 6a8932fc8cf9c6093efb9181d3c4aab978484167 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 8 Mar 2019 23:01:10 +0800 Subject: [PATCH 0305/1060] vpp: config the vd1 canvas1 correctly when 3D enabled [1/1] PD#TV-3086 Problem: 3D display abnormal. The vd1 canvas1 was incorrect. Solution: When enabled 3D function, config vd1 canvas1 correctly Verify: x301 Change-Id: I201cda2f33badf1af54ab4f177a17f761c7cea8d Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index aa06599a13e5..ddab391a9249 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -3780,7 +3780,7 @@ static void vsync_toggle_frame(struct vframe_s *vf) vf->plane_num, &disp_canvas_index[rdma_canvas_id][0]); } - if (is_mvc) { + if (is_mvc || process_3d_type) { if (vf->canvas1Addr != (u32)-1) { canvas_copy(vf->canvas1Addr & 0xff, disp_canvas_index[rdma_canvas_id][3]); @@ -3821,18 +3821,22 @@ static void vsync_toggle_frame(struct vframe_s *vf) disp_canvas[rdma_canvas_id][0]); } if (cur_frame_par - && (process_3d_type & MODE_3D_ENABLE) - && (process_3d_type & MODE_3D_TO_2D_R) - && (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1) - && is_mvc) { + && (process_3d_type & MODE_3D_ENABLE) + && (process_3d_type & MODE_3D_TO_2D_R) + && (cur_frame_par->vpp_2pic_mode + == VPP_SELECT_PIC1)) { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); + disp_canvas[rdma_canvas_id][1]); VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); + disp_canvas[rdma_canvas_id][1]); + if (is_mvc) { + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } } next_rdma_canvas_id = rdma_canvas_id ? 0 : 1; #else @@ -3841,7 +3845,7 @@ static void vsync_toggle_frame(struct vframe_s *vf) disp_canvas_index[1]); canvas_copy((vf->canvas0Addr >> 16) & 0xff, disp_canvas_index[2]); - if (is_mvc) { + if (is_mvc || process_3d_type) { canvas_copy(vf->canvas1Addr & 0xff, disp_canvas_index[3]); canvas_copy((vf->canvas1Addr >> 8) & 0xff, From 31580e773f7122f472d5e2263f63b2c1e87cc7cd Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Thu, 28 Feb 2019 11:24:59 +0800 Subject: [PATCH 0306/1060] vpp: support the interlace format from vdin afbc [1/2] PD#SWPL-5205 Problem: Now vdin support afbc+interlace format Solution: In vpp, add case to support vdin afbc with interlace Verify: tl1_x301, verify pass Change-Id: I6540b03a6cb5308fc2bc202069aa87234fd35df6 Signed-off-by: Yong Qin --- drivers/amlogic/media/video_sink/video.c | 16 +++++++++++++++- drivers/amlogic/media/video_sink/vpp.c | 5 ++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index ddab391a9249..64552dc303a8 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -520,6 +520,7 @@ const char video_dev_id2[] = "amvideo-dev2"; int onwaitendframe; static u32 vpp_hold_line = 8; +static u32 stop_update; struct video_dev_s video_dev[2] = { {0x1d00 - 0x1d00, 0x1a50 - 0x1a50}, @@ -4069,6 +4070,8 @@ static void vsync_toggle_frame(struct vframe_s *vf) #endif } } + if (stop_update) + frame_par_ready_to_set = 0; } static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) @@ -7198,7 +7201,15 @@ SET_FILTER: u32 zoom_start_y, zoom_end_y; correct_vd1_mif_size_for_DV(cur_frame_par); if (cur_dispbuf->type & VIDTYPE_INTERLACE) { - if (cur_dispbuf->type & VIDTYPE_VIU_FIELD) { + if (cur_dispbuf->type + & VIDTYPE_COMPRESS) { + /* for vdin afbc and interlace case */ + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_; + zoom_end_y = + cur_frame_par->VPP_vd_end_lines_; + } else if (cur_dispbuf->type + & VIDTYPE_VIU_FIELD) { zoom_start_y = cur_frame_par->VPP_vd_start_lines_ >> 1; @@ -13036,6 +13047,9 @@ module_param(toggle_count, uint, 0664); MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n"); module_param(vpp_hold_line, uint, 0664); +MODULE_PARM_DESC(stop_update, "\n stop_update\n"); +module_param(stop_update, uint, 0664); + MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n"); module_param(reference_zorder, uint, 0664); diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index e4325bceca60..8590b24418cb 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -2934,7 +2934,10 @@ int vpp_set_filters( aspect_ratio = (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) >> DISP_RATIO_ASPECT_RATIO_BIT; - if (vf->type & VIDTYPE_INTERLACE) + /* the height from vdin afbc will be half */ + /* so need no interlace in */ + if ((vf->type & VIDTYPE_INTERLACE) + && !(vf->type & VIDTYPE_COMPRESS)) vpp_flags = VPP_FLAG_INTERLACE_IN; if (vf->ratio_control & DISP_RATIO_PORTRAIT_MODE) From be1116950a6440865342cc3104651f14244fdc17 Mon Sep 17 00:00:00 2001 From: Yi Zeng Date: Fri, 25 Jan 2019 19:43:53 +0800 Subject: [PATCH 0307/1060] mtd: nand: support new slc nand [1/1] PD#SWPL-4511 Problem: 1Gb SLC Nand ZDND1G08U3D-IA requested by Marketing aka ZDND1G08U3D-xx module number in code Solution: add the nand id into amlogic nand flash id table Verify: AXG_S400 Change-Id: I4e221497b801239aa62f62f844ff247fa05925d0 Signed-off-by: Yi Zeng --- drivers/amlogic/mtd/nand_flash.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/amlogic/mtd/nand_flash.c b/drivers/amlogic/mtd/nand_flash.c index 9f29f4d6f988..eaf9715bf610 100644 --- a/drivers/amlogic/mtd/nand_flash.c +++ b/drivers/amlogic/mtd/nand_flash.c @@ -301,6 +301,19 @@ struct aml_nand_flash_dev aml_nand_flash_ids[] = { 0, (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + {"Zetta NAND ZDND1G08U3D-xx 1Gb", + {NAND_MFR_ZETTA, 0xf1, 0x80, 0x95}, + 2048, + 128, + 0x20000, + 64, + 1, + 20, + 15, + 0, + 0, + (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + {"A revision NAND 1GiB sF1G-A", {NAND_MFR_AMD, 0xf1, 0x80, 0x1d, 0x01, 0xf1}, 2048, From a37c28899570adce912cf72ac844e0c074775ade Mon Sep 17 00:00:00 2001 From: lingjie li Date: Tue, 19 Feb 2019 19:47:06 +0800 Subject: [PATCH 0308/1060] osd: update osd_count according to the chip [2/4] PD#SWPL-3996 Problem: g12b/g12a wayland-drm device print below error "fb: error osd index=0" while start wayland-client. while start wayland-client. Solution: set to the proper osd_count Verify: W400 Change-Id: I3c4c6d821ff0778cd4912a67046f7dbab60be2ad Signed-off-by: lingjie li --- drivers/amlogic/drm/am_meson_vpu.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/drm/am_meson_vpu.c b/drivers/amlogic/drm/am_meson_vpu.c index fccfdc20a88a..9c7850b715b3 100644 --- a/drivers/amlogic/drm/am_meson_vpu.c +++ b/drivers/amlogic/drm/am_meson_vpu.c @@ -208,7 +208,7 @@ static struct osd_device_data_s osd_g12a = { .cpu_id = __MESON_CPU_MAJOR_ID_G12A, .osd_ver = OSD_HIGH_ONE, .afbc_type = MALI_AFBC, - .osd_count = 3, + .osd_count = 4, .has_deband = 1, .has_lut = 1, .has_rdma = 1, @@ -223,7 +223,7 @@ static struct osd_device_data_s osd_g12b = { .cpu_id = __MESON_CPU_MAJOR_ID_G12B, .osd_ver = OSD_HIGH_ONE, .afbc_type = MALI_AFBC, - .osd_count = 3, + .osd_count = 4, .has_deband = 1, .has_lut = 1, .has_rdma = 1, @@ -240,15 +240,22 @@ static struct page *logo_page; static struct delayed_work osd_dwork; static struct platform_device *gp_dev; + int am_meson_crtc_dts_info_set(const void *dt_match_data) { struct osd_device_data_s *osd_meson; osd_meson = (struct osd_device_data_s *)dt_match_data; - if (osd_meson) + if (osd_meson) { memcpy(&osd_meson_dev, osd_meson, sizeof(struct osd_device_data_s)); - else { + osd_meson_dev.viu1_osd_count = osd_meson_dev.osd_count; + if (osd_meson_dev.has_viu2) { + /* set viu1 osd count */ + osd_meson_dev.viu1_osd_count--; + osd_meson_dev.viu2_index = osd_meson_dev.viu1_osd_count; + } + } else { DRM_ERROR("%s data NOT match\n", __func__); return -1; } From ff352493d696a85c6aadfd36ada734709de16b14 Mon Sep 17 00:00:00 2001 From: sky zhou Date: Wed, 13 Feb 2019 18:12:38 +0800 Subject: [PATCH 0309/1060] dts: add u212/w400 wayland+drm dts [1/4] PD#SWPL-3996 Problem: no dts for u212/w400 drm. Solution: add drm dts for u212/w400. Verify: verify on u212/w400. Change-Id: I534e3e6e847dfa10fc3515c256048ea237bdcd68 Signed-off-by: sky zhou --- .../g12a_s905x2_u212_drm_buildroot.dts | 1389 ++++++++++++++++ .../amlogic/g12b_a311d_w400_drm_buildroot.dts | 1459 ++++++++++++++++ .../g12a_s905x2_u212_drm_buildroot.dts | 1384 ++++++++++++++++ .../amlogic/g12b_a311d_w400_drm_buildroot.dts | 1463 +++++++++++++++++ 4 files changed, 5695 insertions(+) create mode 100644 arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts create mode 100644 arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts create mode 100644 arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts new file mode 100644 index 000000000000..5e882d13c814 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts @@ -0,0 +1,1389 @@ +/* + * arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + net_red { + label="net_red"; + gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + + net_green { + label="net_green"; + gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x343 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_telecom = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + meson-fb { + compatible = "amlogic, meson-g12a"; + /*memory-region = <&logo_reserved>;*/ + dev_name = "meson-fb"; + status = "okay"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + mem_alloc = <1>; + logo_addr = "0x3f800000"; + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for SY8120B1ABC*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "amlogic, bl_extern_i2c"; + status = "disabled"; + reg = <0x2c>; /*reg_address for lp8556*/ + dev_name = "lp8556"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_10, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_9 */ + groups = "tdmc_din1_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + spdifout: spdifout { + mux { + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + /*gpiao_10*/ + /*spdifout: spdifout { */ + /* mux { */ + /* groups = "spdif_out_ao"; */ + /* function = "spdif_out_ao";*/ + /* }; */ + /*}; */ +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + +&meson_fb { + status = "disable"; +}; + +&drm_vpu { + status = "okay"; + compatible = "amlogic,meson-g12b-vpu"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts new file mode 100644 index 000000000000..8f786b06455d --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -0,0 +1,1459 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; + +&meson_fb { + status = "disable"; +}; + +&drm_vpu { + status = "okay"; + compatible = "amlogic,meson-g12b-vpu"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts new file mode 100644 index 000000000000..9e106b9e500d --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts @@ -0,0 +1,1384 @@ +/* + * arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + net_red { + label="net_red"; + gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + + net_green { + label="net_green"; + gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x343 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_telecom = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + meson-fb { + compatible = "amlogic, meson-g12a"; + /*memory-region = <&logo_reserved>;*/ + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + mem_alloc = <1>; + logo_addr = "0x3f800000"; + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for SY8120B1ABC*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <761000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <831000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <871000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <921000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&drm_vpu { + status = "okay"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "amlogic, bl_extern_i2c"; + status = "disabled"; + reg = <0x2c>; /*reg_address for lp8556*/ + dev_name = "lp8556"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_10, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_9 */ + groups = "tdmc_din1_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + spdifout: spdifout { + mux { + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + /*gpiao_10*/ + /*spdifout: spdifout { */ + /* mux { */ + /* groups = "spdif_out_ao"; */ + /* function = "spdif_out_ao";*/ + /* }; */ + /*}; */ +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts new file mode 100644 index 000000000000..05c6f78a380f --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -0,0 +1,1463 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "disable"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&drm_vpu { + status = "okay"; + compatible = "amlogic,meson-g12b-vpu"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; From 75bd3a4959a587d2bfd8f5b6ae0588b30fe81066 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Sat, 2 Mar 2019 20:38:49 +0800 Subject: [PATCH 0310/1060] binder: replace vmalloc range if need more memory [1/1] PD#SWPL-5553 Problem: Binder will allocate about 1MB vmalloc memory for IPC for each process, but under code like GTVS, there are about over 100 vmalloc ranges allocated by binder, which cause vmalloc address range not enough for other modules. Solution: 1, only vmalloc 4KB at first; 2, if user space need more memory, try to allocate a new vmalloc range with large size and move all related data to new place 3, dump vmalloc info if vmalloc failed Verify: P212 Change-Id: I07eea2623e5e19d410e0ff8a0bc6b11e2037023c Signed-off-by: Tao Zeng --- arch/arm/mm/proc-v7.S | 2 + drivers/android/binder_alloc.c | 167 +++++++++++++++++++++++++++++++++ drivers/android/binder_alloc.h | 10 ++ mm/vmalloc.c | 18 ++++ 4 files changed, 197 insertions(+) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 850c22bca19c..955fda65ffb4 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -79,7 +79,9 @@ ENDPROC(cpu_v7_do_idle) ENTRY(cpu_v7_dcache_clean_area) ALT_SMP(W(nop)) @ MP extensions imply L1 PTW ALT_UP_B(1f) +#ifndef CONFIG_AMLOGIC_MODIFY ret lr +#endif 1: dcache_line_size r2, r3 2: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, r2 diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index bec6c0a90429..15f287250940 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -185,6 +185,152 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, return buffer; } +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC +static unsigned long check_range(struct binder_alloc *alloc, void *end) +{ + unsigned long size; + + size = (unsigned long)end - (unsigned long)alloc->buffer; + if (size > PAGE_SIZE && size > alloc->mapped_size) { + pr_debug("%s, %d, base:%p, end:%p, size:%ld, task:%d %s\n", + __func__, __LINE__, alloc->buffer, end, size, + current->pid, current->comm); + return size; + } + return 0; +} + +static int move_vma_mapping(void *old, void *new_addr, unsigned long size) +{ + struct page *page, *pages[2] = {}; + unsigned long addr, end, new, moved = 0; + int ret; + + addr = (unsigned long)old; + end = (unsigned long)old + size; + new = (unsigned long)new_addr; + for (; addr < end; addr += PAGE_SIZE) { + page = vmalloc_to_page((void *)addr); + if (!page) { + new += PAGE_SIZE; + continue; + } + /* Make sure cache same for other address */ + cpu_ca8_dcache_clean_area((void *)addr, PAGE_SIZE); + pages[0] = page; + ret = map_kernel_range_noflush(new, PAGE_SIZE, + PAGE_KERNEL, pages); + pr_debug("%s, addr:%lx->%lx, old:%p, new:%p, page:%lx %p %p\n", + __func__, addr, new, old, new_addr, + page_to_pfn(page), pages[0], pages[1]); + flush_cache_vmap(addr, addr + PAGE_SIZE); + new += PAGE_SIZE; + moved++; + if (ret < 0) + return ret; + } + return moved; +} + +static void free_back_buffer(struct binder_alloc *alloc) +{ + int i; + void *p; + + for (i = 0; i < MAX_BUFFER; i++) { + p = alloc->back_buffer[i]; + if (p && p != alloc->buffer) { + vfree(p); + pr_debug("free alloc %p, buffer:%p@%d\n", alloc, p, i); + } + } +} + +static unsigned long get_new_size(unsigned long curr_size, + unsigned long max_size, int next_step) +{ + int order, step; + long next_size; + + order = get_order(max_size); + step = (order + MAX_BUFFER / 2) / MAX_BUFFER; + next_step += 1; + next_size = (1 << (next_step * step + PAGE_SHIFT)); + if (next_size <= curr_size) + return curr_size + PAGE_SIZE * 4; + return next_size; +} + +static int try_to_replace_vmap(struct binder_alloc *alloc, + unsigned long new_sz, + void **start, void **endp) +{ + unsigned long max_size, diff, size; + unsigned long *old_buffer; + struct binder_buffer *buffer; + struct vm_struct *area; + int ret, i; + + for (i = 0; i < MAX_BUFFER; i++) { + if (!alloc->back_buffer[i]) + break; + } + + if (i == MAX_BUFFER) { + pr_info("max buffer:%d, new_sz:%lx, buffer:%p %p %p %p\n", + i, new_sz, alloc->back_buffer[0], + alloc->back_buffer[1], alloc->back_buffer[2], + alloc->back_buffer[3]); + dump_stack(); + return -ENOMEM; + } + + max_size = alloc->vma->vm_end - alloc->vma->vm_start; + size = get_new_size(new_sz, max_size, i); + if (size >= max_size) + size = max_size; + area = get_vm_area(size, VM_ALLOC | VM_NO_GUARD); + if (area == NULL) { + pr_err("%s, get vmalloc size:%lx failed\n", __func__, size); + return -ENOMEM; + } + + ret = move_vma_mapping(alloc->buffer, area->addr, alloc->mapped_size); + pr_debug("%s, move %p:%p, ret:%d, vm size:%x:%lx, want:%lx, alloc:%p\n", + __func__, alloc->buffer, area->addr, + ret, alloc->mapped_size, size, new_sz, alloc); + if (ret < 0) { + free_vm_area(area); + return -ENOMEM; + } + + old_buffer = alloc->buffer; + alloc->buffer = area->addr; + diff = (unsigned long)old_buffer - + (unsigned long)alloc->buffer; + pr_debug("old:%p, new:%p, size:%ld, mapped:%d, alloc:%p\n", + old_buffer, alloc->buffer, size, alloc->mapped_size, alloc); + alloc->user_buffer_offset = alloc->vma->vm_start - + (uintptr_t)alloc->buffer; + list_for_each_entry(buffer, &alloc->buffers, entry) { + void *tmp; + + tmp = buffer->data; + buffer->data = buffer->data - diff; + pr_debug("replace:%p, new:%p, diff:%lx\n", + tmp, buffer->data, diff); + } + *start = *start - diff; + *endp = *endp - diff; + alloc->mapped_size = size; + alloc->back_buffer[i] = area->addr; + pr_debug("replace %i, alloc:%p, size:%lx:%lx, start:%p, end:%p\n", + i, alloc, new_sz, size, *start, *endp); + + return 0; +} +#endif + static int binder_update_page_range(struct binder_alloc *alloc, int allocate, void *start, void *end) { @@ -194,6 +340,9 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, struct vm_area_struct *vma = NULL; struct mm_struct *mm = NULL; bool need_mm = false; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + unsigned long map_size; +#endif binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: %s pages %pK-%pK\n", alloc->pid, @@ -229,6 +378,14 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, goto err_no_vma; } +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + /* try to replace vmalloc */ + map_size = check_range(alloc, end); + if (map_size) { + if (try_to_replace_vmap(alloc, map_size, &start, &end)) + return -ENOMEM; + } +#endif for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { int ret; bool on_lru; @@ -670,7 +827,11 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_already_mapped; } +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + area = get_vm_area(PAGE_SIZE, VM_ALLOC | VM_NO_GUARD); +#else area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC); +#endif if (area == NULL) { ret = -ENOMEM; failure_string = "get_vm_area"; @@ -701,6 +862,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_alloc_pages_failed; } alloc->buffer_size = vma->vm_end - vma->vm_start; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + alloc->mapped_size = PAGE_SIZE; +#endif buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) { @@ -792,6 +956,9 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) } kfree(alloc->pages); vfree(alloc->buffer); + #ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + free_back_buffer(alloc); + #endif } mutex_unlock(&alloc->mutex); if (alloc->vma_vm_mm) diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 9ef64e563856..592d4aa98945 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -99,11 +99,21 @@ struct binder_lru_page { * calls. The address space is used for both user-visible buffers and for * struct binder_buffer objects used to track the user buffers */ +#if defined(CONFIG_AMLOGIC_MODIFY) && defined(CONFIG_ARM) +#define CONFIG_AMLOGIC_BINDER_VMALLOC +#define MAX_BUFFER 4 +extern void cpu_ca8_dcache_clean_area(void *addr, int size); +#endif + struct binder_alloc { struct mutex mutex; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; void *buffer; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + size_t mapped_size; + void *back_buffer[MAX_BUFFER]; +#endif /* CONFIG_AMLOGIC_BINDER_VMALLOC */ ptrdiff_t user_buffer_offset; struct list_head buffers; struct rb_root free_buffers; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6debb44a231e..655e3b8ac185 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -356,6 +356,21 @@ static void purge_vmap_area_lazy(void); static BLOCKING_NOTIFIER_HEAD(vmap_notify_list); +#ifdef CONFIG_AMLOGIC_MODIFY +static void dump_vmalloc(void) +{ + struct vmap_area *va, *next; + + spin_lock(&vmap_area_lock); + list_for_each_entry_safe(va, next, &vmap_area_list, list) { + pr_info("%s, va:%lx-%lx, size:%08ld KB, alloc:%pf\n", + __func__, va->va_start, va->va_end, + (va->va_end - va->va_start) >> 10, va->vm->caller); + } + spin_unlock(&vmap_area_lock); +} +#endif + /* * Allocate a region of KVA of the specified size and alignment, within the * vstart and vend. @@ -496,6 +511,9 @@ overflow: } } +#ifdef CONFIG_AMLOGIC_MODIFY + dump_vmalloc(); +#endif if (printk_ratelimit()) pr_warn("vmap allocation for size %lu failed: use vmalloc= to increase size\n", size); From 1d595205630dafd6f4b0717d4bf6efaf2d3401d0 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Mon, 4 Mar 2019 15:39:02 +0800 Subject: [PATCH 0311/1060] lcd: optimize vsync probe method, by string, not index value in dts [2/2] PD#SWPL-4679 Problem: optimize vsync probe method, by string, not index value in dts Solution: optimize vsync probe method, by string, not index value in dts Verify: verify by t962x2-x301 Change-Id: Ib87a2913b7dafb3ea3c9c5a936b29939ab7ee034 Signed-off-by: Shaochan Liu --- .../media/vout/lcd/lcd_tablet/lcd_tablet.c | 4 +++ drivers/amlogic/media/vout/lcd/lcd_vout.c | 31 +++++-------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 56f2647119cb..acb0e879fdfb 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -992,6 +992,10 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_PCLK + 1)) << 8) | ((*(p + LCD_UKEY_PCLK + 2)) << 16) | ((*(p + LCD_UKEY_PCLK + 3)) << 24)); + if (pconf->lcd_timing.lcd_clk == 0) { /* avoid 0 mistake */ + pconf->lcd_timing.lcd_clk = 60; + LCDERR("lcd_clk is 0, default to 60Hz\n"); + } pconf->lcd_basic.h_period_min = (*(p + LCD_UKEY_H_PERIOD_MIN) | ((*(p + LCD_UKEY_H_PERIOD_MIN + 1)) << 8)); pconf->lcd_basic.h_period_max = (*(p + LCD_UKEY_H_PERIOD_MAX) | diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 959e00fd1d35..4f4574f4ce13 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -1113,29 +1113,14 @@ static int lcd_config_probe(struct platform_device *pdev) LCDPR("detect lcd_auto_test: %d\n", lcd_driver->lcd_auto_test); } - ret = of_property_read_string_index(lcd_driver->dev->of_node, - "interrupt-names", 0, &str); - if (ret == 0) { - lcd_driver->res_vsync_irq = platform_get_resource(pdev, - IORESOURCE_IRQ, 0); - } - ret = of_property_read_string_index(lcd_driver->dev->of_node, - "interrupt-names", 1, &str); - if (ret == 0) { - if (strcmp(str, "vbyone") == 0) { - lcd_driver->res_vx1_irq = - platform_get_resource(pdev, IORESOURCE_IRQ, 1); - } else if (strcmp(str, "vsync2") == 0) { - lcd_driver->res_vsync2_irq = - platform_get_resource(pdev, IORESOURCE_IRQ, 1); - } - } - ret = of_property_read_string_index(lcd_driver->dev->of_node, - "interrupt-names", 2, &str); - if (ret == 0) { - lcd_driver->res_tcon_irq = platform_get_resource(pdev, - IORESOURCE_IRQ, 2); - } + lcd_driver->res_vsync_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "vsync"); + lcd_driver->res_vsync2_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "vsync2"); + lcd_driver->res_vx1_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "vbyone"); + lcd_driver->res_tcon_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "tcon"); lcd_driver->lcd_info = &lcd_vinfo; lcd_driver->lcd_config = &lcd_config_dft; From 47110da7a6b8f72d9dd2c600497d53f632da2c7d Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Tue, 12 Mar 2019 10:58:30 +0800 Subject: [PATCH 0312/1060] audio: Add PDM lane mask [1/1] PD#SWPL-5594 Problem: The PDM input channel is not always in the first lane, we need a mask to detect which lane to use Solution: Add lane config in PDM module Add lane-mask-in in W411 config Verify: W411 Change-Id: I48ca5927402282611ba5e225d75d034eeceacad6 Signed-off-by: yujie.wu --- .../dts/amlogic/g12b_a311x_w411_buildroot.dts | 1 + .../amlogic/g12b_a311x_w411_buildroot_a.dts | 1 + sound/soc/amlogic/auge/pdm.c | 37 +++++++++++++-- sound/soc/amlogic/auge/pdm.h | 13 +++++- sound/soc/amlogic/auge/pdm_hw.c | 45 ++++++++++++++----- sound/soc/amlogic/auge/pdm_hw.h | 16 +++++-- 6 files changed, 96 insertions(+), 17 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index bbb0db177569..95d178a76b74 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -1046,6 +1046,7 @@ "pdm_sysclk"; pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; + lane-mask-in = <0 0 1 0>; filter_mode = <1>; /* mode 0~4, defalut:1 */ status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index 7493fd90e079..76612158e2e1 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -1015,6 +1015,7 @@ "pdm_sysclk"; pinctrl-names = "pdm_pins"; pinctrl-0 = <&pdmin>; + lane-mask-in = <0 0 1 0>; filter_mode = <1>; /* mode 0~4, defalut:1 */ status = "okay"; }; diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index bf92cacb75ea..717289ec6db6 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -54,7 +54,7 @@ static struct snd_pcm_hardware aml_pdm_hardware = { .rate_max = 96000, .channels_min = PDM_CHANNELS_MIN, - .channels_max = PDM_CHANNELS_MAX, + .channels_max = PDM_CHANNELS_LB_MAX, .buffer_bytes_max = 512 * 1024, .period_bytes_max = 256 * 1024, @@ -626,6 +626,7 @@ static int aml_pdm_dai_prepare( struct toddr *to = p_pdm->tddr; struct toddr_fmt fmt; unsigned int osr = 192; + struct pdm_info info; /* to ddr pdmin */ fmt.type = toddr_type; @@ -639,8 +640,12 @@ static int aml_pdm_dai_prepare( aml_toddr_set_format(to, &fmt); aml_toddr_set_fifos(to, 0x40); - aml_pdm_ctrl(p_pdm->actrl, - bitwidth, runtime->channels); + info.bitdepth = bitwidth; + info.channels = runtime->channels; + info.lane_masks = p_pdm->lane_mask_in; + info.dclk_idx = pdm_dclk; + info.bypass = p_pdm->bypass; + aml_pdm_ctrl(&info); /* filter for pdm */ if (pdm_dclk == 1) { @@ -918,6 +923,26 @@ static const struct of_device_id aml_pdm_device_id[] = { }; MODULE_DEVICE_TABLE(of, aml_pdm_device_id); +static int snd_soc_of_get_slot_mask( + struct device_node *np, + const char *prop_name, + unsigned int *mask) +{ + u32 val; + const __be32 *of_slot_mask = of_get_property(np, prop_name, &val); + int i; + + if (!of_slot_mask) + return -EINVAL; + + val /= sizeof(u32); + for (i = 0; i < val; i++) + if (be32_to_cpup(&of_slot_mask[i])) + *mask |= (1 << i); + + return val; +} + static int aml_pdm_platform_probe(struct platform_device *pdev) { struct aml_pdm *p_pdm; @@ -1022,6 +1047,12 @@ static int aml_pdm_platform_probe(struct platform_device *pdev) goto err; } + ret = snd_soc_of_get_slot_mask(node, "lane-mask-in", + &p_pdm->lane_mask_in); + if (ret < 0) { + pr_warn("default set lane_mask_in as all lanes.\n"); + p_pdm->lane_mask_in = 0xf; + } ret = of_property_read_u32(node, "filter_mode", &p_pdm->filter_mode); diff --git a/sound/soc/amlogic/auge/pdm.h b/sound/soc/amlogic/auge/pdm.h index 60a0e1e46689..43100b836780 100644 --- a/sound/soc/amlogic/auge/pdm.h +++ b/sound/soc/amlogic/auge/pdm.h @@ -27,7 +27,9 @@ #define DEFAULT_FS_RATIO 256 #define PDM_CHANNELS_MIN 1 -#define PDM_CHANNELS_MAX (8 + 8) /* 8ch pdm in, 8 ch tdmin_lb */ +/* 8ch pdm in, 8 ch tdmin_lb */ +#define PDM_CHANNELS_LB_MAX (PDM_CHANNELS_MAX + 8) + #define PDM_RATES (SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_64000 |\ @@ -72,6 +74,15 @@ struct aml_pdm { * the group delay (latency) is from high to low. */ int filter_mode; + /* dclk index */ + int dclk_idx; + /* PCM or Raw Data */ + int bypass; + /* PDM clk on/off */ + bool clk_on; + + /* lane mask in, each lane carries two channels */ + int lane_mask_in; struct pdm_chipinfo *chipinfo; struct snd_kcontrol *controls[PDM_RUN_MAX]; diff --git a/sound/soc/amlogic/auge/pdm_hw.c b/sound/soc/amlogic/auge/pdm_hw.c index d870dd0336c5..d814c04f8faf 100644 --- a/sound/soc/amlogic/auge/pdm_hw.c +++ b/sound/soc/amlogic/auge/pdm_hw.c @@ -59,29 +59,54 @@ void pdm_fifo_reset(void) 0x1 << 16); } -void aml_pdm_ctrl( - struct aml_audio_controller *actrl, - int bitdepth, int channels) +void aml_pdm_ctrl(struct pdm_info *info) { int mode, i, ch_mask = 0, sample_count; + int pdm_chs, lane_chs = 0; + + if (!info) + return; /* sameple count */ - if (pdm_dclk == 1) + if (info->dclk_idx == 1) sample_count = 38; - else if (pdm_dclk == 2) + else if (info->dclk_idx == 2) sample_count = 48; else sample_count = 18; - if (bitdepth == 32) + if (info->bitdepth == 32) mode = 0; else mode = 1; - for (i = 0; i < channels; i++) - ch_mask |= (1 << i); + /* update pdm channels for loopback */ + pdm_chs = info->channels; + if (info->channels > PDM_CHANNELS_MAX) + pdm_chs = PDM_CHANNELS_MAX; - pr_info("%s, channels mask:%x\n", __func__, ch_mask); + if (pdm_chs > info->lane_masks * 2) + pr_warn("capturing channels more than lanes carried\n"); + + /* each lanes carries two channels */ + for (i = 0; i < PDM_LANE_MAX; i++) + if ((1 << i) & info->lane_masks) { + ch_mask |= (1 << (2 * i)); + lane_chs += 1; + if (lane_chs >= info->channels) + break; + ch_mask |= (1 << (2 * i + 1)); + lane_chs += 1; + if (lane_chs >= info->channels) + break; + } + + pr_info("%s, lane mask:0x%x, channels:%d, channels mask:0x%x, bypass:%d\n", + __func__, + info->lane_masks, + info->channels, + ch_mask, + info->bypass); aml_pdm_write(PDM_CLKG_CTRL, 1); @@ -96,7 +121,7 @@ void aml_pdm_ctrl( /* bypass mode. * 1: bypass all filter. 0: normal mode. */ - (0 << 28) | + (info->bypass << 28) | /* PDM channel reset. */ (ch_mask << 8) | /* PDM channel enable */ diff --git a/sound/soc/amlogic/auge/pdm_hw.h b/sound/soc/amlogic/auge/pdm_hw.h index b7d19c025c71..b7ad4737dbd8 100644 --- a/sound/soc/amlogic/auge/pdm_hw.h +++ b/sound/soc/amlogic/auge/pdm_hw.h @@ -19,9 +19,19 @@ #define __AML_PDM_HW_H__ #include "audio_io.h" -extern void aml_pdm_ctrl( - struct aml_audio_controller *actrl, - int bitdepth, int channels); +#define PDM_CHANNELS_MAX 8 /* 8ch pdm in */ +#define PDM_LANE_MAX 4 /* 4 data pins, for 8ch maxs*/ + +struct pdm_info { + int bitdepth; + int channels; + int lane_masks; + + int dclk_idx; /* mapping for dclk value */ + int bypass; /* bypass all filter, capture raw data */ +}; + +extern void aml_pdm_ctrl(struct pdm_info *info); extern void aml_pdm_arb_config(struct aml_audio_controller *actrl); From e0d7887c28bd2f28c1229347283130558f2a6d3e Mon Sep 17 00:00:00 2001 From: yuehu mi Date: Fri, 8 Mar 2019 13:52:18 +0800 Subject: [PATCH 0313/1060] vrtc: add debug nodes, set alarm time and wake up system [1/1] PD#TV-3085 Problem: Add VRTC debug interface into TL1 Android P Solution: add wakeup and wakeup_time debug nodes if you want to set alarm time, for example, set alarm wakeup time 10s echo 10 > /sys/kernel/debug/wakeup_time if you want to wake the system when an alarm is triggered, like this echo 1 > /sys/kernel/debug/wakeup Verify: tl1_t962x2_x301 Change-Id: Ic40db0d9cb4ac2cab615206518d8db22b4095f72 Signed-off-by: yuehu mi --- drivers/amlogic/vrtc/aml_vrtc.c | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/amlogic/vrtc/aml_vrtc.c b/drivers/amlogic/vrtc/aml_vrtc.c index 1f102f36fbcd..2c79f35813e0 100644 --- a/drivers/amlogic/vrtc/aml_vrtc.c +++ b/drivers/amlogic/vrtc/aml_vrtc.c @@ -25,10 +25,55 @@ #include #include #include +#include +#include +#include static void __iomem *alarm_reg_vaddr; static void __iomem *timere_low_vaddr, *timere_high_vaddr; static unsigned int vrtc_init_date; +static int wakeup; +static int wakeup_time; +static struct input_dev *vinput_dev; + +static void send_power_btn_wakeup(void) +{ + if ((get_resume_method() == RTC_WAKEUP) || + (get_resume_method() == AUTO_WAKEUP)) { + input_event(vinput_dev, EV_KEY, KEY_POWER, 1); + input_sync(vinput_dev); + input_event(vinput_dev, EV_KEY, KEY_POWER, 0); + input_sync(vinput_dev); + } +} + +static int vinput_dev_init(struct platform_device *pdev) +{ + int r; + + vinput_dev = input_allocate_device(); + if (!vinput_dev) + return -ENOMEM; + + vinput_dev->name = "aml_vkeypad"; + vinput_dev->phys = "keypad/input0"; + vinput_dev->id.vendor = 0x0001; + vinput_dev->id.product = 0x0001; + vinput_dev->id.version = 0x0100; + set_bit(EV_KEY, vinput_dev->evbit); + set_bit(KEY_POWER, vinput_dev->keybit); + + vinput_dev->dev.parent = &pdev->dev; + device_init_wakeup(&vinput_dev->dev, 1); + + r = input_register_device(vinput_dev); + if (r) { + pr_err("failed to register power button: %d\n", r); + input_free_device(vinput_dev); + } + + return r; +} #define TIME_LEN 10 static int parse_init_date(const char *date) @@ -204,6 +249,11 @@ static int aml_vrtc_probe(struct platform_device *pdev) return -1; platform_set_drvdata(pdev, vrtc); + vinput_dev_init(pdev); + + debugfs_create_u32("wakeup", 0644, NULL, &wakeup); + debugfs_create_u32("wakeup_time", 0644, NULL, &wakeup_time); + return 0; } @@ -211,6 +261,8 @@ static int aml_vrtc_remove(struct platform_device *dev) { struct rtc_device *vrtc = platform_get_drvdata(dev); + input_unregister_device(vinput_dev); + rtc_device_unregister(vrtc); return 0; @@ -227,6 +279,11 @@ static int aml_vrtc_resume(struct platform_device *pdev) if (!scpi_get_vrtc(&vrtc_init_date)) pr_debug("get vrtc: %us\n", vrtc_init_date); + if (wakeup > 0) { + pr_info("aml_vrtc_suspend wakeup=%d\n", wakeup); + send_power_btn_wakeup(); + } + return 0; } @@ -234,6 +291,11 @@ static int aml_vrtc_suspend(struct platform_device *pdev, pm_message_t state) { u32 vrtc_val; + if (wakeup_time > 0) { + pr_info("aml_vrtc_suspend wakeup_time=%d\n", wakeup_time); + set_wakeup_time(wakeup_time); + } + vrtc_val = read_te(); if (scpi_set_vrtc(vrtc_val)) From c14bc154cc476a46bfeaf2079736e15b970257d7 Mon Sep 17 00:00:00 2001 From: Tao Guo Date: Wed, 16 Jan 2019 17:11:54 +0800 Subject: [PATCH 0314/1060] debug: add atrace support [1/1] PD#SWPL-4956 Problem: Need atrace to debug multimedia issue Solution: Add atrace functions Verify: P212 Change-Id: I0f07387dfa35a33c25e538a474a3a12bd88d5092 Signed-off-by: Tao Guo --- drivers/amlogic/debug/Kconfig | 6 +++ drivers/amlogic/debug/Makefile | 1 + drivers/amlogic/debug/meson_atrace.c | 21 ++++++++ drivers/amlogic/media/frame_sync/timestamp.c | 4 ++ drivers/amlogic/media/video_sink/video.c | 51 ++++++++++++++++---- include/trace/events/meson_atrace.h | 7 ++- 6 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 drivers/amlogic/debug/meson_atrace.c diff --git a/drivers/amlogic/debug/Kconfig b/drivers/amlogic/debug/Kconfig index 34af20905279..1bbc48731be4 100644 --- a/drivers/amlogic/debug/Kconfig +++ b/drivers/amlogic/debug/Kconfig @@ -13,3 +13,9 @@ config AMLOGIC_DEBUG_LOCKUP Debug lockup in isr and deaklock whit irq disabled. When enable this config, Watchdog should be disabled. +config AMLOGIC_DEBUG_ATRACE + bool "Amlogic Kernel ATrace" + depends on AMLOGIC_DEBUG + default y + help + Add android atrace compatible function diff --git a/drivers/amlogic/debug/Makefile b/drivers/amlogic/debug/Makefile index 2f07bf942da5..7576af9f601b 100644 --- a/drivers/amlogic/debug/Makefile +++ b/drivers/amlogic/debug/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_AMLOGIC_DEBUG_LOCKUP) += debug_lockup.o +obj-$(CONFIG_AMLOGIC_DEBUG_ATRACE) += meson_atrace.o diff --git a/drivers/amlogic/debug/meson_atrace.c b/drivers/amlogic/debug/meson_atrace.c new file mode 100644 index 000000000000..f27132623503 --- /dev/null +++ b/drivers/amlogic/debug/meson_atrace.c @@ -0,0 +1,21 @@ +/* + * drivers/amlogic/debug/meson_atrace.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#define CREATE_TRACE_POINTS +#include + +EXPORT_TRACEPOINT_SYMBOL_GPL(tracing_mark_write); diff --git a/drivers/amlogic/media/frame_sync/timestamp.c b/drivers/amlogic/media/frame_sync/timestamp.c index 472be72c92b2..a6076d58a575 100644 --- a/drivers/amlogic/media/frame_sync/timestamp.c +++ b/drivers/amlogic/media/frame_sync/timestamp.c @@ -22,6 +22,7 @@ #include #include #include +#include u32 acc_apts_inc; @@ -147,6 +148,7 @@ EXPORT_SYMBOL(timestamp_tsdemux_pcr_get); void timestamp_pcrscr_set(u32 pts) { /*pr_info("timestamp_pcrscr_set system time = %x\n", pts);*/ + ATRACE_COUNTER("PCRSCR", pts); system_time = pts; } EXPORT_SYMBOL(timestamp_pcrscr_set); @@ -210,6 +212,7 @@ void timestamp_pcrscr_inc(s32 inc) inc = inc * timestamp_inc_factor / PLL_FACTOR; #endif system_time += inc + system_time_inc_adj; + ATRACE_COUNTER("PCRSCR", system_time); } } EXPORT_SYMBOL(timestamp_pcrscr_inc); @@ -234,6 +237,7 @@ void timestamp_pcrscr_inc_scale(s32 inc, u32 base) system_time++; system_time_scale_remainder -= system_time_scale_base; } + ATRACE_COUNTER("PCRSCR", system_time); } } EXPORT_SYMBOL(timestamp_pcrscr_inc_scale); diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 64552dc303a8..a83e10968de5 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -49,6 +49,7 @@ #include #include #include "video_priv.h" +#include #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) #include @@ -3552,8 +3553,10 @@ static u64 func_div(u64 number, u32 divid) return tmp; } -static void vsync_toggle_frame(struct vframe_s *vf) +static void vsync_toggle_frame(struct vframe_s *vf, int line) { + static u32 last_pts; + u32 diff_pts; u32 first_picture = 0; unsigned long flags = 0; bool vf_with_el = false; @@ -3561,8 +3564,18 @@ static void vsync_toggle_frame(struct vframe_s *vf) long long *clk_array; bool is_mvc = false; + ATRACE_COUNTER(__func__, line); if (vf == NULL) return; + ATRACE_COUNTER("vsync_toggle_frame_pts", vf->pts); + + diff_pts = vf->pts - last_pts; + if (last_pts && diff_pts < 90000) + ATRACE_COUNTER("vsync_toggle_frame_inc", diff_pts); + else + ATRACE_COUNTER("vsync_toggle_frame_inc", 0); /* discontinue */ + last_pts = vf->pts; + frame_count++; toggle_count++; @@ -3645,6 +3658,7 @@ static void vsync_toggle_frame(struct vframe_s *vf) if ((vf->width == 0) && (vf->height == 0)) { amlog_level(LOG_LEVEL_ERROR, "Video: invalid frame dimension\n"); + ATRACE_COUNTER(__func__, __LINE__); return; } @@ -3678,6 +3692,7 @@ static void vsync_toggle_frame(struct vframe_s *vf) } } video_vf_put(vf); + ATRACE_COUNTER(__func__, __LINE__); return; } } @@ -4072,6 +4087,7 @@ static void vsync_toggle_frame(struct vframe_s *vf) } if (stop_update) frame_par_ready_to_set = 0; + ATRACE_COUNTER(__func__, 0); } static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) @@ -6576,7 +6592,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) cur_index; } } - vsync_toggle_frame(cur_dispbuf); + vsync_toggle_frame(cur_dispbuf, __LINE__); } else video_property_changed = 0; } else { @@ -6589,11 +6605,12 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) /* setting video display property in underflow mode */ if ((!vf) && cur_dispbuf && (video_property_changed)) - vsync_toggle_frame(cur_dispbuf); + vsync_toggle_frame(cur_dispbuf, __LINE__); /*debug info for skip & repeate vframe case*/ if (!vf) { underflow++; + ATRACE_COUNTER("underflow", 1); if (video_dbg_vf&(1<<0)) dump_vframe_status("vdin0"); if (video_dbg_vf&(1<<1)) @@ -6604,6 +6621,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) dump_vframe_status("ppmgr"); if (video_dbg_vf&(1<<4)) dump_vdin_reg(); + } else { + ATRACE_COUNTER("underflow", 0); } video_get_vf_cnt = 0; if (platform_type == 1) { @@ -6613,6 +6632,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } while (vf) { if (vpts_expire(cur_dispbuf, vf, toggle_cnt) || show_nosync) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); if (debug_flag & DEBUG_FLAG_PTS_TRACE) pr_info("vpts = 0x%x, c.dur=0x%x, n.pts=0x%x, scr = 0x%x, pcr-pts-diff=%d, ptstrace=%d\n", timestamp_vpts_get(), @@ -6662,8 +6682,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) hdmiin_frame_check_cnt = 0; vf = video_vf_get(); - if (!vf) + if (!vf) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); break; + } if (debug_flag & DEBUG_FLAG_LATENCY) { vf->ready_clock[2] = sched_clock(); pr_info("video get latency %lld ms vdin put latency %lld ms. first %lld ms.\n", @@ -6671,8 +6693,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) func_div(vf->ready_clock[1], 1000), func_div(vf->ready_clock[0], 1000)); } - if (video_vf_dirty_put(vf)) + if (video_vf_dirty_put(vf)) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); break; + } if (vf && hdmiin_frame_check && (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) && video_vf_disp_mode_check(vf)) @@ -6690,7 +6714,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) video_3d_format = vf->trans_fmt; } } - vsync_toggle_frame(vf); + vsync_toggle_frame(vf, __LINE__); toggle_frame = vf; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (is_dolby_vision_enable()) { @@ -6737,6 +6761,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) if (video_get_vf_cnt >= 2) video_drop_vf_cnt++; } else { + ATRACE_COUNTER(MODULE_NAME, __LINE__); /* check if current frame's duration has expired, *in this example * it compares current frame display duration @@ -6748,6 +6773,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) * The playback can be smoother than previous method. */ if (slowsync_repeat_enable) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); if (duration_expire (cur_dispbuf, vf, frame_repeat_count * vsync_pts_inc) @@ -6779,9 +6805,12 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) break; #endif vf = video_vf_get(); - if (!vf) + if (!vf) { + ATRACE_COUNTER(MODULE_NAME, + __LINE__); break; - vsync_toggle_frame(vf); + } + vsync_toggle_frame(vf, __LINE__); toggle_frame = vf; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (is_dolby_vision_enable()) @@ -6814,9 +6843,11 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) if (blackout | force_blackout) { if (cur_dispbuf != &vf_local) vsync_toggle_frame( - cur_dispbuf); + cur_dispbuf, + __LINE__); } else - vsync_toggle_frame(cur_dispbuf); + vsync_toggle_frame(cur_dispbuf, + __LINE__); if (is_dolby_vision_enable()) { pause_vf = cur_dispbuf; video_pause_global = 1; diff --git a/include/trace/events/meson_atrace.h b/include/trace/events/meson_atrace.h index 935ac94c70ec..96d5eea9f96d 100644 --- a/include/trace/events/meson_atrace.h +++ b/include/trace/events/meson_atrace.h @@ -66,13 +66,18 @@ TRACE_EVENT(tracing_mark_write, print_flags_delim(__entry->flags), __get_str(name), __entry->value) ); - +#ifdef CONFIG_AMLOGIC_DEBUG_ATRACE #define ATRACE_COUNTER(name, value) \ trace_tracing_mark_write(name, (1 << KERNEL_ATRACE_COUNTER), value) #define ATRACE_BEGIN(name) \ trace_tracing_mark_write(name, (1 << KERNEL_ATRACE_BEGIN), 0) #define ATRACE_END(name) \ trace_tracing_mark_write("", (1 << KERNEL_ATRACE_END), 1) +#else +#define ATRACE_COUNTER(name, value) +#define ATRACE_BEGIN(name) +#define ATRACE_END(name) +#endif #endif /* _TRACE_MESON_BASE_H */ From 6f6381b16e71847197c342cff1ce727e8186d13f Mon Sep 17 00:00:00 2001 From: Matthew Shyu Date: Mon, 17 Dec 2018 16:37:19 +0800 Subject: [PATCH 0315/1060] crypto: fix and enable aes dma on G12B [1/1] PD# SWPL-4823 Problem: 1. After stack optimization, stack memory cannot be mapped as dma buffers and thus causing crypto dma failed to generate correct result. 2. crypto dma was not enabled on G12B Solution: 1. Move key_iv buffer from stack to memory provided by kzalloc 2. Enable crypto dma on G12B 3. Replace module_param with debugfs 4. Replace pr_err with dev_err Verify: verified on G12B Change-Id: I6de682e3d1fc141f8c6179c7d91f9b4bff165eae Signed-off-by: Matthew Shyu Signed-off-by: Mingyen Hung --- .../devicetree/bindings/crypto/aml-crypto.txt | 47 +-- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 6 + arch/arm/boot/dts/amlogic/mesong12b.dtsi | 23 ++ arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 6 + arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 23 ++ drivers/amlogic/crypto/aml-aes-dma.c | 78 ++-- drivers/amlogic/crypto/aml-crypto-dma.c | 2 - drivers/amlogic/crypto/aml-crypto-dma.h | 11 +- drivers/amlogic/crypto/aml-dma.c | 46 ++- drivers/amlogic/crypto/aml-sha-dma.c | 36 +- drivers/amlogic/crypto/aml-tdes-dma.c | 374 +++++++++++++----- 11 files changed, 448 insertions(+), 204 deletions(-) diff --git a/Documentation/devicetree/bindings/crypto/aml-crypto.txt b/Documentation/devicetree/bindings/crypto/aml-crypto.txt index bf76d17212b8..4d1cc941b76c 100644 --- a/Documentation/devicetree/bindings/crypto/aml-crypto.txt +++ b/Documentation/devicetree/bindings/crypto/aml-crypto.txt @@ -2,10 +2,12 @@ These are the HW cryptographic accelerators found on Amlogic products. +*For S805 series and S905 series + * Advanced Encryption Standard (AES) Required properties: -- compatible : Should be "amlogic,aes" for aes-128/192/256 or "amlogic,aes_g12a_dma" for aes-128/256 +- compatible : Should be "amlogic,aes" for aes-128/192/256 - dev_name : Should be "aml_aes" - interrupts: Should contain the IRQ line for the AES. - resets: Should contain the clock to enable the module @@ -25,10 +27,10 @@ aml_aes{ Required properties: - compatible : Should be "amlogic,des,tdes". -- dev_name : Should be "aml_aes" +- dev_name : Should be "aml_tdes" - interrupts: Should contain the IRQ line for the TDES. - resets: Should contain the clock to enable the module -- reg: Should contain the base address of regs +- reg: Should contain the base address of regs Example: aml_tdes{ @@ -40,29 +42,16 @@ aml_tdes{ 0x0 0xda832000 0x0 0xe4>; }; -* Secure Hash Algorithm (SHA1/SHA224/SHA256) +******************************************************************************** -Required properties: -- compatible : Should be "amlogic,sha". -- dev_name : Should be "aml_sha" -- interrupts: Should contain the IRQ line for the SHA. -- resets: Should contain the clock to enable the module -- reg: Should contain the base address of regs +* For S905X series and beyond +* S905X series use gxl +* T962X series use txlx +* S905X2 series use g12a -Example: -aml_sha{ - compatible = "amlogic,sha"; - dev_name = "aml_sha"; - interrupts = <0 36 1>; - resets = <&clock GCLK_IDX_BLK_MOV>; - reg = <0x0 0xc8832000 0x0 0x2c4 - 0x0 0xda832000 0x0 0xe4>; -}; - -* New DMA for GXL and beyond * Dma engine for crypto operations Required properties: -- compatible : Should be "amlogic,aml_gxl_dma" or "amlogic,aml_txlx_dma". +- compatible : Should be "amlogic,aml_gxl_dma" or "amlogic,aml_txlx_dma" - reg: Should contain the base address of regs - interrupts: Should contain the IRQ line for DMA. @@ -76,8 +65,9 @@ aml_dma { * Advanced Encryption Standard (AES) Required properties: -- compatible : Should be "amlogic,aes". -- dev_name : Should be "aml_aes" +- compatible : Should be "amlogic,aes_dma" for aes-128/192/256 + or "amlogic,aes_g12a_dma" for aes-128/256 +- dev_name : Should be "aml_aes_dma" Example: aml_aes{ @@ -89,8 +79,9 @@ aml_aes{ * Triple Data Encryption Standard (Triple DES) Required properties: -- compatible : Should be "amlogic,des,tdes". -- dev_name : Should be "aml_aes" +- compatible : Should be "amlogic,des_dma,tdes_dma" for gxl + or "amlogic,tdes_dma" for other series. +- dev_name : Should be "aml_tdes_dma" Example: aml_tdes{ @@ -100,8 +91,8 @@ aml_tdes{ * Secure Hash Algorithm (SHA1/SHA224/SHA256/HMAC) Required properties: -- compatible : Should be "amlogic,sha". -- dev_name : Should be "aml_sha" +- compatible : Should be "amlogic,sha_dma". +- dev_name : Should be "aml_sha_dma" Example: aml_sha{ diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 3f6f80ed1cb3..f2b8e93da485 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1816,6 +1816,12 @@ dev_name = "aml_sha_dma"; status = "okay"; }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; }; rng { diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 6fc9d3491594..7c1b55107412 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -863,6 +863,29 @@ }; };/* end of audiobus*/ + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; + }; }; /* end of soc*/ remote:rc@0xff808040 { diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 1d540f503002..4e0f399d6005 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -1826,6 +1826,12 @@ dev_name = "aml_sha_dma"; status = "okay"; }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; }; rng { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 683eb194c411..fa13945a3d77 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -873,6 +873,29 @@ }; };/* end of audiobus*/ + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0x0 0xff63e000 0x0 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; + }; }; /* end of soc*/ remote:rc@0xff808040 { diff --git a/drivers/amlogic/crypto/aml-aes-dma.c b/drivers/amlogic/crypto/aml-aes-dma.c index b7ff8056ea37..6182b619f891 100644 --- a/drivers/amlogic/crypto/aml-aes-dma.c +++ b/drivers/amlogic/crypto/aml-aes-dma.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include #include "aml-crypto-dma.h" @@ -135,14 +135,18 @@ static struct aml_aes_drv aml_aes = { static int set_aes_key_iv(struct aml_aes_dev *dd, u32 *key, uint32_t keylen, u32 *iv, uint8_t swap) { + struct device *dev = dd->dev; struct dma_dsc *dsc = dd->descriptor; - uint32_t key_iv[12]; + uint32_t *key_iv = kzalloc(DMA_KEY_IV_BUF_SIZE, GFP_ATOMIC); uint32_t *piv = key_iv + 8; int32_t len = keylen; dma_addr_t dma_addr_key = 0; uint32_t i = 0; - memset(key_iv, 0, sizeof(key_iv)); + if (!key_iv) { + dev_err(dev, "error allocating key_iv buffer\n"); + return -EINVAL; + } memcpy(key_iv, key, keylen); if (iv) { if (swap) { @@ -153,17 +157,16 @@ static int set_aes_key_iv(struct aml_aes_dev *dd, u32 *key, } else { memcpy(piv, iv, 16); } - len = 48; /* full key storage */ } - if (!len) - return -EPERM; + len = DMA_KEY_IV_BUF_SIZE; /* full key storage */ dma_addr_key = dma_map_single(dd->dev, key_iv, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dma_addr_key)) { - dev_err(dd->dev, "error mapping dma_addr_key\n"); + dev_err(dev, "error mapping dma_addr_key\n"); + kfree(key_iv); return -EINVAL; } @@ -189,8 +192,9 @@ static int set_aes_key_iv(struct aml_aes_dev *dd, u32 *key, ; aml_write_crypto_reg(dd->status, 0xf); dma_unmap_single(dd->dev, dma_addr_key, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); + kfree(key_iv); return 0; } @@ -228,6 +232,7 @@ static size_t aml_aes_sg_copy(struct scatterlist **sg, size_t *offset, static size_t aml_aes_sg_dma(struct aml_aes_dev *dd, struct dma_dsc *dsc, uint32_t *nents, size_t total) { + struct device *dev = dd->dev; size_t count = 0; size_t process = 0; size_t count_total = 0; @@ -253,14 +258,14 @@ static size_t aml_aes_sg_dma(struct aml_aes_dev *dd, struct dma_dsc *dsc, if (dd->in_sg != dd->out_sg) { err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); + dev_err(dev, "dma_map_sg() error\n"); return 0; } err = dma_map_sg(dd->dev, dd->out_sg, *nents, DMA_FROM_DEVICE); if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); + dev_err(dev, "dma_map_sg() error\n"); dma_unmap_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); return 0; @@ -269,7 +274,7 @@ static size_t aml_aes_sg_dma(struct aml_aes_dev *dd, struct dma_dsc *dsc, err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_BIDIRECTIONAL); if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); + dev_err(dev, "dma_map_sg() error\n"); return 0; } dma_sync_sg_for_device(dd->dev, dd->in_sg, @@ -465,6 +470,7 @@ static int aml_aes_write_ctrl(struct aml_aes_dev *dd) static int aml_aes_handle_queue(struct aml_aes_dev *dd, struct ablkcipher_request *req) { + struct device *dev = dd->dev; struct crypto_async_request *async_req, *backlog; struct aml_aes_ctx *ctx; struct aml_aes_reqctx *rctx; @@ -516,7 +522,7 @@ static int aml_aes_handle_queue(struct aml_aes_dev *dd, (dd->flags & AES_FLAGS_CTR)) err = aml_aes_crypt_dma_start(dd); else { - pr_err("size %zd is not multiple of %d", + dev_err(dev, "size %zd is not multiple of %d", dd->total, AML_AES_DMA_THRESHOLD); err = -EINVAL; } @@ -532,6 +538,7 @@ static int aml_aes_handle_queue(struct aml_aes_dev *dd, static int aml_aes_crypt_dma_stop(struct aml_aes_dev *dd) { + struct device *dev = dd->dev; int err = -EINVAL; size_t count; @@ -567,7 +574,8 @@ static int aml_aes_crypt_dma_stop(struct aml_aes_dev *dd) dd->dma_size, 1); if (count != dd->dma_size) { err = -EINVAL; - pr_err("not all data converted: %zu\n", count); + dev_err(dev, "not all data converted: %zu\n", + count); } /* install IV for CBC */ if (dd->flags & AES_FLAGS_CBC) { @@ -584,6 +592,7 @@ static int aml_aes_crypt_dma_stop(struct aml_aes_dev *dd) static int aml_aes_buff_init(struct aml_aes_dev *dd) { + struct device *dev = dd->dev; int err = -ENOMEM; dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0); @@ -593,7 +602,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) dd->buflen &= ~(AES_BLOCK_SIZE - 1); if (!dd->buf_in || !dd->buf_out || !dd->descriptor) { - dev_err(dd->dev, "unable to alloc pages.\n"); + dev_err(dev, "unable to alloc pages.\n"); goto err_alloc; } @@ -601,7 +610,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_in; } @@ -609,7 +618,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen, DMA_FROM_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_out; } @@ -618,7 +627,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) PAGE_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_descript_tab)) { - dev_err(dd->dev, "dma descriptor error\n"); + dev_err(dev, "dma descriptor error\n"); err = -EINVAL; goto err_map_descriptor; } @@ -638,7 +647,7 @@ err_map_in: free_page((uintptr_t)dd->descriptor); err_alloc: if (err) - pr_err("error: %d\n", err); + dev_err(dev, "error: %d\n", err); return err; } @@ -911,7 +920,6 @@ static struct crypto_alg aes_lite_algs[] = { .cra_u.ablkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, .setkey = aml_aes_lite_setkey, .encrypt = aml_aes_ecb_encrypt, .decrypt = aml_aes_ecb_decrypt, @@ -997,6 +1005,7 @@ static void aml_aes_queue_task(unsigned long data) static void aml_aes_done_task(unsigned long data) { struct aml_aes_dev *dd = (struct aml_aes_dev *) data; + struct device *dev = dd->dev; int err; err = aml_aes_crypt_dma_stop(dd); @@ -1014,7 +1023,7 @@ static void aml_aes_done_task(unsigned long data) dd->in_sg = sg_next(dd->in_sg); dd->out_sg = sg_next(dd->out_sg); if (!dd->in_sg || !dd->out_sg) { - pr_err("aml-aes: sg invalid\n"); + dev_err(dev, "aml-aes: sg invalid\n"); err = -EINVAL; break; } @@ -1034,11 +1043,12 @@ static void aml_aes_done_task(unsigned long data) static irqreturn_t aml_aes_irq(int irq, void *dev_id) { struct aml_aes_dev *aes_dd = dev_id; + struct device *dev = aes_dd->dev; uint8_t status = aml_read_crypto_reg(aes_dd->status); if (status) { if (status == 0x1) - pr_err("irq overwrite\n"); + dev_err(dev, "irq overwrite\n"); if (aes_dd->dma->dma_busy == DMA_FLAG_MAY_OCCUPY) return IRQ_HANDLED; if ((aes_dd->flags & AES_FLAGS_DMA) && @@ -1079,7 +1089,7 @@ static int aml_aes_register_algs(struct aml_aes_dev *dd, err_aes_algs: for (j = 0; j < i; j++) - crypto_unregister_alg(&aes_algs[j]); + crypto_unregister_alg(&(aes_info->algs[j])); return err; } @@ -1092,7 +1102,7 @@ static int aml_aes_probe(struct platform_device *pdev) int err = -EPERM; const struct aml_aes_info *aes_info = NULL; - aes_dd = kzalloc(sizeof(struct aml_aes_dev), GFP_KERNEL); + aes_dd = devm_kzalloc(dev, sizeof(struct aml_aes_dev), GFP_KERNEL); if (aes_dd == NULL) { err = -ENOMEM; goto aes_dd_err; @@ -1100,9 +1110,8 @@ static int aml_aes_probe(struct platform_device *pdev) match = of_match_device(aml_aes_dt_match, &pdev->dev); if (!match) { - pr_err("%s: cannot find match dt\n", __func__); + dev_err(dev, "%s: cannot find match dt\n", __func__); err = -EINVAL; - kfree(aes_dd); goto aes_dd_err; } aes_info = match->data; @@ -1121,8 +1130,8 @@ static int aml_aes_probe(struct platform_device *pdev) (unsigned long)aes_dd); crypto_init_queue(&aes_dd->queue, AML_AES_QUEUE_LENGTH); - err = request_irq(aes_dd->irq, aml_aes_irq, IRQF_SHARED, "aml-aes", - aes_dd); + err = devm_request_irq(dev, aes_dd->irq, aml_aes_irq, IRQF_SHARED, + "aml-aes", aes_dd); if (err) { dev_err(dev, "unable to request aes irq.\n"); goto aes_irq_err; @@ -1154,13 +1163,9 @@ err_algs: spin_unlock(&aml_aes.lock); aml_aes_buff_cleanup(aes_dd); err_aes_buff: - free_irq(aes_dd->irq, aes_dd); aes_irq_err: - tasklet_kill(&aes_dd->done_task); tasklet_kill(&aes_dd->queue_task); - kfree(aes_dd); - aes_dd = NULL; aes_dd_err: dev_err(dev, "initialization failed.\n"); @@ -1169,6 +1174,7 @@ aes_dd_err: static int aml_aes_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; static struct aml_aes_dev *aes_dd; const struct of_device_id *match; const struct aml_aes_info *aes_info = NULL; @@ -1178,7 +1184,7 @@ static int aml_aes_remove(struct platform_device *pdev) return -ENODEV; match = of_match_device(aml_aes_dt_match, &pdev->dev); if (!match) { - pr_err("%s: cannot find match dt\n", __func__); + dev_err(dev, "%s: cannot find match dt\n", __func__); return -EINVAL; } aes_info = match->data; @@ -1191,12 +1197,6 @@ static int aml_aes_remove(struct platform_device *pdev) tasklet_kill(&aes_dd->done_task); tasklet_kill(&aes_dd->queue_task); - if (aes_dd->irq > 0) - free_irq(aes_dd->irq, aes_dd); - - kfree(aes_dd); - aes_dd = NULL; - return 0; } diff --git a/drivers/amlogic/crypto/aml-crypto-dma.c b/drivers/amlogic/crypto/aml-crypto-dma.c index 0412b75d8eeb..03b3b05f0673 100644 --- a/drivers/amlogic/crypto/aml-crypto-dma.c +++ b/drivers/amlogic/crypto/aml-crypto-dma.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include #include "aml-crypto-dma.h" u32 swap_ulong32(u32 val) diff --git a/drivers/amlogic/crypto/aml-crypto-dma.h b/drivers/amlogic/crypto/aml-crypto-dma.h index 48e0a4abd67f..12ab5d9ca4da 100644 --- a/drivers/amlogic/crypto/aml-crypto-dma.h +++ b/drivers/amlogic/crypto/aml-crypto-dma.h @@ -19,8 +19,6 @@ #define _AML_CRYPTO_H_ #include -/* #define CRYPTO_DEBUG */ - /* Reserved 4096 bytes and table is 12 bytes each */ #define MAX_NUM_TABLES 341 @@ -117,6 +115,7 @@ struct dma_dsc { #define DMA_FLAG_AES_IN_USE BIT(2) #define DMA_FLAG_SHA_IN_USE BIT(3) +#define DMA_KEY_IV_BUF_SIZE (48) struct aml_dma_dev { spinlock_t dma_lock; uint32_t thread; @@ -136,17 +135,13 @@ u32 get_dma_sts0_offset(void); extern void __iomem *cryptoreg; -extern int debug; -#ifndef CRYPTO_DEBUG -#define dbgp(level, fmt, arg...) -#else +extern u32 debug; #define dbgp(level, fmt, arg...) \ do { \ - if (likely(debug >= level)) \ + if (likely(debug > level)) \ pr_debug("%s: " fmt, __func__, ## arg);\ else \ pr_info("%s: " fmt, __func__, ## arg); \ } while (0) #endif -#endif diff --git a/drivers/amlogic/crypto/aml-dma.c b/drivers/amlogic/crypto/aml-dma.c index 9e74d0f24594..463716465f7e 100644 --- a/drivers/amlogic/crypto/aml-dma.c +++ b/drivers/amlogic/crypto/aml-dma.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -42,10 +43,8 @@ #include #include "aml-crypto-dma.h" -int debug = 2; -#ifdef CRYPTO_DEBUG -module_param(debug, int, 0644); -#endif +static struct dentry *aml_dma_debug_dent; +u32 debug = 3; void __iomem *cryptoreg; @@ -78,6 +77,27 @@ MODULE_DEVICE_TABLE(of, aml_dma_dt_match); #define aml_aes_dt_match NULL #endif +static int aml_dma_init_dbgfs(struct device *dev) +{ + struct dentry *file = NULL; + + if (!aml_dma_debug_dent) { + aml_dma_debug_dent = debugfs_create_dir("aml_dma", NULL); + if (!aml_dma_debug_dent) { + dev_err(dev, "can not create debugfs directory\n"); + return -ENOMEM; + } + file = debugfs_create_u32("debug", 0644, + aml_dma_debug_dent, &debug); + if (!file) { + dev_err(dev, "can not create entry in debugfs directory\n"); + return -ENOMEM; + } + } + return 0; +} + + static int aml_dma_probe(struct platform_device *pdev) { struct aml_dma_dev *dma_dd; @@ -89,7 +109,7 @@ static int aml_dma_probe(struct platform_device *pdev) int err = -EPERM; const struct meson_dma_data *priv_data; - dma_dd = kzalloc(sizeof(struct aml_dma_dev), GFP_KERNEL); + dma_dd = devm_kzalloc(dev, sizeof(struct aml_dma_dev), GFP_KERNEL); if (dma_dd == NULL) { err = -ENOMEM; goto dma_err; @@ -106,8 +126,7 @@ static int aml_dma_probe(struct platform_device *pdev) dev_err(dev, "error to get normal IORESOURCE_MEM.\n"); goto dma_err; } else { - cryptoreg = ioremap(res_base->start, - resource_size(res_base)); + cryptoreg = devm_ioremap_resource(dev, res_base); if (!cryptoreg) { dev_err(dev, "failed to remap crypto reg\n"); goto dma_err; @@ -118,17 +137,21 @@ static int aml_dma_probe(struct platform_device *pdev) dma_dd->irq = res_irq->start; dma_dd->dma_busy = 0; platform_set_drvdata(pdev, dma_dd); + + err = aml_dma_init_dbgfs(dev); + if (err) + goto dma_err; + dev_info(dev, "Aml dma\n"); err = of_platform_populate(np, NULL, NULL, dev); - if (err != 0) - iounmap(cryptoreg); + goto dma_err; return err; dma_err: - kfree(dma_dd); + debugfs_remove_recursive(aml_dma_debug_dent); dev_err(dev, "initialization failed.\n"); return err; @@ -142,8 +165,7 @@ static int aml_dma_remove(struct platform_device *pdev) if (!dma_dd) return -ENODEV; - iounmap(cryptoreg); - kfree(dma_dd); + debugfs_remove_recursive(aml_dma_debug_dent); return 0; } diff --git a/drivers/amlogic/crypto/aml-sha-dma.c b/drivers/amlogic/crypto/aml-sha-dma.c index fde19f1322c6..3a39ef2609c9 100644 --- a/drivers/amlogic/crypto/aml-sha-dma.c +++ b/drivers/amlogic/crypto/aml-sha-dma.c @@ -40,7 +40,6 @@ #include #include #include -#include #include "aml-crypto-dma.h" /* SHA flags */ @@ -459,9 +458,7 @@ static int aml_sha_update_dma_stop(struct aml_sha_dev *dd) static int aml_sha_update_req(struct aml_sha_dev *dd, struct ahash_request *req) { int err; -#ifdef CRYPTO_DEBUG struct aml_sha_reqctx *ctx = ahash_request_ctx(req); -#endif dbgp(1, "update_req: ctx: %p, total: %u, digcnt: 0x%llx 0x%llx\n", ctx, ctx->total, ctx->digcnt[1], ctx->digcnt[0]); @@ -474,9 +471,7 @@ static int aml_sha_update_req(struct aml_sha_dev *dd, struct ahash_request *req) static int aml_sha_final_req(struct aml_sha_dev *dd, struct ahash_request *req) { int err = 0; -#ifdef CRYPTO_DEBUG struct aml_sha_reqctx *ctx = ahash_request_ctx(req); -#endif err = aml_sha_update_dma_slow(dd, req); @@ -1092,7 +1087,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "sha1", .cra_driver_name = "aml-sha1", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aml_sha_ctx), @@ -1118,7 +1113,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "sha256", .cra_driver_name = "aml-sha256", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aml_sha_ctx), @@ -1144,7 +1139,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "sha224", .cra_driver_name = "aml-sha224", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aml_sha_ctx), @@ -1171,7 +1166,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "hmac(sha1)", .cra_driver_name = "aml-hmac-sha1", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, @@ -1199,7 +1194,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "hmac(sha224)", .cra_driver_name = "aml-hmac-sha224", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA224_BLOCK_SIZE, @@ -1227,7 +1222,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "hmac(sha256)", .cra_driver_name = "aml-hmac-sha256", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA256_BLOCK_SIZE, @@ -1285,7 +1280,7 @@ static irqreturn_t aml_sha_irq(int irq, void *dev_id) if (status) { if (status == 0x1) - pr_err("irq overwrite\n"); + dev_err(sha_dd->dev, "irq overwrite\n"); if (sha_dd->dma->dma_busy == DMA_FLAG_MAY_OCCUPY) return IRQ_HANDLED; if (sha_dd->flags & SHA_FLAGS_DMA_ACTIVE && @@ -1335,7 +1330,7 @@ static int aml_sha_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int err = -EPERM; - sha_dd = kzalloc(sizeof(struct aml_sha_dev), GFP_KERNEL); + sha_dd = devm_kzalloc(dev, sizeof(struct aml_sha_dev), GFP_KERNEL); if (sha_dd == NULL) { err = -ENOMEM; goto sha_dd_err; @@ -1355,8 +1350,8 @@ static int aml_sha_probe(struct platform_device *pdev) (unsigned long)sha_dd); crypto_init_queue(&sha_dd->queue, AML_SHA_QUEUE_LENGTH); - err = request_irq(sha_dd->irq, aml_sha_irq, IRQF_SHARED, "aml-sha", - sha_dd); + err = devm_request_irq(dev, sha_dd->irq, aml_sha_irq, IRQF_SHARED, + "aml-sha", sha_dd); if (err) { dev_err(dev, "unable to request sha irq.\n"); goto res_err; @@ -1364,7 +1359,6 @@ static int aml_sha_probe(struct platform_device *pdev) aml_sha_hw_init(sha_dd); - spin_lock(&aml_sha.lock); list_add_tail(&sha_dd->list, &aml_sha.dev_list); spin_unlock(&aml_sha.lock); @@ -1381,12 +1375,8 @@ err_algs: spin_lock(&aml_sha.lock); list_del(&sha_dd->list); spin_unlock(&aml_sha.lock); - - free_irq(sha_dd->irq, sha_dd); res_err: tasklet_kill(&sha_dd->done_task); - kfree(sha_dd); - sha_dd = NULL; sha_dd_err: dev_err(dev, "initialization failed.\n"); @@ -1408,12 +1398,6 @@ static int aml_sha_remove(struct platform_device *pdev) tasklet_kill(&sha_dd->done_task); - if (sha_dd->irq >= 0) - free_irq(sha_dd->irq, sha_dd); - - kfree(sha_dd); - sha_dd = NULL; - return 0; } diff --git a/drivers/amlogic/crypto/aml-tdes-dma.c b/drivers/amlogic/crypto/aml-tdes-dma.c index 99f32ba26663..b2198ccc6977 100644 --- a/drivers/amlogic/crypto/aml-tdes-dma.c +++ b/drivers/amlogic/crypto/aml-tdes-dma.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,8 @@ #include #include #include -#include +//#include +#include #include "aml-crypto-dma.h" /* TDES flags */ @@ -54,6 +56,7 @@ #define AML_TDES_QUEUE_LENGTH 50 +#define SUPPORT_FAST_DMA 0 struct aml_tdes_dev; struct aml_tdes_ctx { @@ -63,6 +66,8 @@ struct aml_tdes_ctx { u32 key[3*DES_KEY_SIZE / sizeof(u32)]; u16 block_size; + struct crypto_skcipher *fallback; + u16 same_key; }; struct aml_tdes_reqctx { @@ -115,6 +120,11 @@ struct aml_tdes_drv { spinlock_t lock; }; +struct aml_tdes_info { + struct crypto_alg *algs; + uint32_t num_algs; +}; + static struct aml_tdes_drv aml_tdes = { .dev_list = LIST_HEAD_INIT(aml_tdes.dev_list), .lock = __SPIN_LOCK_UNLOCKED(aml_tdes.lock), @@ -124,42 +134,43 @@ static int set_tdes_key_iv(struct aml_tdes_dev *dd, u32 *key, u32 keylen, u32 *iv) { struct dma_dsc *dsc = dd->descriptor; - uint32_t key_iv[12]; + struct device *dev = dd->dev; + uint32_t *key_iv = kzalloc(DMA_KEY_IV_BUF_SIZE, GFP_ATOMIC); uint32_t *piv = key_iv + 8; uint32_t len = keylen; - uint32_t processed = 0; dma_addr_t dma_addr_key; uint32_t i = 0; - memset(key_iv, 0, sizeof(key_iv)); + if (!key_iv) { + dev_err(dev, "error allocating key_iv buffer\n"); + return -EINVAL; + } memcpy(key_iv, key, keylen); if (iv) { memcpy(piv, iv, 8); - len = 48; /* full key storage */ } - if (!len) - return -EPERM; + len = DMA_KEY_IV_BUF_SIZE; /* full key storage */ dma_addr_key = dma_map_single(dd->dev, key_iv, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dma_addr_key)) { - dev_err(dd->dev, "error mapping dma_addr_key\n"); + dev_err(dev, "error mapping dma_addr_key\n"); + kfree(key_iv); return -EINVAL; } while (len > 0) { - processed = len > 16 ? 16 : len; dsc[i].src_addr = (uint32_t)dma_addr_key + i * 16; dsc[i].tgt_addr = i * 16; dsc[i].dsc_cfg.d32 = 0; - dsc[i].dsc_cfg.b.length = processed; + dsc[i].dsc_cfg.b.length = len > 16 ? 16 : len; dsc[i].dsc_cfg.b.mode = MODE_KEY; dsc[i].dsc_cfg.b.eoc = 0; dsc[i].dsc_cfg.b.owner = 1; i++; - len -= processed; + len -= 16; } dsc[i - 1].dsc_cfg.b.eoc = 1; @@ -172,8 +183,9 @@ static int set_tdes_key_iv(struct aml_tdes_dev *dd, ; aml_write_crypto_reg(dd->status, 0xf); dma_unmap_single(dd->dev, dma_addr_key, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); + kfree(key_iv); return 0; } @@ -209,11 +221,15 @@ static size_t aml_tdes_sg_copy(struct scatterlist **sg, size_t *offset, return off; } +#if SUPPORT_FAST_DMA static size_t aml_tdes_sg_dma(struct aml_tdes_dev *dd, struct dma_dsc *dsc, uint32_t *nents, size_t total) { + struct device *dev = dd->dev; size_t count = 0; size_t process = 0; + size_t count_total = 0; + size_t count_sg = 0; uint32_t i = 0; int err = 0; struct scatterlist *in_sg = dd->in_sg; @@ -221,44 +237,62 @@ static size_t aml_tdes_sg_dma(struct aml_tdes_dev *dd, struct dma_dsc *dsc, dma_addr_t addr_in, addr_out; while (total && in_sg && out_sg && (in_sg->length == out_sg->length) + && IS_ALIGNED(in_sg->length, DES_BLOCK_SIZE) && *nents < MAX_NUM_TABLES) { process = min_t(unsigned int, total, in_sg->length); count += process; *nents += 1; + if (process != in_sg->length) + dd->out_offset = dd->in_offset = in_sg->length; total -= process; in_sg = sg_next(in_sg); out_sg = sg_next(out_sg); } - err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); - if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); - return 0; - } + if (dd->in_sg != dd->out_sg) { + err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); + if (!err) { + dev_err(dev, "dma_map_sg() error\n"); + return 0; + } - err = dma_map_sg(dd->dev, dd->out_sg, *nents, - DMA_FROM_DEVICE); - if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); - dma_unmap_sg(dd->dev, dd->in_sg, *nents, - DMA_TO_DEVICE); - return 0; + err = dma_map_sg(dd->dev, dd->out_sg, *nents, + DMA_FROM_DEVICE); + if (!err) { + dev_err(dev, "dma_map_sg() error\n"); + dma_unmap_sg(dd->dev, dd->in_sg, *nents, + DMA_TO_DEVICE); + return 0; + } + } else { + err = dma_map_sg(dd->dev, dd->in_sg, *nents, + DMA_BIDIRECTIONAL); + if (!err) { + dev_err(dev, "dma_map_sg() error\n"); + return 0; + } + dma_sync_sg_for_device(dd->dev, dd->in_sg, + *nents, DMA_TO_DEVICE); } in_sg = dd->in_sg; out_sg = dd->out_sg; + count_total = count; for (i = 0; i < *nents; i++) { + count_sg = count_total > sg_dma_len(in_sg) ? + sg_dma_len(in_sg) : count_total; addr_in = sg_dma_address(in_sg); addr_out = sg_dma_address(out_sg); dsc[i].src_addr = (uintptr_t)addr_in; dsc[i].tgt_addr = (uintptr_t)addr_out; dsc[i].dsc_cfg.d32 = 0; - dsc[i].dsc_cfg.b.length = sg_dma_len(in_sg); + dsc[i].dsc_cfg.b.length = count_sg; in_sg = sg_next(in_sg); out_sg = sg_next(out_sg); + count_total -= count_sg; } return count; } - +#endif static struct aml_tdes_dev *aml_tdes_find_dev(struct aml_tdes_ctx *ctx) { struct aml_tdes_dev *tdes_dd = NULL; @@ -362,11 +396,14 @@ static int aml_tdes_crypt_dma_start(struct aml_tdes_dev *dd) dd->fast_nents = 0; } +#if SUPPORT_FAST_DMA if (fast) { count = aml_tdes_sg_dma(dd, dsc, &dd->fast_nents, dd->total); dd->flags |= TDES_FLAGS_FAST; nents = dd->fast_nents; - } else { + } else +#endif + { /* slow dma */ /* use cache buffers */ count = aml_tdes_sg_copy(&dd->in_sg, &dd->in_offset, @@ -472,6 +509,7 @@ static int aml_tdes_handle_queue(struct aml_tdes_dev *dd, static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) { + struct device *dev = dd->dev; int err = -EINVAL; size_t count; @@ -480,10 +518,17 @@ static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) dma_sync_single_for_cpu(dd->dev, dd->dma_descript_tab, PAGE_SIZE, DMA_FROM_DEVICE); if (dd->flags & TDES_FLAGS_FAST) { - dma_unmap_sg(dd->dev, dd->out_sg, + if (dd->in_sg != dd->out_sg) { + dma_unmap_sg(dd->dev, dd->out_sg, dd->fast_nents, DMA_FROM_DEVICE); - dma_unmap_sg(dd->dev, dd->in_sg, + dma_unmap_sg(dd->dev, dd->in_sg, dd->fast_nents, DMA_TO_DEVICE); + } else { + dma_sync_sg_for_cpu(dd->dev, dd->in_sg, + dd->fast_nents, DMA_FROM_DEVICE); + dma_unmap_sg(dd->dev, dd->in_sg, + dd->fast_nents, DMA_BIDIRECTIONAL); + } } else { dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, dd->dma_size, DMA_FROM_DEVICE); @@ -494,7 +539,8 @@ static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) dd->dma_size, 1); if (count != dd->dma_size) { err = -EINVAL; - pr_err("not all data converted: %zu\n", count); + dev_err(dev, "not all data converted: %zu\n", + count); } } dd->flags &= ~TDES_FLAGS_DMA; @@ -506,6 +552,7 @@ static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) static int aml_tdes_buff_init(struct aml_tdes_dev *dd) { + struct device *dev = dd->dev; int err = -ENOMEM; dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0); @@ -515,7 +562,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) dd->buflen &= ~(DES_BLOCK_SIZE - 1); if (!dd->buf_in || !dd->buf_out || !dd->descriptor) { - dev_err(dd->dev, "unable to alloc pages.\n"); + dev_err(dev, "unable to alloc pages.\n"); goto err_alloc; } @@ -523,7 +570,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_in; } @@ -531,7 +578,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen, DMA_FROM_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_out; } @@ -540,7 +587,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) PAGE_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_descript_tab)) { - dev_err(dd->dev, "dma descriptor error\n"); + dev_err(dev, "dma descriptor error\n"); err = -EINVAL; goto err_map_descriptor; } @@ -561,7 +608,7 @@ err_map_in: free_page((uintptr_t)dd->descriptor); err_alloc: if (err) - pr_err("error: %d\n", err); + dev_err(dev, "error: %d\n", err); return err; } @@ -591,6 +638,31 @@ static int aml_tdes_crypt(struct ablkcipher_request *req, unsigned long mode) } ctx->block_size = DES_BLOCK_SIZE; + if (ctx->fallback && ctx->same_key) { + char *__subreq_desc = kzalloc(sizeof(struct skcipher_request) + + crypto_skcipher_reqsize(ctx->fallback), + GFP_ATOMIC); + struct skcipher_request *subreq = (void *)__subreq_desc; + int ret = 0; + + if (!subreq) + return -ENOMEM; + + skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_callback(subreq, req->base.flags, NULL, + NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, + req->nbytes, req->info); + + if (mode & TDES_FLAGS_ENCRYPT) + ret = crypto_skcipher_encrypt(subreq); + else + ret = crypto_skcipher_decrypt(subreq); + + skcipher_request_free(subreq); + return ret; + } + dd = aml_tdes_find_dev(ctx); if (!dd) return -ENODEV; @@ -667,7 +739,10 @@ static int aml_tdes_cbc_decrypt(struct ablkcipher_request *req) static int aml_tdes_cra_init(struct crypto_tfm *tfm) { + struct aml_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + tfm->crt_ablkcipher.reqsize = sizeof(struct aml_tdes_reqctx); + ctx->fallback = NULL; return 0; } @@ -676,7 +751,7 @@ static void aml_tdes_cra_exit(struct crypto_tfm *tfm) { } -static struct crypto_alg des_algs[] = { +static struct crypto_alg des_tdes_algs[] = { { .cra_name = "ecb(des)", .cra_driver_name = "ecb-des-aml", @@ -718,9 +793,6 @@ static struct crypto_alg des_algs[] = { .decrypt = aml_tdes_cbc_decrypt, } }, -}; - -static struct crypto_alg tdes_algs[] = { { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-tdes-aml", @@ -764,6 +836,114 @@ static struct crypto_alg tdes_algs[] = { } }; +static int aml_tdes_lite_cra_init(struct crypto_tfm *tfm) +{ + struct aml_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + const char *alg_name = crypto_tfm_alg_name(tfm); + const u32 flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK; + + tfm->crt_ablkcipher.reqsize = sizeof(struct aml_tdes_reqctx); + + /* Allocate a fallback and abort if it failed. */ + ctx->fallback = crypto_alloc_skcipher(alg_name, 0, + flags); + if (IS_ERR(ctx->fallback)) { + pr_err("aml-tdes: fallback '%s' could not be loaded.\n", + alg_name); + return PTR_ERR(ctx->fallback); + } + + return 0; +} + +static void aml_tdes_lite_cra_exit(struct crypto_tfm *tfm) +{ + struct aml_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + + if (ctx->fallback) + crypto_free_skcipher(ctx->fallback); + + ctx->fallback = NULL; +} + +static int aml_tdes_lite_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct aml_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + int ret = 0; + u64 *tmp = NULL; + + if ((keylen != 2 * DES_KEY_SIZE) && (keylen != 3 * DES_KEY_SIZE)) { + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + tmp = (u64 *)ctx->key; + if (keylen == 2 * DES_KEY_SIZE) + ctx->same_key = !(tmp[0] ^ tmp[1]); + else + ctx->same_key = !((tmp[0] ^ tmp[1]) | (tmp[0] ^ tmp[2])); + + if (ctx->same_key) { + crypto_skcipher_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK); + crypto_skcipher_set_flags(ctx->fallback, tfm->base.crt_flags & + CRYPTO_TFM_REQ_MASK); + ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); + } + + return ret; +} + + +static struct crypto_alg tdes_lite_algs[] = { + { + .cra_name = "ecb(des3_ede)", + .cra_driver_name = "ecb-tdes-lite-aml", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aml_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = aml_tdes_lite_cra_init, + .cra_exit = aml_tdes_lite_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2 * DES_KEY_SIZE, + .max_keysize = 3 * DES_KEY_SIZE, + .setkey = aml_tdes_lite_setkey, + .encrypt = aml_tdes_ecb_encrypt, + .decrypt = aml_tdes_ecb_decrypt, + } + }, + { + .cra_name = "cbc(des3_ede)", + .cra_driver_name = "cbc-tdes-lite-aml", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aml_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = aml_tdes_lite_cra_init, + .cra_exit = aml_tdes_lite_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2 * DES_KEY_SIZE, + .max_keysize = 3 * DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = aml_tdes_lite_setkey, + .encrypt = aml_tdes_cbc_encrypt, + .decrypt = aml_tdes_cbc_decrypt, + } + } +}; + static void aml_tdes_queue_task(unsigned long data) { struct aml_tdes_dev *dd = (struct aml_tdes_dev *)data; @@ -774,6 +954,7 @@ static void aml_tdes_queue_task(unsigned long data) static void aml_tdes_done_task(unsigned long data) { struct aml_tdes_dev *dd = (struct aml_tdes_dev *) data; + struct device *dev = dd->dev; int err; err = aml_tdes_crypt_dma_stop(dd); @@ -790,7 +971,7 @@ static void aml_tdes_done_task(unsigned long data) dd->in_sg = sg_next(dd->in_sg); dd->out_sg = sg_next(dd->out_sg); if (!dd->in_sg || !dd->out_sg) { - pr_err("aml-tdes: sg invalid\n"); + dev_err(dev, "aml-tdes: sg invalid\n"); err = -EINVAL; break; } @@ -810,11 +991,12 @@ static void aml_tdes_done_task(unsigned long data) static irqreturn_t aml_tdes_irq(int irq, void *dev_id) { struct aml_tdes_dev *tdes_dd = dev_id; + struct device *dev = tdes_dd->dev; uint8_t status = aml_read_crypto_reg(tdes_dd->status); if (status) { if (status == 0x1) - pr_err("irq overwrite\n"); + dev_err(dev, "irq overwrite\n"); if (tdes_dd->dma->dma_busy == DMA_FLAG_MAY_OCCUPY) return IRQ_HANDLED; if ((tdes_dd->dma->dma_busy & DMA_FLAG_TDES_IN_USE) && @@ -831,29 +1013,22 @@ static irqreturn_t aml_tdes_irq(int irq, void *dev_id) return IRQ_NONE; } -static void aml_tdes_unregister_algs(struct aml_tdes_dev *dd) +static void aml_tdes_unregister_algs(struct aml_tdes_dev *dd, + const struct aml_tdes_info *tdes_info) { - int i = 0; + int i; - for (; i < ARRAY_SIZE(des_algs); i++) - crypto_unregister_alg(&des_algs[i]); - - for (; i < ARRAY_SIZE(tdes_algs); i++) - crypto_unregister_alg(&tdes_algs[i]); + for (i = 0; i < tdes_info->num_algs; i++) + crypto_unregister_alg(&(tdes_info->algs[i])); } -static int aml_tdes_register_algs(struct aml_tdes_dev *dd) +static int aml_tdes_register_algs(struct aml_tdes_dev *dd, + const struct aml_tdes_info *tdes_info) { - int err = 0, i = 0, j = 0, k = 0; + int err, i, j; - for (; i < ARRAY_SIZE(des_algs); i++) { - err = crypto_register_alg(&des_algs[i]); - if (err) - goto err_des_algs; - } - - for (; k < ARRAY_SIZE(tdes_algs); k++) { - err = crypto_register_alg(&tdes_algs[k]); + for (i = 0; i < tdes_info->num_algs; i++) { + err = crypto_register_alg(&(tdes_info->algs[i])); if (err) goto err_tdes_algs; } @@ -861,28 +1036,58 @@ static int aml_tdes_register_algs(struct aml_tdes_dev *dd) return 0; err_tdes_algs: - for (j = 0; j < k; j++) - crypto_unregister_alg(&tdes_algs[j]); - -err_des_algs: for (j = 0; j < i; j++) - crypto_unregister_alg(&des_algs[j]); + crypto_unregister_alg(&(tdes_info->algs[j])); return err; } +struct aml_tdes_info aml_des_tdes = { + .algs = des_tdes_algs, + .num_algs = ARRAY_SIZE(des_tdes_algs), +}; + +struct aml_tdes_info aml_tdes_lite = { + .algs = tdes_lite_algs, + .num_algs = ARRAY_SIZE(tdes_lite_algs), +}; + +#ifdef CONFIG_OF +static const struct of_device_id aml_tdes_dt_match[] = { + { .compatible = "amlogic,des_dma,tdes_dma", + .data = &aml_des_tdes, + }, + { .compatible = "amlogic,tdes_dma", + .data = &aml_tdes_lite, + }, + {}, +}; +#else +#define aml_tdes_dt_match NULL +#endif + static int aml_tdes_probe(struct platform_device *pdev) { struct aml_tdes_dev *tdes_dd; struct device *dev = &pdev->dev; int err = -EPERM; + const struct of_device_id *match; + const struct aml_tdes_info *tdes_info = NULL; - tdes_dd = kzalloc(sizeof(struct aml_tdes_dev), GFP_KERNEL); + tdes_dd = devm_kzalloc(dev, sizeof(struct aml_tdes_dev), GFP_KERNEL); if (tdes_dd == NULL) { err = -ENOMEM; goto tdes_dd_err; } + match = of_match_device(aml_tdes_dt_match, &pdev->dev); + if (!match) { + dev_err(dev, "%s: cannot find match dt\n", __func__); + err = -EINVAL; + goto tdes_dd_err; + } + + tdes_info = match->data; tdes_dd->dev = dev; tdes_dd->dma = dev_get_drvdata(dev->parent); tdes_dd->thread = tdes_dd->dma->thread; @@ -899,8 +1104,8 @@ static int aml_tdes_probe(struct platform_device *pdev) (unsigned long)tdes_dd); crypto_init_queue(&tdes_dd->queue, AML_TDES_QUEUE_LENGTH); - err = request_irq(tdes_dd->irq, aml_tdes_irq, IRQF_SHARED, "aml-tdes", - tdes_dd); + err = devm_request_irq(dev, tdes_dd->irq, aml_tdes_irq, IRQF_SHARED, + "aml-tdes", tdes_dd); if (err) { dev_err(dev, "unable to request tdes irq.\n"); goto tdes_irq_err; @@ -918,7 +1123,7 @@ static int aml_tdes_probe(struct platform_device *pdev) list_add_tail(&tdes_dd->list, &aml_tdes.dev_list); spin_unlock(&aml_tdes.lock); - err = aml_tdes_register_algs(tdes_dd); + err = aml_tdes_register_algs(tdes_dd, tdes_info); if (err) goto err_algs; @@ -932,13 +1137,9 @@ err_algs: spin_unlock(&aml_tdes.lock); aml_tdes_buff_cleanup(tdes_dd); err_tdes_buff: - free_irq(tdes_dd->irq, tdes_dd); tdes_irq_err: - tasklet_kill(&tdes_dd->done_task); tasklet_kill(&tdes_dd->queue_task); - kfree(tdes_dd); - tdes_dd = NULL; tdes_dd_err: dev_err(dev, "initialization failed.\n"); @@ -948,38 +1149,33 @@ tdes_dd_err: static int aml_tdes_remove(struct platform_device *pdev) { static struct aml_tdes_dev *tdes_dd; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + const struct aml_tdes_info *tdes_info = NULL; tdes_dd = platform_get_drvdata(pdev); if (!tdes_dd) return -ENODEV; + + match = of_match_device(aml_tdes_dt_match, &pdev->dev); + if (!match) { + dev_err(dev, "%s: cannot find match dt\n", __func__); + return -EINVAL; + } + + tdes_info = match->data; spin_lock(&aml_tdes.lock); list_del(&tdes_dd->list); spin_unlock(&aml_tdes.lock); - aml_tdes_unregister_algs(tdes_dd); + aml_tdes_unregister_algs(tdes_dd, tdes_info); tasklet_kill(&tdes_dd->done_task); tasklet_kill(&tdes_dd->queue_task); - if (tdes_dd->irq > 0) - free_irq(tdes_dd->irq, tdes_dd); - - kfree(tdes_dd); - tdes_dd = NULL; - return 0; } -#ifdef CONFIG_OF -static const struct of_device_id aml_tdes_dt_match[] = { - { .compatible = "amlogic,des_dma,tdes_dma", - }, - {}, -}; -#else -#define aml_tdes_dt_match NULL -#endif - static struct platform_driver aml_tdes_driver = { .probe = aml_tdes_probe, .remove = aml_tdes_remove, From c901530fa77c2badd016703a771d65f486db4b7e Mon Sep 17 00:00:00 2001 From: Huan Biao Date: Mon, 4 Mar 2019 13:45:05 +0800 Subject: [PATCH 0316/1060] thermal: cooldev: update cpucore cooldev for multi cluster chip [1/1] PD#SWPL-5366 Problem: g12b cpucore cooling devices hotplug a little core and a big when hot trippoint trigger, need to update cooling devices that hotplug one core one hotstep for big core to little core. Solution: 1.modify cpucore cooling for new solution. 2.modify hotplug core for can hotplug all big core. 3.ipa dts no cluster id, all cpucore is one cooling device dts have cluster id, one cluster is one cooling devices. Verify: test on g12b w400. Change-Id: I3320b007e35e7ac415cf7623f74f0a5153fed9b5 Signed-off-by: Huan Biao --- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 27 +++----------- arch/arm/boot/dts/amlogic/mesong12b_a.dtsi | 27 +++----------- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 25 +++---------- arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 27 +++----------- drivers/amlogic/cpu_hotplug/cpu_hotplug.c | 10 +++--- drivers/amlogic/thermal/cpucore_cooling.c | 38 +++++++++++++++++--- drivers/amlogic/thermal/meson_cooldev.c | 10 +++--- include/linux/amlogic/cpucore_cooling.h | 4 +++ 8 files changed, 67 insertions(+), 101 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 7c1b55107412..44bef6d1e05b 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1610,20 +1610,11 @@ node_name = "cpufreq_cool1"; device_type = "cpufreq"; }; - cpucore_cool_cluster0 { + cpucore_cool_cluster { min_state = <1>; dyn_coeff = <0>; - cluster_id = <0>; gpu_pp = <2>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - cpucore_cool_cluster1 { - min_state = <0>; - dyn_coeff = <0>; - cluster_id = <1>; - gpu_pp = <2>; - node_name = "cpucore_cool1"; + node_name = "cpucore_cool"; device_type = "cpucore"; }; gpufreq_cool { @@ -1649,10 +1640,7 @@ cpufreq_cool1:cpufreq_cool1 { #cooling-cells = <2>; /* min followed by max */ }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool1:cpucore_cool1 { + cpucore_cool:cpucore_cool { #cooling-cells = <2>; /* min followed by max */ }; gpufreq_cool0:gpufreq_cool0 { @@ -1704,14 +1692,9 @@ cooling-device = <&cpufreq_cool1 0 9>; contribution = <1024>; }; - cpucore_cooling_map0 { + cpucore_cooling_map { trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 1>; - contribution = <1024>; - }; - cpucore_cooling_map1 { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool1 0 4>; + cooling-device = <&cpucore_cool 0 5>; contribution = <1024>; }; gpufreq_cooling_map { diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi index 69b03f6bdbd3..2b1a806f56bb 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -1581,20 +1581,11 @@ node_name = "cpufreq_cool1"; device_type = "cpufreq"; }; - cpucore_cool_cluster0 { + cpucore_cool_cluster { min_state = <1>; dyn_coeff = <0>; - cluster_id = <0>; gpu_pp = <2>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - cpucore_cool_cluster1 { - min_state = <0>; - dyn_coeff = <0>; - cluster_id = <1>; - gpu_pp = <2>; - node_name = "cpucore_cool1"; + node_name = "cpucore_cool"; device_type = "cpucore"; }; gpufreq_cool { @@ -1620,10 +1611,7 @@ cpufreq_cool1:cpufreq_cool1 { #cooling-cells = <2>; /* min followed by max */ }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool1:cpucore_cool1 { + cpucore_cool:cpucore_cool { #cooling-cells = <2>; /* min followed by max */ }; gpufreq_cool0:gpufreq_cool0 { @@ -1675,14 +1663,9 @@ cooling-device = <&cpufreq_cool1 0 9>; contribution = <1024>; }; - cpucore_cooling_map0 { + cpucore_cooling_map { trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 1>; - contribution = <1024>; - }; - cpucore_cooling_map1 { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool1 0 4>; + cooling-device = <&cpucore_cool 0 5>; contribution = <1024>; }; gpufreq_cooling_map { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index fa13945a3d77..f3f561f582ae 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1620,20 +1620,11 @@ node_name = "cpufreq_cool1"; device_type = "cpufreq"; }; - cpucore_cool_cluster0 { + cpucore_cool_cluster { min_state = <1>; dyn_coeff = <0>; - cluster_id = <0>; gpu_pp = <2>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - cpucore_cool_cluster1 { - min_state = <0>; - dyn_coeff = <0>; - cluster_id = <1>; - gpu_pp = <2>; - node_name = "cpucore_cool1"; + node_name = "cpucore_cool"; device_type = "cpucore"; }; gpufreq_cool { @@ -1659,10 +1650,7 @@ cpufreq_cool1:cpufreq_cool1 { #cooling-cells = <2>; /* min followed by max */ }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool1:cpucore_cool1 { + cpucore_cool:cpucore_cool { #cooling-cells = <2>; /* min followed by max */ }; gpufreq_cool0:gpufreq_cool0 { @@ -1716,12 +1704,7 @@ }; cpucore_cooling_map0 { trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 1>; - contribution = <1024>; - }; - cpucore_cooling_map1 { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool1 0 4>; + cooling-device = <&cpucore_cool 0 5>; contribution = <1024>; }; gpufreq_cooling_map { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index 283acfe4c325..e6a0ebcdbc03 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -1581,20 +1581,11 @@ node_name = "cpufreq_cool1"; device_type = "cpufreq"; }; - cpucore_cool_cluster0 { + cpucore_cool_cluster { min_state = <1>; dyn_coeff = <0>; - cluster_id = <0>; gpu_pp = <2>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - cpucore_cool_cluster1 { - min_state = <0>; - dyn_coeff = <0>; - cluster_id = <1>; - gpu_pp = <2>; - node_name = "cpucore_cool1"; + node_name = "cpucore_cool"; device_type = "cpucore"; }; gpufreq_cool { @@ -1620,10 +1611,7 @@ cpufreq_cool1:cpufreq_cool1 { #cooling-cells = <2>; /* min followed by max */ }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool1:cpucore_cool1 { + cpucore_cool:cpucore_cool { #cooling-cells = <2>; /* min followed by max */ }; gpufreq_cool0:gpufreq_cool0 { @@ -1675,14 +1663,9 @@ cooling-device = <&cpufreq_cool1 0 9>; contribution = <1024>; }; - cpucore_cooling_map0 { + cpucore_cooling_map { trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 1>; - contribution = <1024>; - }; - cpucore_cooling_map1 { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool1 0 4>; + cooling-device = <&cpucore_cool 0 5>; contribution = <1024>; }; gpufreq_cooling_map { diff --git a/drivers/amlogic/cpu_hotplug/cpu_hotplug.c b/drivers/amlogic/cpu_hotplug/cpu_hotplug.c index 7c260c91e7ca..adf996eef981 100644 --- a/drivers/amlogic/cpu_hotplug/cpu_hotplug.c +++ b/drivers/amlogic/cpu_hotplug/cpu_hotplug.c @@ -97,7 +97,7 @@ void cpu_hotplug_set_max(unsigned int num, int clustr) { unsigned int cpu_online; - if (!num || clustr > hpg.clusters) { + if (clustr > hpg.clusters) { dev_err(NULL, " %s <:%d %d>\n", __func__, num, clustr); return; } @@ -177,7 +177,7 @@ static int __ref cpu_hotplug_thread(void *data) } } else if (flg == CPU_HOTPLUG_UNPLUG) { cnt = 0; - while ((online = cpu_num_online(clustr)) > 1) { + while ((online = cpu_num_online(clustr)) > 0) { if (online <= hpg.gov_num[clustr] && online <= hpg.max_num[clustr]) break; @@ -200,7 +200,8 @@ static int __ref cpu_hotplug_thread(void *data) goto clear_cpu; } if (!cpu_online(target) || - cpumask_first(hpg.cpumask) == target) + (cpumask_first(hpg.cpumask) == target && + clustr == 0)) goto clear_cpu; device_offline(get_cpu_device(target)); clear_cpu: @@ -250,8 +251,7 @@ static ssize_t store_hotplug_max_cpus(struct kobject *kobj, for (c = 0; c < hpg.clusters; c++) { max = input & 0xff; - if (max) - cpu_hotplug_set_max(max, c); + cpu_hotplug_set_max(max, c); input = input >> 8; } return count; diff --git a/drivers/amlogic/thermal/cpucore_cooling.c b/drivers/amlogic/thermal/cpucore_cooling.c index 0b0c7fc3c701..99502fda172b 100644 --- a/drivers/amlogic/thermal/cpucore_cooling.c +++ b/drivers/amlogic/thermal/cpucore_cooling.c @@ -140,7 +140,7 @@ static int cpucore_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct cpucore_cooling_device *cpucore_device = cdev->devdata; - int set_max_num, id; + int set_max_num, id, i, core_num; mutex_lock(&cooling_cpucore_lock); if (cpucore_device->stop_flag) { @@ -156,8 +156,24 @@ static int cpucore_set_cur_state(struct thermal_cooling_device *cdev, cpucore_device->cpucore_state = state; set_max_num = cpucore_device->max_cpu_core_num - state; id = cpucore_device->cluster_id; - pr_debug("set max cpu num=%d,state=%ld\n", set_max_num, state); - cpufreq_set_max_cpu_num(set_max_num, id); + if (id != CLUSTER_FLAG) { + pr_debug("set max cpu num=%d,state=%ld\n", + set_max_num, state); + cpufreq_set_max_cpu_num(set_max_num, id); + } else { + for (i = 0; i < MAX_CLUSTER; i++) { + pr_debug("%s, set max num: %d, cluster: %d\n", + __func__, set_max_num, i); + core_num = cpucore_device->core_num[i]; + if (set_max_num < core_num) { + cpufreq_set_max_cpu_num(set_max_num, i); + set_max_num = 0; + } else { + set_max_num = set_max_num - core_num; + cpufreq_set_max_cpu_num(core_num, i); + } + } + } } return 0; @@ -256,7 +272,7 @@ cpucore_cooling_register(struct device_node *np, int cluster_id) struct thermal_cooling_device *cool_dev; struct cpucore_cooling_device *cpucore_dev = NULL; char dev_name[THERMAL_NAME_LENGTH]; - int ret = 0, cpu; + int ret = 0, cpu, i; int cores = 0; cpucore_dev = kzalloc(sizeof(struct cpucore_cooling_device), @@ -270,7 +286,8 @@ cpucore_cooling_register(struct device_node *np, int cluster_id) return ERR_PTR(-EINVAL); } - if (mc_capable()) { + if ((topology_physical_package_id(0) != -1) + && (cluster_id != CLUSTER_FLAG)) { for_each_possible_cpu(cpu) { if (topology_physical_package_id(cpu) == cluster_id) cores++; @@ -283,6 +300,17 @@ cpucore_cooling_register(struct device_node *np, int cluster_id) snprintf(dev_name, sizeof(dev_name), "thermal-cpucore-%d", cpucore_dev->id); + if (cluster_id == CLUSTER_FLAG) { + for (i = MAX_CLUSTER - 1; i >= 0; i--) { + cores = 0; + for_each_possible_cpu(cpu) { + if (topology_physical_package_id(cpu) == i) + cores++; + } + cpucore_dev->core_num[i] = cores; + pr_info("%s, clutser[%d] core num:%d\n", __func__, i, cores); + } + } cool_dev = thermal_of_cooling_device_register(np, dev_name, cpucore_dev, &cpucore_cooling_ops); if (!cool_dev) { diff --git a/drivers/amlogic/thermal/meson_cooldev.c b/drivers/amlogic/thermal/meson_cooldev.c index db2c9e474f2d..b12bdd9714d7 100644 --- a/drivers/amlogic/thermal/meson_cooldev.c +++ b/drivers/amlogic/thermal/meson_cooldev.c @@ -232,7 +232,7 @@ int meson_cooldev_min_update(struct platform_device *pdev, int index) case COOL_DEV_TYPE_CPU_FREQ: for_each_possible_cpu(cpu) { - if (mc_capable()) + if (topology_physical_package_id(0) != -1) c_id = topology_physical_package_id(cpu); else c_id = 0; /* force cluster 0 if no MC */ @@ -349,10 +349,12 @@ static int parse_cool_device(struct platform_device *pdev) else cool->gpupp = temp; - if (of_property_read_u32(child, "cluster_id", &temp)) - pr_err("thermal: read cluster_id failed\n"); - else + if (of_property_read_u32(child, "cluster_id", &temp)) { + pr_info("thermal: no cluster id, cpucore as one cooldev\n"); + cool->cluster_id = CLUSTER_FLAG; + } else { cool->cluster_id = temp; + } if (of_property_read_string(child, "device_type", &str)) pr_err("thermal: read device_type failed\n"); diff --git a/include/linux/amlogic/cpucore_cooling.h b/include/linux/amlogic/cpucore_cooling.h index 9039455b0d55..439974131761 100644 --- a/include/linux/amlogic/cpucore_cooling.h +++ b/include/linux/amlogic/cpucore_cooling.h @@ -20,6 +20,9 @@ #include #include + +#define MAX_CLUSTER 2 +#define CLUSTER_FLAG 0xF struct cpucore_cooling_device { int id; struct thermal_cooling_device *cool_dev; @@ -29,6 +32,7 @@ struct cpucore_cooling_device { int max_cpu_core_num; int cluster_id; int stop_flag; + int core_num[MAX_CLUSTER]; }; #define CPU_STOP 0x80000000 #ifdef CONFIG_AMLOGIC_CPUCORE_THERMAL From 28c3ea7ffb5e55a3b54dd0ddb568b542c610cd92 Mon Sep 17 00:00:00 2001 From: "shichang.zhai" Date: Wed, 13 Mar 2019 03:31:03 -0400 Subject: [PATCH 0317/1060] dts: add sensor name for imx307 [1/1] PD#OTT-2643 Problem: when bringup imx307,sensor name in dts need to update Solution: add sensor name for imx307 in dts Verify: W400 Change-Id: Ic5614326b0debd01efa028f66e7c6337d78ec242 Signed-off-by: shichang.zhai --- arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index d1a9d6dff4bc..069a0d12451d 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -768,7 +768,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -781,7 +781,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; }; /* end of / */ &i2c2 { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts index 1ce3d622b959..7e829bcc1b3f 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -748,7 +748,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -761,7 +761,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; }; /* end of / */ &i2c2 { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index bd14cfd777ec..7b2fbd20fbc8 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -845,7 +845,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -858,7 +858,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; }; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index f6628233f2b5..c5dbe4acfd6a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -812,7 +812,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -825,7 +825,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; }; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index 95d178a76b74..57f4120a70a7 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -823,7 +823,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -836,7 +836,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; ircut: ircut { compatible = "amlogic, ircut"; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index 76612158e2e1..0107d3111ed2 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -793,7 +793,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -806,7 +806,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; ircut: ircut { compatible = "amlogic, ircut"; From 39e13fe35c9afc24057ead072c67b1ded22fd40e Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 15 Mar 2019 15:43:56 +0800 Subject: [PATCH 0318/1060] vpp: add log switch in vpp_set_filters [1/1] PD#SWPL-5942 Problem: Too many log when DI process called the vpp_set_filters with AFBC. Solution: Add log switch to disable it. Verify: verified on X301 Change-Id: I34c8573bed78e49d27ec386279e929e617bf76d5 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 8 ++++---- drivers/amlogic/media/video_sink/vpp.c | 16 ++++++++++++---- include/linux/amlogic/media/video_sink/vpp.h | 5 +++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index a83e10968de5..7653fb47d62c 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -3168,12 +3168,12 @@ static void pip_toggle_frame(struct vframe_s *vf) if (legacy_vpp || is_meson_tl1_cpu()) iret = vpp_set_filters_no_scaler( &glayer_info[1], vf, - nextpip_frame_par, vinfo); + nextpip_frame_par, vinfo, 1); else iret = vpp_set_filters( &glayer_info[1], vf, nextpip_frame_par, vinfo, - true); + true, 1); if (iret == VppFilter_Success_and_Changed) pip_property_changed = 1; @@ -3976,7 +3976,7 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) &glayer_info[0], vf, next_frame_par, vinfo, (is_dolby_vision_on() && - is_dolby_vision_stb_mode())); + is_dolby_vision_stb_mode()), 1); if (iret == VppFilter_Success_and_Changed) video_property_changed = 1; @@ -8127,7 +8127,7 @@ int get_current_vscale_skip_count(struct vframe_s *vf) &glayer_info[0], vf, &frame_par, vinfo, (is_dolby_vision_on() && - is_dolby_vision_stb_mode())); + is_dolby_vision_stb_mode()), 0); ret = frame_par.vscale_skip_count; if (cur_frame_par && (process_3d_type & MODE_3D_ENABLE)) ret |= (cur_frame_par->vpp_3d_mode<<8); diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 8590b24418cb..e47ee2854a37 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1417,7 +1417,8 @@ RESTART: (vf->canvas0Addr != 0) && (next_frame_par->vscale_skip_count > 1) && (!next_frame_par->nocomp)) { - pr_info( + if (vpp_flags & VPP_FLAG_MORE_LOG) + pr_info( "layer%d: Try DW buffer for compressed frame scaling.\n", input->layer_id); @@ -2798,7 +2799,8 @@ RESTART: (vf->canvas0Addr != 0) && (next_frame_par->vscale_skip_count > 1) && (!next_frame_par->nocomp)) { - pr_info( + if (vpp_flags & VPP_FLAG_MORE_LOG) + pr_info( "layer%d: Try DW buffer for compressed frame scaling.\n", input->layer_id); @@ -2856,7 +2858,7 @@ int vpp_set_filters( struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo, - bool bypass_sr) + bool bypass_sr, u32 op_flag) { u32 src_width = 0; u32 src_height = 0; @@ -2992,6 +2994,9 @@ int vpp_set_filters( if (vinfo->field_height != vinfo->height) vpp_flags |= VPP_FLAG_INTERLACE_OUT; + if (op_flag & 1) + vpp_flags |= VPP_FLAG_MORE_LOG; + next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; @@ -3015,7 +3020,7 @@ int vpp_set_filters_no_scaler( struct disp_info_s *input, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo) + const struct vinfo_s *vinfo, u32 op_flag) { u32 src_width = 0; u32 src_height = 0; @@ -3085,6 +3090,9 @@ int vpp_set_filters_no_scaler( if (vinfo->field_height != vinfo->height) vpp_flags |= VPP_FLAG_INTERLACE_OUT; + if (op_flag & 1) + vpp_flags |= VPP_FLAG_MORE_LOG; + next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index f61c44dacc4a..22a143b596a2 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -34,6 +34,7 @@ extern bool super_scaler; #define VPP_FLAG_AR_BITS 8 #define VPP_FLAG_PORTRAIT_MODE 0x00040000 #define VPP_FLAG_VSCALE_DISABLE 0x00080000 +#define VPP_FLAG_MORE_LOG 0x00100000 #define IDX_H (2 << 8) #define IDX_V_Y (1 << 13) @@ -285,13 +286,13 @@ extern int vpp_set_filters( struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo, - bool bypass_sr); + bool bypass_sr, u32 op_flag); extern int vpp_set_filters_no_scaler( struct disp_info_s *input, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo); + const struct vinfo_s *vinfo, u32 op_flag); extern s32 vpp_set_nonlinear_factor( struct disp_info_s *info, u32 f); From ae7edb8233d4b76f996e3c6c0497eb34ce42f9a8 Mon Sep 17 00:00:00 2001 From: Xiaoming Sui Date: Mon, 11 Mar 2019 17:03:06 +0800 Subject: [PATCH 0319/1060] video: timming gets error when switching channels [1/1] PD#TV-3062 Problem: When switching channels, Hisense platform needs hold video, and the timming obtained at this time is wrong Solution: because we have add hold video function, so get width and height interface give the last video frame width and height, and so on change the video Verify: X301 Change-Id: I331a4589dcb5f5785dce7eea6d8cd03c92d733d2 Signed-off-by: Xiaoming Sui --- drivers/amlogic/media/video_sink/video.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 7653fb47d62c..0f14872d935a 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -213,6 +213,9 @@ static struct vframe_s local_pip; static struct device *amvideo_dev; static struct device *amvideo_poll_dev; +static u32 cur_width; +static u32 cur_height; + #define DRIVER_NAME "amvideo" #define MODULE_NAME "amvideo" #define DEVICE_NAME "amvideo" @@ -3691,6 +3694,13 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) timestamp_vpts_inc(-1); } } + if (vf->type & VIDTYPE_COMPRESS) { + cur_width = vf->compWidth; + cur_height = vf->compHeight; + } else { + cur_width = vf->width; + cur_height = vf->height; + } video_vf_put(vf); ATRACE_COUNTER(__func__, __LINE__); return; @@ -10686,7 +10696,8 @@ static ssize_t video_hold_store(struct class *cla, const char *buf, size_t count) { int r; - + cur_width = 0; + cur_height = 0; if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("%s(%s)\n", __func__, buf); @@ -10851,6 +10862,8 @@ static ssize_t frame_width_show(struct class *cla, struct class_attribute *attr, char *buf) { + if (hold_video == 1) + return sprintf(buf, "%d\n", cur_width); if (cur_dispbuf) { if (cur_dispbuf->type & VIDTYPE_COMPRESS) return sprintf(buf, "%d\n", cur_dispbuf->compWidth); @@ -10864,6 +10877,8 @@ static ssize_t frame_width_show(struct class *cla, static ssize_t frame_height_show(struct class *cla, struct class_attribute *attr, char *buf) { + if (hold_video == 1) + return sprintf(buf, "%d\n", cur_height); if (cur_dispbuf) { if (cur_dispbuf->type & VIDTYPE_COMPRESS) return sprintf(buf, "%d\n", cur_dispbuf->compHeight); From f47d8a4b006221f4ad18f8481cfab1259851607e Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Wed, 27 Feb 2019 14:12:11 +0800 Subject: [PATCH 0320/1060] audio: auge: fix PAO for frhdmirx [1/2] PD#SWPL-4010 Problem: Not detect audio type by PAO for frhdmirx Solution: Add hw detect for frdhmirx PAO audio type is checked by hw for PCM too Verify: x301 Change-Id: Ib60d738c69f336866250a8181609503912bf0485 Signed-off-by: Xing Wang --- sound/soc/amlogic/auge/extn.c | 101 ++++++++++++++++++++++++--- sound/soc/amlogic/auge/frhdmirx_hw.c | 101 +++++++++++++++++++-------- sound/soc/amlogic/auge/frhdmirx_hw.h | 5 ++ sound/soc/amlogic/auge/spdif.c | 2 +- sound/soc/amlogic/auge/tdm.c | 2 +- 5 files changed, 173 insertions(+), 38 deletions(-) diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index 55d3e46ec438..ad7aacbe7a22 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -42,6 +42,15 @@ #define DRV_NAME "EXTN" +#define MAX_INT 0x7ffffff + +struct extn_chipinfo { + /* try to check papb before fetch pcpd + * no nonpcm2pcm irq for tl1 + */ + bool no_nonpcm2pcm_clr; +}; + struct extn { struct aml_audio_controller *actrl; struct device *dev; @@ -69,9 +78,19 @@ struct extn { int arc_src; int arc_en; + /* check whether irq generating + * if not, reset + * 'cuase no irq from nonpcm2pcm, do it by sw. + */ + unsigned int frhdmirx_cnt; /* irq counter */ + unsigned int frhdmirx_last_cnt; + unsigned int frhdmirx_same_cnt; + bool nonpcm_flag; + + struct extn_chipinfo *chipinfo; }; -#define PREALLOC_BUFFER (128 * 1024) +#define PREALLOC_BUFFER (256 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) #define EXTN_RATES (SNDRV_PCM_RATE_8000_192000) @@ -100,21 +119,58 @@ static const struct snd_pcm_hardware extn_hardware = { .channels_max = 32, }; +static void frhdmirx_nonpcm2pcm_clr_reset(struct extn *p_extn) +{ + p_extn->frhdmirx_cnt = 0; + p_extn->frhdmirx_last_cnt = 0; + p_extn->frhdmirx_same_cnt = 0; +} + static irqreturn_t extn_ddr_isr(int irq, void *devid) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)devid; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct extn *p_extn = (struct extn *)dev_get_drvdata(dev); if (!snd_pcm_running(substream)) return IRQ_HANDLED; snd_pcm_period_elapsed(substream); + /* check pcm or nonpcm */ + if (p_extn && + p_extn->chipinfo && + p_extn->chipinfo->no_nonpcm2pcm_clr) { + if (p_extn->frhdmirx_last_cnt == p_extn->frhdmirx_cnt) { + + p_extn->frhdmirx_same_cnt++; + + if (p_extn->frhdmirx_same_cnt > 5) + frhdmirx_nonpcm2pcm_clr_reset(p_extn); + + if (p_extn->frhdmirx_cnt == 0) + p_extn->nonpcm_flag = false; + } else { + p_extn->frhdmirx_last_cnt = p_extn->frhdmirx_cnt; + p_extn->frhdmirx_same_cnt = 0; + p_extn->nonpcm_flag = true; + frhdmirx_clr_PAO_irq_bits(); + } + } + return IRQ_HANDLED; } static irqreturn_t frhdmirx_isr(int irq, void *devid) { + struct extn *p_extn = (struct extn *)devid; + + p_extn->frhdmirx_cnt++; + if (p_extn->frhdmirx_cnt > MAX_INT - 2) + frhdmirx_nonpcm2pcm_clr_reset(p_extn); + return IRQ_HANDLED; } @@ -177,8 +233,12 @@ static int extn_close(struct snd_pcm_substream *substream) else { aml_audio_unregister_toddr(p_extn->dev, substream); - if (toddr_src_get() == FRHDMIRX) + if (toddr_src_get() == FRHDMIRX) { + frhdmirx_nonpcm2pcm_clr_reset(p_extn); + if (p_extn->hdmirx_mode == 1) + frhdmirx_clr_PAO_irq_bits(); free_irq(p_extn->irq_frhdmirx, p_extn); + } } runtime->private_data = NULL; @@ -639,7 +699,7 @@ static const struct sppdif_audio_info type_texts[] = { {3, 0xb, "DTS-I"}, {3, 0x0c, "DTS-II"}, {3, 0x0d, "DTS-III"}, - {3, 0x11, "DTS-IV"}, + {4, 0x11, "DTS-IV"}, {4, 0, "DTS-HD"}, {5, 0x16, "TRUEHD"}, {6, 0x103, "PAUSE"}, @@ -651,13 +711,16 @@ static const struct soc_enum hdmirx_audio_type_enum = SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts), spdif_audio_type_texts); -static int hdmiin_check_audio_type(void) +static int hdmiin_check_audio_type(struct extn *p_extn) { int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info); int pc = frhdmirx_get_chan_status_pc(); int audio_type = 0; int i; + if (!p_extn->nonpcm_flag) + return audio_type; + for (i = 0; i < total_num; i++) { if (pc == type_texts[i].pc) { audio_type = type_texts[i].aud_type; @@ -674,8 +737,12 @@ static int hdmirx_audio_type_get_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct extn *p_extn = dev_get_drvdata(component->dev); + ucontrol->value.enumerated.item[0] = - hdmiin_check_audio_type(); + hdmiin_check_audio_type(p_extn); + return 0; } #endif @@ -730,6 +797,7 @@ static const struct snd_kcontrol_new extn_controls[] = { 0, aml_get_atmos_audio_edid, aml_set_atmos_audio_edid), + SOC_ENUM_EXT("HDMIIN Audio Type", hdmirx_audio_type_enum, hdmirx_audio_type_get_enum, @@ -744,9 +812,18 @@ static const struct snd_soc_component_driver extn_component = { .name = DRV_NAME, }; +struct extn_chipinfo tl1_extn_chipinfo = { + .no_nonpcm2pcm_clr = true, +}; + static const struct of_device_id extn_device_id[] = { { .compatible = "amlogic, snd-extn", + .data = &tl1_extn_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-extn", + .data = &tl1_extn_chipinfo, }, {}, }; @@ -761,9 +838,9 @@ static int extn_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct aml_audio_controller *actrl = NULL; struct extn *p_extn = NULL; + struct extn_chipinfo *p_chipinfo; int ret = 0; - p_extn = devm_kzalloc(dev, sizeof(struct extn), GFP_KERNEL); if (!p_extn) return -ENOMEM; @@ -771,6 +848,14 @@ static int extn_platform_probe(struct platform_device *pdev) p_extn->dev = dev; dev_set_drvdata(dev, p_extn); + /* match data */ + p_chipinfo = (struct extn_chipinfo *) + of_device_get_match_data(dev); + if (!p_chipinfo) + dev_warn_once(dev, "check whether to update chipinfo\n"); + else + p_extn->chipinfo = p_chipinfo; + /* get audio controller */ node_prt = of_get_parent(node); if (node_prt == NULL) @@ -793,8 +878,8 @@ static int extn_platform_probe(struct platform_device *pdev) /* Default ARC SRC */ p_extn->arc_src = 1; - /* Default: SPDIF in mode */ - p_extn->hdmirx_mode = 0; + /* Default: PAO mode */ + p_extn->hdmirx_mode = 1; ret = snd_soc_register_component(&pdev->dev, &extn_component, diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.c b/sound/soc/amlogic/auge/frhdmirx_hw.c index 19c55f480522..1dd059365a71 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.c +++ b/sound/soc/amlogic/auge/frhdmirx_hw.c @@ -15,6 +15,7 @@ * */ #include +#include #include "frhdmirx_hw.h" #include "regs.h" @@ -48,7 +49,7 @@ void frhdmirx_src_select(int src) (bool)src << 23); } -void frhdmirx_enable_irq_bits(int channels, int src) +static void frhdmirx_enable_irq_bits(int channels, int src) { int lane, int_bits = 0, i; @@ -59,10 +60,11 @@ void frhdmirx_enable_irq_bits(int channels, int src) /* interrupt bits */ if (src) { /* PAO mode */ - int_bits = (0x1 << 24 | /* PAO data: find papb */ - 0x1 << 16 /* PAO data: find pcpd changed */ + int_bits = ( + 0x1 << INT_PAO_PAPB_MASK | /* find papb */ + 0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */ ); - } else { /* SPDIF Lane*/ + } else { /* SPDIF Lane */ int lane_irq_bits = (0x1 << 7 | /* lane: find papb */ 0x1 << 6 | /* lane: find papb */ 0x1 << 5 | /* lane: find nonpcm to pcm */ @@ -77,6 +79,39 @@ void frhdmirx_enable_irq_bits(int channels, int src) audiobus_write(EE_AUDIO_FRHDMIRX_CTRL2, int_bits); } +void frhdmirx_clr_irq_bits(int channels, int src) +{ + int lane, int_clr_mask = 0, i; + + if (channels % 2) + lane = channels / 2 + 1; + else + lane = channels / 2; + + /* interrupt bits */ + if (src) { /* PAO mode */ + int_clr_mask = ( + 0x1 << INT_PAO_PAPB_MASK | /* find papb */ + 0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */ + ); + } else { /* SPDIF Lane */ + int lane_irq_bits = (0x1 << 7 | /* lane: find papb */ + 0x1 << 6 | /* lane: find valid changed; */ + 0x1 << 5 | /* lane: find nonpcm to pcm */ + 0x1 << 4 | /* lane: find pcpd changed */ + 0x1 << 3 | /* lane: find ch status changed */ + 0x1 << 1 /* lane: find parity error */ + ); + + for (i = 0; i < lane; i++) + int_clr_mask |= (lane_irq_bits << i); + } + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, ~int_clr_mask); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, int_clr_mask); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, ~int_clr_mask); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, int_clr_mask); +} + void frhdmirx_ctrl(int channels, int src) { int lane, lane_mask = 0, i; @@ -84,30 +119,27 @@ void frhdmirx_ctrl(int channels, int src) /* PAO mode */ if (src) { audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0, - 0x1 << 23 | /* slect pao mode */ 0x1 << 22 | /* capture input by fall edge*/ - 0x1 << 7 | /* start sending ch num info out */ 0x1 << 8 | /* start detect PAPB */ - 0x1 << 6 /* chan status sel: pao pc/pd value */); - return; + 0x4 << 4 /* chan status sel: pao pc/pd value */ + ); + } else { + if (channels % 2) + lane = channels / 2 + 1; + else + lane = channels / 2; + + for (i = 0; i < lane; i++) + lane_mask |= (1 << i); + + audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0, + 0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11, + 0x1 << 30 | /* chnum_sel */ + lane_mask << 24 | /* chnum_sel */ + 0x1 << 22 | /* clk_inv */ + 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ + ); } - - if (channels % 2) - lane = channels / 2 + 1; - else - lane = channels / 2; - - for (i = 0; i < lane; i++) - lane_mask |= (1 << i); - - audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0, - 0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11, - 0x1 << 30 | /* chnum_sel */ - lane_mask << 24 | /* chnum_sel */ - 0x1 << 22 | /* clk_inv */ - 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ - ); - /* nonpcm2pcm_th */ audiobus_write(EE_AUDIO_FRHDMIRX_CTRL1, 0xff << 20); @@ -115,6 +147,22 @@ void frhdmirx_ctrl(int channels, int src) frhdmirx_enable_irq_bits(channels, src); } +void frhdmirx_clr_PAO_irq_bits(void) +{ + audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL4, + 0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK, + 0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK); + + audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL4, + 0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK, + 0x0 << INT_PAO_PAPB_MASK | 0x0 << INT_PAO_PCPD_MASK); +} + +unsigned int frhdmirx_get_ch_status0to31(void) +{ + return (unsigned int)audiobus_read(EE_AUDIO_FRHDMIRX_STAT0); +} + unsigned int frhdmirx_get_chan_status_pc(void) { unsigned int val; @@ -122,6 +170,3 @@ unsigned int frhdmirx_get_chan_status_pc(void) val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1); return (val >> 16) & 0xff; } - - - diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.h b/sound/soc/amlogic/auge/frhdmirx_hw.h index e0ebfe46323e..7c83dd01c704 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.h +++ b/sound/soc/amlogic/auge/frhdmirx_hw.h @@ -17,8 +17,13 @@ #ifndef __FRHDMIRX_HW_H__ #define __FRHDMIRX_HW_H__ +#define INT_PAO_PAPB_MASK 24 +#define INT_PAO_PCPD_MASK 16 + extern void frhdmirx_enable(bool enable); extern void frhdmirx_src_select(int src); extern void frhdmirx_ctrl(int channels, int src); +extern void frhdmirx_clr_PAO_irq_bits(void); +extern unsigned int frhdmirx_get_ch_status0to31(void); extern unsigned int frhdmirx_get_chan_status_pc(void); #endif diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index c107d96117e3..89c58eb862c8 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -875,7 +875,7 @@ static struct snd_pcm_ops aml_spdif_ops = { .mmap = aml_spdif_mmap, }; -#define PREALLOC_BUFFER (128 * 1024) +#define PREALLOC_BUFFER (256 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd) { diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index cc7e9435a637..2549ce147142 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -358,7 +358,7 @@ static struct snd_pcm_ops aml_tdm_ops = { .mmap = aml_tdm_mmap, }; -#define PREALLOC_BUFFER (128 * 1024) +#define PREALLOC_BUFFER (256 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) static int aml_tdm_new(struct snd_soc_pcm_runtime *rtd) { From 7c8e554f825f6fc381eebe28300a8d67671e96a9 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Fri, 15 Mar 2019 21:50:54 +0800 Subject: [PATCH 0321/1060] dtv_demod: Prevent NULL pointer crash caused by tuner attach failure [1/1] PD#TV-1539 Problem: Prevent NULL pointer crash caused by tuner attach failure. Solution: Prevent NULL pointer crash caused by tuner attach failure. Verify: verified by x301 Change-Id: I57cf32947775626467eb952dd2298ae9ec84601d Signed-off-by: nengwen.chen --- drivers/amlogic/media/dtv_demod/aml_demod.c | 4 +++- drivers/amlogic/media/dtv_demod/amlfrontend.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/dtv_demod/aml_demod.c b/drivers/amlogic/media/dtv_demod/aml_demod.c index cd823674b1b3..63d44fa2df17 100644 --- a/drivers/amlogic/media/dtv_demod/aml_demod.c +++ b/drivers/amlogic/media/dtv_demod/aml_demod.c @@ -280,6 +280,7 @@ static long aml_demod_ioctl(struct file *file, dvbfe = aml_get_fe();/*get_si2177_tuner();*/ #if 0 if (dvbfe != NULL) + if (dvbfe->ops.tuner_ops.get_strength) strength = dvbfe->ops.tuner_ops.get_strength(dvbfe); #else strength = tuner_get_ch_power2(); @@ -323,7 +324,8 @@ static long aml_demod_ioctl(struct file *file, #if 0 /*ary temp for my_tool:*/ if (dvbfe != NULL) { pr_dbg("calling tuner ops\n"); - dvbfe->ops.tuner_ops.set_params(dvbfe); + if (dvbfe->ops.tuner_ops.set_params) + dvbfe->ops.tuner_ops.set_params(dvbfe); } #endif break; diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 9abd3b30c337..41af69a06497 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -3828,7 +3828,8 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) else if (mode == AM_FE_ISDBT_N) fe->ops.info.type = FE_ISDBT; - fe->ops.tuner_ops.set_config(fe, NULL); + if (fe->ops.tuner_ops.set_config) + fe->ops.tuner_ops.set_config(fe, NULL); return 0; } From 0a2f97902c39a847f894eb3acc4edf906b0ac1e7 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Mon, 4 Mar 2019 12:43:49 +0800 Subject: [PATCH 0322/1060] gdc: ge2d: fix ge2d dma-buf no free memory issue [1/1] PD#SWPL-5685 Problem: gdc&ge2d dma buf memory leak Solution: clear dmabuf alloc flag when dmabuf really free Verify: verified by w400 Change-Id: I914d93d795311fd6e3e34ca5bd64aaf4db3d4c7a Signed-off-by: Pengcheng Chen --- .../amlogic/media/common/ge2d/ge2d_dmabuf.c | 19 +++++++++++++------ .../amlogic/media/common/ge2d/ge2d_dmabuf.h | 1 + drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 18 ++++++++++++++---- drivers/amlogic/media/gdc/app/gdc_dmabuf.h | 1 + 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 046cb1e0f4de..2e8a8a7beb3b 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -33,13 +33,14 @@ #include "ge2d_log.h" #include "ge2d_dmabuf.h" +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); /* dma free*/ static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; if (!atomic_dec_and_test(&buf->refcount)) { - ge2d_log_dbg("aml_dma_put, refcont=%d\n", + ge2d_log_dbg("ge2d aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } @@ -49,9 +50,10 @@ static void aml_dma_put(void *buf_priv) } dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, buf->attrs); + clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); kfree(buf); - ge2d_log_dbg("aml_dma_put free!\n"); + ge2d_log_dbg("ge2d aml_dma_put free!\n"); } static void *aml_dma_alloc(struct device *dev, unsigned long attrs, @@ -339,6 +341,11 @@ static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) return -1; } +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index) +{ + buffer->gd_buffer[index].alloc = 0; +} + void *ge2d_dma_buffer_create(void) { int i; @@ -391,7 +398,8 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, GFP_HIGHUSER | __GFP_ZERO); if (!buf) return (-ENOMEM); - + ((struct aml_dma_buf *)buf)->priv = buffer; + ((struct aml_dma_buf *)buf)->index = index; mutex_lock(&(buffer->lock)); buffer->gd_buffer[index].mem_priv = buf; buffer->gd_buffer[index].index = index; @@ -416,7 +424,6 @@ int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index) return (-EINVAL); } aml_dma_put(buf); - buffer->gd_buffer[index].alloc = 0; return 0; } @@ -515,7 +522,7 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg) cfg->attach = d_att; cfg->vaddr = vaddr; cfg->sg = sg; - ge2d_log_dbg("%s\n", __func__); + ge2d_log_dbg("%s, dbuf=0x%p\n", __func__, dbuf); return ret; vmap_err: @@ -587,7 +594,7 @@ void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg) dma_buf_put(dbuf); - ge2d_log_dbg("%s\n", __func__); + ge2d_log_dbg("%s, dbuf=0x%p\n", __func__, dbuf); } void ge2d_dma_buffer_dma_flush(struct device *dev, int fd) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h index 85dc94b5d19f..396a6a8f299e 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h @@ -40,6 +40,7 @@ struct aml_dma_buf { struct sg_table *sgt_base; /* DMABUF related */ struct dma_buf_attachment *db_attach; + void *priv; }; struct aml_dma_buf_priv { diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 390874a22dab..624fe7b15fc2 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -34,13 +34,14 @@ #include "system_log.h" #include "gdc_dmabuf.h" +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); /* dma free*/ static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; if (!atomic_dec_and_test(&buf->refcount)) { - gdc_log(LOG_INFO, "aml_dma_put, refcont=%d\n", + gdc_log(LOG_INFO, "gdc aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } @@ -50,9 +51,10 @@ static void aml_dma_put(void *buf_priv) } dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, buf->attrs); + clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); kfree(buf); - gdc_log(LOG_INFO, "aml_dma_put free!\n"); + gdc_log(LOG_INFO, "gdc aml_dma_put free!\n"); } static void *aml_dma_alloc(struct device *dev, unsigned long attrs, @@ -341,6 +343,11 @@ static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) return -1; } +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index) +{ + buffer->gd_buffer[index].alloc = 0; +} + void *gdc_dma_buffer_create(void) { int i; @@ -393,7 +400,8 @@ int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, GFP_HIGHUSER | __GFP_ZERO); if (!buf) return (-ENOMEM); - + ((struct aml_dma_buf *)buf)->priv = buffer; + ((struct aml_dma_buf *)buf)->index = index; mutex_lock(&(buffer->lock)); buffer->gd_buffer[index].mem_priv = buf; buffer->gd_buffer[index].index = index; @@ -418,7 +426,6 @@ int gdc_dma_buffer_free(struct aml_dma_buffer *buffer, int index) return (-EINVAL); } aml_dma_put(buf); - buffer->gd_buffer[index].alloc = 0; return 0; } @@ -476,6 +483,7 @@ int gdc_dma_buffer_map(struct aml_dma_cfg *cfg) struct device *dev = NULL; enum dma_data_direction dir; + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { pr_err("error input param"); return -EINVAL; @@ -517,6 +525,7 @@ int gdc_dma_buffer_map(struct aml_dma_cfg *cfg) cfg->attach = d_att; cfg->vaddr = vaddr; cfg->sg = sg; + gdc_log(LOG_INFO, "gdc_dma_buffer_map, dbuf=0x%p\n", dbuf); return ret; @@ -589,6 +598,7 @@ void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg) dma_buf_detach(dbuf, d_att); dma_buf_put(dbuf); + gdc_log(LOG_INFO, "gdc_dma_buffer_unmap, dbuf=0x%p\n", dbuf); } void gdc_dma_buffer_dma_flush(struct device *dev, int fd) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h index 6de1d577fe11..fb039b4658b5 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h @@ -38,6 +38,7 @@ struct aml_dma_buf { struct sg_table *sgt_base; /* DMABUF related */ struct dma_buf_attachment *db_attach; + void *priv; }; struct aml_dma_buf_priv { From 1d3ab17164ca8df2ecfb0093e6a802c0d09bcd1e Mon Sep 17 00:00:00 2001 From: "huijie.huang" Date: Tue, 12 Mar 2019 18:19:39 +0800 Subject: [PATCH 0323/1060] audio: open audio out for g12b socket board [1/1] PD#SWPL-5833 Problem: No audio out for g12b socket board Solution: Open audio codec Verify: test pass on g12b socket board Change-Id: Ieec710edec218a13da41d249889515b0ac53a3e9 Signed-off-by: huijie.huang --- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 8 ++++---- arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 932f68f5c110..38ba1926fcb0 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -484,11 +484,11 @@ }; amlogic_codec:t9015{ #sound-dai-cells = <0>; - /*compatible = "amlogic, aml_codec_T9015";*/ + compatible = "amlogic, aml_codec_T9015"; reg = <0xFF632000 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ tdmout_index = <1>; - status = "disabled"; + status = "okay"; }; audio_effect:eqdrc{ /*eq_enable = <1>;*/ @@ -568,7 +568,7 @@ }; tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec - &dummy_codec &ad82584f_62>; + &amlogic_codec &ad82584f_62>; }; }; @@ -925,7 +925,7 @@ * 3: spdifout; * 4: spdifout_b; */ - samesource_sel = <4>; + /*samesource_sel = <4>; */ }; aml_tdmc: tdmc { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 069a0d12451d..2692b8d0ef75 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -484,11 +484,11 @@ }; amlogic_codec:t9015{ #sound-dai-cells = <0>; - /*compatible = "amlogic, aml_codec_T9015";*/ + compatible = "amlogic, aml_codec_T9015"; reg = <0x0 0xFF632000 0x0 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ tdmout_index = <1>; - status = "disabled"; + status = "okay"; }; audio_effect:eqdrc{ /*eq_enable = <1>;*/ @@ -568,7 +568,7 @@ }; tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec - &dummy_codec &ad82584f_62>; + &amlogic_codec &ad82584f_62>; }; }; @@ -925,7 +925,7 @@ * 3: spdifout; * 4: spdifout_b; */ - samesource_sel = <4>; + /* samesource_sel = <4>; */ }; aml_tdmc: tdmc { From 38c296498ba78ce6152edde09e97bd4876f194f9 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Thu, 7 Mar 2019 10:17:29 +0800 Subject: [PATCH 0324/1060] vmap: print pfn for register in vmalloc range [1/1] PD#SWPL-5564 Problem: When open VMAP for kernel stack, if we meet kernel panic log, we can't know physical address of stack and hard to debug. Solution: Print pfn for register in vmalloc range Verify: p212 Change-Id: Iee120df1feab88e412ef63e87c2e2bb4ad0645fb Signed-off-by: Tao Zeng --- arch/arm/kernel/process.c | 21 +++++++++++++++++++++ arch/arm64/kernel/process.c | 18 ++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 324b32b2ed67..c0c17304221e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -350,6 +350,23 @@ done: pr_cont("%s", name); pr_cont("\n"); } + +static void show_vmalloc_pfn(struct pt_regs *regs) +{ + int i; + struct page *page; + + for (i = 0; i < 16; i++) { + if (is_vmalloc_or_module_addr((void *)regs->uregs[i])) { + page = vmalloc_to_page((void *)regs->uregs[i]); + if (!page) + continue; + pr_info("R%-2d : %08lx, PFN:%5lx\n", + i, regs->uregs[i], page_to_pfn(page)); + } + } + +} #endif /* CONFIG_AMLOGIC_USER_FAULT */ void __show_regs(struct pt_regs *regs) @@ -408,6 +425,10 @@ void __show_regs(struct pt_regs *regs) buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; buf[4] = '\0'; +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_vmalloc_pfn(regs); +#endif + #ifndef CONFIG_CPU_V7M { const char *segment; diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 6084d01e99b5..7f377c10e433 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -268,6 +268,23 @@ static void show_user_data(unsigned long addr, int nbytes, const char *name) pr_cont("\n"); } } + +static void show_vmalloc_pfn(struct pt_regs *regs) +{ + int i; + struct page *page; + + for (i = 0; i < 16; i++) { + if (is_vmalloc_or_module_addr((void *)regs->regs[i])) { + page = vmalloc_to_page((void *)regs->regs[i]); + if (!page) + continue; + pr_info("R%-2d : %016llx, PFN:%5lx\n", + i, regs->regs[i], page_to_pfn(page)); + } + } + +} #endif /* CONFIG_AMLOGIC_USER_FAULT */ static void show_extra_register_data(struct pt_regs *regs, int nbytes) @@ -443,6 +460,7 @@ void __show_regs(struct pt_regs *regs) show_vma(current->mm, instruction_pointer(regs)); show_vma(current->mm, lr); } + show_vmalloc_pfn(regs); #endif /* CONFIG_AMLOGIC_USER_FAULT */ printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", regs->pc, lr, regs->pstate); From bcffc2c811b85d135fe6578a856e38fb1f2e4f05 Mon Sep 17 00:00:00 2001 From: "xianjun.liu" Date: Thu, 7 Mar 2019 17:26:42 +0800 Subject: [PATCH 0325/1060] MTD: spin_lock stuck problem about marking bad block for mtd driver [1/1] PD#SWPL-5613 Problem: boot fail because of the UBI write error Solution: fixed nested-calls spin-lock when update bbt Verify: AXG-S420 Change-Id: I56b603ebffa5557ab7949ead2fddd41323346d09 Signed-off-by: xianjun.liu --- drivers/amlogic/mtd/aml_dtb.c | 30 +++--- drivers/amlogic/mtd/aml_env.c | 25 ++++- drivers/amlogic/mtd/aml_mtd.h | 3 + drivers/amlogic/mtd/aml_nand.c | 26 +++--- drivers/amlogic/mtd/rsv_manage.c | 156 ++++++++++++++++--------------- 5 files changed, 139 insertions(+), 101 deletions(-) diff --git a/drivers/amlogic/mtd/aml_dtb.c b/drivers/amlogic/mtd/aml_dtb.c index e8711d886f88..4259e15a2352 100644 --- a/drivers/amlogic/mtd/aml_dtb.c +++ b/drivers/amlogic/mtd/aml_dtb.c @@ -129,10 +129,12 @@ ssize_t dtb_read(struct file *file, loff_t *ppos) { u8 *dtb_ptr = NULL; - /*struct nand_flash *flash = &aml_chip_dtb->flash;*/ + struct nand_chip *chip = &aml_chip_dtb->chip; struct mtd_info *mtd = aml_chip_dtb->mtd; ssize_t read_size = 0; int ret = 0; + loff_t addr; + int chipnr; if (*ppos == aml_chip_dtb->dtbsize) return 0; @@ -146,8 +148,10 @@ ssize_t dtb_read(struct file *file, if (dtb_ptr == NULL) return -ENOMEM; - /*not need nand_get_device here, mtd->_read_xx will done with it*/ - /*nand_get_device(mtd, FL_READING);*/ + addr = *ppos; + nand_get_device(mtd, FL_READING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); ret = amlnf_dtb_read((u8 *)dtb_ptr, aml_chip_dtb->dtbsize); if (ret) { pr_info("%s: read failed:%d\n", __func__, ret); @@ -163,8 +167,8 @@ ssize_t dtb_read(struct file *file, ret = copy_to_user(buf, (dtb_ptr + *ppos), read_size); *ppos += read_size; exit: - /*nand_release_device(mtd);*/ - /* kfree(dtb_ptr); */ + chip->select_chip(mtd, -1); + nand_release_device(mtd); vfree(dtb_ptr); return read_size; } @@ -175,9 +179,11 @@ ssize_t dtb_write(struct file *file, { u8 *dtb_ptr = NULL; ssize_t write_size = 0; - /*struct nand_flash *flash = &aml_chip_dtb->flash;*/ - struct mtd_info *mtd = aml_chip_dtb->mtd; int ret = 0; + struct nand_chip *chip = &aml_chip_dtb->chip; + struct mtd_info *mtd = aml_chip_dtb->mtd; + loff_t addr; + int chipnr; if (*ppos == aml_chip_dtb->dtbsize) return 0; @@ -191,8 +197,10 @@ ssize_t dtb_write(struct file *file, if (dtb_ptr == NULL) return -ENOMEM; - /*not need nand_get_device here, mtd->_read_xx will done with it*/ - /*nand_get_device(mtd, FL_WRITING);*/ + addr = *ppos; + nand_get_device(mtd, FL_WRITING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); ret = amlnf_dtb_read((u8 *)dtb_ptr, aml_chip_dtb->dtbsize); if (ret) { pr_info("%s: read failed\n", __func__); @@ -216,8 +224,8 @@ ssize_t dtb_write(struct file *file, *ppos += write_size; exit: - /*nand_release_device(mtd);*/ - /* kfree(dtb_ptr); */ + chip->select_chip(mtd, -1); + nand_release_device(mtd); vfree(dtb_ptr); return write_size; } diff --git a/drivers/amlogic/mtd/aml_env.c b/drivers/amlogic/mtd/aml_env.c index 0de2242ffca7..c56fb1147793 100644 --- a/drivers/amlogic/mtd/aml_env.c +++ b/drivers/amlogic/mtd/aml_env.c @@ -189,6 +189,10 @@ ssize_t uboot_env_read(struct file *file, u8 *env_ptr = NULL; ssize_t read_size = 0; int ret = 0; + struct nand_chip *chip = &aml_chip_env->chip; + struct mtd_info *mtd = aml_chip_env->mtd; + loff_t addr; + int chipnr; if (*ppos == CONFIG_ENV_SIZE) return 0; @@ -201,7 +205,11 @@ ssize_t uboot_env_read(struct file *file, env_ptr = vmalloc(CONFIG_ENV_SIZE + 2048); if (env_ptr == NULL) return -ENOMEM; - mutex_lock(&env_mutex); + + addr = *ppos; + nand_get_device(mtd, FL_READING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); /*amlnand_get_device(aml_chip_env, CHIP_READING);*/ ret = amlnf_env_read((u8 *)env_ptr, CONFIG_ENV_SIZE); @@ -220,7 +228,8 @@ ssize_t uboot_env_read(struct file *file, ret = copy_to_user(buf, (env_ptr + *ppos), read_size); *ppos += read_size; exit: - mutex_unlock(&env_mutex); + chip->select_chip(mtd, -1); + nand_release_device(mtd); /*amlnand_release_device(aml_chip_env);*/ vfree(env_ptr); return read_size; @@ -233,6 +242,10 @@ ssize_t uboot_env_write(struct file *file, u8 *env_ptr = NULL; ssize_t write_size = 0; int ret = 0; + struct nand_chip *chip = &aml_chip_env->chip; + struct mtd_info *mtd = aml_chip_env->mtd; + loff_t addr; + int chipnr; if (*ppos == CONFIG_ENV_SIZE) return 0; @@ -246,7 +259,10 @@ ssize_t uboot_env_write(struct file *file, if (env_ptr == NULL) return -ENOMEM; - mutex_lock(&env_mutex); + addr = *ppos; + nand_get_device(mtd, FL_WRITING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); if ((*ppos + count) > CONFIG_ENV_SIZE) write_size = CONFIG_ENV_SIZE - *ppos; @@ -264,7 +280,8 @@ ssize_t uboot_env_write(struct file *file, *ppos += write_size; exit: - mutex_unlock(&env_mutex); + chip->select_chip(mtd, -1); + nand_release_device(mtd); vfree(env_ptr); return write_size; } diff --git a/drivers/amlogic/mtd/aml_mtd.h b/drivers/amlogic/mtd/aml_mtd.h index a8d475e74630..3d4cadf84509 100644 --- a/drivers/amlogic/mtd/aml_mtd.h +++ b/drivers/amlogic/mtd/aml_mtd.h @@ -883,6 +883,9 @@ int boot_device_register(struct aml_nand_chip *aml_chip); int add_mtd_partitions(struct mtd_info *mtd, const struct mtd_partition *part, int num); +int nand_get_device(struct mtd_info *mtd, int new_state); +void nand_release_device(struct mtd_info *mtd); + #ifdef AML_NAND_UBOOT extern int get_partition_from_dts(unsigned char *buffer); #endif diff --git a/drivers/amlogic/mtd/aml_nand.c b/drivers/amlogic/mtd/aml_nand.c index 7251fffc0a12..e827a9a3e5c7 100644 --- a/drivers/amlogic/mtd/aml_nand.c +++ b/drivers/amlogic/mtd/aml_nand.c @@ -17,7 +17,6 @@ #include "aml_mtd.h" - uint8_t nand_boot_flag; /*#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 13)*/ @@ -1913,9 +1912,10 @@ int aml_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd->priv; struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); - struct mtd_oob_ops aml_oob_ops; int blk_addr, mtd_erase_shift; int8_t *buf = NULL; + int page, chipnr; + int ret = 0; if (!mtd->erasesize) return -EINVAL; @@ -1935,19 +1935,18 @@ int aml_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) } mark_bad: /*no erase here, fixit*/ - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = mtd->oobavail; - /*aml_oob_ops.ooboffs = chip->ecc.layout->oobfree[0].offset;*/ - aml_oob_ops.ooboffs = 0; - aml_oob_ops.datbuf = chip->buffers->databuf; - aml_oob_ops.oobbuf = chip->oob_poi; chip->pagebuf = -1; - memset((unsigned char *)aml_oob_ops.datbuf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, 0x0, aml_oob_ops.ooblen); - - return mtd->_write_oob(mtd, ofs, &aml_oob_ops); + memset((unsigned char *)chip->buffers->databuf, 0x0, mtd->writesize); + memset((unsigned char *)chip->oob_poi, 0x0, mtd->oobavail); + chipnr = (int)(ofs >> chip->chip_shift); + page = (int)(ofs >> chip->page_shift); + chip->select_chip(mtd, chipnr); + ret = chip->write_page(mtd, chip, 0, mtd->writesize, + chip->buffers->databuf, + 1, page, 0, 0); + chip->select_chip(mtd, -1); + return ret; } static uint8_t aml_platform_read_byte(struct mtd_info *mtd) @@ -2195,3 +2194,4 @@ exit_error: aml_chip->block_status = NULL; return err; } + diff --git a/drivers/amlogic/mtd/rsv_manage.c b/drivers/amlogic/mtd/rsv_manage.c index f0ddbc462c17..cb0de55178bf 100644 --- a/drivers/amlogic/mtd/rsv_manage.c +++ b/drivers/amlogic/mtd/rsv_manage.c @@ -418,9 +418,10 @@ int aml_nand_read_rsv_info(struct mtd_info *mtd, loff_t addr = 0; size_t amount_loaded = 0; size_t len; - struct mtd_oob_ops aml_oob_ops; unsigned char *data_buf; unsigned char oob_buf[sizeof(struct oobinfo_t)]; + int page, realpage, chipnr; + struct nand_chip *chip = mtd_to_nand(mtd); READ_RSV_AGAIN: addr = nandrsv_info->valid_node->phy_blk_addr; @@ -433,20 +434,19 @@ READ_RSV_AGAIN: oobinfo = (struct oobinfo_t *)oob_buf; while (amount_loaded < nandrsv_info->size) { - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - /*aml_oob_ops.ooboffs = mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.ooboffs = 0; - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; - - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, - 0x0, aml_oob_ops.ooblen); + memset((unsigned char *)oob_buf, + 0x0, sizeof(struct oobinfo_t)); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + realpage = (int)(addr >> chip->page_shift); + page = realpage & chip->pagemask; - error = mtd->_read_oob(mtd, addr, &aml_oob_ops); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + error = chip->ecc.read_page(mtd, chip, data_buf, + 1, page); + chip->select_chip(mtd, -1); if ((error != 0) && (error != -EUCLEAN)) { pr_info("blk good but read failed: %llx, %d\n", (uint64_t)addr, error); @@ -456,11 +456,12 @@ READ_RSV_AGAIN: goto READ_RSV_AGAIN; } + memcpy(oob_buf, chip->oob_poi, mtd->oobavail); if (memcmp(oobinfo->name, nandrsv_info->name, 4)) pr_info("invalid nand info %s magic: %llx\n", nandrsv_info->name, (uint64_t)addr); - addr += mtd->writesize; + page++; len = min_t(uint32_t, mtd->writesize, (nandrsv_info->size - amount_loaded)); memcpy(buf + amount_loaded, data_buf, len); @@ -487,8 +488,6 @@ READ_RSV_AGAIN: } } #endif - /* if(data_buf) */ - /* kfree(data_buf); */ return 0; } @@ -544,18 +543,17 @@ static int aml_nand_write_rsv(struct mtd_info *mtd, struct aml_nandrsv_info_t *nandrsv_info, loff_t offset, u_char *buf) { struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); + struct nand_chip *chip = mtd_to_nand(mtd); struct oobinfo_t *oobinfo; int error = 0; loff_t addr = 0; size_t amount_saved = 0; size_t len; - struct mtd_oob_ops aml_oob_ops; unsigned char *data_buf; unsigned char oob_buf[sizeof(struct oobinfo_t)]; + int page, chipnr; data_buf = aml_chip->rsv_data_buf; - /* if (data_buf == NULL) */ - /* return -ENOMEM; */ addr = offset; pr_info("%s:%d,write info to %llx\n", __func__, __LINE__, addr); @@ -584,21 +582,21 @@ static int aml_nand_write_rsv(struct mtd_info *mtd, } #endif while (amount_saved < nandrsv_info->size) { - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; - - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); len = min_t(uint32_t, mtd->writesize, nandrsv_info->size - amount_saved); - memcpy((unsigned char *)aml_oob_ops.datbuf, + memcpy((unsigned char *)data_buf, buf + amount_saved, len); - error = mtd->_write_oob(mtd, addr, &aml_oob_ops); + page = (int)(addr >> chip->page_shift); + chipnr = (int)(addr >> chip->chip_shift); + memset(chip->oob_poi, 0xff, mtd->oobsize); + memcpy(chip->oob_poi, oob_buf, mtd->oobsize); + chip->select_chip(mtd, chipnr); + error = chip->write_page(mtd, chip, 0, len, data_buf, + 1, page, 0, 0); + chip->select_chip(mtd, -1); if (error) { pr_info("blk check good but write failed: %llx, %d\n", (uint64_t)addr, error); @@ -609,17 +607,19 @@ static int aml_nand_write_rsv(struct mtd_info *mtd, } if (amount_saved < nandrsv_info->size) return 1; - /* kfree(data_buf); */ + return 0; } int aml_nand_save_rsv_info(struct mtd_info *mtd, struct aml_nandrsv_info_t *nandrsv_info, u_char *buf) { + struct nand_chip *chip = mtd_to_nand(mtd); struct free_node_t *free_node = NULL, *tmp_node = NULL; int error = 0, pages_per_blk, valid_page_addr, i = 1; loff_t addr = 0; - struct erase_info erase_info; + int chipnr = 0; + int page; pages_per_blk = mtd->erasesize / mtd->writesize; /*solve these abnormals caused by power off and ecc error*/ @@ -639,13 +639,12 @@ RE_SEARCH: if ((valid_page_addr - i) == pages_per_blk) { addr = nandrsv_info->valid_node->phy_blk_addr; addr *= mtd->erasesize; - memset(&erase_info, - 0, sizeof(struct erase_info)); - erase_info.mtd = mtd; - erase_info.addr = addr; - erase_info.len = mtd->erasesize; _aml_rsv_disprotect(); - error = mtd->_erase(mtd, &erase_info); + page = (int)(addr >> chip->page_shift); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + error = chip->erase(mtd, page & chip->pagemask); + chip->select_chip(mtd, -1); _aml_rsv_protect(); nandrsv_info->valid_node->ec++; pr_info("---erase bad env block:%llx\n", addr); @@ -691,7 +690,10 @@ RE_SEARCH: pr_info("%s:%d,save info to %llx\n", __func__, __LINE__, addr); if (nandrsv_info->valid_node->phy_page_addr == 0) { - error = mtd->_block_isbad(mtd, addr); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + error = chip->block_bad(mtd, addr); + chip->select_chip(mtd, -1); if (error != 0) { /* *bad block here, need fix it @@ -706,16 +708,18 @@ RE_SEARCH: goto RE_SEARCH; } - memset(&erase_info, 0, sizeof(struct erase_info)); - erase_info.mtd = mtd; - erase_info.addr = addr; - erase_info.len = mtd->erasesize; _aml_rsv_disprotect(); - error = mtd->_erase(mtd, &erase_info); + page = (int)(addr >> chip->page_shift); + //chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + error = chip->erase(mtd, page & chip->pagemask); + chip->select_chip(mtd, -1); _aml_rsv_protect(); if (error) { pr_info("env free blk erase failed %d\n", error); - mtd->_block_markbad(mtd, addr); + chip->select_chip(mtd, chipnr); + chip->block_markbad(mtd, addr); + chip->select_chip(mtd, -1); return error; } nandrsv_info->valid_node->ec++; @@ -941,20 +945,21 @@ int aml_nand_free_rsv_info(struct mtd_info *mtd, struct free_node_t *tmp_node, *next_node = NULL; int error = 0; loff_t addr = 0; - struct erase_info erase_info; + int page, chipnr; + struct nand_chip *chip = mtd_to_nand(mtd); pr_info("free %s:\n", nandrsv_info->name); if (nandrsv_info->valid) { addr = nandrsv_info->valid_node->phy_blk_addr; addr *= mtd->erasesize; - memset(&erase_info, - 0, sizeof(struct erase_info)); - erase_info.mtd = mtd; - erase_info.addr = addr; - erase_info.len = mtd->erasesize; + + page = (int)(addr >> chip->page_shift); + chipnr = (int)(addr >> chip->chip_shift); _aml_rsv_disprotect(); - error = mtd->_erase(mtd, &erase_info); + chip->select_chip(mtd, chipnr); + error = chip->erase(mtd, page & chip->pagemask); + chip->select_chip(mtd, -1); _aml_rsv_protect(); pr_info("erasing valid info block: %llx\n", addr); nandrsv_info->valid_node->phy_blk_addr = -1; @@ -980,7 +985,6 @@ int aml_nand_scan_rsv_info(struct mtd_info *mtd, { struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); struct nand_chip *chip = &aml_chip->chip; - struct mtd_oob_ops aml_oob_ops; struct oobinfo_t *oobinfo; struct free_node_t *free_node, *tmp_node = NULL; unsigned char oob_buf[sizeof(struct oobinfo_t)]; @@ -990,6 +994,7 @@ int aml_nand_scan_rsv_info(struct mtd_info *mtd, int phys_erase_shift, pages_per_blk, page_num; int error = 0, ret = 0; uint32_t remainder; + int page, realpage, chipnr; data_buf = aml_chip->rsv_data_buf; oobinfo = (struct oobinfo_t *)oob_buf; @@ -1007,19 +1012,20 @@ RE_RSV_INFO_EXT: offset *= start_blk; scan_status = 0; RE_RSV_INFO: - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; - - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, - 0x0, aml_oob_ops.ooblen); + memset((unsigned char *)oob_buf, + 0x0, sizeof(struct oobinfo_t)); - error = mtd->_read_oob(mtd, offset, &aml_oob_ops); + realpage = (int)(offset >> chip->page_shift); + page = realpage & chip->pagemask; + chipnr = (int)(offset >> chip->chip_shift); + + chip->select_chip(mtd, chipnr); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + error = chip->ecc.read_page(mtd, chip, data_buf, + 1, page); + chip->select_chip(mtd, -1); if ((error != 0) && (error != -EUCLEAN)) { pr_info("blk check good but read failed: %llx, %d\n", (uint64_t)offset, error); @@ -1033,6 +1039,7 @@ RE_RSV_INFO: goto RE_RSV_INFO; } + memcpy(oob_buf, chip->oob_poi, mtd->oobavail); nandrsv_info->init = 1; nandrsv_info->valid_node->status = 0; if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) { @@ -1121,23 +1128,25 @@ RE_RSV_INFO: if (nandrsv_info->valid == 1) { pr_info("%s %d\n", __func__, __LINE__); - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; for (i = 0; i < pages_per_blk; i++) { - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, - 0x0, aml_oob_ops.ooblen); + memset((unsigned char *)oob_buf, + 0x0, sizeof(struct oobinfo_t)); offset = nandrsv_info->valid_node->phy_blk_addr; offset *= mtd->erasesize; offset += i * mtd->writesize; - error = mtd->_read_oob(mtd, offset, &aml_oob_ops); + + realpage = (int)(offset >> chip->page_shift); + page = realpage & chip->pagemask; + chipnr = (int)(offset >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + error = chip->ecc.read_page(mtd, chip, data_buf, + 1, page); + chip->select_chip(mtd, -1); if ((error != 0) && (error != -EUCLEAN)) { pr_info("blk good but read failed:%llx,%d\n", (uint64_t)offset, error); @@ -1146,6 +1155,7 @@ RE_RSV_INFO: continue; } + memcpy(oob_buf, chip->oob_poi, mtd->oobavail); if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) { good_addr[i] = 1; nandrsv_info->valid_node->phy_page_addr = i; From 298b9a89d8d42b56852edf2a6adddc37fdc41327 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Wed, 20 Mar 2019 14:20:08 +0800 Subject: [PATCH 0326/1060] numa: fix compile error after open NUMA config [2/2] PD#SWPL-5301 Problem: When open NUMA config on ARM64, there is compile error Solution: fix some compile problems Verify: p212 Change-Id: I1ae9ef975c680e3e5545186aac9ca2b57597bfe4 Signed-off-by: Tao Zeng --- drivers/amlogic/memory_ext/Kconfig | 1 + drivers/amlogic/memory_ext/page_trace.c | 17 +++++++++++++++-- include/linux/amlogic/page_trace.h | 6 +++++- include/linux/mm.h | 20 ++++++++++++++++---- mm/slab_common.c | 4 +--- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/memory_ext/Kconfig b/drivers/amlogic/memory_ext/Kconfig index 65fe232527e1..88856a72327c 100644 --- a/drivers/amlogic/memory_ext/Kconfig +++ b/drivers/amlogic/memory_ext/Kconfig @@ -11,6 +11,7 @@ config AMLOGIC_PAGE_TRACE bool "Amlogic trace for page allocate" depends on AMLOGIC_MEMORY_EXTEND depends on KALLSYMS + depends on !NUMA_BALANCING default y help Amlogic page trace will record function address of caller for page diff --git a/drivers/amlogic/memory_ext/page_trace.c b/drivers/amlogic/memory_ext/page_trace.c index 1c2f8ba34694..4350dbc09e0f 100644 --- a/drivers/amlogic/memory_ext/page_trace.c +++ b/drivers/amlogic/memory_ext/page_trace.c @@ -38,7 +38,11 @@ #define DEBUG_PAGE_TRACE 0 #endif +#ifdef CONFIG_NUMA +#define COMMON_CALLER_SIZE 64 /* more function names if NUMA */ +#else #define COMMON_CALLER_SIZE 32 +#endif /* * this is a driver which will hook during page alloc/free and @@ -95,6 +99,14 @@ static struct fun_symbol common_func[] __initdata = { {"vmalloc", 1}, {"__alloc_page_frag", 1}, {"kmalloc_order", 0}, +#ifdef CONFIG_NUMA + {"alloc_pages_current", 1}, + {"alloc_page_interleave", 1}, + {"kmalloc_large_node", 1}, + {"kmem_cache_alloc_node", 1}, + {"__kmalloc_node", 1}, + {"alloc_pages_vma", 1}, +#endif #ifdef CONFIG_SLUB /* for some static symbols not exported in headfile */ {"new_slab", 0}, {"slab_alloc", 0}, @@ -1065,8 +1077,9 @@ void __init page_trace_mem_init(void) * flags, you should disable AMLOGIC_PAGE_TRACE or reduce some page * flags. */ - BUILD_BUG_ON((__NR_PAGEFLAGS + ZONES_WIDTH) > 32); - BUILD_BUG_ON(NODES_WIDTH > 0); + BUILD_BUG_ON((__NR_PAGEFLAGS + ZONES_WIDTH + + NODES_WIDTH + SECTIONS_WIDTH + + LAST_CPUPID_SHIFT) > 32); #else if (page_trace_disable) return; diff --git a/include/linux/amlogic/page_trace.h b/include/linux/amlogic/page_trace.h index 7d724303841c..300e7ef0d4f7 100644 --- a/include/linux/amlogic/page_trace.h +++ b/include/linux/amlogic/page_trace.h @@ -92,7 +92,11 @@ static inline struct page_trace *find_page_base(struct page *page) { return NULL; } -static unsigned long find_back_trace(void) +static inline unsigned long find_back_trace(void) +{ + return 0; +} +static inline unsigned long get_page_trace(struct page *page) { return 0; } diff --git a/include/linux/mm.h b/include/linux/mm.h index d2dbfd694f9b..6038c8a17119 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -700,13 +700,25 @@ int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg, */ /* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_CPUPID] | ... | FLAGS | */ -#define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH) -#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) #if defined(CONFIG_AMLOGIC_PAGE_TRACE) && defined(CONFIG_64BIT) -#define ZONES_PGOFF ((sizeof(unsigned int) * 8) - ZONES_WIDTH) +/* + * We use high 32bit of page->flags for page trace, Make sure: + * __NR_PAGEFLAGS : about 21 bits + * ZONES_WIDTH : about 2 bits, MAX 4 zone types + * NODES_WIDTH : about 2 bits if open CONFIG_NUMA, else 0 bit + * SECTIONS_WIDTH : 0 bit if defined CONFIG_SPARSEMEM_VMEMMAP otherwise 18 + * bits on ARM64 + * LAST_CPUPID_SHIFT : 0 bit if not define CONFIG_NUMA_BALANCING, otherwise + * 8 + NR_CPUS_BITS + * All of these macros should be using less than 32bits in total, otherwise + * compile will fail + */ +#define SECTIONS_PGOFF ((sizeof(unsigned int)*8) - SECTIONS_WIDTH) #else -#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) +#define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH) #endif /* CONFIG_AMLOGIC_PAGE_TRACE */ +#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) +#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) #define LAST_CPUPID_PGOFF (ZONES_PGOFF - LAST_CPUPID_WIDTH) /* diff --git a/mm/slab_common.c b/mm/slab_common.c index f2ae3cb69533..35721fdcb862 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1044,9 +1044,7 @@ static inline void *aml_slub_alloc_large(size_t size, gfp_t flags, int order) unsigned long used_pages = PAGE_ALIGN(size) / PAGE_SIZE; unsigned long total_pages = 1 << order; unsigned long saved = 0; - #ifdef CONFIG_AMLOGIC_PAGE_TRACE - unsigned long fun; - #endif + unsigned long fun = 0; int i; /* record how many pages in first page*/ From dd6aa56fe3d8ad6a3d6272e7b734f34b03008f19 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Tue, 19 Mar 2019 21:19:30 +0800 Subject: [PATCH 0327/1060] vpp: add the pic_mode backup to check difference [1/1] PD#TV-2929 Problem: The pic_mode in cur_dispbuf was changed but not be detected. Solution: Add global pic_mode variable to check if the pic_mode in cur_dispbuf is changed. If so, force vpp_set_filters. Verify: verified on x301 Change-Id: I5b95f512ad0823b031989f05526f114694887f2b Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 47 ++++++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 0f14872d935a..1f2034cc90c7 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -439,6 +439,7 @@ static DEFINE_MUTEX(video_layer_mutex); static u32 layer_cap; static struct disp_info_s glayer_info[MAX_VD_LAYERS]; +static struct vframe_pic_mode_s gPic_info[MAX_VD_LAYERS]; static u32 reference_zorder = 128; @@ -3066,6 +3067,7 @@ static inline void proc_vd2_vsc_phase_per_vsync( static void pip_toggle_frame(struct vframe_s *vf) { u32 first_picture = 0; + bool force_toggle = false; if (vf == NULL) return; @@ -3142,6 +3144,21 @@ static void pip_toggle_frame(struct vframe_s *vf) #endif } + if (cur_pipbuf && + (cur_pipbuf->ratio_control & + DISP_RATIO_ADAPTED_PICMODE)) { + if (vf && (cur_pipbuf->ratio_control + == vf->ratio_control) + && memcmp(&cur_pipbuf->pic_mode, + &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + else if (memcmp(&cur_pipbuf->pic_mode, + &gPic_info[1], + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + } + if (pip_property_changed) { first_picture = 1; pip_property_changed = 0; @@ -3150,7 +3167,8 @@ static void pip_toggle_frame(struct vframe_s *vf) vf->type_backup = vf->type; /* enable new config on the new frames */ - if ((first_picture) || (cur_pipbuf && + if (first_picture || force_toggle || + (cur_pipbuf && ((cur_pipbuf->bufWidth != vf->bufWidth) || (cur_pipbuf->width != vf->width) || (cur_pipbuf->height != vf->height) || @@ -3178,6 +3196,9 @@ static void pip_toggle_frame(struct vframe_s *vf) nextpip_frame_par, vinfo, true, 1); + memcpy(&gPic_info[1], &vf->pic_mode, + sizeof(struct vframe_pic_mode_s)); + if (iret == VppFilter_Success_and_Changed) pip_property_changed = 1; @@ -3935,14 +3956,20 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) vf->type_backup = vf->type; } - if (cur_dispbuf && vf && + if (cur_dispbuf && (cur_dispbuf->ratio_control & - DISP_RATIO_ADAPTED_PICMODE) && - (cur_dispbuf->ratio_control == - vf->ratio_control) && - memcmp(&cur_dispbuf->pic_mode, &vf->pic_mode, - sizeof(struct vframe_pic_mode_s))) - force_toggle = true; + DISP_RATIO_ADAPTED_PICMODE)) { + if (vf && (cur_dispbuf->ratio_control + == vf->ratio_control) + && memcmp(&cur_dispbuf->pic_mode, + &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + else if (memcmp(&cur_dispbuf->pic_mode, + &gPic_info[0], + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + } if ((last_process_3d_type != process_3d_type) || (last_el_status != vf_with_el)) @@ -3991,6 +4018,9 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) if (iret == VppFilter_Success_and_Changed) video_property_changed = 1; + memcpy(&gPic_info[0], &vf->pic_mode, + sizeof(struct vframe_pic_mode_s)); + /* apply new vpp settings */ frame_par_ready_to_set = 1; @@ -12779,6 +12809,7 @@ static int __init video_init(void) /* make vd1 below vd2 */ for (i = 0; i < MAX_VD_LAYERS; i++) { vpp_disp_info_init(&glayer_info[i], i); + memset(&gPic_info[i], 0, sizeof(struct vframe_pic_mode_s)); glayer_info[i].wide_mode = 1; glayer_info[i].zorder = reference_zorder - 2 + i; glayer_info[i].cur_sel_port = i; From 8381ed64294cf43666b6a5a4395b20d1b67d38e1 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 14 Mar 2019 17:44:33 +0800 Subject: [PATCH 0328/1060] gdc: fix gdc buffer index error caused crash issue [1/2] PD#SWPL-5685 Problem: gdc buffer index error when dma alloc called simultaneously Solution: add lock to gdc buffer index Verify: verified by w400 Change-Id: Ia5e41562675b594029fd5a0166561c0069739536 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 43 ++++++++++++---------- drivers/amlogic/media/gdc/app/gdc_module.c | 10 ++++- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 624fe7b15fc2..d21579998533 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -54,7 +54,8 @@ static void aml_dma_put(void *buf_priv) clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); kfree(buf); - gdc_log(LOG_INFO, "gdc aml_dma_put free!\n"); + gdc_log(LOG_INFO, "gdc free:aml_dma_buf=0x%p,buf->index=%d\n", + buf, buf->index); } static void *aml_dma_alloc(struct device *dev, unsigned long attrs, @@ -89,8 +90,8 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, buf->dma_dir = dma_dir; atomic_inc(&buf->refcount); - gdc_log(LOG_INFO, "aml_dma_alloc, refcont=%d\n", - atomic_read(&buf->refcount)); + gdc_log(LOG_INFO, "aml_dma_buf=0x%p, refcont=%d\n", + buf, atomic_read(&buf->refcount)); return buf; } @@ -345,7 +346,11 @@ static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index) { + mutex_lock(&(buffer->lock)); + buffer->gd_buffer[index].mem_priv = NULL; + buffer->gd_buffer[index].index = 0; buffer->gd_buffer[index].alloc = 0; + mutex_unlock(&(buffer->lock)); } void *gdc_dma_buffer_create(void) @@ -375,6 +380,7 @@ int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, struct device *dev, struct gdc_dmabuf_req_s *gdc_req_buf) { + struct aml_dma_buf *dma_buf; void *buf; unsigned int size; int index; @@ -389,20 +395,23 @@ int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, size = PAGE_ALIGN(gdc_req_buf->len); if (size == 0) return (-EINVAL); - - index = find_empty_dma_buffer(buffer); - if ((index < 0) || (index >= AML_MAX_DMABUF)) { - pr_err("no empty buffer found\n"); - return (-ENOMEM); - } - buf = aml_dma_alloc(dev, 0, size, gdc_req_buf->dma_dir, GFP_HIGHUSER | __GFP_ZERO); if (!buf) return (-ENOMEM); + dma_buf = (struct aml_dma_buf *)buf; + mutex_lock(&(buffer->lock)); + index = find_empty_dma_buffer(buffer); + if ((index < 0) || (index >= AML_MAX_DMABUF)) { + pr_err("no empty buffer found\n"); + dma_free_attrs(dev, dma_buf->size, dma_buf->cookie, + dma_buf->dma_addr, + dma_buf->attrs); + mutex_unlock(&(buffer->lock)); + return (-ENOMEM); + } ((struct aml_dma_buf *)buf)->priv = buffer; ((struct aml_dma_buf *)buf)->index = index; - mutex_lock(&(buffer->lock)); buffer->gd_buffer[index].mem_priv = buf; buffer->gd_buffer[index].index = index; buffer->gd_buffer[index].alloc = 1; @@ -452,7 +461,6 @@ int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, pr_err("aml_dma_buf is null\n"); return (-EINVAL); } - dbuf = get_dmabuf(buf, flags & O_ACCMODE); if (IS_ERR_OR_NULL(dbuf)) { pr_err("failed to export buffer %d\n", index); @@ -465,7 +473,6 @@ int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, dma_buf_put(dbuf); return ret; } - gdc_log(LOG_INFO, "buffer %d,exported as %d descriptor\n", index, ret); gdc_exp_buf->fd = ret; @@ -491,21 +498,19 @@ int gdc_dma_buffer_map(struct aml_dma_cfg *cfg) fd = cfg->fd; dev = cfg->dev; dir = cfg->dir; - dbuf = dma_buf_get(fd); - if (dbuf == NULL) { + if (IS_ERR(dbuf)) { pr_err("failed to get dma buffer"); return -EINVAL; } - d_att = dma_buf_attach(dbuf, dev); - if (d_att == NULL) { + if (IS_ERR(d_att)) { pr_err("failed to set dma attach"); goto attach_err; } sg = dma_buf_map_attachment(d_att, dir); - if (sg == NULL) { + if (IS_ERR(sg)) { pr_err("failed to get dma sg"); goto map_attach_err; } @@ -540,7 +545,6 @@ map_attach_err: attach_err: dma_buf_put(dbuf); - return ret; } @@ -588,7 +592,6 @@ void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg) vaddr = cfg->vaddr; d_att = cfg->attach; sg = cfg->sg; - dma_buf_vunmap(dbuf, vaddr); dma_buf_end_cpu_access(dbuf, dir); diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index e698bafb1f66..657cd405e5bb 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -551,6 +551,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, } gdc_log(LOG_INFO, "1 plane get input addr=%x\n", gdc_cmd->y_base_addr); + gdc_buffer_dma_flush(gs_ex->input_buffer.shared_fd); } else if (gs_ex->input_buffer.plane_number == 2) { cfg = &fh->dma_cfg.input_cfg_plane1; cfg->fd = gs_ex->input_buffer.y_base_fd; @@ -564,6 +565,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } gdc_cmd->y_base_addr = addr; + gdc_buffer_dma_flush(gs_ex->input_buffer.y_base_fd); cfg = &fh->dma_cfg.input_cfg_plane2; cfg->fd = gs_ex->input_buffer.uv_base_fd; cfg->dev = &fh->gdev->pdev->dev; @@ -576,6 +578,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } gdc_cmd->uv_base_addr = addr; + gdc_buffer_dma_flush(gs_ex->input_buffer.uv_base_fd); gdc_log(LOG_INFO, "2 plane get input addr=%x\n", gdc_cmd->y_base_addr); gdc_log(LOG_INFO, "2 plane get input addr=%x\n", @@ -596,6 +599,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, } gdc_cmd->y_base_addr = addr; gdc_cmd->uv_base_addr = 0; + gdc_buffer_dma_flush(gs_ex->input_buffer.shared_fd); break; default: gdc_log(LOG_ERR, "Error image format"); @@ -691,7 +695,9 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, } } else if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - gdc_process_input_dma_info(fh, gs_ex); + ret = gdc_process_input_dma_info(fh, gs_ex); + if (ret < 0) + return -EINVAL; } gdc_log(LOG_INFO, "%s, input addr=%x\n", __func__, fh->gdc_cmd.y_base_addr); @@ -923,7 +929,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, gdc_log(LOG_ERR, "copy from user failed\n"); memcpy(&gdc_cmd->gdc_config, &gs_ex.gdc_config, sizeof(struct gdc_config_s)); - gdc_process_ex_info(fh, &gs_ex); + ret = gdc_process_ex_info(fh, &gs_ex); break; case GDC_REQUEST_DMA_BUFF: ret = copy_from_user(&gdc_req_buf, argp, From ea0c38d06ac5087c654567d9d70393ba37382ea5 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 14 Mar 2019 18:02:35 +0800 Subject: [PATCH 0329/1060] ge2d: fix ge2d buffer index error caused crash issue [2/2] PD#SWPL-5685 Problem: ge2d buffer index error when dma alloc called simultaneously Solution: add lock to ge2d buffer index Verify: verified by w400 Change-Id: I1efa4127fbcb939ade457a890769d59a146a0798 Signed-off-by: Pengcheng Chen --- .../amlogic/media/common/ge2d/ge2d_dmabuf.c | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 2e8a8a7beb3b..9a6087a4fdf9 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -53,7 +53,8 @@ static void aml_dma_put(void *buf_priv) clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); kfree(buf); - ge2d_log_dbg("ge2d aml_dma_put free!\n"); + ge2d_log_dbg("ge2d free:aml_dma_buf=0x%p,buf->index=%d\n", + buf, buf->index); } static void *aml_dma_alloc(struct device *dev, unsigned long attrs, @@ -88,8 +89,8 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, buf->dma_dir = dma_dir; atomic_inc(&buf->refcount); - ge2d_log_dbg("aml_dma_alloc, refcont=%d\n", - atomic_read(&buf->refcount)); + ge2d_log_dbg("aml_dma_buf=0x%p, refcont=%d\n", + buf, atomic_read(&buf->refcount)); return buf; } @@ -343,7 +344,11 @@ static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index) { + mutex_lock(&(buffer->lock)); + buffer->gd_buffer[index].mem_priv = NULL; + buffer->gd_buffer[index].index = 0; buffer->gd_buffer[index].alloc = 0; + mutex_unlock(&(buffer->lock)); } void *ge2d_dma_buffer_create(void) @@ -373,6 +378,7 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, struct device *dev, struct ge2d_dmabuf_req_s *ge2d_req_buf) { + struct aml_dma_buf *dma_buf; void *buf; unsigned int size; int index; @@ -388,19 +394,23 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, if (size == 0) return (-EINVAL); - index = find_empty_dma_buffer(buffer); - if ((index < 0) || (index >= AML_MAX_DMABUF)) { - pr_err("no empty buffer found\n"); - return (-ENOMEM); - } - buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir, GFP_HIGHUSER | __GFP_ZERO); if (!buf) return (-ENOMEM); + dma_buf = (struct aml_dma_buf *)buf; + mutex_lock(&(buffer->lock)); + index = find_empty_dma_buffer(buffer); + if ((index < 0) || (index >= AML_MAX_DMABUF)) { + pr_err("no empty buffer found\n"); + dma_free_attrs(dev, dma_buf->size, dma_buf->cookie, + dma_buf->dma_addr, + dma_buf->attrs); + mutex_unlock(&(buffer->lock)); + return (-ENOMEM); + } ((struct aml_dma_buf *)buf)->priv = buffer; ((struct aml_dma_buf *)buf)->index = index; - mutex_lock(&(buffer->lock)); buffer->gd_buffer[index].mem_priv = buf; buffer->gd_buffer[index].index = index; buffer->gd_buffer[index].alloc = 1; @@ -490,19 +500,19 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg) dir = cfg->dir; dbuf = dma_buf_get(fd); - if (dbuf == NULL) { + if (IS_ERR(dbuf)) { pr_err("failed to get dma buffer"); return -EINVAL; } d_att = dma_buf_attach(dbuf, dev); - if (d_att == NULL) { + if (IS_ERR(d_att)) { pr_err("failed to set dma attach"); goto attach_err; } sg = dma_buf_map_attachment(d_att, dir); - if (sg == NULL) { + if (IS_ERR(sg)) { pr_err("failed to get dma sg"); goto map_attach_err; } From 663f5c0da6614aa6d4138bb0b8c26f727722d345 Mon Sep 17 00:00:00 2001 From: Xingyu Chen Date: Mon, 18 Mar 2019 13:36:09 +0800 Subject: [PATCH 0330/1060] pinctrl: gxl: add new group definition for support TEST_N used as i2sout [1/1] PD#OTT-2745 Problem: TEST_N used only as gpio, and don't support other function Solution: add new group definition for support TEST_N used as i2sout Verify: test pass on P212 Change-Id: I47103b27df9baf21537e82b48ad18911a355f873 Signed-off-by: Xingyu Chen --- drivers/amlogic/pinctrl/pinctrl-meson-gxl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c b/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c index a98e3e46c3c0..9366a7705d85 100644 --- a/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c +++ b/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c @@ -755,6 +755,7 @@ static const unsigned int ee_cec_pins[] = { GPIOAO_8 }; /*i2s_out_ao*/ static const unsigned int i2sout_ch23_ao8_pins[] = { GPIOAO_8 }; static const unsigned int i2sout_ch45_ao9_pins[] = { GPIOAO_9 }; +static const unsigned int i2sout_ch67_tn_pins[] = { GPIO_TEST_N }; /*spdif_out_ao*/ static const unsigned int spdid_out_ao9_pins[] = { GPIOAO_9 }; @@ -793,13 +794,14 @@ static struct meson_pmx_group meson_gxl_aobus_groups[] = { GROUP(ir_out_ao7, 0, 21), GROUP(ao_cec, 0, 15), GROUP(ee_cec, 0, 14), - GROUP(i2sout_ch23_ao8, 2, 0), + GROUP(i2sout_ch23_ao8, 1, 0), GROUP(pwm_ao_a_ao8, 0, 17), GROUP(ir_out_ao9, 0, 31), GROUP(spdid_out_ao6, 0, 16), GROUP(spdid_out_ao9, 0, 4), - GROUP(i2sout_ch45_ao9, 2, 1), + GROUP(i2sout_ch45_ao9, 1, 1), GROUP(pwm_ao_b_ao9, 0, 3), + GROUP(i2sout_ch67_tn, 1, 2), }; static const char * const gpio_periphs_groups[] = { @@ -1093,6 +1095,7 @@ static const char * const pwm_ao_b_groups[] = { static const char * const i2s_out_ao_groups[] = { "i2sout_ch23_ao8", "i2sout_ch45_ao9", + "i2sout_ch67_tn", }; static const char * const spdif_out_ao_groups[] = { From 8c2c59459cf32bad3d3fd749991200065405dc9e Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 15 Mar 2019 17:21:08 +0800 Subject: [PATCH 0331/1060] osd: reset afbcd flag when convert format value [1/1] PD#SWPL-5185 Problem: "fence color format error 28" when test weston-simple-egl Solution: reset afbcd flag when convert format value Verify: Locally on g12b_w400 Change-Id: I81a9394288026bc596f6b3438cec72ceaad7749f Signed-off-by: Jian Cao --- drivers/amlogic/media/osd/osd_hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index bd4caefdc64b..c6bd417ae316 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -9516,6 +9516,7 @@ static const struct color_bit_define_s *convert_panel_format(u32 format) { const struct color_bit_define_s *color = NULL; + format &= ~AFBC_EN; switch (format) { case COLOR_INDEX_02_PAL4: case COLOR_INDEX_04_PAL16: From 1c15b2d01a4dd96c76678cbda53fea66b59e7413 Mon Sep 17 00:00:00 2001 From: Xingyu Chen Date: Thu, 21 Mar 2019 11:26:09 +0800 Subject: [PATCH 0332/1060] remote: fix compatibility issue for RC5 protocol [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-6161 Problem: partial ir-keys with RC5 can’t been decoded on some boards(Eg: TL1, TXLX) Solution: adjust the register to extend the detection range of half/whole bit Verify: test pass on TL1 Change-Id: I6ff0af79b3bf9f624c1f249f056b729df7b5dd0c Signed-off-by: Xingyu Chen --- drivers/amlogic/input/remote/remote_regmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/input/remote/remote_regmap.c b/drivers/amlogic/input/remote/remote_regmap.c index 2d9f42404247..93c9697822b3 100644 --- a/drivers/amlogic/input/remote/remote_regmap.c +++ b/drivers/amlogic/input/remote/remote_regmap.c @@ -108,9 +108,9 @@ static struct remote_reg_map regs_default_rc5[] = { /*bit[0-3]: RC5; bit[8]: MSB first mode; bit[11]: compare frame method*/ { REG_REG2, ((1 << 13) | (1 << 11) | (1 << 8) | 0x7)}, /*Half bit for RC5 format: 888.89us*/ - { REG_DURATN2, ((49 << 16) | (40 << 0))}, + { REG_DURATN2, ((53 << 16) | (38 << 0))}, /*RC5 typically 1777.78us for whole bit*/ - { REG_DURATN3, ((94 << 16) | (83 << 0))}, + { REG_DURATN3, ((99 << 16) | (81 << 0))}, { REG_REG3, 0} }; From 725b5742a496ff8d3a5c86a1918e086265145f1c Mon Sep 17 00:00:00 2001 From: Dezhi Kong Date: Thu, 7 Mar 2019 14:06:41 +0800 Subject: [PATCH 0333/1060] drm: a113d support drm issue [1/1] PD#SH-397 Problem: use modetest to test A113D DRM function, displaying is incorrect Solution: add linear addr config for a113d drm mode Verify: verified on s400 Change-Id: Id6a2c6ad94bc0148815076561d9dc2ae8ded6884 Signed-off-by: Dezhi Kong --- drivers/amlogic/media/osd/osd_hw.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index c6bd417ae316..15fad4f1409c 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -9565,11 +9565,17 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) plane_map->byte_stride * plane_map->src_h; osd_log_dbg(MODULE_RENDER, "canvas_id=%x, phy_addr=%x\n", osd_hw.fb_gem[index].canvas_idx, phy_addr); - canvas_config(osd_hw.fb_gem[index].canvas_idx, - phy_addr, - plane_map->byte_stride, - plane_map->src_h, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) { + osd_hw.fb_gem[index].addr = phy_addr; + osd_hw.fb_gem[index].width = plane_map->byte_stride; + osd_update_phy_addr(0); + } else { + canvas_config(osd_hw.fb_gem[index].canvas_idx, + phy_addr, + plane_map->byte_stride, + plane_map->src_h, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + } if (osd_hw.hwc_enable) { /* just get para, need update via do_hwc */ osd_hw.order[index] = plane_map->zorder; From c9f28319036b91ab32d26961d3b2f74eb5b85d17 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Fri, 4 Jan 2019 23:03:28 +0800 Subject: [PATCH 0334/1060] amvecm: fix atv scaled when switch between different formats [1/3] PD#SWPL-3883 Problem: atv picture flash when switch channel between different formats Solution: fresh atv overscan on vync Verify: txhd Change-Id: I74f8e64c12031dbc321675c4b1dbc54adcd3721d Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amve.c | 47 ++++++++++- .../amlogic/media/enhancement/amvecm/amvecm.c | 79 ++++++++++++------- include/linux/amlogic/media/amvecm/amvecm.h | 17 +++- 3 files changed, 109 insertions(+), 34 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index 6bc63d664cf1..33e1c9d53e3c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -1409,11 +1409,14 @@ void amvecm_fresh_overscan(struct vframe_s *vf) { unsigned int height = 0; unsigned int cur_overscan_timing = 0; + unsigned int cur_fmt; + unsigned int offset = TIMING_UHD + 1;/*av&atv*/ if (overscan_disable) return; if (is_dolby_vision_on()) return; + if (overscan_table[0].load_flag) { height = (vf->type & VIDTYPE_COMPRESS) ? vf->compHeight : vf->height; @@ -1445,19 +1448,57 @@ void amvecm_fresh_overscan(struct vframe_s *vf) vf->pic_mode.ve = overscan_table[overscan_timing].ve; vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE; } + if (overscan_table[offset].load_flag) { + cur_fmt = vf->sig_fmt; + if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_M) + cur_overscan_timing = TIMING_NTST_M; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_443) + cur_overscan_timing = TIMING_NTST_443; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_I) + cur_overscan_timing = TIMING_PAL_I; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_M) + cur_overscan_timing = TIMING_PAL_M; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_60) + cur_overscan_timing = TIMING_PAL_60; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_CN) + cur_overscan_timing = TIMING_PAL_CN; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_SECAM) + cur_overscan_timing = TIMING_SECAM; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_50) + cur_overscan_timing = TIMING_NTSC_50; + else + return; + overscan_timing = cur_overscan_timing; + overscan_screen_mode = + overscan_table[overscan_timing].screen_mode; + vf->pic_mode.AFD_enable = + overscan_table[overscan_timing].afd_enable; + vf->pic_mode.screen_mode = overscan_screen_mode; + vf->pic_mode.hs = overscan_table[overscan_timing].hs; + vf->pic_mode.he = overscan_table[overscan_timing].he; + vf->pic_mode.vs = overscan_table[overscan_timing].vs; + vf->pic_mode.ve = overscan_table[overscan_timing].ve; + vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE; + } } void amvecm_reset_overscan(void) { + unsigned int offset = TIMING_UHD + 1;/*av&atv*/ + enum ve_source_input_e source0; + + source0 = overscan_table[0].source; if (overscan_disable) return; if (overscan_timing != TIMING_MAX) { overscan_timing = TIMING_MAX; - if ((overscan_table[0].source != SOURCE_DTV) && - (overscan_table[0].source != SOURCE_MPEG)) { + if ((source0 != SOURCE_DTV) && (source0 != SOURCE_MPEG)) overscan_table[0].load_flag = 0; + else if (!atv_source_flg) + overscan_table[offset].load_flag = 0; + if ((source0 != SOURCE_DTV) && (source0 != SOURCE_MPEG) + && !atv_source_flg) overscan_screen_mode = 0xff; - } } } diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index e93029b5fd4e..e805cc30e404 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -117,7 +117,7 @@ static unsigned int pre_hist_height, pre_hist_width; static unsigned int pc_mode = 0xff; static unsigned int pc_mode_last = 0xff; static struct hdr_metadata_info_s vpp_hdr_metadata_s; - +unsigned int atv_source_flg; /*bit0: brightness *bit1: brightness2 *bit2: saturation_hue @@ -1303,6 +1303,41 @@ static int gamma_table_compare(struct tcon_gamma_table_s *table1, return flag; } +static void parse_overscan_table(unsigned int length, + struct ve_pq_table_s *amvecm_pq_load_table) +{ + unsigned int i; + unsigned int offset = TIMING_UHD + 1; + + memset(overscan_table, 0, sizeof(overscan_table)); + for (i = 0; i < length; i++) { + overscan_table[i].load_flag = + (amvecm_pq_load_table[i].src_timing >> 31) & 0x1; + overscan_table[i].afd_enable = + (amvecm_pq_load_table[i].src_timing >> 30) & 0x1; + overscan_table[i].screen_mode = + (amvecm_pq_load_table[i].src_timing >> 24) & 0x3f; + overscan_table[i].source = + (amvecm_pq_load_table[i].src_timing >> 16) & 0xff; + overscan_table[i].timing = + amvecm_pq_load_table[i].src_timing & 0xffff; + overscan_table[i].hs = + amvecm_pq_load_table[i].value1 & 0xffff; + overscan_table[i].he = + (amvecm_pq_load_table[i].value1 >> 16) & 0xffff; + overscan_table[i].vs = + amvecm_pq_load_table[i].value2 & 0xffff; + overscan_table[i].ve = + (amvecm_pq_load_table[i].value2 >> 16) & 0xffff; + } + /*because SOURCE_TV is 0,so need to add a flg to check ATV*/ + if ((overscan_table[offset].load_flag == 1) && + (overscan_table[offset].source == SOURCE_TV)) + atv_source_flg = 1; + else + atv_source_flg = 0; +} + static long amvecm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1311,7 +1346,6 @@ static long amvecm_ioctl(struct file *file, unsigned int mem_size; struct ve_pq_load_s vpp_pq_load; struct ve_pq_table_s *vpp_pq_load_table = NULL; - int i = 0; enum color_primary_e color_pri; if (debug_amvecm & 2) @@ -1494,7 +1528,8 @@ static long amvecm_ioctl(struct file *file, break; } /*check pq_table length copy_from_user*/ - if (vpp_pq_load.length > PQ_TABLE_MAX_LENGTH) { + if ((vpp_pq_load.length > TIMING_MAX) || + (vpp_pq_load.length <= 0)) { ret = -EFAULT; pr_amvecm_dbg("[amvecm..] pq ioctl length check fail!!\n"); break; @@ -1511,28 +1546,7 @@ static long amvecm_ioctl(struct file *file, pr_amvecm_dbg("[amvecm..] ovescan copy fail!!\n"); break; } - for (i = 0; i < vpp_pq_load.length; i++) { - if (i >= TIMING_MAX) - break; - overscan_table[i].load_flag = - (vpp_pq_load_table[i].src_timing >> 31) & 0x1; - overscan_table[i].afd_enable = - (vpp_pq_load_table[i].src_timing >> 30) & 0x1; - overscan_table[i].screen_mode = - (vpp_pq_load_table[i].src_timing >> 24) & 0x3f; - overscan_table[i].source = - (vpp_pq_load_table[i].src_timing >> 16) & 0xff; - overscan_table[i].timing = - vpp_pq_load_table[i].src_timing & 0xffff; - overscan_table[i].hs = - vpp_pq_load_table[i].value1 & 0xffff; - overscan_table[i].he = - (vpp_pq_load_table[i].value1 >> 16) & 0xffff; - overscan_table[i].vs = - vpp_pq_load_table[i].value2 & 0xffff; - overscan_table[i].ve = - (vpp_pq_load_table[i].value2 >> 16) & 0xffff; - } + parse_overscan_table(vpp_pq_load.length, vpp_pq_load_table); break; case AMVECM_IOC_G_DNLP_STATE: if (copy_to_user((void __user *)arg, @@ -4855,7 +4869,7 @@ static ssize_t amvecm_debug_store(struct class *cla, { char *buf_orig, *parm[8] = {NULL}; long val = 0; - unsigned int mode_sel, color, color_mode; + unsigned int mode_sel, color, color_mode, i; if (!buf) return count; @@ -5255,9 +5269,18 @@ static ssize_t amvecm_debug_store(struct class *cla, cm_luma_bri_con(rd, bri, con, blk_lel); pr_info("cm hist bri_con set success\n"); } - } else { + } else if (!strcmp(parm[0], "dump_overscan_table")) { + for (i = 0; i < TIMING_MAX; i++) { + pr_info("*****dump overscan_tab[%d]*****\n", i); + pr_info("hs:%d, he:%d, vs:%d, ve:%d, screen_mode:%d, afd:%d, flag:%d.\n", + overscan_table[i].hs, overscan_table[i].he, + overscan_table[i].vs, overscan_table[i].ve, + overscan_table[i].screen_mode, + overscan_table[i].afd_enable, + overscan_table[i].load_flag); + } + } else pr_info("unsupport cmd\n"); - } kfree(buf_orig); return count; diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index bcae14831f45..1c39e101b362 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -135,9 +135,6 @@ enum pq_table_name_e { TABLE_NAME_MAX, }; -/*check pq_table length copy_from_user*/ -#define PQ_TABLE_MAX_LENGTH 10000 - #define _VE_CM 'C' #define AMVECM_IOC_G_HIST_AVG _IOW(_VE_CM, 0x22, struct ve_hist_s) @@ -296,11 +293,23 @@ enum ve_source_input_e { SOURCE_MAX, }; +/*pq_timing: + *SD/HD/FHD/UHD for DTV/MEPG, + *NTST_M/NTST_443/PAL_I/PAL_M/PAL_60/PAL_CN/SECAM/NTST_50 for AV/ATV + */ enum ve_pq_timing_e { TIMING_SD = 0, TIMING_HD, TIMING_FHD, TIMING_UHD, + TIMING_NTST_M, + TIMING_NTST_443, + TIMING_PAL_I, + TIMING_PAL_M, + TIMING_PAL_60, + TIMING_PAL_CN, + TIMING_SECAM, + TIMING_NTSC_50, TIMING_MAX, }; @@ -401,6 +410,8 @@ static inline uint32_t READ_VPP_REG_BITS(uint32_t reg, extern signed int vd1_brightness, vd1_contrast; extern bool gamma_en; extern unsigned int hdr_source_type; +extern unsigned int atv_source_flg; + #define CSC_FLAG_TOGGLE_FRAME 1 #define CSC_FLAG_CHECK_OUTPUT 2 From a099be428b0331424ea4cda4f87d1df403d3f79e Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Wed, 20 Mar 2019 21:10:40 +0800 Subject: [PATCH 0335/1060] audio: Image signal delay of 1.5 seconds when switching to AV source [1/2] PD#TV-3067 Problem: Image signal delay of 1.5 seconds when switching to AV source. Solution: 1.add av audio control for audio patch. Verify: verified by x301 Change-Id: I3e820923a26439b3aeb9841562b81cd6d55ed4ea Signed-off-by: nengwen.chen --- include/linux/amlogic/media/sound/misc.h | 9 +++++++++ sound/soc/amlogic/auge/extn.c | 7 +++++++ sound/soc/amlogic/common/misc.c | 14 ++++++++++++++ sound/soc/amlogic/meson/tv.c | 18 +----------------- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/include/linux/amlogic/media/sound/misc.h b/include/linux/amlogic/media/sound/misc.h index 7f3edbfb5bcd..25341c2e18be 100644 --- a/include/linux/amlogic/media/sound/misc.h +++ b/include/linux/amlogic/media/sound/misc.h @@ -31,6 +31,15 @@ int aml_get_atv_audio_stable( #endif +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT +extern int tvin_get_av_status(void); +extern const struct soc_enum av_audio_status_enum; + +extern int aml_get_av_audio_stable( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +#endif + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI extern int update_spdifin_audio_type(int audio_type); diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index ad7aacbe7a22..07d31ee2e8ee 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -772,6 +772,13 @@ static const struct snd_kcontrol_new extn_controls[] = { NULL), #endif +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT + SOC_ENUM_EXT("AV audio stable", + av_audio_status_enum, + aml_get_av_audio_stable, + NULL), +#endif + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI SOC_ENUM_EXT("HDMIIN audio stable", hdmi_in_status_enum[0], diff --git a/sound/soc/amlogic/common/misc.c b/sound/soc/amlogic/common/misc.c index 42d7e23438d1..fc15a68f4de1 100644 --- a/sound/soc/amlogic/common/misc.c +++ b/sound/soc/amlogic/common/misc.c @@ -47,6 +47,20 @@ int aml_get_atv_audio_stable( } #endif /* CONFIG_AMLOGIC_ATV_DEMOD */ +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT + +const struct soc_enum av_audio_status_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_is_stable), + audio_is_stable); + +int aml_get_av_audio_stable(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = tvin_get_av_status(); + return 0; +} +#endif /* CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT */ + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI int hdmiin_fifo_disable_count; diff --git a/sound/soc/amlogic/meson/tv.c b/sound/soc/amlogic/meson/tv.c index 6c184fd8497a..a5b00f110581 100644 --- a/sound/soc/amlogic/meson/tv.c +++ b/sound/soc/amlogic/meson/tv.c @@ -562,22 +562,6 @@ static int aml_set_arc_audio(struct snd_kcontrol *kcontrol, } #endif -#ifdef CONFIG_TVIN_VDIN -static const char *const av_audio_is_stable[] = { - "false", - "true" -}; -static const struct soc_enum av_audio_status_enum = - SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(av_audio_is_stable), - av_audio_is_stable); -static int aml_get_av_audio_stable(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = tvin_get_av_status(); - return 0; -} -#endif /* CONFIG_TVIN_VDIN */ - static const struct snd_kcontrol_new av_controls[] = { SOC_ENUM_EXT("AudioIn Switch", audio_in_switch_enum, @@ -641,7 +625,7 @@ static const struct snd_kcontrol_new aml_tv_controls[] = { aml_get_atv_audio_stable, NULL), #endif -#ifdef CONFIG_TVIN_VDIN +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT SOC_ENUM_EXT("AV audio stable", av_audio_status_enum, aml_get_av_audio_stable, NULL), From 868c936f3353fb7d6e744be5dfff04ee4cf81e6a Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Mon, 25 Mar 2019 17:28:35 +0800 Subject: [PATCH 0336/1060] dtv_demod: playing dtmb is not smooth when signal is non-standard [1/1] PD#SWPL-6286 Problem: tps of non-standard signal is incorrect Solution: ignore calculating amplitude tps Verify: verified by t962x2_x301 Change-Id: Ibd3ff7bfe56ca604ad99fa7c6f457202c227c9ae Signed-off-by: zhiwei.yuan --- drivers/amlogic/media/dtv_demod/dtmb_func.c | 6 ++++++ drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/amlogic/media/dtv_demod/dtmb_func.c b/drivers/amlogic/media/dtv_demod/dtmb_func.c index 784690961b0a..90e7714e95ab 100644 --- a/drivers/amlogic/media/dtv_demod/dtmb_func.c +++ b/drivers/amlogic/media/dtv_demod/dtmb_func.c @@ -198,6 +198,12 @@ void dtmb_all_reset(void) dtmb_write_reg(DTMB_CHE_FD_TD_COEFF, temp_data); } } + + /*for non-standard signal, + *ignore calculatiing amplitude tps(transport parameter signalling) + */ + dtmb_write_reg(DTMB_CHE_IBDFE_CONF0, + dtmb_read_reg(DTMB_CHE_IBDFE_CONF0) & 0xfffff0ff); } void dtmb_initial(struct aml_demod_sta *demod_sta) diff --git a/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h b/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h index 34c28cba4cdf..7252c1ad23a6 100644 --- a/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h +++ b/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h @@ -22,6 +22,7 @@ #define DTMB_CHE_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) +#define DTMB_CHE_IBDFE_CONF0 DTMB_CHE_ADDR(0x8b) #define DTMB_CHE_TE_HREB_SNR DTMB_CHE_ADDR(0x8d) #define DTMB_CHE_MC_SC_TIMING_POWTHR DTMB_CHE_ADDR(0x8e) #define DTMB_CHE_MC_SC_PROTECT_GD DTMB_CHE_ADDR(0x8f) From 20cedb3f4ce01e033ae6f89d6f5ccf78a5d39bb7 Mon Sep 17 00:00:00 2001 From: "shihong.zheng" Date: Tue, 26 Mar 2019 18:40:27 +0800 Subject: [PATCH 0337/1060] pts: fix mvc play is not smooth. [1/1] PD#SWPL-6094 Problem: some mvc stream is not smooth. Solution: optimize the condition for pts loockup fail code. Verify: x301 Change-Id: I50bb3f317e1245735f9ce0ffcc44376c91e871ed Signed-off-by: shihong.zheng --- drivers/amlogic/media/frame_sync/ptsserv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/frame_sync/ptsserv.c b/drivers/amlogic/media/frame_sync/ptsserv.c index 82e1213f33ae..0930068c7f21 100644 --- a/drivers/amlogic/media/frame_sync/ptsserv.c +++ b/drivers/amlogic/media/frame_sync/ptsserv.c @@ -752,10 +752,11 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, p2 = p; } + /* if p2 lookup fail, set p2 = p */ if (type == PTS_TYPE_VIDEO && p2 && p && OFFSET_DIFF(offset, p2->offset) > lookup_threshold && - OFFSET_DIFF(offset, p->offset) < lookup_threshold) + abs(OFFSET_DIFF(offset, p->offset)) < lookup_threshold) p2 = p; } else if (OFFSET_LATER(p->offset, offset)) { list_for_each_entry_continue_reverse(p, From f89996cf8902e18e0dcfce2826fc04f379c05c17 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Tue, 26 Mar 2019 19:13:27 +0800 Subject: [PATCH 0338/1060] vpp: including crop info when AFBC switch to normal frame [1/1] PD#SWPL-6347 Problem: When AFBC switch to normal frame, excluding the crop information, the pps parameters are calculated with wrong input size. Solution: 1.Add the crop information, when afbc swicth to normal frame. 2.check ratio of compress_width/width, sync to crop value Verify: verified on x301 Change-Id: Ib943f8a11263ce577952e589bc172d8b7bafd954 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/vpp.c | 94 +++++++++++++++----------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index e47ee2854a37..ad8151fe8117 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -884,6 +884,8 @@ static int vpp_set_filters_internal( u32 vert_chroma_filter; struct filter_info_s *cur_filter; s32 vpp_zoom_center_x, vpp_zoom_center_y; + u32 crop_ratio = 1; + u32 crop_left, crop_right, crop_top, crop_bottom; if (!input) return VppFilter_Fail; @@ -919,20 +921,6 @@ static int vpp_set_filters_internal( video_source_crop_bottom = input->crop_bottom; } - if (likely(w_in > - (video_source_crop_left + video_source_crop_right))) { - w_in -= video_source_crop_left; - w_in -= video_source_crop_right; - h_crop_enable = true; - } - - if (likely(h_in > - (video_source_crop_top + video_source_crop_bottom))) { - h_in -= video_source_crop_top; - h_in -= video_source_crop_bottom; - v_crop_enable = true; - } - #ifndef TV_3D_FUNCTION_OPEN next_frame_par->vscale_skip_count = 0; next_frame_par->hscale_skip_count = 0; @@ -954,6 +942,26 @@ static int vpp_set_filters_internal( else vskip_step = 1; +RESTART_ALL: + crop_left = video_source_crop_left / crop_ratio; + crop_right = video_source_crop_right / crop_ratio; + crop_top = video_source_crop_top / crop_ratio; + crop_bottom = video_source_crop_bottom / crop_ratio; + + if (likely(w_in > + (crop_left + crop_right))) { + w_in -= crop_left; + w_in -= crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (crop_top + crop_bottom))) { + h_in -= crop_top; + h_in -= crop_bottom; + v_crop_enable = true; + } + RESTART: aspect_factor = (vpp_flags & VPP_FLAG_AR_MASK) >> VPP_FLAG_AR_BITS; /* don't use input->wide_mode */ @@ -1215,8 +1223,8 @@ RESTART: } if (v_crop_enable) { - next_frame_par->VPP_vd_start_lines_ += video_source_crop_top; - next_frame_par->VPP_vd_end_lines_ += video_source_crop_top; + next_frame_par->VPP_vd_start_lines_ += crop_top; + next_frame_par->VPP_vd_end_lines_ += crop_top; } if (vpp_flags & VPP_FLAG_INTERLACE_IN) @@ -1333,8 +1341,8 @@ RESTART: } if (h_crop_enable) { - next_frame_par->VPP_hd_start_lines_ += video_source_crop_left; - next_frame_par->VPP_hd_end_lines_ += video_source_crop_left; + next_frame_par->VPP_hd_start_lines_ += crop_left; + next_frame_par->VPP_hd_end_lines_ += crop_left; } next_frame_par->VPP_line_in_length_ = @@ -1430,7 +1438,8 @@ RESTART: h_in = height_in = vf->height; next_frame_par->hscale_skip_count = 0; next_frame_par->vscale_skip_count = 0; - goto RESTART; + crop_ratio = vf->compWidth / vf->width; + goto RESTART_ALL; } if ((skip_policy & 0xf0) && (skip_policy_check == true)) { @@ -2488,6 +2497,8 @@ static int vpp_set_filters_no_scaler_internal( bool reverse = false; #endif int ret = VppFilter_Success; + u32 crop_ratio = 1; + u32 crop_left, crop_right, crop_top, crop_bottom; if (!input) return VppFilter_Fail; @@ -2515,20 +2526,6 @@ static int vpp_set_filters_no_scaler_internal( video_source_crop_bottom = input->crop_bottom; } - if (likely(w_in > - (video_source_crop_left + video_source_crop_right))) { - w_in -= video_source_crop_left; - w_in -= video_source_crop_right; - h_crop_enable = true; - } - - if (likely(h_in > - (video_source_crop_top + video_source_crop_bottom))) { - h_in -= video_source_crop_top; - h_in -= video_source_crop_bottom; - v_crop_enable = true; - } - next_frame_par->vscale_skip_count = 0; next_frame_par->hscale_skip_count = 0; next_frame_par->nocomp = false; @@ -2542,6 +2539,26 @@ static int vpp_set_filters_no_scaler_internal( else vskip_step = 1; +RESTART_ALL: + crop_left = video_source_crop_left / crop_ratio; + crop_right = video_source_crop_right / crop_ratio; + crop_top = video_source_crop_top / crop_ratio; + crop_bottom = video_source_crop_bottom / crop_ratio; + + if (likely(w_in > + (crop_left + crop_right))) { + w_in -= crop_left; + w_in -= crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (crop_top + crop_bottom))) { + h_in -= crop_top; + h_in -= crop_bottom; + v_crop_enable = true; + } + RESTART: /* don't use input->wide_mode */ wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; @@ -2628,8 +2645,8 @@ RESTART: } if (v_crop_enable) { - next_frame_par->VPP_vd_start_lines_ += video_source_crop_top; - next_frame_par->VPP_vd_end_lines_ += video_source_crop_top; + next_frame_par->VPP_vd_start_lines_ += crop_top; + next_frame_par->VPP_vd_end_lines_ += crop_top; } if (vpp_flags & VPP_FLAG_INTERLACE_IN) @@ -2741,8 +2758,8 @@ RESTART: } if (h_crop_enable) { - next_frame_par->VPP_hd_start_lines_ += video_source_crop_left; - next_frame_par->VPP_hd_end_lines_ += video_source_crop_left; + next_frame_par->VPP_hd_start_lines_ += crop_left; + next_frame_par->VPP_hd_end_lines_ += crop_left; } next_frame_par->VPP_line_in_length_ = @@ -2812,7 +2829,8 @@ RESTART: h_in = height_in = vf->height; next_frame_par->hscale_skip_count = 0; next_frame_par->vscale_skip_count = 0; - goto RESTART; + crop_ratio = vf->compWidth / vf->width; + goto RESTART_ALL; } if ((skip_policy & 0xf0) && (skip_policy_check == true)) { From 38c064e2b08294ecef8e12c594a7c1285bc95778 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Mon, 11 Mar 2019 17:48:52 +0800 Subject: [PATCH 0339/1060] gdc: ge2d: output dma_buf need flush when alloc [1/1] PD#SWPL-5685 Problem: gdc output mismatch Solution: output dma_buf need flush when alloc Verify: verified by w400 Change-Id: Ie206b4f51bd1338420f63e0e06563b67d6d63c88 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c | 9 +++++++-- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 9 +++++++-- drivers/amlogic/media/gdc/app/gdc_module.c | 9 +++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 9a6087a4fdf9..41ff5decfa5e 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -378,8 +378,8 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, struct device *dev, struct ge2d_dmabuf_req_s *ge2d_req_buf) { - struct aml_dma_buf *dma_buf; void *buf; + struct aml_dma_buf *dma_buf; unsigned int size; int index; @@ -416,6 +416,11 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, buffer->gd_buffer[index].alloc = 1; mutex_unlock(&(buffer->lock)); ge2d_req_buf->index = index; + dma_buf = (struct aml_dma_buf *)buf; + if (dma_buf->dma_dir == DMA_FROM_DEVICE) + dma_sync_single_for_cpu(dma_buf->dev, + dma_buf->dma_addr, + dma_buf->size, DMA_FROM_DEVICE); return 0; } @@ -646,7 +651,7 @@ void ge2d_dma_buffer_cache_flush(struct device *dev, int fd) return; } if (buf->size > 0) - dma_sync_single_for_device(buf->dev, buf->dma_addr, + dma_sync_single_for_cpu(buf->dev, buf->dma_addr, buf->size, DMA_FROM_DEVICE); dma_buf_put(dmabuf); } diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index d21579998533..a4408abd2369 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -380,8 +380,8 @@ int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, struct device *dev, struct gdc_dmabuf_req_s *gdc_req_buf) { - struct aml_dma_buf *dma_buf; void *buf; + struct aml_dma_buf *dma_buf; unsigned int size; int index; @@ -417,6 +417,11 @@ int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, buffer->gd_buffer[index].alloc = 1; mutex_unlock(&(buffer->lock)); gdc_req_buf->index = index; + dma_buf = (struct aml_dma_buf *)buf; + if (dma_buf->dma_dir == DMA_FROM_DEVICE) + dma_sync_single_for_cpu(dma_buf->dev, + dma_buf->dma_addr, + dma_buf->size, DMA_FROM_DEVICE); return 0; } @@ -643,7 +648,7 @@ void gdc_dma_buffer_cache_flush(struct device *dev, int fd) return; } if (buf->size > 0) - dma_sync_single_for_device(buf->dev, buf->dma_addr, + dma_sync_single_for_cpu(buf->dev, buf->dma_addr, buf->size, DMA_FROM_DEVICE); dma_buf_put(dmabuf); } diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 657cd405e5bb..c13693e1dc46 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -53,6 +53,9 @@ static const struct of_device_id gdc_dt_match[] = { {} }; MODULE_DEVICE_TABLE(of, gdc_dt_match); +static void meson_gdc_cache_flush(struct device *dev, + dma_addr_t addr, + size_t size); ////// static int meson_gdc_open(struct inode *inode, struct file *file) @@ -80,7 +83,7 @@ static int meson_gdc_open(struct inode *inode, struct file *file) fh->gdev = gdc_dev; - gdc_log(LOG_CRIT, "Success open\n"); + gdc_log(LOG_INFO, "Success open\n"); return rc; } @@ -146,7 +149,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh = NULL; if (ret == 0) - gdc_log(LOG_CRIT, "Success release\n"); + gdc_log(LOG_INFO, "Success release\n"); else gdc_log(LOG_ERR, "Error release\n"); @@ -181,6 +184,8 @@ static long meson_gdc_set_buff(void *f_fh, fh->o_paddr = page_to_phys(cma_pages); fh->o_kaddr = phys_to_virt(fh->o_paddr); fh->o_len = len; + meson_gdc_cache_flush(&fh->gdev->pdev->dev, + fh->o_paddr, fh->o_len); break; case CONFIG_BUFF_TYPE: if (fh->c_paddr != 0 && fh->c_kaddr != NULL) From 7d8a72c1acfdfb3ce16ca5b183c1031a10c1bfcf Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Tue, 26 Mar 2019 15:47:49 +0800 Subject: [PATCH 0340/1060] cpufreq: free clk if failed to set 1G for fixpll when cpufreq init. [1/1] PD#SWPL-6394 Problem: free clk if failed to set 1G for fixpll. Solution: free clk if failed to set 1G for fixpll.. Verify: test pass on A311D-W400 Change-Id: I1a7af6fe459c067e34ff8752453a1a04985edb88 Signed-off-by: Hong Guo --- drivers/amlogic/cpufreq/meson-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index 6341825ba722..700e793854bc 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -412,7 +412,7 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) if (ret) { pr_err("%s: error in setting low_freq_clk_p rate!\n", __func__); - return ret; + goto free_clk; } high_freq_clk_p = of_clk_get_by_name(np, HIGH_FREQ_CLK_PARENT); From fcfae3cf47953d1d4b7a21e780831d015c7dfb7f Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Thu, 21 Mar 2019 01:15:54 +0800 Subject: [PATCH 0341/1060] vpp: add black_threshold to disable video when window is too small [1/1] PD#TV-3641 Problem: Add new interface to disable video when window is too small Solution: Add the black_threshold interface to control the threshold size. And set the default value is width=20, height=30. Verify: verified by x301 Change-Id: Ifeb376c2e2edbb5706b2cdc2d08421bd0086b01e Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 64 +++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 1f2034cc90c7..427ca6de7ebe 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -443,6 +443,10 @@ static struct vframe_pic_mode_s gPic_info[MAX_VD_LAYERS]; static u32 reference_zorder = 128; +/* default value 20 30 */ +static s32 black_threshold_width = 20; +static s32 black_threshold_height = 30; + #define MAX_ZOOM_RATIO 300 #define VPP_PREBLEND_VD_V_END_LIMIT 2304 @@ -6088,6 +6092,32 @@ static int vpp_zorder_check(void) return force_flush; } +static bool black_threshold_check(u8 id) +{ + struct disp_info_s *layer = NULL; + bool ret = false; + + if (id >= MAX_VD_LAYERS) + return ret; + + if ((black_threshold_width <= 0) + || (black_threshold_height <= 0)) + return ret; + + layer = &glayer_info[id]; + if ((layer->layer_top == 0) + && (layer->layer_left == 0) + && (layer->layer_width <= 1) + && (layer->layer_height <= 1)) + /* special case to do full screen display */ + return ret; + + if ((layer->layer_width <= black_threshold_width) + || (layer->layer_height <= black_threshold_height)) + ret = true; + return ret; +} + #ifdef TV_3D_FUNCTION_OPEN inline void switch_3dView_per_vsync(void) { @@ -7760,7 +7790,8 @@ SET_FILTER: spin_unlock_irqrestore(&video2_onoff_lock, flags); } - if (video_global_output == 0) { + if ((video_global_output == 0) + || black_threshold_check(0)) { video_enabled = 0; vpp_misc_set &= ~(VPP_VD1_PREBLEND | VPP_VD2_PREBLEND | @@ -7783,7 +7814,8 @@ SET_FILTER: VPP_PREBLEND_EN); #ifdef VIDEO_PIP - if (pip_global_output == 0) { + if ((pip_global_output == 0) + || black_threshold_check(1)) { video2_enabled = 0; vpp_misc_set &= ~(VPP_VD2_PREBLEND | VPP_VD2_POSTBLEND); @@ -11513,6 +11545,30 @@ static ssize_t video_zorder_store( return count; } +static ssize_t black_threshold_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "width: %d, height: %d\n", + black_threshold_width, + black_threshold_height); +} + +static ssize_t black_threshold_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int parsed[2]; + + if (likely(parse_para(buf, 2, parsed) == 2)) { + black_threshold_width = parsed[0]; + black_threshold_height = parsed[1]; + } + return strnlen(buf, count); +} + #ifdef VIDEO_PIP int _videopip_set_disable(u32 val) { @@ -12035,6 +12091,10 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, video_zorder_show, video_zorder_store), + __ATTR(black_threshold, + 0664, + black_threshold_show, + black_threshold_store), __ATTR_RO(frame_addr), __ATTR_RO(frame_canvas_width), __ATTR_RO(frame_canvas_height), From e784c4b2b3c6edcf7b52729a912cbc726b5e7f12 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 21 Mar 2019 17:33:13 +0800 Subject: [PATCH 0342/1060] ge2d: change dma_buf to cacheable [1/2] PD#SWPL-5685 Problem: ge2d output dmabuf have high variance Solution: change dma_buf to cacheable Verify: verified by w400 Change-Id: Iff9356dd256ce69bd87e7e5a2b1feb9e74c49744 Signed-off-by: Pengcheng Chen --- .../amlogic/media/common/ge2d/ge2d_dmabuf.c | 119 +++++++----------- .../amlogic/media/common/ge2d/ge2d_dmabuf.h | 1 - drivers/amlogic/media/common/ge2d/ge2d_wq.c | 1 - 3 files changed, 47 insertions(+), 74 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 41ff5decfa5e..c2362592295b 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "ge2d_log.h" #include "ge2d_dmabuf.h" @@ -38,18 +39,19 @@ static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; + struct page *cma_pages = NULL; if (!atomic_dec_and_test(&buf->refcount)) { ge2d_log_dbg("ge2d aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } - if (buf->sgt_base) { - sg_free_table(buf->sgt_base); - kfree(buf->sgt_base); + cma_pages = virt_to_page(buf->vaddr); + if (!dma_release_from_contiguous(buf->dev, cma_pages, + buf->size >> PAGE_SHIFT)) { + pr_err("failed to release cma buffer\n"); } - dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, - buf->attrs); + buf->vaddr = NULL; clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); kfree(buf); @@ -62,32 +64,31 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, gfp_t gfp_flags) { struct aml_dma_buf *buf; + struct page *cma_pages = NULL; + dma_addr_t paddr = 0; if (WARN_ON(!dev)) return (void *)(-EINVAL); - buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL); + buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL | gfp_flags); if (!buf) return NULL; if (attrs) buf->attrs = attrs; - buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, - gfp_flags, buf->attrs); - if (!buf->cookie) { - dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); - kfree(buf); + cma_pages = dma_alloc_from_contiguous(dev, + size >> PAGE_SHIFT, 0); + if (cma_pages) { + paddr = page_to_phys(cma_pages); + } else { + pr_err("failed to alloc cma pages.\n"); return NULL; } - - if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) - buf->vaddr = buf->cookie; - - /* Prevent the device from being released while the buffer is used */ + buf->vaddr = phys_to_virt(paddr); buf->dev = get_device(dev); buf->size = size; buf->dma_dir = dma_dir; - + buf->dma_addr = paddr; atomic_inc(&buf->refcount); ge2d_log_dbg("aml_dma_buf=0x%p, refcont=%d\n", buf, atomic_read(&buf->refcount)); @@ -98,26 +99,23 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) { struct aml_dma_buf *buf = buf_priv; - int ret; + unsigned long pfn = 0; + unsigned long vsize = vma->vm_end - vma->vm_start; + int ret = -1; - if (!buf) { - pr_err("No buffer to map\n"); + if (!buf || !vma) { + pr_err("No memory to map\n"); return -EINVAL; } - /* - * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to - * map whole buffer - */ - vma->vm_pgoff = 0; - - ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, - buf->dma_addr, buf->size, buf->attrs); - + pfn = virt_to_phys(buf->vaddr) >> PAGE_SHIFT; + ret = remap_pfn_range(vma, vma->vm_start, pfn, + vsize, vma->vm_page_prot); if (ret) { - pr_err("Remapping memory failed, error: %d\n", ret); + pr_err("Remapping memory, error: %d\n", ret); return ret; } + vma->vm_flags |= VM_DONTEXPAND; ge2d_log_dbg("mapped dma addr 0x%08lx at 0x%08lx, size %d\n", (unsigned long)buf->dma_addr, vma->vm_start, buf->size); @@ -136,10 +134,12 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, struct dma_buf_attachment *dbuf_attach) { struct aml_attachment *attach; - unsigned int i; - struct scatterlist *rd, *wr; - struct sg_table *sgt; struct aml_dma_buf *buf = dbuf->priv; + int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; + struct sg_table *sgt; + struct scatterlist *sg; + void *vaddr = buf->vaddr; + unsigned int i; int ret; attach = kzalloc(sizeof(*attach), GFP_KERNEL); @@ -150,18 +150,21 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, /* Copy the buf->base_sgt scatter list to the attachment, as we can't * map the same scatter list to multiple attachments at the same time. */ - ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL); + ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL); if (ret) { kfree(attach); return -ENOMEM; } + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + struct page *page = virt_to_page(vaddr); - rd = buf->sgt_base->sgl; - wr = sgt->sgl; - for (i = 0; i < sgt->orig_nents; ++i) { - sg_set_page(wr, sg_page(rd), rd->length, rd->offset); - rd = sg_next(rd); - wr = sg_next(wr); + if (!page) { + sg_free_table(sgt); + kfree(attach); + return -ENOMEM; + } + sg_set_page(sg, page, PAGE_SIZE, 0); + vaddr += PAGE_SIZE; } attach->dma_dir = DMA_NONE; @@ -214,7 +217,6 @@ static struct sg_table *aml_dmabuf_ops_map( attach->dma_dir); attach->dma_dir = DMA_NONE; } - /* mapping to the client with new direction */ sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir); @@ -274,25 +276,6 @@ static struct dma_buf_ops ge2d_dmabuf_ops = { .release = aml_dmabuf_ops_release, }; -static struct sg_table *get_base_sgt(struct aml_dma_buf *buf) -{ - int ret; - struct sg_table *sgt; - - sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!sgt) - return NULL; - - ret = dma_get_sgtable(buf->dev, sgt, buf->cookie, - buf->dma_addr, buf->size); - if (ret < 0) { - dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); - kfree(sgt); - return NULL; - } - return sgt; -} - static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) { struct aml_dma_buf *buf = buf_priv; @@ -303,11 +286,7 @@ static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) exp_info.size = buf->size; exp_info.flags = flags; exp_info.priv = buf; - - if (!buf->sgt_base) - buf->sgt_base = get_base_sgt(buf); - - if (WARN_ON(!buf->sgt_base)) + if (WARN_ON(!buf->vaddr)) return NULL; dbuf = dma_buf_export(&exp_info); @@ -393,20 +372,16 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, size = PAGE_ALIGN(ge2d_req_buf->len); if (size == 0) return (-EINVAL); - buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir, GFP_HIGHUSER | __GFP_ZERO); if (!buf) return (-ENOMEM); - dma_buf = (struct aml_dma_buf *)buf; mutex_lock(&(buffer->lock)); index = find_empty_dma_buffer(buffer); if ((index < 0) || (index >= AML_MAX_DMABUF)) { pr_err("no empty buffer found\n"); - dma_free_attrs(dev, dma_buf->size, dma_buf->cookie, - dma_buf->dma_addr, - dma_buf->attrs); mutex_unlock(&(buffer->lock)); + aml_dma_put(buf); return (-ENOMEM); } ((struct aml_dma_buf *)buf)->priv = buffer; @@ -628,7 +603,7 @@ void ge2d_dma_buffer_dma_flush(struct device *dev, int fd) pr_err("error input param"); return; } - if (buf->size > 0) + if ((buf->size > 0) && (buf->dev == dev)) dma_sync_single_for_device(buf->dev, buf->dma_addr, buf->size, DMA_TO_DEVICE); dma_buf_put(dmabuf); @@ -650,7 +625,7 @@ void ge2d_dma_buffer_cache_flush(struct device *dev, int fd) pr_err("error input param"); return; } - if (buf->size > 0) + if ((buf->size > 0) && (buf->dev == dev)) dma_sync_single_for_cpu(buf->dev, buf->dma_addr, buf->size, DMA_FROM_DEVICE); dma_buf_put(dmabuf); diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h index 396a6a8f299e..c3c03d30bb6a 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h @@ -37,7 +37,6 @@ struct aml_dma_buf { unsigned int index; dma_addr_t dma_addr; atomic_t refcount; - struct sg_table *sgt_base; /* DMABUF related */ struct dma_buf_attachment *db_attach; void *priv; diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index e2c420937032..d55c4c476ef6 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -1244,7 +1244,6 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context, dma_cfg->dir = dir; cfg->dma_cfg = dma_cfg; ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr); - ge2d_log_info("phys: addr=%lx\n", addr); if (ret != 0) return ret; From a73c669949998cefc7fc31dbd136c3752b757347 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 21 Mar 2019 18:44:56 +0800 Subject: [PATCH 0343/1060] gdc: change dma_buf to cacheable [2/2] PD#SWPL-5685 Problem: gdc output dmabuf have high variance Solution: change dma_buf to cacheable Verify: verified by w400 Change-Id: Ide8cea975c7dd39bb9185fbb9ba0694d859c74e6 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 115 +++++++++------------ drivers/amlogic/media/gdc/app/gdc_dmabuf.h | 1 - drivers/amlogic/media/gdc/app/gdc_module.c | 16 ++- 3 files changed, 59 insertions(+), 73 deletions(-) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index a4408abd2369..9cc952310ac0 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "system_log.h" #include "gdc_dmabuf.h" @@ -39,18 +40,19 @@ static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; + struct page *cma_pages = NULL; if (!atomic_dec_and_test(&buf->refcount)) { gdc_log(LOG_INFO, "gdc aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } - if (buf->sgt_base) { - sg_free_table(buf->sgt_base); - kfree(buf->sgt_base); + cma_pages = virt_to_page(buf->vaddr); + if (!dma_release_from_contiguous(buf->dev, cma_pages, + buf->size >> PAGE_SHIFT)) { + pr_err("failed to release cma buffer\n"); } - dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, - buf->attrs); + buf->vaddr = NULL; clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); kfree(buf); @@ -63,6 +65,8 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, gfp_t gfp_flags) { struct aml_dma_buf *buf; + struct page *cma_pages = NULL; + dma_addr_t paddr = 0; if (WARN_ON(!dev)) return (void *)(-EINVAL); @@ -73,22 +77,19 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, if (attrs) buf->attrs = attrs; - buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, - gfp_flags, buf->attrs); - if (!buf->cookie) { - dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); - kfree(buf); + cma_pages = dma_alloc_from_contiguous(dev, + size >> PAGE_SHIFT, 0); + if (cma_pages) { + paddr = page_to_phys(cma_pages); + } else { + pr_err("failed to alloc cma pages.\n"); return NULL; } - - if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) - buf->vaddr = buf->cookie; - - /* Prevent the device from being released while the buffer is used */ + buf->vaddr = phys_to_virt(paddr); buf->dev = get_device(dev); buf->size = size; buf->dma_dir = dma_dir; - + buf->dma_addr = paddr; atomic_inc(&buf->refcount); gdc_log(LOG_INFO, "aml_dma_buf=0x%p, refcont=%d\n", buf, atomic_read(&buf->refcount)); @@ -99,26 +100,24 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) { struct aml_dma_buf *buf = buf_priv; - int ret; + unsigned long pfn = 0; + unsigned long vsize = vma->vm_end - vma->vm_start; + int ret = -1; - if (!buf) { - pr_err("No buffer to map\n"); + if (!buf || !vma) { + pr_err("No memory to map\n"); return -EINVAL; } - /* - * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to - * map whole buffer - */ - vma->vm_pgoff = 0; - - ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, - buf->dma_addr, buf->size, buf->attrs); - + pfn = virt_to_phys(buf->vaddr) >> PAGE_SHIFT; + ret = remap_pfn_range(vma, vma->vm_start, pfn, + vsize, vma->vm_page_prot); if (ret) { - pr_err("Remapping memory failed, error: %d\n", ret); + pr_err("Remapping memory, error: %d\n", ret); return ret; } + vma->vm_flags |= VM_DONTEXPAND; + gdc_log(LOG_INFO, "mapped dma addr 0x%08lx at 0x%08lx, size %d\n", (unsigned long)buf->dma_addr, vma->vm_start, buf->size); @@ -137,10 +136,12 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, struct dma_buf_attachment *dbuf_attach) { struct aml_attachment *attach; - unsigned int i; - struct scatterlist *rd, *wr; - struct sg_table *sgt; struct aml_dma_buf *buf = dbuf->priv; + int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; + struct sg_table *sgt; + struct scatterlist *sg; + void *vaddr = buf->vaddr; + unsigned int i; int ret; attach = kzalloc(sizeof(*attach), GFP_KERNEL); @@ -151,18 +152,21 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, /* Copy the buf->base_sgt scatter list to the attachment, as we can't * map the same scatter list to multiple attachments at the same time. */ - ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL); + ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL); if (ret) { kfree(attach); return -ENOMEM; } + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + struct page *page = virt_to_page(vaddr); - rd = buf->sgt_base->sgl; - wr = sgt->sgl; - for (i = 0; i < sgt->orig_nents; ++i) { - sg_set_page(wr, sg_page(rd), rd->length, rd->offset); - rd = sg_next(rd); - wr = sg_next(wr); + if (!page) { + sg_free_table(sgt); + kfree(attach); + return -ENOMEM; + } + sg_set_page(sg, page, PAGE_SIZE, 0); + vaddr += PAGE_SIZE; } attach->dma_dir = DMA_NONE; @@ -275,25 +279,6 @@ static struct dma_buf_ops gdc_dmabuf_ops = { .release = aml_dmabuf_ops_release, }; -static struct sg_table *get_base_sgt(struct aml_dma_buf *buf) -{ - int ret; - struct sg_table *sgt; - - sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!sgt) - return NULL; - - ret = dma_get_sgtable(buf->dev, sgt, buf->cookie, - buf->dma_addr, buf->size); - if (ret < 0) { - dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); - kfree(sgt); - return NULL; - } - return sgt; -} - static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) { struct aml_dma_buf *buf = buf_priv; @@ -305,10 +290,7 @@ static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) exp_info.flags = flags; exp_info.priv = buf; - if (!buf->sgt_base) - buf->sgt_base = get_base_sgt(buf); - - if (WARN_ON(!buf->sgt_base)) + if (WARN_ON(!buf->vaddr)) return NULL; dbuf = dma_buf_export(&exp_info); @@ -399,15 +381,12 @@ int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, GFP_HIGHUSER | __GFP_ZERO); if (!buf) return (-ENOMEM); - dma_buf = (struct aml_dma_buf *)buf; mutex_lock(&(buffer->lock)); index = find_empty_dma_buffer(buffer); if ((index < 0) || (index >= AML_MAX_DMABUF)) { pr_err("no empty buffer found\n"); - dma_free_attrs(dev, dma_buf->size, dma_buf->cookie, - dma_buf->dma_addr, - dma_buf->attrs); mutex_unlock(&(buffer->lock)); + aml_dma_put(buf); return (-ENOMEM); } ((struct aml_dma_buf *)buf)->priv = buffer; @@ -625,7 +604,7 @@ void gdc_dma_buffer_dma_flush(struct device *dev, int fd) pr_err("error input param"); return; } - if (buf->size > 0) + if ((buf->size > 0) && (buf->dev == dev)) dma_sync_single_for_device(buf->dev, buf->dma_addr, buf->size, DMA_TO_DEVICE); dma_buf_put(dmabuf); @@ -647,7 +626,7 @@ void gdc_dma_buffer_cache_flush(struct device *dev, int fd) pr_err("error input param"); return; } - if (buf->size > 0) + if ((buf->size > 0) && (buf->dev == dev)) dma_sync_single_for_cpu(buf->dev, buf->dma_addr, buf->size, DMA_FROM_DEVICE); dma_buf_put(dmabuf); diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h index fb039b4658b5..a6e988d20a2a 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h @@ -35,7 +35,6 @@ struct aml_dma_buf { unsigned int index; dma_addr_t dma_addr; atomic_t refcount; - struct sg_table *sgt_base; /* DMABUF related */ struct dma_buf_attachment *db_attach; void *priv; diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index c13693e1dc46..14dcf1094f17 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -556,7 +556,9 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, } gdc_log(LOG_INFO, "1 plane get input addr=%x\n", gdc_cmd->y_base_addr); - gdc_buffer_dma_flush(gs_ex->input_buffer.shared_fd); + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); } else if (gs_ex->input_buffer.plane_number == 2) { cfg = &fh->dma_cfg.input_cfg_plane1; cfg->fd = gs_ex->input_buffer.y_base_fd; @@ -570,7 +572,9 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } gdc_cmd->y_base_addr = addr; - gdc_buffer_dma_flush(gs_ex->input_buffer.y_base_fd); + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); cfg = &fh->dma_cfg.input_cfg_plane2; cfg->fd = gs_ex->input_buffer.uv_base_fd; cfg->dev = &fh->gdev->pdev->dev; @@ -583,7 +587,9 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } gdc_cmd->uv_base_addr = addr; - gdc_buffer_dma_flush(gs_ex->input_buffer.uv_base_fd); + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->uv_base_addr, + gc->input_y_stride * gc->input_height / 2); gdc_log(LOG_INFO, "2 plane get input addr=%x\n", gdc_cmd->y_base_addr); gdc_log(LOG_INFO, "2 plane get input addr=%x\n", @@ -604,7 +610,9 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, } gdc_cmd->y_base_addr = addr; gdc_cmd->uv_base_addr = 0; - gdc_buffer_dma_flush(gs_ex->input_buffer.shared_fd); + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); break; default: gdc_log(LOG_ERR, "Error image format"); From fef42ce23bc2619b02d250c3eebb87dfa518812f Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 28 Mar 2019 15:12:16 +0800 Subject: [PATCH 0344/1060] ge2d: add ge2d dmabuf 32bit compatible [1/2] PD#SWPL-5685 Problem: ge2d dmabuf not work under 32bit Solution: add ge2d dmabuf 32bit compatible Verify: verified by w400 Change-Id: I03011620fc67cdaf251f5ca1c7b0b512a8fc9a76 Signed-off-by: Pengcheng Chen --- .../amlogic/media/common/ge2d/ge2d_dmabuf.c | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index c2362592295b..3ed7684d1f98 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -35,18 +35,66 @@ #include "ge2d_dmabuf.h" static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); + +static void *aml_mm_vmap(phys_addr_t phys, unsigned long size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot = PAGE_KERNEL; + void *vaddr; + int i; + + offset = offset_in_page(phys); + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /* pgprot = pgprot_writecombine(PAGE_KERNEL); */ + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + ge2d_log_dbg("[HIGH-MEM-MAP] pa(%lx) to va(%p), size: %d\n", + (unsigned long)phys, vaddr, npages << PAGE_SHIFT); + return vaddr; +} + +static void *aml_map_phyaddr_to_virt(dma_addr_t phys, unsigned long size) +{ + void *vaddr = NULL; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + vaddr = aml_mm_vmap(phys, size); + return vaddr; +} + /* dma free*/ static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; struct page *cma_pages = NULL; + void *vaddr = (void *)(PAGE_MASK & (ulong)buf->vaddr); if (!atomic_dec_and_test(&buf->refcount)) { ge2d_log_dbg("ge2d aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } - cma_pages = virt_to_page(buf->vaddr); + cma_pages = phys_to_page(buf->dma_addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(vaddr); + if (!dma_release_from_contiguous(buf->dev, cma_pages, buf->size >> PAGE_SHIFT)) { pr_err("failed to release cma buffer\n"); @@ -84,7 +132,7 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, pr_err("failed to alloc cma pages.\n"); return NULL; } - buf->vaddr = phys_to_virt(paddr); + buf->vaddr = aml_map_phyaddr_to_virt(paddr, size); buf->dev = get_device(dev); buf->size = size; buf->dma_dir = dma_dir; @@ -108,7 +156,7 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) return -EINVAL; } - pfn = virt_to_phys(buf->vaddr) >> PAGE_SHIFT; + pfn = buf->dma_addr >> PAGE_SHIFT; ret = remap_pfn_range(vma, vma->vm_start, pfn, vsize, vma->vm_page_prot); if (ret) { @@ -138,7 +186,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; struct sg_table *sgt; struct scatterlist *sg; - void *vaddr = buf->vaddr; + phys_addr_t phys = buf->dma_addr; unsigned int i; int ret; @@ -156,7 +204,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, return -ENOMEM; } for_each_sg(sgt->sgl, sg, sgt->nents, i) { - struct page *page = virt_to_page(vaddr); + struct page *page = phys_to_page(phys); if (!page) { sg_free_table(sgt); @@ -164,7 +212,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, return -ENOMEM; } sg_set_page(sg, page, PAGE_SIZE, 0); - vaddr += PAGE_SIZE; + phys += PAGE_SIZE; } attach->dma_dir = DMA_NONE; From 65b5a90582e0112737808d5ed517951de74322f2 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Thu, 28 Mar 2019 16:02:18 +0800 Subject: [PATCH 0345/1060] gdc: add gdc dmabuf 32bit compatible [2/2] PD#SWPL-5685 Problem: gdc dmabuf not work under 32bit Solution: add gdc dmabuf 32bit compatible Verify: verified by w400 Change-Id: If26f41ff6cd679dc0220771f5bb2b50eba899aa9 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 59 +++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 9cc952310ac0..6fbead4e611b 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -36,18 +36,65 @@ #include "gdc_dmabuf.h" static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); + +static void *aml_mm_vmap(phys_addr_t phys, unsigned long size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot = PAGE_KERNEL; + void *vaddr; + int i; + + offset = offset_in_page(phys); + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /* pgprot = pgprot_writecombine(PAGE_KERNEL); */ + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + gdc_log(LOG_INFO, "[HIGH-MEM-MAP] pa(%lx) to va(%p), size: %d\n", + (unsigned long)phys, vaddr, npages << PAGE_SHIFT); + return vaddr; +} + +static void *aml_map_phyaddr_to_virt(dma_addr_t phys, unsigned long size) +{ + void *vaddr = NULL; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + vaddr = aml_mm_vmap(phys, size); + return vaddr; +} + /* dma free*/ static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; struct page *cma_pages = NULL; + void *vaddr = (void *)(PAGE_MASK & (ulong)buf->vaddr); if (!atomic_dec_and_test(&buf->refcount)) { gdc_log(LOG_INFO, "gdc aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } - cma_pages = virt_to_page(buf->vaddr); + cma_pages = phys_to_page(buf->dma_addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(vaddr); if (!dma_release_from_contiguous(buf->dev, cma_pages, buf->size >> PAGE_SHIFT)) { pr_err("failed to release cma buffer\n"); @@ -85,7 +132,7 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, pr_err("failed to alloc cma pages.\n"); return NULL; } - buf->vaddr = phys_to_virt(paddr); + buf->vaddr = aml_map_phyaddr_to_virt(paddr, size); buf->dev = get_device(dev); buf->size = size; buf->dma_dir = dma_dir; @@ -109,7 +156,7 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) return -EINVAL; } - pfn = virt_to_phys(buf->vaddr) >> PAGE_SHIFT; + pfn = buf->dma_addr >> PAGE_SHIFT; ret = remap_pfn_range(vma, vma->vm_start, pfn, vsize, vma->vm_page_prot); if (ret) { @@ -140,7 +187,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; struct sg_table *sgt; struct scatterlist *sg; - void *vaddr = buf->vaddr; + phys_addr_t phys = buf->dma_addr; unsigned int i; int ret; @@ -158,7 +205,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, return -ENOMEM; } for_each_sg(sgt->sgl, sg, sgt->nents, i) { - struct page *page = virt_to_page(vaddr); + struct page *page = phys_to_page(phys); if (!page) { sg_free_table(sgt); @@ -166,7 +213,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, return -ENOMEM; } sg_set_page(sg, page, PAGE_SIZE, 0); - vaddr += PAGE_SIZE; + phys += PAGE_SIZE; } attach->dma_dir = DMA_NONE; From 1f0369c5c4f1957d336dfaca2f5c46154e63c089 Mon Sep 17 00:00:00 2001 From: Xiaoming Sui Date: Tue, 26 Mar 2019 22:06:04 +0800 Subject: [PATCH 0346/1060] tsync: reduce the log information [1/1] PD#SWPL-6152 Problem: in some special cases, there are many sync log information from serial port. Solution: remove this log and add pts realign. Verify: X301 Change-Id: I81d1753ef6d4e6c1e39d6c7f38eb3836e07be05d Signed-off-by: Xiaoming Sui --- drivers/amlogic/media/frame_sync/tsync.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index 27fb17d435c5..b18a048f7e4c 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -1211,13 +1211,14 @@ int tsync_set_apts(unsigned int pts) else t = timestamp_pcrscr_get(); if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { - pr_info("tsync_set_apts %x,diff %d\n", - pts, (int)timestamp_pcrscr_get() - pts); timestamp_apts_set(pts); - if ((int)(timestamp_apts_get() - t) > 30 * TIME_UNIT90K / 1000 - || (int)(t - timestamp_apts_get()) > - 80 * TIME_UNIT90K / 1000) + if ((int)(timestamp_apts_get() - timestamp_pcrscr_get()) + > 30 * TIME_UNIT90K / 1000 + || (int)(timestamp_pcrscr_get() - timestamp_apts_get()) + > 80 * TIME_UNIT90K / 1000) { timestamp_pcrscr_set(pts); + set_pts_realign(); + } return 0; } /* do not switch tsync mode until first video toggled. */ From e4efc5381f45e213e3941bd9627ee0a9e121ca55 Mon Sep 17 00:00:00 2001 From: "shaochan.liu" Date: Tue, 26 Mar 2019 11:27:02 +0800 Subject: [PATCH 0347/1060] lcd: supposed vlock_m and vlock_farc interface [1/1] PD#TV-3683 Problem: Repeatedly exit HDMI channel cause black screen Solution: 1, support vlock_m and vlock_frac interface 2, optimized clk change and de timing Verify: verify on t962x2-x301 Change-Id: Iddedade08300290853e59b026b3ca1b9939eed79 Signed-off-by: shaochan.liu --- .../amlogic/media/vout/lcd/lcd_clk_config.c | 62 +++++++++++++++++++ .../amlogic/media/vout/lcd/lcd_clk_config.h | 3 +- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 5 ++ drivers/amlogic/media/vout/lcd/lcd_common.c | 4 +- drivers/amlogic/media/vout/lcd/lcd_debug.c | 2 + .../media/vout/lcd/lcd_tablet/lcd_tablet.c | 2 + .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 2 + .../media/vout/vout_serve/vout_serve.c | 2 + .../linux/amlogic/media/vout/lcd/lcd_vout.h | 2 + 9 files changed, 81 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 22adef45c17e..aad62775596b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -2178,6 +2178,68 @@ lcd_pll_reset_end: LCDPR("%s\n", __func__); } +void lcd_vlock_m_update(unsigned int vlock_m) +{ + struct lcd_clk_ctrl_s *table; + int i = 0; + unsigned long flags = 0; + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + + if (clk_conf.data->pll_ctrl_table == NULL) + return; + + spin_lock_irqsave(&lcd_clk_lock, flags); + vlock_m &= 0xff; + if (lcd_debug_print_flag == 2) + LCDPR("%s,vlcok_m: 0x%x,", __func__, vlock_m); + + table = clk_conf.data->pll_ctrl_table; + while (i < LCD_CLK_CTRL_CNT_MAX) { + if (table[i].flag == LCD_CLK_CTRL_M) { + lcd_hiu_setb(table[i].reg, vlock_m, + table[i].bit, table[i].len); + break; + } + i++; + } + spin_unlock_irqrestore(&lcd_clk_lock, flags); +} + +void lcd_vlock_farc_update(unsigned int vlock_farc) +{ + struct lcd_clk_ctrl_s *table; + int i = 0; + unsigned long flags = 0; + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + + if (clk_conf.data->pll_ctrl_table == NULL) + return; + + spin_lock_irqsave(&lcd_clk_lock, flags); + vlock_farc &= 0x1ffff; + if (lcd_debug_print_flag == 2) + LCDPR("%s,vlock_farc: 0x%x\n", __func__, vlock_farc); + + table = clk_conf.data->pll_ctrl_table; + while (i < LCD_CLK_CTRL_CNT_MAX) { + if (table[i].flag == LCD_CLK_CTRL_FRAC) { + lcd_hiu_setb(table[i].reg, vlock_farc, + table[i].bit, table[i].len); + break; + } + i++; + } + spin_unlock_irqrestore(&lcd_clk_lock, flags); +} + /* for frame rate change */ void lcd_clk_update(struct lcd_config_s *pconf) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 8a52cdaaa407..a7a14df67726 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -27,7 +27,8 @@ */ #define LCD_CLK_CTRL_EN 0 #define LCD_CLK_CTRL_RST 1 -#define LCD_CLK_CTRL_FRAC 2 +#define LCD_CLK_CTRL_M 2 +#define LCD_CLK_CTRL_FRAC 3 #define LCD_CLK_CTRL_END 0xffff #define LCD_CLK_REG_END 0xffff diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index 928ba65cc68d..d35d543eef99 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -294,6 +294,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_txl[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_HDMI_PLL_CNTL, LCD_PLL_EN_TXL, 1}, {LCD_CLK_CTRL_RST, HHI_HDMI_PLL_CNTL, LCD_PLL_RST_TXL, 1}, + {LCD_CLK_CTRL_M, HHI_HDMI_PLL_CNTL, LCD_PLL_M_TXL, 9}, {LCD_CLK_CTRL_FRAC, HHI_HDMI_PLL_CNTL2, 0, 12}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -302,6 +303,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_axg[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_GP0_PLL_CNTL_AXG, LCD_PLL_EN_AXG, 1}, {LCD_CLK_CTRL_RST, HHI_GP0_PLL_CNTL_AXG, LCD_PLL_RST_AXG, 1}, + {LCD_CLK_CTRL_M, HHI_GP0_PLL_CNTL_AXG, LCD_PLL_M_AXG, 9}, {LCD_CLK_CTRL_FRAC, HHI_GP0_PLL_CNTL1_AXG, 0, 12}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -310,6 +312,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_g12a_path0[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_HDMI_PLL_CNTL, LCD_PLL_EN_HPLL_G12A, 1}, {LCD_CLK_CTRL_RST, HHI_HDMI_PLL_CNTL, LCD_PLL_RST_HPLL_G12A, 1}, + {LCD_CLK_CTRL_M, HHI_HDMI_PLL_CNTL, LCD_PLL_M_HPLL_G12A, 8}, {LCD_CLK_CTRL_FRAC, HHI_HDMI_PLL_CNTL2, 0, 19}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -318,6 +321,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_g12a_path1[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_EN_GP0_G12A, 1}, {LCD_CLK_CTRL_RST, HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_RST_GP0_G12A, 1}, + {LCD_CLK_CTRL_M, HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_M_GP0_G12A, 8}, {LCD_CLK_CTRL_FRAC, HHI_GP0_PLL_CNTL1_G12A, 0, 19}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -326,6 +330,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_tl1[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_TCON_PLL_CNTL0, LCD_PLL_EN_TL1, 1}, {LCD_CLK_CTRL_RST, HHI_TCON_PLL_CNTL0, LCD_PLL_RST_TL1, 1}, + {LCD_CLK_CTRL_M, HHI_TCON_PLL_CNTL0, LCD_PLL_M_TL1, 8}, {LCD_CLK_CTRL_FRAC, HHI_TCON_PLL_CNTL1, 0, 17}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index 68fd109c5bfe..b0fc1ec9bf06 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -806,8 +806,8 @@ void lcd_timing_init_config(struct lcd_config_s *pconf) vsync_bp = pconf->lcd_timing.vsync_bp; vsync_width = pconf->lcd_timing.vsync_width; - de_hstart = h_period - h_active - 1; - de_vstart = v_period - v_active; + de_hstart = hsync_bp + hsync_width; + de_vstart = vsync_bp + vsync_width; pconf->lcd_timing.video_on_pixel = de_hstart - h_delay; pconf->lcd_timing.video_on_line = de_vstart; diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index b0c4beb0b7f3..08b268dea6e0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -1397,6 +1397,8 @@ static void lcd_debug_clk_change(unsigned int pclk) struct lcd_config_s *pconf; unsigned int sync_duration; + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, + &lcd_drv->lcd_info->mode); pconf = lcd_drv->lcd_config; sync_duration = pclk / pconf->lcd_basic.h_period; sync_duration = sync_duration * 100 / pconf->lcd_basic.v_period; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index acb0e879fdfb..81ed0a6fb22e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -1242,6 +1242,8 @@ static void lcd_set_vinfo(unsigned int sync_duration) LCDPR("%s: sync_duration=%d\n", __func__, sync_duration); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, + &lcd_drv->lcd_info->mode); /* update vinfo */ lcd_drv->lcd_info->sync_duration_num = sync_duration; lcd_drv->lcd_info->sync_duration_den = 100; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index 5f79aea4bec7..352e5a56b5c9 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -1337,6 +1337,8 @@ static void lcd_set_vinfo(unsigned int sync_duration) LCDPR("%s: sync_duration=%d\n", __func__, sync_duration); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, + &lcd_drv->lcd_info->mode); /* update vinfo */ lcd_drv->lcd_info->sync_duration_num = sync_duration; lcd_drv->lcd_info->sync_duration_den = 100; diff --git a/drivers/amlogic/media/vout/vout_serve/vout_serve.c b/drivers/amlogic/media/vout/vout_serve/vout_serve.c index d41b8697bb5b..4ccc138ea398 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_serve.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_serve.c @@ -424,12 +424,14 @@ static ssize_t vout_dummy_store(struct class *class, mode = VMODE_DUMMY_LCD; ret = sscanf(buf, "%d %d %d %d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]); if (ret == 2) { + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode); nulldisp_vinfo[2].width = tmp[0]; nulldisp_vinfo[2].height = tmp[1]; nulldisp_vinfo[2].field_height = tmp[1]; VOUTPR("set dummy size: %d x %d\n", tmp[0], tmp[1]); vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode); } else if (ret == 4) { + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode); nulldisp_vinfo[2].width = tmp[0]; nulldisp_vinfo[2].height = tmp[1]; nulldisp_vinfo[2].field_height = tmp[1]; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index ce9a5fecbb8e..b8f9c666dc61 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -24,6 +24,8 @@ #include #include +extern void lcd_vlock_m_update(unsigned int vlock_m); +extern void lcd_vlock_frac_update(unsigned int vlock_farc); /* ********************************** * debug print define From 39b717e88d87e6993ed6562d237ccbe6647f360d Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Fri, 22 Feb 2019 13:29:34 +0800 Subject: [PATCH 0348/1060] amvecm: add ioctrl interface for hdr type. [1/1] PD#TV-1592 Problem: no interface to get hdr type Solution: add ioctrl interface for hdr type Verify: tl1 Change-Id: Ib7781fa8c924cbd7721b592acb18d3b834a04f06 Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 8 +++++++- include/linux/amlogic/media/amvecm/amvecm.h | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index e805cc30e404..371dd20a386d 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -180,7 +180,7 @@ unsigned int debug_game_mode_1; module_param(debug_game_mode_1, uint, 0664); MODULE_PARM_DESC(debug_game_mode_1, "\n debug_game_mode_1\n"); unsigned int pq_user_value; -unsigned int hdr_source_type = 0x1; +enum hdr_type_e hdr_source_type = HDRTYPE_SDR; #define SR0_OFFSET 0xc00 #define SR1_OFFSET 0xc80 @@ -1671,6 +1671,12 @@ static long amvecm_ioctl(struct file *file, pr_amvecm_dbg("lc load curve parm success\n"); } break; + case AMVECM_IOC_G_HDR_TYPE: + argp = (void __user *)arg; + if (copy_to_user(argp, + &hdr_source_type, sizeof(enum hdr_type_e))) + ret = -EFAULT; + break; default: ret = -EINVAL; break; diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index 1c39e101b362..380e65798a39 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -211,6 +211,11 @@ enum pc_mode_e { #define AMVECM_IOC_G_PIC_MODE _IOR(_VE_CM, 0x59, struct am_vdj_mode_s) #define AMVECM_IOC_S_PIC_MODE _IOW(_VE_CM, 0x60, struct am_vdj_mode_s) + +/*HDR TYPE command list*/ +#define AMVECM_IOC_G_HDR_TYPE _IOR(_VE_CM, 0x61, enum hdr_type_e) + + /*Local contrast command list*/ #define AMVECM_IOC_S_LC_CURVE _IOW(_VE_CM, 0x62, struct ve_lc_curve_parm_s) @@ -264,6 +269,14 @@ enum vpp_matrix_csc_e { VPP_MATRIX_DEFAULT_CSCTYPE = 0xffff, }; +enum hdr_type_e { + HDRTYPE_NONE = 0, + HDRTYPE_SDR = 0x1, + HDRTYPE_HDR10 = 0x2, + HDRTYPE_HLG = 0x4, + HDRTYPE_MAX, +}; + enum vpp_transfer_characteristic_e { VPP_ST_NULL = 0, VPP_ST709 = 0x1, @@ -409,9 +422,10 @@ static inline uint32_t READ_VPP_REG_BITS(uint32_t reg, extern signed int vd1_brightness, vd1_contrast; extern bool gamma_en; -extern unsigned int hdr_source_type; + extern unsigned int atv_source_flg; +extern enum hdr_type_e hdr_source_type; #define CSC_FLAG_TOGGLE_FRAME 1 #define CSC_FLAG_CHECK_OUTPUT 2 From 28b2e934f21801f55572c86470014ba3b07d625a Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Thu, 21 Mar 2019 22:45:16 +0800 Subject: [PATCH 0349/1060] amvecm: dnlp new c curve and interface [1/4] PD#SWPL-5338 Problem: dnlp new c curve and interface Solution: dnlp new c curve and interface Verify: x301 Change-Id: I7a221b6c5546873ebc3c3182d4856d57ffc3df48 Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 201 ++++++++++++++++++ .../amvecm/dnlp_algorithm/dnlp_alg.h | 26 ++- .../media/enhancement/amvecm/dnlp_cal.c | 179 ++++++++++++++-- .../media/enhancement/amvecm/dnlp_cal.h | 25 +++ include/linux/amlogic/media/amvecm/ve.h | 58 ++++- 5 files changed, 463 insertions(+), 26 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 371dd20a386d..d556f499abfd 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -1945,6 +1945,101 @@ static ssize_t amvecm_dnlp_debug_store(struct class *cla, else pr_info("%d\n", wext_gain_copy[val]); } + } else if (!strcmp(parm[1], "adp_thrd")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 33; i++) + d_convert_str(adp_thrd_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 32) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", adp_thrd_copy[val]); + } + } else if (!strcmp(parm[1], "reg_blk_boost_12")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 13; i++) + d_convert_str(reg_blk_boost_12_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 12) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_blk_boost_12_copy[val]); + } + } else if (!strcmp(parm[1], "reg_adp_ofset_20")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 20; i++) + d_convert_str(reg_adp_ofset_20_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 19) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_adp_ofset_20_copy[val]); + } + } else if (!strcmp(parm[1], "reg_mono_protect")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 6; i++) + d_convert_str(reg_mono_protect_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 5) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_mono_protect_copy[val]); + } + } else if (!strcmp(parm[1], "reg_trend_wht_expand_lut8")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 9; i++) + d_convert_str( + reg_trend_wht_expand_lut8_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 8) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_trend_wht_expand_lut8_copy[val]); + } } else if (!strcmp(parm[1], "ve_dnlp_tgt")) { /*read only curve*/ if (parm[2] == NULL) { @@ -2167,6 +2262,112 @@ static ssize_t amvecm_dnlp_debug_store(struct class *cla, else wext_gain_copy[num] = val; } + } else if (!strcmp(parm[1], "adp_thrd")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 33; i++) + adp_thrd_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 32) + pr_info("error cmd\n"); + else + adp_thrd_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_blk_boost_12")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 13; i++) + reg_blk_boost_12_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 12) + pr_info("error cmd\n"); + else + reg_blk_boost_12_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_adp_ofset_20")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 20; i++) + reg_adp_ofset_20_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 19) + pr_info("error cmd\n"); + else + reg_adp_ofset_20_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_mono_protect")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 6; i++) + reg_mono_protect_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 5) + pr_info("error cmd\n"); + else + reg_mono_protect_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_trend_wht_expand_lut8")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 9; i++) + reg_trend_wht_expand_lut8_copy[i] = + curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 8) + pr_info("error cmd\n"); + else + reg_trend_wht_expand_lut8_copy[num] = val; + } } } else if (!strcmp(parm[0], "ro")) { if (!strcmp(parm[1], "luma_avg4")) diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h b/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h index ca26aedf78e5..5f63f5cc98d0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h @@ -76,6 +76,26 @@ struct param_for_dnlp_s { unsigned int dnlp_scurv_hgh1_th; unsigned int dnlp_scurv_hgh2_th; unsigned int dnlp_mtdrate_adp_en; + unsigned int dnlp_clahe_method; + unsigned int dnlp_ble_en; + unsigned int dnlp_norm; + unsigned int dnlp_scn_chg_th; + unsigned int dnlp_step_th; + unsigned int dnlp_iir_step_mux; + unsigned int dnlp_single_bin_bw; + unsigned int dnlp_single_bin_method; + unsigned int dnlp_reg_max_slop_1st; + unsigned int dnlp_reg_max_slop_mid; + unsigned int dnlp_reg_max_slop_fin; + unsigned int dnlp_reg_min_slop_1st; + unsigned int dnlp_reg_min_slop_mid; + unsigned int dnlp_reg_min_slop_fin; + unsigned int dnlp_reg_trend_wht_expand_mode; + unsigned int dnlp_reg_trend_blk_expand_mode; + unsigned int dnlp_ve_hist_cur_gain; + unsigned int dnlp_ve_hist_cur_gain_precise; + unsigned int dnlp_reg_mono_binrang_st; + unsigned int dnlp_reg_mono_binrang_ed; }; struct dnlp_alg_input_param_s { @@ -112,8 +132,12 @@ struct dnlp_dbg_rw_param_s { int *dnlp_scurv_hgh2; int *gain_var_lut49; int *wext_gain; + int *adp_thrd; + int *reg_blk_boost_12; + int *reg_adp_ofset_20; + int *reg_mono_protect; + int *reg_trend_wht_expand_lut8; }; - struct dnlp_dbg_print_s { int *dnlp_printk; }; diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c index 13510c28a948..f2c6773024f2 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c @@ -69,6 +69,11 @@ int *dnlp_scurv_hgh1_copy; int *dnlp_scurv_hgh2_copy; int *gain_var_lut49_copy; int *wext_gain_copy; +int *adp_thrd_copy; +int *reg_blk_boost_12_copy; +int *reg_adp_ofset_20_copy; +int *reg_mono_protect_copy; +int *reg_trend_wht_expand_lut8_copy; int *ro_luma_avg4_copy; int *ro_var_d8_copy; @@ -154,6 +159,29 @@ struct dnlp_parse_cmd_s dnlp_parse_cmd[] = { {"scurv_hgh1_th", &(dnlp_alg_param.dnlp_scurv_hgh1_th)}, {"scurv_hgh2_th", &(dnlp_alg_param.dnlp_scurv_hgh2_th)}, {"mtdrate_adp_en", &(dnlp_alg_param.dnlp_mtdrate_adp_en)}, + {"clahe_method", &(dnlp_alg_param.dnlp_clahe_method)}, + {"ble_en", &(dnlp_alg_param.dnlp_ble_en)}, + {"norm", &(dnlp_alg_param.dnlp_norm)}, + {"scn_chg_th", &(dnlp_alg_param.dnlp_scn_chg_th)}, + {"step_th", &(dnlp_alg_param.dnlp_step_th)}, + {"iir_step_mux", &(dnlp_alg_param.dnlp_iir_step_mux)}, + {"single_bin_bw", &(dnlp_alg_param.dnlp_single_bin_bw)}, + {"single_bin_method", &(dnlp_alg_param.dnlp_single_bin_method)}, + {"reg_max_slop_1st", &(dnlp_alg_param.dnlp_reg_max_slop_1st)}, + {"reg_max_slop_mid", &(dnlp_alg_param.dnlp_reg_max_slop_mid)}, + {"reg_max_slop_fin", &(dnlp_alg_param.dnlp_reg_max_slop_fin)}, + {"reg_min_slop_1st", &(dnlp_alg_param.dnlp_reg_min_slop_1st)}, + {"reg_min_slop_mid", &(dnlp_alg_param.dnlp_reg_min_slop_mid)}, + {"reg_min_slop_fin", &(dnlp_alg_param.dnlp_reg_min_slop_fin)}, + {"reg_trend_wht_expand_mode", + &(dnlp_alg_param.dnlp_reg_trend_wht_expand_mode)}, + {"reg_trend_blk_expand_mode", + &(dnlp_alg_param.dnlp_reg_trend_blk_expand_mode)}, + {"ve_hist_cur_gain", &(dnlp_alg_param.dnlp_ve_hist_cur_gain)}, + {"ve_hist_cur_gain_precise", + &(dnlp_alg_param.dnlp_ve_hist_cur_gain_precise)}, + {"reg_mono_binrang_st", &(dnlp_alg_param.dnlp_reg_mono_binrang_st)}, + {"reg_mono_binrang_ed", &(dnlp_alg_param.dnlp_reg_mono_binrang_ed)}, {"", NULL} }; @@ -166,6 +194,12 @@ void dnlp_alg_param_copy(void) dnlp_scurv_hgh2_copy = dnlp_dbg_rw_param->dnlp_scurv_hgh2; gain_var_lut49_copy = dnlp_dbg_rw_param->gain_var_lut49; wext_gain_copy = dnlp_dbg_rw_param->wext_gain; + adp_thrd_copy = dnlp_dbg_rw_param->adp_thrd; + reg_blk_boost_12_copy = dnlp_dbg_rw_param->reg_blk_boost_12; + reg_adp_ofset_20_copy = dnlp_dbg_rw_param->reg_adp_ofset_20; + reg_mono_protect_copy = dnlp_dbg_rw_param->reg_mono_protect; + reg_trend_wht_expand_lut8_copy = + dnlp_dbg_rw_param->reg_trend_wht_expand_lut8; ro_luma_avg4_copy = dnlp_dbg_ro_param->ro_luma_avg4; ro_var_d8_copy = dnlp_dbg_ro_param->ro_var_d8; @@ -257,6 +291,26 @@ void dnlp_alg_param_init(void) dnlp_alg_param.dnlp_scurv_hgh1_th = 176; dnlp_alg_param.dnlp_scurv_hgh2_th = 240; dnlp_alg_param.dnlp_mtdrate_adp_en = 1; + dnlp_alg_param.dnlp_clahe_method = 1; + dnlp_alg_param.dnlp_ble_en = 1; + dnlp_alg_param.dnlp_norm = 10; + dnlp_alg_param.dnlp_scn_chg_th = 48; + dnlp_alg_param.dnlp_step_th = 1; + dnlp_alg_param.dnlp_iir_step_mux = 1; + dnlp_alg_param.dnlp_single_bin_bw = 2; + dnlp_alg_param.dnlp_single_bin_method = 1; + dnlp_alg_param.dnlp_reg_max_slop_1st = 614; + dnlp_alg_param.dnlp_reg_max_slop_mid = 400; + dnlp_alg_param.dnlp_reg_max_slop_fin = 614; + dnlp_alg_param.dnlp_reg_min_slop_1st = 77; + dnlp_alg_param.dnlp_reg_min_slop_mid = 144; + dnlp_alg_param.dnlp_reg_min_slop_fin = 77; + dnlp_alg_param.dnlp_reg_trend_wht_expand_mode = 2; + dnlp_alg_param.dnlp_reg_trend_blk_expand_mode = 2; + dnlp_alg_param.dnlp_ve_hist_cur_gain = 8; + dnlp_alg_param.dnlp_ve_hist_cur_gain_precise = 8; + dnlp_alg_param.dnlp_reg_mono_binrang_st = 7; + dnlp_alg_param.dnlp_reg_mono_binrang_ed = 26; if (dnlp_alg_function != NULL) { dnlp_alg_function->dnlp_para_set(&dnlp_alg_output, @@ -500,6 +554,34 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) /* general settings */ if (dnlp_insmod_ok == 0) return; + /*load static curve*/ + memcpy(dnlp_scurv_low_copy, p->ve_dnlp_scurv_low, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_mid1_copy, p->ve_dnlp_scurv_mid1, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_mid2_copy, p->ve_dnlp_scurv_mid2, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_hgh1_copy, p->ve_dnlp_scurv_hgh1, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_hgh2_copy, p->ve_dnlp_scurv_hgh2, + sizeof(int) * DNLP_SCURV_LEN); + /*load gain var*/ + memcpy(gain_var_lut49_copy, p->ve_gain_var_lut49, + sizeof(int) * GAIN_VAR_LUT_LEN); + /*load wext gain*/ + memcpy(wext_gain_copy, p->ve_wext_gain, + sizeof(int) * WEXT_GAIN_LEN); + /*load new c curve lut for vlsi-kite.li*/ + memcpy(adp_thrd_copy, p->ve_adp_thrd, + sizeof(int) * ADP_THRD_LEN); + memcpy(reg_blk_boost_12_copy, p->ve_reg_blk_boost_12, + sizeof(int) * REG_BLK_BOOST_LEN); + memcpy(reg_adp_ofset_20_copy, p->ve_reg_adp_ofset_20, + sizeof(int) * REG_ADP_OFSET_LEN); + memcpy(reg_mono_protect_copy, p->ve_reg_mono_protect, + sizeof(int) * REG_MONO_PROT_LEN); + memcpy(reg_trend_wht_expand_lut8_copy, p->ve_reg_trend_wht_expand_lut8, + sizeof(int) * TREND_WHT_EXP_LUT_LEN); if ((ve_en != p->param[ve_dnlp_enable]) || (dnlp_sel != p->param[ve_dnlp_sel]) || @@ -580,7 +662,45 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) (dnlp_alg_param.dnlp_scurv_hgh2_th != p->param[ve_dnlp_scurv_hgh2_th]) || (dnlp_alg_param.dnlp_mtdrate_adp_en != - p->param[ve_dnlp_mtdrate_adp_en])) { + p->param[ve_dnlp_mtdrate_adp_en]) || + (dnlp_alg_param.dnlp_clahe_method != + p->param[ve_dnlp_clahe_method]) || + (dnlp_alg_param.dnlp_ble_en != + p->param[ve_dnlp_ble_en]) || + (dnlp_alg_param.dnlp_norm != + p->param[ve_dnlp_norm]) || + (dnlp_alg_param.dnlp_scn_chg_th != + p->param[ve_dnlp_scn_chg_th]) || + (dnlp_alg_param.dnlp_iir_step_mux != + p->param[ve_dnlp_iir_step_mux]) || + (dnlp_alg_param.dnlp_single_bin_bw != + p->param[ve_dnlp_single_bin_bw]) || + (dnlp_alg_param.dnlp_single_bin_method != + p->param[ve_dnlp_single_bin_method]) || + (dnlp_alg_param.dnlp_reg_max_slop_1st != + p->param[ve_dnlp_reg_max_slop_1st]) || + (dnlp_alg_param.dnlp_reg_max_slop_mid != + p->param[ve_dnlp_reg_max_slop_mid]) || + (dnlp_alg_param.dnlp_reg_max_slop_fin != + p->param[ve_dnlp_reg_max_slop_fin]) || + (dnlp_alg_param.dnlp_reg_min_slop_1st != + p->param[ve_dnlp_reg_min_slop_1st]) || + (dnlp_alg_param.dnlp_reg_min_slop_mid != + p->param[ve_dnlp_reg_min_slop_mid]) || + (dnlp_alg_param.dnlp_reg_min_slop_fin != + p->param[ve_dnlp_reg_min_slop_fin]) || + (dnlp_alg_param.dnlp_reg_trend_wht_expand_mode != + p->param[ve_dnlp_reg_trend_wht_expand_mode]) || + (dnlp_alg_param.dnlp_reg_trend_blk_expand_mode != + p->param[ve_dnlp_reg_trend_blk_expand_mode]) || + (dnlp_alg_param.dnlp_ve_hist_cur_gain != + p->param[ve_dnlp_ve_hist_cur_gain]) || + (dnlp_alg_param.dnlp_ve_hist_cur_gain_precise != + p->param[ve_dnlp_ve_hist_cur_gain_precise]) || + (dnlp_alg_param.dnlp_reg_mono_binrang_st != + p->param[ve_dnlp_reg_mono_binrang_st]) || + (dnlp_alg_param.dnlp_reg_mono_binrang_ed != + p->param[ve_dnlp_reg_mono_binrang_ed])) { if (dnlp_insmod_ok) *menu_chg_en_copy = 1; } else @@ -651,27 +771,54 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) dnlp_alg_param.dnlp_mtdrate_adp_en = p->param[ve_dnlp_mtdrate_adp_en]; /* TODO: ve_dnlp_set_saturtn = p->dnlp_set_saturtn; */ + /*new c curve param add for vlsi-kiteli*/ + dnlp_alg_param.dnlp_mtdrate_adp_en = + p->param[ve_dnlp_mtdrate_adp_en]; + + dnlp_alg_param.dnlp_clahe_method = + p->param[ve_dnlp_clahe_method]; + dnlp_alg_param.dnlp_ble_en = + p->param[ve_dnlp_ble_en]; + dnlp_alg_param.dnlp_norm = + p->param[ve_dnlp_norm]; + dnlp_alg_param.dnlp_scn_chg_th = + p->param[ve_dnlp_scn_chg_th]; + dnlp_alg_param.dnlp_iir_step_mux = + p->param[ve_dnlp_iir_step_mux]; + dnlp_alg_param.dnlp_single_bin_bw = + p->param[ve_dnlp_single_bin_bw]; + dnlp_alg_param.dnlp_single_bin_method = + p->param[ve_dnlp_single_bin_method]; + dnlp_alg_param.dnlp_reg_max_slop_1st = + p->param[ve_dnlp_reg_max_slop_1st]; + dnlp_alg_param.dnlp_reg_max_slop_mid = + p->param[ve_dnlp_reg_max_slop_mid]; + dnlp_alg_param.dnlp_reg_max_slop_fin = + p->param[ve_dnlp_reg_max_slop_fin]; + dnlp_alg_param.dnlp_reg_min_slop_1st = + p->param[ve_dnlp_reg_min_slop_1st]; + dnlp_alg_param.dnlp_reg_min_slop_mid = + p->param[ve_dnlp_reg_min_slop_mid]; + dnlp_alg_param.dnlp_reg_min_slop_fin = + p->param[ve_dnlp_reg_min_slop_fin]; + dnlp_alg_param.dnlp_reg_trend_wht_expand_mode = + p->param[ve_dnlp_reg_trend_wht_expand_mode]; + dnlp_alg_param.dnlp_reg_trend_blk_expand_mode = + p->param[ve_dnlp_reg_trend_blk_expand_mode]; + dnlp_alg_param.dnlp_ve_hist_cur_gain = + p->param[ve_dnlp_ve_hist_cur_gain]; + dnlp_alg_param.dnlp_ve_hist_cur_gain_precise = + p->param[ve_dnlp_ve_hist_cur_gain_precise]; + dnlp_alg_param.dnlp_reg_mono_binrang_st = + p->param[ve_dnlp_reg_mono_binrang_st]; + dnlp_alg_param.dnlp_reg_mono_binrang_ed = + p->param[ve_dnlp_reg_mono_binrang_ed]; if (dnlp_insmod_ok == 0) return; dnlp_dbg_node_copy(); - /*load static curve*/ - for (i = 0; i < 65; i++) { - dnlp_scurv_low_copy[i] = p->ve_dnlp_scurv_low[i]; - dnlp_scurv_mid1_copy[i] = p->ve_dnlp_scurv_mid1[i]; - dnlp_scurv_mid2_copy[i] = p->ve_dnlp_scurv_mid2[i]; - dnlp_scurv_hgh1_copy[i] = p->ve_dnlp_scurv_hgh1[i]; - dnlp_scurv_hgh2_copy[i] = p->ve_dnlp_scurv_hgh2[i]; - } - /*load gain var*/ - for (i = 0; i < 49; i++) - gain_var_lut49_copy[i] = p->ve_gain_var_lut49[i]; - /*load wext gain*/ - for (i = 0; i < 48; i++) - wext_gain_copy[i] = p->ve_wext_gain[i]; - if (ve_en) { /* clear historic luma sum */ *ve_dnlp_luma_sum_copy = 0; diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h index ece185b1a3b5..0f592e871d24 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h @@ -76,6 +76,26 @@ struct dnlp_alg_param_s { unsigned int dnlp_scurv_hgh1_th; unsigned int dnlp_scurv_hgh2_th; unsigned int dnlp_mtdrate_adp_en; + unsigned int dnlp_clahe_method; + unsigned int dnlp_ble_en; + unsigned int dnlp_norm; + unsigned int dnlp_scn_chg_th; + unsigned int dnlp_step_th; + unsigned int dnlp_iir_step_mux; + unsigned int dnlp_single_bin_bw; + unsigned int dnlp_single_bin_method; + unsigned int dnlp_reg_max_slop_1st; + unsigned int dnlp_reg_max_slop_mid; + unsigned int dnlp_reg_max_slop_fin; + unsigned int dnlp_reg_min_slop_1st; + unsigned int dnlp_reg_min_slop_mid; + unsigned int dnlp_reg_min_slop_fin; + unsigned int dnlp_reg_trend_wht_expand_mode; + unsigned int dnlp_reg_trend_blk_expand_mode; + unsigned int dnlp_ve_hist_cur_gain; + unsigned int dnlp_ve_hist_cur_gain_precise; + unsigned int dnlp_reg_mono_binrang_st; + unsigned int dnlp_reg_mono_binrang_ed; }; struct dnlp_parse_cmd_s { @@ -108,6 +128,11 @@ extern int *dnlp_scurv_hgh1_copy; extern int *dnlp_scurv_hgh2_copy; extern int *gain_var_lut49_copy; extern int *wext_gain_copy; +extern int *adp_thrd_copy; +extern int *reg_blk_boost_12_copy; +extern int *reg_adp_ofset_20_copy; +extern int *reg_mono_protect_copy; +extern int *reg_trend_wht_expand_lut8_copy; extern int *ro_luma_avg4_copy; extern int *ro_var_d8_copy; diff --git a/include/linux/amlogic/media/amvecm/ve.h b/include/linux/amlogic/media/amvecm/ve.h index 11ed51009e5c..9ddb492a49e0 100644 --- a/include/linux/amlogic/media/amvecm/ve.h +++ b/include/linux/amlogic/media/amvecm/ve.h @@ -53,6 +53,16 @@ struct ve_bext_s { unsigned char slope2; }; #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) +#define DNLP_SCURV_LEN 65 +#define GAIN_VAR_LUT_LEN 49 +#define WEXT_GAIN_LEN 48 +#define ADP_THRD_LEN 33 +#define REG_BLK_BOOST_LEN 13 +#define REG_ADP_OFSET_LEN 20 +#define REG_MONO_PROT_LEN 6 +#define TREND_WHT_EXP_LUT_LEN 9 +#define DNLP_PARM_MAX_NUM 100 +#define DNLP_VPP_HIST_BIN_NUM 64 struct ve_dnlp_s { unsigned int en; unsigned int rt; /* 0 ~ 255, */ @@ -71,17 +81,22 @@ struct vpp_hist_param_s { unsigned int vpp_hist_pow; unsigned int vpp_luma_sum; unsigned int vpp_pixel_sum; - unsigned short vpp_histgram[64]; + unsigned short vpp_histgram[DNLP_VPP_HIST_BIN_NUM]; }; struct ve_dnlp_curve_param_s { - unsigned int ve_dnlp_scurv_low[65]; - unsigned int ve_dnlp_scurv_mid1[65]; - unsigned int ve_dnlp_scurv_mid2[65]; - unsigned int ve_dnlp_scurv_hgh1[65]; - unsigned int ve_dnlp_scurv_hgh2[65]; - unsigned int ve_gain_var_lut49[49]; - unsigned int ve_wext_gain[48]; - unsigned int param[100]; + unsigned int ve_dnlp_scurv_low[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_mid1[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_mid2[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_hgh1[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_hgh2[DNLP_SCURV_LEN]; + unsigned int ve_gain_var_lut49[GAIN_VAR_LUT_LEN]; + unsigned int ve_wext_gain[WEXT_GAIN_LEN]; + unsigned int ve_adp_thrd[ADP_THRD_LEN]; + unsigned int ve_reg_blk_boost_12[REG_BLK_BOOST_LEN]; + unsigned int ve_reg_adp_ofset_20[REG_ADP_OFSET_LEN]; + unsigned int ve_reg_mono_protect[REG_MONO_PROT_LEN]; + unsigned int ve_reg_trend_wht_expand_lut8[TREND_WHT_EXP_LUT_LEN]; + unsigned int param[DNLP_PARM_MAX_NUM]; }; enum dnlp_param_e { ve_dnlp_enable = 0, @@ -141,6 +156,26 @@ enum dnlp_param_e { ve_dnlp_scurv_hgh1_th, ve_dnlp_scurv_hgh2_th, ve_dnlp_mtdrate_adp_en, + ve_dnlp_clahe_method, + ve_dnlp_ble_en, + ve_dnlp_norm, + ve_dnlp_scn_chg_th, + ve_dnlp_step_th, + ve_dnlp_iir_step_mux, + ve_dnlp_single_bin_bw, + ve_dnlp_single_bin_method, + ve_dnlp_reg_max_slop_1st, + ve_dnlp_reg_max_slop_mid, + ve_dnlp_reg_max_slop_fin, + ve_dnlp_reg_min_slop_1st, + ve_dnlp_reg_min_slop_mid, + ve_dnlp_reg_min_slop_fin, + ve_dnlp_reg_trend_wht_expand_mode, + ve_dnlp_reg_trend_blk_expand_mode, + ve_dnlp_ve_hist_cur_gain, + ve_dnlp_ve_hist_cur_gain_precise, + ve_dnlp_reg_mono_binrang_st, + ve_dnlp_reg_mono_binrang_ed, ve_dnlp_param_max, }; enum dnlp_curve_e { @@ -151,6 +186,11 @@ enum dnlp_curve_e { ve_scurv_hgh2, ve_curv_var_lut49, ve_curv_wext_gain, + ve_adp_thrd = 1013, + ve_reg_blk_boost_12, + ve_reg_adp_ofset_20, + ve_reg_mono_protect, + ve_reg_trend_wht_expand_lut8, }; #else struct ve_dnlp_s { From 7f9a3c1d1e876f79ec0498629acace5f140812f2 Mon Sep 17 00:00:00 2001 From: "renjiang.han" Date: Thu, 21 Mar 2019 11:16:43 +0800 Subject: [PATCH 0350/1060] PPMGR: modify phys_to_virt to codec_mm_vmap. [5/5] PD#TV-2649 Problem: Kernel panic with phys_to_virt. Solution: Replace phys_to_virt with codec_mm_vmap. Verify: on u212 Change-Id: Ib3f94f66d37463490720cd1348b4ec94ad12aa15 Signed-off-by: renjiang.han --- .../media/video_processor/ppmgr/ppmgr_vpp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index 42cc0a606adc..79491652a753 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -3627,7 +3627,8 @@ void stop_ppmgr_task(void) static int tb_buffer_init(void) { int i; - int flags = CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_CMA_CLEAR; + //int flags = CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_CMA_CLEAR; + int flags = 0; if (tb_buffer_status) return tb_buffer_status; @@ -3676,7 +3677,8 @@ static int tb_buffer_init(void) detect_buf[i].paddr = tb_buffer_start + TB_DETECT_H * TB_DETECT_W * i; detect_buf[i].vaddr = - (ulong)phys_to_virt(detect_buf[i].paddr); + (ulong)codec_mm_vmap(detect_buf[i].paddr, + TB_DETECT_H * TB_DETECT_W); if (ppmgr_device.tb_detect & 0xc) { PPMGRVPP_INFO( "detect buff(%d) paddr: %lx, vaddr: %lx\n", @@ -3692,6 +3694,7 @@ static int tb_buffer_init(void) static int tb_buffer_uninit(void) { + int i; if (tb_src_canvas) { if (tb_src_canvas & 0xff) canvas_pool_map_free_canvas( @@ -3712,6 +3715,13 @@ static int tb_buffer_uninit(void) PPMGRVPP_INFO("tb cma free addr is %x, size is %x\n", (unsigned int)tb_buffer_start, (unsigned int)tb_buffer_size); + for (i = 0; i < tb_buffer_len; i++) { + if (detect_buf[i].vaddr) { + codec_mm_unmap_phyaddr( + (u8 *)detect_buf[i].vaddr); + detect_buf[i].vaddr = 0; + } + } codec_mm_free_for_dma( "tb_detect", tb_buffer_start); From d70eaa6607fa9bd80284455aad2961e75cb10906 Mon Sep 17 00:00:00 2001 From: "shuanglong.wang" Date: Wed, 20 Mar 2019 16:25:57 +0800 Subject: [PATCH 0351/1060] video: reuse initial phase [1/1] PD#SWPL-5664 Problem: for netflix 23.97fps non-tunnle playback 3:2 patten broken so many times Solution: reuse initial phase that Tim use in amazon Verify: verify by u212 Change-Id: I5d988e1c3a3dbf1bb728f55a921e8b8fb6990985 Signed-off-by: shuanglong.wang --- drivers/amlogic/media/video_sink/video.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 427ca6de7ebe..270560e4e9ef 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -4118,9 +4118,8 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) #endif if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc)) && ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) { - /*vsync_pts_align = vsync_pts_inc / 4 - */ - /* (timestamp_pcrscr_get() - vf->pts);*/ - vsync_pts_align = 0; + vsync_pts_align = vsync_pts_inc / 4 - + (timestamp_pcrscr_get() - vf->pts); vsync_pts_aligned = true; #ifdef PTS_TRACE_DEBUG pts_trace_his_rd = 0; @@ -6709,7 +6708,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) (cur_dispbuf) ? cur_dispbuf->duration : 0, vf->pts, timestamp_pcrscr_get(), - timestamp_pcrscr_get() - vf->pts, + timestamp_pcrscr_get() - vf->pts + + vsync_pts_align, pts_trace); amlog_mask_if(toggle_cnt > 0, LOG_MASK_FRAMESKIP, "skipped\n"); From c400f67c800dcc1203e4938dcd93474fd3928d61 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Sun, 31 Mar 2019 00:32:00 +0800 Subject: [PATCH 0352/1060] compile: fix smarthome compile error [1/1] PD#SWPL-6186 Problem: smarthome compile error Solution: fix smarthome compile error Verify: compile OK Change-Id: I6909374b8abbeac8ccb4bca760208d309d24f4bd Signed-off-by: Jianxin Pan --- include/linux/amlogic/power_ctrl.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/linux/amlogic/power_ctrl.h b/include/linux/amlogic/power_ctrl.h index 46cc3cd1b9a9..5b6f7213539e 100644 --- a/include/linux/amlogic/power_ctrl.h +++ b/include/linux/amlogic/power_ctrl.h @@ -19,7 +19,25 @@ #define _POWER_CTRL_H_ #include +#ifdef CONFIG_AMLOGIC_POWER int power_ctrl_sleep(bool power_on, unsigned int shift); int power_ctrl_iso(bool power_on, unsigned int shift); int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift); +#else +static inline int power_ctrl_sleep(bool power_on, unsigned int shift) +{ + return -EINVAL; +} + +static inline int power_ctrl_iso(bool power_on, unsigned int shift) +{ + return -EINVAL; +} + +static inline int power_ctrl_mempd0(bool power_on, unsigned int mask_val, + unsigned int shift) +{ + return -EINVAL; +} +#endif #endif /*_POWER_CTRL_H_*/ From 1c2a0b9846fafa696c26a25ff9a9f589c2637ceb Mon Sep 17 00:00:00 2001 From: Xingyu Chen Date: Fri, 29 Mar 2019 15:15:25 +0800 Subject: [PATCH 0353/1060] iio: adc: disable software calibration for txlx and later platform [1/1] PD#SWPL-6483 Problem: the txlx and later platform use the VDDA as vref by default, and we can use directly the adc sampling value, so it is unnecessary to recalculate calibration factor through ch7. Solution: add new variable to judge whether enabling the software calibration Verify: test pass on u200 Change-Id: I611b4d8b76c95d8fdbdf23a96801bf6d9e5eb1f7 Signed-off-by: Xingyu Chen --- drivers/amlogic/iio/adc/meson_saradc.c | 50 ++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index a32565d97f0f..df998ae13cae 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -213,9 +213,7 @@ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \ BIT(IIO_CHAN_INFO_PROCESSED), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_CALIBBIAS) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .scan_type = { \ .sign = 'u', \ .storagebits = 16, \ @@ -325,6 +323,7 @@ struct meson_sar_adc_reg_diff { * @obt_temp_chan6: whether to read data of temp sensor by channel 6 * @has_bl30_integration: * @vref_sel: txlx and later: VDDA; others(txl etc): calibration voltage + * @calib_enable: txlx and later: disable; others(txl etc): enable * @period_support: periodic sampling support * @has_chnl_regs: whether support for chnl[X] registers * @resolution: gxl and later: 12bit; others(gxtvbb etc): 10bit @@ -335,6 +334,7 @@ struct meson_sar_adc_data { bool obt_temp_chan6; bool has_bl30_integration; bool vref_sel; + bool calib_enable; bool period_support; bool has_chnl_regs; unsigned int resolution; @@ -454,7 +454,10 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, fifo_val &= GENMASK(priv->data->resolution - 1, 0); /* to fix the sample value by software */ - *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + if (priv->data->calib_enable) + *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + else + *val = fifo_val; return 0; } @@ -495,7 +498,10 @@ static int meson_sar_adc_read_raw_sample_from_chnl(struct iio_dev *indio_dev, fifo_val &= GENMASK(priv->data->resolution - 1, 0); /* to fix the sample value by software */ - *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + if (priv->data->calib_enable) + *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + else + *val = fifo_val; return 0; } @@ -761,10 +767,16 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_CALIBBIAS: + if (!priv->data->calib_enable) + return -EINVAL; + *val = priv->calibbias; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBSCALE: + if (!priv->data->calib_enable) + return -EINVAL; + *val = priv->calibscale / MILLION; *val2 = priv->calibscale % MILLION; return IIO_VAL_INT_PLUS_MICRO; @@ -1430,6 +1442,7 @@ struct meson_sar_adc_data meson_sar_adc_txl_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-txl-saradc", .regmap_config = &meson_sar_adc_regmap_config_gxbb, @@ -1445,6 +1458,7 @@ struct meson_sar_adc_data meson_sar_adc_gxl_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-gxl-saradc", .regmap_config = &meson_sar_adc_regmap_config_gxbb, @@ -1460,6 +1474,7 @@ struct meson_sar_adc_data meson_sar_adc_gxm_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-gxm-saradc", .regmap_config = &meson_sar_adc_regmap_config_gxbb, @@ -1475,6 +1490,7 @@ struct meson_sar_adc_data meson_sar_adc_m8b_data = { .obt_temp_chan6 = true, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_10BIT, .name = "meson-m8b-saradc", .regmap_config = &meson_sar_adc_regmap_config_meson8, @@ -1517,8 +1533,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; const struct of_device_id *match; + struct iio_chan_spec *chan; int ret; int irq; + int i; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); if (!indio_dev) { @@ -1590,8 +1608,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return ret; } - priv->calibscale = MILLION; - if (priv->data->period_support) { ret = of_property_read_u32(pdev->dev.of_node, "amlogic,delay-per-tick", &priv->delay_per_tick); @@ -1630,10 +1646,24 @@ static int meson_sar_adc_probe(struct platform_device *pdev) if (ret) goto err; - ret = meson_sar_adc_calib(indio_dev); - if (ret) - dev_warn(&pdev->dev, "calibration failed\n"); + if (priv->data->calib_enable) { + priv->calibscale = MILLION; + for (i = 0; i < indio_dev->num_channels; i++) { + chan = (struct iio_chan_spec *)indio_dev->channels + i; + if (chan->channel < 0) + continue; + + chan->info_mask_shared_by_all = + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE); + + } + ret = meson_sar_adc_calib(indio_dev); + if (ret) + dev_warn(&pdev->dev, "calibration failed\n"); + + } platform_set_drvdata(pdev, indio_dev); ret = iio_device_register(indio_dev); From 52d5e0fdd7920cd1332d73e294fc0c201d23bd0c Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Sat, 16 Feb 2019 02:10:38 -0500 Subject: [PATCH 0354/1060] amvecm: remove driver lc setting by timing [1/1] PD#SWPL-5248 Problem: lc setting load from db Solution: remove driver lc setting by timing Verify: verify on TL1 Change-Id: I7dac2429220d31f7930087ffb01176863cd74453 Signed-off-by: MingLiang Dong --- .../media/enhancement/amvecm/local_contrast.c | 139 ++++++++++++++---- .../media/enhancement/amvecm/local_contrast.h | 2 + 2 files changed, 111 insertions(+), 30 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index cb792d8d429f..39a36af6adda 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -80,30 +80,41 @@ struct ve_lc_curve_parm_s lc_curve_parm_load; struct lc_alg_param_s lc_alg_parm; /*lc saturation gain, low parameters*/ -static unsigned int lc_satur_gain[63] = { - 51, 104, 158, 213, 269, 325, 382, 440, 498, - 556, 615, 674, 734, 794, 854, 915, 976, 1037, - 1099, 1161, 1223, 1286, 1348, 1411, 1475, 1538, - 1602, 1666, 1730, 1795, 1859, 1924, 1989, 2054, - 2120, 2186, 2251, 2318, 2384, 2450, 2517, 2584, - 2651, 2718, 2785, 2853, 2921, 2988, 3057, 3125, - 3193, 3262, 3330, 3399, 3468, 3537, 3607, 3676, - 3746, 3815, 3885, 3955, 4026 +/*static unsigned int lc_satur_gain[63] = { + * 51, 104, 158, 213, 269, 325, 382, 440, 498, + * 556, 615, 674, 734, 794, 854, 915, 976, 1037, + * 1099, 1161, 1223, 1286, 1348, 1411, 1475, 1538, + * 1602, 1666, 1730, 1795, 1859, 1924, 1989, 2054 + * 2120, 2186, 2251, 2318, 2384, 2450, 2517, 2584, + * 2651, 2718, 2785, 2853, 2921, 2988, 3057, 3125, + * 3193, 3262, 3330, 3399, 3468, 3537, 3607, 3676, + * 3746, 3815, 3885, 3955, 4026 + *}; + */ + +/*lc saturation gain, off parameters*/ +static unsigned int lc_satur_off[63] = { + 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, + 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, + 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, + 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, + 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, + 2816, 2880, 2944, 3008, 3072, 3136, 3200, 3264, + 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, + 3840, 3904, 3968, 4032 }; /*lc saturation gain, low parameters*/ -/* - *static unsigned int lc_satur_off[63] = { - * 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, - * 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, - * 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, - * 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, - * 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, - * 2816, 2880, 2944, 3008, 3072, 3136, 3200, 3264, - * 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, - * 3840, 3904, 3968, 4032 - *}; - */ +/*static unsigned int lc_satur_low[63] = {*/ +/* 84, 167, 249, 330, 411, 490, 568, 646, 723, 798,*/ +/* 873, 947, 1020, 1092, 1163, 1234, 1303, 1372, 1440,*/ +/* 1506, 1572, 1638, 1702, 1766, 1828, 1890, 1951,*/ +/* 2011, 2071, 2130, 2187, 2245, 2301, 2356, 2411,*/ +/* 2465, 2518, 2571, 2623, 2674, 2724, 2774, 2822,*/ +/* 2871, 2919, 2967, 3016, 3065, 3115, 3165, 3217,*/ +/* 3271, 3326, 3384, 3443, 3506, 3571, 3639, 3710,*/ +/* 3785, 3863, 3945, 4032*/ +/*};*/ /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, @@ -164,7 +175,7 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, return; switch (mtx_csc) { - case LC_MTX_RGB_YUV709L: + case LC_MTX_RGB_YUV601L: if (mtx_sel & (INP_MTX | OUTP_MTX)) { WRITE_VPP_REG(matrix_coef00_01, 0x1070204); WRITE_VPP_REG(matrix_coef02_10, 0x640f68); @@ -184,7 +195,7 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_pre_offset2, 0x0); } break; - case LC_MTX_YUV709L_RGB: + case LC_MTX_YUV601L_RGB: if (mtx_sel & (INP_MTX | OUTP_MTX)) { WRITE_VPP_REG(matrix_coef00_01, 0x012a0000); WRITE_VPP_REG(matrix_coef02_10, 0x198012a); @@ -204,6 +215,46 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_pre_offset2, 0x00000600); } break; + case LC_MTX_RGB_YUV709L: + if (mtx_sel & (INP_MTX | OUTP_MTX)) { + WRITE_VPP_REG(matrix_coef00_01, 0xba0273); + WRITE_VPP_REG(matrix_coef02_10, 0x3f0f9a); + WRITE_VPP_REG(matrix_coef11_12, 0xea701c0); + WRITE_VPP_REG(matrix_coef20_21, 0x1c00e6a); + WRITE_VPP_REG(matrix_coef22, 0xfd7); + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + } else if (mtx_sel & STAT_MTX) { + WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); + WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99); + WRITE_VPP_REG(matrix_coef11_12, 0x1ea601c2); + WRITE_VPP_REG(matrix_coef20_21, 0x01c21e67); + WRITE_VPP_REG(matrix_coef22, 0x00001fd7); + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_offset2, 0x00000200); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x0); + WRITE_VPP_REG(matrix_pre_offset2, 0x0); + } + break; + case LC_MTX_YUV709L_RGB: + if (mtx_sel & (INP_MTX | OUTP_MTX)) { + WRITE_VPP_REG(matrix_coef00_01, 0x12b0000); + WRITE_VPP_REG(matrix_coef02_10, 0x1cc012b); + WRITE_VPP_REG(matrix_coef11_12, 0xfc90f77); + WRITE_VPP_REG(matrix_coef20_21, 0x12b021f); + WRITE_VPP_REG(matrix_coef22, 0x0); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + } else if (mtx_sel & STAT_MTX) { + WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); + WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); + WRITE_VPP_REG(matrix_coef11_12, 0x1F261DDD); + WRITE_VPP_REG(matrix_coef20_21, 0x04A80876); + WRITE_VPP_REG(matrix_coef22, 0x0); + WRITE_VPP_REG(matrix_offset0_1, 0x0); + WRITE_VPP_REG(matrix_offset2, 0x0); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x7c00600); + WRITE_VPP_REG(matrix_pre_offset2, 0x00000600); + } + break; case LC_MTX_NULL: if (mtx_sel & (INP_MTX | OUTP_MTX)) { WRITE_VPP_REG(matrix_coef00_01, 0x04000000); @@ -213,7 +264,15 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_coef22, 0x400); WRITE_VPP_REG(matrix_offset0_1, 0x0); } else if (mtx_sel & STAT_MTX) { - + WRITE_VPP_REG(matrix_coef00_01, 0x04000000); + WRITE_VPP_REG(matrix_coef02_10, 0x0); + WRITE_VPP_REG(matrix_coef11_12, 0x04000000); + WRITE_VPP_REG(matrix_coef20_21, 0x0); + WRITE_VPP_REG(matrix_coef22, 0x400); + WRITE_VPP_REG(matrix_offset0_1, 0x0); + WRITE_VPP_REG(matrix_offset2, 0x0); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x0); + WRITE_VPP_REG(matrix_pre_offset2, 0x0); } break; default: @@ -469,6 +528,14 @@ static void lc_config(int enable, vf_height = vf->height; vf_width = vf->width; + if (vf_height < 720) { + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + } else { + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + } + lc_top_config(enable, h_num, v_num, height, width); if (sps_h_en == 1) @@ -1182,18 +1249,30 @@ void lc_init(void) WRITE_VPP_REG(LC_CURVE_CONTRAST_LH, 0x000b000b); WRITE_VPP_REG(LC_CURVE_CONTRAST_SCL_LH, 0x00000b0b); WRITE_VPP_REG(LC_CURVE_MISC0, 0x00023028); - WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, 0x3e69443c); - WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, 0x00000b33); - WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1, 0x00440088); + WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, 0x8cc0c060); + WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, 0x00000b3a); + + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1, 0x0030005d); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_2_3, 0x00830091); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_4_5, 0x00a000c4); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_6_7, 0x00e00100); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_8_9, 0x01200140); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_10_11, 0x01600190); + + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1, 0x004400b4); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_2_3, 0x00fb0123); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_4_5, 0x015901a2); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_6_7, 0x01d90208); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_8_9, 0x02400280); WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_10_11, 0x02d70310); for (i = 0; i < 31 ; i++) { - tmp1 = *(lc_satur_gain + 2 * i); - tmp2 = *(lc_satur_gain + 2 * i + 1); + tmp1 = *(lc_satur_off + 2 * i); + tmp2 = *(lc_satur_off + 2 * i + 1); tmp = ((tmp1 & 0xfff)<<16) | (tmp2 & 0xfff); WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i, tmp); } - tmp = (*(lc_satur_gain + 62)) & 0xfff; + tmp = (*(lc_satur_off + 62)) & 0xfff; WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_62, tmp); /*end*/ diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index 9a27ace75af3..3dcf9b8f06a4 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -36,6 +36,8 @@ enum lc_mtx_csc_e { LC_MTX_NULL = 0, LC_MTX_YUV709L_RGB = 0x1, LC_MTX_RGB_YUV709L = 0x2, + LC_MTX_YUV601L_RGB = 0x3, + LC_MTX_RGB_YUV601L = 0x4, LC_MTX_MAX }; From c06a8f6fe7b0a2c6540a2a5a4267b302c307d162 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Tue, 2 Apr 2019 14:16:05 +0800 Subject: [PATCH 0355/1060] vpp: 3d: disable crop when 3d playback or hdmi in [1/1] PD#TV-3962 Problem: 3D mode does not support crop function Solution: Remove crop when 3D display. Verify: Verified on x301 Change-Id: Id35dd662886be24e3ec78d070e3a70f513f89b16 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/vpp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index ad8151fe8117..21e3d600ab33 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -909,7 +909,8 @@ static int vpp_set_filters_internal( reverse = input->reverse; #endif - if (vf->type & VIDTYPE_MVC) { + if ((vf->type & VIDTYPE_MVC) || + (input->proc_3d_type & MODE_3D_ENABLE)) { video_source_crop_left = 0; video_source_crop_right = 0; video_source_crop_top = 0; @@ -2514,7 +2515,8 @@ static int vpp_set_filters_no_scaler_internal( reverse = input->reverse; #endif - if (vf->type & VIDTYPE_MVC) { + if ((vf->type & VIDTYPE_MVC) || + (input->proc_3d_type & MODE_3D_ENABLE)) { video_source_crop_left = 0; video_source_crop_right = 0; video_source_crop_top = 0; From 2ebda4d79a7296c385f09ba1b89334914240ceed Mon Sep 17 00:00:00 2001 From: "changqing.gao" Date: Mon, 1 Apr 2019 13:57:55 +0800 Subject: [PATCH 0356/1060] fs: KASAN error in nls uniname cmp [1/1] PD#SWPL-6404 Problem: KASAN error:global-out-of-bounds in nls_uniname_cmp Solution: Append "\0\0" to the string of UNI_CUR_DIR_NAME and UNI_PAR_DIR_NAME Verify: x301 Change-Id: Ic94e837ed7874d337207c31eedfc966b46ab8ecd Signed-off-by: changqing.gao --- fs/exfat/exfat_nls.c | 2 +- fs/exfat/exfat_nls.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/exfat/exfat_nls.c b/fs/exfat/exfat_nls.c index be7fbf92cc76..2f2f49137530 100644 --- a/fs/exfat/exfat_nls.c +++ b/fs/exfat/exfat_nls.c @@ -106,7 +106,7 @@ s32 nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b) for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { if (nls_upper(sb, *a) != nls_upper(sb, *b)) return 1; - if (*a == 0x0) + if ((*a == 0x0) || (*b == 0x0)) return 0; } return 0; diff --git a/fs/exfat/exfat_nls.h b/fs/exfat/exfat_nls.h index cdc175585411..ef88abc14cc6 100644 --- a/fs/exfat/exfat_nls.h +++ b/fs/exfat/exfat_nls.h @@ -48,11 +48,11 @@ #define DOS_PAR_DIR_NAME ".. " #ifdef __LITTLE_ENDIAN -#define UNI_CUR_DIR_NAME ".\0" -#define UNI_PAR_DIR_NAME ".\0.\0" +#define UNI_CUR_DIR_NAME ".\0\0\0" +#define UNI_PAR_DIR_NAME ".\0.\0\0\0" #else -#define UNI_CUR_DIR_NAME "\0." -#define UNI_PAR_DIR_NAME "\0.\0." +#define UNI_CUR_DIR_NAME "\0.\0\0" +#define UNI_PAR_DIR_NAME "\0.\0.\0\0" #endif /*----------------------------------------------------------------------*/ From 28c4dba5de2c2c807743c47927a8f9c6f0d2b106 Mon Sep 17 00:00:00 2001 From: Peng Yixin Date: Tue, 19 Mar 2019 20:11:58 +0800 Subject: [PATCH 0357/1060] media_module: add double cache in codec_mm_scatter [1/1] PD#SWPL-6677 Problem: Decocder allocation and free mmu memory spend a long time. Solution: Add double cache to solve this problem. Verify: Verified P212 Change-Id: I393ad47b921631a49f551b32e31fd776ff4dfeea Signed-off-by: Peng Yixin --- .../media/common/codec_mm/codec_mm_scatter.c | 333 +++++++++++++++--- .../amlogic/media/codec_mm/codec_mm_scatter.h | 47 +++ 2 files changed, 327 insertions(+), 53 deletions(-) diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c index 31ee5d4c1151..1b8762c91fba 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c @@ -43,6 +43,8 @@ #include "codec_mm_priv.h" #include "codec_mm_scatter_priv.h" +#include + #define SCATTER_MEM "SCATTER_MEM" @@ -175,10 +177,21 @@ struct codec_mm_scatter_mgt { int alloc_1_10ms_cnt; int alloc_10_100ms_cnt; int alloc_100ms_up_cnt; +/*free time states*/ + int free_max_us; + u64 free_total_us; + int free_cnt; + int free_10us_less_cnt; + int free_10_50us_cnt; + int free_50_100us_cnt; + int free_100_1000us_cnt; + int free_1_10ms_cnt; + int free_10_100ms_cnt; + int free_100ms_up_cnt; struct delayed_work dealy_work; int scatter_task_run_num; - struct codec_mm_scatter *cache_sc; + struct codec_mm_scatter *cache_scs[2]; int cached_pages; spinlock_t list_lock; struct mutex monitor_lock; @@ -187,6 +200,8 @@ struct codec_mm_scatter_mgt { struct list_head scatter_list; /*scatter list */ struct codec_mm_scatter *scmap[MAX_SC_LIST];/*used for valid check. */ }; +#define is_cache_sc(smgt, mms) ((smgt->cache_scs[0] == mms) ||\ + (smgt->cache_scs[1] == mms)) static struct codec_mm_scatter_s g_scatter; static struct codec_mm_scatter_mgt *scatter_mgt; @@ -272,6 +287,12 @@ static inline void codec_mm_scatter_lock( { mutex_lock(&mms->mutex); } +static inline int codec_mm_scatter_trylock( + struct codec_mm_scatter *mms) +{ + return mutex_trylock(&mms->mutex); +} + static inline void codec_mm_list_lock( struct codec_mm_scatter_mgt *smgt) { @@ -365,6 +386,39 @@ static void codec_mm_update_alloc_time( } } +static void codec_mm_update_free_time( + struct codec_mm_scatter_mgt *smgt, u64 startus) +{ + int spend_time_us; + + spend_time_us = (int)(codec_mm_get_current_us() - startus); + if (spend_time_us > 0 && spend_time_us < 100000000) { + /* >0 && less than 100s*/ + /*else think time base changed.*/ + smgt->free_cnt++; + if (spend_time_us < 10) + smgt->free_10us_less_cnt++; + else if (spend_time_us < 50) + smgt->free_10_50us_cnt++; + else if (spend_time_us < 100) + smgt->free_50_100us_cnt++; + else if (spend_time_us < 1000) + smgt->free_100_1000us_cnt++; + else if (spend_time_us < 10000) + smgt->free_1_10ms_cnt++; + else if (spend_time_us < 100000) + smgt->free_10_100ms_cnt++; + else + smgt->free_100ms_up_cnt++; + + smgt->free_total_us += spend_time_us; + if (spend_time_us > smgt->free_max_us) { + /*..*/ + smgt->free_max_us = spend_time_us; + } + } +} + static void codec_mm_clear_alloc_infos_in( struct codec_mm_scatter_mgt *smgt) { @@ -378,6 +432,17 @@ static void codec_mm_clear_alloc_infos_in( smgt->alloc_100ms_up_cnt = 0; smgt->alloc_total_us = 0; smgt->alloc_max_us = 0; + + smgt->free_cnt = 0; + smgt->free_10us_less_cnt = 0; + smgt->free_10_50us_cnt = 0; + smgt->free_50_100us_cnt = 0; + smgt->free_100_1000us_cnt = 0; + smgt->free_1_10ms_cnt = 0; + smgt->free_10_100ms_cnt = 0; + smgt->free_100ms_up_cnt = 0; + smgt->free_total_us = 0; + smgt->free_max_us = 0; } void codec_mm_clear_alloc_infos(void) { @@ -1022,19 +1087,60 @@ static int codec_mm_page_alloc_from_slot( return alloced; } +/*flags & 1; alloc.*/ +static struct codec_mm_scatter *codec_mm_get_next_cache_scatter( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *cur_mms, + int flags) +{ + struct codec_mm_scatter *mms = NULL; + + codec_mm_list_lock(smgt); + if (cur_mms) { + if (smgt->cache_scs[0] == cur_mms) + mms = smgt->cache_scs[1]; + else + mms = smgt->cache_scs[0]; + } else if (smgt->cache_scs[0] && smgt->cache_scs[1]) { + int more_pages = flags & 1; + int id = -1; + + if (smgt->cache_scs[0]->page_cnt >= + smgt->cache_scs[1]->page_cnt) + id = more_pages ? 0 : 1; + else + id = more_pages ? 1 : 0; + mms = smgt->cache_scs[id]; + } else { + if (smgt->cache_scs[0]) + mms = smgt->cache_scs[0]; + else + mms = smgt->cache_scs[1]; + } + codec_mm_list_unlock(smgt); + return mms; +} + static int codec_mm_page_alloc_from_free_scatter( struct codec_mm_scatter_mgt *smgt, - phy_addr_type *pages, int num) + struct codec_mm_scatter *src_mms, + phy_addr_type *pages, int num, int wait) { struct codec_mm_scatter *mms; int need = num; int alloced = 0; - mms = smgt->cache_sc; + mms = src_mms; if (!mms) return 0; - codec_mm_scatter_lock(mms); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_1); + if (!wait) { + if (!codec_mm_scatter_trylock(mms)) + return 0;/*mms is locked try another.*/ + } else + codec_mm_scatter_lock(mms); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_2); alloced = min(mms->page_cnt, need); if (alloced > 0) { mms->page_cnt -= alloced; @@ -1053,13 +1159,35 @@ static int codec_mm_page_alloc_from_free_scatter( memset(&mms->pages_list[mms->page_tail + 1], 0, alloced * sizeof(phy_addr_type)); } + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_3); codec_mm_list_lock(smgt); - smgt->cached_pages = mms->page_cnt; + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_4); + smgt->cached_pages -= alloced; codec_mm_list_unlock(smgt); codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_5); return alloced; } +static int codec_mm_page_alloc_from_cache_scatter( + struct codec_mm_scatter_mgt *smgt, + phy_addr_type *pages, int num) +{ + struct codec_mm_scatter *src_mms; + int alloced; + + src_mms = codec_mm_get_next_cache_scatter(smgt, NULL, 1); + alloced = codec_mm_page_alloc_from_free_scatter(smgt, + src_mms, pages, num, 0); + if (alloced < num) { + src_mms = codec_mm_get_next_cache_scatter(smgt, src_mms, 1); + alloced += codec_mm_page_alloc_from_free_scatter(smgt, + src_mms, &pages[alloced], num - alloced, 1); + } + return alloced; +} + + static int codec_mm_page_alloc_all_locked( struct codec_mm_scatter_mgt *smgt, phy_addr_type *pages, int num, int iscache) @@ -1072,17 +1200,25 @@ static int codec_mm_page_alloc_all_locked( while (alloced < num) { new_alloc = 0; if (can_from_scatter) { - new_alloc = codec_mm_page_alloc_from_free_scatter( + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_free_scatter); + new_alloc = codec_mm_page_alloc_from_cache_scatter( smgt, pages + alloced, num - alloced); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_free_scatter_end); if (new_alloc <= 0) can_from_scatter = 0; } else if (can_from_slot) { + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_slot); new_alloc = codec_mm_page_alloc_from_slot( smgt, pages + alloced, num - alloced); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_slot_end); if (new_alloc <= 0) can_from_slot = 0; } else if (!smgt->no_alloc_from_sys && !smgt->tvp_mode) { @@ -1102,18 +1238,24 @@ static int codec_mm_page_alloc_all_locked( static int codec_mm_pages_free_to_scatter( struct codec_mm_scatter_mgt *smgt, - struct codec_mm_scatter *src_mms) + struct codec_mm_scatter *src_mms, + struct codec_mm_scatter *dst_mms, + int wait) { - struct codec_mm_scatter *dst_mms; int moved = 0; int left; if (src_mms->page_used >= src_mms->page_cnt) return -1; /*no need free. */ - dst_mms = smgt->cache_sc; if (!dst_mms || src_mms == dst_mms) return 0; - codec_mm_scatter_lock(dst_mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_DTS); + if (!wait) { + if (!codec_mm_scatter_trylock(dst_mms)) + return -2;/*mms is locked try another.*/ + } else + codec_mm_scatter_lock(dst_mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_DTS_LOCK); moved = min(src_mms->page_cnt - src_mms->page_used, dst_mms->page_max_cnt - dst_mms->page_cnt); left = src_mms->page_cnt - moved; @@ -1128,13 +1270,34 @@ static int codec_mm_pages_free_to_scatter( dst_mms->page_tail += moved; src_mms->page_cnt -= moved; src_mms->page_tail -= moved; + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_SMGT); codec_mm_list_lock(smgt); - smgt->cached_pages = dst_mms->page_cnt; + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_SMGT_LOCK); + smgt->cached_pages += moved; codec_mm_list_unlock(smgt); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_SMGT_LOCK_DONE); codec_mm_scatter_unlock(dst_mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_DTS_LOCK_DONE); return moved; } +static int codec_mm_page_free_to_cache_scatter( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *src_mms) +{ + struct codec_mm_scatter *dst_mms; + int alloced; + + dst_mms = codec_mm_get_next_cache_scatter(smgt, NULL, 0); + alloced = codec_mm_pages_free_to_scatter(smgt, src_mms, + dst_mms, 0); + if (alloced == -2) { + dst_mms = codec_mm_get_next_cache_scatter(smgt, dst_mms, 0); + alloced += codec_mm_pages_free_to_scatter(smgt, src_mms, + dst_mms, 1); + } + return alloced; +} /* @@ -1206,8 +1369,8 @@ static int codec_mm_scatter_free_pages_in_locked( } codec_mm_list_lock(smgt); smgt->alloced_page_num -= freeNum; - if (smgt->cache_sc == mms) - smgt->cached_pages = mms->page_cnt; + if (is_cache_sc(smgt, mms)) + smgt->cached_pages -= freeNum; codec_mm_list_unlock(smgt); return 0; } @@ -1235,7 +1398,9 @@ static int codec_mm_scatter_free_tail_pages_in( if (!mms) return -1; + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START); codec_mm_scatter_lock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK); if (free_mode == 1) start_free_id = mms->page_used; if (free_mode == 2) { @@ -1262,6 +1427,7 @@ static int codec_mm_scatter_free_tail_pages_in( free_mode); } codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK_DONE); return -1; } smgt = (struct codec_mm_scatter_mgt *)mms->manager; @@ -1271,17 +1437,25 @@ static int codec_mm_scatter_free_tail_pages_in( if (fast_mode == 1) { codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK_DONE); return 0; } if (fast_mode == 2 || fast_mode == 3) { - codec_mm_pages_free_to_scatter(smgt, mms); + u64 startus; + + startus = codec_mm_get_current_us(); + codec_mm_page_free_to_cache_scatter(smgt, mms); + codec_mm_update_free_time(smgt, startus); if (fast_mode == 2 || mms->page_used == mms->page_cnt) { codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", + MMU_FREE_SCATTER_START_LOCK_DONE); return 0; } } codec_mm_scatter_free_pages_in_locked(mms, start_free_id); codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK_DONE); return 0; } @@ -1469,7 +1643,7 @@ static int codec_mm_scatter_inc_user_in1( if (old_user >= 0) { ret = atomic_add_return(cnt, &mms->user_cnt); if (old_user == 1) - mms->tofree_jiffies = 0; + mms->tofree_jiffies = jiffies; } codec_mm_list_unlock(smgt); return ret <= 0 ? ret : 0; /*must add before user cnt >= 0 */ @@ -1513,13 +1687,8 @@ static int codec_mm_scatter_dec_user_in1( after_users = atomic_sub_return(cnt, &mms->user_cnt); if (after_users == 0) { /*is free time*/ - if (delay_free_ms > 0) - mms->tofree_jiffies = jiffies + - delay_free_ms * HZ/1000; - else { - mms->page_used = 0; - mms->tofree_jiffies = 0; - } + mms->tofree_jiffies = jiffies + + delay_free_ms * HZ/1000; } } codec_mm_list_unlock(smgt); @@ -1622,7 +1791,7 @@ struct codec_mm_scatter *codec_mm_scatter_alloc_new( if (page_num > 0) { ret = codec_mm_page_alloc_all_locked(smgt, mms->pages_list, page_num, - mms == smgt->cache_sc); + is_cache_sc(smgt, mms)); if (ret <= 0) goto error; mms->page_cnt = ret; @@ -1662,7 +1831,9 @@ struct codec_mm_scatter *codec_mm_scatter_alloc( smgt = codec_mm_get_scatter_mgt(istvp); startus = codec_mm_get_current_us(); alloced_mms = NULL; + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_START); codec_mm_list_lock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_START_LOCK); if (!list_empty(&smgt->scatter_list)) { /*try find a free scatter. */ pos = smgt->scatter_list.prev; /*free on prev. */ while (pos != &smgt->scatter_list) { @@ -1681,17 +1852,26 @@ struct codec_mm_scatter *codec_mm_scatter_alloc( pos = next; } } + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_START_LOCK_DONE); codec_mm_list_unlock(smgt); if (!alloced_mms) { /* *just alloc mms first, *alloc pages later. */ + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_NEW); alloced_mms = codec_mm_scatter_alloc_new(smgt, max_page, 0); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_NEW_END); } if (alloced_mms) { + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN); ret = codec_mm_scatter_alloc_want_pages_in(smgt, alloced_mms, page_num); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_END); if (ret < 0) { atomic_sub(1000, &alloced_mms->user_cnt); return NULL; @@ -1709,20 +1889,22 @@ static int codec_mm_scatter_alloc_want_pages_in( struct codec_mm_scatter *mms, int want_pages) { - int ret; + int ret = 0; if (want_pages > mms->page_max_cnt) return CODEC_MM_S_ERR(100); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_LOCK); codec_mm_scatter_lock(mms); codec_mm_list_lock(smgt); mms->page_used = want_pages; codec_mm_list_unlock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_LOCK_END); if (want_pages > mms->page_cnt) { ret = codec_mm_page_alloc_all_locked( smgt, &mms->pages_list[mms->page_tail + 1], want_pages - mms->page_cnt, - mms == smgt->cache_sc); + is_cache_sc(smgt, mms)); if (ret <= 0) { codec_mm_scatter_unlock(mms); ERR_LOG("can't alloc want pages %d\n", want_pages); @@ -1731,12 +1913,14 @@ static int codec_mm_scatter_alloc_want_pages_in( mms->page_cnt += ret; mms->page_tail += ret; } - if (mms == smgt->cache_sc) { - codec_mm_list_lock(smgt); - if (smgt->cache_sc)/*update cache pages*/ - smgt->cached_pages = smgt->cache_sc->page_cnt; - codec_mm_list_unlock(smgt); - } + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_LIST_LOCK_START); + codec_mm_list_lock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_LIST_LOCK); + if (ret > 0 && is_cache_sc(smgt, mms)) + smgt->cached_pages += ret; + + codec_mm_list_unlock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_LIST_LOCK_END); codec_mm_scatter_unlock(mms); if (smgt->cached_pages < smgt->keep_size_PAGE / 2) { /*try alloc more cache.*/ @@ -1878,6 +2062,18 @@ static int codec_mm_scatter_info_dump_in( smgt->alloc_10_100ms_cnt, smgt->alloc_100ms_up_cnt ); + BUFPRINT("\tfree time max us:%d\n", + smgt->free_max_us); + BUFPRINT("\tfree cnt:%d step:%d:%d:%d:%d:%d:%d:%d\n", + smgt->free_cnt, + smgt->free_10us_less_cnt, + smgt->free_10_50us_cnt, + smgt->free_50_100us_cnt, + smgt->free_100_1000us_cnt, + smgt->free_1_10ms_cnt, + smgt->free_10_100ms_cnt, + smgt->free_100ms_up_cnt + ); { int average_timeus; u64 divider = smgt->alloc_total_us; @@ -1887,6 +2083,13 @@ static int codec_mm_scatter_info_dump_in( 0 : (int)divider); BUFPRINT("\talloc time average us:%d\n", average_timeus); + divider = smgt->free_total_us; + + do_div(divider, smgt->free_cnt); + average_timeus = (smgt->free_cnt == 0 ? + 0 : (int)divider); + BUFPRINT("\tfree time average us:%d\n", + average_timeus); } #undef BUFPRINT @@ -2173,8 +2376,10 @@ static int codec_mm_dump_all_scatters_in(struct codec_mm_scatter_mgt *smgt) } } while (0); INFO_LOG("start dump free scatters!\n"); - if (smgt->cache_sc) - codec_mm_dump_scatter(smgt->cache_sc, 0, 0); + if (smgt->cache_scs[0]) + codec_mm_dump_scatter(smgt->cache_scs[0], 0, 0); + if (smgt->cache_scs[1]) + codec_mm_dump_scatter(smgt->cache_scs[1], 0, 0); codec_mm_list_unlock(smgt); INFO_LOG("finished dump all scatters!\n"); return 0; @@ -2238,7 +2443,7 @@ int codec_mm_scatter_mgt_delay_free_swith( } } codec_mm_list_unlock(smgt); - if (on && wait_size_M > 0 && !is_tvp) { + if (on && wait_size_M > 0 /*&& !is_tvp*/) { smgt->force_cache_on = 1; smgt->force_cache_page_cnt = wait_size_M >> PAGE_SHIFT; smgt->delay_free_timeout_jiffies64 = @@ -2246,9 +2451,8 @@ int codec_mm_scatter_mgt_delay_free_swith( codec_mm_schedule_delay_work(smgt, 0, 1);/*start cache*/ #if 0 while (smgt->total_page_num < smgt->force_cache_page_cnt) { - if (smgt->cache_sc && - (smgt->cached_pages >= - smgt->cache_sc->page_max_cnt - 100)) { + if (smgt->cache_scs[0] && + (smgt->cached_pages >= 65000)) { /*cache sc fulled.*/ break; } @@ -2304,7 +2508,7 @@ static void codec_mm_scatter_cache_manage( (smgt->force_cache_on &&/*on star cache*/ (smgt->total_page_num < smgt->force_cache_page_cnt)) ) {/*first 500ms ,alloc double.*/ - mms = smgt->cache_sc; + mms = codec_mm_get_next_cache_scatter(smgt, NULL, 0); if (mms) { int need; int once_alloc = 1000;/*once 4M*/ @@ -2327,11 +2531,15 @@ static void codec_mm_scatter_cache_manage( if (need > mms->page_max_cnt) need = mms->page_max_cnt - 4; if (need > mms->page_cnt) { + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2); alloced = !codec_mm_scatter_alloc_want_pages_in( smgt, mms, need); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2_END); } else { alloced = 0; } @@ -2352,7 +2560,7 @@ static void codec_mm_scatter_cache_manage( time_after64(get_jiffies_64(), smgt->delay_free_timeout_jiffies64)) { /*wait time out can free.*/ - mms = smgt->cache_sc; + mms = codec_mm_get_next_cache_scatter(smgt, NULL, 0); if (mms) {/*only free some 1M cache*/ codec_mm_scatter_less_pages(mms, 256); @@ -2368,11 +2576,11 @@ static void codec_mm_scatter_cache_manage( } if (smgt->keep_size_PAGE > 0 && smgt->delay_free_on) { if (((smgt->force_cache_on || - (total_free_page < smgt->keep_size_PAGE)) && - !smgt->tvp_mode) && + (total_free_page < smgt->keep_size_PAGE)) /*&&*/ + /*!smgt->tvp_mode*/) && alloced) {/*if failed may deadlock...*/ /*ignore keep on tvp mode.*/ - if (smgt->force_cache_on) + if (smgt->force_cache_on && !smgt->tvp_mode) codec_mm_schedule_delay_work(smgt, 0, 1); else codec_mm_schedule_delay_work(smgt, 10, 0); @@ -2392,26 +2600,43 @@ static int codec_mm_scatter_scatter_arrange( struct list_head *pos, *tmp; int n = 0; - if (smgt->delay_free_on > 0 && !smgt->cache_sc) { - /*no free scatter.*/ + if (smgt->delay_free_on > 0 && !smgt->cache_scs[0]) { + /*cache1*/ mms = codec_mm_scatter_alloc_new(smgt, 16384, 0); if (mms) { codec_mm_list_lock(smgt); list_del_init(&mms->list); - smgt->cache_sc = mms; + smgt->cache_scs[0] = mms; + codec_mm_list_unlock(smgt); + } + /*cache2*/ + mms = codec_mm_scatter_alloc_new(smgt, 16384, 0); + if (mms) { + codec_mm_list_lock(smgt); + list_del_init(&mms->list); + smgt->cache_scs[1] = mms; codec_mm_list_unlock(smgt); } } - if (smgt->delay_free_on <= 0 && smgt->cache_sc && + if (smgt->delay_free_on <= 0 && smgt->cache_scs[0] && time_after64(get_jiffies_64(), smgt->delay_free_timeout_jiffies64)) { + struct codec_mm_scatter *mms0, *mms1; codec_mm_list_lock(smgt); - mms = smgt->cache_sc; - smgt->cache_sc = NULL; + mms0 = smgt->cache_scs[0]; + mms1 = smgt->cache_scs[1]; + smgt->cache_scs[0] = NULL; + smgt->cache_scs[1] = NULL; smgt->cached_pages = 0; codec_mm_list_unlock(smgt); - codec_mm_scatter_dec_owner_user(mms, 0); - codec_mm_scatter_free_on_nouser(smgt, mms); + if (mms0) { + codec_mm_scatter_dec_owner_user(mms0, 0); + codec_mm_scatter_free_on_nouser(smgt, mms0); + } + if (mms1) { + codec_mm_scatter_dec_owner_user(mms1, 0); + codec_mm_scatter_free_on_nouser(smgt, mms1); + } } codec_mm_list_lock(smgt); @@ -2462,6 +2687,7 @@ static int codec_mm_scatter_scatter_clear( break; } } + if ((to_free_mms != NULL) && (((to_free_mms_cnt > 1 || !smgt->delay_free_on) && time_after(jiffies, to_free_mms->tofree_jiffies)) || @@ -2507,8 +2733,9 @@ static int codec_mm_scatter_free_all_ignorecache_in( /*disabled free on first. */ smgt->delay_free_on = 0; codec_mm_list_lock(smgt); - mms = smgt->cache_sc; - smgt->cache_sc = NULL; + mms = smgt->cache_scs[0]; + smgt->cache_scs[0] = smgt->cache_scs[1]; + smgt->cache_scs[1] = NULL; smgt->cached_pages = 0; codec_mm_list_unlock(smgt); if (mms) { @@ -2519,7 +2746,7 @@ static int codec_mm_scatter_free_all_ignorecache_in( } /*alloced again on timer?*/ /* check again. */ - } while (smgt->cache_sc != NULL); + } while (smgt->cache_scs[0] != NULL); do { need_retry = codec_mm_scatter_scatter_clear(smgt, 1); } while ((smgt->scatters_cnt > 0) && (retry_num++ < 1000)); diff --git a/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h b/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h index 5a84e3c3a0c8..fa6d73a2f980 100644 --- a/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h +++ b/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h @@ -47,6 +47,53 @@ struct codec_mm_scatter { struct list_head list; /*hold list. */ }; +enum e_mmu_free_status { + MMU_FREE_START, + MMU_FREE_START_LOCK, + MMU_FREE_SCATTER_START, + MMU_FREE_SCATTER_START_LOCK, + MMU_FREE_SCATTER_START_DTS, + MMU_FREE_SCATTER_START_DTS_LOCK, + MMU_FREE_SCATTER_START_SMGT, + MMU_FREE_SCATTER_START_SMGT_LOCK, + MMU_FREE_SCATTER_START_SMGT_LOCK_DONE, + MMU_FREE_SCATTER_START_DTS_LOCK_DONE, + MMU_FREE_SCATTER_START_LOCK_DONE, + MMU_FREE_START_LOCK_DONE, +}; + +enum e_mmu_alloc_status { + MMU_ALLOC_START, + MMU_ALLOC_START_LOCK, + MMU_ALLOC_SCATTER_START, + MMU_ALLOC_SCATTER_START_LOCK, + MMU_ALLOC_SCATTER_START_LOCK_DONE, + MMU_ALLOC_SCATTER_ALLOC_NEW, + MMU_ALLOC_SCATTER_ALLOC_NEW_END, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN, + MMU_ALLOC_SCATTER_LOCK, + MMU_ALLOC_SCATTER_LOCK_END, + MMU_ALLOC_from_cache_scatter, + MMU_ALLOC_from_cache_scatter_1, + MMU_ALLOC_from_cache_scatter_2, + MMU_ALLOC_from_cache_scatter_3, + MMU_ALLOC_from_cache_scatter_4, + MMU_ALLOC_from_cache_scatter_5, + MMU_ALLOC_from_cache_scatter_end, + MMU_ALLOC_from_free_scatter, + MMU_ALLOC_from_free_scatter_end, + MMU_ALLOC_from_slot, + MMU_ALLOC_from_slot_end, + MMU_ALLOC_LIST_LOCK_START, + MMU_ALLOC_LIST_LOCK, + MMU_ALLOC_LIST_LOCK_END, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_END, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2_END, + MMU_ALLOC_START_LOCK_DONE, +}; + + int codec_mm_scatter_free_all_pages(struct codec_mm_scatter *mms); int codec_mm_scatter_free_tail_pages(struct codec_mm_scatter *mms, From 92e69c53692d88739aafddef778c93b87147ec22 Mon Sep 17 00:00:00 2001 From: "renjiang.han" Date: Mon, 1 Apr 2019 17:09:58 +0800 Subject: [PATCH 0358/1060] ppmgr: The cut table caused a crash. [1/1] PD#SWPL-6557 Problem: The cut table caused a crash. Solution: modify dma flag Verify: on X301 Change-Id: Ic0ced1f4934d1125c56a79d1e102de9d2e02a528 Signed-off-by: renjiang.han --- .../media/video_processor/ppmgr/ppmgr_vpp.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index 79491652a753..225b887f82d4 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -177,9 +177,11 @@ static u32 tb_buffer_len = TB_DETECT_BUFFER_MAX_SIZE; static atomic_t tb_reset_flag; static u32 tb_init_mute; static atomic_t tb_skip_flag; +static atomic_t tb_run_flag; static bool tb_quit_flag; static struct TB_DetectFuncPtr *gfunc; static int tb_buffer_init(void); +static int tb_buffer_uninit(void); #endif const struct vframe_receiver_op_s *vf_ppmgr_reg_provider(void); @@ -3076,7 +3078,9 @@ static int ppmgr_task(void *data) /* wait tb task done */ while ((tb_buff_wptr >= 5) && (tb_buff_rptr - <= tb_buff_wptr - 5)) + <= tb_buff_wptr - 5) + && (atomic_read(&tb_run_flag) + == 1)) usleep_range( 4000, 5000); atomic_set(&detect_status, @@ -3166,7 +3170,9 @@ static int ppmgr_task(void *data) "tb detect skip case1\n"); goto SKIP_DETECT; } - if (tb_buff_wptr < tb_buffer_len) { + if ((tb_buff_wptr < tb_buffer_len) + && (atomic_read(&tb_run_flag) + == 1)) { ret = process_vf_tb_detect( vf, context, &ge2d_config); } else { @@ -3263,6 +3269,9 @@ SKIP_DETECT: } destroy_ge2d_work_queue(context); +#ifdef PPMGR_TB_DETECT + tb_buffer_uninit(); +#endif ppmgr_buffer_uninit(); while (!kthread_should_stop()) { /* may not call stop, wait.. @@ -3742,6 +3751,7 @@ static void tb_detect_init(void) atomic_set(&tb_detect_flag, TB_DETECT_NC); atomic_set(&tb_reset_flag, 0); atomic_set(&tb_skip_flag, 0); + atomic_set(&tb_run_flag, 1); tb_detect_last_flag = TB_DETECT_NC; tb_buff_wptr = 0; tb_buff_rptr = 0; @@ -3840,9 +3850,9 @@ static int tb_task(void *data) atomic_set(&detect_status, tb_done); } } + atomic_set(&tb_run_flag, 0); while (!kthread_should_stop()) usleep_range(9000, 10000); - tb_buffer_uninit(); return 0; } From 7f031826b2d995c37f37c30e4f675c6aa58cc180 Mon Sep 17 00:00:00 2001 From: Xingyu Chen Date: Fri, 29 Mar 2019 16:09:58 +0800 Subject: [PATCH 0359/1060] iio: adc: try to get flag again after the first failure [2/2] PD#SH-451 Problem: to get flag maybe occasionally fail Solution: try to get flag again after the first failure Verify: test pass on s400 Change-Id: Ibf430c9c331c7740864e797047962ad45e6698e3 Signed-off-by: Xingyu Chen --- drivers/amlogic/iio/adc/meson_saradc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index df998ae13cae..ca764dd3cc4e 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -619,6 +619,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); if (priv->data->has_bl30_integration) { +again: /* wait until BL30 releases it's lock (so we can use * the SAR ADC) */ @@ -636,10 +637,10 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) MESON_SAR_ADC_DELAY_KERNEL_BUSY); isb(); dsb(sy); - udelay(1); + udelay(5); regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); if (val & MESON_SAR_ADC_DELAY_BL30_BUSY) - return -ETIMEDOUT; + goto again; } return 0; @@ -649,10 +650,14 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - if (priv->data->has_bl30_integration) + if (priv->data->has_bl30_integration) { /* allow BL30 to use the SAR ADC again */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); + isb(); + dsb(sy); + udelay(5); + } mutex_unlock(&indio_dev->mlock); } From 834ad699ad6448cfb2549e0442201c519e7d4779 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Wed, 3 Apr 2019 18:14:45 +0800 Subject: [PATCH 0360/1060] paddr16: add paddr16 to get register values for 16-bits aligned address. [1/1] PD#SWPL-6718 Problem: paddr just can get register and memory values for 32-bits aligned address. Solution: add paddr16 to get register or memory values for 16-bits aligned address. Verify: g12b w400_a Change-Id: Ic7f32dcc6c2a24d0ac1e8c3ed60acc27e81887e0 Signed-off-by: Jianxiong Pan --- drivers/amlogic/reg_access/reg_access.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/reg_access/reg_access.c b/drivers/amlogic/reg_access/reg_access.c index 3ae2bc1b1fa2..32418f3d0ad7 100644 --- a/drivers/amlogic/reg_access/reg_access.c +++ b/drivers/amlogic/reg_access/reg_access.c @@ -53,7 +53,25 @@ int aml_reg_access(struct aml_ddev *indio_dev, iounmap(vaddr); return 0; } +int aml_reg_access_16(struct aml_ddev *indio_dev, + unsigned int reg, unsigned int writeval, + unsigned int *readval) +{ + void __iomem *vaddr; + + reg = round_down(reg, 0x2); + + vaddr = ioremap(reg, 0x4); + + if (readval) + *readval = readw(vaddr); + else + writew(writeval, vaddr); + iounmap(vaddr); + return 0; +} static struct aml_ddev aml_dev; +static struct aml_ddev aml_dev_16; static ssize_t paddr_read_file(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -118,7 +136,6 @@ static const struct file_operations paddr_file_ops = { .write = paddr_write_file, }; - static ssize_t dump_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { @@ -189,9 +206,12 @@ static int __init aml_debug_init(void) return -1; } aml_dev.debugfs_reg_access = aml_reg_access; + aml_dev_16.debugfs_reg_access = aml_reg_access_16; debugfs_create_file("paddr", S_IFREG | 0440, debugfs_root, &aml_dev, &paddr_file_ops); + debugfs_create_file("paddr16", S_IFREG | 0440, + debugfs_root, &aml_dev_16, &paddr_file_ops); debugfs_create_file("dump", S_IFREG | 0440, debugfs_root, &aml_dev, &dump_file_ops); return 0; From 6a32ec812fe8475231d3869a404d5b22fe82b23b Mon Sep 17 00:00:00 2001 From: Peng Yixin Date: Wed, 6 Mar 2019 10:27:56 +0800 Subject: [PATCH 0361/1060] video: set pcrscr after 2 frames ready [2/3] PD#SWPL-795 Problem: Solution: add a sysfs to get vframe ready count Verify: Verified p212 Change-Id: I92171f57d336063e4a3af751e808b4a778184fe0 Signed-off-by: Peng Yixin --- drivers/amlogic/media/video_sink/video.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 270560e4e9ef..ce43f60572e0 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -11295,6 +11295,18 @@ static ssize_t video_vsync_slow_factor_store(struct class *cla, return count; } +static ssize_t vframe_ready_cnt_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int ret = -1; + struct vframe_states states; + + ret = video_vf_get_states(&states); + + return snprintf(buf, 10, "%d\n", (ret == 0) ? + states.buf_avail_num : 0); +} + static ssize_t fps_info_show(struct class *cla, struct class_attribute *attr, char *buf) { @@ -12106,6 +12118,7 @@ static struct class_attribute amvideo_class_attrs[] = { __ATTR_RO(vframe_states), __ATTR_RO(video_state), __ATTR_RO(fps_info), + __ATTR_RO(vframe_ready_cnt), __ATTR_RO(video_layer1_state), __ATTR_RO(pic_mode_info), #ifdef VIDEO_PIP From c715fa0800ed87aad0b9035582ab3dd26b6cb498 Mon Sep 17 00:00:00 2001 From: Renjun Xu Date: Thu, 4 Apr 2019 15:08:50 +0800 Subject: [PATCH 0362/1060] audio: fixed the issue of PDM 16 channel capture. [1/1] PD#SWPL-5551 Problem: cannot capture 8PDM + 8LOOPBACK. Solution: PDM cannot support 8PDM + 8LOOPBACK. Verify: s420/s400, verify pass Change-Id: Iaf38bdcb218ebfc024666312162569cab93a76a9 Signed-off-by: Renjun Xu --- sound/soc/amlogic/auge/pdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index 717289ec6db6..5dc48e116749 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -883,7 +883,7 @@ struct snd_soc_dai_driver aml_pdm_dai[] = { .name = "PDM", .capture = { .channels_min = PDM_CHANNELS_MIN, - .channels_max = PDM_CHANNELS_MAX, + .channels_max = PDM_CHANNELS_LB_MAX, .rates = PDM_RATES, .formats = PDM_FORMATS, }, From 65e6d31e356bcc46bcd7ea3e79575d7be40bfd5b Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Mon, 1 Apr 2019 21:11:08 +0800 Subject: [PATCH 0363/1060] media_module: mh264/h265/avs2 [1/2] PD#SWPL-6607 Problem: Not support QOS information for mh264.h265,avs2 Solution: Support QOS information picking for mh264,h265,avs2 Support QOS information access interface by ioctl Verify: Verified franklin Change-Id: I4e6f85392007bc78a274726aba510c39088018e3 Signed-off-by: Rong Zhang --- drivers/amlogic/media/frame_sync/ptsserv.c | 38 ++++++++---- drivers/amlogic/media/frame_sync/tsync.c | 4 +- .../linux/amlogic/media/frame_sync/ptsserv.h | 7 ++- .../amlogic/media/registers/regs/hevc_regs.h | 8 +++ include/linux/amlogic/media/utils/amstream.h | 62 +++++++++++++++++++ 5 files changed, 102 insertions(+), 17 deletions(-) diff --git a/drivers/amlogic/media/frame_sync/ptsserv.c b/drivers/amlogic/media/frame_sync/ptsserv.c index 0930068c7f21..a90057903c35 100644 --- a/drivers/amlogic/media/frame_sync/ptsserv.c +++ b/drivers/amlogic/media/frame_sync/ptsserv.c @@ -55,6 +55,7 @@ struct pts_rec_s { struct list_head list; u32 offset; u32 val; + u32 size; u64 pts_uS64; } /*pts_rec_t */; @@ -640,7 +641,7 @@ int get_last_checkout_pts(u8 type) } EXPORT_SYMBOL(get_last_checkout_pts); -int pts_lookup(u8 type, u32 *val, u32 pts_margin) +int pts_lookup(u8 type, u32 *val, u32 *frame_size, u32 pts_margin) { u32 page, offset; @@ -648,18 +649,20 @@ int pts_lookup(u8 type, u32 *val, u32 pts_margin) if (type == PTS_TYPE_VIDEO) { offset = page * pts_table[PTS_TYPE_VIDEO].buf_size + offset; - pts_lookup_offset(PTS_TYPE_VIDEO, offset, val, pts_margin); + pts_lookup_offset( + PTS_TYPE_VIDEO, offset, val, frame_size, pts_margin); return 0; } else if (type == PTS_TYPE_AUDIO) { offset = page * pts_table[PTS_TYPE_AUDIO].buf_size + offset; - pts_lookup_offset(PTS_TYPE_AUDIO, offset, val, pts_margin); + pts_lookup_offset( + PTS_TYPE_AUDIO, offset, val, frame_size, pts_margin); return 0; } else return -EINVAL; } EXPORT_SYMBOL(pts_lookup); static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, - u32 pts_margin, u64 *uS64) + u32 *frame_size, u32 pts_margin, u64 *uS64) { struct pts_table_s *pTable; int lookup_threshold; @@ -777,6 +780,9 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, } else p2 = p; + if (type == PTS_TYPE_VIDEO) + *frame_size = p->size; + if ((p2) && (OFFSET_DIFF(offset, p2->offset) < lookup_threshold)) { if (p2->val == 0) /* FFT: set valid vpts */ @@ -788,8 +794,9 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, ("vpts look up offset<0x%x> -->", offset); pr_info - ("<0x%x:0x%x>, look_cnt = %d\n", - p2->offset, p2->val, look_cnt); + ("<0x%x:0x%x>, fsize %x, look_cnt = %d\n", + p2->offset, p2->val, + p2->size, look_cnt); } if (tsync_get_debug_apts() @@ -805,6 +812,7 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, } *val = p2->val; *uS64 = p2->pts_uS64; + *frame_size = p2->size; #ifdef CALC_CACHED_TIME pTable->last_checkout_pts = p2->val; @@ -1130,14 +1138,15 @@ static int pts_pick_by_offset_inline_locked(u8 type, u32 offset, u32 *val, static int pts_lookup_offset_inline(u8 type, u32 offset, u32 *val, - u32 pts_margin, u64 *uS64) + u32 *frame_size, u32 pts_margin, u64 *uS64) { unsigned long flags; int res; spin_lock_irqsave(&lock, flags); res = pts_lookup_offset_inline_locked( - type, offset, val, pts_margin, uS64); + type, offset, val, + frame_size, pts_margin, uS64); #if 0 if (timestamp_firstvpts_get() == 0 && res == 0 && (*val) != 0 @@ -1175,18 +1184,21 @@ static int pts_pick_by_offset_inline(u8 type, u32 offset, u32 *val, } -int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin) +int pts_lookup_offset(u8 type, u32 offset, u32 *val, + u32 *frame_size, u32 pts_margin) { u64 pts_us; - return pts_lookup_offset_inline(type, offset, val, pts_margin, &pts_us); + return pts_lookup_offset_inline(type, offset, val, + frame_size, pts_margin, &pts_us); } EXPORT_SYMBOL(pts_lookup_offset); -int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, - u64 *uS64) +int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, + u32 *frame_size, u32 pts_margin, u64 *uS64) { - return pts_lookup_offset_inline(type, offset, val, pts_margin, uS64); + return pts_lookup_offset_inline(type, offset, val, + frame_size, pts_margin, uS64); } EXPORT_SYMBOL(pts_lookup_offset_us64); diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index b18a048f7e4c..711a1a4e200f 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -2003,8 +2003,10 @@ static ssize_t show_startsync_mode(struct class *class, static ssize_t show_apts_lookup(struct class *class, struct class_attribute *attrr, char *buf) { + u32 frame_size; unsigned int pts = 0xffffffff; - pts_lookup_offset(PTS_TYPE_AUDIO, apts_lookup_offset, &pts, 300); + pts_lookup_offset(PTS_TYPE_AUDIO, apts_lookup_offset, + &pts, &frame_size, 300); return sprintf(buf, "0x%x\n", pts); } diff --git a/include/linux/amlogic/media/frame_sync/ptsserv.h b/include/linux/amlogic/media/frame_sync/ptsserv.h index d17f1aaec14f..5d981871d7e5 100644 --- a/include/linux/amlogic/media/frame_sync/ptsserv.h +++ b/include/linux/amlogic/media/frame_sync/ptsserv.h @@ -43,12 +43,13 @@ extern int get_last_checkin_pts(u8 type); extern int get_last_checkout_pts(u8 type); -extern int pts_lookup(u8 type, u32 *val, u32 pts_margin); +extern int pts_lookup(u8 type, u32 *val, u32 *frame_size, u32 pts_margin); -extern int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin); +extern int pts_lookup_offset(u8 type, u32 offset, u32 *val, + u32 *frame_size, u32 pts_margin); extern int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, - u32 pts_margin, u64 *uS64); + u32 *frame_size, u32 pts_margin, u64 *uS64); extern int pts_pickout_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, diff --git a/include/linux/amlogic/media/registers/regs/hevc_regs.h b/include/linux/amlogic/media/registers/regs/hevc_regs.h index 3258b90f752f..9eb5eed0e28a 100644 --- a/include/linux/amlogic/media/registers/regs/hevc_regs.h +++ b/include/linux/amlogic/media/registers/regs/hevc_regs.h @@ -357,6 +357,14 @@ #define HEVC_IQIT_STAT_GEN0 0x3708 #define HEVC_QP_WRITE 0x3709 #define HEVC_IQIT_STAT_GEN1 0x370a +#define HEVC_IQIT_BITDEPTH 0x370b +#define HEVC_IQIT_STAT_GEN2 0x370c +#define HEVC_IQIT_AVS2_WQP_0123 0x370d +#define HEVC_IQIT_AVS2_WQP_45 0x370e +#define HEVC_IQIT_AVS2_QP_DELTA 0x370f +#define HEVC_PIC_QUALITY_CTRL 0x3710 +#define HEVC_PIC_QUALITY_DATA 0x3711 + /**/ /*add from M8M2*/ diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index e79e5b2717c1..a398003ce4b1 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -221,6 +221,9 @@ #define AMSTREAM_IOC_SET_EX _IOW((_A_M), 0xc4, struct am_ioctl_parm_ex) #define AMSTREAM_IOC_GET_PTR _IOWR((_A_M), 0xc5, struct am_ioctl_parm_ptr) #define AMSTREAM_IOC_SET_PTR _IOW((_A_M), 0xc6, struct am_ioctl_parm_ptr) +#define AMSTREAM_IOC_GET_AVINFO _IOR((_A_M), 0xc7, struct av_param_info_t) +#define AMSTREAM_IOC_GET_QOSINFO _IOR((_A_M), 0xc8, struct av_param_qosinfo_t) + #define TRICKMODE_NONE 0x00 #define TRICKMODE_I 0x01 @@ -682,6 +685,65 @@ struct am_ioctl_parm_ptr { u32 len; /*char reserved[4]; */ }; +struct vframe_qos_s { + int num; + int type; + int size; + int pts; + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; + int decode_buffer; +} /*vframe_qos */; + +enum FRAME_FORMAT { + FRAME_FORMAT_UNKNOWN, + FRAME_FORMAT_PROGRESS, + FRAME_FORMAT_INTERLACE, +}; + +#define QOS_FRAME_NUM 60 +struct av_info_t { + /*auido info*/ + int sample_rate; + int channels; + int aformat_type; + unsigned int apts; + unsigned int apts_err; + /*video info*/ + unsigned int width; + unsigned int height; + unsigned int dec_error_count; + unsigned int first_pic_coming; + unsigned int fps; + unsigned int current_fps; + unsigned int vpts; + unsigned int vpts_err; + unsigned int ts_error; + unsigned int first_vpts; + int vformat_type; + enum FRAME_FORMAT frame_format; + unsigned int toggle_frame_count;/*toggle frame count*/ + unsigned int dec_err_frame_count;/*vdec error frame count*/ + unsigned int dec_frame_count;/*vdec frame count*/ + unsigned int dec_drop_frame_count;/*drop frame num*/ + int tsync_mode; +}; + +struct av_param_info_t { + struct av_info_t av_info; +}; +struct av_param_qosinfo_t { + struct vframe_qos_s vframe_qos[QOS_FRAME_NUM]; +}; + + #define SUPPORT_VDEC_NUM (20) int vcodec_profile_register(const struct codec_profile_t *vdec_profile); ssize_t vcodec_profile_read(char *buf); From cabc8b0e58cb016418cee604c5f45cdc7c80be14 Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Fri, 22 Feb 2019 16:28:29 +0800 Subject: [PATCH 0364/1060] media_module: h264/mpeg2/h265 [2/2] PD#SWPL-3654 Problem: provide aspect_ratio information by AMSTREAM_IOC_VDECSTAT Solution: add ration_control information in vdec_status function for h264/mh264/vh265/mpeg12/mmpeg12, and normalized it for aspect_ratio in AMSTREAM_IOC_VDECSTAT message. Verify: Verified U212 Change-Id: Icd9270eb8f2ce2f6f7455ec28780d26ac6c56348 Signed-off-by: Rong Zhang --- include/linux/amlogic/media/utils/amstream.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index a398003ce4b1..1343d436ffb2 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -303,12 +303,20 @@ struct buf_status { #define DECODER_ERROR_MASK (0xffff<<16) + +enum E_ASPECT_RATIO { + ASPECT_RATIO_4_3, + ASPECT_RATIO_16_9, + ASPECT_UNDEFINED = 255 +}; + struct vdec_status { unsigned int width; unsigned int height; unsigned int fps; unsigned int error_count; unsigned int status; + enum E_ASPECT_RATIO euAspectRatio; }; struct vdec_info { @@ -328,6 +336,7 @@ struct vdec_info { unsigned long long total_data; unsigned int samp_cnt; unsigned int offset; + unsigned int ratio_control; char reserved[32]; }; From d74450b24009cf78e3f8b35d8fd93f4f72520c27 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Mon, 8 Apr 2019 17:06:27 +0800 Subject: [PATCH 0365/1060] time: fix fail to read generic timer's counter value correctly [1/1] PD#SWPL-6837 Problem: The return value of arch_counter_get_cntvct is always abnormal when it is in irq stack. In this case, arch_counter_get_cntvct trys to access a variable in 8Bytes via a 4Bytes aligned addr- ess, which vialates the rule: The address that is accessed should be aligned to the size of the data element being accessed Solution: after switching to irq stack, force the base sp value to be 16Bytes aligned. Since the address of variable in irq stack is based on the base sp and arranged automatically, all the data accessing in irq stack will be aligned. Verify: Ampere Change-Id: I3b30a56491dd0720d1c885bfaf2ca98d1b103fdd Signed-off-by: Jiamin Ma --- arch/arm/kernel/unwind.c | 2 +- drivers/amlogic/memory_ext/vmap_stack.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 6f7d0e469286..8fc6b5601a54 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -538,7 +538,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) sp_irq = (unsigned long)irq_stack[cpu]; addr = *((unsigned long *)(sp_irq + THREAD_INFO_OFFSET - 8 - - sizeof(addr))); + sizeof(addr) - 12)); pt_regs = (struct pt_regs *)addr; frame.fp = pt_regs->ARM_fp; frame.sp = pt_regs->ARM_sp; diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index 664ab24b3251..d199f76548c9 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -159,8 +159,9 @@ unsigned long notrace irq_stack_entry(unsigned long sp) sp_irq = (unsigned long)dst - 8; /* * save start addr of the interrupted task's context + * minus an extra 12 to force base sp 16Bytes aligned */ - sp_irq = sp_irq - sizeof(sp); + sp_irq = sp_irq - sizeof(sp) - 12; *((unsigned long *)sp_irq) = sp; return sp_irq; } From a66b4167f25b5402e7c7f08320a1da57734850e9 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 11 Jan 2019 11:27:21 +0800 Subject: [PATCH 0366/1060] hdmitx: add audio ATMOS parsing [1/1] PD#SWPL-4085 Problem: Need audio ATMOS information in RX EDID Solution: Add parsing audio ATMOS information Verify: GXL/P212 Change-Id: I882b817a4d7621833bb7e4b85231d7a42e426382 Signed-off-by: Zongdong Jiao --- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 2 +- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 63 ++++++++++++++----- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index 349e14f70086..4ca47e8ab8d9 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -1477,7 +1477,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, pRXCap->RxAudioCap[idx + i].freq_cc = BlockBuf[offset + i * 3 + 1]&0x7f; pRXCap->RxAudioCap[idx + i].cc3 = - BlockBuf[offset + i * 3 + 2]&0x7; + BlockBuf[offset + i * 3 + 2]; } offset += count; break; diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 7bf5d89bf5ac..04c2347d93f9 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -2356,12 +2356,27 @@ static ssize_t show_disp_cap_3d(struct device *dev, return pos; } +static void _show_pcm_ch(struct rx_cap *pRXCap, int i, + int *ppos, char *buf) +{ + const char * const aud_sample_size[] = {"ReferToStreamHeader", + "16", "20", "24", NULL}; + int j = 0; + + for (j = 0; j < 3; j++) { + if (pRXCap->RxAudioCap[i].cc3 & (1 << j)) + *ppos += snprintf(buf + *ppos, PAGE_SIZE, "%s/", + aud_sample_size[j+1]); + } + *ppos += snprintf(buf + *ppos - 1, PAGE_SIZE, " bit\n"); +} + /**/ static ssize_t show_aud_cap(struct device *dev, struct device_attribute *attr, char *buf) { int i, pos = 0, j; - static const char * const aud_coding_type[] = { + static const char * const aud_ct[] = { "ReferToStreamHeader", "PCM", "AC-3", "MPEG1", "MP3", "MPEG2", "AAC", "DTS", "ATRAC", "OneBitAudio", "Dobly_Digital+", "DTS-HD", "MAT", "DST", "WMA_Pro", @@ -2369,32 +2384,52 @@ static ssize_t show_aud_cap(struct device *dev, static const char * const aud_sampling_frequency[] = { "ReferToStreamHeader", "32", "44.1", "48", "88.2", "96", "176.4", "192", NULL}; - static const char * const aud_sample_size[] = {"ReferToStreamHeader", - "16", "20", "24", NULL}; - struct rx_cap *pRXCap = &(hdmitx_device.RXCap); pos += snprintf(buf + pos, PAGE_SIZE, "CodingType MaxChannels SamplingFreq SampleSize\n"); for (i = 0; i < pRXCap->AUD_count; i++) { - pos += snprintf(buf + pos, PAGE_SIZE, "%s, %d ch, ", - aud_coding_type[pRXCap->RxAudioCap[i]. - audio_format_code], + pos += snprintf(buf + pos, PAGE_SIZE, "%s", + aud_ct[pRXCap->RxAudioCap[i].audio_format_code]); + if ((pRXCap->RxAudioCap[i].audio_format_code == CT_DOLBY_D) && + (pRXCap->RxAudioCap[i].cc3 & 1)) + pos += snprintf(buf + pos, PAGE_SIZE, "/ATMOS"); + pos += snprintf(buf + pos, PAGE_SIZE, ", %d ch, ", pRXCap->RxAudioCap[i].channel_num_max + 1); for (j = 0; j < 7; j++) { if (pRXCap->RxAudioCap[i].freq_cc & (1 << j)) pos += snprintf(buf + pos, PAGE_SIZE, "%s/", aud_sampling_frequency[j+1]); } - pos += snprintf(buf + pos - 1, PAGE_SIZE, " kHz, ") - 1; - for (j = 0; j < 3; j++) { - if (pRXCap->RxAudioCap[i].cc3 & (1 << j)) - pos += snprintf(buf + pos, PAGE_SIZE, "%s/", - aud_sample_size[j+1]); + pos += snprintf(buf + pos - 1, PAGE_SIZE, " kHz, "); + switch (pRXCap->RxAudioCap[i].audio_format_code) { + case CT_PCM: + _show_pcm_ch(pRXCap, i, &pos, buf); + break; + case CT_AC_3: + case CT_MPEG1: + case CT_MP3: + case CT_MPEG2: + case CT_AAC: + case CT_DTS: + case CT_ATRAC: + case CT_ONE_BIT_AUDIO: + pos += snprintf(buf + pos, PAGE_SIZE, + "MaxBitRate %dkHz\n", + pRXCap->RxAudioCap[i].cc3 * 8); + break; + case CT_DOLBY_D: + case CT_DTS_HD: + case CT_MAT: + case CT_DST: + pos += snprintf(buf + pos, PAGE_SIZE, "DepVaule 0x%x\n", + pRXCap->RxAudioCap[i].cc3); + break; + case CT_WMA: + default: + break; } - pos += snprintf(buf + pos - 1, PAGE_SIZE, " bit\n") - 1; } - return pos; } From e76291701e928fd1a081d1b5024d20a277d9c084 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Sat, 6 Apr 2019 16:17:57 +0800 Subject: [PATCH 0367/1060] audio: add codec trigger mute for depop [1/1] PD#SWPL-6944 Problem: TV-3381 Speaker sometimes has clicking noise when playing DTV program. Solution: add codec trigger mute for depop Verify: Local verified. Change-Id: Ib15a6b90bd3a6cdda2255afaf86daeab68ba07e2 Signed-off-by: Shuai Li --- sound/soc/amlogic/auge/card.c | 2 +- sound/soc/amlogic/auge/ddr_mngr.c | 14 +++++++--- sound/soc/codecs/amlogic/tas5805.c | 43 ++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/sound/soc/amlogic/auge/card.c b/sound/soc/amlogic/auge/card.c index 6d71f8fcccef..3e7c82cd0ca2 100644 --- a/sound/soc/amlogic/auge/card.c +++ b/sound/soc/amlogic/auge/card.c @@ -648,7 +648,7 @@ static int aml_card_dai_link_of(struct device_node *node, dai_link->ops = &aml_card_ops; dai_link->init = aml_card_dai_init; - + dai_link->nonatomic = 1; dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt); dev_dbg(dev, "\tcpu : %s / %d\n", diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index ee76da9a38d0..9f6e9e324f88 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -67,6 +67,12 @@ static struct frddr_attach attach_aed; static void aml_check_aed(bool enable, int dst); static bool aml_check_aed_module(int dst); +static irqreturn_t aml_ddr_isr(int irq, void *devid) +{ + (void)devid; + return IRQ_WAKE_THREAD; +} + /* to DDRS */ static struct toddr *register_toddr_l(struct device *dev, struct aml_audio_controller *actrl, @@ -88,8 +94,8 @@ static struct toddr *register_toddr_l(struct device *dev, to = &toddrs[i]; /* irqs request */ - ret = request_irq(to->irq, handler, - 0, dev_name(dev), data); + ret = request_threaded_irq(to->irq, aml_ddr_isr, handler, + IRQF_SHARED, dev_name(dev), data); if (ret) { dev_err(dev, "failed to claim irq %u\n", to->irq); return NULL; @@ -834,8 +840,8 @@ static struct frddr *register_frddr_l(struct device *dev, 1<<31|1<irq, handler, - 0, dev_name(dev), data); + ret = request_threaded_irq(from->irq, aml_ddr_isr, handler, + IRQF_SHARED, dev_name(dev), data); if (ret) { dev_err(dev, "failed to claim irq %u\n", from->irq); return NULL; diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c index 615320e73b89..c7c89f84f748 100644 --- a/sound/soc/codecs/amlogic/tas5805.c +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -52,7 +52,9 @@ #define TAS5805M_REG_29 (0x29) #define TAS5805M_REG_2A (0x2a) #define TAS5805M_REG_2B (0x2b) +#define TAS5805M_SDOUT_SEL (0x30) #define TAS5805M_REG_35 (0x35) +#define TAS5805M_DIG_VAL_CTL (0x4c) #define TAS5805M_REG_7F (0x7f) #define TAS5805M_PAGE_00 (0x00) @@ -231,6 +233,7 @@ struct tas5805m_priv { struct tas5805m_platform_data *pdata; int vol; int mute; + struct snd_soc_codec *codec; }; const struct regmap_config tas5805m_regmap = { @@ -303,6 +306,7 @@ static void tas5805m_set_volume(struct snd_soc_codec *codec, int vol) uint8_t byte3; uint8_t byte2; uint8_t byte1; + pr_info("%s(), vol = %d\n", __func__, vol); index = get_volume_index(vol); volume_hex = tas5805m_volume[index]; @@ -340,7 +344,6 @@ static int tas5805m_vol_locked_put(struct snd_kcontrol *kcontrol, tas5805m->vol = ucontrol->value.integer.value[0]; tas5805m_set_volume(codec, tas5805m->vol); - return 0; } @@ -433,10 +436,13 @@ static int tas5805m_set_bias_level(struct snd_soc_codec *codec, static int tas5805m_snd_probe(struct snd_soc_codec *codec) { + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_add_codec_controls(codec, tas5805m_vol_control, 2); + ret = snd_soc_add_codec_controls(codec, tas5805m_vol_control, + ARRAY_SIZE(tas5805m_vol_control)); + tas5805m->codec = codec; return ret; } @@ -476,8 +482,41 @@ static struct snd_soc_codec_driver soc_codec_tas5805m = { .set_bias_level = tas5805m_set_bias_level, }; +static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *codec_dai) +{ + struct tas5805m_priv *tas5805m = snd_soc_dai_get_drvdata(codec_dai); + struct snd_soc_codec *codec = tas5805m->codec; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + pr_debug("%s(), start\n", __func__); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_REG_7F, TAS5805M_BOOK_00); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_DIG_VAL_CTL, 0x30); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pr_debug("%s(), stop\n", __func__); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_REG_7F, TAS5805M_BOOK_00); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_DIG_VAL_CTL, 0xff); + break; + } + } + + return 0; +} + static const struct snd_soc_dai_ops tas5805m_dai_ops = { //.digital_mute = tas5805m_mute, + .trigger = tas5805m_trigger, }; static struct snd_soc_dai_driver tas5805m_dai = { From 999788bba0d43300a7b26fa01843606138c3423d Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Wed, 10 Apr 2019 17:41:22 +0800 Subject: [PATCH 0368/1060] amvecm: fix lc enable/disable not follow pq.db [1/1] PD#TV-4358 Problem: lc enable/disable not follow pq.db Solution: check the db reg vlaue,then adjust lc_en Verify: TL1 Change-Id: I0bf652eff96d75355c8fb1329291d1611e226b96 Signed-off-by: Bencheng Jing --- drivers/amlogic/media/enhancement/amvecm/amcm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm.c b/drivers/amlogic/media/enhancement/amvecm/amcm.c index 5247bdc41609..25f1767ea155 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcm.c @@ -30,6 +30,7 @@ #include "amcm_regmap.h" #include #include "amcsc.h" +#include "local_contrast.h" #define pr_amcm_dbg(fmt, args...)\ do {\ @@ -244,6 +245,14 @@ void am_set_regmap(struct am_regs_s *p) } else { if (p->am_reg[i].addr == 0x1d26) break; + if (p->am_reg[i].addr == SRSHARP1_LC_TOP_CTRL) { + temp = + (p->am_reg[i].val & p->am_reg[i].mask) + >> 4; + temp &= 0x1; + if (!temp && lc_en) + lc_en = 0; + } if (pq_reg_wr_rdma) VSYNC_WR_MPEG_REG(p->am_reg[i].addr, (aml_read_vcbus(p->am_reg[i].addr) & From 8c616e9d8c5a473eb92474eba3c6427319820b88 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Wed, 20 Feb 2019 02:15:44 -0500 Subject: [PATCH 0369/1060] di: disable deghost refresh according to motion [1/1] PD#SWPL-6423 Problem: deghost refresh according to motion Solution: disable deghost refresh according to motion Verify: verify on TL1 Change-Id: Ic3647462e5f5686f6cc182c30797752ea72c013c Signed-off-by: MingLiang Dong --- drivers/amlogic/media/deinterlace/deinterlace_mtn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index cc92763eeca7..457a177b7ae8 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -596,8 +596,9 @@ static void set_combing_regs(int lvl, int bit_mode) DI_Wr_reg_bits(DI_MTN_1_CTRL1, ((*combing_setting_values[lvl])[0] & combing_setting_masks[i]), 0, 24); - if (bit_mode != 10 && - combing_setting_registers[i] == NR2_MATNR_DEGHOST) + /*working on db, driver don't handle this*/ + if (((bit_mode != 10) || cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + && combing_setting_registers[i] == NR2_MATNR_DEGHOST) break; else if (i < GXTVBB_REG_START) { /* TODO: need change to check if From cc7a1cdff86f6269a13fe53d2c6324391b0b60b2 Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Fri, 1 Mar 2019 14:47:01 +0800 Subject: [PATCH 0370/1060] di: pd22 FW parameters need optimize [1/1] PD#SWPL-5046 Problem: PD22 para is incorrect Solution: correct the parameters Verify: verified by t962x2_x301 Change-Id: I0b26914694dd19f9b06cb37c50f7589a200ea0b1 Signed-off-by: zhiwei.yuan --- .../media/deinterlace/deinterlace_mtn.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index 457a177b7ae8..a42619564157 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -193,9 +193,11 @@ static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = { 0x02020606, 0x05080344, 0x40020a04, - 0x0001ff0c, /* 0x0001FF12 */ - 0x00400204, /* 0x00200204 */ - 0x00016404, /* 0x00012002 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ 0x00000142 }; @@ -211,10 +213,12 @@ static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = { 0x0D200302, 0x02020606, 0x05080344, - 0x40020a04, /* 0x60000404,*/ - 0x0001ff0c, /* 0x0001FF12 */ - 0x00400204, /* 0x00200204 */ - 0x00016404, /* 0x00012002 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x60000404, /* 0x40020a04*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ 0x00000131 }; /*special for resolution test file*/ From 20280b11a98fcf5bedd32cd61cc97e21b9133f34 Mon Sep 17 00:00:00 2001 From: shanghai engineers Date: Fri, 22 Mar 2019 04:58:34 -0400 Subject: [PATCH 0371/1060] tm2: add tm2_pxp dts at amlogic for ptm bringup [1/1] PD#SWPL-6157 Problem: Current branch need tm2_pxp dts at amlogic system Solution: Create tm2_pxp dts at tm2 kernel branch, and modified scripts Verify: on ptm board4 Change-Id: I83204db07462729861a59d322fa99e4370c09dea Signed-off-by: pan yang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 2145 +++++++++++++++++++++ arch/arm/boot/dts/amlogic/tm2_pxp.dts | 1134 +++++++++++ arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 2124 ++++++++++++++++++++ arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 1129 +++++++++++ scripts/amlogic/mk_32dtb.sh | 3 +- scripts/amlogic/mk_dtb_gx.sh | 2 + 6 files changed, 6535 insertions(+), 2 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/mesontm2.dtsi create mode 100644 arch/arm/boot/dts/amlogic/tm2_pxp.dts create mode 100644 arch/arm64/boot/dts/amlogic/mesontm2.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/tm2_pxp.dts diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi new file mode 100644 index 000000000000..7204b77c2d95 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -0,0 +1,2145 @@ +/* + * arch/arm/boot/dts/amlogic/mesontl1.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include +/ { + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus:cpus { + #address-cells = <1>; + #size-cells = <0>; + #cooling-cells = <2>;/* min followed by max */ + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x0>; + //timer=<&timer_a>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x1>; + //timer=<&timer_b>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x2>; + //timer=<&timer_c>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0x3>; + //timer=<&timer_d>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg = <0xffd0f190 0x4 0xffd0f194 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating =<300>; + clockevent-shift =<20>; + clockevent-features =<0x23>; + interrupts = <0 60 1>; + bit_enable =<16>; + bit_mode =<12>; + bit_resolution =<0>; + }; + + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xffc01000 0x1000>, + <0xffc02000 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + scpi_clocks { + compatible = "arm, scpi-clks"; + + scpi_dvfs: scpi_clocks@0 { + compatible = "arm, scpi-clk-indexed"; + #clock-cells = <1>; + clock-indices = <0>; + clock-output-names = "vcpu"; + }; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "okay"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@ff63c400 { + status = "disabled"; + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffd7000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + io_cbus_base { + reg = <0xffd00000 0x101000>; + }; + io_apb_base { + reg = <0xffe01000 0x19f000>; + }; + io_aobus_base { + reg = <0xff800000 0x100000>; + }; + io_vapb_base { + reg = <0xff900000 0x200000>; + }; + io_hiu_base { + reg = <0xff63c000 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + meson_suspend: pm { + compatible = "amlogic, pm"; + /*gxbaby-suspend;*/ + status = "okay"; + reg = <0xff8000a8 0x4>, + <0xff80023c 0x4>; + }; + + cpuinfo { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2018/01/01"; + status = "disabled"; + }; + + reboot { + compatible = "amlogic,reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "disabled"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + vpu { + compatible = "amlogic, vpu-tl1"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014 { + compatible = "amlogic,meson-tl1-aobus-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio_ao: ao-bank@ff800014 { + reg = <0xff800014 0x8>, + <0xff800024 0x14>, + <0xff80001c 0x8>; + reg-names = "mux", "gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + aoceca_mux:aoceca_mux { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocecb_mux:aocecb_mux { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + }; + + pinctrl_periphs: pinctrl@ff6346c0 { + compatible = "amlogic,meson-tl1-periphs-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio: banks@ff6346c0 { + reg = <0xff6346c0 0x40>, + <0xff6344e8 0x18>, + <0xff634520 0x18>, + <0xff634440 0x4c>, + <0xff634740 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + + hdmirx_a_mux:hdmirx_a_mux { + mux { + groups = "hdmirx_a_hpd", "hdmirx_a_det", + "hdmirx_a_sda", "hdmirx_a_sck"; + function = "hdmirx_a"; + }; + }; + + hdmirx_b_mux:hdmirx_b_mux { + mux { + groups = "hdmirx_b_hpd", "hdmirx_b_det", + "hdmirx_b_sda", "hdmirx_b_sck"; + function = "hdmirx_b"; + }; + }; + + hdmirx_c_mux:hdmirx_c_mux { + mux { + groups = "hdmirx_c_hpd", "hdmirx_c_det", + "hdmirx_c_sda", "hdmirx_c_sck"; + function = "hdmirx_c"; + }; + }; + + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000 + 0xff658000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <1>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0xffe09080 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ + /** 0x2: amlogic-v2 phy **/ + phy-interface = <0x2>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "disabled"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0xffd0f0d0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao */ + pinctrl-names="jtag_apao_pins"; + pinctrl-0=<&jtag_apao_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <689000>; + regulator-max-microvolt = <1049000>; + regulator-always-on; + max-duty-cycle = <1500>; + /* Voltage Duty-Cycle */ + voltage-table = <1049000 0>, + <1039000 3>, + <1029000 6>, + <1019000 8>, + <1009000 11>, + <999000 14>, + <989000 17>, + <979000 20>, + <969000 23>, + <959000 26>, + <949000 29>, + <939000 31>, + <929000 34>, + <919000 37>, + <909000 40>, + <899000 43>, + <889000 45>, + <879000 48>, + <869000 51>, + <859000 54>, + <849000 56>, + <839000 59>, + <829000 62>, + <819000 65>, + <809000 68>, + <799000 70>, + <789000 73>, + <779000 76>, + <769000 79>, + <759000 81>, + <749000 84>, + <739000 87>, + <729000 89>, + <719000 92>, + <709000 95>, + <699000 98>, + <689000 100>; + status = "disabled"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0xff63c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff63c000 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,tl1-clkc"; + #clock-cells = <1>; + reg = <0x0 0x3fc>; + }; + };/* end of hiubus*/ + + audiobus: audiobus@0xff600000 { + compatible = "amlogic, audio-controller", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff600000 0x10000>; + ranges = <0x0 0xff600000 0x10000>; + + clkaudio:audio_clocks { + compatible = "amlogic, tl1-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0xb0>; + }; + + ddr_manager { + compatible = "amlogic, tl1-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 48 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; + }; + };/* end of audiobus*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF601000 0x400>; + }; + audiobus_base { + reg = <0xFF600000 0x1000>; + }; + audiolocker_base { + reg = <0xFF601400 0x400>; + }; + eqdrc_base { + reg = <0xFF602000 0x2000>; + }; + reset_base { + reg = <0xFFD01000 0x1000>; + }; + vad_base { + reg = <0xFF601800 0x800>; + }; + }; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0xffd00000 0x27000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xffd00000 0x27000>; + + clk-measure@18004 { + compatible = "amlogic,tl1-measure"; + reg = <0x18004 0x4 0x1800c 0x4>; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1f000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1e000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1d000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x1c000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-tl1-gpio-intc"; + reg = <0xf080 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x1b000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x1a000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x19000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x13000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x15000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0xff800000 0xb000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff800000 0xb000>; + + cpu_version { + reg = <0x220 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,tl1-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x1000>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x7000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x2000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + //pinctrl-names = "default"; + //pinctrl-0 = <&ao_a_uart_pins>; + /* 0 not support; 1 support */ + support-sysrq = <0>; + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins1>; + }; + + remote: rc@8040 { + compatible = "amlogic, aml_remote"; + reg = <0x8040 0x44>, + <0x8000 0x20>; + status = "okay"; + protocol = ; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; + }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x05000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x6000 0x20>; + interrupts = ; + pinctrl-names="default"; + pinctrl-0=<&i2c_ao_slave_pins>; + }; + };/* end of aobus */ + + ion_dev { + compatible = "amlogic, ion_dev"; + status = "disabled"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + }; /* end of soc*/ + + custom_maps: custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <44>; /*keymap size*/ + keymap = ; + }; + + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe07000 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_GP0_PLL>, + <&xtal>; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + + spifc: spifc@ffd14000 { + compatible = "amlogic,aml-spi-nor"; + status = "disabled"; + + reg = <0xffd14000 0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&spifc_all_pins>; + clock-names = "core"; + clocks = <&clkc CLKID_CLK81>; + + spi-nor@0 { + compatible = "jedec,spi-nor"; + spifc-frequency = <40000000>; + read-capability = <4>;/* dual read 1_1_2 */ + spifc-io-width = <4>; + }; + }; + + slc_nand: nand-controller@0xFFE07800 { + compatible = "amlogic, aml_mtd_nand"; + status = "disabled"; + reg = <0xFFE07800 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + *with uboot if bl_mode was set as 1 + *bl_mode: 0 compact mode;1 descrete mode + *if bl_mode was set as 1,fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy*/ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts*/ + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + status = "okay"; + clocks = <&clkc CLKID_U_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_CLK81 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "clk_81", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vcodec-dec { + compatible = "amlogic, vcodec-dec"; + status = "okay"; + }; + + vdec { + compatible = "amlogic, vdec"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + canvas: canvas { + compatible = "amlogic, meson, canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + io_efuse_base{ + reg = <0xff630000 0x2000>; + }; + }; + + rdma { + compatible = "amlogic, meson-tl1, rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: fb { + compatible = "amlogic, meson-tl1"; + memory-region = <&logo_reserved>; + status = "disabled"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + ionvideo { + compatible = "amlogic, ionvideo"; + status = "okay"; + }; + + amlvideo { + compatible = "amlogic, amlvideo"; + status = "okay"; + }; + + vdac { + compatible = "amlogic, vdac-tl1"; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "disabled"; + reg_base = <0xff638800>; + interrupts = ; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + mem_size = <0 0x100000>; + status = "okay"; + }; +}; /* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins: sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1", + "GPIOAO_2", + "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_6", + "GPIOAO_7", + "GPIOAO_8", + "GPIOAO_9", + "GPIOAO_10", + "GPIOAO_11", + "GPIOE_0", + "GPIOE_1", + "GPIOE_2", + "GPIO_TEST_N"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins: sd_to_ao_uart_pins { + mux { + groups = "uart_ao_a_tx", + "uart_ao_a_rx", + "uart_ao_a_cts", + "uart_ao_a_rts"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins1: pwm_ao_c_hiz1 { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins2: pwm_ao_c_hiz2 { + mux { + groups = "pwm_ao_c_hiz_7"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_e2"; + }; + }; + + i2c_ao_2_pins:i2c_ao_2 { + mux { + groups = "i2c_ao_sck_2", + "i2c_ao_sda_3"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_e_pins:i2c_ao_e { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_slave_pins:i2c_ao_slave { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_a_rx", + "uart_ao_a_tx"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins1:ao_b_uart1 { + mux { + groups = "uart_ao_b_tx_2", + "uart_ao_b_rx_3"; + function = "uart_ao_b"; + }; + }; + + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_b_tx_8", + "uart_ao_b_rx_9"; + function = "uart_ao_b"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins: emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up: emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done: emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins: sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins: sd_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_1bit_pins: sd_1bit_pins { + mux { + groups = "sdcard_d0", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins: ao_to_sd_uart_pins { + mux { + groups ="uart_ao_a_rx_w3", + "uart_ao_a_tx_w2", + "uart_ao_a_rx_w7", + "uart_ao_a_tx_w6", + "uart_ao_a_rx_w11", + "uart_ao_a_tx_w10"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr"; + function = "nand"; + input-enable; + drive-strength = <3>; + }; + }; + + nand_cs_pins:nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + drive-strength = <3>; + }; + }; + + /* sdemmc port */ + sdio_clk_cmd_pins: sdio_clk_cmd_pins { + mux { + groups = "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins: sdio_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spifc_cs_pin:spifc_cs_pin { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_pulldown: spifc_pulldown { + mux { + groups = "nor_d", + "nor_q", + "nor_c"; + function = "nor"; + bias-pull-down; + }; + }; + + spifc_pullup: spifc_pullup { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_all_pins: spifc_all_pins { + mux { + groups = "nor_d", + "nor_q", + "nor_c", + "nor_hold", + "nor_wp"; + function = "nor"; + input-enable; + bias-pull-down; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_c"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_dv"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_h"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_dv"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_e_pins1: pwm_e1 { + mux { + groups = "pwm_e_dv"; + function = "pwm_e"; + }; + }; + + pwm_e_pins2: pwm_e2 { + mux { + groups = "pwm_e_z"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_dv"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + i2c0_c_pins:i2c0_c { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c0_dv_pins:i2c0_dv { + mux { + groups = "i2c0_sda_dv", + "i2c0_sck_dv"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_z_pins:i2c1_z { + mux { + groups = "i2c1_sda_z", + "i2c1_sck_z"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_h_pins:i2c1_h { + mux { + groups = "i2c1_sda_h", + "i2c1_sck_h"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_h_pins:i2c2_h { + mux { + groups = "i2c2_sda_h", + "i2c2_sck_h"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_z_pins:i2c2_z { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h1_pins:i2c3_h1 { + mux { + groups = "i2c3_sda_h1", + "i2c3_sck_h0"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h20_pins:i2c3_h3 { + mux { + groups = "i2c3_sda_h20", + "i2c3_sck_h19"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_dv_pins:i2c3_dv { + mux { + groups = "i2c3_sda_dv", + "i2c3_sck_dv"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_c_pins:i2c3_c { + mux { + groups = "i2c3_sda_c", + "i2c3_sck_c"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spicc0_pins_h: spicc0_pins_h { + mux { + groups = "spi0_mosi_h", + "spi0_miso_h", + "spi0_clk_h"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins_dv: spicc1_pins_dv { + mux { + groups = "spi1_mosi_dv", + "spi1_miso_dv", + "spi1_clk_dv"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_a_tx", + "uart_a_rx", + "uart_a_cts", + "uart_a_rts"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_b_tx", + "uart_b_rx"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_c_tx", + "uart_c_rx"; + function = "uart_c"; + }; + }; + + atvdemod_agc_pins: atvdemod_agc_pins { + mux { + groups = "atv_if_agc_dv"; + function = "atv"; + }; + }; + + dtvdemod_agc_pins: dtvdemod_agc_pins { + mux { + groups = "dtv_if_agc_dv2"; + function = "dtv"; + }; + }; + + lcd_vbyone_pins: lcd_vbyone_pin { + mux { + groups = "vx1_lockn","vx1_htpdn"; + function = "vx1"; + }; + }; + + lcd_vbyone_off_pins: lcd_vbyone_off_pin { + mux { + groups = "GPIOH_15","GPIOH_16"; + function = "gpio_periphs"; + input-enable; + }; + }; + + lcd_tcon_pins: lcd_tcon_pin { + mux { + groups = "tcon_0","tcon_1","tcon_2","tcon_3", + "tcon_4","tcon_5","tcon_6","tcon_7", + "tcon_8","tcon_9","tcon_10","tcon_11", + "tcon_12","tcon_13","tcon_14","tcon_15", + "tcon_lock","tcon_spi_mo","tcon_spi_mi", + "tcon_spi_clk","tcon_spi_ss"; + function = "tcon"; + }; + }; + lcd_tcon_off_pins: lcd_tcon_off_pin { + mux { + groups = "GPIOH_0","GPIOH_1","GPIOH_2","GPIOH_3", + "GPIOH_4","GPIOH_5","GPIOH_6","GPIOH_7", + "GPIOH_8","GPIOH_9","GPIOH_10","GPIOH_11", + "GPIOH_12","GPIOH_13","GPIOH_14","GPIOH_15", + "GPIOH_16","GPIOH_17","GPIOH_18","GPIOH_19", + "GPIOH_20"; + function = "gpio_periphs"; + input-enable; + }; + }; +}; + +&gpu{ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts new file mode 100644 index 000000000000..25010e7c12a6 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -0,0 +1,1134 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_pxp.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_skt-panel.dtsi" + +/ { + model = "Amlogic TL1 PXP"; + amlogic-dt-id = "tl1_pxp"; + compatible = "amlogic, tl1_pxp"; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + /*alloc-ranges = <0x30000000 0x50000000>;*/ + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + status = "disabled"; + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "disabled"; + }; + + ppmgr { + status = "disabled"; + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + + status = "disabled"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; +/* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "disabled"; + reg = <0xff632000 0x1c>; + tdmout_index = <1>; + tdmin_index = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + //memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * 0: normal mode, not use afbce + * 1: use afbce non-mmu mode + * 2: use afbce mmu mode + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <699000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <699000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <709000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <719000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <729000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <749000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <769000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <779000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <789000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <829000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <879000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <929000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "disabled"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_a &spdifin_a>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "clk_srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "disabled"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8*/ + groups = "pdm_dclk_z", + "pdm_din0_z"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&sd_emmc_b { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&dwc3 { + status = "disabled"; +}; + +&usb2_phy_v2 { + status = "disabled"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "disabled"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "disabled"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "disabled"; +}; + +&efuse { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi new file mode 100644 index 000000000000..b9736ffded44 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -0,0 +1,2124 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus:cpus { + #address-cells = <2>; + #size-cells = <0>; + #cooling-cells = <2>;/* min followed by max */ + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + //timer=<&timer_a>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + //timer=<&timer_b>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x2>; + //timer=<&timer_c>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x3>; + //timer=<&timer_d>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg = <0x0 0xffd0f190 0x0 0x4 0x0 0xffd0f194 0x0 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating =<300>; + clockevent-shift =<20>; + clockevent-features =<0x23>; + interrupts = <0 60 1>; + bit_enable =<16>; + bit_mode =<12>; + bit_resolution =<0>; + }; + + arm_pmu { + compatible = "arm,armv8-pmuv3"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <2>; + interrupt-controller; + reg = <0x0 0xffc01000 0x0 0x1000>, + <0x0 0xffc02000 0x0 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "okay"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@ff63c400 { + status = "disabled"; + compatible = "amlogic, meson_mhu"; + reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ + <0x0 0xfffd7000 0x0 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + io_cbus_base { + reg = <0x0 0xffd00000 0x0 0x101000>; + }; + io_apb_base { + reg = <0x0 0xffe01000 0x0 0x19f000>; + }; + io_aobus_base { + reg = <0x0 0xff800000 0x0 0x100000>; + }; + io_vapb_base { + reg = <0x0 0xff900000 0x0 0x200000>; + }; + io_hiu_base { + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + meson_suspend: pm { + compatible = "amlogic, pm"; + /*gxbaby-suspend;*/ + status = "okay"; + reg = <0x0 0xff8000a8 0x0 0x4>, + <0x0 0xff80023c 0x0 0x4>; + }; + + cpuinfo { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + reboot { + compatible = "amlogic,reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "disabled"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + vpu { + compatible = "amlogic, vpu-tl1"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8 + 0x0 0xff64c000 0x0 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014 { + compatible = "amlogic,meson-tl1-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: ao-bank@ff800014 { + reg = <0x0 0xff800014 0x0 0x8>, + <0x0 0xff800024 0x0 0x14>, + <0x0 0xff80001c 0x0 0x8>; + reg-names = "mux", "gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + aoceca_mux:aoceca_mux { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocecb_mux:aocecb_mux { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + }; + + pinctrl_periphs: pinctrl@ff6346c0 { + compatible = "amlogic,meson-tl1-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: banks@ff6346c0 { + reg = <0x0 0xff6346c0 0x0 0x40>, + <0x0 0xff6344e8 0x0 0x18>, + <0x0 0xff634520 0x0 0x18>, + <0x0 0xff634440 0x0 0x4c>, + <0x0 0xff634740 0x0 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + + hdmirx_a_mux:hdmirx_a_mux { + mux { + groups = "hdmirx_a_hpd", "hdmirx_a_det", + "hdmirx_a_sda", "hdmirx_a_sck"; + function = "hdmirx_a"; + }; + }; + + hdmirx_b_mux:hdmirx_b_mux { + mux { + groups = "hdmirx_b_hpd", "hdmirx_b_det", + "hdmirx_b_sda", "hdmirx_b_sck"; + function = "hdmirx_b"; + }; + }; + + hdmirx_c_mux:hdmirx_c_mux { + mux { + groups = "hdmirx_c_hpd", "hdmirx_c_det", + "hdmirx_c_sda", "hdmirx_c_sck"; + function = "hdmirx_c"; + }; + }; + + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x100 + 0x0 0xff636000 0x0 0x2000 + 0x0 0xff63a000 0x0 0x2000 + 0x0 0xff658000 0x0 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <1>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0x0 0xffe09080 0x0 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ + /** 0x2: amlogic-v2 phy **/ + phy-interface = <0x2>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "disabled"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0x0 0xffd0f0d0 0x0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao */ + pinctrl-names="jtag_apao_pins"; + pinctrl-0=<&jtag_apao_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0x0 0xff809000 0x0 0x48>; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <689000>; + regulator-max-microvolt = <1049000>; + regulator-always-on; + max-duty-cycle = <1500>; + /* Voltage Duty-Cycle */ + voltage-table = <1049000 0>, + <1039000 3>, + <1029000 6>, + <1019000 8>, + <1009000 11>, + <999000 14>, + <989000 17>, + <979000 20>, + <969000 23>, + <959000 26>, + <949000 29>, + <939000 31>, + <929000 34>, + <919000 37>, + <909000 40>, + <899000 43>, + <889000 45>, + <879000 48>, + <869000 51>, + <859000 54>, + <849000 56>, + <839000 59>, + <829000 62>, + <819000 65>, + <809000 68>, + <799000 70>, + <789000 73>, + <779000 76>, + <769000 79>, + <759000 81>, + <749000 84>, + <739000 87>, + <729000 89>, + <719000 92>, + <709000 95>, + <699000 98>, + <689000 100>; + status = "disabled"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0x0 0xff63e000 0x0 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff630218 0x0 0x4>; + quality = /bits/ 16 <1000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,tl1-clkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3fc>; + }; + };/* end of hiubus*/ + + audiobus: audiobus@0xff600000 { + compatible = "amlogic, audio-controller", "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff600000 0x0 0x10000>; + ranges = <0x0 0x0 0x0 0xff600000 0x0 0x10000>; + + clkaudio:audio_clocks { + compatible = "amlogic, tl1-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0xb0>; + }; + + ddr_manager { + compatible = "amlogic, tl1-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 48 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; + }; + };/* end of audiobus*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF601000 0x0 0x400>; + }; + audiobus_base { + reg = <0x0 0xFF600000 0x0 0x1000>; + }; + audiolocker_base { + reg = <0x0 0xFF601400 0x0 0x400>; + }; + eqdrc_base { + reg = <0x0 0xFF602000 0x0 0x2000>; + }; + reset_base { + reg = <0x0 0xFFD01000 0x0 0x1000>; + }; + vad_base { + reg = <0x0 0xFF601800 0x0 0x800>; + }; + }; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x27000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x27000>; + + clk-measure@18004 { + compatible = "amlogic,tl1-measure"; + reg = <0x0 0x18004 0x0 0x4 0x0 0x1800c 0x0 0x4>; + ringctrl = <0xff6345fc>; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-tl1-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x13000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x15000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0xb000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0xb000>; + + cpu_version { + reg = <0x0 0x220 0x0 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,tl1-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x1000>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + //pinctrl-names = "default"; + //pinctrl-0 = <&ao_a_uart_pins>; + /* 0 not support; 1 support */ + support-sysrq = <0>; + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins1>; + }; + remote: rc@8040 { + compatible = "amlogic, aml_remote"; + reg = <0x0 0x8040 0x0 0x44>, + <0x0 0x8000 0x0 0x20>; + status = "okay"; + protocol = ; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; + }; + + meson_irblaster: irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0x14c 0x0 0x10>, + <0x0 0x40 0x0 0x4>; + interrupts = <0 198 1>; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = , + ; + #address-cells = <2>; + #size-cells = <2>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0x6000 0x0 0x20>; + interrupts = ; + pinctrl-names="default"; + pinctrl-0=<&i2c_ao_slave_pins>; + }; + };/* end of aobus */ + + ion_dev { + compatible = "amlogic, ion_dev"; + status = "disabled"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + }; /* end of soc*/ + + custom_maps: custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <44>; /*keymap size*/ + keymap = ; + }; + + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd22000 0x0 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_GP0_PLL>, + <&xtal>; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + + spifc: spifc@ffd14000 { + compatible = "amlogic,aml-spi-nor"; + status = "disabled"; + + reg = <0x0 0xffd14000 0x0 0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&spifc_all_pins>; + clock-names = "core"; + clocks = <&clkc CLKID_CLK81>; + + spi-nor@0 { + compatible = "jedec,spi-nor"; + spifc-frequency = <40000000>; + read-capability = <4>;/* dual read 1_1_2 */ + spifc-io-width = <4>; + }; + }; + + slc_nand: nand-controller@0xFFE07800 { + compatible = "amlogic, aml_mtd_nand"; + status = "disabled"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + *with uboot if bl_mode was set as 1 + *bl_mode: 0 compact mode;1 descrete mode + *if bl_mode was set as 1,fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy*/ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts*/ + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + status = "okay"; + clocks = <&clkc CLKID_U_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_CLK81 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "clk_81", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vcodec-dec { + compatible = "amlogic, vcodec-dec"; + status = "okay"; + }; + + vdec { + compatible = "amlogic, vdec"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + canvas: canvas { + compatible = "amlogic, meson, canvas"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x2000>; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base{ + reg = <0x0 0xffd00000 0x0 0x100000>; + }; + io_dos_base{ + reg = <0x0 0xff620000 0x0 0x10000>; + }; + io_hiubus_base{ + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + io_aobus_base{ + reg = <0x0 0xff800000 0x0 0x10000>; + }; + io_vcbus_base{ + reg = <0x0 0xff900000 0x0 0x40000>; + }; + io_dmc_base{ + reg = <0x0 0xff638000 0x0 0x2000>; + }; + io_efuse_base{ + reg = <0x0 0xff630000 0x0 0x2000>; + }; + }; + + rdma { + compatible = "amlogic, meson-tl1, rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: fb { + compatible = "amlogic, meson-tl1"; + memory-region = <&logo_reserved>; + status = "disabled"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + ionvideo { + compatible = "amlogic, ionvideo"; + status = "okay"; + }; + + amlvideo { + compatible = "amlogic, amlvideo"; + status = "okay"; + }; + + vdac { + compatible = "amlogic, vdac-tl1"; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "disabled"; + reg = <0x0 0xff638000 0x0 0x100 + 0x0 0xff638c00 0x0 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "disabled"; + reg_base = <0xff638800>; + interrupts = ; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + mem_size = <0 0x100000>; + status = "okay"; + }; +}; /* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins: sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1", + "GPIOAO_2", + "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_6", + "GPIOAO_7", + "GPIOAO_8", + "GPIOAO_9", + "GPIOAO_10", + "GPIOAO_11", + "GPIOE_0", + "GPIOE_1", + "GPIOE_2", + "GPIO_TEST_N"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins: sd_to_ao_uart_pins { + mux { + groups = "uart_ao_a_tx", + "uart_ao_a_rx", + "uart_ao_a_cts", + "uart_ao_a_rts"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins1: pwm_ao_c_hiz1 { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins2: pwm_ao_c_hiz2 { + mux { + groups = "pwm_ao_c_hiz_7"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_e2"; + }; + }; + + i2c_ao_2_pins:i2c_ao_2 { + mux { + groups = "i2c_ao_sck_2", + "i2c_ao_sda_3"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_e_pins:i2c_ao_e { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_slave_pins:i2c_ao_slave { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_a_rx", + "uart_ao_a_tx"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins1:ao_b_uart1 { + mux { + groups = "uart_ao_b_tx_2", + "uart_ao_b_rx_3"; + function = "uart_ao_b"; + }; + }; + + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_b_tx_8", + "uart_ao_b_rx_9"; + function = "uart_ao_b"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins: emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up: emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done: emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins: sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins: sd_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_1bit_pins: sd_1bit_pins { + mux { + groups = "sdcard_d0", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins: ao_to_sd_uart_pins { + mux { + groups ="uart_ao_a_rx_w3", + "uart_ao_a_tx_w2", + "uart_ao_a_rx_w7", + "uart_ao_a_tx_w6", + "uart_ao_a_rx_w11", + "uart_ao_a_tx_w10"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr"; + function = "nand"; + input-enable; + drive-strength = <3>; + }; + }; + + nand_cs_pins:nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + drive-strength = <3>; + }; + }; + + /* sdemmc port */ + sdio_clk_cmd_pins: sdio_clk_cmd_pins { + mux { + groups = "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins: sdio_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spifc_cs_pin:spifc_cs_pin { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_pulldown: spifc_pulldown { + mux { + groups = "nor_d", + "nor_q", + "nor_c"; + function = "nor"; + bias-pull-down; + }; + }; + + spifc_pullup: spifc_pullup { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_all_pins: spifc_all_pins { + mux { + groups = "nor_d", + "nor_q", + "nor_c", + "nor_hold", + "nor_wp"; + function = "nor"; + input-enable; + bias-pull-down; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_c"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_dv"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_h"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_dv"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_e_pins1: pwm_e1 { + mux { + groups = "pwm_e_dv"; + function = "pwm_e"; + }; + }; + + pwm_e_pins2: pwm_e2 { + mux { + groups = "pwm_e_z"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_dv"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + i2c0_c_pins:i2c0_c { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c0_dv_pins:i2c0_dv { + mux { + groups = "i2c0_sda_dv", + "i2c0_sck_dv"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_z_pins:i2c1_z { + mux { + groups = "i2c1_sda_z", + "i2c1_sck_z"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_h_pins:i2c1_h { + mux { + groups = "i2c1_sda_h", + "i2c1_sck_h"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_h_pins:i2c2_h { + mux { + groups = "i2c2_sda_h", + "i2c2_sck_h"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_z_pins:i2c2_z { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h1_pins:i2c3_h1 { + mux { + groups = "i2c3_sda_h1", + "i2c3_sck_h0"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h20_pins:i2c3_h3 { + mux { + groups = "i2c3_sda_h20", + "i2c3_sck_h19"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_dv_pins:i2c3_dv { + mux { + groups = "i2c3_sda_dv", + "i2c3_sck_dv"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_c_pins:i2c3_c { + mux { + groups = "i2c3_sda_c", + "i2c3_sck_c"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spicc0_pins_h: spicc0_pins_h { + mux { + groups = "spi0_mosi_h", + "spi0_miso_h", + "spi0_clk_h"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins_dv: spicc1_pins_dv { + mux { + groups = "spi1_mosi_dv", + "spi1_miso_dv", + "spi1_clk_dv"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_a_tx", + "uart_a_rx", + "uart_a_cts", + "uart_a_rts"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_b_tx", + "uart_b_rx"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_c_tx", + "uart_c_rx"; + function = "uart_c"; + }; + }; + + atvdemod_agc_pins: atvdemod_agc_pins { + mux { + groups = "atv_if_agc_dv"; + function = "atv"; + }; + }; + + dtvdemod_agc_pins: dtvdemod_agc_pins { + mux { + groups = "dtv_if_agc_dv2"; + function = "dtv"; + }; + }; + + lcd_vbyone_pins: lcd_vbyone_pin { + mux { + groups = "vx1_lockn","vx1_htpdn"; + function = "vx1"; + }; + }; + lcd_vbyone_off_pins: lcd_vbyone_off_pin { + mux { + groups = "GPIOH_15","GPIOH_16"; + function = "gpio_periphs"; + input-enable; + }; + }; + + lcd_tcon_pins: lcd_tcon_pin { + mux { + groups = "tcon_0","tcon_1","tcon_2","tcon_3", + "tcon_4","tcon_5","tcon_6","tcon_7", + "tcon_8","tcon_9","tcon_10","tcon_11", + "tcon_12","tcon_13","tcon_14","tcon_15", + "tcon_lock","tcon_spi_mo","tcon_spi_mi", + "tcon_spi_clk","tcon_spi_ss"; + function = "tcon"; + }; + }; + lcd_tcon_off_pins: lcd_tcon_off_pin { + mux { + groups = "GPIOH_0","GPIOH_1","GPIOH_2","GPIOH_3", + "GPIOH_4","GPIOH_5","GPIOH_6","GPIOH_7", + "GPIOH_8","GPIOH_9","GPIOH_10","GPIOH_11", + "GPIOH_12","GPIOH_13","GPIOH_14","GPIOH_15", + "GPIOH_16","GPIOH_17","GPIOH_18","GPIOH_19", + "GPIOH_20"; + function = "gpio_periphs"; + input-enable; + }; + }; +}; + +&gpu{ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts new file mode 100644 index 000000000000..5a7bd66c7f80 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -0,0 +1,1129 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_pxp.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +/*#include "mesontl1_skt-panel.dtsi"*/ + +/ { + model = "Amlogic TL1 PXP"; + amlogic-dt-id = "tl1_pxp"; + compatible = "amlogic, tl1_pxp"; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + status = "disabled"; + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "disabled"; + }; + + ppmgr { + status = "disabled"; + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + + status = "disabled"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "disabled"; + reg = <0xff632000 0x1c>; + tdmout_index = <1>; + tdmin_index = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + //memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * 0: normal mode, not use afbce + * 1: use afbce non-mmu mode + * 2: use afbce mmu mode + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 1>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <699000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <699000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <709000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <719000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <729000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <749000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <769000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <779000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <789000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <829000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <879000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <929000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "disabled"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c0>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + }; + }; +};/* end of / */ + + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_a &spdifin_a>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "clk_srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "disabled"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8*/ + groups = "pdm_dclk_z", + "pdm_din0_z"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&sd_emmc_b { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&dwc3 { + status = "disabled"; +}; + +&usb2_phy_v2 { + status = "disabled"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "disabled"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "disabled"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "disabled"; +}; + +&efuse { + status = "disabled"; +}; diff --git a/scripts/amlogic/mk_32dtb.sh b/scripts/amlogic/mk_32dtb.sh index a014162b9b76..88bb658130d1 100755 --- a/scripts/amlogic/mk_32dtb.sh +++ b/scripts/amlogic/mk_32dtb.sh @@ -13,6 +13,5 @@ make ARCH=arm txl_t962_p321.dtb make ARCH=arm txlx_t962e_r321.dtb make ARCH=arm txlx_t962x_r311_1g.dtb make ARCH=arm txlx_t962x_r311_2g.dtb - - +make ARCH=arm tm2_pxp.dtb diff --git a/scripts/amlogic/mk_dtb_gx.sh b/scripts/amlogic/mk_dtb_gx.sh index 1fc3549c688f..6c559867bf16 100755 --- a/scripts/amlogic/mk_dtb_gx.sh +++ b/scripts/amlogic/mk_dtb_gx.sh @@ -45,3 +45,5 @@ make ARCH=arm64 g12b_pxp.dtb || echo "Compile dtb Fail!!" make ARCH=arm64 g12b_a311d_skt.dtb || echo "Compile dtb Fail!!" make ARCH=arm64 g12b_a311d_w400.dtb || echo "Compile dtb Fail!!" + +make ARCH=arm64 tm2_pxp.dtb || echo "Compile dtb Fail!!" From 231ec6e3e6db7479cb3f2f16f66b90ff8e12612c Mon Sep 17 00:00:00 2001 From: shanghai engineers Date: Sun, 24 Mar 2019 22:11:00 -0400 Subject: [PATCH 0372/1060] TM2: add chip id and name for tm2 [1/1] PD#SWPL-6157 Problem: TM2 bring up need to update chip version name and id Solution: add the chipid and chip version name at dts and help file Verify: on ptm board4 Change-Id: I37e44828db1821c7fd2921c3e4271a27bd715b88 Signed-off-by: pan yang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 3 +++ arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 3 +++ .../amlogic/media/common/arch/registers/register_ops_m8.c | 2 ++ include/linux/amlogic/cpu_version.h | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 7204b77c2d95..0ff7ebf142ca 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1424,6 +1424,9 @@ mem_size = <0 0x100000>; status = "okay"; }; + cpu_ver_name { + compatible = "amlogic, cpu-major-id-tm2"; + }; }; /* end of / */ &pinctrl_aobus { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index b9736ffded44..356d18193404 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1404,6 +1404,9 @@ mem_size = <0 0x100000>; status = "okay"; }; + cpu_ver_name { + compatible = "amlogic, cpu-major-id-tm2"; + }; }; /* end of / */ &pinctrl_aobus { diff --git a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c index d8372c8a4eb6..4f7e1a2ba3ca 100644 --- a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c +++ b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c @@ -33,6 +33,7 @@ MESON_CPU_MAJOR_ID_G12B, \ MESON_CPU_MAJOR_ID_TL1, \ MESON_CPU_MAJOR_ID_SM1, \ + MESON_CPU_MAJOR_ID_TM2, \ 0} #define REGISTER_FOR_GXCPU {\ MESON_CPU_MAJOR_ID_GXBB, \ @@ -46,6 +47,7 @@ MESON_CPU_MAJOR_ID_G12B, \ MESON_CPU_MAJOR_ID_TL1, \ MESON_CPU_MAJOR_ID_SM1, \ + MESON_CPU_MAJOR_ID_TM2, \ 0} int codec_apb_read(unsigned int reg) { diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index 0d2244c824ac..4cef9e0bf195 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -37,6 +37,7 @@ #define MESON_CPU_MAJOR_ID_SM1 0x2B #define MESON_CPU_MAJOR_ID_TL1 0x2E +#define MESON_CPU_MAJOR_ID_TM2 0x2F #define MESON_CPU_VERSION_LVL_MAJOR 0 #define MESON_CPU_VERSION_LVL_MINOR 1 @@ -198,6 +199,10 @@ static inline bool is_meson_sm1_cpu(void) { return get_cpu_type() == MESON_CPU_MAJOR_ID_SM1; } +static inline bool is_meson_tm2_cpu(void) +{ + return get_cpu_type() == MESON_CPU_MAJOR_ID_TM2; +} static inline bool cpu_after_eq(unsigned int id) { From b7faeaaab28e411778cf679598be12831f2648f6 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Sat, 30 Mar 2019 16:25:15 +0800 Subject: [PATCH 0373/1060] dts: tm2: add ge2d support [1/1] PD#SWPL-6552 Problem: add ge2d support Solution: add ge2d support Verify: verified on TM2 skt board Change-Id: Idba0f97ea1596a4f579530fb86829f5ede307e52 Signed-off-by: Jian Cao --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 0ff7ebf142ca..179d5a6b8715 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1323,7 +1323,7 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 356d18193404..540dcc6e5795 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1303,7 +1303,7 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; From 8e8df3f8bc18736d5bc7b7916bf335c64181bd51 Mon Sep 17 00:00:00 2001 From: "pan.yang" Date: Sat, 30 Mar 2019 04:56:49 -0400 Subject: [PATCH 0374/1060] tm2: change tm2 mailbox dts config [1/1] PD#SWPL-5639 Problem: tm2 mailbox config has been changed Solution: change tm2 mailbox dts config Verify: tm2_skt Change-Id: I1e3fb569464826304f46276668ed359ad5cc2718 Signed-off-by: pan yang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 179d5a6b8715..b82cc24859ab 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -200,10 +200,10 @@ }; mailbox: mhu@ff63c400 { - status = "disabled"; + status = "okay"; compatible = "amlogic, meson_mhu"; reg = <0xff63c400 0x4c>, /* MHU registers */ - <0xfffd7000 0x800>; /* Payload area */ + <0xfffdf000 0x800>; /* Payload area */ interrupts = <0 209 1>, /* low priority interrupt */ <0 210 1>; /* high priority interrupt */ #mbox-cells = <1>; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 540dcc6e5795..07551b2106a9 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -189,10 +189,10 @@ }; mailbox: mhu@ff63c400 { - status = "disabled"; + status = "okay"; compatible = "amlogic, meson_mhu"; reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ - <0x0 0xfffd7000 0x0 0x800>; /* Payload area */ + <0x0 0xfffdf000 0x0 0x800>; /* Payload area */ interrupts = <0 209 1>, /* low priority interrupt */ <0 210 1>; /* high priority interrupt */ #mbox-cells = <1>; From ab64bfa44959469062ce661216566f9ee90f7f1a Mon Sep 17 00:00:00 2001 From: "pan.yang" Date: Sat, 30 Mar 2019 07:28:52 -0400 Subject: [PATCH 0375/1060] power: tm2: add power control dts config [1/1] PD#SWPL-5648 Problem: need power control dts Solution: add power control dts Verify: tm2_skt Change-Id: Ia677567dec5bb9ca8ea0cf067d8885d3005d32c2 Signed-off-by: pan yang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 6 ++++++ arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index b82cc24859ab..0f6676fbfaaf 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -585,6 +585,12 @@ quality = /bits/ 16 <1000>; }; + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0xff8000e8 0x10>, + <0xff63c100 0x10>; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 07551b2106a9..1bfec960a99d 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -566,6 +566,12 @@ quality = /bits/ 16 <1000>; }; + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0x0 0xff8000e8 0x0 0x10>, + <0x0 0xff63c100 0x0 0x10>; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; From b9cc2bdfa24b5f116f370d978a6bcef9cdb82930 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Sun, 31 Mar 2019 12:58:33 +0800 Subject: [PATCH 0376/1060] dts: add t962ex_ab311 319 and t962x3_a309 [1/1] PD#SWPL-6559 Problem: Need more DTB support Solution: add ab311 ab319 and ab309 ab311 is from tl1_x301 ab319 and ab309 are from tl1_skt Verify: Build pass Change-Id: Ie8a8bec03107d4c4d0328dcd8deab916bd7f63f2 Signed-off-by: Jianxin Pan --- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 1915 +++++++++++++++++ .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 1791 +++++++++++++++ .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 1791 +++++++++++++++ .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 1874 ++++++++++++++++ .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 1790 +++++++++++++++ .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 1790 +++++++++++++++ 6 files changed, 10951 insertions(+) create mode 100644 arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts create mode 100644 arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts create mode 100644 arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts create mode 100644 arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts create mode 100644 arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts create mode 100644 arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts new file mode 100644 index 000000000000..9a11a67ba788 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -0,0 +1,1915 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB311"; + amlogic-dt-id = "tm2_t962e2_ab311"; + compatible = "amlogic, tm2_t962e2_ab311"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts new file mode 100644 index 000000000000..4e951cc2ad93 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -0,0 +1,1791 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_skt-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB319"; + amlogic-dt-id = "tm2_t962e2_ab319"; + compatible = "amlogic, tm2_t962e2_ab319"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <699000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <699000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <709000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <719000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <729000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <749000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <769000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <779000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <789000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <829000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <879000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <929000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; +#if 0 //verify tdm/i2s in + tdmin_a: tdmin_a { + mux { /* GPIOZ_7 */ + groups = "tdma_din0_z"; + function = "tdma_in"; + }; + }; +#endif + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts new file mode 100644 index 000000000000..ffeef0da7d1b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -0,0 +1,1791 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_skt-panel.dtsi" + +/ { + model = "Amlogic TM2 T962X3 AB309"; + amlogic-dt-id = "tm2_t962x3_ab309"; + compatible = "amlogic, tm2_t962x3_ab309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <699000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <699000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <709000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <719000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <729000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <749000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <769000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <779000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <789000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <829000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <879000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <929000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; +#if 0 //verify tdm/i2s in + tdmin_a: tdmin_a { + mux { /* GPIOZ_7 */ + groups = "tdma_din0_z"; + function = "tdma_in"; + }; + }; +#endif + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts new file mode 100644 index 000000000000..429fcac19a36 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -0,0 +1,1874 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB311"; + amlogic-dt-id = "tm2_t962E2_ab311"; + compatible = "amlogic, tm2_t962e2_ab311"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts new file mode 100644 index 000000000000..6ce2ebefd940 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -0,0 +1,1790 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_skt-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB319"; + amlogic-dt-id = "tm2_t962e2_ab319"; + compatible = "amlogic, tm2_t962e2_ab319"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + alloc-ranges = <0x0 0x30000000 0x0 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <699000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <699000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <709000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <719000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <729000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <749000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <769000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <779000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <789000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <829000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <879000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <929000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; +#if 0 //verify tdm/i2s in + tdmin_a: tdmin_a { + mux { /* GPIOZ_7 */ + groups = "tdma_din0_z"; + function = "tdma_in"; + }; + }; +#endif + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x0 0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x0 0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x0 0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x0 0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x0 0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts new file mode 100644 index 000000000000..95785a798157 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -0,0 +1,1790 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_skt-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB319"; + amlogic-dt-id = "tm2_t962x3_ab309"; + compatible = "amlogic, tm2_t962x3_ab309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + alloc-ranges = <0x0 0x30000000 0x0 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <699000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <699000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <709000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <719000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <729000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <749000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <769000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <779000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <789000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <829000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <879000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <929000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; +#if 0 //verify tdm/i2s in + tdmin_a: tdmin_a { + mux { /* GPIOZ_7 */ + groups = "tdma_din0_z"; + function = "tdma_in"; + }; + }; +#endif + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x0 0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x0 0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x0 0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x0 0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x0 0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; From d2e30a37785cf5d110526b8d051a4e31ebd25346 Mon Sep 17 00:00:00 2001 From: "pan.yang" Date: Sun, 31 Mar 2019 05:48:17 -0400 Subject: [PATCH 0377/1060] dts: modified t962ex_ab311 319 and t962x3_a309,pxp dts [1/1] PD#SWPL-6560 Problem: Need to change dts Solution: modified ab311 ab319 and ab309 and pxp Verify: test pass at skt_tm2 Change-Id: Iabc21582910f66b321b55928ce86d0958cb83503 Signed-off-by: pan yang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm/boot/dts/amlogic/tm2_pxp.dts | 4 ++-- arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 3 +-- arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 3 +-- arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 3 +-- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 4 ++-- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts | 3 +-- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts | 3 +-- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts | 3 +-- 10 files changed, 12 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 0f6676fbfaaf..8b879d091793 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -937,7 +937,7 @@ ion_dev { compatible = "amlogic, ion_dev"; - status = "disabled"; + status = "okay"; memory-region = <&ion_cma_reserved>; };/* end of ion_dev*/ }; /* end of soc*/ diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts index 25010e7c12a6..f6c072b915e5 100644 --- a/arch/arm/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -37,7 +37,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; + linux,usable-memory = <0x000000 0x80000000>; }; reserved-memory { @@ -76,7 +76,7 @@ reusable; size = <0x800000>; alignment = <0x400000>; - alloc-ranges = <0x3f800000 0x800000>; + alloc-ranges = <0x7f800000 0x800000>; }; ion_cma_reserved:linux,ion-dev { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 9a11a67ba788..6f69409c4409 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -19,7 +19,6 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesontl1_x301-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB311"; @@ -1154,7 +1153,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; tuner: tuner { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 4e951cc2ad93..65240dd8d6f8 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -19,7 +19,6 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesontl1_skt-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB319"; @@ -1126,7 +1125,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; tuner: tuner { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index ffeef0da7d1b..aece55735943 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -19,7 +19,6 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesontl1_skt-panel.dtsi" / { model = "Amlogic TM2 T962X3 AB309"; @@ -1126,7 +1125,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 1bfec960a99d..5aeabac2367f 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -917,7 +917,7 @@ ion_dev { compatible = "amlogic, ion_dev"; - status = "disabled"; + status = "okay"; memory-region = <&ion_cma_reserved>; };/* end of ion_dev*/ }; /* end of soc*/ diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts index 5a7bd66c7f80..07e24aeb6373 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -37,7 +37,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -75,7 +75,7 @@ reusable; size = <0x0 0x800000>; alignment = <0x0 0x400000>; - alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; }; ion_cma_reserved:linux,ion-dev { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 429fcac19a36..c6163e38ea42 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -19,7 +19,6 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesontl1_x301-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB311"; @@ -1149,7 +1148,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 6ce2ebefd940..375bb3826912 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -19,7 +19,6 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesontl1_skt-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB319"; @@ -1125,7 +1124,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 95785a798157..d4bcc4dfe557 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -19,7 +19,6 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" -#include "mesontl1_skt-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB319"; @@ -1125,7 +1124,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "okay"; + status = "disabled"; }; tuner: tuner { From 84793b0b4be752c85614278ccd9a285d03ba17d8 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Mon, 1 Apr 2019 11:37:50 +0800 Subject: [PATCH 0378/1060] usb: bringup TM2 usb [1/1] PD#SWPL-5609 Problem: bringup TM2 usb. Solution: bringup TM2 usb. Verify: TM2 Change-Id: I61f388a516442064af5b21f4688f6787e9e358e9 Signed-off-by: Yue Wang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 17 ++++++++++++++--- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 8b879d091793..8ddd3b542f64 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -435,18 +435,29 @@ pll-setting-6 = <0x78000>; pll-setting-7 = <0xe0004>; pll-setting-8 = <0xe000c>; - version = <1>; + version = <2>; + pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; }; usb3_phy_v2: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3-v2"; - status = "disabled"; - reg = <0xffe09080 0x20>; + status = "disable"; + reg = <0xffe09080 0x20 + 0xffd01008 0x100>; phy-reg = <0xff646000>; phy-reg-size = <0x2000>; usb2-phy-reg = <0xffe09000>; usb2-phy-reg-size = <0x80>; interrupts = <0 16 4>; + pwr-ctl = <1>; + u3-ctrl-sleep-shift = <18>; + u3-hhi-mem-pd-shift = <26>; + u3-hhi-mem-pd-mask = <0xf>; + u3-ctrl-iso-shift = <18>; }; dwc2_a: dwc2_a@ff400000 { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 5aeabac2367f..bda1626c7403 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -416,18 +416,29 @@ pll-setting-6 = <0x78000>; pll-setting-7 = <0xe0004>; pll-setting-8 = <0xe000c>; - version = <1>; + version = <2>; + pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; }; usb3_phy_v2: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3-v2"; - status = "disabled"; - reg = <0x0 0xffe09080 0x0 0x20>; + status = "disable"; + reg = <0x0 0xffe09080 0x0 0x20 + 0x0 0xffd01008 0x0 0x100>; phy-reg = <0xff646000>; phy-reg-size = <0x2000>; usb2-phy-reg = <0xffe09000>; usb2-phy-reg-size = <0x80>; interrupts = <0 16 4>; + pwr-ctl = <1>; + u3-ctrl-sleep-shift = <18>; + u3-hhi-mem-pd-shift = <26>; + u3-hhi-mem-pd-mask = <0xf>; + u3-ctrl-iso-shift = <18>; }; dwc2_a: dwc2_a@ff400000 { From 28597e230b4bb6822bc5d21e274cc06903a42620 Mon Sep 17 00:00:00 2001 From: "ruixuan.li" Date: Mon, 1 Apr 2019 14:12:07 +0800 Subject: [PATCH 0379/1060] tm2: make emmc run high speed [1/1] PD#SWPL-5658 Problem: emmc run hs200 report cmd18 rx data crc Solution: emmc run high speed first Verify: passed on t962e2_ab319 Change-Id: Iaeef33e38f7c5130ebfd0e7c5886459b8138a803 Signed-off-by: ruixuan.li --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 4 +-- arch/arm/boot/dts/amlogic/tm2_pxp.dts | 2 +- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 4 +-- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 6 ++--- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 4 +-- arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 2 +- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 4 +-- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 9 +++---- drivers/amlogic/mmc/aml_sd_emmc.c | 27 +++++++++++++++++++ include/linux/amlogic/sd.h | 1 + 10 files changed, 45 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 8ddd3b542f64..dbaa3505ccee 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1148,7 +1148,7 @@ sd_emmc_c: emmc@ffe07000 { status = "disabled"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0xffe07000 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; @@ -1157,7 +1157,7 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&clkc CLKID_GP0_PLL>, <&xtal>; clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts index f6c072b915e5..8ffbf10b64ca 100644 --- a/arch/arm/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -1003,7 +1003,7 @@ }; /* end of pinctrl_aobus */ &sd_emmc_b { - status = "disabled"; + status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 6f69409c4409..3d7c79dba1e1 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1733,9 +1733,9 @@ "MMC_CAP_ERASE", "MMC_CAP_CMD23", "MMC_CAP_DRIVER_TYPE_D"; - caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + //caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; - f_max = <198000000>; + f_max = <50000000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 65240dd8d6f8..6646cee796b3 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1614,14 +1614,14 @@ "MMC_CAP_MMC_HIGHSPEED", "MMC_CAP_SD_HIGHSPEED", "MMC_CAP_NONREMOVABLE", - "MMC_CAP_1_8V_DDR", + /*"MMC_CAP_1_8V_DDR",*/ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; + //caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <200000000>; + f_max = <50000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index bda1626c7403..30afcf8e78a0 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1128,7 +1128,7 @@ sd_emmc_c: emmc@ffe07000 { status = "disabled"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0x0 0xffe07000 0x0 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; @@ -1137,7 +1137,7 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&clkc CLKID_GP0_PLL>, <&xtal>; clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts index 07e24aeb6373..233ef245dcb5 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -998,7 +998,7 @@ }; /* end of pinctrl_aobus */ &sd_emmc_b { - status = "disabled"; + status = "okay"; sd { caps = "MMC_CAP_4_BIT_DATA", "MMC_CAP_MMC_HIGHSPEED", diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index c6163e38ea42..6c68b868d69b 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1692,9 +1692,9 @@ "MMC_CAP_ERASE", "MMC_CAP_CMD23", "MMC_CAP_DRIVER_TYPE_D"; - caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + //caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <198000000>; + f_max = <50000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 375bb3826912..26ef579d9d4a 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1160,7 +1160,7 @@ sd_emmc_b: sd@ffe05000 { status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0x0 0xffe05000 0x0 0x800>; interrupts = <0 190 1>; @@ -1613,14 +1613,13 @@ "MMC_CAP_MMC_HIGHSPEED", "MMC_CAP_SD_HIGHSPEED", "MMC_CAP_NONREMOVABLE", - "MMC_CAP_1_8V_DDR", + /*"MMC_CAP_1_8V_DDR",*/ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + /*caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <200000000>; + f_max = <50000000>; }; }; diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index fdbd53170c49..c623bd291a0f 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3668,6 +3668,29 @@ static struct meson_mmc_data mmc_data_sm1 = { .sdmmc.sdr104.core_phase = 2, .sdmmc.sdr104.tx_phase = 0, }; + +static struct meson_mmc_data mmc_data_tm2 = { + .chip_type = MMC_CHIP_TM2, + .port_a_base = 0xffe03000, + .port_b_base = 0xffe05000, + .port_c_base = 0xffe07000, + .pinmux_base = 0xff634400, + .clksrc_base = 0xff63c000, + .ds_pin_poll = 0x3a, + .ds_pin_poll_en = 0x48, + .ds_pin_poll_bit = 13, + .sdmmc.init.core_phase = 3, + .sdmmc.init.tx_phase = 0, + .sdmmc.init.rx_phase = 0, + .sdmmc.hs.core_phase = 3, + .sdmmc.ddr.core_phase = 2, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, + .sdmmc.sd_hs.core_phase = 2, + .sdmmc.sdr104.core_phase = 2, +}; + static const struct of_device_id meson_mmc_of_match[] = { { .compatible = "amlogic, meson-mmc-gxbb", @@ -3725,6 +3748,10 @@ static const struct of_device_id meson_mmc_of_match[] = { .compatible = "amlogic, meson-mmc-sm1", .data = &mmc_data_sm1, }, + { + .compatible = "amlogic, meson-mmc-tm2", + .data = &mmc_data_tm2, + }, {} }; diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index bcd815bb69b2..99e8c86b6faa 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -193,6 +193,7 @@ enum mmc_chip_e { MMC_CHIP_TL1 = 0X2b, MMC_CHIP_G12B = 0x29b, MMC_CHIP_SM1 = 0X2C, + MMC_CHIP_TM2 = 0X2D, }; struct mmc_phase { From cc554d4733095479022cb1571f5e17e904e69396 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 29 Mar 2019 15:53:06 +0800 Subject: [PATCH 0380/1060] vpu: add tm2 support [1/1] PD#SWPL-6397 Problem: tm2 is a new chip Solution: add vpu driver support for tm2 Verify: pxp Change-Id: I19275c513b68fba8feced37f1ff8fca9bf48d395 Signed-off-by: Evoke Zhang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 2 +- drivers/amlogic/media/common/vpu/vpu.c | 45 ++++++++++- drivers/amlogic/media/common/vpu/vpu.h | 2 + drivers/amlogic/media/common/vpu/vpu_ctrl.h | 71 ++++++++++++++++- drivers/amlogic/media/common/vpu/vpu_module.h | 3 + .../amlogic/media/common/vpu/vpu_power_init.c | 77 ++++++++++++++----- include/linux/amlogic/media/vpu/vpu.h | 5 +- 8 files changed, 179 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index dbaa3505ccee..466408d64c18 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -297,7 +297,7 @@ }; vpu { - compatible = "amlogic, vpu-tl1"; + compatible = "amlogic, vpu-tm2"; status = "okay"; clocks = <&clkc CLKID_VAPB_MUX>, <&clkc CLKID_VPU_INTR>, diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 30afcf8e78a0..1e19b5dc0369 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -278,7 +278,7 @@ }; vpu { - compatible = "amlogic, vpu-tl1"; + compatible = "amlogic, vpu-tm2"; status = "okay"; clocks = <&clkc CLKID_VAPB_MUX>, <&clkc CLKID_VPU_INTR>, diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index a1dbda03bfe5..8524fc83911d 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -40,7 +40,8 @@ /* v05: add txl support */ /* v20180925: add tl1 support */ /* v20190314: add sm1 support */ -#define VPU_VERION "v20190314" +/* v20190329: add tm2 support */ +#define VPU_VERION "v20190329" int vpu_debug_print_flag; static spinlock_t vpu_mem_lock; @@ -1256,6 +1257,7 @@ static struct vpu_data_s vpu_data_gxb = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1282,6 +1284,7 @@ static struct vpu_data_s vpu_data_gxtvbb = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1308,6 +1311,7 @@ static struct vpu_data_s vpu_data_gxl = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1335,6 +1339,7 @@ static struct vpu_data_s vpu_data_gxm = { .module_init_table_cnt = sizeof(vpu_module_init_gxm) / sizeof(struct vpu_ctrl_s), .module_init_table = vpu_module_init_gxm, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1361,6 +1366,7 @@ static struct vpu_data_s vpu_data_txl = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1388,6 +1394,7 @@ static struct vpu_data_s vpu_data_txlx = { .module_init_table_cnt = sizeof(vpu_module_init_txlx) / sizeof(struct vpu_ctrl_s), .module_init_table = vpu_module_init_txlx, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1414,6 +1421,7 @@ static struct vpu_data_s vpu_data_axg = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1440,6 +1448,7 @@ static struct vpu_data_s vpu_data_g12a = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1466,6 +1475,7 @@ static struct vpu_data_s vpu_data_g12b = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1492,6 +1502,7 @@ static struct vpu_data_s vpu_data_tl1 = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_tl1, }; @@ -1518,10 +1529,38 @@ static struct vpu_data_s vpu_data_sm1 = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, .hdmi_iso_table = vpu_hdmi_iso_sm1, .reset_table = vpu_reset_txlx, }; +static struct vpu_data_s vpu_data_tm2 = { + .chip_type = VPU_CHIP_TM2, + .chip_name = "tm2", + .clk_level_dft = CLK_LEVEL_DFT_G12A, + .clk_level_max = CLK_LEVEL_MAX_G12A, + .fclk_div_table = fclk_div_table_g12a, + + .gp_pll_valid = 0, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 1, + .mem_pd_reg3_valid = 1, + .mem_pd_reg4_valid = 1, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_tm2) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_g12a) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_tm2, + .clk_gate_table = vpu_clk_gate_g12a, + + .module_init_table_cnt = 0, + .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_sm1, + .reset_table = vpu_reset_tl1, +}; + static const struct of_device_id vpu_of_table[] = { { .compatible = "amlogic, vpu-gxbb", @@ -1567,6 +1606,10 @@ static const struct of_device_id vpu_of_table[] = { .compatible = "amlogic, vpu-sm1", .data = &vpu_data_sm1, }, + { + .compatible = "amlogic, vpu-tm2", + .data = &vpu_data_tm2, + }, {}, }; diff --git a/drivers/amlogic/media/common/vpu/vpu.h b/drivers/amlogic/media/common/vpu/vpu.h index b0f1d86fa2f4..b3a50088f1e7 100644 --- a/drivers/amlogic/media/common/vpu/vpu.h +++ b/drivers/amlogic/media/common/vpu/vpu.h @@ -37,6 +37,7 @@ enum vpu_chip_e { VPU_CHIP_G12B, VPU_CHIP_TL1, VPU_CHIP_SM1, + VPU_CHIP_TM2, VPU_CHIP_MAX, }; @@ -89,6 +90,7 @@ struct vpu_data_s { unsigned int module_init_table_cnt; struct vpu_ctrl_s *module_init_table; + struct vpu_ctrl_s *hdmi_iso_pre_table; struct vpu_ctrl_s *hdmi_iso_table; struct vpu_reset_s *reset_table; }; diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h index 10302e9a9845..30e39dcb3605 100644 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.h +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -379,7 +379,7 @@ static struct vpu_ctrl_s vpu_mem_pd_tl1[] = { {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, - {VPU_LS_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LC_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, @@ -434,7 +434,7 @@ static struct vpu_ctrl_s vpu_mem_pd_sm1[] = { {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, - {VPU_LS_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LC_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, @@ -449,7 +449,7 @@ static struct vpu_ctrl_s vpu_mem_pd_sm1[] = { {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, {VPU_VIU2, HHI_VPU_MEM_PD_REG2, 0x3, 22, 2}, - {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0x3, 24, 2}, {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, {VPU_TCON, HHI_VPU_MEM_PD_REG3_SM1, 0x3, 0, 16}, {VPU_TCON, HHI_VPU_MEM_PD_REG3_SM1, 0x3, 16, 16}, @@ -458,6 +458,62 @@ static struct vpu_ctrl_s vpu_mem_pd_sm1[] = { {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, }; +static struct vpu_ctrl_s vpu_mem_pd_tm2[] = { + /* vpu module, reg, val, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0x3, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 0x3, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 0x3, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 0x3, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 0x3, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 0x3, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 0x3, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 0x3, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 0x3, 20, 2}, + {VPU_AFBC_DEC1, HHI_VPU_MEM_PD_REG0, 0x3, 22, 2}, + {VPU_VIU_DI_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 24, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 0x3, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 0x3, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 0x3, 30, 2}, + {VPU_VIU2, HHI_VPU_MEM_PD_REG1, 0xf, 0, 4}, + {VPU_VKSTONE, HHI_VPU_MEM_PD_REG1, 0x3, 4, 2}, + {VPU_DOLBY_CORE3, HHI_VPU_MEM_PD_REG1, 0x3, 6, 2}, + {VPU_DOLBY0, HHI_VPU_MEM_PD_REG1, 0x3, 8, 2}, + {VPU_DOLBY1A, HHI_VPU_MEM_PD_REG1, 0x3, 10, 2}, + {VPU_DOLBY1B, HHI_VPU_MEM_PD_REG1, 0x3, 12, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 0x3, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 0x3, 16, 2}, + {VPU_VD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 18, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, + {VPU_LC_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, + {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, + {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG2, 0x3, 2, 2}, + {VPU_VIU_OSD3, HHI_VPU_MEM_PD_REG2, 0x3, 4, 2}, + {VPU_VIU_OSD4, HHI_VPU_MEM_PD_REG2, 0x3, 6, 2}, + {VPU_MAIL_AFBCD, HHI_VPU_MEM_PD_REG2, 0x3, 8, 2}, + {VPU_VD1_SCALE, HHI_VPU_MEM_PD_REG2, 0x3, 10, 2}, + {VPU_OSD_BLD34, HHI_VPU_MEM_PD_REG2, 0x3, 12, 2}, + {VPU_PRIME_DOLBY_RAM, HHI_VPU_MEM_PD_REG2, 0x3, 14, 2}, + {VPU_VD2_OFIFO, HHI_VPU_MEM_PD_REG2, 0x3, 16, 2}, + {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, + {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0x3, 24, 2}, + {VPU_DOLBY_S0, HHI_VPU_MEM_PD_REG2, 0x3, 26, 2}, + {VPU_DOLBY_S1, HHI_VPU_MEM_PD_REG2, 0x3, 28, 2}, + {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 0, 16}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, + {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4, 0x3, 0, 2}, + {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4, 0x3, 2, 2}, + {VPU_DMA, HHI_VPU_MEM_PD_REG4, 0xf, 4, 4}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, +}; + /* ******************************************************* */ /* VPU clock gate table */ /* ******************************************************* */ @@ -632,6 +688,15 @@ static struct vpu_ctrl_s vpu_clk_gate_g12a[] = { {VPU_MAX, VPU_REG_END, 0, 0, 0}, }; +/* ******************************************************* */ +/* VPU_HDMI ISO pre: before reset */ +/* ******************************************************* */ +static struct vpu_ctrl_s vpu_hdmi_iso_pre_gxb[] = { + /* reg, val, bit, len */ + {AO_RTI_GEN_PWR_SLEEP0, 1, 8, 1}, + {VPU_REG_END, 0, 0, 0}, +}; + /* ******************************************************* */ /* VPU_HDMI ISO */ /* ******************************************************* */ diff --git a/drivers/amlogic/media/common/vpu/vpu_module.h b/drivers/amlogic/media/common/vpu/vpu_module.h index 0e089f47c80b..72e1b4fa7c56 100644 --- a/drivers/amlogic/media/common/vpu/vpu_module.h +++ b/drivers/amlogic/media/common/vpu/vpu_module.h @@ -78,11 +78,14 @@ static char *vpu_mod_table[] = { "ds", "lut3d", "viu2_osd_rotation", + "dolby_s0", + "dolby_s1", "rdma", "axi_wr1", "axi_wr0", "afbce", + "dma" "vpu_mod_max", diff --git a/drivers/amlogic/media/common/vpu/vpu_power_init.c b/drivers/amlogic/media/common/vpu/vpu_power_init.c index 21ccce7f6c9e..35384e0d6934 100644 --- a/drivers/amlogic/media/common/vpu/vpu_power_init.c +++ b/drivers/amlogic/media/common/vpu/vpu_power_init.c @@ -44,6 +44,7 @@ void vpu_module_init_config(void) cnt = vpu_conf.data->module_init_table_cnt; ctrl_table = vpu_conf.data->module_init_table; if (ctrl_table) { + i = 0; while (i < cnt) { if (ctrl_table[i].reg == VPU_REG_END) break; @@ -71,17 +72,32 @@ void vpu_power_on(void) { struct vpu_ctrl_s *ctrl_table; struct vpu_reset_s *reset_table; - unsigned int _reg, _bit, _len, mask; + unsigned int _reg, _val, _bit, _len, mask; int i = 0, cnt; VPUPR("vpu_power_on\n"); - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 0, 8, 1); /* [8] power on */ + /* power on VPU_HDMI ISO */ + ctrl_table = vpu_conf.data->hdmi_iso_pre_table; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = 0; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } + } udelay(20); /* power up memories */ cnt = vpu_conf.data->mem_pd_table_cnt; ctrl_table = vpu_conf.data->mem_pd_table; + i = 0; while (i < cnt) { if (ctrl_table[i].vmod == VPU_MOD_MAX) break; @@ -125,15 +141,18 @@ void vpu_power_on(void) /* Remove VPU_HDMI ISO */ ctrl_table = vpu_conf.data->hdmi_iso_table; - i = 0; - while (i < VPU_HDMI_ISO_CNT_MAX) { - if (ctrl_table[i].reg == VPU_REG_END) - break; - _reg = ctrl_table[i].reg; - _bit = ctrl_table[i].bit; - _len = ctrl_table[i].len; - vpu_ao_setb(_reg, 0, _bit, _len); - i++; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = 0; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } } if (vpu_debug_print_flag) @@ -151,15 +170,18 @@ void vpu_power_off(void) /* Power down VPU_HDMI */ /* Enable Isolation */ ctrl_table = vpu_conf.data->hdmi_iso_table; - while (i < VPU_HDMI_ISO_CNT_MAX) { - if (ctrl_table[i].reg == VPU_REG_END) - break; - _reg = ctrl_table[i].reg; - _val = ctrl_table[i].val; - _bit = ctrl_table[i].bit; - _len = ctrl_table[i].len; - vpu_ao_setb(_reg, _val, _bit, _len); - i++; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = ctrl_table[i].val; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } } udelay(20); @@ -188,7 +210,20 @@ void vpu_power_off(void) udelay(20); /* Power down VPU domain */ - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 1, 8, 1); /* PDN */ + ctrl_table = vpu_conf.data->hdmi_iso_pre_table; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = ctrl_table[i].val; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } + } vpu_hiu_setb(HHI_VAPBCLK_CNTL, 0, 8, 1); vpu_hiu_setb(HHI_VPU_CLK_CNTL, 0, 8, 1); diff --git a/include/linux/amlogic/media/vpu/vpu.h b/include/linux/amlogic/media/vpu/vpu.h index 3fa09153af76..067b0615d43f 100644 --- a/include/linux/amlogic/media/vpu/vpu.h +++ b/include/linux/amlogic/media/vpu/vpu.h @@ -60,7 +60,7 @@ enum vpu_mod_e { VPU_VENCP, /* reg1[21:20], common */ VPU_VENCL, /* reg1[23:22], common */ VPU_VENCI, /* reg1[25:24], common */ - VPU_LS_STTS, /* reg1[27:26], tl1 */ + VPU_LC_STTS, /* reg1[27:26], tl1 */ VPU_LDIM_STTS, /* reg1[29:28], GXTVBB, GXL, TXL, TXLX */ VPU_TV_DEC_CVD2, /* reg1[29:28] */ VPU_XVYCC_LUT, /* reg1[31:30], GXTVBB, GXL, TXL, TXLX */ @@ -78,11 +78,14 @@ enum vpu_mod_e { VPU_DS, /* reg2[19:18], TL1 */ VPU_LUT3D, /* reg2[21:20], G12B */ VPU_VIU2_OSD_ROT, /* reg2[23:22], G12B */ + VPU_DOLBY_S0, /* reg2[27:26], TM2 */ + VPU_DOLBY_S1, /* reg2[29:28], TM2 */ VPU_RDMA, /* reg2[31:30], G12A */ VPU_AXI_WR1, /* reg4[1:0], TL1 */ VPU_AXI_WR0, /* reg4[3:2], TL1 */ VPU_AFBCE, /* reg4[5:4], TL1 */ + VPU_DMA, /* reg4[7:4], TM2 */ VPU_MOD_MAX, From 9baaa45116b3b17f46a4c24aa3d889c44cadddcc Mon Sep 17 00:00:00 2001 From: Qianggui Song Date: Sat, 23 Mar 2019 12:05:54 +0800 Subject: [PATCH 0381/1060] irqchip: tm2 irqchip support [1/1] PD#SWPL-5651 Problem: tm2 has 2 extra pins than tl1, should use new param data Solution: add tm2 param data Verify: T962e2_ab319 Change-Id: I77aaaead7b10024cd5f12354ba6b47db74ba96f5 Signed-off-by: Qianggui Song --- .../interrupt-controller/amlogic,meson-gpio-intc.txt | 1 + arch/arm/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 2 +- drivers/amlogic/irqchip/irq-meson-gpio.c | 6 ++++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt index 3f305fdf4f94..ec06f877cc5c 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt @@ -20,6 +20,7 @@ Required properties: “amlogic,meson-txl-gpio-intc†for TXL SoCs (T950, T952, T960, T962) “amlogic,meson-tl1-gpio-intc†for TL1 SoCs (T962X2) “amlogic,meson-sm1-gpio-intc†for SM1 SoCs (S905D3, S905X3, S905Y3) + “amlogic,meson-tm2-gpio-intc†for TM2 SoCs (T962X3, T962E2) - interrupt-parent : a phandle to the GIC the interrupts are routed to. Usually this is provided at the root level of the device tree as it is common to most of the SoC. diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 466408d64c18..6bb46efc3ace 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -744,7 +744,7 @@ gpio_intc: interrupt-controller@f080 { compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-tl1-gpio-intc"; + "amlogic,meson-tm2-gpio-intc"; reg = <0xf080 0x10>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 1e19b5dc0369..4fead9a1d16b 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -726,7 +726,7 @@ gpio_intc: interrupt-controller@f080 { compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-tl1-gpio-intc"; + "amlogic,meson-tm2-gpio-intc"; reg = <0x0 0xf080 0x0 0x10>; interrupt-controller; #interrupt-cells = <2>; diff --git a/drivers/amlogic/irqchip/irq-meson-gpio.c b/drivers/amlogic/irqchip/irq-meson-gpio.c index d353df4abff9..b1d15049edfd 100644 --- a/drivers/amlogic/irqchip/irq-meson-gpio.c +++ b/drivers/amlogic/irqchip/irq-meson-gpio.c @@ -90,6 +90,11 @@ static const struct meson_gpio_irq_params sm1_params = { .support_double_edge = 1, }; +static const struct meson_gpio_irq_params tm2_params = { + .nr_hwirq = 104, + .support_double_edge = 1, +}; + static const struct of_device_id meson_irq_gpio_matches[] = { { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, @@ -101,6 +106,7 @@ static const struct of_device_id meson_irq_gpio_matches[] = { { .compatible = "amlogic,meson-txl-gpio-intc", .data = &txl_params }, { .compatible = "amlogic,meson-tl1-gpio-intc", .data = &tl1_params }, { .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params }, + { .compatible = "amlogic,meson-tm2-gpio-intc", .data = &tm2_params }, { } }; From 1a5b3c1941f13832c6590f6ddd09b9693d5ea5d4 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Sat, 30 Mar 2019 19:25:18 +0800 Subject: [PATCH 0382/1060] osd: add osd TM2 support [1/1] PD#SWPL-6558 Problem: bring up osd for TM2 Solution: osd: add osd TM2 support Verify: Verfied on TM2 skt board Change-Id: I2183bd1f60793baf947c303b6d456e8c69d104ac Signed-off-by: Jian Cao --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm/boot/dts/amlogic/tm2_pxp.dts | 18 +++++++++--------- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 2 +- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 2 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 2 +- arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 18 +++++++++--------- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 2 +- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 2 +- drivers/amlogic/media/osd/osd.h | 1 + drivers/amlogic/media/osd/osd_fb.c | 19 +++++++++++++++++++ drivers/amlogic/media/osd/osd_hw.c | 4 ++-- 13 files changed, 48 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 6bb46efc3ace..8ff6e7d46338 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1322,7 +1322,7 @@ }; meson_fb: fb { - compatible = "amlogic, meson-tl1"; + compatible = "amlogic, meson-tm2"; memory-region = <&logo_reserved>; status = "disabled"; interrupts = <0 3 1 diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts index 8ffbf10b64ca..fe88d70c238b 100644 --- a/arch/arm/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -63,14 +63,6 @@ /*alloc-ranges = <0x30000000 0x50000000>;*/ }; - /* codec shared reserved */ - codec_mm_reserved:linux,codec_mm_reserved { - compatible = "amlogic, codec-mm-reserved"; - size = <0x0>; - alignment = <0x100000>; - //no-map; - }; - logo_reserved:linux,meson-fb { compatible = "shared-dma-pool"; reusable; @@ -79,6 +71,14 @@ alloc-ranges = <0x7f800000 0x800000>; }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; @@ -1119,7 +1119,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <1>; pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 3d7c79dba1e1..ec8f5fb941c0 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1859,7 +1859,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <0>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 6646cee796b3..8dc663deca00 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1743,7 +1743,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <0>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index aece55735943..b764d9ed82a1 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1743,7 +1743,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <0>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 4fead9a1d16b..b4f593c3a19a 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1302,7 +1302,7 @@ }; meson_fb: fb { - compatible = "amlogic, meson-tl1"; + compatible = "amlogic, meson-tm2"; memory-region = <&logo_reserved>; status = "disabled"; interrupts = <0 3 1 diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts index 233ef245dcb5..0b22d1e7799c 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -53,6 +53,14 @@ alloc-ranges = <0x0 0x05000000 0x0 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -70,14 +78,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x800000>; - alignment = <0x0 0x400000>; - alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; @@ -1114,7 +1114,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <1>; pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 6c68b868d69b..f5384358b542 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1818,7 +1818,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <0>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 26ef579d9d4a..4f37ef684215 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1741,7 +1741,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <0>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index d4bcc4dfe557..50e84332e91e 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1742,7 +1742,7 @@ &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; - mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; logo_addr = "0x7f800000"; mem_alloc = <0>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index bead47117592..8003c5183305 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -278,6 +278,7 @@ enum cpuid_type_e { __MESON_CPU_MAJOR_ID_G12B, __MESON_CPU_MAJOR_ID_TL1, __MESON_CPU_MAJOR_ID_SM1, + __MESON_CPU_MAJOR_ID_TM2, __MESON_CPU_MAJOR_ID_UNKNOWN, }; diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index 724cf8ecf064..666e462a1479 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -4080,6 +4080,21 @@ static struct osd_device_data_s osd_tl1 = { .has_viu2 = 1, }; +static struct osd_device_data_s osd_tm2 = { + .cpu_id = __MESON_CPU_MAJOR_ID_TM2, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, +}; + static struct osd_device_data_s osd_sm1 = { .cpu_id = __MESON_CPU_MAJOR_ID_SM1, .osd_ver = OSD_HIGH_ONE, @@ -4145,6 +4160,10 @@ static const struct of_device_id meson_fb_dt_match[] = { .compatible = "amlogic, meson-sm1", .data = &osd_sm1, }, + { + .compatible = "amlogic, meson-tm2", + .data = &osd_tm2, + }, {}, }; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 15fad4f1409c..3222e58b6dbb 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1667,6 +1667,7 @@ static u32 osd_get_hw_reset_flag(void) case __MESON_CPU_MAJOR_ID_G12B: case __MESON_CPU_MAJOR_ID_TL1: case __MESON_CPU_MAJOR_ID_SM1: + case __MESON_CPU_MAJOR_ID_TM2: { int i, afbc_enable = 0; @@ -5040,8 +5041,7 @@ static void osd_update_disp_osd_rotate(u32 index) const struct vinfo_s *vinfo; int out_y_crop_start, out_y_crop_end; - if (osd_hw.osd_meson_dev.cpu_id < __MESON_CPU_MAJOR_ID_G12B || - osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_SM1) + if (osd_hw.osd_meson_dev.cpu_id != __MESON_CPU_MAJOR_ID_G12B) return; src_fmt = get_viu2_src_format(); src_data.x = 0; From 2f3d65b83a4ef744c37bb6cd4f509f2d7a397934 Mon Sep 17 00:00:00 2001 From: qingweixu Date: Tue, 2 Apr 2019 10:14:40 +0800 Subject: [PATCH 0383/1060] partion: increase vendor partion size for 64bit [1/1] PD#SWPL-6373 Problem: increase vendor partion size for 64bit kernel Solution: increase vendor partion size for 64bit kernel Verify: verify by tm2_skt Change-Id: I18afd344c4bd4b486407033103743816b8408205 Signed-off-by: qingweixu --- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f2c574203d53..f9dd1c7cbb93 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x19000000>; mask = <1>; }; odm:odm From 458caba1754591fbce50aa79717c70afe20f76e2 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Tue, 2 Apr 2019 19:36:28 +0800 Subject: [PATCH 0384/1060] dts: add tm2_t962e2_ab301.dts. [1/1] PD#SWPL-6678 Problem: need support tm2_t962e2_ab301.dts Solution: copy from tm2_t962e2_ab311.dts Verify: build pass. Change-Id: I83c0f103399352b524a5203f22dc8d6f541b56a9 Signed-off-by: Jianxiong Pan --- .../arm/boot/dts/amlogic/tm2_t962e2_ab301.dts | 1914 +++++++++++++++++ .../boot/dts/amlogic/tm2_t962e2_ab301.dts | 1873 ++++++++++++++++ 2 files changed, 3787 insertions(+) create mode 100644 arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts create mode 100644 arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts new file mode 100644 index 000000000000..80c67de60b5b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -0,0 +1,1914 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB301"; + amlogic-dt-id = "tm2_t962e2_ab301"; + compatible = "amlogic, tm2_t962e2_ab301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "disabled"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tm2"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts new file mode 100644 index 000000000000..efd9c2a89ebc --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -0,0 +1,1873 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB301"; + amlogic-dt-id = "tm2_t962E2_ab301"; + compatible = "amlogic, tm2_t962e2_ab301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "disabled"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tm2"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; From dff85ddb0a1b80f5792664960b9967760d6e436d Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Mon, 1 Apr 2019 18:56:14 +0800 Subject: [PATCH 0385/1060] power: sm1/tm2: add sleep and iso mask function [1/1] PD#SWPL-6186 Problem: add mask function Solution: add sleep and iso mask function Verify: sm1_skt Change-Id: Ifbb7329fd1eb6e333d0332f53c809e7b2e55181d Signed-off-by: Shunzhou Jiang --- drivers/amlogic/power/power_ctrl.c | 52 ++++++++++++++++++++++++++++++ include/linux/amlogic/power_ctrl.h | 4 +++ 2 files changed, 56 insertions(+) diff --git a/drivers/amlogic/power/power_ctrl.c b/drivers/amlogic/power/power_ctrl.c index 9654f6a5ca6f..ad0b7845d942 100644 --- a/drivers/amlogic/power/power_ctrl.c +++ b/drivers/amlogic/power/power_ctrl.c @@ -62,6 +62,32 @@ int power_ctrl_sleep(bool power_on, unsigned int shift) } EXPORT_SYMBOL(power_ctrl_sleep); +int power_ctrl_sleep_mask(bool power_on, + unsigned int mask_val, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val & (~(mask_val << shift)); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } else { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val | (mask_val << shift); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_sleep_mask); + int power_ctrl_iso(bool power_on, unsigned int shift) { unsigned int val; @@ -87,6 +113,32 @@ int power_ctrl_iso(bool power_on, unsigned int shift) } EXPORT_SYMBOL(power_ctrl_iso); +int power_ctrl_iso_mask(bool power_on, + unsigned int mask_val, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&(ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val & (~(mask_val << shift)); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } else { + spin_lock_irqsave((&ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val | (mask_val << shift); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_iso_mask); + int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift) { unsigned int val; diff --git a/include/linux/amlogic/power_ctrl.h b/include/linux/amlogic/power_ctrl.h index 5b6f7213539e..f0ab6117fbb2 100644 --- a/include/linux/amlogic/power_ctrl.h +++ b/include/linux/amlogic/power_ctrl.h @@ -21,7 +21,11 @@ #ifdef CONFIG_AMLOGIC_POWER int power_ctrl_sleep(bool power_on, unsigned int shift); +int power_ctrl_sleep_mask(bool power_on, + unsigned int mask_val, unsigned int shift); int power_ctrl_iso(bool power_on, unsigned int shift); +int power_ctrl_iso_mask(bool power_on, + unsigned int mask_val, unsigned int shift); int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift); #else static inline int power_ctrl_sleep(bool power_on, unsigned int shift) From 1be2442829837c9d3ff3e71f6600abf17da9c649 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Wed, 3 Apr 2019 22:53:30 +0800 Subject: [PATCH 0386/1060] audio: TM2: disable spk on skt board [1/1] PD#SWPL-6721 Problem: audio block start. Solution: disable spk on dts setting. Verify: Verified on T962e2_ab311 Change-Id: I85da808dad14d0b16b66ea4e07276980c6896aa4 Signed-off-by: Zhe Wang --- MAINTAINERS | 23 ++++++---------- .../arm/boot/dts/amlogic/tm2_t962e2_ab301.dts | 4 +-- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 25 +++++++++++------- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 4 +-- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 4 +-- .../boot/dts/amlogic/tm2_t962e2_ab301.dts | 4 +-- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 26 ++++++++++++------- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 4 +-- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 4 +-- 9 files changed, 53 insertions(+), 45 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4399af787aa1..78b1431fd659 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13800,24 +13800,17 @@ AMLOGIC M8b M: Jianxin Pan F: arch/arm/boot/dts/amlogic> -ANLOGIC AUDIO +ANLOGIC AUDIO DRIVER M: Xing Wang -F: arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts -F: arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts -F: arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts -F: arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts -F: arch/arm64/boot/dts/amlogic/gxm_skt.dts -F: arch/arm64/boot/dts/amlogic/mesongxl.dtsi -F: arch/arm64/boot/dts/amlogic/mesongxm.dtsi +M: Zhe Wang +F: arch/arm64/boot/dts/amlogic/* +F: arch/arm/boot/dts/amlogic/* F: arch/arm64/configs/meson64_defconfig -F: drivers/amlogic/clk/clk-mpll.c -F: drivers/amlogic/clk/clk_misc.c -F: drivers/amlogic/clk/clkc.h -F: drivers/amlogic/clk/gxl.c +F: drivers/amlogic/clk/* F: drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c -F: drivers/amlogic/pinctrl/pinctrl_gxl.c -F: include/dt-bindings/clock/amlogic,gxl-clkc.h -F: include/linux/amlogic/media/sound/audin_regs.h +F: drivers/amlogic/pinctrl/* +F: include/dt-bindings/clock/* +F: include/linux/amlogic/media/sound/* F: sound/soc/Kconfig F: sound/soc/Makefile F: sound/soc/amlogic/* diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts index 80c67de60b5b..a5b02d1a24ba 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -319,7 +319,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1715,7 +1715,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_6 0>; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index ec8f5fb941c0..6a7775e8b44f 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -319,7 +319,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1594,10 +1594,10 @@ }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ - groups = "tdma_sclk_z", - "tdma_fs_z", - "tdma_dout0_z"; + mux { /* GPIOH_5, GPIOH_6, GPIOH_7 */ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h"; function = "tdma_out"; bias-pull-down; }; @@ -1698,7 +1698,7 @@ }; &i2c2 { - status = "okay"; + status = "disabled"; pinctrl-names="default"; pinctrl-0=<&i2c2_z_pins>; clock-frequency = <400000>; @@ -1710,15 +1710,22 @@ reg = <0x2d>; status = "disable"; }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_h1_pins>; + clock-frequency = <400000>; ad82584f: ad82584f@62 { compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; - reset_pin = <&gpio_ao GPIOAO_6 0>; + status = "disabled"; + reset_pin = <&gpio GPIOH_13 0>; + no_mclk; }; - }; &sd_emmc_c { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 8dc663deca00..390cff848e01 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -309,7 +309,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1601,7 +1601,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_6 0>; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index b764d9ed82a1..dfa9de0ea3c3 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -309,7 +309,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1601,7 +1601,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_6 0>; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts index efd9c2a89ebc..6b7dd05d8667 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -315,7 +315,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1674,7 +1674,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_6 0>; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index f5384358b542..21a2576d3264 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -315,7 +315,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1553,10 +1553,10 @@ }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ - groups = "tdma_sclk_z", - "tdma_fs_z", - "tdma_dout0_z"; + mux { /* GPIOH_5, GPIOH_6, GPIOH_7 */ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h"; function = "tdma_out"; bias-pull-down; }; @@ -1657,7 +1657,7 @@ }; &i2c2 { - status = "okay"; + status = "disabled"; pinctrl-names="default"; pinctrl-0=<&i2c2_z_pins>; clock-frequency = <400000>; @@ -1669,17 +1669,25 @@ reg = <0x2d>; status = "disable"; }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_h1_pins>; + clock-frequency = <400000>; ad82584f: ad82584f@62 { compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; - reset_pin = <&gpio_ao GPIOAO_6 0>; + status = "disabled"; + reset_pin = <&gpio GPIOH_13 0>; + no_mclk; }; - }; + &sd_emmc_c { status = "okay"; emmc { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 4f37ef684215..ceab60c0fa63 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -308,7 +308,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1600,7 +1600,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x0 0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_6 0>; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 50e84332e91e..0093859facb0 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -308,7 +308,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; @@ -1600,7 +1600,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x0 0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_6 0>; }; From bc9ae277e68043067f633796be79291b1ad8a6c8 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Sun, 31 Mar 2019 02:53:08 +0800 Subject: [PATCH 0387/1060] vpp: tm2: add vpp and sr support [1/2] PD#SWPL-6615 Problem: Need vpp and sr supprt for sm2 Solution: add support for tm2 Verify: test pass on tm2 skt Change-Id: I0ae2cb178fcbe047cdfec6b4e200424178993e6e Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 10 +++++----- drivers/amlogic/media/video_sink/vpp.c | 23 +++++++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index ce43f60572e0..d3a97f1deb50 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -12613,17 +12613,17 @@ static int __init video_early_init(void) WRITE_VCBUS_REG_BITS( VPP_MISC1, 0x100, 0, 9); } - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { /* force bypass dolby for TL1, no dolby function */ - WRITE_VCBUS_REG_BITS( - DOLBY_PATH_CTRL, 0xf, 0, 6); + if (is_meson_tl1_cpu()) + WRITE_VCBUS_REG_BITS( + DOLBY_PATH_CTRL, 0xf, 0, 6); /* disable latch for sr core0/1 scaler */ WRITE_VCBUS_REG_BITS( SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); WRITE_VCBUS_REG_BITS( SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1); - } - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) WRITE_VCBUS_REG_BITS( SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); return 0; diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 21e3d600ab33..72d1c6966d09 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1764,10 +1764,12 @@ int vpp_set_super_scaler_regs( if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_sm1_cpu() || - (is_meson_tl1_cpu() && + is_meson_sm1_cpu()) + tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | + (reg_srscl0_vsize & 0x1fff); + else if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) && ((scaler_path_sel == PPS_CORE0_CORE1) || - (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1)))) + (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1))) tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | (reg_srscl0_vsize & 0x1fff); else @@ -2164,7 +2166,7 @@ static void vpp_set_super_scaler( sr_path = next_frame_par->supscl_path; /* path config */ - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { if (sr_path == CORE0_PPS_CORE1) { next_frame_par->sr0_position = 1; next_frame_par->sr1_position = 1; @@ -2831,7 +2833,8 @@ RESTART: h_in = height_in = vf->height; next_frame_par->hscale_skip_count = 0; next_frame_par->vscale_skip_count = 0; - crop_ratio = vf->compWidth / vf->width; + if (vf->width && vf->compWidth) + crop_ratio = vf->compWidth / vf->width; goto RESTART_ALL; } @@ -3164,8 +3167,11 @@ void vpp_super_scaler_support(void) is_meson_sm1_cpu()) { sr_support |= SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; - } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || - is_meson_txlx_cpu() || is_meson_tl1_cpu()) { + } else if (is_meson_gxtvbb_cpu() + || is_meson_txl_cpu() + || is_meson_txlx_cpu() + || is_meson_tl1_cpu() + || is_meson_tm2_cpu()) { sr_support |= SUPER_CORE0_SUPPORT; sr_support |= SUPER_CORE1_SUPPORT; } else { @@ -3181,7 +3187,8 @@ void vpp_super_scaler_support(void) is_meson_sm1_cpu()) { sr_reg_offt = 0xc00; sr_reg_offt2 = 0x00; - } else if (is_meson_tl1_cpu()) { + } else if (is_meson_tl1_cpu() + || is_meson_tm2_cpu()) { sr_reg_offt = 0xc00; sr_reg_offt2 = 0xc80; } else { From 34ac02b40bcfd8ef6d9cf67848d458f8c7d99213 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Thu, 4 Apr 2019 11:18:28 +0800 Subject: [PATCH 0388/1060] usb: bringup TM2 usb3 [1/1] PD#SWPL-5609 Problem: bringup TM2 usb3. Solution: bringup TM2 usb3. Verify: TM2 Change-Id: Iea60a85e7d344f8f1cd44d07a634a6edd351218c Signed-off-by: Yue Wang --- MAINTAINERS | 2 + arch/arm/boot/dts/amlogic/mesontm2.dtsi | 134 ++- .../arm/boot/dts/amlogic/tm2_t962e2_ab301.dts | 18 +- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 18 +- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 19 +- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 20 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 134 ++- .../boot/dts/amlogic/tm2_t962e2_ab301.dts | 18 +- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 18 +- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 19 +- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 20 +- drivers/amlogic/pci/pcie-amlogic-v2.c | 35 +- drivers/amlogic/pci/pcie-amlogic.h | 1 + drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h | 2 + .../amlogic/usb/dwc_otg/310/dwc_otg_driver.c | 16 +- .../amlogic/usb/dwc_otg/310/dwc_otg_driver.h | 1 + drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h | 1 + .../usb/dwc_otg/310/dwc_otg_pcd_intr.c | 32 +- .../usb/dwc_otg/310/dwc_otg_pcd_linux.c | 20 +- drivers/amlogic/usb/phy/Makefile | 2 + drivers/amlogic/usb/phy/phy-aml-new-otg.c | 388 ++++++++ drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c | 18 +- drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c | 918 ++++++++++++++++++ drivers/usb/dwc3/core.c | 11 + include/linux/amlogic/usb-v2.h | 60 +- 25 files changed, 1835 insertions(+), 90 deletions(-) create mode 100644 drivers/amlogic/usb/phy/phy-aml-new-otg.c create mode 100644 drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c diff --git a/MAINTAINERS b/MAINTAINERS index 78b1431fd659..c7f7f8da2bc5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13560,6 +13560,7 @@ F: drivers/amlogic/esm/* AMLOGIC DWC_OTG USB M: Yue Wang F: drivers/amlogic/usb/* +F: drivers/amlogic/usb/phy/phy-aml-new-otg.c F: drivers/usb/phy/phy-aml-new-usb.h F: drivers/usb/phy/phy-aml-new-usb.c F: drivers/usb/phy/phy-aml-new-usb2.c @@ -13568,6 +13569,7 @@ F: drivers/usb/phy/phy-aml-new-usb-v2.h F: drivers/usb/phy/phy-aml-new-usb-v2.c F: drivers/usb/phy/phy-aml-new-usb2-v2.c F: drivers/usb/phy/phy-aml-new-usb3-v2.c +F: drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c F: drivers/usb/phy/phy-aml-usb.h F: drivers/usb/phy/phy-aml-usb.c F: drivers/usb/phy/phy-aml-usb2.c diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 8ff6e7d46338..01856ea49220 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -24,6 +24,7 @@ #include #include #include +#include #include "mesong12a-bifrost.dtsi" #include / { @@ -417,6 +418,7 @@ clock-src = "usb3.0"; clocks = <&clkc CLKID_USB_GENERAL>; clock-names = "dwc_general"; + snps,quirk-frame-length-adjustment = <0x20>; }; usb2_phy_v2: usb2phy@ffe09000 { @@ -444,22 +446,43 @@ }; usb3_phy_v2: usb3phy@ffe09080 { - compatible = "amlogic, amlogic-new-usb3-v2"; + compatible = "amlogic, amlogic-new-usb3-v3"; status = "disable"; - reg = <0xffe09080 0x20 - 0xffd01008 0x100>; - phy-reg = <0xff646000>; - phy-reg-size = <0x2000>; - usb2-phy-reg = <0xffe09000>; - usb2-phy-reg-size = <0x80>; - interrupts = <0 16 4>; + reg = <0xffe09080 0x20>; + phy0-reg = <0xff646000>; + phy0-reg-size = <0x2000>; + phy1-reg = <0xff65c000>; + phy1-reg-size = <0x2000>; + reset-reg = <0xffd01008>; + reset-reg-size = <0x100>; + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE1_GATE>; + clock-names = "pcie0_gate", + "pcie_refpll", + "pcie1_gate"; pwr-ctl = <1>; - u3-ctrl-sleep-shift = <18>; - u3-hhi-mem-pd-shift = <26>; - u3-hhi-mem-pd-mask = <0xf>; - u3-ctrl-iso-shift = <18>; + u30-ctrl-sleep-shift = <18>; + u30-hhi-mem-pd-shift = <26>; + u30-hhi-mem-pd-mask = <0xf>; + u30-ctrl-iso-shift = <18>; + usb30-ctrl-a-rst-bit = <12>; + u31-ctrl-sleep-shift = <20>; + u31-hhi-mem-pd-shift = <4>; + u31-hhi-mem-pd-mask = <0xf>; + u31-ctrl-iso-shift = <20>; + usb31-ctrl-a-rst-bit = <28>; }; + usb_otg: usbotg@ffe09080 { + compatible = "amlogic, amlogic-new-otg"; + status = "disabled"; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x100>; + interrupts = <0 16 4>; + }; + + dwc2_a: dwc2_a@ff400000 { compatible = "amlogic, dwc2"; status = "disabled"; @@ -482,6 +505,7 @@ /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ /** 0x2: amlogic-v2 phy **/ phy-interface = <0x2>; + phy-otg = <0x1>; clocks = <&clkc CLKID_USB_GENERAL &clkc CLKID_USB1_TO_DDR>; clock-names = "usb_general", @@ -1146,6 +1170,92 @@ pinctrl-0 = <&c_uart_pins>; }; + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfc000000 0x400000 + 0xff648000 0x2000 + 0xfc400000 0x200000 + 0xff646000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE0PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; + status = "disabled"; + }; + + pcie_B: pcieB@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfA000000 0x400000 + 0xff65E000 0x2000 + 0xfA400000 0x200000 + 0xff65C000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", + "reset"; + interrupts = <0 229 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 231 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfA600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0xfA700000 0x0 0xfA700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE1_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE1PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <30>; + pcie-phy-rst-bit = <29>; + pcie-ctrl-a-rst-bit = <28>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <20>; + pcie-hhi-mem-pd-shift = <4>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <20>; + status = "disabled"; + }; + sd_emmc_c: emmc@ffe07000 { status = "disabled"; compatible = "amlogic, meson-mmc-tm2"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts index a5b02d1a24ba..3b78519ba49b 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -1839,7 +1839,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1849,6 +1855,16 @@ controller-type = <1>; }; +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 6a7775e8b44f..1a3d620da86c 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1846,7 +1846,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1856,6 +1862,16 @@ controller-type = <1>; }; +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 390cff848e01..2a9ee68e9a82 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1723,7 +1723,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1733,6 +1739,17 @@ controller-type = <1>; }; +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio is the oe pad, must be changed */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index dfa9de0ea3c3..c4cdfba65bf8 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1723,7 +1723,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1733,6 +1739,18 @@ controller-type = <1>; }; +&pcie_A { + /* pcie a reset gpio must be updated */ + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio must be updated */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index b4f593c3a19a..4736093d2a41 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -24,6 +24,7 @@ #include #include #include +#include #include "mesong12a-bifrost.dtsi" #include / { @@ -398,6 +399,7 @@ clock-src = "usb3.0"; clocks = <&clkc CLKID_USB_GENERAL>; clock-names = "dwc_general"; + snps,quirk-frame-length-adjustment = <0x20>; }; usb2_phy_v2: usb2phy@ffe09000 { @@ -425,22 +427,43 @@ }; usb3_phy_v2: usb3phy@ffe09080 { - compatible = "amlogic, amlogic-new-usb3-v2"; + compatible = "amlogic, amlogic-new-usb3-v3"; status = "disable"; - reg = <0x0 0xffe09080 0x0 0x20 - 0x0 0xffd01008 0x0 0x100>; - phy-reg = <0xff646000>; - phy-reg-size = <0x2000>; - usb2-phy-reg = <0xffe09000>; - usb2-phy-reg-size = <0x80>; - interrupts = <0 16 4>; + reg = <0x0 0xffe09080 0x0 0x20>; + phy0-reg = <0xff646000>; + phy0-reg-size = <0x2000>; + phy1-reg = <0xff65c000>; + phy1-reg-size = <0x2000>; + reset-reg = <0xffd01008>; + reset-reg-size = <0x100>; + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE1_GATE>; + clock-names = "pcie0_gate", + "pcie_refpll", + "pcie1_gate"; pwr-ctl = <1>; - u3-ctrl-sleep-shift = <18>; - u3-hhi-mem-pd-shift = <26>; - u3-hhi-mem-pd-mask = <0xf>; - u3-ctrl-iso-shift = <18>; + u30-ctrl-sleep-shift = <18>; + u30-hhi-mem-pd-shift = <26>; + u30-hhi-mem-pd-mask = <0xf>; + u30-ctrl-iso-shift = <18>; + usb30-ctrl-a-rst-bit = <12>; + u31-ctrl-sleep-shift = <20>; + u31-hhi-mem-pd-shift = <4>; + u31-hhi-mem-pd-mask = <0xf>; + u31-ctrl-iso-shift = <20>; + usb31-ctrl-a-rst-bit = <28>; }; + usb_otg: usbotg@ffe09080 { + compatible = "amlogic, amlogic-new-otg"; + status = "disabled"; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x100>; + interrupts = <0 16 4>; + }; + + dwc2_a: dwc2_a@ff400000 { compatible = "amlogic, dwc2"; status = "disabled"; @@ -463,6 +486,7 @@ /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ /** 0x2: amlogic-v2 phy **/ phy-interface = <0x2>; + phy-otg = <0x1>; clocks = <&clkc CLKID_USB_GENERAL &clkc CLKID_USB1_TO_DDR>; clock-names = "usb_general", @@ -1126,6 +1150,92 @@ pinctrl-0 = <&c_uart_pins>; }; + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfc000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfc400000 0x0 0x200000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE0PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; + status = "disabled"; + }; + + pcie_B: pcieB@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfA000000 0x0 0x400000 + 0x0 0xff65E000 0x0 0x2000 + 0x0 0xfA400000 0x0 0x200000 + 0x0 0xff65C000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", + "reset"; + interrupts = <0 229 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 231 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfA600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfA700000 0x0 0xfA700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE1_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE1PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <30>; + pcie-phy-rst-bit = <29>; + pcie-ctrl-a-rst-bit = <28>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <20>; + pcie-hhi-mem-pd-shift = <4>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <20>; + status = "disabled"; + }; + sd_emmc_c: emmc@ffe07000 { status = "disabled"; compatible = "amlogic, meson-mmc-tm2"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts index 6b7dd05d8667..47f6b868a21a 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -1798,7 +1798,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1808,6 +1814,16 @@ controller-type = <1>; }; +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 21a2576d3264..8ca2b8c70f41 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1806,7 +1806,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1816,6 +1822,16 @@ controller-type = <1>; }; +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index ceab60c0fa63..9331d1af0a95 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1721,7 +1721,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1731,6 +1737,17 @@ controller-type = <1>; }; +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio is the oe pad, must be changed */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 0093859facb0..294704419f60 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1722,7 +1722,13 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; otg = <0>; }; @@ -1732,6 +1738,18 @@ controller-type = <1>; }; +&pcie_A { + /* pcie a reset gpio must be updated */ + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio must be updated */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/drivers/amlogic/pci/pcie-amlogic-v2.c b/drivers/amlogic/pci/pcie-amlogic-v2.c index 479e445b7e76..2bb169ce0efa 100644 --- a/drivers/amlogic/pci/pcie-amlogic-v2.c +++ b/drivers/amlogic/pci/pcie-amlogic-v2.c @@ -57,7 +57,6 @@ struct amlogic_pcie { #define to_amlogic_pcie(x) container_of(x, struct amlogic_pcie, pp) struct pcie_phy_aml_regs pcie_aml_regs_v2; -struct pcie_phy *g_pcie_phy_v2; static void amlogic_elb_writel(struct amlogic_pcie *amlogic_pcie, u32 val, u32 reg) @@ -673,6 +672,7 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, dev_err(pp->dev, "link timeout, disable PCIE PLL\n"); clk_disable_unprepare(amlogic_pcie->bus_clk); clk_disable_unprepare(amlogic_pcie->clk); + clk_disable_unprepare(amlogic_pcie->phy_clk); dev_err(pp->dev, "power down pcie phy\n"); writel(0x1d, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 0; @@ -692,14 +692,14 @@ static void power_switch_to_pcie(struct pcie_phy *phy) udelay(100); val = readl((void __iomem *)(unsigned long)phy->reset_base); - writel((val & (~(0x1<<12))), + writel((val & (~(0x1<pcie_ctrl_a_rst_bit))), (void __iomem *)(unsigned long)phy->reset_base); udelay(100); power_ctrl_iso(1, phy->pcie_ctrl_iso_shift); val = readl((void __iomem *)(unsigned long)phy->reset_base); - writel((val | (0x1<<12)), + writel((val | (0x1<pcie_ctrl_a_rst_bit)), (void __iomem *)(unsigned long)phy->reset_base); udelay(100); } @@ -744,16 +744,6 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) pp->dev = dev; port_num++; amlogic_pcie->port_num = port_num; - if (amlogic_pcie->port_num == 1) { - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) { - port_num--; - return -ENOMEM; - } - g_pcie_phy_v2 = phy; - } - - amlogic_pcie->phy = g_pcie_phy_v2; ret = of_property_read_u32(np, "pcie-apb-rst-bit", &pcie_apb_rst_bit); if (ret) @@ -768,6 +758,15 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) if (ret) amlogic_pcie->rst_mod = 0; + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) { + port_num--; + return -ENOMEM; + } + phy->pcie_ctrl_a_rst_bit = pcie_ctrl_a_rst_bit; + + amlogic_pcie->phy = phy; + ret = of_property_read_u32(np, "pcie-num", &pcie_num); if (ret) amlogic_pcie->pcie_num = 0; @@ -828,8 +827,8 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) if (!amlogic_pcie->phy->reset_base) { reset_base = platform_get_resource_byname( pdev, IORESOURCE_MEM, "reset"); - amlogic_pcie->phy->reset_base = devm_ioremap_resource( - dev, reset_base); + amlogic_pcie->phy->reset_base = ioremap(reset_base->start, + resource_size(reset_base)); if (IS_ERR(amlogic_pcie->phy->reset_base)) { ret = PTR_ERR(amlogic_pcie->phy->reset_base); return ret; @@ -901,10 +900,8 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) if (!amlogic_pcie->phy->reset_state) { rate = clk_get_rate(amlogic_pcie->bus_clk); - if (rate != PCIE_PLL_RATE) { - ret = -ENODEV; - goto fail_pcie; - } + if (rate != PCIE_PLL_RATE) + dev_info(dev, "pcie ref pll is 0x%lx\n", rate); } /*RESET0[6,7] = 1*/ diff --git a/drivers/amlogic/pci/pcie-amlogic.h b/drivers/amlogic/pci/pcie-amlogic.h index 394a33a78663..38a7683988e2 100644 --- a/drivers/amlogic/pci/pcie-amlogic.h +++ b/drivers/amlogic/pci/pcie-amlogic.h @@ -166,6 +166,7 @@ struct pcie_phy { u32 pcie_hhi_mem_pd_mask; u32 pcie_ctrl_iso_shift; u32 pcie_hhi_mem_pd_shift; + u32 pcie_ctrl_a_rst_bit; }; diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h index a58ba8cb5d04..3c8ef428c127 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h @@ -1060,6 +1060,8 @@ struct dwc_otg_core_if { uint32_t phy_interface; + uint32_t phy_otg; + dwc_timer_t *device_connect_timer; uint64_t sof_counter; diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c index 3ce109bf851f..263ed2c1938f 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c @@ -958,6 +958,7 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) unsigned int p_ctrl_reg_addr = 0; unsigned int phy_reg_addr_size = 0; unsigned int phy_interface = 1; + unsigned int phy_otg = 0; const char *s_clock_name = NULL; const char *cpu_type = NULL; const char *gpio_name = NULL; @@ -1059,6 +1060,10 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) if (prop) phy_interface = of_read_ulong(prop, 1); + prop = of_get_property(of_node, "phy-otg", NULL); + if (prop) + phy_otg = of_read_ulong(prop, 1); + if (is_meson_g12b_cpu()) { if (!is_meson_rev_a()) phy_interface = 2; @@ -1162,6 +1167,7 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) dwc_otg_device->core_if->usb_peri_reg = (usb_peri_reg_t *)phy_reg_addr; dwc_otg_device->core_if->controller_type = controller_type; dwc_otg_device->core_if->phy_interface = phy_interface; + dwc_otg_device->core_if->phy_otg = phy_otg; /* * Attempt to ensure this device is really a DWC_otg Controller. * Read and verify the SNPSID register contents. The value should be @@ -1407,10 +1413,14 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) #ifdef CONFIG_AMLOGIC_USB3PHY if (dwc_otg_device->core_if->controller_type == USB_OTG) { - if (dwc_otg_device->core_if->phy_interface == 1) + if (dwc_otg_device->core_if->phy_interface == 1) { aml_new_usb_init(); - else - aml_new_usb_v2_init(); + } else { + if (dwc_otg_device->core_if->phy_otg) + aml_new_otg_init(); + else + aml_new_usb_v2_init(); + } } #endif diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h index 897f51545164..69272923e5c7 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h @@ -47,6 +47,7 @@ #ifdef CONFIG_AMLOGIC_USB3PHY extern void aml_new_usb_init(void); extern void aml_new_usb_v2_init(void); +extern void aml_new_otg_init(void); #endif /* Type declarations */ diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h index 38a153f4c8b7..8fbe4a4401c2 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h @@ -275,6 +275,7 @@ void dwc_otg_iso_buffer_done(dwc_otg_pcd_t *pcd, dwc_otg_pcd_ep_t *ep, extern void do_test_mode(void *data); extern int aml_new_usb_get_mode(void); +extern int aml_new_otg_get_mode(void); #ifdef CONFIG_AMLOGIC_USB3PHY extern void set_usb_phy_device_tuning(int port, int default_val); #endif diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c index 3382a6a1260d..cd503c67b9cb 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c @@ -1067,14 +1067,30 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *pcd) if (GET_CORE_IF(pcd)->phy_interface != 1) { if (GET_CORE_IF(pcd)->controller_type == USB_OTG) { speed = get_device_speed(GET_CORE_IF(pcd)); - if ((speed != USB_SPEED_HIGH) && - (aml_new_usb_get_mode() != 1)) { - gintsts.d32 = 0; - gintsts.b.enumdone = 1; - DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> - core_global_regs->gintsts, gintsts.d32); - DWC_DEBUGPL(DBG_PCD, "false speed emun\n"); - return 1; + if (GET_CORE_IF(pcd)->phy_otg == 1) { + if ((speed != USB_SPEED_HIGH) && + (aml_new_otg_get_mode() != 1)) { + gintsts.d32 = 0; + gintsts.b.enumdone = 1; + DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> + core_global_regs->gintsts, + gintsts.d32); + DWC_DEBUGPL(DBG_PCD, + "false speed emun\n"); + return 1; + } + } else { + if ((speed != USB_SPEED_HIGH) && + (aml_new_usb_get_mode() != 1)) { + gintsts.d32 = 0; + gintsts.b.enumdone = 1; + DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> + core_global_regs->gintsts, + gintsts.d32); + DWC_DEBUGPL(DBG_PCD, + "false speed emun\n"); + return 1; + } } } diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c index 6ba3f1676201..2ad6baf5ec30 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c @@ -1304,10 +1304,14 @@ int pcd_init(struct platform_device *pdev) } #ifdef CONFIG_AMLOGIC_USB3PHY - if (otg_dev->core_if->phy_interface == 1) + if (otg_dev->core_if->phy_interface == 1) { aml_new_usb_register_notifier(&otg_dev->nb); - else - aml_new_usb_v2_register_notifier(&otg_dev->nb); + } else { + if (otg_dev->core_if->phy_otg == 1) + aml_new_otg_register_notifier(&otg_dev->nb); + else + aml_new_usb_v2_register_notifier(&otg_dev->nb); + } otg_dev->nb.notifier_call = dwc_usb_change; #endif @@ -1375,10 +1379,14 @@ void pcd_remove(struct platform_device *pdev) free_wrapper(gadget_wrapper); dwc_otg_pcd_remove(otg_dev->pcd); #ifdef CONFIG_AMLOGIC_USB3PHY - if (otg_dev->core_if->phy_interface == 1) + if (otg_dev->core_if->phy_interface == 1) { aml_new_usb_unregister_notifier(&otg_dev->nb); - else - aml_new_usb_v2_unregister_notifier(&otg_dev->nb); + } else { + if (otg_dev->core_if->phy_otg == 1) + aml_new_otg_unregister_notifier(&otg_dev->nb); + else + aml_new_usb_v2_unregister_notifier(&otg_dev->nb); + } #endif otg_dev->pcd = 0; } diff --git a/drivers/amlogic/usb/phy/Makefile b/drivers/amlogic/usb/phy/Makefile index 22433e19fc7b..47a6d6df259e 100644 --- a/drivers/amlogic/usb/phy/Makefile +++ b/drivers/amlogic/usb/phy/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-usb3.o obj-$(CONFIG_AMLOGIC_USBPHY) += phy-aml-new-usb-v2.o obj-$(CONFIG_AMLOGIC_USB2PHY) += phy-aml-new-usb2-v2.o obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-usb3-v2.o +obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-usb3-v3.o +obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-otg.o diff --git a/drivers/amlogic/usb/phy/phy-aml-new-otg.c b/drivers/amlogic/usb/phy/phy-aml-new-otg.c new file mode 100644 index 000000000000..d4d4f1868998 --- /dev/null +++ b/drivers/amlogic/usb/phy/phy-aml-new-otg.c @@ -0,0 +1,388 @@ +/* + * drivers/amlogic/usb/phy/phy-aml-new-otg.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "phy-aml-new-usb-v2.h" + +#define HOST_MODE 0 +#define DEVICE_MODE 1 + +struct usb_aml_regs_v2 usb_otg_aml_regs; +struct amlogic_otg *g_otg; + +struct amlogic_otg { + struct device *dev; + void __iomem *phy3_cfg; + void __iomem *phy3_cfg_r1; + void __iomem *phy3_cfg_r2; + void __iomem *phy3_cfg_r4; + void __iomem *phy3_cfg_r5; + void __iomem *usb2_phy_cfg; + /* Set VBus Power though GPIO */ + int vbus_power_pin; + int vbus_power_pin_work_mask; + struct delayed_work work; + struct gpio_desc *usb_gpio_desc; +}; + +static void set_mode(unsigned long reg_addr, int mode); +BLOCKING_NOTIFIER_HEAD(aml_new_otg_notifier_list); + +int aml_new_otg_register_notifier(struct notifier_block *nb) +{ + int ret; + + ret = blocking_notifier_chain_register + (&aml_new_otg_notifier_list, nb); + + return ret; +} +EXPORT_SYMBOL(aml_new_otg_register_notifier); + +int aml_new_otg_unregister_notifier(struct notifier_block *nb) +{ + int ret; + + ret = blocking_notifier_chain_unregister + (&aml_new_otg_notifier_list, nb); + + return ret; +} +EXPORT_SYMBOL(aml_new_otg_unregister_notifier); + +static void aml_new_usb_notifier_call(unsigned long is_device_on) +{ + blocking_notifier_call_chain + (&aml_new_otg_notifier_list, is_device_on, NULL); +} + +static void set_usb_vbus_power + (struct gpio_desc *usb_gd, int pin, char is_power_on) +{ + if (is_power_on) + /*set vbus on by gpio*/ + gpiod_direction_output(usb_gd, 1); + else + /*set vbus off by gpio first*/ + gpiod_direction_output(usb_gd, 0); +} + +static void amlogic_new_set_vbus_power + (struct amlogic_otg *phy, char is_power_on) +{ + if (phy->vbus_power_pin != -1) + set_usb_vbus_power(phy->usb_gpio_desc, + phy->vbus_power_pin, is_power_on); +} + + + +void aml_new_otg_init(void) +{ + union usb_r5_v2 r5 = {.d32 = 0}; + unsigned long reg_addr; + + if (!g_otg) + return; + + reg_addr = (unsigned long)g_otg->usb2_phy_cfg; + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) { + amlogic_new_set_vbus_power(g_otg, 1); + aml_new_usb_notifier_call(0); + set_mode(reg_addr, HOST_MODE); + } +} +EXPORT_SYMBOL(aml_new_otg_init); + +int aml_new_otg_get_mode(void) +{ + union usb_r5_v2 r5 = {.d32 = 0}; + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) + return 0; + else + return 1; +} +EXPORT_SYMBOL(aml_new_otg_get_mode); + + +static int amlogic_new_otg_init(struct amlogic_otg *phy) +{ + union usb_r1_v2 r1 = {.d32 = 0}; + union usb_r5_v2 r5 = {.d32 = 0}; + int i = 0; + + for (i = 0; i < 6; i++) { + usb_otg_aml_regs.usb_r_v2[i] = (void __iomem *) + ((unsigned long)phy->usb2_phy_cfg + 0x80 + 4*i); + } + + r1.d32 = readl(usb_otg_aml_regs.usb_r_v2[1]); + r1.b.u3h_fladj_30mhz_reg = 0x20; + writel(r1.d32, usb_otg_aml_regs.usb_r_v2[1]); + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + r5.b.iddig_en0 = 1; + r5.b.iddig_en1 = 1; + r5.b.iddig_th = 255; + writel(r5.d32, usb_otg_aml_regs.usb_r_v2[5]); + + return 0; +} + +static void set_mode(unsigned long reg_addr, int mode) +{ + struct u2p_aml_regs_v2 u2p_aml_regs; + struct usb_aml_regs_v2 usb_gxl_aml_regs; + union u2p_r0_v2 reg0; + union usb_r0_v2 r0 = {.d32 = 0}; + union usb_r4_v2 r4 = {.d32 = 0}; + + u2p_aml_regs.u2p_r_v2[0] = (void __iomem *) + ((unsigned long)reg_addr + PHY_REGISTER_SIZE); + + usb_gxl_aml_regs.usb_r_v2[0] = (void __iomem *) + ((unsigned long)reg_addr + 4*PHY_REGISTER_SIZE + + 4*0); + usb_gxl_aml_regs.usb_r_v2[1] = (void __iomem *) + ((unsigned long)reg_addr + 4*PHY_REGISTER_SIZE + + 4*1); + usb_gxl_aml_regs.usb_r_v2[4] = (void __iomem *) + ((unsigned long)reg_addr + 4*PHY_REGISTER_SIZE + + 4*4); + + r0.d32 = readl(usb_gxl_aml_regs.usb_r_v2[0]); + if (mode == DEVICE_MODE) { + r0.b.u2d_act = 1; + r0.b.u2d_ss_scaledown_mode = 0; + } else + r0.b.u2d_act = 0; + writel(r0.d32, usb_gxl_aml_regs.usb_r_v2[0]); + + r4.d32 = readl(usb_gxl_aml_regs.usb_r_v2[4]); + if (mode == DEVICE_MODE) + r4.b.p21_SLEEPM0 = 0x1; + else + r4.b.p21_SLEEPM0 = 0x0; + writel(r4.d32, usb_gxl_aml_regs.usb_r_v2[4]); + + reg0.d32 = readl(u2p_aml_regs.u2p_r_v2[0]); + if (mode == DEVICE_MODE) { + reg0.b.host_device = 0; + reg0.b.POR = 0; + } else { + reg0.b.host_device = 1; + reg0.b.POR = 0; + } + writel(reg0.d32, u2p_aml_regs.u2p_r_v2[0]); + + udelay(500); +} + +static void amlogic_gxl_work(struct work_struct *work) +{ + struct amlogic_otg *phy = + container_of(work, struct amlogic_otg, work.work); + union usb_r5_v2 r5 = {.d32 = 0}; + unsigned long reg_addr = ((unsigned long)phy->usb2_phy_cfg); + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) { + amlogic_new_set_vbus_power(phy, 1); + aml_new_usb_notifier_call(0); + set_mode(reg_addr, HOST_MODE); + } else { + set_mode(reg_addr, DEVICE_MODE); + aml_new_usb_notifier_call(1); + amlogic_new_set_vbus_power(phy, 0); + } + r5.b.usb_iddig_irq = 0; + writel(r5.d32, usb_otg_aml_regs.usb_r_v2[5]); +} + +static irqreturn_t amlogic_botg_detect_irq(int irq, void *dev) +{ + struct amlogic_otg *phy = (struct amlogic_otg *)dev; + union usb_r5_v2 r5 = {.d32 = 0}; + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + r5.b.usb_iddig_irq = 0; + writel(r5.d32, usb_otg_aml_regs.usb_r_v2[5]); + + schedule_delayed_work(&phy->work, msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static int amlogic_new_otg_probe(struct platform_device *pdev) +{ + struct amlogic_otg *phy; + struct device *dev = &pdev->dev; + void __iomem *usb2_phy_base; + unsigned int usb2_phy_mem; + unsigned int usb2_phy_mem_size = 0; + const char *gpio_name = NULL; + struct gpio_desc *usb_gd = NULL; + const void *prop; + int irq; + int retval; + int gpio_vbus_power_pin = -1; + int otg = 0; + + gpio_name = of_get_property(dev->of_node, "gpio-vbus-power", NULL); + if (gpio_name) { + gpio_vbus_power_pin = 1; + usb_gd = gpiod_get_index(&pdev->dev, + NULL, 0, GPIOD_OUT_LOW); + if (IS_ERR(usb_gd)) + return -1; + } + + prop = of_get_property(dev->of_node, "otg", NULL); + if (prop) + otg = of_read_ulong(prop, 1); + + retval = of_property_read_u32 + (dev->of_node, "usb2-phy-reg", &usb2_phy_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "usb2-phy-reg-size", &usb2_phy_mem_size); + if (retval < 0) + return -EINVAL; + + usb2_phy_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)usb2_phy_mem, + (unsigned long)usb2_phy_mem_size); + if (!usb2_phy_base) + return -ENOMEM; + + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + if (otg) { + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENODEV; + retval = request_irq(irq, amlogic_botg_detect_irq, + IRQF_SHARED | IRQ_LEVEL, + "amlogic_botg_detect", phy); + + if (retval) { + dev_err(&pdev->dev, "request of irq%d failed\n", irq); + retval = -EBUSY; + return retval; + } + } + + dev_info(&pdev->dev, "phy_mem:0x%lx, iomap phy_base:0x%lx\n", + (unsigned long)usb2_phy_mem, + (unsigned long)usb2_phy_base); + + phy->dev = dev; + phy->usb2_phy_cfg = usb2_phy_base; + phy->vbus_power_pin = gpio_vbus_power_pin; + phy->usb_gpio_desc = usb_gd; + + INIT_DELAYED_WORK(&phy->work, amlogic_gxl_work); + + platform_set_drvdata(pdev, phy); + + pm_runtime_enable(phy->dev); + g_otg = phy; + + amlogic_new_otg_init(phy); + + return 0; +} + +static int amlogic_new_otg_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_PM_RUNTIME + +static int amlogic_new_otg_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int amlogic_new_otg_runtime_resume(struct device *dev) +{ + u32 ret = 0; + + return ret; +} + +static const struct dev_pm_ops amlogic_new_otg_pm_ops = { + SET_RUNTIME_PM_OPS(amlogic_new_otg_runtime_suspend, + amlogic_new_otg_runtime_resume, + NULL) +}; + +#define DEV_PM_OPS (&amlogic_new_otg_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +#ifdef CONFIG_OF +static const struct of_device_id amlogic_new_otg_id_table[] = { + { .compatible = "amlogic, amlogic-new-otg" }, + {} +}; +MODULE_DEVICE_TABLE(of, amlogic_new_otg_id_table); +#endif + +static struct platform_driver amlogic_new_otg_driver = { + .probe = amlogic_new_otg_probe, + .remove = amlogic_new_otg_remove, + .driver = { + .name = "amlogic-new-otg", + .owner = THIS_MODULE, + .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(amlogic_new_otg_id_table), + }, +}; + +module_platform_driver(amlogic_new_otg_driver); + +MODULE_ALIAS("platform: amlogic_usb3_v2"); +MODULE_AUTHOR("Amlogic Inc."); +MODULE_DESCRIPTION("amlogic USB3 v2 phy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c index 3c97500bb819..ef22d475f7df 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c @@ -146,6 +146,7 @@ static void cr_bus_addr(unsigned int addr) phy_r4.b.phy_cr_data_in = addr; writel(phy_r4.d32, g_phy_v2->phy3_cfg_r4); + phy_r4.b.phy_cr_cap_addr = 0; writel(phy_r4.d32, g_phy_v2->phy3_cfg_r4); phy_r4.b.phy_cr_cap_addr = 1; @@ -312,7 +313,6 @@ static int amlogic_new_usb3_init(struct usb_phy *x) p3_r2.b.phy_tx_vboost_lvl = 0x4; writel(p3_r2.d32, phy->phy3_cfg_r2); udelay(2); - /* * WORKAROUND: There is SSPHY suspend bug due to * which USB enumerates @@ -487,8 +487,9 @@ static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) { u32 val; - power_ctrl_sleep(1, phy->u3_ctrl_sleep_shift); - power_ctrl_mempd0(1, phy->u3_hhi_mem_pd_mask, phy->u3_hhi_mem_pd_shift); + power_ctrl_sleep(1, phy->u30_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u30_hhi_mem_pd_mask, + phy->u30_hhi_mem_pd_shift); udelay(100); val = readl((void __iomem *) @@ -497,7 +498,7 @@ static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); udelay(100); - power_ctrl_iso(1, phy->u3_ctrl_iso_shift); + power_ctrl_iso(1, phy->u30_ctrl_iso_shift); val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); @@ -695,10 +696,10 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) /* set the phy from pcie to usb3 */ if (phy->portnum > 0) { if (phy->pwr_ctl) { - phy->u3_ctrl_sleep_shift = u3_ctrl_sleep_shift; - phy->u3_hhi_mem_pd_shift = u3_hhi_mem_pd_shift; - phy->u3_hhi_mem_pd_mask = u3_hhi_mem_pd_mask; - phy->u3_ctrl_iso_shift = u3_ctrl_iso_shift; + phy->u30_ctrl_sleep_shift = u3_ctrl_sleep_shift; + phy->u30_hhi_mem_pd_shift = u3_hhi_mem_pd_shift; + phy->u30_hhi_mem_pd_mask = u3_hhi_mem_pd_mask; + phy->u30_ctrl_iso_shift = u3_ctrl_iso_shift; phy->reset_regs = reset_base; power_switch_to_pcie(phy); } @@ -718,7 +719,6 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) ret = PTR_ERR(phy->clk); return ret; } - phy->phy.flags = AML_USB3_PHY_ENABLE; } diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c new file mode 100644 index 000000000000..86b4c9fffea5 --- /dev/null +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c @@ -0,0 +1,918 @@ +/* + * drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "phy-aml-new-usb-v2.h" + +#define HOST_MODE 0 +#define DEVICE_MODE 1 + +struct usb_aml_regs_v2 usb_new_aml_regs_v3; + +static int amlogic_new_usb3_suspend(struct usb_phy *x, int suspend) +{ + return 0; +} + +static void amlogic_new_usb3phy_shutdown(struct usb_phy *x) +{ + struct amlogic_usb_v2 *phy = phy_to_amlusb(x); + + if (phy->phy.flags == AML_USB3_PHY_ENABLE) { + clk_disable_unprepare(phy->clk); + clk_disable_unprepare(phy->gate1_clk); + clk_disable_unprepare(phy->gate0_clk); + } + + phy->suspend_flag = 1; +} + +static void cr_bus_addr(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + phy_r4.b.phy_cr_data_in = addr; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_cap_addr = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static int cr_bus_read(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + int data; + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr(phy_v3, addr); + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_read = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + data = phy_r5.b.phy_cr_data_out; + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + return data; +} + +static void cr_bus_write(struct amlogic_usb_v2 *phy_v3, + unsigned int addr, unsigned int data) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr(phy_v3, addr); + + phy_r4.b.phy_cr_data_in = data; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_cap_data = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_write = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static void cr_bus_addr_31(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + phy_r4.b.phy_cr_data_in = addr; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_cap_addr = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static int cr_bus_read_31(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + int data; + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr_31(phy_v3, addr); + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_read = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + data = phy_r5.b.phy_cr_data_out; + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + return data; +} + +static void cr_bus_write_31(struct amlogic_usb_v2 *phy_v3, + unsigned int addr, unsigned int data) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr(phy_v3, addr); + + phy_r4.b.phy_cr_data_in = data; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_cap_data = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_write = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static void usb3_phy_cr_config_30(struct amlogic_usb_v2 *phy) +{ + u32 data = 0; + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + data = cr_bus_read(phy, 0x102d); + data |= (1 << 7); + cr_bus_write(phy, 0x102D, data); + + data = cr_bus_read(phy, 0x1010); + data &= ~0xff0; + data |= 0x20; + cr_bus_write(phy, 0x1010, data); + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + data = cr_bus_read(phy, 0x1006); + data &= ~(1 << 6); + data |= (1 << 7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (0x1 << 11); + cr_bus_write(phy, 0x1006, data); + + /* + * S et EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + data = cr_bus_read(phy, 0x1002); + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | (1 << 14)); + cr_bus_write(phy, 0x1002, data); + + /* + * MPLL_LOOP_CTL.PROP_CNTRL + */ + data = cr_bus_read(phy, 0x30); + data &= ~(0xf << 4); + data |= (0x8 << 4); + cr_bus_write(phy, 0x30, data); + udelay(2); +} + + +static void usb3_phy_cr_config_31(struct amlogic_usb_v2 *phy) +{ + u32 data = 0; + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + data = cr_bus_read_31(phy, 0x102d); + data |= (1 << 7); + cr_bus_write_31(phy, 0x102D, data); + + data = cr_bus_read_31(phy, 0x1010); + data &= ~0xff0; + data |= 0x20; + cr_bus_write_31(phy, 0x1010, data); + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + data = cr_bus_read_31(phy, 0x1006); + data &= ~(1 << 6); + data |= (1 << 7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (0x1 << 11); + cr_bus_write_31(phy, 0x1006, data); + + /* + * S et EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + data = cr_bus_read_31(phy, 0x1002); + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | (1 << 14)); + cr_bus_write_31(phy, 0x1002, data); + + /* + * MPLL_LOOP_CTL.PROP_CNTRL + */ + data = cr_bus_read_31(phy, 0x30); + data &= ~(0xf << 4); + data |= (0x8 << 4); + cr_bus_write_31(phy, 0x30, data); + udelay(2); +} + + +static int amlogic_new_usb3_init_v3(struct usb_phy *x) +{ + struct amlogic_usb_v2 *phy = phy_to_amlusb(x); + union usb_r1_v2 r1 = {.d32 = 0}; + union usb_r2_v2 r2 = {.d32 = 0}; + union usb_r3_v2 r3 = {.d32 = 0}; + union usb_r7_v2 r7 = {.d32 = 0}; + union phy3_r2 p3_r2 = {.d32 = 0}; + union phy3_r1 p3_r1 = {.d32 = 0}; + int i = 0; + + if (phy->suspend_flag) { + if (phy->phy.flags == AML_USB3_PHY_ENABLE) { + clk_prepare_enable(phy->gate0_clk); + clk_prepare_enable(phy->gate1_clk); + clk_prepare_enable(phy->clk); + } + phy->suspend_flag = 0; + return 0; + } + + if (phy->phy.flags != AML_USB3_PHY_ENABLE) + return 0; + + for (i = 0; i < 8; i++) { + usb_new_aml_regs_v3.usb_r_v2[i] = (void __iomem *) + ((unsigned long)phy->regs + 4*i); + } + + /* config usb30 phy */ + r3.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[3]); + r3.b.p30_ssc_en = 1; + r3.b.p30_ssc_range = 2; + r3.b.p30_ref_ssp_en = 1; + writel(r3.d32, usb_new_aml_regs_v3.usb_r_v2[3]); + udelay(2); + r2.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[2]); + r2.b.p30_pcs_tx_deemph_3p5db = 0x15; + r2.b.p30_pcs_tx_deemph_6db = 0x20; + writel(r2.d32, usb_new_aml_regs_v3.usb_r_v2[2]); + udelay(2); + r1.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[1]); + r1.b.u3h_host_port_power_control_present = 1; + r1.b.u3h_fladj_30mhz_reg = 0x20; + r1.b.p30_pcs_tx_swing_full = 127; + r1.b.u3h_host_u3_port_disable = 0; + writel(r1.d32, usb_new_aml_regs_v3.usb_r_v2[1]); + udelay(2); + p3_r2.d32 = readl(phy->phy3_cfg_r2); + p3_r2.b.phy_tx_vboost_lvl = 0x4; + writel(p3_r2.d32, phy->phy3_cfg_r2); + udelay(2); + + usb3_phy_cr_config_30(phy); + + /* + * LOS_BIAS to 0x5 + * LOS_LEVEL to 0x9 + */ + p3_r1.d32 = readl(phy->phy3_cfg_r1); + p3_r1.b.phy_los_bias = 0x4; + p3_r1.b.phy_los_level = 0x9; + writel(p3_r1.d32, phy->phy3_cfg_r1); + + /* config usb31 phy */ + r7.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[7]); + r7.b.p31_ssc_en = 1; + r7.b.p31_ssc_range = 2; + r7.b.p31_ref_ssp_en = 1; + r7.b.p31_pcs_tx_deemph_6db = 0x20; + r7.b.p31_pcs_tx_swing_full = 127; + writel(r7.d32, usb_new_aml_regs_v3.usb_r_v2[7]); + + udelay(2); + p3_r2.d32 = readl(phy->phy31_cfg_r2); + p3_r2.b.phy_tx_vboost_lvl = 0x4; + writel(p3_r2.d32, phy->phy31_cfg_r2); + udelay(2); + + usb3_phy_cr_config_31(phy); + + /* + * LOS_BIAS to 0x5 + * LOS_LEVEL to 0x9 + */ + p3_r1.d32 = readl(phy->phy31_cfg_r1); + p3_r1.b.phy_los_bias = 0x4; + p3_r1.b.phy_los_level = 0x9; + writel(p3_r1.d32, phy->phy31_cfg_r1); + + return 0; +} + +static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) +{ + u32 val; + + power_ctrl_sleep(1, phy->u30_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u30_hhi_mem_pd_mask, + phy->u30_hhi_mem_pd_shift); + udelay(100); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val & (~(0x1 << phy->usb30_ctrl_rst_bit))), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); + + power_ctrl_iso(1, phy->u30_ctrl_iso_shift); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + writel((val | (0x1 << phy->usb30_ctrl_rst_bit)), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); + + power_ctrl_sleep(1, phy->u31_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u31_hhi_mem_pd_mask, + phy->u31_hhi_mem_pd_shift); + udelay(100); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val & (~(0x1 << phy->usb31_ctrl_rst_bit))), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); + + power_ctrl_iso(1, phy->u31_ctrl_iso_shift); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + writel((val | (0x1 << phy->usb31_ctrl_rst_bit)), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); +} + +static int amlogic_new_usb3_v3_probe(struct platform_device *pdev) +{ + struct amlogic_usb_v2 *phy; + struct device *dev = &pdev->dev; + struct resource *phy_mem; + void __iomem *phy_base; + void __iomem *phy3_base; + void __iomem *phy31_base; + void __iomem *reset_base = NULL; + unsigned int phy3_mem; + unsigned int phy3_mem_size = 0; + unsigned int phy31_mem; + unsigned int phy31_mem_size = 0; + unsigned int reset_mem; + unsigned int reset_mem_size = 0; + + const void *prop; + int portnum = 0; + int retval; + int ret; + u32 pwr_ctl = 0; + u32 u30_ctrl_sleep_shift = 0; + u32 u30_hhi_mem_pd_shift = 0; + u32 u30_hhi_mem_pd_mask = 0; + u32 u30_ctrl_iso_shift = 0; + u32 usb30_ctrl_rst_bit = 0; + u32 u31_ctrl_sleep_shift = 0; + u32 u31_hhi_mem_pd_shift = 0; + u32 u31_hhi_mem_pd_mask = 0; + u32 u31_ctrl_iso_shift = 0; + u32 usb31_ctrl_rst_bit = 0; + u32 portconfig_30 = 0; + u32 portconfig_31 = 0; + unsigned long rate; +#define PCIE_PLL_RATE 100000000 + + prop = of_get_property(dev->of_node, "portnum", NULL); + if (prop) + portnum = of_read_ulong(prop, 1); + + if (!portnum) + dev_err(&pdev->dev, "This phy has no usb port\n"); + + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + phy_base = devm_ioremap_resource(dev, phy_mem); + if (IS_ERR(phy_base)) + return PTR_ERR(phy_base); + + retval = of_property_read_u32(dev->of_node, "phy0-reg", &phy3_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "phy0-reg-size", &phy3_mem_size); + if (retval < 0) + return -EINVAL; + + phy3_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)phy3_mem, + (unsigned long)phy3_mem_size); + if (!phy3_base) + return -ENOMEM; + + retval = of_property_read_u32(dev->of_node, "phy1-reg", &phy31_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "phy1-reg-size", + &phy31_mem_size); + if (retval < 0) + return -EINVAL; + + phy31_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)phy31_mem, + (unsigned long)phy31_mem_size); + if (!phy31_base) + return -ENOMEM; + + prop = of_get_property(dev->of_node, "pwr-ctl", NULL); + if (prop) + pwr_ctl = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + if (pwr_ctl) { + retval = of_property_read_u32(dev->of_node, + "reset-reg", &reset_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "reset-reg-size", + &reset_mem_size); + if (retval < 0) + return -EINVAL; + + reset_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)reset_mem, + (unsigned long)reset_mem_size); + if (!reset_base) + return -ENOMEM; + + prop = of_get_property(dev->of_node, + "u30-ctrl-sleep-shift", NULL); + if (prop) + u30_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u30-hhi-mem-pd-shift", NULL); + if (prop) + u30_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u30-hhi-mem-pd-mask", NULL); + if (prop) + u30_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u30-ctrl-iso-shift", NULL); + if (prop) + u30_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "usb30-ctrl-a-rst-bit", NULL); + if (prop) + usb30_ctrl_rst_bit = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-ctrl-sleep-shift", NULL); + if (prop) + u31_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-hhi-mem-pd-shift", NULL); + if (prop) + u31_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-hhi-mem-pd-mask", NULL); + if (prop) + u31_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-ctrl-iso-shift", NULL); + if (prop) + u31_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "usb31-ctrl-a-rst-bit", NULL); + if (prop) + usb31_ctrl_rst_bit = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + } + + prop = of_get_property(dev->of_node, + "portconfig-30", NULL); + if (prop) + portconfig_30 = of_read_ulong(prop, 1); + + prop = of_get_property(dev->of_node, + "portconfig-31", NULL); + if (prop) + portconfig_31 = of_read_ulong(prop, 1); + + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + dev_info(&pdev->dev, "USB3 phy probe:phy_mem:0x%lx, iomap phy_base:0x%lx\n", + (unsigned long)phy_mem->start, (unsigned long)phy_base); + + phy->dev = dev; + phy->regs = phy_base; + phy->phy3_cfg = phy3_base; + phy->phy3_cfg_r1 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 1); + phy->phy3_cfg_r2 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 2); + phy->phy3_cfg_r4 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 4); + phy->phy3_cfg_r5 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 5); + phy->phy31_cfg = phy31_base; + phy->phy31_cfg_r1 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 1); + phy->phy31_cfg_r2 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 2); + phy->phy31_cfg_r4 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 4); + phy->phy31_cfg_r5 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 5); + phy->portnum = portnum; + phy->suspend_flag = 0; + phy->phy.dev = phy->dev; + phy->phy.label = "amlogic-usbphy3"; + phy->phy.init = amlogic_new_usb3_init_v3; + phy->phy.set_suspend = amlogic_new_usb3_suspend; + phy->phy.shutdown = amlogic_new_usb3phy_shutdown; + phy->phy.type = USB_PHY_TYPE_USB3; + phy->phy.flags = AML_USB3_PHY_DISABLE; + phy->pwr_ctl = pwr_ctl; + + /* set the phy from pcie to usb3 */ + if (phy->portnum > 0) { + if (phy->pwr_ctl) { + phy->u30_ctrl_sleep_shift = u30_ctrl_sleep_shift; + phy->u30_hhi_mem_pd_shift = u30_hhi_mem_pd_shift; + phy->u30_hhi_mem_pd_mask = u30_hhi_mem_pd_mask; + phy->u30_ctrl_iso_shift = u30_ctrl_iso_shift; + phy->reset_regs = reset_base; + phy->usb30_ctrl_rst_bit = usb30_ctrl_rst_bit; + phy->u31_ctrl_sleep_shift = u31_ctrl_sleep_shift; + phy->u31_hhi_mem_pd_shift = u31_hhi_mem_pd_shift; + phy->u31_hhi_mem_pd_mask = u31_hhi_mem_pd_mask; + phy->u31_ctrl_iso_shift = u31_ctrl_iso_shift; + phy->usb31_ctrl_rst_bit = usb31_ctrl_rst_bit; + power_switch_to_pcie(phy); + } + + if (portconfig_30) + writel((readl(phy->phy3_cfg) | (3<<5)), phy->phy3_cfg); + udelay(100); + + if (portconfig_31) + writel((readl(phy->phy31_cfg) | (3<<5)), + phy->phy31_cfg); + udelay(100); + + phy->gate0_clk = devm_clk_get(dev, "pcie0_gate"); + if (IS_ERR(phy->gate0_clk)) { + dev_err(dev, "Failed to get usb3 bus clock\n"); + ret = PTR_ERR(phy->gate0_clk); + return ret; + } + + ret = clk_prepare_enable(phy->gate0_clk); + if (ret) { + dev_err(dev, "Failed to enable usb3 bus clock\n"); + ret = PTR_ERR(phy->gate0_clk); + return ret; + } + + phy->gate1_clk = devm_clk_get(dev, "pcie1_gate"); + if (IS_ERR(phy->gate1_clk)) { + dev_err(dev, "Failed to get usb3 bus clock\n"); + ret = PTR_ERR(phy->gate1_clk); + return ret; + } + + ret = clk_prepare_enable(phy->gate1_clk); + if (ret) { + dev_err(dev, "Failed to enable usb3 bus clock\n"); + ret = PTR_ERR(phy->gate1_clk); + return ret; + } + + phy->clk = devm_clk_get(dev, "pcie_refpll"); + if (IS_ERR(phy->clk)) { + dev_err(dev, "Failed to get usb3 bus clock\n"); + ret = PTR_ERR(phy->clk); + return ret; + } + + ret = clk_prepare_enable(phy->clk); + if (ret) { + dev_err(dev, "Failed to enable usb3 bus clock\n"); + ret = PTR_ERR(phy->clk); + return ret; + } + + rate = clk_get_rate(phy->clk); + if (rate != PCIE_PLL_RATE) + dev_err(dev, "pcie_refpll is not 100M, it is %ld\n", + rate); + + phy->phy.flags = AML_USB3_PHY_ENABLE; + } + + usb_add_phy_dev(&phy->phy); + + platform_set_drvdata(pdev, phy); + + pm_runtime_enable(phy->dev); + + return 0; +} + +static int amlogic_new_usb3_v3_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_PM_RUNTIME + +static int amlogic_new_usb3_v3_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int amlogic_new_usb3_v3_runtime_resume(struct device *dev) +{ + u32 ret = 0; + + return ret; +} + +static const struct dev_pm_ops amlogic_new_usb3_pm_ops = { + SET_RUNTIME_PM_OPS(amlogic_new_usb3_v3_runtime_suspend, + amlogic_new_usb3_v3_runtime_resume, + NULL) +}; + +#define DEV_PM_OPS (&amlogic_new_usb3_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +#ifdef CONFIG_OF +static const struct of_device_id amlogic_new_usb3_v3_id_table[] = { + { .compatible = "amlogic, amlogic-new-usb3-v3" }, + {} +}; +MODULE_DEVICE_TABLE(of, amlogic_new_usb3_v3_id_table); +#endif + +static struct platform_driver amlogic_new_usb3_v3_driver = { + .probe = amlogic_new_usb3_v3_probe, + .remove = amlogic_new_usb3_v3_remove, + .driver = { + .name = "amlogic-new-usb3-v3", + .owner = THIS_MODULE, + .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(amlogic_new_usb3_v3_id_table), + }, +}; + +module_platform_driver(amlogic_new_usb3_v3_driver); + +MODULE_ALIAS("platform: amlogic_usb3_v2"); +MODULE_AUTHOR("Amlogic Inc."); +MODULE_DESCRIPTION("amlogic USB3 v2 phy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a0846a1546fd..314238487d15 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -208,6 +208,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + /* Assert USB3 PHY reset */ + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(1)); + reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(1), reg); + /* Assert USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; @@ -245,6 +250,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + /* Clear USB3 PHY reset */ + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(1)); + reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(1), reg); + /* Clear USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; @@ -959,6 +969,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (dwc->usb3_phy) if (dwc->usb3_phy->flags == AML_USB3_PHY_ENABLE) dwc->super_speed_support = 1; + #endif dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index 4d5df3a8469c..8b3092c0a92d 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -30,6 +30,8 @@ int aml_new_usb_v2_register_notifier(struct notifier_block *nb); int aml_new_usb_v2_unregister_notifier(struct notifier_block *nb); +int aml_new_otg_register_notifier(struct notifier_block *nb); +int aml_new_otg_unregister_notifier(struct notifier_block *nb); struct u2p_aml_regs_v2 { void __iomem *u2p_r_v2[2]; @@ -64,7 +66,7 @@ union u2p_r1_v2 { }; struct usb_aml_regs_v2 { - void __iomem *usb_r_v2[6]; + void __iomem *usb_r_v2[8]; }; union usb_r0_v2 { @@ -88,13 +90,10 @@ union usb_r1_v2 { struct { unsigned u3h_bigendian_gs:1; unsigned u3h_pme_en:1; - unsigned u3h_hub_port_overcurrent:3; - unsigned reserved_1:2; - unsigned u3h_hub_port_perm_attach:3; - unsigned reserved_2:2; - unsigned u3h_host_u2_port_disable:2; - unsigned reserved_3:2; - unsigned u3h_host_u3_port_disable:1; + unsigned u3h_hub_port_overcurrent:5; + unsigned u3h_hub_port_perm_attach:5; + unsigned u3h_host_u2_port_disable:3; + unsigned u3h_host_u3_port_disable:2; unsigned u3h_host_port_power_control_present:1; unsigned u3h_host_msi_enable:1; unsigned u3h_fladj_30mhz_reg:6; @@ -135,7 +134,11 @@ union usb_r4_v2 { unsigned p21_SLEEPM0:1; unsigned mem_pd:2; unsigned p21_only:1; - unsigned reserved:27; + unsigned reserved:12; + unsigned p31_lane0_tx2rx_loopback:1; + unsigned p31_lane0_ext_pclk_req:1; + unsigned p31_pcs_rx_los_mask_val:10; + unsigned reserve:3; } b; }; @@ -157,6 +160,22 @@ union usb_r5_v2 { } b; }; +union usb_r7_v2 { + /** raw register data */ + uint32_t d32; + /** register bits */ + struct { + unsigned p31_ssc_en:1; + unsigned p31_ssc_range:3; + unsigned p31_ssc_ref_clk_sel:9; + unsigned p31_ref_ssp_en:1; + unsigned reserved:2; + unsigned p31_pcs_tx_deemph_6db:6; + unsigned reserve:3; + unsigned p31_pcs_tx_swing_full:7; + } b; +}; + struct amlogic_usb_v2 { struct usb_phy phy; struct device *dev; @@ -168,7 +187,14 @@ struct amlogic_usb_v2 { void __iomem *phy3_cfg_r2; void __iomem *phy3_cfg_r4; void __iomem *phy3_cfg_r5; + void __iomem *phy31_cfg; + void __iomem *phy31_cfg_r1; + void __iomem *phy31_cfg_r2; + void __iomem *phy31_cfg_r4; + void __iomem *phy31_cfg_r5; void __iomem *usb2_phy_cfg; + void __iomem *power_base; + void __iomem *hhi_mem_pd_base; u32 pll_setting[8]; int phy_cfg_state[4]; /* Set VBus Power though GPIO */ @@ -185,11 +211,19 @@ struct amlogic_usb_v2 { u32 u2_hhi_mem_pd_mask; u32 u2_ctrl_iso_shift; u32 u2_hhi_mem_pd_shift; - u32 u3_ctrl_sleep_shift; - u32 u3_hhi_mem_pd_mask; - u32 u3_ctrl_iso_shift; - u32 u3_hhi_mem_pd_shift; + u32 u30_ctrl_sleep_shift; + u32 u30_hhi_mem_pd_mask; + u32 u30_ctrl_iso_shift; + u32 u30_hhi_mem_pd_shift; + u32 usb30_ctrl_rst_bit; + u32 u31_ctrl_sleep_shift; + u32 u31_hhi_mem_pd_mask; + u32 u31_ctrl_iso_shift; + u32 u31_hhi_mem_pd_shift; + u32 usb31_ctrl_rst_bit; struct clk *clk; + struct clk *gate0_clk; + struct clk *gate1_clk; }; union phy3_r1 { From 55894c51b2493ee2b7fe92945aeb797feeb7ea6e Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Thu, 4 Apr 2019 11:01:32 +0800 Subject: [PATCH 0389/1060] CPUFREQ: add cpufreq function for tm2 [1/1] PD#SWPL-6732 Problem: add cpufreq function for tm2. Solution: add cpufreq function for tm2. Verify: test passed on tm2 ab3100 Change-Id: Ic01c39f33ffb64b9bf5e419b8f2c55701b510a94 Signed-off-by: Hong Guo --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 80 +++++++++---------- arch/arm/boot/dts/amlogic/tm2_pxp.dts | 31 ++++--- .../arm/boot/dts/amlogic/tm2_t962e2_ab301.dts | 27 +++---- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 27 +++---- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 27 +++---- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 27 +++---- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 80 +++++++++---------- arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 31 ++++--- .../boot/dts/amlogic/tm2_t962e2_ab301.dts | 27 +++---- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 27 +++---- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 27 +++---- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 27 +++---- 12 files changed, 214 insertions(+), 224 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 01856ea49220..c9ad5f862983 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -548,49 +548,49 @@ compatible = "pwm-regulator"; pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; regulator-name = "vddcpu0"; - regulator-min-microvolt = <689000>; - regulator-max-microvolt = <1049000>; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; regulator-always-on; max-duty-cycle = <1500>; /* Voltage Duty-Cycle */ - voltage-table = <1049000 0>, - <1039000 3>, - <1029000 6>, - <1019000 8>, - <1009000 11>, - <999000 14>, - <989000 17>, - <979000 20>, - <969000 23>, - <959000 26>, - <949000 29>, - <939000 31>, - <929000 34>, - <919000 37>, - <909000 40>, - <899000 43>, - <889000 45>, - <879000 48>, - <869000 51>, - <859000 54>, - <849000 56>, - <839000 59>, - <829000 62>, - <819000 65>, - <809000 68>, - <799000 70>, - <789000 73>, - <779000 76>, - <769000 79>, - <759000 81>, - <749000 84>, - <739000 87>, - <729000 89>, - <719000 92>, - <709000 95>, - <699000 98>, - <689000 100>; - status = "disabled"; + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; + status = "okay"; }; aml_dma { diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts index fe88d70c238b..648341d45d8d 100644 --- a/arch/arm/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -566,58 +566,57 @@ reg-names = "ao_exit","ao"; }; - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <709000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <719000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <729000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <749000>; + opp-microvolt = <780000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <769000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; }; opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <779000>; + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <789000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <829000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <879000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <929000>; + opp-microvolt = <950000>; }; }; @@ -625,7 +624,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts index 3b78519ba49b..1768e753bb6e 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -1094,58 +1094,57 @@ }; }; /*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <749000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <769000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <779000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <789000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <799000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <809000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <849000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <899000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <949000>; + opp-microvolt = <950000>; }; }; @@ -1153,7 +1152,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 1a3d620da86c..3d436215e73e 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1094,58 +1094,57 @@ }; }; /*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <749000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <769000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <779000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <789000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <799000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <809000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <849000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <899000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <949000>; + opp-microvolt = <950000>; }; }; @@ -1153,7 +1152,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 2a9ee68e9a82..5b48c4c40d7a 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1066,58 +1066,57 @@ }; };/*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <709000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <719000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <729000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <749000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <769000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <779000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <789000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <829000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <879000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <929000>; + opp-microvolt = <950000>; }; }; @@ -1125,7 +1124,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index c4cdfba65bf8..c45908ad6fd8 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1066,58 +1066,57 @@ }; };/*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <709000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <719000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <729000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <749000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <769000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <779000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <789000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <829000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <879000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <929000>; + opp-microvolt = <950000>; }; }; @@ -1125,7 +1124,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 4736093d2a41..1de8898ffa69 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -529,49 +529,49 @@ compatible = "pwm-regulator"; pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; regulator-name = "vddcpu0"; - regulator-min-microvolt = <689000>; - regulator-max-microvolt = <1049000>; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; regulator-always-on; max-duty-cycle = <1500>; /* Voltage Duty-Cycle */ - voltage-table = <1049000 0>, - <1039000 3>, - <1029000 6>, - <1019000 8>, - <1009000 11>, - <999000 14>, - <989000 17>, - <979000 20>, - <969000 23>, - <959000 26>, - <949000 29>, - <939000 31>, - <929000 34>, - <919000 37>, - <909000 40>, - <899000 43>, - <889000 45>, - <879000 48>, - <869000 51>, - <859000 54>, - <849000 56>, - <839000 59>, - <829000 62>, - <819000 65>, - <809000 68>, - <799000 70>, - <789000 73>, - <779000 76>, - <769000 79>, - <759000 81>, - <749000 84>, - <739000 87>, - <729000 89>, - <719000 92>, - <709000 95>, - <699000 98>, - <689000 100>; - status = "disabled"; + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; + status = "okay"; }; aml_dma { diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts index 0b22d1e7799c..9f1c72db171a 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -565,58 +565,57 @@ reg-names = "ao_exit","ao"; }; - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <709000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <719000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <729000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <749000>; + opp-microvolt = <780000>; }; opp06 { - opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <769000>; + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; }; opp07 { - opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <779000>; + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <789000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <829000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <879000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <929000>; + opp-microvolt = <950000>; }; }; @@ -624,7 +623,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts index 47f6b868a21a..025cc12d8e4a 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts @@ -1089,58 +1089,57 @@ }; }; /*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <749000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <769000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <779000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <789000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <799000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <809000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <849000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <899000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <949000>; + opp-microvolt = <950000>; }; }; @@ -1148,7 +1147,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 8ca2b8c70f41..63d3604054be 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1089,58 +1089,57 @@ }; }; /*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <729000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <749000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <769000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <779000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <789000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <799000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <809000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <849000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <899000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <949000>; + opp-microvolt = <950000>; }; }; @@ -1148,7 +1147,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 9331d1af0a95..0bb9c1b7b141 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1065,58 +1065,57 @@ }; };/*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <709000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <719000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <729000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <749000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <769000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <779000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <789000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <829000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <879000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <929000>; + opp-microvolt = <950000>; }; }; @@ -1124,7 +1123,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 294704419f60..5311b1d6b615 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1065,58 +1065,57 @@ }; };/*thermal zone end*/ - /*DCDC for MP8756GD*/ cpu_opp_table0: cpu_opp_table0 { compatible = "operating-points-v2"; opp-shared; opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <699000>; + opp-microvolt = <730000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <709000>; + opp-microvolt = <730000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <719000>; + opp-microvolt = <750000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <729000>; + opp-microvolt = <770000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <749000>; + opp-microvolt = <780000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <769000>; + opp-microvolt = <790000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <779000>; + opp-microvolt = <800000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <789000>; + opp-microvolt = <810000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <829000>; + opp-microvolt = <850000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <879000>; + opp-microvolt = <900000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <929000>; + opp-microvolt = <950000>; }; }; @@ -1124,7 +1123,7 @@ compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; pinctrl-0 = <&pwm_ao_d_pins3>; - status = "disabled"; + status = "okay"; }; tuner: tuner { From 68f97f7e517e5aef2829b37be59417423c0960c5 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Thu, 4 Apr 2019 11:02:16 +0800 Subject: [PATCH 0390/1060] dts: rename tm2_t962e2_ab301.dts to tm2_t962x3_ab301.dts. [1/1] PD#SWPL-6678 Problem: rename tm2_t962e2_ab301.dts Solution: rename tm2_t962e2_ab301.dts to tm2_t962x3_ab301.dts. Verify: build pass. Change-Id: Ia320b36323a56b5ae496fbd44ffcd2b38ada8ec1 Signed-off-by: Jianxiong Pan --- .../dts/amlogic/{tm2_t962e2_ab301.dts => tm2_t962x3_ab301.dts} | 0 .../dts/amlogic/{tm2_t962e2_ab301.dts => tm2_t962x3_ab301.dts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename arch/arm/boot/dts/amlogic/{tm2_t962e2_ab301.dts => tm2_t962x3_ab301.dts} (100%) rename arch/arm64/boot/dts/amlogic/{tm2_t962e2_ab301.dts => tm2_t962x3_ab301.dts} (100%) diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts similarity index 100% rename from arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts rename to arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts similarity index 100% rename from arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts rename to arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts From 59ce4d540680d72bcf1f008315e2703af656e01c Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Thu, 4 Apr 2019 20:12:31 +0800 Subject: [PATCH 0391/1060] vpp: tm2: add vd2 function for tm2 [2/2] PD#SWPL-6615 Problem: Need vd2 function Solution: add vd2 function for tm2: 1.vd2 pps scaler 2.disable vd2 afbc Verify: test pass on tm2 skt Change-Id: I7af5de741b90e443ee065218aecb823ef06d66a7 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 37 +++- drivers/amlogic/media/video_sink/vpp.c | 187 +++++++------------ include/linux/amlogic/media/video_sink/vpp.h | 9 +- 3 files changed, 98 insertions(+), 135 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index d3a97f1deb50..5722a3b2e2b4 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -3190,15 +3190,10 @@ static void pip_toggle_frame(struct vframe_s *vf) &pip_frame_parms[1] : &pip_frame_parms[0]; update_layer_info(1); - if (legacy_vpp || is_meson_tl1_cpu()) - iret = vpp_set_filters_no_scaler( - &glayer_info[1], vf, - nextpip_frame_par, vinfo, 1); - else - iret = vpp_set_filters( - &glayer_info[1], vf, - nextpip_frame_par, vinfo, - true, 1); + iret = vpp_set_filters( + &glayer_info[1], vf, + nextpip_frame_par, vinfo, + true, 1); memcpy(&gPic_info[1], &vf->pic_mode, sizeof(struct vframe_pic_mode_s)); @@ -12887,6 +12882,23 @@ static int __init video_init(void) glayer_info[i].zorder = reference_zorder - 2 + i; glayer_info[i].cur_sel_port = i; glayer_info[i].last_sel_port = i; + if (legacy_vpp) { + glayer_info[i].afbc_support = true; + glayer_info[i].pps_support = + (i == 0) ? true : false; + } else if (is_meson_tl1_cpu()) { + glayer_info[i].afbc_support = + (i == 0) ? true : false; + glayer_info[i].pps_support = + (i == 0) ? true : false; + } else if (is_meson_tm2_cpu()) { + glayer_info[i].afbc_support = + (i == 0) ? true : false; + glayer_info[i].pps_support = true; + } else { + glayer_info[i].afbc_support = true; + glayer_info[i].pps_support = true; + } } if (legacy_vpp) @@ -12902,6 +12914,13 @@ static int __init video_init(void) LAYER0_AFBC | LAYER0_SCALER | LAYER0_AVAIL; + else if (is_meson_tm2_cpu()) + layer_cap = + LAYER1_SCALER | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; else layer_cap = LAYER1_AFBC | diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 72d1c6966d09..24f493b4d299 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -597,6 +597,10 @@ static unsigned int custom_ar; MODULE_PARM_DESC(custom_ar, "custom_ar"); module_param(custom_ar, uint, 0664); +static unsigned int force_no_compress; +MODULE_PARM_DESC(force_no_compress, "force_no_compress"); +module_param(force_no_compress, uint, 0664); + /* *test on txlx: *Time_out = (V_out/V_screen_total)/FPS_out; @@ -886,6 +890,7 @@ static int vpp_set_filters_internal( s32 vpp_zoom_center_x, vpp_zoom_center_y; u32 crop_ratio = 1; u32 crop_left, crop_right, crop_top, crop_bottom; + bool no_compress = false; if (!input) return VppFilter_Fail; @@ -1424,9 +1429,17 @@ RESTART: if ((vf->type & VIDTYPE_COMPRESS) && (vf->canvas0Addr != 0) && - (next_frame_par->vscale_skip_count > 1) && (!next_frame_par->nocomp)) { - if (vpp_flags & VPP_FLAG_MORE_LOG) + if ((next_frame_par->vscale_skip_count > 1) + || !input->afbc_support + || force_no_compress) + no_compress = true; + } else + no_compress = false; + + if (no_compress) { + if ((vpp_flags & VPP_FLAG_MORE_LOG) + && input->afbc_support) pr_info( "layer%d: Try DW buffer for compressed frame scaling.\n", input->layer_id); @@ -2502,6 +2515,7 @@ static int vpp_set_filters_no_scaler_internal( int ret = VppFilter_Success; u32 crop_ratio = 1; u32 crop_left, crop_right, crop_top, crop_bottom; + bool no_compress = false; if (!input) return VppFilter_Fail; @@ -2818,9 +2832,17 @@ RESTART: if ((vf->type & VIDTYPE_COMPRESS) && (vf->canvas0Addr != 0) && - (next_frame_par->vscale_skip_count > 1) && (!next_frame_par->nocomp)) { - if (vpp_flags & VPP_FLAG_MORE_LOG) + if ((next_frame_par->vscale_skip_count > 1) + || !input->afbc_support + || force_no_compress) + no_compress = true; + } else + no_compress = false; + + if (no_compress) { + if ((vpp_flags & VPP_FLAG_MORE_LOG) + && input->afbc_support) pr_info( "layer%d: Try DW buffer for compressed frame scaling.\n", input->layer_id); @@ -2907,34 +2929,46 @@ int vpp_set_filters( next_frame_par->VPP_post_blend_vd_h_start_ = 0; next_frame_par->VPP_postproc_misc_ = 0x200; -#ifdef TV_3D_FUNCTION_OPEN next_frame_par->vscale_skip_count = 0; next_frame_par->hscale_skip_count = 0; + + if (vf->type & VIDTYPE_COMPRESS) { + src_width = vf->compWidth; + src_height = vf->compHeight; + } else { + src_width = vf->width; + src_height = vf->height; + } + +#ifdef TV_3D_FUNCTION_OPEN /* *check 3d mode change in display buffer or 3d type *get the source size according to 3d mode */ - if (process_3d_type & MODE_3D_ENABLE) { - vpp_get_video_source_size(&src_width, &src_height, - process_3d_type, vf, next_frame_par); - } else { - if (vf->type & VIDTYPE_COMPRESS) { - src_width = vf->compWidth; - src_height = vf->compHeight; + if (local_input.layer_id == 0) { + if (process_3d_type & MODE_3D_ENABLE) { + vpp_get_video_source_size( + &src_width, &src_height, + process_3d_type, + vf, next_frame_par); } else { - src_width = vf->width; - src_height = vf->height; + next_frame_par->vpp_3d_mode = + VPP_3D_MODE_NULL; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 0; } + next_frame_par->trans_fmt = vf->trans_fmt; + get_vpp_3d_mode(process_3d_type, + next_frame_par->trans_fmt, + &next_frame_par->vpp_3d_mode); + if (local_input.vpp_3d_scale) + next_frame_par->vpp_3d_scale = 1; + } else { next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; next_frame_par->vpp_2pic_mode = 0; next_frame_par->vpp_3d_scale = 0; + next_frame_par->trans_fmt = vf->trans_fmt; } - next_frame_par->trans_fmt = vf->trans_fmt; - get_vpp_3d_mode(process_3d_type, - next_frame_par->trans_fmt, - &next_frame_par->vpp_3d_mode); - if (local_input.vpp_3d_scale) - next_frame_par->vpp_3d_scale = 1; amlog_mask(LOG_MASK_VPP, "%s: src_width %u,src_height %u.\n", __func__, src_width, src_height); #endif @@ -2970,15 +3004,6 @@ int vpp_set_filters( if (vf->type & VIDTYPE_VSCALE_DISABLE) vpp_flags |= VPP_FLAG_VSCALE_DISABLE; -#ifndef TV_3D_FUNCTION_OPEN - if (vf->type & VIDTYPE_COMPRESS) { - src_width = vf->compWidth; - src_height = vf->compHeight; - } else { - src_width = vf->width; - src_height = vf->height; - } -#endif if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) && !disable_adapted) { @@ -3010,6 +3035,9 @@ int vpp_set_filters( } } + if (!local_input.pps_support) + wide_mode = VIDEO_WIDEOPTION_NORMAL; + /* don't restore the wide mode */ /* input->wide_mode = wide_mode; */ vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); @@ -3024,10 +3052,16 @@ int vpp_set_filters( next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; - ret = vpp_set_filters_internal( - &local_input, src_width, src_height, - vinfo->width, vinfo->height, - vinfo, vpp_flags, next_frame_par, vf); + if (local_input.pps_support) + ret = vpp_set_filters_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); + else + ret = vpp_set_filters_no_scaler_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); /*config super scaler after set next_frame_par is calc ok for pps*/ if (local_input.layer_id == 0) @@ -3039,93 +3073,6 @@ int vpp_set_filters( return ret; } -int vpp_set_filters_no_scaler( - struct disp_info_s *input, - struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo, u32 op_flag) -{ - u32 src_width = 0; - u32 src_height = 0; - u32 vpp_flags = 0; - u32 aspect_ratio = 0; - u32 wide_mode; - int ret = VppFilter_Fail; - struct disp_info_s local_input; - - if (!input) - return ret; - - WARN_ON(vinfo == NULL); - - /* use local var to avoid the input data be overwriten */ - memcpy(&local_input, input, sizeof(struct disp_info_s)); - /* wide_mode = local_input.wide_mode; */ - wide_mode = VIDEO_WIDEOPTION_NORMAL; - next_frame_par->VPP_post_blend_vd_v_start_ = 0; - next_frame_par->VPP_post_blend_vd_h_start_ = 0; - - next_frame_par->VPP_postproc_misc_ = 0x200; - next_frame_par->vscale_skip_count = 0; - next_frame_par->hscale_skip_count = 0; - if (vf->type & VIDTYPE_COMPRESS) { - src_width = vf->compWidth; - src_height = vf->compHeight; - } else { - src_width = vf->width; - src_height = vf->height; - } -#ifdef TV_3D_FUNCTION_OPEN - next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; - next_frame_par->vpp_2pic_mode = 0; - next_frame_par->vpp_3d_scale = 0; - next_frame_par->trans_fmt = vf->trans_fmt; -#endif - - if (vf->type & VIDTYPE_INTERLACE) - vpp_flags = VPP_FLAG_INTERLACE_IN; - - if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) - && !disable_adapted) { - if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { - /* from wss, need add global setting */ - local_input.crop_top += vf->pic_mode.vs; - local_input.crop_left += vf->pic_mode.hs; - local_input.crop_bottom += vf->pic_mode.ve; - local_input.crop_right += vf->pic_mode.he; - } else { - /* from PQ database, final setting */ - local_input.crop_top = vf->pic_mode.vs; - local_input.crop_left = vf->pic_mode.hs; - local_input.crop_bottom = vf->pic_mode.ve; - local_input.crop_right = vf->pic_mode.he; - } - } - - aspect_ratio = - (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) - >> DISP_RATIO_ASPECT_RATIO_BIT; - - /* don't restore the wide mode */ - /* input->wide_mode = wide_mode; */ - vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); - - if (vinfo->field_height != vinfo->height) - vpp_flags |= VPP_FLAG_INTERLACE_OUT; - - if (op_flag & 1) - vpp_flags |= VPP_FLAG_MORE_LOG; - - next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; - next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; - next_frame_par->VPP_post_blend_h_size_ = vinfo->width; - - ret = vpp_set_filters_no_scaler_internal( - &local_input, src_width, src_height, - vinfo->width, vinfo->height, - vinfo, vpp_flags, next_frame_par, vf); - return ret; -} s32 vpp_set_nonlinear_factor( struct disp_info_s *info, u32 f) { diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index 22a143b596a2..3520e9c9c49c 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -188,6 +188,9 @@ struct disp_info_s { u32 zorder; u32 cur_sel_port; u32 last_sel_port; + + bool afbc_support; + bool pps_support; }; enum select_scaler_path_e { @@ -288,12 +291,6 @@ extern int vpp_set_filters( const struct vinfo_s *vinfo, bool bypass_sr, u32 op_flag); -extern int vpp_set_filters_no_scaler( - struct disp_info_s *input, - struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo, u32 op_flag); - extern s32 vpp_set_nonlinear_factor( struct disp_info_s *info, u32 f); From 672ffd58fb645176cb69303b8f53c4e2603c1ada Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Thu, 4 Apr 2019 08:13:03 -0400 Subject: [PATCH 0392/1060] hdr: TM2 bringup disable lc/cm [1/1] PD#SWPL-6720 Problem: video display color green Solution: TM2 bringup disable lc/cm Verify: verify on TM2 Change-Id: I2d8222c92f8181710a13a56f650655281fac5115 Signed-off-by: MingLiang Dong --- arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 2 +- arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 2 +- arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 2 +- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts | 2 +- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts | 2 +- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts | 2 +- drivers/amlogic/media/enhancement/amvecm/local_contrast.c | 2 +- drivers/amlogic/media/video_sink/video.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 3d436215e73e..f709ee48da04 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -484,7 +484,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 5b48c4c40d7a..e2922a8fe025 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -472,7 +472,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 1768e753bb6e..d6355aa0a47a 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -484,7 +484,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index c45908ad6fd8..39b494fc2c7b 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -472,7 +472,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 63d3604054be..bad6ec73d05c 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -479,7 +479,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 0bb9c1b7b141..c25a7523a8e7 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -471,7 +471,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 025cc12d8e4a..767bcb535032 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -479,7 +479,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 5311b1d6b615..6deb65398333 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -471,7 +471,7 @@ status = "okay"; gamma_en = <1>;/*1:enabel ;0:disable*/ wb_en = <1>;/*1:enabel ;0:disable*/ - cm_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ wb_sel = <1>;/*1:mtx ;0:gainoff*/ vlock_en = <1>;/*1:enable;0:disable*/ vlock_mode = <0x4>; diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 39a36af6adda..a7efc935df28 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -38,7 +38,7 @@ int amlc_debug; pr_info("AMVE: " fmt, ## args);\ } while (0) -int lc_en = 1; +int lc_en; int lc_demo_mode; int lc_en_chflg = 0xff; static int lc_flag = 0xff; diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 5722a3b2e2b4..b3f97e5479f9 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -167,7 +167,7 @@ static DEFINE_MUTEX(omx_mutex); #define DURATION_GCD 750 -static bool bypass_cm; +static bool bypass_cm = 1; static bool bypass_pps = true; /*For 3D usage ----0: mbx 1: tv */ From 5dd838b1232529cfc36fe18bd037026c64c2149a Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Fri, 5 Apr 2019 01:54:50 -0400 Subject: [PATCH 0393/1060] amvecm: TM2 bringup LC/CM 12bit config [1/1] PD#SWPL-6720 Problem: video display color green Solution: TM2 bringup LC/cm 12bit config Verify: verify on TM2 Change-Id: I42b37e04566ebb5e2f6e7da3f0ade240471cdb33 Signed-off-by: MingLiang Dong --- .../amlogic/media/enhancement/amvecm/amvecm.c | 55 +++++++++++---- .../media/enhancement/amvecm/local_contrast.c | 70 +++++++++++++------ .../media/enhancement/amvecm/local_contrast.h | 2 +- drivers/amlogic/media/video_sink/video.c | 2 +- 4 files changed, 93 insertions(+), 36 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index d556f499abfd..3b7aa8548104 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5005,16 +5005,36 @@ static void get_cm_hist(enum cm_hist_e hist_sel) kfree(hist); } -static void cm_init_config(void) +static void cm_init_config(int bitdepth) { - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x40400); + if (bitdepth == 10) { + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x40400); + } else if (bitdepth == 12) { + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0xfff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0xfff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0xfff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x100400); + } else { + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x40400); + } } static const char *amvecm_debug_usage_str = { @@ -6176,9 +6196,12 @@ free_buf: /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ void init_pq_setting(void) { + + int bitdepth; + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_tl1_cpu()) + is_meson_tl1_cpu() || is_meson_tm2_cpu()) goto tvchip_pq_setting; else if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { sr_offset[0] = SR0_OFFSET; @@ -6194,14 +6217,20 @@ void init_pq_setting(void) return; tvchip_pq_setting: - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (is_meson_tl1_cpu()) + bitdepth = 10; + else if (is_meson_tm2_cpu()) + bitdepth = 12; + else + bitdepth = 12; /*sr0 & sr1 register shfit*/ sr_offset[0] = SR0_OFFSET; sr_offset[1] = SR1_OFFSET; /*cm register init*/ - cm_init_config(); + cm_init_config(bitdepth); /*lc init*/ - lc_init(); + lc_init(bitdepth); } /*probe close sr0 peaking for switch on video*/ WRITE_VPP_REG_BITS(VPP_SRSHARP0_CTRL, 1, 0, 1); diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index a7efc935df28..472ad615b588 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -38,7 +38,7 @@ int amlc_debug; pr_info("AMVE: " fmt, ## args);\ } while (0) -int lc_en; +int lc_en = 1; int lc_demo_mode; int lc_en_chflg = 0xff; static int lc_flag = 0xff; @@ -119,7 +119,8 @@ static unsigned int lc_satur_off[63] = { /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, enum lc_mtx_csc_e mtx_csc, - int mtx_en) + int mtx_en, + int bitdepth) { unsigned int matrix_coef00_01 = 0; unsigned int matrix_coef02_10 = 0; @@ -182,7 +183,16 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_coef11_12, 0xed601c2); WRITE_VPP_REG(matrix_coef20_21, 0x01c20e87); WRITE_VPP_REG(matrix_coef22, 0x0000fb7); - WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else if (bitdepth == 12) { + WRITE_VPP_REG(matrix_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } else { + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99); @@ -202,7 +212,16 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_coef11_12, 0xf9c0f30); WRITE_VPP_REG(matrix_coef20_21, 0x12a0204); WRITE_VPP_REG(matrix_coef22, 0x0); - WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else if (bitdepth == 12) { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } else { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); @@ -356,7 +375,8 @@ static void lc_stts_en(int enable, int eol_en, int hist_mode, int lpf_en, - int din_sel) + int din_sel, + int bitdepth) { int data32; @@ -369,7 +389,7 @@ static void lc_stts_en(int enable, data32 = data32 | ((lpf_en & 0x1) << 21); WRITE_VPP_REG(LC_STTS_HIST_REGION_IDX, data32); - lc_mtx_set(STAT_MTX, LC_MTX_YUV709L_RGB, enable); + lc_mtx_set(STAT_MTX, LC_MTX_YUV709L_RGB, enable, bitdepth); WRITE_VPP_REG_BITS(LC_STTS_CTRL0, din_sel, 3, 3); /*lc hist stts enable*/ @@ -459,7 +479,7 @@ static void lc_blk_bdry_config(unsigned int height, unsigned int width) } static void lc_top_config(int enable, int h_num, int v_num, - unsigned int height, unsigned int width) + unsigned int height, unsigned int width, int bitdepth) { /*lcinput_ysel*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_INPUT_MUX, 5, 4, 3); @@ -481,8 +501,8 @@ static void lc_top_config(int enable, int h_num, int v_num, WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 16, 1); /*lc enable need set at last*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, enable, 4, 1); - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); } static void lc_disable(void) @@ -499,7 +519,8 @@ static void lc_disable(void) static void lc_config(int enable, struct vframe_s *vf, unsigned int sps_h_en, - unsigned int sps_v_en) + unsigned int sps_v_en, + int bitdepth) { int h_num, v_num; unsigned int height, width; @@ -529,14 +550,14 @@ static void lc_config(int enable, vf_width = vf->width; if (vf_height < 720) { - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); } else { - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); } - lc_top_config(enable, h_num, v_num, height, width); + lc_top_config(enable, h_num, v_num, height, width, bitdepth); if (sps_h_en == 1) width /= 2; @@ -545,7 +566,7 @@ static void lc_config(int enable, lc_curve_ctrl_config(enable, height, width); lc_stts_blk_config(enable, height, width); - lc_stts_en(enable, height, width, 0, 0, 1, 1, 4); + lc_stts_en(enable, height, width, 0, 0, 1, 1, 4, bitdepth); } static void read_lc_curve(int blk_vnum, int blk_hnum) @@ -1203,7 +1224,7 @@ static void lc_prt_curve(void) } } -void lc_init(void) +void lc_init(int bitdepth) { int h_num, v_num; unsigned int height, width; @@ -1240,9 +1261,7 @@ void lc_init(void) if (!lc_en) return; - lc_top_config(0, h_num, v_num, height, width); - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + lc_top_config(0, h_num, v_num, height, width, bitdepth); WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); /*default LC low parameters*/ @@ -1285,9 +1304,18 @@ void lc_process(struct vframe_s *vf, unsigned int sps_v_en) { int blk_hnum, blk_vnum, dwTemp; + int bitdepth; if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) return; + + if (is_meson_tl1_cpu()) + bitdepth = 10; + else if (is_meson_tm2_cpu()) + bitdepth = 12; + else + bitdepth = 12; + if (!lc_en) { lc_disable(); return; @@ -1311,7 +1339,7 @@ void lc_process(struct vframe_s *vf, dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); blk_hnum = (dwTemp >> 8) & 0x1f; blk_vnum = (dwTemp) & 0x1f; - lc_config(lc_en, vf, sps_h_en, sps_v_en); + lc_config(lc_en, vf, sps_h_en, sps_v_en, bitdepth); /*get each block curve*/ read_lc_curve(blk_vnum, blk_hnum); lc_read_region(blk_vnum, blk_hnum); diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index 3dcf9b8f06a4..f62bd3b75966 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -92,7 +92,7 @@ extern int *lc_hist;/*12*8*17*/ extern struct ve_lc_curve_parm_s lc_curve_parm_load; extern struct lc_alg_param_s lc_alg_parm; -extern void lc_init(void); +extern void lc_init(int bitdepth); extern void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en); diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index b3f97e5479f9..5722a3b2e2b4 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -167,7 +167,7 @@ static DEFINE_MUTEX(omx_mutex); #define DURATION_GCD 750 -static bool bypass_cm = 1; +static bool bypass_cm; static bool bypass_pps = true; /*For 3D usage ----0: mbx 1: tv */ From ee4dfbabb0fb9e11b381a3027adebab0d8f53b09 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Sat, 6 Apr 2019 15:34:56 +0800 Subject: [PATCH 0394/1060] vdin: close afbc mode current stage for tm2 [1/1] PD#SWPL-6701 Problem: afbc abnormal Solution: close afbc at current stage Verify: test pass on tm2 ab311 Change-Id: I5978caa5decb1536c2240467115395f422637c39 Signed-off-by: Nian Jing --- arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 2 +- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index f709ee48da04..d813ac66567c 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -541,7 +541,7 @@ * 0 -- afbce compression-lossy disable * 1 -- afbce compression-lossy enable */ - afbce_bit_mode = <0x1>; + afbce_bit_mode = <0x0>; }; vdin@1 { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index d6355aa0a47a..94f9ecfd129e 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -541,7 +541,7 @@ * 0 -- afbce compression-lossy disable * 1 -- afbce compression-lossy enable */ - afbce_bit_mode = <0x1>; + afbce_bit_mode = <0x0>; }; vdin@1 { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index bad6ec73d05c..697ebffeaed9 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -536,7 +536,7 @@ * 0 -- afbce compression-lossy disable * 1 -- afbce compression-lossy enable */ - afbce_bit_mode = <0x1>; + afbce_bit_mode = <0x0>; }; vdin@1 { From a4180c7ed84d91ed227cfc96818a63f3e4da19fd Mon Sep 17 00:00:00 2001 From: "qingwei.xu" Date: Mon, 8 Apr 2019 13:19:42 +0800 Subject: [PATCH 0395/1060] partion: increase vendor partion size for 32bit [1/1] PD#SWPL-6373 Problem: increase vendor partion size for 32bit kernel Solution: increase vendor partion size for 32bit kernel Verify: verify by t962e2_ab311 Change-Id: Ifb26b2b9f1ec4712177a5ca1a112d7c60ec4e70b Signed-off-by: qingwei.xu --- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f2c574203d53..f9dd1c7cbb93 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x19000000>; mask = <1>; }; odm:odm From 5e65139400c9df45dc5cb105cdaa5ae8fabdf45a Mon Sep 17 00:00:00 2001 From: "qingwei.xu" Date: Mon, 8 Apr 2019 13:40:58 +0800 Subject: [PATCH 0396/1060] =?UTF-8?q?dts:=20Optimization=20t962e2=5Fskt?= =?UTF-8?q?=E3=80=81t962x3=5Fskt=20logo=20CMA=20memory=20layout=20[1/1]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-6373 Problem: Optimization logo CMA memory layout Solution: Optimization logo CMA memory layout Verify: t962e2_skt Change-Id: I03906452d35881ccd4e463715e5be7580740816d Signed-off-by: qingwei.xu --- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 25 ++++++++++++------- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 25 ++++++++++++------- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 25 ++++++++++++------- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 25 ++++++++++++------- 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index e2922a8fe025..9c3cb06bf253 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -68,6 +68,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -75,7 +91,6 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ @@ -86,14 +101,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x800000>; - alignment = <0x400000>; - alloc-ranges = <0x7f800000 0x800000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 39b494fc2c7b..024164434a52 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -68,6 +68,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -75,7 +91,6 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ @@ -86,14 +101,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x800000>; - alignment = <0x400000>; - alloc-ranges = <0x7f800000 0x800000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index c25a7523a8e7..3d6c47c4a756 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -68,6 +68,22 @@ alloc-ranges = <0x0 0x05000000 0x0 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -75,7 +91,6 @@ size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; - alloc-ranges = <0x0 0x30000000 0x0 0x50000000>; }; /* codec shared reserved */ @@ -86,14 +101,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x800000>; - alignment = <0x0 0x400000>; - alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 6deb65398333..0db1dd0b4d53 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -68,6 +68,22 @@ alloc-ranges = <0x0 0x05000000 0x0 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -75,7 +91,6 @@ size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; - alloc-ranges = <0x0 0x30000000 0x0 0x50000000>; }; /* codec shared reserved */ @@ -86,14 +101,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x800000>; - alignment = <0x0 0x400000>; - alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; From 81b9387ac34d877edbd584fca4bb05933ce71029 Mon Sep 17 00:00:00 2001 From: zhiqiang liang Date: Thu, 4 Apr 2019 15:58:50 +0800 Subject: [PATCH 0397/1060] soc: add mailbox interface for dsp sec reg ops [3/3] PD#SWPL-6583 Problem: tm2 dsp bring up Solution: add the mbox interface Verify: AB311 Change-Id: Ifddb9bb0b22c651c5a0e02c2200874dcaa6dc2ce Signed-off-by: zhiqiang liang --- drivers/amlogic/mailbox/scpi_protocol.c | 24 ++++++++++++++++++++++++ include/linux/amlogic/scpi_protocol.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/drivers/amlogic/mailbox/scpi_protocol.c b/drivers/amlogic/mailbox/scpi_protocol.c index 22883ee98e59..cc5f3692d15d 100644 --- a/drivers/amlogic/mailbox/scpi_protocol.c +++ b/drivers/amlogic/mailbox/scpi_protocol.c @@ -120,6 +120,7 @@ static int high_priority_cmds[] = { SCPI_CMD_SENSOR_CFG_BOUNDS, SCPI_CMD_WAKEUP_REASON_GET, SCPI_CMD_WAKEUP_REASON_CLR, + SCPI_CMD_INIT_DSP, }; static struct scpi_dvfs_info *scpi_opps[MAX_DVFS_DOMAINS]; @@ -556,6 +557,29 @@ int scpi_clr_wakeup_reason(void) } EXPORT_SYMBOL_GPL(scpi_clr_wakeup_reason); +int scpi_init_dsp_cfg0(u32 id, u32 addr, u32 cfg0) +{ + struct scpi_data_buf sdata; + struct mhu_data_buf mdata; + u32 temp = 0; + struct __packed { + u32 id; + u32 addr; + u32 cfg0; + } buf; + buf.id = id; + buf.addr = addr; + buf.cfg0 = cfg0; + + SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_NONE, + SCPI_CMD_INIT_DSP, buf, temp); + if (scpi_execute_cmd(&sdata)) + return -EPERM; + + return 0; +} +EXPORT_SYMBOL_GPL(scpi_init_dsp_cfg0); + int scpi_get_cec_val(enum scpi_std_cmd index, u32 *p_cec) { struct scpi_data_buf sdata; diff --git a/include/linux/amlogic/scpi_protocol.h b/include/linux/amlogic/scpi_protocol.h index 1fe5a19eb67d..a9d60eb74448 100644 --- a/include/linux/amlogic/scpi_protocol.h +++ b/include/linux/amlogic/scpi_protocol.h @@ -72,6 +72,7 @@ enum scpi_std_cmd { SCPI_CMD_WAKEUP_REASON_CLR = 0X31, SCPI_CMD_GET_ETHERNET_CALC = 0x32, SCPI_CMD_GET_CPUINFO = 0x33, + SCPI_CMD_INIT_DSP = 0x34, SCPI_CMD_GET_CEC1 = 0xB4, SCPI_CMD_GET_CEC2 = 0xB5, @@ -113,4 +114,5 @@ int scpi_clr_wakeup_reason(void); int scpi_get_cec_val(enum scpi_std_cmd index, u32 *p_cec); u8 scpi_get_ethernet_calc(void); int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol); +int scpi_init_dsp_cfg0(u32 id, u32 addr, u32 cfg0); #endif /*_SCPI_PROTOCOL_H_*/ From b8c724e4f58f66e55440a9120a5f2ba66ac90355 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Mon, 8 Apr 2019 16:18:02 +0800 Subject: [PATCH 0398/1060] unifykey: securitykey: enable securitykey by default [1/1] PD#SWPL-6823 Problem: Securitykey driver fail to probe Solution: Enable securitykey in DTS by default Verify: TM2 Change-Id: I962f53c0e786fae85dc856e382b060f4f5f7347c Signed-off-by: Jiamin Ma --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 20 -------------------- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 20 -------------------- 2 files changed, 40 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index c9ad5f862983..db0144b63f9c 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -277,26 +277,6 @@ reg-names = "PREG_STICKY_REG8"; }; - securitykey { - compatible = "amlogic, securitykey"; - status = "disabled"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - vpu { compatible = "amlogic, vpu-tm2"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 1de8898ffa69..3b75b440d9f0 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -258,26 +258,6 @@ reg-names = "PREG_STICKY_REG8"; }; - securitykey { - compatible = "amlogic, securitykey"; - status = "disabled"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - vpu { compatible = "amlogic, vpu-tm2"; status = "okay"; From 53f2f5affd9aec2cdf3fa224b9884f63539be147 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Mon, 8 Apr 2019 16:51:25 +0800 Subject: [PATCH 0399/1060] pcie: bringup TM2 pcie [1/1] PD#SWPL-5609 Problem: bringup TM2 pcie. Solution: bringup TM2 pcie,all boards. Verify: TM2 Change-Id: I5477eeda03313c660b8162943ca33ff56bfc7e3c Signed-off-by: Yue Wang --- drivers/amlogic/pci/pcie-amlogic-v2.c | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/amlogic/pci/pcie-amlogic-v2.c b/drivers/amlogic/pci/pcie-amlogic-v2.c index 2bb169ce0efa..465f27bf529a 100644 --- a/drivers/amlogic/pci/pcie-amlogic-v2.c +++ b/drivers/amlogic/pci/pcie-amlogic-v2.c @@ -221,12 +221,20 @@ static ssize_t store_pcie_cr_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct platform_device *pdev = to_platform_device(dev); + struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); u32 reg; u32 val; + int j; if (kstrtouint(buf, 0, ®) != 0) return -EINVAL; + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); + val = amlogic_phy_cr_readl(reg); dev_info(dev, "reg 0x%x value is 0x%x\n", reg, val); @@ -247,11 +255,14 @@ static ssize_t store_pcie_cr_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct platform_device *pdev = to_platform_device(dev); + struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); unsigned int reg, val; int ret = 0; char *pstr; char *pend; char *strbuf; + int j; if (count > 40) return -EINVAL; @@ -278,6 +289,12 @@ static ssize_t store_pcie_cr_write(struct device *dev, ret = -EINVAL; goto cr_end; } + + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); + amlogic_phy_cr_writel(val, reg); ret = count; cr_end: @@ -640,6 +657,7 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, struct pcie_port *pp = &amlogic_pcie->pp; struct device *dev = pp->dev; int ret; + int j; if (IS_ENABLED(CONFIG_PCI_MSI)) { pp->msi_irq = platform_get_irq(pdev, 0); @@ -674,6 +692,10 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, clk_disable_unprepare(amlogic_pcie->clk); clk_disable_unprepare(amlogic_pcie->phy_clk); dev_err(pp->dev, "power down pcie phy\n"); + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); writel(0x1d, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 0; } @@ -1068,6 +1090,7 @@ static int amlogic_pcie_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); + int j; if (!amlogic_pcie->pm_enable) { dev_info(dev, "don't noirq suspend amlogic pcie\n"); @@ -1082,6 +1105,10 @@ static int amlogic_pcie_suspend_noirq(struct device *dev) if (amlogic_pcie->device_attch == 0) { dev_info(dev, "controller power off, no suspend noirq\n"); if (amlogic_pcie->pcie_num == 1) { + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); writel(0x1d, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 0; } @@ -1108,6 +1135,7 @@ static int amlogic_pcie_resume_noirq(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); unsigned long rate = 100000000; + int j; if (!amlogic_pcie->pm_enable) { dev_info(dev, "don't noirq resume amlogic pcie\n"); @@ -1120,6 +1148,10 @@ static int amlogic_pcie_resume_noirq(struct device *dev) } if (amlogic_pcie->pcie_num == 1) { + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); writel(0x1c, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 1; udelay(500); From cf5db798c43bc50b8b792f2a5583a3840f9ab3e1 Mon Sep 17 00:00:00 2001 From: "kunpeng.tang" Date: Mon, 8 Apr 2019 15:06:08 +0800 Subject: [PATCH 0400/1060] dts: tm2 bring up,add h.264 encoder support [1/1] PD#SWPL-6373 Problem: tm2 has no h.264 encoder device path Solution: add in mesontm2.dtsi Verify: AB311 Change-Id: I7a3698eecb6917d3f4e698868cf3b66e7f350fad Signed-off-by: kunpeng.tang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 7 +++++++ arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index db0144b63f9c..a0d7570b635c 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1368,6 +1368,13 @@ "mailbox_1", "mailbox_2"; }; + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; canvas: canvas { compatible = "amlogic, meson, canvas"; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 3b75b440d9f0..d53c942e31db 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1349,6 +1349,14 @@ "mailbox_2"; }; + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + canvas: canvas { compatible = "amlogic, meson, canvas"; status = "okay"; From 699b1776d5a4beb4cdcdba0b41d4fd00bb49b493 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Thu, 14 Mar 2019 16:05:59 +0800 Subject: [PATCH 0401/1060] dv: add tm2 interface [1/1] PD#SWPL-6338 Problem: need to add dv interface in tm2 Solution: choose dv in UI and play films, observe the video and graphic Verify: ab301 verify ok Change-Id: I5d85b195254a16bcc9046d258728bd41d8a809d5 Signed-off-by: Yi Zhou --- arch/arm/boot/dts/amlogic/tm2_pxp.dts | 7 + .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 7 + .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 7 + .../arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 7 + .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 7 + arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 7 + .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 7 + .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 7 + .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 7 + .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 7 + .../amdolby_vision/amdolby_vision.c | 1415 ++++++++++------- .../amdolby_vision/amdolby_vision.h | 1 + .../amvecm/arch/vpp_dolbyvision_regs.h | 149 +- .../media/amdolbyvision/dolby_vision.h | 5 + 14 files changed, 967 insertions(+), 673 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts index 648341d45d8d..d1165eee0c64 100644 --- a/arch/arm/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -419,6 +419,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index d813ac66567c..648dc4380cdd 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -500,6 +500,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 9c3cb06bf253..30960e570255 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -495,6 +495,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 94f9ecfd129e..1caa667f7b2c 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -500,6 +500,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 024164434a52..e2941a2b1789 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -495,6 +495,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts index 9f1c72db171a..5951e7526823 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -419,6 +419,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 697ebffeaed9..4ba3670eda9f 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -495,6 +495,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 3d6c47c4a756..c6c153104115 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -494,6 +494,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 767bcb535032..509130f8ccb6 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -495,6 +495,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 0db1dd0b4d53..8b9f56eea72b 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -494,6 +494,13 @@ vlock_line_limit = <3>; }; + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + vdin@0 { compatible = "amlogic, vdin"; /*memory-region = <&vdin0_cma_reserved>;*/ diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index d578896b2020..e6c09c8568a9 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -57,7 +57,8 @@ DEFINE_SPINLOCK(dovi_lock); -static const struct dolby_vision_func_s *p_funcs; +static const struct dolby_vision_func_s *p_funcs_stb; +static const struct dolby_vision_func_s *p_funcs_tv; #define AMDOLBY_VISION_NAME "amdolby_vision" #define AMDOLBY_VISION_CLASS_NAME "amdolby_vision" @@ -994,13 +995,7 @@ MODULE_PARM_DESC(debug_dolby_frame, "\n debug_dolby_frame\n"); #define dump_enable \ ((debug_dolby_frame >= 0xffff) || \ (debug_dolby_frame + 1 == frame_count)) -static int is_graphics_output_off(void) -{ - if (is_meson_g12()) - return !(READ_VPP_REG(OSD1_BLEND_SRC_CTRL) & (1<<8)); - else - return (!(READ_VPP_REG(VPP_MISC) & (1<<12))); -} + #define single_step_enable \ (((debug_dolby_frame >= 0xffff) || \ ((debug_dolby_frame + 1) == frame_count)) && \ @@ -1024,7 +1019,7 @@ static struct dovi_setting_s dovi_setting; static struct dovi_setting_s new_dovi_setting; void *pq_config_fake; -void *tv_dovi_setting; +struct tv_dovi_setting_s *tv_dovi_setting; static bool pq_config_set_flag; struct ui_menu_params_s menu_param = {50, 50, 50}; static bool tv_dovi_setting_change_flag; @@ -1071,6 +1066,21 @@ bool is_meson_gxm(void) else return false; } +bool is_meson_g12(void) +{ + if (dv_meson_dev.cpu_id == _CPU_MAJOR_ID_G12) + return true; + else + return false; +} + +bool is_meson_box(void) +{ + if (is_meson_gxm() || is_meson_g12()) + return true; + else + return false; +} bool is_meson_txlx(void) { @@ -1087,7 +1097,6 @@ bool is_meson_txlx_tvmode(void) else return false; } - bool is_meson_txlx_stbmode(void) { if ((is_meson_txlx()) && (tv_mode == 0)) @@ -1095,14 +1104,117 @@ bool is_meson_txlx_stbmode(void) else return false; } - -bool is_meson_g12(void) +bool is_meson_tm2(void) { - if (dv_meson_dev.cpu_id == _CPU_MAJOR_ID_G12) + if (dv_meson_dev.cpu_id == _CPU_MAJOR_ID_TM2) return true; else return false; } +bool is_meson_tm2_tvmode(void) +{ + if ((is_meson_tm2()) && (tv_mode == 1)) + return true; + else + return false; +} + +bool is_meson_tm2_stbmode(void) +{ + if ((is_meson_tm2()) && (tv_mode == 0)) + return true; + else + return false; +} + +bool is_meson_tvmode(void) +{ + if (is_meson_tm2_tvmode() || + is_meson_txlx_tvmode()) + return true; + else + return false; +} + +static u32 addr_map(u32 adr) +{ + u32 CORE1_BASE = 0; + u32 CORE1_1_BASE = 0; + u32 CORE2A_BASE = 0; + u32 CORE3_BASE = 0; + u32 CORETV_BASE = 0; + + if (is_meson_gxm() || is_meson_g12()) { + CORE1_BASE = 0x3300; + CORE2A_BASE = 0x3400; + CORE3_BASE = 0x3600; + } else if (is_meson_txlx()) { + CORE2A_BASE = 0x3400; + CORE3_BASE = 0x3600; + CORETV_BASE = 0x3300; + } else if (is_meson_tm2()) { + CORE1_BASE = 0x3300; + CORE1_1_BASE = 0x4400; + CORE2A_BASE = 0x3400; + CORE3_BASE = 0x3600; + CORETV_BASE = 0x4300; + } + + if (adr & CORE1_OFFSET) + adr = (adr & 0xffff) + CORE1_BASE; + else if (adr & CORE1_1_OFFSET) + adr = (adr & 0xffff) + CORE1_1_BASE; + else if (adr & CORE2A_OFFSET) + adr = (adr & 0xffff) + CORE2A_BASE; + else if (adr & CORE3_OFFSET) + adr = (adr & 0xffff) + CORE3_BASE; + else if (adr & CORETV_OFFSET) + adr = (adr & 0xffff) + CORETV_BASE; + + return adr; +} + +static u32 VSYNC_RD_DV_REG(u32 adr) +{ + adr = addr_map(adr); + return _VSYNC_RD_MPEG_REG(adr); +} + +static int VSYNC_WR_DV_REG(u32 adr, u32 val) +{ + adr = addr_map(adr); + _VSYNC_WR_MPEG_REG(adr, val); + return 0; +} + +static int VSYNC_WR_DV_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + adr = addr_map(adr); + _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); + return 0; +} + +static u32 READ_VPP_DV_REG(u32 adr) +{ + adr = addr_map(adr); + return READ_VPP_REG(adr); +} + +static int WRITE_VPP_DV_REG(u32 adr, const u32 val) +{ + adr = addr_map(adr); + WRITE_VPP_REG(adr, val); + return 0; +} + +static int is_graphics_output_off(void) +{ + if (is_meson_g12() || is_meson_tm2_stbmode()) + return !(READ_VPP_DV_REG(OSD1_BLEND_SRC_CTRL) & (1<<8)); + else + return (!(READ_VPP_DV_REG(VPP_MISC) & (1<<12))); +} + static void dump_tv_setting( struct tv_dovi_setting_s *setting, int frame_cnt, int debug_flag) @@ -1319,56 +1431,56 @@ static int stb_dolby_core1_set( FLAG_DISABE_CORE_SETTING)) return 0; - WRITE_VPP_REG( + WRITE_VPP_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); if (reset) { if (!dolby_vision_core1_on) { - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); } else reset = 0; } if (!bl_enable) - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x446); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, 0); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL5, 0x446); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL0, 0); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL1, ((hsize + 0x80) << 16) | (vsize + 0x40)); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) composer_enable = 0; - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL0, /* el dly 3, bl dly 1 after de*/ (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); if (el_enable && (dolby_vision_mask & 1)) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); if (dolby_vision_core1_on && !bypass_core1) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); else if (dolby_vision_core1_on && bypass_core1) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1394,31 +1506,31 @@ static int stb_dolby_core1_set( bypass_flag; if (dolby_vision_on_count < dolby_vision_run_mode_delay) { run_mode |= 1; - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else if (dolby_vision_on_count == dolby_vision_run_mode_delay) { - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else { - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, 0); } } if (reset) - _VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + VSYNC_WR_DV_REG(DOLBY_TV_REG_START + 1, run_mode); /* 962e work around to fix the uv swap issue when bl:el = 1:1 */ if (el_41_mode) - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x6); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL5, 0x6); else - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0xa); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL5, 0xa); /* axi dma for reg table */ reg_size = prepare_stb_dolby_core1_reg( @@ -1428,25 +1540,25 @@ static int stb_dolby_core1_set( if (!dolby_vision_on) { /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x00000080 | (reg_size << 23)); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); /* dma3:23-12 cvm size */ - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL3, + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80100000 | dma_start_line); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } if (reset) { /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x00000080 | (reg_size << 23)); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); /* dma3:23-12 cvm size */ - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80100000 | dma_start_line); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } tv_dovi_setting_update_flag = true; @@ -1509,66 +1621,66 @@ static int tv_dolby_core1_set( FLAG_DISABE_CORE_SETTING)) return 0; - WRITE_VPP_REG( + WRITE_VPP_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); if (reset) { - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); } if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) composer_enable = 0; - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL0, /* el dly 3, bl dly 1 after de*/ (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL1, ((hsize + 0x80) << 16 | (vsize + 0x40))); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); - _VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); /*0x2c2d0:5-4-1-3-2-0*/ - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); if ((hdmi) && (!hdr10)) - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); else - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); /* bypass dither */ - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); if (src_chroma_format == 2) - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); else if (src_chroma_format == 1) - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); /* input 12 or 10 bit */ - _VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); if (el_enable && (dolby_vision_mask & 1)) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); if (dolby_vision_core1_on && !bypass_core1) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); else if (dolby_vision_core1_on && bypass_core1) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1579,43 +1691,43 @@ static int tv_dolby_core1_set( run_mode = tv_run_mode(vsize, hdmi, hdr10, el_41_mode); if (dolby_vision_on_count < dolby_vision_run_mode_delay) { run_mode = (run_mode & 0xfffffffc) | 1; - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else if (dolby_vision_on_count == dolby_vision_run_mode_delay) { - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else { - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - _VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, 0); } } - ((struct tv_dovi_setting_s *)tv_dovi_setting)->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000000 | run_mode; if (reset) - _VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + VSYNC_WR_DV_REG(DOLBY_TV_REG_START + 1, run_mode); if (!dolby_vision_on) { - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL3, + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80000000 | dma_start_line); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } if (reset) { - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80000000 | dma_start_line); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } tv_dovi_setting_update_flag = true; @@ -1629,7 +1741,7 @@ int dolby_vision_update_setting(void) int i; uint64_t *p; - if (!p_funcs) + if (!p_funcs_stb && !p_funcs_tv) return -1; if (!tv_dovi_setting_update_flag) return 0; @@ -1646,9 +1758,8 @@ int dolby_vision_update_setting(void) setting_update_count++; return -1; } - if (is_meson_txlx_tvmode() && !force_stb_mode) { - dma_data = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut; + if (is_meson_tvmode() && !force_stb_mode) { + dma_data = tv_dovi_setting->core1_reg_lut; size = 8 * TV_DMA_TBL_SIZE; memcpy(dma_vaddr, dma_data, size); } else if (is_meson_txlx_stbmode() || force_stb_mode) { @@ -1700,27 +1811,27 @@ static int dolby_core1_set( /* Register: dolby_path_ctrl[0] = 0 to enable BL*/ /* dolby_path_ctrl[1] = 0 to enable EL*/ /* dolby_path_ctrl[2] = 0 to enable OSD*/ - if (is_meson_g12() && frame_count == 1 - && dolby_vision_core1_on == 0) { + if ((is_meson_g12() || is_meson_tm2_stbmode()) && + frame_count == 1 && dolby_vision_core1_on == 0) { pr_dolby_dbg("((%s %d, register DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - _VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); - if ((_VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x1) != 0) { + VSYNC_RD_DV_REG(DOLBY_PATH_CTRL)); + if ((VSYNC_RD_DV_REG(DOLBY_PATH_CTRL) & 0x1) != 0) { pr_dolby_dbg("BL is disable for 1st frame.Re-enable BL\n"); - _VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, 0, 0, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_PATH_CTRL, 0, 0, 1); pr_dolby_dbg("((%s %d, enable_bl, DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - _VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + VSYNC_RD_DV_REG(DOLBY_PATH_CTRL)); } if (el_enable) { - if ((_VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x10) != 0) { + if ((VSYNC_RD_DV_REG(DOLBY_PATH_CTRL) & 0x10) != 0) { pr_dolby_dbg("((%s %d enable el))\n", __func__, __LINE__); - _VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_PATH_CTRL, 0, 1, 1); pr_dolby_dbg("((%s %d, enable_el, DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - _VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + VSYNC_RD_DV_REG(DOLBY_PATH_CTRL)); } } } @@ -1738,8 +1849,8 @@ static int dolby_core1_set( reset = true; if ((!dolby_vision_on || reset) && bl_enable) { - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); reset = true; } @@ -1750,41 +1861,41 @@ static int dolby_core1_set( set_lut = true; if (bl_enable && el_enable && (dolby_vision_mask & 1)) { - if (is_meson_g12()) - _VSYNC_WR_MPEG_REG_BITS( + if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, /* vd2 to core1 */ 0, 1, 1); else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); } else { - if (is_meson_g12()) - _VSYNC_WR_MPEG_REG_BITS( + if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, /* vd2 to core1 */ 1, 1, 1); else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); } - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); - /* _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); + /* VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL1, ((hsize + 0x80) << 16) | (vsize + 0x40)); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x0); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 4, 4); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_CTRL, 0x0); + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 4, 4); + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 2, 1); /* bypass composer to get 12bit when SDR and HDR source */ #ifndef V2_4 @@ -1800,9 +1911,9 @@ static int dolby_core1_set( if (el_41_mode) bypass_flag |= 1 << 3; - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 1, 0x70 | bypass_flag); /* bypass CVM and/or CSC */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 1, 0x70 | bypass_flag); /* for delay */ if (dm_count == 0) count = 24; @@ -1812,7 +1923,7 @@ static int dolby_core1_set( if (reset || (p_core1_dm_regs[i] != last_dm[i])) - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE1_REG_START + 6 + i, p_core1_dm_regs[i]); @@ -1824,12 +1935,12 @@ static int dolby_core1_set( if (reset || (p_core1_comp_regs[i] != last_comp[i])) - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE1_REG_START + 6 + 44 + i, p_core1_comp_regs[i]); /* metadata program done */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 3, 1); + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 3, 1); if (lut_count == 0) count = 256 * 5; @@ -1837,92 +1948,113 @@ static int dolby_core1_set( count = lut_count; if (count && (set_lut || reset)) { if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - _VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, 2, 2, 2); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); if (lut_endian) for (i = 0; i < count; i += 4) { - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+3]); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+2]); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+1]); - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i]); } else for (i = 0; i < count; i++) - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i]); if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - _VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, 0, 2, 2); } if (dolby_vision_on_count <= dolby_vision_run_mode_delay) { - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); if (is_meson_g12()) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); } else { if (dolby_vision_on_count > dolby_vision_run_mode_delay) { - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC1, 0); } if (dolby_vision_core1_on && !bypass_core1) { if (is_meson_g12()) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, - 0, - 0, 1); - else - _VSYNC_WR_MPEG_REG_BITS( + 0, 0, 1); + else if (is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 8, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 10, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 17, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 21, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 24, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 0, 1); /* core1 */ + } else + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); } else if (dolby_vision_core1_on && bypass_core1) { if (is_meson_g12()) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, - 1, - 0, 1); - else - _VSYNC_WR_MPEG_REG_BITS( + 1, 0, 1); + else if (is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 3, 0, 2); /* core1 */ + } else + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); } } - if (is_meson_g12()) - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL0, (el_41_mode ? (0x3 << 4) : (0x0 << 4)) | bl_enable | composer_enable << 1 | el_41_mode << 2); else /* enable core1 */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL0, bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); @@ -1954,8 +2086,8 @@ static int dolby_core2_set( return 0; if (!dolby_vision_on || force_reset_core2) { - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, (1 << 10)); - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG(VIU_SW_RESET, (1 << 10)); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); force_reset_core2 = false; reset = true; } @@ -1966,37 +2098,37 @@ static int dolby_core2_set( if (stb_core_setting_update_flag & FLAG_CHANGE_TC2) set_lut = true; - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); - if (is_meson_gxm() || is_meson_g12() || reset) { - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); + if (is_meson_box() || is_meson_tm2_stbmode() || reset) { + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL1, ((hsize + g_htotal_add) << 16) | (vsize + g_vtotal_add + g_vsize_add)); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL2, + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL2, (hsize << 16) | (vsize + g_vsize_add)); } - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL3, + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL3, (g_hwidth << 16) | g_vwidth); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL4, + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL4, (g_hpotch << 16) | g_vpotch); if (is_meson_txlx_stbmode() || force_stb_mode) - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); - else if (is_meson_g12()) - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); + else if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); else - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 2, 1); if (need_skip_cvm(1)) bypass_flag |= 1 << 0; - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 1, 2 | bypass_flag); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 1, 2 | bypass_flag); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_CTRL, 0); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_CTRL, 0); if (dm_count == 0) count = 24; @@ -2006,7 +2138,7 @@ static int dolby_core2_set( if (reset || (p_core2_dm_regs[i] != last_dm[i])) { - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE2A_REG_START + 6 + i, p_core2_dm_regs[i]); set_lut = true; @@ -2016,7 +2148,7 @@ static int dolby_core2_set( set_lut = false; /* core2 metadata program done */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 3, 1); + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 3, 1); if (lut_count == 0) count = 256 * 5; @@ -2024,32 +2156,32 @@ static int dolby_core2_set( count = lut_count; if (count && (set_lut || reset)) { if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - _VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, 2, 2, 2); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); if (lut_endian) for (i = 0; i < count; i += 4) { - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+3]); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+2]); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+1]); - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i]); } else for (i = 0; i < count; i++) - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i]); /* core2 lookup table program done */ if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_CORE2A_CLKGATE_CTRL, 0, 2, 2); } /* enable core2 */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); return 0; } @@ -2093,7 +2225,7 @@ static int dolby_core3_set( && diag_enable) { cur_dv_mode = dv_ll_output_mode & 0xff; - if (is_meson_g12()) { + if (is_meson_g12() || is_meson_tm2_stbmode()) { if (dolby_vision_ll_policy == DOLBY_VISION_LL_YUV422) diag_mode = 0x20; else @@ -2112,65 +2244,64 @@ static int dolby_core3_set( new_dovi_setting.vsvdb_changed = 0; new_dovi_setting.mode_changed = 0; /* TODO: verify 962e case */ - if (is_meson_gxm() || - is_meson_g12()) { + if (is_meson_box() || is_meson_tm2_stbmode()) { if (new_dovi_setting.dovi_ll_enable && new_dovi_setting.diagnostic_enable == 0) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 3, 6, 2); /* post matrix */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 1, 0, 1); /* post matrix */ } else { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 6, 2); /* post matrix */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 0, 0, 1); /* post matrix */ } } else if (is_meson_txlx_stbmode() || force_stb_mode) { if (pps_state == 2) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 0, 1); /* skip pps/dither/cm */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); } else if (pps_state == 1) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 0, 1); /* enable pps/dither/cm */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); } if (new_dovi_setting.dovi_ll_enable && new_dovi_setting.diagnostic_enable == 0) { /*bypass gainoff to vks */ /*enable wn tp vks*/ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 2, 1); - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x8000800); - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 1, 0, 1); /* post matrix */ } else { /* bypass wm tp vks*/ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 2, 1); - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 1, 1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); - if (is_meson_txlx_tvmode()) + if (is_meson_tvmode()) enable_rgb_to_yuv_matrix_for_dvll( 0, NULL, 12); else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 0, 0, 1); } @@ -2188,27 +2319,27 @@ static int dolby_core3_set( 1, &p_core3_dm_regs[18], 12); #endif - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL1, ((hsize + htotal_add) << 16) | (vsize + vtotal_add + vsize_add + vsize_hold * 2)); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL2, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL2, (hsize << 16) | (vsize + vsize_add)); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL3, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL3, (0x80 << 16) | vsize_hold); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL4, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL4, (0x04 << 16) | vsize_hold); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); if (cur_dv_mode != DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL6, 0); else - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL6, 0x10000000); /* swap UV */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 5, 7); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 4); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 2); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 5, 7); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 4, 4); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 4, 2); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 2, 1); /* Control Register, address 0x04 2:0 RW */ /* Output_operating mode*/ /* 00- IPT 12 bit 444 bypass Dolby Vision output*/ @@ -2216,8 +2347,8 @@ static int dolby_core3_set( /* 02- HDR10 output, RGB 10 bit 444 PQ*/ /* 03- Deep color SDR, RGB 10 bit 444 Gamma*/ /* 04- SDR, RGB 8 bit 444 Gamma*/ - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); /* for delay */ if (dm_count == 0) @@ -2227,7 +2358,7 @@ static int dolby_core3_set( for (i = 0; i < count; i++) if (reset || (p_core3_dm_regs[i] != last_dm[i])) - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_REG_START + 0x6 + i, p_core3_dm_regs[i]); /* from addr 0x18 */ @@ -2236,29 +2367,29 @@ static int dolby_core3_set( for (i = 0; i < count; i++) { #ifdef FORCE_HDMI_META if ((i == 20) && (p_core3_md_regs[i] == 0x5140a3e)) - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 0x24 + i, (p_core3_md_regs[i] & 0xffffff00) | 0x80); else #endif - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 0x24 + i, p_core3_md_regs[i]); } for (; i < 30; i++) - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); /* from addr 0x90 */ /* core3 metadata program done */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 3, 1); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 3, 1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_DIAG_CTRL, diag_mode); if ((dolby_vision_flags & FLAG_CERTIFICAION) && !(dolby_vision_flags & FLAG_DISABLE_CRC)) - _VSYNC_WR_MPEG_REG(0x36fb, 1); + VSYNC_WR_DV_REG(0x36fb, 1); /* enable core3 */ - _VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); return 0; } @@ -2283,7 +2414,6 @@ static void apply_stb_core_settings( #endif u32 graphics_w = osd_graphic_width; u32 graphics_h = osd_graphic_height; - if (is_dolby_vision_stb_mode() && (dolby_vision_flags & FLAG_CERTIFICAION)) { graphics_w = dv_cert_graphic_width; @@ -2402,16 +2532,16 @@ static void osd_bypass(int bypass) static uint32_t osd_backup_mtx; if (bypass) { - osd_backup_ctrl = _VSYNC_RD_MPEG_REG(VIU_OSD1_CTRL_STAT); - osd_backup_eotf = _VSYNC_RD_MPEG_REG(VIU_OSD1_EOTF_CTL); - osd_backup_mtx = _VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); - _VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); - _VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); - _VSYNC_WR_MPEG_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); + osd_backup_ctrl = VSYNC_RD_DV_REG(VIU_OSD1_CTRL_STAT); + osd_backup_eotf = VSYNC_RD_DV_REG(VIU_OSD1_EOTF_CTL); + osd_backup_mtx = VSYNC_RD_DV_REG(VPP_MATRIX_CTRL); + VSYNC_WR_DV_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); + VSYNC_WR_DV_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); + VSYNC_WR_DV_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); } else { - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, osd_backup_mtx); - _VSYNC_WR_MPEG_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); - _VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, osd_backup_mtx); + VSYNC_WR_DV_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); + VSYNC_WR_DV_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); } } @@ -2429,42 +2559,42 @@ static void video_effect_bypass(int bypass) if (bypass) { if (!is_video_effect_bypass) { viu_eotf_ctrl_backup = - _VSYNC_RD_MPEG_REG(VIU_EOTF_CTL); + VSYNC_RD_DV_REG(VIU_EOTF_CTL); xvycc_lut_ctrl_backup = - _VSYNC_RD_MPEG_REG(XVYCC_LUT_CTL); + VSYNC_RD_DV_REG(XVYCC_LUT_CTL); inv_lut_ctrl_backup = - _VSYNC_RD_MPEG_REG(XVYCC_INV_LUT_CTL); + VSYNC_RD_DV_REG(XVYCC_INV_LUT_CTL); vpp_vadj_backup = - _VSYNC_RD_MPEG_REG(VPP_VADJ_CTRL); + VSYNC_RD_DV_REG(VPP_VADJ_CTRL); vpp_gainoff_backup = - _VSYNC_RD_MPEG_REG(VPP_GAINOFF_CTRL0); + VSYNC_RD_DV_REG(VPP_GAINOFF_CTRL0); vpp_ve_enable_ctrl_backup = - _VSYNC_RD_MPEG_REG(VPP_VE_ENABLE_CTRL); + VSYNC_RD_DV_REG(VPP_VE_ENABLE_CTRL); xvycc_vd1_rgb_ctrst_backup = - _VSYNC_RD_MPEG_REG(XVYCC_VD1_RGB_CTRST); + VSYNC_RD_DV_REG(XVYCC_VD1_RGB_CTRST); is_video_effect_bypass = true; } - _VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, 0); - _VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, 0); - _VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, 0); - _VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, 0); - _VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, 0); - _VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, 0); - _VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, 0); + VSYNC_WR_DV_REG(VIU_EOTF_CTL, 0); + VSYNC_WR_DV_REG(XVYCC_LUT_CTL, 0); + VSYNC_WR_DV_REG(XVYCC_INV_LUT_CTL, 0); + VSYNC_WR_DV_REG(VPP_VADJ_CTRL, 0); + VSYNC_WR_DV_REG(VPP_GAINOFF_CTRL0, 0); + VSYNC_WR_DV_REG(VPP_VE_ENABLE_CTRL, 0); + VSYNC_WR_DV_REG(XVYCC_VD1_RGB_CTRST, 0); } else if (is_video_effect_bypass) { - _VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, + VSYNC_WR_DV_REG(VIU_EOTF_CTL, viu_eotf_ctrl_backup); - _VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, + VSYNC_WR_DV_REG(XVYCC_LUT_CTL, xvycc_lut_ctrl_backup); - _VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, + VSYNC_WR_DV_REG(XVYCC_INV_LUT_CTL, inv_lut_ctrl_backup); - _VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, + VSYNC_WR_DV_REG(VPP_VADJ_CTRL, vpp_vadj_backup); - _VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, + VSYNC_WR_DV_REG(VPP_GAINOFF_CTRL0, vpp_gainoff_backup); - _VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, + VSYNC_WR_DV_REG(VPP_VE_ENABLE_CTRL, vpp_ve_enable_ctrl_backup); - _VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, + VSYNC_WR_DV_REG(XVYCC_VD1_RGB_CTRST, xvycc_vd1_rgb_ctrst_backup); } } @@ -2478,54 +2608,54 @@ static void osd_path_enable(int on) if (!on) { enable_osd_path(0, 0); - _VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, 0); - _VSYNC_WR_MPEG_REG(VIU_OSD1_OETF_CTL, 0); + VSYNC_WR_DV_REG(VIU_OSD1_EOTF_CTL, 0); + VSYNC_WR_DV_REG(VIU_OSD1_OETF_CTL, 0); } else { enable_osd_path(1, -1); if ((hdr_osd_reg.viu_osd1_eotf_ctl & 0x80000000) != 0) { addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 0); for (i = 0; i < 16; i++) - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->r_map[i * 2] | (lut->r_map[i * 2 + 1] << 16)); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->r_map[EOTF_LUT_SIZE - 1] | (lut->g_map[0] << 16)); for (i = 0; i < 16; i++) - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->g_map[i * 2 + 1] | (lut->b_map[i * 2 + 2] << 16)); for (i = 0; i < 16; i++) - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->b_map[i * 2] | (lut->b_map[i * 2 + 1] << 16)); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->b_map[EOTF_LUT_SIZE - 1]); /* load eotf matrix */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF00_01, hdr_osd_reg.viu_osd1_eotf_coef00_01); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF02_10, hdr_osd_reg.viu_osd1_eotf_coef02_10); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF11_12, hdr_osd_reg.viu_osd1_eotf_coef11_12); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF20_21, hdr_osd_reg.viu_osd1_eotf_coef20_21); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF22_RS, hdr_osd_reg.viu_osd1_eotf_coef22_rs); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_CTL, hdr_osd_reg.viu_osd1_eotf_ctl); } @@ -2534,82 +2664,82 @@ static void osd_path_enable(int on) addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; data_port = VIU_OSD1_OETF_LUT_DATA_PORT; for (i = 0; i < 20; i++) { - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, i); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->or_map[i * 2] | (lut->or_map[i * 2 + 1] << 16)); } - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 20); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->or_map[41 - 1] | (lut->og_map[0] << 16)); for (i = 0; i < 20; i++) { - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 21 + i); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->og_map[i * 2 + 1] | (lut->og_map[i * 2 + 2] << 16)); } for (i = 0; i < 20; i++) { - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 41 + i); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->ob_map[i * 2] | (lut->ob_map[i * 2 + 1] << 16)); } - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 61); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->ob_map[41 - 1]); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_OETF_CTL, hdr_osd_reg.viu_osd1_oetf_ctl); } } - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_PRE_OFFSET0_1, hdr_osd_reg.viu_osd1_matrix_pre_offset0_1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_PRE_OFFSET2, hdr_osd_reg.viu_osd1_matrix_pre_offset2); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF00_01, hdr_osd_reg.viu_osd1_matrix_coef00_01); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF02_10, hdr_osd_reg.viu_osd1_matrix_coef02_10); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF11_12, hdr_osd_reg.viu_osd1_matrix_coef11_12); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF20_21, hdr_osd_reg.viu_osd1_matrix_coef20_21); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF22_30, hdr_osd_reg.viu_osd1_matrix_coef22_30); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF31_32, hdr_osd_reg.viu_osd1_matrix_coef31_32); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF40_41, hdr_osd_reg.viu_osd1_matrix_coef40_41); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COLMOD_COEF42, hdr_osd_reg.viu_osd1_matrix_colmod_coef42); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_OFFSET0_1, hdr_osd_reg.viu_osd1_matrix_offset0_1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_OFFSET2, hdr_osd_reg.viu_osd1_matrix_offset2); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_CTRL, hdr_osd_reg.viu_osd1_matrix_ctrl); } @@ -2623,27 +2753,26 @@ static uint32_t vpp_data_conv_para1_backup; void enable_dolby_vision(int enable) { uint32_t size = 0; - uint64_t *dma_data = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut; + uint64_t *dma_data = tv_dovi_setting->core1_reg_lut; if (enable) { if (!dolby_vision_on) { dolby_ctrl_backup = - _VSYNC_RD_MPEG_REG(VPP_DOLBY_CTRL); + VSYNC_RD_DV_REG(VPP_DOLBY_CTRL); viu_misc_ctrl_backup = - _VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1); + VSYNC_RD_DV_REG(VIU_MISC_CTRL1); vpp_matrix_backup = - _VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); + VSYNC_RD_DV_REG(VPP_MATRIX_CTRL); vpp_dummy1_backup = - _VSYNC_RD_MPEG_REG(VPP_DUMMY_DATA1); + VSYNC_RD_DV_REG(VPP_DUMMY_DATA1); if (is_meson_txlx()) { vpp_data_conv_para0_backup = - _VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA0); + VSYNC_RD_DV_REG(VPP_DAT_CONV_PARA0); vpp_data_conv_para1_backup = - _VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA1); + VSYNC_RD_DV_REG(VPP_DAT_CONV_PARA1); setting_update_count = 0; } - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { if (efuse_mode == 1) { size = 8 * TV_DMA_TBL_SIZE; memset(dma_vaddr, 0x0, size); @@ -2651,23 +2780,54 @@ void enable_dolby_vision(int enable) dma_data + 1, 8); } - if ((dolby_vision_mask & 1) - && dovi_setting_video_flag) { - _VSYNC_WR_MPEG_REG_BITS( - VIU_MISC_CTRL1, - 0, - 16, 1); /* core1 */ - dolby_vision_core1_on = true; - } else { - _VSYNC_WR_MPEG_REG_BITS( - VIU_MISC_CTRL1, - 1, - 16, 1); /* core1 */ - dolby_vision_core1_on = false; + if (is_meson_txlx_tvmode()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + VIU_MISC_CTRL1, + 0, + 16, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + VIU_MISC_CTRL1, + 1, + 16, 1); /* core1 */ + dolby_vision_core1_on = false; + } + } else if (is_meson_tm2_tvmode()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, 8, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, 10, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 16, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 20, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, 24, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 0, 2); + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 3, 0, 2); + dolby_vision_core1_on = false; + } } + if (dolby_vision_flags & FLAG_CERTIFICAION) { /* bypass dither/PPS/SR/CM, EO/OE */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 3, 0, 2); /* bypass all video effect */ video_effect_bypass(1); @@ -2675,13 +2835,13 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); - WRITE_VPP_REG(0x33e7, 0xb); + WRITE_VPP_DV_REG(0x33e7, 0xb); } else { /* bypass all video effect */ if (dolby_vision_flags @@ -2689,18 +2849,18 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DUMMY_DATA1, 0x80200); /* osd rgb to yuv, vpp out yuv to rgb */ - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0x81); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0x81); pr_dolby_dbg("Dolby Vision TV core turn on\n"); } else if (is_meson_txlx_stbmode() || force_stb_mode) { @@ -2709,29 +2869,29 @@ void enable_dolby_vision(int enable) memset(dma_vaddr, 0x0, size); osd_bypass(1); if (dolby_vision_mask & 4) - _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 1, 3, 1); /* core3 enable */ if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ dolby_vision_core1_on = false; } - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, (((dolby_vision_mask & 1) && dovi_setting_video_flag) ? 0 : 1), 16, 1); /* core1 */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, ((dolby_vision_mask & 2) ? 0 : 1), 18, 1); /* core2 */ @@ -2739,7 +2899,7 @@ void enable_dolby_vision(int enable) /* bypass dither/PPS/SR/CM*/ /* bypass EO/OE*/ /* bypass vadj2/mtx/gainoff */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 7, 0, 3); /* bypass all video effect */ video_effect_bypass(1); @@ -2747,11 +2907,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } else { /* bypass all video effect */ @@ -2760,19 +2920,19 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, 0x80200); - if (is_meson_txlx_tvmode()) - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 1); + if (is_meson_tvmode()) + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 1); else - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0); #ifdef V2_4 if (((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) @@ -2783,17 +2943,17 @@ void enable_dolby_vision(int enable) u32 *reg = (u32 *)&dovi_setting.dm_reg3; /* input u12 -0x800 to s12 */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x8000800); /* bypass vadj */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VADJ_CTRL, 0); /* bypass gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_GAINOFF_CTRL0, 0); /* enable wm tp vks*/ /* bypass gainoff to vks */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 2); enable_rgb_to_yuv_matrix_for_dvll( 1, ®[18], 12); @@ -2804,48 +2964,78 @@ void enable_dolby_vision(int enable) dolby_vision_ll_policy; #endif pr_dolby_dbg("Dolby Vision STB cores turn on\n"); - } else if (is_meson_g12()) { + } else if (is_meson_g12() || is_meson_tm2_stbmode()) { if (dolby_vision_mask & 4) - _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 1, 3, 1); /* core3 enable */ else - _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* bypass core3 */ - _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x0); - _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x0); - _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x0); if (dolby_vision_mask & 2) - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, 0, 2, 1);/*core2 enable*/ else - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, 1, 2, 1);/*core2 bypass*/ - if ((dolby_vision_mask & 1) - && dovi_setting_video_flag) { - _VSYNC_WR_MPEG_REG_BITS( - DOLBY_PATH_CTRL, - 0, - 0, 1); /* core1 */ - dolby_vision_core1_on = true; - } else { - _VSYNC_WR_MPEG_REG_BITS( - DOLBY_PATH_CTRL, - 1, - 0, 1); /* core1 */ - dolby_vision_core1_on = false; + if (is_meson_g12()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, + 0, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, + 0, 1); /* core1 */ + dolby_vision_core1_on = false; + } + } else if (is_meson_tm2_stbmode()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 8, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 10, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 17, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 21, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 24, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 0, 2); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 3, 0, 2); /* core1 */ + dolby_vision_core1_on = false; + } } if (dolby_vision_flags & FLAG_CERTIFICAION) { /* bypass dither/PPS/SR/CM*/ /* bypass EO/OE*/ /* bypass vadj2/mtx/gainoff */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 7, 0, 3); /* bypass all video effect */ video_effect_bypass(1); @@ -2853,11 +3043,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } else { /* bypass all video effect */ @@ -2866,15 +3056,15 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, 0x80200); #ifdef V2_4 if (((dolby_vision_mode == @@ -2886,17 +3076,17 @@ void enable_dolby_vision(int enable) u32 *reg = (u32 *)&dovi_setting.dm_reg3; /* input u12 -0x800 to s12 */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x8000800); /* bypass vadj */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VADJ_CTRL, 0); /* bypass gainoff */ - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_GAINOFF_CTRL0, 0); /* enable wm tp vks*/ /* bypass gainoff to vks */ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 2); enable_rgb_to_yuv_matrix_for_dvll( 1, ®[18], @@ -2910,7 +3100,7 @@ void enable_dolby_vision(int enable) #endif pr_dolby_dbg("Dolby Vision G12a turn on\n"); } else { - _VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG(VPP_DOLBY_CTRL, /* cm_datx4_mode */ (0x0<<21) | /* reg_front_cti_bit_mode */ @@ -2930,7 +3120,7 @@ void enable_dolby_vision(int enable) (0x3<<8) | /* vpp_uns2s_mode 7:0 */ 0x1f); - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* 23-20 ext mode */ (0 << 2) | @@ -2944,13 +3134,13 @@ void enable_dolby_vision(int enable) 18, 6); if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -2960,8 +3150,8 @@ void enable_dolby_vision(int enable) if ((dolby_vision_flags & FLAG_BYPASS_VPP) || (dolby_vision_flags & FLAG_CERTIFICAION)) video_effect_bypass(1); - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, 0x20000000); /* disable osd effect and shadow mode */ osd_path_enable(0); #ifdef V2_4 @@ -2973,7 +3163,7 @@ void enable_dolby_vision(int enable) dovi_setting.dovi_ll_enable) { u32 *reg = (u32 *)&dovi_setting.dm_reg3; - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 3, 6, 2); /* post matrix */ enable_rgb_to_yuv_matrix_for_dvll( @@ -2990,7 +3180,7 @@ void enable_dolby_vision(int enable) if (!dolby_vision_core1_on && (dolby_vision_mask & 1) && dovi_setting_video_flag) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ @@ -2998,7 +3188,7 @@ void enable_dolby_vision(int enable) } else if (dolby_vision_core1_on && (!(dolby_vision_mask & 1) || !dovi_setting_video_flag)){ - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -3012,8 +3202,8 @@ void enable_dolby_vision(int enable) vsync_count = 0; } else { if (dolby_vision_on) { - if (is_meson_txlx_tvmode() && !force_stb_mode) { - _VSYNC_WR_MPEG_REG_BITS( + if (is_meson_tvmode() && !force_stb_mode) { + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 connect to vpp */ (1 << 1) | @@ -3021,8 +3211,8 @@ void enable_dolby_vision(int enable) (1 << 0), 16, 2); #ifdef V1_5 - if (p_funcs) /* destroy ctx */ - p_funcs->tv_control_path( + if (p_funcs_tv) /* destroy ctx */ + p_funcs_tv->tv_control_path( FORMAT_INVALID, 0, NULL, 0, NULL, 0, @@ -3036,18 +3226,18 @@ void enable_dolby_vision(int enable) pr_dolby_dbg("Dolby Vision TV core turn off\n"); } else if (is_meson_txlx_stbmode() || force_stb_mode) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 16, 3); - _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* core3 disable */ osd_bypass(0); #ifdef V2_4 - if (p_funcs) /* destroy ctx */ - p_funcs->control_path( + if (p_funcs_stb) /* destroy ctx */ + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -3063,24 +3253,24 @@ void enable_dolby_vision(int enable) stb_core2_const_flag = false; memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision STB cores turn off\n"); - } else if (is_meson_g12()) { - _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + } else if (is_meson_g12() || is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x1); - _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x1); - _VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x1); - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 0, 3); - _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* core3 disable */ #ifdef V2_4 - if (p_funcs) /* destroy ctx */ - p_funcs->control_path( + if (p_funcs_stb) /* destroy ctx */ + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -3097,20 +3287,20 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision G12a turn off\n"); } else { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 16, 3); - _VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 16, 1); /* core3 disable */ /* enable osd effect and*/ /* use default shadow mode */ osd_path_enable(1); #ifdef V2_4 - if (p_funcs) /* destroy ctx */ - p_funcs->control_path( + if (p_funcs_stb) /* destroy ctx */ + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -3127,56 +3317,55 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision turn off\n"); } - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 3 << 9); - _VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG(VIU_SW_RESET, 3 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); if (is_meson_txlx()) { - _VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA0, + VSYNC_WR_DV_REG(VPP_DAT_CONV_PARA0, vpp_data_conv_para0_backup); - _VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA1, + VSYNC_WR_DV_REG(VPP_DAT_CONV_PARA1, vpp_data_conv_para1_backup); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2414); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE2A_CLKGATE_CTRL, 0x4); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_CLKGATE_CTRL, 0x414); - _VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); } - if (is_meson_gxm() || - is_meson_g12()) { - _VSYNC_WR_MPEG_REG( + if (is_meson_box() || is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG( DOLBY_CORE1_CLKGATE_CTRL, 0x55555555); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE2A_CLKGATE_CTRL, 0x55555555); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_CLKGATE_CTRL, 0x55555555); } - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC1, 0); video_effect_bypass(0); - _VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG(VPP_DOLBY_CTRL, dolby_ctrl_backup); /* always vd2 to vpp and bypass core 1 */ viu_misc_ctrl_backup |= - (_VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 2); - _VSYNC_WR_MPEG_REG(VIU_MISC_CTRL1, + (VSYNC_RD_DV_REG(VIU_MISC_CTRL1) & 2); + VSYNC_WR_DV_REG(VIU_MISC_CTRL1, viu_misc_ctrl_backup | (3 << 16)); - _VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, vpp_matrix_backup); - _VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, vpp_dummy1_backup); } frame_count = 0; @@ -3337,10 +3526,12 @@ static void dump_struct(void *structure, int struct_length, "/data/tmp/tmp", frame_nr-1); fp = filp_open(fn, O_RDWR|O_CREAT, 0666); if (fp == NULL) - pr_info("Error open file for writing %s\n", fn); - vfs_write(fp, structure, struct_length, &pos); - vfs_fsync(fp, 0); - filp_close(fp, NULL); + pr_info("Error open file for writing NULL\n"); + else { + vfs_write(fp, structure, struct_length, &pos); + vfs_fsync(fp, 0); + filp_close(fp, NULL); + } set_fs(old_fs); } @@ -3395,17 +3586,17 @@ static void dump_setting( for (i = DOLBY_CORE1_CLKGATE_CTRL; i <= DOLBY_CORE1_DMA_PORT; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core1 real reg\n"); for (i = DOLBY_CORE1_REG_START; i <= DOLBY_CORE1_REG_START + 5; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core1 composer real reg\n"); for (i = 0; i < 173 ; i++) pr_info("%08x\n", - READ_VPP_REG( + READ_VPP_DV_REG( DOLBY_CORE1_REG_START + 50 + i)); } else if (is_meson_txlx()) { @@ -3413,13 +3604,13 @@ static void dump_setting( for (i = DOLBY_TV_SWAP_CTRL0; i <= DOLBY_TV_STATUS1; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core1 real reg\n"); for (i = DOLBY_TV_REG_START; i <= DOLBY_CORE1_REG_START + 5; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); } } @@ -3461,12 +3652,12 @@ static void dump_setting( for (i = DOLBY_CORE2A_CLKGATE_CTRL; i <= DOLBY_CORE2A_DMA_PORT; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core2 real reg\n"); for (i = DOLBY_CORE2A_REG_START; i <= DOLBY_CORE2A_REG_START + 5; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); } if ((debug_flag & 0x20) && dump_enable && !is_graphics_output_off()) { @@ -3507,12 +3698,12 @@ static void dump_setting( for (i = DOLBY_CORE3_CLKGATE_CTRL; i <= DOLBY_CORE3_OUTPUT_CSC_CRC; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core3 real reg\n"); for (i = DOLBY_CORE3_REG_START; i <= DOLBY_CORE3_REG_START + 67; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); } if ((debug_flag & 0x40) && dump_enable @@ -3528,9 +3719,9 @@ static void dump_setting( void dolby_vision_dump_setting(int debug_flag) { pr_dolby_dbg("\n====== setting for frame %d ======\n", frame_count); - if (is_meson_txlx_tvmode() && !force_stb_mode) - dump_tv_setting((struct tv_dovi_setting_s *)tv_dovi_setting, - frame_count, debug_flag); + if (is_meson_tvmode() && !force_stb_mode) + dump_tv_setting(tv_dovi_setting, + frame_count, debug_flag); else dump_setting(&new_dovi_setting, frame_count, debug_flag); pr_dolby_dbg("=== setting for frame %d dumped ===\n\n", frame_count); @@ -3571,10 +3762,10 @@ static int dolby_vision_policy_process( const struct vinfo_s *vinfo; int mode_change = 0; - if ((!dolby_vision_enable) || (!p_funcs)) + if ((!dolby_vision_enable) || ((!p_funcs_stb) && (!p_funcs_tv))) return mode_change; - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { if (dolby_vision_policy == DOLBY_VISION_FORCE_OUTPUT_MODE) { if (*mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { if (dolby_vision_mode != @@ -3805,7 +3996,7 @@ bool is_dovi_frame(struct vframe_s *vf) req.dv_enhance_exist = 0; if ((vf->source_type == VFRAME_SOURCE_TYPE_HDMI) - && is_meson_txlx_tvmode() && !force_stb_mode) { + && is_meson_tvmode() && !force_stb_mode) { vf_notify_provider_by_name("dv_vdin", VFRAME_EVENT_RECEIVER_GET_AUX_DATA, (void *)&req); @@ -3901,7 +4092,7 @@ struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf) { int i; - if (dolby_vision_flags && p_funcs) { + if (dolby_vision_flags && (p_funcs_stb || p_funcs_tv)) { for (i = 0; i < 16; i++) { if (dv_vf[i][0] == vf) { if (dv_vf[i][1] @@ -4013,27 +4204,49 @@ static int parse_sei_and_meta( meta_buf[i+7]); } - if (!p_funcs) - return -1; + if (tv_mode) { + if (!p_funcs_tv) + return -1; + } else { + if (!p_funcs_stb) + return -1; + } /* prepare metadata parser */ spin_lock_irqsave(&dovi_lock, flags); parser_ready = 0; if (metadata_parser == NULL) { - metadata_parser = - p_funcs->metadata_parser_init( + if (is_meson_tvmode()) { + metadata_parser = + p_funcs_tv->metadata_parser_init( dolby_vision_flags & FLAG_CHANGE_SEQ_HEAD ? 1 : 0); - p_funcs->metadata_parser_reset(1); + p_funcs_tv->metadata_parser_reset(1); + } else { + metadata_parser = + p_funcs_stb->metadata_parser_init( + dolby_vision_flags + & FLAG_CHANGE_SEQ_HEAD + ? 1 : 0); + p_funcs_stb->metadata_parser_reset(1); + } if (metadata_parser != NULL) { parser_ready = 1; if (debug_dolby & 1) pr_dolby_dbg("metadata parser init OK\n"); } } else { - if (p_funcs->metadata_parser_reset( - metadata_parser_reset_flag) == 0) - metadata_parser_reset_flag = 0; + if (is_meson_tvmode()) { + if (p_funcs_tv->metadata_parser_reset( + metadata_parser_reset_flag + ) == 0) + metadata_parser_reset_flag = 0; + } else { + if (p_funcs_stb->metadata_parser_reset( + metadata_parser_reset_flag + ) == 0) + metadata_parser_reset_flag = 0; + } parser_ready = 1; } if (!parser_ready) { @@ -4047,13 +4260,22 @@ static int parse_sei_and_meta( } md_size = comp_size = 0; - rpu_ret = p_funcs->metadata_parser_process( - meta_buf, size + 2, - comp_buf[nextId] + *total_comp_size, - &comp_size, - md_buf[nextId] + *total_md_size, - &md_size, - true); + if (is_meson_tvmode()) + rpu_ret = p_funcs_tv->metadata_parser_process( + meta_buf, size + 2, + comp_buf[nextId] + *total_comp_size, + &comp_size, + md_buf[nextId] + *total_md_size, + &md_size, + true); + else + rpu_ret = p_funcs_stb->metadata_parser_process( + meta_buf, size + 2, + comp_buf[nextId] + *total_comp_size, + &comp_size, + md_buf[nextId] + *total_md_size, + &md_size, + true); if (rpu_ret < 0) { pr_dolby_error( "meta(%d), pts(%lld) -> metadata parser process fail\n", @@ -4670,10 +4892,10 @@ static uint32_t null_vf_cnt; static bool video_off_handled; static int is_video_output_off(struct vframe_s *vf) { - if ((READ_VPP_REG(VPP_MISC) & (1<<10)) == 0) { + if ((READ_VPP_DV_REG(VPP_MISC) & (1<<10)) == 0) { /*Not reset frame0/1 clipping*/ /*when core off to avoid green garbage*/ - if (is_meson_txlx_tvmode() && (vf == NULL) && + if (is_meson_tvmode() && (vf == NULL) && (dolby_vision_on_count <= dolby_vision_run_mode_delay)) return 0; if (vf == NULL) @@ -4790,7 +5012,7 @@ int dolby_vision_parse_metadata( vf->compHeight : vf->height; } - if (is_meson_txlx_tvmode() && !force_stb_mode && vf + if (is_meson_tvmode() && !force_stb_mode && vf && (vf->source_type == VFRAME_SOURCE_TYPE_HDMI)) { req.vf = vf; req.bot_flag = 0; @@ -4823,8 +5045,7 @@ int dolby_vision_parse_metadata( src_format = FORMAT_DOVI; } else { if (toggle_mode == 2) - src_format = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format; + src_format = tv_dovi_setting->src_format; if (vf->type & VIDTYPE_VIU_422) src_chroma_format = 1; p_mdc = &vf->prop.master_display_colour; @@ -4914,9 +5135,8 @@ int dolby_vision_parse_metadata( } } else if (is_dolby_vision_stb_mode()) src_format = dovi_setting.src_format; - else if (is_meson_txlx_tvmode()) - src_format = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format; + else if (is_meson_tvmode()) + src_format = tv_dovi_setting->src_format; if ((src_format != FORMAT_DOVI) && is_hdr10_frame(vf)) { @@ -5039,8 +5259,7 @@ int dolby_vision_parse_metadata( if (is_dolby_vision_stb_mode()) el_flag = dovi_setting.el_flag; else - el_flag = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag; + el_flag = tv_dovi_setting->el_flag; meta_flag_bl = 0; } if ((src_format == FORMAT_DOVI) @@ -5066,8 +5285,10 @@ int dolby_vision_parse_metadata( if ((src_format != FORMAT_DOVI) && metadata_parser && !bypass_release) { - if (p_funcs) - p_funcs->metadata_parser_release(); + if (p_funcs_stb) + p_funcs_stb->metadata_parser_release(); + if (p_funcs_tv) + p_funcs_tv->metadata_parser_release(); metadata_parser = NULL; } @@ -5096,13 +5317,12 @@ int dolby_vision_parse_metadata( return -1; } - if (!p_funcs) + if (!p_funcs_stb && !p_funcs_tv) return -1; /* TV core */ - if (is_meson_txlx_tvmode() && !force_stb_mode) { - if (src_format != ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format) + if (is_meson_tvmode() && !force_stb_mode) { + if (src_format != tv_dovi_setting->src_format) pq_config_set_flag = false; if (!pq_config_set_flag) { if ((dolby_vision_flags & FLAG_FORCE_DOVI_LL) @@ -5122,10 +5342,8 @@ int dolby_vision_parse_metadata( vinfo, &(((struct pq_config_s *) pq_config_fake)->target_display_config)); - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_width = w << 16; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_height = h << 16; + tv_dovi_setting->video_width = w << 16; + tv_dovi_setting->video_height = h << 16; ((struct pq_config_s *) pq_config_fake)->target_display_config.tuningMode = dolby_vision_tunning_mode; @@ -5149,10 +5367,9 @@ int dolby_vision_parse_metadata( ->target_display_config.tuningMode |= TUNINGMODE_EXTLEVEL4_DISABLE; - if (src_format != ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format) { - if (p_funcs->tv_control_path) - p_funcs->tv_control_path( + if (src_format != tv_dovi_setting->src_format) { + if (p_funcs_tv && (p_funcs_tv->tv_control_path)) + p_funcs_tv->tv_control_path( FORMAT_INVALID, 0, NULL, 0, NULL, 0, @@ -5164,9 +5381,9 @@ int dolby_vision_parse_metadata( NULL); } #endif - if (!p_funcs->tv_control_path) + if ((!p_funcs_tv) || (!p_funcs_tv->tv_control_path)) return -1; - flag = p_funcs->tv_control_path( + flag = p_funcs_tv->tv_control_path( src_format, input_mode, comp_buf[currentId], total_comp_size, md_buf[currentId], total_md_size, @@ -5181,48 +5398,33 @@ int dolby_vision_parse_metadata( if (flag >= 0) { if (input_mode == INPUT_MODE_HDMI) { if (h > 1080) - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000043; else - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000042; } else { if (src_format == FORMAT_HDR10) - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x000000010000404c; else if (el_halfsize_flag) - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x000000010000004c; else - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000044; } /* enable CRC */ if (dolby_vision_flags & FLAG_CERTIFICAION) - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut[3] = + tv_dovi_setting->core1_reg_lut[3] = 0x000000ea00000001; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format = src_format; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag = el_flag; - ((struct tv_dovi_setting_s *)tv_dovi_setting) + tv_dovi_setting->src_format = src_format; + tv_dovi_setting->el_flag = el_flag; + tv_dovi_setting ->el_halfsize_flag = el_halfsize_flag; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_width = w; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_height = h; - ((struct tv_dovi_setting_s *)tv_dovi_setting) + tv_dovi_setting->video_width = w; + tv_dovi_setting->video_height = h; + tv_dovi_setting ->input_mode = input_mode; tv_dovi_setting_change_flag = true; dovi_setting_video_flag = video_frame; @@ -5243,16 +5445,13 @@ int dolby_vision_parse_metadata( flag, total_md_size); } - dump_tv_setting( - (struct tv_dovi_setting_s *)tv_dovi_setting, + dump_tv_setting(tv_dovi_setting, frame_count, debug_dolby); el_mode = el_flag; ret = 0; /* setting updated */ } else { - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_width = 0; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_height = 0; + tv_dovi_setting->video_width = 0; + tv_dovi_setting->video_height = 0; pr_dolby_error("tv_control_path() failed\n"); } return ret; @@ -5341,7 +5540,7 @@ int dolby_vision_parse_metadata( || (dst_format != dovi_setting.dst_format) || ((!(dolby_vision_flags & FLAG_CERTIFICAION)) && (frame_count == 0))) - p_funcs->control_path( + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -5497,7 +5696,7 @@ int dolby_vision_parse_metadata( #endif new_dovi_setting.video_width = w << 16; new_dovi_setting.video_height = h << 16; - flag = p_funcs->control_path( + flag = p_funcs_stb->control_path( src_format, dst_format, comp_buf[currentId], ((src_format == FORMAT_DOVI) @@ -5595,12 +5794,10 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) if (dolby_vision_flags & FLAG_CERTIFICAION) { bool ott_mode = true; - if (is_meson_txlx_tvmode() + if (is_meson_tvmode() && !force_stb_mode) - ott_mode = - (((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode != - INPUT_MODE_HDMI); + ott_mode = tv_dovi_setting->input_mode != + INPUT_MODE_HDMI; if ((setting_update_count > crc_count) && (ott_mode == true)) return 1; @@ -5700,7 +5897,7 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) } /* don't use run mode when sdr -> dv and vd1 not disable */ if (dolby_vision_wait_init && - (READ_VPP_REG(VPP_MISC) & (1<<10))) + (READ_VPP_DV_REG(VPP_MISC) & (1<<10))) dolby_vision_on_count = dolby_vision_run_mode_delay + 1; } @@ -5764,14 +5961,14 @@ static void bypass_pps_path(u8 pps_state) if (is_meson_txlx_package_962E() || force_stb_mode) { if (pps_state == 2) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 0, 1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); } else if (pps_state == 1) { - _VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 0, 1); - _VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); } } @@ -5793,8 +5990,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, bool reset_flag = false; bool force_set = false; - if (!is_meson_gxm() && !is_meson_txlx() - && !is_meson_g12()) + if (!is_meson_box() && !is_meson_txlx() && !is_meson_tm2()) return -1; if (dolby_vision_flags & FLAG_CERTIFICAION) { @@ -5824,20 +6020,18 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, & FLAG_FRAME_DELAY_MASK; bool ott_mode = true; - if (is_meson_txlx_tvmode() + if (is_meson_tvmode() && !force_stb_mode) ott_mode = - (((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode != + (tv_dovi_setting->input_mode != INPUT_MODE_HDMI); if ((is_meson_txlx_stbmode() - || is_meson_gxm() - || is_meson_g12() + || is_meson_box() || force_stb_mode) && (setting_update_count == 1) && (crc_read_delay == 1)) { /* work around to enable crc for frame 0 */ - _VSYNC_WR_MPEG_REG(0x36fb, 1); + VSYNC_WR_DV_REG(0x36fb, 1); crc_read_delay++; } else { crc_read_delay++; @@ -5868,10 +6062,8 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } #ifdef V2_4 - if (is_meson_txlx_stbmode() - || is_meson_gxm() - || is_meson_g12() - || force_stb_mode) { + if (is_meson_txlx_stbmode() || is_meson_box() + || is_meson_tm2_stbmode() || force_stb_mode) { if (last_dolby_vision_ll_policy != dolby_vision_ll_policy) { /* handle ll mode policy change */ @@ -5887,7 +6079,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { if (vinfo && sink_support_dolby_vision(vinfo)) dolby_vision_set_toggle_flag(1); - if (!is_meson_txlx_tvmode() || force_stb_mode) { + if (!is_meson_tvmode() || force_stb_mode) { if (vinfo && vinfo->vout_device && (!vinfo->vout_device->dv_info) && (vsync_count < FLAG_VSYNC_CNT)) { @@ -5898,7 +6090,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, if (dolby_vision_status != BYPASS_PROCESS) { enable_dolby_vision(0); if (vinfo && - !is_meson_txlx_tvmode() && + !is_meson_tvmode() && !force_stb_mode) send_hdmi_pkt(FORMAT_SDR, vinfo); if (dolby_vision_flags & FLAG_TOGGLE_FRAME) @@ -5911,7 +6103,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, || (dolby_vision_flags & FLAG_BYPASS_VPP)) video_effect_bypass(1); - if (!p_funcs) { + if (!p_funcs_stb && !p_funcs_tv) { dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; tv_dovi_setting_change_flag = false; new_dovi_setting.video_width = 0; @@ -5930,7 +6122,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, (dolby_vision_reset & 1) && (!dolby_vision_core1_on) && (dolby_vision_on_count == 0); - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { if (tv_dovi_setting_change_flag) { if (vf && (vf->type & VIDTYPE_VIU_422)) src_chroma_format = 2; @@ -5941,22 +6133,17 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, & FLAG_CERTIFICAION)) reset_flag = true; tv_dolby_core1_set( - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut, + tv_dovi_setting->core1_reg_lut, h_size, v_size, dovi_setting_video_flag, /* BL enable */ dovi_setting_video_flag - && (((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag), /* EL en */ - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_halfsize_flag, + && (tv_dovi_setting->el_flag), + tv_dovi_setting->el_halfsize_flag, src_chroma_format, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode == + tv_dovi_setting->input_mode == INPUT_MODE_HDMI, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format == + tv_dovi_setting->src_format == FORMAT_HDR10, reset_flag ); @@ -5971,8 +6158,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, core1_disp_hsize = h_size; core1_disp_vsize = v_size; update_dolby_vision_status( - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format); + tv_dovi_setting->src_format); } } else { if ((new_dovi_setting.video_width & 0xffff) @@ -6041,29 +6227,24 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, dolby_vision_on_count, reset_flag); } - } else if (is_meson_txlx_tvmode()) { + } else if (is_meson_tvmode()) { if ((dolby_vision_on_count <= dolby_vision_run_mode_delay) || force_set) { if (force_set) reset_flag = true; tv_dolby_core1_set( - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut, + tv_dovi_setting->core1_reg_lut, h_size, v_size, dovi_setting_video_flag, /* BL enable */ dovi_setting_video_flag && - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag, /*ELenable*/ - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_halfsize_flag, + tv_dovi_setting->el_flag, /*ELenable*/ + tv_dovi_setting->el_halfsize_flag, src_chroma_format, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode == + tv_dovi_setting->input_mode == INPUT_MODE_HDMI, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format == + tv_dovi_setting->src_format == FORMAT_HDR10, reset_flag); core1_disp_hsize = h_size; @@ -6074,8 +6255,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, dolby_vision_on_count, reset_flag); } - } else if (is_meson_gxm() || - is_meson_g12()) { + } else if (is_meson_box() || is_meson_tm2_stbmode()) { if ((dolby_vision_on_count <= dolby_vision_run_mode_delay) || force_set) { @@ -6133,8 +6313,7 @@ EXPORT_SYMBOL(dolby_vision_set_toggle_flag); void set_dolby_vision_mode(int mode) { - if ((is_meson_gxm() || is_meson_txlx() || - is_meson_g12()) + if ((is_meson_box() || is_meson_txlx() || is_meson_tm2()) && dolby_vision_enable && (dolby_vision_request_mode == 0xff)) { if (dolby_vision_policy_process( @@ -6167,9 +6346,9 @@ EXPORT_SYMBOL(is_dolby_vision_enable); bool is_dolby_vision_stb_mode(void) { return force_stb_mode || - is_meson_txlx_stbmode() || - is_meson_gxm() || - is_meson_g12(); + is_meson_txlx_stbmode() || + is_meson_tm2_stbmode() || + is_meson_box(); } EXPORT_SYMBOL(is_dolby_vision_stb_mode); @@ -6179,56 +6358,63 @@ int register_dv_functions(const struct dolby_vision_func_s *func) unsigned int reg_clk; unsigned int reg_value; struct pq_config_s *pq_config; - struct tv_dovi_setting_s *dovi_setting; const struct vinfo_s *vinfo = get_current_vinfo(); - if (!p_funcs && func) { - pr_info("*** register_dv_functions. version %s ***\n", - func->version_info); + if ((!p_funcs_stb || !p_funcs_tv) && func) { + if (func->control_path && !p_funcs_stb) { + pr_info("*** register_dv_stb_functions. version %s ***\n", + func->version_info); + p_funcs_stb = func; + } else if (func->tv_control_path && !p_funcs_tv) { + pr_info("*** register_dv_tv_functions. version %s ***\n", + func->version_info); + p_funcs_tv = func; + } else + return ret; ret = 0; /* get efuse flag*/ - reg_clk = READ_VPP_REG(DOLBY_TV_CLKGATE_CTRL); - WRITE_VPP_REG(DOLBY_TV_CLKGATE_CTRL, 0x2800); - reg_value = READ_VPP_REG(DOLBY_TV_REG_START + 1); - if (is_meson_txlx_tvmode() - || is_meson_txlx_stbmode()) { + + if (is_meson_txlx() || is_meson_tm2()) { + reg_clk = READ_VPP_DV_REG(DOLBY_TV_CLKGATE_CTRL); + WRITE_VPP_DV_REG(DOLBY_TV_CLKGATE_CTRL, 0x2800); + reg_value = READ_VPP_DV_REG(DOLBY_TV_REG_START + 1); if ((reg_value & 0x400) == 0) efuse_mode = 0; else efuse_mode = 1; + WRITE_VPP_DV_REG(DOLBY_TV_CLKGATE_CTRL, reg_clk); } else { + reg_value = READ_VPP_DV_REG(DOLBY_CORE1_REG_START + 1); if ((reg_value & 0x100) == 0) efuse_mode = 0; else efuse_mode = 1; } - WRITE_VPP_REG(DOLBY_TV_CLKGATE_CTRL, reg_clk); - pr_dolby_dbg - ("efuse_mode=%d reg_value = 0x%x\n", - efuse_mode, - reg_value); + pr_dolby_dbg("efuse_mode=%d reg_value = 0x%x\n", + efuse_mode, reg_value); /*stb core doesn't need run mode*/ /*TV core need run mode and the value is 2*/ - if (is_meson_gxm() || is_meson_g12() || - is_meson_txlx_stbmode() || force_stb_mode) + if (is_meson_box() || is_meson_txlx_stbmode() + || is_meson_tm2_stbmode() || force_stb_mode) dolby_vision_run_mode_delay = 0; else dolby_vision_run_mode_delay = RUN_MODE_DELAY; - pq_config = vmalloc(sizeof(struct pq_config_s)); - if (!pq_config) - return -ENOMEM; + if (is_meson_txlx() || is_meson_tm2()) { + pq_config = vmalloc(sizeof(struct pq_config_s)); + if (!pq_config) + return -ENOMEM; + pq_config_fake = (struct pq_config_s *)pq_config; - pq_config_fake = (struct pq_config_s *)pq_config; - dovi_setting = vmalloc(sizeof(struct tv_dovi_setting_s)); - if (!dovi_setting) + tv_dovi_setting = + vmalloc(sizeof(struct tv_dovi_setting_s)); + if (!tv_dovi_setting) return -ENOMEM; - - tv_dovi_setting = (struct tv_dovi_setting_s *)dovi_setting; + } /* adjust core2 setting to work around fixing with 1080p24hz */ if (is_meson_txlx()) g_vpotch = 0x20; - else if (is_meson_g12()) { + else if (is_meson_g12() || is_meson_tm2_stbmode()) { if (vinfo) { if ((vinfo->width < 1280) && (vinfo->height < 720) && @@ -6240,7 +6426,6 @@ int register_dv_functions(const struct dolby_vision_func_s *func) g_vpotch = 0x8; } else g_vpotch = 0x8; - p_funcs = func; } return ret; } @@ -6261,7 +6446,7 @@ int unregister_dv_functions(void) comp_buf[i] = NULL; } } - if (p_funcs) { + if (p_funcs_stb || p_funcs_tv) { pr_info("*** unregister_dv_functions ***\n"); if (pq_config_fake) { vfree(pq_config_fake); @@ -6271,7 +6456,8 @@ int unregister_dv_functions(void) vfree(tv_dovi_setting); tv_dovi_setting = NULL; } - p_funcs = NULL; + p_funcs_stb = NULL; + p_funcs_tv = NULL; ret = 0; } return ret; @@ -6315,13 +6501,13 @@ void tv_dolby_vision_insert_crc(bool print) crc_count++; return; } - if (is_meson_txlx_tvmode() + if (is_meson_tvmode() && !force_stb_mode) { - crc_enable = (READ_VPP_REG(0x33e7) == 0xb); - crc = READ_VPP_REG(0x33ef); + crc_enable = (READ_VPP_DV_REG(0x33e7) == 0xb); + crc = READ_VPP_DV_REG(0x33ef); } else { - crc_enable = true; /* (READ_VPP_REG(0x36fb) & 1); */ - crc = READ_VPP_REG(0x36fd); + crc_enable = true; /* (READ_VPP_DV_REG(0x36fb) & 1); */ + crc = READ_VPP_DV_REG(0x36fd); } if ((crc == 0) || (crc_enable == false) || (!crc_output_buf)) { crc_bypass_count++; @@ -6362,10 +6548,10 @@ void tv_dolby_vision_dma_table_modify(u32 tbl_id, uint64_t value) void tv_dolby_vision_efuse_info(void) { - if (p_funcs != NULL) { + if (p_funcs_tv != NULL) { pr_info("\n dv efuse info:\n"); pr_info("efuse_mode:%d, version: %s\n", - efuse_mode, p_funcs->version_info); + efuse_mode, p_funcs_tv->version_info); } else { pr_info("\n p_funcs is NULL\n"); pr_info("efuse_mode:%d\n", efuse_mode); @@ -6612,7 +6798,7 @@ static struct class_attribute amdolby_vision_class_attrs[] = { __ATTR(debug, 0644, amdolby_vision_debug_show, amdolby_vision_debug_store), __ATTR(dv_mode, 0644, - amdolby_vision_dv_mode_show, amdolby_vision_dv_mode_store), + amdolby_vision_dv_mode_show, amdolby_vision_dv_mode_store), __ATTR_NULL }; @@ -6628,6 +6814,11 @@ static struct dv_device_data_s dolby_vision_g12 = { .cpu_id = _CPU_MAJOR_ID_G12, }; +static struct dv_device_data_s dolby_vision_tm2 = { + .cpu_id = _CPU_MAJOR_ID_TM2, +}; + + static const struct of_device_id amlogic_dolby_vision_match[] = { { .compatible = "amlogic, dolby_vision_gxm", @@ -6649,6 +6840,10 @@ static const struct of_device_id amlogic_dolby_vision_match[] = { .compatible = "amlogic, dolby_vision_sm1", .data = &dolby_vision_g12, }, + { + .compatible = "amlogic, dolby_vision_tm2", + .data = &dolby_vision_tm2, + }, {}, }; diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h index d1bd610590c7..456a1ff8bd83 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h @@ -526,6 +526,7 @@ enum cpuID_e { _CPU_MAJOR_ID_GXM, _CPU_MAJOR_ID_TXLX, _CPU_MAJOR_ID_G12, + _CPU_MAJOR_ID_TM2, _CPU_MAJOR_ID_UNKNOWN, }; diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h index 0651c43e527e..cfc91d17397d 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h @@ -18,78 +18,101 @@ #ifndef VPP_DOLBYVISION_REGS_H #define VPP_DOLBYVISION_REGS_H -#define DOLBY_CORE1_REG_START 0x3300 -#define DOLBY_CORE1_CLKGATE_CTRL 0x33f2 -#define DOLBY_CORE1_SWAP_CTRL0 0x33f3 -#define DOLBY_CORE1_SWAP_CTRL1 0x33f4 -#define DOLBY_CORE1_SWAP_CTRL2 0x33f5 -#define DOLBY_CORE1_SWAP_CTRL3 0x33f6 -#define DOLBY_CORE1_SWAP_CTRL4 0x33f7 -#define DOLBY_CORE1_SWAP_CTRL5 0x33f8 -#define DOLBY_CORE1_DMA_CTRL 0x33f9 -#define DOLBY_CORE1_DMA_STATUS 0x33fa -#define DOLBY_CORE1_STATUS0 0x33fb -#define DOLBY_CORE1_STATUS1 0x33fc -#define DOLBY_CORE1_STATUS2 0x33fd -#define DOLBY_CORE1_STATUS3 0x33fe -#define DOLBY_CORE1_DMA_PORT 0x33ff +#define CORE1_OFFSET (0x1UL << 24) +#define CORE1_1_OFFSET (0x1UL << 25) +#define CORE2A_OFFSET (0x1UL << 26) +#define CORE3_OFFSET (0x1UL << 27) +#define CORETV_OFFSET (0x1UL << 28) -#define DOLBY_CORE2A_REG_START 0x3400 -#define DOLBY_CORE2A_CTRL 0x3401 -#define DOLBY_CORE2A_CLKGATE_CTRL 0x3432 -#define DOLBY_CORE2A_SWAP_CTRL0 0x3433 -#define DOLBY_CORE2A_SWAP_CTRL1 0x3434 -#define DOLBY_CORE2A_SWAP_CTRL2 0x3435 -#define DOLBY_CORE2A_SWAP_CTRL3 0x3436 -#define DOLBY_CORE2A_SWAP_CTRL4 0x3437 -#define DOLBY_CORE2A_SWAP_CTRL5 0x3438 -#define DOLBY_CORE2A_DMA_CTRL 0x3439 -#define DOLBY_CORE2A_DMA_STATUS 0x343a -#define DOLBY_CORE2A_STATUS0 0x343b -#define DOLBY_CORE2A_STATUS1 0x343c -#define DOLBY_CORE2A_STATUS2 0x343d -#define DOLBY_CORE2A_STATUS3 0x343e -#define DOLBY_CORE2A_DMA_PORT 0x343f +#define DOLBY_CORE1_REG_START (0x00 + CORE1_OFFSET) +#define DOLBY_CORE1_CLKGATE_CTRL (0xf2 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL0 (0xf3 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL1 (0xf4 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL2 (0xf5 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL3 (0xf6 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL4 (0xf7 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL5 (0xf8 + CORE1_OFFSET) +#define DOLBY_CORE1_DMA_CTRL (0xf9 + CORE1_OFFSET) +#define DOLBY_CORE1_DMA_STATUS (0xfa + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS0 (0xfb + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS1 (0xfc + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS2 (0xfd + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS3 (0xfe + CORE1_OFFSET) +#define DOLBY_CORE1_DMA_PORT (0xff + CORE1_OFFSET) -#define DOLBY_CORE3_REG_START 0x3600 -#define DOLBY_CORE3_CLKGATE_CTRL 0x36f0 -#define DOLBY_CORE3_SWAP_CTRL0 0x36f1 -#define DOLBY_CORE3_SWAP_CTRL1 0x36f2 -#define DOLBY_CORE3_SWAP_CTRL2 0x36f3 -#define DOLBY_CORE3_SWAP_CTRL3 0x36f4 -#define DOLBY_CORE3_SWAP_CTRL4 0x36f5 -#define DOLBY_CORE3_SWAP_CTRL5 0x36f6 -#define DOLBY_CORE3_SWAP_CTRL6 0x36f7 -#define DOLBY_CORE3_DIAG_CTRL 0x36f8 +#define DOLBY_CORE1_1_REG_START (0x00 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_CLKGATE_CTRL (0xf2 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL0 (0xf3 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL1 (0xf4 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL2 (0xf5 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL3 (0xf6 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL4 (0xf7 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL5 (0xf8 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_DMA_CTRL (0xf9 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_DMA_STATUS (0xfa + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS0 (0xfb + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS1 (0xfc + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS2 (0xfd + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS3 (0xfe + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_DMA_PORT (0xff + CORE1_1_OFFSET) -#define DOLBY_CORE3_CRC_CTRL 0x36fb -#define DOLBY_CORE3_INPUT_CSC_CRC 0x36fc -#define DOLBY_CORE3_OUTPUT_CSC_CRC 0x36fd -#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d -#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d -#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd +#define DOLBY_CORE2A_REG_START (0x00 + CORE2A_OFFSET) +#define DOLBY_CORE2A_CTRL (0x01 + CORE2A_OFFSET) +#define DOLBY_CORE2A_CLKGATE_CTRL (0x32 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL0 (0x33 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL1 (0x34 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL2 (0x35 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL3 (0x36 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL4 (0x37 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL5 (0x38 + CORE2A_OFFSET) +#define DOLBY_CORE2A_DMA_CTRL (0x39 + CORE2A_OFFSET) +#define DOLBY_CORE2A_DMA_STATUS (0x3a + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS0 (0x3b + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS1 (0x3c + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS2 (0x3d + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS3 (0x3e + CORE2A_OFFSET) +#define DOLBY_CORE2A_DMA_PORT (0x3f + CORE2A_OFFSET) +#define DOLBY_CORE3_REG_START (0x00 + CORE3_OFFSET) +#define DOLBY_CORE3_CLKGATE_CTRL (0xf0 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL0 (0xf1 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL1 (0xf2 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL2 (0xf3 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL3 (0xf4 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL4 (0xf5 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL5 (0xf6 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL6 (0xf7 + CORE3_OFFSET) +#define DOLBY_CORE3_DIAG_CTRL (0xf8 + CORE3_OFFSET) +#define DOLBY_CORE3_CRC_CTRL (0xfb + CORE3_OFFSET) +#define DOLBY_CORE3_INPUT_CSC_CRC (0xfc + CORE3_OFFSET) +#define DOLBY_CORE3_OUTPUT_CSC_CRC (0xfd + CORE3_OFFSET) + +#define DOLBY_TV_REG_START (0x00 + CORETV_OFFSET) +#define DOLBY_TV_CLKGATE_CTRL (0xf1 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL0 (0xf2 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL1 (0xf3 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL2 (0xf4 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL3 (0xf5 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL4 (0xf6 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL5 (0xf7 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL6 (0xf8 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL7 (0xf9 + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL0 (0xfa + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL1 (0xfb + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL2 (0xfc + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL3 (0xfd + CORETV_OFFSET) +#define DOLBY_TV_STATUS0 (0xfe + CORETV_OFFSET) +#define DOLBY_TV_STATUS1 (0xff + CORETV_OFFSET) + + +#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d +#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d +#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd #define DOLBY_PATH_CTRL 0x1a0c #define VIU_MISC_CTRL1 0x1a07 #define VPP_DOLBY_CTRL 0x1d93 #define VIU_SW_RESET 0x1a01 #define VPU_HDMI_FMT_CTRL 0x2743 -#define DOLBY_TV_REG_START 0x3300 -#define DOLBY_TV_CLKGATE_CTRL 0x33f1 -#define DOLBY_TV_SWAP_CTRL0 0x33f2 -#define DOLBY_TV_SWAP_CTRL1 0x33f3 -#define DOLBY_TV_SWAP_CTRL2 0x33f4 -#define DOLBY_TV_SWAP_CTRL3 0x33f5 -#define DOLBY_TV_SWAP_CTRL4 0x33f6 -#define DOLBY_TV_SWAP_CTRL5 0x33f7 -#define DOLBY_TV_SWAP_CTRL6 0x33f8 -#define DOLBY_TV_SWAP_CTRL7 0x33f9 -#define DOLBY_TV_AXI2DMA_CTRL0 0x33fa -#define DOLBY_TV_AXI2DMA_CTRL1 0x33fb -#define DOLBY_TV_AXI2DMA_CTRL2 0x33fc -#define DOLBY_TV_AXI2DMA_CTRL3 0x33fd -#define DOLBY_TV_STATUS0 0x33fe -#define DOLBY_TV_STATUS1 0x33ff #if 0 /* core 1 display manager 24 registers */ struct dm_register_ipcore_1_s { diff --git a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h index f8a2ceb62f7f..59ba5231a739 100644 --- a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h +++ b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h @@ -48,9 +48,14 @@ extern int dolby_vision_update_setting(void); extern bool is_dolby_vision_stb_mode(void); extern bool is_meson_g12(void); extern bool is_meson_gxm(void); +extern bool is_meson_box(void); extern bool is_meson_txlx(void); extern bool is_meson_txlx_tvmode(void); extern bool is_meson_txlx_stbmode(void); +extern bool is_meson_tm2(void); +extern bool is_meson_tm2_tvmode(void); +extern bool is_meson_tm2_stbmode(void); +extern bool is_meson_tvmode(void); extern void tv_dolby_vision_crc_clear(int flag); extern char *tv_dolby_vision_get_crc(u32 *len); extern void tv_dolby_vision_insert_crc(bool print); From 43cc425ff697e6ef0ba152805a6d5c4b4e9ab252 Mon Sep 17 00:00:00 2001 From: "cancan.chang" Date: Fri, 12 Apr 2019 13:03:45 +0800 Subject: [PATCH 0402/1060] NNA: add NNA support on tm2 [1/1] PD#SWPL-5623 Problem: tm2 not support NNA now. Solution: add NNA support. Verify: Verified on tm2_ab319 Change-Id: Ib41544d0ebeb3f25442692ac3365ad3a5fc5d4ab Signed-off-by: Cancan Chang --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 18 +++++++++++++++++- arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 4 +++- arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 4 +++- arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 4 +++- arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 4 +++- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 18 +++++++++++++++++- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 4 +++- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 4 +++- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 4 +++- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 4 +++- 10 files changed, 58 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index a0d7570b635c..e89d41a7a309 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1235,7 +1235,23 @@ pcie-ctrl-iso-shift = <20>; status = "disabled"; }; - + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + interrupts = <0 147 4>; + interrupt-names = "galcore"; + reg = <0xff100000 0x800 + /*reg base value:0xff100000 */ + 0xff000000 0x400000 + /*Sram bse value:0xff000000*/ + 0xff63c118 0x0 + 0xff63c11c 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0xffd01088 0x0 + /*0xffd01088:reset reg*/ + >; + }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; compatible = "amlogic, meson-mmc-tm2"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 648dc4380cdd..ccea9250688b 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -187,7 +187,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 30960e570255..8e61cadadbf8 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -184,7 +184,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 1caa667f7b2c..281a219fd5c3 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -187,7 +187,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index e2941a2b1789..37dfc5ab9a6c 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -184,7 +184,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index d53c942e31db..99f3db82eba3 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1215,7 +1215,23 @@ pcie-ctrl-iso-shift = <20>; status = "disabled"; }; - + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + interrupts = <0 147 4>; + interrupt-names = "galcore"; + reg = <0x0 0xff100000 0x0 0x800 + /*reg base value:0xff100000 */ + 0x0 0xff000000 0x0 0x400000 + /*Sram bse value:0xff000000*/ + 0x0 0xff63c118 0x0 0x0 + 0x0 0xff63c11c 0x0 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0x0 0xffd01088 0x0 0x0 + /*0xffd01088:reset reg*/ + >; + }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; compatible = "amlogic, meson-mmc-tm2"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 4ba3670eda9f..44ab736125f9 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -183,7 +183,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index c6c153104115..f9f60602f56f 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -184,7 +184,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 509130f8ccb6..ec42a3ce80dd 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -183,7 +183,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 8b9f56eea72b..7db627f29e7f 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -184,7 +184,9 @@ linux,contiguous-region; }; }; /* end of reserved-memory */ - + galcore { + status = "okay"; + }; codec_mm { compatible = "amlogic, codec, mm"; status = "okay"; From cfd8ed74ce61b94a004e0edd712d3cd7bf76e1f8 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 10 Apr 2019 16:37:54 +0800 Subject: [PATCH 0403/1060] cec: cec bringup for tm2 [1/1] PD#SWPL-6945 Problem: bringup for tm2 Solution: add chip support and modify dts Verify: tm2 Change-Id: I718c3b81912a3555e19866f96d392bfb09d27384 Signed-off-by: Yong Qin --- arch/arm/boot/dts/amlogic/tm2_pxp.dts | 6 +++-- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 6 +++-- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 6 +++-- .../arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 6 +++-- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 6 +++-- arch/arm64/boot/dts/amlogic/tm2_pxp.dts | 6 +++-- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 6 +++-- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 6 +++-- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 6 +++-- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 6 +++-- drivers/amlogic/cec/hdmi_ao_cec.c | 25 +++++++++++++++++++ drivers/amlogic/cec/hdmi_ao_cec.h | 8 ++++++ 12 files changed, 73 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts index d1165eee0c64..e812ec0f7cb5 100644 --- a/arch/arm/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -548,7 +548,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -556,10 +556,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index ccea9250688b..dabb01f4671e 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -872,7 +872,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -880,10 +880,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 8e61cadadbf8..7e041a8151d3 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -851,7 +851,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -859,10 +859,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 281a219fd5c3..517a72f8b9a9 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -872,7 +872,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -880,11 +880,13 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ arc_port_mask = <0x2>; + output = <1>; /*output port number*/ interrupts = <0 205 1 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 37dfc5ab9a6c..57f919479250 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -851,7 +851,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -859,11 +859,13 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ arc_port_mask = <0x2>; + output = <1>; /*output port number*/ interrupts = <0 205 1 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts index 5951e7526823..defa536fe773 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -547,7 +547,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -555,10 +555,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 44ab736125f9..995204cd7f09 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -867,7 +867,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -875,10 +875,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index f9f60602f56f..def6627bf18b 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -850,7 +850,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -858,10 +858,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index ec42a3ce80dd..03701b9a342c 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -867,7 +867,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -875,10 +875,12 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ arc_port_mask = <0x2>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 7db627f29e7f..bc874844090b 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -850,7 +850,7 @@ }; aocec: aocec { - compatible = "amlogic, aocec-tl1"; + compatible = "amlogic, aocec-tm2"; /*device_name = "aocec";*/ status = "okay"; vendor_name = "Amlogic"; /* Max Chars: 8 */ @@ -858,11 +858,13 @@ * http://standards.ieee.org/develop/regauth/oui/oui.txt */ vendor_id = <0x000000>; - product_desc = "TL1"; /* Max Chars: 16 */ + product_desc = "TM2"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <3>; ee_cec; + /*cec_sel = <2>;*/ arc_port_mask = <0x2>; + output = <1>; /*output port number*/ interrupts = <0 205 1 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 47173ef4d74b..90ac72ffdf76 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -82,6 +82,7 @@ struct cec_platform_data_s { bool ee_to_ao;/*ee cec hw module mv to ao;ao cec delete*/ bool ceca_sts_reg;/*add new internal status register*/ enum cecbver cecb_ver;/* detail discription ref enum cecbver */ + enum cecaver ceca_ver; }; @@ -1135,6 +1136,13 @@ void cec_enable_arc_pin(bool enable) { unsigned int data; + if (is_meson_sm1_cpu() || + cpu_after_eq(MESON_CPU_MAJOR_ID_TM2)) { + /*sm1 and tm2 later, audio module handle this*/ + + return; + } + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) { data = rd_reg_hhi(HHI_HDMIRX_ARC_CNTL); /* enable bit 1:1 bit 0: 0*/ @@ -3065,6 +3073,7 @@ static const struct cec_platform_data_s cec_g12a_data = { .line_bit = 3, .ee_to_ao = 1, .ceca_sts_reg = 0, + .ceca_ver = CECA_VER_0, .cecb_ver = CECB_VER_1, }; @@ -3073,6 +3082,7 @@ static const struct cec_platform_data_s cec_txl_data = { .line_bit = 7, .ee_to_ao = 0, .ceca_sts_reg = 0, + .ceca_ver = CECA_VER_0, .cecb_ver = CECB_VER_0, }; @@ -3081,6 +3091,7 @@ static const struct cec_platform_data_s cec_tl1_data = { .line_bit = 10, .ee_to_ao = 1, .ceca_sts_reg = 1, + .ceca_ver = CECA_VER_0, .cecb_ver = CECB_VER_2, }; @@ -3089,6 +3100,16 @@ static const struct cec_platform_data_s cec_sm1_data = { .line_bit = 3, .ee_to_ao = 1, .ceca_sts_reg = 1, + .ceca_ver = CECA_VER_1, + .cecb_ver = CECB_VER_2, +}; + +static const struct cec_platform_data_s cec_tm2_data = { + .line_reg = 0, + .line_bit = 3, + .ee_to_ao = 1, + .ceca_sts_reg = 1, + .ceca_ver = CECA_VER_1, .cecb_ver = CECB_VER_2, }; @@ -3117,6 +3138,10 @@ static const struct of_device_id aml_cec_dt_match[] = { .compatible = "amlogic, aocec-sm1", .data = &cec_sm1_data, }, + { + .compatible = "amlogic, aocec-tm2", + .data = &cec_tm2_data, + }, {} }; #endif diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index e76e6484ef5a..9ea6ec37170f 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -29,6 +29,14 @@ #define CEC_PHY_PORT_NUM 4 #define HR_DELAY(n) (ktime_set(0, n * 1000 * 1000)) +enum cecaver { + /*first version*/ + CECA_VER_0 = 0, + + /*support multi logical address*/ + CECA_VER_1 = 1, +}; + enum cecbver { /*first version*/ CECB_VER_0 = 0, From 1ace026476a5c7e6207875d6f294e2fbed741729 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Thu, 11 Apr 2019 15:03:06 +0800 Subject: [PATCH 0404/1060] dv: fix error color when playing dv films with EL under tm2 platform [1/1] PD#SWPL-6338 Problem: error color when playing dv films with EL under tm2 platform Solution: bypass dv core Verify: tm2 Change-Id: I477ea5dbdcf2a0af3783aa62200809f2ed89be5e Signed-off-by: Yi Zhou --- .../enhancement/amdolby_vision/amdolby_vision.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index e6c09c8568a9..1f5812dae953 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -377,7 +377,7 @@ uint16_t L2PQ_500_4000[] = { static uint32_t tv_max_lin = 200; static uint16_t tv_max_pq = 2372; -static unsigned int panel_max_lumin; +static unsigned int panel_max_lumin = 300; module_param(panel_max_lumin, uint, 0664); MODULE_PARM_DESC(panel_max_lumin, "\n panel_max_lumin\n"); @@ -3210,6 +3210,9 @@ void enable_dolby_vision(int enable) /* 16 core1 bl bypass */ (1 << 0), 16, 2); + if (is_meson_tm2_tvmode()) + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, 3, 0, 2); #ifdef V1_5 if (p_funcs_tv) /* destroy ctx */ p_funcs_tv->tv_control_path( @@ -5273,7 +5276,6 @@ int dolby_vision_parse_metadata( h = (vf->type & VIDTYPE_COMPRESS) ? vf->compHeight : vf->height; } - if ((src_format == FORMAT_DOVI) && meta_flag_bl && meta_flag_el) { /* dovi frame no meta or meta error */ @@ -5317,8 +5319,13 @@ int dolby_vision_parse_metadata( return -1; } - if (!p_funcs_stb && !p_funcs_tv) - return -1; + if (tv_mode) { + if (!p_funcs_tv) + return -1; + } else { + if (!p_funcs_stb) + return -1; + } /* TV core */ if (is_meson_tvmode() && !force_stb_mode) { @@ -6071,11 +6078,13 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } } #endif + if (!vf) { if (dolby_vision_flags & FLAG_TOGGLE_FRAME) dolby_vision_parse_metadata( NULL, 1, false); } + if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { if (vinfo && sink_support_dolby_vision(vinfo)) dolby_vision_set_toggle_flag(1); From 0ec4248ec63caa6a9a992a8aae85987aa627eab4 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Tue, 9 Apr 2019 22:34:05 +0800 Subject: [PATCH 0405/1060] power: add is_support_pwr_ctrl function. [2/2] PD#SWPL-5261 Problem: bringup sm1 and tm2. Solution: add is_support_pwr_ctrl function. Verify: U212 and AC200 Change-Id: I7f392ea8f23ce6f4e610b98bdcc39c4fcc2e6444 Signed-off-by: Nanxin Qin --- drivers/amlogic/power/power_ctrl.c | 6 ++++++ include/linux/amlogic/power_ctrl.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/amlogic/power/power_ctrl.c b/drivers/amlogic/power/power_ctrl.c index ad0b7845d942..d7f64d72aabe 100644 --- a/drivers/amlogic/power/power_ctrl.c +++ b/drivers/amlogic/power/power_ctrl.c @@ -37,6 +37,12 @@ struct power_ctrl { struct power_ctrl ctrl; static bool probe_done; +bool is_support_power_ctrl(void) +{ + return probe_done; +} +EXPORT_SYMBOL(is_support_power_ctrl); + int power_ctrl_sleep(bool power_on, unsigned int shift) { unsigned int val; diff --git a/include/linux/amlogic/power_ctrl.h b/include/linux/amlogic/power_ctrl.h index f0ab6117fbb2..3a09e58a52f0 100644 --- a/include/linux/amlogic/power_ctrl.h +++ b/include/linux/amlogic/power_ctrl.h @@ -20,6 +20,7 @@ #include #ifdef CONFIG_AMLOGIC_POWER +bool is_support_power_ctrl(void); int power_ctrl_sleep(bool power_on, unsigned int shift); int power_ctrl_sleep_mask(bool power_on, unsigned int mask_val, unsigned int shift); From 15908c9b3445d52dcecc30b4a28771bc0e23ef80 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Fri, 12 Apr 2019 21:04:03 +0800 Subject: [PATCH 0406/1060] dv: add polling interface for systemcontrol [1/1] PD#SWPL-6338 Problem: add polling interface for systemcontrol Solution: add polling interface for systemcontrol Verify: tm2 Change-Id: I1a0a9a3028592ee0df77b33c9c617cbdd9b07d70 Signed-off-by: Yi Zhou --- .../amdolby_vision/amdolby_vision.c | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index 1f5812dae953..a32dec57972a 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include "amdolby_vision.h" #include @@ -69,6 +71,7 @@ struct amdolby_vision_dev_s { dev_t devno; struct device *dev; struct class *clsp; + wait_queue_head_t dv_queue; }; static struct amdolby_vision_dev_s amdolby_vision_dev; struct dv_device_data_s dv_meson_dev; @@ -377,7 +380,7 @@ uint16_t L2PQ_500_4000[] = { static uint32_t tv_max_lin = 200; static uint16_t tv_max_pq = 2372; -static unsigned int panel_max_lumin = 300; +static unsigned int panel_max_lumin = 350; module_param(panel_max_lumin, uint, 0664); MODULE_PARM_DESC(panel_max_lumin, "\n panel_max_lumin\n"); @@ -1207,6 +1210,24 @@ static int WRITE_VPP_DV_REG(u32 adr, const u32 val) return 0; } +void amdolby_vision_wakeup_queue(void) +{ + struct amdolby_vision_dev_s *devp = &amdolby_vision_dev; + + wake_up(&devp->dv_queue); +} + +static unsigned int amdolby_vision_poll(struct file *file, poll_table *wait) +{ + struct amdolby_vision_dev_s *devp = file->private_data; + unsigned int mask = 0; + + poll_wait(file, &devp->dv_queue, wait); + mask = (POLLIN | POLLRDNORM); + + return mask; +} + static int is_graphics_output_off(void) { if (is_meson_g12() || is_meson_tm2_stbmode()) @@ -4941,7 +4962,7 @@ static void calculate_panel_max_pq( max_lin = (max_lin / 100) * 100 + 500; max_pq = L2PQ_500_4000[(max_lin - 500) / 100]; } - pr_info("panel max lumin changed from %d(%d) to %d(%d)\n", + pr_dolby_dbg("panel max lumin changed from %d(%d) to %d(%d)\n", tv_max_lin, tv_max_pq, max_lin, max_pq); tv_max_lin = max_lin; tv_max_pq = max_pq; @@ -5276,6 +5297,7 @@ int dolby_vision_parse_metadata( h = (vf->type & VIDTYPE_COMPRESS) ? vf->compHeight : vf->height; } + if ((src_format == FORMAT_DOVI) && meta_flag_bl && meta_flag_el) { /* dovi frame no meta or meta error */ @@ -6000,6 +6022,11 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, if (!is_meson_box() && !is_meson_txlx() && !is_meson_tm2()) return -1; + if ((dolby_vision_enable == 1) && (tv_mode == 1)) { + amdolby_vision_wakeup_queue(); + pr_dolby_dbg("wake up dv status queue\n"); + } + if (dolby_vision_flags & FLAG_CERTIFICAION) { if (vf) { h_size = (vf->type & VIDTYPE_COMPRESS) ? @@ -6673,6 +6700,7 @@ static const struct file_operations amdolby_vision_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = amdolby_vision_compat_ioctl, #endif + .poll = amdolby_vision_poll, }; static void parse_param_amdolby_vision(char *buf_orig, char **parm) @@ -6919,6 +6947,7 @@ static int amdolby_vision_probe(struct platform_device *pdev) } dolby_vision_init_receiver(pdev); + init_waitqueue_head(&devp->dv_queue); pr_info("%s: ok\n", __func__); return 0; From ca009f2dea295c2d9bbe7c6de61146d195b984cc Mon Sep 17 00:00:00 2001 From: Liang Ji Date: Fri, 12 Apr 2019 19:05:39 +0800 Subject: [PATCH 0407/1060] partition: change vendor size [1/2] PD#SWPL-6586 Problem: Android P trunk can not compile 64bit kernel Android P vendor size is not enough, 64bit kernel and isp so etc , the size exceeds 256M Solution: change vendor size from 256M into 320M Verify: galilei Change-Id: Icc7b3d7c8d56f5c361acf9722bba6422b8dc3af2 Signed-off-by: Liang Ji --- arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi | 4 ++-- arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi | 4 ++-- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi | 2 +- arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi | 4 ++-- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi | 2 +- arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi index a78cd67fdc23..d917b8fa3f70 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index d210d928d4a1..3047ed5c0dca 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f9dd1c7cbb93..6cbedc415e4f 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x19000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 2b8e7304cac6..13e510e4e931 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi index aeb1dee501f9..3b0796a9cf21 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi index a78cd67fdc23..d917b8fa3f70 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index fc5a9b7490f6..8998e7ea6ebe 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi index c64a54e27c17..83409beb1e53 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f9dd1c7cbb93..6cbedc415e4f 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x19000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 2b8e7304cac6..13e510e4e931 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi index aeb1dee501f9..3b0796a9cf21 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm From 213a12adcb9f55049ffd52eca0a9890811df7d9a Mon Sep 17 00:00:00 2001 From: Shuide Chen Date: Thu, 11 Apr 2019 13:20:46 +0800 Subject: [PATCH 0408/1060] osd: fix osd afbc can't display on android5.1 [1/1] PD#SWPL-6869 Problem: afbc can't display with android5.1, because blank enable called before afbc set, which make osd enable not updated and afbc not enable when hwc post frame Solution: if mali afbc enable, call osd enable. Verify: verified on x301 Change-Id: I1d727a586a66c6e7848d09dfb5c5b74ff7a2e3e6 Signed-off-by: Shuide Chen --- drivers/amlogic/media/osd/osd_hw.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 3222e58b6dbb..471ea826b5b7 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -3924,7 +3924,10 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) .update_func(index); osd_update_window_axis = false; } - if ((osd_enable != osd_hw.enable[index]) + if ((osd_enable != osd_hw.enable[index] || + (osd_hw.osd_meson_dev.afbc_type + == MALI_AFBC && + osd_hw.osd_afbcd[index].enable)) && (skip == false) && (suspend_flag == false)) { osd_hw.enable[index] = osd_enable; @@ -4045,7 +4048,10 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) .update_func(index); osd_update_window_axis = false; } - if ((osd_enable != osd_hw.enable[index]) + if ((osd_enable != osd_hw.enable[index] || + (osd_hw.osd_meson_dev.afbc_type + == MALI_AFBC && + osd_hw.osd_afbcd[index].enable)) && (skip == false) && (suspend_flag == false)) { osd_hw.enable[index] = osd_enable; @@ -4057,7 +4063,9 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) osd_mali_afbc_start(); spin_unlock_irqrestore(&osd_lock, lock_flags); osd_wait_vsync_hw(); - } else if ((osd_enable != osd_hw.enable[index]) + } else if ((osd_enable != osd_hw.enable[index] || + (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC && + osd_hw.osd_afbcd[index].enable)) && (skip == false)) { spin_lock_irqsave(&osd_lock, lock_flags); if (suspend_flag == false) { From a32adb0640c504070812921971432d2250247ee7 Mon Sep 17 00:00:00 2001 From: Blance Tang Date: Mon, 15 Apr 2019 14:20:39 +0800 Subject: [PATCH 0409/1060] buildroot: Add missed amlogic-dt-id in U211 DTS file [1/1] PD#SWPL-7177 Problem: Missing amlogic-dt-id in U211 DTS file Solution: Add back amlogic-dt-id to U211 DTS file Verify: Local Change-Id: I6ef3243bfa3323e7eec5f8044e0b0fe2271fcfa0 Signed-off-by: Blance Tang --- arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts | 1 + arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 5b5f62ee59cc..7ade2256ec4e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -21,6 +21,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u211_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index cc243a6e552b..53e8a3c93976 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -21,6 +21,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u211_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; From f88b9ab9f8b9b2d086835023a873d6c5facead5d Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Mon, 15 Apr 2019 14:28:50 +0800 Subject: [PATCH 0410/1060] dts: debug: enable ftrace_ramoops for new tm2 dts [1/1] PD#SWPL-6028 Problem: enable ftrce in ramoops for new tm2 dtbs Solution: enable ftrce in ramoops for new tm2 dtbs Verify: verified ok Change-Id: Ia7ee3b11784a69ef7d6b7671f9ad75c14ae477f7 Signed-off-by: Jianxin Pan --- arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts | 3 +-- arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 3 +-- arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 3 +-- arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 3 +-- arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 3 +-- arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts | 3 +-- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts | 3 +-- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts | 3 +-- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts | 3 +-- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts | 3 +-- 10 files changed, 10 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts index e2bba8f92513..ad02f6c96fb7 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index dabb01f4671e..d92de5e54fb6 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 7e041a8151d3..68276f3539b7 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 517a72f8b9a9..9fa15f293e1d 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 57f919479250..5847b2b3073d 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts index 4000c820ca63..2d4bd8fef7fc 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 995204cd7f09..c81834076863 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index def6627bf18b..d2f8ed3368bf 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 03701b9a342c..198fce058ec8 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index bc874844090b..9a7baefae854 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved: linux,secmon { From e4f5038214de17178bf5bd8a7bc9361944738597 Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Mon, 15 Apr 2019 10:14:37 +0800 Subject: [PATCH 0411/1060] mm: vmap: decrease wrps num [1/1] PD#SWPL-6813 Problem: sys_ptrace watchpoint can't stop Solution: decrease wrps num Verify: u212 Change-Id: I18947bd91f8dd07cedeebbfca6d7ce01107c6a3e Signed-off-by: Hanjie Lin --- arch/arm64/include/asm/hw_breakpoint.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h index b6b167ac082b..9b5a831601e0 100644 --- a/arch/arm64/include/asm/hw_breakpoint.h +++ b/arch/arm64/include/asm/hw_breakpoint.h @@ -159,9 +159,15 @@ static inline int get_num_brps(void) static inline int get_num_wrps(void) { u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1); +#ifdef CONFIG_AMLOGIC_VMAP + return (1 + + cpuid_feature_extract_unsigned_field(dfr0, + ID_AA64DFR0_WRPS_SHIFT)) - 2; +#else return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_WRPS_SHIFT); +#endif } #endif /* __KERNEL__ */ From a19d26e676fdd0bd4377830070390a69e8faeebf Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Thu, 4 Apr 2019 21:31:12 +0800 Subject: [PATCH 0412/1060] gdc: add trace_mode debug node for gdc timeout issue [1/2] PD#GH-27 Problem: gdc timeout when gdc processing data Solution: add trace_mode debug node Verify: verified on G12B-W400 Change-Id: I85ee5a4203c9da1af755844125716a844da54ad3 Signed-off-by: Jian Cao --- drivers/amlogic/media/gdc/app/gdc_module.c | 279 ++++++++++++++++++++- 1 file changed, 275 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 14dcf1094f17..f6f0af338aa9 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -47,6 +47,12 @@ unsigned int gdc_log_level; struct gdc_manager_s gdc_manager; +static int trace_mode_enable; +static char *config_out_file; +static int config_out_path_defined; + +#define WAIT_THRESHOLD 1000 +#define CONFIG_PATH_LENG 128 static const struct of_device_id gdc_dt_match[] = { {.compatible = "amlogic, g12b-gdc"}, @@ -352,7 +358,6 @@ attach_err: return ret; } - static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) { int fd = -1; @@ -746,6 +751,84 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, return 0; } +u8 __iomem *map_virt_from_phys(phys_addr_t phys, unsigned long total_size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot; + u8 __iomem *vaddr; + int i; + + npages = PAGE_ALIGN(total_size) / PAGE_SIZE; + offset = phys & (~PAGE_MASK); + if (offset) + npages++; + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /*nocache*/ + pgprot = pgprot_noncached(PAGE_KERNEL); + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + + return vaddr; +} + +void unmap_virt_from_phys(u8 __iomem *vaddr) +{ + if (vaddr) { + /* unmap prevois vaddr */ + vunmap(vaddr); + vaddr = NULL; + } +} + +int write_buf_to_file(char *path, char *buf, int size) +{ + int ret = 0; + struct file *fp = NULL; + mm_segment_t old_fs; + loff_t pos = 0; + int w_size = 0; + + if (!path || !config_out_path_defined) { + gdc_log(LOG_ERR, "please define path first\n"); + return -1; + } + + /* change to KERNEL_DS address limit */ + old_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file to write */ + fp = filp_open(path, O_WRONLY|O_CREAT, 0640); + if (IS_ERR(fp)) { + gdc_log(LOG_ERR, "open file error\n"); + ret = -1; + } + + /* Write buf to file */ + w_size = vfs_write(fp, buf, size, &pos); + gdc_log(LOG_INFO, "write w_size = %u, size = %u\n", w_size, size); + + vfs_fsync(fp, 0); + filp_close(fp, NULL); + set_fs(old_fs); + + return w_size; +} + static long meson_gdc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -763,7 +846,12 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, ion_phys_addr_t addr; int index, dma_fd; void __user *argp = (void __user *)arg; + void __iomem *config_virt_addr; + ktime_t start_time, stop_time, diff_time; + int process_time = 0; + int i = 0; + start_time.tv64 = 0; switch (cmd) { case GDC_PROCESS: ret = copy_from_user(&gs, argp, sizeof(gs)); @@ -815,16 +903,53 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); + + if (trace_mode_enable >= 1) + start_time = ktime_get(); + ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); + msecs_to_jiffies(WAIT_THRESHOLD)); if (ret == 0) gdc_log(LOG_ERR, "gdc timeout\n"); + if (ret == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + + if (trace_mode_enable >= 2) { + /* dump regs */ + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); + } + } + gdc_stop(gdc_cmd); + + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } mutex_unlock(&fh->gdev->d_mutext); break; case GDC_RUN: @@ -854,16 +979,52 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, fh->i_paddr, fh->i_len); meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->c_paddr, fh->c_len); + + if (trace_mode_enable >= 1) + start_time = ktime_get(); + ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); + msecs_to_jiffies(WAIT_THRESHOLD)); if (ret == 0) gdc_log(LOG_ERR, "gdc timeout\n"); + if (ret == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + + if (trace_mode_enable >= 2) { + /* dump regs */ + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); + } + } + gdc_stop(gdc_cmd); + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); mutex_unlock(&fh->gdev->d_mutext); @@ -893,16 +1054,54 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, } meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->c_paddr, fh->c_len); + + + if (trace_mode_enable >= 1) + start_time = ktime_get(); + ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); + msecs_to_jiffies(WAIT_THRESHOLD)); if (ret == 0) gdc_log(LOG_ERR, "gdc timeout\n"); + if (ret == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + + if (trace_mode_enable >= 2) { + /* dump regs */ + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); + } + } + gdc_stop(gdc_cmd); + + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); meson_gdc_deinit_dma_addr(fh); @@ -1122,6 +1321,60 @@ static ssize_t loglevel_store(struct device *dev, static DEVICE_ATTR(loglevel, 0664, loglevel_show, loglevel_store); +static ssize_t trace_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + len += sprintf(buf+len, "trace_mode_enable: %d\n", + trace_mode_enable); + return len; +} + +static ssize_t trace_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + int res = 0; + int ret = 0; + + ret = kstrtoint(buf, 0, &res); + pr_info("trace_mode: %d->%d\n", trace_mode_enable, res); + trace_mode_enable = res; + + return len; +} +static DEVICE_ATTR(trace_mode, 0664, trace_mode_show, trace_mode_store); + +static ssize_t config_out_path_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + if (config_out_path_defined) + len += sprintf(buf+len, "config out path: %s\n", + config_out_file); + else + len += sprintf(buf+len, "config out path is not set\n"); + + return len; +} + +static ssize_t config_out_path_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + if (strlen(buf) >= sizeof(config_out_file)) { + pr_info("err: path too long\n"); + } else { + strncpy(config_out_file, buf, CONFIG_PATH_LENG - 1); + config_out_path_defined = 1; + pr_info("set config out path: %s\n", config_out_file); + } + + return len; +} +static DEVICE_ATTR(config_out_path, 0664, config_out_path_show, + config_out_path_store); + irqreturn_t gdc_interrupt_handler(int irq, void *param) { struct meson_gdc_dev_t *gdc_dev = param; @@ -1155,6 +1408,13 @@ static int gdc_platform_probe(struct platform_device *pdev) of_reserved_mem_device_init(&(pdev->dev)); + /* alloc mem to store config out path*/ + config_out_file = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); + if (config_out_file == NULL) { + gdc_log(LOG_ERR, "config out alloc failed\n"); + return -ENOMEM; + } + gdc_dev = devm_kzalloc(&pdev->dev, sizeof(*gdc_dev), GFP_KERNEL); @@ -1215,6 +1475,10 @@ static int gdc_platform_probe(struct platform_device *pdev) &dev_attr_firmware1); device_create_file(gdc_dev->misc_dev.this_device, &dev_attr_loglevel); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_trace_mode); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_config_out_path); platform_set_drvdata(pdev, gdc_dev); return rc; @@ -1229,10 +1493,17 @@ static int gdc_platform_remove(struct platform_device *pdev) &dev_attr_firmware1); device_remove_file(meson_gdc_dev.this_device, &dev_attr_loglevel); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_trace_mode); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_config_out_path); gdc_dma_buffer_destroy(gdc_manager.buffer); gdc_manager.gdc_dev = NULL; + kfree(config_out_file); + config_out_file = NULL; + misc_deregister(&meson_gdc_dev); return 0; } From 4cc7c912e14e439deae9cc2691c5e28dcffe092b Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Mon, 15 Apr 2019 16:32:43 +0800 Subject: [PATCH 0413/1060] audio: AB311 bringup, init 2 AMPs AD82584f [1/1] PD#SWPL-7174 Problem: spk is out of work on AB311 Solution: bringup AMP ad82584f Verify: AB311 Change-Id: I8771fc204b19eeebed5247ec4c8984acbf004372 Signed-off-by: Zhe Wang --- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 25 ++++++++++++------- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 25 +++++++++++++------ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index d92de5e54fb6..a6ea1f07e6b0 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -320,12 +320,12 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = ; + prefix-names = "AMP", "AMP1"; + sound-dai = <&ad82584f &ad82584f1 &tl1_codec>; }; }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -1417,8 +1417,8 @@ pinctrl-names = "spdif_pins", "spdif_pins_mute"; - pinctrl-0 = <&spdifout_a>; - pinctrl-1 = <&spdifout_a_mute>; + pinctrl-0 = <&spdifin_a>; + //pinctrl-1 = <&spdifout_a_mute>; /* * whether do asrc for pcm and resample a or b @@ -1727,12 +1727,19 @@ pinctrl-0=<&i2c3_h1_pins>; clock-frequency = <400000>; - ad82584f: ad82584f@62 { + ad82584f: ad82584f@60 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x30>; + status = "okay"; + reset_pin = <&gpio GPIOH_13 0>; + no_mclk; + }; + ad82584f1: ad82584f@62 { compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "disabled"; - reset_pin = <&gpio GPIOH_13 0>; + status = "okay"; no_mclk; }; }; @@ -1833,8 +1840,8 @@ ðmac { status = "okay"; - pinctrl-names = "internal_eth_pins"; - pinctrl-0 = <&internal_eth_pins>; + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; mc_val = <0x4be04>; internal_phy=<1>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index c81834076863..4cf33f45b697 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -316,7 +316,8 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = ; + prefix-names = "AMP", "AMP1"; + sound-dai = <&ad82584f &ad82584f1 &tl1_codec>; }; }; @@ -1411,8 +1412,8 @@ pinctrl-names = "spdif_pins", "spdif_pins_mute"; - pinctrl-0 = <&spdifout_a>; - pinctrl-1 = <&spdifout_a_mute>; + pinctrl-0 = <&spdifin_a>; + //pinctrl-1 = <&spdifout_a_mute>; /* * whether do asrc for pcm and resample a or b @@ -1686,12 +1687,20 @@ pinctrl-0=<&i2c3_h1_pins>; clock-frequency = <400000>; - ad82584f: ad82584f@62 { + ad82584f: ad82584f@60 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x30>; + status = "okay"; + reset_pin = <&gpio GPIOH_13 0>; + no_mclk; + }; + + ad82584f1: ad82584f@62 { compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "disabled"; - reset_pin = <&gpio GPIOH_13 0>; + status = "okay"; no_mclk; }; }; @@ -1793,8 +1802,8 @@ ðmac { status = "okay"; - pinctrl-names = "internal_eth_pins"; - pinctrl-0 = <&internal_eth_pins>; + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; mc_val = <0x4be04>; internal_phy=<1>; From 3d7231006d5c5b9a9029db9c931e23cad482bb7d Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Wed, 3 Apr 2019 22:02:02 +0800 Subject: [PATCH 0414/1060] amvecm: fix CM/sat/bricon adjust not available [1/2] PD#SWPL-6892 Problem: fix CM/sat/bricon adjust not available Solution: fix CM/sat/bricon adjust not available Verify: U212 Change-Id: Ia6a1aebda35550801d4c7e16807714b8349431a4 Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amcm.c | 8 +-- .../amlogic/media/enhancement/amvecm/amve.c | 4 +- .../amlogic/media/enhancement/amvecm/amvecm.c | 49 +++++++++++-------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm.c b/drivers/amlogic/media/enhancement/amvecm/amcm.c index 25f1767ea155..1177a7793515 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcm.c @@ -162,8 +162,8 @@ void am_set_regmap(struct am_regs_s *p) if (!cm_en) { if (p->am_reg[i].addr == 0x208) { - if (get_cpu_type() == - MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_G12A) p->am_reg[i].val = p->am_reg[i].val & 0xfffffffe; else @@ -279,7 +279,7 @@ void amcm_disable(void) WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { if (temp & 0x1) { WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); @@ -305,7 +305,7 @@ void amcm_enable(void) WRITE_VPP_REG_BITS(VPP_MISC, 1, 28, 1); WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { if (!(temp & 0x1)) { WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index 33e1c9d53e3c..ec20427479b3 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -1047,7 +1047,7 @@ void vpp_vd_adj1_contrast(signed int cont_val, struct vframe_s *vf) WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 0, 1, 1); } } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { vd1_contrast = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0x7ff00) | (cont_val << 0); WRITE_VPP_REG(VPP_VADJ1_Y_2, vd1_contrast); @@ -1079,7 +1079,7 @@ void vpp_vd_adj1_brightness(signed int bri_val, struct vframe_s *vf) if (bri_val > 1023 || bri_val < -1024) return; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { vd1_brightness = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0xff) | (bri_val << 8); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 3b7aa8548104..75d0fd1f7e3f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -236,7 +236,7 @@ __setup("pq=", amvecm_load_pq_val); static int amvecm_set_contrast2(int val) { val += 0x80; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG_BITS(VPP_VADJ2_Y_2, val, 0, 8); WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 0, 1); @@ -254,14 +254,14 @@ static int amvecm_set_brightness2(int val) if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) WRITE_VPP_REG_BITS(VPP_VADJ2_Y, vdj_mode_s.brightness2, 8, 9); - else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ2_Y_2, vdj_mode_s.brightness2, 8, 11); else WRITE_VPP_REG_BITS(VPP_VADJ2_Y, vdj_mode_s.brightness2 >> 1, 8, 10); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 0, 1); else WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 2, 1); @@ -290,7 +290,7 @@ static ssize_t video_adj1_brightness_show(struct class *cla, val = (val << 23) >> 23; return sprintf(buf, "%d\n", val); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { val = (READ_VPP_REG(VPP_VADJ1_Y_2) >> 8) & 0x7ff; val = (val << 21) >> 21; @@ -315,12 +315,12 @@ static ssize_t video_adj1_brightness_store(struct class *cla, if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) WRITE_VPP_REG_BITS(VPP_VADJ1_Y, val, 8, 9); - else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ1_Y_2, val, 8, 11); else WRITE_VPP_REG_BITS(VPP_VADJ1_Y, val >> 1, 8, 10); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); else WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 0, 1); @@ -331,7 +331,7 @@ static ssize_t video_adj1_brightness_store(struct class *cla, static ssize_t video_adj1_contrast_show(struct class *cla, struct class_attribute *attr, char *buf) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) return sprintf(buf, "%d\n", (int)(READ_VPP_REG(VPP_VADJ1_Y_2) & 0xff) - 0x80); else @@ -352,7 +352,7 @@ static ssize_t video_adj1_contrast_store(struct class *cla, val += 0x80; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG_BITS(VPP_VADJ1_Y_2, val, 0, 8); WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); } else { @@ -374,7 +374,7 @@ static ssize_t video_adj2_brightness_show(struct class *cla, val = (val << 23) >> 23; return sprintf(buf, "%d\n", val); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { val = (READ_VPP_REG(VPP_VADJ2_Y_2) >> 8) & 0x7ff; val = (val << 21) >> 21; @@ -403,7 +403,7 @@ static ssize_t video_adj2_brightness_store(struct class *cla, static ssize_t video_adj2_contrast_show(struct class *cla, struct class_attribute *attr, char *buf) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) return sprintf(buf, "%d\n", (int)(READ_VPP_REG(VPP_VADJ2_Y_2) & 0xff) - 0x80); else @@ -780,7 +780,7 @@ void vpp_get_vframe_hist_info(struct vframe_s *vf) unsigned int hist_height, hist_width; u64 divid; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { /*TL1 remove VPP_IN_H_V_SIZE register*/ hist_width = READ_VPP_REG_BITS(VPP_PREBLEND_H_SIZE, 0, 13); hist_height = READ_VPP_REG_BITS(VPP_PREBLEND_H_SIZE, 16, 13); @@ -1198,7 +1198,7 @@ static int amvecm_set_saturation_hue(int mab) mb = -512; mab = ((ma & 0x3ff) << 16) | (mb & 0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG(VPP_VADJ1_MA_MB_2, mab); else WRITE_VPP_REG(VPP_VADJ1_MA_MB, mab); @@ -1212,7 +1212,7 @@ static int amvecm_set_saturation_hue(int mab) md = (s16)((mab<<6)>>22); /* md = ma; */ mab = ((mc&0x3ff)<<16)|(md&0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG(VPP_VADJ1_MC_MD_2, mab); WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); } else { @@ -1267,7 +1267,7 @@ static int amvecm_set_saturation_hue_post(int val1, mab = ((ma & 0x3ff) << 16) | (mb & 0x3ff); pr_info("\n[amvideo..] saturation_post:%d hue_post:%d mab:%x\n", saturation_post, hue_post, mab); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG(VPP_VADJ2_MA_MB_2, mab); else WRITE_VPP_REG(VPP_VADJ2_MA_MB, mab); @@ -1279,7 +1279,7 @@ static int amvecm_set_saturation_hue_post(int val1, mc = -512; md = (s16)((mab<<6)>>22); /* md = ma; */ mab = ((mc&0x3ff)<<16)|(md&0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG(VPP_VADJ2_MC_MD_2, mab); WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 0, 1); } else { @@ -1612,8 +1612,8 @@ static long amvecm_ioctl(struct file *file, vecm_latch_flag |= FLAG_VADJ1_BRI; } if (vdj_mode_flg & 0x2) { /*brightness2*/ - if ((vdj_mode_s.brightness2 < -255) || - (vdj_mode_s.brightness2 > 255)) { + if ((vdj_mode_s.brightness2 < -1024) || + (vdj_mode_s.brightness2 > 1023)) { pr_amvecm_dbg("load brightness2 value invalid!!!\n"); return -EINVAL; } @@ -2452,7 +2452,7 @@ static ssize_t amvecm_contrast_store(struct class *cla, static ssize_t amvecm_saturation_hue_show(struct class *cla, struct class_attribute *attr, char *buf) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) return sprintf(buf, "0x%x\n", READ_VPP_REG(VPP_VADJ1_MA_MB_2)); else @@ -2515,7 +2515,7 @@ void vpp_vd_adj1_saturation_hue(signed int sat_val, mab = ((ma & 0x3ff) << 16) | (mb & 0x3ff); pr_info("\n[amvideo..] saturation_pre:%d hue_pre:%d mab:%x\n", sat_val, hue_val, mab); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG(VPP_VADJ1_MA_MB_2, mab); else WRITE_VPP_REG(VPP_VADJ1_MA_MB, mab); @@ -2528,7 +2528,7 @@ void vpp_vd_adj1_saturation_hue(signed int sat_val, md = (s16)((mab<<6)>>22); /* md = ma; */ mab = ((mc&0x3ff)<<16)|(md&0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG(VPP_VADJ1_MC_MD_2, mab); WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); } else { @@ -6203,8 +6203,15 @@ void init_pq_setting(void) is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu() || is_meson_tm2_cpu()) goto tvchip_pq_setting; - else if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + else if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { sr_offset[0] = SR0_OFFSET; + bitdepth = 12; + /*confirm with vlsi-Lunhai.Chen, for G12A/G12B, + *VPP_GCLK_CTRL1 must enable + */ + WRITE_VPP_REG_BITS(VPP_GCLK_CTRL1, 0xf, 0, 4); + cm_init_config(bitdepth); /*dnlp off*/ WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL, 0, DNLP_EN_BIT, DNLP_EN_WID); From db6f61dcafe9f769c35545384176af5889b556c6 Mon Sep 17 00:00:00 2001 From: Ting Li Date: Mon, 18 Feb 2019 18:45:27 +0800 Subject: [PATCH 0415/1060] picdec: add picdec dev node for u200 u211 u212 w400 sm1 [1/1] PD#SWPL-4551 Problem: ImagePlayer cannot play picture Solution: add picdec dev node for u200 u211 u212 w400 Verify: franklin Change-Id: I35cc28e2ab06367f33a7326ce671b1ee461e6fb1 Signed-off-by: xi an Signed-off-by: li ting --- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 15 +++++++++++++++ arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 4eb5c6f3108e..23a98ed3a0c8 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -269,6 +269,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 02082c476e50..8c0bf56759f2 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -269,6 +269,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; From cc4abdec93588731e0e9644adbab3150f188f6d2 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Tue, 9 Apr 2019 11:20:57 +0800 Subject: [PATCH 0416/1060] dts: audio: update vad for sm1 [1/1] PD#SWPL-5427 Problem: lack vad function for sm1 Solution: add vad function for sm1 Verify: ac200 Change-Id: Ib4118b16405102a72f98ff65396e6f9d98f97bca Signed-off-by: Xing Wang --- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 36 +++++++++++++++ arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 36 +++++++++++++++ .../arm/boot/dts/amlogic/sm1_s905x3_ac213.dts | 45 ++++++++++++------- .../boot/dts/amlogic/sm1_s905d3_ac200.dts | 36 +++++++++++++++ .../arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 36 +++++++++++++++ .../boot/dts/amlogic/sm1_s905x3_ac213.dts | 36 +++++++++++++++ 6 files changed, 209 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 83039edc1a7b..37c67a514e00 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1243,6 +1243,42 @@ resample_module = <4>; status = "disabled"; }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 81f9c60ead73..8f0c97315142 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1243,6 +1243,42 @@ resample_module = <4>; status = "disabled"; }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts index ad02f6c96fb7..8dafc01999e7 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -1227,28 +1227,41 @@ resample_module = <4>; status = "okay"; }; - aml_pwrdet: pwrdet { - compatible = "amlogic, g12a-power-detect"; - interrupts = ; - interrupt-names = "pwrdet_irq"; + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; */ - pwrdet_src = <4>; + src = <4>; - hi_th = <0x70000>; - lo_th = <0x16000>; + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; - status = "disabled"; + status = "okay"; }; }; /* end of audiobus */ diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 23a98ed3a0c8..4497e9e982a1 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1257,6 +1257,42 @@ resample_module = <4>; status = "disabled"; }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 8c0bf56759f2..679292791fb4 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -1256,6 +1256,42 @@ resample_module = <4>; status = "disabled"; }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts index 2d4bd8fef7fc..681f0cf32f54 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -1236,6 +1236,42 @@ resample_module = <4>; status = "disabled"; }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; }; /* end of audiobus */ &pinctrl_periphs { From 88121f95e0c96abe480b3d7872c96f02afaa47b6 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Mon, 8 Apr 2019 15:34:22 +0800 Subject: [PATCH 0417/1060] atv_demod: fix audio config (PAL_M, NTSC_M) when video is PAL [1/1] PD#TV-4274 Problem: fix audio config (PAL_M, NTSC_M) when video is PAL. Solution: fix audio config (PAL_M, NTSC_M) when video is PAL Verify: verified by x301. Change-Id: I9be8d71d52a226b6422317be0b77ca6331f23147 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atvdemod_func.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 286c16185e54..90c953673c89 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -1798,7 +1798,8 @@ void atv_dmd_set_std(void) gde_curve = 3; } else if (((ptstd & V4L2_COLOR_STD_PAL) || (ptstd & V4L2_COLOR_STD_SECAM)) - && (ptstd & V4L2_STD_PAL_M)) { + && ((ptstd & V4L2_STD_PAL_M) + || (ptstd & V4L2_STD_NTSC_M))) { amlatvdemod_devp->fre_offset = 2250000; freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; From c5e757bfdac5fd4e14736ccab952a3a6e2ad3104 Mon Sep 17 00:00:00 2001 From: "Nanxin.Qin" Date: Mon, 25 Mar 2019 18:03:13 +0800 Subject: [PATCH 0418/1060] media: add the register sets for parser B [1/1] PD#SWPL-5417 Problem: bringup sm1 and tm2. Solution: add the register sets for parser B. Verify: AB311 Change-Id: I3c1620d69260f92c8d1590976950030604b7dd80 Signed-off-by: Nanxin.Qin --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 6 +- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 6 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 6 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 6 +- .../media/registers/regs/parser_regs.h | 161 ++++++++++++------ 5 files changed, 127 insertions(+), 58 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 521ecc88c3fa..0367819aab61 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -1277,13 +1277,15 @@ 0 32 1 0 43 1 0 44 1 - 0 45 1>; + 0 45 1 + 0 72 1>; interrupt-names = "vsync", "demux", "parser", "mailbox_0", "mailbox_1", - "mailbox_2"; + "mailbox_2", + "parser_b"; }; vcodec_dec { diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index e89d41a7a309..3312fafdb537 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1376,13 +1376,15 @@ 0 32 1 0 43 1 0 44 1 - 0 45 1>; + 0 45 1 + 0 74 1>; interrupt-names = "vsync", "demux", "parser", "mailbox_0", "mailbox_1", - "mailbox_2"; + "mailbox_2", + "parser_b"; }; amvenc_avc{ compatible = "amlogic, amvenc_avc"; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 7a5703927030..eb747a6fd874 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -1276,13 +1276,15 @@ 0 32 1 0 43 1 0 44 1 - 0 45 1>; + 0 45 1 + 0 72 1>; interrupt-names = "vsync", "demux", "parser", "mailbox_0", "mailbox_1", - "mailbox_2"; + "mailbox_2", + "parser_b"; }; vcodec_dec { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 99f3db82eba3..7eeb51c079dd 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1356,13 +1356,15 @@ 0 32 1 0 43 1 0 44 1 - 0 45 1>; + 0 45 1 + 0 74 1>; interrupt-names = "vsync", "demux", "parser", "mailbox_0", "mailbox_1", - "mailbox_2"; + "mailbox_2", + "parser_b"; }; amvenc_avc{ diff --git a/include/linux/amlogic/media/registers/regs/parser_regs.h b/include/linux/amlogic/media/registers/regs/parser_regs.h index cb0f13370458..b340d6f64daa 100644 --- a/include/linux/amlogic/media/registers/regs/parser_regs.h +++ b/include/linux/amlogic/media/registers/regs/parser_regs.h @@ -24,57 +24,118 @@ * converted automatically based on * the platform at init. * #define PARSER_CONTROL 0x3860 + * parser A */ -#define PARSER_CONTROL 0x2960 -#define PARSER_FETCH_ADDR 0x2961 -#define PARSER_FETCH_CMD 0x2962 -#define PARSER_FETCH_STOP_ADDR 0x2963 -#define PARSER_FETCH_LEVEL 0x2964 -#define PARSER_CONFIG 0x2965 -#define PFIFO_WR_PTR 0x2966 -#define PFIFO_RD_PTR 0x2967 -#define PFIFO_DATA 0x2968 -#define PARSER_SEARCH_PATTERN 0x2969 -#define PARSER_SEARCH_MASK 0x296a -#define PARSER_INT_ENABLE 0x296b -#define PARSER_INT_STATUS 0x296c -#define PARSER_SCR_CTL 0x296d -#define PARSER_SCR 0x296e -#define PARSER_PARAMETER 0x296f -#define PARSER_INSERT_DATA 0x2970 -#define VAS_STREAM_ID 0x2971 -#define VIDEO_DTS 0x2972 -#define VIDEO_PTS 0x2973 -#define VIDEO_PTS_DTS_WR_PTR 0x2974 -#define AUDIO_PTS 0x2975 -#define AUDIO_PTS_WR_PTR 0x2976 -#define PARSER_ES_CONTROL 0x2977 -#define PFIFO_MONITOR 0x2978 -#define PARSER_VIDEO_START_PTR 0x2980 -#define PARSER_VIDEO_END_PTR 0x2981 -#define PARSER_VIDEO_WP 0x2982 -#define PARSER_VIDEO_RP 0x2983 -#define PARSER_VIDEO_HOLE 0x2984 -#define PARSER_AUDIO_START_PTR 0x2985 -#define PARSER_AUDIO_END_PTR 0x2986 -#define PARSER_AUDIO_WP 0x2987 -#define PARSER_AUDIO_RP 0x2988 -#define PARSER_AUDIO_HOLE 0x2989 -#define PARSER_SUB_START_PTR 0x298a -#define PARSER_SUB_END_PTR 0x298b -#define PARSER_SUB_WP 0x298c -#define PARSER_SUB_RP 0x298d -#define PARSER_SUB_HOLE 0x298e -#define PARSER_FETCH_INFO 0x298f -#define PARSER_STATUS 0x2990 -#define PARSER_AV_WRAP_COUNT 0x2991 -#define WRRSP_PARSER 0x2992 -#define PARSER_VIDEO2_START_PTR 0x2993 -#define PARSER_VIDEO2_END_PTR 0x2994 -#define PARSER_VIDEO2_WP 0x2995 -#define PARSER_VIDEO2_RP 0x2996 -#define PARSER_VIDEO2_HOLE 0x2997 -#define PARSER_AV2_WRAP_COUNT 0x2998 +#define PARSER_CONTROL 0x2960 +#define PARSER_FETCH_ADDR 0x2961 +#define PARSER_FETCH_CMD 0x2962 +#define PARSER_FETCH_STOP_ADDR 0x2963 +#define PARSER_FETCH_LEVEL 0x2964 +#define PARSER_CONFIG 0x2965 +#define PFIFO_WR_PTR 0x2966 +#define PFIFO_RD_PTR 0x2967 +#define PFIFO_DATA 0x2968 +#define PARSER_SEARCH_PATTERN 0x2969 +#define PARSER_SEARCH_MASK 0x296a +#define PARSER_INT_ENABLE 0x296b +#define PARSER_INT_STATUS 0x296c +#define PARSER_SCR_CTL 0x296d +#define PARSER_SCR 0x296e +#define PARSER_PARAMETER 0x296f +#define PARSER_INSERT_DATA 0x2970 +#define VAS_STREAM_ID 0x2971 +#define VIDEO_DTS 0x2972 +#define VIDEO_PTS 0x2973 +#define VIDEO_PTS_DTS_WR_PTR 0x2974 +#define AUDIO_PTS 0x2975 +#define AUDIO_PTS_WR_PTR 0x2976 +#define PARSER_ES_CONTROL 0x2977 +#define PFIFO_MONITOR 0x2978 +#define PARSER_VIDEO_START_PTR 0x2980 +#define PARSER_VIDEO_END_PTR 0x2981 +#define PARSER_VIDEO_WP 0x2982 +#define PARSER_VIDEO_RP 0x2983 +#define PARSER_VIDEO_HOLE 0x2984 +#define PARSER_AUDIO_START_PTR 0x2985 +#define PARSER_AUDIO_END_PTR 0x2986 +#define PARSER_AUDIO_WP 0x2987 +#define PARSER_AUDIO_RP 0x2988 +#define PARSER_AUDIO_HOLE 0x2989 +#define PARSER_SUB_START_PTR 0x298a +#define PARSER_SUB_END_PTR 0x298b +#define PARSER_SUB_WP 0x298c +#define PARSER_SUB_RP 0x298d +#define PARSER_SUB_HOLE 0x298e +#define PARSER_FETCH_INFO 0x298f +#define PARSER_STATUS 0x2990 +#define PARSER_AV_WRAP_COUNT 0x2991 +#define WRRSP_PARSER 0x2992 +#define PARSER_VIDEO2_START_PTR 0x2993 +#define PARSER_VIDEO2_END_PTR 0x2994 +#define PARSER_VIDEO2_WP 0x2995 +#define PARSER_VIDEO2_RP 0x2996 +#define PARSER_VIDEO2_HOLE 0x2997 +#define PARSER_AV2_WRAP_COUNT 0x2998 + +/* + * pay attention : the regs range has + * changed to 0x34xx in SM1, it was + * converted automatically based on + * the platform at init. + * #define PARSER_B_CONTROL 0x3460 + * parser B + */ + +#define PARSER_B_CONTROL 0x2560 +#define PARSER_B_FETCH_ADDR 0x2561 +#define PARSER_B_FETCH_CMD 0x2562 +#define PARSER_B_FETCH_STOP_ADDR 0x2563 +#define PARSER_B_FETCH_LEVEL 0x2564 +#define PARSER_B_CONFIG 0x2565 +#define PARSER_B_PFIFO_WR_PTR 0x2566 +#define PARSER_B_PFIFO_RD_PTR 0x2567 +#define PARSER_B_PFIFO_DATA 0x2568 +#define PARSER_B_SEARCH_PATTERN 0x2569 +#define PARSER_B_SEARCH_MASK 0x256a +#define PARSER_B_INT_ENABLE 0x256b +#define PARSER_B_INT_STATUS 0x256c +#define PARSER_B_SCR_CTL 0x256d +#define PARSER_B_SCR 0x256e +#define PARSER_B_PARAMETER 0x256f +#define PARSER_B_INSERT_DATA 0x2570 +#define PARSER_B_VAS_STREAM_ID 0x2571 +#define PARSER_B_VIDEO_DTS 0x2572 +#define PARSER_B_VIDEO_PTS 0x2573 +#define PARSER_B_VIDEO_PTS_DTS_WR_PTR 0x2574 +#define PARSER_B_AUDIO_PTS 0x2575 +#define PARSER_B_AUDIO_PTS_WR_PTR 0x2576 +#define PARSER_B_ES_CONTROL 0x2577 +#define PARSER_B_PFIFO_MONITOR 0x2578 +#define PARSER_B_VIDEO_START_PTR 0x2580 +#define PARSER_B_VIDEO_END_PTR 0x2581 +#define PARSER_B_VIDEO_WP 0x2582 +#define PARSER_B_VIDEO_RP 0x2583 +#define PARSER_B_VIDEO_HOLE 0x2584 +#define PARSER_B_AUDIO_START_PTR 0x2585 +#define PARSER_B_AUDIO_END_PTR 0x2586 +#define PARSER_B_AUDIO_WP 0x2587 +#define PARSER_B_AUDIO_RP 0x2588 +#define PARSER_B_AUDIO_HOLE 0x2589 +#define PARSER_B_SUB_START_PTR 0x258a +#define PARSER_B_SUB_END_PTR 0x258b +#define PARSER_B_SUB_WP 0x258c +#define PARSER_B_SUB_RP 0x258d +#define PARSER_B_SUB_HOLE 0x258e +#define PARSER_B_FETCH_INFO 0x258f +#define PARSER_B_STATUS 0x2590 +#define PARSER_B_AV_WRAP_COUNT 0x2591 +#define PARSER_B_WRRSP_PARSER 0x2592 +#define PARSER_B_VIDEO2_START_PTR 0x2593 +#define PARSER_B_VIDEO2_END_PTR 0x2594 +#define PARSER_B_VIDEO2_WP 0x2595 +#define PARSER_B_VIDEO2_RP 0x2596 +#define PARSER_B_VIDEO2_HOLE 0x2597 +#define PARSER_B_AV2_WRAP_COUNT 0x2598 #endif From aab4437abf124757b7e67083f6dab02a54db9ed4 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Thu, 11 Apr 2019 13:37:51 +0800 Subject: [PATCH 0419/1060] earlycon: support aml-uart as the name for earlycon [1/1] PD#SWPL-6969 Problem: For some historical reason, aml-uart is configured as the earlycon name in uboot, which is not recognized by 4.9 kernel Solution: support aml-uart as the name for earlycon Verify: Ampere Change-Id: I53463ac6d27ff3e911aa675cd5d10d6cbf26ba05 Signed-off-by: Jiamin Ma --- drivers/amlogic/uart/meson_uart.c | 1 + include/linux/serial_core.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/amlogic/uart/meson_uart.c b/drivers/amlogic/uart/meson_uart.c index 20ccd0173407..3e1ee9fae42d 100644 --- a/drivers/amlogic/uart/meson_uart.c +++ b/drivers/amlogic/uart/meson_uart.c @@ -956,6 +956,7 @@ static int __init meson_early_console_setup(struct earlycon_device *device, return 0; } EARLYCON_DECLARE(aml_uart, meson_early_console_setup); +EARLYCON_DECLARE_COMP(aml-uart, meson_early_console_setup); static struct console meson_serial_console = { .name = AML_UART_DEV_NAME, diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index c7dff69a4103..3890f0b0ae20 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -376,6 +376,11 @@ extern const struct earlycon_id *__earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) +#ifdef CONFIG_AMLOGIC_MODIFY +#define EARLYCON_DECLARE_COMP(_name, fn) \ + _OF_EARLYCON_DECLARE(_name, "", fn, __LINE__ ## __COUNTER__) +#endif + extern int of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options); From 0ee99c66674c2f8271912a0222a8b801774bc5bb Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 3 Apr 2019 19:16:50 +0800 Subject: [PATCH 0420/1060] debug: improve ftrace_ramoops for io trace [2/2] PD#SWPL-6028 Problem: improve ftrace_ramoops to debug bus hang Solution: 1. in uboot setenv initargs $initargs ramoops_io_en=1 loglevel=3;save;reset 2. in linux command line: cat /sys/module/kernel/parameters/ramoops_io_en to check if success. 3. after watchdog reboot, get trace data with: cat /sys/fs/pstore/ftrace-ramoops-0 Verify: TL1 x301 Change-Id: If1a2582b40a3ded31eedef5355eb0b8a5bf495c3 Signed-off-by: Jianxin Pan --- MAINTAINERS | 1 + arch/arm/include/asm/io.h | 57 +++++++ arch/arm64/include/asm/io.h | 52 +++++- arch/arm64/kernel/io.c | 23 +++ drivers/amlogic/debug/Kconfig | 12 ++ drivers/amlogic/debug/Makefile | 1 + drivers/amlogic/debug/debug_ftrace_ramoops.c | 149 ++++++++++++++++++ drivers/amlogic/iomap/iomap.c | 4 +- .../common/arch/registers/register_map.c | 4 +- .../common/arch/registers/register_ops_m8.c | 14 -- drivers/amlogic/uart/meson_uart.c | 1 + drivers/irqchip/irq-gic.c | 1 + fs/pstore/ftrace.c | 11 +- fs/pstore/inode.c | 6 +- fs/pstore/internal.h | 14 ++ fs/pstore/ram.c | 15 +- fs/pstore/ram_core.c | 16 +- include/linux/amlogic/debug_ftrace_ramoops.h | 62 ++++++++ include/linux/amlogic/iomap.h | 5 +- include/linux/pstore_ram.h | 1 + lib/ioremap.c | 24 ++- 21 files changed, 445 insertions(+), 28 deletions(-) create mode 100644 drivers/amlogic/debug/debug_ftrace_ramoops.c create mode 100644 include/linux/amlogic/debug_ftrace_ramoops.h diff --git a/MAINTAINERS b/MAINTAINERS index c7f7f8da2bc5..ad61e61d39af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14511,6 +14511,7 @@ AMLOGIC DEBUG M: Jianxin Pan M: Tao Guo F: drivers/amlogic/debug/* +F: include/linux/amlogic/debug*.h AMLOGIC G12A spdif channel status M: xing wang diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 021692c64de3..202cab53d821 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -31,6 +31,9 @@ #include #include +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#endif /* * ISA I/O bus memory addresses are 1:1 with the physical address. */ @@ -73,17 +76,29 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen); #define __raw_writew __raw_writew static inline void __raw_writew(u16 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strh %1, %0" : : "Q" (*(volatile u16 __force *)addr), "r" (val)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_readw __raw_readw static inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile("ldrh %0, %1" : "=r" (val) : "Q" (*(volatile u16 __force *)addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } #endif @@ -91,24 +106,42 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) #define __raw_writeb __raw_writeb static inline void __raw_writeb(u8 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strb %1, %0" : : "Qo" (*(volatile u8 __force *)addr), "r" (val)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writel __raw_writel static inline void __raw_writel(u32 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("str %1, %0" : : "Qo" (*(volatile u32 __force *)addr), "r" (val)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_readb __raw_readb static inline u8 __raw_readb(const volatile void __iomem *addr) { u8 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile("ldrb %0, %1" : "=r" (val) : "Qo" (*(volatile u8 __force *)addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -116,9 +149,15 @@ static inline u8 __raw_readb(const volatile void __iomem *addr) static inline u32 __raw_readl(const volatile void __iomem *addr) { u32 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile("ldr %0, %1" : "=r" (val) : "Qo" (*(volatile u32 __force *)addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -317,7 +356,13 @@ static inline void memset_io(volatile void __iomem *dst, unsigned c, size_t count) { extern void mmioset(void *, unsigned int, size_t); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)dst, (unsigned long)count); +#endif mmioset((void __force *)dst, c, count); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)dst, (unsigned long)count); +#endif } #define memset_io(dst,c,count) memset_io(dst,c,count) @@ -325,7 +370,13 @@ static inline void memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { extern void mmiocpy(void *, const void *, size_t); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count); +#endif mmiocpy(to, (const void __force *)from, count); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count); +#endif } #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) @@ -333,7 +384,13 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { extern void mmiocpy(void *, const void *, size_t); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count); +#endif mmiocpy((void __force *)to, from, count); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count); +#endif } #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 0bba427bb4c2..931f49b560bd 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -33,42 +33,74 @@ #include #include - +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#endif /* * Generic IO read/write. These perform native-endian accesses. */ #define __raw_writeb __raw_writeb static inline void __raw_writeb(u8 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writew __raw_writew static inline void __raw_writew(u16 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writel __raw_writel static inline void __raw_writel(u32 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writeq __raw_writeq static inline void __raw_writeq(u64 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_readb __raw_readb static inline u8 __raw_readb(const volatile void __iomem *addr) { u8 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldrb %w0, [%1]", "ldarb %w0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -77,10 +109,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldrh %w0, [%1]", "ldarh %w0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -88,10 +126,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) static inline u32 __raw_readl(const volatile void __iomem *addr) { u32 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldr %w0, [%1]", "ldar %w0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -99,10 +143,16 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) static inline u64 __raw_readq(const volatile void __iomem *addr) { u64 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldr %0, [%1]", "ldar %0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c index 79b17384effa..b90a1613e051 100644 --- a/arch/arm64/kernel/io.c +++ b/arch/arm64/kernel/io.c @@ -18,13 +18,21 @@ #include #include +#define SKIP_IO_TRACE #include +#undef SKIP_IO_TRACE +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#endif /* * Copy data from IO memory space to "real" memory space. */ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif while (count && !IS_ALIGNED((unsigned long)from, 8)) { *(u8 *)to = __raw_readb(from); from++; @@ -45,6 +53,9 @@ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) to++; count--; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif } EXPORT_SYMBOL(__memcpy_fromio); @@ -53,6 +64,9 @@ EXPORT_SYMBOL(__memcpy_fromio); */ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, 0x1234); +#endif while (count && !IS_ALIGNED((unsigned long)to, 8)) { __raw_writeb(*(u8 *)from, to); from++; @@ -73,6 +87,9 @@ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) to++; count--; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, 0x1234); +#endif } EXPORT_SYMBOL(__memcpy_toio); @@ -83,6 +100,9 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count) { u64 qc = (u8)c; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, 0xabcd); +#endif qc |= qc << 8; qc |= qc << 16; qc |= qc << 32; @@ -104,5 +124,8 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count) dst++; count--; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, 0xabcd); +#endif } EXPORT_SYMBOL(__memset_io); diff --git a/drivers/amlogic/debug/Kconfig b/drivers/amlogic/debug/Kconfig index 1bbc48731be4..f8df94eac08a 100644 --- a/drivers/amlogic/debug/Kconfig +++ b/drivers/amlogic/debug/Kconfig @@ -19,3 +19,15 @@ config AMLOGIC_DEBUG_ATRACE default y help Add android atrace compatible function + +config AMLOGIC_DEBUG_FTRACE_PSTORE + bool "Amlogic ftrace pstore debug" + depends on AMLOGIC_DEBUG + depends on PSTORE_FTRACE + default y + help + Dump function call and register access to ramoops after watchdog + reboot. + Enable if doubt. + + diff --git a/drivers/amlogic/debug/Makefile b/drivers/amlogic/debug/Makefile index 7576af9f601b..9b2e3f18c519 100644 --- a/drivers/amlogic/debug/Makefile +++ b/drivers/amlogic/debug/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_AMLOGIC_DEBUG_LOCKUP) += debug_lockup.o obj-$(CONFIG_AMLOGIC_DEBUG_ATRACE) += meson_atrace.o +obj-$(CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE)+= debug_ftrace_ramoops.o diff --git a/drivers/amlogic/debug/debug_ftrace_ramoops.c b/drivers/amlogic/debug/debug_ftrace_ramoops.c new file mode 100644 index 000000000000..f67c59fe91ba --- /dev/null +++ b/drivers/amlogic/debug/debug_ftrace_ramoops.c @@ -0,0 +1,149 @@ +/* + * drivers/amlogic/debug/debug_ftrace_ramoops.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../../../fs/pstore/internal.h> +#include +#include +#include + +static DEFINE_PER_CPU(int, en); +static DEFINE_PER_CPU(unsigned long, irq_flag); + +#define IRQ_D 1 + +unsigned int dump_iomap; +core_param(dump_iomap, dump_iomap, uint, 0664); + +unsigned int ramoops_ftrace_en; +EXPORT_SYMBOL(ramoops_ftrace_en); + +int ramoops_io_en; +EXPORT_SYMBOL(ramoops_io_en); +core_param(ramoops_io_en, ramoops_io_en, int, 0664); + +const char *record_name[PSTORE_FLAG_IO_MAX] = { + "NULL", + "FUNC", + "IO-R", + "IO-W", + "IO-R-E", + "IO-W-E", +}; + +void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec) +{ + int cpu = raw_smp_processor_id(); + + if (unlikely(oops_in_progress) || unlikely(per_cpu(en, cpu))) + return; + per_cpu(en, cpu) = 1; + pstore_ftrace_encode_cpu(rec, cpu); + strlcpy(rec->comm, current->comm, sizeof(rec->comm) - 1); + rec->pid = current->pid; + rec->time = trace_clock_local(); + psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)rec, + 0, sizeof(*rec), psinfo); + per_cpu(en, cpu) = 0; +} +EXPORT_SYMBOL(pstore_ftrace_save); + +static void notrace pstore_function_dump(struct pstore_ftrace_record *rec, + struct seq_file *s) +{ + unsigned long sec = 0, ms = 0; + unsigned long long time = rec->time; + + do_div(time, 1000000); + sec = (unsigned long)time / 1000; + ms = (unsigned long)time % 1000; + seq_printf(s, "[%04ld.%03ld@%d] <%5d-%s> <%pf <- %pF>\n", + sec, ms, pstore_ftrace_decode_cpu(rec), rec->pid, rec->comm, + (void *)rec->ip, (void *)rec->parent_ip); +} + +void notrace pstore_io_rw_dump(struct pstore_ftrace_record *rec, + struct seq_file *s) +{ + unsigned long sec = 0, ms = 0; + unsigned long long time = rec->time; + unsigned int cpu = pstore_ftrace_decode_cpu(rec); + + do_div(time, 1000000); + sec = (unsigned long)time / 1000; + ms = (unsigned long)time % 1000; + seq_printf(s, "[%04ld.%03ld@%d] <%5d-%6s> <%6s %08lx-%8lx> <%pf <- %pF>\n", + sec, ms, cpu, rec->pid, rec->comm, record_name[rec->flag], + rec->val1, (rec->flag == PSTORE_FLAG_IO_W) ? rec->val2 : 0, + (void *)rec->ip, (void *)rec->parent_ip); +} + +void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec, + struct seq_file *s) +{ + switch (rec->flag & PSTORE_FLAG_MASK) { + case PSTORE_FLAG_FUNC: + pstore_function_dump(rec, s); + break; + case PSTORE_FLAG_IO_R: + case PSTORE_FLAG_IO_W: + case PSTORE_FLAG_IO_W_END: + case PSTORE_FLAG_IO_R_END: + pstore_io_rw_dump(rec, s); + break; + default: + seq_printf(s, "Unknown Msg:%x\n", rec->flag); + } +} + +void notrace pstore_io_save(unsigned long reg, unsigned long val, + unsigned long parant, unsigned int flag) +{ + struct pstore_ftrace_record rec; + int cpu = get_cpu(); + + put_cpu(); + if (!ramoops_ftrace_en || !ramoops_io_en) + return; + + if ((flag == PSTORE_FLAG_IO_R || flag == PSTORE_FLAG_IO_W) && IRQ_D) + local_irq_save(per_cpu(irq_flag, cpu)); + + rec.ip = CALLER_ADDR0; + rec.parent_ip = parant; + rec.flag = flag; + rec.val1 = reg; + rec.val2 = val; + pstore_ftrace_save(&rec); + + if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END) + && IRQ_D) + local_irq_restore(per_cpu(irq_flag, cpu)); +} +EXPORT_SYMBOL(pstore_io_save); + diff --git a/drivers/amlogic/iomap/iomap.c b/drivers/amlogic/iomap/iomap.c index b5645c2f6df2..2998450a9b1b 100644 --- a/drivers/amlogic/iomap/iomap.c +++ b/drivers/amlogic/iomap/iomap.c @@ -39,7 +39,7 @@ static const struct of_device_id iomap_dt_match[] = { static void __iomem *meson_reg_map[IO_BUS_MAX] = { NULL }; -int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) +inline int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) { if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) { *val = readl((meson_reg_map[bus_type]+reg)); @@ -49,7 +49,7 @@ int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) } EXPORT_SYMBOL(aml_reg_read); -int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val) +inline int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val) { if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) { writel(val, (meson_reg_map[bus_type]+reg)); diff --git a/drivers/amlogic/media/common/arch/registers/register_map.c b/drivers/amlogic/media/common/arch/registers/register_map.c index e333b065d2fb..390d0dbee951 100644 --- a/drivers/amlogic/media/common/arch/registers/register_map.c +++ b/drivers/amlogic/media/common/arch/registers/register_map.c @@ -51,7 +51,7 @@ enum { static void __iomem *codecio_reg_map[CODECIO_BUS_MAX]; -static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) +static inline int codecio_reg_read(u32 bus_type, u32 reg, u32 *val) { if (bus_type < CODECIO_BUS_MAX) { if (codecio_reg_map[bus_type] == NULL) { @@ -65,7 +65,7 @@ static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) return -1; } -static int codecio_reg_write(u32 bus_type, unsigned int reg, unsigned int val) +static inline int codecio_reg_write(u32 bus_type, u32 reg, u32 val) { if (bus_type < CODECIO_BUS_MAX) { if (codecio_reg_map[bus_type] == NULL) { diff --git a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c index 4f7e1a2ba3ca..a0323e574d6a 100644 --- a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c +++ b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c @@ -49,20 +49,6 @@ MESON_CPU_MAJOR_ID_SM1, \ MESON_CPU_MAJOR_ID_TM2, \ 0} -int codec_apb_read(unsigned int reg) -{ - unsigned int val = 0; - - aml_reg_read(IO_APB_BUS_BASE, reg << 2, &val); - return val; -} -EXPORT_SYMBOL(codec_apb_read); - -void codec_apb_write(unsigned int reg, unsigned int val) -{ - aml_reg_write(IO_APB_BUS_BASE, reg << 2, val); -} -EXPORT_SYMBOL(codec_apb_write); static struct chip_register_ops m8_ops[] __initdata = { {IO_DOS_BUS, 0, codecio_read_dosbus, codecio_write_dosbus}, diff --git a/drivers/amlogic/uart/meson_uart.c b/drivers/amlogic/uart/meson_uart.c index 3e1ee9fae42d..3ce6eb15a523 100644 --- a/drivers/amlogic/uart/meson_uart.c +++ b/drivers/amlogic/uart/meson_uart.c @@ -15,6 +15,7 @@ * */ +#define SKIP_IO_TRACE #include #include #include diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index d6c404b3584d..43efc7ee675a 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -20,6 +20,7 @@ * As such, the enable set/clear, pending set/clear and active bit * registers are banked per-cpu for these sources. */ +#define SKIP_IO_TRACE #include #include #include diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index d4887705bb61..33fa1395e053 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c @@ -27,6 +27,10 @@ #include #include "internal.h" +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#endif + static void notrace pstore_ftrace_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, @@ -39,13 +43,16 @@ static void notrace pstore_ftrace_call(unsigned long ip, return; local_irq_save(flags); - rec.ip = ip; rec.parent_ip = parent_ip; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + rec.flag = PSTORE_FLAG_FUNC; + pstore_ftrace_save(&rec); +#else pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, 0, sizeof(rec), psinfo); - +#endif local_irq_restore(flags); } diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 1781dc50762e..6f6f56c21524 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "internal.h" @@ -107,10 +108,13 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v) struct pstore_ftrace_seq_data *data = v; struct pstore_ftrace_record *rec = (void *)(ps->data + data->off); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_dump(rec, s); +#else seq_printf(s, "%d %08lx %08lx %pf <- %pF\n", pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip, (void *)rec->ip, (void *)rec->parent_ip); - +#endif return 0; } diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index e38a22b31282..cca4fefea880 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -17,8 +17,22 @@ struct pstore_ftrace_record { #ifndef PSTORE_CPU_IN_IP unsigned int cpu; #endif +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + int pid; + unsigned long val1; + unsigned long val2; + unsigned long long time; + unsigned char comm[8]; + unsigned int flag; +#endif }; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec); +void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec, + struct seq_file *s); +#endif + static inline void pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) { diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 8e151fb9bb76..aa3f123f3239 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -602,6 +602,9 @@ static int ramoops_probe(struct platform_device *pdev) cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; cxt->memtype = pdata->mem_type; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + cxt->memtype |= (!!ramoops_io_en); +#endif cxt->record_size = pdata->record_size; cxt->console_size = pdata->console_size; cxt->ftrace_size = pdata->ftrace_size; @@ -621,7 +624,6 @@ static int ramoops_probe(struct platform_device *pdev) cxt->console_size, 0); if (err) goto fail_init_cprz; - err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size, LINUX_VERSION_CODE); if (err) @@ -679,6 +681,17 @@ static int ramoops_probe(struct platform_device *pdev) cxt->size, (unsigned long long)cxt->phys_addr, cxt->ecc_info.ecc_size, cxt->ecc_info.block_size); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + if (ramoops_ftrace_size) { + cxt->fprz->flags |= (PRZ_FLAG_NO_LOCK | PRZ_FLAG_BIG_LOCK); + ramoops_ftrace_en = !persistent_ram_old_size(cxt->fprz); + } + pr_info("ramoops_io_en:%d %d old:0x%lx ftrace_size:0x%lx", + ramoops_io_en, ramoops_ftrace_en, + (unsigned long)persistent_ram_old_size(cxt->fprz), + ramoops_ftrace_size); +#endif + return 0; fail_buf: diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 11e558efd61e..d476f493e478 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -12,6 +12,7 @@ * */ +#define SKIP_IO_TRACE #define pr_fmt(fmt) "persistent_ram: " fmt #include @@ -49,7 +50,8 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz) } /* increase and wrap the start pointer, returning the old value */ -static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) +static size_t notrace buffer_start_add(struct persistent_ram_zone *prz, + size_t a) { int old; int new; @@ -71,7 +73,7 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) } /* increase the size counter until it hits the max size */ -static void buffer_size_add(struct persistent_ram_zone *prz, size_t a) +static void notrace buffer_size_add(struct persistent_ram_zone *prz, size_t a) { size_t old; size_t new; @@ -310,6 +312,12 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz, int c = count; size_t start; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + unsigned long flags = 0; + + if (prz->flags & PRZ_FLAG_BIG_LOCK) + raw_spin_lock_irqsave(&prz->buffer_lock, flags); +#endif if (unlikely(c > prz->buffer_size)) { s += c - prz->buffer_size; c = prz->buffer_size; @@ -330,6 +338,10 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz, persistent_ram_update_header_ecc(prz); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + if (prz->flags & PRZ_FLAG_BIG_LOCK) + raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); +#endif return count; } diff --git a/include/linux/amlogic/debug_ftrace_ramoops.h b/include/linux/amlogic/debug_ftrace_ramoops.h new file mode 100644 index 000000000000..51f4c88173c5 --- /dev/null +++ b/include/linux/amlogic/debug_ftrace_ramoops.h @@ -0,0 +1,62 @@ +/* + * include/linux/amlogic/debug_ftrace_ramoops.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __DEBUG_FTRACE_RAMOOPS_H__ +#define __DEBUG_FTRACE_RAMOOPS_H__ +#define __DEBUG_FTRACE_RAMOOPS_H__ +#include + +extern unsigned int ramoops_ftrace_en; +extern int ramoops_io_en; +extern unsigned int dump_iomap; + +#define PSTORE_FLAG_FUNC 0x1 +#define PSTORE_FLAG_IO_R 0x2 +#define PSTORE_FLAG_IO_W 0x3 +#define PSTORE_FLAG_IO_R_END 0x4 +#define PSTORE_FLAG_IO_W_END 0x5 +#define PSTORE_FLAG_IO_MAX 0x6 +#define PSTORE_FLAG_MASK 0xF + +void notrace pstore_io_save(unsigned long reg, unsigned long val, + unsigned long parant, unsigned int flag); + +//#define SKIP_IO_TRACE +#if (defined CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE) && (!defined SKIP_IO_TRACE) +#define pstore_ftrace_io_wr(reg, val) \ +pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W) + +#define pstore_ftrace_io_wr_end(reg, val) \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END) + +#define pstore_ftrace_io_rd(reg) \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R) +#define pstore_ftrace_io_rd_end(reg) \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END) + +#define need_dump_iomap() (ramoops_io_en | dump_iomap) + +#else +#define pstore_ftrace_io_wr(reg, val) do { } while (0) +#define pstore_ftrace_io_rd(reg) do { } while (0) +#define need_dump_iomap() 0 +#define pstore_ftrace_io_wr_end(reg, val) do { } while (0) +#define pstore_ftrace_io_rd_end(reg) do { } while (0) + +#endif + +#endif diff --git a/include/linux/amlogic/iomap.h b/include/linux/amlogic/iomap.h index 41d885badb9a..663ad76e8777 100644 --- a/include/linux/amlogic/iomap.h +++ b/include/linux/amlogic/iomap.h @@ -26,8 +26,9 @@ enum{ IO_HIUBUS_BASE, IO_BUS_MAX, }; -extern int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val); -extern int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val); + +extern inline int aml_reg_read(u32 bus_type, u32 reg, u32 *val); +extern inline int aml_reg_write(u32 bus_type, u32 reg, u32 val); extern int aml_regmap_update_bits(u32 bus_type, unsigned int reg, unsigned int mask, unsigned int val); diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index cb5edd64a3d3..6f8261547443 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -30,6 +30,7 @@ * PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required. */ #define PRZ_FLAG_NO_LOCK BIT(0) +#define PRZ_FLAG_BIG_LOCK BIT(7) struct persistent_ram_buffer; struct rs_control; diff --git a/lib/ioremap.c b/lib/ioremap.c index b9462037868d..e04366171cba 100644 --- a/lib/ioremap.c +++ b/lib/ioremap.c @@ -12,6 +12,10 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#include +#endif #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP static int __read_mostly ioremap_pud_capable; @@ -122,6 +126,19 @@ static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr, return 0; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +bool is_normal_memory(pgprot_t p) +{ +#if defined(CONFIG_ARM) + return ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC); +#elif defined(CONFIG_ARM64) + return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL); +#else +#error "Unuspported architecture" +#endif +} +#endif + int ioremap_page_range(unsigned long addr, unsigned long end, phys_addr_t phys_addr, pgprot_t prot) { @@ -143,7 +160,12 @@ int ioremap_page_range(unsigned long addr, } while (pgd++, addr = next, addr != end); flush_cache_vmap(start, end); - +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + if (need_dump_iomap() && !is_normal_memory(prot)) + pr_err("io__map pa:0x%lx,port:0x%lx\n", + start, end, (unsigned long)phys_addr, + (unsigned long)pgprot_val(prot)); +#endif return err; } EXPORT_SYMBOL_GPL(ioremap_page_range); From 33081d7a7b7ed5bec4cd28000dc904934d1b4cd4 Mon Sep 17 00:00:00 2001 From: "changqing.gao" Date: Thu, 4 Apr 2019 17:24:40 +0800 Subject: [PATCH 0421/1060] binder: fix memory leak [1/1] PD#TV-3541 Problem: 1.only vmalloc 4KB at first. 2.if user space need more memory, try to allocate a new vmalloc range with large size and move all related data to new place. 3.the first 4KB is not free when release this binder. Solution: free the first 4KB when release binder. Verify: R311 Change-Id: I4429de04a260671e4626b77ec340e47e436d5c8d Signed-off-by: changqing.gao --- drivers/android/binder_alloc.c | 5 +++++ drivers/android/binder_alloc.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 15f287250940..dfb9a24f030c 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -838,6 +838,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_get_vm_area_failed; } alloc->buffer = area->addr; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + alloc->first_addr = area->addr; +#endif alloc->user_buffer_offset = vma->vm_start - (uintptr_t)alloc->buffer; mutex_unlock(&binder_alloc_mmap_lock); @@ -958,6 +961,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) vfree(alloc->buffer); #ifdef CONFIG_AMLOGIC_BINDER_VMALLOC free_back_buffer(alloc); + if (alloc->first_addr && alloc->first_addr != alloc->buffer) + vfree(alloc->first_addr); #endif } mutex_unlock(&alloc->mutex); diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 592d4aa98945..2bda6b16584f 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -113,6 +113,7 @@ struct binder_alloc { #ifdef CONFIG_AMLOGIC_BINDER_VMALLOC size_t mapped_size; void *back_buffer[MAX_BUFFER]; + void *first_addr; #endif /* CONFIG_AMLOGIC_BINDER_VMALLOC */ ptrdiff_t user_buffer_offset; struct list_head buffers; From 4602afe4f40b7b26bc1cd280847da02b3268c23e Mon Sep 17 00:00:00 2001 From: wenbiao zhang Date: Wed, 10 Apr 2019 10:15:13 +0800 Subject: [PATCH 0422/1060] suspend: not do suspend action under freeze mode [1/1] PD#TV-4213 Problem: can't wake up by gpio/adc key when suspend into freeze mode Solution: not suspend gpio/adc when freeze Verify: X301 Change-Id: I32ff27aafebe35d8deb6e9b4d3daee686bbf90bc Signed-off-by: wenbiao zhang --- drivers/amlogic/iio/adc/meson_saradc.c | 7 +++++++ drivers/amlogic/input/keyboard/adc_keypad.c | 5 +++++ drivers/amlogic/input/keyboard/gpio_keypad.c | 6 ++++++ drivers/input/input-polldev.c | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index ca764dd3cc4e..9b4ab35f53f2 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -38,6 +38,7 @@ #include #include #include +#include #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) @@ -1702,6 +1703,9 @@ static int __maybe_unused meson_sar_adc_suspend(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); int ret; + if (is_pm_freeze_mode()) + return 0; + if (iio_buffer_enabled(indio_dev)) { ret = meson_sar_adc_buffer_predisable(indio_dev); if (ret) @@ -1720,6 +1724,9 @@ static int __maybe_unused meson_sar_adc_resume(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); int ret; + if (is_pm_freeze_mode()) + return 0; + ret = meson_sar_adc_hw_enable(indio_dev); if (ret) return ret; diff --git a/drivers/amlogic/input/keyboard/adc_keypad.c b/drivers/amlogic/input/keyboard/adc_keypad.c index 7182e595ab89..c1ad72014e22 100644 --- a/drivers/amlogic/input/keyboard/adc_keypad.c +++ b/drivers/amlogic/input/keyboard/adc_keypad.c @@ -576,6 +576,8 @@ static int meson_adc_kp_remove(struct platform_device *pdev) static int meson_adc_kp_suspend(struct platform_device *pdev, pm_message_t state) { + if (is_pm_freeze_mode()) + return 0; return 0; } @@ -584,6 +586,9 @@ static int meson_adc_kp_resume(struct platform_device *pdev) struct adc_key *key; struct meson_adc_kp *kp = platform_get_drvdata(pdev); + if (is_pm_freeze_mode()) + return 0; + if (get_resume_method() == POWER_KEY_WAKEUP) { list_for_each_entry(key, &kp->adckey_head, list) { if (key->code == KEY_POWER) { diff --git a/drivers/amlogic/input/keyboard/gpio_keypad.c b/drivers/amlogic/input/keyboard/gpio_keypad.c index 3fa6ea35bc30..fd43e6e2748e 100644 --- a/drivers/amlogic/input/keyboard/gpio_keypad.c +++ b/drivers/amlogic/input/keyboard/gpio_keypad.c @@ -343,6 +343,9 @@ static int meson_gpio_kp_suspend(struct platform_device *dev, { struct gpio_keypad *pdata; + if (is_pm_freeze_mode()) + return 0; + pdata = (struct gpio_keypad *)platform_get_drvdata(dev); if (!pdata->use_irq) del_timer(&(pdata->polling_timer)); @@ -354,6 +357,9 @@ static int meson_gpio_kp_resume(struct platform_device *dev) int i; struct gpio_keypad *pdata; + if (is_pm_freeze_mode()) + return 0; + pdata = (struct gpio_keypad *)platform_get_drvdata(dev); if (!pdata->use_irq) mod_timer(&(pdata->polling_timer), diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 3664f81655ca..3dad3a24f115 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -30,7 +30,7 @@ static void input_polldev_queue_work(struct input_polled_dev *dev) if (delay >= HZ) delay = round_jiffies_relative(delay); - queue_delayed_work(system_freezable_wq, &dev->work, delay); + queue_delayed_work(system_wq, &dev->work, delay); } static void input_polled_device_work(struct work_struct *work) From 634cd20ebff0c771bb432b6d8be528292adf91f2 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Wed, 17 Apr 2019 02:35:27 +0800 Subject: [PATCH 0423/1060] vpp: don't overwrite on_pending state when enable vd layer [1/1] PD#OTT-3244 Problem: When vd layer state is on_pending, calling enable videolayer function will overwrite the state. Then it will not enable video layer really. Solution: Add the judgement to check if the state is on_pending. Verify: verified on W400 Change-Id: I0513a6610fdb108bec05858c7f6c7976be5e7edb Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 5722a3b2e2b4..d208cc2fa7e3 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -322,7 +322,8 @@ static u32 frame_detect_drop_count; do { \ unsigned long flags; \ spin_lock_irqsave(&video_onoff_lock, flags); \ - video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + if (video_onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ + video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ video_enabled = 1; \ video_status_saved = 1; \ spin_unlock_irqrestore(&video_onoff_lock, flags); \ @@ -342,7 +343,8 @@ static u32 frame_detect_drop_count; do { \ unsigned long flags; \ spin_lock_irqsave(&video2_onoff_lock, flags); \ - video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + if (video2_onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ + video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ video2_enabled = 1; \ video2_status_saved = 1; \ spin_unlock_irqrestore(&video2_onoff_lock, flags); \ From 253155a2208b07b29d2754c0dd9a8270b4b717e4 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Tue, 16 Apr 2019 19:50:42 +0800 Subject: [PATCH 0424/1060] amvecm: fix dnlp iRgnBgn and iRgnEnd not load db value [1/1] PD#SWPL-7262 Problem: dnlp iRgnBgn and iRgnEnd not load db value Solution: add refresh of iRgnBgn and iRgnEnd. Verify: on x301 Change-Id: I81ae91490a7fd2899eefd4f800948851ebbf21e7 Signed-off-by: Bencheng Jing --- drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c index f2c6773024f2..bd88c513664e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c @@ -637,6 +637,10 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) p->param[ve_dnlp_whtext_ofst]) || (dnlp_alg_param.dnlp_bwext_div4x_min != p->param[ve_dnlp_bwext_div4x_min]) || + (dnlp_alg_param.dnlp_iRgnBgn != + p->param[ve_dnlp_iRgnBgn]) || + (dnlp_alg_param.dnlp_iRgnEnd != + p->param[ve_dnlp_iRgnEnd]) || (dnlp_alg_param.dnlp_blk_cctr != p->param[ve_dnlp_blk_cctr]) || (dnlp_alg_param.dnlp_brgt_ctrl != @@ -752,6 +756,8 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) dnlp_alg_param.dnlp_blkext_ofst = p->param[ve_dnlp_blkext_ofst]; dnlp_alg_param.dnlp_whtext_ofst = p->param[ve_dnlp_whtext_ofst]; dnlp_alg_param.dnlp_bwext_div4x_min = p->param[ve_dnlp_bwext_div4x_min]; + dnlp_alg_param.dnlp_iRgnBgn = p->param[ve_dnlp_iRgnBgn]; + dnlp_alg_param.dnlp_iRgnEnd = p->param[ve_dnlp_iRgnEnd]; /* brightness_plus */ dnlp_alg_param.dnlp_blk_cctr = p->param[ve_dnlp_blk_cctr]; From 1fa91fd8f7a6c60515ce79391cd4349a1042ae7c Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Thu, 4 Apr 2019 22:34:15 +0800 Subject: [PATCH 0425/1060] gdc: add gdc interface with loading fw [1/2] PD#SWPL-4611 Problem: add gdc interface with loading fw Solution: add new gdc interface to request firmware Verify: Verfied on G12B-W400 Change-Id: Id8e0d600eec5f4777511b1fc0e38a1773db9e9cb Signed-off-by: Jian Cao --- drivers/amlogic/media/gdc/app/gdc_module.c | 349 ++++++++++++++++++++ drivers/amlogic/media/gdc/inc/api/gdc_api.h | 108 +++++- 2 files changed, 456 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index f6f0af338aa9..678980b9c464 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -41,6 +41,8 @@ #include #include #include +#include + //gdc configuration sequence #include "gdc_config.h" #include "gdc_dmabuf.h" @@ -794,6 +796,344 @@ void unmap_virt_from_phys(u8 __iomem *vaddr) } } +static void release_config_firmware(struct gdc_settings_with_fw *gs_with_fw) +{ + + if (gs_with_fw->fw_info.virt_addr) + unmap_virt_from_phys(gs_with_fw->fw_info.virt_addr); + if (gs_with_fw->fw_info.cma_pages) { + dma_release_from_contiguous( + &gdc_manager.gdc_dev->pdev->dev, + gs_with_fw->fw_info.cma_pages, + PAGE_ALIGN(gs_with_fw->gdc_config.config_size * 4) + >> PAGE_SHIFT); + + gs_with_fw->fw_info.cma_pages = NULL; + } +} + +static int load_firmware_by_name(struct gdc_settings_with_fw *gs_with_fw) +{ + int ret = -1; + const struct firmware *fw = NULL; + char *path = NULL; + struct fw_info_s *current_fw = &gs_with_fw->fw_info; + struct page *cma_pages = NULL; + void __iomem *virt_addr = NULL; + phys_addr_t phys_addr = 0; + + if (!current_fw->fw_name) { + gdc_log(LOG_ERR, "current firmware name is NULL, invalid\n"); + return -EINVAL; + } + + gdc_log(LOG_DEBUG, "Try to load %s ...\n", current_fw->fw_name); + + path = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); + if (!path) { + gdc_log(LOG_ERR, "cannot malloc fw_name!\n"); + return -ENOMEM; + } + snprintf(path, (CONFIG_PATH_LENG - 1), "%s/%s", + FIRMWARE_DIR, current_fw->fw_name); + + ret = request_firmware(&fw, path, &gdc_manager.gdc_dev->pdev->dev); + if (ret < 0) { + gdc_log(LOG_ERR, "Error : %d can't load the %s.\n", ret, path); + kfree(path); + return -ENOENT; + } + + if (fw->size <= 0) { + gdc_log(LOG_ERR, + "size error, wrong firmware or no enough mem.\n"); + ret = -ENOMEM; + goto release; + } + + cma_pages = dma_alloc_from_contiguous(&gdc_manager.gdc_dev->pdev->dev, + PAGE_ALIGN(fw->size) >> PAGE_SHIFT, 0); + if (cma_pages != NULL) { + phys_addr = page_to_phys(cma_pages); + virt_addr = map_virt_from_phys(phys_addr, + PAGE_ALIGN(fw->size)); + if (!virt_addr) { + gdc_log(LOG_ERR, "map_virt_from_phys failed\n"); + dma_release_from_contiguous( + &gdc_manager.gdc_dev->pdev->dev, + cma_pages, + PAGE_ALIGN(fw->size) >> PAGE_SHIFT); + ret = -ENOMEM; + goto release; + } + } else { + gdc_log(LOG_ERR, "Failed to alloc dma buff\n"); + ret = -ENOMEM; + goto release; + } + memcpy(virt_addr, (char *)fw->data, fw->size); + + gdc_log(LOG_DEBUG, + "current firmware virt_addr: 0x%p, fw->data: 0x%p.\n", + virt_addr, fw->data); + + gs_with_fw->gdc_config.config_addr = phys_addr; + gs_with_fw->gdc_config.config_size = fw->size / 4; + gs_with_fw->fw_info.cma_pages = cma_pages; + + gdc_log(LOG_DEBUG, "load firmware size : %zd, Name : %s.\n", + fw->size, path); + ret = fw->size; + +release: + release_firmware(fw); + kfree(path); + + return ret; +} + +static long gdc_process_with_fw(struct mgdc_fh_s *fh, + struct gdc_settings_with_fw *gs_with_fw) +{ + long ret = -1; + unsigned long addr = 0; + size_t len; + struct aml_dma_cfg *cfg = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + char *fw_name = NULL; + + if (fh == NULL || gs_with_fw == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + + gs_with_fw->fw_info.virt_addr = NULL; + gs_with_fw->fw_info.cma_pages = NULL; + + memcpy(&(gdc_cmd->gdc_config), &(gs_with_fw->gdc_config), + sizeof(struct gdc_config_s)); + + fw_name = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); + if (!fw_name) { + gdc_log(LOG_ERR, "cannot malloc fw_name!\n"); + return -ENOMEM; + } + + gdc_cmd->fh = fh; + if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_with_fw->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d failed\n", + gs_with_fw->output_buffer.shared_fd); + ret = -EINVAL; + goto release_fw_name; + } + } else if (gs_with_fw->output_buffer.mem_alloc_type == + AML_GDC_MEM_DMABUF) { + /* dma alloc */ + cfg = &fh->dma_cfg.output_cfg; + cfg->fd = gs_with_fw->output_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, "dma import out fd %d failed\n", + gs_with_fw->output_buffer.y_base_fd); + ret = -EINVAL; + goto release_fw_name; + } + } + gdc_log(LOG_INFO, "%s, output addr=%lx\n", __func__, addr); + gdc_cmd->base_gdc = 0; + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + + if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_with_fw->input_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d failed\n", + gs_with_fw->input_buffer.shared_fd); + ret = -EINVAL; + goto unmap; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr failed\n"); + ret = -EINVAL; + goto unmap; + } + } else if (gs_with_fw->input_buffer.mem_alloc_type == + AML_GDC_MEM_DMABUF) { + /* dma alloc */ + gdc_process_input_dma_info(fh, + (struct gdc_settings_ex *)gs_with_fw); + } + gdc_log(LOG_INFO, "%s, input addr=%x\n", + __func__, fh->gdc_cmd.y_base_addr); + + /* load firmware */ + if (gs_with_fw->fw_info.fw_name != NULL) { + ret = load_firmware_by_name(gs_with_fw); + if (ret <= 0) { + gdc_log(LOG_ERR, "line %d,load FW %s failed\n", + __LINE__, gs_with_fw->fw_info.fw_name); + ret = -EINVAL; + goto release_fw; + } + } + + if (ret <= 0 || gs_with_fw->fw_info.fw_name == NULL) { + char in_info[64] = {}; + char out_info[64] = {}; + char *format = NULL; + struct fw_input_info_s *in = &gs_with_fw->fw_info.fw_input_info; + struct fw_output_info_s *out = + &gs_with_fw->fw_info.fw_output_info; + union transform_u *trans = + &gs_with_fw->fw_info.fw_output_info.trans; + + switch (gdc_cmd->gdc_config.format) { + case NV12: + format = "nv12"; + break; + case YV12: + format = "yv12"; + break; + case Y_GREY: + format = "ygrey"; + break; + case YUV444_P: + format = "yuv444p"; + break; + case RGB444_P: + format = "rgb444p"; + break; + default: + gdc_log(LOG_ERR, "unsupported gdc format\n"); + ret = -EINVAL; + goto release_fw; + } + snprintf(in_info, (64 - 1), "%d_%d_%d_%d_%d_%d", + in->with, in->height, + in->fov, in->diameter, + in->offsetX, in->offsetY); + + snprintf(out_info, (64 - 1), "%d_%d_%d_%d-%d_%d_%s", + out->offsetX, out->offsetY, + out->width, out->height, + out->pan, out->tilt, out->zoom); + + switch (gs_with_fw->fw_info.fw_type) { + case EQUISOLID: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "equisolid-%s-%s-%s_%s_%d-%s.bin", + in_info, out_info, + trans->fw_equisolid.strengthX, + trans->fw_equisolid.strengthY, + trans->fw_equisolid.rotation, + format); + break; + case CYLINDER: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "cylinder-%s-%s-%s_%d-%s.bin", + in_info, out_info, + trans->fw_cylinder.strength, + trans->fw_cylinder.rotation, + format); + break; + case EQUIDISTANT: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "equidistant-%s-%s-%s_%d_%d_%d_%d_%d_%d_%d-%s.bin", + in_info, out_info, + trans->fw_equidistant.azimuth, + trans->fw_equidistant.elevation, + trans->fw_equidistant.rotation, + trans->fw_equidistant.fov_width, + trans->fw_equidistant.fov_height, + trans->fw_equidistant.keep_ratio, + trans->fw_equidistant.cylindricityX, + trans->fw_equidistant.cylindricityY, + format); + break; + case CUSTOM: + if (trans->fw_custom.fw_name != NULL) { + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "custom-%s-%s-%s-%s.bin", + in_info, out_info, + trans->fw_custom.fw_name, + format); + } else { + gdc_log(LOG_ERR, "custom fw_name is NULL\n"); + ret = -EINVAL; + goto release_fw; + } + break; + case AFFINE: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "affine-%s-%s-%d-%s.bin", + in_info, out_info, + trans->fw_affine.rotation, + format); + break; + default: + gdc_log(LOG_ERR, "unsupported FW type\n"); + ret = -EINVAL; + goto release_fw; + } + + gs_with_fw->fw_info.fw_name = fw_name; + } + ret = load_firmware_by_name(gs_with_fw); + if (ret <= 0) { + gdc_log(LOG_ERR, "line %d,load FW %s failed\n", + __LINE__, gs_with_fw->fw_info.fw_name); + ret = -EINVAL; + goto release_fw; + } + + gdc_cmd->gdc_config.config_addr = + gs_with_fw->gdc_config.config_addr; + gdc_cmd->gdc_config.config_size = + gs_with_fw->gdc_config.config_size; + + mutex_lock(&fh->gdev->d_mutext); + ret = gdc_run(gdc_cmd); + if (ret < 0) + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); + + ret = wait_for_completion_timeout(&fh->gdev->d_com, + msecs_to_jiffies(40)); + if (ret == 0) + gdc_log(LOG_ERR, "gdc timeout\n"); + + gdc_stop(gdc_cmd); + mutex_unlock(&fh->gdev->d_mutext); + +release_fw: + release_config_firmware(gs_with_fw); + +unmap: + if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); + if (gs_with_fw->input_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + } + + if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); + +release_fw_name: + kfree(fw_name); + + return ret; +} +EXPORT_SYMBOL(gdc_process_with_fw); int write_buf_to_file(char *path, char *buf, int size) { int ret = 0; @@ -841,6 +1181,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, struct gdc_buf_cfg buf_cfg; struct page *cma_pages = NULL; struct gdc_settings_ex gs_ex; + struct gdc_settings_with_fw gs_with_fw; struct gdc_dmabuf_req_s gdc_req_buf; struct gdc_dmabuf_exp_s gdc_exp_buf; ion_phys_addr_t addr; @@ -1135,6 +1476,14 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, } break; + case GDC_PROCESS_WITH_FW: + ret = copy_from_user(&gs_with_fw, argp, sizeof(gs_with_fw)); + if (ret < 0) + gdc_log(LOG_ERR, "copy from user failed\n"); + memcpy(&gdc_cmd->gdc_config, &gs_with_fw.gdc_config, + sizeof(struct gdc_config_s)); + ret = gdc_process_with_fw(fh, &gs_with_fw); + break; case GDC_PROCESS_EX: ret = copy_from_user(&gs_ex, argp, sizeof(gs_ex)); if (ret < 0) diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index 942bd4052fb7..bc46e966c941 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -143,7 +143,8 @@ struct gdc_dmabuf_exp_s { #define GDC_FREE_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x08, int) #define GDC_SYNC_DEVICE _IOW(GDC_IOC_MAGIC, 0x09, int) #define GDC_SYNC_CPU _IOW(GDC_IOC_MAGIC, 0x0a, int) - +#define GDC_PROCESS_WITH_FW _IOW(GDC_IOC_MAGIC, 0x0b, \ + struct gdc_settings_with_fw) enum { INPUT_BUFF_TYPE = 0x1000, @@ -161,6 +162,15 @@ enum { FMT_MAX }; +enum { + EQUISOLID = 1, + CYLINDER, + EQUIDISTANT, + CUSTOM, + AFFINE, + FW_TYPE_MAX +}; + struct gdc_dma_cfg { int fd; void *dev; @@ -205,6 +215,102 @@ struct gdc_cmd_s { void *fh; }; +/* path: "/vendor/lib/firmware/gdc/" */ +#define FIRMWARE_DIR "gdc" + +struct fw_equisolid_s { + /* float */ + char strengthX[8]; + /* float */ + char strengthY[8]; + int rotation; +}; + +struct fw_cylinder_s { + /* float */ + char strength[8]; + int rotation; +}; + +struct fw_equidistant_s { + /* float */ + char azimuth[8]; + int elevation; + int rotation; + int fov_width; + int fov_height; + bool keep_ratio; + int cylindricityX; + int cylindricityY; +}; + +struct fw_custom_s { + char *fw_name; +}; + + +struct fw_affine_s { + int rotation; +}; + +struct fw_input_info_s { + int with; + int height; + int fov; + int diameter; + int offsetX; + int offsetY; +}; + +union transform_u { + struct fw_equisolid_s fw_equisolid; + struct fw_cylinder_s fw_cylinder; + struct fw_equidistant_s fw_equidistant; + struct fw_custom_s fw_custom; + struct fw_affine_s fw_affine; +}; + +struct fw_output_info_s { + int offsetX; + int offsetY; + int width; + int height; + union transform_u trans; + int pan; + int tilt; + /* float*/ + char zoom[8]; +}; + +struct firmware_info { + unsigned int format; + unsigned int trans_size_type; + char *file_name; + phys_addr_t phys_addr; + void __iomem *virt_addr; + unsigned int size; + struct page *cma_pages; + unsigned int loaded; +}; + +struct fw_info_s { + char *fw_name; + int fw_type; + struct page *cma_pages; + phys_addr_t phys_addr; + void __iomem *virt_addr; + struct fw_input_info_s fw_input_info; + struct fw_output_info_s fw_output_info; +}; + +struct gdc_settings_with_fw { + uint32_t magic; + struct gdc_config_s gdc_config; + struct gdc_buffer_info input_buffer; + struct gdc_buffer_info output_buffer; + struct fw_info_s fw_info; +}; + /** * Configure the output gdc configuration * From 6b25d1971cd40594b42dca0a461be9947b71fd0f Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Tue, 16 Apr 2019 09:42:24 +0800 Subject: [PATCH 0426/1060] kasan: bring up KASAN for 32bit os [2/2] PD#SWPL-7085 Problem: Currently kasan can't be used on 32bit kernel, it's difficult to debug memory problems; Solution: Bring up KASAN on 32bit kernel Verify: p212 Change-Id: I4d80568f023315994e969c79b786eba856177c9c Signed-off-by: Tao Zeng --- MAINTAINERS | 5 + arch/arm/Kconfig | 2 + arch/arm/Makefile | 4 + arch/arm/boot/compressed/Makefile | 2 + arch/arm/boot/compressed/string.c | 2 + arch/arm/include/asm/highmem.h | 5 + arch/arm/include/asm/kasan.h | 66 +++++++++ arch/arm/include/asm/memory.h | 28 +++- arch/arm/include/asm/pgtable.h | 2 + arch/arm/include/asm/string.h | 19 +++ arch/arm/include/asm/thread_info.h | 6 + arch/arm/include/asm/uaccess.h | 15 ++ arch/arm/kernel/armksyms.c | 6 + arch/arm/kernel/head-common.S | 3 + arch/arm/kernel/module.c | 18 +++ arch/arm/kernel/setup.c | 6 + arch/arm/kernel/unwind.c | 19 +++ arch/arm/lib/memcpy.S | 8 ++ arch/arm/lib/memmove.S | 8 ++ arch/arm/lib/memset.S | 8 ++ arch/arm/mm/Makefile | 3 + arch/arm/mm/init.c | 9 ++ arch/arm/mm/kasan_init.c | 218 +++++++++++++++++++++++++++++ arch/arm/mm/mmu.c | 38 ++++- arch/arm/vdso/Makefile | 2 + drivers/amlogic/memory_ext/Kconfig | 13 ++ drivers/of/of_reserved_mem.c | 12 ++ mm/kasan/kasan.c | 20 +++ 28 files changed, 543 insertions(+), 4 deletions(-) create mode 100644 arch/arm/include/asm/kasan.h create mode 100644 arch/arm/mm/kasan_init.c diff --git a/MAINTAINERS b/MAINTAINERS index ad61e61d39af..82e99de98a39 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13547,6 +13547,11 @@ AMLOGIC boot config for M8B M: Tao Zeng F: arch/arm/mach-meson/Makefile.boot +AMLOGIC implementation for 32bit kasan +M: Tao Zeng +F: arch/arm/include/asm/kasan.h +F: arch/arm/mm/kasan_init.c + HDMITX OUTPUT DRIVER M: Yi Zhou M: Zongdong Jiao diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 787018c6c91c..1ee0ee67df03 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -90,6 +90,7 @@ config ARM select PERF_USE_VMALLOC select RTC_LIB select SYS_SUPPORTS_APM_EMULATION + select HAVE_ARCH_KASAN # Above selects are sorted alphabetically; please add new ones # according to that. Thanks. help @@ -1444,6 +1445,7 @@ config PAGE_OFFSET default 0x40000000 if VMSPLIT_1G default 0x80000000 if VMSPLIT_2G default 0xB0000000 if VMSPLIT_3G_OPT + default 0xD0000000 if AMLOGIC_KASAN32 default 0xC0000000 config NR_CPUS diff --git a/arch/arm/Makefile b/arch/arm/Makefile index a7645d4f0648..ca83dfdc362d 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -52,6 +52,10 @@ AS += -EL LD += -EL endif +ifeq ($(CONFIG_KASAN),y) +KASAN_SHADOW_OFFSET := 0xA0000000 +endif + # # The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and # later may result in code being generated that handles signed short and signed diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 552c7d7f84ce..05fed5260e10 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -4,6 +4,8 @@ # create a compressed vmlinuz image from the original vmlinux # +KASAN_SANITIZE := n + OBJS = AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c index 689467448736..d7b27c5069e0 100644 --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c @@ -120,7 +120,9 @@ char *strchr(const char *s, int c) return (char *)s; } +#ifndef CONFIG_AMLOGIC_KASAN32 /* for compile problems */ #undef memset +#endif void *memset(void *s, int c, size_t count) { diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 0a0e2d1784c0..e3ff8a8d2a96 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -3,7 +3,12 @@ #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#define PKMAP_BASE VMALLOC_END +#else #define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE) +#endif #define LAST_PKMAP PTRS_PER_PTE #define LAST_PKMAP_MASK (LAST_PKMAP - 1) #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) diff --git a/arch/arm/include/asm/kasan.h b/arch/arm/include/asm/kasan.h new file mode 100644 index 000000000000..7b86cb0096b1 --- /dev/null +++ b/arch/arm/include/asm/kasan.h @@ -0,0 +1,66 @@ +#ifndef __ASM_KASAN_H +#define __ASM_KASAN_H + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_KASAN + +#include +#include + +#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) +#define PAGE_KERNEL_RO _MOD_PROT(pgprot_kernel, L_PTE_RDONLY) + +/* + * KASAN_SHADOW_START: beginning of the kernel virtual addresses. + * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/8 of kernel virtual addresses. + * + * For 32bit KASAN, we using a fixed Memory map here + * + * 0x00000000 +--------+ + * | | + * | | + * | | User space memory, 2944MB + * | | + * | | + * 0xb8000000 +--------+ + * | | Kasan shaddow memory, 128MB + * 0xc0000000 +--------+ + * | | Vmalloc address, 240MB + * | | + * 0xCF400000 +--------+ + * 0xCF600000 +--------+ PKmap, for kmap 2MB + * 0xD0000000 +--------+ Module and pkmap, 10MB + * | | + * | | Kernel linear mapped space, 762MB + * 0xFFa00000 +--------+ + * 0xFFFc0000 +--------+ static map, 2MB + * 0xFFF00000 +--------+ Fixed map, for kmap_atomic, 3MB + * 0xFFFF0000 +--------+ High vector, 4KB + * + */ +#define KADDR_SIZE (SZ_1G) +#define KASAN_SHADOW_SIZE (KADDR_SIZE >> 3) +#define KASAN_SHADOW_START (TASK_SIZE) +#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE) + +/* + * This value is used to map an address to the corresponding shadow + * address by the following formula: + * shadow_addr = (address >> 3) + KASAN_SHADOW_OFFSET; + * + */ +#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_START - (VMALLOC_START >> 3)) +struct map_desc; +void kasan_init(void); +void kasan_copy_shadow(pgd_t *pgdir); +asmlinkage void kasan_early_init(void); +void cpu_v7_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); +void create_mapping(struct map_desc *md); +#else +static inline void kasan_init(void) { } +static inline void kasan_copy_shadow(pgd_t *pgdir) { } +#endif + +#endif +#endif diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 508cee7161da..f03375912f4e 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -39,15 +39,22 @@ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area */ #define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_64M)) -#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) -#else /* CONFIG_AMLOGIC_VMAP */ +#elif defined(CONFIG_AMLOGIC_KASAN32) +/* + * reserve 128MB address space for kasan + * for this memory layout implementation, PAGE_OFFSET should be 0xD0000000 + */ +#define VMALLOC_START (UL(CONFIG_PAGE_OFFSET) - UL(SZ_256M)) +#define TASK_SIZE (VMALLOC_START - UL(SZ_128M)) +#define KMEM_END (0xffa00000UL) +#else /* * TASK_SIZE - the maximum size of a user space task. * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area */ #define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M)) -#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) #endif /* CONFIG_AMLOGIC_VMAP */ +#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) /* * The maximum size of a 26-bit user space task. @@ -66,13 +73,24 @@ * and PAGE_OFFSET - it must be within 32MB of the kernel text. */ #ifndef CONFIG_THUMB2_KERNEL +#ifdef CONFIG_AMLOGIC_KASAN32 +/* + * to fix module link problem + */ +#define MODULES_VADDR (PAGE_OFFSET - SZ_16M + SZ_4M + SZ_2M) +#else #define MODULES_VADDR (PAGE_OFFSET - SZ_16M) +#endif #else /* smaller range for Thumb-2 symbols relocation (2^24)*/ #define MODULES_VADDR (PAGE_OFFSET - SZ_8M) #endif #endif /* CONFIG_AMLOGIC_VMAP */ +#ifdef CONFIG_AMLOGIC_KASAN32 +#define VMALLOC_END (MODULES_VADDR - SZ_2M) +#endif + #if TASK_SIZE > MODULES_VADDR #error Top of user space clashes with start of module space #endif @@ -80,11 +98,15 @@ /* * The highmem pkmap virtual space shares the end of the module area. */ +#ifdef CONFIG_AMLOGIC_KASAN32 +#define MODULES_END (PAGE_OFFSET) +#else #ifdef CONFIG_HIGHMEM #define MODULES_END (PAGE_OFFSET - PMD_SIZE) #else #define MODULES_END (PAGE_OFFSET) #endif +#endif /* * The XIP kernel gets mapped at the bottom of the module vm area. diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a8d656d9aec7..b4fe2f6be7d9 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -41,9 +41,11 @@ * The vmalloc() routines leaves a hole of 4kB between each vmalloced * area for the same reason. ;) */ +#ifndef CONFIG_AMLOGIC_KASAN32 #define VMALLOC_OFFSET (8*1024*1024) #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_END 0xff800000UL +#endif /* !CONFIG_AMLOGIC_KASAN32 */ #define LIBRARY_TEXT_START 0x0c000000 diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h index cf4f3aad0fc1..8b9e9029ab4e 100644 --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h @@ -26,6 +26,24 @@ extern void * memset(void *, int, __kernel_size_t); extern void __memzero(void *ptr, __kernel_size_t n); +#ifdef CONFIG_AMLOGIC_KASAN32 +/* replace default function to check kasan */ +extern void *__memcpy(void *dst, const void *src, __kernel_size_t size); +extern void *__memmove(void *dst, const void *src, __kernel_size_t size); +extern void *__memset(void *dst, int v, __kernel_size_t size); +#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__) + +/* + * For files that are not instrumented (e.g. mm/slub.c) we + * should use not instrumented version of mem* functions. + */ + +#define memcpy(dst, src, len) __memcpy(dst, src, len) +#define memmove(dst, src, len) __memmove(dst, src, len) +#define memset(s, c, n) __memset(s, c, n) +#endif + +#else #define memset(p,v,n) \ ({ \ void *__p = (p); size_t __n = n; \ @@ -39,3 +57,4 @@ extern void __memzero(void *ptr, __kernel_size_t n); }) #endif +#endif diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index f01c1eb8000d..935ec19a5b4d 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -16,8 +16,14 @@ #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#define THREAD_SIZE_ORDER 2 +#else #define THREAD_SIZE_ORDER 1 +#endif /* CONFIG_AMLOGIC_KASAN32 */ + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + #ifdef CONFIG_AMLOGIC_VMAP #define THREAD_INFO_SIZE (sizeof(struct thread_info)) #define THREAD_INFO_OFFSET (THREAD_SIZE - THREAD_INFO_SIZE) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 0f6c6b873bc5..eec26db9bdd3 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -18,6 +18,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #include @@ -581,6 +584,9 @@ __clear_user(void __user *addr, unsigned long n) static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n) { +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_write(to, n); +#endif check_object_size(to, n, false); return __arch_copy_from_user(to, from, n); } @@ -589,6 +595,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long res = n; +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_write(to, n); +#endif check_object_size(to, n, false); @@ -602,6 +611,9 @@ copy_from_user(void *to, const void __user *from, unsigned long n) static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_read(from, n); +#endif check_object_size(from, n, true); return __arch_copy_to_user(to, from, n); @@ -610,6 +622,9 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_read(from, n); +#endif check_object_size(from, n, true); if (access_ok(VERIFY_WRITE, to, n)) diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 8e8d20cdbce7..dfadaff9f145 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -181,3 +181,9 @@ EXPORT_SYMBOL(__pv_offset); EXPORT_SYMBOL(__arm_smccc_smc); EXPORT_SYMBOL(__arm_smccc_hvc); #endif + +#ifdef CONFIG_AMLOGIC_KASAN32 +EXPORT_SYMBOL(__memset); +EXPORT_SYMBOL(__memcpy); +EXPORT_SYMBOL(__memmove); +#endif diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index d37d58602d77..165b95a1b91c 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -101,6 +101,9 @@ __mmap_switched: str r2, [r6] @ Save atags pointer cmp r7, #0 strne r0, [r7] @ Save control register values +#ifdef CONFIG_AMLOGIC_KASAN32 + bl kasan_early_init +#endif b start_kernel ENDPROC(__mmap_switched) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 4f14b5ce6535..cb235c9a0b61 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -25,6 +25,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #ifdef CONFIG_XIP_KERNEL /* @@ -40,6 +43,20 @@ #ifdef CONFIG_MMU void *module_alloc(unsigned long size) { +#ifdef CONFIG_AMLOGIC_KASAN32 + void *p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, + MODULES_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, + NUMA_NO_NODE, __builtin_return_address(0)); + if (!p) + p = __vmalloc_node_range(size, MODULE_ALIGN, VMALLOC_START, + VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, + NUMA_NO_NODE, __builtin_return_address(0)); + if (p && (kasan_module_alloc(p, size) < 0)) { + vfree(p); + return NULL; + } + return p; +#else void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); @@ -48,6 +65,7 @@ void *module_alloc(unsigned long size) return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); +#endif } #endif diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index dfcb653f46a6..f318e5a6721a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -68,6 +68,9 @@ #ifdef CONFIG_AMLOGIC_CPU_INFO #include #endif +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #include "atags.h" @@ -1137,6 +1140,9 @@ void __init setup_arch(char **cmdline_p) early_ioremap_reset(); paging_init(mdesc); +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_init(); +#endif request_standard_resources(mdesc); if (mdesc->restart) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 8fc6b5601a54..5d321b6c7314 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -246,8 +246,21 @@ static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) } /* Before poping a register check whether it is feasible or not */ +#ifdef CONFIG_AMLOGIC_KASAN32 +/* + * If enabled KASAN and unwind_frame is called under IRQ routine, + * an value-less kasan report will trigger. Because IRQ is using + * thread context and don't initialized shadow memory when irq_svc + * saving irq context. Since it's hard to guess reserved memory for + * shadow in stack by compiler, so we just tell compiler do not + * sanitize for this function + */ +int __no_sanitize_address unwind_pop_register(struct unwind_ctrl_block *ctrl, + unsigned long **vsp, unsigned int reg) +#else static int unwind_pop_register(struct unwind_ctrl_block *ctrl, unsigned long **vsp, unsigned int reg) +#endif { if (unlikely(ctrl->check_each_pop)) if (*vsp >= (unsigned long *)ctrl->sp_high) @@ -407,7 +420,13 @@ int unwind_frame(struct stackframe *frame) idx = unwind_find_idx(frame->pc); if (!idx) { + #ifdef CONFIG_AMLOGIC_KASAN32 + /* avoid FUCKING close source ko print too many here */ + if (frame->pc > PAGE_OFFSET) + pr_warn("unwind: Index not found %08lx\n", frame->pc); + #else pr_warn("unwind: Index not found %08lx\n", frame->pc); + #endif return -URC_FAILURE; } diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index 64111bd4440b..044d499eadad 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -62,9 +62,17 @@ /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ ENTRY(mmiocpy) +#ifdef CONFIG_AMLOGIC_KASAN32 +ENTRY(__memcpy) +#else ENTRY(memcpy) +#endif #include "copy_template.S" +#ifdef CONFIG_AMLOGIC_KASAN32 +ENDPROC(__memcpy) +#else ENDPROC(memcpy) +#endif ENDPROC(mmiocpy) diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S index 69a9d47fc5ab..d508fe8ff380 100644 --- a/arch/arm/lib/memmove.S +++ b/arch/arm/lib/memmove.S @@ -27,7 +27,11 @@ * occurring in the opposite direction. */ +#ifdef CONFIG_AMLOGIC_KASAN32 +ENTRY(__memmove) +#else ENTRY(memmove) +#endif UNWIND( .fnstart ) subs ip, r0, r1 @@ -224,4 +228,8 @@ ENTRY(memmove) 18: backward_copy_shift push=24 pull=8 +#ifdef CONFIG_AMLOGIC_KASAN32 +ENDPROC(__memmove) +#else ENDPROC(memmove) +#endif diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 3c65e3bd790f..5d23be8b7fab 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -17,7 +17,11 @@ .align 5 ENTRY(mmioset) +#ifdef CONFIG_AMLOGIC_KASAN32 +ENTRY(__memset) +#else ENTRY(memset) +#endif UNWIND( .fnstart ) ands r3, r0, #3 @ 1 unaligned? mov ip, r0 @ preserve r0 as return value @@ -133,5 +137,9 @@ UNWIND( .fnstart ) add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) b 1b UNWIND( .fnend ) +#ifdef CONFIG_AMLOGIC_KASAN32 +ENDPROC(__memset) +#else ENDPROC(memset) +#endif ENDPROC(mmioset) diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 92d47c8cbbc3..0beabc46eab7 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -107,3 +107,6 @@ obj-$(CONFIG_CACHE_L2X0_PMU) += cache-l2x0-pmu.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o + +obj-$(CONFIG_AMLOGIC_KASAN32) += kasan_init.o +KASAN_SANITIZE_kasan_init.o := n diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1565d6b67163..96b980673501 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -36,6 +36,9 @@ #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #include "mm.h" @@ -502,6 +505,9 @@ void __init mem_init(void) #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) pr_notice("Virtual kernel memory layout:\n" +#ifdef CONFIG_AMLOGIC_KASAN32 + " kasan : 0x%08lx - 0x%08lx (%4ld MB)\n" +#endif " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" #ifdef CONFIG_HAVE_TCM " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" @@ -520,6 +526,9 @@ void __init mem_init(void) " .init : 0x%p" " - 0x%p" " (%4td kB)\n" " .data : 0x%p" " - 0x%p" " (%4td kB)\n" " .bss : 0x%p" " - 0x%p" " (%4td kB)\n", +#ifdef CONFIG_AMLOGIC_KASAN32 + MLM(KASAN_SHADOW_START, KASAN_SHADOW_END), +#endif MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) + (PAGE_SIZE)), diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c new file mode 100644 index 000000000000..ac269046dbb9 --- /dev/null +++ b/arch/arm/mm/kasan_init.c @@ -0,0 +1,218 @@ +/* + * This file contains kasan initialization code for ARM64. + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Author: Andrey Ryabinin + * + * 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. + * + */ + +#define pr_fmt(fmt) "kasan: " fmt +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t)) + +static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE); + +/* + * The p*d_populate functions call virt_to_phys implicitly so they can't be used + * directly on kernel symbols (bm_p*d). All the early functions are called too + * early to use lm_alias so __p*d_populate functions must be used to populate + * with the physical address from __pa_symbol. + */ + +static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr, + unsigned long end) +{ + pte_t *pte; + unsigned long next; + pgprot_t kernel_pte = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | + L_PTE_SHARED | L_PTE_DIRTY | + L_PTE_MT_WRITEALLOC); + + if (pmd_none(*pmd)) + __pmd_populate(pmd, __pa_symbol(kasan_zero_pte), + _PAGE_KERNEL_TABLE); + + pte = pte_offset_kernel(pmd, addr); + do { + next = addr + PAGE_SIZE; + cpu_v7_set_pte_ext(pte, pfn_pte(sym_to_pfn(kasan_zero_page), + kernel_pte), + 0); + } while (pte++, addr = next, addr != end && pte_none(*pte)); +} + +static void __init kasan_early_pmd_populate(pud_t *pud, + unsigned long addr, + unsigned long end) +{ + pmd_t *pmd; + unsigned long next; + + if (pud_none(*pud)) + pud_populate(pud, __pa_symbol(kasan_zero_pmd), PMD_TYPE_TABLE); + + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); + kasan_early_pte_populate(pmd, addr, next); + } while (pmd++, addr = next, addr != end && pmd_none(*pmd)); +} + +static void __init kasan_early_pud_populate(pgd_t *pgd, + unsigned long addr, + unsigned long end) +{ + pud_t *pud; + unsigned long next; + + if (pgd_none(*pgd)) + pgd_populate(pgd, __pa_symbol(kasan_zero_pud), PUD_TYPE_TABLE); + + pud = pud_offset(pgd, addr); + do { + next = pud_addr_end(addr, end); + kasan_early_pmd_populate(pud, addr, next); + } while (pud++, addr = next, addr != end && pud_none(*pud)); +} + +static void __init kasan_map_early_shadow(unsigned long start, + unsigned long end) +{ + unsigned long addr = start; + unsigned long next; + pgd_t *pgd; + + pgd = pgd_offset_k(addr); + do { + next = pgd_addr_end(addr, end); + kasan_early_pud_populate(pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + +asmlinkage void __init kasan_early_init(void) +{ + BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); + BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); + kasan_map_early_shadow(KASAN_SHADOW_START, KASAN_SHADOW_END); +} + +static inline pmd_t *pmd_off_k(unsigned long virt) +{ + return pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt); +} + +static void __init clear_pmds(unsigned long start, + unsigned long end) +{ + /* + * Remove references to kasan page tables from + * swapper_pg_dir. pmd_clear() can't be used + * here because it's nop on 2,3-level pagetable setups + */ + for (; start < end; start += PGDIR_SIZE) + pmd_clear(pmd_off_k(start)); +} + +static void kasan_alloc_and_map_shadow(unsigned long start, unsigned long end) +{ + struct map_desc desc; + unsigned long size; + phys_addr_t l_shadow; + + size = (end - start) >> KASAN_SHADOW_SCALE_SHIFT; + l_shadow = memblock_alloc(size, SECTION_SIZE); + WARN(!l_shadow, "%s, reserve %ld shadow memory failed", + __func__, size); + + desc.virtual = (unsigned long)kasan_mem_to_shadow((void *)start); + desc.pfn = __phys_to_pfn(l_shadow); + desc.length = size; + desc.type = MT_MEMORY_RW; + create_mapping(&desc); + pr_info("KASAN shadow, virt:[%lx-%lx], phys:%x, size:%lx\n", + start, end, l_shadow, size); +} + +void __init kasan_init(void) +{ + unsigned long start, end; + int i; + + /* + * We are going to perform proper setup of shadow memory. + * At first we should unmap early shadow (clear_pmds() call bellow). + * However, instrumented code couldn't execute without shadow memory. + * tmp_pg_dir used to keep early shadow mapped until full shadow + * setup will be finished. + */ + memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir)); + dsb(ishst); + cpu_switch_mm(tmp_pg_dir, &init_mm); + clear_pmds(KASAN_SHADOW_START, KASAN_SHADOW_END); + + kasan_alloc_and_map_shadow(PAGE_OFFSET, KMEM_END); + kasan_alloc_and_map_shadow(FIXADDR_START, FIXADDR_END); +#ifdef CONFIG_HIGHMEM + kasan_alloc_and_map_shadow(PKMAP_BASE, + PKMAP_BASE + LAST_PKMAP * PAGE_SIZE); +#endif + + /* + * populate zero page for vmalloc area and other gap area + * TODO: + * Need check kasan for vmalloc? + */ + start = (ulong)kasan_mem_to_shadow((void *)MODULES_VADDR); + kasan_map_early_shadow(KASAN_SHADOW_START, start); + + start = (ulong)kasan_mem_to_shadow((void *)KMEM_END); + end = (ulong)kasan_mem_to_shadow((void *)FIXADDR_START); + kasan_map_early_shadow(start, end); + + /* + * KAsan may reuse the contents of kasan_zero_pte directly, so we + * should make sure that it maps the zero page read-only. + */ + for (i = 0; i < PTRS_PER_PTE; i++) + set_pte_ext(&kasan_zero_pte[i], + pfn_pte(sym_to_pfn(kasan_zero_page), + PAGE_KERNEL_RO), 0); + + memset(kasan_zero_page, 0, PAGE_SIZE); + cpu_switch_mm(swapper_pg_dir, &init_mm); + local_flush_tlb_all(); + flush_cache_all(); + + /* clear all shawdow memory before kasan running */ + memset(kasan_mem_to_shadow((void *)PAGE_OFFSET), 0, + (KMEM_END - PAGE_OFFSET) >> KASAN_SHADOW_SCALE_SHIFT); + memset(kasan_mem_to_shadow((void *)FIXADDR_START), 0, + (FIXADDR_END - FIXADDR_START) >> KASAN_SHADOW_SCALE_SHIFT); +#ifdef CONFIG_HIGHMEM + memset(kasan_mem_to_shadow((void *)PKMAP_BASE), 0, + (LAST_PKMAP * PAGE_SIZE) >> KASAN_SHADOW_SCALE_SHIFT); +#endif + + /* At this point kasan is fully initialized. Enable error messages */ + init_task.kasan_depth = 0; + pr_info("KernelAddressSanitizer initialized\n"); +} diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4d3da37cb798..c7e41d4e11e7 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -37,6 +37,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #include "fault.h" #include "mm.h" @@ -951,7 +954,11 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md, * offsets, and we take full advantage of sections and * supersections. */ +#ifdef CONFIG_AMLOGIC_KASAN32 +void __init create_mapping(struct map_desc *md) +#else static void __init create_mapping(struct map_desc *md) +#endif { if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n", @@ -1121,6 +1128,7 @@ void __init debug_ll_io_init(void) } #endif +#ifndef CONFIG_AMLOGIC_KASAN32 static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); @@ -1149,6 +1157,7 @@ static int __init early_vmalloc(char *arg) return 0; } early_param("vmalloc", early_vmalloc); +#endif phys_addr_t arm_lowmem_limit __initdata = 0; @@ -1166,7 +1175,11 @@ void __init adjust_lowmem_bounds(void) * and may itself be outside the valid range for which phys_addr_t * and therefore __pa() is defined. */ +#ifdef CONFIG_AMLOGIC_KASAN32 + vmalloc_limit = (u64)(KMEM_END - PAGE_OFFSET + PHYS_OFFSET); +#else vmalloc_limit = (u64)(uintptr_t)vmalloc_min - PAGE_OFFSET + PHYS_OFFSET; +#endif for_each_memblock(memory, reg) { phys_addr_t block_start = reg->base; @@ -1244,8 +1257,19 @@ static inline void prepare_page_table(void) /* * Clear out all the mappings below the kernel image. */ +#ifdef CONFIG_AMLOGIC_KASAN32 + for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) { + /* + * keep pre-initialized kasan shadow memory MMU before + * kasan really eanbled + */ + if (addr < KASAN_SHADOW_START || addr >= KASAN_SHADOW_END) + pmd_clear(pmd_off_k(addr)); + } +#else for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); +#endif #ifdef CONFIG_XIP_KERNEL /* The XIP kernel is mapped in the module area -- skip over it */ @@ -1321,8 +1345,16 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) /* * Clear page table except top pmd used by early fixmaps */ +#ifdef CONFIG_AMLOGIC_KASAN32 + /* we have adjusted memory map layout */ + for (addr = VMALLOC_START; + addr < (PAGE_OFFSET & PMD_MASK); + addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); +#else for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); +#endif /* * Map the kernel if it is XIP. @@ -1645,10 +1677,11 @@ void __init paging_init(const struct machine_desc *mdesc) unsigned long notrace phys_check(phys_addr_t x) { unsigned long addr; - struct page *page; addr = x - PHYS_OFFSET + PAGE_OFFSET; +#ifndef CONFIG_AMLOGIC_KASAN32 if (scheduler_running) { + struct page *page; page = phys_to_page(x); /* @@ -1662,16 +1695,19 @@ unsigned long notrace phys_check(phys_addr_t x) dump_stack(); } } +#endif return addr; } EXPORT_SYMBOL(phys_check); unsigned long notrace virt_check(unsigned long x) { +#ifndef CONFIG_AMLOGIC_KASAN32 if (scheduler_running && (x >= VMALLOC_START || x < PAGE_OFFSET)) { pr_err("bad input of virt:%lx\n", x); dump_stack(); } +#endif return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET; } EXPORT_SYMBOL(virt_check); diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile index 59a8fa7b8a3b..fa1c45be6d7b 100644 --- a/arch/arm/vdso/Makefile +++ b/arch/arm/vdso/Makefile @@ -20,6 +20,8 @@ obj-$(CONFIG_VDSO) += vdso.o extra-$(CONFIG_VDSO) += vdso.lds CPPFLAGS_vdso.lds += -P -C -U$(ARCH) +KASAN_SANITIZE_vgettimeofday.o := n + CFLAGS_REMOVE_vdso.o = -pg # Force -O2 to avoid libgcc dependencies diff --git a/drivers/amlogic/memory_ext/Kconfig b/drivers/amlogic/memory_ext/Kconfig index 88856a72327c..f40e0e33025b 100644 --- a/drivers/amlogic/memory_ext/Kconfig +++ b/drivers/amlogic/memory_ext/Kconfig @@ -40,10 +40,23 @@ config AMLOGIC_CMA Amlogic CMA optimization for cma alloc/free problems Including policy change of CMA usage +config AMLOGIC_KASAN32 + bool "Amlogic KASAN support for 32bit kernel" + depends on AMLOGIC_MEMORY_EXTEND + depends on KASAN + depends on !64BIT + default y + help + Amlogic implementation for KASAN on 32bit ARM kernel. + Which can help to debug memory of use-after-free, + out-of-bounds and other problems. This config will + change memory layout. + config AMLOGIC_VMAP bool "Amlogic kernel stack" depends on AMLOGIC_MEMORY_EXTEND depends on !KASAN + depends on !AMLOGIC_KASAN32 default y help This config is used to enable amlogic kernel stack diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 186f267ba87b..d25d99811d44 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -161,6 +161,18 @@ static int __init __reserved_mem_alloc_size(unsigned long node, &prop); #ifdef CONFIG_AMLOGIC_MODIFY + #ifdef CONFIG_AMLOGIC_KASAN32 + { + unsigned long lowmem_size; + + /* fix for cma overlap 2 zone */ + lowmem_size = KMEM_END - PAGE_OFFSET; + lowmem_size += CONFIG_PHYS_OFFSET; + if (start < lowmem_size && end > lowmem_size) { + end = lowmem_size - SZ_4M; + } + } + #endif #ifdef CONFIG_PHYS_ADDR_T_64BIT pr_info("%s, start:%pa, end:%pa, len:%ld MiB\n", __func__, &start, &end, diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index b3293d3807b3..17a4a9c86851 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -423,8 +423,18 @@ void kasan_cache_create(struct kmem_cache *cache, size_t *size, if (redzone_adjust > 0) *size += redzone_adjust; +#ifdef CONFIG_AMLOGIC_KASAN32 /* compile problem */ + { + size_t s1; + + s1 = max(*size, cache->object_size + + optimal_redzone(cache->object_size)); + *size = s1 >= KMALLOC_MAX_SIZE ? KMALLOC_MAX_SIZE : s1; + } +#else *size = min(KMALLOC_MAX_SIZE, max(*size, cache->object_size + optimal_redzone(cache->object_size))); +#endif /* * If the metadata doesn't fit, don't enable KASAN at all. @@ -576,8 +586,13 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object) shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object)); if (shadow_byte < 0 || shadow_byte >= KASAN_SHADOW_SCALE_SIZE) { + #ifdef CONFIG_AMLOGIC_KASAN32 /* for compile problems */ + kasan_report_double_free(cache, object, + __builtin_return_address(0)); + #else kasan_report_double_free(cache, object, __builtin_return_address(1)); + #endif return true; } @@ -739,6 +754,11 @@ static void register_global(struct kasan_global *global) { size_t aligned_size = round_up(global->size, KASAN_SHADOW_SCALE_SIZE); +#ifdef CONFIG_AMLOGIC_KASAN32 + /* avoid FUCKING close source ko panic here */ + if ((unsigned long)global->beg < MODULES_VADDR) + return; +#endif kasan_unpoison_shadow(global->beg, global->size); kasan_poison_shadow(global->beg + aligned_size, From f66b3db2a3283adfc81fcd8ed1778c24f3e1c44d Mon Sep 17 00:00:00 2001 From: Yinming Ding Date: Tue, 16 Apr 2019 17:39:06 +0800 Subject: [PATCH 0427/1060] dvb_core: add SYS_DVBS2 SYS_DVBT2 delsys mode [1/1] PD#SWPL-7017 Problem: TV can't search DVB/S2/T2 Solution: add SYS_DVBS2 SYS_DVBT2 delsys mode Verify: Verified by R314 Change-Id: I30e39d0c236baebc31622fdd5fe1a8fc18209fe0 Signed-off-by: Yinming Ding --- drivers/media/dvb-core/dvb_frontend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index e42024d68152..9869e16c5d5a 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1554,7 +1554,8 @@ static bool is_dvbv3_delsys(u32 delsys) #ifdef CONFIG_AMLOGIC_MODIFY /* added by Amlogic 20180720 */ status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || (delsys == SYS_DVBS) || (delsys == SYS_ATSC) || - (delsys == SYS_DTMB); + (delsys == SYS_DTMB) || (delsys == SYS_DVBS2) || + (delsys == SYS_DVBT2); #else status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || (delsys == SYS_DVBS) || (delsys == SYS_ATSC); From 82745e4bcec5954ff02081ff46d20dd049aee685 Mon Sep 17 00:00:00 2001 From: Huan Biao Date: Wed, 17 Apr 2019 14:57:58 +0800 Subject: [PATCH 0428/1060] thermal: modify ipa parameter for sm1 [1/1] PD#SWPL-7322 Problem: sm1 ipa parameter not match soc power data Solution: update sm1 ipa dts parameter Verify: AC200 Change-Id: Ib636d5c4853d53cf6bafad9b5266e2b13dd7e85c Signed-off-by: Huan Biao --- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 8 ++++---- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 8 ++++---- arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts | 8 ++++---- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 8 ++++---- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 8 ++++---- arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index 37c67a514e00..b946f2c46727 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -820,7 +820,7 @@ cooling_devices { cpufreq_cool_cluster0 { min_state = <1000000>; - dyn_coeff = <115>; + dyn_coeff = <125>; cluster_id = <0>; node_name = "cpufreq_cool0"; device_type = "cpufreq"; @@ -834,7 +834,7 @@ }; gpufreq_cool { min_state = <400>; - dyn_coeff = <358>; + dyn_coeff = <215>; gpu_pp = <2>; cluster_id = <0>; node_name = "gpufreq_cool0"; @@ -867,7 +867,7 @@ soc_thermal: soc_thermal { polling-delay = <1000>; polling-delay-passive = <100>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { @@ -918,7 +918,7 @@ ddr_thermal: ddr_thermal { polling-delay = <2000>; polling-delay-passive = <1000>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 8f0c97315142..0dbf2b0d1d2d 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -820,7 +820,7 @@ cooling_devices { cpufreq_cool_cluster0 { min_state = <1000000>; - dyn_coeff = <115>; + dyn_coeff = <125>; cluster_id = <0>; node_name = "cpufreq_cool0"; device_type = "cpufreq"; @@ -834,7 +834,7 @@ }; gpufreq_cool { min_state = <400>; - dyn_coeff = <358>; + dyn_coeff = <215>; gpu_pp = <2>; cluster_id = <0>; node_name = "gpufreq_cool0"; @@ -867,7 +867,7 @@ soc_thermal: soc_thermal { polling-delay = <1000>; polling-delay-passive = <100>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { @@ -918,7 +918,7 @@ ddr_thermal: ddr_thermal { polling-delay = <2000>; polling-delay-passive = <1000>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts index 8dafc01999e7..5a66538373ee 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -774,7 +774,7 @@ cooling_devices { cpufreq_cool_cluster0 { min_state = <1000000>; - dyn_coeff = <115>; + dyn_coeff = <125>; cluster_id = <0>; node_name = "cpufreq_cool0"; device_type = "cpufreq"; @@ -788,7 +788,7 @@ }; gpufreq_cool { min_state = <400>; - dyn_coeff = <358>; + dyn_coeff = <215>; gpu_pp = <2>; cluster_id = <0>; node_name = "gpufreq_cool0"; @@ -821,7 +821,7 @@ soc_thermal: soc_thermal { polling-delay = <1000>; polling-delay-passive = <100>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { @@ -872,7 +872,7 @@ ddr_thermal: ddr_thermal { polling-delay = <2000>; polling-delay-passive = <1000>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 4497e9e982a1..86b4482d0a2d 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -834,7 +834,7 @@ cooling_devices { cpufreq_cool_cluster0 { min_state = <1000000>; - dyn_coeff = <115>; + dyn_coeff = <125>; cluster_id = <0>; node_name = "cpufreq_cool0"; device_type = "cpufreq"; @@ -848,7 +848,7 @@ }; gpufreq_cool { min_state = <400>; - dyn_coeff = <358>; + dyn_coeff = <215>; gpu_pp = <2>; cluster_id = <0>; node_name = "gpufreq_cool0"; @@ -881,7 +881,7 @@ soc_thermal: soc_thermal { polling-delay = <1000>; polling-delay-passive = <100>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { @@ -932,7 +932,7 @@ ddr_thermal: ddr_thermal { polling-delay = <2000>; polling-delay-passive = <1000>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index 679292791fb4..f25c4a4a754a 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -833,7 +833,7 @@ cooling_devices { cpufreq_cool_cluster0 { min_state = <1000000>; - dyn_coeff = <115>; + dyn_coeff = <125>; cluster_id = <0>; node_name = "cpufreq_cool0"; device_type = "cpufreq"; @@ -847,7 +847,7 @@ }; gpufreq_cool { min_state = <400>; - dyn_coeff = <358>; + dyn_coeff = <215>; gpu_pp = <2>; cluster_id = <0>; node_name = "gpufreq_cool0"; @@ -880,7 +880,7 @@ soc_thermal: soc_thermal { polling-delay = <1000>; polling-delay-passive = <100>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { @@ -931,7 +931,7 @@ ddr_thermal: ddr_thermal { polling-delay = <2000>; polling-delay-passive = <1000>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts index 681f0cf32f54..8966f469daea 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -815,7 +815,7 @@ cooling_devices { cpufreq_cool_cluster0 { min_state = <1000000>; - dyn_coeff = <115>; + dyn_coeff = <125>; cluster_id = <0>; node_name = "cpufreq_cool0"; device_type = "cpufreq"; @@ -829,7 +829,7 @@ }; gpufreq_cool { min_state = <400>; - dyn_coeff = <358>; + dyn_coeff = <215>; gpu_pp = <2>; cluster_id = <0>; node_name = "gpufreq_cool0"; @@ -862,7 +862,7 @@ soc_thermal: soc_thermal { polling-delay = <1000>; polling-delay-passive = <100>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { @@ -913,7 +913,7 @@ ddr_thermal: ddr_thermal { polling-delay = <2000>; polling-delay-passive = <1000>; - sustainable-power = <1460>; + sustainable-power = <1410>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { From 3fa8182617ee72631478cb128d9bc78faf765f44 Mon Sep 17 00:00:00 2001 From: Yan Wang Date: Wed, 10 Apr 2019 17:34:48 +0800 Subject: [PATCH 0429/1060] idle: sm1: enable sm1 idle function [1/1] PD#SWPL-6255 Problem: sm1 need enable idle for power. Solution: enable sm1 idle function. Verify: ac200 Change-Id: Ib106ac552660471f0275dc22374405939d521a62 Signed-off-by: Yan Wang --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 12 ++++++------ arch/arm/kernel/sleep.S | 5 +++++ arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 12 ++++++------ arch/arm64/kernel/sleep.S | 8 ++++++++ 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 0367819aab61..debf56856b83 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -55,7 +55,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -73,7 +73,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x1>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -91,7 +91,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x2>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -109,7 +109,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x3>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -128,9 +128,9 @@ compatible = "arm,idle-state"; arm,psci-suspend-param = <0x0010000>; local-timer-stop; - entry-latency-us = <5000>; + entry-latency-us = <4000>; exit-latency-us = <5000>; - min-residency-us = <15000>; + min-residency-us = <10000>; }; }; }; diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 0f6c1000582c..dd52f5c182e4 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -136,7 +136,12 @@ ARM_BE8(setend be) @ ensure we are in BE mode safe_svcmode_maskall r1 mov r1, #0 ALT_SMP(mrc p15, 0, r0, c0, c0, 5) + ALT_SMP(and r2, r0, #1<<24) + ALT_SMP(cmp r2, #0) + ALT_SMP(beq 2f) + ALT_SMP(lsr r0, r0, #8) ALT_UP_B(1f) +2: adr r2, mpidr_hash_ptr ldr r3, [r2] add r2, r2, r3 @ r2 = struct mpidr_hash phys address diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index eb747a6fd874..6baae096db75 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -55,7 +55,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -73,7 +73,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -91,7 +91,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x2>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -109,7 +109,7 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x3>; enable-method = "psci"; -// cpu-idle-states = <&CPU_SLEEP_0>; + cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, <&clkc CLKID_SYS_PLL>; @@ -128,9 +128,9 @@ compatible = "arm,idle-state"; arm,psci-suspend-param = <0x0010000>; local-timer-stop; - entry-latency-us = <5000>; + entry-latency-us = <4000>; exit-latency-us = <5000>; - min-residency-us = <15000>; + min-residency-us = <10000>; }; }; }; diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index 5a4fbcc744d2..32a9754a884d 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -75,6 +75,10 @@ ENTRY(__cpu_suspend_enter) /* find the mpidr_hash */ ldr_l x1, sleep_save_stash mrs x7, mpidr_el1 + ubfx x2, x7, #24, 1 + cbz x2, __cpu_suspend_enter_cont + lsr x7, x7, #8 +__cpu_suspend_enter_cont: adr_l x9, mpidr_hash ldr x10, [x9, #MPIDR_HASH_MASK] /* @@ -109,6 +113,10 @@ ENDPROC(cpu_resume) ENTRY(_cpu_resume) mrs x1, mpidr_el1 + ubfx x2, x1, #24, 1 + cbz x2, _cpu_resume_cont + lsr x1, x1, #8 +_cpu_resume_cont: adr_l x8, mpidr_hash // x8 = struct mpidr_hash virt address /* retrieve mpidr_hash members to compute the hash */ From db9130af26f5f957900744e7e29187456efe2062 Mon Sep 17 00:00:00 2001 From: "qiyao.zhou" Date: Mon, 15 Apr 2019 17:25:03 +0800 Subject: [PATCH 0430/1060] dts: flanklin bring up based on google-ref! [1/2] PD#SWPL-7184 Problem: flanklin bring up based on google-ref. Solution: Modify copy file for franklin. Verify: verify it on franklin. Change-Id: Ibaba2dcb7a3e8715243f5a93d69a1bf96e8c49a7 Signed-off-by: qiyao.zhou --- .../arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 97 +++++++++++-------- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 97 +++++++++++-------- .../boot/dts/amlogic/g12a_s905x2_u212.dts | 97 +++++++++++-------- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 97 +++++++++++-------- 4 files changed, 224 insertions(+), 164 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index c9947b73297e..a3be7d987147 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -163,17 +163,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -319,43 +319,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -843,7 +847,7 @@ */ &i2c3 { - status = "disabled"; + status = "ok"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -1399,3 +1403,14 @@ status = "okay"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index f40d1519d6f6..4c999c359391 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -168,17 +168,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -317,43 +317,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -839,7 +843,7 @@ */ &i2c3 { - status = "disabled"; + status = "okay"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -1389,3 +1393,14 @@ &saradc { status = "disabled"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index 69a83e54ebfd..8530a386ab17 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -163,17 +163,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -319,43 +319,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -843,7 +847,7 @@ */ &i2c3 { - status = "disabled"; + status = "ok"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -1399,3 +1403,14 @@ status = "okay"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index d10de9e4196f..652dc1895682 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -164,17 +164,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -313,43 +313,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -835,7 +839,7 @@ */ &i2c3 { - status = "disabled"; + status = "okay"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -1385,3 +1389,14 @@ &saradc { status = "disabled"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; From 43e2e7cdef16b25b255e525148a267c0ddc4c42a Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 16 Apr 2019 11:33:04 +0800 Subject: [PATCH 0431/1060] osd: fix afbc decoder error caused flicker in display [1/1] PD#OTT-3000 Problem: afbc decoder error caused flicker in display. Solution: close osd prefetch. Verify: Verified with raven Change-Id: I44356c028b41e251f7a98b5e931b2cbd583b0829 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 471ea826b5b7..decd51d35cdc 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -4920,8 +4920,10 @@ static void osd_update_enable(u32 index) notify_to_amvideo(); VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC, temp_val); } - VSYNCOSD_CLR_MPEG_REG_MASK( - osd_reg->osd_ctrl_stat, 1 << 0); + if (!(osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B)) + VSYNCOSD_CLR_MPEG_REG_MASK( + osd_reg->osd_ctrl_stat, 1 << 0); } if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) { if ((osd_hw.osd_afbcd[index].enable == ENABLE) @@ -8534,13 +8536,11 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_reg_set_bits( hw_osd_reg_array[idx].osd_fifo_ctrl_stat, 1, 10, 2); - /* TODO: temp set at here, - * need check for logo - */ - if (idx > 0) - osd_reg_set_bits( - hw_osd_reg_array[idx].osd_ctrl_stat, - 0, 0, 1); + if (osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B) + osd_reg_set_bits + (hw_osd_reg_array[idx].osd_ctrl_stat, + 1, 0, 1); osd_reg_set_bits( hw_osd_reg_array[idx].osd_ctrl_stat, 0, 31, 1); From ea6864560ee3a73421e0e40857bfe89f8cb71d3f Mon Sep 17 00:00:00 2001 From: peter wang Date: Fri, 12 Apr 2019 13:49:21 +0800 Subject: [PATCH 0432/1060] amvideo: fix video block when pts discontinue [1/1] PD#SWPL-5038 Problem: image will block when pts discontinue Solution: do not show the frame when pts greater than pcr Verify: tested on Marconi Change-Id: I57ea973b7fdcdc7cded2c5c9b681be29f0a31a4b Signed-off-by: peter wang --- drivers/amlogic/media/video_sink/video.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index d208cc2fa7e3..d6d3f0c4623d 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -108,6 +108,8 @@ static int video_global_output = 1; /* video_pause_global: 0 is play, 1 is pause, 2 is invalid */ static int video_pause_global = 1; +static u32 cur_omx_index; + #ifdef CONFIG_GE2D_KEEP_FRAME /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ /* #include */ @@ -5378,11 +5380,13 @@ static inline bool vpts_expire(struct vframe_s *cur_vf, /* pts==0 is a keep frame maybe. */ if (systime > next_vf->pts || next_vf->pts == 0) return true; - if (omx_secret_mode == true) + if (omx_secret_mode == true + && cur_omx_index >= next_vf->omx_index) return true; return false; - } else if (omx_secret_mode == true) + } else if (omx_secret_mode == true + && cur_omx_index >= next_vf->omx_index) return true; } else if (omx_run && omx_secret_mode @@ -8853,6 +8857,7 @@ static void set_omx_pts(u32 *p) u32 session = p[5]; unsigned int try_cnt = 0x1000; + cur_omx_index = frame_num; mutex_lock(&omx_mutex); if (omx_pts_set_index < frame_num) omx_pts_set_index = frame_num; From 4ca49b6c65aa2aba9767d882682728e312f59bd4 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Fri, 19 Apr 2019 08:15:47 +0800 Subject: [PATCH 0433/1060] unifikey: fix kasan bug reported in name_store [1/1] PD#SWPL-7326 Problem: slab-out-of-bounds in strlen called by name_store Solution: Make sure the string passed to strlen is always '\0' ended Verify: Locally Change-Id: Ifd78a100c0e34ff9afb527ebe7b044ceb5c3505e Signed-off-by: Jiamin Ma --- drivers/amlogic/unifykey/unifykey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/unifykey/unifykey.c b/drivers/amlogic/unifykey/unifykey.c index c1e35246b168..d2a9fadbcd60 100644 --- a/drivers/amlogic/unifykey/unifykey.c +++ b/drivers/amlogic/unifykey/unifykey.c @@ -1277,7 +1277,7 @@ static ssize_t name_store(struct class *cla, } key_cnt = unifykey_count_key(&(ukdev->uk_header)); - name = kzalloc(count, GFP_KERNEL); + name = kzalloc(count + 1, GFP_KERNEL); if (!name) { pr_err("can't kzalloc mem,%s:%d\n", __func__, From 1a81c3d07634e0f4854bed233af86caa7fe2ff96 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Thu, 11 Apr 2019 23:03:27 -0400 Subject: [PATCH 0434/1060] amvecm: match uboot sdr2hdr function [1/1] PD#OTT-2524 Problem: enable sdr2hdr function, uboot logo have color change Solution: match uboot sdr2hdr function Verify: verify on G12A Change-Id: I160cd6141d09a385d299ca96a89eb1ebf09c86e8 Signed-off-by: MingLiang Dong --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 75d0fd1f7e3f..69bc6a6c0821 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -61,6 +61,7 @@ #include "vlock.h" #include "hdr/am_hdr10_plus.h" #include "local_contrast.h" +#include "arch/vpp_hdr_regs.h" #define pr_amvecm_dbg(fmt, args...)\ do {\ @@ -6192,6 +6193,12 @@ free_buf: return -EINVAL; } +static void def_hdr_sdr_mode(void) +{ + if (((READ_VPP_REG(VD1_HDR2_CTRL) >> 13) & 0x1) && + ((READ_VPP_REG(OSD1_HDR2_CTRL) >> 13) & 0x1)) + sdr_mode = 2; +} /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ void init_pq_setting(void) @@ -6220,6 +6227,9 @@ void init_pq_setting(void) 0x4000); WRITE_VPP_REG(SRSHARP0_SHARP_SR2_CBIC_VCOEF0 + sr_offset[0], 0x4000); + + /*kernel sdr2hdr match uboot setting*/ + def_hdr_sdr_mode(); } return; From f458721991d6f4d5bec3b169c50a00e1cde773a5 Mon Sep 17 00:00:00 2001 From: Yingyuan Zhu Date: Wed, 10 Apr 2019 15:26:32 +0800 Subject: [PATCH 0435/1060] watchdog: fix watchdog get lefttime error [1/1] PD#SWPL-6937 Problem: 1.get lefttime error by 'cat sys/class/watchdog/watchdog0/timeleft' cmd. 2.if DTS is configured to feed watchdog by Android, the system will restart automatically after wake up. Solution: 1.modify the code to get time. 2.when the system wakes up, first judge whether the watchdog runs, and then decide whether to start the watchdog. Verify: test pass on u200 Change-Id: If64888ffdd5651e8cfcace5ea0d0da31641bb397 Signed-off-by: Yingyuan Zhu --- drivers/amlogic/watchdog/meson_wdt.c | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/amlogic/watchdog/meson_wdt.c b/drivers/amlogic/watchdog/meson_wdt.c index 4da2517889a2..bb48362118d2 100644 --- a/drivers/amlogic/watchdog/meson_wdt.c +++ b/drivers/amlogic/watchdog/meson_wdt.c @@ -54,6 +54,7 @@ struct aml_wdt_dev { void __iomem *reg_base; struct notifier_block pm_notifier; struct notifier_block reboot_notifier; + bool is_running; /* 1:enable 0:disable */ }; static void aml_update_bits(void __iomem *reg, unsigned int mask, @@ -108,7 +109,9 @@ static int aml_wdt_start(struct watchdog_device *wdog) if (wdev->boot_queue) cancel_delayed_work(&wdev->boot_queue); #endif + wdev->is_running = true; dev_info(wdev->dev, "start watchdog\n"); + return 0; } @@ -119,6 +122,7 @@ static int aml_wdt_stop(struct watchdog_device *wdog) mutex_lock(&wdev->lock); disable_watchdog(wdev); mutex_unlock(&wdev->lock); + wdev->is_running = false; dev_info(wdev->dev, "stop watchdog\n"); return 0; @@ -153,12 +157,14 @@ static int aml_wdt_set_timeout(struct watchdog_device *wdog, unsigned int aml_wdt_get_timeleft(struct watchdog_device *wdog) { struct aml_wdt_dev *wdev = watchdog_get_drvdata(wdog); - unsigned int timeleft; + unsigned long timeleft, tick; mutex_lock(&wdev->lock); timeleft = read_watchdog_tcnt(wdev); + tick = readl(wdev->reg_base + TCNT) & 0xffff; mutex_unlock(&wdev->lock); - return timeleft/wdev->one_second; + + return (tick - timeleft)/wdev->one_second; } static void boot_moniter_work(struct work_struct *work) @@ -255,14 +261,18 @@ static int aml_wtd_pm_notify(struct notifier_block *nb, unsigned long event, wdev = container_of(nb, struct aml_wdt_dev, pm_notifier); if (event == PM_SUSPEND_PREPARE) { - disable_watchdog(wdev); - dev_info(wdev->dev, - "pm_notify: disable watchdog, event = %lu\n", event); + if (wdev->is_running) { + disable_watchdog(wdev); + dev_info(wdev->dev, + "pm_notify: disable watchdog, event = %lu\n", event); + } } if (event == PM_POST_SUSPEND) { - enable_watchdog(wdev); - dev_info(wdev->dev, - "pm_notify: enable watchdog, event = %lu\n", event); + if (wdev->is_running) { + enable_watchdog(wdev); + dev_info(wdev->dev, + "pm_notify: enable watchdog, event = %lu\n", event); + } } return NOTIFY_OK; } @@ -338,14 +348,13 @@ static int aml_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(aml_wdt, wdev); platform_set_drvdata(pdev, aml_wdt); + wdev->is_running = false; if (wdev->reset_watchdog_method == 1) { INIT_DELAYED_WORK(&wdev->boot_queue, boot_moniter_work); mod_delayed_work(system_freezable_wq, &wdev->boot_queue, round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000))); - enable_watchdog(wdev); - set_watchdog_cnt(wdev, - wdev->default_timeout * wdev->one_second); + aml_wdt_start(aml_wdt); dev_info(wdev->dev, "creat work queue for watch dog\n"); } ret = watchdog_register_device(aml_wdt); From 6ad192c3c82849d532ae9bd771e0162608ca91b1 Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Thu, 7 Mar 2019 16:12:38 +0800 Subject: [PATCH 0436/1060] hdr_prime: add interface of HDR Prime SL driver [1/1] PD#SWPL-5475 Problem: need to add interface of HDR Prime SL driver Solution: add interface of HDR Prime SL driver Verify: U212 Change-Id: If0e62b74ccbaa4ede490e7a9896d9f5915480d6f Signed-off-by: Yi Zhou --- MAINTAINERS | 6 + arch/arm/boot/dts/amlogic/mesong12a.dtsi | 6 + arch/arm/boot/dts/amlogic/mesong12b.dtsi | 6 + arch/arm/configs/meson64_a32_defconfig | 1 + .../configs/meson64_a32_smarthome_defconfig | 1 + arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 6 + arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 6 + arch/arm64/configs/meson64_defconfig | 1 + .../arm64/configs/meson64_smarthome_defconfig | 1 + drivers/amlogic/media/enhancement/Kconfig | 1 + drivers/amlogic/media/enhancement/Makefile | 5 +- .../media/enhancement/amprime_sl/Kconfig | 15 + .../media/enhancement/amprime_sl/Makefile | 7 + .../media/enhancement/amprime_sl/amprime_sl.c | 511 ++++++++++++++++++ .../media/enhancement/amprime_sl/amprime_sl.h | 391 ++++++++++++++ .../enhancement/amprime_sl/amprime_sl_hw.c | 289 ++++++++++ .../linux/amlogic/media/amprime_sl/prime_sl.h | 26 + 17 files changed, 1277 insertions(+), 2 deletions(-) create mode 100644 drivers/amlogic/media/enhancement/amprime_sl/Kconfig create mode 100644 drivers/amlogic/media/enhancement/amprime_sl/Makefile create mode 100644 drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c create mode 100644 drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h create mode 100644 drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c create mode 100644 include/linux/amlogic/media/amprime_sl/prime_sl.h diff --git a/MAINTAINERS b/MAINTAINERS index 82e99de98a39..d8afba63c32c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13927,6 +13927,7 @@ F: drivers/amlogic/media/enhancement/amvecm/arch/* F: drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/* F: include/linux/amlogic/media/amvecm/* F: drivers/amlogic/media/enhancement/amvecm/hdr/* +F: drivers/amlogic/media/enhancement/amvecm/amprime_sl/* AMLOGIC GXL ADD SKT DTS M: Yun Cai @@ -14442,6 +14443,11 @@ M: Zhilei Wu F: drivers/amlogic/media/enhancement/amdolby_vision* F: include/linux/amlogic/media/amdolbyvision/* +AMLOGIC HDR PRIMSE SL DRIVER +M: Yi Zhou +F: drivers/amlogic/media/enhancement/amprime_sl/* +F: include/linux/amlogic/media/amprime_sl/* + AMLOGIC G12A Media codec io bus M: Nanxin Qin F: include/linux/amlogic/media/registers/regs/efuse_regs.h diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index f2b8e93da485..e62cb5cb1c87 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1082,6 +1082,12 @@ }; }; + amprime_sl:amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + aocec: aocec { compatible = "amlogic, aocec-g12a"; device_name = "aocec"; diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 44bef6d1e05b..9fcd30a3acb8 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1160,6 +1160,12 @@ }; }; + amprime_sl:amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + galcore { compatible = "amlogic, galcore"; dev_name = "galcore"; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 2e1cef27d18a..326ec6d8ed19 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -328,6 +328,7 @@ CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y CONFIG_AMLOGIC_VIDEO_CAPTURE=y CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y diff --git a/arch/arm/configs/meson64_a32_smarthome_defconfig b/arch/arm/configs/meson64_a32_smarthome_defconfig index 3efa96011b19..d7d9c56f2164 100644 --- a/arch/arm/configs/meson64_a32_smarthome_defconfig +++ b/arch/arm/configs/meson64_a32_smarthome_defconfig @@ -294,6 +294,7 @@ CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y CONFIG_AMLOGIC_VRTC=y diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 4e0f399d6005..46c3f1879bdd 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -1092,6 +1092,12 @@ }; }; + amprime_sl: amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + aocec: aocec { compatible = "amlogic, aocec-g12a"; device_name = "aocec"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index f3f561f582ae..ef5c20957035 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1170,6 +1170,12 @@ }; }; + amprime_sl: amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + galcore { compatible = "amlogic, galcore"; dev_name = "galcore"; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index fac7f2d7fbee..62100c08089c 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -322,6 +322,7 @@ CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y CONFIG_AMLOGIC_VIDEO_CAPTURE=y CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y diff --git a/arch/arm64/configs/meson64_smarthome_defconfig b/arch/arm64/configs/meson64_smarthome_defconfig index 4434cfd8a44c..171ceffa64d1 100644 --- a/arch/arm64/configs/meson64_smarthome_defconfig +++ b/arch/arm64/configs/meson64_smarthome_defconfig @@ -284,6 +284,7 @@ CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y CONFIG_AMLOGIC_VRTC=y diff --git a/drivers/amlogic/media/enhancement/Kconfig b/drivers/amlogic/media/enhancement/Kconfig index d4c423730f77..9d1075b220ef 100644 --- a/drivers/amlogic/media/enhancement/Kconfig +++ b/drivers/amlogic/media/enhancement/Kconfig @@ -12,6 +12,7 @@ config AMLOGIC_MEDIA_ENHANCEMENT if AMLOGIC_MEDIA_ENHANCEMENT source "drivers/amlogic/media/enhancement/amvecm/Kconfig" source "drivers/amlogic/media/enhancement/amdolby_vision/Kconfig" +source "drivers/amlogic/media/enhancement/amprime_sl/Kconfig" endif endmenu diff --git a/drivers/amlogic/media/enhancement/Makefile b/drivers/amlogic/media/enhancement/Makefile index b5e365f74498..5a53ee3ae57e 100644 --- a/drivers/amlogic/media/enhancement/Makefile +++ b/drivers/amlogic/media/enhancement/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += amvecm/ -obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) += amdolby_vision/ \ No newline at end of file +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += amvecm/ +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) += amdolby_vision/ +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL) += amprime_sl/ diff --git a/drivers/amlogic/media/enhancement/amprime_sl/Kconfig b/drivers/amlogic/media/enhancement/amprime_sl/Kconfig new file mode 100644 index 000000000000..10dc1798f776 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/Kconfig @@ -0,0 +1,15 @@ +# +# AMLOGIC amprime_sl devices configuration +# + +comment "Amlogic amprime_sl Drivers" + +menu "Amlogic amprime_sl Driver" + +config AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL + bool "Amlogic amprime_sl driver" + default n + help + "Amlogic amprime_sl module init" + +endmenu diff --git a/drivers/amlogic/media/enhancement/amprime_sl/Makefile b/drivers/amlogic/media/enhancement/amprime_sl/Makefile new file mode 100644 index 000000000000..97fbaf30c14c --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for amprime_sl +# + +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL) += amprime_sl.o amprime_sl_hw.o + + diff --git a/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c new file mode 100644 index 000000000000..79ebfc71fce3 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c @@ -0,0 +1,511 @@ +/* + * drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "amprime_sl.h" +#include +#include + +/*======================================*/ + +static const struct hdr_prime_sl_func_s *p_funcs; +struct prime_sl_device_data_s prime_sl_meson_dev; +#define AMPRIME_SL_NAME "amprime_sl" +#define AMPRIME_SL_CLASS_NAME "amprime_sl" + +struct amprime_sl_dev_s { + dev_t devt; + struct cdev cdev; + dev_t devno; + struct device *dev; + struct class *clsp; +}; +static struct amprime_sl_dev_s amprime_sl_dev; +static struct prime_t prime_sl_setting; + +static uint prime_sl_enable = DISABLE; +module_param(prime_sl_enable, uint, 0664); +MODULE_PARM_DESC(prime_sl_enable, "\n prime_sl_enable\n"); + +static uint prime_sl_display_Brightness = 150; +module_param(prime_sl_display_Brightness, uint, 0664); +MODULE_PARM_DESC(prime_sl_display_Brightness, "\n prime_sl_display_Brightness\n"); + +bool is_prime_sl_enable(void) +{ + return prime_sl_enable; +} +EXPORT_SYMBOL(is_prime_sl_enable); + +static int parse_para(char *p) +{ + int data; + + data = cpu_to_le32((unsigned int)(*p)); + *p += 4; + return data; +} + +static int prime_sl_parse_sei_and_meta(char *p, unsigned int size) +{ + unsigned int i; + struct sl_hdr_metadata *sl_hdr_metadata + = &prime_sl_setting.prime_metadata; + + if (size != sizeof(struct sl_hdr_metadata)) { + pr_info("error metadata size\n"); + return 0; + } + + sl_hdr_metadata->partID = parse_para(p); + sl_hdr_metadata->majorSpecVersionID = parse_para(p); + sl_hdr_metadata->minorSpecVersionID = parse_para(p); + sl_hdr_metadata->payloadMode = parse_para(p); + sl_hdr_metadata->hdrPicColourSpace = parse_para(p); + sl_hdr_metadata->hdrDisplayColourSpace = parse_para(p); + sl_hdr_metadata->hdrDisplayMaxLuminance = parse_para(p); + sl_hdr_metadata->hdrDisplayMinLuminance = parse_para(p); + sl_hdr_metadata->sdrPicColourSpace = parse_para(p); + sl_hdr_metadata->sdrDisplayColourSpace = parse_para(p); + sl_hdr_metadata->sdrDisplayMaxLuminance = parse_para(p); + sl_hdr_metadata->sdrDisplayMinLuminance = parse_para(p); + for (i = 0; i < 4; i++) + sl_hdr_metadata->matrixCoefficient[i] = parse_para(p); + for (i = 0; i < 2; i++) + sl_hdr_metadata->chromaToLumaInjection[i] = parse_para(p); + for (i = 0; i < 3; i++) + sl_hdr_metadata->kCoefficient[i] = parse_para(p); + if (!sl_hdr_metadata->payloadMode) { + sl_hdr_metadata->u.variables.tmInputSignalBlackLevelOffset + = parse_para(p); + sl_hdr_metadata->u.variables.tmInputSignalWhiteLevelOffset + = parse_para(p); + sl_hdr_metadata->u.variables.shadowGain = parse_para(p); + sl_hdr_metadata->u.variables.highlightGain = parse_para(p); + sl_hdr_metadata->u.variables.midToneWidthAdjFactor + = parse_para(p); + sl_hdr_metadata->u.variables.tmOutputFineTuningNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.variables.tmOutputFineTuningNumVal; i++) { + sl_hdr_metadata->u.variables.tmOutputFineTuningX[i] + = parse_para(p); + sl_hdr_metadata->u.variables.tmOutputFineTuningX[i] + = parse_para(p); + } + sl_hdr_metadata->u.variables.saturationGainNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.variables.saturationGainNumVal; i++) { + sl_hdr_metadata->u.variables.saturationGainX[i] + = parse_para(p); + sl_hdr_metadata->u.variables.saturationGainY[i] + = parse_para(p); + } + } else { + sl_hdr_metadata->u.tables.luminanceMappingNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.tables.luminanceMappingNumVal; i++) { + sl_hdr_metadata->u.tables.luminanceMappingX[i] + = parse_para(p); + sl_hdr_metadata->u.tables.luminanceMappingY[i] + = parse_para(p); + } + sl_hdr_metadata->u.tables.colourCorrectionNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.tables.colourCorrectionNumVal; i++) { + sl_hdr_metadata->u.tables.colourCorrectionX[i] + = parse_para(p); + sl_hdr_metadata->u.tables.colourCorrectionY[i] + = parse_para(p); + } + } + return 0; +} + +static void prime_sl_parser_metadata(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + struct prime_cfg_t *Cfg = &prime_sl_setting.Cfg; + char *p; + unsigned int size = 0; + unsigned int type = 0; + + if (vf && (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS)) { + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + req.low_latency = 0; + + Cfg->width = (vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width; + Cfg->height = (vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height; + Cfg->bit_depth = vf->bitdepth; + Cfg->yuv_range = (vf->signal_type >> 25) & 0x1; + Cfg->display_Brightness = prime_sl_display_Brightness; + + vf_notify_provider_by_name("prime_sl_dec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + + if (req.aux_buf && req.aux_size) { + p = req.aux_buf; + while (p < req.aux_buf + + req.aux_size - 8) { + size = cpu_to_le32((unsigned int)(*p)); + p += 4; + type = cpu_to_le32((unsigned int)(*p)); + p += 4; + if (type == 0x04000000)/*need to double check*/ + prime_sl_parse_sei_and_meta(p, size); + p += size; + } + } + } +} + +void prime_sl_process(struct vframe_s *vf) +{ + prime_sl_parser_metadata(vf); + if (!p_funcs) + p_funcs->prime_metadata_parser_process(&prime_sl_setting); + prime_sl_set_reg(&prime_sl_setting.prime_sl); + prime_sl_close(); +} +EXPORT_SYMBOL(prime_sl_process); + +static void dbg_setting(struct prime_sl_t *prime_sl) +{ + unsigned int i; + + pr_info("%s\n", __func__); + pr_info("\t legacy_mode_en\t%d\n", prime_sl->legacy_mode_en); + pr_info("\t clip_en\t%d\n", prime_sl->clip_en); + pr_info("\t reg_gclk_ctrl\t%d\n", prime_sl->reg_gclk_ctrl); + pr_info("\t gclk_ctrl\t%d\n", prime_sl->gclk_ctrl); + pr_info("\t primesl_en\t%d\n", + prime_sl->primesl_en); + pr_info("\t inv_chroma_ratio\t%d\n", + prime_sl->inv_chroma_ratio); + pr_info("\t inv_y_ratio\t%d\n", prime_sl->inv_y_ratio); + pr_info("\t l_headroom\t%d\n", prime_sl->l_headroom); + pr_info("\t footroom\t%d\n", prime_sl->footroom); + pr_info("\t c_headroom\t%d\n", prime_sl->c_headroom); + pr_info("\t mub\t%d\n", + prime_sl->mub); + pr_info("\t mua\t%d\n", prime_sl->mua); + + for (i = 0; i < 7; i++) + pr_info("\t oct[%d]\t%d\n", i, prime_sl->oct[i]); + for (i = 0; i < 3; i++) + pr_info("\t d_lut_threshold[%d]\t%d\n", i, + prime_sl->d_lut_threshold[i]); + for (i = 0; i < 4; i++) + pr_info("\t d_lut_step[%d]\t%d\n", i, prime_sl->d_lut_step[i]); + for (i = 0; i < 9; i++) + pr_info("\t rgb2yuv[%d]\t%d\n", i, prime_sl->rgb2yuv[i]); + for (i = 0; i < 65; i++) + pr_info("\t lut_c[%d]\t%d\n", i, prime_sl->lut_c[i]); + for (i = 0; i < 65; i++) + pr_info("\t lut_p[%d]\t%d\n", i, prime_sl->lut_p[i]); + for (i = 0; i < 65; i++) + pr_info("\t lut_d[%d]\t%d\n", i, prime_sl->lut_d[i]); +} + +static void dbg_config(struct prime_cfg_t *Cfg) +{ + pr_info("%s\n", __func__); + + pr_info("\t width\t%d\n", Cfg->width); + pr_info("\t height\t%d\n", Cfg->height); + pr_info("\t bit_depth\t%d\n", Cfg->bit_depth); + pr_info("\t display_OETF\t%d\n", Cfg->display_OETF); + pr_info("\t display_Brightness\t%d\n", + Cfg->display_Brightness); + pr_info("\t yuv_range\t%d\n", Cfg->yuv_range); +} + +static void dbg_metadata(struct sl_hdr_metadata *pmetadata) +{ + pr_info("%s\n", __func__); + + pr_info("\t partID\t%d\n", pmetadata->partID); + pr_info("\t majorSpecVersionID\t%d\n", + pmetadata->majorSpecVersionID); + pr_info("\t minorSpecVersionID\t%d\n", + pmetadata->minorSpecVersionID); + pr_info("\t payloadMode\t%d\n", + pmetadata->payloadMode); + pr_info("\t hdrPicColourSpace\t%d\n", + pmetadata->hdrPicColourSpace); + pr_info("\t hdrDisplayColourSpace\t%d\n", + pmetadata->hdrDisplayColourSpace); + pr_info("\t hdrDisplayMaxLuminance\t%d\n", + pmetadata->hdrDisplayMaxLuminance); + + pr_info("\t hdrDisplayMinLuminance\t%d\n", + pmetadata->hdrDisplayMinLuminance); + pr_info("\t sdrPicColourSpace\t%d\n", + pmetadata->sdrPicColourSpace); + pr_info("\t sdrDisplayColourSpace\t%d\n", + pmetadata->sdrDisplayColourSpace); + pr_info("\t sdrDisplayMaxLuminance\t%d\n", + pmetadata->sdrDisplayMaxLuminance); + pr_info("\t sdrDisplayMinLuminance\t%d\n", + pmetadata->sdrDisplayMinLuminance); + +} + +static ssize_t amprime_sl_debug_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + + if (!buf) + return count; + + if (!strcmp(buf, "metadata")) { + dbg_metadata(&prime_sl_setting.prime_metadata); + dbg_config(&prime_sl_setting.Cfg); + } else if (!strcmp(buf, "setting")) + dbg_setting(&prime_sl_setting.prime_sl); + else + pr_info("unsupport commands\n"); + return count; + +} + +static struct class_attribute amprime_sl_class_attrs[] = { + __ATTR(debug, 0644, NULL, amprime_sl_debug_store), + __ATTR_NULL +}; + + +int register_prime_functions(const struct hdr_prime_sl_func_s *func) +{ + int ret = -1; + + if (!p_funcs && func) { + pr_info("*** register_prime_functions. version %s ***\n", + func->version_info); + ret = 0; + p_funcs = func; + p_funcs->prime_api_init(); + } + return ret; +} +EXPORT_SYMBOL(register_prime_functions); + +int unregister_prime_functions(void) +{ + int ret = -1; + + if (p_funcs) { + pr_info("*** unregister_prime_functions ***\n"); + p_funcs->prime_api_exit(); + p_funcs = NULL; + ret = 0; + } + return ret; +} +EXPORT_SYMBOL(unregister_prime_functions); + +static struct prime_sl_device_data_s prime_sl_g12 = { + .cpu_id = _CPU_MAJOR_ID_G12, +}; + +static struct prime_sl_device_data_s prime_sl_tl1 = { + .cpu_id = _CPU_MAJOR_ID_TL1, +}; + +static const struct of_device_id amprime_sl_match[] = { + { + .compatible = "amlogic, prime_sl_g12", + .data = &prime_sl_g12, + }, + { + .compatible = "amlogic, prime_sl_tl1", + .data = &prime_sl_tl1, + }, + {}, +}; + +static int amprime_sl_probe(struct platform_device *pdev) +{ + int ret = 0; + unsigned int i = 0; + struct amprime_sl_dev_s *devp = &rime_sl_dev; + + pr_info("amprime_sl probe start & ver: %s\n", DRIVER_VER); + if (pdev->dev.of_node) { + const struct of_device_id *match; + struct prime_sl_device_data_s *prime_sl_meson; + struct device_node *of_node = pdev->dev.of_node; + + match = of_match_node(amprime_sl_match, of_node); + if (match) { + prime_sl_meson = + (struct prime_sl_device_data_s *)match->data; + if (prime_sl_meson) + memcpy(&rime_sl_dev, prime_sl_meson, + sizeof(struct prime_sl_device_data_s)); + else { + pr_err("%s data NOT match\n", __func__); + return -ENODEV; + } + } else { + pr_err("%s NOT match\n", __func__); + return -ENODEV; + } + + } + pr_info("\n cpu_id=%d\n", prime_sl_meson_dev.cpu_id); + memset(devp, 0, (sizeof(struct amprime_sl_dev_s))); + ret = alloc_chrdev_region(&devp->devno, 0, 1, AMPRIME_SL_NAME); + if (ret < 0) + goto fail_alloc_region; + devp->clsp = class_create(THIS_MODULE, + AMPRIME_SL_CLASS_NAME); + if (IS_ERR(devp->clsp)) { + ret = PTR_ERR(devp->clsp); + goto fail_create_class; + } + + for (i = 0; amprime_sl_class_attrs[i].attr.name; i++) { + if (class_create_file(devp->clsp, + &rime_sl_class_attrs[i]) < 0) + goto fail_class_create_file; + } +/* cdev_init(&devp->cdev, &rime_sl_fops); + * devp->cdev.owner = THIS_MODULE; + * ret = cdev_add(&devp->cdev, devp->devno, 1); + * if (ret) + * goto fail_add_cdev; + * + * devp->dev = device_create(devp->clsp, NULL, devp->devno, + * NULL, AMPRIME_SL_NAME); + * if (IS_ERR(devp->dev)) { + * ret = PTR_ERR(devp->dev); + * goto fail_create_device; + * } + */ + pr_info("%s: probe ok\n", __func__); + return 0; +/* + * + *fail_create_device: + * pr_info("[amprime_sl.] : amprime_sl device create error.\n"); + * cdev_del(&devp->cdev); + * + *fail_add_cdev: + * pr_info("[amprime_sl.] : amprime_sl add device error.\n"); + */ +fail_class_create_file: + pr_info("[amprime_sl.] : amprime_sl class create file error.\n"); + for (i = 0; amprime_sl_class_attrs[i].attr.name; i++) + class_remove_file(devp->clsp, + &rime_sl_class_attrs[i]); + class_destroy(devp->clsp); +fail_create_class: + pr_info("[amdolby_vision.] : amdolby_vision class create error.\n"); + unregister_chrdev_region(devp->devno, 1); +fail_alloc_region: + pr_info("[amprime_sl.] : amprime_sl alloc error.\n"); + pr_info("[amprime_sl.] : amprime_sl.\n"); + return ret; +} + +static int __exit amprime_sl_remove(struct platform_device *pdev) +{ + struct amprime_sl_dev_s *devp = &rime_sl_dev; + + device_destroy(devp->clsp, devp->devno); + cdev_del(&devp->cdev); + class_destroy(devp->clsp); + unregister_chrdev_region(devp->devno, 1); + pr_info("[ amprime_sl.] : amprime_sl.\n"); + return 0; +} + +static struct platform_driver amprime_sl_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "amprime_sl", + .of_match_table = amprime_sl_match, + }, + .probe = amprime_sl_probe, + .remove = __exit_p(amprime_sl_remove), +}; + +static int __init amprime_sl_init(void) +{ + pr_info("prime_sl module init\n"); + if (platform_driver_register(&rime_sl_driver)) { + pr_info("failed to register amprime_sl module\n"); + return -ENODEV; + } + return 0; +} + +static void __exit amprime_sl_exit(void) +{ + pr_info("prime_sl module exit\n"); +} + +module_init(amprime_sl_init); +module_exit(amprime_sl_exit); + +MODULE_DESCRIPTION("Amlogic HDR Prime SL driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h new file mode 100644 index 000000000000..8466482f730a --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h @@ -0,0 +1,391 @@ +/* + * drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __AMPRIME_SL_H__ +#define __AMPRIME_SL_H__ + +#define DRIVER_VER "20190307" + +#define ENABLE 1 +#define DISABLE 0 + +enum cpuID_e { + _CPU_MAJOR_ID_G12, + _CPU_MAJOR_ID_TL1, + _CPU_MAJOR_ID_UNKNOWN, +}; + +struct prime_sl_device_data_s { + enum cpuID_e cpu_id; +}; + + +#define PRIMESL_LUTC_ADDR_PORT (0x3980) +#define PRIMESL_LUTC_DATA_PORT (0x3981) +#define PRIMESL_LUTP_ADDR_PORT (0x3982) +#define PRIMESL_LUTP_DATA_PORT (0x3983) +#define PRIMESL_LUTD_ADDR_PORT (0x3984) +#define PRIMESL_LUTD_DATA_PORT (0x3985) +#define PRIMESL_CTRL0 (0x3990) +union PRIMESL_CTRL0_BITS { + unsigned int d32; + struct { + unsigned int primesl_en:1, + gclk_ctrl:2, + reg_gclk_ctrl:1, + inv_y_ratio:11, + reserved3:1, + inv_chroma_ratio:11, + reserved2:1, + clip_en:1, + legacy_mode_en:1, + reserved1:2; + } b; +}; +#define PRIMESL_CTRL1 (0x3991) +union PRIMESL_CTRL1_BITS { + unsigned int d32; + struct { + unsigned int footroom:10, + reserved2:6, + l_headroom:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL2 (0x3992) +union PRIMESL_CTRL2_BITS { + unsigned int d32; + struct { + unsigned int c_headroom:10, + reserved1:22; + } b; +}; +#define PRIMESL_CTRL3 (0x3993) +union PRIMESL_CTRL3_BITS { + unsigned int d32; + struct { + unsigned int mua:14, + reserved2:2, + mub:14, + reserved1:2; + } b; +}; +#define PRIMESL_CTRL4 (0x3994) +union PRIMESL_CTRL4_BITS { + unsigned int d32; + struct { + unsigned int oct_7_0:10, + reserved2:6, + oct_7_1:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL5 (0x3995) +union PRIMESL_CTRL5_BITS { + unsigned int d32; + struct { + unsigned int oct_7_2:10, + reserved2:6, + oct_7_3:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL6 (0x3996) +union PRIMESL_CTRL6_BITS { + unsigned int d32; + struct { + unsigned int oct_7_4:10, + reserved2:6, + oct_7_5:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL7 (0x3997) +union PRIMESL_CTRL7_BITS { + unsigned int d32; + struct { + unsigned int oct_7_6:10, + reserved1:22; + } b; +}; +#define PRIMESL_CTRL8 (0x3998) +union PRIMESL_CTRL8_BITS { + unsigned int d32; + struct { + unsigned int d_lut_threshold_3_0:13, + reserved2:3, + d_lut_threshold_3_1:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL9 (0x3999) +union PRIMESL_CTRL9_BITS { + unsigned int d32; + struct { + unsigned int d_lut_threshold_3_2:13, + reserved1:19; + } b; +}; +#define PRIMESL_CTRL10 (0x399a) +union PRIMESL_CTRL10_BITS { + unsigned int d32; + struct { + unsigned int d_lut_step_4_0:4, + d_lut_step_4_1:4, + d_lut_step_4_2:4, + d_lut_step_4_3:4, + reserved1:16; + } b; +}; +#define PRIMESL_CTRL11 (0x399b) +union PRIMESL_CTRL11_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_1:13, + reserved2:3, + rgb2yuv_9_0:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL12 (0x399c) +union PRIMESL_CTRL12_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_3:13, + reserved2:3, + rgb2yuv_9_2:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL13 (0x399d) +union PRIMESL_CTRL13_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_5:13, + reserved2:3, + rgb2yuv_9_4:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL14 (0x399e) +union PRIMESL_CTRL14_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_7:13, + reserved2:3, + rgb2yuv_9_6:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL15 (0x399f) +union PRIMESL_CTRL15_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_8:13, + reserved1:19; + } b; +}; +#define PRIME_PRIMESL_EN (0) +#define PRIME_GCLK_CTRL (1) +#define PRIME_REG_GCLK_CTRL (2) +#define PRIME_INV_Y_RATIO (3) +#define PRIME_INV_CHROMA_RATIO (4) +#define PRIME_CLIP_EN (5) +#define PRIME_LEGACY_MODE_EN (6) +#define PRIME_FOOTROOM (7) +#define PRIME_L_HEADROOM (8) +#define PRIME_C_HEADROOM (9) +#define PRIME_MUA (10) +#define PRIME_MUB (11) +#define PRIME_OCT_7_0 (12) +#define PRIME_OCT_7_1 (13) +#define PRIME_OCT_7_2 (14) +#define PRIME_OCT_7_3 (15) +#define PRIME_OCT_7_4 (16) +#define PRIME_OCT_7_5 (17) +#define PRIME_OCT_7_6 (18) +#define PRIME_D_LUT_THRESHOLD_3_0 (19) +#define PRIME_D_LUT_THRESHOLD_3_1 (20) +#define PRIME_D_LUT_THRESHOLD_3_2 (21) +#define PRIME_D_LUT_STEP_4_0 (22) +#define PRIME_D_LUT_STEP_4_1 (23) +#define PRIME_D_LUT_STEP_4_2 (24) +#define PRIME_D_LUT_STEP_4_3 (25) +#define PRIME_RGB2YUV_9_0 (26) +#define PRIME_RGB2YUV_9_1 (27) +#define PRIME_RGB2YUV_9_2 (28) +#define PRIME_RGB2YUV_9_3 (29) +#define PRIME_RGB2YUV_9_4 (30) +#define PRIME_RGB2YUV_9_5 (31) +#define PRIME_RGB2YUV_9_6 (32) +#define PRIME_RGB2YUV_9_7 (33) +#define PRIME_RGB2YUV_9_8 (34) + + +struct prime_sl_t { + unsigned int legacy_mode_en; + unsigned int clip_en; + unsigned int reg_gclk_ctrl; + unsigned int gclk_ctrl; + unsigned int primesl_en; + + unsigned int inv_chroma_ratio; + unsigned int inv_y_ratio; + unsigned int l_headroom; + unsigned int footroom; + unsigned int c_headroom; + unsigned int mub; + unsigned int mua; + int oct[7]; + unsigned int d_lut_threshold[3]; + unsigned int d_lut_step[4]; + int rgb2yuv[9]; + + uint16_t olut_c[65]; /*from */ + uint16_t olut_p[65]; + uint16_t olut_d[65]; + + unsigned int lut_c[65]; + unsigned int lut_p[65]; + unsigned int lut_d[65]; +}; + +struct sl_hdr_metadata_variables { + int tmInputSignalBlackLevelOffset; + int tmInputSignalWhiteLevelOffset; + int shadowGain; + int highlightGain; + int midToneWidthAdjFactor; + int tmOutputFineTuningNumVal; + int tmOutputFineTuningX[10]; + int tmOutputFineTuningY[10]; + int saturationGainNumVal; + int saturationGainX[6]; + int saturationGainY[6]; +}; + +struct sl_hdr_metadata_tables { + int luminanceMappingNumVal; + int luminanceMappingX[65]; + int luminanceMappingY[65]; + int colourCorrectionNumVal; + int colourCorrectionX[65]; + int colourCorrectionY[65]; +}; + +struct sl_hdr_metadata { + int partID; + int majorSpecVersionID; + int minorSpecVersionID; + int payloadMode; + int hdrPicColourSpace; + int hdrDisplayColourSpace; + int hdrDisplayMaxLuminance; + int hdrDisplayMinLuminance; + int sdrPicColourSpace; + int sdrDisplayColourSpace; + int sdrDisplayMaxLuminance; + int sdrDisplayMinLuminance; + int matrixCoefficient[4]; + int chromaToLumaInjection[2]; + int kCoefficient[3]; + union { + struct sl_hdr_metadata_variables variables; + struct sl_hdr_metadata_tables tables; + } u; +}; + +struct prime_cfg_t { + unsigned int width; /*use?*/ + unsigned int height; /*use?*/ + unsigned int bit_depth; /*use?*/ + int display_OETF; /**/ + int yuv_range; + int display_Brightness; +}; + +struct prime_t { + + int en_ic; /*0: ic not support prime sl; 1: ic support prime sl*/ + int en_top; /*top prime sl switch*/ + int en_pause; + int en_checkdata; + int en_count; + int en_count_tsk; + int en_set; + int en_close; + + int ok_count; + int ok_set; + + int isr_mode; + unsigned int vs_cnt; + unsigned int ver_hw; + unsigned int ver_fw; + + struct prime_cfg_t *pCfg; + struct sl_hdr_metadata *pmta; + struct prime_sl_t *pps; + + struct prime_cfg_t Cfg; + struct sl_hdr_metadata prime_metadata; + struct prime_sl_t prime_sl; + + /*test*/ + unsigned int dbg_nub; + unsigned int dbg_metachange; + struct timeval tv[4][2]; + +}; + +extern void prime_api_init(void); +extern void prime_api_exit(void); +extern void prime_api_isr_process(void); +extern void prime_api_cmd_process(unsigned char cmd, int para); +extern unsigned int prime_api_info_show(char *buf, unsigned int size); +extern int prime_api_store(const char *buf, unsigned int para); +extern int prime_metadata_parser_process(struct prime_t *prime_sl_setting); + +struct hdr_prime_sl_func_s { + const char *version_info; + void (*prime_api_init)(void); + void (*prime_api_exit)(void); + void (*prime_api_isr_process)(void); + void (*prime_api_cmd_process)(unsigned char cmd, int para); + unsigned int (*prime_api_info_show)(char *buf, unsigned int size); + int (*prime_api_store)(const char *buf, unsigned int para); + int (*prime_metadata_parser_process)(struct prime_t *prime_sl_setting); +}; + +extern int register_prime_functions(const struct hdr_prime_sl_func_s *func); +extern int unregister_prime_functions(void); + +#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +#define _VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) +#define _VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) +#define _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + WRITE_VPP_REG_BITS(adr, val, start, len) +#else +extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +extern u32 _VSYNC_RD_MPEG_REG(u32 adr); +extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); +#endif +extern void prime_sl_set_reg(const struct prime_sl_t *pS); +extern void prime_sl_close(void); + + +#endif /*__REG_G12A_PRIME_H__*/ diff --git a/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c new file mode 100644 index 000000000000..1eace541ba9c --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c @@ -0,0 +1,289 @@ +/* + * drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include + + +#include +#include /*gettimeofday*/ +#include /*gettimeofday*/ + +#include /*WRITE_VPP_REG*/ +#include "amprime_sl.h" + +/*======================================*/ +/*#define USE_TASKLET 1*/ + +static inline void wbits_PRIMESL_CTRL0( + unsigned int primesl_en, unsigned int gclk_ctrl, + unsigned int reg_gclk_ctrl, unsigned int inv_y_ratio, + unsigned int inv_chroma_ratio, unsigned int clip_en, + unsigned int legacy_mode_en) +{ + union PRIMESL_CTRL0_BITS v; + + v.b.primesl_en = primesl_en; + v.b.gclk_ctrl = gclk_ctrl; + v.b.reg_gclk_ctrl = reg_gclk_ctrl; + v.b.inv_y_ratio = inv_y_ratio; + v.b.inv_chroma_ratio = inv_chroma_ratio; + v.b.clip_en = clip_en; + v.b.legacy_mode_en = legacy_mode_en; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL0, v.d32); +} +static inline void wbits_PRIMESL_CTRL1(unsigned int footroom, + unsigned int l_headroom) +{ + union PRIMESL_CTRL1_BITS v; + + v.b.footroom = footroom; + v.b.l_headroom = l_headroom; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL1, v.d32); +} +static inline void wbits_PRIMESL_CTRL2(unsigned int c_headroom) +{ + union PRIMESL_CTRL2_BITS v; + + v.b.c_headroom = c_headroom; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL2, v.d32); +} +static inline void wbits_PRIMESL_CTRL3(unsigned int mua, + unsigned int mub) +{ + union PRIMESL_CTRL3_BITS v; + + v.b.mua = mua; + v.b.mub = mub; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL3, v.d32); +} +static inline void wbits_PRIMESL_CTRL4(unsigned int oct_7_0, + unsigned int oct_7_1) +{ + union PRIMESL_CTRL4_BITS v; + + v.b.oct_7_0 = oct_7_0; + v.b.oct_7_1 = oct_7_1; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL4, v.d32); +} +static inline void wbits_PRIMESL_CTRL5(unsigned int oct_7_2, + unsigned int oct_7_3) +{ + union PRIMESL_CTRL5_BITS v; + + v.b.oct_7_2 = oct_7_2; + v.b.oct_7_3 = oct_7_3; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL5, v.d32); +} +static inline void wbits_PRIMESL_CTRL6(unsigned int oct_7_4, + unsigned int oct_7_5) +{ + union PRIMESL_CTRL6_BITS v; + + v.b.oct_7_4 = oct_7_4; + v.b.oct_7_5 = oct_7_5; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL6, v.d32); +} +static inline void wbits_PRIMESL_CTRL7(unsigned int oct_7_6) +{ + union PRIMESL_CTRL7_BITS v; + + v.b.oct_7_6 = oct_7_6; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL7, v.d32); +} +static inline void wbits_PRIMESL_CTRL8(unsigned int d_lut_threshold_3_0, + unsigned int d_lut_threshold_3_1) +{ + union PRIMESL_CTRL8_BITS v; + + v.b.d_lut_threshold_3_0 = d_lut_threshold_3_0; + v.b.d_lut_threshold_3_1 = d_lut_threshold_3_1; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL8, v.d32); +} +static inline void wbits_PRIMESL_CTRL9(unsigned int d_lut_threshold_3_2) +{ + union PRIMESL_CTRL9_BITS v; + + v.b.d_lut_threshold_3_2 = d_lut_threshold_3_2; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL9, v.d32); +} +static inline void wbits_PRIMESL_CTRL10(unsigned int d_lut_step_4_0, + unsigned int d_lut_step_4_1, + unsigned int d_lut_step_4_2, + unsigned int d_lut_step_4_3) +{ + union PRIMESL_CTRL10_BITS v; + + v.b.d_lut_step_4_0 = d_lut_step_4_0; + v.b.d_lut_step_4_1 = d_lut_step_4_1; + v.b.d_lut_step_4_2 = d_lut_step_4_2; + v.b.d_lut_step_4_3 = d_lut_step_4_3; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL10, v.d32); +} +static inline void wbits_PRIMESL_CTRL11(unsigned int rgb2yuv_9_1, + unsigned int rgb2yuv_9_0) +{ + union PRIMESL_CTRL11_BITS v; + + v.b.rgb2yuv_9_1 = rgb2yuv_9_1; + v.b.rgb2yuv_9_0 = rgb2yuv_9_0; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL11, v.d32); +} +static inline void wbits_PRIMESL_CTRL12(unsigned int rgb2yuv_9_3, + unsigned int rgb2yuv_9_2) +{ + union PRIMESL_CTRL12_BITS v; + + v.b.rgb2yuv_9_3 = rgb2yuv_9_3; + v.b.rgb2yuv_9_2 = rgb2yuv_9_2; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL12, v.d32); +} +static inline void wbits_PRIMESL_CTRL13(unsigned int rgb2yuv_9_5, + unsigned int rgb2yuv_9_4) +{ + union PRIMESL_CTRL13_BITS v; + + v.b.rgb2yuv_9_5 = rgb2yuv_9_5; + v.b.rgb2yuv_9_4 = rgb2yuv_9_4; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL13, v.d32); +} +static inline void wbits_PRIMESL_CTRL14(unsigned int rgb2yuv_9_7, + unsigned int rgb2yuv_9_6) +{ + union PRIMESL_CTRL14_BITS v; + + v.b.rgb2yuv_9_7 = rgb2yuv_9_7; + v.b.rgb2yuv_9_6 = rgb2yuv_9_6; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL14, v.d32); +} +static inline void wbits_PRIMESL_CTRL15(unsigned int rgb2yuv_9_8) +{ + union PRIMESL_CTRL15_BITS v; + + v.b.rgb2yuv_9_8 = rgb2yuv_9_8; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL15, v.d32); +} + +#define NOT_USR_WR_T 1 + +void slctr_set_rgb2yuv(const int *pTab)/*9byte*/ +{ +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL11(pTab[1], pTab[0]); + wbits_PRIMESL_CTRL12(pTab[3], pTab[2]); + wbits_PRIMESL_CTRL13(pTab[5], pTab[4]); + wbits_PRIMESL_CTRL14(pTab[7], pTab[6]); + wbits_PRIMESL_CTRL15(pTab[8]); + +#else + int i; + + for (i = 0; i < 9; i++) + WR_T(PRIME_RGB2YUV_9_0+i, (unsigned int)pTab[i]); +#endif +} + +void slctr_set_lutstep(const unsigned int *pTab)/*4byte*/ +{ + +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL10(pTab[0], pTab[1], pTab[2], pTab[3]); + +#else + int i; + + for (i = 0; i < 4; i++) + WR_T(PRIME_D_LUT_STEP_4_0+i, pTab[i]); + +#endif +} +void slctr_set_lutthrd(const unsigned int *pTab)/*3byte*/ +{ + +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL8(pTab[0], pTab[1]); + wbits_PRIMESL_CTRL9(pTab[2]); +#else + int i; + + for (i = 0; i < 3; i++) + WR_T(PRIME_D_LUT_THRESHOLD_3_0+i, pTab[i]); + +#endif +} +void slctr_set_oct(const int *pTab)/*7byte*/ +{ + +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL4(pTab[0], pTab[1]); + wbits_PRIMESL_CTRL5(pTab[2], pTab[3]); + wbits_PRIMESL_CTRL6(pTab[4], pTab[5]); + wbits_PRIMESL_CTRL7(pTab[6]); +#else + int i; + + for (i = 0; i < 7; i++) + WR_T(PRIME_OCT_7_0+i, (unsigned int)pTab[i]); +#endif +} +void slctr_set_lut_c(const int *pTab)/*7byte*/ +{ + int i; + + _VSYNC_WR_MPEG_REG(PRIMESL_LUTC_ADDR_PORT, 0); + for (i = 0; i < 65; i++) + _VSYNC_WR_MPEG_REG(PRIMESL_LUTC_DATA_PORT, pTab[i]); +} + +void slctr_set_lut_p(const int *pTab)/*7byte*/ +{ + int i; + + _VSYNC_WR_MPEG_REG(PRIMESL_LUTP_ADDR_PORT, 0); + for (i = 0; i < 65; i++) + _VSYNC_WR_MPEG_REG(PRIMESL_LUTP_DATA_PORT, pTab[i]); +} + +void slctr_set_lut_d(const int *pTab)/*7byte*/ +{ + int i; + + _VSYNC_WR_MPEG_REG(PRIMESL_LUTD_ADDR_PORT, 0); + for (i = 0; i < 65; i++) + _VSYNC_WR_MPEG_REG(PRIMESL_LUTD_DATA_PORT, pTab[i]); +} + +void prime_sl_set_reg(const struct prime_sl_t *pS) +{ + wbits_PRIMESL_CTRL1(pS->footroom, pS->l_headroom); + wbits_PRIMESL_CTRL2(pS->c_headroom); + wbits_PRIMESL_CTRL3(pS->mua, pS->mub); + slctr_set_oct(&pS->oct[0]); + slctr_set_lutthrd(&pS->d_lut_threshold[0]); + slctr_set_lutstep(&pS->d_lut_step[0]); + slctr_set_rgb2yuv(&pS->rgb2yuv[0]); + slctr_set_lut_c(&pS->lut_c[0]); + slctr_set_lut_p(&pS->lut_p[0]); + slctr_set_lut_d(&pS->lut_d[0]); + + wbits_PRIMESL_CTRL0(1, 0, 0, pS->inv_y_ratio, + pS->inv_chroma_ratio, 0, 0); +} +void prime_sl_close(void) +{ + wbits_PRIMESL_CTRL0(0, 0, 0, 0, 0, 0, 0); +} + diff --git a/include/linux/amlogic/media/amprime_sl/prime_sl.h b/include/linux/amlogic/media/amprime_sl/prime_sl.h new file mode 100644 index 000000000000..76bf489d3d4d --- /dev/null +++ b/include/linux/amlogic/media/amprime_sl/prime_sl.h @@ -0,0 +1,26 @@ +/* + * include/linux/amlogic/media/amprime_sl/prime_sl.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _PRIMSE_SL_H_ +#define _PRIMSE_SL_H_ + +#include + +extern void prime_sl_process(struct vframe_s *vf); +extern bool is_dolby_vision_enable(void); + +#endif From cf1f268b3d67996ebd2d22dac263609df2827e0d Mon Sep 17 00:00:00 2001 From: Jian Hu Date: Mon, 15 Apr 2019 16:32:04 +0800 Subject: [PATCH 0437/1060] i2c: meson: add detail calculation process for i2c duty cycle [1/1] PD#SWPL-7197 Problem: There is not detail calculation process for i2c duty cycle Solution: add detail calculation process for i2c duty cycle Verify: verified on x301 Change-Id: Ifc222acda3268f792f63e84c6dc3513d80568e19 Signed-off-by: Jian Hu --- drivers/amlogic/i2c/i2c-meson-master.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/amlogic/i2c/i2c-meson-master.c b/drivers/amlogic/i2c/i2c-meson-master.c index b5280102d344..17458e76adbc 100644 --- a/drivers/amlogic/i2c/i2c-meson-master.c +++ b/drivers/amlogic/i2c/i2c-meson-master.c @@ -162,13 +162,31 @@ static void meson_i2c_write_tokens(struct meson_i2c *i2c) /* * Count = clk/freq = H + L * Duty = H/(H + L) = 1/2 -- duty 50% + * 1. register desription + * in I2C_CONTROL_REG , n = [28:29][21:12], control the high level time + * n consists of 12bit, [21:12] is the low 10bit, + * [28:29] is the bit 11 and 12. + * in I2C_SLAVE_ADDRESS, m = [27:16], control the low level time, + * bit 28 enable the function + * + * 2.I2C controller internal characteristic * H = n + delay * L = 2m + * (H:high clock counts equals n + 15 clocks which + * cost by sampling and filtering + * L:low clock counts equals m multiply by 2) + * + * 3.high level and low level relationship: + * H/L = (n + 15)/2m = 1/1 + * H+L = 2m + n +15 = Count + * Count = 166M/freq = 166M/100k * * => * * n = Count/2 - delay * m = Count/4 + * + * n equals div_h, m equals div_l below * Standard Mode : 100k */ static void meson_i2c_set_clk_div_std(struct meson_i2c *i2c) From 74749b03832a1619d768a3c6e85579a7e82b12da Mon Sep 17 00:00:00 2001 From: "binqi.zhang" Date: Wed, 17 Apr 2019 03:24:30 -0400 Subject: [PATCH 0438/1060] dts: update gpu freq tbl for buildroot [1/1] PD#SWPL-4253 Problem: Compared with P212, GPU on g12a can not work with high frequency when running some cases like particle; Solution: update gpu freq tbl for buildroot Verify: build pass GPU on g12a can work with high freq when running particle Change-Id: Ie10335d1f3a043d4418245d31efa8b42077031a9 Signed-off-by: binqi.zhang --- .../amlogic/g12a_s905d2_u200_buildroot.dts | 1 + .../g12a_s905d2_u200_buildroot_vccktest.dts | 2 +- .../amlogic/g12a_s905x2_u211_buildroot.dts | 1 + .../amlogic/g12a_s905x2_u212_buildroot.dts | 1 + .../arm64/boot/dts/amlogic/mesong12a_drm.dtsi | 21 +++++++++++++++++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index d2759bd878f3..0a6139cf7043 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -19,6 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index 5b288e80018e..b700f088315e 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -19,7 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" - +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; compatible = "amlogic, g12a"; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 53e8a3c93976..ee50e8619731 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 258d55415141..453319dfa442 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi index 9708a6296f86..60c3cff86599 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi @@ -107,3 +107,24 @@ }; }; +&gpu{ + /*gpu max freq is 850M*/ + def_clk = <1>; + tbl = <&dvfs285_cfg &dvfs666_cfg &dvfs850_cfg &dvfs850_cfg>; + + dvfs285_cfg:dvfs285_cfg { + keep_count = <2>; + threshold = <100 200>; + }; + + dvfs666_cfg:dvfs666_cfg { + keep_count = <1>; + threshold = <85 200>; + }; + + dvfs850_cfg:dvfs850_cfg { + keep_count = <1>; + threshold = <179 255>; + }; + +}; From aaa0a89b03e6de46dfa3e77982852e3bebadf1c1 Mon Sep 17 00:00:00 2001 From: "binqi.zhang" Date: Mon, 22 Apr 2019 02:07:22 -0400 Subject: [PATCH 0439/1060] dts: update gpu freq tbl for 32bit kernel [1/1] PD#SWPL-4253 Problem: Compared with P212, GPU on g12a can not work with high frequency when running some cases like particle; Solution: update gpu freq tbl for buildroot Verify: build pass GPU on g12a can work with high freq when running particle Change-Id: Ifcb286cd37faa9f618b48ab515ca360aba563a34 Signed-off-by: binqi.zhang --- .../amlogic/g12a_s905d2_u200_buildroot.dts | 1 + .../g12a_s905d2_u200_buildroot_vccktest.dts | 1 + .../amlogic/g12a_s905x2_u211_buildroot.dts | 1 + .../amlogic/g12a_s905x2_u212_buildroot.dts | 1 + arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi | 21 +++++++++++++++++++ 5 files changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 97780745706b..80e76f34a047 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -19,6 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index bc7730e015e4..6b6890bc646b 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -19,6 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 7ade2256ec4e..1980e58a71ad 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 29097af0de37..102bfbb9ae29 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; diff --git a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi index b6597c677d88..00beafaba1a2 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi @@ -107,3 +107,24 @@ }; }; +&gpu{ + /*gpu max freq is 850M*/ + def_clk = <1>; + tbl = <&dvfs285_cfg &dvfs666_cfg &dvfs850_cfg &dvfs850_cfg>; + + dvfs285_cfg:dvfs285_cfg { + keep_count = <2>; + threshold = <100 200>; + }; + + dvfs666_cfg:dvfs666_cfg { + keep_count = <1>; + threshold = <85 200>; + }; + + dvfs850_cfg:dvfs850_cfg { + keep_count = <1>; + threshold = <179 255>; + }; + +}; From a677355477e74d35d8da44fedf5d4e7853129445 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Thu, 18 Apr 2019 10:47:16 +0800 Subject: [PATCH 0440/1060] amvecm: fix tm2 show green screen when play videos [1/1] PD#SWPL-7183 Problem: LC mtx use 10bit, should be 12bit Solution: add 12bit 709 mtx Verify: ab311 Change-Id: I2367fc7b7ef4cb164d86348b618d13d465c7a6a1 Signed-off-by: Bencheng Jing --- .../media/enhancement/amvecm/local_contrast.c | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 472ad615b588..bcbae917426a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -186,12 +186,9 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, if (bitdepth == 10) { WRITE_VPP_REG(matrix_offset0_1, 0x00400200); WRITE_VPP_REG(matrix_clip, 0x3ff); - } else if (bitdepth == 12) { + } else { WRITE_VPP_REG(matrix_offset0_1, 0x01000800); WRITE_VPP_REG(matrix_clip, 0xfff); - } else { - WRITE_VPP_REG(matrix_offset0_1, 0x00400200); - WRITE_VPP_REG(matrix_clip, 0x3ff); } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); @@ -215,12 +212,9 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, if (bitdepth == 10) { WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); WRITE_VPP_REG(matrix_clip, 0x3ff); - } else if (bitdepth == 12) { + } else { WRITE_VPP_REG(matrix_pre_offset0_1, 0x01000800); WRITE_VPP_REG(matrix_clip, 0xfff); - } else { - WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); - WRITE_VPP_REG(matrix_clip, 0x3ff); } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); @@ -241,7 +235,13 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_coef11_12, 0xea701c0); WRITE_VPP_REG(matrix_coef20_21, 0x1c00e6a); WRITE_VPP_REG(matrix_coef22, 0xfd7); - WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else { + WRITE_VPP_REG(matrix_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99); @@ -261,7 +261,13 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_coef11_12, 0xfc90f77); WRITE_VPP_REG(matrix_coef20_21, 0x12b021f); WRITE_VPP_REG(matrix_coef22, 0x0); - WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); @@ -479,7 +485,7 @@ static void lc_blk_bdry_config(unsigned int height, unsigned int width) } static void lc_top_config(int enable, int h_num, int v_num, - unsigned int height, unsigned int width, int bitdepth) + unsigned int height, unsigned int width, int bitdepth, int flag) { /*lcinput_ysel*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_INPUT_MUX, 5, 4, 3); @@ -501,8 +507,13 @@ static void lc_top_config(int enable, int h_num, int v_num, WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 16, 1); /*lc enable need set at last*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, enable, 4, 1); - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); + if (flag == 1) { + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); + } else { + lc_mtx_set(INP_MTX, LC_MTX_YUV601L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV601L, 1, bitdepth); + } } static void lc_disable(void) @@ -525,6 +536,7 @@ static void lc_config(int enable, int h_num, v_num; unsigned int height, width; static unsigned int vf_height, vf_width; + unsigned int flag; const struct vinfo_s *vinfo = get_current_vinfo(); height = vinfo->height; @@ -548,16 +560,9 @@ static void lc_config(int enable, vf_height = vf->height; vf_width = vf->width; - - if (vf_height < 720) { - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); - } else { - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); - } - - lc_top_config(enable, h_num, v_num, height, width, bitdepth); + /*flag: 0 for 601; 1 for 709*/ + flag = (vf_height > 720) ? 1 : 0; + lc_top_config(enable, h_num, v_num, height, width, bitdepth, flag); if (sps_h_en == 1) width /= 2; @@ -1261,7 +1266,7 @@ void lc_init(int bitdepth) if (!lc_en) return; - lc_top_config(0, h_num, v_num, height, width, bitdepth); + lc_top_config(0, h_num, v_num, height, width, bitdepth, 1); WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); /*default LC low parameters*/ From 716ba3ee14a044d620ba412cf2b8ee407aafc391 Mon Sep 17 00:00:00 2001 From: Xiaoming Sui Date: Mon, 8 Apr 2019 20:04:51 +0800 Subject: [PATCH 0441/1060] avsync: tsync: fix the avsync for ms12 [3/4] PD#SWPL-5837 Problem: dtv is out of avsync when dolby ms12 certificate Solution: when the audio is played, recalculate the apts to sync pcrsrc when pcrmaster. Verify: X301 Change-Id: Ia121e57ad69c5b0d211e14bf3a61f165457e54c7 Signed-off-by: Xiaoming Sui --- drivers/amlogic/media/frame_sync/timestamp.c | 13 ++++++++++++ drivers/amlogic/media/frame_sync/tsync.c | 20 +++++++++++++++++++ .../linux/amlogic/media/frame_sync/tsync.h | 3 +++ 3 files changed, 36 insertions(+) diff --git a/drivers/amlogic/media/frame_sync/timestamp.c b/drivers/amlogic/media/frame_sync/timestamp.c index a6076d58a575..03e3fe92fdec 100644 --- a/drivers/amlogic/media/frame_sync/timestamp.c +++ b/drivers/amlogic/media/frame_sync/timestamp.c @@ -136,6 +136,19 @@ u32 timestamp_pcrscr_get(void) } EXPORT_SYMBOL(timestamp_pcrscr_get); +void timestamp_set_pcrlatency(u32 latency) +{ + if (latency < 500 * 90) + pcrscr_lantcy = latency; +} +EXPORT_SYMBOL(timestamp_set_pcrlatency); + +u32 timestamp_get_pcrlatency(void) +{ + return pcrscr_lantcy; +} +EXPORT_SYMBOL(timestamp_get_pcrlatency); + u32 timestamp_tsdemux_pcr_get(void) { if (tsdemux_pcrscr_get_cb) diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index 711a1a4e200f..170584a2435f 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -1999,6 +1999,25 @@ static ssize_t show_startsync_mode(struct class *class, return sprintf(buf, "0x%x\n", tsync_get_startsync_mode()); } +static ssize_t show_latency(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", timestamp_get_pcrlatency()); +} + +static ssize_t store_latency(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int latency = 0; + ssize_t r; + + r = kstrtoint(buf, 0, &latency); + if (r != 0) + return -EINVAL; + timestamp_set_pcrlatency(latency); + return size; +} static ssize_t show_apts_lookup(struct class *class, struct class_attribute *attrr, char *buf) @@ -2088,6 +2107,7 @@ static struct class_attribute tsync_class_attrs[] = { NULL), __ATTR(checkin_firstapts, 0644, show_checkin_firstapts, NULL), + __ATTR(pts_latency, 0664, show_latency, store_latency), __ATTR_NULL }; diff --git a/include/linux/amlogic/media/frame_sync/tsync.h b/include/linux/amlogic/media/frame_sync/tsync.h index 2194d6a18609..edf83a71be44 100644 --- a/include/linux/amlogic/media/frame_sync/tsync.h +++ b/include/linux/amlogic/media/frame_sync/tsync.h @@ -157,6 +157,9 @@ extern int tsync_set_av_threshold_max(int max); extern void set_pts_realign(void); +extern void timestamp_set_pcrlatency(u32 latency); +extern u32 timestamp_get_pcrlatency(void); + static inline u32 tsync_vpts_discontinuity_margin(void) { return tsync_get_av_threshold_min(); From 28d0f28514a29d0f5bdcbec1cc8f5ceb14f7c430 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Thu, 11 Apr 2019 16:16:35 +0800 Subject: [PATCH 0442/1060] vpp: use new interface to increase accuracy of ar calculation [1/2] PD#OTT-2068 Problem: When playing 1280x128 video under normal screen mode, the aspect ratio from decodec is not accurate enough by multipling 0x100. (128x256/1280=25.6). Dropping 0.6 will cause height losing 9 lines. Solution: Using new interface to pass real ar width and height following steps: 1.Set old ar variable to 0x3ff as a trigger flag. 2.set the original ar value into sar_width and sar_height of vframe Verify: verified on franklin Change-Id: I8a794edd968a76f198ee9cb168a7cfb858c858f8 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/vpp.c | 89 ++++++++++++++++++++---- include/linux/amlogic/media/vfm/vframe.h | 3 + 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 24f493b4d299..1c89853f8c85 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -597,6 +597,10 @@ static unsigned int custom_ar; MODULE_PARM_DESC(custom_ar, "custom_ar"); module_param(custom_ar, uint, 0664); +static unsigned int force_use_ext_ar; +MODULE_PARM_DESC(force_use_ext_ar, "force_use_ext_ar"); +module_param(force_use_ext_ar, uint, 0664); + static unsigned int force_no_compress; MODULE_PARM_DESC(force_no_compress, "force_no_compress"); module_param(force_no_compress, uint, 0664); @@ -867,7 +871,7 @@ static int vpp_set_filters_internal( u32 width_out = wid_out; /* vinfo->width; */ u32 height_out = hei_out; /* vinfo->height; */ u32 aspect_ratio_out = - (vinfo->aspect_ratio_den << 8) / vinfo->aspect_ratio_num; + (vinfo->aspect_ratio_den << 10) / vinfo->aspect_ratio_num; bool fill_match = true; u32 orig_aspect = 0; u32 screen_aspect = 0; @@ -890,6 +894,8 @@ static int vpp_set_filters_internal( s32 vpp_zoom_center_x, vpp_zoom_center_y; u32 crop_ratio = 1; u32 crop_left, crop_right, crop_top, crop_bottom; + u32 sar_width = 0, sar_height = 0; + bool ext_sar = false; bool no_compress = false; if (!input) @@ -948,6 +954,11 @@ static int vpp_set_filters_internal( else vskip_step = 1; + if (super_debug) + pr_info("sar_width=%d, sar_height = %d, %d\n", + vf->sar_width, vf->sar_height, + force_use_ext_ar); + RESTART_ALL: crop_left = video_source_crop_left / crop_ratio; crop_right = video_source_crop_right / crop_ratio; @@ -973,6 +984,26 @@ RESTART: /* don't use input->wide_mode */ wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + if ((vpp_flags & VPP_FLAG_AR_MASK) == VPP_FLAG_AR_MASK) { + ext_sar = true; + sar_width = vf->sar_width; + sar_height = vf->sar_height; + } else if (force_use_ext_ar) { + ext_sar = true; + sar_width = 1; + sar_height = 1; + } + + if (ext_sar && sar_width && sar_height) { + aspect_factor = + div_u64((u64)256ULL * + (u64)sar_height * + (u64)height_in, + (u32)(sar_width * width_in)); + } else { + ext_sar = false; + } + /* keep 8 bits resolution for aspect conversion */ if (wide_mode == VIDEO_WIDEOPTION_4_3) { if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) @@ -980,12 +1011,14 @@ RESTART: else aspect_factor = 0xc0; wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; } else if (wide_mode == VIDEO_WIDEOPTION_16_9) { if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) aspect_factor = 0x1c7; else aspect_factor = 0x90; wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; } else if ((wide_mode >= VIDEO_WIDEOPTION_4_3_IGNORE) && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { if (aspect_factor != 0xc0) @@ -993,6 +1026,7 @@ RESTART: orig_aspect = aspect_factor; screen_aspect = 0xc0; + ext_sar = false; } else if ((wide_mode >= VIDEO_WIDEOPTION_16_9_IGNORE) && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { if (aspect_factor != 0x90) @@ -1000,35 +1034,60 @@ RESTART: orig_aspect = aspect_factor; screen_aspect = 0x90; + ext_sar = false; } else if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { - if (cur_custom_ar != 0) + if (cur_custom_ar != 0) { aspect_factor = cur_custom_ar & 0x3ff; + ext_sar = false; + } wide_mode = VIDEO_WIDEOPTION_NORMAL; } else if (wide_mode == VIDEO_WIDEOPTION_AFD) { - if (aspect_factor == 0x90) + if (aspect_factor == 0x90) { wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; - else + ext_sar = false; + } else wide_mode = VIDEO_WIDEOPTION_NORMAL; } + /* if use the mode ar, will disable ext ar */ if (super_debug) pr_info("aspect_factor=%d,%d,%d,%d,%d,%d\n", aspect_factor, w_in, height_out, - width_out, h_in, aspect_ratio_out); + width_out, h_in, aspect_ratio_out >> 2); if ((aspect_factor == 0) + || (aspect_factor == + (VPP_FLAG_AR_MASK >> VPP_FLAG_AR_BITS)) || (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) - || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) + || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) { aspect_factor = 0x100; - else { + height_after_ratio = h_in; + } else if (ext_sar) { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * width_in) * aspect_ratio_out); + + tmp = tmp >> 2; + height_after_ratio = + div_u64((u64)256ULL * + (u64)w_in * + (u64)height_out * + (u64)sar_height * + (u64)height_in, + (u32)tmp); + height_after_ratio /= sar_height; + aspect_factor = (height_after_ratio << 8) / h_in; + } else { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * h_in) * aspect_ratio_out); + + tmp = tmp >> 2; aspect_factor = div_u64((unsigned long long)w_in * height_out * - (aspect_factor << 8), - width_out * h_in * aspect_ratio_out); + (aspect_factor << 8), + (u32)tmp); + height_after_ratio = (h_in * aspect_factor) >> 8; } - height_after_ratio = (h_in * aspect_factor) >> 8; - /* *if we have ever set a cropped display area for video layer * (by checking video_layer_width/video_height), then @@ -1064,17 +1123,17 @@ RESTART: && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED) && orig_aspect) { if (vinfo->width && vinfo->height) - aspect_ratio_out = (vinfo->height << 8) / vinfo->width; + aspect_ratio_out = (vinfo->height << 10) / vinfo->width; - if ((video_height << 8) > (video_width * aspect_ratio_out)) { + if ((video_height << 10) > (video_width * aspect_ratio_out)) { u32 real_video_height = - (video_width * aspect_ratio_out) >> 8; + (video_width * aspect_ratio_out) >> 10; video_top += (video_height - real_video_height) >> 1; video_height = real_video_height; } else { u32 real_video_width = - (video_height << 8) / aspect_ratio_out; + (video_height << 10) / aspect_ratio_out; video_left += (video_width - real_video_width) >> 1; video_width = real_video_width; diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 1ca5c71ba285..f29ed1b0aa24 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -411,6 +411,9 @@ struct vframe_s { struct vframe_pic_mode_s pic_mode; unsigned long v4l_mem_handle; + + u32 sar_width; + u32 sar_height; } /*vframe_t */; #if 0 From 5a78b7ca5406471b188cdf5e4f9b91008593ec69 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Mon, 22 Apr 2019 18:57:12 +0800 Subject: [PATCH 0443/1060] debug: save irqflag locally when ftrace_ramoops io [1/1] PD#SWPL-6028 Problem: save irqflag locally when ftrace_ramoops io Solution: save irqflag locally when ftrace_ramoops io Verify: TL1 x301 Change-Id: I6df9700cceaccc97dc983d88ada73197a6968f73 Signed-off-by: Jianxin Pan --- drivers/amlogic/debug/debug_ftrace_ramoops.c | 14 ++++++-------- include/linux/amlogic/debug_ftrace_ramoops.h | 15 +++++++++------ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/debug/debug_ftrace_ramoops.c b/drivers/amlogic/debug/debug_ftrace_ramoops.c index f67c59fe91ba..145c66f14266 100644 --- a/drivers/amlogic/debug/debug_ftrace_ramoops.c +++ b/drivers/amlogic/debug/debug_ftrace_ramoops.c @@ -33,7 +33,6 @@ #include static DEFINE_PER_CPU(int, en); -static DEFINE_PER_CPU(unsigned long, irq_flag); #define IRQ_D 1 @@ -122,17 +121,16 @@ void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec, } void notrace pstore_io_save(unsigned long reg, unsigned long val, - unsigned long parant, unsigned int flag) + unsigned long parant, unsigned int flag, + unsigned long *irq_flag) { struct pstore_ftrace_record rec; - int cpu = get_cpu(); - put_cpu(); if (!ramoops_ftrace_en || !ramoops_io_en) return; if ((flag == PSTORE_FLAG_IO_R || flag == PSTORE_FLAG_IO_W) && IRQ_D) - local_irq_save(per_cpu(irq_flag, cpu)); + local_irq_save(*irq_flag); rec.ip = CALLER_ADDR0; rec.parent_ip = parant; @@ -141,9 +139,9 @@ void notrace pstore_io_save(unsigned long reg, unsigned long val, rec.val2 = val; pstore_ftrace_save(&rec); - if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END) - && IRQ_D) - local_irq_restore(per_cpu(irq_flag, cpu)); + if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END) && + IRQ_D) + local_irq_restore(*irq_flag); } EXPORT_SYMBOL(pstore_io_save); diff --git a/include/linux/amlogic/debug_ftrace_ramoops.h b/include/linux/amlogic/debug_ftrace_ramoops.h index 51f4c88173c5..fa6d4c4921e9 100644 --- a/include/linux/amlogic/debug_ftrace_ramoops.h +++ b/include/linux/amlogic/debug_ftrace_ramoops.h @@ -33,20 +33,23 @@ extern unsigned int dump_iomap; #define PSTORE_FLAG_MASK 0xF void notrace pstore_io_save(unsigned long reg, unsigned long val, - unsigned long parant, unsigned int flag); + unsigned long parant, unsigned int flag, + unsigned long *irq_flag); //#define SKIP_IO_TRACE #if (defined CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE) && (!defined SKIP_IO_TRACE) #define pstore_ftrace_io_wr(reg, val) \ -pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W) +unsigned long irqflg; \ +pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W, &irqflg) #define pstore_ftrace_io_wr_end(reg, val) \ -pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END) +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END, &irqflg) -#define pstore_ftrace_io_rd(reg) \ -pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R) +#define pstore_ftrace_io_rd(reg) \ +unsigned long irqflg; \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R, &irqflg) #define pstore_ftrace_io_rd_end(reg) \ -pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END) +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END, &irqflg) #define need_dump_iomap() (ramoops_io_en | dump_iomap) From 15c4a9db5040bd48b976777efbea6645396c26b7 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Tue, 23 Apr 2019 10:52:07 +0800 Subject: [PATCH 0444/1060] atv_demod: fix audio output when adjust the input amplitude [1/1] PD#TV-4901 Problem: fix audio output when adjust the input amplitude. Solution: fix audio output when adjust the input amplitude. Verify: verified by x301 Change-Id: If08e4adff6f4d0355448687ebe6756fa2e155704 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.c b/drivers/amlogic/atv_demod/atv_demod_monitor.c index 86cd6fcb16bb..72c42ddbe2b6 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.c +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.c @@ -31,7 +31,7 @@ bool atvdemod_mixer_tune_en; bool atvdemod_overmodulated_en; bool audio_det_en; bool atvdemod_det_snr_en = true; -bool audio_thd_en = true; +bool audio_thd_en; bool atvdemod_det_nonstd_en; bool atvaudio_det_outputmode_en = true; From 986180e0c6d1b48d12f3d959c5f9cb71c166c40d Mon Sep 17 00:00:00 2001 From: "qiyao.zhou" Date: Tue, 23 Apr 2019 14:30:24 +0800 Subject: [PATCH 0445/1060] dts: flanklin bring up based on google-ref! [1/1] PD#SWPL-7184 Problem: flanklin bring up based on google-ref. Solution: Modify copy file for franklin. Verify: verify it on franklin. Change-Id: If55159835daf0a87439647586526f836a226504c Signed-off-by: qiyao.zhou --- .../arm/boot/dts/amlogic/sm1_s905x3_ac213.dts | 110 ++++++++++-------- .../boot/dts/amlogic/sm1_s905x3_ac213.dts | 75 ++++++++++-- 2 files changed, 127 insertions(+), 58 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts index 5a66538373ee..09ae70cc028b 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -171,17 +171,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -332,43 +332,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -1003,15 +1007,16 @@ }; }; -&i2c2 { - status = "disabled"; - pinctrl-names="default"; - pinctrl-0=<&i2c2_master_pins2>; - clock-frequency = <100000>; -}; +/*&i2c2 { + * status = "okay"; + * pinctrl-names="default"; + * pinctrl-0=<&i2c2_master_pins2>; + * clock-frequency = <300000>; + *}; + */ &i2c3 { - status = "okay"; + status = "ok"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -1606,3 +1611,14 @@ status = "okay"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts index 8966f469daea..8c22a555aa35 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -169,17 +169,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -325,6 +325,47 @@ nrds-enable = <1>; pps-enable = <1>; }; + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; ionvideo { compatible = "amlogic, ionvideo"; dev_name = "ionvideo"; @@ -1044,15 +1085,16 @@ }; }; -&i2c2 { - status = "disabled"; - pinctrl-names="default"; - pinctrl-0=<&i2c2_master_pins2>; - clock-frequency = <100000>; -}; +/*&i2c2 { + * status = "okay"; + * pinctrl-names="default"; + * pinctrl-0=<&i2c2_master_pins2>; + * clock-frequency = <300000>; + *}; + */ &i2c3 { - status = "okay"; + status = "ok"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -1062,7 +1104,7 @@ compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; reg = <0x31>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio GPIOA_5 0>; no_mclk; }; @@ -1614,3 +1656,14 @@ status = "okay"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; From 3e136f08fdb0b72408afd52a8725d9de4348ac4b Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Tue, 23 Apr 2019 19:37:41 +0800 Subject: [PATCH 0446/1060] schedtune: fix crash when there is cpu boot fail in hmp [1/1] PD#SWPL-7656 Problem: crash when there is cpu boot fail in hmp Solution: fix crash when there is cpu boot fail in hmp Verify: W400 Change-Id: I0153975593adb0bfcbc3c3bd6543f0fb2e6bf2e0 Signed-off-by: Jianxin Pan --- kernel/sched/tune.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c index fbdd00a7aabf..7399e709f954 100644 --- a/kernel/sched/tune.c +++ b/kernel/sched/tune.c @@ -951,6 +951,9 @@ schedtune_add_cluster_nrg( * Assume we have EM data only at the CPU and * the upper CLUSTER level */ +#ifdef CONFIG_AMLOGIC_MODIFY + if (sd2->parent) +#endif BUG_ON(!cpumask_equal( sched_group_cpus(sg), sched_group_cpus(sd2->parent->groups) From 96efc51fc9470da1b9a95ab6c327a1a908f1ddb7 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Tue, 23 Apr 2019 13:55:44 +0800 Subject: [PATCH 0447/1060] tvafe: fix pal60 afbc abnormal [1/1] PD#SWPL-7057 Problem: pal60 abnormal when enable afbc Solution: fix the v_active size Verify: test on x301 Change-Id: I02c6077ac364c4f585fb3cf5742e0b4228c39cd2 Signed-off-by: Nian Jing --- drivers/amlogic/media/vin/tvin/tvin_format_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvin_format_table.c b/drivers/amlogic/media/vin/tvin/tvin_format_table.c index ff3ca0f8be3a..e952d031fd34 100644 --- a/drivers/amlogic/media/vin/tvin/tvin_format_table.c +++ b/drivers/amlogic/media/vin/tvin/tvin_format_table.c @@ -1494,7 +1494,7 @@ const unsigned int cvbs_acd_table[TVIN_SIG_FMT_CVBS_NTSC_50 - 0x00000000, 0x00000000, 0x00000000, 0x08000000, 0x02020000, 0x0209c832, 0x00000000, 0xfcf44396, 0x00000102, 0xe7f14e8e, 0x00140008, 0x20800000, 0x00275a60, 0x00001001, 0x10e0474f, - 0x00890359, 0x00170137, 0x00000000, 0x00070000, 0x00000000, + 0x00880358, 0x00130103, 0x00000000, 0x00070000, 0x00000000, 0x00000000, 0x00000050, 0x00000000, 0x000003ff, 0x00000000, 0x00000000, 0x00000000, 0x0004d206, 0x00000000, 0x030000f0, 0x0000000a, 0x0000523e, 0x0004114e, 0x000000f0, 0x00000001, @@ -1936,7 +1936,7 @@ const unsigned int rf_acd_table[TVIN_SIG_FMT_CVBS_NTSC_50 - 0x00000000, 0x00000000, 0x00000000, 0x08000000, 0x02020000, 0x0209c832, 0x00000000, 0xfcf44396, 0x00000102, 0xe7f14e8e, 0x00140008, 0x20800000, 0x00275a60, 0x00001001, 0x10e0474f, - 0x00890359, 0x00170137, 0x00000000, 0x00070000, 0x00000000, + 0x00880358, 0x00130103, 0x00000000, 0x00070000, 0x00000000, 0x00000000, 0x00000050, 0x00000000, 0x000003ff, 0x00000000, 0x00000000, 0x00000000, 0x0004d206, 0x00000000, 0x030000f0, 0x0000000a, 0x0000523e, 0x0004114e, 0x000000f0, 0x00000001, From 08f2b392f6c8173174392e7f694fcf85af8141f3 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Mon, 22 Apr 2019 17:20:09 +0800 Subject: [PATCH 0448/1060] hdmitx: move work_internal_intr to delayed_work [1/1] PD#SWPL-6894 Problem: Queue work 'work_internal_intr' cause the hdcp22 flicker Solution: Move work_internal_intr to delayed_work Verify: G12/U212 Change-Id: Ib05c82bb66c9ad7396790d5eb237ff486c56c980 Signed-off-by: Zongdong Jiao --- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 4 ++-- .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 21 +++++++++++-------- .../media/vout/hdmi_tx/hdmi_tx_module.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 04c2347d93f9..4bc31062d63d 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -3932,7 +3932,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) static void hdmitx_internal_intr_handler(struct work_struct *work) { - struct hdmitx_dev *hdev = container_of((struct work_struct *)work, + struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, struct hdmitx_dev, work_internal_intr); hdev->HWOp.DebugFun(hdev, "dumpintr"); @@ -3985,7 +3985,7 @@ static int hdmi_task_handle(void *data) hdmitx_hpd_plugin_handler); INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugout, hdmitx_hpd_plugout_handler); - INIT_WORK(&hdmitx_device->work_internal_intr, + INIT_DELAYED_WORK(&hdmitx_device->work_internal_intr, hdmitx_internal_intr_handler); /* for rx sense feature */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 775e291de9f3..375e45d6c330 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -669,9 +669,8 @@ static irqreturn_t intr_handler(int irq, void *dev) hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, ~0); hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_STAT, 0xff); - pr_info(SYS "irq %x\n", dat_top); - if (dat_dwc) - pr_info(SYS "irq %x\n", dat_dwc); + pr_info(SYS "irq %x %x\n", dat_top, dat_dwc); + if (hdev->hpd_lock == 1) { pr_info(HW "HDMI hpd locked\n"); goto next; @@ -702,7 +701,8 @@ static irqreturn_t intr_handler(int irq, void *dev) /* internal interrupt */ if (dat_top & (1 << 0)) { hdev->hdmitx_event |= HDMI_TX_INTERNAL_INTR; - queue_work(hdev->hdmi_wq, &hdev->work_internal_intr); + queue_delayed_work(hdev->hdmi_wq, + &hdev->work_internal_intr, HZ / 10); } if (dat_top & (1 << 3)) { unsigned int rd_nonce_mode = @@ -3051,11 +3051,9 @@ do { \ #define DUMP_HDMITXREG_SECTION(start, end) \ do { \ - if (start > end) { \ - pr_info("Error start = 0x%lx > end = 0x%lx\n", start, end); \ + if (start > end) \ break; \ - } \ - pr_info("Start = 0x%lx End = 0x%lx\n", start, end); \ +\ for (addr = start; addr < end + 1; addr++) { \ val = hdmitx_rd_reg(addr); \ if (val) \ @@ -3067,7 +3065,12 @@ static void hdmitx_dump_intr(void) { unsigned int addr = 0, val = 0; - DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_FC_STAT0, HDMITX_DWC_IH_MUTE); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_FC_STAT0, + HDMITX_DWC_IH_I2CMPHY_STAT0); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_DECODE, HDMITX_DWC_IH_DECODE); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_MUTE_FC_STAT0, + HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_MUTE, HDMITX_DWC_IH_MUTE); } static void mode420_half_horizontal_para(void) diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 7c8082885d7a..274f5db0a169 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -302,7 +302,7 @@ struct hdmitx_dev { struct delayed_work work_hpd_plugin; struct delayed_work work_hpd_plugout; struct delayed_work work_rxsense; - struct work_struct work_internal_intr; + struct delayed_work work_internal_intr; struct work_struct work_hdr; struct delayed_work work_do_hdcp; #ifdef CONFIG_AML_HDMI_TX_14 From 0e26ac0d502a35e11ac46c5836f2f54aade696f7 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Wed, 24 Apr 2019 19:34:32 +0800 Subject: [PATCH 0449/1060] hdmitx: add the arbitration between hdcp22 and EMP [1/1] PD#SWPL-5618 Problem: Need to optimize the arbitration between hdcp22 and EMP Solution: Add the arbitration between hdcp22 and EMP Verify: TM2/T962E2/AB311 Change-Id: Ib910ac40754e744e36ee1349de5b2c55e2a011eb Signed-off-by: Zongdong Jiao --- .../media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 375e45d6c330..c7ff9fd16c3e 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -587,6 +587,11 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev) hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 6, 1); /* Enable tmds_clk to HDCP2.2 IP */ hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 5, 1); + /* Enable axi_clk */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 13, 1); + /* Enable axi_async_req_en_emp & axi_async_req_en_esm */ + hdmitx_set_reg_bits(HDMITX_TOP_AXI_ASYNC_CNTL0, 1, 0, 1); + hdmitx_set_reg_bits(HDMITX_TOP_AXI_ASYNC_CNTL0, 1, 16, 1); hdmitx_hpd_hw_op(HPD_INIT_DISABLE_PULLUP); hdmitx_hpd_hw_op(HPD_INIT_SET_FILTER); @@ -4258,7 +4263,7 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) pr_info("topo: %d\n", hdmitx_hdcp_opr(0xe)); return; } else if (strncmp(tmpbuf, "dumphdmireg", 11) == 0) { - unsigned char reg_val = 0; + unsigned int reg_val = 0; unsigned int reg_adr = 0; #define DUMP_HDMITX_SECTION(a, b) \ @@ -4283,8 +4288,10 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) HDMITX_TOP_SEC_SCRATCH); DUMP_HDMITX_SECTION(HDMITX_DWC_DESIGN_ID, HDMITX_DWC_A_KSVMEMCTRL); +#if 0 DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCP_BSTATUS_0, HDMITX_DWC_HDCP_REVOC_LIST_END); +#endif DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCPREG_BKSV0, HDMITX_DWC_HDCPREG_BKSV4); DUMP_HDMITX_SECTION(HDMITX_DWC_HDCPREG_ANCONF, @@ -4851,6 +4858,7 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd, break; case DDC_HDCP_MUX_INIT: if (argv == 2) { + hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); hdmitx_ddc_hw_op(DDC_MUX_DDC); hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1); udelay(5); From 5e25e10f76f324dc309ac14f60ccc66566eea9df Mon Sep 17 00:00:00 2001 From: Dongjin Kim Date: Fri, 3 May 2019 16:26:27 +0900 Subject: [PATCH 0450/1060] ODROID-N2: media_modules: rebased with new BSP 20190415 Change-Id: I43c457bd241b2438c05df820545ed500266e56ea Signed-off-by: Dongjin Kim --- drivers/amlogic/media_modules/Makefile | 1 + .../media_modules/amvdec_ports/Makefile | 11 + .../amvdec_ports/aml_vcodec_adapt.c | 720 +++++ .../amvdec_ports/aml_vcodec_adapt.h | 65 + .../amvdec_ports/aml_vcodec_dec.c | 1837 +++++++++++ .../amvdec_ports/aml_vcodec_dec.h | 109 + .../amvdec_ports/aml_vcodec_dec_drv.c | 345 ++ .../amvdec_ports/aml_vcodec_dec_pm.c | 206 ++ .../amvdec_ports/aml_vcodec_dec_pm.h | 34 + .../amvdec_ports/aml_vcodec_drv.h | 428 +++ .../amvdec_ports/aml_vcodec_util.c | 122 + .../amvdec_ports/aml_vcodec_util.h | 94 + .../amvdec_ports/aml_vcodec_vfm.c | 205 ++ .../amvdec_ports/aml_vcodec_vfm.h | 57 + .../amvdec_ports/aml_vcodec_vfq.h | 112 + .../amvdec_ports/decoder/h264_parse.c | 389 +++ .../amvdec_ports/decoder/h264_parse.h | 141 + .../amvdec_ports/decoder/h264_stream.c | 111 + .../amvdec_ports/decoder/h264_stream.h | 39 + .../amvdec_ports/decoder/utils.h | 31 + .../amvdec_ports/decoder/vdec_h264_if.c | 736 +++++ .../amvdec_ports/test/Android.mk | 23 + .../amvdec_ports/test/vcodec_m2m_test.c | 292 ++ .../amvdec_ports/vdec_drv_base.h | 64 + .../media_modules/amvdec_ports/vdec_drv_if.c | 138 + .../media_modules/amvdec_ports/vdec_drv_if.h | 110 + .../media_modules/common/chips/chips.c | 38 +- .../common/chips/decoder_cpu_ver_info.c | 161 + .../common/chips/decoder_cpu_ver_info.h | 55 + .../common/firmware/firmware_cfg.h | 6 +- .../common/firmware/firmware_drv.c | 95 +- .../common/firmware/firmware_priv.h | 3 +- .../common/firmware/firmware_type.c | 47 +- .../common/firmware/firmware_type.h | 23 +- .../media_modules/common/media_clock/Makefile | 1 + .../common/media_clock/clk/clk.c | 9 +- .../common/media_clock/clk/clk.h | 2 +- .../common/media_clock/clk/clkg12.c | 57 +- .../common/media_clock/switch/amports_gate.c | 5 - .../frame_provider/decoder/avs/avs.c | 195 +- .../frame_provider/decoder/avs/avs.h | 19 + .../frame_provider/decoder/avs/avsp_trans.c | 19 + .../frame_provider/decoder/avs2/avs2_bufmgr.c | 133 +- .../frame_provider/decoder/avs2/avs2_global.h | 29 +- .../frame_provider/decoder/avs2/vavs2.c | 2651 ++++++++++++--- .../frame_provider/decoder/h264/vh264.c | 1487 ++++++++- .../frame_provider/decoder/h264/vh264_4k2k.c | 45 +- .../frame_provider/decoder/h264/vh264_mvc.c | 57 +- .../decoder/h264_multi/h264_dpb.c | 183 +- .../decoder/h264_multi/h264_dpb.h | 92 + .../decoder/h264_multi/vmh264.c | 2697 +++++++++++++--- .../frame_provider/decoder/h265/vh265.c | 2417 ++++++++++++-- .../frame_provider/decoder/mjpeg/vmjpeg.c | 25 +- .../decoder/mjpeg/vmjpeg_multi.c | 604 +++- .../frame_provider/decoder/mpeg12/Makefile | 3 + .../frame_provider/decoder/mpeg12/vmpeg12.c | 112 +- .../decoder/mpeg12/vmpeg12_multi.c | 2854 +++++++++++++++++ .../frame_provider/decoder/mpeg4/vmpeg4.c | 107 +- .../decoder/mpeg4/vmpeg4_multi.c | 1142 +++++-- .../frame_provider/decoder/real/vreal.c | 22 +- .../frame_provider/decoder/utils/Makefile | 3 + .../decoder/utils/amlogic_fbc_hook.c | 104 + .../decoder/utils/amlogic_fbc_hook.h | 55 + .../decoder/utils/amstream_profile.c | 54 + .../frame_provider/decoder/utils/amvdec.c | 142 +- .../frame_provider/decoder/utils/amvdec.h | 9 +- .../decoder/utils/decoder_bmmu_box.c | 60 +- .../decoder/utils/decoder_mmu_box.c | 19 +- .../decoder/utils/decoder_mmu_box.h | 2 + .../frame_provider/decoder/utils/firmware.h | 20 + .../decoder/utils/frame_check.c | 1161 +++++++ .../decoder/utils/frame_check.h | 111 + .../frame_provider/decoder/utils/secprot.c | 32 + .../frame_provider/decoder/utils/secprot.h | 2 +- .../frame_provider/decoder/utils/vdec.c | 1249 +++++++- .../frame_provider/decoder/utils/vdec.h | 39 +- .../frame_provider/decoder/utils/vdec_input.c | 460 ++- .../frame_provider/decoder/utils/vdec_input.h | 11 + .../decoder/utils/vdec_profile.c | 223 +- .../frame_provider/decoder/vc1/vvc1.c | 76 +- .../frame_provider/decoder/vp9/vvp9.c | 1604 ++++----- .../frame_provider/decoder/vp9/vvp9.h | 2 +- .../frame_sink/encoder/h264/encoder.c | 49 +- .../frame_sink/encoder/h264/encoder.h | 3 + .../frame_sink/encoder/h265/vmm.h | 2 +- .../frame_sink/encoder/h265/vpu.c | 267 +- .../frame_sink/encoder/h265/vpu.h | 4 + .../media_modules/stream_input/Makefile | 8 +- .../stream_input/amports/Makefile | 2 +- .../media_modules/stream_input/amports/adec.c | 49 +- .../stream_input/amports/amports_priv.h | 2 + .../stream_input/amports/amstream.c | 387 ++- .../stream_input/parser/esparser.c | 51 +- .../stream_input/parser/hw_demux/Makefile | 2 +- .../parser/hw_demux/aml_demod_gt.h | 55 +- .../stream_input/parser/hw_demux/aml_dmx.c | 992 ++++-- .../stream_input/parser/hw_demux/aml_dvb.c | 714 ++++- .../stream_input/parser/hw_demux/aml_dvb.h | 77 +- .../parser/hw_demux/aml_dvb_reg.h | 8 +- .../parser/hw_demux/c_stb_define.h | 66 +- .../parser/hw_demux/c_stb_regs_define.h | 45 + .../parser/hw_demux/dvb_ci/Makefile | 16 +- .../parser/hw_demux/dvb_ci/aml_ci.c | 456 ++- .../parser/hw_demux/dvb_ci/aml_ci.h | 66 +- .../parser/hw_demux/dvb_ci/aml_pcmcia.c | 7 +- .../parser/hw_demux/dvb_ci/aml_pcmcia.h | 19 + .../parser/hw_demux/dvb_ci/aml_spi.c | 723 +++-- .../parser/hw_demux/dvb_ci/aml_spi.h | 8 +- .../parser/hw_demux/dvb_ci/cimax/aml_cimax.c | 279 ++ .../parser/hw_demux/dvb_ci/cimax/aml_cimax.h | 61 + .../hw_demux/dvb_ci/cimax/aml_cimax_spi.c | 2139 ++++++++++++ .../hw_demux/dvb_ci/cimax/aml_cimax_spi.h | 20 + .../hw_demux/dvb_ci/cimax/aml_cimax_usb.c | 1714 ++++++++++ .../hw_demux/dvb_ci/cimax/aml_cimax_usb.h | 20 + .../dvb_ci/cimax/aml_cimax_usb_priv.h | 22 + .../dvb_ci/cimax/dvb_ca_en50221_cimax.c | 1910 +++++++++++ .../dvb_ci/cimax/dvb_ca_en50221_cimax.h | 144 + .../hw_demux/dvb_ci/cimax/dvb_ringbuffer.c | 381 +++ .../hw_demux/dvb_ci/cimax/dvb_ringbuffer.h | 280 ++ .../parser/hw_demux/dvb_ci/cimax/dvbdev.c | 968 ++++++ .../parser/hw_demux/dvb_ci/cimax/dvbdev.h | 299 ++ .../hw_demux/dvb_ci/cimax/usb/COPYING.LESSER | 499 +++ .../hw_demux/dvb_ci/cimax/usb/README.txt | 61 + .../dvb_ci/cimax/usb/SRC/99-cimax+usb.rules | 4 + .../hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt | 85 + .../hw_demux/dvb_ci/cimax/usb/SRC/Makefile | 35 + .../hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h | 424 +++ .../dvb_ci/cimax/usb/SRC/cimax+usb-driver.c | 2535 +++++++++++++++ .../dvb_ci/cimax/usb/SRC/cimax+usb-driver.h | 362 +++ .../dvb_ci/cimax/usb/SRC/cimax+usb_config.c | 684 ++++ .../dvb_ci/cimax/usb/SRC/cimax+usb_config.h | 58 + .../dvb_ci/cimax/usb/SRC/cimax+usb_fw.c | 325 ++ .../dvb_ci/cimax/usb/SRC/cimax+usb_fw.h | 61 + .../dvb_ci/cimax/usb/SRC/cimax+usb_handle.h | 46 + .../dvb_ci/cimax/usb/SRC/cimax+usb_time.c | 130 + .../dvb_ci/cimax/usb/SRC/cimax+usb_time.h | 92 + .../dvb_ci/cimax/usb/firmware/cimax+usb.cfg | 97 + .../cimax/usb/firmware/cimax+usb_ms.cfg | 136 + .../stream_input/parser/psparser.c | 10 +- .../stream_input/parser/streambuf.c | 3 + .../stream_input/parser/streambuf.h | 4 +- .../stream_input/parser/thread_rw.c | 17 +- .../stream_input/parser/thread_rw.h | 3 +- .../stream_input/parser/tsdemux.c | 23 +- .../stream_input/subtitle/subtitle.c | 715 +++++ .../stream_input/subtitle/subtitle.h | 24 + .../stream_input/tv_frontend/aml_fe.c | 27 +- .../stream_input/tv_frontend/aml_fe.h | 25 +- .../tv_frontend/dtv_demod/aml_demod.c | 19 + .../tv_frontend/dtv_demod/demod_func.c | 19 + .../tv_frontend/dtv_demod/dvbc_func.c | 19 + .../tv_frontend/dtv_demod/dvbt_func.c | 19 + .../tv_frontend/dtv_demod/i2c_func.c | 19 + .../include/acf_filter_coefficient.h | 19 + .../dtv_demod/include/addr_dtmb_che.h | 19 + .../dtv_demod/include/addr_dtmb_che_bit.h | 19 + .../dtv_demod/include/addr_dtmb_front.h | 19 + .../dtv_demod/include/addr_dtmb_front_bit.h | 19 + .../dtv_demod/include/addr_dtmb_sync.h | 19 + .../dtv_demod/include/addr_dtmb_sync_bit.h | 19 + .../dtv_demod/include/addr_dtmb_top.h | 19 + .../dtv_demod/include/addr_dtmb_top_bit.h | 19 + .../dtv_demod/include/aml_dtv_demod_reg.h | 19 + .../dtv_demod/include/amlfrontend.h | 20 + .../dtv_demod/include/demod_func.h | 19 + .../tv_frontend/dtv_demod/tuner_func.c | 19 + firmware/video/video_ucode.bin | Bin 768768 -> 1671680 bytes firmware/video_ucode.bin | Bin 768768 -> 1671680 bytes 168 files changed, 42004 insertions(+), 4392 deletions(-) create mode 100644 drivers/amlogic/media_modules/amvdec_ports/Makefile create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/test/Android.mk create mode 100644 drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h create mode 100644 drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c create mode 100644 drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h create mode 100644 drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c create mode 100644 drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg create mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg create mode 100644 drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c create mode 100644 drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h diff --git a/drivers/amlogic/media_modules/Makefile b/drivers/amlogic/media_modules/Makefile index f2a514848876..018c8feff897 100644 --- a/drivers/amlogic/media_modules/Makefile +++ b/drivers/amlogic/media_modules/Makefile @@ -2,3 +2,4 @@ obj-y += common/ obj-y += frame_provider/ obj-y += frame_sink/ obj-y += stream_input/ +obj-y += amvdec_ports/ diff --git a/drivers/amlogic/media_modules/amvdec_ports/Makefile b/drivers/amlogic/media_modules/amvdec_ports/Makefile new file mode 100644 index 000000000000..5ce0a7fcc114 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/Makefile @@ -0,0 +1,11 @@ +obj-m += amvdec_ports.o +amvdec_ports-objs += aml_vcodec_dec_drv.o +amvdec_ports-objs += aml_vcodec_dec.o +amvdec_ports-objs += aml_vcodec_dec_pm.o +amvdec_ports-objs += aml_vcodec_util.o +amvdec_ports-objs += aml_vcodec_adapt.o +amvdec_ports-objs += aml_vcodec_vfm.o +amvdec_ports-objs += vdec_drv_if.o +amvdec_ports-objs += decoder/vdec_h264_if.o +amvdec_ports-objs += decoder/h264_parse.o +amvdec_ports-objs += decoder/h264_stream.o diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c new file mode 100644 index 000000000000..5a3f71b7016e --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c @@ -0,0 +1,720 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../stream_input/amports/adec.h" +#include "../stream_input/parser/streambuf.h" +#include "../stream_input/parser/streambuf_reg.h" +#include "../stream_input/parser/tsdemux.h" +#include "../stream_input/parser/psparser.h" +#include "../stream_input/parser/esparser.h" +#include "../frame_provider/decoder/utils/vdec.h" +#include "../common/media_clock/switch/amports_gate.h" +#include +#include "aml_vcodec_adapt.h" +#include + +#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) +#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) +#define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2) +#define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256) + +#define PTS_OUTSIDE (1) +#define SYNC_OUTSIDE (2) +#define USE_V4L_PORTS (0x80) + +//#define DATA_DEBUG + +static int def_4k_vstreambuf_sizeM = + (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); +static int def_vstreambuf_sizeM = + (DEFAULT_VIDEO_BUFFER_SIZE >> 20); + +static int slow_input = 0; + +static int use_bufferlevelx10000 = 10000; +static unsigned int amstream_buf_num = BUF_MAX_NUM; + +static struct stream_buf_s bufs[BUF_MAX_NUM] = { + { + .reg_base = VLD_MEM_VIFIFO_REG_BASE, + .type = BUF_TYPE_VIDEO, + .buf_start = 0, + .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, + .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = AIU_MEM_AIFIFO_REG_BASE, + .type = BUF_TYPE_AUDIO, + .buf_start = 0, + .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, + .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = 0, + .type = BUF_TYPE_SUBTITLE, + .buf_start = 0, + .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, + .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = 0, + .type = BUF_TYPE_USERDATA, + .buf_start = 0, + .buf_size = 0, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = HEVC_STREAM_REG_BASE, + .type = BUF_TYPE_HEVC, + .buf_start = 0, + .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, + .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, + .first_tstamp = INVALID_PTS + }, +}; + +static void set_cfg_info(struct aml_vdec_adapt *vdec) +{ + unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); + + vdec->port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_FRAME/* | PORT_TYPE_ES*/); + vdec->port.flag |= PORT_FLAG_VFORMAT; + vdec->dec_prop.format = vdec->format; + vdec->dec_prop.width = 1920; + vdec->dec_prop.height = 1080; + vdec->dec_prop.rate = 3200; + vdec->dec_prop.param = (void *)sync_mode; +} + +static void set_vdec_mode(struct vdec_s *vdec) +{ + //vdec->type = VDEC_TYPE_SINGLE; + vdec->type = VDEC_TYPE_FRAME_BLOCK; +} + +static void set_vdec_vfm(struct vdec_s *vdec) +{ + vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO; +} + +static int enable_hardware(struct stream_port_s *port) +{ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) + return -1; + + amports_switch_gate("demux", 1); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + amports_switch_gate("parser_top", 1); + + if (port->type & PORT_TYPE_VIDEO) { + amports_switch_gate("vdec", 1); + + if (has_hevc_vdec()) { + if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) + vdec_poweron(VDEC_HEVC); + + if ((port->type & PORT_TYPE_HEVC) == 0) + vdec_poweron(VDEC_1); + } else { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + vdec_poweron(VDEC_1); + } + } + + return 0; +} + +static int disable_hardware(struct stream_port_s *port) +{ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) + return -1; + + if ((port->type & PORT_TYPE_VIDEO) + && get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { +#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + if (has_hevc_vdec()) + vdec_poweroff(VDEC_HEVC); + + vdec_poweroff(VDEC_1); +#else + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + && port->vformat == VFORMAT_H264 + && bufs[BUF_TYPE_VIDEO].for_4k) + vdec_poweroff(VDEC_HEVC); + + if ((port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9)) + vdec_poweroff(VDEC_HEVC); + else + vdec_poweroff(VDEC_1); +#endif + amports_switch_gate("vdec", 0); + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + amports_switch_gate("parser_top", 0); + + amports_switch_gate("demux", 0); + + return 0; +} + +static int reset_canuse_buferlevel(int levelx10000) +{ + int i; + struct stream_buf_s *p = NULL; + + if (levelx10000 >= 0 && levelx10000 <= 10000) + use_bufferlevelx10000 = levelx10000; + else + use_bufferlevelx10000 = 10000; + for (i = 0; i < amstream_buf_num; i++) { + p = &bufs[i]; + p->canusebuf_size = ((p->buf_size / 1024) * + use_bufferlevelx10000 / 10000) * 1024; + p->canusebuf_size += 1023; + p->canusebuf_size &= ~1023; + + if (p->canusebuf_size > p->buf_size) + p->canusebuf_size = p->buf_size; + } + + return 0; +} + +static void change_vbufsize(struct vdec_s *vdec, + struct stream_buf_s *pvbuf) +{ + if (pvbuf->buf_start != 0) { + pr_info("streambuf is alloced before\n"); + return; + } + + if (pvbuf->for_4k) { + pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M; + + if (vdec->port_flag & PORT_FLAG_DRM) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP; + + if ((pvbuf->buf_size > 30 * SZ_1M) + && (codec_mm_get_total_size() < 220 * SZ_1M)) { + /*if less than 250M, used 20M for 4K & 265*/ + pvbuf->buf_size = pvbuf->buf_size >> 1; + } + } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { + if (vdec->port_flag & PORT_FLAG_DRM) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; + } else { + pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; + if (vdec->port_flag & PORT_FLAG_DRM) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; + } + + reset_canuse_buferlevel(10000); +} + +static void user_buffer_init(void) +{ + struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA]; + + pubuf->buf_size = 0; + pubuf->buf_start = 0; + pubuf->buf_wp = 0; + pubuf->buf_rp = 0; +} + +static void audio_component_release(struct stream_port_s *port, + struct stream_buf_s *pbuf, int release_num) +{ + switch (release_num) { + default: + case 0: + case 4: + esparser_release(pbuf); + case 3: + adec_release(port->vformat); + case 2: + stbuf_release(pbuf, false); + case 1: + ; + } +} + +static int audio_component_init(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int r; + + if ((port->flag & PORT_FLAG_AFORMAT) == 0) { + pr_err("aformat not set\n"); + return 0; + } + + r = stbuf_init(pbuf, NULL, false); + if (r < 0) + return r; + + r = adec_init(port); + if (r < 0) { + audio_component_release(port, pbuf, 2); + return r; + } + + if (port->type & PORT_TYPE_ES) { + r = esparser_init(pbuf, NULL); + if (r < 0) { + audio_component_release(port, pbuf, 3); + return r; + } + } + + pbuf->flag |= BUF_FLAG_IN_USE; + + return 0; +} + +static void video_component_release(struct stream_port_s *port, +struct stream_buf_s *pbuf, int release_num) +{ + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; + + struct vdec_s *slave = NULL; + bool is_multidec = !vdec_single(vdec); + + switch (release_num) { + default: + case 0: + case 4: { + if ((port->type & PORT_TYPE_FRAME) == 0) + esparser_release(pbuf); + } + + case 3: { + if (vdec->slave) + slave = vdec->slave; + vdec_release(vdec); + + if (slave) + vdec_release(slave); + vdec = NULL; + } + + case 2: { + if ((port->type & PORT_TYPE_FRAME) == 0) + stbuf_release(pbuf, is_multidec); + } + + case 1: + ; + } +} + +static int video_component_init(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int ret = -1; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; + + if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { + pr_err("vformat not set\n"); + return -EPERM; + } + + if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088 + || port->vformat == VFORMAT_H264_4K2K) { + pbuf->for_4k = 1; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + && port->vformat == VFORMAT_H264) + vdec_poweron(VDEC_HEVC); + } else + pbuf->for_4k = 0; + + if (port->type & PORT_TYPE_FRAME) { + ret = vdec_init(vdec, pbuf->for_4k); + if (ret < 0) { + pr_err("video_component_init %d, failed\n", __LINE__); + video_component_release(port, pbuf, 2); + return ret; + } + + return 0; + } + + change_vbufsize(vdec, pbuf); + + if (has_hevc_vdec()) { + if (port->type & PORT_TYPE_MPTS) { + if (pbuf->type == BUF_TYPE_HEVC) + vdec_poweroff(VDEC_1); + else + vdec_poweroff(VDEC_HEVC); + } + } + + ret = stbuf_init(pbuf, vdec, false); + if (ret < 0) { + pr_err("video_component_init %d, stbuf_init failed\n", __LINE__); + return ret; + } + + /* todo: set path based on port flag */ + ret = vdec_init(vdec, pbuf->for_4k); + if (ret < 0) { + pr_err("video_component_init %d, vdec_init failed\n", __LINE__); + video_component_release(port, pbuf, 2); + return ret; + } + + if (vdec_dual(vdec)) { + ret = vdec_init(vdec->slave, pbuf->for_4k); + if (ret < 0) { + pr_err("video_component_init %d, vdec_init failed\n", + __LINE__); + video_component_release(port, pbuf, 2); + return ret; + } + } + + if (port->type & PORT_TYPE_ES) { + ret = esparser_init(pbuf, vdec); + if (ret < 0) { + video_component_release(port, pbuf, 3); + pr_err("esparser_init() failed\n"); + return ret; + } + } + + pbuf->flag |= BUF_FLAG_IN_USE; + + vdec_connect(vdec); + + return 0; +} + +static int vdec_ports_release(struct stream_port_s *port) +{ + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; + + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + struct vdec_s *slave = NULL; + + if (has_hevc_vdec()) { + if (port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9) + pvbuf = &bufs[BUF_TYPE_HEVC]; + } + + if (port->type & PORT_TYPE_MPTS) { + tsync_pcr_stop(); + tsdemux_release(); + } + + if (port->type & PORT_TYPE_MPPS) + psparser_release(); + + if (port->type & PORT_TYPE_VIDEO) + video_component_release(port, pvbuf, 0); + + if (port->type & PORT_TYPE_AUDIO) + audio_component_release(port, pabuf, 0); + + if (port->type & PORT_TYPE_SUB) + //sub_port_release(port, psbuf); + + if (vdec) { + if (vdec->slave) + slave = vdec->slave; + + vdec_release(vdec); + + if (slave) + vdec_release(slave); + vdec = NULL; + } + + port->pcr_inited = 0; + port->flag = 0; + + return 0; +} + +static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) +{ + int ret = -1; + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + struct stream_port_s *port = &vdec_adapt->port; + struct vdec_s *vdec = NULL; + + /* create the vdec instance.*/ + vdec = vdec_create(port, NULL); + if (IS_ERR_OR_NULL(vdec)) + return -1; + + /* set v4l2 ctx */ + vdec->private = vdec_adapt->ctx; + + vdec_adapt->vdec = vdec; + vdec->sys_info = &vdec_adapt->dec_prop; + vdec->sys_info_store = vdec_adapt->dec_prop; + vdec->vf_receiver_name = vdec_adapt->recv_name; + + /* set video format and sys info */ + vdec_set_format(vdec, vdec_adapt->dec_prop.format); + set_vdec_mode(vdec); + set_vdec_vfm(vdec); + + stbuf_fetch_init(); + + user_buffer_init(); + + if ((port->type & PORT_TYPE_AUDIO) + && (port->flag & PORT_FLAG_AFORMAT)) { + ret = audio_component_init(port, pabuf); + if (ret < 0) { + pr_err("audio_component_init failed\n"); + goto error1; + } + } + + if ((port->type & PORT_TYPE_VIDEO) + && (vdec->port_flag & PORT_FLAG_VFORMAT)) { + pvbuf->for_4k = 0; + if (has_hevc_vdec()) { + if (port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9) + pvbuf = &bufs[BUF_TYPE_HEVC]; + } + + ret = video_component_init(port, pvbuf); + if (ret < 0) { + pr_err("video_component_init failed\n"); + goto error2; + } + } + + /* connect vdec at the end after all HW initialization */ + if ((port->type & PORT_TYPE_VIDEO) + && (vdec->port_flag & PORT_FLAG_VFORMAT)) + vdec_connect(vdec); + + return 0; + +//error3: + //video_component_release(port, pvbuf, 0); +error2: + audio_component_release(port, pabuf, 0); +error1: + return ret; +} + +int video_decoder_init(struct aml_vdec_adapt *vdec) +{ + int ret = -1; + + /* sets configure data */ + set_cfg_info(vdec); + + /* init hw and gate*/ + ret = enable_hardware(&vdec->port); + if (ret < 0) { + pr_info("enable hw fail.\n"); + goto out; + } + + /* init the buffer work space and connect vdec.*/ + ret = vdec_ports_init(vdec); + if (ret < 0) { + pr_info("vdec ports init fail.\n"); + goto out; + } +out: + return ret; +} + +int video_decoder_release(struct aml_vdec_adapt *vdec) +{ + int ret = -1; + struct stream_port_s *port = &vdec->port; + + ret = vdec_ports_release(port); + if (ret < 0) { + pr_info("vdec ports release fail.\n"); + goto out; + } + + /* disable gates */ + ret = disable_hardware(port); + if (ret < 0) { + pr_info("disable hw fail.\n"); + goto out; + } +out: + return ret; +} + +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count) +{ + int ret = -1; + int try_cnt = 100; + struct stream_port_s *port = &ada_ctx->port; + struct vdec_s *vdec = ada_ctx->vdec; + struct stream_buf_s *pbuf = NULL; + + if (has_hevc_vdec()) { + pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : + &bufs[BUF_TYPE_VIDEO]; + } else + pbuf = &bufs[BUF_TYPE_VIDEO]; + + /*if (!(port_get_inited(priv))) { + r = video_decoder_init(priv); + if (r < 0) + return r; + }*/ + + do { + if (vdec->port_flag & PORT_FLAG_DRM) + ret = drm_write(ada_ctx->filp, pbuf, buf, count); + else + ret = esparser_write(ada_ctx->filp, pbuf, buf, count); + } while (ret == -EAGAIN && try_cnt--); + + if (slow_input) { + pr_info("slow_input: es codec write size %x\n", ret); + msleep(10); + } + +#ifdef DATA_DEBUG + /* dump to file */ + //dump_write(vbuf, size); + //pr_info("vbuf: %p, size: %u, ret: %d\n", vbuf, size, ret); +#endif + + return ret; +} + +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + + if (vdec->input.have_frame_num > 8) + return 0; + else + return 1; +} + +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp) +{ + int ret = -1; + int try_cnt = 10; + struct vdec_s *vdec = ada_ctx->vdec; + + /* set timestamp */ + vdec_set_timestamp(vdec, timestamp); + + do { + ret = vdec_write_vframe(vdec, buf, count); + if (ret == -EAGAIN) { + /*vdec_input_level(&vdec->input);*/ + msleep(20); + } + } while (ret == -EAGAIN && try_cnt--); + + if (slow_input) { + pr_info("slow_input: frame codec write size %d\n", ret); + msleep(30); + } + +#ifdef DATA_DEBUG + /* dump to file */ + dump_write(buf, count); +#endif + aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + ada_ctx->ctx->id, buf, count, ret, crc32(0, buf, count)); + + return ret; +} + +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + + if (vdec) + vdec_set_eos(vdec, true); +} + +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + int ret = 0; + + if (vdec) { + vdec_set_eos(vdec, false); + ret = vdec_reset(vdec); + } + + return ret; +} + +bool is_input_ready(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + int state = VDEC_STATUS_UNINITIALIZED; + + if (vdec) { + state = vdec_get_status(vdec); + + if (state == VDEC_STATUS_CONNECTED + || state == VDEC_STATUS_ACTIVE) + return true; + } + + return false; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h new file mode 100644 index 000000000000..da4553f50970 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef VDEC_ADAPT_H +#define VDEC_ADAPT_H + +#include +#include +#include "../stream_input/parser/streambuf.h" +#include "aml_vcodec_drv.h" + +struct aml_vdec_adapt { + enum vformat_e format; + void *vsi; + int32_t failure; + uint32_t inst_addr; + unsigned int signaled; + struct aml_vcodec_ctx *ctx; + struct platform_device *dev; + wait_queue_head_t wq; + struct file *filp; + struct vdec_s *vdec; + struct stream_port_s port; + struct dec_sysinfo dec_prop; + char *recv_name; +}; + +int video_decoder_init(struct aml_vdec_adapt *ada_ctx); + +int video_decoder_release(struct aml_vdec_adapt *ada_ctx); + +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count); + +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp); + +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); + +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); + +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); + +extern void dump_write(const char __user *buf, size_t count); + +bool is_input_ready(struct aml_vdec_adapt *ada_ctx); + +#endif /* VDEC_ADAPT_H */ + diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c new file mode 100644 index 000000000000..20dd5d5346b4 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c @@ -0,0 +1,1837 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +//#include "aml_vcodec_intr.h" +#include "aml_vcodec_util.h" +#include "vdec_drv_if.h" +#include "aml_vcodec_dec_pm.h" +#include +#include +#include +#include "aml_vcodec_adapt.h" + +#include "aml_vcodec_vfm.h" + +#define OUT_FMT_IDX 0 +#define CAP_FMT_IDX 1//3 + +#define AML_VDEC_MIN_W 64U +#define AML_VDEC_MIN_H 64U +#define DFT_CFG_WIDTH AML_VDEC_MIN_W +#define DFT_CFG_HEIGHT AML_VDEC_MIN_H + +//#define USEC_PER_SEC 1000000 + +#define call_void_memop(vb, op, args...) \ + do { \ + if ((vb)->vb2_queue->mem_ops->op) \ + (vb)->vb2_queue->mem_ops->op(args); \ + } while (0) + +static struct aml_video_fmt aml_video_formats[] = { + { + .fourcc = V4L2_PIX_FMT_H264, + .type = AML_FMT_DEC, + .num_planes = 1, + }, +/* { + .fourcc = V4L2_PIX_FMT_VP8, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_VP9, + .type = AML_FMT_DEC, + .num_planes = 1, + },*/ + { + .fourcc = V4L2_PIX_FMT_NV12, + .type = AML_FMT_FRAME, + .num_planes = 2, + }, +}; + +static const struct aml_codec_framesizes aml_vdec_framesizes[] = { + { + .fourcc = V4L2_PIX_FMT_H264, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, + }, +/* { + .fourcc = V4L2_PIX_FMT_VP8, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, + }, + { + .fourcc = V4L2_PIX_FMT_VP9, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, + },*/ +}; + +#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(aml_vdec_framesizes) +#define NUM_FORMATS ARRAY_SIZE(aml_video_formats) + +static struct aml_video_fmt *aml_vdec_find_format(struct v4l2_format *f) +{ + struct aml_video_fmt *fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + fmt = &aml_video_formats[k]; + if (fmt->fourcc == f->fmt.pix_mp.pixelformat) + return fmt; + } + + return NULL; +} + +static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx, + enum v4l2_buf_type type) +{ + if (V4L2_TYPE_IS_OUTPUT(type)) + return &ctx->q_data[AML_Q_DATA_SRC]; + + return &ctx->q_data[AML_Q_DATA_DST]; +} + +static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) +{ + static const struct v4l2_event ev_src_ch = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = + V4L2_EVENT_SRC_CH_RESOLUTION, + }; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); +} + +static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) +{ + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + aml_decoder_flush(ctx->ada_ctx); +} + +static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) +{ + unsigned int dpbsize = 0; + int ret; + + if (vdec_if_get_param(ctx, + GET_PARAM_PIC_INFO, + &ctx->last_decoded_picinfo)) { + aml_v4l2_err("[%d] Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", + ctx->id); + return; + } + + if (ctx->last_decoded_picinfo.visible_width == 0 || + ctx->last_decoded_picinfo.visible_height == 0 || + ctx->last_decoded_picinfo.coded_width == 0 || + ctx->last_decoded_picinfo.coded_height == 0) { + aml_v4l2_err("Cannot get correct pic info"); + return; + } + + if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || + (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height)) + return; + + aml_v4l2_debug(4, + "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", + ctx->id, ctx->last_decoded_picinfo.visible_width, + ctx->last_decoded_picinfo.visible_height, + ctx->picinfo.visible_width, ctx->picinfo.visible_height, + ctx->last_decoded_picinfo.coded_width, + ctx->last_decoded_picinfo.coded_width); + + ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize); + if (dpbsize == 0) + aml_v4l2_err("[%d] Incorrect dpb size, ret=%d", ctx->id, ret); + + ctx->dpb_size = dpbsize; +} + +int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) +{ + struct vb2_buffer *dst_buf = NULL; + struct vdec_fb *pfb; + struct aml_video_dec_buf *dst_buf_info, *info; + struct vb2_v4l2_buffer *dst_vb2_v4l2; + int try_cnt = 10; + + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + do { + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + if (dst_buf) + break; + aml_v4l2_debug(3, "[%d] waitting enough dst buffers.", ctx->id); + msleep(20); + } while (try_cnt--); + + if (!dst_buf) + return -1; + + dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); + dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb); + + pfb = &dst_buf_info->frame_buffer; + //pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); + pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + pfb->base_y.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_y.dma_addr)); + pfb->base_y.size = ctx->picinfo.y_len_sz; + + //pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); + pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); + pfb->base_c.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_c.dma_addr)); + pfb->base_c.size = ctx->picinfo.c_len_sz; + pfb->status = FB_ST_NORMAL; + + aml_v4l2_debug(4, "[%d] id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx", + ctx->id, dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, + &pfb->base_c.dma_addr, pfb->base_y.size, pfb->base_c.size); + + //mutex_lock(&ctx->lock); + dst_buf_info->used = true; + //mutex_unlock(&ctx->lock); + + v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + *out_fb = pfb; + + info = container_of(pfb, struct aml_video_dec_buf, frame_buffer); + + return 0; +} +EXPORT_SYMBOL(get_fb_from_queue); + +int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) +{ + struct aml_video_dec_buf *dstbuf; + + pr_info("[%d] %s() [%d]\n", ctx->id, __func__, __LINE__); + + if (in_fb == NULL) { + aml_v4l2_debug(4, "[%d] No free frame buffer", ctx->id); + return -1; + } + + aml_v4l2_debug(4, "[%d] tmp_frame_addr = 0x%p", ctx->id, in_fb); + + dstbuf = container_of(in_fb, struct aml_video_dec_buf, frame_buffer); + + mutex_lock(&ctx->lock); + + if (!dstbuf->used) + goto out; + + aml_v4l2_debug(4, + "[%d] status=%x queue id=%d to rdy_queue", + ctx->id, in_fb->status, + dstbuf->vb.vb2_buf.index); + + v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb); + + dstbuf->used = false; +out: + mutex_unlock(&ctx->lock); + + return 0; + +} +EXPORT_SYMBOL(put_fb_to_queue); + +void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) +{ + int cnt; + struct aml_video_dec_buf *dstbuf = NULL; + struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; + + dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); + + aml_v4l2_debug(4,"%s() [%d], base_y: %zu, idx: %u\n", + __FUNCTION__, __LINE__, fb->base_y.size, dstbuf->vb.vb2_buf.index); + aml_v4l2_debug(4,"%s() [%d], base_c: %zu, idx: %u\n", + __FUNCTION__, __LINE__, fb->base_c.size, dstbuf->vb.vb2_buf.index); + + dstbuf->vb.vb2_buf.timestamp = vf->timestamp; + aml_v4l2_debug(4, "[%d] %s() [%d], timestamp: %llx", + ctx->id, __func__, __LINE__, vf->timestamp); + + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->base_y.bytes_used); + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->base_c.bytes_used); + + dstbuf->ready_to_display = true; + + aml_v4l2_debug(4, "[%d]status=%x queue id=%d to done_list %d", + ctx->id, fb->status, dstbuf->vb.vb2_buf.index, + dstbuf->queued_in_vb2); + + cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); + aml_v4l2_debug(4, "[%d] %s() [%d], owned_by_drv_count: %d", + ctx->id, __func__, __LINE__, cnt); + aml_v4l2_debug(4, "[%d] %s() [%d], y_va: %p, vf_h: %lx", + ctx->id, __func__, __LINE__, dstbuf->frame_buffer.base_y.va, + dstbuf->frame_buffer.vf_handle); + + if (vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { + dstbuf->lastframe = true; + dstbuf->vb.flags = V4L2_BUF_FLAG_LAST; + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); + ctx->has_receive_eos = true; + pr_info("[%d] recevie a empty frame.\n", ctx->id); + } + + v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHING && + ctx->has_receive_eos) { + ctx->state = AML_STATE_FLUSHED; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + ctx->decoded_frame_cnt++; +} + +static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) +{ + int ret = -1; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + + ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out); + if (ret) { + aml_v4l2_err("[%d] Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); + return -1; + } + + if (!*out) { + aml_v4l2_debug(4, "[%d] No display frame buffer", ctx->id); + return -1; + } + + return ret; +} + +static int is_vdec_ready(struct aml_vcodec_ctx *ctx) +{ + struct aml_vcodec_dev *dev = ctx->dev; + + if (!is_input_ready(ctx->ada_ctx)) { + pr_err("[%d] %s() the decoder intput has not ready.\n", + ctx->id, __func__); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + return 0; + } + + if (ctx->state == AML_STATE_PROBE) { + int buf_ready_num; + + /* is there enough dst bufs for decoding? */ + buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); + if (buf_ready_num < ctx->dpb_size) { + aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.\n", + ctx->id, buf_ready_num); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + v4l2_m2m_try_schedule(ctx->m2m_ctx); + msleep(60); + return 0; + } + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_PROBE) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + } + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_READY) { + ctx->state = AML_STATE_ACTIVE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + return 1; +} + +static void aml_vdec_worker(struct work_struct *work) +{ + struct aml_vcodec_ctx *ctx = + container_of(work, struct aml_vcodec_ctx, decode_work); + struct aml_vcodec_dev *dev = ctx->dev; + struct vb2_buffer *src_buf; + struct aml_vcodec_mem buf; + bool res_chg = false; + int ret; + struct aml_video_dec_buf *src_buf_info; + struct vb2_v4l2_buffer *src_vb2_v4l2; + + aml_v4l2_debug(4, "[%d] entry [%d] [%s]", ctx->id, __LINE__, __func__); + + aml_vdec_lock(ctx); + + if (ctx->state < AML_STATE_INIT || + ctx->state > AML_STATE_FLUSHED) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); + return; + } + + if (!is_vdec_ready(ctx)) { + pr_err("[%d] %s() the decoder has not ready.\n", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } + + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + if (src_buf == NULL) { + pr_err("[%d] src_buf empty!\n", ctx->id); + aml_vdec_unlock(ctx); + return; + } + + src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf); + src_buf_info = container_of(src_vb2_v4l2, struct aml_video_dec_buf, vb); + + if (src_buf_info->lastframe) { + //the empty data use to flushed the decoder. + aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id); + + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + + /* sets eos data for vdec input. */ + aml_vdec_flush_decoder(ctx); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_ACTIVE) { + ctx->state = AML_STATE_FLUSHING;// prepare flushing + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + aml_vdec_unlock(ctx); + return; + } + + buf.va = vb2_plane_vaddr(src_buf, 0); + buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); + //buf.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), buf.dma_addr)); + + buf.size = (size_t)src_buf->planes[0].bytesused; + if (!buf.va) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_v4l2_err("[%d] id=%d src_addr is NULL!!", + ctx->id, src_buf->index); + aml_vdec_unlock(ctx); + return; + } + aml_v4l2_debug(4, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", + ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); + + src_buf_info->used = true; + + //pr_err("%s() [%d], size: 0x%zx, crc: 0x%x\n", + //__func__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); + + /* pts = (time / 10e6) * (90k / fps) */ + aml_v4l2_debug(4, "[%d] %s() timestamp: 0x%llx", ctx->id , __func__, + src_buf->timestamp); + + ret = vdec_if_decode(ctx, &buf, src_buf->timestamp, &res_chg); + if (ret > 0) { + /* + * we only return src buffer with VB2_BUF_STATE_DONE + * when decode success without resolution change + */ + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); + } else if (ret == -EAGAIN) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); + return; + } else { + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + if (ret == -EIO) { + //mutex_lock(&ctx->lock); + src_buf_info->error = true; + //mutex_unlock(&ctx->lock); + } + v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); + } + + if (!ret && res_chg) { + if (0) aml_vdec_pic_info_update(ctx); + /* + * On encountering a resolution change in the stream. + * The driver must first process and decode all + * remaining buffers from before the resolution change + * point, so call flush decode here + */ + if (0) aml_vdec_flush_decoder(ctx); + /* + * After all buffers containing decoded frames from + * before the resolution change point ready to be + * dequeued on the CAPTURE queue, the driver sends a + * V4L2_EVENT_SOURCE_CHANGE event for source change + * type V4L2_EVENT_SRC_CH_RESOLUTION + */ + if (0) aml_vdec_queue_res_chg_event(ctx); + } + + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); +} + +static void aml_reset_worker(struct work_struct *work) +{ + struct aml_vcodec_ctx *ctx = + container_of(work, struct aml_vcodec_ctx, reset_work); + struct aml_video_dec_buf *buf = NULL; + + aml_vdec_lock(ctx); + + if (ctx->state == AML_STATE_ABORT) { + pr_err("[%d] %s() the decoder will be exited.\n", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } + + /* fast enque capture buffers. */ + list_for_each_entry(buf, &ctx->capture_list, node) { + if (buf->que_in_m2m) + v4l2_m2m_buf_queue(ctx->m2m_ctx, &buf->vb); + } + + if (aml_codec_reset(ctx->ada_ctx)) { + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_RESET) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + + v4l2_m2m_try_schedule(ctx->m2m_ctx); + } + mutex_unlock(&ctx->state_lock); + + aml_vdec_unlock(ctx); +} + +void try_to_capture(struct aml_vcodec_ctx *ctx) +{ + int ret = 0; + struct vdec_fb *fb = NULL; + + ret = get_display_buffer(ctx, &fb); + if (ret) { + aml_v4l2_debug(4, "[%d] %s() [%d], the que have no disp buf,ret: %d", + ctx->id, __func__, __LINE__, ret); + return; + } + + trans_vframe_to_user(ctx, fb); +} +EXPORT_SYMBOL_GPL(try_to_capture); + +static int vdec_thread(void *data) +{ + struct aml_vdec_thread *thread = + (struct aml_vdec_thread *) data; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *) thread->priv; + + for (;;) { + aml_v4l2_debug(3, "[%d] %s() state: %d", ctx->id, + __func__, ctx->state); + + if (down_interruptible(&thread->sem)) + break; + + if (thread->stop) + break; + + thread->func(ctx); + } + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + + return 0; +} + +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type) +{ + struct aml_vdec_thread *thread = NULL; + + list_for_each_entry(thread, &ctx->vdec_thread_list, node) { + if (thread->task == NULL) + continue; + + if (thread->type == type) + up(&thread->sem); + } +} +EXPORT_SYMBOL_GPL(aml_thread_notify); + +int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, + enum aml_thread_type type, const char *thread_name) +{ + struct aml_vdec_thread *thread; + int ret = 0; + + thread = kzalloc(sizeof(*thread), GFP_KERNEL); + if (thread == NULL) + return -ENOMEM; + + thread->type = type; + thread->func = func; + thread->priv = ctx; + sema_init(&thread->sem, 0); + + thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name); + if (IS_ERR(thread->task)) { + ret = PTR_ERR(thread->task); + thread->task = NULL; + goto err; + } + + list_add(&thread->node, &ctx->vdec_thread_list); + + return 0; + +err: + kfree(thread); + + return ret; +} +EXPORT_SYMBOL_GPL(aml_thread_start); + +void aml_thread_stop(struct aml_vcodec_ctx *ctx) +{ + struct aml_vdec_thread *thread = NULL; + + while (!list_empty(&ctx->vdec_thread_list)) { + thread = list_entry(ctx->vdec_thread_list.next, + struct aml_vdec_thread, node); + list_del(&thread->node); + thread->stop = true; + up(&thread->sem); + kthread_stop(thread->task); + thread->task = NULL; + kfree(thread); + } +} +EXPORT_SYMBOL_GPL(aml_thread_stop); + +static int vidioc_try_decoder_cmd(struct file *file, void *priv, + struct v4l2_decoder_cmd *cmd) +{ + switch (cmd->cmd) { + case V4L2_DEC_CMD_STOP: + case V4L2_DEC_CMD_START: + if (cmd->flags != 0) { + aml_v4l2_err("cmd->flags=%u", cmd->flags); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_decoder_cmd(struct file *file, void *priv, + struct v4l2_decoder_cmd *cmd) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct vb2_queue *src_vq, *dst_vq; + int ret; + + ret = vidioc_try_decoder_cmd(file, priv, cmd); + if (ret) + return ret; + + aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", + ctx->id, __func__, __LINE__, cmd->cmd); + dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + switch (cmd->cmd) { + case V4L2_DEC_CMD_STOP: + + if (ctx->state != AML_STATE_ACTIVE) + return 0; + + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!vb2_is_streaming(src_vq)) { + pr_err("[%d] Output stream is off. No need to flush.\n", ctx->id); + return 0; + } + + if (!vb2_is_streaming(dst_vq)) { + pr_err("[%d] Capture stream is off. No need to flush.\n", ctx->id); + return 0; + } + + /* flush src */ + v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); + v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention + + break; + + case V4L2_DEC_CMD_START: + aml_v4l2_debug(4, "[%d] CMD V4L2_DEC_CMD_START ", ctx->id); + vb2_clear_last_buffer_dequeued(dst_vq);//pay attention + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int vidioc_decoder_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct v4l2_fh *fh = file->private_data; + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + struct aml_vcodec_dev *dev = ctx->dev; + struct vb2_queue *q; + int ret = 0; + + ret = v4l2_m2m_ioctl_streamon(file, priv, i); + + q = v4l2_m2m_get_vq(fh->m2m_ctx, i); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHED) { + if (!V4L2_TYPE_IS_OUTPUT(q->type)) { + ctx->state = AML_STATE_RESET; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", + ctx->id, __func__); + queue_work(dev->reset_workqueue, &ctx->reset_work); + } + } + mutex_unlock(&ctx->state_lock); + + return ret; +} + +void aml_vdec_unlock(struct aml_vcodec_ctx *ctx) +{ + mutex_unlock(&ctx->dev->dec_mutex); +} + +void aml_vdec_lock(struct aml_vcodec_ctx *ctx) +{ + mutex_lock(&ctx->dev->dec_mutex); +} + +void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) +{ + aml_vdec_lock(ctx); + + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + + vdec_if_deinit(ctx); + + aml_vdec_unlock(ctx); +} + +void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) +{ + struct aml_q_data *q_data; + + ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex; + ctx->fh.m2m_ctx = ctx->m2m_ctx; + ctx->fh.ctrl_handler = &ctx->ctrl_hdl; + INIT_WORK(&ctx->decode_work, aml_vdec_worker); + INIT_WORK(&ctx->reset_work, aml_reset_worker); + ctx->colorspace = V4L2_COLORSPACE_REC709; + ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + ctx->quantization = V4L2_QUANTIZATION_DEFAULT; + ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; + ctx->dev->dec_capability = VCODEC_CAPABILITY_4K_DISABLED;//disable 4k + + q_data = &ctx->q_data[AML_Q_DATA_SRC]; + memset(q_data, 0, sizeof(struct aml_q_data)); + q_data->visible_width = DFT_CFG_WIDTH; + q_data->visible_height = DFT_CFG_HEIGHT; + q_data->fmt = &aml_video_formats[OUT_FMT_IDX]; + q_data->field = V4L2_FIELD_NONE; + + q_data->sizeimage[0] = (1024 * 1024);//DFT_CFG_WIDTH * DFT_CFG_HEIGHT; //1m + q_data->bytesperline[0] = 0; + + q_data = &ctx->q_data[AML_Q_DATA_DST]; + memset(q_data, 0, sizeof(struct aml_q_data)); + q_data->visible_width = DFT_CFG_WIDTH; + q_data->visible_height = DFT_CFG_HEIGHT; + q_data->coded_width = DFT_CFG_WIDTH; + q_data->coded_height = DFT_CFG_HEIGHT; + q_data->fmt = &aml_video_formats[CAP_FMT_IDX]; + q_data->field = V4L2_FIELD_NONE; + + v4l_bound_align_image(&q_data->coded_width, + AML_VDEC_MIN_W, + AML_VDEC_MAX_W, 4, + &q_data->coded_height, + AML_VDEC_MIN_H, + AML_VDEC_MAX_H, 5, 6); + + q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height; + q_data->bytesperline[0] = q_data->coded_width; + q_data->sizeimage[1] = q_data->sizeimage[0] / 2; + q_data->bytesperline[1] = q_data->coded_width; + + ctx->state = AML_STATE_IDLE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)", + ctx->id, __func__); +} + +static int vidioc_vdec_qbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (ctx->state == AML_STATE_ABORT) { + aml_v4l2_err("[%d] Call on QBUF after unrecoverable error", + ctx->id); + return -EIO; + } + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_vdec_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (ctx->state == AML_STATE_ABORT) { + aml_v4l2_err("[%d] Call on DQBUF after unrecoverable error", + ctx->id); + return -EIO; + } + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_vdec_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strlcpy(cap->driver, AML_VCODEC_DEC_NAME, sizeof(cap->driver)); + strlcpy(cap->bus_info, AML_PLATFORM_STR, sizeof(cap->bus_info)); + strlcpy(cap->card, AML_PLATFORM_STR, sizeof(cap->card)); + + return 0; +} + +static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(fh, sub, 2, NULL); + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_src_change_event_subscribe(fh, sub); + default: + return v4l2_ctrl_subscribe_event(fh, sub); + } +} + +static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt) +{ + struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + int i; + + pix_fmt_mp->field = V4L2_FIELD_NONE; + + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + pix_fmt_mp->num_planes = 1; + pix_fmt_mp->plane_fmt[0].bytesperline = 0; + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + int tmp_w, tmp_h; + + pix_fmt_mp->height = clamp(pix_fmt_mp->height, + AML_VDEC_MIN_H, + AML_VDEC_MAX_H); + pix_fmt_mp->width = clamp(pix_fmt_mp->width, + AML_VDEC_MIN_W, + AML_VDEC_MAX_W); + + /* + * Find next closer width align 64, heign align 64, size align + * 64 rectangle + * Note: This only get default value, the real HW needed value + * only available when ctx in AML_STATE_PROBE state + */ + tmp_w = pix_fmt_mp->width; + tmp_h = pix_fmt_mp->height; + v4l_bound_align_image(&pix_fmt_mp->width, + AML_VDEC_MIN_W, + AML_VDEC_MAX_W, 6, + &pix_fmt_mp->height, + AML_VDEC_MIN_H, + AML_VDEC_MAX_H, 6, 9); + + if (pix_fmt_mp->width < tmp_w && + (pix_fmt_mp->width + 64) <= AML_VDEC_MAX_W) + pix_fmt_mp->width += 64; + if (pix_fmt_mp->height < tmp_h && + (pix_fmt_mp->height + 64) <= AML_VDEC_MAX_H) + pix_fmt_mp->height += 64; + + aml_v4l2_debug(4, + "before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d", + tmp_w, tmp_h, pix_fmt_mp->width, + pix_fmt_mp->height, + pix_fmt_mp->width * pix_fmt_mp->height); + + pix_fmt_mp->num_planes = fmt->num_planes; + pix_fmt_mp->plane_fmt[0].sizeimage = + pix_fmt_mp->width * pix_fmt_mp->height; + pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width; + + if (pix_fmt_mp->num_planes == 2) { + pix_fmt_mp->plane_fmt[1].sizeimage = + (pix_fmt_mp->width * pix_fmt_mp->height) / 2; + pix_fmt_mp->plane_fmt[1].bytesperline = + pix_fmt_mp->width; + } + } + + for (i = 0; i < pix_fmt_mp->num_planes; i++) + memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0, + sizeof(pix_fmt_mp->plane_fmt[0].reserved)); + + pix_fmt_mp->flags = 0; + memset(&pix_fmt_mp->reserved, 0x0, sizeof(pix_fmt_mp->reserved)); + return 0; +} + +static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aml_video_fmt *fmt; + + fmt = aml_vdec_find_format(f); + if (!fmt) { + f->fmt.pix.pixelformat = aml_video_formats[CAP_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + struct aml_video_fmt *fmt; + + fmt = aml_vdec_find_format(f); + if (!fmt) { + f->fmt.pix.pixelformat = aml_video_formats[OUT_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } + + if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { + aml_v4l2_err("sizeimage of output format must be given"); + return -EINVAL; + } + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_vdec_g_selection(struct file *file, void *priv, + struct v4l2_selection *s) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct aml_q_data *q_data; + + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + q_data = &ctx->q_data[AML_Q_DATA_DST]; + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + s->r.left = 0; + s->r.top = 0; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; + break; + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + s->r.left = 0; + s->r.top = 0; + s->r.width = ctx->picinfo.coded_width; + s->r.height = ctx->picinfo.coded_height; + break; + case V4L2_SEL_TGT_COMPOSE: + if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) { + /* set to default value if header info not ready yet*/ + s->r.left = 0; + s->r.top = 0; + s->r.width = q_data->visible_width; + s->r.height = q_data->visible_height; + } + break; + default: + return -EINVAL; + } + + if (ctx->state < AML_STATE_PROBE) { + /* set to default value if header info not ready yet*/ + s->r.left = 0; + s->r.top = 0; + s->r.width = q_data->visible_width; + s->r.height = q_data->visible_height; + return 0; + } + + return 0; +} + +static int vidioc_vdec_s_selection(struct file *file, void *priv, + struct v4l2_selection *s) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE: + s->r.left = 0; + s->r.top = 0; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int vidioc_vdec_s_fmt(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct v4l2_pix_format_mplane *pix_mp; + struct aml_q_data *q_data; + int ret = 0; + struct aml_video_fmt *fmt; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + + q_data = aml_vdec_get_q_data(ctx, f->type); + if (!q_data) + return -EINVAL; + + pix_mp = &f->fmt.pix_mp; + if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && + vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) { + aml_v4l2_err("[%d] out_q_ctx buffers already requested", ctx->id); + } + + if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) { + aml_v4l2_err("[%d] cap_q_ctx buffers already requested", ctx->id); + } + + fmt = aml_vdec_find_format(f); + if (fmt == NULL) { + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + f->fmt.pix.pixelformat = + aml_video_formats[OUT_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + f->fmt.pix.pixelformat = + aml_video_formats[CAP_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } + } + + q_data->fmt = fmt; + vidioc_try_fmt(f, q_data->fmt); + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage; + q_data->coded_width = pix_mp->width; + q_data->coded_height = pix_mp->height; + + aml_v4l2_debug(4, "[%d] %s() [%d], w: %d, h: %d, size: %d", + ctx->id, __func__, __LINE__, pix_mp->width, pix_mp->height, + pix_mp->plane_fmt[0].sizeimage); + + ctx->colorspace = f->fmt.pix_mp.colorspace; + ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + ctx->quantization = f->fmt.pix_mp.quantization; + ctx->xfer_func = f->fmt.pix_mp.xfer_func; + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_IDLE) { + ret = vdec_if_init(ctx, q_data->fmt->fourcc); + if (ret) { + aml_v4l2_err("[%d]: vdec_if_init() fail ret=%d", + ctx->id, ret); + mutex_unlock(&ctx->state_lock); + return -EINVAL; + } + ctx->state = AML_STATE_INIT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + } + + return 0; +} + +static int vidioc_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + int i = 0; + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (fsize->index != 0) + return -EINVAL; + + for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) { + if (fsize->pixel_format != aml_vdec_framesizes[i].fourcc) + continue; + + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + fsize->stepwise = aml_vdec_framesizes[i].stepwise; + if (!(ctx->dev->dec_capability & + VCODEC_CAPABILITY_4K_DISABLED)) { + aml_v4l2_debug(4, "[%d] 4K is enabled", ctx->id); + fsize->stepwise.max_width = + VCODEC_DEC_4K_CODED_WIDTH; + fsize->stepwise.max_height = + VCODEC_DEC_4K_CODED_HEIGHT; + } + aml_v4l2_debug(4, "[%d] %x, %d %d %d %d %d %d", + ctx->id, ctx->dev->dec_capability, + fsize->stepwise.min_width, + fsize->stepwise.max_width, + fsize->stepwise.step_width, + fsize->stepwise.min_height, + fsize->stepwise.max_height, + fsize->stepwise.step_height); + return 0; + } + + return -EINVAL; +} + +static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue) +{ + struct aml_video_fmt *fmt; + int i, j = 0; + + for (i = 0; i < NUM_FORMATS; i++) { + if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC)) + continue; + if (!output_queue && + (aml_video_formats[i].type != AML_FMT_FRAME)) + continue; + + if (j == f->index) + break; + ++j; + } + + if (i == NUM_FORMATS) + return -EINVAL; + + fmt = &aml_video_formats[i]; + f->pixelformat = fmt->fourcc; + + return 0; +} + +static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, + struct v4l2_fmtdesc *f) +{ + return vidioc_enum_fmt(f, false); +} + +static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return vidioc_enum_fmt(f, true); +} + +static int vidioc_vdec_g_fmt(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + struct vb2_queue *vq; + struct aml_q_data *q_data; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) { + aml_v4l2_err("[%d] no vb2 queue for type=%d", ctx->id, f->type); + return -EINVAL; + } + + q_data = aml_vdec_get_q_data(ctx, f->type); + + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->colorspace = ctx->colorspace; + pix_mp->ycbcr_enc = ctx->ycbcr_enc; + pix_mp->quantization = ctx->quantization; + pix_mp->xfer_func = ctx->xfer_func; + + if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + (ctx->state >= AML_STATE_PROBE)) { + /* Until STREAMOFF is called on the CAPTURE queue + * (acknowledging the event), the driver operates as if + * the resolution hasn't changed yet. + * So we just return picinfo yet, and update picinfo in + * stop_streaming hook function + */ + /* it is used for alloc the decode buffer size. */ + q_data->sizeimage[0] = ctx->picinfo.y_len_sz; + q_data->sizeimage[1] = ctx->picinfo.c_len_sz; + + /* it is used for alloc the EGL image buffer size. */ + q_data->coded_width = ctx->picinfo.coded_width; + q_data->coded_height = ctx->picinfo.coded_height; + + q_data->bytesperline[0] = ctx->picinfo.coded_width; + q_data->bytesperline[1] = ctx->picinfo.coded_height; + + /* + * Width and height are set to the dimensions + * of the movie, the buffer is bigger and + * further processing stages should crop to this + * rectangle. + */ + pix_mp->width = q_data->coded_width; + pix_mp->height = q_data->coded_height; + + /* + * Set pixelformat to the format in which mt vcodec + * outputs the decoded frame + */ + pix_mp->num_planes = q_data->fmt->num_planes; + pix_mp->pixelformat = q_data->fmt->fourcc; + pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; + pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; + pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; + pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; + } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* + * This is run on OUTPUT + * The buffer contains compressed image + * so width and height have no meaning. + * Assign value here to pass v4l2-compliance test + */ + pix_mp->width = q_data->visible_width; + pix_mp->height = q_data->visible_height; + pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; + pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; + pix_mp->pixelformat = q_data->fmt->fourcc; + pix_mp->num_planes = q_data->fmt->num_planes; + } else { + pix_mp->width = q_data->coded_width; + pix_mp->height = q_data->coded_height; + pix_mp->num_planes = q_data->fmt->num_planes; + pix_mp->pixelformat = q_data->fmt->fourcc; + pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; + pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; + pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; + pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; + + aml_v4l2_debug(4, "[%d] type=%d state=%d Format information could not be read, not ready yet!", + ctx->id, f->type, ctx->state); + } + + return 0; +} + +/*int vidioc_vdec_g_ctrl(struct file *file, void *fh, + struct v4l2_control *a) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + + if (a->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) + a->value = 20; + + return 0; +}*/ + +static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, + unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vq); + struct aml_q_data *q_data; + unsigned int i; + + q_data = aml_vdec_get_q_data(ctx, vq->type); + + if (q_data == NULL) { + aml_v4l2_err("[%d] vq->type=%d err", ctx->id, vq->type); + return -EINVAL; + } + + if (*nplanes) { + for (i = 0; i < *nplanes; i++) { + if (sizes[i] < q_data->sizeimage[i]) + return -EINVAL; + //alloc_devs[i] = &ctx->dev->plat_dev->dev; + alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm + } + } else { + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + *nplanes = 2; + else + *nplanes = 1; + + for (i = 0; i < *nplanes; i++) { + sizes[i] = q_data->sizeimage[i]; + //alloc_devs[i] = &ctx->dev->plat_dev->dev; + alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm + } + } + + pr_info("[%d] type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", + ctx->id, vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]); + + return 0; +} + +static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct aml_q_data *q_data; + int i; + + aml_v4l2_debug(4, "[%d] (%d) id=%d", + ctx->id, vb->vb2_queue->type, vb->index); + + q_data = aml_vdec_get_q_data(ctx, vb->vb2_queue->type); + + for (i = 0; i < q_data->fmt->num_planes; i++) { + if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { + aml_v4l2_err("[%d] data will not fit into plane %d (%lu < %d)", + ctx->id, i, vb2_plane_size(vb, i), + q_data->sizeimage[i]); + } + } + + return 0; +} + +static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *buf = NULL; + struct aml_vcodec_mem src_mem; + unsigned int dpb = 0; + + vb2_v4l2 = to_vb2_v4l2_buffer(vb); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + + aml_v4l2_debug(3, "[%d] %s(), vb: %p, type: %d, idx: %d, state: %d, used: %d", + ctx->id, __func__, vb, vb->vb2_queue->type, + vb->index, vb->state, buf->used); + /* + * check if this buffer is ready to be used after decode + */ + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + aml_v4l2_debug(3, "[%d] %s() [%d], y_va: %p, vf_h: %lx, state: %d", ctx->id, + __func__, __LINE__, buf->frame_buffer.base_y.va, + buf->frame_buffer.vf_handle, buf->frame_buffer.status); + + if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { + aml_v4l2_debug(3, "[%d] enque capture buf idx %d, %p\n", + ctx->id, vb->index, vb); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); + buf->que_in_m2m = true; + buf->queued_in_vb2 = true; + buf->queued_in_v4l2 = true; + buf->ready_to_display = false; + + /*save capture bufs to be used for resetting config.*/ + list_add(&buf->node, &ctx->capture_list); + } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { + buf->queued_in_vb2 = false; + buf->queued_in_v4l2 = true; + buf->ready_to_display = false; + + /* recycle vf */ + video_vf_put(ctx->ada_ctx->recv_name, + &buf->frame_buffer, ctx->id); + } + return; + } + + v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); + + if (ctx->state != AML_STATE_INIT) { + aml_v4l2_debug(4, "[%d] already init driver %d", + ctx->id, ctx->state); + return; + } + + vb2_v4l2 = to_vb2_v4l2_buffer(vb); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + if (buf->lastframe) { + /* This shouldn't happen. Just in case. */ + aml_v4l2_err("[%d] Invalid flush buffer.", ctx->id); + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + return; + } + + src_mem.va = vb2_plane_vaddr(vb, 0); + src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + src_mem.size = (size_t)vb->planes[0].bytesused; + if (vdec_if_probe(ctx, &src_mem, NULL)) + return; + + if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) { + pr_err("[%d] GET_PARAM_PICTURE_INFO err\n", ctx->id); + return; + } + + if (vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpb)) { + pr_err("[%d] GET_PARAM_DPB_SIZE err\n", ctx->id); + return; + } + + ctx->dpb_size = dpb; + ctx->last_decoded_picinfo = ctx->picinfo; + aml_vdec_queue_res_chg_event(ctx); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_INIT) { + ctx->state = AML_STATE_PROBE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); +} + +static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *buf = NULL; + bool buf_error; + + vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + + //mutex_lock(&ctx->lock); + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + buf->queued_in_v4l2 = false; + buf->queued_in_vb2 = false; + } + buf_error = buf->error; + //mutex_unlock(&ctx->lock); + + if (buf_error) { + aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + } +} + +static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb, + struct vb2_v4l2_buffer, vb2_buf); + struct aml_video_dec_buf *buf = container_of(vb2_v4l2, + struct aml_video_dec_buf, vb); + unsigned int size, phy_addr = 0; + char *owner = __getname(); + + aml_v4l2_debug(4, "[%d] (%d) id=%d", + ctx->id, vb->vb2_queue->type, vb->index); + + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + buf->used = false; + buf->ready_to_display = false; + buf->queued_in_v4l2 = false; + buf->frame_buffer.status = FB_ST_NORMAL; + } else { + buf->lastframe = false; + } + + /* codec_mm buffers count */ + if (V4L2_TYPE_IS_OUTPUT(vb->type)) { + size = vb->planes[0].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] IN alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + } else { + size = vb->planes[0].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + + size = vb->planes[1].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + } + + __putname(owner); + + return 0; +} + +static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *buf = NULL; + int i; + + for (i = 0; i < q->num_buffers; ++i) { + vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + if (IS_ERR_OR_NULL(buf->mem[0])) + return; + + if (V4L2_TYPE_IS_OUTPUT(q->bufs[i]->type)) { + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + + aml_v4l2_debug(3, "[%d] IN clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + buf->mem[0] = NULL; + continue; + } + + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); + + aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); + buf->mem[0] = NULL; + buf->mem[1] = NULL; + } +} + +static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); + + ctx->has_receive_eos = false; + v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true); + + return 0; +} + +static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) +{ + struct aml_video_dec_buf *buf = NULL; + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); + int i; + + aml_v4l2_debug(3, "[%d] (%d) state=(%x) frame_cnt=%d", + ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt); + + codec_mm_bufs_cnt_clean(q); + + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + while (v4l2_m2m_src_buf_remove(ctx->m2m_ctx)); + return; + } + + while (v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)); + + for (i = 0; i < q->num_buffers; ++i) { + if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { + q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; + atomic_dec(&q->owned_by_drv_count); + } + vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + buf->frame_buffer.status = FB_ST_FREE; + } +} + +static void m2mops_vdec_device_run(void *priv) +{ + struct aml_vcodec_ctx *ctx = priv; + struct aml_vcodec_dev *dev = ctx->dev; + + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + queue_work(dev->decode_workqueue, &ctx->decode_work); +} + +void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) +{ + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + if (ctx->state < AML_STATE_ACTIVE || + ctx->state > AML_STATE_FLUSHED) + return; + + aml_thread_notify(ctx, AML_THREAD_CAPTURE); +} + +static int m2mops_vdec_job_ready(void *m2m_priv) +{ + struct aml_vcodec_ctx *ctx = m2m_priv; + + aml_v4l2_debug(4, "[%d] %s(), state: %d", ctx->id, + __func__, ctx->state); + + if (ctx->state < AML_STATE_PROBE || + ctx->state > AML_STATE_FLUSHED) + return 0; + + return 1; +} + +static void m2mops_vdec_job_abort(void *priv) +{ + struct aml_vcodec_ctx *ctx = priv; + + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + + wake_up(&ctx->m2m_ctx->finished); +} + +static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) +{ + struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl); + int ret = 0; + + aml_v4l2_debug(4, "%s() [%d]", __func__, __LINE__); + + switch (ctrl->id) { + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + if (ctx->state >= AML_STATE_PROBE) { + ctrl->val = ctx->dpb_size; + } else { + pr_err("Seqinfo not ready.\n"); + ctrl->val = 0; + } + break; + default: + ret = -EINVAL; + } + return ret; +} + +static const struct v4l2_ctrl_ops aml_vcodec_dec_ctrl_ops = { + .g_volatile_ctrl = aml_vdec_g_v_ctrl, +}; + +int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx) +{ + struct v4l2_ctrl *ctrl; + + v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1); + + ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl, + &aml_vcodec_dec_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, + 0, 32, 1, 1); + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; + + if (ctx->ctrl_hdl.error) { + aml_v4l2_err("[%d] Adding control failed %d", + ctx->id, ctx->ctrl_hdl.error); + return ctx->ctrl_hdl.error; + } + + v4l2_ctrl_handler_setup(&ctx->ctrl_hdl); + return 0; +} + +static void m2mops_vdec_lock(void *m2m_priv) +{ + struct aml_vcodec_ctx *ctx = m2m_priv; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + mutex_lock(&ctx->dev->dev_mutex); +} + +static void m2mops_vdec_unlock(void *m2m_priv) +{ + struct aml_vcodec_ctx *ctx = m2m_priv; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + mutex_unlock(&ctx->dev->dev_mutex); +} + +const struct v4l2_m2m_ops aml_vdec_m2m_ops = { + .device_run = m2mops_vdec_device_run, + .job_ready = m2mops_vdec_job_ready, + .job_abort = m2mops_vdec_job_abort, + .lock = m2mops_vdec_lock, + .unlock = m2mops_vdec_unlock, +}; + +static const struct vb2_ops aml_vdec_vb2_ops = { + .queue_setup = vb2ops_vdec_queue_setup, + .buf_prepare = vb2ops_vdec_buf_prepare, + .buf_queue = vb2ops_vdec_buf_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .buf_init = vb2ops_vdec_buf_init, + .buf_finish = vb2ops_vdec_buf_finish, + .start_streaming = vb2ops_vdec_start_streaming, + .stop_streaming = vb2ops_vdec_stop_streaming, +}; + +const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = { + .vidioc_streamon = vidioc_decoder_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//?? + //.vidioc_g_ctrl = vidioc_vdec_g_ctrl, + + .vidioc_qbuf = vidioc_vdec_qbuf, + .vidioc_dqbuf = vidioc_vdec_dqbuf, + + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out_mplane, + + .vidioc_s_fmt_vid_cap_mplane = vidioc_vdec_s_fmt, + .vidioc_s_fmt_vid_out_mplane = vidioc_vdec_s_fmt, + .vidioc_g_fmt_vid_cap_mplane = vidioc_vdec_g_fmt, + .vidioc_g_fmt_vid_out_mplane = vidioc_vdec_g_fmt, + + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + + .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane, + .vidioc_enum_framesizes = vidioc_enum_framesizes, + + .vidioc_querycap = vidioc_vdec_querycap, + .vidioc_subscribe_event = vidioc_vdec_subscribe_evt, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_selection = vidioc_vdec_g_selection, + .vidioc_s_selection = vidioc_vdec_s_selection, + + .vidioc_decoder_cmd = vidioc_decoder_cmd, + .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd, +}; + +int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct aml_vcodec_ctx *ctx = priv; + int ret = 0; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_DMABUF | VB2_MMAP; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); + src_vq->ops = &aml_vdec_vb2_ops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->dev->dev_mutex; + + ret = vb2_queue_init(src_vq); + if (ret) { + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(output)", ctx->id); + return ret; + } + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); + dst_vq->ops = &aml_vdec_vb2_ops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->dev->dev_mutex; + + ret = vb2_queue_init(dst_vq); + if (ret) { + vb2_queue_release(src_vq); + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(capture)", ctx->id); + } + + return ret; +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h new file mode 100644 index 000000000000..6f884c4321ed --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h @@ -0,0 +1,109 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _AML_VCODEC_DEC_H_ +#define _AML_VCODEC_DEC_H_ + +#include +#include +#include + +#define VCODEC_CAPABILITY_4K_DISABLED 0x10 +#define VCODEC_DEC_4K_CODED_WIDTH 4096U +#define VCODEC_DEC_4K_CODED_HEIGHT 2304U +#define AML_VDEC_MAX_W 2048U +#define AML_VDEC_MAX_H 1088U + +#define AML_VDEC_IRQ_STATUS_DEC_SUCCESS 0x10000 +#define V4L2_BUF_FLAG_LAST 0x00100000 + +/** + * struct vdec_fb - decoder frame buffer + * @base_y : Y plane memory info + * @base_c : C plane memory info + * @status : frame buffer status (vdec_fb_status) + */ +struct vdec_fb { + unsigned long vf_handle; + struct aml_vcodec_mem base_y; + struct aml_vcodec_mem base_c; + unsigned int status; +}; + +/** + * struct aml_video_dec_buf - Private data related to each VB2 buffer. + * @b: VB2 buffer + * @list: link list + * @used: Capture buffer contain decoded frame data and keep in + * codec data structure + * @ready_to_display: Capture buffer not display yet + * @queued_in_vb2: Capture buffer is queue in vb2 + * @queued_in_v4l2: Capture buffer is in v4l2 driver, but not in vb2 + * queue yet + * @lastframe: Intput buffer is last buffer - EOS + * @error: An unrecoverable error occurs on this buffer. + * @frame_buffer: Decode status, and buffer information of Capture buffer + * + * Note : These status information help us track and debug buffer state + */ +struct aml_video_dec_buf { + struct vb2_v4l2_buffer vb; + struct list_head list; + + struct vdec_fb frame_buffer; + struct codec_mm_s *mem[2]; + char mem_onwer[32]; + struct list_head node; + bool used; + bool ready_to_display; + bool que_in_m2m; + bool queued_in_vb2; + bool queued_in_v4l2; + bool lastframe; + bool error; +}; + +extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops; +extern const struct v4l2_m2m_ops aml_vdec_m2m_ops; + + +/* + * aml_vdec_lock/aml_vdec_unlock are for ctx instance to + * get/release lock before/after access decoder hw. + * aml_vdec_lock get decoder hw lock and set curr_ctx + * to ctx instance that get lock + */ +void aml_vdec_unlock(struct aml_vcodec_ctx *ctx); +void aml_vdec_lock(struct aml_vcodec_ctx *ctx); +int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq); +void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx); +void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx); +int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx); + +void vdec_device_vf_run(struct aml_vcodec_ctx *ctx); + +void try_to_capture(struct aml_vcodec_ctx *ctx); +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type); +int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, + enum aml_thread_type type, const char *thread_name); +void aml_thread_stop(struct aml_vcodec_ctx *ctx); + +#endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c new file mode 100644 index 000000000000..53b25c492605 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c @@ -0,0 +1,345 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +#include "aml_vcodec_dec_pm.h" +//#include "aml_vcodec_intr.h" +#include "aml_vcodec_util.h" +#include "aml_vcodec_vfm.h" + +#define VDEC_HW_ACTIVE 0x10 +#define VDEC_IRQ_CFG 0x11 +#define VDEC_IRQ_CLR 0x10 +#define VDEC_IRQ_CFG_REG 0xa4 + +module_param(aml_v4l2_dbg_level, int, 0644); +module_param(aml_vcodec_dbg, bool, 0644); + +static int fops_vcodec_open(struct file *file) +{ + struct aml_vcodec_dev *dev = video_drvdata(file); + struct aml_vcodec_ctx *ctx = NULL; + struct aml_video_dec_buf *aml_buf = NULL; + int ret = 0; + struct vb2_queue *src_vq; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + aml_buf = kzalloc(sizeof(*aml_buf), GFP_KERNEL); + if (!aml_buf) { + kfree(ctx); + return -ENOMEM; + } + + mutex_lock(&dev->dev_mutex); + ctx->empty_flush_buf = aml_buf; + ctx->id = dev->id_counter++; + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + INIT_LIST_HEAD(&ctx->list); + INIT_LIST_HEAD(&ctx->capture_list); + INIT_LIST_HEAD(&ctx->vdec_thread_list); + dev->filp = file; + ctx->dev = dev; + init_waitqueue_head(&ctx->queue); + mutex_init(&ctx->state_lock); + mutex_init(&ctx->lock); + init_waitqueue_head(&ctx->wq); + + ctx->type = AML_INST_DECODER; + ret = aml_vcodec_dec_ctrls_setup(ctx); + if (ret) { + aml_v4l2_err("Failed to setup vcodec controls"); + goto err_ctrls_setup; + } + ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, + &aml_vcodec_dec_queue_init); + if (IS_ERR((__force void *)ctx->m2m_ctx)) { + ret = PTR_ERR((__force void *)ctx->m2m_ctx); + aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret); + goto err_m2m_ctx_init; + } + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq; + ctx->empty_flush_buf->lastframe = true; + aml_vcodec_dec_set_default_params(ctx); + + ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap"); + if (ret) { + aml_v4l2_err("Failed to creat capture thread."); + goto err_creat_thread; + } + + list_add(&ctx->list, &dev->ctx_list); + + mutex_unlock(&dev->dev_mutex); + pr_info("[%d] %s decoder\n", ctx->id, dev_name(&dev->plat_dev->dev)); + + return ret; + + /* Deinit when failure occurred */ +err_creat_thread: + v4l2_m2m_ctx_release(ctx->m2m_ctx); +err_m2m_ctx_init: + v4l2_ctrl_handler_free(&ctx->ctrl_hdl); +err_ctrls_setup: + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx->empty_flush_buf); + kfree(ctx); + mutex_unlock(&dev->dev_mutex); + + return ret; +} + +static int fops_vcodec_release(struct file *file) +{ + struct aml_vcodec_dev *dev = video_drvdata(file); + struct aml_vcodec_ctx *ctx = fh_to_ctx(file->private_data); + + pr_info("[%d] release decoder\n", ctx->id); + mutex_lock(&dev->dev_mutex); + + /* + * Call v4l2_m2m_ctx_release before aml_vcodec_dec_release. First, it + * makes sure the worker thread is not running after vdec_if_deinit. + * Second, the decoder will be flushed and all the buffers will be + * returned in stop_streaming. + */ + aml_vcodec_dec_release(ctx); + v4l2_m2m_ctx_release(ctx->m2m_ctx); + + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + + aml_thread_stop(ctx); + + list_del_init(&ctx->list); + kfree(ctx->empty_flush_buf); + kfree(ctx); + mutex_unlock(&dev->dev_mutex); + return 0; +} + +static const struct v4l2_file_operations aml_vcodec_fops = { + .owner = THIS_MODULE, + .open = fops_vcodec_open, + .release = fops_vcodec_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static int aml_vcodec_probe(struct platform_device *pdev) +{ + struct aml_vcodec_dev *dev; + struct video_device *vfd_dec; + int ret = 0; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + INIT_LIST_HEAD(&dev->ctx_list); + dev->plat_dev = pdev; + + mutex_init(&dev->dec_mutex); + mutex_init(&dev->dev_mutex); + spin_lock_init(&dev->irqlock); + + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", + "[/AML_V4L2_VDEC]"); + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) { + aml_v4l2_err("v4l2_device_register err=%d", ret); + goto err_res; + } + + init_waitqueue_head(&dev->queue); + + vfd_dec = video_device_alloc(); + if (!vfd_dec) { + aml_v4l2_err("Failed to allocate video device"); + ret = -ENOMEM; + goto err_dec_alloc; + } + + vfd_dec->fops = &aml_vcodec_fops; + vfd_dec->ioctl_ops = &aml_vdec_ioctl_ops; + vfd_dec->release = video_device_release; + vfd_dec->lock = &dev->dev_mutex; + vfd_dec->v4l2_dev = &dev->v4l2_dev; + vfd_dec->vfl_dir = VFL_DIR_M2M; + vfd_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | + V4L2_CAP_STREAMING; + + snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s", + AML_VCODEC_DEC_NAME); + video_set_drvdata(vfd_dec, dev); + dev->vfd_dec = vfd_dec; + platform_set_drvdata(pdev, dev); + + dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops); + if (IS_ERR((__force void *)dev->m2m_dev_dec)) { + aml_v4l2_err("Failed to init mem2mem dec device"); + ret = PTR_ERR((__force void *)dev->m2m_dev_dec); + goto err_dec_mem_init; + } + + dev->decode_workqueue = + alloc_ordered_workqueue(AML_VCODEC_DEC_NAME, + WQ_MEM_RECLAIM | WQ_FREEZABLE); + if (!dev->decode_workqueue) { + aml_v4l2_err("Failed to create decode workqueue"); + ret = -EINVAL; + goto err_event_workq; + } + + dev->reset_workqueue = + alloc_ordered_workqueue("aml-vcodec-reset", + WQ_MEM_RECLAIM | WQ_FREEZABLE); + if (!dev->reset_workqueue) { + aml_v4l2_err("Failed to create decode workqueue"); + ret = -EINVAL; + destroy_workqueue(dev->decode_workqueue); + goto err_event_workq; + } + + //dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); + + ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26); + if (ret) { + pr_err("Failed to register video device\n"); + goto err_dec_reg; + } + + pr_info("decoder registered as /dev/video%d\n", vfd_dec->num); + + return 0; + +err_dec_reg: + destroy_workqueue(dev->reset_workqueue); + destroy_workqueue(dev->decode_workqueue); +err_event_workq: + v4l2_m2m_release(dev->m2m_dev_dec); +err_dec_mem_init: + video_unregister_device(vfd_dec); +err_dec_alloc: + v4l2_device_unregister(&dev->v4l2_dev); +err_res: + + return ret; +} + +static const struct of_device_id aml_vcodec_match[] = { + {.compatible = "amlogic, vcodec-dec",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, aml_vcodec_match); + +static int aml_vcodec_dec_remove(struct platform_device *pdev) +{ + struct aml_vcodec_dev *dev = platform_get_drvdata(pdev); + + flush_workqueue(dev->reset_workqueue); + destroy_workqueue(dev->reset_workqueue); + + flush_workqueue(dev->decode_workqueue); + destroy_workqueue(dev->decode_workqueue); + + if (dev->m2m_dev_dec) + v4l2_m2m_release(dev->m2m_dev_dec); + + if (dev->vfd_dec) + video_unregister_device(dev->vfd_dec); + + v4l2_device_unregister(&dev->v4l2_dev); + + return 0; +} + +/*static void aml_vcodec_dev_release(struct device *dev) +{ +}*/ + +static struct platform_driver aml_vcodec_dec_driver = { + .probe = aml_vcodec_probe, + .remove = aml_vcodec_dec_remove, + .driver = { + .name = AML_VCODEC_DEC_NAME, + .of_match_table = aml_vcodec_match, + }, +}; + +/* +static struct platform_device aml_vcodec_dec_device = { + .name = AML_VCODEC_DEC_NAME, + .dev.release = aml_vcodec_dev_release, +};*/ + +module_platform_driver(aml_vcodec_dec_driver); + +/* +static int __init amvdec_ports_init(void) +{ + int ret; + + ret = platform_device_register(&aml_vcodec_dec_device); + if (ret) + return ret; + + ret = platform_driver_register(&aml_vcodec_dec_driver); + if (ret) + platform_device_unregister(&aml_vcodec_dec_device); + + return ret; +} + +static void __exit amvdec_ports_exit(void) +{ + platform_driver_unregister(&aml_vcodec_dec_driver); + platform_device_unregister(&aml_vcodec_dec_device); +} + +module_init(amvdec_ports_init); +module_exit(amvdec_ports_exit); +*/ + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("AML video codec V4L2 decoder driver"); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c new file mode 100644 index 000000000000..c801e871b397 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c @@ -0,0 +1,206 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include + +#include "aml_vcodec_dec_pm.h" +#include "aml_vcodec_util.h" +//#include "aml_vpu.h" + +int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *amldev) +{ + struct device_node *node; + struct platform_device *pdev; + struct aml_vcodec_pm *pm; + int ret = 0; + + pdev = amldev->plat_dev; + pm = &amldev->pm; + pm->amldev = amldev; + node = of_parse_phandle(pdev->dev.of_node, "larb", 0); + if (!node) { + aml_v4l2_err("of_parse_phandle larb fail!"); + return -1; + } + + pdev = of_find_device_by_node(node); + if (WARN_ON(!pdev)) { + of_node_put(node); + return -1; + } + pm->larbvdec = &pdev->dev; + pdev = amldev->plat_dev; + pm->dev = &pdev->dev; + + pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll"); + if (IS_ERR(pm->vcodecpll)) { + aml_v4l2_err("devm_clk_get vcodecpll fail"); + ret = PTR_ERR(pm->vcodecpll); + } + + pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2"); + if (IS_ERR(pm->univpll_d2)) { + aml_v4l2_err("devm_clk_get univpll_d2 fail"); + ret = PTR_ERR(pm->univpll_d2); + } + + pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel"); + if (IS_ERR(pm->clk_cci400_sel)) { + aml_v4l2_err("devm_clk_get clk_cci400_sel fail"); + ret = PTR_ERR(pm->clk_cci400_sel); + } + + pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel"); + if (IS_ERR(pm->vdec_sel)) { + aml_v4l2_err("devm_clk_get vdec_sel fail"); + ret = PTR_ERR(pm->vdec_sel); + } + + pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll"); + if (IS_ERR(pm->vdecpll)) { + aml_v4l2_err("devm_clk_get vdecpll fail"); + ret = PTR_ERR(pm->vdecpll); + } + + pm->vencpll = devm_clk_get(&pdev->dev, "vencpll"); + if (IS_ERR(pm->vencpll)) { + aml_v4l2_err("devm_clk_get vencpll fail"); + ret = PTR_ERR(pm->vencpll); + } + + pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel"); + if (IS_ERR(pm->venc_lt_sel)) { + aml_v4l2_err("devm_clk_get venc_lt_sel fail"); + ret = PTR_ERR(pm->venc_lt_sel); + } + + pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src"); + if (IS_ERR(pm->vdec_bus_clk_src)) { + aml_v4l2_err("devm_clk_get vdec_bus_clk_src"); + ret = PTR_ERR(pm->vdec_bus_clk_src); + } + + pm_runtime_enable(&pdev->dev); + + return ret; +} + +void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev) +{ + pm_runtime_disable(dev->pm.dev); +} + +void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm) +{ + int ret; + + ret = pm_runtime_get_sync(pm->dev); + if (ret) + aml_v4l2_err("pm_runtime_get_sync fail %d", ret); +} + +void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm) +{ + int ret; + + ret = pm_runtime_put_sync(pm->dev); + if (ret) + aml_v4l2_err("pm_runtime_put_sync fail %d", ret); +} + +void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm) +{ + int ret; + + ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000); + if (ret) + aml_v4l2_err("clk_set_rate vcodecpll fail %d", ret); + + ret = clk_set_rate(pm->vencpll, 800 * 1000000); + if (ret) + aml_v4l2_err("clk_set_rate vencpll fail %d", ret); + + ret = clk_prepare_enable(pm->vcodecpll); + if (ret) + aml_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret); + + ret = clk_prepare_enable(pm->vencpll); + if (ret) + aml_v4l2_err("clk_prepare_enable vencpll fail %d", ret); + + ret = clk_prepare_enable(pm->vdec_bus_clk_src); + if (ret) + aml_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d", + ret); + + ret = clk_prepare_enable(pm->venc_lt_sel); + if (ret) + aml_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret); + + ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src); + if (ret) + aml_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d", + ret); + + ret = clk_prepare_enable(pm->univpll_d2); + if (ret) + aml_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret); + + ret = clk_prepare_enable(pm->clk_cci400_sel); + if (ret) + aml_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret); + + ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2); + if (ret) + aml_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d", + ret); + + ret = clk_prepare_enable(pm->vdecpll); + if (ret) + aml_v4l2_err("clk_prepare_enable vdecpll fail %d", ret); + + ret = clk_prepare_enable(pm->vdec_sel); + if (ret) + aml_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret); + + ret = clk_set_parent(pm->vdec_sel, pm->vdecpll); + if (ret) + aml_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret); + + //ret = aml_smi_larb_get(pm->larbvdec); + if (ret) + aml_v4l2_err("aml_smi_larb_get larbvdec fail %d", ret); + +} + +void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm) +{ + //aml_smi_larb_put(pm->larbvdec); + clk_disable_unprepare(pm->vdec_sel); + clk_disable_unprepare(pm->vdecpll); + clk_disable_unprepare(pm->univpll_d2); + clk_disable_unprepare(pm->clk_cci400_sel); + clk_disable_unprepare(pm->venc_lt_sel); + clk_disable_unprepare(pm->vdec_bus_clk_src); + clk_disable_unprepare(pm->vencpll); + clk_disable_unprepare(pm->vcodecpll); +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h new file mode 100644 index 000000000000..ccdf313f0ca8 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h @@ -0,0 +1,34 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + +#ifndef _AML_VCODEC_DEC_PM_H_ +#define _AML_VCODEC_DEC_PM_H_ + +#include "aml_vcodec_drv.h" + +int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *dev); +void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev); + +void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm); +void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm); +void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm); +void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm); + +#endif /* _AML_VCODEC_DEC_PM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h new file mode 100644 index 000000000000..4b638992af93 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h @@ -0,0 +1,428 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _AML_VCODEC_DRV_H_ +#define _AML_VCODEC_DRV_H_ + +#include +#include +#include +#include +#include +#include +#include "aml_vcodec_util.h" + +#define AML_VCODEC_DRV_NAME "aml_vcodec_drv" +#define AML_VCODEC_DEC_NAME "aml-vcodec-dec" +#define AML_VCODEC_ENC_NAME "aml-vcodec-enc" +#define AML_PLATFORM_STR "platform:amlogic" + +#define AML_VCODEC_MAX_PLANES 3 +#define AML_V4L2_BENCHMARK 0 +#define WAIT_INTR_TIMEOUT_MS 1000 + +/** + * enum aml_hw_reg_idx - AML hw register base index + */ +enum aml_hw_reg_idx { + VDEC_SYS, + VDEC_MISC, + VDEC_LD, + VDEC_TOP, + VDEC_CM, + VDEC_AD, + VDEC_AV, + VDEC_PP, + VDEC_HWD, + VDEC_HWQ, + VDEC_HWB, + VDEC_HWG, + NUM_MAX_VDEC_REG_BASE, + /* h264 encoder */ + VENC_SYS = NUM_MAX_VDEC_REG_BASE, + /* vp8 encoder */ + VENC_LT_SYS, + NUM_MAX_VCODEC_REG_BASE +}; + +/** + * enum aml_instance_type - The type of an AML Vcodec instance. + */ +enum aml_instance_type { + AML_INST_DECODER = 0, + AML_INST_ENCODER = 1, +}; + +/** + * enum aml_instance_state - The state of an AML Vcodec instance. + * @AML_STATE_IDLE - default state when instance is created + * @AML_STATE_INIT - vcodec instance is initialized + * @AML_STATE_PROBE - vdec/venc had sps/pps header parsed/encoded + * @AML_STATE_ACTIVE - vdec is ready for work. + * @AML_STATE_FLUSHING - vdec is flushing. Only used by decoder + * @AML_STATE_FLUSHED - decoder has transacted the last frame. + * @AML_STATE_RESET - decoder has be reset after flush. + * @AML_STATE_ABORT - vcodec should be aborted + */ +enum aml_instance_state { + AML_STATE_IDLE, + AML_STATE_INIT, + AML_STATE_PROBE, + AML_STATE_READY, + AML_STATE_ACTIVE, + AML_STATE_FLUSHING, + AML_STATE_FLUSHED, + AML_STATE_RESET, + AML_STATE_ABORT, +}; + +/** + * struct aml_encode_param - General encoding parameters type + */ +enum aml_encode_param { + AML_ENCODE_PARAM_NONE = 0, + AML_ENCODE_PARAM_BITRATE = (1 << 0), + AML_ENCODE_PARAM_FRAMERATE = (1 << 1), + AML_ENCODE_PARAM_INTRA_PERIOD = (1 << 2), + AML_ENCODE_PARAM_FORCE_INTRA = (1 << 3), + AML_ENCODE_PARAM_GOP_SIZE = (1 << 4), +}; + +enum aml_fmt_type { + AML_FMT_DEC = 0, + AML_FMT_ENC = 1, + AML_FMT_FRAME = 2, +}; + +/** + * struct aml_video_fmt - Structure used to store information about pixelformats + */ +struct aml_video_fmt { + u32 fourcc; + enum aml_fmt_type type; + u32 num_planes; +}; + +/** + * struct aml_codec_framesizes - Structure used to store information about + * framesizes + */ +struct aml_codec_framesizes { + u32 fourcc; + struct v4l2_frmsize_stepwise stepwise; +}; + +/** + * struct aml_q_type - Type of queue + */ +enum aml_q_type { + AML_Q_DATA_SRC = 0, + AML_Q_DATA_DST = 1, +}; + +/** + * struct aml_q_data - Structure used to store information about queue + */ +struct aml_q_data { + unsigned int visible_width; + unsigned int visible_height; + unsigned int coded_width; + unsigned int coded_height; + enum v4l2_field field; + unsigned int bytesperline[AML_VCODEC_MAX_PLANES]; + unsigned int sizeimage[AML_VCODEC_MAX_PLANES]; + struct aml_video_fmt *fmt; +}; + +/** + * struct aml_enc_params - General encoding parameters + * @bitrate: target bitrate in bits per second + * @num_b_frame: number of b frames between p-frame + * @rc_frame: frame based rate control + * @rc_mb: macroblock based rate control + * @seq_hdr_mode: H.264 sequence header is encoded separately or joined + * with the first frame + * @intra_period: I frame period + * @gop_size: group of picture size, it's used as the intra frame period + * @framerate_num: frame rate numerator. ex: framerate_num=30 and + * framerate_denom=1 menas FPS is 30 + * @framerate_denom: frame rate denominator. ex: framerate_num=30 and + * framerate_denom=1 menas FPS is 30 + * @h264_max_qp: Max value for H.264 quantization parameter + * @h264_profile: V4L2 defined H.264 profile + * @h264_level: V4L2 defined H.264 level + * @force_intra: force/insert intra frame + */ +struct aml_enc_params { + unsigned int bitrate; + unsigned int num_b_frame; + unsigned int rc_frame; + unsigned int rc_mb; + unsigned int seq_hdr_mode; + unsigned int intra_period; + unsigned int gop_size; + unsigned int framerate_num; + unsigned int framerate_denom; + unsigned int h264_max_qp; + unsigned int h264_profile; + unsigned int h264_level; + unsigned int force_intra; +}; + +/** + * struct aml_vcodec_pm - Power management data structure + */ +struct aml_vcodec_pm { + struct clk *vdec_bus_clk_src; + struct clk *vencpll; + + struct clk *vcodecpll; + struct clk *univpll_d2; + struct clk *clk_cci400_sel; + struct clk *vdecpll; + struct clk *vdec_sel; + struct clk *vencpll_d2; + struct clk *venc_sel; + struct clk *univpll1_d2; + struct clk *venc_lt_sel; + struct device *larbvdec; + struct device *larbvenc; + struct device *larbvenclt; + struct device *dev; + struct aml_vcodec_dev *amldev; +}; + +/** + * struct vdec_pic_info - picture size information + * @visible_width: picture width + * @visible_height: picture height + * @coded_width: picture buffer width (64 aligned up from pic_w) + * @coded_height: picture buffer heiht (64 aligned up from pic_h) + * @y_bs_sz: Y bitstream size + * @c_bs_sz: CbCr bitstream size + * @y_len_sz: additional size required to store decompress information for y + * plane + * @c_len_sz: additional size required to store decompress information for cbcr + * plane + * E.g. suppose picture size is 176x144, + * buffer size will be aligned to 176x160. + */ +struct vdec_pic_info { + unsigned int visible_width; + unsigned int visible_height; + unsigned int coded_width; + unsigned int coded_height; + unsigned int y_bs_sz; + unsigned int c_bs_sz; + unsigned int y_len_sz; + unsigned int c_len_sz; +}; + +enum aml_thread_type { + AML_THREAD_OUTPUT, + AML_THREAD_CAPTURE, +}; + +typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx); + +struct aml_vdec_thread { + struct list_head node; + spinlock_t lock; + struct semaphore sem; + struct task_struct *task; + enum aml_thread_type type; + void *priv; + int stop; + + aml_thread_func func; +}; + +/** + * struct aml_vcodec_ctx - Context (instance) private data. + * + * @type: type of the instance - decoder or encoder + * @dev: pointer to the aml_vcodec_dev of the device + * @list: link to ctx_list of aml_vcodec_dev + * @fh: struct v4l2_fh + * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context + * @q_data: store information of input and output queue + * of the context + * @id: index of the context that this structure describes + * @state: state of the context + * @param_change: indicate encode parameter type + * @enc_params: encoding parameters + * @dec_if: hooked decoder driver interface + * @enc_if: hoooked encoder driver interface + * @drv_handle: driver handle for specific decode/encode instance + * + * @picinfo: store picture info after header parsing + * @dpb_size: store dpb count after header parsing + * @int_cond: variable used by the waitqueue + * @int_type: type of the last interrupt + * @queue: waitqueue that can be used to wait for this context to + * finish + * @irq_status: irq status + * + * @ctrl_hdl: handler for v4l2 framework + * @decode_work: worker for the decoding + * @encode_work: worker for the encoding + * @last_decoded_picinfo: pic information get from latest decode + * @empty_flush_buf: a fake size-0 capture buffer that indicates flush + * + * @colorspace: enum v4l2_colorspace; supplemental to pixelformat + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding + * @quantization: enum v4l2_quantization, colorspace quantization + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function + * @lock: protect variables accessed by V4L2 threads and worker thread such as + * aml_video_dec_buf. + */ +struct aml_vcodec_ctx { + enum aml_instance_type type; + struct aml_vcodec_dev *dev; + struct list_head list; + + struct v4l2_fh fh; + struct v4l2_m2m_ctx *m2m_ctx; + struct aml_vdec_adapt *ada_ctx; + struct aml_q_data q_data[2]; + int id; + struct mutex state_lock; + enum aml_instance_state state; + enum aml_encode_param param_change; + struct aml_enc_params enc_params; + + const struct vdec_common_if *dec_if; + const struct venc_common_if *enc_if; + unsigned long drv_handle; + + struct vdec_pic_info picinfo; + int dpb_size; + + int int_cond; + int int_type; + wait_queue_head_t queue; + unsigned int irq_status; + + struct v4l2_ctrl_handler ctrl_hdl; + struct work_struct decode_work; + struct work_struct encode_work; + struct work_struct reset_work; + struct vdec_pic_info last_decoded_picinfo; + struct aml_video_dec_buf *empty_flush_buf; + + enum v4l2_colorspace colorspace; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quantization; + enum v4l2_xfer_func xfer_func; + + int decoded_frame_cnt; + struct mutex lock; + wait_queue_head_t wq; + bool has_receive_eos; + struct list_head capture_list; + struct list_head vdec_thread_list; +}; + +/** + * struct aml_vcodec_dev - driver data + * @v4l2_dev: V4L2 device to register video devices for. + * @vfd_dec: Video device for decoder + * @vfd_enc: Video device for encoder. + * + * @m2m_dev_dec: m2m device for decoder + * @m2m_dev_enc: m2m device for encoder. + * @plat_dev: platform device + * @vpu_plat_dev: aml vpu platform device + * @alloc_ctx: VB2 allocator context + * (for allocations without kernel mapping). + * @ctx_list: list of struct aml_vcodec_ctx + * @irqlock: protect data access by irq handler and work thread + * @curr_ctx: The context that is waiting for codec hardware + * + * @reg_base: Mapped address of AML Vcodec registers. + * + * @id_counter: used to identify current opened instance + * + * @encode_workqueue: encode work queue + * + * @int_cond: used to identify interrupt condition happen + * @int_type: used to identify what kind of interrupt condition happen + * @dev_mutex: video_device lock + * @queue: waitqueue for waiting for completion of device commands + * + * @dec_irq: decoder irq resource + * @enc_irq: h264 encoder irq resource + * @enc_lt_irq: vp8 encoder irq resource + * + * @dec_mutex: decoder hardware lock + * @enc_mutex: encoder hardware lock. + * + * @pm: power management control + * @dec_capability: used to identify decode capability, ex: 4k + * @enc_capability: used to identify encode capability + */ +struct aml_vcodec_dev { + struct v4l2_device v4l2_dev; + struct video_device *vfd_dec; + struct video_device *vfd_enc; + struct file *filp; + + struct v4l2_m2m_dev *m2m_dev_dec; + struct v4l2_m2m_dev *m2m_dev_enc; + struct platform_device *plat_dev; + struct platform_device *vpu_plat_dev;//?? + struct vb2_alloc_ctx *alloc_ctx;//?? + struct list_head ctx_list; + spinlock_t irqlock; + struct aml_vcodec_ctx *curr_ctx; + void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE]; + + unsigned long id_counter; + + struct workqueue_struct *decode_workqueue; + struct workqueue_struct *encode_workqueue; + struct workqueue_struct *reset_workqueue; + int int_cond; + int int_type; + struct mutex dev_mutex; + wait_queue_head_t queue; + + int dec_irq; + int enc_irq; + int enc_lt_irq; + + struct mutex dec_mutex; + struct mutex enc_mutex; + + struct aml_vcodec_pm pm; + unsigned int dec_capability; + unsigned int enc_capability; +}; + +static inline struct aml_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh) +{ + return container_of(fh, struct aml_vcodec_ctx, fh); +} + +static inline struct aml_vcodec_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) +{ + return container_of(ctrl->handler, struct aml_vcodec_ctx, ctrl_hdl); +} + +#endif /* _AML_VCODEC_DRV_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c new file mode 100644 index 000000000000..0026c6a2ad40 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c @@ -0,0 +1,122 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_util.h" +//#include "aml_vpu.h" + +/* For encoder, this will enable logs in venc/*/ +bool aml_vcodec_dbg; +EXPORT_SYMBOL(aml_vcodec_dbg); + +/* The log level of v4l2 encoder or decoder driver. + * That is, files under aml-vcodec/. + */ +int aml_v4l2_dbg_level; +EXPORT_SYMBOL(aml_v4l2_dbg_level); + +void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, + unsigned int reg_idx) +{ + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; + + if (!data || reg_idx >= NUM_MAX_VCODEC_REG_BASE) { + aml_v4l2_err("Invalid arguments, reg_idx=%d", reg_idx); + return NULL; + } + return ctx->dev->reg_base[reg_idx]; +} +EXPORT_SYMBOL(aml_vcodec_get_reg_addr); + +int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem) +{ + unsigned long size = mem->size; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; + struct device *dev = &ctx->dev->plat_dev->dev; + + //mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); + mem->va = codec_mm_dma_alloc_coherent(dev_name(dev), size, + &mem->dma_addr, GFP_KERNEL, 0); + if (!mem->va) { + aml_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev), + size); + return -ENOMEM; + } + + memset(mem->va, 0, size); + + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, + (unsigned long)mem->dma_addr); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); + + return 0; +} +EXPORT_SYMBOL(aml_vcodec_mem_alloc); + +void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem) +{ + unsigned long size = mem->size; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; + struct device *dev = &ctx->dev->plat_dev->dev; + + if (!mem->va) { + aml_v4l2_err("%s dma_free size=%ld failed!", dev_name(dev), + size); + return; + } + + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, + (unsigned long)mem->dma_addr); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); + + dma_free_coherent(dev, size, mem->va, mem->dma_addr); + mem->va = NULL; + mem->dma_addr = 0; + mem->size = 0; +} +EXPORT_SYMBOL(aml_vcodec_mem_free); + +void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev, + struct aml_vcodec_ctx *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->irqlock, flags); + dev->curr_ctx = ctx; + spin_unlock_irqrestore(&dev->irqlock, flags); +} +EXPORT_SYMBOL(aml_vcodec_set_curr_ctx); + +struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev) +{ + unsigned long flags; + struct aml_vcodec_ctx *ctx; + + spin_lock_irqsave(&dev->irqlock, flags); + ctx = dev->curr_ctx; + spin_unlock_irqrestore(&dev->irqlock, flags); + return ctx; +} +EXPORT_SYMBOL(aml_vcodec_get_curr_ctx); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h new file mode 100644 index 000000000000..894cfb24b89c --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h @@ -0,0 +1,94 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _AML_VCODEC_UTIL_H_ +#define _AML_VCODEC_UTIL_H_ + +#include +#include +#include + +#define DEBUG + +struct aml_vcodec_mem { + size_t size; + void *va; + dma_addr_t dma_addr; + unsigned int bytes_used; +}; + +struct aml_vcodec_ctx; +struct aml_vcodec_dev; + +extern int aml_v4l2_dbg_level; +extern bool aml_vcodec_dbg; + + +#if defined(DEBUG) + +#define aml_v4l2_debug(level, fmt, args...) \ + do { \ + if (aml_v4l2_dbg_level >= level) \ + pr_info(fmt "\n", ##args); \ + } while (0) + +#define aml_v4l2_debug_enter() aml_v4l2_debug(3, "+") +#define aml_v4l2_debug_leave() aml_v4l2_debug(3, "-") + +#define aml_vcodec_debug(h, fmt, args...) \ + do { \ + if (aml_vcodec_dbg) \ + pr_info("[%d]: %s() " fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, \ + __func__, ##args); \ + } while (0) + +#define aml_vcodec_debug_enter(h) aml_vcodec_debug(h, "+") +#define aml_vcodec_debug_leave(h) aml_vcodec_debug(h, "-") + +#else + +#define aml_v4l2_debug(level, fmt, args...) +#define aml_v4l2_debug_enter() +#define aml_v4l2_debug_leave() + +#define aml_vcodec_debug(h, fmt, args...) +#define aml_vcodec_debug_enter(h) +#define aml_vcodec_debug_leave(h) + +#endif + +#define aml_v4l2_err(fmt, args...) \ + pr_err("[ERR]" fmt "\n", ##args) + +#define aml_vcodec_err(h, fmt, args...) \ + pr_err("[ERR][%d]" fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, ##args) + +void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, + unsigned int reg_idx); +int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem); +void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem); +void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev, + struct aml_vcodec_ctx *ctx); +struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev); + +#endif /* _AML_VCODEC_UTIL_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c new file mode 100644 index 000000000000..ac48b9c08330 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c @@ -0,0 +1,205 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include "aml_vcodec_vfm.h" +#include "aml_vcodec_vfq.h" +#include "aml_vcodec_util.h" +#include "aml_vcodec_adapt.h" +#include + +#define RECEIVER_NAME "v4l2-video" +#define PROVIDER_NAME "v4l2-video" + +static struct vframe_s *vdec_vf_peek(void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + return vfq_peek(&vfm->vf_que); +} + +static struct vframe_s *vdec_vf_get(void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + return vfq_pop(&vfm->vf_que); +} + +static void vdec_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + vf_put(vf, vfm->recv_name); + vf_notify_provider(vfm->recv_name, VFRAME_EVENT_RECEIVER_PUT, NULL); +} + +static int vdec_event_cb(int type, void *data, void *private_data) +{ + + if (type & VFRAME_EVENT_RECEIVER_PUT) { + } else if (type & VFRAME_EVENT_RECEIVER_GET) { + } else if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) { + } + return 0; +} + +static int vdec_vf_states(struct vframe_states *states, void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + states->vf_pool_size = POOL_SIZE; + states->buf_recycle_num = 0; + states->buf_free_num = POOL_SIZE - vfq_level(&vfm->vf_que); + states->buf_avail_num = vfq_level(&vfm->vf_que); + + return 0; +} + +void video_vf_put(char *receiver, struct vdec_fb *fb, int id) +{ + struct vframe_provider_s *vfp = vf_get_provider(receiver); + struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; + + aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d", + id, vfp->name, vf, vf->index); + + if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) + vf_put(vf, receiver); +} + +static const struct vframe_operations_s vf_provider = { + .peek = vdec_vf_peek, + .get = vdec_vf_get, + .put = vdec_vf_put, + .event_cb = vdec_event_cb, + .vf_states = vdec_vf_states, +}; + +static int video_receiver_event_fun(int type, void *data, void *private_data) +{ + int ret = 0; + struct vframe_states states; + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data; + + //aml_v4l2_debug(4, "[%d] type: %d, vfm: %p", vfm->ctx->id, type, vfm); + + switch (type) { + case VFRAME_EVENT_PROVIDER_UNREG: { + if (vf_get_receiver(vfm->prov_name)) { + aml_v4l2_debug(4, "[%d] unreg %s provider.", + vfm->ctx->id, vfm->prov_name); + vf_unreg_provider(&vfm->vf_prov); + } + + break; + } + + case VFRAME_EVENT_PROVIDER_START: { + if (vf_get_receiver(vfm->prov_name)) { + aml_v4l2_debug(4, "[%d] reg %s provider.", + vfm->ctx->id, vfm->prov_name); + vf_provider_init(&vfm->vf_prov, vfm->prov_name, + &vf_provider, vfm); + vf_reg_provider(&vfm->vf_prov); + vf_notify_receiver(vfm->prov_name, + VFRAME_EVENT_PROVIDER_START, NULL); + } + + vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]); + + break; + } + + case VFRAME_EVENT_PROVIDER_QUREY_STATE: { + vdec_vf_states(&states, vfm); + if (states.buf_avail_num > 0) + ret = RECEIVER_ACTIVE; + break; + } + + case VFRAME_EVENT_PROVIDER_VFRAME_READY: { + if (vfq_level(&vfm->vf_que) > POOL_SIZE - 1) + ret = -1; + + if (!vf_peek(vfm->recv_name)) + ret = -1; + + vfm->vf = vf_get(vfm->recv_name); + if (!vfm->vf) + ret = -1; + + if (ret < 0) { + pr_err("[%d] receiver vf err.\n", vfm->ctx->id); + break; + } + + vfq_push(&vfm->vf_que, vfm->vf); + + /*vf_notify_receiver(vfm->prov_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);*/ + + /* schedule capture work. */ + vdec_device_vf_run(vfm->ctx); + + aml_v4l2_debug(2, "[%d] FROM (%s) vf: %p, idx: %d", + vfm->ctx->id, vf_get_provider(vfm->recv_name)->name, + vfm->vf, vfm->vf->index); + break; + } + + default: + aml_v4l2_debug(4, "[%d] the vf event is %d", vfm->ctx->id, type); + } + + return ret; +} + +static const struct vframe_receiver_op_s vf_receiver = { + .event_cb = video_receiver_event_fun +}; + +struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm) +{ + return vfq_peek(&vfm->vf_que); +} + +struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) +{ + return vfq_pop(&vfm->vf_que); +} + +int vcodec_vfm_init(struct vcodec_vfm_s *vfm) +{ + snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", + RECEIVER_NAME, vfm->ctx->id); + snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", + PROVIDER_NAME, vfm->ctx->id); + + vfm->ada_ctx->recv_name = vfm->recv_name; + + vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm); + vf_reg_receiver(&vfm->vf_recv); + + return 0; +} + +void vcodec_vfm_release(struct vcodec_vfm_s *vfm) +{ + vf_unreg_receiver(&vfm->vf_recv); +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h new file mode 100644 index 000000000000..bcd88757f21f --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef __AML_VCODEC_VFM_H_ +#define __AML_VCODEC_VFM_H_ + +#include "aml_vcodec_vfq.h" +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +#include +#include + +#define VF_NAME_SIZE (32) +#define POOL_SIZE (64) + +struct vcodec_vfm_s { + struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt *ada_ctx; + struct vfq_s vf_que; + struct vframe_s *vf; + struct vframe_s *pool[POOL_SIZE + 1]; + char recv_name[VF_NAME_SIZE]; + char prov_name[VF_NAME_SIZE]; + struct vframe_provider_s vf_prov; + struct vframe_receiver_s vf_recv; +}; + +int vcodec_vfm_init(struct vcodec_vfm_s *vfm); + +void vcodec_vfm_release(struct vcodec_vfm_s *vfm); + +struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm); + +struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm); + +int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb); +int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb); + +void video_vf_put(char *receiver, struct vdec_fb *fb, int id); + +#endif /* __AML_VCODEC_VFM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h new file mode 100644 index 000000000000..e19c53ca0a28 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h @@ -0,0 +1,112 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef __AML_VCODEC_VFQ_H_ +#define __AML_VCODEC_VFQ_H_ + +#include +#include + +struct vfq_s { + int rp; + int wp; + int size; + int pre_rp; + int pre_wp; + struct vframe_s **pool; +}; + +static inline void vfq_lookup_start(struct vfq_s *q) +{ + q->pre_rp = q->rp; + q->pre_wp = q->wp; +} +static inline void vfq_lookup_end(struct vfq_s *q) +{ + q->rp = q->pre_rp; + q->wp = q->pre_wp; +} + +static inline void vfq_init(struct vfq_s *q, u32 size, struct vframe_s **pool) +{ + q->rp = q->wp = 0; + q->size = size; + q->pool = pool; +} + +static inline bool vfq_empty(struct vfq_s *q) +{ + return q->rp == q->wp; +} + +static inline void vfq_push(struct vfq_s *q, struct vframe_s *vf) +{ + int wp = q->wp; + + /*ToDo*/ + smp_mb(); + + q->pool[wp] = vf; + + /*ToDo*/ + smp_wmb(); + + q->wp = (wp == (q->size - 1)) ? 0 : (wp + 1); +} + +static inline struct vframe_s *vfq_pop(struct vfq_s *q) +{ + struct vframe_s *vf; + int rp; + + if (vfq_empty(q)) + return NULL; + + rp = q->rp; + + /*ToDo*/ + smp_rmb(); + + vf = q->pool[rp]; + + /*ToDo*/ + smp_mb(); + + q->rp = (rp == (q->size - 1)) ? 0 : (rp + 1); + + return vf; +} + +static inline struct vframe_s *vfq_peek(struct vfq_s *q) +{ + return (vfq_empty(q)) ? NULL : q->pool[q->rp]; +} + +static inline int vfq_level(struct vfq_s *q) +{ + int level = q->wp - q->rp; + + if (level < 0) + level += q->size; + + return level; +} + +#endif /* __AML_VCODEC_VFQ_H_ */ + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c new file mode 100644 index 000000000000..1c3b73dfb7be --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c @@ -0,0 +1,389 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include "h264_parse.h" +#include "h264_stream.h" + +static unsigned char h264_exp_golomb_bits[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static unsigned char ZZ_SCAN[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +static unsigned char ZZ_SCAN8[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +unsigned int h264_u(struct h264_stream_t *s, unsigned int n) +{ + //if (n % 8 == 0) { + // return h264_stream_read_bytes(s, n / 8); + //} + return h264_stream_read_bits(s, n); +} + +unsigned int h264_ue(struct h264_stream_t *s) +{ + unsigned int bits, read; + unsigned char coded; + + bits = 0; + while (true) { + if (h264_stream_bytes_remaining(s) < 1) { + read = h264_stream_peek_bits(s, s->bit_pos) << + (8 - s->bit_pos); + break; + } + + read = h264_stream_peek_bits(s, 8); + if (bits > 16) + break; + + if (read) + break; + + h264_stream_read_bits(s, 8); + bits += 8; + } + + coded = h264_exp_golomb_bits[read]; + h264_stream_read_bits(s, coded); + bits += coded; + return h264_stream_read_bits(s, bits + 1) - 1; +} + +int h264_se(struct h264_stream_t *s) +{ + unsigned int ret; + + ret = h264_ue(s); + if (!(ret & 0x1)) { + ret >>= 1; + return (int)(-ret); + } + + return (ret + 1) >> 1; +} + +void h264_f(struct h264_stream_t *s, unsigned int n, unsigned int pattern) +{ + unsigned int val = h264_u(s, n); + + if (val != pattern) { + pr_err("fixed-pattern doesn't match. expected: %x actual: %x\n", + pattern, (unsigned int)val); + return; + } +} + +void h264_rbsp_trailing_bits(struct h264_stream_t *s) +{ + h264_f(s, 1, 1); + h264_f(s, s->bit_pos, 0); +} + +// syntax for scaling list matrix values +void Scaling_List(int *scalingList, int sizeOfScalingList, + bool *UseDefaultScalingMatrix, struct h264_stream_t *s) +{ + int j, scanj; + int delta_scale, lastScale, nextScale; + + lastScale = 8; + nextScale = 8; + + for (j = 0; j < sizeOfScalingList; j++) { + scanj = (sizeOfScalingList == 16) ? ZZ_SCAN[j] : ZZ_SCAN8[j]; + + if (nextScale != 0) { + delta_scale = h264_ue(s); + nextScale = (lastScale + delta_scale + 256) % 256; + *UseDefaultScalingMatrix = + (bool) (scanj == 0 && nextScale == 0); + } + + scalingList[scanj] = (nextScale == 0) ? lastScale : nextScale; + lastScale = scalingList[scanj]; + } +} + +void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps) +{ + unsigned int i, n_ScalingList; + + sps->profile_idc = h264_u(s, 8); + + if ((sps->profile_idc != BASELINE) && + (sps->profile_idc != MAIN) && + (sps->profile_idc != EXTENDED) && + (sps->profile_idc != FREXT_HP) && + (sps->profile_idc != FREXT_Hi10P) && + (sps->profile_idc != FREXT_Hi422) && + (sps->profile_idc != FREXT_Hi444) && + (sps->profile_idc != FREXT_CAVLC444) + && (sps->profile_idc != MVC_HIGH) + && (sps->profile_idc != STEREO_HIGH)) { + pr_err("Invalid Profile IDC (%d) encountered.\n", + sps->profile_idc); + return; + } + + sps->constrained_set0_flag = h264_u(s, 1); + sps->constrained_set1_flag = h264_u(s, 1); + sps->constrained_set2_flag = h264_u(s, 1); + h264_u(s, 5); // reserved_zero_5bits + sps->level_idc = h264_u(s, 8); + sps->seq_parameter_set_id = h264_ue(s); + + // Fidelity Range Extensions stuff + sps->chroma_format_idc = 1; + sps->bit_depth_luma_minus8 = 0; + sps->bit_depth_chroma_minus8 = 0; + sps->lossless_qpprime_flag = 0; + sps->separate_colour_plane_flag = 0; + + if ((sps->profile_idc == FREXT_HP) || + (sps->profile_idc == FREXT_Hi10P) || + (sps->profile_idc == FREXT_Hi422) || + (sps->profile_idc == FREXT_Hi444) || + (sps->profile_idc == FREXT_CAVLC444)) { + sps->chroma_format_idc = h264_ue(s); + + if (sps->chroma_format_idc == YUV444) + sps->separate_colour_plane_flag = h264_u(s, 1); + + sps->bit_depth_luma_minus8 = h264_ue(s); + sps->bit_depth_chroma_minus8 = h264_ue(s); + //checking; + if ((sps->bit_depth_luma_minus8 + 8 > sizeof(unsigned short) * 8) || + (sps->bit_depth_chroma_minus8 + 8 > sizeof(unsigned short) * 8)) { + pr_err("Source picture has higher bit depth than imgpel data type.\n"); + pr_err("Please recompile with larger data type for imgpel.\n"); + } + + sps->lossless_qpprime_flag = h264_u(s, 1); + sps->seq_scaling_matrix_present_flag = h264_u(s, 1); + if (sps->seq_scaling_matrix_present_flag) { + n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12; + for (i = 0; i < n_ScalingList; i++) { + sps->seq_scaling_list_present_flag[i] = h264_u(s, 1); + if (sps->seq_scaling_list_present_flag[i]) { + if (i < 6) + Scaling_List(sps->ScalingList4x4[i], 16, + &sps->UseDefaultScalingMatrix4x4Flag[i], s); + else + Scaling_List(sps->ScalingList8x8[i - 6], + 64, &sps->UseDefaultScalingMatrix8x8Flag[i - 6], s); + } + } + } + } + + sps->log2_max_frame_num_minus4 = h264_ue(s); + sps->pic_order_cnt_type = h264_ue(s); + if (sps->pic_order_cnt_type == 0) { + sps->log2_max_pic_order_cnt_lsb_minus4 = h264_ue(s); + } else if (sps->pic_order_cnt_type == 1) { + sps->delta_pic_order_always_zero_flag = h264_se(s); + sps->offset_for_non_ref_pic = h264_se(s); + sps->offset_for_top_to_bottom_field = h264_se(s); + sps->num_ref_frames_in_poc_cycle = h264_se(s); + for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) + sps->offset_for_ref_frame[i] = h264_se(s); + } + + sps->num_ref_frames = h264_ue(s); + sps->gaps_in_frame_num_value_allowed_flag = h264_u(s, 1); + sps->pic_width_in_mbs_minus1 = h264_ue(s); + sps->pic_height_in_map_units_minus1 = h264_ue(s); + sps->frame_mbs_only_flag = h264_u(s, 1); + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = h264_u(s, 1); + + sps->direct_8x8_inference_flag = h264_u(s, 1); + sps->frame_cropping_flag = h264_u(s, 1); + if (sps->frame_cropping_flag) { + sps->frame_crop_left_offset = h264_ue(s); + sps->frame_crop_right_offset = h264_ue(s); + sps->frame_crop_top_offset = h264_ue(s); + sps->frame_crop_bottom_offset = h264_ue(s); + } + + sps->vui_parameters_present_flag = h264_u(s, 1); + //if (sps->vui_parameters_present_flag) { + // sps->vui_parameters = h264_vui_parameters(s); + //} + h264_rbsp_trailing_bits(s); +} + +void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps) +{ + pps->pic_parameter_set_id = h264_ue(s); + pps->seq_parameter_set_id = h264_ue(s); + pps->entropy_coding_mode_flag = h264_u(s, 1); + pps->pic_order_present_flag = h264_u(s, 1); + pps->num_slice_groups_minus1 = h264_ue(s); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = h264_ue(s); + if (pps->slice_group_map_type == 0) { + pps->run_length_minus1 = h264_ue(s); + } else if (pps->slice_group_map_type == 2) { + pps->top_left = h264_ue(s); + pps->bottom_right = h264_ue(s); + } else if (pps->slice_group_map_type == 3 || + pps->slice_group_map_type == 4 || + pps->slice_group_map_type == 5) { + pps->slice_group_change_direction_flag = h264_u(s, 1); + pps->slice_group_change_rate_minus1 = h264_ue(s); + } else if (pps->slice_group_map_type == 6) { + pps->pic_size_in_map_units_minus1 = h264_ue(s); + pps->slice_group_id = h264_ue(s); + } + } + pps->num_ref_idx_l0_active_minus1 = h264_ue(s); + pps->num_ref_idx_l1_active_minus1 = h264_ue(s); + pps->weighted_pred_flag = h264_u(s, 1); + pps->weighted_bipred_idc = h264_u(s, 2); + pps->pic_init_qp_minus26 = h264_se(s); + pps->pic_init_qs_minus26 = h264_se(s); + pps->chroma_qp_index_offset = h264_se(s); + pps->deblocking_filter_control_present_flag = h264_u(s, 1); + pps->constrained_intra_pred_flag = h264_u(s, 1); + pps->redundant_pic_cnt_present_flag = h264_u(s, 1); + h264_rbsp_trailing_bits(s); +} + +void h264_sps_info(struct h264_SPS_t *sps) +{ + int i; + + pr_info("sequence_parameter_set {\n"); + pr_info(" profile_idc: %d\n", sps->profile_idc); + pr_info(" constraint_set0_flag: %d\n", sps->constrained_set0_flag); + pr_info(" constraint_set1_flag: %d\n", sps->constrained_set1_flag); + pr_info(" constraint_set2_flag: %d\n", sps->constrained_set2_flag); + pr_info(" level_idc: %d\n", sps->level_idc); + pr_info(" seq_parameter_set_id: %d\n", sps->seq_parameter_set_id); + + pr_info(" log2_max_frame_num_minus4: %d\n", + sps->log2_max_frame_num_minus4); + pr_info(" pic_order_cnt_type: %d\n", sps->pic_order_cnt_type); + if (sps->pic_order_cnt_type == 0) { + pr_info(" log2_max_pic_order_cnt_lsb_minus4: %d\n", + sps->log2_max_pic_order_cnt_lsb_minus4); + } else if (sps->pic_order_cnt_type == 1) { + pr_info(" delta_pic_order_always_zero_flag: %d\n", + sps->delta_pic_order_always_zero_flag); + pr_info(" offset_for_non_ref_pic: %d\n", + sps->offset_for_non_ref_pic); + pr_info(" offset_for_top_to_bottom_field: %d\n", + sps->offset_for_top_to_bottom_field); + pr_info(" num_ref_frames_in_pic_order_cnt_cycle: %d\n", + sps->num_ref_frames_in_poc_cycle); + for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) { + pr_info(" offset_for_ref_frame[%d]: %d\n", i, + sps->offset_for_ref_frame[i]); + } + } + pr_info(" num_ref_frames: %d\n", sps->num_ref_frames); + pr_info(" gaps_in_frame_num_value_allowed_flag: %d\n", + sps->gaps_in_frame_num_value_allowed_flag); + pr_info(" pic_width_in_mbs_minus1: %d\n", + sps->pic_width_in_mbs_minus1); + pr_info(" pic_height_in_map_units_minus1: %d\n", + sps->pic_height_in_map_units_minus1); + pr_info(" frame_mbs_only_flag: %d\n", + sps->frame_mbs_only_flag); + pr_info(" mb_adaptive_frame_field_flag: %d\n", + sps->mb_adaptive_frame_field_flag); + pr_info(" direct_8x8_inference_flag: %d\n", + sps->direct_8x8_inference_flag); + pr_info(" frame_cropping_flag: %d\n", + sps->frame_cropping_flag); + if (sps->frame_cropping_flag) { + pr_info(" frame_crop_left_offset: %d\n", + sps->frame_crop_left_offset); + pr_info(" frame_crop_right_offset: %d\n", + sps->frame_crop_right_offset); + pr_info(" frame_crop_top_offset: %d\n", + sps->frame_crop_top_offset); + pr_info(" frame_crop_bottom_offset: %d\n", + sps->frame_crop_bottom_offset); + } + pr_info(" vui_parameters_present_flag: %d\n", + sps->vui_parameters_present_flag); + //if (sps->vui_parameters_present_flag) { + // h264_print_vui_parameters(sps->vui_parameters); + //} + + pr_info(" }\n"); +} + +void h264_pps_info(struct h264_PPS_t *pps) +{ + pr_info("pic_parameter_set {\n"); + pr_info(" pic_parameter_set_id: %d\n", + pps->pic_parameter_set_id); + pr_info(" seq_parameter_set_id: %d\n", + pps->seq_parameter_set_id); + pr_info(" entropy_coding_mode_flag: %d\n", + pps->entropy_coding_mode_flag); + pr_info(" pic_order_present_flag: %d\n", + pps->pic_order_present_flag); + pr_info(" num_slice_groups_minus1: %d\n", + pps->num_slice_groups_minus1); + // FIXME: Code for slice groups is missing here. + pr_info(" num_ref_idx_l0_active_minus1: %d\n", + pps->num_ref_idx_l0_active_minus1); + pr_info(" num_ref_idx_l1_active_minus1: %d\n", + pps->num_ref_idx_l1_active_minus1); + pr_info(" weighted_pred_flag: %d\n", pps->weighted_pred_flag); + pr_info(" weighted_bipred_idc: %d\n", pps->weighted_bipred_idc); + pr_info(" pic_init_qp_minus26: %d\n", pps->pic_init_qp_minus26); + pr_info(" pic_init_qs_minus26: %d\n", pps->pic_init_qs_minus26); + pr_info(" chroma_qp_index_offset: %d\n", + pps->chroma_qp_index_offset); + pr_info(" deblocking_filter_control_present_flag: %d\n", + pps->deblocking_filter_control_present_flag); + pr_info(" constrained_intra_pred_flag: %d\n", + pps->constrained_intra_pred_flag); + pr_info(" redundant_pic_cnt_present_flag: %d\n", + pps->redundant_pic_cnt_present_flag); + pr_info(" }\n"); +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h new file mode 100644 index 000000000000..e54e4d3665ff --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h @@ -0,0 +1,141 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _H264_PARSE_H +#define _H264_PARSE_H + +#include "h264_stream.h" + +enum color_model { + CM_UNKNOWN = -1, + CM_YUV = 0, + CM_RGB = 1, + CM_XYZ = 2 +}; + +enum color_format { + CF_UNKNOWN = -1, //!< Unknown color format + YUV400 = 0, //!< Monochrome + YUV420 = 1, //!< 4:2:0 + YUV422 = 2, //!< 4:2:2 + YUV444 = 3 //!< 4:4:4 +}; + +enum pixel_format { + PF_UNKNOWN = -1, //!< Unknown color ordering + UYVY = 0, //!< UYVY + YUY2 = 1, //!< YUY2 + YUYV = 1, //!< YUYV + YVYU = 2, //!< YVYU + BGR = 3, //!< BGR + V210 = 4 //!< Video Clarity 422 format (10 bits) +}; + +//AVC Profile IDC definitions +enum profile_idc{ + NO_PROFILE = 0, //!< disable profile checking for experimental coding (enables FRExt, but disables MV) + FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4" + BASELINE = 66, //!< YUV 4:2:0/8 "Baseline" + MAIN = 77, //!< YUV 4:2:0/8 "Main" + EXTENDED = 88, //!< YUV 4:2:0/8 "Extended" + FREXT_HP = 100, //!< YUV 4:2:0/8 "High" + FREXT_Hi10P = 110, //!< YUV 4:2:0/10 "High 10" + FREXT_Hi422 = 122, //!< YUV 4:2:2/10 "High 4:2:2" + FREXT_Hi444 = 244, //!< YUV 4:4:4/14 "High 4:4:4" + MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High" + STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High" +}; + +/* sequence parameter set */ +struct h264_SPS_t { + bool vailid; + unsigned int profile_idc; + bool constrained_set0_flag; + bool constrained_set1_flag; + bool constrained_set2_flag; + bool constrained_set3_flag; + unsigned int level_idc; + unsigned int seq_parameter_set_id; + unsigned int chroma_format_idc; + bool seq_scaling_matrix_present_flag; + int seq_scaling_list_present_flag[12]; + int ScalingList4x4[6][16]; + int ScalingList8x8[6][64]; + bool UseDefaultScalingMatrix4x4Flag[6]; + bool UseDefaultScalingMatrix8x8Flag[6]; + unsigned int bit_depth_luma_minus8; + unsigned int bit_depth_chroma_minus8; + unsigned int log2_max_frame_num_minus4; + unsigned int pic_order_cnt_type; + unsigned int log2_max_pic_order_cnt_lsb_minus4; + bool delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + unsigned int num_ref_frames_in_poc_cycle; + int offset_for_ref_frame[255]; + int num_ref_frames; + bool gaps_in_frame_num_value_allowed_flag; + unsigned int pic_width_in_mbs_minus1; + unsigned int pic_height_in_map_units_minus1; + bool frame_mbs_only_flag; + bool mb_adaptive_frame_field_flag; + bool direct_8x8_inference_flag; + bool frame_cropping_flag; + unsigned int frame_crop_left_offset; + unsigned int frame_crop_right_offset; + unsigned int frame_crop_top_offset; + unsigned int frame_crop_bottom_offset; + bool vui_parameters_present_flag; + //h264_vui_parameters_t *vui_parameters; + unsigned separate_colour_plane_flag; + int lossless_qpprime_flag; +}; + +/* pic parameter set */ +struct h264_PPS_t { + int pic_parameter_set_id; + int seq_parameter_set_id; + int entropy_coding_mode_flag; + int pic_order_present_flag; + int num_slice_groups_minus1; + int slice_group_map_type; + int run_length_minus1; + int top_left; + int bottom_right; + int slice_group_change_direction_flag; + int slice_group_change_rate_minus1; + int pic_size_in_map_units_minus1; + int slice_group_id; + int num_ref_idx_l0_active_minus1; + int num_ref_idx_l1_active_minus1; + int weighted_pred_flag; + int weighted_bipred_idc; + int pic_init_qp_minus26; + int pic_init_qs_minus26; + int chroma_qp_index_offset; + int deblocking_filter_control_present_flag; + int constrained_intra_pred_flag; + int redundant_pic_cnt_present_flag; +}; + +void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps); +void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps); + +void h264_sps_info(struct h264_SPS_t *sps); +void h264_pps_info(struct h264_PPS_t *pps); + +#endif //_H264_PARSE_H diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c new file mode 100644 index 000000000000..3061568309fc --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c @@ -0,0 +1,111 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include "h264_stream.h" + +void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size) +{ + s->data = data; + s->size = size; + s->bit_pos = 7; + s->byte_pos = 0; +} + +unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n) +{ + unsigned int ret = 0; + unsigned char b = 0; + int i; + + if (n == 0) + return 0; + + for (i = 0; i < n; ++i) { + if (h264_stream_bits_remaining(s) == 0) + ret <<= n - i - 1; + + b = s->data[s->byte_pos]; + if (n - i <= 32) + ret = ret << 1 | BITAT(b, s->bit_pos); + + if (s->bit_pos == 0) { + s->bit_pos = 7; + s->byte_pos++; + } else + s->bit_pos--; + } + + return ret; +} + +unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n) +{ + int prev_bit_pos = s->bit_pos; + int prev_byte_pos = s->byte_pos; + unsigned int ret = h264_stream_read_bits(s, n); + + s->bit_pos = prev_bit_pos; + s->byte_pos = prev_byte_pos; + + return ret; +} + +unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n) +{ + unsigned int ret = 0; + int i; + + if (n == 0) + return 0; + + for (i = 0; i < n; ++i) { + if (h264_stream_bytes_remaining(s) == 0) { + ret <<= (n - i - 1) * 8; + break; + } + + if (n - i <= 4) + ret = ret << 8 | s->data[s->byte_pos]; + + s->byte_pos++; + } + + return ret; +} + +unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n) +{ + int prev_byte_pos = s->byte_pos; + unsigned int ret = h264_stream_read_bytes(s, n); + + s->byte_pos = prev_byte_pos; + + return ret; +} + +int h264_stream_bits_remaining(struct h264_stream_t *s) +{ + return (s->size - s->byte_pos) * 8 + s->bit_pos; +} + +int h264_stream_bytes_remaining(struct h264_stream_t *s) +{ + return s->size - s->byte_pos; +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h new file mode 100644 index 000000000000..d6d2eac88b93 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h @@ -0,0 +1,39 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _H264_STREAM_H +#define _H264_STREAM_H + +#include "utils.h" + +struct h264_stream_t { + unsigned char *data; + unsigned int size; + int bit_pos; + int byte_pos; +}; + +void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size); +unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n); +unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n); +unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n); +unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n); +int h264_stream_bits_remaining(struct h264_stream_t *s); +int h264_stream_bytes_remaining(struct h264_stream_t *s); + +#endif //_H264_STREAM_H + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h new file mode 100644 index 000000000000..26b155271916 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h @@ -0,0 +1,31 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _UTILS_H +#define _UTILS_H + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define CLAMP(x, low, high) \ + (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define BITAT(x, n) ((x & (1 << n)) == (1 << n)) + +typedef unsigned char uint8_t; +typedef int int32_t; +typedef unsigned int uint32_t; + +#endif //_UTILS_H diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c new file mode 100644 index 000000000000..324d30ec2ef5 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c @@ -0,0 +1,736 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include "../vdec_drv_if.h" +#include "../aml_vcodec_util.h" +#include "../aml_vcodec_dec.h" +//#include "../aml_vcodec_intr.h" +#include "../aml_vcodec_adapt.h" +#include "../vdec_drv_base.h" +#include "../aml_vcodec_vfm.h" +#include "h264_stream.h" +#include "h264_parse.h" +#include + +/* h264 NALU type */ +#define NAL_NON_IDR_SLICE 0x01 +#define NAL_IDR_SLICE 0x05 +#define NAL_H264_SEI 0x06 +#define NAL_H264_SPS 0x07 +#define NAL_H264_PPS 0x08 + +#define NAL_TYPE(value) ((value) & 0x1F) + +#define BUF_PREDICTION_SZ (64 * 1024)//(32 * 1024) + +#define MB_UNIT_LEN 16 + +/* motion vector size (bytes) for every macro block */ +#define HW_MB_STORE_SZ 64 + +#define H264_MAX_FB_NUM 17 +#define HDR_PARSING_BUF_SZ 1024 + +#define HEADER_BUFFER_SIZE (32 * 1024) + +/** + * struct h264_fb - h264 decode frame buffer information + * @vdec_fb_va : virtual address of struct vdec_fb + * @y_fb_dma : dma address of Y frame buffer (luma) + * @c_fb_dma : dma address of C frame buffer (chroma) + * @poc : picture order count of frame buffer + * @reserved : for 8 bytes alignment + */ +struct h264_fb { + uint64_t vdec_fb_va; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + int32_t poc; + uint32_t reserved; +}; + +/** + * struct h264_ring_fb_list - ring frame buffer list + * @fb_list : frame buffer arrary + * @read_idx : read index + * @write_idx : write index + * @count : buffer count in list + */ +struct h264_ring_fb_list { + struct h264_fb fb_list[H264_MAX_FB_NUM]; + unsigned int read_idx; + unsigned int write_idx; + unsigned int count; + unsigned int reserved; +}; + +/** + * struct vdec_h264_dec_info - decode information + * @dpb_sz : decoding picture buffer size + * @resolution_changed : resoltion change happen + * @realloc_mv_buf : flag to notify driver to re-allocate mv buffer + * @reserved : for 8 bytes alignment + * @bs_dma : Input bit-stream buffer dma address + * @y_fb_dma : Y frame buffer dma address + * @c_fb_dma : C frame buffer dma address + * @vdec_fb_va : VDEC frame buffer struct virtual address + */ +struct vdec_h264_dec_info { + uint32_t dpb_sz; + uint32_t resolution_changed; + uint32_t realloc_mv_buf; + uint32_t reserved; + uint64_t bs_dma; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + uint64_t vdec_fb_va; +}; + +/** + * struct vdec_h264_vsi - shared memory for decode information exchange + * between VPU and Host. + * The memory is allocated by VPU then mapping to Host + * in vpu_dec_init() and freed in vpu_dec_deinit() + * by VPU. + * AP-W/R : AP is writer/reader on this item + * VPU-W/R: VPU is write/reader on this item + * @hdr_buf : Header parsing buffer (AP-W, VPU-R) + * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R) + * @mv_buf_dma : HW working motion vector buffer dma address (AP-W, VPU-R) + * @list_free : free frame buffer ring list (AP-W/R, VPU-W) + * @list_disp : display frame buffer ring list (AP-R, VPU-W) + * @dec : decode information (AP-R, VPU-W) + * @pic : picture information (AP-R, VPU-W) + * @crop : crop information (AP-R, VPU-W) + */ +struct vdec_h264_vsi { + unsigned char hdr_buf[HDR_PARSING_BUF_SZ]; + char *header_buf; + int sps_size; + int pps_size; + int sei_size; + int head_offset; + uint64_t pred_buf_dma; + uint64_t mv_buf_dma[H264_MAX_FB_NUM]; + struct h264_ring_fb_list list_free; + struct h264_ring_fb_list list_disp; + struct vdec_h264_dec_info dec; + struct vdec_pic_info pic; + struct v4l2_rect crop; +}; + +/** + * struct vdec_h264_inst - h264 decoder instance + * @num_nalu : how many nalus be decoded + * @ctx : point to aml_vcodec_ctx + * @pred_buf : HW working predication buffer + * @mv_buf : HW working motion vector buffer + * @vpu : VPU instance + * @vsi : VPU shared information + */ +struct vdec_h264_inst { + unsigned int num_nalu; + struct aml_vcodec_ctx *ctx; + struct aml_vcodec_mem pred_buf; + struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM]; + //struct vdec_vpu_inst vpu; + struct aml_vdec_adapt vdec; + struct vdec_h264_vsi *vsi; + struct vcodec_vfm_s vfm; +}; + +#define DUMP_FILE_NAME "/data/dump/dump.tmp" +static struct file *filp; +static loff_t file_pos; + +void dump_write(const char __user *buf, size_t count) +{ + mm_segment_t old_fs; + + if (!filp) + return; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + if (count != vfs_write(filp, buf, count, &file_pos)) + pr_err("Failed to write file\n"); + + set_fs(old_fs); +} + +void dump_init(void) +{ + filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644); + if (IS_ERR(filp)) { + pr_err("open dump file failed\n"); + filp = NULL; + } +} + +void dump_deinit(void) +{ + if (filp) { + filp_close(filp, current->files); + filp = NULL; + file_pos = 0; + } +} + +void swap_uv(void *uv, int size) +{ + int i; + __u16 *p = uv; + + size /= 2; + + for (i = 0; i < size; i++, p++) + *p = __swab16(*p); +} + +static void get_pic_info(struct vdec_h264_inst *inst, + struct vdec_pic_info *pic) +{ + *pic = inst->vsi->pic; + + aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); + aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, + pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); +} + +static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr) +{ + cr->left = inst->vsi->crop.left; + cr->top = inst->vsi->crop.top; + cr->width = inst->vsi->crop.width; + cr->height = inst->vsi->crop.height; + + aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz) +{ + *dpb_sz = inst->vsi->dec.dpb_sz; + aml_vcodec_debug(inst, "sz=%d", *dpb_sz); +} + +static int find_start_code(unsigned char *data, unsigned int data_sz) +{ + if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) + return 3; + + if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && + data[3] == 1) + return 4; + + return -1; +} + +static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) +{ + struct vdec_h264_inst *inst = NULL; + int ret = -1; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vdec.format = VFORMAT_H264; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + + vcodec_vfm_init(&inst->vfm); + + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); + goto error_free_inst; + } + + /* probe info from the stream */ + inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } + + /* alloc the header buffer to be used cache sps or spp etc.*/ + inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_vsi; + } + + inst->vsi->pic.visible_width = 1920; + inst->vsi->pic.visible_height = 1080; + inst->vsi->pic.coded_width = 1920; + inst->vsi->pic.coded_height = 1088; + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + + aml_vcodec_debug(inst, "H264 Instance >> %p", inst); + + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; + + dump_init(); + + return 0; + +error_free_vsi: + kfree(inst->vsi); +error_free_inst: + kfree(inst); + *h_vdec = 0; + + return ret; +} + +static int refer_buffer_num(int level_idc, int poc_cnt, + int mb_width, int mb_height) +{ + int max_ref_num = 27; + int size, size_margin = 6; + int pic_size = mb_width * mb_height * 384; + + switch (level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + case 52: + default: + size = 70778880; + break; + } + + size /= pic_size; + size = size + 1; /* need more buffers */ + + if (poc_cnt > size) + size = poc_cnt; + + size = size + size_margin; + if (size > max_ref_num) + size = max_ref_num; + + return size; +} + +static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_h264_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + unsigned int mb_w, mb_h, width, height; + unsigned int crop_unit_x = 0, crop_unit_y = 0; + unsigned int poc_cnt = 0; + + mb_w = sps->pic_width_in_mbs_minus1 + 1; + mb_h = sps->pic_height_in_map_units_minus1 + 1; + + width = mb_w << 4; // 16 + height = (2 - sps->frame_mbs_only_flag) * (mb_h << 4); + + if (sps->frame_cropping_flag) { + if (0 == sps->chroma_format_idc) {// monochrome + crop_unit_x = 1; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } else if (1 == sps->chroma_format_idc) {// 4:2:0 + crop_unit_x = 2; + crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag); + } else if (2 == sps->chroma_format_idc) {// 4:2:2 + crop_unit_x = 2; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } else {// 3 == sps.chroma_format_idc // 4:4:4 + crop_unit_x = 1; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } + } + + width -= crop_unit_x * (sps->frame_crop_left_offset + + sps->frame_crop_right_offset); + height -= crop_unit_y * (sps->frame_crop_top_offset + + sps->frame_crop_bottom_offset); + + /* fill visible area size that be used for EGL. */ + pic->visible_width = width; + pic->visible_height = height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = ALIGN(mb_w, 4) << 4; + pic->coded_height = ALIGN(mb_h, 4) << 4; + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + poc_cnt = sps->pic_order_cnt_type; + if (!poc_cnt) + poc_cnt = (sps->log2_max_pic_order_cnt_lsb_minus4 + 4) << 1; + + dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + + pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + inst->ctx->id, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, dec->dpb_sz); +} + +static int vdec_h264_probe(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out) +{ + struct vdec_h264_inst *inst = + (struct vdec_h264_inst *)h_vdec; + struct h264_stream_t s; + struct h264_SPS_t *sps; + unsigned int nal_type; + int nal_idx; + int real_data_pos, real_data_size; + unsigned char *buf = (unsigned char *)bs->va; + unsigned int size = bs->size; + + nal_idx = find_start_code(buf, size); + if (nal_idx < 0) + return -1; + + nal_type = NAL_TYPE(buf[nal_idx]); + if (nal_type != NAL_H264_SPS) + return -1; + + /* start code plus nal type. */ + real_data_pos = nal_idx + 1; + real_data_size = size - real_data_pos; + + sps = kzalloc(sizeof(struct h264_SPS_t), GFP_KERNEL); + if (sps == NULL) + return -ENOMEM; + + h264_stream_set(&s, &buf[real_data_pos], real_data_size); + h264_sps_parse(&s, sps); + //h264_sps_info(sps); + + fill_vdec_params(inst, sps); + + kfree(sps); + + return 0; +} + +static void vdec_h264_deinit(unsigned long h_vdec) +{ + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + + if (!inst) + return; + + aml_vcodec_debug_enter(inst); + + video_decoder_release(&inst->vdec); + + vcodec_vfm_release(&inst->vfm); + + dump_deinit(); + + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); +} + +static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out) +{ + return get_fb_from_queue(inst->ctx, out); +} + +static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) +{ + struct vframe_s *vf = NULL; + struct vdec_fb *fb = NULL; + + aml_vcodec_debug(inst, "%s() [%d], vfm: %p", + __func__, __LINE__, &inst->vfm); + + vf = peek_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "there is no vframe."); + *out = NULL; + return; + } + + vf = get_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "the vframe is avalid."); + *out = NULL; + return; + } + + atomic_set(&vf->use_cnt, 1); + + aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", + __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); + + fb = (struct vdec_fb *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; + + *out = fb; + + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); + //dump_write(fb->base_y.va, fb->base_y.bytes_used); + //dump_write(fb->base_c.va, fb->base_c.bytes_used); + + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); + + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", + __func__, __LINE__, fb->base_y.va, + (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", + __func__, __LINE__, fb->base_c.va, + (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); +} + +static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, + unsigned long int timestamp, bool *res_chg) +{ + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + struct aml_vdec_adapt *vdec = &inst->vdec; + int nal_start_idx = 0; + int err = 0; + unsigned int nal_start; + unsigned int nal_type; + unsigned char *buf; + unsigned int buf_sz; + int ret = 0; + + /* bs NULL means flush decoder */ + if (bs == NULL) + return 0;//vpu_dec_reset(vpu); + + buf = (unsigned char *)bs->va; + buf_sz = bs->size; + nal_start_idx = find_start_code(buf, buf_sz); + if (nal_start_idx < 0) + goto err_free_fb_out; + + nal_start = buf[nal_start_idx]; + nal_type = NAL_TYPE(buf[nal_start_idx]); + aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, buf_sz); + + if (nal_type == NAL_H264_SPS) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { + err = -EILSEQ; + goto err_free_fb_out; + } + inst->vsi->sps_size = buf_sz; + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); + inst->vsi->head_offset += inst->vsi->sps_size; + } else if (nal_type == NAL_H264_PPS) { + //buf_sz -= nal_start_idx; + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { + err = -EILSEQ; + goto err_free_fb_out; + } + inst->vsi->pps_size = buf_sz; + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); + inst->vsi->head_offset += inst->vsi->pps_size; + } else if (nal_type == NAL_H264_SEI) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { + err = -EILSEQ; + goto err_free_fb_out; + } + inst->vsi->sei_size = buf_sz; + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); + inst->vsi->head_offset += inst->vsi->sei_size; + } else { + char *write_buf = vmalloc(inst->vsi->head_offset + buf_sz); + + memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset); + memcpy(write_buf + inst->vsi->head_offset, buf, buf_sz); + + ret = vdec_vframe_write(vdec, write_buf, + inst->vsi->head_offset + buf_sz, timestamp); + + aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", + write_buf, inst->vsi->head_offset + buf_sz, ret); + + memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); + inst->vsi->head_offset = 0; + inst->vsi->sps_size = 0; + inst->vsi->pps_size = 0; + inst->vsi->sei_size = 0; + + vfree(write_buf); + } + + //err = vpu_dec_start(vpu, data, 2); + /*if (err) + goto err_free_fb_out;*/ + +#if 0 + *res_chg = inst->vsi->dec.resolution_changed; + if (*res_chg) { + struct vdec_pic_info pic; + + aml_vcodec_debug(inst, "- resolution changed -"); + get_pic_info(inst, &pic); + + if (inst->vsi->dec.realloc_mv_buf) { + err = alloc_mv_buf(inst, &pic); + if (err) + goto err_free_fb_out; + } + } +#endif + if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) { + /* wait decoder done interrupt */ + //err = aml_vcodec_wait_for_done_ctx(inst->ctx, aml_INST_IRQ_RECEIVED, WAIT_INTR_TIMEOUT_MS); + /*if (err) + goto err_free_fb_out;*/ + + //vpu_dec_end(vpu); + } + return ret; + +err_free_fb_out: + //put_fb_to_free(inst, fb); + aml_vcodec_err(inst, "NALU[%d] err=%d", inst->num_nalu, err); + + return err; +} + +static int vdec_h264_get_param(unsigned long h_vdec, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + + if (!inst) { + pr_err("the h264 inst of dec is void."); + return -1; + } + + switch (type) { + case GET_PARAM_DISP_FRAME_BUFFER: + vdec_h264_get_vf(inst, out); + break; + + case GET_PARAM_FREE_FRAME_BUFFER: + ret = vdec_h264_get_fb(inst, out); + break; + + case GET_PARAM_PIC_INFO: + get_pic_info(inst, out); + break; + + case GET_PARAM_DPB_SIZE: + get_dpb_size(inst, out); + break; + + case GET_PARAM_CROP_INFO: + get_crop_info(inst, out); + break; + + default: + aml_vcodec_err(inst, "invalid get parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static struct vdec_common_if vdec_h264_if = { + vdec_h264_init, + vdec_h264_probe, + vdec_h264_decode, + vdec_h264_get_param, + vdec_h264_deinit, +}; + +struct vdec_common_if *get_h264_dec_comm_if(void); + +struct vdec_common_if *get_h264_dec_comm_if(void) +{ + return &vdec_h264_if; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk b/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk new file mode 100644 index 000000000000..d9652fb23b4a --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := vcode_m2m +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := vcodec_m2m_test.c +LOCAL_ARM_MODE := arm + +LOCAL_C_INCLUDES := \ + $(JNI_H_INCLUDE) \ + $(BOARD_AML_VENDOR_PATH)/vendor/amlogic/external/ffmpeg + +LOCAL_SHARED_LIBRARIES := \ + libamffmpeg + +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_PREBUILT_LIBS:= \ +# libavcodec:ffmpeg/lib/libavcodec.so \ + +include $(BUILD_MULTI_PREBUILT) diff --git a/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c b/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c new file mode 100644 index 000000000000..5bed46c1644e --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c @@ -0,0 +1,292 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#define INBUF_SIZE (4096) +#define DUMP_DIR "/mnt/video_frames" + +typedef struct VcodecCtx { + AVFormatContext *fmt_ctx; + AVStream *stream; + int nb_streams; + int vst_idx; + char *filename; + pthread_t tid; + pthread_mutex_t pthread_mutex; + pthread_cond_t pthread_cond; +} VcodecCtx; + +static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, + char *filename) +{ + FILE *f; + int i; + + printf("wrap: %d, xsize: %d, ysize: %d, filename: %s\n", wrap, xsize, ysize, filename); + + f = fopen(filename,"w+"); + fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); + + for (i = 0; i < ysize; i++) + fwrite(buf + i * wrap, 1, xsize, f); + fclose(f); +} + +static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, + const char *filename) +{ + char buf[1024]; + int ret; + + ret = avcodec_send_packet(dec_ctx, pkt); + if (ret < 0) { + fprintf(stderr, "Error sending a packet for decoding\n"); + return; + } + + while (ret >= 0) { + ret = avcodec_receive_frame(dec_ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return; + else if (ret < 0) { + fprintf(stderr, "Error during decoding, ret: %s\n", av_err2str(ret)); + break; + } + + //fprintf(stderr, "saving frame %3d\n", dec_ctx->frame_number); + fflush(stdout); + + /* the picture is allocated by the decoder. no need to free it */ + snprintf(buf, sizeof(buf), "%s/frame-%d", filename, dec_ctx->frame_number); + pgm_save(frame->data[0], frame->linesize[0], + frame->width, frame->height, buf); + } +} + +static void* read_thread(void *arg) +{ + int ret, err; + AVFormatContext *ic = NULL; + AVCodecContext *dec_ctx = NULL; + AVStream *stream = NULL; + AVCodec *codec = NULL; + AVPacket pkt1, *pkt = &pkt1; + AVFrame *frame = NULL; + int vst_idx = 0; + int has_video = 0; + unsigned int st_idx = 0; + VcodecCtx *vctx = arg; + + printf("entry read thread, tid: %ld.\n", vctx->tid); + + ic = avformat_alloc_context(); + if (!ic) { + fprintf(stderr, "Could not allocate avformat context.\n"); + return NULL; + } + + err = avformat_open_input(&ic, vctx->filename, NULL, NULL); + if (err < 0) { + fprintf(stderr, "Could not open avformat input.\n"); + return NULL; + } + + err = avformat_find_stream_info(ic, NULL); + if (err < 0) { + fprintf(stderr, "find stream info err.\n"); + return NULL; + } + + for (st_idx = 0; st_idx < ic->nb_streams; st_idx++) { + AVStream *st = ic->streams[st_idx]; + + enum AVMediaType type = st->codecpar->codec_type; + st->discard = AVDISCARD_ALL; + + if (type == AVMEDIA_TYPE_VIDEO) { + st->discard = AVDISCARD_NONE; + vctx->vst_idx = st_idx; + has_video = 1; + break; + } + } + + if (!has_video) { + fprintf(stderr, "no video stream.\n"); + return NULL; + } + + stream = ic->streams[vctx->vst_idx]; + + //codec = avcodec_find_decoder(stream->codecpar->codec_id); + codec = avcodec_find_decoder_by_name("h264_v4l2m2m"); + if (!codec) { + fprintf(stderr, "Unsupported codec with id %d for input stream %d\n", + stream->codecpar->codec_id, stream->index); + return NULL; + } + + dec_ctx = avcodec_alloc_context3(codec); + if (!dec_ctx) { + fprintf(stderr, "Could not allocate video codec context\n"); + return NULL; + } + + err = avcodec_parameters_to_context(dec_ctx, stream->codecpar); + if (err < 0) { + fprintf(stderr, "Could not set paras to context\n"); + return NULL; + } + + av_codec_set_pkt_timebase(dec_ctx, stream->time_base); + dec_ctx->framerate = stream->avg_frame_rate; + + if (avcodec_open2(dec_ctx, codec, NULL) < 0) { + fprintf(stderr, "Could not open codec for input stream %d\n", + stream->index); + return NULL; + } + + printf("fmt ctx: %p, stream: %p, video st idx: %d, num: %d\n", + ic, stream, vst_idx, ic->nb_streams); + printf("format: %s\n",ic->iformat->name); + + ic->flags |= AVFMT_FLAG_GENPTS; + ic->debug = 0xff; + + //if (ic->pb) + // ic->pb->eof_reached = 0; + + frame = av_frame_alloc(); + if (!frame) { + fprintf(stderr, "Could not allocate video frame\n"); + return NULL; + } + + for (;;) { + ret = av_read_frame(ic, pkt); + if (ret < 0) { + if (ret == AVERROR_EOF || avio_feof(ic->pb)) { + printf("read data end, ret: %d.\n", ret); + break; + } + + if (ic->pb && ic->pb->error) + break; + + printf("read data fail, ret: %d.\n", ret); + continue; + } + + if (pkt->stream_index == vctx->vst_idx) { + //packet_queue_put(&is->audioq, pkt); + printf("read video data size: %d.\n", pkt->size); + if (pkt->size) + decode(dec_ctx, frame, pkt, DUMP_DIR); + } else + av_packet_unref(pkt); + } + + /* flush the decoder */ + decode(dec_ctx, frame, NULL, DUMP_DIR); + + avcodec_free_context(&dec_ctx); + av_frame_free(&frame); + + if (ic) + avformat_close_input(&ic); + + printf("read thread exit.\n"); + + pthread_mutex_lock(&vctx->pthread_mutex); + pthread_cond_signal(&vctx->pthread_cond); + pthread_mutex_unlock(&vctx->pthread_mutex); + + return NULL; +} + + +static int open_input_file(const char *filename) +{ + int ret; + VcodecCtx *vctx; + pthread_t pid = pthread_self(); + + vctx = av_mallocz(sizeof(VcodecCtx)); + if (!vctx) + return -1; + + vctx->filename = av_strdup(filename); + if (!vctx->filename) + return -1; + + pthread_mutex_init(&vctx->pthread_mutex, NULL); + pthread_cond_init(&vctx->pthread_cond, NULL); + + ret = pthread_create(&vctx->tid, NULL, read_thread, (void *)vctx); + if (ret == 0) { + pthread_setname_np(pid, "read_thread"); + + pthread_mutex_lock(&vctx->pthread_mutex); + pthread_cond_wait(&vctx->pthread_cond, &vctx->pthread_mutex); + pthread_mutex_unlock(&vctx->pthread_mutex); + } + + printf("creat the read thread, ret: %d.\n", ret); + + return 0; +} + +int main(int argc, char **argv) +{ + int ret; + const char *filename, *outfilename; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n ==> %s/frame-123\n", argv[0], DUMP_DIR); + exit(0); + } + + filename = argv[1]; + outfilename = argv[2]; + + mkdir(DUMP_DIR, 0664); + + /*set debug level*/ + //av_log_set_level(AV_LOG_DEBUG); + + av_register_all(); + + ret = open_input_file(filename); + if (ret < 0) { + fprintf(stderr, "open input file fail.\n"); + goto out; + } + +out: + return ret < 0; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h new file mode 100644 index 000000000000..dfe5d27457df --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h @@ -0,0 +1,64 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _VDEC_DRV_BASE_ +#define _VDEC_DRV_BASE_ + +#include "aml_vcodec_drv.h" + +#include "vdec_drv_if.h" + +struct vdec_common_if { + /** + * (*init)() - initialize decode driver + * @ctx : [in] aml v4l2 context + * @h_vdec : [out] driver handle + */ + int (*init)(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec); + + int (*probe)(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out); + + /** + * (*decode)() - trigger decode + * @h_vdec : [in] driver handle + * @bs : [in] input bitstream + * @fb : [in] frame buffer to store decoded frame + * @res_chg : [out] resolution change happen + */ + int (*decode)(unsigned long h_vdec, struct aml_vcodec_mem *bs, + unsigned long int pts, bool *res_chg); + + /** + * (*get_param)() - get driver's parameter + * @h_vdec : [in] driver handle + * @type : [in] input parameter type + * @out : [out] buffer to store query result + */ + int (*get_param)(unsigned long h_vdec, + enum vdec_get_param_type type, void *out); + + /** + * (*deinit)() - deinitialize driver. + * @h_vdec : [in] driver handle to be deinit + */ + void (*deinit)(unsigned long h_vdec); +}; + +#endif diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c new file mode 100644 index 000000000000..d981260b1361 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c @@ -0,0 +1,138 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include + +#include "vdec_drv_if.h" +#include "aml_vcodec_dec.h" +#include "vdec_drv_base.h" +#include "aml_vcodec_dec_pm.h" +//#include "aml_vpu.h" + +const struct vdec_common_if *get_h264_dec_comm_if(void); +const struct vdec_common_if *get_vp8_dec_comm_if(void); +const struct vdec_common_if *get_vp9_dec_comm_if(void); + +int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) +{ + int ret = 0; + + switch (fourcc) { + case V4L2_PIX_FMT_H264: + ctx->dec_if = get_h264_dec_comm_if(); + break; + /*case V4L2_PIX_FMT_VP8: + ctx->dec_if = get_vp8_dec_comm_if(); + break; + case V4L2_PIX_FMT_VP9: + ctx->dec_if = get_vp9_dec_comm_if(); + break;*/ + default: + return -EINVAL; + } + + aml_vdec_lock(ctx); + //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp + ret = ctx->dec_if->init(ctx, &ctx->drv_handle); + //aml_vcodec_dec_clock_off(&ctx->dev->pm); + aml_vdec_unlock(ctx); + + return ret; +} + +int vdec_if_probe(struct aml_vcodec_ctx *ctx, + struct aml_vcodec_mem *bs, void *out) +{ + int ret = 0; + + aml_vdec_lock(ctx); + ret = ctx->dec_if->probe(ctx->drv_handle, bs, out); + aml_vdec_unlock(ctx); + + return ret; +} + +int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, + unsigned long int timestamp, bool *res_chg) +{ + int ret = 0; + + if (bs) { + if ((bs->dma_addr & 63) != 0) { + aml_v4l2_err("bs dma_addr should 64 byte align"); + return -EINVAL; + } + } + + /*if (fb) { + if (((fb->base_y.dma_addr & 511) != 0) || + ((fb->base_c.dma_addr & 511) != 0)) { + aml_v4l2_err("frame buffer dma_addr should 512 byte align"); + return -EINVAL; + } + }*/ + + if (ctx->drv_handle == 0) + return -EIO; + + //aml_vdec_lock(ctx); + + aml_vcodec_set_curr_ctx(ctx->dev, ctx); + //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp + //enable_irq(ctx->dev->dec_irq); + ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg); + //disable_irq(ctx->dev->dec_irq); + //aml_vcodec_dec_clock_off(&ctx->dev->pm); + aml_vcodec_set_curr_ctx(ctx->dev, NULL); + + //aml_vdec_unlock(ctx); + + return ret; +} + +int vdec_if_get_param(struct aml_vcodec_ctx *ctx, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + + if (ctx->drv_handle == 0) + return -EIO; + + //aml_vdec_lock(ctx); + ret = ctx->dec_if->get_param(ctx->drv_handle, type, out); + //aml_vdec_unlock(ctx); + + return ret; +} + +void vdec_if_deinit(struct aml_vcodec_ctx *ctx) +{ + if (ctx->drv_handle == 0) + return; + + //aml_vdec_lock(ctx); + //aml_vcodec_dec_clock_on(&ctx->dev->pm); + ctx->dec_if->deinit(ctx->drv_handle); + //aml_vcodec_dec_clock_off(&ctx->dev->pm); + //aml_vdec_unlock(ctx); + + ctx->drv_handle = 0; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h new file mode 100644 index 000000000000..c6f461a15ba7 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h @@ -0,0 +1,110 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _VDEC_DRV_IF_H_ +#define _VDEC_DRV_IF_H_ + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +#include "aml_vcodec_util.h" + + +/** + * struct vdec_fb_status - decoder frame buffer status + * @FB_ST_NORMAL : initial state + * @FB_ST_DISPLAY : frmae buffer is ready to be displayed + * @FB_ST_FREE : frame buffer is not used by decoder any more + */ +enum vdec_fb_status { + FB_ST_NORMAL, + FB_ST_DISPLAY, + FB_ST_FREE +}; + +/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER, + * the caller does not own the returned buffer. The buffer will not be + * released before vdec_if_deinit. + * GET_PARAM_DISP_FRAME_BUFFER : get next displayable frame buffer, + * struct vdec_fb** + * GET_PARAM_FREE_FRAME_BUFFER : get non-referenced framebuffer, vdec_fb** + * GET_PARAM_PIC_INFO : get picture info, struct vdec_pic_info* + * GET_PARAM_CROP_INFO : get crop info, struct v4l2_crop* + * GET_PARAM_DPB_SIZE : get dpb size, unsigned int* + */ +enum vdec_get_param_type { + GET_PARAM_DISP_FRAME_BUFFER, + GET_PARAM_FREE_FRAME_BUFFER, + GET_PARAM_PIC_INFO, + GET_PARAM_CROP_INFO, + GET_PARAM_DPB_SIZE +}; + +/** + * struct vdec_fb_node - decoder frame buffer node + * @list : list to hold this node + * @fb : point to frame buffer (vdec_fb), fb could point to frame buffer and + * working buffer this is for maintain buffers in different state + */ +struct vdec_fb_node { + struct list_head list; + struct vdec_fb *fb; +}; + +/** + * vdec_if_init() - initialize decode driver + * @ctx : [in] v4l2 context + * @fourcc : [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9.. + */ +int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc); + +int vdec_if_probe(struct aml_vcodec_ctx *ctx, + struct aml_vcodec_mem *bs, void *out); + +/** + * vdec_if_deinit() - deinitialize decode driver + * @ctx : [in] v4l2 context + * + */ +void vdec_if_deinit(struct aml_vcodec_ctx *ctx); + +/** + * vdec_if_decode() - trigger decode + * @ctx : [in] v4l2 context + * @bs : [in] input bitstream + * @fb : [in] frame buffer to store decoded frame, when null menas parse + * header only + * @res_chg : [out] resolution change happens if current bs have different + * picture width/height + * Note: To flush the decoder when reaching EOF, set input bitstream as NULL. + * + * Return: 0 on success. -EIO on unrecoverable error. + */ +int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, + unsigned long int timestamp, bool *res_chg); + +/** + * vdec_if_get_param() - get driver's parameter + * @ctx : [in] v4l2 context + * @type : [in] input parameter type + * @out : [out] buffer to store query result + */ +int vdec_if_get_param(struct aml_vcodec_ctx *ctx, enum vdec_get_param_type type, + void *out); + +#endif diff --git a/drivers/amlogic/media_modules/common/chips/chips.c b/drivers/amlogic/media_modules/common/chips/chips.c index a9912f498602..63d55ba9fe99 100644 --- a/drivers/amlogic/media_modules/common/chips/chips.c +++ b/drivers/amlogic/media_modules/common/chips/chips.c @@ -31,6 +31,7 @@ #include "chips.h" #include #include +#include "decoder_cpu_ver_info.h" #define VIDEO_FIRMWARE_FATHER_NAME "video" @@ -56,22 +57,25 @@ struct type_name { const char *name; }; static const struct type_name cpu_type_name[] = { - {MESON_CPU_MAJOR_ID_M6, "m6"}, - {MESON_CPU_MAJOR_ID_M6TV, "m6tv"}, - {MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"}, - {MESON_CPU_MAJOR_ID_M8, "m8"}, - {MESON_CPU_MAJOR_ID_MTVD, "mtvd"}, - {MESON_CPU_MAJOR_ID_M8B, "m8b"}, - {MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"}, - {MESON_CPU_MAJOR_ID_M8M2, "m8"}, - {MESON_CPU_MAJOR_ID_GXBB, "gxbb"}, - {MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"}, - {MESON_CPU_MAJOR_ID_GXL, "gxl"}, - {MESON_CPU_MAJOR_ID_GXM, "gxm"}, - {MESON_CPU_MAJOR_ID_TXL, "txl"}, - {MESON_CPU_MAJOR_ID_TXLX, "txlx"}, - {MESON_CPU_MAJOR_ID_G12A, "g12a"}, - {MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_M6, "m6"}, + {AM_MESON_CPU_MAJOR_ID_M6TV, "m6tv"}, + {AM_MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"}, + {AM_MESON_CPU_MAJOR_ID_M8, "m8"}, + {AM_MESON_CPU_MAJOR_ID_MTVD, "mtvd"}, + {AM_MESON_CPU_MAJOR_ID_M8B, "m8b"}, + {AM_MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"}, + {AM_MESON_CPU_MAJOR_ID_M8M2, "m8"}, + {AM_MESON_CPU_MAJOR_ID_GXBB, "gxbb"}, + {AM_MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"}, + {AM_MESON_CPU_MAJOR_ID_GXL, "gxl"}, + {AM_MESON_CPU_MAJOR_ID_GXM, "gxm"}, + {AM_MESON_CPU_MAJOR_ID_TXL, "txl"}, + {AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"}, + {AM_MESON_CPU_MAJOR_ID_G12A, "g12a"}, + {AM_MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_SM1, "sm1"}, + {AM_MESON_CPU_MAJOR_ID_TL1, "tl1"}, + {AM_MESON_CPU_MAJOR_ID_TM2, "tm2"}, {0, NULL}, }; @@ -99,7 +103,7 @@ const char *get_cpu_type_name(void) return get_type_name(cpu_type_name, sizeof(cpu_type_name) / sizeof(struct type_name), - get_cpu_type()); + get_cpu_major_id()); } EXPORT_SYMBOL(get_cpu_type_name); diff --git a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c new file mode 100644 index 000000000000..7818a21b4844 --- /dev/null +++ b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c @@ -0,0 +1,161 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "decoder_cpu_ver_info.h" + +#define DECODE_CPU_VER_ID_NODE_NAME "cpu_ver_name" +#define AM_SUCESS 0 +#define MAJOR_ID_START AM_MESON_CPU_MAJOR_ID_M6 + +static enum AM_MESON_CPU_MAJOR_ID cpu_ver_id = AM_MESON_CPU_MAJOR_ID_MAX; + +static enum AM_MESON_CPU_MAJOR_ID cpu_ver_info[AM_MESON_CPU_MAJOR_ID_MAX - MAJOR_ID_START]= +{ + AM_MESON_CPU_MAJOR_ID_M6, + AM_MESON_CPU_MAJOR_ID_M6TV, + AM_MESON_CPU_MAJOR_ID_M6TVL, + AM_MESON_CPU_MAJOR_ID_M8, + AM_MESON_CPU_MAJOR_ID_MTVD, + AM_MESON_CPU_MAJOR_ID_M8B, + AM_MESON_CPU_MAJOR_ID_MG9TV, + AM_MESON_CPU_MAJOR_ID_M8M2, + AM_MESON_CPU_MAJOR_ID_UNUSE, + AM_MESON_CPU_MAJOR_ID_GXBB, + AM_MESON_CPU_MAJOR_ID_GXTVBB, + AM_MESON_CPU_MAJOR_ID_GXL, + AM_MESON_CPU_MAJOR_ID_GXM, + AM_MESON_CPU_MAJOR_ID_TXL, + AM_MESON_CPU_MAJOR_ID_TXLX, + AM_MESON_CPU_MAJOR_ID_AXG, + AM_MESON_CPU_MAJOR_ID_GXLX, + AM_MESON_CPU_MAJOR_ID_TXHD, + AM_MESON_CPU_MAJOR_ID_G12A, + AM_MESON_CPU_MAJOR_ID_G12B, + AM_MESON_CPU_MAJOR_ID_GXLX2, + AM_MESON_CPU_MAJOR_ID_SM1, + AM_MESON_CPU_MAJOR_ID_RES_0x2c, + AM_MESON_CPU_MAJOR_ID_RES_0x2d, + AM_MESON_CPU_MAJOR_ID_TL1, + AM_MESON_CPU_MAJOR_ID_TM2, +}; + +static const struct of_device_id cpu_ver_of_match[] = { + { + .compatible = "amlogic, cpu-major-id-axg", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_AXG - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-g12a", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_G12A - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-gxl", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXL - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-gxm", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXM - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-txl", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXL - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-txlx", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXLX - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-sm1", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_SM1 - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-tl1", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TL1 - MAJOR_ID_START], + }, + { + .compatible = "amlogic, cpu-major-id-tm2", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TM2 - MAJOR_ID_START], + }, + {}, +}; + +static bool get_cpu_id_from_dtb(enum AM_MESON_CPU_MAJOR_ID *pidType) +{ + struct device_node *pNode = NULL; + struct platform_device* pDev = NULL; + const struct of_device_id *pMatch = NULL; + + pNode = of_find_node_by_name(NULL, DECODE_CPU_VER_ID_NODE_NAME); + if (NULL == pNode) { + pr_err("No find node.\n"); + return -EINVAL; + } + + pDev = of_find_device_by_node(pNode); + if (NULL == pDev) + return -EINVAL; + + pMatch = of_match_device(cpu_ver_of_match, &pDev->dev); + if (NULL == pMatch) { + pr_err("No find of_match_device\n"); + return -EINVAL; + } + + *pidType = *(enum AM_MESON_CPU_MAJOR_ID *)pMatch->data; + + return AM_SUCESS; +} + +static void initial_cpu_id(void) +{ + enum AM_MESON_CPU_MAJOR_ID id_type = AM_MESON_CPU_MAJOR_ID_MAX; + + if (AM_SUCESS == get_cpu_id_from_dtb(&id_type)) + cpu_ver_id = id_type; + else + cpu_ver_id = (enum AM_MESON_CPU_MAJOR_ID)get_cpu_type(); + + if (AM_MESON_CPU_MAJOR_ID_G12B == cpu_ver_id) + if (is_meson_rev_b()) + cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1; +} + +enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void) +{ + if (AM_MESON_CPU_MAJOR_ID_MAX == cpu_ver_id) + initial_cpu_id(); + + return cpu_ver_id; +} +EXPORT_SYMBOL(get_cpu_major_id); diff --git a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h new file mode 100644 index 000000000000..494f5f6fdbfd --- /dev/null +++ b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h @@ -0,0 +1,55 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef DECODER_CPU_VER_INFO_H +#define DECODER_CPU_VER_INFO_H + +enum AM_MESON_CPU_MAJOR_ID +{ + AM_MESON_CPU_MAJOR_ID_M6 = 0x16, + AM_MESON_CPU_MAJOR_ID_M6TV = 0x17, + AM_MESON_CPU_MAJOR_ID_M6TVL = 0x18, + AM_MESON_CPU_MAJOR_ID_M8 = 0x19, + AM_MESON_CPU_MAJOR_ID_MTVD = 0x1A, + AM_MESON_CPU_MAJOR_ID_M8B = 0x1B, + AM_MESON_CPU_MAJOR_ID_MG9TV = 0x1C, + AM_MESON_CPU_MAJOR_ID_M8M2 = 0x1D, + AM_MESON_CPU_MAJOR_ID_UNUSE = 0x1E, + AM_MESON_CPU_MAJOR_ID_GXBB = 0x1F, + AM_MESON_CPU_MAJOR_ID_GXTVBB = 0x20, + AM_MESON_CPU_MAJOR_ID_GXL = 0x21, + AM_MESON_CPU_MAJOR_ID_GXM = 0x22, + AM_MESON_CPU_MAJOR_ID_TXL = 0x23, + AM_MESON_CPU_MAJOR_ID_TXLX = 0x24, + AM_MESON_CPU_MAJOR_ID_AXG = 0x25, + AM_MESON_CPU_MAJOR_ID_GXLX = 0x26, + AM_MESON_CPU_MAJOR_ID_TXHD = 0x27, + AM_MESON_CPU_MAJOR_ID_G12A = 0x28, + AM_MESON_CPU_MAJOR_ID_G12B = 0x29, + AM_MESON_CPU_MAJOR_ID_GXLX2 = 0x2a, + AM_MESON_CPU_MAJOR_ID_SM1 = 0x2b, + AM_MESON_CPU_MAJOR_ID_RES_0x2c, + AM_MESON_CPU_MAJOR_ID_RES_0x2d, + AM_MESON_CPU_MAJOR_ID_TL1 = 0x2e, + AM_MESON_CPU_MAJOR_ID_TM2 = 0x2f, + AM_MESON_CPU_MAJOR_ID_MAX, +}; + +enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void); +#endif diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h index 082d8f457535..e23ac2ad41dd 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h +++ b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h @@ -26,7 +26,7 @@ /*firmware for a special format, to replace the format in the package.*/ -{VIDEO_DECODE, VIDEO_FW_FILE, "h265.bin"}, -{VIDEO_DECODE, VIDEO_FW_FILE, "h264.bin"}, -{VIDEO_DECODE, VIDEO_FW_FILE, "h264_multi.bin"}, +/*{VIDEO_DECODE, VIDEO_FW_FILE, "h265.bin"},*/ +/*{VIDEO_DECODE, VIDEO_FW_FILE, "h264.bin"},*/ +/*{VIDEO_DECODE, VIDEO_FW_FILE, "h264_multi.bin"},*/ diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c index 775f9352c728..f1ea44526448 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c +++ b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c @@ -14,7 +14,6 @@ * more details. * */ - #include #include #include @@ -38,9 +37,10 @@ #include #include #include +#include "../chips/decoder_cpu_ver_info.h" -/* major.minor.revision */ -#define PACK_VERS "v0.0.1" +/* major.minor */ +#define PACK_VERS "v0.1" #define CLASS_NAME "firmware_codec" #define DEV_NAME "firmware_vdec" @@ -79,15 +79,12 @@ int get_firmware_data(unsigned int format, char *buf) struct fw_mgr_s *mgr = g_mgr; struct fw_info_s *info; - if (tee_enabled()) { - pr_info ("tee load firmware fomat = %d\n",(u32)format); - ret = tee_load_video_fw((u32)format, 0); - if (ret == 0) - ret = 1; - else - ret = -1; - return ret; - } + pr_info("[%s], the fw (%s) will be loaded.\n", + tee_enabled() ? "TEE" : "LOCAL", + get_fw_format_name(format)); + + if (tee_enabled()) + return 0; mutex_lock(&mutex); @@ -120,7 +117,7 @@ int get_data_from_name(const char *name, char *buf) struct fw_info_s *info; char *fw_name = __getname(); - if (IS_ERR_OR_NULL(fw_name)) + if (fw_name == NULL) return -ENOMEM; strcat(fw_name, name); @@ -363,11 +360,12 @@ static ssize_t info_show(struct class *class, - sys_tz.tz_minuteswest * 60; time_to_tm(secs, 0, &tm); - pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %s\n", + pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %-8s, %s %s\n", "fmt:", info->data->head.format, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, - "id:", info->data->head.commit, + "cmtid:", info->data->head.commit, + "chgid:", info->data->head.change_id, "mk:", info->data->head.maker); } out: @@ -394,7 +392,7 @@ static int fw_info_fill(void) char *path = __getname(); const char *name; - if (IS_ERR_OR_NULL(path)) + if (path == NULL) return -ENOMEM; for (i = 0; i < info_size; i++) { @@ -408,7 +406,7 @@ static int fw_info_fill(void) continue; files = kzalloc(sizeof(struct fw_files_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(files)) { + if (files == NULL) { __putname(path); return -ENOMEM; } @@ -416,7 +414,9 @@ static int fw_info_fill(void) files->file_type = ucode_info[i].file_type; files->fw_type = ucode_info[i].fw_type; strncpy(files->path, path, sizeof(files->path)); + files->path[sizeof(files->path) - 1] = '\0'; strncpy(files->name, name, sizeof(files->name)); + files->name[sizeof(files->name) - 1] = '\0'; list_add(&files->node, &mgr->files_head); } @@ -448,7 +448,6 @@ static int fw_data_filter(struct firmware_s *fw, int cpu = fw_get_cpu(fw->head.cpu); if (mgr->cur_cpu < cpu) { - pr_info("the fw %s is not match.\n", fw_info->name); kfree(fw_info); kfree(fw); return -1; @@ -477,15 +476,18 @@ static int fw_data_filter(struct firmware_s *fw, /* the cpu ver is lower and needs to be filtered */ if (cpu < fw_get_cpu(info->data->head.cpu)) { - pr_info("the fw %s is not match.\n", - fw_info->name); + if (debug) + pr_info("keep the newer fw (%s) and ignore the older fw (%s).\n", + info->name, fw_info->name); kfree(fw_info); kfree(fw); return 1; } /* removes not match fw from info list */ - pr_info("the fw %s is not match.\n", info->name); + if (debug) + pr_info("drop the old fw (%s) will be load the newer fw (%s).\n", + info->name, fw_info->name); kfree(info->data); fw_del_info(info); } @@ -496,26 +498,30 @@ static int fw_data_filter(struct firmware_s *fw, static int fw_check_pack_version(char *buf) { struct package_s *pack = NULL; - int major, minor, rev, ver = 0; + int major, minor, major_fw, minor_fw, ver = 0; + int ret; pack = (struct package_s *) buf; - sscanf(PACK_VERS, "v%x.%x.%x", &major, &minor, &rev); - ver = (major << 24 | minor << 16 | rev); + ret = sscanf(PACK_VERS, "v%x.%x", &major, &minor); + if (ret != 2) + return -1; - pr_info("the package has %d fws totally.\n", pack->head.total); + ver = (major << 16 | minor); - major = pack->head.version >> 24; - minor = (pack->head.version >> 16) & 0xf; - rev = pack->head.version & 0xff; + if (debug) + pr_info("the package has %d fws totally.\n", pack->head.total); - if (ver < pack->head.version) { - pr_info("the pack ver v%d.%d.%d too higher to unsupport.\n", - major, minor, rev); + major_fw = (pack->head.version >> 16) & 0xff; + minor_fw = pack->head.version & 0xff; + + if (major < major_fw) { + pr_info("the pack ver v%d.%d too higher to unsupport.\n", + major_fw, minor_fw); return -1; } if (ver != pack->head.version) { - pr_info("the fw pack ver v%d.%d.%d is too lower.\n", major, minor, rev); + pr_info("the fw pack ver v%d.%d is too lower.\n", major_fw, minor_fw); pr_info("it may work abnormally so need to be update in time.\n"); } @@ -534,7 +540,7 @@ static int fw_package_parse(struct fw_files_s *files, int try_cnt = 100; char *path = __getname(); - if (IS_ERR_OR_NULL(path)) + if (path == NULL) return -ENOMEM; pack_data = ((struct package_s *)buf)->data; @@ -551,13 +557,13 @@ static int fw_package_parse(struct fw_files_s *files, continue; info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(info)) { + if (info == NULL) { ret = -ENOMEM; goto out; } data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); - if (IS_ERR_OR_NULL(data)) { + if (data == NULL) { kfree(info); ret = -ENOMEM; goto out; @@ -566,8 +572,10 @@ static int fw_package_parse(struct fw_files_s *files, info->file_type = files->file_type; strncpy(info->src_from, files->name, sizeof(info->src_from)); + info->src_from[sizeof(info->src_from) - 1] = '\0'; strncpy(info->name, pack_info->head.name, sizeof(info->name)); + info->name[sizeof(info->name) - 1] = '\0'; info->format = get_fw_format(pack_info->head.format); len = pack_info->head.length; @@ -604,21 +612,25 @@ static int fw_code_parse(struct fw_files_s *files, struct fw_info_s *info; info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(info)) + if (info == NULL) return -ENOMEM; info->data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); - if (IS_ERR_OR_NULL(info->data)) + if (info->data == NULL) { + kfree(info); return -ENOMEM; + } info->file_type = files->file_type; strncpy(info->src_from, files->name, sizeof(info->src_from)); + info->src_from[sizeof(info->src_from) - 1] = '\0'; memcpy(info->data, buf, size); if (!fw_data_check_sum(info->data)) { pr_info("check sum fail !\n"); kfree(info->data); + kfree(info); return -1; } @@ -647,7 +659,7 @@ static int fw_data_binding(void) int ret = 0, magic = 0; struct fw_mgr_s *mgr = g_mgr; struct fw_files_s *files, *tmp; - char *buf = vmalloc(BUFF_SIZE); + char *buf = NULL; int size; if (list_empty(&mgr->files_head)) { @@ -655,6 +667,7 @@ static int fw_data_binding(void) return 0; } + buf = vmalloc(BUFF_SIZE); if (IS_ERR_OR_NULL(buf)) return -ENOMEM; @@ -665,13 +678,9 @@ static int fw_data_binding(void) magic = fw_probe(buf); if (files->file_type == VIDEO_PACKAGE && magic == PACK) { - pr_info("start to parse fw package.\n"); - if (!fw_check_pack_version(buf)) ret = fw_package_parse(files, buf, size); } else if (files->file_type == VIDEO_FW_FILE && magic == CODE) { - pr_info("start to parse fw code.\n"); - ret = fw_code_parse(files, buf, size); } else { list_del(&files->node); @@ -711,7 +720,7 @@ static int fw_mgr_init(void) if (IS_ERR_OR_NULL(g_mgr)) return -ENOMEM; - g_mgr->cur_cpu = get_cpu_type(); + g_mgr->cur_cpu = get_cpu_major_id(); INIT_LIST_HEAD(&g_mgr->files_head); INIT_LIST_HEAD(&g_mgr->fw_head); spin_lock_init(&g_mgr->lock); diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_priv.h b/drivers/amlogic/media_modules/common/firmware/firmware_priv.h index 811fdc6e0159..b8c4da876246 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_priv.h +++ b/drivers/amlogic/media_modules/common/firmware/firmware_priv.h @@ -65,7 +65,8 @@ struct fw_head_s { char commit[16]; int data_size; unsigned int time; - char reserved[128]; + char change_id[16]; + char reserved[112]; }; struct firmware_s { diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.c b/drivers/amlogic/media_modules/common/firmware/firmware_type.c index b2d9f17d6572..609ff6e8611d 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_type.c +++ b/drivers/amlogic/media_modules/common/firmware/firmware_type.c @@ -1,12 +1,31 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include "firmware_type.h" -#include +#include "../chips/decoder_cpu_ver_info.h" static const struct format_name_s format_name[] = { {VIDEO_DEC_MPEG12, "mpeg12"}, {VIDEO_DEC_MPEG12_MULTI, "mpeg12_multi"}, - {VIDEO_DEC_MPEG4_3, "divx311"}, - {VIDEO_DEC_MPEG4_4, "divx4x"}, - {VIDEO_DEC_MPEG4_4_MULTI, "divx4x_multi"}, + {VIDEO_DEC_MPEG4_3, "mpeg4_3"}, + {VIDEO_DEC_MPEG4_4, "mpeg4_4"}, + {VIDEO_DEC_MPEG4_4_MULTI, "mpeg4_4_multi"}, {VIDEO_DEC_MPEG4_5, "xvid"}, {VIDEO_DEC_MPEG4_5_MULTI, "xvid_multi"}, {VIDEO_DEC_H263, "h263"}, @@ -21,8 +40,6 @@ static const struct format_name_s format_name[] = { {VIDEO_DEC_AVS_GXM, "avs_gxm"}, {VIDEO_DEC_AVS_NOCABAC, "avs_no_cabac"}, {VIDEO_DEC_H264, "h264"}, - {VIDEO_DEC_H264_4k2K, "h264_4k2k"}, - {VIDEO_DEC_H264_4k2K_SINGLE, "h264_4k2k_single"}, {VIDEO_DEC_H264_MVC, "h264_mvc"}, {VIDEO_DEC_H264_MVC_GXM, "h264_mvc_gxm"}, {VIDEO_DEC_H264_MULTI, "h264_multi"}, @@ -30,6 +47,7 @@ static const struct format_name_s format_name[] = { {VIDEO_DEC_H264_MULTI_GXM, "h264_multi_gxm"}, {VIDEO_DEC_HEVC, "hevc"}, {VIDEO_DEC_HEVC_MMU, "hevc_mmu"}, + {VIDEO_DEC_HEVC_MMU_SWAP, "hevc_mmu_swap"}, {VIDEO_DEC_HEVC_G12A, "hevc_g12a"}, {VIDEO_DEC_VP9, "vp9"}, {VIDEO_DEC_VP9_MMU, "vp9_mmu"}, @@ -42,10 +60,19 @@ static const struct format_name_s format_name[] = { }; static const struct cpu_type_s cpu_type[] = { - {MESON_CPU_MAJOR_ID_GXL, "gxl"}, - {MESON_CPU_MAJOR_ID_GXM, "gxm"}, - {MESON_CPU_MAJOR_ID_G12A, "g12a"}, - {MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_GXL, "gxl"}, + {AM_MESON_CPU_MAJOR_ID_GXM, "gxm"}, + {AM_MESON_CPU_MAJOR_ID_TXL, "txl"}, + {AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"}, + {AM_MESON_CPU_MAJOR_ID_AXG, "axg"}, + {AM_MESON_CPU_MAJOR_ID_GXLX, "gxlx"}, + {AM_MESON_CPU_MAJOR_ID_TXHD, "txhd"}, + {AM_MESON_CPU_MAJOR_ID_G12A, "g12a"}, + {AM_MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_GXLX2, "gxlx2"}, + {AM_MESON_CPU_MAJOR_ID_SM1, "sm1"}, + {AM_MESON_CPU_MAJOR_ID_TL1, "tl1"}, + {AM_MESON_CPU_MAJOR_ID_TM2, "tm2"}, }; const char *get_fw_format_name(unsigned int format) diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.h b/drivers/amlogic/media_modules/common/firmware/firmware_type.h index f51956bbf561..6c1b3f7bcd7e 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_type.h +++ b/drivers/amlogic/media_modules/common/firmware/firmware_type.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __VIDEO_FIRMWARE_FORMAT_ #define __VIDEO_FIRMWARE_FORMAT_ @@ -44,7 +63,7 @@ #define VIDEO_DEC_MPEG4_4_MULTI TAG('M', '4', '4', 'M') #define VIDEO_DEC_MPEG4_5_MULTI TAG('M', '4', '5', 'M') #define VIDEO_DEC_H263_MULTI TAG('2', '6', '3', 'M') - +#define VIDEO_DEC_HEVC_MMU_SWAP TAG('2', '6', '5', 'S') /* ... */ #define FIRMWARE_MAX (UINT_MAX) @@ -69,7 +88,7 @@ struct cpu_type_s { const char *name; }; -const char *get_firmware_type_name(unsigned int format); +const char *get_fw_format_name(unsigned int format); unsigned int get_fw_format(const char *name); int fw_get_cpu(const char *name); diff --git a/drivers/amlogic/media_modules/common/media_clock/Makefile b/drivers/amlogic/media_modules/common/media_clock/Makefile index 994857a05219..975b5e57c452 100644 --- a/drivers/amlogic/media_modules/common/media_clock/Makefile +++ b/drivers/amlogic/media_modules/common/media_clock/Makefile @@ -3,3 +3,4 @@ media_clock-objs += ../chips/chips.o media_clock-objs += clk/clkg12.o media_clock-objs += clk/clk.o media_clock-objs += switch/amports_gate.o +media_clock-objs += ../chips/decoder_cpu_ver_info.o diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c index 4ffaf12bfb46..b60a08d0805b 100644 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c @@ -33,6 +33,7 @@ #include "../../chips/chips.h" #include "clk_priv.h" #include +#include "../../chips/decoder_cpu_ver_info.h" #define p_vdec() (get_current_vdec_chip()->clk_mgr[VDEC_1]) #define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2]) @@ -336,7 +337,7 @@ int vdec_source_changed_for_clk_set(int format, int width, int height, int fps) || format == VFORMAT_AVS2) { ret_clk = hevc_clock_set(clk); clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { ret_clk = hevc_back_clock_set(clk); clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps; } @@ -344,7 +345,7 @@ int vdec_source_changed_for_clk_set(int format, int width, int height, int fps) ret_clk = hcodec_clock_set(clk); clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps; } else if (format == VFORMAT_H264_4K2K && - get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { + get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_M8) { ret_clk = vdec2_clock_set(clk); clock_source_wxhxfps_saved[VDEC_2] = width * height * fps; ret_clk = vdec_clock_set(clk); @@ -363,7 +364,7 @@ static int register_vdec_clk_mgr_per_cpu(int cputype, struct chip_vdec_clk_s *mgr; - if (cputype != get_cpu_type() || vdec_type >= VDEC_MAX) { + if (cputype != get_cpu_major_id() || vdec_type >= VDEC_MAX) { /* *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n", *vdec_type, cputype); @@ -414,7 +415,7 @@ static int register_vdec_clk_setting_per_cpu(int cputype, struct clk_set_setting *p_setting; - if (cputype != get_cpu_type()) { + if (cputype != get_cpu_major_id()) { /* *pr_info("ignore clk_set_setting for cpu=%d\n", *cputype); diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h index 5fefcbc6c335..9e6c02588b8b 100644 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h @@ -130,7 +130,7 @@ static int __init vdec_init_clk(void) #endif #ifdef VDEC_HAS_HEVC register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) register_vdec_clk_mgr(cpus, VDEC_HEVCB, &vdec_hevc_back_clk_mgr); #endif #ifdef VDEC_HAS_VDEC_HCODEC diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c b/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c index d7111eb63eca..f045bd320889 100644 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c @@ -30,8 +30,11 @@ #include #include "../switch/amports_gate.h" +#include "../../chips/decoder_cpu_ver_info.h" + #define MHz (1000000) #define debug_print pr_info +#define TL1_HEVC_MAX_CLK (800) //#define NO_CLKTREE @@ -395,6 +398,11 @@ static struct clk_set_setting clks_for_formats[] = { 630}, {INT_MAX, 630}, } }, + {/*VFORMAT_AVS2*/ + {{1280*720*30, 100}, {1920*1080*30, 100}, + {1920*1080*60, 166}, {4096*2048*30, 333}, + {4096*2048*60, 630}, {INT_MAX, 630},} + }, }; @@ -492,12 +500,12 @@ static int vdec_clock_init(void) { gp_pll_user_vdec = gp_pll_user_register("vdec", 0, gp_pll_user_cb_vdec); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) is_gp0_div2 = false; else is_gp0_div2 = true; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) { pr_info("used fix clk for vdec clk source!\n"); //update_vdec_clk_config_settings(1); } @@ -597,6 +605,16 @@ static int hevc_clock_init(void) return (gp_pll_user_hevc) ? 0 : -ENOMEM; } +static int hevc_back_clock_init(void) +{ + return 0; +} + +static int hevc_back_clock_set(int clk) +{ + return 0; +} + static int hevc_clock_set(int clk) { int use_gpll = 0; @@ -701,6 +719,10 @@ static int vdec_clock_set(int clk) clk = 667; } + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1 && + get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1) + clk = 800; + if (set_frq_enable && vdec_frq) { pr_info("Set the vdec frq is %u MHz\n", vdec_frq); clk = vdec_frq; @@ -747,7 +769,10 @@ static int hevc_back_clock_set(int clk) if ((clk > 500 && clk != 667)) { if (clock_real_clk[VDEC_HEVCB] == 648) return 648; - clk = 667; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + clk = TL1_HEVC_MAX_CLK; + else + clk = 667; } if (set_frq_enable && hevcb_frq) { @@ -755,7 +780,7 @@ static int hevc_back_clock_set(int clk) clk = hevcb_frq; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) { if ((READ_EFUSE_REG(EFUSE_LIC1) >> 28 & 0x1) && clk > 333) { pr_info("The hevcb clock limit to 333MHz.\n"); clk = 333; @@ -792,7 +817,10 @@ static int hevc_clock_set(int clk) if ((clk > 500 && clk != 667)) { if (clock_real_clk[VDEC_HEVC] == 648) return 648; - clk = 667; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + clk = TL1_HEVC_MAX_CLK; + else + clk = 667; } if (set_frq_enable && hevc_frq) { @@ -977,14 +1005,17 @@ static int vdec_clock_get(enum vdec_type_e core) #define VDEC_HAS_VDEC_HCODEC #define VDEC_HAS_CLK_SETTINGS #define CLK_FOR_CPU {\ - MESON_CPU_MAJOR_ID_GXBB,\ - MESON_CPU_MAJOR_ID_GXTVBB,\ - MESON_CPU_MAJOR_ID_GXL,\ - MESON_CPU_MAJOR_ID_GXM,\ - MESON_CPU_MAJOR_ID_TXL,\ - MESON_CPU_MAJOR_ID_TXLX,\ - MESON_CPU_MAJOR_ID_G12A,\ - MESON_CPU_MAJOR_ID_G12B,\ + AM_MESON_CPU_MAJOR_ID_GXBB,\ + AM_MESON_CPU_MAJOR_ID_GXTVBB,\ + AM_MESON_CPU_MAJOR_ID_GXL,\ + AM_MESON_CPU_MAJOR_ID_GXM,\ + AM_MESON_CPU_MAJOR_ID_TXL,\ + AM_MESON_CPU_MAJOR_ID_TXLX,\ + AM_MESON_CPU_MAJOR_ID_G12A,\ + AM_MESON_CPU_MAJOR_ID_G12B,\ + AM_MESON_CPU_MAJOR_ID_SM1,\ + AM_MESON_CPU_MAJOR_ID_TL1,\ + AM_MESON_CPU_MAJOR_ID_TM2,\ 0} #include "clk.h" diff --git a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c index c6898217300e..beaea5388c05 100644 --- a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c +++ b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c @@ -191,14 +191,9 @@ int amports_clock_gate_init(struct device *dev) } EXPORT_SYMBOL(amports_clock_gate_init); -static int amports_switch_gate(struct gate_switch_node *gate_node, int enable) -{ - return 0; -} int amports_switch_gate(const char *name, int enable) { - amports_switch_gate(0, 0); return 0; } EXPORT_SYMBOL(amports_switch_gate); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c index bb2ea4a504e7..ae50ec2989f8 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -41,11 +42,15 @@ #include "../utils/decoder_mmu_box.h" #include "../utils/decoder_bmmu_box.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + + +#include #define DRIVER_NAME "amvdec_avs" #define MODULE_NAME "amvdec_avs" -#define ENABLE_USER_DATA #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ #define NV21 @@ -91,6 +96,11 @@ #define INT_AMVENCODER INT_MAILBOX_1A #endif + +#define DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE 0x0001 +static u32 dec_control = DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE; + + #define VPP_VD1_POSTBLEND (1 << 10) static int debug_flag; @@ -103,6 +113,7 @@ firmware_sel static int firmware_sel; static int disable_longcabac_trans = 1; +static int support_user_data = 1; int avs_get_debug_flag(void) { @@ -195,10 +206,10 @@ void *avsp_heap_adr; static uint long_cabac_busy; #endif -#ifdef ENABLE_USER_DATA + static void *user_data_buffer; static dma_addr_t user_data_buffer_phys; -#endif + static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); @@ -303,7 +314,6 @@ static void set_frame_info(struct vframe_s *vf, unsigned int *duration) vf->flag = 0; } -#ifdef ENABLE_USER_DATA static struct work_struct userdata_push_work; /* @@ -402,7 +412,7 @@ static void UserDataHandler(void) schedule_work(&userdata_push_work); } } -#endif + #ifdef HANDLE_AVS_IRQ static irqreturn_t vavs_isr(int irq, void *dev_id) @@ -416,8 +426,9 @@ static void vavs_isr(void) u32 repeat_count; u32 picture_type; u32 buffer_index; - - unsigned int pts, pts_valid = 0, offset; + u32 frame_size; + bool force_interlaced_frame = false; + unsigned int pts, pts_valid = 0, offset = 0; u64 pts_us64; if (debug_flag & AVS_DEBUG_UCODE) { if (READ_VREG(AV_SCRATCH_E) != 0) { @@ -437,9 +448,9 @@ static void vavs_isr(void) } #endif -#ifdef ENABLE_USER_DATA + UserDataHandler(); -#endif + reg = READ_VREG(AVS_BUFFEROUT); if (reg) { @@ -450,6 +461,7 @@ static void vavs_isr(void) if (debug_flag & AVS_DEBUG_PRINT) pr_info("AVS OFFSET=%x\n", offset); if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 0, &pts_us64) == 0) { pts_valid = 1; #ifdef DEBUG_PTS @@ -484,6 +496,11 @@ static void vavs_isr(void) } #endif + if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE) + && frame_width == 1920 && frame_height == 1080) { + force_interlaced_frame = true; + } + if (throw_pb_flag && picture_type != I_PICTURE) { if (debug_flag & AVS_DEBUG_PRINT) { @@ -491,7 +508,7 @@ static void vavs_isr(void) picture_type); } WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index)); - } else if (reg & INTERLACE_FLAG) { /* interlace */ + } else if (reg & INTERLACE_FLAG || force_interlaced_frame) { /* interlace */ throw_pb_flag = 0; if (debug_flag & AVS_DEBUG_PRINT) { @@ -544,10 +561,14 @@ static void vavs_isr(void) vf->signal_type = 0; vf->index = buffer_index; vf->duration_pulldown = 0; - vf->type = + if (force_interlaced_frame) { + vf->type = VIDTYPE_INTERLACE_TOP; + }else{ + vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM; + } #ifdef NV21 vf->type |= VIDTYPE_VIU_NV21; #endif @@ -565,9 +586,10 @@ static void vavs_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, buffer_index); - + decoder_do_frame_check(NULL, vf); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -578,8 +600,11 @@ static void vavs_isr(void) } set_frame_info(vf, &dur); vf->bufWidth = 1920; - + if (force_interlaced_frame) + vf->pts = 0; + else vf->pts = next_pts; + if ((repeat_count > 1) && avi_flag) { /* vf->duration = vavs_amstream_dec_info.rate * * repeat_count >> 1; @@ -600,10 +625,14 @@ static void vavs_isr(void) vf->signal_type = 0; vf->index = buffer_index; vf->duration_pulldown = 0; - vf->type = - (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP; + if (force_interlaced_frame) { + vf->type = VIDTYPE_INTERLACE_BOTTOM; + } else { + vf->type = + (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; + } #ifdef NV21 vf->type |= VIDTYPE_VIU_NV21; #endif @@ -619,6 +648,7 @@ static void vavs_isr(void) kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -694,8 +724,10 @@ static void vavs_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, buffer_index); + decoder_do_frame_check(NULL, vf); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -711,7 +743,6 @@ static void vavs_isr(void) */ WRITE_VREG(AVS_BUFFEROUT, 0); } - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); #ifdef HANDLE_AVS_IRQ @@ -777,6 +808,9 @@ static void vavs_vf_put(struct vframe_s *vf, void *op_arg) int vavs_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (frame_dur != 0) @@ -824,6 +858,7 @@ static int vavs_canvas_init(void) u32 decbuf_size, decbuf_y_size, decbuf_uv_size; unsigned long buf_start; int need_alloc_buf_num; + u32 endian; vf_buf_num_used = vf_buf_num; if (buf_size <= 0x00400000) { @@ -874,37 +909,40 @@ static int vavs_canvas_init(void) continue; } #endif - + if (vdec->canvas_mode == CANVAS_BLKMODE_LINEAR) + endian = 7; + else + endian = 0; #ifdef NV21 - canvas_config(canvas_base + canvas_num * i + 0, + canvas_config_ex(canvas_base + canvas_num * i + 0, buf_start, canvas_width, canvas_height, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(canvas_base + canvas_num * i + 1, + vdec->canvas_mode, endian); + canvas_config_ex(canvas_base + canvas_num * i + 1, buf_start + decbuf_y_size, canvas_width, canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + vdec->canvas_mode, endian); #else - canvas_config(canvas_num * i + 0, + canvas_config_ex(canvas_num * i + 0, buf_start, canvas_width, canvas_height, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(canvas_num * i + 1, + vdec->canvas_mode, endian); + canvas_config_ex(canvas_num * i + 1, buf_start + decbuf_y_size, canvas_width / 2, canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(canvas_num * i + 2, + vdec->canvas_mode, endian); + canvas_config_ex(canvas_num * i + 2, buf_start + decbuf_y_size + decbuf_uv_size, canvas_width / 2, canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + vdec->canvas_mode, endian); #endif if (debug_flag & AVS_DEBUG_PRINT) { pr_info("canvas config %d, addr %p\n", i, @@ -995,6 +1033,13 @@ void vavs_recover(void) WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); } #endif + WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset)); + pr_info("support_user_data = %d\n", support_user_data); + if (support_user_data) + WRITE_VREG(AV_SCRATCH_M, 1); + else + WRITE_VREG(AV_SCRATCH_M, 0); + WRITE_VREG(AV_SCRATCH_5, 0); } @@ -1101,10 +1146,12 @@ static int vavs_prot_init(void) } #endif -#ifdef ENABLE_USER_DATA WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset)); - pr_debug("AV_SCRATCH_N = 0x%x\n", READ_VREG(AV_SCRATCH_N)); -#endif + pr_info("support_user_data = %d\n", support_user_data); + if (support_user_data) + WRITE_VREG(AV_SCRATCH_M, 1); + else + WRITE_VREG(AV_SCRATCH_M, 0); return r; } @@ -1195,13 +1242,14 @@ static void vavs_local_reset(void) recover_flag = 1; pr_info("error, local reset\n"); amvdec_stop(); + msleep(100); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); vavs_local_init(); vavs_recover(); -#ifdef ENABLE_USER_DATA + reset_userdata_fifo(1); -#endif + amvdec_start(); recover_flag = 0; @@ -1259,8 +1307,6 @@ static void vavs_notify_work(struct work_struct *work) static void avs_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; @@ -1272,8 +1318,6 @@ static void avs_set_clk(struct work_struct *work) vdec_source_changed(VFORMAT_AVS, frame_width, frame_height, fps); } - - } } static void vavs_put_timer_func(unsigned long arg) @@ -1366,7 +1410,9 @@ static void vavs_put_timer_func(unsigned long arg) } - schedule_work(&set_clk_work); + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; @@ -1488,7 +1534,7 @@ static void init_avsp_long_cabac_buf(void) static s32 vavs_init(void) { - int r, size = -1; + int ret, size = -1; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) @@ -1501,9 +1547,11 @@ static s32 vavs_init(void) amvdec_enable(); + vdec_enable_DMC(NULL); + vavs_local_init(); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) size = get_firmware_data(VIDEO_DEC_AVS, buf); else { if (firmware_sel == 1) @@ -1523,19 +1571,18 @@ static s32 vavs_init(void) return -1; } - if (size == 1) - pr_info("tee load ok\n"); - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) - size = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) + ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); else if (firmware_sel == 1) - size = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", buf); + ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", buf); else - size = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); + ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); - if (size < 0) { + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("AVS: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1544,9 +1591,9 @@ static s32 vavs_init(void) stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ - r = vavs_prot_init(); - if (r < 0) - return r; + ret = vavs_prot_init(); + if (ret < 0) + return ret; #ifdef HANDLE_AVS_IRQ if (vdec_request_irq(VDEC_IRQ_1, vavs_isr, @@ -1569,12 +1616,13 @@ static s32 vavs_init(void) #endif if (vavs_amstream_dec_info.rate != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *)((unsigned long) vavs_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -1592,7 +1640,8 @@ static s32 vavs_init(void) if (firmware_sel == 0) INIT_WORK(&long_cabac_wd_work, long_cabac_do_work); #endif - + vdec_source_changed(VFORMAT_AVS, + 1920, 1080, 30); amvdec_start(); stat |= STAT_VDEC_RUN; @@ -1608,7 +1657,7 @@ static int amvdec_avs_probe(struct platform_device *pdev) pr_info("amvdec_avs memory resource undefined.\n"); return -EFAULT; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) firmware_sel = 1; if (firmware_sel == 1) { @@ -1637,7 +1686,7 @@ static int amvdec_avs_probe(struct platform_device *pdev) vavs_vdec_info_init(); -#ifdef ENABLE_USER_DATA + if (NULL == user_data_buffer) { user_data_buffer = dma_alloc_coherent(amports_get_dma_device(), @@ -1651,22 +1700,22 @@ static int amvdec_avs_probe(struct platform_device *pdev) pr_debug("user_data_buffer = 0x%p, user_data_buffer_phys = 0x%x\n", user_data_buffer, (u32)user_data_buffer_phys); } -#endif + INIT_WORK(&set_clk_work, avs_set_clk); + vdec = pdata; if (vavs_init() < 0) { pr_info("amvdec_avs init failed.\n"); kfree(gvs); gvs = NULL; - + pdata->dec_status = NULL; return -ENODEV; } - vdec = pdata; INIT_WORK(&fatal_error_wd_work, vavs_fatal_error_handler); atomic_set(&error_handler_run, 0); -#ifdef ENABLE_USER_DATA + INIT_WORK(&userdata_push_work, userdata_push_do_work); -#endif + INIT_WORK(¬ify_work, vavs_notify_work); return 0; @@ -1676,11 +1725,10 @@ static int amvdec_avs_remove(struct platform_device *pdev) { cancel_work_sync(&fatal_error_wd_work); atomic_set(&error_handler_run, 0); -#ifdef ENABLE_USER_DATA + cancel_work_sync(&userdata_push_work); -#endif + cancel_work_sync(¬ify_work); - cancel_work_sync(&set_clk_work); if (stat & STAT_VDEC_RUN) { amvdec_stop(); stat &= ~STAT_VDEC_RUN; @@ -1732,7 +1780,7 @@ static int amvdec_avs_remove(struct platform_device *pdev) } #endif if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); fr_hint_status = VDEC_NO_NEED_HINT; @@ -1740,7 +1788,7 @@ static int amvdec_avs_remove(struct platform_device *pdev) stat &= ~STAT_VF_HOOK; } -#ifdef ENABLE_USER_DATA + if (user_data_buffer != NULL) { dma_free_coherent( amports_get_dma_device(), @@ -1750,8 +1798,10 @@ static int amvdec_avs_remove(struct platform_device *pdev) user_data_buffer = NULL; user_data_buffer_phys = 0; } -#endif + + amvdec_disable(); + vdec_disable_DMC(NULL); pic_type = 0; if (mm_blk_handle) { @@ -1767,6 +1817,7 @@ static int amvdec_avs_remove(struct platform_device *pdev) kfree(gvs); gvs = NULL; + cancel_work_sync(&set_clk_work); return 0; } @@ -1808,7 +1859,7 @@ static int __init amvdec_avs_driver_init_module(void) return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) amvdec_avs_profile.profile = "avs+"; vcodec_profile_register(&amvdec_avs_profile); @@ -1879,6 +1930,12 @@ MODULE_PARM_DESC(firmware_sel, "\n firmware_sel\n"); module_param(disable_longcabac_trans, uint, 0664); MODULE_PARM_DESC(disable_longcabac_trans, "\n disable_longcabac_trans\n"); +module_param(dec_control, uint, 0664); +MODULE_PARM_DESC(dec_control, "\n amvdec_vavs decoder control\n"); + +module_param(support_user_data, uint, 0664); +MODULE_PARM_DESC(support_user_data, "\n support_user_data\n"); + module_init(amvdec_avs_driver_init_module); module_exit(amvdec_avs_driver_remove_module); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h index 93a04de603df..8277d202d3cd 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef AVS_H_ #define AVS_H_ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c index 2aca5ebe094d..b5dc44468278 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c index df2adbb7d775..6862180a4f47 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include @@ -481,6 +500,14 @@ void Get_I_Picture_Header(struct avs2_decoder *avs2_dec) hd->curr_RPS.num_to_remove = get_param(rpm_param->p.num_to_remove_cur, "num of removed picture"); +#ifdef SANITY_CHECK + if (hd->curr_RPS.num_to_remove > 8) { + hd->curr_RPS.num_to_remove = 8; + pr_info("Warning, %s: num_to_remove %d beyond range, force to 8\n", + __func__, hd->curr_RPS.num_to_remove); + } +#endif + for (j = 0; j < hd->curr_RPS.num_to_remove; j++) { hd->curr_RPS.remove_pic[j] = get_param( @@ -663,6 +690,13 @@ void Get_PB_Picture_Header(struct avs2_decoder *avs2_dec) get_param( rpm_param->p.num_to_remove_cur, "num of removed picture"); +#ifdef SANITY_CHECK + if (hd->curr_RPS.num_to_remove > 8) { + hd->curr_RPS.num_to_remove = 8; + pr_info("Warning, %s: num_to_remove %d beyond range, force to 8\n", + __func__, hd->curr_RPS.num_to_remove); + } +#endif for (j = 0; j < hd->curr_RPS.num_to_remove; j++) { hd->curr_RPS.remove_pic[j] = @@ -1065,12 +1099,14 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) (avs2_dec->fref[0]->imgtr_fwRefDistance <= img->tr || avs2_dec->fref[1]->imgtr_fwRefDistance >= img->tr)) { - pr_info("wrong reference configuration for B frame"); + pr_info("wrong reference configuration for B frame\n"); pr_info( "fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, img->tr %d\n", avs2_dec->fref[0]->imgtr_fwRefDistance, avs2_dec->fref[1]->imgtr_fwRefDistance, img->tr); + hc->f_rec->error_mark = 1; + avs2_dec->bufmgr_error_flag = 1; return; /* exit(-1);*/ /*******************************************/ } @@ -1111,14 +1147,18 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) && avs2_dec->fref[i]->bg_flag == 0 #ifndef NO_DISPLAY && avs2_dec->fref[i]->vf_ref == 0 - && avs2_dec->fref[i]->to_prepare_disp ==0 + && avs2_dec->fref[i]->to_prepare_disp == 0 #endif ) { break; } } - if (i == avs2_dec->ref_maxbuffer) + if (i == avs2_dec->ref_maxbuffer) { + pr_info( + "%s, warning, no enough buf\n", + __func__); i--; + } hc->f_rec = avs2_dec->fref[i]; hc->currentFrame = hc->f_rec->ref; @@ -1128,11 +1168,17 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) hc->f_rec->temporal_id = hd->cur_layer; #endif hc->f_rec->is_output = 1; +#ifdef AML + hc->f_rec->error_mark = 0; + hc->f_rec->decoded_lcu = 0; + hc->f_rec->slice_type = img->type; +#endif hc->f_rec->refered_by_others = hd->curr_RPS.referd_by_others; if (is_avs2_print_bufmgr_detail()) pr_info( - "%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d\n", - __func__, i, img->tr, img->coding_order); + "%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d img_type %d\n", + __func__, i, img->tr, img->coding_order, + img->type); if (img->type != B_IMG) { for (j = 0; @@ -1181,24 +1227,24 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) #if 1 /*rain*/ if (is_avs2_print_bufmgr_detail()) { - for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { - pr_info( + for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { + pr_info( "fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, is_out %d, bg %d, vf_ref %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", ii, avs2_dec->fref[ii]->index, avs2_dec->fref[ii]->imgcoi_ref, avs2_dec->fref[ii]->imgtr_fwRefDistance, - avs2_dec->fref[ii]->refered_by_others, - avs2_dec->fref[ii]->is_output, - avs2_dec->fref[ii]->bg_flag, - avs2_dec->fref[ii]->vf_ref, - avs2_dec->fref[ii]->ref_poc[0], - avs2_dec->fref[ii]->ref_poc[1], - avs2_dec->fref[ii]->ref_poc[2], - avs2_dec->fref[ii]->ref_poc[3], - avs2_dec->fref[ii]->ref_poc[4], - avs2_dec->fref[ii]->ref_poc[5], - avs2_dec->fref[ii]->ref_poc[6] - ); + avs2_dec->fref[ii]->refered_by_others, + avs2_dec->fref[ii]->is_output, + avs2_dec->fref[ii]->bg_flag, + avs2_dec->fref[ii]->vf_ref, + avs2_dec->fref[ii]->ref_poc[0], + avs2_dec->fref[ii]->ref_poc[1], + avs2_dec->fref[ii]->ref_poc[2], + avs2_dec->fref[ii]->ref_poc[3], + avs2_dec->fref[ii]->ref_poc[4], + avs2_dec->fref[ii]->ref_poc[5], + avs2_dec->fref[ii]->ref_poc[6] + ); } } #endif @@ -1270,7 +1316,7 @@ void flushDPB(struct avs2_decoder *avs2_dec) for (j = 0; j < search_times; j++) { pos = -1; tmp_min = (1 << 20); - //search for min poi picture to display + /*search for min poi picture to display*/ for (i = 0; i < avs2_dec->outprint.buffer_num; i++) { if (avs2_dec->outprint.stdoutdata[i].tr < tmp_min) { pos = i; @@ -1281,20 +1327,23 @@ void flushDPB(struct avs2_decoder *avs2_dec) if (pos != -1) { hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr; report_frame(avs2_dec, &avs2_dec->outprint, pos); - if (avs2_dec->outprint.stdoutdata[pos].typeb == BACKGROUND_IMG && avs2_dec->outprint.stdoutdata[pos].background_picture_output_flag == 0) { + if (avs2_dec->outprint.stdoutdata[pos].typeb + == BACKGROUND_IMG && + avs2_dec->outprint.stdoutdata[pos]. + background_picture_output_flag + == 0) { /*write_GB_frame(hd->p_out_background);*/ - } - else { - write_frame(avs2_dec, avs2_dec->outprint.stdoutdata[pos].tr); + } else { + write_frame(avs2_dec, + avs2_dec->outprint.stdoutdata[pos].tr); } delete_trbuffer(&avs2_dec->outprint, pos); } } - // clear dpb info - for (j = 0; j < REF_MAXBUFFER; j++) - { + /*clear dpb info*/ + for (j = 0; j < REF_MAXBUFFER; j++) { avs2_dec->fref[j]->imgtr_fwRefDistance = -256; avs2_dec->fref[j]->imgcoi_ref = -257; avs2_dec->fref[j]->temporal_id = -1; @@ -1310,19 +1359,19 @@ void cleanRefMVBufRef(int pos) { #if 0 int k, x, y; - //re-init mvbuf + /*re-init mvbuf*/ for (k = 0; k < 2; k++) { for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) { - for (x = 0; x < img->width / MIN_BLOCK_SIZE; x++) { + for (x = 0; x < img->width / MIN_BLOCK_SIZE; x++) fref[pos]->mvbuf[y][x][k] = 0; - } + } } - //re-init refbuf + /*re-init refbuf*/ for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) { - for (x = 0; x < img->width / MIN_BLOCK_SIZE ; x++) { + for (x = 0; x < img->width / MIN_BLOCK_SIZE ; x++) fref[pos]->refbuf[y][x] = -1; - } + } #endif } @@ -1510,6 +1559,7 @@ void write_frame(struct avs2_decoder *avs2_dec, int32_t pos) for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { if (avs2_dec->fref[j]->imgtr_fwRefDistance == pos) { + avs2_dec->fref[j]->imgtr_fwRefDistance_bak = pos; avs2_dec->fref[j]->is_output = -1; avs2_dec->fref[j]->to_prepare_disp = avs2_dec->to_prepare_disp_count++; @@ -1523,7 +1573,8 @@ void write_frame(struct avs2_decoder *avs2_dec, int32_t pos) avs2_dec->fref[j]->temporal_id = -1; #endif if (is_avs2_print_bufmgr_detail()) - pr_info("%s, fref index %d\n", __func__, j); + pr_info("%s, fref index %d\n", + __func__, j); } break; } @@ -1689,6 +1740,7 @@ void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) #endif img->number = 0; img->PrevPicDistanceLsb = 0; + avs2_dec->init_hw_flag = 0; } #endif @@ -1710,6 +1762,7 @@ void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) #endif img->number = 0; img->PrevPicDistanceLsb = 0; + avs2_dec->init_hw_flag = 0; } #endif img->seq_header_indicate = 1; @@ -1772,6 +1825,8 @@ void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) break; case SEQUENCE_END_CODE: + if (is_avs2_print_bufmgr_detail()) + pr_info("SEQUENCE_END_CODE\n"); #ifdef TO_CHECK #if SEQ_CHANGE_CHECKER if (seq_checker_buf != NULL) { @@ -1981,6 +2036,16 @@ int avs2_post_process(struct avs2_decoder *avs2_dec) /* delete the frame that will never be used*/ { int32_t i, j; + if (is_avs2_print_bufmgr_detail()) { + pr_info( + "%s, coding_order %d to remove %d buf: ", + __func__, + img->coding_order, + hd->curr_RPS.num_to_remove); + for (i = 0; i < hd->curr_RPS.num_to_remove; i++) + pr_info("%d ", hd->curr_RPS.remove_pic[i]); + pr_info("\n"); + } for (i = 0; i < hd->curr_RPS.num_to_remove; i++) { for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h index 7f9cca4971c7..e6c28cfddb6b 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h @@ -49,6 +49,7 @@ /* #include */ #define AML +#define SANITY_CHECK #undef NO_DISPLAY /* #include "define.h" */ @@ -792,10 +793,24 @@ struct avs2_frame_s { int vf_ref; int decode_idx; int slice_type; + int32_t imgtr_fwRefDistance_bak; + int32_t error_mark; + int32_t decoded_lcu; #endif #ifndef MV_USE_FIXED_BUF int mv_buf_index; #endif + + /* picture qos infomation*/ + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; }; @@ -1585,6 +1600,17 @@ union param_u { uint16_t chroma_quant_param_delta_cb; uint16_t chroma_quant_param_delta_cr; uint16_t loop_filter_disable; + + uint16_t video_signal_type; + uint16_t color_description; + uint16_t display_primaries_x[3]; + uint16_t display_primaries_y[3]; + uint16_t white_point_x; + uint16_t white_point_y; + uint16_t max_display_mastering_luminance; + uint16_t min_display_mastering_luminance; + uint16_t max_content_light_level; + uint16_t max_picture_average_light_level; } p; struct { uint16_t padding[ALF_BEGIN - RPM_BEGIN]; @@ -1629,7 +1655,8 @@ struct avs2_decoder { int32_t lcu_y_num; int32_t lcu_total; int32_t ref_maxbuffer; - int32_t to_prepare_disp_count; + int32_t to_prepare_disp_count; + int8_t bufmgr_error_flag; #endif }; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c index 16b3c29abefa..cc221610d586 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -53,11 +54,14 @@ #include #include "../utils/config_parser.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include +#include +#define I_ONLY_SUPPORT #define MIX_STREAM_SUPPORT -#define SUPPORT_4K2K - #define G12A_BRINGUP_DEBUG +#define CONSTRAIN_MAX_BUF_NUM #include "vavs2.h" #define HEVC_SHIFT_LENGTH_PROTECT 0x313a @@ -72,6 +76,7 @@ #define HEVC_SAO_MMU_VH0_ADDR 0x363a #define HEVC_SAO_MMU_STATUS 0x3639 + /* * AVS2_DEC_STATUS define */ @@ -109,6 +114,7 @@ /*cmd*/ #define AVS2_10B_DISCARD_NAL 0xf0 +#define AVS2_SEARCH_NEW_PIC 0xf1 #define AVS2_ACTION_ERROR 0xfe #define HEVC_ACTION_ERROR 0xfe #define AVS2_ACTION_DONE 0xff @@ -139,8 +145,67 @@ #define PARSER_CMD_SKIP_CFG_2 0x001b1910 + #define PARSER_CMD_NUMBER 37 +static unsigned short parser_cmd[PARSER_CMD_NUMBER] = { +0x0401, +0x8401, +0x0800, +0x0402, +0x9002, +0x1423, +0x8CC3, +0x1423, +0x8804, +0x9825, +0x0800, +0x04FE, +0x8406, +0x8411, +0x1800, +0x8408, +0x8409, +0x8C2A, +0x9C2B, +0x1C00, +0x840F, +0x8407, +0x8000, +0x8408, +0x2000, +0xA800, +0x8410, +0x04DE, +0x840C, +0x840D, +0xAC00, +0xA000, +0x08C0, +0x08E0, +0xA40E, +0xFC00, +0x7C00 +}; + +static int32_t g_WqMDefault4x4[16] = { + 64, 64, 64, 68, + 64, 64, 68, 72, + 64, 68, 76, 80, + 72, 76, 84, 96 +}; + + +static int32_t g_WqMDefault8x8[64] = { + 64, 64, 64, 64, 68, 68, 72, 76, + 64, 64, 64, 68, 72, 76, 84, 92, + 64, 64, 68, 72, 76, 80, 88, 100, + 64, 68, 72, 80, 84, 92, 100, 112, + 68, 72, 80, 84, 92, 104, 112, 128, + 76, 80, 84, 92, 104, 116, 132, 152, + 96, 100, 104, 116, 124, 140, 164, 188, + 104, 108, 116, 128, 152, 172, 192, 216 +}; /*#define HEVC_PIC_STRUCT_SUPPORT*/ /* to remove, fix build error */ @@ -148,18 +213,13 @@ #define MULTI_INSTANCE_SUPPORT /* #define ERROR_HANDLE_DEBUG */ -#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ -#undef SUPPORT_4K2K -#else -#define SUPPORT_4K2K -#endif #ifndef STAT_KTHREAD #define STAT_KTHREAD 0x40 #endif #ifdef MULTI_INSTANCE_SUPPORT -#define MAX_DECODE_INSTANCE_NUM 9 +#define MAX_DECODE_INSTANCE_NUM 12 #define MULTI_DRIVER_NAME "ammvdec_avs2" #define lock_buffer(dec, flags) \ @@ -178,7 +238,7 @@ static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; #ifdef G12A_BRINGUP_DEBUG -static u32 decode_timeout_val; +static u32 decode_timeout_val = 200; #else static u32 decode_timeout_val = 200; #endif @@ -190,6 +250,9 @@ static u32 work_buf_size = 32 * 1024 * 1024; #endif static u32 mv_buf_margin; +static int pre_decode_buf_level = 0x1000; +static u32 again_threshold = 0x40; + /* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ /* double_write_mode: 0, no double write @@ -258,13 +321,14 @@ static u32 video_signal_type; static u32 pts_unstable; static u32 on_no_keyframe_skiped; +static u32 force_video_signal_type; +static u32 enable_force_video_signal_type; +#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 -#define PROB_SIZE (496 * 2 * 4) -#define PROB_BUF_SIZE (0x5000) -#define COUNT_BUF_SIZE (0x300 * 4 * 4) -/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ -#define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +static const char * const video_format_names[] = { + "component", "PAL", "NTSC", "SECAM", + "MAC", "unspecified", "Reserved", "Reserved" +}; static inline int div_r32(int64_t m, int n) { @@ -272,8 +336,9 @@ static inline int div_r32(int64_t m, int n) return (int)(m/n) */ #ifndef CONFIG_ARM64 - do_div(m, n); - return (int)m; + int64_t qu = 0; + qu = div_s64(m, n); + return (int)qu; #else return (int)(m/n); #endif @@ -346,20 +411,25 @@ typedef unsigned short u16; #define AVS2_DBG_OUT_PTS 0x10 #define AVS2_DBG_PRINT_SOURCE_LINE 0x20 #define AVS2_DBG_PRINT_PARAM 0x40 +#define AVS2_DBG_PRINT_PIC_LIST 0x80 #define AVS2_DBG_SEND_PARAM_WITH_REG 0x100 #define AVS2_DBG_MERGE 0x200 #define AVS2_DBG_DBG_LF_PRINT 0x400 #define AVS2_DBG_REG 0x800 +#define AVS2_DBG_PIC_LEAK 0x1000 +#define AVS2_DBG_PIC_LEAK_WAIT 0x2000 +#define AVS2_DBG_HDR_INFO 0x4000 #define AVS2_DBG_DIS_LOC_ERROR_PROC 0x10000 #define AVS2_DBG_DIS_SYS_ERROR_PROC 0x20000 #define AVS2_DBG_DUMP_PIC_LIST 0x40000 #define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000 -#define AVS2_DBG_HW_RESET 0x100000 +#define AVS2_DBG_FORCE_UNCOMPRESS 0x100000 #define AVS2_DBG_LOAD_UCODE_FROM_FILE 0x200000 #define AVS2_DBG_FORCE_SEND_AGAIN 0x400000 #define AVS2_DBG_DUMP_DATA 0x800000 -#define AVS2_DBG_CACHE 0x1000000 -#define AVS2_DBG_CACHE_HIT_RATE 0x2000000 +#define AVS2_DBG_DUMP_LMEM_BUF 0x1000000 +#define AVS2_DBG_DUMP_RPM_BUF 0x2000000 +#define AVS2_DBG_CACHE 0x4000000 #define IGNORE_PARAM_FROM_CONFIG 0x8000000 /*MULTI_INSTANCE_SUPPORT*/ #define PRINT_FLAG_ERROR 0 @@ -368,11 +438,15 @@ typedef unsigned short u16; #define PRINT_FLAG_VDEC_DATA 0x80000000 #define PRINT_LINE() \ - if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\ - pr_info("%s line %d\n", __func__, __LINE__) + do { \ + if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\ + pr_info("%s line %d\n", __func__, __LINE__);\ + } while (0) static u32 debug; +static u32 debug_again; + bool is_avs2_print_param(void) { bool ret = false; @@ -433,6 +507,7 @@ static void WRITE_VREG_DBG2(unsigned adr, unsigned val) #ifdef AVS2_10B_MMU #define MMU_COMPRESS_HEADER_SIZE 0x48000 +#define MMU_COMPRESS_8K_HEADER_SIZE 0x48000*4 #endif #define INVALID_IDX -1 /* Invalid buffer index.*/ @@ -446,16 +521,16 @@ static void WRITE_VREG_DBG2(unsigned adr, unsigned val) #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) /*buffer + header buffer + workspace*/ #ifdef MV_USE_FIXED_BUF -#define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1) +#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1) #define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) -#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS) +#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) +#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1) #else -#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS + 1) +#define MAX_BMMU_BUFFER_NUM (((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1) #define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) -#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n) -#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS) +#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) +#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n+1) +#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1) #endif /* static void set_canvas(struct AVS2Decoder_s *dec, @@ -554,10 +629,14 @@ struct AVS2Decoder_s { u32 frame_ar; int fatal_error; uint8_t init_flag; + uint8_t first_sc_checked; uint8_t process_busy; #define PROC_STATE_INIT 0 -#define PROC_STATE_DECODESLICE 1 -#define PROC_STATE_SENDAGAIN 2 +#define PROC_STATE_HEAD_DONE 1 +#define PROC_STATE_DECODING 2 +#define PROC_STATE_HEAD_AGAIN 3 +#define PROC_STATE_DECODE_AGAIN 4 +#define PROC_STATE_TEST1 5 uint8_t process_state; u32 ucode_pause_pos; @@ -594,6 +673,7 @@ struct AVS2Decoder_s { unsigned int losless_comp_body_size; u32 video_signal_type; + u32 video_ori_signal_type; int pts_mode; int last_lookup_pts; @@ -629,9 +709,11 @@ struct AVS2Decoder_s { int slice_idx; uint8_t wait_buf; uint8_t error_flag; + unsigned int bufmgr_error_count; /* bit 0, for decoding; bit 1, for displaying */ uint8_t ignore_bufmgr_error; + uint8_t skip_PB_before_I; int PB_skip_mode; int PB_skip_count_after_decoding; /*hw*/ @@ -658,7 +740,22 @@ struct AVS2Decoder_s { int32_t m_varIndTab[NO_VAR_BINS]; struct vframe_s vframe_dummy; - + /* start_decoding_flag, + bit 0, SEQ ready + bit 1, I ready + */ + unsigned char start_decoding_flag; + uint32_t mpred_abv_start_addr; + uint32_t mpred_abv_start_addr_bak; + u8 next_again_flag; + u32 pre_parser_wr_ptr; + int need_cache_size; + u64 sc_start_time; +#ifdef I_ONLY_SUPPORT + u32 i_only; +#endif + int frameinfo_enable; + struct vframe_qos_s vframe_qos; }; static int compute_losless_comp_body_size( @@ -702,6 +799,31 @@ static int avs2_print_cont(struct AVS2Decoder_s *dec, return 0; } +#define PROB_SIZE (496 * 2 * 4) +#define PROB_BUF_SIZE (0x5000) +#define COUNT_BUF_SIZE (0x300 * 4 * 4) +/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ +#define MAX_FRAME_4K_NUM 0x1200 +#define MAX_FRAME_8K_NUM 0x4800 +#define MAX_SIZE_4K (4096 * 2304) +#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) + +static int get_frame_mmu_map_size(struct AVS2Decoder_s *dec) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) + return (MAX_FRAME_8K_NUM * 4); + return (MAX_FRAME_4K_NUM * 4); +} + +static int get_compress_header_size(struct AVS2Decoder_s *dec) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) + return MMU_COMPRESS_8K_HEADER_SIZE; + return MMU_COMPRESS_HEADER_SIZE; +} + static void reset_process_time(struct AVS2Decoder_s *dec) { if (dec->start_process_time) { @@ -720,14 +842,20 @@ static void start_process_time(struct AVS2Decoder_s *dec) dec->last_lcu_idx = 0; } +static void update_decoded_pic(struct AVS2Decoder_s *dec); + static void timeout_process(struct AVS2Decoder_s *dec) { + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; dec->timeout_num++; amhevc_stop(); avs2_print(dec, 0, "%s decoder timeout\n", __func__); - + if (cur_pic) + cur_pic->error_mark = 1; dec->dec_result = DEC_RESULT_DONE; + update_decoded_pic(dec); reset_process_time(dec); vdec_schedule_work(&dec->work); } @@ -788,7 +916,7 @@ static int get_double_write_ratio(struct AVS2Decoder_s *dec, return ratio; } -#define MAX_4K_NUM 0x1200 +//#define MAX_4K_NUM 0x1200 #ifdef AVS2_10B_MMU int avs2_alloc_mmu( struct AVS2Decoder_s *dec, @@ -800,13 +928,36 @@ int avs2_alloc_mmu( { int bit_depth_10 = (bit_depth == AVS2_BITS_10); int picture_size; - int cur_mmu_4k_number; + int cur_mmu_4k_number, max_frame_num; +#ifdef DYNAMIC_ALLOC_HEAD + unsigned long buf_addr; + struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; + if (pic->header_adr == 0) { + if (decoder_bmmu_box_alloc_buf_phy + (dec->bmmu_box, + HEADER_BUFFER_IDX(cur_buf_idx), + MMU_COMPRESS_HEADER_SIZE, + DRIVER_HEADER_NAME, + &buf_addr) < 0){ + avs2_print(dec, 0, + "%s malloc compress header failed %d\n", + DRIVER_HEADER_NAME, cur_buf_idx); + dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; + return -1; + } else + pic->header_adr = buf_addr; + } +#endif picture_size = compute_losless_comp_body_size( dec, pic_width, pic_height, bit_depth_10); cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - if (cur_mmu_4k_number > MAX_4K_NUM) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + if (cur_mmu_4k_number > max_frame_num) { pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", cur_mmu_4k_number, pic_width, pic_height); return -1; @@ -819,7 +970,8 @@ int avs2_alloc_mmu( } #endif -#ifndef MV_USE_FIXED_BUF +#if 0 +/*ndef MV_USE_FIXED_BUF*/ static void dealloc_mv_bufs(struct AVS2Decoder_s *dec) { int i; @@ -986,6 +1138,7 @@ static int get_free_buf_count(struct AVS2Decoder_s *dec) && avs2_dec->fref[i]->bg_flag == 0 #ifndef NO_DISPLAY && avs2_dec->fref[i]->vf_ref == 0 + && avs2_dec->fref[i]->to_prepare_disp == 0 #endif ) { count++; @@ -995,6 +1148,57 @@ static int get_free_buf_count(struct AVS2Decoder_s *dec) return count; } +#ifdef CONSTRAIN_MAX_BUF_NUM +static int get_vf_ref_only_buf_count(struct AVS2Decoder_s *dec) +{ + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + int i; + int count = 0; + for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { + if ((avs2_dec->fref[i]->imgcoi_ref < -256 +#if 0 + || abs(avs2_dec->fref[i]-> + imgtr_fwRefDistance - img->tr) >= 128 +#endif + ) && avs2_dec->fref[i]->is_output == -1 + && avs2_dec->fref[i]->bg_flag == 0 +#ifndef NO_DISPLAY + && avs2_dec->fref[i]->vf_ref > 0 + && avs2_dec->fref[i]->to_prepare_disp == 0 +#endif + ) { + count++; + } + } + + return count; +} + +static int get_used_buf_count(struct AVS2Decoder_s *dec) +{ + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + int i; + int count = 0; + for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { + if ((avs2_dec->fref[i]->imgcoi_ref >= -256 +#if 0 + || abs(avs2_dec->fref[i]-> + imgtr_fwRefDistance - img->tr) >= 128 +#endif + ) || avs2_dec->fref[i]->is_output != -1 + || avs2_dec->fref[i]->bg_flag != 0 +#ifndef NO_DISPLAY + || avs2_dec->fref[i]->vf_ref != 0 + || avs2_dec->fref[i]->to_prepare_disp != 0 +#endif + ) { + count++; + } + } + + return count; +} +#endif int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, struct buff_s *mc_buf_i) { @@ -1021,6 +1225,7 @@ int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, /*int m_uiMaxCUHeight = 1<<7;*/ dec->wait_buf = 0; dec->error_flag = 0; + dec->skip_PB_before_I = 0; dec->pts_mode = PTS_NORMAL; dec->last_pts = 0; @@ -1035,6 +1240,7 @@ int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, dec->buf_num = 0; + dec->bufmgr_error_count = 0; return 0; } @@ -1074,19 +1280,23 @@ static u32 decode_pic_begin; static uint slice_parse_begin; static u32 step; #ifdef MIX_STREAM_SUPPORT -#ifdef SUPPORT_4K2K static u32 buf_alloc_width = 4096; static u32 buf_alloc_height = 2304; -#else -static u32 buf_alloc_width = 1920; -static u32 buf_alloc_height = 1088; -#endif + static u32 dynamic_buf_num_margin; #else static u32 buf_alloc_width; static u32 buf_alloc_height; static u32 dynamic_buf_num_margin = 7; #endif +#ifdef CONSTRAIN_MAX_BUF_NUM +static u32 run_ready_max_vf_only_num; +static u32 run_ready_display_q_num; + /*0: not check + 0xff: avs2_dec.ref_maxbuffer + */ +static u32 run_ready_max_buf_num = 0xff; +#endif static u32 buf_alloc_depth = 10; static u32 buf_alloc_size; /* @@ -1123,23 +1333,20 @@ static u32 max_decoding_time; error handling */ /*error_handle_policy: -bit 0: 0, auto skip error_skip_nal_count nals before error recovery; -1, skip error_skip_nal_count nals before error recovery; -bit 1 (valid only when bit0 == 1): -1, wait vps/sps/pps after error recovery; -bit 2 (valid only when bit0 == 0): -0, auto search after error recovery (avs2_recover() called); -1, manual search after error recovery -(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) - -bit 4: 0, set error_mark after reset/recover - 1, do not set error_mark after reset/recover -bit 5: 0, check total lcu for every picture - 1, do not check total lcu - +bit 0: search seq again if buffer mgr error occur + (buffer mgr error count need big than + re_search_seq_threshold) +bit 1: 1, display from I picture; + 0, display from any correct pic */ -static u32 error_handle_policy; +static u32 error_handle_policy = 1; +/* +re_search_seq_threshold: + bit 7~0: buffer mgr error research seq count + bit 15~8: frame count threshold +*/ +static u32 re_search_seq_threshold = 0x800; /*0x8;*/ /*static u32 parser_sei_enable = 1;*/ static u32 max_buf_num = (REF_BUFFER + 1); @@ -1150,7 +1357,7 @@ static DEFINE_MUTEX(vavs2_mutex); #define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 #define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 -#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 +#define AVS2_ALF_SWAP_BUFFER HEVC_ASSIST_SCRATCH_2 #define HEVC_RCS_BUFFER HEVC_ASSIST_SCRATCH_3 #define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 #define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 @@ -1197,17 +1404,22 @@ bit [17]: for NAL_SEI when bit0 is 0: bit [31:20]: used by ucode for debug purpose */ #define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I - /*set before start decoder*/ + /*DECODE_MODE: set before start decoder + bit 7~0: decode mode + bit 23~16: start_decoding_flag + bit [0] - SEQ_ready + bit [2:1] - I Picture Count + bit 31~24: chip feature + */ #define DECODE_MODE HEVC_ASSIST_SCRATCH_J #define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K - /*read only*/ #define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J -#define RPM_BUF_SIZE (0x400 * 2) -#define LMEM_BUF_SIZE (0x400 * 2) +#define RPM_BUF_SIZE (0x600 * 2) +#define LMEM_BUF_SIZE (0x600 * 2) -#define WORK_BUF_SPEC_NUM 2 +#define WORK_BUF_SPEC_NUM 3 static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = { { /* 8M bytes */ @@ -1392,6 +1604,92 @@ static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = { /* 4096x2304 , 0x120000 per buffer */ .buf_size = 0x120000 * FRAME_BUFFERS, }, +#endif + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x400 * 2, + } + }, + { + .max_width = 4096 * 2, + .max_height = 2304 * 2, + .ipp = { + /*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, + round to 16k*/ + .buf_size = 0x4000 * 2, + }, + .sao_abv = { + .buf_size = 0x30000 * 2, + }, + .sao_vb = { + .buf_size = 0x30000 * 2, + }, + .short_term_rps = { + /*SHORT_TERM_RPS - Max 64 set, 16 entry every set, + total 64x16x2 = 2048 bytes (0x800)*/ + .buf_size = 0x800, + }, + .rcs = { + /*RCS STORE AREA - Max 16 RCS, each has 32 bytes, + total 0x0400 bytes*/ + .buf_size = 0x400, + }, + .sps = { + /*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, + total 0x0800 bytes*/ + .buf_size = 0x800, + }, + .pps = { + /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total + 0x2000 bytes*/ + .buf_size = 0x2000, + }, + .sao_up = { + /*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i + total 0x2800 bytes*/ + .buf_size = 0x2800 * 2, + }, + .swap_buf = { + /*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/ + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + /*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/ + .buf_size = 0x8000 * 2, + }, + .dblk_para = { + .buf_size = 0x40000 * 2, + }, + .dblk_data = { + .buf_size = 0x80000 * 2, + }, + .dblk_data2 = { + .buf_size = 0x80000 * 2, + }, +#ifdef AVS2_10B_MMU + .mmu_vbh = { + .buf_size = 0x5000 * 2, /*2*16*2304/4, 4K*/ + }, +#if 0 + .cm_header = { + /*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ + .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17, + }, +#endif +#endif + .mpred_above = { + .buf_size = 0x8000 * 2, + }, +#ifdef MV_USE_FIXED_BUF + .mpred_mv = { + /*4k2k , 0x100000 per buffer*/ + .buf_size = 0x120000 * FRAME_BUFFERS * 4, + }, #endif .rpm = { .buf_size = RPM_BUF_SIZE, @@ -1582,7 +1880,8 @@ static void init_buff_spec(struct AVS2Decoder_s *dec, static void uninit_mmu_buffers(struct AVS2Decoder_s *dec) { -#ifndef MV_USE_FIXED_BUF +#if 0 +/*ndef MV_USE_FIXED_BUF*/ dealloc_mv_bufs(dec); #endif decoder_mmu_box_free(dec->mmu_box); @@ -1776,12 +2075,14 @@ static int config_pic(struct AVS2Decoder_s *dec, #endif #ifdef AVS2_10B_MMU +#ifndef DYNAMIC_ALLOC_HEAD pic->header_adr = decoder_bmmu_box_get_phy_addr( dec->bmmu_box, HEADER_BUFFER_IDX(pic->index)); avs2_print(dec, AVS2_DBG_BUFMGR_MORE, "buf_size %d, MMU header_adr %d: %ld\n", buf_size, pic->index, pic->header_adr); +#endif #endif i = pic->index; @@ -1820,7 +2121,7 @@ static int config_pic(struct AVS2Decoder_s *dec, dec->mc_buf->buf_end) y_adr = dec->mc_buf->buf_start + i * buf_size; else {*/ - if (buf_size > 0) { + if (buf_size > 0 && pic->cma_alloc_addr == 0) { ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, VF_BUFFER_IDX(i), buf_size, DRIVER_NAME, @@ -1888,9 +2189,15 @@ static int config_pic(struct AVS2Decoder_s *dec, } #ifdef MV_USE_FIXED_BUF #ifdef G12A_BRINGUP_DEBUG - pic->mpred_mv_wr_start_addr = - dec->work_space_buf->mpred_mv.buf_start + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + pic->mpred_mv_wr_start_addr = + dec->work_space_buf->mpred_mv.buf_start + + (pic->index * 0x120000 * 4); + } else { + pic->mpred_mv_wr_start_addr = + dec->work_space_buf->mpred_mv.buf_start + (pic->index * 0x120000); + } #else pic->mpred_mv_wr_start_addr = dec->work_space_buf->mpred_mv.buf_start + @@ -1937,12 +2244,25 @@ static void init_pic_list(struct AVS2Decoder_s *dec, struct avs2_decoder *avs2_dec = &dec->avs2_dec; struct avs2_frame_s *pic; #ifdef AVS2_10B_MMU + unsigned long buf_addr1; /*alloc AVS2 compress header first*/ + if (decoder_bmmu_box_alloc_buf_phy + (dec->bmmu_box, + HEADER_BUFFER_IDX(-1), get_compress_header_size(dec), + DRIVER_HEADER_NAME, + &buf_addr1) < 0){ + avs2_print(dec, 0, + "%s malloc compress header failed %d\n", + DRIVER_HEADER_NAME, -1); + dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; + return; + } +#ifndef DYNAMIC_ALLOC_HEAD for (i = 0; i < dec->used_buf_num; i++) { unsigned long buf_addr; if (decoder_bmmu_box_alloc_buf_phy (dec->bmmu_box, - HEADER_BUFFER_IDX(i), MMU_COMPRESS_HEADER_SIZE, + HEADER_BUFFER_IDX(i), get_compress_header_size(dec), DRIVER_HEADER_NAME, &buf_addr) < 0){ avs2_print(dec, 0, @@ -1953,6 +2273,10 @@ static void init_pic_list(struct AVS2Decoder_s *dec, } } #endif +#endif + dec->frame_height = avs2_dec->img.height; + dec->frame_width = avs2_dec->img.width; + for (i = 0; i < dec->used_buf_num; i++) { if (i == (dec->used_buf_num - 1)) pic = avs2_dec->m_bg; @@ -1994,12 +2318,14 @@ static void init_pic_list_hw(struct AVS2Decoder_s *dec) struct avs2_decoder *avs2_dec = &dec->avs2_dec; struct avs2_frame_s *pic; /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ +#if 0 WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); #ifdef DUAL_CORE_64 WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); +#endif #endif for (i = 0; i < dec->used_buf_num; i++) { if (i == (dec->used_buf_num - 1)) @@ -2008,11 +2334,21 @@ static void init_pic_list_hw(struct AVS2Decoder_s *dec) pic = avs2_dec->fref[i]; if (pic->index < 0) break; - #ifdef AVS2_10B_MMU /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, pic->header_adr | (pic->mc_canvas_y << 8)|0x1);*/ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (pic->index << 8)); + +#ifdef DUAL_CORE_64 + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXLX2) + WRITE_VREG(HEVC2_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (pic->index << 8)); + else + WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (pic->index << 8)); +#endif WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5); #else /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, @@ -2060,33 +2396,32 @@ static void init_pic_list_hw(struct AVS2Decoder_s *dec) static void dump_pic_list(struct AVS2Decoder_s *dec) { -#if 0 + int ii; struct avs2_decoder *avs2_dec = &dec->avs2_dec; - int i; - for (i = 0; i < FRAME_BUFFERS; i++) { - struct avs2_frame_s *pic = - avs2_dec->fref[i]; - if (pic == NULL) - continue; - avs2_print(dec, - 0, - "Buf(%d) index %d mv_buf_index %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n", - i, - pic->index, -#ifndef MV_USE_FIXED_BUF - pic->mv_buf_index, -#else - -1, -#endif - pic->vf_ref, - pic->decode_idx, - pic->slice_type, - pic->pic_w, - pic->pic_h, - pic->cma_alloc_addr - ); + for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { + avs2_print(dec, 0, + "fref[%d]: index %d decode_id %d mvbuf %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, pre %d is_out %d, bg %d, vf_ref %d error %d lcu %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", + ii, avs2_dec->fref[ii]->index, + avs2_dec->fref[ii]->decode_idx, + avs2_dec->fref[ii]->mv_buf_index, + avs2_dec->fref[ii]->imgcoi_ref, + avs2_dec->fref[ii]->imgtr_fwRefDistance, + avs2_dec->fref[ii]->refered_by_others, + avs2_dec->fref[ii]->to_prepare_disp, + avs2_dec->fref[ii]->is_output, + avs2_dec->fref[ii]->bg_flag, + avs2_dec->fref[ii]->vf_ref, + avs2_dec->fref[ii]->error_mark, + avs2_dec->fref[ii]->decoded_lcu, + avs2_dec->fref[ii]->ref_poc[0], + avs2_dec->fref[ii]->ref_poc[1], + avs2_dec->fref[ii]->ref_poc[2], + avs2_dec->fref[ii]->ref_poc[3], + avs2_dec->fref[ii]->ref_poc[4], + avs2_dec->fref[ii]->ref_poc[5], + avs2_dec->fref[ii]->ref_poc[6] + ); } -#endif return; } @@ -2095,6 +2430,8 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) int32_t i; struct avs2_decoder *avs2_dec = &dec->avs2_dec; struct avs2_frame_s *pic; + struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; + /*if (avs2_dec->img.type == I_IMG) return 0; */ @@ -2138,9 +2475,14 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v << 16) | (pic->mc_canvas_u_v << 8) | pic->mc_canvas_y); + + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + i, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); } } else if (avs2_dec->img.type == F_IMG) { avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, @@ -2155,9 +2497,14 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v << 16) | (pic->mc_canvas_u_v << 8) | pic->mc_canvas_y); + + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + i, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); } WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (16 << 8) | (0<<1) | 1); @@ -2183,9 +2530,13 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v << 8) | pic->mc_canvas_y); + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - 1, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + 1, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); pic = avs2_dec->fref[0]; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, @@ -2195,13 +2546,155 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v<<8) | pic->mc_canvas_y); + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - 0, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + 0, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); } return 0; } +#if 0 +static void mcrcc_get_hitrate(void) +{ + u32 tmp; + u32 raw_mcr_cnt; + u32 hit_mcr_cnt; + u32 byp_mcr_cnt_nchoutwin; + u32 byp_mcr_cnt_nchcanv; + int hitrate; + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n"); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1)); + raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1)); + hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1)); + byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1)); + byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + + if (debug & AVS2_DBG_CACHE) { + pr_info("raw_mcr_cnt_total: %d\n",raw_mcr_cnt); + pr_info("hit_mcr_cnt_total: %d\n",hit_mcr_cnt); + pr_info("byp_mcr_cnt_nchoutwin_total: %d\n",byp_mcr_cnt_nchoutwin); + pr_info("byp_mcr_cnt_nchcanv_total: %d\n",byp_mcr_cnt_nchcanv); + } + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1)); + tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("miss_mcr_0_cnt_total: %d\n", tmp); + + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1)); + tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("miss_mcr_1_cnt_total: %d\n", tmp); + + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1)); + tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("hit_mcr_0_cnt_total: %d\n",tmp); + + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1)); + tmp= READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("hit_mcr_1_cnt_total: %d\n",tmp); + + if (raw_mcr_cnt != 0) { + hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("MCRCC_HIT_RATE : %d\n", hitrate); + hitrate = ((byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv) + /raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("MCRCC_BYP_RATE : %d\n", hitrate); + } else if (debug & AVS2_DBG_CACHE) { + pr_info("MCRCC_HIT_RATE : na\n"); + pr_info("MCRCC_BYP_RATE : na\n"); + } + return; +} + + +static void decomp_get_hitrate(void) +{ + u32 raw_mcr_cnt; + u32 hit_mcr_cnt; + int hitrate; + + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered decomp_get_hitrate...\n"); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1)); + raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1)); + hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + + if (debug & AVS2_DBG_CACHE) { + pr_info("hcache_raw_cnt_total: %d\n",raw_mcr_cnt); + pr_info("hcache_hit_cnt_total: %d\n",hit_mcr_cnt); + } + if (raw_mcr_cnt != 0) { + hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate); + } else { + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_HCACHE_HIT_RATE : na\n"); + } + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1)); + raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1)); + hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + + if (debug & AVS2_DBG_CACHE) { + pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt); + pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt); + } + if (raw_mcr_cnt != 0) { + hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate); + } else if (debug & AVS2_DBG_CACHE) { + pr_info("DECOMP_DCACHE_HIT_RATE : na\n"); + } +return; +} + +static void decomp_get_comprate(void) +{ + u32 raw_ucomp_cnt; + u32 fast_comp_cnt; + u32 slow_comp_cnt; + int comprate; + + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered decomp_get_comprate...\n"); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1)); + fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1)); + slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1)); + raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) { + pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt); + pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt); + pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt); + } + + if (raw_ucomp_cnt != 0) { + comprate = ((fast_comp_cnt + slow_comp_cnt) + / raw_ucomp_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_COMP_RATIO : %d\n", comprate); + } else if (debug & AVS2_DBG_CACHE) { + pr_info("DECOMP_COMP_RATIO : na\n"); + } + return; +} +#endif static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec) { @@ -2216,13 +2709,13 @@ static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec) WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); return; } - - #if 0 - mcrcc_get_hitrate(); - decomp_get_hitrate(); - decomp_get_comprate(); - #endif - +/* + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + mcrcc_get_hitrate(); + decomp_get_hitrate(); + decomp_get_comprate(); + } +*/ if ((avs2_dec->img.type == B_IMG) || (avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/ /*Programme canvas0 */ @@ -2353,7 +2846,7 @@ static void config_mpred_hw(struct AVS2Decoder_s *dec) avs2_dec->fref[0]->ref_poc[4], avs2_dec->fref[0]->ref_poc[5], avs2_dec->fref[0]->ref_poc[6] - ); + ); avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, "pic_distance %d, imgtr_next_P %d\n", avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P); @@ -2571,7 +3064,7 @@ static void config_sao_hw(struct AVS2Decoder_s *dec) data32 |= endian; /* Big-Endian per 64-bit */ data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ #if 0 - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { if (get_double_write_mode(dec) == 0) data32 |= 0x2; /*disable double write*/ #ifndef AVS2_10B_MMU @@ -2916,7 +3409,7 @@ static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec) WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) WRITE_VREG(HEVC_RPM_BUFFER, (u32)dec->rpm_phy_addr); - WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start); + WRITE_VREG(AVS2_ALF_SWAP_BUFFER, buf_spec->short_term_rps.buf_start); WRITE_VREG(HEVC_RCS_BUFFER, buf_spec->rcs.buf_start); WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start); WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); @@ -2978,44 +3471,45 @@ static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec) /* use HEVC_CM_HEADER_START_ADDR */ data32 = READ_VREG(HEVC_SAO_CTRL5); data32 |= (1<<10); +#if 1 + if (debug & AVS2_DBG_FORCE_UNCOMPRESS) + data32 |= 0x80; +#endif WRITE_VREG(HEVC_SAO_CTRL5, data32); #endif WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr); +#if 1 +/*MULTI_INSTANCE_SUPPORT*/ + /*new added in simulation???*/ + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, buf_spec->mpred_above.buf_start); +#endif +} +static void decomp_perfcount_reset(void) +{ + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered decomp_perfcount_reset...\n"); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x1); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x0); + return; +} + +static void mcrcc_perfcount_reset(void) +{ + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered mcrcc_perfcount_reset...\n"); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x1); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x0); + return; } static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) { unsigned int data32; + unsigned int decode_mode; int i; - const unsigned short parser_cmd[PARSER_CMD_NUMBER] = { - 0x0401, 0x8401, 0x0800, 0x0402, 0x9002, 0x1423, - 0x8CC3, 0x1423, 0x8804, 0x9825, 0x0800, 0x04FE, - 0x8406, 0x8411, 0x1800, 0x8408, 0x8409, 0x8C2A, - 0x9C2B, 0x1C00, 0x840F, 0x8407, 0x8000, 0x8408, - 0x2000, 0xA800, 0x8410, 0x04DE, 0x840C, 0x840D, - 0xAC00, 0xA000, 0x08C0, 0x08E0, 0xA40E, 0xFC00, - 0x7C00 - }; - const int32_t g_WqMDefault4x4[16] = { - 64, 64, 64, 68, - 64, 64, 68, 72, - 64, 68, 76, 80, - 72, 76, 84, 96 - }; - - const int32_t g_WqMDefault8x8[64] = { - 64, 64, 64, 64, 68, 68, 72, 76, - 64, 64, 64, 68, 72, 76, 84, 92, - 64, 64, 68, 72, 76, 80, 88, 100, - 64, 68, 72, 80, 84, 92, 100, 112, - 68, 72, 80, 84, 92, 104, 112, 128, - 76, 80, 84, 92, 104, 116, 132, 152, - 96, 100, 104, 116, 124, 140, 164, 188, - 104, 108, 116, 128, 152, 172, 192, 216 - }; /*if (debug & AVS2_DBG_BUFMGR_MORE) pr_info("%s\n", __func__);*/ @@ -3083,11 +3577,34 @@ static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); #endif if (!dec->m_ins_flag) - WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE); + decode_mode = DECODE_MODE_SINGLE; else if (vdec_frame_based(hw_to_vdec(dec))) - WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE); + decode_mode = DECODE_MODE_MULTI_FRAMEBASE; else - WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE); + decode_mode = DECODE_MODE_MULTI_STREAMBASE; + if (dec->avs2_dec.bufmgr_error_flag && + (error_handle_policy & 0x1)) { + dec->bufmgr_error_count++; + dec->avs2_dec.bufmgr_error_flag = 0; + if (dec->bufmgr_error_count > + (re_search_seq_threshold & 0xff) + && dec->frame_count > + ((re_search_seq_threshold >> 8) & 0xff)) { + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + dec->start_decoding_flag = 0; + avs2_dec->hd.vec_flag = 1; + dec->skip_PB_before_I = 1; + avs2_print(dec, 0, + "!!Bufmgr error, search seq again (0x%x %d %d)\n", + error_handle_policy, + dec->frame_count, + dec->bufmgr_error_count); + dec->bufmgr_error_count = 0; + } + } + decode_mode |= (dec->start_decoding_flag << 16); + + WRITE_VREG(DECODE_MODE, decode_mode); WRITE_VREG(HEVC_DECODE_SIZE, 0); WRITE_VREG(HEVC_DECODE_COUNT, 0); @@ -3107,6 +3624,22 @@ static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) (1 << 2) | /*parser_mpred_if_en*/ (1 << 0) /*parser_scaler_if_en*/ ); + +#ifdef MULTI_INSTANCE_SUPPORT + WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); + + WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); + + for (i = 0; i < 8; i++) + data32 = READ_VREG(HEVC_MPRED_ABV_START_ADDR); + + WRITE_VREG(DOS_SW_RESET3, (1<<18)); /* reset mpred */ + WRITE_VREG(DOS_SW_RESET3, 0); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); +#endif + /*End of Multi-instance*/ /*Changed to Start MPRED in microcode*/ /* pr_info("[test.c] Start MPRED\n"); @@ -3157,13 +3690,18 @@ static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) else if (get_double_write_mode(dec) == 0x10) data32 |= (0x1 << 9); /*double write only*/ else - data32 |= ((0x1 << 8) |(0x1 << 9)); + data32 |= ((0x1 << 8) | (0x1 << 9)); WRITE_VREG(HEVC_DBLK_CFGB, data32); WRITE_VREG(HEVC_DBLK_CFG0, (1 << 0)); /* [0] rst_sync*/ avs2_print(dec, AVS2_DBG_BUFMGR_MORE, "Bitstream level Init for DBLK .Done.\n"); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + mcrcc_perfcount_reset(); + decomp_perfcount_reset(); + } + return; } @@ -3217,7 +3755,7 @@ static void config_avs2_clk_forced_on(void) -static struct AVS2Decoder_s *gHevc; +static struct AVS2Decoder_s gAVS2Decoder; static void avs2_local_uninit(struct AVS2Decoder_s *dec) { @@ -3231,10 +3769,10 @@ static void avs2_local_uninit(struct AVS2Decoder_s *dec) dec->rpm_addr = NULL; } if (dec->lmem_addr) { - if (dec->lmem_phy_addr) - dma_free_coherent(amports_get_dma_device(), - LMEM_BUF_SIZE, dec->lmem_addr, - dec->lmem_phy_addr); + if (dec->lmem_phy_addr) + dma_free_coherent(amports_get_dma_device(), + LMEM_BUF_SIZE, dec->lmem_addr, + dec->lmem_phy_addr); dec->lmem_addr = NULL; } @@ -3242,7 +3780,7 @@ static void avs2_local_uninit(struct AVS2Decoder_s *dec) if (dec->frame_mmu_map_addr) { if (dec->frame_mmu_map_phy_addr) dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, dec->frame_mmu_map_addr, + get_frame_mmu_map_size(dec), dec->frame_mmu_map_addr, dec->frame_mmu_map_phy_addr); dec->frame_mmu_map_addr = NULL; } @@ -3260,17 +3798,18 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) struct BuffInfo_s *cur_buf_info = NULL; cur_buf_info = &dec->work_space_buf_store; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - memcpy(cur_buf_info, &amvavs2_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + memcpy(cur_buf_info, &amvavs2_workbuff_spec[2], /* 8k */ + sizeof(struct BuffInfo_s)); + else + memcpy(cur_buf_info, &amvavs2_workbuff_spec[1], /* 4k */ + sizeof(struct BuffInfo_s)); + } else memcpy(cur_buf_info, &amvavs2_workbuff_spec[0],/* 1080p */ sizeof(struct BuffInfo_s)); -#else - memcpy(cur_buf_info, &amvavs2_workbuff_spec[0], /* 1080p work space */ - sizeof(struct BuffInfo_s)); -#endif + cur_buf_info->start_adr = dec->buf_start; #ifndef AVS2_10B_MMU dec->mc_buf_spec.buf_end = dec->buf_start + dec->buf_size; @@ -3300,6 +3839,9 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { buf_alloc_width = 1920; buf_alloc_height = 1088; + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + buf_alloc_width = 8192; + buf_alloc_height = 4608; } dec->init_pic_w = buf_alloc_width ? buf_alloc_width : (dec->vavs2_amstream_dec_info.width ? @@ -3309,7 +3851,8 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) (dec->vavs2_amstream_dec_info.height ? dec->vavs2_amstream_dec_info.height : dec->work_space_buf->max_height); -#ifndef MV_USE_FIXED_BUF +#if 0 +/*ndef MV_USE_FIXED_BUF*/ if (init_mv_buf_list(dec) < 0) { pr_err("%s: init_mv_buf_list fail\n", __func__); return -1; @@ -3346,6 +3889,9 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) kfree(dec->rpm_addr); dec->rpm_addr = NULL; return -1; + } else { + avs2_print(dec, AVS2_DBG_BUFMGR, + "rpm_phy_addr %x\n", (u32) dec->rpm_phy_addr); } dec->rpm_ptr = dec->rpm_addr; @@ -3357,7 +3903,10 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) if (dec->lmem_addr == NULL) { pr_err("%s: failed to alloc lmem buffer\n", __func__); return -1; - } + } else + avs2_print(dec, AVS2_DBG_BUFMGR, + "%s, lmem_phy_addr %x\n", + __func__, (u32)dec->lmem_phy_addr); /* dec->lmem_phy_addr = dma_map_single(amports_get_dma_device(), dec->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL); @@ -3374,13 +3923,13 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) #ifdef AVS2_10B_MMU dec->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, + get_frame_mmu_map_size(dec), &dec->frame_mmu_map_phy_addr, GFP_KERNEL); if (dec->frame_mmu_map_addr == NULL) { pr_err("%s: failed to alloc count_buffer\n", __func__); return -1; } - memset(dec->frame_mmu_map_addr, 0, COUNT_BUF_SIZE); + memset(dec->frame_mmu_map_addr, 0, get_frame_mmu_map_size(dec)); /* dec->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), dec->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL); if (dma_mapping_error(amports_get_dma_device(), @@ -3423,6 +3972,7 @@ static void set_canvas(struct AVS2Decoder_s *dec, int canvas_w = ALIGN(pic->pic_w, 64)/4; int canvas_h = ALIGN(pic->pic_h, 32)/4; int blkmode = mem_map_mode; + struct vdec_s *vdec = hw_to_vdec(dec); /*CANVAS_BLKMODE_64X32*/ if (pic->double_write_mode) { canvas_w = pic->pic_w / @@ -3438,8 +3988,15 @@ static void set_canvas(struct AVS2Decoder_s *dec, canvas_w = ALIGN(canvas_w, 64); canvas_h = ALIGN(canvas_h, 32); - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + } canvas_config_ex(pic->y_canvas_index, pic->dw_y_adr, canvas_w, canvas_h, @@ -3470,8 +4027,15 @@ static void set_canvas(struct AVS2Decoder_s *dec, #endif } else { #ifndef AVS2_10B_MMU - pic->y_canvas_index = 128 + pic->index; - pic->uv_canvas_index = 128 + pic->index; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index; + pic->uv_canvas_index = 128 + pic->index; + } canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, @@ -3577,20 +4141,36 @@ static struct vframe_s *vavs2_vf_get(void *op_arg) if (kfifo_get(&dec->display_q, &vf)) { uint8_t index = vf->index & 0xff; - - if (index >= 0 && index < dec->used_buf_num) { + if (index >= 0 && index < dec->used_buf_num) { struct avs2_frame_s *pic = get_pic_by_index(dec, index); - dec->vf_get_count++; + if (pic == NULL && + (debug & AVS2_DBG_PIC_LEAK)) { + int i; + avs2_print(dec, 0, + "%s error index 0x%x pic not exist\n", + __func__, index); + dump_pic_list(dec); + for (i = 0; i < 10; i++) { + pic = get_pic_by_index(dec, index); + pr_info("pic = %p\n", pic); + } + + if (debug & AVS2_DBG_PIC_LEAK) + debug |= AVS2_DBG_PIC_LEAK_WAIT; + return NULL; + } + dec->vf_get_count++; + if (pic) avs2_print(dec, AVS2_DBG_BUFMGR, - "%s index 0x%x pos %d getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n", - __func__, index, - pic->imgtr_fwRefDistance, - dec->vf_get_count, - vf->type, - vf->width, vf->height, - vf->pts, - vf->pts_us64); - return vf; + "%s index 0x%x pos %d getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n", + __func__, index, + pic->imgtr_fwRefDistance_bak, + dec->vf_get_count, + vf->type, + vf->width, vf->height, + vf->pts, + vf->pts_us64); + return vf; } } return NULL; @@ -3667,11 +4247,72 @@ static struct avs2_frame_s *get_disp_pic(struct AVS2Decoder_s *dec) } + + +static void fill_frame_info(struct AVS2Decoder_s *dec, + struct avs2_frame_s *pic, unsigned int framesize, unsigned int pts) +{ + struct vframe_qos_s *vframe_qos = &dec->vframe_qos; + + if (pic->slice_type == I_IMG) + vframe_qos->type = 1; + else if (pic->slice_type == P_IMG) + vframe_qos->type = 2; + else if (pic->slice_type == B_IMG) + vframe_qos->type = 3; +/* +#define SHOW_QOS_INFO +*/ + vframe_qos->size = framesize; + vframe_qos->pts = pts; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "slice:%d\n", pic->slice_type); +#endif + + + vframe_qos->max_mv = pic->max_mv; + vframe_qos->avg_mv = pic->avg_mv; + vframe_qos->min_mv = pic->min_mv; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "mv: max:%d, avg:%d, min:%d\n", + vframe_qos->max_mv, + vframe_qos->avg_mv, + vframe_qos->min_mv); +#endif + + vframe_qos->max_qp = pic->max_qp; + vframe_qos->avg_qp = pic->avg_qp; + vframe_qos->min_qp = pic->min_qp; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "qp: max:%d, avg:%d, min:%d\n", + vframe_qos->max_qp, + vframe_qos->avg_qp, + vframe_qos->min_qp); +#endif + + vframe_qos->max_skip = pic->max_skip; + vframe_qos->avg_skip = pic->avg_skip; + vframe_qos->min_skip = pic->min_skip; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "skip: max:%d, avg:%d, min:%d\n", + vframe_qos->max_skip, + vframe_qos->avg_skip, + vframe_qos->min_skip); +#endif + + vframe_qos->num++; + + if (dec->frameinfo_enable) + vdec_fill_frame_info(vframe_qos, 1); +} + static void set_vframe(struct AVS2Decoder_s *dec, struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy) { unsigned long flags; int stream_offset; + unsigned int frame_size; + int pts_discontinue; stream_offset = pic->stream_offset; avs2_print(dec, AVS2_DBG_BUFMGR, "%s index = %d pos = %d\r\n", @@ -3693,7 +4334,8 @@ static void set_vframe(struct AVS2Decoder_s *dec, /* if (pts_lookup_offset(PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0) != 0) { */ if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, + (PTS_TYPE_VIDEO, stream_offset, + &vf->pts, &frame_size, 0, &vf->pts_us64) != 0) { #ifdef DEBUG_PTS dec->pts_missed++; @@ -3708,6 +4350,8 @@ static void set_vframe(struct AVS2Decoder_s *dec, if (pts_unstable) dec->pts_mode = PTS_NONE_REF_USE_DURATION; + fill_frame_info(dec, pic, frame_size, vf->pts); + if ((dec->pts_mode == PTS_NORMAL) && (vf->pts != 0) && dec->get_frame_dur) { int pts_diff = (int)vf->pts - dec->last_lookup_pts; @@ -3734,11 +4378,16 @@ static void set_vframe(struct AVS2Decoder_s *dec, } } + pts_discontinue = + (abs(dec->last_pts - vf->pts) >= + tsync_vpts_discontinuity_margin()); + if (vf->pts != 0) dec->last_lookup_pts = vf->pts; -#if 0 +#if 1 if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != KEY_FRAME)) + && ((pic->slice_type != I_IMG) || (!pts_discontinue && + !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) vf->pts = dec->last_pts + DUR2PTS(dec->frame_dur); #endif dec->last_pts = vf->pts; @@ -3746,9 +4395,10 @@ static void set_vframe(struct AVS2Decoder_s *dec, if (vf->pts_us64 != 0) dec->last_lookup_pts_us64 = vf->pts_us64; -#if 0 +#if 1 if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != KEY_FRAME)) { + && ((pic->slice_type != I_IMG) || (!pts_discontinue && + !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) { vf->pts_us64 = dec->last_pts_us64 + (DUR2PTS(dec->frame_dur) * 100 / 9); @@ -3757,17 +4407,16 @@ static void set_vframe(struct AVS2Decoder_s *dec, dec->last_pts_us64 = vf->pts_us64; avs2_print(dec, AVS2_DBG_OUT_PTS, "avs2 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n", - vf->pts, vf->pts_us64); + vf->pts, vf->pts_us64); + } - } + vf->index = 0xff00 | pic->index; - vf->index = 0xff00 | pic->index; - - if (pic->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { + if (pic->double_write_mode & 0x10) { + /* double write only */ + vf->compBodyAddr = 0; + vf->compHeadAddr = 0; + } else { #ifdef AVS2_10B_MMU vf->compBodyAddr = 0; vf->compHeadAddr = pic->header_adr; @@ -3777,109 +4426,109 @@ static void set_vframe(struct AVS2Decoder_s *dec, pic->comp_body_size; /*head adr*/ #endif - } - if (pic->double_write_mode) { - vf->type = VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if (pic->double_write_mode == 3) { - vf->type |= VIDTYPE_COMPRESS; + } + if (pic->double_write_mode) { + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; + if (pic->double_write_mode == 3) { + vf->type |= VIDTYPE_COMPRESS; +#ifdef AVS2_10B_MMU + vf->type |= VIDTYPE_SCATTER; +#endif + } +#ifdef MULTI_INSTANCE_SUPPORT + if (dec->m_ins_flag) { + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 2; + vf->canvas0_config[0] = + pic->canvas_config[0]; + vf->canvas0_config[1] = + pic->canvas_config[1]; + + vf->canvas1_config[0] = + pic->canvas_config[0]; + vf->canvas1_config[1] = + pic->canvas_config[1]; + + } else +#endif + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(pic); + } else { + vf->canvas0Addr = vf->canvas1Addr = 0; + vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; #ifdef AVS2_10B_MMU vf->type |= VIDTYPE_SCATTER; #endif } -#ifdef MULTI_INSTANCE_SUPPORT - if (dec->m_ins_flag) { - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - pic->canvas_config[0]; - vf->canvas0_config[1] = - pic->canvas_config[1]; - vf->canvas1_config[0] = - pic->canvas_config[0]; - vf->canvas1_config[1] = - pic->canvas_config[1]; + switch (pic->bit_depth) { + case AVS2_BITS_8: + vf->bitdepth = BITDEPTH_Y8 | + BITDEPTH_U8 | BITDEPTH_V8; + break; + case AVS2_BITS_10: + case AVS2_BITS_12: + vf->bitdepth = BITDEPTH_Y10 | + BITDEPTH_U10 | BITDEPTH_V10; + break; + default: + vf->bitdepth = BITDEPTH_Y10 | + BITDEPTH_U10 | BITDEPTH_V10; + break; + } + if ((vf->type & VIDTYPE_COMPRESS) == 0) + vf->bitdepth = + BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; + if (pic->bit_depth == AVS2_BITS_8) + vf->bitdepth |= BITDEPTH_SAVING_MODE; - } else -#endif - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(pic); - } else { - vf->canvas0Addr = vf->canvas1Addr = 0; - vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; + set_frame_info(dec, vf); + /* if((vf->width!=pic->width)| + (vf->height!=pic->height)) */ + /* pr_info("aaa: %d/%d, %d/%d\n", + vf->width,vf->height, pic->width, + pic->height); */ + vf->width = pic->pic_w / + get_double_write_ratio(dec, + pic->double_write_mode); + vf->height = pic->pic_h / + get_double_write_ratio(dec, + pic->double_write_mode); + if (force_w_h != 0) { + vf->width = (force_w_h >> 16) & 0xffff; + vf->height = force_w_h & 0xffff; + } + vf->compWidth = pic->pic_w; + vf->compHeight = pic->pic_h; + if (force_fps & 0x100) { + u32 rate = force_fps & 0xff; + if (rate) + vf->duration = 96000/rate; + else + vf->duration = 0; + } #ifdef AVS2_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif - } - - switch (pic->bit_depth) { - case AVS2_BITS_8: - vf->bitdepth = BITDEPTH_Y8 | - BITDEPTH_U8 | BITDEPTH_V8; - break; - case AVS2_BITS_10: - case AVS2_BITS_12: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - default: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - } - if ((vf->type & VIDTYPE_COMPRESS) == 0) - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - if (pic->bit_depth == AVS2_BITS_8) - vf->bitdepth |= BITDEPTH_SAVING_MODE; - - set_frame_info(dec, vf); - /* if((vf->width!=pic->width)| - (vf->height!=pic->height)) */ - /* pr_info("aaa: %d/%d, %d/%d\n", - vf->width,vf->height, pic->width, - pic->height); */ - vf->width = pic->pic_w / - get_double_write_ratio(dec, - pic->double_write_mode); - vf->height = pic->pic_h / - get_double_write_ratio(dec, - pic->double_write_mode); - if (force_w_h != 0) { - vf->width = (force_w_h >> 16) & 0xffff; - vf->height = force_w_h & 0xffff; - } - vf->compWidth = pic->pic_w; - vf->compHeight = pic->pic_h; - if (force_fps & 0x100) { - u32 rate = force_fps & 0xff; - if (rate) - vf->duration = 96000/rate; - else - vf->duration = 0; - } -#ifdef AVS2_10B_MMU - if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = decoder_mmu_box_get_mem_handle( - dec->mmu_box, - pic->index); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - } else { + if (vf->type & VIDTYPE_SCATTER) { + vf->mem_handle = decoder_mmu_box_get_mem_handle( + dec->mmu_box, + pic->index); + vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( + dec->bmmu_box, + HEADER_BUFFER_IDX(pic->index)); + } else { + vf->mem_handle = decoder_bmmu_box_get_mem_handle( + dec->bmmu_box, + VF_BUFFER_IDX(pic->index)); + vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( + dec->bmmu_box, + HEADER_BUFFER_IDX(pic->index)); + } +#else vf->mem_handle = decoder_bmmu_box_get_mem_handle( dec->bmmu_box, VF_BUFFER_IDX(pic->index)); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - } -#else - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - VF_BUFFER_IDX(pic->index)); #endif if (!dummy) { @@ -3890,6 +4539,7 @@ static void set_vframe(struct AVS2Decoder_s *dec, dec->vf_pre_count++; } + static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) { #ifndef NO_DISPLAY @@ -3906,6 +4556,24 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) continue; } + if (pic->error_mark) { + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, + "!!!error pic, skip\n", + 0); + continue; + } + + if (dec->start_decoding_flag != 0) { + if (dec->skip_PB_before_I && + pic->slice_type != I_IMG) { + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, + "!!!slice type %d (not I) skip\n", + 0, pic->slice_type); + continue; + } + dec->skip_PB_before_I = 0; + } + if (kfifo_get(&dec->newframe_q, &vf) == 0) { pr_info("fatal error, no available buffer slot."); return -1; @@ -3913,14 +4581,16 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) if (vf) { set_vframe(dec, vf, pic, 0); - + decoder_do_frame_check(hw_to_vdec(dec), vf); kfifo_put(&dec->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC /*count info*/ gvs->frame_dur = dec->frame_dur; vdec_count_info(gvs, 0, stream_offset); #endif + hw_to_vdec(dec)->vdec_fps_detec(hw_to_vdec(dec)->id); vf_notify_receiver(dec->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -3993,13 +4663,15 @@ static void dec_again_process(struct AVS2Decoder_s *dec) amhevc_stop(); dec->dec_result = DEC_RESULT_AGAIN; if (dec->process_state == - PROC_STATE_DECODESLICE) { + PROC_STATE_DECODING) { dec->process_state = - PROC_STATE_SENDAGAIN; -#ifdef AVS2_10B_MMU - avs2_recycle_mmu_buf(dec); -#endif + PROC_STATE_DECODE_AGAIN; + } else if (dec->process_state == + PROC_STATE_HEAD_DONE) { + dec->process_state = + PROC_STATE_HEAD_AGAIN; } + dec->next_again_flag = 1; reset_process_time(dec); vdec_schedule_work(&dec->work); } @@ -4014,6 +4686,517 @@ static uint32_t log2i(uint32_t val) return ret; } +static void check_pic_error(struct AVS2Decoder_s *dec, + struct avs2_frame_s *pic) +{ + if (pic->decoded_lcu == 0) { + pic->decoded_lcu = + (READ_VREG(HEVC_PARSER_LCU_START) + & 0xffffff) + 1; + } + if (pic->decoded_lcu != dec->avs2_dec.lcu_total) { + avs2_print(dec, AVS2_DBG_BUFMGR, + "%s error pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", + __func__, pic->index, pic->imgtr_fwRefDistance, + pic->decoded_lcu, dec->avs2_dec.lcu_total); + pic->error_mark = 1; + } else { + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, + "%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", + __func__, pic->index, pic->imgtr_fwRefDistance, + pic->decoded_lcu, dec->avs2_dec.lcu_total); + + } +} +static void update_decoded_pic(struct AVS2Decoder_s *dec) +{ + struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; + if (pic) { + dec->avs2_dec.hc.cur_pic->decoded_lcu = + (READ_VREG(HEVC_PARSER_LCU_START) + & 0xffffff) + 1; + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, + "%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", + __func__, pic->index, pic->imgtr_fwRefDistance, + pic->decoded_lcu, dec->avs2_dec.lcu_total); + } +} +/* +[SE] [BUG][BUG-171463][chuanqi.wang]: get frame rate by video sequeue*/ +static int get_frame_rate(union param_u *params, struct AVS2Decoder_s *dec) +{ + int tmp = 0; + + switch (params->p.frame_rate_code) { + case 1: + case 2: + tmp = 24; + break; + case 3: + tmp = 25; + break; + case 4: + case 5: + tmp = 30; + break; + case 6: + tmp = 50; + break; + case 7: + case 8: + tmp = 60; + break; + case 9: + tmp = 100; + break; + case 10: + tmp = 120; + break; + default: + tmp = 25; + break; + } + + if (!params->p.progressive_sequence) + tmp = tmp / 2; + dec->frame_dur = div_u64(96000ULL, tmp); + dec->get_frame_dur = true; + /*avs2_print(dec, 0, "avs2 frame_dur:%d,progressive:%d\n", dec->frame_dur, params->p.progressive_sequence);*/ + return 0; +} + + +#define HEVC_MV_INFO 0x310d +#define HEVC_QP_INFO 0x3137 +#define HEVC_SKIP_INFO 0x3136 + +/* only when we decoded one field or one frame, +we can call this function to get qos info*/ +static void get_picture_qos_info(struct AVS2Decoder_s *dec) +{ + struct avs2_frame_s *picture = dec->avs2_dec.hc.cur_pic; + if (!picture) { + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, + "%s decode picture is none exist\n"); + + return; + } + +/* +#define DEBUG_QOS +*/ + + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + unsigned char a[3]; + unsigned char i, j, t; + unsigned long data; + + data = READ_VREG(HEVC_MV_INFO); + if (picture->slice_type == I_IMG) + data = 0; + a[0] = data & 0xff; + a[1] = (data >> 8) & 0xff; + a[2] = (data >> 16) & 0xff; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_mv = a[2]; + picture->avg_mv = a[1]; + picture->min_mv = a[0]; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_QP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_qp = a[2]; + picture->avg_qp = a[1]; + picture->min_qp = a[0]; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_SKIP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_skip = a[2]; + picture->avg_skip = a[1]; + picture->min_skip = a[0]; + +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + } else { + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +#ifdef DEBUG_QOS + int pic_number = 0; +#endif + + picture->max_mv = 0; + picture->avg_mv = 0; + picture->min_mv = 0; + + picture->max_skip = 0; + picture->avg_skip = 0; + picture->min_skip = 0; + + picture->max_qp = 0; + picture->avg_qp = 0; + picture->min_qp = 0; + + + +#ifdef DEBUG_QOS + avs2_print(dec, 0, "slice_type:%d, poc:%d\n", + picture->slice_type, + pic_number); +#endif + /* set rd_idx to 0 */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); + + blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif + picture->avg_qp = rdata32/blk88_y_count; + /* intra_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + picture->avg_skip = rdata32*100/blk88_y_count; + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif + picture->min_qp = (rdata32>>0)&0xff; + +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif + picture->max_qp = (rdata32>>8)&0xff; + +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + avs2_print(dec, 0, "[Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)value, + value, blk22_mv_count); +#endif + picture->avg_mv = value; + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + picture->max_mv = mv_hi; + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + picture->min_mv = mv_lo; + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + } +} + static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data; @@ -4024,46 +5207,64 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) /*if (dec->wait_buf) pr_info("set wait_buf to 0\r\n"); */ + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s %x\n", __func__, dec_status); + "%s decode_status 0x%x process_state %d lcu 0x%x\n", + __func__, dec_status, dec->process_state, + READ_VREG(HEVC_PARSER_LCU_START)); + #ifndef G12A_BRINGUP_DEBUG if (dec->eos) { PRINT_LINE(); - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } #endif dec->wait_buf = 0; - if ((dec_status == HEVC_NAL_DECODE_DONE) || - (dec_status == AVS2_DECODE_TIMEOUT) || - (dec_status == AVS2_DECODE_BUFEMPTY) - ) { + if (dec_status == AVS2_DECODE_BUFEMPTY) { PRINT_LINE(); if (dec->m_ins_flag) { reset_process_time(dec); if (!vdec_frame_based(hw_to_vdec(dec))) dec_again_process(dec); else { - dec->dec_result = DEC_RESULT_GET_DATA; + dec->dec_result = DEC_RESULT_DONE; + reset_process_time(dec); + amhevc_stop(); vdec_schedule_work(&dec->work); } } - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } else if (dec_status == HEVC_DECPIC_DATA_DONE) { PRINT_LINE(); + dec->start_decoding_flag |= 0x3; if (dec->m_ins_flag) { + update_decoded_pic(dec); + get_picture_qos_info(dec); reset_process_time(dec); dec->dec_result = DEC_RESULT_DONE; amhevc_stop(); +#if 0 /*def AVS2_10B_MMU*/ + if (dec->m_ins_flag) { + /*avs2_recycle_mmu_buf_tail(dec);*/ + dec->used_4k_num = + (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + } +#endif + +#if 0 + /*keep hardware state*/ + WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); + WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); + dec->mpred_abv_start_addr = + READ_VREG(HEVC_MPRED_ABV_START_ADDR); + /**/ +#endif vdec_schedule_work(&dec->work); } - - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } PRINT_LINE(); - +#if 0 if (dec_status == AVS2_EOS) { if (dec->m_ins_flag) reset_process_time(dec); @@ -4077,14 +5278,16 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) avs2_print(dec, AVS2_DBG_BUFMGR, "send AVS2_10B_DISCARD_NAL\r\n"); WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL); - dec->process_busy = 0; if (dec->m_ins_flag) { + update_decoded_pic(dec); dec->dec_result = DEC_RESULT_DONE; amhevc_stop(); vdec_schedule_work(&dec->work); } - return IRQ_HANDLED; - } else if (dec_status == AVS2_DECODE_OVER_SIZE) { + goto irq_handled_exit; + } else +#endif + if (dec_status == AVS2_DECODE_OVER_SIZE) { avs2_print(dec, 0, "avs2 decode oversize !!\n"); debug |= (AVS2_DBG_DIS_LOC_ERROR_PROC | @@ -4092,33 +5295,79 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) dec->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; if (dec->m_ins_flag) reset_process_time(dec); - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } PRINT_LINE(); if (dec->m_ins_flag) reset_process_time(dec); - if ((dec_status == AVS2_HEAD_PIC_I_READY) - || (dec_status == AVS2_HEAD_PIC_PB_READY)) { + if (dec_status == AVS2_HEAD_SEQ_READY) + start_code = SEQUENCE_HEADER_CODE; + else if (dec_status == AVS2_HEAD_PIC_I_READY) + start_code = I_PICTURE_START_CODE; + else if (dec_status == AVS2_HEAD_PIC_PB_READY) + start_code = PB_PICTURE_START_CODE; + else if (dec_status == AVS2_STARTCODE_SEARCH_DONE) + /*SEQUENCE_END_CODE, VIDEO_EDIT_CODE*/ + start_code = READ_VREG(CUR_NAL_UNIT_TYPE); + + if (dec->process_state == + PROC_STATE_HEAD_AGAIN + ) { + if ((start_code == I_PICTURE_START_CODE) + || (start_code == PB_PICTURE_START_CODE)) { + avs2_print(dec, 0, + "PROC_STATE_HEAD_AGAIN error, start_code 0x%x!!!\r\n", + start_code); + goto irq_handled_exit; + } else { + avs2_print(dec, AVS2_DBG_BUFMGR, + "PROC_STATE_HEAD_AGAIN, start_code 0x%x\r\n", + start_code); + dec->process_state = PROC_STATE_HEAD_DONE; + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); + goto irq_handled_exit; + } + } else if (dec->process_state == + PROC_STATE_DECODE_AGAIN) { + if ((start_code == I_PICTURE_START_CODE) + || (start_code == PB_PICTURE_START_CODE)) { + avs2_print(dec, AVS2_DBG_BUFMGR, + "PROC_STATE_DECODE_AGAIN=> decode_slice, start_code 0x%x\r\n", + start_code); + goto decode_slice; + } else { + avs2_print(dec, 0, + "PROC_STATE_DECODE_AGAIN, start_code 0x%x!!!\r\n", + start_code); + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); + goto irq_handled_exit; + } + } + + if ((start_code == I_PICTURE_START_CODE) + || (start_code == PB_PICTURE_START_CODE) + || (start_code == SEQUENCE_END_CODE) + || (start_code == VIDEO_EDIT_CODE)) { PRINT_LINE(); - if (dec->avs2_dec.hc.cur_pic != NULL && - dec->process_state != PROC_STATE_SENDAGAIN) { + if (dec->avs2_dec.hc.cur_pic != NULL) { int32_t ii; #ifdef AVS2_10B_MMU avs2_recycle_mmu_buf_tail(dec); #endif + check_pic_error(dec, dec->avs2_dec.hc.cur_pic); avs2_post_process(&dec->avs2_dec); + + if (debug & AVS2_DBG_PRINT_PIC_LIST) + dump_pic_list(dec); + avs2_prepare_display_buf(dec); dec->avs2_dec.hc.cur_pic = NULL; -#ifdef AVS2_10B_MMU for (ii = 0; ii < dec->avs2_dec.ref_maxbuffer; ii++) { if (dec->avs2_dec.fref[ii]-> - refered_by_others == 0 && - dec->avs2_dec.fref[ii]-> bg_flag == 0 && dec->avs2_dec.fref[ii]-> is_output == -1 && @@ -4126,16 +5375,43 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) mmu_alloc_flag && dec->avs2_dec.fref[ii]-> vf_ref == 0) { - dec->avs2_dec.fref[ii]-> - mmu_alloc_flag = 0; - /*release_buffer_4k( - dec->avs2_dec.fref[ii]->index);*/ - decoder_mmu_box_free_idx(dec->mmu_box, - dec->avs2_dec.fref[ii]->index); + struct avs2_frame_s *pic = + dec->avs2_dec.fref[ii]; + if (dec->avs2_dec.fref[ii]-> + refered_by_others == 0) { +#ifdef AVS2_10B_MMU + dec->avs2_dec.fref[ii]-> + mmu_alloc_flag = 0; + /*release_buffer_4k( + dec->avs2_dec.fref[ii]->index);*/ + decoder_mmu_box_free_idx(dec->mmu_box, + dec->avs2_dec.fref[ii]->index); +#ifdef DYNAMIC_ALLOC_HEAD + decoder_bmmu_box_free_idx( + dec->bmmu_box, + HEADER_BUFFER_IDX(pic->index)); + pic->header_adr = 0; +#endif +#endif +#ifndef MV_USE_FIXED_BUF + decoder_bmmu_box_free_idx( + dec->bmmu_box, + MV_BUFFER_IDX(pic->index)); + pic->mpred_mv_wr_start_addr = 0; +#endif + } + decoder_bmmu_box_free_idx( + dec->bmmu_box, + VF_BUFFER_IDX(pic->index)); + dec->cma_alloc_addr = 0; } } -#endif } + } + + if ((dec_status == AVS2_HEAD_PIC_I_READY) + || (dec_status == AVS2_HEAD_PIC_PB_READY)) { + PRINT_LINE(); if (debug & AVS2_DBG_SEND_PARAM_WITH_REG) { get_rpm_param( @@ -4155,48 +5431,215 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) dec->rpm_ptr[i + 3 - ii]; } } +#ifdef SANITY_CHECK + if (dec->avs2_dec.param.p.num_of_ref_cur > + dec->avs2_dec.ref_maxbuffer) { + pr_info("Warning: Wrong num_of_ref_cur %d, force to %d\n", + dec->avs2_dec.param.p.num_of_ref_cur, + dec->avs2_dec.ref_maxbuffer); + dec->avs2_dec.param.p.num_of_ref_cur = + dec->avs2_dec.ref_maxbuffer; + } +#endif PRINT_LINE(); debug_buffer_mgr_more(dec); + get_frame_rate(&dec->avs2_dec.param, dec); + if (dec->avs2_dec.param.p.video_signal_type + & (1<<30)) { + union param_u *pPara; + + avs2_print(dec, 0, + "avs2 HDR meta data present\n"); + pPara = &dec->avs2_dec.param; + + /*clean this flag*/ + pPara->p.video_signal_type + &= ~(1<<30); + + dec->vf_dp.present_flag = 1; + + dec->vf_dp.white_point[0] + = pPara->p.white_point_x; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "white_point[0]:0x%x\n", + dec->vf_dp.white_point[0]); + + dec->vf_dp.white_point[1] + = pPara->p.white_point_y; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "white_point[1]:0x%x\n", + dec->vf_dp.white_point[1]); + + for (i = 0; i < 3; i++) { + dec->vf_dp.primaries[i][0] + = pPara->p.display_primaries_x[i]; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "primaries[%d][0]:0x%x\n", + i, + dec->vf_dp.primaries[i][0]); + } + + for (i = 0; i < 3; i++) { + dec->vf_dp.primaries[i][1] + = pPara->p.display_primaries_y[i]; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "primaries[%d][1]:0x%x\n", + i, + dec->vf_dp.primaries[i][1]); + } + + dec->vf_dp.luminance[0] + = pPara->p.max_display_mastering_luminance; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "luminance[0]:0x%x\n", + dec->vf_dp.luminance[0]); + + dec->vf_dp.luminance[1] + = pPara->p.min_display_mastering_luminance; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "luminance[1]:0x%x\n", + dec->vf_dp.luminance[1]); + + + dec->vf_dp.content_light_level.present_flag + = 1; + dec->vf_dp.content_light_level.max_content + = pPara->p.max_content_light_level; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "max_content:0x%x\n", + dec->vf_dp.content_light_level.max_content); + + dec->vf_dp.content_light_level.max_pic_average + = pPara->p.max_picture_average_light_level; + + avs2_print(dec, AVS2_DBG_HDR_INFO, + "max_pic_average:0x%x\n", + dec->vf_dp.content_light_level.max_pic_average); + } + + + if (dec->video_ori_signal_type != + ((dec->avs2_dec.param.p.video_signal_type << 16) + | dec->avs2_dec.param.p.color_description)) { + u32 v = dec->avs2_dec.param.p.video_signal_type; + u32 c = dec->avs2_dec.param.p.color_description; + u32 convert_c = c; + + if (v & 0x2000) { + avs2_print(dec, 0, + "video_signal_type present:\n"); + avs2_print(dec, 0, + " %s %s\n", + video_format_names[(v >> 10) & 7], + ((v >> 9) & 1) ? + "full_range" : "limited"); + if (v & 0x100) { + u32 transfer; + u32 maxtrix; + + avs2_print(dec, 0, + "color_description present:\n"); + avs2_print(dec, 0, + "color_primarie = %d\n", + v & 0xff); + avs2_print(dec, 0, + "transfer_characteristic = %d\n", + (c >> 8) & 0xff); + avs2_print(dec, 0, + " matrix_coefficient = %d\n", + c & 0xff); + + transfer = (c >> 8) & 0xFF; + if (transfer >= 15) + avs2_print(dec, 0, + "unsupport transfer_characteristic\n"); + else if (transfer == 14) + transfer = 18; /* HLG */ + else if (transfer == 13) + transfer = 32; + else if (transfer == 12) + transfer = 16; + else if (transfer == 11) + transfer = 15; + + maxtrix = c & 0xFF; + if (maxtrix >= 10) + avs2_print(dec, 0, + "unsupport matrix_coefficient\n"); + else if (maxtrix == 9) + maxtrix = 10; + else if (maxtrix == 8) + maxtrix = 9; + + convert_c = (transfer << 8) | (maxtrix); + + avs2_print(dec, 0, + " convered c:0x%x\n", + convert_c); + } + } + + if (enable_force_video_signal_type) + dec->video_signal_type + = force_video_signal_type; + else { + dec->video_signal_type + = (v << 16) | convert_c; + + dec->video_ori_signal_type + = (v << 16) | c; + } + + video_signal_type = dec->video_signal_type; + } } - - if (dec_status == AVS2_HEAD_SEQ_READY) - start_code = SEQUENCE_HEADER_CODE; - else if (dec_status == AVS2_HEAD_PIC_I_READY) - start_code = I_PICTURE_START_CODE; - else if (dec_status == AVS2_HEAD_PIC_PB_READY) - start_code = PB_PICTURE_START_CODE; - else if (dec_status == AVS2_HEAD_SEQ_END_READY) - start_code = SEQUENCE_END_CODE; - else if (dec_status == AVS2_STARTCODE_SEARCH_DONE) - start_code = READ_VREG(CUR_NAL_UNIT_TYPE); - +#if 0 + if ((debug_again & 0x4) && + dec->process_state == + PROC_STATE_INIT) { + if (start_code == PB_PICTURE_START_CODE) { + dec->process_state = PROC_STATE_TEST1; + dec_again_process(dec); + goto irq_handled_exit; + } + } +#endif PRINT_LINE(); avs2_prepare_header(&dec->avs2_dec, start_code); if (start_code == SEQUENCE_HEADER_CODE || - start_code == VIDEO_EDIT_CODE) + start_code == VIDEO_EDIT_CODE || + start_code == SEQUENCE_END_CODE) { + if (dec->m_ins_flag && + vdec_frame_based(hw_to_vdec(dec))) + dec->start_decoding_flag |= 0x1; + dec->process_state = PROC_STATE_HEAD_DONE; WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - else if (start_code == I_PICTURE_START_CODE || + } else if (start_code == I_PICTURE_START_CODE || start_code == PB_PICTURE_START_CODE) { ret = 0; - if (dec->process_state != PROC_STATE_SENDAGAIN) { - if (dec->pic_list_init_flag == 0) { - int32_t lcu_size_log2 = - log2i(dec->avs2_dec.param.p.lcu_size); + if (dec->pic_list_init_flag == 0) { + int32_t lcu_size_log2 = + log2i(dec->avs2_dec.param.p.lcu_size); - avs2_init_global_buffers(&dec->avs2_dec); - /*avs2_dec->m_bg->index is - set to dec->used_buf_num - 1*/ - init_pic_list(dec, lcu_size_log2); - init_pic_list_hw(dec); - } - ret = avs2_process_header(&dec->avs2_dec); - if (!dec->m_ins_flag) - dec->slice_idx++; + avs2_init_global_buffers(&dec->avs2_dec); + /*avs2_dec->m_bg->index is + set to dec->used_buf_num - 1*/ + init_pic_list(dec, lcu_size_log2); + init_pic_list_hw(dec); } + ret = avs2_process_header(&dec->avs2_dec); + if (!dec->m_ins_flag) + dec->slice_idx++; + PRINT_LINE(); +#ifdef I_ONLY_SUPPORT + if ((start_code == PB_PICTURE_START_CODE) && + (dec->i_only & 0x2)) + ret = -2; +#endif #ifdef AVS2_10B_MMU if (ret >= 0) { ret = avs2_alloc_mmu(dec, @@ -4215,12 +5658,34 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) ret); } #endif + +#ifndef MV_USE_FIXED_BUF + if (ret >= 0 && + dec->avs2_dec.hc.cur_pic-> + mpred_mv_wr_start_addr == 0) { + unsigned long buf_addr; + unsigned mv_buf_size = 0x120000; + int i = dec->avs2_dec.hc.cur_pic->index; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + mv_buf_size = 0x120000 * 4; + if (decoder_bmmu_box_alloc_buf_phy + (dec->bmmu_box, + MV_BUFFER_IDX(i), + mv_buf_size, + DRIVER_NAME, + &buf_addr) < 0) + ret = -1; + else + dec->avs2_dec.hc.cur_pic-> + mpred_mv_wr_start_addr + = buf_addr; + } +#endif if (ret < 0) { avs2_print(dec, AVS2_DBG_BUFMGR, "avs2_bufmgr_process=> %d, AVS2_10B_DISCARD_NAL\r\n", ret); WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL); - dec->process_busy = 0; #ifdef AVS2_10B_MMU avs2_recycle_mmu_buf(dec); #endif @@ -4230,35 +5695,36 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) vdec_schedule_work(&dec->work); } - return IRQ_HANDLED; + goto irq_handled_exit; } else { PRINT_LINE(); + dec->avs2_dec.hc.cur_pic->stream_offset = + READ_VREG(HEVC_SHIFT_BYTE_COUNT); /* struct PIC_BUFFER_CONFIG_s *cur_pic = &cm->cur_frame->buf; cur_pic->decode_idx = dec->frame_count; */ - if (dec->process_state != PROC_STATE_SENDAGAIN) { - if (!dec->m_ins_flag) { - dec->frame_count++; - decode_frame_count[dec->index] - = dec->frame_count; - } - /*MULTI_INSTANCE_SUPPORT*/ - if (dec->chunk) { - dec->avs2_dec.hc.cur_pic->pts = - dec->chunk->pts; - dec->avs2_dec.hc.cur_pic->pts64 = - dec->chunk->pts64; - } - /**/ + if (!dec->m_ins_flag) { + dec->frame_count++; + decode_frame_count[dec->index] + = dec->frame_count; } + /*MULTI_INSTANCE_SUPPORT*/ + if (dec->chunk) { + dec->avs2_dec.hc.cur_pic->pts = + dec->chunk->pts; + dec->avs2_dec.hc.cur_pic->pts64 = + dec->chunk->pts64; + } + /**/ dec->avs2_dec.hc.cur_pic->bit_depth = dec->avs2_dec.input.sample_bit_depth; dec->avs2_dec.hc.cur_pic->double_write_mode = get_double_write_mode(dec); - +decode_slice: PRINT_LINE(); + config_mc_buffer(dec); config_mcrcc_axi_hw(dec); config_mpred_hw(dec); @@ -4276,17 +5742,26 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) dec->avs2_dec.fref[4]->imgtr_fwRefDistance, dec->avs2_dec.img.tr); + if ((debug_again & 0x2) && + dec->process_state == + PROC_STATE_INIT) { + dec->process_state = PROC_STATE_DECODING; + dec_again_process(dec); + goto irq_handled_exit; + } + + dec->process_state = PROC_STATE_DECODING; + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); } - dec->process_busy = 0; - dec->process_state = PROC_STATE_DECODESLICE; if (dec->m_ins_flag) start_process_time(dec); } - dec->process_busy = 0; +irq_handled_exit: PRINT_LINE(); + dec->process_busy = 0; return IRQ_HANDLED; } @@ -4296,6 +5771,7 @@ static irqreturn_t vavs2_isr(int irq, void *data) unsigned int dec_status; struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data; uint debug_tag; + WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); dec_status = READ_VREG(HEVC_DEC_STATUS_REG); @@ -4506,25 +5982,6 @@ static void vavs2_put_timer_func(unsigned long arg) dec->ucode_pause_pos = 0; WRITE_HREG(DEBUG_REG1, 0); } - if (debug & AVS2_DBG_FORCE_SEND_AGAIN) { - pr_info( - "Force Send Again\r\n"); - debug &= ~AVS2_DBG_FORCE_SEND_AGAIN; - reset_process_time(dec); - dec->dec_result = DEC_RESULT_AGAIN; - if (dec->process_state == - PROC_STATE_DECODESLICE) { -#ifdef AVS2_10B_MMU - avs2_recycle_mmu_buf(dec); -#endif - dec->process_state = - PROC_STATE_SENDAGAIN; - } - amhevc_stop(); - - vdec_schedule_work(&dec->work); - } - if (debug & AVS2_DBG_DUMP_DATA) { debug &= ~AVS2_DBG_DUMP_DATA; avs2_print(dec, 0, @@ -4544,6 +6001,50 @@ static void vavs2_put_timer_func(unsigned long arg) WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); debug &= ~AVS2_DBG_TRIG_SLICE_SEGMENT_PROC; } + if (debug & AVS2_DBG_DUMP_RPM_BUF) { + int i; + dma_sync_single_for_cpu( + amports_get_dma_device(), + dec->rpm_phy_addr, + RPM_BUF_SIZE, + DMA_FROM_DEVICE); + + pr_info("RPM:\n"); + for (i = 0; i < RPM_BUF_SIZE; i += 4) { + int ii; + if ((i & 0xf) == 0) + pr_info("%03x: ", i); + for (ii = 0; ii < 4; ii++) { + pr_info("%04x ", + dec->lmem_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + pr_info("\n"); + } + debug &= ~AVS2_DBG_DUMP_RPM_BUF; + } + if (debug & AVS2_DBG_DUMP_LMEM_BUF) { + int i; + dma_sync_single_for_cpu( + amports_get_dma_device(), + dec->lmem_phy_addr, + LMEM_BUF_SIZE, + DMA_FROM_DEVICE); + + pr_info("LMEM:\n"); + for (i = 0; i < LMEM_BUF_SIZE; i += 4) { + int ii; + if ((i & 0xf) == 0) + pr_info("%03x: ", i); + for (ii = 0; ii < 4; ii++) { + pr_info("%04x ", + dec->lmem_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + pr_info("\n"); + } + debug &= ~AVS2_DBG_DUMP_LMEM_BUF; + } /*if (debug & AVS2_DBG_HW_RESET) { }*/ @@ -4578,7 +6079,7 @@ static void vavs2_put_timer_func(unsigned long arg) if (dbg_cmd != 0) { if (dbg_cmd == 1) { u32 disp_laddr; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && get_double_write_mode(dec) == 0) { disp_laddr = READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; @@ -4614,8 +6115,13 @@ int vavs2_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; + + if (!dec) + return -1; + + vstatus->frame_width = dec->frame_width; + vstatus->frame_height = dec->frame_height; + if (dec->frame_dur != 0) vstatus->frame_rate = 96000 / dec->frame_dur; else @@ -4714,6 +6220,21 @@ static void vavs2_prot_init(struct AVS2Decoder_s *dec) } +#ifdef I_ONLY_SUPPORT +static int vavs2_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) +{ + struct AVS2Decoder_s *dec = + (struct AVS2Decoder_s *)vdec->private; + if (i_only_flag & 0x100) + return 0; + if (trickmode == TRICKMODE_I) + dec->i_only = 0x3; + else if (trickmode == TRICKMODE_NONE) + dec->i_only = 0x0; + return 0; +} +#endif + static int vavs2_local_init(struct AVS2Decoder_s *dec) { int i; @@ -4751,7 +6272,15 @@ TODO:FOR VERSION if (dec->frame_dur == 0) dec->frame_dur = 96000 / 24; - +#ifdef I_ONLY_SUPPORT + if (i_only_flag & 0x100) + dec->i_only = i_only_flag & 0xff; + else if ((unsigned long) dec->vavs2_amstream_dec_info.param + & 0x08) + dec->i_only = 0x7; + else + dec->i_only = 0x0; +#endif INIT_KFIFO(dec->display_q); INIT_KFIFO(dec->newframe_q); @@ -4771,7 +6300,7 @@ TODO:FOR VERSION static s32 vavs2_init(struct vdec_s *vdec) { - int size = -1; + int ret = -1, size = -1; int fw_size = 0x1000 * 16; struct firmware_s *fw = NULL; struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; @@ -4784,20 +6313,14 @@ static s32 vavs2_init(struct vdec_s *vdec) fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; -#ifdef MULTI_INSTANCE_SUPPORT - if (tee_enabled()) { - size = 1; - pr_debug ("laod\n"); - } else -#endif + size = get_firmware_data(VIDEO_DEC_AVS2_MMU, fw->data); if (size < 0) { pr_err("get firmware fail.\n"); vfree(fw); return -1; } - avs2_print(dec, AVS2_DBG_BUFMGR, - "firmware size %d\n", size); + fw->len = fw_size; if (dec->m_ins_flag) { @@ -4815,20 +6338,20 @@ static s32 vavs2_init(struct vdec_s *vdec) return 0; } - + hevc_enable_DMC(hw_to_vdec(dec)); amhevc_enable(); - if (size == 1) - pr_info ("tee load ok\n"); - if (amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data) < 0) { + ret = amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data); + if (ret < 0) { amhevc_disable(); vfree(fw); + pr_err("AVS2: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } - avs2_print(dec, AVS2_DBG_BUFMGR, - "firmware size %d\n", size); vfree(fw); + dec->stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ @@ -4870,12 +6393,6 @@ static s32 vavs2_init(struct vdec_s *vdec) dec->stat |= STAT_TIMER_ARM; /* dec->stat |= STAT_KTHREAD; */ - - amhevc_start(); - - dec->stat |= STAT_VDEC_RUN; - - dec->init_flag = 1; dec->process_busy = 0; avs2_print(dec, AVS2_DBG_BUFMGR_MORE, "%d, vavs2_init, RP=0x%x\n", @@ -4886,7 +6403,7 @@ static s32 vavs2_init(struct vdec_s *vdec) static int vmavs2_stop(struct AVS2Decoder_s *dec) { dec->init_flag = 0; - + dec->first_sc_checked = 0; if (dec->stat & STAT_TIMER_ARM) { del_timer_sync(&dec->timer); dec->stat &= ~STAT_TIMER_ARM; @@ -4905,6 +6422,10 @@ static int vmavs2_stop(struct AVS2Decoder_s *dec) reset_process_time(dec); cancel_work_sync(&dec->work); uninit_mmu_buffers(dec); + if (dec->fw) { + vfree(dec->fw); + dec->fw = NULL; + } return 0; } @@ -4914,7 +6435,7 @@ static int vavs2_stop(struct AVS2Decoder_s *dec) { dec->init_flag = 0; - + dec->first_sc_checked = 0; if (dec->stat & STAT_VDEC_RUN) { amhevc_stop(); dec->stat &= ~STAT_VDEC_RUN; @@ -4948,8 +6469,6 @@ static int vavs2_stop(struct AVS2Decoder_s *dec) else amhevc_disable(); uninit_mmu_buffers(dec); - vfree(dec->fw); - dec->fw = NULL; return 0; } @@ -4958,11 +6477,14 @@ static int amvdec_avs2_mmu_init(struct AVS2Decoder_s *dec) { int tvp_flag = vdec_secure(hw_to_vdec(dec)) ? CODEC_MM_FLAGS_TVP : 0; + int buf_size = 48; #ifdef AVS2_10B_MMU + dec->need_cache_size = buf_size * SZ_1M; + dec->sc_start_time = get_jiffies_64(); dec->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, dec->index, FRAME_BUFFERS, - 48 * SZ_1M, + dec->need_cache_size, tvp_flag ); if (!dec->mmu_box) { @@ -4989,23 +6511,17 @@ static int amvdec_avs2_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct BUF_s BUF[MAX_BUF_NUM]; - struct AVS2Decoder_s *dec; + struct AVS2Decoder_s *dec = &gAVS2Decoder; int ret; pr_info("%s\n", __func__); mutex_lock(&vavs2_mutex); - dec = vmalloc(sizeof(struct AVS2Decoder_s)); - if (dec == NULL) { - pr_info("failed to vamlloc amvdec_avs2 dec struct\n"); - return -ENOMEM; - } - gHevc = dec; memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); memset(dec, 0, sizeof(struct AVS2Decoder_s)); memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); dec->init_flag = 0; - + dec->first_sc_checked = 0; dec->eos = 0; dec->start_process_time = 0; dec->timeout_num = 0; @@ -5014,7 +6530,6 @@ static int amvdec_avs2_probe(struct platform_device *pdev) if (pdata == NULL) { avs2_print(dec, 0, "\namvdec_avs2 memory resource undefined.\n"); - vfree(dec); mutex_unlock(&vavs2_mutex); return -EFAULT; } @@ -5023,7 +6538,6 @@ static int amvdec_avs2_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pdata); if (amvdec_avs2_mmu_init(dec) < 0) { - vfree(dec); mutex_unlock(&vavs2_mutex); pr_err("avs2 alloc bmmu box failed!!\n"); return -1; @@ -5033,7 +6547,6 @@ static int amvdec_avs2_probe(struct platform_device *pdev) work_buf_size, DRIVER_NAME, &pdata->mem_start); if (ret < 0) { uninit_mmu_buffers(dec); - vfree(dec); mutex_unlock(&vavs2_mutex); return ret; } @@ -5048,9 +6561,11 @@ static int amvdec_avs2_probe(struct platform_device *pdev) pdata->mem_start, dec->buf_size); } - if (pdata->sys_info) + if (pdata->sys_info) { dec->vavs2_amstream_dec_info = *pdata->sys_info; - else { + dec->frame_width = dec->vavs2_amstream_dec_info.width; + dec->frame_height = dec->vavs2_amstream_dec_info.height; + } else { dec->vavs2_amstream_dec_info.width = 0; dec->vavs2_amstream_dec_info.height = 0; dec->vavs2_amstream_dec_info.rate = 30; @@ -5059,13 +6574,13 @@ static int amvdec_avs2_probe(struct platform_device *pdev) pdata->private = dec; pdata->dec_status = vavs2_dec_status; - pdata->set_isreset = vavs2_set_isreset; + /*pdata->set_isreset = vavs2_set_isreset;*/ is_reset = 0; if (vavs2_init(pdata) < 0) { pr_info("\namvdec_avs2 init failed.\n"); avs2_local_uninit(dec); uninit_mmu_buffers(dec); - vfree(dec); + pdata->dec_status = NULL; mutex_unlock(&vavs2_mutex); return -ENODEV; } @@ -5079,7 +6594,7 @@ static int amvdec_avs2_probe(struct platform_device *pdev) static int amvdec_avs2_remove(struct platform_device *pdev) { - struct AVS2Decoder_s *dec = gHevc; + struct AVS2Decoder_s *dec = &gAVS2Decoder; if (debug) pr_info("amvdec_avs2_remove\n"); @@ -5096,8 +6611,6 @@ static int amvdec_avs2_remove(struct platform_device *pdev) dec->pts_missed, dec->pts_hit, dec->frame_dur); #endif - vfree(dec); - mutex_unlock(&vavs2_mutex); return 0; @@ -5127,20 +6640,37 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + u8 *data = NULL; + + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, size); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } static void dump_data(struct AVS2Decoder_s *dec, int size) { int jj; - u8 *data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + u8 *data = NULL; int padding_size = dec->chunk->offset & (VDEC_FIFO_ALIGN - 1); + + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, size); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; + avs2_print(dec, 0, "padding: "); for (jj = padding_size; jj > 0; jj--) avs2_print_cont(dec, @@ -5165,6 +6695,9 @@ static void dump_data(struct AVS2Decoder_s *dec, int size) avs2_print(dec, 0, "\n"); + + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } static void avs2_work(struct work_struct *work) @@ -5290,6 +6823,7 @@ static void avs2_work(struct work_struct *work) "%s: end of stream\n", __func__); dec->eos = 1; + check_pic_error(dec, dec->avs2_dec.hc.cur_pic); avs2_post_process(&dec->avs2_dec); avs2_prepare_display_buf(dec); vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk); @@ -5315,7 +6849,10 @@ static void avs2_work(struct work_struct *work) dec->stat &= ~STAT_TIMER_ARM; } /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec ==1) + vdec_core_finish_run(vdec, CORE_MASK_HEVC); + else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); if (dec->vdec_cb) dec->vdec_cb(hw_to_vdec(dec), dec->vdec_cb_arg); @@ -5332,21 +6869,89 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; - bool ret = 0; + int tvp = vdec_secure(hw_to_vdec(dec)) ? + CODEC_MM_FLAGS_TVP : 0; + unsigned long ret = 0; avs2_print(dec, PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + if (debug & AVS2_DBG_PIC_LEAK_WAIT) + return ret; + if (dec->eos) return ret; + if (!dec->first_sc_checked) { + int size = decoder_mmu_box_sc_check(dec->mmu_box, tvp); + dec->first_sc_checked = 1; + avs2_print(dec, 0, "vavs2 cached=%d need_size=%d speed= %d ms\n", + size, (dec->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - dec->sc_start_time) * 1000/HZ); + } + + if (dec->next_again_flag && + (!vdec_frame_based(vdec))) { + u32 parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + if (parser_wr_ptr >= dec->pre_parser_wr_ptr && + (parser_wr_ptr - dec->pre_parser_wr_ptr) < + again_threshold) { + int r = vdec_sync_input(vdec); + avs2_print(dec, + PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); + return 0; + } + } +/* + if (vdec_stream_based(vdec) && (dec->pic_list_init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < pre_decode_buf_level) + return 0; + } +*/ if ((dec->pic_list_init_flag == 0) || get_free_buf_count(dec) >= run_ready_min_buf_num) ret = 1; +#ifdef CONSTRAIN_MAX_BUF_NUM + if (dec->pic_list_init_flag) { + if (run_ready_max_vf_only_num > 0 && + get_vf_ref_only_buf_count(dec) >= + run_ready_max_vf_only_num + ) + ret = 0; + if (run_ready_display_q_num > 0 && + kfifo_len(&dec->display_q) >= + run_ready_display_q_num) + ret = 0; + + if (run_ready_max_buf_num == 0xff && + get_used_buf_count(dec) >= + dec->avs2_dec.ref_maxbuffer) + ret = 0; + else if (run_ready_max_buf_num && + get_used_buf_count(dec) >= + run_ready_max_buf_num) + ret = 0; + } +#endif if (ret) not_run_ready[dec->index] = 0; else not_run_ready[dec->index]++; - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + + if (vdec->parallel_dec == 1) + return ret ? CORE_MASK_HEVC : 0; + else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -5361,6 +6966,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, dec->vdec_cb = callback; /* dec->chunk = vdec_prepare_input(vdec); */ hevc_reset_core(vdec); + dec->pre_parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + dec->next_again_flag = 0; r = vdec_prepare_input(vdec, &dec->chunk); if (r < 0) { @@ -5386,23 +6994,31 @@ static void run(struct vdec_s *vdec, unsigned long mask, dec->frame_count, r, dec->chunk ? dec->chunk->size : 0, dec->chunk ? dec->chunk->offset : 0, - (vdec_frame_based(vdec) && + dec->chunk ? ((vdec_frame_based(vdec) && (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(dec, r) : 0, + get_data_check_sum(dec, r) : 0) : 0, READ_VREG(HEVC_STREAM_START_ADDR), READ_VREG(HEVC_STREAM_END_ADDR), READ_VREG(HEVC_STREAM_LEVEL), READ_VREG(HEVC_STREAM_WR_PTR), READ_VREG(HEVC_STREAM_RD_PTR), dec->start_shift_bytes); - if (vdec_frame_based(vdec)) { - u8 *data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + if (vdec_frame_based(vdec) && dec->chunk) { + u8 *data = NULL; + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, 8); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; + avs2_print_cont(dec, 0, "data adr %p:", data); for (ii = 0; ii < 8; ii++) avs2_print_cont(dec, 0, "%02x ", data[ii]); + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } avs2_print_cont(dec, 0, "\r\n"); } @@ -5416,9 +7032,13 @@ static void run(struct vdec_s *vdec, unsigned long mask, amhevc_disable(); avs2_print(dec, 0, "%s: Error amvdec_loadmc fail\n", __func__); + dec->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&dec->work); return; - } else + } else { vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_AVS2; + } if (avs2_hw_ctx_restore(dec) < 0) { @@ -5428,9 +7048,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, vdec_enable_input(vdec); - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_SEARCH_NEW_PIC); - if (vdec_frame_based(vdec)) { + if (vdec_frame_based(vdec) && dec->chunk) { if (debug & PRINT_FLAG_VDEC_DATA) dump_data(dec, dec->chunk->size); @@ -5594,9 +7214,13 @@ static void avs2_dump_state(struct vdec_s *vdec) int jj; if (dec->chunk && dec->chunk->block && dec->chunk->size > 0) { - u8 *data = - ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + u8 *data = NULL; + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, dec->chunk->size); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; avs2_print(dec, 0, "frame data size 0x%x\n", dec->chunk->size); @@ -5610,6 +7234,9 @@ static void avs2_dump_state(struct vdec_s *vdec) avs2_print_cont(dec, 0, "\n"); } + + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } @@ -5639,9 +7266,18 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) pr_info("\nammvdec_avs2 device data allocation failed\n"); return -ENOMEM; } + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) { + dec->avs2_dec.frm_pool[i].y_canvas_index = -1; + dec->avs2_dec.frm_pool[i].uv_canvas_index = -1; + } + } pdata->private = dec; pdata->dec_status = vavs2_dec_status; - /* pdata->set_trickmode = set_trickmode; */ +#ifdef I_ONLY_SUPPORT + pdata->set_trickmode = vavs2_set_trickmode; +#endif pdata->run_ready = run_ready; pdata->run = run; pdata->reset = reset; @@ -5649,18 +7285,18 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) pdata->threaded_irq_handler = avs2_threaded_irq_cb; pdata->dump_state = avs2_dump_state; - - memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); memset(dec, 0, sizeof(struct AVS2Decoder_s)); memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); dec->index = pdev->id; + dec->m_ins_flag = 1; - if (pdata->use_vfm_path) + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); - else + dec->frameinfo_enable = 1; + } else snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); @@ -5672,7 +7308,8 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->platform_dev = pdev; dec->video_signal_type = 0; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_TXLX) + dec->video_ori_signal_type = 0; + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) dec->stat |= VP9_TRIGGER_FRAME_ENABLE; #if 1 if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && @@ -5755,9 +7392,8 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->buf_start = dec->cma_alloc_addr; dec->buf_size = work_buf_size; #endif - dec->m_ins_flag = 1; - dec->init_flag = 0; + dec->first_sc_checked = 0; dec->fatal_error = 0; dec->show_frame_num = 0; if (pdata == NULL) { @@ -5774,9 +7410,11 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->buf_size); } - if (pdata->sys_info) + if (pdata->sys_info) { dec->vavs2_amstream_dec_info = *pdata->sys_info; - else { + dec->frame_width = dec->vavs2_amstream_dec_info.width; + dec->frame_height = dec->vavs2_amstream_dec_info.height; + } else { dec->vavs2_amstream_dec_info.width = 0; dec->vavs2_amstream_dec_info.height = 0; dec->vavs2_amstream_dec_info.rate = 30; @@ -5789,14 +7427,18 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) uninit_mmu_buffers(dec); /* devm_kfree(&pdev->dev, (void *)dec); */ vfree((void *)dec); + pdata->dec_status = NULL; return -ENODEV; } vdec_set_prepare_level(pdata, start_decode_buf_level); hevc_source_changed(VFORMAT_AVS2, 4096, 2048, 60); - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_HEVC); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); + } return 0; } @@ -5805,14 +7447,26 @@ static int ammvdec_avs2_remove(struct platform_device *pdev) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + int i; + if (debug) pr_info("amvdec_avs2_remove\n"); vmavs2_stop(dec); - vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); + if (pdata->parallel_dec == 1) + vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); + else + vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(dec), VDEC_STATUS_DISCONNECTED); + if (pdata->parallel_dec == 1) { + for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) { + pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].y_canvas_index, pdata->id); + pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].uv_canvas_index, pdata->id); + } + } #ifdef DEBUG_PTS @@ -5880,14 +7534,15 @@ static int __init amvdec_avs2_driver_init_module(void) #ifdef AVS2_10B_MMU struct BuffInfo_s *p_buf_info; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - p_buf_info = &amvavs2_workbuff_spec[1]; - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + p_buf_info = &amvavs2_workbuff_spec[2]; + else + p_buf_info = &amvavs2_workbuff_spec[1]; + } else p_buf_info = &amvavs2_workbuff_spec[0]; -#else - p_buf_info = &amvavs2_workbuff_spec[0]; -#endif + init_buff_spec(NULL, p_buf_info); work_buf_size = (p_buf_info->end_adr - p_buf_info->start_adr @@ -5896,8 +7551,6 @@ static int __init amvdec_avs2_driver_init_module(void) #endif pr_debug("amvdec_avs2 module init\n"); - error_handle_policy = 0; - #ifdef ERROR_HANDLE_DEBUG dbg_nal_skip_flag = 0; dbg_nal_skip_count = 0; @@ -5915,19 +7568,22 @@ static int __init amvdec_avs2_driver_init_module(void) return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL - /*&& get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX*/) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + amvdec_avs2_profile.profile = + "8k, 10bit, dwrite, compressed"; + vcodec_profile_register(&amvdec_avs2_profile); + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { if (vdec_is_support_4k()) amvdec_avs2_profile.profile = "4k, 10bit, dwrite, compressed"; else amvdec_avs2_profile.profile = "10bit, dwrite, compressed"; + vcodec_profile_register(&amvdec_avs2_profile); } else { amvdec_avs2_profile.name = "avs2_unsupport"; } - vcodec_profile_register(&amvdec_avs2_profile); INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node, "avs2", avs2_configs, CONFIG_FOR_RW); @@ -5958,6 +7614,9 @@ MODULE_PARM_DESC(frame_height, "\n amvdec_avs2 frame_height\n"); module_param(debug, uint, 0664); MODULE_PARM_DESC(debug, "\n amvdec_avs2 debug\n"); +module_param(debug_again, uint, 0664); +MODULE_PARM_DESC(debug_again, "\n amvdec_avs2 debug_again\n"); + module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); @@ -5991,6 +7650,9 @@ MODULE_PARM_DESC(i_only_flag, "\n amvdec_avs2 i_only_flag\n"); module_param(error_handle_policy, uint, 0664); MODULE_PARM_DESC(error_handle_policy, "\n amvdec_avs2 error_handle_policy\n"); +module_param(re_search_seq_threshold, uint, 0664); +MODULE_PARM_DESC(re_search_seq_threshold, "\n amvdec_avs2 re_search_seq_threshold\n"); + module_param(buf_alloc_width, uint, 0664); MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); @@ -6015,6 +7677,17 @@ MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); module_param(dynamic_buf_num_margin, uint, 0664); MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); +#ifdef CONSTRAIN_MAX_BUF_NUM +module_param(run_ready_max_vf_only_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); + +module_param(run_ready_display_q_num, uint, 0664); +MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); + +module_param(run_ready_max_buf_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); +#endif + module_param(mv_buf_margin, uint, 0664); MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n"); @@ -6071,6 +7744,16 @@ module_param_array(input_empty, uint, module_param_array(not_run_ready, uint, &max_decode_instance_num, 0664); +module_param(video_signal_type, uint, 0664); +MODULE_PARM_DESC(video_signal_type, "\n amvdec_avs2 video_signal_type\n"); + +module_param(force_video_signal_type, uint, 0664); +MODULE_PARM_DESC(force_video_signal_type, "\n amvdec_avs2 force_video_signal_type\n"); + +module_param(enable_force_video_signal_type, uint, 0664); +MODULE_PARM_DESC(enable_force_video_signal_type, "\n amvdec_avs2 enable_force_video_signal_type\n"); + + module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); @@ -6083,6 +7766,14 @@ MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); module_param(udebug_pause_decode_idx, uint, 0664); MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, + "\n amvdec_avs2 pre_decode_buf_level\n"); + +module_param(again_threshold, uint, 0664); +MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); + + module_param(force_disp_pic_index, int, 0664); MODULE_PARM_DESC(force_disp_pic_index, "\n amvdec_h265 force_disp_pic_index\n"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c index 40c7bbdc8dd2..3e95690e73db 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c @@ -54,6 +54,12 @@ #include #include "../utils/firmware.h" #include +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + + +#include + #define DRIVER_NAME "amvdec_h264" #define MODULE_NAME "amvdec_h264" @@ -77,7 +83,7 @@ #define PTS2DUR(x) ((x)*96/90) #define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) #define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2 -#define VDEC_CLOCK_ADJUST_FRAME 50 +#define VDEC_CLOCK_ADJUST_FRAME 30 static inline bool close_to(int a, int b, int m) { @@ -241,13 +247,19 @@ static u32 max_refer_buf = 1; static u32 decoder_force_reset; static unsigned int no_idr_error_count; static unsigned int no_idr_error_max = 60; +static unsigned int canvas_mode; + #ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY /* 0~128*/ static u32 bad_block_scale; #endif +static u32 enable_userdata_debug; static unsigned int enable_switch_fense = 1; #define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k) +static struct vframe_qos_s s_vframe_qos; +static int frame_count; + #if 0 static u32 vh264_no_disp_wd_count; #endif @@ -294,13 +306,36 @@ static struct work_struct notify_work; static struct work_struct set_clk_work; static struct work_struct userdata_push_work; +struct h264_qos_data_node_t { + struct list_head list; + uint32_t b_offset; + int poc; + /* picture qos infomation*/ + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; +}; +/*qos data records list waiting for match with picture that be display*/ +static struct list_head picture_qos_list; +/*free qos data records list*/ +static struct list_head free_qos_nodes_list; +#define MAX_FREE_QOS_NODES 64 +static struct h264_qos_data_node_t free_nodes[MAX_FREE_QOS_NODES]; +static struct work_struct qos_work; static struct dec_sysinfo vh264_amstream_dec_info; static dma_addr_t mc_dma_handle; static void *mc_cpu_addr; static u32 first_offset; static u32 first_pts; +static u32 first_frame_size; static u64 first_pts64; static bool first_pts_cached; static void *sei_data_buffer; @@ -327,6 +362,7 @@ static bool block_display_q; static int vh264_stop(int mode); static s32 vh264_init(void); + #define DFS_HIGH_THEASHOLD 3 static bool pts_discontinue; @@ -335,6 +371,8 @@ static struct ge2d_context_s *ge2d_videoh264_context; static struct vdec_info *gvs; +static struct vdec_s *vdec_h264; + static int ge2d_videoh264task_init(void) { if (ge2d_videoh264_context == NULL) @@ -425,16 +463,19 @@ static inline int fifo_level(void) void spec_set_canvas(struct buffer_spec_s *spec, unsigned int width, unsigned int height) { - canvas_config(spec->y_canvas_index, + int endian; + + endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + canvas_config_ex(spec->y_canvas_index, spec->y_addr, width, height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + CANVAS_ADDR_NOWRAP, canvas_mode, endian); + + canvas_config_ex(spec->u_canvas_index, + spec->u_addr, + width, height / 2, + CANVAS_ADDR_NOWRAP, canvas_mode, endian); - canvas_config(spec->u_canvas_index, - spec->u_addr, - width, height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - return; } static void vh264_notify_work(struct work_struct *work) @@ -478,6 +519,7 @@ static void prepare_display_q(void) if (kfifo_get(&delay_display_q, &vf)) { kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -570,7 +612,10 @@ static tvin_trans_fmt_t convert_3d_format(u32 type) #endif -#ifdef DEBUG_CC_USER_DATA + +#define DUMP_CC_AS_ASCII + +#ifdef DUMP_CC_AS_ASCII static int vbi_to_ascii(int c) { if (c < 0) @@ -584,7 +629,7 @@ static int vbi_to_ascii(int c) return c; } -static void dump_cc_ascii(const uint8_t *buf, int poc) +static void dump_cc_ascii(const uint8_t *buf, unsigned int vpts, int poc) { int cc_flag; int cc_count; @@ -621,72 +666,56 @@ static void dump_cc_ascii(const uint8_t *buf, int poc) break; } } - switch (index) { - case 8: - pr_info("push poc:%d : %c %c %c %c %c %c %c %c\n", - poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5], szAscii[6], szAscii[7]); - break; - case 7: - pr_info("push poc:%d : %c %c %c %c %c %c %c\n", - poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5], szAscii[6]); - break; - case 6: - pr_info("push poc:%d : %c %c %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5]); - break; - case 5: - pr_info("push poc:%d : %c %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4]); - break; - case 4: - pr_info("push poc:%d : %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3]); - break; - case 3: - pr_info("push poc:%d : %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2]); - break; - case 2: - pr_info("push poc:%d : %c %c\n", poc, - szAscii[0], szAscii[1]); - break; - case 1: - pr_info("push poc:%d : %c\n", poc, szAscii[0]); - break; - default: - pr_info("push poc:%d and no CC data: index = %d\n", - poc, index); - break; + + if (index > 0 && index <= 8) { + char pr_buf[128]; + int len; + + sprintf(pr_buf, "push vpts:0x%x, poc:%d :", vpts, poc); + len = strlen(pr_buf); + for (i=0;i= 16) { + int i; + + for (i=0;i<16;i++) + sprintf(buf+i*3, "%02x ", pdata[i]); + + pr_info("%s\n", buf); + nLeft -= 16; + pdata += 16; + } while (nLeft >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); + int i; + for (i=0;idata_buf = userdata_buf; + p_userdata_mgr->buf_len = buf_len; + p_userdata_mgr->data_buf_end = userdata_buf + buf_len; + } +} + +void vh264_destroy_userdata_manager(void) +{ + if (p_userdata_mgr) { + vfree(p_userdata_mgr); + p_userdata_mgr = NULL; + } +} + +/* +#define DUMP_USER_DATA +*/ +#ifdef DUMP_USER_DATA + +#define MAX_USER_DATA_SIZE 3145728 +static void *user_data_buf; +static unsigned char *pbuf_start; +static int total_len; +static int bskip; +static int n_userdata_id; + + +static void print_mem_data(unsigned char *pdata, + int len, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id) +{ + int nLeft; + + nLeft = len; +#if 0 + pr_info("%d len = %d, flag = %d, duration = %d, vpts = 0x%x, vpts_valid = %d\n", + rec_id, len, flag, + duration, vpts, vpts_valid); +#endif + pr_info("%d len = %d, flag = %d, vpts = 0x%x\n", + rec_id, len, flag, vpts); + + + while (nLeft >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7], + pdata[8], pdata[9], pdata[10], pdata[11], + pdata[12], pdata[13], pdata[14], pdata[15]); + nLeft -= 16; + pdata += 16; + } + + + while (nLeft > 0) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7]); + nLeft -= 8; + pdata += 8; + } +} + + +static void dump_data(u8 *pdata, + unsigned int user_data_length, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id) +{ + unsigned char szBuf[256]; + + + memset(szBuf, 0, 256); + memcpy(szBuf, pdata, user_data_length); +/* + aml_swap_data(szBuf, user_data_length); +*/ + + print_mem_data(szBuf, user_data_length, + flag, duration, vpts, + vpts_valid, rec_id); + +#ifdef DEBUG_CC_DUMP_ASCII + dump_cc_ascii(szBuf+7); +#endif +} + +static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta) +{ + u32 *pLen; + int info_cnt; + u8 *pbuf_end; + + if (!user_data_buf) + return; + + if (bskip) { + pr_info("over size, skip\n"); + return; + } + info_cnt = 0; + pLen = (u32 *)pbuf_start; + + *pLen = len; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->duration; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->flags; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts_valid; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + + *pLen = n_userdata_id; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + + + pbuf_end = (u8 *)sei_data_buffer + USER_DATA_SIZE; + if (pdata + len > pbuf_end) { + int first_section_len; + + first_section_len = pbuf_end - pdata; + memcpy(pbuf_start, pdata, first_section_len); + pdata = (u8 *)sei_data_buffer; + pbuf_start += first_section_len; + memcpy(pbuf_start, pdata, len - first_section_len); + pbuf_start += len - first_section_len; + } else { + memcpy(pbuf_start, pdata, len); + pbuf_start += len; + } + + total_len += len + info_cnt * sizeof(u32); + if (total_len >= MAX_USER_DATA_SIZE-4096) + bskip = 1; +} + + +static void dump_userdata_info( + void *puser_data, + int len, + struct userdata_meta_info_t *pmeta) +{ + u8 *pstart; + + pstart = (u8 *)puser_data; + + + push_to_buf(pstart, len, pmeta); +} + +static void show_user_data_buf(void) +{ + u8 *pbuf; + int len; + unsigned int flag; + unsigned int duration; + unsigned int vpts; + unsigned int vpts_valid; + int rec_id; + + pr_info("show user data buf\n"); + pbuf = user_data_buf; + + while (pbuf < pbuf_start) { + u32 *pLen; + + pLen = (u32 *)pbuf; + + len = *pLen; + pLen++; + pbuf += sizeof(u32); + + duration = *pLen; + pLen++; + pbuf += sizeof(u32); + + flag = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts_valid = *pLen; + pLen++; + pbuf += sizeof(u32); + + rec_id = *pLen; + pLen++; + pbuf += sizeof(u32); + + dump_data(pbuf, len, flag, duration, vpts, vpts_valid, rec_id); + pbuf += len; + msleep(30); + } +} + +static int vh264_init_userdata_dump(void) +{ + user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); + if (user_data_buf) + return 1; + else + return 0; +} + +static void vh264_dump_userdata(void) +{ + if (user_data_buf) { + show_user_data_buf(); + kfree(user_data_buf); + user_data_buf = NULL; + } +} + +static void vh264_reset_user_data_buf(void) +{ + total_len = 0; + pbuf_start = user_data_buf; + bskip = 0; + n_userdata_id = 0; } #endif +static void vh264_add_userdata(struct userdata_meta_info_t meta_info, int wp) +{ + struct vh264_userdata_recored_t *p_userdata_rec; + int data_length; + + mutex_lock(&userdata_mutex); + + if (p_userdata_mgr) { + if (wp > p_userdata_mgr->last_wp) + data_length = wp - p_userdata_mgr->last_wp; + else + data_length = wp + p_userdata_mgr->buf_len - + p_userdata_mgr->last_wp; + + if (data_length & 0x7) + data_length = (((data_length + 8) >> 3) << 3); +#if 0 + pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", + p_userdata_mgr->read_index, + p_userdata_mgr->write_index, + data_length, + p_userdata_mgr->last_wp, + wp, + n_userdata_id); +#endif + p_userdata_rec = p_userdata_mgr->records + + p_userdata_mgr->write_index; + p_userdata_rec->meta_info = meta_info; + p_userdata_rec->rec_start = p_userdata_mgr->last_wp; + p_userdata_rec->rec_len = data_length; + p_userdata_mgr->last_wp = wp; + +#ifdef DUMP_USER_DATA + dump_userdata_info(p_userdata_mgr->data_buf + + p_userdata_rec->rec_start, + data_length, + &meta_info); + n_userdata_id++; +#endif + + p_userdata_mgr->write_index++; + if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM) + p_userdata_mgr->write_index = 0; + } + mutex_unlock(&userdata_mutex); + + vdec_wakeup_userdata_poll(vdec_h264); +} + +static int vh264_user_data_read(struct vdec_s *vdec, + struct userdata_param_t *puserdata_para) +{ + int rec_ri, rec_wi; + int rec_len; + u8 *rec_data_start; + u8 *pdest_buf; + struct vh264_userdata_recored_t *p_userdata_rec; + u32 data_size; + u32 res; + int copy_ok = 1; + + + pdest_buf = puserdata_para->pbuf_addr; + + + mutex_lock(&userdata_mutex); + + if (!p_userdata_mgr) { + mutex_unlock(&userdata_mutex); + return 0; + } +/* + pr_info("ri = %d, wi = %d\n", + p_userdata_mgr->read_index, + p_userdata_mgr->write_index); +*/ + rec_ri = p_userdata_mgr->read_index; + rec_wi = p_userdata_mgr->write_index; + + if (rec_ri == rec_wi) { + mutex_unlock(&userdata_mutex); + return 0; + } + + p_userdata_rec = p_userdata_mgr->records + rec_ri; + + rec_len = p_userdata_rec->rec_len; + rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf; +/* + pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n", + p_userdata_rec->rec_len, + p_userdata_rec->rec_start, + puserdata_para->buf_len); +*/ + if (rec_len <= puserdata_para->buf_len) { + /* dvb user data buffer is enought to copy the whole recored. */ + data_size = rec_len; + if (rec_data_start + data_size + > p_userdata_mgr->data_buf_end) { + int first_section_len; + + first_section_len = p_userdata_mgr->buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p1 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)p_userdata_mgr->data_buf, + data_size - first_section_len); + if (res) { + pr_info("p2 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p3 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + p_userdata_mgr->read_index++; + if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM) + p_userdata_mgr->read_index = 0; + } + } else { + /* dvb user data buffer is not enought + to copy the whole recored. */ + data_size = puserdata_para->buf_len; + if (rec_data_start + data_size + > p_userdata_mgr->data_buf_end) { + int first_section_len; + + first_section_len = p_userdata_mgr->buf_len + - p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p4 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + /* first secton copy is ok*/ + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)p_userdata_mgr->data_buf, + data_size - first_section_len); + if (res) { + pr_info("p5 read not end res=%d, request=%d\n", + res, + data_size - first_section_len); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p6 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + p_userdata_mgr->read_index++; + if (p_userdata_mgr->read_index + >= USERDATA_FIFO_NUM) + p_userdata_mgr->read_index = 0; + } + + } + puserdata_para->meta_info = p_userdata_rec->meta_info; + + if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) + puserdata_para->meta_info.records_in_que = + p_userdata_mgr->write_index - + p_userdata_mgr->read_index; + else + puserdata_para->meta_info.records_in_que = + p_userdata_mgr->write_index + + USERDATA_FIFO_NUM - + p_userdata_mgr->read_index; + + puserdata_para->version = (0<<24|0<<16|0<<8|1); + + mutex_unlock(&userdata_mutex); + + return 1; +} + +static void vh264_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + +static void vh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) +{ + mutex_lock(&userdata_mutex); + + if (p_userdata_mgr) { + pr_info("h264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + bInit, p_userdata_mgr->read_index, + p_userdata_mgr->write_index); + p_userdata_mgr->read_index = 0; + p_userdata_mgr->write_index = 0; + + if (bInit) + p_userdata_mgr->last_wp = 0; + } + + mutex_unlock(&userdata_mutex); +} + +static void h264_reset_qos_mgr(void) +{ + int i; + + pr_info("h264_reset_qos_mgr\n"); + + INIT_LIST_HEAD(&free_qos_nodes_list); + INIT_LIST_HEAD(&picture_qos_list); + + for (i = 0; i < MAX_FREE_QOS_NODES; i++) { + free_nodes[i].b_offset = 0xFFFFFFFF; + + list_add_tail(&free_nodes[i].list, + &free_qos_nodes_list); + } +} + + +static void load_qos_data(int pic_number, uint32_t b_offset) +{ + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +/* +#define DEBUG_QOS +*/ +#define SUPPORT_NODE + +#ifdef SUPPORT_NODE + struct h264_qos_data_node_t *node; + struct h264_qos_data_node_t *tmp; + int bFoundNode = 0; + + node = NULL; + if (!list_empty(&picture_qos_list)) { + list_for_each_entry_safe(node, tmp, &picture_qos_list, list) { + if (node->b_offset == b_offset) { + bFoundNode = 1; + break; + } + } + } + /* + pr_info("bFoundNode = %d, node:0x%p\n", bFoundNode, node); + */ + if (!bFoundNode) { + if (!list_empty(&free_qos_nodes_list)) { + node = list_entry( + free_qos_nodes_list.next, + struct h264_qos_data_node_t, + list); + /* + pr_info("get a node:0x%p\n", node); + */ + } else { + pr_info("there is no qos data node avaible\n"); + + return; + } + } + + node->b_offset = b_offset; + node->poc = pic_number; + + node->max_mv = 0; + node->avg_mv = 0; + node->min_mv = 0; + + node->max_skip = 0; + node->avg_skip = 0; + node->min_skip = 0; + + node->max_qp = 0; + node->avg_qp = 0; + node->min_qp = 0; +#endif + + + + + + + /* set rd_idx to 0 */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0); + blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif +#ifdef SUPPORT_NODE + node->avg_qp = rdata32/blk88_y_count; +#endif + + /* intra_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif +#ifdef SUPPORT_NODE + node->avg_skip = rdata32*100/blk88_y_count; +#endif + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif +#ifdef SUPPORT_NODE + node->min_qp = (rdata32>>0)&0xff; +#endif + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif +#ifdef SUPPORT_NODE + node->max_qp = (rdata32>>8)&0xff; +#endif + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + pr_info(" [Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)(value), + value, blk22_mv_count); +#endif +#ifdef SUPPORT_NODE + node->avg_mv = value; +#endif + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif +#ifdef SUPPORT_NODE + node->max_mv = mv_hi; +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif +#ifdef SUPPORT_NODE + node->min_mv = mv_lo; +#endif + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif +} + +void search_qos_node(struct vframe_qos_s *picture_qos, uint32_t b_offset) +{ + struct h264_qos_data_node_t *node; + struct h264_qos_data_node_t *tmp; + + if (!list_empty(&picture_qos_list)) { + list_for_each_entry_safe(node, tmp, &picture_qos_list, list) { + if (node->b_offset == b_offset) { + + picture_qos->avg_mv = node->avg_mv; + picture_qos->min_mv = node->min_mv; + picture_qos->max_mv = node->max_mv; + + picture_qos->avg_skip = node->avg_skip; + picture_qos->min_skip = node->min_skip; + picture_qos->max_skip = node->max_skip; + + picture_qos->avg_qp = node->avg_qp; + picture_qos->min_qp = node->min_qp; + picture_qos->max_qp = node->max_qp; + +#if 0 + pr_info("POC:%d, mv: max:%d, avg:%d, min:%d\n" + "qp: max:%d, avg:%d, min:%d\n" + "skip: max:%d, avg:%d, min:%d\n", + node->poc, + picture_qos->max_mv, + picture_qos->avg_mv, + picture_qos->min_mv, + picture_qos->max_qp, + picture_qos->avg_qp, + picture_qos->min_qp, + picture_qos->max_skip, + picture_qos->avg_skip, + picture_qos->min_skip); +#endif + node->b_offset = 0xFFFFFFFF; + list_move(&node->list, &free_qos_nodes_list); + + break; + } + } + } +} + +static void qos_do_work(struct work_struct *work) +{ + uint32_t poc; + uint32_t bOffset; + + + poc = READ_VREG(AV_SCRATCH_M); + bOffset = READ_VREG(AV_SCRATCH_L); +/* + pr_info("poc:%d, bOffset:0x%x\n", poc, bOffset); +*/ + load_qos_data(poc, bOffset); + + + WRITE_VREG(AV_SCRATCH_0, 0); +} static void userdata_push_do_work(struct work_struct *work) { unsigned int sei_itu35_flags; unsigned int sei_itu35_wp; unsigned int sei_itu35_data_length; - struct userdata_poc_info_t user_data_poc; + struct userdata_meta_info_t meta_info; + u32 offset, pts; + u64 pts_us64 = 0; + u32 slice_type; + u32 reg; + u32 poc_number; + u32 picture_struct; + + memset(&meta_info, 0, sizeof(meta_info)); + + meta_info.duration = frame_dur; + + reg = READ_VREG(AV_SCRATCH_M); + poc_number = reg & 0x7FFFFFF; + if ((poc_number >> 16) == 0x7FF) + poc_number = (reg & 0x7FFFFFF) - 0x8000000; + + slice_type = (reg >> 29) & 0x7; + switch (slice_type) { + case SLICE_TYPE_I: + meta_info.flags |= 1<<7; + break; + case SLICE_TYPE_P: + meta_info.flags |= 3<<7; + break; + case SLICE_TYPE_B: + meta_info.flags |= 2<<7; + break; + } + meta_info.poc_number = poc_number; + picture_struct = (reg >> 27) & 0x3; + + meta_info.flags |= (VFORMAT_H264 << 3) | (picture_struct << 12); + + + offset = READ_VREG(AV_SCRATCH_L); + + if (pts_pickout_offset_us64 + (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) { + pr_info("pts pick outfailed, offset:0x%x\n", offset); + pts = -1; + meta_info.vpts_valid = 0; + } else + meta_info.vpts_valid = 1; + meta_info.vpts = pts; +/* + pr_info("offset:0x%x, vpts:0x%x, slice:%d, poc:%d\n", + offset, pts, slice_type, + poc_number); +*/ sei_itu35_flags = READ_VREG(AV_SCRATCH_J); sei_itu35_wp = (sei_itu35_flags >> 16) & 0xffff; sei_itu35_data_length = sei_itu35_flags & 0x7fff; -#if 0 - pr_info("pocinfo 0x%x, top poc %d, wp 0x%x, length %d\n", - READ_VREG(AV_SCRATCH_L), - READ_VREG(AV_SCRATCH_M), - sei_itu35_wp, sei_itu35_data_length); -#endif - user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L); - user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M); -#ifdef DEBUG_CC_USER_DATA - dump_data(sei_itu35_wp, sei_itu35_data_length, - user_data_poc.poc_number); -#endif + if (enable_userdata_debug) + udr_dump_data(sei_itu35_wp, + sei_itu35_data_length, + pts, poc_number); + + + vh264_add_userdata(meta_info, sei_itu35_wp); + WRITE_VREG(AV_SCRATCH_J, 0); - wakeup_userdata_poll(user_data_poc, sei_itu35_wp, - (unsigned long)sei_data_buffer, - USER_DATA_SIZE, sei_itu35_data_length); } @@ -898,7 +1968,7 @@ static void vh264_set_params(struct work_struct *work) int max_dpb_size, actual_dpb_size, max_reference_size; int i, mb_mv_byte, ret; unsigned long addr; - unsigned int post_canvas, buf_size; + unsigned int post_canvas, buf_size, endian; unsigned int frame_mbs_only_flag; unsigned int chroma_format_idc, chroma444, video_signal; unsigned int crop_infor, crop_bottom, crop_right, level_idc; @@ -910,7 +1980,12 @@ static void vh264_set_params(struct work_struct *work) post_canvas = get_post_canvas(); clk_adj_frame_count = 0; /* set to max decoder clock rate at the beginning */ - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + + if (vdec_is_support_4k()) + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + else + vdec_source_changed(VFORMAT_H264, 1920, 1080, 29); + timing_info_present_flag = 0; mb_width = READ_VREG(AV_SCRATCH_1); seq_info = READ_VREG(AV_SCRATCH_2); @@ -950,11 +2025,12 @@ static void vh264_set_params(struct work_struct *work) if (ucode_type == UCODE_IP_ONLY_PARAM) mb_mv_byte = 96; mb_width = mb_width & 0xff; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { if (!mb_width && mb_total) mb_width = 256; } - mb_height = mb_total / mb_width; + if (mb_width) + mb_height = mb_total / mb_width; last_duration = 0; /* AV_SCRATCH_2 * bit 15: frame_mbs_only_flag @@ -1032,7 +2108,7 @@ static void vh264_set_params(struct work_struct *work) if (max_dpb_size < max_reference_size) max_dpb_size = max_reference_size; if (max_dpb_size > 15 - && get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB + && get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB && (codec_mm_get_total_size() < 80 * SZ_1M)) { actual_dpb_size = max_reference_size + dpb_size_adj; @@ -1112,16 +2188,17 @@ static void vh264_set_params(struct work_struct *work) buffer_spec[i].v_canvas_width = mb_width << 4; buffer_spec[i].v_canvas_height = mb_height << 4; - canvas_config(128 + i * 2, + endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + canvas_config_ex(128 + i * 2, buffer_spec[i].y_addr, mb_width << 4, mb_height << 4, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(128 + i * 2 + 1, + canvas_mode, endian); + canvas_config_ex(128 + i * 2 + 1, buffer_spec[i].u_addr, mb_width << 4, mb_height << 3, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + canvas_mode, endian); WRITE_VREG(ANC0_CANVAS_ADDR + i, spec2canvas(&buffer_spec[i])); } else { @@ -1485,9 +2562,12 @@ static void vh264_isr(void) unsigned int cpu_cmd; unsigned int pts, pts_lookup_save, pts_valid_save, pts_valid = 0; unsigned int pts_us64_valid = 0; + unsigned int framesize; u64 pts_us64; bool force_interlaced_frame = false; +#ifdef ENABLE_SEI_ITU_T35 unsigned int sei_itu35_flags; +#endif static const unsigned int idr_num = FIX_FRAME_RATE_CHECK_IDRFRAME_NUM; static const unsigned int flg_1080_itl = @@ -1621,7 +2701,7 @@ static void vh264_isr(void) return IRQ_HANDLED; } - if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) + if (clk_adj_frame_count < (VDEC_CLOCK_ADJUST_FRAME + 1)) clk_adj_frame_count++; set_frame_info(vf); @@ -1667,6 +2747,7 @@ static void vh264_isr(void) && (first_pts_cached))) { pts = first_pts; pts_us64 = first_pts64; + framesize = first_frame_size; first_pts_cached = false; pts_valid = 1; pts_us64_valid = 1; @@ -1674,8 +2755,8 @@ static void vh264_isr(void) pts_hit++; #endif } else if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, b_offset, &pts, 0, - &pts_us64) == 0) { + (PTS_TYPE_VIDEO, b_offset, &pts, + &framesize, 0, &pts_us64) == 0) { pts_valid = 1; pts_us64_valid = 1; #ifdef DEBUG_PTS @@ -1684,11 +2765,100 @@ static void vh264_isr(void) } else { pts_valid = 0; pts_us64_valid = 0; + framesize = 0; #ifdef DEBUG_PTS pts_missed++; #endif } + if (idr_flag) + s_vframe_qos.type = 4; + else if (slice_type == SLICE_TYPE_I) + s_vframe_qos.type = 1; + else if (slice_type == SLICE_TYPE_P) + s_vframe_qos.type = 2; + else if (slice_type == SLICE_TYPE_B || slice_type == 8) + s_vframe_qos.type = 3; + + s_vframe_qos.size = framesize; + + if (pts_valid) + s_vframe_qos.pts = pts; + else + s_vframe_qos.pts = last_pts + DUR2PTS(frame_dur); +#ifndef ENABLE_SEI_ITU_T35 + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + u32 reg_data; + if (i) { + reg_data = READ_VREG(AV_SCRATCH_N); + s_vframe_qos.max_mv + = (reg_data >> 16) & 0xffff; + s_vframe_qos.avg_mv + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_mv + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_L); + s_vframe_qos.max_qp + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_qp + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_qp + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_M); + s_vframe_qos.max_skip + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_skip + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_skip + = reg_data & 0xff; + } else { + reg_data = READ_VREG(AV_SCRATCH_J); + s_vframe_qos.max_mv + = (reg_data >> 16) & 0xffff; + s_vframe_qos.avg_mv + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_mv + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_I); + s_vframe_qos.max_qp + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_qp + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_qp + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_K); + s_vframe_qos.max_skip + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_skip + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_skip + = reg_data & 0xff; + } + if (decoder_debug_flag&0x2) { + pr_info("max_mv %d avg_mv %d min_mv %d slice_type %d offset %x i = %d\n", + s_vframe_qos.max_mv, + s_vframe_qos.avg_mv, + s_vframe_qos.min_mv, + slice_type, + b_offset, + i); + pr_info("max_qp %d avg_qp %d min_qp %d\n", + s_vframe_qos.max_qp, + s_vframe_qos.avg_qp, + s_vframe_qos.min_qp); + pr_info("max_skip %d avg_skip %d min_skip %d\n", + s_vframe_qos.max_skip, + s_vframe_qos.avg_skip, + s_vframe_qos.min_skip); + } + } else + search_qos_node(&s_vframe_qos, b_offset); +#endif + frame_count++; + + s_vframe_qos.num = frame_count; + vdec_fill_frame_info(&s_vframe_qos, 1); + /* on second IDR frame,check the diff between pts * compute from duration and pts from lookup , * if large than frame_dur,we think it is uncorrect. @@ -1898,6 +3068,7 @@ static void vh264_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, VF_BUFFER_IDX(buffer_index)); + decoder_do_frame_check(NULL, vf); if ((error_recovery_mode_use & 2) && error) { kfifo_put(&recycle_q, (const struct vframe_s *)vf); @@ -1948,6 +3119,7 @@ static void vh264_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, VF_BUFFER_IDX(buffer_index)); + decoder_do_frame_check(NULL, vf); if ((error_recovery_mode_use & 2) && error) { kfifo_put(&recycle_q, (const struct vframe_s *)vf); @@ -2046,12 +3218,14 @@ static void vh264_isr(void) } else if ((cpu_cmd & 0xff) == 9) { first_offset = READ_VREG(AV_SCRATCH_1); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, first_offset, &first_pts, 0, + (PTS_TYPE_VIDEO, first_offset, &first_pts, + &first_frame_size, 0, &first_pts64) == 0) first_pts_cached = true; WRITE_VREG(AV_SCRATCH_0, 0); } else if ((cpu_cmd & 0xff) == 0xa) { int b_offset; + unsigned int frame_size; b_offset = READ_VREG(AV_SCRATCH_2); buffer_index = READ_VREG(AV_SCRATCH_1); @@ -2065,7 +3239,8 @@ static void vh264_isr(void) return IRQ_HANDLED; } if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, b_offset, - &pts, 0, &pts_us64) != 0) + &pts, &frame_size, + 0, &pts_us64) != 0) vf->pts_us64 = vf->pts = 0; else { vf->pts_us64 = pts_us64; @@ -2088,15 +3263,19 @@ static void vh264_isr(void) p_last_vf = vf; pts_discontinue = false; iponly_early_mode = 1; + decoder_do_frame_check(NULL, vf); kfifo_put(&delay_display_q, (const struct vframe_s *)vf); WRITE_VREG(AV_SCRATCH_0, 0); + } else if ((cpu_cmd & 0xff) == 0xB) { + schedule_work(&qos_work); } - +#ifdef ENABLE_SEI_ITU_T35 sei_itu35_flags = READ_VREG(AV_SCRATCH_J); if (sei_itu35_flags & (1 << 15)) { /* data ready */ schedule_work(&userdata_push_work); } +#endif #ifdef HANDLE_H264_IRQ return IRQ_HANDLED; #else @@ -2106,10 +3285,6 @@ static void vh264_isr(void) static void vh264_set_clk(struct work_struct *work) { - if (ucode_type != UCODE_IP_ONLY_PARAM && - (clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) && - frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; if (frame_dur < 10) /*dur is too small ,think it errors fps*/ @@ -2117,7 +3292,6 @@ static void vh264_set_clk(struct work_struct *work) saved_resolution = frame_width * frame_height * fps; vdec_source_changed(VFORMAT_H264, frame_width, frame_height, fps); - } } static void vh264_put_timer_func(unsigned long arg) @@ -2207,7 +3381,7 @@ static void vh264_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) && (vf->index < VF_BUF_NUM)) { + if (vf->index < VF_BUF_NUM) { if (--vfbuf_use[vf->index] == 0) { if (READ_VREG(AV_SCRATCH_7) == 0) { WRITE_VREG(AV_SCRATCH_7, @@ -2230,8 +3404,7 @@ static void vh264_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0 && - (vf->index < VF_BUF_NUM))) { + if (vf->index < VF_BUF_NUM) { vf->index = VF_BUF_NUM; kfifo_put(&newframe_q, (const struct vframe_s *)vf); @@ -2246,7 +3419,11 @@ static void vh264_put_timer_func(unsigned long arg) stream_switching_done(); } - schedule_work(&set_clk_work); + if (ucode_type != UCODE_IP_ONLY_PARAM && + (clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) && + frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); exit: timer->expires = jiffies + PUT_INTERVAL; @@ -2256,6 +3433,12 @@ exit: int vh264_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + u32 ratio_control; + u32 ar; + + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (frame_dur != 0) @@ -2276,6 +3459,13 @@ int vh264_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->total_data = gvs->total_data; vstatus->samp_cnt = gvs->samp_cnt; vstatus->offset = gvs->offset; + ar = min_t(u32, + h264_ar, + DISP_RATIO_ASPECT_RATIO_MAX); + ratio_control = + ar << DISP_RATIO_ASPECT_RATIO_BIT; + vstatus->ratio_control = ratio_control; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); @@ -2394,7 +3584,7 @@ static void vh264_prot_init(void) WRITE_VREG(AV_SCRATCH_I, (u32)(sei_data_buffer_phys - buf_offset)); WRITE_VREG(AV_SCRATCH_J, 0); /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { /* pr_info("vh264 meson8 prot init\n"); */ WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); } @@ -2444,7 +3634,7 @@ static int vh264_local_init(void) pr_debug("sync_outside=%d, use_idr_framerate=%d\n", sync_outside, use_idr_framerate); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) size = V_BUF_ADDR_OFFSET_NEW; else size = V_BUF_ADDR_OFFSET; @@ -2513,7 +3703,8 @@ static int vh264_local_init(void) pts_discontinue = false; no_idr_error_count = 0; - reset_userdata_fifo(1); + vh264_reset_userdata_fifo(vdec_h264, 1); + h264_reset_qos_mgr(); if (enable_switch_fense) { for (i = 0; i < ARRAY_SIZE(fense_buffer_spec); i++) { @@ -2561,6 +3752,8 @@ static s32 vh264_init(void) iponly_early_mode = 0; saved_idc_level = 0; + frame_count = 0; + memset(&s_vframe_qos, 0, sizeof(s_vframe_qos)); /*init vdec status*/ ret = vh264_vdec_info_init(); if (0 != ret) @@ -2573,9 +3766,12 @@ static s32 vh264_init(void) amvdec_enable(); if (!firmwareloaded && tee_enabled()) { - if (tee_load_video_fw((u32)VIDEO_DEC_H264, 0) != 0) { + ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, NULL); + if (ret < 0) { amvdec_disable(); - return -1; + pr_err("H264: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + return ret; } } else { /* -- ucode loading (amrisc and swap code) */ @@ -2649,14 +3845,13 @@ static s32 vh264_init(void) } firmwareloaded = 1; } else { - int ret = -1, size = -1; + int ret = -1; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) return -ENOMEM; - size = get_firmware_data(VIDEO_DEC_H264, buf); - if (size < 0) { + if (get_firmware_data(VIDEO_DEC_H264, buf) < 0) { pr_err("get firmware fail."); vfree(buf); return -1; @@ -2677,7 +3872,6 @@ static s32 vh264_init(void) vfree(buf); if (ret < 0) { - pr_err("h264 load orignal firmware error %d.\n", ret); amvdec_disable(); if (mc_cpu_addr) { dma_free_coherent(amports_get_dma_device(), @@ -2685,6 +3879,8 @@ static s32 vh264_init(void) mc_dma_handle); mc_cpu_addr = NULL; } + pr_err("H264: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } } @@ -2720,11 +3916,12 @@ static s32 vh264_init(void) #endif if (frame_dur != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *)((unsigned long)frame_dur)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -2776,7 +3973,7 @@ static int vh264_stop(int mode) if (stat & STAT_VF_HOOK) { if (mode == MODE_FULL) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); @@ -2814,9 +4011,27 @@ static int vh264_stop(int mode) return 0; } +static void wait_vh264_search_done(void) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 2000) { + pr_info("%s, timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); +} + + static void error_do_work(struct work_struct *work) { - mutex_lock(&vh264_mutex); /* * we need to lock vh264_stop/vh264_init. @@ -2827,8 +4042,9 @@ static void error_do_work(struct work_struct *work) if (atomic_read(&vh264_active)) { amvdec_stop(); do { - msleep(20); + msleep(50); } while (vh264_stream_switching_state != SWITCHING_STATE_OFF); + wait_vh264_search_done(); vh264_reset = 1; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER vh264_ppmgr_reset(); @@ -2839,14 +4055,10 @@ static void error_do_work(struct work_struct *work) vf_reg_provider(&vh264_vf_prov); #endif - msleep(30); vh264_prot_init(); - amvdec_start(); vh264_reset = 0; } - - mutex_unlock(&vh264_mutex); } static void stream_switching_done(void) @@ -2907,6 +4119,7 @@ static void stream_switching_do(struct work_struct *work) if (kfifo_get(&delay_display_q, &vf)) { kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } else @@ -2988,7 +4201,7 @@ static void stream_switching_do(struct work_struct *work) /* send clone to receiver */ kfifo_put(&display_q, (const struct vframe_s *)&fense_vf[i]); - + ATRACE_COUNTER(MODULE_NAME, fense_vf[i].pts); /* early recycle frames for last session */ if (delay) vh264_vf_put(vf, NULL); @@ -3018,6 +4231,7 @@ static int amvdec_h264_probe(struct platform_device *pdev) mutex_unlock(&vh264_mutex); return -EFAULT; } + canvas_mode = pdata->canvas_mode; tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0; if (pdata->sys_info) vh264_amstream_dec_info = *pdata->sys_info; @@ -3040,15 +4254,29 @@ static int amvdec_h264_probe(struct platform_device *pdev) pdata->dec_status = vh264_dec_status; pdata->set_trickmode = vh264_set_trickmode; pdata->set_isreset = vh264_set_isreset; - is_reset = 0; + pdata->user_data_read = vh264_user_data_read; + pdata->reset_userdata_fifo = vh264_reset_userdata_fifo; + pdata->wakeup_userdata_poll = vh264_wakeup_userdata_poll; + + is_reset = 0; + clk_adj_frame_count = 0; if (vh264_init() < 0) { pr_info("\namvdec_h264 init failed.\n"); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; mutex_unlock(&vh264_mutex); return -ENODEV; } + vdec_h264 = pdata; + vh264_crate_userdata_manager(sei_data_buffer, USER_DATA_SIZE); + vh264_reset_userdata_fifo(vdec_h264, 1); + +#ifdef DUMP_USER_DATA + vh264_init_userdata_dump(); + vh264_reset_user_data_buf(); +#endif INIT_WORK(&error_wd_work, error_do_work); INIT_WORK(&stream_switching_work, stream_switching_do); @@ -3056,6 +4284,9 @@ static int amvdec_h264_probe(struct platform_device *pdev) INIT_WORK(¬ify_work, vh264_notify_work); INIT_WORK(&set_clk_work, vh264_set_clk); INIT_WORK(&userdata_push_work, userdata_push_do_work); + INIT_WORK(&qos_work, qos_do_work); + + atomic_set(&vh264_active, 1); @@ -3071,12 +4302,17 @@ static int amvdec_h264_remove(struct platform_device *pdev) cancel_work_sync(&error_wd_work); cancel_work_sync(&stream_switching_work); cancel_work_sync(¬ify_work); - cancel_work_sync(&set_clk_work); cancel_work_sync(&userdata_push_work); + cancel_work_sync(&qos_work); + - mutex_lock(&vh264_mutex); vh264_stop(MODE_FULL); + wait_vh264_search_done(); vdec_source_changed(VFORMAT_H264, 0, 0, 0); +#ifdef DUMP_USER_DATA + vh264_dump_userdata(); +#endif + vh264_destroy_userdata_manager(); atomic_set(&vh264_active, 0); #ifdef DEBUG_PTS pr_info @@ -3087,6 +4323,7 @@ static int amvdec_h264_remove(struct platform_device *pdev) #endif kfree(gvs); gvs = NULL; + cancel_work_sync(&set_clk_work); mutex_unlock(&vh264_mutex); return 0; } @@ -3140,7 +4377,7 @@ static int __init amvdec_h264_driver_init_module(void) pr_err("failed to register amvdec_h264 driver\n"); return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB && (codec_mm_get_total_size() > 80 * SZ_1M)) { amvdec_h264_profile.profile = "4k"; } @@ -3169,6 +4406,9 @@ module_param(sync_outside, uint, 0664); MODULE_PARM_DESC(sync_outside, "\n amvdec_h264 sync_outside\n"); module_param(dec_control, uint, 0664); MODULE_PARM_DESC(dec_control, "\n amvdec_h264 decoder control\n"); +module_param(frame_count, uint, 0664); +MODULE_PARM_DESC(frame_count, + "\n amvdec_h264 decoded total count\n"); module_param(fatal_error_reset, uint, 0664); MODULE_PARM_DESC(fatal_error_reset, "\n amvdec_h264 decoder reset when fatal error happens\n"); @@ -3208,6 +4448,11 @@ MODULE_PARM_DESC(bad_block_scale, "\n print bad_block_scale\n"); #endif +module_param(enable_userdata_debug, uint, 0664); +MODULE_PARM_DESC(enable_userdata_debug, + "\n enable_userdata_debug\n"); + + module_init(amvdec_h264_driver_init_module); module_exit(amvdec_h264_driver_remove_module); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c index 9363bcf9c377..8ea595f09cd9 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c @@ -37,6 +37,10 @@ #include #include #include "../utils/firmware.h" +#include +#include "../../../common/chips/decoder_cpu_ver_info.h" + + #define MEM_NAME "codec_264_4k" @@ -55,6 +59,9 @@ #include #include +#include + + #if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TVD */ #define DOUBLE_WRITE #endif @@ -70,7 +77,6 @@ #define VF_BUFFER_IDX(n) (2 + n) #define DECODER_WORK_SPACE_SIZE 0x800000 - #if 1 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV */ #define H264_4K2K_SINGLE_CORE 1 #else @@ -678,6 +684,7 @@ static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) unsigned int stream_offset; struct vframe_s *vf = NULL; int ret = READ_VREG(MAILBOX_COMMAND); + u32 frame_size; switch (ret & 0xff) { case CMD_ALLOC_VIEW: @@ -714,6 +721,7 @@ static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) ret = pts_lookup_offset_us64(PTS_TYPE_VIDEO, stream_offset, &vf->pts, + &frame_size, 0, &vf->pts_us64); if (ret != 0) @@ -760,6 +768,7 @@ static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) VF_BUFFER_IDX(display_buff_id)); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -942,8 +951,7 @@ static void vh264_4k2k_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) - && (vf->index < DECODE_BUFFER_NUM_MAX) + if ((vf->index < DECODE_BUFFER_NUM_MAX) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(BUFFER_RECYCLE, vf->index + 1); vf->index = DECODE_BUFFER_NUM_MAX; @@ -1408,7 +1416,7 @@ static s32 vh264_4k2k_init(void) int ret = -1, size = -1; char *buf = vmalloc(0x1000 * 16); - if (IS_ERR_OR_NULL(buf)) + if (buf == NULL) return -ENOMEM; pr_info("\nvh264_4k2k_init\n"); @@ -1418,8 +1426,10 @@ static s32 vh264_4k2k_init(void) stat |= STAT_TIMER_INIT; ret = vh264_4k2k_local_init(); - if (ret < 0) + if (ret < 0) { + vfree(buf); return ret; + } amvdec_enable(); /* -- ucode loading (amrisc and swap code) */ @@ -1438,7 +1448,6 @@ static s32 vh264_4k2k_init(void) if (H264_4K2K_SINGLE_CORE) size = get_firmware_data(VIDEO_DEC_H264_4k2K_SINGLE, buf); - else size = get_firmware_data(VIDEO_DEC_H264_4k2K, buf); @@ -1448,11 +1457,18 @@ static s32 vh264_4k2k_init(void) return -1; } - if (amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf) < 0) { + if (H264_4K2K_SINGLE_CORE) + ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, "single_core", buf); + else + ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf); + + if (ret < 0) { amvdec_disable(); dma_free_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); mc_cpu_addr = NULL; + pr_err("H264_4K2K: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1478,19 +1494,6 @@ static s32 vh264_4k2k_init(void) /*slice*/ memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); - if (ret < 0) { - amvdec_disable(); - if (!H264_4K2K_SINGLE_CORE) - amvdec2_disable(); - pr_info("vh264_4k2k load firmware error.\n"); - if (mc_cpu_addr) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - } - - return -EBUSY; - } stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ @@ -1776,7 +1779,7 @@ static int __init amvdec_h264_4k2k_driver_init_module(void) pr_err("failed to register amvdec_h264_4k2k driver\n"); return -ENODEV; } - if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB) + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXTVBB) vcodec_profile_register(&amvdec_h264_4k2k_profile); INIT_REG_NODE_CONFIGS("media.decoder", &h264_4k2k_node, "h264_4k2k", h264_4k2k_configs, CONFIG_FOR_RW); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c index 9ca073f99326..5181a459bd2a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c @@ -476,15 +476,14 @@ static struct vframe_s *vh264mvc_vf_get(void *op_arg) INCPTR(get_ptr); - if (vf) { - if (frame_width == 0) - frame_width = vh264mvc_amstream_dec_info.width; - if (frame_height == 0) - frame_height = vh264mvc_amstream_dec_info.height; + if (frame_width == 0) + frame_width = vh264mvc_amstream_dec_info.width; + if (frame_height == 0) + frame_height = vh264mvc_amstream_dec_info.height; + + vf->width = frame_width; + vf->height = frame_height; - vf->width = frame_width; - vf->height = frame_height; - } if ((no_dropping_cnt < DROPPING_FIRST_WAIT) && (vf->frame_dirty == 0)) no_dropping_cnt++; return vf; @@ -892,6 +891,7 @@ static void vh264mvc_isr(void) struct vframe_s *vf; unsigned int pts, pts_valid = 0; u64 pts_us64; + u32 frame_size; int ret = READ_VREG(MAILBOX_COMMAND); /* pr_info("vh264mvc_isr, cmd =%x\n", ret); */ switch (ret & 0xff) { @@ -1003,6 +1003,11 @@ static void vh264mvc_isr(void) VF_BUFFER_IDX(display_buff_id)); } else if (display_view_id == 1) { + vf->mem_head_handle = + decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + VF_BUFFER_IDX(display_buff_id)); + vf->mem_handle = decoder_bmmu_box_get_mem_handle( mm_blk_handle, @@ -1020,6 +1025,7 @@ static void vh264mvc_isr(void) if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, vfpool_idx[slot].stream_offset, &pts, + &frame_size, 0x10000, &pts_us64) == 0) pts_valid = 1; else @@ -1376,8 +1382,10 @@ static int vh264mvc_local_init(void) vfpool_idx[i].view1_drop = 0; vfpool_idx[i].used = 0; } - for (i = 0; i < VF_POOL_SIZE; i++) + for (i = 0; i < VF_POOL_SIZE; i++) { memset(&vfpool[i], 0, sizeof(struct vframe_s)); + vfpool[i].index = i; + } init_vf_buf(); if (mm_blk_handle) { @@ -1402,10 +1410,10 @@ static int vh264mvc_local_init(void) static s32 vh264mvc_init(void) { - int ret = -1, size = -1; + int ret = -1; char *buf = vmalloc(0x1000 * 16); - if (IS_ERR_OR_NULL(buf)) + if (buf == NULL) return -ENOMEM; pr_info("\nvh264mvc_init\n"); @@ -1414,20 +1422,26 @@ static s32 vh264mvc_init(void) stat |= STAT_TIMER_INIT; ret = vh264mvc_vdec_info_init(); - if (0 != ret) + if (0 != ret) { + vfree(buf); return -ret; + } ret = vh264mvc_local_init(); - if (ret < 0) + if (ret < 0) { + vfree(buf); return ret; + } amvdec_enable(); if (tee_enabled()) { - pr_info("the video fw from the teeload.\n"); - ret = tee_load_video_fw((u32)VIDEO_DEC_H264_MVC, 0); + ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf); if (ret != 0) { amvdec_disable(); + vfree(buf); + pr_err("H264_MVC: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -1; } } else { @@ -1443,8 +1457,7 @@ static s32 vh264mvc_init(void) WRITE_VREG(UCODE_START_ADDR, mc_dma_handle); - size = get_firmware_data(VIDEO_DEC_H264_MVC, buf); - if (size < 0) { + if (get_firmware_data(VIDEO_DEC_H264_MVC, buf) < 0) { pr_err("get firmware fail."); vfree(buf); return -1; @@ -1459,8 +1472,6 @@ static s32 vh264mvc_init(void) /*slice*/ memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); - vfree(buf); - if (ret < 0) { amvdec_disable(); @@ -1471,6 +1482,8 @@ static s32 vh264mvc_init(void) return -EBUSY; } } + vfree(buf); + stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ @@ -1704,13 +1717,13 @@ module_param(view_mode, uint, 0664); MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n"); module_param(dbg_cmd, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc cmd mode\n"); +MODULE_PARM_DESC(dbg_cmd, "\n amvdec_h264mvc cmd mode\n"); module_param(drop_rate, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc drop rate\n"); +MODULE_PARM_DESC(drop_rate, "\n amvdec_h264mvc drop rate\n"); module_param(drop_thread_hold, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc drop thread hold\n"); +MODULE_PARM_DESC(drop_thread_hold, "\n amvdec_h264mvc drop thread hold\n"); module_init(amvdec_h264mvc_driver_init_module); module_exit(amvdec_h264mvc_driver_remove_module); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c index 3ec89d64509d..8008310f56e2 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #define DEBUG #include #include @@ -9,6 +28,8 @@ #include "h264_dpb.h" +#define FRAME_NUM_MAX_SIZE 0x10000 + #undef pr_info #define pr_info printk int dpb_print(int index, int debug_flag, const char *fmt, ...) @@ -364,6 +385,18 @@ void slice_prepare(struct h264_dpb_stru *p_H264_Dpb, pSlice->structure = (p_H264_Dpb-> dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ? FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE]; + if (pSlice->structure == FRAME) { + pSlice->field_pic_flag = 0; + pSlice->bottom_field_flag = 0; + } else { + pSlice->field_pic_flag = 1; + if (pSlice->structure == TOP_FIELD) + pSlice->bottom_field_flag = 0; + else + pSlice->bottom_field_flag = 1; + } + pSlice->pic_struct = p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT]; + sps->num_ref_frames = p_H264_Dpb-> dpb_param.l.data[MAX_REFERENCE_FRAME_NUM]; sps->profile_idc = @@ -516,6 +549,14 @@ void slice_prepare(struct h264_dpb_stru *p_H264_Dpb, p_H264_Dpb->dpb_param.l.data[NUM_UNITS_IN_TICK]; p_H264_Dpb->time_scale = p_H264_Dpb->dpb_param.l.data[TIME_SCALE] | (p_H264_Dpb->dpb_param.l.data[TIME_SCALE + 1] << 16); + + p_H264_Dpb->bitstream_restriction_flag = + (p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1; + p_H264_Dpb->num_reorder_frames = + p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES]; + p_H264_Dpb->max_dec_frame_buffering = + p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME]; + /**/ dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, "%s return\n", __func__); @@ -1016,6 +1057,14 @@ static void init_picture(struct h264_dpb_stru *p_H264_Dpb, currSlice->picture_structure_mmco); } + if (currSlice->pic_struct >= 3) + dec_picture->pic_struct = currSlice->pic_struct + 2; + else if (currSlice->pic_struct == 1) + dec_picture->pic_struct = PIC_TOP_BOT; + else if (currSlice->pic_struct >= 2) + dec_picture->pic_struct = PIC_BOT_TOP; + else + dec_picture->pic_struct = PIC_INVALID; } void dump_pic(struct h264_dpb_stru *p_H264_Dpb) @@ -1460,30 +1509,33 @@ static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb, fs->frame->buf_spec_num = fs->top_field->buf_spec_num; fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index; fs->frame->data_flag = fs->top_field->data_flag; + fs->frame->slice_type = fs->top_field->slice_type; if (fs->bottom_field) fs->frame->data_flag |= (fs->bottom_field->data_flag & 0xf0); #endif + if (fs->bottom_field) { + fs->poc = fs->frame->poc = fs->frame->frame_poc = imin( + fs->top_field->poc, fs->bottom_field->poc); - fs->poc = fs->frame->poc = fs->frame->frame_poc = imin( - fs->top_field->poc, fs->bottom_field->poc); + fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; - fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; + fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; + fs->top_field->bottom_poc = fs->frame->bottom_poc = + fs->bottom_field->poc; - fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; - fs->top_field->bottom_poc = fs->frame->bottom_poc = - fs->bottom_field->poc; - - fs->frame->used_for_reference = (fs->top_field->used_for_reference && - fs->bottom_field->used_for_reference); - fs->frame->is_long_term = (fs->top_field->is_long_term && - fs->bottom_field->is_long_term); + fs->frame->used_for_reference = (fs->top_field->used_for_reference && + fs->bottom_field->used_for_reference); + fs->frame->is_long_term = (fs->top_field->is_long_term && + fs->bottom_field->is_long_term); + } if (fs->frame->is_long_term) fs->frame->long_term_frame_idx = fs->long_term_frame_idx; fs->frame->top_field = fs->top_field; - fs->frame->bottom_field = fs->bottom_field; + if (fs->bottom_field) + fs->frame->bottom_field = fs->bottom_field; fs->frame->frame = fs->frame; fs->frame->coded_frame = 0; @@ -1500,12 +1552,13 @@ static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb, fs->frame->frame_crop_right_offset = fs->top_field->frame_crop_right_offset; } - - fs->top_field->frame = fs->bottom_field->frame = fs->frame; - fs->top_field->top_field = fs->top_field; - fs->top_field->bottom_field = fs->bottom_field; - fs->bottom_field->top_field = fs->top_field; - fs->bottom_field->bottom_field = fs->bottom_field; + if (fs->bottom_field) { + fs->top_field->frame = fs->bottom_field->frame = fs->frame; + fs->top_field->top_field = fs->top_field; + fs->top_field->bottom_field = fs->bottom_field; + fs->bottom_field->top_field = fs->top_field; + fs->bottom_field->bottom_field = fs->bottom_field; + } /**/ #if (MVC_EXTENSION_ENABLE) @@ -1561,10 +1614,13 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->buf_spec_num = p->buf_spec_num; fs->colocated_buf_index = p->colocated_buf_index; #endif + p->slice_type = p_H264_Dpb->mSlice.slice_type; switch (p->structure) { case FRAME: fs->frame = p; fs->is_used = 3; + fs->slice_type = p->slice_type; + fs->frame_size = p->frame_size; if (p->used_for_reference) { fs->is_reference = 3; fs->is_orig_reference = 3; @@ -1591,6 +1647,12 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->top_field = p; fs->is_used |= 1; fs->layer_id = p->layer_id; + if (fs->frame_size == 0) { + fs->slice_type = p->slice_type; +// fs->pts = p->pts; +// fs->pts64 = p->pts64; + } + fs->frame_size += p->frame_size; #if (MVC_EXTENSION_ENABLE) fs->view_id = p->view_id; fs->inter_view_flag[0] = p->inter_view_flag; @@ -1617,6 +1679,12 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->bottom_field = p; fs->is_used |= 2; fs->layer_id = p->layer_id; + if (fs->frame_size == 0) { + fs->slice_type = p->slice_type; +// fs->pts = p->pts; +// fs->pts64 = p->pts64; + } + fs->frame_size += p->frame_size; #if (MVC_EXTENSION_ENABLE) fs->view_id = p->view_id; fs->inter_view_flag[1] = p->inter_view_flag; @@ -1646,6 +1714,19 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->is_output = p->is_output; fs->pre_output = p->pre_output; + /* picture qos infomation*/ + fs->max_mv = p->max_mv; + fs->avg_mv = p->avg_mv; + fs->min_mv = p->min_mv; + + fs->max_qp = p->max_qp; + fs->avg_qp = p->avg_qp; + fs->min_qp = p->min_qp; + + fs->max_skip = p->max_skip; + fs->avg_skip = p->avg_skip; + fs->min_skip = p->min_skip; + if (fs->is_used == 3) { calculate_frame_no(p_Vid, p); #if 0 @@ -1657,6 +1738,7 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->pts = p->pts; fs->pts64 = p->pts64; + fs->timestamp = p->timestamp; } void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb, @@ -1927,7 +2009,7 @@ static void remove_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb, int pos) fs->is_long_term = 0; fs->is_reference = 0; fs->is_orig_reference = 0; - + fs->frame_size = 0; /* move empty framestore to end of buffer */ tmp = p_Dpb->fs[pos]; @@ -2114,7 +2196,8 @@ static void get_smallest_poc(struct DecodedPictureBuffer *p_Dpb, int *poc, /* rain */ if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output) && - (!p_Dpb->fs[i]->pre_output)) { + (!p_Dpb->fs[i]->pre_output) && + (p_Dpb->fs[i]->is_used == 3)) { #else if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) { #endif @@ -2134,8 +2217,18 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) if (!flush_flag) { for (i = 0; i < p_Dpb->used_size; i++) { if ((!p_Dpb->fs[i]->is_output) && - (!p_Dpb->fs[i]->pre_output)) { + (!p_Dpb->fs[i]->pre_output) && (p_Dpb->fs[i]->is_used == 3)) { none_displayed_num++; + if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE) + && (p_Dpb->fs[i]->is_used == 3) + && (p_Dpb->last_output_poc == INT_MIN)) { + p_H264_Dpb->first_insert_frame = FirstInsertFrm_OUT; + p_H264_Dpb->first_output_poc = p_Dpb->fs[i]->poc; + fast_output_flag = 1; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s first insert frame i %d poc %d frame_num %x\n", + __func__, i, p_Dpb->fs[i]->poc, p_Dpb->fs[i]->frame_num); + } /*check poc even/odd*/ if (p_H264_Dpb->poc_even_odd_flag == 0 && p_H264_Dpb->decode_pic_count >= 3) @@ -2147,10 +2240,6 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) if ((p_H264_Dpb->fast_output_enable & 0x1) && (p_Dpb->fs[i]->data_flag & IDR_FLAG)) fast_output_flag = 1; - if (p_H264_Dpb->fast_output_enable & 0x6 - && p_H264_Dpb->poc_even_odd_flag - && p_Dpb->last_output_poc == INT_MIN) - fast_output_flag = 1; if ((p_H264_Dpb->fast_output_enable & 0x2) && ((p_Dpb->fs[i]->poc - p_Dpb->last_output_poc) @@ -2158,6 +2247,7 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) fast_output_flag = 1; if ((p_H264_Dpb->fast_output_enable & 0x4) && (p_H264_Dpb->poc_even_odd_flag == 2) && + (p_Dpb->fs[i]->is_used == 3) && ((p_Dpb->fs[i]->poc - p_Dpb->last_output_poc) == 2)) @@ -2179,6 +2269,19 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) if (is_used_for_reference(p_Dpb->fs[pos])) return 0; #endif + if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) { + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s pos %d pos->poc %d first_output_poc %d \n", + __func__, pos, p_Dpb->fs[pos]->poc, p_H264_Dpb->first_output_poc); + + if (p_Dpb->fs[pos]->poc < p_H264_Dpb->first_output_poc) + p_Dpb->fs[pos]->data_flag |= NODISP_FLAG; + else if (p_Dpb->last_output_poc != INT_MIN) + p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s first_insert_frame %d \n", __func__, p_H264_Dpb->first_insert_frame); + } if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) p_Dpb->fs[pos]->pre_output = 1; else { @@ -2828,12 +2931,12 @@ static void unmark1(struct DecodedPictureBuffer *p_Dpb, unsigned int curr_frame_num, int i) { if (p_Dpb->last_picture) { - if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || - p_Dpb->last_picture->frame_num != curr_frame_num) { + /*if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || + p_Dpb->last_picture->frame_num != curr_frame_num) {*/ unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { + /*} else { unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } + }*/ } } @@ -3500,6 +3603,14 @@ int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, update_ltref_list(p_Dpb); check_num_ref(p_Dpb); + if (p_H264_Dpb->fast_output_enable == H264_OUTPUT_MODE_FAST) + i = 1; + else + i = 0; + if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)) { + while (output_frames(p_H264_Dpb, i)) + ; + } dump_dpb(p_Dpb, 0); p_Dpb->first_pic_done = 1; /*by rain*/ @@ -4904,7 +5015,8 @@ static struct StorablePicture *get_long_term_pic(struct Slice *currSlice, for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { if (currSlice->structure == FRAME) { if (p_Dpb->fs_ltref[i]->is_reference == 3) - if ((p_Dpb->fs_ltref[i]->frame-> + if ((p_Dpb->fs_ltref[i]->frame) && + (p_Dpb->fs_ltref[i]->frame-> is_long_term) && (p_Dpb->fs_ltref[i]->frame-> long_term_pic_num == @@ -4912,13 +5024,16 @@ static struct StorablePicture *get_long_term_pic(struct Slice *currSlice, return p_Dpb->fs_ltref[i]->frame; } else { if (p_Dpb->fs_ltref[i]->is_reference & 1) - if ((p_Dpb->fs_ltref[i]->top_field-> + if ((p_Dpb->fs_ltref[i]->top_field) && + (p_Dpb->fs_ltref[i]->top_field-> is_long_term) && (p_Dpb->fs_ltref[i]->top_field-> long_term_pic_num == LongtermPicNum)) return p_Dpb->fs_ltref[i]->top_field; + if (p_Dpb->fs_ltref[i]->is_reference & 2) - if ((p_Dpb->fs_ltref[i]->bottom_field-> + if ((p_Dpb->fs_ltref[i]->bottom_field) && + (p_Dpb->fs_ltref[i]->bottom_field-> is_long_term) && (p_Dpb->fs_ltref[i]->bottom_field-> long_term_pic_num == @@ -5602,6 +5717,7 @@ int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb) p_Vid->pre_frame_num, p_Vid->max_frame_num); if (p_Vid->recovery_point == 0 && + p_Vid->max_frame_num <= FRAME_NUM_MAX_SIZE && currSlice->frame_num != p_Vid->pre_frame_num && currSlice->frame_num != (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num) { @@ -5735,6 +5851,9 @@ int dpb_check_ref_list_error( int i; /*int j;*/ struct Slice *currSlice = &p_H264_Dpb->mSlice; + /* in first output, ignore ref check */ + if (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE) + return 0; if ((currSlice->slice_type != I_SLICE) && (currSlice->slice_type != SI_SLICE)) { for (i = 0; i < currSlice->listXsize[0]; i++) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h index dc3824f451a5..222113f7eb1b 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef H264_DPB_H_ #define H264_DPB_H_ @@ -19,15 +38,27 @@ #define RRINT_FLAG_RPM 0x0400 #define DEBUG_DISABLE_RUNREADY_RMBUF 0x0800 #define PRINT_FLAG_DUMP_BUFSPEC 0x1000 +#define PRINT_FLAG_V4L_DETAIL 0x8000 #define DISABLE_ERROR_HANDLE 0x10000 #define DEBUG_DUMP_STAT 0x80000 +#define PIC_SINGLE_FRAME 0 +#define PIC_TOP_BOT_TOP 1 +#define PIC_BOT_TOP_BOT 2 +#define PIC_DOUBLE_FRAME 3 +#define PIC_TRIPLE_FRAME 4 +#define PIC_TOP_BOT 5 +#define PIC_BOT_TOP 6 +#define PIC_INVALID 7 #define MVC_EXTENSION_ENABLE 0 #define PRINTREFLIST 0 #define MAX_LIST_SIZE 33 +#define H264_OUTPUT_MODE_NORMAL 0x4 +#define H264_OUTPUT_MODE_FAST 0x8 + #define FALSE 0 #define H264_SLICE_HEAD_DONE 0x01 @@ -47,10 +78,17 @@ #define H264_SEARCH_BUFEMPTY 0x22 #define H264_DECODE_OVER_SIZE 0x23 +#define VIDEO_SIGNAL_LOW 0x26 +#define VIDEO_SIGNAL_HIGHT 0x27 + + #define H264_FIND_NEXT_PIC_NAL 0x50 #define H264_FIND_NEXT_DVEL_NAL 0x51 #define H264_AUX_DATA_READY 0x52 +#define H264_SEI_DATA_READY 0x53 +#define H264_SEI_DATA_DONE 0x54 + /* 0x8x, search state*/ #define H264_STATE_SEARCH_AFTER_SPS 0x80 #define H264_STATE_SEARCH_AFTER_PPS 0x81 @@ -100,8 +138,19 @@ union param { #define BUFFER_SIZE_HI 0X69 #define CROPPING_LEFT_RIGHT 0X6A #define CROPPING_TOP_BOTTOM 0X6B +#if 1 + /* sps_flags2: + *bit 3, bitstream_restriction_flag + *bit 2, pic_struct_present_flag + *bit 1, vcl_hrd_parameters_present_flag + *bit 0, nal_hrd_parameters_present_flag + */ +#define SPS_FLAGS2 0x6c +#define NUM_REORDER_FRAMES 0x6d +#else #define POC_SELECT_NEED_SWAP 0X6C #define POC_SELECT_SWAP 0X6D +#endif #define MAX_BUFFER_FRAME 0X6E #define NON_CONFORMING_STREAM 0X70 @@ -398,6 +447,13 @@ enum ProfileIDC { STEREO_HIGH = 128 /*!< YUV 4:2:0/8 "Stereo High"*/ }; +enum FirstInsertFrm_State { + FirstInsertFrm_IDLE = 0, + FirstInsertFrm_OUT = 1, + FirstInsertFrm_SKIPDONE = 2, +}; + + struct SPSParameters { unsigned int profile_idc; int pic_order_cnt_type; @@ -470,6 +526,7 @@ struct Slice { unsigned char dec_ref_pic_marking_buffer_valid; struct DecRefPicMarking_s dec_ref_pic_marking_buffer[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX]; + int pic_struct; }; struct OldSliceParams { @@ -646,7 +703,21 @@ struct StorablePicture { u32 pts; u64 pts64; + u64 timestamp; unsigned char data_flag; + int pic_struct; + + /* picture qos infomation*/ + int frame_size; + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; }; struct FrameStore { @@ -709,6 +780,22 @@ struct FrameStore { u32 pts; u64 pts64; + u64 timestamp; + + + /* picture qos infomation*/ + int slice_type; + int frame_size; + + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; }; @@ -790,10 +877,15 @@ struct h264_dpb_stru { unsigned int aspect_ratio_idc; unsigned int aspect_ratio_sar_width; unsigned int aspect_ratio_sar_height; + u8 bitstream_restriction_flag; + u16 num_reorder_frames; + u16 max_dec_frame_buffering; unsigned int dec_dpb_status; unsigned char buf_alloc_fail; unsigned int dpb_error_flag; + unsigned int first_insert_frame; + int first_output_poc; }; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c index 690c04c3ba35..08d5421564ed 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -57,10 +58,16 @@ #include #include #include "../utils/config_parser.h" +#include "../../../amvdec_ports/vdec_drv_base.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + +#include + #undef pr_info #define pr_info printk - +#define VDEC_DW #define DEBUG_UCODE #define MEM_NAME "codec_m264" #define MULTI_INSTANCE_FRAMEWORK @@ -74,6 +81,7 @@ #define CHECK_INTERVAL (HZ/100) +#define SEI_DATA_SIZE (8*1024) #define SEI_ITU_DATA_SIZE (4*1024) #define RATE_MEASURE_NUM 8 @@ -108,7 +116,10 @@ #define H264_DEV_NUM 9 +#define CONSTRAIN_MAX_BUF_NUM + #define H264_MMU +#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 static int mmu_enable; static int force_enable_mmu = 1; unsigned int h264_debug_flag; /* 0xa0000000; */ @@ -126,6 +137,8 @@ static unsigned int fixed_frame_rate_mode; static unsigned int error_recovery_mode_in; static int start_decode_buf_level = 0x8000; static int pre_decode_buf_level = 0x1000; +static int stream_mode_start_num = 4; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION /*to make reorder size difference of bl and el not too big*/ static unsigned int reorder_dpb_size_margin_dv = 16; @@ -133,6 +146,18 @@ static unsigned int reorder_dpb_size_margin_dv = 16; static unsigned int reorder_dpb_size_margin = 6; static unsigned int reference_buf_margin = 4; +#ifdef CONSTRAIN_MAX_BUF_NUM +static u32 run_ready_max_vf_only_num; +static u32 run_ready_display_q_num; + /*0: not check + 0xff: mDPB.size + */ +static u32 run_ready_max_buf_num = 0xff; +#endif + +#define VDEC_ASSIST_CANVAS_BLK32 0x5 + + static unsigned int max_alloc_buf_count; static unsigned int decode_timeout_val = 100; static unsigned int errordata_timeout_val = 50; @@ -184,11 +209,16 @@ static unsigned int max_get_frame_interval[H264_DEV_NUM]; static unsigned int run_count[H264_DEV_NUM]; static unsigned int input_empty[H264_DEV_NUM]; static unsigned int not_run_ready[H264_DEV_NUM]; - /* bit[3:0]: - *0, run ; 1, pause; 3, step - *bit[4]: - *1, schedule run - */ +static unsigned int ref_frame_mark_flag[H264_DEV_NUM] = +{1, 1, 1, 1, 1, 1, 1, 1, 1}; + +#define VDEC_CLOCK_ADJUST_FRAME 30 +static unsigned int clk_adj_frame_count; + +/* + *bit[3:0]: 0, run ; 1, pause; 3, step + *bit[4]: 1, schedule run + */ static unsigned int step[H264_DEV_NUM]; #define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf)) @@ -230,7 +260,8 @@ static unsigned int i_only_flag; bit[12] i_only when error happen */ -static unsigned int error_proc_policy = 0x1f36; /*0x1f14*/ +static unsigned int error_proc_policy = 0xf36; /*0x1f14*/ + /* error_skip_count: @@ -249,7 +280,7 @@ static unsigned int force_sliding_margin; bit[15:8]: the max count of skip frames after first I 3, start playing from IDR */ -static unsigned int first_i_policy = (15 << 8) | 2; +static unsigned int first_i_policy = 1; /* fast_output_enable: @@ -257,13 +288,13 @@ static unsigned int first_i_policy = (15 << 8) | 2; bit [1], output frame if the current poc is 1 big than the previous poc bit [2], if even poc only, output frame ifthe cuurent poc is 2 big than the previous poc + bit [3], ip only */ -static unsigned int fast_output_enable = 4; +static unsigned int fast_output_enable = H264_OUTPUT_MODE_NORMAL; static unsigned int enable_itu_t35 = 1; -//static unsigned int frmbase_cont_bitlevel = 0x40;//DEBUG_TMP -static unsigned int frmbase_cont_bitlevel; +static unsigned int frmbase_cont_bitlevel = 0x40; static unsigned int frmbase_cont_bitlevel2 = 0x1; @@ -278,9 +309,13 @@ static unsigned int frmbase_cont_bitlevel2 = 0x1; 3, (1/4):(1/4) ratio, with both compressed frame included 4, (1/2):(1/2) ratio 0x10, double write only + 0x10000: vdec dw horizotal 1/2 + 0x20000: vdec dw horizotal/vertical 1/2 */ static u32 double_write_mode; +#define IS_VDEC_DW(hw) (hw->double_write_mode >> 16 & 0xf) + static void vmh264_dump_state(struct vdec_s *vdec); #define is_in_parsing_state(status) \ @@ -320,17 +355,9 @@ static inline bool close_to(int a, int b, int m) /*#define V_BUF_ADDR_OFFSET (0x13e000)*/ u32 V_BUF_ADDR_OFFSET = 0x200000; #define DCAC_READ_MARGIN (64 * 1024) -#define PIC_SINGLE_FRAME 0 -#define PIC_TOP_BOT_TOP 1 -#define PIC_BOT_TOP_BOT 2 -#define PIC_DOUBLE_FRAME 3 -#define PIC_TRIPLE_FRAME 4 -#define PIC_TOP_BOT 5 -#define PIC_BOT_TOP 6 -#define PIC_INVALID 7 + #define EXTEND_SAR 0xff - #define BUFSPEC_POOL_SIZE 64 #define VF_POOL_SIZE 64 #define VF_POOL_NUM 2 @@ -339,7 +366,7 @@ u32 V_BUF_ADDR_OFFSET = 0x200000; #define BMMU_REF_IDX (BUFSPEC_POOL_SIZE) #define BMMU_DPB_IDX (BUFSPEC_POOL_SIZE + 1) #define BMMU_EXTIF_IDX (BUFSPEC_POOL_SIZE + 2) -#define EXTIF_BUF_SIZE 0x10000 +#define EXTIF_BUF_SIZE (0x10000 * 2) #define HEADER_BUFFER_IDX(n) (n) #define VF_BUFFER_IDX(n) (n) @@ -386,6 +413,21 @@ struct buffer_spec_s { int u_canvas_index; int v_canvas_index; +#ifdef VDEC_DW + unsigned int vdec_dw_y_addr; + unsigned int vdec_dw_u_addr; + unsigned int vdec_dw_v_addr; + + int vdec_dw_y_canvas_index; + int vdec_dw_u_canvas_index; + int vdec_dw_v_canvas_index; +#ifdef NV21 + struct canvas_config_s vdec_dw_canvas_config[2]; +#else + struct canvas_config_s vdec_dw_canvas_config[3]; +#endif +#endif + #ifdef NV21 struct canvas_config_s canvas_config[2]; #else @@ -412,6 +454,13 @@ struct buffer_spec_s { #define AUX_DATA_BUF(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_buf) #define DEL_EXIST(h, p) (h->buffer_spec[p->buf_spec_num].dv_enhance_exist) + +#define vdec_dw_spec2canvas(x) \ + (((x)->vdec_dw_v_canvas_index << 16) | \ + ((x)->vdec_dw_u_canvas_index << 8) | \ + ((x)->vdec_dw_y_canvas_index << 0)) + + #define spec2canvas(x) \ (((x)->v_canvas_index << 16) | \ ((x)->u_canvas_index << 8) | \ @@ -428,9 +477,9 @@ static int vh264_vf_states(struct vframe_states *states, void *); static int vh264_event_cb(int type, void *data, void *private_data); static void vh264_work(struct work_struct *work); static void vh264_notify_work(struct work_struct *work); -static void user_data_push_work(struct work_struct *work); #ifdef MH264_USERDATA_ENABLE static void user_data_ready_notify_work(struct work_struct *work); +static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec); #endif static const char vh264_dec_id[] = "vh264-dev"; @@ -558,6 +607,11 @@ struct vdec_h264_hw_s { u32 suffix_aux_size; void *aux_addr; dma_addr_t aux_phy_addr; + + /* buffer for store all sei data */ + void *sei_data_buf; + u32 sei_data_len; + /* buffer for storing one itu35 recored */ void *sei_itu_data_buf; u32 sei_itu_data_len; @@ -565,8 +619,6 @@ struct vdec_h264_hw_s { /* recycle buffer for user data storing all itu35 records */ void *sei_user_data_buffer; u32 sei_user_data_wp; - int sei_poc; - struct work_struct user_data_work; #ifdef MH264_USERDATA_ENABLE struct work_struct user_data_ready_work; #endif @@ -604,6 +656,7 @@ struct vdec_h264_hw_s { struct vframe_s switching_fense_vf; struct h264_dpb_stru dpb; u8 init_flag; + u8 first_sc_checked; u8 has_i_frame; u8 config_bufmgr_done; u32 max_reference_size; @@ -641,6 +694,9 @@ struct vdec_h264_hw_s { u32 video_signal_from_vui; /*to do .. */ u32 timing_info_present_flag; u32 fixed_frame_rate_flag; + u32 bitstream_restriction_flag; + u32 num_reorder_frames; + u32 max_dec_frame_buffering; u32 iframe_count; u32 aspect_ratio_info; u32 num_units_in_tick; @@ -653,6 +709,7 @@ struct vdec_h264_hw_s { u32 h264_pts_count; u32 duration_from_pts_done; u32 pts_unstable; + u32 unstable_pts; u32 last_checkout_pts; u32 max_refer_buf; @@ -760,11 +817,21 @@ struct vdec_h264_hw_s { /*user data*/ struct mutex userdata_mutex; struct mh264_userdata_info_t userdata_info; - struct list_head frame_uds; /*user data records list waiting for vpts*/ - struct list_head free_uds_wait_nodes; /*free user data records list*/ - struct mh264_ud_record_wait_node_t free_nodes[MAX_FREE_USERDATA_NODES]; + struct mh264_userdata_record_t ud_record; int wait_for_udr_send; #endif + u32 no_mem_count; + u32 canvas_mode; + bool is_used_v4l; + void *v4l2_ctx; + wait_queue_head_t wait_q; + u32 reg_g_status; + struct mutex chunks_mutex; + int need_cache_size; + u64 sc_start_time; + u8 frmbase_cont_flag; + struct vframe_qos_s vframe_qos; + int frameinfo_enable; }; static u32 again_threshold = 0x40; @@ -796,6 +863,7 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); #define HEVC_SAO_MMU_STATUS 0x3639 #define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 + #define HEVC_CM_HEADER_START_ADDR 0x3628 #define HEVC_CM_BODY_START_ADDR 0x3626 #define HEVC_CM_BODY_LENGTH 0x3627 @@ -804,7 +872,9 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); #define HEVC_SAO_CTRL9 0x362d #define HEVCD_MPP_DECOMP_CTL3 0x34c4 #define HEVCD_MPP_VDEC_MCR_CTL 0x34c8 - +#define HEVC_DBLK_CFGB 0x350b +#define HEVC_CM_CORE_STATUS 0x3640 +#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 #define H265_DW_NO_SCALE #define H265_MEM_MAP_MODE 0 /*0:linear 1:32x32 2:64x32*/ @@ -812,16 +882,30 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); #define MAX_FRAME_4K_NUM 0x1200 #define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) - /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ static u32 mem_map_mode = H265_MEM_MAP_MODE; +#define MAX_SIZE_8K (8192 * 4608) +#define MAX_SIZE_4K (4096 * 2304) + +static int is_oversize(int w, int h) +{ + int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? + MAX_SIZE_8K : MAX_SIZE_4K; + + if (w < 0 || h < 0) + return true; + + if (h != 0 && (w > max / h)) + return true; + + return false; +} + static int compute_losless_comp_body_size(int width, int height, int bit_depth_10); static int compute_losless_comp_header_size(int width, int height); - - static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx, int pic_width, int pic_height, u16 bit_depth, unsigned int *mmu_index_adr) { @@ -839,6 +923,13 @@ static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx, PRINT_FLAG_MMU_DETAIL, "alloc_mmu new_fb_idx %d picture_size %d cur_mmu_4k_number %d\n", cur_buf_idx, picture_size, cur_mmu_4k_number); + + if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) { + pr_err("hevc_alloc_mmu cur_mmu_4k_number %d unsupport\n", + cur_mmu_4k_number); + return -1; + } + return decoder_mmu_box_alloc_idx( hw->mmu_box, cur_buf_idx, @@ -892,14 +983,10 @@ static int compute_losless_comp_header_size(int width, int height) return hsize; } - - static int get_double_write_ratio(struct vdec_h264_hw_s *hw) { int ratio = 1; - int dw_mode; - - dw_mode = hw->double_write_mode; + int dw_mode = hw->double_write_mode; if ((dw_mode == 2) || (dw_mode == 3)) ratio = 4; @@ -916,11 +1003,12 @@ static int get_dw_size(struct vdec_h264_hw_s *hw, u32 *pdw_buffer_size_u_v_h) int dw_buf_size; u32 dw_buffer_size_u_v; u32 dw_buffer_size_u_v_h; + int dw_mode = hw->double_write_mode; pic_width = hw->frame_width; pic_height = hw->frame_height; - if (hw->double_write_mode) { + if (dw_mode) { int pic_width_dw = pic_width / get_double_write_ratio(hw); int pic_height_dw = pic_height / @@ -958,6 +1046,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) int dw_size = 0; u32 dw_buffer_size_u_v_h; u32 blkmode = mem_map_mode; + int dw_mode = hw->double_write_mode; canvas_addr = ANC0_CANVAS_ADDR; for (i = 0; i < num_buff; i++) @@ -1000,7 +1089,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) "%s : canvas: %d axiaddr:%x size 0x%x\n", __func__, i, (u32)maddr, size); - if (hw->double_write_mode) { + if (dw_mode) { u32 addr; int canvas_w; int canvas_h; @@ -1074,6 +1163,8 @@ static void hevc_mcr_config_mc_ref(struct vdec_h264_hw_s *hw) /*REFLIST[0]*/ for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) { struct StorablePicture *ref = pSlice->listX[0][i]; + if (ref == NULL) + return; WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24); ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, @@ -1083,6 +1174,8 @@ static void hevc_mcr_config_mc_ref(struct vdec_h264_hw_s *hw) /*REFLIST[1]*/ for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) { struct StorablePicture *ref = pSlice->listX[1][i]; + if (ref == NULL) + return; WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24); ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, @@ -1108,6 +1201,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) } if (slice_type == B_SLICE) { ref = pSlice->listX[0][0]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1116,6 +1211,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); ref = pSlice->listX[1][0]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1123,6 +1220,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) rdata32_2 = rdata32_2 | (rdata32_2 << 16); if (rdata32 == rdata32_2) { ref = pSlice->listX[1][1]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1132,6 +1231,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); } else { /*P-PIC*/ ref = pSlice->listX[0][0]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1140,6 +1241,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); ref = pSlice->listX[0][1]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1151,6 +1254,7 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) return; } + static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, u32 width, u32 height) { u32 data32; @@ -1158,6 +1262,7 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, u32 lcu_total; u32 mc_buffer_size_u_v; u32 mc_buffer_size_u_v_h; + int dw_mode = hw->double_write_mode; lcu_x_num = (width + 15) >> 4; lcu_y_num = (height + 15) >> 4; @@ -1208,6 +1313,15 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, /* ipp_enable*/ WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1 << 1); + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(HEVC_DBLK_CFG1, 0x2); // set ctusize==16 + WRITE_VREG(HEVC_DBLK_CFG2, ((height & 0xffff)<<16) | (width & 0xffff)); + if (dw_mode) + WRITE_VREG(HEVC_DBLK_CFGB, 0x40405703); + else + WRITE_VREG(HEVC_DBLK_CFGB, 0x40405503); + } + data32 = READ_VREG(HEVC_SAO_CTRL0); data32 &= (~0xf); data32 |= 0x4; @@ -1229,7 +1343,7 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, data32 &= (~0xff0); data32 |= endian; /* Big-Endian per 64-bit */ - if (hw->mmu_enable && hw->double_write_mode) + if (hw->mmu_enable && dw_mode) data32 |= ((mem_map_mode << 12)); else data32 |= ((mem_map_mode << 12)|2); @@ -1238,13 +1352,13 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, #ifdef H265_DW_NO_SCALE WRITE_VREG(HEVC_SAO_CTRL5, READ_VREG(HEVC_SAO_CTRL5) & ~(0xff << 16)); - if (hw->mmu_enable && hw->double_write_mode) { + if (hw->mmu_enable && dw_mode) { data32 = READ_VREG(HEVC_SAO_CTRL5); data32 &= (~(0xff << 16)); - if (hw->double_write_mode == 2 || - hw->double_write_mode == 3) + if (dw_mode == 2 || + dw_mode == 3) data32 |= (0xff<<16); - else if (hw->double_write_mode == 4) + else if (dw_mode == 4) data32 |= (0x33<<16); WRITE_VREG(HEVC_SAO_CTRL5, data32); } @@ -1293,6 +1407,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, u32 dw_u_v_adr; u32 canvas_addr; int ret; + int dw_mode = hw->double_write_mode; if (hw->is_new_pic != 1) return; @@ -1312,7 +1427,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); - if (hw->double_write_mode) { + if (dw_mode) { dw_y_adr = hw->buffer_spec[pic->buf_spec_num].dw_y_adr; dw_u_v_adr = hw->buffer_spec[pic->buf_spec_num].dw_u_v_adr; } else { @@ -1320,7 +1435,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, dw_u_v_adr = 0; } #ifdef H265_LOSLESS_COMPRESS_MODE - if (hw->double_write_mode) + if (dw_mode) WRITE_VREG(HEVC_SAO_Y_START_ADDR, dw_y_adr); WRITE_VREG(HEVC_CM_BODY_START_ADDR, mc_y_adr); #ifdef H264_MMU @@ -1336,12 +1451,12 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, #ifndef H265_LOSLESS_COMPRESS_MODE WRITE_VREG(HEVC_SAO_C_START_ADDR, mc_u_v_adr); #else - if (hw->double_write_mode) + if (dw_mode) WRITE_VREG(HEVC_SAO_C_START_ADDR, dw_u_v_adr); #endif #ifndef LOSLESS_COMPRESS_MODE - if (hw->double_write_mode) { + if (dw_mode) { WRITE_VREG(HEVC_SAO_Y_WPTR, mc_y_adr); WRITE_VREG(HEVC_SAO_C_WPTR, mc_u_v_adr); } @@ -1351,7 +1466,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, #endif ret = hevc_alloc_mmu(hw, pic->buf_spec_num, - hw->frame_width, hw->frame_height, 0x0, + (hw->mb_width << 4), (hw->mb_height << 4), 0x0, hw->frame_mmu_map_addr); if (ret != 0) { dpb_print(DECODE_ID(hw), @@ -1362,14 +1477,20 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, } /*Reset SAO + Enable SAO slice_start*/ + if (hw->mmu_enable && get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) + WRITE_VREG(HEVC_DBLK_CFG0, 0x1); // reset buffer32x4 in lpf for every picture WRITE_VREG(HEVC_SAO_INT_STATUS, READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 28); WRITE_VREG(HEVC_SAO_INT_STATUS, READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 31); /*pr_info("hevc_sao_set_pic_buffer:mc_y_adr: %x\n", mc_y_adr);*/ /*Send coommand to hevc-code to supply 4k buffers to sao*/ - WRITE_VREG(H265_SAO_4K_SET_BASE, (u32)hw->frame_mmu_map_phy_addr); - WRITE_VREG(H265_SAO_4K_SET_COUNT, MAX_FRAME_4K_NUM); + + if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(H265_SAO_4K_SET_BASE, (u32)hw->frame_mmu_map_phy_addr); + WRITE_VREG(H265_SAO_4K_SET_COUNT, MAX_FRAME_4K_NUM); + } else + WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, (u32)hw->frame_mmu_map_phy_addr); WRITE_VREG(SYS_COMMAND, H265_PUT_SAO_4K_SET); hw->frame_busy = 1; return; @@ -1399,6 +1520,14 @@ static void hevc_set_frame_done(struct vdec_h264_hw_s *hw) break; } } + timeout = jiffies + HZ; + while (READ_VREG(HEVC_CM_CORE_STATUS) & 0x1) { + if (time_after(jiffies, timeout)) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_MMU_DETAIL, " %s cm_core..timeout!\n", __func__); + break; + } + } WRITE_VREG(HEVC_SAO_INT_STATUS, 0x1); hw->frame_done = 1; return; @@ -1431,15 +1560,17 @@ static void hevc_sao_wait_done(struct vdec_h264_hw_s *hw) } } timeout = jiffies + HZ; - if ((hw->frame_busy == 1) && (hw->frame_done == 1)) { + if ((hw->frame_busy == 1) && (hw->frame_done == 1) ) { + if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { WRITE_VREG(SYS_COMMAND, H265_ABORT_SAO_4K_SET); - while ((READ_VREG(SYS_COMMAND) & 0xff) != - H265_ABORT_SAO_4K_SET_DONE) { - if (time_after(jiffies, timeout)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "wait h265_abort_sao_4k_set_done timeout!\n"); - break; + while ((READ_VREG(SYS_COMMAND) & 0xff) != + H265_ABORT_SAO_4K_SET_DONE) { + if (time_after(jiffies, timeout)) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_MMU_DETAIL, + "wait h265_abort_sao_4k_set_done timeout!\n"); + break; + } } } amhevc_stop(); @@ -1499,8 +1630,16 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) return -1; } else { - int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); + int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); int addr; +#ifdef VDEC_DW + int orig_buf_size; + orig_buf_size = buf_size; + if (IS_VDEC_DW(hw) == 1) + buf_size += (hw->mb_total << 7) + (hw->mb_total << 6); + else if (IS_VDEC_DW(hw) == 2) + buf_size += (hw->mb_total << 6) + (hw->mb_total << 6); +#endif if (hw->buffer_spec[i].cma_alloc_addr) return 0; @@ -1508,12 +1647,20 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) PAGE_ALIGN(buf_size), DRIVER_NAME, &hw->buffer_spec[i].cma_alloc_addr) < 0) { hw->buffer_spec[i].cma_alloc_addr = 0; + if (hw->no_mem_count++ > 3) { + hw->stat |= DECODER_FATAL_ERROR_NO_MEM; + hw->reset_bufmgr_flag = 1; + } dpb_print(DECODE_ID(hw), 0, "%s, fail to alloc buf for bufspec%d, try later\n", __func__, i ); return -1; + } else { + hw->no_mem_count = 0; + hw->stat &= ~DECODER_FATAL_ERROR_NO_MEM; } + hw->buffer_spec[i].buf_adr = hw->buffer_spec[i].cma_alloc_addr; addr = hw->buffer_spec[i].buf_adr; @@ -1521,55 +1668,295 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) hw->buffer_spec[i].y_addr = addr; addr += hw->mb_total << 8; - hw->buffer_spec[i].u_addr = addr; hw->buffer_spec[i].v_addr = addr; addr += hw->mb_total << 7; hw->buffer_spec[i].canvas_config[0].phy_addr = - hw->buffer_spec[i].y_addr; + hw->buffer_spec[i].y_addr; hw->buffer_spec[i].canvas_config[0].width = - hw->mb_width << 4; + hw->mb_width << 4; hw->buffer_spec[i].canvas_config[0].height = - hw->mb_height << 4; + hw->mb_height << 4; hw->buffer_spec[i].canvas_config[0].block_mode = + hw->canvas_mode; + + hw->buffer_spec[i].canvas_config[1].phy_addr = + hw->buffer_spec[i].u_addr; + hw->buffer_spec[i].canvas_config[1].width = + hw->mb_width << 4; + hw->buffer_spec[i].canvas_config[1].height = + hw->mb_height << 3; + hw->buffer_spec[i].canvas_config[1].block_mode = + hw->canvas_mode; + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s, alloc buf for bufspec%d\n", + __func__, i + ); +#ifdef VDEC_DW + + if (!IS_VDEC_DW(hw)) + return 0; + else if (IS_VDEC_DW(hw) == 1) { + addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size; + hw->buffer_spec[i].vdec_dw_y_addr = addr; + addr += hw->mb_total << 7; + hw->buffer_spec[i].vdec_dw_u_addr = addr; + hw->buffer_spec[i].vdec_dw_v_addr = addr; + addr += hw->mb_total << 6; + + hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr = + hw->buffer_spec[i].vdec_dw_y_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[0].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[0].height = + hw->mb_height << 4; + hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode = CANVAS_BLKMODE_32X32; - hw->buffer_spec[i].canvas_config[1].phy_addr = - hw->buffer_spec[i].u_addr; - hw->buffer_spec[i].canvas_config[1].width = - hw->mb_width << 4; - hw->buffer_spec[i].canvas_config[1].height = + hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr = + hw->buffer_spec[i].vdec_dw_u_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[1].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[1].height = hw->mb_height << 3; - hw->buffer_spec[i].canvas_config[1].block_mode = + hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode = CANVAS_BLKMODE_32X32; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s, alloc buf for bufspec%d\n", - __func__, i - ); + }else { + addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size; + hw->buffer_spec[i].vdec_dw_y_addr = addr; + addr += hw->mb_total << 6; + hw->buffer_spec[i].vdec_dw_u_addr = addr; + hw->buffer_spec[i].vdec_dw_v_addr = addr; + addr += hw->mb_total << 5; + + hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr = + hw->buffer_spec[i].vdec_dw_y_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[0].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[0].height = + hw->mb_height << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode = + CANVAS_BLKMODE_32X32; + + hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr = + hw->buffer_spec[i].vdec_dw_u_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[1].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[1].height = + hw->mb_height << 2; + hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode = + CANVAS_BLKMODE_32X32; + } + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s, vdec_dw: alloc buf for bufspec%d\n", + __func__, i + ); +#endif } return 0; } +static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) +{ + int ret = 0; + + ret = ctx->dec_if->get_param(ctx->drv_handle, + GET_PARAM_FREE_FRAME_BUFFER, out); + if (ret) + pr_err("get frame buffer failed.\n"); + + return ret; +} + +static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) +{ + int ret = 0; + struct aml_vcodec_ctx *ctx = NULL; + struct buffer_spec_s *bs = &hw->buffer_spec[idx]; + struct canvas_config_s *y_canvas_cfg = NULL; + struct canvas_config_s *c_canvas_cfg = NULL; + struct vdec_fb *fb = NULL; + unsigned int y_addr, c_addr; + + if (IS_ERR_OR_NULL(hw->v4l2_ctx)) { + pr_err("the v4l context has err.\n"); + return -1; + } + + if (bs->cma_alloc_addr) + return 0; + + ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), buf size: %d\n", ctx->id, __func__, + (hw->mb_total << 8) + (hw->mb_total << 7)); + + ret = v4l_get_fb(hw->v4l2_ctx, &fb); + if (ret) { + pr_err("[%d] get fb fail.\n", ctx->id); + return ret; + } + + bs->cma_alloc_addr = (unsigned long)fb; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), cma alloc addr: 0x%x\n", + ctx->id, __func__, bs->cma_alloc_addr); + + y_addr = virt_to_phys(fb->base_y.va); + c_addr = virt_to_phys(fb->base_c.va); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), y_addr: %x, va: %p\n", + ctx->id, __func__, y_addr, fb->base_y.va); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), c_addr: %x, va: %p\n", + ctx->id, __func__, c_addr, fb->base_c.va); + + bs->y_addr = y_addr; + bs->u_addr = c_addr; + bs->v_addr = c_addr; + + y_canvas_cfg = &bs->canvas_config[0]; + c_canvas_cfg = &bs->canvas_config[1]; + + y_canvas_cfg->phy_addr = y_addr; + y_canvas_cfg->width = hw->mb_width << 4; + y_canvas_cfg->height = hw->mb_height << 4; + y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; + fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, + y_canvas_cfg->width,y_canvas_cfg->height); + + c_canvas_cfg->phy_addr = c_addr; + c_canvas_cfg->width = hw->mb_width << 4; + c_canvas_cfg->height = hw->mb_height << 3; + c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; + fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, + c_canvas_cfg->width, c_canvas_cfg->height); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx); + + return ret; +} + static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i) { - canvas_config(hw->buffer_spec[i]. + int endian = 0; + int blkmode = ((hw->canvas_mode == CANVAS_BLKMODE_LINEAR) || + hw->is_used_v4l) ? CANVAS_BLKMODE_LINEAR : + CANVAS_BLKMODE_32X32; + if (blkmode == CANVAS_BLKMODE_LINEAR) + endian = 7; + + canvas_config_ex(hw->buffer_spec[i]. y_canvas_index, hw->buffer_spec[i].y_addr, hw->mb_width << 4, hw->mb_height << 4, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + blkmode, + endian); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | /* canvas_blk32_wr */ + (blkmode << 10) | /* canvas_blk32*/ + (1 << 8) | /* canvas_index_wr*/ + (hw->buffer_spec[i].y_canvas_index << 0) /* canvas index*/ + ); + } - canvas_config(hw->buffer_spec[i]. + canvas_config_ex(hw->buffer_spec[i]. u_canvas_index, hw->buffer_spec[i].u_addr, hw->mb_width << 4, hw->mb_height << 3, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + blkmode, + endian); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].u_canvas_index << 0)); + } WRITE_VREG(ANC0_CANVAS_ADDR + hw->buffer_spec[i].canvas_pos, spec2canvas(&hw->buffer_spec[i])); + + +#ifdef VDEC_DW + if (!IS_VDEC_DW(hw)) + return; + else if (IS_VDEC_DW(hw) == 1) { + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_y_canvas_index, + hw->buffer_spec[i].vdec_dw_y_addr, + hw->mb_width << 3, + hw->mb_height << 4, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_y_canvas_index << 0)); + } + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_u_canvas_index, + hw->buffer_spec[i].vdec_dw_u_addr, + hw->mb_width << 3, + hw->mb_height << 3, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_u_canvas_index << 0)); + } + } else { + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_y_canvas_index, + hw->buffer_spec[i].vdec_dw_y_addr, + hw->mb_width << 3, + hw->mb_height << 3, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_y_canvas_index << 0)); + } + + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_u_canvas_index, + hw->buffer_spec[i].vdec_dw_u_addr, + hw->mb_width << 3, + hw->mb_height << 2, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_u_canvas_index << 0)); + } + } +#endif } static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) @@ -1664,13 +2051,13 @@ int get_free_buf_idx(struct vdec_s *vdec) int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num) { - u32 cur_buf_idx; + /*u32 cur_buf_idx;*/ unsigned long flags; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, "%s buf_spec_num %d used %d\n", __func__, buf_spec_num, - hw->buffer_spec[buf_spec_num].used); + buf_spec_num > 0 ? hw->buffer_spec[buf_spec_num].used : 0); if (buf_spec_num >= 0 && buf_spec_num < BUFSPEC_POOL_SIZE ) { @@ -1678,10 +2065,10 @@ int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num) hw->buffer_spec[buf_spec_num].used = 0; spin_unlock_irqrestore(&hw->bufspec_lock, flags); if (hw->mmu_enable) { - WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24); + /*WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24); cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL); - cur_buf_idx = cur_buf_idx&0xff; - decoder_mmu_box_free_idx(hw->mmu_box, cur_buf_idx); + cur_buf_idx = cur_buf_idx&0xff;*/ + decoder_mmu_box_free_idx(hw->mmu_box, buf_spec_num); } release_aux_data(hw, buf_spec_num); } @@ -1696,6 +2083,8 @@ static void config_buf_specs(struct vdec_s *vdec) int i, j; unsigned long flags; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + int mode = IS_VDEC_DW(hw) ? 2 : 1; + spin_lock_irqsave(&hw->bufspec_lock, flags); for (i = 0, j = 0; j < hw->dpb.mDPB.size @@ -1704,16 +2093,53 @@ static void config_buf_specs(struct vdec_s *vdec) int canvas; if (hw->buffer_spec[i].used != -1) continue; - canvas = vdec->get_canvas(j, 2); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); - hw->buffer_spec[i].used = 0; + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) { + hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index; + } +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1) + hw->buffer_spec[i].vdec_dw_y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) { + hw->buffer_spec[i].vdec_dw_u_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].vdec_dw_v_canvas_index = + hw->buffer_spec[i].vdec_dw_u_canvas_index; + } + } +#endif + } else { + canvas = vdec->get_canvas(j * mode, 2); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + canvas = vdec->get_canvas(j * mode + 1, 2); + hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas); + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "vdec_dw: config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); + } +#endif + } + hw->buffer_spec[i].used = 0; hw->buffer_spec[i].canvas_pos = j; - /*pr_info("config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i);*/ + j++; } spin_unlock_irqrestore(&hw->bufspec_lock, flags); @@ -1724,25 +2150,64 @@ static void config_buf_specs_ex(struct vdec_s *vdec) int i, j; unsigned long flags; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + int mode = IS_VDEC_DW(hw) ? 2 : 1; + spin_lock_irqsave(&hw->bufspec_lock, flags); for (i = 0, j = 0; j < hw->dpb.mDPB.size && i < BUFSPEC_POOL_SIZE; i++) { - int canvas; + int canvas = 0; if (hw->buffer_spec[i].used != -1) continue; - canvas = vdec->get_canvas(j, 2); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) { + hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index; + } +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1) + hw->buffer_spec[i].vdec_dw_y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) { + hw->buffer_spec[i].vdec_dw_u_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].vdec_dw_v_canvas_index = + hw->buffer_spec[i].vdec_dw_u_canvas_index; + } + } +#endif + } else { + canvas = vdec->get_canvas(j* mode, 2); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + canvas = vdec->get_canvas(j*mode + 1, 2); + hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas); + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "vdec_dw: config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); + } +#endif + } + hw->buffer_spec[i].used = 0; hw->buffer_spec[i].alloc_header_addr = 0; - hw->buffer_spec[i].canvas_pos = j; - pr_info("config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i); j++; } spin_unlock_irqrestore(&hw->bufspec_lock, flags); @@ -1773,9 +2238,11 @@ static void dealloc_buf_specs(struct vdec_h264_hw_s *hw, if (!hw->mmu_enable) { if (hw->buffer_spec[i].cma_alloc_addr) { - decoder_bmmu_box_free_idx( - hw->bmmu_box, - i); + if (!hw->is_used_v4l) { + decoder_bmmu_box_free_idx( + hw->bmmu_box, + i); + } spin_lock_irqsave (&hw->bufspec_lock, flags); hw->buffer_spec[i].cma_alloc_addr = 0; @@ -1837,7 +2304,10 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) dealloc_buf_specs(hw, 0); if (max_alloc_buf_count == 0 || allocated_count < max_alloc_buf_count) { - if (alloc_one_buf_spec(hw, index) >= 0) + if (hw->is_used_v4l) { + if (alloc_one_buf_spec_from_queue(hw, index) >= 0) + ret = 1; + } else if (alloc_one_buf_spec(hw, index) >= 0) ret = 1; } mutex_unlock(&vmh264_mutex); @@ -1910,6 +2380,63 @@ static int check_force_interlace(struct vdec_h264_hw_s *hw, return bForceInterlace; } +static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame) +{ + struct vframe_qos_s *vframe_qos = &hw->vframe_qos; + if (frame->slice_type == I_SLICE) + vframe_qos->type = 1; + else if (frame->slice_type == P_SLICE) + vframe_qos->type = 2; + else if (frame->slice_type == B_SLICE) + vframe_qos->type = 3; + + vframe_qos->size = frame->frame_size; + vframe_qos->pts = frame->pts64; + + vframe_qos->max_mv = frame->max_mv; + vframe_qos->avg_mv = frame->avg_mv; + vframe_qos->min_mv = frame->min_mv; +/* + pr_info("mv: max:%d, avg:%d, min:%d\n", + vframe_qos->max_mv, + vframe_qos->avg_mv, + vframe_qos->min_mv); +*/ + + vframe_qos->max_qp = frame->max_qp; + vframe_qos->avg_qp = frame->avg_qp; + vframe_qos->min_qp = frame->min_qp; +/* + pr_info("qp: max:%d, avg:%d, min:%d\n", + vframe_qos->max_qp, + vframe_qos->avg_qp, + vframe_qos->min_qp); +*/ + + vframe_qos->max_skip = frame->max_skip; + vframe_qos->avg_skip = frame->avg_skip; + vframe_qos->min_skip = frame->min_skip; +/* + pr_info("skip: max:%d, avg:%d, min:%d\n", + vframe_qos->max_skip, + vframe_qos->avg_skip, + vframe_qos->min_skip); +*/ + vframe_qos->num++; + if (hw->frameinfo_enable) + vdec_fill_frame_info(vframe_qos, 1); +} + +static int is_iframe(struct FrameStore *frame) { + + if (frame->frame && frame->frame->slice_type == I_SLICE) { + return 1; + } + return 0; +} + + + int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) { struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; @@ -1948,9 +2475,17 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) __func__, buffer_index, frame->data_flag & ERROR_FLAG, frame->poc, hw->data_flag & ERROR_FLAG, error_proc_policy); + if (frame->frame == NULL && + ((frame->is_used == 1 && frame->top_field) + || (frame->is_used == 2 && frame->bottom_field))) { + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, + "%s Error frame_num %d used %d\n", + frame->frame_num, frame->is_used); + frame->data_flag |= ERROR_FLAG; + } + if ((frame->data_flag & NODISP_FLAG) || (frame->data_flag & NULL_FLAG) || - (frame->data_flag & ERROR_FLAG) || ((!hw->send_error_frame_flag) && (frame->data_flag & ERROR_FLAG)) || ((hw->i_only & 0x1) && @@ -1960,6 +2495,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return 0; /*do not return -1, otherwise flush_dpb() will not flush all dbp frames*/ } + display_frame_count[DECODE_ID(hw)]++; if (dpb_is_debug(DECODE_ID(hw), @@ -1984,6 +2520,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (bForceInterlace) vf_count = 2; hw->buffer_spec[buffer_index].vf_ref = 0; + fill_frame_info(hw, frame); for (i = 0; i < vf_count; i++) { if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { @@ -1993,9 +2530,27 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return -1; } vf->duration_pulldown = 0; - vf->pts = frame->pts; - vf->pts_us64 = frame->pts64; - vf->index = VF_INDEX(frame->index, buffer_index); + if (!(is_iframe(frame)) && hw->unstable_pts) { + vf->pts = 0; + vf->pts_us64 = 0; + vf->timestamp = 0; + vf->index = VF_INDEX(frame->index, buffer_index); + } else { + vf->pts = frame->pts; + vf->pts_us64 = frame->pts64; + vf->timestamp = frame->timestamp; + vf->index = VF_INDEX(frame->index, buffer_index); + } + + if (hw->is_used_v4l) { + vf->v4l_mem_handle + = hw->buffer_spec[buffer_index].cma_alloc_addr; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l mem handle: 0x%x\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); + } + if (hw->mmu_enable) { if (hw->double_write_mode & 0x10) { /* double write only */ @@ -2040,6 +2595,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; vf->canvas0Addr = vf->canvas1Addr = 0; } + vf->bitdepth = BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; @@ -2048,8 +2604,15 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) } else { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21; + vf->canvas0Addr = vf->canvas1Addr = spec2canvas(&hw->buffer_spec[buffer_index]); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) + vf->canvas0Addr = vf->canvas1Addr = + vdec_dw_spec2canvas(&hw->buffer_spec[buffer_index]); +#endif + } set_frame_info(hw, vf, buffer_index); @@ -2094,8 +2657,21 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) vf->duration = vf->duration/2; } + if (i == 0) { + if (hw->mmu_enable) + decoder_do_frame_check(hw_to_vdec(hw), vf); + else + decoder_do_frame_check(hw_to_vdec(hw), vf); + } + + vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT); + vf->sar_width = vf->width; + vf->sar_height = vf->height; + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hw->vf_pre_count++; + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -2106,6 +2682,42 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return 0; } +int notify_v4l_eos(struct vdec_s *vdec) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct vframe_s *vf = NULL; + struct vdec_fb *fb = NULL; + + if (hw->is_used_v4l && hw->eos) { + if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s fatal error, no available buffer slot.\n", + __func__); + return -1; + } + + if (v4l_get_fb(hw->v4l2_ctx, &fb)) { + pr_err("[%d] get fb fail.\n", ctx->id); + return -1; + } + + vf->timestamp = ULONG_MAX; + vf->v4l_mem_handle = (unsigned long)fb; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + + ATRACE_COUNTER(MODULE_NAME, vf->pts); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] H264 EOS notify.\n", ctx->id); + } + + return 0; +} + /****************** * Hardware config */ @@ -2421,6 +3033,7 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) struct Slice *pSlice = &(p_H264_Dpb->mSlice); unsigned int colocate_adr_offset; unsigned int val; + #ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF int colocate_buf_index; #endif @@ -2471,12 +3084,23 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) canvas_pos); print_pic_info(DECODE_ID(hw), "cur", pic, pSlice->slice_type); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw) && pic->mb_aff_frame_flag) + WRITE_VREG(MDEC_DOUBLEW_CFG0, + ( READ_VREG(MDEC_DOUBLEW_CFG0) & (~(1 << 30)))); +#endif WRITE_VREG(CURR_CANVAS_CTRL, canvas_pos << 24); + canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff; + if (!hw->mmu_enable) { - canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff; WRITE_VREG(REC_CANVAS_ADDR, canvas_adr); WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr); WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr); +#ifdef VDEC_DW + WRITE_VREG(MDEC_DOUBLEW_CFG1, + (hw->buffer_spec[canvas_pos].vdec_dw_y_canvas_index + | (hw->buffer_spec[canvas_pos].vdec_dw_u_canvas_index << 8))); +#endif } else hevc_sao_set_pic_buffer(hw, pic); @@ -2545,14 +3169,14 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) /* bit[6:5] - frame/field info, * 01 - top, 10 - bottom, 11 - frame */ -#ifdef ERROR_CHECK + #ifdef ERROR_CHECK if (ref == NULL) { hw->data_flag |= ERROR_FLAG; pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref list0 NULL\n"); return -1; } - if (ref->data_flag & ERROR_FLAG) { + if ((ref->data_flag & ERROR_FLAG) && ref_frame_mark_flag[DECODE_ID(hw)]) { hw->data_flag |= ERROR_FLAG; pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark1 \n"); @@ -2568,6 +3192,7 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) cfg = 0x2; else /* FRAME */ cfg = 0x3; + one_ref_cfg = (canvas_pos & 0x1f) | (cfg << 5); ref_reg_val <<= 8; ref_reg_val |= one_ref_cfg; @@ -2613,14 +3238,15 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) /* bit[6:5] - frame/field info, * 01 - top, 10 - bottom, 11 - frame */ -#ifdef ERROR_CHECK + + #ifdef ERROR_CHECK if (ref == NULL) { hw->data_flag |= ERROR_FLAG; pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error list1 NULL\n"); return -2; } - if (ref->data_flag & ERROR_FLAG) { + if ((ref->data_flag & ERROR_FLAG) && (ref_frame_mark_flag[DECODE_ID(hw)])) { pic->data_flag |= ERROR_FLAG; hw->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark2\n"); @@ -3070,6 +3696,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; int buf_spec_num; int frame_index; + if (vf == (&hw->vframe_dummy)) return; if (vf->index == -1) { @@ -3174,6 +3801,7 @@ static int vh264_event_cb(int type, void *data, void *op_arg) static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, u32 index) { + struct canvas_config_s *p_canvas_config; int force_rate = input_frame_based(hw_to_vdec(hw)) ? force_rate_framebase : force_rate_streambase; dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, @@ -3201,16 +3829,427 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, #else vf->plane_num = 3; #endif - vf->canvas0_config[0] = hw->buffer_spec[index].canvas_config[0]; - vf->canvas0_config[1] = hw->buffer_spec[index].canvas_config[1]; + + if (IS_VDEC_DW(hw)) { + vf->width = (hw->frame_width /2); + if (IS_VDEC_DW(hw) == 2) + vf->height = (hw->frame_height /2); + p_canvas_config = &hw->buffer_spec[index].vdec_dw_canvas_config[0]; + } else + p_canvas_config = &hw->buffer_spec[index].canvas_config[0]; + + vf->canvas0_config[0] = p_canvas_config[0]; + vf->canvas0_config[1] = p_canvas_config[1]; #ifndef NV21 - vf->canvas0_config[2] = hw->buffer_spec[index].canvas_config[2]; + vf->canvas0_config[2] = p_canvas_config[2]; #endif - vf->canvas1_config[0] = hw->buffer_spec[index].canvas_config[0]; - vf->canvas1_config[1] = hw->buffer_spec[index].canvas_config[1]; + vf->canvas1_config[0] = p_canvas_config[0]; + vf->canvas1_config[1] = p_canvas_config[1]; #ifndef NV21 - vf->canvas1_config[2] = hw->buffer_spec[index].canvas_config[2]; + vf->canvas1_config[2] = p_canvas_config[2]; #endif + /* signal_type */ + if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) + vf->signal_type = hw->video_signal_from_vui; + else + vf->signal_type = 0; + +} + +static void get_picture_qos_info(struct StorablePicture *picture) +{ + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + unsigned char a[3]; + unsigned char i, j, t; + unsigned long data; + + get_random_bytes(&data, sizeof(unsigned long)); + if (picture->slice_type == I_SLICE) + data = 0; + a[0] = data & 0xff; + a[1] = (data >> 8) & 0xff; + a[2] = (data >> 16) & 0xff; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_mv = a[2]; + picture->avg_mv = a[1]; + picture->min_mv = a[0]; + /* + pr_info("mv data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); + */ + + get_random_bytes(&data, sizeof(unsigned long)); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_qp = a[2]; + picture->avg_qp = a[1]; + picture->min_qp = a[0]; + /* + pr_info("qp data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); + */ + + get_random_bytes(&data, sizeof(unsigned long)); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_skip = a[2]; + picture->avg_skip = a[1]; + picture->min_skip = a[0]; + + + /* + pr_info("skip data %x a[0]= %x a[1]= %x a[2]= %x\n", + data,a[0], a[1], a[2]); + */ + } else { + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +/* +#define DEBUG_QOS +*/ +#ifdef DEBUG_QOS + int pic_number = picture->poc; +#endif + + picture->max_mv = 0; + picture->avg_mv = 0; + picture->min_mv = 0; + + picture->max_skip = 0; + picture->avg_skip = 0; + picture->min_skip = 0; + + picture->max_qp = 0; + picture->avg_qp = 0; + picture->min_qp = 0; + + + + + + /* set rd_idx to 0 */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0); + blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif + picture->avg_qp = rdata32/blk88_y_count; + /* intra_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + picture->avg_skip = rdata32*100/blk88_y_count; + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif + picture->min_qp = (rdata32>>0)&0xff; + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif + picture->max_qp = (rdata32>>8)&0xff; + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + pr_info(" [Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)(value), + value, blk22_mv_count); +#endif + picture->avg_mv = value; + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + picture->max_mv = mv_hi; + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + picture->min_mv = mv_lo; + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + } } static int get_max_dec_frame_buf_size(int level_idc, @@ -3292,7 +4331,8 @@ static void vh264_config_canvs_for_mmu(struct vdec_h264_hw_s *hw) if (hw->decode_pic_count == 0) { for (j = 0; j < hw->dpb.mDPB.size; j++) { i = get_buf_spec_by_canvas_pos(hw, j); - config_decode_canvas_ex(hw, i); + if (i >= 0) + config_decode_canvas_ex(hw, i); } } mutex_unlock(&vmh264_mutex); @@ -3305,7 +4345,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, int i, j; int mb_width, mb_total; int max_reference_size, level_idc; - int mb_height; + int mb_height = 0; unsigned long flags; /*int mb_mv_byte;*/ struct vdec_s *vdec = hw_to_vdec(hw); @@ -3330,11 +4370,10 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, mb_total = (seq_info2 >> 8) & 0xffff; if (!mb_width && mb_total) /*for 4k2k*/ mb_width = 256; - mb_height = mb_total/mb_width; - if (mb_width > 0x110 || - mb_height > 0xa0 || - mb_width <= 0 || - mb_height <= 0) { + if (mb_width) + mb_height = mb_total/mb_width; + if (mb_width <= 0 || mb_height <= 0 || + is_oversize(mb_width << 4, mb_height << 4)) { dpb_print(DECODE_ID(hw), 0, "!!!wrong seq_info2 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n", seq_info2, @@ -3413,7 +4452,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, (unsigned int)((8 << chroma444) - 1)); } dpb_print(DECODE_ID(hw), 0, - "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ", + "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d,\n", frame_mbs_only_flag, crop_bottom, hw->frame_height); dpb_print(DECODE_ID(hw), 0, "mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", @@ -3423,13 +4462,17 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (hw->frame_height == 1088) hw->frame_height = 1080; #endif - - mb_width = (mb_width+3) & 0xfffffffc; - mb_height = (mb_height+3) & 0xfffffffc; + if (!hw->mmu_enable) { + mb_width = (mb_width+3) & 0xfffffffc; + mb_height = (mb_height+3) & 0xfffffffc; + } mb_total = mb_width * mb_height; + hw->mb_width = mb_width; + hw->mb_height = mb_height; + hw->mb_total = mb_total; if (hw->mmu_enable) hevc_mcr_sao_global_hw_init(hw, - hw->frame_width, hw->frame_height); + (hw->mb_width << 4), (hw->mb_height << 4)); reg_val = param4; level_idc = reg_val & 0xff; @@ -3440,13 +4483,25 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, level_idc, max_reference_size); p_H264_Dpb->colocated_buf_size = mb_total * 96; - hw->mb_total = mb_total; - hw->mb_width = mb_width; - hw->mb_height = mb_height; - hw->dpb.reorder_pic_num = get_max_dec_frame_buf_size(level_idc, max_reference_size, mb_width, mb_height); + + dpb_print(DECODE_ID(hw), 0, + "restriction_flag=%d, max_dec_frame_buffering=%d, reorder_pic_num=%d\n", + hw->bitstream_restriction_flag, + hw->max_dec_frame_buffering, + hw->dpb.reorder_pic_num); + + if ((hw->bitstream_restriction_flag) && + (hw->max_dec_frame_buffering < + hw->dpb.reorder_pic_num)) { + hw->dpb.reorder_pic_num = hw->max_dec_frame_buffering; + dpb_print(DECODE_ID(hw), 0, + "set reorder_pic_num to %d\n", + hw->dpb.reorder_pic_num); + } + active_buffer_spec_num = hw->dpb.reorder_pic_num + used_reorder_dpb_size_margin; @@ -3477,10 +4532,19 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (!hw->mmu_enable) { config_buf_specs(vdec); i = get_buf_spec_by_canvas_pos(hw, 0); - if (alloc_one_buf_spec(hw, i) >= 0) - config_decode_canvas(hw, i); - else - ret = -1; + + if (hw->is_used_v4l) { + if (i != -1) { + ret = alloc_one_buf_spec_from_queue(hw, i); + if (!ret) + config_decode_canvas(hw, i); + } + } else { + if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0) + config_decode_canvas(hw, i); + else + ret = -1; + } } else { if (hw->double_write_mode) { config_buf_specs_ex(vdec); @@ -3548,11 +4612,23 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (!hw->mmu_enable) { mutex_lock(&vmh264_mutex); if (ret >= 0 && hw->decode_pic_count == 0) { + int buf_cnt; /* h264_reconfig: alloc later*/ - for (j = 1; j < hw->dpb.mDPB.size; j++) { + buf_cnt = hw->dpb.mDPB.size; + + for (j = 1; j < buf_cnt; j++) { i = get_buf_spec_by_canvas_pos(hw, j); - if (alloc_one_buf_spec(hw, i) < 0) + + if (hw->is_used_v4l) { + if (alloc_one_buf_spec_from_queue + (hw, i) < 0) { + if (j++ != buf_cnt) + ret = -1; + break; + } + } else if (alloc_one_buf_spec(hw, i) < 0) break; + config_decode_canvas(hw, i); } } @@ -3578,6 +4654,19 @@ static void vui_config(struct vdec_h264_hw_s *hw) hw->time_scale = p_H264_Dpb->time_scale; hw->timing_info_present_flag = p_H264_Dpb->vui_status & 0x2; + hw->bitstream_restriction_flag = + p_H264_Dpb->bitstream_restriction_flag; + hw->num_reorder_frames = + p_H264_Dpb->num_reorder_frames; + hw->max_dec_frame_buffering = + p_H264_Dpb->max_dec_frame_buffering; + + dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, + "vui_config: pdb %d, %d, %d\n", + p_H264_Dpb->bitstream_restriction_flag, + p_H264_Dpb->num_reorder_frames, + p_H264_Dpb->max_dec_frame_buffering); + hw->fixed_frame_rate_flag = 0; if (hw->timing_info_present_flag) { hw->fixed_frame_rate_flag = @@ -3763,9 +4852,12 @@ static void vui_config(struct vdec_h264_hw_s *hw) static void bufmgr_recover(struct vdec_h264_hw_s *hw) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2); - if (error_proc_policy & 0x20) - hw->reset_bufmgr_flag = 1; + if (error_proc_policy & 0x20) { + if (!hw->is_used_v4l) + hw->reset_bufmgr_flag = 1; + } } void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) @@ -3779,6 +4871,32 @@ void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) hw->reset_bufmgr_flag = 1; } +#ifdef CONSTRAIN_MAX_BUF_NUM +static int get_vf_ref_only_buf_count(struct vdec_h264_hw_s *hw) +{ + int i; + int count = 0; + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (is_buf_spec_in_disp_q(hw, i) && + hw->buffer_spec[i].vf_ref > 0) + count++; + } + return count; +} + +static int get_used_buf_count(struct vdec_h264_hw_s *hw) +{ + int i; + int count = 0; + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (is_buf_spec_in_use(hw, i)) + count++; + } + return count; +} +#endif + + static bool is_buffer_available(struct vdec_s *vdec) { bool buffer_available = 1; @@ -3788,7 +4906,7 @@ static bool is_buffer_available(struct vdec_s *vdec) if ((kfifo_len(&hw->newframe_q) <= 0) || ((hw->config_bufmgr_done) && (!have_free_buf_spec(vdec))) || ((p_H264_Dpb->mDPB.init_done) && - (p_H264_Dpb->mDPB.used_size == p_H264_Dpb->mDPB.size) && + (p_H264_Dpb->mDPB.used_size >= (p_H264_Dpb->mDPB.size -1)) && (is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) == 0))) { dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, "%s, empty, newq(%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n", @@ -3854,6 +4972,211 @@ static bool is_buffer_available(struct vdec_s *vdec) return buffer_available; } +#define AUX_TAG_SEI 0x2 + +#define SEI_BUFFERING_PERIOD 0 +#define SEI_PicTiming 1 +#define SEI_USER_DATA 4 +#define SEI_RECOVERY_POINT 6 + +/* + ************************************************************************* + * Function:Reads bits from the bitstream buffer + * Input: + byte buffer[] + containing sei message data bits + int totbitoffset + bit offset from start of partition + int bytecount + total bytes in bitstream + int numbits + number of bits to read + * Output: + int *info + * Return: + -1: failed + > 0: the count of bit read + * Attention: + ************************************************************************* + */ + +static int get_bits(unsigned char buffer[], + int totbitoffset, + int *info, + int bytecount, + int numbits) +{ + register int inf; + long byteoffset; + int bitoffset; + + int bitcounter = numbits; + + byteoffset = totbitoffset / 8; + bitoffset = 7 - (totbitoffset % 8); + + inf = 0; + while (numbits) { + inf <<= 1; + inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset; + numbits--; + bitoffset--; + if (bitoffset < 0) { + byteoffset++; + bitoffset += 8; + if (byteoffset > bytecount) + return -1; + } + } + + *info = inf; + + + return bitcounter; +} + +static int parse_one_sei_record(struct vdec_h264_hw_s *hw, + u8 *sei_data_buf, + u8 *sei_data_buf_end) +{ + int payload_type; + int payload_size; + u8 *p_sei; + int temp; + int bit_offset; + int read_size; + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + + p_sei = sei_data_buf; + read_size = 0; + payload_type = 0; + do { + if (p_sei >= sei_data_buf_end) + return read_size; + + payload_type += *p_sei; + read_size++; + } while (*p_sei++ == 255); + + + payload_size = 0; + do { + if (p_sei >= sei_data_buf_end) + return read_size; + + payload_size += *p_sei; + read_size++; + } while (*p_sei++ == 255); + + + if (p_sei + payload_size > sei_data_buf_end) { + dpb_print(DECODE_ID(hw), 0, + "%s: payload_type = %d, payload_size = %d is over\n", + __func__, payload_type, payload_size); + return read_size; + } + bit_offset = 0; + + if (payload_size <= 0) { + dpb_print(DECODE_ID(hw), 0, + "%s warning: this is a null sei message for payload_type = %d\n", + __func__, payload_type); + return read_size; + } + switch (payload_type) { + case SEI_BUFFERING_PERIOD: + break; + case SEI_PicTiming: + if (p_H264_Dpb->vui_status & 0xc) { + int cpb_removal_delay; + int dpb_output_delay; + u32 delay_len; + + delay_len = p_H264_Dpb->dpb_param.l.data[DELAY_LENGTH]; + cpb_removal_delay + = (delay_len & 0x1F) + 1; + dpb_output_delay + = ((delay_len >> 5) & 0x1F) + 1; + + get_bits(p_sei, bit_offset, + &temp, payload_size, + dpb_output_delay+cpb_removal_delay); + bit_offset += dpb_output_delay+cpb_removal_delay; + } + if (p_H264_Dpb->vui_status & 0x10) { + get_bits(p_sei, bit_offset, &temp, payload_size, 4); + bit_offset += 4; + p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT] = temp; + } + break; + case SEI_USER_DATA: + if (enable_itu_t35) { + int i; + int j; + int data_len; + u8 *user_data_buf; + + user_data_buf + = hw->sei_itu_data_buf + hw->sei_itu_data_len; + /* user data length should be align with 8 bytes, + if not, then padding with zero*/ + for (i = 0; i < payload_size; i += 8) { + for (j = 0; j < 8; j++) { + int index; + + index = i+7-j; + if (index >= payload_size) + user_data_buf[i+j] = 0; + else + user_data_buf[i+j] + = p_sei[i+7-j]; + } + } + + data_len = payload_size; + if (payload_size % 8) + data_len = ((payload_size + 8) >> 3) << 3; + + hw->sei_itu_data_len += data_len; + /* + dpb_print(DECODE_ID(hw), 0, + "%s: user data, and len = %d:\n", + __func__, hw->sei_itu_data_len); + */ + } + break; + case SEI_RECOVERY_POINT: + p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT] = 1; + break; + } + + return read_size + payload_size; +} + +static void parse_sei_data(struct vdec_h264_hw_s *hw, + u8 *sei_data_buf, + int len) +{ + char *p_sei; + char *p_sei_end; + int parsed_size; + int read_size; + + + p_sei = sei_data_buf; + p_sei_end = p_sei + len; + parsed_size = 0; + while (parsed_size < len) { + read_size = parse_one_sei_record(hw, p_sei, p_sei_end); + p_sei += read_size; + parsed_size += read_size; + if (*p_sei == 0x80) { + p_sei++; + parsed_size++; + } + } +} + static void check_decoded_pic_error(struct vdec_h264_hw_s *hw) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; @@ -3909,12 +5232,67 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) int ret; if (dec_dpb_status == H264_CONFIG_REQUEST) { +#if 1 + unsigned short *p = (unsigned short *)hw->lmem_addr; + dma_sync_single_for_cpu( + amports_get_dma_device(), + hw->lmem_addr_remap, + PAGE_SIZE, + DMA_FROM_DEVICE); + for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) { + int ii; + for (ii = 0; ii < 4; ii++) { + p_H264_Dpb->dpb_param.l.data[i+ii] = + p[i+3-ii]; + if (dpb_is_debug(DECODE_ID(hw), + RRINT_FLAG_RPM)) { + if (((i + ii) & 0xf) == 0) + dpb_print(DECODE_ID(hw), + 0, "%04x:", + i); + dpb_print_cont(DECODE_ID(hw), + 0, "%04x ", + p[i+3-ii]); + if (((i + ii + 1) & 0xf) == 0) + dpb_print_cont( + DECODE_ID(hw), + 0, "\r\n"); + } + } + } + + p_H264_Dpb->bitstream_restriction_flag = + (p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1; + p_H264_Dpb->num_reorder_frames = + p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES]; + p_H264_Dpb->max_dec_frame_buffering = + p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME]; + + dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, + "H264_CONFIG_REQUEST: pdb %d, %d, %d\n", + p_H264_Dpb->bitstream_restriction_flag, + p_H264_Dpb->num_reorder_frames, + p_H264_Dpb->max_dec_frame_buffering); + hw->bitstream_restriction_flag = + p_H264_Dpb->bitstream_restriction_flag; + hw->num_reorder_frames = + p_H264_Dpb->num_reorder_frames; + hw->max_dec_frame_buffering = + p_H264_Dpb->max_dec_frame_buffering; +#endif + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE); reset_process_time(hw); + hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->dec_result = DEC_RESULT_CONFIG_PARAM; vdec_schedule_work(&hw->work); } else if (dec_dpb_status == H264_SLICE_HEAD_DONE) { + u16 data_hight; + u16 data_low; + u32 video_signal; + int slice_header_process_status = 0; + int I_flag; /*unsigned char is_idr;*/ unsigned short *p = (unsigned short *)hw->lmem_addr; reset_process_time(hw); @@ -3998,6 +5376,26 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } } #endif + data_low = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_LOW]; + data_hight = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_HIGHT]; + + video_signal = (data_hight << 16) | data_low; + hw->video_signal_from_vui = + ((video_signal & 0xffff) << 8) | + ((video_signal & 0xff0000) >> 16) | + ((video_signal & 0x3f000000)); + + + /*dpb_print(DECODE_ID(hw), + 0, + "video_signal_from_vui:0x%x, " + "data_low:0x%x, data_hight:0x%x\n", + hw->video_signal_from_vui, + data_low, + data_hight);*/ + + parse_sei_data(hw, hw->sei_data_buf, hw->sei_data_len); + if (hw->config_bufmgr_done == 0) { hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); @@ -4053,6 +5451,13 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) val(p_H264_Dpb->dpb_param.dpb.frame_pic_order_cnt), val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt), val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt)); + I_flag = (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice) + ? I_FLAG : 0; + if ((hw->i_only & 0x2) && (!(I_flag & I_FLAG)) && + (p_H264_Dpb->mSlice.structure == FRAME)) { + hw->data_flag = NULL_FLAG; + goto pic_done_proc; + } slice_header_process_status = h264_slice_header_process(p_H264_Dpb); @@ -4064,33 +5469,17 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) if (p_H264_Dpb->mVideo.dec_picture) { int cfg_ret = 0; - if (hw->sei_itu_data_len) { - hw->sei_poc = - p_H264_Dpb->mVideo.dec_picture->poc; - schedule_work(&hw->user_data_work); - } if (slice_header_process_status == 1) { - /* for baseline , set fast_output mode */ - if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) - || ((((unsigned long) - hw->vh264_amstream_dec_info.param) & 0x8) - && (!hw->i_only))) - p_H264_Dpb->fast_output_enable = 4; + if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || + (((unsigned long)(hw->vh264_amstream_dec_info + .param)) & 0x8)) { + p_H264_Dpb->fast_output_enable = + H264_OUTPUT_MODE_FAST; + } else p_H264_Dpb->fast_output_enable = fast_output_enable; - hw->data_flag = - (p_H264_Dpb-> - dpb_param.l.data[SLICE_TYPE] - == I_Slice) - ? I_FLAG : 0; - if ((hw->i_only & 0x2) && - (!(hw->data_flag & I_FLAG)) && - (p_H264_Dpb->mSlice.structure - == FRAME)) { - hw->data_flag = NULL_FLAG; - goto pic_done_proc; - } + hw->data_flag = I_flag; if ((p_H264_Dpb-> dpb_param.dpb.NAL_info_mmco & 0x1f) == 5) @@ -4126,6 +5515,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) p->data_flag |= MAYBE_ERROR_FLAG; } } + if (error_proc_policy & 0x400) { int ret = dpb_check_ref_list_error(p_H264_Dpb); if (ret != 0) { @@ -4134,6 +5524,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) ret, hw->decode_pic_count+1, hw->skip_frame_count); + flush_dpb(p_H264_Dpb); hw->data_flag |= ERROR_FLAG; p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; if ((error_proc_policy & 0x80) @@ -4193,7 +5584,23 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } else if (dec_dpb_status == H264_PIC_DATA_DONE) { pic_done_proc: reset_process_time(hw); + + if (input_frame_based(vdec) && + frmbase_cont_bitlevel != 0 && + READ_VREG(VIFF_BIT_CNT) > + frmbase_cont_bitlevel) { + /*handle the case: multi pictures in one packet*/ + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", + __func__, + hw->decode_pic_count, + READ_VREG(VIFF_BIT_CNT)); + hw->frmbase_cont_flag = 1; + } else + hw->frmbase_cont_flag = 0; + if (p_H264_Dpb->mVideo.dec_picture) { + get_picture_qos_info(p_H264_Dpb->mVideo.dec_picture); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION DEL_EXIST(hw, p_H264_Dpb->mVideo.dec_picture) = 0; @@ -4207,11 +5614,14 @@ pic_done_proc: = 1; } #endif + mutex_lock(&hw->chunks_mutex); if (hw->chunk) { p_H264_Dpb->mVideo.dec_picture->pts = hw->chunk->pts; p_H264_Dpb->mVideo.dec_picture->pts64 = hw->chunk->pts64; + p_H264_Dpb->mVideo.dec_picture->timestamp = + hw->chunk->timestamp; #ifdef MH264_USERDATA_ENABLE vmh264_udc_fill_vpts(hw, p_H264_Dpb->mSlice.slice_type, @@ -4233,7 +5643,8 @@ pic_done_proc: u32 offset = pic->offset_delimiter_lo | (pic->offset_delimiter_hi << 16); if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, - offset, &pic->pts, 0, &pic->pts64)) { + offset, &pic->pts, &pic->frame_size, + 0, &pic->pts64)) { pic->pts = 0; pic->pts64 = 0; #ifdef MH264_USERDATA_ENABLE @@ -4249,6 +5660,7 @@ pic_done_proc: #endif } } + mutex_unlock(&hw->chunks_mutex); check_decoded_pic_error(hw); #ifdef ERROR_HANDLE_TEST if ((hw->data_flag & ERROR_FLAG) @@ -4309,16 +5721,7 @@ pic_done_proc: } } } - if (input_frame_based(vdec) && - frmbase_cont_bitlevel != 0 && - READ_VREG(VIFF_BIT_CNT) > - frmbase_cont_bitlevel) { - /*handle the case: multi pictures in one packet*/ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", - __func__, - hw->decode_pic_count, - READ_VREG(VIFF_BIT_CNT)); + if (hw->frmbase_cont_flag) { /*do not DEC_RESULT_GET_DATA*/ hw->get_data_count = 0x7fffffff; WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); @@ -4357,6 +5760,8 @@ pic_done_proc: #endif if (!hw->wait_for_udr_send) { hw->dec_result = DEC_RESULT_DONE; + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s wait_for_udr_send\n", __func__); vdec_schedule_work(&hw->work); } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -4406,6 +5811,8 @@ pic_done_proc: hw->switch_dvlayer_flag = 0; hw->got_valid_nal = 1; #endif + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s H264_AUX_DATA_READY\n", __func__); hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); } else if (/*(dec_dpb_status == H264_DATA_REQUEST) ||*/ @@ -4414,8 +5821,8 @@ pic_done_proc: (dec_dpb_status == H264_DECODE_TIMEOUT)) { empty_proc: reset_process_time(hw); - - release_cur_decoding_buf(hw); + if (!hw->frmbase_cont_flag) + release_cur_decoding_buf(hw); if (input_frame_based(vdec) || (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x200)) { @@ -4446,8 +5853,8 @@ empty_proc: hw->decode_timeout_num++; else if (dec_dpb_status == H264_DECODE_BUFEMPTY) hw->decode_dataempty_num++; - - hw->data_flag |= ERROR_FLAG; + if (!hw->frmbase_cont_flag) + hw->data_flag |= ERROR_FLAG; vdec_schedule_work(&hw->work); } else { @@ -4466,6 +5873,7 @@ send_again: "%s H264_DATA_REQUEST (%d)\n", __func__, hw->get_data_count); hw->dec_result = DEC_RESULT_GET_DATA; + hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->get_data_start_time = jiffies; hw->get_data_count++; if (hw->get_data_count >= frame_max_data_packet) @@ -4483,47 +5891,72 @@ send_again: hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); return IRQ_HANDLED; - } - - if (READ_VREG(AV_SCRATCH_G) == 1) { - hw->sei_itu_data_len = + } else if (dec_dpb_status == H264_SEI_DATA_READY) { + int aux_data_len; + aux_data_len = (READ_VREG(H264_AUX_DATA_SIZE) >> 16) << 4; - if (hw->sei_itu_data_len > SEI_ITU_DATA_SIZE * 2) { + + if (aux_data_len > SEI_DATA_SIZE) { dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "itu data size more than 4K: %d, discarded it\n", + "sei data size more than 4K: %d, discarded it\n", hw->sei_itu_data_len); hw->sei_itu_data_len = 0; } - if (hw->sei_itu_data_len != 0) { + if (aux_data_len != 0) { u8 *trans_data_buf; u8 *sei_data_buf; - u32 temp; - u32 *pswap_data; + u8 swap_byte; dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); + amports_get_dma_device(), + hw->aux_phy_addr, + hw->prefix_aux_size + hw->suffix_aux_size, + DMA_FROM_DEVICE); #if 0 dump_aux_buf(hw); #endif - trans_data_buf = (u8 *)hw->aux_addr; - sei_data_buf = (u8 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len/2; i++) - sei_data_buf[i] = trans_data_buf[i*2]; - hw->sei_itu_data_len = hw->sei_itu_data_len / 2; - pswap_data = (u32 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len/4; i = i+2) { - temp = pswap_data[i]; - pswap_data[i] = pswap_data[i+1]; - pswap_data[i+1] = temp; + if (trans_data_buf[7] == AUX_TAG_SEI) { + int left_len; + + sei_data_buf = (u8 *)hw->sei_data_buf + + hw->sei_data_len; + left_len = SEI_DATA_SIZE - hw->sei_data_len; + if (aux_data_len/2 <= left_len) { + for (i = 0; i < aux_data_len/2; i++) + sei_data_buf[i] + = trans_data_buf[i*2]; + + aux_data_len = aux_data_len / 2; + for (i = 0; i < aux_data_len; i = i+4) { + swap_byte = sei_data_buf[i]; + sei_data_buf[i] + = sei_data_buf[i+3]; + sei_data_buf[i+3] = swap_byte; + + swap_byte = sei_data_buf[i+1]; + sei_data_buf[i+1] + = sei_data_buf[i+2]; + sei_data_buf[i+2] = swap_byte; + } + + for (i = aux_data_len-1; i >= 0; i--) + if (sei_data_buf[i] != 0) + break; + + hw->sei_data_len += i+1; + } else + dpb_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, + "sei data size %d and more than left space: %d, discarded it\n", + hw->sei_itu_data_len, + left_len); } } - WRITE_VREG(AV_SCRATCH_G, 0); + WRITE_VREG(DPB_STATUS_REG, H264_SEI_DATA_DONE); + return IRQ_HANDLED; } @@ -4600,11 +6033,9 @@ static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq) WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - if (!hw) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "decoder is not running\n"); + if (!hw) return IRQ_HANDLED; - } + if (hw->eos) return IRQ_HANDLED; @@ -4684,12 +6115,14 @@ static void vmh264_dump_state(struct vdec_s *vdec) dpb_print(DECODE_ID(hw), 0, "====== %s\n", __func__); dpb_print(DECODE_ID(hw), 0, - "width/height (%d/%d), reorder_pic_num %d dpb size(bufspec count) %d max_reference_size(collocate count) %d\n", + "width/height (%d/%d), reorder_pic_num %d dpb size(bufspec count) %d max_reference_size(collocate count) %d i_only %d send_err %d\n", hw->frame_width, hw->frame_height, hw->dpb.reorder_pic_num, hw->dpb.mDPB.size, - hw->max_reference_size + hw->max_reference_size, + hw->i_only, + hw->send_error_frame_flag ); dpb_print(DECODE_ID(hw), 0, @@ -4718,7 +6151,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) } dpb_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n", + "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x\n", __func__, kfifo_len(&hw->newframe_q), VF_POOL_SIZE, @@ -4730,7 +6163,8 @@ static void vmh264_dump_state(struct vdec_s *vdec) have_free_buf_spec(vdec), p_H264_Dpb->mDPB.init_done, p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, - is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) + is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB), + p_H264_Dpb->fast_output_enable ); dump_dpb(&p_H264_Dpb->mDPB, 1); @@ -4778,9 +6212,15 @@ static void vmh264_dump_state(struct vdec_s *vdec) int jj; if (hw->chunk && hw->chunk->block && hw->chunk->size > 0) { - u8 *data = - ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + dpb_print(DECODE_ID(hw), 0, "frame data size 0x%x\n", hw->chunk->size); @@ -4797,6 +6237,9 @@ static void vmh264_dump_state(struct vdec_s *vdec) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } } @@ -4891,7 +6334,12 @@ static void check_timer_func(unsigned long arg) static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + u32 ar; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + if (!hw) + return -1; + vstatus->frame_width = hw->frame_width; vstatus->frame_height = hw->frame_height; if (hw->frame_dur != 0) @@ -4900,6 +6348,12 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->frame_rate = -1; vstatus->error_count = 0; vstatus->status = hw->stat; + ar = min_t(u32, + hw->h264_ar, + DISP_RATIO_ASPECT_RATIO_MAX); + vstatus->ratio_control = + ar << DISP_RATIO_ASPECT_RATIO_BIT; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s-%02d", DRIVER_NAME, hw->id); @@ -4972,13 +6426,19 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); #endif + /* cbcr_merge_swap_en */ + if (hw->is_used_v4l) + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); if (hw->mmu_enable) { SET_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1<<31); - WRITE_VREG(MDEC_EXTIF_CFG1, 0x80000000); + /* sw reset to extif hardware */ + SET_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30); + CLEAR_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30); } else { CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31); WRITE_VREG(MDEC_EXTIF_CFG1, 0); @@ -4989,6 +6449,16 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) /* pr_info("vh264 meson8 prot init\n"); */ WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); #endif + +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + u32 data = ((1 << 30) |(1 << 0) |(1 << 8)); + + if (IS_VDEC_DW(hw) == 2) + data |= (1 << 9); + WRITE_VREG(MDEC_DOUBLEW_CFG0, data); /* Double Write Enable*/ + } +#endif if (hw->dpb.mDPB.size > 0) { WRITE_VREG(AV_SCRATCH_7, (hw->max_reference_size << 24) | (hw->dpb.mDPB.size << 16) | @@ -5068,6 +6538,7 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) { int i; hw->init_flag = 0; + hw->first_sc_checked= 0; hw->eos = 0; hw->valve_count = 0; hw->config_bufmgr_done = 0; @@ -5084,7 +6555,7 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->reg_rv_ai_mb_count = 0; hw->vld_dec_control = 0; hw->decode_timeout_count = 0; - + hw->no_mem_count = 0; hw->vh264_ratio = hw->vh264_amstream_dec_info.ratio; /* vh264_ratio = 0x100; */ @@ -5110,13 +6581,23 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->frame_dur = 96000/30; } - pr_info - ("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n", - hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); - pr_debug("sync_outside=%d, use_idr_framerate=%d\n", - hw->sync_outside, hw->use_idr_framerate); + hw->unstable_pts = (((unsigned long) hw->vh264_amstream_dec_info.param & 0x40) >> 6); + + hw->is_used_v4l = (((unsigned long) + hw->vh264_amstream_dec_info.param & 0x80) >> 7); + + if (hw->is_used_v4l) + mem_map_mode = CANVAS_BLKMODE_LINEAR; + + pr_info("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n", + hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); + pr_debug("sync_outside=%d, use_idr_framerate=%d, is_used_v4l: %d\n", + hw->sync_outside, hw->use_idr_framerate, hw->is_used_v4l); + if (i_only_flag & 0x100) hw->i_only = i_only_flag & 0xff; + if (hw->i_only) + hw->dpb.first_insert_frame = FirstInsertFrm_SKIPDONE; if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x08) @@ -5144,11 +6625,18 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->vh264_stream_switching_state = SWITCHING_STATE_OFF; hw->hevc_cur_buf_idx = 0xffff; + init_waitqueue_head(&hw->wait_q); + return; } static s32 vh264_init(struct vdec_h264_hw_s *hw) { + int size = -1; + int fw_size = 0x1000 * 16; + int fw_mmu_size = 0x1000 * 16; + struct firmware_s *fw = NULL, *fw_mmu = NULL; + /* int trickmode_fffb = 0; */ /* pr_info("\nvh264_init\n"); */ @@ -5165,10 +6653,10 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->stat |= STAT_TIMER_ARM; hw->stat |= STAT_ISR_REG; + mutex_init(&hw->chunks_mutex); vh264_local_init(hw); INIT_WORK(&hw->work, vh264_work); INIT_WORK(&hw->notify_work, vh264_notify_work); - INIT_WORK(&hw->user_data_work, user_data_push_work); #ifdef MH264_USERDATA_ENABLE INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work); #endif @@ -5190,11 +6678,38 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) return -ENOMEM; } } - if (!tee_enabled()) { - int ret = 0, size = -1; - int fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; + fw = vmalloc(sizeof(struct firmware_s) + fw_size); + if (IS_ERR_OR_NULL(fw)) + return -ENOMEM; + + size = get_firmware_data(VIDEO_DEC_H264_MULTI, fw->data); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(fw); + return -1; + } + + fw->len = size; + hw->fw = fw; + + if (hw->mmu_enable) { + fw_mmu = vmalloc(sizeof(struct firmware_s) + fw_mmu_size); + if (IS_ERR_OR_NULL(fw_mmu)) + return -ENOMEM; + + size = get_firmware_data(VIDEO_DEC_H264_MULTI_MMU, fw_mmu->data); + if (size < 0) { + pr_err("get mmu fw fail.\n"); + vfree(fw_mmu); + return -1; + } + + fw_mmu->len = size; + hw->fw_mmu = fw_mmu; + } + + if (!tee_enabled()) { /* -- ucode loading (amrisc and swap code) */ hw->mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, @@ -5212,23 +6727,6 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) (void *)hw->mc_dma_handle, hw->mc_cpu_addr); */ - - pr_debug("start load orignal firmware ...\n"); - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_H264_MULTI, fw->data); - if (size < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = size; - hw->fw = fw; - /*ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf);*/ /*header*/ @@ -5255,48 +6753,8 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) /*slice*/ memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x3000, fw->data + 0x5000, 0x1000); - - if (hw->mmu_enable) { - int fw_mmu_size = 0x1000 * 16; - struct firmware_s *fw_mmu = NULL; - - pr_debug("start load mmu fw ...\n"); - - fw_mmu = vmalloc(sizeof(struct firmware_s) + fw_mmu_size); - if (IS_ERR_OR_NULL(fw_mmu)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_H264_MULTI_MMU, - fw_mmu->data); - if (size < 0) { - pr_err("get mmu fw fail.\n"); - vfree(fw_mmu); - return -1; - } - - ret = amhevc_loadmc_ex(VFORMAT_HEVC, - NULL, fw_mmu->data); - - fw_mmu->len = size; - hw->fw_mmu = fw_mmu; - } - - if (ret < 0) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "264 load orignal firmware error.\n"); - amvdec_disable(); - if (hw->mmu_enable) - amhevc_disable(); - if (hw->mc_cpu_addr) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, hw->mc_cpu_addr, - hw->mc_dma_handle); - hw->mc_cpu_addr = NULL; - } - return -EBUSY; - } - } + #if 1 /* #ifdef BUFFER_MGR_IN_C */ hw->lmem_addr = __get_free_page(GFP_KERNEL); if (!hw->lmem_addr) { @@ -5342,10 +6800,21 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->aux_addr = NULL; return -1; } + hw->sei_data_buf = kmalloc(SEI_DATA_SIZE, GFP_KERNEL); + if (hw->sei_data_buf == NULL) { + pr_err("%s: failed to alloc sei itu data buffer\n", + __func__); + return -1; + } hw->sei_itu_data_buf = kmalloc(SEI_ITU_DATA_SIZE, GFP_KERNEL); if (hw->sei_itu_data_buf == NULL) { pr_err("%s: failed to alloc sei itu data buffer\n", __func__); + kfree(hw->aux_addr); + hw->aux_addr = NULL; + kfree(hw->sei_data_buf); + hw->sei_data_buf = NULL; + return -1; } @@ -5355,6 +6824,13 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) if (!hw->sei_user_data_buffer) { pr_info("%s: Can not allocate sei_data_buffer\n", __func__); + kfree(hw->aux_addr); + hw->aux_addr = NULL; + kfree(hw->sei_data_buf); + hw->sei_data_buf = NULL; + kfree(hw->sei_itu_data_buf); + hw->sei_itu_data_buf = NULL; + return -1; } hw->sei_user_data_wp = 0; @@ -5376,10 +6852,11 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) amvdec_stop(); hw->stat &= ~STAT_VDEC_RUN; } - +#ifdef VDEC_DW + WRITE_VREG(MDEC_DOUBLEW_CFG0, 0); +#endif cancel_work_sync(&hw->work); cancel_work_sync(&hw->notify_work); - cancel_work_sync(&hw->user_data_work); #ifdef MH264_USERDATA_ENABLE cancel_work_sync(&hw->user_data_ready_work); #endif @@ -5421,6 +6898,10 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) kfree(hw->aux_addr); hw->aux_addr = NULL; } + if (hw->sei_data_buf != NULL) { + kfree(hw->sei_data_buf); + hw->sei_data_buf = NULL; + } if (hw->sei_itu_data_buf != NULL) { kfree(hw->sei_itu_data_buf); hw->sei_itu_data_buf = NULL; @@ -5445,6 +6926,25 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) return 0; } +static void wait_vmh264_search_done(struct vdec_h264_hw_s *hw) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 2000) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, "%s timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); +} + static void vh264_notify_work(struct work_struct *work) { struct vdec_h264_hw_s *hw = container_of(work, @@ -5463,15 +6963,9 @@ static void vh264_notify_work(struct work_struct *work) #ifdef MH264_USERDATA_ENABLE static void vmh264_reset_udr_mgr(struct vdec_h264_hw_s *hw) { - int i; hw->wait_for_udr_send = 0; - - INIT_LIST_HEAD(&hw->free_uds_wait_nodes); - INIT_LIST_HEAD(&hw->frame_uds); - - for (i = 0; i < MAX_FREE_USERDATA_NODES; i++) - list_add_tail(&hw->free_nodes[i].list, - &hw->free_uds_wait_nodes); + hw->sei_itu_data_len = 0; + memset(&hw->ud_record, 0, sizeof(hw->ud_record)); } static void vmh264_crate_userdata_manager( @@ -5532,8 +7026,8 @@ static void print_data(unsigned char *pdata, rec_id, len, flag, duration, vpts, vpts_valid, poc_number); #endif - pr_info("%d len = %d, flag = %d, vpts = 0x%x, poc = %d\n", - rec_id, len, flag, vpts, poc); + pr_info("%d len = %d, flag = %d, vpts = 0x%x\n", + rec_id, len, flag, vpts); if (len == 96) { int i; @@ -5775,70 +7269,77 @@ static void vmh264_reset_user_data_buf(void) } #endif -static void vmh264_input_udc_waitqueue(struct vdec_h264_hw_s *hw, - struct userdata_meta_info_t meta_info, - int wp) -{ - struct mh264_ud_record_wait_node_t *node; - struct mh264_userdata_record_t *p_userdata_rec; - int data_length; - - node = list_entry( - hw->free_uds_wait_nodes.next, - struct mh264_ud_record_wait_node_t, - list); - - if (node) { - if (wp > hw->userdata_info.last_wp) - data_length = wp - hw->userdata_info.last_wp; - else - data_length = wp + hw->userdata_info.buf_len - - hw->userdata_info.last_wp; - - if (data_length & 0x7) - data_length = (((data_length + 8) >> 3) << 3); -#if 0 - pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", - lg_p_mpeg12_userdata_info->read_index, - lg_p_mpeg12_userdata_info->write_index, - data_length, - lg_p_mpeg12_userdata_info->last_wp, - wp, - n_userdata_id); -#endif - p_userdata_rec = &node->ud_record; - p_userdata_rec->meta_info = meta_info; - p_userdata_rec->rec_start = hw->userdata_info.last_wp; - p_userdata_rec->rec_len = data_length; -#if 0 - dump_userdata_record(hw, p_userdata_rec); -#endif - list_move(&node->list, &hw->frame_uds); - } - hw->userdata_info.last_wp = wp; -} static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw, int frame_type, u32 vpts, u32 vpts_valid) { - struct mh264_ud_record_wait_node_t *node; - struct mh264_ud_record_wait_node_t *tmp; - struct mh264_userdata_record_t *pud_record; struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - if (!list_empty(&hw->frame_uds)) { - list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) { - pud_record = &node->ud_record; - pud_record->meta_info.vpts = vpts; - pud_record->meta_info.vpts_valid = vpts_valid; - pud_record->meta_info.poc_number = - p_H264_Dpb->mVideo.dec_picture->poc; - } - hw->wait_for_udr_send = 1; - schedule_work(&hw->user_data_ready_work); + unsigned char *pdata; + u8 *pmax_sei_data_buffer; + u8 *sei_data_buf; + int i; + int wp; + int data_length; + struct mh264_userdata_record_t *p_userdata_rec; + + +#ifdef MH264_USERDATA_ENABLE + struct userdata_meta_info_t meta_info; + memset(&meta_info, 0, sizeof(meta_info)); +#endif + + if (hw->sei_itu_data_len <= 0) + return; + + pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp; + pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE; + sei_data_buf = (u8 *)hw->sei_itu_data_buf; + for (i = 0; i < hw->sei_itu_data_len; i++) { + *pdata++ = sei_data_buf[i]; + if (pdata >= pmax_sei_data_buffer) + pdata = (u8 *)hw->sei_user_data_buffer; } + + hw->sei_user_data_wp = (hw->sei_user_data_wp + + hw->sei_itu_data_len) % USER_DATA_SIZE; + hw->sei_itu_data_len = 0; + +#ifdef MH264_USERDATA_ENABLE + meta_info.duration = hw->frame_dur; + meta_info.flags |= (VFORMAT_H264 << 3); + + meta_info.vpts = vpts; + meta_info.vpts_valid = vpts_valid; + meta_info.poc_number = + p_H264_Dpb->mVideo.dec_picture->poc; + + + wp = hw->sei_user_data_wp; + + if (hw->sei_user_data_wp > hw->userdata_info.last_wp) + data_length = wp - hw->userdata_info.last_wp; + else + data_length = wp + hw->userdata_info.buf_len + - hw->userdata_info.last_wp; + + if (data_length & 0x7) + data_length = (((data_length + 8) >> 3) << 3); + + p_userdata_rec = &hw->ud_record; + p_userdata_rec->meta_info = meta_info; + p_userdata_rec->rec_start = hw->userdata_info.last_wp; + p_userdata_rec->rec_len = data_length; + hw->userdata_info.last_wp = wp; + + p_userdata_rec->meta_info.flags |= + p_H264_Dpb->mVideo.dec_picture->pic_struct << 12; + + hw->wait_for_udr_send = 1; + schedule_work(&hw->user_data_ready_work); +#endif } @@ -5847,30 +7348,30 @@ static void user_data_ready_notify_work(struct work_struct *work) struct vdec_h264_hw_s *hw = container_of(work, struct vdec_h264_hw_s, user_data_ready_work); - struct mh264_ud_record_wait_node_t *node; - struct mh264_ud_record_wait_node_t *tmp; - list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) { - mutex_lock(&hw->userdata_mutex); + mutex_lock(&hw->userdata_mutex); - hw->userdata_info.records[hw->userdata_info.write_index] - = node->ud_record; - hw->userdata_info.write_index++; - if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) - hw->userdata_info.write_index = 0; + hw->userdata_info.records[hw->userdata_info.write_index] + = hw->ud_record; + hw->userdata_info.write_index++; + if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) + hw->userdata_info.write_index = 0; - mutex_unlock(&hw->userdata_mutex); + mutex_unlock(&hw->userdata_mutex); - list_move(&node->list, &hw->free_uds_wait_nodes); #ifdef DUMP_USERDATA_RECORD - dump_userdata_record(hw, &node->ud_record); + dump_userdata_record(hw, &hw->ud_record); #endif - vdec_wakeup_userdata_poll(hw_to_vdec(hw)); - } + vdec_wakeup_userdata_poll(hw_to_vdec(hw)); hw->wait_for_udr_send = 0; - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); + if (!hw->frmbase_cont_flag) { + hw->dec_result = DEC_RESULT_DONE; + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s\n", __func__); + + vdec_schedule_work(&hw->work); + } } static int vmh264_user_data_read(struct vdec_s *vdec, @@ -5888,7 +7389,8 @@ static int vmh264_user_data_read(struct vdec_s *vdec, hw = (struct vdec_h264_hw_s *)vdec->private; - pdest_buf = (void *)(puserdata_para->pbuf_addr); + pdest_buf = puserdata_para->pbuf_addr; + mutex_lock(&hw->userdata_mutex); /* @@ -6039,9 +7541,7 @@ static int vmh264_user_data_read(struct vdec_s *vdec, } } - res = (u32)copy_to_user((void *)&puserdata_para->meta_info, - (void *)&p_userdata_rec->meta_info, - sizeof(p_userdata_rec->meta_info)); + puserdata_para->meta_info = p_userdata_rec->meta_info; if (hw->userdata_info.read_index <= hw->userdata_info.write_index) puserdata_para->meta_info.records_in_que = @@ -6068,7 +7568,7 @@ static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) if (hw) { mutex_lock(&hw->userdata_mutex); - pr_info("vmpeg12_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", bInit, hw->userdata_info.read_index, hw->userdata_info.write_index); @@ -6080,52 +7580,15 @@ static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) mutex_unlock(&hw->userdata_mutex); } } -#endif -static void user_data_push_work(struct work_struct *work) +static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec) { - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, user_data_work); - - struct userdata_poc_info_t user_data_poc; - unsigned char *pdata; - u8 *pmax_sei_data_buffer; - u8 *sei_data_buf; - int i; -#ifdef MH264_USERDATA_ENABLE - struct userdata_meta_info_t meta_info; - memset(&meta_info, 0, sizeof(meta_info)); -#endif - - pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp; - pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE; - sei_data_buf = (u8 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len; i++) { - *pdata++ = sei_data_buf[i]; - if (pdata >= pmax_sei_data_buffer) - pdata = (u8 *)hw->sei_user_data_buffer; - } - - hw->sei_user_data_wp = (hw->sei_user_data_wp - + hw->sei_itu_data_len) % USER_DATA_SIZE; - user_data_poc.poc_number = hw->sei_poc; - - hw->sei_itu_data_len = 0; - -#ifdef MH264_USERDATA_ENABLE - meta_info.duration = hw->frame_dur; - meta_info.flags |= (VFORMAT_H264 << 3); - - - vmh264_input_udc_waitqueue(hw, meta_info, hw->sei_user_data_wp); - -#endif -/* - pr_info("sei_itu35_wp = %d, poc = %d\n", - hw->sei_user_data_wp, hw->sei_poc); -*/ + amstream_wakeup_userdata_poll(vdec); } +#endif + + static void vh264_work(struct work_struct *work) { struct vdec_h264_hw_s *hw = container_of(work, @@ -6178,7 +7641,10 @@ static void vh264_work(struct work_struct *work) READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP), READ_VREG(VLD_MEM_VIFIFO_RP)); + mutex_lock(&hw->chunks_mutex); vdec_vframe_dirty(vdec, hw->chunk); + hw->chunk = NULL; + mutex_unlock(&hw->chunks_mutex); vdec_clean_input(vdec); } if ((hw->dec_result == DEC_RESULT_GET_DATA_RETRY) && @@ -6211,9 +7677,17 @@ static void vh264_work(struct work_struct *work) if (dpb_is_debug(DECODE_ID(hw), PRINT_FRAMEBASE_DATA)) { int jj; - u8 *data = - ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap( + hw->chunk->block->start + + hw->chunk->offset, r); + else + data = ((u8 *) + hw->chunk->block->start_virt) + + hw->chunk->offset; + for (jj = 0; jj < r; jj++) { if ((jj & 0xf) == 0) dpb_print(DECODE_ID(hw), @@ -6227,6 +7701,9 @@ static void vh264_work(struct work_struct *work) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } WRITE_VREG(POWER_CTL_VLD, READ_VREG(POWER_CTL_VLD) | @@ -6271,6 +7748,13 @@ result_done: } decode_frame_count[DECODE_ID(hw)]++; amvdec_stop(); + if (!vdec_is_support_4k()) { + if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) { + clk_adj_frame_count++; + if (clk_adj_frame_count == VDEC_CLOCK_ADJUST_FRAME) + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + } + } dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s dec_result %d %x %x %x\n", __func__, @@ -6278,7 +7762,10 @@ result_done: READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP), READ_VREG(VLD_MEM_VIFIFO_RP)); + mutex_lock(&hw->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + mutex_unlock(&hw->chunks_mutex); } else if (hw->dec_result == DEC_RESULT_AGAIN) { /* stream base: stream buf empty or timeout @@ -6300,7 +7787,13 @@ result_done: amhevc_stop(); hw->eos = 1; flush_dpb(p_H264_Dpb); + if (hw->is_used_v4l) + notify_v4l_eos(hw_to_vdec(hw)); + mutex_lock(&hw->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + mutex_unlock(&hw->chunks_mutex); + vdec_clean_input(vdec); } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s: force exit\n", @@ -6318,8 +7811,8 @@ result_done: del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; + wait_vmh264_search_done(hw); /* mark itself has all HW resource released and input released */ - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (hw->switch_dvlayer_flag) { @@ -6332,8 +7825,15 @@ result_done: #endif /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) { + if (hw->mmu_enable == 0) + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1); + else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + } else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + wake_up_interruptible(&hw->wait_q); if (hw->vdec_cb) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); } @@ -6343,7 +7843,17 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) bool ret = 0; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + int tvp = vdec_secure(hw_to_vdec(hw)) ? + CODEC_MM_FLAGS_TVP : 0; + if (!hw->first_sc_checked && hw->mmu_enable) { + int size = decoder_mmu_box_sc_check(hw->mmu_box, tvp); + hw->first_sc_checked =1; + dpb_print(DECODE_ID(hw), 0, + "vmh264 cached=%d need_size=%d speed= %d ms\n", + size, (hw->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - hw->sc_start_time) * 1000/HZ); + } if (vdec_stream_based(vdec) && (hw->init_flag == 0) && pre_decode_buf_level != 0) { @@ -6367,6 +7877,9 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (hw->eos) return 0; + if (hw->stat & DECODER_FATAL_ERROR_NO_MEM) + return 0; + if (disp_vframe_valve_level && kfifo_len(&hw->display_q) >= disp_vframe_valve_level) { @@ -6382,8 +7895,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) READ_PARSER_REG(PARSER_VIDEO_WP); if (parser_wr_ptr >= hw->pre_parser_wr_ptr && (parser_wr_ptr - hw->pre_parser_wr_ptr) < - again_threshold) + again_threshold) { + int r = vdec_sync_input(vdec); + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, + "%s buf lelvel:%x\n", __func__, r); return 0; + } } if (h264_debug_flag & 0x20000000) { @@ -6392,11 +7909,40 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) } else ret = is_buffer_available(vdec); +#ifdef CONSTRAIN_MAX_BUF_NUM + if (hw->dpb.mDPB.size > 0) { /*make sure initilized*/ + if (run_ready_max_vf_only_num > 0 && + get_vf_ref_only_buf_count(hw) >= + run_ready_max_vf_only_num + ) + ret = 0; + if (run_ready_display_q_num > 0 && + kfifo_len(&hw->display_q) >= + run_ready_display_q_num) + ret = 0; + /*avoid more buffers consumed when + switching resolution*/ + if (run_ready_max_buf_num == 0xff && + get_used_buf_count(hw) >= + hw->dpb.mDPB.size) + ret = 0; + else if (run_ready_max_buf_num && + get_used_buf_count(hw) >= + run_ready_max_buf_num) + ret = 0; + } +#endif if (ret) not_run_ready[DECODE_ID(hw)] = 0; else not_run_ready[DECODE_ID(hw)]++; - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + if (vdec->parallel_dec == 1) { + if (hw->mmu_enable == 0) + return ret ? (CORE_MASK_VDEC_1) : 0; + else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + } else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; } static unsigned char get_data_check_sum @@ -6404,10 +7950,20 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } @@ -6417,9 +7973,10 @@ static void run(struct vdec_s *vdec, unsigned long mask, struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - int size; + int size, ret = -1; run_count[DECODE_ID(hw)]++; + vdec_reset_core(vdec); if (hw->mmu_enable) hevc_reset_core(vdec); hw->vdec_cb_arg = arg; @@ -6478,9 +8035,16 @@ static void run(struct vdec_s *vdec, unsigned long mask, READ_VREG(VLD_MEM_VIFIFO_WP)); #endif - if (input_frame_based(vdec)) { - u8 *data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + if (input_frame_based(vdec) && !vdec_secure(vdec)) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS) ) { @@ -6496,9 +8060,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, PRINT_FRAMEBASE_DATA) ) { int jj; - u8 *data = - ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + for (jj = 0; jj < size; jj++) { if ((jj & 0xf) == 0) dpb_print(DECODE_ID(hw), @@ -6514,6 +8076,8 @@ static void run(struct vdec_s *vdec, unsigned long mask, } } + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } else dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s: %x %x %x %x %x size 0x%x\n", @@ -6526,42 +8090,46 @@ static void run(struct vdec_s *vdec, unsigned long mask, size); start_process_time(hw); - - if (tee_enabled()) { - if (tee_load_video_fw(VIDEO_DEC_H264_MULTI, 0) != 0) { - amvdec_enable_flag = false; - amvdec_disable(); - dpb_print(DECODE_ID(hw), 0, "%s: Error amvdec_vdec_loadmc fail\n", __func__); - return; - } - if (hw->mmu_enable) { - if (tee_load_video_fw(VIDEO_DEC_H264_MULTI_MMU, - OPTEE_VDEC_HEVC) < 0) { - amvdec_enable_flag = false; - amhevc_disable(); - dpb_print(DECODE_ID(hw), 0, "tee mmu fw load fail\n"); - return; - } - } - + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + WRITE_VREG(AV_SCRATCH_G, hw->reg_g_status); } else { - if (amvdec_vdec_loadmc_ex(vdec, NULL, hw->fw->data) < 0) { + + ret = amvdec_vdec_loadmc_ex(VFORMAT_H264, "mh264", vdec, hw->fw->data); + if (ret < 0) { amvdec_enable_flag = false; amvdec_disable(); - dpb_print(DECODE_ID(hw), 0, "%s: Error amvdec_vdec_loadmc fail\n", __func__); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "MH264 the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); return; } + vdec->mc_type = VFORMAT_H264; + hw->reg_g_status = READ_VREG(AV_SCRATCH_G); if (hw->mmu_enable) { - if (amhevc_loadmc_ex(VFORMAT_HEVC, - NULL, hw->fw_mmu->data) < 0) { + ret = amhevc_loadmc_ex(VFORMAT_H264, "mh264_mmu", + hw->fw_mmu->data); + if (ret < 0) { amvdec_enable_flag = false; amhevc_disable(); - dpb_print(DECODE_ID(hw), 0, "mmu fw load fail\n"); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "MH264_MMU the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); return; } + vdec->mc_type = ((1 << 16) | VFORMAT_H264); } + vdec->mc_loaded = 1; } - vmh264_reset_udr_mgr(hw); if (vh264_hw_ctx_restore(hw) < 0) { @@ -6569,7 +8137,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, return; } if (input_frame_based(vdec)) { - int decode_size = hw->chunk->size + + int decode_size = 0; + + decode_size = hw->chunk->size + (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1)); WRITE_VREG(H264_DECODE_INFO, (1<<13)); WRITE_VREG(H264_DECODE_SIZE, decode_size); @@ -6585,6 +8155,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, config_decode_mode(hw); vdec_enable_input(vdec); WRITE_VREG(NAL_SEARCH_CTL, 0); + hw->sei_data_len = 0; if (enable_itu_t35) WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x1); if (!hw->init_flag) { @@ -6599,13 +8170,20 @@ static void run(struct vdec_s *vdec, unsigned long mask, WRITE_VREG(AV_SCRATCH_K, udebug_flag); mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { + + if (hw->mmu_enable) + SET_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); + else + CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); + } amvdec_start(); if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) { WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0); amhevc_start(); if (hw->config_bufmgr_done) { hevc_mcr_sao_global_hw_init(hw, - hw->frame_width, hw->frame_height); + (hw->mb_width << 4), (hw->mb_height << 4)); hevc_mcr_config_canv2axitbl(hw, 1); } } @@ -6619,7 +8197,26 @@ static void run(struct vdec_s *vdec, unsigned long mask, static void reset(struct vdec_s *vdec) { - pr_info("ammvdec_h264: reset.\n"); + struct vdec_h264_hw_s *hw = + (struct vdec_h264_hw_s *)vdec->private; + + cancel_work_sync(&hw->work); + cancel_work_sync(&hw->notify_work); + if (hw->stat & STAT_VDEC_RUN) { + amhevc_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + hw->eos = 0; + hw->decode_pic_count = 0; + hw->dec_result = DEC_RESULT_NONE; + reset_process_time(hw); + h264_reset_bufmgr(vdec); + dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); } static void h264_reconfig(struct vdec_h264_hw_s *hw) @@ -6693,6 +8290,7 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw) static void h264_reset_bufmgr(struct vdec_s *vdec) { int i; + ulong timeout; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; #if 0 struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; @@ -6750,6 +8348,13 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) __func__, hw->decode_pic_count+1, hw->skip_frame_count); + timeout = jiffies + HZ; + while (kfifo_len(&hw->display_q) > 0) { + if (time_after(jiffies, timeout)) + break; + schedule(); + } + for (i = 0; i < VF_POOL_SIZE; i++) hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ @@ -6794,14 +8399,17 @@ int ammvdec_h264_mmu_init(struct vdec_h264_hw_s *hw) int ret = -1; int tvp_flag = vdec_secure(hw_to_vdec(hw)) ? CODEC_MM_FLAGS_TVP : 0; + int buf_size = 64; pr_debug("ammvdec_h264_mmu_init tvp = 0x%x mmu_enable %d\n", tvp_flag, hw->mmu_enable); + hw->need_cache_size = buf_size * SZ_1M; + hw->sc_start_time = get_jiffies_64(); if (hw->mmu_enable && !hw->mmu_box) { hw->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, hw->id, MMU_MAX_BUFFERS, - 64 * SZ_1M, + hw->need_cache_size, tvp_flag); if (!hw->mmu_box) { pr_err("h264 4k alloc mmu box failed!!\n"); @@ -6856,38 +8464,66 @@ static int ammvdec_h264_probe(struct platform_device *pdev) } hw->id = pdev->id; hw->platform_dev = pdev; + + /* the ctx from v4l2 driver. */ + hw->v4l2_ctx = pdata->private; + + hw->canvas_mode = pdata->canvas_mode; + platform_set_drvdata(pdev, pdata); hw->mmu_enable = 0; if (force_enable_mmu && pdata->sys_info && - (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) && + (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) && (pdata->sys_info->height * pdata->sys_info->width > 1920 * 1088)) hw->mmu_enable = 1; + + if (hw->mmu_enable && + (pdata->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO)) { + hw->mmu_enable = 0; + pr_info("ionvideo needs disable mmu, path= %d \n", + pdata->frame_base_video_path); + } + if (ammvdec_h264_mmu_init(hw)) { h264_free_hw_stru(&pdev->dev, (void *)hw); pr_info("\nammvdec_h264 mmu alloc failed!\n"); return -ENOMEM; } - if (hw->mmu_enable) { - if (pdata->config && pdata->config_len) { - /*use ptr config for doubel_write_mode, etc*/ - if (get_config_int(pdata->config, - "mh264_double_write_mode", &config_val) == 0) - hw->double_write_mode = config_val; - else - hw->double_write_mode = double_write_mode; - } else + if (pdata->config_len) { + /*use ptr config for doubel_write_mode, etc*/ + if (get_config_int(pdata->config, + "mh264_double_write_mode", &config_val) == 0) + hw->double_write_mode = config_val; + else hw->double_write_mode = double_write_mode; } else - hw->double_write_mode = 0; + hw->double_write_mode = double_write_mode; + + if (hw->mmu_enable) + hw->double_write_mode &= 0xffff; + + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + hw->buffer_spec[i].y_canvas_index = -1; + hw->buffer_spec[i].u_canvas_index = -1; + hw->buffer_spec[i].v_canvas_index = -1; +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + hw->buffer_spec[i].vdec_dw_y_canvas_index = -1; + hw->buffer_spec[i].vdec_dw_u_canvas_index = -1; + hw->buffer_spec[i].vdec_dw_v_canvas_index = -1; + } +#endif + } + } dpb_print(DECODE_ID(hw), 0, - "%s mmu_enable %d double_write_mode %d\n", + "%s mmu_enable %d double_write_mode 0x%x\n", __func__, hw->mmu_enable, hw->double_write_mode); pdata->private = hw; @@ -6901,15 +8537,19 @@ static int ammvdec_h264_probe(struct platform_device *pdev) pdata->dump_state = vmh264_dump_state; #ifdef MH264_USERDATA_ENABLE + pdata->wakeup_userdata_poll = vmh264_wakeup_userdata_poll; pdata->user_data_read = vmh264_user_data_read; pdata->reset_userdata_fifo = vmh264_reset_userdata_fifo; #else + pdata->wakeup_userdata_poll = NULL; pdata->user_data_read = NULL; pdata->reset_userdata_fifo = NULL; #endif - if (pdata->use_vfm_path) + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); + hw->frameinfo_enable = 1; + } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION else if (vdec_dual(pdata)) { if (dv_toggle_prov_name) /*debug purpose*/ @@ -6944,25 +8584,43 @@ static int ammvdec_h264_probe(struct platform_device *pdev) if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_DPB_IDX, V_BUF_ADDR_OFFSET, DRIVER_NAME, &hw->cma_alloc_addr) < 0) { h264_free_hw_stru(&pdev->dev, (void *)hw); + pdata->dec_status = NULL; return -ENOMEM; } hw->buf_offset = hw->cma_alloc_addr - DEF_BUF_START_ADDR + DCAC_READ_MARGIN; - if (hw->mmu_enable) + if (hw->mmu_enable) { + u32 extif_size = EXTIF_BUF_SIZE; + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) + extif_size <<= 1; if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_EXTIF_IDX, - EXTIF_BUF_SIZE, DRIVER_NAME, &hw->extif_addr) < 0) { + extif_size, DRIVER_NAME, &hw->extif_addr) < 0) { h264_free_hw_stru(&pdev->dev, (void *)hw); + pdata->dec_status = NULL; return -ENOMEM; } + } if (!vdec_secure(pdata)) { #if 1 /*init internal buf*/ tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr); - memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); - dma_sync_single_for_device(amports_get_dma_device(), - hw->cma_alloc_addr, - V_BUF_ADDR_OFFSET, DMA_TO_DEVICE); + if (tmpbuf) { + memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); + codec_mm_dma_flush(tmpbuf, + V_BUF_ADDR_OFFSET, + DMA_TO_DEVICE); + } else { + tmpbuf = codec_mm_vmap(hw->cma_alloc_addr, + V_BUF_ADDR_OFFSET); + if (tmpbuf) { + memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); + codec_mm_dma_flush(tmpbuf, + V_BUF_ADDR_OFFSET, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(tmpbuf); + } + } #else /*init sps/pps internal buf 64k*/ tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr @@ -6999,13 +8657,17 @@ static int ammvdec_h264_probe(struct platform_device *pdev) pr_debug("ammvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx\n", pdata->mem_start, hw->buf_offset, hw->cma_alloc_addr); - - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + if (vdec_is_support_4k() || + (clk_adj_frame_count > (VDEC_CLOCK_ADJUST_FRAME - 1))) + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + else + vdec_source_changed(VFORMAT_H264, 1920, 1080, 29); if (vh264_init(hw) < 0) { pr_info("\nammvdec_h264 init failed.\n"); ammvdec_h264_mmu_release(hw); h264_free_hw_stru(&pdev->dev, (void *)hw); + pdata->dec_status = NULL; return -ENODEV; } #ifdef MH264_USERDATA_ENABLE @@ -7015,9 +8677,16 @@ static int ammvdec_h264_probe(struct platform_device *pdev) #endif vdec_set_prepare_level(pdata, start_decode_buf_level); - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); + if (pdata->parallel_dec == 1) { + if (hw->mmu_enable == 0) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); + } + } else + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); atomic_set(&hw->vh264_active, 1); @@ -7031,6 +8700,18 @@ static int ammvdec_h264_remove(struct platform_device *pdev) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); int i; + struct vdec_s *vdec = hw_to_vdec(hw); + + if (vdec->next_status == VDEC_STATUS_DISCONNECTED + && (vdec->status == VDEC_STATUS_ACTIVE)) { + pr_info("%s force exit %d\n", __func__, __LINE__); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + wait_event_interruptible_timeout(hw->wait_q, + (vdec->status == VDEC_STATUS_CONNECTED), + msecs_to_jiffies(50)); /* wait for work done */ + } + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) release_aux_data(hw, i); @@ -7051,12 +8732,32 @@ static int ammvdec_h264_remove(struct platform_device *pdev) /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ atomic_set(&hw->vh264_active, 0); - - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) { + if (hw->mmu_enable == 0) + vdec_core_release(vdec, CORE_MASK_VDEC_1); + else + vdec_core_release(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | + CORE_MASK_COMBINE); + } else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); + if (vdec->parallel_dec == 1) { + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); + if (IS_VDEC_DW(hw)) { + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id); + } + } + } ammvdec_h264_mmu_release(hw); h264_free_hw_stru(&pdev->dev, (void *)hw); + clk_adj_frame_count = 0; + return 0; } @@ -7116,10 +8817,10 @@ static int __init ammvdec_h264_driver_init_module(void) } if (vdec_is_support_4k()) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) { ammvdec_h264_profile.profile = "4k, dwrite, compressed"; - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { ammvdec_h264_profile.profile = "4k"; } } @@ -7138,7 +8839,6 @@ static void __exit ammvdec_h264_driver_remove_module(void) } /****************************************/ - module_param(h264_debug_flag, uint, 0664); MODULE_PARM_DESC(h264_debug_flag, "\n ammvdec_h264 h264_debug_flag\n"); @@ -7176,6 +8876,17 @@ MODULE_PARM_DESC(reorder_dpb_size_margin_dv, module_param(reference_buf_margin, uint, 0664); MODULE_PARM_DESC(reference_buf_margin, "\n ammvdec_h264 reference_buf_margin\n"); +#ifdef CONSTRAIN_MAX_BUF_NUM +module_param(run_ready_max_vf_only_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); + +module_param(run_ready_display_q_num, uint, 0664); +MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); + +module_param(run_ready_max_buf_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); +#endif + module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); @@ -7245,7 +8956,7 @@ MODULE_PARM_DESC(frmbase_cont_bitlevel2, "\n amvdec_h264 frmbase_cont_bitlevel\n"); module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); +MODULE_PARM_DESC(udebug_flag, "\n amvdec_mh264 udebug_flag\n"); module_param(udebug_pause_pos, uint, 0664); MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); @@ -7274,6 +8985,8 @@ MODULE_PARM_DESC(force_enable_mmu, "\n force_enable_mmu\n"); module_param(again_threshold, uint, 0664); MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); +module_param(stream_mode_start_num, uint, 0664); +MODULE_PARM_DESC(stream_mode_start_num, "\n stream_mode_start_num\n"); /* module_param(trigger_task, uint, 0664); @@ -7299,6 +9012,8 @@ module_param_array(max_get_frame_interval, uint, module_param_array(step, uint, &max_decode_instance_num, 0664); +module_param_array(ref_frame_mark_flag, uint, &max_decode_instance_num, 0664); + module_param(disp_vframe_valve_level, uint, 0664); MODULE_PARM_DESC(disp_vframe_valve_level, "\n disp_vframe_valve_level\n"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c index e566b9949bde..f0d97b5c080e 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c @@ -45,6 +45,14 @@ #include "../utils/decoder_bmmu_box.h" #include "../utils/config_parser.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + +#define CONSTRAIN_MAX_BUF_NUM + +#define SWAP_HEVC_UCODE +#define DETREFILL_ENABLE + #define AGAIN_HAS_THRESHOLD /*#define TEST_NO_BUF*/ /*#define HEVC_PIC_STRUCT_SUPPORT*/ @@ -54,11 +62,17 @@ /* .buf_size = 0x100000*16, //4k2k , 0x100000 per buffer */ /* 4096x2304 , 0x120000 per buffer */ -#define MPRED_MV_BUF_SIZE 0x120000 +#define MPRED_8K_MV_BUF_SIZE (0x120000*4) +#define MPRED_4K_MV_BUF_SIZE (0x120000) +#define MPRED_MV_BUF_SIZE (0x40000) #define MMU_COMPRESS_HEADER_SIZE 0x48000 +#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) + #define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +#define MAX_FRAME_8K_NUM (0x1200*4) + +//#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) #define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7 #define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 @@ -70,7 +84,7 @@ #define HEVC_DBLK_CFGB 0x350b #define HEVCD_MPP_DECOMP_AXIURG_CTL 0x34c7 - +#define SWAP_HEVC_OFFSET (3 * 0x1000) #define MEM_NAME "codec_265" /* #include */ @@ -84,11 +98,6 @@ #define SEND_LMEM_WITH_RPM #define SUPPORT_10BIT /* #define ERROR_HANDLE_DEBUG */ -#if 0/*MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ -#undef SUPPORT_4K2K -#else -#define SUPPORT_4K2K -#endif #ifndef STAT_KTHREAD #define STAT_KTHREAD 0x40 @@ -112,8 +121,14 @@ #define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 #define DUR2PTS(x) ((x)*90/96) -#define MAX_SIZE (4096 + 2304) -#define OVER_SIZE(w, h) (MAX_SIZE < (w + h)) + +#define MAX_SIZE_8K (8192 * 4608) +#define MAX_SIZE_4K (4096 * 2304) + +#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) +#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) + +#define SEI_UserDataITU_T_T35 4 static struct semaphore h265_sema; @@ -228,6 +243,7 @@ static u32 force_fps; static u32 pts_unstable; #define H265_DEBUG_BUFMGR 0x01 #define H265_DEBUG_BUFMGR_MORE 0x02 +#define H265_DEBUG_DETAIL 0x04 #define H265_DEBUG_REG 0x08 #define H265_DEBUG_MAN_SEARCH_NAL 0x10 #define H265_DEBUG_MAN_SKIP_NAL 0x20 @@ -240,6 +256,7 @@ static u32 pts_unstable; #define H265_DEBUG_DUMP_PIC_LIST 0x1000 #define H265_DEBUG_PRINT_SEI 0x2000 #define H265_DEBUG_PIC_STRUCT 0x4000 +#define H265_DEBUG_HAS_AUX_IN_SLICE 0x8000 #define H265_DEBUG_DIS_LOC_ERROR_PROC 0x10000 #define H265_DEBUG_DIS_SYS_ERROR_PROC 0x20000 #define H265_NO_CHANG_DEBUG_FLAG_IN_CODE 0x40000 @@ -273,6 +290,10 @@ static u32 pts_unstable; #define MV_BUFFER_IDX(n) (BUF_POOL_SIZE + 1 + n) #endif +#define HEVC_MV_INFO 0x310d +#define HEVC_QP_INFO 0x3137 +#define HEVC_SKIP_INFO 0x3136 + const u32 h265_version = 201602101; static u32 debug_mask = 0xffffffff; static u32 log_mask; @@ -318,6 +339,15 @@ static uint slice_parse_begin; static u32 step; static bool is_reset; +#ifdef CONSTRAIN_MAX_BUF_NUM +static u32 run_ready_max_vf_only_num; +static u32 run_ready_display_q_num; + /*0: not check + 0xff: work_pic_num + */ +static u32 run_ready_max_buf_num = 0xff; +#endif + static u32 dynamic_buf_num_margin = 7; static u32 buf_alloc_width; static u32 buf_alloc_height; @@ -368,6 +398,8 @@ bit 0, fast output first I picture */ static u32 fast_output_enable = 1; +static u32 frmbase_cont_bitlevel = 0x60; + /* use_cma: 1, use both reserver memory and cma for buffers 2, only use cma for buffers @@ -429,6 +461,7 @@ static u32 mmu_enable_force; static u32 work_buf_size; static unsigned int force_disp_pic_index; static unsigned int disp_vframe_valve_level; +static int pre_decode_buf_level = 0x1000; #ifdef MULTI_INSTANCE_SUPPORT static unsigned int max_decode_instance_num @@ -440,6 +473,8 @@ static unsigned int max_get_frame_interval[MAX_DECODE_INSTANCE_NUM]; static unsigned int run_count[MAX_DECODE_INSTANCE_NUM]; static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; +static unsigned int ref_frame_mark_flag[MAX_DECODE_INSTANCE_NUM] = +{1, 1, 1, 1, 1, 1, 1, 1, 1}; #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC static unsigned char get_idx(struct hevc_state_s *hevc); @@ -449,6 +484,8 @@ static unsigned char get_idx(struct hevc_state_s *hevc); static u32 dv_toggle_prov_name; static u32 dv_debug; + +static u32 force_bypass_dvenl; #endif #endif @@ -603,6 +640,7 @@ enum NalUnitType { #define HEVC_SEI_DAT 0xc #define HEVC_SEI_DAT_DONE 0xd #define HEVC_NAL_DECODE_DONE 0xe +#define HEVC_OVER_DECODE 0xf #define HEVC_DATA_REQUEST 0x12 @@ -652,8 +690,8 @@ enum NalUnitType { #define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 #define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 #define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 -/*#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 -#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8*/ +#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 +#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 #define HEVC_sao_mem_unit HEVC_ASSIST_SCRATCH_9 #define HEVC_SAO_ABV HEVC_ASSIST_SCRATCH_A #define HEVC_sao_vb_size HEVC_ASSIST_SCRATCH_B @@ -802,6 +840,7 @@ union param_u { unsigned short aspect_ratio_idc; unsigned short sar_width; unsigned short sar_height; + unsigned short sps_max_dec_pic_buffering_minus1_0; } p; }; @@ -843,7 +882,7 @@ struct BuffInfo_s { struct buff_s rpm; struct buff_s lmem; }; -#define WORK_BUF_SPEC_NUM 2 +#define WORK_BUF_SPEC_NUM 3 static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { { /* 8M bytes */ @@ -1036,7 +1075,7 @@ static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { /* .buf_size = 0x100000*16, //4k2k , 0x100000 per buffer */ /* 4096x2304 , 0x120000 per buffer */ - .buf_size = MPRED_MV_BUF_SIZE * MAX_REF_PIC_NUM, + .buf_size = MPRED_4K_MV_BUF_SIZE * MAX_REF_PIC_NUM, }, #endif .rpm = { @@ -1045,6 +1084,78 @@ static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { .lmem = { .buf_size = 0x500 * 2, } + }, + + { + .max_width = 4096*2, + .max_height = 2048*2, + .ipp = { + // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k + .buf_size = 0x4000*2, + }, + .sao_abv = { + .buf_size = 0x30000*2, + }, + .sao_vb = { + .buf_size = 0x30000*2, + }, + .short_term_rps = { + // SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800) + .buf_size = 0x800, + }, + .vps = { + // VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .sps = { + // SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .pps = { + // PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes + .buf_size = 0x2000, + }, + .sao_up = { + // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes + .buf_size = 0x2800*2, + }, + .swap_buf = { + // 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid) + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) + .buf_size = 0x8000*2, + }, + .dblk_para = {.buf_size = 0x40000*2, }, // dblk parameter + .dblk_data = {.buf_size = 0x80000*2, }, // dblk data for left/top + .dblk_data2 = {.buf_size = 0x80000*2, }, // dblk data for adapter + .mmu_vbh = { + .buf_size = 0x5000*2, //2*16*2304/4, 4K + }, +#if 0 + .cm_header = { + .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * + MAX_REF_PIC_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) + }, +#endif + .mpred_above = { + .buf_size = 0x8000*2, + }, +#ifdef MV_USE_FIXED_BUF + .mpred_mv = { + .buf_size = MPRED_8K_MV_BUF_SIZE * MAX_REF_PIC_NUM, //4k2k , 0x120000 per buffer + }, +#endif + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x500 * 2, + }, } }; @@ -1252,6 +1363,24 @@ struct PIC_s { u32 sar_width; u32 sar_height; u32 double_write_mode; + u32 video_signal_type; + unsigned short conformance_window_flag; + unsigned short conf_win_left_offset; + unsigned short conf_win_right_offset; + unsigned short conf_win_top_offset; + unsigned short conf_win_bottom_offset; + unsigned short chroma_format_idc; + + /* picture qos infomation*/ + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; } /*PIC_t */; #define MAX_TILE_COL_NUM 10 @@ -1268,6 +1397,7 @@ struct tile_s { #define SEI_MASTER_DISPLAY_COLOR_MASK 0x00000001 #define SEI_CONTENT_LIGHT_LEVEL_MASK 0x00000002 +#define SEI_HDR10PLUS_MASK 0x00000004 #define VF_POOL_SIZE 32 @@ -1312,6 +1442,8 @@ struct hevc_state_s { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION unsigned char switch_dvlayer_flag; unsigned char no_switch_dvlayer_count; + unsigned char bypass_dvenl_enable; + unsigned char bypass_dvenl; #endif unsigned char start_parser_type; /*start_decoding_flag: @@ -1321,6 +1453,7 @@ struct hevc_state_s { unsigned char eos; int pic_decoded_lcu_idx; u8 over_decode; + u8 empty_flag; #endif struct vframe_s vframe_dummy; char *provider_name; @@ -1335,6 +1468,7 @@ struct hevc_state_s { struct BuffInfo_s work_space_buf_store; struct BuffInfo_s *work_space_buf; + u8 aux_data_dirty; u32 prefix_aux_size; u32 suffix_aux_size; void *aux_addr; @@ -1480,6 +1614,7 @@ struct hevc_state_s { u32 bit_depth_luma; u32 bit_depth_chroma; u32 video_signal_type; + u32 video_signal_type_debug; u32 saved_resolution; bool get_frame_dur; u32 error_watchdog_count; @@ -1492,6 +1627,7 @@ struct hevc_state_s { #endif struct dec_sysinfo vh265_amstream_dec_info; unsigned char init_flag; + unsigned char first_sc_checked; unsigned char uninit_list; u32 start_decoding_time; @@ -1528,6 +1664,7 @@ struct hevc_state_s { int double_write_mode; int dynamic_buf_num_margin; int start_action; + int save_buffer_mode; #endif u32 i_only; struct list_head log_list; @@ -1537,6 +1674,17 @@ struct hevc_state_s { u32 vf_pre_count; u32 vf_get_count; u32 vf_put_count; +#ifdef SWAP_HEVC_UCODE + dma_addr_t mc_dma_handle; + void *mc_cpu_addr; + int swap_size; + ulong swap_addr; +#endif +#ifdef DETREFILL_ENABLE + dma_addr_t detbuf_adr; + u16 *detbuf_adr_virt; + u8 delrefill_check; +#endif u8 head_error_flag; int valve_count; struct firmware_s *fw; @@ -1546,6 +1694,18 @@ struct hevc_state_s { u8 next_again_flag; u32 pre_parser_wr_ptr; #endif + u32 ratio_control; + u32 first_pic_flag; + u32 decode_size; + struct mutex chunks_mutex; + int need_cache_size; + u64 sc_start_time; + u32 skip_first_nal; + bool is_swap; + bool is_4k; + + int frameinfo_enable; + struct vframe_qos_s vframe_qos; } /*hevc_stru_t */; #ifdef AGAIN_HAS_THRESHOLD @@ -1555,6 +1715,29 @@ u32 again_threshold = 0x40; #define get_lmem_params(hevc, ladr) \ hevc->lmem_ptr[ladr - (ladr & 0x3) + 3 - (ladr & 0x3)] + +static int get_frame_mmu_map_size(void) +{ + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + return (MAX_FRAME_8K_NUM * 4); + + return (MAX_FRAME_4K_NUM * 4); +} + +static int is_oversize(int w, int h) +{ + int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? + MAX_SIZE_8K : MAX_SIZE_4K; + + if (w < 0 || h < 0) + return true; + + if (h != 0 && (w > max / h)) + return true; + + return false; +} + void check_head_error(struct hevc_state_s *hevc) { #define pcm_enabled_flag 0x040 @@ -1683,7 +1866,7 @@ static unsigned char is_skip_decoding(struct hevc_state_s *hevc, static int get_pic_poc(struct hevc_state_s *hevc, unsigned int idx) { - if (idx != 0xff && idx >= 0 + if (idx != 0xff && idx < MAX_REF_PIC_NUM && hevc->m_PIC[idx]) return hevc->m_PIC[idx]->POC; @@ -1711,7 +1894,7 @@ static int get_dynamic_buf_num_margin(struct hevc_state_s *hevc) static int get_double_write_mode(struct hevc_state_s *hevc) { u32 valid_dw_mode = get_valid_double_write_mode(hevc); - u32 dw; + u32 dw = hevc->double_write_mode; if (valid_dw_mode == 0x100) { int w = hevc->pic_w; int h = hevc->pic_h; @@ -1939,6 +2122,7 @@ static void hevc_init_stru(struct hevc_state_s *hevc, hevc->sei_present_flag = 0; hevc->valve_count = 0; + hevc->first_pic_flag = 0; #ifdef MULTI_INSTANCE_SUPPORT hevc->decoded_poc = INVALID_POC; hevc->start_process_time = 0; @@ -1953,6 +2137,10 @@ static void hevc_init_stru(struct hevc_state_s *hevc, hevc->rps_set_id = 0; backup_decode_state(hevc); #endif +#ifdef DETREFILL_ENABLE + hevc->detbuf_adr = 0; + hevc->detbuf_adr_virt = NULL; +#endif } static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic); @@ -1960,6 +2148,384 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, unsigned short bit_depth, unsigned int *mmu_index_adr); +#ifdef DETREFILL_ENABLE +#define DETREFILL_BUF_SIZE (4 * 0x4000) +#define HEVC_SAO_DBG_MODE0 0x361e +#define HEVC_SAO_DBG_MODE1 0x361f +#define HEVC_SAO_CTRL10 0x362e +#define HEVC_SAO_CTRL11 0x362f +static int init_detrefill_buf(struct hevc_state_s *hevc) +{ + if (hevc->detbuf_adr_virt) + return 0; + + hevc->detbuf_adr_virt = + (void *)dma_alloc_coherent(amports_get_dma_device(), + DETREFILL_BUF_SIZE, &hevc->detbuf_adr, + GFP_KERNEL); + + if (hevc->detbuf_adr_virt == NULL) { + pr_err("%s: failed to alloc ETREFILL_BUF\n", __func__); + return -1; + } + return 0; +} + +static void uninit_detrefill_buf(struct hevc_state_s *hevc) +{ + if (hevc->detbuf_adr_virt) { + dma_free_coherent(amports_get_dma_device(), + DETREFILL_BUF_SIZE, hevc->detbuf_adr_virt, + hevc->detbuf_adr); + + hevc->detbuf_adr_virt = NULL; + hevc->detbuf_adr = 0; + } +} + +/* + * convert uncompressed frame buffer data from/to ddr + */ +static void convUnc8x4blk(uint16_t* blk8x4Luma, + uint16_t* blk8x4Cb, uint16_t* blk8x4Cr, uint16_t* cmBodyBuf, int32_t direction) +{ + if (direction == 0) { + blk8x4Luma[3 + 0 * 8] = ((cmBodyBuf[0] >> 0)) & 0x3ff; + blk8x4Luma[3 + 1 * 8] = ((cmBodyBuf[1] << 6) + | (cmBodyBuf[0] >> 10)) & 0x3ff; + blk8x4Luma[3 + 2 * 8] = ((cmBodyBuf[1] >> 4)) & 0x3ff; + blk8x4Luma[3 + 3 * 8] = ((cmBodyBuf[2] << 2) + | (cmBodyBuf[1] >> 14)) & 0x3ff; + blk8x4Luma[7 + 0 * 8] = ((cmBodyBuf[3] << 8) + | (cmBodyBuf[2] >> 8)) & 0x3ff; + blk8x4Luma[7 + 1 * 8] = ((cmBodyBuf[3] >> 2)) & 0x3ff; + blk8x4Luma[7 + 2 * 8] = ((cmBodyBuf[4] << 4) + | (cmBodyBuf[3] >> 12)) & 0x3ff; + blk8x4Luma[7 + 3 * 8] = ((cmBodyBuf[4] >> 6)) & 0x3ff; + blk8x4Cb [0 + 0 * 4] = ((cmBodyBuf[5] >> 0)) & 0x3ff; + blk8x4Cr [0 + 0 * 4] = ((cmBodyBuf[6] << 6) + | (cmBodyBuf[5] >> 10)) & 0x3ff; + blk8x4Cb [0 + 1 * 4] = ((cmBodyBuf[6] >> 4)) & 0x3ff; + blk8x4Cr [0 + 1 * 4] = ((cmBodyBuf[7] << 2) + | (cmBodyBuf[6] >> 14)) & 0x3ff; + + blk8x4Luma[0 + 0 * 8] = ((cmBodyBuf[0 + 8] >> 0)) & 0x3ff; + blk8x4Luma[1 + 0 * 8] = ((cmBodyBuf[1 + 8] << 6) | + (cmBodyBuf[0 + 8] >> 10)) & 0x3ff; + blk8x4Luma[2 + 0 * 8] = ((cmBodyBuf[1 + 8] >> 4)) & 0x3ff; + blk8x4Luma[0 + 1 * 8] = ((cmBodyBuf[2 + 8] << 2) | + (cmBodyBuf[1 + 8] >> 14)) & 0x3ff; + blk8x4Luma[1 + 1 * 8] = ((cmBodyBuf[3 + 8] << 8) | + (cmBodyBuf[2 + 8] >> 8)) & 0x3ff; + blk8x4Luma[2 + 1 * 8] = ((cmBodyBuf[3 + 8] >> 2)) & 0x3ff; + blk8x4Luma[0 + 2 * 8] = ((cmBodyBuf[4 + 8] << 4) | + (cmBodyBuf[3 + 8] >> 12)) & 0x3ff; + blk8x4Luma[1 + 2 * 8] = ((cmBodyBuf[4 + 8] >> 6)) & 0x3ff; + blk8x4Luma[2 + 2 * 8] = ((cmBodyBuf[5 + 8] >> 0)) & 0x3ff; + blk8x4Luma[0 + 3 * 8] = ((cmBodyBuf[6 + 8] << 6) | + (cmBodyBuf[5 + 8] >> 10)) & 0x3ff; + blk8x4Luma[1 + 3 * 8] = ((cmBodyBuf[6 + 8] >> 4)) & 0x3ff; + blk8x4Luma[2 + 3 * 8] = ((cmBodyBuf[7 + 8] << 2) | + (cmBodyBuf[6 + 8] >> 14)) & 0x3ff; + + blk8x4Luma[4 + 0 * 8] = ((cmBodyBuf[0 + 16] >> 0)) & 0x3ff; + blk8x4Luma[5 + 0 * 8] = ((cmBodyBuf[1 + 16] << 6) | + (cmBodyBuf[0 + 16] >> 10)) & 0x3ff; + blk8x4Luma[6 + 0 * 8] = ((cmBodyBuf[1 + 16] >> 4)) & 0x3ff; + blk8x4Luma[4 + 1 * 8] = ((cmBodyBuf[2 + 16] << 2) | + (cmBodyBuf[1 + 16] >> 14)) & 0x3ff; + blk8x4Luma[5 + 1 * 8] = ((cmBodyBuf[3 + 16] << 8) | + (cmBodyBuf[2 + 16] >> 8)) & 0x3ff; + blk8x4Luma[6 + 1 * 8] = ((cmBodyBuf[3 + 16] >> 2)) & 0x3ff; + blk8x4Luma[4 + 2 * 8] = ((cmBodyBuf[4 + 16] << 4) | + (cmBodyBuf[3 + 16] >> 12)) & 0x3ff; + blk8x4Luma[5 + 2 * 8] = ((cmBodyBuf[4 + 16] >> 6)) & 0x3ff; + blk8x4Luma[6 + 2 * 8] = ((cmBodyBuf[5 + 16] >> 0)) & 0x3ff; + blk8x4Luma[4 + 3 * 8] = ((cmBodyBuf[6 + 16] << 6) | + (cmBodyBuf[5 + 16] >> 10)) & 0x3ff; + blk8x4Luma[5 + 3 * 8] = ((cmBodyBuf[6 + 16] >> 4)) & 0x3ff; + blk8x4Luma[6 + 3 * 8] = ((cmBodyBuf[7 + 16] << 2) | + (cmBodyBuf[6 + 16] >> 14)) & 0x3ff; + + blk8x4Cb[1 + 0 * 4] = ((cmBodyBuf[0 + 24] >> 0)) & 0x3ff; + blk8x4Cr[1 + 0 * 4] = ((cmBodyBuf[1 + 24] << 6) | + (cmBodyBuf[0 + 24] >> 10)) & 0x3ff; + blk8x4Cb[2 + 0 * 4] = ((cmBodyBuf[1 + 24] >> 4)) & 0x3ff; + blk8x4Cr[2 + 0 * 4] = ((cmBodyBuf[2 + 24] << 2) | + (cmBodyBuf[1 + 24] >> 14)) & 0x3ff; + blk8x4Cb[3 + 0 * 4] = ((cmBodyBuf[3 + 24] << 8) | + (cmBodyBuf[2 + 24] >> 8)) & 0x3ff; + blk8x4Cr[3 + 0 * 4] = ((cmBodyBuf[3 + 24] >> 2)) & 0x3ff; + blk8x4Cb[1 + 1 * 4] = ((cmBodyBuf[4 + 24] << 4) | + (cmBodyBuf[3 + 24] >> 12)) & 0x3ff; + blk8x4Cr[1 + 1 * 4] = ((cmBodyBuf[4 + 24] >> 6)) & 0x3ff; + blk8x4Cb[2 + 1 * 4] = ((cmBodyBuf[5 + 24] >> 0)) & 0x3ff; + blk8x4Cr[2 + 1 * 4] = ((cmBodyBuf[6 + 24] << 6) | + (cmBodyBuf[5 + 24] >> 10)) & 0x3ff; + blk8x4Cb[3 + 1 * 4] = ((cmBodyBuf[6 + 24] >> 4)) & 0x3ff; + blk8x4Cr[3 + 1 * 4] = ((cmBodyBuf[7 + 24] << 2) | + (cmBodyBuf[6 + 24] >> 14)) & 0x3ff; + } else { + cmBodyBuf[0 + 8 * 0] = (blk8x4Luma[3 + 1 * 8] << 10) | + blk8x4Luma[3 + 0 * 8]; + cmBodyBuf[1 + 8 * 0] = (blk8x4Luma[3 + 3 * 8] << 14) | + (blk8x4Luma[3 + 2 * 8] << 4) | (blk8x4Luma[3 + 1 * 8] >> 6); + cmBodyBuf[2 + 8 * 0] = (blk8x4Luma[7 + 0 * 8] << 8) | + (blk8x4Luma[3 + 3 * 8] >> 2); + cmBodyBuf[3 + 8 * 0] = (blk8x4Luma[7 + 2 * 8] << 12) | + (blk8x4Luma[7 + 1 * 8] << 2) | (blk8x4Luma[7 + 0 * 8] >>8); + cmBodyBuf[4 + 8 * 0] = (blk8x4Luma[7 + 3 * 8] << 6) | + (blk8x4Luma[7 + 2 * 8] >>4); + cmBodyBuf[5 + 8 * 0] = (blk8x4Cr[0 + 0 * 4] << 10) | + blk8x4Cb[0 + 0 * 4]; + cmBodyBuf[6 + 8 * 0] = (blk8x4Cr[0 + 1 * 4] << 14) | + (blk8x4Cb[0 + 1 * 4] << 4) | (blk8x4Cr[0 + 0 * 4] >> 6); + cmBodyBuf[7 + 8 * 0] = (0<< 8) | (blk8x4Cr[0 + 1 * 4] >> 2); + + cmBodyBuf[0 + 8 * 1] = (blk8x4Luma[1 + 0 * 8] << 10) | + blk8x4Luma[0 + 0 * 8]; + cmBodyBuf[1 + 8 * 1] = (blk8x4Luma[0 + 1 * 8] << 14) | + (blk8x4Luma[2 + 0 * 8] << 4) | (blk8x4Luma[1 + 0 * 8] >> 6); + cmBodyBuf[2 + 8 * 1] = (blk8x4Luma[1 + 1 * 8] << 8) | + (blk8x4Luma[0 + 1 * 8] >> 2); + cmBodyBuf[3 + 8 * 1] = (blk8x4Luma[0 + 2 * 8] << 12) | + (blk8x4Luma[2 + 1 * 8] << 2) | (blk8x4Luma[1 + 1 * 8] >>8); + cmBodyBuf[4 + 8 * 1] = (blk8x4Luma[1 + 2 * 8] << 6) | + (blk8x4Luma[0 + 2 * 8] >>4); + cmBodyBuf[5 + 8 * 1] = (blk8x4Luma[0 + 3 * 8] << 10) | + blk8x4Luma[2 + 2 * 8]; + cmBodyBuf[6 + 8 * 1] = (blk8x4Luma[2 + 3 * 8] << 14) | + (blk8x4Luma[1 + 3 * 8] << 4) | (blk8x4Luma[0 + 3 * 8] >> 6); + cmBodyBuf[7 + 8 * 1] = (0<< 8) | (blk8x4Luma[2 + 3 * 8] >> 2); + + cmBodyBuf[0 + 8 * 2] = (blk8x4Luma[5 + 0 * 8] << 10) | + blk8x4Luma[4 + 0 * 8]; + cmBodyBuf[1 + 8 * 2] = (blk8x4Luma[4 + 1 * 8] << 14) | + (blk8x4Luma[6 + 0 * 8] << 4) | (blk8x4Luma[5 + 0 * 8] >> 6); + cmBodyBuf[2 + 8 * 2] = (blk8x4Luma[5 + 1 * 8] << 8) | + (blk8x4Luma[4 + 1 * 8] >> 2); + cmBodyBuf[3 + 8 * 2] = (blk8x4Luma[4 + 2 * 8] << 12) | + (blk8x4Luma[6 + 1 * 8] << 2) | (blk8x4Luma[5 + 1 * 8] >>8); + cmBodyBuf[4 + 8 * 2] = (blk8x4Luma[5 + 2 * 8] << 6) | + (blk8x4Luma[4 + 2 * 8] >>4); + cmBodyBuf[5 + 8 * 2] = (blk8x4Luma[4 + 3 * 8] << 10) | + blk8x4Luma[6 + 2 * 8]; + cmBodyBuf[6 + 8 * 2] = (blk8x4Luma[6 + 3 * 8] << 14) | + (blk8x4Luma[5 + 3 * 8] << 4) | (blk8x4Luma[4 + 3 * 8] >> 6); + cmBodyBuf[7 + 8 * 2] = (0<< 8) | (blk8x4Luma[6 + 3 * 8] >> 2); + + cmBodyBuf[0 + 8 * 3] = (blk8x4Cr[1 + 0 * 4] << 10) | + blk8x4Cb[1 + 0 * 4]; + cmBodyBuf[1 + 8 * 3] = (blk8x4Cr[2 + 0 * 4] << 14) | + (blk8x4Cb[2 + 0 * 4] << 4) | (blk8x4Cr[1 + 0 * 4] >> 6); + cmBodyBuf[2 + 8 * 3] = (blk8x4Cb[3 + 0 * 4] << 8) | + (blk8x4Cr[2 + 0 * 4] >> 2); + cmBodyBuf[3 + 8 * 3] = (blk8x4Cb[1 + 1 * 4] << 12) | + (blk8x4Cr[3 + 0 * 4] << 2) | (blk8x4Cb[3 + 0 * 4] >>8); + cmBodyBuf[4 + 8 * 3] = (blk8x4Cr[1 + 1 * 4] << 6) | + (blk8x4Cb[1 + 1 * 4] >>4); + cmBodyBuf[5 + 8 * 3] = (blk8x4Cr[2 + 1 * 4] << 10) | + blk8x4Cb[2 + 1 * 4]; + cmBodyBuf[6 + 8 * 3] = (blk8x4Cr[3 + 1 * 4] << 14) | + (blk8x4Cb[3 + 1 * 4] << 4) | (blk8x4Cr[2 + 1 * 4] >> 6); + cmBodyBuf[7 + 8 * 3] = (0 << 8) | (blk8x4Cr[3 + 1 * 4] >> 2); + } +} + +static void corrRefillWithAmrisc ( + struct hevc_state_s *hevc, + uint32_t cmHeaderBaseAddr, + uint32_t picWidth, + uint32_t ctuPosition) +{ + int32_t i; + uint16_t ctux = (ctuPosition>>16) & 0xffff; + uint16_t ctuy = (ctuPosition>> 0) & 0xffff; + int32_t aboveCtuAvailable = (ctuy) ? 1 : 0; + + uint16_t cmBodyBuf[32 * 18]; + + uint32_t pic_width_x64_pre = picWidth + 0x3f; + uint32_t pic_width_x64 = pic_width_x64_pre >> 6; + uint32_t stride64x64 = pic_width_x64 * 128; + uint32_t addr_offset64x64_abv = stride64x64 * + (aboveCtuAvailable ? ctuy - 1 : ctuy) + 128 * ctux; + uint32_t addr_offset64x64_cur = stride64x64*ctuy + 128 * ctux; + uint32_t cmHeaderAddrAbv = cmHeaderBaseAddr + addr_offset64x64_abv; + uint32_t cmHeaderAddrCur = cmHeaderBaseAddr + addr_offset64x64_cur; + unsigned int tmpData32; + + uint16_t blkBuf0Y[32]; + uint16_t blkBuf0Cb[8]; + uint16_t blkBuf0Cr[8]; + uint16_t blkBuf1Y[32]; + uint16_t blkBuf1Cb[8]; + uint16_t blkBuf1Cr[8]; + int32_t blkBufCnt = 0; + + int32_t blkIdx; + + WRITE_VREG(HEVC_SAO_CTRL10, cmHeaderAddrAbv); + WRITE_VREG(HEVC_SAO_CTRL11, cmHeaderAddrCur); + WRITE_VREG(HEVC_SAO_DBG_MODE0, hevc->detbuf_adr); + WRITE_VREG(HEVC_SAO_DBG_MODE1, 2); + + for (i = 0; i < 32 * 18; i++) + cmBodyBuf[i] = 0; + + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); + do { + tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1); + } while (tmpData32); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); + + hevc_print(hevc, H265_DEBUG_DETAIL, + "cmBodyBuf from detbuf:\n"); + for (i = 0; i < 32 * 18; i++) { + cmBodyBuf[i] = hevc->detbuf_adr_virt[i]; + if (get_dbg_flag(hevc) & + H265_DEBUG_DETAIL) { + if ((i & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]); + } + } + hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n"); + + for (i = 0; i < 32; i++) + blkBuf0Y[i] = 0; + for (i = 0; i < 8; i++) + blkBuf0Cb[i] = 0; + for (i = 0; i < 8; i++) + blkBuf0Cr[i] = 0; + for (i = 0; i < 32; i++) + blkBuf1Y[i] = 0; + for (i = 0; i < 8; i++) + blkBuf1Cb[i] = 0; + for (i = 0; i < 8; i++) + blkBuf1Cr[i] = 0; + + for (blkIdx = 0; blkIdx < 18; blkIdx++) { + int32_t inAboveCtu = (blkIdx<2) ? 1 : 0; + int32_t restoreEnable = (blkIdx>0) ? 1 : 0; + uint16_t* blkY = (blkBufCnt==0) ? blkBuf0Y : blkBuf1Y ; + uint16_t* blkCb = (blkBufCnt==0) ? blkBuf0Cb : blkBuf1Cb; + uint16_t* blkCr = (blkBufCnt==0) ? blkBuf0Cr : blkBuf1Cr; + uint16_t* cmBodyBufNow = cmBodyBuf + (blkIdx * 32); + + if (!aboveCtuAvailable && inAboveCtu) + continue; + + /* detRefillBuf --> 8x4block*/ + convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 0); + + if (restoreEnable) { + blkY[3 + 0 * 8] = blkY[2 + 0 * 8] + 2; + blkY[4 + 0 * 8] = blkY[1 + 0 * 8] + 3; + blkY[5 + 0 * 8] = blkY[0 + 0 * 8] + 1; + blkY[6 + 0 * 8] = blkY[0 + 0 * 8] + 2; + blkY[7 + 0 * 8] = blkY[1 + 0 * 8] + 2; + blkY[3 + 1 * 8] = blkY[2 + 1 * 8] + 1; + blkY[4 + 1 * 8] = blkY[1 + 1 * 8] + 2; + blkY[5 + 1 * 8] = blkY[0 + 1 * 8] + 2; + blkY[6 + 1 * 8] = blkY[0 + 1 * 8] + 2; + blkY[7 + 1 * 8] = blkY[1 + 1 * 8] + 3; + blkY[3 + 2 * 8] = blkY[2 + 2 * 8] + 3; + blkY[4 + 2 * 8] = blkY[1 + 2 * 8] + 1; + blkY[5 + 2 * 8] = blkY[0 + 2 * 8] + 3; + blkY[6 + 2 * 8] = blkY[0 + 2 * 8] + 3; + blkY[7 + 2 * 8] = blkY[1 + 2 * 8] + 3; + blkY[3 + 3 * 8] = blkY[2 + 3 * 8] + 0; + blkY[4 + 3 * 8] = blkY[1 + 3 * 8] + 0; + blkY[5 + 3 * 8] = blkY[0 + 3 * 8] + 1; + blkY[6 + 3 * 8] = blkY[0 + 3 * 8] + 2; + blkY[7 + 3 * 8] = blkY[1 + 3 * 8] + 1; + blkCb[1 + 0 * 4] = blkCb[0 + 0 * 4]; + blkCb[2 + 0 * 4] = blkCb[0 + 0 * 4]; + blkCb[3 + 0 * 4] = blkCb[0 + 0 * 4]; + blkCb[1 + 1 * 4] = blkCb[0 + 1 * 4]; + blkCb[2 + 1 * 4] = blkCb[0 + 1 * 4]; + blkCb[3 + 1 * 4] = blkCb[0 + 1 * 4]; + blkCr[1 + 0 * 4] = blkCr[0 + 0 * 4]; + blkCr[2 + 0 * 4] = blkCr[0 + 0 * 4]; + blkCr[3 + 0 * 4] = blkCr[0 + 0 * 4]; + blkCr[1 + 1 * 4] = blkCr[0 + 1 * 4]; + blkCr[2 + 1 * 4] = blkCr[0 + 1 * 4]; + blkCr[3 + 1 * 4] = blkCr[0 + 1 * 4]; + + /*Store data back to DDR*/ + convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 1); + } + + blkBufCnt = (blkBufCnt==1) ? 0 : blkBufCnt + 1; + } + + hevc_print(hevc, H265_DEBUG_DETAIL, + "cmBodyBuf to detbuf:\n"); + for (i = 0; i < 32 * 18; i++) { + hevc->detbuf_adr_virt[i] = cmBodyBuf[i]; + if (get_dbg_flag(hevc) & + H265_DEBUG_DETAIL) { + if ((i & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]); + } + } + hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n"); + + WRITE_VREG(HEVC_SAO_DBG_MODE1, 3); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); + do { + tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1); + } while (tmpData32); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); +} + +static void delrefill(struct hevc_state_s *hevc) +{ + /* + * corrRefill + */ + /*HEVC_SAO_DBG_MODE0: picGlobalVariable + [31:30]error number + [29:20]error2([9:7]tilex[6:0]ctuy) + [19:10]error1 [9:0]error0*/ + uint32_t detResult = READ_VREG(HEVC_ASSIST_SCRATCH_3); + uint32_t errorIdx; + uint32_t errorNum = (detResult>>30); + + if (detResult) { + hevc_print(hevc, H265_DEBUG_BUFMGR, + "[corrRefillWithAmrisc] detResult=%08x\n", detResult); + for (errorIdx = 0; errorIdx < errorNum; errorIdx++) { + uint32_t errorPos = errorIdx * 10; + uint32_t errorResult = (detResult >> errorPos) & 0x3ff; + uint32_t tilex = (errorResult >> 7) - 1; + uint16_t ctux = hevc->m_tile[0][tilex].start_cu_x + + hevc->m_tile[0][tilex].width - 1; + uint16_t ctuy = (uint16_t)(errorResult & 0x7f); + uint32_t ctuPosition = (ctux<< 16) + ctuy; + hevc_print(hevc, H265_DEBUG_BUFMGR, + "Idx:%d tilex:%d ctu(%d(0x%x), %d(0x%x))\n", + errorIdx,tilex,ctux,ctux, ctuy,ctuy); + corrRefillWithAmrisc( + hevc, + (uint32_t)hevc->cur_pic->header_adr, + hevc->pic_w, + ctuPosition); + } + + WRITE_VREG(HEVC_ASSIST_SCRATCH_3, 0); /*clear status*/ + WRITE_VREG(HEVC_SAO_DBG_MODE0, 0); + WRITE_VREG(HEVC_SAO_DBG_MODE1, 1); + } +} +#endif + static void get_rpm_param(union param_u *params) { int i; @@ -2044,10 +2610,8 @@ static unsigned int log2i(unsigned int val) } static int init_buf_spec(struct hevc_state_s *hevc); - static void uninit_mmu_buffers(struct hevc_state_s *hevc) { - if (hevc->mmu_box) decoder_mmu_box_free(hevc->mmu_box); hevc->mmu_box = NULL; @@ -2069,8 +2633,10 @@ static int init_mmu_buffers(struct hevc_state_s *hevc) hevc_print(hevc, 0, "%s max_w %d max_h %d\n", __func__, hevc->max_pic_w, hevc->max_pic_h); } - - if (hevc->mmu_enable) { + hevc->need_cache_size = buf_size * SZ_1M; + hevc->sc_start_time = get_jiffies_64(); + if (hevc->mmu_enable + && ((get_double_write_mode(hevc) & 0x10) == 0)) { hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, hevc->index, MAX_REF_PIC_NUM, @@ -2082,6 +2648,7 @@ static int init_mmu_buffers(struct hevc_state_s *hevc) return -1; } } + hevc->bmmu_box = decoder_bmmu_box_alloc_box(DRIVER_NAME, hevc->index, BMMU_MAX_BUFFERS, @@ -2164,19 +2731,28 @@ static int alloc_mv_buf(struct hevc_state_s *hevc, int i) static int get_mv_buf(struct hevc_state_s *hevc, struct PIC_s *pic) { #ifdef MV_USE_FIXED_BUF - if (pic && pic->index >= 0) - pic->mpred_mv_wr_start_addr = - hevc->work_space_buf->mpred_mv.buf_start - + (pic->index * MPRED_MV_BUF_SIZE); + if (pic && pic->index >= 0) { + if (IS_8K_SIZE(pic->width, pic->height)) { + pic->mpred_mv_wr_start_addr = + hevc->work_space_buf->mpred_mv.buf_start + + (pic->index * MPRED_8K_MV_BUF_SIZE); + } else { + pic->mpred_mv_wr_start_addr = + hevc->work_space_buf->mpred_mv.buf_start + + (pic->index * MPRED_4K_MV_BUF_SIZE); + } + } return 0; #else int i; int ret = -1; int new_size; - if (pic->width > 1920 || pic->height > 1088) - new_size = MPRED_MV_BUF_SIZE + 0x10000; /*0x120000*/ + if (IS_8K_SIZE(pic->width, pic->height)) + new_size = MPRED_8K_MV_BUF_SIZE + 0x10000; + else if (IS_4K_SIZE(pic->width, pic->height)) + new_size = MPRED_4K_MV_BUF_SIZE + 0x10000; /*0x120000*/ else - new_size = 0x40000 + 0x10000; + new_size = MPRED_MV_BUF_SIZE + 0x10000; if (new_size != hevc->mv_buf_size) { dealloc_mv_bufs(hevc); hevc->mv_buf_size = new_size; @@ -2270,11 +2846,15 @@ static int cal_current_buf_size(struct hevc_state_s *hevc, int dw_mode = get_double_write_mode(hevc); - if (hevc->mmu_enable) - buf_size = - ((MMU_COMPRESS_HEADER_SIZE + 0xffff) >> 16) - << 16; - else + if (hevc->mmu_enable) { + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) + buf_size = ((MMU_COMPRESS_8K_HEADER_SIZE + 0xffff) >> 16) + << 16; + else + buf_size = ((MMU_COMPRESS_HEADER_SIZE + 0xffff) >> 16) + << 16; + } else buf_size = 0; if (dw_mode) { @@ -2426,9 +3006,22 @@ static void dealloc_pic_buf(struct hevc_state_s *hevc, static int get_work_pic_num(struct hevc_state_s *hevc) { int used_buf_num = 0; + int sps_pic_buf_diff = 0; + if (get_dynamic_buf_num_margin(hevc) > 0) { - used_buf_num = hevc->sps_num_reorder_pics_0 - + get_dynamic_buf_num_margin(hevc); + if ((!hevc->sps_num_reorder_pics_0) && + (hevc->param.p.sps_max_dec_pic_buffering_minus1_0)) { + /* the range of sps_num_reorder_pics_0 is in + [0, sps_max_dec_pic_buffering_minus1_0] */ + used_buf_num = get_dynamic_buf_num_margin(hevc) + + hevc->param.p.sps_max_dec_pic_buffering_minus1_0; + } else + used_buf_num = hevc->sps_num_reorder_pics_0 + + get_dynamic_buf_num_margin(hevc); + + sps_pic_buf_diff = hevc->param.p.sps_max_dec_pic_buffering_minus1_0 + - hevc->sps_num_reorder_pics_0; + #ifdef MULTI_INSTANCE_SUPPORT /* need one more for multi instance, as @@ -2441,6 +3034,16 @@ static int get_work_pic_num(struct hevc_state_s *hevc) } else used_buf_num = max_buf_num; + if (hevc->save_buffer_mode) + hevc_print(hevc, 0, + "save buf _mode : dynamic_buf_num_margin %d ----> %d \n", + dynamic_buf_num_margin, hevc->dynamic_buf_num_margin); + + if (sps_pic_buf_diff >= 4) + { + used_buf_num += 1; + } + if (used_buf_num > MAX_BUF_NUM) used_buf_num = MAX_BUF_NUM; return used_buf_num; @@ -2488,7 +3091,13 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) if (hevc->mmu_enable) { pic->header_adr = hevc->m_BUF[i].start_adr; - y_adr = hevc->m_BUF[i].start_adr + MMU_COMPRESS_HEADER_SIZE; + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) + y_adr = hevc->m_BUF[i].start_adr + + MMU_COMPRESS_8K_HEADER_SIZE; + else + y_adr = hevc->m_BUF[i].start_adr + + MMU_COMPRESS_HEADER_SIZE; } else y_adr = hevc->m_BUF[i].start_adr; @@ -2546,7 +3155,7 @@ static void init_pic_list(struct hevc_state_s *hevc) int i; int init_buf_num = get_work_pic_num(hevc); int dw_mode = get_double_write_mode(hevc); - + struct vdec_s *vdec = hw_to_vdec(hevc); /*alloc decoder buf*/ for (i = 0; i < init_buf_num; i++) { if (alloc_buf(hevc) < 0) { @@ -2574,6 +3183,10 @@ static void init_pic_list(struct hevc_state_s *hevc) pic->index = i; pic->BUF_index = -1; pic->mv_buf_index = -1; + if (vdec->parallel_dec == 1) { + pic->y_canvas_index = -1; + pic->uv_canvas_index = -1; + } if (config_pic(hevc, pic) < 0) { if (get_dbg_flag(hevc)) hevc_print(hevc, 0, @@ -2602,12 +3215,17 @@ static void init_pic_list(struct hevc_state_s *hevc) hevc->m_PIC[i] = pic; pic->index = -1; pic->BUF_index = -1; + if (vdec->parallel_dec == 1) { + pic->y_canvas_index = -1; + pic->uv_canvas_index = -1; + } } } static void uninit_pic_list(struct hevc_state_s *hevc) { + struct vdec_s *vdec = hw_to_vdec(hevc); int i; #ifndef MV_USE_FIXED_BUF dealloc_mv_bufs(hevc); @@ -2616,6 +3234,10 @@ static void uninit_pic_list(struct hevc_state_s *hevc) struct PIC_s *pic = hevc->m_PIC[i]; if (pic) { + if (vdec->parallel_dec == 1) { + vdec->free_canvas_ex(pic->y_canvas_index, vdec->id); + vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id); + } release_aux_data(hevc, pic); vfree(pic); hevc->m_PIC[i] = NULL; @@ -2689,7 +3311,7 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) int i; int cur_pic_num = MAX_REF_PIC_NUM; int dw_mode = get_double_write_mode(hevc); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); else @@ -2701,8 +3323,8 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) cur_pic_num = i; break; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { + if (hevc->mmu_enable && ((dw_mode & 0x10) == 0)) WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, hevc->m_PIC[i]->header_adr>>5); else @@ -2713,11 +3335,7 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) hevc->m_PIC[i]->mc_y_adr | (hevc->m_PIC[i]->mc_canvas_y << 8) | 0x1); if (dw_mode & 0x10) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable) - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[i]->header_adr>>5); - else + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, hevc->m_PIC[i]->mc_u_v_adr >> 5); } @@ -2731,8 +3349,8 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) if (cur_pic_num == 0) return; for (; i < MAX_REF_PIC_NUM; i++) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { + if (hevc->mmu_enable && ((dw_mode & 0x10) == 0)) WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, hevc->m_PIC[cur_pic_num-1]->header_adr>>5); else @@ -2818,6 +3436,18 @@ static void clear_referenced_flag(struct hevc_state_s *hevc) } } +static void clear_poc_flag(struct hevc_state_s *hevc) +{ + int i; + struct PIC_s *pic; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + pic->POC = INVALID_POC; + } +} + static struct PIC_s *output_pic(struct hevc_state_s *hevc, unsigned char flush_flag) { @@ -2911,6 +3541,10 @@ static struct PIC_s *output_pic(struct hevc_state_s *hevc, pic_display = NULL; } } + if (pic_display && (hevc->vf_pre_count == 1) && (hevc->first_pic_flag == 1)) { + pic_display = NULL; + hevc->first_pic_flag = 0; + } return pic_display; } @@ -2940,7 +3574,7 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) pic->width, pic->height); cur_pic->error_mark = 1; } - if (pic->error_mark) + if (pic->error_mark && (ref_frame_mark_flag[hevc->index])) cur_pic->error_mark = 1; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, (pic->mc_canvas_u_v << 16) @@ -2975,6 +3609,7 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) "config_mc_buffer RefNum_L1\n"); WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (16 << 8) | (0 << 1) | 1); + for (i = 0; i < cur_pic->RefNum_L1; i++) { pic = get_ref_pic_by_POC(hevc, @@ -2991,7 +3626,7 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) cur_pic->error_mark = 1; } - if (pic->error_mark) + if (pic->error_mark && (ref_frame_mark_flag[hevc->index])) cur_pic->error_mark = 1; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, (pic->mc_canvas_u_v << 16) @@ -3032,6 +3667,7 @@ static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, unsigned char is_referenced; /* hevc_print(hevc, 0, "%s cur_poc %d\n", __func__, cur_poc); */ + for (ii = 0; ii < MAX_REF_PIC_NUM; ii++) { pic = hevc->m_PIC[ii]; if (pic == NULL || @@ -3270,6 +3906,26 @@ static void update_tile_info(struct hevc_state_s *hevc, int pic_width_cu, int start_cu_x, start_cu_y; int sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu; int sao_abv_size = sao_mem_unit * pic_width_cu; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + int tmpRefillLcuSize = 1 << + (params->p.log2_min_coding_block_size_minus3 + + 3 + params->p.log2_diff_max_min_coding_block_size); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%x, %x, %x, %x\n", + params->p.slice_segment_address, + params->p.bit_depth, + params->p.tiles_enabled_flag, + tmpRefillLcuSize); + if (params->p.slice_segment_address == 0 && + params->p.bit_depth != 0 && + (params->p.tiles_enabled_flag & 1) && + tmpRefillLcuSize == 64) + hevc->delrefill_check = 1; + else + hevc->delrefill_check = 0; + } +#endif hevc->tile_enabled = params->p.tiles_enabled_flag & 1; if (params->p.tiles_enabled_flag & 1) { @@ -3476,7 +4132,7 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc) struct BuffInfo_s *buf_spec = hevc->work_space_buf; if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__, buf_spec->ipp.buf_start, @@ -3501,7 +4157,7 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc) WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, hevc->frame_mmu_map_phy_addr); hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "write HEVC_ASSIST_MMU_MAP_ADDR\n"); @@ -3544,7 +4200,7 @@ static void hevc_init_decoder_hw(struct hevc_state_s *hevc, unsigned int data32; int i; #if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { /* Set MCR fetch priorities*/ data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); @@ -3589,7 +4245,7 @@ static void hevc_init_decoder_hw(struct hevc_state_s *hevc, if (!hevc->m_ins_flag) { data32 = READ_VREG(HEVC_STREAM_CONTROL); data32 = data32 | (1 << 0); /* stream_fetch_enable */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) data32 |= (0xf << 25); /*arwlen_axi_max*/ WRITE_VREG(HEVC_STREAM_CONTROL, data32); } @@ -3919,13 +4575,24 @@ static void config_title_hw(struct hevc_state_s *hevc, int sao_vb_size, WRITE_VREG(HEVC_SAO_VB, hevc->work_space_buf->sao_vb.buf_start); } +static u32 init_aux_size; +static int aux_data_is_avaible(struct hevc_state_s *hevc) +{ + u32 reg_val; + + reg_val = READ_VREG(HEVC_AUX_DATA_SIZE); + if (reg_val != 0 && reg_val != init_aux_size) + return 1; + else + return 0; +} + static void config_aux_buf(struct hevc_state_s *hevc) { WRITE_VREG(HEVC_AUX_ADR, hevc->aux_phy_addr); - WRITE_VREG(HEVC_AUX_DATA_SIZE, - ((hevc->prefix_aux_size >> 4) << 16) | - (hevc->suffix_aux_size >> 4) - ); + init_aux_size = ((hevc->prefix_aux_size >> 4) << 16) | + (hevc->suffix_aux_size >> 4); + WRITE_VREG(HEVC_AUX_DATA_SIZE, init_aux_size); } static void config_mpred_hw(struct hevc_state_s *hevc) @@ -4227,9 +4894,13 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) #endif /* DBLK CONFIG HERE */ if (hevc->new_pic) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - data32 = (0x57 << 8) | /* 1st/2nd write both enable*/ - (0x0 << 0); /* h265 video format*/ + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + data32 = (0xff << 8) | (0x0 << 0); + else + data32 = (0x57 << 8) | /* 1st/2nd write both enable*/ + (0x0 << 0); /* h265 video format*/ + if (hevc->pic_w >= 1280) data32 |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/ data32 &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ @@ -4244,7 +4915,6 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data32); } - data32 = (hevc->pic_w | hevc->pic_h << 16); WRITE_VREG(HEVC_DBLK_CFG2, data32); @@ -4266,7 +4936,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) WRITE_VREG(HEVC_DBLK_CFG1, data32); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { /*if (debug & 0x80) {*/ data32 = 1 << 28; /* Debug only: sts1 chooses dblk_main*/ WRITE_VREG(HEVC_DBLK_STS1 + 4, data32); /* 0x3510 */ @@ -4274,7 +4944,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) "[DBLK DEBUG] HEVC1 STS1 : 0x%x\n", data32); /*}*/ - } + } } #if 0 data32 = READ_VREG(HEVC_SAO_CTRL1); @@ -4309,15 +4979,32 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) data32 &= (~0xff0); /* data32 |= 0x670; // Big-Endian per 64-bit */ data32 |= endian; /* Big-Endian per 64-bit */ - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ if (get_double_write_mode(hevc) == 0) data32 |= 0x2; /*disable double write*/ - else if (!hevc->mmu_enable && (get_double_write_mode(hevc) & 0x10)) + else if (get_double_write_mode(hevc) & 0x10) data32 |= 0x1; /*disable cm*/ - } - WRITE_VREG(HEVC_SAO_CTRL1, data32); + } else { + unsigned int data; + data = (0x57 << 8) | /* 1st/2nd write both enable*/ + (0x0 << 0); /* h265 video format*/ + if (hevc->pic_w >= 1280) + data |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/ + data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ + if (get_double_write_mode(hevc) == 0) + data |= (0x1 << 8); /*enable first write*/ + else if (get_double_write_mode(hevc) & 0x10) + data |= (0x1 << 9); /*double write only*/ + else + data |= ((0x1 << 8) |(0x1 << 9)); + WRITE_VREG(HEVC_DBLK_CFGB, data); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data); + } + + WRITE_VREG(HEVC_SAO_CTRL1, data32); if (get_double_write_mode(hevc) & 0x10) { /* [23:22] dw_v1_ctrl *[21:20] dw_v0_ctrl @@ -4573,6 +5260,7 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, rpm_param->p.bit_depth, hevc->frame_mmu_map_addr); if (ret != 0) { + put_mv_buf(hevc, new_pic); hevc_print(hevc, 0, "can't alloc need mmu1,idx %d ret =%d\n", new_pic->decode_idx, @@ -4600,6 +5288,21 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, hevc->bit_depth_luma; new_pic->bit_depth_chroma = hevc->bit_depth_chroma; + new_pic->video_signal_type = + hevc->video_signal_type; + + new_pic->conformance_window_flag = + hevc->param.p.conformance_window_flag; + new_pic->conf_win_left_offset = + hevc->param.p.conf_win_left_offset; + new_pic->conf_win_right_offset = + hevc->param.p.conf_win_right_offset; + new_pic->conf_win_top_offset = + hevc->param.p.conf_win_top_offset; + new_pic->conf_win_bottom_offset = + hevc->param.p.conf_win_bottom_offset; + new_pic->chroma_format_idc = + hevc->param.p.chroma_format_idc; hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "%s: index %d, buf_idx %d, decode_idx %d, POC %d\n", @@ -4713,8 +5416,20 @@ static void set_aux_data(struct hevc_state_s *hevc, READ_VREG(HEVC_AUX_DATA_SIZE); unsigned int aux_count = 0; int aux_size = 0; - if (pic == NULL) + if (pic == NULL || 0 == aux_data_is_avaible(hevc)) return; + + if (hevc->aux_data_dirty || + hevc->m_ins_flag == 0) { + dma_sync_single_for_cpu( + amports_get_dma_device(), + hevc->aux_phy_addr, + hevc->prefix_aux_size + hevc->suffix_aux_size, + DMA_FROM_DEVICE); + + hevc->aux_data_dirty = 0; + } + if (suffix_flag) { aux_adr = (unsigned short *) (hevc->aux_addr + @@ -4735,8 +5450,8 @@ static void set_aux_data(struct hevc_state_s *hevc, } if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { hevc_print(hevc, 0, - "%s:old size %d count %d,suf %d dv_flag %d\r\n", - __func__, pic->aux_data_size, + "%s:pic 0x%p old size %d count %d,suf %d dv_flag %d\r\n", + __func__, pic, pic->aux_data_size, aux_count, suffix_flag, dv_meta_flag); } if (aux_size > 0 && aux_count > 0) { @@ -4902,7 +5617,8 @@ static inline void hevc_pre_pic(struct hevc_state_s *hevc, hevc->ignore_bufmgr_error |= 0x2; } } - if (hevc->mmu_enable) { + if (hevc->mmu_enable + && ((hevc->double_write_mode & 0x10) == 0)) { if (!hevc->m_ins_flag) { hevc->used_4k_num = READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; @@ -5039,6 +5755,15 @@ static void check_pic_decoded_error_pre(struct hevc_state_s *hevc, hevc_print(hevc, 0, "head has error, set error_mark\n"); } + + if ((error_handle_policy & 0x80) == 0) { + if (hevc->over_decode && hevc->cur_pic) { + hevc_print(hevc, 0, + "over decode, set error_mark\n"); + hevc->cur_pic->error_mark = 1; + } + } + hevc->lcu_x_num_pre = hevc->lcu_x_num; hevc->lcu_y_num_pre = hevc->lcu_y_num; } @@ -5092,6 +5817,431 @@ static void check_pic_decoded_error(struct hevc_state_s *hevc, } } +/* only when we decoded one field or one frame, +we can call this function to get qos info*/ +static void get_picture_qos_info(struct hevc_state_s *hevc) +{ + struct PIC_s *picture = hevc->cur_pic; + +/* +#define DEBUG_QOS +*/ + + if (!hevc->cur_pic) + return; + + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + unsigned char a[3]; + unsigned char i, j, t; + unsigned long data; + + data = READ_VREG(HEVC_MV_INFO); + if (picture->slice_type == I_SLICE) + data = 0; + a[0] = data & 0xff; + a[1] = (data >> 8) & 0xff; + a[2] = (data >> 16) & 0xff; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_mv = a[2]; + picture->avg_mv = a[1]; + picture->min_mv = a[0]; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_QP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_qp = a[2]; + picture->avg_qp = a[1]; + picture->min_qp = a[0]; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_SKIP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_skip = a[2]; + picture->avg_skip = a[1]; + picture->min_skip = a[0]; + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + } else { + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +#ifdef DEBUG_QOS + int pic_number = picture->POC; +#endif + + picture->max_mv = 0; + picture->avg_mv = 0; + picture->min_mv = 0; + + picture->max_skip = 0; + picture->avg_skip = 0; + picture->min_skip = 0; + + picture->max_qp = 0; + picture->avg_qp = 0; + picture->min_qp = 0; + + + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "slice_type:%d, poc:%d\n", + picture->slice_type, + picture->POC); +#endif + /* set rd_idx to 0 */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); + + blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif + picture->avg_qp = rdata32/blk88_y_count; + /* intra_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + picture->avg_skip = rdata32*100/blk88_y_count; + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif + picture->min_qp = (rdata32>>0)&0xff; + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif + picture->max_qp = (rdata32>>8)&0xff; + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + hevc_print(hevc, 0, "[Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)value, + value, blk22_mv_count); +#endif + picture->avg_mv = value; + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + picture->max_mv = mv_hi; + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + picture->min_mv = mv_lo; + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + } +} + static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, union param_u *rpm_param, int decode_pic_begin) @@ -5168,7 +6318,7 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, #endif } - if (OVER_SIZE(hevc->pic_w, hevc->pic_h)) { + if (is_oversize(hevc->pic_w, hevc->pic_h)) { hevc_print(hevc, 0, "over size : %u x %u.\n", hevc->pic_w, hevc->pic_h); if ((!hevc->m_ins_flag) && @@ -5351,6 +6501,10 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, hevc->pic_list_init_flag = 3; } } + if (!hevc->m_ins_flag) { + if (hevc->cur_pic) + get_picture_qos_info(hevc); + } hevc->first_pic_after_recover = 0; if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) dump_pic_list(hevc); @@ -5380,7 +6534,11 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, } if (vdec->master == NULL && vdec->slave == NULL) - set_aux_data(hevc, hevc->cur_pic, 1, 0); + set_aux_data(hevc, + hevc->cur_pic, 1, 0); /*suffix*/ + if (hevc->bypass_dvenl && !dolby_meta_with_el) + set_aux_data(hevc, + hevc->cur_pic, 0, 1); /*dv meta only*/ #else set_aux_data(hevc, hevc->cur_pic, 1, 0); #endif @@ -5394,6 +6552,8 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, } #ifdef MULTI_INSTANCE_SUPPORT hevc->decoding_pic = hevc->cur_pic; + if (!hevc->m_ins_flag) + hevc->over_decode = 0; #endif #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION hevc->cur_pic->dv_enhance_exist = 0; @@ -5403,7 +6563,12 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, hevc->curr_POC); if (vdec->master == NULL && vdec->slave == NULL) - set_aux_data(hevc, hevc->cur_pic, 0, 0); + set_aux_data(hevc, + hevc->cur_pic, 0, 0); /*prefix*/ + + if (hevc->bypass_dvenl && !dolby_meta_with_el) + set_aux_data(hevc, + hevc->cur_pic, 0, 2); /*pre sei only*/ #else set_aux_data(hevc, hevc->cur_pic, 0, 0); #endif @@ -5416,16 +6581,18 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, return -1; } } else { + if (get_dbg_flag(hevc) & H265_DEBUG_HAS_AUX_IN_SLICE) { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->master == NULL && - vdec->slave == NULL) { + if (vdec->master == NULL && + vdec->slave == NULL) { + set_aux_data(hevc, hevc->cur_pic, 1, 0); + set_aux_data(hevc, hevc->cur_pic, 0, 0); + } +#else set_aux_data(hevc, hevc->cur_pic, 1, 0); set_aux_data(hevc, hevc->cur_pic, 0, 0); - } -#else - set_aux_data(hevc, hevc->cur_pic, 1, 0); - set_aux_data(hevc, hevc->cur_pic, 0, 0); #endif + } if (hevc->pic_list_init_flag != 3 || hevc->cur_pic == NULL) { /* make it dec from the first slice segment */ @@ -5441,6 +6608,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, if (hevc->cur_pic == NULL) return -1; + if (!hevc->m_ins_flag) + hevc->over_decode = 0; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION hevc->cur_pic->dv_enhance_exist = 0; if (vdec->master == NULL && @@ -5707,11 +6877,12 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, int bit_depth_10 = (bit_depth != 0x00); int picture_size; int cur_mmu_4k_number; - int ret; + int ret, max_frame_num; picture_size = compute_losless_comp_body_size(hevc, new_pic->width, new_pic->height, !bit_depth_10); cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12); - + if (hevc->double_write_mode & 0x10) + return 0; /*hevc_print(hevc, 0, "alloc_mmu cur_idx : %d picture_size : %d mmu_4k_number : %d\r\n", cur_buf_idx, picture_size, cur_mmu_4k_number);*/ @@ -5719,7 +6890,11 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, decoder_mmu_box_free_idx(hevc->mmu_box, new_pic->index); new_pic->scatter_alloc = 0; } - if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + if (cur_mmu_4k_number > max_frame_num) { hevc_print(hevc, 0, "over max !! 0x%x width %d height %d\n", cur_mmu_4k_number, new_pic->width, @@ -5750,7 +6925,9 @@ static void release_pic_mmu_buf(struct hevc_state_s *hevc, __func__, pic->index, pic->scatter_alloc); - if (hevc->mmu_enable && pic->scatter_alloc) + if (hevc->mmu_enable + && ((hevc->double_write_mode & 0x10) == 0) + && pic->scatter_alloc) decoder_mmu_box_free_idx(hevc->mmu_box, pic->index); pic->scatter_alloc = 0; } @@ -5769,6 +6946,21 @@ static void hevc_local_uninit(struct hevc_state_s *hevc) hevc->rpm_ptr = NULL; hevc->lmem_ptr = NULL; +#ifdef SWAP_HEVC_UCODE + if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->mc_cpu_addr != NULL) { + dma_free_coherent(amports_get_dma_device(), + hevc->swap_size, hevc->mc_cpu_addr, + hevc->mc_dma_handle); + hevc->mc_cpu_addr = NULL; + } + + } +#endif +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + uninit_detrefill_buf(hevc); +#endif if (hevc->aux_addr) { dma_unmap_single(amports_get_dma_device(), hevc->aux_phy_addr, @@ -5793,7 +6985,7 @@ static void hevc_local_uninit(struct hevc_state_s *hevc) if (hevc->mmu_enable && hevc->frame_mmu_map_addr) { if (hevc->frame_mmu_map_phy_addr) dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, hevc->frame_mmu_map_addr, + get_frame_mmu_map_size(), hevc->frame_mmu_map_addr, hevc->frame_mmu_map_phy_addr); hevc->frame_mmu_map_addr = NULL; @@ -5811,17 +7003,18 @@ static int hevc_local_init(struct hevc_state_s *hevc) memset(&hevc->param, 0, sizeof(union param_u)); cur_buf_info = &hevc->work_space_buf_store; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - memcpy(cur_buf_info, &amvh265_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + memcpy(cur_buf_info, &amvh265_workbuff_spec[2], /* 4k */ + sizeof(struct BuffInfo_s)); + else + memcpy(cur_buf_info, &amvh265_workbuff_spec[1], /* 4k */ + sizeof(struct BuffInfo_s)); + } else memcpy(cur_buf_info, &amvh265_workbuff_spec[0], /* 1080p */ sizeof(struct BuffInfo_s)); -#else - memcpy(cur_buf_info, &amvh265_workbuff_spec[0], /* 1080p work space */ - sizeof(struct BuffInfo_s)); -#endif + cur_buf_info->start_adr = hevc->buf_start; init_buff_spec(hevc, cur_buf_info); @@ -5830,6 +7023,7 @@ static int hevc_local_init(struct hevc_state_s *hevc) hevc->bit_depth_luma = 8; hevc->bit_depth_chroma = 8; hevc->video_signal_type = 0; + hevc->video_signal_type_debug = 0; bit_depth_luma = hevc->bit_depth_luma; bit_depth_chroma = hevc->bit_depth_chroma; video_signal_type = hevc->video_signal_type; @@ -5897,13 +7091,13 @@ static int hevc_local_init(struct hevc_state_s *hevc) if (hevc->mmu_enable) { hevc->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, + get_frame_mmu_map_size(), &hevc->frame_mmu_map_phy_addr, GFP_KERNEL); if (hevc->frame_mmu_map_addr == NULL) { pr_err("%s: failed to alloc count_buffer\n", __func__); return -1; } - memset(hevc->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); + memset(hevc->frame_mmu_map_addr, 0, get_frame_mmu_map_size()); } ret = 0; return ret; @@ -5934,6 +7128,7 @@ static int hevc_local_init(struct hevc_state_s *hevc) static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) { + struct vdec_s *vdec = hw_to_vdec(hevc); int canvas_w = ALIGN(pic->width, 64)/4; int canvas_h = ALIGN(pic->height, 32)/4; int blkmode = mem_map_mode; @@ -5952,8 +7147,15 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_w = ALIGN(canvas_w, 64); canvas_h = ALIGN(canvas_h, 32); - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + } canvas_config_ex(pic->y_canvas_index, pic->dw_y_adr, canvas_w, canvas_h, @@ -5985,8 +7187,14 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) } else { if (!hevc->mmu_enable) { /* to change after 10bit VPU is ready ... */ - pic->y_canvas_index = 128 + pic->index; - pic->uv_canvas_index = 128 + pic->index; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + pic->uv_canvas_index = pic->y_canvas_index; + } else { + pic->y_canvas_index = 128 + pic->index; + pic->uv_canvas_index = 128 + pic->index; + } canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, @@ -5997,8 +7205,16 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) } } #else - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + } + canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, CANVAS_ADDR_NOWRAP, blkmode, 0x7); @@ -6064,6 +7280,17 @@ static int parse_sei(struct hevc_state_s *hevc, "parse result pic_struct = %d\n", hevc->curr_pic_struct); } + break; + case SEI_UserDataITU_T_T35: + p_sei = p; + if (p_sei[0] == 0xB5 + && p_sei[1] == 0x00 + && p_sei[2] == 0x3C + && p_sei[3] == 0x00 + && p_sei[4] == 0x01 + && p_sei[5] == 0x04) + hevc->sei_present_flag |= SEI_HDR10PLUS_MASK; + break; case SEI_MasteringDisplayColorVolume: /*hevc_print(hevc, 0, @@ -6112,8 +7339,9 @@ static int parse_sei(struct hevc_state_s *hevc, hevc->luminance[1]);*/ break; case SEI_ContentLightLevel: - hevc_print(hevc, 0, - "sei type: max content light level %d, size %d\n", + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "sei type: max content light level %d, size %d\n", payload_type, payload_size); /* content_light_level */ p_sei = p; @@ -6125,8 +7353,9 @@ static int parse_sei(struct hevc_state_s *hevc, p_sei += 2; hevc->sei_present_flag |= SEI_CONTENT_LIGHT_LEVEL_MASK; - hevc_print(hevc, 0, - "\tmax cll = %04x, max_pa_cll = %04x\n", + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\tmax cll = %04x, max_pa_cll = %04x\n", hevc->content_light_level[0], hevc->content_light_level[1]); break; @@ -6229,11 +7458,6 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, ar = min_t(u32, hevc->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - /* signal_type */ - if (hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) - vf->signal_type = hevc->video_signal_type; - else - vf->signal_type = 0; if (((pic->aspect_ratio_idc == 255) && pic->sar_width && @@ -6249,6 +7473,7 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); } + hevc->ratio_control = vf->ratio_control; if (pic->aux_data_buf && pic->aux_data_size) { /* parser sei */ @@ -6271,6 +7496,19 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, p += size; } } + if (hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) { + vf->signal_type = pic->video_signal_type; + if (hevc->sei_present_flag & SEI_HDR10PLUS_MASK) { + u32 data; + data = vf->signal_type; + data = data & 0xFFFF00FF; + data = data | (0x30<<8); + vf->signal_type = data; + } + } + else + vf->signal_type = 0; + hevc->video_signal_type_debug = vf->signal_type; /* master_display_colour */ if (hevc->sei_present_flag & SEI_MASTER_DISPLAY_COLOR_MASK) { @@ -6443,13 +7681,32 @@ static struct vframe_s *vh265_vf_get(void *op_arg) struct vframe_s *next_vf; if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, - "%s(type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n", - __func__, vf->type, vf->index, + "%s(vf 0x%p type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n", + __func__, vf, vf->type, vf->index, get_pic_poc(hevc, vf->index & 0xff), get_pic_poc(hevc, (vf->index >> 8) & 0xff), vf->pts, vf->pts_us64, vf->duration); - +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (get_dbg_flag(hevc) & H265_DEBUG_DV) { + struct PIC_s *pic = hevc->m_PIC[vf->index & 0xff]; + if (pic->aux_data_buf && pic->aux_data_size > 0) { + int i; + struct PIC_s *pic = + hevc->m_PIC[vf->index & 0xff]; + hevc_print(hevc, 0, + "pic 0x%p aux size %d:\n", + pic, pic->aux_data_size); + for (i = 0; i < pic->aux_data_size; i++) { + hevc_print_cont(hevc, 0, + "%02x ", pic->aux_data_buf[i]); + if (((i + 1) & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + } + hevc_print_cont(hevc, 0, "\n"); + } + } +#endif hevc->show_frame_num++; hevc->vf_get_count++; @@ -6486,7 +7743,7 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg) kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf); spin_lock_irqsave(&lock, flags); - if (index_top != 0xff && index_top >= 0 + if (index_top != 0xff && index_top < MAX_REF_PIC_NUM && hevc->m_PIC[index_top]) { if (hevc->m_PIC[index_top]->vf_ref > 0) { @@ -6502,7 +7759,7 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg) } } - if (index_bot != 0xff && index_bot >= 0 + if (index_bot != 0xff && index_bot < MAX_REF_PIC_NUM && hevc->m_PIC[index_bot]) { if (hevc->m_PIC[index_bot]->vf_ref > 0) { @@ -6554,17 +7811,22 @@ static int vh265_event_cb(int type, void *data, void *op_arg) req->aux_size = 0; if (req->bot_flag) index = (req->vf->index >> 8) & 0xff; - if (index != 0xff && index >= 0 + if (index != 0xff && index < MAX_REF_PIC_NUM && hevc->m_PIC[index]) { req->aux_buf = hevc->m_PIC[index]->aux_data_buf; req->aux_size = hevc->m_PIC[index]->aux_data_size; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - req->dv_enhance_exist = - hevc->m_PIC[index]->dv_enhance_exist; + if (hevc->bypass_dvenl && !dolby_meta_with_el) + req->dv_enhance_exist = false; + else + req->dv_enhance_exist = + hevc->m_PIC[index]->dv_enhance_exist; hevc_print(hevc, H265_DEBUG_DV, - "query dv_enhance_exist for pic (poc %d) flag => %d\n", - hevc->m_PIC[index]->POC, req->dv_enhance_exist); + "query dv_enhance_exist for pic (vf 0x%p, poc %d index %d) flag => %d, aux sizd 0x%x\n", + req->vf, + hevc->m_PIC[index]->POC, index, + req->dv_enhance_exist, req->aux_size); #else req->dv_enhance_exist = 0; #endif @@ -6575,8 +7837,17 @@ static int vh265_event_cb(int type, void *data, void *op_arg) hevc_print(hevc, 0, "%s(type 0x%x vf index 0x%x)=>size 0x%x\n", __func__, type, index, req->aux_size); - } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } else if (type & VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL) { + if ((force_bypass_dvenl & 0x80000000) == 0) { + hevc_print(hevc, 0, + "%s: VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL\n", + __func__); + hevc->bypass_dvenl_enable = 1; + } +#endif + } return 0; } @@ -6606,6 +7877,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, __func__, vf->index); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } if (kfifo_peek(&hevc->pending_q, &vf)) { @@ -6627,6 +7899,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } } else if ((!pair_frame_top_flag) && (((vf->index >> 8) & 0xff) == 0xff)) { @@ -6644,6 +7917,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, pair_pic->vf_ref++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, @@ -6666,6 +7940,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, pair_pic->vf_ref++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, @@ -6701,6 +7976,65 @@ static void update_vf_memhandle(struct hevc_state_s *hevc, } return; } + +static void fill_frame_info(struct hevc_state_s *hevc, + struct PIC_s *pic, unsigned int framesize, unsigned int pts) +{ + struct vframe_qos_s *vframe_qos = &hevc->vframe_qos; + if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR) + vframe_qos->type = 4; + else if (pic->slice_type == I_SLICE) + vframe_qos->type = 1; + else if (pic->slice_type == P_SLICE) + vframe_qos->type = 2; + else if (pic->slice_type == B_SLICE) + vframe_qos->type = 3; +/* +#define SHOW_QOS_INFO +*/ + vframe_qos->size = framesize; + vframe_qos->pts = pts; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "slice:%d, poc:%d\n", pic->slice_type, pic->POC); +#endif + + + vframe_qos->max_mv = pic->max_mv; + vframe_qos->avg_mv = pic->avg_mv; + vframe_qos->min_mv = pic->min_mv; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "mv: max:%d, avg:%d, min:%d\n", + vframe_qos->max_mv, + vframe_qos->avg_mv, + vframe_qos->min_mv); +#endif + + vframe_qos->max_qp = pic->max_qp; + vframe_qos->avg_qp = pic->avg_qp; + vframe_qos->min_qp = pic->min_qp; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "qp: max:%d, avg:%d, min:%d\n", + vframe_qos->max_qp, + vframe_qos->avg_qp, + vframe_qos->min_qp); +#endif + + vframe_qos->max_skip = pic->max_skip; + vframe_qos->avg_skip = pic->avg_skip; + vframe_qos->min_skip = pic->min_skip; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "skip: max:%d, avg:%d, min:%d\n", + vframe_qos->max_skip, + vframe_qos->avg_skip, + vframe_qos->min_skip); +#endif + + vframe_qos->num++; + + if (hevc->frameinfo_enable) + vdec_fill_frame_info(vframe_qos, 1); +} + static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -6709,6 +8043,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) struct vframe_s *vf = NULL; int stream_offset = pic->stream_offset; unsigned short slice_type = pic->slice_type; + u32 frame_size; + if (force_disp_pic_index & 0x100) { /*recycle directly*/ pic->output_ready = 0; @@ -6742,7 +8078,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) "call pts_lookup_offset_us64(0x%x)\n", stream_offset); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, + (PTS_TYPE_VIDEO, stream_offset, &vf->pts, + &frame_size, 0, &vf->pts_us64) != 0) { #ifdef DEBUG_PTS hevc->pts_missed++; @@ -6767,6 +8104,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (pts_unstable && (hevc->frame_dur > 0)) hevc->pts_mode = PTS_NONE_REF_USE_DURATION; + fill_frame_info(hevc, pic, frame_size, vf->pts); + if ((hevc->pts_mode == PTS_NORMAL) && (vf->pts != 0) && hevc->get_frame_dur) { int pts_diff = (int)vf->pts - hevc->last_lookup_pts; @@ -6853,7 +8192,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (pic->double_write_mode) { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; vf->type |= VIDTYPE_VIU_NV21; - if (pic->double_write_mode == 3) { + if ((pic->double_write_mode == 3) && + (!(IS_8K_SIZE(pic->width, pic->height)))) { vf->type |= VIDTYPE_COMPRESS; if (hevc->mmu_enable) vf->type |= VIDTYPE_SCATTER; @@ -6948,12 +8288,12 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) * need move below code to get_new_pic(), * hevc->xxx can only be used by current decoded pic */ - if (hevc->param.p.conformance_window_flag && + if (pic->conformance_window_flag && (get_dbg_flag(hevc) & H265_DEBUG_IGNORE_CONFORMANCE_WINDOW) == 0) { unsigned int SubWidthC, SubHeightC; - switch (hevc->param.p.chroma_format_idc) { + switch (pic->chroma_format_idc) { case 1: SubWidthC = 2; SubHeightC = 2; @@ -6968,27 +8308,27 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) break; } vf->width -= SubWidthC * - (hevc->param.p.conf_win_left_offset + - hevc->param.p.conf_win_right_offset); + (pic->conf_win_left_offset + + pic->conf_win_right_offset); vf->height -= SubHeightC * - (hevc->param.p.conf_win_top_offset + - hevc->param.p.conf_win_bottom_offset); + (pic->conf_win_top_offset + + pic->conf_win_bottom_offset); vf->compWidth -= SubWidthC * - (hevc->param.p.conf_win_left_offset + - hevc->param.p.conf_win_right_offset); + (pic->conf_win_left_offset + + pic->conf_win_right_offset); vf->compHeight -= SubHeightC * - (hevc->param.p.conf_win_top_offset + - hevc->param.p.conf_win_bottom_offset); + (pic->conf_win_top_offset + + pic->conf_win_bottom_offset); if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) hevc_print(hevc, 0, "conformance_window %d, %d, %d, %d, %d => cropped width %d, height %d com_w %d com_h %d\n", - hevc->param.p.chroma_format_idc, - hevc->param.p.conf_win_left_offset, - hevc->param.p.conf_win_right_offset, - hevc->param.p.conf_win_top_offset, - hevc->param.p.conf_win_bottom_offset, + pic->chroma_format_idc, + pic->conf_win_left_offset, + pic->conf_win_right_offset, + pic->conf_win_top_offset, + pic->conf_win_bottom_offset, vf->width, vf->height, vf->compWidth, vf->compHeight); } @@ -7029,9 +8369,11 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf2); + ATRACE_COUNTER(MODULE_NAME, vf2->pts); } else if (pic->pic_struct == 5 || pic->pic_struct == 6) { struct vframe_s *vf2, *vf3; @@ -7075,12 +8417,15 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf2); + ATRACE_COUNTER(MODULE_NAME, vf2->pts); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf3); + ATRACE_COUNTER(MODULE_NAME, vf3->pts); } else if (pic->pic_struct == 9 || pic->pic_struct == 10) { @@ -7184,12 +8529,15 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } #else vf->type_original = vf->type; pic->vf_ref = 1; hevc->vf_pre_count++; + decoder_do_frame_check(hw_to_vdec(hevc), vf); kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, @@ -7204,6 +8552,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) /*count info*/ vdec_count_info(gvs, 0, stream_offset); #endif + hw_to_vdec(hevc)->vdec_fps_detec(hw_to_vdec(hevc)->id); vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -7436,6 +8785,13 @@ static int hevc_recover(struct hevc_state_s *hevc) hevc_print(hevc, 0, "%s HEVC_SHIFT_BYTE_COUNT=0x%x\n", __func__, READ_VREG(HEVC_SHIFT_BYTE_COUNT)); +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); + /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ + } +#endif amhevc_start(); /* skip, search next start code */ @@ -7508,11 +8864,7 @@ static void dump_aux_buf(struct hevc_state_s *hevc) static void dolby_get_meta(struct hevc_state_s *hevc) { struct vdec_s *vdec = hw_to_vdec(hevc); - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->aux_phy_addr, - hevc->prefix_aux_size + hevc->suffix_aux_size, - DMA_FROM_DEVICE); + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) dump_aux_buf(hevc); @@ -7657,6 +9009,7 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) hevc->shift_byte_count_lo = i; } #ifdef MULTI_INSTANCE_SUPPORT + mutex_lock(&hevc->chunks_mutex); if ((dec_status == HEVC_DECPIC_DATA_DONE || dec_status == HEVC_FIND_NEXT_PIC_NAL || dec_status == HEVC_FIND_NEXT_DVEL_NAL) @@ -7664,12 +9017,14 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) hevc->cur_pic->pts = hevc->chunk->pts; hevc->cur_pic->pts64 = hevc->chunk->pts64; } + mutex_unlock(&hevc->chunks_mutex); if (dec_status == HEVC_DECODE_BUFEMPTY || dec_status == HEVC_DECODE_BUFEMPTY2) { if (hevc->m_ins_flag) { read_decode_info(hevc); if (vdec_frame_based(hw_to_vdec(hevc))) { + hevc->empty_flag = 1; goto pic_done; } else { if ( @@ -7695,6 +9050,7 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) read_decode_info(hevc); if (vdec_frame_based(hw_to_vdec(hevc))) { /*hevc->dec_result = DEC_RESULT_GET_DATA;*/ + hevc->empty_flag = 1; goto pic_done; } else { hevc->dec_result = DEC_RESULT_AGAIN; @@ -7709,15 +9065,143 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) return IRQ_HANDLED; } else if (dec_status == HEVC_DECPIC_DATA_DONE) { if (hevc->m_ins_flag) { + struct PIC_s *pic; + struct PIC_s *pic_display; + int decoded_poc; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->detbuf_adr_virt && hevc->delrefill_check + && READ_VREG(HEVC_SAO_DBG_MODE0)) + hevc->delrefill_check = 2; + } +#endif + hevc->empty_flag = 0; pic_done: - read_decode_info(hevc); + if (input_frame_based(hw_to_vdec(hevc)) && + frmbase_cont_bitlevel != 0 && + (hevc->decode_size > READ_VREG(HEVC_SHIFT_BYTE_COUNT)) && + (hevc->decode_size - (READ_VREG(HEVC_SHIFT_BYTE_COUNT)) + > frmbase_cont_bitlevel)) { + /*handle the case: multi pictures in one packet*/ + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s has more data index= %d, size=0x%x shiftcnt=0x%x)\n", + __func__, + hevc->decode_idx, hevc->decode_size, + READ_VREG(HEVC_SHIFT_BYTE_COUNT)); + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + start_process_time(hevc); + return IRQ_HANDLED; + } + read_decode_info(hevc); + get_picture_qos_info(hevc); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + hevc->start_parser_type = 0; + hevc->switch_dvlayer_flag = 0; +#endif hevc->decoded_poc = hevc->curr_POC; hevc->decoding_pic = NULL; hevc->dec_result = DEC_RESULT_DONE; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + if (hevc->delrefill_check != 2) +#endif + amhevc_stop(); reset_process_time(hevc); + + if (hevc->vf_pre_count == 0) { + decoded_poc = hevc->curr_POC; + pic = get_pic_by_POC(hevc, decoded_poc); + if (pic && (pic->POC != INVALID_POC)) { + /*PB skip control */ + if (pic->error_mark == 0 + && hevc->PB_skip_mode == 1) { + /* start decoding after + * first I + */ + hevc->ignore_bufmgr_error |= 0x1; + } + if (hevc->ignore_bufmgr_error & 1) { + if (hevc->PB_skip_count_after_decoding > 0) { + hevc->PB_skip_count_after_decoding--; + } else { + /* start displaying */ + hevc->ignore_bufmgr_error |= 0x2; + } + } + if (hevc->mmu_enable + && ((hevc->double_write_mode & 0x10) == 0)) { + if (!hevc->m_ins_flag) { + hevc->used_4k_num = + READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; + + if ((!is_skip_decoding(hevc, pic)) && + (hevc->used_4k_num >= 0) && + (hevc->cur_pic->scatter_alloc + == 1)) { + hevc_print(hevc, + H265_DEBUG_BUFMGR_MORE, + "%s pic index %d scatter_alloc %d page_start %d\n", + "decoder_mmu_box_free_idx_tail", + hevc->cur_pic->index, + hevc->cur_pic->scatter_alloc, + hevc->used_4k_num); + decoder_mmu_box_free_idx_tail( + hevc->mmu_box, + hevc->cur_pic->index, + hevc->used_4k_num); + hevc->cur_pic->scatter_alloc + = 2; + } + hevc->used_4k_num = -1; + } + } + + pic->output_mark = 1; + pic->recon_mark = 1; + } + + pic_display = output_pic(hevc, 1); + + if (pic_display) { + if ((pic_display->error_mark && + ((hevc->ignore_bufmgr_error & + 0x2) == 0)) + || (get_dbg_flag(hevc) & + H265_DEBUG_DISPLAY_CUR_FRAME) + || (get_dbg_flag(hevc) & + H265_DEBUG_NO_DISPLAY)) { + pic_display->output_ready = 0; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] Display: POC %d, ", + pic_display->POC); + hevc_print_cont(hevc, 0, + "decoding index %d ==> ", + pic_display-> + decode_idx); + hevc_print_cont(hevc, 0, + "Debug or err,recycle it\n"); + } + } else { + if (pic_display-> + slice_type != 2) { + pic_display->output_ready = 0; + } else { + prepare_display_buf + (hevc, + pic_display); + hevc->first_pic_flag = 1; + } + } + } + } + vdec_schedule_work(&hevc->work); } @@ -7798,7 +9282,7 @@ pic_done: hevc->dec_result = DEC_RESULT_DONE; amhevc_stop(); reset_process_time(hevc); - if (READ_VREG(HEVC_AUX_DATA_SIZE) != 0) + if (aux_data_is_avaible(hevc)) dolby_get_meta(hevc); vdec_schedule_work(&hevc->work); @@ -7844,7 +9328,7 @@ pic_done: hevc_print(hevc, 0, "get NAL_UNIT_EOS, flush output\n"); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((vdec->master || vdec->slave) && - READ_VREG(HEVC_AUX_DATA_SIZE) != 0) { + aux_data_is_avaible(hevc)) { if (hevc->decoding_pic) dolby_get_meta(hevc); } @@ -7856,6 +9340,7 @@ pic_done: /* add to fix RAP_B_Bossen_1 */ hevc->m_pocRandomAccess = MAX_INT; flush_output(hevc, pic); + clear_poc_flag(hevc); WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_DISCARD_NAL); /* Interrupt Amrisc to excute */ WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); @@ -8076,7 +9561,7 @@ pic_done: vdec->master == NULL && vdec->slave == NULL && #endif - READ_VREG(HEVC_AUX_DATA_SIZE) != 0 + aux_data_is_avaible(hevc) ) { dma_sync_single_for_cpu( amports_get_dma_device(), @@ -8188,10 +9673,16 @@ pic_done: hevc->lcu_size = 1 << (log + 3 + log_s); hevc->lcu_size_log2 = log2i(hevc->lcu_size); if (hevc->pic_w == 0 || hevc->pic_h == 0 - || hevc->lcu_size == 0) { + || hevc->lcu_size == 0 + || is_oversize(hevc->pic_w, hevc->pic_h) + || (!hevc->skip_first_nal && + (hevc->pic_h == 96) && (hevc->pic_w == 160))) { /* skip search next start code */ WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2)); + if ( !hevc->skip_first_nal && + (hevc->pic_h == 96) && (hevc->pic_w == 160)) + hevc->skip_first_nal = 1; hevc->skip_flag = 1; WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); /* Interrupt Amrisc to excute */ @@ -8404,6 +9895,16 @@ static irqreturn_t vh265_isr(int irq, void *data) if (hevc->pic_list_init_flag == 1) return IRQ_HANDLED; + if (!hevc->m_ins_flag) { + if (dec_status == HEVC_OVER_DECODE) { + hevc->over_decode = 1; + hevc_print(hevc, 0, + "isr: over decode\n"), + WRITE_VREG(HEVC_DEC_STATUS_REG, 0); + return IRQ_HANDLED; + } + } + return IRQ_WAKE_THREAD; } @@ -8413,18 +9914,12 @@ static void vh265_set_clk(struct work_struct *work) struct hevc_state_s *hevc = container_of(work, struct hevc_state_s, work); - if (hevc->m_ins_flag == 0 && - hevc->get_frame_dur && hevc->show_frame_num > 60 && - hevc->frame_dur > 0 && hevc->saved_resolution != - hevc->frame_width * hevc->frame_height * - (96000 / hevc->frame_dur)) { int fps = 96000 / hevc->frame_dur; if (hevc_source_changed(VFORMAT_HEVC, hevc->frame_width, hevc->frame_height, fps) > 0) hevc->saved_resolution = hevc->frame_width * hevc->frame_height * fps; - } } static void vh265_check_timer_func(unsigned long arg) @@ -8622,7 +10117,7 @@ static void vh265_check_timer_func(unsigned long arg) if (dbg_cmd == 1) { u32 disp_laddr; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && get_double_write_mode(hevc) == 0) { disp_laddr = READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; @@ -8640,7 +10135,11 @@ static void vh265_check_timer_func(unsigned long arg) dbg_cmd = 0; } /*don't changed at start.*/ - if (hevc->m_ins_flag == 0) + if (hevc->m_ins_flag == 0 && + hevc->get_frame_dur && hevc->show_frame_num > 60 && + hevc->frame_dur > 0 && hevc->saved_resolution != + hevc->frame_width * hevc->frame_height * + (96000 / hevc->frame_dur)) schedule_work(&hevc->set_clk_work); mod_timer(timer, jiffies + PUT_INTERVAL); @@ -8675,20 +10174,17 @@ static int h265_task_handle(void *data) hevc_print(hevc, 0, "uninit list\n"); hevc->uninit_list = 0; #ifdef USE_UNINIT_SEMA - if (use_cma && hevc->init_flag) { + if (use_cma) { up(&hevc->h265_uninit_done_sema); + while (!kthread_should_stop()) + msleep(1); break; } #endif } } - while (!kthread_should_stop()) { - msleep(1); - } - return 0; - } void vh265_free_cmabuf(void) @@ -8717,6 +10213,9 @@ int vh265_dec_status(struct vdec_info *vstatus) #else struct hevc_state_s *hevc = gHevc; #endif + if (!hevc) + return -1; + vstatus->frame_width = hevc->frame_width; vstatus->frame_height = hevc->frame_height; if (hevc->frame_dur != 0) @@ -8742,6 +10241,7 @@ int vh265_dec_status(struct vdec_info *vstatus) snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); #endif + vstatus->ratio_control = hevc->ratio_control; return 0; } @@ -8794,11 +10294,25 @@ static void config_decode_mode(struct hevc_state_s *hevc) decode_mode = DECODE_MODE_MULTI_FRAMEBASE; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec->slave) - decode_mode = - (hevc->start_parser_type << 8) - | DECODE_MODE_MULTI_DVBAL; - else if (vdec->master) + else if (vdec->slave) { + if (force_bypass_dvenl & 0x80000000) + hevc->bypass_dvenl = force_bypass_dvenl & 0x1; + else + hevc->bypass_dvenl = hevc->bypass_dvenl_enable; + if (dolby_meta_with_el && hevc->bypass_dvenl) { + hevc->bypass_dvenl = 0; + hevc_print(hevc, 0, + "NOT support bypass_dvenl when meta_with_el\n"); + } + if (hevc->bypass_dvenl) + decode_mode = + (hevc->start_parser_type << 8) + | DECODE_MODE_MULTI_STREAMBASE; + else + decode_mode = + (hevc->start_parser_type << 8) + | DECODE_MODE_MULTI_DVBAL; + } else if (vdec->master) decode_mode = (hevc->start_parser_type << 8) | DECODE_MODE_MULTI_DVENL; @@ -8878,6 +10392,20 @@ static void vh265_prot_init(struct hevc_state_s *hevc) config_decode_mode(hevc); config_aux_buf(hevc); +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); + /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ + } +#endif +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_SAO_DBG_MODE0, 0); + WRITE_VREG(HEVC_SAO_DBG_MODE1, 0); + } +#endif } static int vh265_local_init(struct hevc_state_s *hevc) @@ -8894,12 +10422,23 @@ static int vh265_local_init(struct hevc_state_s *hevc) hevc->get_frame_dur = false; hevc->frame_width = hevc->vh265_amstream_dec_info.width; hevc->frame_height = hevc->vh265_amstream_dec_info.height; - if (OVER_SIZE(hevc->frame_width, hevc->frame_height)) { + if (is_oversize(hevc->frame_width, hevc->frame_height)) { pr_info("over size : %u x %u.\n", hevc->frame_width, hevc->frame_height); hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; return ret; } + + if (hevc->max_pic_w && hevc->max_pic_h) { + hevc->is_4k = !(hevc->max_pic_w && hevc->max_pic_h) || + ((hevc->max_pic_w * hevc->max_pic_h) > + 1920 * 1088) ? true : false; + } else { + hevc->is_4k = !(hevc->frame_width && hevc->frame_height) || + ((hevc->frame_width * hevc->frame_height) > + 1920 * 1088) ? true : false; + } + hevc->frame_dur = (hevc->vh265_amstream_dec_info.rate == 0) ? 3600 : hevc->vh265_amstream_dec_info.rate; @@ -8967,29 +10506,35 @@ static s32 vh265_init(struct hevc_state_s *hevc) if (vh265_local_init(hevc) < 0) return -EBUSY; + mutex_init(&hevc->chunks_mutex); INIT_WORK(&hevc->notify_work, vh265_notify_work); INIT_WORK(&hevc->set_clk_work, vh265_set_clk); + fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; -#ifdef MULTI_INSTANCE_SUPPORT - if (tee_enabled()) - size = 1; - else -#endif - if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - size = get_firmware_data(VIDEO_DEC_HEVC, fw->data); - hevc_print(hevc, 0, "vh265 ucode loaded!\n"); - } else { + if (hevc->mmu_enable) + if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) size = get_firmware_data(VIDEO_DEC_HEVC_MMU, fw->data); - hevc_print(hevc, 0, "vh265 mmu ucode loaded!\n"); + else { + if (!hevc->is_4k) { + /* if an older version of the fw was loaded, */ + /* needs try to load noswap fw because the */ + /* old fw package dose not contain the swap fw.*/ + size = get_firmware_data( + VIDEO_DEC_HEVC_MMU_SWAP, fw->data); + if (size < 0) + size = get_firmware_data( + VIDEO_DEC_HEVC_MMU, fw->data); + else if (size) + hevc->is_swap = true; + } else + size = get_firmware_data(VIDEO_DEC_HEVC_MMU, + fw->data); } - } else { + else size = get_firmware_data(VIDEO_DEC_HEVC, fw->data); - hevc_print(hevc, 0, "vh265 ucode loaded!\n"); - } if (size < 0) { pr_err("get firmware fail.\n"); @@ -8999,6 +10544,31 @@ static s32 vh265_init(struct hevc_state_s *hevc) fw->len = size; +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->mmu_enable) { + hevc->swap_size = (4 * (4 * SZ_1K)); /*max 4 swap code, each 0x400*/ + hevc->mc_cpu_addr = + dma_alloc_coherent(amports_get_dma_device(), + hevc->swap_size, + &hevc->mc_dma_handle, GFP_KERNEL); + if (!hevc->mc_cpu_addr) { + amhevc_disable(); + pr_info("vh265 mmu swap ucode loaded fail.\n"); + return -ENOMEM; + } + + memcpy((u8 *) hevc->mc_cpu_addr, fw->data + SWAP_HEVC_OFFSET, + hevc->swap_size); + + hevc_print(hevc, 0, + "vh265 mmu ucode swap loaded %x\n", + hevc->mc_dma_handle); + } + } +#endif + #ifdef MULTI_INSTANCE_SUPPORT if (hevc->m_ins_flag) { hevc->timer.data = (ulong) hevc; @@ -9020,24 +10590,36 @@ static s32 vh265_init(struct hevc_state_s *hevc) return 0; } #endif + hevc_enable_DMC(hw_to_vdec(hevc)); amhevc_enable(); - if (size == 1) { - pr_info ("tee load ok"); - - if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC, 0); - else - ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC_MMU, 0); - } else - ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC, 0); - } else + if (hevc->mmu_enable) + if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) + ret = amhevc_loadmc_ex(VFORMAT_HEVC, "h265_mmu", fw->data); + else { + if (!hevc->is_4k) { + /* if an older version of the fw was loaded, */ + /* needs try to load noswap fw because the */ + /* old fw package dose not contain the swap fw. */ + ret = amhevc_loadmc_ex(VFORMAT_HEVC, + "hevc_mmu_swap", fw->data); + if (ret < 0) + ret = amhevc_loadmc_ex(VFORMAT_HEVC, + "h265_mmu", fw->data); + else + hevc->is_swap = true; + } else + ret = amhevc_loadmc_ex(VFORMAT_HEVC, + "h265_mmu", fw->data); + } + else ret = amhevc_loadmc_ex(VFORMAT_HEVC, NULL, fw->data); if (ret < 0) { amhevc_disable(); vfree(fw); + pr_err("H265: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -9045,6 +10627,11 @@ static s32 vh265_init(struct hevc_state_s *hevc) hevc->stat |= STAT_MC_LOAD; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + init_detrefill_buf(hevc); +#endif /* enable AMRISC side protocol */ vh265_prot_init(hevc); @@ -9067,12 +10654,13 @@ static s32 vh265_init(struct hevc_state_s *hevc) vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_START, NULL); if (hevc->frame_dur != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long)hevc->frame_dur)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; #else @@ -9143,17 +10731,21 @@ static s32 vh265_init(struct hevc_state_s *hevc) (1 << 3)); /* 3 */ } #endif - amhevc_start(); +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); + /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ + } +#endif - hevc->stat |= STAT_VDEC_RUN; #ifndef MULTI_INSTANCE_SUPPORT set_vdec_func(&vh265_dec_status); #endif + amhevc_start(); + hevc->stat |= STAT_VDEC_RUN; hevc->init_flag = 1; - if (hevc->mmu_enable) - error_handle_threshold = 300; - else - error_handle_threshold = 30; + error_handle_threshold = 30; /* pr_info("%d, vh265_init, RP=0x%x\n", * __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); */ @@ -9195,7 +10787,7 @@ static int vh265_stop(struct hevc_state_s *hevc) } if (hevc->stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) { + if (fr_hint_status == VDEC_HINTED) { vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); @@ -9211,12 +10803,10 @@ static int vh265_stop(struct hevc_state_s *hevc) hevc->uninit_list = 1; up(&h265_sema); #ifdef USE_UNINIT_SEMA - if (hevc->init_flag) { - down(&hevc->h265_uninit_done_sema); - if (!IS_ERR(h265_task)) { - kthread_stop(h265_task); - h265_task = NULL; - } + down(&hevc->h265_uninit_done_sema); + if (!IS_ERR(h265_task)) { + kthread_stop(h265_task); + h265_task = NULL; } #else while (hevc->uninit_list) /* wait uninit complete */ @@ -9225,6 +10815,7 @@ static int vh265_stop(struct hevc_state_s *hevc) } hevc->init_flag = 0; + hevc->first_sc_checked = 0; cancel_work_sync(&hevc->notify_work); cancel_work_sync(&hevc->set_clk_work); uninit_mmu_buffers(hevc); @@ -9278,6 +10869,43 @@ static void timeout_process(struct hevc_state_s *hevc) vdec_schedule_work(&hevc->work); } +#ifdef CONSTRAIN_MAX_BUF_NUM +static int get_vf_ref_only_buf_count(struct hevc_state_s *hevc) +{ + struct PIC_s *pic; + int i; + int count = 0; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 1) + count++; + } + + return count; +} + +static int get_used_buf_count(struct hevc_state_s *hevc) +{ + struct PIC_s *pic; + int i; + int count = 0; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->output_mark != 0 || pic->referenced != 0 + || pic->output_ready != 0) + count++; + } + + return count; +} +#endif + + static unsigned char is_new_pic_available(struct hevc_state_s *hevc) { struct PIC_s *new_pic = NULL; @@ -9346,6 +10974,7 @@ static int vmh265_stop(struct hevc_state_s *hevc) #endif } hevc->init_flag = 0; + hevc->first_sc_checked = 0; cancel_work_sync(&hevc->work); cancel_work_sync(&hevc->notify_work); cancel_work_sync(&hevc->set_clk_work); @@ -9363,10 +10992,20 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap(hevc->chunk->block->start + + hevc->chunk->offset, size); + else + data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } @@ -9492,7 +11131,10 @@ static void vh265_work(struct work_struct *work) READ_VREG(HEVC_STREAM_WR_PTR), READ_VREG(HEVC_STREAM_RD_PTR), READ_VREG(HEVC_MPC_E)); + mutex_lock(&hevc->chunks_mutex); vdec_vframe_dirty(vdec, hevc->chunk); + hevc->chunk = NULL; + mutex_unlock(&hevc->chunks_mutex); vdec_clean_input(vdec); } @@ -9521,9 +11163,17 @@ static void vh265_work(struct work_struct *work) if (get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) { int jj; - u8 *data = - ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap( + hevc->chunk->block->start + + hevc->chunk->offset, r); + else + data = ((u8 *) + hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < r; jj++) { if ((jj & 0xf) == 0) hevc_print(hevc, @@ -9537,6 +11187,9 @@ static void vh265_work(struct work_struct *work) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } decode_size = hevc->chunk->size + @@ -9566,7 +11219,16 @@ static void vh265_work(struct work_struct *work) /* if (!hevc->ctx_valid) hevc->ctx_valid = 1; */ decode_frame_count[hevc->index]++; - if (hevc->mmu_enable) { +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->delrefill_check == 2) { + delrefill(hevc); + amhevc_stop(); + } + } +#endif + if (hevc->mmu_enable && ((hevc->double_write_mode & 0x10) == 0)) { hevc->used_4k_num = READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; if (hevc->used_4k_num >= 0 && @@ -9589,11 +11251,15 @@ static void vh265_work(struct work_struct *work) hevc->pic_decoded_lcu_idx = READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff; - hevc->over_decode = - (READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1; - if (hevc->over_decode) - hevc_print(hevc, 0, - "!!!Over decode\n"); + + if (vdec->master == NULL && vdec->slave == NULL && + hevc->empty_flag == 0) { + hevc->over_decode = + (READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1; + if (hevc->over_decode) + hevc_print(hevc, 0, + "!!!Over decode\n"); + } if (is_log_enable(hevc)) add_log(hevc, @@ -9672,7 +11338,10 @@ static void vh265_work(struct work_struct *work) hevc->shift_byte_count_lo; } #endif + mutex_lock(&hevc->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); + hevc->chunk = NULL; + mutex_unlock(&hevc->chunks_mutex); } else if (hevc->dec_result == DEC_RESULT_AGAIN) { /* stream base: stream buf empty or timeout @@ -9691,7 +11360,7 @@ static void vh265_work(struct work_struct *work) hevc->eos = 1; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((vdec->master || vdec->slave) && - READ_VREG(HEVC_AUX_DATA_SIZE) != 0) + aux_data_is_avaible(hevc)) dolby_get_meta(hevc); #endif check_pic_decoded_error(hevc, @@ -9722,7 +11391,10 @@ static void vh265_work(struct work_struct *work) hevc->shift_byte_count_lo; } #endif + mutex_lock(&hevc->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); + hevc->chunk = NULL; + mutex_unlock(&hevc->chunks_mutex); } else if (hevc->dec_result == DEC_RESULT_FORCE_EXIT) { hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, "%s: force exit\n", @@ -9762,8 +11434,10 @@ static void vh265_work(struct work_struct *work) #endif /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - + if (vdec->parallel_dec == 1) + vdec_core_finish_run(vdec, CORE_MASK_HEVC); + else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); if (hevc->vdec_cb) hevc->vdec_cb(hw_to_vdec(hevc), hevc->vdec_cb_arg); @@ -9775,11 +11449,12 @@ static int vh265_hw_ctx_restore(struct hevc_state_s *hevc) vh265_prot_init(hevc); return 0; } - static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; + int tvp = vdec_secure(hw_to_vdec(hevc)) ? + CODEC_MM_FLAGS_TVP : 0; bool ret = 0; if (step == 0x12) return 0; @@ -9788,6 +11463,29 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (hevc->eos) return 0; + if (!hevc->first_sc_checked && hevc->mmu_enable) { + int size = decoder_mmu_box_sc_check(hevc->mmu_box, tvp); + hevc->first_sc_checked =1; + hevc_print(hevc, 0, + "vh265 cached=%d need_size=%d speed= %d ms\n", + size, (hevc->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - hevc->sc_start_time) * 1000/HZ); + } + if (vdec_stream_based(vdec) && (hevc->init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < pre_decode_buf_level) + return 0; + } + #ifdef AGAIN_HAS_THRESHOLD if (hevc->next_again_flag && (!vdec_frame_based(vdec))) { @@ -9795,8 +11493,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) READ_PARSER_REG(PARSER_VIDEO_WP); if (parser_wr_ptr >= hevc->pre_parser_wr_ptr && (parser_wr_ptr - hevc->pre_parser_wr_ptr) < - again_threshold) + again_threshold) { + int r = vdec_sync_input(vdec); + hevc_print(hevc, + PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); return 0; + } } #endif @@ -9816,11 +11518,40 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) PRINT_FLAG_VDEC_DETAIL, "%s=>%d\r\n", __func__, ret); } + +#ifdef CONSTRAIN_MAX_BUF_NUM + if (hevc->pic_list_init_flag == 3) { + if (run_ready_max_vf_only_num > 0 && + get_vf_ref_only_buf_count(hevc) >= + run_ready_max_vf_only_num + ) + ret = 0; + if (run_ready_display_q_num > 0 && + kfifo_len(&hevc->display_q) >= + run_ready_display_q_num) + ret = 0; + + /*avoid more buffers consumed when + switching resolution*/ + if (run_ready_max_buf_num == 0xff && + get_used_buf_count(hevc) >= + get_work_pic_num(hevc)) + ret = 0; + else if (run_ready_max_buf_num && + get_used_buf_count(hevc) >= + run_ready_max_buf_num) + ret = 0; + } +#endif + if (ret) not_run_ready[hevc->index] = 0; else not_run_ready[hevc->index]++; - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + if (vdec->parallel_dec == 1) + return ret ? (CORE_MASK_HEVC) : 0; + else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -9834,7 +11565,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, run_count[hevc->index]++; hevc->vdec_cb_arg = arg; hevc->vdec_cb = callback; - + hevc->aux_data_dirty = 1; hevc_reset_core(vdec); #ifdef AGAIN_HAS_THRESHOLD @@ -9846,7 +11577,6 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (r < 0) { input_empty[hevc->index]++; hevc->dec_result = DEC_RESULT_AGAIN; - hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, "ammvdec_vh265: Insufficient data\n"); @@ -9855,7 +11585,6 @@ static void run(struct vdec_s *vdec, unsigned long mask, } input_empty[hevc->index] = 0; hevc->dec_result = DEC_RESULT_NONE; - if (vdec_frame_based(vdec) && ((get_dbg_flag(hevc) & PRINT_FLAG_VDEC_STATUS) || is_log_enable(hevc))) @@ -9883,8 +11612,15 @@ static void run(struct vdec_s *vdec, unsigned long mask, if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) && input_frame_based(vdec)) { int jj; - u8 *data = ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap(hevc->chunk->block->start + + hevc->chunk->offset, r); + else + data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < r; jj++) { if ((jj & 0xf) == 0) hevc_print(hevc, PRINT_FRAMEBASE_DATA, @@ -9895,32 +11631,72 @@ static void run(struct vdec_s *vdec, unsigned long mask, hevc_print_cont(hevc, PRINT_FRAMEBASE_DATA, "\n"); } - } - if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - loadr = amhevc_vdec_loadmc_ex(vdec, - "vh265_mc", hevc->fw->data); + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + if (tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->swap_addr); + } else { + if (hevc->mmu_enable) + if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) + loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, + "h265_mmu", hevc->fw->data); + else { + if (!hevc->is_4k) { + /* if an older version of the fw was loaded, */ + /* needs try to load noswap fw because the */ + /* old fw package dose not contain the swap fw.*/ + loadr = amhevc_vdec_loadmc_ex( + VFORMAT_HEVC, vdec, + "hevc_mmu_swap", + hevc->fw->data); + if (loadr < 0) + loadr = amhevc_vdec_loadmc_ex( + VFORMAT_HEVC, vdec, + "h265_mmu", + hevc->fw->data); + else + hevc->is_swap = true; + } else + loadr = amhevc_vdec_loadmc_ex( + VFORMAT_HEVC, vdec, + "h265_mmu", hevc->fw->data); + } else - loadr = amhevc_vdec_loadmc_ex(vdec, - "vh265_mc_mmu", hevc->fw->data); - } else - loadr = amhevc_vdec_loadmc_ex(vdec, - "vh265_mc", hevc->fw->data); + loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, + NULL, hevc->fw->data); - if (loadr < 0) { - amhevc_disable(); - hevc_print(hevc, 0, - "%s: Error amvdec_loadmc fail\n", - __func__); - return; + if (loadr < 0) { + amhevc_disable(); + hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", loadr); + hevc->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hevc->work); + return; + } + + if (tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + hevc->swap_addr = READ_VREG(HEVC_STREAM_SWAP_BUFFER2); +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + init_detrefill_buf(hevc); +#endif + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_HEVC; } - if (vh265_hw_ctx_restore(hevc) < 0) { vdec_schedule_work(&hevc->work); return; } - vdec_enable_input(vdec); WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); @@ -9929,6 +11705,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); r = hevc->chunk->size + (hevc->chunk->offset & (VDEC_FIFO_ALIGN - 1)); + hevc->decode_size = r; } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION else { @@ -10007,14 +11784,16 @@ static int amvdec_h265_probe(struct platform_device *pdev) hevc_print(hevc, 0, "%s\r\n", __func__); mutex_lock(&vh265_mutex); - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) && + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) && (parser_sei_enable & 0x100) == 0) parser_sei_enable = 7; /*old 1*/ hevc->m_ins_flag = 0; hevc->init_flag = 0; + hevc->first_sc_checked = 0; hevc->uninit_list = 0; hevc->fatal_error = 0; hevc->show_frame_num = 0; + hevc->frameinfo_enable = 1; #ifdef MULTI_INSTANCE_SUPPORT hevc->platform_dev = pdev; platform_set_drvdata(pdev, pdata); @@ -10028,7 +11807,7 @@ static int amvdec_h265_probe(struct platform_device *pdev) return -EFAULT; } if (mmu_enable_force == 0) { - if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXL + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL || double_write_mode == 0x10) hevc->mmu_enable = 0; else @@ -10046,7 +11825,6 @@ static int amvdec_h265_probe(struct platform_device *pdev) work_buf_size, DRIVER_NAME, &hevc->buf_start); if (ret < 0) { uninit_mmu_buffers(hevc); - devm_kfree(&pdev->dev, (void *)hevc); vfree(hevc); mutex_unlock(&vh265_mutex); return ret; @@ -10091,6 +11869,7 @@ static int amvdec_h265_probe(struct platform_device *pdev) hevc_local_uninit(hevc); uninit_mmu_buffers(hevc); vfree(hevc); + pdata->dec_status = NULL; mutex_unlock(&vh265_mutex); return -ENODEV; } @@ -10154,11 +11933,13 @@ static void vh265_dump_state(struct vdec_s *vdec) "====== %s\n", __func__); hevc_print(hevc, 0, - "width/height (%d/%d), reorder_pic_num %d buf count(bufspec size) %d\n", + "width/height (%d/%d), reorder_pic_num %d buf count(bufspec size) %d, video_signal_type 0x%x, is_swap %d\n", hevc->frame_width, hevc->frame_height, hevc->sps_num_reorder_pics_0, - get_work_pic_num(hevc) + get_work_pic_num(hevc), + hevc->video_signal_type_debug, + hevc->is_swap ); hevc_print(hevc, 0, @@ -10270,9 +12051,13 @@ static void vh265_dump_state(struct vdec_s *vdec) int jj; if (hevc->chunk && hevc->chunk->block && hevc->chunk->size > 0) { - u8 *data = - ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap(hevc->chunk->block->start + + hevc->chunk->offset, hevc->chunk->size); + else + data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; hevc_print(hevc, 0, "frame data size 0x%x\n", hevc->chunk->size); @@ -10289,11 +12074,15 @@ static void vh265_dump_state(struct vdec_s *vdec) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } } + static int ammvdec_h265_probe(struct platform_device *pdev) { @@ -10327,11 +12116,14 @@ static int ammvdec_h265_probe(struct platform_device *pdev) pdata->dump_state = vh265_dump_state; hevc->index = pdev->id; + hevc->m_ins_flag = 1; - if (pdata->use_vfm_path) + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); + hevc->frameinfo_enable = 1; + } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION else if (vdec_dual(pdata)) { struct hevc_state_s *hevc_pair = NULL; @@ -10382,6 +12174,12 @@ static int ammvdec_h265_probe(struct platform_device *pdev) else hevc->double_write_mode = double_write_mode; + if (get_config_int(pdata->config, "save_buffer_mode", + &config_val) == 0) + hevc->save_buffer_mode = config_val; + else + hevc->save_buffer_mode = 0; + /*use ptr config for max_pic_w, etc*/ if (get_config_int(pdata->config, "hevc_buf_width", &config_val) == 0) { @@ -10394,16 +12192,22 @@ static int ammvdec_h265_probe(struct platform_device *pdev) #endif } else { - hevc->vh265_amstream_dec_info.width = 0; - hevc->vh265_amstream_dec_info.height = 0; - hevc->vh265_amstream_dec_info.rate = 30; - hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; + if (pdata->sys_info) + hevc->vh265_amstream_dec_info = *pdata->sys_info; + else { + hevc->vh265_amstream_dec_info.width = 0; + hevc->vh265_amstream_dec_info.height = 0; + hevc->vh265_amstream_dec_info.rate = 30; + } hevc->double_write_mode = double_write_mode; } + if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2) + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2; + else + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; if (mmu_enable_force == 0) { - if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXL - || hevc->double_write_mode == 0x10) + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL) hevc->mmu_enable = 0; else hevc->mmu_enable = 1; @@ -10416,6 +12220,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /* devm_kfree(&pdev->dev, (void *)hevc);*/ if (hevc) vfree((void *)hevc); + pdata->dec_status = NULL; return -EFAULT; } #if 0 @@ -10431,28 +12236,21 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /* devm_kfree(&pdev->dev, (void *)hevc); */ if (hevc) vfree((void *)hevc); + pdata->dec_status = NULL; mutex_unlock(&vh265_mutex); return ret; } hevc->buf_size = work_buf_size; #endif - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) && + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) && (parser_sei_enable & 0x100) == 0) parser_sei_enable = 7; - hevc->m_ins_flag = 1; hevc->init_flag = 0; + hevc->first_sc_checked = 0; hevc->uninit_list = 0; hevc->fatal_error = 0; hevc->show_frame_num = 0; - if (pdata == NULL) { - hevc_print(hevc, 0, - "\namvdec_h265 memory resource undefined.\n"); - uninit_mmu_buffers(hevc); - /* devm_kfree(&pdev->dev, (void *)hevc); */ - if (hevc) - vfree((void *)hevc); - return -EFAULT; - } + /* *hevc->mc_buf_spec.buf_end = pdata->mem_end + 1; *for (i = 0; i < WORK_BUF_SPEC_NUM; i++) @@ -10481,6 +12279,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /* devm_kfree(&pdev->dev, (void *)hevc); */ if (hevc) vfree((void *)hevc); + pdata->dec_status = NULL; return -ENODEV; } @@ -10489,9 +12288,11 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /*set the max clk for smooth playing...*/ hevc_source_changed(VFORMAT_HEVC, 3840, 2160, 60); - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_HEVC); + else + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); return 0; } @@ -10501,6 +12302,10 @@ static int ammvdec_h265_remove(struct platform_device *pdev) struct hevc_state_s *hevc = (struct hevc_state_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hevc); + + if (hevc == NULL) + return 0; if (get_dbg_flag(hevc)) hevc_print(hevc, 0, "%s\r\n", __func__); @@ -10508,12 +12313,14 @@ static int ammvdec_h265_remove(struct platform_device *pdev) vmh265_stop(hevc); /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ - - vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); + else + vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_DISCONNECTED); - if (hevc) - vfree((void *)hevc); + + vfree((void *)hevc); return 0; } @@ -10594,14 +12401,15 @@ static struct mconfig_node decoder_265_node; static int __init amvdec_h265_driver_init_module(void) { struct BuffInfo_s *p_buf_info; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - p_buf_info = &amvh265_workbuff_spec[1]; - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + p_buf_info = &amvh265_workbuff_spec[2]; + else + p_buf_info = &amvh265_workbuff_spec[1]; + } else p_buf_info = &amvh265_workbuff_spec[0]; -#else - p_buf_info = &amvh265_workbuff_spec[0]; -#endif + init_buff_spec(NULL, p_buf_info); work_buf_size = (p_buf_info->end_adr - p_buf_info->start_adr @@ -10638,10 +12446,13 @@ static int __init amvdec_h265_driver_init_module(void) if (is_meson_m8m2_cpu()) { /* m8m2 support 4k */ amvdec_h265_profile.profile = "4k"; - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { amvdec_h265_profile.profile = - "4k, 9bit, 10bit, dwrite, compressed"; - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_MG9TV) + "8k, 8bit, 10bit, dwrite, compressed"; + }else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) { + amvdec_h265_profile.profile = + "4k, 8bit, 10bit, dwrite, compressed"; + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_MG9TV) amvdec_h265_profile.profile = "4k"; } #endif @@ -10776,6 +12587,17 @@ MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); module_param(buf_alloc_size, uint, 0664); MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); +#ifdef CONSTRAIN_MAX_BUF_NUM +module_param(run_ready_max_vf_only_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); + +module_param(run_ready_display_q_num, uint, 0664); +MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); + +module_param(run_ready_max_buf_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); +#endif + #if 0 module_param(re_config_pic_flag, uint, 0664); MODULE_PARM_DESC(re_config_pic_flag, "\n re_config_pic_flag\n"); @@ -10864,6 +12686,10 @@ module_param_array(input_empty, uint, module_param_array(not_run_ready, uint, &max_decode_instance_num, 0664); + +module_param_array(ref_frame_mark_flag, uint, + &max_decode_instance_num, 0664); + #endif #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION module_param(dv_toggle_prov_name, uint, 0664); @@ -10871,6 +12697,9 @@ MODULE_PARM_DESC(dv_toggle_prov_name, "\n dv_toggle_prov_name\n"); module_param(dv_debug, uint, 0664); MODULE_PARM_DESC(dv_debug, "\n dv_debug\n"); + +module_param(force_bypass_dvenl, uint, 0664); +MODULE_PARM_DESC(force_bypass_dvenl, "\n force_bypass_dvenl\n"); #endif #ifdef AGAIN_HAS_THRESHOLD @@ -10882,6 +12711,9 @@ module_param(force_disp_pic_index, int, 0664); MODULE_PARM_DESC(force_disp_pic_index, "\n amvdec_h265 force_disp_pic_index\n"); +module_param(frmbase_cont_bitlevel, uint, 0664); +MODULE_PARM_DESC(frmbase_cont_bitlevel, "\n frmbase_cont_bitlevel\n"); + module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); @@ -10891,6 +12723,9 @@ MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); module_param(udebug_pause_val, uint, 0664); MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n"); + module_param(udebug_pause_decode_idx, uint, 0664); MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c index b5af67a2ffe4..1c69a5a41fd9 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c @@ -36,6 +36,10 @@ #include "../utils/decoder_bmmu_box.h" #include #include +#include + +#include + #ifdef CONFIG_AM_VDEC_MJPEG_LOG #define AMLOG @@ -166,6 +170,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) u32 reg, offset, pts, pts_valid = 0; struct vframe_s *vf = NULL; u64 pts_us64; + u32 frame_size; WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); @@ -175,7 +180,8 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) offset = READ_VREG(MREG_FRAME_OFFSET); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) == 0) + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 0, &pts_us64) == 0) pts_valid = 1; if ((reg & PICINFO_INTERLACE) == 0) { @@ -218,6 +224,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) vdec_count_info(gvs, 0, offset); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -275,6 +282,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) vfbuf_use[index]++; kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); #else /* send whole frame by weaving top & bottom field */ #ifdef NV21 @@ -303,6 +311,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) vdec_count_info(gvs, 0, offset); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -398,8 +407,7 @@ static void vmjpeg_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) - && (vf->index < DECODE_BUFFER_NUM_MAX) + if ((vf->index < DECODE_BUFFER_NUM_MAX) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(MREG_TO_AMRISC, vf->index + 1); vf->index = DECODE_BUFFER_NUM_MAX; @@ -418,6 +426,9 @@ static void vmjpeg_put_timer_func(unsigned long arg) int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (0 != frame_dur) @@ -746,11 +757,12 @@ static s32 vmjpeg_init(void) return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_MJPEG, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_MJPEG, NULL, buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("MJPEG: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -840,6 +852,7 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev) mutex_unlock(&vmjpeg_mutex); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; return -ENODEV; } diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c index a0b449324efe..38c08e1e113a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,9 @@ #include #include "../utils/firmware.h" +#include + + #define MEM_NAME "codec_mmjpeg" #define DRIVER_NAME "ammvdec_mjpeg" @@ -59,7 +63,10 @@ #define MREG_TO_AMRISC AV_SCRATCH_8 #define MREG_FROM_AMRISC AV_SCRATCH_9 #define MREG_FRAME_OFFSET AV_SCRATCH_A -#define DEC_STATUS_REG AV_SCRATCH_J +#define DEC_STATUS_REG AV_SCRATCH_F +#define MREG_PIC_WIDTH AV_SCRATCH_B +#define MREG_PIC_HEIGHT AV_SCRATCH_C +#define DECODE_STOP_POS AV_SCRATCH_K #define PICINFO_BUF_IDX_MASK 0x0007 #define PICINFO_AVI1 0x0080 @@ -73,8 +80,15 @@ #define DEFAULT_MEM_SIZE (32*SZ_1M) static int debug_enable; +static u32 udebug_flag; #define DECODE_ID(hw) (hw_to_vdec(hw)->id) +static unsigned int radr; +static unsigned int rval; +#define VMJPEG_DEV_NUM 9 +static unsigned int max_decode_instance_num = VMJPEG_DEV_NUM; +static unsigned int max_process_time[VMJPEG_DEV_NUM]; +static unsigned int decode_timeout_val = 200; static struct vframe_s *vmjpeg_vf_peek(void *); static struct vframe_s *vmjpeg_vf_get(void *); static void vmjpeg_vf_put(struct vframe_s *, void *); @@ -82,6 +96,36 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *); static int vmjpeg_event_cb(int type, void *data, void *private_data); static void vmjpeg_work(struct work_struct *work); static int pre_decode_buf_level = 0x800; +#undef pr_info +#define pr_info printk +unsigned int mmjpeg_debug_mask = 0xff; +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_RUN_FLOW 0X0001 +#define PRINT_FLAG_TIMEINFO 0x0002 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_VLD_DETAIL 0x0008 +#define PRINT_FLAG_DEC_DETAIL 0x0010 +#define PRINT_FLAG_BUFFER_DETAIL 0x0020 +#define PRINT_FLAG_RESTORE 0x0040 +#define PRINT_FRAME_NUM 0x0080 +#define PRINT_FLAG_FORCE_DONE 0x0100 +#define PRINT_FRAMEBASE_DATA 0x0400 +int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((debug_enable & debug_flag) && + ((1 << index) & mmjpeg_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} static const char vmjpeg_dec_id[] = "vmmjpeg-dev"; @@ -152,15 +196,33 @@ struct vdec_mjpeg_hw_s { void *vdec_cb_arg; struct firmware_s *fw; struct timer_list check_timer; - unsigned decode_timeout_count; + u32 decode_timeout_count; + u32 start_process_time; + u32 last_vld_level; u8 eos; - u32 frame_num, put_num; + u32 frame_num; + u32 put_num; + u32 run_count; + u32 not_run_ready; + u32 input_empty; + u32 peek_num; + u32 get_num; }; +static void reset_process_time(struct vdec_mjpeg_hw_s *hw); static void set_frame_info(struct vdec_mjpeg_hw_s *hw, struct vframe_s *vf) { - vf->width = hw->frame_width; - vf->height = hw->frame_height; + u32 temp; + temp = READ_VREG(MREG_PIC_WIDTH); + if (temp > 1920) + vf->width = hw->frame_width = 1920; + else if (temp > 0) + vf->width = hw->frame_width = temp; + temp = READ_VREG(MREG_PIC_HEIGHT); + if (temp > 1088) + vf->height = hw->frame_height = 1088; + else if (temp > 0) + vf->height = hw->frame_height = temp; vf->duration = hw->frame_dur; vf->ratio_control = 0; vf->duration_pulldown = 0; @@ -185,16 +247,23 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) struct vframe_s *vf = NULL; u32 index, offset = 0, pts; u64 pts_us64; - - if (debug_enable & 0x1) - pr_info("%s: %d\n", __func__, __LINE__); - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + u32 frame_size; if (!hw) return IRQ_HANDLED; + if (hw->eos) return IRQ_HANDLED; + reset_process_time(hw); + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + if (READ_VREG(AV_SCRATCH_D) != 0 && + (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { + pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_D), + READ_VREG(AV_SCRATCH_E)); + WRITE_VREG(AV_SCRATCH_D, 0); + return IRQ_HANDLED; + } + reg = READ_VREG(MREG_FROM_AMRISC); index = READ_VREG(AV_SCRATCH_5); @@ -222,7 +291,8 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) } else { offset = READ_VREG(MREG_FRAME_OFFSET); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 3000, &pts_us64) == 0) { vf->pts = pts; vf->pts_us64 = pts_us64; @@ -235,15 +305,20 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) hw->vfbuf_use[index]++; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - + ATRACE_COUNTER(MODULE_NAME, vf->pts); hw->frame_num++; + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:frame num:%d,pts=%d,pts64=%lld. dur=%d\n", + __func__, hw->frame_num, + vf->pts, vf->pts_us64, vf->duration); + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); hw->dec_result = DEC_RESULT_DONE; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return IRQ_HANDLED; } @@ -256,7 +331,7 @@ static struct vframe_s *vmjpeg_vf_peek(void *op_arg) if (!hw) return NULL; - + hw->peek_num++; if (kfifo_peek(&hw->display_q, &vf)) return vf; @@ -271,7 +346,7 @@ static struct vframe_s *vmjpeg_vf_get(void *op_arg) if (!hw) return NULL; - + hw->get_num++; if (kfifo_get(&hw->display_q, &vf)) return vf; @@ -282,7 +357,8 @@ static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg) { struct vdec_s *vdec = op_arg; struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:put_num:%d\n", __func__, hw->put_num); hw->vfbuf_use[vf->index]--; kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); hw->put_num++; @@ -314,6 +390,10 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *op_arg) static int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + + if (!hw) + return -1; + vstatus->frame_width = hw->frame_width; vstatus->frame_height = hw->frame_height; if (0 != hw->frame_dur) @@ -345,7 +425,7 @@ static void vmjpeg_canvas_init(struct vdec_s *vdec) for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { int canvas; - canvas = vdec->get_canvas(i, 3); + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, decbuf_size, DRIVER_NAME, &buf_start); @@ -364,9 +444,19 @@ static void vmjpeg_canvas_init(struct vdec_s *vdec) addr += decbuf_uv_size; hw->buffer_spec[i].v_addr = addr; - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) + hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].v_canvas_index == -1) + hw->buffer_spec[i].v_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + } else { + canvas = vdec->get_canvas(i, 3); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + } canvas_config(hw->buffer_spec[i].y_canvas_index, hw->buffer_spec[i].y_addr, @@ -499,12 +589,129 @@ static void init_scaler(void) WRITE_VREG(PSCALE_RST, 0x0); } +static void vmjpeg_dump_state(struct vdec_s *vdec) +{ + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *)(vdec->private); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "====== %s\n", __func__); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "width/height (%d/%d)\n", + hw->frame_width, + hw->frame_height + ); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d input_empty %d\n", + input_frame_based(vdec), + hw->eos, + hw->stat, + hw->dec_result, + hw->frame_num, + hw->put_num, + hw->run_count, + hw->not_run_ready, + hw->input_empty + ); + if (vf_get_receiver(vdec->vf_provider_name)) { + enum receviver_start_e state = + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "\nreceiver(%s) state %d\n", + vdec->vf_provider_name, + state); + } + mmjpeg_debug_print(DECODE_ID(hw), 0, + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", + __func__, + kfifo_len(&hw->newframe_q), + VF_POOL_SIZE, + kfifo_len(&hw->display_q), + VF_POOL_SIZE, + hw->peek_num, + hw->get_num, + hw->put_num + ); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VIFF_BIT_CNT=0x%x\n", + READ_VREG(VIFF_BIT_CNT)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_LEVEL=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_WP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_RP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_RP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_RP)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_WP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_WP)); + if (input_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + if (hw->chunk && hw->chunk->block && + hw->chunk->size > 0) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + mmjpeg_debug_print(DECODE_ID(hw), 0, + "frame data size 0x%x\n", + hw->chunk->size); + for (jj = 0; jj < hw->chunk->size; jj++) { + if ((jj & 0xf) == 0) + mmjpeg_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + mmjpeg_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + mmjpeg_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + } +} +static void reset_process_time(struct vdec_mjpeg_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[DECODE_ID(hw)]) + max_process_time[DECODE_ID(hw)] = process_time; + } +} + +static void start_process_time(struct vdec_mjpeg_hw_s *hw) +{ + hw->decode_timeout_count = 2; + hw->start_process_time = jiffies; +} + static void timeout_process(struct vdec_mjpeg_hw_s *hw) { amvdec_stop(); - pr_info("%s decoder timeout\n", __func__); + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s decoder timeout\n", __func__); hw->dec_result = DEC_RESULT_DONE; - + reset_process_time(hw); vdec_schedule_work(&hw->work); } @@ -512,31 +719,43 @@ static void check_timer_func(unsigned long arg) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)arg; struct vdec_s *vdec = hw_to_vdec(hw); - if ((debug_enable & 0x2) != 0) { - pr_info("%s: status:nstatus=%d:%d\n", + int timeout_val = decode_timeout_val; + + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "%s: status:nstatus=%d:%d\n", __func__, vdec->status, vdec->next_status); - pr_info("%s: %d,buftl=%x:%x:%x:%x\n", + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "%s: %d,buftl=%x:%x:%x:%x\n", __func__, __LINE__, READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), READ_PARSER_REG(PARSER_VIDEO_WP), READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP)); - } - if ((debug_enable & 0x100) != 0) { - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - pr_info("vdec %d is forced to be disconnected\n", - debug_enable & 0xff); - debug_enable = 0; - return; + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; } - if (input_stream_based(vdec) - && READ_VREG(VLD_MEM_VIFIFO_LEVEL) <= 0x80) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); + if ((debug_enable == 0) && + (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && + (timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > timeout_val)) { + if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); } if (READ_VREG(DEC_STATUS_REG) == DEC_DECODE_TIMEOUT) { @@ -556,6 +775,7 @@ static void check_timer_func(unsigned long arg) } mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); } + static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index) { struct vdec_mjpeg_hw_s *hw = @@ -601,10 +821,7 @@ static s32 vmjpeg_init(struct vdec_s *vdec) fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; - if (tee_enabled()) { - size = 1; - pr_debug (" tee load\n"); - } else + size = get_firmware_data(VIDEO_DEC_MJPEG_MULTI, fw->data); if (size < 0) { pr_err("get firmware fail."); @@ -617,12 +834,18 @@ static s32 vmjpeg_init(struct vdec_s *vdec) hw->frame_width = hw->vmjpeg_amstream_dec_info.width; hw->frame_height = hw->vmjpeg_amstream_dec_info.height; - hw->frame_dur = hw->vmjpeg_amstream_dec_info.rate; + hw->frame_dur = ((hw->vmjpeg_amstream_dec_info.rate) ? + hw->vmjpeg_amstream_dec_info.rate : 3840); hw->saved_resolution = 0; hw->eos = 0; hw->init_flag = 0; hw->frame_num = 0; hw->put_num = 0; + hw->run_count = 0; + hw->not_run_ready = 0; + hw->input_empty = 0; + hw->peek_num = 0; + hw->get_num = 0; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) hw->vfbuf_use[i] = 0; @@ -656,16 +879,20 @@ static s32 vmjpeg_init(struct vdec_s *vdec) hw->check_timer.expires = jiffies + CHECK_INTERVAL; /*add_timer(&hw->check_timer);*/ hw->stat |= STAT_TIMER_ARM; + hw->stat |= STAT_ISR_REG; + WRITE_VREG(DECODE_STOP_POS, udebug_flag); INIT_WORK(&hw->work, vmjpeg_work); - + pr_info("w:h=%d:%d\n", hw->frame_width, hw->frame_height); return 0; } -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) +static unsigned long run_ready(struct vdec_s *vdec, + unsigned long mask) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + hw->not_run_ready++; if (hw->eos) return 0; if (vdec_stream_based(vdec) && (hw->init_flag == 0) @@ -682,7 +909,11 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (level < pre_decode_buf_level) return 0; } - return CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + hw->not_run_ready = 0; + if (vdec->parallel_dec == 1) + return CORE_MASK_VDEC_1; + else + return CORE_MASK_VDEC_1 | CORE_MASK_HEVC; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -690,11 +921,13 @@ static void run(struct vdec_s *vdec, unsigned long mask, { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - int i,ret = -1; + int i, ret; hw->vdec_cb_arg = arg; hw->vdec_cb = callback; + hw->run_count++; + vdec_reset_core(vdec); for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { if (hw->vfbuf_use[i] == 0) break; @@ -702,29 +935,42 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (i == DECODE_BUFFER_NUM_MAX) { hw->dec_result = DEC_RESULT_AGAIN; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return; } ret = vdec_prepare_input(vdec, &hw->chunk); - if (ret < 0) { - if (debug_enable & 0x1) { - pr_info("%s: %d,r=%d,buftl=%x:%x:%x\n", + if (ret <= 0) { + hw->input_empty++; + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s: %d,r=%d,buftl=%x:%x:%x\n", __func__, __LINE__, ret, READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), READ_PARSER_REG(PARSER_VIDEO_WP), READ_VREG(VLD_MEM_VIFIFO_WP)); - } + hw->dec_result = DEC_RESULT_AGAIN; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return; } - + hw->input_empty = 0; hw->dec_result = DEC_RESULT_NONE; - - if (amvdec_vdec_loadmc_ex(vdec, "vmmjpeg_mc",hw->fw->data) < 0) { - pr_err("%s: Error amvdec_loadmc fail\n", __func__); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_ex(VFORMAT_MJPEG, "mmjpeg", vdec, hw->fw->data); + if (ret < 0) { + pr_err("[%d] MMJPEG: the %s fw loading failed, err: %x\n", + vdec->id, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MJPEG; } /* if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) { pr_err("%s: Error amvdec_loadmc fail\n", __func__); @@ -736,42 +982,65 @@ static void run(struct vdec_s *vdec, unsigned long mask, vdec_enable_input(vdec); mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); #endif + hw->stat |= STAT_MC_LOAD; + start_process_time(hw); + hw->last_vld_level = 0; + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); amvdec_start(); vdec_enable_input(vdec); - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); - hw->decode_timeout_count = 2; + hw->stat |= STAT_VDEC_RUN; hw->init_flag = 1; - if (debug_enable&0x1) { - pr_info("%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_DECODE_CONTROL), - READ_VREG(VIFF_BIT_CNT), - READ_VREG(POWER_CTL_VLD), - READ_VREG(VLD_MEM_VIFIFO_START_PTR), - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), - READ_VREG(VLD_MEM_VIFIFO_CONTROL), - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), - READ_VREG(VLD_MEM_VIFIFO_END_PTR)); + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VLD_DECODE_CONTROL), + READ_VREG(VIFF_BIT_CNT), + READ_VREG(POWER_CTL_VLD), + READ_VREG(VLD_MEM_VIFIFO_START_PTR), + READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), + READ_VREG(VLD_MEM_VIFIFO_END_PTR)); +} +static void wait_vmjpeg_search_done(struct vdec_mjpeg_hw_s *hw) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; - } + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 1000) { + mmjpeg_debug_print(DECODE_ID(hw), 0, + "%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); } static void vmjpeg_work(struct work_struct *work) { struct vdec_mjpeg_hw_s *hw = container_of(work, struct vdec_mjpeg_hw_s, work); - if (debug_enable & 0x2) - pr_info("%s: result=%d,len=%d:%d\n", + struct vdec_s *vdec = hw_to_vdec(hw); + + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "%s: result=%d,len=%d:%d\n", __func__, hw->dec_result, kfifo_len(&hw->newframe_q), kfifo_len(&hw->display_q)); - if (hw->dec_result == DEC_RESULT_DONE) + if (hw->dec_result == DEC_RESULT_DONE) { vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - else if (hw->dec_result == DEC_RESULT_AGAIN) { + hw->chunk = NULL; + } else if (hw->dec_result == DEC_RESULT_AGAIN) { /* stream base: stream buf empty or timeout frame base: vdec_prepare_input fail @@ -784,20 +1053,37 @@ static void vmjpeg_work(struct work_struct *work) return; } } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { - pr_info("%s: force exit\n", - __func__); + pr_info("%s: force exit\n", __func__); + if (hw->stat & STAT_ISR_REG) { + amvdec_stop(); + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } } else if (hw->dec_result == DEC_RESULT_EOS) { - /*pr_info("%s: end of stream\n", - __func__);*/ - if (READ_VREG(VLD_MEM_VIFIFO_LEVEL) < 0x100) - hw->eos = 1; + pr_info("%s: end of stream\n", __func__); + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + hw->eos = 1; vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); } - amvdec_stop(); + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + wait_vmjpeg_search_done(hw); /* mark itself has all HW resource released and input released */ - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 + if (vdec->parallel_dec == 1) + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else { + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + } del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; @@ -805,18 +1091,54 @@ static void vmjpeg_work(struct work_struct *work) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); } -static int amvdec_mjpeg_probe(struct platform_device *pdev) +static int vmjpeg_stop(struct vdec_mjpeg_hw_s *hw) +{ + pr_info("%s ...count = %d\n", __func__, hw->frame_num); + + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + pr_info("%s amvdec_stop\n", __func__); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + cancel_work_sync(&hw->work); + hw->init_flag = 0; + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + + if (hw->fw) { + vfree(hw->fw); + hw->fw = NULL; + } + + return 0; +} + +static int ammvdec_mjpeg_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mjpeg_hw_s *hw = NULL; if (pdata == NULL) { - pr_info("amvdec_mjpeg memory resource undefined.\n"); + pr_info("ammvdec_mjpeg memory resource undefined.\n"); return -EFAULT; } hw = (struct vdec_mjpeg_hw_s *)devm_kzalloc(&pdev->dev, sizeof(struct vdec_mjpeg_hw_s), GFP_KERNEL); + hw = vzalloc(sizeof(struct vdec_mjpeg_hw_s)); if (hw == NULL) { pr_info("\nammvdec_mjpeg device data allocation failed\n"); return -ENOMEM; @@ -828,7 +1150,16 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev) pdata->run = run; pdata->run_ready = run_ready; pdata->irq_handler = vmjpeg_isr; + pdata->dump_state = vmjpeg_dump_state; + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + hw->buffer_spec[i].y_canvas_index = -1; + hw->buffer_spec[i].u_canvas_index = -1; + hw->buffer_spec[i].v_canvas_index = -1; + } + } if (pdata->use_vfm_path) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, @@ -847,48 +1178,62 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev) if (pdata->sys_info) hw->vmjpeg_amstream_dec_info = *pdata->sys_info; + vdec_source_changed(VFORMAT_MJPEG, + 1920, 1080, 60); if (vmjpeg_init(pdata) < 0) { - pr_info("amvdec_mjpeg init failed.\n"); + pr_info("ammvdec_mjpeg init failed.\n"); + if (hw) { + vfree(hw); + hw = NULL; + } + pdata->dec_status = NULL; return -ENODEV; } - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); + } return 0; } -static int amvdec_mjpeg_remove(struct platform_device *pdev) +static int ammvdec_mjpeg_remove(struct platform_device *pdev) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hw); + int i; + vmjpeg_stop(hw); - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - cancel_work_sync(&hw->work); - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - - vfree(hw->fw); - hw->fw = NULL; - - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - + if (vdec->parallel_dec == 1) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); + } + } + if (hw) { + vfree(hw); + hw = NULL; + } + pr_info("%s\n", __func__); return 0; } /****************************************/ -static struct platform_driver amvdec_mjpeg_driver = { - .probe = amvdec_mjpeg_probe, - .remove = amvdec_mjpeg_remove, +static struct platform_driver ammvdec_mjpeg_driver = { + .probe = ammvdec_mjpeg_probe, + .remove = ammvdec_mjpeg_remove, #ifdef CONFIG_PM .suspend = amvdec_suspend, .resume = amvdec_resume, @@ -898,24 +1243,24 @@ static struct platform_driver amvdec_mjpeg_driver = { } }; -static struct codec_profile_t amvdec_mjpeg_profile = { +static struct codec_profile_t ammvdec_mjpeg_profile = { .name = "mmjpeg", .profile = "" }; -static int __init amvdec_mjpeg_driver_init_module(void) +static int __init ammvdec_mjpeg_driver_init_module(void) { - if (platform_driver_register(&amvdec_mjpeg_driver)) { - pr_err("failed to register amvdec_mjpeg driver\n"); + if (platform_driver_register(&ammvdec_mjpeg_driver)) { + pr_err("failed to register ammvdec_mjpeg driver\n"); return -ENODEV; } - vcodec_profile_register(&amvdec_mjpeg_profile); + vcodec_profile_register(&ammvdec_mjpeg_profile); return 0; } -static void __exit amvdec_mjpeg_driver_remove_module(void) +static void __exit ammvdec_mjpeg_driver_remove_module(void) { - platform_driver_unregister(&amvdec_mjpeg_driver); + platform_driver_unregister(&ammvdec_mjpeg_driver); } /****************************************/ @@ -924,8 +1269,23 @@ MODULE_PARM_DESC(debug_enable, "\n debug enable\n"); module_param(pre_decode_buf_level, int, 0664); MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n"); -module_init(amvdec_mjpeg_driver_init_module); -module_exit(amvdec_mjpeg_driver_remove_module); +module_param(udebug_flag, uint, 0664); +MODULE_PARM_DESC(udebug_flag, "\n amvdec_mmpeg12 udebug_flag\n"); + + +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mjpeg decode_timeout_val\n"); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_init(ammvdec_mjpeg_driver_init_module); +module_exit(ammvdec_mjpeg_driver_remove_module); MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile index 9a07229b0cb0..34f78c477e30 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile @@ -1,2 +1,5 @@ obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12) += amvdec_mpeg12.o amvdec_mpeg12-objs += vmpeg12.o + +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI) += amvdec_mmpeg12.o +amvdec_mmpeg12-objs += vmpeg12_multi.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c index 2e3a90edea7c..ab54188c87e5 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c @@ -41,6 +41,10 @@ #include "../utils/decoder_bmmu_box.h" #include #include +#include + +#include + #ifdef CONFIG_AM_VDEC_MPEG12_LOG #define AMLOG @@ -56,6 +60,7 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); #include "../utils/amvdec.h" #include "../utils/vdec.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" #define DRIVER_NAME "amvdec_mpeg12" #define MODULE_NAME "amvdec_mpeg12" @@ -171,6 +176,7 @@ static int ccbuf_phyAddress_is_remaped_nocache; static u32 lastpts; static u32 fr_hint_status; static u32 last_offset; +static u32 ratio_control; static DEFINE_SPINLOCK(lock); @@ -194,6 +200,10 @@ static struct work_struct reset_work; static struct work_struct set_clk_work; static bool is_reset; +static DEFINE_MUTEX(userdata_mutex); + +static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len); + struct mpeg12_userdata_recored_t { struct userdata_meta_info_t meta_info; u32 rec_start; @@ -286,6 +296,8 @@ static void set_frame_info(struct vframe_s *vf) else vf->ratio_control = 0; + ratio_control = vf->ratio_control; + amlog_level_if(first, LOG_LEVEL_INFO, "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", frame_width, frame_height, frame_dur, @@ -756,8 +768,8 @@ static void userdata_push_do_work(struct work_struct *work) DMA_FROM_DEVICE); } - - if (p_userdata_mgr) { + mutex_lock(&userdata_mutex); + if (p_userdata_mgr && ccbuf_phyAddress_virt) { int new_wp; new_wp = reg & 0xffff; @@ -769,6 +781,7 @@ static void userdata_push_do_work(struct work_struct *work) memcpy(head_info, pdata, 8); } else memset(head_info, 0, 8); + mutex_unlock(&userdata_mutex); aml_swap_data(head_info, 8); wp = (head_info[0] << 8 | head_info[1]); @@ -854,6 +867,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) u32 reg, info, seqinfo, offset, pts, pts_valid = 0; struct vframe_s *vf; u64 pts_us64 = 0; + u32 frame_size; WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); @@ -870,7 +884,8 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) first_i_frame_ready = 1; if ((pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) == 0) + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 0, &pts_us64) == 0) && (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) || ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P))) @@ -928,7 +943,9 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) } set_frame_info(vf); - vf->signal_type = 0; + /*pr_info("video signal type:0x%x\n", + READ_VREG(AV_SCRATCH_H));*/ + vf->signal_type = READ_VREG(AV_SCRATCH_H); vf->index = index; #ifdef NV21 vf->type = @@ -986,6 +1003,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1071,6 +1089,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1123,6 +1142,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1163,6 +1183,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) } else { kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1254,6 +1275,7 @@ static void vmpeg12_ppmgr_reset(void) #endif static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit); +static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec); static void reset_do_work(struct work_struct *work) { @@ -1267,6 +1289,7 @@ static void reset_do_work(struct work_struct *work) vf_reg_provider(&vmpeg_vf_prov); #endif vmpeg12_prot_init(); + vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); vmpeg12_reset_userdata_fifo(vdec, 1); #ifdef DUMP_USER_DATA last_wp = 0; @@ -1277,8 +1300,7 @@ static void reset_do_work(struct work_struct *work) static void vmpeg12_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { + { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; @@ -1342,7 +1364,9 @@ static void vmpeg_put_timer_func(unsigned long arg) } } - schedule_work(&set_clk_work); + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; @@ -1351,6 +1375,9 @@ static void vmpeg_put_timer_func(unsigned long arg) int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (frame_dur != 0) @@ -1369,6 +1396,7 @@ int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->total_data = gvs->total_data; vstatus->samp_cnt = gvs->samp_cnt; vstatus->offset = gvs->offset; + vstatus->ratio_control = ratio_control; snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); @@ -1381,10 +1409,10 @@ int vmpeg12_set_isreset(struct vdec_s *vdec, int isreset) return 0; } -static DEFINE_MUTEX(userdata_mutex); -void vmpeg12_crate_userdata_manager(u8 *userdata_buf, int buf_len) + +static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len) { mutex_lock(&userdata_mutex); @@ -1400,7 +1428,7 @@ void vmpeg12_crate_userdata_manager(u8 *userdata_buf, int buf_len) mutex_unlock(&userdata_mutex); } -void vmpeg12_destroy_userdata_manager(void) +static void vmpeg12_destroy_userdata_manager(void) { mutex_lock(&userdata_mutex); @@ -1473,13 +1501,12 @@ static int vmpeg12_user_data_read(struct vdec_s *vdec, u8 *rec_data_start; u8 *pdest_buf; struct mpeg12_userdata_recored_t *p_userdata_rec; - - u32 data_size; u32 res; int copy_ok = 1; - pdest_buf = (void *)(puserdata_para->pbuf_addr); + pdest_buf = puserdata_para->pbuf_addr; + mutex_lock(&userdata_mutex); if (!p_userdata_mgr) { @@ -1630,9 +1657,8 @@ static int vmpeg12_user_data_read(struct vdec_s *vdec, } } - res = (u32)copy_to_user((void *)&puserdata_para->meta_info, - (void *)&p_userdata_rec->meta_info, - sizeof(p_userdata_rec->meta_info)); + + puserdata_para->meta_info = p_userdata_rec->meta_info; if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) puserdata_para->meta_info.records_in_que = @@ -1668,6 +1694,11 @@ static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit) mutex_unlock(&userdata_mutex); } +static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + static int vmpeg12_vdec_info_init(void) { gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); @@ -1721,12 +1752,13 @@ static int vmpeg12_canvas_init(void) = (u32)buf_start; ccbuf_phyAddress_virt - = codec_mm_phys_to_virt(ccbuf_phyAddress); + = codec_mm_phys_to_virt( + ccbuf_phyAddress); if (!ccbuf_phyAddress_virt) { ccbuf_phyAddress_virt - = ioremap_nocache( - ccbuf_phyAddress, - CCBUF_SIZE); + = codec_mm_vmap( + ccbuf_phyAddress, + CCBUF_SIZE); ccbuf_phyAddress_is_remaped_nocache = 1; } } @@ -1767,13 +1799,13 @@ static int vmpeg12_canvas_init(void) static int vmpeg12_prot_init(void) { int ret; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { int save_reg = READ_VREG(POWER_CTL_VLD); WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); WRITE_VREG(DOS_SW_RESET0, 0); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); @@ -1875,10 +1907,20 @@ static void vmpeg12_local_init(void) for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) vfbuf_use[i] = 0; - if (mm_blk_handle) { + mutex_lock(&userdata_mutex); + if (p_userdata_mgr) { + vfree(p_userdata_mgr); + p_userdata_mgr = NULL; + } + if (ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); + ccbuf_phyAddress_virt = NULL; + ccbuf_phyAddress = 0; + ccbuf_phyAddress_is_remaped_nocache = 0; decoder_bmmu_box_free(mm_blk_handle); mm_blk_handle = NULL; + mutex_unlock(&userdata_mutex); } mm_blk_handle = decoder_bmmu_box_alloc_box( @@ -1921,11 +1963,12 @@ static s32 vmpeg12_init(void) return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_MPEG12, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_MPEG12, "mpeg12", buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("MPEG12: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1957,13 +2000,14 @@ static s32 vmpeg12_init(void) vf_reg_provider(&vmpeg_vf_prov); #endif if (vmpeg12_amstream_dec_info.rate != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long) vmpeg12_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -2015,7 +2059,7 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev) pdata->user_data_read = vmpeg12_user_data_read; pdata->reset_userdata_fifo = vmpeg12_reset_userdata_fifo; - + pdata->wakeup_userdata_poll = vmpeg12_wakeup_userdata_poll; is_reset = 0; vmpeg12_vdec_info_init(); @@ -2025,14 +2069,14 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev) amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg12 init failed.\n"); kfree(gvs); gvs = NULL; - + pdata->dec_status = NULL; return -ENODEV; } vdec = pdata; #ifdef DUMP_USER_DATA amvdec_mpeg12_init_userdata_dump(); #endif - vmpeg12_crate_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); + vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); INIT_WORK(&userdata_push_work, userdata_push_do_work); INIT_WORK(¬ify_work, vmpeg12_notify_work); @@ -2055,7 +2099,6 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) cancel_work_sync(&userdata_push_work); cancel_work_sync(¬ify_work); cancel_work_sync(&reset_work); - cancel_work_sync(&set_clk_work); if (stat & STAT_VDEC_RUN) { amvdec_stop(); @@ -2072,8 +2115,9 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) stat &= ~STAT_TIMER_ARM; } + cancel_work_sync(&set_clk_work); if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); fr_hint_status = VDEC_NO_NEED_HINT; @@ -2084,7 +2128,7 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) amvdec_disable(); if (ccbuf_phyAddress_is_remaped_nocache) - iounmap(ccbuf_phyAddress_virt); + codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); ccbuf_phyAddress_virt = NULL; ccbuf_phyAddress = 0; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c new file mode 100644 index 000000000000..a8962ddd9f70 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -0,0 +1,2854 @@ +/* + * drivers/amlogic/amports/vmpeg12.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../../../stream_input/amports/amports_priv.h" + +#include "../utils/vdec_input.h" +#include "../utils/vdec.h" +#include "../utils/amvdec.h" +#include "../utils/decoder_mmu_box.h" +#include "../utils/decoder_bmmu_box.h" +#include +#include +#include "../utils/firmware.h" + + +#define MEM_NAME "codec_mmpeg12" +#define CHECK_INTERVAL (HZ/100) + +#define DRIVER_NAME "ammvdec_mpeg12" +#define MODULE_NAME "ammvdec_mpeg12" +#define MREG_REF0 AV_SCRATCH_2 +#define MREG_REF1 AV_SCRATCH_3 +/* protocol registers */ +#define MREG_SEQ_INFO AV_SCRATCH_4 +#define MREG_PIC_INFO AV_SCRATCH_5 +#define MREG_PIC_WIDTH AV_SCRATCH_6 +#define MREG_PIC_HEIGHT AV_SCRATCH_7 +#define MREG_INPUT AV_SCRATCH_8 /*input_type*/ +#define MREG_BUFFEROUT AV_SCRATCH_9 /*FROM_AMRISC_REG*/ + +#define MREG_CMD AV_SCRATCH_A +#define MREG_CO_MV_START AV_SCRATCH_B +#define MREG_ERROR_COUNT AV_SCRATCH_C +#define MREG_FRAME_OFFSET AV_SCRATCH_D +#define MREG_WAIT_BUFFER AV_SCRATCH_E +#define MREG_FATAL_ERROR AV_SCRATCH_F + +#define PICINFO_ERROR 0x80000000 +#define PICINFO_TYPE_MASK 0x00030000 +#define PICINFO_TYPE_I 0x00000000 +#define PICINFO_TYPE_P 0x00010000 +#define PICINFO_TYPE_B 0x00020000 + +#define GET_SLICE_TYPE(type) ("IPB###"[(type&PICINFO_TYPE_MASK)>>16]) +#define PICINFO_PROG 0x8000 +#define PICINFO_RPT_FIRST 0x4000 +#define PICINFO_TOP_FIRST 0x2000 +#define PICINFO_FRAME 0x1000 +#define TOP_FIELD 0x1000 +#define BOTTOM_FIELD 0x2000 +#define FRAME_PICTURE 0x3000 +#define FRAME_PICTURE_MASK 0x3000 + +#define SEQINFO_EXT_AVAILABLE 0x80000000 +#define SEQINFO_PROG 0x00010000 +#define CCBUF_SIZE (5*1024) + +#define VF_POOL_SIZE 32 +#define DECODE_BUFFER_NUM_MAX 8 +#define PUT_INTERVAL (HZ/100) +#define WORKSPACE_SIZE (4*SZ_64K) /*swap&ccbuf&matirx&MV*/ +#define CTX_LMEM_SWAP_OFFSET 0 +#define CTX_CCBUF_OFFSET 0x800 +#define CTX_QUANT_MATRIX_OFFSET (CTX_CCBUF_OFFSET + 5*1024) +#define CTX_CO_MV_OFFSET (CTX_QUANT_MATRIX_OFFSET + 1*1024) +#define CTX_DECBUF_OFFSET (CTX_CO_MV_OFFSET + 0x11000) + +#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) +#define DEFAULT_MEM_SIZE (32*SZ_1M) +static u32 buf_size = 32 * 1024 * 1024; +static int pre_decode_buf_level = 0x800; +static u32 dec_control; +static u32 error_frame_skip_level; +static u32 stat; +static u32 udebug_flag; +static unsigned int radr; +static unsigned int rval; + +#define VMPEG12_DEV_NUM 9 +static unsigned int max_decode_instance_num = VMPEG12_DEV_NUM; +static unsigned int max_process_time[VMPEG12_DEV_NUM]; +static unsigned int decode_timeout_val = 100; +#define INCPTR(p) ptr_atomic_wrap_inc(&p) + +#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002 +#define DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE 0x0004 +#define DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE 0x0008 +#define DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE 0x0010 +#define DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE 0x0020 +#define DEC_CONTROL_INTERNAL_MASK 0x0fff +#define DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE 0x1000 + +#define INTERLACE_SEQ_ALWAYS + +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +#endif + +#define AGAIN_HAS_THRESHOLD + +#ifdef AGAIN_HAS_THRESHOLD +u32 again_threshold = 0x40; +#endif + +/* +#define DUMP_USER_DATA +*/ + +enum { + FRAME_REPEAT_TOP, + FRAME_REPEAT_BOT, + FRAME_REPEAT_NONE +}; +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 +#define DEC_RESULT_ERROR 3 +#define DEC_RESULT_FORCE_EXIT 4 +#define DEC_RESULT_EOS 5 +#define DEC_RESULT_GET_DATA 6 +#define DEC_RESULT_GET_DATA_RETRY 7 + +#define DEC_DECODE_TIMEOUT 0x21 +#define DECODE_ID(hw) (hw_to_vdec(hw)->id) +#define DECODE_STOP_POS AV_SCRATCH_K + +static struct vframe_s *vmpeg_vf_peek(void *); +static struct vframe_s *vmpeg_vf_get(void *); +static void vmpeg_vf_put(struct vframe_s *, void *); +static int vmpeg_vf_states(struct vframe_states *states, void *); +static int vmpeg_event_cb(int type, void *data, void *private_data); + +struct mmpeg2_userdata_record_t { + struct userdata_meta_info_t meta_info; + u32 rec_start; + u32 rec_len; +}; + +#define USERDATA_FIFO_NUM 256 +#define MAX_FREE_USERDATA_NODES 5 + +struct mmpeg2_userdata_info_t { + struct mmpeg2_userdata_record_t records[USERDATA_FIFO_NUM]; + u8 *data_buf; + u8 *data_buf_end; + u32 buf_len; + u32 read_index; + u32 write_index; + u32 last_wp; +}; +#define MAX_UD_RECORDS 5 + +struct vdec_mpeg12_hw_s { + spinlock_t lock; + struct platform_device *platform_dev; + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + struct vframe_s vfpool[VF_POOL_SIZE]; + s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; + u32 frame_width; + u32 frame_height; + u32 frame_dur; + u32 frame_prog; + u32 seqinfo; + u32 ctx_valid; + u32 dec_control; + void *mm_blk_handle; + struct vframe_chunk_s *chunk; + u32 stat; + u8 init_flag; + unsigned long buf_start; + u32 buf_size; + u32 reg_pic_width; + u32 reg_pic_height; + u32 reg_mpeg1_2_reg; + u32 reg_pic_head_info; + u32 reg_f_code_reg; + u32 reg_slice_ver_pos_pic_type; + u32 reg_vcop_ctrl_reg; + u32 reg_mb_info; + u32 reg_signal_type; + u32 frame_num; + struct timer_list check_timer; + u32 decode_timeout_count; + u32 start_process_time; + u32 last_vld_level; + u32 eos; + u32 buffer_info[DECODE_BUFFER_NUM_MAX]; + u32 pts[DECODE_BUFFER_NUM_MAX]; + u64 pts64[DECODE_BUFFER_NUM_MAX]; + bool pts_valid[DECODE_BUFFER_NUM_MAX]; + u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; + struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; + struct dec_sysinfo vmpeg12_amstream_dec_info; + + s32 refs[2]; + int dec_result; + struct work_struct work; + struct work_struct notify_work; + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; + unsigned long ccbuf_phyAddress; + void *ccbuf_phyAddress_virt; + unsigned long ccbuf_phyAddress_is_remaped_nocache; + u32 frame_rpt_state; +/* for error handling */ + s32 frame_force_skip_flag; + s32 error_frame_skip_level; + s32 wait_buffer_counter; + u32 first_i_frame_ready; + u32 run_count; + u32 not_run_ready; + u32 input_empty; + u32 put_num; + u32 peek_num; + u32 get_num; + u32 drop_frame_count; + u32 buffer_not_ready; + u32 ratio_control; + int frameinfo_enable; + struct firmware_s *fw; + u32 canvas_mode; +#ifdef AGAIN_HAS_THRESHOLD + u32 pre_parser_wr_ptr; + u8 next_again_flag; +#endif + struct work_struct userdata_push_work; + struct mutex userdata_mutex; + struct mmpeg2_userdata_info_t userdata_info; + struct mmpeg2_userdata_record_t ud_record[MAX_UD_RECORDS]; + int cur_ud_idx; + u8 *user_data_buffer; + int wait_for_udr_send; + u32 ucode_cc_last_wp; + u32 notify_ucode_cc_last_wp; + u32 notify_data_cc_last_wp; + +#ifdef DUMP_USER_DATA +#define MAX_USER_DATA_SIZE 1572864 + void *user_data_dump_buf; + unsigned char *pdump_buf_cur_start; + int total_len; + int bskip; + int n_userdata_id; + u32 reference[MAX_UD_RECORDS]; +#endif +}; +static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw); +static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw); +static void reset_process_time(struct vdec_mpeg12_hw_s *hw); +static struct vdec_info gvs; +static int debug_enable; +/*static struct work_struct userdata_push_work;*/ +#undef pr_info +#define pr_info printk +unsigned int mpeg12_debug_mask = 0xff; +/*static int counter_max = 5;*/ + +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_RUN_FLOW 0X0001 +#define PRINT_FLAG_TIMEINFO 0x0002 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_VLD_DETAIL 0x0008 +#define PRINT_FLAG_DEC_DETAIL 0x0010 +#define PRINT_FLAG_BUFFER_DETAIL 0x0020 +#define PRINT_FLAG_RESTORE 0x0040 +#define PRINT_FRAME_NUM 0x0080 +#define PRINT_FLAG_FORCE_DONE 0x0100 +#define PRINT_FLAG_COUNTER 0X0200 +#define PRINT_FRAMEBASE_DATA 0x0400 +#define PRINT_FLAG_VDEC_STATUS 0x0800 +#define PRINT_FLAG_PARA_DATA 0x1000 +#define PRINT_FLAG_USERDATA_DETAIL 0x2000 + + + +int debug_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((debug_enable & debug_flag) && + ((1 << index) & mpeg12_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} + + +/*static bool is_reset;*/ +#define PROVIDER_NAME "vdec.mpeg12" +static const struct vframe_operations_s vf_provider_ops = { + .peek = vmpeg_vf_peek, + .get = vmpeg_vf_get, + .put = vmpeg_vf_put, + .event_cb = vmpeg_event_cb, + .vf_states = vmpeg_vf_states, +}; + + +static const u32 frame_rate_tab[16] = { + 96000 / 30, 96000000 / 23976, 96000 / 24, 96000 / 25, + 9600000 / 2997, 96000 / 30, 96000 / 50, 9600000 / 5994, + 96000 / 60, + /* > 8 reserved, use 24 */ + 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, + 96000 / 24, 96000 / 24, 96000 / 24 +}; + + +static u32 find_buffer(struct vdec_mpeg12_hw_s *hw) +{ + u32 i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + return i; + } + + return DECODE_BUFFER_NUM_MAX; +} + +static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec) +{ + u32 i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->canvas_spec[i] == spec) + return i; + } + + return DECODE_BUFFER_NUM_MAX; +} + +static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf) +{ + unsigned ar_bits; + u32 temp; + u32 buffer_index = vf->index; +#ifdef CONFIG_AM_VDEC_MPEG12_LOG + bool first = (hw->frame_width == 0) && (hw->frame_height == 0); +#endif + + temp = READ_VREG(MREG_PIC_WIDTH); + if (temp > 1920 || temp == 0) + vf->width = hw->frame_width = 1920; + else + vf->width = hw->frame_width = temp; + + temp = READ_VREG(MREG_PIC_HEIGHT); + if (temp > 1088 || temp == 0) + vf->height = hw->frame_height = 1088; + else + vf->height = hw->frame_height = temp; + + if (hw->frame_dur > 0) + vf->duration = hw->frame_dur; + else { + vf->duration = hw->frame_dur = + frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]; + schedule_work(&hw->notify_work); + } + + ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf; + + if (ar_bits == 0x2) + vf->ratio_control = 0xc0 << DISP_RATIO_ASPECT_RATIO_BIT; + + else if (ar_bits == 0x3) + vf->ratio_control = 0x90 << DISP_RATIO_ASPECT_RATIO_BIT; + + else if (ar_bits == 0x4) + vf->ratio_control = 0x74 << DISP_RATIO_ASPECT_RATIO_BIT; + else + vf->ratio_control = 0; + + hw->ratio_control = vf->ratio_control; + + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 2; + + vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; + vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; + + vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; + vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; + + + debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, + "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", + hw->frame_width, hw->frame_height, hw->frame_dur, + frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]); +} + +static bool error_skip(struct vdec_mpeg12_hw_s *hw, + u32 info, struct vframe_s *vf) +{ + if (hw->error_frame_skip_level) { + /* skip error frame */ + if ((info & PICINFO_ERROR) || (hw->frame_force_skip_flag)) { + if ((info & PICINFO_ERROR) == 0) { + if ((info & PICINFO_TYPE_MASK) == + PICINFO_TYPE_I) + hw->frame_force_skip_flag = 0; + } else { + if (hw->error_frame_skip_level >= 2) + hw->frame_force_skip_flag = 1; + } + if ((info & PICINFO_ERROR) + || (hw->frame_force_skip_flag)) + return true; + } + } + return false; +} + +static inline void vmpeg12_save_hw_context(struct vdec_mpeg12_hw_s *hw) +{ + hw->seqinfo = READ_VREG(MREG_SEQ_INFO); + hw->reg_pic_width = READ_VREG(MREG_PIC_WIDTH); + hw->reg_pic_height = READ_VREG(MREG_PIC_HEIGHT); + hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG); + hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO); + hw->reg_f_code_reg = READ_VREG(F_CODE_REG); + hw->reg_slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE); + hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); + hw->reg_mb_info = READ_VREG(MB_INFO); + hw->reg_signal_type = READ_VREG(AV_SCRATCH_H); + debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, + "signal_type = %x", hw->reg_signal_type); +} + +static void vmmpeg2_reset_udr_mgr(struct vdec_mpeg12_hw_s *hw) +{ + hw->wait_for_udr_send = 0; + hw->cur_ud_idx = 0; + memset(&hw->ud_record, 0, sizeof(hw->ud_record)); +} + +static void vmmpeg2_crate_userdata_manager( + struct vdec_mpeg12_hw_s *hw, + u8 *userdata_buf, + int buf_len) +{ + if (hw) { + mutex_init(&hw->userdata_mutex); + + memset(&hw->userdata_info, 0, + sizeof(struct mmpeg2_userdata_info_t)); + hw->userdata_info.data_buf = userdata_buf; + hw->userdata_info.buf_len = buf_len; + hw->userdata_info.data_buf_end = userdata_buf + buf_len; + + vmmpeg2_reset_udr_mgr(hw); + } +} + +static void vmmpeg2_destroy_userdata_manager(struct vdec_mpeg12_hw_s *hw) +{ + if (hw) + memset(&hw->userdata_info, + 0, + sizeof(struct mmpeg2_userdata_info_t)); +} + +static void aml_swap_data(uint8_t *user_data, int ud_size) +{ + int swap_blocks, i, j, k, m; + unsigned char c_temp; + + /* swap byte order */ + swap_blocks = ud_size / 8; + for (i = 0; i < swap_blocks; i++) { + j = i * 8; + k = j + 7; + for (m = 0; m < 4; m++) { + c_temp = user_data[j]; + user_data[j++] = user_data[k]; + user_data[k--] = c_temp; + } + } +} + +#ifdef DUMP_USER_DATA +static void push_to_buf(struct vdec_mpeg12_hw_s *hw, + u8 *pdata, + int len, + struct userdata_meta_info_t *pmeta, + u32 reference) +{ + u32 *pLen; + int info_cnt; + u8 *pbuf_end; + + if (!hw->user_data_dump_buf) + return; + + if (hw->bskip) { + pr_info("over size, skip\n"); + return; + } + info_cnt = 0; + pLen = (u32 *)hw->pdump_buf_cur_start; + + *pLen = len; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->duration; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->flags; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts_valid; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + + *pLen = hw->n_userdata_id; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = reference; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + pbuf_end = hw->userdata_info.data_buf_end; + if (pdata + len > pbuf_end) { + int first_section_len; + + first_section_len = pbuf_end - pdata; + memcpy(hw->pdump_buf_cur_start, pdata, first_section_len); + pdata = (u8 *)hw->userdata_info.data_buf; + hw->pdump_buf_cur_start += first_section_len; + memcpy(hw->pdump_buf_cur_start, pdata, len - first_section_len); + hw->pdump_buf_cur_start += len - first_section_len; + } else { + memcpy(hw->pdump_buf_cur_start, pdata, len); + hw->pdump_buf_cur_start += len; + } + + hw->total_len += len + info_cnt * sizeof(u32); + if (hw->total_len >= MAX_USER_DATA_SIZE-4096) + hw->bskip = 1; +} + +static void dump_userdata_info(struct vdec_mpeg12_hw_s *hw, + void *puser_data, + int len, + struct userdata_meta_info_t *pmeta, + u32 reference) +{ + u8 *pstart; + + pstart = (u8 *)puser_data; + +#ifdef DUMP_HEAD_INFO_DATA + push_to_buf(hw, pstart, len, pmeta, reference); +#else + push_to_buf(hw, pstart+8, len - 8, pmeta, reference); +#endif +} + + +static void print_data(unsigned char *pdata, + int len, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id, + u32 reference) +{ + int nLeft; + + nLeft = len; + + pr_info("%d len:%d, flag:0x%x, dur:%d, vpts:0x%x, valid:%d, refer:%d\n", + rec_id, len, flag, + duration, vpts, vpts_valid, + reference); + while (nLeft >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7], + pdata[8], pdata[9], pdata[10], pdata[11], + pdata[12], pdata[13], pdata[14], pdata[15]); + nLeft -= 16; + pdata += 16; + } + + + while (nLeft > 0) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7]); + nLeft -= 8; + pdata += 8; + } +} + +static void dump_data(u8 *pdata, + unsigned int user_data_length, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id, + u32 reference) +{ + unsigned char szBuf[256]; + + + memset(szBuf, 0, 256); + memcpy(szBuf, pdata, user_data_length); + + aml_swap_data(szBuf, user_data_length); + + print_data(szBuf, + user_data_length, + flag, + duration, + vpts, + vpts_valid, + rec_id, + reference); +} + + +static void show_user_data_buf(struct vdec_mpeg12_hw_s *hw) +{ + u8 *pbuf; + int len; + unsigned int flag; + unsigned int duration; + unsigned int vpts; + unsigned int vpts_valid; + int rec_id; + u32 reference; + + pr_info("show user data buf\n"); + pbuf = hw->user_data_dump_buf; + + while (pbuf < hw->pdump_buf_cur_start) { + u32 *pLen; + + pLen = (u32 *)pbuf; + + len = *pLen; + pLen++; + pbuf += sizeof(u32); + + duration = *pLen; + pLen++; + pbuf += sizeof(u32); + + flag = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts_valid = *pLen; + pLen++; + pbuf += sizeof(u32); + + rec_id = *pLen; + pLen++; + pbuf += sizeof(u32); + + reference = *pLen; + pLen++; + pbuf += sizeof(u32); + + + dump_data(pbuf, len, flag, duration, + vpts, vpts_valid, rec_id, reference); + pbuf += len; + msleep(30); + } +} + +static int amvdec_mmpeg12_init_userdata_dump(struct vdec_mpeg12_hw_s *hw) +{ + hw->user_data_dump_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); + if (hw->user_data_dump_buf) + return 1; + else + return 0; +} + +static void amvdec_mmpeg12_uninit_userdata_dump(struct vdec_mpeg12_hw_s *hw) +{ + if (hw->user_data_dump_buf) { + show_user_data_buf(hw); + kfree(hw->user_data_dump_buf); + hw->user_data_dump_buf = NULL; + } +} + +static void reset_user_data_buf(struct vdec_mpeg12_hw_s *hw) +{ + hw->total_len = 0; + hw->pdump_buf_cur_start = hw->user_data_dump_buf; + hw->bskip = 0; + hw->n_userdata_id = 0; +} +#endif + +static void user_data_ready_notify(struct vdec_mpeg12_hw_s *hw, + u32 pts, u32 pts_valid) +{ + struct mmpeg2_userdata_record_t *p_userdata_rec; + int i; + + if (hw->wait_for_udr_send) { + for (i = 0; i < hw->cur_ud_idx; i++) { + mutex_lock(&hw->userdata_mutex); + + + p_userdata_rec = hw->userdata_info.records + + hw->userdata_info.write_index; + + hw->ud_record[i].meta_info.vpts_valid = pts_valid; + hw->ud_record[i].meta_info.vpts = pts; + + *p_userdata_rec = hw->ud_record[i]; +#ifdef DUMP_USER_DATA + dump_userdata_info(hw, + hw->userdata_info.data_buf + p_userdata_rec->rec_start, + p_userdata_rec->rec_len, + &p_userdata_rec->meta_info, + hw->reference[i]); + hw->n_userdata_id++; +#endif +/* + pr_info("notify: rec_start:%d, rec_len:%d, wi:%d, reference:%d\n", + p_userdata_rec->rec_start, + p_userdata_rec->rec_len, + hw->userdata_info.write_index, + hw->reference[i]); +*/ + hw->userdata_info.write_index++; + if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) + hw->userdata_info.write_index = 0; + + mutex_unlock(&hw->userdata_mutex); + + + vdec_wakeup_userdata_poll(hw_to_vdec(hw)); + } + hw->wait_for_udr_send = 0; + hw->cur_ud_idx = 0; + } + hw->notify_ucode_cc_last_wp = hw->ucode_cc_last_wp; + hw->notify_data_cc_last_wp = hw->userdata_info.last_wp; +} + +static int vmmpeg2_user_data_read(struct vdec_s *vdec, + struct userdata_param_t *puserdata_para) +{ + struct vdec_mpeg12_hw_s *hw = NULL; + int rec_ri, rec_wi; + int rec_len; + u8 *rec_data_start; + u8 *pdest_buf; + struct mmpeg2_userdata_record_t *p_userdata_rec; + u32 data_size; + u32 res; + int copy_ok = 1; + + hw = (struct vdec_mpeg12_hw_s *)vdec->private; + + pdest_buf = puserdata_para->pbuf_addr; + + mutex_lock(&hw->userdata_mutex); + +/* + pr_info("ri = %d, wi = %d\n", + hw->userdata_info.read_index, + hw->userdata_info.write_index); +*/ + rec_ri = hw->userdata_info.read_index; + rec_wi = hw->userdata_info.write_index; + + if (rec_ri == rec_wi) { + mutex_unlock(&hw->userdata_mutex); + return 0; + } + + p_userdata_rec = hw->userdata_info.records + rec_ri; + + rec_len = p_userdata_rec->rec_len; + rec_data_start = p_userdata_rec->rec_start + hw->userdata_info.data_buf; +/* + pr_info("ri:%d, wi:%d, rec_len:%d, rec_start:%d, buf_len:%d\n", + rec_ri, rec_wi, + p_userdata_rec->rec_len, + p_userdata_rec->rec_start, + puserdata_para->buf_len); +*/ + if (rec_len <= puserdata_para->buf_len) { + /* dvb user data buffer is enought to + copy the whole recored. */ + data_size = rec_len; + if (rec_data_start + data_size + > hw->userdata_info.data_buf_end) { + int first_section_len; + + first_section_len = hw->userdata_info.buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p1 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)hw->userdata_info.data_buf, + data_size - first_section_len); + if (res) { + pr_info("p2 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p3 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + hw->userdata_info.read_index++; + if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) + hw->userdata_info.read_index = 0; + } + } else { + /* dvb user data buffer is not enought + to copy the whole recored. */ + data_size = puserdata_para->buf_len; + if (rec_data_start + data_size + > hw->userdata_info.data_buf_end) { + int first_section_len; + + first_section_len = hw->userdata_info.buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p4 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + /* first secton copy is ok*/ + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)hw->userdata_info.data_buf, + data_size - first_section_len); + if (res) { + pr_info("p5 read not end res=%d, request=%d\n", + res, + data_size - first_section_len); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p6 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + hw->userdata_info.read_index++; + if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) + hw->userdata_info.read_index = 0; + } + + } + puserdata_para->meta_info = p_userdata_rec->meta_info; + + if (hw->userdata_info.read_index <= hw->userdata_info.write_index) + puserdata_para->meta_info.records_in_que = + hw->userdata_info.write_index - + hw->userdata_info.read_index; + else + puserdata_para->meta_info.records_in_que = + hw->userdata_info.write_index + + USERDATA_FIFO_NUM - + hw->userdata_info.read_index; + + puserdata_para->version = (0<<24|0<<16|0<<8|1); + + mutex_unlock(&hw->userdata_mutex); + + + return 1; +} + +static void vmmpeg2_reset_userdata_fifo(struct vdec_s *vdec, int bInit) +{ + struct vdec_mpeg12_hw_s *hw = NULL; + + hw = (struct vdec_mpeg12_hw_s *)vdec->private; + + if (hw) { + mutex_lock(&hw->userdata_mutex); + pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + bInit, + hw->userdata_info.read_index, + hw->userdata_info.write_index); + hw->userdata_info.read_index = 0; + hw->userdata_info.write_index = 0; + + if (bInit) + hw->userdata_info.last_wp = 0; + mutex_unlock(&hw->userdata_mutex); + } +} + +static void vmmpeg2_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + +/* +#define PRINT_HEAD_INFO +*/ +static void userdata_push_do_work(struct work_struct *work) +{ + u32 reg; + u8 *pdata; + u8 *psrc_data; + u8 head_info[8]; + struct userdata_meta_info_t meta_info; + u32 wp; + u32 index; + u32 picture_struct; + u32 reference; + u32 picture_type; + u32 temp; + u32 data_length; + u32 data_start; + int i; + u32 offset; + u32 cur_wp; +#ifdef PRINT_HEAD_INFO + u8 *ptype_str; +#endif + struct mmpeg2_userdata_record_t *pcur_ud_rec; + + struct vdec_mpeg12_hw_s *hw = container_of(work, + struct vdec_mpeg12_hw_s, userdata_push_work); + + memset(&meta_info, 0, sizeof(meta_info)); + + meta_info.duration = hw->frame_dur; + + + reg = READ_VREG(AV_SCRATCH_J); + meta_info.flags = ((reg >> 30) << 1); + meta_info.flags |= (VFORMAT_MPEG12 << 3); + /* check top_field_first flag */ + if ((reg >> 28) & 0x1) { + meta_info.flags |= (1 << 10); + meta_info.flags |= (((reg >> 29) & 0x1) << 11); + } + + cur_wp = reg & 0x7fff; + if (cur_wp == hw->ucode_cc_last_wp) { + debug_print(DECODE_ID(hw), 0, + "Null user data package: wp = %d\n", cur_wp); + WRITE_VREG(AV_SCRATCH_J, 0); + return; + } + + if (hw->cur_ud_idx >= MAX_UD_RECORDS) { + debug_print(DECODE_ID(hw), 0, + "UD Records over: %d, skip it\n", MAX_UD_RECORDS); + WRITE_VREG(AV_SCRATCH_J, 0); + return; + } + + if (cur_wp < hw->ucode_cc_last_wp) + hw->ucode_cc_last_wp = 0; + + offset = READ_VREG(AV_SCRATCH_I); + + codec_mm_dma_flush( + hw->ccbuf_phyAddress_virt, + CCBUF_SIZE, + DMA_FROM_DEVICE); + + mutex_lock(&hw->userdata_mutex); + if (hw->ccbuf_phyAddress_virt) { + pdata = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; + memcpy(head_info, pdata, 8); + } else + memset(head_info, 0, 8); + mutex_unlock(&hw->userdata_mutex); + aml_swap_data(head_info, 8); + + wp = (head_info[0] << 8 | head_info[1]); + index = (head_info[2] << 8 | head_info[3]); + + picture_struct = (head_info[6] << 8 | head_info[7]); + temp = (head_info[4] << 8 | head_info[5]); + reference = temp & 0x3FF; + picture_type = (temp >> 10) & 0x7; + + if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) + pr_info("index:%d, wp:%d, ref:%d, type:%d, struct:0x%x, u_last_wp:0x%x\n", + index, wp, reference, + picture_type, picture_struct, + hw->ucode_cc_last_wp); + + switch (picture_type) { + case 1: + /* pr_info("I type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (1<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " I"; +#endif + break; + case 2: + /* pr_info("P type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (2<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " P"; +#endif + break; + case 3: + /* pr_info("B type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (3<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " B"; +#endif + break; + case 4: + /* pr_info("D type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (4<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " D"; +#endif + break; + default: + /* pr_info("Unknown type:0x%x, pos:%d\n", + pheader->picture_coding_type, + (meta_info.flags>>1)&0x3); */ +#ifdef PRINT_HEAD_INFO + ptype_str = " U"; +#endif + break; + } +#ifdef PRINT_HEAD_INFO + pr_info("ref:%d, type:%s, ext:%d, first:%d, data_length:%d\n", + reference, ptype_str, + (reg >> 30), + (reg >> 28)&0x3, + reg & 0xffff); +#endif + data_length = cur_wp - hw->ucode_cc_last_wp; + data_start = reg & 0xffff; + psrc_data = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; + + pdata = hw->userdata_info.data_buf + hw->userdata_info.last_wp; + for (i = 0; i < data_length; i++) { + *pdata++ = *psrc_data++; + if (pdata >= hw->userdata_info.data_buf_end) + pdata = hw->userdata_info.data_buf; + } + pcur_ud_rec = hw->ud_record + hw->cur_ud_idx; + + pcur_ud_rec->meta_info = meta_info; + pcur_ud_rec->rec_start = hw->userdata_info.last_wp; + pcur_ud_rec->rec_len = data_length; + + hw->userdata_info.last_wp += data_length; + if (hw->userdata_info.last_wp >= USER_DATA_SIZE) + hw->userdata_info.last_wp -= USER_DATA_SIZE; + + hw->wait_for_udr_send = 1; + + hw->ucode_cc_last_wp = cur_wp; + + if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) + pr_info("cur_wp:%d, rec_start:%d, rec_len:%d\n", + cur_wp, + pcur_ud_rec->rec_start, + pcur_ud_rec->rec_len); + +#ifdef DUMP_USER_DATA + hw->reference[hw->cur_ud_idx] = reference; +#endif + + hw->cur_ud_idx++; + WRITE_VREG(AV_SCRATCH_J, 0); + +} + + +void userdata_pushed_drop(struct vdec_mpeg12_hw_s *hw) +{ + hw->userdata_info.last_wp = hw->notify_data_cc_last_wp; + hw->ucode_cc_last_wp = hw->notify_ucode_cc_last_wp; + hw->cur_ud_idx = 0; + hw->wait_for_udr_send = 0; + +} + + +static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) +{ + u32 reg, info, seqinfo, offset, pts, pts_valid = 0; + struct vframe_s *vf = NULL; + u32 index; + u64 pts_us64 = 0; + u32 frame_size; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)(vdec->private); + + if (READ_VREG(AV_SCRATCH_M) != 0 && + (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { + + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "dbg %x: %x, level %x, wp %x, rp %x, cnt %x\n", + READ_VREG(AV_SCRATCH_M), READ_VREG(AV_SCRATCH_N), + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VIFF_BIT_CNT)); + WRITE_VREG(AV_SCRATCH_M, 0); + return IRQ_HANDLED; + } + + reg = READ_VREG(AV_SCRATCH_J); + if (reg & (1<<16)) { + vdec_schedule_work(&hw->userdata_push_work); + return IRQ_HANDLED; + } + + reg = READ_VREG(MREG_BUFFEROUT); + + if (reg == 2) { + /*timeout when decoding next frame*/ + + debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "ammvdec_mpeg12: Insufficient data\n"); + debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "level=%x, vtl=%x,bcnt=%d\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VIFF_BIT_CNT)); + if (input_frame_based(vdec)) + vmpeg12_save_hw_context(hw); + else { + hw->dec_result = DEC_RESULT_AGAIN; + vdec_schedule_work(&hw->work); + userdata_pushed_drop(hw); + } + return IRQ_HANDLED; + } else { + reset_process_time(hw); + info = READ_VREG(MREG_PIC_INFO); + offset = READ_VREG(MREG_FRAME_OFFSET); + index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); + seqinfo = READ_VREG(MREG_SEQ_INFO); + if ((info & PICINFO_PROG) == 0 && + (info & FRAME_PICTURE_MASK) != FRAME_PICTURE) + hw->first_i_frame_ready = 1; /* for field struct case*/ + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "struct: %d %x\n", (info & PICINFO_FRAME), info); + if (index >= DECODE_BUFFER_NUM_MAX) { + + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "invalid buffer index,index=%d\n", + index); + hw->dec_result = DEC_RESULT_ERROR; + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + + hw->dec_result = DEC_RESULT_DONE; + + /*debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "ammvdec_mpeg12: error = 0x%x, offset = 0x%x\n", + info & PICINFO_ERROR, offset);*/ + + if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I)) { + if (hw->chunk) { + hw->pts_valid[index] = hw->chunk->pts_valid; + hw->pts[index] = hw->chunk->pts; + hw->pts64[index] = hw->chunk->pts64; + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "!!!cpts=%d,pts64=%lld,size=%d,offset=%d\n", + hw->pts[index], hw->pts64[index], + hw->chunk->size, hw->chunk->offset); + } else { + if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, + offset, &pts, &frame_size, + 0, &pts_us64) == 0) { + hw->pts_valid[index] = true; + hw->pts[index] = pts; + hw->pts64[index] = pts_us64; + } else { + hw->pts_valid[index] = false; + } + } + } else { + hw->pts_valid[index] = false; + } + /*if (frame_prog == 0) */ + { + hw->frame_prog = info & PICINFO_PROG; + if ((seqinfo & SEQINFO_EXT_AVAILABLE) + && (!(seqinfo & SEQINFO_PROG))) + hw->frame_prog = 0; + } + if ((hw->dec_control & + DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) && + (hw->frame_width == 720) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) && + (hw->frame_width == 704) && + (hw->frame_height == 480) && + (hw->frame_dur == 3200)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) && + (hw->frame_width == 704) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) && + (hw->frame_width == 544) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) && + (hw->frame_width == 480) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if (hw->dec_control + & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) { + hw->frame_prog = 0; + } + + hw->buffer_info[index] = info; + + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "ammvdec_mpeg12: decoded buffer %d, frame_type %c\n", + index, GET_SLICE_TYPE(info)); + + /* Buffer management + todo: add sequence-end flush */ + if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) || + ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) { + hw->vfbuf_use[index]++; + if (hw->refs[1] == -1) { + hw->refs[1] = index; + index = DECODE_BUFFER_NUM_MAX; + } else if (hw->refs[0] == -1) { + hw->refs[0] = hw->refs[1]; + hw->refs[1] = index; + index = hw->refs[0]; + } else { + hw->vfbuf_use[hw->refs[0]]--; + hw->refs[0] = hw->refs[1]; + hw->refs[1] = index; + index = hw->refs[0]; + } + } else { + /* if this is a B frame, then drop + (depending on if there are two reference frames) + or display immediately*/ + if (hw->refs[0] == -1) + index = DECODE_BUFFER_NUM_MAX; + + } + + vmpeg12_save_hw_context(hw); + + if (index >= DECODE_BUFFER_NUM_MAX) { + debug_print(DECODE_ID(hw), 0, + "invalid buffer index,index=%d\n", index); + hw->dec_result = DEC_RESULT_ERROR; + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + + info = hw->buffer_info[index]; + pts_valid = hw->pts_valid[index]; + pts = hw->pts[index]; + pts_us64 = hw->pts64[index]; + + user_data_ready_notify(hw, pts, pts_valid); + + if ((hw->first_i_frame_ready == 0) && + ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && + ((info & PICINFO_ERROR) == 0)) + hw->first_i_frame_ready = 1; + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "ammvdec_mpeg12: display buffer %d, frame_type %c\n", + index, GET_SLICE_TYPE(info)); + if (hw->frame_prog & PICINFO_PROG) { + + seqinfo = READ_VREG(MREG_SEQ_INFO); + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "fatal error, no available buffer slot."); + hw->dec_result = DEC_RESULT_ERROR; + vdec_schedule_work(&hw->work); + + return IRQ_HANDLED; + } + + vf->index = index; + set_frame_info(hw, vf); + vf->signal_type = hw->reg_signal_type; + +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + if ((hw->seqinfo & SEQINFO_EXT_AVAILABLE) + && (hw->seqinfo & SEQINFO_PROG)) { + if (info & PICINFO_RPT_FIRST) { + if (info & PICINFO_TOP_FIRST) { + vf->duration = + vf->duration * 3; + /* repeat three times */ + } else { + vf->duration = + vf->duration * 2; + /* repeat two times */ + } + } + vf->duration_pulldown = 0; + /* no pull down */ + + } else { + vf->duration_pulldown = + (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + } + + vf->duration += vf->duration_pulldown; + + vf->orientation = 0; + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + vf->type_original = vf->type; + hw->vfbuf_use[index]++; + + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + + } else { + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "cpts=%d,pts64=%lld\n", + vf->pts, vf->pts_us64); + decoder_do_frame_check(hw_to_vdec(hw), vf); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } +/*interlace temp*/ + else { + int first_field_type = (info & PICINFO_TOP_FIRST) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; + +#ifdef INTERLACE_SEQ_ALWAYS + /* once an interlaced sequence exist, + always force interlaced type */ + /* to make DI easy. */ + hw->dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE; +#endif + + hw->frame_rpt_state = FRAME_REPEAT_NONE; + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "fatal error, no available buffer slot."); + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + + hw->vfbuf_use[index] += 2; + vf->signal_type = hw->reg_signal_type; + vf->index = index; + set_frame_info(hw, vf); + vf->type = + (first_field_type == VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + if (info & PICINFO_RPT_FIRST) + vf->duration /= 3; + else + vf->duration >>= 1; + vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + hw->vfbuf_use[index]--; + hw->drop_frame_count++; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "cpts0=%d,pts64=%lld,dur=%d, index %d , use %d\n", + vf->pts, vf->pts_us64, vf->duration, + vf->index, hw->vfbuf_use[index]); + decoder_do_frame_check(hw_to_vdec(hw), vf); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "ammvdec_mpeg12: fatal error, no available buffer slot."); + + hw->vfbuf_use[index]--; + + vdec_schedule_work(&hw->work); + + return IRQ_HANDLED; + } + vf->signal_type = hw->reg_signal_type; + vf->index = index; + set_frame_info(hw, vf); + vf->type = (first_field_type == + VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + if (info & PICINFO_RPT_FIRST) + vf->duration /= 3; + else + vf->duration >>= 1; + vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + vf->pts = 0; + vf->pts_us64 = 0; + vf->type_original = vf->type; + + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "cpts1=%d,pts64=%lld,dur=%d index %d, used %d\n", + vf->pts, vf->pts_us64, vf->duration, vf->index, + hw->vfbuf_use[index]); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + + if (info & PICINFO_RPT_FIRST) { + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, + "error, no available buffer slot."); + return IRQ_HANDLED; + } + hw->vfbuf_use[index]++; + vf->index = index; + set_frame_info(hw, vf); + vf->type = (first_field_type == + VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->duration /= 3; + vf->duration_pulldown = + (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + + vf->pts = 0; + vf->pts_us64 = 0; + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) + != PICINFO_TYPE_I))) { + hw->vfbuf_use[index]--; + hw->drop_frame_count++; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + hw->frame_num++; + debug_print(DECODE_ID(hw), + PRINT_FLAG_TIMEINFO, + "cpts2=%d,pts64=%lld,dur=%d index %d, used %d\n", + vf->pts, vf->pts_us64, vf->duration, + vf->index, hw->vfbuf_use[index]); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver( + vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } + } + vdec_schedule_work(&hw->work); + + debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "frame_num=%d\n", hw->frame_num); + if (hw->frame_num == 1) + debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "frame_num==1\n"); + if (hw->frame_num == 1000) + debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "frame_num==1000\n"); + } + + return IRQ_HANDLED; +} +static irqreturn_t vmpeg12_isr(struct vdec_s *vdec, int irq) +{ + u32 info, offset; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)(vdec->private); + if (hw->eos) + return IRQ_HANDLED; + info = READ_VREG(MREG_PIC_INFO); + offset = READ_VREG(MREG_FRAME_OFFSET); + + vdec_count_info(&gvs, info & PICINFO_ERROR, offset); + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + return IRQ_WAKE_THREAD; +} + +static void vmpeg12_notify_work(struct work_struct *work) +{ + struct vdec_mpeg12_hw_s *hw = container_of(work, + struct vdec_mpeg12_hw_s, notify_work); + struct vdec_s *vdec = hw_to_vdec(hw); + + if (vdec->fr_hint_state == VDEC_NEED_HINT) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)hw->frame_dur)); + vdec->fr_hint_state = VDEC_HINTED; + } +} + +static void wait_vmmpeg12_search_done(struct vdec_mpeg12_hw_s *hw) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; + + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 1000) { + debug_print(DECODE_ID(hw), 0, + "%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); +} + +static void vmpeg12_work(struct work_struct *work) +{ + struct vdec_mpeg12_hw_s *hw = + container_of(work, struct vdec_mpeg12_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); + if (hw->dec_result != DEC_RESULT_DONE) + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "ammvdec_mpeg12: vmpeg_work,result=%d,status=%d\n", + hw->dec_result, hw_to_vdec(hw)->next_status); + + if (hw->dec_result == DEC_RESULT_DONE) { + if (!hw->ctx_valid) + hw->ctx_valid = 1; + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + } else if (hw->dec_result == DEC_RESULT_AGAIN + && (hw_to_vdec(hw)->next_status != + VDEC_STATUS_DISCONNECTED)) { + /* + stream base: stream buf empty or timeout + frame base: vdec_prepare_input fail + */ + if (!vdec_has_more_input(hw_to_vdec(hw))) { + hw->dec_result = DEC_RESULT_EOS; + vdec_schedule_work(&hw->work); + return; + } +#ifdef AGAIN_HAS_THRESHOLD + hw->next_again_flag = 1; +#endif + } else if (hw->dec_result == DEC_RESULT_GET_DATA + && (hw_to_vdec(hw)->next_status != + VDEC_STATUS_DISCONNECTED)) { + if (!vdec_has_more_input(hw_to_vdec(hw))) { + hw->dec_result = DEC_RESULT_EOS; + vdec_schedule_work(&hw->work); + return; + } + debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "%s DEC_RESULT_GET_DATA %x %x %x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP)); + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); + return; + } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s: force exit\n", __func__); + if (hw->stat & STAT_ISR_REG) { + amvdec_stop(); + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + } else if (hw->dec_result == DEC_RESULT_EOS) { + pr_info("%s: end of stream\n", __func__); + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + hw->eos = 1; + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); + } + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + wait_vmmpeg12_search_done(hw); + if (vdec->parallel_dec == 1) + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + + if (hw->vdec_cb) { + hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); + debug_print(DECODE_ID(hw), 0x80000, + "%s:\n", __func__); + } +} + +static struct vframe_s *vmpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + hw->peek_num++; + if (kfifo_peek(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + hw->get_num++; + if (kfifo_get(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + hw->vfbuf_use[vf->index]--; + hw->put_num++; + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); +} + +static int vmpeg_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + spin_lock_irqsave(&hw->lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&hw->newframe_q); + states->buf_avail_num = kfifo_len(&hw->display_q); + states->buf_recycle_num = 0; + + spin_unlock_irqrestore(&hw->lock, flags); + return 0; +} +static int vmmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + if (!hw) + return -1; + + vstatus->frame_width = hw->frame_width; + vstatus->frame_height = hw->frame_height; + if (hw->frame_dur != 0) + vstatus->frame_rate = 96000 / hw->frame_dur; + else + vstatus->frame_rate = -1; + vstatus->error_count = READ_VREG(AV_SCRATCH_C); + vstatus->status = hw->stat; + vstatus->bit_rate = gvs.bit_rate; + vstatus->frame_dur = hw->frame_dur; + vstatus->frame_data = gvs.frame_data; + vstatus->total_data = gvs.total_data; + vstatus->frame_count = gvs.frame_count; + vstatus->error_frame_count = gvs.error_frame_count; + vstatus->drop_frame_count = hw->drop_frame_count; + vstatus->total_data = gvs.total_data; + vstatus->samp_cnt = gvs.samp_cnt; + vstatus->offset = gvs.offset; + vstatus->ratio_control = hw->ratio_control; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), + "%s", DRIVER_NAME); + + return 0; +} + + + +/****************************************/ +static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) +{ + int i, ret; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + unsigned long decbuf_start; + /*u32 disp_addr = 0xffffffff;*/ + struct vdec_s *vdec = hw_to_vdec(hw); + + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + /* HD & SD */ + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + + for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { + + unsigned canvas; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */ + decbuf_size = WORKSPACE_SIZE; + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &decbuf_start); + if (ret < 0) { + pr_err("mmu alloc failed! size 0x%d idx %d\n", + decbuf_size, i); + return; + } + + if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + if (hw->ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); + hw->ccbuf_phyAddress_virt = NULL; + hw->ccbuf_phyAddress = 0; + hw->ccbuf_phyAddress_is_remaped_nocache = 0; + + hw->buf_start = decbuf_start; + hw->ccbuf_phyAddress = hw->buf_start + CTX_CCBUF_OFFSET; + hw->ccbuf_phyAddress_virt + = codec_mm_phys_to_virt( + hw->ccbuf_phyAddress); + if (!hw->ccbuf_phyAddress_virt) { + hw->ccbuf_phyAddress_virt + = codec_mm_vmap( + hw->ccbuf_phyAddress, + CCBUF_SIZE); + hw->ccbuf_phyAddress_is_remaped_nocache = 1; + } + + WRITE_VREG(MREG_CO_MV_START, hw->buf_start); + } else { + if (vdec->parallel_dec == 1) { + unsigned tmp; + if (canvas_u(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~(0xffff << 8); + hw->canvas_spec[i] |= tmp << 8; + hw->canvas_spec[i] |= tmp << 16; + } + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } + canvas = hw->canvas_spec[i]; + } else { + canvas = vdec->get_canvas(i, 2); + hw->canvas_spec[i] = canvas; + } + + hw->canvas_config[i][0].phy_addr = + decbuf_start; + hw->canvas_config[i][0].width = + canvas_width; + hw->canvas_config[i][0].height = + canvas_height; + hw->canvas_config[i][0].block_mode = + hw->canvas_mode; + hw->canvas_config[i][0].endian = + (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + + canvas_config_config(canvas_y(canvas), + &hw->canvas_config[i][0]); + + hw->canvas_config[i][1].phy_addr = + decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = + canvas_width; + hw->canvas_config[i][1].height = + canvas_height / 2; + hw->canvas_config[i][1].block_mode = + hw->canvas_mode; + hw->canvas_config[i][0].endian = + (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + + canvas_config_config(canvas_u(canvas), + &hw->canvas_config[i][1]); + } + } + return; +} + +static void vmpeg2_dump_state(struct vdec_s *vdec) +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)(vdec->private); + u32 i; + debug_print(DECODE_ID(hw), 0, + "====== %s\n", __func__); + debug_print(DECODE_ID(hw), 0, + "width/height (%d/%d),i_first %d\n", + hw->frame_width, + hw->frame_height, + hw->first_i_frame_ready + ); + debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d,input_empty %d\n", + input_frame_based(vdec), + hw->eos, + hw->stat, + hw->dec_result, + hw->frame_num, + hw->put_num, + hw->run_count, + hw->not_run_ready, + hw->input_empty + ); + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + debug_print(DECODE_ID(hw), 0, + "index %d, used %d\n", i, hw->vfbuf_use[i]); + } + + if (vf_get_receiver(vdec->vf_provider_name)) { + enum receviver_start_e state = + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + debug_print(DECODE_ID(hw), 0, + "\nreceiver(%s) state %d\n", + vdec->vf_provider_name, + state); + } + debug_print(DECODE_ID(hw), 0, + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d),drop=%d, buffer_not_ready %d\n", + __func__, + kfifo_len(&hw->newframe_q), + VF_POOL_SIZE, + kfifo_len(&hw->display_q), + VF_POOL_SIZE, + hw->peek_num, + hw->get_num, + hw->put_num, + hw->drop_frame_count, + hw->buffer_not_ready + ); + debug_print(DECODE_ID(hw), 0, + "VIFF_BIT_CNT=0x%x\n", + READ_VREG(VIFF_BIT_CNT)); + debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_LEVEL=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_WP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_RP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_RP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_RP)); + debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_WP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_WP)); + if (input_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + if (hw->chunk && hw->chunk->block && + hw->chunk->size > 0) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + debug_print(DECODE_ID(hw), 0, + "frame data size 0x%x\n", + hw->chunk->size); + for (jj = 0; jj < hw->chunk->size; jj++) { + if ((jj & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + } +} + +static void reset_process_time(struct vdec_mpeg12_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[DECODE_ID(hw)]) + max_process_time[DECODE_ID(hw)] = process_time; + } +} +static void start_process_time(struct vdec_mpeg12_hw_s *hw) +{ + hw->decode_timeout_count = 10; + hw->start_process_time = jiffies; +} +static void timeout_process(struct vdec_mpeg12_hw_s *hw) +{ + struct vdec_s *vdec = hw_to_vdec(hw); + + reset_process_time(hw); + amvdec_stop(); + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s decoder timeout, status=%d, level=%d\n", + __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + hw->dec_result = DEC_RESULT_DONE; + hw->first_i_frame_ready = 0; + vdec_schedule_work(&hw->work); +} + +static void check_timer_func(unsigned long arg) +{ + struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)arg; + struct vdec_s *vdec = hw_to_vdec(hw); + unsigned int timeout_val = decode_timeout_val; + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + + if (debug_enable == 0 && + (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && + (timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > timeout_val)) { + if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + } + + if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + pr_info("vdec requested to be disconnected\n"); + return; + } + + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); +} + +static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw) +{ + u32 index; + index = find_buffer(hw); + if (index >= DECODE_BUFFER_NUM_MAX) + return -1; + vmpeg12_canvas_init(hw); + + /* prepare REF0 & REF1 + points to the past two IP buffers + prepare REC_CANVAS_ADDR and ANC2_CANVAS_ADDR + points to the output buffer*/ + WRITE_VREG(MREG_REF0, + (hw->refs[1] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[0]]); + WRITE_VREG(MREG_REF1, + (hw->refs[0] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[1]]); + WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); + WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); + + debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, + "%s,ref0=0x%x, ref1=0x%x,rec=0x%x, ctx_valid=%d,index=%d\n", + __func__, + READ_VREG(MREG_REF0), + READ_VREG(MREG_REF1), + READ_VREG(REC_CANVAS_ADDR), + hw->ctx_valid, index); + + /* set to mpeg1 default */ + WRITE_VREG(MPEG1_2_REG, + (hw->ctx_valid) ? hw->reg_mpeg1_2_reg : 0); + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + /* for Mpeg1 default value */ + WRITE_VREG(PIC_HEAD_INFO, + (hw->ctx_valid) ? hw->reg_pic_head_info : 0x380); + /* disable mpeg4 */ + WRITE_VREG(M4_CONTROL_REG, 0); + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + /* clear buffer IN/OUT registers */ + WRITE_VREG(MREG_BUFFEROUT, 0); + /* set reference width and height */ + if ((hw->frame_width != 0) && (hw->frame_height != 0)) + WRITE_VREG(MREG_CMD, + (hw->frame_width << 16) | hw->frame_height); + else + WRITE_VREG(MREG_CMD, 0); + + + debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, + "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + hw->frame_width, hw->frame_height, hw->seqinfo, + hw->reg_f_code_reg, hw->reg_slice_ver_pos_pic_type, + hw->reg_mb_info); + + WRITE_VREG(MREG_PIC_WIDTH, hw->reg_pic_width); + WRITE_VREG(MREG_PIC_HEIGHT, hw->reg_pic_height); + WRITE_VREG(MREG_SEQ_INFO, hw->seqinfo); + WRITE_VREG(F_CODE_REG, hw->reg_f_code_reg); + WRITE_VREG(SLICE_VER_POS_PIC_TYPE, + hw->reg_slice_ver_pos_pic_type); + WRITE_VREG(MB_INFO, hw->reg_mb_info); + WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg); + WRITE_VREG(AV_SCRATCH_H, hw->reg_signal_type); + + /* clear error count */ + WRITE_VREG(MREG_ERROR_COUNT, 0); + WRITE_VREG(MREG_FATAL_ERROR, 0); + /* clear wait buffer status */ + WRITE_VREG(MREG_WAIT_BUFFER, 0); +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); +#endif + if (hw->chunk) { + /*frame based input*/ + WRITE_VREG(MREG_INPUT, + (hw->chunk->offset & 7) | (1<<7) | (hw->ctx_valid<<6)); + } else { + /*stream based input*/ + WRITE_VREG(MREG_INPUT, (hw->ctx_valid<<6)); + } + return 0; +} + +static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw) +{ + int i; + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf; + vf = &hw->vfpool[i]; + hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); + } + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->vfbuf_use[i] = 0; + + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + + hw->mm_blk_handle = decoder_bmmu_box_alloc_box( + DRIVER_NAME, + 0, + MAX_BMMU_BUFFER_NUM, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + hw->eos = 0; + hw->frame_width = hw->frame_height = 0; + hw->frame_dur = hw->frame_prog = 0; + hw->frame_force_skip_flag = 0; + hw->wait_buffer_counter = 0; + hw->first_i_frame_ready = 0; + hw->dec_control &= DEC_CONTROL_INTERNAL_MASK; + hw->refs[0] = -1; + hw->refs[1] = -1; + hw->frame_num = 0; + hw->put_num = 0; + hw->run_count = 0; + hw->not_run_ready = 0; + hw->input_empty = 0; + hw->peek_num = 0; + hw->get_num = 0; + hw->drop_frame_count = 0; + hw->buffer_not_ready = 0; + hw->start_process_time = 0; + hw->error_frame_skip_level = error_frame_skip_level; + if (dec_control) + hw->dec_control = dec_control; +} + +static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw) +{ + int size; + u32 fw_size = 16*0x1000; + struct firmware_s *fw; + + vmpeg12_local_init(hw); + + fw = vmalloc(sizeof(struct firmware_s) + fw_size); + if (IS_ERR_OR_NULL(fw)) + return -ENOMEM; + + pr_debug("get firmware ...\n"); + size = get_firmware_data(VIDEO_DEC_MPEG12_MULTI, fw->data); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(fw); + return -1; + } + + fw->len = size; + hw->fw = fw; + + INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); + INIT_WORK(&hw->work, vmpeg12_work); + INIT_WORK(&hw->notify_work, vmpeg12_notify_work); + + if (NULL == hw->user_data_buffer) { + hw->user_data_buffer = kmalloc(USER_DATA_SIZE, + GFP_KERNEL); + if (!hw->user_data_buffer) { + pr_info("%s: Can not allocate user_data_buffer\n", + __func__); + return -1; + } + } + + vmmpeg2_crate_userdata_manager(hw, + hw->user_data_buffer, + USER_DATA_SIZE); + + amvdec_enable(); + init_timer(&hw->check_timer); + hw->check_timer.data = (unsigned long)hw; + hw->check_timer.function = check_timer_func; + hw->check_timer.expires = jiffies + CHECK_INTERVAL; + + hw->stat |= STAT_TIMER_ARM; + hw->stat |= STAT_ISR_REG; + + hw->buf_start = 0; + hw->init_flag = 0; + WRITE_VREG(DECODE_STOP_POS, udebug_flag); + + return 0; +} + +static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) +{ + int index; + + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + if (hw->eos) + return 0; + if (vdec_stream_based(vdec) && (hw->init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < pre_decode_buf_level) { + hw->not_run_ready++; + return 0; + } + } + +#ifdef AGAIN_HAS_THRESHOLD + if (hw->next_again_flag&& + (!vdec_frame_based(vdec))) { + u32 parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + if (parser_wr_ptr >= hw->pre_parser_wr_ptr && + (parser_wr_ptr - hw->pre_parser_wr_ptr) < + again_threshold) { + int r = vdec_sync_input(vdec); + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s buf level%x\n", + __func__, r); + return 0; + } + } +#endif + + index = find_buffer(hw); + if (index >= DECODE_BUFFER_NUM_MAX) { + hw->buffer_not_ready++; + return 0; + } + hw->not_run_ready = 0; + hw->buffer_not_ready = 0; + if (vdec->parallel_dec == 1) + return (unsigned long)(CORE_MASK_VDEC_1); + else + return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); +} + +static unsigned char get_data_check_sum + (struct vdec_mpeg12_hw_s *hw, int size) +{ + int jj; + int sum = 0; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + for (jj = 0; jj < size; jj++) + sum += data[jj]; + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + return sum; +} + +static void run(struct vdec_s *vdec, unsigned long mask, +void (*callback)(struct vdec_s *, void *), + void *arg) +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + int save_reg = READ_VREG(POWER_CTL_VLD); + int size, ret; + /* reset everything except DOS_TOP[1] and APB_CBUS[0]*/ + WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); + WRITE_VREG(DOS_SW_RESET0, 0); + WRITE_VREG(POWER_CTL_VLD, save_reg); + hw->run_count++; + vdec_reset_core(vdec); + hw->vdec_cb_arg = arg; + hw->vdec_cb = callback; + +#ifdef AGAIN_HAS_THRESHOLD + hw->pre_parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + hw->next_again_flag = 0; +#endif + + size = vdec_prepare_input(vdec, &hw->chunk); + if (size < 0) { + hw->input_empty++; + hw->dec_result = DEC_RESULT_AGAIN; + vdec_schedule_work(&hw->work); + return; + } + if (input_frame_based(vdec)) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + if (debug_enable & PRINT_FLAG_VDEC_STATUS + ) { + debug_print(DECODE_ID(hw), 0, + "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", + __func__, size, get_data_check_sum(hw, size), + data[0], data[1], data[2], data[3], + data[4], data[5], data[size - 4], + data[size - 3], data[size - 2], + data[size - 1]); + } + if (debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + + for (jj = 0; jj < size; jj++) { + if ((jj & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } else + debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s: %x %x %x %x %x size 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP), + size); + + + hw->input_empty = 0; + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s,%d, size=%d\n", __func__, __LINE__, size); + vdec_enable_input(vdec); + hw->init_flag = 1; + + if (hw->chunk) + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "input chunk offset %d, size %d\n", + hw->chunk->offset, hw->chunk->size); + + hw->dec_result = DEC_RESULT_NONE; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG12, "mmpeg12", vdec, + hw->fw->data, hw->fw->len); + if (ret < 0) { + pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, + hw->fw->name, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MPEG12; + } + if (vmpeg12_hw_ctx_restore(hw) < 0) { + hw->dec_result = DEC_RESULT_ERROR; + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "ammvdec_mpeg12: error HW context restore\n"); + vdec_schedule_work(&hw->work); + return; + } + /*wmb();*/ + hw->stat |= STAT_MC_LOAD; + hw->last_vld_level = 0; + start_process_time(hw); + amvdec_start(); + hw->stat |= STAT_VDEC_RUN; + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); +} + +static void reset(struct vdec_s *vdec) +{ + pr_info("ammvdec_mpeg12: reset.\n"); +} + +static int ammvdec_mpeg12_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct vdec_mpeg12_hw_s *hw = NULL; + + pr_info("ammvdec_mpeg12 probe start.\n"); + + if (pdata == NULL) { + pr_info("ammvdec_mpeg12 platform data undefined.\n"); + return -EFAULT; + } + + hw = vzalloc(sizeof(struct vdec_mpeg12_hw_s)); + if (hw == NULL) { + pr_info("\nammvdec_mpeg12 decoder driver alloc failed\n"); + return -ENOMEM; + } + + pdata->private = hw; + pdata->dec_status = vmmpeg12_dec_status; + pdata->run_ready = run_ready; + pdata->run = run; + pdata->reset = reset; + pdata->irq_handler = vmpeg12_isr; + pdata->threaded_irq_handler = vmpeg12_isr_thread_fn; + pdata->dump_state = vmpeg2_dump_state; + + pdata->user_data_read = vmmpeg2_user_data_read; + pdata->reset_userdata_fifo = vmmpeg2_reset_userdata_fifo; + pdata->wakeup_userdata_poll = vmmpeg2_wakeup_userdata_poll; + + if (pdata->use_vfm_path) { + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); + hw->frameinfo_enable = 1; + } + else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + PROVIDER_NAME ".%02x", pdev->id & 0xff); + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->canvas_spec[i] = 0xffffff; + } + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vf_provider_ops, pdata); + + platform_set_drvdata(pdev, pdata); + hw->canvas_mode = pdata->canvas_mode; + hw->platform_dev = pdev; + + if (pdata->sys_info) + hw->vmpeg12_amstream_dec_info = *pdata->sys_info; + + if (vmpeg12_init(hw) < 0) { + pr_info("ammvdec_mpeg12 init failed.\n"); + if (hw) { + vfree(hw); + hw = NULL; + } + pdata->dec_status = NULL; + return -ENODEV; + } + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); + } +#ifdef DUMP_USER_DATA + amvdec_mmpeg12_init_userdata_dump(hw); + reset_user_data_buf(hw); +#endif + + /*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/ + return 0; +} + +static int ammvdec_mpeg12_remove(struct platform_device *pdev) + +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hw); + int i; + + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + cancel_work_sync(&hw->userdata_push_work); + cancel_work_sync(&hw->work); + cancel_work_sync(&hw->notify_work); + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); + + if (vdec->parallel_dec == 1) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); + vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); + } + } + + if (hw->ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); + hw->ccbuf_phyAddress_virt = NULL; + hw->ccbuf_phyAddress = 0; + hw->ccbuf_phyAddress_is_remaped_nocache = 0; + + if (hw->user_data_buffer != NULL) { + kfree(hw->user_data_buffer); + hw->user_data_buffer = NULL; + } + vmmpeg2_destroy_userdata_manager(hw); + +#ifdef DUMP_USER_DATA + amvdec_mmpeg12_uninit_userdata_dump(hw); +#endif + + if (hw->fw) { + vfree(hw->fw); + hw->fw = NULL; + } + if (hw) { + vfree(hw); + hw = NULL; + } + pr_info("ammvdec_mpeg12 removed.\n"); + memset(&gvs, 0x0, sizeof(gvs)); + + return 0; +} + +/****************************************/ + +static struct platform_driver ammvdec_mpeg12_driver = { + .probe = ammvdec_mpeg12_probe, + .remove = ammvdec_mpeg12_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t ammvdec_mpeg12_profile = { + .name = "mmpeg12", + .profile = "" +}; + +static struct mconfig mmpeg12_configs[] = { + MC_PU32("stat", &stat), + MC_PU32("radr", &radr), + MC_PU32("rval", &rval), + MC_PU32("dec_control", &dec_control), + MC_PU32("error_frame_skip_level", &error_frame_skip_level), + MC_PU32("decode_timeout_val", &decode_timeout_val), +}; +static struct mconfig_node mmpeg12_node; + +static int __init ammvdec_mpeg12_driver_init_module(void) +{ + pr_info("ammvdec_mpeg12 module init\n"); + + if (platform_driver_register(&ammvdec_mpeg12_driver)) { + pr_info("failed to register ammvdec_mpeg12 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&ammvdec_mpeg12_profile); + INIT_REG_NODE_CONFIGS("media.decoder", &mmpeg12_node, + "mmpeg12", mmpeg12_configs, CONFIG_FOR_RW); + return 0; +} + +static void __exit ammvdec_mpeg12_driver_remove_module(void) +{ + pr_info("ammvdec_mpeg12 module exit.\n"); + platform_driver_unregister(&ammvdec_mpeg12_driver); +} + +/****************************************/ +module_param(dec_control, uint, 0664); +MODULE_PARM_DESC(dec_control, "\n ammvdec_mpeg12 decoder control\n"); +module_param(error_frame_skip_level, uint, 0664); +MODULE_PARM_DESC(error_frame_skip_level, + "\n ammvdec_mpeg12 error_frame_skip_level\n"); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(debug_enable, uint, 0664); +MODULE_PARM_DESC(debug_enable, + "\n ammvdec_mpeg12 debug enable\n"); +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, + "\n ammvdec_mpeg12 pre_decode_buf_level\n"); +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg12 decode_timeout_val\n"); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param(udebug_flag, uint, 0664); +MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg12 udebug_flag\n"); + +#ifdef AGAIN_HAS_THRESHOLD +module_param(again_threshold, uint, 0664); +MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); +#endif + +module_init(ammvdec_mpeg12_driver_init_module); +module_exit(ammvdec_mpeg12_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MULTI MPEG1/2 Video Decoder Driver"); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c index f6a5910316b4..0d8d4078a1d6 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c @@ -40,6 +40,10 @@ #include "../utils/decoder_bmmu_box.h" #include #include +#include + +#include + /* #define CONFIG_AM_VDEC_MPEG4_LOG */ #ifdef CONFIG_AM_VDEC_MPEG4_LOG @@ -116,6 +120,8 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); #define DUR2PTS(x) ((x) - ((x) >> 4)) +#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) + static struct vframe_s *vmpeg_vf_peek(void *); static struct vframe_s *vmpeg_vf_get(void *); static void vmpeg_vf_put(struct vframe_s *, void *); @@ -287,6 +293,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) u32 pts, pts_valid = 0, offset = 0; u64 pts_us64 = 0; u32 rate, vop_time_inc, repeat_cnt, duration = 3200; + u32 frame_size; reg = READ_VREG(MREG_BUFFEROUT); @@ -379,7 +386,8 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) *263 may need small? */ if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 3000, &pts_us64) == 0) { pts_valid = 1; last_anch_pts = pts; @@ -489,6 +497,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -535,6 +544,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) vmpeg4_amstream_dec_info.rate, picture_type); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -582,6 +592,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -697,14 +708,11 @@ static void reset_do_work(struct work_struct *work) static void vmpeg4_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; vdec_source_changed(VFORMAT_MPEG4, frame_width, frame_height, fps); - } } static void vmpeg_put_timer_func(unsigned long arg) @@ -715,8 +723,7 @@ static void vmpeg_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) - && (vf->index < DECODE_BUFFER_NUM_MAX) + if ((vf->index < DECODE_BUFFER_NUM_MAX) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(MREG_BUFFERIN, ~(1 << vf->index)); vf->index = DECODE_BUFFER_NUM_MAX; @@ -725,7 +732,9 @@ static void vmpeg_put_timer_func(unsigned long arg) } } - schedule_work(&set_clk_work); + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); if (READ_VREG(AV_SCRATCH_L)) { pr_info("mpeg4 fatal error happened,need reset !!\n"); @@ -740,6 +749,9 @@ static void vmpeg_put_timer_func(unsigned long arg) int vmpeg4_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = vmpeg4_amstream_dec_info.width; vstatus->frame_height = vmpeg4_amstream_dec_info.height; if (0 != vmpeg4_amstream_dec_info.rate) @@ -1010,45 +1022,29 @@ static void vmpeg4_local_init(void) static s32 vmpeg4_init(void) { - int r; int trickmode_fffb = 0; - int size = -1; + int size = -1, ret = -1; + char fw_name[32] = {0}; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) return -ENOMEM; - - query_video_status(0, &trickmode_fffb); - amlog_level(LOG_LEVEL_INFO, "vmpeg4_init\n"); - init_timer(&recycle_timer); - stat |= STAT_TIMER_INIT; - - amvdec_enable(); - - vmpeg4_local_init(); - - if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_3) { - size = get_firmware_data(VIDEO_DEC_MPEG4_3, buf); - - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_3\n"); - } else if (vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_4) { - size = get_firmware_data(VIDEO_DEC_MPEG4_4, buf); - - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_4\n"); - } else if (vmpeg4_amstream_dec_info.format == + if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_5) { size = get_firmware_data(VIDEO_DEC_MPEG4_5, buf); + strncpy(fw_name, "vmpeg4_mc_5", sizeof(fw_name)); amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_5\n"); } else if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_H263) { size = get_firmware_data(VIDEO_DEC_H263, buf); + strncpy(fw_name, "h263_mc", sizeof(fw_name)); - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_H263\n"); + pr_info("load VIDEO_DEC_FORMAT_H263\n"); } else - amlog_level(LOG_LEVEL_ERROR, "not supported MPEG4 format\n"); + pr_err("unsupport mpeg4 sub format %d\n", + vmpeg4_amstream_dec_info.format); if (size < 0) { pr_err("get firmware fail."); @@ -1056,32 +1052,39 @@ static s32 vmpeg4_init(void) return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_MPEG4, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_MPEG4, fw_name, buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("%s: the %s fw loading failed, err: %x\n", + fw_name, tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } vfree(buf); - stat |= STAT_MC_LOAD; + query_video_status(0, &trickmode_fffb); - /* enable AMRISC side protocol */ - r = vmpeg4_prot_init(); - if (r < 0) - return r; + init_timer(&recycle_timer); + stat |= STAT_TIMER_INIT; if (vdec_request_irq(VDEC_IRQ_1, vmpeg4_isr, "vmpeg4-irq", (void *)vmpeg4_dec_id)) { - amvdec_disable(); - amlog_level(LOG_LEVEL_ERROR, "vmpeg4 irq register error.\n"); return -ENOENT; } - stat |= STAT_ISR_REG; + vmpeg4_local_init(); + /* enable AMRISC side protocol */ + ret = vmpeg4_prot_init(); + if (ret < 0) { + if (mm_blk_handle) { + decoder_bmmu_box_free(mm_blk_handle); + mm_blk_handle = NULL; + } + return ret; + } + amvdec_enable(); fr_hint_status = VDEC_NO_NEED_HINT; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, @@ -1094,13 +1097,14 @@ static s32 vmpeg4_init(void) vf_reg_provider(&vmpeg_vf_prov); #endif if (vmpeg4_amstream_dec_info.rate != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long) vmpeg4_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -1131,9 +1135,17 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) return -EFAULT; } - if (pdata->sys_info) + if (pdata->sys_info) { vmpeg4_amstream_dec_info = *pdata->sys_info; - + if ((vmpeg4_amstream_dec_info.height != 0) && + (vmpeg4_amstream_dec_info.width > + (MAX_MPEG4_SUPPORT_SIZE/vmpeg4_amstream_dec_info.height))) { + pr_info("amvdec_mpeg4: oversize, unsupport: %d*%d\n", + vmpeg4_amstream_dec_info.width, + vmpeg4_amstream_dec_info.height); + return -EFAULT; + } + } pdata->dec_status = vmpeg4_dec_status; pdata->set_isreset = vmpeg4_set_isreset; is_reset = 0; @@ -1148,6 +1160,7 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg4 init failed.\n"); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; return -ENODEV; } @@ -1172,7 +1185,7 @@ static int amvdec_mpeg4_remove(struct platform_device *pdev) } if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); fr_hint_status = VDEC_NO_NEED_HINT; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c index f21d830360b9..84a8d38d23be 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -32,9 +32,8 @@ #include #include #include - +#include #include -#include "vmpeg4.h" #include #include "../../../stream_input/amports/amports_priv.h" @@ -42,11 +41,18 @@ #include "../utils/vdec_input.h" #include "../utils/vdec.h" #include "../utils/firmware.h" +#include "../utils/decoder_mmu_box.h" +#include "../utils/decoder_bmmu_box.h" +#include +#include "../utils/firmware.h" + +#include + #define DRIVER_NAME "ammvdec_mpeg4" #define MODULE_NAME "ammvdec_mpeg4" -#define MEM_NAME "codec_mpeg4" +#define MEM_NAME "codec_mmpeg4" #define DEBUG_PTS @@ -89,6 +95,9 @@ #define VF_POOL_SIZE 16 #define DECODE_BUFFER_NUM_MAX 4 #define PUT_INTERVAL (HZ/100) +#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) +#define WORKSPACE_SIZE (12*SZ_64K) +static u32 buf_size = 32 * 1024 * 1024; #define CTX_LMEM_SWAP_OFFSET 0 #define CTX_QUANT_MATRIX_OFFSET 0x800 @@ -99,24 +108,79 @@ #define RATE_DETECT_COUNT 5 #define DURATION_UNIT 96000 #define PTS_UNIT 90000 +#define CHECK_INTERVAL (HZ/100) #define DUR2PTS(x) ((x) - ((x) >> 4)) +#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) + #define DEC_RESULT_NONE 0 #define DEC_RESULT_DONE 1 #define DEC_RESULT_AGAIN 2 #define DEC_RESULT_ERROR 3 +#define DEC_RESULT_FORCE_EXIT 4 +#define DEC_RESULT_EOS 5 +#define DEC_DECODE_TIMEOUT 0x21 +#define DECODE_ID(hw) (hw_to_vdec(hw)->id) +#define DECODE_STOP_POS AV_SCRATCH_K +static u32 udebug_flag; static struct vframe_s *vmpeg_vf_peek(void *); static struct vframe_s *vmpeg_vf_get(void *); static void vmpeg_vf_put(struct vframe_s *, void *); static int vmpeg_vf_states(struct vframe_states *states, void *); static int vmpeg_event_cb(int type, void *data, void *private_data); +static int pre_decode_buf_level = 0x800; +static int debug_enable; +static unsigned int radr; +static unsigned int rval; + +#define VMPEG4_DEV_NUM 9 +static unsigned int max_decode_instance_num = VMPEG4_DEV_NUM; +static unsigned int max_process_time[VMPEG4_DEV_NUM]; +static unsigned int decode_timeout_val = 100; + + +#undef pr_info +#define pr_info printk +unsigned int mpeg4_debug_mask = 0xff; + +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_RUN_FLOW 0X0001 +#define PRINT_FLAG_TIMEINFO 0x0002 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_VLD_DETAIL 0x0008 +#define PRINT_FLAG_DEC_DETAIL 0x0010 +#define PRINT_FLAG_BUFFER_DETAIL 0x0020 +#define PRINT_FLAG_RESTORE 0x0040 +#define PRINT_FRAME_NUM 0x0080 +#define PRINT_FLAG_FORCE_DONE 0x0100 +#define PRINT_FLAG_COUNTER 0X0200 +#define PRINT_FRAMEBASE_DATA 0x0400 +#define PRINT_FLAG_VDEC_STATUS 0x0800 +#define PRINT_FLAG_TIMEOUT_STATUS 0x1000 + +int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((debug_enable & debug_flag) && + ((1 << index) & mpeg4_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} struct vdec_mpeg4_hw_s { spinlock_t lock; struct platform_device *platform_dev; - struct device *cma_dev; + /* struct device *cma_dev; */ DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); @@ -140,13 +204,22 @@ struct vdec_mpeg4_hw_s { u32 reg_iqidct_control; u32 reg_resync_marker_length; u32 reg_rv_ai_mb_count; + struct timer_list check_timer; + u32 decode_timeout_count; + u32 start_process_time; + u32 last_vld_level; + u8 init_flag; + u32 eos; + void *mm_blk_handle; struct vframe_chunk_s *chunk; u32 stat; - u32 buf_start; + unsigned long buf_start; u32 buf_size; + /* unsigned long cma_alloc_addr; int cma_alloc_count; + */ u32 vmpeg4_ratio; u64 vmpeg4_ratio64; u32 rate_detect; @@ -163,7 +236,7 @@ struct vdec_mpeg4_hw_s { u32 pts_missed; u32 pts_i_hit; u32 pts_i_missed; - + u32 decoded_type[DECODE_BUFFER_NUM_MAX]; u32 buffer_info[DECODE_BUFFER_NUM_MAX]; u32 pts[DECODE_BUFFER_NUM_MAX]; u64 pts64[DECODE_BUFFER_NUM_MAX]; @@ -182,6 +255,19 @@ struct vdec_mpeg4_hw_s { void (*vdec_cb)(struct vdec_s *, void *); void *vdec_cb_arg; + u32 frame_num; + u32 put_num; + u32 sys_mp4_rate; + u32 run_count; + u32 not_run_ready; + u32 buffer_not_ready; + u32 input_empty; + u32 peek_num; + u32 get_num; + u32 first_i_frame_ready; + u32 drop_frame_count; + u32 timeout_flag; + struct firmware_s *fw; }; static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); @@ -212,6 +298,7 @@ static unsigned char aspect_ratio_table[16] = { PARC_RESERVED, PARC_EXTENDED }; +static void reset_process_time(struct vdec_mpeg4_hw_s *hw); static int find_buffer(struct vdec_mpeg4_hw_s *hw) { int i; @@ -221,7 +308,7 @@ static int find_buffer(struct vdec_mpeg4_hw_s *hw) return i; } - return -1; + return DECODE_BUFFER_NUM_MAX; } static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec) @@ -342,7 +429,7 @@ static inline void vmpeg4_save_hw_context(struct vdec_mpeg4_hw_s *hw) hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); } -static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) +static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) { u32 reg; struct vframe_s *vf = NULL; @@ -351,26 +438,46 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) u32 pts, offset = 0; bool pts_valid = false; u64 pts_us64 = 0; + u32 frame_size; u32 time_increment_resolution, fixed_vop_rate, vop_time_inc; u32 repeat_cnt, duration = 3200; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); + if (hw->eos) + return IRQ_HANDLED; WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - + if (READ_VREG(AV_SCRATCH_M) != 0 && + (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_UCODE_DETAIL, + "dbg %x: %x, level %x, wp %x, rp %x, cnt %x\n", + READ_VREG(AV_SCRATCH_M), READ_VREG(AV_SCRATCH_N), + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VIFF_BIT_CNT)); + WRITE_VREG(AV_SCRATCH_M, 0); + return IRQ_HANDLED; + } reg = READ_VREG(MREG_BUFFEROUT); time_increment_resolution = READ_VREG(MP4_RATE); fixed_vop_rate = time_increment_resolution >> 16; time_increment_resolution &= 0xffff; - + if (time_increment_resolution > 0 && fixed_vop_rate == 0) + hw->sys_mp4_rate = time_increment_resolution; if (hw->vmpeg4_amstream_dec_info.rate == 0) { if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { /* fixed VOP rate */ hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * - DURATION_UNIT / - time_increment_resolution; - } + DURATION_UNIT / time_increment_resolution; + } else if (time_increment_resolution == 0 + && hw->sys_mp4_rate > 0) + time_increment_resolution = hw->sys_mp4_rate; } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "resolution=%d,fvop=%d,rate=%d\n", + time_increment_resolution, fixed_vop_rate, + hw->vmpeg4_amstream_dec_info.rate); if (reg == 2) { /* timeout when decoding next frame */ @@ -379,15 +486,24 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) * at the beginning when only VOL head is available save * HW context also, such as for the QTable from VCOP register */ - if (input_frame_based(vdec)) + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "ammvdec_mpeg4: timeout\n"); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "level=%x, vtl=%x,bcnt=%d\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VIFF_BIT_CNT)); + if (input_frame_based(vdec)) { vmpeg4_save_hw_context(hw); - + hw->timeout_flag++; + } else { hw->dec_result = DEC_RESULT_AGAIN; schedule_work(&hw->work); - + } return IRQ_HANDLED; } else { + reset_process_time(hw); picture_type = (reg >> 3) & 7; repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT); vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); @@ -395,42 +511,30 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); if (index < 0) { - pr_err("invalid buffer index."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "invalid buffer index."); hw->dec_result = DEC_RESULT_ERROR; schedule_work(&hw->work); return IRQ_HANDLED; } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "index=%d, used=%d cnt=%d, vopinc=%d\n", + index, hw->vfbuf_use[index], repeat_cnt, vop_time_inc); hw->dec_result = DEC_RESULT_DONE; - pr_debug("amvdec_mpeg4: offset = 0x%x\n", - READ_VREG(MP4_OFFSET_REG)); - if (hw->vmpeg4_amstream_dec_info.width == 0) { hw->vmpeg4_amstream_dec_info.width = READ_VREG(MP4_PIC_WH) >> 16; } -#if 0 - else { - pr_info("info width = %d, ucode width = %d\n", - hw->vmpeg4_amstream_dec_info.width, - READ_VREG(MP4_PIC_WH) >> 16); - } -#endif if (hw->vmpeg4_amstream_dec_info.height == 0) { hw->vmpeg4_amstream_dec_info.height = READ_VREG(MP4_PIC_WH) & 0xffff; } -#if 0 - else { - pr_info("info height = %d, ucode height = %d\n", - hw->vmpeg4_amstream_dec_info.height, - READ_VREG(MP4_PIC_WH) & 0xffff); - } -#endif + if (hw->vmpeg4_amstream_dec_info.rate == 0) { if (vop_time_inc < hw->last_vop_time_inc) { duration = vop_time_inc + @@ -443,7 +547,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) if (duration == hw->last_duration) { hw->rate_detect++; - if (hw->rate_detect >= RATE_DETECT_COUNT) { + if ((hw->rate_detect >= RATE_DETECT_COUNT) && + (time_increment_resolution != 0)) { hw->vmpeg4_amstream_dec_info.rate = duration * DURATION_UNIT / time_increment_resolution; @@ -463,8 +568,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) #endif } - if ((picture_type == I_PICTURE) || - (picture_type == P_PICTURE)) { + if ((I_PICTURE == picture_type) || + (P_PICTURE == picture_type)) { offset = READ_VREG(MP4_OFFSET_REG); if (hw->chunk) { hw->pts_valid[index] = hw->chunk->pts_valid; @@ -472,7 +577,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) hw->pts64[index] = hw->chunk->pts64; } else { if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 3000, &pts_us64) == 0) { hw->pts_valid[index] = true; hw->pts[index] = pts; @@ -483,9 +589,10 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) hw->pts_missed++; } } - pr_debug("I/P offset 0x%x, pts_valid %d pts=0x%x\n", + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "I/P offset 0x%x, pts_valid %d pts=0x%x,index=%d,used=%d\n", offset, hw->pts_valid[index], - hw->pts[index]); + hw->pts[index], index, hw->vfbuf_use[index]); } else { hw->pts_valid[index] = false; hw->pts[index] = 0; @@ -494,11 +601,13 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) hw->buffer_info[index] = reg; hw->vfbuf_use[index] = 0; - - pr_debug("amvdec_mpeg4: decoded buffer %d, frame_type %s\n", + hw->decoded_type[index] = picture_type; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "amvdec_mpeg4: decoded buffer %d, frame_type %s,pts=%x\n", index, (picture_type == I_PICTURE) ? "I" : - (picture_type == P_PICTURE) ? "P" : "B"); + (picture_type == P_PICTURE) ? "P" : "B", + hw->pts[index]); /* Buffer management * todo: add sequence-end flush @@ -541,15 +650,20 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) pts = hw->pts[index]; pts_us64 = hw->pts64[index]; - pr_debug("queued buffer %d, pts = 0x%x, pts_valid=%d\n", - index, pts, pts_valid); + if ((hw->first_i_frame_ready == 0) && + (I_PICTURE == hw->decoded_type[index])) + hw->first_i_frame_ready = 1; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "queued %d, pts = 0x%x, pts_valid=%d,index=%d,used=%d,type=%d,decode_type=%d\n", + index, pts, pts_valid, index, hw->vfbuf_use[index], + picture_type, hw->decoded_type[index]); if (pts_valid) { hw->last_anch_pts = pts; hw->last_anch_pts_us64 = pts_us64; hw->frame_num_since_last_anch = 0; hw->vop_time_inc_since_last_anch = 0; - } else { + } else if (input_stream_based(vdec)) { pts = hw->last_anch_pts; pts_us64 = hw->last_anch_pts_us64; @@ -606,8 +720,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) if (reg & INTERLACE_FLAG) { /* interlace */ if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_err - ("fatal error, no available buffer slot."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); return IRQ_HANDLED; } @@ -630,15 +744,31 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) set_frame_info(hw, vf, index); hw->vfbuf_use[index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "pts0=%d,pts64=%lld,w%d,h%d,dur:%d\n", + vf->pts, vf->pts_us64, + vf->width, vf->height, + vf->duration); + if ((hw->first_i_frame_ready == 0) + && (picture_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - + } if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_err("fatal error, no available buffer slot."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); hw->dec_result = DEC_RESULT_ERROR; schedule_work(&hw->work); return IRQ_HANDLED; @@ -664,16 +794,32 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) set_frame_info(hw, vf, index); hw->vfbuf_use[index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "pts1=%d,pts64=%lld,w%d,h%d,dur:%d\n", + vf->pts, vf->pts_us64, + vf->width, vf->height, + vf->duration); + if ((hw->first_i_frame_ready == 0) + && (picture_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - + } } else { /* progressive */ if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_err("fatal error, no available buffer slot."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); return IRQ_HANDLED; } @@ -697,14 +843,35 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) #endif set_frame_info(hw, vf, index); - hw->vfbuf_use[index]++; - - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "pts=%d,pts64=%lld,w%d,h%d,index=%d,used=%d,dur:%d, flag=%d, type=%d\n", + vf->pts, vf->pts_us64, + vf->width, vf->height, + index, hw->vfbuf_use[index], + vf->duration, + hw->timeout_flag, picture_type); + if ((hw->first_i_frame_ready == 0) + && (picture_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + hw->timeout_flag++; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + if (hw->timeout_flag > 2) + hw->timeout_flag = 2; + if (hw->timeout_flag && input_frame_based(vdec)) + vf->duration = duration * (hw->timeout_flag + 1); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + hw->timeout_flag = 0; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } } hw->total_frame += repeat_cnt + 1; @@ -712,19 +879,53 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) schedule_work(&hw->work); } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:frame num:%d\n", __func__, hw->frame_num); return IRQ_HANDLED; } +static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) +{ + u32 time_increment_resolution, fixed_vop_rate; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); + + if (hw->eos) + return IRQ_HANDLED; + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + time_increment_resolution = READ_VREG(MP4_RATE); + fixed_vop_rate = time_increment_resolution >> 16; + time_increment_resolution &= 0xffff; + if (time_increment_resolution > 0 && fixed_vop_rate == 0) + hw->sys_mp4_rate = time_increment_resolution; + if (hw->vmpeg4_amstream_dec_info.rate == 0) { + if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { + hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * + DURATION_UNIT / + time_increment_resolution; + } else if (time_increment_resolution == 0 + && hw->sys_mp4_rate > 0) + time_increment_resolution = hw->sys_mp4_rate; + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "resolution=%d,fvop=%d,rate=%d\n", + time_increment_resolution, fixed_vop_rate, + hw->vmpeg4_amstream_dec_info.rate); + return IRQ_WAKE_THREAD; +} static void vmpeg4_work(struct work_struct *work) { struct vdec_mpeg4_hw_s *hw = container_of(work, struct vdec_mpeg4_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); /* finished decoding one frame or error, * notify vdec core to switch context */ - amvdec_stop(); + if (hw->dec_result != DEC_RESULT_DONE) + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "mmpeg4: vmpeg_work,result=%d,status=%d\n", + hw->dec_result, hw_to_vdec(hw)->next_status); if ((hw->dec_result == DEC_RESULT_DONE) || ((hw->chunk) && @@ -733,10 +934,55 @@ static void vmpeg4_work(struct work_struct *work) hw->ctx_valid = 1; vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + } else if (hw->dec_result == DEC_RESULT_AGAIN + && (hw_to_vdec(hw)->next_status != + VDEC_STATUS_DISCONNECTED)) { + /* + stream base: stream buf empty or timeout + frame base: vdec_prepare_input fail + */ + if (!vdec_has_more_input(hw_to_vdec(hw))) { + hw->dec_result = DEC_RESULT_EOS; + vdec_schedule_work(&hw->work); + /*pr_info("%s: return\n", + __func__);*/ + return; + } + } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s: force exit\n", __func__); + if (hw->stat & STAT_ISR_REG) { + amvdec_stop(); + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + } else if (hw->dec_result == DEC_RESULT_EOS) { + /*pr_info("%s: end of stream\n", + __func__);*/ + hw->eos = 1; + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); } + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); if (hw->vdec_cb) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); @@ -750,7 +996,7 @@ static struct vframe_s *vmpeg_vf_peek(void *op_arg) if (!hw) return NULL; - + hw->peek_num++; if (kfifo_peek(&hw->display_q, &vf)) return vf; @@ -762,7 +1008,7 @@ static struct vframe_s *vmpeg_vf_get(void *op_arg) struct vframe_s *vf; struct vdec_s *vdec = op_arg; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - + hw->get_num++; if (kfifo_get(&hw->display_q, &vf)) return vf; @@ -775,7 +1021,13 @@ static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; hw->vfbuf_use[vf->index]--; - + hw->put_num++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:put num:%d\n", + __func__, hw->put_num); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "index=%d, used=%d\n", + vf->index, hw->vfbuf_use[vf->index]); kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); } @@ -807,6 +1059,9 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + if (!hw) + return -1; + vstatus->frame_width = hw->vmpeg4_amstream_dec_info.width; vstatus->frame_height = hw->vmpeg4_amstream_dec_info.height; if (0 != hw->vmpeg4_amstream_dec_info.rate) @@ -823,86 +1078,311 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) /****************************************/ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) { - int i; + int i, ret; + u32 canvas_width, canvas_height; u32 decbuf_size, decbuf_y_size; struct vdec_s *vdec = hw_to_vdec(hw); - u32 decbuf_start; + unsigned long decbuf_start; - int w = hw->vmpeg4_amstream_dec_info.width; - int h = hw->vmpeg4_amstream_dec_info.height; + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_size = 0x100000; + } else { + int w = hw->vmpeg4_amstream_dec_info.width; + int h = hw->vmpeg4_amstream_dec_info.height; + int align_w, align_h; + int max, min; + if (w == 0) + w = 1920; + if (h == 0) + h = 1088; + align_w = ALIGN(w, 64); + align_h = ALIGN(h, 64); + if (align_w > align_h) { + max = align_w; + min = align_h; + } else { + max = align_h; + min = align_w; + } + /* HD & SD */ + if ((max > 1920 || min > 1088) && + ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= + buf_size) { + canvas_width = align_w; + canvas_height = align_h; + decbuf_y_size = + ALIGN(align_w * align_h, SZ_64K); + decbuf_size = + ALIGN(align_w * align_h * 3/2, SZ_64K); + } else { /*1080p*/ + if (h > w) { + canvas_width = 1088; + canvas_height = 1920; + } else { + canvas_width = 1920; + canvas_height = 1088; + } + decbuf_y_size = 0x200000; + decbuf_size = 0x300000; + } + } - if (w == 0) - w = 1920; - if (h == 0) - h = 1088; + for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - w = ALIGN(w, 64); - h = ALIGN(h, 64); - decbuf_y_size = ALIGN(w * h, SZ_64K); - decbuf_size = ALIGN(w * h * 3/2, SZ_64K); + unsigned canvas; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) + decbuf_size = WORKSPACE_SIZE; + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &decbuf_start); + if (ret < 0) { + pr_err("mmu alloc failed! size 0x%d idx %d\n", + decbuf_size, i); + return ret; + } - decbuf_start = hw->buf_start + CTX_DECBUF_OFFSET; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + hw->buf_start = decbuf_start; + } else { + if (vdec->parallel_dec == 1) { + unsigned tmp; + if (canvas_u(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~(0xffff << 8); + hw->canvas_spec[i] |= tmp << 8; + hw->canvas_spec[i] |= tmp << 16; + } + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } + canvas = hw->canvas_spec[i]; + } else { + canvas = vdec->get_canvas(i, 2); + hw->canvas_spec[i] = canvas; + } - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { -#ifdef NV21 - unsigned int canvas = vdec->get_canvas(i, 2); -#else - unsigned int canvas = vdec->get_canvas(i, 3); -#endif - - hw->canvas_spec[i] = canvas; - -#ifdef NV21 - hw->canvas_config[i][0].phy_addr = decbuf_start + - i * decbuf_size; - hw->canvas_config[i][0].width = w; - hw->canvas_config[i][0].height = h; - hw->canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32; + hw->canvas_config[i][0].phy_addr = + decbuf_start; + hw->canvas_config[i][0].width = + canvas_width; + hw->canvas_config[i][0].height = + canvas_height; + hw->canvas_config[i][0].block_mode = + CANVAS_BLKMODE_32X32; canvas_config_config(canvas_y(canvas), &hw->canvas_config[i][0]); - hw->canvas_config[i][1].phy_addr = decbuf_start + - i * decbuf_size + decbuf_y_size; - hw->canvas_config[i][1].width = w; - hw->canvas_config[i][1].height = h / 2; - hw->canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32; + hw->canvas_config[i][1].phy_addr = + decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = + canvas_width; + hw->canvas_config[i][1].height = + canvas_height / 2; + hw->canvas_config[i][1].block_mode = + CANVAS_BLKMODE_32X32; canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]); -#else - hw->canvas_config[i][0].phy_addr = decbuf_start + - i * decbuf_size; - hw->canvas_config[i][0].width = w; - hw->canvas_config[i][0].height = h; - hw->canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_y(canvas), - &hw->canvas_config[i][0]); - - hw->canvas_config[i][1].phy_addr = decbuf_start + - i * decbuf_size + decbuf_y_size; - hw->canvas_config[i][1].width = w / 2; - hw->canvas_config[i][1].height = h / 2; - hw->canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_u(canvas), - &hw->canvas_config[i][1]); - - hw->canvas_config[i][2].phy_addr = decbuf_start + - i * decbuf_size + decbuf_y_size + - decbuf_uv_size; - hw->canvas_config[i][2].width = w / 2; - hw->canvas_config[i][2].height = h / 2; - hw->canvas_config[i][2].block_mode = CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_v(canvas), - &hw->canvas_config[i][2]); -#endif + } } return 0; } +static void vmpeg4_dump_state(struct vdec_s *vdec) +{ + struct vdec_mpeg4_hw_s *hw = + (struct vdec_mpeg4_hw_s *)(vdec->private); + u32 i; + mmpeg4_debug_print(DECODE_ID(hw), 0, + "====== %s\n", __func__); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "width/height (%d/%d), i_fram:%d, buffer_not_ready %d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height, + hw->first_i_frame_ready, + hw->buffer_not_ready + ); + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "index %d, used %d\n", i, hw->vfbuf_use[i]); + } + + mmpeg4_debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d\n", + input_frame_based(vdec), + hw->eos, + hw->stat, + hw->dec_result, + hw->frame_num + ); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), put_frm %d run %d not_run_ready %d input_empty %d,drop %d\n", + input_frame_based(vdec), + hw->put_num, + hw->run_count, + hw->not_run_ready, + hw->input_empty, + hw->drop_frame_count + ); + + if (vf_get_receiver(vdec->vf_provider_name)) { + enum receviver_start_e state = + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "\nreceiver(%s) state %d\n", + vdec->vf_provider_name, + state); + } + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", + __func__, + kfifo_len(&hw->newframe_q), + VF_POOL_SIZE, + kfifo_len(&hw->display_q), + VF_POOL_SIZE, + hw->peek_num, + hw->get_num, + hw->put_num + ); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VIFF_BIT_CNT=0x%x\n", + READ_VREG(VIFF_BIT_CNT)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_LEVEL=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_WP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_RP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_RP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_RP)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_WP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_WP)); + if (input_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + if (hw->chunk && hw->chunk->block && + hw->chunk->size > 0) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + mmpeg4_debug_print(DECODE_ID(hw), 0, + "frame data size 0x%x\n", + hw->chunk->size); + for (jj = 0; jj < hw->chunk->size; jj++) { + if ((jj & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + } +} + +static void reset_process_time(struct vdec_mpeg4_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[DECODE_ID(hw)]) + max_process_time[DECODE_ID(hw)] = process_time; + } +} +static void start_process_time(struct vdec_mpeg4_hw_s *hw) +{ + hw->decode_timeout_count = 2; + hw->start_process_time = jiffies; +} + +static void timeout_process(struct vdec_mpeg4_hw_s *hw) +{ + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEOUT_STATUS, + "%s decoder timeout\n", __func__); + reset_process_time(hw); + hw->first_i_frame_ready = 0; + hw->dec_result = DEC_RESULT_DONE; + vdec_schedule_work(&hw->work); +} + + +static void check_timer_func(unsigned long arg) +{ + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)arg; + struct vdec_s *vdec = hw_to_vdec(hw); + unsigned int timeout_val = decode_timeout_val; + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + + if (debug_enable == 0 && + (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && + (timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > timeout_val)) { + if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + } + + if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "vdec requested to be disconnected\n"); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); +} static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) { @@ -939,11 +1419,12 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); - pr_debug("vmpeg4_hw_ctx_restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d\n", + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, + "restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d,index=%d\n", READ_VREG(MREG_REF0), READ_VREG(MREG_REF1), READ_VREG(REC_CANVAS_ADDR), - hw->ctx_valid); + hw->ctx_valid, index); /* notify ucode the buffer start address */ WRITE_VREG(MEM_OFFSET_REG, hw->buf_start); @@ -1011,7 +1492,7 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vmpeg4_rotation = (((unsigned long) hw->vmpeg4_amstream_dec_info.param) >> 16) & 0xffff; - + hw->sys_mp4_rate = hw->vmpeg4_amstream_dec_info.rate; hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0; hw->total_frame = 0; @@ -1025,8 +1506,21 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vop_time_inc_since_last_anch = 0; hw->frame_num_since_last_anch = 0; + hw->frame_num = 0; + hw->put_num = 0; + hw->run_count = 0; + hw->not_run_ready = 0; + hw->input_empty = 0; + hw->peek_num = 0; + hw->get_num = 0; hw->pts_hit = hw->pts_missed = hw->pts_i_hit = hw->pts_i_missed = 0; + hw->refs[0] = -1; + hw->refs[1] = -1; + hw->first_i_frame_ready = 0; + hw->drop_frame_count = 0; + hw->buffer_not_ready = 0; + hw->timeout_flag = 0; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) hw->vfbuf_use[i] = 0; @@ -1040,11 +1534,21 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); } - + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + hw->mm_blk_handle = decoder_bmmu_box_alloc_box( + DRIVER_NAME, + 0, + MAX_BMMU_BUFFER_NUM, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); INIT_WORK(&hw->work, vmpeg4_work); } -static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) +static s32 vmmpeg4_init(struct vdec_mpeg4_hw_s *hw) { int trickmode_fffb = 0; int size = -1, fw_size = 0x1000 * 16; @@ -1055,29 +1559,19 @@ static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) return -ENOMEM; if (hw->vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_3) { - size = get_firmware_data(VIDEO_DEC_MPEG4_3, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_MPEG4_3\n"); - } else if (hw->vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_4) { - size = get_firmware_data(VIDEO_DEC_MPEG4_4, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_MPEG4_4\n"); - } else if (hw->vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_5) { - size = get_firmware_data(VIDEO_DEC_MPEG4_5, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_MPEG4_5\n"); + size = get_firmware_data(VIDEO_DEC_MPEG4_5_MULTI, fw->data); + strncpy(fw->name, "mmpeg4_mc_5", sizeof(fw->name)); } else if (hw->vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_H263) { - size = get_firmware_data(VIDEO_DEC_H263, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_H263\n"); - } - + size = get_firmware_data(VIDEO_DEC_H263_MULTI, fw->data); + strncpy(fw->name, "mh263_mc", sizeof(fw->name)); + } else + pr_err("unsupport mpeg4 sub format %d\n", + hw->vmpeg4_amstream_dec_info.format); + pr_info("mmpeg4 get fw %s, size %x\n", fw->name, size); if (size < 0) { - pr_err("get firmware fail."); + pr_err("get firmware failed."); vfree(fw); return -1; } @@ -1087,11 +1581,20 @@ static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) query_video_status(0, &trickmode_fffb); - pr_info("vmpeg4_init\n"); + pr_info("%s\n", __func__); amvdec_enable(); + init_timer(&hw->check_timer); + hw->check_timer.data = (unsigned long)hw; + hw->check_timer.function = check_timer_func; + hw->check_timer.expires = jiffies + CHECK_INTERVAL; + hw->stat |= STAT_TIMER_ARM; + hw->eos = 0; + WRITE_VREG(DECODE_STOP_POS, udebug_flag); + vmpeg4_local_init(hw); + wmb(); return 0; } @@ -1100,10 +1603,57 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { int index; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + if (hw->eos) + return 0; + if (vdec_stream_based(vdec) && (hw->init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + if (level < pre_decode_buf_level) { + hw->not_run_ready++; + return 0; + } + } index = find_buffer(hw); + if (index >= DECODE_BUFFER_NUM_MAX) { + hw->buffer_not_ready++; + return 0; + } + hw->not_run_ready = 0; + hw->buffer_not_ready = 0; + if (vdec->parallel_dec == 1) + return (unsigned long)(CORE_MASK_VDEC_1); + else + return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); +} - return (index >= 0) ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; +static unsigned char get_data_check_sum + (struct vdec_mpeg4_hw_s *hw, int size) +{ + int jj; + int sum = 0; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + for (jj = 0; jj < size; jj++) + sum += data[jj]; + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + return sum; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -1111,8 +1661,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; int save_reg = READ_VREG(POWER_CTL_VLD); - int ret = -1; + int size, ret = 0; + hw->run_count++; /* reset everything except DOS_TOP[1] and APB_CBUS[0] */ WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); WRITE_VREG(DOS_SW_RESET0, 0); @@ -1120,72 +1671,163 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->vdec_cb_arg = arg; hw->vdec_cb = callback; - - ret = vdec_prepare_input(vdec, &hw->chunk); - if (ret < 0) { - pr_debug("amvdec_mpeg4: Input not ready\n"); + vdec_reset_core(vdec); + size = vdec_prepare_input(vdec, &hw->chunk); + if (size < 0) { + hw->input_empty++; hw->dec_result = DEC_RESULT_AGAIN; schedule_work(&hw->work); return; } - vdec_enable_input(vdec); + if (input_frame_based(vdec)) { + u8 *data = NULL; - if (hw->chunk) - pr_debug("input chunk offset %d, size %d\n", - hw->chunk->offset, hw->chunk->size); + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + if (debug_enable & PRINT_FLAG_VDEC_STATUS + ) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", + __func__, size, get_data_check_sum(hw, size), + data[0], data[1], data[2], data[3], + data[4], data[5], data[size - 4], + data[size - 3], data[size - 2], + data[size - 1]); + } + if (debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + + for (jj = 0; jj < size; jj++) { + if ((jj & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } else + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s: %x %x %x %x %x size 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP), + size); + + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s,%d, size=%d, %x %x %x %x %x\n", + __func__, __LINE__, size, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP)); hw->dec_result = DEC_RESULT_NONE; - - if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) { - pr_err("VIDEO_DEC_FORMAT_MPEG4 ucode loading failed\n"); - hw->dec_result = DEC_RESULT_ERROR; - schedule_work(&hw->work); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG4,hw->fw->name, vdec, + hw->fw->data, hw->fw->len); + if (ret < 0) { + pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, + hw->fw->name, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MPEG4; } - if (vmpeg4_hw_ctx_restore(hw) < 0) { hw->dec_result = DEC_RESULT_ERROR; - pr_err("amvdec_mpeg4: error HW context restore\n"); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "amvdec_mpeg4: error HW context restore\n"); schedule_work(&hw->work); return; } - + hw->input_empty = 0; + hw->last_vld_level = 0; + start_process_time(hw); + vdec_enable_input(vdec); /* wmb before ISR is handled */ wmb(); amvdec_start(); + hw->stat |= STAT_VDEC_RUN; + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); } +static int vmpeg4_stop(struct vdec_mpeg4_hw_s *hw) +{ + cancel_work_sync(&hw->work); + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + + if (hw->fw) { + vfree(hw->fw); + hw->fw = NULL; + } + return 0; +} static void reset(struct vdec_s *vdec) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - pr_info("amvdec_mpeg4: reset.\n"); + pr_info("amvdec_mmpeg4: reset.\n"); vmpeg4_local_init(hw); hw->ctx_valid = false; } -static int amvdec_mpeg4_probe(struct platform_device *pdev) +static int ammvdec_mpeg4_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mpeg4_hw_s *hw = NULL; - pr_info("amvdec_mpeg4[%d] probe start.\n", pdev->id); + pr_info("%s [%d] probe start.\n", __func__, pdev->id); if (pdata == NULL) { - pr_err("ammvdec_mpeg4 memory resource undefined.\n"); + pr_err("%s memory resource undefined.\n", __func__); return -EFAULT; } - hw = (struct vdec_mpeg4_hw_s *)devm_kzalloc(&pdev->dev, - sizeof(struct vdec_mpeg4_hw_s), GFP_KERNEL); + hw = vmalloc(sizeof(struct vdec_mpeg4_hw_s)); if (hw == NULL) { - pr_info("\namvdec_mpeg4 decoder driver alloc failed\n"); + pr_err("\namvdec_mpeg4 decoder driver alloc failed\n"); return -ENOMEM; } + memset(hw, 0, sizeof(struct vdec_mpeg4_hw_s)); pdata->private = hw; pdata->dec_status = dec_status; @@ -1194,7 +1836,8 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) pdata->run = run; pdata->reset = reset; pdata->irq_handler = vmpeg4_isr; - + pdata->threaded_irq_handler = vmpeg4_isr_thread_fn; + pdata->dump_state = vmpeg4_dump_state; if (pdata->use_vfm_path) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, @@ -1203,14 +1846,20 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, PROVIDER_NAME ".%02x", pdev->id & 0xff); - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vf_provider_ops, pdata); + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->canvas_spec[i] = 0xffffff; + } + + vf_provider_init(&pdata->vframe_provider, + pdata->vf_provider_name, &vf_provider_ops, pdata); platform_set_drvdata(pdev, pdata); - hw->platform_dev = pdev; - hw->cma_dev = pdata->cma_dev; +/* + hw->cma_dev = pdata->cma_dev; hw->cma_alloc_count = PAGE_ALIGN(DEFAULT_MEM_SIZE) / PAGE_SIZE; hw->cma_alloc_addr = codec_mm_alloc_for_dma(MEM_NAME, hw->cma_alloc_count, @@ -1220,59 +1869,106 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) pr_err("codec_mm alloc failed, request buf size 0x%lx\n", hw->cma_alloc_count * PAGE_SIZE); hw->cma_alloc_count = 0; + if (hw) { + vfree((void *)hw); + hw = NULL; + } return -ENOMEM; } hw->buf_start = hw->cma_alloc_addr; hw->buf_size = DEFAULT_MEM_SIZE; - - if (pdata->sys_info) +*/ + if (pdata->sys_info) { hw->vmpeg4_amstream_dec_info = *pdata->sys_info; + if ((hw->vmpeg4_amstream_dec_info.height != 0) && + (hw->vmpeg4_amstream_dec_info.width > + (MAX_MPEG4_SUPPORT_SIZE/hw->vmpeg4_amstream_dec_info.height))) { + pr_info("ammvdec_mpeg4: oversize, unsupport: %d*%d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height); + pdata->dec_status = NULL; + vfree((void *)hw); + hw = NULL; + return -EFAULT; + } + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "W:%d,H:%d,rate=%d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height, + hw->vmpeg4_amstream_dec_info.rate); + hw->vmpeg4_amstream_dec_info.height = 0; + hw->vmpeg4_amstream_dec_info.width = 0; - if (vmpeg4_init(hw) < 0) { - pr_err("amvdec_mpeg4 init failed.\n"); - + if (vmmpeg4_init(hw) < 0) { + pr_err("%s init failed.\n", __func__); +/* + if (hw->cma_alloc_addr) { + codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); + hw->cma_alloc_count = 0; + } +*/ + if (hw) { + vfree((void *)hw); + hw = NULL; + } + pdata->dec_status = NULL; return -ENODEV; } - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); + } return 0; } -static int amvdec_mpeg4_remove(struct platform_device *pdev) +static int ammvdec_mpeg4_remove(struct platform_device *pdev) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hw); + int i; - - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - amvdec_disable(); - + vmpeg4_stop(hw); + /* if (hw->cma_alloc_addr) { pr_info("codec_mm release buffer 0x%lx\n", hw->cma_alloc_addr); codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); hw->cma_alloc_count = 0; } + */ + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - vfree(hw->fw); - hw->fw = NULL; + if (vdec->parallel_dec == 1) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); + vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); + } + } pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); pr_info("total frame %d, rate %d\n", hw->total_frame, hw->vmpeg4_amstream_dec_info.rate); + vfree((void *)hw); + hw = NULL; return 0; } /****************************************/ -static struct platform_driver amvdec_mpeg4_driver = { - .probe = amvdec_mpeg4_probe, - .remove = amvdec_mpeg4_remove, +static struct platform_driver ammvdec_mpeg4_driver = { + .probe = ammvdec_mpeg4_probe, + .remove = ammvdec_mpeg4_remove, #ifdef CONFIG_PM .suspend = amvdec_suspend, .resume = amvdec_resume, @@ -1287,29 +1983,49 @@ static struct codec_profile_t amvdec_mpeg4_profile = { .profile = "" }; -static int __init amvdec_mmpeg4_driver_init_module(void) +static int __init ammvdec_mpeg4_driver_init_module(void) { - pr_info("amvdec_mmpeg4 module init\n"); + pr_info("%s \n", __func__); - if (platform_driver_register(&amvdec_mpeg4_driver)) { - pr_err("failed to register amvdec_mpeg4 driver\n"); + if (platform_driver_register(&ammvdec_mpeg4_driver)) { + pr_err("failed to register ammvdec_mpeg4 driver\n"); return -ENODEV; } vcodec_profile_register(&amvdec_mpeg4_profile); return 0; } -static void __exit amvdec_mmpeg4_driver_remove_module(void) +static void __exit ammvdec_mpeg4_driver_remove_module(void) { - pr_info("amvdec_mmpeg4 module remove.\n"); + pr_info("ammvdec_mpeg4 module remove.\n"); - platform_driver_unregister(&amvdec_mpeg4_driver); + platform_driver_unregister(&ammvdec_mpeg4_driver); } /****************************************/ +module_param(debug_enable, uint, 0664); +MODULE_PARM_DESC(debug_enable, + "\n ammvdec_mpeg4 debug enable\n"); -module_init(amvdec_mmpeg4_driver_init_module); -module_exit(amvdec_mmpeg4_driver_remove_module); +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg4 decode_timeout_val\n"); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, + "\n ammvdec_ mpeg4 pre_decode_buf_level\n"); + +module_param(udebug_flag, uint, 0664); +MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg4 udebug_flag\n"); +module_init(ammvdec_mpeg4_driver_init_module); +module_exit(ammvdec_mpeg4_driver_remove_module); MODULE_DESCRIPTION("AMLOGIC MPEG4 Video Decoder Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c index ef0f340d2b78..afce94eee6bf 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c @@ -52,6 +52,10 @@ #include #include #include "../utils/firmware.h" +#include + +#include + #define DRIVER_NAME "amvdec_real" #define MODULE_NAME "amvdec_real" @@ -354,6 +358,7 @@ static irqreturn_t vreal_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); frame_count++; vf_notify_receiver(PROVIDER_NAME, @@ -499,7 +504,7 @@ static void vreal_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) && (vf->index < VF_BUF_NUM) + if ((vf->index < VF_BUF_NUM) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(TO_AMRISC, ~(1 << vf->index)); vf->index = VF_BUF_NUM; @@ -518,6 +523,9 @@ static void vreal_put_timer_func(unsigned long arg) int vreal_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = vreal_amstream_dec_info.width; vstatus->frame_height = vreal_amstream_dec_info.height; if (0 != vreal_amstream_dec_info.rate) @@ -793,6 +801,7 @@ static void load_block_data(void *dest, unsigned int count) s32 vreal_init(struct vdec_s *vdec) { int ret = -1, size = -1; + char fw_name[32] = {0}; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) @@ -832,10 +841,12 @@ s32 vreal_init(struct vdec_s *vdec) while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) ; size = get_firmware_data(VIDEO_DEC_REAL_V8, buf); + strncpy(fw_name, "vreal_mc_8", sizeof(fw_name)); pr_info("load VIDEO_DEC_FORMAT_REAL_8\n"); } else if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_9) { size = get_firmware_data(VIDEO_DEC_REAL_V9, buf); + strncpy(fw_name, "vreal_mc_9", sizeof(fw_name)); pr_info("load VIDEO_DEC_FORMAT_REAL_9\n"); } else @@ -848,12 +859,14 @@ s32 vreal_init(struct vdec_s *vdec) vfree(buf); return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_REAL, NULL, buf) < 0) { + + ret = amvdec_loadmc_ex(VFORMAT_REAL, fw_name, buf); + if (ret < 0) { rmparser_release(); amvdec_disable(); vfree(buf); + pr_err("%s: the %s fw loading failed, err: %x\n", + fw_name, tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -935,6 +948,7 @@ static int amvdec_real_probe(struct platform_device *pdev) if (vreal_init(pdata) < 0) { pr_info("amvdec_real init failed.\n"); + pdata->dec_status = NULL; return -ENODEV; } INIT_WORK(&set_clk_work, vreal_set_clk); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile index 92eadc3e6ff2..ee7dbf425f11 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile @@ -2,3 +2,6 @@ obj-m += decoder_common.o decoder_common-objs += utils.o vdec.o vdec_input.o amvdec.o decoder_common-objs += decoder_mmu_box.o decoder_bmmu_box.o decoder_common-objs += config_parser.o secprot.o vdec_profile.o +decoder_common-objs += amstream_profile.o +decoder_common-objs += frame_check.o amlogic_fbc_hook.o + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c new file mode 100644 index 000000000000..b6179fb9a629 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c @@ -0,0 +1,104 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#include +#include +#include + +#include "amlogic_fbc_hook.h" +static AMLOGIC_FBC_vframe_decoder_fun_t g_decoder_fun; +static AMLOGIC_FBC_vframe_encoder_fun_t g_encoder_fun; + + +int AMLOGIC_FBC_vframe_decoder( + void *dstyuv[4], + struct vframe_s *vf, + int out_format, + int flags) + +{ + if (g_decoder_fun) { + return g_decoder_fun(dstyuv, + vf, + out_format, + flags); + } + printk("no AMLOGIC_FBC_vframe_decoder ERRR!!\n"); + return -1; +} +EXPORT_SYMBOL(AMLOGIC_FBC_vframe_decoder); + +int AMLOGIC_FBC_vframe_encoder( + void *srcyuv[4], + void *dst_header, + void *dst_body, + int in_format, + int flags) + +{ + if (g_encoder_fun) { + return g_encoder_fun( + srcyuv, + dst_header, + dst_body, + in_format, + flags); + } + printk("no AMLOGIC_FBC_vframe_encoder ERRR!!\n"); + return -1; +} +EXPORT_SYMBOL(AMLOGIC_FBC_vframe_encoder); + +int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn) +{ + if (g_decoder_fun) { + pr_err("error!!,AMLOGIC_FBC dec have register\n"); + return -1; + } + printk("register_amlogic_afbc_dec_fun\n"); + g_decoder_fun = fn; + return 0; +} +EXPORT_SYMBOL(register_amlogic_afbc_dec_fun); + +int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn) +{ + if (g_encoder_fun) { + pr_err("error!!,AMLOGIC_FBC enc have register\n"); + return -1; + } + g_encoder_fun = fn; + return 0; +} +EXPORT_SYMBOL(register_amlogic_afbc_enc_fun); + +int unregister_amlogic_afbc_dec_fun(void) +{ + g_decoder_fun = NULL; + pr_err("unregister_amlogic_afbc_dec_fun\n"); + return 0; +} +EXPORT_SYMBOL(unregister_amlogic_afbc_dec_fun); + +int unregister_amlogic_afbc_enc_fun(void) +{ + g_encoder_fun = NULL; + pr_err("unregister_amlogic_afbc_dec_fun\n"); + return 0; +} +EXPORT_SYMBOL(unregister_amlogic_afbc_enc_fun); + + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h new file mode 100644 index 000000000000..7eec4b719e9f --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h @@ -0,0 +1,55 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef AMLGIC_FBC_HEADER___ +#define AMLGIC_FBC_HEADER___ +#include +/* +unsigned short *planes[4], + unsigned char *buf, + unsigned *v2_head_buf // v2_head_buf_size=(((frame_info->mbw + 1)>>1)*2) * (((frame_info->mbh + 15)>>4)*16) +); +*/ + +int AMLOGIC_FBC_vframe_decoder( + void *dstyuv[4], + struct vframe_s *vf, + int out_format, + int flags); +int AMLOGIC_FBC_vframe_encoder( + void *srcyuv[4], + void *dst_header, + void *dst_body, + int in_format, + int flags); + +typedef int (*AMLOGIC_FBC_vframe_decoder_fun_t)( + void **, + struct vframe_s *, + int, + int); +typedef int (*AMLOGIC_FBC_vframe_encoder_fun_t)( + void **, + void *, + void *, + int, + int); +int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn); +int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn); +int unregister_amlogic_afbc_dec_fun(void); +int unregister_amlogic_afbc_enc_fun(void); +#endif \ No newline at end of file diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c new file mode 100644 index 000000000000..93f50c793068 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c @@ -0,0 +1,54 @@ +/* + * drivers/amlogic/media/stream_input/amports/amstream_profile.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include + +static const struct codec_profile_t *vcodec_profile[SUPPORT_VDEC_NUM] = { 0 }; + +static int vcodec_profile_idx; + +ssize_t vcodec_profile_read(char *buf) +{ + char *pbuf = buf; + int i = 0; + + for (i = 0; i < vcodec_profile_idx; i++) { + pbuf += snprintf(pbuf, PAGE_SIZE - (pbuf - buf), "%s:%s;\n", vcodec_profile[i]->name, + vcodec_profile[i]->profile); + } + + return pbuf - buf; +} +EXPORT_SYMBOL(vcodec_profile_read); + +int vcodec_profile_register(const struct codec_profile_t *vdec_profile) +{ + if (vcodec_profile_idx < SUPPORT_VDEC_NUM) { + vcodec_profile[vcodec_profile_idx] = vdec_profile; + vcodec_profile_idx++; + pr_debug("regist %s codec profile\n", vdec_profile->name); + + } + + return 0; +} +EXPORT_SYMBOL(vcodec_profile_register); + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c index 7289fece7d21..1d4e6f5a49eb 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c @@ -14,7 +14,7 @@ * more details. * */ - +#define DEBUG #include #include #include @@ -44,6 +44,7 @@ #include #include "firmware.h" #include +#include "../../../common/chips/decoder_cpu_ver_info.h" #define MC_SIZE (4096 * 16) @@ -73,14 +74,14 @@ static void amvdec_pg_enable(bool enable) /* AMVDEC_CLK_GATE_ON(VLD_CLK); */ AMVDEC_CLK_GATE_ON(AMRISC); /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) WRITE_VREG(GCLK_EN, 0x3ff); /* #endif */ CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); } else { AMVDEC_CLK_GATE_OFF(AMRISC); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) { if (time_after(jiffies, timeout)) { @@ -94,7 +95,7 @@ static void amvdec_pg_enable(bool enable) } AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(DBLK_STATUS) & 1) { if (time_after(jiffies, timeout)) { @@ -107,7 +108,7 @@ static void amvdec_pg_enable(bool enable) } } AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(MC_STATUS0) & 1) { if (time_after(jiffies, timeout)) { @@ -120,7 +121,7 @@ static void amvdec_pg_enable(bool enable) } } AMVDEC_CLK_GATE_OFF(MC_CLK); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) { if (time_after(jiffies, timeout)) break; @@ -266,7 +267,7 @@ static s32 am_vdec_loadmc_ex(struct vdec_s *vdec, pr_err("loading firmware %s to vdec ram failed!\n", name); return err; } - pr_debug("loading firmware %s to vdec ram ok!\n", name); + return err; } @@ -285,7 +286,7 @@ static s32 am_vdec_loadmc_buf_ex(struct vdec_s *vdec, pr_err("loading firmware to vdec ram failed!\n"); return err; } - pr_debug("loading firmware to vdec ram ok!\n"); + return err; } @@ -311,10 +312,11 @@ static s32 am_loadmc_ex(enum vformat_e type, err = (*load)((u32 *) pmc_addr); if (err < 0) { pr_err("loading firmware %s to vdec ram failed!\n", name); + vfree(mc_addr); return err; } vfree(mc_addr); - pr_debug("loading firmware %s to vdec ram ok!\n", name); + return err; } @@ -379,6 +381,7 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) unsigned int format = FIRMWARE_MAX; unsigned int vdec = OPTEE_VDEC_LEGENCY; char *name = __getname(); + bool is_swap = false; sprintf(name, "%s", fw_name ? fw_name : "null"); @@ -395,11 +398,17 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) break; case VFORMAT_MPEG12: - format = VIDEO_DEC_MPEG12; + if (!strcmp(name, "mpeg12")) + format = VIDEO_DEC_MPEG12; + else if (!strcmp(name, "mmpeg12")) + format = VIDEO_DEC_MPEG12_MULTI; break; case VFORMAT_MJPEG: - format = VIDEO_DEC_MJPEG; + if (!strcmp(name, "mmjpeg")) + format = VIDEO_DEC_MJPEG_MULTI; + else + format = VIDEO_DEC_MJPEG; break; case VFORMAT_VP9: @@ -415,10 +424,14 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) break; case VFORMAT_HEVC: - if (!strcmp(name, "vh265_mc")) - format = VIDEO_DEC_HEVC; - else + if (!strcmp(name, "h265_mmu")) format = VIDEO_DEC_HEVC_MMU; + else if (!strcmp(name, "hevc_mmu_swap")) { + format = VIDEO_DEC_HEVC_MMU_SWAP; + vdec = OPTEE_VDEC_HEVC; + is_swap = true; + } else + format = VIDEO_DEC_HEVC; break; case VFORMAT_REAL: @@ -429,30 +442,53 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) break; case VFORMAT_MPEG4: - if (!strcmp(name, "vmpeg4_mc_311")) - format = VIDEO_DEC_MPEG4_3; - else if (!strcmp(name, "vmpeg4_mc_4")) - format = VIDEO_DEC_MPEG4_4; + if (!strcmp(name, "mmpeg4_mc_5")) + format = VIDEO_DEC_MPEG4_5_MULTI; + else if ((!strcmp(name, "mh263_mc"))) + format = VIDEO_DEC_H263_MULTI; else if (!strcmp(name, "vmpeg4_mc_5")) format = VIDEO_DEC_MPEG4_5; else if (!strcmp(name, "h263_mc")) - format = VIDEO_DEC_FORMAT_H263; + format = VIDEO_DEC_H263; + /*not support now*/ + else if (!strcmp(name, "vmpeg4_mc_311")) + format = VIDEO_DEC_MPEG4_3; + else if (!strcmp(name, "vmpeg4_mc_4")) + format = VIDEO_DEC_MPEG4_4; + break; + + case VFORMAT_H264_4K2K: + if (!strcmp(name, "single_core")) + format = VIDEO_DEC_H264_4k2K_SINGLE; + else + format = VIDEO_DEC_H264_4k2K; + break; + + case VFORMAT_H264MVC: + format = VIDEO_DEC_H264_MVC; + break; + + case VFORMAT_H264: + if (!strcmp(name, "mh264")) + format = VIDEO_DEC_H264_MULTI; + else if (!strcmp(name, "mh264_mmu")) { + format = VIDEO_DEC_H264_MULTI_MMU; + vdec = OPTEE_VDEC_HEVC; + } else + format = VIDEO_DEC_H264; break; default: - if (!strcmp(name, "vh265_mc")) - format = VIDEO_DEC_HEVC; - else if (!strcmp(name, "vh265_mc_mmu")) - format = VIDEO_DEC_HEVC_MMU; - else if (!strcmp(name, "vmmjpeg_mc")) - format = VIDEO_DEC_MJPEG_MULTI; - else - pr_info("unknow dec format\n"); + pr_info("Unknow vdec format!\n"); break; } - if (format < FIRMWARE_MAX) - ret = tee_load_video_fw(format, vdec); + if (format < FIRMWARE_MAX) { + if (is_swap) + ret = tee_load_video_fw_swap(format, vdec, is_swap); + else + ret = tee_load_video_fw(format, vdec); + } __putname(name); @@ -469,18 +505,23 @@ s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def) } EXPORT_SYMBOL(amvdec_loadmc_ex); -s32 amvdec_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def) +s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *def) { if (tee_enabled()) - return optee_load_fw(FIRMWARE_MAX, name); + return optee_load_fw(type, name); else - return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc); + return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc); } EXPORT_SYMBOL(amvdec_vdec_loadmc_ex); -s32 amvdec_vdec_loadmc_buf_ex(struct vdec_s *vdec, char *buf, int size) +s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *buf, int size) { - return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc); + if (tee_enabled()) + return optee_load_fw(type, name); + else + return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc); } EXPORT_SYMBOL(amvdec_vdec_loadmc_buf_ex); @@ -659,19 +700,20 @@ s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def) else return am_loadmc_ex(type, name, def, &amhevc_loadmc); else - return 0; + return -1; } EXPORT_SYMBOL(amhevc_loadmc_ex); -s32 amhevc_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def) +s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec, + const char *name, char *def) { if (has_hevc_vdec()) if (tee_enabled()) - return optee_load_fw(FIRMWARE_MAX, name); + return optee_load_fw(type, name); else - return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc); + return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc); else - return 0; + return -1; } EXPORT_SYMBOL(amhevc_vdec_loadmc_ex); @@ -682,7 +724,7 @@ void amvdec_start(void) #endif /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); @@ -768,7 +810,7 @@ EXPORT_SYMBOL(amhevc_start); void amvdec_stop(void) { - ulong timeout = jiffies + HZ; + ulong timeout = jiffies + HZ/10; WRITE_VREG(MPSR, 0); WRITE_VREG(CPSR, 0); @@ -778,8 +820,14 @@ void amvdec_stop(void) break; } + timeout = jiffies + HZ/10; + while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); @@ -811,7 +859,7 @@ EXPORT_SYMBOL(amvdec_stop); void amvdec2_stop(void) { if (has_vdec2()) { - ulong timeout = jiffies + HZ; + ulong timeout = jiffies + HZ/10; WRITE_VREG(VDEC2_MPSR, 0); WRITE_VREG(VDEC2_CPSR, 0); @@ -841,7 +889,7 @@ EXPORT_SYMBOL(amhcodec_stop); void amhevc_stop(void) { if (has_hevc_vdec()) { - ulong timeout = jiffies + HZ; + ulong timeout = jiffies + HZ/10; WRITE_VREG(HEVC_MPSR, 0); WRITE_VREG(HEVC_CPSR, 0); @@ -851,6 +899,12 @@ void amhevc_stop(void) break; } + timeout = jiffies + HZ/10; + while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + READ_VREG(DOS_SW_RESET3); READ_VREG(DOS_SW_RESET3); READ_VREG(DOS_SW_RESET3); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h index 8a269ad977ab..a3deecd916e7 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h @@ -38,7 +38,8 @@ extern void amvdec_stop(void); extern void amvdec_enable(void); extern void amvdec_disable(void); s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def); -s32 amvdec_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def); +s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *def); extern void amvdec2_start(void); extern void amvdec2_stop(void); @@ -51,8 +52,10 @@ extern void amhevc_stop(void); extern void amhevc_enable(void); extern void amhevc_disable(void); s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def); -s32 amhevc_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def); -s32 amvdec_vdec_loadmc_buf_ex(struct vdec_s *vdec, char *buf, int size); +s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec, + const char *name, char *def); +s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *buf, int size); extern void amhcodec_start(void); extern void amhcodec_stop(void); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c index fe00832b061c..590b812d36dc 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c @@ -32,6 +32,7 @@ #include #include "decoder_bmmu_box.h" #include +#include struct decoder_bmmu_box { int max_mm_num; @@ -133,19 +134,28 @@ int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n, mm = box->mm_list[idx]; if (mm) { int invalid = 0; + int keeped = 0; - if (mm->page_count * PAGE_SIZE < size) { - /*size is small. */ - invalid = 1; - } else if (box->change_size_on_need_smaller && - (mm->buffer_size > (size << 1))) { - /*size is too large. */ - invalid = 2; - } else if (mm->phy_addr & ((1 << align) - 1)) { - /*addr is not align */ - invalid = 4; - } - if (invalid) { + keeped = is_codec_mm_keeped(mm); + if (!keeped) { + if (mm->page_count * PAGE_SIZE < size) { + /*size is small. */ + invalid = 1; + } else if (box->change_size_on_need_smaller && + (mm->buffer_size > (size << 1))) { + /*size is too large. */ + invalid = 2; + } else if (mm->phy_addr & ((1 << align) - 1)) { + /*addr is not align */ + invalid = 4; + } + if (invalid) { + box->total_size -= mm->buffer_size; + codec_mm_release(mm, box->name); + box->mm_list[idx] = NULL; + mm = NULL; + } + } else { box->total_size -= mm->buffer_size; codec_mm_release(mm, box->name); box->mm_list[idx] = NULL; @@ -173,7 +183,7 @@ int decoder_bmmu_box_free_idx(void *handle, int idx) if (!box || idx < 0 || idx >= box->max_mm_num) { pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", box, idx, 0, - box->max_mm_num - 1); + box ? (box->max_mm_num - 1) : 0); return -1; } mutex_lock(&box->mutex); @@ -289,15 +299,29 @@ int decoder_bmmu_box_alloc_idx_wait( { int have_space; int ret = -1; + int keeped = 0; - if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) - return 0;/*have alloced memery before.*/ + if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) { + struct decoder_bmmu_box *box = handle; + struct codec_mm_s *mm; + mutex_lock(&box->mutex); + mm = box->mm_list[idx]; + keeped = is_codec_mm_keeped(mm); + mutex_unlock(&box->mutex); + + if (!keeped) + return 0;/*have alloced memery before.*/ + } have_space = decoder_bmmu_box_check_and_wait_size( size, wait_flags); if (have_space) { ret = decoder_bmmu_box_alloc_idx(handle, idx, size, aligned_2n, mem_flags); + if (ret == -ENOMEM) { + pr_info("bmmu alloc idx fail, try free keep video.\n"); + try_free_keep_video(1); + } } else { try_free_keep_video(1); ret = -ENOMEM; @@ -335,7 +359,7 @@ int decoder_bmmu_box_alloc_buf_phy( * driver_name, idx, *buf_phy_addr, size); */ } else { - pr_info("%s malloc failed %d\n", driver_name, idx); + pr_info("%s malloc failed %d\n", driver_name, idx); return -ENOMEM; } @@ -353,7 +377,7 @@ static int decoder_bmmu_box_dump(struct decoder_bmmu_box *box, void *buf, int i; if (!buf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ do {\ @@ -397,7 +421,7 @@ static int decoder_bmmu_box_dump_all(void *buf, int size) struct list_head *head, *list; if (!buf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ do {\ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c index 6135394b5735..cc9e7a906666 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c @@ -74,6 +74,16 @@ static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box) return 0; } +int decoder_mmu_box_sc_check(void *handle, int is_tvp) +{ + struct decoder_mmu_box *box = handle; + if (!box) { + pr_err("mmu box NULL !!!\n"); + return 0; + } + return codec_mm_scatter_size(is_tvp); +} +EXPORT_SYMBOL(decoder_mmu_box_sc_check); void *decoder_mmu_box_alloc_box(const char *name, @@ -152,7 +162,6 @@ int decoder_mmu_box_alloc_idx( for (i = 0; i < num_pages; i++) mmu_index_adr[i] = PAGE_INDEX(sc->pages_list[i]); - mmu_index_adr[num_pages] = 0; mutex_unlock(&box->mutex); @@ -170,7 +179,7 @@ int decoder_mmu_box_free_idx_tail( if (!box || idx < 0 || idx >= box->max_sc_num) { pr_err("can't free tail mmu box(%p),idx:%d in (%d-%d)\n", box, idx, 0, - box->max_sc_num - 1); + box ? (box->max_sc_num - 1) : 0); return -1; } mutex_lock(&box->mutex); @@ -191,7 +200,7 @@ int decoder_mmu_box_free_idx(void *handle, int idx) if (!box || idx < 0 || idx >= box->max_sc_num) { pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", box, idx, 0, - box->max_sc_num - 1); + box ? (box->max_sc_num - 1) : 0); return -1; } mutex_lock(&box->mutex); @@ -251,7 +260,7 @@ static int decoder_mmu_box_dump(struct decoder_mmu_box *box, if (!buf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ do {\ @@ -288,7 +297,7 @@ static int decoder_mmu_box_dump_all(void *buf, int size) if (!pbuf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h index 4aa9bf5ba781..9f4e0987567b 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h @@ -24,6 +24,8 @@ void *decoder_mmu_box_alloc_box(const char *name, int min_size_M, int mem_flags); +int decoder_mmu_box_sc_check(void *handle, int is_tvp); + int decoder_mmu_box_alloc_idx( void *handle, int idx, int num_pages, unsigned int *mmu_index_adr); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h index 17f64e430b72..c799fd091a3a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __VIDEO_FIRMWARE_HEADER_ #define __VIDEO_FIRMWARE_HEADER_ @@ -8,6 +27,7 @@ #define FW_LOAD_TRY (0X2) struct firmware_s { + char name[32]; unsigned int len; char data[0]; }; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c new file mode 100644 index 000000000000..e783dbc41ae0 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c @@ -0,0 +1,1161 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vdec.h" +#include "frame_check.h" +#include "amlogic_fbc_hook.h" +#include +#include +#include "../../../common/chips/decoder_cpu_ver_info.h" + + +#define FC_ERROR 0x0 + +#define FC_YUV_DEBUG 0x01 +#define FC_CRC_DEBUG 0x02 +#define FC_TST_DEBUG 0x80 +#define FC_ERR_CRC_BLOCK_MODE 0x10 +#define FC_CHECK_CRC_LOOP_MODE 0x20 + +#define YUV_MASK 0x01 +#define CRC_MASK 0x02 + +#define YUV_DEF_SIZE (1920*1088*3/2) +#define YUV_DEF_NUM 1 + +#define MAX_SIZE_AFBC_PLANES (4096 * 2048) + +#define VMAP_STRIDE_SIZE (1024*1024) + +static unsigned int fc_debug; +static unsigned int size_yuv_buf = (YUV_DEF_SIZE * YUV_DEF_NUM); + +#define dbg_print(mask, ...) do { \ + if ((fc_debug & mask) || \ + (mask == FC_ERROR)) \ + printk("[FRMAE_CHECK] "__VA_ARGS__);\ + } while(0) + + +#define CRC_PATH "/data/tmp/" +#define YUV_PATH "/data/tmp/" +static char comp_crc[128] = "name"; + +static struct vdec_s *single_mode_vdec = NULL; + +static unsigned int yuv_enable, check_enable; +static unsigned int yuv_start[MAX_INSTANCE_MUN]; +static unsigned int yuv_num[MAX_INSTANCE_MUN]; + + +static inline void set_enable(struct pic_check_mgr_t *p, int mask) +{ + p->enable |= mask; +} + +static inline void set_disable(struct pic_check_mgr_t *p, int mask) +{ + p->enable &= (~mask); +} + +static inline void check_schedule(struct pic_check_mgr_t *mgr) +{ + if (atomic_read(&mgr->work_inited)) + vdec_schedule_work(&mgr->frame_check_work); +} + +static int get_frame_size(struct pic_check_mgr_t *pic, + struct vframe_s *vf) +{ + if ((vf->width < 1) || (vf->height < 1)) + return -1; + pic->size_y = vf->width* vf->height; + pic->size_uv = pic->size_y >> 1; + pic->size_pic = pic->size_y + pic->size_uv; + + if (!(vf->type & VIDTYPE_VIU_NV21)) + return 0; + + if ((vf->canvas0Addr == vf->canvas1Addr) && + (vf->canvas0Addr != 0) && + (vf->canvas0Addr != -1)) { + pic->canvas_w = + canvas_get_width(canvasY(vf->canvas0Addr)); + pic->canvas_h = + canvas_get_height(canvasY(vf->canvas0Addr)); + } else { + pic->canvas_w = vf->canvas0_config[0].width; + pic->canvas_h = vf->canvas0_config[1].height; + } + + if ((pic->canvas_h < 1) || (pic->canvas_w < 1)) { + dbg_print(FC_ERROR, "(canvas,pic) w(%d,%d), h(%d,%d)\n", + pic->canvas_w, vf->width, pic->canvas_h, vf->height); + return -1; + } +/* + int blkmod; + blkmod = canvas_get_blkmode(canvasY(vf->canvas0Addr)); + if (blkmod != CANVAS_BLKMODE_LINEAR) { + dbg_print(0, "WARN: canvas blkmod %x\n", blkmod); + } +*/ + return 0; +} + +static int canvas_get_virt_addr(struct pic_check_mgr_t *pic, + struct vframe_s *vf) +{ + int phy_y_addr, phy_uv_addr; + void *vaddr_y, *vaddr_uv; + + if ((vf->canvas0Addr == vf->canvas1Addr) && + (vf->canvas0Addr != 0) && + (vf->canvas0Addr != -1)) { + phy_y_addr = canvas_get_addr(canvasY(vf->canvas0Addr)); + phy_uv_addr = canvas_get_addr(canvasUV(vf->canvas0Addr)); + } else { + phy_y_addr = vf->canvas0_config[0].phy_addr; + phy_uv_addr = vf->canvas0_config[1].phy_addr; + } + vaddr_y = codec_mm_phys_to_virt(phy_y_addr); + vaddr_uv = codec_mm_phys_to_virt(phy_uv_addr); + + if (((!vaddr_y) || (!vaddr_uv)) && ((!phy_y_addr) || (!phy_uv_addr))) { + dbg_print(FC_ERROR, "%s, y_addr %p(0x%x), uv_addr %p(0x%x)\n", + __func__, vaddr_y, phy_y_addr, vaddr_uv, phy_uv_addr); + return -1; + } + pic->y_vaddr = vaddr_y; + pic->uv_vaddr = vaddr_uv; + pic->y_phyaddr = phy_y_addr; + pic->uv_phyaddr = phy_uv_addr; + + return 0; +} + +static int str_strip(char *str) +{ + char *s = str; + int i = 0; + + while (s[i]) { + if (s[i] == '\n') + s[i] = 0; + else if (s[i] == ' ') + s[i] = '_'; + i++; + } + + return i; +} + +static char *fget_crc_str(char *buf, + unsigned int size, struct pic_check_t *fc) +{ + unsigned int c = 0, sz, ret, index, crc1, crc2; + mm_segment_t old_fs; + char *cs; + + if (!fc->compare_fp) + return NULL; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + do { + cs = buf; + sz = size; + while (--sz && (c = vfs_read(fc->compare_fp, + cs, 1, &fc->compare_pos) != 0)) { + if (*cs++ == '\n') + break; + } + *cs = '\0'; + if ((c == 0) && (cs == buf)) { + set_fs(old_fs); + return NULL; + } + ret = sscanf(buf, "%08u: %8x %8x", &index, &crc1, &crc2); + dbg_print(FC_CRC_DEBUG, "%s, index = %d, cmp = %d\n", + __func__, index, fc->cmp_crc_cnt); + }while(ret != 3 || index != fc->cmp_crc_cnt); + + set_fs(old_fs); + fc->cmp_crc_cnt++; + + return buf; +} + +static struct file* file_open(int mode, const char *str, ...) +{ + char file[256] = {0}; + struct file* fp = NULL; + va_list args; + + va_start(args, str); + vsnprintf(file, sizeof(file), str, args); + + fp = filp_open(file, mode, (mode&O_CREAT)?0666:0); + if (IS_ERR(fp)) { + fp = NULL; + dbg_print(FC_ERROR, "open %s failed\n", file); + return fp; + } + dbg_print(FC_ERROR, "open %s success\n", file); + va_end(args); + + return fp; +} + +static int write_yuv_work(struct pic_check_mgr_t *mgr) +{ + mm_segment_t old_fs; + unsigned int i, wr_size; + struct pic_dump_t *dump = &mgr->pic_dump; + + if (dump->dump_cnt > 0) { + if (!dump->yuv_fp) { + dump->yuv_fp = file_open(O_CREAT | O_WRONLY | O_TRUNC, + "%s%s-%d-%d.yuv", YUV_PATH, comp_crc, mgr->id, mgr->file_cnt); + dump->yuv_pos = 0; + } + + if ((mgr->enable & YUV_MASK) && + (dump->yuv_fp != NULL) && + (dump->dump_cnt >= dump->num)) { + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (i = 0; dump->dump_cnt > 0; i++) { + wr_size = vfs_write(dump->yuv_fp, + (dump->buf_addr + i * mgr->size_pic), + mgr->size_pic, &dump->yuv_pos); + if (mgr->size_pic != wr_size) { + dbg_print(FC_ERROR, "buf failed to write yuv file\n"); + break; + } + dump->dump_cnt--; + } + set_fs(old_fs); + vfs_fsync(dump->yuv_fp, 0); + + filp_close(dump->yuv_fp, current->files); + dump->yuv_pos = 0; + dump->yuv_fp = NULL; + set_disable(mgr, YUV_MASK); + dbg_print(FC_YUV_DEBUG, + "closed yuv file, dump yuv exit\n"); + dump->num = 0; + dump->dump_cnt = 0; + if (dump->buf_addr != NULL) + vfree(dump->buf_addr); + dump->buf_addr = NULL; + dump->buf_size = 0; + } + } + + return 0; +} + +static int write_crc_work(struct pic_check_mgr_t *mgr) +{ + unsigned int wr_size; + char *crc_buf, crc_tmp[64*30]; + mm_segment_t old_fs; + struct pic_check_t *check = &mgr->pic_check; + + if (mgr->enable & CRC_MASK) { + wr_size = 0; + while (kfifo_get(&check->wr_chk_q, &crc_buf) != 0) { + wr_size += sprintf(&crc_tmp[wr_size], "%s", crc_buf); + if (check->compare_fp != NULL) { + if (!fget_crc_str(crc_buf, SIZE_CRC, check)) { + dbg_print(0, "%s, can't get more compare crc\n", __func__); + filp_close(check->compare_fp, current->files); + check->compare_fp = NULL; + } + } + kfifo_put(&check->new_chk_q, crc_buf); + } + if (check->check_fp && (wr_size != 0)) { + old_fs = get_fs(); + set_fs(KERNEL_DS); + if (wr_size != vfs_write(check->check_fp, + crc_tmp, wr_size, &check->check_pos)) { + dbg_print(FC_ERROR, "failed to check_dump_filp\n"); + } + set_fs(old_fs); + } + } + return 0; +} + +static void do_check_work(struct work_struct *work) +{ + struct pic_check_mgr_t *mgr = container_of(work, + struct pic_check_mgr_t, frame_check_work); + + write_yuv_work(mgr); + + write_crc_work(mgr); +} + +static int memcpy_phy_to_virt(char *to_virt, + ulong phy_from, unsigned int size) +{ + void *vaddr = NULL; + unsigned int tmp_size = 0; + + if (single_mode_vdec != NULL) { + unsigned int offset = phy_from & (~PAGE_MASK); + while (size > 0) { + if (offset + size >= PAGE_SIZE) { + vaddr = kmap_atomic(phys_to_page(phy_from)); + tmp_size = (PAGE_SIZE - offset); + phy_from += tmp_size; + size -= tmp_size; + vaddr += offset; + } else { + vaddr = kmap_atomic(phys_to_page(phy_from)); + vaddr += offset; + tmp_size = size; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n", + __func__, (unsigned int)phy_from); + return -1; + } + /* + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + */ + memcpy(to_virt, vaddr, tmp_size); + + kunmap_atomic(vaddr - offset); + offset = 0; + } + } else { + while (size > 0) { + if (size >= VMAP_STRIDE_SIZE) { + vaddr = codec_mm_vmap(phy_from, VMAP_STRIDE_SIZE); + tmp_size = VMAP_STRIDE_SIZE; + phy_from += VMAP_STRIDE_SIZE; + size -= VMAP_STRIDE_SIZE; + } else { + vaddr = codec_mm_vmap(phy_from, size); + tmp_size = size; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_YUV_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n", + __func__, (unsigned int)phy_from); + return -1; + } + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + memcpy(to_virt, vaddr, tmp_size); + to_virt += tmp_size; + + codec_mm_unmap_phyaddr(vaddr); + } + } + return 0; +} + +static int do_yuv_dump(struct pic_check_mgr_t *mgr, struct vframe_s *vf) +{ + int i, ret = 0; + void *tmp_addr, *tmp_yaddr, *tmp_uvaddr; + ulong y_phyaddr, uv_phyaddr; + struct pic_dump_t *dump = &mgr->pic_dump; + /* + if ((vf->type & VIDTYPE_VIU_NV21) == 0) + return 0; + */ + if (dump->start > 0) { + dump->start--; + return 0; + } + + if (dump->dump_cnt >= dump->num) + return 0; + + if (mgr->size_pic > + (dump->buf_size - dump->dump_cnt * mgr->size_pic)) { + if (dump->buf_size) { + dbg_print(FC_ERROR, + "not enough buf, force dump less\n"); + dump->num = dump->dump_cnt; + check_schedule(mgr); + } else + set_disable(mgr, YUV_MASK); + return -1; + } + + tmp_addr = dump->buf_addr + + mgr->size_pic * dump->dump_cnt; + if ((mgr->uv_vaddr == NULL) || (mgr->y_vaddr == NULL)) { + y_phyaddr = mgr->y_phyaddr; + uv_phyaddr = mgr->uv_phyaddr; + if (vf->width == mgr->canvas_w) { + ret |= memcpy_phy_to_virt(tmp_addr, y_phyaddr, mgr->size_y); + ret |= memcpy_phy_to_virt(tmp_addr + mgr->size_y, + uv_phyaddr, mgr->size_uv); + } else { + for (i = 0; i < vf->height; i++) { + ret |= memcpy_phy_to_virt(tmp_addr, y_phyaddr, vf->width); + y_phyaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + for (i = 0; i < vf->height/2; i++) { + ret |= memcpy_phy_to_virt(tmp_addr, uv_phyaddr, vf->width); + uv_phyaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + } + if (ret < 0) { + dbg_print(0, "dump yuv failed, may codec_mm_vmap failed\n"); + return ret; + } + } else { + if (vf->width == mgr->canvas_w) { + memcpy(tmp_addr, mgr->y_vaddr, mgr->size_y); + memcpy(tmp_addr + mgr->size_y, + mgr->uv_vaddr, mgr->size_uv); + } else { + tmp_yaddr = mgr->y_vaddr; + tmp_uvaddr = mgr->uv_vaddr; + for (i = 0; i < vf->height; i++) { + memcpy(tmp_addr, tmp_yaddr, vf->width); + tmp_yaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + for (i = 0; i < vf->height/2; i++) { + memcpy(tmp_addr, tmp_uvaddr, vf->width); + tmp_uvaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + } + } + dump->dump_cnt++; + dbg_print(0, "----->dump frame num: %d, dump %dst, size %x\n", + mgr->frame_cnt, dump->dump_cnt, mgr->size_pic); + + if (dump->dump_cnt >= dump->num) + check_schedule(mgr); + + return 0; +} + +static int crc_store(struct pic_check_mgr_t *mgr, struct vframe_s *vf, + int crc_y, int crc_uv) +{ + int ret = 0; + char *crc_addr = NULL; + int comp_frame = 0, comp_crc_y, comp_crc_uv; + struct pic_check_t *check = &mgr->pic_check; + + if (kfifo_get(&check->new_chk_q, &crc_addr) == 0) { + dbg_print(0, "%08d: %08x %08x\n", + mgr->frame_cnt, crc_y, crc_uv); + if (check->check_fp) { + dbg_print(0, "crc32 dropped\n"); + } else { + dbg_print(0, "no opened file to write crc32\n"); + } + return -1; + } + if (check->cmp_crc_cnt > mgr->frame_cnt) { + sscanf(crc_addr, "%08u: %8x %8x", + &comp_frame, &comp_crc_y, &comp_crc_uv); + + dbg_print(0, "%08d: %08x %08x <--> %08d: %08x %08x\n", + mgr->frame_cnt, crc_y, crc_uv, + comp_frame, comp_crc_y, comp_crc_uv); + + if (comp_frame == mgr->frame_cnt) { + if ((comp_crc_y != crc_y) || (crc_uv != comp_crc_uv)) { + mgr->pic_dump.start = 0; + mgr->pic_dump.num++; + dbg_print(0, "\n\nError: %08d: %08x %08x != %08x %08x\n\n", + mgr->frame_cnt, crc_y, crc_uv, comp_crc_y, comp_crc_uv); + do_yuv_dump(mgr, vf); + if (fc_debug & FC_ERR_CRC_BLOCK_MODE) + mgr->err_crc_block = 1; + } + } else { + dbg_print(0, "frame num error: frame_cnt(%d) frame_comp(%d)\n", + mgr->frame_cnt, comp_frame); + } + } else { + dbg_print(0, "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv); + } + + if ((check->check_fp) && (crc_addr != NULL)) { + ret = snprintf(crc_addr, SIZE_CRC, + "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv); + + kfifo_put(&check->wr_chk_q, crc_addr); + if ((mgr->frame_cnt & 0xf) == 0) + check_schedule(mgr); + } + return ret; +} + + +static int crc32_vmap_le(unsigned int *crc32, + ulong phyaddr, unsigned int size) +{ + void *vaddr = NULL; + unsigned int crc = 0; + unsigned int tmp_size = 0; + + /*single mode cannot use codec_mm_vmap*/ + if (single_mode_vdec != NULL) { + unsigned int offset = phyaddr & (~PAGE_MASK); + while (size > 0) { + if (offset + size >= PAGE_SIZE) { + vaddr = kmap_atomic(phys_to_page(phyaddr)); + tmp_size = (PAGE_SIZE - offset); + phyaddr += tmp_size; + size -= tmp_size; + vaddr += offset; + } else { + vaddr = kmap_atomic(phys_to_page(phyaddr)); + tmp_size = size; + vaddr += offset; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n", + __func__, (unsigned int)phyaddr); + return -1; + } + /* + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + */ + crc = crc32_le(crc, vaddr, tmp_size); + + kunmap_atomic(vaddr - offset); + offset = 0; + } + } else { + while (size > 0) { + if (size >= VMAP_STRIDE_SIZE) { + vaddr = codec_mm_vmap(phyaddr, VMAP_STRIDE_SIZE); + tmp_size = VMAP_STRIDE_SIZE; + phyaddr += VMAP_STRIDE_SIZE; + size -= VMAP_STRIDE_SIZE; + } else { + vaddr = codec_mm_vmap(phyaddr, size); + tmp_size = size; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_CRC_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n", + __func__, (unsigned int)phyaddr); + return -1; + } + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + + crc = crc32_le(crc, vaddr, tmp_size); + + codec_mm_unmap_phyaddr(vaddr); + } + } + *crc32 = crc; + + return 0; +} + +static int do_check_nv21(struct pic_check_mgr_t *mgr, struct vframe_s *vf) +{ + int i; + unsigned int crc_y = 0, crc_uv = 0; + void *p_yaddr, *p_uvaddr; + ulong y_phyaddr, uv_phyaddr; + int ret = 0; + + p_yaddr = mgr->y_vaddr; + p_uvaddr = mgr->uv_vaddr; + y_phyaddr = mgr->y_phyaddr; + uv_phyaddr = mgr->uv_phyaddr; + if ((p_yaddr == NULL) || (p_uvaddr == NULL)) + { + if (vf->width == mgr->canvas_w) { + ret = crc32_vmap_le(&crc_y, y_phyaddr, mgr->size_y); + ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, mgr->size_uv); + } else { + for (i = 0; i < vf->height; i++) { + ret |= crc32_vmap_le(&crc_y, y_phyaddr, vf->width); + y_phyaddr += mgr->canvas_w; + } + for (i = 0; i < vf->height/2; i++) { + ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, vf->width); + uv_phyaddr += mgr->canvas_w; + } + } + if (ret < 0) { + dbg_print(0, "calc crc failed, may codec_mm_vmap failed\n"); + return ret; + } + } else { + if (mgr->frame_cnt == 0) { + unsigned int *p = mgr->y_vaddr; + dbg_print(0, "YUV0000: %08x-%08x-%08x-%08x\n", + p[0], p[1], p[2], p[3]); + } + if (vf->width == mgr->canvas_w) { + crc_y = crc32_le(crc_y, p_yaddr, mgr->size_y); + crc_uv = crc32_le(crc_uv, p_uvaddr, mgr->size_uv); + } else { + for (i = 0; i < vf->height; i++) { + crc_y = crc32_le(crc_y, p_yaddr, vf->width); + p_yaddr += mgr->canvas_w; + } + for (i = 0; i < vf->height/2; i++) { + crc_uv = crc32_le(crc_uv, p_uvaddr, vf->width); + p_uvaddr += mgr->canvas_w; + } + } + } + + crc_store(mgr, vf, crc_y, crc_uv); + + return 0; +} + +static int do_check_yuv16(struct pic_check_mgr_t *mgr, + struct vframe_s *vf, char *ybuf, char *uvbuf, + char *ubuf, char *vbuf) +{ + unsigned int crc1, crc2, crc3, crc4; + int w, h; + + w = vf->width; + h = vf->height; + crc1 = 0; + crc2 = 0; + crc3 = 0; + crc4 = 0; + + crc1 = crc32_le(0, ybuf, w * h *2); + crc2 = crc32_le(0, ubuf, w * h/2); + crc3 = crc32_le(0, vbuf, w * h/2); + crc4 = crc32_le(0, uvbuf, w * h*2/2); + /* + printk("%08d: %08x %08x %08x %08x\n", + mgr->frame_cnt, crc1, crc4, crc2, crc3); + */ + mgr->size_y = w * h * 2; + mgr->size_uv = w * h; + mgr->size_pic = mgr->size_y + mgr->size_uv; + mgr->y_vaddr = ybuf; + mgr->uv_vaddr = uvbuf; + mgr->canvas_w = w; + mgr->canvas_h = h; + crc_store(mgr, vf, crc1, crc4); + + return 0; +} + +static int fbc_check_prepare(struct pic_check_t *check, + int resize, int y_size) +{ + int i = 0; + + if (y_size > MAX_SIZE_AFBC_PLANES) + return -1; + + if (((!check->fbc_planes[0]) || + (!check->fbc_planes[1]) || + (!check->fbc_planes[2]) || + (!check->fbc_planes[3])) && + (!resize)) + return -1; + + if (resize) { + dbg_print(0, "size changed to 0x%x(y_size)\n", y_size); + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (check->fbc_planes[i]) { + vfree(check->fbc_planes[i]); + check->fbc_planes[i] = NULL; + } + } + } + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (!check->fbc_planes[i]) + check->fbc_planes[i] = + vmalloc(y_size * sizeof(short)); + } + if ((!check->fbc_planes[0]) || + (!check->fbc_planes[1]) || + (!check->fbc_planes[2]) || + (!check->fbc_planes[3])) { + dbg_print(0, "vmalloc staicplanes failed %lx %lx %lx %lx\n", + (ulong)check->fbc_planes[0], + (ulong)check->fbc_planes[1], + (ulong)check->fbc_planes[2], + (ulong)check->fbc_planes[3]); + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (check->fbc_planes[i]) { + vfree(check->fbc_planes[i]); + check->fbc_planes[i] = NULL; + } + } + return -1; + } else + dbg_print(FC_CRC_DEBUG, "vmalloc staicplanes sucessed\n"); + + return 0; +} + + + +int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf) +{ + int resize = 0; + void *planes[4]; + struct pic_check_t *check = NULL; + struct pic_check_mgr_t *mgr = NULL; + int ret = 0; + + if (vdec == NULL) { + if (single_mode_vdec == NULL) + return 0; + mgr = &single_mode_vdec->vfc; + } else { + mgr = &vdec->vfc; + single_mode_vdec = NULL; + } + + if ((mgr == NULL) || + (vf == NULL) || + (mgr->enable == 0)) + return 0; + + if (get_frame_size(mgr, vf) < 0) + return -1; + + if (mgr->last_size_pic != mgr->size_pic) { + resize = 1; + dbg_print(0, "size changed, %x-->%x\n", + mgr->last_size_pic, mgr->size_pic); + } else + resize = 0; + mgr->last_size_pic = mgr->size_pic; + + if (vf->type & VIDTYPE_VIU_NV21) { + if (canvas_get_virt_addr(mgr, vf) < 0) + return -2; + if ((mgr->y_vaddr) && (mgr->uv_vaddr)) { + codec_mm_dma_flush(mgr->y_vaddr, + mgr->size_y, DMA_FROM_DEVICE); + codec_mm_dma_flush(mgr->uv_vaddr, + mgr->size_uv, DMA_FROM_DEVICE); + } + if (mgr->enable & CRC_MASK) + ret = do_check_nv21(mgr, vf); + if (mgr->enable & YUV_MASK) + do_yuv_dump(mgr, vf); + + } else if (vf->type & VIDTYPE_SCATTER) { + check = &mgr->pic_check; + + if (mgr->pic_dump.buf_addr != NULL) { + dbg_print(0, "scatter free yuv buf\n"); + vfree(mgr->pic_dump.buf_addr); + mgr->pic_dump.buf_addr = NULL; + } + if (fbc_check_prepare(check, + resize, mgr->size_y) < 0) + return -3; + planes[0] = check->fbc_planes[0]; + planes[1] = check->fbc_planes[1]; + planes[2] = check->fbc_planes[2]; + planes[3] = check->fbc_planes[3]; + ret = AMLOGIC_FBC_vframe_decoder(planes, vf, 0, 0); + if (ret < 0) { + dbg_print(0, "amlogic_fbc_lib.ko error %d\n", ret); + } else { + do_check_yuv16(mgr, vf, + (void *)planes[0], (void *)planes[3],//uv + (void *)planes[1], (void *)planes[2]); + } + } + mgr->frame_cnt++; + + return ret; +} +EXPORT_SYMBOL(decoder_do_frame_check); + +static int dump_buf_alloc(struct pic_dump_t *dump) +{ + if ((dump->buf_addr != NULL) && + (dump->buf_size != 0)) + return 0; + + dump->buf_addr = + (char *)vmalloc(size_yuv_buf); + if (!dump->buf_addr) { + dump->buf_size = 0; + dbg_print(0, "vmalloc yuv buf failed\n"); + return -ENOMEM; + } + dump->buf_size = size_yuv_buf; + + dbg_print(0, "%s: buf for yuv is alloced\n", __func__); + + return 0; +} + +int dump_yuv_trig(struct pic_check_mgr_t *mgr, + int id, int start, int num) +{ + struct pic_dump_t *dump = &mgr->pic_dump; + + if (!dump->num) { + mgr->id = id; + dump->start = start; + dump->num = num; + dump->end = start + num; + dump->dump_cnt = 0; + dump->yuv_fp = NULL; + if (!atomic_read(&mgr->work_inited)) { + INIT_WORK(&mgr->frame_check_work, do_check_work); + atomic_set(&mgr->work_inited, 1); + } + dump_buf_alloc(dump); + str_strip(comp_crc); + set_enable(mgr, YUV_MASK); + } else { + dbg_print(FC_ERROR, "yuv dump now, trig later\n"); + return -EBUSY; + } + dbg_print(0, "dump yuv trigger, from %d to %d frame\n", + dump->start, dump->end); + return 0; +} + +int frame_check_init(struct pic_check_mgr_t *mgr, int id) +{ + int i; + struct pic_dump_t *dump = &mgr->pic_dump; + struct pic_check_t *check = &mgr->pic_check; + + mgr->frame_cnt = 0; + mgr->size_pic = 0; + mgr->last_size_pic = 0; + mgr->id = id; + + dump->num = 0; + dump->dump_cnt = 0; + dump->yuv_fp = NULL; + check->check_pos = 0; + check->compare_pos = 0; + + if (!atomic_read(&mgr->work_inited)) { + INIT_WORK(&mgr->frame_check_work, do_check_work); + atomic_set(&mgr->work_inited, 1); + } + /* for dump error yuv prepare. */ + dump_buf_alloc(dump); + + /* try to open compare crc32 file */ + str_strip(comp_crc); + check->compare_fp = file_open(O_RDONLY, + "%s%s", CRC_PATH, comp_crc); + + /* create crc32 log file */ + check->check_fp = file_open(O_CREAT| O_WRONLY | O_TRUNC, + "%s%s-%d-%d.crc", CRC_PATH, comp_crc, id, mgr->file_cnt); + + INIT_KFIFO(check->new_chk_q); + INIT_KFIFO(check->wr_chk_q); + check->check_addr = vmalloc(SIZE_CRC * SIZE_CHECK_Q); + if (check->check_addr == NULL) { + dbg_print(FC_ERROR, "vmalloc qbuf fail\n"); + } else { + void *qaddr = NULL, *rdret = NULL; + check->cmp_crc_cnt = 0; + for (i = 0; i < SIZE_CHECK_Q; i++) { + qaddr = check->check_addr + i * SIZE_CRC; + rdret = fget_crc_str(qaddr, + SIZE_CRC, check); + if (rdret == NULL) { + if (i < 3) + dbg_print(0, "can't get compare crc string\n"); + if (check->compare_fp) { + filp_close(check->compare_fp, current->files); + check->compare_fp = NULL; + } + } + + kfifo_put(&check->new_chk_q, qaddr); + } + } + set_enable(mgr, CRC_MASK); + dbg_print(0, "%s end\n", __func__); + + return 0; +} + +void frame_check_exit(struct pic_check_mgr_t *mgr) +{ + int i; + struct pic_dump_t *dump = &mgr->pic_dump; + struct pic_check_t *check = &mgr->pic_check; + + if (mgr->enable != 0) { + if (dump->dump_cnt != 0) { + dbg_print(0, "%s, cnt = %d, num = %d\n", + __func__, dump->dump_cnt, dump->num); + set_enable(mgr, YUV_MASK); + } + if (atomic_read(&mgr->work_inited)) { + cancel_work_sync(&mgr->frame_check_work); + atomic_set(&mgr->work_inited, 0); + } + write_yuv_work(mgr); + write_crc_work(mgr); + + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (check->fbc_planes[i]) { + vfree(check->fbc_planes[i]); + check->fbc_planes[i] = NULL; + } + } + if (check->check_addr) { + vfree(check->check_addr); + check->check_addr = NULL; + } + + if (check->check_fp) { + filp_close(check->check_fp, current->files); + check->check_fp = NULL; + } + if (check->compare_fp) { + filp_close(check->compare_fp, current->files); + check->compare_fp = NULL; + } + if (dump->yuv_fp) { + filp_close(dump->yuv_fp, current->files); + dump->yuv_fp = NULL; + } + if (dump->buf_addr) { + vfree(dump->buf_addr); + dump->buf_addr = NULL; + } + mgr->file_cnt++; + set_disable(mgr, YUV_MASK | CRC_MASK); + dbg_print(0, "%s end\n", __func__); + } +} + + +int vdec_frame_check_init(struct vdec_s *vdec) +{ + int ret = 0, id = 0; + + if (vdec == NULL) + return 0; + + if ((vdec->is_reset) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXL)) + return 0; + + vdec->vfc.err_crc_block = 0; + if (!check_enable && !yuv_enable) + return 0; + + if (vdec_single(vdec)) + single_mode_vdec = vdec; + + vdec->canvas_mode = CANVAS_BLKMODE_LINEAR; + id = vdec->id; + + if (check_enable & (0x01 << id)) { + frame_check_init(&vdec->vfc, id); + /*repeat check one video crc32, not clear enable*/ + if ((fc_debug & FC_CHECK_CRC_LOOP_MODE) == 0) + check_enable &= ~(0x01 << id); + } + + if (yuv_enable & (0x01 << id)) { + ret = dump_yuv_trig(&vdec->vfc, + id, yuv_start[id], yuv_num[id]); + if (ret < 0) + pr_info("dump yuv init failed\n"); + else { + pr_info("dump yuv init ok, total %d\n", + yuv_num[id]); + vdec->canvas_mode = CANVAS_BLKMODE_LINEAR; + } + yuv_num[id] = 0; + yuv_start[id] = 0; + yuv_enable &= ~(0x01 << id); + } + + return ret; +} + +void vdec_frame_check_exit(struct vdec_s *vdec) +{ + if (vdec == NULL) + return; + frame_check_exit(&vdec->vfc); + + single_mode_vdec = NULL; +} + +ssize_t dump_yuv_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + struct vdec_s *vdec = NULL; + unsigned int id = 0, num = 0, start = 0; + int ret = -1; + + ret = sscanf(buf, "%d %d %d", &id, &start, &num); + if (ret < 0) { + pr_info("%s, parse failed\n", buf); + return size; + } + if ((num == 0) || (num > YUV_MAX_DUMP_NUM)) { + pr_info("requred yuv num %d, max %d\n", + num, YUV_MAX_DUMP_NUM); + return size; + } + vdec = vdec_get_with_id(id); + if (vdec == NULL) { + yuv_start[id] = start; + yuv_num[id] = num; + yuv_enable |= (1 << id); + pr_info("no connected vdec.%d now, set dump ok\n", id); + return size; + } + + ret = dump_yuv_trig(&vdec->vfc, id, start, num); + if (ret < 0) + pr_info("trigger dump yuv failed\n"); + else + pr_info("trigger dump yuv init ok, total %d frames\n", num); + + return size; +} + +ssize_t dump_yuv_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int i; + char *pbuf = buf; + + for (i = 0; i < MAX_INSTANCE_MUN; i++) { + pbuf += pr_info("vdec.%d, start: %d, total: %d frames\n", + i, yuv_start[i], yuv_num[i]); + } + pbuf += sprintf(pbuf, + "\nUsage: echo [id] [start] [num] > dump_yuv\n\n"); + return pbuf - buf; +} + + +ssize_t frame_check_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + int ret = -1; + int on_off, id; + + ret = sscanf(buf, "%d %d", &id, &on_off); + if (ret < 0) { + pr_info("%s, parse failed\n", buf); + return size; + } + if (id >= MAX_INSTANCE_MUN) { + pr_info("%d out of max vdec id\n", id); + return size; + } + if (on_off) + check_enable |= (1 << id); + else + check_enable &= ~(1 << id); + + return size; +} + +ssize_t frame_check_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int i; + char *pbuf = buf; + + for (i = 0; i < MAX_INSTANCE_MUN; i++) { + pbuf += sprintf(pbuf, + "vdec.%d\tcrc: %s\n", i, + (check_enable & (0x01 << i))?"enabled":"--"); + } + pbuf += sprintf(pbuf, + "\nUsage:\techo [id] [1:on/0:off] > frame_check\n\n"); + + if (fc_debug & FC_ERR_CRC_BLOCK_MODE) { + /* cat frame_check to next frame when block */ + struct vdec_s *vdec = NULL; + vdec = vdec_get_with_id(__ffs(check_enable)); + if (vdec) + vdec->vfc.err_crc_block = 0; + } + + return pbuf - buf; +} + + +module_param_string(comp_crc, comp_crc, 128, 0664); +MODULE_PARM_DESC(comp_crc, "\n crc_filename\n"); + +module_param(fc_debug, uint, 0664); +MODULE_PARM_DESC(fc_debug, "\n frame check debug\n"); + +module_param(size_yuv_buf, uint, 0664); +MODULE_PARM_DESC(size_yuv_buf, "\n size_yuv_buf\n"); + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h new file mode 100644 index 000000000000..f1ba6773fe43 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h @@ -0,0 +1,111 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef __FRAME_CHECK_H__ +#define __FRAME_CHECK_H__ + + +#include +#include +#include +#include + +#define FRAME_CHECK + +#define YUV_MAX_DUMP_NUM 20 + +#define SIZE_CRC 64 +#define SIZE_CHECK_Q 128 + +struct pic_dump_t{ + struct file *yuv_fp; + loff_t yuv_pos; + unsigned int start; + unsigned int num; + unsigned int end; + unsigned int dump_cnt; + + unsigned int buf_size; + char *buf_addr; +}; + +struct pic_check_t{ + struct file *check_fp; + loff_t check_pos; + + struct file *compare_fp; + loff_t compare_pos; + unsigned int cmp_crc_cnt; + void *fbc_planes[4]; + void *check_addr; + DECLARE_KFIFO(new_chk_q, char *, SIZE_CHECK_Q); + DECLARE_KFIFO(wr_chk_q, char *, SIZE_CHECK_Q); +}; + +struct pic_check_mgr_t{ + int id; + int enable; + unsigned int frame_cnt; + /* pic info */ + unsigned int canvas_w; + unsigned int canvas_h; + unsigned int size_y; //real size + unsigned int size_uv; + unsigned int size_pic; + unsigned int last_size_pic; + void *y_vaddr; + void *uv_vaddr; + ulong y_phyaddr; + ulong uv_phyaddr; + int err_crc_block; + + int file_cnt; + atomic_t work_inited; + struct work_struct frame_check_work; + + struct pic_check_t pic_check; + struct pic_dump_t pic_dump; +}; + +int dump_yuv_trig(struct pic_check_mgr_t *mgr, + int id, int start, int num); + +int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf); + +int frame_check_init(struct pic_check_mgr_t *mgr, int id); + +void frame_check_exit(struct pic_check_mgr_t *mgr); + +ssize_t frame_check_show(struct class *class, + struct class_attribute *attr, char *buf); + +ssize_t frame_check_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size); + +ssize_t dump_yuv_show(struct class *class, + struct class_attribute *attr, char *buf); + +ssize_t dump_yuv_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size); + +void vdec_frame_check_exit(struct vdec_s *vdec); +int vdec_frame_check_init(struct vdec_s *vdec); + +#endif /* __FRAME_CHECK_H__ */ + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c index 1d14e2c39bef..a1e7fa79008f 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c @@ -15,7 +15,14 @@ * */ +#include +#include #include "secprot.h" +#ifndef CONFIG_ARM64 +#include +#endif + +#ifdef CONFIG_ARM64 int tee_config_device_secure(int dev_id, int secure) { @@ -40,4 +47,29 @@ int tee_config_device_secure(int dev_id, int secure) return ret; } +#else +int tee_config_device_secure(int dev_id, int secure) +{ + int ret = 0; + register unsigned int r0 asm("r0"); + register unsigned int r1 asm("r1"); + register unsigned int r2 asm("r2"); + + r0 = OPTEE_SMC_CONFIG_DEVICE_SECURE; + r1 = dev_id; + r2 = secure; + + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") + __SMC(0) + : "=r"(r0) + : "r"(r0), "r"(r1), "r"(r2)); + ret = r0; + + return ret; +} +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h index f8fc5da845e9..28ee47725dbc 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h @@ -31,7 +31,7 @@ #define OPTEE_SMC_CONFIG_DEVICE_SECURE 0xb200000e -#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" +/*#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"*/ extern int tee_config_device_secure(int dev_id, int secure); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c index e7fb7514ea55..3e7a47f7a287 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c @@ -67,6 +67,12 @@ #include #include #include "secprot.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include "frame_check.h" + +#ifdef CONFIG_AMLOGIC_POWER +#include +#endif static DEFINE_MUTEX(vdec_mutex); @@ -80,16 +86,42 @@ static int keep_vdec_mem; static unsigned int debug_trace_num = 16 * 20; static int step_mode; static unsigned int clk_config; +/* + &1: sched_priority to MAX_RT_PRIO -1. + &2: always reload firmware. + &4: vdec canvas debug enable + */ +static unsigned int debug; static int hevc_max_reset_count; -#define MAX_INSTANCE_MUN 9 static int no_powerdown; +static int parallel_decode = 1; +static int fps_detection; +static int fps_clear; + + +static int force_nosecure_even_drm; + static DEFINE_SPINLOCK(vdec_spin_lock); #define HEVC_TEST_LIMIT 100 #define GXBB_REV_A_MINOR 0xA +#define PRINT_FRAME_INFO 1 +#define DISABLE_FRAME_INFO 2 + +static int frameinfo_flag = 0; +//static int path_debug = 0; + +static struct vframe_qos_s *frame_info_buf_in = NULL; +static struct vframe_qos_s *frame_info_buf_out = NULL; +static int frame_qos_wr = 0; +static int frame_qos_rd = 0; +int decode_underflow = 0; + +#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1) + struct am_reg { char *name; int offset; @@ -104,13 +136,23 @@ struct vdec_isr_context_s { struct vdec_s *vdec; }; +struct decode_fps_s { + u32 frame_count; + u64 start_timestamp; + u64 last_timestamp; + u32 fps; +}; + struct vdec_core_s { struct list_head connected_vdec_list; spinlock_t lock; + spinlock_t canvas_lock; + spinlock_t fps_lock; struct ida ida; atomic_t vdec_nr; struct vdec_s *vfm_vdec; struct vdec_s *active_vdec; + struct vdec_s *active_hevc; struct vdec_s *hint_fr_vdec; struct platform_device *vdec_core_platform_device; struct device *cma_dev; @@ -121,8 +163,20 @@ struct vdec_core_s { unsigned long sched_mask; struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX]; int power_ref_count[VDEC_MAX]; + struct vdec_s *last_vdec; + int parallel_dec; + unsigned long power_ref_mask; + int vdec_combine_flag; + struct decode_fps_s decode_fps[MAX_INSTANCE_MUN]; }; +struct canvas_status_s { + int type; + int canvas_used_flag; + int id; +}; + + static struct vdec_core_s *vdec_core; static const char * const vdec_status_string[] = { @@ -134,6 +188,9 @@ static const char * const vdec_status_string[] = { static int debugflags; +static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1]; + + int vdec_get_debug_flags(void) { return debugflags; @@ -168,6 +225,32 @@ static const int cores_int[VDEC_MAX] = { VDEC_IRQ_HEVC_BACK }; +unsigned long vdec_canvas_lock(struct vdec_core_s *core) +{ + unsigned long flags; + spin_lock_irqsave(&core->canvas_lock, flags); + + return flags; +} + +void vdec_canvas_unlock(struct vdec_core_s *core, unsigned long flags) +{ + spin_unlock_irqrestore(&core->canvas_lock, flags); +} + +unsigned long vdec_fps_lock(struct vdec_core_s *core) +{ + unsigned long flags; + spin_lock_irqsave(&core->fps_lock, flags); + + return flags; +} + +void vdec_fps_unlock(struct vdec_core_s *core, unsigned long flags) +{ + spin_unlock_irqrestore(&core->fps_lock, flags); +} + unsigned long vdec_core_lock(struct vdec_core_s *core) { unsigned long flags; @@ -182,10 +265,80 @@ void vdec_core_unlock(struct vdec_core_s *core, unsigned long flags) spin_unlock_irqrestore(&core->lock, flags); } +static u64 vdec_get_us_time_system(void) +{ + struct timeval tv; + + do_gettimeofday(&tv); + + return div64_u64(timeval_to_ns(&tv), 1000); +} + +static void vdec_fps_clear(int id) +{ + if (id >= MAX_INSTANCE_MUN) + return; + + vdec_core->decode_fps[id].frame_count = 0; + vdec_core->decode_fps[id].start_timestamp = 0; + vdec_core->decode_fps[id].last_timestamp = 0; + vdec_core->decode_fps[id].fps = 0; +} + +static void vdec_fps_clearall(void) +{ + int i; + + for (i = 0; i < MAX_INSTANCE_MUN; i++) { + vdec_core->decode_fps[i].frame_count = 0; + vdec_core->decode_fps[i].start_timestamp = 0; + vdec_core->decode_fps[i].last_timestamp = 0; + vdec_core->decode_fps[i].fps = 0; + } +} + +static void vdec_fps_detec(int id) +{ + unsigned long flags; + + if (fps_detection == 0) + return; + + if (id >= MAX_INSTANCE_MUN) + return; + + flags = vdec_fps_lock(vdec_core); + + if (fps_clear == 1) { + vdec_fps_clearall(); + fps_clear = 0; + } + + vdec_core->decode_fps[id].frame_count++; + if (vdec_core->decode_fps[id].frame_count == 1) { + vdec_core->decode_fps[id].start_timestamp = + vdec_get_us_time_system(); + vdec_core->decode_fps[id].last_timestamp = + vdec_core->decode_fps[id].start_timestamp; + } else { + vdec_core->decode_fps[id].last_timestamp = + vdec_get_us_time_system(); + vdec_core->decode_fps[id].fps = + (u32)div_u64(((u64)(vdec_core->decode_fps[id].frame_count) * + 10000000000), + (vdec_core->decode_fps[id].last_timestamp - + vdec_core->decode_fps[id].start_timestamp)); + } + vdec_fps_unlock(vdec_core, flags); +} + + + static int get_canvas(unsigned int index, unsigned int base) { int start; int canvas_index = index * base; + int ret; if ((base > 4) || (base == 0)) return -1; @@ -203,26 +356,173 @@ static int get_canvas(unsigned int index, unsigned int base) } if (base == 1) { - return start; + ret = start; } else if (base == 2) { - return ((start + 1) << 16) | ((start + 1) << 8) | start; + ret = ((start + 1) << 16) | ((start + 1) << 8) | start; } else if (base == 3) { - return ((start + 2) << 16) | ((start + 1) << 8) | start; + ret = ((start + 2) << 16) | ((start + 1) << 8) | start; } else if (base == 4) { - return (((start + 3) << 24) | (start + 2) << 16) | + ret = (((start + 3) << 24) | (start + 2) << 16) | ((start + 1) << 8) | start; } + return ret; +} + +static int get_canvas_ex(int type, int id) +{ + int i; + unsigned long flags; + + flags = vdec_canvas_lock(vdec_core); + + for (i = 0; i < CANVAS_MAX_SIZE; i++) { + /*0x10-0x15 has been used by rdma*/ + if ((i >= 0x10) && (i <= 0x15)) + continue; + if ((canvas_stat[i].type == type) && + (canvas_stat[i].id & (1 << id)) == 0) { + canvas_stat[i].canvas_used_flag++; + canvas_stat[i].id |= (1 << id); + if (debug & 4) + pr_debug("get used canvas %d\n", i); + vdec_canvas_unlock(vdec_core, flags); + if (i < AMVDEC_CANVAS_MAX2 + 1) + return i; + else + return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1); + } + } + + for (i = 0; i < CANVAS_MAX_SIZE; i++) { + /*0x10-0x15 has been used by rdma*/ + if ((i >= 0x10) && (i <= 0x15)) + continue; + if (canvas_stat[i].type == 0) { + canvas_stat[i].type = type; + canvas_stat[i].canvas_used_flag = 1; + canvas_stat[i].id = (1 << id); + if (debug & 4) { + pr_debug("get canvas %d\n", i); + pr_debug("canvas_used_flag %d\n", + canvas_stat[i].canvas_used_flag); + pr_debug("canvas_stat[i].id %d\n", + canvas_stat[i].id); + } + vdec_canvas_unlock(vdec_core, flags); + if (i < AMVDEC_CANVAS_MAX2 + 1) + return i; + else + return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1); + } + } + vdec_canvas_unlock(vdec_core, flags); + + pr_info("cannot get canvas\n"); + return -1; } +static void free_canvas_ex(int index, int id) +{ + unsigned long flags; + int offset; + + flags = vdec_canvas_lock(vdec_core); + if (index >= 0 && + index < AMVDEC_CANVAS_MAX2 + 1) + offset = index; + else if ((index >= AMVDEC_CANVAS_START_INDEX) && + (index <= AMVDEC_CANVAS_MAX1)) + offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX; + else { + vdec_canvas_unlock(vdec_core, flags); + return; + } + + if ((canvas_stat[offset].canvas_used_flag > 0) && + (canvas_stat[offset].id & (1 << id))) { + canvas_stat[offset].canvas_used_flag--; + canvas_stat[offset].id &= ~(1 << id); + if (canvas_stat[offset].canvas_used_flag == 0) { + canvas_stat[offset].type = 0; + canvas_stat[offset].id = 0; + } + if (debug & 4) { + pr_debug("free index %d used_flag %d, type = %d, id = %d\n", + offset, + canvas_stat[offset].canvas_used_flag, + canvas_stat[offset].type, + canvas_stat[offset].id); + } + } + vdec_canvas_unlock(vdec_core, flags); + + return; + +} + + + + +static int vdec_get_hw_type(int value) +{ + int type; + switch (value) { + case VFORMAT_HEVC: + case VFORMAT_VP9: + case VFORMAT_AVS2: + type = CORE_MASK_HEVC; + break; + + case VFORMAT_MPEG12: + case VFORMAT_MPEG4: + case VFORMAT_H264: + case VFORMAT_MJPEG: + case VFORMAT_REAL: + case VFORMAT_JPEG: + case VFORMAT_VC1: + case VFORMAT_AVS: + case VFORMAT_YUV: + case VFORMAT_H264MVC: + case VFORMAT_H264_4K2K: + case VFORMAT_H264_ENC: + case VFORMAT_JPEG_ENC: + type = CORE_MASK_VDEC_1; + break; + + default: + type = -1; + } + + return type; +} + + +static void vdec_save_active_hw(struct vdec_s *vdec) +{ + int type; + + type = vdec_get_hw_type(vdec->port->vformat); + + if (type == CORE_MASK_HEVC) { + vdec_core->active_hevc = vdec; + } else if (type == CORE_MASK_VDEC_1) { + vdec_core->active_vdec = vdec; + } else { + pr_info("save_active_fw wrong\n"); + } +} + int vdec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { - if (vdec && vdec->dec_status) + if (vdec && vdec->dec_status && + ((vdec->status == VDEC_STATUS_CONNECTED || + vdec->status == VDEC_STATUS_ACTIVE))) return vdec->dec_status(vdec, vstatus); - return -1; + return 0; } EXPORT_SYMBOL(vdec_status); @@ -324,7 +624,7 @@ EXPORT_SYMBOL(update_vdec_clk_config_settings); static bool hevc_workaround_needed(void) { - return (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) && + return (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) && (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == GXBB_REV_A_MINOR); } @@ -526,6 +826,13 @@ int vdec_set_pts(struct vdec_s *vdec, u32 pts) } EXPORT_SYMBOL(vdec_set_pts); +void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp) +{ + vdec->timestamp = timestamp; + vdec->timestamp_valid = true; +} +EXPORT_SYMBOL(vdec_set_timestamp); + int vdec_set_pts64(struct vdec_s *vdec, u64 pts64) { vdec->pts64 = pts64; @@ -537,6 +844,12 @@ int vdec_set_pts64(struct vdec_s *vdec, u64 pts64) } EXPORT_SYMBOL(vdec_set_pts64); +int vdec_get_status(struct vdec_s *vdec) +{ + return vdec->status; +} +EXPORT_SYMBOL(vdec_get_status); + void vdec_set_status(struct vdec_s *vdec, int status) { //trace_vdec_set_status(vdec, status);/*DEBUG_TMP*/ @@ -1198,7 +1511,7 @@ void vdec_clean_input(struct vdec_s *vdec) while (!list_empty(&input->vframe_chunk_list)) { struct vframe_chunk_s *chunk = vdec_input_next_chunk(input); - if (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED) + if (chunk && (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED)) vdec_input_release_chunk(input, chunk); else break; @@ -1207,12 +1520,74 @@ void vdec_clean_input(struct vdec_s *vdec) } EXPORT_SYMBOL(vdec_clean_input); + +static int vdec_input_read_restore(struct vdec_s *vdec) +{ + struct vdec_input_s *input = &vdec->input; + + if (!vdec_stream_based(vdec)) + return 0; + + if (!input->swap_valid) { + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, + input->start); + WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, + input->start + input->size - 8); + WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, + input->start); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* set to manual mode */ + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + WRITE_VREG(HEVC_STREAM_START_ADDR, + input->start); + WRITE_VREG(HEVC_STREAM_END_ADDR, + input->start + input->size); + WRITE_VREG(HEVC_STREAM_RD_PTR, + input->start); + } + return 0; + } + if (input->target == VDEC_INPUT_TARGET_VLD) { + /* restore read side */ + WRITE_VREG(VLD_MEM_SWAP_ADDR, + input->swap_page_phys); + + /*swap active*/ + WRITE_VREG(VLD_MEM_SWAP_CTL, 1); + + /*wait swap busy*/ + while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) + ; + + WRITE_VREG(VLD_MEM_SWAP_CTL, 0); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + /* restore read side */ + WRITE_VREG(HEVC_STREAM_SWAP_ADDR, + input->swap_page_phys); + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1); + + while (READ_VREG(HEVC_STREAM_SWAP_CTRL) + & (1<<7)) + ; + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); + } + + return 0; +} + + int vdec_sync_input(struct vdec_s *vdec) { struct vdec_input_s *input = &vdec->input; u32 rp = 0, wp = 0, fifo_len = 0; int size; + vdec_input_read_restore(vdec); vdec_sync_input_read(vdec); vdec_sync_input_write(vdec); if (input->target == VDEC_INPUT_TARGET_VLD) { @@ -1343,7 +1718,7 @@ int vdec_disconnect(struct vdec_s *vdec) (vdec->status != VDEC_STATUS_ACTIVE)) { return 0; } - + mutex_lock(&vdec_mutex); /* *when a vdec is under the management of scheduler * the status change will only be from vdec_core_thread @@ -1354,16 +1729,26 @@ int vdec_disconnect(struct vdec_s *vdec) vdec_set_next_status(vdec->slave, VDEC_STATUS_DISCONNECTED); else if (vdec->master) vdec_set_next_status(vdec->master, VDEC_STATUS_DISCONNECTED); - + mutex_unlock(&vdec_mutex); up(&vdec_core->sem); - wait_for_completion(&vdec->inactive_done); + if(!wait_for_completion_timeout(&vdec->inactive_done, + msecs_to_jiffies(2000))) + goto discon_timeout; - if (vdec->slave) - wait_for_completion(&vdec->slave->inactive_done); - else if (vdec->master) - wait_for_completion(&vdec->master->inactive_done); + if (vdec->slave) { + if(!wait_for_completion_timeout(&vdec->slave->inactive_done, + msecs_to_jiffies(2000))) + goto discon_timeout; + } else if (vdec->master) { + if(!wait_for_completion_timeout(&vdec->master->inactive_done, + msecs_to_jiffies(2000))) + goto discon_timeout; + } + return 0; +discon_timeout: + pr_err("%s timeout!!! status: 0x%x\n", __func__, vdec->status); return 0; } EXPORT_SYMBOL(vdec_disconnect); @@ -1403,6 +1788,30 @@ static const char *get_dev_name(bool use_legacy_vdec, int format) #endif } +struct vdec_s *vdec_get_with_id(unsigned int id) +{ + struct vdec_s *vdec, *ret_vdec = NULL; + struct vdec_core_s *core = vdec_core; + unsigned long flags; + + if (id >= MAX_INSTANCE_MUN) + return NULL; + + flags = vdec_core_lock(vdec_core); + if (!list_empty(&core->connected_vdec_list)) { + list_for_each_entry(vdec, &core->connected_vdec_list, list) { + if (vdec->id == id) { + pr_info("searched avaliable vdec connected, id = %d\n", id); + ret_vdec = vdec; + break; + } + } + } + vdec_core_unlock(vdec_core, flags); + + return ret_vdec; +} + /* *register vdec_device * create output, vfm or create ionvideo output @@ -1449,6 +1858,9 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) p->cma_dev = vdec_core->cma_dev; p->get_canvas = get_canvas; + p->get_canvas_ex = get_canvas_ex; + p->free_canvas_ex = free_canvas_ex; + p->vdec_fps_detec = vdec_fps_detec; atomic_set(&p->inirq_flag, 0); atomic_set(&p->inirq_thread_flag, 0); /* todo */ @@ -1457,6 +1869,12 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) /* vdec_dev_reg.flag = 0; */ if (vdec->id >= 0) id = vdec->id; + p->parallel_dec = parallel_decode; + vdec_core->parallel_dec = parallel_decode; + vdec->canvas_mode = CANVAS_BLKMODE_32X32; +#ifdef FRAME_CHECK + vdec_frame_check_init(vdec); +#endif p->dev = platform_device_register_data( &vdec_core->vdec_core_platform_device->dev, dev_name, @@ -1514,26 +1932,26 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) r = ionvideo_assign_map(&vdec->vf_receiver_name, &vdec->vf_receiver_inst); #else - /* - * temporarily just use decoder instance ID as iondriver ID - * to solve OMX iondriver instance number check time sequence - * only the limitation is we can NOT mix different video - * decoders since same ID will be used for different decoder - * formats. - */ - vdec->vf_receiver_inst = p->dev->id; - r = ionvideo_assign_map(&vdec->vf_receiver_name, - &vdec->vf_receiver_inst); + /* + * temporarily just use decoder instance ID as iondriver ID + * to solve OMX iondriver instance number check time sequence + * only the limitation is we can NOT mix different video + * decoders since same ID will be used for different decoder + * formats. + */ + vdec->vf_receiver_inst = p->dev->id; + r = ionvideo_assign_map(&vdec->vf_receiver_name, + &vdec->vf_receiver_inst); #endif - if (r < 0) { - pr_err("IonVideo frame receiver allocation failed.\n"); + if (r < 0) { + pr_err("IonVideo frame receiver allocation failed.\n"); - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); - goto error; - } + goto error; + } snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s", vdec->vf_provider_name, @@ -1542,16 +1960,34 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_AMLVIDEO_AMVIDEO) { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - "amlvideo deinterlace amvideo"); + if (vdec_secure(vdec)) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amlvideo amvideo"); + } else { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amlvideo deinterlace amvideo"); + } snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_AMLVIDEO1_AMVIDEO2) { snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s", vdec->vf_provider_name, - "ppmgr amlvideo.1 amvide2"); + "aml_video.1 videosync.0 videopip"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == FRAME_BASE_PATH_TUNNEL_MODE) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amvideo"); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); } @@ -1601,13 +2037,14 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) if (vdec_core->hint_fr_vdec == vdec) { if (p->sys_info->rate != 0) { - if (!vdec->is_reset) + if (!vdec->is_reset) { vf_notify_receiver(p->vf_provider_name, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long) p->sys_info->rate)); - vdec->fr_hint_state = VDEC_HINTED; + vdec->fr_hint_state = VDEC_HINTED; + } } else { vdec->fr_hint_state = VDEC_NEED_HINT; } @@ -1622,7 +2059,25 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) vdec->sys_info->height); /* vdec is now ready to be active */ vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); + if (p->use_vfm_path) { + frame_info_buf_in = (struct vframe_qos_s *) + kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); + if (!frame_info_buf_in) + pr_err("kmalloc: frame_info_buf_in failed\n"); + else + memset(frame_info_buf_in, 0, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); + frame_info_buf_out = (struct vframe_qos_s *) + kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); + if (!frame_info_buf_out) + pr_err("kmalloc: frame_info_buf_out failed\n"); + else + memset(frame_info_buf_out, 0, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); + frame_qos_wr = 0; + frame_qos_rd = 0; + } return 0; error: @@ -1648,8 +2103,7 @@ void vdec_release(struct vdec_s *vdec) if (vdec->vframe_provider.name) { if (!vdec_single(vdec)) { if (vdec_core->hint_fr_vdec == vdec - && vdec->fr_hint_state == VDEC_HINTED - && !vdec->is_reset) + && vdec->fr_hint_state == VDEC_HINTED) vf_notify_receiver( vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_FR_END_HINT, @@ -1676,15 +2130,28 @@ void vdec_release(struct vdec_s *vdec) || (atomic_read(&vdec->inirq_thread_flag) > 0)) schedule(); +#ifdef FRAME_CHECK + vdec_frame_check_exit(vdec); +#endif + vdec_fps_clear(vdec->id); + platform_device_unregister(vdec->dev); + pr_debug("vdec_release instance %p, total %d\n", vdec, + atomic_read(&vdec_core->vdec_nr)); + if (vdec->use_vfm_path) { + kfree(frame_info_buf_in); + frame_info_buf_in = NULL; + kfree(frame_info_buf_out); + frame_info_buf_out = NULL; + frame_qos_wr = 0; + frame_qos_rd = 0; + } vdec_destroy(vdec); mutex_lock(&vdec_mutex); inited_vcodec_num--; mutex_unlock(&vdec_mutex); - pr_debug("vdec_release instance %p, total %d\n", vdec, - atomic_read(&vdec_core->vdec_nr)); } EXPORT_SYMBOL(vdec_release); @@ -1707,9 +2174,14 @@ int vdec_reset(struct vdec_s *vdec) if (vdec->slave) vdec->slave->reset(vdec->slave); } - + vdec->mc_loaded = 0;/*clear for reload firmware*/ vdec_input_release(&vdec->input); + vdec_input_init(&vdec->input, vdec); + + vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width, + vdec->sys_info->height); + vf_reg_provider(&vdec->vframe_provider); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_START, vdec); @@ -1718,6 +2190,7 @@ int vdec_reset(struct vdec_s *vdec) vf_reg_provider(&vdec->slave->vframe_provider); vf_notify_receiver(vdec->slave->vf_provider_name, VFRAME_EVENT_PROVIDER_START, vdec->slave); + vdec->slave->mc_loaded = 0;/*clear for reload firmware*/ } vdec_connect(vdec); @@ -1730,21 +2203,24 @@ void vdec_free_cmabuf(void) { mutex_lock(&vdec_mutex); - if (inited_vcodec_num > 0) { + /*if (inited_vcodec_num > 0) { mutex_unlock(&vdec_mutex); return; - } + }*/ mutex_unlock(&vdec_mutex); } -int vdec_core_request(struct vdec_s *vdec, unsigned long mask) +void vdec_core_request(struct vdec_s *vdec, unsigned long mask) { vdec->core_mask |= mask; if (vdec->slave) vdec->slave->core_mask |= mask; + if (vdec_core->parallel_dec == 1) { + if (mask & CORE_MASK_COMBINE) + vdec_core->vdec_combine_flag++; + } - return 0; } EXPORT_SYMBOL(vdec_core_request); @@ -1754,12 +2230,15 @@ int vdec_core_release(struct vdec_s *vdec, unsigned long mask) if (vdec->slave) vdec->slave->core_mask &= ~mask; - + if (vdec_core->parallel_dec == 1) { + if (mask & CORE_MASK_COMBINE) + vdec_core->vdec_combine_flag--; + } return 0; } EXPORT_SYMBOL(vdec_core_release); -const bool vdec_core_with_input(unsigned long mask) +bool vdec_core_with_input(unsigned long mask) { enum vdec_type_e type; @@ -1775,7 +2254,7 @@ void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask) { unsigned long i; unsigned long t = mask; - + mutex_lock(&vdec_mutex); while (t) { i = __ffs(t); clear_bit(i, &vdec->active_mask); @@ -1784,6 +2263,8 @@ void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask) if (vdec->active_mask == 0) vdec_set_status(vdec, VDEC_STATUS_CONNECTED); + + mutex_unlock(&vdec_mutex); } EXPORT_SYMBOL(vdec_core_finish_run); /* @@ -1831,8 +2312,18 @@ static irqreturn_t vdec_isr(int irq, void *dev_id) { struct vdec_isr_context_s *c = (struct vdec_isr_context_s *)dev_id; - struct vdec_s *vdec = vdec_core->active_vdec; + struct vdec_s *vdec = vdec_core->last_vdec; irqreturn_t ret = IRQ_HANDLED; + + if (vdec_core->parallel_dec == 1) { + if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq) + vdec = vdec_core->active_hevc; + else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq) + vdec = vdec_core->active_vdec; + else + vdec = NULL; + } + if (vdec) atomic_set(&vdec->inirq_flag, 1); if (c->dev_isr) { @@ -1875,8 +2366,18 @@ static irqreturn_t vdec_thread_isr(int irq, void *dev_id) { struct vdec_isr_context_s *c = (struct vdec_isr_context_s *)dev_id; - struct vdec_s *vdec = vdec_core->active_vdec; + struct vdec_s *vdec = vdec_core->last_vdec; irqreturn_t ret = IRQ_HANDLED; + + if (vdec_core->parallel_dec == 1) { + if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq) + vdec = vdec_core->active_hevc; + else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq) + vdec = vdec_core->active_vdec; + else + vdec = NULL; + } + if (vdec) atomic_set(&vdec->inirq_thread_flag, 1); if (c->dev_threaded_isr) { @@ -1906,6 +2407,10 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask) if (!vdec->run_ready) return false; + /* when crc32 error, block at error frame */ + if (vdec->vfc.err_crc_block) + return false; + if ((vdec->slave || vdec->master) && (vdec->sched == 0)) return false; @@ -2014,6 +2519,15 @@ void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) if (!vdec_core_with_input(mask)) return; + if (secure && vdec_stream_based(vdec) && force_nosecure_even_drm) + { + /* Verimatrix ultra webclient (HLS) was played in drmmode and used hw demux. In drmmode VDEC only can access secure. + Now HW demux parsed es data to no-secure buffer. So the VDEC input was no-secure, VDEC playback failed. Forcing + use nosecure for verimatrix webclient HLS. If in the future HW demux can parse es data to secure buffer, make + VDEC r/w secure.*/ + secure = 0; + //pr_debug("allow VDEC can access nosecure even in drmmode\n"); + } if (input->target == VDEC_INPUT_TARGET_VLD) tee_config_device_secure(DMC_DEV_ID_VDEC, secure); else if (input->target == VDEC_INPUT_TARGET_HEVC) @@ -2039,8 +2553,9 @@ void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) static int vdec_core_thread(void *data) { struct vdec_core_s *core = (struct vdec_core_s *)data; - - struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; + struct sched_param param = {.sched_priority = MAX_RT_PRIO/2}; + unsigned long flags; + int i; sched_setscheduler(current, SCHED_FIFO, ¶m); @@ -2053,7 +2568,16 @@ static int vdec_core_thread(void *data) if (kthread_should_stop()) break; + mutex_lock(&vdec_mutex); + if (core->parallel_dec == 1) { + for (i = VDEC_1; i < VDEC_MAX; i++) { + core->power_ref_mask = + core->power_ref_count[i] > 0 ? + (core->power_ref_mask | (1 << i)) : + (core->power_ref_mask & ~(1 << i)); + } + } /* clean up previous active vdec's input */ list_for_each_entry(vdec, &core->connected_vdec_list, list) { unsigned long mask = vdec->sched_mask & @@ -2075,8 +2599,8 @@ static int vdec_core_thread(void *data) &input->vframe_chunk_list)) { struct vframe_chunk_s *chunk = vdec_input_next_chunk(input); - if (chunk->flag & - VFRAME_CHUNK_FLAG_CONSUMED) + if (chunk && (chunk->flag & + VFRAME_CHUNK_FLAG_CONSUMED)) vdec_input_release_chunk(input, chunk); else @@ -2106,18 +2630,26 @@ static int vdec_core_thread(void *data) */ /* check disconnected decoders */ + flags = vdec_core_lock(vdec_core); list_for_each_entry_safe(vdec, tmp, &core->connected_vdec_list, list) { if ((vdec->status == VDEC_STATUS_CONNECTED) && (vdec->next_status == VDEC_STATUS_DISCONNECTED)) { - if (core->active_vdec == vdec) - core->active_vdec = NULL; + if (core->parallel_dec == 1) { + if (vdec_core->active_hevc == vdec) + vdec_core->active_hevc = NULL; + if (vdec_core->active_vdec == vdec) + vdec_core->active_vdec = NULL; + } + if (core->last_vdec == vdec) + core->last_vdec = NULL; list_move(&vdec->list, &disconnecting_list); } } - + vdec_core_unlock(vdec_core, flags); + mutex_unlock(&vdec_mutex); /* elect next vdec to be scheduled */ - vdec = core->active_vdec; + vdec = core->last_vdec; if (vdec) { vdec = list_entry(vdec->list.next, struct vdec_s, list); list_for_each_entry_from(vdec, @@ -2142,7 +2674,7 @@ static int vdec_core_thread(void *data) &core->connected_vdec_list, list) { sched_mask = vdec_schedule_mask(vdec, core->sched_mask); - if (vdec == core->active_vdec) { + if (vdec == core->last_vdec) { if (!sched_mask) { vdec = NULL; break; @@ -2188,11 +2720,19 @@ static int vdec_core_thread(void *data) /* vdec's sched_mask is only set from core thread */ vdec->sched_mask |= mask; - + if (core->last_vdec) { + if ((core->last_vdec != vdec) && + (core->last_vdec->mc_type != vdec->mc_type)) + vdec->mc_loaded = 0;/*clear for reload firmware*/ + } + core->last_vdec = vdec; + if (debug & 2) + vdec->mc_loaded = 0;/*alway reload firmware*/ vdec_set_status(vdec, VDEC_STATUS_ACTIVE); core->sched_mask |= mask; - core->active_vdec = vdec; + if (core->parallel_dec == 1) + vdec_save_active_hw(vdec); #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN); #endif @@ -2207,20 +2747,39 @@ static int vdec_core_thread(void *data) /* we have some cores scheduled, keep working until * all vdecs are checked with no cores to schedule */ - up(&core->sem); + if (core->parallel_dec == 1) { + if (vdec_core->vdec_combine_flag == 0) + up(&core->sem); + } else + up(&core->sem); } /* remove disconnected decoder from active list */ list_for_each_entry_safe(vdec, tmp, &disconnecting_list, list) { list_del(&vdec->list); vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); + /*core->last_vdec = NULL;*/ complete(&vdec->inactive_done); } /* if there is no new work scheduled and nothing * is running, sleep 20ms */ - if ((!worker) && (!core->sched_mask)) { + if (core->parallel_dec == 1) { + if (vdec_core->vdec_combine_flag == 0) { + if ((!worker) && + ((core->sched_mask != core->power_ref_mask)) && + (atomic_read(&vdec_core->vdec_nr) > 0)) { + usleep_range(1000, 2000); + up(&core->sem); + } + } else { + if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) { + usleep_range(1000, 2000); + up(&core->sem); + } + } + } else if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) { usleep_range(1000, 2000); up(&core->sem); } @@ -2343,6 +2902,8 @@ void vdec_poweron(enum vdec_type_e core) dma_addr_t decomp_dma_addr; u32 decomp_addr_aligned = 0; int hevc_loop = 0; + int sleep_val, iso_val; + bool is_power_ctrl_ver2 = false; if (core >= VDEC_MAX) return; @@ -2360,6 +2921,10 @@ void vdec_poweron(enum vdec_type_e core) return; } + is_power_ctrl_ver2 = + ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false; + if (hevc_workaround_needed() && (core == VDEC_HEVC)) { decomp_addr = codec_mm_dma_alloc_coherent(MEM_NAME, @@ -2375,9 +2940,25 @@ void vdec_poweron(enum vdec_type_e core) } if (core == VDEC_1) { + sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc; + iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0; + /* vdec1 power on */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(true, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power on ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~0xc); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); +#endif /* wait 10uS */ udelay(10); /* vdec1 soft reset */ @@ -2389,16 +2970,31 @@ void vdec_poweron(enum vdec_type_e core) * m8baby and m8m2 can dynamic adjust vdec clock, * power on with default clock level */ + amports_switch_gate("clk_vdec_mux", 1); vdec_clock_hi_enable(); /* power up vdec memories */ WRITE_VREG(DOS_MEM_PD_VDEC, 0); + /* remove vdec1 isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(true, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power on ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~0xC0); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); +#endif /* reset DOS top registers */ WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0); - if (get_cpu_type() >= - MESON_CPU_MAJOR_ID_GXBB) { + if (get_cpu_major_id() >= + AM_MESON_CPU_MAJOR_ID_GXBB) { /* *enable VDEC_1 DMC request */ @@ -2433,10 +3029,25 @@ void vdec_poweron(enum vdec_type_e core) } } else if (core == VDEC_HCODEC) { if (has_hdec()) { + sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3; + iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30; + /* hcodec power on */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(true, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power on ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - ~0x3); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); +#endif /* wait 10uS */ udelay(10); /* hcodec soft reset */ @@ -2447,34 +3058,75 @@ void vdec_poweron(enum vdec_type_e core) /* power up hcodec memories */ WRITE_VREG(DOS_MEM_PD_HCODEC, 0); /* remove hcodec isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(true, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power on ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - ~0x30); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); +#endif } } else if (core == VDEC_HEVC) { if (has_hevc_vdec()) { bool hevc_fixed = false; + sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0; + iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00; + while (!hevc_fixed) { /* hevc power on */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(true, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power on ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - ~0xc0); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); +#endif /* wait 10uS */ udelay(10); /* hevc soft reset */ WRITE_VREG(DOS_SW_RESET3, 0xffffffff); WRITE_VREG(DOS_SW_RESET3, 0); /* enable hevc clock */ + amports_switch_gate("clk_hevc_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + amports_switch_gate("clk_hevcb_mux", 1); hevc_clock_hi_enable(); hevc_back_clock_hi_enable(); /* power up hevc memories */ WRITE_VREG(DOS_MEM_PD_HEVC, 0); /* remove hevc isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(true, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power on ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - ~0xc00); - + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); +#endif if (!hevc_workaround_needed()) break; @@ -2526,6 +3178,9 @@ EXPORT_SYMBOL(vdec_poweron); void vdec_poweroff(enum vdec_type_e core) { + int sleep_val, iso_val; + bool is_power_ctrl_ver2 = false; + if (core >= VDEC_MAX) return; @@ -2537,9 +3192,16 @@ void vdec_poweroff(enum vdec_type_e core) return; } + is_power_ctrl_ver2 = + ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false; + if (core == VDEC_1) { - if (get_cpu_type() >= - MESON_CPU_MAJOR_ID_GXBB) { + sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc; + iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0; + + if (get_cpu_major_id() >= + AM_MESON_CPU_MAJOR_ID_GXBB) { /* disable VDEC_1 DMC REQ*/ unsigned long flags; @@ -2550,15 +3212,41 @@ void vdec_poweroff(enum vdec_type_e core) udelay(10); } /* enable vdec1 isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(false, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power off ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc0); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); +#endif /* power off vdec1 memories */ WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL); /* disable vdec1 clock */ vdec_clock_off(); /* vdec1 power off */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(false, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power off ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); +#endif } else if (core == VDEC_2) { if (has_vdec2()) { /* enable vdec2 isolation */ @@ -2576,37 +3264,92 @@ void vdec_poweroff(enum vdec_type_e core) } } else if (core == VDEC_HCODEC) { if (has_hdec()) { + sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3; + iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30; + /* enable hcodec isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(false, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power off ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - 0x30); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); +#endif /* power off hcodec memories */ WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); /* disable hcodec clock */ hcodec_clock_off(); /* hcodec power off */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(false, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power off ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 3); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); +#endif } } else if (core == VDEC_HEVC) { if (has_hevc_vdec()) { + sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0; + iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00; + if (no_powerdown == 0) { /* enable hevc isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(false, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power off ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - 0xc00); - /* power off hevc memories */ - WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); +#endif + /* power off hevc memories */ + WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); - /* disable hevc clock */ - hevc_clock_off(); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - hevc_back_clock_off(); + /* disable hevc clock */ + hevc_clock_off(); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + hevc_back_clock_off(); - /* hevc power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | - 0xc0); + /* hevc power off */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(false, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power off ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); + } +#else + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); +#endif } else { pr_info("!!!!!!!!not power down\n"); hevc_reset_core(NULL); @@ -2623,7 +3366,10 @@ bool vdec_on(enum vdec_type_e core) bool ret = false; if (core == VDEC_1) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0xc) == 0) && + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) + ? 0x2 : 0xc)) == 0) && (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100)) ret = true; } else if (core == VDEC_2) { @@ -2634,13 +3380,19 @@ bool vdec_on(enum vdec_type_e core) } } else if (core == VDEC_HCODEC) { if (has_hdec()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x3) == 0) && + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) + ? 0x1 : 0x3)) == 0) && (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000)) ret = true; } } else if (core == VDEC_HEVC) { if (has_hevc_vdec()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0xc0) == 0) && + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) + ? 0x4 : 0xc0)) == 0) && (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000)) ret = true; } @@ -2746,6 +3498,82 @@ int vdec_source_changed(int format, int width, int height, int fps) } EXPORT_SYMBOL(vdec_source_changed); +void vdec_disable_DMC(struct vdec_s *vdec) +{ + /*close first,then wait pedding end,timing suggestion from vlsi*/ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); + spin_unlock_irqrestore(&vdec_spin_lock, flags); + + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & (1 << 13))) + ; +} +EXPORT_SYMBOL(vdec_disable_DMC); + +void vdec_enable_DMC(struct vdec_s *vdec) +{ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); +} + +EXPORT_SYMBOL(vdec_enable_DMC); + +void vdec_reset_core(struct vdec_s *vdec) +{ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); + spin_unlock_irqrestore(&vdec_spin_lock, flags); + + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & (1 << 13))) + ; + /* + * 2: assist + * 3: vld_reset + * 4: vld_part_reset + * 5: vfifo reset + * 6: iqidct + * 7: mc + * 8: dblk + * 9: pic_dc + * 10: psc + * 11: mcpu + * 12: ccpu + * 13: ddr + * 14: afifo + */ + + WRITE_VREG(DOS_SW_RESET0, + (1<<3)|(1<<4)|(1<<5)); + + WRITE_VREG(DOS_SW_RESET0, 0); + + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); +} +EXPORT_SYMBOL(vdec_reset_core); + +void hevc_enable_DMC(struct vdec_s *vdec) +{ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); +} + +EXPORT_SYMBOL(hevc_enable_DMC); + void hevc_reset_core(struct vdec_s *vdec) { unsigned long flags; @@ -2897,7 +3725,7 @@ static ssize_t amrisc_regs_show(struct class *class, unsigned int val; ssize_t ret; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { mutex_lock(&vdec_mutex); if (!vdec_on(VDEC_1)) { mutex_unlock(&vdec_mutex); @@ -2905,7 +3733,7 @@ static ssize_t amrisc_regs_show(struct class *class, ret = pbuf - buf; return ret; } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 1); @@ -2918,9 +3746,9 @@ static ssize_t amrisc_regs_show(struct class *class, pbuf += sprintf(pbuf, "%s(%#x)\t:%#x(%d)\n", regs[i].name, regs[i].offset, val, val); } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) mutex_unlock(&vdec_mutex); - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 0); @@ -2944,7 +3772,7 @@ static ssize_t dump_trace_show(struct class *class, ret = pbuf - buf; return ret; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { mutex_lock(&vdec_mutex); if (!vdec_on(VDEC_1)) { mutex_unlock(&vdec_mutex); @@ -2953,7 +3781,7 @@ static ssize_t dump_trace_show(struct class *class, ret = pbuf - buf; return ret; } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 1); @@ -2982,9 +3810,9 @@ static ssize_t dump_trace_show(struct class *class, i += 16; }; pr_info("dump trace steps:%d finished\n", debug_trace_num); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) mutex_unlock(&vdec_mutex); - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 0); @@ -3141,6 +3969,7 @@ static ssize_t show_debug(struct class *class, struct vdec_s *vdec; struct vdec_core_s *core = vdec_core; unsigned long flags = vdec_core_lock(vdec_core); + u64 tmp; pbuf += sprintf(pbuf, "============== help:\n"); @@ -3180,11 +4009,12 @@ static ssize_t show_debug(struct class *class, vdec->input_underrun_count[type]); pbuf += sprintf(pbuf, "\t%d", vdec->not_run_ready_count[type]); + tmp = vdec->run_clk[type] * 100; + do_div(tmp, vdec->total_clk[type]); pbuf += sprintf(pbuf, "\t%d%%\n", vdec->total_clk[type] == 0 ? 0 : - (u32)((vdec->run_clk[type] * 100) - / vdec->total_clk[type])); + (u32)tmp); } } } @@ -3322,6 +4152,31 @@ struct vdec_s *vdec_get_default_vdec_for_userdata(void) } EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata); +struct vdec_s *vdec_get_vdec_by_id(int vdec_id) +{ + struct vdec_s *vdec; + struct vdec_s *ret_vdec; + struct vdec_core_s *core = vdec_core; + unsigned long flags; + + flags = vdec_core_lock(vdec_core); + + ret_vdec = NULL; + if (!list_empty(&core->connected_vdec_list)) { + list_for_each_entry(vdec, &core->connected_vdec_list, list) { + if (vdec->id == vdec_id) { + ret_vdec = vdec; + break; + } + } + } + + vdec_core_unlock(vdec_core, flags); + + return ret_vdec; +} +EXPORT_SYMBOL(vdec_get_vdec_by_id); + int vdec_read_user_data(struct vdec_s *vdec, struct userdata_param_t *p_userdata_param) { @@ -3340,8 +4195,10 @@ EXPORT_SYMBOL(vdec_read_user_data); int vdec_wakeup_userdata_poll(struct vdec_s *vdec) { - /*if (vdec && vdec == vdec_get_default_vdec_for_userdata()) - amstream_wakeup_userdata_poll();*/ //DEBUG_TMP + if (vdec) { + if (vdec->wakeup_userdata_poll) + vdec->wakeup_userdata_poll(vdec); + } return 0; } @@ -3416,7 +4273,7 @@ static ssize_t dump_risc_mem_show(struct class *class, char *pbuf = buf; int ret; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { mutex_lock(&vdec_mutex); if (!vdec_on(VDEC_1)) { mutex_unlock(&vdec_mutex); @@ -3424,7 +4281,7 @@ static ssize_t dump_risc_mem_show(struct class *class, ret = pbuf - buf; return ret; } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 1); @@ -3444,9 +4301,9 @@ static ssize_t dump_risc_mem_show(struct class *class, } /*done*/ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) mutex_unlock(&vdec_mutex); - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 0); @@ -3469,7 +4326,7 @@ static ssize_t core_show(struct class *class, struct class_attribute *attr, pbuf += sprintf(pbuf, " Core: last_sched %p, sched_mask %lx\n", - core->active_vdec, + core->last_vdec, core->sched_mask); list_for_each_entry(vdec, &core->connected_vdec_list, list) { @@ -3503,7 +4360,8 @@ static ssize_t vdec_status_show(struct class *class, } list_for_each_entry(vdec, &core->connected_vdec_list, list) { - if (VDEC_STATUS_CONNECTED == vdec->status) { + if ((vdec->status == VDEC_STATUS_CONNECTED + || vdec->status == VDEC_STATUS_ACTIVE)) { memset(&vs, 0, sizeof(vs)); if (vdec_status(vdec, &vs)) { pbuf += sprintf(pbuf, "err.\n"); @@ -3551,6 +4409,9 @@ static ssize_t vdec_status_show(struct class *class, pbuf += sprintf(pbuf, "%13s : %llu %s\n\n", "total data", vs.total_data / 1024, "KB"); + pbuf += sprintf(pbuf, + "%13s : %x\n", "ratio_control", + vs.ratio_control); vdec_num++; } @@ -3621,6 +4482,23 @@ static ssize_t dump_decoder_state_show(struct class *class, return pbuf - buf; } +static ssize_t dump_fps_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + struct vdec_core_s *core = vdec_core; + int i; + + unsigned long flags = vdec_fps_lock(vdec_core); + for (i = 0; i < MAX_INSTANCE_MUN; i++) + pbuf += sprintf(pbuf, "%d ", core->decode_fps[i].fps); + + pbuf += sprintf(pbuf, "\n"); + vdec_fps_unlock(vdec_core, flags); + + return pbuf - buf; +} + static struct class_attribute vdec_class_attrs[] = { @@ -3642,6 +4520,13 @@ static struct class_attribute vdec_class_attrs[] = { __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP, show_debug, store_debug), #endif +#ifdef FRAME_CHECK + __ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP, + dump_yuv_show, dump_yuv_store), + __ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP, + frame_check_show, frame_check_store), +#endif + __ATTR_RO(dump_fps), __ATTR_NULL }; @@ -3699,7 +4584,7 @@ static int vdec_probe(struct platform_device *pdev) return r; } #if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { r = vdec_request_threaded_irq(VDEC_IRQ_HEVC_BACK, NULL, NULL, IRQF_ONESHOT, "vdec-hevc_back", NULL); if (r < 0) { @@ -3714,23 +4599,26 @@ static int vdec_probe(struct platform_device *pdev) vdec_core->cma_dev = &pdev->dev; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_M8) { /* default to 250MHz */ vdec_clock_hi_enable(); } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) { + if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) { /* set vdec dmc request to urgent */ WRITE_DMCREG(DMC_AM5_CHAN_CTRL, 0x3f203cf); } INIT_LIST_HEAD(&vdec_core->connected_vdec_list); spin_lock_init(&vdec_core->lock); + spin_lock_init(&vdec_core->canvas_lock); + spin_lock_init(&vdec_core->fps_lock); ida_init(&vdec_core->ida); vdec_core->thread = kthread_run(vdec_core_thread, vdec_core, "vdec-core"); - vdec_core->vdec_core_wq = create_singlethread_workqueue("threadvdec"); - + vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",__WQ_LEGACY | + WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work"); + /*work queue priority lower than vdec-core.*/ return 0; } @@ -3782,6 +4670,11 @@ static struct platform_driver vdec_driver = { } }; +static struct codec_profile_t amvdec_input_profile = { + .name = "vdec_input", + .profile = "drm_framemode" +}; + int vdec_module_init(void) { if (platform_driver_register(&vdec_driver)) { @@ -3790,6 +4683,7 @@ int vdec_module_init(void) } INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node, "vdec", vdec_configs, CONFIG_FOR_RW); + vcodec_profile_register(&amvdec_input_profile); return 0; } EXPORT_SYMBOL(vdec_module_init); @@ -3837,6 +4731,105 @@ static int __init vdec_mem_setup(struct reserved_mem *rmem) return 0; } +void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug) +{ + if (frame_info_buf_in == NULL) { + pr_info("error,frame_info_buf_in is null\n"); + return; + } + if (frame_info_buf_out == NULL) { + pr_info("error,frame_info_buf_out is null\n"); + return; + } + if (frame_qos_wr >= QOS_FRAME_NUM) + frame_qos_wr = 0; + + if (frame_qos_wr >= QOS_FRAME_NUM || + frame_qos_wr < 0) { + pr_info("error,index :%d is error\n", frame_qos_wr); + return; + } + if (frameinfo_flag == DISABLE_FRAME_INFO) + return; + + if (frameinfo_flag == PRINT_FRAME_INFO) { + pr_info("num %d size %d pts %d\n", + vframe_qos->num, + vframe_qos->size, + vframe_qos->pts); + pr_info("mv min_mv %d avg_mv %d max_mv %d\n", + vframe_qos->min_mv, + vframe_qos->avg_mv, + vframe_qos->max_mv); + pr_info("qp min_qp %d avg_qp %d max_qp %d\n", + vframe_qos->min_qp, + vframe_qos->avg_qp, + vframe_qos->max_qp); + pr_info("skip min_skip %d avg_skip %d max_skip %d\n", + vframe_qos->min_skip, + vframe_qos->avg_skip, + vframe_qos->max_skip); + } + memcpy(&frame_info_buf_in[frame_qos_wr++], + vframe_qos, sizeof(struct vframe_qos_s)); + if (frame_qos_wr >= QOS_FRAME_NUM) + frame_qos_wr = 0; + + /*pr_info("frame_qos_wr:%d\n", frame_qos_wr);*/ + +} +EXPORT_SYMBOL(vdec_fill_frame_info); + +struct vframe_qos_s *vdec_get_qos_info(void) +{ + int write_count = 0; + int qos_wr = frame_qos_wr; + + if (frame_info_buf_in == NULL) { + pr_info("error,frame_info_buf_in is null\n"); + return NULL; + } + if (frame_info_buf_out == NULL) { + pr_info("error,frame_info_buf_out is null\n"); + return NULL; + } + + + memset(frame_info_buf_out, 0, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); + if (frame_qos_rd > qos_wr) { + write_count = QOS_FRAME_NUM - frame_qos_rd; + if (write_count > 0 && write_count <= QOS_FRAME_NUM) { + memcpy(frame_info_buf_out, &frame_info_buf_in[0], + write_count*sizeof(struct vframe_qos_s)); + if ((write_count + qos_wr) <= QOS_FRAME_NUM) + memcpy(&frame_info_buf_out[write_count], frame_info_buf_in, + qos_wr*sizeof(struct vframe_qos_s)); + else + pr_info("get_qos_info:%d,out of range\n", __LINE__); + } else + pr_info("get_qos_info:%d,out of range\n", __LINE__); + } else if (frame_qos_rd < qos_wr) { + write_count = qos_wr - frame_qos_rd; + if (write_count > 0 && write_count < QOS_FRAME_NUM) + memcpy(frame_info_buf_out, &frame_info_buf_in[frame_qos_rd], + (write_count)*sizeof(struct vframe_qos_s)); + else + pr_info("get_qos_info:%d, out of range\n", __LINE__); + } + /* + pr_info("cnt:%d,size:%d,num:%d,rd:%d,wr:%d\n", + wirte_count, + frame_info_buf_out[0].size, + frame_info_buf_out[0].num, + frame_qos_rd,qos_wr); + */ + frame_qos_rd = qos_wr; + return frame_info_buf_out; +} +EXPORT_SYMBOL(vdec_get_qos_info); + + RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup); /* uint force_hevc_clock_cntl; @@ -3844,12 +4837,20 @@ EXPORT_SYMBOL(force_hevc_clock_cntl); module_param(force_hevc_clock_cntl, uint, 0664); */ +module_param(debug, uint, 0664); module_param(debug_trace_num, uint, 0664); module_param(hevc_max_reset_count, int, 0664); module_param(clk_config, uint, 0664); module_param(step_mode, int, 0664); module_param(debugflags, int, 0664); +module_param(parallel_decode, int, 0664); +module_param(fps_detection, int, 0664); +module_param(fps_clear, int, 0664); +module_param(force_nosecure_even_drm, int, 0664); +module_param(frameinfo_flag, int, 0664); +MODULE_PARM_DESC(frameinfo_flag, + "\n frameinfo_flag\n"); /* *module_init(vdec_module_init); *module_exit(vdec_module_exit); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h index 90158f300eae..b7287fb95238 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h @@ -32,6 +32,7 @@ /*#define CONFIG_AM_VDEC_DV*/ #include "vdec_input.h" +#include "frame_check.h" s32 vdec_dev_register(void); s32 vdec_dev_unregister(void); @@ -43,6 +44,8 @@ struct device *get_vdec_device(void); int vdec_module_init(void); void vdec_module_exit(void); +#define MAX_INSTANCE_MUN 9 + #define VDEC_DEBUG_SUPPORT #define DEC_FLAG_HEVC_WORKAROUND 0x01 @@ -117,6 +120,7 @@ extern void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size); unsigned int get_vdec_clk_config_settings(void); void update_vdec_clk_config_settings(unsigned int config); //unsigned int get_mmu_mode(void);//DEBUG_TMP +extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug); struct vdec_s; enum vformat_t; @@ -147,7 +151,7 @@ enum vformat_t; #define VDEC_PROVIDER_NAME_SIZE 16 #define VDEC_RECEIVER_NAME_SIZE 16 -#define VDEC_MAP_NAME_SIZE 45 +#define VDEC_MAP_NAME_SIZE 90 #define VDEC_FLAG_OTHER_INPUT_CONTEXT 0x0 #define VDEC_FLAG_SELF_INPUT_CONTEXT 0x01 @@ -175,9 +179,12 @@ struct vdec_s { u32 pts; u64 pts64; bool pts_valid; + u64 timestamp; + bool timestamp_valid; int flag; int sched; int need_more_data; + u32 canvas_mode; struct completion inactive_done; @@ -195,10 +202,13 @@ struct vdec_s { /* input */ struct vdec_input_s input; + /*frame check*/ + struct pic_check_mgr_t vfc; + /* mc cache */ u32 mc[4096 * 4]; bool mc_loaded; - + u32 mc_type; /* frame provider/receiver interface */ char vf_provider_name[VDEC_PROVIDER_NAME_SIZE]; struct vframe_provider_s vframe_provider; @@ -216,10 +226,13 @@ struct vdec_s { /* canvas */ int (*get_canvas)(unsigned int index, unsigned int base); + int (*get_canvas_ex)(int type, int id); + void (*free_canvas_ex)(int index, int id); int (*dec_status)(struct vdec_s *vdec, struct vdec_info *vstatus); int (*set_trickmode)(struct vdec_s *vdec, unsigned long trickmode); int (*set_isreset)(struct vdec_s *vdec, int isreset); + void (*vdec_fps_detec)(int id); unsigned long (*run_ready)(struct vdec_s *vdec, unsigned long mask); void (*run)(struct vdec_s *vdec, unsigned long mask, @@ -232,7 +245,7 @@ struct vdec_s { int (*user_data_read)(struct vdec_s *vdec, struct userdata_param_t *puserdata_para); void (*reset_userdata_fifo)(struct vdec_s *vdec, int bInit); - + void (*wakeup_userdata_poll)(struct vdec_s *vdec); /* private */ void *private; /* decoder per instance specific data */ #ifdef VDEC_DEBUG_SUPPORT @@ -247,6 +260,7 @@ struct vdec_s { #endif atomic_t inirq_thread_flag; atomic_t inirq_flag; + int parallel_dec; }; /* common decoder vframe provider name to use default vfm path */ @@ -383,6 +397,8 @@ extern void vdec_count_info(struct vdec_info *vs, unsigned int err, extern bool vdec_need_more_data(struct vdec_s *vdec); +extern void vdec_reset_core(struct vdec_s *vdec); + extern void hevc_reset_core(struct vdec_s *vdec); extern void vdec_set_suspend_clk(int mode, int hevc); @@ -391,11 +407,11 @@ extern unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask); extern void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask); -extern int vdec_core_request(struct vdec_s *vdec, unsigned long mask); +extern void vdec_core_request(struct vdec_s *vdec, unsigned long mask); extern int vdec_core_release(struct vdec_s *vdec, unsigned long mask); -extern const bool vdec_core_with_input(unsigned long mask); +extern bool vdec_core_with_input(unsigned long mask); extern void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask); @@ -403,6 +419,10 @@ extern void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask); extern void vdec_set_step_mode(void); #endif +extern void vdec_disable_DMC(struct vdec_s *vdec); +extern void vdec_enable_DMC(struct vdec_s *vdec); +extern void hevc_enable_DMC(struct vdec_s *vdec); + int vdec_read_user_data(struct vdec_s *vdec, struct userdata_param_t *p_userdata_param); @@ -410,6 +430,8 @@ int vdec_wakeup_userdata_poll(struct vdec_s *vdec); void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit); +struct vdec_s *vdec_get_vdec_by_id(int vdec_id); + #ifdef VDEC_DEBUG_SUPPORT extern void vdec_set_step_mode(void); #endif @@ -417,4 +439,11 @@ int vdec_get_debug_flags(void); unsigned char is_mult_inc(unsigned int); +int vdec_get_status(struct vdec_s *vdec); + +void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp); + +struct vdec_s *vdec_get_with_id(unsigned int id); + +extern struct vframe_qos_s *vdec_get_qos_info(void); #endif /* VDEC_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c index 439e513677d3..f571bcf52592 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c @@ -25,6 +25,11 @@ #include "vdec.h" #include "vdec_input.h" +#include +#include + +#include + #define VFRAME_BLOCK_SIZE (512 * SZ_1K)/*512 for 1080p default init.*/ #define VFRAME_BLOCK_SIZE_4K (2 * SZ_1M) /*2M for 4K default.*/ #define VFRAME_BLOCK_SIZE_MAX (4 * SZ_1M) @@ -47,49 +52,96 @@ #define EXTRA_PADDING_SIZE (16 * SZ_1K) /*HEVC_PADDING_SIZE*/ #define MEM_NAME "VFRAME_INPUT" -static int vdec_input_get_duration_u64(struct vdec_input_s *input); + +//static int vdec_input_get_duration_u64(struct vdec_input_s *input); static struct vframe_block_list_s * - vdec_input_alloc_new_block(struct vdec_input_s *input); + vdec_input_alloc_new_block(struct vdec_input_s *input, + ulong phy_addr, + int size); + +static int copy_from_user_to_phyaddr(void *virts, const char __user *buf, + u32 size, ulong phys, u32 pading, bool is_mapped) +{ + u32 i, span = SZ_1M; + u32 count = size / PAGE_ALIGN(span); + u32 remain = size % PAGE_ALIGN(span); + ulong addr = phys; + u8 *p = virts; + + if (is_mapped) { + if (copy_from_user(p, buf, size)) + return -EFAULT; + + if (pading) + memset(p + size, 0, pading); + + codec_mm_dma_flush(p, size + pading, DMA_TO_DEVICE); + + return 0; + } + + for (i = 0; i < count; i++) { + addr = phys + i * span; + p = codec_mm_vmap(addr, span); + if (!p) + return -1; + + if (copy_from_user(p, buf + i * span, span)) { + codec_mm_unmap_phyaddr(p); + return -EFAULT; + } + + codec_mm_dma_flush(p, span, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + } + + if (!remain) + return 0; + + span = size - remain; + addr = phys + span; + p = codec_mm_vmap(addr, remain + pading); + if (!p) + return -1; + + if (copy_from_user(p, buf + span, remain)) { + codec_mm_unmap_phyaddr(p); + return -EFAULT; + } + + if (pading) + memset(p + remain, 0, pading); + + codec_mm_dma_flush(p, remain + pading, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + + return 0; +} static int vframe_chunk_fill(struct vdec_input_s *input, struct vframe_chunk_s *chunk, const char *buf, size_t count, struct vframe_block_list_s *block) { u8 *p = (u8 *)block->start_virt + block->wp; - int total_size = count + chunk->pading_size; if (block->type == VDEC_TYPE_FRAME_BLOCK) { - if (copy_from_user(p, buf, count)) - return -EFAULT; - - p += count; - - memset(p, 0, chunk->pading_size); - - dma_sync_single_for_device(get_vdec_device(), + copy_from_user_to_phyaddr(p, buf, count, block->start + block->wp, - total_size, DMA_TO_DEVICE); - + chunk->pading_size, + block->is_mapped); } else if (block->type == VDEC_TYPE_FRAME_CIRCULAR) { size_t len = min((size_t)(block->size - block->wp), count); u32 wp; - if (copy_from_user(p, buf, len)) - return -EFAULT; - - dma_sync_single_for_device(get_vdec_device(), - block->start + block->wp, - len, DMA_TO_DEVICE); - + copy_from_user_to_phyaddr(p, buf, len, + block->start + block->wp, 0, + block->is_mapped); p += len; if (count > len) { - p = (u8 *)block->start_virt; - if (copy_from_user(p, buf, count - len)) - return -EFAULT; - - dma_sync_single_for_device(get_vdec_device(), - block->start, - count-len, DMA_TO_DEVICE); + copy_from_user_to_phyaddr(p, buf + len, + count - len, + block->start, 0, + block->is_mapped); p += count - len; } @@ -100,20 +152,33 @@ static int vframe_chunk_fill(struct vdec_input_s *input, len = min(block->size - wp, chunk->pading_size); - memset(p, 0, len); - - dma_sync_single_for_device(get_vdec_device(), - block->start + wp, - len, DMA_TO_DEVICE); + if (!block->is_mapped) { + p = codec_mm_vmap(block->start + wp, len); + memset(p, 0, len); + codec_mm_dma_flush(p, len, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + } else { + memset(p, 0, len); + codec_mm_dma_flush(p, len, DMA_TO_DEVICE); + } if (chunk->pading_size > len) { p = (u8 *)block->start_virt; - memset(p, 0, count - len); - - dma_sync_single_for_device(get_vdec_device(), - block->start, - chunk->pading_size - len, DMA_TO_DEVICE); + if (!block->is_mapped) { + p = codec_mm_vmap(block->start, + chunk->pading_size - len); + memset(p, 0, chunk->pading_size - len); + codec_mm_dma_flush(p, + chunk->pading_size - len, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + } else { + memset(p, 0, chunk->pading_size - len); + codec_mm_dma_flush(p, + chunk->pading_size - len, + DMA_TO_DEVICE); + } } } @@ -157,7 +222,9 @@ static void vframe_block_free_block(struct vframe_block_list_s *block) } static int vframe_block_init_alloc_storage(struct vdec_input_s *input, - struct vframe_block_list_s *block) + struct vframe_block_list_s *block, + ulong phy_addr, + int size) { int alloc_size = input->default_block_size; block->magic = 0x4b434c42; @@ -167,24 +234,34 @@ static int vframe_block_init_alloc_storage(struct vdec_input_s *input, /* * todo: for different type use different size */ - alloc_size = PAGE_ALIGN(alloc_size); - block->addr = codec_mm_alloc_for_dma_ex( - MEM_NAME, - alloc_size/PAGE_SIZE, - VFRAME_BLOCK_PAGEALIGN, - CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER, - input->id, - block->id); + if (phy_addr) { + block->is_out_buf = 1; + block->start_virt = NULL; + block->start = phy_addr; + block->size = size; + } else { + alloc_size = PAGE_ALIGN(alloc_size); + block->addr = codec_mm_alloc_for_dma_ex( + MEM_NAME, + alloc_size/PAGE_SIZE, + VFRAME_BLOCK_PAGEALIGN, + CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER, + input->id, + block->id); - if (!block->addr) { - pr_err("Input block allocation failed\n"); - return -ENOMEM; + if (!block->addr) { + pr_err("Input block allocation failed\n"); + return -ENOMEM; + } + + block->start_virt = (void *)codec_mm_phys_to_virt(block->addr); + if (block->start_virt) + block->is_mapped = true; + block->start = block->addr; + block->size = alloc_size; + block->is_out_buf = 0; } - block->start_virt = (void *)codec_mm_phys_to_virt(block->addr); - block->start = block->addr; - block->size = alloc_size; - return 0; } @@ -208,6 +285,8 @@ int vdec_input_prepare_bufs(struct vdec_input_s *input, int i; unsigned long flags; + if (vdec_secure(input->vdec)) + return 0; if (input->size > 0) return 0; if (frame_width * frame_height >= 1920 * 1088) { @@ -216,7 +295,7 @@ int vdec_input_prepare_bufs(struct vdec_input_s *input, } /*prepared 3 buffers for smooth start.*/ for (i = 0; i < 3; i++) { - block = vdec_input_alloc_new_block(input); + block = vdec_input_alloc_new_block(input, 0, 0); if (!block) break; flags = vdec_input_lock(input); @@ -505,7 +584,9 @@ int vdec_input_level(struct vdec_input_s *input) EXPORT_SYMBOL(vdec_input_level); static struct vframe_block_list_s * - vdec_input_alloc_new_block(struct vdec_input_s *input) + vdec_input_alloc_new_block(struct vdec_input_s *input, + ulong phy_addr, + int size) { struct vframe_block_list_s *block; block = kzalloc(sizeof(struct vframe_block_list_s), @@ -517,7 +598,7 @@ static struct vframe_block_list_s * } if (vframe_block_init_alloc_storage(input, - block) != 0) { + block, phy_addr, size) != 0) { kfree(block); pr_err("vframe_block storage allocation failed\n"); return NULL; @@ -551,7 +632,7 @@ static struct vframe_block_list_s * } return block; } -static int vdec_input_get_duration_u64(struct vdec_input_s *input) +int vdec_input_get_duration_u64(struct vdec_input_s *input) { int duration = (input->last_inpts_u64 - input->last_comsumed_pts_u64); if (input->last_in_nopts_cnt > 0 && @@ -571,6 +652,8 @@ static int vdec_input_get_duration_u64(struct vdec_input_s *input) duration = 0; return duration; } +EXPORT_SYMBOL(vdec_input_get_duration_u64); + /* ret >= 13: have enough buffer, blocked add more buffers */ @@ -646,7 +729,7 @@ static int vdec_input_get_free_block( /*128k aligned,same as codec_mm*/ input->default_block_size = def_size; } - block = vdec_input_alloc_new_block(input); + block = vdec_input_alloc_new_block(input, 0, 0); if (!block) { input->no_mem_err_cnt++; return -EAGAIN; @@ -656,94 +739,104 @@ static int vdec_input_get_free_block( return 0; } -int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, - size_t count) +int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf, + size_t count, u32 handle) { unsigned long flags; struct vframe_chunk_s *chunk; struct vdec_s *vdec = input->vdec; struct vframe_block_list_s *block; + int need_pading_size = MIN_FRAME_PADDING_SIZE; -#if 0 - if (add_count == 0) { - add_count++; - memcpy(sps, buf, 30); - return 30; - } else if (add_count == 1) { - add_count++; - memcpy(pps, buf, 8); - return 8; - } - add_count++; -#endif - -#if 0 - pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count); - - if (count >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); - } - if (count >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[8], buf[9], buf[10], buf[11], - buf[12], buf[13], buf[14], buf[15]); - } - if (count >= 24) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[16], buf[17], buf[18], buf[19], - buf[20], buf[21], buf[22], buf[23]); - } - if (count >= 32) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[24], buf[25], buf[26], buf[27], - buf[28], buf[29], buf[30], buf[31]); - } -#endif - if (input_stream_based(input)) - return -EINVAL; - if (count < PAGE_SIZE) { - need_pading_size = PAGE_ALIGN(count + need_pading_size) - - count; + if (vdec_secure(vdec)) { + block = vdec_input_alloc_new_block(input, (ulong)buf, + PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1)); /*Add padding large than HEVC_PADDING_SIZE */ + if (!block) + return -ENOMEM; + block->handle = handle; } else { - /*to 64 bytes aligned;*/ - if (count & 0x3f) - need_pading_size += 64 - (count & 0x3f); - } - block = input->wr_block; - if (block && - (vframe_block_space(block) > (count + need_pading_size))) { - /*this block have enough buffers. - do nothings. - */ - } else if (block && (block->type == VDEC_TYPE_FRAME_CIRCULAR)) { - /*in circular module. - only one block,.*/ - return -EAGAIN; - } else if (block != NULL) { - /*have block but not enough space. - recycle the no enough blocks.*/ - flags = vdec_input_lock(input); - if (input->wr_block == block && - block->chunk_count == 0) { - block->rp = 0; - block->wp = 0; - /*block no data move to freelist*/ - list_move_tail(&block->list, - &input->vframe_block_free_list); - input->wr_block = NULL; +#if 0 + if (add_count == 0) { + add_count++; + memcpy(sps, buf, 30); + return 30; + } else if (add_count == 1) { + add_count++; + memcpy(pps, buf, 8); + return 8; } - vdec_input_unlock(input, flags); - block = NULL; + add_count++; +#endif + +#if 0 + pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count); + + if (count >= 8) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + } + if (count >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15]); + } + if (count >= 24) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23]); + } + if (count >= 32) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31]); } - if (!block) {/*try new block.*/ - int ret = vdec_input_get_free_block(input, - count + need_pading_size + EXTRA_PADDING_SIZE, - &block); - if (ret < 0)/*no enough block now.*/ - return ret; +#endif + if (input_stream_based(input)) + return -EINVAL; + + if (count < PAGE_SIZE) { + need_pading_size = PAGE_ALIGN(count + need_pading_size) - + count; + } else { + /*to 64 bytes aligned;*/ + if (count & 0x3f) + need_pading_size += 64 - (count & 0x3f); + } + block = input->wr_block; + if (block && + (vframe_block_space(block) > (count + need_pading_size))) { + /*this block have enough buffers. + do nothings. + */ + } else if (block && (block->type == VDEC_TYPE_FRAME_CIRCULAR)) { + /*in circular module. + only one block,.*/ + return -EAGAIN; + } else if (block != NULL) { + /*have block but not enough space. + recycle the no enough blocks.*/ + flags = vdec_input_lock(input); + if (input->wr_block == block && + block->chunk_count == 0) { + block->rp = 0; + block->wp = 0; + /*block no data move to freelist*/ + list_move_tail(&block->list, + &input->vframe_block_free_list); + input->wr_block = NULL; + } + vdec_input_unlock(input, flags); + block = NULL; + } + if (!block) {/*try new block.*/ + int ret = vdec_input_get_free_block(input, + count + need_pading_size + EXTRA_PADDING_SIZE, + &block); + if (ret < 0)/*no enough block now.*/ + return ret; + } } chunk = kzalloc(sizeof(struct vframe_chunk_s), GFP_KERNEL); @@ -758,6 +851,10 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, chunk->pts = vdec->pts; chunk->pts64 = vdec->pts64; } + + if (vdec->timestamp_valid) + chunk->timestamp = vdec->timestamp; + if (vdec->pts_valid && input->last_inpts_u64 > 0 && input->last_in_nopts_cnt == 0) { @@ -771,17 +868,26 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, } chunk->pts_valid = vdec->pts_valid; vdec->pts_valid = false; - chunk->offset = block->wp; - chunk->size = count; - chunk->pading_size = need_pading_size; INIT_LIST_HEAD(&chunk->list); - if (vframe_chunk_fill(input, chunk, buf, count, block)) { - pr_err("vframe_chunk_fill failed\n"); - kfree(chunk); - return -EFAULT; + if (vdec_secure(vdec)) { + chunk->offset = 0; + chunk->size = count; + chunk->pading_size = PAGE_ALIGN(chunk->size + need_pading_size) - + chunk->size; + } else { + chunk->offset = block->wp; + chunk->size = count; + chunk->pading_size = need_pading_size; + if (vframe_chunk_fill(input, chunk, buf, count, block)) { + pr_err("vframe_chunk_fill failed\n"); + kfree(chunk); + return -EFAULT; + } + } + flags = vdec_input_lock(input); vframe_block_add_chunk(block, chunk); @@ -789,6 +895,7 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, list_add_tail(&chunk->list, &input->vframe_chunk_list); input->data_size += chunk->size; input->have_frame_num++; + ATRACE_COUNTER(MEM_NAME, input->have_frame_num); if (chunk->pts_valid) { input->last_inpts_u64 = chunk->pts64; input->last_in_nopts_cnt = 0; @@ -796,11 +903,10 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, /*nopts*/ input->last_in_nopts_cnt++; } - vdec_input_unlock(input, flags); if (chunk->size > input->frame_max_size) input->frame_max_size = chunk->size; input->total_wr_count += count; - + vdec_input_unlock(input, flags); #if 0 if (add_count == 2) input->total_wr_count += 38; @@ -808,6 +914,39 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, return count; } + +int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, + size_t count) +{ + int ret = 0; + struct drm_info drm; + struct vdec_s *vdec = input->vdec; + unsigned long phy_buf; + + if (vdec_secure(vdec)) { + while (count > 0) { + if (count < sizeof(struct drm_info)) + return -EIO; + if (copy_from_user(&drm, buf + ret, sizeof(struct drm_info))) + return -EAGAIN; + if (!(drm.drm_flag & TYPE_DRMINFO_V2)) + return -EIO; /*must drm info v2 version*/ + phy_buf = (unsigned long) drm.drm_phy; + vdec_input_add_chunk(input, (char *)phy_buf, + (size_t)drm.drm_pktsize, drm.handle); + count -= sizeof(struct drm_info); + ret += sizeof(struct drm_info); + + /* the drm frame data might include head infos and raw */ + /* data thus the next drm unit still need a valid pts.*/ + if (count >= sizeof(struct drm_info)) + vdec->pts_valid = true; + } + } else { + ret = vdec_input_add_chunk(input, buf, count, 0); + } + return ret; +} EXPORT_SYMBOL(vdec_input_add_frame); struct vframe_chunk_s *vdec_input_next_chunk(struct vdec_input_s *input) @@ -855,6 +994,7 @@ void vdec_input_release_chunk(struct vdec_input_s *input, list_del(&chunk->list); input->have_frame_num--; + ATRACE_COUNTER(MEM_NAME, input->have_frame_num); if (chunk->pts_valid) { input->last_comsumed_no_pts_cnt = 0; input->last_comsumed_pts_u64 = chunk->pts64; @@ -867,8 +1007,11 @@ void vdec_input_release_chunk(struct vdec_input_s *input, block->chunk_count--; input->data_size -= chunk->size; input->total_rd_count += chunk->size; - if (block->chunk_count == 0 && - input->wr_block != block) {/*don't free used block*/ + if (block->is_out_buf) { + list_move_tail(&block->list, + &input->vframe_block_free_list); + } else if (block->chunk_count == 0 && + input->wr_block != block ) {/*don't free used block*/ if (block->size < input->default_block_size) { vdec_input_del_block_locked(input, block); tofreeblock = block; @@ -938,3 +1081,26 @@ void vdec_input_release(struct vdec_input_s *input) } EXPORT_SYMBOL(vdec_input_release); +u32 vdec_input_get_freed_handle(struct vdec_s *vdec) +{ + struct vframe_block_list_s *block; + struct vdec_input_s *input = &vdec->input; + unsigned long flags; + u32 handle = 0; + + if (!vdec_secure(vdec)) + return 0; + + flags = vdec_input_lock(input); + block = list_first_entry_or_null(&input->vframe_block_free_list, + struct vframe_block_list_s, list); + + if (block) { + handle = block->handle; + vdec_input_del_block_locked(input, block); + kfree(block); + } + vdec_input_unlock(input, flags); + return handle; +} +EXPORT_SYMBOL(vdec_input_get_freed_handle); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h index d95e13f97c42..d2304f6bcf4d 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h @@ -28,12 +28,15 @@ struct vframe_block_list_s { ulong start; void *start_virt; ulong addr; + bool is_mapped; int type; u32 size; u32 wp; u32 rp; int data_size; int chunk_count; + int is_out_buf; + u32 handle; struct vdec_input_s *input; }; @@ -49,12 +52,16 @@ struct vframe_chunk_s { u32 pading_size; u64 pts64; bool pts_valid; + u64 timestamp; + bool timestamp_valid; u64 sequence; struct vframe_block_list_s *block; }; #define VDEC_INPUT_TARGET_VLD 0 #define VDEC_INPUT_TARGET_HEVC 1 +#define VLD_PADDING_SIZE 1024 +#define HEVC_PADDING_SIZE (1024*16) struct vdec_input_s { struct list_head vframe_block_list; @@ -156,9 +163,13 @@ extern void vdec_input_unlock(struct vdec_input_s *input, unsigned long lock); /* release all resource for decoder's input */ extern void vdec_input_release(struct vdec_input_s *input); +/* return block handle and free block */ +extern u32 vdec_input_get_freed_handle(struct vdec_s *vdec); int vdec_input_dump_chunks(struct vdec_input_s *input, char *bufs, int size); int vdec_input_dump_blocks(struct vdec_input_s *input, char *bufs, int size); +int vdec_input_get_duration_u64(struct vdec_input_s *input); + #endif /* VDEC_INPUT_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c index 77eb4e30f116..d03335a6297c 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c @@ -19,8 +19,11 @@ #include #include #include +#include + #include +#include #include "vdec_profile.h" #include "vdec.h" @@ -32,9 +35,40 @@ static DEFINE_MUTEX(vdec_profile_mutex); static int rec_wp; static bool rec_wrapped; +static uint dec_time_stat_flag; +static uint dec_time_stat_reset; + struct dentry *root, *event; +#define MAX_INSTANCE_MUN 9 + +struct vdec_profile_time_stat_s { + int time_6ms_less_cnt; + int time_6_9ms_cnt; + int time_9_12ms_cnt; + int time_12_15ms_cnt; + int time_15_18ms_cnt; + int time_18_21ms_cnt; + int time_21ms_up_cnt; + u64 time_max_us; + u64 time_total_us; +}; + +struct vdec_profile_statistics_s { + bool status; + u64 run_lasttimestamp; + int run_cnt; + u64 cb_lasttimestamp; + int cb_cnt; + u64 decode_first_us; + struct vdec_profile_time_stat_s run2cb_time_stat; + struct vdec_profile_time_stat_s decode_time_stat; +}; + +static struct vdec_profile_statistics_s statistics_s[MAX_INSTANCE_MUN]; + + struct vdec_profile_rec_s { struct vdec_s *vdec; u64 timestamp; @@ -62,7 +96,7 @@ static u64 get_us_time_hw(void) int offset = 0; /* txlx, g12a isa register base is 0x3c00 */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) offset = 0x1600; do { @@ -84,6 +118,90 @@ static u64 get_us_time_system(void) return div64_u64(timeval_to_ns(&tv), 1000); } +static void vdec_profile_update_alloc_time( + struct vdec_profile_time_stat_s *time_stat, u64 startus, u64 endus) +{ + u64 spend_time_us = endus - startus; + + if (spend_time_us > 0 && spend_time_us < 100000000) { + if (spend_time_us < 6000) + time_stat->time_6ms_less_cnt++; + else if (spend_time_us < 9000) + time_stat->time_6_9ms_cnt++; + else if (spend_time_us < 12000) + time_stat->time_9_12ms_cnt++; + else if (spend_time_us < 15000) + time_stat->time_12_15ms_cnt++; + else if (spend_time_us < 18000) + time_stat->time_15_18ms_cnt++; + else if (spend_time_us < 21000) + time_stat->time_18_21ms_cnt++; + else + time_stat->time_21ms_up_cnt++; + } + + if (spend_time_us > time_stat->time_max_us) + time_stat->time_max_us = spend_time_us; + + time_stat->time_total_us += spend_time_us; +} + + +static void vdec_profile_statistics(struct vdec_s *vdec, int event) +{ + struct vdec_profile_statistics_s *time_stat = NULL; + u64 timestamp; + int i; + + if (vdec->id >= MAX_INSTANCE_MUN) + return; + + if (event != VDEC_PROFILE_EVENT_RUN && + event != VDEC_PROFILE_EVENT_CB) + return; + + mutex_lock(&vdec_profile_mutex); + + if (dec_time_stat_reset == 1) { + if (event != VDEC_PROFILE_EVENT_RUN) { + mutex_unlock(&vdec_profile_mutex); + return; + } + for (i = 0; i < MAX_INSTANCE_MUN; i++) + memset(&statistics_s[i], 0, + sizeof(struct vdec_profile_statistics_s)); + dec_time_stat_reset = 0; + } + + time_stat = &statistics_s[vdec->id]; + timestamp = get_us_time_system(); + + if (time_stat->status == false) { + time_stat->decode_first_us = timestamp; + time_stat->status = true; + } + + if (event == VDEC_PROFILE_EVENT_RUN) { + time_stat->run_lasttimestamp = timestamp; + time_stat->run_cnt++; + } else if (event == VDEC_PROFILE_EVENT_CB) { + /*run2cb statistics*/ + vdec_profile_update_alloc_time(&time_stat->run2cb_time_stat, time_stat->run_lasttimestamp, timestamp); + + /*decode statistics*/ + if (time_stat->cb_cnt == 0) + vdec_profile_update_alloc_time(&time_stat->decode_time_stat, time_stat->decode_first_us, timestamp); + else + vdec_profile_update_alloc_time(&time_stat->decode_time_stat, time_stat->cb_lasttimestamp, timestamp); + + time_stat->cb_lasttimestamp = timestamp; + time_stat->cb_cnt++; + } + + mutex_unlock(&vdec_profile_mutex); +} + + void vdec_profile_more(struct vdec_s *vdec, int event, int para1, int para2) { mutex_lock(&vdec_profile_mutex); @@ -106,7 +224,10 @@ EXPORT_SYMBOL(vdec_profile_more); void vdec_profile(struct vdec_s *vdec, int event) { + ATRACE_COUNTER(vdec_device_name_str(vdec), event); vdec_profile_more(vdec, event, 0 , 0); + if (dec_time_stat_flag == 1) + vdec_profile_statistics(vdec, event); } EXPORT_SYMBOL(vdec_profile); @@ -114,6 +235,9 @@ void vdec_profile_flush(struct vdec_s *vdec) { int i; + if (vdec->id >= MAX_INSTANCE_MUN) + return; + mutex_lock(&vdec_profile_mutex); for (i = 0; i < PROFILE_REC_SIZE; i++) { @@ -121,6 +245,8 @@ void vdec_profile_flush(struct vdec_s *vdec) recs[i].vdec = NULL; } + memset(&statistics_s[vdec->id], 0, sizeof(struct vdec_profile_statistics_s)); + mutex_unlock(&vdec_profile_mutex); } @@ -183,11 +309,84 @@ static int vdec_profile_dbg_show(struct seq_file *m, void *v) return 0; } +static int time_stat_profile_dbg_show(struct seq_file *m, void *v) +{ + int i; + + mutex_lock(&vdec_profile_mutex); + + for (i = 0; i < MAX_INSTANCE_MUN; i++) + { + if (statistics_s[i].status == false) + continue; + + seq_printf(m, "[%d]run_cnt:%d, cb_cnt:%d\n\ + \t\t\ttime_total_us:%llu\n\ + \t\t\trun2cb time:\n\ + \t\t\ttime_max_us:%llu\n\ + \t\t\t[%d]run2cb ave_us:%llu\n\ + \t\t\ttime_6ms_less_cnt:%d\n\ + \t\t\ttime_6_9ms_cnt:%d\n\ + \t\t\ttime_9_12ms_cnt:%d\n\ + \t\t\ttime_12_15ms_cnt:%d\n\ + \t\t\ttime_15_18ms_cnt:%d\n\ + \t\t\ttime_18_21ms_cnt:%d\n\ + \t\t\ttime_21ms_up_cnt:%d\n\ + \t\t\tdecode time:\n\ + \t\t\ttime_total_us:%llu\n\ + \t\t\ttime_max_us:%llu\n\ + \t\t\t[%d]cb2cb ave_us:%llu\n\ + \t\t\ttime_6ms_less_cnt:%d\n\ + \t\t\ttime_6_9ms_cnt:%d\n\ + \t\t\ttime_9_12ms_cnt:%d\n\ + \t\t\ttime_12_15ms_cnt:%d\n\ + \t\t\ttime_15_18ms_cnt:%d\n\ + \t\t\ttime_18_21ms_cnt:%d\n\ + \t\t\ttime_21ms_up_cnt:%d\n", + i, + statistics_s[i].run_cnt, + statistics_s[i].cb_cnt, + statistics_s[i].run2cb_time_stat.time_total_us, + statistics_s[i].run2cb_time_stat.time_max_us, + i, + div_u64(statistics_s[i].run2cb_time_stat.time_total_us , statistics_s[i].cb_cnt), + statistics_s[i].run2cb_time_stat.time_6ms_less_cnt, + statistics_s[i].run2cb_time_stat.time_6_9ms_cnt, + statistics_s[i].run2cb_time_stat.time_9_12ms_cnt, + statistics_s[i].run2cb_time_stat.time_12_15ms_cnt, + statistics_s[i].run2cb_time_stat.time_15_18ms_cnt, + statistics_s[i].run2cb_time_stat.time_18_21ms_cnt, + statistics_s[i].run2cb_time_stat.time_21ms_up_cnt, + statistics_s[i].decode_time_stat.time_total_us, + statistics_s[i].decode_time_stat.time_max_us, + i, + div_u64(statistics_s[i].decode_time_stat.time_total_us , statistics_s[i].cb_cnt), + statistics_s[i].decode_time_stat.time_6ms_less_cnt, + statistics_s[i].decode_time_stat.time_6_9ms_cnt, + statistics_s[i].decode_time_stat.time_9_12ms_cnt, + statistics_s[i].decode_time_stat.time_12_15ms_cnt, + statistics_s[i].decode_time_stat.time_15_18ms_cnt, + statistics_s[i].decode_time_stat.time_18_21ms_cnt, + statistics_s[i].decode_time_stat.time_21ms_up_cnt); + } + + mutex_unlock(&vdec_profile_mutex); + + return 0; +} + + static int vdec_profile_dbg_open(struct inode *inode, struct file *file) { return single_open(file, vdec_profile_dbg_show, NULL); } +static int time_stat_profile_dbg_open(struct inode *inode, struct file *file) +{ + return single_open(file, time_stat_profile_dbg_show, NULL); +} + + static const struct file_operations event_dbg_fops = { .open = vdec_profile_dbg_open, .read = seq_read, @@ -195,6 +394,14 @@ static const struct file_operations event_dbg_fops = { .release = single_release, }; +static const struct file_operations time_stat_dbg_fops = { + .open = time_stat_profile_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + #if 0 /*DEBUG_TMP*/ static int __init vdec_profile_init_debugfs(void) { @@ -224,7 +431,7 @@ err: int vdec_profile_init_debugfs(void) { - struct dentry *root, *event; + struct dentry *root, *event, *time_stat; root = debugfs_create_dir("vdec_profile", NULL); if (IS_ERR(root) || !root) @@ -235,10 +442,17 @@ int vdec_profile_init_debugfs(void) if (!event) goto err_1; + time_stat = debugfs_create_file("time_stat", 0400, root, NULL, + &time_stat_dbg_fops); + if (!time_stat) + goto err_2; + mutex_init(&vdec_profile_mutex); return 0; +err_2: + debugfs_remove(event); err_1: debugfs_remove(root); err: @@ -254,5 +468,10 @@ void vdec_profile_exit_debugfs(void) } EXPORT_SYMBOL(vdec_profile_exit_debugfs); +module_param(dec_time_stat_flag, uint, 0664); + +module_param(dec_time_stat_reset, uint, 0664); + + /*module_init(vdec_profile_init_debugfs);*/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c index 49517eebf562..d9cb53c0839a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c @@ -42,6 +42,9 @@ #include #include "../utils/firmware.h" #include +#include +#include + #define DRIVER_NAME "amvdec_vc1" #define MODULE_NAME "amvdec_vc1" @@ -51,6 +54,8 @@ #define NV21 #endif +#define VC1_MAX_SUPPORT_SIZE (1920*1088) + #define I_PICTURE 0 #define P_PICTURE 1 #define B_PICTURE 2 @@ -137,6 +142,7 @@ static u32 next_pts; static u64 next_pts_us64; static bool is_reset; static struct work_struct set_clk_work; +static struct work_struct error_wd_work; #ifdef DEBUG_PTS static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; @@ -273,9 +279,10 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) u32 repeat_count; u32 picture_type; u32 buffer_index; - unsigned int pts, pts_valid = 0, offset; + unsigned int pts, pts_valid = 0, offset = 0; u32 v_width, v_height; u64 pts_us64 = 0; + u32 frame_size; reg = READ_VREG(VC1_BUFFEROUT); @@ -302,7 +309,8 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) offset = READ_VREG(VC1_OFFSET_REG); if (pts_lookup_offset_us64( PTS_TYPE_VIDEO, - offset, &pts, 0, &pts_us64) == 0) { + offset, &pts, &frame_size, + 0, &pts_us64) == 0) { pts_valid = 1; #ifdef DEBUG_PTS pts_hit++; @@ -490,6 +498,7 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver( PROVIDER_NAME, @@ -549,6 +558,7 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver( PROVIDER_NAME, @@ -633,6 +643,7 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) mm_blk_handle, buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -721,6 +732,9 @@ static int vvc1_event_cb(int type, void *data, void *private_data) int vvc1_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = vvc1_amstream_dec_info.width; vstatus->frame_height = vvc1_amstream_dec_info.height; if (vvc1_amstream_dec_info.rate != 0) @@ -978,23 +992,18 @@ static void vvc1_ppmgr_reset(void) static void vvc1_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; vdec_source_changed(VFORMAT_VC1, frame_width, frame_height, fps); - } + } -static void vvc1_put_timer_func(unsigned long arg) +static void error_do_work(struct work_struct *work) { - struct timer_list *timer = (struct timer_list *)arg; - -#if 1 - if (READ_VREG(VC1_SOS_COUNT) > 10) { amvdec_stop(); + msleep(20); #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER vvc1_ppmgr_reset(); #else @@ -1004,8 +1013,15 @@ static void vvc1_put_timer_func(unsigned long arg) #endif vvc1_prot_init(); amvdec_start(); - } -#endif +} + + +static void vvc1_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + + if (READ_VREG(VC1_SOS_COUNT) > 10) + schedule_work(&error_wd_work); while (!kfifo_is_empty(&recycle_q) && (READ_VREG(VC1_BUFFERIN) == 0)) { struct vframe_s *vf; @@ -1020,7 +1036,10 @@ static void vvc1_put_timer_func(unsigned long arg) kfifo_put(&newframe_q, (const struct vframe_s *)vf); } } - schedule_work(&set_clk_work); + + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; add_timer(timer); @@ -1028,7 +1047,7 @@ static void vvc1_put_timer_func(unsigned long arg) static s32 vvc1_init(void) { - int ret = -1, size = -1; + int ret = -1; char *buf = vmalloc(0x1000 * 16); int fw_type = VIDEO_DEC_VC1; @@ -1056,19 +1075,19 @@ static s32 vvc1_init(void) } else pr_info("not supported VC1 format\n"); - size = get_firmware_data(fw_type, buf); - if (size < 0) { + if (get_firmware_data(fw_type, buf) < 0) { amvdec_disable(); pr_err("get firmware fail."); vfree(buf); return -1; } - if (size == 1) - pr_info("tee load ok\n"); - else if (amvdec_loadmc_ex(VFORMAT_VC1, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_VC1, NULL, buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("VC1: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1134,28 +1153,40 @@ static int amvdec_vc1_probe(struct platform_device *pdev) return -EFAULT; } - if (pdata->sys_info) + if (pdata->sys_info) { vvc1_amstream_dec_info = *pdata->sys_info; + if ((vvc1_amstream_dec_info.height != 0) && + (vvc1_amstream_dec_info.width > + (VC1_MAX_SUPPORT_SIZE/vvc1_amstream_dec_info.height))) { + pr_info("amvdec_vc1: over size, unsupport: %d * %d\n", + vvc1_amstream_dec_info.width, + vvc1_amstream_dec_info.height); + return -EFAULT; + } + } pdata->dec_status = vvc1_dec_status; pdata->set_isreset = vvc1_set_isreset; is_reset = 0; vvc1_vdec_info_init(); + INIT_WORK(&error_wd_work, error_do_work); + INIT_WORK(&set_clk_work, vvc1_set_clk); if (vvc1_init() < 0) { pr_info("amvdec_vc1 init failed.\n"); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; return -ENODEV; } - INIT_WORK(&set_clk_work, vvc1_set_clk); + return 0; } static int amvdec_vc1_remove(struct platform_device *pdev) { - cancel_work_sync(&set_clk_work); + cancel_work_sync(&error_wd_work); if (stat & STAT_VDEC_RUN) { amvdec_stop(); stat &= ~STAT_VDEC_RUN; @@ -1171,6 +1202,7 @@ static int amvdec_vc1_remove(struct platform_device *pdev) stat &= ~STAT_TIMER_ARM; } + cancel_work_sync(&set_clk_work); if (stat & STAT_VF_HOOK) { if (!is_reset) vf_notify_receiver(PROVIDER_NAME, diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c index df2880dffd39..42ecd4613b83 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c @@ -53,16 +53,19 @@ #include #include "../utils/config_parser.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" + +#include + #define MIX_STREAM_SUPPORT -#define SUPPORT_4K2K #include "vvp9.h" -#ifdef VP9_10B_MMU + /*#define SUPPORT_FB_DECODING*/ /*#define FB_DECODING_TEST_SCHEDULE*/ -#endif + #define HW_MASK_FRONT 0x1 #define HW_MASK_BACK 0x2 @@ -131,11 +134,6 @@ #define MULTI_INSTANCE_SUPPORT #define SUPPORT_10BIT /* #define ERROR_HANDLE_DEBUG */ -#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ -#undef SUPPORT_4K2K -#else -#define SUPPORT_4K2K -#endif #ifndef STAT_KTHREAD #define STAT_KTHREAD 0x40 @@ -156,11 +154,7 @@ static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; static u32 decode_timeout_val = 200; static int start_decode_buf_level = 0x8000; -#ifdef VP9_10B_MMU -static u32 work_buf_size; /* = 24 * 1024 * 1024*/; -#else -static u32 work_buf_size = 32 * 1024 * 1024; -#endif +static u32 work_buf_size; static u32 mv_buf_margin; @@ -209,7 +203,6 @@ static void dump_data(struct VP9Decoder_s *pbi, int size); static unsigned char get_data_check_sum (struct VP9Decoder_s *pbi, int size); static void dump_pic_list(struct VP9Decoder_s *pbi); -#ifdef VP9_10B_MMU static int vp9_alloc_mmu( struct VP9Decoder_s *pbi, int cur_buf_idx, @@ -217,7 +210,7 @@ static int vp9_alloc_mmu( int pic_height, unsigned short bit_depth, unsigned int *mmu_index_adr); -#endif + static const char vvp9_dec_id[] = "vvp9-dev"; @@ -247,7 +240,7 @@ static u32 on_no_keyframe_skiped; #define COUNT_BUF_SIZE (0x300 * 4 * 4) /*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ #define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +#define MAX_FRAME_8K_NUM 0x4800 #define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 @@ -269,8 +262,9 @@ static inline int div_r32(int64_t m, int n) *return (int)(m/n) */ #ifndef CONFIG_ARM64 - do_div(m, n); - return (int)m; + int64_t qu = 0; + qu = div_s64(m, n); + return (int)qu; #else return (int)(m/n); #endif @@ -298,7 +292,8 @@ struct MVBUF_s { /* #undef BUFMGR_ONLY to enable hardware configuration */ /*#define TEST_WR_PTR_INC*/ -#define WR_PTR_INC_NUM 128 +/*#define WR_PTR_INC_NUM 128*/ +#define WR_PTR_INC_NUM 1 #define SIMULATION #define DOS_PROJECT @@ -312,12 +307,6 @@ struct MVBUF_s { /*#define ENABLE_SWAP_TEST*/ #define MCRCC_ENABLE -#ifdef VP9_10B_NV21 -#define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/ -#else -#define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/ -#endif - #define VP9_LPF_LVL_UPDATE /*#define DBG_LF_PRINT*/ @@ -410,9 +399,12 @@ void WRITE_VREG_DBG2(unsigned int adr, unsigned int val) VP9 buffer management start ***************************************************/ -#ifdef VP9_10B_MMU + #define MMU_COMPRESS_HEADER_SIZE 0x48000 -#endif +#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) +#define MAX_SIZE_8K (8192 * 4608) +#define MAX_SIZE_4K (4096 * 2304) +#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) #define INVALID_IDX -1 /* Invalid buffer index.*/ @@ -512,12 +504,11 @@ struct PIC_BUFFER_CONFIG_s { /**/ int slice_idx; /*buffer*/ -#ifdef VP9_10B_MMU unsigned long header_adr; -#endif unsigned long mpred_mv_wr_start_addr; - unsigned long mc_y_adr; - unsigned long mc_u_v_adr; + /*unsigned long mc_y_adr; + *unsigned long mc_u_v_adr; + */ unsigned int dw_y_adr; unsigned int dw_u_v_adr; int mc_canvas_y; @@ -736,9 +727,7 @@ struct VP9_Common_s { int prev_fb_idx; int new_fb_idx; -#ifdef VP9_10B_MMU int cur_fb_idx_mmu; -#endif /*last frame's frame type for motion search*/ enum FRAME_TYPE last_frame_type; enum FRAME_TYPE frame_type; @@ -807,7 +796,7 @@ struct VP9_Common_s { int above_context_alloc_cols; -} VP9_COMMON; +}; static void set_canvas(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config); @@ -897,10 +886,8 @@ struct BuffInfo_s { struct buff_s dblk_para; struct buff_s dblk_data; struct buff_s seg_map; -#ifdef VP9_10B_MMU struct buff_s mmu_vbh; struct buff_s cm_header; -#endif struct buff_s mpred_above; #ifdef MV_USE_FIXED_BUF struct buff_s mpred_mv; @@ -983,12 +970,12 @@ struct VP9Decoder_s { unsigned last_lcu_idx; int decode_timeout_count; unsigned timeout_num; + int save_buffer_mode; int double_write_mode; #endif -#ifdef VP9_10B_MMU long used_4k_num; -#endif + unsigned char m_ins_flag; char *provider_name; union param_u param; @@ -1000,6 +987,7 @@ struct VP9Decoder_s { u32 frame_ar; int fatal_error; uint8_t init_flag; + uint8_t first_sc_checked; uint8_t process_busy; #define PROC_STATE_INIT 0 #define PROC_STATE_DECODESLICE 1 @@ -1008,9 +996,7 @@ struct VP9Decoder_s { u32 ucode_pause_pos; int show_frame_num; -#ifndef VP9_10B_MMU struct buff_s mc_buf_spec; -#endif struct dec_sysinfo vvp9_amstream_dec_info; void *rpm_addr; void *lmem_addr; @@ -1024,11 +1010,9 @@ struct VP9Decoder_s { dma_addr_t prob_buffer_phy_addr; dma_addr_t count_buffer_phy_addr; -#if 1 - /*VP9_10B_MMU*/ void *frame_mmu_map_addr; dma_addr_t frame_mmu_map_phy_addr; -#endif + unsigned int use_cma_flag; struct BUF_s m_BUF[MAX_BUF_NUM]; @@ -1078,10 +1062,11 @@ struct VP9Decoder_s { uint8_t hold_ref_buf; uint8_t ready_for_new_data; struct BufferPool_s vp9_buffer_pool; + struct BuffInfo_s *work_space_buf; -#ifndef VP9_10B_MMU + struct buff_s *mc_buf; -#endif + unsigned int frame_width; unsigned int frame_height; @@ -1121,6 +1106,7 @@ struct VP9Decoder_s { int new_frame_displayed; void *mmu_box; void *bmmu_box; + int mmu_enable; struct vframe_master_display_colour_s vf_dp; struct firmware_s *fw; int max_pic_w; @@ -1153,7 +1139,9 @@ struct VP9Decoder_s { union param_u s1_param; u8 back_not_run_ready; #endif -} ; + int need_cache_size; + u64 sc_start_time; +}; static void resize_context_buffers(struct VP9Decoder_s *pbi, struct VP9_Common_s *cm, int width, int height) @@ -1217,27 +1205,24 @@ static int setup_frame_size( (" * 16-bits h read : %d (height : %d)\n", width, height); WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); - -#ifdef VP9_10B_MMU - /* if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);*/ - /* cm->prev_fb_idx = cm->new_fb_idx;*/ - /*pr_info - ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n", - cm->prev_fb_idx, cm->new_fb_idx);*/ - ret = vp9_alloc_mmu(pbi, - cm->new_fb_idx, - params->p.width, - params->p.height, - params->p.bit_depth, - mmu_index_adr); - if (ret != 0) { - pr_err("can't alloc need mmu1,idx %d ret =%d\n", - cm->new_fb_idx, - ret); - return ret; - } - cm->cur_fb_idx_mmu = cm->new_fb_idx; +#ifdef VP9_10B_HED_FB + WRITE_VREG(HEVC_ASSIST_PIC_SIZE_FB_READ, (height << 16) | width); #endif + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + ret = vp9_alloc_mmu(pbi, + cm->new_fb_idx, + params->p.width, + params->p.height, + params->p.bit_depth, + mmu_index_adr); + if (ret != 0) { + pr_err("can't alloc need mmu1,idx %d ret =%d\n", + cm->new_fb_idx, + ret); + return ret; + } + cm->cur_fb_idx_mmu = cm->new_fb_idx; + } resize_context_buffers(pbi, cm, width, height); setup_display_size(cm, params, print_header_info); @@ -1340,22 +1325,25 @@ static int setup_frame_size_with_refs( params->p.height = height; WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); -#ifdef VP9_10B_MMU - /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); - cm->prev_fb_idx = cm->new_fb_idx;*/ -/* pr_info - ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n", - cm->prev_fb_idx, cm->new_fb_idx);*/ - ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, - params->p.width, params->p.height, - params->p.bit_depth, mmu_index_adr); - if (ret != 0) { - pr_err("can't alloc need mmu,idx %d\r\n", - cm->new_fb_idx); - return ret; + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); + *cm->prev_fb_idx = cm->new_fb_idx; + */ + /* pr_info + * ("[DEBUG DEBUG]Before alloc_mmu, + * prev_fb_idx : %d, new_fb_idx : %d\r\n", + * cm->prev_fb_idx, cm->new_fb_idx); + */ + ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, + params->p.width, params->p.height, + params->p.bit_depth, mmu_index_adr); + if (ret != 0) { + pr_err("can't alloc need mmu,idx %d\r\n", + cm->new_fb_idx); + return ret; + } + cm->cur_fb_idx_mmu = cm->new_fb_idx; } - cm->cur_fb_idx_mmu = cm->new_fb_idx; -#endif /*Check to make sure at least one of frames that this frame references *has valid dimensions. @@ -1513,8 +1501,7 @@ static void timeout_process(struct VP9Decoder_s *pbi) static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi) { - return (pbi->m_ins_flag && - ((double_write_mode & 0x80000000) == 0)) ? + return ((double_write_mode & 0x80000000) == 0) ? pbi->double_write_mode : (double_write_mode & 0x7fffffff); } @@ -1575,8 +1562,8 @@ static int get_double_write_ratio(struct VP9Decoder_s *pbi, return ratio; } -#define MAX_4K_NUM 0x1200 -#ifdef VP9_10B_MMU +//#define MAX_4K_NUM 0x1200 + int vp9_alloc_mmu( struct VP9Decoder_s *pbi, int cur_buf_idx, @@ -1587,11 +1574,13 @@ int vp9_alloc_mmu( { int bit_depth_10 = (bit_depth == VPX_BITS_10); int picture_size; - int cur_mmu_4k_number; + int cur_mmu_4k_number, max_frame_num; if (!pbi->mmu_box) { pr_err("error no mmu box!\n"); return -1; } + if (pbi->double_write_mode & 0x10) + return 0; if (bit_depth >= VPX_BITS_12) { pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW; pr_err("fatal_error, un support bit depth 12!\n\n"); @@ -1600,7 +1589,13 @@ int vp9_alloc_mmu( picture_size = compute_losless_comp_body_size(pic_width, pic_height, bit_depth_10); cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - if (cur_mmu_4k_number > MAX_4K_NUM) { + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + + if (cur_mmu_4k_number > max_frame_num) { pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", cur_mmu_4k_number, pic_width, pic_height); return -1; @@ -1611,7 +1606,7 @@ int vp9_alloc_mmu( cur_mmu_4k_number, mmu_index_adr); } -#endif + #ifndef MV_USE_FIXED_BUF static void dealloc_mv_bufs(struct VP9Decoder_s *pbi) @@ -2185,6 +2180,7 @@ static void refresh_ref_frames(struct VP9Decoder_s *pbi) unlock_buffer_pool(pool, flags); return; } + int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) { struct VP9_Common_s *const cm = &pbi->common; @@ -2202,16 +2198,16 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) } pbi->has_keyframe = 1; on_no_keyframe_skiped = 0; -/* -#ifdef VP9_10B_MMU - if (!pbi->m_ins_flag) - pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - if (cm->prev_fb_idx >= 0) { - decoder_mmu_box_free_idx_tail(pbi->mmu_box, - cm->prev_fb_idx, pbi->used_4k_num); +#if 0 + if (pbi->mmu_enable) { + if (!pbi->m_ins_flag) + pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + if (cm->prev_fb_idx >= 0) { + decoder_mmu_box_free_idx_tail(pbi->mmu_box, + cm->prev_fb_idx, pbi->used_4k_num); + } } #endif -*/ if (cm->new_fb_idx >= 0 && frame_bufs[cm->new_fb_idx].ref_count == 0){ vp9_release_frame_buffer @@ -2254,12 +2250,13 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) cm->new_fb_idx);*/ pbi->cur_buf = &frame_bufs[cm->new_fb_idx]; -#ifdef VP9_10B_MMU - /* moved to after picture size ready - alloc_mmu(cm, params->p.width, params->p.height, - params->p.bit_depth, pbi->frame_mmu_map_addr);*/ - cm->prev_fb_idx = cm->new_fb_idx; -#endif + if (pbi->mmu_enable) { + /* moved to after picture size ready + *alloc_mmu(cm, params->p.width, params->p.height, + *params->p.bit_depth, pbi->frame_mmu_map_addr); + */ + cm->prev_fb_idx = cm->new_fb_idx; + } /*read_uncompressed_header()*/ cm->last_frame_type = cm->frame_type; cm->last_intra_only = cm->intra_only; @@ -2570,10 +2567,8 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, spin_lock_init(&cm->buffer_pool->lock); cm->prev_fb_idx = INVALID_IDX; cm->new_fb_idx = INVALID_IDX; -#ifdef VP9_10B_MMU pbi->used_4k_num = -1; cm->cur_fb_idx_mmu = INVALID_IDX; -#endif pr_debug ("After vp9_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n", cm->prev_fb_idx, cm->new_fb_idx); @@ -2586,9 +2581,9 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, /* private init */ pbi->work_space_buf = buf_spec_i; -#ifndef VP9_10B_MMU - pbi->mc_buf = mc_buf_i; -#endif + if (!pbi->mmu_enable) + pbi->mc_buf = mc_buf_i; + pbi->rpm_addr = NULL; pbi->lmem_addr = NULL; @@ -2673,8 +2668,11 @@ union param_u vp9_param; #define LOSLESS_COMPRESS_MODE /*#define DECOMP_HEADR_SURGENT*/ - +#ifdef VP9_10B_NV21 +static u32 mem_map_mode = 2 /* 0:linear 1:32x32 2:64x32*/ +#else static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ +#endif static u32 enable_mem_saving = 1; static u32 force_w_h; @@ -2699,18 +2697,11 @@ static u32 decode_pic_begin; static uint slice_parse_begin; static u32 step; #ifdef MIX_STREAM_SUPPORT -#ifdef SUPPORT_4K2K static u32 buf_alloc_width = 4096; static u32 buf_alloc_height = 2304; static u32 vp9_max_pic_w = 4096; static u32 vp9_max_pic_h = 2304; -#else -static u32 buf_alloc_width = 1920; -static u32 buf_alloc_height = 1088; -static u32 vp9_max_pic_w = 1920; -static u32 vp9_max_pic_h = 1088; -#endif static u32 dynamic_buf_num_margin; #else static u32 buf_alloc_width; @@ -2771,11 +2762,14 @@ static u32 max_decoding_time; static u32 error_handle_policy; /*static u32 parser_sei_enable = 1;*/ - -static u32 max_buf_num = 10; +#define MAX_BUF_NUM_NORMAL 12 +#define MAX_BUF_NUM_LESS 10 +static u32 max_buf_num = MAX_BUF_NUM_NORMAL; +#define MAX_BUF_NUM_SAVE_BUF 8 static u32 run_ready_min_buf_num = 2; + static DEFINE_MUTEX(vvp9_mutex); #ifndef MULTI_INSTANCE_SUPPORT static struct device *cma_dev; @@ -2841,7 +2835,7 @@ static struct device *cma_dev; #endif #define LMEM_BUF_SIZE (0x400 * 2) -#define WORK_BUF_SPEC_NUM 2 +#define WORK_BUF_SPEC_NUM 3 static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { { /* 8M bytes */ @@ -2918,7 +2912,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { /*4096x2304/64/64 *24 = 0xd800 Bytes*/ .buf_size = 0xd800, }, -#ifdef VP9_10B_MMU .mmu_vbh = { .buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/ }, @@ -2929,7 +2922,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { (FRAME_BUFFERS + 1), /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ }, -#endif #endif .mpred_above = { .buf_size = 0x10000, /* 2 * size of hevc*/ @@ -3020,7 +3012,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { /*4096x2304/64/64 *24 = 0xd800 Bytes*/ .buf_size = 0xd800, }, -#ifdef VP9_10B_MMU .mmu_vbh = { .buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/ }, @@ -3031,7 +3022,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { (FRAME_BUFFERS + 1), /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ }, -#endif #endif .mpred_above = { .buf_size = 0x10000, /* 2 * size of hevc*/ @@ -3044,6 +3034,83 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { /* 4096x2304 , 0x120000 per buffer */ .buf_size = 0x120000 * FRAME_BUFFERS, }, +#endif + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x400 * 2, + } + }, + { + .max_width = 4096*2, + .max_height = 2304*2, + .ipp = { + // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k + .buf_size = 0x4000*2, + }, + .sao_abv = { + .buf_size = 0x30000*2, + }, + .sao_vb = { + .buf_size = 0x30000*2, + }, + .short_term_rps = { + // SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800) + .buf_size = 0x800, + }, + .vps = { + // VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .sps = { + // SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .pps = { + // PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes + .buf_size = 0x2000, + }, + .sao_up = { + // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes + .buf_size = 0x2800*2, + }, + .swap_buf = { + // 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid) + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) + .buf_size = 0x8000*2, + }, + .dblk_para = { + // DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000) + .buf_size = 0x80000*2, + }, + .dblk_data = { + .buf_size = 0x80000*2, + }, + .mmu_vbh = { + .buf_size = 0x5000*2, //2*16*(more than 2304)/4, 4K + }, +#if 0 + .cm_header = { + //.buf_size = MMU_COMPRESS_HEADER_SIZE*8, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) + .buf_size = MMU_COMPRESS_HEADER_SIZE*16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) + }, +#endif + .mpred_above = { + .buf_size = 0x10000*2, /* 2 * size of hevc*/ + }, +#ifdef MV_USE_FIXED_BUF + .mpred_mv = { + //4k2k , 0x100000 per buffer */ + /* 4096x2304 , 0x120000 per buffer */ + .buf_size = 0x120000 * FRAME_BUFFERS * 4, + }, #endif .rpm = { .buf_size = RPM_BUF_SIZE, @@ -3067,11 +3134,7 @@ int compute_losless_comp_body_size(int width, int height, width_x64 >>= 6; height_x32 = height + 31; height_x32 >>= 5; -#ifdef VP9_10B_MMU - bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32; -#else - bsize = (is_bit_depth_10?4096:3072)*width_x64*height_x32; -#endif + bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32; if (debug & VP9_DEBUG_BUFMGR_MORE) pr_info("%s(%d,%d,%d)=>%d\n", __func__, width, height, @@ -3135,15 +3198,17 @@ static void init_buff_spec(struct VP9Decoder_s *pbi, buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; buf_spec->seg_map.buf_start = buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; -#ifdef VP9_10B_MMU - buf_spec->mmu_vbh.buf_start = + if (pbi == NULL || pbi->mmu_enable) { + buf_spec->mmu_vbh.buf_start = + buf_spec->seg_map.buf_start + + buf_spec->seg_map.buf_size; + buf_spec->mpred_above.buf_start = + buf_spec->mmu_vbh.buf_start + + buf_spec->mmu_vbh.buf_size; + } else { + buf_spec->mpred_above.buf_start = buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; - buf_spec->mpred_above.buf_start = - buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; -#else - buf_spec->mpred_above.buf_start = - buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; -#endif + } #ifdef MV_USE_FIXED_BUF buf_spec->mpred_mv.buf_start = buf_spec->mpred_above.buf_start + @@ -3165,24 +3230,43 @@ static void init_buff_spec(struct VP9Decoder_s *pbi, buf_spec->lmem.buf_start + buf_spec->lmem.buf_size; - if (pbi) { + if (!pbi) + return; + + if (!vdec_secure(hw_to_vdec(pbi))) { mem_start_virt = codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start); if (mem_start_virt) { - memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size); + memset(mem_start_virt, 0, + buf_spec->dblk_para.buf_size); codec_mm_dma_flush(mem_start_virt, buf_spec->dblk_para.buf_size, DMA_TO_DEVICE); } else { - /*not virt for tvp playing, - may need clear on ucode.*/ - pr_err("mem_start_virt failed\n"); + mem_start_virt = codec_mm_vmap( + buf_spec->dblk_para.buf_start, + buf_spec->dblk_para.buf_size); + if (mem_start_virt) { + memset(mem_start_virt, 0, + buf_spec->dblk_para.buf_size); + codec_mm_dma_flush(mem_start_virt, + buf_spec->dblk_para.buf_size, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(mem_start_virt); + } else { + /*not virt for tvp playing, + may need clear on ucode.*/ + pr_err("mem_start_virt failed\n"); + } } - if (debug) { - pr_info("%s workspace (%x %x) size = %x\n", __func__, - buf_spec->start_adr, buf_spec->end_adr, + } + + if (debug) { + pr_info("%s workspace (%x %x) size = %x\n", __func__, + buf_spec->start_adr, buf_spec->end_adr, buf_spec->end_adr - buf_spec->start_adr); } + if (debug) { pr_info("ipp.buf_start :%x\n", buf_spec->ipp.buf_start); @@ -3212,23 +3296,21 @@ static void init_buff_spec(struct VP9Decoder_s *pbi, buf_spec->dblk_data.buf_start); pr_info("seg_map.buf_start :%x\n", buf_spec->seg_map.buf_start); - #ifdef VP9_10B_MMU - pr_info("mmu_vbh.buf_start :%x\n", - buf_spec->mmu_vbh.buf_start); - #endif - pr_info("mpred_above.buf_start :%x\n", - buf_spec->mpred_above.buf_start); + if (pbi->mmu_enable) { + pr_info("mmu_vbh.buf_start :%x\n", + buf_spec->mmu_vbh.buf_start); + } + pr_info("mpred_above.buf_start :%x\n", + buf_spec->mpred_above.buf_start); #ifdef MV_USE_FIXED_BUF - pr_info("mpred_mv.buf_start :%x\n", - buf_spec->mpred_mv.buf_start); + pr_info("mpred_mv.buf_start :%x\n", + buf_spec->mpred_mv.buf_start); #endif - if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { - pr_info("rpm.buf_start :%x\n", - buf_spec->rpm.buf_start); - } + if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { + pr_info("rpm.buf_start :%x\n", + buf_spec->rpm.buf_start); } } - } /* cache_util.c */ @@ -4420,7 +4502,8 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) #ifndef MV_USE_FIXED_BUF dealloc_mv_bufs(pbi); #endif - decoder_mmu_box_free(pbi->mmu_box); + if (pbi->mmu_box) + decoder_mmu_box_free(pbi->mmu_box); pbi->mmu_box = NULL; if (pbi->bmmu_box) @@ -4428,121 +4511,6 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) pbi->bmmu_box = NULL; } -#ifndef VP9_10B_MMU -static void init_buf_list(struct VP9Decoder_s *pbi) -{ - int i; - int buf_size; -#ifndef VP9_10B_MMU - int mc_buffer_end = pbi->mc_buf->buf_start + pbi->mc_buf->buf_size; -#endif - pbi->used_buf_num = max_buf_num; - - if (pbi->used_buf_num > MAX_BUF_NUM) - pbi->used_buf_num = MAX_BUF_NUM; - if (buf_alloc_size > 0) { - buf_size = buf_alloc_size; - if (debug) - pr_info("[Buffer Management] init_buf_list:\n"); - } else { - int pic_width = pbi->init_pic_w; - int pic_height = pbi->init_pic_h; - - /*SUPPORT_10BIT*/ - int losless_comp_header_size = compute_losless_comp_header_size - (pic_width, pic_height); - int losless_comp_body_size = compute_losless_comp_body_size - (pic_width, pic_height, buf_alloc_depth == 10); - int mc_buffer_size = losless_comp_header_size - + losless_comp_body_size; - int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; - - int dw_mode = get_double_write_mode_init(pbi); - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(pbi, dw_mode); - int pic_height_dw = pic_height / - get_double_write_ratio(pbi, dw_mode); - int lcu_size = 64; /*fixed 64*/ - int pic_width_64 = (pic_width_dw + 63) & (~0x3f); - int pic_height_32 = (pic_height_dw + 31) & (~0x1f); - int pic_width_lcu = - (pic_width_64 % lcu_size) ? pic_width_64 / lcu_size - + 1 : pic_width_64 / lcu_size; - int pic_height_lcu = - (pic_height_32 % lcu_size) ? pic_height_32 / lcu_size - + 1 : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; - int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; - int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - buf_size = ((mc_buffer_size_u_v_h << 16) * 3); - } else - buf_size = 0; - - if (mc_buffer_size & 0xffff) { /*64k alignment*/ - mc_buffer_size_h += 1; - } - if ((dw_mode & 0x10) == 0) - buf_size += (mc_buffer_size_h << 16); - if (debug) { - pr_info - ("init_buf_list num %d (width %d height %d):\n", - pbi->used_buf_num, pic_width, pic_height); - } - } - - for (i = 0; i < pbi->used_buf_num; i++) { - if (((i + 1) * buf_size) > pbi->mc_buf->buf_size) - pbi->use_cma_flag = 1; -#ifndef VP9_10B_MMU - pbi->m_BUF[i].alloc_flag = 0; - pbi->m_BUF[i].index = i; - - pbi->use_cma_flag = 1; - if (pbi->use_cma_flag) { - pbi->m_BUF[i].cma_page_count = - PAGE_ALIGN(buf_size) / PAGE_SIZE; - if (decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, - VF_BUFFER_IDX(i), buf_size, DRIVER_NAME, - &pbi->m_BUF[i].alloc_addr) < 0) { - pbi->m_BUF[i].cma_page_count = 0; - if (i <= 5) { - pbi->fatal_error |= - DECODER_FATAL_ERROR_NO_MEM; - } - break; - } - pbi->m_BUF[i].start_adr = pbi->m_BUF[i].alloc_addr; - } else { - pbi->m_BUF[i].cma_page_count = 0; - pbi->m_BUF[i].alloc_addr = 0; - pbi->m_BUF[i].start_adr = - pbi->mc_buf->buf_start + i * buf_size; - } - pbi->m_BUF[i].size = buf_size; - pbi->m_BUF[i].free_start_adr = pbi->m_BUF[i].start_adr; - - if (((pbi->m_BUF[i].start_adr + buf_size) > mc_buffer_end) - && (pbi->m_BUF[i].alloc_addr == 0)) { - if (debug) { - pr_info - ("Max mc buffer or mpred_mv buffer is used\n"); - } - break; - } - - if (debug) { - pr_info("Buffer %d: start_adr %p size %x\n", i, - (void *)pbi->m_BUF[i].start_adr, - pbi->m_BUF[i].size); - } -#endif - } - pbi->buf_num = i; -} -#endif static int config_pic(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) @@ -4605,20 +4573,19 @@ static int config_pic(struct VP9Decoder_s *pbi, if (mc_buffer_size & 0xffff) /*64k alignment*/ mc_buffer_size_h += 1; -#ifndef VP9_10B_MMU - if ((dw_mode & 0x10) == 0) + if ((!pbi->mmu_enable) && ((dw_mode & 0x10) == 0)) buf_size += (mc_buffer_size_h << 16); -#endif -#ifdef VP9_10B_MMU - pic_config->header_adr = decoder_bmmu_box_get_phy_addr( + + if (pbi->mmu_enable) { + pic_config->header_adr = decoder_bmmu_box_get_phy_addr( pbi->bmmu_box, HEADER_BUFFER_IDX(pic_config->index)); - if (debug & VP9_DEBUG_BUFMGR_MORE) { - pr_info("MMU header_adr %d: %ld\n", - pic_config->index, pic_config->header_adr); + if (debug & VP9_DEBUG_BUFMGR_MORE) { + pr_info("MMU header_adr %d: %ld\n", + pic_config->index, pic_config->header_adr); + } } -#endif i = pic_config->index; #ifdef MV_USE_FIXED_BUF @@ -4627,31 +4594,7 @@ static int config_pic(struct VP9Decoder_s *pbi, <= mpred_mv_end ) { #endif -#ifndef VP9_10B_MMU - if (debug) { - pr_err("start %x .size=%d\n", - pbi->mc_buf_spec.buf_start + i * buf_size, - buf_size); - } -#endif -#ifndef VP9_10B_MMU - for (i = 0; i < pbi->buf_num; i++) { - y_adr = ((pbi->m_BUF[i].free_start_adr - + 0xffff) >> 16) << 16; - /*64k alignment*/ - if ((y_adr+buf_size) <= (pbi->m_BUF[i].start_adr+ - pbi->m_BUF[i].size)) { - pbi->m_BUF[i].free_start_adr = - y_adr + buf_size; - break; - } - } - if (i < pbi->buf_num) -#else - /*if ((pbi->mc_buf->buf_start + (i + 1) * buf_size) < - pbi->mc_buf->buf_end) - y_adr = pbi->mc_buf->buf_start + i * buf_size; - else {*/ + if (buf_size > 0) { ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, VF_BUFFER_IDX(i), @@ -4677,7 +4620,6 @@ static int config_pic(struct VP9Decoder_s *pbi, return -1; } } -#endif { /*ensure get_pic_by_POC() not get the buffer not decoded*/ @@ -4686,37 +4628,22 @@ static int config_pic(struct VP9Decoder_s *pbi, pic_config->comp_body_size = losless_comp_body_size; pic_config->buf_size = buf_size; -#ifndef VP9_10B_MMU - pic_config->mc_y_adr = y_adr; -#endif + pic_config->mc_canvas_y = pic_config->index; pic_config->mc_canvas_u_v = pic_config->index; -#ifndef VP9_10B_MMU if (dw_mode & 0x10) { - pic_config->mc_u_v_adr = y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); pic_config->mc_canvas_y = (pic_config->index << 1); pic_config->mc_canvas_u_v = (pic_config->index << 1) + 1; - + } else if (dw_mode) { pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = pic_config->mc_u_v_adr; - } else -#endif - if (dw_mode) { - pic_config->dw_y_adr = y_adr -#ifndef VP9_10B_MMU - + (mc_buffer_size_h << 16) -#endif - ; pic_config->dw_u_v_adr = pic_config->dw_y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); -#ifdef VP9_10B_MMU - pic_config->mc_y_adr = pic_config->dw_y_adr; - pic_config->mc_u_v_adr = pic_config->dw_u_v_adr; -#endif + ((mc_buffer_size_u_v_h << 16) << 1); } #ifdef MV_USE_FIXED_BUF pic_config->mpred_mv_wr_start_addr = @@ -4726,10 +4653,9 @@ static int config_pic(struct VP9Decoder_s *pbi, #endif if (debug) { pr_info - ("%s index %d BUF_index %d mc_y_adr %lx ", + ("%s index %d BUF_index %d ", __func__, pic_config->index, - pic_config->BUF_index, - pic_config->mc_y_adr); + pic_config->BUF_index); pr_info ("comp_body_size %x comp_buf_size %x ", pic_config->comp_body_size, @@ -4749,32 +4675,73 @@ static int config_pic(struct VP9Decoder_s *pbi, return ret; } +static int is_oversize(int w, int h) +{ + int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? + MAX_SIZE_8K : MAX_SIZE_4K; + + if (w < 0 || h < 0) + return true; + + if (h != 0 && (w > max / h)) + return true; + + return false; +} + +static int vvp9_mmu_compress_header_size(struct VP9Decoder_s *pbi) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h)) + return (MMU_COMPRESS_8K_HEADER_SIZE); + + return (MMU_COMPRESS_HEADER_SIZE); +} + +/*#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)*/ +static int vvp9_frame_mmu_map_size(struct VP9Decoder_s *pbi) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h)) + return (MAX_FRAME_8K_NUM * 4); + + return (MAX_FRAME_4K_NUM * 4); +} + + static void init_pic_list(struct VP9Decoder_s *pbi) { int i; struct VP9_Common_s *cm = &pbi->common; struct PIC_BUFFER_CONFIG_s *pic_config; -#ifdef VP9_10B_MMU - /*alloc VP9 compress header first*/ - for (i = 0; i < pbi->used_buf_num; i++) { - unsigned long buf_addr; - if (decoder_bmmu_box_alloc_buf_phy + u32 header_size; + struct vdec_s *vdec = hw_to_vdec(pbi); + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + header_size = vvp9_mmu_compress_header_size(pbi); + /*alloc VP9 compress header first*/ + for (i = 0; i < pbi->used_buf_num; i++) { + unsigned long buf_addr; + if (decoder_bmmu_box_alloc_buf_phy (pbi->bmmu_box, - HEADER_BUFFER_IDX(i), MMU_COMPRESS_HEADER_SIZE, + HEADER_BUFFER_IDX(i), header_size, DRIVER_HEADER_NAME, - &buf_addr) < 0){ - pr_info("%s malloc compress header failed %d\n", + &buf_addr) < 0) { + pr_info("%s malloc compress header failed %d\n", DRIVER_HEADER_NAME, i); - pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; - return; + pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; + return; + } } } -#endif for (i = 0; i < pbi->used_buf_num; i++) { pic_config = &cm->buffer_pool->frame_bufs[i].buf; pic_config->index = i; pic_config->BUF_index = -1; pic_config->mv_buf_index = -1; + if (vdec->parallel_dec == 1) { + pic_config->y_canvas_index = -1; + pic_config->uv_canvas_index = -1; + } if (config_pic(pbi, pic_config) < 0) { if (debug) pr_info("Config_pic %d fail\n", @@ -4784,20 +4751,26 @@ static void init_pic_list(struct VP9Decoder_s *pbi) } pic_config->y_crop_width = pbi->init_pic_w; pic_config->y_crop_height = pbi->init_pic_h; - /*set_canvas(pic_config);*/ + pic_config->double_write_mode = get_double_write_mode(pbi); + if (pic_config->double_write_mode) { + set_canvas(pbi, pic_config); + } } for (; i < pbi->used_buf_num; i++) { pic_config = &cm->buffer_pool->frame_bufs[i].buf; pic_config->index = -1; pic_config->BUF_index = -1; pic_config->mv_buf_index = -1; + if (vdec->parallel_dec == 1) { + pic_config->y_canvas_index = -1; + pic_config->uv_canvas_index = -1; + } } pr_info("%s ok, used_buf_num = %d\n", __func__, pbi->used_buf_num); } - static void init_pic_list_hw(struct VP9Decoder_s *pbi) { int i; @@ -4813,24 +4786,31 @@ static void init_pic_list_hw(struct VP9Decoder_s *pbi) if (pic_config->index < 0) break; -#ifdef VP9_10B_MMU - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic_config->header_adr - | (pic_config->mc_canvas_y << 8)|0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->header_adr >> 5); -#else - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic_config->mc_y_adr - | (pic_config->mc_canvas_y << 8) | 0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_y_adr >> 5); -#endif -#ifndef LOSLESS_COMPRESS_MODE - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic_config->mc_u_v_adr - | (pic_config->mc_canvas_u_v << 8)| 0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_u_v_adr >> 5); -#endif + if (pbi->mmu_enable && ((pic_config->double_write_mode & 0x10) == 0)) { + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->header_adr >> 5); + } else { + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + * pic_config->mc_y_adr + * | (pic_config->mc_canvas_y << 8) | 0x1); + */ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->dw_y_adr >> 5); + } +#ifndef LOSLESS_COMPRESS_MODE + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + * pic_config->mc_u_v_adr + * | (pic_config->mc_canvas_u_v << 8)| 0x1); + */ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->header_adr >> 5); +#else + if (pic_config->double_write_mode & 0x10) { + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->dw_u_v_adr >> 5); + } +#endif } WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); @@ -4900,21 +4880,24 @@ static int config_pic_size(struct VP9Decoder_s *pbi, unsigned short bit_depth) WRITE_VREG(HEVC_SAO_CTRL5, data32); -#ifdef VP9_10B_MMU - /*bit[4] : paged_mem_mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); -#else + if (pbi->mmu_enable) { + /*bit[4] : paged_mem_mode*/ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); + } else { /*bit[3] smem mdoe*/ - if (bit_depth == VPX_BITS_10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); - else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); -#endif - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); + if (bit_depth == VPX_BITS_10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); + else + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); + } + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + if (get_double_write_mode(pbi) & 0x10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #else WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #endif @@ -4982,11 +4965,10 @@ static int config_mc_buffer(struct VP9Decoder_s *pbi, unsigned short bit_depth) WRITE_VREG(VP9D_MPP_REFINFO_DATA, (pic_config->y_crop_height << 14) / cur_pic_config->y_crop_height); -#ifdef VP9_10B_MMU - WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0); -#else - WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5); -#endif + if (pbi->mmu_enable) + WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0); + else + WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5); } WRITE_VREG(VP9D_MPP_REF_SCALE_ENBL, scale_enable); return 0; @@ -5061,10 +5043,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ -#ifndef VP9_10B_MMU - if ((get_double_write_mode(pbi) & 0x10) == 0) - WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic_config->mc_y_adr); -#endif + if (get_double_write_mode(pbi)) { WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr); WRITE_VREG(HEVC_SAO_C_START_ADDR, pic_config->dw_u_v_adr); @@ -5074,9 +5053,9 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); } -#ifdef VP9_10B_MMU - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr); -#endif + if (pbi->mmu_enable) + WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr); + data32 = (mc_buffer_size_u_v_h << 16) << 1; /*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n", * data32, mc_buffer_size_u_v_h, pic_config->lcu_total); @@ -5091,7 +5070,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (MEM_MAP_MODE << 12); + data32 |= (mem_map_mode << 12); data32 &= (~0x3); data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/ WRITE_VREG(HEVC_SAO_CTRL1, data32); @@ -5105,14 +5084,14 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (MEM_MAP_MODE << 4); + data32 |= (mem_map_mode << 4); WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); #else /*m8baby test1902*/ data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (MEM_MAP_MODE << 12); + data32 |= (mem_map_mode << 12); data32 &= (~0xff0); /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/ data32 |= 0x880; /*.Big-Endian per 64-bit */ @@ -5130,7 +5109,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (MEM_MAP_MODE << 4); + data32 |= (mem_map_mode << 4); data32 &= (~0xF); data32 |= 0x8; /*Big-Endian per 64-bit*/ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); @@ -5138,7 +5117,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) #else data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); - data32 |= (MEM_MAP_MODE << + data32 |= (mem_map_mode << 12); /* [13:12] axi_aformat, 0-Linear, @@ -5147,22 +5126,19 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 &= (~0xff0); /* data32 |= 0x670; // Big-Endian per 64-bit */ data32 |= endian; /* Big-Endian per 64-bit */ - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ if (get_double_write_mode(pbi) == 0) data32 |= 0x2; /*disable double write*/ -#ifndef VP9_10B_MMU - else - if (get_double_write_mode(pbi) & 0x10) + else if (get_double_write_mode(pbi) & 0x10) data32 |= 0x1; /*disable cm*/ -#endif } else { /* >= G12A dw write control */ unsigned int data; data = READ_VREG(HEVC_DBLK_CFGB); data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ if (get_double_write_mode(pbi) == 0) data |= (0x1 << 8); /*enable first write*/ - else if (get_double_write_mode(pbi) == 0x10) + else if (get_double_write_mode(pbi) & 0x10) data |= (0x1 << 9); /*double write only*/ else data |= ((0x1 << 8) |(0x1 << 9)); @@ -5206,9 +5182,8 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) { struct BuffInfo_s *buf_spec = pbi->work_space_buf; -#ifdef VP9_10B_MMU unsigned int data32; -#endif + if (debug && pbi->init_flag == 0) pr_info("%s %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__, @@ -5255,24 +5230,33 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) buf_spec->ipp.buf_start); WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { /* cfg_addr_adp*/ WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_para.buf_start); if (debug & VP9_DEBUG_BUFMGR_MORE) pr_info("Write HEVC_DBLK_CFGE\n"); - } else { - /* cfg_p_addr */ - WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); } + /* cfg_p_addr */ + WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); /* cfg_d_addr */ WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + /* + * data32 = (READ_VREG(P_HEVC_DBLK_CFG3)>>8) & 0xff; // xio left offset, default is 0x40 + * data32 = data32 * 2; + * data32 = (READ_VREG(P_HEVC_DBLK_CFG3)>>16) & 0xff; // adp left offset, default is 0x040 + * data32 = data32 * 2; + */ + WRITE_VREG(HEVC_DBLK_CFG3, 0x808010); // make left storage 2 x 4k] + } #ifdef LOSLESS_COMPRESS_MODE -#ifdef VP9_10B_MMU + if (pbi->mmu_enable) { /*bit[4] : paged_mem_mode*/ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); -#else + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); + } else { /*if(cur_pic_config->bit_depth == VPX_BITS_10) * WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (0<<3)); */ @@ -5281,20 +5265,22 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) /*bit[3] smem mdoe*/ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); -#endif - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, - (losless_comp_body_size >> 5));*/ - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, - (0xff<<20) | (0xff<<10) | 0xff);*/ - /*8-bit mode */ - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + } + /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, + (losless_comp_body_size >> 5));*/ + /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, + (0xff<<20) | (0xff<<10) | 0xff);*/ + /*8-bit mode */ + WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + if (get_double_write_mode(pbi) & 0x10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #else WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #endif -#ifdef VP9_10B_MMU + if (pbi->mmu_enable) { WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size/2); @@ -5306,20 +5292,21 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) data32 = READ_VREG(HEVC_SAO_CTRL5); data32 |= (1<<10); WRITE_VREG(HEVC_SAO_CTRL5, data32); -#endif + } + WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start); + WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr); /**/ WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr); WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr); -#ifdef VP9_10B_MMU - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr); - else - WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr); -#endif + if (pbi->mmu_enable) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr); + else + WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr); + } } - } @@ -5453,6 +5440,7 @@ void vp9_loop_filter_init(struct VP9Decoder_s *pbi) struct loopfilter *lf = pbi->lf; struct segmentation *seg_4lf = pbi->seg_4lf; int i; + unsigned int data32; memset(lfi, 0, sizeof(struct loop_filter_info_n)); memset(lf, 0, sizeof(struct loopfilter)); @@ -5478,16 +5466,21 @@ void vp9_loop_filter_init(struct VP9Decoder_s *pbi) } /*video format is VP9*/ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - unsigned int data32; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + data32 = (0x3 << 14) | // (dw fifo thres r and b) + (0x3 << 12) | // (dw fifo thres r or b) + (0x3 << 10) | // (dw fifo thres not r/b) + (0x3 << 8) | // 1st/2nd write both enable + (0x1 << 0); // vp9 video format + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { data32 = (0x57 << 8) | /*1st/2nd write both enable*/ - (0x1 << 0); /*vp9 video format*/ - WRITE_VREG(HEVC_DBLK_CFGB, data32); - - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("[DBLK DEBUG] CFGB : 0x%x\n", data32); + (0x1 << 0); /*vp9 video format*/ } else - WRITE_VREG(HEVC_DBLK_CFGB, 0x40400001); + data32 = 0x40400001; + + WRITE_VREG(HEVC_DBLK_CFGB, data32); + if (debug & VP9_DEBUG_BUFMGR_MORE) + pr_info("[DBLK DEBUG] CFGB : 0x%x\n", data32); } /* perform this function per frame*/ void vp9_loop_filter_frame_init(struct segmentation *seg, @@ -5613,7 +5606,7 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi, u32 mask) 0x7C00 }; #if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { /* Set MCR fetch priorities*/ data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); @@ -5747,10 +5740,10 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi, u32 mask) (1 << 1) | /*enable ipp*/ (0 << 0) /*software reset ipp and mpp*/ ); -#ifdef VP9_10B_NV21 + if (get_double_write_mode(pbi) & 0x10) { /*Enable NV21 reference read mode for MC*/ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif + } /*Initialize mcrcc and decomp perf counters*/ if (mcrcc_cache_alg_flag && @@ -5833,11 +5826,11 @@ static void config_mcrcc_axi_hw(struct VP9Decoder_s *pbi) return; } -#if 0 - mcrcc_get_hitrate(); - decomp_get_hitrate(); - decomp_get_comprate(); -#endif + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + mcrcc_get_hitrate(pbi->m_ins_flag); + decomp_get_hitrate(); + decomp_get_comprate(); + } WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (1 << 1) | 0); @@ -6082,15 +6075,17 @@ static void vp9_local_uninit(struct VP9Decoder_s *pbi) pbi->count_buffer_addr = NULL; } -#ifdef VP9_10B_MMU - if (pbi->frame_mmu_map_addr) { - if (pbi->frame_mmu_map_phy_addr) - dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, pbi->frame_mmu_map_addr, + if (pbi->mmu_enable) { + u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi); + if (pbi->frame_mmu_map_addr) { + if (pbi->frame_mmu_map_phy_addr) + dma_free_coherent(amports_get_dma_device(), + mmu_map_size, + pbi->frame_mmu_map_addr, pbi->frame_mmu_map_phy_addr); - pbi->frame_mmu_map_addr = NULL; + pbi->frame_mmu_map_addr = NULL; + } } -#endif #ifdef SUPPORT_FB_DECODING if (pbi->stage_mmu_map_addr) { if (pbi->stage_mmu_map_phy_addr) @@ -6112,9 +6107,6 @@ static void vp9_local_uninit(struct VP9Decoder_s *pbi) pbi->gvs = NULL; } - - - static int vp9_local_init(struct VP9Decoder_s *pbi) { int ret = -1; @@ -6126,49 +6118,36 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) memset(&pbi->common, 0, sizeof(struct VP9_Common_s)); #ifdef MULTI_INSTANCE_SUPPORT cur_buf_info = &pbi->work_space_buf_store; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - memcpy(cur_buf_info, &amvvp9_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + memcpy(cur_buf_info, &amvvp9_workbuff_spec[2], /* 8k */ + sizeof(struct BuffInfo_s)); + } else + memcpy(cur_buf_info, &amvvp9_workbuff_spec[1], /* 4k */ + sizeof(struct BuffInfo_s)); + } else memcpy(cur_buf_info, &amvvp9_workbuff_spec[0],/* 1080p */ sizeof(struct BuffInfo_s)); -#else - memcpy(cur_buf_info, &amvvp9_workbuff_spec[0], /* 1080p work space */ - sizeof(struct BuffInfo_s)); -#endif + cur_buf_info->start_adr = pbi->buf_start; -#ifndef VP9_10B_MMU - pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size; -#endif + if (!pbi->mmu_enable) + pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size; + #else /*! MULTI_INSTANCE_SUPPORT*/ -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - cur_buf_info = &amvvp9_workbuff_spec[1];/* 4k2k work space */ - else + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + cur_buf_info = &amvvp9_workbuff_spec[2];/* 8k work space */ + else + cur_buf_info = &amvvp9_workbuff_spec[1];/* 4k2k work space */ + } else cur_buf_info = &amvvp9_workbuff_spec[0];/* 1080p work space */ -#else - cur_buf_info = &amvvp9_workbuff_spec[0]; /* 1080p work space */ -#endif + #endif init_buff_spec(pbi, cur_buf_info); -#ifdef VP9_10B_MMU vp9_bufmgr_init(pbi, cur_buf_info, NULL); -#else - pbi->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff) - & (~0xffff); - pbi->mc_buf_spec.buf_size = (pbi->mc_buf_spec.buf_end - - pbi->mc_buf_spec.buf_start); - if (debug) { - pr_err("pbi->mc_buf_spec.buf_start %x-%x\n", - pbi->mc_buf_spec.buf_start, - pbi->mc_buf_spec.buf_start + - pbi->mc_buf_spec.buf_size); - } - vp9_bufmgr_init(pbi, cur_buf_info, &pbi->mc_buf_spec); -#endif if (!vdec_is_support_4k() && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { @@ -6178,6 +6157,9 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) pbi->max_pic_w = 1920; pbi->max_pic_h = 1088; } + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + buf_alloc_width = 8192; + buf_alloc_height = 4608; } pbi->init_pic_w = pbi->max_pic_w ? pbi->max_pic_w : (buf_alloc_width ? buf_alloc_width : @@ -6189,6 +6171,13 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) (pbi->vvp9_amstream_dec_info.height ? pbi->vvp9_amstream_dec_info.height : pbi->work_space_buf->max_height)); + + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (pbi->double_write_mode != 0) && + (((pbi->max_pic_w % 64) != 0) || + (pbi->vvp9_amstream_dec_info.width % 64) != 0)) + mem_map_mode = 2; + #ifndef MV_USE_FIXED_BUF if (init_mv_buf_list(pbi) < 0) { pr_err("%s: init_mv_buf_list fail\n", __func__); @@ -6196,15 +6185,16 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) } #endif -#ifndef VP9_10B_MMU - init_buf_list(pbi); -#else - pbi->used_buf_num = max_buf_num; + if (pbi->save_buffer_mode) + pbi->used_buf_num = MAX_BUF_NUM_SAVE_BUF; + else + pbi->used_buf_num = max_buf_num; + if (pbi->used_buf_num > MAX_BUF_NUM) pbi->used_buf_num = MAX_BUF_NUM; if (pbi->used_buf_num > FRAME_BUFFERS) pbi->used_buf_num = FRAME_BUFFERS; -#endif + init_pic_list(pbi); pbi->pts_unstable = ((unsigned long)(pbi->vvp9_amstream_dec_info.param) @@ -6286,26 +6276,27 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) return -1; } */ -#ifdef VP9_10B_MMU - pbi->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, + if (pbi->mmu_enable) { + u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi); + pbi->frame_mmu_map_addr = + dma_alloc_coherent(amports_get_dma_device(), + mmu_map_size, &pbi->frame_mmu_map_phy_addr, GFP_KERNEL); - if (pbi->frame_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; + if (pbi->frame_mmu_map_addr == NULL) { + pr_err("%s: failed to alloc count_buffer\n", __func__); + return -1; + } + memset(pbi->frame_mmu_map_addr, 0, COUNT_BUF_SIZE); + /* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->frame_mmu_map_addr, mmu_map_size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + pbi->frame_mmu_map_phy_addr)) { + pr_err("%s: failed to map count_buffer\n", __func__); + kfree(pbi->frame_mmu_map_addr); + pbi->frame_mmu_map_addr = NULL; + return -1; + }*/ } - memset(pbi->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); -/* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), - pbi->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - pbi->frame_mmu_map_phy_addr)) { - pr_err("%s: failed to map count_buffer\n", __func__); - kfree(pbi->frame_mmu_map_addr); - pbi->frame_mmu_map_addr = NULL; - return -1; - }*/ -#endif - #ifdef SUPPORT_FB_DECODING if (pbi->m_ins_flag && stage_buf_num > 0) { pbi->stage_mmu_map_addr = @@ -6351,6 +6342,7 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) static void set_canvas(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) { + struct vdec_s *vdec = hw_to_vdec(pbi); int canvas_w = ALIGN(pic_config->y_crop_width, 64)/4; int canvas_h = ALIGN(pic_config->y_crop_height, 32)/4; int blkmode = mem_map_mode; @@ -6369,8 +6361,17 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_w = ALIGN(canvas_w, 64); canvas_h = ALIGN(canvas_h, 32); - pic_config->y_canvas_index = 128 + pic_config->index * 2; - pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic_config->y_canvas_index == -1) + pic_config->y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic_config->uv_canvas_index == -1) + pic_config->uv_canvas_index = + vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic_config->y_canvas_index = 128 + pic_config->index * 2; + pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1; + } canvas_config_ex(pic_config->y_canvas_index, pic_config->dw_y_adr, canvas_w, canvas_h, @@ -6378,6 +6379,7 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_config_ex(pic_config->uv_canvas_index, pic_config->dw_u_v_adr, canvas_w, canvas_h, CANVAS_ADDR_NOWRAP, blkmode, 0x7); + #ifdef MULTI_INSTANCE_SUPPORT pic_config->canvas_config[0].phy_addr = pic_config->dw_y_adr; @@ -6399,18 +6401,6 @@ static void set_canvas(struct VP9Decoder_s *pbi, blkmode; pic_config->canvas_config[1].endian = 7; #endif - } else { - #ifndef VP9_10B_MMU - pic_config->y_canvas_index = 128 + pic_config->index; - pic_config->uv_canvas_index = 128 + pic_config->index; - - canvas_config_ex(pic_config->y_canvas_index, - pic_config->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic_config->uv_canvas_index, - pic_config->mc_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - #endif } } @@ -6476,7 +6466,7 @@ static struct vframe_s *vvp9_vf_get(void *op_arg) if (kfifo_get(&pbi->display_q, &vf)) { struct vframe_s *next_vf; uint8_t index = vf->index & 0xff; - if (index >= 0 && index < pbi->used_buf_num) { + if (index < pbi->used_buf_num) { pbi->vf_get_count++; if (debug & VP9_DEBUG_BUFMGR) pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n", @@ -6504,8 +6494,7 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf); pbi->vf_put_count++; - if (index >= 0 - && index < pbi->used_buf_num) { + if (index < pbi->used_buf_num) { struct VP9_Common_s *cm = &pbi->common; struct BufferPool_s *pool = cm->buffer_pool; unsigned long flags; @@ -6630,7 +6619,31 @@ static int frame_duration_adapt(struct VP9Decoder_s *pbi, struct vframe_s *vf, u return true; } - +static void update_vf_memhandle(struct VP9Decoder_s *pbi, + struct vframe_s *vf, struct PIC_BUFFER_CONFIG_s *pic) +{ + if (pic->index < 0) { + vf->mem_handle = NULL; + vf->mem_head_handle = NULL; + } else if (vf->type & VIDTYPE_SCATTER) { + vf->mem_handle = + decoder_mmu_box_get_mem_handle( + pbi->mmu_box, pic->index); + vf->mem_head_handle = + decoder_bmmu_box_get_mem_handle( + pbi->bmmu_box, + HEADER_BUFFER_IDX(pic->BUF_index)); + } else { + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + pbi->bmmu_box, VF_BUFFER_IDX(pic->BUF_index)); + vf->mem_head_handle = NULL; + /*vf->mem_head_handle = + *decoder_bmmu_box_get_mem_handle( + *hevc->bmmu_box, VF_BUFFER_IDX(BUF_index)); + */ + } +} static int prepare_display_buf(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) { @@ -6640,6 +6653,7 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, u32 pts_valid = 0, pts_us64_valid = 0; u32 pts_save; u64 pts_us64_save; + u32 frame_size; if (debug & VP9_DEBUG_BUFMGR) pr_info("%s index = %d\r\n", __func__, pic_config->index); @@ -6670,8 +6684,9 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, * stream_offset, &vf->pts, 0) != 0) { */ if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, - &vf->pts_us64) != 0) { + (PTS_TYPE_VIDEO, stream_offset, &vf->pts, + &frame_size, 0, + &vf->pts_us64) != 0) { #ifdef DEBUG_PTS pbi->pts_missed++; #endif @@ -6768,25 +6783,27 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, vf->compBodyAddr = 0; vf->compHeadAddr = 0; } else { -#ifdef VP9_10B_MMU - vf->compBodyAddr = 0; - vf->compHeadAddr = pic_config->header_adr; -#else - vf->compBodyAddr = pic_config->mc_y_adr; /*body adr*/ - vf->compHeadAddr = pic_config->mc_y_adr + - pic_config->comp_body_size; - /*head adr*/ -#endif + if (pbi->mmu_enable) { + vf->compBodyAddr = 0; + vf->compHeadAddr = pic_config->header_adr; + } else { + /*vf->compBodyAddr = pic_config->mc_y_adr; + *vf->compHeadAddr = pic_config->mc_y_adr + + *pic_config->comp_body_size; */ + /*head adr*/ + } + vf->canvas0Addr = vf->canvas1Addr = 0; } if (pic_config->double_write_mode) { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; vf->type |= VIDTYPE_VIU_NV21; - if (pic_config->double_write_mode == 3) { + if ((pic_config->double_write_mode == 3) && + (!IS_8K_SIZE(pic_config->y_crop_width, + pic_config->y_crop_height))) { vf->type |= VIDTYPE_COMPRESS; -#ifdef VP9_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif + if (pbi->mmu_enable) + vf->type |= VIDTYPE_SCATTER; } #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) { @@ -6808,9 +6825,8 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, } else { vf->canvas0Addr = vf->canvas1Addr = 0; vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; -#ifdef VP9_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif + if (pbi->mmu_enable) + vf->type |= VIDTYPE_SCATTER; } switch (pic_config->bit_depth) { @@ -6861,39 +6877,22 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, else vf->duration = 0; } -#ifdef VP9_10B_MMU - if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = decoder_mmu_box_get_mem_handle( - pbi->mmu_box, - pic_config->index); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - HEADER_BUFFER_IDX(pic_config->index)); - } else { - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - VF_BUFFER_IDX(pic_config->index)); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - HEADER_BUFFER_IDX(pic_config->index)); - } -#else - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - VF_BUFFER_IDX(pic_config->index)); -#endif + update_vf_memhandle(pbi, vf, pic_config); if (!(pic_config->y_crop_width == 196 && pic_config->y_crop_height == 196 && (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0 )) { inc_vf_ref(pbi, pic_config->index); + decoder_do_frame_check(hw_to_vdec(pbi), vf); kfifo_put(&pbi->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); pbi->vf_pre_count++; #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC /*count info*/ gvs->frame_dur = pbi->frame_dur; vdec_count_info(gvs, 0, stream_offset); #endif + hw_to_vdec(pbi)->vdec_fps_detec(hw_to_vdec(pbi)->id); vf_notify_receiver(pbi->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } else { @@ -6998,10 +6997,12 @@ static void debug_buffer_mgr_more(struct VP9Decoder_s *pbi) } -#ifdef VP9_10B_MMU + static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; + if (pbi->double_write_mode & 0x10) + return; if (cm->cur_fb_idx_mmu != INVALID_IDX) { if (pbi->used_4k_num == -1) pbi->used_4k_num = @@ -7018,6 +7019,8 @@ static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi) static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; + if (pbi->double_write_mode & 0x10) + return; if (cm->cur_fb_idx_mmu != INVALID_IDX) { decoder_mmu_box_free_idx(pbi->mmu_box, cm->cur_fb_idx_mmu); @@ -7027,7 +7030,7 @@ static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi) } } #endif -#endif + static void dec_again_process(struct VP9Decoder_s *pbi) { @@ -7037,6 +7040,8 @@ static void dec_again_process(struct VP9Decoder_s *pbi) PROC_STATE_DECODESLICE) { pbi->process_state = PROC_STATE_SENDAGAIN; + if (pbi->mmu_enable) + vp9_recycle_mmu_buf(pbi); } reset_process_time(pbi); vdec_schedule_work(&pbi->work); @@ -7058,22 +7063,22 @@ int continue_decoding(struct VP9Decoder_s *pbi) pbi->slice_idx++; } else { union param_u *params = &vp9_param; -#ifdef VP9_10B_MMU - ret = vp9_alloc_mmu(pbi, - cm->new_fb_idx, - params->p.width, - params->p.height, - params->p.bit_depth, - pbi->frame_mmu_map_addr); - if (ret >= 0) - cm->cur_fb_idx_mmu = cm->new_fb_idx; - else - pr_err("can't alloc need mmu1,idx %d ret =%d\n", + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, - ret); -#else - ret = 0; -#endif + params->p.width, + params->p.height, + params->p.bit_depth, + pbi->frame_mmu_map_addr); + if (ret >= 0) + cm->cur_fb_idx_mmu = cm->new_fb_idx; + else + pr_err("can't alloc need mmu1,idx %d ret =%d\n", + cm->new_fb_idx, + ret); + } else { + ret = 0; + } WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (params->p.height << 16) | params->p.width); } @@ -7082,9 +7087,8 @@ int continue_decoding(struct VP9Decoder_s *pbi) ret); WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL); cm->show_frame = 0; -#ifdef VP9_10B_MMU - vp9_recycle_mmu_buf(pbi); -#endif + if (pbi->mmu_enable) + vp9_recycle_mmu_buf(pbi); #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) { pbi->dec_result = DEC_RESULT_DONE; @@ -7139,46 +7143,46 @@ int continue_decoding(struct VP9Decoder_s *pbi) config_sao_hw(pbi, &vp9_param); #ifdef VP9_LPF_LVL_UPDATE - /* - * Get loop filter related picture level parameters from Parser - */ - pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled; - pbi->lf->sharpness_level = vp9_param.p.sharpness_level; - for (i = 0; i < 4; i++) - pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i]; - for (i = 0; i < 2; i++) - pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i]; - pbi->default_filt_lvl = vp9_param.p.filter_level; - pbi->seg_4lf->enabled = vp9_param.p.seg_enabled; - pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta; - for (i = 0; i < MAX_SEGMENTS; i++) - pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] & - 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0; - for (i = 0; i < MAX_SEGMENTS; i++) - pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF] - = (vp9_param.p.seg_lf_info[i] - & 0x100) ? -(vp9_param.p.seg_lf_info[i] - & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - /*Set pipeline mode*/ - uint32_t lpf_data32 = READ_VREG(HEVC_DBLK_CFGB); - /*dblk pipeline mode=1 for performance*/ - if (vp9_param.p.width >= 1280) - lpf_data32 |= (0x1 << 4); - else - lpf_data32 &= ~(0x3 << 4); - WRITE_VREG(HEVC_DBLK_CFGB, lpf_data32); - } - /* - * Update loop filter Thr/Lvl table for every frame - */ - /*pr_info - ("vp9_loop_filter (run before every frame decoding start)\n");*/ - vp9_loop_filter_frame_init(pbi->seg_4lf, - pbi->lfi, pbi->lf, pbi->default_filt_lvl); + /* + * Get loop filter related picture level parameters from Parser + */ + pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled; + pbi->lf->sharpness_level = vp9_param.p.sharpness_level; + for (i = 0; i < 4; i++) + pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i]; + for (i = 0; i < 2; i++) + pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i]; + pbi->default_filt_lvl = vp9_param.p.filter_level; + pbi->seg_4lf->enabled = vp9_param.p.seg_enabled; + pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta; + for (i = 0; i < MAX_SEGMENTS; i++) + pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] & + 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0; + for (i = 0; i < MAX_SEGMENTS; i++) + pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF] + = (vp9_param.p.seg_lf_info[i] + & 0x100) ? -(vp9_param.p.seg_lf_info[i] + & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + /*Set pipeline mode*/ + uint32_t lpf_data32 = READ_VREG(HEVC_DBLK_CFGB); + /*dblk pipeline mode=1 for performance*/ + if (vp9_param.p.width >= 1280) + lpf_data32 |= (0x1 << 4); + else + lpf_data32 &= ~(0x3 << 4); + WRITE_VREG(HEVC_DBLK_CFGB, lpf_data32); + } + /* + * Update loop filter Thr/Lvl table for every frame + */ + /*pr_info + ("vp9_loop_filter (run before every frame decoding start)\n");*/ + vp9_loop_filter_frame_init(pbi->seg_4lf, + pbi->lfi, pbi->lf, pbi->default_filt_lvl); #endif - /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/ - WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); + /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/ + WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); } else { pr_info("Skip search next start code\n"); cm->prev_fb_idx = INVALID_IDX; @@ -7186,19 +7190,20 @@ int continue_decoding(struct VP9Decoder_s *pbi) WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); } pbi->process_state = PROC_STATE_DECODESLICE; -#ifdef VP9_10B_MMU - if (pbi->last_put_idx >= 0 && pbi->last_put_idx < pbi->used_buf_num) { - struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; - int i = pbi->last_put_idx; - /*free not used buffers.*/ - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.vf_ref == 0) && - (frame_bufs[i].buf.index != -1)) { - decoder_mmu_box_free_idx(pbi->mmu_box, i); + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + if (pbi->last_put_idx < pbi->used_buf_num) { + struct RefCntBuffer_s *frame_bufs = + cm->buffer_pool->frame_bufs; + int i = pbi->last_put_idx; + /*free not used buffers.*/ + if ((frame_bufs[i].ref_count == 0) && + (frame_bufs[i].buf.vf_ref == 0) && + (frame_bufs[i].buf.index != -1)) { + decoder_mmu_box_free_idx(pbi->mmu_box, i); + } + pbi->last_put_idx = -1; } - pbi->last_put_idx = -1; } -#endif return ret; } @@ -7270,6 +7275,9 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) #endif { reset_process_time(pbi); + if (pbi->vf_pre_count == 0) + vp9_bufmgr_postproc(pbi); + pbi->dec_result = DEC_RESULT_DONE; amhevc_stop(); if (mcrcc_cache_alg_flag) @@ -7330,9 +7338,9 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) && pbi->used_stage_buf_num == 0 #endif ) { -#ifdef VP9_10B_MMU - vp9_recycle_mmu_buf_tail(pbi); -#endif + if (pbi->mmu_enable) + vp9_recycle_mmu_buf_tail(pbi); + if (pbi->frame_count > 0) vp9_bufmgr_postproc(pbi); @@ -7395,11 +7403,13 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) return IRQ_HANDLED; } else #endif - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) - vp9_param.l.data[i + ii] = - pbi->rpm_ptr[i + 3 - ii]; + { + for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { + int ii; + for (ii = 0; ii < 4; ii++) + vp9_param.l.data[i + ii] = + pbi->rpm_ptr[i + 3 - ii]; + } } } @@ -7564,17 +7574,12 @@ static void vp9_set_clk(struct work_struct *work) struct VP9Decoder_s *pbi = container_of(work, struct VP9Decoder_s, work); - if (pbi->get_frame_dur && pbi->show_frame_num > 60 && - pbi->frame_dur > 0 && pbi->saved_resolution != - frame_width * frame_height * - (96000 / pbi->frame_dur)) { int fps = 96000 / pbi->frame_dur; if (hevc_source_changed(VFORMAT_VP9, frame_width, frame_height, fps) > 0) pbi->saved_resolution = frame_width * frame_height * fps; - } } static void vvp9_put_timer_func(unsigned long arg) @@ -7698,6 +7703,8 @@ static void vvp9_put_timer_func(unsigned long arg) pbi->dec_result = DEC_RESULT_AGAIN; if (pbi->process_state == PROC_STATE_DECODESLICE) { + if (pbi->mmu_enable) + vp9_recycle_mmu_buf(pbi); pbi->process_state = PROC_STATE_SENDAGAIN; } @@ -7762,7 +7769,7 @@ static void vvp9_put_timer_func(unsigned long arg) if (dbg_cmd == 1) { u32 disp_laddr; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && get_double_write_mode(pbi) == 0) { disp_laddr = READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; @@ -7779,7 +7786,11 @@ static void vvp9_put_timer_func(unsigned long arg) dbg_cmd = 0; } /*don't changed at start.*/ - schedule_work(&pbi->set_clk_work); + if (pbi->get_frame_dur && pbi->show_frame_num > 60 && + pbi->frame_dur > 0 && pbi->saved_resolution != + frame_width * frame_height * + (96000 / pbi->frame_dur)) + schedule_work(&pbi->set_clk_work); timer->expires = jiffies + PUT_INTERVAL; add_timer(timer); @@ -7790,6 +7801,10 @@ int vvp9_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct VP9Decoder_s *vp9 = (struct VP9Decoder_s *)vdec->private; + + if (!vp9) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (vp9->frame_dur != 0) @@ -7868,7 +7883,7 @@ static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask) ; WRITE_VREG(HEVC_STREAM_CONTROL, data32); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { if (debug & VP9_DEBUG_BUFMGR) pr_info("[test.c] Config STREAM_FIFO_CTL\n"); data32 = READ_VREG(HEVC_STREAM_FIFO_CTL); @@ -8039,34 +8054,20 @@ static s32 vvp9_init(struct vdec_s *vdec) static s32 vvp9_init(struct VP9Decoder_s *pbi) { #endif - int ret, size = -1; + int ret; int fw_size = 0x1000 * 16; struct firmware_s *fw = NULL; - INIT_WORK(&pbi->set_clk_work, vp9_set_clk); - - init_timer(&pbi->timer); - pbi->stat |= STAT_TIMER_INIT; + if (vvp9_local_init(pbi) < 0) return -EBUSY; fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; -#ifdef MULTI_INSTANCE_SUPPORT - if (tee_enabled()) { - size = 1; - pr_debug ("laod\n"); - } else -#endif - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - size = get_firmware_data(VIDEO_DEC_VP9, fw->data); - else - size = get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data); - - if (size < 0) { + if (get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data) < 0) { pr_err("get firmware fail.\n"); vfree(fw); return -1; @@ -8074,6 +8075,9 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi) fw->len = fw_size; + INIT_WORK(&pbi->set_clk_work, vp9_set_clk); + init_timer(&pbi->timer); + #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) { pbi->timer.data = (ulong) pbi; @@ -8095,21 +8099,15 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi) return 0; } #endif - + hevc_enable_DMC(hw_to_vdec(pbi)); amhevc_enable(); - if (size == 1) { - pr_info ("tee load ok\n"); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ret = tee_load_video_fw((u32)VIDEO_DEC_VP9, 0); - else - ret = tee_load_video_fw((u32)VIDEO_DEC_VP9_MMU, 0); - } else - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, fw->data); - + ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, fw->data); if (ret < 0) { amhevc_disable(); vfree(fw); + pr_err("VP9: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -8160,17 +8158,14 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi) pbi->timer.function = vvp9_put_timer_func; pbi->timer.expires = jiffies + PUT_INTERVAL; + pbi->stat |= STAT_VDEC_RUN; add_timer(&pbi->timer); pbi->stat |= STAT_TIMER_ARM; - /* pbi->stat |= STAT_KTHREAD; */ - amhevc_start(); - pbi->stat |= STAT_VDEC_RUN; - pbi->init_flag = 1; pbi->process_busy = 0; pr_info("%d, vvp9_init, RP=0x%x\n", @@ -8223,7 +8218,7 @@ static int vvp9_stop(struct VP9Decoder_s *pbi) { pbi->init_flag = 0; - + pbi->first_sc_checked = 0; if (pbi->stat & STAT_VDEC_RUN) { amhevc_stop(); pbi->stat &= ~STAT_VDEC_RUN; @@ -8273,14 +8268,12 @@ static int vvp9_stop(struct VP9Decoder_s *pbi) pbi->fw = NULL; return 0; } - static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi) { int tvp_flag = vdec_secure(hw_to_vdec(pbi)) ? CODEC_MM_FLAGS_TVP : 0; - -#ifdef VP9_10B_MMU int buf_size = 48; + if ((pbi->max_pic_w * pbi->max_pic_h > 1280*736) && (pbi->max_pic_w * pbi->max_pic_h <= 1920*1088)) { buf_size = 12; @@ -8288,16 +8281,19 @@ static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi) (pbi->max_pic_w * pbi->max_pic_h <= 1280*736)) { buf_size = 4; } - pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, - pbi->index, FRAME_BUFFERS + STAGE_MAX_BUFFERS, - buf_size * SZ_1M, - tvp_flag - ); - if (!pbi->mmu_box) { - pr_err("vp9 alloc mmu box failed!!\n"); - return -1; + pbi->need_cache_size = buf_size * SZ_1M; + pbi->sc_start_time = get_jiffies_64(); + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, + pbi->index, FRAME_BUFFERS, + pbi->need_cache_size, + tvp_flag + ); + if (!pbi->mmu_box) { + pr_err("vp9 alloc mmu box failed!!\n"); + return -1; + } } -#endif pbi->bmmu_box = decoder_bmmu_box_alloc_box( DRIVER_NAME, pbi->index, @@ -8340,6 +8336,11 @@ static int amvdec_vp9_probe(struct platform_device *pdev) memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); pbi->init_flag = 0; + pbi->first_sc_checked= 0; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + vp9_max_pic_w = 8192; + vp9_max_pic_h = 4608; + } pbi->max_pic_w = vp9_max_pic_w; pbi->max_pic_h = vp9_max_pic_h; @@ -8361,6 +8362,8 @@ static int amvdec_vp9_probe(struct platform_device *pdev) pbi->platform_dev = pdev; platform_set_drvdata(pdev, pdata); #endif + pbi->double_write_mode = double_write_mode; + pbi->mmu_enable = 1; if (amvdec_vp9_mmu_init(pbi) < 0) { vfree(pbi); mutex_unlock(&vvp9_mutex); @@ -8381,9 +8384,9 @@ static int amvdec_vp9_probe(struct platform_device *pdev) #ifdef MULTI_INSTANCE_SUPPORT pbi->buf_start = pdata->mem_start; #else -#ifndef VP9_10B_MMU - pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size; -#endif + if (!pbi->mmu_enable) + pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size; + for (i = 0; i < WORK_BUF_SPEC_NUM; i++) amvvp9_workbuff_spec[i].start_adr = pdata->mem_start; #endif @@ -8420,6 +8423,7 @@ static int amvdec_vp9_probe(struct platform_device *pdev) vp9_local_uninit(pbi); uninit_mmu_buffers(pbi); vfree(pbi); + pdata->dec_status = NULL; mutex_unlock(&vvp9_mutex); return -ENODEV; } @@ -8480,20 +8484,37 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + u8 *data = NULL; + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap(pbi->chunk->block->start + + pbi->chunk->offset, size); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } static void dump_data(struct VP9Decoder_s *pbi, int size) { int jj; - u8 *data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + u8 *data = NULL; int padding_size = pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1); + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap(pbi->chunk->block->start + + pbi->chunk->offset, size); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + vp9_print(pbi, 0, "padding: "); for (jj = padding_size; jj > 0; jj--) vp9_print_cont(pbi, @@ -8518,6 +8539,9 @@ static void dump_data(struct VP9Decoder_s *pbi, int size) vp9_print(pbi, 0, "\n"); + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } static void vp9_work(struct work_struct *work) @@ -8626,10 +8650,9 @@ static void vp9_work(struct work_struct *work) pbi->process_state = PROC_STATE_INIT; decode_frame_count[pbi->index] = pbi->frame_count; -#ifdef VP9_10B_MMU - pbi->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); -#endif + if (pbi->mmu_enable) + pbi->used_4k_num = + (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, "%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n", __func__, @@ -8648,10 +8671,6 @@ static void vp9_work(struct work_struct *work) stream base: stream buf empty or timeout frame base: vdec_prepare_input fail */ -#ifdef VP9_10B_MMU - if (pbi->process_state == PROC_STATE_SENDAGAIN) - vp9_recycle_mmu_buf(pbi); -#endif if (!vdec_has_more_input(vdec)) { pbi->dec_result = DEC_RESULT_EOS; vdec_schedule_work(&pbi->work); @@ -8702,8 +8721,11 @@ static void vp9_work(struct work_struct *work) | CORE_MASK_HEVC_BACK ); #else - vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1 - | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_finish_run(vdec, CORE_MASK_HEVC); + else + vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1 + | CORE_MASK_HEVC); #endif trigger_schedule(pbi); } @@ -8723,15 +8745,23 @@ static int vp9_hw_ctx_restore(struct VP9Decoder_s *pbi) #endif return 0; } - static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)vdec->private; + int tvp = vdec_secure(hw_to_vdec(pbi)) ? + CODEC_MM_FLAGS_TVP : 0; unsigned long ret = 0; if (pbi->eos) return ret; + if (!pbi->first_sc_checked && pbi->mmu_enable) { + int size = decoder_mmu_box_sc_check(pbi->mmu_box, tvp); + pbi->first_sc_checked = 1; + vp9_print(pbi, 0, "vp9 cached=%d need_size=%d speed= %d ms\n", + size, (pbi->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - pbi->sc_start_time) * 1000/HZ); + } #ifdef SUPPORT_FB_DECODING if (pbi->used_stage_buf_num > 0) { if (mask & CORE_MASK_HEVC_FRONT) { @@ -8782,8 +8812,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) #else if (get_free_buf_count(pbi) >= - run_ready_min_buf_num) - ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + run_ready_min_buf_num) { + if (vdec->parallel_dec == 1) + ret = CORE_MASK_HEVC; + else + ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + } if (ret) not_run_ready[pbi->index] = 0; else @@ -8839,37 +8873,54 @@ static void run_front(struct vdec_s *vdec) pbi->frame_count, size, pbi->chunk ? pbi->chunk->size : 0, pbi->chunk ? pbi->chunk->offset : 0, - (vdec_frame_based(vdec) && + pbi->chunk ? ((vdec_frame_based(vdec) && (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(pbi, size) : 0, + get_data_check_sum(pbi, size) : 0) : 0, READ_VREG(HEVC_STREAM_START_ADDR), READ_VREG(HEVC_STREAM_END_ADDR), READ_VREG(HEVC_STREAM_LEVEL), READ_VREG(HEVC_STREAM_WR_PTR), READ_VREG(HEVC_STREAM_RD_PTR), pbi->start_shift_bytes); - if (vdec_frame_based(vdec)) { - u8 *data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + if (vdec_frame_based(vdec) && pbi->chunk) { + u8 *data = NULL; + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap(pbi->chunk->block->start + + pbi->chunk->offset, 8); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + vp9_print_cont(pbi, 0, "data adr %p:", data); for (ii = 0; ii < 8; ii++) vp9_print_cont(pbi, 0, "%02x ", data[ii]); + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } vp9_print_cont(pbi, 0, "\r\n"); } - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ret = amhevc_loadmc_ex(VFORMAT_VP9, "vp9_mc", pbi->fw->data); - else - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); - - if (ret < 0) { - amhevc_disable(); - vp9_print(pbi, 0, - "%s: Error amvdec_loadmc fail\n", __func__); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); + if (ret < 0) { + amhevc_disable(); + vp9_print(pbi, PRINT_FLAG_ERROR, + "VP9: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + pbi->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&pbi->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_VP9; } if (vp9_hw_ctx_restore(pbi) < 0) { @@ -9206,9 +9257,16 @@ static void vp9_dump_state(struct vdec_s *vdec) int jj; if (pbi->chunk && pbi->chunk->block && pbi->chunk->size > 0) { - u8 *data = - ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + u8 *data = NULL; + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap( + pbi->chunk->block->start + + pbi->chunk->offset, + pbi->chunk->size); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; vp9_print(pbi, 0, "frame data size 0x%x\n", pbi->chunk->size); @@ -9222,6 +9280,9 @@ static void vp9_dump_state(struct vdec_s *vdec) vp9_print_cont(pbi, 0, "\n"); } + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } @@ -9283,11 +9344,17 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->platform_dev = pdev; pbi->video_signal_type = 0; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_TXLX) + pbi->m_ins_flag = 1; + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) pbi->stat |= VP9_TRIGGER_FRAME_ENABLE; + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + pbi->max_pic_w = 8192; + pbi->max_pic_h = 4608; + } #if 1 if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && - pdata->config && pdata->config_len) { + pdata->config_len) { #ifdef MULTI_INSTANCE_SUPPORT /*use ptr config for doubel_write_mode, etc*/ vp9_print(pbi, 0, "pdata->config=%s\n", pdata->config); @@ -9297,6 +9364,12 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) else pbi->double_write_mode = double_write_mode; + if (get_config_int(pdata->config, "save_buffer_mode", + &config_val) == 0) + pbi->save_buffer_mode = config_val; + else + pbi->save_buffer_mode = 0; + /*use ptr config for max_pic_w, etc*/ if (get_config_int(pdata->config, "vp9_max_pic_w", &config_val) == 0) { @@ -9353,6 +9426,12 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->vvp9_amstream_dec_info.rate = 30;*/ pbi->double_write_mode = double_write_mode; } + if (is_oversize(pbi->max_pic_w, pbi->max_pic_h)) { + pr_err("over size: %dx%d, probe failed\n", + pbi->max_pic_w, pbi->max_pic_h); + return -1; + } + pbi->mmu_enable = 1; video_signal_type = pbi->video_signal_type; #if 0 pbi->buf_start = pdata->mem_start; @@ -9362,6 +9441,7 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pr_err("vp9 alloc bmmu box failed!!\n"); /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); + pdata->dec_status = NULL; return -1; } @@ -9373,23 +9453,17 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) uninit_mmu_buffers(pbi); /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); + pdata->dec_status = NULL; return ret; } pbi->buf_start = pbi->cma_alloc_addr; pbi->buf_size = work_buf_size; #endif - pbi->m_ins_flag = 1; pbi->init_flag = 0; + pbi->first_sc_checked = 0; pbi->fatal_error = 0; pbi->show_frame_num = 0; - if (pdata == NULL) { - pr_info("\namvdec_vp9 memory resource undefined.\n"); - uninit_mmu_buffers(pbi); - /* devm_kfree(&pdev->dev, (void *)pbi); */ - vfree((void *)pbi); - return -EFAULT; - } if (debug) { pr_info("===VP9 decoder mem resource 0x%lx size 0x%x\n", @@ -9412,6 +9486,7 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) uninit_mmu_buffers(pbi); /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); + pdata->dec_status = NULL; return -ENODEV; } vdec_set_prepare_level(pdata, start_decode_buf_level); @@ -9426,6 +9501,9 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK | CORE_MASK_COMBINE); #else + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_HEVC); + else vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); #endif @@ -9436,6 +9514,8 @@ static int ammvdec_vp9_remove(struct platform_device *pdev) { struct VP9Decoder_s *pbi = (struct VP9Decoder_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(pbi); + int i; if (debug) pr_info("amvdec_vp9_remove\n"); @@ -9446,10 +9526,24 @@ static int ammvdec_vp9_remove(struct platform_device *pdev) | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK ); #else - vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(pbi), CORE_MASK_HEVC); + else + vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); #endif vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_DISCONNECTED); + if (vdec->parallel_dec == 1) { + for (i = 0; i < FRAME_BUFFERS; i++) { + vdec->free_canvas_ex + (pbi->common.buffer_pool->frame_bufs[i].buf.y_canvas_index, + vdec->id); + vdec->free_canvas_ex + (pbi->common.buffer_pool->frame_bufs[i].buf.uv_canvas_index, + vdec->id); + } + } + #ifdef DEBUG_PTS pr_info("pts missed %ld, pts hit %ld, duration %d\n", @@ -9515,24 +9609,23 @@ static struct mconfig_node vp9_node; static int __init amvdec_vp9_driver_init_module(void) { -#ifdef VP9_10B_MMU - struct BuffInfo_s *p_buf_info; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - p_buf_info = &amvvp9_workbuff_spec[1]; - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + p_buf_info = &amvvp9_workbuff_spec[2]; + else + p_buf_info = &amvvp9_workbuff_spec[1]; + } else p_buf_info = &amvvp9_workbuff_spec[0]; -#else - p_buf_info = &amvvp9_workbuff_spec[0]; -#endif + init_buff_spec(NULL, p_buf_info); work_buf_size = (p_buf_info->end_adr - p_buf_info->start_adr + 0xffff) & (~0xffff); -#endif pr_debug("amvdec_vp9 module init\n"); + error_handle_policy = 0; #ifdef ERROR_HANDLE_DEBUG @@ -9554,8 +9647,12 @@ static int __init amvdec_vp9_driver_init_module(void) return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL - /*&& get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX*/) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + amvdec_vp9_profile.profile = + "8k, 10bit, dwrite, compressed"; + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL + /*&& get_cpu_major_id() != MESON_CPU_MAJOR_ID_GXLX*/ + && get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TXL) { if (vdec_is_support_4k()) amvdec_vp9_profile.profile = "4k, 10bit, dwrite, compressed"; @@ -9566,6 +9663,9 @@ static int __init amvdec_vp9_driver_init_module(void) amvdec_vp9_profile.name = "vp9_unsupport"; } + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + max_buf_num = MAX_BUF_NUM_LESS; + vcodec_profile_register(&amvdec_vp9_profile); INIT_REG_NODE_CONFIGS("media.decoder", &vp9_node, "vp9", vp9_configs, CONFIG_FOR_RW); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h index 3f4959ccccc2..1db9d0998ff2 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h @@ -17,7 +17,7 @@ #ifndef VVP9_H #define VVP9_H -#define VP9_10B_MMU + void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count); #endif diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c index 48e701a56ee5..fadff431d0b5 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c @@ -762,6 +762,9 @@ static void avc_buffspec_init(struct encode_wq_s *wq) wq->mem.buf_start + wq->mem.bufspec.cbr_info.buf_start; wq->mem.cbr_info_ddr_size = wq->mem.bufspec.cbr_info.buf_size; + wq->mem.cbr_info_ddr_virt_addr = + codec_mm_vmap(wq->mem.cbr_info_ddr_start_addr, + wq->mem.bufspec.cbr_info.buf_size); wq->mem.dblk_buf_canvas = ((ENC_CANVAS_OFFSET + 2) << 16) | @@ -1059,6 +1062,9 @@ static int scale_frame(struct encode_wq_s *wq, || (request->fmt == FMT_NV12)) { src_canvas = src_addr & 0xffff; input_format = GE2D_FORMAT_M24_NV21; + } else if (request->fmt == FMT_BGR888) { + src_canvas = src_addr & 0xffffff; + input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d } else { src_canvas = src_addr & 0xffffff; input_format = GE2D_FORMAT_M24_YUV420; @@ -1082,6 +1088,16 @@ static int scale_frame(struct encode_wq_s *wq, ((ENC_CANVAS_OFFSET + 10) << 8) | (ENC_CANVAS_OFFSET + 9); input_format = GE2D_FORMAT_M24_NV21; + } else if (request->fmt == FMT_BGR888) { + src_canvas_w = + ((request->src_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 9, + src_addr, + src_canvas_w * 3, src_h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + src_canvas = ENC_CANVAS_OFFSET + 9; + input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d } else { src_canvas_w = ((request->src_w + 63) >> 6) << 6; @@ -1169,6 +1185,7 @@ static int scale_frame(struct encode_wq_s *wq, ge2d_config->dst_para.height = dst_h; ge2d_config->dst_para.x_rev = 0; ge2d_config->dst_para.y_rev = 0; + if (ge2d_context_config_ex(context, ge2d_config) < 0) { pr_err("++ge2d configing error.\n"); return -1; @@ -2401,7 +2418,11 @@ static s32 avc_poweron(u32 clock) /* Powerup HCODEC */ /* [1:0] HCODEC */ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - (READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & (~0x3))); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? ~0x1 : ~0x3)); + udelay(10); WRITE_VREG(DOS_SW_RESET1, 0xffffffff); @@ -2415,7 +2436,11 @@ static s32 avc_poweron(u32 clock) /* Remove HCODEC ISO */ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - (READ_AOREG(AO_RTI_GEN_PWR_ISO0) & (~0x30))); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? ~0x1 : ~0x30)); + udelay(10); /* Disable auto-clock gate */ WRITE_VREG(DOS_GEN_CTRL0, @@ -2437,7 +2462,11 @@ static s32 avc_poweroff(void) /* enable HCODEC isolation */ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? 0x1 : 0x30)); + /* power off HCODEC memories */ WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); @@ -2446,7 +2475,10 @@ static s32 avc_poweroff(void) /* HCODEC power off */ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0x3); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? 0x1 : 0x3)); spin_unlock_irqrestore(&lock, flags); @@ -3236,11 +3268,10 @@ static s32 encode_process_request(struct encode_manager_s *manager, if (request->cmd == ENCODER_IDR || request->cmd == ENCODER_NON_IDR) { if (request->flush_flag & AMVENC_FLUSH_FLAG_CBR && get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - void *vaddr = - phys_to_virt(wq->mem.cbr_info_ddr_start_addr); + void *vaddr = wq->mem.cbr_info_ddr_virt_addr; ConvertTable2Risc(vaddr, 0xa00); buf_start = getbuffer(wq, ENCODER_BUFFER_CBR); - dma_flush(buf_start, wq->mem.cbr_info_ddr_size); + codec_mm_dma_flush(vaddr, wq->mem.cbr_info_ddr_size, DMA_TO_DEVICE); } } #endif @@ -3526,6 +3557,10 @@ s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue) spin_unlock(&encode_manager.event.sem_lock); #ifdef CONFIG_CMA if (encode_work_queue->mem.buf_start) { + if (wq->mem.cbr_info_ddr_virt_addr != NULL) { + codec_mm_unmap_phyaddr(wq->mem.cbr_info_ddr_virt_addr); + wq->mem.cbr_info_ddr_virt_addr = NULL; + } codec_mm_free_for_dma( ENCODE_NAME, encode_work_queue->mem.buf_start); diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h index 1c3ade4427d7..a5e0ceee1c12 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h @@ -149,6 +149,7 @@ enum amvenc_frame_fmt_e { FMT_YUV422_12BIT, FMT_YUV444_10BIT, FMT_YUV422_10BIT, + FMT_BGR888, MAX_FRAME_FMT }; @@ -259,6 +260,8 @@ struct encode_meminfo_s { u32 cbr_info_ddr_start_addr; u32 cbr_info_ddr_size; + u8 * cbr_info_ddr_virt_addr; + s32 dblk_buf_canvas; s32 ref_buf_canvas; struct BuffInfo_s bufspec; diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h index 3c9c6d8734f8..a32dd06eb7ab 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h @@ -476,7 +476,7 @@ s32 vmem_init(struct video_mm_t *mm, ulong addr, ulong size) (struct page_t *)VMEM_P_ALLOC( mm->num_pages * sizeof(struct page_t)); if (mm->page_list == NULL) { - pr_err("%s:%d failed to kmalloc(%ld)\n", + pr_err("%s:%d failed to kmalloc(%zu)\n", __func__, __LINE__, mm->num_pages * sizeof(struct page_t)); return -1; diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c index 3345b0a23e07..3180b4968a9e 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c @@ -154,8 +154,7 @@ static s32 vpu_alloc_dma_buffer(struct vpudrv_buffer_t *vb) return -1; } - vb->base = (ulong)(s_video_memory.base + - (vb->phys_addr - s_video_memory.phys_addr)); + enc_pr(LOG_INFO, "vpu_alloc_dma_buffer: vb->phys_addr 0x%lx \n",vb->phys_addr); return 0; } @@ -163,8 +162,9 @@ static void vpu_free_dma_buffer(struct vpudrv_buffer_t *vb) { if (!vb) return; + enc_pr(LOG_INFO, "vpu_free_dma_buffer 0x%lx\n",vb->phys_addr); - if (vb->base) + if (vb->phys_addr) vmem_free(&s_vmem, vb->phys_addr, 0); } @@ -211,7 +211,7 @@ static s32 vpu_free_buffers(struct file *filp) list_for_each_entry_safe(pool, n, &s_vbp_head, list) { if (pool->filp == filp) { vb = pool->vb; - if (vb.base) { + if (vb.phys_addr) { vpu_free_dma_buffer(&vb); list_del(&pool->list); kfree(pool); @@ -323,14 +323,8 @@ static s32 vpu_open(struct inode *inode, struct file *filp) s_video_memory.size = VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE; s_video_memory.phys_addr = (ulong)codec_mm_alloc_for_dma(VPU_DEV_NAME, - VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE >> PAGE_SHIFT, 0, - CODEC_MM_FLAGS_CPU); - if (s_video_memory.phys_addr) - s_video_memory.base = - (ulong)phys_to_virt(s_video_memory.phys_addr); - else - s_video_memory.base = 0; - if (s_video_memory.base) { + VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE >> PAGE_SHIFT, 0, 0); + if (s_video_memory.phys_addr) { enc_pr(LOG_DEBUG, "allocating phys 0x%lx, virt addr 0x%lx, size %dk\n", s_video_memory.phys_addr, @@ -366,7 +360,7 @@ static s32 vpu_open(struct inode *inode, struct file *filp) "No CMA and reserved memory for HevcEnc!!!\n"); r = -ENOMEM; #endif - } else if (!s_video_memory.base) { + } else if (!s_video_memory.phys_addr) { enc_pr(LOG_ERROR, "HevcEnc memory is not malloced!!!\n"); r = -ENOMEM; @@ -383,6 +377,7 @@ static s32 vpu_open(struct inode *inode, struct file *filp) if (err) { enc_pr(LOG_ERROR, "fail to register interrupt handler\n"); + s_vpu_drv_context.open_count--; return -EFAULT; } s_vpu_irq_requested = true; @@ -390,7 +385,9 @@ static s32 vpu_open(struct inode *inode, struct file *filp) amports_switch_gate("vdec", 1); spin_lock_irqsave(&s_vpu_lock, flags); WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~(0x3<<24)); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? ~0x8 : ~(0x3<<24))); udelay(10); if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXLX) { @@ -423,12 +420,16 @@ static s32 vpu_open(struct inode *inode, struct file *filp) WRITE_VREG(DOS_MEM_PD_WAVE420L, 0x0); WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~(0x3<<12)); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? ~0x8 : ~(0x3<<12))); udelay(10); spin_unlock_irqrestore(&s_vpu_lock, flags); } Err: + if (r != 0) + s_vpu_drv_context.open_count--; enc_pr(LOG_DEBUG, "[-] %s, ret: %d\n", __func__, r); return r; } @@ -491,6 +492,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32: { struct vpudrv_buffer_pool_t *vbp; @@ -519,8 +521,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) vbp->vb.cached = buf32.cached; vbp->vb.phys_addr = (ulong)buf32.phys_addr; - vbp->vb.base = - (ulong)buf32.base; vbp->vb.virt_addr = (ulong)buf32.virt_addr; ret = vpu_alloc_dma_buffer(&(vbp->vb)); @@ -534,8 +534,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.size = vbp->vb.size; buf32.phys_addr = (compat_ulong_t)vbp->vb.phys_addr; - buf32.base = - (compat_ulong_t)vbp->vb.base; buf32.virt_addr = (compat_ulong_t)vbp->vb.virt_addr; @@ -560,6 +558,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32\n"); } break; +#endif case VDI_IOCTL_FREE_PHYSICALMEMORY: { struct vpudrv_buffer_pool_t *vbp, *n; @@ -577,25 +576,27 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) return -EACCES; } - if (vb.base) + if (vb.phys_addr) vpu_free_dma_buffer(&vb); spin_lock(&s_vpu_lock); list_for_each_entry_safe(vbp, n, &s_vbp_head, list) { - if (vbp->vb.base == vb.base) { + if (vbp->vb.phys_addr == vb.phys_addr) { list_del(&vbp->list); kfree(vbp); break; } } spin_unlock(&s_vpu_lock); + up(&s_vpu_sem); } enc_pr(LOG_ALL, "[-]VDI_IOCTL_FREE_PHYSICALMEMORY\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_FREE_PHYSICALMEMORY32: { struct vpudrv_buffer_pool_t *vbp, *n; @@ -617,12 +618,10 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) vb.size = buf32.size; vb.phys_addr = (ulong)buf32.phys_addr; - vb.base = - (ulong)buf32.base; vb.virt_addr = (ulong)buf32.virt_addr; - if (vb.base) + if (vb.phys_addr) vpu_free_dma_buffer(&vb); spin_lock(&s_vpu_lock); @@ -642,11 +641,12 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_FREE_PHYSICALMEMORY32\n"); } break; +#endif case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO: { enc_pr(LOG_ALL, "[+]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); - if (s_video_memory.base != 0) { + if (s_video_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &s_video_memory, sizeof(struct vpudrv_buffer_t)); @@ -659,6 +659,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32: { struct compat_vpudrv_buffer_t buf32; @@ -669,11 +670,9 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.size = s_video_memory.size; buf32.phys_addr = (compat_ulong_t)s_video_memory.phys_addr; - buf32.base = - (compat_ulong_t)s_video_memory.base; buf32.virt_addr = (compat_ulong_t)s_video_memory.virt_addr; - if (s_video_memory.base != 0) { + if (s_video_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &buf32, sizeof(struct compat_vpudrv_buffer_t)); @@ -686,6 +685,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32\n"); } break; +#endif case VDI_IOCTL_WAIT_INTERRUPT: { struct vpudrv_intr_info_t info; @@ -706,6 +706,9 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) ret = -ETIME; break; } + enc_pr(LOG_INFO, + "s_interrupt_flag(%d), reason(0x%08lx)\n", + s_interrupt_flag, dev->interrupt_reason); if (dev->interrupt_reason & (1 << W4_INT_ENC_PIC)) { u32 start, end, size, core = 0; @@ -804,6 +807,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_INSTANCE_POOL\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_INSTANCE_POOL32: { struct compat_vpudrv_buffer_t buf32; @@ -818,9 +822,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_instance_pool.phys_addr; - buf32.base = - (compat_ulong_t) - s_instance_pool.base; buf32.virt_addr = (compat_ulong_t) s_instance_pool.virt_addr; @@ -875,11 +876,12 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_INSTANCE_POOL32\n"); } break; +#endif case VDI_IOCTL_GET_COMMON_MEMORY: { enc_pr(LOG_ALL, "[+]VDI_IOCTL_GET_COMMON_MEMORY\n"); - if (s_common_memory.base != 0) { + if (s_common_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &s_common_memory, sizeof(struct vpudrv_buffer_t)); @@ -907,6 +909,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_COMMON_MEMORY\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_COMMON_MEMORY32: { struct compat_vpudrv_buffer_t buf32; @@ -918,13 +921,10 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_common_memory.phys_addr; - buf32.base = - (compat_ulong_t) - s_common_memory.base; buf32.virt_addr = (compat_ulong_t) s_common_memory.virt_addr; - if (s_common_memory.base != 0) { + if (s_common_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &buf32, sizeof(struct compat_vpudrv_buffer_t)); @@ -946,9 +946,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_common_memory.phys_addr; - buf32.base = - (compat_ulong_t) - s_common_memory.base; buf32.virt_addr = (compat_ulong_t) s_common_memory.virt_addr; @@ -965,6 +962,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_COMMON_MEMORY32\n"); } break; +#endif case VDI_IOCTL_OPEN_INSTANCE: { struct vpudrv_inst_info_t inst_info; @@ -1133,6 +1131,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) s_vpu_register.size); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_REGISTER_INFO32: { struct compat_vpudrv_buffer_t buf32; @@ -1144,9 +1143,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_vpu_register.phys_addr; - buf32.base = - (compat_ulong_t) - s_vpu_register.base; buf32.virt_addr = (compat_ulong_t) s_vpu_register.virt_addr; @@ -1207,6 +1203,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_FLUSH_BUFFER32\n"); } break; +#endif case VDI_IOCTL_FLUSH_BUFFER: { struct vpudrv_buffer_pool_t *pool, *n; @@ -1248,6 +1245,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) { enc_pr(LOG_ERROR, "No such IOCTL, cmd is %d\n", cmd); + ret = -EFAULT; } break; } @@ -1341,18 +1339,24 @@ static s32 vpu_release(struct inode *inode, struct file *filp) vpu_free_instances(filp); s_vpu_drv_context.open_count--; if (s_vpu_drv_context.open_count == 0) { + enc_pr(LOG_INFO, + "vpu_release: s_interrupt_flag(%d), reason(0x%08lx)\n", + s_interrupt_flag, s_vpu_drv_context.interrupt_reason); + s_vpu_drv_context.interrupt_reason = 0; + s_interrupt_flag = 0; if (s_instance_pool.base) { enc_pr(LOG_DEBUG, "free instance pool\n"); vfree((const void *)s_instance_pool.base); s_instance_pool.base = 0; } - if (s_common_memory.base) { - enc_pr(LOG_DEBUG, "free common memory\n"); + if (s_common_memory.phys_addr) { + enc_pr(LOG_INFO, "vpu_release, s_common_memory 0x%lx\n",s_common_memory.phys_addr); vpu_free_dma_buffer(&s_common_memory); - s_common_memory.base = 0; + s_common_memory.phys_addr = 0; } - if (s_video_memory.base && !use_reserve) { + if (s_video_memory.phys_addr && !use_reserve) { + enc_pr(LOG_DEBUG, "vpu_release, s_video_memory 0x%lx\n",s_video_memory.phys_addr); codec_mm_free_for_dma( VPU_DEV_NAME, (u32)s_video_memory.phys_addr); @@ -1368,7 +1372,9 @@ static s32 vpu_release(struct inode *inode, struct file *filp) } spin_lock_irqsave(&s_vpu_lock, flags); WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | (0x3<<12)); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? 0x8 : (0x3<<12))); udelay(10); WRITE_VREG(DOS_MEM_PD_WAVE420L, 0xffffffff); @@ -1376,7 +1382,9 @@ static s32 vpu_release(struct inode *inode, struct file *filp) vpu_clk_config(0); #endif WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | (0x3<<24)); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? 0x8 : (0x3<<24))); udelay(10); spin_unlock_irqrestore(&s_vpu_lock, flags); amports_switch_gate("vdec", 0); @@ -1563,18 +1571,8 @@ static s32 hevc_mem_device_init( r = 0; s_video_memory.size = rmem->size; s_video_memory.phys_addr = (ulong)rmem->base; - s_video_memory.base = - (ulong)phys_to_virt(s_video_memory.phys_addr); - if (!s_video_memory.base) { - enc_pr(LOG_ERROR, "fail to remap video memory "); - enc_pr(LOG_ERROR, - "physical phys_addr=0x%lx, base=0x%lx, size=0x%x\n", - (ulong)s_video_memory.phys_addr, - (ulong)s_video_memory.base, - (u32)s_video_memory.size); - s_video_memory.phys_addr = 0; - r = -EFAULT; - } + enc_pr(LOG_DEBUG, "hevc_mem_device_init %d, 0x%lx\n ",s_video_memory.size,s_video_memory.phys_addr); + return r; } @@ -1741,7 +1739,7 @@ ERROR_PROVE_DEVICE: memset(&s_vpu_register, 0, sizeof(struct vpudrv_buffer_t)); } - if (s_video_memory.base) { + if (s_video_memory.phys_addr) { vmem_exit(&s_vmem); memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); memset(&s_vmem, 0, sizeof(struct video_mm_t)); @@ -1769,16 +1767,17 @@ static s32 vpu_remove(struct platform_device *pdev) s_instance_pool.base = 0; } - if (s_common_memory.base) { + if (s_common_memory.phys_addr) { vpu_free_dma_buffer(&s_common_memory); - s_common_memory.base = 0; + s_common_memory.phys_addr = 0; } - if (s_video_memory.base) { - if (!use_reserve) + if (s_video_memory.phys_addr) { + if (!use_reserve) { codec_mm_free_for_dma( VPU_DEV_NAME, (u32)s_video_memory.phys_addr); + } vmem_exit(&s_vmem); memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); @@ -1880,72 +1879,73 @@ static s32 vpu_resume(struct platform_device *pdev) enc_pr(LOG_DEBUG, "vpu_resume\n"); vpu_clk_config(1); - - for (core = 0; core < MAX_NUM_VPU_CORE; core++) { - if (s_bit_firmware_info[core].size == 0) - continue; - code_base = s_common_memory.phys_addr; - /* ALIGN TO 4KB */ - code_size = (s_common_memory.size & ~0xfff); - if (code_size < s_bit_firmware_info[core].size * 2) - goto DONE_WAKEUP; - - /*---- LOAD BOOT CODE */ - for (i = 0; i < 512; i += 2) { - val = s_bit_firmware_info[core].bit_code[i]; - val |= (s_bit_firmware_info[core].bit_code[i+1] << 16); - WriteVpu(code_base+(i*2), val); - } - - regVal = 0; - WriteVpuRegister(W4_PO_CONF, regVal); - - /* Reset All blocks */ - regVal = 0x7ffffff; - WriteVpuRegister(W4_VPU_RESET_REQ, regVal); - - /* Waiting reset done */ - while (ReadVpuRegister(W4_VPU_RESET_STATUS)) { - if (time_after(jiffies, timeout)) + if (s_vpu_open_ref_count > 0) { + for (core = 0; core < MAX_NUM_VPU_CORE; core++) { + if (s_bit_firmware_info[core].size == 0) + continue; + code_base = s_common_memory.phys_addr; + /* ALIGN TO 4KB */ + code_size = (s_common_memory.size & ~0xfff); + if (code_size < s_bit_firmware_info[core].size * 2) goto DONE_WAKEUP; - } - WriteVpuRegister(W4_VPU_RESET_REQ, 0); + /*---- LOAD BOOT CODE */ + for (i = 0; i < 512; i += 2) { + val = s_bit_firmware_info[core].bit_code[i]; + val |= (s_bit_firmware_info[core].bit_code[i+1] << 16); + WriteVpu(code_base+(i*2), val); + } - /* remap page size */ - remap_size = (code_size >> 12) & 0x1ff; - regVal = 0x80000000 | (W4_REMAP_CODE_INDEX<<12) - | (0 << 16) | (1<<11) | remap_size; - WriteVpuRegister(W4_VPU_REMAP_CTRL, regVal); - /* DO NOT CHANGE! */ - WriteVpuRegister(W4_VPU_REMAP_VADDR, 0x00000000); - WriteVpuRegister(W4_VPU_REMAP_PADDR, code_base); - WriteVpuRegister(W4_ADDR_CODE_BASE, code_base); - WriteVpuRegister(W4_CODE_SIZE, code_size); - WriteVpuRegister(W4_CODE_PARAM, 0); - WriteVpuRegister(W4_INIT_VPU_TIME_OUT_CNT, timeout); - WriteVpuRegister(W4_HW_OPTION, hwOption); + regVal = 0; + WriteVpuRegister(W4_PO_CONF, regVal); - /* Interrupt */ - regVal = (1 << W4_INT_DEC_PIC_HDR); - regVal |= (1 << W4_INT_DEC_PIC); - regVal |= (1 << W4_INT_QUERY_DEC); - regVal |= (1 << W4_INT_SLEEP_VPU); - regVal |= (1 << W4_INT_BSBUF_EMPTY); - regVal = 0xfffffefe; - WriteVpuRegister(W4_VPU_VINT_ENABLE, regVal); - Wave4BitIssueCommand(core, W4_CMD_INIT_VPU); - WriteVpuRegister(W4_VPU_REMAP_CORE_START, 1); - while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { - if (time_after(jiffies, timeout)) + /* Reset All blocks */ + regVal = 0x7ffffff; + WriteVpuRegister(W4_VPU_RESET_REQ, regVal); + + /* Waiting reset done */ + while (ReadVpuRegister(W4_VPU_RESET_STATUS)) { + if (time_after(jiffies, timeout)) + goto DONE_WAKEUP; + } + + WriteVpuRegister(W4_VPU_RESET_REQ, 0); + + /* remap page size */ + remap_size = (code_size >> 12) & 0x1ff; + regVal = 0x80000000 | (W4_REMAP_CODE_INDEX<<12) + | (0 << 16) | (1<<11) | remap_size; + WriteVpuRegister(W4_VPU_REMAP_CTRL, regVal); + /* DO NOT CHANGE! */ + WriteVpuRegister(W4_VPU_REMAP_VADDR, 0x00000000); + WriteVpuRegister(W4_VPU_REMAP_PADDR, code_base); + WriteVpuRegister(W4_ADDR_CODE_BASE, code_base); + WriteVpuRegister(W4_CODE_SIZE, code_size); + WriteVpuRegister(W4_CODE_PARAM, 0); + WriteVpuRegister(W4_INIT_VPU_TIME_OUT_CNT, timeout); + WriteVpuRegister(W4_HW_OPTION, hwOption); + + /* Interrupt */ + regVal = (1 << W4_INT_DEC_PIC_HDR); + regVal |= (1 << W4_INT_DEC_PIC); + regVal |= (1 << W4_INT_QUERY_DEC); + regVal |= (1 << W4_INT_SLEEP_VPU); + regVal |= (1 << W4_INT_BSBUF_EMPTY); + regVal = 0xfffffefe; + WriteVpuRegister(W4_VPU_VINT_ENABLE, regVal); + Wave4BitIssueCommand(core, W4_CMD_INIT_VPU); + WriteVpuRegister(W4_VPU_REMAP_CORE_START, 1); + while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { + if (time_after(jiffies, timeout)) + goto DONE_WAKEUP; + } + + if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { + enc_pr(LOG_ERROR, + "WAKEUP_VPU failed [0x%x]", + ReadVpuRegister(W4_RET_FAIL_REASON)); goto DONE_WAKEUP; - } - - if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { - enc_pr(LOG_ERROR, - "WAKEUP_VPU failed [0x%x]", - ReadVpuRegister(W4_RET_FAIL_REASON)); - goto DONE_WAKEUP; + } } } @@ -1988,7 +1988,8 @@ static s32 __init vpu_init(void) if ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) - && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B)) { + && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) + && (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) { enc_pr(LOG_DEBUG, "The chip is not support hevc encoder\n"); return -1; @@ -2010,8 +2011,16 @@ static s32 __init vpu_init(void) static void __exit vpu_exit(void) { enc_pr(LOG_DEBUG, "vpu_exit\n"); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) - platform_driver_unregister(&vpu_driver); + if ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) { + enc_pr(LOG_INFO, + "The chip is not support hevc encoder\n"); + return; + } + platform_driver_unregister(&vpu_driver); } static const struct reserved_mem_ops rmem_hevc_ops = { diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h index 9c29a430f4e0..eaf764c1c4b3 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h @@ -101,6 +101,7 @@ READ_HHI_REG(HHI_WAVE420L_CLK_CNTL2) \ & (~(1 << 8))) +#ifdef CONFIG_COMPAT struct compat_vpudrv_buffer_t { u32 size; u32 cached; @@ -108,6 +109,7 @@ struct compat_vpudrv_buffer_t { compat_ulong_t base; /* kernel logical address in use kernel */ compat_ulong_t virt_addr; /* virtual user space address */ }; +#endif struct vpudrv_buffer_t { u32 size; @@ -204,6 +206,7 @@ struct vpudrv_instance_pool_t { #define VDI_IOCTL_FLUSH_BUFFER \ _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN) +#ifdef CONFIG_COMPAT #define VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32 \ _IOW(VDI_MAGIC, 0, VPUDRV_BUF_LEN32) @@ -224,6 +227,7 @@ struct vpudrv_instance_pool_t { #define VDI_IOCTL_FLUSH_BUFFER32 \ _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN32) +#endif enum { W4_INT_INIT_VPU = 0, diff --git a/drivers/amlogic/media_modules/stream_input/Makefile b/drivers/amlogic/media_modules/stream_input/Makefile index fdc41621e46f..73dfd13058ab 100644 --- a/drivers/amlogic/media_modules/stream_input/Makefile +++ b/drivers/amlogic/media_modules/stream_input/Makefile @@ -1,7 +1,6 @@ obj-m += stream_input.o stream_input-objs += amports/amstream.o -stream_input-objs += amports/amstream_profile.o stream_input-objs += amports/adec.o stream_input-objs += parser/thread_rw.o stream_input-objs += parser/streambuf.o @@ -9,9 +8,10 @@ stream_input-objs += parser/esparser.o stream_input-objs += parser/tsdemux.o stream_input-objs += parser/psparser.o stream_input-objs += parser/rmparser.o +stream_input-objs += subtitle/subtitle.o -obj-y += parser/hw_demux/ -obj-y += tv_frontend/ +obj-$(CONFIG_AMLOGIC_DVB) += parser/hw_demux/ +#obj-y += tv_frontend/ # obj-y += box-frontend/avl6211/ # obj-y += box-frontend/atbm8881/ -# obj-y += box-frontend/avl68xx/ \ No newline at end of file +# obj-y += box-frontend/avl68xx/ diff --git a/drivers/amlogic/media_modules/stream_input/amports/Makefile b/drivers/amlogic/media_modules/stream_input/amports/Makefile index 55fbdce8aa7a..82f5934b5f9b 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/Makefile +++ b/drivers/amlogic/media_modules/stream_input/amports/Makefile @@ -1,2 +1,2 @@ obj-y += amports.o -amports-objs += amstream.o amstream_profile.o adec.o +amports-objs += amstream.o adec.o diff --git a/drivers/amlogic/media_modules/stream_input/amports/adec.c b/drivers/amlogic/media_modules/stream_input/amports/adec.c index b1bd0726fad8..5bca205c4262 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/adec.c +++ b/drivers/amlogic/media_modules/stream_input/amports/adec.c @@ -29,7 +29,7 @@ #include #include #include "amports_priv.h" - +#include "../../common/chips/decoder_cpu_ver_info.h" #define INFO_VALID ((astream_dev) && (astream_dev->format)) struct astream_device_s { @@ -121,13 +121,14 @@ static ssize_t datawidth_show(struct class *class, static ssize_t pts_show(struct class *class, struct class_attribute *attr, char *buf) { - u32 pts; + u32 pts, frame_size; u32 pts_margin = 0; if (astream_dev->samplerate <= 12000) pts_margin = 512; - if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts, pts_margin) >= 0)) + if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts, + &frame_size, pts_margin) >= 0)) return sprintf(buf, "0x%x\n", pts); else return sprintf(buf, "%s\n", na_string); @@ -155,9 +156,13 @@ static struct class astream_class = { }; #if 1 -#define IO_CBUS_PHY_BASE 0xc1100000 +#define IO_CBUS_PHY_BASE 0xc1100000ULL +#define IO_AOBUS_PHY_BASE 0xc8100000ULL #define CBUS_REG_OFFSET(reg) ((reg) << 2) -#define IO_SECBUS_PHY_BASE 0xda000000 +#define IO_SECBUS_PHY_BASE 0xda000000ULL + + +#define IO_AOBUS_PHY_BASE_AFTER_G12A 0xff800000ULL static struct uio_info astream_uio_info = { .name = "astream_uio", @@ -179,13 +184,15 @@ static struct uio_info astream_uio_info = { (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(VCOP_CTRL_REG)), .size = PAGE_SIZE, }, +/* [2] = { .name = "SECBUS", .memtype = UIO_MEM_PHYS, .addr = (IO_SECBUS_PHY_BASE), .size = PAGE_SIZE, }, - [3] = { +*/ + [2] = { .name = "CBUS", .memtype = UIO_MEM_PHYS, .addr = @@ -193,11 +200,17 @@ static struct uio_info astream_uio_info = { &(PAGE_MASK), .size = PAGE_SIZE, }, - [4] = { + [3] = { .name = "CBUS-START", .memtype = UIO_MEM_PHYS, .addr = (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(0x1000)), - .size = PAGE_SIZE * 4, + .size = PAGE_SIZE, + }, + [4] = { + .name = "AOBUS-START", + .memtype = UIO_MEM_PHYS, + .addr = (IO_AOBUS_PHY_BASE), + .size = PAGE_SIZE, }, }, }; @@ -224,12 +237,13 @@ s32 adec_init(struct stream_port_s *port) astream_dev->datawidth = port->adatawidth; /*wmb();don't need it...*/ - if (af <= ARRAY_SIZE(astream_format)) + if (af < ARRAY_SIZE(astream_format)) astream_dev->format = astream_format[af]; else astream_dev->format = NULL; return 0; } +EXPORT_SYMBOL(adec_init); s32 adec_release(enum aformat_e vf) { @@ -242,13 +256,14 @@ s32 adec_release(enum aformat_e vf) return 0; } +EXPORT_SYMBOL(adec_release); int amstream_adec_show_fun(const char *trigger, int id, char *sbuf, int size) { int ret = -1; void *buf, *getbuf = NULL; if (size < PAGE_SIZE) { - void *getbuf = (void *)__get_free_page(GFP_KERNEL); + getbuf = (void *)__get_free_page(GFP_KERNEL); if (!getbuf) return -ENOMEM; buf = getbuf; @@ -275,7 +290,7 @@ int amstream_adec_show_fun(const char *trigger, int id, char *sbuf, int size) ret = -1; } if (ret > 0 && getbuf != NULL) { - int ret = min_t(int, ret, size); + ret = min_t(int, ret, size); strncpy(sbuf, buf, ret); } if (getbuf != NULL) @@ -326,14 +341,18 @@ s32 astream_dev_register(void) goto err_2; } - if (MESON_CPU_MAJOR_ID_TXL < get_cpu_type()) { + if (AM_MESON_CPU_MAJOR_ID_TXL < get_cpu_major_id()) { node = of_find_node_by_path("/codec_io/io_cbus_base"); if (!node) { pr_info("No io_cbus_base node found."); goto err_1; } +#ifdef CONFIG_ARM64_A32 + r = of_property_read_u32_index(node, "reg", 0, &cbus_base); +#else r = of_property_read_u32_index(node, "reg", 1, &cbus_base); +#endif if (r) { pr_info("No find node.\n"); goto err_1; @@ -343,9 +362,11 @@ s32 astream_dev_register(void) astream_dev->offset = -0x100; /*need to offset -0x180 in g12a.*/ - if (MESON_CPU_MAJOR_ID_G12A <= get_cpu_type()) + if (AM_MESON_CPU_MAJOR_ID_G12A <= get_cpu_major_id()) { astream_dev->offset = -0x180; - + /* after G12A chip, the aobus base addr changed */ + astream_uio_info.mem[4].addr = IO_AOBUS_PHY_BASE_AFTER_G12A; + } astream_uio_info.mem[0].addr = (cbus_base + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL + astream_dev->offset)) & (PAGE_MASK); diff --git a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h index 53669a5951a9..b09118d19057 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h +++ b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h @@ -26,6 +26,7 @@ struct port_priv_s { struct vdec_s *vdec; struct stream_port_s *port; + struct mutex mutex; }; struct stream_buf_s *get_buf_by_type(u32 type); @@ -44,6 +45,7 @@ int amstream_request_firmware_from_sys(const char *file_name, void set_vsync_pts_inc_mode(int inc); void set_real_audio_info(void *arg); +void amstream_wakeup_userdata_poll(struct vdec_s *vdec); #define dbg() pr_info("on %s,line %d\n", __func__, __LINE__); struct device *amports_get_dma_device(void); diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream.c b/drivers/amlogic/media_modules/stream_input/amports/amstream.c index 6546633df359..2c0ae399013f 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream.c +++ b/drivers/amlogic/media_modules/stream_input/amports/amstream.c @@ -79,6 +79,8 @@ #include #include "../../frame_provider/decoder/utils/firmware.h" #include "../../common/chips/chips.h" +#include "../../common/chips/decoder_cpu_ver_info.h" +#include "../subtitle/subtitle.h" //#define G12A_BRINGUP_DEBUG @@ -321,6 +323,8 @@ static wait_queue_head_t amstream_userdata_wait; static struct userdata_poc_info_t userdata_poc_info[USERDATA_FIFO_NUM]; static int userdata_poc_ri, userdata_poc_wi; static int last_read_wi; +static u32 ud_ready_vdec_flag; + static DEFINE_MUTEX(userdata_mutex); @@ -600,17 +604,16 @@ static int video_port_init(struct port_priv_s *priv, pr_err("vformat not set\n"); return -EPERM; } - + if (vdec_dual(vdec) && vdec_secure(vdec)) { + /*copy drm flags for slave dec.*/ + vdec->slave->port_flag |= PORT_FLAG_DRM; + } if (port->vformat == VFORMAT_H264_4K2K || (priv->vdec->sys_info->height * priv->vdec->sys_info->width) > 1920*1088) { pbuf->for_4k = 1; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX && port->vformat == VFORMAT_H264) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); - vdec_poweron(VDEC_HEVC); } } else { @@ -682,8 +685,6 @@ static int video_port_init(struct port_priv_s *priv, pbuf->flag |= BUF_FLAG_IN_USE; - vdec_connect(priv->vdec); - return 0; } @@ -875,7 +876,7 @@ static int amstream_port_init(struct port_priv_s *priv) mutex_lock(&amstream_mutex); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { r = check_efuse_chip(port->vformat); if (r) { pr_info("No support video format %d.\n", port->vformat); @@ -916,11 +917,14 @@ static int amstream_port_init(struct port_priv_s *priv) port->vformat == VFORMAT_VP9) pvbuf = &bufs[BUF_TYPE_HEVC]; } + mutex_lock(&priv->mutex); r = video_port_init(priv, pvbuf); if (r < 0) { + mutex_unlock(&priv->mutex); pr_err("video_port_init failed\n"); goto error2; } + mutex_unlock(&priv->mutex); } if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) { @@ -1025,6 +1029,7 @@ static int amstream_port_release(struct port_priv_s *priv) } if (port->type & PORT_TYPE_MPTS) { + vdec_disconnect(priv->vdec); tsync_pcr_stop(); tsdemux_release(); } @@ -1264,8 +1269,7 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, res = copy_to_user((void *)buf, (void *)(codec_mm_phys_to_virt(sub_rp)), data_size); - if (res >= 0) - stbuf_sub_rp_set(sub_rp + data_size - res); + stbuf_sub_rp_set(sub_rp + data_size - res); return data_size - res; } else { @@ -1273,10 +1277,8 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, res = copy_to_user((void *)buf, (void *)(codec_mm_phys_to_virt(sub_rp)), first_num); - if (res >= 0) { - stbuf_sub_rp_set(sub_rp + first_num - - res); - } + stbuf_sub_rp_set(sub_rp + first_num - + res); return first_num - res; } @@ -1285,10 +1287,8 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, (void *)(codec_mm_phys_to_virt(sub_start)), data_size - first_num); - if (res >= 0) { - stbuf_sub_rp_set(sub_start + data_size - - first_num - res); - } + stbuf_sub_rp_set(sub_start + data_size - + first_num - res); return data_size - first_num - res; } @@ -1298,8 +1298,7 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, (void *)(codec_mm_phys_to_virt(sub_rp)), data_size); - if (res >= 0) - stbuf_sub_rp_set(sub_rp + data_size - res); + stbuf_sub_rp_set(sub_rp + data_size - res); return data_size - res; } @@ -1414,6 +1413,28 @@ int wakeup_userdata_poll(struct userdata_poc_info_t poc, } EXPORT_SYMBOL(wakeup_userdata_poll); + +void amstream_wakeup_userdata_poll(struct vdec_s *vdec) +{ + int vdec_id; + + vdec_id = vdec->id; + if (vdec_id > 31) { + pr_info("Error, not support so many instances(%d) user data push\n", + vdec_id); + return; + } + + mutex_lock(&userdata_mutex); + ud_ready_vdec_flag |= (1<mutex); + priv->port = port; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /* TODO: mod gate */ /* switch_mod_gate_by_name("demux", 1); */ amports_switch_gate("demux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { /* TODO: clc gate */ /* CLK_GATE_ON(HIU_PARSER_TOP); */ amports_switch_gate("parser_top", 1); @@ -1615,22 +1638,14 @@ static int amstream_open(struct inode *inode, struct file *file) if (has_hevc_vdec()) { if (port->type & - (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); + (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) vdec_poweron(VDEC_HEVC); - } - if ((port->type & PORT_TYPE_HEVC) == 0) { - amports_switch_gate("clk_vdec_mux", 1); + if ((port->type & PORT_TYPE_HEVC) == 0) vdec_poweron(VDEC_1); - } } else { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { - amports_switch_gate("clk_vdec_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) vdec_poweron(VDEC_1); - } } } @@ -1738,16 +1753,16 @@ static int amstream_release(struct inode *inode, struct file *file) debug_file_pos = 0; } #endif - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { if (port->type & PORT_TYPE_VIDEO) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC if (has_hevc_vdec()) vdec_poweroff(VDEC_HEVC); vdec_poweroff(VDEC_1); #else - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX && port->vformat == VFORMAT_H264 && bufs[BUF_TYPE_VIDEO].for_4k) vdec_poweroff(VDEC_HEVC); @@ -1772,7 +1787,7 @@ static int amstream_release(struct inode *inode, struct file *file) /* amports_switch_gate("audio", 0); */ } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { /* TODO: clc gate */ /* CLK_GATE_OFF(HIU_PARSER_TOP); */ amports_switch_gate("parser_top", 0); @@ -1782,6 +1797,8 @@ static int amstream_release(struct inode *inode, struct file *file) amports_switch_gate("demux", 0); } + mutex_destroy(&priv->mutex); + kfree(priv); mutex_unlock(&amstream_mutex); @@ -1839,10 +1856,11 @@ static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg) break; case AMSTREAM_GET_APTS_LOOKUP: if (this->type & PORT_TYPE_AUDIO) { - u32 pts = 0, offset; + u32 pts = 0, frame_size, offset; offset = parm.data_32; - pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, 300); + pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, + &frame_size, 300); parm.data_32 = pts; } break; @@ -1935,6 +1953,9 @@ static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg) case AMSTREAM_GET_NEED_MORE_DATA: parm.data_32 = vdec_need_more_data(priv->vdec); break; + case AMSTREAM_GET_FREED_HANDLE: + parm.data_32 = vdec_input_get_freed_handle(priv->vdec); + break; default: r = -ENOIOCTLCMD; break; @@ -1979,7 +2000,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) parm.data_32, false); } - r = stbuf_change_size( + r += stbuf_change_size( &bufs[BUF_TYPE_VIDEO], parm.data_32, false); @@ -2169,10 +2190,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) tsync_set_dec_reset(); break; case AMSTREAM_SET_TS_SKIPBYTE: - if (parm.data_32 >= 0) - tsdemux_set_skipbyte(parm.data_32); - else - r = -EINVAL; + tsdemux_set_skipbyte(parm.data_32); break; case AMSTREAM_SET_SUB_TYPE: sub_type = parm.data_32; @@ -2251,6 +2269,34 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) } return r; } + +static enum E_ASPECT_RATIO get_normalized_aspect_ratio(u32 ratio_control) +{ + enum E_ASPECT_RATIO euAspectRatio; + + ratio_control = ratio_control >> DISP_RATIO_ASPECT_RATIO_BIT; + + switch (ratio_control) { + case 0x8c: + case 0x90: + euAspectRatio = ASPECT_RATIO_16_9; + /*pr_info("ASPECT_RATIO_16_9\n");*/ + break; + case 0xbb: + case 0xc0: + euAspectRatio = ASPECT_RATIO_4_3; + /*pr_info("ASPECT_RATIO_4_3\n");*/ + break; + default: + euAspectRatio = ASPECT_UNDEFINED; + /*pr_info("ASPECT_UNDEFINED and ratio_control = 0x%x\n", + ratio_control);*/ + break; + } + + return euAspectRatio; +} + static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) { struct stream_port_s *this = priv->port; @@ -2274,11 +2320,6 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; - if (p == NULL) { - r = -EINVAL; - break; - } - if (this->type & PORT_TYPE_FRAME) { struct vdec_input_status_s status; @@ -2315,8 +2356,6 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) struct am_ioctl_parm_ex *p = &parm; struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; - if (p == NULL) - r = -EINVAL; p->status.size = stbuf_canusesize(buf); p->status.data_len = stbuf_level(buf); @@ -2334,15 +2373,24 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) struct vdec_info vstatus; struct am_ioctl_parm_ex *p = &parm; - if (p == NULL) - return -EINVAL; - if (vdec_status(priv->vdec, &vstatus) == -1) + memset(&vstatus, 0, sizeof(vstatus)); + + mutex_lock(&priv->mutex); + if (vdec_status(priv->vdec, &vstatus) == -1) { + mutex_unlock(&priv->mutex); return -ENODEV; + } + mutex_unlock(&priv->mutex); + p->vstatus.width = vstatus.frame_width; p->vstatus.height = vstatus.frame_height; p->vstatus.fps = vstatus.frame_rate; p->vstatus.error_count = vstatus.error_count; p->vstatus.status = vstatus.status; + p->vstatus.euAspectRatio = + get_normalized_aspect_ratio( + vstatus.ratio_control); + } break; case AMSTREAM_GET_EX_ADECSTAT: @@ -2360,8 +2408,6 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) struct adec_status astatus; struct am_ioctl_parm_ex *p = &parm; - if (p == NULL) - return -EINVAL; amstream_adec_status(&astatus); p->astatus.channels = astatus.channels; p->astatus.sample_rate = astatus.sample_rate; @@ -2411,7 +2457,7 @@ static long amstream_ioctl_get_ptr(struct port_priv_s *priv, ulong arg) if (copy_from_user ((void *)&parm, (void *)arg, sizeof(parm))) - r = -EFAULT; + return -EFAULT; switch (parm.cmd) { case AMSTREAM_GET_PTR_SUB_INFO: @@ -2461,10 +2507,14 @@ static long amstream_ioctl_set_ptr(struct port_priv_s *priv, ulong arg) case AMSTREAM_SET_PTR_AUDIO_INFO: if ((this->type & PORT_TYPE_VIDEO) || (this->type & PORT_TYPE_AUDIO)) { - if (parm.pdata_audio_info != NULL) - memcpy((void *)&audio_dec_info, - (void *)parm.pdata_audio_info, - sizeof(audio_dec_info)); + if (parm.pdata_audio_info != NULL) { + if (copy_from_user + ((void *)&audio_dec_info, (void *)parm.pdata_audio_info, + sizeof(audio_dec_info))) { + pr_err("[%s]%d, arg err\n", __func__, __LINE__); + r = -EFAULT; + } + } } else r = -EINVAL; break; @@ -2525,6 +2575,20 @@ static long amstream_do_ioctl_new(struct port_priv_s *priv, else r = -EINVAL; break; + case AMSTREAM_IOC_GET_QOSINFO: + { + struct av_param_qosinfo_t __user *uarg = (void *)arg; + struct vframe_qos_s *qos_info = vdec_get_qos_info(); + if (this->type & PORT_TYPE_VIDEO) { + if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos, + qos_info, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) { + r = -EFAULT; + break; + } + } + } + break; default: r = -ENOIOCTLCMD; break; @@ -2560,7 +2624,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, &bufs[BUF_TYPE_HEVC], arg, false); } - r = stbuf_change_size( + r += stbuf_change_size( &bufs[BUF_TYPE_VIDEO], arg, false); } @@ -2660,11 +2724,6 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; - if (p == NULL) { - r = -EINVAL; - break; - } - if (this->type & PORT_TYPE_FRAME) { struct vdec_input_status_s status; @@ -2709,9 +2768,6 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct am_io_param *p = ¶ struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; - if (p == NULL) - r = -EINVAL; - p->status.size = stbuf_canusesize(buf); p->status.data_len = stbuf_level(buf); p->status.free_len = stbuf_space(buf); @@ -2815,15 +2871,24 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct am_io_param para; struct am_io_param *p = ¶ - if (p == NULL) - return -EINVAL; - if (vdec_status(priv->vdec, &vstatus) == -1) + memset(&vstatus, 0, sizeof(vstatus)); + + mutex_lock(&priv->mutex); + if (vdec_status(priv->vdec, &vstatus) == -1) { + mutex_unlock(&priv->mutex); return -ENODEV; + } + mutex_unlock(&priv->mutex); + p->vstatus.width = vstatus.frame_width; p->vstatus.height = vstatus.frame_height; p->vstatus.fps = vstatus.frame_rate; p->vstatus.error_count = vstatus.error_count; p->vstatus.status = vstatus.status; + p->vstatus.euAspectRatio = + get_normalized_aspect_ratio( + vstatus.ratio_control); + if (copy_to_user((void *)arg, p, sizeof(para))) r = -EFAULT; return r; @@ -2836,8 +2901,15 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct vdec_info vinfo; struct am_io_info para; - if (vdec_status(priv->vdec, &vinfo) == -1) + memset(¶, 0x0, sizeof(struct am_io_info)); + + mutex_lock(&priv->mutex); + if (vdec_status(priv->vdec, &vinfo) == -1) { + mutex_unlock(&priv->mutex); return -ENODEV; + } + mutex_unlock(&priv->mutex); + memcpy(¶.vinfo, &vinfo, sizeof(struct vdec_info)); if (copy_to_user((void *)arg, ¶, sizeof(para))) r = -EFAULT; @@ -2854,8 +2926,6 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct am_io_param para; struct am_io_param *p = ¶ - if (p == NULL) - return -EINVAL; amstream_adec_status(&astatus); p->astatus.channels = astatus.channels; p->astatus.sample_rate = astatus.sample_rate; @@ -2993,10 +3063,72 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, } break; + case AMSTREAM_IOC_UD_BUF_READ: + { + if (this->type & PORT_TYPE_USERDATA) { + struct userdata_param_t param; + struct userdata_param_t *p_userdata_param; + struct vdec_s *vdec; + + p_userdata_param = ¶m; + + if (copy_from_user(p_userdata_param, + (void __user *)arg, + sizeof(struct userdata_param_t))) { + r = -EFAULT; + break; + } + + vdec = vdec_get_vdec_by_id(p_userdata_param->instance_id); + if (vdec) { + if (vdec_read_user_data(vdec, + p_userdata_param) == 0) { + r = -EFAULT; + break; + } + + if (copy_to_user((void *)arg, + p_userdata_param, + sizeof(struct userdata_param_t))) + r = -EFAULT; + } else + r = -EINVAL; + } + } + break; + + case AMSTREAM_IOC_UD_AVAILABLE_VDEC: + { + unsigned int ready_vdec; + + mutex_lock(&userdata_mutex); + ready_vdec = ud_ready_vdec_flag; + ud_ready_vdec_flag = 0; + mutex_unlock(&userdata_mutex); + + put_user(ready_vdec, (uint32_t __user *)arg); + } + break; + + case AMSTREAM_IOC_GET_VDEC_ID: + if (this->type & PORT_TYPE_VIDEO && priv->vdec) { + put_user(priv->vdec->id, (int32_t __user *)arg); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_UD_FLUSH_USERDATA: if (this->type & PORT_TYPE_USERDATA) { - reset_userdata_fifo(0); - pr_info("reset_userdata_fifo\n"); + struct vdec_s *vdec; + int vdec_id; + + get_user(vdec_id, (int __user *)arg); + vdec = vdec_get_vdec_by_id(vdec_id); + if (vdec) { + vdec_reset_userdata_fifo(vdec, 0); + pr_info("reset_userdata_fifo for vdec: %d\n", vdec_id); + } } else r = -EINVAL; break; @@ -3018,10 +3150,11 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, case AMSTREAM_IOC_APTS_LOOKUP: if (this->type & PORT_TYPE_AUDIO) { - u32 pts = 0, offset; + u32 pts = 0, frame_size, offset; get_user(offset, (unsigned long __user *)arg); - pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, 300); + pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, + &frame_size, 300); put_user(pts, (int __user *)arg); } return 0; @@ -3193,6 +3326,7 @@ static long amstream_do_ioctl(struct port_priv_s *priv, case AMSTREAM_IOC_GET_PTR: case AMSTREAM_IOC_SET_PTR: case AMSTREAM_IOC_SYSINFO: + case AMSTREAM_IOC_GET_QOSINFO: r = amstream_do_ioctl_new(priv, cmd, arg); break; default: @@ -3252,19 +3386,23 @@ static long amstream_ioc_setget_ptr(struct port_priv_s *priv, unsigned int cmd, struct am_ioctl_parm_ptr32 __user *arg) { struct am_ioctl_parm_ptr __user *data; - struct am_ioctl_parm_ptr32 __user *data32 = arg; + struct am_ioctl_parm_ptr32 param; int ret; + if (copy_from_user(¶m, + (void __user *)arg, + sizeof(struct am_ioctl_parm_ptr32))) + return -EFAULT; + data = compat_alloc_user_space(sizeof(*data)); if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) return -EFAULT; - if (put_user(data32->cmd, &data->cmd) || - put_user(compat_ptr(data32->pointer), &data->pointer) || - put_user(data32->len, &data->len)) + if (put_user(param.cmd, &data->cmd) || + put_user(compat_ptr(param.pointer), &data->pointer) || + put_user(param.len, &data->len)) return -EFAULT; - ret = amstream_do_ioctl(priv, cmd, (unsigned long)data); if (ret < 0) return ret; @@ -3278,13 +3416,19 @@ static long amstream_set_sysinfo(struct port_priv_s *priv, struct dec_sysinfo __user *data; struct dec_sysinfo32 __user *data32 = arg; int ret; + struct dec_sysinfo32 param; + + if (copy_from_user(¶m, + (void __user *)arg, + sizeof(struct dec_sysinfo32))) + return -EFAULT; data = compat_alloc_user_space(sizeof(*data)); if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) return -EFAULT; if (copy_in_user(data, data32, 7 * sizeof(u32))) return -EFAULT; - if (put_user(compat_ptr(data32->param), &data->param)) + if (put_user(compat_ptr(param.param), &data->param)) return -EFAULT; if (copy_in_user(&data->ratio64, &data32->ratio64, sizeof(data->ratio64))) @@ -3302,6 +3446,60 @@ static long amstream_set_sysinfo(struct port_priv_s *priv, return 0; } + + +struct userdata_param32_t { + uint32_t version; + uint32_t instance_id; /*input, 0~9*/ + uint32_t buf_len; /*input*/ + uint32_t data_size; /*output*/ + compat_uptr_t pbuf_addr; /*input*/ + struct userdata_meta_info_t meta_info; /*output*/ +}; + + +static long amstream_ioc_get_userdata(struct port_priv_s *priv, + struct userdata_param32_t __user *arg) +{ + struct userdata_param_t __user *data; + struct userdata_param32_t __user *data32 = arg; + int ret; + struct userdata_param32_t param; + + + if (copy_from_user(¶m, + (void __user *)arg, + sizeof(struct userdata_param32_t))) + return -EFAULT; + + data = compat_alloc_user_space(sizeof(*data)); + if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) + return -EFAULT; + + if (copy_in_user(data, data32, 4 * sizeof(u32))) + return -EFAULT; + + if (copy_in_user(&data->meta_info, &data32->meta_info, + sizeof(data->meta_info))) + return -EFAULT; + + if (put_user(compat_ptr(param.pbuf_addr), &data->pbuf_addr)) + return -EFAULT; + + ret = amstream_do_ioctl(priv, AMSTREAM_IOC_UD_BUF_READ, + (unsigned long)data); + if (ret < 0) + return ret; + + if (copy_in_user(&data32->version, &data->version, 4 * sizeof(u32)) || + copy_in_user(&data32->meta_info, &data->meta_info, + sizeof(data32->meta_info))) + return -EFAULT; + + return 0; +} + + static long amstream_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) { @@ -3320,6 +3518,8 @@ static long amstream_compat_ioctl(struct file *file, return amstream_ioc_setget_ptr(priv, cmd, compat_ptr(arg)); case AMSTREAM_IOC_SYSINFO: return amstream_set_sysinfo(priv, compat_ptr(arg)); + case AMSTREAM_IOC_UD_BUF_READ: + return amstream_ioc_get_userdata(priv, compat_ptr(arg)); default: return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg)); } @@ -3438,7 +3638,7 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr, "\tbuf regbase:%#lx\n", p->reg_base); if (p->reg_base && p->flag & BUF_FLAG_IN_USE) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /* TODO: mod gate */ /* switch_mod_gate_by_name("vdec", 1);*/ amports_switch_gate("vdec", 1); @@ -3450,7 +3650,7 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr, pbuf += sprintf(pbuf, "\tbuf read pointer:%#x\n", stbuf_rp(p)); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /* TODO: mod gate */ /* switch_mod_gate_by_name("vdec", 0);*/ amports_switch_gate("vdec", 0); @@ -3797,7 +3997,7 @@ static int amstream_probe(struct platform_device *pdev) REG_PATH_CONFIGS("media.amports", amports_configs); /* poweroff the decode core because dos can not be reset when reboot */ - if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) + if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_G12A) vdec_power_reset(); return 0; @@ -3899,12 +4099,19 @@ static int __init amstream_module_init(void) pr_err("failed to register amstream module\n"); return -ENODEV; } + + if (subtitle_init()) { + pr_err("failed to init subtitle\n"); + return -ENODEV; + } + return 0; } static void __exit amstream_module_exit(void) { platform_driver_unregister(&amstream_driver); + subtitle_exit(); } module_init(amstream_module_init); diff --git a/drivers/amlogic/media_modules/stream_input/parser/esparser.c b/drivers/amlogic/media_modules/stream_input/parser/esparser.c index f04b9decb969..1cf8f02e056b 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/esparser.c +++ b/drivers/amlogic/media_modules/stream_input/parser/esparser.c @@ -61,6 +61,9 @@ #define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START) #define PARSER_BUSY (ES_PARSER_BUSY) +#define MAX_DRM_PACKAGE_SIZE 0x500000 + + static unsigned char *search_pattern; static dma_addr_t search_pattern_map; static u32 audio_real_wp; @@ -151,7 +154,7 @@ static inline u32 buf_wp(u32 type) } static ssize_t _esparser_write(const char __user *buf, - size_t count, u32 type, int isphybuf) + size_t count, struct stream_buf_s *stbuf, int isphybuf) { size_t r = count; const char __user *p = buf; @@ -161,6 +164,7 @@ static ssize_t _esparser_write(const char __user *buf, int ret; u32 wp; dma_addr_t dma_addr = 0; + u32 type = stbuf->type; if (type == BUF_TYPE_HEVC) parser_type = PARSER_VIDEO; @@ -245,11 +249,12 @@ static ssize_t _esparser_write(const char __user *buf, else if (type == BUF_TYPE_AUDIO) audio_data_parsed += len; + threadrw_update_buffer_level(stbuf, len); return len; } static ssize_t _esparser_write_s(const char __user *buf, - size_t count, u32 type) + size_t count, struct stream_buf_s *stbuf) { size_t r = count; const char __user *p = buf; @@ -257,6 +262,7 @@ static ssize_t _esparser_write_s(const char __user *buf, int ret; u32 wp, buf_start, buf_end; dma_addr_t buf_wp_map; + u32 type = stbuf->type; if (type != BUF_TYPE_AUDIO) BUG(); @@ -310,7 +316,10 @@ static ssize_t _esparser_write_s(const char __user *buf, end_write: if (type == BUF_TYPE_AUDIO) + { audio_data_parsed += len; + threadrw_update_buffer_level(stbuf, len); + } return len; } @@ -347,7 +356,11 @@ s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts) return 0; } #endif - u32 passed = video_data_parsed + threadrw_buffer_level(buf); + u32 passed = 0; + + mutex_lock(&esparser_mutex); + passed = video_data_parsed + threadrw_buffer_level(buf); + mutex_unlock(&esparser_mutex); return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts); @@ -363,7 +376,10 @@ s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts) return 0; } #endif - u32 passed = audio_data_parsed + threadrw_buffer_level(buf); + u32 passed = 0; + mutex_lock(&esparser_mutex); + passed = audio_data_parsed + threadrw_buffer_level(buf); + mutex_unlock(&esparser_mutex); return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts); } @@ -609,6 +625,7 @@ Err_1: mutex_unlock(&esparser_mutex); return r; } +EXPORT_SYMBOL(esparser_init); void esparser_audio_reset_s(struct stream_buf_s *buf) { @@ -714,6 +731,7 @@ void esparser_release(struct stream_buf_s *buf) buf->flag &= ~BUF_FLAG_PARSER; pts_stop(pts_type); } +EXPORT_SYMBOL(esparser_release); ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, const char __user *buf, size_t count) @@ -745,6 +763,10 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, } if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) { + if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) { + pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); + return -EINVAL; + } /* buf only has drminfo not have esdata; */ realbuf = drm->drm_phy; realcount = drm->drm_pktsize; @@ -755,6 +777,10 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, *drm->drm_hasesdata,stbuf->type,buf); */ } else if (drm->drm_hasesdata == 1) { /* buf is drminfo+es; */ + if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) { + pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); + return -EINVAL; + } realcount = drm->drm_pktsize; realbuf = (unsigned long)buf + sizeof(struct drm_info); isphybuf = 0; @@ -781,7 +807,9 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) { /*should not write partial data in drm mode*/ - stbuf_wait_space(stbuf, count); + r = stbuf_wait_space(stbuf, count); + if (r < 0) + return r; if (stbuf_space(stbuf) < count) return -EAGAIN; } @@ -791,12 +819,13 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, if (stbuf->type != BUF_TYPE_AUDIO) r = _esparser_write((const char __user *)realbuf, len, - stbuf->type, isphybuf); + stbuf, isphybuf); else r = _esparser_write_s((const char __user *)realbuf, len, - stbuf->type); + stbuf); if (r < 0) { pr_info("drm_write _esparser_write failed [%d]\n", r); + mutex_unlock(&esparser_mutex); return r; } havewritebytes += r; @@ -821,6 +850,8 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, return re_count; } +EXPORT_SYMBOL(drm_write); + /* *flags: *1:phy @@ -864,9 +895,9 @@ ssize_t esparser_write_ex(struct file *file, mutex_lock(&esparser_mutex); if (stbuf->type == BUF_TYPE_AUDIO) - r = _esparser_write_s(buf, len, stbuf->type); + r = _esparser_write_s(buf, len, stbuf); else - r = _esparser_write(buf, len, stbuf->type, flags & 1); + r = _esparser_write(buf, len, stbuf, flags & 1); mutex_unlock(&esparser_mutex); @@ -914,7 +945,7 @@ ssize_t esparser_write(struct file *file, } return esparser_write_ex(file, stbuf, buf, count, 0); } - +EXPORT_SYMBOL(esparser_write); void esparser_sub_reset(void) { diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile index e0315940b63a..594f78f42e12 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile @@ -5,4 +5,4 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core -I$(srctree)/drivers/gpio -I$(s aml_hardware_dmx-objs += aml_dvb.o aml_hardware_dmx-objs += aml_dmx.o -#obj-y += dvb_ci/ +obj-y += dvb_ci/ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h index b923798f02ed..3a5b3b0d7496 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __AML_DEMOD_GT_H__ #define __AML_DEMOD_GT_H__ @@ -18,22 +37,41 @@ struct amlfe_demod_config { int reset_value; }; +/* For configure different tuners */ +/* It can add fields as extensions */ +struct tuner_config { + u8 id; + u8 i2c_addr; + u8 xtal; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + u8 xtal_cap; + u8 xtal_mode; +}; + static inline struct dvb_frontend* aml_dtvdm_attach (const struct amlfe_exp_config *config) { return NULL; } -static inline struct dvb_frontend* si2151_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c,u8 i2c_addr/*, - struct si2151_config *cfg*/) +static inline struct dvb_frontend* si2151_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c, struct tuner_config *cfg) { return NULL; } -static inline struct dvb_frontend* mxl661_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c,u8 i2c_addr/*, - struct mxl661_config *cfg*/) + +static inline struct dvb_frontend* mxl661_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c, struct tuner_config *cfg) { return NULL; } -static inline struct dvb_frontend* si2159_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c,u8 i2c_addr/*, - struct si2159_config *cfg*/) + +static inline struct dvb_frontend* si2159_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c, struct tuner_config *cfg) +{ + return NULL; +} + +static inline struct dvb_frontend* r842_attach (struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tuner_config *cfg) +{ + return NULL; +} + +static inline struct dvb_frontend* r840_attach (struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tuner_config *cfg) { return NULL; } @@ -43,4 +81,9 @@ static inline struct dvb_frontend* atbm8881_attach (const struct amlfe_demod_con return NULL; } +static inline struct dvb_frontend* si2168_attach (const struct amlfe_demod_config *config) +{ + return NULL; +} + #endif /*__AML_DEMOD_GT_H__*/ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c index e5226ccde533..3b2b9a7106f3 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * AMLOGIC demux driver. */ @@ -24,7 +43,7 @@ #include #include #include - +#include #include "../streambuf.h" #include "c_stb_define.h" #include "c_stb_regs_define.h" @@ -207,7 +226,6 @@ dmx_write_reg(int r, u32 v) return; } } - WRITE_MPEG_REG(r, v); } @@ -234,14 +252,17 @@ dmx_write_reg(int r, u32 v) #define WRITE_PERI_REG WRITE_CBUS_REG #define READ_ASYNC_FIFO_REG(i, r)\ - ((i) ? READ_PERI_REG(ASYNC_FIFO2_##r) : READ_PERI_REG(ASYNC_FIFO_##r)) + ((i) ? ((i-1)?READ_PERI_REG(ASYNC_FIFO1_##r):\ + READ_PERI_REG(ASYNC_FIFO2_##r)) : READ_PERI_REG(ASYNC_FIFO_##r)) #define WRITE_ASYNC_FIFO_REG(i, r, d)\ do {\ - if (i == 1) {\ - WRITE_PERI_REG(ASYNC_FIFO2_##r, d);\ - } else {\ + if (i == 2) {\ + WRITE_PERI_REG(ASYNC_FIFO1_##r, d);\ + } else if (i == 0) {\ WRITE_PERI_REG(ASYNC_FIFO_##r, d);\ + } else {\ + WRITE_PERI_REG(ASYNC_FIFO2_##r, d);\ } \ } while (0) @@ -287,13 +308,10 @@ static inline int _set(int v, int b) { return b; } static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key); -static int dsc_set_aes_key(struct aml_dsc_channel *ch, int flags, +static int dsc_set_aes_des_sm4_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key); - -static void aml_ci_plus_disable_output(void); static void aml_ci_plus_disable(void); static void am_ci_plus_set_output(struct aml_dsc_channel *ch); -static void aml_ci_plus_enable(void); static void dmxn_op_chan(int dmx, int ch, int(*op)(int, int), int ch_op) { @@ -417,10 +435,13 @@ static int dmx_timeout_set(struct aml_dmxtimeout *dto, int enable, /*Audio & Video PTS value*/ static u32 video_pts; static u32 audio_pts; +static u32 video_pts_bit32; +static u32 audio_pts_bit32; static u32 first_video_pts; static u32 first_audio_pts; static int demux_skipbyte; static int tsfile_clkdiv = 4; +static int asyncfifo_buf_len = ASYNCFIFO_BUFFER_SIZE_DEFAULT; #define SF_DMX_ID 2 #define SF_AFIFO_ID 1 @@ -1109,10 +1130,14 @@ static void process_sub(struct aml_dmx *dmx) pr_dbg("sub no data\n"); } - if (buffer1) - buffer1_virt = phys_to_virt(buffer1); - if (buffer2) - buffer2_virt = phys_to_virt(buffer2); + if (buffer1 && len1) + buffer1_virt = codec_mm_phys_to_virt(buffer1); + + if (buffer2 && len2) + buffer2_virt = codec_mm_phys_to_virt(buffer2); + +// printk("rd_ptr %p buffer1 %p len1 %d buffer2 %p len2 %d buffer1_virt %p buffer2_virt %p\n", +// (void*)rd_ptr, (void*)buffer1, len1, (void*)buffer2, len2, buffer1_virt, buffer2_virt); if (len1) dma_sync_single_for_cpu(dmx_get_dev(dmx), @@ -1124,7 +1149,9 @@ static void process_sub(struct aml_dmx *dmx) DMA_FROM_DEVICE); if (dmx->channel[2].used) { - if (dmx->channel[2].feed && dmx->channel[2].feed->cb.ts) { + if (dmx->channel[2].feed && dmx->channel[2].feed->cb.ts && + ((buffer1_virt != NULL && len1 !=0 ) | (buffer2_virt != NULL && len2 != 0))) + { dmx->channel[2].feed->cb.ts(buffer1_virt, len1, buffer2_virt, len2, &dmx->channel[2].feed->feed.ts); @@ -1282,6 +1309,8 @@ static irqreturn_t dmx_irq_handler(int irq_number, void *para) if (pdts_status & (1 << VIDEO_PTS_READY)) { video_pts = DMX_READ_REG(dmx->id, VIDEO_PTS_DEMUX); + video_pts_bit32 = + (status & (1 << VIDEO_PTS_BIT32)) ? 1 : 0; if (!first_video_pts || 0 > (int)(video_pts - first_video_pts)) first_video_pts = video_pts; @@ -1289,6 +1318,8 @@ static irqreturn_t dmx_irq_handler(int irq_number, void *para) if (pdts_status & (1 << AUDIO_PTS_READY)) { audio_pts = DMX_READ_REG(dmx->id, AUDIO_PTS_DEMUX); + audio_pts_bit32 = + (status & (1 << AUDIO_PTS_BIT32)) ? 1 : 0; if (!first_audio_pts || 0 > (int)(audio_pts - first_audio_pts)) first_audio_pts = audio_pts; @@ -1358,9 +1389,11 @@ static void dvr_process_channel(struct aml_asyncfifo *afifo, { int cnt; int ret = 0; + struct aml_dvr_block blk; if (afifo->buf_read > afifo->buf_toggle) { cnt = total - afifo->buf_read; + if (!afifo->secure_enable) { dma_sync_single_for_cpu(asyncfifo_get_dev(afifo), afifo->pages_map+afifo->buf_read*size, cnt*size, @@ -1374,11 +1407,27 @@ static void dvr_process_channel(struct aml_asyncfifo *afifo, (u8 *)afifo->pages+afifo->buf_read*size, cnt*size, NULL, 0, &channel->dvr_feed->feed.ts); + } else { + blk.addr = afifo->blk.addr+afifo->buf_read*size; + blk.len = cnt*size; + if (sf) + ret = _rbuf_write(&sf->rbuf, + (u8 *)afifo->pages+afifo->buf_read*size, + cnt*size); + else { + channel->dvr_feed->cb.ts( + (u8 *)&blk, + sizeof(struct aml_dvr_block), + NULL, 0, + &channel->dvr_feed->feed.ts); + } + } afifo->buf_read = 0; } if (afifo->buf_toggle > afifo->buf_read) { cnt = afifo->buf_toggle - afifo->buf_read; + if (!afifo->secure_enable) { dma_sync_single_for_cpu(asyncfifo_get_dev(afifo), afifo->pages_map+afifo->buf_read*size, cnt*size, @@ -1388,11 +1437,27 @@ static void dvr_process_channel(struct aml_asyncfifo *afifo, ret = _rbuf_write(&sf->rbuf, (u8 *)afifo->pages+afifo->buf_read*size, cnt*size); - } else + } else { channel->dvr_feed->cb.ts( (u8 *)afifo->pages+afifo->buf_read*size, cnt*size, NULL, 0, + &channel->dvr_feed->feed.ts); + } + } else { + blk.addr = afifo->blk.addr+afifo->buf_read*size; + blk.len = cnt*size; + if (sf) + ret = _rbuf_write(&sf->rbuf, + (u8 *)afifo->pages+afifo->buf_read*size, + cnt*size); + else { + channel->dvr_feed->cb.ts( + (u8 *)&blk, + sizeof(struct aml_dvr_block), + NULL, 0, &channel->dvr_feed->feed.ts); + } + } afifo->buf_read = afifo->buf_toggle; } @@ -1421,6 +1486,7 @@ static void dvr_irq_bh_handler(unsigned long arg) if (dvb && afifo->source >= AM_DMX_0 && afifo->source < AM_DMX_MAX) { dmx = &dvb->dmx[afifo->source]; + // pr_inf("async fifo %d irq, source:%d\n", afifo->id,afifo->source); if (dmx->init && dmx->record) { struct aml_swfilter *sf = &dvb->swfilter; int issf = 0; @@ -1465,8 +1531,8 @@ static void stb_enable(struct aml_dvb *dvb) { int out_src, des_in, en_des, fec_clk, hiu, dec_clk_en; int src, tso_src, i; - u32 fec_s0, fec_s1; - u32 invert0, invert1; + u32 fec_s0, fec_s1,fec_s2; + u32 invert0, invert1, invert2; u32 data; switch (dvb->stb_source) { @@ -1497,6 +1563,10 @@ static void stb_enable(struct aml_dvb *dvb) fec_clk = tsfile_clkdiv; hiu = 0; break; + case AM_TS_SRC_TS3: + fec_clk = tsfile_clkdiv; + hiu = 0; + break; case AM_TS_SRC_S_TS0: fec_clk = tsfile_clkdiv; hiu = 0; @@ -1513,6 +1583,10 @@ static void stb_enable(struct aml_dvb *dvb) fec_clk = tsfile_clkdiv; hiu = 1; break; + case AM_TS_SRC_HIU1: + fec_clk = tsfile_clkdiv; + hiu = 1; + break; default: fec_clk = 0; hiu = 0; @@ -1567,11 +1641,18 @@ static void stb_enable(struct aml_dvb *dvb) case AM_TS_SRC_TS2: out_src = 2; break; + case AM_TS_SRC_TS3: + out_src = 3; + break; case AM_TS_SRC_S_TS0: - case AM_TS_SRC_S_TS1: - case AM_TS_SRC_S_TS2: out_src = 6; break; + case AM_TS_SRC_S_TS1: + out_src = 5; + break; + case AM_TS_SRC_S_TS2: + out_src = 4; + break; case AM_TS_SRC_HIU: out_src = 7; break; @@ -1584,14 +1665,18 @@ static void stb_enable(struct aml_dvb *dvb) fec_s0 = 0; fec_s1 = 0; + fec_s2 = 0; invert0 = 0; invert1 = 0; + invert2 = 0; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { if (dvb->ts[i].s2p_id == 0) fec_s0 = i; else if (dvb->ts[i].s2p_id == 1) fec_s1 = i; + else if (dvb->ts[i].s2p_id == 2) + fec_s2 = i; } invert0 = dvb->s2p[0].invert; @@ -1607,6 +1692,15 @@ static void stb_enable(struct aml_dvb *dvb) (invert0 << INVERT_S2P0_FEC_CLK) | (fec_s0 << S2P0_FEC_SERIAL_SEL)); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { + invert2 = dvb->s2p[2].invert; + + WRITE_MPEG_REG(STB_S2P2_CONFIG, + (invert2 << INVERT_S2P2_FEC_CLK) | + (fec_s2 << S2P2_FEC_SERIAL_SEL)); + } + if (dvb->reset_flag) hiu = 0; /* invert ts out clk,add ci model need add this*/ @@ -1616,13 +1710,23 @@ static void stb_enable(struct aml_dvb *dvb) data |= 1 << TS_OUT_CLK_INVERT; WRITE_MPEG_REG(TS_TOP_CONFIG, data); } - /* invert ts out clk end */ - WRITE_MPEG_REG(TS_FILE_CONFIG, - (demux_skipbyte << 16) | - (6 << DES_OUT_DLY) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD_2) | - (hiu << TS_HIU_ENABLE) | (fec_clk << FEC_FILE_CLK_DIV)); + + if (src == AM_TS_SRC_HIU1) { + WRITE_MPEG_REG(TS_HIU1_CONFIG, + (demux_skipbyte << FILE_M2TS_SKIP_BYTES_HIU1) | + (hiu << TS_HIU_ENABLE_HIU1) | + (fec_clk << FEC_CLK_DIV_HIU1) | + (0xBB << TS_PACKAGE_LENGTH_SUB_1_HIU1) | + (0x47 << FEC_SYNC_BYTE_HIU1)); + } else { + /* invert ts out clk end */ + WRITE_MPEG_REG(TS_FILE_CONFIG, + (demux_skipbyte << 16) | + (6 << DES_OUT_DLY) | + (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | + (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD_2) | + (hiu << TS_HIU_ENABLE) | (fec_clk << FEC_FILE_CLK_DIV)); + } } int dsc_set_pid(struct aml_dsc_channel *ch, int pid) @@ -1663,43 +1767,105 @@ int dsc_set_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, /*struct aml_dsc *dsc = ch->dsc;*/ int ret = -1; - if (type == CA_CW_DVB_CSA_EVEN || type == CA_CW_DVB_CSA_ODD) { + switch (type) { + case CA_CW_DVB_CSA_EVEN: + case CA_CW_DVB_CSA_ODD: + aml_ci_plus_disable(); ret = dsc_set_csa_key(ch, flags, type, key); if (ret != 0) goto END; /* Different with old mode, do change */ if (ch->work_mode == CIPLUS_MODE || ch->work_mode == -1) { if (ch->work_mode == -1) - pr_error("Dsc set output and enable\n"); + pr_inf("dsc[%d:%d] enable\n", + ch->dsc->id, ch->id); else - pr_error("Dsc set output change from ciplus\n"); - aml_ci_plus_disable_output(); - ch->aes_mode = AES_ECB_MODE; - /*aml_ci_plus_disable();*/ + pr_inf("dsc[%d:%d] enable (from ciplus)\n", + ch->dsc->id, ch->id); + ch->mode = ECB_MODE; ch->work_mode = DVBCSA_MODE; } - } else if (type == CA_CW_AES_EVEN || - type == CA_CW_AES_ODD || - type == CA_CW_AES_EVEN_IV || - type == CA_CW_AES_ODD_IV) { - ret = dsc_set_aes_key(ch, flags, type, key); + break; + case CA_CW_AES_EVEN: + case CA_CW_AES_ODD: + case CA_CW_AES_EVEN_IV: + case CA_CW_AES_ODD_IV: + case CA_CW_DES_EVEN: + case CA_CW_DES_ODD: + case CA_CW_SM4_EVEN: + case CA_CW_SM4_ODD: + case CA_CW_SM4_EVEN_IV: + case CA_CW_SM4_ODD_IV: + am_ci_plus_set_output(ch); + ret = dsc_set_aes_des_sm4_key(ch, flags, type, key); if (ret != 0) goto END; /* Different with old mode, do change */ if (ch->work_mode == DVBCSA_MODE || ch->work_mode == -1) { if (ch->work_mode == -1) - pr_error("Ciplus set output and enable\n"); + pr_inf("dsc[%d:%d] ciplus enable\n", + ch->dsc->id, ch->id); else - pr_error("Ciplus set output change from dsc\n"); - am_ci_plus_set_output(ch); - aml_ci_plus_enable(); + pr_inf("dsc[%d:%d] ciplus enable (from dsc)\n", + ch->dsc->id, ch->id); ch->work_mode = CIPLUS_MODE; } + break; + default: + break; } END: return ret; } +int dsc_set_keys(struct aml_dsc_channel *ch) +{ + int types = ch->set & 0xFFFFFF; + int flag = (ch->set >> 24) & 0xFF; + int i; + u8 *k; + int ret = 0; + + for (i = 0; i < CA_CW_TYPE_MAX; i++) { + if (types & (1 << i)) { + k = NULL; + switch (i) { + case CA_CW_DVB_CSA_EVEN: + case CA_CW_AES_EVEN: + case CA_CW_DES_EVEN: + case CA_CW_SM4_EVEN: + k = ch->even; + break; + case CA_CW_DVB_CSA_ODD: + case CA_CW_AES_ODD: + case CA_CW_DES_ODD: + case CA_CW_SM4_ODD: + k = ch->odd; + break; + case CA_CW_AES_EVEN_IV: + case CA_CW_SM4_EVEN_IV: + k = ch->even_iv; + break; + case CA_CW_AES_ODD_IV: + case CA_CW_SM4_ODD_IV: + k = ch->odd_iv; + break; + default: + break; + } + /* + if (k) + pr_inf("dsc ch:%d flag:%d type:%d\n", ch->id, flag, i); + */ + if (k) + ret = dsc_set_key(ch, flag, + i, + k); + } + } + return 0; +} + static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key) { @@ -1707,18 +1873,10 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, int is_dsc2 = (dsc->id == 1) ? 1 : 0; u16 k0, k1, k2, k3; u32 key0, key1; - int reg; /*not sure if reg readable*/ -/* u32 data; - * u32 pid = 0x1fff; - */ - int from_kl = flags & CA_CW_FROM_KL; -/* int pid = ch->pid; */ + int reg; - if (from_kl) { + if (flags & DSC_FROM_KL) { k0 = k1 = k2 = k3 = 0; -/* ch->used = 1; - * dsc_set_pid(ch, pid); - */ /*dummy write to check if kl not working*/ key0 = key1 = 0; WRITE_MPEG_REG(COMM_DESC_KEY0, key0); @@ -1732,7 +1890,9 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, ((ch->id + type * DSC_COUNT)+ (is_dsc2 ? 16 : 0))); } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL) { + if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL || + get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) { + pr_info("do kl..\n"); WRITE_MPEG_REG(COMM_DESC_KEY_RW, (type ? (1 << 6) : (1 << 5)) | (1<<7) | ((ch->id + type * DSC_COUNT)+ @@ -1751,9 +1911,9 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, key1 = (k2 << 16) | k3; WRITE_MPEG_REG(COMM_DESC_KEY0, key0); WRITE_MPEG_REG(COMM_DESC_KEY1, key1); - WRITE_MPEG_REG(COMM_DESC_KEY_RW, - (ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0)); + reg = (ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0); + WRITE_MPEG_REG(COMM_DESC_KEY_RW, reg); } return 0; @@ -1778,7 +1938,11 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, #define KEY_WR_AES_IV_A 4 #define KEY_WR_AES_B 3 #define KEY_WR_AES_A 2 +#define KEY_WR_DES_B 1 +#define KEY_WR_DES_A 0 +#define IDSA_MODE_BIT 31 +#define SM4_MODE 30 #define CNTL_ENABLE 3 #define AES_CBC_DISABLE 2 #define AES_EN 1 @@ -1787,7 +1951,13 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, #define AES_MSG_OUT_ENDIAN 24 #define AES_MSG_IN_ENDIAN 20 #define AES_KEY_ENDIAN 16 +#define DES_MSG_OUT_ENDIAN 8 +#define DES_MSG_IN_ENDIAN 4 +#define DES_KEY_ENDIAN 0 +#define ALGO_AES 0 +#define ALGO_SM4 1 +#define ALGO_DES 2 #if 0 static void aml_ci_plus_set_stb(void) @@ -1834,14 +2004,16 @@ void aml_ci_plus_set_iv(struct aml_dsc_channel *ch, enum ca_cw_type type, k1 = (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11]; k0 = (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15]; - if (type == CA_CW_AES_EVEN_IV) { + if (type == CA_CW_AES_EVEN_IV || + type == CA_CW_SM4_EVEN_IV) { WRITE_MPEG_REG(CIPLUS_KEY0, k0); WRITE_MPEG_REG(CIPLUS_KEY1, k1); WRITE_MPEG_REG(CIPLUS_KEY2, k2); WRITE_MPEG_REG(CIPLUS_KEY3, k3); WRITE_MPEG_REG(CIPLUS_KEY_WR, (ch->id << 9) | (1<dsc; u32 data; + u32 in = 0, out = 0; + int set = 0; if (dsc->id != 0) { pr_error("Ciplus set output can only work at dsc0 device\n"); return; } + switch (dsc->source) { + case AM_TS_SRC_DMX0: + in = 0; + break; + case AM_TS_SRC_DMX1: + in = 1; + break; + case AM_TS_SRC_DMX2: + in = 2; + break; + default: + break; + } + if (ciplus_out_auto_mode == 1) { - data = READ_MPEG_REG(STB_TOP_CONFIG); - switch (dsc->source) { + switch (dsc->dst) { case AM_TS_SRC_DMX0: - data |= 1 << CIPLUS_OUT_SEL; - ciplus_out_sel = 1; - break; + out = 1; + break; case AM_TS_SRC_DMX1: - data |= 2 << CIPLUS_OUT_SEL; - ciplus_out_sel = 2; - break; + out = 2; + break; case AM_TS_SRC_DMX2: - data |= 4 << CIPLUS_OUT_SEL; - ciplus_out_sel = 4; - break; + out = 4; + break; default: - pr_error("ciplus auto set source failed\n"); - return; + break; } - WRITE_MPEG_REG(STB_TOP_CONFIG, data); + set = 1; + ciplus_out_sel = out; } else if (ciplus_out_sel >= 0 && ciplus_out_sel <= 7) { - pr_error("Set output selection %d\n", ciplus_out_sel); + set = 1; + out = ciplus_out_sel; + } else { + pr_error("dsc ciplus out config is invalid\n"); + } + + if (set) { + /* Set ciplus input source , + * output set 0 means no output. ---> need confirm. + * if output set 0 still affects dsc output, we need to disable + * ciplus module. + */ data = READ_MPEG_REG(STB_TOP_CONFIG); + data &= ~(3<aes_mode == -1) - ch->aes_mode = AES_ECB_MODE; - } else if (type == CA_CW_AES_ODD) { - aes_a = 1; - aes_b = 0; - if (ch->aes_mode == -1) - ch->aes_mode = AES_ECB_MODE; - } else if ((type == CA_CW_AES_EVEN_IV) - || (type == CA_CW_AES_ODD_IV)) { - aml_ci_plus_set_iv(ch, type, key); - ch->aes_mode = AES_CBC_MODE; - return 0; + if (!from_kl) { + if (get_cpu_type() < MESON_CPU_MAJOR_ID_SM1) { + k3 = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3]; + k2 = (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7]; + k1 = (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11]; + k0 = (key[12] << 24) | (key[13] << 16) + | (key[14] << 8) | key[15]; + } else { + k0 = (key[0]) | (key[1] << 8) | (key[2] << 16) | (key[3] << 24); + k1 = (key[4]) | (key[5] << 8) | (key[6] << 16) | (key[7] << 24); + k2 = (key[8]) | (key[9] << 8) | (key[10] << 16)| (key[11] << 24); + k3 = (key[12])| (key[13] << 8)| (key[14] << 16)| (key[15] << 24); + } + } else + k0 = k1 = k2 = k3 = 0; + + switch (type) { + case CA_CW_AES_EVEN: + case CA_CW_SM4_EVEN: + ab_aes = (from_kl) ? 0x2 : 0x1; + if (ch->mode == -1) + ch->mode = ECB_MODE; + aes = 1; + if (type == CA_CW_AES_EVEN) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_AES_ODD: + case CA_CW_SM4_ODD: + ab_aes = (from_kl) ? 0x1 : 0x2; + if (ch->mode == -1) + ch->mode = ECB_MODE; + aes = 1; + if (type == CA_CW_AES_ODD) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_AES_EVEN_IV: + case CA_CW_SM4_EVEN_IV: + ab_iv = 0x1; + if (ch->mode == -1) + ch->mode = CBC_MODE; + iv = 1; + if (type == CA_CW_AES_EVEN_IV) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_AES_ODD_IV: + case CA_CW_SM4_ODD_IV: + ab_iv = 0x2; + if (ch->mode == -1) + ch->mode = CBC_MODE; + iv = 1; + if (type == CA_CW_AES_ODD_IV) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_DES_EVEN: + ab_des = 0x1; + ch->mode = ECB_MODE; + des = 1; + algo = ALGO_DES; + break; + case CA_CW_DES_ODD: + ab_des = 0x2; + ch->mode = ECB_MODE; + algo = ALGO_DES; + des = 1; + break; + default: + break; } /* Set endian and cbc/ecb mode */ if (from_kl) - aml_ci_plus_config(7, ch->aes_mode); + aml_ci_plus_config(7, ch->mode, algo); else - aml_ci_plus_config(0, ch->aes_mode); + aml_ci_plus_config(0, ch->mode, algo); /* Write keys to work */ - if (from_kl) { - k0 = k1 = k2 = k3 = 0; - -/* dummy write to - * check if kl not working - */ + if (iv || aes) { WRITE_MPEG_REG(CIPLUS_KEY0, k0); WRITE_MPEG_REG(CIPLUS_KEY1, k1); WRITE_MPEG_REG(CIPLUS_KEY2, k2); WRITE_MPEG_REG(CIPLUS_KEY3, k3); - WRITE_MPEG_REG(CIPLUS_KEY_WR, - (ch->id << 9) | - -/* bit[11:9] the key of index, - * need match PID index - */ - (0 << 8) | /* bit[8] des key use cw[127:64]*/ - (0 << 7) | /* bit[7] aes iv use cw*/ - (1 << 6) | /* bit[6] aes/des key use cw*/ - (0 << 5) | /* bit[5] write AES IV B value*/ - (0 << 4) | /* bit[4] write AES IV A value*/ - (aes_b << 3) | /* bit[3] write AES B key*/ - (aes_a << 2) | /* bit[2] write AES A key*/ - (0 << 1) | /* bit[1] write DES B key*/ - (0)); /* bit[0] write DES A key*/ - } else { - - k3 = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3]; - k2 = (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7]; - k1 = (key[8] << 24) | (key[9] << 16) | - (key[10] << 8) | key[11]; - k0 = (key[12] << 24) | (key[13] << 16) | - (key[14] << 8) | key[15]; - - WRITE_MPEG_REG(CIPLUS_KEY0, k0); - WRITE_MPEG_REG(CIPLUS_KEY1, k1); - WRITE_MPEG_REG(CIPLUS_KEY2, k2); - WRITE_MPEG_REG(CIPLUS_KEY3, k3); - index_flag = (ch->id << 9); - if (type == 2) { /* even */ - WRITE_MPEG_REG(CIPLUS_KEY_WR, - index_flag | (1<id << 9) | + /* bit[11:9] the key of index, + need match PID index*/ + ((from_kl && des) ? (1 << 8) : 0) | + /* bit[8] des key use cw[127:64]*/ + (0 << 7) | /* bit[7] aes iv use cw*/ + ((from_kl && (aes || des)) ? (1 << 6) : 0) | + /* bit[6] aes/des key use cw*/ + /* bit[5] write AES IV B value*/ + (ab_iv << 4) | /* bit[4] write AES IV A value*/ + /* bit[3] write AES B key*/ + (ab_aes << 2) | /* bit[2] write AES A key*/ + /* bit[1] write DES B key*/ + (ab_des)); /* bit[0] write DES A key*/ + + /* + pr_inf("k:%08x:%08x:%08x:%08x kl:%d aes:%d des:%d ab_iv:%d ab_aes:%d ab_des:%d id:%d mod:%d\n", + k0, k1, k2, k3, + from_kl, aes, des, ab_iv, ab_aes, ab_des, ch->id, ch->aes_mode); + */ return 0; } - void dsc_release(void) { aml_ci_plus_disable(); @@ -2054,7 +2342,7 @@ int dsc_enable(struct aml_dsc *dsc, int enable) (1 << ENABLE_DES_PL)| (1 << ENABLE_DES_PL_CLK))); } else if (dsc->id == 1) { - WRITE_MPEG_REG(COMM_DESC_2_CTL, 0); + WRITE_MPEG_REG(COMM_DESC_2_CTL, 0); } return 0; } @@ -2196,7 +2484,7 @@ static int asyncfifo_set_buffer(struct aml_asyncfifo *afifo, afifo->buf_toggle = 0; afifo->buf_read = 0; afifo->buf_len = len; - pr_error("async fifo %d buf size %d, flush size %d\n", + pr_error("++++async fifo %d buf size %d, flush size %d\n", afifo->id, afifo->buf_len, afifo->flush_size); if ((afifo->flush_size <= 0) @@ -2275,11 +2563,16 @@ int async_fifo_init(struct aml_asyncfifo *afifo, int initirq, int async_fifo_deinit(struct aml_asyncfifo *afifo, int freeirq) { + struct aml_dvb *dvb = afifo->dvb; + unsigned long flags; + if (!afifo->init) return 0; + spin_lock_irqsave(&dvb->slock, flags); CLEAR_ASYNC_FIFO_REG_MASK(afifo->id, REG1, 1 << ASYNC_FIFO_FLUSH_EN); CLEAR_ASYNC_FIFO_REG_MASK(afifo->id, REG2, 1 << ASYNC_FIFO_FILL_EN); + spin_unlock_irqrestore(&dvb->slock, flags); asyncfifo_put_buffer(afifo); @@ -2447,12 +2740,22 @@ static int dmx_init(struct aml_dmx *dmx) { struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; int irq; + int ret = 0; + char buf[32]; + u32 value = 0; if (dmx->init) return 0; pr_inf("demux init\n"); + memset(buf, 0, 32); + snprintf(buf, sizeof(buf), "asyncfifo_buf_len"); + ret = of_property_read_u32(dvb->pdev->dev.of_node, buf, &value); + if (!ret) { + pr_inf("%s: 0x%x\n", buf, value); + asyncfifo_buf_len = value; + } /*Register irq handlers */ if (dmx->dmx_irq != -1) { pr_dbg("request irq\n"); @@ -2556,7 +2859,7 @@ static int dmx_get_record_flag(struct aml_dmx *dmx) struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; /*Check whether a async fifo connected to this dmx */ - for (i = 0; i < ASYNCFIFO_COUNT; i++) { + for (i = 0; i < dvb->async_fifo_total_count; i++) { if (!dvb->asyncfifo[i].init) continue; if ((dvb->asyncfifo[i].source == dmx->id) @@ -2601,6 +2904,29 @@ find_done: return record_flag; } +static void dmx_cascade_set(int cur_dmx, int source) { + int fec_sel_demux = 0; + int data; + + switch (source) { + case AM_TS_SRC_DMX0: + case AM_TS_SRC_DMX1: + case AM_TS_SRC_DMX2: + fec_sel_demux = source -AM_TS_SRC_DMX0; + break; + default: + fec_sel_demux = cur_dmx; + break; + } + + data = READ_MPEG_REG(TS_TOP_CONFIG1); + data &= ~(0x3 << (cur_dmx*2)); + data |= (fec_sel_demux << (cur_dmx*2)); + WRITE_MPEG_REG(TS_TOP_CONFIG1,data); + + pr_dbg("%s id:%d, source:%d data:0x%0x\n",__FUNCTION__,cur_dmx,fec_sel_demux,data); +} + /*Enable the demux device*/ static int dmx_enable(struct aml_dmx *dmx) { @@ -2609,7 +2935,7 @@ static int dmx_enable(struct aml_dmx *dmx) int fec_core_sel = 0; int set_stb = 0, fec_s = 0; int s2p_id; - u32 invert0 = 0, invert1 = 0, fec_s0 = 0, fec_s1 = 0; + u32 invert0 = 0, invert1 = 0, invert2 = 0, fec_s0 = 0, fec_s1 = 0, fec_s2 = 0; u32 use_sop = 0; record = dmx_get_record_flag(dmx); @@ -2648,7 +2974,8 @@ static int dmx_enable(struct aml_dmx *dmx) s2p_id = dvb->ts[2].s2p_id; fec_ctrl = dvb->ts[2].control; } - fec_sel = (s2p_id == 1) ? 5 : 6; + //fec_sel = (s2p_id == 1) ? 5 : 6; + fec_sel = 6 - s2p_id; record = record ? 1 : 0; set_stb = 1; fec_s = dmx->source - AM_TS_SRC_S_TS0; @@ -2656,7 +2983,25 @@ static int dmx_enable(struct aml_dmx *dmx) case AM_TS_SRC_HIU: fec_sel = 7; fec_ctrl = 0; + /* + support record in HIU mode record = 0; + */ + break; + case AM_TS_SRC_HIU1: + fec_sel = 8; + fec_ctrl = 0; + /* + support record in HIU mode + record = 0; + */ + break; + case AM_TS_SRC_DMX0: + case AM_TS_SRC_DMX1: + case AM_TS_SRC_DMX2: + fec_sel = -1; + fec_ctrl = 0; + record = record ? 1 : 0; break; default: fec_sel = 0; @@ -2665,11 +3010,14 @@ static int dmx_enable(struct aml_dmx *dmx) break; } - if (dmx->channel[0].used || dmx->channel[1].used) + if (dmx->channel[0].used || dmx->channel[1].used) { hi_bsf = 1; - else + if (fec_sel == 8) { + hi_bsf = 2; /*hi_bsf select hiu1*/ + } + }else { hi_bsf = 0; - + } if ((dvb->dsc[0].dst != -1) && ((dvb->dsc[0].dst - AM_TS_SRC_DMX0) == dmx->id)) fec_core_sel = 1; @@ -2734,11 +3082,13 @@ static int dmx_enable(struct aml_dmx *dmx) u32 v = READ_MPEG_REG(STB_TOP_CONFIG); int i; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { if (dvb->ts[i].s2p_id == 0) fec_s0 = i; else if (dvb->ts[i].s2p_id == 1) fec_s1 = i; + else if (dvb->ts[i].s2p_id == 2) + fec_s2 = i; } invert0 = dvb->s2p[0].invert; @@ -2754,6 +3104,18 @@ static int dmx_enable(struct aml_dmx *dmx) (fec_s1 << S2P1_FEC_SERIAL_SEL) | (invert1 << INVERT_S2P1_FEC_CLK); WRITE_MPEG_REG(STB_TOP_CONFIG, v); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { + invert2 = dvb->s2p[2].invert; + + //add s2p2 config + v = READ_MPEG_REG(STB_S2P2_CONFIG); + v &= ~((0x3 << S2P2_FEC_SERIAL_SEL) | + (0x1f << INVERT_S2P2_FEC_CLK)); + v |= (fec_s2 << S2P2_FEC_SERIAL_SEL) | + (invert2 << INVERT_S2P2_FEC_CLK); + WRITE_MPEG_REG(STB_S2P2_CONFIG, v); + } } /*Initialize the registers */ @@ -2780,13 +3142,33 @@ static int dmx_enable(struct aml_dmx *dmx) (7<id, TS_HIU_CTL, - (0 << LAST_BURST_THRESHOLD) | - (hi_bsf << USE_HI_BSF_INTERFACE)); + if (fec_sel != 8) { + DMX_WRITE_REG(dmx->id, TS_HIU_CTL, +// (0 << LAST_BURST_THRESHOLD) | + (hi_bsf << USE_HI_BSF_INTERFACE)); + } else { + DMX_WRITE_REG(dmx->id, TS_HIU_CTL, + (1 << PDTS_WR_SEL) | + (hi_bsf << USE_HI_BSF_INTERFACE)); + } - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, + if (fec_sel == -1) { + dmx_cascade_set(dmx->id,dmx->source); + DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, (fec_core_sel << FEC_CORE_SEL) | - (fec_sel << FEC_SEL) | (fec_ctrl << 0)); + (0 << FEC_SEL) | (fec_ctrl << 0)); + } else { + dmx_cascade_set(dmx->id,dmx->source); + if (fec_sel != 8) { + DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, + (fec_core_sel << FEC_CORE_SEL) | + (fec_sel << FEC_SEL) | (fec_ctrl << 0)); + } else { + DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, + (fec_core_sel << FEC_CORE_SEL) | + (1 << FEC_SEL_3BIT) | (fec_ctrl << 0)); + } + } DMX_WRITE_REG(dmx->id, STB_OM_CTL, (0x40 << MAX_OM_DMA_COUNT) | (0x7f << LAST_OM_ADDR)); @@ -2808,8 +3190,13 @@ static int dmx_enable(struct aml_dmx *dmx) DMX_WRITE_REG(dmx->id, STB_INT_MASK, 0); DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, 0); DMX_WRITE_REG(dmx->id, DEMUX_CONTROL, 0); + //dmx not used, but it can cascade for other dmx + if ((dmx->source == AM_TS_SRC_DMX0 || + dmx->source == AM_TS_SRC_DMX1 || + dmx->source == AM_TS_SRC_DMX2 ) && + (dmx->id != dmx->source-AM_TS_SRC_DMX0)) + dmx_cascade_set(dmx->id,dmx->source); } - return 0; } @@ -3138,12 +3525,13 @@ static void dmx_clear_filter_buffer(struct aml_dmx *dmx, int fid) static void async_fifo_set_regs(struct aml_asyncfifo *afifo, int source_val) { - u32 start_addr = virt_to_phys((void *)afifo->pages); + u32 start_addr = afifo->secure_enable ? afifo->blk.addr : + virt_to_phys((void *)afifo->pages); u32 size = afifo->buf_len; u32 flush_size = afifo->flush_size; int factor = dmx_get_order(size / flush_size); - - pr_dbg("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d,source value 0x%x, factor %d\n", + pr_error("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d," + "source value 0x%x, factor %d\n", afifo->id, afifo->source, start_addr, size, source_val, factor); /* Destination address */ WRITE_ASYNC_FIFO_REG(afifo->id, REG0, start_addr); @@ -3208,11 +3596,12 @@ static void reset_async_fifos(struct aml_dvb *dvb) { struct aml_asyncfifo *low_dmx_fifo = NULL; struct aml_asyncfifo *high_dmx_fifo = NULL; + struct aml_asyncfifo *highest_dmx_fifo = NULL; int i, j; int record_enable; pr_dbg("reset ASYNC FIFOs\n"); - for (i = 0; i < ASYNCFIFO_COUNT; i++) { + for (i = 0; i < dvb->async_fifo_total_count; i++) { if (!dvb->asyncfifo[i].init) continue; pr_dbg("Disable ASYNC FIFO id=%d\n", dvb->asyncfifo[i].id); @@ -3235,7 +3624,7 @@ static void reset_async_fifos(struct aml_dvb *dvb) if (!dvb->dmx[j].init) continue; record_enable = 0; - for (i = 0; i < ASYNCFIFO_COUNT; i++) { + for (i = 0; i < dvb->async_fifo_total_count; i++) { if (!dvb->asyncfifo[i].init) continue; @@ -3249,11 +3638,25 @@ static void reset_async_fifos(struct aml_dvb *dvb) low_dmx_fifo = &dvb->asyncfifo[i]; } else if (low_dmx_fifo->source > dvb->asyncfifo[i].source) { - high_dmx_fifo = low_dmx_fifo; + if (!high_dmx_fifo) + high_dmx_fifo = low_dmx_fifo; + else { + highest_dmx_fifo = high_dmx_fifo; + high_dmx_fifo = low_dmx_fifo; + } low_dmx_fifo = &dvb->asyncfifo[i]; } else if (low_dmx_fifo->source < dvb->asyncfifo[i].source) { - high_dmx_fifo = &dvb->asyncfifo[i]; + if (!high_dmx_fifo) + high_dmx_fifo = &dvb->asyncfifo[i]; + else { + if (high_dmx_fifo->source > dvb->asyncfifo[i].source) { + highest_dmx_fifo = high_dmx_fifo; + high_dmx_fifo = &dvb->asyncfifo[i]; + } else { + highest_dmx_fifo = &dvb->asyncfifo[i]; + } + } } break; @@ -3282,8 +3685,12 @@ static void reset_async_fifos(struct aml_dvb *dvb) if (low_dmx_fifo) { async_fifo_set_regs(low_dmx_fifo, 0x3); - if (high_dmx_fifo) + if (high_dmx_fifo) { async_fifo_set_regs(high_dmx_fifo, 0x2); + + if (highest_dmx_fifo) + async_fifo_set_regs(highest_dmx_fifo, 0x0); + } } } @@ -3326,6 +3733,7 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) } WRITE_MPEG_REG(STB_TOP_CONFIG, 0); + WRITE_MPEG_REG(STB_S2P2_CONFIG, 0); for (id = 0; id < DMX_DEV_COUNT; id++) { u32 version, data; @@ -3450,28 +3858,9 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) /*if(ch->used) */ { ch->id = n; + ch->work_mode = -1; dsc_set_pid(ch, ch->pid); - - if (ch->flags & DSC_SET_EVEN) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_EVEN, - ch->even); - } - if (ch->flags & DSC_SET_ODD) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_ODD, - ch->odd); - } - if (ch->flags & DSC_SET_AES_EVEN) { - dsc_set_key(ch, 0, - CA_CW_AES_EVEN, - ch->aes_even); - } - if (ch->flags & DSC_SET_AES_ODD) { - dsc_set_key(ch, 0, - CA_CW_AES_ODD, - ch->aes_odd); - } + dsc_set_keys(ch); } } } @@ -3653,28 +4042,9 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx, for (n = 0; n < DSC_COUNT; n++) { struct aml_dsc_channel *ch = &dsc->channel[n]; /*if(ch->used) */ + ch->work_mode = -1; dsc_set_pid(ch, ch->pid); - - if (ch->flags & DSC_SET_EVEN) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_EVEN, - ch->even); - } - if (ch->flags & DSC_SET_ODD) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_ODD, - ch->odd); - } - if (ch->flags & DSC_SET_AES_EVEN) { - dsc_set_key(ch, 0, - CA_CW_AES_EVEN, - ch->aes_even); - } - if (ch->flags & DSC_SET_AES_ODD) { - dsc_set_key(ch, 0, - CA_CW_AES_ODD, - ch->aes_odd); - } + dsc_set_keys(ch); } } } @@ -3718,6 +4088,7 @@ void dmx_reset_dmx_hw(struct aml_dvb *dvb, int id) } /*Allocate subtitle pes buffer*/ +#if 0 static int alloc_subtitle_pes_buffer(struct aml_dmx *dmx) { int start_ptr = 0; @@ -3747,6 +4118,7 @@ static int alloc_subtitle_pes_buffer(struct aml_dmx *dmx) exit: return 0; } +#endif /*Allocate a new channel*/ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid) @@ -3768,7 +4140,7 @@ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid) case DMX_PES_TELETEXT: if (!dmx->channel[2].used) id = 2; - alloc_subtitle_pes_buffer(dmx); + //alloc_subtitle_pes_buffer(dmx); break; case DMX_PES_PCR: if (!dmx->channel[3].used) @@ -4351,7 +4723,7 @@ int aml_asyncfifo_hw_init(struct aml_asyncfifo *afifo) */ int ret; - int len = ASYNCFIFO_BUFFER_SIZE_DEFAULT; + int len = asyncfifo_buf_len; unsigned long buf = asyncfifo_alloc_buffer(len); if (!buf) @@ -4401,17 +4773,18 @@ int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo) unsigned long flags; int ret, src = -1; - int len = ASYNCFIFO_BUFFER_SIZE_DEFAULT; - unsigned long buf = asyncfifo_alloc_buffer(len); - + unsigned long buf = 0; + int len = asyncfifo_buf_len; + buf = asyncfifo_alloc_buffer(len); if (!buf) return -1; - spin_lock_irqsave(&dvb->slock, flags); if (afifo->init) { src = afifo->source; async_fifo_deinit(afifo, 0); } + + spin_lock_irqsave(&dvb->slock, flags); ret = async_fifo_init(afifo, 0, len, buf); /* restore the source */ if (src != -1) @@ -4494,21 +4867,38 @@ int aml_dmx_hw_set_source(struct dmx_demux *demux, dmx_source_t src) case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS0 : AM_TS_SRC_TS0; + AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS1 : AM_TS_SRC_TS1; + AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS2 : AM_TS_SRC_TS2; + AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + break; + case DMX_SOURCE_FRONT3: + hw_src = + (dvb->ts[3].mode == + AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; break; + case DMX_SOURCE_DVR1: + hw_src = AM_TS_SRC_HIU1; + break; + case DMX_SOURCE_FRONT0_OFFSET: + hw_src = AM_TS_SRC_DMX0; + break; + case DMX_SOURCE_FRONT1_OFFSET: + hw_src = AM_TS_SRC_DMX1; + break; + case DMX_SOURCE_FRONT2_OFFSET: + hw_src = AM_TS_SRC_DMX2; + break; default: pr_error("illegal demux source %d\n", src); ret = -EINVAL; @@ -4543,21 +4933,29 @@ int aml_stb_hw_set_source(struct aml_dvb *dvb, dmx_source_t src) case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS0 : AM_TS_SRC_TS0; + AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS1 : AM_TS_SRC_TS1; + AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS2 : AM_TS_SRC_TS2; + AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + break; + case DMX_SOURCE_FRONT3: + hw_src = + (dvb->ts[3].mode == + AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; break; + case DMX_SOURCE_DVR1: + hw_src = AM_TS_SRC_HIU1; + break; case DMX_SOURCE_FRONT0_OFFSET: hw_src = AM_TS_SRC_DMX0; break; @@ -4664,34 +5062,34 @@ int aml_dsc_hw_set_source(struct aml_dsc *dsc, } if (src_reset) { - pr_dbg("dsc%d source changed: %d -> %d\n", + pr_inf("dsc%d source changed: %d -> %d\n", dsc->id, org_src, hw_src); if (org_src != -1) { - pr_dbg("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (org_src - AM_TS_SRC_DMX0), 0); } if (hw_src != -1) { - pr_dbg("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (hw_src - AM_TS_SRC_DMX0), 0); } else dsc_enable(dsc, 0); } if (dst_reset) { - pr_dbg("dsc%d dest changed: %d -> %d\n", + pr_inf("dsc%d dest changed: %d -> %d\n", dsc->id, org_dst, hw_dst); if (((!src_reset) && (org_dst != -1)) || (src_reset && (org_dst != -1) && (org_dst != org_src) && (org_dst != hw_src))) { - pr_dbg("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (org_dst - AM_TS_SRC_DMX0), 0); } if (((!src_reset) && (hw_dst != -1)) || (src_reset && (hw_dst != -1) && (hw_dst != org_src) && (hw_dst != hw_src))) { - pr_dbg("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (hw_dst - AM_TS_SRC_DMX0), 0); } @@ -4704,47 +5102,6 @@ int aml_dsc_hw_set_source(struct aml_dsc *dsc, return ret; } -int aml_ciplus_hw_set_source(int src) -{ - int hw_src = 0; - int hw_dst = 0; - u32 data; - - switch (src) { - case DMX_SOURCE_FRONT0_OFFSET: - hw_src = 0; - hw_dst = 1; - break; - case DMX_SOURCE_FRONT1_OFFSET: - hw_src = 1; - hw_dst = 2; - break; - case DMX_SOURCE_FRONT2_OFFSET: - hw_src = 2; - hw_dst = 4; - break; - default: - return -1; - } - - data = READ_MPEG_REG(STB_TOP_CONFIG); - - /* Set ciplus input source , - * output set 0 means no output. ---> need confirm. - * if output set 0 still affects dsc output, we need to disable - * ciplus module. - */ - data &= ~(3<ts[0].mode == AM_TS_SERIAL) - ? AM_TS_SRC_S_TS0 : AM_TS_SRC_TS0; + ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == AM_TS_SERIAL) - ? AM_TS_SRC_S_TS1 : AM_TS_SRC_TS1; + ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == AM_TS_SERIAL) - ? AM_TS_SRC_S_TS2 : AM_TS_SRC_TS2; + ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + break; + case DMX_SOURCE_FRONT3: + hw_src = (dvb->ts[3].mode == AM_TS_SERIAL) + ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; @@ -4877,6 +5238,29 @@ u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb) return pts; } +u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb) +{ + unsigned long flags; + u32 bit32; + + spin_lock_irqsave(&dvb->slock, flags); + bit32 = video_pts_bit32; + spin_unlock_irqrestore(&dvb->slock, flags); + + return bit32; +} + +u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb) +{ + unsigned long flags; + u32 bit32; + + spin_lock_irqsave(&dvb->slock, flags); + bit32 = audio_pts_bit32; + spin_unlock_irqrestore(&dvb->slock, flags); + + return bit32; +} u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb) { unsigned long flags; @@ -5048,22 +5432,29 @@ static ssize_t ciplus_output_ctrl_show(struct class *class, char *buf) { int ret; + char *out = "none"; - pr_error("output demux use 3 bit to indicate. "); - pr_error("1bit:demux0 2bit:demux1 3bit:demux2\n"); - if (ciplus_out_auto_mode == 1) - ret = sprintf(buf, "Using auto mode, value: %x\n", - ciplus_out_sel); - else - ret = sprintf(buf, "%d\n", ciplus_out_sel); - pr_error("ciplus output path:\n"); - if (ciplus_out_sel&1) - pr_error("demux0 "); - if (ciplus_out_sel&1<<1) - pr_error("demux1 "); - if (ciplus_out_sel&1<<2) - pr_error("demux2 "); - pr_error("\n"); + pr_inf("output demux use 3 bit to indicate.\n"); + pr_inf("1bit:demux0 2bit:demux1 3bit:demux2\n"); + + switch (ciplus_out_sel) { + case 1: + out = "dmx0"; + break; + case 2: + out = "dmx1"; + break; + case 4: + out = "dmx2"; + break; + default: + break; + } + + ret = sprintf(buf, "%s 0x%x %s\n", + out, + ciplus_out_sel, + (ciplus_out_auto_mode) ? "" : "(force)"); return ret; } @@ -5073,9 +5464,6 @@ static ssize_t ciplus_output_ctrl_store(struct class *class, { int i, tmp; - pr_error("output demux use 3 bit to indicate. "); - pr_error("1bit:demux0 2bit:demux1 3bit:demux2, 8 for auto\n"); - /*i = sscanf(buf, "%d", &tmp); */ i = kstrtoint(buf, -1, &tmp); if (tmp > 8 || tmp < 0) pr_error("Invalid output set\n"); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c index 1c882ff1e6cc..b3ffbb7cefa6 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * AMLOGIC DVB driver. */ @@ -44,6 +63,7 @@ typedef enum __demod_type DEMOD_INVALID, DEMOD_INTERNAL, DEMOD_ATBM8881, + DEMOD_SI2168, DEMOD_MAX_NUM }demod_type; @@ -53,6 +73,8 @@ typedef enum __tuner_type TUNER_SI2151, TUNER_MXL661, TUNER_SI2159, + TUNER_R842, + TUNER_R840, TUNER_MAX_NUM }tuner_type; @@ -120,6 +142,65 @@ static struct tsdemux_ops aml_tsdemux_ops = { .set_demux = aml_tsdemux_set_demux }; +static int dvb_attach_tuner(struct dvb_frontend *fe, struct aml_tuner *tuner, tuner_type *type) +{ + struct tuner_config *cfg = &tuner->cfg; + struct i2c_adapter *i2c_adap = tuner->i2c_adp; + + switch (cfg->id) { + case AM_TUNER_R840: + if (!dvb_attach(r840_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach r840_attach tuner error\n"); + return -1; + } else { + pr_inf("r840_attach attach sucess\n"); + *type = TUNER_R840; + } + break; + case AM_TUNER_R842: + if (!dvb_attach(r842_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach r842_attach tuner error\n"); + return -1; + } else { + pr_inf("r842_attach attach sucess\n"); + *type = TUNER_R842; + } + break; + case AM_TUNER_SI2151: + if (!dvb_attach(si2151_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach tuner error\n"); + return -1; + } else { + pr_inf("si2151 attach sucess\n"); + *type = TUNER_SI2151; + } + break; + case AM_TUNER_SI2159: + if (!dvb_attach(si2159_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach si2159_attach tuner error\n"); + return -1; + } else { + pr_inf("si2159_attach attach sucess\n"); + *type = TUNER_SI2159; + } + break; + case AM_TUNER_MXL661: + if (!dvb_attach(mxl661_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach mxl661_attach tuner error\n"); + return -1; + } else { + pr_inf("mxl661_attach attach sucess\n"); + *type = TUNER_MXL661; + } + break; + default: + pr_error("can't support tuner type: %d\n", cfg->id); + break; + } + + return 0; +} + long aml_stb_get_base(int id) { int newbase = 0; @@ -135,6 +216,8 @@ long aml_stb_get_base(int id) return (newbase) ? 0x9400 : 0x2110; case ID_ASYNC_FIFO_REG_BASE: return (newbase) ? 0x2800 : 0x2310; + case ID_ASYNC_FIFO1_REG_BASE: + return 0x9800; case ID_ASYNC_FIFO2_REG_BASE: return (newbase) ? 0x2400 : 0x2314; case ID_RESET_BASE: @@ -317,9 +400,9 @@ static void dsc_channel_alloc(struct aml_dsc *dsc, int id, unsigned int pid) ch->work_mode = -1; ch->id = id; ch->pid = pid; - ch->flags = 0; + ch->set = 0; ch->dsc = dsc; - ch->aes_mode = -1; + ch->mode = -1; dsc_set_pid(ch, ch->pid); } @@ -334,9 +417,9 @@ static void dsc_channel_free(struct aml_dsc_channel *ch) dsc_release(); ch->pid = 0x1fff; - ch->flags = 0; + ch->set = 0; ch->work_mode = -1; - ch->aes_mode = -1; + ch->mode = -1; } static void dsc_reset(struct aml_dsc *dsc) @@ -349,15 +432,26 @@ static void dsc_reset(struct aml_dsc *dsc) static int get_dsc_key_work_mode(enum ca_cw_type cw_type) { - int work_mode = 0; + int work_mode = DVBCSA_MODE; - if (cw_type == CA_CW_DVB_CSA_EVEN || cw_type == CA_CW_DVB_CSA_ODD) + switch (cw_type) { + case CA_CW_DVB_CSA_EVEN: + case CA_CW_DVB_CSA_ODD: work_mode = DVBCSA_MODE; - else if (cw_type == CA_CW_AES_EVEN || - cw_type == CA_CW_AES_ODD || - cw_type == CA_CW_AES_EVEN_IV || - cw_type == CA_CW_AES_ODD_IV) { + break; + case CA_CW_AES_EVEN: + case CA_CW_AES_ODD: + case CA_CW_AES_ODD_IV: + case CA_CW_AES_EVEN_IV: + case CA_CW_DES_EVEN: + case CA_CW_DES_ODD: + case CA_CW_SM4_EVEN: + case CA_CW_SM4_ODD: + case CA_CW_SM4_ODD_IV: + case CA_CW_SM4_EVEN_IV: work_mode = CIPLUS_MODE; + default: + break; } return work_mode; } @@ -385,6 +479,8 @@ static void dsc_ciplus_switch_check(struct aml_dsc_channel *ch, pr_error("Dsc work mode changed,"); pr_error("but there are still some channels"); pr_error("run in different mode\n"); + pr_error("mod_pre[%d] -> mod[%d] ch[%d]\n", + pch->work_mode, work_mode, i); } } } @@ -400,32 +496,36 @@ static int dsc_set_cw(struct aml_dsc *dsc, struct ca_descr_ex *d) switch (d->type) { case CA_CW_DVB_CSA_EVEN: - memcpy(ch->even, d->cw, 8); - ch->flags &= ~(DSC_SET_AES_EVEN|DSC_SET_AES_ODD); - ch->flags |= DSC_SET_EVEN; + case CA_CW_AES_EVEN: + case CA_CW_DES_EVEN: + case CA_CW_SM4_EVEN: + memcpy(ch->even, d->cw, DSC_KEY_SIZE_MAX); break; case CA_CW_DVB_CSA_ODD: - memcpy(ch->odd, d->cw, 8); - ch->flags &= ~(DSC_SET_AES_EVEN|DSC_SET_AES_ODD); - ch->flags |= DSC_SET_ODD; - break; - case CA_CW_AES_EVEN: - memcpy(ch->aes_even, d->cw, 16); - ch->flags &= ~(DSC_SET_EVEN|DSC_SET_ODD); - ch->flags |= DSC_SET_AES_EVEN; - break; case CA_CW_AES_ODD: - memcpy(ch->aes_odd, d->cw, 16); - ch->flags &= ~(DSC_SET_EVEN|DSC_SET_ODD); - ch->flags |= DSC_SET_AES_ODD; + case CA_CW_DES_ODD: + case CA_CW_SM4_ODD: + memcpy(ch->odd, d->cw, DSC_KEY_SIZE_MAX); + break; + case CA_CW_AES_EVEN_IV: + case CA_CW_SM4_EVEN_IV: + memcpy(ch->even_iv, d->cw, DSC_KEY_SIZE_MAX); + break; + case CA_CW_AES_ODD_IV: + case CA_CW_SM4_ODD_IV: + memcpy(ch->odd_iv, d->cw, DSC_KEY_SIZE_MAX); break; default: break; } - if (d->flags & CA_CW_FROM_KL) - ch->flags = DSC_FROM_KL; + ch->set |= (1 << d->type) | (d->flags << 24); + if (d->mode == CA_DSC_IDSA) { + ch->mode = IDSA_MODE; + } + + /*do key set*/ dsc_set_key(ch, d->flags, d->type, d->cw); dsc_ciplus_switch_check(ch, d->type); @@ -478,6 +578,7 @@ static int dvb_dsc_do_ioctl(struct file *file, unsigned int cmd, dex.index = d->index; dex.type = d->parity ? CA_CW_DVB_CSA_ODD : CA_CW_DVB_CSA_EVEN; + dex.mode = -1; dex.flags = 0; memcpy(dex.cw, d->cw, sizeof(d->cw)); @@ -656,6 +757,8 @@ static int aml_dvb_asyncfifo_init(struct aml_dvb *advb, if (id == 0) asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO_FLUSH; + else if(id == 2) + asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO3_FLUSH; else asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO2_FLUSH; @@ -668,6 +771,9 @@ static int aml_dvb_asyncfifo_init(struct aml_dvb *advb, asyncfifo->id = id; asyncfifo->init = 0; asyncfifo->flush_size = 256 * 1024; + asyncfifo->secure_enable = 0; + asyncfifo->blk.addr = 0; + asyncfifo->blk.len = 0; return aml_asyncfifo_hw_init(asyncfifo); } @@ -685,7 +791,7 @@ static int aml_dvb_dsc_init(struct aml_dvb *advb, for (i = 0; i < DSC_COUNT; i++) { dsc->channel[i].id = i; dsc->channel[i].used = 0; - dsc->channel[i].flags = 0; + dsc->channel[i].set = 0; dsc->channel[i].pid = 0x1fff; dsc->channel[i].dsc = dsc; } @@ -728,9 +834,15 @@ static ssize_t stb_show_source(struct class *class, case AM_TS_SRC_S_TS2: src = "ts2"; break; + case AM_TS_SRC_TS3: + src = "ts3"; + break; case AM_TS_SRC_HIU: src = "hiu"; break; + case AM_TS_SRC_HIU1: + src = "hiu1"; + break; case AM_TS_SRC_DMX0: src = "dmx0"; break; @@ -749,6 +861,20 @@ static ssize_t stb_show_source(struct class *class, return ret; } +static ssize_t stb_clear_av(struct class *class, + struct class_attribute *attr, const char *buf, + size_t size) +{ + if (!strncmp("1", buf, 1)) { + aml_tsdemux_set_vid(0x1fff); + aml_tsdemux_set_aid(0x1fff); + aml_tsdemux_set_sid(0x1fff); + aml_tsdemux_set_pcrid(0x1fff); + } + + return size; +} + /*Set the STB input source*/ static ssize_t stb_store_source(struct class *class, struct class_attribute *attr, const char *buf, @@ -762,6 +888,10 @@ static ssize_t stb_store_source(struct class *class, src = DMX_SOURCE_FRONT1; else if (!strncmp("ts2", buf, 3)) src = DMX_SOURCE_FRONT2; + else if (!strncmp("ts3", buf, 3)) + src = DMX_SOURCE_FRONT3; + else if (!strncmp("hiu1", buf, 4)) + src = DMX_SOURCE_DVR1; else if (!strncmp("hiu", buf, 3)) src = DMX_SOURCE_DVR0; else if (!strncmp("dmx0", buf, 4)) @@ -842,8 +972,6 @@ static ssize_t dsc##i##_store_source(struct class *class, \ else \ dst = src; \ aml_dsc_hw_set_source(&aml_dvb_device.dsc[i], src, dst);\ - if (i == 0) \ - aml_ciplus_hw_set_source(src); \ return size;\ } @@ -899,6 +1027,9 @@ static ssize_t tso_show_source(struct class *class, case AM_TS_SRC_S_TS2: src = "ts2"; break; + case AM_TS_SRC_TS3: + src = "ts3"; + break; case AM_TS_SRC_HIU: src = "hiu"; break; @@ -933,6 +1064,8 @@ static ssize_t tso_store_source(struct class *class, src = DMX_SOURCE_FRONT1; else if (!strncmp("ts2", buf, 3)) src = DMX_SOURCE_FRONT2; + else if (!strncmp("ts3", buf, 3)) + src = DMX_SOURCE_FRONT3; else if (!strncmp("hiu", buf, 3)) src = DMX_SOURCE_DVR0; else if (!strncmp("dmx0", buf, 4)) @@ -984,9 +1117,21 @@ static ssize_t demux##i##_show_source(struct class *class, \ CASE_PREFIX case AM_TS_SRC_S_TS2:\ src = "ts2";\ break;\ + CASE_PREFIX case AM_TS_SRC_DMX0:\ + src = "dmx0";\ + break;\ + CASE_PREFIX case AM_TS_SRC_DMX1:\ + src = "dmx1";\ + break;\ + CASE_PREFIX case AM_TS_SRC_DMX2:\ + src = "dmx2";\ + break;\ CASE_PREFIX case AM_TS_SRC_HIU:\ src = "hiu";\ break;\ + CASE_PREFIX case AM_TS_SRC_HIU1:\ + src = "hiu1";\ + break;\ CASE_PREFIX default :\ src = "";\ break;\ @@ -1005,8 +1150,16 @@ static ssize_t demux##i##_store_source(struct class *class, \ src = DMX_SOURCE_FRONT1;\ } else if (!strncmp("ts2", buf, 3)) {\ src = DMX_SOURCE_FRONT2;\ + } else if (!strncmp("hiu1", buf, 4)) {\ + src = DMX_SOURCE_DVR1;\ } else if (!strncmp("hiu", buf, 3)) {\ src = DMX_SOURCE_DVR0;\ + } else if (!strncmp("dmx0", buf, 4)) {\ + src = DMX_SOURCE_FRONT0_OFFSET;\ + } else if (!strncmp("dmx1", buf, 4)) {\ + src = DMX_SOURCE_FRONT1_OFFSET;\ + } else if (!strncmp("dmx2", buf, 4)) {\ + src = DMX_SOURCE_FRONT2_OFFSET;\ } \ if (src != -1) {\ aml_dmx_hw_set_source(aml_dvb_device.dmx[i].dmxdev.demux, src);\ @@ -1201,6 +1354,8 @@ static ssize_t asyncfifo##i##_show_source(struct class *class, \ struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ ssize_t ret = 0;\ char *src;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ switch (afifo->source) {\ CASE_PREFIX case AM_DMX_0:\ src = "dmx0";\ @@ -1223,6 +1378,8 @@ static ssize_t asyncfifo##i##_store_source(struct class *class, \ {\ enum aml_dmx_id_t src = -1;\ \ + if (aml_dvb_device.async_fifo_total_count <= i)\ + return 0;\ if (!strncmp("dmx0", buf, 4)) {\ src = AM_DMX_0;\ } else if (!strncmp("dmx1", buf, 4)) {\ @@ -1242,6 +1399,11 @@ ASYNCFIFO_SOURCE_FUNC_DECL(0) #if ASYNCFIFO_COUNT > 1 ASYNCFIFO_SOURCE_FUNC_DECL(1) #endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SOURCE_FUNC_DECL(2) +#endif + /*Show the async fifo flush size*/ #define ASYNCFIFO_FLUSHSIZE_FUNC_DECL(i) \ static ssize_t asyncfifo##i##_show_flush_size(struct class *class, \ @@ -1250,6 +1412,8 @@ static ssize_t asyncfifo##i##_show_flush_size(struct class *class, \ struct aml_dvb *dvb = &aml_dvb_device;\ struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ ssize_t ret = 0;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ ret = sprintf(buf, "%d\n", afifo->flush_size);\ return ret;\ } \ @@ -1262,7 +1426,10 @@ static ssize_t asyncfifo##i##_store_flush_size(struct class *class, \ /*int fsize = simple_strtol(buf, NULL, 10);*/\ int fsize = 0;\ long value;\ - int ret = kstrtol(buf, 0, &value);\ + int ret =0;\ + if (dvb->async_fifo_total_count <= i)\ + return (size_t)0;\ + ret = kstrtol(buf, 0, &value);\ if (ret == 0)\ fsize = value;\ if (fsize != afifo->flush_size) {\ @@ -1279,6 +1446,101 @@ ASYNCFIFO_FLUSHSIZE_FUNC_DECL(0) #if ASYNCFIFO_COUNT > 1 ASYNCFIFO_FLUSHSIZE_FUNC_DECL(1) #endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_FLUSHSIZE_FUNC_DECL(2) +#endif + +/*Show the async fifo secure buffer addr*/ +#define ASYNCFIFO_SECUREADDR_FUNC_DECL(i) \ +static ssize_t asyncfifo##i##_show_secure_addr(struct class *class, \ + struct class_attribute *attr, char *buf)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + ssize_t ret = 0;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ + ret = sprintf(buf, "0x%x\n", afifo->blk.addr);\ + return ret;\ +} \ +static ssize_t asyncfifo##i##_store_secure_addr(struct class *class, \ + struct class_attribute *attr, \ +const char *buf, size_t size)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + unsigned long value;\ + int ret=0;\ + if (dvb->async_fifo_total_count <= i)\ + return (size_t)0;\ + ret = kstrtol(buf, 0, &value);\ + if (ret == 0 && value != afifo->blk.addr) {\ + afifo->blk.addr = value;\ + aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ + } \ + return size;\ +} + +#if ASYNCFIFO_COUNT > 0 + ASYNCFIFO_SECUREADDR_FUNC_DECL(0) +#endif + +#if ASYNCFIFO_COUNT > 1 + ASYNCFIFO_SECUREADDR_FUNC_DECL(1) +#endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SECUREADDR_FUNC_DECL(2) +#endif + + +/*Show the async fifo secure enable*/ +#define ASYNCFIFO_SECURENABLE_FUNC_DECL(i) \ +static ssize_t asyncfifo##i##_show_secure_enable(struct class *class, \ + struct class_attribute *attr, char *buf)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + ssize_t ret = 0;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ + ret = sprintf(buf, "%d\n", afifo->secure_enable);\ + return ret;\ +} \ +static ssize_t asyncfifo##i##_store_secure_enable(struct class *class, \ + struct class_attribute *attr, \ + const char *buf, size_t size)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + int enable = 0;\ + long value;\ + int ret=0;\ + if (dvb->async_fifo_total_count <= i)\ + return (size_t)0;\ + ret = kstrtol(buf, 0, &value);\ + if (ret == 0)\ + enable = value;\ + if (enable != afifo->secure_enable) {\ + afifo->secure_enable = enable;\ + aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ + } \ + return size;\ +} + +#if ASYNCFIFO_COUNT > 0 +ASYNCFIFO_SECURENABLE_FUNC_DECL(0) +#endif + +#if ASYNCFIFO_COUNT > 1 + ASYNCFIFO_SECURENABLE_FUNC_DECL(1) +#endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SECURENABLE_FUNC_DECL(2) +#endif + /*Reset the Demux*/ static ssize_t demux_do_reset(struct class *class, struct class_attribute *attr, @@ -1321,6 +1583,31 @@ static ssize_t demux_show_audio_pts(struct class *class, return ret; } +/*Show the Video PTS bit32 value*/ +static ssize_t demux_show_video_pts_bit32(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_dvb *dvb = &aml_dvb_device; + ssize_t ret = 0; + + ret = sprintf(buf, "%u\n", aml_dmx_get_video_pts_bit32(dvb)); + + return ret; +} + +/*Show the Audio PTS bit32 value*/ +static ssize_t demux_show_audio_pts_bit32(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_dvb *dvb = &aml_dvb_device; + ssize_t ret = 0; + + ret = sprintf(buf, "%u\n", aml_dmx_get_audio_pts_bit32(dvb)); + + return ret; +} + + /*Show the First Video PTS value*/ static ssize_t demux_show_first_video_pts(struct class *class, struct class_attribute *attr, @@ -1355,7 +1642,7 @@ static ssize_t stb_show_hw_setting(struct class *class, struct aml_dvb *dvb = &aml_dvb_device; int invert, ctrl; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { struct aml_ts_input *ts = &dvb->ts[i]; if (ts->s2p_id != -1) @@ -1391,7 +1678,7 @@ static ssize_t stb_store_hw_setting(struct class *class, if (r != 4) return -EINVAL; - if (id < 0 || id >= TS_IN_COUNT) + if (id < 0 || id >= dvb->ts_in_total_count) return -EINVAL; if ((mname[0] == 's') || (mname[0] == 'S')) { @@ -1411,12 +1698,12 @@ static ssize_t stb_store_hw_setting(struct class *class, int i; int scnt = 0; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { if (dvb->ts[i].s2p_id != -1) scnt++; } - if (scnt >= S2P_COUNT) + if (scnt >= dvb->s2p_total_count) pr_error("no free s2p\n"); else ts->s2p_id = scnt; @@ -1445,6 +1732,82 @@ static ssize_t stb_store_hw_setting(struct class *class, return count; } +static ssize_t stb_show_tuner_setting(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_dvb *dvb = &aml_dvb_device; + + if (dvb->tuner_cur >= 0) + pr_inf("dvb current attatch tuner %d, id: %d\n", + dvb->tuner_cur, dvb->tuners[dvb->tuner_cur].cfg.id); + else + pr_inf("dvb has no attatch tuner.\n"); + + return 0; +} + +static ssize_t stb_store_tuner_setting(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int n = 0, i = 0, val = 0; + unsigned long tmp = 0; + char *buf_orig = NULL, *ps = NULL, *token = NULL; + char *parm[4] = { NULL }; + struct aml_dvb *dvb = &aml_dvb_device; + int tuner_id = 0; + struct aml_tuner *tuner = NULL; + + buf_orig = kstrdup(buf, GFP_KERNEL); + ps = buf_orig; + + while (1) { + token = strsep(&ps, "\n "); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } + + if (parm[0] && kstrtoul(parm[0], 10, &tmp) == 0) { + val = tmp; + + for (i = 0; i < dvb->tuner_num; ++i) { + if (dvb->tuners[i].cfg.id == val) { + tuner_id = dvb->tuners[i].cfg.id; + break; + } + } + + if (tuner_id == 0 || dvb->tuner_cur == i) { + pr_error("%s: set nonsupport or the same tuner %d.\n", + __func__, val); + goto EXIT; + } + + dvb->tuner_cur = i; + + for (i = 0; i < FE_DEV_COUNT; i++) { + tuner = &dvb->tuners[dvb->tuner_cur]; + + if (frontend[i] == NULL) + continue; + + if (dvb_attach_tuner(frontend[i], tuner, &s_tuner_type[i]) < 0) { + pr_error("attach tuner %d failed\n", dvb->tuner_cur); + goto EXIT; + } + } + + pr_error("%s: attach tuner %d done.\n", __func__, dvb->tuners[dvb->tuner_cur].cfg.id); + } + +EXIT: + + return count; +} + static struct class_attribute aml_stb_class_attrs[] = { __ATTR(hw_setting, 0664, stb_show_hw_setting, stb_store_hw_setting), @@ -1514,13 +1877,33 @@ static struct class_attribute aml_stb_class_attrs[] = { __ATTR(asyncfifo##i##_flush_size, 0664,\ asyncfifo##i##_show_flush_size, \ asyncfifo##i##_store_flush_size) +#define ASYNCFIFO_SECUREADDR_ATTR_DECL(i)\ + __ATTR(asyncfifo##i##_secure_addr, S_IRUGO | S_IWUSR | S_IWGRP,\ + asyncfifo##i##_show_secure_addr, \ + asyncfifo##i##_store_secure_addr) +#define ASYNCFIFO_SECURENABLE_ATTR_DECL(i)\ + __ATTR(asyncfifo##i##_secure_enable, S_IRUGO | S_IWUSR | S_IWGRP,\ + asyncfifo##i##_show_secure_enable, \ + asyncfifo##i##_store_secure_enable) + #if ASYNCFIFO_COUNT > 0 ASYNCFIFO_SOURCE_ATTR_DECL(0), ASYNCFIFO_FLUSHSIZE_ATTR_DECL(0), + ASYNCFIFO_SECUREADDR_ATTR_DECL(0), + ASYNCFIFO_SECURENABLE_ATTR_DECL(0), #endif #if ASYNCFIFO_COUNT > 1 ASYNCFIFO_SOURCE_ATTR_DECL(1), ASYNCFIFO_FLUSHSIZE_ATTR_DECL(1), + ASYNCFIFO_SECUREADDR_ATTR_DECL(1), + ASYNCFIFO_SECURENABLE_ATTR_DECL(1), +#endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SOURCE_ATTR_DECL(2), + ASYNCFIFO_FLUSHSIZE_ATTR_DECL(2), + ASYNCFIFO_SECUREADDR_ATTR_DECL(2), + ASYNCFIFO_SECURENABLE_ATTR_DECL(2), #endif __ATTR(demux_reset, 0644, NULL, demux_do_reset), @@ -1528,10 +1911,13 @@ static struct class_attribute aml_stb_class_attrs[] = { NULL), __ATTR(audio_pts, 0664, demux_show_audio_pts, NULL), + __ATTR(video_pts_bit32, 0644, demux_show_video_pts_bit32, NULL), + __ATTR(audio_pts_bit32, 0644, demux_show_audio_pts_bit32, NULL), __ATTR(first_video_pts, 0644, demux_show_first_video_pts, NULL), __ATTR(first_audio_pts, 0644, demux_show_first_audio_pts, NULL), + __ATTR(clear_av, 0644, NULL, stb_clear_av), #define DSC_SOURCE_ATTR_DECL(i)\ __ATTR(dsc##i##_source, 0664,\ @@ -1549,6 +1935,8 @@ static struct class_attribute aml_stb_class_attrs[] = { DSC_FREE_ATTR_DECL(1), #endif + __ATTR(tuner_setting, 0664, stb_show_tuner_setting, stb_store_tuner_setting), + __ATTR_NULL }; @@ -1577,7 +1965,7 @@ static int aml_dvb_probe(struct platform_device *pdev) int i, ret = 0; struct devio_aml_platform_data *pd_dvb; - pr_inf("probe amlogic dvb driver\n"); + pr_dbg("probe amlogic dvb driver\n"); /*switch_mod_gate_by_name("demux", 1); */ #if 0 @@ -1642,6 +2030,16 @@ static int aml_dvb_probe(struct platform_device *pdev) amports_switch_gate("demux", 1); amports_switch_gate("ahbarb0", 1); amports_switch_gate("parser_top", 1); + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + { + aml_dvb_afifo_clk = + devm_clk_get(&pdev->dev, "asyncfifo"); + if (IS_ERR_OR_NULL(aml_dvb_afifo_clk)) { + dev_err(&pdev->dev, "get asyncfifo clk fail\n"); + return -1; + } + clk_prepare_enable(aml_dvb_afifo_clk); + } } #endif advb = &aml_dvb_device; @@ -1654,6 +2052,16 @@ static int aml_dvb_probe(struct platform_device *pdev) advb->stb_source = -1; advb->tso_source = -1; + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) { + advb->ts_in_total_count = 3; + advb->s2p_total_count = 2; + advb->async_fifo_total_count = 2; + } else { + advb->ts_in_total_count = 4; + advb->s2p_total_count = 3; + advb->async_fifo_total_count = 3; + } + for (i = 0; i < DMX_DEV_COUNT; i++) { advb->dmx[i].dmx_irq = -1; advb->dmx[i].dvr_irq = -1; @@ -1666,7 +2074,7 @@ static int aml_dvb_probe(struct platform_device *pdev) const char *str; u32 value; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < advb->ts_in_total_count; i++) { advb->ts[i].mode = AM_TS_DISABLE; advb->ts[i].s2p_id = -1; @@ -1680,7 +2088,7 @@ static int aml_dvb_probe(struct platform_device *pdev) if (!strcmp(str, "serial")) { pr_inf("%s: serial\n", buf); - if (s2p_id >= S2P_COUNT) + if (s2p_id >= advb->s2p_total_count) pr_error("no free s2p\n"); else { snprintf(buf, sizeof(buf), @@ -1760,10 +2168,9 @@ static int aml_dvb_probe(struct platform_device *pdev) for (i = 0; idsc[i].id = -1; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { - for (i = 0; i < ASYNCFIFO_COUNT; i++) - advb->asyncfifo[i].id = -1; - } + for (i = 0; i < advb->async_fifo_total_count; i++) + advb->asyncfifo[i].id = -1; + advb->dvb_adapter.priv = advb; dev_set_drvdata(advb->dev, advb); @@ -1778,15 +2185,14 @@ static int aml_dvb_probe(struct platform_device *pdev) if (ret < 0) goto error; } - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - /*Init the async fifos */ - for (i = 0; i < ASYNCFIFO_COUNT; i++) { - ret = aml_dvb_asyncfifo_init(advb, &advb->asyncfifo[i], i); - if (ret < 0) - goto error; - } + + /*Init the async fifos */ + for (i = 0; i < advb->async_fifo_total_count; i++) { + ret = aml_dvb_asyncfifo_init(advb, &advb->asyncfifo[i], i); + if (ret < 0) + goto error; } + aml_regist_dmx_class(); if (class_register(&aml_stb_class) < 0) { @@ -1803,11 +2209,13 @@ static int aml_dvb_probe(struct platform_device *pdev) //pengcc add for dvb using linux TV frontend api init { struct amlfe_exp_config config; - struct i2c_adapter *i2c_adapter = NULL; char buf[32]; const char *str = NULL; + struct device_node *node_tuner = NULL; struct device_node *node_i2c = NULL; u32 i2c_addr = 0xFFFFFFFF; + u32 value = 0; + int j = 0; for (i=0; idev.of_node, buf, &str); - if (ret) { - // pr_error("tuner%d type error\n",i); - ret = 0; - continue; - } - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_i2c_adap_id",i); - node_i2c = of_parse_phandle(pdev->dev.of_node,buf,0); - if (!node_i2c) { - pr_error("tuner_i2c_adap_id error\n"); - } else { - i2c_adapter = of_find_i2c_adapter_by_node(node_i2c); - of_node_put(node_i2c); - if (i2c_adapter == NULL) { - pr_error("i2c_get_adapter error\n"); - goto error_fe; - } + node_tuner = of_parse_phandle(pdev->dev.of_node, buf, 0); + if (!node_tuner) { + pr_err("can't find tuner.\n"); + goto error_fe; } - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_tuner_i2c_addr",i); - ret = of_property_read_u32(pdev->dev.of_node, buf,&i2c_addr); + ret = of_property_read_u32(node_tuner, "tuner_num", &value); if (ret) { - pr_error("i2c_addr error\n"); + pr_err("can't find tuner_num.\n"); + goto error_fe; + } else + advb->tuner_num = value; + + advb->tuners = kzalloc(sizeof(struct aml_tuner) * advb->tuner_num, GFP_KERNEL); + if (!advb->tuners) { + pr_err("can't kzalloc for tuners.\n"); + goto error_fe; } + + ret = of_property_read_u32(node_tuner, "tuner_cur", &value); + if (ret) { + pr_err("can't find tuner_cur, use default 0.\n"); + advb->tuner_cur = -1; + } else + advb->tuner_cur = value; + + for (j = 0; j < advb->tuner_num; ++j) { + snprintf(buf, sizeof(buf), "tuner_name_%d", j); + ret = of_property_read_string(node_tuner, buf, &str); + if (ret) { + //pr_error("tuner%d type error\n",i); + ret = 0; + continue; + } else { + if (!strncmp(str, "mxl661_tuner", 12)) + advb->tuners[j].cfg.id = AM_TUNER_MXL661; + else if (!strncmp(str, "si2151_tuner", 12)) + advb->tuners[j].cfg.id = AM_TUNER_SI2151; + else if (!strncmp(str, "si2159_tuner", 12)) + advb->tuners[j].cfg.id = AM_TUNER_SI2159; + else if (!strncmp(str, "r840_tuner", 10)) + advb->tuners[j].cfg.id = AM_TUNER_R840; + else if (!strncmp(str, "r842_tuner", 10)) + advb->tuners[j].cfg.id = AM_TUNER_R842; + else { + pr_err("nonsupport tuner: %s.\n", str); + advb->tuners[j].cfg.id = AM_TUNER_NONE; + } + } + + snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", j); + node_i2c = of_parse_phandle(node_tuner, buf, 0); + if (!node_i2c) { + pr_error("tuner_i2c_adap_id error\n"); + } else { + advb->tuners[j].i2c_adp = of_find_i2c_adapter_by_node(node_i2c); + of_node_put(node_i2c); + if (advb->tuners[j].i2c_adp == NULL) { + pr_error("i2c_get_adapter error\n"); + of_node_put(node_tuner); + goto error_fe; + } + } + + snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", j); + ret = of_property_read_u32(node_tuner, buf, &i2c_addr); + if (ret) { + pr_error("i2c_addr error\n"); + } + else + advb->tuners[j].cfg.i2c_addr = i2c_addr; + + snprintf(buf, sizeof(buf), "tuner_xtal_%d", j); + ret = of_property_read_u32(node_tuner, buf, &value); + if (ret) + pr_err("tuner_xtal error.\n"); + else + advb->tuners[j].cfg.xtal = value; + + snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", j); + ret = of_property_read_u32(node_tuner, buf, &value); + if (ret) + pr_err("tuner_xtal_mode error.\n"); + else + advb->tuners[j].cfg.xtal_mode = value; + + snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", j); + ret = of_property_read_u32(node_tuner, buf, &value); + if (ret) + pr_err("tuner_xtal_cap error.\n"); + else + advb->tuners[j].cfg.xtal_cap = value; + } + + of_node_put(node_tuner); + /* define general-purpose callback pointer */ frontend[i]->callback = NULL; - if (!strcmp(str,"si2151_tuner")) { - if (!dvb_attach(si2151_attach, frontend[i],i2c_adapter,i2c_addr)) { - pr_error("dvb attach tuner error\n"); + if (advb->tuner_cur >= 0) { + if (dvb_attach_tuner(frontend[i], &advb->tuners[advb->tuner_cur], &s_tuner_type[i]) < 0) { + pr_error("attach tuner failed\n"); goto error_fe; - } else { - pr_inf("si2151 attach sucess\n"); - s_tuner_type[i] = TUNER_SI2151; } - }else if(!strcmp(str,"mxl661_tuner")) { - if (!dvb_attach(mxl661_attach, frontend[i],i2c_adapter,i2c_addr)) { - pr_error("dvb attach mxl661_attach tuner error\n"); - goto error_fe; - } else { - pr_inf("mxl661_attach attach sucess\n"); - s_tuner_type[i] = TUNER_MXL661; - } - }else if(!strcmp(str,"si2159_tuner")) { - if (!dvb_attach(si2159_attach, frontend[i],i2c_adapter,i2c_addr)) { - pr_error("dvb attach si2159_attach tuner error\n"); - goto error_fe; - } else { - pr_inf("si2159_attach attach sucess\n"); - s_tuner_type[i] = TUNER_SI2159; - } - }else { - pr_error("can't support tuner type: %s\n",str); } + ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]); if (ret) { pr_error("register dvb frontend failed\n"); @@ -1966,6 +2424,16 @@ static int aml_dvb_probe(struct platform_device *pdev) s_demod_type[i] = DEMOD_ATBM8881; } } + if (!strcmp(name,"Si2168")) { + frontend[i] = dvb_attach(si2168_attach,&config); + if (frontend[i] == NULL) { + pr_error("dvb attach demod error\n"); + goto error_fe; + } else { + pr_inf("dtvdemod attatch sucess\n"); + s_demod_type[i] = DEMOD_SI2168; + } + } if (frontend[i]) { ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]); if (ret) { @@ -1986,6 +2454,10 @@ error_fe: dvb_detach(atbm8881_attach); frontend[i] = NULL; s_demod_type[i] = DEMOD_INVALID; + }else if (s_demod_type[i] == DEMOD_SI2168) { + dvb_detach(si2168_attach); + frontend[i] = NULL; + s_demod_type[i] = DEMOD_INVALID; } if (s_tuner_type[i] == TUNER_SI2151) { dvb_detach(si2151_attach); @@ -1996,19 +2468,27 @@ error_fe: }else if (s_tuner_type[i] == TUNER_SI2159) { dvb_detach(si2159_attach); s_tuner_type[i] = TUNER_INVALID; + }else if (s_tuner_type[i] == TUNER_R842) { + dvb_detach(r842_attach); + s_tuner_type[i] = TUNER_INVALID; + }else if (s_tuner_type[i] == TUNER_R840) { + dvb_detach(r840_attach); + s_tuner_type[i] = TUNER_INVALID; } } return 0; } + + if (advb->tuners) + kfree(advb->tuners); + return 0; error: - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - for (i = 0; i < ASYNCFIFO_COUNT; i++) { - if (advb->asyncfifo[i].id != -1) - aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); - } + for (i = 0; i < advb->async_fifo_total_count; i++) { + if (advb->asyncfifo[i].id != -1) + aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); } + for (i = 0; i < DMX_DEV_COUNT; i++) { if (advb->dmx[i].id != -1) aml_dvb_dmx_release(advb, &advb->dmx[i]); @@ -2033,6 +2513,8 @@ static int aml_dvb_remove(struct platform_device *pdev) dvb_detach(aml_dtvdm_attach); }else if (s_demod_type[i] == DEMOD_ATBM8881) { dvb_detach(atbm8881_attach); + }else if (s_demod_type[i] == DEMOD_SI2168) { + dvb_detach(si2168_attach); } if (s_tuner_type[i] == TUNER_SI2151) { dvb_detach(si2151_attach); @@ -2040,10 +2522,14 @@ static int aml_dvb_remove(struct platform_device *pdev) dvb_detach(mxl661_attach); }else if (s_tuner_type[i] == TUNER_SI2159) { dvb_detach(si2159_attach); + }else if (s_tuner_type[i] == TUNER_R842) { + dvb_detach(r842_attach); + }else if (s_tuner_type[i] == TUNER_R840) { + dvb_detach(r840_attach); } if (frontend[i] && \ - ( (s_tuner_type[i] == TUNER_SI2151) || (s_tuner_type[i] == TUNER_MXL661) || (s_tuner_type[i] == TUNER_SI2159) ) \ + ( (s_tuner_type[i] == TUNER_SI2151) || (s_tuner_type[i] == TUNER_MXL661) || (s_tuner_type[i] == TUNER_SI2159) || (s_tuner_type[i] == TUNER_R842) || (s_tuner_type[i] == TUNER_R840)) \ ) { dvb_unregister_frontend(frontend[i]); @@ -2058,12 +2544,10 @@ static int aml_dvb_remove(struct platform_device *pdev) aml_unregist_dmx_class(); class_unregister(&aml_stb_class); - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - for (i = 0; i < ASYNCFIFO_COUNT; i++) { - if (advb->asyncfifo[i].id != -1) - aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); - } + + for (i = 0; i < advb->async_fifo_total_count; i++) { + if (advb->asyncfifo[i].id != -1) + aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); } for (i = 0; i < DMX_DEV_COUNT; i++) { @@ -2078,7 +2562,7 @@ static int aml_dvb_remove(struct platform_device *pdev) } dvb_unregister_adapter(&advb->dvb_adapter); - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < advb->ts_in_total_count; i++) { if (advb->ts[i].pinctrl && !IS_ERR_VALUE(advb->ts[i].pinctrl)) devm_pinctrl_put(advb->ts[i].pinctrl); } @@ -2103,9 +2587,17 @@ static int aml_dvb_remove(struct platform_device *pdev) amports_switch_gate("demux", 0); amports_switch_gate("ahbarb0", 0); amports_switch_gate("parser_top", 0); + + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + clk_disable_unprepare(aml_dvb_afifo_clk); + } } #endif #endif + + if (advb->tuners) + kfree(advb->tuners); + return 0; } diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h index f04c5c915a47..50ad86215f46 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _AML_DVB_H_ #define _AML_DVB_H_ @@ -35,8 +54,16 @@ #include #include +#include "aml_demod_gt.h" + +#define TS_IN_COUNT 4 +#define S2P_COUNT 3 +#define ASYNCFIFO_COUNT 3 +#if 0 #define TS_IN_COUNT 3 #define S2P_COUNT 2 +#define ASYNCFIFO_COUNT 2 +#endif #define DMX_DEV_COUNT 3 #define FE_DEV_COUNT 2 @@ -48,7 +75,6 @@ #define SEC_BUF_GRP_COUNT 4 #define SEC_BUF_BUSY_SIZE 4 #define SEC_BUF_COUNT (SEC_BUF_GRP_COUNT*8) -#define ASYNCFIFO_COUNT 2 enum aml_dmx_id_t { AM_DMX_0 = 0, @@ -61,10 +87,14 @@ enum aml_ts_source_t { AM_TS_SRC_TS0, AM_TS_SRC_TS1, AM_TS_SRC_TS2, + AM_TS_SRC_TS3, + AM_TS_SRC_S_TS0, AM_TS_SRC_S_TS1, AM_TS_SRC_S_TS2, + AM_TS_SRC_HIU, + AM_TS_SRC_HIU1, AM_TS_SRC_DMX0, AM_TS_SRC_DMX1, AM_TS_SRC_DMX2 @@ -97,27 +127,32 @@ struct aml_filter { #define DVBCSA_MODE 0 #define CIPLUS_MODE 1 -#define AES_CBC_MODE 0 -#define AES_ECB_MODE 1 +#define CBC_MODE 0 +#define ECB_MODE 1 +#define IDSA_MODE 2 #define DSC_SET_EVEN 1 #define DSC_SET_ODD 2 #define DSC_SET_AES_EVEN 4 #define DSC_SET_AES_ODD 8 #define DSC_FROM_KL 16 +#define DSC_SET_SM4_EVEN 32 +#define DSC_SET_SM4_ODD 64 + +#define DSC_KEY_SIZE_MAX 16 struct aml_dsc_channel { int pid; - u8 even[8]; - u8 odd[8]; - u8 aes_even[16]; - u8 aes_odd[16]; + u8 even[DSC_KEY_SIZE_MAX]; + u8 odd[DSC_KEY_SIZE_MAX]; + u8 even_iv[DSC_KEY_SIZE_MAX]; + u8 odd_iv[DSC_KEY_SIZE_MAX]; int used; - int flags; + int set; int id; struct aml_dsc *dsc; int work_mode; - int aes_mode; + int mode; }; struct aml_dsc { @@ -214,6 +249,11 @@ struct aml_dmx { u32 crc_check_time; }; +struct aml_dvr_block { + u32 addr; + u32 len; +}; + struct aml_asyncfifo { int id; int init; @@ -225,8 +265,10 @@ struct aml_asyncfifo { int buf_toggle; int buf_read; int flush_size; + int secure_enable; struct tasklet_struct asyncfifo_tasklet; struct aml_dvb *dvb; + struct aml_dvr_block blk; }; enum{ @@ -258,13 +300,21 @@ struct aml_swfilter { int track_dmx; }; +struct aml_tuner { + struct tuner_config cfg; + unsigned int i2c_adapter_id; + struct i2c_adapter *i2c_adp; +}; + struct aml_dvb { struct dvb_device dvb_dev; - + int ts_in_total_count; struct aml_ts_input ts[TS_IN_COUNT]; + int s2p_total_count; struct aml_s2p s2p[S2P_COUNT]; struct aml_dmx dmx[DMX_DEV_COUNT]; struct aml_dsc dsc[DSC_DEV_COUNT]; + int async_fifo_total_count; struct aml_asyncfifo asyncfifo[ASYNCFIFO_COUNT]; struct dvb_adapter dvb_adapter; struct device *dev; @@ -278,6 +328,11 @@ struct aml_dvb { int dmx_watchdog_disable[DMX_DEV_COUNT]; struct aml_swfilter swfilter; int ts_out_invert; + + unsigned int tuner_num; + unsigned int tuner_cur; + struct aml_tuner *tuners; + bool tuner_attached; }; @@ -320,6 +375,8 @@ extern int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo); /*Get the Audio & Video PTS*/ extern u32 aml_dmx_get_video_pts(struct aml_dvb *dvb); extern u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb); +extern u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb); +extern u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb); extern u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb); extern u32 aml_dmx_get_first_audio_pts(struct aml_dvb *dvb); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h index 180b3d897e96..dbfa6ba43a6d 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h @@ -25,9 +25,10 @@ #define ID_STB_CBUS_BASE 0 #define ID_SMARTCARD_REG_BASE 1 #define ID_ASYNC_FIFO_REG_BASE 2 -#define ID_ASYNC_FIFO2_REG_BASE 3 -#define ID_RESET_BASE 4 -#define ID_PARSER_SUB_START_PTR_BASE 5 +#define ID_ASYNC_FIFO1_REG_BASE 3 +#define ID_ASYNC_FIFO2_REG_BASE 4 +#define ID_RESET_BASE 5 +#define ID_PARSER_SUB_START_PTR_BASE 6 long aml_stb_get_base(int id); #include "c_stb_define.h" @@ -52,5 +53,6 @@ long aml_stb_get_base(int id); #define INT_ASYNC_FIFO2_FILL AM_IRQ(24) #define INT_ASYNC_FIFO2_FLUSH AM_IRQ(25) +#define INT_ASYNC_FIFO3_FLUSH AM_IRQ(17) #endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h index a5309d52753c..6b815b67bbd7 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* ----------------------------------------------------------------------*/ /* This file is automatically generated from the script:*/ /**/ @@ -43,11 +62,12 @@ /* bit 19 -- invert fec_valid for S2P1*/ /* bit 18 -- invert fec_clk for S2P1*/ /* bit 17:16 -- fec_s_sel for S2P1 - * 00 - select TS0, 01 -- select TS1, 10 -- select TS2, 11 - reserved*/ + * 00 - select TS0, 01 -- select TS1, 10 -- select TS2, 11 - TS3*/ /* Bit 15 -- enable_des_pl_clk*/ -/* Bit 14:13 -- reserved*/ +/* Bit 14 -- reserved*/ +/* Bit 13 -- use FAIL for TS3*/ /* Bit 12:10 -- ts_out_select, - * 0-TS0, 1-TS1, 2-TS2, 3,4-Reserved, 5-S2P1, 6-S2P0, 7-File*/ + * 0-TS0, 1-TS1, 2-TS2, 3-TS3,4-S2P2, 5-S2P1, 6-S2P0, 7-File*/ /* bit 9:8 -- des_i_sel 00 -- select demux0 as des input, * 01 -- select_demux1, 10 -- select_demux2, 11 - reserved*/ /* bit 7 -- enable_des_pl*/ @@ -67,6 +87,7 @@ #define INVERT_S2P1_FEC_CLK 18 #define S2P1_FEC_SERIAL_SEL 16 #define ENABLE_DES_PL_CLK 15 +#define FAIL_TS3 13 #define TS_OUTPUT_SOURCE 10 #define DES_INPUT_SEL 8 #define ENABLE_DES_PL 7 @@ -77,6 +98,37 @@ #define INVERT_S2P0_FEC_CLK 2 #define S2P0_FEC_SERIAL_SEL 0 +//define STB_S2P2_CONFIG +#define S2P2_DISABLE 11 +#define S2P2_CLK_DIV 7 +#define INVERT_S2P2_FEC_ERROR 6 +#define INVERT_S2P2_FEC_DATA 5 +#define INVERT_S2P2_FEC_SYNC 4 +#define INVERT_S2P2_FEC_VALID 3 +#define INVERT_S2P2_FEC_CLK 2 +#define S2P2_FEC_SERIAL_SEL 0 + + +/* 31:24 -- file_m2ts_skip_bytes_hiu1*/ +/* 21 -- ts_hiu_enable_hiu1 */ +/*20:16 -- fec_clk_div_hiu1*/ +/*15:8 -- TS_package_length_sub_1_hiu1 */ +/*7:0 -- fec_sync_byte_hiu1*/ +/*#define TS_HIU1_CONFIG (STB_CBUS_BASE + 0x4e)*/ +#define FILE_M2TS_SKIP_BYTES_HIU1 24 +#define TS_HIU_ENABLE_HIU1 21 +#define FEC_CLK_DIV_HIU1 16 +#define TS_PACKAGE_LENGTH_SUB_1_HIU1 8 +#define FEC_SYNC_BYTE_HIU1 0 + +/*5:4 -- fec_sel_demux_2, default:2*/ +/*3:2 -- fec_sel_demux_1, default:1*/ +/*1:0 -- fec_sel_demux_0, default:0*/ +/*#define TS_TOP_CONFIG1 (STB_CBUS_BASE + 0x4f)*/ +#define FEC_SEL_DEMUX_2 4 +#define FEC_SEL_DEMUX_1 2 +#define FEC_SEL_DEMUX_0 0 + /* 31:28 - s2p1_clk_div*/ /* 27:24 - s2p0_clk_div*/ /* 23 - s2p1_disable*/ @@ -183,6 +235,7 @@ /*#define FEC_INPUT_CONTROL_3 * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x02) // 0x16a2*/ /*----------- bit define -----------*/ +#define FEC_SEL_3BIT 16 #define FEC_CORE_SEL 15 #define FEC_SEL 12 #define FEC_INPUT_FEC_CLK 11 @@ -705,8 +758,8 @@ #define BYPASS_ENDIAN 3 #define SECTION_ENDIAN 0 -/* Bit 15:8 -- last_burst_threshold*/ -/* Bit 7 -- use hi_bsf interface*/ +/* Bit 10:9 -- PDTS_wr_sel: 0 select video_PDTS_wr_ptr; 1 select video_PDTS_wr_ptr_parser_B; */ +/* Bit 7:8 -- use hi_bsf interface*/ /* Bit 6:2 - fec_clk_div*/ /* Bit 1 ts_source_sel */ /* Bit 0 - Hiu TS generate enable */ @@ -717,7 +770,8 @@ /*#define TS_HIU_CTL_3 * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x25) // 0x16c5*/ /*----------- bit define -----------*/ -#define LAST_BURST_THRESHOLD 8 +//#define LAST_BURST_THRESHOLD 8 +#define PDTS_WR_SEL 9 #define USE_HI_BSF_INTERFACE 7 /* bit 15:0 -- base address for section buffer start diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h index 5651ba7f5aa8..b12db6898f7d 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * This file is automaticly generated by genregs.awk. Please do not edit it * Base files are .. @@ -15,6 +34,7 @@ #define STB_CBUS_BASE aml_stb_get_base(ID_STB_CBUS_BASE) #define SMARTCARD_REG_BASE aml_stb_get_base(ID_SMARTCARD_REG_BASE) #define ASYNC_FIFO_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO_REG_BASE) +#define ASYNC_FIFO1_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO1_REG_BASE) #define ASYNC_FIFO2_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO2_REG_BASE) #define RESET_BASE aml_stb_get_base(ID_RESET_BASE) #define PARSER_SUB_START_PTR_BASE \ @@ -27,6 +47,18 @@ #define DEMUX_3_OFFSET 0xa0 +#define TS_HIU1_CONFIG (STB_CBUS_BASE + 0x4e) +#define P_TS_HIU1_CONFIG CBUS_REG_ADDR(TS_HIU1_CONFIG) + +#define TS_TOP_CONFIG1 (STB_CBUS_BASE + 0x4f) +#define P_TS_TOP_CONFIG1 CBUS_REG_ADDR(TS_TOP_CONFIG1) + +#define STB_S2P2_CONFIG (STB_CBUS_BASE + 0xef) +#define P_STB_S2P2_CONFIG CBUS_REG_ADDR(STB_S2P2_CONFIG) + +#define STB_RECORDER2_CNTL (STB_CBUS_BASE + 0xee) +#define P_STB_RECORDER2_CNTL CBUS_REG_ADDR(STB_RECORDER2_CNTL) + #define STB_TOP_CONFIG (STB_CBUS_BASE + 0xf0) #define P_STB_TOP_CONFIG CBUS_REG_ADDR(STB_TOP_CONFIG) #define TS_TOP_CONFIG (STB_CBUS_BASE + 0xf1) @@ -90,6 +122,19 @@ #define ASYNC_FIFO_REG5 (ASYNC_FIFO_REG_BASE + 0x5) #define P_ASYNC_FIFO_REG5 CBUS_REG_ADDR(ASYNC_FIFO_REG5) +#define ASYNC_FIFO1_REG0 (ASYNC_FIFO1_REG_BASE + 0x0) +#define P_ASYNC_FIFO1_REG0 CBUS_REG_ADDR(ASYNC_FIFO1_REG0) +#define ASYNC_FIFO1_REG1 (ASYNC_FIFO1_REG_BASE + 0x1) +#define P_ASYNC_FIFO1_REG1 CBUS_REG_ADDR(ASYNC_FIFO1_REG1) +#define ASYNC_FIFO1_REG2 (ASYNC_FIFO1_REG_BASE + 0x2) +#define P_ASYNC_FIFO1_REG2 CBUS_REG_ADDR(ASYNC_FIFO1_REG2) +#define ASYNC_FIFO1_REG3 (ASYNC_FIFO1_REG_BASE + 0x3) +#define P_ASYNC_FIFO1_REG3 CBUS_REG_ADDR(ASYNC_FIFO1_REG3) +#define ASYNC_FIFO1_REG4 (ASYNC_FIFO1_REG_BASE + 0x4) +#define P_ASYNC_FIFO1_REG4 CBUS_REG_ADDR(ASYNC_FIFO1_REG4) +#define ASYNC_FIFO1_REG5 (ASYNC_FIFO1_REG_BASE + 0x5) +#define P_ASYNC_FIFO1_REG5 CBUS_REG_ADDR(ASYNC_FIFO1_REG5) + #define ASYNC_FIFO2_REG0 (ASYNC_FIFO2_REG_BASE + 0x0) #define P_ASYNC_FIFO2_REG0 CBUS_REG_ADDR(ASYNC_FIFO2_REG0) diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile index e258f64ad7dd..bbfbdd48e16a 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile @@ -1,9 +1,15 @@ -obj-m += aml_hardware_spi.o aml_hardware_pcmcia.o aml_hardware_ci.o +obj-m += ci.o cimax-usb.o -ccflags-y += -I$(srctree)/drivers/media/dvb-core -I$(srctree)/drivers/gpio -I$(srctree)/include +ci-objs = $(amlci-objs) $(cimax-objs) -aml_hardware_spi-objs += aml_spi.o +amlci-objs = aml_pcmcia.o aml_ci.o +cimax-objs = cimax/dvb_ca_en50221_cimax.o cimax/aml_cimax.o cimax/dvb_ringbuffer.o +cimax-usb-objs += cimax/usb/SRC/cimax+usb-driver.o cimax/usb/SRC/cimax+usb_fw.o +cimax-usb-objs += cimax/usb/SRC/cimax+usb_config.o +cimax-objs += cimax/aml_cimax_usb.o -aml_hardware_pcmcia-objs += aml_pcmcia.o +ccflags-y += -I$(srctree)/ +ccflags-y += -I$(srctree)/include +ccflags-y += -I$(srctree)/drivers/gpio +ccflags-y += -I$(srctree)/drivers/media/dvb-core -aml_hardware_ci-objs += aml_ci.o diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c index bf72b4ec5a5b..c28d2fc3cf83 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c @@ -1,36 +1,37 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + #include #include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include "aml_ci.h" #include "aml_spi.h" +#include "cimax/aml_cimax.h" MODULE_PARM_DESC(aml_ci_debug, "\n\t\t dvb ci debug"); static int aml_ci_debug = 1; -module_param(aml_ci_debug, int, 0444); +module_param(aml_ci_debug, int, S_IRUGO); #define pr_dbg(args...)\ do {\ @@ -71,7 +72,7 @@ static int aml_ci_mem_read(struct dvb_ca_en50221 *en50221, int slot, int addr) * - -EINVAL : error */ static int aml_ci_mem_write(struct dvb_ca_en50221 *en50221, - int slot, int addr, u8 data) + int slot, int addr, u8 data) { struct aml_ci *ci = en50221->data; @@ -118,8 +119,8 @@ static int aml_ci_io_read(struct dvb_ca_en50221 *en50221, int slot, u8 addr) * - 0:ok * - -EINVAL : error */ -static int aml_ci_io_write( - struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) +static int aml_ci_io_write(struct dvb_ca_en50221 *en50221, + int slot, u8 addr, u8 data) { struct aml_ci *ci = en50221->data; @@ -144,7 +145,6 @@ static int aml_ci_io_write( static int aml_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) { struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); if (ci->ci_slot_reset != NULL) { ci->ci_slot_reset(ci, slot); @@ -164,7 +164,6 @@ static int aml_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) static int aml_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) { struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot shutdown\n", slot); if (ci->ci_slot_shutdown != NULL) { ci->ci_slot_shutdown(ci, slot); @@ -185,7 +184,6 @@ static int aml_ci_ts_control(struct dvb_ca_en50221 *en50221, int slot) { struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): TS control\n", slot); if (ci->ci_slot_ts_enable != NULL) { ci->ci_slot_ts_enable(ci, slot); @@ -203,18 +201,282 @@ static int aml_ci_ts_control(struct dvb_ca_en50221 *en50221, int slot) * - cam status * - -EINVAL : error */ -static int aml_ci_slot_status( - struct dvb_ca_en50221 *en50221, int slot, int open) +static int aml_ci_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open) { struct aml_ci *ci = en50221->data; pr_dbg("Slot(%d): Poll Slot status\n", slot); - if (ci->ci_poll_slot_status != NULL) + if (ci->ci_poll_slot_status != NULL) { return ci->ci_poll_slot_status(ci, slot, open); - pr_error("ci_poll_slot_status is null %s\r\n", __func__); + } else { + pr_error("ci_poll_slot_status is null %s\r\n", __func__); + return -EINVAL; + } + return -EINVAL; } +static int aml_ci_cimax_slot_reset(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + struct aml_ci *ci = en50221->data; + pr_dbg("Slot(%d): Slot RESET\n", slot); + if (ci->ci_slot_reset != NULL) { + ci->ci_slot_reset(ci, slot); + } else { + pr_error("ci_slot_reset is null %s\r\n", __func__); + return -EINVAL; + } + return 0; +} +/**\brief aml_ci_slot_shutdown:show slot + * \param en50221: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \return + * - 0:ok + * - -EINVAL : error + */ +static int aml_ci_cimax_slot_shutdown(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + struct aml_ci *ci = en50221->data; + pr_dbg("Slot(%d): Slot shutdown\n", slot); + if (ci->ci_slot_shutdown != NULL) { + ci->ci_slot_shutdown(ci, slot); + } else { + pr_error("aml_ci_slot_shutdown is null %s\r\n", __func__); + return -EINVAL; + } + return 0; +} +/**\brief aml_ci_ts_control:control slot ts + * \param en50221: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \return + * - 0:ok + * - -EINVAL : error + */ +static int aml_ci_cimax_ts_control(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + + struct aml_ci *ci = en50221->data; + pr_dbg("Slot(%d): TS control\n", slot); + if (ci->ci_slot_ts_enable != NULL) { + ci->ci_slot_ts_enable(ci, slot); + } else { + pr_error("aml_ci_ts_control is null %s\r\n", __func__); + return -EINVAL; + } + return 0; +} +/**\brief aml_ci_slot_status:get slot status + * \param en50221: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param open: no used + * \return + * - cam status + * - -EINVAL : error + */ +static int aml_ci_cimax_slot_status( + struct dvb_ca_en50221_cimax *en50221, int slot, int open) +{ + struct aml_ci *ci = en50221->data; + + /*pr_dbg("Slot(%d): Poll Slot status\n", slot);*/ + + if (ci->ci_poll_slot_status != NULL) { + return ci->ci_poll_slot_status(ci, slot, open); + } else { + pr_error("ci_poll_slot_status is null %s\r\n", __func__); + return -EINVAL; + } + + return -EINVAL; +} + +/**\brief aml_ci_read_cis: read cis + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param buf: buf for cis data + * \param size: buf size + * \return + * --EINVAL : error + * - : actual size read + */ +static int aml_ci_read_cis(struct dvb_ca_en50221_cimax *en50221, + int slot, u8 *buf, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_read_cis != NULL) + return ci->ci_read_cis(ci, slot, buf, size); + + pr_error("ci_read_cis is null %s\r\n", __func__); + return -EINVAL; +} +/**\brief aml_ci_write_cor: write cor + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param addr: + * \param buf: + * \return + * --EINVAL : error + * -0 : ok + */ +static int aml_ci_write_cor(struct dvb_ca_en50221_cimax *en50221, + int slot, int address, u8 *buf) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_write_cor != NULL) + return ci->ci_write_cor(ci, slot, address, buf); + + pr_error("ci_write_cor is null %s\r\n", __func__); + return -EINVAL; +} +/**\brief aml_ci_negociate: negotiate + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param size: suggested size + * \return + * --EINVAL : error + * - : size negotiated + */ +static int aml_ci_negotiate(struct dvb_ca_en50221_cimax *en50221, + int slot, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_negotiate != NULL) + return ci->ci_negotiate(ci, slot, size); + + pr_error("ci_negotiate is null %s\r\n", __func__); + return -EINVAL; +} +/**\brief aml_ci_read_lpdu: read lpdu + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param buf: buf + * \param size: buf size + * \return + * --EINVAL : error + * - : size read + */ +static int aml_ci_read_lpdu(struct dvb_ca_en50221_cimax *en50221, + int slot, u8 *buf, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_read_lpdu != NULL) + return ci->ci_read_lpdu(ci, slot, buf, size); + + pr_error("ci_read_lpdu is null %s\r\n", __func__); + return -EINVAL; +} + +/**\brief aml_ci_write_lpdu: write lpdu + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param buf: buf + * \param size: write size + * \return + * --EINVAL : error + * - : size written + */ +static int aml_ci_write_lpdu(struct dvb_ca_en50221_cimax *en50221, + int slot, u8 *buf, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_write_lpdu != NULL) + return ci->ci_write_lpdu(ci, slot, buf, size); + + pr_error("ci_write_lpdu is null %s\r\n", __func__); + return -EINVAL; +} + +static int aml_ci_read_cam_status(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_read_cam_status != NULL) + return ci->ci_read_cam_status(ci, slot); + + pr_error("ci_read_cam_status is null %s\r\n", __func__); + return -EINVAL; +} + +static int aml_ci_cam_reset(struct dvb_ca_en50221_cimax *en50221, int slot) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_cam_reset != NULL) + return ci->ci_cam_reset(ci, slot); + + pr_error("ci_cam_reset is null %s\r\n", __func__); + return -EINVAL; +} + +/**\brief aml_ci_get_capbility + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \return + * - : capbilities + */ +static int aml_ci_get_capbility(struct dvb_ca_en50221_cimax *en50221, int slot) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_get_capbility != NULL) + return ci->ci_get_capbility(ci, slot); + + pr_error("ci_get_capbility is null %s\r\n", __func__); + return -EINVAL; +} + /**\brief get ci config from dts * \param np: device node @@ -222,8 +484,8 @@ static int aml_ci_slot_status( * - 0 æˆåŠŸ * - 其他值 : */ -static int aml_ci_get_config_from_dts( - struct platform_device *pdev, struct aml_ci *ci) +static int aml_ci_get_config_from_dts(struct platform_device *pdev, + struct aml_ci *ci) { char buf[32]; int ret = 0; @@ -263,67 +525,106 @@ int aml_ci_init(struct platform_device *pdev, aml_ci_get_config_from_dts(pdev, ci); ci->priv = dvb; - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; /* register CA interface */ - ci->en50221.owner = THIS_MODULE; - ci->en50221.read_attribute_mem = aml_ci_mem_read; - ci->en50221.write_attribute_mem = aml_ci_mem_write; - ci->en50221.read_cam_control = aml_ci_io_read; - ci->en50221.write_cam_control = aml_ci_io_write; - ci->en50221.slot_reset = aml_ci_slot_reset; - ci->en50221.slot_shutdown = aml_ci_slot_shutdown; - ci->en50221.slot_ts_enable = aml_ci_ts_control; - ci->en50221.poll_slot_status = aml_ci_slot_status; - ci->en50221.data = ci; + if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) { + ci->en50221_cimax.owner = THIS_MODULE; + ci->en50221_cimax.read_cis = aml_ci_read_cis; + ci->en50221_cimax.write_cor = aml_ci_write_cor; + ci->en50221_cimax.negotiate = aml_ci_negotiate; + ci->en50221_cimax.read_lpdu = aml_ci_read_lpdu; + ci->en50221_cimax.write_lpdu = aml_ci_write_lpdu; + ci->en50221_cimax.read_cam_status = aml_ci_read_cam_status; + ci->en50221_cimax.cam_reset = aml_ci_cam_reset; + ci->en50221_cimax.get_capbility = aml_ci_get_capbility; + ci->en50221_cimax.slot_reset = aml_ci_cimax_slot_reset; + ci->en50221_cimax.slot_shutdown = aml_ci_cimax_slot_shutdown; + ci->en50221_cimax.slot_ts_enable = aml_ci_cimax_ts_control; + ci->en50221_cimax.poll_slot_status = aml_ci_cimax_slot_status; + ci->en50221_cimax.data = ci; + + pr_dbg("Registering EN50221 CIMAX device\n"); + result = dvb_ca_en50221_cimax_init(dvb_adapter, + &ci->en50221_cimax, ca_flags, 1); + if (result != 0) { + pr_error("EN50221 CIMAX: Initialization failed <%d>\n", + result); + goto err; + } + } else { + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; + ci->en50221.read_attribute_mem = aml_ci_mem_read; + ci->en50221.write_attribute_mem = aml_ci_mem_write; + ci->en50221.read_cam_control = aml_ci_io_read; + ci->en50221.write_cam_control = aml_ci_io_write; + ci->en50221.slot_reset = aml_ci_slot_reset; + ci->en50221.slot_shutdown = aml_ci_slot_shutdown; + ci->en50221.slot_ts_enable = aml_ci_ts_control; + ci->en50221.poll_slot_status = aml_ci_slot_status; + ci->en50221.data = ci; - pr_dbg("Registering EN50221 device\n"); - result = dvb_ca_en50221_init(dvb_adapter, &ci->en50221, ca_flags, 1); - if (result != 0) { - pr_error("EN50221: Initialization failed <%d>\n", result); - goto err; + pr_dbg("Registering EN50221 device\n"); + result = dvb_ca_en50221_init(dvb_adapter, + &ci->en50221, ca_flags, 1); + if (result != 0) { + pr_error("EN50221: Initialization failed <%d>\n", + result); + goto err; + } } *cip = ci; pr_dbg("Registered EN50221 device\n"); + if (ci->io_type == AML_DVB_IO_TYPE_SPI) { /* spi init */ - aml_spi_init(pdev, ci); + //ci->ci_init = aml_spi_init; + //ci->ci_exit = aml_spi_exit; + } else if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) { + ci->ci_init = aml_cimax_init; + ci->ci_exit = aml_cimax_exit; } else { /* no io dev init,is error */ - pr_dbg("io dev no init,we do not known use spi or iobus or other,please check io_type in dts file\r\n"); + pr_dbg("unknown io type, please check io_type in dts file\r\n"); } - return 0; + + if (ci->ci_init) + result = ci->ci_init(pdev, ci); + + if (result) + dvb_ca_en50221_cimax_release(&ci->en50221_cimax); + + return result; err: - /* for init spi */ - aml_spi_exit(); kfree(ci); return result; } -EXPORT_SYMBOL_GPL(aml_ci_init); void aml_ci_exit(struct aml_ci *ci) { pr_dbg("Unregistering EN50221 device\n"); if (ci) { - dvb_ca_en50221_release(&ci->en50221); + if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) + dvb_ca_en50221_cimax_release(&ci->en50221_cimax); + else + dvb_ca_en50221_release(&ci->en50221); + if (ci->ci_exit) + ci->ci_exit(ci); kfree(ci); } } -EXPORT_SYMBOL_GPL(aml_ci_exit); static struct aml_ci *ci_dev; static ssize_t aml_ci_ts_show(struct class *class, -struct class_attribute *attr, char *buf) + struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "ts%d\n", 1); return ret; } static struct class_attribute amlci_class_attrs[] = { - __ATTR(ts, 0644, aml_ci_ts_show, NULL), + __ATTR(ts, S_IRUGO | S_IWUSR, aml_ci_ts_show, NULL), __ATTR_NULL }; @@ -361,7 +662,6 @@ static int aml_ci_probe(struct platform_device *pdev) { struct aml_dvb *dvb = aml_get_dvb_device(); int err = 0; - pr_dbg("---Amlogic CI Init---\n"); err = aml_ci_init(pdev, dvb, &ci_dev); if (err < 0) @@ -375,10 +675,13 @@ static int aml_ci_remove(struct platform_device *pdev) { aml_ci_unregister_class(ci_dev); platform_set_drvdata(pdev, NULL); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) - aml_spi_exit(); + if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { + //aml_spi_exit(ci_dev); + } + else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) + aml_cimax_exit(ci_dev); else - pr_dbg("---Amlogic CI remove unknown io type---\n"); + pr_dbg("---Amlogic CI remove unkown io type---\n"); aml_ci_exit(ci_dev); return 0; @@ -387,10 +690,13 @@ static int aml_ci_remove(struct platform_device *pdev) static int aml_ci_suspend(struct platform_device *pdev, pm_message_t state) { pr_dbg("Amlogic CI Suspend!\n"); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) - aml_spi_exit(); + if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { + //aml_spi_exit(ci_dev); + } + else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) + aml_cimax_exit(ci_dev); else - pr_dbg("---Amlogic CI remove unknown io type---\n"); + pr_dbg("---Amlogic CI remove unkown io type---\n"); return 0; } @@ -398,12 +704,14 @@ static int aml_ci_suspend(struct platform_device *pdev, pm_message_t state) static int aml_ci_resume(struct platform_device *pdev) { int err = 0; - pr_dbg("Amlogic CI Resume!\n"); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) - aml_spi_init(pdev, ci_dev); + if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { + //aml_spi_init(pdev, ci_dev); + } + else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) + aml_cimax_init(pdev, ci_dev); else - pr_dbg("---Amlogic CI remove unknown io type---\n"); + pr_dbg("---Amlogic CI remove unkown io type---\n"); return err; } @@ -428,13 +736,13 @@ static struct platform_driver aml_ci_driver = { } }; -static int __init aml_ci_mod_init(void) +static int aml_ci_mod_init(void) { pr_dbg("Amlogic CI mode init\n"); return platform_driver_register(&aml_ci_driver); } -static void __exit aml_ci_mod_exit(void) +static void aml_ci_mod_exit(void) { pr_dbg("Amlogic CI mode Exit\n"); platform_driver_unregister(&aml_ci_driver); @@ -442,7 +750,5 @@ static void __exit aml_ci_mod_exit(void) module_init(aml_ci_mod_init); module_exit(aml_ci_mod_exit); - MODULE_LICENSE("GPL"); - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h index 03f5e5e2c141..3e34417e0c39 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h @@ -1,22 +1,47 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + #ifndef __AML_CI_H_ #define __AML_CI_H_ -#include +#include "drivers/media/dvb-core/dvb_ca_en50221.h" +#include "cimax/dvb_ca_en50221_cimax.h" #include "../aml_dvb.h" enum aml_dvb_io_type_e { AML_DVB_IO_TYPE_IOBUS = 0, AML_DVB_IO_TYPE_SPI, + AML_DVB_IO_TYPE_CIMAX, AML_DVB_IO_TYPE_MAX, }; struct aml_ci { - struct dvb_ca_en50221 en50221; - struct mutex ci_lock; - int io_type; - void *priv; - int id; - struct class class; + struct dvb_ca_en50221 en50221; + struct mutex ci_lock; + int io_type; + void *priv; + int id; + struct class class; + + int (*ci_init)(struct platform_device *pdev, struct aml_ci *ci); + int (*ci_exit)(struct aml_ci *ci); /* NOTE: the read_*, write_* and poll_slot_status functions will be * called for different slots concurrently and need to use locks where @@ -37,11 +62,28 @@ struct aml_ci { int (*ci_slot_ts_enable)(struct aml_ci *ca, int slot); /* - * Poll slot status. - * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set - */ + * Poll slot status. + * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set + */ int (*ci_poll_slot_status)(struct aml_ci *ca, int slot, int open); + + struct dvb_ca_en50221_cimax en50221_cimax; + + int (*ci_read_cis)(struct aml_ci *ca, int slot, u8 *buf, int size); + int (*ci_write_cor)(struct aml_ci *ca, int slot, int address, u8 *buf); + /*return the final size or -1 for error*/ + int (*ci_negotiate)(struct aml_ci *ca, int slot, int size); + + /* functions for accessing the control interface on the CAM */ + int (*ci_read_lpdu)(struct aml_ci *ca, int slot, u8 *buf, int size); + int (*ci_write_lpdu)(struct aml_ci *ca, int slot, u8 *buf, int size); + + int (*ci_get_capbility)(struct aml_ci *ca, int slot); + + int (*ci_cam_reset)(struct aml_ci *ca, int slot); + int (*ci_read_cam_status)(struct aml_ci *ca, int slot); + /* private data, used by caller */ void *data; }; @@ -52,8 +94,8 @@ struct ci_dev_config_s { int cs_hold_delay; int cs_clk_delay; }; -extern int aml_ci_init(struct platform_device - *pdev, struct aml_dvb *dvb, struct aml_ci **cip); +extern int aml_ci_init(struct platform_device *pdev, + struct aml_dvb *dvb, struct aml_ci **cip); extern void aml_ci_exit(struct aml_ci *ci); #endif /* __AML_CI_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c index b840db43918d..ac8c87d71128 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c @@ -61,7 +61,6 @@ static int pcmcia_unplug(struct aml_pcmcia *pc) static irqreturn_t pcmcia_irq_handler(int irq, void *dev_id) { struct aml_pcmcia *pc = (struct aml_pcmcia *)dev_id; - pr_dbg("pcmcia_irq_handler--into--\r\n"); disable_irq_nosync(pc->irq); schedule_work(&pc->pcmcia_work); @@ -96,7 +95,6 @@ static struct aml_pcmcia *pc_cur; int aml_pcmcia_init(struct aml_pcmcia *pc) { int err = 0; - pr_dbg("aml_pcmcia_init start pc->irq=%d\r\n", pc->irq); pc->rst(pc, AML_L); /*power on*/ @@ -144,7 +142,7 @@ int aml_pcmcia_reset(struct aml_pcmcia *pc) EXPORT_SYMBOL(aml_pcmcia_reset); - +#if 0 static ssize_t aml_pcmcia_test_cmd(struct class *class, struct class_attribute *attr, const char *buf, size_t size) { @@ -167,7 +165,7 @@ struct class_attribute *attr, const char *buf, size_t size) } static struct class_attribute aml_pcmcia_class_attrs[] = { - __ATTR(cmd, 0644, NULL, aml_pcmcia_test_cmd), + __ATTR(cmd, S_IRUGO | S_IWUSR, NULL, aml_pcmcia_test_cmd), __ATTR_NULL }; @@ -198,3 +196,4 @@ module_init(aml_pcmcia_mod_init); module_exit(aml_pcmcia_mod_exit); MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h index 2d8a3ad4b9fc..612d5776e081 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _AML_PCMCIA_ #define _AML_PCMCIA_ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c index bbfe295b6977..62f4f5315dc6 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c @@ -1,3 +1,23 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + #include #include @@ -14,7 +34,6 @@ #include #include #include -#include #include "aml_spi.h" #include "aml_ci.h" @@ -59,25 +78,25 @@ struct spi_board_info aml_ci_spi_bdinfo = { #define PULLHIGH 0 /* - *sendbuf data struct - *---------------------------------------------------- - *|start flag| cmd | data | addr |end flag | - *---------------------------------------------------- - *| 2 byte | 1byte | 1byte | 2 byte| 2 byte | - *---------------------------------------------------- - */ +sendbuf data struct +---------------------------------------------------- +|start flag| cmd | data | addr |end flag | +---------------------------------------------------- +| 2 byte | 1byte | 1byte | 2 byte| 2 byte | +---------------------------------------------------- +*/ #define SENDBUFLEN 8 static u8 sendbuf[SENDBUFLEN];/* send data */ static u8 rbuf[SENDBUFLEN];/*save get data */ /**\brief aml_init_send_buf:init spi send buf - * \param cmd: ci cmd - * \param data: write value - * \param addr: read or write addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param cmd: ci cmd +* \param data: write value +* \param addr: read or write addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_init_send_buf(u8 cmd, u8 data, u16 addr) { /* start flag */ @@ -96,20 +115,20 @@ static int aml_init_send_buf(u8 cmd, u8 data, u16 addr) return 0; } /**\brief aml_ci_spi_reciver - * \param[out] None - * \param[in] value,get from spi - * \return - * - 0:reciver end,-1:reciver - * - - */ +* \param[out] None +* \param[in] value,get from spi +* \return +* - 0:reciver end,-1:reciver +* - +*/ /* - *data strouct - *---------------------------------------------------- - *|start flag| cmd | data | addr |end flag | - *---------------------------------------------------- - *| 2 byte | 1byte | 1byte | 2 byte| 2 byte | - *---------------------------------------------------- - */ +data strouct +---------------------------------------------------- +|start flag| cmd | data | addr |end flag | +---------------------------------------------------- +| 2 byte | 1byte | 1byte | 2 byte| 2 byte | +---------------------------------------------------- +*/ int aml_ci_spi_paser_bit(uint8_t value) { /* read spi data from slave */ @@ -161,21 +180,20 @@ int aml_ci_spi_paser_bit(uint8_t value) } /**\brief aml_spi_io_api:spi read or write api with mcu - * \param spi_dev: aml_spi obj,used this data to get spi obj - * \param val: write value - * \param len: write value len - * \param mode: read or write - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj,used this data to get spi obj +* \param val: write value +* \param len: write value len +* \param mode: read or write +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_spi_io_api(struct aml_spi *spi_dev, u8 *val, int len, int mode) { u8 rb[32] = {0}; int ret = 0; int i = 0; u8 rd = 0; - if (spi_dev->spi == NULL) { pr_error("%s spi is null\r\n", __func__); return -EINVAL; @@ -226,16 +244,15 @@ static int aml_spi_io_api(struct aml_spi *spi_dev, u8 *val, int len, int mode) /********************************************************/ /********************************************************/ /**\brief aml_set_gpio_out:set gio out and set val value - * \param gpio: gpio_desc obj, - * \param val: set val - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param gpio: gpio_desc obj, +* \param val: set val +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_set_gpio_out(struct gpio_desc *gpio, int val) { int ret = 0; - if (val < 0) { pr_dbg("gpio out val = -1.\n"); return -1; @@ -246,51 +263,53 @@ static int aml_set_gpio_out(struct gpio_desc *gpio, int val) pr_dbg("dvb ci gpio out ret %d set val:%d\n", ret, val); return ret; } +#if 0 /**\brief aml_set_gpio_in:set gio in - * \param gpio: gpio_desc obj, - * \return - * - 0:ok - * - -EINVAL : error - */ -static inline int aml_set_gpio_in(struct gpio_desc *gpio) +* \param gpio: gpio_desc obj, +* \return +* - 0:ok +* - -EINVAL : error +*/ +static int aml_set_gpio_in(struct gpio_desc *gpio) { gpiod_direction_input(gpio); return 0; } +#endif + /**\brief aml_get_gpio_value:get gio value - * \param gpio: gpio_desc obj, - * \return - * - gpio value:ok - * - -EINVAL : error - */ -static inline int aml_get_gpio_value(struct gpio_desc *gpio) +* \param gpio: gpio_desc obj, +* \return +* - gpio value:ok +* - -EINVAL : error +*/ +static int aml_get_gpio_value(struct gpio_desc *gpio) { int ret = 0; - ret = gpiod_get_value(gpio); return ret; } /**\brief aml_gpio_free:free gio - * \param gpio: gpio_desc obj, - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param gpio: gpio_desc obj, +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_gpio_free(struct gpio_desc *gpio) { gpiod_put(gpio); return 0; } /**\brief spi_get_gpio_by_name:get gpio desc from dts file - * \param spi_dev: aml_spi obj - * \param gpiod: gpio_desc * obj - * \param str: gpio name at dts file - * \param input_output: gpio input or output type - * \param output_value: gpio out put value - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj +* \param gpiod: gpio_desc * obj +* \param str: gpio name at dts file +* \param input_output: gpio input or output type +* \param output_value: gpio out put value +* \return +* - 0:ok +* - -EINVAL : error +*/ static int spi_get_gpio_by_name(struct aml_spi *spi_dev, struct gpio_desc **gpiod, int *pin_value, char *str, int input_output, int output_level) @@ -332,120 +351,117 @@ char *str, int input_output, int output_level) /******* gpio api end *************/ /********************************************************/ /********************************************************/ +#if 0 /**\brief aml_ci_cis_test_by_spi:test cis - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - test :ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - test :ok +* - -EINVAL : error +*/ /**\brief aml_ci_full_test_by_spi:ci full test - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_ci_full_test_by_spi( struct aml_ci *ci_dev, int slot, int addr) { u8 data = 0; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_FULLTEST, data, address); + aml_init_send_buf(AM_CI_CMD_FULLTEST, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_FULLTEST); pr_dbg("FULL : TEST END \r\n"); return value; } - +#endif /**\brief aml_ci_mem_read_by_spi:io read from cam - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_ci_mem_read_by_spi( struct aml_ci *ci_dev, int slot, int addr) { u8 data = 0; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_MEMR, data, address); + aml_init_send_buf(AM_CI_CMD_MEMR, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_MEMR); /*pr_dbg("Read : mem[%d] = 0x%x\n", addr, value);*/ return value; } /**\brief aml_ci_mem_write_by_spi:io write to cam by spi api - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: write addr - * \param addr: write value - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: write addr +* \param addr: write value +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_ci_mem_write_by_spi( struct aml_ci *ci_dev, int slot, int addr, u8 val) { u8 data = val; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_MEMW, data, address); + aml_init_send_buf(AM_CI_CMD_MEMW, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_MEMW); /*pr_dbg("write : mem[%d] = 0x%x\n", addr, data);*/ - return value; +return value; } /**\brief aml_ci_io_read_by_spi:io read from cam by spi api - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_ci_io_read_by_spi( struct aml_ci *ci_dev, int slot, int addr) { u8 data = 0; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_IOR, data, address); + aml_init_send_buf(AM_CI_CMD_IOR, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_IOR); /*pr_dbg("read : io[%d] = 0x%x\n", addr, value);*/ return value; } /**\brief aml_ci_io_write_by_spi:io write to cam - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: write addr - * \param addr: write value - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: write addr +* \param addr: write value +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_ci_io_write_by_spi( struct aml_ci *ci_dev, int slot, int addr, u8 val) { u8 data = val; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; /*add by chl,need add time delay*/ mdelay(10); - aml_init_send_buf(AM_CI_CMD_IOW, data, address); + aml_init_send_buf(AM_CI_CMD_IOW, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_IOW); /*pr_dbg("write : ATTR[%d] = 0x%x\n", addr, data);*/ return value; @@ -453,55 +469,54 @@ static int aml_ci_io_write_by_spi( /**\brief aml_ci_slot_reset:reset slot - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_ci_slot_reset(struct aml_ci *ci_dev, int slot) { struct aml_spi *spi_dev = ci_dev->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); aml_pcmcia_reset(&spi_dev->pc); dvb_ca_en50221_camready_irq(&ci_dev->en50221, 0); return 0; } /**\brief aml_ci_slot_shutdown:show slot - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - * readme:no use this api - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \return +* - 0:ok +* - -EINVAL : error +* readme:no use this api +*/ static int aml_ci_slot_shutdown(struct aml_ci *ci_dev, int slot) { pr_dbg("Slot(%d): Slot shutdown\n", slot); return 0; } /**\brief aml_ci_ts_control:control slot ts - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - * readme:no use this api - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \return +* - 0:ok +* - -EINVAL : error +* readme:no use this api +*/ static int aml_ci_ts_control(struct aml_ci *ci_dev, int slot) { pr_dbg("Slot(%d): TS control\n", slot); return 0; } /**\brief aml_ci_slot_status:get slot status - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param open: no used - * \return - * - cam status - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param open: no used +* \return +* - cam status +* - -EINVAL : error +*/ static int aml_ci_slot_status(struct aml_ci *ci_dev, int slot, int open) { struct aml_spi *spi_dev = ci_dev->data; @@ -517,36 +532,36 @@ static int aml_ci_slot_status(struct aml_ci *ci_dev, int slot, int open) } return -EINVAL; } - +#if 0 /**\brief aml_ci_gio_get_irq:get gpio cam irq pin value - * \return - * - irq pin value - * - -EINVAL : error - */ +* \return +* - irq pin value +* - -EINVAL : error +*/ static int aml_ci_gio_get_irq(void) { int ret = 0; - ret = aml_get_gpio_value(g_spi_dev->irq_cam_pin); return ret; } +#endif + /********************************************************/ /********************************************************/ /******* for pcmcid api *************/ /********************************************************/ /********************************************************/ /**\brief aml_gio_power:set power gpio hi or low - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \param enable: power pin hi or low - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \param enable: power pin hi or low +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_gio_power(struct aml_pcmcia *pc, int enable) { int ret = 0; struct aml_spi *spi_dev = pc->priv; - if (spi_dev == NULL) { pr_dbg("spi dev is null %s : %d\r\n", __func__, enable); return -1; @@ -562,18 +577,17 @@ static int aml_gio_power(struct aml_pcmcia *pc, int enable) return ret; } /**\brief aml_gio_reset:set reset gpio hi or low - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \param enable: reset pin hi or low - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \param enable: reset pin hi or low +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_gio_reset(struct aml_pcmcia *pc, int enable) { /*need set hi and sleep set low*/ int ret = 0; struct aml_spi *spi_dev = pc->priv; - pr_dbg("%s : %d\r\n", __func__, enable); if (enable == AML_L) ret = aml_set_gpio_out(spi_dev->reset_pin, AML_GPIO_LOW); @@ -583,80 +597,79 @@ static int aml_gio_reset(struct aml_pcmcia *pc, int enable) } /**\brief aml_gio_init_irq:set gpio irq - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \param flag: rising or falling or hi or low - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \param flag: rising or falling or hi or low +* \return +* - 0 +* - -EINVAL : error +*/ /*need change*/ static int aml_gio_init_irq(struct aml_pcmcia *pc, int flag) -{ - struct aml_spi *spi_dev = (struct aml_spi *)pc->priv; - + { + struct aml_spi *spi_dev = (struct aml_spi *)pc->priv; + #if 0 - int cd1_pin = desc_to_gpio(spi_dev->cd_pin1); - - int irq = pc->irq-AML_CI_GPIO_IRQ_BASE; - - printk("----cd1_pin=%d irq=%d\r\n", cd1_pin, irq); - aml_set_gpio_in(spi_dev->cd_pin1); - - if (flag == IRQF_TRIGGER_RISING) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_RISING)); - else if (flag == IRQF_TRIGGER_FALLING) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_FALLING)); - else if (flag == IRQF_TRIGGER_HIGH) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_HIGH)); - else if (flag == IRQF_TRIGGER_LOW) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_LOW)); - else - return -1; + int cd1_pin = desc_to_gpio(spi_dev->cd_pin1); + + int irq = pc->irq-AML_CI_GPIO_IRQ_BASE; + + printk("----cd1_pin=%d irq=%d\r\n", cd1_pin, irq); + aml_set_gpio_in(spi_dev->cd_pin1); + + if (flag == IRQF_TRIGGER_RISING) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_RISING)); + else if (flag == IRQF_TRIGGER_FALLING) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_FALLING)); + else if (flag == IRQF_TRIGGER_HIGH) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_HIGH)); + else if (flag == IRQF_TRIGGER_LOW) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_LOW)); + else + return -1; #endif - gpiod_to_irq(spi_dev->cd_pin1); + gpiod_to_irq(spi_dev->cd_pin1); + + return 0; + } - return 0; -} /**\brief aml_gio_get_cd1:get gpio cd1 pin value - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \return - * - cd1 pin value - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \return +* - cd1 pin value +* - -EINVAL : error +*/ static int aml_gio_get_cd1(struct aml_pcmcia *pc) { int ret = 0; struct aml_spi *spi_dev = pc->priv; - ret = aml_get_gpio_value(spi_dev->cd_pin1); return ret; } /**\brief aml_gio_get_cd2:get gpio cd2 pin value - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \return - * - cd2 pin value - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \return +* - cd2 pin value +* - -EINVAL : error +*/ static int aml_gio_get_cd2(struct aml_pcmcia *pc) { int ret = 0; struct aml_spi *spi_dev = pc->priv; - ret = aml_get_gpio_value(spi_dev->cd_pin2); pr_dbg("%s : %d\r\n", __func__, ret); return ret; } /**\brief aml_cam_plugin:notify en50221 cam card in or out - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \plugin: 0:remove;1:in - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \plugin: 0:remove;1:in +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_cam_plugin(struct aml_pcmcia *pc, int plugin) { struct aml_ci *ci = (struct aml_ci *) @@ -672,12 +685,12 @@ static int aml_cam_plugin(struct aml_pcmcia *pc, int plugin) return 0; } /**\brief aml_pcmcia_alloc:alloc nad init pcmcia obj - * \param spi_dev: aml_spi obj, - * \param pcmcia: aml_pcmcia * obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj, +* \param pcmcia: aml_pcmcia * obj, +* \return +* - 0 +* - -EINVAL : error +*/ static void aml_pcmcia_alloc(struct aml_spi *spi_dev, struct aml_pcmcia **pcmcia) { @@ -696,11 +709,11 @@ static void aml_pcmcia_alloc(struct aml_spi *spi_dev, } /**\brief aml_spi_get_config_from_dts:get spi config and gpio config from dts - * \param spi_dev: aml_spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) { struct device_node *child = NULL; @@ -708,7 +721,6 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) struct device_node *np = pdev->dev.of_node; unsigned int temp[5], val; int ret = 0; - pr_dbg("into get spi dts \r\n"); /*get spi and gpio config from dts*/ @@ -770,11 +782,10 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) spi_dev->irq = 5; } else { /*set irq value need add - *AML_CI_GPIO_IRQ_BASE,but - *we need minus - *AML_CI_GPIO_IRQ_BASE - *when gpio request irq - */ + AML_CI_GPIO_IRQ_BASE,but + we need minus + AML_CI_GPIO_IRQ_BASE + when gpio request irq */ spi_dev->irq = val+AML_CI_GPIO_IRQ_BASE; } @@ -803,11 +814,8 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) } spi_dev->cd_pin2 = spi_dev->cd_pin1; spi_dev->cd_pin2_value = spi_dev->cd_pin1_value; - /*set irq*/ - spi_dev->irq = gpiod_to_irq(spi_dev->cd_pin1); spi_dev->pwr_pin = NULL; - pr_dbg("spi_dev->cd_pin1_value==%d irq=%d\r\n", - spi_dev->cd_pin1_value, spi_dev->irq); + pr_dbg("spi_dev->cd_pin1_value==%d\r\n", spi_dev->cd_pin1_value); ret = spi_get_gpio_by_name(spi_dev, &spi_dev->pwr_pin, &spi_dev->pwr_pin_value, "pwr_pin", OUTPUT, OUTLEVEL_HIGH); @@ -827,11 +835,11 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) return 0; } /**\brief aml_ci_free_gpio:free ci gpio - * \param spi_dev: aml_spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static void aml_ci_free_gpio(struct aml_spi *spi_dev) { if (spi_dev == NULL) { @@ -856,23 +864,23 @@ static void aml_ci_free_gpio(struct aml_spi *spi_dev) aml_gpio_free(spi_dev->irq_cam_pin); spi_dev->irq_cam_pin = NULL; } + return; } /**\brief ci_spi_dev_remove:spi probe api - * \param spi: spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi: spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static int ci_spi_dev_probe(struct spi_device *spi) { int ret; - pr_dbg("spi Dev probe--\n"); if (g_spi_dev) g_spi_dev->spi = spi; - else + else pr_dbg("spi Dev probe-error-\n"); spi->bits_per_word = 8; ret = spi_setup(spi); @@ -881,11 +889,11 @@ static int ci_spi_dev_probe(struct spi_device *spi) return ret; } /**\brief ci_spi_dev_remove:spi remove api - * \param spi: spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi: spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static int ci_spi_dev_remove(struct spi_device *spi) { pr_dbg("spi Dev remove--\n"); @@ -904,12 +912,12 @@ static struct spi_driver ci_spi_dev_driver = { }, }; /**\brief aml_spi_init:spi_dev init - * \param ci_dev: aml_ci obj, - * \param pdev: platform_device obj,used to get dts info - * \return - * - 0 - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj, +* \param pdev: platform_device obj,used to get dts info +* \return +* - 0 +* - -EINVAL : error +*/ int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) { struct aml_spi *spi_dev = NULL; @@ -936,8 +944,10 @@ int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) } aml_pcmcia_alloc(spi_dev, &pc); result = aml_pcmcia_init(pc); - if (result < 0) + if (result < 0) { pr_error("aml_pcmcia_init failed\n"); + goto fail2; + } /*init ci_dev used api.*/ ci_dev->ci_mem_read = aml_ci_mem_read_by_spi; @@ -952,20 +962,21 @@ int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) /*init spi_lock*/ spin_lock_init(&(spi_dev->spi_lock)); return 0; +fail2: spi_unregister_driver(&ci_spi_dev_driver); fail1: - kfree(spi_dev); - spi_dev = NULL; + kfree(spi_dev); + spi_dev = NULL; err: return -1; } EXPORT_SYMBOL(aml_spi_init); /**\brief aml_spi_exit:spi exit - * \return - * - 0 - * - -EINVAL : error - */ -int aml_spi_exit(void) +* \return +* - 0 +* - -EINVAL : error +*/ +int aml_spi_exit(struct aml_ci *ci) { /*exit pc card*/ aml_pcmcia_exit(&g_spi_dev->pc); @@ -981,6 +992,8 @@ int aml_spi_exit(void) } EXPORT_SYMBOL(aml_spi_exit); + +#if 0 /********************************************************/ /********************************************************/ /******* for spi test api *************/ @@ -1011,7 +1024,6 @@ static void aml_spi_ca_full_test(struct aml_ci *ci_dev) int cnt = 0; unsigned char buf[10]; int count = 1000; - mdelay(1000); pr_dbg("READ CIS START\r\n"); for (i = 0; i < 267; i++) { @@ -1040,18 +1052,17 @@ static void aml_spi_ca_full_test(struct aml_ci *ci_dev) unsigned char reg; unsigned char reg1; int count1 = 4000; - while (1) { mdelay(20); count1--; reg1 = aml_ci_io_read_by_spi( ci_dev, 0, COM_STA_REG); if (FR != (FR & reg1)) { - continue; - } else { - pr_dbg("CAM Reset Ok\r\n"); - break; - } + continue; + } else { + pr_dbg("CAM Reset Ok\r\n"); + break; + } } reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); pr_dbg("STA_REG = 0x%2.2x\r\n", reg); @@ -1076,11 +1087,9 @@ end: if ((reg & DA) == DA) { pr_dbg("Buffer negotiate size date avalible.\r\n"); break; - } - { + } else { /*pr_dbg("Buffer negotiate - *size date NOT avalible\r\n"); - */ + size date NOT avalible\r\n");*/ continue; } mdelay(100); @@ -1196,8 +1205,7 @@ end: if (WE == (WE & reg)) { pr_dbg("Write CAM ERR!\r\n"); return; - } - { + } else { aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, SW); mdelay(100); aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, 0); @@ -1208,17 +1216,17 @@ end: } /** - * Read a tuple from attribute memory. - * - * @param ca CA instance. - * @param slot Slot id. - * @param address Address to read from. Updated. - * @param tupleType Tuple id byte. Updated. - * @param tupleLength Tuple length. Updated. - * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. - * - * @return 0 on success, nonzero on error. - */ +* Read a tuple from attribute memory. +* +* @param ca CA instance. +* @param slot Slot id. +* @param address Address to read from. Updated. +* @param tupleType Tuple id byte. Updated. +* @param tupleLength Tuple length. Updated. +* @param tuple Dest buffer for tuple (must be 256 bytes). Updated. +* +* @return 0 on success, nonzero on error. +*/ static int dvb_ca_en50221_read_tuple( int *address, int *tupleType, int *tupleLength, u8 *tuple) { @@ -1279,15 +1287,14 @@ static char *findstr(char *haystack, int hlen, char *needle, int nlen) } /** - * Parse attribute memory of a CAM module, - * extracting Config register, and checking - * it is a DVB CAM module. - * - * @param ca CA instance. - * @param slot Slot id. - * - * @return 0 on success, <0 on failure. - */ +* Parse attribute memory of a CAM module, extracting Config register, and checking +* it is a DVB CAM module. +* +* @param ca CA instance. +* @param slot Slot id. +* +* @return 0 on success, <0 on failure. +*/ static int dvb_ca_en50221_parse_attributes(void) { int address = 0; @@ -1413,13 +1420,13 @@ static int dvb_ca_en50221_parse_attributes(void) } /* process the CFTABLE_ENTRY tuples, and any after those */ - while ((!end_chain) && (address < 0x1000)) { +while ((!end_chain) && (address < 0x1000)) { status = dvb_ca_en50221_read_tuple(&address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("process the CFTABLE_ENTRY tuples error\r\n"); - return status; - } + &tupleLength, tuple); + if (status < 0) { + pr_error("process the CFTABLE_ENTRY tuples error\r\n"); + return status; + } switch (tupleType) { case 0x1B: /* CISTPL_CFTABLE_ENTRY */ @@ -1453,9 +1460,9 @@ static int dvb_ca_en50221_parse_attributes(void) default: /* Unknown tuple type - just skip - *this tuple and move to the next one - */ - pr_error("Skipping unknown tupletype:0x%x L:0x%x\n", + *this tuple and move to the next one + */ +pr_error("Skipping unknown tupletype:0x%x L:0x%x\n", tupleType, tupleLength); break; } @@ -1474,7 +1481,6 @@ static ssize_t aml_spi_ci_reset_help(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "echo 1 > %s\n\t", attr->attr.name); return ret; } @@ -1484,7 +1490,6 @@ struct class_attribute *attr, const char *buf, size_t size) { int ret; struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - ret = aml_ci_slot_reset(ci, 0); return size; } @@ -1493,7 +1498,6 @@ static ssize_t aml_spi_ci_pwr_help(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "echo 1|0> %s\n\t", attr->attr.name); return ret; } @@ -1504,7 +1508,6 @@ struct class_attribute *attr, const char *buf, size_t size) int ret = 0; int enable = 0; long value; - if (kstrtol(buf, 0, &value) == 0) enable = (int)value; ret = aml_gio_power(&g_spi_dev->pc, enable); @@ -1515,7 +1518,6 @@ struct class_attribute *attr, char *buf) { int ret; struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - ret = aml_ci_slot_status(ci, 0, 0); ret = sprintf(buf, "%s: %d;\n\t", attr->attr.name, ret); return ret; @@ -1525,7 +1527,6 @@ static ssize_t aml_spi_ci_irq_show(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = aml_ci_gio_get_irq(); ret = sprintf(buf, "%s irq: %d\n\t", attr->attr.name, ret); return ret; @@ -1535,7 +1536,6 @@ static ssize_t aml_spi_io_test_help(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "echo (r|w|f|c)(i|a) addr data > %s\n", attr->attr.name); return ret; @@ -1550,7 +1550,6 @@ struct class_attribute *attr, const char *buf, size_t size) unsigned int addr = 0, val = 0, retval = 0; long value = 0; struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - buf_orig = kstrdup(buf, GFP_KERNEL); ps = buf_orig; while (1) { @@ -1563,7 +1562,7 @@ struct class_attribute *attr, const char *buf, size_t size) parm[n++] = token; } - if ((n > 0) && (strlen(parm[0]) != 2)) { + if (!n || ((n > 0) && (strlen(parm[0]) != 2))) { pr_err("invalid command\n"); kfree(buf_orig); return size; @@ -1579,16 +1578,15 @@ struct class_attribute *attr, const char *buf, size_t size) addr = (int)value; pr_err("%s 0x%x\n", parm[0], addr); /* switch ((char)parm[0][1]) { - * case 'i': - * retval = aml_ci_io_read_by_spi(ci, 0, addr); - * break; - * case 'a': - * retval = aml_ci_mem_read_by_spi(ci, 0, addr); - * break; - * default: - * break; - * } - */ + case 'i': + retval = aml_ci_io_read_by_spi(ci, 0, addr); + break; + case 'a': + retval = aml_ci_mem_read_by_spi(ci, 0, addr); + break; + default: + break; + }*/ pr_dbg("%s: 0x%x --> 0x%x\n", parm[0], addr, retval); } else if ((parm[0][0] == 'w')) { if (n != 3) { @@ -1597,22 +1595,21 @@ struct class_attribute *attr, const char *buf, size_t size) return size; } if (kstrtol(parm[1], 0, &value) == 0) - addr = (int)value; + addr = (int)value; if (kstrtol(parm[2], 0, &value) == 0) - val = (int)value; + val = (int)value; pr_err("%s 0x%x 0x%x", parm[0], addr, val); /*switch ((char)parm[0][1]) { - * case 'i': + case 'i': retval = aml_ci_io_write_by_spi(ci, 0, addr, val); - * break; - * case 'a': + break; + case 'a': retval = aml_ci_mem_write_by_spi(ci, 0, addr, val); - * break; - * default: - * break; - *} - */ + break; + default: + break; + }*/ pr_dbg("%s: 0x%x <-- 0x%x\n", parm[0], addr, retval); } else if ((parm[0][0] == 'f')) { pr_dbg("full test----\r\n"); @@ -1630,15 +1627,15 @@ retval = aml_ci_mem_write_by_spi(ci, 0, addr, val); } static struct class_attribute aml_spi_class_attrs[] = { - __ATTR(reset, 0644, + __ATTR(reset, S_IRUGO | S_IWUSR, aml_spi_ci_reset_help, aml_spi_ci_reset), - __ATTR(pwr, 0644, + __ATTR(pwr, S_IRUGO | S_IWUSR, aml_spi_ci_pwr_help, aml_spi_ci_pwr), - __ATTR(irq, 0644, + __ATTR(irq, S_IRUGO | S_IWUSR, aml_spi_ci_irq_show, NULL), - __ATTR(status, 0644, + __ATTR(status, S_IRUGO | S_IWUSR, aml_spi_ci_state_show, NULL), - __ATTR(iotest, 0644, + __ATTR(iotest, S_IRUGO | S_IWUSR, aml_spi_io_test_help, aml_spi_io_test), __ATTR_NULL }; @@ -1648,14 +1645,15 @@ static struct class aml_spi_class = { .class_attrs = aml_spi_class_attrs, }; -static int __init aml_spi_mod_init(void) +static int aml_spi_mod_init(void) { + int ret; pr_dbg("Amlogic DVB SPI Init\n"); - class_register(&aml_spi_class); -return 0; + ret = class_register(&aml_spi_class); + return 0; } -static void __exit aml_spi_mod_exit(void) +static void aml_spi_mod_exit(void) { pr_dbg("Amlogic DVB SPI Exit\n"); class_unregister(&aml_spi_class); @@ -1665,3 +1663,4 @@ module_init(aml_spi_mod_init); module_exit(aml_spi_mod_exit); MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h index 2795dc9dae5d..43d0d162e32e 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h @@ -3,13 +3,13 @@ #include #include -#include #include "aml_pcmcia.h" #include "aml_ci.h" +#include "drivers/media/dvb-core/dvb_ca_en50221.h" /* - *aml spi dev - */ +aml spi dev +*/ struct aml_spi { spinlock_t spi_lock; @@ -76,6 +76,6 @@ extern void dirspi_start(struct spi_device *spi); extern void dirspi_stop(struct spi_device *spi); extern void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot); extern int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev); -extern int aml_spi_exit(void); +extern int aml_spi_exit(struct aml_ci *ci_dev); #endif /* __AML_SPI_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c new file mode 100644 index 000000000000..9346b8dd46c5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c @@ -0,0 +1,279 @@ + +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include "../aml_ci.h" +#include "aml_cimax.h" +#include "aml_cimax_spi.h" +#include "aml_cimax_usb.h" + +#define MODUDLE_NAME "aml_cimax" + +MODULE_PARM_DESC(cimax_debug, "enable verbose debug messages"); +static int aml_cimax_debug = 1; +module_param_named(cimax_debug, aml_cimax_debug, int, 0644); + +//static struct switch_dev slot_state = { +// .name = "ci_slot", +//}; + +#define pr_dbg(fmt...)\ + do {\ + if (aml_cimax_debug)\ + pr_info("AML_CIMAX: " fmt);\ + } while (0) +#define pr_error(fmt...) pr_err("AML_CIMAX: " fmt) + +static int aml_cimax_slot_reset(struct aml_ci *ci, int slot) +{ + int ret = 0; + struct aml_cimax *cimax = ci->data; + pr_dbg("cimax: slot(%d) reset\n", slot); + if (cimax->ops.slot_reset) + ret = cimax->ops.slot_reset(cimax, slot); + return ret; +} + +static int aml_cimax_slot_shutdown(struct aml_ci *ci, int slot) +{ + pr_dbg("slot(%d) shutdown\n", slot); + return 0; +} + +static int aml_cimax_slot_ts_enable(struct aml_ci *ci, int slot) +{ + pr_dbg("slot(%d) ts control\n", slot); + return 0; +} + +static int aml_cimax_slot_status(struct aml_ci *ci, int slot, int open) +{ + int ret = 0; + struct aml_cimax *cimax = ci->data; + + /*pr_dbg("cimax: slot(%d) poll\n", slot);*/ + if (cimax->ops.slot_status) + ret = cimax->ops.slot_status(cimax, slot); + return ret; +} + +#define DEF_FUNC_WRAPPER3(_pre, _fn, _S, _P1, _P2, _P3) \ +static int _pre##_fn(_S s, _P1 p1, _P2 p2, _P3 p3)\ +{\ + struct aml_cimax *cimax = s->data;\ + /*pr_dbg("%s\n", #_fn);*/\ + if (cimax->ops._fn)\ + return cimax->ops._fn(cimax, p1, p2, p3);\ + return 0;\ +} + +/*DEF_FUNC_WRAPPER3(aml_cimax_, read_reg, struct aml_ci*, int, u8*, int)*/ +/*DEF_FUNC_WRAPPER3(aml_cimax_, write_reg, struct aml_ci*, int, u8*, int)*/ +DEF_FUNC_WRAPPER3(aml_cimax_, read_cis, struct aml_ci*, int, u8*, int) +DEF_FUNC_WRAPPER3(aml_cimax_, read_lpdu, struct aml_ci*, int, u8*, int) +DEF_FUNC_WRAPPER3(aml_cimax_, write_lpdu, struct aml_ci*, int, u8*, int) + +static int aml_cimax_write_cor(struct aml_ci *ci, int slot, int addr, u8 *buf) +{ + struct aml_cimax *cimax = ci->data; + pr_dbg("write_cor\n"); + if (cimax->ops.write_cor) + return cimax->ops.write_cor(cimax, slot, addr, buf); + return 0; +} + +static int aml_cimax_negotiate(struct aml_ci *ci, int slot, int size) +{ + struct aml_cimax *cimax = ci->data; + pr_dbg("negotiate\n"); + if (cimax->ops.negotiate) + return cimax->ops.negotiate(cimax, slot, size); + return 0; +} + +static int aml_cimax_read_cam_status(struct aml_ci *ci, int slot) +{ + struct aml_cimax *cimax = ci->data; + if (cimax->ops.read_cam_status) + return cimax->ops.read_cam_status(cimax, slot); + return 0; +} + +static int aml_cimax_cam_reset(struct aml_ci *ci, int slot) +{ + struct aml_cimax *cimax = ci->data; + if (cimax->ops.cam_reset) + return cimax->ops.cam_reset(cimax, slot); + return 0; +} + +static int aml_cimax_get_capbility(struct aml_ci *ci, int slot) +{ + return 0; +} + +int aml_cimax_camchanged(struct aml_cimax *cimax, int slot, int plugin) +{ + struct aml_ci *ci = cimax->ci; + if (plugin) { + dvb_ca_en50221_cimax_camchange_irq(&ci->en50221_cimax, + slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); + } else { + dvb_ca_en50221_cimax_camchange_irq(&ci->en50221_cimax, + slot, DVB_CA_EN50221_CAMCHANGE_REMOVED); + } + return 0; +} + +static int aml_cimax_start(struct aml_cimax *cimax) +{ + int ret = 0; + if (cimax->ops.start) + ret = cimax->ops.start(cimax); + return ret; +} + +static int aml_cimax_stop(struct aml_cimax *cimax) +{ + int ret = 0; + if (cimax->ops.stop) + ret = cimax->ops.stop(cimax); + return ret; +} + +static int aml_cimax_get_config_from_dts(struct aml_cimax *cimax) +{ + struct device_node *child = NULL; + struct platform_device *pdev = cimax->pdev; + struct device_node *np = pdev->dev.of_node; + unsigned int val; + int ret = 0; + pr_dbg("get cimax dts\n"); + + child = of_get_child_by_name(np, "cimax"); + if (child == NULL) { + pr_error("failed to get cimax\n"); + return -1; + } + ret = of_property_read_u32(child, "io_type", &val); + if (ret) + cimax->io_type = IO_TYPE_SPI; + else + cimax->io_type = val; + + return 0; +} + +int aml_cimax_init(struct platform_device *pdev, struct aml_ci *ci) +{ + struct aml_cimax *cimax = NULL; + int ret = 0; + + cimax = kzalloc(sizeof(struct aml_cimax), GFP_KERNEL); + if (!cimax) { + pr_error("Out of memory!, exiting ..\n"); + return -ENOMEM; + } + cimax->pdev = pdev; + cimax->ci = ci; + + aml_cimax_get_config_from_dts(cimax); + + if (cimax->io_type == IO_TYPE_SPI) { + //ret = aml_cimax_spi_init(pdev, cimax); + } + else { + ret = aml_cimax_usb_init(pdev, cimax); + } + + if (ret != 0) { + kfree(cimax); + cimax = NULL; + return -EIO; + } + + ret = aml_cimax_start(cimax); + if (ret != 0) + return ret; + + ci->ci_read_cis = aml_cimax_read_cis; + ci->ci_write_cor = aml_cimax_write_cor; + ci->ci_negotiate = aml_cimax_negotiate; + ci->ci_read_lpdu = aml_cimax_read_lpdu; + ci->ci_write_lpdu = aml_cimax_write_lpdu; + ci->ci_read_cam_status = aml_cimax_read_cam_status; + ci->ci_cam_reset = aml_cimax_cam_reset; + ci->ci_get_capbility = aml_cimax_get_capbility; + ci->ci_slot_reset = aml_cimax_slot_reset; + ci->ci_slot_shutdown = aml_cimax_slot_shutdown; + ci->ci_slot_ts_enable = aml_cimax_slot_ts_enable; + ci->ci_poll_slot_status = aml_cimax_slot_status; + + ci->data = cimax; + return 0; +} +EXPORT_SYMBOL(aml_cimax_init); + +int aml_cimax_exit(struct aml_ci *ci) +{ + struct aml_cimax *cimax = ci->data; + + aml_cimax_stop(cimax); + + if (cimax->io_type == IO_TYPE_SPI) { + //aml_cimax_spi_exit(cimax); + } + else { + aml_cimax_usb_exit(cimax); + } + kfree(cimax); + ci->data = NULL; + + return 0; +} +EXPORT_SYMBOL(aml_cimax_exit); + +int aml_cimax_slot_state_changed(struct aml_cimax *cimax, int slot, int state) +{ + //if (slot == 0) + // switch_set_state(&slot_state, state); + return 0; +} +EXPORT_SYMBOL(aml_cimax_slot_state_changed); +#if 0 +static int __init aml_cimax_mod_init(void) +{ + pr_dbg("Amlogic DVB CIMAX Init\n"); + //switch_dev_register(&slot_state); + //switch_set_state(&slot_state, 0); + return 0; +} + +static void __exit aml_cimax_mod_exit(void) +{ + pr_dbg("Amlogic DVB CIMAX Exit\n"); + //switch_dev_unregister(&slot_state); +} + +module_init(aml_cimax_mod_init); +module_exit(aml_cimax_mod_exit); + +MODULE_LICENSE("GPL"); +#endif + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h new file mode 100644 index 000000000000..17c62fad7625 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef __AML_CIMAX_H_ +#define __AML_CIMAX_H_ + +#include "../aml_ci.h" +#include "dvb_ca_en50221_cimax.h" + +struct aml_cimax; + +struct aml_cimax_ops { + int (*read_cis)(struct aml_cimax *cimax, int slot, u8 *buf, int size); + int (*write_cor)(struct aml_cimax *cimax, + int slot, int address, u8 *buf); + int (*negotiate)(struct aml_cimax *cimax, int slot, int size); + int (*read_lpdu)(struct aml_cimax *cimax, int slot, u8 *buf, int size); + int (*write_lpdu)(struct aml_cimax *cimax, int slot, u8 *buf, int size); + int (*read_cam_status)(struct aml_cimax *cimax, int slot); + int (*cam_reset)(struct aml_cimax *cimax, int slot); + int (*get_capblility)(struct aml_cimax *cimax, int slot); + + int (*slot_reset)(struct aml_cimax *cimax, int slot); + int (*slot_shutdown)(struct aml_cimax *cimax, int slot); + int (*slot_ts_enable)(struct aml_cimax *cimax, int slot); + int (*slot_status)(struct aml_cimax *cimax, int slot); + + /*load fw etc.*/ + int (*start)(struct aml_cimax *cimax); + int (*stop)(struct aml_cimax *cimax); + + /*cimax reg*/ + int (*read_reg)(struct aml_cimax *cimax, int addr, u8 *buf, int size); + int (*write_reg)(struct aml_cimax *cimax, int addr, u8 *buf, int size); +}; + +struct aml_cimax { + struct platform_device *pdev; + struct device *dev; + struct aml_ci *ci; + + int io_type; +#define IO_TYPE_SPI 0 +#define IO_TYPE_USB 1 + struct aml_cimax_ops ops; + void *priv; +}; + +int aml_cimax_init(struct platform_device *pdev, struct aml_ci *ci_dev); +int aml_cimax_exit(struct aml_ci *ci_dev); + +int aml_cimax_camchanged(struct aml_cimax *cimax, int slot, int plugin); +int aml_cimax_slot_state_changed(struct aml_cimax *cimax, int slot, int state); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c new file mode 100644 index 000000000000..a4aaddae0260 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c @@ -0,0 +1,2139 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_cimax.h" + +#define MOD_NAME "aml_cimax_spi" + +#define pr_dbg(fmt...)\ + do {\ + if (cimax_spi_debug)\ + pr_info("cimax_spi: "fmt);\ + } while (0) +#define pr_error(fmt...) pr_err("AML_CIMAX_SPI: " fmt) + +#define BUFFIN_CFG 0x0000 +#define BUFFIN_ADDR_LSB 0x0001 +#define BUFFIN_ADDR_MSB 0x0002 +#define BUFFIN_DATA 0x0003 +#define BUFFOUT_CFG 0x0004 +#define BUFFOUT_ADDR_LSB 0x0005 +#define BUFFOUT_ADDR_MSB 0x0006 +#define BUFFOUT_DATA 0x0007 +#define BOOT_Key 0x0008 +#define BOOT_Status 0x0009 +#define BOOT_Test 0x000A +#define usb2_0_irq_mask 0x0010 +#define usb2_0_status 0x0011 +#define usb2_0_rx 0x0012 +#define usb2_0_tx 0x0013 +#define SPI_Slave_Ctrl 0x0018 +#define SPI_Slave_Status 0x0019 +#define SPI_Slave_Rx 0x001A +#define SPI_Slave_Tx 0x001B +#define SPI_Slave_Mask 0x001C +#define UCSG_Ctrl 0x0020 +#define UCSG_Status 0x0021 +#define UCSG_RxData 0x0022 +#define UCSG_TxData 0x0023 +#define PCtrl_Ctrl 0x0028 +#define PCtrl_Status 0x0029 +#define PCtrl_NbByte_LSB 0x002A +#define PCtrl_NbByte_MSB 0x002B +#define SPI_Master_Ctl 0x0030 +#define SPI_Master_NCS 0x0031 +#define SPI_Master_Status 0x0032 +#define SPI_Master_TxBuf 0x0033 +#define SPI_Master_RxBuf 0x0034 +#define BISTRAM_Ctl 0x0038 +#define BISTRAM_Bank 0x0039 +#define BISTRAM_Pat 0x003A +#define BISTRAM_SM 0x003B +#define BISTRAM_AddrLSB 0x003C +#define BISTROM_Config 0x0040 +#define BISTROM_SignatureLSB 0x0041 +#define BISTROM_SignatureMSB 0x0042 +#define BISTROM_StartAddrLSB 0x0043 +#define BISTROM_StartAddrMSB 0x0043 +#define BISTROM_StopAddrLSB 0x0043 +#define BISTROM_StopAddrMSB 0x0043 +#define CkMan_Config 0x0048 +#define CkMan_Select 0x0049 +#define CkMan_Test 0x004A +#define Revision_Number 0x004B +#define ResMan_Config 0x0050 +#define ResMan_Status 0x0051 +#define ResMan_WD 0x0052 +#define ResMan_WD_MSB 0x0053 +#define CPU_Test 0x0060 +#define IrqMan_Config0 0x0068 +#define IrqMan_Config1 0x0069 +#define IrqMan_Irq0 0x006A +#define IrqMan_NMI 0x006B +#define IrqMan_SleepKey 0x006C +#define Tim_Config 0x0070 +#define Tim_Value_LSB 0x0071 +#define Tim_Value_MSB 0x0072 +#define Tim_Comp_LSB 0x0073 +#define Tim_Comp_MSB 0x0074 +#define TI_Config 0x0076 +#define TI_Data 0x0077 +#define TI_Reg0 0x0078 +#define TI_Reg1 0x0079 +#define TI_Reg2 0x007A +#define TI_Reg3 0x007B +#define TI_Reg4 0x007C +#define TI_ROM1 0x007D +#define TI_ROM2 0x007E +#define TI_ROM3 0x007F +#define DVBCI_START_ADDR 0x0100 +#define DVBCI_END_ADDR 0x017F +#define DATA 0x0180 +/*#define CTRL 0x0181*/ +#define QB_HOST 0x0182 +#define LEN_HOST_LSB 0x0183 +#define LEN_HOST_MSB 0x0184 +#define FIFO_TX_TH_LSB 0x0185 +#define FIFO_TX_TH_MSB 0x0186 +#define FIFO_TX_D_NB_LSB 0x0187 +#define FIFO_TX_D_NB_MSB 0x0188 +#define QB_MOD_CURR 0x0189 +#define LEN_MOD_CURR_LSB 0x018A +#define LEN_MOD_CURR_MSB 0x018B +#define QB_MOD 0x018C +#define LEN_MOD_LSB 0x018D +#define LEN_MOD_MSB 0x018E +#define FIFO_RX_TH_LSB 0x018F +#define FIFO_RX_TH_MSB 0x0190 +#define FIFO_RX_D_NB_LSB 0x0191 +#define FIFO_RX_D_NB_MSB 0x0192 +#define IT_STATUS_0 0x0193 +#define IT_STATUS_1 0x0194 +#define IT_MASK_0 0x0195 +#define IT_MASK_1 0x0196 +#define IT_HOST_PIN_CFG 0x0200 +#define CFG_0 0x0201 +#define CFG_1 0x0202 +#define CFG_2 0x0203 +#define IT_HOST 0x0204 +#define MOD_IT_STATUS 0x0205 +#define MOD_IT_MASK 0x0206 +#define MOD_CTRL_A 0x0207 +#define MOD_CTRL_B 0x0208 +#define DEST_SEL 0x0209 +#define CAM_MSB_ADD 0x020A +#define GPIO0_DIR 0x020B +#define GPIO0_DATA_IN 0x020C +#define GPIO0_DATA_OUT 0x020D +#define GPIO0_STATUS 0x020E +#define GPIO0_IT_MASK 0x020F +#define GPIO0_DFT 0x0210 +#define GPIO0_MASK_DATA 0x0211 +#define GPIO1_DIR 0x0212 +#define GPIO1_DATA_IN 0x0213 +#define GPIO1_DATA_OUT 0x0214 +#define GPIO1_STATUS 0x0215 +#define GPIO1_IT_MASK 0x0216 +#define MEM_ACC_TIME_A 0x0217 +#define MEM_ACC_TIME_B 0x0218 +#define IO_ACC_TIME_A 0x0219 +#define IO_ACC_TIME_B 0x021A +#define EXT_CH_ACC_TIME_A 0x021B +#define EXT_CH_ACC_TIME_B 0x021C +#define PAR_IF_0 0x021D +#define PAR_IF_1 0x021E +#define PAR_IF_CTRL 0x021F +#define PCK_LENGTH 0x0220 +#define USB2TS_CTRL 0x0221 +#define USB2TS0_RDL 0x0222 +#define USB2TS1_RDL 0x0223 +#define TS2USB_CTRL 0x0224 +#define TSOUT_PAR_CTRL 0x0225 +#define TSOUT_PAR_CLK_SEL 0x0226 +#define S2P_CH0_CTRL 0x0227 +#define S2P_CH1_CTRL 0x0228 +#define P2S_CH0_CTRL 0x0229 +#define P2S_CH1_CTRL 0x022A +#define TS_IT_STATUS 0x022B +#define TS_IT_MASK 0x022C +#define IN_SEL 0x022D +#define OUT_SEL 0x022E +#define ROUTER_CAM_CH 0x022F +#define ROUTER_CAM_MOD 0x0230 +#define FIFO_CTRL 0x0231 +#define FIFO1_2_STATUS 0x0232 +#define FIFO3_4_STATUS 0x0233 +#define GAP_REMOVER_CH0_CTRL 0x0234 +#define GAP_REMOVER_CH1_CTRL 0x0235 +#define SYNC_RTV_CTRL 0x0236 +#define SYNC_RTV_CH0_SYNC_NB 0x0237 +#define SYNC_RTV_CH0_PATTERN 0x0238 +#define SYNC_RTV_CH1_SYNC_NB 0x0239 +#define SYNC_RTV_CH1_PATTERN 0x023A +#define SYNC_RTV_OFFSET_PATT 0x023B +#define CTRL_FILTER 0x023D +#define PID_EN_FILTER_CH0 0x023E +#define PID_EN_FILTER_CH1 0x023F +#define PID_LSB_FILTER_CH0_0 0x0240 +#define PID_MSB_FILTER_CH0_0 0x0241 +#define PID_LSB_FILTER_CH0_1 0x0242 +#define PID_MSB_FILTER_CH0_1 0x0243 +#define PID_LSB_FILTER_CH0_2 0x0244 +#define PID_MSB_FILTER_CH0_2 0x0245 +#define PID_LSB_FILTER_CH0_3 0x0246 +#define PID_MSB_FILTER_CH0_3 0x0247 +#define PID_LSB_FILTER_CH0_4 0x0248 +#define PID_MSB_FILTER_CH0_4 0x0249 +#define PID_LSB_FILTER_CH0_5 0x024A +#define PID_MSB_FILTER_CH0_5 0x024B +#define PID_LSB_FILTER_CH0_6 0x024C +#define PID_MSB_FILTER_CH0_6 0x024D +#define PID_LSB_FILTER_CH0_7 0x024E +#define PID_MSB_FILTER_CH0_7 0x024F +#define PID_LSB_FILTER_CH1_0 0x0260 +#define PID_MSB_FILTER_CH1_0 0x0261 +#define PID_LSB_FILTER_CH1_1 0x0262 +#define PID_MSB_FILTER_CH1_1 0x0263 +#define PID_LSB_FILTER_CH1_2 0x0264 +#define PID_MSB_FILTER_CH1_2 0x0265 +#define PID_LSB_FILTER_CH1_3 0x0266 +#define PID_MSB_FILTER_CH1_3 0x0267 +#define PID_LSB_FILTER_CH1_4 0x0268 +#define PID_MSB_FILTER_CH1_4 0x0269 +#define PID_LSB_FILTER_CH1_5 0x026A +#define PID_MSB_FILTER_CH1_5 0x026B +#define PID_LSB_FILTER_CH1_6 0x026C +#define PID_MSB_FILTER_CH1_6 0x026D +#define PID_LSB_FILTER_CH1_7 0x026E +#define PID_MSB_FILTER_CH1_7 0x026F +#define PID_OLD_LSB_REMAPPER_0 0x0280 +#define PID_OLD_MSB_REMAPPER_0 0x0281 +#define PID_OLD_LSB_REMAPPER_1 0x0282 +#define PID_OLD_MSB_REMAPPER_1 0x0283 +#define PID_OLD_LSB_REMAPPER_2 0x0284 +#define PID_OLD_MSB_REMAPPER_2 0x0285 +#define PID_OLD_LSB_REMAPPER_3 0x0286 +#define PID_OLD_MSB_REMAPPER_3 0x0287 +#define PID_OLD_LSB_REMAPPER_4 0x0288 +#define PID_OLD_MSB_REMAPPER_4 0x0289 +#define PID_OLD_LSB_REMAPPER_5 0x028A +#define PID_OLD_MSB_REMAPPER_5 0x028B +#define PID_OLD_LSB_REMAPPER_6 0x028C +#define PID_OLD_MSB_REMAPPER_6 0x028D +#define PID_OLD_LSB_REMAPPER_7 0x028E +#define PID_OLD_MSB_REMAPPER_7 0x028F +#define PID_NEW_LSB_REMAPPER_0 0x02A0 +#define PID_NEW_MSB_REMAPPER_0 0x02A1 +#define PID_NEW_LSB_REMAPPER_1 0x02A2 +#define PID_NEW_MSB_REMAPPER_1 0x02A3 +#define PID_NEW_LSB_REMAPPER_2 0x02A4 +#define PID_NEW_MSB_REMAPPER_2 0x02A5 +#define PID_NEW_LSB_REMAPPER_3 0x02A6 +#define PID_NEW_MSB_REMAPPER_3 0x02A7 +#define PID_NEW_LSB_REMAPPER_4 0x02A8 +#define PID_NEW_MSB_REMAPPER_4 0x02A9 +#define PID_NEW_LSB_REMAPPER_5 0x02AA +#define PID_NEW_MSB_REMAPPER_5 0x02AB +#define PID_NEW_LSB_REMAPPER_6 0x02AC +#define PID_NEW_MSB_REMAPPER_6 0x02AD +#define PID_NEW_LSB_REMAPPER_7 0x02AE +#define PID_NEW_MSB_REMAPPER_7 0x02AF +#define MERGER_DIV_MICLK 0x02C0 +#define PID_AND_SYNC_REMAPPER_CTRL 0x02C1 +#define PID_EN_REMAPPER 0x02C2 +#define SYNC_SYMBOL 0x02C3 +#define PID_AND_SYNC_REMAPPER_INV_CTRL 0x02C4 +#define BITRATE_CH0_LSB 0x02C5 +#define BITRATE_CH0_MSB 0x02C6 +#define BITRATE_CH1_LSB 0x02C7 +#define BITRATE_CH1_MSB 0x02C8 +#define STATUS_CLK_SWITCH_0 0x02C9 +#define STATUS_CLK_SWITCH_1 0x02CA +#define RESET_CLK_SWITCH_0 0x02CB +#define RESET_CLK_SWITCH_1 0x02CC +#define PAD_DRVSTR_CTRL 0x02CD +#define PAD_PUPD_CTRL 0x02CE +#define PRE_HEADER_ADDER_CH0_0 0x02D0 +#define PRE_HEADER_ADDER_CH0_1 0x02D1 +#define PRE_HEADER_ADDER_CH0_2 0x02D2 +#define PRE_HEADER_ADDER_CH0_3 0x02D3 +#define PRE_HEADER_ADDER_CH0_4 0x02D4 +#define PRE_HEADER_ADDER_CH0_5 0x02D5 +#define PRE_HEADER_ADDER_CH0_6 0x02D6 +#define PRE_HEADER_ADDER_CH0_7 0x02D7 +#define PRE_HEADER_ADDER_CH0_8 0x02D8 +#define PRE_HEADER_ADDER_CH0_9 0x02D9 +#define PRE_HEADER_ADDER_CH0_10 0x02DA +#define PRE_HEADER_ADDER_CH0_11 0x02DB +#define PRE_HEADER_ADDER_CH1_0 0x02E0 +#define PRE_HEADER_ADDER_CH1_1 0x02E1 +#define PRE_HEADER_ADDER_CH1_2 0x02E2 +#define PRE_HEADER_ADDER_CH1_3 0x02E3 +#define PRE_HEADER_ADDER_CH1_4 0x02E4 +#define PRE_HEADER_ADDER_CH1_5 0x02E5 +#define PRE_HEADER_ADDER_CH1_6 0x02E6 +#define PRE_HEADER_ADDER_CH1_7 0x02E7 +#define PRE_HEADER_ADDER_CH1_8 0x02E8 +#define PRE_HEADER_ADDER_CH1_9 0x02E9 +#define PRE_HEADER_ADDER_CH1_10 0x02EA +#define PRE_HEADER_ADDER_CH1_11 0x02EB +#define PRE_HEADER_ADDER_CTRL 0x02EC +#define PRE_HEADER_ADDER_LEN 0x02ED +#define PRE_HEADER_REMOVER_CTRL 0x02EE +#define FSM_DVB 0x02F0 +#define TS2USB_FSM_DEBUG 0x02F2 +#define TSOUT_PAR_FSM_DEBUG 0x02F3 +#define GAP_REMOVER_FSM_DEBUG 0x02F4 +#define PID_AND_SYNC_REMAPPER_FSM_DEBUG 0x02F5 +#define PRE_HEADER_ADDER_FSM_DEBUG 0x02F6 +#define SYNC_RTV_FSM_DEBUG 0x02F7 +#define CHECK_PHY_CLK 0x0E00 +#define USB_CTRL1 0x0E01 +#define USB_ISO2_out 0x0800 +#define USB_ISO1_out 0x1000 +#define USB_Interrupt_out 0x1E00 +#define USB_Bulk_in 0x1F00 +#define CC2_Buffer_out 0x2000 +#define USB_EP0 0x30C0 +#define CC2_Buffer_in 0x4000 +#define USB_ISO2_in 0x5800 +#define USB_ISO1_in 0x6000 +#define nmb_vector_address_lsb 0xFFFA +#define nmb_vector_address_msb 0xFFFB +#define reset_vector_address_lsb 0xFFFC +#define reset_vector_address_msb 0xFFFD +#define irb_vector_address_lsb 0xFFFE +#define irb_vector_address_msb 0xFFFF + + +#define CIMAX_REG_HDR_SIZE 4 +#define CIMAX_REG_PLD_SIZE 255 +#define CIMAX_CAM_HDR_SIZE 4 +#define CIMAX_CAM_PLD_SIZE 65535 + +#define DEF_LOCK(_l_) struct mutex _l_ + +struct cimax_spi { + struct platform_device *pdev; + struct spi_device *dev; + + struct aml_cimax *cimax; + + u8 buf[CIMAX_REG_HDR_SIZE + CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE]; + + int cam_inserted[2]; + int cam_data_ready[2]; + + int poll_mode; +#define STOP_MODE 0 +#define POLL_MODE 1 +#define INT_MODE 2 + + int irq; + int irq_io; + int rst_io; + + struct workqueue_struct *workq; + struct delayed_work work; + int work_cnt; + + DEF_LOCK(lock); +#define lock_init(_spi) mutex_init(&(_spi)->lock) +#define lock_lock(_spi) do {\ + int err = mutex_lock_interruptible(&(_spi)->lock);\ + if (err)\ + return err;\ +} while (0) +#define lock_unlock(_spi) mutex_unlock(&(_spi)->lock) + + u8 *cis; +#define CIS_MAX 512 +}; + +static struct cimax_spi *g_spi; + +MODULE_PARM_DESC(debug, "enable verbose debug messages"); +static int cimax_spi_debug = 1; +module_param_named(debug, cimax_spi_debug, int, 0644); + +MODULE_PARM_DESC(poll_interval, "interval for spi poll"); +static int spi_poll_interval = 100; +module_param_named(poll_interval, spi_poll_interval, int, 0644); + +MODULE_PARM_DESC(poll_mode, "set cimax poll mode, need reset"); +static int cimax_poll_mode = 1; +module_param_named(poll_mode, cimax_poll_mode, int, 0644); + +MODULE_PARM_DESC(cam_irq_mode, "set cam irq mode, need reset"); +static int cam_irq_mode; +module_param_named(cam_irq_mode, cam_irq_mode, int, 0644); + +#define CIMAX_REG_READ 0xff +#define CIMAX_REG_READ_OK 0x4c +#define CIMAX_REG_WRITE 0x7f +#define CIMAX_REG_WRITE_OK 0x4d +#define CIMAX_REG_INIT 0x00 +#define CIMAX_REG_INIT_OK 0x4b +#define CIMAX_REG_CMD_ERROR 0x51 + +#define CIMAX_CAM_RESET 0x01 +#define CIMAX_CAM_RESET_OK 0x40 +#define CIMAX_CAM_CIS 0x02 +#define CIMAX_CAM_CIS_OK 0x41 +#define CIMAX_CAM_COR 0x03 +#define CIMAX_CAM_COR_OK 0x42 +#define CIMAX_CAM_NEG 0x04 +#define CIMAX_CAM_NEG_OK 0x43 +#define CIMAX_CAM_WLPDU 0x05 +#define CIMAX_CAM_WLPDU_OK 0x44 +#define CIMAX_CAM_RLPDU 0x06 +#define CIMAX_CAM_RLPDU_OK 0x46 +#define CIMAX_CAM_EVT 0x0d +#define CIMAX_CAM_DET_OK 0x45 +#define CIMAX_CAM_NOCAM 0x49 +#define CIMAX_CAM_ERROR 0x4a +#define CIMAX_CAM_NOEVT 0x55 +#define CIMAX_CAM_DATA_READY 0x4e +#define CIMAX_CAM_WBUSY 0x54 +#define CIMAX_CAM_PENDING 0x56 +#define CIMAX_CAM_REGSTAT 0x0e +#define CIMAX_CAM_REGSTAT_OK 0x57 + + +#define CIMAX_CAM_PKT_CNT_VAL 1 + +#define CIMAX_SLOT_A 0 +#define CIMAX_SLOT_B 1 + +#define CIMAX_CMD_RESP_MASK 0x7f + +#define cimax_to_spi(_c) ((struct cimax_spi *)((_c)->priv)) +#define dev_to_spi(_d) ((struct cimax_spi *)spi_get_drvdata(_d)) + +#define byte_to_u16(_b1, _b2) (((_b1)<<8) | (_b2)) + +#define hdr_cmd_resp(_s) ((_s)->buf[0] & CIMAX_CMD_RESP_MASK) + +#define reg_hdr(_s) ((_s)->buf) +#define reg_addr(_s) byte_to_u16((_s)->buf[1], (_s)->buf[2]) +#define reg_hdr_dat_size(_s) ((_s)->buf[3]) +#define reg_dat(_s) (&((_s)->buf[CIMAX_REG_HDR_SIZE])) + +#define cam_hdr(_s) ((_s)->buf) +#define cam_hdr_slot(_s) (((_s)->buf[0] & 0x80) ? 1 : 0) +#define cam_hdr_pkt_cnt(_s) ((_s)->buf[1]) +#define cam_hdr_dat_size(_s) byte_to_u16((_s)->buf[2], (_s)->buf[3]) +#define cam_dat(_s) (&((_s)->buf[CIMAX_CAM_HDR_SIZE])) + +#define REG_TIMEOUT 500 +#define CAM_TIMEOUT 5000 + +#define USE_INT_PIO + +static int aml_cimax_spi_mod_init(void); +static void aml_cimax_spi_mod_exit(void); + +static void dump(char *title, u8 *buf, int size) +{ + int i; + pr_info("%s\n", title); + for (i = 0; i < size; i++) { + if (!(i & 0xf)) + pr_info("\n\t"); + pr_info("%02x ", *(buf+i)); + } + pr_info("\n"); +} + +static void perr(char *err, struct cimax_spi *spi) +{ + pr_error("error: %s\n", err); + dump("dump:", spi->buf, 16); +} + +static inline unsigned long get_jiffies(void) +{ + return (unsigned long)(sched_clock()/10000000); +} + +static inline void set_spi_cam_ready(struct cimax_spi *spi, int slot) +{ + if (spi->cam_inserted[slot] == 1) { + spi->cam_inserted[slot] = 2; + aml_cimax_slot_state_changed(spi->cimax, + slot, spi->cam_inserted[slot]); + } +} + + +static int cimax_spi_get_resp(struct cimax_spi *spi, int timeout) +{ + struct spi_device *dev = spi->dev; + int ret = 0; + unsigned long start = get_jiffies(); +#ifndef USE_INT_PIO + u8 t = 0; + + while (!t && jiffies_to_msecs(get_jiffies() - start) < timeout) { + ret = spi_read(dev, &t, 1); + if (ret) + return ret; + usleep_range(1000, 2000); + } + if (!t) { + pr_error("resp timeout: %dms\n", timeout); + return -EIO; + } + cam_hdr(spi)[0] = t; + ret = spi_read(dev, cam_hdr(spi)+1, CIMAX_CAM_HDR_SIZE-1); + if (ret) + return ret; +#else + do { + if (jiffies_to_msecs(get_jiffies() - start) >= timeout) { + pr_error("resp timeout: %dms\n", timeout); + return -EIO; + } + usleep_range(1000, 2000); + } while (gpio_get_value(spi->irq_io)); + + ret = spi_read(dev, cam_hdr(spi), CIMAX_CAM_HDR_SIZE); + if (ret) + return ret; +#endif + /*pr_dbg("rp: %02x:%02x:%02x:%02x\n", + cam_hdr(spi)[0], cam_hdr(spi)[1], + cam_hdr(spi)[2], cam_hdr(spi)[3]);*/ + switch (hdr_cmd_resp(spi)) { + case CIMAX_REG_READ_OK: + case CIMAX_REG_WRITE_OK: + case CIMAX_REG_INIT_OK: + case CIMAX_REG_CMD_ERROR: { + int len = reg_hdr_dat_size(spi); + if (len) { + ret = spi_read(dev, reg_dat(spi), len); + if (ret != 0) + return ret; + } + } break; + case CIMAX_CAM_RESET_OK: + case CIMAX_CAM_CIS_OK: + case CIMAX_CAM_COR_OK: + case CIMAX_CAM_NEG_OK: + case CIMAX_CAM_WLPDU_OK: + case CIMAX_CAM_RLPDU_OK: + case CIMAX_CAM_NOCAM: + case CIMAX_CAM_ERROR: + case CIMAX_CAM_WBUSY: + case CIMAX_CAM_DET_OK: + case CIMAX_CAM_DATA_READY: + case CIMAX_CAM_PENDING: + case CIMAX_CAM_REGSTAT_OK: + case CIMAX_CAM_NOEVT: { + int len = cam_hdr_dat_size(spi); + if (len) { + ret = spi_read(dev, cam_dat(spi), len); + if (ret != 0) + return ret; + /*if (len) + dump("dat:", cam_dat(spi), len);*/ + } + } + break; + default: + pr_error("unknown resp:0x%02x\n", hdr_cmd_resp(spi)); + return -EINVAL; + } + return 0; +} + +static int init_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + hdr[0] = tag; + hdr[1] = (addr>>8) & 0xff; + hdr[2] = addr & 0xff; + hdr[3] = size; + return 0; +} + +static int check_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + return hdr[0] != tag + || hdr[1] != ((addr>>8) & 0xff) + || hdr[2] != (addr & 0xff) + || hdr[3] != size; +} + +static int aml_cimax_spi_read_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + struct spi_device *dev = spi->dev; + int err = 0; + + init_reg_hdr(spi->buf, CIMAX_REG_READ, addr, size); + + lock_lock(spi); + + pr_dbg("rd %02x:%02x:%02x:%02x\n", + reg_hdr(spi)[0], reg_hdr(spi)[1], + reg_hdr(spi)[2], reg_hdr(spi)[3]); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); + if (err) + goto end; + err = cimax_spi_get_resp(spi, REG_TIMEOUT); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(spi), CIMAX_REG_READ_OK, addr, size) != 0) { + perr("read reg fail.", spi); + err = -EINVAL; + goto end; + } + memcpy(buf, reg_dat(spi), size); +end: + lock_unlock(spi); + return err; +} + +static int aml_cimax_spi_write_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + struct spi_device *dev = spi->dev; + int err = 0; + + init_reg_hdr(spi->buf, CIMAX_REG_WRITE, addr, size); + memcpy(&spi->buf[CIMAX_REG_HDR_SIZE], buf, size); + + lock_lock(spi); + + pr_dbg("wr %02x:%02x:%02x:%02x\n", + reg_hdr(spi)[0], reg_hdr(spi)[1], + reg_hdr(spi)[2], reg_hdr(spi)[3]); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE + size); + if (err) + goto end; + err = cimax_spi_get_resp(spi, REG_TIMEOUT); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(spi), CIMAX_REG_WRITE_OK, addr, 0) != 0) { + perr("write reg fail.", spi); + err = -EINVAL; + goto end; + } +end: + lock_unlock(spi); + return err; +} + +static inline int init_cam_hdr(u8 *hdr, int cmd, int size) +{ + hdr[0] = cmd; + hdr[1] = CIMAX_CAM_PKT_CNT_VAL; + hdr[2] = (size>>8) & 0xff; + hdr[3] = size & 0xff; + return 0; +} + +static inline int cam_err(struct cimax_spi *spi) +{ + if (hdr_cmd_resp(spi) != CIMAX_CAM_ERROR + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 2) + return 0; + return byte_to_u16(cam_dat(spi)[0], cam_dat(spi)[1]); +} + +static inline char *cam_err_str(int err) +{ +#define CAMERROR_RESET 0x0101 +#define CAMERROR_CIS_BUF 0x0201 +#define CAMERROR_CIS_SIZE 0x0202 +#define CAMERROR_CAM_NOT_ACT 0x0203 +#define CAMERROR_COR_NOT_READY 0x0301 +#define CAMERROR_COR_VAL_CHK 0x0302 +#define CAMERROR_NEG_NO_RESP 0x0401 +#define CAMERROR_NEG_BAD_SIZE 0x0402 +#define CAMERROR_NEG_NOT_READY 0x0403 +#define CAMERROR_LPDU_NOT_AVAIL 0x0601 + struct { int err; char *str; } cam_err_strings[] = { + {CAMERROR_RESET, "reset error, not ready."}, + {CAMERROR_CIS_BUF, "cis error, buffer not allocated."}, + {CAMERROR_CIS_SIZE, "cis error, bad cis size."}, + {CAMERROR_CAM_NOT_ACT, "cam not activated."}, + {CAMERROR_COR_NOT_READY, "cam not ready during write COR."}, + {CAMERROR_COR_VAL_CHK, "COR value check failed."}, + {CAMERROR_NEG_NO_RESP, "cam not responding when negotiation."}, + {CAMERROR_NEG_BAD_SIZE, "cam buf size length != 2."}, + {CAMERROR_NEG_NOT_READY, "cam not ready during negotiation."}, + {CAMERROR_LPDU_NOT_AVAIL, "lpdu not available."} + }; + int i; + for (i = 0; + i < sizeof(cam_err_strings)/sizeof(cam_err_strings[0]); i++) { + if (cam_err_strings[i].err == err) + return cam_err_strings[i].str; + } + return "err unknown."; +} + +static int cimax_spi_access_cam(struct cimax_spi *spi, int slot, + int cmd, u8 *buf, int size) +{ + struct spi_device *dev = spi->dev; + int err = 0; + + cmd |= slot ? 0x80 : 0; + init_cam_hdr(cam_hdr(spi), cmd, size); + memcpy(cam_dat(spi), buf, size); + /*dump("access cam:", cam_hdr(spi), CIMAX_CAM_HDR_SIZE+size);*/ + err = spi_write(dev, cam_hdr(spi), CIMAX_CAM_HDR_SIZE + size); + if (err) + return err; + err = cimax_spi_get_resp(spi, CAM_TIMEOUT); + if (err) + return err; + if (cam_hdr_slot(spi) != slot) { + pr_error("expect slot(%d), but slot(%d)\n", + slot, cam_hdr_slot(spi)); + return -EINVAL; + } + switch (hdr_cmd_resp(spi)) { + case CIMAX_CAM_NOCAM: + pr_dbg("no cam\n"); + err = -ENODEV; + break; + case CIMAX_CAM_ERROR: + pr_error("cam error\n"); + pr_error("err code: 0x%04x(%s)\n", cam_err(spi), + cam_err_str(cam_err(spi))); + err = -ENODEV; + break; + case CIMAX_CAM_WBUSY: + pr_dbg("cam busy\n"); + err = -EBUSY; + break; + case CIMAX_CAM_PENDING: + pr_dbg("cam pending\n"); + err = -EAGAIN; + break; + } + return err; +} + +static int aml_cimax_spi_read_cis(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int err = 0; + int len; + + lock_lock(spi); + + err = cimax_spi_access_cam(spi, slot, CIMAX_CAM_CIS, NULL, 0); + if (err) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_CIS_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read cis fail.", spi); + err = -EINVAL; + goto end; + } + len = cam_hdr_dat_size(spi); + if (size < len) { + pr_error("cis size too large, expect<%d, but:%d\n", size, len); + perr("cis fail.", spi); + err = -EINVAL; + goto end; + } + memcpy(buf, cam_dat(spi), len); + + if (!spi->cis) + spi->cis = kzalloc((len < 512) ? 512 : len, GFP_KERNEL); + if (spi->cis) + memcpy(spi->cis, cam_dat(spi), len); + +end: + lock_unlock(spi); + return err; +} +#define CIMAX_CAM_COR_PLD_SIZE 5 +static int aml_cimax_spi_write_cor(struct aml_cimax *cimax, int slot, + int addr, u8 *buf) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int err = 0; + u8 out[CIMAX_CAM_COR_PLD_SIZE + 8]; + int sz = CIMAX_CAM_COR_PLD_SIZE; + + out[0] = addr>>8 & 0xff; + out[1] = addr & 0xff; + out[2] = buf[0]; + out[3] = 0; + out[4] = 0; + + if (!cam_irq_mode) { + out[5] = 0x40;/*cam poll mode*/ + sz++; + } + + lock_lock(spi); + + err = cimax_spi_access_cam(spi, slot, CIMAX_CAM_COR, out, sz); + if (err) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_COR_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 0) { + perr("write cor fail.", spi); + err = -EINVAL; + goto end; + } +end: + lock_unlock(spi); + return err; +} +#define CIMAX_CAM_NEG_PLD_SIZE 2 +static int aml_cimax_spi_negotiate(struct aml_cimax *cimax, int slot, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + u8 out[CIMAX_CAM_NEG_PLD_SIZE]; + + out[0] = (size>>8) & 0xff; + out[1] = size & 0xff; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_NEG, + out, CIMAX_CAM_NEG_PLD_SIZE); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_NEG_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 2) { + perr("negotiate fail.", spi); + ret = -EINVAL; + goto end; + } + ret = byte_to_u16(cam_dat(spi)[0], cam_dat(spi)[1]); + + set_spi_cam_ready(spi, slot); +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_write_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + lock_lock(spi); + + /*dump("lpdu ->", buf, size);*/ + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_WLPDU, buf, size); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_WLPDU_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 0) { + perr("write lpdu fail.", spi); + ret = -EINVAL; + goto end; + } + ret = size; +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_read_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_RLPDU, NULL, 0); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_RLPDU_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read lpdu fail.", spi); + ret = -EINVAL; + goto end; + } + ret = cam_hdr_dat_size(spi); + memcpy(buf, cam_dat(spi), ret); + + /*dump("lpdu <-", buf, ret);*/ + + spi->cam_data_ready[slot] = 0; +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_read_cam_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + if (cam_irq_mode && spi->cam_data_ready[slot]) + return 0x80; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_REGSTAT, NULL, 0); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_REGSTAT_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 1) { + perr("read cam status fail.", spi); + ret = -EINVAL; + goto end; + } + + ret = cam_dat(spi)[0]; +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_slot_reset(struct aml_cimax *cimax, int slot) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + spi->cam_data_ready[slot] = 0; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_RESET, NULL, 0); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_RESET_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 0) { + perr("slot reset fail.", spi); + ret = -EINVAL; + goto end; + } +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_cam_reset(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): camreset\n", slot); + return 0; +} + +static int aml_cimax_spi_slot_shutdown(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): shutdown\n", slot); + return 0; +} +static int aml_cimax_spi_slot_ts_enable(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): ts control\n", slot); + return 0; +} +static int aml_cimax_spi_slot_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + if (spi->cam_inserted[slot]) { + /*pr_dbg("CA Module present and ready\n");*/ + return DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + } else { + /*pr_error("CA Module not present or not ready\n");*/ + } + return 0; +} + +static int cimax_spi_cam_plugin(struct cimax_spi *spi, int slot, int plugin) +{ + pr_dbg("cam plug: slot(%d) %s\n", + slot, plugin ? "plugged" : "unplugged"); + return aml_cimax_camchanged(spi->cimax, slot, plugin); +} + +static int cimax_spi_poll(struct cimax_spi *spi) +{ + struct spi_device *dev = spi->dev; + int err = 0; + + lock_lock(spi); + +#ifdef USE_INT_PIO + if (gpio_get_value(spi->irq_io)) + goto end; +#endif + + init_reg_hdr(spi->buf, CIMAX_CAM_EVT, 0x100, 0); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); + if (err) + goto end; + err = cimax_spi_get_resp(spi, CAM_TIMEOUT); + if (err) + goto end; + switch (hdr_cmd_resp(spi)) { + case CIMAX_CAM_DET_OK: { + int slot = cam_hdr_slot(spi); + int insert = cam_dat(spi)[0]; + if (!!spi->cam_inserted[slot] != insert) { + spi->cam_inserted[slot] = insert; + cimax_spi_cam_plugin(spi, slot, insert); + aml_cimax_slot_state_changed(spi->cimax, slot, + spi->cam_inserted[slot]); + } + } break; + case CIMAX_CAM_DATA_READY: { + int slot = cam_hdr_slot(spi); + spi->cam_data_ready[slot] = 1; + } break; + case CIMAX_CAM_NOEVT: + break; + default: + pr_error("unknown resp:%02x\n", hdr_cmd_resp(spi)); + break; + } +end: + queue_delayed_work(spi->workq, &spi->work, spi_poll_interval); + lock_unlock(spi); + return 0; +} + +static void cimax_spi_poll_work(struct work_struct *work) +{ + struct cimax_spi *spi = + container_of(to_delayed_work(work), struct cimax_spi, work); + spi->work_cnt++; + cimax_spi_poll(spi); +} + +static irqreturn_t cimax_irq_handler(int irq, void *para) +{ + return IRQ_HANDLED; +} + +#define CTRL_DISABLE -1 +#define CTRL_STOP 0 +#define CTRL_START 1 + +static inline int cimax_spi_poll_ctrl(struct cimax_spi *spi, int ctrl) +{ + if (ctrl == CTRL_START) { + spi->workq = create_singlethread_workqueue("cimax_spi"); + INIT_DELAYED_WORK(&spi->work, &cimax_spi_poll_work); + queue_delayed_work(spi->workq, + &spi->work, spi_poll_interval); + pr_dbg("poll started\n"); + } else { + if (!spi->workq) + return 0; + cancel_delayed_work_sync(&spi->work); + destroy_workqueue(spi->workq); + spi->workq = NULL; + pr_dbg("poll stopped\n"); + } + return 0; +} + +static inline int cimax_spi_intr_ctrl(struct cimax_spi *spi, int ctrl) +{ + if (ctrl == CTRL_START) { + int ret; + if (spi->irq == -1) { + pr_error("incorrect irq"); + return -1; + } + ret = request_irq(spi->irq, cimax_irq_handler, + IRQF_SHARED|IRQF_TRIGGER_RISING, + "cimax irq", spi); + enable_irq(spi->irq); + } else { + if (spi->irq == -1) + return 0; + disable_irq(spi->irq); + free_irq(spi->irq, spi); + } + return 0; +} + +static int cimax_spi_setup_poll(struct cimax_spi *spi, int poll_mode) +{ + if (poll_mode == spi->poll_mode) + return 0; + switch (poll_mode) { + case POLL_MODE: + if (spi->poll_mode == INT_MODE) + cimax_spi_intr_ctrl(spi, CTRL_DISABLE); + cimax_spi_poll_ctrl(spi, CTRL_START); + spi->poll_mode = POLL_MODE; + break; + case INT_MODE: + if (spi->poll_mode == POLL_MODE) + cimax_spi_poll_ctrl(spi, CTRL_DISABLE); + cimax_spi_intr_ctrl(spi, CTRL_START); + spi->poll_mode = INT_MODE; + break; + case STOP_MODE: + if (spi->poll_mode == POLL_MODE) + cimax_spi_poll_ctrl(spi, CTRL_DISABLE); + else if (spi->poll_mode == INT_MODE) + cimax_spi_intr_ctrl(spi, CTRL_DISABLE); + spi->poll_mode = STOP_MODE; + break; + default: + break; + } + return 0; +} + +static int cimax_spi_hw_reset(struct cimax_spi *spi, int reset_val) +{ + /*trigger reset io*/ + if (spi->rst_io) { + gpio_direction_output(spi->rst_io, reset_val ? 1 : 0); + msleep(50); + gpio_direction_output(spi->rst_io, reset_val ? 0 : 1); + } + return 0; +} + + +enum regOperation_e { + /** Read register. */ + REG_OP_READ, + /** Write register. */ + REG_OP_WRITE, + /** Read register until some bits are set. */ + REG_OP_WAIT_TO_BE_SET, + /** Read register until some bits are cleared. */ + REG_OP_WAIT_TO_BE_CLEARED, + /** Read register until it's value is not equal to defined. */ + REG_OP_WAIT_EQUAL, + /** Perform logical AND over register. */ + REG_OP_LOGICAL_AND, + /** Perform logical OR over register. */ + REG_OP_LOGICAL_OR, + /** Wait timeout in miliseconds. */ + REG_OP_WAIT +}; + +struct regSettings_s { + /** CIMaX+ register address. */ + u16 reg; + /** CIMaX+ register value. */ + u16 val; + /** CIMaX+ register operation. */ + enum regOperation_e op; +}; + +static struct regSettings_s spiRegSettings[] = { + /** TS interface init. */ + {IN_SEL, 0x00, REG_OP_WRITE}, /** Close TS input. */ + {OUT_SEL, 0x00, REG_OP_WRITE}, /** Close TS output. */ + {FIFO_CTRL, 0x0f, REG_OP_WRITE}, /** Reset TS FIFO. */ + {SYNC_RTV_CTRL, 0x0f, REG_OP_WRITE}, + + /** CAM power. */ + {GPIO0_DATA_OUT, 0x00, REG_OP_WRITE}, + /** Unlock CFG. */ + {CFG_2, 0x00, REG_OP_WRITE}, + /** 1) DVB/CI/CI+/SCARD 2slot. */ + {CFG_1, 0x00, REG_OP_WRITE}, + /** 2) Set the Default "power off" state + such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z'. */ + {GPIO0_DFT, 0x00, REG_OP_WRITE}, + /** 3) Set GPIO3 as external power switch driver. */ + {GPIO0_MASK_DATA, 0x07, REG_OP_WRITE}, + /** 4) Set "power on" state (VCC=VPP1=VPP2= 5V). */ + {GPIO0_DATA_OUT, 0x03, REG_OP_WRITE}, + /** 5) Lock config. */ + {CFG_2, 0x01, REG_OP_WRITE}, + /** 6) Write in the GPIO0_DIR_REG: defines the GPIOs, + which are used to drive the external power switch, in output mode. */ + {GPIO0_DIR, 0x07, REG_OP_WRITE}, + /** 7) Check VCCENable. */ + {CFG_1, 0x20, REG_OP_WAIT_TO_BE_SET}, + /** 8) Set & wait for PcmciaOutputEnable. */ + {CFG_1, 0x08, REG_OP_LOGICAL_OR}, + {CFG_1, 0x08, REG_OP_WAIT_TO_BE_SET}, + + /** Set router CAM. */ + /** CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1. */ + {ROUTER_CAM_MOD, 0x21, REG_OP_WRITE}, + {ROUTER_CAM_CH, 0x00, REG_OP_WRITE}, + /** Wait 200 miliseconds. */ + {0x0000, 200, REG_OP_WAIT}, + + /** Set In/Out. */ + /** Route CAM Channel 0 to Channel 0, Channel 1 null. */ + {ROUTER_CAM_CH, 0x80, REG_OP_WRITE}, + +#ifdef PARALLEL_OUT +#else +#if 1 + /*72M internal clock source*/ + /*CLK Select SER0->72M*/ + {CkMan_Select, 0x20, REG_OP_WRITE}, + /*Enable SER0 clk source, Enable 72M clk source*/ + {CkMan_Config, 0x44, REG_OP_LOGICAL_OR}, +#else + /*108M internal clock source*/ + /*CLK Select SER0->108M*/ + {CkMan_Select, 0x30, REG_OP_WRITE}, + /*Enable SER0 clk source, Enable 108M clk source*/ + {CkMan_Config, 0x48, REG_OP_LOGICAL_OR}, +#endif + {P2S_CH0_CTRL, 0x19, REG_OP_WRITE}, /*Enable p2s*/ + {OUT_SEL, 0x02, REG_OP_WRITE}, /*Out1=p2s0*/ +#endif /*Parallel out*/ + + /** Input Ch0=Parallel, Ch1=null. */ + {IN_SEL, 0x01, REG_OP_WRITE}, +}; + +int downloadCfg(struct cimax_spi *spi) +{ + u32 cnt; + u8 buf[CIMAX_REG_PLD_SIZE]; + struct aml_cimax *cimax = spi->cimax; + + pr_info("Download CIMaX+ configuration(register settings):\n"); + + for (cnt = 0; cnt < sizeof(spiRegSettings)/sizeof(struct regSettings_s); + cnt++) { + pr_dbg("reg:%04x, val:%02x, op:%d\n", + spiRegSettings[cnt].reg, + spiRegSettings[cnt].val, + spiRegSettings[cnt].op); + switch (spiRegSettings[cnt].op) { + case REG_OP_READ: + /* Read register. */ + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("FAILED at REG_OP_READ operation.\n"); + return -1; + } + break; + case REG_OP_WRITE: + /* Write register. */ + if (aml_cimax_spi_write_reg(cimax, + spiRegSettings[cnt].reg, + (u8 *)&spiRegSettings[cnt].val, + 1) < 0) { + /* CIMaX+ write error. */ + pr_error("FAILED at REG_OP_WRITE operation.\n"); + return -1; + } + break; + case REG_OP_WAIT_TO_BE_SET: + do { + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("E REG_OP_WAIT_TO_BE_SET\n"); + return -1; + } + } while ((buf[0] & spiRegSettings[cnt].val) + != spiRegSettings[cnt].val); + break; + case REG_OP_WAIT_TO_BE_CLEARED: + do { + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("REG_OP_WAIT_TO_BE_CLEARED\n"); + return -1; + } + } while ((buf[0] & spiRegSettings[cnt].val) != 0); + break; + case REG_OP_WAIT_EQUAL: + do { + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("REG_OP_WAIT_EQUAL.\n"); + return -1; + } + } while (buf[0] != spiRegSettings[cnt].val); + break; + case REG_OP_LOGICAL_AND: + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("FAILED at REG_OP_LOGICAL_AND(r).\n"); + return -1; + } + buf[0] &= spiRegSettings[cnt].val; + if (aml_cimax_spi_write_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ write error. */ + pr_error("FAILED at REG_OP_LOGICAL_AND(w).\n"); + return -1; + } + break; + case REG_OP_LOGICAL_OR: + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("FAILED at REG_OP_LOGICAL_OR(r).\n"); + return -1; + } + buf[0] |= spiRegSettings[cnt].val; + if (aml_cimax_spi_write_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ write error. */ + pr_error("FAILED at REG_OP_LOGICAL_AND(w).\n"); + return -1; + } + break; + case REG_OP_WAIT: + msleep(spiRegSettings[cnt].val); + break; + default: + pr_error("\nInvalid operation 0x%02x!\n", + spiRegSettings[cnt].op); + } + } + pr_info("config OK.\n"); + return 0; +} + + +#define CIMAX_FW_PKT_SIZE 128 +#define CIMAX_FW_START_ADDR 0x8000 +#define CIMAX_FW_STOP_ADDR 0xcff9 +#define CIMAX_FW_VECT_ADDR 0xfffa +#define CIMAX_FW_VECT_SIZE 6 + +static u32 compute_bistrom(const u8 *ptr, int size, u32 sign) +{ + int k, i; + u16 s; + + for (k = 0; k < size; k++) { + s = ptr[k]&0x01; + for (i = 0; i < 16; i++) + if (0x88B7 & (1<>i) & 0x01; + s |= ((sign<<1) ^ (ptr[k])) & 0x00FE; + s |= (sign<<1) & 0x00FF00; + sign = s; + } + return sign; +} + +static int cimax_spi_upload_firmware(struct cimax_spi *spi, + const u8 *fw_data, u32 *sign) +{ + struct aml_cimax *cimax = spi->cimax; + int err = 0; + int addr; + const u8 *ptr; + int size; + int debug = cimax_spi_debug; + u8 *ptmp = kzalloc(CIMAX_FW_PKT_SIZE + CIMAX_REG_HDR_SIZE, GFP_KERNEL); + + if (!ptmp) + return -ENOMEM; + + cimax_spi_debug = 0; + + addr = CIMAX_FW_START_ADDR; + ptr = fw_data + addr; + while (addr < CIMAX_FW_STOP_ADDR) { + size = (addr <= (CIMAX_FW_STOP_ADDR+1-CIMAX_FW_PKT_SIZE)) ? + CIMAX_FW_PKT_SIZE : (CIMAX_FW_STOP_ADDR+1-addr); + + *sign = compute_bistrom(ptr, size, *sign); + + pr_dbg(">>%x@%x\n", size, addr); + + /*dump("w:", (u8*)ptr, size);*/ + err = aml_cimax_spi_write_reg(cimax, addr, (u8 *)ptr, size); + if (err) + break; + err = aml_cimax_spi_read_reg(cimax, addr, ptmp, size); + if (err) + break; + /*dump("r:", ptmp, size);*/ + if (memcmp(ptr, ptmp, size)) { + pr_error("fw write error.\n"); + err = -ENODEV; + break; + } + + addr += size; + ptr += size; + } + + if (!err) { + addr = CIMAX_FW_VECT_ADDR; + ptr = fw_data + addr; + size = CIMAX_FW_VECT_SIZE; + + *sign = compute_bistrom(ptr, size, *sign); + + err = aml_cimax_spi_write_reg(cimax, addr, (u8 *)ptr, size); + if (err) + goto end; + err = aml_cimax_spi_read_reg(cimax, addr, ptmp, size); + if (err) + goto end; + if (memcmp(ptr, ptmp, size)) { + pr_error("fw vect write error.\n"); + err = -ENODEV; + goto end; + } + } +end: + kfree(ptmp); + + cimax_spi_debug = debug; + return err; +} + +static int cimax_spi_check_bistrom(struct cimax_spi *spi, + int start, int end, u32 sign) +{ + struct aml_cimax *cimax = spi->cimax; + int err = 0; + u8 buf[2]; + + buf[0] = (0xd000-start) & 0xff; + buf[1] = (0xd000-start) >> 8; + err = aml_cimax_spi_write_reg(cimax, 0x8d, buf, 2); + if (err) + return err; + buf[0] = sign & 0xff; + buf[1] = sign >> 8; + err = aml_cimax_spi_write_reg(cimax, 0x80, buf, 2); + if (err) + return err; + buf[0] = 0xf; + err = aml_cimax_spi_write_reg(cimax, 0x82, buf, 1); + if (err) + return err; + err = aml_cimax_spi_read_reg(cimax, 0x41, buf, 2); + if (err) + return err; + pr_dbg("bist checked: 0x%04x\n", byte_to_u16(buf[0], buf[1])); + err = aml_cimax_spi_read_reg(cimax, 0x09, buf, 1); + if (err) + return err; + pr_dbg("rom status: 0x%02x\n", buf[0]); + return buf[0]; +} + +static int cimax_spi_init_firmware(struct cimax_spi *spi) +{ + struct spi_device *dev = spi->dev; + int err = 0; + + init_reg_hdr(spi->buf, CIMAX_REG_INIT, 0, 0); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); + if (err) + return err; + err = cimax_spi_get_resp(spi, REG_TIMEOUT); + if (err) + return err; + if (check_reg_hdr(spi->buf, CIMAX_REG_INIT_OK, 0, 0)) { + perr("init fw fail.", spi); + return -EINVAL; + } + return err; +} + +static void request_fw_callback(const struct firmware *fw, void *context) +{ + u32 sign = 0; + int err = 0; + struct cimax_spi *spi = (struct cimax_spi *)context; + + if (!fw) + return; + + pr_dbg("got fw: %zd @ %p\n", fw->size, fw->data); + + /*cimax_spi_hw_reset(spi, 1);*/ + + err = cimax_spi_upload_firmware(spi, fw->data, &sign); + if (err) + goto end; + pr_dbg("upload fw done.\n"); + err = cimax_spi_check_bistrom(spi, + CIMAX_FW_START_ADDR, CIMAX_FW_STOP_ADDR, sign); + if (err != 0x2) + goto end; + pr_dbg("check bistrom done.\n"); + err = cimax_spi_init_firmware(spi); + if (err) + goto end; +end: + if (fw) + release_firmware(fw); + if (err) + return; + + if (downloadCfg(spi)) { + pr_error("download config fail.\n"); + return; + } + + cimax_spi_setup_poll(spi, cimax_poll_mode ? POLL_MODE : INT_MODE); + + return; +} + +static int cimax_spi_load_fw(struct cimax_spi *spi) +{ + char *name = "cimax_spidvb.bin"; + return request_firmware_nowait(THIS_MODULE, 1, name, + &spi->dev->dev, GFP_KERNEL, spi, request_fw_callback); +} + +static int cimax_spi_dev_probe(struct spi_device *spi) +{ + int ret; + struct cimax_spi *cimax_spi; + + pr_dbg("dev probe\n"); + /*setup again?*/ + spi->bits_per_word = 8; + ret = spi_setup(spi); + if (ret) + pr_dbg("spi setup failed\n"); + + cimax_spi = dev_get_platdata(&spi->dev); + cimax_spi->dev = spi; + + spi_set_drvdata(spi, cimax_spi); + + return cimax_spi_load_fw(cimax_spi); +} + +static int cimax_spi_dev_remove(struct spi_device *spi) +{ + struct cimax_spi *cimax_spi = dev_get_drvdata(&spi->dev); + + pr_dbg("dev remove\n"); + cimax_spi_setup_poll(cimax_spi, STOP_MODE); + return 0; +} + +static int cimax_spi_get_config_from_dts(struct cimax_spi *spi, + struct spi_board_info *bdinfo) +{ + struct device_node *child = NULL; + struct platform_device *pdev = spi->pdev; + struct device_node *np = pdev->dev.of_node; + unsigned int val; + int ret = 0; + pr_dbg("fetch cimax spi in dts\n"); + + child = of_get_child_by_name(np, "cimax"); + if (child == NULL) { + pr_error("cimax not found in dts\n"); + return -1; + } + child = of_get_child_by_name(child, "spi"); + if (!child) { + pr_error("spi not found in cimax"); + return -1; + } + + /* get spi config */ + ret = of_property_read_u32(child, "bus_num", &val); + if (ret) + pr_error("bus_num not found, use default.\n"); + else + bdinfo->bus_num = val; + pr_dbg("bus_num: %d\n", bdinfo->bus_num); + ret = of_property_read_u32(child, "chip_select", &val); + if (ret) + pr_error("chip_select not found, use default.\n"); + else + bdinfo->chip_select = val; + pr_dbg("chip_select: %d\n", bdinfo->chip_select); + ret = of_property_read_u32(child, "max_frequency", &val); + if (ret) + pr_error("max_frequency not found, use default.\n"); + else + bdinfo->max_speed_hz = val; + pr_dbg("max_speed_hz: %d\n", bdinfo->max_speed_hz); + ret = of_property_read_u32(child, "mode", &val); + if (ret) + pr_error("mode not found, use default.\n"); + else + bdinfo->mode = val; + pr_dbg("mode: %d\n", bdinfo->mode); +/* +dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:spi,2:cimax + cimax { + io_type = <0> //0:spi 1:usb + spi { + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <3000000>; + + rst_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + irq_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + irq = <2>; + interrupts = ; + }; + }; + +}; +*/ +#ifdef USE_INT_PIO + { + int ret = 0; + int gpio = -1; + gpio = of_get_named_gpio_flags(child, "irq-gpios", 0, NULL); + ret = gpio_request(gpio, "cimax-irq"); + if (ret < 0) { + pr_error("irq-gpios request fail.\n"); + return ret; + } + + ret = gpio_direction_input(gpio); + + spi->irq_io = gpio; + pr_dbg("irq_io: %d\n", spi->irq_io); + } +#ifdef CIMAX_IRQ + { + int irq; + unsigned int irqflag; + ret = of_property_read_u32(child, "irq", &gpio_irq); + irq = irq_of_parse_and_map(child, 0); + + gpio_for_irq(gpio, + AML_GPIO_IRQ(gpio_irq, FILTER_NUM7, GPIO_IRQ_FALLING)); + spi->irq = irq; + pr_dbg("irq: %d\n", spi->irq); + } +#else + spi->irq = -1; +#endif +#endif/*USE_INT_PIO*/ + { + int ret = 0; + int gpio = -1; + gpio = of_get_named_gpio_flags(child, "rst-gpios", 0, NULL); + if (gpio != -1) { + ret = gpio_request(gpio, "cimax"); + if (ret < 0) { + pr_error("rst-gpios request fail.\n"); + return ret; + } + + cimax_spi_hw_reset(spi, 1); + + spi->rst_io = gpio; + pr_dbg("rst: %d\n", spi->rst_io); + } else { + pr_error("rst io got fail, %d\n", gpio); + } + } + return 0; +} + +static struct spi_board_info cimax_spi_bdinfo = { + .modalias = "cimax_spi", + .mode = SPI_MODE_3, + .max_speed_hz = 1000000, /* 1MHz */ + .bus_num = 0, /* SPI bus No. */ + .chip_select = 0, /* the device index on the spi bus */ + .controller_data = NULL, +}; + +static struct spi_driver cimax_spi_dev_driver = { + .probe = cimax_spi_dev_probe, + .remove = cimax_spi_dev_remove, + .driver = { + .name = "cimax_spi", + .owner = THIS_MODULE, + }, +}; + +int aml_cimax_spi_init(struct platform_device *pdev, struct aml_cimax *cimax) +{ + int ret; + struct cimax_spi *cimax_spi; + + cimax_spi = kzalloc(sizeof(struct cimax_spi), GFP_KERNEL); + if (!cimax_spi) + return -ENOMEM; + + cimax_spi->pdev = pdev; + cimax_spi->cimax = cimax; + cimax_spi_get_config_from_dts(cimax_spi, &cimax_spi_bdinfo); + + /*init spi_lock*/ + lock_init(cimax_spi); + + /*register device*/ + cimax_spi_bdinfo.platform_data = cimax_spi; + spi_register_board_info(&cimax_spi_bdinfo, 1); + + /*register driver*/ + ret = spi_register_driver(&cimax_spi_dev_driver); + if (ret) { + pr_error("register cimax spi driver failed\n"); + return ret; + } + + /*init cimax used api.*/ +#define WI(_f)\ + cimax->ops._f = aml_cimax_spi_##_f + WI(read_cis); + WI(write_cor); + WI(negotiate); + WI(read_lpdu); + WI(write_lpdu); + WI(read_cam_status); + WI(cam_reset); + WI(slot_reset); + WI(slot_shutdown); + WI(slot_ts_enable); + WI(slot_status); + /*WI(start);*/ + /*WI(stop);*/ + WI(read_reg); + WI(write_reg); + + cimax->priv = cimax_spi; + + g_spi = cimax_spi; + + aml_cimax_spi_mod_init(); + + return 0; +} +EXPORT_SYMBOL(aml_cimax_spi_init); + +int aml_cimax_spi_exit(struct aml_cimax *cimax) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + + if (!spi) + return -ENODEV; + + aml_cimax_spi_mod_exit(); + + /*unregister driver*/ + spi_unregister_driver(&cimax_spi_dev_driver); + /*unregister device*/ + spi_unregister_device(spi->dev); + + if (spi->irq_io) + gpio_free(spi->irq_io); + if (spi->rst_io) + gpio_free(spi->rst_io); + + kfree(spi->cis); + + kfree(spi); + cimax->priv = NULL; + + g_spi = NULL; + return 0; +} +EXPORT_SYMBOL(aml_cimax_spi_exit); + +static int cimax_spi_reset(struct cimax_spi *spi, int reset_val) +{ + pr_dbg("reset spi:%p, rst:%d\n", spi, spi ? spi->rst_io : -1); + if (!spi) + return -ENODEV; + + pr_dbg("cimax spi reset\n"); + + cimax_spi_setup_poll(spi, STOP_MODE); + + cimax_spi_hw_reset(spi, reset_val); + + /*notify unplugged*/ + aml_cimax_camchanged(spi->cimax, 0, 0); + aml_cimax_camchanged(spi->cimax, 1, 0); + + spi->cam_inserted[0] = spi->cam_inserted[1] = 0; + spi->cam_data_ready[0] = spi->cam_data_ready[1] = 0; + + /*async start fw*/ + cimax_spi_load_fw(spi); + + /*cimax_spi_setup_poll(spi, cimax_poll_mode? POLL_MODE : INT_MODE);*/ + return 0; +} + +static ssize_t reset_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret; + ret = sprintf(buf, "echo 1 > %s\n", attr->attr.name); + return ret; +} + +static ssize_t reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret; + int val = 0; + if (!g_spi) + return size; + ret = sscanf(buf, "%i", &val); + if (ret == 1) + ret = cimax_spi_reset(g_spi, val); + return size; +} + +static ssize_t debug_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + if (!g_spi) + return ret; + + ret = sprintf(buf, "poll mode: %d\n", g_spi->poll_mode); + ret += sprintf(buf+ret, "status slot[0]=[%d] slot[1]=[%d]\n", + g_spi->cam_inserted[0], g_spi->cam_inserted[1]); + ret += sprintf(buf+ret, "data slot[0]=[%d] slot[1]=[%d]\n", + g_spi->cam_data_ready[0], g_spi->cam_data_ready[1]); + ret += sprintf(buf+ret, "work cnt:%d\n", g_spi->work_cnt); + return ret; +} + +static int reg_addr; +static ssize_t addr_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + ret = sprintf(buf, "addr = 0x%04x\n", reg_addr); + return ret; +} + +static ssize_t addr_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (!g_spi) + return size; + if (sscanf(buf, "%i", ®_addr) == 1) + return size; + return size; +} + +static ssize_t reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 reg_val = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return ret; + + cimax = g_spi->cimax; + ret = aml_cimax_spi_read_reg(cimax, reg_addr, ®_val, 1); + if (ret) + ret = sprintf(buf, "read fail, err=%d\n", ret); + else + ret = sprintf(buf, "reg[0x%04x] = 0x%02x\n", reg_addr, reg_val); + return ret; +} + +static ssize_t reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + struct aml_cimax *cimax = NULL; + int val = 0; + u8 reg_val = 0; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &val) != 1) + return size; + reg_val = val; + cimax = g_spi->cimax; + ret = aml_cimax_spi_write_reg(cimax, reg_addr, ®_val, 1); + if (ret) + return ret; + return size; +} + +static int cis_mode; /*0:hex 1:binary*/ +static ssize_t cis_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + if (!g_spi || !g_spi->cis) + return ret; + + if (cis_mode == 0) { + int i; + for (i = 0; i < CIS_MAX; i++) { + if (i && !(i & 0xf)) + ret += sprintf(buf+ret, "\n"); + ret += sprintf(buf+ret, "%02X ", g_spi->cis[i]); + } + ret += sprintf(buf+ret, "\n"); + return ret; + } else { + memcpy(buf, g_spi->cis, CIS_MAX); + return CIS_MAX; + } + return ret; +} + +static ssize_t cis_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (size >= 3 + && !memcmp(buf, "bin", 3)) + cis_mode = 1; + else + cis_mode = 0; + return size; +} + +static ssize_t ts_rate_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 lsb = 0, msb = 0, plen = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_spi) + return ret; + + cimax = g_spi->cimax; + err = aml_cimax_spi_read_reg(cimax, PCK_LENGTH, &plen, 1); + err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH0_LSB, &lsb, 1); + err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH0_MSB, &msb, 1); + if (err || !byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else + ret += sprintf(buf+ret, "rate[0] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + if (err) + return ret; + + err = aml_cimax_spi_read_reg(cimax, BITRATE_CH1_LSB, &lsb, 1); + err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH1_MSB, &msb, 1); + if (err || !byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else + ret += sprintf(buf+ret, "rate[1] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + return ret; +} + +static ssize_t loop_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 ch = 0, mod = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_spi) + return ret; + + cimax = g_spi->cimax; + err = aml_cimax_spi_read_reg(cimax, ROUTER_CAM_CH, &ch, 1); + err |= aml_cimax_spi_read_reg(cimax, ROUTER_CAM_MOD, &mod, 1); + if (err) { + ret = sprintf(buf, "read fail, err=%d\n", err); + return ret; + } + ret += sprintf(buf + ret, "OUT-0 <= "); + switch (ch & 0x0f) { + case 0x0: + ret += sprintf(buf + ret, "CAM-A"); break; + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + case 0x8: + ret += sprintf(buf + ret, "NONE"); break; + default: + ret += sprintf(buf + ret, "UNKNOWN"); break; + } + ret += sprintf(buf + ret, "\nCAM-A <= "); + switch (mod & 0x07) { + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + default: + ret += sprintf(buf + ret, "NONE"); break; + } + ret += sprintf(buf + ret, "\n"); + + return ret; +} + + +static ssize_t loop_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int loop = 0; + int err = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &loop) == 1) { + int a = g_spi->cam_inserted[0]; + int b = g_spi->cam_inserted[1]; + u8 cm[2]; + cm[0] = loop ? (b ? 0x85 : 0x80) : 0x81;/*CH*/ + cm[1] = loop ? (a ? 0x51 : 0x11) : 0x00;/*MOD*/ + cimax = g_spi->cimax; + err = aml_cimax_spi_write_reg(cimax, ROUTER_CAM_CH, cm, 2); + } + return size; +} + +static ssize_t slot_reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + pr_dbg("reset slot %d\n", slot); + cimax = g_spi->cimax; + err = aml_cimax_spi_slot_reset(cimax, slot); + } + } + return size; +} + +static ssize_t detect_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + cimax = g_spi->cimax; + err = aml_cimax_spi_read_reg(cimax, addr, ®, 1); + g_spi->cam_inserted[slot] = reg & 1; + pr_dbg("detect slot(%d): %d\n", slot, reg & 1); + } + } + return size; +} + +static struct class_attribute cimax_spi_class_attrs[] = { + __ATTR_RW(reset), + __ATTR_RO(debug), + __ATTR_RW(addr), + __ATTR_RW(reg), + __ATTR_RW(cis), + __ATTR_RO(ts_rate), + __ATTR_RW(loop), + __ATTR_WO(slot_reset), + __ATTR_WO(detect), + __ATTR_NULL +}; + +static struct class cimax_spi_class = { + .name = "cimax_spi", + .class_attrs = cimax_spi_class_attrs, +}; + +static int aml_cimax_spi_mod_init(void) +{ + int ret; + pr_dbg("Amlogic CIMAX SPI Init\n"); + ret = class_register(&cimax_spi_class); + return 0; +} + +static void aml_cimax_spi_mod_exit(void) +{ + pr_dbg("Amlogic CIMAX SPI Exit\n"); + class_unregister(&cimax_spi_class); +} + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h new file mode 100644 index 000000000000..3548de0506dd --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h @@ -0,0 +1,20 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef _AML_CIMAX_SPI_H_ +#define _AML_CIMAX_SPI_H_ + +#include +#include "aml_cimax.h" + +int aml_cimax_spi_init(struct platform_device *pdev, struct aml_cimax *ci); +int aml_cimax_spi_exit(struct aml_cimax *ci); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c new file mode 100644 index 000000000000..b74b34a63b51 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c @@ -0,0 +1,1714 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include "aml_cimax.h" +#include "./usb/SRC/cimax+usb-driver.h" + +#define MOD_NAME "aml_cimax_usb" + +#define pr_dbg(fmt...)\ + do {\ + if (cimax_usb_debug)\ + pr_info("cimax_usb: "fmt);\ + } while (0) +#define pr_inf(fmt...) pr_info("cimax_usb: "fmt) +#define pr_error(fmt...) pr_err("AML_CIMAX_USB: " fmt) + +/* + Uncomment below and enable permanent power in cfg + to disable dynamic power control mechanism +*/ +/*#define DISABLE_POWER_PATCH*/ + +#define BUFFIN_CFG 0x0000 +#define BUFFIN_ADDR_LSB 0x0001 +#define BUFFIN_ADDR_MSB 0x0002 +#define BUFFIN_DATA 0x0003 +#define BUFFOUT_CFG 0x0004 +#define BUFFOUT_ADDR_LSB 0x0005 +#define BUFFOUT_ADDR_MSB 0x0006 +#define BUFFOUT_DATA 0x0007 +#define BOOT_Key 0x0008 +#define BOOT_Status 0x0009 +#define BOOT_Test 0x000A +#define usb2_0_irq_mask 0x0010 +#define usb2_0_status 0x0011 +#define usb2_0_rx 0x0012 +#define usb2_0_tx 0x0013 +#define SPI_Slave_Ctrl 0x0018 +#define SPI_Slave_Status 0x0019 +#define SPI_Slave_Rx 0x001A +#define SPI_Slave_Tx 0x001B +#define SPI_Slave_Mask 0x001C +#define UCSG_Ctrl 0x0020 +#define UCSG_Status 0x0021 +#define UCSG_RxData 0x0022 +#define UCSG_TxData 0x0023 +#define PCtrl_Ctrl 0x0028 +#define PCtrl_Status 0x0029 +#define PCtrl_NbByte_LSB 0x002A +#define PCtrl_NbByte_MSB 0x002B +#define SPI_Master_Ctl 0x0030 +#define SPI_Master_NCS 0x0031 +#define SPI_Master_Status 0x0032 +#define SPI_Master_TxBuf 0x0033 +#define SPI_Master_RxBuf 0x0034 +#define BISTRAM_Ctl 0x0038 +#define BISTRAM_Bank 0x0039 +#define BISTRAM_Pat 0x003A +#define BISTRAM_SM 0x003B +#define BISTRAM_AddrLSB 0x003C +#define BISTROM_Config 0x0040 +#define BISTROM_SignatureLSB 0x0041 +#define BISTROM_SignatureMSB 0x0042 +#define BISTROM_StartAddrLSB 0x0043 +#define BISTROM_StartAddrMSB 0x0043 +#define BISTROM_StopAddrLSB 0x0043 +#define BISTROM_StopAddrMSB 0x0043 +#define CkMan_Config 0x0048 +#define CkMan_Select 0x0049 +#define CkMan_Test 0x004A +#define Revision_Number 0x004B +#define ResMan_Config 0x0050 +#define ResMan_Status 0x0051 +#define ResMan_WD 0x0052 +#define ResMan_WD_MSB 0x0053 +#define CPU_Test 0x0060 +#define IrqMan_Config0 0x0068 +#define IrqMan_Config1 0x0069 +#define IrqMan_Irq0 0x006A +#define IrqMan_NMI 0x006B +#define IrqMan_SleepKey 0x006C +#define Tim_Config 0x0070 +#define Tim_Value_LSB 0x0071 +#define Tim_Value_MSB 0x0072 +#define Tim_Comp_LSB 0x0073 +#define Tim_Comp_MSB 0x0074 +#define TI_Config 0x0076 +#define TI_Data 0x0077 +#define TI_Reg0 0x0078 +#define TI_Reg1 0x0079 +#define TI_Reg2 0x007A +#define TI_Reg3 0x007B +#define TI_Reg4 0x007C +#define TI_ROM1 0x007D +#define TI_ROM2 0x007E +#define TI_ROM3 0x007F +#define DVBCI_START_ADDR 0x0100 +#define DVBCI_END_ADDR 0x017F +#define DATA 0x0180 +/*#define CTRL 0x0181*/ +#define QB_HOST 0x0182 +#define LEN_HOST_LSB 0x0183 +#define LEN_HOST_MSB 0x0184 +#define FIFO_TX_TH_LSB 0x0185 +#define FIFO_TX_TH_MSB 0x0186 +#define FIFO_TX_D_NB_LSB 0x0187 +#define FIFO_TX_D_NB_MSB 0x0188 +#define QB_MOD_CURR 0x0189 +#define LEN_MOD_CURR_LSB 0x018A +#define LEN_MOD_CURR_MSB 0x018B +#define QB_MOD 0x018C +#define LEN_MOD_LSB 0x018D +#define LEN_MOD_MSB 0x018E +#define FIFO_RX_TH_LSB 0x018F +#define FIFO_RX_TH_MSB 0x0190 +#define FIFO_RX_D_NB_LSB 0x0191 +#define FIFO_RX_D_NB_MSB 0x0192 +#define IT_STATUS_0 0x0193 +#define IT_STATUS_1 0x0194 +#define IT_MASK_0 0x0195 +#define IT_MASK_1 0x0196 +#define IT_HOST_PIN_CFG 0x0200 +#define CFG_0 0x0201 +#define CFG_1 0x0202 +#define CFG_2 0x0203 +#define IT_HOST 0x0204 +#define MOD_IT_STATUS 0x0205 +#define MOD_IT_MASK 0x0206 +#define MOD_CTRL_A 0x0207 +#define MOD_CTRL_B 0x0208 +#define DEST_SEL 0x0209 +#define CAM_MSB_ADD 0x020A +#define GPIO0_DIR 0x020B +#define GPIO0_DATA_IN 0x020C +#define GPIO0_DATA_OUT 0x020D +#define GPIO0_STATUS 0x020E +#define GPIO0_IT_MASK 0x020F +#define GPIO0_DFT 0x0210 +#define GPIO0_MASK_DATA 0x0211 +#define GPIO1_DIR 0x0212 +#define GPIO1_DATA_IN 0x0213 +#define GPIO1_DATA_OUT 0x0214 +#define GPIO1_STATUS 0x0215 +#define GPIO1_IT_MASK 0x0216 +#define MEM_ACC_TIME_A 0x0217 +#define MEM_ACC_TIME_B 0x0218 +#define IO_ACC_TIME_A 0x0219 +#define IO_ACC_TIME_B 0x021A +#define EXT_CH_ACC_TIME_A 0x021B +#define EXT_CH_ACC_TIME_B 0x021C +#define PAR_IF_0 0x021D +#define PAR_IF_1 0x021E +#define PAR_IF_CTRL 0x021F +#define PCK_LENGTH 0x0220 +#define USB2TS_CTRL 0x0221 +#define USB2TS0_RDL 0x0222 +#define USB2TS1_RDL 0x0223 +#define TS2USB_CTRL 0x0224 +#define TSOUT_PAR_CTRL 0x0225 +#define TSOUT_PAR_CLK_SEL 0x0226 +#define S2P_CH0_CTRL 0x0227 +#define S2P_CH1_CTRL 0x0228 +#define P2S_CH0_CTRL 0x0229 +#define P2S_CH1_CTRL 0x022A +#define TS_IT_STATUS 0x022B +#define TS_IT_MASK 0x022C +#define IN_SEL 0x022D +#define OUT_SEL 0x022E +#define ROUTER_CAM_CH 0x022F +#define ROUTER_CAM_MOD 0x0230 +#define FIFO_CTRL 0x0231 +#define FIFO1_2_STATUS 0x0232 +#define FIFO3_4_STATUS 0x0233 +#define GAP_REMOVER_CH0_CTRL 0x0234 +#define GAP_REMOVER_CH1_CTRL 0x0235 +#define SYNC_RTV_CTRL 0x0236 +#define SYNC_RTV_CH0_SYNC_NB 0x0237 +#define SYNC_RTV_CH0_PATTERN 0x0238 +#define SYNC_RTV_CH1_SYNC_NB 0x0239 +#define SYNC_RTV_CH1_PATTERN 0x023A +#define SYNC_RTV_OFFSET_PATT 0x023B +#define CTRL_FILTER 0x023D +#define PID_EN_FILTER_CH0 0x023E +#define PID_EN_FILTER_CH1 0x023F +#define PID_LSB_FILTER_CH0_0 0x0240 +#define PID_MSB_FILTER_CH0_0 0x0241 +#define PID_LSB_FILTER_CH0_1 0x0242 +#define PID_MSB_FILTER_CH0_1 0x0243 +#define PID_LSB_FILTER_CH0_2 0x0244 +#define PID_MSB_FILTER_CH0_2 0x0245 +#define PID_LSB_FILTER_CH0_3 0x0246 +#define PID_MSB_FILTER_CH0_3 0x0247 +#define PID_LSB_FILTER_CH0_4 0x0248 +#define PID_MSB_FILTER_CH0_4 0x0249 +#define PID_LSB_FILTER_CH0_5 0x024A +#define PID_MSB_FILTER_CH0_5 0x024B +#define PID_LSB_FILTER_CH0_6 0x024C +#define PID_MSB_FILTER_CH0_6 0x024D +#define PID_LSB_FILTER_CH0_7 0x024E +#define PID_MSB_FILTER_CH0_7 0x024F +#define PID_LSB_FILTER_CH1_0 0x0260 +#define PID_MSB_FILTER_CH1_0 0x0261 +#define PID_LSB_FILTER_CH1_1 0x0262 +#define PID_MSB_FILTER_CH1_1 0x0263 +#define PID_LSB_FILTER_CH1_2 0x0264 +#define PID_MSB_FILTER_CH1_2 0x0265 +#define PID_LSB_FILTER_CH1_3 0x0266 +#define PID_MSB_FILTER_CH1_3 0x0267 +#define PID_LSB_FILTER_CH1_4 0x0268 +#define PID_MSB_FILTER_CH1_4 0x0269 +#define PID_LSB_FILTER_CH1_5 0x026A +#define PID_MSB_FILTER_CH1_5 0x026B +#define PID_LSB_FILTER_CH1_6 0x026C +#define PID_MSB_FILTER_CH1_6 0x026D +#define PID_LSB_FILTER_CH1_7 0x026E +#define PID_MSB_FILTER_CH1_7 0x026F +#define PID_OLD_LSB_REMAPPER_0 0x0280 +#define PID_OLD_MSB_REMAPPER_0 0x0281 +#define PID_OLD_LSB_REMAPPER_1 0x0282 +#define PID_OLD_MSB_REMAPPER_1 0x0283 +#define PID_OLD_LSB_REMAPPER_2 0x0284 +#define PID_OLD_MSB_REMAPPER_2 0x0285 +#define PID_OLD_LSB_REMAPPER_3 0x0286 +#define PID_OLD_MSB_REMAPPER_3 0x0287 +#define PID_OLD_LSB_REMAPPER_4 0x0288 +#define PID_OLD_MSB_REMAPPER_4 0x0289 +#define PID_OLD_LSB_REMAPPER_5 0x028A +#define PID_OLD_MSB_REMAPPER_5 0x028B +#define PID_OLD_LSB_REMAPPER_6 0x028C +#define PID_OLD_MSB_REMAPPER_6 0x028D +#define PID_OLD_LSB_REMAPPER_7 0x028E +#define PID_OLD_MSB_REMAPPER_7 0x028F +#define PID_NEW_LSB_REMAPPER_0 0x02A0 +#define PID_NEW_MSB_REMAPPER_0 0x02A1 +#define PID_NEW_LSB_REMAPPER_1 0x02A2 +#define PID_NEW_MSB_REMAPPER_1 0x02A3 +#define PID_NEW_LSB_REMAPPER_2 0x02A4 +#define PID_NEW_MSB_REMAPPER_2 0x02A5 +#define PID_NEW_LSB_REMAPPER_3 0x02A6 +#define PID_NEW_MSB_REMAPPER_3 0x02A7 +#define PID_NEW_LSB_REMAPPER_4 0x02A8 +#define PID_NEW_MSB_REMAPPER_4 0x02A9 +#define PID_NEW_LSB_REMAPPER_5 0x02AA +#define PID_NEW_MSB_REMAPPER_5 0x02AB +#define PID_NEW_LSB_REMAPPER_6 0x02AC +#define PID_NEW_MSB_REMAPPER_6 0x02AD +#define PID_NEW_LSB_REMAPPER_7 0x02AE +#define PID_NEW_MSB_REMAPPER_7 0x02AF +#define MERGER_DIV_MICLK 0x02C0 +#define PID_AND_SYNC_REMAPPER_CTRL 0x02C1 +#define PID_EN_REMAPPER 0x02C2 +#define SYNC_SYMBOL 0x02C3 +#define PID_AND_SYNC_REMAPPER_INV_CTRL 0x02C4 +#define BITRATE_CH0_LSB 0x02C5 +#define BITRATE_CH0_MSB 0x02C6 +#define BITRATE_CH1_LSB 0x02C7 +#define BITRATE_CH1_MSB 0x02C8 +#define STATUS_CLK_SWITCH_0 0x02C9 +#define STATUS_CLK_SWITCH_1 0x02CA +#define RESET_CLK_SWITCH_0 0x02CB +#define RESET_CLK_SWITCH_1 0x02CC +#define PAD_DRVSTR_CTRL 0x02CD +#define PAD_PUPD_CTRL 0x02CE +#define PRE_HEADER_ADDER_CH0_0 0x02D0 +#define PRE_HEADER_ADDER_CH0_1 0x02D1 +#define PRE_HEADER_ADDER_CH0_2 0x02D2 +#define PRE_HEADER_ADDER_CH0_3 0x02D3 +#define PRE_HEADER_ADDER_CH0_4 0x02D4 +#define PRE_HEADER_ADDER_CH0_5 0x02D5 +#define PRE_HEADER_ADDER_CH0_6 0x02D6 +#define PRE_HEADER_ADDER_CH0_7 0x02D7 +#define PRE_HEADER_ADDER_CH0_8 0x02D8 +#define PRE_HEADER_ADDER_CH0_9 0x02D9 +#define PRE_HEADER_ADDER_CH0_10 0x02DA +#define PRE_HEADER_ADDER_CH0_11 0x02DB +#define PRE_HEADER_ADDER_CH1_0 0x02E0 +#define PRE_HEADER_ADDER_CH1_1 0x02E1 +#define PRE_HEADER_ADDER_CH1_2 0x02E2 +#define PRE_HEADER_ADDER_CH1_3 0x02E3 +#define PRE_HEADER_ADDER_CH1_4 0x02E4 +#define PRE_HEADER_ADDER_CH1_5 0x02E5 +#define PRE_HEADER_ADDER_CH1_6 0x02E6 +#define PRE_HEADER_ADDER_CH1_7 0x02E7 +#define PRE_HEADER_ADDER_CH1_8 0x02E8 +#define PRE_HEADER_ADDER_CH1_9 0x02E9 +#define PRE_HEADER_ADDER_CH1_10 0x02EA +#define PRE_HEADER_ADDER_CH1_11 0x02EB +#define PRE_HEADER_ADDER_CTRL 0x02EC +#define PRE_HEADER_ADDER_LEN 0x02ED +#define PRE_HEADER_REMOVER_CTRL 0x02EE +#define FSM_DVB 0x02F0 +#define TS2USB_FSM_DEBUG 0x02F2 +#define TSOUT_PAR_FSM_DEBUG 0x02F3 +#define GAP_REMOVER_FSM_DEBUG 0x02F4 +#define PID_AND_SYNC_REMAPPER_FSM_DEBUG 0x02F5 +#define PRE_HEADER_ADDER_FSM_DEBUG 0x02F6 +#define SYNC_RTV_FSM_DEBUG 0x02F7 +#define CHECK_PHY_CLK 0x0E00 +#define USB_CTRL1 0x0E01 +#define USB_ISO2_out 0x0800 +#define USB_ISO1_out 0x1000 +#define USB_Interrupt_out 0x1E00 +#define USB_Bulk_in 0x1F00 +#define CC2_Buffer_out 0x2000 +#define USB_EP0 0x30C0 +#define CC2_Buffer_in 0x4000 +#define USB_ISO2_in 0x5800 +#define USB_ISO1_in 0x6000 +#define nmb_vector_address_lsb 0xFFFA +#define nmb_vector_address_msb 0xFFFB +#define reset_vector_address_lsb 0xFFFC +#define reset_vector_address_msb 0xFFFD +#define irb_vector_address_lsb 0xFFFE +#define irb_vector_address_msb 0xFFFF + + +#define CIMAX_REG_HDR_SIZE 4 +#define CIMAX_REG_PLD_SIZE 255 +#define CIMAX_CAM_HDR_SIZE 4 +#define CIMAX_CAM_PLD_SIZE 65535 + +#define DEF_LOCK(_l_) struct mutex _l_ + +struct cimax_usb { + struct platform_device *pdev; + struct device_s *dev; + + struct aml_cimax *cimax; + + u8 buf[CIMAX_REG_HDR_SIZE + CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE]; + int buf_size; + + int cam_inserted[2]; +#define IN_INSERTED 0x01 +#define IN_POWERED 0x02 +#define IN_LINKED 0x04 + int cam_data_ready[2]; + + int poll_mode; +#define STOP_MODE 0 +#define POLL_MODE 1 +#define INT_MODE 2 + + int rst_io; + + struct workqueue_struct *workq; + struct delayed_work work; + int work_auto_restart; + int work_cnt; + + struct delayed_work power_work; + int power_work_cnt; + int cam_det; + + DEF_LOCK(lock); +#define lock_init(_usb) mutex_init(&(_usb)->lock) +#define lock_lock(_usb) do {\ + int err = mutex_lock_interruptible(&(_usb)->lock);\ + if (err)\ + return err;\ +} while (0) +#define lock_unlock(_usb) mutex_unlock(&(_usb)->lock) + + u8 *cis; +#define CIS_MAX 512 +}; + +static struct cimax_usb *g_usb; + +MODULE_PARM_DESC(usbdebug, "enable verbose debug messages"); +static int cimax_usb_debug = 1; +module_param_named(usbdebug, cimax_usb_debug, int, 0644); + +MODULE_PARM_DESC(usbpoll_interval, "interval for usb poll"); +static int usb_poll_interval = 100; +module_param_named(usbpoll_interval, usb_poll_interval, int, 0644); + +MODULE_PARM_DESC(usbpoll_mode, "set cimax poll mode, need reset"); +static int cimax_poll_mode = 1; +module_param_named(usbpoll_mode, cimax_poll_mode, int, 0644); + +MODULE_PARM_DESC(usbcam_irq_mode, "set cam irq mode, need reset"); +static int cam_irq_mode; +module_param_named(usbcam_irq_mode, cam_irq_mode, int, 0644); + + +#define CIMAX_REG_READ 0xff +#define CIMAX_REG_READ_OK 0x4c +#define CIMAX_REG_WRITE 0x7f +#define CIMAX_REG_WRITE_OK 0x4d +#define CIMAX_REG_INIT 0x00 +#define CIMAX_REG_INIT_OK 0x4b +#define CIMAX_REG_CMD_ERROR 0x51 + +#define CIMAX_CAM_RESET 0x01 +#define CIMAX_CAM_RESET_OK 0x40 +#define CIMAX_CAM_CIS 0x02 +#define CIMAX_CAM_CIS_OK 0x41 +#define CIMAX_CAM_COR 0x03 +#define CIMAX_CAM_COR_OK 0x42 +#define CIMAX_CAM_NEG 0x04 +#define CIMAX_CAM_NEG_OK 0x43 +#define CIMAX_CAM_WLPDU 0x05 +#define CIMAX_CAM_WLPDU_OK 0x44 +#define CIMAX_CAM_RLPDU 0x06 +#define CIMAX_CAM_RLPDU_OK 0x46 +#define CIMAX_CAM_EVT 0x0d +#define CIMAX_CAM_DET_OK 0x45 +#define CIMAX_CAM_NOCAM 0x49 +#define CIMAX_CAM_ERROR 0x4a +#define CIMAX_CAM_NOEVT 0x55 +#define CIMAX_CAM_DATA_READY 0x4e +#define CIMAX_CAM_WBUSY 0x54 +#define CIMAX_CAM_PENDING 0x56 +#define CIMAX_CAM_REGSTAT 0x0e +#define CIMAX_CAM_REGSTAT_OK 0x57 + + +#define CIMAX_CAM_PKT_CNT_VAL 1 + +#define CIMAX_SLOT_A 0 +#define CIMAX_SLOT_B 1 + +#define CIMAX_CMD_RESP_MASK 0x7f + +#define cimax_to_usb(_c) ((struct cimax_usb *)((_c)->priv)) +#define dev_to_usb(_d) ((struct cimax_usb *)usb_get_drvdata(_d)) + +#define byte_to_u16(_b1, _b2) (((_b1)<<8) | (_b2)) + +#define hdr_cmd_resp(_s) ((_s)->buf[0] & CIMAX_CMD_RESP_MASK) + +#define reg_hdr(_s) ((_s)->buf) +#define reg_addr(_s) byte_to_u16((_s)->buf[1], (_s)->buf[2]) +#define reg_hdr_dat_size(_s) ((_s)->buf[3]) +#define reg_dat(_s) (&((_s)->buf[CIMAX_REG_HDR_SIZE])) + +#define cam_hdr(_s) ((_s)->buf) +#define cam_hdr_slot(_s) (((_s)->buf[0] & 0x80) ? 1 : 0) +#define cam_hdr_pkt_cnt(_s) ((_s)->buf[1]) +#define cam_hdr_dat_size(_s) byte_to_u16((_s)->buf[2], (_s)->buf[3]) +#define cam_dat(_s) (&((_s)->buf[CIMAX_CAM_HDR_SIZE])) + +#define REG_TIMEOUT 500 +#define CAM_TIMEOUT 5000 + +static int aml_cimax_usb_mod_init(void); +static void aml_cimax_usb_mod_exit(void); + +static int cimax_usb_set_loop(struct cimax_usb *usb, int loop); + +static void dump(char *title, u8 *buf, int size) +{ + int i; + pr_info("%s\n", title); + for (i = 0; i < size; i++) { + if (!(i & 0xf)) + pr_info("\n\t"); + pr_info("%02x ", *(buf+i)); + } + pr_info("\n"); +} + +static void perr(char *err, struct cimax_usb *usb) +{ + pr_error("error: %s\n", err); + dump("dump:", usb->buf, 16); +} + +static inline unsigned long get_jiffies(void) +{ + return (unsigned long)(sched_clock()/10000000); +} + +static int cam_usb_cam_detect(struct cimax_usb *usb, int slot, int flag) +{ + usb->cam_inserted[slot] = flag; + pr_inf("detect slot(%d): 0x%x(%s)\n", + slot, usb->cam_inserted[slot], + (!flag) ? "none" : + (flag & IN_LINKED) ? "linked" : + (flag & IN_POWERED) ? "powered" : + (flag & IN_INSERTED) ? "inserted" : + "unknown"); + aml_cimax_slot_state_changed(usb->cimax, slot, + usb->cam_inserted[slot]); + return 0; +} + +static inline void set_usb_cam_ready(struct cimax_usb *usb, int slot) +{ + if (usb->cam_inserted[slot] & IN_POWERED) { + cam_usb_cam_detect(usb, slot, + usb->cam_inserted[slot] | IN_LINKED); + cimax_usb_set_loop(usb, 1);/*set auto-loop*/ + } +} + +static int init_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + hdr[0] = tag; + hdr[1] = (addr>>8) & 0xff; + hdr[2] = addr & 0xff; + hdr[3] = size; + return 0; +} + +static int check_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + return hdr[0] != tag + || hdr[1] != ((addr>>8) & 0xff) + || hdr[2] != (addr & 0xff) + || hdr[3] != size; +} + +static int aml_cimax_usb_read_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + struct device_s *dev = usb->dev; + u8 out[CIMAX_REG_HDR_SIZE]; + int err = 0; + + init_reg_hdr(out, CIMAX_REG_READ, addr, size); + + lock_lock(usb); + + /*pr_dbg("rd %02x:%02x:%02x:%02x\n", + out[0], out[1], + out[2], out[3]);*/ + err = cimax_usb_ci_write(dev, + out, CIMAX_REG_HDR_SIZE, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(usb), CIMAX_REG_READ_OK, addr, size) != 0) { + pr_dbg("rd %02x:%02x:%02x:%02x\n", + out[0], out[1], + out[2], out[3]); + perr("read reg fail.", usb); + err = -EINVAL; + goto end; + } + memcpy(buf, reg_dat(usb), size); +end: + lock_unlock(usb); + return err; +} + +static int aml_cimax_usb_write_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + struct device_s *dev = usb->dev; + u8 out[CIMAX_REG_HDR_SIZE + CIMAX_REG_PLD_SIZE]; + int err = 0; + + init_reg_hdr(out, CIMAX_REG_WRITE, addr, size); + memcpy(&out[CIMAX_REG_HDR_SIZE], buf, size); + + lock_lock(usb); + + pr_dbg("wr %02x:%02x:%02x:%02x\n", + out[0], out[1], + out[2], out[3]); + err = cimax_usb_ci_write(dev, + out, CIMAX_REG_HDR_SIZE + size, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(usb), CIMAX_REG_WRITE_OK, addr, 0) != 0) { + perr("write reg fail.", usb); + err = -EINVAL; + goto end; + } +end: + lock_unlock(usb); + return err; +} + +static inline int init_cam_hdr(u8 *hdr, int cmd, int size) +{ + hdr[0] = cmd; + hdr[1] = CIMAX_CAM_PKT_CNT_VAL; + hdr[2] = (size>>8) & 0xff; + hdr[3] = size & 0xff; + return 0; +} + +static inline int cam_err(struct cimax_usb *usb) +{ + if (hdr_cmd_resp(usb) != CIMAX_CAM_ERROR + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 2) + return 0; + return byte_to_u16(cam_dat(usb)[0], cam_dat(usb)[1]); +} + +static inline char *cam_err_str(int err) +{ +#define CAMERROR_RESET 0x0101 +#define CAMERROR_CIS_BUF 0x0201 +#define CAMERROR_CIS_SIZE 0x0202 +#define CAMERROR_CAM_NOT_ACT 0x0203 +#define CAMERROR_COR_NOT_READY 0x0301 +#define CAMERROR_COR_VAL_CHK 0x0302 +#define CAMERROR_NEG_NO_RESP 0x0401 +#define CAMERROR_NEG_BAD_SIZE 0x0402 +#define CAMERROR_NEG_NOT_READY 0x0403 +#define CAMERROR_LPDU_NOT_AVAIL 0x0601 + struct { int err; char *str; } cam_err_strings[] = { + {CAMERROR_RESET, "reset error, not ready."}, + {CAMERROR_CIS_BUF, "cis error, buffer not allocated."}, + {CAMERROR_CIS_SIZE, "cis error, bad cis size."}, + {CAMERROR_CAM_NOT_ACT, "cam not activated."}, + {CAMERROR_COR_NOT_READY, "cam not ready during write COR."}, + {CAMERROR_COR_VAL_CHK, "COR value check failed."}, + {CAMERROR_NEG_NO_RESP, "cam not responding when negotiation."}, + {CAMERROR_NEG_BAD_SIZE, "cam buf size length != 2."}, + {CAMERROR_NEG_NOT_READY, "cam not ready during negotiation."}, + {CAMERROR_LPDU_NOT_AVAIL, "lpdu not available."} + }; + int i; + for (i = 0; + i < sizeof(cam_err_strings)/sizeof(cam_err_strings[0]); i++) { + if (cam_err_strings[i].err == err) + return cam_err_strings[i].str; + } + return "err unknown."; +} + +static int cimax_usb_access_cam(struct cimax_usb *usb, int slot, + int cmd, u8 *tx, int tx_size, u8 *rx, int rx_size) +{ + struct device_s *dev = usb->dev; + u8 *out = NULL; + int err = 0; + + out = kzalloc(CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE, GFP_KERNEL); + if (!out) { + pr_err("no mem for access cam.\n"); + return -ENOMEM; + } + + cmd |= slot ? 0x80 : 0; + init_cam_hdr(out, cmd, tx_size); + memcpy(&out[CIMAX_CAM_HDR_SIZE], tx, tx_size); + /*dump("access cam:", out, CIMAX_CAM_HDR_SIZE+size);*/ + + lock_lock(usb); + + err = cimax_usb_ci_write(dev, + out, CIMAX_CAM_HDR_SIZE + tx_size, rx, rx_size); + if (err) + goto end; + if (cam_hdr_slot(usb) != slot) { + pr_error("expect slot(%d), but slot(%d)\n", + slot, cam_hdr_slot(usb)); + err = -EINVAL; + goto end; + } + switch (hdr_cmd_resp(usb)) { + case CIMAX_CAM_NOCAM: + pr_dbg("no cam\n"); + err = -ENODEV; + break; + case CIMAX_CAM_ERROR: + pr_error("cam error\n"); + pr_error("err code: 0x%04x(%s)\n", cam_err(usb), + cam_err_str(cam_err(usb))); + err = -ENODEV; + break; + case CIMAX_CAM_WBUSY: + pr_dbg("cam busy\n"); + err = -EBUSY; + break; + case CIMAX_CAM_PENDING: + pr_dbg("cam pending\n"); + err = -EAGAIN; + break; + } +end: + kfree(out); + lock_unlock(usb); + return err; +} + +static int aml_cimax_usb_read_cis(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int err = 0; + int len; + + err = cimax_usb_access_cam(usb, slot, CIMAX_CAM_CIS, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_CIS_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read cis fail.", usb); + err = -EINVAL; + goto end; + } + len = cam_hdr_dat_size(usb); + if (size < len) { + pr_error("cis size too large, expect<%d, but:%d\n", size, len); + perr("cis fail.", usb); + err = -EINVAL; + goto end; + } + memcpy(buf, cam_dat(usb), len); + + if (!usb->cis) + usb->cis = kzalloc((len < 512) ? 512 : len, GFP_KERNEL); + if (usb->cis) + memcpy(usb->cis, cam_dat(usb), len); + +end: + return err; +} +#define CIMAX_CAM_COR_PLD_SIZE 5 +static int aml_cimax_usb_write_cor(struct aml_cimax *cimax, int slot, + int addr, u8 *buf) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int err = 0; + u8 out[CIMAX_CAM_COR_PLD_SIZE + 8]; + int sz = CIMAX_CAM_COR_PLD_SIZE; + + out[0] = addr>>8 & 0xff; + out[1] = addr & 0xff; + out[2] = buf[0]; + out[3] = 0; + out[4] = 0; + + if (!cam_irq_mode) { + out[5] = 0x40;/*cam poll mode*/ + sz++; + } + + err = cimax_usb_access_cam(usb, slot, CIMAX_CAM_COR, + out, sz, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_COR_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 0) { + perr("write cor fail.", usb); + err = -EINVAL; + goto end; + } +end: + return err; +} +#define CIMAX_CAM_NEG_PLD_SIZE 2 +static int aml_cimax_usb_negotiate(struct aml_cimax *cimax, int slot, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + u8 out[CIMAX_CAM_NEG_PLD_SIZE]; + + out[0] = (size>>8) & 0xff; + out[1] = size & 0xff; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_NEG, + out, CIMAX_CAM_NEG_PLD_SIZE, + usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_NEG_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 2) { + perr("negotiate fail.", usb); + ret = -EINVAL; + goto end; + } + ret = byte_to_u16(cam_dat(usb)[0], cam_dat(usb)[1]); + + set_usb_cam_ready(usb, slot); +end: + return ret; +} + +static int aml_cimax_usb_write_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + /*dump("lpdu ->", buf, size);*/ + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_WLPDU, + buf, size, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_WLPDU_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 0) { + perr("write lpdu fail.", usb); + ret = -EINVAL; + goto end; + } + ret = size; +end: + return ret; +} + +static int aml_cimax_usb_read_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_RLPDU, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_RLPDU_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read lpdu fail.", usb); + ret = -EINVAL; + goto end; + } + ret = cam_hdr_dat_size(usb); + memcpy(buf, cam_dat(usb), ret); + + /*dump("lpdu <-", buf, ret);*/ + + usb->cam_data_ready[slot] = 0; +end: + return ret; +} + +static int aml_cimax_usb_read_cam_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + if (cam_irq_mode && usb->cam_data_ready[slot]) + return 0x80; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_REGSTAT, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_REGSTAT_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 1) { + perr("read cam status fail.", usb); + ret = -EINVAL; + goto end; + } + + ret = cam_dat(usb)[0]; +end: + return ret; +} + +static int aml_cimax_usb_slot_reset(struct aml_cimax *cimax, int slot) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + usb->cam_data_ready[slot] = 0; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_RESET, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_RESET_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 0) { + perr("slot reset fail.", usb); + ret = -EINVAL; + goto end; + } +end: + return ret; +} + +static int aml_cimax_usb_cam_reset(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): camreset\n", slot); + return 0; +} + +static int aml_cimax_usb_slot_shutdown(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): shutdown\n", slot); + return 0; +} +static int aml_cimax_usb_slot_ts_enable(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): ts control\n", slot); + return 0; +} +static int aml_cimax_usb_slot_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + if (usb->cam_inserted[slot] & IN_POWERED) { + /*pr_dbg("CA Module present and ready\n");*/ + return DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + } else { + /*pr_error("CA Module not present or not ready\n");*/ + } + return 0; +} + +static int cimax_usb_cam_plugin(struct cimax_usb *usb, int slot, int plugin) +{ + pr_dbg("cam plug: slot(%d) %s\n", + slot, plugin ? "plugged" : "unplugged"); + return aml_cimax_camchanged(usb->cimax, slot, plugin); +} + +static int cimax_usb_set_power(struct cimax_usb *usb, int on) +{ + u8 reg = 0; + int err = 0; + if (!on) { + reg = 0; + err = aml_cimax_usb_read_reg(usb->cimax, MOD_IT_MASK, ®, 1); + if (err) + return err; + reg |= 0x03; + reg &= 0xf3; + + err = aml_cimax_usb_write_reg(usb->cimax, MOD_IT_MASK, ®, 1); + if (err) + return err; + } + reg = on ? 0x3 : 0x0; + return aml_cimax_usb_write_reg(usb->cimax, GPIO0_DATA_OUT, ®, 1); +} + +static int cimax_usb_check_poe(struct cimax_usb *usb, int *on) +{ + u8 reg = 0; + int err = 0; + + *on = 0; + + err = aml_cimax_usb_read_reg(usb->cimax, CFG_1, ®, 1); + if (err) + return err; + if (reg & 0x20) {/*if VCCEN*/ + reg |= 0x08;/*set POE*/ + err = aml_cimax_usb_write_reg(usb->cimax, CFG_1, ®, 1); + if (err) + return err; + err = aml_cimax_usb_read_reg(usb->cimax, CFG_1, ®, 1); + if (err) + return err; + if (reg & 0x08)/*if POE ok*/ + *on = 1; + } + return err; +} + +static void cimax_usb_power_work(struct work_struct *work) +{ + struct cimax_usb *usb = container_of(to_delayed_work(work), + struct cimax_usb, power_work); + int power = 0; + int err = 0; + + usb->power_work_cnt++; + err = cimax_usb_set_power(usb, 1); + if (err) + return; + + err = cimax_usb_check_poe(usb, &power); + if (err) + return; + + if (power) { + return; + } + + schedule_delayed_work(&usb->power_work, usb_poll_interval); +} + +static int cimax_usb_cam_powerctrl(struct cimax_usb *usb, + int slot, int power) +{ + if (slot != 0) + return 0; + +#ifdef DISABLE_POWER_PATCH + if (power) { + cam_usb_cam_detect(usb, slot, + usb->cam_inserted[slot] | IN_POWERED); + cimax_usb_cam_plugin(usb, slot, 1); + } + return 0; +#else + pr_inf("cancel power ctrl previous\n"); + cancel_delayed_work_sync(&usb->power_work); + + if (!power) { + int err = 0; + err = cimax_usb_set_power(usb, 0); + pr_inf("slot[%d] power off\n", slot); + return 0; + } + + INIT_DELAYED_WORK(&usb->power_work, &cimax_usb_power_work); + schedule_delayed_work(&usb->power_work, usb_poll_interval); + pr_inf("slot[%d] power ctrl started\n", slot); +#endif + return 0; +} + +static int cimax_usb_poll(struct cimax_usb *usb) +{ + struct device_s *dev = usb->dev; + int power = 0; + int err = 0; + int slot = 0; + + if (!usb->cam_det) { + for (slot = 0; slot < 2; slot++) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + err = aml_cimax_usb_read_reg(usb->cimax, + addr, ®, 1); + if (reg & 1) { + cam_usb_cam_detect(usb, slot, + (reg & 1) ? IN_INSERTED : 0); + msleep(200); + err = cimax_usb_set_power(usb, (reg & 1)); + err = cimax_usb_check_poe(usb, &power); + pr_inf("slot[%d] power on\n", slot); + msleep(200); + if (power) { + cam_usb_cam_detect(usb, slot, + usb->cam_inserted[slot] | IN_POWERED); + cimax_usb_cam_plugin(usb, slot, 1); + usb->cam_det = 1; + } + } + } + return 0; + } + err = cimax_usb_ci_read_evt(dev, CIMAX_SLOT_A, + usb->buf, sizeof(usb->buf)); + if (err) + goto end; + + switch (hdr_cmd_resp(usb)) { + case CIMAX_CAM_DET_OK: { + int slot = cam_hdr_slot(usb); + int insert = cam_dat(usb)[0]; + if ((!!usb->cam_inserted[slot]) != insert) { + cam_usb_cam_detect(usb, slot, + insert ? IN_INSERTED : 0); + cimax_usb_cam_powerctrl(usb, slot, insert); + } + if (!insert) + usb->cam_det = 0; + } break; + case CIMAX_CAM_DATA_READY: { + int slot = cam_hdr_slot(usb); + usb->cam_data_ready[slot] = 1; + } break; + case CIMAX_CAM_NOEVT: + break; + default: + pr_error("unknown resp:%02x\n", hdr_cmd_resp(usb)); + break; + } +end: + return 0; +} + +static void cimax_usb_poll_work(struct work_struct *work) +{ + struct cimax_usb *usb = + container_of(to_delayed_work(work), struct cimax_usb, work); + usb->work_cnt++; + cimax_usb_poll(usb); + if (usb->work_auto_restart) + queue_delayed_work(usb->workq, &usb->work, usb_poll_interval); +} + +#define CTRL_DISABLE -1 +#define CTRL_STOP 0 +#define CTRL_START 1 + +static inline int cimax_usb_poll_ctrl(struct cimax_usb *usb, int ctrl) +{ + if (ctrl == CTRL_START) { + if (usb->workq) + return 0; + usb->work_auto_restart = 1; + usb->workq = create_singlethread_workqueue("cimax_usb"); + INIT_DELAYED_WORK(&usb->work, &cimax_usb_poll_work); + queue_delayed_work(usb->workq, + &usb->work, usb_poll_interval); + pr_inf("poll started\n"); + } else { + if (!usb->workq) + return 0; + usb->work_auto_restart = 0; + cancel_delayed_work_sync(&usb->work); + destroy_workqueue(usb->workq); + usb->workq = NULL; + pr_inf("poll stopped\n"); + } + return 0; +} + +static int cimax_usb_setup_poll(struct cimax_usb *usb, int poll_mode) +{ + if (poll_mode == usb->poll_mode) + return 0; + switch (poll_mode) { + case POLL_MODE: + cimax_usb_poll_ctrl(usb, CTRL_START); + usb->poll_mode = POLL_MODE; + break; + case STOP_MODE: + if (usb->poll_mode == POLL_MODE) + cimax_usb_poll_ctrl(usb, CTRL_DISABLE); + usb->poll_mode = STOP_MODE; + break; + default: + break; + } + return 0; +} + +static int cimax_usb_hw_reset(struct cimax_usb *usb, int reset_val) +{ + /*trigger reset io*/ + if (usb->rst_io) { + gpio_direction_output(usb->rst_io, reset_val ? 1 : 0); + msleep(50); + gpio_direction_output(usb->rst_io, reset_val ? 0 : 1); + } + return 0; +} + +static int cimax_usb_set_loop(struct cimax_usb *usb, int loop) +{ + int a = usb->cam_inserted[0]; + int b = usb->cam_inserted[1]; + u8 cm[2]; + + pr_inf("set loop: %d\n", loop); + + cm[0] = loop ? (b ? 0x85 : 0x80) : 0x81;/*CH*/ + cm[1] = loop ? (a ? 0x51 : 0x11) : 0x00;/*MOD*/ + + return aml_cimax_usb_write_reg(usb->cimax, ROUTER_CAM_CH, cm, 2); +} + +int cimax_usb_dev_add(struct device_s *dev, int id) +{ + pr_inf("dev add\n"); + if (!g_usb) + return 0; + + id = id; + + cimax_usb_device_open(dev); + cimax_usb_select_interface(dev, 3); + + lock_lock(g_usb); + g_usb->dev = dev; + lock_unlock(g_usb); + + if (0) + { + /* + the cimax's fw do not report cam status + when board power on with cam plugged, + have to check manually here. + */ + int slot = 0; + int err = 0; + for (slot = 0; slot < 2; slot++) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + err = aml_cimax_usb_read_reg(g_usb->cimax, + addr, ®, 1); + cam_usb_cam_detect(g_usb, slot, + (reg & 1) ? IN_INSERTED : 0); + cimax_usb_cam_powerctrl(g_usb, slot, (reg & 1)); + } + } + cimax_usb_set_power(g_usb, 0); + cimax_usb_setup_poll(g_usb, cimax_poll_mode ? POLL_MODE : INT_MODE); + return 0; +} +EXPORT_SYMBOL(cimax_usb_dev_add); + +int cimax_usb_dev_remove(struct device_s *dev, int id) +{ + pr_dbg("dev remove\n"); + if (!g_usb) + return 0; + id = id; + pr_dbg("setup poll -> stop\n"); + cimax_usb_setup_poll(g_usb, STOP_MODE); + pr_dbg("setup poll end\n"); + lock_lock(g_usb); + g_usb->dev = NULL; + lock_unlock(g_usb); + return 0; +} +EXPORT_SYMBOL(cimax_usb_dev_remove); + +static int cimax_usb_get_config_from_dts(struct cimax_usb *usb) +{ + struct device_node *child = NULL; + struct platform_device *pdev = usb->pdev; + struct device_node *np = pdev->dev.of_node; + pr_dbg("fetch cimax usb in dts\n"); + + child = of_get_child_by_name(np, "cimax"); + if (child == NULL) { + pr_error("cimax not found in dts\n"); + return -1; + } + child = of_get_child_by_name(child, "usb"); + if (!child) { + pr_error("usb not found in cimax"); + return -1; + } +/* +dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:usb,2:cimax + cimax { + io_type = <1> //0:spi 1:usb + usb { + rst_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + }; + }; + +}; +*/ + { + int ret = 0; + int gpio = -1; + gpio = of_get_named_gpio_flags(child, "rst-gpios", 0, NULL); + if (gpio != -1) { + ret = gpio_request(gpio, "cimax"); + if (ret < 0) { + pr_error("rst-gpios request fail.\n"); + return ret; + } + usb->rst_io = gpio; + cimax_usb_hw_reset(usb, 1); + pr_dbg("rst: %d\n", usb->rst_io); + } else { + pr_error("rst io got fail, %d\n", gpio); + } + } + return 0; +} + +int aml_cimax_usb_init(struct platform_device *pdev, struct aml_cimax *cimax) +{ + struct cimax_usb *cimax_usb; + + cimax_usb = kzalloc(sizeof(struct cimax_usb), GFP_KERNEL); + if (!cimax_usb) + return -ENOMEM; + + cimax_usb->pdev = pdev; + cimax_usb->cimax = cimax; + cimax_usb_get_config_from_dts(cimax_usb); + + /*init usb_lock*/ + lock_init(cimax_usb); + + /*init cimax used api.*/ +#define WI(_f)\ + cimax->ops._f = aml_cimax_usb_##_f + WI(read_cis); + WI(write_cor); + WI(negotiate); + WI(read_lpdu); + WI(write_lpdu); + WI(read_cam_status); + WI(cam_reset); + WI(slot_reset); + WI(slot_shutdown); + WI(slot_ts_enable); + WI(slot_status); + WI(read_reg); + WI(write_reg); + + cimax->priv = cimax_usb; + + g_usb = cimax_usb; + + aml_cimax_usb_mod_init(); + + cimax_usb_set_cb(cimax_usb_dev_add, cimax_usb_dev_remove); + + return 0; +} +EXPORT_SYMBOL(aml_cimax_usb_init); + +int aml_cimax_usb_exit(struct aml_cimax *cimax) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + + if (!usb) + return -ENODEV; + + aml_cimax_usb_mod_exit(); + + cimax_usb_device_close(usb->dev); + cimax_usb_setup_poll(usb, STOP_MODE); + + if (usb->rst_io) + gpio_free(usb->rst_io); + + kfree(usb->cis); + + kfree(usb); + cimax->priv = NULL; + + g_usb = NULL; + return 0; +} +EXPORT_SYMBOL(aml_cimax_usb_exit); + +static int cimax_usb_reset(struct cimax_usb *usb, int reset_val) +{ + pr_dbg("reset usb:%p, rst:%d\n", usb, usb ? usb->rst_io : -1); + if (!usb) + return -ENODEV; + + pr_inf("cimax usb reset\n"); + + /*notify unplugged*/ + aml_cimax_camchanged(usb->cimax, 0, 0); + aml_cimax_camchanged(usb->cimax, 1, 0); + + if (usb->dev) + cimax_usb_device_close(usb->dev); + + cimax_usb_setup_poll(usb, STOP_MODE); + + usb->cam_inserted[0] = usb->cam_inserted[1] = 0; + usb->cam_data_ready[0] = usb->cam_data_ready[1] = 0; + + cimax_usb_hw_reset(usb, reset_val); + + pr_inf("cimax usb reset end\n"); + return 0; +} + +static ssize_t reset_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret; + ret = sprintf(buf, "echo 1 > %s\n", attr->attr.name); + return ret; +} + +static ssize_t reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret; + int val = 0; + if (!g_usb) + return size; + ret = sscanf(buf, "%i", &val); + if (ret == 1) + ret = cimax_usb_reset(g_usb, val); + return size; +} + +static ssize_t debug_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + if (!g_usb) + return ret; + + ret = sprintf(buf, "poll mode: %d\n", g_usb->poll_mode); + ret += sprintf(buf+ret, "status slot[0]=[%d] slot[1]=[%d]\n", + g_usb->cam_inserted[0], g_usb->cam_inserted[1]); + { + int power = 0; + int err = cimax_usb_check_poe(g_usb, &power); + ret += sprintf(buf+ret, "power slot[0]=[%d] slot[1]=[%d]\n", + err ? -1 : power, 0); + } + ret += sprintf(buf+ret, "data slot[0]=[%d] slot[1]=[%d]\n", + g_usb->cam_data_ready[0], g_usb->cam_data_ready[1]); + ret += sprintf(buf+ret, "work cnt:%d\n", g_usb->work_cnt); + ret += sprintf(buf+ret, "pwr work cnt:%d\n", g_usb->power_work_cnt); + return ret; +} + +static int reg_addr; +static ssize_t addr_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + ret = sprintf(buf, "addr = 0x%04x\n", reg_addr); + return ret; +} + +static ssize_t addr_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (!g_usb) + return size; + if (sscanf(buf, "%i", ®_addr) != 1) + return size; + return size; +} + +static ssize_t reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 reg_val = 0; + struct aml_cimax *cimax = NULL; + + if (!g_usb) + return ret; + + cimax = g_usb->cimax; + ret = aml_cimax_usb_read_reg(cimax, reg_addr, ®_val, 1); + if (ret) + ret = sprintf(buf, "read fail, err=%d\n", ret); + else + ret = sprintf(buf, "reg[0x%04x] = 0x%02x\n", reg_addr, reg_val); + return ret; +} + +static ssize_t reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + struct aml_cimax *cimax = NULL; + int val = 0; + u8 reg_val = 0; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &val) != 1) + return size; + reg_val = val; + cimax = g_usb->cimax; + ret = aml_cimax_usb_write_reg(cimax, reg_addr, ®_val, 1); + if (ret) + return ret; + return size; +} + +static int cis_mode; /*0:hex 1:binary*/ +static ssize_t cis_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + if (!g_usb || !g_usb->cis) + return ret; + + if (cis_mode == 0) { + int i; + for (i = 0; i < CIS_MAX; i++) { + if (i && !(i & 0xf)) + ret += sprintf(buf+ret, "\n"); + ret += sprintf(buf+ret, "%02X ", g_usb->cis[i]); + } + ret += sprintf(buf+ret, "\n"); + return ret; + } else { + memcpy(buf, g_usb->cis, CIS_MAX); + return CIS_MAX; + } + return ret; +} + +static ssize_t cis_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (size >= 3 + && !memcmp(buf, "bin", 3)) + cis_mode = 1; + else + cis_mode = 0; + return size; +} + +static ssize_t ts_rate_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 lsb = 0, msb = 0, plen = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_usb) + return ret; + + cimax = g_usb->cimax; + err = aml_cimax_usb_read_reg(cimax, PCK_LENGTH, &plen, 1); + err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH0_LSB, &lsb, 1); + err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH0_MSB, &msb, 1); + if (err) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else if (!byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "rate[0] = 0 Kbps\n"); + else + ret += sprintf(buf+ret, "rate[0] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + if (err) + return ret; + + err = aml_cimax_usb_read_reg(cimax, BITRATE_CH1_LSB, &lsb, 1); + err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH1_MSB, &msb, 1); + if (err) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else if (!byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "rate[1] = 0 Kbps\n"); + else + ret += sprintf(buf+ret, "rate[1] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + return ret; +} + +static ssize_t loop_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 ch = 0, mod = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_usb) + return ret; + + cimax = g_usb->cimax; + err = aml_cimax_usb_read_reg(cimax, ROUTER_CAM_CH, &ch, 1); + err |= aml_cimax_usb_read_reg(cimax, ROUTER_CAM_MOD, &mod, 1); + if (err) { + ret = sprintf(buf, "read fail, err=%d\n", err); + return ret; + } + ret += sprintf(buf + ret, "OUT-0 <= "); + switch (ch & 0x0f) { + case 0x0: + ret += sprintf(buf + ret, "CAM-A"); break; + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + case 0x8: + ret += sprintf(buf + ret, "NONE"); break; + default: + ret += sprintf(buf + ret, "UNKNOWN"); break; + } + ret += sprintf(buf + ret, "\nCAM-A <= "); + switch (mod & 0x07) { + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + default: + ret += sprintf(buf + ret, "NONE"); break; + } + ret += sprintf(buf + ret, "\n"); + + return ret; +} + +static ssize_t loop_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int loop = 0; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &loop) == 1) + cimax_usb_set_loop(g_usb, loop); + return size; +} + +static ssize_t slot_reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + pr_dbg("reset slot %d\n", slot); + cimax = g_usb->cimax; + err = aml_cimax_usb_slot_reset(cimax, slot); + } + } + return size; +} + +static ssize_t detect_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + cimax = g_usb->cimax; + err = aml_cimax_usb_read_reg(cimax, addr, ®, 1); + cam_usb_cam_detect(g_usb, slot, + (reg & 1) ? IN_INSERTED : 0); + cimax_usb_cam_powerctrl(g_usb, slot, (reg & 1)); + } + } + return size; +} + + +static struct class_attribute cimax_usb_class_attrs[] = { + __ATTR_RW(reset), + __ATTR_RO(debug), + __ATTR_RW(addr), + __ATTR_RW(reg), + __ATTR_RW(cis), + __ATTR_RO(ts_rate), + __ATTR_RW(loop), + __ATTR_WO(slot_reset), + __ATTR_WO(detect), + __ATTR_NULL +}; + +static struct class cimax_usb_class = { + .name = "cimax_usb", + .class_attrs = cimax_usb_class_attrs, +}; + +static int aml_cimax_usb_mod_init(void) +{ + int ret; + pr_dbg("Amlogic CIMAX USB Init\n"); + ret = class_register(&cimax_usb_class); + return 0; +} + +static void aml_cimax_usb_mod_exit(void) +{ + pr_dbg("Amlogic CIMAX USB Exit\n"); + class_unregister(&cimax_usb_class); +} + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h new file mode 100644 index 000000000000..471d2da5af56 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h @@ -0,0 +1,20 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef _AML_CIMAX_USB_H_ +#define _AML_CIMAX_USB_H_ + +#include +#include "aml_cimax.h" + +int aml_cimax_usb_init(struct platform_device *pdev, struct aml_cimax *ci); +int aml_cimax_usb_exit(struct aml_cimax *ci); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h new file mode 100644 index 000000000000..aec694c66a3c --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h @@ -0,0 +1,22 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef _CIMAX_USB_DEV_H_ +#define _CIMAX_USB_DEV_H_ + +#if 0 +__attribute__ ((weak)) +int cimax_usb_dev_add(struct device_s *device, int id); +__attribute__ ((weak)) +int cimax_usb_dev_remove(struct device_s *device, int id); +#endif + +#endif + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c new file mode 100644 index 000000000000..e8fb0eec9064 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c @@ -0,0 +1,1910 @@ +/* + * dvb_ca.c: generic DVB functions for EN50221 CAM CIMAX interfaces + * + * Parts of this file were based on sources as follows: + * + * based on code: + * + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_ca_en50221_cimax.h" +#include "dvb_ringbuffer.h" + +static int dvb_ca_en50221_debug = 1; + +module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); +MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); + +#define HOST_LINK_BUF_SIZE 0x1000 + +static int dvb_ca_en50221_link_size = HOST_LINK_BUF_SIZE; +module_param_named(link_size, dvb_ca_en50221_link_size, int, 0644); +MODULE_PARM_DESC(link_size, "debug only, no more than 0x1000"); + + +#define dprintk(args...)\ + do {\ + if (dvb_ca_en50221_debug)\ + printk(args);\ + } while (0) +#define pr_error(fmt, args...) printk("CA EN50211: " fmt, ## args) + +#define INIT_TIMEOUT_SECS 40 + + +#define RX_BUFFER_SIZE 65535 + +#define MAX_RX_PACKETS_PER_ITERATION 10 + +#define CTRLIF_DATA 0 +#define CTRLIF_COMMAND 1 +#define CTRLIF_STATUS 1 +#define CTRLIF_SIZE_LOW 2 +#define CTRLIF_SIZE_HIGH 3 + +#define CMDREG_HC 1 /* Host control */ +#define CMDREG_SW 2 /* Size write */ +#define CMDREG_SR 4 /* Size read */ +#define CMDREG_RS 8 /* Reset interface */ +#define CMDREG_FRIE 0x40 /* Enable FR interrupt */ +#define CMDREG_DAIE 0x80 /* Enable DA interrupt */ +#define IRQEN (CMDREG_DAIE) + +#define STATUSREG_RE 1 /* read error */ +#define STATUSREG_WE 2 /* write error */ +#define STATUSREG_FR 0x40 /* module free */ +#define STATUSREG_DA 0x80 /* data available */ +#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE)/* general transfer error */ + + +#define DVB_CA_SLOTSTATE_NONE 0 +#define DVB_CA_SLOTSTATE_UNINITIALISED 1 +#define DVB_CA_SLOTSTATE_RUNNING 2 +#define DVB_CA_SLOTSTATE_INVALID 3 +#define DVB_CA_SLOTSTATE_WAITREADY 4 +#define DVB_CA_SLOTSTATE_VALIDATE 5 +#define DVB_CA_SLOTSTATE_WAITFR 6 +#define DVB_CA_SLOTSTATE_LINKINIT 7 +#define DVB_CA_SLOTSTATE_WAITLINKINIT 8 + +#define MAX_CIS_SIZE 512 + +/* Information on a CA slot */ +struct dvb_ca_slot { + + /* current state of the CAM */ + int slot_state; + + /* mutex used for serializing access to one CI slot */ + struct mutex slot_lock; + + /* Number of CAMCHANGES that have occurred since last processing */ + atomic_t camchange_count; + + /* Type of last CAMCHANGE */ + int camchange_type; + + /* base address of CAM config */ + u32 config_base; + + /* value to write into Config Control register */ + u8 config_option; + + /* if 1, the CAM supports DA IRQs */ + u8 da_irq_supported:1; + + /* size of the buffer to use when talking to the CAM */ + int link_buf_size; + + /* buffer for incoming packets */ + struct dvb_ringbuffer rx_buffer; + + /* timer used during various states of the slot */ + unsigned long timeout; +}; + +/* Private CA-interface information */ +struct dvb_ca_private { + + /* pointer back to the public data structure */ + struct dvb_ca_en50221_cimax *pub; + + /* the DVB device */ + struct dvb_device *dvbdev; + + /* Flags describing the interface (DVB_CA_FLAG_*) */ + u32 flags; + + /* number of slots supported by this CA interface */ + unsigned int slot_count; + + /* information on each slot */ + struct dvb_ca_slot *slot_info; + + /* wait queues for read() and write() operations */ + wait_queue_head_t wait_queue; + + /* PID of the monitoring thread */ + struct task_struct *thread; + + /* Flag indicating if the CA device is open */ + unsigned int open:1; + + /* Flag indicating the thread should wake up now */ + unsigned int wakeup:1; + + /* Delay the main thread should use */ + unsigned long delay; + + /* Slot to start looking for data + to read from in the next user-space read operation */ + int next_read_slot; + + /* mutex serializing ioctls */ + struct mutex ioctl_mutex; + + /*two bufs for read/write*/ + u8 *rbuf; + u8 *wbuf; +}; + +static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); +static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, + int slot, u8 *ebuf, int ecount); +static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, + int slot, u8 *ebuf, int ecount); + + +/** + * Safely find needle in haystack. + * + * @param haystack Buffer to look in. + * @param hlen Number of bytes in haystack. + * @param needle Buffer to find. + * @param nlen Number of bytes in needle. + * @return Pointer into haystack needle was found at, or NULL if not found. + */ +static char *findstr(char *haystack, int hlen, char *needle, int nlen) +{ + int i; + + if (hlen < nlen) + return NULL; + + for (i = 0; i <= hlen - nlen; i++) { + if (!strncmp(haystack + i, needle, nlen)) + return haystack + i; + } + + return NULL; +} + + + +/* ************************************************************************** */ +/* EN50221 physical interface functions */ + + +/** + * Check CAM status. + */ +static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) +{ + int slot_status; + int cam_present; + int cam_changed; + + /* IRQ mode */ + if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) + return atomic_read(&ca->slot_info[slot].camchange_count) != 0; + + /* poll mode */ + slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); + + cam_present = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0; + cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0; + if (!cam_changed) { + int cam_present_old = + (ca->slot_info[slot].slot_state + != DVB_CA_SLOTSTATE_NONE); + cam_changed = (cam_present != cam_present_old); + } + + if (cam_changed) { + if (!cam_present) { + ca->slot_info[slot].camchange_type = + DVB_CA_EN50221_CAMCHANGE_REMOVED; + } else { + ca->slot_info[slot].camchange_type = + DVB_CA_EN50221_CAMCHANGE_INSERTED; + } + atomic_set(&ca->slot_info[slot].camchange_count, 1); + } else { + if ((ca->slot_info[slot].slot_state + == DVB_CA_SLOTSTATE_WAITREADY) && + (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) { + /* move to validate state if reset is completed */ + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_VALIDATE; + } + } + return cam_changed; +} + + +/** + * Initialise the link layer connection to a CAM. + * + * @param ca CA instance. + * @param slot Slot id. + * + * @return 0 on success, nonzero on failure. + */ +static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) +{ + int ret; + dprintk("%s\n", __func__); + + /* we'll be determining these during this function */ + ca->slot_info[slot].da_irq_supported = 0; + + /* set the host link buffer size temporarily. + it will be overwritten with the real negotiated size later. */ + ca->slot_info[slot].link_buf_size = dvb_ca_en50221_link_size; + dprintk("negotiate: host(%i)\n", ca->slot_info[slot].link_buf_size); + + ret = ca->pub->negotiate(ca->pub, + slot, ca->slot_info[slot].link_buf_size); + if (ret <= 0) + return ret; + + ca->slot_info[slot].link_buf_size = ret; + dprintk("Chosen link buffer size of %i\n", ret); + + /* success */ + return 0; +} + +/** + * Read a tuple from attribute memory. + * + * @param ca CA instance. + * @param slot Slot id. + * @param cis CIS data + * @param address Address to read from. Updated. + * @param tupleType Tuple id byte. Updated. + * @param tupleLength Tuple length. Updated. + * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. + * + * @return 0 on success, nonzero on error. + */ +static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, + int slot, u8 *cis, + int *address, int *tupleType, int *tupleLength, u8 *tuple) +{ + int i; + int _tupleType; + int _tupleLength; + int _address = *address; + + /* grab the next tuple length and type */ + _tupleType = cis[_address]; + if (_tupleType < 0) + return _tupleType; + if (_tupleType == 0xff) { + dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); + *address += 1; + *tupleType = _tupleType; + *tupleLength = 0; + return 0; + } + _tupleLength = cis[_address + 1]; + if (_tupleLength < 0) + return _tupleLength; + _address += 2; + + dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); + + /* read in the whole tuple */ + for (i = 0; i < _tupleLength; i++) { + tuple[i] = cis[_address + (i)]; + dprintk(" 0x%02x: 0x%02x %c\n", + i, tuple[i] & 0xff, + ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); + } + _address += (_tupleLength); + + /* success */ + *tupleType = _tupleType; + *tupleLength = _tupleLength; + *address = _address; + return 0; +} + + +/** + * Parse attribute memory of a CAM module, extracting Config register, + * and checking it is a DVB CAM module. + * + * @param ca CA instance. + * @param slot Slot id. + * + * @return 0 on success, <0 on failure. + */ +static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) +{ + int address = 0; + int tupleLength; + int tupleType; + u8 tuple[257]; + char *dvb_str; + int rasz; + int status; + int got_cftableentry = 0; + int end_chain = 0; + int i; + u16 manfid = 0; + u16 devid = 0; + u8 cis[MAX_CIS_SIZE]; + + status = ca->pub->read_cis(ca->pub, slot, cis, MAX_CIS_SIZE); + if (status != 0) + return -EINVAL; + + /* CISTPL_DEVICE_0A */ + status = + dvb_ca_en50221_read_tuple(ca, slot, cis, &address, + &tupleType, &tupleLength, tuple); + if (status < 0) { + pr_error("read status error\r\n"); + return status; + } + if (tupleType != 0x1D) { + pr_error("read tupleType error [0x%x]\r\n", tupleType); + return -EINVAL; + } + + + + /* CISTPL_DEVICE_0C */ + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, + &tupleType, &tupleLength, tuple); + + if (status < 0) { + pr_error("read read cis error\r\n"); + return -EINVAL; + } + if (tupleType != 0x1C) { + pr_error("read read cis type error\r\n"); + return -EINVAL; + } + + + + /* CISTPL_VERS_1 */ + status = + dvb_ca_en50221_read_tuple(ca, slot, cis, + &address, &tupleType, &tupleLength, tuple); + if (status < 0) { + pr_error("read read cis version error\r\n"); + return status; + } + if (tupleType != 0x15) { + pr_error("read read cis version type error\r\n"); + return -EINVAL; + } + + + + /* CISTPL_MANFID */ + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, &tupleType, + &tupleLength, tuple); + if (status < 0) { + pr_error("read read cis manfid error\r\n"); + return status; + } + if (tupleType != 0x20) { + pr_error("read read cis manfid type error\r\n"); + return -EINVAL; + } + if (tupleLength != 4) { + pr_error("read read cis manfid len error\r\n"); + return -EINVAL; + } + manfid = (tuple[1] << 8) | tuple[0]; + devid = (tuple[3] << 8) | tuple[2]; + + + + /* CISTPL_CONFIG */ + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, &tupleType, + &tupleLength, tuple); + if (status < 0) { + pr_error("read read cis config error\r\n"); + return status; + } + if (tupleType != 0x1A) { + pr_error("read read cis config type error\r\n"); + return -EINVAL; + } + if (tupleLength < 3) { + pr_error("read read cis config len error\r\n"); + return -EINVAL; + } + + /* extract the configbase */ + rasz = tuple[0] & 3; + if (tupleLength < (3 + rasz + 14)) { + pr_error("read extract the configbase error\r\n"); + return -EINVAL; + } + ca->slot_info[slot].config_base = 0; + for (i = 0; i < rasz + 1; i++) + ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i)); + + /* check it contains the correct DVB string */ + dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8); + if (dvb_str == NULL) { + pr_error("find dvb str DVB_CI_V error\r\n"); + return -EINVAL; + } + if (tupleLength < ((dvb_str - (char *) tuple) + 12)) { + pr_error("find dvb str DVB_CI_V len error\r\n"); + return -EINVAL; + } + + /* is it a version we support? */ + if (strncmp(dvb_str + 8, "1.00", 4)) { + pr_info("dvb_ca adapter %d: ", ca->dvbdev->adapter->num); + pr_info("Unsupported DVB CAM module version %c%c%c%c\n", + dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); + return -EINVAL; + } + + /* process the CFTABLE_ENTRY tuples, and any after those */ + while ((!end_chain) && (address < 0x1000)) { + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, + &tupleType, &tupleLength, tuple); + if (status < 0) { + pr_error("process tuples error\r\n"); + return status; + } + + switch (tupleType) { + case 0x1B: /* CISTPL_CFTABLE_ENTRY */ + if (tupleLength < (2 + 11 + 17)) + break; + + /* if we've already parsed one, just use it */ + if (got_cftableentry) + break; + + /* get the config option */ + ca->slot_info[slot].config_option = tuple[0] & 0x3f; + + /* OK, check it contains the correct strings */ + if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) + == NULL) + || (findstr((char *)tuple, + tupleLength, "DVB_CI_MODULE", 13) + == NULL)) { + break; + } + got_cftableentry = 1; + break; + + case 0x14: /* CISTPL_NO_LINK */ + break; + + case 0xFF: /* CISTPL_END */ + end_chain = 1; + break; + + default: /* Unknown tuple type + -just skip this tuple and move to the next one */ + dprintk("dvb_ca: Skipping unknown tuple type:0x%x", + tupleType); + dprintk(" length:0x%x\n", tupleLength); + break; + } + } + + if ((address > 0x1000) || (!got_cftableentry)) { + pr_error("got_cftableentry :%d\r\n", got_cftableentry); + return -EINVAL; + } + + dprintk("Valid DVB CAM detected MANID:%x DEVID:%x", manfid, devid); + dprintk(" CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", + ca->slot_info[slot].config_base, + ca->slot_info[slot].config_option); + + /* success! */ + return 0; +} + + +/** + * Set CAM's configoption correctly. + * + * @param ca CA instance. + * @param slot Slot containing the CAM. + */ +static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) +{ + int configoption; + + dprintk("%s\n", __func__); + + /* set the config option */ + ca->pub->write_cor(ca->pub, slot, + ca->slot_info[slot].config_base, + &ca->slot_info[slot].config_option); + + configoption = ca->slot_info[slot].config_option; + dprintk("Set configoption 0x%x, base 0x%x\n", + ca->slot_info[slot].config_option, + ca->slot_info[slot].config_base); + + /* fine! */ + return 0; + +} + + +/** + * This function talks to an EN50221 CAM control interface. It reads a buffer of + * data from the CAM. The data can either be stored in a supplied buffer, or + * automatically be added to the slot's rx_buffer. + * + * @param ca CA instance. + * @param slot Slot to read from. + * @param ebuf If non-NULL, the data will be written to this buffer. If NULL, + * the data will be added into the buffering system as a normal fragment. + * @param ecount Size of ebuf. Ignored if ebuf is NULL. + * + * @return Number of bytes read, or < 0 on error + */ +static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, + int slot, u8 *ebuf, int ecount) +{ + int bytes_read; + int status; + u8 *buf = ca->rbuf; + + /* dprintk("%s\n", __func__); */ + + /* check if we have space for a link buf in the rx_buffer */ + if (ebuf == NULL) { + int buf_free; + + if (ca->slot_info[slot].rx_buffer.data == NULL) { + status = -EIO; + goto exit; + } + buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); + + if (buf_free < (ca->slot_info[slot].link_buf_size + + DVB_RINGBUFFER_PKTHDRSIZE)) { + status = -EAGAIN; + goto exit; + } + } + + /* check if there is data available */ + status = ca->pub->read_cam_status(ca->pub, slot); + if (status < 0) + goto exit; + if (!(status & STATUSREG_DA)) { + /* no data */ + status = 0; + goto exit; + } + + /* read the amount of data */ + status = ca->pub->read_lpdu(ca->pub, + slot, buf, dvb_ca_en50221_link_size); + if (status < 0) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + + bytes_read = status; + + /* check it will fit */ + if (ebuf == NULL) { + if (bytes_read > ca->slot_info[slot].link_buf_size) { + pr_error("dvb_ca adapter %d:", + ca->dvbdev->adapter->num); + pr_error(" CAM tried to send a buffer larger "); + pr_error("than the link buffer size(%i > %i)!\n", + bytes_read, ca->slot_info[slot].link_buf_size); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + if (bytes_read < 2) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("CAM sent a buffer"); + pr_error("that was less than 2B!\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + } else { + if (bytes_read > ecount) { + pr_error("dvb_ca adapter %d:", + ca->dvbdev->adapter->num); + pr_error(" CAM tried to send a buffer larger"); + pr_error(" than the ecount size!\n"); + status = -EIO; + goto exit; + } + } + + /* OK, add it to the receive buffer, + or copy into external buffer if supplied */ + if (ebuf == NULL) { + if (ca->slot_info[slot].rx_buffer.data == NULL) { + status = -EIO; + goto exit; + } + dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, + buf, bytes_read); + } else { + memcpy(ebuf, buf, bytes_read); + } + + /* wake up readers when a last_fragment is received */ + if ((buf[1] & 0x80) == 0x00) + wake_up_interruptible(&ca->wait_queue); + status = bytes_read; + +exit: + return status; +} + + +/** + * This function talks to an EN50221 CAM control interface. + * It writes a buffer of data + * to a CAM. + * + * @param ca CA instance. + * @param slot Slot to write to. + * @param ebuf The data in this buffer + * is treated as a complete link-level packet to be written. + * @param count Size of ebuf. + * + * @return Number of bytes written, or < 0 on error. + */ +static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, + int slot, u8 *buf, int bytes_write) +{ + int status; + + /* dprintk("%s\n", __func__); */ + + /* sanity check */ + if (bytes_write > ca->slot_info[slot].link_buf_size) + return -EINVAL; + + /* it is possible we are dealing with a single buffer implementation, + thus if there is data available for read or if there is even a read + already in progress, we do nothing but awake the kernel thread to + process the data if necessary. */ + status = ca->pub->read_cam_status(ca->pub, slot); + if (status < 0) + return status; + if (status & (STATUSREG_DA | STATUSREG_RE)) { + if (status & STATUSREG_DA) + dvb_ca_en50221_thread_wakeup(ca); + status = -EAGAIN; + return status; + } + + if (!(status & STATUSREG_FR)) { + status = -EAGAIN; + return status; + } + + status = ca->pub->write_lpdu(ca->pub, slot, buf, bytes_write); + if (status < 0) { + if (status == -EBUSY) { + status = -EAGAIN; + return status; + } else { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + return status; + } + } + + status = bytes_write; + + return status; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_camchange_irq); + + + +/* ************************************************************************** */ +/* EN50221 higher level functions */ + + +/** + * A CAM has been removed => shut it down. + * + * @param ca CA instance. + * @param slot Slot to shut down. + */ +static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) +{ + dprintk("%s\n", __func__); + + ca->pub->slot_shutdown(ca->pub, slot); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; + + /* need to wake up all processes to check if they're now + trying to write to a defunct CAM */ + wake_up_interruptible(&ca->wait_queue); + + dprintk("Slot %i shutdown\n", slot); + + /* success */ + return 0; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_camready_irq); + + +/** + * A CAMCHANGE IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + * @param change_type One of the DVB_CA_CAMCHANGE_* values. + */ +void dvb_ca_en50221_cimax_camchange_irq(struct dvb_ca_en50221_cimax *pubca, + int slot, int change_type) +{ + struct dvb_ca_private *ca = pubca->private; + + dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type); + + switch (change_type) { + case DVB_CA_EN50221_CAMCHANGE_REMOVED: + case DVB_CA_EN50221_CAMCHANGE_INSERTED: + break; + + default: + return; + } + + ca->slot_info[slot].camchange_type = change_type; + atomic_inc(&ca->slot_info[slot].camchange_count); + dvb_ca_en50221_thread_wakeup(ca); +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_frda_irq); + + +/** + * A CAMREADY IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_camready_irq(struct dvb_ca_en50221_cimax *pubca, + int slot) +{ + struct dvb_ca_private *ca = pubca->private; + + dprintk("CAMREADY IRQ slot:%i\n", slot); + + if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; + dvb_ca_en50221_thread_wakeup(ca); + } +} + + +/** + * An FR or DA IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_frda_irq(struct dvb_ca_en50221_cimax *pubca, + int slot) +{ + struct dvb_ca_private *ca = pubca->private; + int flags; + + dprintk("FR/DA IRQ slot:%i\n", slot); + + switch (ca->slot_info[slot].slot_state) { + case DVB_CA_SLOTSTATE_LINKINIT: + flags = ca->pub->get_capbility(pubca, slot); + if (flags & DVB_CA_EN50221_CAP_IRQ) { + dprintk("CAM supports DA IRQ\n"); + ca->slot_info[slot].da_irq_supported = 1; + } + break; + + case DVB_CA_SLOTSTATE_RUNNING: + if (ca->open) + dvb_ca_en50221_thread_wakeup(ca); + break; + } +} + + + +/* ************************************************************************** */ +/* EN50221 thread functions */ + +/** + * Wake up the DVB CA thread + * + * @param ca CA instance. + */ +static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) +{ + + dprintk("%s\n", __func__); + + ca->wakeup = 1; + mb(); /*original*/ + wake_up_process(ca->thread); +} + +/** + * Update the delay used by the thread. + * + * @param ca CA instance. + */ +static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) +{ + int delay; + int curdelay = 100000000; + int slot; + + /* Beware of too high polling frequency, because one polling + * call might take several hundred milliseconds until timeout! + */ + for (slot = 0; slot < ca->slot_count; slot++) { + switch (ca->slot_info[slot].slot_state) { + default: + case DVB_CA_SLOTSTATE_NONE: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ * 5; /* 5s */ + break; + case DVB_CA_SLOTSTATE_INVALID: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ / 10; /* 100ms */ + break; + + case DVB_CA_SLOTSTATE_UNINITIALISED: + case DVB_CA_SLOTSTATE_WAITREADY: + case DVB_CA_SLOTSTATE_VALIDATE: + case DVB_CA_SLOTSTATE_WAITFR: + case DVB_CA_SLOTSTATE_LINKINIT: + delay = HZ / 10; /* 100ms */ + break; + case DVB_CA_SLOTSTATE_WAITLINKINIT: + delay = HZ * 2; + break; + + case DVB_CA_SLOTSTATE_RUNNING: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ / 10; /* 100ms */ + if (ca->open) { + if ((!ca->slot_info[slot].da_irq_supported) || + (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) + delay = HZ / 10; /* 100ms */ + } + break; + } + + if (delay < curdelay) + curdelay = delay; + } + + ca->delay = curdelay; +} + +static int dvb_ca_en50221_slot_process(struct dvb_ca_private *ca, int slot) +{ + int flags; + int status; + int pktcount; + void *rxbuf; + + mutex_lock(&ca->slot_info[slot].slot_lock); + + /*check the cam status + deal with CAMCHANGEs*/ + while (dvb_ca_en50221_check_camstatus(ca, slot)) { + /* clear down an old CI slot if necessary */ + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) + dvb_ca_en50221_slot_shutdown(ca, slot); + + /* if a CAM is NOW present, initialise it */ + if (ca->slot_info[slot].camchange_type + == DVB_CA_EN50221_CAMCHANGE_INSERTED) + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_UNINITIALISED; + + /* we've handled one CAMCHANGE */ + dvb_ca_en50221_thread_update_delay(ca); + atomic_dec(&ca->slot_info[slot].camchange_count); + } + + /* CAM state machine */ + switch (ca->slot_info[slot].slot_state) { + case DVB_CA_SLOTSTATE_NONE: + case DVB_CA_SLOTSTATE_INVALID: + /* no action needed */ + break; + + case DVB_CA_SLOTSTATE_UNINITIALISED: + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY; + ca->pub->slot_reset(ca->pub, slot); + ca->slot_info[slot].timeout = jiffies + + (INIT_TIMEOUT_SECS * HZ); + break; + + case DVB_CA_SLOTSTATE_WAITREADY: + if (time_after(jiffies, ca->slot_info[slot].timeout)) { + dprintk("%d: PC card did not respond\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + /* no other action needed; will automatically + * change state when ready + */ + break; + + case DVB_CA_SLOTSTATE_VALIDATE: + if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { + /* we need this extra check + for annoying interfaces like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + && (ca->pub->poll_slot_status)) { + status = ca->pub->poll_slot_status(ca->pub, + slot, 0); + if (!(status + & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_NONE; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + } + dprintk(" %d: Invalid PC card inserted :(\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { + dprintk("%d: Unable initialise CAM:(\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + if (ca->pub->cam_reset(ca->pub, slot) != 0) { + dprintk("%d: Unable to reset CAM IF\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + dprintk("DVB CAM validated successfully\n"); + + ca->slot_info[slot].timeout = + jiffies + (INIT_TIMEOUT_SECS * HZ); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR; + ca->wakeup = 1; + break; + + case DVB_CA_SLOTSTATE_WAITFR: + if (time_after(jiffies, ca->slot_info[slot].timeout)) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("DVB CAM did not respond :(\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + /*flags = ca->pub->read_cam_status(ca->pub, slot);*/ + flags = STATUSREG_FR; + if (flags & STATUSREG_FR) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + ca->wakeup = 1; + } + break; + + case DVB_CA_SLOTSTATE_WAITLINKINIT: + if (time_after(jiffies, ca->slot_info[slot].timeout)) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("DVB CAM link initialisation failed :(\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + case DVB_CA_SLOTSTATE_LINKINIT: + if (dvb_ca_en50221_link_init(ca, slot) != 0) { + /* we need this extra check for annoying interfaces + like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + && (ca->pub->poll_slot_status)) { + status = ca->pub->poll_slot_status(ca->pub, + slot, 0); + if (!(status + & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_NONE; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + } + + ca->slot_info[slot].timeout = + jiffies + (INIT_TIMEOUT_SECS * HZ); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_WAITLINKINIT; + ca->wakeup = 1; + break; + } + + if (ca->slot_info[slot].rx_buffer.data == NULL) { + rxbuf = vmalloc(RX_BUFFER_SIZE); + if (rxbuf == NULL) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("Unable to allocate CAM rx buffer\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, + rxbuf, RX_BUFFER_SIZE); + } + + ca->pub->slot_ts_enable(ca->pub, slot); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; + dvb_ca_en50221_thread_update_delay(ca); + dprintk("%d: DVB CAM Initialised successfully\n", + ca->dvbdev->adapter->num); + break; + + case DVB_CA_SLOTSTATE_RUNNING: + if (!ca->open) + break; + + pktcount = 0; + while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) + > 0) { + if (!ca->open) + break; + + /* if a CAMCHANGE occurred at some point, + do not do any more processing of this slot */ + if (dvb_ca_en50221_check_camstatus(ca, slot)) { + /* we dont want to sleep on the next iteration + so we can handle the cam change*/ + ca->wakeup = 1; + break; + } + + /* check if we've hit our limit this time */ + if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { + /*dont sleep; + there is likely to be more data to read*/ + ca->wakeup = 1; + break; + } + } + break; + } + + mutex_unlock(&ca->slot_info[slot].slot_lock); + return 0; +} + + +/** + * Kernel thread which monitors CA slots for CAM changes, + * and performs data transfers. + */ +static int dvb_ca_en50221_thread(void *data) +{ + struct dvb_ca_private *ca = data; + int slot; + + dprintk(" %s\n", __func__); + /* choose the correct initial delay */ + dvb_ca_en50221_thread_update_delay(ca); + + /* main loop */ + while (!kthread_should_stop()) { + /* sleep for a bit */ + if (!ca->wakeup) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(ca->delay); + if (kthread_should_stop()) + return 0; + } + ca->wakeup = 0; + + /* go through all the slots processing them */ + for (slot = 0; slot < ca->slot_count; slot++) + dvb_ca_en50221_slot_process(ca, slot); + } + + return 0; +} + + + +/* ************************************************************************** */ +/* EN50221 IO interface functions */ + +/** + * Real ioctl implementation. + * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. + * + * @param inode Inode concerned. + * @param file File concerned. + * @param cmd IOCTL command. + * @param arg Associated argument. + * + * @return 0 on success, <0 on error. + */ +static int dvb_ca_en50221_io_do_ioctl(struct file *file, + unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int err = 0; + int slot; + + if (mutex_lock_interruptible(&ca->ioctl_mutex)) { + pr_error("ci lock interrupt error\r\n"); + return -ERESTARTSYS; + } + + switch (cmd) { + case CA_RESET: + dprintk("ci reset---\r\n"); + for (slot = 0; slot < ca->slot_count; slot++) { + mutex_lock(&ca->slot_info[slot].slot_lock); + if (ca->slot_info[slot].slot_state + == DVB_CA_SLOTSTATE_NONE) + goto next; + dvb_ca_en50221_slot_shutdown(ca, slot); + if (ca->flags + & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) + dvb_ca_en50221_cimax_camchange_irq( + ca->pub, + slot, + DVB_CA_EN50221_CAMCHANGE_INSERTED); +next: + mutex_unlock(&ca->slot_info[slot].slot_lock); + } + ca->next_read_slot = 0; + dvb_ca_en50221_thread_wakeup(ca); + break; + + case CA_GET_CAP: { + struct ca_caps *caps = parg; + + caps->slot_num = ca->slot_count; + caps->slot_type = CA_CI_LINK; + caps->descr_num = 0; + caps->descr_type = 0; + break; + } + + case CA_GET_SLOT_INFO: { + struct ca_slot_info *info = parg; + + if ((info->num > ca->slot_count) || (info->num < 0)) { + err = -EINVAL; + pr_error("info num error :%d\r\n", info->num); + goto out_unlock; + } + + info->type = CA_CI_LINK; + info->flags = 0; + if ((ca->slot_info[info->num].slot_state + != DVB_CA_SLOTSTATE_NONE) + && (ca->slot_info[info->num].slot_state + != DVB_CA_SLOTSTATE_INVALID)) { + info->flags = CA_CI_MODULE_PRESENT; + } + if (ca->slot_info[info->num].slot_state + == DVB_CA_SLOTSTATE_RUNNING) { + info->flags |= CA_CI_MODULE_READY; + } + break; + } + + default: + pr_error("Invalid cmd :%d\r\n", cmd); + err = -EINVAL; + break; + } + +out_unlock: + mutex_unlock(&ca->ioctl_mutex); + return err; +} + + +static int dvb_usercopy__(struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = -ENOTTY; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + kfree(mbuf); + return err; +} + + + +/** + * Wrapper for ioctl implementation. + * + * @param inode Inode concerned. + * @param file File concerned. + * @param cmd IOCTL command. + * @param arg Associated argument. + * + * @return 0 on success, <0 on error. + */ +static long dvb_ca_en50221_io_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return dvb_usercopy__(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); +} + + +/** + * Implementation of write() syscall. + * + * @param file File structure. + * @param buf Source buffer. + * @param count Size of source buffer. + * @param ppos Position in file (ignored). + * + * @return Number of bytes read, or <0 on error. + */ +static ssize_t dvb_ca_en50221_io_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + u8 slot, connection_id; + int status; + u8 *fragbuf = ca->wbuf; + int fragpos = 0; + int fraglen; + unsigned long timeout; + int written; + + /* dprintk("%s\n", __func__); */ + + /* Incoming packet has a 2 byte header. + hdr[0] = slot_id, hdr[1] = connection_id */ + if (count < 2) + return -EINVAL; + + /* extract slot & connection id */ + if (copy_from_user(&slot, buf, 1)) + return -EFAULT; + if (copy_from_user(&connection_id, buf + 1, 1)) + return -EFAULT; + buf += 2; + count -= 2; + + if (slot >= ca->slot_count) + return -EFAULT; + /* check if the slot is actually running */ + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + return -EINVAL; + + /* fragment the packets & store in the buffer */ + while (fragpos < count) { + fraglen = ca->slot_info[slot].link_buf_size - 2; + if (fraglen < 0) + break; + if (fraglen > dvb_ca_en50221_link_size - 2) + fraglen = dvb_ca_en50221_link_size - 2; + if ((count - fragpos) < fraglen) + fraglen = count - fragpos; + + fragbuf[0] = connection_id; + fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; + status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen); + if (status) { + status = -EFAULT; + goto exit; + } + + timeout = jiffies + HZ / 2; + written = 0; + while (!time_after(jiffies, timeout)) { + /* check the CAM hasn't been removed/reset + in the meantime */ + if (ca->slot_info[slot].slot_state + != DVB_CA_SLOTSTATE_RUNNING) { + status = -EIO; + goto exit; + } + + mutex_lock(&ca->slot_info[slot].slot_lock); + status = dvb_ca_en50221_write_data(ca, + slot, fragbuf, fraglen + 2); + mutex_unlock(&ca->slot_info[slot].slot_lock); + if (status == (fraglen + 2)) { + written = 1; + break; + } + if (status != -EAGAIN) + goto exit; + + msleep(20); + } + if (!written) { + status = -EIO; + goto exit; + } + + fragpos += fraglen; + } + status = count + 2; + +exit: + return status; +} + + +/** + * Condition for waking up in dvb_ca_en50221_io_read_condition + */ +static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, + int *result, int *_slot) +{ + int slot; + int slot_count = 0; + int idx; + size_t fraglen; + int connection_id = -1; + int found = 0; + u8 hdr[2]; + + slot = ca->next_read_slot; + while ((slot_count < ca->slot_count) && (!found)) { + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + goto nextslot; + + if (ca->slot_info[slot].rx_buffer.data == NULL) + return 0; + + idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, + -1, &fraglen); + while (idx != -1) { + dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, + idx, 0, hdr, 2); + if (connection_id == -1) + connection_id = hdr[0]; + if ((hdr[0] == connection_id) + && ((hdr[1] & 0x80) == 0)) { + *_slot = slot; + found = 1; + break; + } + + idx = dvb_ringbuffer_pkt_next( + &ca->slot_info[slot].rx_buffer, + idx, + &fraglen); + } + +nextslot: + slot = (slot + 1) % ca->slot_count; + slot_count++; + } + + ca->next_read_slot = slot; + return found; +} + + +/** + * Implementation of read() syscall. + * + * @param file File structure. + * @param buf Destination buffer. + * @param count Size of destination buffer. + * @param ppos Position in file (ignored). + * + * @return Number of bytes read, or <0 on error. + */ +static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int status; + int result = 0; + u8 hdr[2]; + int slot; + int connection_id = -1; + size_t idx, idx2; + int last_fragment = 0; + size_t fraglen; + int pktlen; + int dispose = 0; + + /* dprintk("%s\n", __func__); */ + + /* Outgoing packet has a 2 byte header. + hdr[0] = slot_id, hdr[1] = connection_id */ + if (count < 2) + return -EINVAL; + + /* wait for some data */ + status = dvb_ca_en50221_io_read_condition(ca, &result, &slot); + if (status == 0) { + /* if we're in nonblocking mode, exit immediately */ + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + /* wait for some data */ + status = wait_event_interruptible(ca->wait_queue, + dvb_ca_en50221_io_read_condition + (ca, &result, &slot)); + } + if ((status < 0) || (result < 0)) { + if (result) + return result; + return status; + } + + idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, + -1, &fraglen); + pktlen = 2; + do { + if (idx == -1) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("BUG: read packet ended"); + pr_error("before last_fragment encountered\n"); + status = -EIO; + goto exit; + } + + dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, + idx, 0, hdr, 2); + if (connection_id == -1) + connection_id = hdr[0]; + if (hdr[0] == connection_id) { + if (pktlen < count) { + if ((pktlen + fraglen - 2) > count) + fraglen = count - pktlen; + else + fraglen -= 2; + + status = dvb_ringbuffer_pkt_read_user( + &ca->slot_info[slot].rx_buffer, + idx, + 2, + buf + pktlen, + fraglen); + if (status < 0) + goto exit; + pktlen += fraglen; + } + + if ((hdr[1] & 0x80) == 0) + last_fragment = 1; + dispose = 1; + } + + idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, + idx, &fraglen); + if (dispose) + dvb_ringbuffer_pkt_dispose( + &ca->slot_info[slot].rx_buffer, idx); + idx = idx2; + dispose = 0; + } while (!last_fragment); + + hdr[0] = slot; + hdr[1] = connection_id; + status = copy_to_user(buf, hdr, 2); + if (status) { + status = -EFAULT; + goto exit; + } + status = pktlen; + +exit: + return status; +} + + +/** + * Implementation of file open syscall. + * + * @param inode Inode concerned. + * @param file File concerned. + * + * @return 0 on success, <0 on failure. + */ +static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int err; + int i; + + dprintk("%s\n", __func__); + + if (!try_module_get(ca->pub->owner)) + return -EIO; + + err = dvb_generic_open(inode, file); + if (err < 0) { + module_put(ca->pub->owner); + return err; + } + + for (i = 0; i < ca->slot_count; i++) { + + if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { + if (ca->slot_info[i].rx_buffer.data != NULL) { + /* it is safe to call this here without locks + because ca->open == 0. + Data is not read in this case */ + dvb_ringbuffer_flush( + &ca->slot_info[i].rx_buffer); + } + } + } + + ca->open = 1; + dvb_ca_en50221_thread_update_delay(ca); + dvb_ca_en50221_thread_wakeup(ca); + + return 0; +} + + +/** + * Implementation of file close syscall. + * + * @param inode Inode concerned. + * @param file File concerned. + * + * @return 0 on success, <0 on failure. + */ +static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int err; + + dprintk("%s\n", __func__); + + /* mark the CA device as closed */ + ca->open = 0; + dvb_ca_en50221_thread_update_delay(ca); + + err = dvb_generic_release(inode, file); + + module_put(ca->pub->owner); + + return err; +} + + +/** + * Implementation of poll() syscall. + * + * @param file File concerned. + * @param wait poll wait table. + * + * @return Standard poll mask. + */ +static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + unsigned int mask = 0; + int slot; + int result = 0; + + /* dprintk("%s\n", __func__); */ + + if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) + mask |= POLLIN; + + /* if there is something, return now */ + if (mask) + return mask; + + /* wait for something to happen */ + poll_wait(file, &ca->wait_queue, wait); + + if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) + mask |= POLLIN; + + return mask; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_init); + +#ifdef CONFIG_COMPAT +static long dvb_ca_en50221_compat_ioctl(struct file *filp, + unsigned int cmd, unsigned long args) +{ + unsigned long ret; + + args = (unsigned long)compat_ptr(args); + ret = dvb_ca_en50221_io_ioctl(filp, cmd, args); + return ret; +} +#endif +static const struct file_operations dvb_ca_fops = { + .owner = THIS_MODULE, + .read = dvb_ca_en50221_io_read, + .write = dvb_ca_en50221_io_write, + .unlocked_ioctl = dvb_ca_en50221_io_ioctl, + .open = dvb_ca_en50221_io_open, + .release = dvb_ca_en50221_io_release, + .poll = dvb_ca_en50221_io_poll, + .llseek = noop_llseek, +#ifdef CONFIG_COMPAT + .compat_ioctl = dvb_ca_en50221_compat_ioctl, +#endif +}; + +static struct dvb_device dvbdev_ca = { + .priv = NULL, + .users = 1, + .readers = 1, + .writers = 1, + .fops = &dvb_ca_fops, +}; + + +/* ************************************************************************** */ +/* Initialisation/shutdown functions */ + + +/** + * Initialise a new DVB CA EN50221 CIMAX interface device. + * + * @param dvb_adapter DVB adapter to attach the new CA device to. + * @param ca The dvb_ca instance. + * @param flags Flags describing the CA device (DVB_CA_FLAG_*). + * @param slot_count Number of slots supported. + * + * @return 0 on success, nonzero on failure + */ +int dvb_ca_en50221_cimax_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221_cimax *pubca, + int flags, int slot_count) +{ + int ret; + struct dvb_ca_private *ca = NULL; + int i; + + dprintk("%s\n", __func__); + + if (slot_count < 1) + return -EINVAL; + + /* initialise the system data */ + ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL); + if (ca == NULL) { + ret = -ENOMEM; + goto error; + } + ca->pub = pubca; + ca->flags = flags; + ca->slot_count = slot_count; + ca->slot_info = + kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL); + if (ca->slot_info == NULL) { + ret = -ENOMEM; + goto error; + } + init_waitqueue_head(&ca->wait_queue); + ca->open = 0; + ca->wakeup = 0; + ca->next_read_slot = 0; + ca->rbuf = kcalloc(HOST_LINK_BUF_SIZE, 1, GFP_KERNEL); + ca->wbuf = kcalloc(HOST_LINK_BUF_SIZE, 1, GFP_KERNEL); + if (ca->rbuf == NULL || ca->wbuf == NULL) { + ret = -ENOMEM; + goto error; + } + pubca->private = ca; + + /* register the DVB device */ + ret = dvb_register_device(dvb_adapter, + &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0); + if (ret) + goto error; + + /* now initialise each slot */ + for (i = 0; i < slot_count; i++) { + memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot)); + ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; + atomic_set(&ca->slot_info[i].camchange_count, 0); + ca->slot_info[i].camchange_type = + DVB_CA_EN50221_CAMCHANGE_REMOVED; + mutex_init(&ca->slot_info[i].slot_lock); + } + + mutex_init(&ca->ioctl_mutex); + + if (signal_pending(current)) { + ret = -EINTR; + goto error; + } + mb();/*original*/ + + /* create a kthread for monitoring this CA device */ + ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", + ca->dvbdev->adapter->num, ca->dvbdev->id); + if (IS_ERR(ca->thread)) { + ret = PTR_ERR(ca->thread); + printk("dvb_ca_init: failed to start kernel_thread (%d)\n", + ret); + goto error; + } + return 0; + +error: + if (ca != NULL) { + if (ca->dvbdev != NULL) + dvb_unregister_device(ca->dvbdev); + kfree(ca->slot_info); + kfree(ca->rbuf); + kfree(ca->wbuf); + kfree(ca); + } + pubca->private = NULL; + return ret; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_release); + + + +/** + * Release a DVB CA EN50221 CIMAX interface device. + * + * @param ca_dev The dvb_struct device_s instance for the CA device. + * @param ca The associated dvb_ca instance. + */ +void dvb_ca_en50221_cimax_release(struct dvb_ca_en50221_cimax *pubca) +{ + struct dvb_ca_private *ca = pubca->private; + int i; + + dprintk("%s\n", __func__); + + /* shutdown the thread if there was one */ + kthread_stop(ca->thread); + + for (i = 0; i < ca->slot_count; i++) { + dvb_ca_en50221_slot_shutdown(ca, i); + vfree(ca->slot_info[i].rx_buffer.data); + } + kfree(ca->slot_info); + kfree(ca->rbuf); + kfree(ca->wbuf); + dvb_unregister_device(ca->dvbdev); + kfree(ca); + pubca->private = NULL; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h new file mode 100644 index 000000000000..e2ebde6cbc62 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h @@ -0,0 +1,144 @@ +/* + * dvb_ca_cimax.h: generic DVB functions for EN50221 CA CIMAX interfaces + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * 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. + */ + +#ifndef _DVB_CA_EN50221_CIMAX_H_ +#define _DVB_CA_EN50221_CIMAX_H_ + +#include +#include + +#include "dvbdev.h" + +#define DVB_CA_EN50221_POLL_CAM_PRESENT 1 +#define DVB_CA_EN50221_POLL_CAM_CHANGED 2 +#define DVB_CA_EN50221_POLL_CAM_READY 4 + +#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1 +#define DVB_CA_EN50221_FLAG_IRQ_FR 2 +#define DVB_CA_EN50221_FLAG_IRQ_DA 4 + +#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0 +#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1 + +#define DVB_CA_EN50221_CAP_IRQ 1 + +/* Structure describing a CA interface */ +struct dvb_ca_en50221_cimax { + + /* the module owning this structure */ + struct module *owner; + + /* NOTE: the read_*, write_* and poll_slot_status functions will be + * called for different slots concurrently and need to use locks where + * and if appropriate. There will be no concurrent access to one slot. + */ + + /* functions for accessing attribute memory on the CAM */ + int (*read_cis)(struct dvb_ca_en50221_cimax *ca, + int slot, u8 *buf, int size); + int (*write_cor)(struct dvb_ca_en50221_cimax *ca, + int slot, int address, u8 *buf); + /*return the final size or -1 for error*/ + int (*negotiate)(struct dvb_ca_en50221_cimax *ca, int slot, int size); + + /* functions for accessing the control interface on the CAM */ + int (*read_lpdu)(struct dvb_ca_en50221_cimax *ca, + int slot, u8 *buf, int size); + int (*write_lpdu)(struct dvb_ca_en50221_cimax *ca, + int slot, u8 *buf, int size); + + int (*cam_reset)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*read_cam_status)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*get_capbility)(struct dvb_ca_en50221_cimax *ca, int slot); + + /* Functions for controlling slots */ + int (*slot_reset)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*slot_shutdown)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*slot_ts_enable)(struct dvb_ca_en50221_cimax *ca, int slot); + + /* + * Poll slot status. + * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set + */ + int (*poll_slot_status)(struct dvb_ca_en50221_cimax *ca, + int slot, int open); + + /* private data, used by caller */ + void *data; + + /* Opaque data used by the dvb_ca core. Do not modify! */ + void *private; +}; + + + + +/* ************************************************************************* */ +/* Functions for reporting IRQ events */ + +/** + * A CAMCHANGE IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + * @param change_type One of the DVB_CA_CAMCHANGE_* values + */ +void dvb_ca_en50221_cimax_camchange_irq(struct dvb_ca_en50221_cimax *pubca, + int slot, int change_type); + +/** + * A CAMREADY IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_camready_irq(struct dvb_ca_en50221_cimax *pubca, + int slot); + +/** + * An FR or a DA IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_frda_irq(struct dvb_ca_en50221_cimax *ca, int slot); + + + +/* ************************************************************************** */ +/* Initialisation/shutdown functions */ + +/** + * Initialise a new DVB CA device. + * + * @param dvb_adapter DVB adapter to attach the new CA device to. + * @param ca The dvb_ca instance. + * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*). + * @param slot_count Number of slots supported. + * + * @return 0 on success, nonzero on failure + */ +extern int dvb_ca_en50221_cimax_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221_cimax *ca, int flags, int slot_count); + +/** + * Release a DVB CA device. + * + * @param ca The associated dvb_ca instance. + */ +extern void dvb_ca_en50221_cimax_release(struct dvb_ca_en50221_cimax *ca); + + + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c new file mode 100644 index 000000000000..fa5c16335909 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c @@ -0,0 +1,381 @@ +/* + * + * dvb_ringbuffer.c: ring buffer implementation for the dvb driver + * + * Copyright (C) 2003 Oliver Endriss + * Copyright (C) 2004 Andrew de Quincey + * + * based on code originally found in av7110.c & dvb_ci.c: + * Copyright (C) 1999-2003 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +#include +#include +#include +#include +#include +#include + +#include "dvb_ringbuffer.h" + +#define PKT_READY 0 +#define PKT_DISPOSED 1 + + +void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) +{ + rbuf->pread=rbuf->pwrite=0; + rbuf->data=data; + rbuf->size=len; + rbuf->error=0; + + init_waitqueue_head(&rbuf->queue); + + spin_lock_init(&(rbuf->lock)); +} + + + +int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) +{ + /* smp_load_acquire() to load write pointer on reader side + * this pairs with smp_store_release() in dvb_ringbuffer_write(), + * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() + * + * for memory barriers also see Documentation/circular-buffers.txt + */ + return (rbuf->pread == smp_load_acquire(&rbuf->pwrite)); +} + + + +ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) +{ + ssize_t free; + + /* ACCESS_ONCE() to load read pointer on writer side + * this pairs with smp_store_release() in dvb_ringbuffer_read(), + * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(), + * or dvb_ringbuffer_reset() + */ + free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite; + if (free <= 0) + free += rbuf->size; + return free-1; +} + + + +ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) +{ + ssize_t avail; + + /* smp_load_acquire() to load write pointer on reader side + * this pairs with smp_store_release() in dvb_ringbuffer_write(), + * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() + */ + avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread; + if (avail < 0) + avail += rbuf->size; + return avail; +} + + + +void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) +{ + /* dvb_ringbuffer_flush() counts as read operation + * smp_load_acquire() to load write pointer + * smp_store_release() to update read pointer, this ensures that the + * correct pointer is visible for subsequent dvb_ringbuffer_free() + * calls on other cpu cores + */ + smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite)); + rbuf->error = 0; +} +//EXPORT_SYMBOL(dvb_ringbuffer_flush); + +void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) +{ + /* dvb_ringbuffer_reset() counts as read and write operation + * smp_store_release() to update read pointer + */ + smp_store_release(&rbuf->pread, 0); + /* smp_store_release() to update write pointer */ + smp_store_release(&rbuf->pwrite, 0); + rbuf->error = 0; +} + +void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) +{ + unsigned long flags; + + spin_lock_irqsave(&rbuf->lock, flags); + dvb_ringbuffer_flush(rbuf); + spin_unlock_irqrestore(&rbuf->lock, flags); + + wake_up(&rbuf->queue); +} + +ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; + if (split > 0) { + if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) + return -EFAULT; + buf += split; + todo -= split; + /* smp_store_release() for read pointer update to ensure + * that buf is not overwritten until read is complete, + * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() + */ + smp_store_release(&rbuf->pread, 0); + } + if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) + return -EFAULT; + + /* smp_store_release() to update read pointer, see above */ + smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size); + + return len; +} + +void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; + if (split > 0) { + memcpy(buf, rbuf->data+rbuf->pread, split); + buf += split; + todo -= split; + /* smp_store_release() for read pointer update to ensure + * that buf is not overwritten until read is complete, + * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() + */ + smp_store_release(&rbuf->pread, 0); + } + memcpy(buf, rbuf->data+rbuf->pread, todo); + + /* smp_store_release() to update read pointer, see above */ + smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size); +} + + +ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; + + if (split > 0) { + memcpy(rbuf->data+rbuf->pwrite, buf, split); + buf += split; + todo -= split; + /* smp_store_release() for write pointer update to ensure that + * written data is visible on other cpu cores before the pointer + * update, this pairs with smp_load_acquire() in + * dvb_ringbuffer_empty() or dvb_ringbuffer_avail() + */ + smp_store_release(&rbuf->pwrite, 0); + } + memcpy(rbuf->data+rbuf->pwrite, buf, todo); + /* smp_store_release() for write pointer update, see above */ + smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); + + return len; +} + +ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, + const u8 __user *buf, size_t len) +{ + int status; + size_t todo = len; + size_t split; + + split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; + + if (split > 0) { + status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split); + if (status) + return len - todo; + buf += split; + todo -= split; + /* smp_store_release() for write pointer update to ensure that + * written data is visible on other cpu cores before the pointer + * update, this pairs with smp_load_acquire() in + * dvb_ringbuffer_empty() or dvb_ringbuffer_avail() + */ + smp_store_release(&rbuf->pwrite, 0); + } + status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo); + if (status) + return len - todo; + /* smp_store_release() for write pointer update, see above */ + smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); + + return len; +} + +ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) +{ + int status; + ssize_t oldpwrite = rbuf->pwrite; + + DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8); + DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff); + DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY); + status = dvb_ringbuffer_write(rbuf, buf, len); + + if (status < 0) rbuf->pwrite = oldpwrite; + return status; +} + +ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, + int offset, u8 __user *buf, size_t len) +{ + size_t todo; + size_t split; + size_t pktlen; + + pktlen = rbuf->data[idx] << 8; + pktlen |= rbuf->data[(idx + 1) % rbuf->size]; + if (offset > pktlen) return -EINVAL; + if ((offset + len) > pktlen) len = pktlen - offset; + + idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; + todo = len; + split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; + if (split > 0) { + if (copy_to_user(buf, rbuf->data+idx, split)) + return -EFAULT; + buf += split; + todo -= split; + idx = 0; + } + if (copy_to_user(buf, rbuf->data+idx, todo)) + return -EFAULT; + + return len; +} + +ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, + int offset, u8* buf, size_t len) +{ + size_t todo; + size_t split; + size_t pktlen; + + pktlen = rbuf->data[idx] << 8; + pktlen |= rbuf->data[(idx + 1) % rbuf->size]; + if (offset > pktlen) return -EINVAL; + if ((offset + len) > pktlen) len = pktlen - offset; + + idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; + todo = len; + split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; + if (split > 0) { + memcpy(buf, rbuf->data+idx, split); + buf += split; + todo -= split; + idx = 0; + } + memcpy(buf, rbuf->data+idx, todo); + return len; +} + +void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) +{ + size_t pktlen; + + rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED; + + // clean up disposed packets + while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { + if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { + pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; + pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); + DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); + } else { + // first packet is not disposed, so we stop cleaning now + break; + } + } +} + +ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen) +{ + int consumed; + int curpktlen; + int curpktstatus; + + if (idx == -1) { + idx = rbuf->pread; + } else { + curpktlen = rbuf->data[idx] << 8; + curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; + idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; + } + + consumed = (idx - rbuf->pread) % rbuf->size; + + while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { + + curpktlen = rbuf->data[idx] << 8; + curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; + curpktstatus = rbuf->data[(idx + 2) % rbuf->size]; + + if (curpktstatus == PKT_READY) { + *pktlen = curpktlen; + return idx; + } + + consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE; + idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; + } + + // no packets available + return -1; +} + + +#if 0 +EXPORT_SYMBOL(dvb_ringbuffer_init); +EXPORT_SYMBOL(dvb_ringbuffer_empty); +EXPORT_SYMBOL(dvb_ringbuffer_free); +EXPORT_SYMBOL(dvb_ringbuffer_avail); +EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); +EXPORT_SYMBOL(dvb_ringbuffer_read_user); +EXPORT_SYMBOL(dvb_ringbuffer_read); +EXPORT_SYMBOL(dvb_ringbuffer_write); +EXPORT_SYMBOL(dvb_ringbuffer_write_user); +#endif +EXPORT_SYMBOL(dvb_ringbuffer_pkt_read); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_write); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_next); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_dispose); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_read_user); + + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h new file mode 100644 index 000000000000..bbe94873d44d --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h @@ -0,0 +1,280 @@ +/* + * + * dvb_ringbuffer.h: ring buffer implementation for the dvb driver + * + * Copyright (C) 2003 Oliver Endriss + * Copyright (C) 2004 Andrew de Quincey + * + * based on code originally found in av7110.c & dvb_ci.c: + * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * 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 Lesser General Public License for more details. + */ + +#ifndef _DVB_RINGBUFFER_H_ +#define _DVB_RINGBUFFER_H_ + +#include +#include + +/** + * struct dvb_ringbuffer - Describes a ring buffer used at DVB framework + * + * @data: Area were the ringbuffer data is written + * @size: size of the ringbuffer + * @pread: next position to read + * @pwrite: next position to write + * @error: used by ringbuffer clients to indicate that an error happened. + * @queue: Wait queue used by ringbuffer clients to indicate when buffer + * was filled + * @lock: Spinlock used to protect the ringbuffer + */ +struct dvb_ringbuffer { + u8 *data; + ssize_t size; + ssize_t pread; + ssize_t pwrite; + int error; + + wait_queue_head_t queue; + spinlock_t lock; +}; + +#define DVB_RINGBUFFER_PKTHDRSIZE 3 + +/** + * dvb_ringbuffer_init - initialize ring buffer, lock and queue + * + * @rbuf: pointer to struct dvb_ringbuffer + * @data: pointer to the buffer where the data will be stored + * @len: bytes from ring buffer into @buf + */ +extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, + size_t len); + +/** + * dvb_ringbuffer_empty - test whether buffer is empty + * + * @rbuf: pointer to struct dvb_ringbuffer + */ +extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_free - returns the number of free bytes in the buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * + * Return: number of free bytes in the buffer + */ +extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * + * Return: number of bytes waiting in the buffer + */ +extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_reset - resets the ringbuffer to initial state + * + * @rbuf: pointer to struct dvb_ringbuffer + * + * Resets the read and write pointers to zero and flush the buffer. + * + * This counts as a read and write operation + */ +extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); + +/* + * read routines & macros + */ + +/** + * dvb_ringbuffer_flush - flush buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + */ +extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock + * and wake-up waiting task(s) + * + * @rbuf: pointer to struct dvb_ringbuffer + */ +extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); + +/** + * DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @offs: offset inside the ringbuffer + */ +#define DVB_RINGBUFFER_PEEK(rbuf, offs) \ + ((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size]) + +/** + * DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes + * + * @rbuf: pointer to struct dvb_ringbuffer + * @num: number of bytes to advance + */ +#define DVB_RINGBUFFER_SKIP(rbuf, num) {\ + (rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\ +} + +/** + * dvb_ringbuffer_read_user - Reads a buffer into an user pointer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be stored + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the userspace. So, + * it will internally call copy_to_user(). + * + * Return: number of bytes transferred or -EFAULT + */ +extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, + u8 __user *buf, size_t len); + +/** + * dvb_ringbuffer_read - Reads a buffer into a pointer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be stored + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the Kernel space + * + * Return: number of bytes transferred or -EFAULT + */ +extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, + u8 *buf, size_t len); + +/* + * write routines & macros + */ + +/** + * DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @byte: byte to write + */ +#define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \ + { (rbuf)->data[(rbuf)->pwrite] = (byte); \ + (rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; } + +/** + * dvb_ringbuffer_write - Writes a buffer into the ringbuffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be read + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the Kernel space + * + * return: number of bytes transferred or -EFAULT + */ +extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, + size_t len); + +/** + * dvb_ringbuffer_write_user - Writes a buffer received via an user pointer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be read + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the userspace. So, + * it will internally call copy_from_user(). + * + * Return: number of bytes transferred or -EFAULT + */ +extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, + const u8 __user *buf, size_t len); + +/** + * dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer. + * + * @rbuf: Ringbuffer to write to. + * @buf: Buffer to write. + * @len: Length of buffer (currently limited to 65535 bytes max). + * + * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. + */ +extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, + size_t len); + +/** + * dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer. + * + * @rbuf: Ringbuffer concerned. + * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). + * @offset: Offset into packet to read from. + * @buf: Destination buffer for data. + * @len: Size of destination buffer. + * + * Return: Number of bytes read, or -EFAULT. + * + * .. note:: + * + * unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer + * in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a + * packet as no longer required. + */ +extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, + size_t idx, + int offset, u8 __user *buf, + size_t len); + +/** + * dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer. + * Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer + * in the ringbuffer. + * + * @rbuf: Ringbuffer concerned. + * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). + * @offset: Offset into packet to read from. + * @buf: Destination buffer for data. + * @len: Size of destination buffer. + * + * Return: Number of bytes read, or -EFAULT. + */ +extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, + int offset, u8 *buf, size_t len); + +/** + * dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer. + * + * @rbuf: Ring buffer concerned. + * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). + */ +extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); + +/** + * dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer. + * + * @rbuf: Ringbuffer concerned. + * @idx: Previous packet index, or -1 to return the first packet index. + * @pktlen: On success, will be updated to contain the length of the packet + * in bytes. + * returns Packet index (if >=0), or -1 if no packets available. + */ +extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, + size_t idx, size_t *pktlen); + +#endif /* _DVB_RINGBUFFER_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c new file mode 100644 index 000000000000..0e9599bcb1b5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c @@ -0,0 +1,968 @@ +/* + * dvbdev.c + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbdev.h" + +/* Due to enum tuner_pad_index */ +#include + +static DEFINE_MUTEX(dvbdev_mutex); +static int dvbdev_debug; + +module_param(dvbdev_debug, int, 0644); +MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); + +#define dprintk if (dvbdev_debug) printk + +static LIST_HEAD(dvb_adapter_list); +static DEFINE_MUTEX(dvbdev_register_lock); + +static const char * const dnames[] = { + "video", "audio", "sec", "frontend", "demux", "dvr", "ca", + "net", "osd" +}; + +#ifdef CONFIG_DVB_DYNAMIC_MINORS +#define MAX_DVB_MINORS 256 +#define DVB_MAX_IDS MAX_DVB_MINORS +#else +#define DVB_MAX_IDS 4 +#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) +#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) +#endif + +static struct class *dvb_class; + +static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; +static DECLARE_RWSEM(minor_rwsem); + +static int dvb_device_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev; + + mutex_lock(&dvbdev_mutex); + down_read(&minor_rwsem); + dvbdev = dvb_minors[iminor(inode)]; + + if (dvbdev && dvbdev->fops) { + int err = 0; + const struct file_operations *new_fops; + + new_fops = fops_get(dvbdev->fops); + if (!new_fops) + goto fail; + file->private_data = dvbdev; + replace_fops(file, new_fops); + if (file->f_op->open) + err = file->f_op->open(inode, file); + up_read(&minor_rwsem); + mutex_unlock(&dvbdev_mutex); + return err; + } +fail: + up_read(&minor_rwsem); + mutex_unlock(&dvbdev_mutex); + return -ENODEV; +} + + +static const struct file_operations dvb_device_fops = +{ + .owner = THIS_MODULE, + .open = dvb_device_open, + .llseek = noop_llseek, +}; + +static struct cdev dvb_device_cdev; + +int dvb_generic_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + + if (!dvbdev) + return -ENODEV; + + if (!dvbdev->users) + return -EBUSY; + + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + if (!dvbdev->readers) + return -EBUSY; + dvbdev->readers--; + } else { + if (!dvbdev->writers) + return -EBUSY; + dvbdev->writers--; + } + + dvbdev->users--; + return 0; +} +EXPORT_SYMBOL(dvb_generic_open); + + +int dvb_generic_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + + if (!dvbdev) + return -ENODEV; + + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + dvbdev->readers++; + } else { + dvbdev->writers++; + } + + dvbdev->users++; + return 0; +} +EXPORT_SYMBOL(dvb_generic_release); + + +long dvb_generic_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct dvb_device *dvbdev = file->private_data; + + if (!dvbdev) + return -ENODEV; + + if (!dvbdev->kernel_ioctl) + return -EINVAL; + + return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); +} +EXPORT_SYMBOL(dvb_generic_ioctl); + + +static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) +{ + u32 id = 0; + + while (id < DVB_MAX_IDS) { + struct dvb_device *dev; + list_for_each_entry(dev, &adap->device_list, list_head) + if (dev->type == type && dev->id == id) + goto skip; + return id; +skip: + id++; + } + return -ENFILE; +} + +static void dvb_media_device_free(struct dvb_device *dvbdev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + if (dvbdev->entity) { + media_device_unregister_entity(dvbdev->entity); + kfree(dvbdev->entity); + kfree(dvbdev->pads); + dvbdev->entity = NULL; + dvbdev->pads = NULL; + } + + if (dvbdev->tsout_entity) { + int i; + + for (i = 0; i < dvbdev->tsout_num_entities; i++) { + media_device_unregister_entity(&dvbdev->tsout_entity[i]); + kfree(dvbdev->tsout_entity[i].name); + } + kfree(dvbdev->tsout_entity); + kfree(dvbdev->tsout_pads); + dvbdev->tsout_entity = NULL; + dvbdev->tsout_pads = NULL; + + dvbdev->tsout_num_entities = 0; + } + + if (dvbdev->intf_devnode) { + media_devnode_remove(dvbdev->intf_devnode); + dvbdev->intf_devnode = NULL; + } + + if (dvbdev->adapter->conn) { + media_device_unregister_entity(dvbdev->adapter->conn); + dvbdev->adapter->conn = NULL; + kfree(dvbdev->adapter->conn_pads); + dvbdev->adapter->conn_pads = NULL; + } +#endif +} + +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) +static int dvb_create_tsout_entity(struct dvb_device *dvbdev, + const char *name, int npads) +{ + int i, ret = 0; + + dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads), + GFP_KERNEL); + if (!dvbdev->tsout_pads) + return -ENOMEM; + + dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity), + GFP_KERNEL); + if (!dvbdev->tsout_entity) + return -ENOMEM; + + dvbdev->tsout_num_entities = npads; + + for (i = 0; i < npads; i++) { + struct media_pad *pads = &dvbdev->tsout_pads[i]; + struct media_entity *entity = &dvbdev->tsout_entity[i]; + + entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i); + if (!entity->name) + return -ENOMEM; + + entity->function = MEDIA_ENT_F_IO_DTV; + pads->flags = MEDIA_PAD_FL_SINK; + + ret = media_entity_pads_init(entity, 1, pads); + if (ret < 0) + return ret; + + ret = media_device_register_entity(dvbdev->adapter->mdev, + entity); + if (ret < 0) + return ret; + } + return 0; +} + +#define DEMUX_TSOUT "demux-tsout" +#define DVR_TSOUT "dvr-tsout" + +static int dvb_create_media_entity(struct dvb_device *dvbdev, + int type, int demux_sink_pads) +{ + int i, ret, npads; + + switch (type) { + case DVB_DEVICE_FRONTEND: + npads = 2; + break; + case DVB_DEVICE_DVR: + ret = dvb_create_tsout_entity(dvbdev, DVR_TSOUT, + demux_sink_pads); + return ret; + case DVB_DEVICE_DEMUX: + npads = 1 + demux_sink_pads; + ret = dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT, + demux_sink_pads); + if (ret < 0) + return ret; + break; + case DVB_DEVICE_CA: + npads = 2; + break; + case DVB_DEVICE_NET: + /* + * We should be creating entities for the MPE/ULE + * decapsulation hardware (or software implementation). + * + * However, the number of for the MPE/ULE decaps may not be + * fixed. As we don't have yet dynamic support for PADs at + * the Media Controller, let's not create the decap + * entities yet. + */ + return 0; + default: + return 0; + } + + dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL); + if (!dvbdev->entity) + return -ENOMEM; + + dvbdev->entity->name = dvbdev->name; + + if (npads) { + dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), + GFP_KERNEL); + if (!dvbdev->pads) + return -ENOMEM; + } + + switch (type) { + case DVB_DEVICE_FRONTEND: + dvbdev->entity->function = MEDIA_ENT_F_DTV_DEMOD; + dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; + dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; + break; + case DVB_DEVICE_DEMUX: + dvbdev->entity->function = MEDIA_ENT_F_TS_DEMUX; + dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; + for (i = 1; i < npads; i++) + dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE; + break; + case DVB_DEVICE_CA: + dvbdev->entity->function = MEDIA_ENT_F_DTV_CA; + dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; + dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; + break; + default: + /* Should never happen, as the first switch prevents it */ + kfree(dvbdev->entity); + kfree(dvbdev->pads); + dvbdev->entity = NULL; + dvbdev->pads = NULL; + return 0; + } + + if (npads) { + ret = media_entity_pads_init(dvbdev->entity, npads, dvbdev->pads); + if (ret) + return ret; + } + ret = media_device_register_entity(dvbdev->adapter->mdev, + dvbdev->entity); + if (ret) + return ret; + + printk(KERN_DEBUG "%s: media entity '%s' registered.\n", + __func__, dvbdev->entity->name); + + return 0; +} +#endif + +static int dvb_register_media_device(struct dvb_device *dvbdev, + int type, int minor, + unsigned demux_sink_pads) +{ +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + struct media_link *link; + u32 intf_type; + int ret; + + if (!dvbdev->adapter->mdev) + return 0; + + ret = dvb_create_media_entity(dvbdev, type, demux_sink_pads); + if (ret) + return ret; + + switch (type) { + case DVB_DEVICE_FRONTEND: + intf_type = MEDIA_INTF_T_DVB_FE; + break; + case DVB_DEVICE_DEMUX: + intf_type = MEDIA_INTF_T_DVB_DEMUX; + break; + case DVB_DEVICE_DVR: + intf_type = MEDIA_INTF_T_DVB_DVR; + break; + case DVB_DEVICE_CA: + intf_type = MEDIA_INTF_T_DVB_CA; + break; + case DVB_DEVICE_NET: + intf_type = MEDIA_INTF_T_DVB_NET; + break; + default: + return 0; + } + + dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev, + intf_type, 0, + DVB_MAJOR, minor); + + if (!dvbdev->intf_devnode) + return -ENOMEM; + + /* + * Create the "obvious" link, e. g. the ones that represent + * a direct association between an interface and an entity. + * Other links should be created elsewhere, like: + * DVB FE intf -> tuner + * DVB demux intf -> dvr + */ + + if (!dvbdev->entity) + return 0; + + link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; +#endif + return 0; +} + +int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + const struct dvb_device *template, void *priv, int type, + int demux_sink_pads) +{ + struct dvb_device *dvbdev; + struct file_operations *dvbdevfops; + struct device *clsdev; + int minor; + int id, ret; + + mutex_lock(&dvbdev_register_lock); + + if ((id = dvbdev_get_free_id (adap, type)) < 0){ + mutex_unlock(&dvbdev_register_lock); + *pdvbdev = NULL; + printk(KERN_ERR "%s: couldn't find free device id\n", __func__); + return -ENFILE; + } + + *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); + + if (!dvbdev){ + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + + dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); + + if (!dvbdevfops){ + kfree (dvbdev); + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + + memcpy(dvbdev, template, sizeof(struct dvb_device)); + dvbdev->type = type; + dvbdev->id = id; + dvbdev->adapter = adap; + dvbdev->priv = priv; + dvbdev->fops = dvbdevfops; + init_waitqueue_head (&dvbdev->wait_queue); + + memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); + dvbdevfops->owner = adap->module; + + list_add_tail (&dvbdev->list_head, &adap->device_list); + + down_write(&minor_rwsem); +#ifdef CONFIG_DVB_DYNAMIC_MINORS + for (minor = 0; minor < MAX_DVB_MINORS; minor++) + if (dvb_minors[minor] == NULL) + break; + + if (minor == MAX_DVB_MINORS) { + kfree(dvbdevfops); + kfree(dvbdev); + up_write(&minor_rwsem); + mutex_unlock(&dvbdev_register_lock); + return -EINVAL; + } +#else + minor = nums2minor(adap->num, type, id); +#endif + + dvbdev->minor = minor; + dvb_minors[minor] = dvbdev; + up_write(&minor_rwsem); + + ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); + if (ret) { + printk(KERN_ERR + "%s: dvb_register_media_device failed to create the mediagraph\n", + __func__); + + dvb_media_device_free(dvbdev); + kfree(dvbdevfops); + kfree(dvbdev); + up_write(&minor_rwsem); + mutex_unlock(&dvbdev_register_lock); + return ret; + } + + mutex_unlock(&dvbdev_register_lock); + + clsdev = device_create(dvb_class, adap->device, + MKDEV(DVB_MAJOR, minor), + dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); + if (IS_ERR(clsdev)) { + printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", + __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); + return PTR_ERR(clsdev); + } + dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", + adap->num, dnames[type], id, minor, minor); + + return 0; +} +EXPORT_SYMBOL(dvb_register_device); + + +void dvb_unregister_device(struct dvb_device *dvbdev) +{ + if (!dvbdev) + return; + + down_write(&minor_rwsem); + dvb_minors[dvbdev->minor] = NULL; + up_write(&minor_rwsem); + + dvb_media_device_free(dvbdev); + + device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); + + list_del (&dvbdev->list_head); + kfree (dvbdev->fops); + kfree (dvbdev); +} +EXPORT_SYMBOL(dvb_unregister_device); + + +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + +static int dvb_create_io_intf_links(struct dvb_adapter *adap, + struct media_interface *intf, + char *name) +{ + struct media_device *mdev = adap->mdev; + struct media_entity *entity; + struct media_link *link; + + media_device_for_each_entity(entity, mdev) { + if (entity->function == MEDIA_ENT_F_IO_DTV) { + if (strncmp(entity->name, name, strlen(name))) + continue; + link = media_create_intf_link(entity, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } + } + return 0; +} + +int dvb_create_media_graph(struct dvb_adapter *adap, + bool create_rf_connector) +{ + struct media_device *mdev = adap->mdev; + struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn; + struct media_entity *demux = NULL, *ca = NULL; + struct media_link *link; + struct media_interface *intf; + unsigned demux_pad = 0; + unsigned dvr_pad = 0; + unsigned ntuner = 0, ndemod = 0; + int ret; + static const char *connector_name = "Television"; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_TUNER: + tuner = entity; + ntuner++; + break; + case MEDIA_ENT_F_DTV_DEMOD: + demod = entity; + ndemod++; + break; + case MEDIA_ENT_F_TS_DEMUX: + demux = entity; + break; + case MEDIA_ENT_F_DTV_CA: + ca = entity; + break; + } + } + + /* + * Prepare to signalize to media_create_pad_links() that multiple + * entities of the same type exists and a 1:n or n:1 links need to be + * created. + * NOTE: if both tuner and demod have multiple instances, it is up + * to the caller driver to create such links. + */ + if (ntuner > 1) + tuner = NULL; + if (ndemod > 1) + demod = NULL; + + if (create_rf_connector) { + conn = kzalloc(sizeof(*conn), GFP_KERNEL); + if (!conn) + return -ENOMEM; + adap->conn = conn; + + adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL); + if (!adap->conn_pads) + return -ENOMEM; + + conn->flags = MEDIA_ENT_FL_CONNECTOR; + conn->function = MEDIA_ENT_F_CONN_RF; + conn->name = connector_name; + adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(conn, 1, adap->conn_pads); + if (ret) + return ret; + + ret = media_device_register_entity(mdev, conn); + if (ret) + return ret; + + if (!ntuner) + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_CONN_RF, + conn, 0, + MEDIA_ENT_F_DTV_DEMOD, + demod, 0, + MEDIA_LNK_FL_ENABLED, + false); + else + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_CONN_RF, + conn, 0, + MEDIA_ENT_F_TUNER, + tuner, TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED, + false); + if (ret) + return ret; + } + + if (ntuner && ndemod) { + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_TUNER, + tuner, TUNER_PAD_OUTPUT, + MEDIA_ENT_F_DTV_DEMOD, + demod, 0, MEDIA_LNK_FL_ENABLED, + false); + if (ret) + return ret; + } + + if (ndemod && demux) { + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_DTV_DEMOD, + demod, 1, + MEDIA_ENT_F_TS_DEMUX, + demux, 0, MEDIA_LNK_FL_ENABLED, + false); + if (ret) + return ret; + } + if (demux && ca) { + ret = media_create_pad_link(demux, 1, ca, + 0, MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + /* Create demux links for each ringbuffer/pad */ + if (demux) { + media_device_for_each_entity(entity, mdev) { + if (entity->function == MEDIA_ENT_F_IO_DTV) { + if (!strncmp(entity->name, DVR_TSOUT, + strlen(DVR_TSOUT))) { + ret = media_create_pad_link(demux, + ++dvr_pad, + entity, 0, 0); + if (ret) + return ret; + } + if (!strncmp(entity->name, DEMUX_TSOUT, + strlen(DEMUX_TSOUT))) { + ret = media_create_pad_link(demux, + ++demux_pad, + entity, 0, 0); + if (ret) + return ret; + } + } + } + } + + /* Create interface links for FE->tuner, DVR->demux and CA->ca */ + media_device_for_each_intf(intf, mdev) { + if (intf->type == MEDIA_INTF_T_DVB_CA && ca) { + link = media_create_intf_link(ca, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } + + if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) { + link = media_create_intf_link(tuner, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } +#if 0 + /* + * Indirect link - let's not create yet, as we don't know how + * to handle indirect links, nor if this will + * actually be needed. + */ + if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) { + link = media_create_intf_link(demux, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } +#endif + if (intf->type == MEDIA_INTF_T_DVB_DVR) { + ret = dvb_create_io_intf_links(adap, intf, DVR_TSOUT); + if (ret) + return ret; + } + if (intf->type == MEDIA_INTF_T_DVB_DEMUX) { + ret = dvb_create_io_intf_links(adap, intf, DEMUX_TSOUT); + if (ret) + return ret; + } + } + return 0; +} +EXPORT_SYMBOL_GPL(dvb_create_media_graph); +#endif + +static int dvbdev_check_free_adapter_num(int num) +{ + struct list_head *entry; + list_for_each(entry, &dvb_adapter_list) { + struct dvb_adapter *adap; + adap = list_entry(entry, struct dvb_adapter, list_head); + if (adap->num == num) + return 0; + } + return 1; +} + +static int dvbdev_get_free_adapter_num (void) +{ + int num = 0; + + while (num < DVB_MAX_ADAPTERS) { + if (dvbdev_check_free_adapter_num(num)) + return num; + num++; + } + + return -ENFILE; +} + + +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums) +{ + int i, num; + + mutex_lock(&dvbdev_register_lock); + + for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { + num = adapter_nums[i]; + if (num >= 0 && num < DVB_MAX_ADAPTERS) { + /* use the one the driver asked for */ + if (dvbdev_check_free_adapter_num(num)) + break; + } else { + num = dvbdev_get_free_adapter_num(); + break; + } + num = -1; + } + + if (num < 0) { + mutex_unlock(&dvbdev_register_lock); + return -ENFILE; + } + + memset (adap, 0, sizeof(struct dvb_adapter)); + INIT_LIST_HEAD (&adap->device_list); + + printk(KERN_INFO "DVB: registering new adapter (%s)\n", name); + + adap->num = num; + adap->name = name; + adap->module = module; + adap->device = device; + adap->mfe_shared = 0; + adap->mfe_dvbdev = NULL; + mutex_init (&adap->mfe_lock); + + list_add_tail (&adap->list_head, &dvb_adapter_list); + + mutex_unlock(&dvbdev_register_lock); + + return num; +} +EXPORT_SYMBOL(dvb_register_adapter); + + +int dvb_unregister_adapter(struct dvb_adapter *adap) +{ + mutex_lock(&dvbdev_register_lock); + list_del (&adap->list_head); + mutex_unlock(&dvbdev_register_lock); + return 0; +} +EXPORT_SYMBOL(dvb_unregister_adapter); + +/* if the miracle happens and "generic_usercopy()" is included into + the kernel, then this can vanish. please don't make the mistake and + define this as video_usercopy(). this will introduce a dependecy + to the v4l "videodev.o" module, which is unnecessary for some + cards (ie. the budget dvb-cards don't need the v4l module...) */ +int dvb_usercopy(struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = -ENOTTY; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + kfree(mbuf); + return err; +} +EXPORT_SYMBOL(dvb_usercopy); +static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct dvb_device *dvbdev = dev_get_drvdata(dev); + + add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); + add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); + add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id); + return 0; +} + +static char *dvb_devnode(struct device *dev, umode_t *mode) +{ + struct dvb_device *dvbdev = dev_get_drvdata(dev); + + return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", + dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); +} + + +static int __init init_dvbdev(void) +{ + int retval; + dev_t dev = MKDEV(DVB_MAJOR, 0); + + if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { + printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR); + return retval; + } + + cdev_init(&dvb_device_cdev, &dvb_device_fops); + if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { + printk(KERN_ERR "dvb-core: unable register character device\n"); + goto error; + } + + dvb_class = class_create(THIS_MODULE, "dvb"); + if (IS_ERR(dvb_class)) { + retval = PTR_ERR(dvb_class); + goto error; + } + dvb_class->dev_uevent = dvb_uevent; + dvb_class->devnode = dvb_devnode; + return 0; + +error: + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(dev, MAX_DVB_MINORS); + return retval; +} + + +static void __exit exit_dvbdev(void) +{ + class_destroy(dvb_class); + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); +} +#if 0 +subsys_initcall(init_dvbdev); +module_exit(exit_dvbdev); + +MODULE_DESCRIPTION("DVB Core Driver"); +MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); +MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h new file mode 100644 index 000000000000..4aff7bd3dea8 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h @@ -0,0 +1,299 @@ +/* + * dvbdev.h + * + * Copyright (C) 2000 Ralph Metzler & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBDEV_H_ +#define _DVBDEV_H_ + +#include +#include +#include +#include +#include + +#define DVB_MAJOR 212 + +#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 + #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS +#else + #define DVB_MAX_ADAPTERS 8 +#endif + +#define DVB_UNSET (-1) + +#define DVB_DEVICE_VIDEO 0 +#define DVB_DEVICE_AUDIO 1 +#define DVB_DEVICE_SEC 2 +#define DVB_DEVICE_FRONTEND 3 +#define DVB_DEVICE_DEMUX 4 +#define DVB_DEVICE_DVR 5 +#define DVB_DEVICE_CA 6 +#define DVB_DEVICE_NET 7 +#define DVB_DEVICE_OSD 8 + +#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ + static short adapter_nr[] = \ + {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \ + module_param_array(adapter_nr, short, NULL, 0444); \ + MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") + +struct dvb_frontend; + +/** + * struct dvb_adapter - represents a Digital TV adapter using Linux DVB API + * + * @num: Number of the adapter + * @list_head: List with the DVB adapters + * @device_list: List with the DVB devices + * @name: Name of the adapter + * @proposed_mac: proposed MAC address for the adapter + * @priv: private data + * @device: pointer to struct device + * @module: pointer to struct module + * @mfe_shared: mfe shared: indicates mutually exclusive frontends + * Thie usage of this flag is currently deprecated + * @mfe_dvbdev: Frontend device in use, in the case of MFE + * @mfe_lock: Lock to prevent using the other frontends when MFE is + * used. + * @mdev: pointer to struct media_device, used when the media + * controller is used. + * @conn: RF connector. Used only if the device has no separate + * tuner. + * @conn_pads: pointer to struct media_pad associated with @conn; + */ +struct dvb_adapter { + int num; + struct list_head list_head; + struct list_head device_list; + const char *name; + u8 proposed_mac [6]; + void* priv; + + struct device *device; + + struct module *module; + + int mfe_shared; /* indicates mutually exclusive frontends */ + struct dvb_device *mfe_dvbdev; /* frontend device in use */ + struct mutex mfe_lock; /* access lock for thread creation */ + +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + struct media_device *mdev; + struct media_entity *conn; + struct media_pad *conn_pads; +#endif +}; + +/** + * struct dvb_device - represents a DVB device node + * + * @list_head: List head with all DVB devices + * @fops: pointer to struct file_operations + * @adapter: pointer to the adapter that holds this device node + * @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, + * DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET + * @minor: devnode minor number. Major number is always DVB_MAJOR. + * @id: device ID number, inside the adapter + * @readers: Initialized by the caller. Each call to open() in Read Only mode + * decreases this counter by one. + * @writers: Initialized by the caller. Each call to open() in Read/Write + * mode decreases this counter by one. + * @users: Initialized by the caller. Each call to open() in any mode + * decreases this counter by one. + * @wait_queue: wait queue, used to wait for certain events inside one of + * the DVB API callers + * @kernel_ioctl: callback function used to handle ioctl calls from userspace. + * @name: Name to be used for the device at the Media Controller + * @entity: pointer to struct media_entity associated with the device node + * @pads: pointer to struct media_pad associated with @entity; + * @priv: private data + * @intf_devnode: Pointer to media_intf_devnode. Used by the dvbdev core to + * store the MC device node interface + * @tsout_num_entities: Number of Transport Stream output entities + * @tsout_entity: array with MC entities associated to each TS output node + * @tsout_pads: array with the source pads for each @tsout_entity + * + * This structure is used by the DVB core (frontend, CA, net, demux) in + * order to create the device nodes. Usually, driver should not initialize + * this struct diretly. + */ +struct dvb_device { + struct list_head list_head; + const struct file_operations *fops; + struct dvb_adapter *adapter; + int type; + int minor; + u32 id; + + /* in theory, 'users' can vanish now, + but I don't want to change too much now... */ + int readers; + int writers; + int users; + + wait_queue_head_t wait_queue; + /* don't really need those !? -- FIXME: use video_usercopy */ + int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg); + + /* Needed for media controller register/unregister */ +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + const char *name; + + /* Allocated and filled inside dvbdev.c */ + struct media_intf_devnode *intf_devnode; + + unsigned tsout_num_entities; + struct media_entity *entity, *tsout_entity; + struct media_pad *pads, *tsout_pads; +#endif + + void *priv; +}; + +/** + * dvb_register_adapter - Registers a new DVB adapter + * + * @adap: pointer to struct dvb_adapter + * @name: Adapter's name + * @module: initialized with THIS_MODULE at the caller + * @device: pointer to struct device that corresponds to the device driver + * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter; + * to select among them. Typically, initialized with: + * DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums) + */ +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums); + +/** + * dvb_unregister_adapter - Unregisters a DVB adapter + * + * @adap: pointer to struct dvb_adapter + */ +int dvb_unregister_adapter(struct dvb_adapter *adap); + +/** + * dvb_register_device - Registers a new DVB device + * + * @adap: pointer to struct dvb_adapter + * @pdvbdev: pointer to the place where the new struct dvb_device will be + * stored + * @template: Template used to create &pdvbdev; + * @priv: private data + * @type: type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND, + * %DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA, + * %DVB_DEVICE_NET + * @demux_sink_pads: Number of demux outputs, to be used to create the TS + * outputs via the Media Controller. + */ +int dvb_register_device(struct dvb_adapter *adap, + struct dvb_device **pdvbdev, + const struct dvb_device *template, + void *priv, + int type, + int demux_sink_pads); + +/** + * dvb_unregister_device - Unregisters a DVB device + * + * @dvbdev: pointer to struct dvb_device + */ +void dvb_unregister_device(struct dvb_device *dvbdev); + +#ifdef CONFIG_MEDIA_CONTROLLER_DVB +/** + * dvb_create_media_graph - Creates media graph for the Digital TV part of the + * device. + * + * @adap: pointer to struct dvb_adapter + * @create_rf_connector: if true, it creates the RF connector too + * + * This function checks all DVB-related functions at the media controller + * entities and creates the needed links for the media graph. It is + * capable of working with multiple tuners or multiple frontends, but it + * won't create links if the device has multiple tuners and multiple frontends + * or if the device has multiple muxes. In such case, the caller driver should + * manually create the remaining links. + */ +__must_check int dvb_create_media_graph(struct dvb_adapter *adap, + bool create_rf_connector); + +static inline void dvb_register_media_controller(struct dvb_adapter *adap, + struct media_device *mdev) +{ + adap->mdev = mdev; +} + +static inline struct media_device +*dvb_get_media_controller(struct dvb_adapter *adap) +{ + return adap->mdev; +} +#else +static inline +int dvb_create_media_graph(struct dvb_adapter *adap, + bool create_rf_connector) +{ + return 0; +}; +#define dvb_register_media_controller(a, b) {} +#define dvb_get_media_controller(a) NULL +#endif + +int dvb_generic_open (struct inode *inode, struct file *file); +int dvb_generic_release (struct inode *inode, struct file *file); +long dvb_generic_ioctl (struct file *file, + unsigned int cmd, unsigned long arg); + +/* we don't mess with video_usercopy() any more, +we simply define out own dvb_usercopy(), which will hopefully become +generic_usercopy() someday... */ + +int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, unsigned int cmd, void *arg)); + +/** generic DVB attach function. */ +#ifdef CONFIG_MEDIA_ATTACH +#define dvb_attach(FUNCTION, ARGS...) ({ \ + void *__r = NULL; \ + typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ + if (__a) { \ + __r = (void *) __a(ARGS); \ + if (__r == NULL) \ + symbol_put(FUNCTION); \ + } else { \ + printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \ + } \ + __r; \ +}) + +#define dvb_detach(FUNC) symbol_put_addr(FUNC) + +#else +#define dvb_attach(FUNCTION, ARGS...) ({ \ + FUNCTION(ARGS); \ +}) + +#define dvb_detach(FUNC) {} + +#endif + +#endif /* #ifndef _DVBDEV_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER new file mode 100644 index 000000000000..8f4a86041ed0 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER @@ -0,0 +1,499 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. +We sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt new file mode 100644 index 000000000000..1d6a01c7dccd --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt @@ -0,0 +1,61 @@ +April 28, 2011 + +Linux CIMaX+ Kernel driver. +Release Code version: + +DISCLAIMER +---------- + +This is a Smardtv' Linux Kernel driver for use with +the CIMaX+ USB reference board hardware. + +IMPORTANT NOTE +-------------- + +This packages contains a Linux Kernel driver to be installed in the +/lib/modules target directory in order to be loaded automaticaly. + +1. High level driver: cimax+usb_driver.ko + This driver provide the high level interface to control the CIMaX+ USB interface. + +2. Firmware + To have a functional hardware, the firmware must be uploaded to the device. + + The firmwares is delivered in 2 files for dedicated usage and must be + installed in the Linux firmware directory on the target board: + + - /lib/firmware + + A) CIMaX+ firmware binary file + Copy the following firmware file to the /lib/firmware directory: + - firmware/cimax+_usbdvb.bin + + B) CIMaX+ configuration file + Copy the following firmware file to the /lib/firmware directory: + - firmware/cimax+usb.cfg + + +BUILD AND INSTALLATION INSTRUCTIONS +----------------------------------- + +2. Building LINUX USB DVB driver + On the target machine performs the following commands: + + 1. cd src + 2. make + 3. make install + +3. Installing firmware files + On the target machine performs the following command: + + 1. cp firmware/*.* /lib/firmware/ + +4. Installing rules file + 1. cp src/99-cimax+usb.rules /etc/udev/rules.d/ + 2. udevadm control --reload-rules + +5. Build modules dependencies + On the target machine performs the following command: + + 1. depmod -a + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules new file mode 100644 index 000000000000..82af37083592 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules @@ -0,0 +1,4 @@ +BUS=="usb", ACTION=="add", SYSFS{idProduct}=="2F00", SYSFS{idVendor}=="1B0D" +KERNEL=="cimaxusb[0-9]", GROUP="users" + + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt new file mode 100644 index 000000000000..23de038208c9 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt @@ -0,0 +1,85 @@ +The following examples shows how to use the cimax+usb driver. +All structures and macro are defined in file cimax+usb-driver.h. + + +1.Open the device cimax+usb +=========================== +/* open device */ +dev = open("/dev/cimaxusb0", O_RDWR); +/* select USB alt_setting */ +ioctl(dev, DEVICE_IOC_SELECT_INTF, alt_setting); + + +2.Close the device cimax+usb +============================ +/* unlock read queue */ +ioctl(dev, DEVICE_IOC_UNLOCK_READ, 0); +/* close device */ +close(dev); + + +3.Send a CI message to a CAM through the device +=============================================== +/* Send CAM A Reset command */ +uint8 command[5] = {0x01, /* Command */ + 0x01, /* Counter */ + 0x00, /* MSB data size */ + 0x01, /* LSB data size */ + 0x00}; /* data */ +uint8 response[4100]; +struct ioctl_data_s stData; +stData.txData = command; +stData.txSize = 5; +stData.rxData = response; +stData.rxSize = 4100; +ioctl(dev, DEVICE_IOC_CI_WRITE, &stData); + +/* Send CAM B Get CIS command */ +uint8 command[5] = {0x82, /* Command */ + 0x01, /* Counter */ + 0x00, /* MSB data size */ + 0x00}; /* LSB data size */ +uint8 response[4100]; +struct ioctl_data_s stData; +stData.txData = command; +stData.txSize = 4; +stData.rxData = response; +stData.rxSize = 4100; +ioctl(dev, DEVICE_IOC_CI_WRITE, &stData); + + +4.Send a Transport Stream to a CAM through the device +===================================================== +/* Send to CAM A */ +struct rw_data_s rwData; +rwData.type = DEVICE_TYPE_TS_WRITE; +rwData.moduleId = 0; /* CAM A */ +rwData.data = stream; +rwData.size = size; +rwData.copiedSize = 0; +write(dev, &rwData, sizeof(struct rw_data_s)); + + +5.Read a Transport Stream from a CAM through the device +======================================================= +/* Read from CAM B */ +struct rw_data_s rwData; +rwData.type = DEVICE_TYPE_TS_READ; +rwData.moduleId = 1; /* CAM B */ +rwData.data = stream; +rwData.size = size; +rwData.copiedSize = 0; +read(dev, &rwData, sizeof(struct rw_data_s)); + + +6.Read a CI message from a CAM through the device +================================================= +/* Read from CAM A */ +uint8 response[4096]; +struct rw_data_s rwData; +rwData.type = DEVICE_TYPE_CI_READ; +rwData.moduleId = 0; /* CAM A */ +rwData.data = response; +rwData.size = 4096; +rwData.copiedSize = 0; +read(dev, &rwData, sizeof(struct rw_data_s)); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile new file mode 100644 index 000000000000..bc7994599d3f --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile @@ -0,0 +1,35 @@ +TARGET = cimax+usb_driver +OBJS = cimax+usb_driver.o +MDIR = drivers/misc + +ccflags-y = -DEXPORT_SYMTAB +#ccflags-y = -DEXPORT_SYMTAB -DDEBUG +CURRENT = $(shell uname -r) +KDIR = /lib/modules/$(CURRENT)/build +PWD = $(shell pwd) +DEST = /lib/modules/$(CURRENT)/kernel/$(MDIR) + +obj-m := $(TARGET).o +cimax+usb_driver-y := cimax+usb-driver.o cimax+usb_fw.o +cimax+usb_driver-y += cimax+usb_config.o +cimax+usb_driver-y += cimax+usb_time.o + +default: + make -C /usr/src/linux SUBDIRS=$(PWD) modules +# make -C /lib/modules/`uname -r`/build M=$(PWD) modules + +$(TARGET).o: $(OBJS) + $(LD) $(LD_RFLAG) -r -o $@ $(OBJS) + +ifneq (,$(findstring 2.4.,$(CURRENT))) +install: + su -c "cp -v $(TARGET).o $(DEST) && /sbin/depmod -a" +else +install: + su -c "cp -v $(TARGET).ko $(DEST) && /sbin/depmod -a" +endif + +clean: + -rm -f *.o *.ko .*.cmd .*.flags *.mod.c + +-include $(KDIR)/Rules.make diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h new file mode 100644 index 000000000000..f93fef5d2274 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h @@ -0,0 +1,424 @@ +/**************************************************************************//** + * @file bodydef.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#ifndef __BODYDEF_H +#define __BODYDEF_H + +struct reg_s { + __u8 RegisterName[50]; + __u16 RegAddr; +}; + +/*======================================================================= + Input/Output Ports and Data Direction Registers +=======================================================================*/ +struct reg_s cimax_reg_map[] = { + {"BUFFIN_CFG" , 0x0000}, + {"BUFFIN_ADDR_LSB" , 0x0001}, + {"BUFFIN_ADDR_MSB" , 0x0002}, + {"BUFFIN_DATA" , 0x0003}, + {"BUFFOUT_CFG" , 0x0004}, + {"BUFFOUT_ADDR_LSB" , 0x0005}, + {"BUFFOUT_ADDR_MSB" , 0x0006}, + {"BUFFOUT_DATA" , 0x0007}, + {"BOOT_Key" , 0x0008}, + {"BOOT_Status" , 0x0009}, + {"BOOT_Test " , 0x000A}, + {"RxDMA_Ctrl" , 0x0010}, + {"RxDMA_Status" , 0x0011}, + {"RxDMA_DbgL" , 0x0012}, + {"RxDMA_DbgH" , 0x0013}, + {"SPI_Slave_Ctrl" , 0x0018}, + {"SPI_Slave_Status" , 0x0019}, + {"SPI_Slave_Rx" , 0x001A}, + {"SPI_Slave_Tx" , 0x001B}, + {"SPI_Slave_Mask" , 0x001C}, + {"UCSG_Ctrl" , 0x0020}, + {"UCSG_Status" , 0x0021}, + {"UCSG_RxData" , 0x0022}, + {"UCSG_TxData" , 0x0023}, + {"PCtrl_Ctrl" , 0x0028}, + {"PCtrl_Status" , 0x0029}, + {"PCtrl_NbByte_LSB" , 0x002A}, + {"PCtrl_NbByte_MSB" , 0x002B}, + {"SPI_Master_Ctl" , 0x0030}, + {"SPI_Master_NCS" , 0x0031}, + {"SPI_Master_Status" , 0x0032}, + {"SPI_Master_TxBuf" , 0x0033}, + {"SPI_Master_RxBuf" , 0x0034}, + {"BISTRAM_Ctl" , 0x0038}, + {"BISTRAM_Bank" , 0x0039}, + {"BISTRAM_Pat" , 0x003A}, + {"BISTRAM_SM" , 0x003B}, + {"BISTRAM_AddrLSB" , 0x003C}, + {"BISTROM_Config" , 0x0040}, + {"BISTROM_SignatureLSB" , 0x0041}, + {"BISTROM_SignatureMSB" , 0x0042}, + {"BISTROM_StartAddrLSB" , 0x0043}, + {"BISTROM_StartAddrMSB" , 0x0044}, + {"BISTROM_StopAddrLSB" , 0x0045}, + {"BISTROM_StopAddrMSB" , 0x0046}, + {"CkMan_Config" , 0x0048}, + {"CkMan_Select" , 0x0049}, + {"CkMan_Test" , 0x004A}, + {"Revision_Number" , 0x004B}, + {"CkMan_PD_Key" , 0x004C}, + {"USB_Power_Mode" , 0x004D}, + {"ResMan_Config" , 0x0050}, + {"ResMan_Status" , 0x0051}, + {"ResMan_WD" , 0x0052}, + {"ResMan_WD_MSB" , 0x0053}, + {"TxDMA_Ctrl" , 0x0058}, + {"TxDMA_Status" , 0x0059}, + {"TxDMA_StartAddrL" , 0x005A}, + {"TxDMA_StartAddrH" , 0x005B}, + {"TxDMA_StopAddrL" , 0x005C}, + {"TxDMA_StopAddrH" , 0x005D}, + {"CPU_Test" , 0x0060}, + {"IrqMan_Config0" , 0x0068}, + {"IrqMan_Config1" , 0x0069}, + {"IrqMan_Irq0" , 0x006A}, + {"IrqMan_NMI" , 0x006B}, + {"IrqMan_SleepKey" , 0x006C}, + {"Tim_Config" , 0x0070}, + {"Tim_Value_LSB" , 0x0071}, + {"Tim_Value_MSB" , 0x0072}, + {"Tim_Comp_LSB" , 0x0073}, + {"Tim_Comp_MSB" , 0x0074}, + {"TI_Config" , 0x0076}, + {"TI_Data" , 0x0077}, + {"TI_Reg0" , 0x0078}, + {"TI_Reg1" , 0x0079}, + {"TI_Reg2" , 0x007A}, + {"TI_Reg3" , 0x007B}, + {"TI_Reg4" , 0x007C}, + {"TI_ROM1" , 0x007D}, + {"TI_ROM2" , 0x007E}, + {"TI_ROM3" , 0x007F}, + {"DVBCI_START_ADDR" , 0x0100}, + {"DVBCI_END_ADDR" , 0x017F}, + {"DATA" , 0x0180}, + {"CTRL" , 0x0181}, + {"QB_HOST" , 0x0182}, + {"LEN_HOST_LSB" , 0x0183}, + {"LEN_HOST_MSB" , 0x0184}, + {"FIFO_TX_TH_LSB" , 0x0185}, + {"FIFO_TX_TH_MSB" , 0x0186}, + {"FIFO_TX_D_NB_LSB" , 0x0187}, + {"FIFO_TX_D_NB_MSB" , 0x0188}, + {"QB_MOD_CURR" , 0x0189}, + {"LEN_MOD_CURR_LSB" , 0x018A}, + {"LEN_MOD_CURR_MSB" , 0x018B}, + {"QB_MOD" , 0x018C}, + {"LEN_MOD_LSB" , 0x018D}, + {"LEN_MOD_MSB" , 0x018E}, + {"FIFO_RX_TH_LSB" , 0x018F}, + {"FIFO_RX_TH_MSB" , 0x0190}, + {"FIFO_RX_D_NB_LSB" , 0x0191}, + {"FIFO_RX_D_NB_MSB" , 0x0192}, + {"IT_STATUS_0" , 0x0193}, + {"IT_STATUS_1" , 0x0194}, + {"IT_MASK_0" , 0x0195}, + {"IT_MASK_1" , 0x0196}, + {"IT_HOST_PIN_CFG" , 0x0200}, + {"CFG_0" , 0x0201}, + {"CFG_1" , 0x0202}, + {"CFG_2" , 0x0203}, + {"IT_HOST" , 0x0204}, + {"MOD_IT_STATUS" , 0x0205}, + {"MOD_IT_MASK" , 0x0206}, + {"MOD_CTRL_A" , 0x0207}, + {"MOD_CTRL_B" , 0x0208}, + {"DEST_SEL" , 0x0209}, + {"CAM_MSB_ADD" , 0x020A}, + {"GPIO0_DIR" , 0x020B}, + {"GPIO0_DATA_IN" , 0x020C}, + {"GPIO0_DATA_OUT" , 0x020D}, + {"GPIO0_STATUS" , 0x020E}, + {"GPIO0_IT_MASK" , 0x020F}, + {"GPIO0_DFT" , 0x0210}, + {"GPIO0_MASK_DATA" , 0x0211}, + {"GPIO1_DIR" , 0x0212}, + {"GPIO1_DATA_IN" , 0x0213}, + {"GPIO1_DATA_OUT" , 0x0214}, + {"GPIO1_STATUS" , 0x0215}, + {"GPIO1_IT_MASK" , 0x0216}, + {"MEM_ACC_TIME_A" , 0x0217}, + {"MEM_ACC_TIME_B" , 0x0218}, + {"IO_ACC_TIME_A" , 0x0219}, + {"IO_ACC_TIME_B" , 0x021A}, + {"EXT_CH_ACC_TIME_A" , 0x021B}, + {"EXT_CH_ACC_TIME_B" , 0x021C}, + {"PAR_IF_0" , 0x021D}, + {"PAR_IF_1" , 0x021E}, + {"PAR_IF_CTRL" , 0x021F}, + {"PCK_LENGTH" , 0x0220}, + {"USB2TS_CTRL" , 0x0221}, + {"USB2TS0_RDL" , 0x0222}, + {"USB2TS1_RDL" , 0x0223}, + {"TS2USB_CTRL" , 0x0224}, + {"TSOUT_PAR_CTRL" , 0x0225}, + {"TSOUT_PAR_CLK_SEL" , 0x0226}, + {"S2P_CH0_CTRL" , 0x0227}, + {"S2P_CH1_CTRL" , 0x0228}, + {"P2S_CH0_CTRL" , 0x0229}, + {"P2S_CH1_CTRL" , 0x022A}, + {"TS_IT_STATUS" , 0x022B}, + {"TS_IT_MASK" , 0x022C}, + {"IN_SEL" , 0x022D}, + {"OUT_SEL" , 0x022E}, + {"ROUTER_CAM_CH" , 0x022F}, + {"ROUTER_CAM_MOD" , 0x0230}, + {"FIFO_CTRL" , 0x0231}, + {"FIFO1_2_STATUS" , 0x0232}, + {"FIFO3_4_STATUS" , 0x0233}, + {"GAP_REMOVER_CH0_CTRL" , 0x0234}, + {"GAP_REMOVER_CH1_CTRL" , 0x0235}, + {"SYNC_RTV_CTRL" , 0x0236}, + {"SYNC_RTV_CH0_SYNC_NB" , 0x0237}, + {"SYNC_RTV_CH0_PATTERN" , 0x0238}, + {"SYNC_RTV_CH1_SYNC_NB" , 0x0239}, + {"SYNC_RTV_CH1_PATTERN" , 0x023A}, + {"SYNC_RTV_OFFSET_PATT" , 0x023B}, + {"CTRL_FILTER" , 0x023D}, + {"PID_EN_FILTER_CH0" , 0x023E}, + {"PID_EN_FILTER_CH1" , 0x023F}, + {"PID_LSB_FILTER_CH0_0" , 0x0240}, + {"PID_MSB_FILTER_CH0_0" , 0x0241}, + {"PID_LSB_FILTER_CH0_1" , 0x0242}, + {"PID_MSB_FILTER_CH0_1" , 0x0243}, + {"PID_LSB_FILTER_CH0_2" , 0x0244}, + {"PID_MSB_FILTER_CH0_2" , 0x0245}, + {"PID_LSB_FILTER_CH0_3" , 0x0246}, + {"PID_MSB_FILTER_CH0_3" , 0x0247}, + {"PID_LSB_FILTER_CH0_4" , 0x0248}, + {"PID_MSB_FILTER_CH0_4" , 0x0249}, + {"PID_LSB_FILTER_CH0_5" , 0x024A}, + {"PID_MSB_FILTER_CH0_5" , 0x024B}, + {"PID_LSB_FILTER_CH0_6" , 0x024C}, + {"PID_MSB_FILTER_CH0_6" , 0x024D}, + {"PID_LSB_FILTER_CH0_7" , 0x024E}, + {"PID_MSB_FILTER_CH0_7" , 0x024F}, + {"PID_LSB_FILTER_CH1_0" , 0x0260}, + {"PID_MSB_FILTER_CH1_0" , 0x0261}, + {"PID_LSB_FILTER_CH1_1" , 0x0262}, + {"PID_MSB_FILTER_CH1_1" , 0x0263}, + {"PID_LSB_FILTER_CH1_2" , 0x0264}, + {"PID_MSB_FILTER_CH1_2" , 0x0265}, + {"PID_LSB_FILTER_CH1_3" , 0x0266}, + {"PID_MSB_FILTER_CH1_3" , 0x0267}, + {"PID_LSB_FILTER_CH1_4" , 0x0268}, + {"PID_MSB_FILTER_CH1_4" , 0x0269}, + {"PID_LSB_FILTER_CH1_5" , 0x026A}, + {"PID_MSB_FILTER_CH1_5" , 0x026B}, + {"PID_LSB_FILTER_CH1_6" , 0x026C}, + {"PID_MSB_FILTER_CH1_6" , 0x026D}, + {"PID_LSB_FILTER_CH1_7" , 0x026E}, + {"PID_MSB_FILTER_CH1_7" , 0x026F}, + {"PID_OLD_LSB_REMAPPER_0" , 0x0280}, + {"PID_OLD_MSB_REMAPPER_0" , 0x0281}, + {"PID_OLD_LSB_REMAPPER_1" , 0x0282}, + {"PID_OLD_MSB_REMAPPER_1" , 0x0283}, + {"PID_OLD_LSB_REMAPPER_2" , 0x0284}, + {"PID_OLD_MSB_REMAPPER_2" , 0x0285}, + {"PID_OLD_LSB_REMAPPER_3" , 0x0286}, + {"PID_OLD_MSB_REMAPPER_3" , 0x0287}, + {"PID_OLD_LSB_REMAPPER_4" , 0x0288}, + {"PID_OLD_MSB_REMAPPER_4" , 0x0289}, + {"PID_OLD_LSB_REMAPPER_5" , 0x028A}, + {"PID_OLD_MSB_REMAPPER_5" , 0x028B}, + {"PID_OLD_LSB_REMAPPER_6" , 0x028C}, + {"PID_OLD_MSB_REMAPPER_6" , 0x028D}, + {"PID_OLD_LSB_REMAPPER_7" , 0x028E}, + {"PID_OLD_MSB_REMAPPER_7" , 0x028F}, + {"PID_NEW_LSB_REMAPPER_0" , 0x02A0}, + {"PID_NEW_MSB_REMAPPER_0" , 0x02A1}, + {"PID_NEW_LSB_REMAPPER_1" , 0x02A2}, + {"PID_NEW_MSB_REMAPPER_1" , 0x02A3}, + {"PID_NEW_LSB_REMAPPER_2" , 0x02A4}, + {"PID_NEW_MSB_REMAPPER_2" , 0x02A5}, + {"PID_NEW_LSB_REMAPPER_3" , 0x02A6}, + {"PID_NEW_MSB_REMAPPER_3" , 0x02A7}, + {"PID_NEW_LSB_REMAPPER_4" , 0x02A8}, + {"PID_NEW_MSB_REMAPPER_4" , 0x02A9}, + {"PID_NEW_LSB_REMAPPER_5" , 0x02AA}, + {"PID_NEW_MSB_REMAPPER_5" , 0x02AB}, + {"PID_NEW_LSB_REMAPPER_6" , 0x02AC}, + {"PID_NEW_MSB_REMAPPER_6" , 0x02AD}, + {"PID_NEW_LSB_REMAPPER_7" , 0x02AE}, + {"PID_NEW_MSB_REMAPPER_7" , 0x02AF}, + {"MERGER_DIV_MICLK" , 0x02C0}, + {"PID_AND_SYNC_REMAPPER_CTRL" , 0x02C1}, + {"PID_EN_REMAPPER" , 0x02C2}, + {"SYNC_SYMBOL" , 0x02C3}, + {"PID_AND_SYNC_REMAPPER_INV_CTRL" , 0x02C4}, + {"BITRATE_CH0_LSB" , 0x02C5}, + {"BITRATE_CH0_MSB" , 0x02C6}, + {"BITRATE_CH1_LSB" , 0x02C7}, + {"BITRATE_CH1_MSB" , 0x02C8}, + {"STATUS_CLK_SWITCH_0" , 0x02C9}, + {"STATUS_CLK_SWITCH_1" , 0x02CA}, + {"RESET_CLK_SWITCH_0" , 0x02CB}, + {"RESET_CLK_SWITCH_1" , 0x02CC}, + {"PAD_DRVSTR_CTRL" , 0x02CD}, + {"PAD_PUPD_CTRL" , 0x02CE}, + {"PRE_HEADER_ADDER_CH0_0" , 0x02D0}, + {"PRE_HEADER_ADDER_CH0_1" , 0x02D1}, + {"PRE_HEADER_ADDER_CH0_2" , 0x02D2}, + {"PRE_HEADER_ADDER_CH0_3" , 0x02D3}, + {"PRE_HEADER_ADDER_CH0_4" , 0x02D4}, + {"PRE_HEADER_ADDER_CH0_5" , 0x02D5}, + {"PRE_HEADER_ADDER_CH0_6" , 0x02D6}, + {"PRE_HEADER_ADDER_CH0_7" , 0x02D7}, + {"PRE_HEADER_ADDER_CH0_8" , 0x02D8}, + {"PRE_HEADER_ADDER_CH0_9" , 0x02D9}, + {"PRE_HEADER_ADDER_CH0_10" , 0x02DA}, + {"PRE_HEADER_ADDER_CH0_11" , 0x02DB}, + {"PRE_HEADER_ADDER_CH1_0" , 0x02E0}, + {"PRE_HEADER_ADDER_CH1_1" , 0x02E1}, + {"PRE_HEADER_ADDER_CH1_2" , 0x02E2}, + {"PRE_HEADER_ADDER_CH1_3" , 0x02E3}, + {"PRE_HEADER_ADDER_CH1_4" , 0x02E4}, + {"PRE_HEADER_ADDER_CH1_5" , 0x02E5}, + {"PRE_HEADER_ADDER_CH1_6" , 0x02E6}, + {"PRE_HEADER_ADDER_CH1_7" , 0x02E7}, + {"PRE_HEADER_ADDER_CH1_8" , 0x02E8}, + {"PRE_HEADER_ADDER_CH1_9" , 0x02E9}, + {"PRE_HEADER_ADDER_CH1_10" , 0x02EA}, + {"PRE_HEADER_ADDER_CH1_11" , 0x02EB}, + {"PRE_HEADER_ADDER_CTRL" , 0x02EC}, + {"PRE_HEADER_ADDER_LEN" , 0x02ED}, + {"PRE_HEADER_REMOVER_CTRL" , 0x02EE}, + {"FSM_DVB" , 0x02F0}, + {"TS2USB_FSM_DEBUG" , 0x02F2}, + {"TSOUT_PAR_FSM_DEBUG" , 0x02F3}, + {"GAP_REMOVER_FSM_DEBUG" , 0x02F4}, + {"PID_AND_SYNC_REMAPPER_FSM_DEBUG" , 0x02F5}, + {"PRE_HEADER_ADDER_FSM_DEBUG" , 0x02F6}, + {"SYNC_RTV_FSM_DEBUG" , 0x02F7}, + {"CHECK_PHY_CLK" , 0x0E00}, + {"CONTROL1" , 0x0E01}, + {"WAKE_UP" , 0x0E02}, + {"CONTROL2" , 0x0E03}, + {"PHY_RELATED" , 0x0E04}, + {"EP_CFG" , 0x0E05}, + {"MAX_PKT_EP1L" , 0x0E06}, + {"MAX_PKT_EP1H" , 0x0E07}, + {"MAX_PKT_EP2L" , 0x0E08}, + {"MAX_PKT_EP2H" , 0x0E09}, + {"MAX_PKT_EP3L" , 0x0E0A}, + {"MAX_PKT_EP3H" , 0x0E0B}, + {"MAX_PKT_EP4L" , 0x0E0C}, + {"MAX_PKT_EP4H" , 0x0E0D}, + {"EPS_STALL_SET" , 0x0E10}, + {"EPS_STALL_CLR" , 0x0E11}, + {"EPS_ENABLE" , 0x0E12}, + {"DMA_ACC_EPS" , 0x0E13}, + {"CPU_ACC_EPS_EN" , 0x0E14}, + {"SETUP_BYTE0" , 0x0E15}, + {"SETUP_BYTE1" , 0x0E16}, + {"SETUP_BYTE2" , 0x0E17}, + {"SETUP_BYTE3" , 0x0E18}, + {"SETUP_BYTE4" , 0x0E19}, + {"SETUP_BYTE5" , 0x0E1A}, + {"SETUP_BYTE6" , 0x0E1B}, + {"SETUP_BYTE7" , 0x0E1C}, + {"SETUP_DT_VLD" , 0x0E1D}, + {"CLR_EPS_TOG" , 0x0E1E}, + {"EP0_CTRL" , 0x0E20}, + {"EP0_DATA_CNT" , 0x0E21}, + {"EP0_DATA" , 0x0E22}, + {"EP1_CTRL" , 0x0E30}, + {"EP1_DATA_CNTL" , 0x0E31}, + {"EP1_DATA_CNTH" , 0x0E32}, + {"EP1_DATA" , 0x0E33}, + {"EP1_HEADER" , 0x0E34}, + {"EP2_CTRL" , 0x0E40}, + {"EP2_DATA_CNTL" , 0x0E41}, + {"EP2_DATA_CNTH" , 0x0E42}, + {"EP2_DATA" , 0x0E43}, + {"EP2_HEADER" , 0x0E44}, + {"EP3_DATA_CNTL" , 0x0E50}, + {"EP3_DATA_CNTH" , 0x0E51}, + {"EP3_DATA" , 0x0E52}, + {"EP3_HEADER" , 0x0E53}, + {"EP3_HEADER_CNT" , 0x0E54}, + {"EP3_HEADER_DATA" , 0x0E55}, + {"EP4_DATA_CNTL" , 0x0E60}, + {"EP4_DATA_CNTH" , 0x0E61}, + {"EP4_DATA" , 0x0E62}, + {"EP4_HEADER" , 0x0E63}, + {"EP4_HEADER_CNT" , 0x0E64}, + {"EP4_HEADER_DATA" , 0x0E65}, + {"EP5_CTRL" , 0x0E70}, + {"EP5_DATA_CNTL" , 0x0E71}, + {"EP5_DATA_CNTH" , 0x0E72}, + {"EP5_DATA" , 0x0E73}, + {"MAX_PKT_EP5L" , 0x0E74}, + {"MAX_PKT_EP5H" , 0x0E75}, + {"EP6_DATA_CNTL" , 0x0E80}, + {"EP6_DATA_CNTH" , 0x0E81}, + {"EP6_DATA" , 0x0E82}, + {"MAX_PKT_EP6L" , 0x0E83}, + {"MAX_PKT_EP6H" , 0x0E84}, + {"FRAME_NUML" , 0x0E90}, + {"FRAME_NUMH" , 0x0E91}, + {"FRAME_TIMEL" , 0x0E92}, + {"FRAME_TIMEH" , 0x0E93}, + {"STC_DIVL" , 0x0E94}, + {"STC_DIVM" , 0x0E95}, + {"STC_DIVH" , 0x0E96}, + {"USB_STATUS" , 0x0E97}, + {"DEV_STATE1" , 0x0E98}, + {"DEV_STATE2" , 0x0E99}, + {"DEV_STATE3" , 0x0E9A}, + {"DEV_STATE4" , 0x0E9B}, + {"INTR_EN1" , 0x0EA0}, + {"INTR_EN2" , 0x0EA1}, + {"INTR_EN3" , 0x0EA2}, + {"INTR_EN4" , 0x0EA3}, + {"INTR_SRC1" , 0x0EB0}, + {"INTR_SRC2" , 0x0EB1}, + {"INTR_SRC3" , 0x0EB2}, + {"INTR_SRC4" , 0x0EB3}, + {"INTR_FLAG1" , 0x0EC0}, + {"INTR_FLAG2" , 0x0EC1}, + {"INTR_FLAG3" , 0x0EC2}, + {"INTR_FLAG4" , 0x0EC3}, + {"EP0_INAK_CNT" , 0x0ED0}, + {"EP0_ONAK_CNT" , 0x0ED1}, + {"EP1_NAK_CNT" , 0x0ED2}, + {"EP2_NAK_CNT" , 0x0ED3}, + {"EP3_NAK_CNT" , 0x0ED4}, + {"EP4_NAK_CNT" , 0x0ED5}, + {"EP5_NAK_CNT" , 0x0ED6}, + {"EP6_NAK_CNT" , 0x0ED7}, + {"NAK_CNT_LEVEL" , 0x0ED8}, + {"CC2_Buffer_out" , 0x2000}, + {"CC2_Buffer_in" , 0x4000}, + {"nmb_vector_address_lsb" , 0xFFFA}, + {"nmb_vector_address_msb" , 0xFFFB}, + {"reset_vector_address_lsb" , 0xFFFC}, + {"reset_vector_address_msb" , 0xFFFD}, + {"irb_vector_address_lsb" , 0xFFFE}, + {"irb_vector_address_msb" , 0xFFFF} +}; +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c new file mode 100644 index 000000000000..43cdcde5b8eb --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c @@ -0,0 +1,2535 @@ +/**************************************************************************//** + * @file cimax+usb-driver.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#define FRBIT +/*#define DEBUG*/ +/*#define DEBUG_BITRATE*/ +/*#define DEBUG_ISOC_IN*/ +/*#define DEBUG_ISOC_OUT*/ +/*#define DEBUG_CONTINUITY*/ + +/****************************************************************************** + * Include + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cimax+usb-driver.h" +#include "cimax+usb_fw.h" +#include "cimax+usb_config.h" +#ifdef TIMESTAMP +#include "cimax+usb_time.h" +#endif +#include "../../aml_cimax_usb_priv.h" + +/****************************************************************************** + * Defines + *****************************************************************************/ +#define DRIVER_VERSION "v1.1.2" +#define DRIVER_AUTHOR "Bruno Tonelli, tonelli@smardtv.com" +#define DRIVER_DESC "CIMaX+ USB Driver for Linux (c)2009-2011" + +#define DRIVER_MAX_NUMBER 1 + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); + +/****************************************************************************** + * Structures + ******************************************************************************/ +/****************************************************************************** + * Globals + ******************************************************************************/ +#ifdef FRBIT +int CimaxCfg = 1; +module_param_named(CimaxCfg, CimaxCfg, int, 0644); +MODULE_PARM_DESC(CimaxCfg, "Turn on/off configuration of CIMaX+ (default: on)"); +int CimaxDwnl = 1; +module_param_named(CimaxDwnl, CimaxDwnl, int, 0644); +MODULE_PARM_DESC(CimaxDwnl, "Enable upload of FW in CIMaX+ chip (default: on)"); +#endif + +static struct device_s *gdevice; +static unsigned int gdeviceNumber; + +static struct usb_driver device_driver; +static struct timespec gStart; + +static __u8 nullHeader[] = { + 0x47, 0x1F, 0xFF, 0x1F, 0xFA, 0xDE, 0xBA, 0xBE +}; + +static struct bulk_timer_s gbulk_timer[DEVICE_NUM_CAM]; +int (*cimax_usb_dev_add)(struct device_s *device, int id); +int (*cimax_usb_dev_remove)(struct device_s *device, int id); + +#ifdef TIMESTAMP +static int bSetTimestamps; +#endif + +/****************************************************************************** + * Functions + ******************************************************************************/ +#ifdef DEBUG_CONTINUITY +#define TS_MAXPIDS 8192 /* max value of a PID */ +unsigned char tab_cc[TS_MAXPIDS]; + +__u16 get_ts_pid(unsigned char *pid) +{ + __u16 pp = 0; + + pp = (pid[0] & 0X1f)<<8; + pp |= pid[1]; + + return pp; +} + +static void init_tab_cc(void) +{ + memset(tab_cc, 0xff, TS_MAXPIDS); +} + +static int dbg_cc(unsigned char *buf) +{ + int pid; + unsigned char cc; + + if (buf[0] != DEVICE_MPEG2_SYNC_BYTE) { + err("Out Of Sync: "); + return -1; + } + + pid = get_ts_pid(buf + 1); + + if (!(buf[3] & 0x10)) /* no payload?*/ + return 0; + + if (buf[1] & 0x80) + err("Error in TS for PID: %d\n", pid); + + /* Check continuity count*/ + cc = tab_cc[pid]; + if (cc == 255) + cc = (buf[3] & 15); + else { + cc = ((cc) + 1) & 15; + if (cc != (buf[3] & 15)) { + /* Otherwise, this is a real corruption */ + err("pid %d cc %d expected cc %d actual\n", + pid, cc, buf[3] & 15); + cc = (buf[3] & 15); + } + } + return 0; +} +#endif + +/*-------------------------------------------------------------------*/ +#ifdef DEBUG +static void dbg_dump(char *hdr, unsigned char *data, int size) +{ + int i; + char line[40]; + char str[9]; + line[0] = 0; + for (i = 0; i < size; i++) { + sprintf(line, "%s%.2x ", line, data[i]); + if ((data[i] >= 32) && (data[i] <= 126)) + str[i%8] = data[i]; + else + str[i%8] = '.'; + if (!((i+1)%8)) { + str[i%8 + 1] = 0; + dbg_s("%s %s %s", hdr, line, str); + line[0] = 0; + } /* if */ + } /* for */ + if (i%8) { + int j; + str[i%8 + 1] = 0; + for (j = (i%8); j < 8; j++) + sprintf(line, "%s ", line); + dbg_s("%s %s %s", hdr, line, str); + line[0] = 0; + } /* if */ +} /* dbg_dump */ +#else +#define dbg_dump(format, arg...) do {} while (0) +#endif /* DEBUG */ + +static unsigned long copyDataFrom(int us, + void *to, const void *from, unsigned long n) +{ + if (us) + return copy_from_user(to, from, n); + memcpy(to, from, n); + return 0; +} + +static unsigned long copyDataTo(int us, + void *to, const void *from, unsigned long n) +{ + if (us) + return copy_to_user(to, from, n); + memcpy(to, from, n); + return 0; +} + +static void vb_init(struct video_buf_s *buf) +{ + buf->readOffset = 0; + buf->writeOffset = 0; + buf->isEmpty = 1; +} /* vb_init */ + +static int vb_get_write_size(struct video_buf_s *buf) +{ + int writeSize = 0; + + if (buf->writeOffset == buf->readOffset) { + if (buf->isEmpty) + writeSize = DEVICE_VB_LENGTH; + } else if (buf->writeOffset > buf->readOffset) + writeSize = + DEVICE_VB_LENGTH - (buf->writeOffset - buf->readOffset); + else + writeSize = buf->readOffset - buf->writeOffset; + return writeSize; +} /* vb_get_write_size */ + +static int vb_write(struct video_buf_s *buf, __u8 *data, int size) +{ + int writeSize = vb_get_write_size(buf); + int firstPart = DEVICE_VB_LENGTH - buf->writeOffset; + if (size > writeSize) + size = writeSize; + + if (size < firstPart) { + memcpy(&buf->data[buf->writeOffset], data, size); + buf->writeOffset += size; + } /* if */ else { + memcpy(&buf->data[buf->writeOffset], data, firstPart); + memcpy(buf->data, &data[firstPart], size - firstPart); + buf->writeOffset = size - firstPart; + } /* else */ + + if (size > 0) + buf->isEmpty = 0; + return size; +} /* vb_write */ + +static int vb_read_next(struct video_buf_s *buf, __u8 *data) +{ + int readSize; + int firstPart; + int nextOffset; + int isStuffing; + int ret; + + readSize = DEVICE_VB_LENGTH - vb_get_write_size(buf); + nextOffset = buf->readOffset + DEVICE_MPEG2_PACKET_SIZE; + if (nextOffset >= DEVICE_VB_LENGTH) + nextOffset -= DEVICE_VB_LENGTH; + while (readSize > DEVICE_MPEG2_PACKET_SIZE) { + if ((buf->data[buf->readOffset] == DEVICE_MPEG2_SYNC_BYTE) && + (buf->data[nextOffset] == DEVICE_MPEG2_SYNC_BYTE)) { + /* packet in sync */ + break; + } /* if */ + buf->readOffset++; + if (buf->readOffset == DEVICE_VB_LENGTH) + buf->readOffset = 0; + nextOffset++; + if (nextOffset == DEVICE_VB_LENGTH) + nextOffset = 0; + readSize--; + } /* while */ + if (readSize <= DEVICE_MPEG2_PACKET_SIZE) { + buf->isEmpty = 1; + return 0; + } /* if */ + + /* packet is in sync, check if it is a stuffing packet */ + isStuffing = 0; + firstPart = DEVICE_VB_LENGTH - buf->readOffset; + if (firstPart < DEVICE_NULL_HEADER_SIZE) { + if ((memcmp(nullHeader, &buf->data[buf->readOffset], firstPart) + == 0) && + (memcmp(&nullHeader[firstPart], buf->data, + DEVICE_NULL_HEADER_SIZE - firstPart) + == 0)) { + isStuffing = 1; + } /* if */ + } /* if */ + else { + if (memcmp(nullHeader, &buf->data[buf->readOffset], + DEVICE_NULL_HEADER_SIZE) == 0) { + isStuffing = 1; + } /* if */ + } /* else */ + readSize -= DEVICE_MPEG2_PACKET_SIZE; + if (readSize <= DEVICE_MPEG2_PACKET_SIZE) + buf->isEmpty = 1; + + /* skip stuffing packet */ + if (isStuffing) { + buf->readOffset = nextOffset; + return 0; + } /* if */ + + /* copy packet to user space */ + if (firstPart >= DEVICE_MPEG2_PACKET_SIZE) { + ret = copy_to_user(data, + &buf->data[buf->readOffset], DEVICE_MPEG2_PACKET_SIZE); + } /* if */ else { + ret = copy_to_user(data, + &buf->data[buf->readOffset], firstPart); + ret = copy_to_user(&data[firstPart], + buf->data, DEVICE_MPEG2_PACKET_SIZE - firstPart); + } /* else */ + buf->readOffset = nextOffset; + return DEVICE_MPEG2_PACKET_SIZE; +} /* vb_read_next */ + +/*-------------------------------------------------------------------*/ +#ifdef DEBUG_BITRATE +static void print_bitrate(struct ts_channel_s *channel, __u8 channel_number) +{ + int readSize; + ktime_t currentTime; + int diffTime_us; + int bitrate; + + currentTime = ktime_get_real(); + if (!(channel->bitrateTime.tv64)) { + channel->bitrateTime = currentTime; + } else { + readSize = DEVICE_VB_LENGTH - vb_get_write_size(&channel->inVb); + dbg("%d bytes received\n", readSize); + diffTime_us = (int)(ktime_us_delta(currentTime, + channel->bitrateTime)); + if (diffTime_us) { + bitrate = (int)((readSize * 8 * USEC_PER_SEC) + / diffTime_us); + } + channel->bitrateTime = currentTime; + dbg("received bitrate for channel[%d] = %dbps\n", + channel_number, bitrate); + } +} +#endif /* DEBUG_BITRATE */ +/*-------------------------------------------------------------------*/ + +static void device_cibulk_complete(struct urb *urb) +{ + dbg("start"); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + dbg("end"); +} /* device_cibulk_complete */ + +static int device_cibulk_send(struct device_s *device, + struct ioctl_data_s *data, + int user_space) +{ + int res; + struct urb *urb; + int size; + int index = -1; + __u8 *ptr; + __u32 todo = data->txSize; + __u8 *userData = data->txData; + + dbg("start"); + + do { + /* get a free bulk message */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("alloc urb"); + return -ENOMEM; + } /* if */ + urb->dev = device->usbdev; + + /* allocate bulk data */ + size = device->ciBulk.outMaxPacketSize; + if (todo < size) + size = todo; + urb->transfer_buffer = kmalloc(size, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("alloc transfer buffer"); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + + /* copy data */ + ptr = urb->transfer_buffer; + res = copyDataFrom(user_space, ptr, userData, size); + +#ifdef TIMESTAMP + if (bSetTimestamps) { + if (index == -1) { + SetTimestamp("urb %x, toSend %d, send %d", + urb, todo, size); + SetTimestamp("cmd 0x%02x", ptr[0]); + } else { + SetTimestamp("urb %x, toSend %d, send %d", + urb, todo, size); + } + } +#endif + + /* first packet, get index */ + if (index == -1) { + if ((ptr[DEVICE_COMMAND_OFFSET] == DEVICE_CMD_INIT) || + (ptr[DEVICE_COMMAND_OFFSET] + == DEVICE_CMD_WRITE_REG) || + (ptr[DEVICE_COMMAND_OFFSET] + == DEVICE_CMD_READ_REG)) { + index = 0; /* register command, no module */ + } else if (ptr[DEVICE_COMMAND_OFFSET] + & DEVICE_SEL_MASK) { + index = 1; /* module B */ + } else { + index = 0; /* module A */ + } /* else */ + device->ciBulk.ciData[index].syncDataSize = 0; + device->ciBulk.ciData[index].syncSignal = 0; + } /* if */ + + /* submit bulk */ + urb->pipe = usb_sndbulkpipe(device->usbdev, + DEVICE_BULK_OUT_PIPE); + urb->transfer_buffer_length = size; + urb->complete = device_cibulk_complete; + urb->context = NULL; + dbg_dump("txBuf", urb->transfer_buffer, + urb->transfer_buffer_length); + res = usb_submit_urb(urb, GFP_KERNEL); + if (res < 0) { + err("submit urb res = %d", res); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + todo -= size; + userData += size; + } while (todo); + + device->ciBulk.ciData[index].bPendingSend = 1; + dbg("end"); + return index; +} /* device_cibulk_send */ + +static void device_int_complete(struct urb *urb) +{ + unsigned long flags; + struct device_s *device = urb->context; + __u8 *dataToCopy; + int sizeToCopy, SizeReceived; + __u8 isFirstPacket = 0; + __u8 isLastPacket = 0; + __u8 index, i; + __u8 status; + struct message_node_s *message; + + dbg("start"); + + if (urb->status) { + dbg("urb status %d, not submitted again", urb->status); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { + if (device->ciBulk.intUrb[i] == urb) + device->ciBulk.intUrb[i] = NULL; + } + return; + } /* if */ + + spin_lock_irqsave(&device->ciBulk.intUrbLock, flags); + dbg("urb status %d, transfer_buffer_length %d actual_length %d", + urb->status, + urb->transfer_buffer_length, + urb->actual_length); + dataToCopy = urb->transfer_buffer; + SizeReceived = urb->actual_length; + dbg_dump("total rxBuf", dataToCopy, SizeReceived); + + + do { + if (device->ciBulk.intSizeToReceive == 0) { + if (!dataToCopy[DEVICE_STATUS_OFFSET] && + !dataToCopy[DEVICE_LENGTH_MSB_OFFSET] && + !dataToCopy[DEVICE_LENGTH_LSB_OFFSET] && + !dataToCopy[DEVICE_COUNTER_OFFSET]){ + dbg("no data receive"); + memset(urb->transfer_buffer, + 0, urb->transfer_buffer_length); + usb_submit_urb(urb, GFP_ATOMIC); + return; + } + /* first packet, read header */ + isFirstPacket = 1; + device->ciBulk.intCurrStatus = + dataToCopy[DEVICE_STATUS_OFFSET] & + DEVICE_CMD_MASK; + if (dataToCopy[DEVICE_STATUS_OFFSET] + & DEVICE_SEL_MASK) { + device->ciBulk.intCurrIndex = 1; /* module B */ + } else { + device->ciBulk.intCurrIndex = 0; /* module A */ + } + if ((device->ciBulk.intCurrStatus == DEVICE_READ_REGOK) + || (device->ciBulk.intCurrStatus + == DEVICE_WRITE_REGOK)) { + device->ciBulk.intSizeToReceive = + dataToCopy[DEVICE_LENGTH_LSB_OFFSET] + + DEVICE_DATA_OFFSET; + } else { + device->ciBulk.intSizeToReceive = + dataToCopy[DEVICE_LENGTH_MSB_OFFSET] * 256 + + dataToCopy[DEVICE_LENGTH_LSB_OFFSET] + + DEVICE_DATA_OFFSET; + } + } /* if */ + + /* get last packet state */ + status = device->ciBulk.intCurrStatus; + index = device->ciBulk.intCurrIndex; + sizeToCopy = device->ciBulk.intSizeToReceive; + if (sizeToCopy > urb->actual_length) { + /* limit size to received buffer size */ + sizeToCopy = urb->actual_length; + } /* if */ else + isLastPacket = 1; + dbg_dump("rxBuf", dataToCopy, sizeToCopy); + +#ifndef FRBIT + if (status == DEVICE_DATAREADY) { + if (device->ciBulk.ciData[index].bPendingSend) + status = DEVICE_DATAREADY_SYNC; + } +#endif + +#ifdef TIMESTAMP + if (device->ciBulk.intSizeToReceive > 2000) + bSetTimestamps = 1; + if (bSetTimestamps) { + SetTimestamp("urb %x,toReceive %d,received %d,toCopy%d", + urb, + device->ciBulk.intSizeToReceive, + SizeReceived, + sizeToCopy); + SetTimestamp("status 0x%02x, camIndex %d, isLast %d", + status, index, isLastPacket); + } +#endif + + switch (status) { + case DEVICE_INITOK: + case DEVICE_READ_REGOK: + case DEVICE_WRITE_REGOK: + index = 0; + case DEVICE_CAMRESETOK: + /*only for debug*/ + if (!dataToCopy[DEVICE_STATUS_OFFSET] && + !dataToCopy[DEVICE_LENGTH_MSB_OFFSET] && + !dataToCopy[DEVICE_LENGTH_LSB_OFFSET] && + !dataToCopy[DEVICE_COUNTER_OFFSET]){ + break; + } + case DEVICE_CISOK: + case DEVICE_WRITECOROK: + case DEVICE_NEGOTIATEOK: + case DEVICE_WRITELPDUOK: + case DEVICE_WRITELPDUBUSY: + case DEVICE_READLPDUOK: + case DEVICE_WRITEEXTOK: + case DEVICE_READEXTOK: + case DEVICE_NO_CAM: + case DEVICE_NOK: + case DEVICE_MCARD_WRITEOK: + case DEVICE_CAMPARSE_ERROR: + case DEVICE_CMDPENDING: + case DEVICE_REGSTATUSOK: + case DEVICE_DATAREADY_SYNC: + /* copy partial message */ + spin_lock_irqsave(&device->ciBulk.intLock, + flags); + memcpy(&device->ciBulk.ciData[index]. + syncData[device->ciBulk.ciData[index]. + syncDataSize], + dataToCopy, sizeToCopy); + device->ciBulk.intSizeToReceive -= sizeToCopy; + device->ciBulk.ciData[index].syncDataSize += + sizeToCopy; + spin_unlock_irqrestore(&device->ciBulk.intLock, + flags); + dbg("copied %d bytes at offset %d", sizeToCopy, + device->ciBulk.ciData[index]. + syncDataSize - sizeToCopy); + + if (isLastPacket) { + /* last packet received, sync message */ + device->ciBulk.ciData[index].syncSignal = 1; + wake_up_interruptible(&device->ciBulk. + ciData[index].syncWait); + device->ciBulk.ciData[index].bPendingSend = 0; + dbg("sync signal return %d %d ", + device->ciBulk.ciData[index]. + syncDataSize, index); + } /* if */ + break; + case DEVICE_CAMDET: + case DEVICE_DATAREADY: + case DEVICE_MCARD_READ: + case DEVICE_FRBit: + if (isFirstPacket) { + /* create new async message */ + message = kmalloc(sizeof(struct message_node_s), + GFP_ATOMIC); + if (!message) { + err("cannot allocate async message"); + break; + } + memset(message, + 0, sizeof(struct message_node_s)); + list_add_tail(&message->node, + &device->ciBulk.ciData[index]. + asyncDataList); + } /* if */ + else { + /* get tail message */ + message = list_entry((device->ciBulk. + ciData[index].asyncDataList.prev), + struct message_node_s, node); + } /* else */ + + /* copy partial message */ + spin_lock_irqsave(&device->ciBulk.intLock, flags); + memcpy(&message->data[message->size], + dataToCopy, sizeToCopy); + device->ciBulk.intSizeToReceive -= sizeToCopy; + message->size += sizeToCopy; + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + dbg("async copied %d bytes at offset %d", sizeToCopy, + message->size - sizeToCopy); + + if (isLastPacket) { + /* last packet received, signal async message */ + wake_up_interruptible(&device->ciBulk. + ciData[index].asyncWait); + dbg("async signal %d", index); + } /* if */ + break; + case DEVICE_GPIOCHANGE: + info("GPIO change %x %x %x", + status, dataToCopy[4], dataToCopy[5]); + device->ciBulk.intSizeToReceive -= sizeToCopy; + break; + default: + err("unknown status 0x%2x", status); + break; + } /* switch */ + dataToCopy += sizeToCopy; + SizeReceived -= sizeToCopy; + + } while (SizeReceived > 0); + + memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); + usb_submit_urb(urb, GFP_ATOMIC); + +#ifdef TIMESTAMP + /*if (bSetTimestamps) { + SetTimestamp("urb %x submitted", urb); + }*/ +#endif + + spin_unlock_irqrestore(&device->ciBulk.intUrbLock, flags); + + dbg("end"); +} /* device_int_complete */ + +static int device_wait_sync_data(struct device_s *device, + __u8 index, + struct ioctl_data_s *data, + int user_space) +{ + unsigned long flags; + int ret; + + dbg("start %d", index); + + spin_lock_irqsave(&device->ciBulk.intLock, flags); + while (device->ciBulk.ciData[index].syncSignal == 0) { + /* nothing to copy */ + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + if (wait_event_interruptible(device->ciBulk. + ciData[index].syncWait, + device->ciBulk.ciData[index].syncSignal)) { + device->ciBulk.ciData[index].bPendingSend = 0; + err("interrupt"); + return -ERESTARTSYS; + /* signal: tell the fs layer to handle it */ + } /* if */ + /* otherwise loop, but first reacquire the lock */ + spin_lock_irqsave(&device->ciBulk.intLock, flags); + } /* while */ + + /* copy packet to user space buffer */ + if (device->ciBulk.ciData[index].syncDataSize < data->rxSize) + /* truncate returned message against user buffer size */ + data->rxSize = device->ciBulk.ciData[index].syncDataSize; + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + /* release the lock */ + ret = copyDataTo(user_space, + data->rxData, + device->ciBulk.ciData[index].syncData, data->rxSize); + dbg_dump("userMsg", + device->ciBulk.ciData[index].syncData, data->rxSize); + dbg("userRet %d", data->rxSize); + device->ciBulk.ciData[index].syncDataSize = 0; + device->ciBulk.ciData[index].syncSignal = 0; + + dbg("end"); + return 0; +} /* device_wait_sync_data */ + +static int device_wait_async_data(struct device_s *device, + __u8 index, + struct rw_data_s *data, + int user_space) +{ + struct list_head *item; + struct message_node_s *message; + unsigned long flags; + int ret; + + dbg("start %d", index); + + if ((device->askToRelease) || (device->askToSuspend)) { + err("ask to release or ask to suspend"); + return -EINTR; /* device close interrupt */ + } /* if */ + + if (index >= DEVICE_NUM_CAM) { + err("bad index(%d)", index); + return -EINVAL; + } + + spin_lock_irqsave(&device->ciBulk.intLock, flags); + while (list_empty(&device->ciBulk.ciData[index].asyncDataList)) { + /* nothing to copy */ + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + /* release the lock */ + if (wait_event_interruptible(device->ciBulk. + ciData[index].asyncWait, + device->askToRelease || + device->askToSuspend || + (!list_empty(&device->ciBulk. + ciData[index].asyncDataList)))) { + err("interrupt"); + return -ERESTARTSYS; + /* signal: tell the fs layer to handle it */ + } /* if */ + if ((device->askToRelease) || (device->askToSuspend)) { + err("ask to release or ask to suspend"); + return -EINTR; /* device close interrupt */ + } /* if */ + /* otherwise loop, but first reacquire the lock */ + spin_lock_irqsave(&device->ciBulk.intLock, flags); + } /* while */ + + /* ok, data is there, return first item */ + item = device->ciBulk.ciData[index].asyncDataList.next; + message = list_entry(item, struct message_node_s, node); + if (message->size < data->size) { + /* truncate returned message against user buffer size */ + data->size = message->size; + } /* if */ + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + /* release the lock */ + ret = copyDataTo(user_space, data->data, message->data, data->size); + dbg_dump("userMsg", message->data, data->size); + dbg("userRet %d", data->size); + list_del(item); + kfree(message); + + dbg("end"); + return 0; +} /* device_wait_async_data */ + +static int device_start_intr(struct device_s *device) +{ + __u8 i, j; + struct urb *urb; + + dbg("start"); + + for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("alloc urb"); + return -ENOMEM; + } /* if */ + urb->transfer_buffer = + kmalloc(device->ciBulk.inMaxPacketSize, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("alloc transfer buffer"); + usb_free_urb(urb); + urb = NULL; + return -ENOMEM; + } /* if */ + + urb->dev = device->usbdev; + urb->pipe = usb_rcvintpipe(device->usbdev, DEVICE_INT_IN_PIPE); + urb->transfer_buffer_length = device->ciBulk.inMaxPacketSize; + urb->complete = device_int_complete; + urb->context = device; + urb->interval = 1; + device->ciBulk.intUrb[i] = urb; + for (j = 0; j < DEVICE_NUM_CAM; j++) { + init_waitqueue_head(&device->ciBulk.ciData[j].syncWait); + init_waitqueue_head(&device->ciBulk. + ciData[j].asyncWait); + } /* for */ + usb_submit_urb(device->ciBulk.intUrb[i], GFP_KERNEL); + } + + dbg("end"); + return 0; +} /* device_start_intr */ + +static void device_stop_intr(struct device_s *device) +{ + struct list_head *item; + struct list_head *tmp; + struct message_node_s *message; + int i, j; + + dbg("start"); + + for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { + if (!device->ciBulk.intUrb[i]) + break; + usb_unlink_urb(device->ciBulk.intUrb[i]); + device->ciBulk.intUrb[i] = NULL; + for (j = 0; j < DEVICE_NUM_CAM; j++) { + for (item = device->ciBulk.ciData[j].asyncDataList.next; + item != &device->ciBulk.ciData[j].asyncDataList; + ) { + message = list_entry(item, + struct message_node_s, node); + tmp = item->next; + list_del(item); + kfree(item); + item = tmp; + } /* for */ + } /* for */ + dbg("unlink urb"); + } + + dbg("end"); +} /* device_stop_intr */ + +static void device_iso_in_complete(struct urb *urb) +{ + unsigned long flags; + struct ts_channel_s *channel = urb->context; + __u8 i; + __u8 *data; + + /*dbg("start");*/ + + if (urb->status) { + dbg("urb status %d, not submitted again", urb->status); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; + } /* if */ + + spin_lock_irqsave(&channel->inLock, flags); + for (i = 0; i < urb->number_of_packets; i++) { + data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + if (!urb->iso_frame_desc[i].status && + (urb->iso_frame_desc[i].actual_length > 0)) { + if (vb_get_write_size(&channel->inVb) + >= urb->iso_frame_desc[i].actual_length) { + vb_write(&channel->inVb, data, + urb->iso_frame_desc[i].actual_length); + } /* if */ + else { + err("video buffer is full, packet loss %d", + urb->iso_frame_desc[i].actual_length); + } /* else */ + } /* if */ + else { + err("frame rejected, status %x, actual_length %d bytes", + urb->iso_frame_desc[i].status, + urb->iso_frame_desc[i].actual_length); + } + } /* for */ + spin_unlock_irqrestore(&channel->inLock, flags); + + if (!channel->inVb.isEmpty) + wake_up_interruptible(&channel->inWait); + + memset(urb->transfer_buffer, + 0, DEVICE_ISOC_LENGTH(channel->maxPacketSize)); + urb->transfer_buffer_length = + DEVICE_ISOC_LENGTH(channel->maxPacketSize); + urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb->complete = device_iso_in_complete; + urb->context = channel; + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + for (i = 0; i < DEVICE_NUM_FRAMES_PER_URB; i++) { + urb->iso_frame_desc[i].offset = i * channel->maxPacketSize; + urb->iso_frame_desc[i].length = channel->maxPacketSize; + } /* for */ + usb_submit_urb(urb, GFP_ATOMIC); + + /*dbg("end");*/ +} /* device_iso_in_complete */ + +static void device_tsbulk_in_complete(struct urb *urb) +{ + unsigned long flags; + struct ts_channel_s *channel = urb->context; + __u8 *data; +#ifdef DEBUG_CONTINUITY + unsigned int i; +#endif + + /*dbg("start");*/ + + if (urb->status) { + err("urb status %d(%x), not submitted again", + urb->status, urb->status); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; + } /* if */ + + spin_lock_irqsave(&channel->inLock, flags); + data = urb->transfer_buffer; + +#ifdef DEBUG_CONTINUITY + i = 0; + /* check synchro byte*/ + while (i < urb->actual_length) { + if (!((data[i] == DEVICE_MPEG2_SYNC_BYTE) && + (data[i+DEVICE_MPEG2_PACKET_SIZE] + == DEVICE_MPEG2_SYNC_BYTE))) { + i++; + } else { + /* Synchro find*/ + break; + } + } + + /* Synchro Ok, check discontinuity*/ + while (i < urb->actual_length) { + if (dbg_cc(&data[i]) < 0) { + dbg("(actual_length= %d i=%d pkt=%d)", + urb->actual_length, + i, + i/DEVICE_MPEG2_PACKET_SIZE); + dbg("%02x %02x %02x %02x %02x %02x %02x %02x\n", + data[i-4], data[i-3], data[i-2], data[i-1], + data[i], data[i+1], data[i+2], data[i+3]); + } + i += DEVICE_MPEG2_PACKET_SIZE; + } +#endif + + if (urb->actual_length) { + channel->nbByteRead += urb->actual_length; + if (vb_get_write_size(&channel->inVb) >= urb->actual_length) + vb_write(&channel->inVb, data, urb->actual_length); + else + err("video buffer is full, packet loss %d", + urb->actual_length); + } else { + /*warn("receive size of 0\n");*/ + } + + spin_unlock_irqrestore(&channel->inLock, flags); + /* dbg("urb->actual_length=%d",urb->actual_length);*/ + /* info("urb->actual_length=%d\n",urb->actual_length);*/ + + if (!channel->inVb.isEmpty) + wake_up_interruptible(&channel->inWait); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + /*dbg("end");*/ +} /* device_tsbulk_in_complete */ + +static int device_fill_ts(struct device_s *device, + __u8 index, + struct rw_data_s *data) +{ + unsigned long flags; + __u32 copiedSize; + struct ts_channel_s *channel = &device->channel[index]; + + /*dbg("start");*/ + + spin_lock_irqsave(&channel->inLock, flags); + do { + while (channel->inVb.isEmpty) { + /* nothing to copy */ + spin_unlock_irqrestore(&channel->inLock, flags); + /* release the lock */ + if (wait_event_interruptible(channel->inWait, + device->askToRelease || + device->askToSuspend || + (!channel->inVb.isEmpty))) { + err("interrupt"); + return -ERESTARTSYS; + /* signal: tell the fs layer to handle it */ + } /* if */ + if ((device->askToRelease) || (device->askToSuspend)) { + err("ask to release or ask to suspend"); + return -EINTR; /* device close interrupt */ + } /* if */ + /* otherwise loop, but first reacquire the lock */ + spin_lock_irqsave(&channel->inLock, flags); + } /* while */ + + spin_unlock_irqrestore(&channel->inLock, flags); + + copiedSize = vb_read_next(&channel->inVb, + &data->data[data->copiedSize]); + if (copiedSize) { + /*dbg("copied %d bytes in buffer 0x%p, offset %d", + copiedSize, data->data, data->copiedSize);*/ + data->copiedSize += copiedSize; + } /* if */ + spin_lock_irqsave(&channel->inLock, flags); + } while ((data->copiedSize+DEVICE_MPEG2_PACKET_SIZE) <= data->size); + /* buffer not full */ + + spin_unlock_irqrestore(&channel->inLock, flags); + +#ifdef DEBUG_BITRATE + print_bitrate(channel, index); +#endif + + /*dbg("end, buffer 0x%p", data->data);*/ + return 0; +} /* device_fill_ts */ + +static int device_start_iso_in(struct device_s *device, __u8 index) +{ + int i, j; + int ret = 0; + struct urb *urb; + + /*dbg("start");*/ + +#ifdef DEBUG_BITRATE + device->channel[index].bitrateTime = ktime_set(0, 0); +#endif + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + urb = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); + device->channel[index].isocInUrb[i] = urb; + if (urb) { + /*urb->transfer_buffer = + kmalloc(DEVICE_ISOC_LENGTH, GFP_KERNEL);*/ + urb->transfer_buffer = + kmalloc(DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize), + GFP_KERNEL); + if (!urb->transfer_buffer) { + ret = -ENOMEM; + err("transfer_buffer allocation failed %d", i); + break; + } /* if */ + } /* if */ else { + ret = -ENOMEM; + err("usb_alloc_urb failed %d", i); + break; + } /* if */ + } /* for */ + + if (ret) { + /* Allocation error, must free already allocated data */ + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + urb = device->channel[index].isocInUrb[i]; + if (urb) { + kfree(urb->transfer_buffer); + if (urb->transfer_buffer) + urb->transfer_buffer = NULL; + usb_free_urb(urb); + device->channel[index].isocInUrb[i] = NULL; + } /* if */ + } /* for */ + return ret; + } /* if */ + + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + urb = device->channel[index].isocInUrb[i]; + memset(urb->transfer_buffer, + 0, + DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)); + urb->transfer_buffer_length = + DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb->complete = device_iso_in_complete; + urb->context = &device->channel[index]; + urb->dev = device->usbdev; + urb->pipe = usb_rcvisocpipe( + device->usbdev, DEVICE_TS_IN_PIPE + index); + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { + urb->iso_frame_desc[j].offset = + j * device->channel[index].maxPacketSize; + urb->iso_frame_desc[j].length = + device->channel[index].maxPacketSize; + } /* for */ + } /* for */ + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) + usb_submit_urb(device->channel[index].isocInUrb[i], GFP_KERNEL); + + /*dbg("end");*/ + return 0; +} /* device_start_iso_in */ + +static void device_stop_iso_in(struct device_s *device, __u8 index) +{ + int i; + + /*dbg("start");*/ + + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + if (device->channel[index].isocInUrb[i]) { + usb_unlink_urb(device->channel[index].isocInUrb[i]); + device->channel[index].isocInUrb[i] = NULL; + dbg("unlink urb %i", i); + } /* if */ + } /* for */ + + /*dbg("end");*/ +} /* device_stop_iso_in */ + +static int device_start_tsbulk_in(struct device_s *device, __u8 index) +{ + struct urb *urb; + + dbg("start"); + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (urb) { + urb->transfer_buffer = kmalloc(3072, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("transfer_buffer allocation failed"); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + } /* if */ else { + err("usb_alloc_urb failed"); + return -ENOMEM; + } /* if */ + device->channel[index].bulkInUrb = urb; + memset(urb->transfer_buffer, 0, 3072); + urb->transfer_buffer_length = 3072; + + urb->complete = device_tsbulk_in_complete; + urb->context = &device->channel[index]; + urb->dev = device->usbdev; + urb->pipe = usb_rcvbulkpipe(device->usbdev, DEVICE_TS_IN_PIPE + index); + usb_submit_urb(device->channel[index].bulkInUrb, GFP_KERNEL); + + dbg("end"); + return 0; +} /* device_start_tsbulk_in */ + +static void device_stop_tsbulk_in(struct device_s *device, __u8 index) +{ + dbg("start"); + + if (device->channel[index].bulkInUrb) { + usb_unlink_urb(device->channel[index].bulkInUrb); + device->channel[index].bulkInUrb = NULL; + dbg("unlink urb"); + } /* if */ + + dbg("end"); +} /* device_stop_tsbulk_in */ + +static void device_iso_out_complete(struct urb *urb) +{ + struct ts_channel_s *channel = urb->context; + struct urb *tmpUrb; + int i; + int ret = 0; + + /*dbg("start");*/ + +/*dbg_dump("txBuf", urb->transfer_buffer, urb->transfer_buffer_length);*/ + + if (urb->status || channel->outStop) { + /* error, free all coming urbs */ + err("free urb"); + channel->outStop = 1; + atomic_dec(&channel->numOutUrbs); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; + } /* if */ + + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + if (urb == channel->isocOutUrb[i]) + break; + } /* for */ + if (i == DEVICE_NUM_ISOC_OUT_URBS) { + /* urb must be deleted */ + kfree(urb->transfer_buffer); + usb_free_urb(urb); + } /* if */ + + if (atomic_dec_and_test(&channel->numOutUrbs)) { + /* get next free urb */ + tmpUrb = channel->isocOutUrb[channel->nextFreeOutUrbIndex++]; + if (channel->nextFreeOutUrbIndex == DEVICE_NUM_ISOC_OUT_URBS) + channel->nextFreeOutUrbIndex = 0; + + /* reinitialize urb with null packets */ + memset(tmpUrb->transfer_buffer, + 0xCD, DEVICE_ISOC_LENGTH(channel->maxPacketSize)); + for (i = 0; + i < DEVICE_ISOC_LENGTH(channel->maxPacketSize); + i += DEVICE_MPEG2_PACKET_SIZE) { + memcpy(tmpUrb->transfer_buffer+i, + nullHeader, sizeof(nullHeader)); + } /* for */ + tmpUrb->transfer_buffer_length = + DEVICE_ISOC_LENGTH(channel->maxPacketSize); + tmpUrb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + tmpUrb->complete = device_iso_out_complete; + tmpUrb->context = channel; + tmpUrb->transfer_flags = URB_ISO_ASAP; + tmpUrb->interval = 1; + for (i = 0; i < DEVICE_NUM_FRAMES_PER_URB; i++) { + tmpUrb->iso_frame_desc[i].offset = + i * channel->maxPacketSize; + tmpUrb->iso_frame_desc[i].length = + channel->maxPacketSize; + } /* for */ + + /* submit urb */ + ret = usb_submit_urb(tmpUrb, GFP_ATOMIC); + if (ret) + err("usb_submit_urb failed %d", ret); + + atomic_inc(&channel->numOutUrbs); + } /* if */ + + /*dbg("end");*/ +} /* device_iso_out_complete */ + +static int device_tsiso_send(struct device_s *device, + __u8 index, __u8 *data, int size) +{ + int i, j; + struct urb **urb; + __u32 numUrbs; + int ret = 0; + + /* dbg("start");*/ + + numUrbs = + size / DEVICE_ISOC_LENGTH(device->channel[index].maxPacketSize); + urb = kmalloc(numUrbs * sizeof(struct urb *), GFP_KERNEL); + if (!urb) { + err("urb array allocation failed %d", numUrbs); + return -ENOMEM; + + } /* if */ + memset(urb, 0, numUrbs * sizeof(struct urb *)); + + for (i = 0; i < numUrbs; i++) { + urb[i] = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); + if (urb[i]) { + urb[i]->transfer_buffer = + kmalloc(DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize), + GFP_KERNEL); + if (!urb[i]->transfer_buffer) { + ret = -ENOMEM; + err("transfer_buffer allocation failed %d", i); + break; + } /* if */ + } /* if */ + else { + ret = -ENOMEM; + err("usb_alloc_urb failed %d", i); + break; + } /* if */ + } /* for */ + if (ret) { + /* Allocation error, must free already allocated data */ + for (i = 0; i < numUrbs; i++) { + if (urb[i]) { + kfree(urb[i]->transfer_buffer); + urb[i]->transfer_buffer = NULL; + usb_free_urb(urb[i]); + urb[i] = NULL; + } /* if */ + } /* for */ + kfree(urb); + return ret; + } /* if */ + + for (i = 0; i < numUrbs; i++) { + ret = copy_from_user(urb[i]->transfer_buffer, + &data[i*DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)], + DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)); + urb[i]->transfer_buffer_length = DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + urb[i]->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb[i]->complete = device_iso_out_complete; + urb[i]->context = &device->channel[index]; + urb[i]->dev = device->usbdev; + urb[i]->pipe = usb_sndisocpipe(device->usbdev, + DEVICE_TS_OUT_PIPE + index); + urb[i]->transfer_flags = URB_ISO_ASAP; + urb[i]->interval = 1; + for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { + urb[i]->iso_frame_desc[j].offset = + j * device->channel[index].maxPacketSize; + urb[i]->iso_frame_desc[j].length = + device->channel[index].maxPacketSize; + } /* for */ + } /* for */ + + atomic_add(numUrbs, &device->channel[index].numOutUrbs); + for (i = 0; i < numUrbs; i++) { + ret = usb_submit_urb(urb[i], GFP_ATOMIC); + if (ret) + err("usb_submit_urb failed %d", ret); + } /* for */ + + kfree(urb); + + /* dbg("end");*/ + return size; +} /* device_tsiso_send */ + +static int device_start_iso_out(struct device_s *device, __u8 index) +{ + int i, j; + int ret = 0; + struct urb *urb; + + /*dbg("start");*/ + + device->channel[index].outStop = 0; + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + urb = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); + device->channel[index].isocOutUrb[i] = urb; + if (urb) { + urb->transfer_buffer = kmalloc(DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize), + GFP_KERNEL); + if (!urb->transfer_buffer) { + ret = -ENOMEM; + err("transfer_buffer allocation failed %d", i); + break; + } /* if */ + } /* if */ else { + ret = -ENOMEM; + err("usb_alloc_urb failed %d", i); + break; + } /* if */ + } /* for */ + + if (ret) { + /* Allocation error, must free already allocated data */ + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + urb = device->channel[index].isocOutUrb[i]; + if (urb) { + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; + usb_free_urb(urb); + device->channel[index].isocOutUrb[i] = NULL; + } /* if */ + } /* for */ + return ret; + } /* if */ + + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + urb = device->channel[index].isocOutUrb[i]; + memset(urb->transfer_buffer, 0, DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)); + for (j = 0; + j < DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + j += DEVICE_MPEG2_PACKET_SIZE) { + memcpy(urb->transfer_buffer+j, + nullHeader, sizeof(nullHeader)); + } /* for */ + urb->transfer_buffer_length = DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb->complete = device_iso_out_complete; + urb->context = &device->channel[index]; + urb->dev = device->usbdev; + urb->pipe = usb_sndisocpipe(device->usbdev, + DEVICE_TS_OUT_PIPE + index); + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { + urb->iso_frame_desc[j].offset = + j * device->channel[index].maxPacketSize; + urb->iso_frame_desc[j].length = + device->channel[index].maxPacketSize; + } /* for */ + } /* for */ + device->channel[index].nextFreeOutUrbIndex = DEVICE_NUM_ISOC_OUT_URBS-1; + atomic_set(&device->channel[index].numOutUrbs, 1); + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS-1; i++) { + ret = usb_submit_urb( + device->channel[index].isocOutUrb[i], GFP_KERNEL); + if (ret) + err("usb_submit_urb failed %d", ret); + } /* for */ + + /*dbg("end");*/ + return 0; +} /* device_start_iso_out */ + +static void device_stop_iso_out(struct device_s *device, __u8 index) +{ + dbg("start"); + + device->channel[index].outStop = 1; + + dbg("end"); +} /* device_stop_iso_out */ + +static void device_tsbulk_complete(struct urb *urb) +{ + struct device_s *device = urb->context; + __u8 index = 0; + + /*dbg("start");*/ + if (!urb->status) { + if (usb_endpoint_num(&(urb->ep->desc)) != DEVICE_TS_OUT_PIPE) + index = 1; + device->channel[index].nbByteSend += urb->actual_length; + } + kfree(urb->transfer_buffer); + usb_free_urb(urb); + /*dbg("end");*/ +} /* device_tsbulk_complete */ + +static int device_tsbulk_send(struct device_s *device, + __u8 index, __u8 *data, int size) +{ + struct urb *urb; + /* int todo = size;*/ + int ret = 0; + + dbg("start"); + + /* get a free bulk message */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("alloc urb"); + return -ENOMEM; + } /* if */ + urb->dev = device->usbdev; + + /* allocate bulk data */ + urb->transfer_buffer = kmalloc(size, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("alloc transfer buffer"); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + + /* copy data */ + ret = copy_from_user(urb->transfer_buffer, data, size); + + /* submit bulk */ + urb->pipe = usb_sndbulkpipe(device->usbdev, DEVICE_TS_OUT_PIPE + index); + urb->transfer_buffer_length = size; + urb->complete = device_tsbulk_complete; + urb->context = device; + /*dbg("Transmit %d bytes\n",urb->transfer_buffer_length);*/ + /*dbg_dump("txBuf", + urb->transfer_buffer, urb->transfer_buffer_length);*/ + mod_timer(&(device->channel[index].StartBulkReadTimer), + usecs_to_jiffies(50)); + + if (usb_submit_urb(urb, GFP_KERNEL) < 0) { + err("submit urb"); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + + dbg("end"); + return 0; +} /* device_tsbulk_send */ + +/* ---------------------------------------------------------- */ +static void StartBulkRead_func(unsigned long context) +{ + struct bulk_timer_s *bulk_time = (struct bulk_timer_s *) context; + + device_start_tsbulk_in(bulk_time->device, bulk_time->index); +} + +static int device_drv_open(struct device_s *device) +{ + int index; + mutex_lock(&device->lock); + + if (!device->usbdev) { + err("no dev, can not start dev"); + mutex_unlock(&device->lock); + return -ENODEV; + } + + if (device->opened) { + mutex_unlock(&device->lock); + device->opened++; + info("udev=%p opened=%d", (device->usbdev), device->opened); + return 0; + } /* while */ + + info("set interface 0"); + if (usb_set_interface(device->usbdev, 0, 0) < 0) { + mutex_unlock(&device->lock); + err("set_interface fail"); + return -EINVAL; + } /* if */ + + device->opened++; + device->askToRelease = 0; + mutex_unlock(&device->lock); + + for (index = 0; index < DEVICE_NUM_CAM; index++) { + device->channel[index].nbByteSend = -376; + device->channel[index].nbByteRead = 0; + device->channel[index].FirstTransfer = true; + gbulk_timer[index].device = device; + gbulk_timer[index].index = index; + setup_timer(&device->channel[index].StartBulkReadTimer, + StartBulkRead_func, + (unsigned long)&(gbulk_timer[index])); + } +#ifdef DEBUG_CONTINUITY + init_tab_cc(); +#endif + info("udev=%p opened=%d", (device->usbdev), device->opened); + return 0; +} + +static int device_ci_unlock_read(struct device_s *device) +{ + if (device->opened) { + /* release blocking functions */ + device->askToRelease = 1; + wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); + wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); + wake_up_interruptible(&device->channel[0].inWait); + wake_up_interruptible(&device->channel[1].inWait); + } + return 0; +} + +static int device_drv_close(struct device_s *device) +{ + int i; + mutex_lock(&device->lock); + if (device->opened && ((--device->opened) == 0)) { + device->askToRelease = 1; + device_stop_intr(device); + for (i = 0; i < DEVICE_NUM_CAM; i++) { + if (device->useIsoc) { + device_stop_iso_out(device, i); + device_stop_iso_in(device, i); + } else + device_stop_tsbulk_in(device, i); + } /* for */ + device->opened = 0; + } /* if */ + mutex_unlock(&device->lock); + return 0; +} + +static int device_open(struct inode *inode, struct file *file) +{ + int devnum = iminor(inode); +#ifdef DEBUG + int type = (MINOR(inode->i_rdev) >> 4); + int num = (MINOR(inode->i_rdev) & 0xf); +#endif + int ret = 0; + + struct device_s *device; + + dbg("start, devnum = %d type = %d num = %d", devnum, type, num); + + if (gdeviceNumber >= DRIVER_MAX_NUMBER) { + dbg("only support one device open"); + return -EINVAL; + } + device = &gdevice[gdeviceNumber]; + /*gdeviceNumber++;*/ + + ktime_get_ts(&gStart); + + ret = device_drv_open(device); + if (ret < 0) + return ret; + + file->f_pos = 0; + file->private_data = device; + + dbg("end"); + return nonseekable_open(inode, file); +} /* device_open */ + +static int device_release(struct inode *inode, struct file *file) +{ + struct device_s *device = (struct device_s *)file->private_data; + + dbg("start"); + device_drv_close(device); + dbg("end"); + return 0; +} /* device_release */ + +int cimax_usb_select_interface(struct device_s *device, unsigned long intf) +{ + int max = 0; + int mult = 0; + int ret = 0; + + info("set interface %ld", intf); + if (usb_set_interface(device->usbdev, 0, intf) < 0) { + err("set_interface failed interface 0, altSetting %ld", intf); + return -EINVAL; + } /* if */ + + /* check endpoints */ + /* CI bulk out */ + if (!usb_endpoint_is_bulk_out( + &device->usbdev->ep_out[DEVICE_BULK_OUT_PIPE]->desc)) { + err("unexpected endpoint %d", DEVICE_BULK_OUT_PIPE); + return -EINVAL; + } /* if */ + device->ciBulk.outMaxPacketSize = DEVICE_BULK_OUT_MAXPACKET; + dbg("CI bulk out (endpoint %d), packet size %d", DEVICE_BULK_OUT_PIPE, + device->ciBulk.outMaxPacketSize); + /* CI int in */ + if (!usb_endpoint_is_int_in( + &device->usbdev->ep_in[DEVICE_INT_IN_PIPE]->desc)) { + err("unexpected endpoint %d", DEVICE_INT_IN_PIPE); + return -EINVAL; + } /* if */ + device->ciBulk.inMaxPacketSize = + device->usbdev->ep_in[DEVICE_INT_IN_PIPE]->desc.wMaxPacketSize; + dbg("CI int in (endpoint %d), packet size %d", DEVICE_INT_IN_PIPE, + device->ciBulk.inMaxPacketSize); + /* TS out */ + if (device->usbdev->ep_out[DEVICE_TS_OUT_PIPE] == NULL) + dbg("no TS endpoint"); + else { + if (usb_endpoint_is_bulk_out( + &device->usbdev->ep_out[DEVICE_TS_OUT_PIPE]->desc)) { + device->useIsoc = 0; + dbg("TS is configured as bulk"); + } else if (usb_endpoint_is_isoc_out( + &device->usbdev->ep_out[DEVICE_TS_OUT_PIPE]->desc)) { + device->useIsoc = 1; + dbg("TS is configured as isochronous"); + } else { + err("unexpected endpoint %d", DEVICE_TS_OUT_PIPE); + return -EINVAL; + } /* if */ + max = device->usbdev-> + ep_out[DEVICE_TS_OUT_PIPE]->desc.wMaxPacketSize; + mult = 1 + ((max >> 11) & 0x03); + max &= 0x7ff; + device->channel[0].maxPacketSize = max * mult; + dbg("TS out (endpoint %d), packet size %d", DEVICE_TS_OUT_PIPE, + device->channel[0].maxPacketSize); + + max = device->usbdev-> + ep_out[DEVICE_TS_OUT_PIPE+1]->desc.wMaxPacketSize; + mult = 1 + ((max >> 11) & 0x03); + max &= 0x7ff; + device->channel[1].maxPacketSize = max * mult; + dbg("TS out (endpoint %d), packet size %d", + DEVICE_TS_OUT_PIPE + 1, + device->channel[1].maxPacketSize); + } + + /* start intr urb */ + if (device->ciBulk.intUrb[0] == NULL) { + ret = device_start_intr(device); + if (ret < 0) { + err("cannot start int urb"); + return ret; + } /* if */ + } /* if */ + + return ret; +} +EXPORT_SYMBOL(cimax_usb_select_interface); + +static int device_ci_write(struct device_s *device, + struct ioctl_data_s *data, int isIoctl) +{ + int ret = 0; + if (!device) + return -ENODEV; + ret = device_cibulk_send(device, data, isIoctl); + if (ret < 0) + return ret; + return device_wait_sync_data(device, ret, data, isIoctl); +} + +static int device_ci_write_ioctl(struct device_s *device, + struct ioctl_data_s *data) +{ + return device_ci_write(device, data, 1); +} + +int cimax_usb_ci_write(struct device_s *device, + u8 *txData, int txSize, u8 *rxData, int rxSize) +{ + struct ioctl_data_s data; + if (!device) + return -ENODEV; + memset(&data, 0, sizeof(data)); + data.txData = txData; + data.txSize = txSize; + data.rxData = rxData; + data.rxSize = rxSize; + return device_ci_write(device, &data, 0); +} +EXPORT_SYMBOL(cimax_usb_ci_write); + +int cimax_usb_ci_read_evt(struct device_s *device, + int moduleId, u8 *buf, int size) +{ + int ret = 0; + struct rw_data_s data; + if (!device || !device->opened) + return -ENODEV; + memset(&data, 0, sizeof(data)); + data.moduleId = moduleId; + data.data = buf; + data.size = size; + ret = device_wait_async_data(device, data.moduleId, &data, 0); + if (ret < 0) { + err("wait ci read failed"); + return ret; + } /* if */ + dbg("return CI, moduleId %d, data 0x%p, size %d", + data.moduleId, data.data, data.size); + return ret; +} +EXPORT_SYMBOL(cimax_usb_ci_read_evt); + +int cimax_usb_device_open(struct device_s *device) +{ + return device_drv_open(device); +} +EXPORT_SYMBOL(cimax_usb_device_open); + +int cimax_usb_device_unlock_read(struct device_s *device) +{ + int ret = 0; + if (!device) + return 0; + mutex_lock(&device->lock); + ret = device_ci_unlock_read(device); + mutex_unlock(&device->lock); + return ret; +} +EXPORT_SYMBOL(cimax_usb_device_unlock_read); + +int cimax_usb_device_close(struct device_s *device) +{ + if (!device) + return 0; + cimax_usb_device_unlock_read(device); + if (cimax_usb_dev_remove) + cimax_usb_dev_remove(device, gdeviceNumber); + return device_drv_close(device); +} +EXPORT_SYMBOL(cimax_usb_device_close); + +static long device_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct device_s *device = (struct device_s *)file->private_data; + int err = 0; + int ret = 0; + struct ioctl_data_s data; + void *transfer_buffer = NULL; + + dbg("start"); + + /* Don't decode wrong cmds: return ENOTTY (inappropriate ioctl) */ + if (_IOC_TYPE(cmd) != DEVICE_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > DEVICE_IOC_MAXNR) + return -ENOTTY; + + /* Verify direction (read/write) */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + if (mutex_lock_interruptible(&device->lock)) + return -ERESTARTSYS; + + switch (cmd) { + case DEVICE_IOC_SELECT_INTF: + dbg("DEVICE_IOC_SELECT_INTF start"); + ret = cimax_usb_select_interface(device, arg); + dbg("DEVICE_IOC_SELECT_INTF end"); + break; + + case DEVICE_IOC_CI_WRITE: + dbg("DEVICE_IOC_CI_WRITE start"); + + /* send CI message */ + ret = copy_from_user(&data, + (void __user *)arg, sizeof(struct ioctl_data_s)); + dbg("inMsg, rx 0x%p, rxSize %d, tx 0x%p, txSize %d", + data.rxData, + data.rxSize, + data.txData, + data.txSize); + ret = device_ci_write_ioctl(device, &data); + if (ret < 0) + break; + ret = copy_to_user((void __user *)arg, + &data, sizeof(struct ioctl_data_s)); + + dbg("DEVICE_IOC_CI_WRITE end"); + break; + + case DEVICE_IOC_UNLOCK_READ: + dbg("DEVICE_IOC_UNLOCK_READ start"); + + ret = device_ci_unlock_read(device); + + dbg("DEVICE_IOC_UNLOCK_READ end"); + break; + + case DEVICE_IOC_SET_CONFIG: + dbg("DEVICE_IOC_SET_CONFIG start"); + + /* send CI message */ + ret = copy_from_user(&data, + (void __user *)arg, sizeof(struct ioctl_data_s)); + dbg("inMsg, rx 0x%p, rxSize %d, tx 0x%p, txSize %d", + data.rxData, data.rxSize, + data.txData, data.txSize); + transfer_buffer = kmalloc(data.txSize, GFP_KERNEL); + memcpy(transfer_buffer, data.txData, data.txSize); + dbg_dump("New config", transfer_buffer, data.txSize); + err = usb_control_msg(device->usbdev, + usb_sndctrlpipe(device->usbdev, 0), + USB_REQ_SET_DESCRIPTOR, + USB_TYPE_STANDARD, + (USB_DT_CONFIG << 8), + 0, + transfer_buffer, + data.txSize, + 5000); + if (err < 0) { + err("set_config failed %d", err); + ret = -EINVAL; + } + kfree(transfer_buffer); + dbg("DEVICE_IOC_SET_CONFIG end"); + break; + + default: + ret = -ENOIOCTLCMD; + break; + } /* switch */ + mutex_unlock(&device->lock); + + dbg("end, ret %d", ret); + return ret; +} /* device_ioctl */ + +static ssize_t device_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int ret; + struct rw_data_s data; + struct device_s *device = (struct device_s *)file->private_data; + + dbg("start"); + + /* get transmission buffer */ + ret = copy_from_user(&data, buf, sizeof(struct rw_data_s)); + dbg("txBuffer, moduleId %u, data 0x%p, size %d", + data.moduleId, data.data, data.size); + if (data.moduleId >= DEVICE_NUM_CAM) { + err("bad moduleId"); + return 0; + } + + if (device->useIsoc) { + if (!data.size || (data.size % DEVICE_ISOC_LENGTH( + device->channel[data.moduleId].maxPacketSize))) { + err("transmission buffer size must be a multiple of %d", + DEVICE_ISOC_LENGTH( + device->channel[data.moduleId].maxPacketSize)); + return -EINVAL; + } /* if */ + } + + if (device->useIsoc) { + if (device->channel[data.moduleId].isocInUrb[0] == NULL) { + ret = device_start_iso_in(device, data.moduleId); + if (ret < 0) + return ret; + } /* if */ + + if (device->channel[data.moduleId].isocOutUrb[0] == NULL) { + ret = device_start_iso_out(device, data.moduleId); + if (ret < 0) + return ret; + } /* if */ + + dbg("call device_tsiso_send moduleId %d, data 0x%p, size %d", + data.moduleId, data.data, data.size); + ret = device_tsiso_send(device, + data.moduleId, data.data, data.size); + } /* if */ + else { + ret = device_tsbulk_send(device, + data.moduleId, data.data, data.size); + } /* else */ + + dbg("end, moduleId %d return %d", data.moduleId, ret); + return ret; +} /* device_write */ + +static ssize_t device_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int res; + struct rw_data_s data; + struct device_s *device = (struct device_s *)file->private_data; + + dbg("start"); + + if (count != sizeof(struct rw_data_s)) { + err("try to read uncorrect size %zd", count); + return -EFAULT; + } /* if */ + res = copy_from_user(&data, buf, sizeof(struct rw_data_s)); + data.copiedSize = 0; + if (data.type == DEVICE_TYPE_TS_READ) { + res = device_fill_ts(device, data.moduleId, &data); + if (res < 0) { + err("fill ts buffer failed"); + return res; + } /* if */ + dbg("return TS, moduleId %d, data 0x%p, size %d, copiedSize %d", + data.moduleId, data.data, data.size, data.copiedSize); + /*res = count;*/ + res = data.copiedSize; + } /* if */ + else if (data.type == DEVICE_TYPE_CI_READ) { + res = device_wait_async_data(device, data.moduleId, &data, 1); + if (res < 0) { + err("wait ci read failed"); + return res; + } /* if */ + dbg("return CI, moduleId %d, data 0x%p, size %d", + data.moduleId, data.data, data.size); + res = data.size; + } /* else if */ + else { + err("unknown data type %d", data.type); + res = -EFAULT; + } /* else */ + + dbg("end, return %d", res); + return res; +} /* device_read */ + +/****************************************************************************** + * @brief + * write data on Control endpoint. + * + + * @param dev + * Pointer to usb device. + * + * @param addr + + * register address to write. + * + * @param data + * data to write. + * + + * @param size + * size to write. + * + * @return + + * data writen or ENODEV error + ******************************************************************************/ +int write_ctrl_message(struct usb_device *dev, int addr, void *data, int size) +{ + int ret; + void *ptr = NULL; +#ifdef DEBUG + /* int i;*/ + /* unsigned char dump[500];*/ +#endif + + /* info("%s: . addr = %04x size=%d",DRIVER_NAME,addr,size);*/ + + if (size <= 0) + return 0; + + ptr = kmemdup(data, size, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xA0, 0x40, addr, 0x0001, + ptr, size, 300); + if (ret != size) { + err("Failed to write CIMaX+ register 0x%04x", addr); + ret = -ENODEV; + } + +#ifdef DEBUG + /* dump[0] =0; + for(i=0;i Init Status = %02X", *bootStatus); + if (bootStatus) + kfree(bootStatus); + return 0; + } + if (bootStatus) + kfree(bootStatus); + + return len; +} + +/****************************************************************************** + * @brief + * Start new Firmware. + * + * @param dev + * Pointer to usb device. + + * + * @return + * None. + ******************************************************************************/ +int write_ep6_message(struct usb_device *dev, void *data, int size) +{ + int ret; + void * ptr = NULL; + ptr = kmemdup(data, size, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + if (usb_bulk_msg(dev, usb_sndbulkpipe(dev, 6), + ptr, size, &ret, 200) < 0) { + err("Failed to write cmd 0x%02x", ((unsigned char *)data)[0]); + ret = -ENODEV; + } + kfree(ptr); + return ret; +} + +/****************************************************************************** + * @brief + * Start new Firmware. + * + * @param dev + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int read_ep5_message(struct usb_device *dev, void *data, int size) +{ + int ret; + + if (usb_interrupt_msg(dev, usb_rcvintpipe(dev, 5), + data, size, &ret, 200) < 0) { + err("Failed read interrupt endpoint"); + ret = -ENODEV; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long device_compat_ioctl(struct file *filp, + unsigned int cmd, unsigned long args) +{ + unsigned long ret; + + args = (unsigned long)compat_ptr(args); + ret = device_ioctl(filp, cmd, args); + return ret; +} +#endif + +static const struct file_operations device_fops = { + .owner = THIS_MODULE, + .open = device_open, + .release = device_release, + .unlocked_ioctl = device_ioctl, + .write = device_write, + .read = device_read, + /* + .poll = device_poll, + */ +#ifdef CONFIG_COMPAT + .compat_ioctl = device_compat_ioctl, +#endif +}; + +struct cimaxusb_priv_ops_t cimaxusb_priv_ops = { + .write_ctrl_message = write_ctrl_message, + .read_ctrl_message = read_ctrl_message, + .init_fw = init_fw, + .write_ep6_message = write_ep6_message, + .read_ep5_message = read_ep5_message +}; + +static struct usb_class_driver device_class = { + .name = "cimaxusb%d", + .fops = &device_fops, + .minor_base = DEVICE_MINOR, +}; + +/* ---------------------------------------------------------- */ + + +void cimax_usb_set_cb(void *cb1, void *cb2) +{ + cimax_usb_dev_add = cb1; + cimax_usb_dev_remove = cb2; +} +EXPORT_SYMBOL(cimax_usb_set_cb); + +static int device_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = interface_to_usbdev(intf); + struct device_s *device; + char cmd[] = { 0x0C, 0x01, 0x00, 0x00 }; + char *rsp; + + dbg("start vendor id 0x%x, product id 0x%x, Device id 0x%x minor 0x%x", + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct), + le16_to_cpu(usbdev->descriptor.bcdDevice), + intf->minor); + + /* device = &gdevice[intf->minor];*/ + device = &gdevice[gdeviceNumber]; + + mutex_lock(&device->lock); + /* device->usbdev = usbdev;*/ + device->usbdev = usb_get_dev(usbdev); + dbg("device->usbdev 0x%p", (device->usbdev)); + + /* set private callback functions */ + device->ops = &cimaxusb_priv_ops; + + device->askToSuspend = 0; + + usb_set_intfdata(intf, device); + mutex_unlock(&device->lock); + + if (usb_register_dev(intf, &device_class)) { + err("usb_register_dev"); + usb_set_intfdata(intf, NULL); + return -ENOMEM; + } /* if */ + + /* test if firmware loafing is needed */ +#ifdef FRBIT + if ((le16_to_cpu(usbdev->descriptor.bcdDevice) != 0) && + (CimaxDwnl == 1)) { +#else + if (le16_to_cpu(usbdev->descriptor.bcdDevice) != 0) { +#endif + info("start firmware download"); + /* load firmware*/ + cimaxusb_fw_upload(device); + info("end firmware download"); + } else { + info("set alternate setting 1"); + if (usb_set_interface(device->usbdev, 0, 1) < 0) { + err("set_interface failed intf 0, alt 1"); + } else { + info("check FW version"); + /* Get BOOT version */ + if (write_ep6_message(device->usbdev, + cmd, sizeof(cmd)) == sizeof(cmd)) { + rsp = kcalloc(256, + sizeof(unsigned char), + GFP_KERNEL); + if (!rsp) { + err("out of memory"); + return -ENOMEM; + } + if (read_ep5_message(device->usbdev, + rsp, 256) >= 0) { + info("=> ---- F.W. Version -------"); + info("=>= %02X.%02X.%02X.%02X.%02X%c", + rsp[4], rsp[5], rsp[6], + rsp[7], rsp[8], rsp[9]); + info("=> Boot Version = %d.%d", + rsp[10], rsp[11]); + info("=> --------------------"); + } + kfree(rsp); + } + } + info("start cfg download"); + if (cimaxusb_configuration_setting(device) < 0) + err(" Error : set CIMaX+ configuration"); + info("end cfg download"); + + if (cimax_usb_dev_add) + cimax_usb_dev_add(device, gdeviceNumber); + } + + dbg("end"); + return 0; +} /* device_probe */ + +static void device_disconnect(struct usb_interface *intf) +{ + struct device_s *device = usb_get_intfdata(intf); + int i; + + dbg("start"); + + if (!device) + return; + + mutex_lock(&device->lock); + if (device->opened) { + /* release blocking functions */ + device->askToRelease = 1; + wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); + wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); + wake_up_interruptible(&device->channel[0].inWait); + wake_up_interruptible(&device->channel[1].inWait); + device_stop_intr(device); + for (i = 0; i < DEVICE_NUM_CAM; i++) { + if (device->useIsoc) { + device_stop_iso_out(device, i); + device_stop_iso_in(device, i); + } /* if */ + else + device_stop_tsbulk_in(device, i); + } /* for */ + device->opened = 0; + + if (cimax_usb_dev_remove) + cimax_usb_dev_remove(device, gdeviceNumber); + } /* if */ + mutex_unlock(&device->lock); + usb_set_intfdata(intf, NULL); + if (device) { + usb_deregister_dev(intf, &device_class); + device->usbdev = NULL; + } /* if */ + dbg("end"); +} /* device_disconnect */ + +static int cimaxusb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct device_s *device = usb_get_intfdata(intf); + int i; + + dbg("start"); + + if (!device) + return 0; + + mutex_lock(&device->lock); + if (device->opened) { + /* release blocking functions */ + device->askToSuspend = 1; + wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); + wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); + wake_up_interruptible(&device->channel[0].inWait); + wake_up_interruptible(&device->channel[1].inWait); + device_stop_intr(device); + for (i = 0; i < DEVICE_NUM_CAM; i++) { + if (device->useIsoc) { + device_stop_iso_out(device, i); + device_stop_iso_in(device, i); + } /* if */ + else + device_stop_tsbulk_in(device, i); + } /* for */ + device->opened = 0; + } /* if */ + mutex_unlock(&device->lock); + dbg("end"); + + return 0; +} + +static int cimaxusb_resume(struct usb_interface *intf) +{ + struct device_s *device = usb_get_intfdata(intf); + + dbg("start"); + + if (!device) + return 0; + + device->askToSuspend = 0; + dbg("end"); + return 0; +} + +static struct usb_device_id device_ids[] = { + { USB_DEVICE(0x1b0d, 0x2f00) }, + { USB_DEVICE(0x1b0d, 0x2f01) }, + { USB_DEVICE(0x1b0d, 0x2f02) }, + { USB_DEVICE(0x1b0d, 0x2f03) }, + { USB_DEVICE(0x1b0d, 0x2f04) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, device_ids); + + +static struct usb_driver device_driver = { + .name = "cimaxusb", + .probe = device_probe, + .disconnect = device_disconnect, + .suspend = cimaxusb_suspend, + .resume = cimaxusb_resume, + .id_table = device_ids, +}; + +/* ---------------------------------------------------------- */ + +static int device_init_module(void) +{ + int ret = 0; + int i, j; + struct device_s *device; + + info("start"); + + if (!gdevice) + gdevice = kcalloc(DRIVER_MAX_NUMBER, + sizeof(struct device_s), GFP_KERNEL); + if (!gdevice) { + err("not enough memory"); + return -ENOMEM; + } + + for (i = 0; i < DRIVER_MAX_NUMBER; i++) { + device = &gdevice[i]; + /* initialize struct */ + memset(device, 0, sizeof(struct device_s)); + mutex_init(&device->lock); + + /* initialize ci bulk struct */ + device->ciBulk.counter = 1; + spin_lock_init(&device->ciBulk.intLock); + spin_lock_init(&device->ciBulk.intUrbLock); + for (j = 0; j < DEVICE_NUM_CAM; j++) { + init_waitqueue_head(&device->ciBulk.ciData[j].syncWait); + init_waitqueue_head( + &device->ciBulk.ciData[j].asyncWait); + INIT_LIST_HEAD(&device->ciBulk.ciData[j].asyncDataList); + } /* for */ + + /* initialize channels */ + for (j = 0; j < DEVICE_NUM_CAM; j++) { + spin_lock_init(&device->channel[j].inLock); + init_waitqueue_head(&device->channel[j].inWait); + vb_init(&device->channel[j].inVb); + device->channel[j].syncOffset = -1; + spin_lock_init(&device->channel[j].outLock); + } /* for */ + } /* for */ + + /* register misc device */ + ret = usb_register(&device_driver); + +#ifdef TIMESTAMP + InitTimestamp(); +#endif + + if (ret) + info("end driver register failed"); + else + info("end driver registered"); + + info(DRIVER_VERSION ":" DRIVER_DESC); + + return ret; +} /* device_init_module */ + +static void device_exit_module(void) +{ + int i; + struct device_s *device; + + info("start"); + +#ifdef TIMESTAMP + ShowTimestamp(); +#endif + + for (i = 0; i < DRIVER_MAX_NUMBER; i++) { + device = &gdevice[i]; + device->askToRelease = 1; + /* destroy struct */ + mutex_destroy(&device->lock); + } /* for */ + usb_deregister(&device_driver); + gdeviceNumber = 0; + + kfree(gdevice); + gdevice = NULL; + info("end"); +} /* device_exit_module */ + +module_init(device_init_module); +module_exit(device_exit_module); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h new file mode 100644 index 000000000000..e4656e0e54f8 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h @@ -0,0 +1,362 @@ +/**************************************************************************//** + * @file cimax+usb-driver.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#include + +#ifndef CIMAXPLUS_USB_DRIVER_H +#define CIMAXPLUS_USB_DRIVER_H + +/****************************************************************************** + * Includes + *****************************************************************************/ +/****************************************************************************** + * Defines + *****************************************************************************/ +/** + * @brief + * Driver Name + */ +#define DRIVER_NAME "cimax+usb" +/** + * @brief + * An unassigned USB minor. + */ +#define DEVICE_MINOR 240 + +/** + * @brief + * Driver version. + */ +#define DEVICE_VERSION 0x1000 + +/** + * @brief + * Number of CA module supported by the driver. + */ +#define DEVICE_NUM_CAM 2 + +/** + * @brief + * Buffer length. + */ +#define DEVICE_MESSAGE_LENGTH 4100 + +/* Offset */ +#define DEVICE_COMMAND_OFFSET 0 +#define DEVICE_STATUS_OFFSET 0 +#define DEVICE_COUNTER_OFFSET 1 +#define DEVICE_LENGTH_MSB_OFFSET 2 +#define DEVICE_LENGTH_LSB_OFFSET 3 +#define DEVICE_DATA_OFFSET 4 + +/* Mask */ +#define DEVICE_SEL_MASK 0x80 +#define DEVICE_TYP_MASK 0x40 +#define DEVICE_CMD_MASK 0x3F + +/* Command tag */ +#define DEVICE_CMD_INIT 0x00 +#define DEVICE_CMD_WRITE_REG 0x7F +#define DEVICE_CMD_READ_REG 0xFF +#define DEVICE_CMD_CAMRESET 0x01 +#define DEVICE_CMD_GETCIS 0x02 +#define DEVICE_CMD_WRITECOR 0x03 +#define DEVICE_CMD_NEGOTIATE 0x04 +#define DEVICE_CMD_WRITELPDU 0x05 +#define DEVICE_CMD_READLPDU 0x06 +#define DEVICE_CMD_WRITEEXT 0x07 +#define DEVICE_CMD_READEXT 0x08 +#define DEVICE_CMD_CC1RESET 0x09 +#define DEVICE_CMD_MCARD_WRITE 0x0a + +/* Status field */ +#define DEVICE_CAMRESETOK 0x00 +#define DEVICE_CISOK 0x01 +#define DEVICE_WRITECOROK 0x02 +#define DEVICE_NEGOTIATEOK 0x03 +#define DEVICE_WRITELPDUOK 0x04 +#define DEVICE_CAMDET 0x05 +#define DEVICE_READLPDUOK 0x06 +#define DEVICE_WRITEEXTOK 0x07 +#define DEVICE_READEXTOK 0x08 +#define DEVICE_NO_CAM 0x09 +#define DEVICE_NOK 0x0a +#define DEVICE_INITOK 0x0b +#define DEVICE_READ_REGOK 0x0c +#define DEVICE_WRITE_REGOK 0x0d +#define DEVICE_DATAREADY 0x0e +#define DEVICE_MCARD_WRITEOK 0x0f +#define DEVICE_MCARD_READ 0x10 +#define DEVICE_CAMPARSE_ERROR 0x11 +#define DEVICE_WRITELPDUBUSY 0x14 +#define DEVICE_CMDPENDING 0x16 +#define DEVICE_REGSTATUSOK 0x17 +#define DEVICE_GPIOCHANGE 0x18 +#define DEVICE_FRBit 0x1A + + +#define DEVICE_DATAREADY_SYNC 0x3e + +/** + * @brief + * MPEG2 transport size,.isochronous size and number of frames per URB. + */ +#define DEVICE_MPEG2_PACKET_SIZE 188 +#define DEVICE_MPEG2_SYNC_BYTE 0x47 +#define DEVICE_NULL_HEADER_SIZE 8 +#define DEVICE_NUM_FRAMES_PER_URB 8 +#define DEVICE_ISOC_LENGTH(x) (DEVICE_NUM_FRAMES_PER_URB*x) +#define DEVICE_VB_LENGTH 902400 + +/** + * @brief + * Endpoint address. + */ +#define DEVICE_TS_IN_PIPE 1 /* and 2 */ +#define DEVICE_TS_OUT_PIPE 3 /* and 4 */ +#define DEVICE_INT_IN_PIPE 5 +#define DEVICE_BULK_OUT_PIPE 6 +#define DEVICE_BULK_OUT_MAXPACKET 256 + +/** + * @brief + * Number of isochronous/int URBs in the driver. + */ +#define DEVICE_NUM_ISOC_OUT_URBS 3 +#define DEVICE_NUM_ISOC_IN_URBS 2 +#define DEVICE_NUM_INT_IN_URBS 2 + +/** + * @brief + * ioctl() calls definition. + */ +#define DEVICE_IOC_MAGIC 'a' +#define DEVICE_IOC_SELECT_INTF _IOWR(DEVICE_IOC_MAGIC, 0, signed long) +#define DEVICE_IOC_CI_WRITE _IOWR(DEVICE_IOC_MAGIC, 1, struct ioctl_data_s) +#define DEVICE_IOC_UNLOCK_READ _IOWR(DEVICE_IOC_MAGIC, 2, signed long) +#define DEVICE_IOC_SET_CONFIG _IOWR(DEVICE_IOC_MAGIC, 3, struct ioctl_data_s) +#define DEVICE_IOC_MAXNR 4 + +/****************************************************************************** + * Types + *****************************************************************************/ +#ifdef __KERNEL__ +#include +#include +#include + +#undef dbg +#undef dbg_isoc_in +#undef dbg_isoc_out + +#undef err +#undef info +#undef warn + +#define DEBUG + +#ifdef DEBUG +#define dbg(format, arg...) pr_debug("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#define dbg_s(format, arg...)\ + pr_debug("cimax+usb: " format "\n" , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#define dbg_s(format, arg...) do {} while (0) +#endif + +#ifdef DEBUG_ISOC_IN +#define dbg_isoc_in(format, arg...)\ + pr_debug("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#else +#define dbg_isoc_in(format, arg...) do {} while (0) +#endif + +#ifdef DEBUG_ISOC_OUT +#define dbg_isoc_out(format, arg...)\ + pr_debug("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#else +#define dbg_isoc_out(format, arg...) do {} while (0) +#endif + +#define err(format, arg...)\ + pr_err("cimax+usb: %s> ERROR " format "\n" , \ + __func__, ## arg) +#define info(format, arg...)\ + pr_info("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#define warn(format, arg...)\ + pr_warn("cimax+usb: %s> WARN" format "\n" , \ + __func__, ## arg) + +/** + * @brief + * Video buffer structure. + */ +struct video_buf_s { + __u8 data[DEVICE_VB_LENGTH]; + int readOffset; + int writeOffset; + int isEmpty; +}; +#endif + +/** + * @brief + * Io control data structure exchanged between user and kernel space. + */ +struct ioctl_data_s { + __u8 *txData; + __u32 txSize; + __u8 *rxData; + __u32 rxSize; +}; + +/** + * @brief + * Read/write type exchanged between user and kernel space. + */ +enum rw_type_e { + DEVICE_TYPE_CI_READ, + DEVICE_TYPE_TS_WRITE, + DEVICE_TYPE_TS_READ +}; + +/** + * @brief + * Read/write data structure exchanged between user and kernel space. + */ +struct rw_data_s { + enum rw_type_e type; + __u8 moduleId; + __u8 *data; + __u32 size; + __u32 copiedSize; +}; +#ifdef __KERNEL__ +/** + * @brief + * Message node structure. Can be inserted in a list. + */ +struct message_node_s { + __u8 data[DEVICE_MESSAGE_LENGTH]; + __u32 size; + struct list_head node; +}; + +/** + * @brief + * Received CI data. + */ +struct ci_rx_data_s { + wait_queue_head_t syncWait; + __u8 syncSignal; + __u8 syncData[DEVICE_MESSAGE_LENGTH]; + __u32 syncDataSize; + wait_queue_head_t asyncWait; + struct list_head asyncDataList; + __u8 bPendingSend; +}; + +/** + * @brief + * CI bulk channel. + */ +struct ci_bulk_s { + __u8 counter; + __u16 inMaxPacketSize; + __u16 outMaxPacketSize; + struct urb *intUrb[DEVICE_NUM_INT_IN_URBS]; + spinlock_t intLock; + spinlock_t intUrbLock; + __u8 intCurrStatus; + __u8 intCurrIndex; + __u16 intSizeToReceive; + struct ci_rx_data_s ciData[DEVICE_NUM_CAM]; +}; + +/** + * @brief + * TS channel (can use isoc or bulk interface). + */ +struct ts_channel_s { + spinlock_t inLock; + wait_queue_head_t inWait; + struct video_buf_s inVb; + int syncOffset; + int prevOffset; + __u8 lastPacket[DEVICE_MPEG2_PACKET_SIZE]; + __u8 lastPacketSize; + spinlock_t outLock; + __u8 nextFreeOutUrbIndex; + atomic_t numOutUrbs; + __u8 outStop; + __u16 maxPacketSize; + /* isochronous urbs */ + struct urb *isocInUrb[DEVICE_NUM_ISOC_IN_URBS]; + struct urb *isocOutUrb[DEVICE_NUM_ISOC_OUT_URBS]; + /* bulk urbs */ + struct urb *bulkInUrb; + int nbByteSend; + int nbByteRead; + __u8 FirstTransfer; + struct timer_list StartBulkReadTimer; + +#ifdef DEBUG_BITRATE + ktime_t bitrateTime +#endif +}; + +struct device_s { + struct mutex lock; + struct usb_device *usbdev; + __u8 opened; + __u8 askToRelease; + __u8 askToSuspend; + struct ci_bulk_s ciBulk; + __u8 useIsoc; + struct ts_channel_s channel[DEVICE_NUM_CAM]; + /* bus adapter private ops callback */ + struct cimaxusb_priv_ops_t *ops; + int ref; +}; + +struct bulk_timer_s { + struct device_s *device; + __u8 index; +}; + +int cimax_usb_select_interface(struct device_s *device, unsigned long intf); +int cimax_usb_ci_write(struct device_s *device, + u8 *txData, int txSize, u8 *rxData, int rxSize); +int cimax_usb_ci_read_evt(struct device_s *device, + int moduleId, u8 *buf, int size); + +int cimax_usb_device_unlock_read(struct device_s *device); +int cimax_usb_device_open(struct device_s *device); +int cimax_usb_device_close(struct device_s *device); +void cimax_usb_set_cb(void *cb1, void *cb2); + + +#endif +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c new file mode 100644 index 000000000000..4469b872995b --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c @@ -0,0 +1,684 @@ +/**************************************************************************//** + * @file cimax+usb_config.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ +/****************************************************************************** + * Include + ******************************************************************************/ + + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "cimax+usb-driver.h" +#include "cimax+usb_config.h" +#include "bodydef.h" + +#include + +#define DEBUG +#include + +/****************************************************************************** + * Structures + ******************************************************************************/ +/****************************************************************************** + * Globals + ******************************************************************************/ +char *cimax_config_file[4] = { + "cimax+usb.cfg", + "cimax+usb_vcc0.cfg", + "cimax+usb_vcc3.cfg", + "cimax+usb_vcc5.cfg" +}; + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * set CIMaX+ register value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * CIMaX+ register value to set. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int usb_setbyte(struct device_s *bus_adap, unsigned int addr, unsigned char val) +{ + unsigned char cmd[5]; + unsigned char *buf; + int len; + struct usb_device *dev = bus_adap->usbdev; + + cmd[0] = 0x7F; + cmd[1] = (unsigned char)((addr>>8)&0xff); + cmd[2] = (unsigned char)(addr&0xff); + cmd[3] = 0x01; + cmd[4] = val; + if (bus_adap->ops->write_ep6_message(dev, cmd, sizeof(cmd)) + == sizeof(cmd)) { + /*pr_debug("%s-%s: cmd=0x%x\n", + DRIVER_NAME, __func__,cmd[0]);*/ + buf = kcalloc(256, sizeof(unsigned char), GFP_KERNEL); + if (!buf) { + pr_err("%s-%s: out of memory.\n", + DRIVER_NAME, __func__); + return -ENOMEM; + } + + while ((len = bus_adap->ops->read_ep5_message(dev, buf, 256)) + >= 0) { + if (len == 0) + continue; + if ((len == 5) && ((buf[0] & 0x7f) == 0x45)) + continue; + if (len < 4) { + pr_err("%s-%s: failed to read addr 0x%x\n", + DRIVER_NAME, __func__, addr); + kfree(buf); + return -1; + } else { + break; + } + } + } else { + pr_err("%s-%s: failed to write addr 0x%x\n", + DRIVER_NAME, __func__, addr); + return -1; + } + kfree(buf); + return 0; +} + +/****************************************************************************** + * @brief + * get CIMaX+ register value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int usb_getbyte(struct device_s *bus_adap, + unsigned int addr, unsigned char *val) +{ + unsigned char cmd[4]; + unsigned char *buf; + int len; + struct usb_device *dev = bus_adap->usbdev; + + cmd[0] = 0xFF; + cmd[1] = (unsigned char)((addr>>8)&0xff); + cmd[2] = (unsigned char)(addr&0xff); + cmd[3] = 0x01; + if (bus_adap->ops->write_ep6_message(dev, cmd, sizeof(cmd)) + == sizeof(cmd)) { + /*pr_debug("%s-%s: cmd=0x%x\n", + DRIVER_NAME, __func__,cmd[0]);*/ + buf = kcalloc(256, sizeof(unsigned char), GFP_KERNEL); + if (!buf) { + pr_err("%s-%s: out of memory.\n", + DRIVER_NAME, __func__); + return -ENOMEM; + } + + while ((len = bus_adap->ops->read_ep5_message(dev, buf, 256)) + >= 0) { + if (len == 0) + continue; + /*pr_debug("%s-%s: 0x%x\n", + DRIVER_NAME, __func__,buf[0]);*/ + if ((len == 5) && ((buf[0] & 0x7f) == 0x45)) + continue; + if (len >= 5) { + *val = buf[4]; + break; + } else { + pr_err("%s-%s: failed to read addr 0x%x\n", + DRIVER_NAME, __func__, addr); + kfree(buf); + return -1; + } + } + } else { + pr_err("%s-%s: failed to read addr 0x%x\n", + DRIVER_NAME, __func__, addr); + return -1; + } + kfree(buf); + return 0; +} + +/****************************************************************************** + * @brief + * compute a logical Or between CIMaX+ register value and a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to compute. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int setLogicalOr(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + *pval |= val; + + if (usb_setbyte(bus_adap, addr, *pval) < 0) + return -1; + + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("=> Logical OR [%02X] => %02X\n", val, *pval); + + return 0; +} + +/****************************************************************************** + * @brief + * compute a logical And between CIMaX+ register value and a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to compute. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int setLogicalAnd(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + *pval &= val; + + if (usb_setbyte(bus_adap, addr, *pval) < 0) + return -1; + + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("=> Logical AND [%02X] => %02X\n", val, *pval); + + return 0; +} + +/****************************************************************************** + * @brief + * wait CIMaX+ register value match a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to match. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int waitForValue(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + dbg("=> Wait for Value [%02X]\n", val); + if (*pval == val) + return 0; + + while (1) { + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("\r => %02X", *pval); + + if (*pval == val) + break; + } + + dbg("\n"); + + return 0; +} + +/****************************************************************************** + * @brief + * wait CIMaX+ register bits match a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to match. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int waitForBitsSet(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + dbg("=> Wait for Bits set [%02X]\n", val); + if ((*pval & val) == val) + return 0; + + while (1) { + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("\r => %02X", *pval); + + if ((*pval & val) == val) + break; + } + + dbg("\n"); + + return 0; +} + +/****************************************************************************** + * @brief + * wait CIMaX+ register bits cleared. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * bits to check. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int waitForBitsCleared(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + dbg("=> Wait for Bits cleared [%02X]\n", val); + if ((*pval & val) == 0x00) + return 0; + + while (1) { + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("\r => %02X", *pval); + + if ((*pval & val) == 0x00) + break; + } + + dbg("\n"); + + return 0; +} + +/****************************************************************************** + * @brief + * retreive addr of CIMaX+ register. + * + * @param dev + * Pointer to CIMaX+ register Name. + * + * @return + * Address of CIMaX+ register. + *****************************************************************************/ +int cimaxusb_rtr_reg_addr(char *str_addr) +{ + int i32NbItem = sizeof(cimax_reg_map) / sizeof(struct reg_s); + int i32index; + int i32ValAddr = -1; + + for (i32index = 0; i32index < i32NbItem; i32index++) { + if (strcmp(str_addr, cimax_reg_map[i32index].RegisterName) + == 0) { + i32ValAddr = cimax_reg_map[i32index].RegAddr; + break; + } + } + return i32ValAddr; +} + +static int cimaxusb_parse_cfg_ops(struct device_s *bus_adap, + unsigned char **pptr, size_t *plen) +{ + unsigned char op; + int ret; + char param1[256], param2[256]; + char line[256], *ptr_line; + int val; + unsigned char val2; + unsigned int addr; + unsigned char *ptr = *pptr; + size_t len = *plen; + + ptr_line = line; + op = *ptr; + ret = sscanf(ptr, "%s %s", param1, param2); + ptr++; + len++; + if (sscanf(ptr, "%s %X", param1, &val) != 2) + return -EFAULT; + /*pr_debug("%s: param1=%s,param2=%s, val=%x\n", + DRIVER_NAME, param1, param2, val);*/ + strcpy(ptr_line, param1); + len += strlen(param1); + ptr += strlen(param1); + strncat(ptr_line, ptr, 1); + len++; + ptr++; + strcat(ptr_line, param2); + len += strlen(param2); + ptr += strlen(param2); + /*pr_debug("%s: len = %08d line: %s\n", + DRIVER_NAME, len, line);*/ + addr = cimaxusb_rtr_reg_addr(param1); + if (((signed)addr) < 0) { + pr_err("%s: unknown register name: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_getbyte(bus_adap, addr, &val2) < 0) { + pr_err("%s: CIMaX+ register reading problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + + switch (op) { + case '=': + if (waitForValue(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : waitForValue failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : wait for value ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '?': + if (waitForBitsSet(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : waitForBitsSet failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : wait for bitsset ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '!': + if (waitForBitsCleared(bus_adap, addr, val, &val2) + == -1) { + pr_err("%s : waitForBitsCleared failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : wait for bits cleared ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '|': + if (setLogicalOr(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : setLogicalOr failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : setOr ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '&': + if (setLogicalAnd(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : setLogicalAnd failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : setAnd ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + default: + pr_err("Error: Marker Unknown <%c> !!!\n", op); + return -ENODEV; + } + *pptr = ptr; + *plen = len; + return 0; +} + +static int cimaxusb_parse_cfg_default(struct device_s *bus_adap, + unsigned char **pptr, size_t *plen) +{ + unsigned char *ptr = *pptr; + size_t len = *plen; + int ret; + char param1[256], param2[256]; + char line[256], *ptr_line; + int val; + unsigned char val2; + unsigned int addr; + + ptr_line = line; + + ret = sscanf(ptr, "%s %s", param1, param2); + ret = sscanf(param2, "%X", &val); + /*pr_debug("%s: param1=%s,param2=%s,val=%x\n", + DRIVER_NAME,param1,param2,val);*/ + strcpy(ptr_line, param1); + len += strlen(param1); + ptr += strlen(param1); + strncat(ptr_line, ptr, 1); + len++; + ptr++; + strcat(ptr_line, param2); + len += strlen(param2); + ptr += strlen(param2); + /*pr_debug("%s: len = %08d line: %s\n", + DRIVER_NAME, len, line);*/ + addr = cimaxusb_rtr_reg_addr(param1); + if (((signed)addr) < 0) { + pr_err("%s: unknown register name: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_getbyte(bus_adap, addr, &val2) < 0) { + pr_err("%s: CIMaX+ register reading problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_setbyte(bus_adap, addr, val) < 0) { + pr_err("%s: CIMaX+ register writing problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_getbyte(bus_adap, addr, &val2) < 0) { + pr_err("%s: CIMaX+ register checking problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("set: %s(0x%04x) : 0x%02x\n", param1, addr, val); + + *pptr = ptr; + *plen = len; + return 0; +} + +/****************************************************************************** + * @brief + * parse CIMaX+ config file. + * + * @param dev + * Pointer to usb device. + * + * @param fw_data + * Pointer to buffer with firmware data. + * + * @return + * O if no error otherwise errno. + *****************************************************************************/ +int cimaxusb_parse_cfg(struct device_s *bus_adap, + const unsigned char *cfg_data, size_t size) +{ + char line[256], *ptr_line; + size_t len = 0; + unsigned char *ptr = (unsigned char *)cfg_data; + int ret = -EFAULT; + + dbg("%s: %s size = %zd\n", DRIVER_NAME, __func__, size); + do { + ptr_line = line; + switch (*ptr) { + case ';': + /* continue up to find \r character */ + while (*ptr != 0x0A) { + *ptr_line++ = *ptr; + ptr++; + len++; + } + *ptr_line = 0; + /*pr_debug("%s: len = %08d line: %s\n", + DRIVER_NAME, len, line);*/ + break; + case 0x0A: + case 0x0D: + ptr++; + len++; + break; + case '=': + case '?': + case '!': + case '|': + case '&': + ret = cimaxusb_parse_cfg_ops(bus_adap, &ptr, &len); + if (ret < 0) + return ret; + break; + default: + ret = cimaxusb_parse_cfg_default(bus_adap, &ptr, &len); + if (ret < 0) + return ret; + break; + } + } while (len < size); + + return (ret == -EFAULT) ? 0 : ret; +} + +/****************************************************************************** + * @brief + * read configuration file ( CIMAX_CONFIG_NAME) and set in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +/* +opt: 0: init, 1: off, 2: Vcc3.3 3: Vcc5 +*/ +int cimaxusb_configuration_setting_opt(struct device_s *bus_adap, int opt) +{ + int errno = -EFAULT; + const struct firmware *config; + char *cfg = cimax_config_file[opt]; + + struct usb_device *dev = bus_adap->usbdev; + + dbg("request configuration file"); + /* request kernel to locate firmware file */ + errno = request_firmware(&config, cfg, &dev->dev); + if (errno < 0) { + pr_err("%s: unable to locate configuration file: %s\n", + DRIVER_NAME, cfg); + goto error; + } + + dbg("parse configuration file"); + errno = cimaxusb_parse_cfg(bus_adap, config->data, config->size); + if (errno < 0) { + pr_err("%s: unable to parse config file: %s\n", + DRIVER_NAME, cfg); + goto error; + } + +error: + /* release firmware if needed */ + if (config != NULL) + release_firmware(config); + return errno; +} + +int cimaxusb_configuration_setting(struct device_s *bus_adap) +{ + return cimaxusb_configuration_setting_opt(bus_adap, 0); +} + +int cimaxusb_configuration_setting_vcc(struct device_s *bus_adap, int vcc) +{ + return cimaxusb_configuration_setting_opt(bus_adap, vcc); +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h new file mode 100644 index 000000000000..5c55204c62cc --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h @@ -0,0 +1,58 @@ +/**************************************************************************//** + * @file cimax+usb_config.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_CFG_H +#define __CIMAXPLUS_USB_CFG_H + +/****************************************************************************** + * Include + ******************************************************************************/ +#include "cimax+usb_handle.h" + +/****************************************************************************** + * Defines + ******************************************************************************/ +#define CIMAX_CONFIG_NAME "cimax+usb.cfg" + +/****************************************************************************** + * Enums + ******************************************************************************/ +/****************************************************************************** + * Structures + ******************************************************************************/ + +/****************************************************************************** + * Functions + ******************************************************************************/ + +/****************************************************************************** + * @brief + * read configuration file ( CIMAX_CONFIG_NAME) and set in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_configuration_setting(struct device_s *bus_adap); + +#endif + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c new file mode 100644 index 000000000000..6bccf4b8e64b --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c @@ -0,0 +1,325 @@ +/**************************************************************************//** + * @file cimax+usb_fw.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ +/****************************************************************************** + * Include + ******************************************************************************/ +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "cimax+usb-driver.h" +#include "cimax+usb_fw.h" + +/****************************************************************************** + * Structures + ******************************************************************************/ +/****************************************************************************** + * Globals + ******************************************************************************/ +char cimax_fw[] = CIMAX_FIRMWARE_NAME; + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * Start & check Bistrom. + * + * @param dev + * Pointer to usb device. + * + * @param startAddr + * start address of firmware to compute + * + * @param endAddr + * stop address of firmware to compute + * + * @param FWSign + * Current signature to check + * + * + * @return + * None. + ******************************************************************************/ +int checkBistRom(struct device_s *bus_adap, + int startAddr, int endAddr, int signature) +{ + unsigned char *Val; + int rv; + + struct usb_device *dev = bus_adap->usbdev; + + Val = kcalloc(2, sizeof(unsigned char), GFP_KERNEL); + if (!Val) { + pr_err("%s-%s: out of memory.\n", DRIVER_NAME, __func__); + return -ENOMEM; + } + + /* Write "Flash" Size + (!) BistRom is computed since D000-flashSize to D0000-6 + */ + Val[0] = (0xD000-startAddr)&0x00ff; + Val[1] = (0xD000-startAddr)>>8; + if (bus_adap->ops->write_ctrl_message(dev, 0x008D, Val, 2) != 2) { + kfree(Val); + return -1; + } + + /* Write Signature*/ + Val[0] = signature&0x00ff; + Val[1] = signature>>8; + if (bus_adap->ops->write_ctrl_message(dev, 0x0080, Val, 2) != 2) { + kfree(Val); + return -1; + } + + /* Launch BistRom [(D000-flashSize)..CFF9]+[FFFA..FFFF] computation*/ + Val[0] = 0x0F; + if (bus_adap->ops->write_ctrl_message(dev, 0x0082, Val, 1) != 1) { + kfree(Val); + return -1; + } + + pr_info("\n>>Read Signature\n"); + + /* Read Signature*/ + if (bus_adap->ops->read_ctrl_message(dev, 0x0041, Val, 2) != 2) { + kfree(Val); + return -1; + } + + pr_info("\n>> Bistrom computed = %04X\n", Val[0]|Val[1]<<8); + + /* Read Boot status*/ + if (bus_adap->ops->read_ctrl_message(dev, 0x0009, Val, 1) != 1) { + kfree(Val); + return -1; + } + + pr_info("\n>> BootRom Status = %02X\n", Val[0]); + rv = Val[0]; + kfree(Val); + + return rv; +} + +/****************************************************************************** + * @brief + * Compute BistRom. + * + * @param ptr + * Pointer to buffer with register data + * + * @param size + * Number of register to process + * + * @param FWSign + * Current signature + * + * @return + * None. + ******************************************************************************/ +unsigned int MISR(const unsigned char *ptr, int size, unsigned int FWSign) +{ + int k, i; + + unsigned short mySign; + + for (k = 0; k < size; k++) { + mySign = ptr[k]&0x01; + + for (i = 0; i < 16; i++) { + if (0x88B7 & (1<>i) & 0x01; + } + + mySign |= ((FWSign<<1)^(ptr[k])) & 0x00FE; + mySign |= (FWSign<<1) & 0x00FF00; + + FWSign = mySign; + } + + return FWSign; +} + + +/****************************************************************************** + * @brief + * upload firmware in CIMaX+ chip. + * + * @param dev + * Pointer to usb device. + * + * @param fw_data + * Pointer to buffer with firmware data. + * + * @param FWSign + * Pointer to store computed signature. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_firmware_upload(struct device_s *bus_adap, + const unsigned char *fw_data, unsigned int *FWSign) +{ + int errno = -EFAULT; + const unsigned char *ptr; + int startAddr = START_FW_ADDR; + unsigned char *recv; + int size; + + struct usb_device *dev = bus_adap->usbdev; + + /* data firmware */ + ptr = fw_data; + ptr += START_FW_ADDR; + + recv = kcalloc(300, sizeof(unsigned char), GFP_KERNEL); + if (!recv) { + pr_err("%s-%s: out of memory.\n", DRIVER_NAME, __func__); + return -ENOMEM; + } + + do { + /* compute the size to send to CIMaX+ */ + size = (startAddr <= (STOP_FW_ADDR + 1 - MAX_FW_PKT_SIZE)) ? + (MAX_FW_PKT_SIZE) : (STOP_FW_ADDR + 1 - startAddr); + /* compute Signature */ + *FWSign = MISR(ptr, size, *FWSign); + + pr_info("%s: firmware start address %08x size %d\n", + DRIVER_NAME, startAddr, size); + + /* upload data firmware */ + if (bus_adap->ops->write_ctrl_message( + dev, startAddr, (void *)ptr, size) != size) { + pr_err("Failed to load CIMaX+ firmware\n"); + errno = -ENODEV; + break; + } + if (bus_adap->ops->read_ctrl_message( + dev, startAddr, (void *)recv, size) != size) { + pr_err("Failed to load CIMaX+ firmware\n"); + errno = -ENODEV; + break; + } + if (memcmp(ptr, recv, size)) { + pr_err("Failed compare at Address 0x%04x\n", + startAddr); + errno = -ENODEV; + break; + } + /* update size sent to CIMaX+ */ + startAddr += size; + ptr += size; + if (startAddr >= STOP_FW_ADDR) + break; + } while (1); + + kfree(recv); + + if (errno == -EFAULT) { + /* upload interrupt vector*/ + ptr = fw_data; + ptr += START_INTVECT_ADDR; + startAddr = START_INTVECT_ADDR; + + /* continue to compute Signature */ + *FWSign = MISR(ptr, 6, *FWSign); + + /* upload interrupt vector data*/ + if (bus_adap->ops->write_ctrl_message( + dev, startAddr, (void *)ptr, 6) != 6) { + pr_err("Failed to load CIMaX firmware(Int vector)\n"); + errno = -ENODEV; + } + } + return (errno == -EFAULT) ? 0 : errno; +} + +/****************************************************************************** + * @brief + * upload and start firmware in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_fw_upload(struct device_s *bus_adap) +{ + int errno = -EFAULT; + const struct firmware *firmware; + char *fw = cimax_fw; + unsigned int FWSign = 0; + int ret; + + struct usb_device *dev = bus_adap->usbdev; + + /* request kernel to locate firmware file */ + errno = request_firmware(&firmware, fw, &dev->dev); + if (errno < 0) { + pr_err("%s: unable to locate firmware file: %s\n", + DRIVER_NAME, fw); + goto error; + } + + errno = cimaxusb_firmware_upload(bus_adap, firmware->data, &FWSign); + if (errno < 0) { + pr_err("%s: unable to upload firmware file: %s\n", + DRIVER_NAME, fw); + goto error; + } + + pr_info("%s: firmware: %s loaded with success. Current Bistrom %04X\n", + DRIVER_NAME, fw, FWSign); + + ret = checkBistRom(bus_adap, START_FW_ADDR, STOP_FW_ADDR, FWSign); + if (ret != 0x02) { + pr_err("\nError: Fail on compare BistRom (%02X) !\n", ret); + errno = -ENODEV; + goto error; + } + + if (bus_adap->ops->init_fw(dev) != 0) { + pr_err("\nError: Fail on INIT command !\n"); + errno = -ENODEV; + goto error; + } + +error: + /* release firmware if needed */ + if (firmware != NULL) + release_firmware(firmware); + return errno; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h new file mode 100644 index 000000000000..bf3f64cab8e3 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h @@ -0,0 +1,61 @@ +/**************************************************************************//** + * @file cimax+usb_fw.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_FW_H +#define __CIMAXPLUS_USB_FW_H + +/****************************************************************************** + * Include + ******************************************************************************/ +#include "cimax+usb_handle.h" + +/****************************************************************************** + * Defines + ******************************************************************************/ +#define CIMAX_FIRMWARE_NAME "cimax+_usbdvb.bin" +#define START_FW_ADDR 0x8000 +#define STOP_FW_ADDR 0xCFF9 +#define START_INTVECT_ADDR 0xFFFA +#define MAX_FW_PKT_SIZE 256 + +/****************************************************************************** + * Enums + ******************************************************************************/ +/****************************************************************************** + * Structures + ******************************************************************************/ + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * upload firmware in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_fw_upload(struct device_s *bus_adap); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h new file mode 100644 index 000000000000..936b9cf56bad --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h @@ -0,0 +1,46 @@ +/**************************************************************************//** + * @file cimax+usb_handle.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_HDLE_H +#define __CIMAXPLUS_USB_HDLE_H + +#ifdef __KERNEL__ + +struct cimaxusb_priv_ops_t { + int (*write_ctrl_message)( + struct usb_device *dev, int addr, void *data, int size); + + int (*read_ctrl_message)( + struct usb_device *dev, int addr, void *data, int size); + + int (*init_fw)( + struct usb_device *dev); + + int (*write_ep6_message)( + struct usb_device *dev, void *data, int size); + + int (*read_ep5_message)( + struct usb_device *dev, void *data, int size); +}; + +#endif + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c new file mode 100644 index 000000000000..ea80b5ef473f --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c @@ -0,0 +1,130 @@ +/**************************************************************************//** + * @file cimax+usb_fw.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ + +/*#define TIMESTAMP*/ + +/****************************************************************************** + * Include + ******************************************************************************/ +#include + +#include "cimax+usb_time.h" + +/****************************************************************************** + * Structures + ******************************************************************************/ +#define err(format, arg...)\ + pr_err("cimax+usb_time: %s> ERROR " format "\n" , \ + __func__, ## arg) +#define info(format, arg...) pr_info("time> " format "\n", ## arg) +/****************************************************************************** + * Globals + ******************************************************************************/ +#ifdef TIMESTAMP +struct item_array_s gstArray; +#endif +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * Init timestamp. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void InitTimestamp(void) +{ +#ifdef TIMESTAMP + gstArray.count = 0; +#endif + return; +} + +/****************************************************************************** + * @brief + * Set timestamp. + * + * @param pcFormat + * Printf-like format + * + * @return + * None. + ******************************************************************************/ +void SetTimestamp(const char *pcFormat, ...) +{ +#ifdef TIMESTAMP + va_list stArgs; + + if (gstArray.count >= MAX_ITEMS) { + if (gstArray.count++ == MAX_ITEMS) + ShowTimestamp(); + return; + } + ktime_get_ts(&gstArray.stItem[gstArray.count].stTime); + va_start(stArgs, pcFormat); + vsprintf(gstArray.stItem[gstArray.count++].pcLine, pcFormat, stArgs); + va_end(stArgs); +#endif + return; +} + +/****************************************************************************** + * @brief + * Display all timestamps. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void ShowTimestamp(void) +{ +#ifdef TIMESTAMP + int i; + + if (gstArray.count == 0) { + err("No timestamps available"); + return; + } + + info("==============================================================="); + info(" TIMESTAMPS"); + info("==============================================================="); + + for (i = 0; i < gstArray.count; i++) { + info("[%04d] [%03d.%09d] %s", + i, + gstArray.stItem[i].stTime.tv_sec, + gstArray.stItem[i].stTime.tv_nsec, + gstArray.stItem[i].pcLine); + if ((i % 100) == 0) + msleep(20); + } + info("==============================================================="); + gstArray.count = 0; + +#endif + return; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h new file mode 100644 index 000000000000..0012c64dfba4 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h @@ -0,0 +1,92 @@ +/**************************************************************************//** + * @file cimax+usb_time.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_TIME_H +#define __CIMAXPLUS_USB_TIME_H + +/****************************************************************************** + * Include + ******************************************************************************/ +#include + +/****************************************************************************** + * Defines + ******************************************************************************/ +#define MAX_ITEMS 100000 +#define MAX_LINE_SIZE 128 + +/****************************************************************************** + * Enums + ******************************************************************************/ +/****************************************************************************** + * Structures + ******************************************************************************/ +struct item_s { + struct timespec stTime; + char pcLine[MAX_LINE_SIZE]; +}; + +struct item_array_s { + int count; + item_s stItem[MAX_ITEMS]; +}; + +extern struct item_array_s gstArray; + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * Init timestamp. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void InitTimestamp(void); + +/****************************************************************************** + * @brief + * Set timestamp. + * + * @param pcFormat + * Printf-like format + * + * @return + * None. + ******************************************************************************/ +void SetTimestamp(const char *pcFormat, ...); + +/****************************************************************************** + * @brief + * Display all timestamps. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void ShowTimestamp(void); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg new file mode 100644 index 000000000000..7e792d80285d --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg @@ -0,0 +1,97 @@ +; +; ************************ +; * INIT_TS.TXT SCRIPT * +; ************************ +; +; *** CLOSE INPUT *** +; +IN_SEL 0x00 +; +; *** CLOSE OUPUT *** +; +OUT_SEL 0x00 +; +; *** RESET FIFO *** +; +FIFO_CTRL 0x0f +SYNC_RTV_CTRL 0x0f +; +; +; ************************* +; * INIT_USB.TXT SCRIPT * +; ************************* +; +; *** Endpoint Config *** +; +DMA_ACC_EPS 0x3f +EPS_ENABLE 0x7f +; +; *** FIFO Control *** +; +USB2TS_CTRL 0x0f +TS2USB_CTRL 0x0f +; +; *** FREQ Control *** +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +;----------------------------------------------------------------------------- +; Set CAM power +;----------------------------------------------------------------------------- +; +GPIO0_DATA_OUT 0x00 +; +; unlock CFG +CFG_2 0x00 +; +; 1) DVB/CI/CI+/SCARD 2slot +CFG_1 0x00 +; +; 2) Set the Default "power off" state such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z' +GPIO0_DFT 0x00 +; +; 3) Set GPIO3 as external power switch driver +GPIO0_MASK_DATA 0x07 +; +; 4) Set "power on" state (VCC=VPP1=VPP2= 5V) +GPIO0_DATA_OUT 0x01 +; +; 5) Lock config +CFG_2 0x01 +; +; 6) Write in the GPIO0_DIR_REG: defines the GPIOs, which +; are used to drive the external power switch, in output mode. +GPIO0_DIR 0x07 +; +; 7) Check VCCENable +?CFG_1 0x20 +; +; 8) Set & wait for PcmciaOutputEnable +|CFG_1 0x08 +?CFG_1 0x08 +; +;--------------------------------------- +; Set Router CAM +;--------------------------------------- +; +; +GAP_REMOVER_CH0_CTRL 0x0C +GAP_REMOVER_CH1_CTRL 0x0C + +; 9) CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1 +; +ROUTER_CAM_MOD 0x21 +ROUTER_CAM_CH 0x00 +; +;_Wait 200 +;--------------------------------------- +; ROUTER CAM +;--------------------------------------- +OUT_SEL 0x03 +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +IN_SEL 0x22 + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg new file mode 100644 index 000000000000..5c38429e78e5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg @@ -0,0 +1,136 @@ +; +; ************************ +; * INIT_TS.TXT SCRIPT * +; ************************ +; +; *** CLOSE INPUT *** +; +IN_SEL 0x00 +; +; *** CLOSE OUPUT *** +; +OUT_SEL 0x00 +; +; *** RESET FIFO *** +; +FIFO_CTRL 0x0f +SYNC_RTV_CTRL 0x0f +; +; +; ************************* +; * INIT_USB.TXT SCRIPT * +; ************************* +; +; *** Endpoint Config *** +; +DMA_ACC_EPS 0x3f +EPS_ENABLE 0x7f +; +; *** FIFO Control *** +; +USB2TS_CTRL 0x0f +TS2USB_CTRL 0x0f +; +; *** FREQ Control *** +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +;----------------------------------------------------------------------------- +; Set CAM power +;----------------------------------------------------------------------------- +; +GPIO0_DATA_OUT 0x00 +; +; unlock CFG +CFG_2 0x00 +; +; 1) DVB/CI/CI+/SCARD 2slot +CFG_1 0x00 +; +; 2) Set the Default "power off" state such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z' +GPIO0_DFT 0x00 +; +; 3) Set GPIO3 as external power switch driver +GPIO0_MASK_DATA 0x07 +; +; 4) Set "power on" state (VCC=VPP1=VPP2= 5V) +GPIO0_DATA_OUT 0x01 +; +; 5) Lock config +CFG_2 0x01 +; +; 6) Write in the GPIO0_DIR_REG: defines the GPIOs, which +; are used to drive the external power switch, in output mode. +GPIO0_DIR 0x07 +; +; 7) Check VCCENable +?CFG_1 0x20 +; +; 8) Set & wait for PcmciaOutputEnable +|CFG_1 0x08 +?CFG_1 0x08 +; +;--------------------------------------- +; Set Router CAM +;--------------------------------------- +; +; +GAP_REMOVER_CH0_CTRL 0x0C +GAP_REMOVER_CH1_CTRL 0x0C + +; 9) CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1 +; +ROUTER_CAM_MOD 0x21 +ROUTER_CAM_CH 0x00 +; +;_Wait 200 +;--------------------------------------- +; ROUTER CAM +;--------------------------------------- +OUT_SEL 0x03 +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +IN_SEL 0x22 + +; *************************** +; * MuliStream.TXT SCRIPT * +; *************************** +; +; *** CLOSE INPUT *** +; +IN_SEL 0x00 +; +; *** CLOSE OUPUT *** +; +OUT_SEL 0x00 +; +; *** RESET FIFO *** +; +FIFO_CTRL 0x0f +SYNC_RTV_CTRL 0x0f +; +; *** *** +; +CkMan_Config 0x1f +CkMan_Select 0x00 +MERGER_DIV_MICLK 0x02 +SYNC_SYMBOL 0x0d +PID_AND_SYNC_REMAPPER_INV_CTRL 0x01 + +FIFO_CTRL 0x0f +ROUTER_CAM_MOD 0x03 +ROUTER_CAM_CH 0x80 + +USB2TS_CTRL 0x0f +TS2USB_CTRL 0x0f +USB2TS0_RDL 0x20 +USB2TS1_RDL 0x20 + +OUT_SEL 0x03 +IN_SEL 0x22 +; +; ************************ +; diff --git a/drivers/amlogic/media_modules/stream_input/parser/psparser.c b/drivers/amlogic/media_modules/stream_input/parser/psparser.c index c3b63c181a98..3197976e437e 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/psparser.c +++ b/drivers/amlogic/media_modules/stream_input/parser/psparser.c @@ -598,15 +598,6 @@ static u32 parser_process(s32 type, s32 packet_len) SET_DISCARD_SIZE(packet_len); return DISCARD_SEARCH; } - - if (!packet_len) - return SEARCH_START_CODE; - - else { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - } } return SEARCH_START_CODE; @@ -1025,6 +1016,7 @@ void psparser_release(void) pr_info("psparser release subtitle info\n"); #endif } +EXPORT_SYMBOL(psparser_release); ssize_t psparser_write(struct file *file, struct stream_buf_s *vbuf, diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf.c b/drivers/amlogic/media_modules/stream_input/parser/streambuf.c index 14991a940335..256afb99a80a 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/streambuf.c +++ b/drivers/amlogic/media_modules/stream_input/parser/streambuf.c @@ -183,6 +183,7 @@ int stbuf_fetch_init(void) } return 0; } +EXPORT_SYMBOL(stbuf_fetch_init); void stbuf_fetch_release(void) { @@ -362,6 +363,7 @@ s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi) MEM_CTRL_EMPTY_EN); return 0; } +EXPORT_SYMBOL(stbuf_init); void stbuf_vdec2_init(struct stream_buf_s *buf) { @@ -425,6 +427,7 @@ void stbuf_release(struct stream_buf_s *buf, bool is_multi) } buf->flag &= ~BUF_FLAG_IN_USE; } +EXPORT_SYMBOL(stbuf_release); u32 stbuf_sub_rp_get(void) { diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h index 6ea2c75c32c2..d73865e010f7 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h +++ b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h @@ -104,9 +104,11 @@ struct drm_info { u32 drm_vir; u32 drm_remap; u32 data_offset; - u32 extpad[8]; + u32 handle; + u32 extpad[7]; } /*drminfo_t */; +#define TYPE_DRMINFO_V2 0x100 #define TYPE_DRMINFO 0x80 #define TYPE_PATTERN 0x40 diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c index 04e5a2c4613d..6fe6cd871dc0 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c +++ b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c @@ -254,7 +254,6 @@ static int do_write_work_in(struct threadrw_write_task *task) if (write_len > 0) { spin_lock_irqsave(&task->lock, flags); task->passed_data_len += write_len; - task->buffered_data_size -= write_len; spin_unlock_irqrestore(&task->lock, flags); } return need_re_write; @@ -445,6 +444,22 @@ err1: *fifo data size; */ +void threadrw_update_buffer_level(struct stream_buf_s *stbuf, + int parsed_size) +{ + struct threadrw_write_task *task = stbuf->write_thread; + unsigned long flags; + + if (task) + { + spin_lock_irqsave(&task->lock, flags); + task->buffered_data_size -= parsed_size; + spin_unlock_irqrestore(&task->lock, flags); + } + +} +EXPORT_SYMBOL(threadrw_update_buffer_level); + int threadrw_buffer_level(struct stream_buf_s *stbuf) { struct threadrw_write_task *task = stbuf->write_thread; diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h index c6283f0963ab..a91b00498efc 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h +++ b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h @@ -48,5 +48,6 @@ int threadrw_alloc_more_buffer_size( struct stream_buf_s *stbuf, int size); int threadrw_support_more_buffers(struct stream_buf_s *stbuf); - +void threadrw_update_buffer_level(struct stream_buf_s *stbuf, + int parsed_size); #endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c index a93396f350c0..ac34cf74c3d3 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c +++ b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c @@ -47,6 +47,8 @@ #include #include "../amports/amports_priv.h" +#define MAX_DRM_PACKAGE_SIZE 0x500000 + static const char tsdemux_fetch_id[] = "tsdemux-fetch-id"; static const char tsdemux_irq_id[] = "tsdemux-irq-id"; @@ -111,7 +113,7 @@ int tsdemux_set_reset_flag(void) static int tsdemux_reset(void) { unsigned long flags; - int r; + int r = 0; spin_lock_irqsave(&demux_ops_lock, flags); if (demux_ops && demux_ops->reset) { @@ -126,7 +128,7 @@ static int tsdemux_reset(void) static int tsdemux_request_irq(irq_handler_t handler, void *data) { unsigned long flags; - int r; + int r = 0; spin_lock_irqsave(&demux_ops_lock, flags); if (demux_ops && demux_ops->request_irq) @@ -139,7 +141,7 @@ static int tsdemux_request_irq(irq_handler_t handler, void *data) static int tsdemux_free_irq(void) { unsigned long flags; - int r; + int r = 0; spin_lock_irqsave(&demux_ops_lock, flags); if (demux_ops && demux_ops->free_irq) @@ -664,12 +666,13 @@ s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc, } curr_pcr_id = pcrid; + pcrscr_valid = reset_pcr_regs(); + if ((pcrid < 0x1FFF) && (pcrid != vid) && (pcrid != aid) && (pcrid != sid)) tsdemux_set_pcrid(pcrid); } - pcrscr_valid = reset_pcr_regs(); first_pcr = 0; return 0; @@ -747,6 +750,7 @@ void tsdemux_release(void) amports_switch_gate("demux", 0); } +EXPORT_SYMBOL(tsdemux_release); static int limited_delay_check(struct file *file, struct stream_buf_s *vbuf, @@ -820,7 +824,12 @@ ssize_t drm_tswrite(struct file *file, if (drm->drm_flag == TYPE_DRMINFO && drm->drm_level == DRM_LEVEL1) { /* buf only has drminfo not have esdata; */ - realcount = drm->drm_pktsize; + if (drm->drm_pktsize <= MAX_DRM_PACKAGE_SIZE) + realcount = drm->drm_pktsize; + else { + pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); + return -EINVAL; + } realbuf = drm->drm_phy; isphybuf = 1; } else @@ -1156,8 +1165,8 @@ u8 tsdemux_pcrvideo_valid(void) void tsdemux_pcr_set(unsigned int pcr) { if (pcr_init_flag == 0) { - timestamp_pcrscr_set(pcr); - timestamp_pcrscr_enable(1); + /*timestamp_pcrscr_set(pcr); + timestamp_pcrscr_enable(1);*/ pcr_init_flag = 1; } } diff --git a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c new file mode 100644 index 000000000000..bfcf6122e7d8 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c @@ -0,0 +1,715 @@ +/* + * drivers/amlogic/media/subtitle/subtitle.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "amports_priv.h" + +//#include "amlog.h" +//MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0, LOG_DEFAULT_LEVEL_DESC, + //LOG_DEFAULT_MASK_DESC); +#define DEVICE_NAME "amsubtitle" +/* Dev name as it appears in /proc/devices */ +#define DEVICE_CLASS_NAME "subtitle" + +static int subdevice_open; + +#define MAX_SUBTITLE_PACKET 10 +static DEFINE_MUTEX(amsubtitle_mutex); + +struct subtitle_data_s { + int subtitle_size; + int subtitle_pts; + char *data; +}; +static struct subtitle_data_s subtitle_data[MAX_SUBTITLE_PACKET]; +static int subtitle_enable = 1; +static int subtitle_total; +static int subtitle_width; +static int subtitle_height; +static int subtitle_type = -1; +static int subtitle_current; /* no subtitle */ +/* sub_index node will be modified by libplayer; amlogicplayer will use */ +/* it to detect wheather libplayer switch sub finished or not */ +static int subtitle_index; /* no subtitle */ +/* static int subtitle_size = 0; */ +/* static int subtitle_read_pos = 0; */ +static int subtitle_write_pos; +static int subtitle_start_pts; +static int subtitle_fps; +static int subtitle_subtype; +static int subtitle_reset; +/* static int *subltitle_address[MAX_SUBTITLE_PACKET]; */ + +enum subinfo_para_e { + SUB_NULL = -1, + SUB_ENABLE = 0, + SUB_TOTAL, + SUB_WIDTH, + SUB_HEIGHT, + SUB_TYPE, + SUB_CURRENT, + SUB_INDEX, + SUB_WRITE_POS, + SUB_START_PTS, + SUB_FPS, + SUB_SUBTYPE, + SUB_RESET, + SUB_DATA_T_SIZE, + SUB_DATA_T_DATA +}; + +struct subinfo_para_s { + enum subinfo_para_e subinfo_type; + int subtitle_info; + char *data; +}; + +/* total */ +/* curr */ +/* bimap */ +/* text */ +/* type */ +/* info */ +/* pts */ +/* duration */ +/* color pallete */ +/* width/height */ + +static ssize_t show_curr(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: current\n", subtitle_current); +} + +static ssize_t store_curr(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int curr; + ssize_t r; + + r = kstrtoint(buf, 0, &curr); + if (r < 0) + return -EINVAL; + + + subtitle_current = curr; + + return size; +} + +static ssize_t show_index(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: current\n", subtitle_index); +} + +static ssize_t store_index(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int curr; + ssize_t r; + + r = kstrtoint(buf, 0, &curr); + if (r < 0) + return -EINVAL; + + subtitle_index = curr; + + return size; +} + +static ssize_t show_reset(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: current\n", subtitle_reset); +} + +static ssize_t store_reset(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int reset; + ssize_t r; + + r = kstrtoint(buf, 0, &reset); + + pr_info("reset is %d\n", reset); + if (r < 0) + return -EINVAL; + + + subtitle_reset = reset; + + return size; +} + +static ssize_t show_type(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: type\n", subtitle_type); +} + +static ssize_t store_type(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int type; + ssize_t r; + + r = kstrtoint(buf, 0, &type); + if (r < 0) + return -EINVAL; + + subtitle_type = type; + + return size; +} + +static ssize_t show_width(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: width\n", subtitle_width); +} + +static ssize_t store_width(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int width; + ssize_t r; + + r = kstrtoint(buf, 0, &width); + if (r < 0) + return -EINVAL; + + subtitle_width = width; + + return size; +} + +static ssize_t show_height(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: height\n", subtitle_height); +} + +static ssize_t store_height(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int height; + ssize_t r; + + r = kstrtoint(buf, 0, &height); + if (r < 0) + return -EINVAL; + + subtitle_height = height; + + return size; +} + +static ssize_t show_total(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: num\n", subtitle_total); +} + +static ssize_t store_total(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int total; + ssize_t r; + + r = kstrtoint(buf, 0, &total); + if (r < 0) + return -EINVAL; + pr_info("subtitle num is %d\n", total); + subtitle_total = total; + + return size; +} + +static ssize_t show_enable(struct class *class, struct class_attribute *attr, + char *buf) +{ + if (subtitle_enable) + return sprintf(buf, "1: enabled\n"); + + return sprintf(buf, "0: disabled\n"); +} + +static ssize_t store_enable(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int mode; + ssize_t r; + + r = kstrtoint(buf, 0, &mode); + if (r < 0) + return -EINVAL; + pr_info("subtitle enable is %d\n", mode); + subtitle_enable = mode ? 1 : 0; + + return size; +} + +static ssize_t show_size(struct class *class, struct class_attribute *attr, + char *buf) +{ + if (subtitle_enable) + return sprintf(buf, "1: size\n"); + + return sprintf(buf, "0: size\n"); +} + +static ssize_t store_size(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int ssize; + ssize_t r; + + r = kstrtoint(buf, 0, &ssize); + if (r < 0) + return -EINVAL; + pr_info("subtitle size is %d\n", ssize); + subtitle_data[subtitle_write_pos].subtitle_size = ssize; + + return size; +} + +static ssize_t show_startpts(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: pts\n", subtitle_start_pts); +} + +static ssize_t store_startpts(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int spts; + ssize_t r; + + r = kstrtoint(buf, 0, &spts); + if (r < 0) + return -EINVAL; + pr_info("subtitle start pts is %x\n", spts); + subtitle_start_pts = spts; + + return size; +} + +static ssize_t show_data(struct class *class, struct class_attribute *attr, + char *buf) +{ +#if 0 + if (subtitle_data[subtitle_write_pos].data) + return sprintf(buf, "%lld\n", + (unsigned long)(subtitle_data[subtitle_write_pos].data)); +#endif + return sprintf(buf, "0: disabled\n"); +} + +static ssize_t store_data(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int address; + ssize_t r; + + r = kstrtoint(buf, 0, &address); + if ((r == 0)) + return -EINVAL; +#if 0 + if (subtitle_data[subtitle_write_pos].subtitle_size > 0) { + subtitle_data[subtitle_write_pos].data = vmalloc(( + subtitle_data[subtitle_write_pos].subtitle_size)); + if (subtitle_data[subtitle_write_pos].data) + memcpy(subtitle_data[subtitle_write_pos].data, + (unsigned long *)address, + subtitle_data[subtitle_write_pos].subtitle_size); + } + pr_info("subtitle data address is %x", + (unsigned int)(subtitle_data[subtitle_write_pos].data)); +#endif + subtitle_write_pos++; + if (subtitle_write_pos >= MAX_SUBTITLE_PACKET) + subtitle_write_pos = 0; + return 1; +} + +static ssize_t show_fps(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: fps\n", subtitle_fps); +} + +static ssize_t store_fps(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int ssize; + ssize_t r; + + r = kstrtoint(buf, 0, &ssize); + if (r < 0) + return -EINVAL; + pr_info("subtitle fps is %d\n", ssize); + subtitle_fps = ssize; + + return size; +} + +static ssize_t show_subtype(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: subtype\n", subtitle_subtype); +} + +static ssize_t store_subtype(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int ssize; + ssize_t r; + + r = kstrtoint(buf, 0, &ssize); + if (r < 0) + return -EINVAL; + pr_info("subtitle subtype is %d\n", ssize); + subtitle_subtype = ssize; + + return size; +} + +static struct class_attribute subtitle_class_attrs[] = { + __ATTR(enable, 0664, show_enable, store_enable), + __ATTR(total, 0664, show_total, store_total), + __ATTR(width, 0664, show_width, store_width), + __ATTR(height, 0664, show_height, store_height), + __ATTR(type, 0664, show_type, store_type), + __ATTR(curr, 0664, show_curr, store_curr), + __ATTR(index, 0664, show_index, store_index), + __ATTR(size, 0664, show_size, store_size), + __ATTR(data, 0664, show_data, store_data), + __ATTR(startpts, 0664, show_startpts, + store_startpts), + __ATTR(fps, 0664, show_fps, store_fps), + __ATTR(subtype, 0664, show_subtype, + store_subtype), + __ATTR(reset, 0644, show_reset, store_reset), + __ATTR_NULL +}; + + +/********************************************************* + * /dev/amvideo APIs + *********************************************************/ +static int amsubtitle_open(struct inode *inode, struct file *file) +{ + mutex_lock(&amsubtitle_mutex); + + if (subdevice_open) { + mutex_unlock(&amsubtitle_mutex); + return -EBUSY; + } + + subdevice_open = 1; + + try_module_get(THIS_MODULE); + + mutex_unlock(&amsubtitle_mutex); + + return 0; +} + +static int amsubtitle_release(struct inode *inode, struct file *file) +{ + mutex_lock(&amsubtitle_mutex); + + subdevice_open = 0; + + module_put(THIS_MODULE); + + mutex_unlock(&amsubtitle_mutex); + + return 0; +} + +static long amsubtitle_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + switch (cmd) { + case AMSTREAM_IOC_GET_SUBTITLE_INFO: { + struct subinfo_para_s Vstates; + struct subinfo_para_s *states = &Vstates; + + if (copy_from_user((void *)states, + (void *)arg, sizeof(Vstates))) + return -EFAULT; + switch (states->subinfo_type) { + case SUB_ENABLE: + states->subtitle_info = subtitle_enable; + break; + case SUB_TOTAL: + states->subtitle_info = subtitle_total; + break; + case SUB_WIDTH: + states->subtitle_info = subtitle_width; + break; + case SUB_HEIGHT: + states->subtitle_info = subtitle_height; + break; + case SUB_TYPE: + states->subtitle_info = subtitle_type; + break; + case SUB_CURRENT: + states->subtitle_info = subtitle_current; + break; + case SUB_INDEX: + states->subtitle_info = subtitle_index; + break; + case SUB_WRITE_POS: + states->subtitle_info = subtitle_write_pos; + break; + case SUB_START_PTS: + states->subtitle_info = subtitle_start_pts; + break; + case SUB_FPS: + states->subtitle_info = subtitle_fps; + break; + case SUB_SUBTYPE: + states->subtitle_info = subtitle_subtype; + break; + case SUB_RESET: + states->subtitle_info = subtitle_reset; + break; + case SUB_DATA_T_SIZE: + states->subtitle_info = + subtitle_data[subtitle_write_pos].subtitle_size; + break; + case SUB_DATA_T_DATA: { + if (states->subtitle_info > 0) + states->subtitle_info = + (long)subtitle_data[subtitle_write_pos].data; + } + break; + default: + break; + } + if (copy_to_user((void *)arg, (void *)states, sizeof(Vstates))) + return -EFAULT; + } + + break; + case AMSTREAM_IOC_SET_SUBTITLE_INFO: { + struct subinfo_para_s Vstates; + struct subinfo_para_s *states = &Vstates; + + if (copy_from_user((void *)states, + (void *)arg, sizeof(Vstates))) + return -EFAULT; + switch (states->subinfo_type) { + case SUB_ENABLE: + subtitle_enable = states->subtitle_info; + break; + case SUB_TOTAL: + subtitle_total = states->subtitle_info; + break; + case SUB_WIDTH: + subtitle_width = states->subtitle_info; + break; + case SUB_HEIGHT: + subtitle_height = states->subtitle_info; + break; + case SUB_TYPE: + subtitle_type = states->subtitle_info; + break; + case SUB_CURRENT: + subtitle_current = states->subtitle_info; + break; + case SUB_INDEX: + subtitle_index = states->subtitle_info; + break; + case SUB_WRITE_POS: + subtitle_write_pos = states->subtitle_info; + break; + case SUB_START_PTS: + subtitle_start_pts = states->subtitle_info; + break; + case SUB_FPS: + subtitle_fps = states->subtitle_info; + break; + case SUB_SUBTYPE: + subtitle_subtype = states->subtitle_info; + break; + case SUB_RESET: + subtitle_reset = states->subtitle_info; + break; + case SUB_DATA_T_SIZE: + subtitle_data[subtitle_write_pos].subtitle_size = + states->subtitle_info; + break; + case SUB_DATA_T_DATA: { + if (states->subtitle_info > 0) { + subtitle_data[subtitle_write_pos].data = + vmalloc((states->subtitle_info)); + if (subtitle_data[subtitle_write_pos].data) + memcpy( + subtitle_data[subtitle_write_pos].data, + (char *)states->data, + states->subtitle_info); + } + + subtitle_write_pos++; + if (subtitle_write_pos >= MAX_SUBTITLE_PACKET) + subtitle_write_pos = 0; + } + break; + default: + break; + } + + } + + break; + default: + break; + } + + return 0; +} + +#ifdef CONFIG_COMPAT +static long amsub_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + long ret = 0; + + ret = amsubtitle_ioctl(file, cmd, (ulong)compat_ptr(arg)); + return ret; +} +#endif + +static const struct file_operations amsubtitle_fops = { + .owner = THIS_MODULE, + .open = amsubtitle_open, + .release = amsubtitle_release, + .unlocked_ioctl = amsubtitle_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amsub_compat_ioctl, +#endif +}; + +static struct device *amsubtitle_dev; +static dev_t amsub_devno; +static struct class *amsub_clsp; +static struct cdev *amsub_cdevp; +#define AMSUBTITLE_DEVICE_COUNT 1 + +static void create_amsub_attrs(struct class *class) +{ + int i = 0; + + for (i = 0; subtitle_class_attrs[i].attr.name; i++) { + if (class_create_file(class, &subtitle_class_attrs[i]) < 0) + break; + } +} + +static void remove_amsub_attrs(struct class *class) +{ + int i = 0; + + for (i = 0; subtitle_class_attrs[i].attr.name; i++) + class_remove_file(class, &subtitle_class_attrs[i]); +} + +int subtitle_init(void) +{ + int ret = 0; + + ret = alloc_chrdev_region(&amsub_devno, 0, AMSUBTITLE_DEVICE_COUNT, + DEVICE_NAME); + if (ret < 0) { + pr_info("amsub: failed to alloc major number\n"); + ret = -ENODEV; + return ret; + } + + amsub_clsp = class_create(THIS_MODULE, DEVICE_CLASS_NAME); + if (IS_ERR(amsub_clsp)) { + ret = PTR_ERR(amsub_clsp); + goto err1; + } + + create_amsub_attrs(amsub_clsp); + + amsub_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL); + if (!amsub_cdevp) { + /*pr_info("amsub: failed to allocate memory\n");*/ + ret = -ENOMEM; + goto err2; + } + + cdev_init(amsub_cdevp, &amsubtitle_fops); + amsub_cdevp->owner = THIS_MODULE; + /* connect the major/minor number to cdev */ + ret = cdev_add(amsub_cdevp, amsub_devno, AMSUBTITLE_DEVICE_COUNT); + if (ret) { + pr_info("amsub:failed to add cdev\n"); + goto err3; + } + + amsubtitle_dev = device_create(amsub_clsp, + NULL, MKDEV(MAJOR(amsub_devno), 0), + NULL, DEVICE_NAME); + + if (IS_ERR(amsubtitle_dev)) { + pr_err("## Can't create amsubtitle device\n"); + goto err4; + } + + return 0; + +err4: + cdev_del(amsub_cdevp); +err3: + kfree(amsub_cdevp); +err2: + remove_amsub_attrs(amsub_clsp); + class_destroy(amsub_clsp); +err1: + unregister_chrdev_region(amsub_devno, 1); + + return ret; +} +EXPORT_SYMBOL(subtitle_init); + +void subtitle_exit(void) +{ + unregister_chrdev_region(amsub_devno, 1); + device_destroy(amsub_clsp, MKDEV(MAJOR(amsub_devno), 0)); + cdev_del(amsub_cdevp); + kfree(amsub_cdevp); + remove_amsub_attrs(amsub_clsp); + class_destroy(amsub_clsp); +} +EXPORT_SYMBOL(subtitle_exit); + diff --git a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h new file mode 100644 index 000000000000..375a31a06d25 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h @@ -0,0 +1,24 @@ +/* + * drivers/amlogic/media/stream_input/amports/amports_priv.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef SUBTITLE_H +#define SUBTITLE_H + +int subtitle_init(void); +void subtitle_exit(void); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c index f683f2ca5f34..6253def75c4f 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * AMLOGIC DVB frontend driver. */ @@ -749,7 +768,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "tuner", &value); if (!ret) { - int id = value; + id = value; if ((id < 0) || (id >= FE_DEV_COUNT) || !fe_man.tuner[id].drv) { pr_error("invalid tuner device id %d\n", id); @@ -762,7 +781,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "atv_demod", &value); if (!ret) { - int id = value; + id = value; if ((id < 0) || (id >= FE_DEV_COUNT) || @@ -777,7 +796,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "dtv_demod", &value); if (!ret) { - int id = value; + id = value; if ((id < 0) || (id >= FE_DEV_COUNT) || @@ -813,7 +832,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "dev", &value); if (!ret) { - int id = value; + id = value; if ((id >= 0) && (id < FE_DEV_COUNT)) fe->dev_id = id; diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h index c32c3801617f..c975b4ce8941 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _AML_FE_H_ #define _AML_FE_H_ @@ -42,6 +61,7 @@ #include "../parser/hw_demux/aml_dvb.h" enum aml_tuner_type_t { + AM_TUNER_NONE = 0, AM_TUNER_SI2176 = 1, AM_TUNER_SI2196 = 2, AM_TUNER_FQ1216 = 3, @@ -51,7 +71,10 @@ enum aml_tuner_type_t { AM_TUNER_R840 = 7, AM_TUNER_SI2157 = 8, AM_TUNER_SI2151 = 9, - AM_TUNER_MXL661 = 10 + AM_TUNER_MXL661 = 10, + AM_TUNER_MXL608 = 11, + AM_TUNER_SI2159 = 12, + AM_TUNER_R842 = 13, }; enum aml_atv_demod_type_t { diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c index 009f81e2f727..7ccdfae3e1a9 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c index 9609a93c6b00..a54d82cadddc 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /*#include "register.h"*/ /*#include "c_arc_pointer_reg.h"*/ /*#include "a9_func.h"*/ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c index 8f10dccffd82..cf2ea8163947 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c index b8515d888eda..7654aaef1607 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c index 7edef46742ff..68b214efc470 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h index b1437a2cdab2..57448858678d 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ void program_acf(int acf1[20], int acf2[33]) { int i; diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h index 01ff78361d2b..4b231320adbf 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_CHE_H__ #define __ADDR_DTMB_CHE_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h index edb848c9e676..d81c47795d20 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_CHE_BIT_H__ #define __ADDR_DTMB_CHE_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h index a120bc8dff82..bf2f524e1caf 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_FRONT_H__ #define __ADDR_DTMB_FRONT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h index b6df7f602041..ec74d2353f27 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_FRONT_BIT_H__ #define __ADDR_DTMB_FRONT_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h index 0455a4e3e35f..0607b19b4e23 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_SYNC_H__ #define __ADDR_DTMB_SYNC_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h index 51c2517d6eec..0aebdd101af2 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_SYNC_BIT_H__ #define __ADDR_DTMB_SYNC_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h index 827c87a75260..c12d26f66c0f 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_TOP_H__ #define __ADDR_DTMB_TOP_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h index 4a6df5d5e8b6..63233c4e49d9 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_TOP_BIT_H__ #define __ADDR_DTMB_TOP_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h index 9c318b1524f3..4f49fa7c5261 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _DTV_REG_H_ #define _DTV_REG_H_ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h index 9867a24e4ee5..5df7b1c48995 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h @@ -1,3 +1,23 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + /***************************************************************** ** ** Copyright (C) 2010 Amlogic,Inc. diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h index 37f0441c644c..4c9d28193b18 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifdef DEMOD_FUNC_H #else #define DEMOD_FUNC_H diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c index a6ab31882b64..f4c1a3808ba6 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c @@ -1,3 +1,22 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/firmware/video/video_ucode.bin b/firmware/video/video_ucode.bin index 24b752810f2856f26f21ff13edd52ae594ad8628..dd56ade8bfbde386a811e935b2ba7e24e9859dc6 100644 GIT binary patch delta 133360 zcmeEv2b@&Z+5Wj@?%aE4c42pcr7qhjOD~F2#Ip;+3{9HY5Lv)3irBER2TWuZtW4xa zO_X9w?5w(pe$fMdiL;srQ_7&wJ`~ zo>zQ1K>Xn3nzLVcs&eAkcW>%>-sOL+yWsRTzde%;8~Ts>sTX~D%9EjodMy3=qsnu= zF^~PTW6q1n*L{wTq0+dMJ`?1`>3zV25o%&ozw1mv2)FjbN+B< z&8TyR-e2;@jA0d5ZtXjH^{tEk@c9?_zBF{~&o4WS{j$yI)0f=z>Sz2P$DG#wkY5gx z7YthX`k9CPcJS&K>&M>u^{hTOe!T9kN3J~Q#8Xbc`K=9KSEM?B_SjL^UGTj5!K?qc zXGH(5SNwYOFKTWd<(>5KMKdos_O%n9y6CRA?_3=F<6lo(p1f!4r+2rRe8n%@6nryr zOyyK2Iq>4IZ3a zX!PZi&pxZTa?#@A!3P%)9yH?M;Uk6)FCH>z@NgFVf=FpAV~ZHO>2Gzj(}~nQH>0<< zI@BY4F^e9Qid)G%tw(ZNXi#OlB~cYg!sLtAGotR<<9R-ZVvU* z{*?SnXyB-C=DOTg?wc=N=T?nc=WZ_E;PQXfM7uCy8HbDT6Jv#2aJUS!Zr9Qo94RGT@uY<%dPO{xh})= zRhK0{a_`VqCD%k=(3aMn9-U~mAFf3|bD3HEf@5pvF}w-|IzRE0j-sSp+CwWz4k#U?_4ZDGIy5CIOV2a~swg?PtUOu#vqL?(QnQmw ze)h|9UhYbirQeHj>uyoz_WiwMec+Zjf9WG!p}~Dqu`83u{`>?>M*G~l+(85By1GYP zdpJ3v#|rPc6GM~gy7jy=TNqIG)re^CEb2U>*s~Nnv+8Z>uf>t#(v|q zj-GW&=n1`@;cY!7w7gA)2w(ZcTsPWZgeUQLBHpA^L%owz2jplc*3B7kqNYceBp)9* zTDO-Zza6-&P%gME>e$teJ#~y_eNpLQjtp;qhftou^01Fh5DT%LU%WHKD%U zZevjgr4iN2d3+T!<0cPJYsXAJH@WSIfzAm*ggIW32z7SZ@yae{lfBEq$0%!9-0p^p z*SX=vB4mrTuB=`f9UmmLLT9EUgvDkBQIGb{5}{u0XDI8FmCQ^BmD9YRBh{R#%4@uV zY#f<&8o>oF|KxGcpLsx@aC|% z&81>YYsXDFO}1GvgF9DW&O=k)5f1s2-+19|naSg0b09~L#JY5^Rc&>Od@~YW?>dQrGQ46SK0)x(g^5al6!q-{?(#ZNI7ss#A`KexRZKz{i z{)DSFUF3Mb`C({SpD;@QByy^9&s6D_i%^`Gxa2-GQS&;?+0!O#oqU}ToEcQmG3GyipkQ?%cnZ&1}NY0a#w^F zyRy4#r0i91<%-aVTzPxQPjea7$=lwx6``6Q&nc(zr83;GtgR!SRrWZFKt*X-#vJ}k za?X@zw9Ux@N1mPc%iz^P_47xP_a6DAc8|AmW$3tG?02E)Rj5$jpi-F;bcOZ{am)Vg z*)Dx3e(z<;Rnxn5mg|C)3YbYvMy^$MzBaje`YqasN07COGP-$*7;%NDalz!9ho;Tkdbp`I6Qr-Bde1SA2qP3 zeK_h!d~oD(#j`T(H_0F#FF;R}43*@{<5bjeRm@?>dG}gYVIJZ&oQrq-L0Dn#Sgc+0 zxLMt`qmmcT8rZ`Q((Da?e2_5T;M!FPGp#8ZJ~g>*R-qP2zBlX0!STRdZg9uzJUqVg zUN@ePc=R!2%8%Sr@=V`dj!T|=^dZ`qs-cosY8o4?ezXk|Tx(aS)ci!}zMPjx#uFu{AZ(`UgDi?ymNE3x}L|>X2avd3lq< zg~{%EiGJQfuiDeQC#&@h(GyQya$~a)CWAHE*BJEw>D1%-?_uik>z1Y-JwC4SKS8{c z2s_0kZo_rbk(XT@jd!9xL$El8JEkTkkNFc5_a04+oxfw=$2W#Yd;LGsJ9@8GhJK%% z>)fDS>(5uN!hGf7zE3x_Hep$AjbDywRv0}trfTv_jG68l?E=hT*1O_9)%Ef_lU31P z+G%P+Q{K{qCi&Q!&e8VWrdUTE+}3F?&UU@IkA%8fd@$0jNd9xph`FL-Nwl3Ntn2%T z@bwtd1YY;MauHs`|LV@_CBhxpt?n$0>}xQxw?k3ewHKkn@o|gnNB@vHN5S6yd>%Qf zJu}MLFGts&tDAGf5FPz^^5*ulbeZcdeLU2`N?jqG z*ox%#n+hXZi9bZy%cbMp|9I%i8mtJ~yeq zCef&cD2j1m)l;)-_el~>V@Z_6k{zMk!^?}E6#CqWa3k?0KQe2VbKRbMcO-f0Pb<5P zR$&rZDVKYaX6Xo}0;Q=OmqQ}X6pXSwXn!1`8l`>j1)_F7n{{DbA~TMA^G)k|y?Rc3-1r_c`TJE2ngl z_4KqsPEP3v=jrLiPEJ`LXX|txik9)vlZ&NpUoQ2hr?-WBXJ_krxR1$nXK;6&t)Ibt zzH%qIqd3vaD?`yb$BNd)tw}~@h}?6GWg*|aEbxfJBMQgK2%H1A90aC-li`k~$Fr+@ z#B@Pxk1K3;FIturwUcvul-GUJqukJ#H+X)iP!q}F6}@0NXMX5hP1gOk;ziB5Aai-r z0et}$kEy;~m&ah8GRt5mVtVjWXqYwy>y!bV+5O>YPG3lbm>Urv)I^^?d|kxGmlC^Q zz*OY)$Bcp9Z~Xfy=Dbuc7;S|k4}pUB4{Z}rh{A~mv$L*o?`RdxQ@1!8;*u&Fh^i2 zpR+;g9IIOj8>?cD@17Hmj-P>kGVr&{Oy?=Sz@3D+^kJQ()FsjlBaE<+MxCtD?J^rL zXdVbn7lGP2-1GzK_88MiCqR)I{Ku0&y{HbYXpEiV-_Btn@-K48?m^9q}bkWyKX%Hc35o$WX_UFN0yDV1cohEW?8KNIE!QWV*T+9sX+}}?C^0GYb#79 z?(>I7_*<+p@F&yZ6xQ*>N@mwhz3BejWU+SV#)PSvZSTMCh}8+4aMXV9CmhAQIpL7W zb)iCsZw%&E$xWeNI)CrG-c-19x91sG_NvRnX@<@>)%Cd=#~HUK|9OpnoN?_gk29{l zLtB|#bKMKtWp$^oKD@=_3`xfsmpDx)8SB@ze3J2a<|zi-5-jj0Vu5$KmRooFhOgD> z#WO9RTzs8*YQcv!o?49YPb{i**?45JAS#{>s(-&0H%&(uy>~pixEn_oD>K&yM{5g{ z?#83_bN!QxVaXf%#ddpa@k*#7r?P3*FXz3 zK0iQ{zU%?UzvBT0`!_zoVE+vV82q=v6fM>I6m8EBFldUl!wH6T_vZxTm4RK`wLV1? zNo`hnPP5Ysnx3^ql+42mo;-F|F`Zq!y2oc1uNEfXoi%mvcW`nsYKKYJ-ke6$^a z5P<%{`~TlXboSOk_SQl6)Y06z843BLJ`Z#Qi3XNtjk z6jQD8r_a+@92~Ocs4R)SLFMcCdDRa>cjj>ugwZ`?sY%PKtZ zJWZF8`t`atU)M%^R!AFgD96o7g1PWllxa(DB{cO)`OFgkRs5IA&oKo6@Z5CfiI68k z+BZ6X##?G>rJdQ+TGT;i+kg){-)*X z(S|3AedK`AVxo%=5g_S7;OJ zKlq1sj;3*M&evKJ#?=Y!X7Ac>v_U#sT0f^&d%`5YF4`p;ufO?fZL?ATzaf3p6hKYv zHE(IQY8TzVF7+zj*4lVe-@<#Ssd$IKrR60L{if`IA!%A_ptt`~TNI`_cC!|mF$wou zXl4MkP=6AhZK3}SEi_D5uQJ<4=H0Bw#Rq-jgN`fc$V3P4<#V;8bG~Tmz{KZ42gcBWolhOuVX6ZYF9pd49a&}v#)1w^{9@-0 ztX}+8yUlUu&2*d`+|inMUj4u?wCB)4`d!c=nr3(-zS2r{_G{{bzSUdmbmVS2opukO zr5!-5U`w6K!{=znpYxq|TMz$HGtV)r&hP- zXuYj2wtD$b>jRCqwW!zirpRH#2VSCvIa~$7fW>%7(Gkc$2LtNgf~Fbxvvj!6yho1K z$GL3KMbTO@*Tt=9_ZYosg6xM@=i-Vb+BXe>vPzlaL6uJU*$*PAF?1zry&Kj`f#bi{ zV);gNMO0ehv6HOvi*VUuY}67Dc*otOkHHPun{U#WdIue=AJakpS)~=mjry=W8*#6* zsO283{|=+vLEgp3>sRRV_ntmmpQ4K~-t^h}1ed>}`-!s$z1wH&Mfvg%%1+?q@K{_> zKf`8OS}ut(QoW5t5hs`d63FX z6`PH(@3UC9FnPJr8@Ev}(#4OxlQ-(~juTv=`v>739yKaHOY^_GoTDQ8jpZoiM*i}c z;5nnwh4E3twhV`V2lF_Xm=20N>-F>Wp1RIDdbtnjhu5EWfnHPWPl~HAIM>T7Hw(R@ znR?@_m@fWqh-~V+_yn33r-P_zvDfz~eb48`yOZ%jEz5YGcAb}hv_8P(w<;MQH9~B= zxJ4mncL&1#aLYn29t?#1+aKb(LIKz)n2B`usU>iyfNMWpj2eE)SWB_Q*>$6nMAuh_M`x+~9I?{4|)+phS)`{z2n z$mMsc_APC%v|7JJ*DmsIS+Ada(0_9m1}O*=j!q&ff$QG z>eyu&5iSWLT+%4UXBM%=fq25C5{4nca*=Z5=XibY(0}fVla!sEOd|Z4&MzeC-Pn$; zXVK%pykH+T$+Gi1I5yoe{^V4>lXuR~^ohNhsgmU3z-+I~@u;V8G}l_uS%#nND8t^1 zKhujlNV_Jw0#%aTml7jRAjexK3l z@IZu@DU;1m;p7+(qP*F&H|nD_;SD}l?+#*n`cTdB zM!cs_sQ=M>`rVom>U*=rPK6a;?nttuFkGwZ7 z(EHSX_>lgTroC4G(O>k%v@ELrKtJT52r7bF;Yvq@8*m?PLKX9uQxoAvjmgC=)I|QJ zj(fFZ*)?<%`eNq}`GMZ{VNVC({wG)F<*)JdVz2j)^*x8&@2iY^c{l0=VzuNiXWe{)$fo3FjXLpA?ia)E=c*d6QnK^YfHI zvqkk7oyX~h_*(NWIbJXIoSXGkJw?tAGJWIDGR;TVW7u7z7to+Zuac|OtKV|a=pja>D_lT3fF(UPR{|D|2|)4yUF!|6m19+gv^R{fh2j_@AVpu)i3+K zZs^_Qk|5|s89^^h2VM7)zN(0yrK}QWT29$QSyFL zO-1Etxy+|gwr2+s-C6Q@L`k0fh9vJ~jIDv_iKhe6yICbB>(9BHL{E+((Yx2^%mdlu zB9OglDj;S@jk2c;FBnR%_lMHO-TMdBM zzgW|UR^90!YSsNc41hQ4dD^u!01h1da9j`w$KpUZUaMT2 z2}fIh$lC+q$knv_Nj9GBhIs<9q6nCNV}@uniA#DotJZEzPf9Ni!ozF~-zYPUquIi4 zXRB}w16W!}ngoZ0rXxHTzHSCO$Z<|iTw0x@x05ECa5 zlYgoKs?$}f(WeI}%oqGL*y{Slck3?1q%s(x0wORGj8J^K3Mj`mO37i`k4Z?ndp~?v zzpw+lbY}?>57uL78UbpJStKI2w_B~7cbHpr%_Lb^vjsx~-=ZJjbzX~ez^n++tS>79 zn4|q4i-5oTmL3B9Q6jzl*0fBb{kL=wwg2`#j1osGHEv}cku`Wx?Q{#l|o z^N(8pkys7UgoSMY;YmrQ#oGqT(+PC3%suyT-7_8hlP!LpPcsz-a{`JDuF=C`M?Q`DUQJnA=AB$%jLT&`^{4|H!c)NG$a{E?6c{6PQR01hyU|zE zz3s!z&RVT^SUaP;&boMW+8Kp4i&Tyh&muDtKN(K-fE}EmWVZ)mhYSByE*e39 zJma6hKZSooH=LB9PGh;ECTw>{qyg~6pBxjpu$PE%4E7ZMM0fKBXc}U8Sp)oH^MuPD(TR_TttD8~aaMbGicz4QsdW?DW@YqO{31v+9=32{chZqZ0JvjsL8oVx! z*KO%9!nGT@8%5X%>?^&64;bCGgm={gMwgRP$Z!l4j0v0@*+ZBatD5V?8lO*f98I?p zHVTcuql2q91Uph}z~8rrb;}N077@2K;P1QHaI-BdhRoVHVz2coHyT~NPDhw+v<9!@ z2(zrl!Df$BI@gK&<^nJfhnkXIKi6?6`Kn`_xNk0TY%64~#527nv7G6YEESAiS-YC) z{z*RK`5!fZsbhzmr{_|=<6ny~y?TqDmV8}{+9V^r@e%Rt;yHm@q7RZpn((czjU1kb=qkeNg;HLWf9)-IAShCA0-bc>hska4%y={D>5 z0{K-UB*SS+aVjw~}Oom4*=cJeBb)lVNb270M7BdW!{ya{I4w#TXF*}bxd zd*Y{?oVcfz8|B(@-qL!suN?1YGTL~L)f+u4NCs+AiddXfJ5{;l!jKS+E3SNeUzXbInwZr~M2Kh|DbkM2RBAgS1bxP17 zLRcs0EKJF++Q{^+2saVoshsxZ$S~}b**N0(J=bckGjzTUuoGV;;#P&Xz%mh)LJ3U7 za|((1C5AXsZPSkgnCYwy)oLmi^MdzkqHkQd$y5@2PA{WCw+DEyKVp=Y$oil)4TNM$ zl}GV#O|%;M+#z@`W2AF`Iy27y#%2cznj&CxckI}i3 zDwc$G!g^E=#_I{)F+%0AXtX<$O|ycv3GBg`%<_~yfy!<0-l{ML>TXGpY>A)j2z;OB z$(CRWWgr^98}sL24CmC%?eKxWck`jvFmG;On}3w%&~n z%95Y}t|VmKv#fFj6CbrBfX{0zZ4KPJlFcq6N}vx zEDh;Es0HUb6(NS2hzHLJJl6)#Ha>GhIt-qj)j@b~*>8+4d8t8YhdK+_>KwfdGZWr* z$C`!3;vuNJ;24IV;cBh+4F(ge)!2ii1_QmtAC5JD;cOkK3ee#F>Pe$-UZMi!>V;k^ z=$)SS)*XbIvNH(%Jvy!{y-$xbyL5B#*{NjY%rNhH3YkjBNO_Y}#*yBV>i9Dh7wIiuO%P+LB zs?DLm3J8s4F5~mi=ak$5H z&55BdXqM$?0d6TYlsMd0!lc0?hJo4n9kX^!s}}x<6N*wo-X|lC_TD}7%=w+Rq9$n3 zetS{Hpot`w{E`Qyx$sSl-Dq&gQem{ZvBjxxxJrbRt0ph z^nwl+VwGi{zY&xiC#Td2Mbf7}w|p-laDggY`aV2J*f z_t$}Db%zG@t5fE2cM9nuDYyKUne6Ue{8OW^USic>Gsw)*BBHJGU~Mh$@tcj#damWY za#()xuwsqjnHfhGn$l-8eFuur zmLg#K`6hTP{md*z;2{}-13QI9ecQ$Qvc|5c*VyHjxG@~<&A27c2z$?H#xVUd%M0s9 z9DU?8-MBmd^-$EIogy-^b0=O4d2I}1upyU+y)lL{q6X?aXzfdCJp451t8Nt7c`*cm{=}cSHrk7TfNkU+XS*B6D~55P9!#c zkmH0^qLcv=-}nypTJI>+C<`^fd6jpWX`DKi#1c7j@X4L&!nKib14<~TTTzD+$IGzr z4U1nP9BoU%#22x||Ae9qFnvkzD*BpTY8pBqPtc0u6bg&OjKh?_Kyb3dY#@6*{K1aR zVPcMANf5=>!lW|z6^xq^t1M&%+iothwGz);)=R(3XAdF`gcWr#U1WvK2+ZyN?0=Za zHo^gOQT)U49E`{h;AL2glbvRG)OXeT?yA#|(J1WYSw`Q5PJ0=4+8klU!S(F`X2tMB zF?TJ*5MXhqsy6H!|DTBfprw#Ic8^U|n^)m}5)V5KdDqU>a z9F%iZ&TPCI3mNRJU1LSrEtZ@F13#*!%jwgini>#4mOsjI+Ik=LGmECxwuQZFkV9jC z1D?fC@X9Vmi zF>EK@;2XRXa*Tm)9O=jOkmGdpmJT(CMEFJOyT~OW@6n-VCv*fKt~H9go{u`B3pnSY zj$ksFwPZgR_2A_lWDfLB%{6*ArXKgsImj$9*qI^kmRzF*u>MWCMzY2ie`vqytv46{ z1d0C%f%yNy@>_;HLA4kx@|p=8*O~+_h1~Pwk+n`(OQKd1*b^qfB*}M47{3bnl0N~` zfgS=g`6}U3mmoe-9@I`&1nnf=2~~l1QcLELVNQc@Kge-9llu@S4pYoTxjRD)(RLDK zpMmlR_7v+}@`W6hO<9q^&9v;fVI8-wAD5%p;;I z6rHd+Y*G!yFb9{a(=oRqTz+Oi>|;bHRC&3Fnnk)(<}J;~O3x{Wh~ZCK2x?(c$(N@~ zj?DWd$KD==lOs?|<>(<{*21K)>C8Id@%MKDAar&o6egpK5TC08&?HEH($rlbZjI_M zC<8y+!TiC%Uw8+V6@2%`$be{|AFNuNfxlv|;6T>5UVcaV;x@g#< zEi^jjylq9dVR)c9nv?GhILs`v5(vn2?}9>OSg%+<(k0=FEWth->KpHfPAbt zQL>PC-(hBZCxHMlc6$Wd`h~_&bhO%N^N>#LE7PB6&>|~Zz)cnkisDThZ59r0plr3p zTUfPg_og>5iN;`3R@0K=z)q49hq=|eVKfeV&}W5faW|ksCMKFDBCYKUW<7zz=~#~zw*PWKPnVx=?v1Gre}F-{6opjau0`_T=?N^uz173Sgv z4$kX38-^=Z{Eh2vZBTD(p+;I;kGmdlVGXpr;81tqd& zwM!+WQ>=tn-NoqAH;$zIejkk{M#0fUNutDNd~qbPsvr7rBq27L-W^?x{*hP@1j3#x zd(8CS0G3w2G35Qd(j2U%yoxHb%WQcfx-~2t?C0^<%UpW|!s~BG;;3Poky1_9GPM&T z>Mm8ceg|0525Ks!QBL?dI8^3iRO9BL)wds}ilrN?+5dcVx{9KK69B|d|6cfQl?LQ_$0(j6WCW7@)mOE)*(){a|NQgjlyTDnhnPqatoMO5BhFMevK4c&FTM zjLT`)1d3qoyhm;~Mrv)nFAI!52K!X=z8&sQHxIkRD8?lRfFe57@Y8}b{av6U7!VBG z(5}*`2#zZ{WEUp|#mPWL2!Q&hz)#K({4!7x@`EN+1plLtil~7Msc&ziv8G=jE1FOd zEUx@XNDn+Jq6Sjc9sdCs;qa$HUQNx=AHkl&U!bRG2^Ar6LFrUTAwMdpK|E8>Kp%RK zQ4z&-WQyKAM*j>{1joiMC8SUh2Q$>_`!r?59x*{6*xo`QdZv)OSm~}I5O$Hb?Ezy* zWx_`Pfxmx%zpqe;zCb}N+z8kW7O}fTK{TQn2>mbsZ^oYx3@*?OsTI=M0o7n}^c*%O zcBf$Q5-+p@YUqy{7t(MrFn)c6+5W#1-oVc|5by@vf@}rfAomU5AWv-_-@s1Udwc_1 z)?7IJaoEQ<1n~YWzF{lmA&YNF!yyhhzQGlv6}|xg#H#^t(4GHye1q(wumgLBZxDql zGz*SA2;abQ>1LPs23>CV`t&!3>?^!MTI!|#HU*~I8Sn;O{K?zC2}xt?%OYS#7T*wH zHL~~y`$)|DusVyu%;Fn-00q{%dxmddceRXf5I+m>4L=!b$nOZ>FuxV-LbZ*#^&Vjt z2H{*&=Z&a|4VVJ|5l3_7wLDZdd|6}zw&>omD?{(XoIiZCUJfuzxl7;L;zPP_-^0|bKl0cVk7)u_i%+b|FoBIh2l@JwTliczL@P2t}yp& z?CS)xvYp@xKLT7K(F9kx9&m*}<5U5CqIe%B;0o;hOt``tz!lz7`|#pTWdiNi46Y!~ z3QkmCYdXSd4X(gnIY4j)eoAw=0zZ3y;R+t$3R{B1A=)X)fGhA5nodt`8@uXITNbxb zWl!Q14JLz$-IX+4A!H0yaD~mNQGzGHj1xQohe)+#huJ`Opd+xAVsV&pnDTM>!^}Kf zX%(&jq(lS4`bY_aD-dF$8C>B}IAp>V9>L36fGddm)Cdv7UQ{Mr!5C-xM3Q?0SHL+` z92*%(F;&l-mEMYDymy?-s5AWP}e_ zAcVx8!WGt|23vtE0PuchYj_2q91bL20jF~Q0qM0n;T8B{`-)dsu0D)h)*P>}6qQ8y zgv(G#Fd0lAuW%_UVi$OY^LNH8a44DY-4b5mWF`L$N4(TDQ0di`^T%mE)Yl}6T3hFirrxs2u#KBYYn>~Cp5<{6lH=JGO-Ih zwtv_KHU>2Y%mRTWaNgIfo7@$4L4KnOK-dNGQB&X147(sk;?wK~yTA+;IgMT5uc?E4 zIjm{mV*mlPgk2CXG+`Iy&=#-@V#sc>3v!?mmfc_%_}k5~3k;(g$%iOW{b?Gzz&1Bw z7dWy<*aiM4RacqV1qOBHY3zb{wPoxAdu2D+1seNW!Y&Y`Z-1~0lhsj@z$}m&>5kY1 z)(H)K-?0mYx$MoIzzbmlFUW5#@4`ak;8xKK(or8P1@r=Qc8Ol#Oa)D&7bNti`-Rz8 z^un(?8heIbkYBWpUSOZ^J$iwKRnGSxy)cZ>3;a(zpckl1y95B|OHG?FVC*sgd7n{G z2JuG)W$0{lIF_Ej2P^}7O<@_ttKTb@LAke23o&uJki_yst zw}!m0y8z>y@{Z_g3_2cY;of_QWnhm6ScbkWU>R@+nVLF>epqKOfPNFW|RVp6hM7^uuyIAkwLAO`Q6k{N)9pYBM>ye3NmktKo1l0alhAWB;y zfdFnWjw4!dnrBHMvLq1x7?&l1@UkQjSrQ0<^RgrmEK34GJHr6wJ6RHlED3~-dofuO zh%5;N=1Ex+h~g{>1jG5Ya~M!tqj27RSe67LO9DZ_htGD8s>qT+U|L0Yqq8IsSrUjW z2?Q>Gu`CG$xEqLdB})R4C4q3tadr*z2Le)LNg%Q$5Lpt4ED1!G1Oij$-UKrJ&mnJs}~KJciLHW{1p5MOmX7Eh3ETz$vmw9%7ja_^?15@wPAJ|GnscfWyzU7 z=AtneCE<0u4%BXqvD#lSXu#kBhYUJo-a&^99T1;Cbnt?c1`kdyH2U(%XP;GExoC0m z;Dd_?4;pds@DaOHvaz;hB^&)r@l~2pg0yTzl-4!*z<13karFK(N{9)&V3d$C#VEo0 zrx_)F1T7m-262{ z8H5u&7x8dgfz)tFP-XaPIK+8DL5Urug+lX7RiW9Zs?aearkK%GIk9x*T%^M7B{4QSXl^qzju=+&uJWgYcU z*0Dk>;KPIdjS1?I!t$t=m@Gzub`d%{y5zChiY=v?l8!Q+A5U63z+aI|YC4K^3H6oG z(@{fYE48@6(x|87x^Oc+9n22&bYL&pme5#&nZM0%^*^onM7_!e$5M)IfU0(-o}EF5 zs|!q`{RG0Mo56iS_X!0Z)G7i+9yPuu4|d+pOc(OaU2F1S;1PNs8Bf!|1WXse)~V{+ zGop(#l!lB0r^$n76?uRs==)OS!5<1*6IyXvkq3LQ6-6E+TppSL)iirW+#Qa%eIES2miaE^ zJ^uxK7uCdf(ZRd4!Dt6+)z%e$bg@n;#s2Yy-s=rUpC;uWJ+>G}|GSZ8yrwR_Wyvy@ z?^3(Re*;-Y8D{fKqDr?%X*1m(9Pa$BCY>I=eLZ~ApW-*8PCSs>IK~CqIKXP5v~dh+ zf!;z^G|^j-HjbWYdJEA$(8kd|(8d8;3tt-tv~o0R;}8!WIBgvN*gJZQwcB?|Z&9TV+=oU{zjbIaP+`vJKW2OH`)+I2A``mdWgZkMvsFH$(uMbNTtVG++L+!Co)Z%HiIK$jWI-z z1sXkmtZs0!z}%4{gZEOG_}TSMH-$xID;hmktBb%qZ$CA9u;S(v8LapIQe==u4^RgX z$Ahy2MF#88bYY(;GDHo+5j6(PTB6DTw?M~iH6|7sq`SieP3TrY-fs$e?kWKMWu%vu09MO-b9g+ z1C<^Jqmqak113>qh=UM}>@ashks-8bU9^!$3 zC}U9AZy+MzR@sRtV^)*g`HBmOTctIkjLEGLWgOAeGwh9G4}K>~pFxzt??5eN5M?m< z?-NmmT#twWQHI=rs>U;iSxauHseM-L!IWIYAacH9kJgAXQ?!J-_C;;(^GKQ)mW)fxaQ!|J%FxdKi(hf>KSTAeWNZR^pJqoTAM??`_nj!Ci`$}xkEy%S@G(<;C*sJEGj_?5!6vGpjT{-r z2Ict9IWh!3d~NSmG<=Lkt-%lfK>Nq;HGHrcD(44?BZCb=7Ai6{e6+xkA@dZg3kQKr zTHOb6$$Ss$K6)W{r0xUe_o?oqJ6=obK8o<#{Z#i+h|iy??xRC!2X!9>p@1Ueljal| z5A8Wch775Wj{l$qii{gnd*MGqkAmYUW?bg0`}oSNN#TGpb?#yZ1gEOAW;oe;yD}8P ziPfsNmxZ?AG%EsK;}eGP5UyN?Cah<=O^2F`dFaU1%X}Te2`H6}Y?ONB31(4x4LI2) z-Qza&bW@lK7%Eq;t_(SguZ~>v8S~Y1vhGl$EH~Cz=|pVk$!x%MHI9JHWzi!)6Z$iV z>>%>Q(&hd!TTEA`8^Q^yfILBY-736f<$9Gd7y2??4(?{?%XIkzmJ5BEF7#!t#M*5_ zpf7V(v#=+m1Fvf_usZ{hH#5f#DC}6Ub#Dh5Ankc=kVzYf`XxpNY-E76_uBkd$!l`k z*U&^k4r0;N7##QFc>;tzw)}E;<>i$jSp;RUa7#cvrx>8Z#0+V&G8WxdRqW)fXAbYd zq7!v#+5;?{(OVWTAwTBW1I9t!8T=8J{P_{;3pz!X#kx}%o5BEDu)dwc5Qze@Knty1 zG!B}Gs~sDGc~=VD*0Bc$2_jQ|f;>pDI}+?nVLAq3kRIar=|P*VKgM@g>4{t*YY^Tq z5Z;*@Q#03pxxIlqq8R(18)iBTW@g&`B~lAYAMcnuyXqU_l8GUh)wy-W^PiHQz)8I=}h=F241;8JPr zpp;ZXS*S`LAfAlu~(t74@vlqy~f7(ZEQCh`mwf19Bo1BESiAHeG?gk zBG<&2n8ST@s*@OVjFXO+qBay&@$5~-uCx7dv>~ZaK^vhk)bihR@^q+wEl zVIEnr^d zHLyVb&FB-$LRVJJb#f5tX}E2L+hn+rQsk%MUOR-Di6PQW4dG@3zBPUC98_r>RT&?% z$f3ldh=;Ep#a@sZ8^axYd1WZ)d8SKLdvr58LwvrpTNLl1@HGt8uOdM6RXPHCTNMFX zxB|DF<>*Jy`B8!~+MfvA3IC;6|#L-V&RVREchSbNz>+iKzKEBb4 z>y@EeBJD$mn)4j1v2yXy27ju0lGWI9t|v-SD~pA>Wz#x0g{pQdt0NKYPEC+=BU_Oe zxiz3sQ5?!VsXC3|pIDDluNR@jddyPrOrNp=&y*>a&!TQ=TSw%PImlr!Bc(NPK#PyS zp|S5R) zmW~M2;YceGMHFljdQy9XFedPI?o&{v7OmkQyQI&Ja!;k1h?l!{Xk2yZUWbavWPImI z^u6IWd5DPQpjsXLC+^@+ajEv2;z~CM@u;(+xH)J$6xVKytNd#yKsvHhz?^9QSjX2J zR-pUOF^sTIf$2XdO2ddl&u16}}2?ke7b}Y3T$R1?SZ+P-P zm)b-xwtRubp*)XNDny_EA@sEhi+Vpw@0wibQHA*Bpk;4MqS0lDpz}8HOZc|&%{*j7 zud)5v3e%oWgPhb;den^2Kxd<>X`q{{2D($s2^jO{w8K3bMLVd-G$ZW`Kuz&i~&}VK`-*}g1n-KrGh+#U3ALx9q^McDnH713;7+j z%M9--Gbn&}%~58D<1#Y{62`_1=3nh+@K2P%ttu1pPf!zxO!m^S^}9v6(H9^$e`Kb# z0Df$m33SM(@io(Vs$Xy3+N5TCuU=`FlkT;)+wh@-Pu?aq#b`#}k z^=t)3vC9Euy_y7Z8DV9|1QjfSrlM6 zcY&7WR&%th(3G8@8I&diEi1oO>ez$r3^~4b>BStFi5*6fztu-L=NH1h(>VP_loT+PZq3jxgImU0cNw&|``NlwGQ8 zbFl1lFtWydb4ix3EX!9$Qw*NvE6ehgRb~0gvV3K`R_bPOXa7*HJg-%htH!*4Z8C;t zmAZ|!oC1u};7W@_LAR5iRqB>i>PCv(Y@9qbTqhiQj^TOFl)8zBu&u?{TJ|$st!lqf zi(U30+@X-z`@^y3FTNwCZby1cjyF4Y@-Hi3!daVN>Bi~e0w&wFLwID1_p{^8k*z3x ztFRGrj}*Uom9x#VU1C@dZ^Es9INLnhm1ig=Z+wPQ^2R6oO5SSrS;-r&6ZOEVlMhwP zt+IhN)_nPKq-+n>zA>ftt-xm3Bg%xY@=tcq_4fE_F3s1(=jzycce>uhm(6s&$sKgP z$?rhd8-GPzJK4Riw~^Sb?}7cU9+FvR$gufV6_Yl^V%SQy_f7{~fh(j+fW7QJHo_>< zgtw{M9IA0IZ=_LBBYvrT`@C6NOtx(RlLb81 zhsin_Fj;x`frH8Z8I5Kyw7_Ng${<}NVOhSiEMHk|8}zaYaAwEyM>`INPdTS$h^w5W zU=e!*aTPxS90YJx26Im#uAGp6tw3D6>I+*zxbka(8aZ$XSKdvb$;67C5UvE&+b4vp z54DEi0c!0%I@Iih$D&kjHdXyc4z+irokbXKUDp?FedulfA*V3SiSRv8`eT%AbL4E)<+j^G*dC^SC$F}-c z$;Dh(K=GR#j~8U(S;wI?yTP-v`&5Fh;#sSj<5@HHzU5~seq%t;O{ns64>gN)r_5WL zZxq!y<(Nd_&kY=e!lci$JXiC@zM%}0tNc;ewyt(5T$Zm4=s6OQ-6(!zFE>~GCZTi9 z$Fl;nN(%&%4HAj8&NVul6*wv-JS$=7DNHjwD{dF06~FNpTUPugpWlt*H}Oj}cL;GH zm`!pCK>PmSS%X6=3H6wi?;RDt$+l?V`;KSrn1gfo79p+rZXm6i`cx@`w6a}8TEBvp zGWrC6$7wV`4h#rizbN|(X}w`I4tvmNg=^;lQ`1|9BOpN`a0mJ=xB*oJVQYZ9_^@@g zZ}P8uul9{^SB+=?A+7C6?HhYz2eohBONX07bLIakO>aEQSB4%Qdp-YAd}VKGA+t%* zTQL;9c@=MKZM>;v=7TwenmA?fkm^QgMKAAA(2?aICt1j2mxTy#$CJ!e_Yw~G5c^!z;4Ik2QvoK?(S_FjD56NITD);f0*_Z_=5~9 z2Gj0`v|z@%!XIV=W)?A#MNH^dp^;72d6=d=_O$AV^AYwHae{qy7BRs@aKTdGVq~sl zHlZ%w`Sxr#itf2{}NY_~wF_A?~bi?{5|4^saH-|wj z1KAI9;=mX9(4s72B4B}vvTJbme2XPMR|mO11K1}`0ITK8(XQQw(McYhrgDam0goAj$V1A#xUt926;{9sCYxk4)Ycnu1 znY>?{%pG{Y9y7f+?ln5=H-@~wSDJ&NP^qHI>@r)PxaYiIqVCe@x7cVPCc*~nmO404 zYQQ4XAw^bWRR7CIW5$j!^8QPG-mfF$L^W|v_~B~}Q!{hI*H4G8w_<20}e7X`O5ubh6!~NF?Od0kr~+ zNV<3LkBq`Yt_(;de%bfoUQKdN^grn^8oS-zBBog63+@vneHB29i^ zlPa}92OS&JL?Xc_t6NY1ek2m86(W%k)j6MH#hjt+6n9g$Dr??f}$}MiNHgz?I0cw zxE+2n)R5m1x5NBacpIwy3Dq2+4W7je8)$=8Q3yaMOhNCJ?xi+hJO7VZdz9DmP}%Th zkqzxd_#L}4^e)W#!#C^Y9Yna?sSKUueR#0ZT^CseX4JRujsZe`(To9t?Z5!Rz5@mb z@v<7Xch3N!4fI}~YZi62N6;cn>h=g3b~b@}VL5lGSvZ@R<;~t^EO6vYDoyUK8)5u6 zC@?E`X=A?PMQ;6!mo-yhM(!*)29s|#DKh*21hrrrgZ0tid9aPo^uYno1MAxY&jT-Q z;(2hP4y}8d=Yc^-2La1P4tO3S*p-Wb=OJQD(XH=>=Ye<|_J-%7_;X>!8hIg@ul+2Z zi+xvgaPiOB%$?Ms%>|~UmOK|DFi3nG0|)k6M7Ax{UK`F(hXz$<;zl3{7`NmZP-XTb zW0-zPlP0t4p~>u39NwTq6|caACNuU5G?^L3U_&m4Dzi1lh#Fk<^egfOW$viTOjHL~ z(Sb;ytxHm$CR;%*@NEYOwZM;Sj#}XJ_7}C_0kuGA1T+~3wVa7s;8UBU7TBW*2b6+% zM4=WKOnkO9Y9V9{Rj7rBP@{xWfa#+a9t=LlieXqi8WXxI%dkUe=N- zv-{Ll;8-qg8{}C=--S+l^smM^D^8~)fvN;*cw6wF@ENvWbkm9>I1w~W*bF=M20FeM!KA!8$zr@_+6+nJE0Yxhd?P2Rnz6^3*v30e~9C> z^*-un7EP;d3wzZdht@j{cosj#D~aa;<{tArT#p)Th3BD*!Ov`s=;2C~`T!C=bPA;F z@|}nt_+k4>^l-lVF!H?SL=U9xj))x=p^{)Sn6+d-8x^q&qK8v=CVJrER)`*sRr1ep z(o0Q))WxBB>`e6VFJvW?=;3JCTO)eF5jEW#5AKs^5Iuabk3j*nxHXDhq8uH>0DPL=Kp5DU%^?i@Sp{K`6-@&l15}|U z2!nW`3Bn+Iwg6!eJ$4IWkflmkc0>BWf7_h&fv|NXAEHF{rz9r?^kWYxcOre@$eypn z41^I_E;J*3U>%!CAH*{)lRmI*yCHp$81q^peUNvnOr(0CwIU-n&N^#>QQ#)jBEXD! z3p*Hv7CAZXy_Gvb7=lA3fmtBsdq>g-7DWT!chZN#Tn5bsJFq^46TN^){MPa=EHn=8 z70ahq2Tqm966~spu*=uEq?|&2qqrPWpnYK9nBIMdneCkf0>s$uk%aeYp)nNvI@)OS zkWTz>&1oM%bf*flue1-p>S*j4?Sp*3b=n8^r@g0rU;)Ty|7jnF5$yx7X<*MPNP~FhdxbQJCl#cD z!Q4+sgM7R>q(K6~a7P!TeKMF`g7o(FQyymLR02-z>h5bDKdYMa0b6bBq z5=RZwbd_ql7NSft$?gpx4SidHG~j@ag7A?F(!lS^gfwij)_?@U3zeDQn*Vwt|LZkn zX0gZL(tvB&u79^&4?i;cneqjNYw%_!js7FQP-nCJr{6WOVZ;FdHuTsPu%RpfHsFMR zO;4+1PBlj5jiFtW&;=wITYm-(Sm}a zrD!X80fh}(R3aHq+Xtsb%ghurdd4E9qG z*^rTdY)JQz4ap9&LH$VK-<|Fl9vjdM!aHKh`!O=hnRk&z_;A>U&v3B?J`;l;*Z`$S zzdfrFY{TE&3o^t^FD?<=@L|FQ8E-k*hH{h5a63N{+aNl|u?=Ln8-H@J4ds|yZSlkD zT^K)k{2a#C%WMZ~27eSkd8?4bDugiaY7rNjVOyQBBPD1RiEUsLz6Z7;_mjpi$PnIz zO)i>Y07I+3k8ek1+1ND8gxO%TnWD#lA+!+GxTkPV{hdSmN11aOPyk1S%lV~`K=~e+ zu}6H_|FgGZ*e}H~5aPu{U?BJ>!~AW3NaVv0XXAm*ZVV;yL)&;Dvt0ay_^Wp?9Vo_D zF~`AAu$f9Q1u`*HV4cL}SI%1Z_TljpY>_*UV)MsAtcW$hPv|aa6L{b(`> zKsQV{`P@wyce8d@B_>)3cc00RO+{LH)DnW_JeekjUvc8(yq0OlRs_r*ATEHvNcZlK zE1dkLj7OqDo%|Lz;U|nzP+Es_tz@dazpWO2DPbC}lK(0j50*GX2^s)ni5$M-DPOi~ zmh&4&`F{-h-0nBN3@%3dd#hGkUN+jFrP8*%u)vp9{GV;(fwVdn=!9r?Fm%FJmBZV3 zP{}vEpu4XqEe6cEUM0o|9Bo$eOS}8J_JOfeJrS=_+Oa-fgZK}HocNvc4*zx=a*kyY z%ej;nZ}+uGb|fR<=7Xm&&1}V!d-!&in=OiU3M+sV7f4ik7f84lNeqR0j0``MmO`RJ zi$WB_TDWDjR=Vj|(po3|0$Q1b{Vwp`m6#7S57$IBnRp0w0u3zzEp0OKFh&?=OGy6D z6GjL(l|EHPD7ZyvmzCP3>RQJmKlJyEcKqlc&>DwN90;j zcxq#bI^c!ag%>b(QR+R1@m%RWo1Kw9mIlv9cPR$DuW{gn*x&&tPU58)qc2GrrkCR0 z*4PP*1BJs1UHK`ie?5i_TL=6riRv^}!*7^gnXXcc%(LVvP9;upEH>BOihEEm$q~eW z7iWPAh4{9puYFG$d{lR7c$f^{x{vR4+H^}su)SO>PXb1w>6VOXAPfUQNI)Q>{e@B4 z-19#L*IwXU z0<*WjuR}TcFGf%F^szDrKJkeUTMvGH5C3GJ=+_8-f)pjjyC|JVA2JMLhMTfQTTkPmy5UE!yD$g z4N(;Aa`&8cc3+PNaj7iopfGKo_+*tbyCW_yegyn*v5*??7_61a77DKa1qj z4;QPXZa;%~xCCzHQNkz~45HT}tpG`pFbXE!L>L8o8UYC~3bqv=YXn9?9&r!XLfA7W z!YCRn;;7~kVH5)Aa&q3`=fEiB(OISEPlQoO*a$dt2R3pT7{#Hk%OF6|5d0krj6&Rx zPXZFb;2tfE!rp)uJOqs5(AQauAB*xUb8wm%9Bzmc~&ONxrsi z*kUviU=yMOjRcp$l`slnqah9rqrmMO{O)95JLP)5E!kIf*!wcb9FG8a_hpbd?vQDC zUxp0~Tq2CZz8FP21dKw!*nFcf3IQyJjF1E6SnkUZ(^2mP7=@UI`X|6BY{VZIjDnqy z7Xh6xTjPjuGHQ-zfw1ojqad&@g9$FfIZ^Mv40hJ{gieIeN)kFzf=V0ksTL4?1y1e6>3o>kp!DW6+7yjtrgX?M{#*K_}j80G$BbK@NS<;JysGB*}0Iorv9+ z!GJcBZFQ*oGVHyFfKKc=5_AIVU8B$mEJd;q#|xeCtUr+6Ue|cAnP`O#U4BI;IT+x_ z51lyf`!Ynb+f`8soJcfX-1{;JY%j($WM2En3gA^i} zY(0b}SUw;JI))1~1W+E8$l`jOwgixc*wqj#@mvfmvGMrrKL~O3_8-XBM6kqK)41}| zqNxim=*81I_*?LtE&e?9%1illuD0dV$EoWBn@0X<^HdeukQhn3L#k62Wq;Q{qNAi{}{_~WRU5@jLPwE#oeB)=v6_@s^-wi&5RHZ37 z@oq>=f^LBK-=-UkD=%qSe1y2g-{Rj`FItYEOa4VgS6M{uuc?ZE#Lm#|)%`Uffp)4u z0u9iP0SR=3!FyRFgLkFY5myA{57P4dYykvi|&arfpWm>d5k9?RAC!Y>3vn>P1T{c&kFM z**47*xS}nIEY^+f(=3AL7ZxnmOBPSFn6WU(Qt2y$TtX!Qj_-|rLBrQ zv0WRfC{Od8G1^r6gu5*!k4EM`qfJqgNLwSQv=5pFgn5j=_N>;UfV3?S(%+TpwGjR< z6YDIJQyw&PaTuViv!pR0X?9_m4Ld8X`S7!~wrO`5L218DtZ}mz&H2@5YlSNLm~T2; z%g-eH^k6_dtQ!JZoPCpS6xo(Y=eu@jMXLQ*o;6O(Q`y^m;5aQiEl?gTI|BvzngpeS zg}9Q>9;apHh~3D7J*->e2Hh$VI?V-}_ZNh%d04m4;LB^YES3G4Zykpg+iCD!HNc*i zv=v5;QI(TZq>3;2?D5(t`ibsTm3>yV`ksmOL(jLr>f3ud(f2*yzN*4|v-l+wG@*(o zdErEDqVlK6+?|?*E{awq=jQN-&(V^UXZhB1v_XAOb*o$hk-s5Z3V(KYH_QMvjY1j_ zoqicLR#3;(dhD5S<$3L$E|u8e5uvm33xiSA+R4RsF?#kjUM^^7@*q!sL2IF0#|KW* z2CMd2eD(|4D5W=l@&)Yz<%>wpE)-HZpRYJyTcXV4U;R#7po#^2`DC;T`7vMdqBc9g z<}PwL4G5U3?jDn$RqQsX!Mr|s%eKgDB$=gGy*Vb6pZk*5LM0RV@+n%O`5{ghyW00# ze9cQ*%Py>j1iL<}s>WE0%6$^s;rf&O1y21%u}G=u0Z|s;`;ykSDp%>d<@Z`gLpig` zdUPVc<~6Nv^ZrJ#q$3WW(8J*lz)Il~X)-vn^EK@OMakw1F4ktK>?!{G#oA_{{lTKD zc|Fd8F^#INJuprJ{M$FQY$Z_jZI7jqHM6zp%?#x7QnoOv%Q5lni9DxV%S>i4Ybr-| z&9dA88(&p6EHjTlXGjJu%OKhdkV==dA5CAtptsB1a8kyvF4qcj#9bsPxe+nk4KEoC zkOmf!G0lkIF0I-%tkAO0^j-<^99zq>*ihFmhB^K|WU%Wu>uiwsF5`1;%of()_16>=e=IFIgKxrjlG*8QT!{}w>C1m_V+M)8a=ik> z-tNN-E3^VtoWdtnXk%4Tz&BTDyDTX*mepo$_|nB_SW!{+WC-KJu6i{zSS4wE_!4bk zOYyFT3ARROsqQc-K?BsFQ6sl5(e720wUL3>X@yD_+pW3H`ZSt#?=?Zgk3ym%;*F}g zBlGfXfYlvZ0zjPomus8>$6oWokj(xQ-?>!F%VV#)Ve(ZQ;CT5?35@x~nwh=Klb2~% ztM>DJ`7-Scy3XCmk>~lYW!j>Aw%zrYCM`3 z5Rg_?6ULXNlV)BQUm*-*>}X0ds`s6}qy8=iRM!YCfMh z$pnBv(PGzJ6e*8Pxm$~9U=cF!)mEoIgOyxn<;Q`kAJ9kst9!Nmt$ydy+7|{*w?wu3 zY)gY#f96ka&`v{de!4*`O#J{v<44O0z3lcC0g_Anyyr%(d%NGp-zC?(&k~7bUk;4t z1z6~IMHX$;e(OK0*a*JZ3sey+_$Tviqt|FcFVD3oQ`SQ6kLmIw?_I3B^X-I}8{RE(2z-a~Uvug=E0W^vEqj z>#H0;8+MCokB>aLT^rFjCpJ|{%8fH(qAh~t;m=Pm6jWS}ah0BQ9 zpSX;e4UVTFBgUG!j2H|IIE1kr=_JYJ#Kbo)C&m`IoEY14FegUdbU86Hz~#im z8;x;dJSVE1qWnX0Vr3Tl%q2hKbFg9)EVkeC9snP<$U0^VFb$H&O=QXJIg5h!MRhD$ zOXZw{IkHxrqxBgw;W223WXMK?A?skMY?#ZD%>qYu#=#t!%_2KzNscV5K1W902S@f; znUY+!^|AH}<=_4Y{Fv3mk2UdQ{|@{Z$#wZL*2d$r?~u> znEb!Zk4fD)|HVapdb{%8-2PhZg5o%=_s%ic~8d}Vy zwcBznX`@|=Gb;fdhGHlU-_Vmvuw3XmK!(NwGK9>VcZ9ZUJ~6X85py2m?7u6)p2(w0 zeAkzY<%-FJx9QD$eF9y!AW(0RMY7)R7fqxN<0L1FpTru5VcW}G+>@GrLz)A8O1|Dn z$>mG)^@|3y!}p7DeUl%lC7d}7<<^)ru%dpHN=ZH9V!4C{_obx>lNP}$^LRlgJ-b|b zx93sX9&UOrrJ9@kTF0PRe=2XftE?A>TcdRO*?zQEhNl(lrA5qNim=i=rqRLUsF|kd zwHolh+olKhg(PQfP*3Wb_x@Vby6-s_GI6vnM|7;dCh8l)8A*shrN;}e%NyoK zORH>JiSb!3Uyx(O#BGSN0lPx_-|9eRoMQdDQ zIJ{~*ARSI6Yh^sj78_k=N15K%qjHX0m>igXW_l(yVe(9-i;XlV9_^PHCetUDD+GUe z*qP(*T#%7+UYj6mWTyn#IUirYVJA-quwq zT@{7$Y8;EN_0osE^b~NI(0mwzgd3LWZF8L!mLCc5eO>je@=A1ltTyrkl}Je01?~_@ z!pOldF}~J`$1uGN=k`zpVQ@>~%8^%#wA3TLbrrCuTa^eGmy%$uOb?ePW9WeN!`Rs* zE2^WJP9g5RDDm9aT$lXQb=gJkm<&s@*TWm14d#V3{~`g=2rUgL3KI}FSBVBKeL0PhY%JE=lu)ynZc;6 zovdj(4qQjC)ti}h@lbASJwz%RmnI{p^x?G9aYMA$aiQ@}ky|=08%#e3oPtTMypgnW za5A+9k9M`-(-+X;Se1UgRv%x?MtD8po$|^VEBd&UO*Ug}2-Kp7DZ96B#@973AG1!+ zNQWg+XK@cOTMwv)&gSq1>-0it9j>R|qdW>;AOsC0*bp&77(gMoVL5={M)5;)>cj`5 zRG<%0Jj?V^=-W8yWjs_*Vrj!t{Q~KB8hEFRI|D0K;&gDO$_%S^b3k4VQENc4--MaK z#iI-8aOYtfUGBJ-QJQ4vwRpDBR!BhQ`72E}^bo&hz23I06cfOip^gh~32t(+t>0KG z`4jXd*$9Z2`|T(W`JZFL2t2a})=Gpk2a?crl2?&{ETBksuh)UYX~n1X(%YsDLsgtC z);R`oNlU(>m);_+1hq~Gwwue~Ow<0UJ9{FR-J>^C0AeZUQ~#k%=Ij*Rui9VnefR2% z^6dxQMB?MPRhGmt^^lEXe9V__&-LDn}H4&fP(1K4*?0t~8D3 z^wu-W%)Y#2UYzL$`XXW&Jq+bzS9 zN4Vx3dUwe}8U+;(drWAkczO?q3pEqC&|LDk)7FUv57~Px2Ijvuh41POR-5rD**J_# zJypLrU4A%J#Iz6yiJYR8@xuG`Svg{-XYwYY0i1k*Qgrjl9-VG$7PIwAyb3!hj*7qJ zyf$IvYyw9$9K+5`XPN{jNjh~u+D(S#=cUqcm!UL&a4rp(hUop30PLWRX7PV+)LWK+ zQ6B8*v>*!B$QPCaII(1t+DGqeQc(9H=$7RxIXvm1B=-&yhDozTvtbR4RAa# zl580|6svlXfJBl=LfB(B_~QFX5KE?CeTkT&f&@?DH$Uaeu$HC;scz4)$OHU9AALEG zp02m_Mbp>tLBG(4;o;$`8?P|DJDlhX7lxE@@FO~bX|^8E?4 z(s3s_;clKGYAS|q21;~jz@4FYval2ybOxg|nZNs>zA`g};TytQ5<>Q75%GrxPs7z= ze8pyczO<_fGC81--^TM&gCg==D`Xv(z) zZWOaCD*c!pA#D4?a+biAvn2}GVXQhJT&{9G;DWw|;19`ka3wDk>WKF(_&Z|r6v9Ik z0b#hId_-i}hS>=(zzx9-!wtiY!i~ZOB{s~?h=&`38-^Q(8-*K%YvKwEvkT(khTw+b zhT%rxM&X*c+QKYAJls%0ITGL@jDRTIC|t7z5_ClZxFNVTBqITu&Y|-R zFTx*!E2(oBu8CV4oIyE_Z~muJ$S-+BZp*DFK$!bkPoQi@Sw zq1!5pDgt%3EQD*z!gTfvE*~vAxJ2B}cHMd4g=~iGFoQ%(WY5$3_%h17;gxP=gVh}q zuIpE}-VN?0BZ{rA_D9x-S9K(OVOFFXV?Mo#6s9@TS_?a$pI z-4%kEIgFPvFsOD<5-dbL9>6d!yyRZ%Qly`|{~l{U>NtmWu)4!N@VE8Wg9v}1xV_`w zynmgwAN~W~@3H10PJTyzd(O|+y6NA}4LpeV228NlPEPwn8U)Xk={T<-Q(UdF#1!=8rAtroTj= zhcu$Cn!G;k}KtqUI(N}$W7@S}1lI#v3=hCkIFqgRdt!!#N{ zpP`E{y+r50j~8W_Y<4Lrk*v8{%k1(*LeoiMq;yLlp1St8Bnw8|}AcLcX9{ znK(eWmMwbWUXVv%<)Y_HMDG=BM|*U$Er}NFrL=Q~gmA|t5pTM~uE*z#sd$+e{7TQ_ z;a`DgDvjLrEB&-lTk>>VEK4qDRn>WV%mQnB{p9Lh)QKyl-Vn4dI>_r~XY})=mEX8l zSPv(y6yLcU_euo>=_sX@Bw6J(9rbgEGZR)=F(b?y+$l_c>1GDlpL5BDBe*=p|YwRZ?le+4I6#9m{p4wJqT{k_) zmu_F?Ql8je)t(o@UNzb0BQ(Cb($q|ae~8VMQp0C&(6iN`!k2B(U&(biF6>L>T)@60 zAm@PGmbi1FLXVukQ9oT#p6Au~>2I>F-h%46N8*_6KgKy``=Nt4X0|;7j`<^lPH<^5 zDU2+CL~o(6Cf4GAgteH42`E_$xRuiyuog2LvKCi1!dfi+cVsQ5*)D4#U5~Y(4Ot6W z+eFqv);5u~h*dU`wQwtYGFXcUSc`Ygsvcp`2-FD29)rqn(GgXTSJzWLUeHsC;6lx_ zk3r}6xIR&4d^w2rDw;9%(%F|?c#(wTW%69pXy-#1IF~k#-fyygZ`N}_M zjbqTiK8_M{G(uYHewUV$T53vVO~KRd2xLQHF33j*jHgubF;5N}1uFT1_X`@(^!k*~ z4I0q@JHQ{6;o?KSJ7{EOk$ohX;}Fja)?)>-gL>qcC0E9e01`)j0sWjwu+0{_i% ze@P1FI^*|`H?niYRo?pTox7>ho@JG{u4eIF=|)a3vE0pD*0>bgHuI@mNBh|P)b{&P zMl)?N^|uSceDxYDgwqzn(=v?qezI7k@NXs<-TGMnG?KuBkW#hSU%PEdp!Q~_`rD1v z{l&KPqD)!yosneb2X*^%_v3buZ=PUes*tSim>>t;PxEH`IxI_6A8Q4*un*$Y}RdY%HI3j@Y%~ zX+D_#@v;ia*||n;P%9zS-(oO*Lm=d5GGthY(4j2{)4i#SDSsRx<;;|$(jA$Z1wp+9 z8oN1eFZ6d9sXz1EkDSuVuta}0(zQldR)ci82ych*whh9YH7EX;$FaanGTZ9Viuu{E z%Y!phZA0WPbUWl|Kise&4gJSnuoRT6!N1#WZbOK#w zq-A_kpFm54(sJL+N0%9WRYLgkGGnnSK6A))I{Pd>9yblLb@4eLK1$NOk0jY1qI}4= zjxq|+jMI}qe?JZywAH)u(VR%Q$zLVmE>p=KNx7lfzFU&+w#plPb&}D77boNWXp+(W ztXJdjlZ0pXN<7?tIsPpE5Pxn+w#n}$*}hs*YEbOclpT^__fUT8(rfVupEVZrn$2}* zh4{6k*M)q~SUFWC(QeDlvyE<9_Al`XZ&Hd!-Ooun26F>tXB$PJ*Q-5xeMdZ@L$7al z=(Wl?|7x63SYD6dN&=loaHT(y;7S6VNN}b9rg;7i!M-u>cL??h_+tcL66~MH{UF#r zgWbS4jW=L=z&o>w?e-+aCMz3I?4@qzKP<)m$%&)bQ|nXgIrXb|Sc-kIN3mym6nh5V zjZtj*+>m0A^(gkZ|5S=?xBIuC*y9eO*eWaFubyX&%^|6nwVpIQAFHh1KB!w*k0ccr zxAEoY8@H>_70sV)B-%zqO+BCto%;SmbIYSmT3ur-)Bk336NU ziZM|Uk=I@^K2%lvGQQ(a#_A0FBUi4o#s+@_$eL|j#UGj*s8(K$B)@KCg3eLCVU_WA z(iS%zP&y{*&3C&wv1-~#B@W($gE>qcPKIK7UY2@LLjiDK)G(WX)!H;HoUA4k!SILATUM#$ACbkk7^&!Nu4SdU5BahmbLuLl%S48%% zHP*{sM@MJ#H5-hU0X5#;{KgNAb9w4U;~f=m${ttuEsC7+rFD%GN!?`3R29O1{0rkf zm5q#`v#T?Q_)1iC~s$NI=VDZhFPLlG~rST}=$*z8N({wtK(`mytBh?wk4OY3j zVg8ag% z#+x&%M^n#)%NTkLN4ZC!Rk@9=u4mKK4t5)NeRFm+UBI7w^R&+VICJv*U`7zsy}z^i zw&Wwvro9Wq9QUA?b#h%B_W>JZq|SPH;Stvr9bjyP&dnlw7X~X~s#&~*bRkHG`g>bP zlNXJnlYGQ?6~A#DooulQO3*LGU{~-j#?gFL$h+s#99WZq!KQlxW#xAD!XSNy>e4D&iP&V-6mPVa0h?U|EVoI@bZO*? zeCC$YcH~Zk$h7h!CFz7hSW3-x#aamHTAF?tE%DS8q?syX@igkXqdk{V_9@I)y@mH* z!Z%ke_k!>>N2Tjb5#&EHyHF z2F(JidmyrOCQVn;#T%aKI3m!fjEFx+HeE;u1F^{?2Yy6%`c*MJ^5k5)&*zh@VPFhx z!*el|<3z`At~dJZ`s|umw3Dvu7<%Hk{oF$i^7igXIMg7wha?Vic7-=I3SBog$VDG7 ze5>oSZr&h&&l}`_bO*W3yg{Dq4RU%FfBLS#l(fn2xD?o1$YCk|#tT;m+5&JThkCjw zlfl4R&GDlD!gKBpv`|L6Bi;_V!7LV?FyiHGkh6zOansZr@$Ybq_~EKZ;{(?OhIcUE zFV#afP}=WP-S|zZUNc6g29Q>=L?K%^;rx<`w09mxpJ5JW5SH3TO>wbi%ol3SPi$&@ zK=qoR2)KOpL`)5GmDe7>bL(xqm}}Yl_<@Nu|A^B{>^OK@+0VMu%6{6LR=PK>_H#_D z!Kzrp3ntOmRdSb{U8Blx{oy7TyJ=yN+n8PHKX)e=gX>K$j>)xO71u;opHBy>syLVL zon;0(MC@@|39*CWY?hou<s_DcOZ&tCTCJh{o6^K1ymoIhZa;pIVbxk!mT z!j+$?lF^S-fH>PPDS%w!V$n{ze-Q;}TIQOTxf8q0NnuspG8Y$Z#g@5Pw2a~ZqCwuY z%rz}@ay>cGJY>@{*Vr=WzfzhH2wX{9^V}jm_@bY&q=d7gHUTw6)MNN%%GuYQ)$OxwNeI`fi+dif=N%~wrfWKLVi z`K@$>)>m(S@k0LIt@M=U3-wi6J367IFji>_t%fV3dfZ04c63td%`ac5kH3x}iEXUv zxWpQV3&LK(y|v9{(#x^qxQ%wANP68E+H6{1{?Ki7NUy$nb&_qog5LyfI&FSgU)^~d zImG<0;<I2qmoW|0xb+ulJhD(|bm%qnPevIYPFq05RjM@7cV*YGU2 z56zMNDj(wJxoOA4A4|JxOqIUsmgk)JUcr0S_{AC|F(2}0cY`QvT(7u;kG{NmV|7P8 zA|-dyueGGUy3fBkReyQ_=HUEP+%UEK)d9=*>OyPZuP zV%<$$7SDNtUTukwuMXy*LCNWS-4pa2IsTuZUt%{q zjvrV^`$W1uMITnv**!SXp~9dRenG0U_58qAny1*2w5MrTq<)?c6m&)oqweVeNpW4N zMg$$ElqlZAhJUM|!!y~1UYdTMyBc=~TocLJMmJ#7U&^y8DBw<0`M2BYnK*11_FMXA zIPIRH*(w{)2R?(HHB#j)fk4A9;RBb@e7@!xdcMlO=HEU;7b9)Ov-E9zROVF3U%VDZ z{O{a>W@p{`)*Upbhz<4jh*OoI*7_#n*|9{`!~ij(%=f#~tS@1dot$mN6g(jtXKe!Q1{ z=*OAa^mplB8YhJuq_9gfJL#HW9>k+rIYabGLL$LLF!Ig&&=-#Qub?OOY^|FT!4m(? zAZJq%h*9JC=EI}L&fY^(V`uNtM2(xMaT7KEpI||osBs-N_NTf;@=D3FVtW=Rk~o4l z&g#_jj}DbYv`ZzgJn1~^0@@PLsWuDfPc8D2$Fk<|bqidUbpicE0W-RPA$?Cxw>Q>j zR_zTgvnnF=XEYn>c*kq#1$n{)ATf_ktH-OR;|yq%fbp3VNDEiGf)y+*MfUOSOXzMNc|+mZ6|}qLY{AF3;rp(o zvkE1rD4AKwJd&MmPSWhjbNERsXoSW&Ngz}gT}N>*`a4jmi_&}(=I>=u1%K^2+SMn% zBmCD<+EHcy^mxkub9hRrKC!$OM|L=S*;fnpTkPZ3PU*hS3mo^|$nc%?e1(4+rZW?E z(0?-Pv6v70BSB8*Do4X;?rmZ;>upz$ez*GHvb*NkT~Al-QGC;#@@RW!dMUvAT zvzC5x7*11Rk-x5|8R~`&G}YaI$B0?{R5eD-oDH}nX7ZtH6ESNdW*}-!#H>kFSdaFe z08!zIA!hP`xNiGe2bhz@?76NtJm?${JJLjn3jJ5?UmdCW6Ep)-b16~EPCJT~9eRvS zA|%LNzpvcf-XgMcKBcg{xT65ueblE(il7}lnf(I0BG{}-Q(uE{uw zsx(sE{{)?Q42Cj}uoU2Ws0N3rU6hFO4gGGOJ6*q$!m=+REURP5F0nS&ML7>$zdC_} zvc}6Z&ywYlDB@Uo;``k^{T}`F4;I8?-RUU`EX`xR~4kEcjZ$ zf(@!W1%x4mca~P@Gs_|?2U)8P)t($FDuFg(CYu36!1Ax1&s288V#(n0ps#CWN61=A zRhG=l##(^H!;-{U3nu={OLbap(^C8@@vD{394Pj3s#AbYEAd==lb{s9(@Jx(PT`mF z8$ZXz;t}?ODNKxy{uV*V^EYhLg9Kg zQn>23tW+F=r(GOaqN=z{*in0aaCTshDw;>K<^)y)!v108$x8#PO-oD%<-!klCmh&s zEsE?}5O^NCBHbdJuL?|3Qq5o2Ct#8O|7VR?VEbbE`$j>Q9nΠeb@g5HXZ_DKCSX zYdwADKm9DwIXgk0(rL0ctprW-H?4aD8=kHJ74Xz4k;GG{++&@%7Hh0KtM3S;`9?UJ zBd`YYgue(1@GT-0Z&?PEt#jQ5T>Fl-M71*``G2*xn$%v7Hp7oZ_V2ew_y7iq^!vnG z2Swe;Up}*jG~ROKfKBq6j=k;y^1Y^GFS~v_B%3blU=88#eij%I8TxnYse%L@?^q+o z7getj<*;*gQk_PWYi!r1M&t>ND2JJ=ROvJ#CU1N_l1i0w^43e^4aNV}$=fYE;=eF( zERdMvpj;a+4)jb=Cyx#9I1l@#m8fp+j%~T=JlSJg(tDSWy)6K~`qn@LZMd&jtQ{dI zSpd;4BYWEkB=Wh95&4TjvQj-|w{CX?#%0-~UFEG9Q_FA-lho+6TSsocBd}ZVv^DvG@e*E`#rxbHsP4yFc;Wp# z_xIj8GqgTgvYR*S?#77(txvI4>cHXXt&|t83GB!eqdbkZhum^X3mf(%ZmkVum5Xz{ zdK5wVGkv|;+r$_<$4^do6-Vt$UByvywyQWQW{-C2 zAloSfTSZ~{gWgy4>1h`GyIXE)Dc<tVb9C&dV~P zgbIy3ec*m2 z%!}>`458N=!QrwC7q}{_?D8XP(b=B4adLuHRP7%vkdyA+r$gYzl<3;t8`!I| zb2yafeqk-vt#w2-$#ps(J(*qt!x+DrOsBQ|1N0Hofzr)D>nhW!@q4N(R}$0sL#b|H zpTwta3^bc!XSjXMJQd_pRK5~@B6aa*WBiJDaTAd2Q}lO@!u+=4_Fwe7B~XM02m(g# zq$~CI>?tnVpcZijc$d7*H*E||=wkncxZ?ugblFHXFp|Fs-ytyAE5}O>4E4$U4c_Ix zzzB)vU2tC@Cx^j2myDKbekDI~RsKq(f+aRZVh(@wzQBA{RD0@udwALXf%VxG+cgJ! z2s6VC*e(9?{ejM%mtmgH#<#^2ZsyP<_ES|DPW{rR`B}iNA7`5advM23B=3R1N~rTb z!nZsWn382ra+?G9i#U*)uz}&5Mf~L4Na4eQU4H(?T-uX&cq{-=$hgSn#{v`lTW$@& z9(iEq$R*Hd&*hzO3!HMo*y-HHh#5FmKf!%uP`YTz9co6(8mDF?%cEv7Ds?1kCaMmm zX6!wen%R3LHJh5&*(Er(qoNLCP;7k}|1O?~tj(kTNpvrpd%!uO_TlVjA(_Ey@4)Qr7z^wf-;U!R)U{QiyL*$7we3$#d+reF_4yTnUJ zrd{loMB25pjx>>@Ax)M@byqN4?^EzVASW{JfxtAsN`7^$bP8yi2OkTR`(1fbj3bNl z?^1D7a%7G`NpfWJp=%RI*2IxDab!P)#-IWqU;rjFFr9qLF@C;2o7XX9)><#za_ fle#8;ZAWGkzm~B1Y~t5qyU!+m?Vx>Sj9>eI@)2c^ delta 71277 zcmeFa2YgjU+CM($+nkMQ? z$EOZ&SO3OOMjWkgOm;v13%#n_r1?L2_l@rFeYE9-A-BJJ>Y=Gap8Rt5*qV(;{bA;- z8`AQg%BdY6_~c(+bC+e6?Y|s7{l4OJHm^GWSN*nKaew`)L(ZIWW^w+IL!Y?kp!O%9 zd~NBeSB$KD;l<>X`gE0!~yLNTcnpY^$Z2mR(5dNprOMDA2fXMfn|dS4jRgWKNWs(*2>tqj7_jQoVa@GlLNIykxKIt<{p?y z8clgxWz)pSz_Nmwt_tjda>j~gx+WWIFsAH6F3Z!3ZT6rF#^u^Pt%uIuYI;91pxuAp z;ZWRlmo0Ou4_)T0D_h}+ra?x*f&7b<+ldL|Mz2qFq$La%n(5m^BgYye59Q8CmxV*m zltsON1>tzFXwy|jue_Hvw-0jHnQKvL#NV49F^aX1n_e_3w5?5_89kc27HGwq&epCT zZf(@Gl}(OQp)G6b?=*M#UA@t=c8cRUGu;@gH_UZY90v2X7c^~m?$Bm8-5z~jyL|O5 z_lR)eP|f|sVd1jpZA-h5AuH5wLi2{s+8M^`QN?*7?bhbn?%HWu)8*IZHa*?xx~8u4 zO67$;wcMr!otG7!$NVO9P(kl;Wfqg=@LpO;(pkys9--Exf6zOWA=< zd5cEL#=e@X4VO#$q9zNv#@ya2YUU8n6!PYN+61jqZtaIe+Lu>qWle{dkJNg}-do&p zP0y5{)pSb5(56upW%Bv~+HZP_ZjOgC_x(fC_?1`T^m)lPK6JX;@Anptr@>w8>UWH2 zs_XVsbY<_A_4cCQ4_#E5)c&ifwz9#z2U#1g)ikBD+v+bW?~T}vrh6u;!ylF#wz|ja z?Chrat;dG=`KC;LrC64YKv1YUwy~GUxu5?w6fKF$P+o*Uz?246_poW;kR2&n41&Zv9PH3a-5iF zveOM$t8lHB1~9~VP2)xvcm0`iX((WkrwFBV@$|_ETwbPK}l+6^kJ7(E3$2?y|EV0z_ zrd;7>i`byEur0v9#{@BtZJITv$6=F{t)+^Evmw0+%B==5ygV)I1crwg(6l~zjqXjCCHb-TtIw#Nr^!FWW7iwK zbA{ohnl_Cs?(mO@>c2vuMy_n|Dwjh*j!rK;E2Tk?k7*zmY_U&K$d4uxeO$W6JiE4qtU zlv_=?XSUYm+TvwpPllP#d98KK=6`J3K5nD-WYdQ6=j5#m^3HP4V@=~Gv}kMO4F$2u z1ul53H-2WXv4;70nIj&$Ty{Dk)?u)>Ca4a2rRA$t&il)B-4#3CY zdM0UD-Z_34ey_@wFOSH3PKZ?=&u377-EWv&n2Dnn80II!VRv2b@>^83`c#ZHK5*(H zAAB}n@g}(EgO1?S^Sqo7X0dQfF@_ez2C+jeD#|Z5eX}f^9P4UsJI)m!rCd2-a;*IT z9%62v2X)Me^)rByB;EW&iTSwegC9Wv_;2M6&_}|4)YANT$m;cM#QO2#~w32Z>nPA zmJ2-7oHW7qrZlZNW>Ym1>l41}dFtf?Ml+k;$#HBUT6yRY+u@1Cgb4@Dw( zhaz#9wmSB~-*TF@xE9jFm47`jvLvpR$(}jde?nua`WB7F3se;rXfRpIA5a`FekIpI zhtb~L|0;~UDqs5+9Y%hZkG!94E+;ic^O}dZ)1bzzkWP^XJx2B~(!N2Fk=u*3JG4f5 zd$IPsc3JbR_S%R&>N1|M%Uo)=QDbtX*F#&J)nguLtHX#V)U3fzBpqgi7HNk5@;T`) zH_F_;+K}Cpm(OEu6c>K5yrrKuUTH2PeXXTh_jaf)r-Z~aGn-DXIP3?iE~ECSx-@?= zNQ3T@-l@AxjUA_*<*P2@Jg6?yVh3r{+G;N6YOyK|X?DNyKD1Krr_D2lYbR+THY6oC z9-|Ko!c@S%zV_oCk?wU+-9-_5XWO%+(WaO-A+CFPCt;L%CZ_#A< z57A`!btxAc7`JxDiZZt5G=2XlG;McAZa+gmcg^kL{h#ofyTT`)w?EXcT}nG4bnX(} zFr_&+@@074TZi7bWNxIaiNBjGhh7`0*dN*P9opVNZOLT8=j)T@ZvIO6YK;=A)t6wUf)srRvbIAYY;11@nJu~zarN@qc&q?Y&5UFNu! z=nslNUZtqFS|wvX^ID*vZi_N;>cXRfd5KU<-ZRUf8uwV z{HQdygS_nJNI&fXdH(g0GxI-O=~!!NA-BR=f7UW*_FtCC&##aCCCo0x`sx{OoS;1= zdsi7PT|Dd*VWt(Jl$bdZicB{v6Tu623@< z@<6jO*}@>Tg>u!V$Ot+5mdFuZyoMmTbPzBPHM&N*F?sJTk$W6|X^_^X(%BrDB>(Hy z$Xt!ds-=zGmYG;(n!ex;o@ez2qzHjE-{dvPjR4><#St+^ke@yESRp zSdcZK3B~5-4a*`k(EhE>hp&j#YaKkP^ic1Qii*2ba;*8~m652Xd;Obdw>L^dGICes z5M5j?tM7^&u8Uc+{;tRk9a*)C#jXreIZDOmW8}Q|BJ1Qo?~aVpyyV?fxuB|8{-%PhaUvxAHW zgHhbBMvu6E&x4WOCm)_48RLl0X8NO%erc}0zJW*$@VL@1znG)B4?@mR`jKzpu__Dbq zX`H6DpA)e3Q^CNvS*5|6FE2JQFvO_lyN@vL3w1a=@J}hqC#Y~u2lxhQS)JzYvq4GYYa_6P@1AW&O@LH zu;HN3aYGD)*vxRlniw*yFvRI3P;AXx6G8@iI^;K5MXbuGur>Ql93)lPUF~i-DXDm# z8x@Vre)BMx8*}Y$hZ8Nc-$Z&VW)HM0p5?}ABujrAa(lwOCC$3n6@?UNg57N`^F76H z;E9Cz%^?iS@_6SF*4(LTo4QhE%{$I=zw(%sz~(+HQ{D|(_Az?70sGjEBOpIzb?CXK>~-+#R@2^7Zr^b)@?-t>^4Ce0^_ z0?$n2M+HwK-E{R(+c7YG4IXSKK~G5J540P}0U4(2h2v=Gsydaa1Gie(`E1>FP>5_I ziAe+PR>aA+Mndmu+vwo7_M~jxZd61X;e3SLw%s^=)H|xCt)?*TNy4#^a4Tx){Q^xx ziBpY{9O>kZLSKnO@V})*@ken-IJhoei1<^h(Z^I6n1f??i4V-_teT0FccvBoY?5u@({c_Le0D+U*MucTV9Tee@pi$Vj zr`*~3?4YoC2@b9>@H1_k@`)FbSzynQ+ajhX>GW^08rD`^m`QowBC}7bwVh|$p)p1h z`P)JrdZ3!-Z2W3JnPS^|*su}2mVWDC4}}dD4qI%4YCbTF*+@x0jUu4jWKZKqS+-J9 zohXtl`*?jD<-)ea0s@a3u=}KZml(R7h z{E>gC-I^mmyV5C{n9PN}dZ10)|BW!Sb;uJ(W@0V!%o7I8W}=?y7Q}Ab_D;f1%x)tN zsr-!y8;5xM~rxI!8s56F!H|^5+TRxP16(C%?Uo;oX{==Ik>1;3oNEvz`3s z)lN^xMl&Szh}~K&dtc)Wj(W!{=HbU{a%0Hs0BKcsjZ@l1U^&oQ0OkR;+o40T&PakX z&_?;YYn%b$BwAK(zQ#E)Cp(I0(IbvP6D={jYDdVmOU$NJB8K*5(;edM1r9rh&b+yH0WGu_P>*Bj{_;k9sbQrqy#PT|WayfM?Aa#_8R*byE_24zbmyO z(^KL;JZHCXA|K%f%acsAq<pSHsFQ2TE<5%bk+c^YdCy}Vm~=UTmW?_AmOTB{=@N8TTd(iEu(7J^b{v-5eF(sHgxJY+5P_Dr-JxxJm=kKYw35px|v2%2H9Q?#Pf!`NP9j?zj z)lZn8jfkXeJr9lS6y2Rbn%P^y0A7oLmn(A*Ow~N4yFD5A*)^-tB_ds;3AC8^`b=Mu zYTJ^Ha8Jmob08&KVPvl{U&pdv;s#AFt%rk2QKv?E^BkvBsue0Jjdr#`wexzkJB@Ju z3pJ9xU#h;OkxnDr!$O5dIKeT*rMf#8;)pF)eU=C5|I`R!xRAW!EYqDhibtp)X;Z;h z4Fh(zG>jGG>7}*Fz6UWAXg-BPTE+~kF(Vpy%LWgI% zHmKDB%qg{)*)9rOYdhG$igLn6tKAR_E{X1NA(?rkYGzWwsK3(`5AK;dVOwzx_z&hb zcE@0qc^j?bNGqa3IdaSb+v?%@X(r{esM%Q_d970%=L1c59wuHA`>lC$gJYH$354TE z%T*h#gL+u`NS(w&bf#MivxAWyMd{gZR1al2mR z+(F!@f(kILTfoEOw?V<>wy0S=s1dnkXn+Fdl7X4&GhM5vDrt7yx5C{Y_i&#hU!CVv zq#$_B#%V{}NjOEJWm1zu_`+?9?O`Z1!kyiQoO?ox>nTiMn+n1o0aoHG&`j{dFYudU zQyiyQ!$u>tEI?5jyP>O4;l=?7;{k8=U#jF$K2^$RtuB#PM6l(u`A%`3-3vv|tupNV z<83QfGaBXV&sv@2GtXM#*c^f3h%Tc1l5%3qEI6nU!Nn33p_ed@AP(=0tVk4J3WfBt zutjqLyF6@(UnsT8YhrF|FM0R^r|1MS+r1&eQC++D0$&+S^hR;PA&F_DYztLN07RDQ zL3EOBL0w3cA8jXmdc2+X=}+v8Pp8-x@=lz8ik*=6E^vyg(y-D#GoOp%AsY{SNUflD zUX?*XXZOZPfd1)6fqnfB`}ww=rx|Hk7dMN4X7@qcuxUIwU(~9kz{?%9uKa4D(;?(d)MTecPEt$DXP21+Q&u3p zu#UF$3MVrR;q^D7Hd>gLG}O|K)I<2=XDC_8X_Z2ZL-H4XHbf$$%_IDYw;@a*F2!kT z>?YvnB?EC;CJay8Dc`NKIz#^R4~CmkBYujn6Qrq%RBCaXZ_o7iOltt#Aj&fEv-){v z0>3nVjl@UbDK&j#N+LgmCpR^PBOTb&_zCpHYe0=zR3l99B+YtYVaNZe)w(_5$bJ$` z1u#?7Q*|gpYk$}WAOZpH20~!LoVsVS+=k|-&)MJ>YH z5J5LCvVE^vtp7cT10flphHhtSA>ly z#sTjV*i(>fB5ZlU{nhpqrh8e~n2o-3kbW85xyIbtGVdqOJ>$F_6(xNow^?A$z#MB= zX6N#iju*@NPq0~FW?|+g^7HM?3Sj!8S^p_Ei^^NBv+AQ5giu!?dj4>^9I@D{veSJ% zlSEoV4w_*ef(9FOlG8c&cqML2t16w7x2?5pxoxpkp|j)VBQwlWEh@Ku?38M8xqXJ& zy%({65-pJ^7g54aGikcF*37i+a5codXL~fWhjj?Vypx@RA>Ln9+8GFlj0aUeP|&L zu%7Fb88w5S5G8uPi27m)tWQdbFx7B=4e@sgS56tIcz%X&h^U|Ta*D6qla$vqDzwQM zEm_iX;S{GJvWeo!iJOdKNJx@?!W@e=gtek7+KNRAZPnE3%sc{RpYtHokLc%_Poge! zV2=*){GwV{ifE=U`X5=e!oL=Njf=QW9{?l~mXrlbqZZ~TgLG&i{UpL#u+OFZDnySc z`$q~#1Hz!hRD(eh!jlrAgeh=qnT(%jc9egc;&j%TF2}(#B#HoOcv1-xI*U`!&>xL) zrn4MsWNKXR?Uei4FV==z`_s@qZ?l0h-A^8VzFATB8^tae_z-lJ>Mb5hxl>W@T|-Zv z<_ved2eZNDEz=wO6ArI%#I;(;pKAUbmt;S=DG{bf{2B>C1uq`<^X+tiQM#t(NS+Lk>l=)cRB=3 zMC+K^JuU7`Gi z5WWoQ1=~J6va20F@NXWs#n82|^%ytg#}}JrWv!8^QR;s7mA@Mad9_sSA{DElCO71|)VK`{?Bhc7$bZ#cw?>QF7VwNhCEyNwP?SnxJaI(sC!fDP>y)`0dpXQ(ezl0+F zmN6(VoBSN&V@h5we9P!_IJQ4_$`hzlxX2W$zk2dL{i_xb2rHAEiMql!~R9h83+b)btF0x$RxZ&{ix? zC^J>~YTL5HSe}mB8O)!>p*_2prvjcyV4ku@VWfg4h;|odnke+p45&X(j>a&Ddjgd7 ziwtNQ)EWbdf+s*Tt~k?7!;nBG8BhxeST(TsLIBV-Xc{!r4gN%7$I*zHh6GK3W(L5Y z?9}2UU-Ee*QSa#)xFtv!CE*8}0L_%ht?wBnDT~rN68@mpIQaL0KWGLt4NAIv1~ftX z{&@IT!XGq&6|pq|cF+W91~d(76(Ky?Q8{1bsYY8*L^!xxli?1U0JVw{eljMF1PmEC zq(Q9{;em(=&;(Y_2}HC&GoTrYK>h`=lRv2S6T|~efYNd-0oF)(WsXHGu|U{l&H&t> z49v7jXbjA0m|GW&3<8lpx=@)d)I1rO6EHUhW?ELXX2bME_(ef@dGFayr@Zt)u&U0? zMx8@yu`tBj2S)M0>|q+eUCry(My?Lqz7XoLjZ|73w(*t9U*^tmJbTUnRiQ>%ce~Xm zFVPG2>;Y*NaNMlTsZl%YHBgvGq8=7fv?juRtBNuX?&IK|O?5i@>P>9+bZg|1 zieYup>0p8_R#oIS(CNe0>2HE|v#TPNa_YHGsm>6%)Jcz>0f>dc~3*%an>hfLk_=+7OJwp$JnX7@vd`8K{O>yAUt zw@#wB9LC%@@~8Z^e07e4y!zLh zE#U+u@?Zp^e^Nf8fSl z_-3l-v&`s)FCTl*myd9VCgQgP+ibc$o?%80oTc{&zMDcR<;njrk_VB1Z^X}E99Cc! z)3Kuyqvqxz9B}xDAYVUgl>I}YB6HY#&014zTbos8J0x?gWdWx^U9aO--R0m!B;vWbq;0-F%EU3Vn{{uk< z=hZo2eecTj-`%t0$a1)MMl z1SSCXfItNtlt2aE8}LUo4hjXs@Lq>MXxm-FBMcM;J8-*$3a}^Tg9-$I3Ir-(MB9Q2 z7`DqB0}z27Lz#hCfL`f?44|I*0x3!E`wvtgo>$F>CiFoCbXeJl<|KO>zbvSLJ&U3M zR3M%~y}t*jfM5LGK?R}(dFG;>K%sW;6R3bcj`DwZPyxq&|9%7&@G-&gdN2SLwExr? zq~EW}BR(}g(U)s-#6OLb^qckoD)5?Ae*jca^e>~2zCde!?Li!wIM`hwHfJeKp718wpAP znxr)*K@h$PQoyj`{X-xH1QGZykb=#1-w{$!HhbS71ydI98>B!Sq$I7lPeBUAL8{ZS z1l|==zyL?e3OE0d@jx{3ULXa0qdL=bAe9nyKv=CH1s+D#_ktAgekfHNNCEGQery9N zVDNAK9*_cpDzpZW0QNcYT?dwYcxc%{g!4Wz&;LB+le zQoycOiSG?kAb?ZY7f1nX|HB{!9(HkXd}YvX&bL4cSO5hejdE|00v<(YAUW$BAO#$A z0>d92Mf*s_d(?5XFm^x+PBpta*DFMU2wfsio@ZYA1PHhnd;uE!#pZ*3!0ZZ?SDBxErySFtsDr$o$5CA(8q9BV@NGL>s z`!lMX2b4e-Q6Mmh(RxC>uU3fGZioVJ;ocDi9B>7~iMCY~c0&}1H`S5Aw;&1xPyux6 zzaGuL9-57JnHtEuBMSIM%AJm+81y|t6o?yCm+cKv;LTTQv)vE{z`A`iqCi}zB+~9u zhMlbnK^r$V3i3k{1*CuZJl6qx16ZtQ5e44UIFbFgBMQVLs)sT_6nMY;21LQo_PM-jLWAo`TW~C#1t1Whz`GNz1V8)&zi$T=@P}2&_YYYQkCkm8;89Z}$&qvWXfF6If0>sIWGWDx~oyW$x3F9;KeJa)DcmxL%_SNBX-9dcwg;$lFBYnZPwZkGIXH#e+qBF2$e$00;Cpy3v&s~|FiH0eD1Dz z1Me!r8&u;Q{@D|q9v$`yBWMPUpg}7j9iJG11!w)@NB!ral}X8YQ*D|u(A|&v=kCg&KOXh}pFip^?@H(T#Kv@*lRfL_*m&RLS^pvS z1KH4Y)L-h}r>tK)=|9fCV@E(7^dFGBLRkgYE_BZC$=_XI_HcM@aLnJAj`=(3=lpLz z#&DLeI)giy;$+d4A2mE-( z|Kk}yj@>##*&6Ttc*gGo2P`bnzT+AHYPD+G>lyz8%Kv}$8UM+2#$P1)odD`4<-O+u z8j-{~J1vBhP`hnbXV|jtPOH=s7vUCOXp?fmli_ZfBOlmmbONb5&pGbj3lVtZM~J|W z5P|qR$O!Y;m@S+r7H}oh4fcCGa`!)A)DXKJcu8+XpVn!UWFH`<2dBFadGU z{)7qeKmBl+fN1>&n1I)!U;^Tv-C+W}r^=d@d^=3Q>!e@;d{J=w0KdI0PT-ybZY!XG zhp$BlD8Q}Y`T>5ofBnF)6vuZRbh7BNJwpY&x#}#_0}O!HfobfzvL}KKa2(6*_;e26 z#EQ>@Z(`5iXQ;qreE#$G`v>SVMB3xdLIr65I(t}^rVlN@$NdARjrM>6psMbU6`=3! zvd3wJ72w#^vT?}oy@T+e9JCQM0aOh>@B7N=;0icVU#(oP?+z4704NFB&!)94Eufo0pATP z!1sa`@PH8@tN{O>SONAuumT*XnS>SaeviJ`N2~z*epmsvf3X5AzzXm-Sb>2d?>-+a zur0(DTHvQ4z9+bV*aa@oJH&w(z$FAREy@GHfOmxt80ZjU3NdhGh3stYEN$8qG{6UaUFOm~1Uvu@c)wDh0lqiT0DZcZm2&=9!Uv#<_W~MVdjSm) zBqu9}ztcSg1PW*i8eqGD20Ylm4`{%@zaRh&hyXOe_6KNy?*z-*WGaXybnMDZ#STT2!I02+yyAGB)EDYoCONp)&?kWn*s_f3xEQ3y8s1l*m;oD z7AU~}x(`5sYjy()01U7J0*QaL2cQ7300a~e!IcKP0tEm#+yNB0Ft~c)gJ8_!@9V;{4GEMwq#eJ0KZ%fUU7r!N;<3euO4U%6o9tpUp;W6 z+PP~B6yRsKxq4v1o`C}1w*dthG9xLpJ5YcwXCuk-gMk9$RWt7mD8O+e+r9z?+Q$a% z`Q`z3%(vV;@Tlq_!U^z4z5yqIn+NtcP+*vA?&Hk^cqRuRfjt5R_+4lv`2D{D3KaS` z59|&Uke9^F1L7jU2GDh?J1!f5`9FXS;0qKsz?=Uc#Rhl{3LC&df9PccxMZ*`Hh`se z!v>&rgUbev(WJ~V2jTp>HOK6fVjcG#8^G{=JgpQ3mQA~31NfIpu6Um+Yyh93hAUwM z#DqXXmSGK5uv4V}kH7{9JHQ5b)AkEC;02?&OL|X-|3K{DN$yg6(Kv2c7B@hcf$aSQ z{Cw3;`-}(pSsFNoL^=P)`v?5REf%=n|K5Q?FBx?2fc7D-K53@UK4J zwh7Zvjn6IV{sEX1I6b6`JLo0@|4s$i8}ZdJJ|+y?xKm)qeFeCmAc63W6d&%p-BZxr z2k6uGE&&H<;k`%TfLyrHD*f?#0(@OX+ahcquP0#7?g^r>&({-dqFV}Ld%m7PEcss7 z6L8#TM3{wdxSoLSN}_R<9Yi}Y3ziZ{KVDCOw)ydTg8$t01RMVD^ss9bY=QMww-b2h z{x8NYh^}g+eK*{K*IC74ZEy<=u!23_PM|Yuzu*>_t1{giZb9cC|9CmUkCzhwu<+yM z1pX}tKj?A-@BVKFE_kby|KguSANn`lO)y>_{}-cuhgN8t{yjVSRgMkdWGxhi#=$%~ zTQ>g1IAkyP7xW^;+dkc2AiHig=u_{#z!J{eYK+(kM0k3uah$_~y9)S3bytB`>)%y? z2kG!uX!{}Ga5I57dgsjqZEqtGf7|Ugg47xRw%Z7hSKHeN_Uq$(vCtTc=Fm%X^M=yE8%|0sfdw0KFm2hsGYAlL$)4eIOd&Vsf zi^~|j#L!Mo$+*1S3pSaRwuGwtS`%mdQnh8kE|Kdp?)y3)EmyU=C2=+y&sx=Qj(T6F zTv07wX?0iW?6&6F>)lthX%3zZawc?jYD%U$&f^FaQ;C@6j-4p;%$99+VH32b4zIW3 z>dFQ@PtJ4kB>6ja{!`@w??7aqD)-_u-KQ_AH)`q;hAv!dhu&9#vl*Zoc;q?(=%C*@9=5 zaD{VA9uKn?+mhlXw|%>e#!VAX((mxe1U_N%k@wfeuG863%_sfQJwnqSk$1oBo@_s) z8h|~}{Mp#pNm`thnEq=fCT=6)UE~#iatGvmncdlUuBHl8=mw zmF8iKzp)FN@>Z3S*G_I77wfNk@5++#vF=6Q8+eY_!<)(;1R}kuJXknho}4^BHdyDI z)$ORWKgilw-R^pAshm6^RvV@sk!8KLA==;NrU|iej`wl!;4fIAw|1QU zeqjAj#`|bJ>~{j|dvenz_Z3~NmJh$?9;dz3{Mn=!9#LT}vgCEQPw4S0TsgL{c39^F zRc%|aDU^LtS@aEBK(2k=-O^iJsUBVSa7;k`?gs^LP|0{o1vSM|$Gca?`)jxyC?z)> z6B~)^;^?V*Jklj+ZE>gR;^XE`Tijz&gyUq%@v(Z{J5xUVmV2=-ejz)a5bFqF^O0}6 zXWHx>^~}3_7t@jJVkv~ zZ@;i!@D#Q9SIYgMmW9`x7^^h3vGh8uylh%*SYfs4)>LAEpv%%YrxUn@N7OX0pBB4E z)4Ixww^1$D$yc_yt3uw#S2U#t02xr|KNMT8<;v|pi*?fT{73JbZ~CkIvvy6f(Ve>U zlT>xGud45O<34z0pxKk?tVKUQ_!*WS1fo|^ZL_TRX_85{S+QxjF_nrgr_!`y$x zoKNuIxIa?)c;nO?_eUtJ80)`rpM8*ew>R$D5qo&!eoPRv#((2}q_XYu#(kA?qbJ(G z_QpLA{OEDm5%LwA#>v|mnBn^lBo-Q}Fi`}hz-R11U zSZ|$mYhF_rtJU$gSMHiQFAVy#tdGm*9Rmiq z0J0xXtn&_dV!eNfx5C)#8|!SjyrOfgJkIk~RC*p=uo=c>vb}FWhlmgDcP4KD92s3R(>A z*{9a|_DIud#|;U2pGBH(J+6a1uq1}(0B@4BN@5#yZ+>%aY3vg%Nf*B@7Q{`;VZtMUB$V?i8*B_Wx8eq9s=AL2}JUez^rfua3cmiLVH$iBQy zw`XUn)R&X&isqAg#+oBqfh_7DyG1_UKlYan&nQ{@^oXgBhdXI0Y5#_QOgaN%2WwAC zePFDA?)~1~QC7ynuD3KgzHX@_`M_Aeu8;4G%jPOG-N-4R3-IZXs2iK-4U9b&J`y7E znL+s05=zjv^MyHR0<+I6b8N0Hb2OkB#Th|dOrvZ;SBH&I;k{dwJEvPcv*yE^Zy6Gs zrub`U3~Jsj7uZKF85#>N#QHaDdAJq4jh44Vn+vo%svxE>=3Szc9!x^ts^y6lKTyky zy}fT*p7{9x2U;GF=@1S7OvDT9|rcnkgC_+=I;e|`RXS3PdfWGsd~ri{AJShqMGaiMKA0r8wSwxrfZ*&ns=P09Zy=`mD<@#$-^p&lsujPLXLae zJ;M>_2G8=HCGS2V*1aP??CWYCKkEvYpDy1&AvQppv_sG9&~x3cYMvLUeX-ruJh^ak ztaQ!0E|k1lrR06&4lCqeSMu1H=Jg-BQ1VK5Rr2^pO34!isiutsy6QYfZvVvXr04vo zD(*a7}qx-7l`7h9SS-y8APb}TD zl6P!T0YkL5S{_@L)$-IE^h@?d%WK+jY_Wd*epK@KjY`Sm^ZpG=9u|bYX2z!d-&67y z#-ZeS1D_bOWMMq`o~bmx-?#FX(5f?`)ofg)@IhlUuHfpK!Q%5O^w=g)?2(j2+IBHmx-%6QKhZa#LS_>@TK zcy~jNmhl4|4|np;tz2u0d|5B!BL@R(L3y8pP#(+!X^DTO=5_@{gDnqq)a43vVuelP z2t3Rky*@tMph7w`ynCvIIC@1(!PWc0T93u|tV4hiMY8TZGFwSJTEXapYnY{Vm)jyJ>Kx=~%pSRY*4`~fa) zrfS@WCSv*0IXqq>KRhAq%9Rhs+f8F}=JrRg-h+Gl`uAPwoQ+Ut;*Q{cnlQHZUE$md z`#p8#zI|1{<<4JV-+J~6X9oNz)va5~qW2;!g&%+)vzglu>Gku}t<3E2vj6HhcDbOG zO%9hxu_1hw&i{c6Ov0VCR(a9_{n+M#YvRuwiHm@TMlcX;ng3p1kt|&pkH~2oBb_Dh z5P94^s(bjW(*_Nmdh*nZFOYff_4#o!Gos`9(FJ}6gJHa zl?^@m^oz=BFPc$Sc5vCCp~D9sG<@)ZWrGI}8cM~cKNWtkve5sw8{kWha{7ht%8nY` z6XfzKj|S7ByVIw{3`8JlQzIC1sVCy{VY-oQoghRsuce(}r$1`U#VZ#sop z3l8TxNd9i#<2i@jn*8-?GtWA?ZKx*xZf@I<`$<@qwK*+Z@?0dZPqP|Pz`WX6wIbV=Xb z_D0CGEoRF1&noVW_m6GwBS*St7Y|J-clh0`0-Mj2IV^Z!v_=tmGHq))q zv8BrZBgWC8`N@@0fqO4tH%#W44REiaN2S(*G<3>veg~pBk95*#m>v(t`(qt)Nv~)(`PB?5u z>8NG|kj_L<)AMm4ikDW1*5E*t3PK{a28olo2CdP6j7{t$M|!$e4Kg?BybxwO~y0TU*GsSZWt zkE>GC?dKWzTlgiAFl7ey2iS5nGbR@cPh(Kw`~tv@UQx07xCl#WEqBsu@$^{zGA9Av zp?p$FDiQ7^ZKOm{1A4tLibP#1U7Nz$7LJ&w38!Y7Yg3$>Y0T!>8m4%Dji-7!En0QB zhSCen4S}ES&^;m5b_TGnM1HMp_jL^uZl*T{{hv=mftnKzYnMh_zymNFiEgmdnRHJC zZc`A-EVK4!j``G-sOKuCWz)Qz^vH9fnL0geRWFZP^{bo)Osxrhl~Y6X%6lD?z7E64 z$Sgz{bgSP&`6+H^9=it-jWDxtX>T1EOh3gjC*I+|Lc+k9>1%FxGGk7SX0%Y)dg5o% zOdjZt1Q5S*CHx{`hA~a?6ZK1-boF#(xI(3Y!dcbRRN>mj3oVOgQplK?iXxg~nHmlL z2tZ$=RWj#s-A2nK-{6r1D4varCaR`I?S8IN^Bf+?Ll?9*3A^UGDR!$A*n!8ZbH1Ol z+XGx9iFme$N6f?H3=@1{PMTtylg_X$jEa=S(njV=VVeV}qvuF;k! zyG9$%TIMv|i-Le@yd!W3f*;2ZvV(bR@j%%+FUQWUGZN)2Dpsc41P%fvUy<8Qp1UHq z{cz%G6QacgSilUqMnebCjugtwERu5?fFkTR=T+ZO-mLj7*2zOb#i5 zFIT9o#K9PU-4VX4m(zgsEy&3V$|W;awef*I+nTa6aTY7(0bs66|55EuUZbY*UVnFcvMF;^3q>D-<}@1`;| zP+D2{fST~9`Pj0PM&;Vgl}%~7oJaR@1l^>DL* z)gboLkg@xVfufm$u-Tmo>9xP2~-NKcaRuB$$+4%KW1?5hf0>W?XC5*-<_Q&g*%Wx@nJz|Kq+)LLMeX^x3! z61(Si?9qZzkU%Tc=-f0>iDW(V%@nTXTs+K$7J;9tN+xC`j*hZSbm2{1j4mn6ETq2iqm|S! zfq1Ivi^kUKA`PJC+N9AE*v)>huY*6R?@#u};2+q{{;)p-e^B3_?9akKu$u#5e-8ej zzCUPt^LYda986qC>s_ljRX($+xLs-;c)p%^-9M9LEJ?HKatMs&Ya>di?X;7C^E#>6 zJHkVFX2f#Gs#@+({kBU2&@*$;9^+x&2y-@UmW~HA*6`)g`O{g-j(f|TaRuOF{H}eT zhvqlM?QvU}J`VtcoZPO?(_cMmT)TyZ$W95+i(&~ZWJ!1=Hr^LCsZS3=eTVGK$Ye_m z6PefG*MMIOer61I{8~t%f=X$kfaxL7)F`3Mrz)Xr3E}CBvDuIY4VX$O!5DrUw{d5~ zLhd|0kvmkwIDT~ZdJObwI)=b(eJ$wI2uJ=KU?xd14s^qLh*!m(`7nEsdgDQH>&Hx& z5_x(M_s1bjoX+W`}k2~{7BD<(FOfz zq49r(8_eS?IHZi{?sVsR3*<2At2F1;gqAs}9Cv|9(>uwo@y-JOsdO^WgS&^<(PA;s zf0-`%jYt3IpefOR;cNoq+r*#WCjJJB|AFZqN%8+~y5u(>@rft0g}2Rk%4jJlv2!5d zYEVFEwBa4%GO{;COdPTcTb0YxHN?HwA9 zU)mZ_U$w)mQv-kBjDj@4Y(fxaGeMu5^AA8_4-&?;&olkV5HmMkAi^69c;xBlMd-*1 zWiL`L}F{fsfjnisV5N_S;emLSca~;C7naC_#!b+47N-inPJ4(oJb7FNtfnbmqk_ys|jC(vRU6oSH36HWQ0@DreB;$2XP zP@8VR+kP=1YyDb|qHaI|{6s@RH=wD%LpSi^psS&M_?1jiUt@U}!$W@F>nT?yR_^z` z->2wjzfaNcJNi^-s!y@Tp*|H@`t4{j=ml&G(m{G0H$m^{qA;}#(xSp6EmKDqp}SLl z(@=kBn+A#dO#@G#f#63i;{ohT-Lp$(U?4M5sS3Le86Yf4KuUN=w^b7_AT7TOH1Gx( z6$S8o9$+aj5o%5)y&4(~UM8l@e3ANC&_sRjrUI#x)=N+W8 z8|QP3f{mCPEDX6c*1T4^i0mAu!_+v1eBLomH(Ve>nXcS!xqycfC=6Z+57Fu!YYW|c z!}A5oxDc0*_RbxaBAm2&P1hZ}BX-$RgXd8bU}3xN4kuYW-)N`?J#L=SvhH>#x%gVc z90~fuT%+c(+nm;;<{AwnL7$&vv^=)bNluz$n4>_Sn{CuQzQVC5&NdoGfj--4v^<&IQfYVmpzN30V~u*O3f7GfMm5~)@mq(V4&|!Ub`1^N{2}??^4w1CPsM`e zcDpWeJLo_Hem!AZK3IE7zucjztlZVHb)#FZp(8_mR6u8XhR$K${;07o1#@*9_bL|! zK-feZ|Iy@M=f|%OXx6?i2%C*luhkjVVXu=PI9rGgqsAI16y@6;#C?vqOOETGTZ|8X z=B>=_k;1g_9`ugWXHT%t#LWAFx6iB|&hYgf#wev-+@U*BQF+ zeQCt1=u3qxyyWiO!ea3==S6Ji6d}JQg*;4>@5Kmku>3TnT_h*oo!e;?E12oNfC2sj za%EUG7EuHgoH8rMu4Qq%xKRj=a51#NV?bX3T|9h&SvVYVK#u{H3y_=kmh3+yx9IpH zXzWWOb&+F1iwegXOAvtU98&*9m|sM~OHBBIQdkN{VaRVWM%`i*ghU}VMWJ?zb1W44 zV~T{iua@p#~|N5C|qZp$05&L4!`>mxj=!oLWH}=!X>=*;`dHdju|9%ck#=q#g6xczjL!P^{VtZB^M91Sv_wTdBwZ%>32Faf^MxyO=XP84t{pz`%)w_;H49`} zeqqG7qNc@?$F;}v-hAb&ZB*0K2Oo6c$vZ+)W$m3#Re#bu?$dGAx11{Blsh<88l;us zUJjpqf`6PVyS6@QRAD8#x9;O2dva@T?iyv$r! zSYE|S1Fl4$Gsam6pFpV`lwBO4F4WC(;|@AFxM)|dO&1oY^oNAO88_=bo*%8sWnqC` zL=QiPokW(04J`U$I12ncT^J0b$}{l894(+Xd63Gy9R51O^Rb3jjbAR;s{{*IA#4?^ zi`0Rt>`_4MO9(--Nf_F85jRk9w;C4xS$z5>Cl(cUinI4<2H;Gq4jI}Da#m5{iCs>t zGibd@Gi?YV#g~s7blMeOZ(9JsZf`8?UHMqN&M;sXf2Nk<$P2|q5d~BTDlP-%vZ}bS zQ=xcE%`suj&EdRUI}8vAZ@zqXVF#^adDJ`#TO)bQHh!Blu31}V|9&dd4L-w>OXn0G zs61c+z9DH;moZ(Rhyygd%dSlrX;ghIB2~c# zpLP`N9{ zCxF_9?>4Z#avL~lr(14G5bpRkZn?G&=}X;R1yp_=QA!iPYBtr@@FCt>l!V;s%3Oq< z=CF0PRrT?e;i_DoimbyES5&<^zaT735$h09$Jc#23RN$7q<)|m)=@C+LS|6~7&1Yk z1|KN=Jx-5!3Dx!t=yy~R>^@KvFl4SF9r_ZGJ)JbzW^5>8-qX%y{+EHw8wba1;Go@T z^UU8#HE>U4WaWnmYczbQ*A3x^%# zVSk=NSXdJJ6kBVw8)Q9W8w{h6w(VFw&R)tLyAi{~`lK$L$&(LO7WPiH(s02U3}24@ zdhi<^iDe#z9zIQ|BNo`{ePdcd@V}>g5J(b3hxQBkV8p|5Oe2{=TLYTO6J`RcU4o9( zND@4VgC*$PnJejd4H982&I>+HxqLd-&3=KAcpBq1U!aZkwK-OOuAQMVh(cQy5`PFc zW8edl41MSI7aS(QEn^DPdUbps;j8 znz2%d$d^006dC&;RuT3yEMd+=VQAlrVULkMKIFJ6fFfGeXjSZ?@cWeA{}dGQ=@fwS z)XGMnuW%A_@6PaP3jZr*&(J;$GPbaT#BdLumZDnWvnua3tQcu05FP@T;Q6(MJKv<- z(-eV93~E6J+f*pnZEVw8QDgvf64Xze-{D}S`YpN$bCy`C(o2WAnf%I(Eo#TYX~b`J zgn33{5!YwqbS@ocCV9Z@(=#H*Qvs=>*V=83n%xdXX7Y-0&Bq}g-2WqnnR|b+V)b)Z#?$smB0L~ zXCc0TOUwSf3X2@k7{tZxE4>O!hIu#Qv%cqSgZMA=*iy#}o(7^cMSaky*nS-k89N)7 z{8Fz!b0v>@^0r=ur6*We-6il#>DIJn zdb+yDl4hhHX#|$_euA-Oo(9_`*}%+5*2BiZHef6nKY1Q=_a4H@@w9AMk0h`$T)S>| z&u(NMHpgVMY}lY|c9%4U4I|0H;6OHkguOhD%_BI3JT?%(_xrnhWcdMxjk7n&mChMe zcRl|4tLm@6s{Z<_TBn^Zl54C!Tj6GChxdLf5SPBeK*4>TMp-HofdJqTavClXr@EuM z&*XdE=O&LS5~}-Cp$zKOzQOg=FsbCD2^HV>$Vt$?$Do@v)lVE@E)!ZrTj=L!!b8K95O6VxG`7*wwm_ht*F8 zA80&iN}`wJi2^;7VJD0@oYK`|7h;|;C{2QXML5eCfgf5k9l?IDh6mB@TPIwqwaI1BAp#Z7=6h)nPt#Tye4p3MSP|Kl83?Kaq8K# z&1e!gMvu{a9_cca4tZ)~rJg1?n>Uu2*}TJHC44)KrHArVRx%c)b%XethWrys#3 zI&m^MLUU*GK+DtS>|C!>kzOl7{9ME%7j!a|zQ_uupF{)oLh@+L!`h1s(^PIplo6L) z3#QFV#(`zX(sbzIaMCu2aLz~(NG?rB!CKZ2H$%@D->3#@ z_!+_YmC)s?CbMaF2F>8q5;endCDYJs9D79+P9;r40dQ#9?0b8@{9%*XqmBj#RSZS5 zXP8MmKT6MAoafM>I-DM}URVahHD*#yA_3{n5~)URZ@(e6D#*>VHSUfC*-C zh?E#5d7$}FF&JNrSw5|d5&|`Qh8668f2+SAh!DC=GO4iONK-K%K)g1{&RyuN18|MU zY-Iq?jvHCVlZrqkzy=DsefUv2gIP$sQEyem9Fm9N@WxyCFa&pa<8p3b3Q1KyirO2+ z*fG3Oa063Hrx~7x3%MG_Zy4)V<0-k|JacvzYxYzh39fI2P6g5|;9!tp8tbVHei~in z0F{_6WQM`d2ch;>ghpAFZeXsamA!7X%8$=8&q}?uAr!=tW*G2=Bq%skF&#HHGM*{J zyMkO${5W#Spvs)8!*nu3xtBw+n=V#`!F1~6it0&Q(0Axo!{9XGyI=2f^q@Q866jte zXyQ9Amq0AJCmC(HL?Cd#&p%88LqjQ;iaY)LL7irG*zEBR7QR?6S%0gkwQeze-&u~YOrhxo0 z*@>VKaVi{o3FX6E@}adqaF3H++5)}yTlvaG&~|jmyN*PfNZ=|Hn`?rrX;hh>*d|Wedx=`)7X5e5f zt7bI{N3(nhHOMfT4yU0h;ioAre)5l@>c=;Yz?_zvMngOu@fOaagcdxZW^G)jOaW=M zTN*uqBObECM;(FvpY@rBN{-s%06bHB+-4%t?sxqXPS*E z0ppEPHmGu}B>8eI`07(?!Y+5ty;7_28oc9B2xouq=q`>%(eJU;5ZG`lY*3F2JTJ$H z0KGFGn54Ta3mr6LE;<@*MG_sOtXgNtYu`qJK5|=V0QGPepeJ9u*t}>ShLhlY;2^Y( z%->eI#Rz$r2TJIO9m-9U*MY|@p3O7^1~kk@_Ccpnd|7viDda7em}TKDkknjs2Lc$- z%&%SUyu>Uxn^V!+d^xP$%pKTUQ?4ePcpEJU{5 z(aE>nv7AS~$<@fC`27RK!&@7~<>Wc${^{0kw|H6aHq?oMn%=ip%bzxzwX(3qToc+)!iK;7D8GET#k{ZqL!cw3 zG?|`{HlGBMm?R*k%PlpGW=kIs#^}?wZoe-Z=9)`6VZ{iHnUG(dYc{%#K1IGU*DTBp zUjz;A)sWR8OXitVQ&yYX>0*{EoB=3fn#nFgc6lh?iwm1`I4FQ%XE_}LeDWw#&FsoW@YwTjjWE?Ur>laE5@dxg#q zFn=1dPa{`+uP|i#GV{z7LzWtnVJ75|%aUc&J+e?X9@(Q*QDvQfvBjW^ggOJwikRxf zg)*hMkqVy@!F*&axAnr%QFS`(YXX>mCqJynQ6y}idgT}eTX~4odL1(iD4-C!>OKst zbVy(nD~t}md&y512Fz{v4WK9k-(t!rG8|cN>(n;;Uf-%yJGCJlE%n_&nbv41peNpL z-2rKYD$4WME%!4X4{gPZV>7t5IY*jSU^`U*e*8KD-Mj!BB84$|;BuJUwnCldiJkh3 zIlYJjXc>M5m}y;s#(n`Z{bH3*A(+AfbnlKBGy#6k<#coU1k8Z~pF+Zz&1XMobv)Va zfV4V5V=I39$(;fhzb_%*?fC7-kN7Aowkm`F>paK;{$5<S6wVv{nf8^o7hI zg%$ygyPg&~`U65qzz8!Rs^j~W%|<(q!_z0q!CZc9PwQWbYdC(K%*$G@cR;Cm~!S7lMYdf9Kw}6N0sw-YxV1 zY677`_d0)e$dHrT%yUY`kKHSJY`7E>K$Wu}xqjA<z{9PjL~r{HM9eVjZtjt z8kW55OJ++dPAd&-ryfR=QJN(35#MsVGg$!AbJ5MbwUmg%e*?}pTWH?tFvZ{O#REp0 zw5m4DRTJr7!~kSg*uh2kZO89LdM?8J9a~fJO50hxX;tXPRdyaJ{+AY~ zb){Z`4@-1mdl;Dh_#GA}47Ii;p{6(Ec?+JYA<$3{_Vub&tzd~(Qy8%|=sgC-ujvqw z^>&`XNjdUM_ri*T6CpJeklAE&K)5)=o(R1ssIqm}PO4#h?y7qE;p}Kl)L|5roW`b$ z4l(b?+*+@frAy4B>akbb(Pw6G+-wLt8%zypAhUFdSy4*lVeHdCgB%|tC%?1AYz)++ z;_7kZj9FVq4JU5aN2!t;;H`A=jGQH+#lCtud#O1$jJVD0cwhPBNR_Zrk zouQYtsUs~hSXdr3Mk|DWpk)cy)evk&w}rkAx?iU_D&oM@)7tx*K3ai^M$=*^4lN6Q zhBzbdGu~?dAKk)`OUg-#mgq&@U~(7=qaPlk9-Y0;4(@|r$dmm9-tAh~U#SUcdHChv z#}TIwuq%?qVHCzOhyaF4>8m#n>WjqBjeV$uzB>6*OSEIML-IyPPY_84+%82W-4w5t zQ?D^EnC`Tp9W26fXEA;xA=xTrCL|Qq>Ndej9pfmq+c)M$&p;!M%#BW=mYW-`gp)fj zI%V3pW*JY1Xt>Sd3dmS<$ZO_BE4>!(rWWp>7d_*eaa6LLWE+FWrslgnRAF z>2z70byZNu=MnoVI=POKf(VkXibKIdX*j2voKXbtP7_qZA53N%FzSFX5v9IX4L~F* zVcK>`cn6EL2KmXgW>bX?(=UxqS|jvEV@PeU#CFM?od)Sh8#n1DD&@M%qW`lYp(E{= zZG9A#SiSiH-M|QMfS!#ljeYO8a05z<@-Zr;etEQ{z7@PA>V1ZRk;MpJrw@Q`EAkFm zgEW~?4ZsZE#xm&pa#pu_MoO&m21V3&`l(%Rlhe3?fhR$1<2ivrhuDbk-Dps;DaSS zT&GSyjfrns$1;JQ?Jz;NZ6GZ%$bO666?(oHb-TBWYsqq>75=RlIa|x%qTVTw_?=Z~ zV3aa>r{GDHFq!aSMQ*9pn|tUs5~l>H*mXV7!bw!5hPZLNR@ad!!JjF!>SuOS__xurPNnAiZq#suJF~#ZzQ6#Q)x_8XyV|ENy4=N zDj25T!;cmmtO{dL1^NrVe4MG6$!0{Wlq)#-&W|5ldp&|LRDvykB(hQSr? zyF>TM6}slp!Ti&|4@*31pV9ZNls~-?x4~4-97n**z$1_avyC=c{xq0y;(D3e-hzbz zIiA=E#O`BU<&P!Qemv`V*73Y$Q*$5}&$)QskLNr*=i!+Ox$j8oyJ{$>IY5VVCjG!x zCT-+2Lk5S?Yxv7%K&O&9;)Sq^Nx*gD_98Ay9kO6xZ|Zg8>t38>HV)`zEoRyDV_}rO zjR?%O{X`_288t335!%!oXxnQmtvQ?g^XE1P?goQxw^~j{xn4#c<1z}#cN5OYdU%DI z3e;olfa**}OO%cpx#c?Z{7D^5SP6tiW@lUoMhtOe* z!_c0A*4f+ak5|glmFD>YH+lC;v$8Oa4sS!?GjMfajrU;nCLe8$7WxL{->t-4!2Tr` z-twm_&B?XBSc}0%_>{%5F&_N>y&^F19j55uW#F4QVS=U3{9pF^@0QJN(PmpY{y!-h`*{1<-~|ugGtnC z(Ao_JCx8)s6SJd-**iMXst!J+*Pvv()`~zK=+%{2fi(c1zQfske=Ud}x?NG~K(rR_ z!L^FAi_i1d6y&P)U~E?)#HI_j2yfO8F`G=f+3Jz zw#J+?2?ebSwX1cykJlt+{~FAIk;5wFM)+9Dtrk>jF*+WK34bl7N{3J%^h{T)Pca8aIJq&h1TGCSB&|05u?NmRt419tI(iy{DTTm)BBLI8uV&m^t0bjg?5AH zA*9(&VOS}Uu+Y#>op^Nv3c_yGyQq}4V1P=x+Nv<9q%}x*5cSLOM+r!3CXA#=QxQN0Tp?u-_s*63ES=Jt(7O>(QgBX%aQv3tg%5{Q6=GTXdSV0@^FnFswM zGEszQD>vKp+2$o--u-1%G@7>t>>o@pUW-btY1ygPqMS8ir~F!Hv^<$5Knb(0v%AV| zokMV`b&e+%wYv3#-FtZrD)%7DEe@wpx$^CG=EbVFLT|j@tiZ?D+OIdK7Sb%>9n1ps zdC<`47bAN}X>>&kqgfMWuoHtdehCn3)#XcF(W&yi>rMYOuGlK?;_$?V=H4>H@WY~k zJt*FlP+NO$;fWm@2oL=?X|bAy=nCgE2s9Xy@?u+{*Dim({g<;ocYLt?nB3bb;qT=uk5YK zH3Z=G{9HOm|9{SVs=fe%_ZnaTj?#ztUFE)yA$ZRwVYFB;q@F6^NsIv2d9L3va9*5# zcj6I<4~8%Y&U=Le=e?25bOkyq;K##x*|{f&^IBOr@A=23C);t}g}^{*u*35<)oEHb zM>QY=hTOSCEdXXBgrE?-(y9SOfl%FIIZ;9(wG~?3n1q$2FQm2l?@*1YN8{#Qi1_*0 zYO$T_p@pGtVfuPGWwD?Qj-|SqZW{leTUoQmQ^^@qYYtoNLzyZ9Ln~bB-sk zM9|m@V*mupz~X`g%b3-sjsn9q>OpCZEeX|l)Z!yStO6mj1`Gl^%IG{lYCG@7w-f3} z9{d2pBS!H3Aytpa(yr)~aUH5WMe|An#+3mm8l%<@j$*yv3fI6$Vqhd8MKnNh5KdMo zswkp2ig&cD>cj8%z*8^y{Q=cSz|cwX)X$R9QH;Y=FD><5)2n_ep!(_K0M$>DYzcG$ zkT1ZR$i(n{44^t{jktErV*u5|LmT?d;t53c|9^<;ZwLRh5Y>f2>* zgIW3Cg{cO3DJwo>nCcr{KW!3BN1q2%z0Qk|slgbgdadKTdIncTGJX5gM4O!Z6;Qw=ON)eKwaX6|6BQBsG=ET$ST zd6JQ!)iy3;YXLrj-uti@4tk@px+cI6O6f0ZRoK1ZbOvZFHv!pNX+fxp8PSHchh*xN$6$fo?b+WDWfEy?-c- zHEelyx3dr6=tQh>n7sRJGj9TRO`E*`&tTVI8xOl)0weTg*5`m-&+^3XWU%XtkA+>I z_va70UVcj0H67wl2-GaLO#fJ6*GsHsPfbI?#Ko()FA-M#(*?h7OtIe=e;xI<-n}~m z9rL|~A?p<;UW$S(*E8!KD%8&XzWAd!HZ__(F~A z=i;xemrlfATmJ(G#x&Z`H%Sqm9z?PA#L4m37N$lg;IDBSPqhoYQnkc6D+tQ}xX3h9 z44)G}9RO_mBmivN@G`785rEAwO+mE*A$JR^#sVCm4BJoWAOye`7@1Eu0Nch?`wt4h zwm$~|n_&uk0sz~_+?N2@RvM)~1pwRrjSEI33_bge2f#jZ8~_`D>@NVow!K3I69DW_ z0bt+bD#kxc0QPd<8*;-OvnP=cwcm+NAp-2t#u>R0%rWf=e6|D1KM6ittab6(VwDFF zhS8dgn19UpY|Hx$>A#7i_-y8P1)L1-gwM9Q_wM1dtrPIswlm^US!v`G-p5K~E=Iea zK-x#q)c<9Sww3(+7;XFV35@mxMtcIIeGHiVzaOJ5Ox4i{$78hZDXu?h3E9khXrJ|` zh|so=LuiXnL1^RB6(F=L&i>G?YwKU!ZA>lS1!>zS18Iv-2WeY>svvFq3xKq(EJ)k> z6p;2C<3QTi{c(Y`-vCJay8kLjn=Y>T1Aw&c36S;#NP7aL{RabS+ouL;-*5sJu@BSn z(*x25o)JJ2LaA#&scY;3nYY}W+`tyOLk?ZOOr!FjIeOdvvNxOY(A(A=*Kj_8-kv~j zPoTFa(AyK}?Fsbu1bTY{y`4pG4|?eB-TpVjKL3H#`sF*`4C4#hZ|2Jj-wJ=eFKC|v zV_i0OOY$_|j(5WORd$iPU8-Q2$8cJgee_*b_<>RJK13TlyPvLP`w$P`Ct;U(km(%R^t13%MSLuuD2-hk z?(~IVTh^=_U1sc`$*EIfQ+(yJ^xg0i5v!TJ5xmR`{;4c2ixv6iNcC`d$4qgt>&>#k z&wH?g27IV-hD+H-4m9Ir&v{{Zw0|`8!^2_4r;A%Wt~2trpNE@D*m<4!Y{YWEbpzar z>-{VVcm4H#t6NTeFFZ49eHYk8fO0d~sCCZMW8N&DkQ?3$FH^*~spI{xiG<_iUU!l>8ukyH8=!q3?YdE>RTm ztD)CE3P*eq>$MGTp&k3XVAiWc8_FXsentGvP*RDE_!X;DZfS@d9>NC?KT_^1^Ig4T zf1y64e;Dcde4mg#g|vw=X*<_9Oe{nip9X#%+3}aP66{TD0DkpX5cR_zubTkBXm& z*dg*paHALeiaeYjDe~#^{Ev%w%*3_ej$RSj-~&e$E(6AZD6>*Gjy+D{T7NI0aBCE6 zrkwgo@%N&Z@QOU>jtULHHrPq2A1N+b%o1KHnxKEHJ41c5aXwOfT@P-&-Y$&0qx9~wWsBTu|1~YQ2{Z3? zkT>~bR}}#pM8&dufswV`OVc;wvLAWNufvml-Nf5nrYL0NX+RjhYEmD&vR=H*T*0I5ZCoVqjNc0GA>sV7>;H_{sRz-FmrGwT)~eVu zWqUAIs;~p{reLf@5nq=5!Pt5QDDY2$u^NTFE^8WNBj_Dr+~SGv@=%tWA@u8LxP@8T z=?pmM&gI9y3%{<2(xIpxyBAmB+j38CY?+VASEt8{6l?L&htp%v`sH)y#~$^uq23E( KDL=-#7yd8QSe+vP diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin index 24b752810f2856f26f21ff13edd52ae594ad8628..dd56ade8bfbde386a811e935b2ba7e24e9859dc6 100755 GIT binary patch delta 133360 zcmeEv2b@&Z+5Wj@?%aE4c42pcr7qhjOD~F2#Ip;+3{9HY5Lv)3irBER2TWuZtW4xa zO_X9w?5w(pe$fMdiL;srQ_7&wJ`~ zo>zQ1K>Xn3nzLVcs&eAkcW>%>-sOL+yWsRTzde%;8~Ts>sTX~D%9EjodMy3=qsnu= zF^~PTW6q1n*L{wTq0+dMJ`?1`>3zV25o%&ozw1mv2)FjbN+B< z&8TyR-e2;@jA0d5ZtXjH^{tEk@c9?_zBF{~&o4WS{j$yI)0f=z>Sz2P$DG#wkY5gx z7YthX`k9CPcJS&K>&M>u^{hTOe!T9kN3J~Q#8Xbc`K=9KSEM?B_SjL^UGTj5!K?qc zXGH(5SNwYOFKTWd<(>5KMKdos_O%n9y6CRA?_3=F<6lo(p1f!4r+2rRe8n%@6nryr zOyyK2Iq>4IZ3a zX!PZi&pxZTa?#@A!3P%)9yH?M;Uk6)FCH>z@NgFVf=FpAV~ZHO>2Gzj(}~nQH>0<< zI@BY4F^e9Qid)G%tw(ZNXi#OlB~cYg!sLtAGotR<<9R-ZVvU* z{*?SnXyB-C=DOTg?wc=N=T?nc=WZ_E;PQXfM7uCy8HbDT6Jv#2aJUS!Zr9Qo94RGT@uY<%dPO{xh})= zRhK0{a_`VqCD%k=(3aMn9-U~mAFf3|bD3HEf@5pvF}w-|IzRE0j-sSp+CwWz4k#U?_4ZDGIy5CIOV2a~swg?PtUOu#vqL?(QnQmw ze)h|9UhYbirQeHj>uyoz_WiwMec+Zjf9WG!p}~Dqu`83u{`>?>M*G~l+(85By1GYP zdpJ3v#|rPc6GM~gy7jy=TNqIG)re^CEb2U>*s~Nnv+8Z>uf>t#(v|q zj-GW&=n1`@;cY!7w7gA)2w(ZcTsPWZgeUQLBHpA^L%owz2jplc*3B7kqNYceBp)9* zTDO-Zza6-&P%gME>e$teJ#~y_eNpLQjtp;qhftou^01Fh5DT%LU%WHKD%U zZevjgr4iN2d3+T!<0cPJYsXAJH@WSIfzAm*ggIW32z7SZ@yae{lfBEq$0%!9-0p^p z*SX=vB4mrTuB=`f9UmmLLT9EUgvDkBQIGb{5}{u0XDI8FmCQ^BmD9YRBh{R#%4@uV zY#f<&8o>oF|KxGcpLsx@aC|% z&81>YYsXDFO}1GvgF9DW&O=k)5f1s2-+19|naSg0b09~L#JY5^Rc&>Od@~YW?>dQrGQ46SK0)x(g^5al6!q-{?(#ZNI7ss#A`KexRZKz{i z{)DSFUF3Mb`C({SpD;@QByy^9&s6D_i%^`Gxa2-GQS&;?+0!O#oqU}ToEcQmG3GyipkQ?%cnZ&1}NY0a#w^F zyRy4#r0i91<%-aVTzPxQPjea7$=lwx6``6Q&nc(zr83;GtgR!SRrWZFKt*X-#vJ}k za?X@zw9Ux@N1mPc%iz^P_47xP_a6DAc8|AmW$3tG?02E)Rj5$jpi-F;bcOZ{am)Vg z*)Dx3e(z<;Rnxn5mg|C)3YbYvMy^$MzBaje`YqasN07COGP-$*7;%NDalz!9ho;Tkdbp`I6Qr-Bde1SA2qP3 zeK_h!d~oD(#j`T(H_0F#FF;R}43*@{<5bjeRm@?>dG}gYVIJZ&oQrq-L0Dn#Sgc+0 zxLMt`qmmcT8rZ`Q((Da?e2_5T;M!FPGp#8ZJ~g>*R-qP2zBlX0!STRdZg9uzJUqVg zUN@ePc=R!2%8%Sr@=V`dj!T|=^dZ`qs-cosY8o4?ezXk|Tx(aS)ci!}zMPjx#uFu{AZ(`UgDi?ymNE3x}L|>X2avd3lq< zg~{%EiGJQfuiDeQC#&@h(GyQya$~a)CWAHE*BJEw>D1%-?_uik>z1Y-JwC4SKS8{c z2s_0kZo_rbk(XT@jd!9xL$El8JEkTkkNFc5_a04+oxfw=$2W#Yd;LGsJ9@8GhJK%% z>)fDS>(5uN!hGf7zE3x_Hep$AjbDywRv0}trfTv_jG68l?E=hT*1O_9)%Ef_lU31P z+G%P+Q{K{qCi&Q!&e8VWrdUTE+}3F?&UU@IkA%8fd@$0jNd9xph`FL-Nwl3Ntn2%T z@bwtd1YY;MauHs`|LV@_CBhxpt?n$0>}xQxw?k3ewHKkn@o|gnNB@vHN5S6yd>%Qf zJu}MLFGts&tDAGf5FPz^^5*ulbeZcdeLU2`N?jqG z*ox%#n+hXZi9bZy%cbMp|9I%i8mtJ~yeq zCef&cD2j1m)l;)-_el~>V@Z_6k{zMk!^?}E6#CqWa3k?0KQe2VbKRbMcO-f0Pb<5P zR$&rZDVKYaX6Xo}0;Q=OmqQ}X6pXSwXn!1`8l`>j1)_F7n{{DbA~TMA^G)k|y?Rc3-1r_c`TJE2ngl z_4KqsPEP3v=jrLiPEJ`LXX|txik9)vlZ&NpUoQ2hr?-WBXJ_krxR1$nXK;6&t)Ibt zzH%qIqd3vaD?`yb$BNd)tw}~@h}?6GWg*|aEbxfJBMQgK2%H1A90aC-li`k~$Fr+@ z#B@Pxk1K3;FIturwUcvul-GUJqukJ#H+X)iP!q}F6}@0NXMX5hP1gOk;ziB5Aai-r z0et}$kEy;~m&ah8GRt5mVtVjWXqYwy>y!bV+5O>YPG3lbm>Urv)I^^?d|kxGmlC^Q zz*OY)$Bcp9Z~Xfy=Dbuc7;S|k4}pUB4{Z}rh{A~mv$L*o?`RdxQ@1!8;*u&Fh^i2 zpR+;g9IIOj8>?cD@17Hmj-P>kGVr&{Oy?=Sz@3D+^kJQ()FsjlBaE<+MxCtD?J^rL zXdVbn7lGP2-1GzK_88MiCqR)I{Ku0&y{HbYXpEiV-_Btn@-K48?m^9q}bkWyKX%Hc35o$WX_UFN0yDV1cohEW?8KNIE!QWV*T+9sX+}}?C^0GYb#79 z?(>I7_*<+p@F&yZ6xQ*>N@mwhz3BejWU+SV#)PSvZSTMCh}8+4aMXV9CmhAQIpL7W zb)iCsZw%&E$xWeNI)CrG-c-19x91sG_NvRnX@<@>)%Cd=#~HUK|9OpnoN?_gk29{l zLtB|#bKMKtWp$^oKD@=_3`xfsmpDx)8SB@ze3J2a<|zi-5-jj0Vu5$KmRooFhOgD> z#WO9RTzs8*YQcv!o?49YPb{i**?45JAS#{>s(-&0H%&(uy>~pixEn_oD>K&yM{5g{ z?#83_bN!QxVaXf%#ddpa@k*#7r?P3*FXz3 zK0iQ{zU%?UzvBT0`!_zoVE+vV82q=v6fM>I6m8EBFldUl!wH6T_vZxTm4RK`wLV1? zNo`hnPP5Ysnx3^ql+42mo;-F|F`Zq!y2oc1uNEfXoi%mvcW`nsYKKYJ-ke6$^a z5P<%{`~TlXboSOk_SQl6)Y06z843BLJ`Z#Qi3XNtjk z6jQD8r_a+@92~Ocs4R)SLFMcCdDRa>cjj>ugwZ`?sY%PKtZ zJWZF8`t`atU)M%^R!AFgD96o7g1PWllxa(DB{cO)`OFgkRs5IA&oKo6@Z5CfiI68k z+BZ6X##?G>rJdQ+TGT;i+kg){-)*X z(S|3AedK`AVxo%=5g_S7;OJ zKlq1sj;3*M&evKJ#?=Y!X7Ac>v_U#sT0f^&d%`5YF4`p;ufO?fZL?ATzaf3p6hKYv zHE(IQY8TzVF7+zj*4lVe-@<#Ssd$IKrR60L{if`IA!%A_ptt`~TNI`_cC!|mF$wou zXl4MkP=6AhZK3}SEi_D5uQJ<4=H0Bw#Rq-jgN`fc$V3P4<#V;8bG~Tmz{KZ42gcBWolhOuVX6ZYF9pd49a&}v#)1w^{9@-0 ztX}+8yUlUu&2*d`+|inMUj4u?wCB)4`d!c=nr3(-zS2r{_G{{bzSUdmbmVS2opukO zr5!-5U`w6K!{=znpYxq|TMz$HGtV)r&hP- zXuYj2wtD$b>jRCqwW!zirpRH#2VSCvIa~$7fW>%7(Gkc$2LtNgf~Fbxvvj!6yho1K z$GL3KMbTO@*Tt=9_ZYosg6xM@=i-Vb+BXe>vPzlaL6uJU*$*PAF?1zry&Kj`f#bi{ zV);gNMO0ehv6HOvi*VUuY}67Dc*otOkHHPun{U#WdIue=AJakpS)~=mjry=W8*#6* zsO283{|=+vLEgp3>sRRV_ntmmpQ4K~-t^h}1ed>}`-!s$z1wH&Mfvg%%1+?q@K{_> zKf`8OS}ut(QoW5t5hs`d63FX z6`PH(@3UC9FnPJr8@Ev}(#4OxlQ-(~juTv=`v>739yKaHOY^_GoTDQ8jpZoiM*i}c z;5nnwh4E3twhV`V2lF_Xm=20N>-F>Wp1RIDdbtnjhu5EWfnHPWPl~HAIM>T7Hw(R@ znR?@_m@fWqh-~V+_yn33r-P_zvDfz~eb48`yOZ%jEz5YGcAb}hv_8P(w<;MQH9~B= zxJ4mncL&1#aLYn29t?#1+aKb(LIKz)n2B`usU>iyfNMWpj2eE)SWB_Q*>$6nMAuh_M`x+~9I?{4|)+phS)`{z2n z$mMsc_APC%v|7JJ*DmsIS+Ada(0_9m1}O*=j!q&ff$QG z>eyu&5iSWLT+%4UXBM%=fq25C5{4nca*=Z5=XibY(0}fVla!sEOd|Z4&MzeC-Pn$; zXVK%pykH+T$+Gi1I5yoe{^V4>lXuR~^ohNhsgmU3z-+I~@u;V8G}l_uS%#nND8t^1 zKhujlNV_Jw0#%aTml7jRAjexK3l z@IZu@DU;1m;p7+(qP*F&H|nD_;SD}l?+#*n`cTdB zM!cs_sQ=M>`rVom>U*=rPK6a;?nttuFkGwZ7 z(EHSX_>lgTroC4G(O>k%v@ELrKtJT52r7bF;Yvq@8*m?PLKX9uQxoAvjmgC=)I|QJ zj(fFZ*)?<%`eNq}`GMZ{VNVC({wG)F<*)JdVz2j)^*x8&@2iY^c{l0=VzuNiXWe{)$fo3FjXLpA?ia)E=c*d6QnK^YfHI zvqkk7oyX~h_*(NWIbJXIoSXGkJw?tAGJWIDGR;TVW7u7z7to+Zuac|OtKV|a=pja>D_lT3fF(UPR{|D|2|)4yUF!|6m19+gv^R{fh2j_@AVpu)i3+K zZs^_Qk|5|s89^^h2VM7)zN(0yrK}QWT29$QSyFL zO-1Etxy+|gwr2+s-C6Q@L`k0fh9vJ~jIDv_iKhe6yICbB>(9BHL{E+((Yx2^%mdlu zB9OglDj;S@jk2c;FBnR%_lMHO-TMdBM zzgW|UR^90!YSsNc41hQ4dD^u!01h1da9j`w$KpUZUaMT2 z2}fIh$lC+q$knv_Nj9GBhIs<9q6nCNV}@uniA#DotJZEzPf9Ni!ozF~-zYPUquIi4 zXRB}w16W!}ngoZ0rXxHTzHSCO$Z<|iTw0x@x05ECa5 zlYgoKs?$}f(WeI}%oqGL*y{Slck3?1q%s(x0wORGj8J^K3Mj`mO37i`k4Z?ndp~?v zzpw+lbY}?>57uL78UbpJStKI2w_B~7cbHpr%_Lb^vjsx~-=ZJjbzX~ez^n++tS>79 zn4|q4i-5oTmL3B9Q6jzl*0fBb{kL=wwg2`#j1osGHEv}cku`Wx?Q{#l|o z^N(8pkys7UgoSMY;YmrQ#oGqT(+PC3%suyT-7_8hlP!LpPcsz-a{`JDuF=C`M?Q`DUQJnA=AB$%jLT&`^{4|H!c)NG$a{E?6c{6PQR01hyU|zE zz3s!z&RVT^SUaP;&boMW+8Kp4i&Tyh&muDtKN(K-fE}EmWVZ)mhYSByE*e39 zJma6hKZSooH=LB9PGh;ECTw>{qyg~6pBxjpu$PE%4E7ZMM0fKBXc}U8Sp)oH^MuPD(TR_TttD8~aaMbGicz4QsdW?DW@YqO{31v+9=32{chZqZ0JvjsL8oVx! z*KO%9!nGT@8%5X%>?^&64;bCGgm={gMwgRP$Z!l4j0v0@*+ZBatD5V?8lO*f98I?p zHVTcuql2q91Uph}z~8rrb;}N077@2K;P1QHaI-BdhRoVHVz2coHyT~NPDhw+v<9!@ z2(zrl!Df$BI@gK&<^nJfhnkXIKi6?6`Kn`_xNk0TY%64~#527nv7G6YEESAiS-YC) z{z*RK`5!fZsbhzmr{_|=<6ny~y?TqDmV8}{+9V^r@e%Rt;yHm@q7RZpn((czjU1kb=qkeNg;HLWf9)-IAShCA0-bc>hska4%y={D>5 z0{K-UB*SS+aVjw~}Oom4*=cJeBb)lVNb270M7BdW!{ya{I4w#TXF*}bxd zd*Y{?oVcfz8|B(@-qL!suN?1YGTL~L)f+u4NCs+AiddXfJ5{;l!jKS+E3SNeUzXbInwZr~M2Kh|DbkM2RBAgS1bxP17 zLRcs0EKJF++Q{^+2saVoshsxZ$S~}b**N0(J=bckGjzTUuoGV;;#P&Xz%mh)LJ3U7 za|((1C5AXsZPSkgnCYwy)oLmi^MdzkqHkQd$y5@2PA{WCw+DEyKVp=Y$oil)4TNM$ zl}GV#O|%;M+#z@`W2AF`Iy27y#%2cznj&CxckI}i3 zDwc$G!g^E=#_I{)F+%0AXtX<$O|ycv3GBg`%<_~yfy!<0-l{ML>TXGpY>A)j2z;OB z$(CRWWgr^98}sL24CmC%?eKxWck`jvFmG;On}3w%&~n z%95Y}t|VmKv#fFj6CbrBfX{0zZ4KPJlFcq6N}vx zEDh;Es0HUb6(NS2hzHLJJl6)#Ha>GhIt-qj)j@b~*>8+4d8t8YhdK+_>KwfdGZWr* z$C`!3;vuNJ;24IV;cBh+4F(ge)!2ii1_QmtAC5JD;cOkK3ee#F>Pe$-UZMi!>V;k^ z=$)SS)*XbIvNH(%Jvy!{y-$xbyL5B#*{NjY%rNhH3YkjBNO_Y}#*yBV>i9Dh7wIiuO%P+LB zs?DLm3J8s4F5~mi=ak$5H z&55BdXqM$?0d6TYlsMd0!lc0?hJo4n9kX^!s}}x<6N*wo-X|lC_TD}7%=w+Rq9$n3 zetS{Hpot`w{E`Qyx$sSl-Dq&gQem{ZvBjxxxJrbRt0ph z^nwl+VwGi{zY&xiC#Td2Mbf7}w|p-laDggY`aV2J*f z_t$}Db%zG@t5fE2cM9nuDYyKUne6Ue{8OW^USic>Gsw)*BBHJGU~Mh$@tcj#damWY za#()xuwsqjnHfhGn$l-8eFuur zmLg#K`6hTP{md*z;2{}-13QI9ecQ$Qvc|5c*VyHjxG@~<&A27c2z$?H#xVUd%M0s9 z9DU?8-MBmd^-$EIogy-^b0=O4d2I}1upyU+y)lL{q6X?aXzfdCJp451t8Nt7c`*cm{=}cSHrk7TfNkU+XS*B6D~55P9!#c zkmH0^qLcv=-}nypTJI>+C<`^fd6jpWX`DKi#1c7j@X4L&!nKib14<~TTTzD+$IGzr z4U1nP9BoU%#22x||Ae9qFnvkzD*BpTY8pBqPtc0u6bg&OjKh?_Kyb3dY#@6*{K1aR zVPcMANf5=>!lW|z6^xq^t1M&%+iothwGz);)=R(3XAdF`gcWr#U1WvK2+ZyN?0=Za zHo^gOQT)U49E`{h;AL2glbvRG)OXeT?yA#|(J1WYSw`Q5PJ0=4+8klU!S(F`X2tMB zF?TJ*5MXhqsy6H!|DTBfprw#Ic8^U|n^)m}5)V5KdDqU>a z9F%iZ&TPCI3mNRJU1LSrEtZ@F13#*!%jwgini>#4mOsjI+Ik=LGmECxwuQZFkV9jC z1D?fC@X9Vmi zF>EK@;2XRXa*Tm)9O=jOkmGdpmJT(CMEFJOyT~OW@6n-VCv*fKt~H9go{u`B3pnSY zj$ksFwPZgR_2A_lWDfLB%{6*ArXKgsImj$9*qI^kmRzF*u>MWCMzY2ie`vqytv46{ z1d0C%f%yNy@>_;HLA4kx@|p=8*O~+_h1~Pwk+n`(OQKd1*b^qfB*}M47{3bnl0N~` zfgS=g`6}U3mmoe-9@I`&1nnf=2~~l1QcLELVNQc@Kge-9llu@S4pYoTxjRD)(RLDK zpMmlR_7v+}@`W6hO<9q^&9v;fVI8-wAD5%p;;I z6rHd+Y*G!yFb9{a(=oRqTz+Oi>|;bHRC&3Fnnk)(<}J;~O3x{Wh~ZCK2x?(c$(N@~ zj?DWd$KD==lOs?|<>(<{*21K)>C8Id@%MKDAar&o6egpK5TC08&?HEH($rlbZjI_M zC<8y+!TiC%Uw8+V6@2%`$be{|AFNuNfxlv|;6T>5UVcaV;x@g#< zEi^jjylq9dVR)c9nv?GhILs`v5(vn2?}9>OSg%+<(k0=FEWth->KpHfPAbt zQL>PC-(hBZCxHMlc6$Wd`h~_&bhO%N^N>#LE7PB6&>|~Zz)cnkisDThZ59r0plr3p zTUfPg_og>5iN;`3R@0K=z)q49hq=|eVKfeV&}W5faW|ksCMKFDBCYKUW<7zz=~#~zw*PWKPnVx=?v1Gre}F-{6opjau0`_T=?N^uz173Sgv z4$kX38-^=Z{Eh2vZBTD(p+;I;kGmdlVGXpr;81tqd& zwM!+WQ>=tn-NoqAH;$zIejkk{M#0fUNutDNd~qbPsvr7rBq27L-W^?x{*hP@1j3#x zd(8CS0G3w2G35Qd(j2U%yoxHb%WQcfx-~2t?C0^<%UpW|!s~BG;;3Poky1_9GPM&T z>Mm8ceg|0525Ks!QBL?dI8^3iRO9BL)wds}ilrN?+5dcVx{9KK69B|d|6cfQl?LQ_$0(j6WCW7@)mOE)*(){a|NQgjlyTDnhnPqatoMO5BhFMevK4c&FTM zjLT`)1d3qoyhm;~Mrv)nFAI!52K!X=z8&sQHxIkRD8?lRfFe57@Y8}b{av6U7!VBG z(5}*`2#zZ{WEUp|#mPWL2!Q&hz)#K({4!7x@`EN+1plLtil~7Msc&ziv8G=jE1FOd zEUx@XNDn+Jq6Sjc9sdCs;qa$HUQNx=AHkl&U!bRG2^Ar6LFrUTAwMdpK|E8>Kp%RK zQ4z&-WQyKAM*j>{1joiMC8SUh2Q$>_`!r?59x*{6*xo`QdZv)OSm~}I5O$Hb?Ezy* zWx_`Pfxmx%zpqe;zCb}N+z8kW7O}fTK{TQn2>mbsZ^oYx3@*?OsTI=M0o7n}^c*%O zcBf$Q5-+p@YUqy{7t(MrFn)c6+5W#1-oVc|5by@vf@}rfAomU5AWv-_-@s1Udwc_1 z)?7IJaoEQ<1n~YWzF{lmA&YNF!yyhhzQGlv6}|xg#H#^t(4GHye1q(wumgLBZxDql zGz*SA2;abQ>1LPs23>CV`t&!3>?^!MTI!|#HU*~I8Sn;O{K?zC2}xt?%OYS#7T*wH zHL~~y`$)|DusVyu%;Fn-00q{%dxmddceRXf5I+m>4L=!b$nOZ>FuxV-LbZ*#^&Vjt z2H{*&=Z&a|4VVJ|5l3_7wLDZdd|6}zw&>omD?{(XoIiZCUJfuzxl7;L;zPP_-^0|bKl0cVk7)u_i%+b|FoBIh2l@JwTliczL@P2t}yp& z?CS)xvYp@xKLT7K(F9kx9&m*}<5U5CqIe%B;0o;hOt``tz!lz7`|#pTWdiNi46Y!~ z3QkmCYdXSd4X(gnIY4j)eoAw=0zZ3y;R+t$3R{B1A=)X)fGhA5nodt`8@uXITNbxb zWl!Q14JLz$-IX+4A!H0yaD~mNQGzGHj1xQohe)+#huJ`Opd+xAVsV&pnDTM>!^}Kf zX%(&jq(lS4`bY_aD-dF$8C>B}IAp>V9>L36fGddm)Cdv7UQ{Mr!5C-xM3Q?0SHL+` z92*%(F;&l-mEMYDymy?-s5AWP}e_ zAcVx8!WGt|23vtE0PuchYj_2q91bL20jF~Q0qM0n;T8B{`-)dsu0D)h)*P>}6qQ8y zgv(G#Fd0lAuW%_UVi$OY^LNH8a44DY-4b5mWF`L$N4(TDQ0di`^T%mE)Yl}6T3hFirrxs2u#KBYYn>~Cp5<{6lH=JGO-Ih zwtv_KHU>2Y%mRTWaNgIfo7@$4L4KnOK-dNGQB&X147(sk;?wK~yTA+;IgMT5uc?E4 zIjm{mV*mlPgk2CXG+`Iy&=#-@V#sc>3v!?mmfc_%_}k5~3k;(g$%iOW{b?Gzz&1Bw z7dWy<*aiM4RacqV1qOBHY3zb{wPoxAdu2D+1seNW!Y&Y`Z-1~0lhsj@z$}m&>5kY1 z)(H)K-?0mYx$MoIzzbmlFUW5#@4`ak;8xKK(or8P1@r=Qc8Ol#Oa)D&7bNti`-Rz8 z^un(?8heIbkYBWpUSOZ^J$iwKRnGSxy)cZ>3;a(zpckl1y95B|OHG?FVC*sgd7n{G z2JuG)W$0{lIF_Ej2P^}7O<@_ttKTb@LAke23o&uJki_yst zw}!m0y8z>y@{Z_g3_2cY;of_QWnhm6ScbkWU>R@+nVLF>epqKOfPNFW|RVp6hM7^uuyIAkwLAO`Q6k{N)9pYBM>ye3NmktKo1l0alhAWB;y zfdFnWjw4!dnrBHMvLq1x7?&l1@UkQjSrQ0<^RgrmEK34GJHr6wJ6RHlED3~-dofuO zh%5;N=1Ex+h~g{>1jG5Ya~M!tqj27RSe67LO9DZ_htGD8s>qT+U|L0Yqq8IsSrUjW z2?Q>Gu`CG$xEqLdB})R4C4q3tadr*z2Le)LNg%Q$5Lpt4ED1!G1Oij$-UKrJ&mnJs}~KJciLHW{1p5MOmX7Eh3ETz$vmw9%7ja_^?15@wPAJ|GnscfWyzU7 z=AtneCE<0u4%BXqvD#lSXu#kBhYUJo-a&^99T1;Cbnt?c1`kdyH2U(%XP;GExoC0m z;Dd_?4;pds@DaOHvaz;hB^&)r@l~2pg0yTzl-4!*z<13karFK(N{9)&V3d$C#VEo0 zrx_)F1T7m-262{ z8H5u&7x8dgfz)tFP-XaPIK+8DL5Urug+lX7RiW9Zs?aearkK%GIk9x*T%^M7B{4QSXl^qzju=+&uJWgYcU z*0Dk>;KPIdjS1?I!t$t=m@Gzub`d%{y5zChiY=v?l8!Q+A5U63z+aI|YC4K^3H6oG z(@{fYE48@6(x|87x^Oc+9n22&bYL&pme5#&nZM0%^*^onM7_!e$5M)IfU0(-o}EF5 zs|!q`{RG0Mo56iS_X!0Z)G7i+9yPuu4|d+pOc(OaU2F1S;1PNs8Bf!|1WXse)~V{+ zGop(#l!lB0r^$n76?uRs==)OS!5<1*6IyXvkq3LQ6-6E+TppSL)iirW+#Qa%eIES2miaE^ zJ^uxK7uCdf(ZRd4!Dt6+)z%e$bg@n;#s2Yy-s=rUpC;uWJ+>G}|GSZ8yrwR_Wyvy@ z?^3(Re*;-Y8D{fKqDr?%X*1m(9Pa$BCY>I=eLZ~ApW-*8PCSs>IK~CqIKXP5v~dh+ zf!;z^G|^j-HjbWYdJEA$(8kd|(8d8;3tt-tv~o0R;}8!WIBgvN*gJZQwcB?|Z&9TV+=oU{zjbIaP+`vJKW2OH`)+I2A``mdWgZkMvsFH$(uMbNTtVG++L+!Co)Z%HiIK$jWI-z z1sXkmtZs0!z}%4{gZEOG_}TSMH-$xID;hmktBb%qZ$CA9u;S(v8LapIQe==u4^RgX z$Ahy2MF#88bYY(;GDHo+5j6(PTB6DTw?M~iH6|7sq`SieP3TrY-fs$e?kWKMWu%vu09MO-b9g+ z1C<^Jqmqak113>qh=UM}>@ashks-8bU9^!$3 zC}U9AZy+MzR@sRtV^)*g`HBmOTctIkjLEGLWgOAeGwh9G4}K>~pFxzt??5eN5M?m< z?-NmmT#twWQHI=rs>U;iSxauHseM-L!IWIYAacH9kJgAXQ?!J-_C;;(^GKQ)mW)fxaQ!|J%FxdKi(hf>KSTAeWNZR^pJqoTAM??`_nj!Ci`$}xkEy%S@G(<;C*sJEGj_?5!6vGpjT{-r z2Ict9IWh!3d~NSmG<=Lkt-%lfK>Nq;HGHrcD(44?BZCb=7Ai6{e6+xkA@dZg3kQKr zTHOb6$$Ss$K6)W{r0xUe_o?oqJ6=obK8o<#{Z#i+h|iy??xRC!2X!9>p@1Ueljal| z5A8Wch775Wj{l$qii{gnd*MGqkAmYUW?bg0`}oSNN#TGpb?#yZ1gEOAW;oe;yD}8P ziPfsNmxZ?AG%EsK;}eGP5UyN?Cah<=O^2F`dFaU1%X}Te2`H6}Y?ONB31(4x4LI2) z-Qza&bW@lK7%Eq;t_(SguZ~>v8S~Y1vhGl$EH~Cz=|pVk$!x%MHI9JHWzi!)6Z$iV z>>%>Q(&hd!TTEA`8^Q^yfILBY-736f<$9Gd7y2??4(?{?%XIkzmJ5BEF7#!t#M*5_ zpf7V(v#=+m1Fvf_usZ{hH#5f#DC}6Ub#Dh5Ankc=kVzYf`XxpNY-E76_uBkd$!l`k z*U&^k4r0;N7##QFc>;tzw)}E;<>i$jSp;RUa7#cvrx>8Z#0+V&G8WxdRqW)fXAbYd zq7!v#+5;?{(OVWTAwTBW1I9t!8T=8J{P_{;3pz!X#kx}%o5BEDu)dwc5Qze@Knty1 zG!B}Gs~sDGc~=VD*0Bc$2_jQ|f;>pDI}+?nVLAq3kRIar=|P*VKgM@g>4{t*YY^Tq z5Z;*@Q#03pxxIlqq8R(18)iBTW@g&`B~lAYAMcnuyXqU_l8GUh)wy-W^PiHQz)8I=}h=F241;8JPr zpp;ZXS*S`LAfAlu~(t74@vlqy~f7(ZEQCh`mwf19Bo1BESiAHeG?gk zBG<&2n8ST@s*@OVjFXO+qBay&@$5~-uCx7dv>~ZaK^vhk)bihR@^q+wEl zVIEnr^d zHLyVb&FB-$LRVJJb#f5tX}E2L+hn+rQsk%MUOR-Di6PQW4dG@3zBPUC98_r>RT&?% z$f3ldh=;Ep#a@sZ8^axYd1WZ)d8SKLdvr58LwvrpTNLl1@HGt8uOdM6RXPHCTNMFX zxB|DF<>*Jy`B8!~+MfvA3IC;6|#L-V&RVREchSbNz>+iKzKEBb4 z>y@EeBJD$mn)4j1v2yXy27ju0lGWI9t|v-SD~pA>Wz#x0g{pQdt0NKYPEC+=BU_Oe zxiz3sQ5?!VsXC3|pIDDluNR@jddyPrOrNp=&y*>a&!TQ=TSw%PImlr!Bc(NPK#PyS zp|S5R) zmW~M2;YceGMHFljdQy9XFedPI?o&{v7OmkQyQI&Ja!;k1h?l!{Xk2yZUWbavWPImI z^u6IWd5DPQpjsXLC+^@+ajEv2;z~CM@u;(+xH)J$6xVKytNd#yKsvHhz?^9QSjX2J zR-pUOF^sTIf$2XdO2ddl&u16}}2?ke7b}Y3T$R1?SZ+P-P zm)b-xwtRubp*)XNDny_EA@sEhi+Vpw@0wibQHA*Bpk;4MqS0lDpz}8HOZc|&%{*j7 zud)5v3e%oWgPhb;den^2Kxd<>X`q{{2D($s2^jO{w8K3bMLVd-G$ZW`Kuz&i~&}VK`-*}g1n-KrGh+#U3ALx9q^McDnH713;7+j z%M9--Gbn&}%~58D<1#Y{62`_1=3nh+@K2P%ttu1pPf!zxO!m^S^}9v6(H9^$e`Kb# z0Df$m33SM(@io(Vs$Xy3+N5TCuU=`FlkT;)+wh@-Pu?aq#b`#}k z^=t)3vC9Euy_y7Z8DV9|1QjfSrlM6 zcY&7WR&%th(3G8@8I&diEi1oO>ez$r3^~4b>BStFi5*6fztu-L=NH1h(>VP_loT+PZq3jxgImU0cNw&|``NlwGQ8 zbFl1lFtWydb4ix3EX!9$Qw*NvE6ehgRb~0gvV3K`R_bPOXa7*HJg-%htH!*4Z8C;t zmAZ|!oC1u};7W@_LAR5iRqB>i>PCv(Y@9qbTqhiQj^TOFl)8zBu&u?{TJ|$st!lqf zi(U30+@X-z`@^y3FTNwCZby1cjyF4Y@-Hi3!daVN>Bi~e0w&wFLwID1_p{^8k*z3x ztFRGrj}*Uom9x#VU1C@dZ^Es9INLnhm1ig=Z+wPQ^2R6oO5SSrS;-r&6ZOEVlMhwP zt+IhN)_nPKq-+n>zA>ftt-xm3Bg%xY@=tcq_4fE_F3s1(=jzycce>uhm(6s&$sKgP z$?rhd8-GPzJK4Riw~^Sb?}7cU9+FvR$gufV6_Yl^V%SQy_f7{~fh(j+fW7QJHo_>< zgtw{M9IA0IZ=_LBBYvrT`@C6NOtx(RlLb81 zhsin_Fj;x`frH8Z8I5Kyw7_Ng${<}NVOhSiEMHk|8}zaYaAwEyM>`INPdTS$h^w5W zU=e!*aTPxS90YJx26Im#uAGp6tw3D6>I+*zxbka(8aZ$XSKdvb$;67C5UvE&+b4vp z54DEi0c!0%I@Iih$D&kjHdXyc4z+irokbXKUDp?FedulfA*V3SiSRv8`eT%AbL4E)<+j^G*dC^SC$F}-c z$;Dh(K=GR#j~8U(S;wI?yTP-v`&5Fh;#sSj<5@HHzU5~seq%t;O{ns64>gN)r_5WL zZxq!y<(Nd_&kY=e!lci$JXiC@zM%}0tNc;ewyt(5T$Zm4=s6OQ-6(!zFE>~GCZTi9 z$Fl;nN(%&%4HAj8&NVul6*wv-JS$=7DNHjwD{dF06~FNpTUPugpWlt*H}Oj}cL;GH zm`!pCK>PmSS%X6=3H6wi?;RDt$+l?V`;KSrn1gfo79p+rZXm6i`cx@`w6a}8TEBvp zGWrC6$7wV`4h#rizbN|(X}w`I4tvmNg=^;lQ`1|9BOpN`a0mJ=xB*oJVQYZ9_^@@g zZ}P8uul9{^SB+=?A+7C6?HhYz2eohBONX07bLIakO>aEQSB4%Qdp-YAd}VKGA+t%* zTQL;9c@=MKZM>;v=7TwenmA?fkm^QgMKAAA(2?aICt1j2mxTy#$CJ!e_Yw~G5c^!z;4Ik2QvoK?(S_FjD56NITD);f0*_Z_=5~9 z2Gj0`v|z@%!XIV=W)?A#MNH^dp^;72d6=d=_O$AV^AYwHae{qy7BRs@aKTdGVq~sl zHlZ%w`Sxr#itf2{}NY_~wF_A?~bi?{5|4^saH-|wj z1KAI9;=mX9(4s72B4B}vvTJbme2XPMR|mO11K1}`0ITK8(XQQw(McYhrgDam0goAj$V1A#xUt926;{9sCYxk4)Ycnu1 znY>?{%pG{Y9y7f+?ln5=H-@~wSDJ&NP^qHI>@r)PxaYiIqVCe@x7cVPCc*~nmO404 zYQQ4XAw^bWRR7CIW5$j!^8QPG-mfF$L^W|v_~B~}Q!{hI*H4G8w_<20}e7X`O5ubh6!~NF?Od0kr~+ zNV<3LkBq`Yt_(;de%bfoUQKdN^grn^8oS-zBBog63+@vneHB29i^ zlPa}92OS&JL?Xc_t6NY1ek2m86(W%k)j6MH#hjt+6n9g$Dr??f}$}MiNHgz?I0cw zxE+2n)R5m1x5NBacpIwy3Dq2+4W7je8)$=8Q3yaMOhNCJ?xi+hJO7VZdz9DmP}%Th zkqzxd_#L}4^e)W#!#C^Y9Yna?sSKUueR#0ZT^CseX4JRujsZe`(To9t?Z5!Rz5@mb z@v<7Xch3N!4fI}~YZi62N6;cn>h=g3b~b@}VL5lGSvZ@R<;~t^EO6vYDoyUK8)5u6 zC@?E`X=A?PMQ;6!mo-yhM(!*)29s|#DKh*21hrrrgZ0tid9aPo^uYno1MAxY&jT-Q z;(2hP4y}8d=Yc^-2La1P4tO3S*p-Wb=OJQD(XH=>=Ye<|_J-%7_;X>!8hIg@ul+2Z zi+xvgaPiOB%$?Ms%>|~UmOK|DFi3nG0|)k6M7Ax{UK`F(hXz$<;zl3{7`NmZP-XTb zW0-zPlP0t4p~>u39NwTq6|caACNuU5G?^L3U_&m4Dzi1lh#Fk<^egfOW$viTOjHL~ z(Sb;ytxHm$CR;%*@NEYOwZM;Sj#}XJ_7}C_0kuGA1T+~3wVa7s;8UBU7TBW*2b6+% zM4=WKOnkO9Y9V9{Rj7rBP@{xWfa#+a9t=LlieXqi8WXxI%dkUe=N- zv-{Ll;8-qg8{}C=--S+l^smM^D^8~)fvN;*cw6wF@ENvWbkm9>I1w~W*bF=M20FeM!KA!8$zr@_+6+nJE0Yxhd?P2Rnz6^3*v30e~9C> z^*-un7EP;d3wzZdht@j{cosj#D~aa;<{tArT#p)Th3BD*!Ov`s=;2C~`T!C=bPA;F z@|}nt_+k4>^l-lVF!H?SL=U9xj))x=p^{)Sn6+d-8x^q&qK8v=CVJrER)`*sRr1ep z(o0Q))WxBB>`e6VFJvW?=;3JCTO)eF5jEW#5AKs^5Iuabk3j*nxHXDhq8uH>0DPL=Kp5DU%^?i@Sp{K`6-@&l15}|U z2!nW`3Bn+Iwg6!eJ$4IWkflmkc0>BWf7_h&fv|NXAEHF{rz9r?^kWYxcOre@$eypn z41^I_E;J*3U>%!CAH*{)lRmI*yCHp$81q^peUNvnOr(0CwIU-n&N^#>QQ#)jBEXD! z3p*Hv7CAZXy_Gvb7=lA3fmtBsdq>g-7DWT!chZN#Tn5bsJFq^46TN^){MPa=EHn=8 z70ahq2Tqm966~spu*=uEq?|&2qqrPWpnYK9nBIMdneCkf0>s$uk%aeYp)nNvI@)OS zkWTz>&1oM%bf*flue1-p>S*j4?Sp*3b=n8^r@g0rU;)Ty|7jnF5$yx7X<*MPNP~FhdxbQJCl#cD z!Q4+sgM7R>q(K6~a7P!TeKMF`g7o(FQyymLR02-z>h5bDKdYMa0b6bBq z5=RZwbd_ql7NSft$?gpx4SidHG~j@ag7A?F(!lS^gfwij)_?@U3zeDQn*Vwt|LZkn zX0gZL(tvB&u79^&4?i;cneqjNYw%_!js7FQP-nCJr{6WOVZ;FdHuTsPu%RpfHsFMR zO;4+1PBlj5jiFtW&;=wITYm-(Sm}a zrD!X80fh}(R3aHq+Xtsb%ghurdd4E9qG z*^rTdY)JQz4ap9&LH$VK-<|Fl9vjdM!aHKh`!O=hnRk&z_;A>U&v3B?J`;l;*Z`$S zzdfrFY{TE&3o^t^FD?<=@L|FQ8E-k*hH{h5a63N{+aNl|u?=Ln8-H@J4ds|yZSlkD zT^K)k{2a#C%WMZ~27eSkd8?4bDugiaY7rNjVOyQBBPD1RiEUsLz6Z7;_mjpi$PnIz zO)i>Y07I+3k8ek1+1ND8gxO%TnWD#lA+!+GxTkPV{hdSmN11aOPyk1S%lV~`K=~e+ zu}6H_|FgGZ*e}H~5aPu{U?BJ>!~AW3NaVv0XXAm*ZVV;yL)&;Dvt0ay_^Wp?9Vo_D zF~`AAu$f9Q1u`*HV4cL}SI%1Z_TljpY>_*UV)MsAtcW$hPv|aa6L{b(`> zKsQV{`P@wyce8d@B_>)3cc00RO+{LH)DnW_JeekjUvc8(yq0OlRs_r*ATEHvNcZlK zE1dkLj7OqDo%|Lz;U|nzP+Es_tz@dazpWO2DPbC}lK(0j50*GX2^s)ni5$M-DPOi~ zmh&4&`F{-h-0nBN3@%3dd#hGkUN+jFrP8*%u)vp9{GV;(fwVdn=!9r?Fm%FJmBZV3 zP{}vEpu4XqEe6cEUM0o|9Bo$eOS}8J_JOfeJrS=_+Oa-fgZK}HocNvc4*zx=a*kyY z%ej;nZ}+uGb|fR<=7Xm&&1}V!d-!&in=OiU3M+sV7f4ik7f84lNeqR0j0``MmO`RJ zi$WB_TDWDjR=Vj|(po3|0$Q1b{Vwp`m6#7S57$IBnRp0w0u3zzEp0OKFh&?=OGy6D z6GjL(l|EHPD7ZyvmzCP3>RQJmKlJyEcKqlc&>DwN90;j zcxq#bI^c!ag%>b(QR+R1@m%RWo1Kw9mIlv9cPR$DuW{gn*x&&tPU58)qc2GrrkCR0 z*4PP*1BJs1UHK`ie?5i_TL=6riRv^}!*7^gnXXcc%(LVvP9;upEH>BOihEEm$q~eW z7iWPAh4{9puYFG$d{lR7c$f^{x{vR4+H^}su)SO>PXb1w>6VOXAPfUQNI)Q>{e@B4 z-19#L*IwXU z0<*WjuR}TcFGf%F^szDrKJkeUTMvGH5C3GJ=+_8-f)pjjyC|JVA2JMLhMTfQTTkPmy5UE!yD$g z4N(;Aa`&8cc3+PNaj7iopfGKo_+*tbyCW_yegyn*v5*??7_61a77DKa1qj z4;QPXZa;%~xCCzHQNkz~45HT}tpG`pFbXE!L>L8o8UYC~3bqv=YXn9?9&r!XLfA7W z!YCRn;;7~kVH5)Aa&q3`=fEiB(OISEPlQoO*a$dt2R3pT7{#Hk%OF6|5d0krj6&Rx zPXZFb;2tfE!rp)uJOqs5(AQauAB*xUb8wm%9Bzmc~&ONxrsi z*kUviU=yMOjRcp$l`slnqah9rqrmMO{O)95JLP)5E!kIf*!wcb9FG8a_hpbd?vQDC zUxp0~Tq2CZz8FP21dKw!*nFcf3IQyJjF1E6SnkUZ(^2mP7=@UI`X|6BY{VZIjDnqy z7Xh6xTjPjuGHQ-zfw1ojqad&@g9$FfIZ^Mv40hJ{gieIeN)kFzf=V0ksTL4?1y1e6>3o>kp!DW6+7yjtrgX?M{#*K_}j80G$BbK@NS<;JysGB*}0Iorv9+ z!GJcBZFQ*oGVHyFfKKc=5_AIVU8B$mEJd;q#|xeCtUr+6Ue|cAnP`O#U4BI;IT+x_ z51lyf`!Ynb+f`8soJcfX-1{;JY%j($WM2En3gA^i} zY(0b}SUw;JI))1~1W+E8$l`jOwgixc*wqj#@mvfmvGMrrKL~O3_8-XBM6kqK)41}| zqNxim=*81I_*?LtE&e?9%1illuD0dV$EoWBn@0X<^HdeukQhn3L#k62Wq;Q{qNAi{}{_~WRU5@jLPwE#oeB)=v6_@s^-wi&5RHZ37 z@oq>=f^LBK-=-UkD=%qSe1y2g-{Rj`FItYEOa4VgS6M{uuc?ZE#Lm#|)%`Uffp)4u z0u9iP0SR=3!FyRFgLkFY5myA{57P4dYykvi|&arfpWm>d5k9?RAC!Y>3vn>P1T{c&kFM z**47*xS}nIEY^+f(=3AL7ZxnmOBPSFn6WU(Qt2y$TtX!Qj_-|rLBrQ zv0WRfC{Od8G1^r6gu5*!k4EM`qfJqgNLwSQv=5pFgn5j=_N>;UfV3?S(%+TpwGjR< z6YDIJQyw&PaTuViv!pR0X?9_m4Ld8X`S7!~wrO`5L218DtZ}mz&H2@5YlSNLm~T2; z%g-eH^k6_dtQ!JZoPCpS6xo(Y=eu@jMXLQ*o;6O(Q`y^m;5aQiEl?gTI|BvzngpeS zg}9Q>9;apHh~3D7J*->e2Hh$VI?V-}_ZNh%d04m4;LB^YES3G4Zykpg+iCD!HNc*i zv=v5;QI(TZq>3;2?D5(t`ibsTm3>yV`ksmOL(jLr>f3ud(f2*yzN*4|v-l+wG@*(o zdErEDqVlK6+?|?*E{awq=jQN-&(V^UXZhB1v_XAOb*o$hk-s5Z3V(KYH_QMvjY1j_ zoqicLR#3;(dhD5S<$3L$E|u8e5uvm33xiSA+R4RsF?#kjUM^^7@*q!sL2IF0#|KW* z2CMd2eD(|4D5W=l@&)Yz<%>wpE)-HZpRYJyTcXV4U;R#7po#^2`DC;T`7vMdqBc9g z<}PwL4G5U3?jDn$RqQsX!Mr|s%eKgDB$=gGy*Vb6pZk*5LM0RV@+n%O`5{ghyW00# ze9cQ*%Py>j1iL<}s>WE0%6$^s;rf&O1y21%u}G=u0Z|s;`;ykSDp%>d<@Z`gLpig` zdUPVc<~6Nv^ZrJ#q$3WW(8J*lz)Il~X)-vn^EK@OMakw1F4ktK>?!{G#oA_{{lTKD zc|Fd8F^#INJuprJ{M$FQY$Z_jZI7jqHM6zp%?#x7QnoOv%Q5lni9DxV%S>i4Ybr-| z&9dA88(&p6EHjTlXGjJu%OKhdkV==dA5CAtptsB1a8kyvF4qcj#9bsPxe+nk4KEoC zkOmf!G0lkIF0I-%tkAO0^j-<^99zq>*ihFmhB^K|WU%Wu>uiwsF5`1;%of()_16>=e=IFIgKxrjlG*8QT!{}w>C1m_V+M)8a=ik> z-tNN-E3^VtoWdtnXk%4Tz&BTDyDTX*mepo$_|nB_SW!{+WC-KJu6i{zSS4wE_!4bk zOYyFT3ARROsqQc-K?BsFQ6sl5(e720wUL3>X@yD_+pW3H`ZSt#?=?Zgk3ym%;*F}g zBlGfXfYlvZ0zjPomus8>$6oWokj(xQ-?>!F%VV#)Ve(ZQ;CT5?35@x~nwh=Klb2~% ztM>DJ`7-Scy3XCmk>~lYW!j>Aw%zrYCM`3 z5Rg_?6ULXNlV)BQUm*-*>}X0ds`s6}qy8=iRM!YCfMh z$pnBv(PGzJ6e*8Pxm$~9U=cF!)mEoIgOyxn<;Q`kAJ9kst9!Nmt$ydy+7|{*w?wu3 zY)gY#f96ka&`v{de!4*`O#J{v<44O0z3lcC0g_Anyyr%(d%NGp-zC?(&k~7bUk;4t z1z6~IMHX$;e(OK0*a*JZ3sey+_$Tviqt|FcFVD3oQ`SQ6kLmIw?_I3B^X-I}8{RE(2z-a~Uvug=E0W^vEqj z>#H0;8+MCokB>aLT^rFjCpJ|{%8fH(qAh~t;m=Pm6jWS}ah0BQ9 zpSX;e4UVTFBgUG!j2H|IIE1kr=_JYJ#Kbo)C&m`IoEY14FegUdbU86Hz~#im z8;x;dJSVE1qWnX0Vr3Tl%q2hKbFg9)EVkeC9snP<$U0^VFb$H&O=QXJIg5h!MRhD$ zOXZw{IkHxrqxBgw;W223WXMK?A?skMY?#ZD%>qYu#=#t!%_2KzNscV5K1W902S@f; znUY+!^|AH}<=_4Y{Fv3mk2UdQ{|@{Z$#wZL*2d$r?~u> znEb!Zk4fD)|HVapdb{%8-2PhZg5o%=_s%ic~8d}Vy zwcBznX`@|=Gb;fdhGHlU-_Vmvuw3XmK!(NwGK9>VcZ9ZUJ~6X85py2m?7u6)p2(w0 zeAkzY<%-FJx9QD$eF9y!AW(0RMY7)R7fqxN<0L1FpTru5VcW}G+>@GrLz)A8O1|Dn z$>mG)^@|3y!}p7DeUl%lC7d}7<<^)ru%dpHN=ZH9V!4C{_obx>lNP}$^LRlgJ-b|b zx93sX9&UOrrJ9@kTF0PRe=2XftE?A>TcdRO*?zQEhNl(lrA5qNim=i=rqRLUsF|kd zwHolh+olKhg(PQfP*3Wb_x@Vby6-s_GI6vnM|7;dCh8l)8A*shrN;}e%NyoK zORH>JiSb!3Uyx(O#BGSN0lPx_-|9eRoMQdDQ zIJ{~*ARSI6Yh^sj78_k=N15K%qjHX0m>igXW_l(yVe(9-i;XlV9_^PHCetUDD+GUe z*qP(*T#%7+UYj6mWTyn#IUirYVJA-quwq zT@{7$Y8;EN_0osE^b~NI(0mwzgd3LWZF8L!mLCc5eO>je@=A1ltTyrkl}Je01?~_@ z!pOldF}~J`$1uGN=k`zpVQ@>~%8^%#wA3TLbrrCuTa^eGmy%$uOb?ePW9WeN!`Rs* zE2^WJP9g5RDDm9aT$lXQb=gJkm<&s@*TWm14d#V3{~`g=2rUgL3KI}FSBVBKeL0PhY%JE=lu)ynZc;6 zovdj(4qQjC)ti}h@lbASJwz%RmnI{p^x?G9aYMA$aiQ@}ky|=08%#e3oPtTMypgnW za5A+9k9M`-(-+X;Se1UgRv%x?MtD8po$|^VEBd&UO*Ug}2-Kp7DZ96B#@973AG1!+ zNQWg+XK@cOTMwv)&gSq1>-0it9j>R|qdW>;AOsC0*bp&77(gMoVL5={M)5;)>cj`5 zRG<%0Jj?V^=-W8yWjs_*Vrj!t{Q~KB8hEFRI|D0K;&gDO$_%S^b3k4VQENc4--MaK z#iI-8aOYtfUGBJ-QJQ4vwRpDBR!BhQ`72E}^bo&hz23I06cfOip^gh~32t(+t>0KG z`4jXd*$9Z2`|T(W`JZFL2t2a})=Gpk2a?crl2?&{ETBksuh)UYX~n1X(%YsDLsgtC z);R`oNlU(>m);_+1hq~Gwwue~Ow<0UJ9{FR-J>^C0AeZUQ~#k%=Ij*Rui9VnefR2% z^6dxQMB?MPRhGmt^^lEXe9V__&-LDn}H4&fP(1K4*?0t~8D3 z^wu-W%)Y#2UYzL$`XXW&Jq+bzS9 zN4Vx3dUwe}8U+;(drWAkczO?q3pEqC&|LDk)7FUv57~Px2Ijvuh41POR-5rD**J_# zJypLrU4A%J#Iz6yiJYR8@xuG`Svg{-XYwYY0i1k*Qgrjl9-VG$7PIwAyb3!hj*7qJ zyf$IvYyw9$9K+5`XPN{jNjh~u+D(S#=cUqcm!UL&a4rp(hUop30PLWRX7PV+)LWK+ zQ6B8*v>*!B$QPCaII(1t+DGqeQc(9H=$7RxIXvm1B=-&yhDozTvtbR4RAa# zl580|6svlXfJBl=LfB(B_~QFX5KE?CeTkT&f&@?DH$Uaeu$HC;scz4)$OHU9AALEG zp02m_Mbp>tLBG(4;o;$`8?P|DJDlhX7lxE@@FO~bX|^8E?4 z(s3s_;clKGYAS|q21;~jz@4FYval2ybOxg|nZNs>zA`g};TytQ5<>Q75%GrxPs7z= ze8pyczO<_fGC81--^TM&gCg==D`Xv(z) zZWOaCD*c!pA#D4?a+biAvn2}GVXQhJT&{9G;DWw|;19`ka3wDk>WKF(_&Z|r6v9Ik z0b#hId_-i}hS>=(zzx9-!wtiY!i~ZOB{s~?h=&`38-^Q(8-*K%YvKwEvkT(khTw+b zhT%rxM&X*c+QKYAJls%0ITGL@jDRTIC|t7z5_ClZxFNVTBqITu&Y|-R zFTx*!E2(oBu8CV4oIyE_Z~muJ$S-+BZp*DFK$!bkPoQi@Sw zq1!5pDgt%3EQD*z!gTfvE*~vAxJ2B}cHMd4g=~iGFoQ%(WY5$3_%h17;gxP=gVh}q zuIpE}-VN?0BZ{rA_D9x-S9K(OVOFFXV?Mo#6s9@TS_?a$pI z-4%kEIgFPvFsOD<5-dbL9>6d!yyRZ%Qly`|{~l{U>NtmWu)4!N@VE8Wg9v}1xV_`w zynmgwAN~W~@3H10PJTyzd(O|+y6NA}4LpeV228NlPEPwn8U)Xk={T<-Q(UdF#1!=8rAtroTj= zhcu$Cn!G;k}KtqUI(N}$W7@S}1lI#v3=hCkIFqgRdt!!#N{ zpP`E{y+r50j~8W_Y<4Lrk*v8{%k1(*LeoiMq;yLlp1St8Bnw8|}AcLcX9{ znK(eWmMwbWUXVv%<)Y_HMDG=BM|*U$Er}NFrL=Q~gmA|t5pTM~uE*z#sd$+e{7TQ_ z;a`DgDvjLrEB&-lTk>>VEK4qDRn>WV%mQnB{p9Lh)QKyl-Vn4dI>_r~XY})=mEX8l zSPv(y6yLcU_euo>=_sX@Bw6J(9rbgEGZR)=F(b?y+$l_c>1GDlpL5BDBe*=p|YwRZ?le+4I6#9m{p4wJqT{k_) zmu_F?Ql8je)t(o@UNzb0BQ(Cb($q|ae~8VMQp0C&(6iN`!k2B(U&(biF6>L>T)@60 zAm@PGmbi1FLXVukQ9oT#p6Au~>2I>F-h%46N8*_6KgKy``=Nt4X0|;7j`<^lPH<^5 zDU2+CL~o(6Cf4GAgteH42`E_$xRuiyuog2LvKCi1!dfi+cVsQ5*)D4#U5~Y(4Ot6W z+eFqv);5u~h*dU`wQwtYGFXcUSc`Ygsvcp`2-FD29)rqn(GgXTSJzWLUeHsC;6lx_ zk3r}6xIR&4d^w2rDw;9%(%F|?c#(wTW%69pXy-#1IF~k#-fyygZ`N}_M zjbqTiK8_M{G(uYHewUV$T53vVO~KRd2xLQHF33j*jHgubF;5N}1uFT1_X`@(^!k*~ z4I0q@JHQ{6;o?KSJ7{EOk$ohX;}Fja)?)>-gL>qcC0E9e01`)j0sWjwu+0{_i% ze@P1FI^*|`H?niYRo?pTox7>ho@JG{u4eIF=|)a3vE0pD*0>bgHuI@mNBh|P)b{&P zMl)?N^|uSceDxYDgwqzn(=v?qezI7k@NXs<-TGMnG?KuBkW#hSU%PEdp!Q~_`rD1v z{l&KPqD)!yosneb2X*^%_v3buZ=PUes*tSim>>t;PxEH`IxI_6A8Q4*un*$Y}RdY%HI3j@Y%~ zX+D_#@v;ia*||n;P%9zS-(oO*Lm=d5GGthY(4j2{)4i#SDSsRx<;;|$(jA$Z1wp+9 z8oN1eFZ6d9sXz1EkDSuVuta}0(zQldR)ci82ych*whh9YH7EX;$FaanGTZ9Viuu{E z%Y!phZA0WPbUWl|Kise&4gJSnuoRT6!N1#WZbOK#w zq-A_kpFm54(sJL+N0%9WRYLgkGGnnSK6A))I{Pd>9yblLb@4eLK1$NOk0jY1qI}4= zjxq|+jMI}qe?JZywAH)u(VR%Q$zLVmE>p=KNx7lfzFU&+w#plPb&}D77boNWXp+(W ztXJdjlZ0pXN<7?tIsPpE5Pxn+w#n}$*}hs*YEbOclpT^__fUT8(rfVupEVZrn$2}* zh4{6k*M)q~SUFWC(QeDlvyE<9_Al`XZ&Hd!-Ooun26F>tXB$PJ*Q-5xeMdZ@L$7al z=(Wl?|7x63SYD6dN&=loaHT(y;7S6VNN}b9rg;7i!M-u>cL??h_+tcL66~MH{UF#r zgWbS4jW=L=z&o>w?e-+aCMz3I?4@qzKP<)m$%&)bQ|nXgIrXb|Sc-kIN3mym6nh5V zjZtj*+>m0A^(gkZ|5S=?xBIuC*y9eO*eWaFubyX&%^|6nwVpIQAFHh1KB!w*k0ccr zxAEoY8@H>_70sV)B-%zqO+BCto%;SmbIYSmT3ur-)Bk336NU ziZM|Uk=I@^K2%lvGQQ(a#_A0FBUi4o#s+@_$eL|j#UGj*s8(K$B)@KCg3eLCVU_WA z(iS%zP&y{*&3C&wv1-~#B@W($gE>qcPKIK7UY2@LLjiDK)G(WX)!H;HoUA4k!SILATUM#$ACbkk7^&!Nu4SdU5BahmbLuLl%S48%% zHP*{sM@MJ#H5-hU0X5#;{KgNAb9w4U;~f=m${ttuEsC7+rFD%GN!?`3R29O1{0rkf zm5q#`v#T?Q_)1iC~s$NI=VDZhFPLlG~rST}=$*z8N({wtK(`mytBh?wk4OY3j zVg8ag% z#+x&%M^n#)%NTkLN4ZC!Rk@9=u4mKK4t5)NeRFm+UBI7w^R&+VICJv*U`7zsy}z^i zw&Wwvro9Wq9QUA?b#h%B_W>JZq|SPH;Stvr9bjyP&dnlw7X~X~s#&~*bRkHG`g>bP zlNXJnlYGQ?6~A#DooulQO3*LGU{~-j#?gFL$h+s#99WZq!KQlxW#xAD!XSNy>e4D&iP&V-6mPVa0h?U|EVoI@bZO*? zeCC$YcH~Zk$h7h!CFz7hSW3-x#aamHTAF?tE%DS8q?syX@igkXqdk{V_9@I)y@mH* z!Z%ke_k!>>N2Tjb5#&EHyHF z2F(JidmyrOCQVn;#T%aKI3m!fjEFx+HeE;u1F^{?2Yy6%`c*MJ^5k5)&*zh@VPFhx z!*el|<3z`At~dJZ`s|umw3Dvu7<%Hk{oF$i^7igXIMg7wha?Vic7-=I3SBog$VDG7 ze5>oSZr&h&&l}`_bO*W3yg{Dq4RU%FfBLS#l(fn2xD?o1$YCk|#tT;m+5&JThkCjw zlfl4R&GDlD!gKBpv`|L6Bi;_V!7LV?FyiHGkh6zOansZr@$Ybq_~EKZ;{(?OhIcUE zFV#afP}=WP-S|zZUNc6g29Q>=L?K%^;rx<`w09mxpJ5JW5SH3TO>wbi%ol3SPi$&@ zK=qoR2)KOpL`)5GmDe7>bL(xqm}}Yl_<@Nu|A^B{>^OK@+0VMu%6{6LR=PK>_H#_D z!Kzrp3ntOmRdSb{U8Blx{oy7TyJ=yN+n8PHKX)e=gX>K$j>)xO71u;opHBy>syLVL zon;0(MC@@|39*CWY?hou<s_DcOZ&tCTCJh{o6^K1ymoIhZa;pIVbxk!mT z!j+$?lF^S-fH>PPDS%w!V$n{ze-Q;}TIQOTxf8q0NnuspG8Y$Z#g@5Pw2a~ZqCwuY z%rz}@ay>cGJY>@{*Vr=WzfzhH2wX{9^V}jm_@bY&q=d7gHUTw6)MNN%%GuYQ)$OxwNeI`fi+dif=N%~wrfWKLVi z`K@$>)>m(S@k0LIt@M=U3-wi6J367IFji>_t%fV3dfZ04c63td%`ac5kH3x}iEXUv zxWpQV3&LK(y|v9{(#x^qxQ%wANP68E+H6{1{?Ki7NUy$nb&_qog5LyfI&FSgU)^~d zImG<0;<I2qmoW|0xb+ulJhD(|bm%qnPevIYPFq05RjM@7cV*YGU2 z56zMNDj(wJxoOA4A4|JxOqIUsmgk)JUcr0S_{AC|F(2}0cY`QvT(7u;kG{NmV|7P8 zA|-dyueGGUy3fBkReyQ_=HUEP+%UEK)d9=*>OyPZuP zV%<$$7SDNtUTukwuMXy*LCNWS-4pa2IsTuZUt%{q zjvrV^`$W1uMITnv**!SXp~9dRenG0U_58qAny1*2w5MrTq<)?c6m&)oqweVeNpW4N zMg$$ElqlZAhJUM|!!y~1UYdTMyBc=~TocLJMmJ#7U&^y8DBw<0`M2BYnK*11_FMXA zIPIRH*(w{)2R?(HHB#j)fk4A9;RBb@e7@!xdcMlO=HEU;7b9)Ov-E9zROVF3U%VDZ z{O{a>W@p{`)*Upbhz<4jh*OoI*7_#n*|9{`!~ij(%=f#~tS@1dot$mN6g(jtXKe!Q1{ z=*OAa^mplB8YhJuq_9gfJL#HW9>k+rIYabGLL$LLF!Ig&&=-#Qub?OOY^|FT!4m(? zAZJq%h*9JC=EI}L&fY^(V`uNtM2(xMaT7KEpI||osBs-N_NTf;@=D3FVtW=Rk~o4l z&g#_jj}DbYv`ZzgJn1~^0@@PLsWuDfPc8D2$Fk<|bqidUbpicE0W-RPA$?Cxw>Q>j zR_zTgvnnF=XEYn>c*kq#1$n{)ATf_ktH-OR;|yq%fbp3VNDEiGf)y+*MfUOSOXzMNc|+mZ6|}qLY{AF3;rp(o zvkE1rD4AKwJd&MmPSWhjbNERsXoSW&Ngz}gT}N>*`a4jmi_&}(=I>=u1%K^2+SMn% zBmCD<+EHcy^mxkub9hRrKC!$OM|L=S*;fnpTkPZ3PU*hS3mo^|$nc%?e1(4+rZW?E z(0?-Pv6v70BSB8*Do4X;?rmZ;>upz$ez*GHvb*NkT~Al-QGC;#@@RW!dMUvAT zvzC5x7*11Rk-x5|8R~`&G}YaI$B0?{R5eD-oDH}nX7ZtH6ESNdW*}-!#H>kFSdaFe z08!zIA!hP`xNiGe2bhz@?76NtJm?${JJLjn3jJ5?UmdCW6Ep)-b16~EPCJT~9eRvS zA|%LNzpvcf-XgMcKBcg{xT65ueblE(il7}lnf(I0BG{}-Q(uE{uw zsx(sE{{)?Q42Cj}uoU2Ws0N3rU6hFO4gGGOJ6*q$!m=+REURP5F0nS&ML7>$zdC_} zvc}6Z&ywYlDB@Uo;``k^{T}`F4;I8?-RUU`EX`xR~4kEcjZ$ zf(@!W1%x4mca~P@Gs_|?2U)8P)t($FDuFg(CYu36!1Ax1&s288V#(n0ps#CWN61=A zRhG=l##(^H!;-{U3nu={OLbap(^C8@@vD{394Pj3s#AbYEAd==lb{s9(@Jx(PT`mF z8$ZXz;t}?ODNKxy{uV*V^EYhLg9Kg zQn>23tW+F=r(GOaqN=z{*in0aaCTshDw;>K<^)y)!v108$x8#PO-oD%<-!klCmh&s zEsE?}5O^NCBHbdJuL?|3Qq5o2Ct#8O|7VR?VEbbE`$j>Q9nΠeb@g5HXZ_DKCSX zYdwADKm9DwIXgk0(rL0ctprW-H?4aD8=kHJ74Xz4k;GG{++&@%7Hh0KtM3S;`9?UJ zBd`YYgue(1@GT-0Z&?PEt#jQ5T>Fl-M71*``G2*xn$%v7Hp7oZ_V2ew_y7iq^!vnG z2Swe;Up}*jG~ROKfKBq6j=k;y^1Y^GFS~v_B%3blU=88#eij%I8TxnYse%L@?^q+o z7getj<*;*gQk_PWYi!r1M&t>ND2JJ=ROvJ#CU1N_l1i0w^43e^4aNV}$=fYE;=eF( zERdMvpj;a+4)jb=Cyx#9I1l@#m8fp+j%~T=JlSJg(tDSWy)6K~`qn@LZMd&jtQ{dI zSpd;4BYWEkB=Wh95&4TjvQj-|w{CX?#%0-~UFEG9Q_FA-lho+6TSsocBd}ZVv^DvG@e*E`#rxbHsP4yFc;Wp# z_xIj8GqgTgvYR*S?#77(txvI4>cHXXt&|t83GB!eqdbkZhum^X3mf(%ZmkVum5Xz{ zdK5wVGkv|;+r$_<$4^do6-Vt$UByvywyQWQW{-C2 zAloSfTSZ~{gWgy4>1h`GyIXE)Dc<tVb9C&dV~P zgbIy3ec*m2 z%!}>`458N=!QrwC7q}{_?D8XP(b=B4adLuHRP7%vkdyA+r$gYzl<3;t8`!I| zb2yafeqk-vt#w2-$#ps(J(*qt!x+DrOsBQ|1N0Hofzr)D>nhW!@q4N(R}$0sL#b|H zpTwta3^bc!XSjXMJQd_pRK5~@B6aa*WBiJDaTAd2Q}lO@!u+=4_Fwe7B~XM02m(g# zq$~CI>?tnVpcZijc$d7*H*E||=wkncxZ?ugblFHXFp|Fs-ytyAE5}O>4E4$U4c_Ix zzzB)vU2tC@Cx^j2myDKbekDI~RsKq(f+aRZVh(@wzQBA{RD0@udwALXf%VxG+cgJ! z2s6VC*e(9?{ejM%mtmgH#<#^2ZsyP<_ES|DPW{rR`B}iNA7`5advM23B=3R1N~rTb z!nZsWn382ra+?G9i#U*)uz}&5Mf~L4Na4eQU4H(?T-uX&cq{-=$hgSn#{v`lTW$@& z9(iEq$R*Hd&*hzO3!HMo*y-HHh#5FmKf!%uP`YTz9co6(8mDF?%cEv7Ds?1kCaMmm zX6!wen%R3LHJh5&*(Er(qoNLCP;7k}|1O?~tj(kTNpvrpd%!uO_TlVjA(_Ey@4)Qr7z^wf-;U!R)U{QiyL*$7we3$#d+reF_4yTnUJ zrd{loMB25pjx>>@Ax)M@byqN4?^EzVASW{JfxtAsN`7^$bP8yi2OkTR`(1fbj3bNl z?^1D7a%7G`NpfWJp=%RI*2IxDab!P)#-IWqU;rjFFr9qLF@C;2o7XX9)><#za_ fle#8;ZAWGkzm~B1Y~t5qyU!+m?Vx>Sj9>eI@)2c^ delta 71277 zcmeFa2YgjU+CM($+nkMQ? z$EOZ&SO3OOMjWkgOm;v13%#n_r1?L2_l@rFeYE9-A-BJJ>Y=Gap8Rt5*qV(;{bA;- z8`AQg%BdY6_~c(+bC+e6?Y|s7{l4OJHm^GWSN*nKaew`)L(ZIWW^w+IL!Y?kp!O%9 zd~NBeSB$KD;l<>X`gE0!~yLNTcnpY^$Z2mR(5dNprOMDA2fXMfn|dS4jRgWKNWs(*2>tqj7_jQoVa@GlLNIykxKIt<{p?y z8clgxWz)pSz_Nmwt_tjda>j~gx+WWIFsAH6F3Z!3ZT6rF#^u^Pt%uIuYI;91pxuAp z;ZWRlmo0Ou4_)T0D_h}+ra?x*f&7b<+ldL|Mz2qFq$La%n(5m^BgYye59Q8CmxV*m zltsON1>tzFXwy|jue_Hvw-0jHnQKvL#NV49F^aX1n_e_3w5?5_89kc27HGwq&epCT zZf(@Gl}(OQp)G6b?=*M#UA@t=c8cRUGu;@gH_UZY90v2X7c^~m?$Bm8-5z~jyL|O5 z_lR)eP|f|sVd1jpZA-h5AuH5wLi2{s+8M^`QN?*7?bhbn?%HWu)8*IZHa*?xx~8u4 zO67$;wcMr!otG7!$NVO9P(kl;Wfqg=@LpO;(pkys9--Exf6zOWA=< zd5cEL#=e@X4VO#$q9zNv#@ya2YUU8n6!PYN+61jqZtaIe+Lu>qWle{dkJNg}-do&p zP0y5{)pSb5(56upW%Bv~+HZP_ZjOgC_x(fC_?1`T^m)lPK6JX;@Anptr@>w8>UWH2 zs_XVsbY<_A_4cCQ4_#E5)c&ifwz9#z2U#1g)ikBD+v+bW?~T}vrh6u;!ylF#wz|ja z?Chrat;dG=`KC;LrC64YKv1YUwy~GUxu5?w6fKF$P+o*Uz?246_poW;kR2&n41&Zv9PH3a-5iF zveOM$t8lHB1~9~VP2)xvcm0`iX((WkrwFBV@$|_ETwbPK}l+6^kJ7(E3$2?y|EV0z_ zrd;7>i`byEur0v9#{@BtZJITv$6=F{t)+^Evmw0+%B==5ygV)I1crwg(6l~zjqXjCCHb-TtIw#Nr^!FWW7iwK zbA{ohnl_Cs?(mO@>c2vuMy_n|Dwjh*j!rK;E2Tk?k7*zmY_U&K$d4uxeO$W6JiE4qtU zlv_=?XSUYm+TvwpPllP#d98KK=6`J3K5nD-WYdQ6=j5#m^3HP4V@=~Gv}kMO4F$2u z1ul53H-2WXv4;70nIj&$Ty{Dk)?u)>Ca4a2rRA$t&il)B-4#3CY zdM0UD-Z_34ey_@wFOSH3PKZ?=&u377-EWv&n2Dnn80II!VRv2b@>^83`c#ZHK5*(H zAAB}n@g}(EgO1?S^Sqo7X0dQfF@_ez2C+jeD#|Z5eX}f^9P4UsJI)m!rCd2-a;*IT z9%62v2X)Me^)rByB;EW&iTSwegC9Wv_;2M6&_}|4)YANT$m;cM#QO2#~w32Z>nPA zmJ2-7oHW7qrZlZNW>Ym1>l41}dFtf?Ml+k;$#HBUT6yRY+u@1Cgb4@Dw( zhaz#9wmSB~-*TF@xE9jFm47`jvLvpR$(}jde?nua`WB7F3se;rXfRpIA5a`FekIpI zhtb~L|0;~UDqs5+9Y%hZkG!94E+;ic^O}dZ)1bzzkWP^XJx2B~(!N2Fk=u*3JG4f5 zd$IPsc3JbR_S%R&>N1|M%Uo)=QDbtX*F#&J)nguLtHX#V)U3fzBpqgi7HNk5@;T`) zH_F_;+K}Cpm(OEu6c>K5yrrKuUTH2PeXXTh_jaf)r-Z~aGn-DXIP3?iE~ECSx-@?= zNQ3T@-l@AxjUA_*<*P2@Jg6?yVh3r{+G;N6YOyK|X?DNyKD1Krr_D2lYbR+THY6oC z9-|Ko!c@S%zV_oCk?wU+-9-_5XWO%+(WaO-A+CFPCt;L%CZ_#A< z57A`!btxAc7`JxDiZZt5G=2XlG;McAZa+gmcg^kL{h#ofyTT`)w?EXcT}nG4bnX(} zFr_&+@@074TZi7bWNxIaiNBjGhh7`0*dN*P9opVNZOLT8=j)T@ZvIO6YK;=A)t6wUf)srRvbIAYY;11@nJu~zarN@qc&q?Y&5UFNu! z=nslNUZtqFS|wvX^ID*vZi_N;>cXRfd5KU<-ZRUf8uwV z{HQdygS_nJNI&fXdH(g0GxI-O=~!!NA-BR=f7UW*_FtCC&##aCCCo0x`sx{OoS;1= zdsi7PT|Dd*VWt(Jl$bdZicB{v6Tu623@< z@<6jO*}@>Tg>u!V$Ot+5mdFuZyoMmTbPzBPHM&N*F?sJTk$W6|X^_^X(%BrDB>(Hy z$Xt!ds-=zGmYG;(n!ex;o@ez2qzHjE-{dvPjR4><#St+^ke@yESRp zSdcZK3B~5-4a*`k(EhE>hp&j#YaKkP^ic1Qii*2ba;*8~m652Xd;Obdw>L^dGICes z5M5j?tM7^&u8Uc+{;tRk9a*)C#jXreIZDOmW8}Q|BJ1Qo?~aVpyyV?fxuB|8{-%PhaUvxAHW zgHhbBMvu6E&x4WOCm)_48RLl0X8NO%erc}0zJW*$@VL@1znG)B4?@mR`jKzpu__Dbq zX`H6DpA)e3Q^CNvS*5|6FE2JQFvO_lyN@vL3w1a=@J}hqC#Y~u2lxhQS)JzYvq4GYYa_6P@1AW&O@LH zu;HN3aYGD)*vxRlniw*yFvRI3P;AXx6G8@iI^;K5MXbuGur>Ql93)lPUF~i-DXDm# z8x@Vre)BMx8*}Y$hZ8Nc-$Z&VW)HM0p5?}ABujrAa(lwOCC$3n6@?UNg57N`^F76H z;E9Cz%^?iS@_6SF*4(LTo4QhE%{$I=zw(%sz~(+HQ{D|(_Az?70sGjEBOpIzb?CXK>~-+#R@2^7Zr^b)@?-t>^4Ce0^_ z0?$n2M+HwK-E{R(+c7YG4IXSKK~G5J540P}0U4(2h2v=Gsydaa1Gie(`E1>FP>5_I ziAe+PR>aA+Mndmu+vwo7_M~jxZd61X;e3SLw%s^=)H|xCt)?*TNy4#^a4Tx){Q^xx ziBpY{9O>kZLSKnO@V})*@ken-IJhoei1<^h(Z^I6n1f??i4V-_teT0FccvBoY?5u@({c_Le0D+U*MucTV9Tee@pi$Vj zr`*~3?4YoC2@b9>@H1_k@`)FbSzynQ+ajhX>GW^08rD`^m`QowBC}7bwVh|$p)p1h z`P)JrdZ3!-Z2W3JnPS^|*su}2mVWDC4}}dD4qI%4YCbTF*+@x0jUu4jWKZKqS+-J9 zohXtl`*?jD<-)ea0s@a3u=}KZml(R7h z{E>gC-I^mmyV5C{n9PN}dZ10)|BW!Sb;uJ(W@0V!%o7I8W}=?y7Q}Ab_D;f1%x)tN zsr-!y8;5xM~rxI!8s56F!H|^5+TRxP16(C%?Uo;oX{==Ik>1;3oNEvz`3s z)lN^xMl&Szh}~K&dtc)Wj(W!{=HbU{a%0Hs0BKcsjZ@l1U^&oQ0OkR;+o40T&PakX z&_?;YYn%b$BwAK(zQ#E)Cp(I0(IbvP6D={jYDdVmOU$NJB8K*5(;edM1r9rh&b+yH0WGu_P>*Bj{_;k9sbQrqy#PT|WayfM?Aa#_8R*byE_24zbmyO z(^KL;JZHCXA|K%f%acsAq<pSHsFQ2TE<5%bk+c^YdCy}Vm~=UTmW?_AmOTB{=@N8TTd(iEu(7J^b{v-5eF(sHgxJY+5P_Dr-JxxJm=kKYw35px|v2%2H9Q?#Pf!`NP9j?zj z)lZn8jfkXeJr9lS6y2Rbn%P^y0A7oLmn(A*Ow~N4yFD5A*)^-tB_ds;3AC8^`b=Mu zYTJ^Ha8Jmob08&KVPvl{U&pdv;s#AFt%rk2QKv?E^BkvBsue0Jjdr#`wexzkJB@Ju z3pJ9xU#h;OkxnDr!$O5dIKeT*rMf#8;)pF)eU=C5|I`R!xRAW!EYqDhibtp)X;Z;h z4Fh(zG>jGG>7}*Fz6UWAXg-BPTE+~kF(Vpy%LWgI% zHmKDB%qg{)*)9rOYdhG$igLn6tKAR_E{X1NA(?rkYGzWwsK3(`5AK;dVOwzx_z&hb zcE@0qc^j?bNGqa3IdaSb+v?%@X(r{esM%Q_d970%=L1c59wuHA`>lC$gJYH$354TE z%T*h#gL+u`NS(w&bf#MivxAWyMd{gZR1al2mR z+(F!@f(kILTfoEOw?V<>wy0S=s1dnkXn+Fdl7X4&GhM5vDrt7yx5C{Y_i&#hU!CVv zq#$_B#%V{}NjOEJWm1zu_`+?9?O`Z1!kyiQoO?ox>nTiMn+n1o0aoHG&`j{dFYudU zQyiyQ!$u>tEI?5jyP>O4;l=?7;{k8=U#jF$K2^$RtuB#PM6l(u`A%`3-3vv|tupNV z<83QfGaBXV&sv@2GtXM#*c^f3h%Tc1l5%3qEI6nU!Nn33p_ed@AP(=0tVk4J3WfBt zutjqLyF6@(UnsT8YhrF|FM0R^r|1MS+r1&eQC++D0$&+S^hR;PA&F_DYztLN07RDQ zL3EOBL0w3cA8jXmdc2+X=}+v8Pp8-x@=lz8ik*=6E^vyg(y-D#GoOp%AsY{SNUflD zUX?*XXZOZPfd1)6fqnfB`}ww=rx|Hk7dMN4X7@qcuxUIwU(~9kz{?%9uKa4D(;?(d)MTecPEt$DXP21+Q&u3p zu#UF$3MVrR;q^D7Hd>gLG}O|K)I<2=XDC_8X_Z2ZL-H4XHbf$$%_IDYw;@a*F2!kT z>?YvnB?EC;CJay8Dc`NKIz#^R4~CmkBYujn6Qrq%RBCaXZ_o7iOltt#Aj&fEv-){v z0>3nVjl@UbDK&j#N+LgmCpR^PBOTb&_zCpHYe0=zR3l99B+YtYVaNZe)w(_5$bJ$` z1u#?7Q*|gpYk$}WAOZpH20~!LoVsVS+=k|-&)MJ>YH z5J5LCvVE^vtp7cT10flphHhtSA>ly z#sTjV*i(>fB5ZlU{nhpqrh8e~n2o-3kbW85xyIbtGVdqOJ>$F_6(xNow^?A$z#MB= zX6N#iju*@NPq0~FW?|+g^7HM?3Sj!8S^p_Ei^^NBv+AQ5giu!?dj4>^9I@D{veSJ% zlSEoV4w_*ef(9FOlG8c&cqML2t16w7x2?5pxoxpkp|j)VBQwlWEh@Ku?38M8xqXJ& zy%({65-pJ^7g54aGikcF*37i+a5codXL~fWhjj?Vypx@RA>Ln9+8GFlj0aUeP|&L zu%7Fb88w5S5G8uPi27m)tWQdbFx7B=4e@sgS56tIcz%X&h^U|Ta*D6qla$vqDzwQM zEm_iX;S{GJvWeo!iJOdKNJx@?!W@e=gtek7+KNRAZPnE3%sc{RpYtHokLc%_Poge! zV2=*){GwV{ifE=U`X5=e!oL=Njf=QW9{?l~mXrlbqZZ~TgLG&i{UpL#u+OFZDnySc z`$q~#1Hz!hRD(eh!jlrAgeh=qnT(%jc9egc;&j%TF2}(#B#HoOcv1-xI*U`!&>xL) zrn4MsWNKXR?Uei4FV==z`_s@qZ?l0h-A^8VzFATB8^tae_z-lJ>Mb5hxl>W@T|-Zv z<_ved2eZNDEz=wO6ArI%#I;(;pKAUbmt;S=DG{bf{2B>C1uq`<^X+tiQM#t(NS+Lk>l=)cRB=3 zMC+K^JuU7`Gi z5WWoQ1=~J6va20F@NXWs#n82|^%ytg#}}JrWv!8^QR;s7mA@Mad9_sSA{DElCO71|)VK`{?Bhc7$bZ#cw?>QF7VwNhCEyNwP?SnxJaI(sC!fDP>y)`0dpXQ(ezl0+F zmN6(VoBSN&V@h5we9P!_IJQ4_$`hzlxX2W$zk2dL{i_xb2rHAEiMql!~R9h83+b)btF0x$RxZ&{ix? zC^J>~YTL5HSe}mB8O)!>p*_2prvjcyV4ku@VWfg4h;|odnke+p45&X(j>a&Ddjgd7 ziwtNQ)EWbdf+s*Tt~k?7!;nBG8BhxeST(TsLIBV-Xc{!r4gN%7$I*zHh6GK3W(L5Y z?9}2UU-Ee*QSa#)xFtv!CE*8}0L_%ht?wBnDT~rN68@mpIQaL0KWGLt4NAIv1~ftX z{&@IT!XGq&6|pq|cF+W91~d(76(Ky?Q8{1bsYY8*L^!xxli?1U0JVw{eljMF1PmEC zq(Q9{;em(=&;(Y_2}HC&GoTrYK>h`=lRv2S6T|~efYNd-0oF)(WsXHGu|U{l&H&t> z49v7jXbjA0m|GW&3<8lpx=@)d)I1rO6EHUhW?ELXX2bME_(ef@dGFayr@Zt)u&U0? zMx8@yu`tBj2S)M0>|q+eUCry(My?Lqz7XoLjZ|73w(*t9U*^tmJbTUnRiQ>%ce~Xm zFVPG2>;Y*NaNMlTsZl%YHBgvGq8=7fv?juRtBNuX?&IK|O?5i@>P>9+bZg|1 zieYup>0p8_R#oIS(CNe0>2HE|v#TPNa_YHGsm>6%)Jcz>0f>dc~3*%an>hfLk_=+7OJwp$JnX7@vd`8K{O>yAUt zw@#wB9LC%@@~8Z^e07e4y!zLh zE#U+u@?Zp^e^Nf8fSl z_-3l-v&`s)FCTl*myd9VCgQgP+ibc$o?%80oTc{&zMDcR<;njrk_VB1Z^X}E99Cc! z)3Kuyqvqxz9B}xDAYVUgl>I}YB6HY#&014zTbos8J0x?gWdWx^U9aO--R0m!B;vWbq;0-F%EU3Vn{{uk< z=hZo2eecTj-`%t0$a1)MMl z1SSCXfItNtlt2aE8}LUo4hjXs@Lq>MXxm-FBMcM;J8-*$3a}^Tg9-$I3Ir-(MB9Q2 z7`DqB0}z27Lz#hCfL`f?44|I*0x3!E`wvtgo>$F>CiFoCbXeJl<|KO>zbvSLJ&U3M zR3M%~y}t*jfM5LGK?R}(dFG;>K%sW;6R3bcj`DwZPyxq&|9%7&@G-&gdN2SLwExr? zq~EW}BR(}g(U)s-#6OLb^qckoD)5?Ae*jca^e>~2zCde!?Li!wIM`hwHfJeKp718wpAP znxr)*K@h$PQoyj`{X-xH1QGZykb=#1-w{$!HhbS71ydI98>B!Sq$I7lPeBUAL8{ZS z1l|==zyL?e3OE0d@jx{3ULXa0qdL=bAe9nyKv=CH1s+D#_ktAgekfHNNCEGQery9N zVDNAK9*_cpDzpZW0QNcYT?dwYcxc%{g!4Wz&;LB+le zQoycOiSG?kAb?ZY7f1nX|HB{!9(HkXd}YvX&bL4cSO5hejdE|00v<(YAUW$BAO#$A z0>d92Mf*s_d(?5XFm^x+PBpta*DFMU2wfsio@ZYA1PHhnd;uE!#pZ*3!0ZZ?SDBxErySFtsDr$o$5CA(8q9BV@NGL>s z`!lMX2b4e-Q6Mmh(RxC>uU3fGZioVJ;ocDi9B>7~iMCY~c0&}1H`S5Aw;&1xPyux6 zzaGuL9-57JnHtEuBMSIM%AJm+81y|t6o?yCm+cKv;LTTQv)vE{z`A`iqCi}zB+~9u zhMlbnK^r$V3i3k{1*CuZJl6qx16ZtQ5e44UIFbFgBMQVLs)sT_6nMY;21LQo_PM-jLWAo`TW~C#1t1Whz`GNz1V8)&zi$T=@P}2&_YYYQkCkm8;89Z}$&qvWXfF6If0>sIWGWDx~oyW$x3F9;KeJa)DcmxL%_SNBX-9dcwg;$lFBYnZPwZkGIXH#e+qBF2$e$00;Cpy3v&s~|FiH0eD1Dz z1Me!r8&u;Q{@D|q9v$`yBWMPUpg}7j9iJG11!w)@NB!ral}X8YQ*D|u(A|&v=kCg&KOXh}pFip^?@H(T#Kv@*lRfL_*m&RLS^pvS z1KH4Y)L-h}r>tK)=|9fCV@E(7^dFGBLRkgYE_BZC$=_XI_HcM@aLnJAj`=(3=lpLz z#&DLeI)giy;$+d4A2mE-( z|Kk}yj@>##*&6Ttc*gGo2P`bnzT+AHYPD+G>lyz8%Kv}$8UM+2#$P1)odD`4<-O+u z8j-{~J1vBhP`hnbXV|jtPOH=s7vUCOXp?fmli_ZfBOlmmbONb5&pGbj3lVtZM~J|W z5P|qR$O!Y;m@S+r7H}oh4fcCGa`!)A)DXKJcu8+XpVn!UWFH`<2dBFadGU z{)7qeKmBl+fN1>&n1I)!U;^Tv-C+W}r^=d@d^=3Q>!e@;d{J=w0KdI0PT-ybZY!XG zhp$BlD8Q}Y`T>5ofBnF)6vuZRbh7BNJwpY&x#}#_0}O!HfobfzvL}KKa2(6*_;e26 z#EQ>@Z(`5iXQ;qreE#$G`v>SVMB3xdLIr65I(t}^rVlN@$NdARjrM>6psMbU6`=3! zvd3wJ72w#^vT?}oy@T+e9JCQM0aOh>@B7N=;0icVU#(oP?+z4704NFB&!)94Eufo0pATP z!1sa`@PH8@tN{O>SONAuumT*XnS>SaeviJ`N2~z*epmsvf3X5AzzXm-Sb>2d?>-+a zur0(DTHvQ4z9+bV*aa@oJH&w(z$FAREy@GHfOmxt80ZjU3NdhGh3stYEN$8qG{6UaUFOm~1Uvu@c)wDh0lqiT0DZcZm2&=9!Uv#<_W~MVdjSm) zBqu9}ztcSg1PW*i8eqGD20Ylm4`{%@zaRh&hyXOe_6KNy?*z-*WGaXybnMDZ#STT2!I02+yyAGB)EDYoCONp)&?kWn*s_f3xEQ3y8s1l*m;oD z7AU~}x(`5sYjy()01U7J0*QaL2cQ7300a~e!IcKP0tEm#+yNB0Ft~c)gJ8_!@9V;{4GEMwq#eJ0KZ%fUU7r!N;<3euO4U%6o9tpUp;W6 z+PP~B6yRsKxq4v1o`C}1w*dthG9xLpJ5YcwXCuk-gMk9$RWt7mD8O+e+r9z?+Q$a% z`Q`z3%(vV;@Tlq_!U^z4z5yqIn+NtcP+*vA?&Hk^cqRuRfjt5R_+4lv`2D{D3KaS` z59|&Uke9^F1L7jU2GDh?J1!f5`9FXS;0qKsz?=Uc#Rhl{3LC&df9PccxMZ*`Hh`se z!v>&rgUbev(WJ~V2jTp>HOK6fVjcG#8^G{=JgpQ3mQA~31NfIpu6Um+Yyh93hAUwM z#DqXXmSGK5uv4V}kH7{9JHQ5b)AkEC;02?&OL|X-|3K{DN$yg6(Kv2c7B@hcf$aSQ z{Cw3;`-}(pSsFNoL^=P)`v?5REf%=n|K5Q?FBx?2fc7D-K53@UK4J zwh7Zvjn6IV{sEX1I6b6`JLo0@|4s$i8}ZdJJ|+y?xKm)qeFeCmAc63W6d&%p-BZxr z2k6uGE&&H<;k`%TfLyrHD*f?#0(@OX+ahcquP0#7?g^r>&({-dqFV}Ld%m7PEcss7 z6L8#TM3{wdxSoLSN}_R<9Yi}Y3ziZ{KVDCOw)ydTg8$t01RMVD^ss9bY=QMww-b2h z{x8NYh^}g+eK*{K*IC74ZEy<=u!23_PM|Yuzu*>_t1{giZb9cC|9CmUkCzhwu<+yM z1pX}tKj?A-@BVKFE_kby|KguSANn`lO)y>_{}-cuhgN8t{yjVSRgMkdWGxhi#=$%~ zTQ>g1IAkyP7xW^;+dkc2AiHig=u_{#z!J{eYK+(kM0k3uah$_~y9)S3bytB`>)%y? z2kG!uX!{}Ga5I57dgsjqZEqtGf7|Ugg47xRw%Z7hSKHeN_Uq$(vCtTc=Fm%X^M=yE8%|0sfdw0KFm2hsGYAlL$)4eIOd&Vsf zi^~|j#L!Mo$+*1S3pSaRwuGwtS`%mdQnh8kE|Kdp?)y3)EmyU=C2=+y&sx=Qj(T6F zTv07wX?0iW?6&6F>)lthX%3zZawc?jYD%U$&f^FaQ;C@6j-4p;%$99+VH32b4zIW3 z>dFQ@PtJ4kB>6ja{!`@w??7aqD)-_u-KQ_AH)`q;hAv!dhu&9#vl*Zoc;q?(=%C*@9=5 zaD{VA9uKn?+mhlXw|%>e#!VAX((mxe1U_N%k@wfeuG863%_sfQJwnqSk$1oBo@_s) z8h|~}{Mp#pNm`thnEq=fCT=6)UE~#iatGvmncdlUuBHl8=mw zmF8iKzp)FN@>Z3S*G_I77wfNk@5++#vF=6Q8+eY_!<)(;1R}kuJXknho}4^BHdyDI z)$ORWKgilw-R^pAshm6^RvV@sk!8KLA==;NrU|iej`wl!;4fIAw|1QU zeqjAj#`|bJ>~{j|dvenz_Z3~NmJh$?9;dz3{Mn=!9#LT}vgCEQPw4S0TsgL{c39^F zRc%|aDU^LtS@aEBK(2k=-O^iJsUBVSa7;k`?gs^LP|0{o1vSM|$Gca?`)jxyC?z)> z6B~)^;^?V*Jklj+ZE>gR;^XE`Tijz&gyUq%@v(Z{J5xUVmV2=-ejz)a5bFqF^O0}6 zXWHx>^~}3_7t@jJVkv~ zZ@;i!@D#Q9SIYgMmW9`x7^^h3vGh8uylh%*SYfs4)>LAEpv%%YrxUn@N7OX0pBB4E z)4Ixww^1$D$yc_yt3uw#S2U#t02xr|KNMT8<;v|pi*?fT{73JbZ~CkIvvy6f(Ve>U zlT>xGud45O<34z0pxKk?tVKUQ_!*WS1fo|^ZL_TRX_85{S+QxjF_nrgr_!`y$x zoKNuIxIa?)c;nO?_eUtJ80)`rpM8*ew>R$D5qo&!eoPRv#((2}q_XYu#(kA?qbJ(G z_QpLA{OEDm5%LwA#>v|mnBn^lBo-Q}Fi`}hz-R11U zSZ|$mYhF_rtJU$gSMHiQFAVy#tdGm*9Rmiq z0J0xXtn&_dV!eNfx5C)#8|!SjyrOfgJkIk~RC*p=uo=c>vb}FWhlmgDcP4KD92s3R(>A z*{9a|_DIud#|;U2pGBH(J+6a1uq1}(0B@4BN@5#yZ+>%aY3vg%Nf*B@7Q{`;VZtMUB$V?i8*B_Wx8eq9s=AL2}JUez^rfua3cmiLVH$iBQy zw`XUn)R&X&isqAg#+oBqfh_7DyG1_UKlYan&nQ{@^oXgBhdXI0Y5#_QOgaN%2WwAC zePFDA?)~1~QC7ynuD3KgzHX@_`M_Aeu8;4G%jPOG-N-4R3-IZXs2iK-4U9b&J`y7E znL+s05=zjv^MyHR0<+I6b8N0Hb2OkB#Th|dOrvZ;SBH&I;k{dwJEvPcv*yE^Zy6Gs zrub`U3~Jsj7uZKF85#>N#QHaDdAJq4jh44Vn+vo%svxE>=3Szc9!x^ts^y6lKTyky zy}fT*p7{9x2U;GF=@1S7OvDT9|rcnkgC_+=I;e|`RXS3PdfWGsd~ri{AJShqMGaiMKA0r8wSwxrfZ*&ns=P09Zy=`mD<@#$-^p&lsujPLXLae zJ;M>_2G8=HCGS2V*1aP??CWYCKkEvYpDy1&AvQppv_sG9&~x3cYMvLUeX-ruJh^ak ztaQ!0E|k1lrR06&4lCqeSMu1H=Jg-BQ1VK5Rr2^pO34!isiutsy6QYfZvVvXr04vo zD(*a7}qx-7l`7h9SS-y8APb}TD zl6P!T0YkL5S{_@L)$-IE^h@?d%WK+jY_Wd*epK@KjY`Sm^ZpG=9u|bYX2z!d-&67y z#-ZeS1D_bOWMMq`o~bmx-?#FX(5f?`)ofg)@IhlUuHfpK!Q%5O^w=g)?2(j2+IBHmx-%6QKhZa#LS_>@TK zcy~jNmhl4|4|np;tz2u0d|5B!BL@R(L3y8pP#(+!X^DTO=5_@{gDnqq)a43vVuelP z2t3Rky*@tMph7w`ynCvIIC@1(!PWc0T93u|tV4hiMY8TZGFwSJTEXapYnY{Vm)jyJ>Kx=~%pSRY*4`~fa) zrfS@WCSv*0IXqq>KRhAq%9Rhs+f8F}=JrRg-h+Gl`uAPwoQ+Ut;*Q{cnlQHZUE$md z`#p8#zI|1{<<4JV-+J~6X9oNz)va5~qW2;!g&%+)vzglu>Gku}t<3E2vj6HhcDbOG zO%9hxu_1hw&i{c6Ov0VCR(a9_{n+M#YvRuwiHm@TMlcX;ng3p1kt|&pkH~2oBb_Dh z5P94^s(bjW(*_Nmdh*nZFOYff_4#o!Gos`9(FJ}6gJHa zl?^@m^oz=BFPc$Sc5vCCp~D9sG<@)ZWrGI}8cM~cKNWtkve5sw8{kWha{7ht%8nY` z6XfzKj|S7ByVIw{3`8JlQzIC1sVCy{VY-oQoghRsuce(}r$1`U#VZ#sop z3l8TxNd9i#<2i@jn*8-?GtWA?ZKx*xZf@I<`$<@qwK*+Z@?0dZPqP|Pz`WX6wIbV=Xb z_D0CGEoRF1&noVW_m6GwBS*St7Y|J-clh0`0-Mj2IV^Z!v_=tmGHq))q zv8BrZBgWC8`N@@0fqO4tH%#W44REiaN2S(*G<3>veg~pBk95*#m>v(t`(qt)Nv~)(`PB?5u z>8NG|kj_L<)AMm4ikDW1*5E*t3PK{a28olo2CdP6j7{t$M|!$e4Kg?BybxwO~y0TU*GsSZWt zkE>GC?dKWzTlgiAFl7ey2iS5nGbR@cPh(Kw`~tv@UQx07xCl#WEqBsu@$^{zGA9Av zp?p$FDiQ7^ZKOm{1A4tLibP#1U7Nz$7LJ&w38!Y7Yg3$>Y0T!>8m4%Dji-7!En0QB zhSCen4S}ES&^;m5b_TGnM1HMp_jL^uZl*T{{hv=mftnKzYnMh_zymNFiEgmdnRHJC zZc`A-EVK4!j``G-sOKuCWz)Qz^vH9fnL0geRWFZP^{bo)Osxrhl~Y6X%6lD?z7E64 z$Sgz{bgSP&`6+H^9=it-jWDxtX>T1EOh3gjC*I+|Lc+k9>1%FxGGk7SX0%Y)dg5o% zOdjZt1Q5S*CHx{`hA~a?6ZK1-boF#(xI(3Y!dcbRRN>mj3oVOgQplK?iXxg~nHmlL z2tZ$=RWj#s-A2nK-{6r1D4varCaR`I?S8IN^Bf+?Ll?9*3A^UGDR!$A*n!8ZbH1Ol z+XGx9iFme$N6f?H3=@1{PMTtylg_X$jEa=S(njV=VVeV}qvuF;k! zyG9$%TIMv|i-Le@yd!W3f*;2ZvV(bR@j%%+FUQWUGZN)2Dpsc41P%fvUy<8Qp1UHq z{cz%G6QacgSilUqMnebCjugtwERu5?fFkTR=T+ZO-mLj7*2zOb#i5 zFIT9o#K9PU-4VX4m(zgsEy&3V$|W;awef*I+nTa6aTY7(0bs66|55EuUZbY*UVnFcvMF;^3q>D-<}@1`;| zP+D2{fST~9`Pj0PM&;Vgl}%~7oJaR@1l^>DL* z)gboLkg@xVfufm$u-Tmo>9xP2~-NKcaRuB$$+4%KW1?5hf0>W?XC5*-<_Q&g*%Wx@nJz|Kq+)LLMeX^x3! z61(Si?9qZzkU%Tc=-f0>iDW(V%@nTXTs+K$7J;9tN+xC`j*hZSbm2{1j4mn6ETq2iqm|S! zfq1Ivi^kUKA`PJC+N9AE*v)>huY*6R?@#u};2+q{{;)p-e^B3_?9akKu$u#5e-8ej zzCUPt^LYda986qC>s_ljRX($+xLs-;c)p%^-9M9LEJ?HKatMs&Ya>di?X;7C^E#>6 zJHkVFX2f#Gs#@+({kBU2&@*$;9^+x&2y-@UmW~HA*6`)g`O{g-j(f|TaRuOF{H}eT zhvqlM?QvU}J`VtcoZPO?(_cMmT)TyZ$W95+i(&~ZWJ!1=Hr^LCsZS3=eTVGK$Ye_m z6PefG*MMIOer61I{8~t%f=X$kfaxL7)F`3Mrz)Xr3E}CBvDuIY4VX$O!5DrUw{d5~ zLhd|0kvmkwIDT~ZdJObwI)=b(eJ$wI2uJ=KU?xd14s^qLh*!m(`7nEsdgDQH>&Hx& z5_x(M_s1bjoX+W`}k2~{7BD<(FOfz zq49r(8_eS?IHZi{?sVsR3*<2At2F1;gqAs}9Cv|9(>uwo@y-JOsdO^WgS&^<(PA;s zf0-`%jYt3IpefOR;cNoq+r*#WCjJJB|AFZqN%8+~y5u(>@rft0g}2Rk%4jJlv2!5d zYEVFEwBa4%GO{;COdPTcTb0YxHN?HwA9 zU)mZ_U$w)mQv-kBjDj@4Y(fxaGeMu5^AA8_4-&?;&olkV5HmMkAi^69c;xBlMd-*1 zWiL`L}F{fsfjnisV5N_S;emLSca~;C7naC_#!b+47N-inPJ4(oJb7FNtfnbmqk_ys|jC(vRU6oSH36HWQ0@DreB;$2XP zP@8VR+kP=1YyDb|qHaI|{6s@RH=wD%LpSi^psS&M_?1jiUt@U}!$W@F>nT?yR_^z` z->2wjzfaNcJNi^-s!y@Tp*|H@`t4{j=ml&G(m{G0H$m^{qA;}#(xSp6EmKDqp}SLl z(@=kBn+A#dO#@G#f#63i;{ohT-Lp$(U?4M5sS3Le86Yf4KuUN=w^b7_AT7TOH1Gx( z6$S8o9$+aj5o%5)y&4(~UM8l@e3ANC&_sRjrUI#x)=N+W8 z8|QP3f{mCPEDX6c*1T4^i0mAu!_+v1eBLomH(Ve>nXcS!xqycfC=6Z+57Fu!YYW|c z!}A5oxDc0*_RbxaBAm2&P1hZ}BX-$RgXd8bU}3xN4kuYW-)N`?J#L=SvhH>#x%gVc z90~fuT%+c(+nm;;<{AwnL7$&vv^=)bNluz$n4>_Sn{CuQzQVC5&NdoGfj--4v^<&IQfYVmpzN30V~u*O3f7GfMm5~)@mq(V4&|!Ub`1^N{2}??^4w1CPsM`e zcDpWeJLo_Hem!AZK3IE7zucjztlZVHb)#FZp(8_mR6u8XhR$K${;07o1#@*9_bL|! zK-feZ|Iy@M=f|%OXx6?i2%C*luhkjVVXu=PI9rGgqsAI16y@6;#C?vqOOETGTZ|8X z=B>=_k;1g_9`ugWXHT%t#LWAFx6iB|&hYgf#wev-+@U*BQF+ zeQCt1=u3qxyyWiO!ea3==S6Ji6d}JQg*;4>@5Kmku>3TnT_h*oo!e;?E12oNfC2sj za%EUG7EuHgoH8rMu4Qq%xKRj=a51#NV?bX3T|9h&SvVYVK#u{H3y_=kmh3+yx9IpH zXzWWOb&+F1iwegXOAvtU98&*9m|sM~OHBBIQdkN{VaRVWM%`i*ghU}VMWJ?zb1W44 zV~T{iua@p#~|N5C|qZp$05&L4!`>mxj=!oLWH}=!X>=*;`dHdju|9%ck#=q#g6xczjL!P^{VtZB^M91Sv_wTdBwZ%>32Faf^MxyO=XP84t{pz`%)w_;H49`} zeqqG7qNc@?$F;}v-hAb&ZB*0K2Oo6c$vZ+)W$m3#Re#bu?$dGAx11{Blsh<88l;us zUJjpqf`6PVyS6@QRAD8#x9;O2dva@T?iyv$r! zSYE|S1Fl4$Gsam6pFpV`lwBO4F4WC(;|@AFxM)|dO&1oY^oNAO88_=bo*%8sWnqC` zL=QiPokW(04J`U$I12ncT^J0b$}{l894(+Xd63Gy9R51O^Rb3jjbAR;s{{*IA#4?^ zi`0Rt>`_4MO9(--Nf_F85jRk9w;C4xS$z5>Cl(cUinI4<2H;Gq4jI}Da#m5{iCs>t zGibd@Gi?YV#g~s7blMeOZ(9JsZf`8?UHMqN&M;sXf2Nk<$P2|q5d~BTDlP-%vZ}bS zQ=xcE%`suj&EdRUI}8vAZ@zqXVF#^adDJ`#TO)bQHh!Blu31}V|9&dd4L-w>OXn0G zs61c+z9DH;moZ(Rhyygd%dSlrX;ghIB2~c# zpLP`N9{ zCxF_9?>4Z#avL~lr(14G5bpRkZn?G&=}X;R1yp_=QA!iPYBtr@@FCt>l!V;s%3Oq< z=CF0PRrT?e;i_DoimbyES5&<^zaT735$h09$Jc#23RN$7q<)|m)=@C+LS|6~7&1Yk z1|KN=Jx-5!3Dx!t=yy~R>^@KvFl4SF9r_ZGJ)JbzW^5>8-qX%y{+EHw8wba1;Go@T z^UU8#HE>U4WaWnmYczbQ*A3x^%# zVSk=NSXdJJ6kBVw8)Q9W8w{h6w(VFw&R)tLyAi{~`lK$L$&(LO7WPiH(s02U3}24@ zdhi<^iDe#z9zIQ|BNo`{ePdcd@V}>g5J(b3hxQBkV8p|5Oe2{=TLYTO6J`RcU4o9( zND@4VgC*$PnJejd4H982&I>+HxqLd-&3=KAcpBq1U!aZkwK-OOuAQMVh(cQy5`PFc zW8edl41MSI7aS(QEn^DPdUbps;j8 znz2%d$d^006dC&;RuT3yEMd+=VQAlrVULkMKIFJ6fFfGeXjSZ?@cWeA{}dGQ=@fwS z)XGMnuW%A_@6PaP3jZr*&(J;$GPbaT#BdLumZDnWvnua3tQcu05FP@T;Q6(MJKv<- z(-eV93~E6J+f*pnZEVw8QDgvf64Xze-{D}S`YpN$bCy`C(o2WAnf%I(Eo#TYX~b`J zgn33{5!YwqbS@ocCV9Z@(=#H*Qvs=>*V=83n%xdXX7Y-0&Bq}g-2WqnnR|b+V)b)Z#?$smB0L~ zXCc0TOUwSf3X2@k7{tZxE4>O!hIu#Qv%cqSgZMA=*iy#}o(7^cMSaky*nS-k89N)7 z{8Fz!b0v>@^0r=ur6*We-6il#>DIJn zdb+yDl4hhHX#|$_euA-Oo(9_`*}%+5*2BiZHef6nKY1Q=_a4H@@w9AMk0h`$T)S>| z&u(NMHpgVMY}lY|c9%4U4I|0H;6OHkguOhD%_BI3JT?%(_xrnhWcdMxjk7n&mChMe zcRl|4tLm@6s{Z<_TBn^Zl54C!Tj6GChxdLf5SPBeK*4>TMp-HofdJqTavClXr@EuM z&*XdE=O&LS5~}-Cp$zKOzQOg=FsbCD2^HV>$Vt$?$Do@v)lVE@E)!ZrTj=L!!b8K95O6VxG`7*wwm_ht*F8 zA80&iN}`wJi2^;7VJD0@oYK`|7h;|;C{2QXML5eCfgf5k9l?IDh6mB@TPIwqwaI1BAp#Z7=6h)nPt#Tye4p3MSP|Kl83?Kaq8K# z&1e!gMvu{a9_cca4tZ)~rJg1?n>Uu2*}TJHC44)KrHArVRx%c)b%XethWrys#3 zI&m^MLUU*GK+DtS>|C!>kzOl7{9ME%7j!a|zQ_uupF{)oLh@+L!`h1s(^PIplo6L) z3#QFV#(`zX(sbzIaMCu2aLz~(NG?rB!CKZ2H$%@D->3#@ z_!+_YmC)s?CbMaF2F>8q5;endCDYJs9D79+P9;r40dQ#9?0b8@{9%*XqmBj#RSZS5 zXP8MmKT6MAoafM>I-DM}URVahHD*#yA_3{n5~)URZ@(e6D#*>VHSUfC*-C zh?E#5d7$}FF&JNrSw5|d5&|`Qh8668f2+SAh!DC=GO4iONK-K%K)g1{&RyuN18|MU zY-Iq?jvHCVlZrqkzy=DsefUv2gIP$sQEyem9Fm9N@WxyCFa&pa<8p3b3Q1KyirO2+ z*fG3Oa063Hrx~7x3%MG_Zy4)V<0-k|JacvzYxYzh39fI2P6g5|;9!tp8tbVHei~in z0F{_6WQM`d2ch;>ghpAFZeXsamA!7X%8$=8&q}?uAr!=tW*G2=Bq%skF&#HHGM*{J zyMkO${5W#Spvs)8!*nu3xtBw+n=V#`!F1~6it0&Q(0Axo!{9XGyI=2f^q@Q866jte zXyQ9Amq0AJCmC(HL?Cd#&p%88LqjQ;iaY)LL7irG*zEBR7QR?6S%0gkwQeze-&u~YOrhxo0 z*@>VKaVi{o3FX6E@}adqaF3H++5)}yTlvaG&~|jmyN*PfNZ=|Hn`?rrX;hh>*d|Wedx=`)7X5e5f zt7bI{N3(nhHOMfT4yU0h;ioAre)5l@>c=;Yz?_zvMngOu@fOaagcdxZW^G)jOaW=M zTN*uqBObECM;(FvpY@rBN{-s%06bHB+-4%t?sxqXPS*E z0ppEPHmGu}B>8eI`07(?!Y+5ty;7_28oc9B2xouq=q`>%(eJU;5ZG`lY*3F2JTJ$H z0KGFGn54Ta3mr6LE;<@*MG_sOtXgNtYu`qJK5|=V0QGPepeJ9u*t}>ShLhlY;2^Y( z%->eI#Rz$r2TJIO9m-9U*MY|@p3O7^1~kk@_Ccpnd|7viDda7em}TKDkknjs2Lc$- z%&%SUyu>Uxn^V!+d^xP$%pKTUQ?4ePcpEJU{5 z(aE>nv7AS~$<@fC`27RK!&@7~<>Wc${^{0kw|H6aHq?oMn%=ip%bzxzwX(3qToc+)!iK;7D8GET#k{ZqL!cw3 zG?|`{HlGBMm?R*k%PlpGW=kIs#^}?wZoe-Z=9)`6VZ{iHnUG(dYc{%#K1IGU*DTBp zUjz;A)sWR8OXitVQ&yYX>0*{EoB=3fn#nFgc6lh?iwm1`I4FQ%XE_}LeDWw#&FsoW@YwTjjWE?Ur>laE5@dxg#q zFn=1dPa{`+uP|i#GV{z7LzWtnVJ75|%aUc&J+e?X9@(Q*QDvQfvBjW^ggOJwikRxf zg)*hMkqVy@!F*&axAnr%QFS`(YXX>mCqJynQ6y}idgT}eTX~4odL1(iD4-C!>OKst zbVy(nD~t}md&y512Fz{v4WK9k-(t!rG8|cN>(n;;Uf-%yJGCJlE%n_&nbv41peNpL z-2rKYD$4WME%!4X4{gPZV>7t5IY*jSU^`U*e*8KD-Mj!BB84$|;BuJUwnCldiJkh3 zIlYJjXc>M5m}y;s#(n`Z{bH3*A(+AfbnlKBGy#6k<#coU1k8Z~pF+Zz&1XMobv)Va zfV4V5V=I39$(;fhzb_%*?fC7-kN7Aowkm`F>paK;{$5<S6wVv{nf8^o7hI zg%$ygyPg&~`U65qzz8!Rs^j~W%|<(q!_z0q!CZc9PwQWbYdC(K%*$G@cR;Cm~!S7lMYdf9Kw}6N0sw-YxV1 zY677`_d0)e$dHrT%yUY`kKHSJY`7E>K$Wu}xqjA<z{9PjL~r{HM9eVjZtjt z8kW55OJ++dPAd&-ryfR=QJN(35#MsVGg$!AbJ5MbwUmg%e*?}pTWH?tFvZ{O#REp0 zw5m4DRTJr7!~kSg*uh2kZO89LdM?8J9a~fJO50hxX;tXPRdyaJ{+AY~ zb){Z`4@-1mdl;Dh_#GA}47Ii;p{6(Ec?+JYA<$3{_Vub&tzd~(Qy8%|=sgC-ujvqw z^>&`XNjdUM_ri*T6CpJeklAE&K)5)=o(R1ssIqm}PO4#h?y7qE;p}Kl)L|5roW`b$ z4l(b?+*+@frAy4B>akbb(Pw6G+-wLt8%zypAhUFdSy4*lVeHdCgB%|tC%?1AYz)++ z;_7kZj9FVq4JU5aN2!t;;H`A=jGQH+#lCtud#O1$jJVD0cwhPBNR_Zrk zouQYtsUs~hSXdr3Mk|DWpk)cy)evk&w}rkAx?iU_D&oM@)7tx*K3ai^M$=*^4lN6Q zhBzbdGu~?dAKk)`OUg-#mgq&@U~(7=qaPlk9-Y0;4(@|r$dmm9-tAh~U#SUcdHChv z#}TIwuq%?qVHCzOhyaF4>8m#n>WjqBjeV$uzB>6*OSEIML-IyPPY_84+%82W-4w5t zQ?D^EnC`Tp9W26fXEA;xA=xTrCL|Qq>Ndej9pfmq+c)M$&p;!M%#BW=mYW-`gp)fj zI%V3pW*JY1Xt>Sd3dmS<$ZO_BE4>!(rWWp>7d_*eaa6LLWE+FWrslgnRAF z>2z70byZNu=MnoVI=POKf(VkXibKIdX*j2voKXbtP7_qZA53N%FzSFX5v9IX4L~F* zVcK>`cn6EL2KmXgW>bX?(=UxqS|jvEV@PeU#CFM?od)Sh8#n1DD&@M%qW`lYp(E{= zZG9A#SiSiH-M|QMfS!#ljeYO8a05z<@-Zr;etEQ{z7@PA>V1ZRk;MpJrw@Q`EAkFm zgEW~?4ZsZE#xm&pa#pu_MoO&m21V3&`l(%Rlhe3?fhR$1<2ivrhuDbk-Dps;DaSS zT&GSyjfrns$1;JQ?Jz;NZ6GZ%$bO666?(oHb-TBWYsqq>75=RlIa|x%qTVTw_?=Z~ zV3aa>r{GDHFq!aSMQ*9pn|tUs5~l>H*mXV7!bw!5hPZLNR@ad!!JjF!>SuOS__xurPNnAiZq#suJF~#ZzQ6#Q)x_8XyV|ENy4=N zDj25T!;cmmtO{dL1^NrVe4MG6$!0{Wlq)#-&W|5ldp&|LRDvykB(hQSr? zyF>TM6}slp!Ti&|4@*31pV9ZNls~-?x4~4-97n**z$1_avyC=c{xq0y;(D3e-hzbz zIiA=E#O`BU<&P!Qemv`V*73Y$Q*$5}&$)QskLNr*=i!+Ox$j8oyJ{$>IY5VVCjG!x zCT-+2Lk5S?Yxv7%K&O&9;)Sq^Nx*gD_98Ay9kO6xZ|Zg8>t38>HV)`zEoRyDV_}rO zjR?%O{X`_288t335!%!oXxnQmtvQ?g^XE1P?goQxw^~j{xn4#c<1z}#cN5OYdU%DI z3e;olfa**}OO%cpx#c?Z{7D^5SP6tiW@lUoMhtOe* z!_c0A*4f+ak5|glmFD>YH+lC;v$8Oa4sS!?GjMfajrU;nCLe8$7WxL{->t-4!2Tr` z-twm_&B?XBSc}0%_>{%5F&_N>y&^F19j55uW#F4QVS=U3{9pF^@0QJN(PmpY{y!-h`*{1<-~|ugGtnC z(Ao_JCx8)s6SJd-**iMXst!J+*Pvv()`~zK=+%{2fi(c1zQfske=Ud}x?NG~K(rR_ z!L^FAi_i1d6y&P)U~E?)#HI_j2yfO8F`G=f+3Jz zw#J+?2?ebSwX1cykJlt+{~FAIk;5wFM)+9Dtrk>jF*+WK34bl7N{3J%^h{T)Pca8aIJq&h1TGCSB&|05u?NmRt419tI(iy{DTTm)BBLI8uV&m^t0bjg?5AH zA*9(&VOS}Uu+Y#>op^Nv3c_yGyQq}4V1P=x+Nv<9q%}x*5cSLOM+r!3CXA#=QxQN0Tp?u-_s*63ES=Jt(7O>(QgBX%aQv3tg%5{Q6=GTXdSV0@^FnFswM zGEszQD>vKp+2$o--u-1%G@7>t>>o@pUW-btY1ygPqMS8ir~F!Hv^<$5Knb(0v%AV| zokMV`b&e+%wYv3#-FtZrD)%7DEe@wpx$^CG=EbVFLT|j@tiZ?D+OIdK7Sb%>9n1ps zdC<`47bAN}X>>&kqgfMWuoHtdehCn3)#XcF(W&yi>rMYOuGlK?;_$?V=H4>H@WY~k zJt*FlP+NO$;fWm@2oL=?X|bAy=nCgE2s9Xy@?u+{*Dim({g<;ocYLt?nB3bb;qT=uk5YK zH3Z=G{9HOm|9{SVs=fe%_ZnaTj?#ztUFE)yA$ZRwVYFB;q@F6^NsIv2d9L3va9*5# zcj6I<4~8%Y&U=Le=e?25bOkyq;K##x*|{f&^IBOr@A=23C);t}g}^{*u*35<)oEHb zM>QY=hTOSCEdXXBgrE?-(y9SOfl%FIIZ;9(wG~?3n1q$2FQm2l?@*1YN8{#Qi1_*0 zYO$T_p@pGtVfuPGWwD?Qj-|SqZW{leTUoQmQ^^@qYYtoNLzyZ9Ln~bB-sk zM9|m@V*mupz~X`g%b3-sjsn9q>OpCZEeX|l)Z!yStO6mj1`Gl^%IG{lYCG@7w-f3} z9{d2pBS!H3Aytpa(yr)~aUH5WMe|An#+3mm8l%<@j$*yv3fI6$Vqhd8MKnNh5KdMo zswkp2ig&cD>cj8%z*8^y{Q=cSz|cwX)X$R9QH;Y=FD><5)2n_ep!(_K0M$>DYzcG$ zkT1ZR$i(n{44^t{jktErV*u5|LmT?d;t53c|9^<;ZwLRh5Y>f2>* zgIW3Cg{cO3DJwo>nCcr{KW!3BN1q2%z0Qk|slgbgdadKTdIncTGJX5gM4O!Z6;Qw=ON)eKwaX6|6BQBsG=ET$ST zd6JQ!)iy3;YXLrj-uti@4tk@px+cI6O6f0ZRoK1ZbOvZFHv!pNX+fxp8PSHchh*xN$6$fo?b+WDWfEy?-c- zHEelyx3dr6=tQh>n7sRJGj9TRO`E*`&tTVI8xOl)0weTg*5`m-&+^3XWU%XtkA+>I z_va70UVcj0H67wl2-GaLO#fJ6*GsHsPfbI?#Ko()FA-M#(*?h7OtIe=e;xI<-n}~m z9rL|~A?p<;UW$S(*E8!KD%8&XzWAd!HZ__(F~A z=i;xemrlfATmJ(G#x&Z`H%Sqm9z?PA#L4m37N$lg;IDBSPqhoYQnkc6D+tQ}xX3h9 z44)G}9RO_mBmivN@G`785rEAwO+mE*A$JR^#sVCm4BJoWAOye`7@1Eu0Nch?`wt4h zwm$~|n_&uk0sz~_+?N2@RvM)~1pwRrjSEI33_bge2f#jZ8~_`D>@NVow!K3I69DW_ z0bt+bD#kxc0QPd<8*;-OvnP=cwcm+NAp-2t#u>R0%rWf=e6|D1KM6ittab6(VwDFF zhS8dgn19UpY|Hx$>A#7i_-y8P1)L1-gwM9Q_wM1dtrPIswlm^US!v`G-p5K~E=Iea zK-x#q)c<9Sww3(+7;XFV35@mxMtcIIeGHiVzaOJ5Ox4i{$78hZDXu?h3E9khXrJ|` zh|so=LuiXnL1^RB6(F=L&i>G?YwKU!ZA>lS1!>zS18Iv-2WeY>svvFq3xKq(EJ)k> z6p;2C<3QTi{c(Y`-vCJay8kLjn=Y>T1Aw&c36S;#NP7aL{RabS+ouL;-*5sJu@BSn z(*x25o)JJ2LaA#&scY;3nYY}W+`tyOLk?ZOOr!FjIeOdvvNxOY(A(A=*Kj_8-kv~j zPoTFa(AyK}?Fsbu1bTY{y`4pG4|?eB-TpVjKL3H#`sF*`4C4#hZ|2Jj-wJ=eFKC|v zV_i0OOY$_|j(5WORd$iPU8-Q2$8cJgee_*b_<>RJK13TlyPvLP`w$P`Ct;U(km(%R^t13%MSLuuD2-hk z?(~IVTh^=_U1sc`$*EIfQ+(yJ^xg0i5v!TJ5xmR`{;4c2ixv6iNcC`d$4qgt>&>#k z&wH?g27IV-hD+H-4m9Ir&v{{Zw0|`8!^2_4r;A%Wt~2trpNE@D*m<4!Y{YWEbpzar z>-{VVcm4H#t6NTeFFZ49eHYk8fO0d~sCCZMW8N&DkQ?3$FH^*~spI{xiG<_iUU!l>8ukyH8=!q3?YdE>RTm ztD)CE3P*eq>$MGTp&k3XVAiWc8_FXsentGvP*RDE_!X;DZfS@d9>NC?KT_^1^Ig4T zf1y64e;Dcde4mg#g|vw=X*<_9Oe{nip9X#%+3}aP66{TD0DkpX5cR_zubTkBXm& z*dg*paHALeiaeYjDe~#^{Ev%w%*3_ej$RSj-~&e$E(6AZD6>*Gjy+D{T7NI0aBCE6 zrkwgo@%N&Z@QOU>jtULHHrPq2A1N+b%o1KHnxKEHJ41c5aXwOfT@P-&-Y$&0qx9~wWsBTu|1~YQ2{Z3? zkT>~bR}}#pM8&dufswV`OVc;wvLAWNufvml-Nf5nrYL0NX+RjhYEmD&vR=H*T*0I5ZCoVqjNc0GA>sV7>;H_{sRz-FmrGwT)~eVu zWqUAIs;~p{reLf@5nq=5!Pt5QDDY2$u^NTFE^8WNBj_Dr+~SGv@=%tWA@u8LxP@8T z=?pmM&gI9y3%{<2(xIpxyBAmB+j38CY?+VASEt8{6l?L&htp%v`sH)y#~$^uq23E( KDL=-#7yd8QSe+vP From 4f604517ed8d85007b9147c439f81ac16889c764 Mon Sep 17 00:00:00 2001 From: Dongjin Kim Date: Thu, 16 May 2019 14:50:19 +0900 Subject: [PATCH 0451/1060] ODROID-N2: config: fix kernel config for new BSP 201904 Change-Id: I92924ed3824bae0ddab82666d529439e0dad6a6f Signed-off-by: Dongjin Kim --- arch/arm64/configs/odroidn2_defconfig | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/odroidn2_defconfig b/arch/arm64/configs/odroidn2_defconfig index 167ef76cb3bf..91a33b2b2e56 100644 --- a/arch/arm64/configs/odroidn2_defconfig +++ b/arch/arm64/configs/odroidn2_defconfig @@ -246,10 +246,11 @@ CONFIG_SECCOMP_FILTER=y CONFIG_HAVE_GCC_PLUGINS=y # CONFIG_GCC_PLUGINS is not set CONFIG_HAVE_CC_STACKPROTECTOR=y -CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set # CONFIG_CC_STACKPROTECTOR_NONE is not set # CONFIG_CC_STACKPROTECTOR_REGULAR is not set CONFIG_CC_STACKPROTECTOR_STRONG=y +# CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC is not set # CONFIG_LTO is not set CONFIG_ARCH_SUPPORTS_LTO_CLANG=y CONFIG_LTO_NONE=y @@ -1659,6 +1660,11 @@ CONFIG_AMLOGIC_IONVIDEO=y # CONFIG_AMLOGIC_PIC_DEC=y +# +# Amlogic videosync support +# +CONFIG_AMLOGIC_VIDEOSYNC=y + # # Amlogic Enhancement drivers # @@ -1681,6 +1687,15 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y # Amlogic amdolby_vision Driver # # CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION is not set + +# +# Amlogic amprime_sl Drivers +# + +# +# Amlogic amprime_sl Driver +# +# CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL is not set CONFIG_AMLOGIC_MEDIA_GDC=y # @@ -1782,6 +1797,7 @@ CONFIG_AMLOGIC_ESM=y # # DVB COMPAT support # +# CONFIG_AMLOGIC_POWER is not set # # Multimedia Card support @@ -1806,14 +1822,16 @@ CONFIG_AMLOGIC_MEMORY_EXTEND=y CONFIG_AMLOGIC_RAMDUMP=y CONFIG_AMLOGIC_CMA=y # CONFIG_AMLOGIC_VMAP is not set +# CONFIG_AMLOGIC_WATCHPOINT is not set CONFIG_AMLOGIC_GPIO_IRQ=y # # Amlogic ATV driver # -CONFIG_AMLOGIC_ATV_DEMOD=y +# CONFIG_AMLOGIC_ATV_DEMOD is not set CONFIG_AMLOGIC_DEBUG=y CONFIG_AMLOGIC_DEBUG_LOCKUP=y +# CONFIG_AMLOGIC_DEBUG_ATRACE is not set # # Amlogic defend img file update support From abc5ce3fe6dcf249fda8fccb143aeae670d55ae1 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Mon, 22 Oct 2018 04:20:05 -0400 Subject: [PATCH 0452/1060] amvecm: hdr: add hdr10 plus support [1/2] PD#SWPL-869 Problem: new feature, add hdr10 plus support Solution: 1. add hdr10 plus metadat parser 2. add hdr10 plus code support 3. add hdr10 plus bypass mode Verify: verify on U200 Change-Id: I957954ce148021882e17f2913dd2552e64f1298c Signed-off-by: MingLiang Dong Conflicts: MAINTAINERS drivers/amlogic/media/enhancement/amvecm/Makefile drivers/amlogic/media/enhancement/amvecm/amvecm.c drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c include/linux/amlogic/media/amvecm/amvecm.h --- drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index f28f66561c79..d4ab598a4dc5 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -1301,6 +1301,14 @@ void set_hdr_matrix( adpscl_alpha[i] = 10 * in_luma * (1 << adp_scal_shift) / out_luma; + if (hdr_mtx_param->p_sel & HDR_SDR) { + if (i == 0) + adpscl_shift[i] = adp_scal_shift; + else + adpscl_shift[i] = adp_scal_shift - 2; + } else + adpscl_shift[i] = adp_scal_shift; + adpscl_ys_coef[i] = 1 << adp_scal_shift; adpscl_beta_s[i] = 0; From 62a7c968416405ea8e723eecdf288c9b6754fb3d Mon Sep 17 00:00:00 2001 From: "he.he" Date: Tue, 16 Oct 2018 19:20:23 +0800 Subject: [PATCH 0453/1060] usb: adb reboot and then adb disconnect[1/1] PD#174155: complete_ep 0xffffffc05bed2858, ep->queue empty! Problem: 1. After adb process be killed, data buffer is freed and this memory is allocated for the other. But the address is hold by the controller. 2. Adbd in PC is running. So, the controller receive the data and write to this memory. 3.The value of this memory is modified by the controller. This could cause the memory problem. Solution: whenever io_data->aio equals 1, the data buffer is from a fixed array. Verify: verified by huang xiaojing Change-Id: I2055ea013021c8411bf626ce170e6b32164bef4a Signed-off-by: he.he Conflicts: drivers/usb/gadget/function/f_fs.c --- drivers/usb/gadget/function/f_fs.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 528876248227..266fbd7374fc 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -900,13 +900,7 @@ static void ffs_user_copy_worker(struct work_struct *work) if (io_data->read) kfree(io_data->to_free); - -#ifdef CONFIG_AMLOGIC_USB - if (io_data->aio) { - if (buffer) - release_ffs_buffer(io_data->ffs, buffer); - } -#else +#ifndef CONFIG_AMLOGIC_USB kfree(io_data->buf); #endif kfree(io_data); @@ -1012,7 +1006,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) #ifdef CONFIG_AMLOGIC_USB struct ffs_ep *ep = epfile->ep; struct ffs_data_buffer *buffer = NULL; - int data_aio_flag = -1; #else struct ffs_ep *ep; #endif @@ -1114,7 +1107,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) *reboot adb disconnect,so buffer aways used assign_ffs_buffer. */ buffer = assign_ffs_buffer(epfile->ffs); - data_aio_flag = 1; if (unlikely(!buffer)) { ret = -ENOMEM; spin_unlock_irq(&epfile->ffs->eps_lock); @@ -1161,9 +1153,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) DECLARE_COMPLETION_ONSTACK(done); #endif bool interrupted = false; -#ifdef CONFIG_AMLOGIC_USB - data_aio_flag = 1; -#endif req = ep->req; req->buf = data; req->length = data_len; @@ -1201,9 +1190,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { ret = -ENOMEM; } else { -#ifdef CONFIG_AMLOGIC_USB - data_aio_flag = -1; -#endif req->buf = data; req->length = data_len; @@ -1235,10 +1221,8 @@ error_mutex: mutex_unlock(&epfile->mutex); error: #ifdef CONFIG_AMLOGIC_USB - if (data_aio_flag > 0) { - if (buffer) - release_ffs_buffer(epfile->ffs, buffer); - } + if (buffer) + release_ffs_buffer(epfile->ffs, buffer); #else kfree(data); #endif From 1aac63619dacdcf5b4ae2500155ee6c9d9ba438d Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 23 Nov 2018 21:15:01 +0800 Subject: [PATCH 0454/1060] lcd: update lvds,vbyone,p2p config [1/1] PD#172587 Problem: lcd not work on real chip Solution: update pll, phy and channel_swap config Verify: skt Change-Id: I737f7c253697ed281050ad9606cbf7d86a4b2e39 Signed-off-by: Evoke Zhang Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi --- MAINTAINERS | 5 + arch/arm/boot/dts/amlogic/mesontl1.dtsi | 35 + .../boot/dts/amlogic/mesontl1_pxp-panel.dtsi | 92 - .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 669 + arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 36 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 72 +- drivers/amlogic/media/vout/backlight/aml_bl.c | 5 +- .../amlogic/media/vout/lcd/lcd_clk_config.c | 304 +- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 2 +- drivers/amlogic/media/vout/lcd/lcd_common.c | 41 +- drivers/amlogic/media/vout/lcd/lcd_common.h | 2 + drivers/amlogic/media/vout/lcd/lcd_debug.c | 193 +- drivers/amlogic/media/vout/lcd/lcd_debug.h | 6 +- drivers/amlogic/media/vout/lcd/lcd_reg.h | 51 +- drivers/amlogic/media/vout/lcd/lcd_tcon.c | 55 + .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 269 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 2 + drivers/amlogic/media/vout/lcd/lcd_vout.c | 34 + drivers/amlogic/media/vout/lcd/tcon_ceds.h | 24019 ++++++++++++++++ .../linux/amlogic/media/vout/lcd/lcd_vout.h | 10 +- 20 files changed, 25562 insertions(+), 340 deletions(-) delete mode 100644 arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi create mode 100644 arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi create mode 100644 drivers/amlogic/media/vout/lcd/tcon_ceds.h diff --git a/MAINTAINERS b/MAINTAINERS index d8afba63c32c..bed14ed68b75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14754,6 +14754,11 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c F: drivers/amlogic/media/common/vfm/vfm.c F: include/linux/amlogic/media/camera/* +AMLOGIC MESON TL1 PANEL DTS +M: Evoke Zhang +F: arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi + AMLOGIC multimedia M: Pengcheng Chen F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index e524bad70691..3b61f79e1036 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -2089,4 +2089,39 @@ }; }; + lcd_vbyone_pins: lcd_vbyone_pin { + mux { + groups = "vx1_lockn","vx1_htpdn"; + function = "vx1"; + }; + }; + lcd_vbyone_off_pins: lcd_vbyone_off_pin { + mux { + groups = "GPIOH_15","GPIOH_16"; + function = "gpio_periphs"; + input-enable; + }; + }; + + lcd_tcon_pins: lcd_tcon_pin { + mux { + groups = "tcon_0","tcon_1","tcon_2","tcon_3", + "tcon_4","tcon_5","tcon_6","tcon_7", + "tcon_8","tcon_9","tcon_10","tcon_11", + "tcon_12","tcon_13","tcon_14","tcon_15", + "tcon_lock"; + function = "tcon"; + }; + }; + lcd_tcon_off_pins: lcd_tcon_off_pin { + mux { + groups = "GPIOH_0","GPIOH_1","GPIOH_2","GPIOH_3", + "GPIOH_4","GPIOH_5","GPIOH_6","GPIOH_7", + "GPIOH_8","GPIOH_9","GPIOH_10","GPIOH_11", + "GPIOH_12","GPIOH_13","GPIOH_14","GPIOH_15", + "GPIOH_16"; + function = "gpio_periphs"; + input-enable; + }; + }; }; diff --git a/arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi deleted file mode 100644 index 765211c88d49..000000000000 --- a/arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi +++ /dev/null @@ -1,92 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/mesontl1_pxp-panel.dtsi - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/ { - lcd { - compatible = "amlogic, lcd-tl1"; - status = "okay"; - mode = "tv"; - fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ - key_valid = <0>; - clocks = <&clkc CLKID_VCLK2_ENCL - &clkc CLKID_VCLK2_VENCL - &clkc CLKID_TCON - &clkc CLKID_FCLK_DIV5 - &clkc CLKID_TCON_PLL_COMP>; - clock-names = "encl_top_gate", - "encl_int_gate", - "tcon_gate", - "fclk_div5", - "clk_tcon"; - reg = <0xff660000 0x8100 - 0xff634400 0x100>; - interrupts = <0 3 1 - 0 78 1 - 0 88 1>; - interrupt-names = "vsync","vbyone","tcon"; - pinctrl_version = <2>; /* for uboot */ - - /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ - /* power index:(gpios_index, or extern_index, 0xff=invalid) */ - /* power value:(0=output low, 1=output high, 2=input) */ - /* power delay:(unit in ms) */ - - lvds_0{ - model_name = "1080p-vfreq"; - interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ - basic_setting = < - 1920 1080 /*h_active, v_active*/ - 2200 1125 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 2060 2650 /*h_period_min,max*/ - 1100 1480 /*v_period_min,max*/ - 120000000 160000000>; /*pclk_min,max*/ - lcd_timing = < - 44 148 0 /*hs_width, hs_bp, hs_pol*/ - 5 30 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 0 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - lvds_attr = < - 1 /*lvds_repack*/ - 1 /*dual_port*/ - 0 /*pn_swap*/ - 0 /*port_swap*/ - 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/ - 0 0>; /*clk vswing_level, preem_level*/ - - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 2 0 0 0 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - }; /* end of lcd */ - -}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi new file mode 100644 index 000000000000..0832e10d5e7d --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -0,0 +1,669 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=< + 3 0 /*vswing_level, preem_level*/ + 0 0>; /*clk vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=< + 3 0 /*vswing_level, preem_level*/ + 0 0>; /*clk vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=< + 3 0 /*vswing_level, preem_level*/ + 0 0>; /*clk vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 1 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<3 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, mlvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=< + 3 0 /*vswing_level, preem_level*/>; + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_B","PWM_C"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index f689dac1f0a4..fcf991a1616a 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -449,7 +449,7 @@ compatible = "amlogic, unifykey"; status = "okay"; - unifykey-num = <19>; + unifykey-num = <20>; unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -469,6 +469,7 @@ unifykey-index-16 = <&keysn_16>; unifykey-index-17 = <&keysn_17>; unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; keysn_0: key_0{ key-name = "usid"; @@ -570,6 +571,11 @@ key-device = "normal"; key-permit = "read","write","del"; }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; }; /* End unifykey */ hdmirx { @@ -1461,6 +1467,34 @@ status = "okay"; }; +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + &pwm_ab { status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 5604ed0ad376..0d4590746490 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -19,7 +19,7 @@ #include "mesontl1.dtsi" #include "partition_mbox_normal_P_32.dtsi" -#include "mesontl1_skt-panel.dtsi" +#include "mesontl1_x301-panel.dtsi" / { model = "Amlogic TL1 T962X2 X301"; @@ -451,7 +451,7 @@ compatible = "amlogic, unifykey"; status = "okay"; - unifykey-num = <19>; + unifykey-num = <20>; unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -471,6 +471,7 @@ unifykey-index-16 = <&keysn_16>; unifykey-index-17 = <&keysn_17>; unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; keysn_0: key_0{ key-name = "usid"; @@ -572,6 +573,11 @@ key-device = "normal"; key-permit = "read","write","del"; }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; }; /* End unifykey */ hdmirx { @@ -1252,6 +1258,40 @@ }; }; + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; }; /* end of pinctrl_periphs */ @@ -1445,6 +1485,34 @@ status = "okay"; }; +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + &pwm_ab { status = "okay"; }; diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index 64b7ff279585..b649434b74f5 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -3539,7 +3539,7 @@ static int aml_bl_probe(struct platform_device *pdev) err: kfree(bl_drv); bl_drv = NULL; - return ret; + return 0; } static int __exit aml_bl_remove(struct platform_device *pdev) @@ -3547,6 +3547,9 @@ static int __exit aml_bl_remove(struct platform_device *pdev) int ret; /*struct aml_bl *bl_drv = platform_get_drvdata(pdev);*/ + if (bl_drv == NULL) + return 0; + aml_bl_remove_class(); ret = cancel_delayed_work_sync(&bl_drv->bl_delayed_work); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index aad62775596b..b5f5c4bccfb4 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -483,6 +483,7 @@ static void lcd_set_pll_ss_tl1(unsigned int ss_level) static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) { +#if 0 unsigned int pll_ctrl, pll_ctrl1; int ret; @@ -509,7 +510,85 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); +#else + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int ret; + switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { + case LCD_LVDS: + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200704ad); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300704ad); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10508000); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340704ad); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x142e04ad); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); + mdelay(10); + break; + case LCD_VBYONE: + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200f04f7); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300f04f7); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10110000); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340f04f7); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x140f04f7); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); + mdelay(10); + break; + case LCD_P2P: + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200604e1); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300604e1); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10208000); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340604e1); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x14af04e1); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); + mdelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); + mdelay(10); + break; + default: + break; + } +#endif ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1); if (ret) LCDERR("hpll lock failed\n"); @@ -554,7 +633,7 @@ static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cConf) lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, shift_sel, 16, 2); lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, 1, 15, 1); - lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, shift_val, 0, 14); + lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, shift_val, 0, 15); lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1); } /* Enable the final output clock */ @@ -604,34 +683,17 @@ static void lcd_set_dsi_phy_clk(int sel) static void lcd_set_tcon_clk(struct lcd_config_s *pconf) { -#if 0 - unsigned int val; - if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); switch (pconf->lcd_basic.lcd_type) { - case LCD_LVDS: - lcd_hiu_write(HHI_DIF_TCON_CNTL0, 0x0); - lcd_hiu_write(HHI_DIF_TCON_CNTL0, 0x80000000); - lcd_hiu_write(HHI_DIF_TCON_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_TCON_CNTL2, 0x0); - break; case LCD_MLVDS: - val = pconf->lcd_control.mlvds_config->pi_clk_sel; - /*val = (~val) & 0x3ff;*/ - lcd_hiu_write(HHI_DIF_TCON_CNTL0, (val << 12)); - lcd_hiu_write(HHI_DIF_TCON_CNTL0, ((1 << 31) | (val << 12))); - - val = pconf->lcd_control.mlvds_config->clk_phase & 0xfff; - lcd_hiu_write(HHI_DIF_TCON_CNTL1, val); - lcd_hiu_write(HHI_DIF_TCON_CNTL2, 0x0); - + case LCD_P2P: /* tcon_clk 50M */ /*lcd_hiu_write(HHI_TCON_CLK_CNTL, * (1 << 7) | (1 << 6) | (7 << 0)); */ - if (!IS_ERR(lcd_clktree.tcon_clk)) { + if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) { clk_set_rate(lcd_clktree.tcon_clk, 50000000); clk_prepare_enable(lcd_clktree.tcon_clk); } @@ -639,7 +701,6 @@ static void lcd_set_tcon_clk(struct lcd_config_s *pconf) default: break; } -#endif } /* **************************************************** @@ -1088,6 +1149,32 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) } } break; + case LCD_P2P: + clk_div_sel = CLK_DIV_SEL_1; + xd = 1; + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + goto generate_clk_done_txl; + if (lcd_debug_print_flag == 2) { + LCDPR("fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + clk_div_in = clk_vid_pll_div_calc(clk_div_out, + clk_div_sel, CLK_DIV_O2I); + if (clk_div_in > cConf->data->div_in_fmax) + goto generate_clk_done_txl; + cConf->xd = xd; + cConf->div_sel = clk_div_sel; + pll_fout = clk_div_in; + if (lcd_debug_print_flag == 2) { + LCDPR("clk_div_sel=%s(index %d), pll_fout=%d\n", + lcd_clk_div_sel_table[clk_div_sel], + clk_div_sel, pll_fout); + } + done = check_pll_txl(cConf, pll_fout); + if (done) + goto generate_clk_done_txl; + break; default: break; } @@ -1525,20 +1612,20 @@ static void lcd_clk_set_tl1(struct lcd_config_s *pconf) static void lcd_clk_gate_switch_dft(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_prepare_enable(lcd_clktree.encl_int_gate); } else { - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gata\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_top_gate); @@ -1548,44 +1635,44 @@ static void lcd_clk_gate_switch_dft(struct aml_lcd_drv_s *lcd_drv, int status) static void lcd_clk_gate_switch_axg(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.mipi_enable_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) LCDERR("%s: mipi_enable_gate\n", __func__); else clk_prepare_enable(lcd_clktree.mipi_enable_gate); - if (IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) LCDERR("%s: mipi_bandgap_gate\n", __func__); else clk_prepare_enable(lcd_clktree.mipi_bandgap_gate); } else { - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.mipi_enable_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) LCDERR("%s: mipi_enable_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.mipi_enable_gate); - if (IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) LCDERR("%s: mipi_bandgap_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.mipi_bandgap_gate); @@ -1596,56 +1683,56 @@ static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { if (clk_conf.data->vclk_sel) { - if (IS_ERR(lcd_clktree.gp0_pll)) + if (IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) LCDERR("%s: gp0_pll\n", __func__); else clk_prepare_enable(lcd_clktree.gp0_pll); } - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_prepare_enable(lcd_clktree.encl_int_gate); } else { - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_top_gate); if (clk_conf.data->vclk_sel) { - if (IS_ERR(lcd_clktree.gp0_pll)) + if (IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) LCDERR("%s: gp0_pll\n", __func__); else clk_disable_unprepare(lcd_clktree.gp0_pll); @@ -1656,22 +1743,22 @@ static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *lcd_drv, int status) static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_prepare_enable(lcd_clktree.encl_int_gate); switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: - if (IS_ERR(lcd_clktree.tcon_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) LCDERR("%s: tcon_gate\n", __func__); else clk_prepare_enable(lcd_clktree.tcon_gate); - if (IS_ERR(lcd_clktree.tcon_clk)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) LCDERR("%s: tcon_clk\n", __func__); else clk_prepare_enable(lcd_clktree.tcon_clk); @@ -1683,11 +1770,11 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: - if (IS_ERR(lcd_clktree.tcon_clk)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) LCDERR("%s: tcon_clk\n", __func__); else clk_disable_unprepare(lcd_clktree.tcon_clk); - if (IS_ERR(lcd_clktree.tcon_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) LCDERR("%s: tcon_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.tcon_gate); @@ -1695,11 +1782,11 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) default: break; } - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_top_gate); @@ -1713,11 +1800,11 @@ static void lcd_clktree_probe_dft(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.encl_top_gate = devm_clk_get(lcd_drv->dev, "encl_top_gate"); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: get encl_top_gate error\n", __func__); lcd_clktree.encl_int_gate = devm_clk_get(lcd_drv->dev, "encl_int_gate"); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: get encl_int_gate error\n", __func__); LCDPR("lcd_clktree_probe\n"); @@ -1730,25 +1817,25 @@ static void lcd_clktree_probe_axg(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.dsi_host_gate = devm_clk_get(lcd_drv->dev, "dsi_host_gate"); - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: clk dsi_host_gate\n", __func__); lcd_clktree.dsi_phy_gate = devm_clk_get(lcd_drv->dev, "dsi_phy_gate"); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: clk dsi_phy_gate\n", __func__); lcd_clktree.dsi_meas = devm_clk_get(lcd_drv->dev, "dsi_meas"); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: clk dsi_meas\n", __func__); lcd_clktree.mipi_enable_gate = devm_clk_get(lcd_drv->dev, "mipi_enable_gate"); - if (IS_ERR(lcd_clktree.mipi_enable_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) LCDERR("%s: clk mipi_enable_gate\n", __func__); lcd_clktree.mipi_bandgap_gate = devm_clk_get(lcd_drv->dev, "mipi_bandgap_gate"); - if (IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) LCDERR("%s: clk mipi_bandgap_gate\n", __func__); LCDPR("lcd_clktree_probe\n"); @@ -1761,27 +1848,27 @@ static void lcd_clktree_probe_g12a(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.dsi_host_gate = devm_clk_get(lcd_drv->dev, "dsi_host_gate"); - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: clk dsi_host_gate\n", __func__); lcd_clktree.dsi_phy_gate = devm_clk_get(lcd_drv->dev, "dsi_phy_gate"); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: clk dsi_phy_gate\n", __func__); lcd_clktree.dsi_meas = devm_clk_get(lcd_drv->dev, "dsi_meas"); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: clk dsi_meas\n", __func__); lcd_clktree.encl_top_gate = devm_clk_get(lcd_drv->dev, "encl_top_gate"); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: clk encl_top_gate\n", __func__); lcd_clktree.encl_int_gate = devm_clk_get(lcd_drv->dev, "encl_int_gate"); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: clk encl_int_gate\n", __func__); lcd_clktree.gp0_pll = devm_clk_get(lcd_drv->dev, "gp0_pll"); - if (IS_ERR(lcd_clktree.gp0_pll)) + if (IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) LCDERR("%s: clk gp0_pll\n", __func__); LCDPR("lcd_clktree_probe\n"); @@ -1795,34 +1882,27 @@ static void lcd_clktree_probe_tl1(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.encl_top_gate = devm_clk_get(lcd_drv->dev, "encl_top_gate"); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: get encl_top_gate error\n", __func__); lcd_clktree.encl_int_gate = devm_clk_get(lcd_drv->dev, "encl_int_gate"); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: get encl_int_gate error\n", __func__); - switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { - case LCD_MLVDS: - case LCD_P2P: - lcd_clktree.tcon_gate = devm_clk_get(lcd_drv->dev, "tcon_gate"); - if (IS_ERR(lcd_clktree.tcon_gate)) - LCDERR("%s: get tcon_gate error\n", __func__); + lcd_clktree.tcon_gate = devm_clk_get(lcd_drv->dev, "tcon_gate"); + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) + LCDERR("%s: get tcon_gate error\n", __func__); - temp_clk = devm_clk_get(lcd_drv->dev, "fclk_div5"); - if (IS_ERR(temp_clk)) { - LCDERR("%s: clk fclk_div5\n", __func__); - return; - } - lcd_clktree.tcon_clk = devm_clk_get(lcd_drv->dev, "clk_tcon"); - if (IS_ERR(lcd_clktree.tcon_clk)) - LCDERR("%s: clk clk_tcon\n", __func__); - else - clk_set_parent(lcd_clktree.tcon_clk, temp_clk); - break; - default: - break; + temp_clk = devm_clk_get(lcd_drv->dev, "fclk_div5"); + if (IS_ERR_OR_NULL(temp_clk)) { + LCDERR("%s: clk fclk_div5\n", __func__); + return; } + lcd_clktree.tcon_clk = devm_clk_get(lcd_drv->dev, "clk_tcon"); + if (IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) + LCDERR("%s: clk clk_tcon\n", __func__); + else + clk_set_parent(lcd_clktree.tcon_clk, temp_clk); LCDPR("lcd_clktree_probe\n"); } @@ -1834,9 +1914,9 @@ static void lcd_clktree_remove_dft(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.encl_top_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_top_gate); - if (!IS_ERR(lcd_clktree.encl_int_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_int_gate); } @@ -1847,17 +1927,17 @@ static void lcd_clktree_remove_axg(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.mipi_bandgap_gate); - if (!IS_ERR(lcd_clktree.mipi_enable_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.mipi_enable_gate); - if (!IS_ERR(lcd_clktree.dsi_meas)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_meas); - if (!IS_ERR(lcd_clktree.dsi_phy_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_phy_gate); - if (!IS_ERR(lcd_clktree.dsi_host_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_host_gate); - if (!IS_ERR(lcd_clktree.gp0_pll)) + if (!IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) devm_clk_put(lcd_drv->dev, lcd_clktree.gp0_pll); } @@ -1868,15 +1948,15 @@ static void lcd_clktree_remove_g12a(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.dsi_host_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_host_gate); - if (!IS_ERR(lcd_clktree.dsi_phy_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_phy_gate); - if (!IS_ERR(lcd_clktree.dsi_meas)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_meas); - if (!IS_ERR(lcd_clktree.encl_top_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_top_gate); - if (!IS_ERR(lcd_clktree.encl_int_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_int_gate); } @@ -1887,22 +1967,14 @@ static void lcd_clktree_remove_tl1(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.encl_top_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_top_gate); - if (!IS_ERR(lcd_clktree.encl_int_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_int_gate); - - switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { - case LCD_MLVDS: - case LCD_P2P: - if (!IS_ERR(lcd_clktree.tcon_clk)) - devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_clk); - if (IS_ERR(lcd_clktree.tcon_gate)) - devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_gate); - break; - default: - break; - } + if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) + devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_clk); + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) + devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_gate); } static void lcd_clk_config_init_print_dft(void) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index d35d543eef99..2bf31f6f5efd 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -232,7 +232,7 @@ /* video */ #define CLK_DIV_IN_MAX_TL1 (3100 * 1000) #define CRT_VID_CLK_IN_MAX_TL1 (3100 * 1000) -#define ENCL_CLK_IN_MAX_TL1 (400 * 1000) +#define ENCL_CLK_IN_MAX_TL1 (750 * 1000) /* ********************************** diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index b0fc1ec9bf06..cd61eff6e0a0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -363,35 +363,42 @@ void lcd_vbyone_pinmux_set(int status) pconf->pinmux_flag = index; } +static char *lcd_tcon_pinmux_str[] = { + "tcon", + "tcon_off", + "none", +}; + void lcd_tcon_pinmux_set(int status) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); struct lcd_config_s *pconf; + unsigned int index; if (lcd_debug_print_flag) LCDPR("%s: %d\n", __func__, status); pconf = lcd_drv->lcd_config; - if (status) { - if (pconf->pinmux_flag == 0) { - pconf->pinmux_flag = 1; - /* request pinmux */ - pconf->pin = devm_pinctrl_get_select(lcd_drv->dev, - "tcon"); - if (IS_ERR(pconf->pin)) - LCDERR("set tcon pinmux error\n"); - } else { - LCDPR("tcon pinmux is already selected\n"); - } + index = (status) ? 0 : 1; + + if (pconf->pinmux_flag == index) { + LCDPR("pinmux %s is already selected\n", + lcd_tcon_pinmux_str[index]); + return; + } + + pconf->pin = devm_pinctrl_get_select(lcd_drv->dev, + lcd_tcon_pinmux_str[index]); + if (IS_ERR(pconf->pin)) { + LCDERR("set vbyone pinmux %s error\n", + lcd_tcon_pinmux_str[index]); } else { - if (pconf->pinmux_flag) { - pconf->pinmux_flag = 0; - /* release pinmux */ - devm_pinctrl_put(pconf->pin); - } else { - LCDPR("tcon pinmux is already released\n"); + if (lcd_debug_print_flag) { + LCDPR("set vbyone pinmux %s: %p\n", + lcd_tcon_pinmux_str[index], pconf->pin); } } + pconf->pinmux_flag = index; } unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf) diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 9512a7bc809b..6a49629bfaff 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -118,6 +118,8 @@ extern void lcd_venc_change(struct lcd_config_s *pconf); extern void lcd_if_enable_retry(struct lcd_config_s *pconf); /* lcd tcon */ +extern unsigned int lcd_tcon_reg_read(unsigned int addr); +extern void lcd_tcon_reg_write(unsigned int addr, unsigned int val); extern void lcd_tcon_reg_table_print(void); extern void lcd_tcon_reg_readback_print(void); extern int lcd_tcon_info_print(char *buf, int offset); diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 08b268dea6e0..3663f66c7042 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -41,7 +41,7 @@ static struct lcd_debug_info_reg_s *lcd_debug_info_reg; static struct lcd_debug_info_if_s *lcd_debug_info_if; -#define PR_BUF_MAX 2048 +#define PR_BUF_MAX 4096 static void lcd_debug_parse_param(char *buf_orig, char **parm) { @@ -464,7 +464,7 @@ static int lcd_info_print_p2p(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, - "channel_num %d\n" + "lane_num %d\n" "channel_sel1 0x%08x\n" "channel_sel1 0x%08x\n" "clk_phase 0x%04x\n" @@ -474,7 +474,7 @@ static int lcd_info_print_p2p(char *buf, int offset) "phy_preem 0x%x\n" "bit_rate %dHz\n" "pi_clk_sel 0x%03x\n\n", - pconf->lcd_control.p2p_config->channel_num, + pconf->lcd_control.p2p_config->lane_num, pconf->lcd_control.p2p_config->channel_sel0, pconf->lcd_control.p2p_config->channel_sel1, pconf->lcd_control.p2p_config->clk_phase, @@ -962,28 +962,13 @@ static int lcd_reg_print_p2p(char *buf, int offset) int n, len = 0; n = lcd_debug_info_len(len + offset); - len += snprintf((buf+len), n, "\nmlvds regs:\n"); + len += snprintf((buf+len), n, "\np2p regs:\n"); n = lcd_debug_info_len(len + offset); - reg = HHI_TCON_CLK_CNTL; + reg = HHI_TCON_CLK_CNTL_TL1; len += snprintf((buf+len), n, "HHI_TCON_CLK_CNTL [0x%04x] = 0x%08x\n", reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_DIF_TCON_CNTL0; - len += snprintf((buf+len), n, - "HHI_DIF_TCON_CNTL0 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_DIF_TCON_CNTL1; - len += snprintf((buf+len), n, - "HHI_DIF_TCON_CNTL1 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_DIF_TCON_CNTL2; - len += snprintf((buf+len), n, - "HHI_DIF_TCON_CNTL2 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = TCON_TOP_CTRL; @@ -1077,17 +1062,103 @@ static int lcd_reg_print_phy_analog(char *buf, int offset) n = lcd_debug_info_len(len + offset); reg = HHI_DIF_CSI_PHY_CNTL1; len += snprintf((buf+len), n, - "HHI_DIF_CSI_PHY_CNTL1 [0x%04x] = 0x%08x\n", + "HHI_DIF_CSI_PHY_CNTL1 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_DIF_CSI_PHY_CNTL2; len += snprintf((buf+len), n, - "HHI_DIF_CSI_PHY_CNTL2 [0x%04x] = 0x%08x\n", + "HHI_DIF_CSI_PHY_CNTL2 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_DIF_CSI_PHY_CNTL3; len += snprintf((buf+len), n, - "HHI_DIF_CSI_PHY_CNTL3 [0x%04x] = 0x%08x\n", + "HHI_DIF_CSI_PHY_CNTL3 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + + return len; +} + +static int lcd_reg_print_phy_analog_tl1(char *buf, int offset) +{ + unsigned int reg; + int n, len = 0; + + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, "\nphy analog regs:\n"); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL1; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL1 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL2; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL2 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL3; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL3 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL4; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL4 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL6; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL6 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL7; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL7 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL8; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL8 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL9; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL9 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL10; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL10 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL11; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL11 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL12; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL12 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL13; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL13 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL14; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL14 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL15; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL15 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL16; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL16 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); return len; @@ -1103,17 +1174,17 @@ static int lcd_reg_print_mipi_phy_analog(char *buf, int offset) n = lcd_debug_info_len(len + offset); reg = HHI_MIPI_CNTL0; len += snprintf((buf+len), n, - "HHI_MIPI_CNTL0 [0x%04x] = 0x%08x\n", + "HHI_MIPI_CNTL0 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_MIPI_CNTL1; len += snprintf((buf+len), n, - "HHI_MIPI_CNTL1 [0x%04x] = 0x%08x\n", + "HHI_MIPI_CNTL1 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_MIPI_CNTL2; len += snprintf((buf+len), n, - "HHI_MIPI_CNTL2 [0x%04x] = 0x%08x\n", + "HHI_MIPI_CNTL2 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); return len; @@ -1139,7 +1210,7 @@ static int lcd_reg_print(char *buf, int offset) break; n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, - "hiu [0x%08x] = 0x%08x\n", + "hiu [0x%02x] = 0x%08x\n", table[i], lcd_hiu_read(table[i])); i++; } @@ -1174,7 +1245,7 @@ static int lcd_reg_print(char *buf, int offset) if (table[i] == LCD_DEBUG_REG_END) break; len += snprintf((buf+len), n, - "PERIPHS_PIN_MUX [0x%08x] = 0x%08x\n", + "PERIPHS_PIN_MUX [0x%02x] = 0x%08x\n", table[i], lcd_periphs_read(table[i])); i++; } @@ -1967,18 +2038,18 @@ static ssize_t lcd_debug_change_store(struct class *class, ret = sscanf(buf, "p2p %d %x %x %x %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); if (ret == 6) { - p2p_conf->channel_num = val[0]; + p2p_conf->lane_num = val[0]; p2p_conf->channel_sel0 = val[1]; p2p_conf->channel_sel1 = val[2]; p2p_conf->clk_phase = val[3]; p2p_conf->pn_swap = val[4]; p2p_conf->bit_swap = val[5]; - pr_info("change mlvds config:\n" - "channel_num=%d,\n" + pr_info("change p2p config:\n" + "lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->channel_num, + p2p_conf->lane_num, p2p_conf->channel_sel0, p2p_conf->channel_sel1, p2p_conf->clk_phase, @@ -2433,6 +2504,16 @@ static void lcd_debug_reg_write(unsigned int reg, unsigned int data, pr_info("write mipi_dsi_phy [0x%04x] = 0x%08x, readback 0x%08x\n", reg, data, dsi_phy_read(reg)); break; + case 6: /* tcon */ + lcd_tcon_reg_write(reg, data); + if (reg < TCON_TOP_BASE) { + pr_info("write tcon [0x%04x] = 0x%02x, readback 0x%02x\n", + reg, data, lcd_tcon_reg_read(reg)); + } else { + pr_info("write tcon [0x%04x] = 0x%08x, readback 0x%08x\n", + reg, data, lcd_tcon_reg_read(reg)); + } + break; default: break; } @@ -2465,6 +2546,15 @@ static void lcd_debug_reg_read(unsigned int reg, unsigned int bus) pr_info("read mipi_dsi_phy [0x%04x] = 0x%08x\n", reg, dsi_phy_read(reg)); break; + case 6: + if (reg < TCON_TOP_BASE) { + pr_info("read tcon [0x%04x] = 0x%02x\n", + reg, lcd_tcon_reg_read(reg)); + } else { + pr_info("read tcon [0x%04x] = 0x%08x\n", + reg, lcd_tcon_reg_read(reg)); + } + break; default: break; } @@ -2518,6 +2608,20 @@ static void lcd_debug_reg_dump(unsigned int reg, unsigned int num, (reg + i), dsi_phy_read(reg + i)); } break; + case 6: + pr_info("dump tcon regs:\n"); + if (reg < TCON_TOP_BASE) { + for (i = 0; i < num; i++) { + pr_info("[0x%04x] = 0x%02x\n", + (reg + i), lcd_tcon_reg_read(reg + i)); + } + } else { + for (i = 0; i < num; i++) { + pr_info("[0x%04x] = 0x%08x\n", + (reg + i), lcd_tcon_reg_read(reg + i)); + } + } + break; default: break; } @@ -2552,6 +2656,9 @@ static ssize_t lcd_debug_reg_store(struct class *class, ret = sscanf(buf, "wmp %x %x", ®32, &data32); bus = 5; } + } else if (buf[1] == 't') { + ret = sscanf(buf, "wt %x %x", ®32, &data32); + bus = 6; } if (ret == 2) { lcd_debug_reg_write(reg32, data32, bus); @@ -2581,6 +2688,9 @@ static ssize_t lcd_debug_reg_store(struct class *class, ret = sscanf(buf, "rmp %x", ®32); bus = 5; } + } else if (buf[1] == 't') { + ret = sscanf(buf, "rt %x", ®32); + bus = 6; } if (ret == 1) { lcd_debug_reg_read(reg32, bus); @@ -2610,6 +2720,9 @@ static ssize_t lcd_debug_reg_store(struct class *class, ret = sscanf(buf, "dmp %x %d", ®32, &data32); bus = 5; } + } else if (buf[1] == 't') { + ret = sscanf(buf, "dt %x %d", ®32, &data32); + bus = 6; } if (ret == 2) { lcd_debug_reg_dump(reg32, data32, bus); @@ -2978,7 +3091,7 @@ static const char *lcd_mlvds_debug_usage_str = { static const char *lcd_p2p_debug_usage_str = { "Usage:\n" -" echo > minilvds ; set minilvds config\n" +" echo > minilvds ; set minilvds config\n" "data format:\n" " : minilvds 8 channels mapping in tx 10 channels\n" " : bit[13:12]=clk01_pi_sel, bit[11:8]=pi2, bit[7:4]=pi1, bit[3:0]=pi0\n" @@ -3287,17 +3400,17 @@ static ssize_t lcd_p2p_debug_store(struct class *class, p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; ret = sscanf(buf, "%d %x %x %x %d %d", - &p2p_conf->channel_num, + &p2p_conf->lane_num, &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, &p2p_conf->clk_phase, &p2p_conf->pn_swap, &p2p_conf->bit_swap); if (ret == 6) { pr_info("set minilvds config:\n" - "channel_num=%d,\n" + "lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->channel_num, + p2p_conf->lane_num, p2p_conf->channel_sel0, p2p_conf->channel_sel1, p2p_conf->clk_phase, p2p_conf->pn_swap, p2p_conf->bit_swap); @@ -4236,6 +4349,14 @@ int lcd_debug_probe(void) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: lcd_debug_info_reg = &lcd_debug_info_reg_tl1; + lcd_debug_info_if_lvds.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_vbyone.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_mlvds.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_p2p.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; break; case LCD_CHIP_G12A: case LCD_CHIP_G12B: diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.h b/drivers/amlogic/media/vout/lcd/lcd_debug.h index 8c72d7b00ea3..af5bbf6612f3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.h +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.h @@ -178,9 +178,9 @@ static unsigned int lcd_reg_dump_pinmux_txlx[] = { }; static unsigned int lcd_reg_dump_pinmux_tl1[] = { - PERIPHS_PIN_MUX_7, - PERIPHS_PIN_MUX_8, - PERIPHS_PIN_MUX_9, + PERIPHS_PIN_MUX_7_TL1, + PERIPHS_PIN_MUX_8_TL1, + PERIPHS_PIN_MUX_9_TL1, LCD_DEBUG_REG_END, }; diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index b09f71d21d36..c6225693b85c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -58,6 +58,23 @@ #define PERIPHS_PIN_MUX_11 0x37 #define PERIPHS_PIN_MUX_12 0x38 +#define PERIPHS_PIN_MUX_0_TL1 0x0b0 +#define PERIPHS_PIN_MUX_1_TL1 0x0b1 +#define PERIPHS_PIN_MUX_2_TL1 0x0b2 +#define PERIPHS_PIN_MUX_3_TL1 0x0b3 +#define PERIPHS_PIN_MUX_4_TL1 0x0b4 +#define PERIPHS_PIN_MUX_5_TL1 0x0b5 +#define PERIPHS_PIN_MUX_6_TL1 0x0b6 +#define PERIPHS_PIN_MUX_7_TL1 0x0b7 +#define PERIPHS_PIN_MUX_8_TL1 0x0b8 +#define PERIPHS_PIN_MUX_9_TL1 0x0b9 +#define PERIPHS_PIN_MUX_A_TL1 0x0ba +#define PERIPHS_PIN_MUX_B_TL1 0x0bb +#define PERIPHS_PIN_MUX_C_TL1 0x0bc +#define PERIPHS_PIN_MUX_D_TL1 0x0bd +#define PERIPHS_PIN_MUX_E_TL1 0x0be +#define PERIPHS_PIN_MUX_F_TL1 0x0bf + /* HIU: HHI_CBUS_BASE = 0x10 */ #define HHI_GCLK_MPEG0 0x50 @@ -139,14 +156,13 @@ #define HHI_DSI_LVDS_EDP_CNTL0 0xd1 #define HHI_DSI_LVDS_EDP_CNTL1 0xd2 -#define HHI_DIF_CSI_PHY_CNTL0 0xd8 #define HHI_DIF_CSI_PHY_CNTL1 0xd9 #define HHI_DIF_CSI_PHY_CNTL2 0xda #define HHI_DIF_CSI_PHY_CNTL3 0xdb -#define HHI_DIF_CSI_PHY_CNTL4 0xdc -#define HHI_DIF_CSI_PHY_CNTL5 0xdd #define HHI_LVDS_TX_PHY_CNTL0 0xde #define HHI_LVDS_TX_PHY_CNTL1 0xdf +#define HHI_LVDS_TX_PHY_CNTL0_TL1 0x9a +#define HHI_LVDS_TX_PHY_CNTL1_TL1 0x9b #define HHI_VID2_PLL_CNTL 0xe0 #define HHI_VID2_PLL_CNTL2 0xe1 #define HHI_VID2_PLL_CNTL3 0xe2 @@ -155,6 +171,19 @@ #define HHI_VID2_PLL_CNTL6 0xe5 #define HHI_VID_LOCK_CLK_CNTL 0xf2 +#define HHI_DIF_CSI_PHY_CNTL10 0x8e +#define HHI_DIF_CSI_PHY_CNTL11 0x8f +#define HHI_DIF_CSI_PHY_CNTL12 0x90 +#define HHI_DIF_CSI_PHY_CNTL13 0x91 +#define HHI_DIF_CSI_PHY_CNTL14 0x92 +#define HHI_DIF_CSI_PHY_CNTL15 0x93 +#define HHI_DIF_CSI_PHY_CNTL16 0xde +#define HHI_DIF_CSI_PHY_CNTL4 0xe9 +#define HHI_DIF_CSI_PHY_CNTL6 0xea +#define HHI_DIF_CSI_PHY_CNTL7 0xeb +#define HHI_DIF_CSI_PHY_CNTL8 0xec +#define HHI_DIF_CSI_PHY_CNTL9 0xed + /* AXG use PLL 0xff63c000 */ #define HHI_GP0_PLL_CNTL_AXG 0x10 #define HHI_GP0_PLL_CNTL2_AXG 0x11 @@ -175,14 +204,15 @@ #define HHI_MIPIDSI_PHY_CLK_CNTL 0x95 -#define HHI_MIPI_CNTL0 0x00 -#define HHI_MIPI_CNTL1 0x01 -#define HHI_MIPI_CNTL2 0x02 +#define HHI_MIPI_CNTL0 0x00 +#define HHI_MIPI_CNTL1 0x01 +#define HHI_MIPI_CNTL2 0x02 #define HHI_DIF_TCON_CNTL0 0x3c #define HHI_DIF_TCON_CNTL1 0x3d #define HHI_DIF_TCON_CNTL2 0x3e #define HHI_TCON_CLK_CNTL 0xf0 +#define HHI_TCON_CLK_CNTL_TL1 0x9c /* Global control: RESET_CBUS_BASE = 0x11 */ #define VERSION_CTRL 0x1100 @@ -711,6 +741,9 @@ * G5B10 Other */ #define LCD_MCU_DATA_1 0x14df +#define LVDS_CH_SWAP0 0x14e1 +#define LVDS_CH_SWAP1 0x14e2 +#define LVDS_CH_SWAP2 0x14e3 /* LVDS */ #define LVDS_GEN_CNTL 0x14e0 #define LVDS_PHY_CNTL0 0x14e1 @@ -909,8 +942,13 @@ #define ENCL_DACSEL_0 0x1cc9 #define ENCL_DACSEL_1 0x1cca +#define ENCL_VIDEO_H_PRE_DE_END 0x1ccf +#define ENCL_VIDEO_H_PRE_DE_BEGIN 0x1cd0 +#define ENCL_VIDEO_V_PRE_DE_ELINE 0x1cd1 +#define ENCL_VIDEO_V_PRE_DE_BLINE 0x1cd2 #define ENCL_INBUF_CNTL0 0x1cd3 #define ENCL_INBUF_CNTL1 0x1cd4 +#define ENCL_INBUF_CNT 0x1cd5 /* ******************************** * TCON TOP: TCON_TOP_BASE = 0x2000 @@ -920,6 +958,7 @@ #define TCON_CTRL_TIMING_BASE 0x01b0 +#define TCON_TOP_BASE 0x2000 #define TCON_TOP_CTRL 0x2000 #define TCON_RGB_IN_MUX 0x2001 #define TCON_OUT_CH_SEL0 0x2002 diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index b2e26713d24a..dfd90ca4ed59 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -33,6 +33,7 @@ #include "lcd_common.h" #include "lcd_reg.h" #include "lcd_tcon.h" +#include "tcon_ceds.h" #define TCON_INTR_MASKN_VAL 0x0 /* default mask all */ @@ -54,6 +55,48 @@ static int lcd_tcon_valid_check(void) return 0; } +unsigned int lcd_tcon_reg_read(unsigned int addr) +{ + unsigned int val; + int ret; + + ret = lcd_tcon_valid_check(); + if (ret) + return 0; + + if (addr < TCON_TOP_BASE) { + if (lcd_tcon_data->core_reg_width == 8) + val = lcd_tcon_read_byte(addr); + else + val = lcd_tcon_read(addr); + } else { + val = lcd_tcon_read(addr); + } + + return val; +} + +void lcd_tcon_reg_write(unsigned int addr, unsigned int val) +{ + unsigned char temp; + int ret; + + ret = lcd_tcon_valid_check(); + if (ret) + return; + + if (addr < TCON_TOP_BASE) { + if (lcd_tcon_data->core_reg_width == 8) { + temp = (unsigned char)val; + lcd_tcon_write_byte(addr, temp); + } else { + lcd_tcon_write(addr, val); + } + } else { + lcd_tcon_write(addr, val); + } +} + static void lcd_tcon_od_check(unsigned char *table) { unsigned int reg, bit; @@ -227,6 +270,7 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) LCDPR("tcon axi_offset_addr = 0x%08x\n", lcd_tcon_data->axi_offset_addr); +#if 0 /* get reg table from unifykey */ reg_len = lcd_tcon_data->reg_table_len; if (lcd_tcon_data->reg_table == NULL) { @@ -254,6 +298,17 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) __func__); return -1; } +#else + reg_len = lcd_tcon_data->reg_table_len; + lcd_tcon_data->reg_table = uhd_tcon_setting_ceds_h10; + key_len = sizeof(uhd_tcon_setting_ceds_h10)/sizeof(unsigned char); + if (key_len != reg_len) { + lcd_tcon_data->reg_table = NULL; + LCDERR("%s: !!!!!!!!tcon unifykey load length error!!!!!!!!\n", + __func__); + return -1; + } +#endif LCDPR("tcon: load key len: %d\n", key_len); lcd_tcon_intr_init(lcd_drv); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 4124b6735c90..072e0f4fcd2a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -75,6 +75,7 @@ static int lcd_type_supported(struct lcd_config_s *pconf) static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int vswing, preem, ext_pullup; unsigned int data32; unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; @@ -97,17 +98,41 @@ static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) __func__, preem); preem = VX1_PHY_PREEM_DFT; } - if (ext_pullup) - data32 = VX1_PHY_CNTL1_G9TV_PULLUP | (vswing << 3); - else - data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | - (rinner_table[ext_pullup] << 8); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = VX1_PHY_CNTL3_G9TV; - /*lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x00000a7c);*/ - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xf02027af); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x26022602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x26022602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x26022602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x26022602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x26022602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x26022602); + break; + default: + if (ext_pullup) { + data32 = VX1_PHY_CNTL1_G9TV_PULLUP | + (vswing << 3); + } else { + data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | + (rinner_table[ext_pullup] << 8); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + data32 = VX1_PHY_CNTL3_G9TV; + /*lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x00000a7c);*/ + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + break; + } } else { lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); @@ -117,6 +142,7 @@ static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; unsigned int data32; @@ -151,15 +177,36 @@ static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) clk_preem = LVDS_PHY_CLK_PREEM_DFT; } - data32 = LVDS_PHY_CNTL1_G9TV | - (vswing << 26) | (preem << 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = LVDS_PHY_CNTL2_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = LVDS_PHY_CNTL3_G9TV | - (channel_on << 16) | - (clk_vswing << 8) | (clk_preem << 5); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027ef); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); + break; + default: + data32 = LVDS_PHY_CNTL1_G9TV | + (vswing << 26) | (preem << 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + data32 = LVDS_PHY_CNTL2_G9TV; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + data32 = LVDS_PHY_CNTL3_G9TV | + (channel_on << 16) | + (clk_vswing << 8) | (clk_preem << 5); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + break; + } } else { lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); @@ -209,37 +256,25 @@ static void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) { - unsigned int vswing, preem; - unsigned int data32; - if (lcd_debug_print_flag) LCDPR("%s: %d\n", __func__, status); if (status) { - vswing = pconf->lcd_control.p2p_config->phy_vswing; - preem = pconf->lcd_control.p2p_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - if (preem > 3) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - - data32 = MLVDS_PHY_CNTL1_TL1 | - (vswing << 3) | (vswing << 0) | (preem << 23); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = MLVDS_PHY_CNTL2_TL1 | - (preem << 14) | (preem << 12) | - (preem << 26) | (preem << 24); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = MLVDS_PHY_CNTL3_TL1 | - (preem << 6) | (preem << 4) | - (preem << 2) | (preem << 0) | (preem << 30); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027af); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); } else { lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); @@ -318,6 +353,20 @@ static void lcd_venc_set(struct lcd_config_s *pconf) lcd_vcbus_write(ENCL_VIDEO_HAVON_END, h_active - 1 + video_on_pixel); lcd_vcbus_write(ENCL_VIDEO_VAVON_BLINE, video_on_line); lcd_vcbus_write(ENCL_VIDEO_VAVON_ELINE, v_active - 1 + video_on_line); + switch (pconf->lcd_basic.lcd_type) { + case LCD_P2P: + lcd_vcbus_write(ENCL_VIDEO_V_PRE_DE_BLINE, + video_on_line - 1 - 4); + lcd_vcbus_write(ENCL_VIDEO_V_PRE_DE_ELINE, + video_on_line - 1); + lcd_vcbus_write(ENCL_VIDEO_H_PRE_DE_BEGIN, + video_on_pixel + PRE_DE_DELAY); + lcd_vcbus_write(ENCL_VIDEO_H_PRE_DE_END, + h_active - 1 + video_on_pixel + PRE_DE_DELAY); + break; + default: + break; + } lcd_vcbus_write(ENCL_VIDEO_HSO_BEGIN, pconf->lcd_timing.hs_hs_addr); lcd_vcbus_write(ENCL_VIDEO_HSO_END, pconf->lcd_timing.hs_he_addr); @@ -352,7 +401,20 @@ static void lcd_venc_set(struct lcd_config_s *pconf) static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int phy_div; + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } if (pconf->lcd_control.lvds_config->dual_port) phy_div = 2; @@ -360,23 +422,32 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) phy_div = 1; /* set fifo_clk_sel: div 7 */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (1 << 6)); + lcd_hiu_write(reg_cntl0, (1 << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static void lcd_lvds_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int bit_num = 1; unsigned int pn_swap, port_swap, lane_reverse; unsigned int dual_port, fifo_mode; unsigned int lvds_repack = 1; + unsigned int ch_swap0, ch_swap1, ch_swap2; if (lcd_debug_print_flag) LCDPR("%s\n", __func__); @@ -423,10 +494,21 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) (1 << 12) | /* g_select //0:R, 1:G, 2:B, 3:0 */ (2 << 14)); /* b_select //0:R, 1:G, 2:B, 3:0 */ - lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); - - if (lane_reverse) - lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + ch_swap0 = 0x3210; + ch_swap1 = 0x7654; + ch_swap2 = 0xba98; + lcd_vcbus_write(LVDS_CH_SWAP0, ch_swap0); + lcd_vcbus_write(LVDS_CH_SWAP1, ch_swap1); + lcd_vcbus_write(LVDS_CH_SWAP2, ch_swap2); + break; + default: + lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); + if (lane_reverse) + lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + break; + } lcd_vcbus_write(LVDS_GEN_CNTL, (lcd_vcbus_read(LVDS_GEN_CNTL) | (1 << 4) | (fifo_mode << 0))); @@ -548,6 +630,19 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) { unsigned int lcd_bits; unsigned int div_sel, phy_div; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } phy_div = pconf->lcd_control.vbyone_config->phy_div; lcd_bits = pconf->lcd_basic.lcd_bits; @@ -567,20 +662,28 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) break; } /* set fifo_clk_sel */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); + lcd_hiu_write(reg_cntl0, (div_sel << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, int hsize, int vsize) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int sublane_num; int region_size[4]; int tmp; @@ -644,6 +747,16 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, lcd_vcbus_setb(VBO_CTRL_H, 0x1, 9, 1); /* lcd_vcbus_setb(VBO_CTRL_L,enable,0,1); */ + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); + lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); + lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); + break; + default: + break; + } + return 0; } @@ -775,7 +888,8 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* lcd_vcbus_setb(LCD_PORT_SWAP, 1, 8, 1);//reverse lane output order */ /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ - lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1); + /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ + lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); @@ -1295,10 +1409,39 @@ static irqreturn_t lcd_vbyone_interrupt_handler(int irq, void *dev_id) static void lcd_p2p_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg_cntl0, reg_cntl1; + if (lcd_debug_print_flag) LCDPR("%s\n", __func__); - lcd_vbyone_control_set(pconf); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } + + /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ + lcd_hiu_write(reg_cntl0, (2 << 6)); + /* serializer_en[27:16] */ + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + /* pn swap[2] */ + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + + /* fifo enable[30], phy_clock gating[24] */ + lcd_hiu_write(reg_cntl1, (1 << 30) | (1 << 24)); + /* fifo write enable[31] */ + lcd_hiu_setb(reg_cntl1, 1, 31, 1); + + /* channel swap default no swap */ + lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); + lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); + lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); lcd_tcon_enable(pconf); } @@ -1306,8 +1449,6 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) static void lcd_p2p_disable(void) { lcd_tcon_disable(); - - lcd_vbyone_disable(); } static unsigned int vbyone_lane_num[] = { @@ -1583,8 +1724,8 @@ int lcd_tv_driver_init(void) break; case LCD_P2P: lcd_p2p_control_set(pconf); - lcd_tcon_pinmux_set(1); lcd_p2p_phy_set(pconf, 1); + lcd_tcon_pinmux_set(1); break; default: break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index 352e5a56b5c9..cbe6cef7f9ce 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -1001,6 +1001,8 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, } } break; + case LCD_P2P: + break; default: LCDERR("invalid lcd type\n"); break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 4f4574f4ce13..1680588b5a34 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -115,6 +115,36 @@ static struct vbyone_config_s lcd_vbyone_config = { .cdr_training_hold = VX1_CDR_TRAINING_HOLD_DFT, }; +static struct mlvds_config_s lcd_mlvds_config = { + .channel_num = 12, + .channel_sel0 = 0x76543210, + .channel_sel1 = 0xba98, + .clk_phase = 0, + .pn_swap = 0, + .bit_swap = 0, + .phy_vswing = 0, + .phy_preem = 0, + + .pi_clk_sel = 0, + .bit_rate = 0, +}; + +static struct p2p_config_s lcd_p2p_config = { + .p2p_type = P2P_MAX, + .port_num = 6, + .lane_num = 12, + .channel_sel0 = 0x76543210, + .channel_sel1 = 0xba98, + .clk_phase = 0, + .pn_swap = 0, + .bit_swap = 0, + .phy_vswing = 0, + .phy_preem = 0, + + .pi_clk_sel = 0, + .bit_rate = 0, +}; + static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff}; static unsigned char dsi_init_off_table[DSI_INIT_OFF_MAX] = {0xff, 0xff}; @@ -197,6 +227,8 @@ static struct lcd_config_s lcd_config_dft = { .ttl_config = &lcd_ttl_config, .lvds_config = &lcd_lvds_config, .vbyone_config = &lcd_vbyone_config, + .mlvds_config = &lcd_mlvds_config, + .p2p_config = &lcd_p2p_config, .mipi_config = &lcd_mipi_config, .vlock_param = vlock_param, }, @@ -965,6 +997,8 @@ static int lcd_mode_probe(struct device *dev) LCDERR("invalid lcd mode: %d\n", lcd_driver->lcd_mode); break; } + if (lcd_driver->data->chip_type == LCD_CHIP_TL1) + lcd_tcon_probe(lcd_driver); lcd_debug_probe(); lcd_fops_create(); diff --git a/drivers/amlogic/media/vout/lcd/tcon_ceds.h b/drivers/amlogic/media/vout/lcd/tcon_ceds.h new file mode 100644 index 000000000000..169cd79fd69a --- /dev/null +++ b/drivers/amlogic/media/vout/lcd/tcon_ceds.h @@ -0,0 +1,24019 @@ +/* + * drivers/amlogic/media/vout/lcd/tcon_ceds.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +unsigned char uhd_tcon_setting_ceds_h10[] = { +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x07, +0x00, +0xFF, +0x00, +0x07, +0x00, +0x00, +0xFF, +0x07, +0xFF, +0xFF, +0xFF, +0x07, +0x7F, +0x7F, +0x7F, +0x07, +0x00, +0x00, +0x00, +0x00, +0x63, +0x22, +0x51, +0xB0, +0x2D, +0x05, +0xA0, +0x50, +0x0A, +0x00, +0x80, +0x00, +0x80, +0x00, +0x00, +0x19, +0x00, +0x32, +0x01, +0x00, +0x05, +0x00, +0x12, +0x80, +0x0E, +0x00, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x66, +0x66, +0x66, +0x66, +0x65, +0x66, +0x66, +0x66, +0x00, +0x00, +0x00, +0x01, +0x0D, +0x00, +0x87, +0x00, +0x00, +0x00, +0x00, +0x00, +0x55, +0x83, +0x80, +0x03, +0x28, +0x45, +0x00, +0x00, +0x28, +0x40, +0x00, +0x05, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x0B, +0x50, +0x1A, +0x70, +0x34, +0x00, +0x44, +0x00, +0x47, +0xF0, +0x48, +0x50, +0x4C, +0xE0, +0xB4, +0x33, +0x00, +0x3B, +0x00, +0x06, +0x01, +0x00, +0x02, +0x27, +0x52, +0xF0, +0x54, +0x00, +0x55, +0x10, +0x5C, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xE8, +0x01, +0x5A, +0x00, +0x2A, +0xE8, +0x00, +0x02, +0x00, +0x02, +0x3D, +0xA3, +0xC2, +0x33, +0x82, +0xCA, +0x28, +0xC2, +0x2D, +0x22, +0xB1, +0xFB, +0x1F, +0xA1, +0x56, +0x11, +0x90, +0xBD, +0x02, +0xD0, +0x14, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x08, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3B, +0x00, +0x00, +0x00, +0x00, +0x00, +0x06, +0x3B, +0x01, +0x00, +0x00, +0x00, +0x00, +0x9F, +0x3B, +0x02, +0x00, +0x00, +0x53, +0x42, +0x31, +0x37, +0x30, +0x32, +0x38, +0xC2, +0x28, +0x15, +0x20, +0x00, +0x00, +0x00, +0x05, +0x00, +0x01, +0x86, +0x01, +0x87, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x13, +0x00, +0x1E, +0x00, +0x00, +0x71, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x3F, +0xFF, +0xFF, +0xFF, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x2A, +0x58, +0x58, +0x58, +0x2A, +0xC8, +0xC8, +0xC8, +0x2A, +0x00, +0x00, +0x00, +0x00, +0xCC, +0xCC, +0xCC, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x00, +0x7F, +0x7F, +0x7F, +0x00, +0x3F, +0x3F, +0x3F, +0x15, +0xFF, +0xFF, +0xFF, +0x00, +0xFF, +0xFF, +0xFF, +0x3F, +0xFF, +0xFF, +0xFF, +0x00, +0x1F, +0x1F, +0x1F, +0xFF, +0x7F, +0x3F, +0x00, +0x00, +0x00, +0x46, +0x20, +0x00, +0xFF, +0x0C, +0xFF, +0x8F, +0x70, +0x76, +0x08, +0xFC, +0x40, +0x4C, +0x96, +0xCC, +0x01, +0xFF, +0x0A, +0x0A, +0x0A, +0x0C, +0x14, +0x47, +0x80, +0x08, +0x70, +0x2B, +0xB8, +0x08, +0x98, +0x08, +0x98, +0x08, +0x98, +0x89, +0x00, +0x0A, +0x00, +0x0F, +0x05, +0xDC, +0x03, +0x00, +0x0A, +0x3F, +0x1B, +0x0F, +0x1B, +0x00, +0x05, +0x03, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x32, +0x32, +0x32, +0x00, +0x00, +0x00, +0x02, +0x00, +0x00, +0x00, +0x7F, +0xFF, +0xFF, +0x61, +0x00, +0x01, +0x01, +0x02, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x40, +0x00, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x64, +0x64, +0x64, +0x14, +0x00, +0x00, +0x10, +0x32, +0x54, +0x10, +0x32, +0x54, +0x00, +0x14, +0x14, +0x28, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x30, +0xE8, +0xFC, +0x03, +0x21, +0x49, +0xFF, +0xFF, +0xFF, +0x04, +0x20, +0xA0, +0x86, +0x01, +0x00, +0xA0, +0x86, +0x01, +0xD0, +0x38, +0x34, +0xC0, +0x38, +0x74, +0x01, +0xA0, +0xC7, +0x11, +0xC7, +0x27, +0x10, +0x20, +0xA0, +0xFF, +0x11, +0xFF, +0x0E, +0x10, +0x20, +0xA0, +0x38, +0x01, +0xC0, +0xA7, +0xF8, +0x20, +0xA0, +0x3F, +0x00, +0x3F, +0x3E, +0x80, +0x20, +0xA0, +0x07, +0x00, +0x07, +0x0B, +0xB8, +0x20, +0xE0, +0x07, +0x00, +0x07, +0x05, +0x14, +0x20, +0x20, +0xCC, +0xCC, +0xCC, +0xFD, +0xE8, +0x20, +0x21, +0xC7, +0x10, +0x00, +0x03, +0xE8, +0x20, +0x80, +0xC7, +0x11, +0xC7, +0x27, +0x10, +0x20, +0x20, +0xC7, +0x11, +0xC7, +0x27, +0x10, +0x20, +0xA0, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x34, +0x50, +0xFF, +0x30, +0xC7, +0x01, +0x10, +0x27, +0x02, +0x80, +0x00, +0x00, +0x00, +0x01, +0xC7, +0x01, +0xC7, +0x00, +0x01, +0x00, +0x00, +0x01, +0xC7, +0x27, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x20, +0x22, +0x00, +0x10, +0x22, +0x22, +0x34, +0x22, +0x46, +0x58, +0x22, +0x6B, +0x7D, +0x22, +0x8F, +0xA2, +0x22, +0xB4, +0xC6, +0x22, +0xD8, +0xEB, +0x23, +0xFD, +0x0F, +0x33, +0x22, +0x34, +0x33, +0x46, +0x58, +0x33, +0x6B, +0x7D, +0x33, +0x8F, +0xA2, +0x33, +0xB4, +0xC6, +0x33, +0xD8, +0xEB, +0x34, +0xFD, +0x0F, +0x44, +0x21, +0x34, +0x40, +0x47, +0x00, +0x00, +0x00, +0x04, +0x40, +0x10, +0x01, +0x08, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0xC0, +0x40, +0x00, +0x00, +0x00, +0x00, +0xC0, +0x40, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0x00, +0x00, +0x40, +0xC0, +0x00, +0x00, +0x00, +0x00, +0x40, +0xC0, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x40, +0xC0, +0x00, +0x40, +0xC0, +0x00, +0x40, +0xC0, +0x00, +0x40, +0xC0, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x8B, +0x33, +0xE1, +0x11, +0x0F, +0x00, +0x00, +0x00, +0x44, +0x01, +0x90, +0x04, +0xC0, +0x0B, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x0F, +0xFF, +0x03, +0x14, +0x01, +0x41, +0x00, +0xA0, +0x00, +0xD6, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x38, +0xC2, +0x08, +0x08, +0x00, +0x08, +0x08, +0x00, +0x54, +0xAA, +0x55, +0x80, +0xFC, +0x00, +0x0E, +0x00, +0x80, +0x00, +0x08, +0x07, +0x80, +0x07, +0x80, +0x0E, +0x00, +0x20, +0x01, +0x1E, +0xF0, +0x1A, +0x00, +0x0C, +0x0D, +0xB7, +0x03, +0x94, +0x18, +0x00, +0x10, +0xF0, +0x07, +0x80, +0x20, +0x00, +0x66, +0x0B, +0x0B, +0x33, +0x0E, +0x1C, +0x2A, +0x38, +0x46, +0x54, +0x62, +0x69, +0x70, +0x77, +0x79, +0x7B, +0x7D, +0x7E, +0x02, +0x04, +0x00, +0x04, +0x00, +0x0D, +0x3E, +0x0E, +0x3C, +0x1F, +0x3A, +0x1F, +0x38, +0x1F, +0x78, +0x18, +0x78, +0x19, +0x76, +0x1A, +0x76, +0x1B, +0x74, +0x2C, +0x74, +0x2D, +0x74, +0x3D, +0x74, +0x6F, +0x00, +0x08, +0x11, +0x1A, +0x23, +0x2C, +0x2D, +0x3E, +0x10, +0x22, +0x33, +0x44, +0x55, +0x66, +0x87, +0x88, +0xCA, +0xF5, +0xF0, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x00, +0x08, +0x07, +0x80, +0x07, +0x80, +0x82, +0x00, +0x01, +0x1E, +0x60, +0x1A, +0x0C, +0x0D, +0xB7, +0x03, +0x94, +0x18, +0x00, +0x10, +0xF0, +0x20, +0x00, +0x0B, +0x0B, +0x33, +0x0E, +0x1C, +0x2A, +0x38, +0x46, +0x54, +0x62, +0x69, +0x70, +0x77, +0x79, +0x7B, +0x7D, +0x7E, +0x02, +0x20, +0x00, +0x20, +0x00, +0x29, +0x3E, +0x31, +0x3C, +0x3B, +0x3A, +0x3B, +0x38, +0x3B, +0x38, +0x43, +0x38, +0x4B, +0x36, +0x53, +0x36, +0x5B, +0x34, +0x65, +0x34, +0x6D, +0x34, +0x6F, +0x74, +0x7D, +0x10, +0x22, +0x33, +0x44, +0x55, +0x66, +0x87, +0x88, +0x00, +0x10, +0x21, +0x32, +0x43, +0x54, +0x55, +0x76, +0x5A, +0x04, +0x28, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x28, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0x5F, +0xA0, +0x00, +0x07, +0x04, +0x0B, +0x33, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xBA, +0x32, +0x28, +0x10, +0xE0, +0x81, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0xA5, +0x2D, +0x36, +0x2D, +0x36, +0x10, +0x00, +0x00, +0xD5, +0x5E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x0A, +0x00, +0x00, +0xAA, +0x55, +0xAA, +0x44, +0x66, +0x88, +0x11, +0x33, +0x55, +0x00, +0x00, +0x00, +0xAA, +0xCC, +0xEE, +0x77, +0x99, +0xBB, +0x00, +0x00, +0x00, +0x88, +0xAA, +0xCC, +0x55, +0x77, +0x99, +0x00, +0x00, +0x00, +0xEE, +0x00, +0x22, +0xBB, +0xDD, +0xFF, +0x00, +0x00, +0x00, +0x66, +0x66, +0x66, +0xBB, +0xBB, +0xBB, +0x00, +0x00, +0x00, +0x66, +0xAA, +0xAA, +0xBB, +0xBB, +0xBB, +0x00, +0x00, +0x00, +0x01, +0x00, +0x00, +0x00, +0x00, +0x03, +0x30, +0x90, +0xC2, +0x22, +0x82, +0xE2, +0x42, +0xA2, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x6F, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3F, +0x00, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x02, +0x00, +0x10, +0xEA, +0x06, +0x90, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x05, +0x00, +0x00, +0x00, +0x03, +0x90, +0xFF, +0xFF, +0x00, +0xF0, +0xE0, +0xD0, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x00, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x64, +0x64, +0x64, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x65, +0xC1, +0x07, +0x10, +0xE0, +0x00, +0x04, +0x13, +0x40, +0x00, +0x60, +0x00, +0x00, +0x3F, +0xFF, +0x00, +0x00, +0x3F, +0xFF, +0x00, +0x00, +0x3F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x20, +0x10, +0x04, +0x29, +0x00, +0x00, +0x08, +0x08, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x40, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xB9, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x05, +0x40, +0x40, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xB0, +0x00, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x8C, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFC, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x40, +0x00, +0x02, +0x03, +0x00, +0x00, +0x0C, +0x64, +0x08, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x83, +0x1E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x8C, +0x00, +0x0B, +0x0A, +0x09, +0x08, +0x07, +0x06, +0x05, +0x04, +0x03, +0x02, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x32, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0xA8, +0x61, +0xC4, +0x09, +0x03, +0x03, +0x7C, +0x13, +0x23, +0x33, +0x43, +0x53, +0x63, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x98, +0x3A, +0x31, +0x2F, +0x07, +0x27, +0x01, +0x00, +0x48, +0x00, +0x00, +0x49, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x70, +0x57, +0xA0, +0x3C, +0x00, +0x11, +0x22, +0x33, +0x44, +0x55, +0x00, +0x00, +0xFF, +0x00, +0xFA, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x44, +0x01, +0x89, +0x20, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x99, +0x30, +0x01, +0x00, +0x06, +0x20, +0x11, +0x40, +0x41, +0x24, +0x24, +0x01, +0x08, +0x80, +0x01, +0x00, +0x01, +0x80, +0x01, +0x0A, +0x40, +0x24, +0x24, +0x01, +0x01, +0x10, +0x01, +0x0A, +0x08, +0x01, +0x11, +0x40, +0x41, +0x24, +0x44, +0x01, +0x09, +0x40, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x19, +0x50, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x29, +0x60, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x39, +0x70, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x49, +0x80, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x59, +0x90, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x69, +0x00, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x79, +0x10, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x20, +0x0C, +0x00, +0x00, +0x5A, +0x00, +0x1C, +0x01, +0x13, +0x64, +0x00, +0x00, +0x31, +0x0C, +0x00, +0x00, +0x5A, +0x00, +0x1C, +0x01, +0x13, +0x64, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x00, +0x00, +0x00, +0x01, +0x00, +0x01, +0x00, +0x87, +0x32, +0x20, +0x03, +0xF0, +0xB0, +0xF0, +0xF0, +0x70, +0x80, +0x00, +0x10, +0xC0, +0xD0, +0x20, +0x40, +0x50, +0x60, +0x90, +0xA0, +0x4F, +0x50, +0x61, +0xFF, +0x7F, +0x8F, +0x92, +0x13, +0x00, +0x0D, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x44, +0x50, +0x44, +0x44, +0x44, +0x44, +0x55, +0x00, +0x00, +0x00, +0xFF, +0xFF, +0x02, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x4E, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x3C, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x21, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x82, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x1E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0xD2, +0x00, +0x00, +0x00, +0x7F, +0x80, +0xE0, +0x00, +0x80, +0x7E, +0x00, +0xE0, +0x00, +0xE0, +0x80, +0x7E, +0xE0, +0x00, +0x7E, +0x80, +0x68, +0x80, +0x80, +0x10, +0x80, +0x69, +0x10, +0x80, +0x10, +0x80, +0x80, +0x68, +0x80, +0x10, +0x69, +0x80, +0x60, +0x84, +0x78, +0x80, +0x90, +0x61, +0x80, +0x78, +0x80, +0x78, +0x80, +0x60, +0x78, +0x80, +0x60, +0x84, +0x01, +0x96, +0x7C, +0x80, +0x96, +0x00, +0x80, +0x78, +0x80, +0x78, +0x96, +0x00, +0x6C, +0x80, +0x00, +0x96, +0x80, +0x70, +0x16, +0x88, +0x70, +0x80, +0x88, +0x56, +0x88, +0x56, +0x70, +0x80, +0x06, +0x88, +0x81, +0x70, +0x80, +0x60, +0x50, +0xE8, +0x70, +0x80, +0xE8, +0x10, +0xE8, +0x10, +0x60, +0x80, +0x50, +0xE8, +0x80, +0x60, +0x80, +0x48, +0x80, +0x70, +0x4C, +0x80, +0x70, +0x80, +0x70, +0x80, +0x4C, +0x81, +0x80, +0x70, +0x80, +0x48, +0x90, +0x68, +0x80, +0x66, +0x68, +0x94, +0x66, +0x80, +0x66, +0x80, +0x68, +0x95, +0x80, +0x66, +0x90, +0x68, +0x78, +0x80, +0x80, +0x00, +0x80, +0x78, +0x00, +0x80, +0x00, +0x80, +0x80, +0x78, +0x80, +0x00, +0x78, +0x80, +0x68, +0x80, +0x80, +0x76, +0x80, +0x68, +0x76, +0x81, +0x76, +0x80, +0x80, +0x68, +0x80, +0x76, +0x68, +0x80, +0x10, +0x80, +0x7E, +0x80, +0x84, +0x00, +0x80, +0x7E, +0x80, +0x7F, +0x94, +0x00, +0x7E, +0x80, +0x00, +0x90, +0x00, +0xF0, +0x68, +0x80, +0xF0, +0x04, +0x80, +0x68, +0x80, +0x69, +0xF0, +0x04, +0x68, +0x90, +0x00, +0xF0, +0xC0, +0x70, +0x61, +0x88, +0x70, +0x80, +0x88, +0x60, +0x88, +0x60, +0x70, +0x80, +0x61, +0x98, +0xC0, +0x70, +0x90, +0x66, +0x10, +0x88, +0x66, +0x80, +0x88, +0x50, +0x88, +0x50, +0x76, +0x80, +0x11, +0x88, +0x80, +0x76, +0xE6, +0x08, +0x80, +0x74, +0x08, +0xE6, +0x70, +0x81, +0x70, +0x80, +0x08, +0xE6, +0x80, +0x74, +0xE6, +0x08, +0x94, +0x48, +0x81, +0x60, +0x48, +0x90, +0x60, +0x80, +0x60, +0x80, +0x48, +0x90, +0x80, +0x60, +0x94, +0x48, +0x7F, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7F, +0x80, +0xE0, +0x00, +0x80, +0x7E, +0x00, +0xE0, +0x00, +0xE0, +0x80, +0x7E, +0xE0, +0x00, +0x7E, +0x80, +0x68, +0x80, +0x80, +0x10, +0x80, +0x69, +0x10, +0x80, +0x10, +0x80, +0x80, +0x68, +0x80, +0x10, +0x69, +0x80, +0x60, +0x84, +0x78, +0x80, +0x90, +0x61, +0x80, +0x78, +0x80, +0x78, +0x80, +0x60, +0x78, +0x80, +0x60, +0x84, +0x01, +0x96, +0x7C, +0x80, +0x96, +0x00, +0x80, +0x78, +0x80, +0x78, +0x96, +0x00, +0x6C, +0x80, +0x00, +0x96, +0x80, +0x70, +0x16, +0x88, +0x70, +0x80, +0x88, +0x56, +0x88, +0x56, +0x70, +0x80, +0x06, +0x88, +0x81, +0x70, +0x80, +0x60, +0x50, +0xE8, +0x70, +0x80, +0xE8, +0x10, +0xE8, +0x10, +0x60, +0x80, +0x50, +0xE8, +0x80, +0x60, +0x80, +0x48, +0x80, +0x70, +0x4C, +0x80, +0x70, +0x80, +0x70, +0x80, +0x4C, +0x81, +0x80, +0x70, +0x80, +0x48, +0x90, +0x68, +0x80, +0x66, +0x68, +0x94, +0x66, +0x80, +0x66, +0x80, +0x68, +0x95, +0x80, +0x66, +0x90, +0x68, +0x78, +0x80, +0x80, +0x00, +0x80, +0x78, +0x00, +0x80, +0x00, +0x80, +0x80, +0x78, +0x80, +0x00, +0x78, +0x80, +0x68, +0x80, +0x80, +0x76, +0x80, +0x68, +0x76, +0x81, +0x76, +0x80, +0x80, +0x68, +0x80, +0x76, +0x68, +0x80, +0x10, +0x80, +0x7E, +0x80, +0x84, +0x00, +0x80, +0x7E, +0x80, +0x7F, +0x94, +0x00, +0x7E, +0x80, +0x00, +0x90, +0x00, +0xF0, +0x68, +0x80, +0xF0, +0x04, +0x80, +0x68, +0x80, +0x69, +0xF0, +0x04, +0x68, +0x90, +0x00, +0xF0, +0xC0, +0x70, +0x61, +0x88, +0x70, +0x80, +0x88, +0x60, +0x88, +0x60, +0x70, +0x80, +0x61, +0x98, +0xC0, +0x70, +0x90, +0x66, +0x10, +0x88, +0x66, +0x80, +0x88, +0x50, +0x88, +0x50, +0x76, +0x80, +0x11, +0x88, +0x80, +0x76, +0xE6, +0x08, +0x80, +0x74, +0x08, +0xE6, +0x70, +0x81, +0x70, +0x80, +0x08, +0xE6, +0x80, +0x74, +0xE6, +0x08, +0x94, +0x48, +0x81, +0x60, +0x48, +0x90, +0x60, +0x80, +0x60, +0x80, +0x48, +0x90, +0x80, +0x60, +0x94, +0x48, +0x7F, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x5B, +0x7C, +0x1A, +0x64, +0x1B, +0x3D, +0xE8, +0x71, +0x4E, +0xB4, +0x95, +0x2B, +0x8F, +0xA3, +0x64, +0x2A, +0x90, +0xE8, +0xB3, +0xEA, +0x5C, +0xFC, +0xD3, +0x60, +0xE1, +0x6F, +0x2C, +0xD7, +0x62, +0x7B, +0xD9, +0x72, +0x17, +0x47, +0x5E, +0x1D, +0x65, +0x40, +0xB8, +0x10, +0xA9, +0x95, +0x63, +0xC0, +0x3F, +0xF0, +0xB8, +0x93, +0xCA, +0x2D, +0xE4, +0x8E, +0xB8, +0x2D, +0x2B, +0x4E, +0xBF, +0x15, +0x9C, +0x2A, +0x19, +0x73, +0x6C, +0x30, +0x5D, +0x1A, +0x4D, +0xF1, +0x68, +0xE6, +0x3F, +0x50, +0xF8, +0x46, +0xDE, +0x27, +0xEA, +0x7F, +0xA2, +0x16, +0xC7, +0xC9, +0xB8, +0x93, +0x30, +0xFD, +0xA5, +0xC9, +0x85, +0xF0, +0x5D, +0x4C, +0x90, +0xA7, +0x20, +0x48, +0x38, +0xB1, +0xE7, +0xED, +0xF6, +0x92, +0x02, +0xDF, +0xB5, +0x70, +0x4E, +0xD6, +0x40, +0x2D, +0x5C, +0x91, +0x7C, +0x6F, +0x8F, +0x50, +0x39, +0x1A, +0x69, +0x4F, +0xB8, +0x49, +0x0A, +0x65, +0x4F, +0x20, +0x46, +0xA7, +0xEC, +0xD5, +0x81, +0xE7, +0x2D, +0xAC, +0x83, +0xCA, +0xE3, +0x7F, +0xEC, +0x1B, +0xA2, +0x79, +0x3C, +0x5D, +0x73, +0x85, +0x1B, +0x57, +0x16, +0xD4, +0x04, +0xD5, +0x86, +0xAF, +0x60, +0xC4, +0xE4, +0xBF, +0x90, +0xFB, +0x92, +0xB9, +0xC8, +0x8E, +0x30, +0x2B, +0xA2, +0xD7, +0x6D, +0x02, +0x51, +0xB9, +0x70, +0x46, +0x39, +0xB4, +0x8E, +0x51, +0x7D, +0x1B, +0xCA, +0x59, +0x83, +0x12, +0x3E, +0xAC, +0xF6, +0x38, +0x1A, +0x3E, +0xCA, +0xF2, +0xD6, +0x0A, +0x92, +0x35, +0x61, +0x08, +0x9D, +0x57, +0x3B, +0x4C, +0xD3, +0x0A, +0x1F, +0xE5, +0xC3, +0xAE, +0x29, +0xB4, +0xA6, +0x2C, +0xD7, +0xB8, +0x37, +0x29, +0x97, +0xC7, +0xF1, +0xE3, +0x08, +0xC9, +0xC1, +0x4D, +0x05, +0x02, +0xFB, +0x84, +0xC4, +0x31, +0x6E, +0x29, +0x4B, +0x58, +0x28, +0xE8, +0x6A, +0x5E, +0x16, +0xB1, +0x0B, +0xE9, +0xD6, +0xD3, +0xFA, +0x01, +0xDF, +0x72, +0xE4, +0x03, +0xFD, +0x79, +0x8A, +0x62, +0x3C, +0x65, +0x3C, +0x7F, +0x86, +0x59, +0x1B, +0xC7, +0x4A, +0x3F, +0x24, +0xBC, +0xFA, +0x04, +0x8D, +0xE2, +0xE1, +0x0F, +0x5A, +0xFA, +0x05, +0xC6, +0x17, +0xE4, +0x4D, +0xFB, +0xB9, +0x57, +0x7B, +0xA6, +0xD2, +0x95, +0x18, +0x8E, +0x94, +0xA8, +0x2E, +0x2C, +0xDA, +0xBF, +0x08, +0xE1, +0xA4, +0xE7, +0x9F, +0xC6, +0xCA, +0x64, +0x78, +0x07, +0xE3, +0x6C, +0x53, +0xB8, +0x18, +0xD5, +0x01, +0xF3, +0x83, +0x2B, +0x0D, +0xB2, +0xD7, +0x47, +0x8E, +0xF2, +0x9D, +0xAF, +0x59, +0x2A, +0x1F, +0xEA, +0x59, +0x91, +0xC6, +0xF3, +0xB4, +0x5A, +0xC0, +0xB6, +0xC4, +0x3E, +0xE7, +0x50, +0xA4, +0x4F, +0x82, +0xAB, +0x67, +0x01, +0x5E, +0xDA, +0x97, +0xB2, +0x61, +0x3D, +0x58, +0xE0, +0xC4, +0x26, +0xA2, +0xB6, +0xD8, +0x93, +0x81, +0x0C, +0xDC, +0x79, +0x07, +0x8D, +0x57, +0x39, +0x1C, +0xF3, +0xE4, +0x42, +0xDE, +0x69, +0xF5, +0x3F, +0xB1, +0x96, +0x04, +0xD1, +0x53, +0x2C, +0x7F, +0x0B, +0xB6, +0x51, +0x0D, +0x5C, +0xE5, +0xE4, +0x37, +0x83, +0xC1, +0x6E, +0x5A, +0x2A, +0x58, +0x62, +0xD6, +0xB1, +0x4F, +0x8A, +0xAF, +0x12, +0xDB, +0x94, +0xC0, +0x83, +0xAE, +0x9D, +0x40, +0xF5, +0xA7, +0x5E, +0x21, +0xB6, +0x37, +0x09, +0xE4, +0x51, +0xD7, +0xB5, +0xB6, +0x37, +0xC2, +0xD7, +0x94, +0x0D, +0x9F, +0xB3, +0x17, +0x2C, +0x60, +0xF8, +0x92, +0x8D, +0x1E, +0x1A, +0x6E, +0x58, +0x50, +0xFC, +0x29, +0x84, +0x4E, +0x16, +0x0F, +0xF5, +0xCA, +0x9C, +0x0A, +0xF3, +0x3E, +0x1D, +0xA3, +0x5E, +0xBA, +0xF7, +0xA6, +0x26, +0xD4, +0x17, +0xB2, +0xCB, +0xB6, +0x89, +0x40, +0xC8, +0x24, +0x93, +0x73, +0xC0, +0x79, +0xB2, +0x8D, +0x6E, +0xF9, +0xC3, +0x08, +0xF4, +0x71, +0xDB, +0x8A, +0x36, +0xA3, +0x19, +0x90, +0xC7, +0x2D, +0x48, +0xD5, +0x91, +0x04, +0xBF, +0x50, +0x2D, +0xB9, +0xF3, +0x57, +0xEA, +0x56, +0x1D, +0x8F, +0x2F, +0xC9, +0x40, +0xDE, +0x6C, +0x16, +0xB0, +0x8D, +0x34, +0xB1, +0xC7, +0x53, +0xC7, +0x24, +0x6D, +0x98, +0xB1, +0x2C, +0x4F, +0x2A, +0x98, +0x4A, +0x6E, +0xAC, +0xE3, +0xBF, +0x07, +0x5A, +0xA3, +0xE7, +0xC6, +0xE5, +0xB0, +0x2C, +0x83, +0xE4, +0x61, +0x90, +0xDA, +0xD7, +0x7C, +0x41, +0x39, +0x91, +0x8D, +0xD0, +0x75, +0x6C, +0xB8, +0x15, +0x92, +0x4B, +0xE0, +0x63, +0xE5, +0x4E, +0x50, +0x4A, +0x62, +0x7E, +0x30, +0xFB, +0x5F, +0xE2, +0x8B, +0x1F, +0x7F, +0xF3, +0x29, +0x86, +0xAF, +0xB1, +0x7C, +0xAD, +0x28, +0xB3, +0x1E, +0x60, +0xD6, +0x8C, +0x4E, +0xA3, +0xE5, +0x1A, +0xE6, +0xDC, +0x37, +0x4C, +0xEA, +0x25, +0x5C, +0x24, +0x90, +0xFE, +0xB6, +0x62, +0xA9, +0x16, +0xD8, +0x72, +0x93, +0xFB, +0x97, +0x79, +0x1E, +0x80, +0x25, +0xCE, +0x4B, +0xF0, +0x94, +0x16, +0x5D, +0xA0, +0xA2, +0xF0, +0xD6, +0xF5, +0xD1, +0x17, +0x8D, +0x78, +0xC3, +0x3E, +0x4B, +0x85, +0x13, +0x8B, +0x3F, +0xD7, +0x3A, +0xB8, +0x2F, +0x3C, +0x5B, +0xB4, +0x20, +0xE9, +0xD7, +0x6F, +0x27, +0x0F, +0xCE, +0x42, +0x96, +0x9D, +0x60, +0x18, +0x6F, +0xAC, +0x2B, +0xA7, +0xFA, +0x18, +0x4B, +0xF9, +0xEC, +0x48, +0x17, +0x59, +0xA5, +0xD8, +0xA0, +0x19, +0xB3, +0xC4, +0x20, +0x5D, +0x50, +0x73, +0xC4, +0x81, +0xB4, +0xCE, +0x78, +0x61, +0xB5, +0x0B, +0x82, +0x97, +0x0D, +0x97, +0xF2, +0xE6, +0x07, +0xD8, +0xB2, +0xFD, +0x0A, +0x47, +0x3B, +0xE0, +0x51, +0x3F, +0x8B, +0x2A, +0xC1, +0x74, +0x3E, +0xB5, +0xF3, +0x19, +0xAF, +0x7A, +0xC3, +0x8A, +0x29, +0xCF, +0xE7, +0x5D, +0x5B, +0x4E, +0x2C, +0x6D, +0x4C, +0x93, +0x19, +0x50, +0x6E, +0x80, +0x96, +0x1F, +0xB8, +0x30, +0x95, +0x94, +0x97, +0x10, +0xA7, +0xF2, +0xD4, +0x2E, +0xDA, +0x86, +0x6F, +0xD2, +0xC4, +0xA5, +0x61, +0xDB, +0x3C, +0x64, +0xAF, +0xA5, +0x98, +0x31, +0xC4, +0x05, +0x71, +0xE7, +0xB8, +0x23, +0x04, +0xC1, +0xEB, +0xDF, +0x23, +0x06, +0x3D, +0xCE, +0x48, +0x62, +0xAD, +0xC6, +0xF9, +0x5E, +0x5A, +0x5B, +0x7C, +0x1A, +0x64, +0x1B, +0x3D, +0xE8, +0x71, +0x4E, +0xB4, +0x95, +0x2B, +0x8F, +0xA3, +0x64, +0x2A, +0x90, +0xE8, +0xB3, +0xEA, +0x5C, +0xFC, +0xD3, +0x60, +0xE1, +0x6F, +0x2C, +0xD7, +0x62, +0x7B, +0xD9, +0x72, +0x17, +0x47, +0x5E, +0x1D, +0x65, +0x40, +0xB8, +0x10, +0xA9, +0x95, +0x63, +0xC0, +0x3F, +0xF0, +0xB8, +0x93, +0xCA, +0x2D, +0xE4, +0x8E, +0xB8, +0x2D, +0x2B, +0x4E, +0xBF, +0x15, +0x9C, +0x2A, +0x19, +0x73, +0x6C, +0x30, +0x5D, +0x1A, +0x4D, +0xF1, +0x68, +0xE6, +0x3F, +0x50, +0xF8, +0x46, +0xDE, +0x27, +0xEA, +0x7F, +0xA2, +0x16, +0xC7, +0xC9, +0xB8, +0x93, +0x30, +0xFD, +0xA5, +0xC9, +0x85, +0xF0, +0x5D, +0x4C, +0x90, +0xA7, +0x20, +0x48, +0x38, +0xB1, +0xE7, +0xED, +0xF6, +0x92, +0x02, +0xDF, +0xB5, +0x70, +0x4E, +0xD6, +0x40, +0x2D, +0x5C, +0x91, +0x7C, +0x6F, +0x8F, +0x50, +0x39, +0x1A, +0x69, +0x4F, +0xB8, +0x49, +0x0A, +0x65, +0x4F, +0x20, +0x46, +0xA7, +0xEC, +0xD5, +0x81, +0xE7, +0x2D, +0xAC, +0x83, +0xCA, +0xE3, +0x7F, +0xEC, +0x1B, +0xA2, +0x79, +0x3C, +0x5D, +0x73, +0x85, +0x1B, +0x57, +0x16, +0xD4, +0x04, +0xD5, +0x86, +0xAF, +0x60, +0xC4, +0xE4, +0xBF, +0x90, +0xFB, +0x92, +0xB9, +0xC8, +0x8E, +0x30, +0x2B, +0xA2, +0xD7, +0x6D, +0x02, +0x51, +0xB9, +0x70, +0x46, +0x39, +0xB4, +0x8E, +0x51, +0x7D, +0x1B, +0xCA, +0x59, +0x83, +0x12, +0x3E, +0xAC, +0xF6, +0x38, +0x1A, +0x3E, +0xCA, +0xF2, +0xD6, +0x0A, +0x92, +0x35, +0x61, +0x08, +0x9D, +0x57, +0x3B, +0x4C, +0xD3, +0x0A, +0x1F, +0xE5, +0xC3, +0xAE, +0x29, +0xB4, +0xA6, +0x2C, +0xD7, +0xB8, +0x37, +0x29, +0x97, +0xC7, +0xF1, +0xE3, +0x08, +0xC9, +0xC1, +0x4D, +0x05, +0x02, +0xFB, +0x84, +0xC4, +0x31, +0x6E, +0x29, +0x4B, +0x58, +0x28, +0xE8, +0x6A, +0x5E, +0x16, +0xB1, +0x0B, +0xE9, +0xD6, +0xD3, +0xFA, +0x01, +0xDF, +0x72, +0xE4, +0x03, +0xFD, +0x79, +0x8A, +0x62, +0x3C, +0x65, +0x3C, +0x7F, +0x86, +0x59, +0x1B, +0xC7, +0x4A, +0x3F, +0x24, +0xBC, +0xFA, +0x04, +0x8D, +0xE2, +0xE1, +0x0F, +0x5A, +0xFA, +0x05, +0xC6, +0x17, +0xE4, +0x4D, +0xFB, +0xB9, +0x57, +0x7B, +0xA6, +0xD2, +0x95, +0x18, +0x8E, +0x94, +0xA8, +0x2E, +0x2C, +0xDA, +0xBF, +0x08, +0xE1, +0xA4, +0xE7, +0x9F, +0xC6, +0xCA, +0x64, +0x78, +0x07, +0xE3, +0x6C, +0x53, +0xB8, +0x18, +0xD5, +0x01, +0xF3, +0x83, +0x2B, +0x0D, +0xB2, +0xD7, +0x47, +0x8E, +0xF2, +0x9D, +0xAF, +0x59, +0x2A, +0x1F, +0xEA, +0x59, +0x91, +0xC6, +0xF3, +0xB4, +0x5A, +0xC0, +0xB6, +0xC4, +0x3E, +0xE7, +0x50, +0xA4, +0x4F, +0x82, +0xAB, +0x67, +0x01, +0x5E, +0xDA, +0x97, +0xB2, +0x61, +0x3D, +0x58, +0xE0, +0xC4, +0x26, +0xA2, +0xB6, +0xD8, +0x93, +0x81, +0x0C, +0xDC, +0x79, +0x07, +0x8D, +0x57, +0x39, +0x1C, +0xF3, +0xE4, +0x42, +0xDE, +0x69, +0xF5, +0x3F, +0xB1, +0x96, +0x04, +0xD1, +0x53, +0x2C, +0x7F, +0x0B, +0xB6, +0x51, +0x0D, +0x5C, +0xE5, +0xE4, +0x37, +0x83, +0xC1, +0x6E, +0x5A, +0x2A, +0x58, +0x62, +0xD6, +0xB1, +0x4F, +0x8A, +0xAF, +0x12, +0xDB, +0x94, +0xC0, +0x83, +0xAE, +0x9D, +0x40, +0xF5, +0xA7, +0x5E, +0x21, +0xB6, +0x37, +0x09, +0xE4, +0x51, +0xD7, +0xB5, +0xB6, +0x37, +0xC2, +0xD7, +0x94, +0x0D, +0x9F, +0xB3, +0x17, +0x2C, +0x60, +0xF8, +0x92, +0x8D, +0x1E, +0x1A, +0x6E, +0x58, +0x50, +0xFC, +0x29, +0x84, +0x4E, +0x16, +0x0F, +0xF5, +0xCA, +0x9C, +0x0A, +0xF3, +0x3E, +0x1D, +0xA3, +0x5E, +0xBA, +0xF7, +0xA6, +0x26, +0xD4, +0x17, +0xB2, +0xCB, +0xB6, +0x89, +0x40, +0xC8, +0x24, +0x93, +0x73, +0xC0, +0x79, +0xB2, +0x8D, +0x6E, +0xF9, +0xC3, +0x08, +0xF4, +0x71, +0xDB, +0x8A, +0x36, +0xA3, +0x19, +0x90, +0xC7, +0x2D, +0x48, +0xD5, +0x91, +0x04, +0xBF, +0x50, +0x2D, +0xB9, +0xF3, +0x57, +0xEA, +0x56, +0x1D, +0x8F, +0x2F, +0xC9, +0x40, +0xDE, +0x6C, +0x16, +0xB0, +0x8D, +0x34, +0xB1, +0xC7, +0x53, +0xC7, +0x24, +0x6D, +0x98, +0xB1, +0x2C, +0x4F, +0x2A, +0x98, +0x4A, +0x6E, +0xAC, +0xE3, +0xBF, +0x07, +0x5A, +0xA3, +0xE7, +0xC6, +0xE5, +0xB0, +0x2C, +0x83, +0xE4, +0x61, +0x90, +0xDA, +0xD7, +0x7C, +0x41, +0x39, +0x91, +0x8D, +0xD0, +0x75, +0x6C, +0xB8, +0x15, +0x92, +0x4B, +0xE0, +0x63, +0xE5, +0x4E, +0x50, +0x4A, +0x62, +0x7E, +0x30, +0xFB, +0x5F, +0xE2, +0x8B, +0x1F, +0x7F, +0xF3, +0x29, +0x86, +0xAF, +0xB1, +0x7C, +0xAD, +0x28, +0xB3, +0x1E, +0x60, +0xD6, +0x8C, +0x4E, +0xA3, +0xE5, +0x1A, +0xE6, +0xDC, +0x37, +0x4C, +0xEA, +0x25, +0x5C, +0x24, +0x90, +0xFE, +0xB6, +0x62, +0xA9, +0x16, +0xD8, +0x72, +0x93, +0xFB, +0x97, +0x79, +0x1E, +0x80, +0x25, +0xCE, +0x4B, +0xF0, +0x94, +0x16, +0x5D, +0xA0, +0xA2, +0xF0, +0xD6, +0xF5, +0xD1, +0x17, +0x8D, +0x78, +0xC3, +0x3E, +0x4B, +0x85, +0x13, +0x8B, +0x3F, +0xD7, +0x3A, +0xB8, +0x2F, +0x3C, +0x5B, +0xB4, +0x20, +0xE9, +0xD7, +0x6F, +0x27, +0x0F, +0xCE, +0x42, +0x96, +0x9D, +0x60, +0x18, +0x6F, +0xAC, +0x2B, +0xA7, +0xFA, +0x18, +0x4B, +0xF9, +0xEC, +0x48, +0x17, +0x59, +0xA5, +0xD8, +0xA0, +0x19, +0xB3, +0xC4, +0x20, +0x5D, +0x50, +0x73, +0xC4, +0x81, +0xB4, +0xCE, +0x78, +0x61, +0xB5, +0x0B, +0x82, +0x97, +0x0D, +0x97, +0xF2, +0xE6, +0x07, +0xD8, +0xB2, +0xFD, +0x0A, +0x47, +0x3B, +0xE0, +0x51, +0x3F, +0x8B, +0x2A, +0xC1, +0x74, +0x3E, +0xB5, +0xF3, +0x19, +0xAF, +0x7A, +0xC3, +0x8A, +0x29, +0xCF, +0xE7, +0x5D, +0x5B, +0x4E, +0x2C, +0x6D, +0x4C, +0x93, +0x19, +0x50, +0x6E, +0x80, +0x96, +0x1F, +0xB8, +0x30, +0x95, +0x94, +0x97, +0x10, +0xA7, +0xF2, +0xD4, +0x2E, +0xDA, +0x86, +0x6F, +0xD2, +0xC4, +0xA5, +0x61, +0xDB, +0x3C, +0x64, +0xAF, +0xA5, +0x98, +0x31, +0xC4, +0x05, +0x71, +0xE7, +0xB8, +0x23, +0x04, +0xC1, +0xEB, +0xDF, +0x23, +0x06, +0x3D, +0xCE, +0x48, +0x62, +0xAD, +0xC6, +0xF9, +0x5E, +0x5A, +0xB4, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x02, +0x28, +0x02, +0x2D, +0x02, +0x2E, +0x02, +0x2F, +0x02, +0x32, +0x02, +0x33, +0x02, +0x26, +0x02, +0x31, +0x02, +0x30, +0x02, +0x2B, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x20, +0x40, +0x60, +0x00, +0x80, +0xA0, +0xC0, +0xE0, +0x00, +0x00, +0x20, +0x40, +0x60, +0x55, +0x80, +0xA0, +0xC0, +0xE0, +0x55, +0x00, +0x20, +0x40, +0x60, +0xAA, +0x80, +0xA0, +0xC0, +0xE0, +0xAA, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x36, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +}; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index b8f9c666dc61..0edca2ebf941 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -69,6 +69,7 @@ extern unsigned char lcd_debug_print_flag; * ********************************** */ #define TTL_DELAY 13 +#define PRE_DE_DELAY 8 /* ********************************** @@ -338,8 +339,15 @@ struct mlvds_config_s { unsigned int bit_rate; /* Hz */ }; +enum p2p_type_e { + P2P_CEDS = 0, + P2P_MAX, +}; + struct p2p_config_s { - unsigned int channel_num; + unsigned int p2p_type; + unsigned int port_num; + unsigned int lane_num; unsigned int channel_sel0; unsigned int channel_sel1; unsigned int clk_phase; /* [13:12]=clk01_pi_sel, From 4a8336a3c4826c182b616ed7c721e4d740d33d6e Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Tue, 27 Nov 2018 10:31:16 +0800 Subject: [PATCH 0455/1060] dv: fix the flickered problem [1/1] PD#SWPL-1207 Problem: fix the filckered problem when playing transition video in sdr tv Solution: when dv core2 don't run, the reset can't be executed Verify: r321 Change-Id: I719325f1722589e02a40d46442258b0d1e3feb17 Signed-off-by: Yi Zhou Conflicts: drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c --- .../media/enhancement/amdolby_vision/amdolby_vision.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index a32dec57972a..ada4287ba682 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -2119,10 +2119,10 @@ static int dolby_core2_set( if (stb_core_setting_update_flag & FLAG_CHANGE_TC2) set_lut = true; - VSYNC_WR_DV_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); - VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); - if (is_meson_box() || is_meson_tm2_stbmode() || reset) { - VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL1, + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); + if (is_meson_gxm() || is_meson_g12() || reset) { + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, ((hsize + g_htotal_add) << 16) | (vsize + g_vtotal_add + g_vsize_add)); VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL2, @@ -2435,6 +2435,7 @@ static void apply_stb_core_settings( #endif u32 graphics_w = osd_graphic_width; u32 graphics_h = osd_graphic_height; + if (is_dolby_vision_stb_mode() && (dolby_vision_flags & FLAG_CERTIFICAION)) { graphics_w = dv_cert_graphic_width; From 82334bc90509708e60a0f93e370764b65a0ad066 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Mon, 3 Dec 2018 22:04:24 +0800 Subject: [PATCH 0456/1060] vpp: sr: remove the vpp misc operation in sr function [1/1] PD#SWPL-2613 Problem: sr mux in vpp misc is set incorrectly. Solution: move the vpp misc operation together Verify: verify by x301 Change-Id: Ie813e5b04b97a4481c2e45bcf0c8b4c065fb9f69 Signed-off-by: Brian Zhu Conflicts: drivers/amlogic/media/video_sink/vpp.c --- drivers/amlogic/media/video_sink/video.c | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index d6d3f0c4623d..3d5141113b15 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -7834,6 +7834,33 @@ SET_FILTER: u32 set_value = 0; force_flush |= vpp_zorder_check(); + /* for sr core0, put it between prebld & pps as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE0_SUPPORT)) + if (cur_frame_par->sr0_position) + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + else + vpp_misc_set &= + ~SR0_AFTER_DNLP; + else + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + /* for sr core1, put it before post blend as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE1_SUPPORT)) + if (cur_frame_par->sr1_position) + vpp_misc_set |= + DNLP_SR1_CM; + else + vpp_misc_set &= + ~SR1_AFTER_POSTBLEN; + else + vpp_misc_set |= + DNLP_SR1_CM; + /* for sr core0, put it between prebld & pps as default */ if (cur_frame_par && (cur_frame_par->sr_core_support & From dcd84c2f6ede2e13c6d2331195af8fa61a22d1cd Mon Sep 17 00:00:00 2001 From: "bichao.zheng" Date: Thu, 29 Nov 2018 20:25:10 +0800 Subject: [PATCH 0457/1060] arm: dts: fix wifi 32K Frequency offset [2/2] PD#SWPL-2623 Problem: wifi 32K Frequency offset too large Solution: Modification cycle Verify: x301 Change-Id: I04724b0eacdffc1760b67689be373cb8f671a125 Signed-off-by: bichao.zheng Conflicts: arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts --- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 0d4590746490..d2e96f42f808 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -913,13 +913,13 @@ wifi_pwm_conf:wifi_pwm_conf{ pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_1 30040 0>; - duty-cycle = <15020>; + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; times = <8>; }; pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_3 30030 0>; - duty-cycle = <15015>; + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; times = <12>; }; }; From bca85ddb1a97baf93bab368f7e0783845de8e96c Mon Sep 17 00:00:00 2001 From: "liangzhuo.xie" Date: Fri, 23 Nov 2018 10:36:11 +0800 Subject: [PATCH 0458/1060] dts: add video11 and video12 for screenrecord [2/6] PD#SWPL-209 Problem: add screenrecord function Solution: add video11 and video12 for screenrecord Verify: verify by t962_p321 Change-Id: I0d33d9d01704b6fe6e5c7dbeccb1fb2be68904b3 Signed-off-by: liangzhuo.xie Conflicts: arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts --- arch/arm/boot/dts/amlogic/txl_t962_p321.dts | 16 +++++++++++++++ .../boot/dts/amlogic/txl_t962_p321_720p.dts | 20 +++++++++++++++++++ arch/arm64/boot/dts/amlogic/txl_t962_p321.dts | 16 +++++++++++++++ .../boot/dts/amlogic/txl_t962_p321_720p.dts | 16 +++++++++++++++ .../video_processor/video_dev/amlvideo2.c | 9 +++++---- 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts index c896f12a95d0..d2b48c43b38e 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts @@ -280,6 +280,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts index 2549e9ef3526..5ddaf04b9e8d 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -280,6 +280,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; @@ -1180,3 +1196,7 @@ cs-gpios = <&gpio GPIOZ_3 0>; }; +&defendkey { + memory-region = <&defendkey_reserved>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts index 446bf37091e4..d0b8ad511a58 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts @@ -272,6 +272,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts index ce7bea90cd69..5aa2c625fd53 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -272,6 +272,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 288d47948bec..df62d822f7fc 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -77,7 +77,8 @@ /* #define USE_SEMA_QBUF */ /* #define USE_VDIN_PTS */ -/* #define MULTI_NODE */ +#define MULTI_NODE + #ifdef MULTI_NODE #define MAX_SUB_DEV_NODE 2 #else @@ -4653,8 +4654,8 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) #ifdef PREVIOUS_VOUT_MODE static enum tvin_scan_mode_e vmode2scan_mode(enum vmode_e mode) { - enum tvin_scan_mode_e scan_mode = - TVIN_SCAN_MODE_NULL;/* 1: progressive 2:interlaced */ + enum tvin_scan_mode_e scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + //TVIN_SCAN_MODE_NULL;/* 1: progressive 2:interlaced */ switch (mode) { case VMODE_480I: @@ -5358,7 +5359,7 @@ int amlvideo2_cma_buf_init(struct amlvideo2_device *vid_dev, int node_id) return -1; } } else { - flags = CODEC_MM_FLAGS_DMA | + flags = CODEC_MM_FLAGS_DMA_CPU| CODEC_MM_FLAGS_CMA_CLEAR; if (node_id == 0) { if (vid_dev->node[node_id]-> From 67ffbba75fc62274c30ed23f57243ee0bfcc6494 Mon Sep 17 00:00:00 2001 From: Yingyuan Zhu Date: Tue, 11 Dec 2018 16:37:32 +0800 Subject: [PATCH 0459/1060] watchdog: Change the feed watchdog mode [1/1] PD#SWPL-2378 Problem: Using Android to feed watchdog is not easy to debug the crash problem, in addition, the Android does not open the dog feeding service. Solution: Change the DTS configuration and change into driver feed watchdog. Verify: test pass on g12a-u200 Change-Id: Ie0a91fd8451fdccf3038ba6290a277c9048c52cd Signed-off-by: Yingyuan Zhu Conflicts: arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm64/boot/dts/amlogic/mesontxl.dtsi --- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index 3b61f79e1036..cd8b20f58b95 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -464,8 +464,14 @@ }; wdt: watchdog@0xffd0f0d0 { - compatible = "amlogic,meson-tl1-wdt"; + compatible = "amlogic, meson-wdt"; status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; reg = <0xffd0f0d0 0x10>; clock-names = "xtal"; clocks = <&xtal>; From e6cc1de027734ff8ab0efe31193fe0ba2927e5d9 Mon Sep 17 00:00:00 2001 From: Chao Liu Date: Wed, 28 Mar 2018 13:44:00 +0800 Subject: [PATCH 0460/1060] dts: add the attestationkeybox of unifykey[1/3] PD#162644: Attestation key burn tool development Change-Id: I53903436560957026b8dc1ab4b72c48b4b160399 Signed-off-by: Chao Liu Conflicts: arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts arch/arm64/boot/dts/amlogic/gxl_p212_1g_buildroot.dts arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts arch/arm64/boot/dts/amlogic/gxl_p212_2g_buildroot.dts arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts arch/arm64/boot/dts/amlogic/gxl_skt.dts arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts --- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 3 +++ arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts | 3 +++ arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts | 3 +++ arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 3 +++ arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts | 10 ++++++++++ arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts | 10 ++++++++++ 6 files changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index 7ffa10199b20..38ab2a431550 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -475,6 +475,7 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "region_code"; key-device = "normal"; @@ -485,6 +486,8 @@ key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey efusekey:efusekey{ diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts index 7d8d55ab43b9..35b9af46f645 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts @@ -1111,11 +1111,14 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "netflix_mgkid"; key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts index ba85a853779d..a45c09ec3f90 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts @@ -1111,11 +1111,14 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "netflix_mgkid"; key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index 2a7245aff17a..5d9833ba1592 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -1319,11 +1319,14 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "netflix_mgkid"; key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts b/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts index a9043e836c4c..4e7b21493617 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts @@ -1112,7 +1112,11 @@ compatible = "amlogic, unifykey"; status = "ok"; +<<<<<<< HEAD unifykey-num = <17>; +======= + unifykey-num = <15>; +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -1128,8 +1132,11 @@ unifykey-index-12= <&keysn_12>; unifykey-index-13= <&keysn_13>; unifykey-index-14= <&keysn_14>; +<<<<<<< HEAD unifykey-index-15= <&keysn_15>; unifykey-index-16= <&keysn_16>; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] keysn_0: key_0{ key-name = "usid"; @@ -1209,6 +1216,7 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "region_code"; key-device = "normal"; @@ -1219,6 +1227,8 @@ key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts index 0b9e93620866..9fc21ce39103 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts @@ -1115,7 +1115,11 @@ compatible = "amlogic, unifykey"; status = "ok"; +<<<<<<< HEAD unifykey-num = <17>; +======= + unifykey-num = <15>; +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -1131,8 +1135,11 @@ unifykey-index-12= <&keysn_12>; unifykey-index-13= <&keysn_13>; unifykey-index-14= <&keysn_14>; +<<<<<<< HEAD unifykey-index-15= <&keysn_15>; unifykey-index-16= <&keysn_16>; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] keysn_0: key_0{ key-name = "usid"; @@ -1212,6 +1219,7 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "region_code"; key-device = "normal"; @@ -1222,6 +1230,8 @@ key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { From c942c4a60654ff8a0f94437393c433672dd15d74 Mon Sep 17 00:00:00 2001 From: Dianzhong Huo Date: Tue, 25 Dec 2018 16:23:56 +0800 Subject: [PATCH 0461/1060] dts: add w411 dts for buildroot [1/1] PD#SH-224 Problem: buildroot no w411 dts Solution: 1.add w411 dts 2.w411 dts copy form w400_buildtoot dts, and do some memory cost down, and also sdio port has some different with w400 board Verify: w411 board test pass Change-Id: Iba3de4fc4fe1d37dbb6070dbe54ad35c9caf45d9 Signed-off-by: Dianzhong Huo Conflicts: arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts --- MAINTAINERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index bed14ed68b75..29aeea4f1455 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14577,6 +14577,10 @@ AMLOGIC G12B w400 buildroot dts M: liangzhuo xie F: arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +AMLOGIC G12B w411 buildroot dts +M: dianzhong.huo +F: arch/arm64/boot/dts/amlogic/g12b_a311d_w411_buildroot.dts + AMLOGIC P PARTITION DTSI M: Xindong Xu F: arch/arm64/boot/dts/amlogic/firmware_avb.dtsi From 9f97fce3f01375b77a836d48eaeec1e30c644dca Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Thu, 27 Dec 2018 14:31:29 +0800 Subject: [PATCH 0462/1060] dmc: fix panic problem when show memory in highmem [1/1] PD#SWPL-2767 Problem: If DMC violation address is in highmem, then it will panic when show memory using page_address(); Solution: map violation address for highmem Verify: p212 Change-Id: Ib6213eaab42b129c8c0a381511a0b3376b0d3e66 Signed-off-by: Tao Zeng Conflicts: drivers/amlogic/ddr_tool/dmc_g12.c drivers/amlogic/ddr_tool/dmc_gx.c --- drivers/amlogic/ddr_tool/dmc_g12.c | 35 ++++++++++++++++++++---------- drivers/amlogic/ddr_tool/dmc_gx.c | 35 ++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/amlogic/ddr_tool/dmc_g12.c b/drivers/amlogic/ddr_tool/dmc_g12.c index 8276e157f4f6..8e35e212697e 100644 --- a/drivers/amlogic/ddr_tool/dmc_g12.c +++ b/drivers/amlogic/ddr_tool/dmc_g12.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -76,12 +77,31 @@ static size_t g12_dmc_dump_reg(char *buf) return sz; } +static void show_violation_mem(unsigned long addr) +{ + struct page *page; + unsigned long *p, *q; + + if (!pfn_valid(__phys_to_pfn(addr))) + return; + + page = phys_to_page(addr); + p = kmap_atomic(page); + if (!p) + return; + + q = p + ((addr & (PAGE_SIZE - 1)) / sizeof(*p)); + pr_info(DMC_TAG "[%08lx]:%016lx, f:%8lx, m:%p, a:%ps\n", + (unsigned long)q, *q, page->flags & 0xffffffff, + page->mapping, + (void *)get_page_trace(page)); + kunmap_atomic(p); +} + static void check_violation(struct dmc_monitor *mon) { int i, port, subport; unsigned long addr, status; - struct page *page; - unsigned long *p; char id_str[4]; char off1 = 21, off2 = 10; @@ -112,16 +132,7 @@ static void check_violation(struct dmc_monitor *mon) pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n", addr, status, to_ports(port), to_sub_ports(port, subport, id_str), mon->same_page); - if (pfn_valid(__phys_to_pfn(addr))) { - page = phys_to_page(addr); - p = (page_address(page) + (addr & (PAGE_SIZE - 1))); -#if defined(CONFIG_AMLOGIC_PAGE_TRACE) - pr_info(DMC_TAG" [%08lx]:%016lx, f:%8lx, m:%p, a:%pf\n", - addr, *p, page->flags & 0xffffffff, - page->mapping, - (void *)get_page_trace(page)); -#endif - } + show_violation_mem(addr); if (!port) /* dump stack for CPU write */ dump_stack(); diff --git a/drivers/amlogic/ddr_tool/dmc_gx.c b/drivers/amlogic/ddr_tool/dmc_gx.c index bc07f7a31d21..7871970cdd6a 100644 --- a/drivers/amlogic/ddr_tool/dmc_gx.c +++ b/drivers/amlogic/ddr_tool/dmc_gx.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -80,12 +81,31 @@ static size_t gx_dmc_dump_reg(char *buf) return sz; } +static void show_violation_mem(unsigned long addr) +{ + struct page *page; + unsigned long *p, *q; + + if (!pfn_valid(__phys_to_pfn(addr))) + return; + + page = phys_to_page(addr); + p = kmap_atomic(page); + if (!p) + return; + + q = p + ((addr & (PAGE_SIZE - 1)) / sizeof(*p)); + pr_info(DMC_TAG "[%08lx]:%016lx, f:%8lx, m:%p, a:%ps\n", + (unsigned long)q, *q, page->flags & 0xffffffff, + page->mapping, + (void *)get_page_trace(page)); + kunmap_atomic(p); +} + static void check_violation(struct dmc_monitor *mon) { int i, port, subport; unsigned long addr, status; - struct page *page; - unsigned long *p; char id_str[4]; for (i = 1; i < 8; i += 2) { @@ -109,16 +129,7 @@ static void check_violation(struct dmc_monitor *mon) pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n", addr, status, to_ports(port), to_sub_ports(port, subport, id_str), mon->same_page); - if (pfn_valid(__phys_to_pfn(addr))) { - page = phys_to_page(addr); - p = (page_address(page) + (addr & (PAGE_SIZE - 1))); -#if defined(CONFIG_AMLOGIC_PAGE_TRACE) - pr_info(DMC_TAG" [%08lx]:%016lx, f:%8lx, m:%p, a:%pf\n", - addr, *p, page->flags & 0xffffffff, - page->mapping, - (void *)get_page_trace(page)); -#endif - } + show_violation_mem(addr); if (!port) /* dump stack for CPU write */ dump_stack(); From b2b85c4aee82e9dd34ed0200b196f4f84068ca58 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Wed, 26 Dec 2018 19:42:37 +0800 Subject: [PATCH 0463/1060] audio: codec: fix to resume ad82584's volume after suspend [1/1] PD#SWPL-3456 Problem: 1) After suspend, volume is not resume 2) ARC connected, still sound out from spk Solution: 1) save channel volume when suspend, then resume the volume 2) add mute mixer control for ad82584 Verify: x301 Change-Id: Ic6e7502e3f9689cc2d1053295f26aaf4d5be2603 Signed-off-by: Xing Wang Conflicts: sound/soc/codecs/amlogic/ad82584f.c --- sound/soc/codecs/amlogic/ad82584f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index c66a18b62512..1e6bb4b57f43 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -831,7 +831,7 @@ static int ad82584f_init(struct snd_soc_codec *codec) udelay(100); /* unmute, default power-on is mute. */ - snd_soc_write(codec, 0x02, 0x00); + snd_soc_write(codec, MUTE, 0x00); return 0; } From d152d4eae93b4f3324bfc7fcdabb5034550e2ea4 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Wed, 5 Dec 2018 23:12:54 +0800 Subject: [PATCH 0464/1060] audio: auge: add vad driver [1/1] PD#SWPL-2404 Problem: VAD for wake up Solution: Add vad driver to fetch VAD buffer and ALSA buffer, in userspace, they will be combined for wakeup engine Verify: x301 Change-Id: I3b4de5fdfe173ce18e58a187a3adeda601e226b3 Signed-off-by: Xing Wang Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts include/linux/amlogic/major.h sound/soc/amlogic/auge/ddr_mngr.h sound/soc/amlogic/auge/tdm.c --- MAINTAINERS | 2 +- sound/soc/amlogic/auge/tdm.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 29aeea4f1455..e920bbcfc796 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14696,7 +14696,7 @@ AMLOGIC TL1 NEW EQDRC AMLOGIC TL1 MIXER CONTROLS AMLOGIC TL1 VAD DRIVER AMLOGIC SM1 SOUND CARD -M: Xing Wang F: arch/arm/boot/dts/amlogic/tl1_pxp.dts F: include/dt-bindings/clock/amlogic,tl1-audio-clk.h F: include/dt-bindings/clock/amlogic,sm1-audio-clk.h diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 2549ce147142..8c1ad18eab87 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -565,6 +565,9 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, break; } + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, false); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback stop\n"); memset(substream->runtime->dma_area, From 04676b9fc8478a4c833827d4fcb723a68d12e0e6 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Tue, 8 Jan 2019 22:16:41 +0800 Subject: [PATCH 0465/1060] audio: fix pop snd after bootup [2/2] PD#SWPL-3178 Problem: output big pop noise after system boot up. Solution: Add zero and then unmute the stream. NOTICE: user should unmute the AD82584F after boot. Verify: local verified. Change-Id: I21555318f9347c5340a28f7e5cf0e3e2cde849a0 Signed-off-by: Shuai Li Conflicts: sound/soc/codecs/amlogic/ad82584f.c --- sound/soc/codecs/amlogic/ad82584f.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index 1e6bb4b57f43..da82c73f6565 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -827,11 +827,8 @@ static int ad82584f_init(struct snd_soc_codec *codec) /* eq and drc */ ad82584f_set_eq_drc(codec); - /* for de-pop */ - udelay(100); - - /* unmute, default power-on is mute. */ - snd_soc_write(codec, MUTE, 0x00); + /*unmute,default power-on is mute.*/ + /*snd_soc_write(codec, 0x02, 0x00);*/ return 0; } From 7029d2bde984e6811d8b354e2d2ee6e5b65b3011 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Sat, 29 Dec 2018 19:14:23 +0800 Subject: [PATCH 0466/1060] audio: auge: fix sharebuffer channel map [1/1] PD#SWPL-2645 Problem: play ddp source, then play pcm source, no sound Solution: 1. fix same source control and channel map issue 2. i2s 8ch, spdif 2ch, channels are not mapped, make spdif 8 channel mask 3. when same source used, keep mpll use same mpll Verify: x301 Change-Id: I2fe4bbcbcbfff0a1c1a6cebf61d1da5aba9b7a9d Signed-off-by: Xing Wang Conflicts: arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts --- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts | 2 +- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 4cf33f45b697..a7c8832248d4 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1322,7 +1322,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 198fce058ec8..d265738263f0 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -1321,7 +1321,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; From e7fe56502f78140f71cec7f851a00f61d5d2c0ff Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Sun, 13 Jan 2019 23:03:48 +0800 Subject: [PATCH 0467/1060] audio: add stream mute and continuous clk [1/1] PD#SWPL-2952 Problem: Pop noise could be heard when switching between sources. Solution: 1. Add stream digital mute functions. 2. continuous clock to eliminate the clk reset issue. Verify: Local verified. Change-Id: I372f4c03aaf875d75aa903c9c2dfda00619af000 Signed-off-by: Shuai Li Conflicts: sound/soc/amlogic/auge/tdm_hw.c sound/soc/amlogic/auge/tdm_hw.h --- sound/soc/amlogic/auge/tdm_hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index 83874c90c79e..2927beb5c2f5 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -698,6 +698,7 @@ void i2s_to_hdmitx_disable(void) { audiobus_write(EE_AUDIO_TOHDMITX_CTRL0, 0); } + void aml_tdm_mute_playback( struct aml_audio_controller *actrl, int tdm_index, From b74aa0619cbde6d82f973e3ff691e702842d84e1 Mon Sep 17 00:00:00 2001 From: MingLiang Dong Date: Wed, 16 Jan 2019 01:36:29 -0500 Subject: [PATCH 0468/1060] amvecm: sdr2hdr function set by uplayer, driver default disable [1/1] PD#SWPL-4255 Problem: UI disable SDR TO HDR, reboot BOX, TV flicker white and then display ok when connect hdr tv Solution: dr2hdr function set by uplayer, kernel default disable Verify: verify on G12A Change-Id: Iea5a1e0be9b5665bb7deb785b6b5faa702ef1664 Signed-off-by: MingLiang Dong Conflicts: drivers/amlogic/media/enhancement/amvecm/amvecm.c --- drivers/amlogic/media/enhancement/amvecm/amvecm.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 69bc6a6c0821..ee7374135e76 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -6666,21 +6666,9 @@ static int aml_vecm_probe(struct platform_device *pdev) else hdr_flag = (1 << 0) | (1 << 1) | (0 << 2) | (0 << 3); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) - sdr_mode = 2; - - /*config vlock mode*/ - /*todo:txlx & g9tv support auto pll,*/ - /*but support not good,need vlsi support optimize*/ - vlock_mode = VLOCK_MODE_MANUAL_PLL; - if (is_meson_gxtvbb_cpu() || - is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_txhd_cpu()) - vlock_en = 1; - else - vlock_en = 0; hdr_init(&amvecm_dev.hdr_d); aml_vecm_dt_parse(pdev); + vlock_status_init(); probe_ok = 1; pr_info("%s: ok\n", __func__); From b1aacd934baf9dc905a21bb4124851e3c86556fe Mon Sep 17 00:00:00 2001 From: Yi Zhou Date: Tue, 15 Jan 2019 15:31:13 +0800 Subject: [PATCH 0469/1060] dv: close afbc2 when playing sources with unnecessary el [1/1] PD#SWPL-915 Problem: DOLBY only sets the enhancement for the first frame -> Vd sets cur_dispubf2 according to enhance -> codec_mm keeps the last frame according to cur_dispbuf2, so it fails -> AFBC2 access to the released content causes the trigger. Solution: close afbc2 Verify: r321 Change-Id: I03c431a6ea11b8aabf97b1f0b21f717024be2f62 Signed-off-by: Yi Zhou Conflicts: drivers/amlogic/media/video_sink/video.c --- drivers/amlogic/media/video_sink/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 3d5141113b15..225abc3dde56 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -4051,7 +4051,7 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) /* if el is unnecessary, afbc2 need to be closed */ if ((last_el_status == 1) && (vf_with_el == 0)) - need_disable_vd2 = true; + need_disable_vd2 = 1; if (((vf->type & VIDTYPE_MVC) == 0) && last_mvc_status) From 1ca90ca607e4f1580a0a6b8ec2ded38fc1ea70b9 Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Wed, 26 Dec 2018 15:07:47 +0800 Subject: [PATCH 0470/1060] lcd: unify lcd pinmux usage in dts [1/1] PD#SWPL-3294 Problem: unify lcd pinmux usage in dts Solution: change lcd pinmux usage to be recommend by linux upstream Verify: verify by t962x_r311 Change-Id: I7069b5272fa779575a8111b12a3ed835ab72cd02 Signed-off-by: Shaochan Liu Conflicts: arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts --- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 18 +++++++++--------- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 18 +++++++++--------- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 18 +++++++++--------- .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 18 +++++++++--------- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 18 +++++++++--------- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 18 +++++++++--------- .../arm64/boot/dts/amlogic/txlx_t962x_r314.dts | 18 +++++++++--------- 7 files changed, 63 insertions(+), 63 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 95753b5f5542..81ff45f15d12 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -1563,7 +1563,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1575,50 +1575,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index 3d775920a9e7..4ad29dbd091c 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -1552,7 +1552,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1564,50 +1564,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 2e42e3c8e83d..f4e21c905bfb 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -1560,7 +1560,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1572,50 +1572,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index e9c8d700c1c7..f9646d3694c6 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -1554,7 +1554,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1566,50 +1566,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 30be795a013b..8348ffb6e196 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -1560,7 +1560,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1572,50 +1572,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index c3593f28c298..e7d7721e6393 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -1552,7 +1552,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1564,50 +1564,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 231de7001847..5c8a29eff0f5 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -1555,7 +1555,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1567,50 +1567,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; From fd04ea8e4c9d1cf34320905a772381f26aee44cb Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Wed, 9 Jan 2019 14:23:11 +0800 Subject: [PATCH 0471/1060] lcd: optimize bit_rate config in lcd driver [2/2] PD#SWPL-3562 Problem: optimize bit_rate config in lcd driver Solution: optimize bit_rate config in lcd driver Verify: verify by t962x2-x301 Change-Id: Ia804628aa60590f4311ece394ddacc08ca64d573 Signed-off-by: Shaochan Liu Conflicts: drivers/amlogic/media/vout/lcd/lcd_clk_config.c drivers/amlogic/media/vout/lcd/lcd_debug.c drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c drivers/amlogic/media/vout/lcd/lcd_vout.c include/linux/amlogic/media/vout/lcd/lcd_vout.h --- .../amlogic/media/vout/lcd/lcd_clk_config.c | 71 ++++++++++++++----- drivers/amlogic/media/vout/lcd/lcd_debug.c | 5 +- .../media/vout/lcd/lcd_tablet/lcd_drv.c | 2 +- .../media/vout/lcd/lcd_tablet/mipi_dsi_util.c | 23 +++--- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 33 ++++++++- drivers/amlogic/media/vout/lcd/lcd_vout.c | 6 +- .../linux/amlogic/media/vout/lcd/lcd_vout.h | 8 +-- 7 files changed, 104 insertions(+), 44 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index b5f5c4bccfb4..b5287455a319 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -1011,6 +1011,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) goto generate_clk_done_txl; } + bit_rate = pconf->lcd_timing.bit_rate / 1000; + if (pconf->lcd_timing.clk_auto == 2) cConf->pll_mode = 1; else @@ -1074,7 +1076,7 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) case LCD_VBYONE: cConf->div_sel_max = CLK_DIV_SEL_MAX; cConf->xd_max = CRT_VID_DIV_MAX; - pll_fout = pconf->lcd_control.vbyone_config->bit_rate / 1000; + pll_fout = bit_rate; clk_div_in = pll_fout; if (clk_div_in > cConf->data->div_in_fmax) goto generate_clk_done_txl; @@ -1103,17 +1105,30 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) done = check_pll_txl(cConf, pll_fout); break; case LCD_MLVDS: - bit_rate = pconf->lcd_control.mlvds_config->bit_rate / 1000; - for (pi_div_sel = 0; pi_div_sel < 2; pi_div_sel++) { - pll_fvco = bit_rate * pi_div_table[pi_div_sel] * 4; - done = check_pll_tl1_mlvds(cConf, pll_fvco); - if (done) { - clk_div_sel = CLK_DIV_SEL_1; - cConf->xd_max = CRT_VID_DIV_MAX; - for (xd = 1; xd <= cConf->xd_max; xd++) { - clk_div_out = cConf->fout * xd; - if (clk_div_out > - cConf->data->div_out_fmax) + /* must go through div4 for clk phase */ + for (tcon_div_sel = 3; tcon_div_sel < 5; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + done = check_pll_vco(cConf, pll_fvco); + if (done == 0) + continue; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + continue; + if (lcd_debug_print_flag == 2) { + LCDPR( + "fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + for (clk_div_sel = CLK_DIV_SEL_1; + clk_div_sel < CLK_DIV_SEL_MAX; + clk_div_sel++) { + clk_div_in = clk_vid_pll_div_calc( + clk_div_out, clk_div_sel, + CLK_DIV_O2I); + if (clk_div_in > + cConf->data->div_in_fmax) continue; if (lcd_debug_print_flag == 2) { LCDPR("fout=%d, xd=%d\n", @@ -1121,6 +1136,32 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) LCDPR("clk_div_out=%d\n", clk_div_out); } + done = check_pll_od(cConf, pll_fout); + if (done) + goto generate_clk_done_txl; + } + } + } + break; + case LCD_P2P: + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + done = check_pll_vco(cConf, pll_fvco); + if (done == 0) + continue; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + continue; + if (lcd_debug_print_flag == 2) { + LCDPR( + "fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + for (clk_div_sel = CLK_DIV_SEL_1; + clk_div_sel < CLK_DIV_SEL_MAX; + clk_div_sel++) { clk_div_in = clk_vid_pll_div_calc( clk_div_out, clk_div_sel, CLK_DIV_O2I); @@ -1375,8 +1416,7 @@ static void lcd_clk_generate_axg(struct lcd_config_s *pconf) if (lcd_debug_print_flag == 2) LCDPR("fout=%d, xd=%d\n", cConf->fout, xd); - pconf->lcd_control.mipi_config->bit_rate = - pll_fout * 1000; + pconf->lcd_timing.bit_rate = pll_fout * 1000; pconf->lcd_control.mipi_config->clk_factor = xd; cConf->xd = xd; done = check_pll_axg(cConf, pll_fout); @@ -1510,8 +1550,7 @@ static void lcd_clk_generate_hpll_g12a(struct lcd_config_s *pconf) if (lcd_debug_print_flag == 2) LCDPR("fout=%d, xd=%d\n", cConf->fout, xd); - pconf->lcd_control.mipi_config->bit_rate = - pll_fout * 1000; + pconf->lcd_timing.bit_rate = pll_fout * 1000; pconf->lcd_control.mipi_config->clk_factor = xd; cConf->xd = xd; cConf->div_sel = clk_div_sel; diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 3663f66c7042..faa5843cd81b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -358,7 +358,7 @@ static int lcd_info_print_vbyone(char *buf, int offset) vx1_conf->region_num, vx1_conf->byte_mode, vx1_conf->color_fmt, - vx1_conf->bit_rate, + pconf->lcd_timing.bit_rate, vx1_conf->phy_vswing, vx1_conf->phy_preem, vx1_conf->intr_en, @@ -439,7 +439,7 @@ static int lcd_info_print_mlvds(char *buf, int offset) pconf->lcd_control.mlvds_config->bit_swap, pconf->lcd_control.mlvds_config->phy_vswing, pconf->lcd_control.mlvds_config->phy_preem, - pconf->lcd_control.mlvds_config->bit_rate, + pconf->lcd_timing.bit_rate, pconf->lcd_control.mlvds_config->pi_clk_sel); len += lcd_tcon_info_print((buf+len), (len+offset)); @@ -480,6 +480,7 @@ static int lcd_info_print_p2p(char *buf, int offset) pconf->lcd_control.p2p_config->clk_phase, pconf->lcd_control.p2p_config->pn_swap, pconf->lcd_control.p2p_config->bit_swap, + pconf->lcd_timing.bit_rate, pconf->lcd_control.p2p_config->phy_vswing, pconf->lcd_control.p2p_config->phy_preem, pconf->lcd_control.p2p_config->bit_rate, diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 025e0dbcfa04..02659768e24c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -833,7 +833,7 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) bit_rate = bit_rate * 1000; /* Hz */ pconf->lcd_control.vbyone_config->phy_div = phy_div; - pconf->lcd_control.vbyone_config->bit_rate = bit_rate; + pconf->lcd_timing.bit_rate = bit_rate; if (lcd_debug_print_flag) { LCDPR("lane_count=%u, bit_rate = %uMHz, pclk=%u.%03uMhz\n", diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c index 49d701a50533..fdf006c3f95d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c @@ -152,11 +152,11 @@ static void mipi_dsi_init_table_print(struct dsi_config_s *dconf, int on_off) } } -static void mipi_dsi_dphy_print_info(struct dsi_config_s *dconf) +static void mipi_dsi_dphy_print_info(struct lcd_config_s *pconf) { unsigned int temp; - temp = ((1000000 * 100) / (dconf->bit_rate / 1000)) * 8; + temp = ((1000000 * 100) / (pconf->lcd_timing.bit_rate / 1000)) * 8; pr_info("MIPI DSI DPHY timing (unit: ns)\n" " UI: %d.%02d\n" " LP TESC: %d\n" @@ -217,7 +217,7 @@ static void mipi_dsi_host_print_info(struct lcd_config_s *pconf) struct dsi_config_s *dconf; dconf = pconf->lcd_control.mipi_config; - esc_clk = dconf->bit_rate / 8 / dsi_phy_config.lp_tesc; + esc_clk = pconf->lcd_timing.bit_rate / 8 / dsi_phy_config.lp_tesc; factor = dconf->factor_numerator; factor = ((factor * 1000 / dconf->factor_denominator) + 5) / 10; @@ -243,7 +243,8 @@ static void mipi_dsi_host_print_info(struct lcd_config_s *pconf) " data format: %s\n" " lp escape clock: %d.%03dMHz\n", dconf->lane_num, dconf->bit_rate_max, - (dconf->bit_rate / 1000000), (dconf->bit_rate % 1000000) / 1000, + (pconf->lcd_timing.bit_rate / 1000000), + (pconf->lcd_timing.bit_rate % 1000000) / 1000, factor, operation_mode_table[dconf->operation_mode_init], dconf->operation_mode_init, @@ -267,7 +268,7 @@ void mipi_dsi_print_info(struct lcd_config_s *pconf) { mipi_dsi_host_print_info(pconf); - mipi_dsi_dphy_print_info(pconf->lcd_control.mipi_config); + mipi_dsi_dphy_print_info(pconf); mipi_dsi_video_print_info(pconf->lcd_control.mipi_config); } @@ -1699,13 +1700,13 @@ static void mipi_dsi_non_burst_packet_config(struct lcd_config_s *pconf) hactive = pconf->lcd_basic.h_active; bit_rate_required = pconf->lcd_timing.lcd_clk * 3 * dsi_vconf.data_bits; bit_rate_required = bit_rate_required / lane_num; - if (dconf->bit_rate > bit_rate_required) + if (pconf->lcd_timing.bit_rate > bit_rate_required) multi_pkt_en = 1; else multi_pkt_en = 0; if (lcd_debug_print_flag) { LCDPR("non-burst: bit_rate_required=%d, bit_rate=%d\n", - bit_rate_required, dconf->bit_rate); + bit_rate_required, pconf->lcd_timing.bit_rate); } if (multi_pkt_en == 0) { @@ -2018,11 +2019,11 @@ void lcd_mipi_dsi_config_post(struct lcd_config_s *pconf) /* pclk lanebyteclk factor */ if (dconf->factor_numerator == 0) { - lanebyteclk = dconf->bit_rate / 8 / 1000; + lanebyteclk = pconf->lcd_timing.bit_rate / 8 / 1000; LCDPR("pixel_clk = %d.%03dMHz, bit_rate = %d.%03dMHz\n", (pclk / 1000), (pclk % 1000), - (dconf->bit_rate / 1000000), - ((dconf->bit_rate / 1000) % 1000)); + (pconf->lcd_timing.bit_rate / 1000000), + ((pconf->lcd_timing.bit_rate / 1000) % 1000)); #if 0 dconf->factor_numerator = pclk; dconf->factor_denominator = lanebyteclk; @@ -2042,7 +2043,7 @@ void lcd_mipi_dsi_config_post(struct lcd_config_s *pconf) mipi_dsi_vid_mode_config(pconf); /* phy config */ - mipi_dsi_phy_config(&dsi_phy_config, dconf->bit_rate); + mipi_dsi_phy_config(&dsi_phy_config, pconf->lcd_timing.bit_rate); } static void mipi_dsi_host_on(struct lcd_config_s *pconf) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 072e0f4fcd2a..3287b48b362a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -1511,7 +1511,7 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) bit_rate = bit_rate * 1000; /* Hz */ pconf->lcd_control.vbyone_config->phy_div = phy_div; - pconf->lcd_control.vbyone_config->bit_rate = bit_rate; + pconf->lcd_timing.bit_rate = bit_rate; if (lcd_debug_print_flag) { LCDPR("lane_count=%u, bit_rate = %uMHz, pclk=%u.%03uMhz\n", @@ -1535,7 +1535,7 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) pclk = pconf->lcd_timing.lcd_clk / 1000; bit_rate = lcd_bits * 3 * pclk / channel_num; - pconf->lcd_control.mlvds_config->bit_rate = bit_rate * 1000; + pconf->lcd_timing.bit_rate = bit_rate * 1000; if (lcd_debug_print_flag) { LCDPR("channel_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", @@ -1575,6 +1575,35 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) } } +static void lcd_p2p_config_set(struct lcd_config_s *pconf) +{ + unsigned int bit_rate, pclk; + unsigned int lcd_bits, lane_num; + + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + + lcd_bits = pconf->lcd_basic.lcd_bits; + lane_num = pconf->lcd_control.p2p_config->lane_num; + pclk = pconf->lcd_timing.lcd_clk / 1000; + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: /* 8/10 coding */ + bit_rate = (pclk * 3 * lcd_bits * 10 / 8) / lane_num; + break; + default: + bit_rate = pclk * 3 * lcd_bits / lane_num; + break; + } + + pconf->lcd_timing.bit_rate = bit_rate * 1000; + + if (lcd_debug_print_flag) { + LCDPR("lane_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", + lane_num, (bit_rate / 1000), (bit_rate % 1000), + (pclk / 1000), (pclk % 1000)); + } +} + void lcd_tv_clk_config_change(struct lcd_config_s *pconf) { #ifdef CONFIG_AMLOGIC_VPU diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 1680588b5a34..eb8d61847088 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -103,7 +103,6 @@ static struct vbyone_config_s lcd_vbyone_config = { .byte_mode = 4, .color_fmt = 4, .phy_div = 1, - .bit_rate = 0, .phy_vswing = VX1_PHY_VSWING_DFT, .phy_preem = VX1_PHY_PREEM_DFT, .intr_en = 1, @@ -126,7 +125,6 @@ static struct mlvds_config_s lcd_mlvds_config = { .phy_preem = 0, .pi_clk_sel = 0, - .bit_rate = 0, }; static struct p2p_config_s lcd_p2p_config = { @@ -140,9 +138,6 @@ static struct p2p_config_s lcd_p2p_config = { .bit_swap = 0, .phy_vswing = 0, .phy_preem = 0, - - .pi_clk_sel = 0, - .bit_rate = 0, }; static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff}; @@ -207,6 +202,7 @@ static struct lcd_config_s lcd_config_dft = { .clk_auto = 1, .ss_level = 0, .fr_adjust_type = 0, + .bit_rate = 0, }, .optical_info = { .hdr_support = 0, diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 0edca2ebf941..da726bc91156 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -139,6 +139,7 @@ struct lcd_timing_s { unsigned char clk_auto; /* clk parameters auto generation */ unsigned int lcd_clk; /* pixel clock(unit: Hz) */ unsigned int lcd_clk_dft; /* internal used */ + unsigned int bit_rate; /* Hz */ unsigned int h_period_dft; /* internal used */ unsigned int v_period_dft; /* internal used */ unsigned char clk_change; /* internal used */ @@ -238,7 +239,6 @@ struct vbyone_config_s { unsigned int byte_mode; unsigned int color_fmt; unsigned int phy_div; - unsigned int bit_rate; unsigned int phy_vswing; /*[4]:ext_pullup, [3:0]vswing*/ unsigned int phy_preem; unsigned int intr_en; @@ -295,7 +295,6 @@ struct dsi_config_s { unsigned char lane_num; unsigned int bit_rate_max; /* MHz */ unsigned int bit_rate_min; /* MHz*/ - unsigned int bit_rate; /* Hz */ unsigned int clk_factor; /* bit_rate/pclk */ unsigned int factor_numerator; unsigned int factor_denominator; /* 100 */ @@ -336,7 +335,6 @@ struct mlvds_config_s { /* internal used */ unsigned int pi_clk_sel; /* bit[9:0] */ - unsigned int bit_rate; /* Hz */ }; enum p2p_type_e { @@ -357,10 +355,6 @@ struct p2p_config_s { unsigned int bit_swap; /* MSB/LSB reverse */ unsigned int phy_vswing; unsigned int phy_preem; - - /* internal used */ - unsigned int pi_clk_sel; /* bit[9:0] */ - unsigned int bit_rate; /* Hz */ }; struct lcd_control_config_s { From 6d4a452b142caeea8c069ba3d6296a3b7df55ed6 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 14 Jan 2019 20:56:01 +0800 Subject: [PATCH 0472/1060] backlight: ldim: add dev reg access api support [1/1] PD#TV-1481 Problem: need ldim_dev reg access uniform api Solution: add ldim_dev reg access uniform api Verify: x301 Change-Id: I72756d178ef70aac1f8b7fef842468f2e27a0ffe Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c include/linux/amlogic/media/vout/lcd/aml_ldim.h --- .../media/vout/backlight/aml_ldim/iw7027_bl.c | 34 ++ .../vout/backlight/aml_ldim/ldim_dev_drv.c | 389 ++++++++++++++++++ .../linux/amlogic/media/vout/lcd/aml_ldim.h | 7 +- 3 files changed, 429 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index 6c123d1d57c0..205d99dbdbd6 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -116,6 +116,37 @@ static int iw7027_wregs(struct spi_device *spi, unsigned char addr, return ret; } +static int iw7027_reg_write(unsigned char *buf, unsigned int len) +{ + int ret; + + if (len > 28) { + LDIMERR("%s: unsupport len: %d\n", __func__, len); + return -1; + } + + if (len > 1) + ret = iw7027_wreg(bl_iw7027->spi, buf[0], buf[1]); + else + ret = iw7027_wregs(bl_iw7027->spi, buf[0], &buf[1], (len - 1)); + + return ret; +} + +static int iw7027_reg_read(unsigned char *buf, unsigned int len) +{ + int ret; + + if (len > 1) { + LDIMERR("%s: unsupport len: %d\n", __func__, len); + return -1; + } + + ret = iw7027_rreg(bl_iw7027->spi, buf[0], &buf[0]); + + return ret; +} + static int ldim_power_cmd_dynamic_size(void) { unsigned char *table; @@ -687,6 +718,9 @@ static int iw7027_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) ldim_drv->device_power_off = iw7027_power_off; ldim_drv->device_bri_update = iw7027_smr; ldim_drv->device_bri_check = iw7027_check; + + ldim_drv->ldev_conf->dev_reg_write = iw7027_reg_write; + ldim_drv->ldev_conf->dev_reg_read = iw7027_reg_read; return 0; } diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index 455066dc412b..a26870933f34 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -83,8 +83,19 @@ struct ldim_dev_config_s ldim_dev_config = { .pwm_duty_max = 100, .pwm_duty_min = 1, }, + .analog_pwm_config = { + .pwm_method = BL_PWM_POSITIVE, + .pwm_port = BL_PWM_MAX, + .pwm_freq = 1000, + .pwm_duty_max = 100, + .pwm_duty_min = 10, + }, .bl_regnum = 0, + + .dim_range_update = NULL, + .dev_reg_write = NULL, + .dev_reg_read = NULL, }; static void ldim_gpio_probe(int index) @@ -1159,6 +1170,384 @@ ldim_get_config_err: return -1; } +static ssize_t ldim_dev_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + ldim_dev_config_print(); + + return ret; +} + +static ssize_t ldim_dev_pwm_ldim_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + bl_pwm = &ldim_dev_config.ldim_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_MAX) { + len += sprintf(buf+len, + "ldim_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty); + } + + return len; +} + +static ssize_t ldim_dev_pwm_ldim_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int val = 0; + struct bl_pwm_config_s *bl_pwm; + + bl_pwm = &ldim_dev_config.ldim_pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_MAX) + return count; + + switch (buf[0]) { + case 'f': /* frequency */ + ret = sscanf(buf, "freq %d", &val); + if (ret == 1) { + bl_pwm->pwm_freq = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): freq = %dHz\n", + bl_pwm->pwm_port, bl_pwm->pwm_freq); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'd': /* duty */ + ret = sscanf(buf, "duty %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty = val; + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): duty = %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'p': /* polarity */ + ret = sscanf(buf, "pol %d", &val); + if (ret == 1) { + bl_pwm->pwm_method = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): method = %d\n", + bl_pwm->pwm_port, bl_pwm->pwm_method); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'm': + if (buf[1] == 'a') { /* max */ + ret = sscanf(buf, "max %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_max = val; + if (ldim_dev_config.dim_range_update) + ldim_dev_config.dim_range_update(); + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_max = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_max); + } + } else { + LDIMERR("invalid parameters\n"); + } + } else if (buf[1] == 'i') { /* min */ + ret = sscanf(buf, "min %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_min = val; + if (ldim_dev_config.dim_range_update) + ldim_dev_config.dim_range_update(); + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_min = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_min); + } + } else { + LDIMERR("invalid parameters\n"); + } + } + break; + default: + LDIMERR("wrong command\n"); + break; + } + + return count; +} + +static ssize_t ldim_dev_pwm_analog_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + bl_pwm = &ldim_dev_config.analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) { + len += sprintf(buf+len, + "analog_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty); + } + + return len; +} + +static ssize_t ldim_dev_pwm_analog_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int val = 0; + struct bl_pwm_config_s *bl_pwm; + + bl_pwm = &ldim_dev_config.analog_pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_VS) + return count; + + switch (buf[0]) { + case 'f': /* frequency */ + ret = sscanf(buf, "freq %d", &val); + if (ret == 1) { + bl_pwm->pwm_freq = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): freq = %dHz\n", + bl_pwm->pwm_port, bl_pwm->pwm_freq); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'd': /* duty */ + ret = sscanf(buf, "duty %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty = val; + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): duty = %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'p': /* polarity */ + ret = sscanf(buf, "pol %d", &val); + if (ret == 1) { + bl_pwm->pwm_method = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): method = %d\n", + bl_pwm->pwm_port, bl_pwm->pwm_method); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'm': + if (buf[1] == 'a') { /* max */ + ret = sscanf(buf, "max %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_max = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_max = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_max); + } + } else { + LDIMERR("invalid parameters\n"); + } + } else if (buf[1] == 'i') { /* min */ + ret = sscanf(buf, "min %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_min = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_min = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_min); + } + } else { + LDIMERR("invalid parameters\n"); + } + } + break; + default: + LDIMERR("wrong command\n"); + break; + } + + return count; +} + +static unsigned char ldim_dev_reg; +static unsigned char ldim_dev_reg_dump_cnt; +static ssize_t ldim_dev_reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned char data; + ssize_t len = 0; + int ret; + + if (ldim_dev_config.dev_reg_read == NULL) + return sprintf(buf, "ldim dev_reg_read is null\n"); + + data = ldim_dev_reg; + ret = ldim_dev_config.dev_reg_read(&data, 1); + if (ret) { + len = sprintf(buf, "reg[0x%02x] read error\n", ldim_dev_reg); + } else { + len = sprintf(buf, "reg[0x%02x] = 0x%02x\n", + ldim_dev_reg, data); + } + + return len; +} + +static ssize_t ldim_dev_reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int reg = 0, val = 0; + unsigned char data[2]; + unsigned int ret; + + ret = sscanf(buf, "%x %x", ®, &val); + if (ret == 1) { + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + ldim_dev_reg = (unsigned char)reg; + } else if (ret == 2) { + if (ldim_dev_config.dev_reg_write == NULL) { + LDIMERR("ldim dev_reg_write is null\n"); + return count; + } + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + ldim_dev_reg = (unsigned char)reg; + data[0] = ldim_dev_reg; + data[1] = (unsigned char)val; + ldim_dev_config.dev_reg_write(data, 2); + LDIMPR("write reg[0x%02x] = 0x%02x\n", data[0], data[1]); + } else { + LDIMERR("invalid parameters\n"); + } + + return count; +} + +static ssize_t ldim_dev_reg_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned char *data; + ssize_t len = 0; + int i, ret; + + if (ldim_dev_config.dev_reg_read == NULL) + return sprintf(buf, "ldim dev_reg_read is null\n"); + + if (ldim_dev_reg_dump_cnt == 0) + return sprintf(buf, "ldim reg_dump_cnt is zero\n"); + + data = kcalloc(ldim_dev_reg_dump_cnt, + sizeof(unsigned char), GFP_KERNEL); + ret = ldim_dev_config.dev_reg_read(data, ldim_dev_reg_dump_cnt); + if (ret) { + len = sprintf(buf, "reg[0x%02x] read error\n", ldim_dev_reg); + } else { + len += sprintf(buf+len, "reg[0x%02x] = ", ldim_dev_reg); + for (i = 0; i < (ldim_dev_reg_dump_cnt - 1); i++) + len += sprintf(buf+len, "0x%02x,", data[i]); + len += sprintf(buf+len, "0x%02x\n", + data[ldim_dev_reg_dump_cnt - 1]); + } + kfree(data); + + return len; +} + +static ssize_t ldim_dev_reg_dump_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int reg = 0, cnt = 0; + unsigned int ret; + + ret = sscanf(buf, "%x %d", ®, &cnt); + if (ret == 2) { + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + if (cnt > 0xff) { + LDIMERR("invalid reg cnt: %d\n", cnt); + return count; + } + ldim_dev_reg = (unsigned char)reg; + ldim_dev_reg_dump_cnt = (unsigned char)cnt; + } else { + LDIMERR("invalid parameters\n"); + } + + return count; +} + +static struct class_attribute ldim_dev_class_attrs[] = { + __ATTR(status, 0644, ldim_dev_show, NULL), + __ATTR(pwm_ldim, 0644, ldim_dev_pwm_ldim_show, ldim_dev_pwm_ldim_store), + __ATTR(pwm_analog, 0644, ldim_dev_pwm_analog_show, + ldim_dev_pwm_analog_store), + __ATTR(reg, 0644, ldim_dev_reg_show, ldim_dev_reg_store), + __ATTR(reg_dump, 0644, ldim_dev_reg_dump_show, ldim_dev_reg_dump_store), + __ATTR_NULL +}; + +static void ldim_dev_class_create(void) +{ + int ret; + + ldim_dev_class.name = kzalloc(10, GFP_KERNEL); + if (ldim_dev_class.name == NULL) { + LDIMERR("%s: malloc failed\n", __func__); + return; + } + sprintf((char *)ldim_dev_class.name, "ldim_dev"); + ldim_dev_class.class_attrs = ldim_dev_class_attrs; + ret = class_register(&ldim_dev_class); + if (ret < 0) + LDIMERR("register ldim_dev_class failed\n"); +} + static int ldim_dev_add_driver(struct aml_ldim_driver_s *ldim_drv) { struct ldim_dev_config_s *ldev_conf = ldim_drv->ldev_conf; diff --git a/include/linux/amlogic/media/vout/lcd/aml_ldim.h b/include/linux/amlogic/media/vout/lcd/aml_ldim.h index 66380831270f..c066b0539e6e 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_ldim.h +++ b/include/linux/amlogic/media/vout/lcd/aml_ldim.h @@ -81,10 +81,15 @@ struct ldim_dev_config_s { unsigned int init_on_cnt; unsigned int init_off_cnt; - struct bl_pwm_config_s pwm_config; + struct bl_pwm_config_s ldim_pwm_config; + struct bl_pwm_config_s analog_pwm_config; unsigned short bl_regnum; unsigned short bl_mapping[LD_BLKREGNUM]; + + void (*dim_range_update)(void); + int (*dev_reg_write)(unsigned char *buf, unsigned int len); + int (*dev_reg_read)(unsigned char *buf, unsigned int len); }; /*******global API******/ From bb892368eefdad5a01007ff22f43f3b822170a8d Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Fri, 14 Dec 2018 19:39:58 +0800 Subject: [PATCH 0473/1060] perf_event: aml pmu interrupts routing on g12b [1/1] PD#SWPL-3088 Problem: g12b big-little cluster is different from other SoC with pmu interrupts and registers. software modifications must adapt to the difference. Solution: modify Verify: u200 w400 Change-Id: If9217c1025dff5c17d51790f8c216e31b7d6532b Signed-off-by: Hanjie Lin Conflicts: arch/arm/boot/dts/amlogic/mesongxl.dtsi arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi arch/arm/boot/dts/amlogic/mesongxm.dtsi arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm/include/asm/perf_event.h arch/arm/kernel/perf_event_v7.c arch/arm64/boot/dts/amlogic/mesong12a.dtsi arch/arm64/boot/dts/amlogic/mesongxl.dtsi arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi arch/arm64/boot/dts/amlogic/mesongxm.dtsi arch/arm64/boot/dts/amlogic/mesontxl.dtsi --- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index cd8b20f58b95..fbe396c5d70d 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -127,19 +127,14 @@ arm_pmu { compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ interrupts = ; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { From 3cb9b59d7a86b577b74499e27dc7a916f0900b2e Mon Sep 17 00:00:00 2001 From: tao zeng Date: Fri, 30 Nov 2018 18:01:31 +0800 Subject: [PATCH 0474/1060] mm: optimize thread stack usage on ARMv7 [1/1] PD#SWPL-2681 Problem: Kernel stack usage is large when running many tasks. Solution: Map kernel stack to module space and handle page-fault for stack fault. This can save about 50% memory of stack usage Verify: p212 Change-Id: Ie894bc8f00cb525ddf8ac63c6d99d9c6e937fdc0 Signed-off-by: tao zeng Conflicts: arch/arm/include/asm/memory.h arch/arm/include/asm/thread_info.h arch/arm/kernel/entry-armv.S arch/arm/kernel/unwind.c drivers/amlogic/memory_ext/Kconfig drivers/amlogic/memory_ext/vmap_stack.c --- arch/arm/configs/meson64_a32_defconfig | 1 - arch/arm/kernel/unwind.c | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 326ec6d8ed19..948702e23717 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -30,7 +30,6 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y -CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 5d321b6c7314..4682dd2485c0 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -97,7 +97,7 @@ extern const struct unwind_idx __start_unwind_idx[]; static const struct unwind_idx *__origin_unwind_idx; extern const struct unwind_idx __stop_unwind_idx[]; -static DEFINE_RAW_SPINLOCK(unwind_lock); +static DEFINE_SPINLOCK(unwind_lock); static LIST_HEAD(unwind_tables); /* Convert a prel31 symbol to an absolute address */ @@ -205,7 +205,7 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr) /* module unwind tables */ struct unwind_table *table; - raw_spin_lock_irqsave(&unwind_lock, flags); + spin_lock_irqsave(&unwind_lock, flags); list_for_each_entry(table, &unwind_tables, list) { if (addr >= table->begin_addr && addr < table->end_addr) { @@ -217,7 +217,7 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr) break; } } - raw_spin_unlock_irqrestore(&unwind_lock, flags); + spin_unlock_irqrestore(&unwind_lock, flags); } pr_debug("%s: idx = %p\n", __func__, idx); @@ -601,9 +601,9 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, tab->begin_addr = text_addr; tab->end_addr = text_addr + text_size; - raw_spin_lock_irqsave(&unwind_lock, flags); + spin_lock_irqsave(&unwind_lock, flags); list_add_tail(&tab->list, &unwind_tables); - raw_spin_unlock_irqrestore(&unwind_lock, flags); + spin_unlock_irqrestore(&unwind_lock, flags); return tab; } @@ -615,9 +615,9 @@ void unwind_table_del(struct unwind_table *tab) if (!tab) return; - raw_spin_lock_irqsave(&unwind_lock, flags); + spin_lock_irqsave(&unwind_lock, flags); list_del(&tab->list); - raw_spin_unlock_irqrestore(&unwind_lock, flags); + spin_unlock_irqrestore(&unwind_lock, flags); kfree(tab); } From 94a573ec4d2888016f98a8ac7924740994fda111 Mon Sep 17 00:00:00 2001 From: "shuanglong.wang" Date: Thu, 17 Jan 2019 17:58:00 +0800 Subject: [PATCH 0475/1060] video: video peek do not post video start event [1/1] PD#SWPL-4317 Problem: for video peek, before audio post audio start, video may have rended. Solution: do not post video start for video peek, all wait for audio start to start pcr Verify: verify by p212 Change-Id: If5656154e30613164465f84c44d3fd1ee386d654 Signed-off-by: shuanglong.wang Conflicts: drivers/amlogic/media/video_sink/video.c --- drivers/amlogic/media/video_sink/video.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 225abc3dde56..e91c55b0dd39 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -156,6 +156,11 @@ static bool video_start_post; static bool videopeek; static bool nopostvideostart; static struct video_frame_detect_s video_frame_detect; +static struct timeval time_setomxpts = { + .tv_sec = 0, + .tv_usec = 0, +}; + /*----omx_info bit0: keep_last_frame, bit1~31: unused----*/ static u32 omx_info = 0x1; @@ -4051,7 +4056,7 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) /* if el is unnecessary, afbc2 need to be closed */ if ((last_el_status == 1) && (vf_with_el == 0)) - need_disable_vd2 = 1; + need_disable_vd2 = true; if (((vf->type & VIDTYPE_MVC) == 0) && last_mvc_status) From dfa3a8a79cafac05191db72c95ab03f079a76f36 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Tue, 1 Jan 2019 10:28:08 +0800 Subject: [PATCH 0476/1060] vlock: screen flash after PAL NTSC swich [1/1] PD#SWPL-4246 Problem: the screen always flash after switch PAL to NTSC in AVin Solution: do not change pll M value, M value will case v by one fail Verify: verified on tl1 android p Change-Id: Ib5ea8dfef1c40af5535e69fdc9241a7f77b4a7dd Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/enhancement/amvecm/amvecm.c drivers/amlogic/media/enhancement/amvecm/vlock.c drivers/amlogic/media/enhancement/amvecm/vlock.h --- .../amlogic/media/enhancement/amvecm/amvecm.c | 53 +- .../enhancement/amvecm/amvecm_vlock_regmap.h | 6 +- .../media/enhancement/amvecm/arch/vpp_regs.h | 26 +- .../amlogic/media/enhancement/amvecm/vlock.c | 778 ++++++++++++++++-- .../amlogic/media/enhancement/amvecm/vlock.h | 62 +- include/linux/amlogic/media/amvecm/amvecm.h | 23 + 6 files changed, 848 insertions(+), 100 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index ee7374135e76..f8de07d7e4cc 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -734,6 +734,14 @@ static ssize_t amvecm_vlock_store(struct class *cla, vlock_log_stop(); } else if (!strncmp(parm[0], "log_print", 9)) { vlock_log_print(); + } else if (!strncmp(parm[0], "phase", 5)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + vlock_set_phase(val); + } else if (!strncmp(parm[0], "phaseen", 7)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + vlock_set_phase_en(val); } else { pr_info("unsupport cmd!!\n"); } @@ -6503,6 +6511,44 @@ static const struct file_operations amvecm_fops = { #endif .poll = amvecm_poll, }; + +static const struct vecm_match_data_s vecm_dt_xxx = { + .vlk_support = true, + .vlk_new_fsm = 0, + .vlk_hwver = vlock_hw_org, + .vlk_phlock_en = false, +}; + +static const struct vecm_match_data_s vecm_dt_tl1 = { + .vlk_support = true, + .vlk_new_fsm = 1, + .vlk_hwver = vlock_hw_ver2, + .vlk_phlock_en = true, +}; + +static const struct vecm_match_data_s vecm_dt_tm2 = { + .vlk_support = true, + .vlk_new_fsm = 1, + .vlk_hwver = vlock_hw_ver2, + .vlk_phlock_en = false, +}; + +static const struct of_device_id aml_vecm_dt_match[] = { + { + .compatible = "amlogic, vecm", + .data = &vecm_dt_xxx, + }, + { + .compatible = "amlogic, vecm-tl1", + .data = &vecm_dt_tl1, + }, + { + .compatible = "amlogic, vecm-tm2", + .data = &vecm_dt_tm2, + }, + {}, +}; + static void aml_vecm_dt_parse(struct platform_device *pdev) { struct device_node *node; @@ -6758,13 +6804,6 @@ static void amvecm_shutdown(struct platform_device *pdev) lc_free(); } -static const struct of_device_id aml_vecm_dt_match[] = { - { - .compatible = "amlogic, vecm", - }, - {}, -}; - static struct platform_driver aml_vecm_driver = { .driver = { .name = "aml_vecm", diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index bdd4737d4570..543d9bbe39f2 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -54,15 +54,15 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3001, 0x04053c32 }, {0x3002, 0x06000000 }, {0x3003, 0x20780780 }, - {0x3004, 0x00000000 }, + {0x3004, 0x00680680 }, {0x3005, 0x00080000 }, {0x3006, 0x00070000 }, {0x3007, 0x00000000 }, {0x3008, 0x00000000 }, {0x3009, 0x00100000 }, - {0x300a, 0x00600000 }, + {0x300a, 0x00008000 },/*0x00600000*/ {0x300b, 0x00100000 }, - {0x300c, 0x00000000 }, + {0x300c, 0x00600000 }, {0x300d, 0x00004000 }, {0x3010, 0x20001000 }, {0x3016, 0x0003de00 }, diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h index ec7f6397a9ea..48f1be555193 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h @@ -342,6 +342,10 @@ #define VPU_VLOCK_GCLK_EN 0x301e #define VPU_VLOCK_LOOP1_ACCUM_LMT 0x301f #define VPU_VLOCK_RO_M_INT_FRAC 0x3020 +#define VPU_VLOCK_RO_PH_DIS 0x3021 +#define VPU_VLOCK_RO_PH_ERR 0x3022 +#define VPU_VLOCK_RO_LCK_TH 0x3023 +#define VPU_VLOCK_RO_LCK_FRM 0x3024 #define XVYCC_VD1_RGB_CTRST 0x3170 @@ -529,11 +533,19 @@ /*ve dither*/ #define VPP_VE_DITHER_CTRL 0x3120 +/* TL1 */ +/*offset 0x1000*/ +#define HHI_TCON_PLL_CNTL0 0x20 +#define HHI_TCON_PLL_CNTL1 0x21 +#define HHI_HDMI_PLL_VLOCK_CNTL 0xd1 + /* for pll bug */ -#define HHI_HDMI_PLL_CNTL 0x10c8 -#define HHI_HDMI_PLL_CNTL2 0x10c9 -#define HHI_VID_LOCK_CLK_CNTL 0x10f2 -#define HHI_HDMI_PLL_CNTL6 0x10cd + +#define HHI_HDMI_PLL_CNTL 0xc8 +#define HHI_HDMI_PLL_CNTL2 0xc9 +#define HHI_VID_LOCK_CLK_CNTL 0xf2 +#define HHI_HDMI_PLL_CNTL6 0xcd + /* for vlock enc mode adjust begin */ #define ENCL_VIDEO_MAX_LNCNT 0x1cbb #define ENCL_VIDEO_MAX_PXCNT 0x1cb0 @@ -552,13 +564,11 @@ #define ENCT_MAX_LINE_SWITCH_POINT 0x1c88 /* for vlock enc mode adjust end */ -#define HHI_VID_LOCK_CLK_CNTL 0x10f2 - #define VDIN_MEAS_VS_COUNT_LO 0x125c /*after GXL new add CNTL1,same with CNTL2 on G9TV/GXTVBB*/ -#define HHI_HDMI_PLL_CNTL1 0x10c9 +#define HHI_HDMI_PLL_CNTL1 0xc9 /*after GXL CNTL5[bit3] is same with CNTL6[bit20] on G9TV/GXTVBB*/ -#define HHI_HDMI_PLL_CNTL5 0x10cd +#define HHI_HDMI_PLL_CNTL5 0xcd /* #define VI_HIST_CTRL 0x2e00 */ diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 8ce8c0c088b7..bd5344f8b01c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -35,9 +35,11 @@ #include "amcm.h" /* video lock */ -/* 0:enc;1:pll; - * 2:manual pll; - * 3:manual_enc mode(only support lvds/vx1) +/* 0:off; + * 1:auto enc; VLOCK_MODE_AUTO_ENC + * 2:auto pll; + * 4:manual pll; VLOCK_MODE_MANUAL_PLL + * 8:manual_enc mode(only support lvds/vx1) */ unsigned int vlock_mode = VLOCK_MODE_MANUAL_PLL; unsigned int vlock_en = 1; @@ -102,6 +104,12 @@ static unsigned int vlock_log_last_ivcnt; static unsigned int vlock_log_last_ovcnt; static unsigned int vlock_log_delta_m; static unsigned int vlock_log_delta_en; +static unsigned int hhi_pll_reg_m; +static unsigned int hhi_pll_reg_frac; + +static struct stvlock_sig_sts vlock; + +/*static unsigned int hhi_pll_reg_vlock_ctl;*/ module_param(vlock_log_size, uint, 0664); MODULE_PARM_DESC(vlock_log_size, "\n vlock_log_size\n"); module_param(vlock_log_cnt, uint, 0664); @@ -188,33 +196,41 @@ static unsigned int vlock_check_input_hz(struct vframe_s *vf) return ret_hz; } -static unsigned int vlock_check_output_hz(unsigned int sync_duration_num) +static unsigned int vlock_check_output_hz(unsigned int sync_duration_num, + unsigned int sync_duration_den) { unsigned int ret_hz = 0; + unsigned int tempHz; - switch (sync_duration_num) { - case 24: + tempHz = (sync_duration_num*100)/sync_duration_den; + + switch (tempHz) { + case 2400: ret_hz = 24; break; - case 30: + case 3000: ret_hz = 30; break; - case 50: + case 5000: ret_hz = 50; break; - case 60: + case 6000: ret_hz = 60; break; - case 100: + case 10000: ret_hz = 100; break; - case 120: + case 12000: ret_hz = 120; break; default: ret_hz = 0; break; } + + if ((ret_hz == 0) && (vlock_debug & VLOCK_DEBUG_INFO)) + pr_info("sync_duration_num:%d\n", sync_duration_num); + return ret_hz; } /*vlock is support eq_after gxbb,but which is useful only for tv chip @@ -246,6 +262,20 @@ static void vlock_enable(bool enable) else amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, enable, 3, 1); + } else if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + /*reset*/ + if (!(vlock_mode & VLOCK_MODE_MANUAL_PLL)) { + /*reset*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + } + + if (!enable) { + /*amvecm_hiu_reg_write_bits(*/ + /* HHI_HDMI_PLL_VLOCK_CNTL, 0, 0, 3);*/ + + /*WRITE_VPP_REG(VPU_VLOCK_CTRL, 0);*/ + } } } static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) @@ -352,7 +382,18 @@ static void vlock_setting(struct vframe_s *vf, amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &hiu_reg_value); amvecm_hiu_reg_read(hiu_reg_value_2_addr, &hiu_reg_value_2); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { + + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("hhi_pll_reg_m:0x%x\n", hiu_reg_value); + pr_info("hhi_pll_reg_frac:0x%x\n", hiu_reg_value_2); + } + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + hiu_m_val = hiu_reg_value & 0xff; + /*discard low 5 bits*/ + hiu_frac_val = (hiu_reg_value_2 >> 5) & 0xfff; + reg_value = (hiu_m_val << 12) + hiu_frac_val; + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { hiu_m_val = hiu_reg_value & 0x1FF; hiu_frac_val = hiu_reg_value_2 & 0x3FF; if (hiu_reg_value_2 & 0x800) { @@ -383,6 +424,19 @@ static void vlock_setting(struct vframe_s *vf, /* enable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 29, 1); } + + /*initial phase lock setting*/ + if (vlock.dtdata->vlk_phlock_en) { + /*WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, 0x06000000);*/ + WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, 0x06000000); + WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_PLL_LMT, 0x06000000); + WRITE_VPP_REG(VPU_VLOCK_OUTPUT1_CAPT_LMT, 0x06000000); + WRITE_VPP_REG(VPU_VLOCK_OUTPUT1_PLL_LMT, 0x06000000); + + /*enable pll mode and enc mode phase lock*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 3, 0, 2); + } + /* vlock module output goes to which module */ switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0:/* ENCL */ @@ -487,24 +541,61 @@ static void vlock_disable_step1(void) if ((vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL | VLOCK_MODE_MANUAL_SOFT_ENC))) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - m_reg_value = tmp_value & 0xfff; - if (m_reg_value != pre_hiu_reg_frac) { - tmp_value = (tmp_value & 0xfffff000) | - (pre_hiu_reg_frac & 0xfff); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - } - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - m_reg_value = tmp_value & 0x1ff; - if ((m_reg_value != pre_hiu_reg_m) && - (pre_hiu_reg_m != 0)) { - tmp_value = (tmp_value & 0xfffffe00) | - (pre_hiu_reg_m & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + #if 0 + amvecm_hiu_reg_read(hhi_pll_reg_frac, + &tmp_value); + m_reg_value = (tmp_value >> 5) & 0xfff; + if (m_reg_value != pre_hiu_reg_frac) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + amvecm_hiu_reg_write(hhi_pll_reg_frac, + tmp_value); + pr_info("restore f value=0x%x\n", tmp_value); + } + amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + m_reg_value = tmp_value & 0xff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xffffff00) | + (pre_hiu_reg_m & 0xff); + amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value); + pr_info("restore m value=0x%x\n", tmp_value); + } + #endif + + #if 1 + /*restore the orginal pll setting*/ + amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + m_reg_value = tmp_value & 0xff; + if (m_reg_value != (vlock.val_m & 0xff)) + amvecm_hiu_reg_write(hhi_pll_reg_m, + vlock.val_m); + + amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value); + m_reg_value = tmp_value & 0x1ffff; + if (m_reg_value != (vlock.val_frac & 0xfff)) + amvecm_hiu_reg_write(hhi_pll_reg_frac, + vlock.val_frac); + pr_info("restore orignal m,f value\n"); + #endif + } else { + amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value); + m_reg_value = tmp_value & 0xfff; + if (m_reg_value != pre_hiu_reg_frac) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + amvecm_hiu_reg_write(hhi_pll_reg_frac, + tmp_value); + } + amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + m_reg_value = tmp_value & 0x1ff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xfffffe00) | + (pre_hiu_reg_m & 0x1ff); + amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value); + } } } if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | @@ -539,13 +630,22 @@ static void vlock_disable_step1(void) vlock_enc_stable_flag = 0; } -static void vlock_disable_step2(void) +static bool vlock_disable_step2(void) { unsigned int temp_val; + bool ret = false; + /* need delay to disable follow regs(vlsi suggest!!!) */ if (vlock_dis_cnt > 0) vlock_dis_cnt--; - if (vlock_dis_cnt == 0) { + else if (vlock_dis_cnt == 0) { + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x4, 0, 3); + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x0, 0, 3); + } + /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); /* CFG_VID_LOCK_ADJ_EN disable */ @@ -556,11 +656,21 @@ static void vlock_disable_step2(void) /* disable vid_lock_en */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); - if (is_meson_gxtvbb_cpu() && (((temp_val >> 21) & 0x3) != 0)) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 21, 2); + if (is_meson_gxtvbb_cpu()) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); + if (((temp_val >> 21) & 0x3) != 0) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, + 0, 21, 2); + } + ret = true; + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } + + return ret; } + static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, unsigned int input_hz, unsigned int output_hz) { @@ -919,12 +1029,19 @@ static void vlock_enable_step3_pll(void) *on gxtvbb this load signal will effect SSG, *which may result in flashes black */ + if (is_meson_gxtvbb_cpu()) { amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu() && (((tmp_value >> 21) & 0x3) != 2)) + if (((tmp_value >> 21) & 0x3) != 2) amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 2, 21, 2); - /*add delta count check*/ - /*for interlace input need div 2*/ - if (vlock_intput_type) + } + + /* add delta count check + *for interlace input need div 2 + *0:progressive type + *1:interlace type + */ + if (vlock_intput_type && + (vlock.dtdata->vlk_hwver < vlock_hw_ver2)) ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST) / 2; else ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); @@ -936,45 +1053,61 @@ static void vlock_enable_step3_pll(void) return; } /*frac*/ - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); - if ((abs_val >= vlock_log_delta_frac) && (vlock_log_delta_en&(1<<3))) - pr_info("vlock frac delta:%d(0x%x,0x%x)\n", - abs_val, ((m_reg_value & 0xfff) >> 2), + tmp_value = vlock_get_panel_pll_frac(); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { + abs_val = abs(((m_f_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); - if ((abs_val >= vlock_delta_limit) && - (abs_cnt > vlock_delta_cnt_limit)) { - tmp_value = (tmp_value & 0xfffff000) | - ((m_reg_value & 0xfff) >> 2); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - vlock_pll_val_last &= 0xffff0000; - vlock_pll_val_last |= (m_reg_value & 0xfff); + if ((abs_val >= vlock_log_delta_frac) && + (vlock_log_delta_en&(1<<3))) + pr_info("vlock frac delta:%d(0x%x,0x%x)\n", + abs_val, ((m_f_reg_value & 0xfff) >> 2), + (tmp_value & 0xfff)); + if ((abs_val >= vlock_delta_limit) && + (abs_cnt > vlock_delta_cnt_limit)) { + tmp_value = (tmp_value & 0xfffff000) | + ((m_f_reg_value & 0xfff) >> 2); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);*/ + vlock_set_panel_pll_frac(tmp_value); + vlock_pll_val_last &= 0xffff0000; + vlock_pll_val_last |= (m_f_reg_value & 0xfff); + } + /*check stable by diff frac*/ + if ((abs_val < (2 * vlock_delta_limit)) && + (abs_cnt < vlock_enc_adj_limit)) + vlock_pll_stable_cnt++; + else + vlock_pll_stable_cnt = 0; + } else { + abs_val = abs((tmp_value & 0x1ffff) - + ((m_f_reg_value & 0xfff) << 5)); + + if (abs_val > (50 << 5)) + tmp_value = ((tmp_value & 0xfffe0000) | + (((tmp_value & 0x1ffff) + + ((m_f_reg_value & 0xfff) << 5)) >> 1)); + else + tmp_value = (tmp_value & 0xfffe0000) | + ((m_f_reg_value & 0xfff) << 5); + if (((tmp_value & 0x1ffff) != + (vlock_get_panel_pll_frac() & 0x1ffff)) && + !mchang) { + if (f_diff_cnt++ > VLOCK_UPDATE_F_CNT) { + f_diff_cnt = 0; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock f: 0x%x\n", tmp_value); + vlock_set_panel_pll_frac(tmp_value);/*16:0*/ } - /*check stable by diff frac*/ - if ((abs_val < (2 * vlock_delta_limit)) && - (abs_cnt < vlock_enc_adj_limit)) - vlock_pll_stable_cnt++; - else - vlock_pll_stable_cnt = 0; - /*m*/ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (pre_hiu_reg_m & 0x1ff)); - if ((abs_val > vlock_log_delta_m) && (vlock_log_delta_en&(1<<4))) - pr_info("vlock m delta:%d(0x%x,0x%x)\n", - abs_val, ((m_reg_value >> 16) & 0x1ff), - (tmp_value & 0x1ff)); - if ((abs_val <= vlock_pll_m_limit) && - (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) && - (abs_cnt > vlock_delta_cnt_limit)) { - tmp_value = (tmp_value & 0xfffffe00) | - ((m_reg_value >> 16) & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); - vlock_pll_val_last &= 0x0000ffff; - vlock_pll_val_last |= (m_reg_value & 0xffff0000); + } } + /*check stable by diff m*/ - if (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (((m_f_reg_value >> 16) & 0xff) != (tmp_value & 0xff)) + vlock_pll_stable_cnt = 0; + } else { + if (((m_f_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) vlock_pll_stable_cnt = 0; + } } /* won't change this function internal seqence, * if really need change,please be carefull and check with vlsi @@ -994,7 +1127,8 @@ void amve_vlock_process(struct vframe_s *vf) } vinfo = get_current_vinfo(); input_hz = vlock_check_input_hz(vf); - output_hz = vlock_check_output_hz(vinfo->sync_duration_num); + output_hz = vlock_check_output_hz(vinfo->sync_duration_num, + vinfo->sync_duration_den); vlock_dis_cnt_no_vf = 0; if (vecm_latch_flag & FLAG_VLOCK_EN) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); @@ -1072,6 +1206,22 @@ void amve_vlock_process(struct vframe_s *vf) /*cal accum0 value*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE; + + /* + * tl1 auto pll,swich clk need after + *several frames + */ + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + else if (IS_MANUAL_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + } + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-2\n"); } else if (vlock_dynamic_adjust && (vlock_sync_limit_flag > 5) && (vlock_state == VLOCK_STATE_ENABLE_STEP2_DONE) && @@ -1149,6 +1299,450 @@ void amve_vlock_resume(void) } } +void vlock_clear_frame_counter(void) +{ + vlock.frame_cnt_in = 0; + vlock.frame_cnt_no = 0; +} + +void vlock_set_en(bool en) +{ + /*if (vlock.dtdata->vlk_support)*/ + vlock_en = en; +} + +void vlock_status_init(void) +{ + unsigned int val; + + /*config vlock mode*/ + /*todo:txlx & g9tv support auto pll,*/ + /*but support not good,need vlsi support optimize*/ + vlock_mode = VLOCK_MODE_MANUAL_PLL; + if (is_meson_gxtvbb_cpu() || + is_meson_txl_cpu() || is_meson_txlx_cpu() + || is_meson_tl1_cpu()) + vlock_en = 1; + else + vlock_en = 0; + + if (is_meson_tl1_cpu()) { + hhi_pll_reg_m = HHI_TCON_PLL_CNTL0; + hhi_pll_reg_frac = HHI_TCON_PLL_CNTL1; + /*hhi_pll_reg_vlock_ctl = HHI_HDMI_PLL_VLOCK_CNTL;*/ + } else if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXL) { + hhi_pll_reg_m = HHI_HDMI_PLL_CNTL; + hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; + } else { + hhi_pll_reg_m = HHI_HDMI_PLL_CNTL; + hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; + } + + /*back up orignal pll value*/ + amvecm_hiu_reg_read(hhi_pll_reg_m, &val); + vlock.val_m = val; + pr_info("HIU pll m[0x%x]=0x%x\n", + hhi_pll_reg_m, val); + amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); + vlock.val_frac = val; + pr_info("HIU pll f[0x%x]=0x%x\n", + hhi_pll_reg_frac, val); + + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock.fsm_prests = VLOCK_STATE_NULL; + vlock.vf_sts = false; + vlock.vmd_chg = false; + vlock.md_support = false; + vlock.phlock_percent = 40; + vlock_clear_frame_counter(); + pr_info("%s vlock_en:%d\n", __func__, vlock_en); +} + +void vlock_dt_match_init(struct vecm_match_data_s *pdata) +{ + vlock.dtdata = pdata; + /*vlock_en = vlock.dtdata.vlk_support;*/ + pr_info("vlock dt support: %d\n", vlock.dtdata->vlk_support); + pr_info("vlock dt new_fsm: %d\n", vlock.dtdata->vlk_new_fsm); + pr_info("vlock dt hwver: %d\n", vlock.dtdata->vlk_hwver); + pr_info("vlock dt phlock_en: %d\n", vlock.dtdata->vlk_phlock_en); +} + +void vlock_set_phase(u32 percent) +{ + u32 vs_i_val = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + /*u32 vs_o_val = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST);*/ + u32 data = 0; + + if (!vlock.dtdata->vlk_phlock_en) + return; + + if (percent > 100) { + pr_info("percent val err:%d\n", percent); + return; + } + + vlock.phlock_percent = percent; + data = (vs_i_val * (100 + vlock.phlock_percent))/200; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, data); + pr_info("LOOP1_PHSDIF_TGT:0x%x\n", data); + + /*reset*/ + data = READ_VPP_REG(VPU_VLOCK_CTRL); + data |= 1 << 2; + data |= 1 << 5; + WRITE_VPP_REG(VPU_VLOCK_CTRL, data); + data &= ~(1 << 2); + data &= ~(1 << 5); + WRITE_VPP_REG(VPU_VLOCK_CTRL, data); +} + +void vlock_set_phase_en(u32 en) +{ + if (en) + vlock.dtdata->vlk_phlock_en = true; + else + vlock.dtdata->vlk_phlock_en = false; +} + +#if 1 + +u32 vlock_fsm_check_support(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = true; + + if (((pvlock->input_hz != pvlock->output_hz) && (vlock_adapt == 0)) || + (pvlock->input_hz == 0) || (pvlock->output_hz == 0) || + (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) && + is_meson_txlx_package_962E())) { + + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("[%s] for no support case!!!\n", + __func__); + pr_info("input_hz:%d, output_hz:%d\n", + pvlock->input_hz, pvlock->output_hz); + pr_info("type_original:0x%x\n", vf->type_original); + } + ret = false; + } + + if (vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE_PRE) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s] for vmode change pre case!!!\n", + __func__); + ret = false; + } + + return ret; +} + +u32 vlock_fsm_input_check(struct stvlock_sig_sts *vlock, struct vframe_s *vf) +{ + u32 ret = 0; + u32 vframe_sts; + struct vinfo_s *vinfo = NULL; + + if (vf == NULL) + vframe_sts = false; + else + vframe_sts = true; + + vlock_vmode_check(); + + if (vf != NULL) { + vinfo = get_current_vinfo(); + vlock->input_hz = vlock_check_input_hz(vf); + vlock->output_hz = vlock_check_output_hz( + vinfo->sync_duration_num, vinfo->sync_duration_den); + } + + /*check vf exist status*/ + if (vlock->vf_sts != vframe_sts) { + vlock->vf_sts = vframe_sts; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock vfsts chg %d\n", vframe_sts); + ret = 1; + } else if (vlock_vmode_change_status) { + /*check video mode status*/ + vlock->vmd_chg = true; + ret = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock vmode chg\n"); + } + + if (vlock->vf_sts) + vlock->md_support = vlock_fsm_check_support(vlock, vf); + + return ret; +} + +u32 vlock_fsm_to_en_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + struct vinfo_s *vinfo; + + if ((vf->source_type != pre_source_type) || + (vf->source_mode != pre_source_mode) || + (pvlock->input_hz != pre_input_freq) || + (pvlock->output_hz != pre_output_freq) || + vlock_vmode_changed || + (pvlock->fsm_sts == + VLOCK_STATE_ENABLE_FORCE_RESET)) { + + /*back up orignal pll value*/ + amvecm_hiu_reg_read(hhi_pll_reg_m, &vlock.val_m); + amvecm_hiu_reg_read(hhi_pll_reg_frac, &vlock.val_frac); + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("HIU pll m[0x%x]=0x%x\n", + hhi_pll_reg_m, vlock.val_m); + pr_info("HIU pll f[0x%x]=0x%x\n", + hhi_pll_reg_frac, vlock.val_frac); + } + vinfo = get_current_vinfo(); + vlock_enable_step1(vf, vinfo, + pvlock->input_hz, pvlock->output_hz); + ret = 1; + } + + return ret; +} + +u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + u32 input_vs_cnt; + + if ((pvlock->frame_cnt_in <= 3) && + ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | + VLOCK_MODE_MANUAL_PLL)))) { + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear first 3 frame internal cnt*/ + WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); + WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -0\n", __func__); + } else if ((pvlock->frame_cnt_in == 4) && + ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | + VLOCK_MODE_MANUAL_PLL)))) { + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -1\n", __func__); + } else if (pvlock->frame_cnt_in == 5) { + /*input_vs_cnt =*/ + /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ + /* 0, 28);*/ + input_vs_cnt = XTAL_VLOCK_CLOCK/pvlock->input_hz; + /*tl1 not need */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && + vf->type_original & VIDTYPE_TYPEMASK) + input_vs_cnt = input_vs_cnt << 1; + + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, + input_vs_cnt*125/100); + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, + input_vs_cnt*70/100); + + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*cal accum0 value*/ + //WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + + /* + * tl1 auto pll,swich clk need after + *several frames + */ + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + else if (IS_MANUAL_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + } + + ret = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -2\n", __func__); + } + + return ret; +} + + +void vlock_phaselock_check(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + /*vs_i*/ + u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + u32 val; + + if (vlock.dtdata->vlk_phlock_en) { + ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + val = (ia * (100 + vlock.phlock_percent))/200; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); + + /*reset*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + } +} + +u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + + if (vlock_dynamic_adjust && + (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) && + (IS_MANUAL_MODE(vlock_mode))) { + if (IS_MANUAL_ENC_MODE(vlock_mode)) + vlock_enable_step3_enc(); + else if (IS_MANUAL_PLL_MODE(vlock_mode)) + vlock_enable_step3_pll(); + else if (IS_MANUAL_SOFTENC_MODE(vlock_mode)) + vlock_enable_step3_soft_enc(); + } + + /*check phase*/ + vlock_phaselock_check(pvlock, vf); + return ret; +} + + +void vlock_fsm_monitor(struct vframe_s *vf) +{ + u32 changed; + + changed = vlock_fsm_input_check(&vlock, vf); + switch (vlock.fsm_sts) { + case VLOCK_STATE_NULL: + if (vlock.vf_sts) { + /*have frame in*/ + if (vlock.frame_cnt_in++ >= 20) { + /*vframe input valid*/ + if (vlock.md_support) { + if (vlock_fsm_to_en_func(&vlock, vf)) { + vlock_clear_frame_counter(); + vlock.fsm_sts = + VLOCK_STATE_ENABLE_STEP1_DONE; + } else { + /*error waitting here*/ + vlock_clear_frame_counter(); + } + } + } + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE; + } else { + /*disabled and waitting here*/ + vlock_clear_frame_counter(); + } + break; + + case VLOCK_STATE_ENABLE_STEP1_DONE: + if (vlock.vf_sts) { + vlock.frame_cnt_in++; + if (vlock_fsm_en_step1_func(&vlock, vf)) + vlock.fsm_sts = VLOCK_STATE_ENABLE_STEP2_DONE; + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else { + vlock.frame_cnt_in = 0; + if (vlock.frame_cnt_no++ > vlock_dis_cnt_no_vf_limit) { + /*go to disable state*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } + } + break; + + case VLOCK_STATE_ENABLE_STEP2_DONE: + if (vlock.vf_sts) { + if (!vlock.md_support) { + /*function not support*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else if (vecm_latch_flag & FLAG_VLOCK_DIS) { + /*disable vlock by vecm cmd*/ + vlock_disable_step1(); + vlock_disable_step2(); + vlock_en = 0; + vecm_latch_flag &= ~FLAG_VLOCK_DIS; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s] vlock dis\n", __func__); + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_NULL; + } else { + /*normal mode*/ + vlock.frame_cnt_no = 0; + vlock_fsm_en_step2_func(&vlock, vf); + } + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else { + /*no frame input*/ + if (vlock.frame_cnt_no++ > vlock_dis_cnt_no_vf_limit) { + /*go to disable state*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } + } + break; + + case VLOCK_STATE_DISABLE_STEP1_DONE: + vlock_disable_step1(); + if (vlock_disable_step2()) + vlock.fsm_sts = VLOCK_STATE_NULL; + else + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE; + break; + + case VLOCK_STATE_DISABLE_STEP2_DONE: + if (vlock_disable_step2()) + vlock.fsm_sts = VLOCK_STATE_NULL; + break; + + default: + pr_info("err state %d\n", vlock.fsm_sts); + break; + } + + /*capture log*/ + if (((vlock_mode & (VLOCK_MODE_AUTO_PLL | + VLOCK_MODE_AUTO_ENC))) && + vlock_log_en && (vlock_log_cnt < vlock_log_size) && + (vlock_debug & VLOCK_DEBUG_AUTO_MODE_LOG_EN)) { + vlock_reg_get(); + vlock_log_cnt++; + } + + if ((vlock_debug & VLOCK_DEBUG_INFO) && + vlock.fsm_sts != vlock.fsm_prests) { + pr_info(">>> %s fsm %d to %d\n", __func__, + vlock.fsm_prests, vlock.fsm_sts); + vlock.fsm_prests = vlock.fsm_sts; + } +} +#endif + /*new packed separeted from amvecm_on_vs,avoid the influencec of repeate call, *which may affect vlock process */ @@ -1157,6 +1751,9 @@ void vlock_process(struct vframe_s *vf) if (probe_ok == 0) return; + if (vlock_debug & VLOCK_DEBUG_FSM_DIS) + return; + /* todo:vlock processs only for tv chip */ if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() @@ -1216,7 +1813,10 @@ void vlock_param_set(unsigned int val, enum vlock_param_e sel) } void vlock_status(void) { + struct vinfo_s *vinfo; + pr_info("\n current vlock parameters status:\n"); + pr_info("vlock driver version : %s\n", VLOCK_VER); pr_info("vlock_mode:%d\n", vlock_mode); pr_info("vlock_en:%d\n", vlock_en); pr_info("vlock_adapt:%d\n", vlock_adapt); @@ -1248,8 +1848,18 @@ void vlock_status(void) pr_info("vlock_intput_type:%d\n", vlock_intput_type); pr_info("vlock_pll_adj_limit:%d\n", vlock_pll_adj_limit); pr_info("vlock_pll_val_last:%d\n", vlock_pll_val_last); - pr_info("vlock driver version : %s\n", VLOCK_VER); + pr_info("vlk_support:%d\n", vlock.dtdata->vlk_support); + pr_info("vlk_new_fsm:%d\n", vlock.dtdata->vlk_new_fsm); + pr_info("vlk_phlock_en:%d\n", vlock.dtdata->vlk_phlock_en); + pr_info("vlk_hwver:%d\n", vlock.dtdata->vlk_hwver); + vinfo = get_current_vinfo(); + pr_info("vinfo sync_duration_num:%d\n", vinfo->sync_duration_num); + pr_info("vinfo sync_duration_den:%d\n", vinfo->sync_duration_den); + pr_info("vinfo video_clk:%d\n", vinfo->video_clk); + pr_info("vframe input_hz:%d\n", vlock.input_hz); + pr_info("vframe output_hz:%d\n", vlock.output_hz); } + void vlock_reg_dump(void) { unsigned int addr; @@ -1259,6 +1869,24 @@ void vlock_reg_dump(void) pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", (0xd0100000+(addr<<2)), addr, READ_VPP_REG(addr)); + + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + for (addr = (0x3021); addr <= (0x302a); addr++) + pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", + (0xd0100000+(addr<<2)), addr, + READ_VPP_REG(addr)); + amvecm_hiu_reg_read(HHI_HDMI_PLL_VLOCK_CNTL, &val); + pr_info("HIU [0x%04x]=0x%08x\n", HHI_HDMI_PLL_VLOCK_CNTL, val); + } + amvecm_hiu_reg_read(hhi_pll_reg_m, &val); + pr_info("HIU pll m[0x%04x]=0x%08x\n", hhi_pll_reg_m, val); + amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); + pr_info("HIU pll f[0x%04x]=0x%08x\n", hhi_pll_reg_frac, val); + + /*back up orignal pll value*/ + pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m); + pr_info("HIU pll f[0x%x]=0x%x\n", hhi_pll_reg_frac, vlock.val_frac); + } /*work around method for vlock process hdmirx input interlace source.@20170803 **for interlace input,TOP and BOT have one line delta, diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index 96784fb753f8..01a3eafc43ff 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2018/11/07a" +#define VLOCK_VER "Ref.2019/1/24" #define VLOCK_REG_NUM 33 @@ -59,6 +59,21 @@ enum vlock_param_e { VLOCK_PARAM_MAX, }; +struct stvlock_sig_sts { + u32 fsm_sts; + u32 fsm_prests; + u32 vf_sts; + u32 vmd_chg; + u32 frame_cnt_in; + u32 frame_cnt_no; + u32 input_hz; + u32 output_hz; + bool md_support; + u32 phlock_percent; + struct vecm_match_data_s *dtdata; + u32 val_frac; + u32 val_m; +}; extern void amve_vlock_process(struct vframe_s *vf); extern void amve_vlock_resume(void); extern void vlock_param_set(unsigned int val, enum vlock_param_e sel); @@ -84,6 +99,32 @@ extern void vlock_log_print(void); #define VLOCK_MODE_MANUAL_SOFT_ENC (1 << 4) #define VLOCK_MODE_MANUAL_MIX_PLL_ENC (1 << 5) +#define IS_MANUAL_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_PLL | \ + VLOCK_MODE_MANUAL_ENC | \ + VLOCK_MODE_MANUAL_SOFT_ENC)) + +#define IS_AUTO_MODE(md) (md & \ + (VLOCK_MODE_AUTO_PLL | \ + VLOCK_MODE_AUTO_ENC)) + +#define IS_PLL_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_PLL | \ + VLOCK_MODE_AUTO_PLL)) + +#define IS_AUTO_PLL_MODE(md) (md & \ + VLOCK_MODE_AUTO_PLL) + +#define IS_MANUAL_ENC_MODE(md) (md & \ + VLOCK_MODE_MANUAL_ENC) + +#define IS_MANUAL_PLL_MODE(md) (md & \ + VLOCK_MODE_MANUAL_PLL) + +#define IS_MANUAL_SOFTENC_MODE(md) (md & \ + VLOCK_MODE_MANUAL_SOFT_ENC) + + #define XTAL_VLOCK_CLOCK 24000000/*vlock use xtal clock*/ #define VLOCK_SUPPORT_HDMI (1 << 0) @@ -95,12 +136,13 @@ extern void vlock_log_print(void); #define VLOCK_PLL_ADJ_LIMIT 9/*vlock pll adj limit(0x300a default)*/ /*vlock_debug mask*/ -#define VLOCK_DEBUG_INFO (1 << 0) -#define VLOCK_DEBUG_FLUSH_REG_DIS (1 << 1) -#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (1 << 2) -#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (1 << 3) -#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (1 << 4) -#define VLOCK_DEBUG_PLL2ENC_DIS (1 << 5) +#define VLOCK_DEBUG_INFO (0x1) +#define VLOCK_DEBUG_FLUSH_REG_DIS (0x2) +#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (0x4) +#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (0x8) +#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (0x10) +#define VLOCK_DEBUG_PLL2ENC_DIS (0x20) +#define VLOCK_DEBUG_FSM_DIS (0x40) /* 0:enc;1:pll;2:manual pll */ extern unsigned int vlock_mode; @@ -123,4 +165,10 @@ extern void vlock_lcd_param_work(struct work_struct *p_work); extern int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, void *para); #endif +extern void vlock_status_init(void); +extern void vlock_dt_match_init(struct vecm_match_data_s *pdata); +extern void vlock_set_en(bool en); +extern void vlock_set_phase(u32 percent); +extern void vlock_set_phase_en(u32 en); + diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index 380e65798a39..1f8492bbb27c 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -326,6 +326,29 @@ enum ve_pq_timing_e { TIMING_MAX, }; +enum vlock_hw_ver_e { + /*gxtvbb*/ + vlock_hw_org, + /* + *txl + *txlx + */ + vlock_hw_ver1, + /* tl1 later + * fix bug:i problem + * fix bug:affect ss function + * add: phase lock + */ + vlock_hw_ver2, +}; + +struct vecm_match_data_s { + u32 vlk_support; + u32 vlk_new_fsm; + enum vlock_hw_ver_e vlk_hwver; + u32 vlk_phlock_en; +}; + /*overscan: *length 0~31bit :number of crop; *src_timing: bit31: on: load/save all crop From 8ad280b58f2a620201b8cf95eb419bee0c3555fe Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 30 Jan 2019 14:45:25 +0800 Subject: [PATCH 0477/1060] vlock: add phase lock function [1/1] PD#SWPL-3644 Problem: new feature on tl1 Solution: add function Verify: verified on tl1 android p Change-Id: I964054512f59a98f03d20df11b8c63d6802744d5 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/enhancement/amvecm/amvecm.c drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h drivers/amlogic/media/enhancement/amvecm/vlock.c drivers/amlogic/media/enhancement/amvecm/vlock.h --- .../amlogic/media/enhancement/amvecm/amvecm.c | 43 ++- .../enhancement/amvecm/amvecm_vlock_regmap.h | 24 +- .../amlogic/media/enhancement/amvecm/vlock.c | 334 ++++++++++++++---- .../amlogic/media/enhancement/amvecm/vlock.h | 21 +- 4 files changed, 323 insertions(+), 99 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index f8de07d7e4cc..77373273d938 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -738,12 +738,32 @@ static ssize_t amvecm_vlock_store(struct class *cla, if (kstrtol(parm[1], 10, &val) < 0) return -EINVAL; vlock_set_phase(val); - } else if (!strncmp(parm[0], "phaseen", 7)) { + } else if (!strncmp(parm[0], "phlock_en", 9)) { if (kstrtol(parm[1], 10, &val) < 0) return -EINVAL; vlock_set_phase_en(val); } else { - pr_info("unsupport cmd!!\n"); + pr_info("----cmd list -----\n"); + pr_info("vlock_mode val\n"); + pr_info("vlock_en val\n"); + pr_info("vlock_debug val\n"); + pr_info("vlock_adapt val\n"); + pr_info("vlock_dis_cnt_limit val\n"); + pr_info("vlock_delta_limit val\n"); + pr_info("vlock_dynamic_adjust val\n"); + pr_info("vlock_line_limit val\n"); + pr_info("vlock_dis_cnt_no_vf_limit val\n"); + pr_info("vlock_line_limit val\n"); + pr_info("vlock_support val\n"); + pr_info("enable\n"); + pr_info("disable\n"); + pr_info("status\n"); + pr_info("dump_reg\n"); + pr_info("log_start\n"); + pr_info("log_stop\n"); + pr_info("log_print\n"); + pr_info("phase persent\n"); + pr_info("phlock_en val\n"); } if (sel < VLOCK_PARAM_MAX) vlock_param_set(temp_val, sel); @@ -6526,13 +6546,6 @@ static const struct vecm_match_data_s vecm_dt_tl1 = { .vlk_phlock_en = true, }; -static const struct vecm_match_data_s vecm_dt_tm2 = { - .vlk_support = true, - .vlk_new_fsm = 1, - .vlk_hwver = vlock_hw_ver2, - .vlk_phlock_en = false, -}; - static const struct of_device_id aml_vecm_dt_match[] = { { .compatible = "amlogic, vecm", @@ -6592,6 +6605,18 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) pr_info("Can't find tx_op_color_primary.\n"); else tx_op_color_primary = val; + + /*get compatible matched device, to get chip related data*/ + of_id = of_match_device(aml_vecm_dt_match, &pdev->dev); + if (of_id != NULL) { + pr_info("%s", of_id->compatible); + matchdata = (struct vecm_match_data_s *)of_id->data; + } else { + matchdata = (struct vecm_match_data_s *)&vecm_dt_xxx; + pr_info("unable to get matched device\n"); + } + vlock_dt_match_init(matchdata); + /*vlock param config*/ vlock_param_config(node); } diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index 543d9bbe39f2..292827d3c464 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -30,13 +30,13 @@ static struct vlock_regs_s vlock_enc_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3000, 0xE3f50f10 }, {0x3001, 0x41E3c3c }, {0x3002, 0x6000000 }, - {0x3003, 0x20680680 }, - {0x3004, 0x280280 }, + {0x3003, 0x20709709/*0x20680680 */}, + {0x3004, 0x00709709/*0x280280 */}, {0x3005, 0x8020000 }, {0x3006, 0x0008000 }, {0x3007, 0x0000000 }, {0x3008, 0x0000000 }, - {0x3009, 0x0008000 }, + {0x3009, 0x6000000/*0x0008000 */}, {0x300a, 0x8000000 }, {0x300b, 0x000a000 }, {0x300c, 0xa000000 }, @@ -60,17 +60,31 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3007, 0x00000000 }, {0x3008, 0x00000000 }, {0x3009, 0x00100000 }, - {0x300a, 0x00008000 },/*0x00600000*/ + {0x300a, 0x00600000 }, {0x300b, 0x00100000 }, {0x300c, 0x00600000 }, {0x300d, 0x00004000 }, {0x3010, 0x20001000 }, {0x3016, 0x0003de00 }, - {0x3017, 0x00001080 }, + {0x3017, 0x00001010 }, {0x301d, 0x30501080 }, {0x301e, 0x00000007 }, {0x301f, 0x06000000 } }; +#define VLOCK_PHASE_REG_SIZE 9 +static struct vlock_regs_s vlock_pll_phase_setting[VLOCK_PHASE_REG_SIZE] = { + {0x3004, 0x00620680}, + {0x3009, 0x06000000}, + {0x300a, 0x00600000}, + {0x300b, 0x06000000}, + {0x300c, 0x00600000}, + + {0x3025, 0x00002000}, + {0x3027, 0x00022002}, + {0x3028, 0x00001000}, + {0x302a, 0x00022002}, +}; + #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index bd5344f8b01c..77e83be83a1e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -36,12 +36,12 @@ /* video lock */ /* 0:off; - * 1:auto enc; VLOCK_MODE_AUTO_ENC + * 1:auto enc; * 2:auto pll; - * 4:manual pll; VLOCK_MODE_MANUAL_PLL + * 4:manual pll; * 8:manual_enc mode(only support lvds/vx1) */ -unsigned int vlock_mode = VLOCK_MODE_MANUAL_PLL; +enum VLOCK_MD vlock_mode = VLOCK_MODE_MANUAL_PLL; unsigned int vlock_en = 1; /* *0:only support 50->50;60->60;24->24;30->30; @@ -67,7 +67,7 @@ static unsigned int vlock_intput_type; static signed int vlock_line_limit = 3; static unsigned int vlock_enc_adj_limit; /* 0x3009 default setting for 2 line(1080p-output) is 0x8000 */ -static unsigned int vlock_capture_limit = 0x8000; +static unsigned int vlock_capture_limit = 0x10000/*0x8000*/; static unsigned int vlock_debug; static unsigned int vlock_dynamic_adjust = 1; @@ -170,6 +170,41 @@ static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, return 0; } +u32 vlock_get_panel_pll_m(void) +{ + u32 val; + + amvecm_hiu_reg_read(hhi_pll_reg_m, &val); + return val; +} + +void vlock_set_panel_pll_m(u32 val) +{ + amvecm_hiu_reg_write(hhi_pll_reg_m, val); +} + +u32 vlock_get_panel_pll_frac(void) +{ + u32 val; + + amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); + return val; +} + +void vlock_set_panel_pll_frac(u32 val) +{ + amvecm_hiu_reg_write(hhi_pll_reg_frac, val); +} + + +/*returen 1: use phase lock*/ +int phase_lock_check(void) +{ + unsigned int ret = 0; + + ret = READ_VPP_REG_BITS(VPU_VLOCK_RO_LCK_FRM, 17, 1); + return ret; +} static unsigned int vlock_check_input_hz(struct vframe_s *vf) { @@ -266,8 +301,8 @@ static void vlock_enable(bool enable) /*reset*/ if (!(vlock_mode & VLOCK_MODE_MANUAL_PLL)) { /*reset*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ } if (!enable) { @@ -295,13 +330,13 @@ static void vlock_setting(struct vframe_s *vf, unsigned int hiu_m_val, hiu_frac_val, temp_value; amvecm_hiu_reg_write(HHI_VID_LOCK_CLK_CNTL, 0x80); - if ((vlock_mode & (VLOCK_MODE_AUTO_ENC | - VLOCK_MODE_MANUAL_ENC | - VLOCK_MODE_MANUAL_SOFT_ENC))) { + if (IS_ENC_MODE(vlock_mode)) { /*init default config for enc mode*/ vlock_hw_reinit(vlock_enc_setting, VLOCK_DEFAULT_REG_SIZE); /*vlock line limit*/ - WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, vlock_capture_limit); + /*WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT,*/ + /* vlock_capture_limit);*/ + /* VLOCK_CNTL_EN disable */ vlock_enable(0); /* disable to adjust pll */ @@ -347,12 +382,14 @@ static void vlock_setting(struct vframe_s *vf, WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, input_hz, 16, 8); temp_value = READ_VPP_REG(enc_max_line_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 0, 14); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, + temp_value + 1, 0, 14); temp_value = READ_VPP_REG(enc_max_pixel_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 16, 14); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, + temp_value + 1, 16, 14); WRITE_VPP_REG_BITS(VPU_VLOCK_ADJ_EN_SYNC_CTRL, vlock_latch_en_cnt, 8, 8); - WRITE_VPP_REG_BITS(enc_video_mode_addr, 0, 15, 1); + WRITE_VPP_REG_BITS(enc_video_mode_addr, 1, 15, 1); } if ((vlock_mode & (VLOCK_MODE_AUTO_PLL | VLOCK_MODE_MANUAL_PLL))) { @@ -379,9 +416,11 @@ static void vlock_setting(struct vframe_s *vf, /*set PLL M_INT;PLL M_frac*/ /* WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, */ /* READ_CBUS_REG_BITS(HHI_HDMI_PLL_CNTL,0,9),12,9); */ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &hiu_reg_value); - amvecm_hiu_reg_read(hiu_reg_value_2_addr, - &hiu_reg_value_2); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &hiu_reg_value);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac,*/ + /* &hiu_reg_value_2);*/ + hiu_reg_value = vlock_get_panel_pll_m(); + hiu_reg_value_2 = vlock_get_panel_pll_frac(); if (vlock_debug & VLOCK_DEBUG_INFO) { pr_info("hhi_pll_reg_m:0x%x\n", hiu_reg_value); @@ -427,14 +466,16 @@ static void vlock_setting(struct vframe_s *vf, /*initial phase lock setting*/ if (vlock.dtdata->vlk_phlock_en) { - /*WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, 0x06000000);*/ - WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, 0x06000000); - WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_PLL_LMT, 0x06000000); - WRITE_VPP_REG(VPU_VLOCK_OUTPUT1_CAPT_LMT, 0x06000000); - WRITE_VPP_REG(VPU_VLOCK_OUTPUT1_PLL_LMT, 0x06000000); + vlock_hw_reinit(vlock_pll_phase_setting, VLOCK_PHASE_REG_SIZE); + /*disable pll lock*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 3, 1);*/ /*enable pll mode and enc mode phase lock*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 3, 0, 2); + + /*reset*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); } /* vlock module output goes to which module */ @@ -477,14 +518,22 @@ void vlock_vmode_check(void) (pre_hiu_reg_m == 0)) { if (vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL)) { - amvecm_hiu_reg_read(hiu_reg_addr, &t0); - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &t1); - pre_hiu_reg_frac = t0 & 0xfff; - pre_hiu_reg_m = t1 & 0x1ff; + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &t0);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &t1);*/ + t0 = vlock_get_panel_pll_m(); + t1 = vlock_get_panel_pll_frac(); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + pre_hiu_reg_frac = (t0 >> 5) & 0xfff; + pre_hiu_reg_m = t1 & 0xff; + } else { + pre_hiu_reg_frac = t0 & 0xfff; + pre_hiu_reg_m = t1 & 0x1ff; + } } if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_AUTO_ENC | VLOCK_MODE_MANUAL_SOFT_ENC))) { + #if 0 switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0: @@ -520,6 +569,7 @@ void vlock_vmode_check(void) ENCL_MAX_LINE_SWITCH_POINT; break; } + #endif pre_enc_max_line = READ_VPP_REG(enc_max_line_addr); pre_enc_max_pixel = READ_VPP_REG(enc_max_pixel_addr); vlock_capture_limit = ((1 << 12) * vlock_line_limit) / @@ -566,35 +616,44 @@ static void vlock_disable_step1(void) #if 1 /*restore the orginal pll setting*/ - amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); m_reg_value = tmp_value & 0xff; if (m_reg_value != (vlock.val_m & 0xff)) - amvecm_hiu_reg_write(hhi_pll_reg_m, - vlock.val_m); + vlock_set_panel_pll_m(vlock.val_m); + /*amvecm_hiu_reg_write(hhi_pll_reg_m,*/ + /* vlock.val_m);*/ - amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value); + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); m_reg_value = tmp_value & 0x1ffff; if (m_reg_value != (vlock.val_frac & 0xfff)) - amvecm_hiu_reg_write(hhi_pll_reg_frac, - vlock.val_frac); + vlock_set_panel_pll_frac(vlock.val_frac); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ + /* vlock.val_frac);*/ pr_info("restore orignal m,f value\n"); #endif } else { - amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value); + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); m_reg_value = tmp_value & 0xfff; if (m_reg_value != pre_hiu_reg_frac) { tmp_value = (tmp_value & 0xfffff000) | (pre_hiu_reg_frac & 0xfff); - amvecm_hiu_reg_write(hhi_pll_reg_frac, - tmp_value); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ + /* tmp_value);*/ + vlock_set_panel_pll_frac(tmp_value); } - amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); m_reg_value = tmp_value & 0x1ff; if ((m_reg_value != pre_hiu_reg_m) && (pre_hiu_reg_m != 0)) { tmp_value = (tmp_value & 0xfffffe00) | (pre_hiu_reg_m & 0x1ff); - amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value); + /*amvecm_hiu_reg_write(hhi_pll_reg_m, */ + /*tmp_value);*/ + vlock_set_panel_pll_m(tmp_value); } } } @@ -977,6 +1036,7 @@ static void vlock_enable_step3_pll(void) { unsigned int m_reg_value, tmp_value, abs_val, hiu_reg_addr; unsigned int ia, oa, abs_cnt; + unsigned int pre_m, new_m, tar_m, org_m; if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) hiu_reg_addr = HHI_HDMI_PLL_CNTL1; @@ -1008,10 +1068,20 @@ static void vlock_enable_step3_pll(void) m_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC); if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) { + #if 0 vlock_log[vlock_log_cnt]->pll_frac = (vlock_pll_val_last & 0xfff) >> 2; vlock_log[vlock_log_cnt]->pll_m = (vlock_pll_val_last >> 16) & 0x1ff; + #else + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); + vlock_log[vlock_log_cnt]->pll_frac = tmp_value; + + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); + vlock_log[vlock_log_cnt]->pll_m = tmp_value; + #endif vlock_reg_get(); vlock_log_cnt++; } @@ -1053,6 +1123,7 @@ static void vlock_enable_step3_pll(void) return; } /*frac*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ tmp_value = vlock_get_panel_pll_frac(); if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { abs_val = abs(((m_f_reg_value & 0xfff) >> 2) - @@ -1065,7 +1136,7 @@ static void vlock_enable_step3_pll(void) if ((abs_val >= vlock_delta_limit) && (abs_cnt > vlock_delta_cnt_limit)) { tmp_value = (tmp_value & 0xfffff000) | - ((m_f_reg_value & 0xfff) >> 2); + ((m_reg_value & 0xfff) >> 2); /*amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);*/ vlock_set_panel_pll_frac(tmp_value); vlock_pll_val_last &= 0xffff0000; @@ -1096,7 +1167,7 @@ static void vlock_enable_step3_pll(void) if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("vlock f: 0x%x\n", tmp_value); vlock_set_panel_pll_frac(tmp_value);/*16:0*/ - } + } } } @@ -1303,6 +1374,7 @@ void vlock_clear_frame_counter(void) { vlock.frame_cnt_in = 0; vlock.frame_cnt_no = 0; + vlock_log_cnt = 0; } void vlock_set_en(bool en) @@ -1313,8 +1385,6 @@ void vlock_set_en(bool en) void vlock_status_init(void) { - unsigned int val; - /*config vlock mode*/ /*todo:txlx & g9tv support auto pll,*/ /*but support not good,need vlsi support optimize*/ @@ -1326,6 +1396,7 @@ void vlock_status_init(void) else vlock_en = 0; + /*initial pll register address*/ if (is_meson_tl1_cpu()) { hhi_pll_reg_m = HHI_TCON_PLL_CNTL0; hhi_pll_reg_frac = HHI_TCON_PLL_CNTL1; @@ -1339,15 +1410,46 @@ void vlock_status_init(void) hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; } + /*initial enc register address*/ + switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, + 0, 2)) { + case 0: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; +#if 0 /*enc mode not adapt to ENCP and ENCT*/ + case 2: + enc_max_line_addr = ENCP_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCP_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCP_VIDEO_MODE; + enc_max_line_switch_addr = + ENCP_MAX_LINE_SWITCH_POINT; + break; + case 3: + enc_max_line_addr = ENCT_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCT_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCT_VIDEO_MODE; + enc_max_line_switch_addr = + ENCT_MAX_LINE_SWITCH_POINT; + break; +#endif + default: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; + } + /*back up orignal pll value*/ - amvecm_hiu_reg_read(hhi_pll_reg_m, &val); - vlock.val_m = val; - pr_info("HIU pll m[0x%x]=0x%x\n", - hhi_pll_reg_m, val); - amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); - vlock.val_frac = val; - pr_info("HIU pll f[0x%x]=0x%x\n", - hhi_pll_reg_frac, val); + vlock.val_m = vlock_get_panel_pll_m(); + vlock.val_frac = vlock_get_panel_pll_frac(); vlock.fsm_sts = VLOCK_STATE_NULL; vlock.fsm_prests = VLOCK_STATE_NULL; @@ -1356,6 +1458,8 @@ void vlock_status_init(void) vlock.md_support = false; vlock.phlock_percent = 40; vlock_clear_frame_counter(); + + pr_info("%s vlock_en:%d\n", __func__, vlock_en); } @@ -1404,6 +1508,91 @@ void vlock_set_phase_en(u32 en) vlock.dtdata->vlk_phlock_en = true; else vlock.dtdata->vlk_phlock_en = false; + pr_info("vlock phlock_en=%d\n", en); +} + +void vlock_phaselock_check(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + /*vs_i*/ + u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + u32 val; + static u32 cnt = 48; + + if (vlock.dtdata->vlk_phlock_en) { + if (cnt++ > 50) { + ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + val = (ia * (100 + vlock.phlock_percent))/200; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); + cnt = 0; + #if 0 + /*reset*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + #endif + } + } +} + +bool vlock_get_phlock_flag(void) +{ + u32 flag; + u32 sts; + + if (!vlock.dtdata->vlk_phlock_en) + return false; + + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 17; + flag = flag&0x01; + + if (vlock.dtdata->vlk_new_fsm) + sts = vlock.fsm_sts; + else + sts = vlock_state; + + if (flag && (sts == VLOCK_STATE_ENABLE_STEP2_DONE)) + return true; + else + return false; +} + +bool vlock_get_vlock_flag(void) +{ + u32 flag; + u32 sts; + + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 16; + flag = flag&0x01; + + if (vlock.dtdata->vlk_new_fsm) + sts = vlock.fsm_sts; + else + sts = vlock_state; + + if (flag && (sts == VLOCK_STATE_ENABLE_STEP2_DONE)) + return true; + else + return false; +} + +void vlock_enc_timing_monitor(void) +{ + static unsigned int pre_line, pre_pixel; + unsigned int cur_line, cur_pixel; + unsigned int val; + + val = READ_VPP_REG(VPU_VLOCK_RO_LINE_PIX_ADJ); + cur_pixel = (val & 0x0000ffff); + cur_line = (val >> 16) & 0x0000ffff; + + if ((cur_line != pre_line) || (cur_pixel != pre_pixel)) { + pr_info("vlock line=0x%x pixel=0x%x\n", + cur_line, cur_pixel); + pre_line = cur_line; + pre_pixel = cur_pixel; + } } #if 1 @@ -1494,8 +1683,10 @@ u32 vlock_fsm_to_en_func(struct stvlock_sig_sts *pvlock, VLOCK_STATE_ENABLE_FORCE_RESET)) { /*back up orignal pll value*/ - amvecm_hiu_reg_read(hhi_pll_reg_m, &vlock.val_m); - amvecm_hiu_reg_read(hhi_pll_reg_frac, &vlock.val_frac); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &vlock.val_m);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &vlock.val_frac);*/ + vlock.val_m = vlock_get_panel_pll_m(); + vlock.val_frac = vlock_get_panel_pll_frac(); if (vlock_debug & VLOCK_DEBUG_INFO) { pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m); @@ -1554,7 +1745,7 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, /*cal accum1 value*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); /*cal accum0 value*/ - //WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); /* * tl1 auto pll,swich clk need after @@ -1577,36 +1768,14 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, return ret; } - -void vlock_phaselock_check(struct stvlock_sig_sts *pvlock, - struct vframe_s *vf) -{ - /*vs_i*/ - u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); - u32 val; - - if (vlock.dtdata->vlk_phlock_en) { - ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); - val = (ia * (100 + vlock.phlock_percent))/200; - WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); - - /*reset*/ - /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/ - /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ - - /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ - /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ - } -} - u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, struct vframe_s *vf) { u32 ret = 0; if (vlock_dynamic_adjust && - (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) && - (IS_MANUAL_MODE(vlock_mode))) { + (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) && + (IS_MANUAL_MODE(vlock_mode))) { if (IS_MANUAL_ENC_MODE(vlock_mode)) vlock_enable_step3_enc(); else if (IS_MANUAL_PLL_MODE(vlock_mode)) @@ -1615,6 +1784,9 @@ u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, vlock_enable_step3_soft_enc(); } + if (IS_ENC_MODE(vlock_mode)) + vlock_enc_timing_monitor(); + /*check phase*/ vlock_phaselock_check(pvlock, vf); return ret; @@ -1848,10 +2020,14 @@ void vlock_status(void) pr_info("vlock_intput_type:%d\n", vlock_intput_type); pr_info("vlock_pll_adj_limit:%d\n", vlock_pll_adj_limit); pr_info("vlock_pll_val_last:%d\n", vlock_pll_val_last); + pr_info("vlk_fsm_sts:%d(2 is working)\n", vlock.fsm_sts); pr_info("vlk_support:%d\n", vlock.dtdata->vlk_support); pr_info("vlk_new_fsm:%d\n", vlock.dtdata->vlk_new_fsm); pr_info("vlk_phlock_en:%d\n", vlock.dtdata->vlk_phlock_en); pr_info("vlk_hwver:%d\n", vlock.dtdata->vlk_hwver); + pr_info("phlock flag:%d\n", vlock_get_phlock_flag()); + pr_info("vlock flag:%d\n", vlock_get_vlock_flag()); + pr_info("phase:%d\n", vlock.phlock_percent); vinfo = get_current_vinfo(); pr_info("vinfo sync_duration_num:%d\n", vinfo->sync_duration_num); pr_info("vinfo sync_duration_den:%d\n", vinfo->sync_duration_den); @@ -1871,16 +2047,18 @@ void vlock_reg_dump(void) READ_VPP_REG(addr)); if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { - for (addr = (0x3021); addr <= (0x302a); addr++) + for (addr = (0x3021); addr <= (0x302b); addr++) pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", (0xd0100000+(addr<<2)), addr, READ_VPP_REG(addr)); amvecm_hiu_reg_read(HHI_HDMI_PLL_VLOCK_CNTL, &val); pr_info("HIU [0x%04x]=0x%08x\n", HHI_HDMI_PLL_VLOCK_CNTL, val); } - amvecm_hiu_reg_read(hhi_pll_reg_m, &val); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &val);*/ + val = vlock_get_panel_pll_m(); pr_info("HIU pll m[0x%04x]=0x%08x\n", hhi_pll_reg_m, val); - amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &val);*/ + val = vlock_get_panel_pll_frac(); pr_info("HIU pll f[0x%04x]=0x%08x\n", hhi_pll_reg_frac, val); /*back up orignal pll value*/ diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index 01a3eafc43ff..4ba169fae64f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -82,7 +82,7 @@ extern void vlock_reg_dump(void); extern void vlock_log_start(void); extern void vlock_log_stop(void); extern void vlock_log_print(void); - +extern int phase_lock_check(void); #define VLOCK_STATE_NULL 0 #define VLOCK_STATE_ENABLE_STEP1_DONE 1 @@ -92,12 +92,14 @@ extern void vlock_log_print(void); #define VLOCK_STATE_ENABLE_FORCE_RESET 5 /* video lock */ -#define VLOCK_MODE_AUTO_ENC (1 << 0) -#define VLOCK_MODE_AUTO_PLL (1 << 1) -#define VLOCK_MODE_MANUAL_PLL (1 << 2) -#define VLOCK_MODE_MANUAL_ENC (1 << 3) -#define VLOCK_MODE_MANUAL_SOFT_ENC (1 << 4) -#define VLOCK_MODE_MANUAL_MIX_PLL_ENC (1 << 5) +enum VLOCK_MD { + VLOCK_MODE_AUTO_ENC = 0x01, + VLOCK_MODE_AUTO_PLL = 0x02, + VLOCK_MODE_MANUAL_PLL = 0x04, + VLOCK_MODE_MANUAL_ENC = 0x08, + VLOCK_MODE_MANUAL_SOFT_ENC = 0x10, + VLOCK_MODE_MANUAL_MIX_PLL_ENC = 0x20, +}; #define IS_MANUAL_MODE(md) (md & \ (VLOCK_MODE_MANUAL_PLL | \ @@ -112,6 +114,11 @@ extern void vlock_log_print(void); (VLOCK_MODE_MANUAL_PLL | \ VLOCK_MODE_AUTO_PLL)) +#define IS_ENC_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_ENC | \ + VLOCK_MODE_MANUAL_SOFT_ENC | \ + VLOCK_MODE_AUTO_ENC)) + #define IS_AUTO_PLL_MODE(md) (md & \ VLOCK_MODE_AUTO_PLL) From f6c0e8bc88c9b616fc4356ff363a23cb27bce871 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 25 Mar 2019 21:01:15 +0800 Subject: [PATCH 0478/1060] vlock: pretect display pll set in vlock [1/1] PD#TV-3683 Problem: 1.pretect display pll set in vlock, m and frac value write at the sametime. Solution: 1.optmis vlock flow 2.add notify_callback when mode change Verify: tl1 Change-Id: I72fab117c5b7247659c5c08eeff62fbc4d421839 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/enhancement/amvecm/vlock.c drivers/amlogic/media/enhancement/amvecm/vlock.h --- .../amlogic/media/enhancement/amvecm/amvecm.c | 8 +- .../amlogic/media/enhancement/amvecm/vlock.c | 227 +++++++++++++----- .../amlogic/media/enhancement/amvecm/vlock.h | 19 +- 3 files changed, 183 insertions(+), 71 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 77373273d938..e92a2320bfcc 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* #include */ #include /* for parse_para_pq */ #include @@ -6555,10 +6557,6 @@ static const struct of_device_id aml_vecm_dt_match[] = { .compatible = "amlogic, vecm-tl1", .data = &vecm_dt_tl1, }, - { - .compatible = "amlogic, vecm-tm2", - .data = &vecm_dt_tm2, - }, {}, }; @@ -6567,6 +6565,8 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) struct device_node *node; unsigned int val; int ret; + const struct of_device_id *of_id; + struct vecm_match_data_s *matchdata; node = pdev->dev.of_node; /* get integer value */ diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 77e83be83a1e..ad8934aed7cf 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -81,7 +81,7 @@ static unsigned int pre_input_freq; static unsigned int pre_output_freq; static unsigned int vlock_dis_cnt; static bool vlock_vmode_changed; -static unsigned int vlock_vmode_change_status; +static unsigned int vlock_notify_event; static unsigned int pre_hiu_reg_m; static unsigned int pre_hiu_reg_frac; static signed int pre_enc_max_line; @@ -178,11 +178,6 @@ u32 vlock_get_panel_pll_m(void) return val; } -void vlock_set_panel_pll_m(u32 val) -{ - amvecm_hiu_reg_write(hhi_pll_reg_m, val); -} - u32 vlock_get_panel_pll_frac(void) { u32 val; @@ -191,11 +186,27 @@ u32 vlock_get_panel_pll_frac(void) return val; } -void vlock_set_panel_pll_frac(u32 val) +void vlock_set_panel_pll_m(u32 val) { - amvecm_hiu_reg_write(hhi_pll_reg_frac, val); + u32 m = val & 0xff; + + /*amvecm_hiu_reg_write(hhi_pll_reg_m, m);*/ + lcd_vlock_m_update(m); } +void vlock_set_panel_pll_frac(u32 val) +{ + u32 frac = val & 0x1ffff; + + /*amvecm_hiu_reg_write(hhi_pll_reg_frac, frac);*/ + lcd_vlock_farc_update(frac); +} + +void vlock_set_panel_pll(u32 m, u32 frac) +{ + vlock_set_panel_pll_m(m); + vlock_set_panel_pll_frac(frac); +} /*returen 1: use phase lock*/ int phase_lock_check(void) @@ -514,7 +525,7 @@ void vlock_vmode_check(void) hiu_reg_addr = HHI_HDMI_PLL_CNTL2; vinfo = get_current_vinfo(); vlock_vmode_changed = 0; - if ((vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE) || + if ((vlock_notify_event == VOUT_EVENT_MODE_CHANGE) || (pre_hiu_reg_m == 0)) { if (vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL)) { @@ -576,14 +587,13 @@ void vlock_vmode_check(void) vinfo->vtotal + 1; vlock_capture_limit <<= 12; } - vlock_vmode_change_status = 0; + vlock_notify_event = 0; vlock_vmode_changed = 1; } } static void vlock_disable_step1(void) { unsigned int m_reg_value, tmp_value, enc_max_line, enc_max_pixel; - unsigned int hiu_reg_addr; /* VLOCK_CNTL_EN disable */ vlock_enable(0); @@ -613,46 +623,32 @@ static void vlock_disable_step1(void) pr_info("restore m value=0x%x\n", tmp_value); } #endif - - #if 1 /*restore the orginal pll setting*/ - /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ tmp_value = vlock_get_panel_pll_m(); m_reg_value = tmp_value & 0xff; if (m_reg_value != (vlock.val_m & 0xff)) vlock_set_panel_pll_m(vlock.val_m); - /*amvecm_hiu_reg_write(hhi_pll_reg_m,*/ - /* vlock.val_m);*/ - - /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ tmp_value = vlock_get_panel_pll_frac(); m_reg_value = tmp_value & 0x1ffff; if (m_reg_value != (vlock.val_frac & 0xfff)) vlock_set_panel_pll_frac(vlock.val_frac); /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ /* vlock.val_frac);*/ - pr_info("restore orignal m,f value\n"); - #endif + pr_info("restore orignal m,f value\n"); } else { - /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ tmp_value = vlock_get_panel_pll_frac(); m_reg_value = tmp_value & 0xfff; if (m_reg_value != pre_hiu_reg_frac) { tmp_value = (tmp_value & 0xfffff000) | (pre_hiu_reg_frac & 0xfff); - /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ - /* tmp_value);*/ vlock_set_panel_pll_frac(tmp_value); } - /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ tmp_value = vlock_get_panel_pll_m(); m_reg_value = tmp_value & 0x1ff; if ((m_reg_value != pre_hiu_reg_m) && (pre_hiu_reg_m != 0)) { tmp_value = (tmp_value & 0xfffffe00) | (pre_hiu_reg_m & 0x1ff); - /*amvecm_hiu_reg_write(hhi_pll_reg_m, */ - /*tmp_value);*/ vlock_set_panel_pll_m(tmp_value); } } @@ -687,6 +683,8 @@ static void vlock_disable_step1(void) } vlock_pll_stable_cnt = 0; vlock_enc_stable_flag = 0; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } static bool vlock_disable_step2(void) @@ -707,13 +705,13 @@ static bool vlock_disable_step2(void) /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); - /* CFG_VID_LOCK_ADJ_EN disable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, - 0, 13, 1); /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); /* disable vid_lock_en */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); + /* CFG_VID_LOCK_ADJ_EN disable */ + WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, + 0, 13, 1); vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; if (is_meson_gxtvbb_cpu()) { amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); @@ -1034,14 +1032,13 @@ static void vlock_pll_adj_limit_check(unsigned int *pll_val) } static void vlock_enable_step3_pll(void) { - unsigned int m_reg_value, tmp_value, abs_val, hiu_reg_addr; + unsigned int m_reg_value, tmp_value, abs_val; unsigned int ia, oa, abs_cnt; unsigned int pre_m, new_m, tar_m, org_m; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + u32 m_f_reg_value; + static u32 m_diff_cnt, f_diff_cnt; + u32 mchang = 0; + /*static u32 aaa;*/ /*vs_i*/ tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); @@ -1066,7 +1063,7 @@ static void vlock_enable_step3_pll(void) __func__, vlock_log_delta_vcnt, abs_val, vlock_log_last_ivcnt, vlock_log_last_ovcnt); - m_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC); + m_f_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC); if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) { #if 0 vlock_log[vlock_log_cnt]->pll_frac = @@ -1078,14 +1075,13 @@ static void vlock_enable_step3_pll(void) tmp_value = vlock_get_panel_pll_frac(); vlock_log[vlock_log_cnt]->pll_frac = tmp_value; - /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ tmp_value = vlock_get_panel_pll_m(); vlock_log[vlock_log_cnt]->pll_m = tmp_value; #endif vlock_reg_get(); vlock_log_cnt++; } - if (m_reg_value == 0) { + if (m_f_reg_value == 0) { vlock_state = VLOCK_STATE_ENABLE_FORCE_RESET; if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("%s:vlock pll work abnormal! force reset vlock\n", @@ -1093,7 +1089,8 @@ static void vlock_enable_step3_pll(void) return; } /*check adjust delta limit*/ - vlock_pll_adj_limit_check(&m_reg_value); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) + vlock_pll_adj_limit_check(&m_f_reg_value); /*vlsi suggest config:don't enable load signal, *on gxtvbb this load signal will effect SSG, @@ -1122,8 +1119,70 @@ static void vlock_enable_step3_pll(void) pr_info("%s:vlock input cnt abnormal!!\n", __func__); return; } + + /*m*/ + tmp_value = vlock_get_panel_pll_m(); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { + abs_val = abs(((m_f_reg_value >> 16) & 0xff) - + (pre_hiu_reg_m & 0xff)); + if ((abs_val > vlock_log_delta_m) && + (vlock_log_delta_en&(1<<4))) + pr_info("vlock m delta:%d(0x%x,0x%x)\n", + abs_val, ((m_f_reg_value >> 16) & 0x1ff), + (tmp_value & 0x1ff)); + if ((abs_val <= vlock_pll_m_limit) && + (((m_f_reg_value >> 16) & 0x1ff) != + (tmp_value & 0x1ff)) && + (abs_cnt > vlock_delta_cnt_limit)) { + tmp_value = (tmp_value & 0xfffffe00) | + ((m_f_reg_value >> 16) & 0x1ff); + vlock_set_panel_pll_m(tmp_value); + vlock_pll_val_last &= 0x0000ffff; + vlock_pll_val_last |= (m_f_reg_value & 0xffff0000); + } + } else { + pre_m = (tmp_value & 0xff); + new_m = ((m_f_reg_value >> 16) & 0x1ff); + org_m = (vlock.val_m & 0xff); + if ((pre_m != new_m) && (m_diff_cnt++ > VLOCK_UPDATE_M_CNT)) { + m_diff_cnt = 0; + if (new_m > pre_m) { + tar_m = ((pre_m + 1) < + (org_m + 1))?(pre_m + 1):(org_m + 1); + } else { + /*tar_m < pre_m*/ + tar_m = ((pre_m - 1) < + (org_m - 1))?(org_m - 1):(pre_m - 1); + } + m_reg_value = (tmp_value & 0xffffff00) + tar_m; + if (tar_m != (tmp_value & 0xffffff00)) { + vlock_set_panel_pll_m(m_reg_value); + mchang = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock m: pre=0x%x, rp=0x%x, wr=0x%x\n", + pre_m, new_m, m_reg_value); + } + #if 0 + /*for test*/ + pr_info("vlock m: 0x%x (%d)\n", vlock.val_m, aaa); + if (aaa == 0) { + aaa = 1; + vlock_set_panel_pll_m(vlock.val_m + 1); + } else if (aaa == 1) { + aaa = 2; + vlock_set_panel_pll_m(vlock.val_m); + } else if (aaa == 2) { + aaa = 3; + vlock_set_panel_pll_m(vlock.val_m - 1); + } else if (aaa == 3) { + aaa = 0; + vlock_set_panel_pll_m(vlock.val_m); + } + #endif + } + } + /*frac*/ - /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ tmp_value = vlock_get_panel_pll_frac(); if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { abs_val = abs(((m_f_reg_value & 0xfff) >> 2) - @@ -1136,7 +1195,7 @@ static void vlock_enable_step3_pll(void) if ((abs_val >= vlock_delta_limit) && (abs_cnt > vlock_delta_cnt_limit)) { tmp_value = (tmp_value & 0xfffff000) | - ((m_reg_value & 0xfff) >> 2); + ((m_f_reg_value & 0xfff) >> 2); /*amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);*/ vlock_set_panel_pll_frac(tmp_value); vlock_pll_val_last &= 0xffff0000; @@ -1203,6 +1262,7 @@ void amve_vlock_process(struct vframe_s *vf) vlock_dis_cnt_no_vf = 0; if (vecm_latch_flag & FLAG_VLOCK_EN) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; vlock_en = 1; vecm_latch_flag &= ~FLAG_VLOCK_EN; } @@ -1227,7 +1287,7 @@ void amve_vlock_process(struct vframe_s *vf) __func__); return; } - if (vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE_PRE) { + if (vlock_notify_event == VOUT_EVENT_MODE_CHANGE_PRE) { vlock_enable(0); if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("[%s]auto disable vlock module for vmode change pre case!!!\n", @@ -1240,8 +1300,10 @@ void amve_vlock_process(struct vframe_s *vf) (input_hz != pre_input_freq) || (output_hz != pre_output_freq) || vlock_vmode_changed || - (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) + (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + } if ((vlock_sync_limit_flag < 10) && (vlock_state >= VLOCK_STATE_ENABLE_STEP1_DONE)) { vlock_sync_limit_flag++; @@ -1252,12 +1314,16 @@ void amve_vlock_process(struct vframe_s *vf) WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-0\n"); } if ((vlock_sync_limit_flag == 4) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-1\n"); } } if ((vlock_sync_limit_flag == 5) && @@ -1266,16 +1332,19 @@ void amve_vlock_process(struct vframe_s *vf) /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ /* 0, 28);*/ input_vs_cnt = XTAL_VLOCK_CLOCK/input_hz; - if (vf->type_original & VIDTYPE_TYPEMASK) + /*tl1 not need */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && + vf->type_original & VIDTYPE_TYPEMASK) input_vs_cnt = input_vs_cnt << 1; WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, input_vs_cnt*125/100); WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, input_vs_cnt*70/100); /*cal accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ /*cal accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + vlock_reset(0); vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE; /* @@ -1375,6 +1444,10 @@ void vlock_clear_frame_counter(void) vlock.frame_cnt_in = 0; vlock.frame_cnt_no = 0; vlock_log_cnt = 0; + vlock.phlock_sts = false; + vlock.frqlock_sts = false; + vlock.pll_mode_pause = false; + /*vlock.frqlock_stable_cnt = 0;*/ } void vlock_set_en(bool en) @@ -1391,13 +1464,13 @@ void vlock_status_init(void) vlock_mode = VLOCK_MODE_MANUAL_PLL; if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_tl1_cpu()) + || is_meson_tl1_cpu() || is_meson_tm2_cpu()) vlock_en = 1; else vlock_en = 0; /*initial pll register address*/ - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { hhi_pll_reg_m = HHI_TCON_PLL_CNTL0; hhi_pll_reg_frac = HHI_TCON_PLL_CNTL1; /*hhi_pll_reg_vlock_ctl = HHI_HDMI_PLL_VLOCK_CNTL;*/ @@ -1456,7 +1529,13 @@ void vlock_status_init(void) vlock.vf_sts = false; vlock.vmd_chg = false; vlock.md_support = false; - vlock.phlock_percent = 40; + vlock.fsm_pause = false; + vlock.ss_sts = true; + vlock.phlock_sts = false; + vlock.frqlock_sts = false; + vlock.pll_mode_pause = false; + vlock.phlock_en = vlock.dtdata->vlk_phlock_en; + /* vlock.phlock_percent = phlock_percent; */ vlock_clear_frame_counter(); @@ -1479,7 +1558,7 @@ void vlock_set_phase(u32 percent) /*u32 vs_o_val = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST);*/ u32 data = 0; - if (!vlock.dtdata->vlk_phlock_en) + if (!vlock.phlock_en) return; if (percent > 100) { @@ -1490,22 +1569,15 @@ void vlock_set_phase(u32 percent) vlock.phlock_percent = percent; data = (vs_i_val * (100 + vlock.phlock_percent))/200; WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, data); - pr_info("LOOP1_PHSDIF_TGT:0x%x\n", data); - /*reset*/ - data = READ_VPP_REG(VPU_VLOCK_CTRL); - data |= 1 << 2; - data |= 1 << 5; - WRITE_VPP_REG(VPU_VLOCK_CTRL, data); - data &= ~(1 << 2); - data &= ~(1 << 5); - WRITE_VPP_REG(VPU_VLOCK_CTRL, data); + vlock_reset(1); + vlock_reset(0); } void vlock_set_phase_en(u32 en) { if (en) - vlock.dtdata->vlk_phlock_en = true; + vlock.phlock_en = true; else vlock.dtdata->vlk_phlock_en = false; pr_info("vlock phlock_en=%d\n", en); @@ -1618,7 +1690,7 @@ u32 vlock_fsm_check_support(struct stvlock_sig_sts *pvlock, ret = false; } - if (vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE_PRE) { + if (vlock_notify_event == VOUT_EVENT_MODE_CHANGE_PRE) { if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("[%s] for vmode change pre case!!!\n", __func__); @@ -1654,7 +1726,7 @@ u32 vlock_fsm_input_check(struct stvlock_sig_sts *vlock, struct vframe_s *vf) if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("vlock vfsts chg %d\n", vframe_sts); ret = 1; - } else if (vlock_vmode_change_status) { + } else if (vlock_notify_event) { /*check video mode status*/ vlock->vmd_chg = true; ret = 1; @@ -1797,12 +1869,15 @@ void vlock_fsm_monitor(struct vframe_s *vf) { u32 changed; + if (vlock.fsm_pause) + return; + changed = vlock_fsm_input_check(&vlock, vf); switch (vlock.fsm_sts) { case VLOCK_STATE_NULL: if (vlock.vf_sts) { /*have frame in*/ - if (vlock.frame_cnt_in++ >= 20) { + if (vlock.frame_cnt_in++ >= 100) { /*vframe input valid*/ if (vlock.md_support) { if (vlock_fsm_to_en_func(&vlock, vf)) { @@ -2163,6 +2238,7 @@ int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, void *para) { const struct vinfo_s *vinfo; + u32 cnt = 0; vinfo = get_current_vinfo(); if (!vinfo) { @@ -2172,11 +2248,32 @@ int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("current vmode=%s, vinfo w=%d,h=%d, cmd: 0x%lx\n", vinfo->name, vinfo->width, vinfo->height, cmd); + switch (cmd) { case VOUT_EVENT_MODE_CHANGE_PRE: - case VOUT_EVENT_MODE_CHANGE: - vlock_vmode_change_status = cmd; + vlock.fsm_pause = true; + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock_notify_event = cmd; + if (vlock.dtdata->vlk_new_fsm && + (vlock.fsm_sts >= VLOCK_STATE_ENABLE_STEP1_DONE) && + (vlock.fsm_sts <= VLOCK_STATE_DISABLE_STEP1_DONE)) { + /*stop vlock*/ + vlock_disable_step1(); + while (!vlock_disable_step2()) { + if (cnt++ > 10) + break; + } + } + pr_info("vlock: event MODE_CHANGE_PRE %d\n", cnt); break; + + case VOUT_EVENT_MODE_CHANGE: + vlock.fsm_pause = false; + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock_notify_event = cmd; + pr_info("vlock: event MODE_CHANGE\n"); + break; + default: break; } diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index 4ba169fae64f..c6540d7680b1 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2019/1/24" +#define VLOCK_VER "Ref.2019/3/26a" #define VLOCK_REG_NUM 33 @@ -62,6 +62,7 @@ enum vlock_param_e { struct stvlock_sig_sts { u32 fsm_sts; u32 fsm_prests; + u32 fsm_pause; u32 vf_sts; u32 vmd_chg; u32 frame_cnt_in; @@ -70,6 +71,12 @@ struct stvlock_sig_sts { u32 output_hz; bool md_support; u32 phlock_percent; + u32 phlock_sts; + u32 phlock_en; + u32 frqlock_sts; + /*u32 frqlock_stable_cnt;*/ + u32 ss_sts; + u32 pll_mode_pause; struct vecm_match_data_s *dtdata; u32 val_frac; u32 val_m; @@ -131,6 +138,11 @@ enum VLOCK_MD { #define IS_MANUAL_SOFTENC_MODE(md) (md & \ VLOCK_MODE_MANUAL_SOFT_ENC) +#define VLOCK_START_CNT 50 +#define VLOCK_WORK_CNT (VLOCK_START_CNT + 10) + +#define VLOCK_UPDATE_M_CNT 8 +#define VLOCK_UPDATE_F_CNT 4 #define XTAL_VLOCK_CLOCK 24000000/*vlock use xtal clock*/ @@ -155,7 +167,7 @@ enum VLOCK_MD { extern unsigned int vlock_mode; extern unsigned int vlock_en; extern unsigned int vecm_latch_flag; -extern void __iomem *amvecm_hiu_reg_base; +/*extern void __iomem *amvecm_hiu_reg_base;*/ extern unsigned int probe_ok; extern void lcd_ss_enable(bool flag); @@ -178,4 +190,7 @@ extern void vlock_set_en(bool en); extern void vlock_set_phase(u32 percent); extern void vlock_set_phase_en(u32 en); +extern void lcd_vlock_m_update(unsigned int vlock_m); +extern void lcd_vlock_farc_update(unsigned int vlock_farc); +extern int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode); From 80bbcb532b4118a0c9e02269d8babab6081f1cfe Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Fri, 29 Mar 2019 17:08:09 +0800 Subject: [PATCH 0479/1060] vlock: vlock: improve vlock flow [1/1] PD#TV-3683 Problem: 1. write pll m will cause vbyone lockn unlock. Solution: 1.not change m,f at the sametime 2.reduce the frequency of write m and f Verify: tl1 Change-Id: Ia1ff93122d8b2ae355eae73b0094f8e09edba1cd Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/enhancement/amvecm/vlock.c drivers/amlogic/media/enhancement/amvecm/vlock.h --- drivers/amlogic/media/enhancement/amvecm/vlock.c | 12 ++++++++++-- drivers/amlogic/media/enhancement/amvecm/vlock.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index ad8934aed7cf..557b52cfef45 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -697,9 +697,12 @@ static bool vlock_disable_step2(void) vlock_dis_cnt--; else if (vlock_dis_cnt == 0) { if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + #if 0 amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x4, 0, 3); - amvecm_hiu_reg_write_bits( + #endif + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x0, 0, 3); } @@ -1355,9 +1358,11 @@ void amve_vlock_process(struct vframe_s *vf) if (IS_AUTO_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + #if 0 else if (IS_MANUAL_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + #endif } if (vlock_debug & VLOCK_DEBUG_INFO) @@ -1827,9 +1832,11 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, if (IS_AUTO_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + #if 0 else if (IS_MANUAL_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + #endif } ret = 1; @@ -1877,7 +1884,7 @@ void vlock_fsm_monitor(struct vframe_s *vf) case VLOCK_STATE_NULL: if (vlock.vf_sts) { /*have frame in*/ - if (vlock.frame_cnt_in++ >= 100) { + if (vlock.frame_cnt_in++ >= VLOCK_START_CNT) { /*vframe input valid*/ if (vlock.md_support) { if (vlock_fsm_to_en_func(&vlock, vf)) { @@ -1921,6 +1928,7 @@ void vlock_fsm_monitor(struct vframe_s *vf) case VLOCK_STATE_ENABLE_STEP2_DONE: if (vlock.vf_sts) { + vlock.frame_cnt_in++; if (!vlock.md_support) { /*function not support*/ vlock_clear_frame_counter(); diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index c6540d7680b1..dde7f7fe128c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2019/3/26a" +#define VLOCK_VER "Ref.2019/3/29a" #define VLOCK_REG_NUM 33 From f202264f60a27a7a6f097ee8cba3d6d73b9a81fb Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 3 Apr 2019 19:36:42 +0800 Subject: [PATCH 0480/1060] vlock: phase lock sometime lose effect [1/1] PD#SWPL-6723 Problem: phase lock sometime effect vlock Solution: disable phase lock function now Verify: tl1 Change-Id: I4cfe1e0153084717967309e832b028691ab44c88 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/enhancement/amvecm/vlock.c --- .../amlogic/media/enhancement/amvecm/amvecm.c | 2 +- .../enhancement/amvecm/amvecm_vlock_regmap.h | 9 +- .../amlogic/media/enhancement/amvecm/vlock.c | 127 +++++++++++++----- .../amlogic/media/enhancement/amvecm/vlock.h | 2 +- 4 files changed, 97 insertions(+), 43 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index e92a2320bfcc..430ea828330e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -6545,7 +6545,7 @@ static const struct vecm_match_data_s vecm_dt_tl1 = { .vlk_support = true, .vlk_new_fsm = 1, .vlk_hwver = vlock_hw_ver2, - .vlk_phlock_en = true, + .vlk_phlock_en = false, }; static const struct of_device_id aml_vecm_dt_match[] = { diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index 292827d3c464..862b4faad881 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -27,27 +27,28 @@ struct vlock_regs_s { #define VLOCK_DEFAULT_REG_SIZE 20 static struct vlock_regs_s vlock_enc_setting[VLOCK_DEFAULT_REG_SIZE] = { /* optimize */ - {0x3000, 0xE3f50f10 }, + {0x3000, 0xE3f53f10 }, {0x3001, 0x41E3c3c }, - {0x3002, 0x6000000 }, + {0x3002, 0x8000/*0x6000000*/ }, {0x3003, 0x20709709/*0x20680680 */}, {0x3004, 0x00709709/*0x280280 */}, {0x3005, 0x8020000 }, {0x3006, 0x0008000 }, {0x3007, 0x0000000 }, {0x3008, 0x0000000 }, - {0x3009, 0x6000000/*0x0008000 */}, + {0x3009, 0x8000/*x60000000 x0008000 */}, {0x300a, 0x8000000 }, {0x300b, 0x000a000 }, {0x300c, 0xa000000 }, {0x300d, 0x0004000 }, - {0x3010, 0x20001000 }, + {0x3010, 0x8ca/*0x20001000*/ }, {0x3016, 0x18000 }, {0x3017, 0x01080 }, {0x301d, 0x30501080 }, {0x301e, 0x7 }, {0x301f, 0x6000000 }, }; + static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { /* optimize */ {0x3000, 0x07f13f1a }, diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 557b52cfef45..f9405f1b6c07 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -36,9 +36,9 @@ /* video lock */ /* 0:off; - * 1:auto enc; + * 1:auto enc; VLOCK_MODE_AUTO_ENC * 2:auto pll; - * 4:manual pll; + * 4:manual pll; VLOCK_MODE_MANUAL_PLL * 8:manual_enc mode(only support lvds/vx1) */ enum VLOCK_MD vlock_mode = VLOCK_MODE_MANUAL_PLL; @@ -149,13 +149,17 @@ static unsigned int last_i_vsync; int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val) { - *val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2)); + /**val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2));*/ + *val = aml_read_hiubus(reg); + /*pr_info("vlock rd hiu reg:0x%x,0x%x\n", (reg - 0x1000), *val);*/ return 0; } int amvecm_hiu_reg_write(unsigned int reg, unsigned int val) { - writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2))); + /*writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2)));*/ + /*pr_info("vlock rd hiu reg:0x%x,0x%x\n", (reg - 0x1000), val);*/ + aml_write_hiubus(reg, val); return 0; } static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, @@ -188,7 +192,7 @@ u32 vlock_get_panel_pll_frac(void) void vlock_set_panel_pll_m(u32 val) { - u32 m = val & 0xff; + u32 m = val; /*amvecm_hiu_reg_write(hhi_pll_reg_m, m);*/ lcd_vlock_m_update(m); @@ -196,7 +200,7 @@ void vlock_set_panel_pll_m(u32 val) void vlock_set_panel_pll_frac(u32 val) { - u32 frac = val & 0x1ffff; + u32 frac = val; /*amvecm_hiu_reg_write(hhi_pll_reg_frac, frac);*/ lcd_vlock_farc_update(frac); @@ -279,6 +283,23 @@ static unsigned int vlock_check_output_hz(unsigned int sync_duration_num, return ret_hz; } + +void vlock_reset(u32 onoff) +{ + if (onoff) { + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + } else { + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + } + /*pr_info("%s (%d)\n", __func__, onoff);*/ +} + /*vlock is support eq_after gxbb,but which is useful only for tv chip *after gxl,the enable/disable reg_bit is changed */ @@ -336,10 +357,15 @@ static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) static void vlock_setting(struct vframe_s *vf, unsigned int input_hz, unsigned int output_hz) { - unsigned int freq_hz = 0, hiu_reg_value_2_addr = HHI_HDMI_PLL_CNTL2; + unsigned int freq_hz = 0; unsigned int reg_value = 0, hiu_reg_value, hiu_reg_value_2; - unsigned int hiu_m_val, hiu_frac_val, temp_value; + unsigned int hiu_m_val = 0, hiu_frac_val = 0, temp_value; + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info(">>>[%s]\n", __func__); + pr_info("inputHz:%d,outputHz:%d\n", input_hz, output_hz); + pr_info("type_original:0x%x\n", vf->type_original); + } amvecm_hiu_reg_write(HHI_VID_LOCK_CLK_CNTL, 0x80); if (IS_ENC_MODE(vlock_mode)) { /*init default config for enc mode*/ @@ -368,10 +394,12 @@ static void vlock_setting(struct vframe_s *vf, } /* enable to adjust enc */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 30, 1); - /*clear accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); - /*clear accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) { + /*clear accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + } /*@20180314 new add*/ /* *set input & output freq @@ -379,8 +407,14 @@ static void vlock_setting(struct vframe_s *vf, *bit8~15:output freq */ if ((vf->type_original & VIDTYPE_TYPEMASK) && - !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) + !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) { + /*tl1 fix i problem*/ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) input_hz = input_hz >> 1; + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 1, 28, 1); + } freq_hz = input_hz | (output_hz << 8); WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); /* @@ -395,9 +429,10 @@ static void vlock_setting(struct vframe_s *vf, temp_value = READ_VPP_REG(enc_max_line_addr); WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value + 1, 0, 14); - temp_value = READ_VPP_REG(enc_max_pixel_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, - temp_value + 1, 16, 14); + /*tune pixel*/ + /*temp_value = READ_VPP_REG(enc_max_pixel_addr);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX,*/ + /* temp_value + 1, 16, 14);*/ WRITE_VPP_REG_BITS(VPU_VLOCK_ADJ_EN_SYNC_CTRL, vlock_latch_en_cnt, 8, 8); WRITE_VPP_REG_BITS(enc_video_mode_addr, 1, 15, 1); @@ -411,8 +446,17 @@ static void vlock_setting(struct vframe_s *vf, *bit0~7:input freq *bit8~15:output freq */ - if (vf->type_original & VIDTYPE_TYPEMASK) - input_hz = input_hz >> 1; + if (vf->type_original & VIDTYPE_TYPEMASK) { + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) + input_hz = input_hz >> 1; + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 1, 28, 1); + } else { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 0, 28, 1); + } freq_hz = input_hz | (output_hz << 8); WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); /* @@ -457,6 +501,12 @@ static void vlock_setting(struct vframe_s *vf, } reg_value = (hiu_m_val << 12) + (hiu_frac_val << 2); + } else { + pr_info("err: m f value\n"); + } + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("hiu_m_val=0x%x\n", hiu_m_val); + pr_info("hiu_frac_val=0x%x\n", hiu_frac_val); } WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, reg_value, 0, 21); /*vlock_pll_adj_limit = (reg_value * 0x8000) >> 24;*/ @@ -466,7 +516,7 @@ static void vlock_setting(struct vframe_s *vf, /*enable vlock to adj pll*/ /* CFG_VID_LOCK_ADJ_EN disable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, 0, 13, 1); + WRITE_VPP_REG_BITS(enc_max_line_switch_addr, 0, 13, 1); /* disable to adjust enc */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); /* VLOCK_CNTL_EN enable */ @@ -476,7 +526,7 @@ static void vlock_setting(struct vframe_s *vf, } /*initial phase lock setting*/ - if (vlock.dtdata->vlk_phlock_en) { + if (vlock.phlock_en) { vlock_hw_reinit(vlock_pll_phase_setting, VLOCK_PHASE_REG_SIZE); /*disable pll lock*/ /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 3, 1);*/ @@ -485,8 +535,8 @@ static void vlock_setting(struct vframe_s *vf, WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 3, 0, 2); /*reset*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ } /* vlock module output goes to which module */ @@ -697,24 +747,21 @@ static bool vlock_disable_step2(void) vlock_dis_cnt--; else if (vlock_dis_cnt == 0) { if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { - #if 0 amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x4, 0, 3); - #endif - if (IS_AUTO_MODE(vlock_mode)) - amvecm_hiu_reg_write_bits( + amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x0, 0, 3); } /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); + /* CFG_VID_LOCK_ADJ_EN disable */ + WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, + 0, 13, 1); /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); /* disable vid_lock_en */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); - /* CFG_VID_LOCK_ADJ_EN disable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, - 0, 13, 1); vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; if (is_meson_gxtvbb_cpu()) { amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); @@ -1078,6 +1125,7 @@ static void vlock_enable_step3_pll(void) tmp_value = vlock_get_panel_pll_frac(); vlock_log[vlock_log_cnt]->pll_frac = tmp_value; + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ tmp_value = vlock_get_panel_pll_m(); vlock_log[vlock_log_cnt]->pll_m = tmp_value; #endif @@ -1239,7 +1287,7 @@ static void vlock_enable_step3_pll(void) vlock_pll_stable_cnt = 0; } else { if (((m_f_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) - vlock_pll_stable_cnt = 0; + vlock_pll_stable_cnt = 0; } } /* won't change this function internal seqence, @@ -1313,8 +1361,10 @@ void amve_vlock_process(struct vframe_s *vf) if ((vlock_sync_limit_flag <= 3) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { + /*reset*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear first 3 frame internal cnt*/ WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); if (vlock_debug & VLOCK_DEBUG_INFO) @@ -1323,12 +1373,14 @@ void amve_vlock_process(struct vframe_s *vf) if ((vlock_sync_limit_flag == 4) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { + /*release reset*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("amve_vlock_process-1\n"); } } + if ((vlock_sync_limit_flag == 5) && (vlock_state == VLOCK_STATE_ENABLE_STEP1_DONE)) { /*input_vs_cnt =*/ @@ -1339,10 +1391,12 @@ void amve_vlock_process(struct vframe_s *vf) if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && vf->type_original & VIDTYPE_TYPEMASK) input_vs_cnt = input_vs_cnt << 1; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, input_vs_cnt*125/100); WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, input_vs_cnt*70/100); + /*cal accum1 value*/ /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ /*cal accum0 value*/ @@ -1358,11 +1412,9 @@ void amve_vlock_process(struct vframe_s *vf) if (IS_AUTO_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); - #if 0 else if (IS_MANUAL_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); - #endif } if (vlock_debug & VLOCK_DEBUG_INFO) @@ -1832,11 +1884,9 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, if (IS_AUTO_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); - #if 0 else if (IS_MANUAL_MODE(vlock_mode)) amvecm_hiu_reg_write_bits( HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); - #endif } ret = 1; @@ -2122,9 +2172,10 @@ void vlock_status(void) void vlock_reg_dump(void) { unsigned int addr; + unsigned int val; pr_info("----dump vlock reg----\n"); - for (addr = (0x3000); addr <= (0x3020); addr++) + for (addr = (VPU_VLOCK_CTRL); addr <= (VPU_VLOCK_RO_M_INT_FRAC); addr++) pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", (0xd0100000+(addr<<2)), addr, READ_VPP_REG(addr)); @@ -2137,6 +2188,8 @@ void vlock_reg_dump(void) amvecm_hiu_reg_read(HHI_HDMI_PLL_VLOCK_CNTL, &val); pr_info("HIU [0x%04x]=0x%08x\n", HHI_HDMI_PLL_VLOCK_CNTL, val); } + pr_info("[0x1cc8]=0x%08x\n", READ_VPP_REG(0x1cc8)); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &val);*/ val = vlock_get_panel_pll_m(); pr_info("HIU pll m[0x%04x]=0x%08x\n", hhi_pll_reg_m, val); @@ -2145,8 +2198,8 @@ void vlock_reg_dump(void) pr_info("HIU pll f[0x%04x]=0x%08x\n", hhi_pll_reg_frac, val); /*back up orignal pll value*/ - pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m); - pr_info("HIU pll f[0x%x]=0x%x\n", hhi_pll_reg_frac, vlock.val_frac); + /*pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m);*/ + /*pr_info("HIU pll f[0x%x]=0x%x\n", hhi_pll_reg_frac, vlock.val_frac);*/ } /*work around method for vlock process hdmirx input interlace source.@20170803 diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index dde7f7fe128c..a1008a3bfca7 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2019/3/29a" +#define VLOCK_VER "Ref.2019/4/02a" #define VLOCK_REG_NUM 33 From 2f1f394941e99c36da6eab731b616abd3d5198cf Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 27 Dec 2018 17:41:44 +0800 Subject: [PATCH 0481/1060] lcd: fix tcon crash with reserved-memory fail and tcon_clk mistake [2/2] PD#SWPL-3664 Problem: tcon will crash in kernel Solution: 1.prior meson-fb & lcd_tcon reserved-memory 2.fix tcon_clk not enable mistake when use panel ini Verify: x301 Change-Id: I97baec22ecabea393f9b0d712456923720fac972 Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 32 +++---- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 16 ++++ .../amlogic/media/vout/lcd/lcd_clk_config.c | 87 ++++++++++++------- .../amlogic/media/vout/lcd/lcd_clk_config.h | 3 + drivers/amlogic/media/vout/lcd/lcd_tcon.c | 5 +- drivers/amlogic/media/vout/lcd/lcd_vout.c | 5 +- 6 files changed, 96 insertions(+), 52 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index ef3f0448d3cd..7bb218fa333c 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -60,6 +60,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -78,22 +94,6 @@ //no-map; }; - logo_reserved:linux,meson-fb { - compatible = "shared-dma-pool"; - reusable; - size = <0x800000>; - alignment = <0x400000>; - alloc-ranges = <0x7f800000 0x800000>; - }; - - lcd_tcon_reserved:linux,lcd_tcon { - compatible = "shared-dma-pool"; - reusable; - size = <0xc00000>; - alignment = <0x400000>; - alloc-ranges = <0x71000000 0xc00000>; - }; - ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index d2e96f42f808..4ba9a32c3c10 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -59,6 +59,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index b5287455a319..c3710a92351d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -63,6 +63,7 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */ static struct lcd_clktree_s lcd_clktree = { .clk_gate_state = 0, + .clk_gate_optional_state = 0, /* by interface */ .encl_top_gate = NULL, .encl_int_gate = NULL, @@ -1779,17 +1780,10 @@ static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *lcd_drv, int status) } } -static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) +static void lcd_clk_gate_optional_switch_tl1(struct aml_lcd_drv_s *lcd_drv, + int status) { if (status) { - if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) - LCDERR("%s: encl_top_gate\n", __func__); - else - clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) - LCDERR("%s: encl_int_gata\n", __func__); - else - clk_prepare_enable(lcd_clktree.encl_int_gate); switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: @@ -1801,6 +1795,7 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) LCDERR("%s: tcon_clk\n", __func__); else clk_prepare_enable(lcd_clktree.tcon_clk); + lcd_clktree.clk_gate_optional_state = 1; break; default: break; @@ -1817,18 +1812,11 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) LCDERR("%s: tcon_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.tcon_gate); + lcd_clktree.clk_gate_optional_state = 0; break; default: break; } - if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) - LCDERR("%s: encl_int_gate\n", __func__); - else - clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) - LCDERR("%s: encl_top_gate\n", __func__); - else - clk_disable_unprepare(lcd_clktree.encl_top_gate); } } @@ -2438,37 +2426,63 @@ void lcd_clk_disable(void) LCDPR("%s\n", __func__); } +static void lcd_clk_gate_optional_switch(int status) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + if (clk_conf.data->clk_gate_optional_switch == NULL) + return; + + if (status) { + if (lcd_clktree.clk_gate_optional_state) + LCDPR("clk_gate_optional is already on\n"); + else + clk_conf.data->clk_gate_optional_switch(lcd_drv, 1); + } else { + if (lcd_clktree.clk_gate_optional_state == 0) + LCDPR("clk_gate_optional is already off\n"); + else + clk_conf.data->clk_gate_optional_switch(lcd_drv, 0); + } +} + void lcd_clk_gate_switch(int status) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + if (status) { if (lcd_clktree.clk_gate_state) { - LCDPR("clk gate is already on\n"); - return; - } + LCDPR("clk_gate is already on\n"); + } else { #ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_ON); + switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_ON); #endif - if (clk_conf.data) { if (clk_conf.data->clk_gate_switch) clk_conf.data->clk_gate_switch(lcd_drv, 1); + lcd_clktree.clk_gate_state = 1; } - lcd_clktree.clk_gate_state = 1; + lcd_clk_gate_optional_switch(1); } else { + lcd_clk_gate_optional_switch(0); if (lcd_clktree.clk_gate_state == 0) { - LCDPR("clk gate is already off\n"); - return; - } - - if (clk_conf.data) { + LCDPR("clk_gate is already off\n"); + } else { if (clk_conf.data->clk_gate_switch) clk_conf.data->clk_gate_switch(lcd_drv, 0); - } #ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_OFF); + switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_OFF); #endif - lcd_clktree.clk_gate_state = 0; + lcd_clktree.clk_gate_state = 0; + } } } @@ -2534,6 +2548,7 @@ static struct lcd_clk_data_s lcd_clk_data_gxl = { .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2569,6 +2584,7 @@ static struct lcd_clk_data_s lcd_clk_data_txl = { .set_spread_spectrum = lcd_set_pll_ss_txl, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2604,6 +2620,7 @@ static struct lcd_clk_data_s lcd_clk_data_txlx = { .set_spread_spectrum = lcd_set_pll_ss_txlx, .clk_set = lcd_clk_set_txlx, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2639,6 +2656,7 @@ static struct lcd_clk_data_s lcd_clk_data_axg = { .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_axg, .clk_gate_switch = lcd_clk_gate_switch_axg, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_axg, .clktree_remove = lcd_clktree_remove_axg, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2674,6 +2692,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path0 = { .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_g12a_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2709,6 +2728,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path1 = { .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_g12a_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2744,6 +2764,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path0 = { .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_g12b_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2779,6 +2800,7 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path1 = { .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_g12b_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2813,7 +2835,8 @@ static struct lcd_clk_data_s lcd_clk_data_tl1 = { .pll_frac_generate = lcd_pll_frac_generate_txl, .set_spread_spectrum = NULL, .clk_set = lcd_clk_set_tl1, - .clk_gate_switch = lcd_clk_gate_switch_tl1, + .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1, .clktree_probe = lcd_clktree_probe_tl1, .clktree_remove = lcd_clktree_remove_tl1, .clk_config_init_print = lcd_clk_config_init_print_dft, diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index a7a14df67726..9044c5994b2f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -70,6 +70,8 @@ struct lcd_clk_data_s { void (*set_spread_spectrum)(unsigned int ss_level); void (*clk_set)(struct lcd_config_s *pconf); void (*clk_gate_switch)(struct aml_lcd_drv_s *lcd_drv, int status); + void (*clk_gate_optional_switch)(struct aml_lcd_drv_s *lcd_drv, + int status); void (*clktree_probe)(void); void (*clktree_remove)(void); void (*clk_config_init_print)(void); @@ -106,6 +108,7 @@ struct lcd_clk_config_s { /* unit: kHz */ struct lcd_clktree_s { unsigned char clk_gate_state; + unsigned char clk_gate_optional_state; struct clk *encl_top_gate; struct clk *encl_int_gate; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index dfd90ca4ed59..67b060b15d8e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -563,10 +563,11 @@ void lcd_tcon_disable(void) /* disable over_drive */ if (lcd_tcon_data->reg_core_od != REG_LCD_TCON_MAX) { reg = lcd_tcon_data->reg_core_od + TCON_CORE_REG_START; + bit = lcd_tcon_data->bit_od_en; if (lcd_tcon_data->core_reg_width == 8) - lcd_tcon_write_byte(reg, 0); + lcd_tcon_setb_byte(reg, 0, bit, 1); else - lcd_tcon_write(reg, 0); + lcd_tcon_setb(reg, 0, bit, 1); msleep(100); } diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index eb8d61847088..32d3d7be22f6 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -993,8 +993,9 @@ static int lcd_mode_probe(struct device *dev) LCDERR("invalid lcd mode: %d\n", lcd_driver->lcd_mode); break; } - if (lcd_driver->data->chip_type == LCD_CHIP_TL1) - lcd_tcon_probe(lcd_driver); + lcd_tcon_probe(lcd_driver); + if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) + lcd_clk_gate_switch(1); lcd_debug_probe(); lcd_fops_create(); From 199e697b7fb8b0d774004373b10d3028b281bea1 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 3 Jan 2019 06:40:26 -0500 Subject: [PATCH 0482/1060] backlight: ldim: add analog pwm support [1/1] PD#SWPL-3702 Problem: local dimming need analog pwm function Solution: add analog pwm support Verify: x301 Change-Id: I502bb7505947c1f3670f44d0d307f9546f1d57fd Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h include/linux/amlogic/media/vout/lcd/aml_ldim.h --- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 165 +++++++++++ .../dts/amlogic/mesontxlx_r311-panel.dtsi | 75 ++--- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 2 + .../dts/amlogic/mesontxlx_r311-panel.dtsi | 70 +++-- drivers/amlogic/media/vout/backlight/aml_bl.c | 19 +- .../media/vout/backlight/aml_ldim/global_bl.c | 28 +- .../media/vout/backlight/aml_ldim/iw7027_bl.c | 12 +- .../vout/backlight/aml_ldim/ldim_dev_drv.c | 256 ++++++++++++------ .../media/vout/backlight/aml_ldim/ldim_drv.h | 4 +- .../media/vout/backlight/aml_ldim/ob3350_bl.c | 28 +- include/linux/amlogic/media/vout/lcd/aml_bl.h | 9 + 11 files changed, 497 insertions(+), 171 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 0832e10d5e7d..706d97e48914 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -653,6 +653,64 @@ 2 0 /*pwm1 gpio_index, gpio_off*/ 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; }; bl_pwm_conf:bl_pwm_conf{ @@ -666,4 +724,111 @@ }; }; + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; }; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi index 73df62601014..3e9c828df85d 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi @@ -678,6 +678,23 @@ }; backlight_4{ index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; bl_name = "ldim_iw7027"; bl_level_default_uboot_kernel = <100 100>; bl_level_attr = <255 10 /*max, min*/ @@ -687,29 +704,12 @@ 1 0 /*on_value, off_value*/ 200 200>; /*on_delay(ms), off_delay(ms)*/ bl_ldim_region_row_col = <1 10>; - bl_ldim_mode = <1>; /*1=single_side - * (top, bottom, left or right), - *2=uniform(top/bottom, left/right) + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct */ ldim_dev_index = <2>; }; - backlight_5{ - index = <5>; - bl_name = "ldim_global"; - bl_level_default_uboot_kernel = <100 100>; - bl_level_attr = <255 10 /*max, min*/ - 128 128>; /*mid, mid_mapping*/ - bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ - bl_power_attr = <0 /*en_gpio_index*/ - 1 0 /*on_value, off_value*/ - 200 200>; /* on_delay(ms), off_delay(ms)*/ - bl_ldim_region_row_col = <1 1>; - bl_ldim_mode = <1>; /*1=single_side - * (top, bottom, left or right), - *2=uniform(top/bottom, left/right) - */ - ldim_dev_index = <1>; - }; }; bl_pwm_conf:bl_pwm_conf{ @@ -728,54 +728,63 @@ status = "okay"; pinctrl-names = "ldim_pwm", "ldim_pwm_vs", - "ldim_pwm_off"; + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; pinctrl-0 = <&bl_pwm_on_pins>; pinctrl-1 = <&bl_pwm_vs_on_pins>; - pinctrl-2 = <&bl_pwm_off_pins>; + pinctrl-2 = <&bl_pwm_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-3 = <&bl_pwm_vs_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; pinctrl_version = <1>; /* for uboot */ ldim_pwm_config = <&bl_pwm_conf>; /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ ldim_dev-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH &gpio GPIOZ_6 GPIO_ACTIVE_HIGH - &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; - ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7"; + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH + &gpio GPIOZ_4 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7","GPIOZ_4"; ldim_dev_0 { index = <0>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "ob3350"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <0 /* pol */ 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ + 50>;/*default duty(%)*/ en_gpio_on_off = <0 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_1 { index = <1>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "global"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <1 /* pol */ 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ - en_gpio_on_off = <2 /*ldim_dev-gpios index*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_C"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <3 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_2 { index = <2>; type = <1>; /* 0=normal,1=spi,2=i2c */ ldim_dev_name = "iw7027"; - ldim_pwm_pinmux_sel = "ldim_pwm_vs"; ldim_pwm_port = "PWM_VS"; ldim_pwm_attr = <1 /* pol */ 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ + 50>;/*default duty(%)*/ spi_bus_num = <0>; spi_chip_select = <0>; spi_max_frequency = <1000000>; /* unit: hz */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 4ba9a32c3c10..fb49ebdc1115 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -39,6 +39,8 @@ i2c2 = &i2c2; i2c3 = &i2c3; i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; }; memory@00000000 { diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi index 99c8c93e14ab..610a57d10ec6 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi @@ -678,6 +678,23 @@ }; backlight_4{ index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; bl_name = "ldim_iw7027"; bl_level_default_uboot_kernel = <100 100>; bl_level_attr = <255 10 /*max, min*/ @@ -693,23 +710,6 @@ */ ldim_dev_index = <2>; }; - backlight_5{ - index = <5>; - bl_name = "ldim_global"; - bl_level_default_uboot_kernel = <100 100>; - bl_level_attr = <255 10 /*max, min*/ - 128 128>; /*mid, mid_mapping*/ - bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ - bl_power_attr = <0 /*en_gpio_index*/ - 1 0 /*on_value, off_value*/ - 200 200>; /* on_delay(ms), off_delay(ms)*/ - bl_ldim_region_row_col = <1 1>; - bl_ldim_mode = <1>; /*0=left/right side - *1=top/bottom side - *2=direct - */ - ldim_dev_index = <1>; - }; }; bl_pwm_conf:bl_pwm_conf{ @@ -728,54 +728,63 @@ status = "okay"; pinctrl-names = "ldim_pwm", "ldim_pwm_vs", - "ldim_pwm_off"; + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; pinctrl-0 = <&bl_pwm_on_pins>; pinctrl-1 = <&bl_pwm_vs_on_pins>; - pinctrl-2 = <&bl_pwm_off_pins>; + pinctrl-2 = <&bl_pwm_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-3 = <&bl_pwm_vs_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; pinctrl_version = <1>; /* for uboot */ ldim_pwm_config = <&bl_pwm_conf>; /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ ldim_dev-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH &gpio GPIOZ_6 GPIO_ACTIVE_HIGH - &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; - ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7"; + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH + &gpio GPIOZ_4 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7","GPIOZ_4"; ldim_dev_0 { index = <0>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "ob3350"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <0 /* pol */ 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ + 50>;/*default duty(%)*/ en_gpio_on_off = <0 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_1 { index = <1>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "global"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <1 /* pol */ 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ - en_gpio_on_off = <2 /*ldim_dev-gpios index*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_C"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <3 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_2 { index = <2>; type = <1>; /* 0=normal,1=spi,2=i2c */ ldim_dev_name = "iw7027"; - ldim_pwm_pinmux_sel = "ldim_pwm_vs"; ldim_pwm_port = "PWM_VS"; ldim_pwm_attr = <1 /* pol */ 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ + 50>;/*default duty(%)*/ spi_bus_num = <0>; spi_chip_select = <0>; spi_max_frequency = <1000000>; /* unit: hz */ @@ -818,6 +827,7 @@ 0xc0 2 0x34 0xc8 0xc0 2 0x35 0xbf 0xff 0>; + init_off = <0xff 0>; }; }; diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index b649434b74f5..e6859f81c63e 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -330,15 +330,6 @@ static void bl_gpio_set(int index, int value) } } -static inline unsigned int bl_do_div(unsigned long long num, unsigned int den) -{ - unsigned long long ret = num; - - do_div(ret, den); - - return (unsigned int)ret; -} - /* ****************************************************** */ #define BL_PINMUX_MAX 8 static char *bl_pinmux_str[BL_PINMUX_MAX] = { @@ -2865,11 +2856,11 @@ static ssize_t bl_debug_pwm_show(struct class *class, return len; } -#define BL_DEBUG_PWM_FREQ 0 -#define BL_DEBUG_PWM_DUTY 1 -#define BL_DEBUG_PWM_POL 2 -#define BL_DEBUG_PWM_DUTY_MAX 3 -#define BL_DEBUG_PWM_DUTY_MIN 4 +#define BL_DEBUG_PWM_FREQ 0 +#define BL_DEBUG_PWM_DUTY 1 +#define BL_DEBUG_PWM_POL 2 +#define BL_DEBUG_PWM_DUTY_MAX 3 +#define BL_DEBUG_PWM_DUTY_MIN 4 static void bl_debug_pwm_set(unsigned int index, unsigned int value, int state) { struct bl_config_s *bconf = bl_drv->bconf; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c index d2dcd99745b5..1a1856c3017c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c @@ -44,7 +44,8 @@ static int global_hw_init_on(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); mdelay(2); ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, @@ -61,7 +62,8 @@ static int global_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -88,12 +90,22 @@ static int global_smr(unsigned short *buf, unsigned char len) level = buf[0]; val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - ldim_drv->ldev_conf->pwm_config.pwm_duty = val; - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val; + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); return 0; } +static void global_dim_range_update(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct ldim_dev_config_s *ldim_dev; + + ldim_dev = ldim_drv->ldev_conf; + ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max; + ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min; +} + static int global_power_on(void) { if (global_on_flag) { @@ -137,7 +149,7 @@ static ssize_t global_show(struct class *class, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->dim_max, ldim_drv->ldev_conf->dim_min, - ldim_drv->ldev_conf->pwm_config.pwm_duty); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty); } return ret; @@ -150,6 +162,12 @@ static struct class_attribute global_class_attrs[] = { static int global_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) { + struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf; + + ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max; + ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min; + ldim_dev->dim_range_update = global_dim_range_update; + ldim_drv->device_power_on = global_power_on; ldim_drv->device_power_off = global_power_off; ldim_drv->device_bri_update = global_smr; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index 205d99dbdbd6..c1536128e3c0 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -304,7 +304,8 @@ static int iw7027_hw_init_on(void) iw7027_power_on_init(); /* step 5: supply stable vsync */ - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); /* step 6: delay for system clock and light bar PSU stable */ @@ -336,7 +337,8 @@ static int iw7027_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -648,7 +650,7 @@ static ssize_t iw7027_store(struct class *class, struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); struct iw7027_s *bl = container_of(class, struct iw7027_s, cls); unsigned int val, val2; - unsigned char reg_addr, reg_val; + unsigned char reg_addr, reg_val, temp; int i; if (!strcmp(attr->attr.name, "init")) { @@ -663,6 +665,10 @@ static ssize_t iw7027_store(struct class *class, reg_addr = (unsigned char)val; reg_val = (unsigned char)val2; iw7027_wreg(bl->spi, reg_addr, reg_val); + iw7027_rreg(bl->spi, reg_addr, &temp); + pr_info( + "reg 0x%02x = 0x%02x, readback 0x%02x\n", + reg_addr, reg_val, temp); mutex_unlock(&iw7027_spi_mutex); } else { LDIMERR("%s: invalid args\n", __func__); diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index a26870933f34..9dab744e1622 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -58,6 +58,7 @@ static struct spi_board_info ldim_spi_info = { static unsigned char *table_init_on_dft; static unsigned char *table_init_off_dft; static int ldim_dev_probe_flag; +static struct class ldim_dev_class; struct ldim_dev_config_s ldim_dev_config = { .type = LDIM_DEV_TYPE_NORMAL, @@ -77,11 +78,11 @@ struct ldim_dev_config_s ldim_dev_config = { .init_off = NULL, .init_on_cnt = 0, .init_off_cnt = 0, - .pwm_config = { + .ldim_pwm_config = { .pwm_method = BL_PWM_POSITIVE, .pwm_port = BL_PWM_MAX, .pwm_duty_max = 100, - .pwm_duty_min = 1, + .pwm_duty_min = 0, }, .analog_pwm_config = { .pwm_method = BL_PWM_POSITIVE, @@ -257,14 +258,13 @@ unsigned int ldim_gpio_get(int index) void ldim_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned long temp; + unsigned long long temp; if (bl_pwm->pwm_port >= BL_PWM_MAX) return; temp = bl_pwm->pwm_cnt; - temp = (((temp * bl_pwm->pwm_duty) + 50) / 100); - bl_pwm->pwm_level = (unsigned int)temp; + bl_pwm->pwm_level = bl_do_div(((temp * bl_pwm->pwm_duty) + 50), 100); if (ldim_debug_print == 2) { LDIMPR( @@ -288,42 +288,53 @@ void ldim_pwm_off(struct bl_pwm_config_s *bl_pwm) static char *ldim_pinmux_str[] = { "ldim_pwm", /* 0 */ "ldim_pwm_vs", /* 1 */ - "ldim_pwm_off", /* 1 */ - "none", + "ldim_pwm_combo", /* 2 */ + "ldim_pwm_vs_combo", /* 3 */ + "ldim_pwm_off", /* 4 */ + "ldim_pwm_combo_off", /* 5 */ + "custome", }; static int ldim_pwm_pinmux_ctrl(int status) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); struct bl_pwm_config_s *bl_pwm; + char *str; int ret = 0, index = 0xff; - if (strcmp(ldim_drv->ldev_conf->pinmux_name, "invalid") == 0) + if (ldim_drv->ldev_conf->ldim_pwm_config.pwm_port >= BL_PWM_MAX) return 0; - bl_pwm = &ldim_drv->ldev_conf->pwm_config; - if (bl_pwm->pwm_port >= BL_PWM_MAX) - return 0; - - if (bl_pwm->pwm_port == BL_PWM_VS) - index = (status) ? 1 : 2; - else - index = (status) ? 0 : 2; + if (status) { + bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config; + if (bl_pwm->pwm_port == BL_PWM_VS) + index = 1; + else + index = 0; + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) + index += 2; + } else { + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) + index = 5; + else + index = 4; + } + str = ldim_pinmux_str[index]; if (ldim_drv->pinmux_flag == index) { - LDIMPR("pinmux %s is already selected\n", - ldim_pinmux_str[index]); + LDIMPR("pinmux %s is already selected\n", str); return 0; } /* request pwm pinmux */ - ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, - ldim_pinmux_str[index]); + ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, str); if (IS_ERR(ldim_drv->pin)) { - LDIMERR("set pinmux %s error\n", ldim_pinmux_str[index]); + LDIMERR("set pinmux %s error\n", str); + ret = -1; } else { - LDIMPR("set pinmux %s: 0x%p\n", - ldim_pinmux_str[index], ldim_drv->pin); + LDIMPR("set pinmux %s: 0x%p\n", str, ldim_drv->pin); } ldim_drv->pinmux_flag = index; @@ -332,7 +343,7 @@ static int ldim_pwm_pinmux_ctrl(int status) static int ldim_pwm_vs_update(void) { - struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.pwm_config; + struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.ldim_pwm_config; unsigned int cnt; int ret = 0; @@ -374,6 +385,10 @@ static void ldim_dev_init_table_dynamic_size_print( table = econf->init_off; max_len = econf->init_off_cnt; } + if (max_len == 0) { + kfree(str); + return; + } if (table == NULL) { LDIMERR("init_table %d is NULL\n", flag); kfree(str); @@ -451,6 +466,10 @@ static void ldim_dev_init_table_fixed_size_print( table = econf->init_off; max_len = econf->init_off_cnt; } + if (max_len == 0) { + kfree(str); + return; + } if (table == NULL) { LDIMERR("init_table %d is NULL\n", flag); kfree(str); @@ -487,7 +506,7 @@ static void ldim_dev_config_print(void) pr_info("valid_flag = %d\n" "dev_index = %d\n" - "vsync_change_flag = %d\n", + "vsync_change_flag = %d\n\n", ldim_drv->valid_flag, ldim_drv->dev_index, ldim_drv->vsync_change_flag); @@ -496,7 +515,6 @@ static void ldim_dev_config_print(void) return; } - bl_pwm = &ldim_drv->ldev_conf->pwm_config; pr_info("dev_name = %s\n" "type = %d\n" "en_gpio = %d\n" @@ -559,13 +577,14 @@ static void ldim_dev_config_print(void) default: break; } + bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config; if (bl_pwm->pwm_port < BL_PWM_MAX) { - pr_info("pwm_port: %d\n" - "pwm_pol: %d\n" - "pwm_freq: %d\n" - "pwm_cnt: %d\n" - "pwm_level: %d\n" - "pwm_duty: %d%%\n", + pr_info("lidm_pwm_port: %d\n" + "lidm_pwm_pol: %d\n" + "lidm_pwm_freq: %d\n" + "lidm_pwm_cnt: %d\n" + "lidm_pwm_level: %d\n" + "lidm_pwm_duty: %d%%\n", bl_pwm->pwm_port, bl_pwm->pwm_method, bl_pwm->pwm_freq, bl_pwm->pwm_cnt, bl_pwm->pwm_level, bl_pwm->pwm_duty); @@ -577,28 +596,28 @@ static void ldim_dev_config_print(void) case BL_PWM_E: case BL_PWM_F: if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { - pr_info("pwm invalid\n"); + pr_info("lidm_pwm invalid\n"); break; } - pr_info("pwm_pointer: %p\n", + pr_info("lidm_pwm_pointer: 0x%p\n", bl_pwm->pwm_data.pwm); pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); - pr_info("pwm state:\n" - " period: %d\n" - " duty_cycle: %d\n" - " polarity: %d\n" - " enabled: %d\n", + pr_info("lidm_pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", pstate.period, pstate.duty_cycle, pstate.polarity, pstate.enabled); value = bl_cbus_read( bl_drv->data->pwm_reg[bl_pwm->pwm_port]); - pr_info("pwm_reg: 0x%08x\n", value); + pr_info("lidm_pwm_reg: 0x%08x\n", value); break; case BL_PWM_VS: - pr_info("pwm_reg0: 0x%08x\n" - "pwm_reg1: 0x%08x\n" - "pwm_reg2: 0x%08x\n" - "pwm_reg3: 0x%08x\n", + pr_info("lidm_pwm_reg0: 0x%08x\n" + "lidm_pwm_reg1: 0x%08x\n" + "lidm_pwm_reg2: 0x%08x\n" + "lidm_pwm_reg3: 0x%08x\n", bl_vcbus_read(VPU_VPU_PWM_V0), bl_vcbus_read(VPU_VPU_PWM_V1), bl_vcbus_read(VPU_VPU_PWM_V2), @@ -608,16 +627,59 @@ static void ldim_dev_config_print(void) break; } } - pr_info("pinmux_flag: %d\n" - "pinmux_pointer: 0x%p\n\n", + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_MAX) { + pr_info("\nanalog_pwm_port: %d\n" + "analog_pwm_pol: %d\n" + "analog_pwm_freq: %d\n" + "analog_pwm_cnt: %d\n" + "analog_pwm_level: %d\n" + "analog_pwm_duty: %d%%\n" + "analog_pwm_duty_max: %d%%\n" + "analog_pwm_duty_min: %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_method, + bl_pwm->pwm_freq, bl_pwm->pwm_cnt, + bl_pwm->pwm_level, bl_pwm->pwm_duty, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + switch (bl_pwm->pwm_port) { + case BL_PWM_A: + case BL_PWM_B: + case BL_PWM_C: + case BL_PWM_D: + case BL_PWM_E: + case BL_PWM_F: + if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { + pr_info("analog_pwm invalid\n"); + break; + } + pr_info("analog_pwm_pointer: 0x%p\n", + bl_pwm->pwm_data.pwm); + pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); + pr_info("analog_pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", + pstate.period, pstate.duty_cycle, + pstate.polarity, pstate.enabled); + value = bl_cbus_read( + bl_drv->data->pwm_reg[bl_pwm->pwm_port]); + pr_info("analog_pwm_reg: 0x%08x\n", value); + break; + default: + break; + } + } + pr_info("\npinmux_flag: %d\n" + "pinmux_pointer: 0x%p\n\n", ldim_drv->pinmux_flag, ldim_drv->pin); if (ldim_drv->ldev_conf->cmd_size > 0) { - pr_info("table_loaded: %d\n" - "cmd_size: %d\n" - "init_on_cnt: %d\n" - "init_off_cnt: %d\n", + pr_info("table_loaded: %d\n" + "cmd_size: %d\n" + "init_on_cnt: %d\n" + "init_off_cnt: %d\n", ldim_drv->ldev_conf->init_loaded, ldim_drv->ldev_conf->cmd_size, ldim_drv->ldev_conf->init_on_cnt, @@ -647,6 +709,9 @@ static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, struct device_node *child; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + if (ldim_debug_print) + LDIMPR("%s ok\n", __func__); + ret = of_property_read_u32(blnode, "ldim_pwm_config", &pwm_phandle); if (ret) { LDIMERR("not match ldim_pwm_config node\n"); @@ -694,8 +759,6 @@ static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); } - LDIMPR("%s ok\n", __func__); - return ret; } @@ -902,6 +965,7 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) int i; int ret = 0; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct bl_pwm_config_s *bl_pwm; temp = kcalloc(LD_BLKREGNUM, sizeof(unsigned int), GFP_KERNEL); if (temp == NULL) { @@ -927,48 +991,77 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) ret = of_property_read_string(child, "ldim_pwm_pinmux_sel", &str); if (ret) { - LDIMERR("failed to get ldim_pwm_name\n"); strcpy(ldim_dev_config.pinmux_name, "invalid"); } else { + LDIMPR("find custome ldim_pwm_pinmux_sel: %s\n", str); strcpy(ldim_dev_config.pinmux_name, str); } + /* ldim pwm config */ + bl_pwm = &ldim_dev_config.ldim_pwm_config; ret = of_property_read_string(child, "ldim_pwm_port", &str); if (ret) { LDIMERR("failed to get ldim_pwm_port\n"); - ldim_dev_config.pwm_config.pwm_port = BL_PWM_MAX; } else { - ldim_dev_config.pwm_config.pwm_port = bl_pwm_str_to_pwm(str); + bl_pwm->pwm_port = bl_pwm_str_to_pwm(str); + LDIMPR("ldim_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port); } - LDIMPR("pwm_port: %s(%u)\n", str, ldim_dev_config.pwm_config.pwm_port); - - if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_MAX) { + if (bl_pwm->pwm_port < BL_PWM_MAX) { ret = of_property_read_u32_array(child, "ldim_pwm_attr", temp, 3); if (ret) { LDIMERR("failed to get ldim_pwm_attr\n"); - ldim_dev_config.pwm_config.pwm_method = BL_PWM_POSITIVE; - if (ldim_dev_config.pwm_config.pwm_port == BL_PWM_VS) - ldim_dev_config.pwm_config.pwm_freq = 1; + bl_pwm->pwm_method = BL_PWM_POSITIVE; + if (bl_pwm->pwm_port == BL_PWM_VS) + bl_pwm->pwm_freq = 1; else - ldim_dev_config.pwm_config.pwm_freq = 60; - ldim_dev_config.pwm_config.pwm_duty = 50; + bl_pwm->pwm_freq = 60; + bl_pwm->pwm_duty = 50; } else { - ldim_dev_config.pwm_config.pwm_method = temp[0]; - ldim_dev_config.pwm_config.pwm_freq = temp[1]; - ldim_dev_config.pwm_config.pwm_duty = temp[2]; + bl_pwm->pwm_method = temp[0]; + bl_pwm->pwm_freq = temp[1]; + bl_pwm->pwm_duty = temp[2]; } - LDIMPR("get pwm pol = %d, freq = %d, duty = %d%%\n", - ldim_dev_config.pwm_config.pwm_method, - ldim_dev_config.pwm_config.pwm_freq, - ldim_dev_config.pwm_config.pwm_duty); + LDIMPR( + "get ldim_pwm pol = %d, freq = %d, default duty = %d%%\n", + bl_pwm->pwm_method, bl_pwm->pwm_freq, + bl_pwm->pwm_duty); - bl_pwm_config_init(&ldim_dev_config.pwm_config); + bl_pwm_config_init(bl_pwm); - if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_VS) { - ldim_dev_pwm_channel_register( - &ldim_dev_config.pwm_config, np); + if (bl_pwm->pwm_port < BL_PWM_VS) + ldim_dev_pwm_channel_register(bl_pwm, np); + } + + /* analog pwm config */ + bl_pwm = &ldim_dev_config.analog_pwm_config; + ret = of_property_read_string(child, "analog_pwm_port", &str); + if (ret) + bl_pwm->pwm_port = BL_PWM_MAX; + else + bl_pwm->pwm_port = bl_pwm_str_to_pwm(str); + if (bl_pwm->pwm_port < BL_PWM_VS) { + LDIMPR("find analog_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port); + ret = of_property_read_u32_array(child, "analog_pwm_attr", + temp, 5); + if (ret) { + LDIMERR("failed to get analog_pwm_attr\n"); + } else { + bl_pwm->pwm_method = temp[0]; + bl_pwm->pwm_freq = temp[1]; + bl_pwm->pwm_duty_max = temp[2]; + bl_pwm->pwm_duty_min = temp[3]; + bl_pwm->pwm_duty = temp[4]; } + LDIMPR( +"get analog_pwm pol = %d, freq = %d, duty_max = %d%%, duty_min = %d%%, default duty = %d%%\n", + bl_pwm->pwm_method, bl_pwm->pwm_freq, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min, + bl_pwm->pwm_duty); + + bl_pwm_config_init(bl_pwm); + + ldim_dev_pwm_channel_register(bl_pwm, np); } ret = of_property_read_u32_array(child, "en_gpio_on_off", temp, 3); @@ -1643,12 +1736,14 @@ static int ldim_dev_probe(struct platform_device *pdev) ldim_dev_get_config_from_dts(pdev->dev.of_node, ldim_drv->dev_index); + ldim_dev_class_create(); ldim_dev_add_driver(ldim_drv); + + /* init ldim function */ + if (ldim_drv->valid_flag) + ldim_drv->init(); + LDIMPR("%s OK\n", __func__); } - /* init ldim function */ - if (ldim_drv->valid_flag) - ldim_drv->init(); - LDIMPR("%s OK\n", __func__); return 0; } @@ -1657,10 +1752,11 @@ static int __exit ldim_dev_remove(struct platform_device *pdev) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (ldim_drv->dev_index != 0xff) + if (ldim_drv->dev_index != 0xff) { ldim_dev_remove_driver(ldim_drv); + LDIMPR("%s OK\n", __func__); + } - LDIMPR("%s OK\n", __func__); return 0; } diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index 0875bde52656..6c44b2a23122 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -25,7 +25,9 @@ /*20180820: pq tooling support, espically optimize some alg parameters */ /*20181101: fix ldim_op_func null mistake, add new spi api support */ /*20181203: add 50/60hz change & iw7027 error handle support */ -#define LDIM_DRV_VER "20181203" +/*20181220: add tl1 support*/ +/*20190103: add analog pwm support*/ +#define LDIM_DRV_VER "20190103" extern unsigned char ldim_debug_print; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c index 4348321adf17..8efef8baaa2c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c @@ -48,7 +48,8 @@ static int ob3350_hw_init_on(void) ldim_drv->ldev_conf->en_gpio_on); mdelay(2); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); mdelay(20); @@ -62,7 +63,8 @@ static int ob3350_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -89,12 +91,22 @@ static int ob3350_smr(unsigned short *buf, unsigned char len) level = buf[0]; val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - ldim_drv->ldev_conf->pwm_config.pwm_duty = val; - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val; + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); return 0; } +static void ob3350_dim_range_update(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct ldim_dev_config_s *ldim_dev; + + ldim_dev = ldim_drv->ldev_conf; + ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max; + ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min; +} + static int ob3350_power_on(void) { if (ob3350_on_flag) { @@ -138,7 +150,7 @@ static ssize_t ob3350_show(struct class *class, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->dim_max, ldim_drv->ldev_conf->dim_min, - ldim_drv->ldev_conf->pwm_config.pwm_duty); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty); } return ret; @@ -151,6 +163,12 @@ static struct class_attribute ob3350_class_attrs[] = { static int ob3350_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) { + struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf; + + ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max; + ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min; + ldim_dev->dim_range_update = ob3350_dim_range_update; + ldim_drv->device_power_on = ob3350_power_on; ldim_drv->device_power_off = ob3350_power_off; ldim_drv->device_bri_update = ob3350_smr; diff --git a/include/linux/amlogic/media/vout/lcd/aml_bl.h b/include/linux/amlogic/media/vout/lcd/aml_bl.h index a9424d1ab8de..04dc80b0171b 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_bl.h +++ b/include/linux/amlogic/media/vout/lcd/aml_bl.h @@ -197,5 +197,14 @@ extern void bl_pwm_ctrl(struct bl_pwm_config_s *bl_pwm, int status); #define BL_GPIO_OUTPUT_HIGH 1 #define BL_GPIO_INPUT 2 +static inline unsigned int bl_do_div(unsigned long long num, unsigned int den) +{ + unsigned long long ret = num; + + do_div(ret, den); + + return (unsigned int)ret; +} + #endif From 91c95b3e09a5e0876b71805c52bda501b4ed2fd9 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 8 Jan 2019 00:29:50 -0500 Subject: [PATCH 0483/1060] lcd: optimize tcon type for extensible usage [1/1] PD#SWPL-3957 Problem: tcon_type need extensible usage for special case Solution: tcon_type change to hex value Verify: x301 Change-Id: I26cb58ffc1cd2f525c8cf0f7c08b0d9cf66766e5 Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_skt-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi drivers/amlogic/media/vout/lcd/lcd_debug.c include/linux/amlogic/media/vout/lcd/lcd_vout.h --- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 251 +++++++++++++++++- .../amlogic/media/vout/lcd/lcd_clk_config.c | 4 - drivers/amlogic/media/vout/lcd/lcd_debug.c | 132 +++++++-- drivers/amlogic/media/vout/lcd/lcd_reg.h | 3 +- .../linux/amlogic/media/vout/lcd/lcd_vout.h | 6 + 5 files changed, 363 insertions(+), 33 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 706d97e48914..06526f26ba9c 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -441,13 +441,16 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 1 /*lvds_repack*/ - 1 /*dual_port*/ - 0 /*pn_swap*/ - 0 /*port_swap*/ - 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/>; + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -461,6 +464,240 @@ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; }; lcd_extern{ diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index c3710a92351d..cd776721a2d7 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -690,10 +690,6 @@ static void lcd_set_tcon_clk(struct lcd_config_s *pconf) switch (pconf->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: - /* tcon_clk 50M */ - /*lcd_hiu_write(HHI_TCON_CLK_CNTL, - * (1 << 7) | (1 << 6) | (7 << 0)); - */ if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) { clk_set_rate(lcd_clktree.tcon_clk, 50000000); clk_prepare_enable(lcd_clktree.tcon_clk); diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index faa5843cd81b..e5ae37360829 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -280,13 +280,13 @@ static int lcd_info_print_ttl(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "clk_pol %u\n" - "hvsync_valid %u\n" "de_valid %u\n" + "hvsync_valid %u\n" "rb_swap %u\n" "bit_swap %u\n\n", pconf->lcd_control.ttl_config->clk_pol, - ((pconf->lcd_control.ttl_config->sync_valid >> 0) & 1), ((pconf->lcd_control.ttl_config->sync_valid >> 1) & 1), + ((pconf->lcd_control.ttl_config->sync_valid >> 0) & 1), ((pconf->lcd_control.ttl_config->swap_ctrl >> 1) & 1), ((pconf->lcd_control.ttl_config->swap_ctrl >> 0) & 1)); @@ -464,6 +464,7 @@ static int lcd_info_print_p2p(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, + "p2p_type 0x%x\n" "lane_num %d\n" "channel_sel1 0x%08x\n" "channel_sel1 0x%08x\n" @@ -966,7 +967,7 @@ static int lcd_reg_print_p2p(char *buf, int offset) len += snprintf((buf+len), n, "\np2p regs:\n"); n = lcd_debug_info_len(len + offset); - reg = HHI_TCON_CLK_CNTL_TL1; + reg = HHI_TCON_CLK_CNTL; len += snprintf((buf+len), n, "HHI_TCON_CLK_CNTL [0x%04x] = 0x%08x\n", reg, lcd_hiu_read(reg)); @@ -2036,7 +2037,7 @@ static ssize_t lcd_debug_change_store(struct class *class, break; case 'p': p2p_conf = pconf->lcd_control.p2p_config; - ret = sscanf(buf, "p2p %d %x %x %x %d %d", + ret = sscanf(buf, "p2p %x %d %x %x %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); if (ret == 6) { p2p_conf->lane_num = val[0]; @@ -2046,7 +2047,7 @@ static ssize_t lcd_debug_change_store(struct class *class, p2p_conf->pn_swap = val[4]; p2p_conf->bit_swap = val[5]; pr_info("change p2p config:\n" - "lane_num=%d,\n" + "p2p_type=0x%x, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", @@ -3092,10 +3093,11 @@ static const char *lcd_mlvds_debug_usage_str = { static const char *lcd_p2p_debug_usage_str = { "Usage:\n" -" echo > minilvds ; set minilvds config\n" +" echo > p2p ; set p2p config\n" "data format:\n" -" : minilvds 8 channels mapping in tx 10 channels\n" -" : bit[13:12]=clk01_pi_sel, bit[11:8]=pi2, bit[7:4]=pi1, bit[3:0]=pi0\n" +" : 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi,\n" +" 0x10=chpi, 0x11=cspi, 0x12=usit\n" +" : 12 channels mapping\n" " : 0=normal, 1=swap p/n channels\n" " : 0=normal, 1=swap bit LSB/MSB\n" "\n" @@ -3126,37 +3128,128 @@ static const char *lcd_debug_tcon_usage_str = { static ssize_t lcd_ttl_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_ttl_debug_usage_str); + int len = 0; + + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct ttl_config_s *ttl_conf; + + ttl_conf = lcd_drv->lcd_config->lcd_control.ttl_config; + + len += sprintf(buf+len, + "ttl config: clk_pol=%d, de_valid=%d, hvsync_valid=%d,", + ttl_conf->clk_pol, + (ttl_conf->sync_valid >> 1) & 0x1, + (ttl_conf->sync_valid >> 0) & 0x1); + len += sprintf(buf+len, "rb_swap=%d, bit_swap=%d\n\n", + (ttl_conf->swap_ctrl >> 1) & 0x1, + (ttl_conf->swap_ctrl >> 0) & 0x1); + len += sprintf(buf+len, "%s\n", lcd_ttl_debug_usage_str); + + return len; } static ssize_t lcd_lvds_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_lvds_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lvds_config_s *lvds_conf; + + lvds_conf = lcd_drv->lcd_config->lcd_control.lvds_config; + + len += sprintf(buf+len, "lvds config: repack=%d, dual_port=%d,", + lvds_conf->lvds_repack, lvds_conf->dual_port); + len += sprintf(buf+len, "pn_swap=%d, port_swap=%d, lane_reverse=%d\n\n", + lvds_conf->pn_swap, lvds_conf->port_swap, + lvds_conf->lane_reverse); + len += sprintf(buf+len, "%s\n", lcd_lvds_debug_usage_str); + + return len; } static ssize_t lcd_vx1_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_vbyone_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct vbyone_config_s *vx1_conf; + + vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config; + + len += sprintf(buf+len, "vbyone config: lane_count=%d,", + vx1_conf->lane_count); + len += sprintf(buf+len, "region_num=%d, byte_mode=%d\n\n", + vx1_conf->region_num, vx1_conf->byte_mode); + len += sprintf(buf+len, "%s\n", lcd_vbyone_debug_usage_str); + + return len; } static ssize_t lcd_mipi_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_mipi_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct dsi_config_s *dsi_conf; + + dsi_conf = lcd_drv->lcd_config->lcd_control.mipi_config; + + len += sprintf(buf+len, "mipi_dsi config: lane_num=%d, ", + dsi_conf->lane_num); + len += sprintf(buf+len, "bit_rate_max=%dMhz, factor_numerator=%d, ", + dsi_conf->bit_rate_max, dsi_conf->factor_numerator); + len += sprintf(buf+len, + "operation_mode_init=%d, operation_mode_display=%d, ", + dsi_conf->operation_mode_init, + dsi_conf->operation_mode_display); + len += sprintf(buf+len, + "video_mode_type=%d, clk_always_hs=%d, phy_switch=%d\n\n", + dsi_conf->video_mode_type, dsi_conf->clk_always_hs, + dsi_conf->phy_switch); + len += sprintf(buf+len, "%s\n", lcd_mipi_debug_usage_str); + + return len; } static ssize_t lcd_mlvds_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_mlvds_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct mlvds_config_s *mlvds_conf; + + mlvds_conf = lcd_drv->lcd_config->lcd_control.mlvds_config; + + len += sprintf(buf+len, "minilvds config: channel_num=%d, ", + mlvds_conf->channel_num); + len += sprintf(buf+len, "channel_sel0=0x%08x, channel_sel1=0x%08x, ", + mlvds_conf->channel_sel0, mlvds_conf->channel_sel1); + len += sprintf(buf+len, "clk_phase=0x%04x, pn_swap=%d, bit_swap=%d\n\n", + mlvds_conf->clk_phase, + mlvds_conf->pn_swap, mlvds_conf->bit_swap); + len += sprintf(buf+len, "%s\n", lcd_mlvds_debug_usage_str); + + return len; } static ssize_t lcd_p2p_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_p2p_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct p2p_config_s *p2p_conf; + + p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; + + len += sprintf(buf+len, "p2p config: p2p_type=0x%x, lane_num=%d, ", + p2p_conf->p2p_type, p2p_conf->lane_num); + len += sprintf(buf+len, "channel_sel0=0x%08x, channel_sel1=0x%08x, ", + p2p_conf->channel_sel0, p2p_conf->channel_sel1); + len += sprintf(buf+len, "pn_swap=%d, bit_swap=%d\n\n", + p2p_conf->pn_swap, p2p_conf->bit_swap); + len += sprintf(buf+len, "%s\n", lcd_p2p_debug_usage_str); + + return len; } static ssize_t lcd_tcon_debug_show(struct class *class, @@ -3178,7 +3271,7 @@ static ssize_t lcd_ttl_debug_store(struct class *class, &temp[0], &temp[1], &temp[2], &temp[3], &temp[4]); if (ret == 5) { pr_info("set ttl config:\n" - "clk_pol=%d, de_valid=%d, de_valid=%d\n" + "clk_pol=%d, de_valid=%d, hvsync_valid=%d\n" "rb_swap=%d, bit_swap=%d\n", temp[0], temp[1], temp[2], temp[3], temp[4]); ttl_conf->clk_pol = temp[0]; @@ -3400,14 +3493,13 @@ static ssize_t lcd_p2p_debug_store(struct class *class, struct p2p_config_s *p2p_conf; p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; - ret = sscanf(buf, "%d %x %x %x %d %d", - &p2p_conf->lane_num, + ret = sscanf(buf, "%x %d %x %x %d %d", + &p2p_conf->p2p_type, &p2p_conf->lane_num, &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, - &p2p_conf->clk_phase, &p2p_conf->pn_swap, &p2p_conf->bit_swap); if (ret == 6) { - pr_info("set minilvds config:\n" - "lane_num=%d,\n" + pr_info("set p2p config:\n" + "p2p_type=0x%x, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index c6225693b85c..a3e2d3bf4e53 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -211,8 +211,7 @@ #define HHI_DIF_TCON_CNTL0 0x3c #define HHI_DIF_TCON_CNTL1 0x3d #define HHI_DIF_TCON_CNTL2 0x3e -#define HHI_TCON_CLK_CNTL 0xf0 -#define HHI_TCON_CLK_CNTL_TL1 0x9c +#define HHI_TCON_CLK_CNTL 0x9c /* Global control: RESET_CBUS_BASE = 0x11 */ #define VERSION_CTRL 0x1100 diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index da726bc91156..62fbc8b07952 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -339,6 +339,12 @@ struct mlvds_config_s { enum p2p_type_e { P2P_CEDS = 0, + P2P_CMPI, + P2P_ISP, + P2P_EPI, + P2P_CHPI = 0x10, /* low common mode */ + P2P_CSPI, + P2P_USIT, P2P_MAX, }; From 0e89b2d7c91d94346070337395af46bd0a4320a9 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 11 Feb 2019 17:34:23 +0800 Subject: [PATCH 0484/1060] lcd: tcon: change axi_mem cma alloc api to avoid memory clear [1/1] PD#SWPL-4554 Problem: tcon axi memory will clear when enter kernel Solution: change axi_mem cma alloc api Verify: t309 Change-Id: Ied6ef9976e503c597818a73109b222868c0f0387 Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tcon.c --- drivers/amlogic/media/vout/lcd/lcd_tcon.c | 77 +++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index 67b060b15d8e..9e74de498f2c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include #include "lcd_common.h" @@ -621,6 +624,9 @@ static struct lcd_tcon_data_s tcon_data_tl1 = { int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) { + struct cma *cma; + unsigned int mem_size; + int key_init_flag = 0; int ret = 0; switch (lcd_drv->data->chip_type) { @@ -639,16 +645,79 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) lcd_tcon_data = NULL; break; } - ret = lcd_tcon_valid_check(); - if (ret) - return -1; + if (lcd_tcon_data == NULL) + return 0; + + /* init reserved memory */ + ret = of_reserved_mem_device_init(lcd_drv->dev); + if (ret) { + LCDERR("tcon: init reserved memory failed\n"); + } else { + if ((void *)tcon_rmem.mem_paddr == NULL) { +#ifdef CONFIG_CMA + cma = dev_get_cma_area(lcd_drv->dev); + if (cma) { + tcon_rmem.mem_paddr = cma_get_base(cma); + LCDPR("tcon axi_mem base:0x%lx, size:0x%lx\n", + (unsigned long)tcon_rmem.mem_paddr, + cma_get_size(cma)); + + mem_size = lcd_tcon_data->axi_mem_size; + tcon_rmem.mem_vaddr = dma_alloc_from_contiguous( + lcd_drv->dev, + (mem_size >> PAGE_SHIFT), + 0); + if (tcon_rmem.mem_vaddr == NULL) { + LCDERR("tcon axi_mem alloc failed\n"); + } else { + LCDPR("tcon axi_mem dma_alloc=0x%x\n", + mem_size); + tcon_rmem.mem_size = mem_size; + tcon_rmem.flag = 2; /* cma memory */ + } + } else { + LCDERR("tcon: NO CMA\n"); + } +#else + LCDERR("tcon axi_mem alloc failed\n"); +#endif + } else { + tcon_rmem.flag = 1; /* reserved memory */ + mem_size = tcon_rmem.mem_size; + LCDPR("tcon axi_mem base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, mem_size); + } + } + + INIT_DELAYED_WORK(&lcd_tcon_delayed_work, lcd_tcon_config_delayed); ret = lcd_tcon_config(lcd_drv); return ret; } -static int rmem_tcon_fb_device_init(struct reserved_mem *rmem, +int lcd_tcon_remove(struct aml_lcd_drv_s *lcd_drv) +{ + if (tcon_rmem.flag == 2) { + LCDPR("tcon free memory: base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); +#ifdef CONFIG_CMA + dma_release_from_contiguous(lcd_drv->dev, + tcon_rmem.mem_vaddr, + tcon_rmem.mem_size >> PAGE_SHIFT); +#endif + } + + if (lcd_tcon_data) { + /* lcd_tcon_data == NULL; */ + lcd_tcon_data->tcon_valid = 0; + } + + return 0; +} + +static int __init tcon_fb_device_init(struct reserved_mem *rmem, struct device *dev) { return 0; From 74500342179546c7ac35b96dad0756462883749b Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Fri, 18 Jan 2019 19:35:36 +0800 Subject: [PATCH 0485/1060] lcd: add wait for gpio input value support in lcd power step [2/2] PD#SWPL-3938 Problem: add wait for gpio input value support in lcd power step Solution: add wait for gpio input value support in lcd power step Verify: verify by t962x-r311 Change-Id: Ie1c4ec6f9f5d91332b6b20e1d1bd2adde17e547b Signed-off-by: Shaochan Liu Conflicts: drivers/amlogic/media/vout/lcd/lcd_vout.c --- drivers/amlogic/media/vout/lcd/lcd_common.c | 9 ++++- drivers/amlogic/media/vout/lcd/lcd_debug.c | 41 ++++++++++++++++----- drivers/amlogic/media/vout/lcd/lcd_vout.c | 39 +++++++++++++++++--- 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index cd61eff6e0a0..471cd968fa25 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -477,6 +477,9 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf, int i, j; unsigned int index; + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + if (child == NULL) { LCDPR("error: failed to get %s\n", pconf->lcd_propname); return -1; @@ -513,6 +516,7 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf, index = lcd_power->power_on_step[i].index; switch (lcd_power->power_on_step[i].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -567,6 +571,7 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf, index = lcd_power->power_off_step[i].index; switch (lcd_power->power_off_step[i].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -612,8 +617,6 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, /* power: (5byte * n) */ p = buf + len; - if (lcd_debug_print_flag) - LCDPR("power_on step:\n"); i = 0; while (i < LCD_PWR_STEP_MAX) { pconf->lcd_power->power_on_step_max = i; @@ -641,6 +644,7 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, index = pconf->lcd_power->power_on_step[i].index; switch (pconf->lcd_power->power_on_step[i].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -693,6 +697,7 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, index = pconf->lcd_power->power_off_step[j].index; switch (pconf->lcd_power->power_off_step[j].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index e5ae37360829..bab975064fa4 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -226,6 +226,7 @@ static int lcd_power_step_print(struct lcd_config_s *pconf, int status, switch (power_step->type) { case LCD_POWER_TYPE_CPU: case LCD_POWER_TYPE_PMU: + case LCD_POWER_TYPE_WAIT_GPIO: n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "%d: type=%d, index=%d, value=%d, delay=%d\n", @@ -2207,37 +2208,59 @@ static ssize_t lcd_debug_power_step_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; - unsigned int i, delay; + unsigned int i; + unsigned int tmp[2]; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); struct lcd_power_ctrl_s *lcd_power_step; lcd_power_step = lcd_drv->lcd_config->lcd_power; switch (buf[1]) { case 'n': /* on */ - ret = sscanf(buf, "on %d %d", &i, &delay); - if (ret == 2) { + ret = sscanf(buf, "on %d %d %d", &i, &tmp[0], &tmp[1]); + if (ret == 3) { + if (i >= lcd_power_step->power_on_step_max) { + pr_info("invalid power_on step: %d, step_max: %d\n", + i, lcd_power_step->power_on_step_max); + return -EINVAL; + } + lcd_power_step->power_on_step[i].value = tmp[0]; + lcd_power_step->power_on_step[i].delay = tmp[1]; + pr_info( + "set power_on step %d value %d delay: %dms\n", + i, tmp[0], tmp[1]); + } else if (ret == 2) { if (i >= lcd_power_step->power_on_step_max) { pr_info("invalid power_on step: %d\n", i); return -EINVAL; } - lcd_power_step->power_on_step[i].delay = delay; + lcd_power_step->power_on_step[i].delay = tmp[0]; pr_info("set power_on step %d delay: %dms\n", - i, delay); + i, tmp[0]); } else { pr_info("invalid data\n"); return -EINVAL; } break; case 'f': /* off */ - ret = sscanf(buf, "off %d %d", &i, &delay); - if (ret == 1) { + ret = sscanf(buf, "off %d %d %d\n", &i, &tmp[0], &tmp[1]); + if (ret == 3) { if (i >= lcd_power_step->power_off_step_max) { pr_info("invalid power_off step: %d\n", i); return -EINVAL; } - lcd_power_step->power_off_step[i].delay = delay; + lcd_power_step->power_off_step[i].value = tmp[0]; + lcd_power_step->power_off_step[i].delay = tmp[1]; + pr_info( + "set power_off step %d value %d delay: %dms\n", + i, tmp[0], tmp[1]); + } else if (ret == 2) { + if (i >= lcd_power_step->power_off_step_max) { + pr_info("invalid power_off step: %d\n", i); + return -EINVAL; + } + lcd_power_step->power_off_step[i].delay = tmp[0]; pr_info("set power_off step %d delay: %dms\n", - i, delay); + i, tmp[0]); } else { pr_info("invalid data\n"); return -EINVAL; diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 32d3d7be22f6..e077fe0f137e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -260,7 +260,8 @@ static void lcd_power_ctrl(int status) #ifdef CONFIG_AMLOGIC_LCD_EXTERN struct aml_lcd_extern_driver_s *ext_drv; #endif - int i, index; + unsigned int i, index, wait, temp; + int value = -1; int ret = 0; LCDPR("%s: %d\n", __func__, status); @@ -275,8 +276,8 @@ static void lcd_power_ctrl(int status) break; if (lcd_debug_print_flag) { LCDPR("power_ctrl: %d, step %d\n", status, i); - LCDPR("type=%d, index=%d, value=%d, delay=%d\n", - power_step->type, power_step->index, + LCDPR("%s: type=%d, index=%d, value=%d, delay=%d\n", + __func__, power_step->type, power_step->index, power_step->value, power_step->delay); } switch (power_step->type) { @@ -312,14 +313,42 @@ static void lcd_power_ctrl(int status) } break; #endif + case LCD_POWER_TYPE_WAIT_GPIO: + index = power_step->index; + lcd_cpu_gpio_set(index, LCD_GPIO_INPUT); + LCDPR("lcd_power_type_wait_gpio wait\n"); + for (wait = 0; wait < power_step->delay; wait++) { + value = lcd_cpu_gpio_get(index); + if (value == power_step->value) { + LCDPR("wait_gpio %d ok\n", value); + break; + } + mdelay(1); + } + if (wait == power_step->delay) + LCDERR("wait_gpio %d timeout!\n", value); + break; + case LCD_POWER_TYPE_CLK_SS: + temp = lcd_driver->lcd_config->lcd_timing.ss_level; + value = (power_step->value) & 0xff; + ret = lcd_set_ss(0xff, + (value >> LCD_CLK_SS_BIT_FREQ) & 0xf, + (value >> LCD_CLK_SS_BIT_MODE) & 0xf); + if (ret == 0) { + temp &= ~(0xff << 8); + temp |= (value << 8); + lcd_driver->lcd_config->lcd_timing.ss_level = + temp; + } + break; default: break; } - if (power_step->delay) + if ((power_step->type != LCD_POWER_TYPE_WAIT_GPIO) && + (power_step->delay > 0)) mdelay(power_step->delay); i++; } - if (lcd_debug_print_flag) LCDPR("%s: %d finished\n", __func__, status); } From 2968992a4bb7ef9aa5bf40ec52d53dd13bf9f38d Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 10 Jan 2019 22:21:01 +0800 Subject: [PATCH 0486/1060] lcd: optimize unifykey read flow to avoid crash [1/1] PD#SWPL-4682 Problem: lcd wait unifykey init timeout and read unifykey will crash Solution: incrase wait unifykey init time, and add read protection Verify: x301 Change-Id: Ib86a2b3b0c6c1491606404358420fd213dcfdaa8 Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_common.h drivers/amlogic/media/vout/lcd/lcd_tcon.c drivers/amlogic/media/vout/lcd/lcd_vout.c --- drivers/amlogic/media/vout/lcd/lcd_common.h | 7 +- drivers/amlogic/media/vout/lcd/lcd_tcon.c | 18 ++ drivers/amlogic/media/vout/lcd/lcd_vout.c | 213 ++++++++++-------- .../amlogic/media/vout/lcd/lcd_unifykey.h | 3 +- 4 files changed, 147 insertions(+), 94 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 6a49629bfaff..aa31da107db0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -33,7 +33,12 @@ /* 20180827: add pinmux off support */ /* 20180928: tl1 support, optimize clk config */ /* 20181012: tl1 support tcon */ -#define LCD_DRV_VERSION "20181012" +/* 20181212: tl1 update p2p config and pll setting */ +/* 20181225: update phy config */ +/* 20190108: tl1 support tablet mode */ +/* 20190115: tl1 tcon all interface support */ +/* 20190225: optimize unifykey read flow to avoid crash */ +#define LCD_DRV_VERSION "20190225" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index 9e74de498f2c..76a90b826679 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -319,6 +319,24 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) return 0; } +static void lcd_tcon_config_delayed(struct work_struct *work) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int key_init_flag = 0; + int i = 0; + + key_init_flag = key_unify_get_init_flag(); + while (key_init_flag == 0) { + if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) + break; + msleep(LCD_UNIFYKEY_RETRY_INTERVAL); + key_init_flag = key_unify_get_init_flag(); + } + LCDPR("tcon: key_init_flag=%d, i=%d\n", key_init_flag, i); + if (key_init_flag) + lcd_tcon_config(lcd_drv); +} + /* ********************************** * tcon function api * ********************************** diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index e077fe0f137e..f804126f766e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -464,14 +464,40 @@ static void lcd_resume_work(struct work_struct *p_work) mutex_unlock(&lcd_driver->power_mutex); } +static struct delayed_work lcd_test_delayed_work; +static void lcd_auto_test_delayed(struct work_struct *work) +{ + LCDPR("%s\n", __func__); + mutex_lock(&lcd_driver->power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + mutex_unlock(&lcd_driver->power_mutex); +} + +static void lcd_auto_test(unsigned char flag) +{ + lcd_driver->lcd_test_state = flag; + if (lcd_driver->workqueue) { + queue_delayed_work(lcd_driver->workqueue, + &lcd_test_delayed_work, + msecs_to_jiffies(20000)); + } else { + schedule_delayed_work(&lcd_test_delayed_work, + msecs_to_jiffies(20000)); + } +} + static int lcd_vsync_print_cnt; static inline void lcd_vsync_handler(void) { int flag; #ifdef CONFIG_AMLOGIC_LCD_TABLET - struct lcd_config_s *pconf = lcd_driver->lcd_config; + struct lcd_config_s *pconf; #endif + if (lcd_driver == NULL) + return; + + pconf = lcd_driver->lcd_config; #ifdef CONFIG_AMLOGIC_LCD_TABLET if (pconf->lcd_control.mipi_config->dread) { if (pconf->lcd_control.mipi_config->dread->flag) { @@ -518,6 +544,9 @@ static inline void lcd_vsync_handler(void) static irqreturn_t lcd_vsync_isr(int irq, void *dev_id) { + if (lcd_driver == NULL) + return IRQ_HANDLED; + if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) return IRQ_HANDLED; @@ -531,6 +560,9 @@ static irqreturn_t lcd_vsync_isr(int irq, void *dev_id) static irqreturn_t lcd_vsync2_isr(int irq, void *dev_id) { + if (lcd_driver == NULL) + return IRQ_HANDLED; + if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) return IRQ_HANDLED; @@ -564,6 +596,9 @@ static void lcd_wait_vsync(void) static void lcd_vsync_none_timer_handler(unsigned long arg) { + if (lcd_driver == NULL) + return; + if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) goto lcd_vsync_none_timer_handler_end; @@ -986,6 +1021,57 @@ static void lcd_fops_remove(void) } /* ************************************************************* */ +static int lcd_vsync_irq_init(void) +{ + if (lcd_driver->res_vsync_irq) { + if (request_irq(lcd_driver->res_vsync_irq->start, + lcd_vsync_isr, IRQF_SHARED, + "lcd_vsync", (void *)"lcd_vsync")) { + LCDERR("can't request lcd_vsync_irq\n"); + } else { + if (lcd_debug_print_flag) + LCDPR("request lcd_vsync_irq successful\n"); + } + } + + if (lcd_driver->res_vsync2_irq) { + if (request_irq(lcd_driver->res_vsync2_irq->start, + lcd_vsync2_isr, IRQF_SHARED, + "lcd_vsync2", (void *)"lcd_vsync2")) { + LCDERR("can't request lcd_vsync2_irq\n"); + } else { + if (lcd_debug_print_flag) + LCDPR("request lcd_vsync2_irq successful\n"); + } + } + + /* add timer to monitor hpll frequency */ + init_timer(&lcd_vsync_none_timer); + /* lcd_vsync_none_timer.data = NULL; */ + lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler; + lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL; + /*add_timer(&lcd_vsync_none_timer);*/ + /*LCDPR("add lcd_vsync_none_timer handler\n"); */ + + return 0; +} + +static void lcd_vsync_irq_remove(void) +{ + if (lcd_driver->res_vsync_irq) + free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync"); + + if (lcd_driver->res_vsync2_irq) { + free_irq(lcd_driver->res_vsync2_irq->start, + (void *)"lcd_vsync"); + } + + if (lcd_driver->vsync_none_timer_flag) { + del_timer_sync(&lcd_vsync_none_timer); + lcd_driver->vsync_none_timer_flag = 0; + } +} + static void lcd_init_vout(void) { switch (lcd_driver->lcd_mode) { @@ -1030,11 +1116,15 @@ static int lcd_mode_probe(struct device *dev) lcd_fops_create(); lcd_notifier_register(); + lcd_vsync_irq_init(); /* add notifier for video sync_duration info refresh */ vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &lcd_driver->lcd_info->mode); + if (lcd_driver->lcd_auto_test) + lcd_auto_test(lcd_driver->lcd_auto_test); + return 0; } @@ -1071,16 +1161,22 @@ static void lcd_config_probe_delayed(struct work_struct *work) int i = 0; int ret; - if (lcd_driver->lcd_key_valid) { + key_init_flag = key_unify_get_init_flag(); + while (key_init_flag == 0) { + if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) + break; + msleep(LCD_UNIFYKEY_RETRY_INTERVAL); key_init_flag = key_unify_get_init_flag(); - while (key_init_flag == 0) { - if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) - break; - msleep(20); - key_init_flag = key_unify_get_init_flag(); - } - LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i); } + LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i); + + if (key_init_flag == 0) { + kfree(lcd_driver); + lcd_driver = NULL; + LCDERR("key is not ready, probe exit\n"); + return; + } + ret = lcd_mode_probe(lcd_driver->dev); if (ret) { kfree(lcd_driver); @@ -1219,55 +1315,6 @@ static int lcd_config_probe(struct platform_device *pdev) return 0; } -static int lcd_vsync_irq_init(void) -{ - if (lcd_driver->res_vsync_irq) { - if (request_irq(lcd_driver->res_vsync_irq->start, - lcd_vsync_isr, IRQF_SHARED, - "lcd_vsync", (void *)"lcd_vsync")) { - LCDERR("can't request lcd_vsync_irq\n"); - } else { - LCDPR("request lcd_vsync_irq successful\n"); - } - } - - if (lcd_driver->res_vsync2_irq) { - if (request_irq(lcd_driver->res_vsync2_irq->start, - lcd_vsync2_isr, IRQF_SHARED, - "lcd_vsync2", (void *)"lcd_vsync2")) { - LCDERR("can't request lcd_vsync2_irq\n"); - } else { - LCDPR("request lcd_vsync2_irq successful\n"); - } - } - - /* add timer to monitor hpll frequency */ - init_timer(&lcd_vsync_none_timer); - /* lcd_vsync_none_timer.data = NULL; */ - lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler; - lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL; - /*add_timer(&lcd_vsync_none_timer);*/ - /*LCDPR("add lcd_vsync_none_timer handler\n"); */ - - return 0; -} - -static void lcd_vsync_irq_remove(void) -{ - if (lcd_driver->res_vsync_irq) - free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync"); - - if (lcd_driver->res_vsync2_irq) { - free_irq(lcd_driver->res_vsync2_irq->start, - (void *)"lcd_vsync"); - } - - if (lcd_driver->vsync_none_timer_flag) { - del_timer_sync(&lcd_vsync_none_timer); - lcd_driver->vsync_none_timer_flag = 0; - } -} - #ifdef CONFIG_OF static struct lcd_data_s lcd_data_gxl = { @@ -1365,28 +1412,6 @@ static const struct of_device_id lcd_dt_match_table[] = { }; #endif -static struct delayed_work lcd_test_delayed_work; -static void lcd_auto_test_delayed(struct work_struct *work) -{ - LCDPR("%s\n", __func__); - mutex_lock(&lcd_driver->power_mutex); - aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); - mutex_unlock(&lcd_driver->power_mutex); -} - -static void lcd_auto_test(unsigned char flag) -{ - lcd_driver->lcd_test_state = flag; - if (lcd_driver->workqueue) { - queue_delayed_work(lcd_driver->workqueue, - &lcd_test_delayed_work, - msecs_to_jiffies(20000)); - } else { - schedule_delayed_work(&lcd_test_delayed_work, - msecs_to_jiffies(20000)); - } -} - static int lcd_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1432,32 +1457,29 @@ static int lcd_probe(struct platform_device *pdev) lcd_ioremap(pdev); ret = lcd_config_probe(pdev); - lcd_vsync_irq_init(); LCDPR("%s %s\n", __func__, (ret ? "failed" : "ok")); - if (lcd_driver->lcd_auto_test) - lcd_auto_test(lcd_driver->lcd_auto_test); - return 0; } static int lcd_remove(struct platform_device *pdev) { + if (lcd_driver == NULL) + return 0; + cancel_delayed_work(&lcd_driver->lcd_probe_delayed_work); cancel_work_sync(&(lcd_driver->lcd_resume_work)); if (lcd_driver->workqueue) destroy_workqueue(lcd_driver->workqueue); - if (lcd_driver) { - lcd_vsync_irq_remove(); - lcd_fops_remove(); - lcd_debug_remove(); - lcd_config_remove(lcd_driver->dev); + lcd_vsync_irq_remove(); + lcd_fops_remove(); + lcd_debug_remove(); + lcd_config_remove(lcd_driver->dev); - kfree(lcd_driver); - lcd_driver = NULL; - } + kfree(lcd_driver); + lcd_driver = NULL; LCDPR("%s\n", __func__); return 0; @@ -1473,6 +1495,8 @@ static int lcd_resume(struct platform_device *pdev) (get_resume_method() == UDEFINED_WAKEUP)) return 0; + if (lcd_driver == NULL) + return 0; if ((lcd_driver->lcd_status & LCD_STATUS_VMODE_ACTIVE) == 0) return 0; @@ -1499,6 +1523,9 @@ static int lcd_resume(struct platform_device *pdev) static int lcd_suspend(struct platform_device *pdev, pm_message_t state) { + if (lcd_driver == NULL) + return 0; + mutex_lock(&lcd_driver->power_mutex); if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) { aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL); @@ -1514,6 +1541,8 @@ static void lcd_shutdown(struct platform_device *pdev) if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + if (lcd_driver == NULL) + return; if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL); } diff --git a/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h b/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h index 2204c6c2f10b..c27f57fe2be4 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h @@ -18,7 +18,8 @@ #ifndef _INC_AML_LCD_UNIFYKEY_H__ #define _INC_AML_LCD_UNIFYKEY_H__ -#define LCD_UNIFYKEY_WAIT_TIMEOUT 300 +#define LCD_UNIFYKEY_WAIT_TIMEOUT 500 +#define LCD_UNIFYKEY_RETRY_INTERVAL 20 /* ms */ /* declare external unifykey function */ extern void *get_ukdev(void); From dfa0f6134399addd88ec7ebe2cc854a542484fd6 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 27 Feb 2019 16:27:51 +0800 Subject: [PATCH 0487/1060] lcd: optimize vbyone auto recovery with hw filter [1/1] PD#SWPL-5172 Problem: vbyone stable is easily affected by ESD Solution: increase hw filter time to anti ESD after vbyone stable, but lower the hw filter time when vbyone training, to avoid side effect to vbyone fsm working. only support in TL1. Verify: x301 Change-Id: If8a8b14a47262abd682f5c95185e82cf3c0f58f2 Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c --- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 3287b48b362a..28a231f15634 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -760,6 +760,30 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, return 0; } +static void lcd_vbyone_hw_filter(int flag) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + if (flag) { + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xffff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0xf); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + } else { + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + } + break; + default: + lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + break; + } +} + static void lcd_vbyone_sw_reset(void) { if (lcd_debug_print_flag) @@ -890,7 +914,7 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ - lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + lcd_vbyone_hw_filter(0); lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); @@ -928,6 +952,7 @@ void lcd_vbyone_interrupt_enable(int flag) vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config; if (flag) { + lcd_vbyone_hw_filter(1); if (vx1_conf->intr_en) { vx1_fsm_acq_st = 0; /* clear interrupt */ @@ -982,6 +1007,7 @@ static void lcd_vbyone_interrupt_init(struct aml_lcd_drv_s *lcd_drv) /* release sw filter ctrl in uboot */ lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 0, 1); + lcd_vbyone_hw_filter(1); /* set hold in FSM_ACQ */ if (vx1_conf->vsync_intr_en == 3) @@ -1216,19 +1242,23 @@ static irqreturn_t lcd_vbyone_vsync_isr(int irq, void *dev_id) if (vsync_cnt < VSYNC_CNT_VX1_RESET) vsync_cnt++; else if (vsync_cnt == VSYNC_CNT_VX1_RESET) { + lcd_vbyone_hw_filter(0); lcd_vbyone_sw_reset(); vsync_cnt++; } else if ((vsync_cnt > VSYNC_CNT_VX1_RESET) && (vsync_cnt < VSYNC_CNT_VX1_STABLE)) { - if (lcd_vcbus_read(VBO_STATUS_L) & 0x20) + if (lcd_vcbus_read(VBO_STATUS_L) & 0x20) { vsync_cnt = VSYNC_CNT_VX1_STABLE; - else + lcd_vbyone_hw_filter(1); + } else { vsync_cnt++; + } } } else if (vx1_conf->vsync_intr_en == 2) { if (vsync_cnt >= 5) { vsync_cnt = 0; if (!(lcd_vcbus_read(VBO_STATUS_L) & 0x20)) { + lcd_vbyone_hw_filter(0); lcd_vbyone_sw_reset(); LCDPR("vx1 sw_reset 2\n"); while (lcd_vcbus_read(VBO_STATUS_L) & 0x4) @@ -1236,6 +1266,8 @@ static irqreturn_t lcd_vbyone_vsync_isr(int irq, void *dev_id) lcd_vcbus_setb(VBO_INTR_STATE_CTRL, 0, 15, 1); lcd_vcbus_setb(VBO_INTR_STATE_CTRL, 1, 15, 1); + } else { + lcd_vbyone_hw_filter(1); } } else vsync_cnt++; @@ -1398,6 +1430,7 @@ static irqreturn_t lcd_vbyone_interrupt_handler(int irq, void *dev_id) #if (VX1_FSM_ACQ_NEXT == VX1_FSM_ACQ_NEXT_RELEASE_HOLDER) lcd_vcbus_setb(VBO_FSM_HOLDER_L, 0xffff, 0, 16); #endif + lcd_vbyone_hw_filter(1); LCDPR("vx1 fsm stable\n"); } } From b9e8ed0351a3e454a2d202ef5bca71dd79503e49 Mon Sep 17 00:00:00 2001 From: pengcheng chen Date: Tue, 30 Oct 2018 14:55:40 +0800 Subject: [PATCH 0488/1060] osd: add meson-hwc repodution rate support [1/2] PD#SWPL-1810 Problem: osd blend repodution rate not supported Solution: add meson-hwc repodution rate support Verify: verified on u212 dev board Change-Id: Ied10393e240e8d3f2a1eefe17a2d4d3c965e3383 Signed-off-by: pengcheng chen Conflicts: drivers/amlogic/media/osd/osd.h drivers/amlogic/media/osd/osd_fb.c drivers/amlogic/media/osd/osd_hw.c --- drivers/amlogic/media/osd/osd_hw.c | 120 +++-------------------------- 1 file changed, 9 insertions(+), 111 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index decd51d35cdc..8cfb51fd37a4 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1944,7 +1944,7 @@ int osd_set_scan_mode(u32 index) if ((vinfo->width == 720) && (vinfo->height == 480)) { if (osd_hw.free_scale_mode[index]) { - osd_hw.field_out_en = 1; + //osd_hw.field_out_en = 1; switch (y_end) { case 719: osd_hw.bot_type = 2; @@ -1964,7 +1964,7 @@ int osd_set_scan_mode(u32 index) } else if ((vinfo->width == 720) && (vinfo->height == 576)) { if (osd_hw.free_scale_mode[index]) { - osd_hw.field_out_en = 1; + //osd_hw.field_out_en = 1; switch (y_end) { case 719: osd_hw.bot_type = 2; @@ -1985,7 +1985,7 @@ int osd_set_scan_mode(u32 index) } else if ((vinfo->width == 1920) && (vinfo->height == 1080)) { if (osd_hw.free_scale_mode[index]) { - osd_hw.field_out_en = 1; + //osd_hw.field_out_en = 1; switch (y_end) { case 719: osd_hw.bot_type = 1; @@ -6119,12 +6119,12 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) if (!blending) return; if (osd_hw.hdr_used) - workaround_line = osd_hw.workaround_line; + workaround_line = 1; else { if (blending->layer_cnt == 2) workaround_line = 0; else - workaround_line = osd_hw.workaround_line; + workaround_line = 1; } layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -6415,7 +6415,7 @@ static void osd_set_freescale(u32 index, struct layer_blend_reg_s *blend_reg; u32 width, height; u32 src_height; - u32 workaround_line = osd_hw.workaround_line; + u32 workaround_line = 1; layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -6557,7 +6557,6 @@ static void osd_setting_blend0_input(u32 index, u32 workaround_line = 0; /* for g12a blend shift issue */ - workaround_line = osd_hw.workaround_line; layer_blend = &(blending->layer_blend); if (index == OSD1) { @@ -6600,12 +6599,12 @@ static void osd_setting_blend1_input(u32 index, /* for g12a blend shift issue */ if (osd_hw.hdr_used) - workaround_line = osd_hw.workaround_line; + workaround_line = 1; else { if (blending->layer_cnt == 2) workaround_line = 0; else - workaround_line = osd_hw.workaround_line; + workaround_line = 1; } layer_blend = &(blending->layer_blend); @@ -7672,101 +7671,6 @@ static bool set_old_hwc_freescale(u32 index) return false; } -#if 0 -static bool set_old_hwc_freescale(u32 index) -{ - u32 x_start, x_end, y_start, y_end; - u32 width_src = 0, width_dst = 0, height_src = 0, height_dst = 0; - u32 width, height; - u32 screen_ratio_w, screen_ratio_h; - - width_src = osd_hw.disp_info.background_w; - height_src = osd_hw.disp_info.background_h; - - width_dst = osd_hw.vinfo_width; - height_dst = osd_hw.vinfo_height; - screen_ratio_w = (osd_hw.disp_info.position_w << OSD_CALC) - / osd_hw.disp_info.background_w; - screen_ratio_h = (osd_hw.disp_info.position_h << OSD_CALC) - / osd_hw.disp_info.background_h; - osd_log_dbg("width_src:%d,%d\n", - width_src, height_src); - osd_log_dbg("width_src:%d,%d\n", - width_dst, height_dst); - - width = osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start; - height = osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start; - osd_hw.free_dst_data[index].x_start = - (osd_hw.free_dst_data[index].x_start - * screen_ratio_w >> OSD_CALC); - osd_hw.free_dst_data[index].y_start = - (osd_hw.free_dst_data[index].y_start - * screen_ratio_h >> OSD_CALC); - width = (width * screen_ratio_w >> OSD_CALC); - height = (height * screen_ratio_h >> OSD_CALC); - - osd_hw.free_dst_data[index].x_start += - osd_hw.disp_info.position_x; - osd_hw.free_dst_data[index].x_end = - osd_hw.free_dst_data[index].x_start + width; - osd_hw.free_dst_data[index].y_start += - osd_hw.disp_info.position_y; - osd_hw.free_dst_data[index].y_end = - osd_hw.free_dst_data[index].y_start + height; - - if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_end - 1; - y_start = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_end - 1; - x_end = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_start - 1; - y_end = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_start - 1; - osd_hw.free_dst_data[index].x_start = x_start; - osd_hw.free_dst_data[index].y_start = y_start; - osd_hw.free_dst_data[index].x_end = x_end; - osd_hw.free_dst_data[index].y_end = y_end; - } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_end - 1; - x_end = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_start - 1; - osd_hw.free_dst_data[index].x_start = x_start; - osd_hw.free_dst_data[index].x_end = x_end; - } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_end - 1; - y_end = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_start - 1; - osd_hw.free_dst_data[index].y_start = y_start; - osd_hw.free_dst_data[index].y_end = y_end; - } - osd_log_dbg("free_dst_data: %x,%x,%x,%x\n", - osd_hw.free_dst_data[index].x_start, - osd_hw.free_dst_data[index].x_end, - osd_hw.free_dst_data[index].y_start, - osd_hw.free_dst_data[index].y_end); - if ((memcmp(&(osd_hw.free_src_data[index]), - &osd_hw.free_src_data_backup[index], - sizeof(struct pandata_s)) != 0) || - (memcmp(&(osd_hw.free_dst_data[index]), - &osd_hw.free_dst_data_backup[index], - sizeof(struct pandata_s)) != 0)) { - memcpy(&osd_hw.free_src_data_backup[index], - &osd_hw.free_src_data[index], - sizeof(struct pandata_s)); - memcpy(&osd_hw.free_dst_data_backup[index], - &osd_hw.free_dst_data[index], - sizeof(struct pandata_s)); - return true; - } else - return false; -} -#endif - static void osd_setting_old_hwc(void) { int index = OSD1; @@ -8498,13 +8402,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.disp_info.position_h = 1080; osd_hw.vinfo_width = 1920; osd_hw.vinfo_height = 1080; - osd_hw.workaround_line = 0; - if ((osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12A) || - ((osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12B) && - is_meson_rev_a())) - osd_hw.workaround_line = 1; + for (idx = 0; idx < osd_hw.osd_meson_dev.osd_count; idx++) { osd_hw.premult_en[idx] = 0; osd_hw.osd_afbcd[idx].format = COLOR_INDEX_32_ABGR; From aa41df845eaf23d5eae19f019bd8cc04ba58d773 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 30 Nov 2018 15:55:52 +0800 Subject: [PATCH 0489/1060] osd: osd: recovey mode always blank [1/1] PD#TV-1287 Problem: recovey mode always blank Solution: set right condition to enable free_scale Verify: verified on P321 board Change-Id: I2f70b9c5436b30156f157a3297a11a2ef1cfec67 Signed-off-by: Jian Cao Conflicts: drivers/amlogic/media/osd/osd_hw.c --- drivers/amlogic/media/osd/osd_hw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 8cfb51fd37a4..1924bfa57ef4 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -2442,7 +2442,10 @@ static void osd_set_free_scale_enable_mode1(u32 index, u32 enable) void osd_set_free_scale_enable_hw(u32 index, u32 enable) { - if (osd_hw.free_scale_mode[index] && (index != OSD4)) { + if (osd_hw.free_scale_mode[index] + && (osd_hw.osd_meson_dev.has_viu2 ? + ((index != osd_hw.osd_meson_dev.viu2_index) ? + 1 : 0) : 1)) { osd_set_free_scale_enable_mode1(index, enable); if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) { u32 height_dst, height_src; From 8a0cfce5105db5c575217f05c00f22699b9905cb Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Wed, 16 Jan 2019 05:12:00 +0800 Subject: [PATCH 0490/1060] vpp: add two layers support for each chips [1/6] PD#SWPL-85 Problem: Need support two video layers feature Solution: 1.Add vd2 mif config 2.Add vd2 pps calculation and config 3.Add vd2 axis/crop/screen mode interface by sysfs and ioctl 4.Add layer query/alloc/free interface Verify: Verify on U212 Change-Id: I71fc9ab2ae0230c3e84c4b790e77d2c790951642 Signed-off-by: Brian Zhu Conflicts: drivers/amlogic/media/video_sink/video.c drivers/amlogic/media/video_sink/video_keeper.c drivers/amlogic/media/video_sink/video_priv.h drivers/amlogic/media/video_sink/vpp.c include/linux/amlogic/media/video_sink/video.h include/linux/amlogic/media/video_sink/vpp.h --- drivers/amlogic/media/video_sink/video.c | 40 +++++--------------- drivers/amlogic/media/video_sink/vpp.c | 19 +++++++++- include/linux/amlogic/media/utils/amstream.h | 25 ++++++++++++ 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index e91c55b0dd39..42328cdcf26a 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -4029,6 +4029,9 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) memcpy(&gPic_info[0], &vf->pic_mode, sizeof(struct vframe_pic_mode_s)); + if (iret == VppFilter_Success_and_Changed) + video_property_changed = 1; + /* apply new vpp settings */ frame_par_ready_to_set = 1; @@ -7839,33 +7842,6 @@ SET_FILTER: u32 set_value = 0; force_flush |= vpp_zorder_check(); - /* for sr core0, put it between prebld & pps as default */ - if (cur_frame_par && - (cur_frame_par->sr_core_support & - SUPER_CORE0_SUPPORT)) - if (cur_frame_par->sr0_position) - vpp_misc_set |= - PREBLD_SR0_VD1_SCALER; - else - vpp_misc_set &= - ~SR0_AFTER_DNLP; - else - vpp_misc_set |= - PREBLD_SR0_VD1_SCALER; - /* for sr core1, put it before post blend as default */ - if (cur_frame_par && - (cur_frame_par->sr_core_support & - SUPER_CORE1_SUPPORT)) - if (cur_frame_par->sr1_position) - vpp_misc_set |= - DNLP_SR1_CM; - else - vpp_misc_set &= - ~SR1_AFTER_POSTBLEN; - else - vpp_misc_set |= - DNLP_SR1_CM; - /* for sr core0, put it between prebld & pps as default */ if (cur_frame_par && (cur_frame_par->sr_core_support & @@ -9181,7 +9157,12 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) put_user(disable_videopip, (u32 __user *)argp); break; case AMSTREAM_IOC_GET_VIDEO_DISABLE: - put_user(disable_video, (u32 __user *)argp); + if (layer->layer_id == 0) + put_user(disable_video, (u32 __user *)argp); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + put_user(disable_videopip, (u32 __user *)argp); +#endif break; case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: @@ -13120,9 +13101,6 @@ MODULE_PARM_DESC(underflow, "\n Underflow count\n"); module_param(next_peek_underflow, uint, 0664); MODULE_PARM_DESC(skip, "\n Underflow count\n"); -module_param(hdmiin_frame_check, uint, 0664); -MODULE_PARM_DESC(hdmiin_frame_check, "\n hdmiin_frame_check\n"); - module_param(step_enable, uint, 0664); MODULE_PARM_DESC(step_enable, "\n step_enable\n"); diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 1c89853f8c85..93787f418a7c 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -2976,7 +2976,10 @@ int vpp_set_filters( if (!input) return ret; - WARN_ON(vinfo == NULL); + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + vskip_step = 2; + else + vskip_step = 1; /* use local var to avoid the input data be overwriten */ memcpy(&local_input, input, sizeof(struct disp_info_s)); @@ -3063,6 +3066,20 @@ int vpp_set_filters( if (vf->type & VIDTYPE_VSCALE_DISABLE) vpp_flags |= VPP_FLAG_VSCALE_DISABLE; +#ifndef TV_3D_FUNCTION_OPEN + if (vf->type & VIDTYPE_COMPRESS) { + src_width = vf->compWidth; + src_height = vf->compHeight; + } else { + src_width = vf->width; + src_height = vf->height; + } +#endif + + if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) + && !disable_adapted) { + if (vf->pic_mode.screen_mode != 0xff) + wide_mode = vf->pic_mode.screen_mode; if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) && !disable_adapted) { diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index 1343d436ffb2..0d690f28fc18 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -119,6 +119,31 @@ #define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) #define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) +#define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT _IOR((_A_M), 0x2b, int) +#define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT _IOW((_A_M), 0x2c, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_DISABLE _IOR((_A_M), 0x2d, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_DISABLE _IOW((_A_M), 0x2e, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_AXIS _IOR((_A_M), 0x2f, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_AXIS _IOW((_A_M), 0x30, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_CROP _IOR((_A_M), 0x31, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_CROP _IOW((_A_M), 0x32, int) +#define AMSTREAM_IOC_GET_PIP_SCREEN_MODE _IOR((_A_M), 0x33, int) +#define AMSTREAM_IOC_SET_PIP_SCREEN_MODE _IOW((_A_M), 0x34, int) +#define AMSTREAM_IOC_GET_PIP_ZORDER _IOW((_A_M), 0x35, unsigned int) +#define AMSTREAM_IOC_SET_PIP_ZORDER _IOW((_A_M), 0x36, unsigned int) + +#define AMSTREAM_IOC_GET_ZORDER _IOW((_A_M), 0x37, unsigned int) +#define AMSTREAM_IOC_SET_ZORDER _IOW((_A_M), 0x38, unsigned int) + +#define AMSTREAM_IOC_QUERY_LAYER _IOW((_A_M), 0x39, unsigned int) +#define AMSTREAM_IOC_ALLOC_LAYER _IOW((_A_M), 0x3a, unsigned int) +#define AMSTREAM_IOC_FREE_LAYER _IOW((_A_M), 0x3b, unsigned int) + +/* VPP.3D IOCTL command list^M */ +#define AMSTREAM_IOC_SET_3D_TYPE _IOW((_A_M), 0x3c, unsigned int) +#define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) +#define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) + #define AMSTREAM_IOC_APTS _IOR((_A_M), 0x40, int) #define AMSTREAM_IOC_VPTS _IOR((_A_M), 0x41, int) #define AMSTREAM_IOC_PCRSCR _IOR((_A_M), 0x42, int) From e7e934364a8bd8e3dc953e9ecc3dff7269ae9a9b Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 18 Jan 2019 03:25:21 +0800 Subject: [PATCH 0491/1060] vpp: add osd and video zorder control [2/6] PD#SWPL-85 Problem: Upper layer need control osd and video layer zorder Solution: 1.Add video layer zorder interface by sysfs and ioctl 2.Switch the osd and video layer order in vsync Verify: Verify on U212 Change-Id: Ic50e81784b865cc57e4ab9a63d74806f7a8721cf Signed-off-by: Brian Zhu Conflicts: drivers/amlogic/media/video_sink/video.c include/linux/amlogic/media/video_sink/vpp.h --- drivers/amlogic/media/video_sink/video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 42328cdcf26a..1d2300c77497 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -456,6 +456,8 @@ static u32 reference_zorder = 128; static s32 black_threshold_width = 20; static s32 black_threshold_height = 30; +static u32 reference_zorder = 128; + #define MAX_ZOOM_RATIO 300 #define VPP_PREBLEND_VD_V_END_LIMIT 2304 From e5136d971e4616701f27046f645d7ce8d2de7611 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Fri, 15 Feb 2019 16:52:52 +0800 Subject: [PATCH 0492/1060] osd: add viu2 fence support [1/1] PD#SWPL-6384 Problem: viu2 not support fence Solution: add viu2 fence support. Verify: test pass on tl1 Change-Id: I94a5e483c88cace79b7386bb918c203ada6b8274 Signed-off-by: Pengcheng Chen Conflicts: drivers/amlogic/media/osd/osd_hw.c --- drivers/amlogic/media/osd/osd.h | 21 +- drivers/amlogic/media/osd/osd_debug.c | 4 +- drivers/amlogic/media/osd/osd_drm.c | 12 +- drivers/amlogic/media/osd/osd_fb.c | 179 ++--- drivers/amlogic/media/osd/osd_hw.c | 937 +++++++++++++++++--------- drivers/amlogic/media/osd/osd_hw.h | 27 +- 6 files changed, 696 insertions(+), 484 deletions(-) diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 8003c5183305..404c53a2bdc6 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -106,7 +106,6 @@ enum color_index_e { #define FBIOPUT_OSD_CURSOR \ _IOWR(FB_IOC_MAGIC, 0x0, struct fb_cursor_user) - /* OSD color definition */ #define KEYCOLOR_FLAG_TARGET 1 #define KEYCOLOR_FLAG_ONHOLD 2 @@ -114,6 +113,8 @@ enum color_index_e { #define HW_OSD_COUNT 4 #define OSD_BLEND_LAYERS 4 +#define VIU_COUNT 2 + /* OSD block definition */ #define HW_OSD_BLOCK_COUNT 4 #define HW_OSD_BLOCK_REG_COUNT (HW_OSD_BLOCK_COUNT*2) @@ -707,7 +708,7 @@ struct hw_para_s { u32 scan_mode[HW_OSD_COUNT]; u32 order[HW_OSD_COUNT]; u32 premult_en[HW_OSD_COUNT]; - struct display_flip_info_s disp_info; + struct display_flip_info_s disp_info[VIU_COUNT]; struct osd_3d_mode_s mode_3d[HW_OSD_COUNT]; u32 updated[HW_OSD_COUNT]; /* u32 block_windows[HW_OSD_COUNT][HW_OSD_BLOCK_REG_COUNT]; */ @@ -722,7 +723,7 @@ struct hw_para_s { int use_h_filter_mode[HW_OSD_COUNT]; int use_v_filter_mode[HW_OSD_COUNT]; struct hw_list_s reg[HW_REG_INDEX_MAX]; - u32 field_out_en; + u32 field_out_en[VIU_COUNT]; u32 scale_workaround; u32 fb_for_4k2k; u32 antiflicker_mode; @@ -734,21 +735,21 @@ struct hw_para_s { struct osd_device_data_s osd_meson_dev; u32 urgent[HW_OSD_COUNT]; u32 osd_deband_enable; - u32 osd_fps; - u32 osd_fps_start; + u32 osd_fps[VIU_COUNT]; + u32 osd_fps_start[VIU_COUNT]; u32 osd_display_debug; ulong screen_base[HW_OSD_COUNT]; ulong screen_size[HW_OSD_COUNT]; ulong screen_base_backup[HW_OSD_COUNT]; ulong screen_size_backup[HW_OSD_COUNT]; - u32 vinfo_width; - u32 vinfo_height; + u32 vinfo_width[VIU_COUNT]; + u32 vinfo_height[VIU_COUNT]; u32 fb_drvier_probe; u32 afbc_force_reset; u32 afbc_regs_backup; u32 afbc_status_err_reset; u32 afbc_use_latch; - u32 hwc_enable; + u32 hwc_enable[VIU_COUNT]; u32 osd_use_latch[HW_OSD_COUNT]; u32 hw_cursor_en; u32 hw_rdma_en; @@ -761,8 +762,8 @@ struct hw_para_s { u32 viu_type; u32 line_n_rdma; struct hw_debug_s osd_debug; - int out_fence_fd; + int out_fence_fd[VIU_COUNT]; int in_fd[HW_OSD_COUNT]; - struct osd_fence_fun_s osd_fence[2]; + struct osd_fence_fun_s osd_fence[VIU_COUNT][2]; }; #endif /* _OSD_H_ */ diff --git a/drivers/amlogic/media/osd/osd_debug.c b/drivers/amlogic/media/osd/osd_debug.c index 701da240af6e..c456a34543b0 100644 --- a/drivers/amlogic/media/osd/osd_debug.c +++ b/drivers/amlogic/media/osd/osd_debug.c @@ -66,7 +66,9 @@ static void osd_debug_dump_value(void) osd_log_info("--- OSD ---\n"); osd_log_info("bot_type: %d\n", hwpara->bot_type); - osd_log_info("field_out_en: %d\n", hwpara->field_out_en); + osd_log_info("field_out_en: %d\n", hwpara->field_out_en[VIU1]); + if (osd_hw.osd_meson_dev.has_viu2) + osd_log_info("field_out_en: %d\n", hwpara->field_out_en[VIU2]); if (hwpara->osd_meson_dev.osd_ver == OSD_HIGH_ONE) { struct hw_osd_blending_s *blend_para = NULL; diff --git a/drivers/amlogic/media/osd/osd_drm.c b/drivers/amlogic/media/osd/osd_drm.c index d2cb62783e21..3732b201d41d 100644 --- a/drivers/amlogic/media/osd/osd_drm.c +++ b/drivers/amlogic/media/osd/osd_drm.c @@ -563,11 +563,13 @@ static ssize_t osd_hwc_enable_read_file(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { + struct seq_file *s = file->private_data; + int osd_id = *(int *)s; char buf[128]; ssize_t len; unsigned int hwc_enable = 0; - osd_get_hwc_enable(&hwc_enable); + osd_get_hwc_enable(osd_id, &hwc_enable); len = snprintf(buf, 128, "%d\n", hwc_enable); return simple_read_from_buffer(userbuf, count, ppos, buf, len); } @@ -576,6 +578,8 @@ static ssize_t osd_hwc_enable_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { + struct seq_file *s = file->private_data; + int osd_id = *(int *)s; char buf[128]; unsigned int hwc_enable = 0; int ret = 0; @@ -586,7 +590,7 @@ static ssize_t osd_hwc_enable_write_file(struct file *file, buf[count] = 0; ret = kstrtoint(buf, 0, &hwc_enable); osd_log_info("hwc enable: %d\n", hwc_enable); - osd_set_hwc_enable(hwc_enable); + osd_set_hwc_enable(osd_id, hwc_enable); return count; } @@ -594,6 +598,8 @@ static ssize_t osd_do_hwc_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { + struct seq_file *s = file->private_data; + int osd_id = *(int *)s; char buf[128]; unsigned int do_hwc = 0; int ret = 0; @@ -605,7 +611,7 @@ static ssize_t osd_do_hwc_write_file(struct file *file, ret = kstrtoint(buf, 0, &do_hwc); osd_log_info("do_hwc: %d\n", do_hwc); if (do_hwc) - osd_do_hwc(); + osd_do_hwc(osd_id); return count; } diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index 666e462a1479..c6748d489f0b 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -735,10 +735,13 @@ static int osd_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int osd_set_par(struct fb_info *info) { - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; struct osd_fb_dev_s *fbdev = (struct osd_fb_dev_s *)info->par; struct osd_ctl_s *osd_ctrl = &fbdev->osd_ctl; u32 virt_end_x, virt_end_y; + u32 output_index; + + output_index = get_output_device_id(fbdev->fb_index); if (fbdev->fb_index <= OSD3) { vinfo = get_current_vinfo(); @@ -747,7 +750,9 @@ static int osd_set_par(struct fb_info *info) return -1; } } else { +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE vinfo = get_current_vinfo2(); +#endif if (!vinfo) { osd_log_err("current vinfo NULL\n"); return -1; @@ -932,7 +937,7 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) arg & 0xffff ? 1 : 0); break; case FBIOGET_OSD_FLUSH_RATE: - osd_get_flush_rate_hw(&flush_rate); + osd_get_flush_rate_hw(info->node, &flush_rate); if (copy_to_user(argp, &flush_rate, sizeof(u32))) return -EFAULT; break; @@ -1142,12 +1147,12 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) #endif break; case FBIOPUT_OSD_HWC_ENABLE: - osd_set_hwc_enable(hwc_enable); + osd_set_hwc_enable(info->node, hwc_enable); ret = 0; break; case FBIOPUT_OSD_DO_HWC: do_hwc_cmd.out_fen_fd = - osd_sync_do_hwc(&do_hwc_cmd); + osd_sync_do_hwc(info->node, &do_hwc_cmd); ret = copy_to_user(argp, &do_hwc_cmd, sizeof(struct do_hwc_cmd_s)); @@ -1968,13 +1973,14 @@ static int osd_cursor(struct fb_info *fbi, struct fb_cursor *var) { s16 startx = 0, starty = 0; struct osd_fb_dev_s *fb_dev = gp_fbdev_list[1]; + u32 output_index; if (fb_dev) { startx = fb_dev->osd_ctl.disp_start_x; starty = fb_dev->osd_ctl.disp_start_y; } - - if (osd_hw.hwc_enable) + output_index = get_output_device_id(fbi->node); + if (osd_hw.hwc_enable[output_index]) osd_cursor_hw_no_scale(fbi->node, (s16)var->hot.x, (s16)var->hot.y, (s16)startx, (s16)starty, fbi->var.xres, fbi->var.yres); @@ -2067,9 +2073,9 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, if ((!strcmp(vinfo->name, "invalid")) || (!strcmp(vinfo->name, "null"))) return -1; - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->field_height; - osd_hw.field_out_en = is_interlaced(vinfo); + osd_hw.vinfo_width[VIU1] = vinfo->width; + osd_hw.vinfo_height[VIU1] = vinfo->field_height; + osd_hw.field_out_en[VIU1] = is_interlaced(vinfo); switch (cmd) { case VOUT_EVENT_MODE_CHANGE: set_osd_logo_freescaler(); @@ -2078,7 +2084,7 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, set_reset_rdma_trigger_line(); if ((osd_meson_dev.osd_ver == OSD_NORMAL) || (osd_meson_dev.osd_ver == OSD_SIMPLE) - || (osd_hw.hwc_enable == 0)) { + || (osd_hw.hwc_enable[VIU1] == 0)) { for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { fb_dev = gp_fbdev_list[i]; if (fb_dev == NULL) @@ -2109,7 +2115,7 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, case VOUT_EVENT_OSD_DISP_AXIS: if ((osd_meson_dev.osd_ver == OSD_NORMAL) || (osd_meson_dev.osd_ver == OSD_SIMPLE) - || (osd_hw.hwc_enable == 0)) { + || (osd_hw.hwc_enable[VIU1] == 0)) { disp_rect = (struct disp_rect_s *)para; for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { @@ -2160,111 +2166,6 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, return 0; } -#if 0 -int osd_notify_callback(struct notifier_block *block, unsigned long cmd, - void *para) -{ - struct vinfo_s *vinfo; - struct osd_fb_dev_s *fb_dev; - int i, blank; - struct disp_rect_s *disp_rect; - - vinfo = get_current_vinfo(); - if (!vinfo) { - osd_log_err("current vinfo NULL\n"); - return -1; - } - osd_log_info("current vmode=%s, cmd: 0x%lx\n", - vinfo->name, cmd); - if ((!strcmp(vinfo->name, "invalid")) || - (!strcmp(vinfo->name, "null"))) - return -1; - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->field_height; - osd_hw.field_out_en = is_interlaced(vinfo); - switch (cmd) { - case VOUT_EVENT_MODE_CHANGE: - set_osd_logo_freescaler(); - for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { - fb_dev = gp_fbdev_list[i]; - if (fb_dev == NULL) - continue; - set_default_display_axis(&fb_dev->fb_info->var, - &fb_dev->osd_ctl, vinfo); - console_lock(); - osddev_update_disp_axis(fb_dev, 1); - if ((osd_meson_dev.osd_ver == OSD_NORMAL) - || (osd_meson_dev.osd_ver == OSD_SIMPLE)) - osd_set_antiflicker_hw(DEV_OSD1, vinfo, - gp_fbdev_list - [DEV_OSD1]->fb_info->var.yres); - else if (osd_meson_dev.osd_ver == OSD_HIGH_ONE) - osd_set_antiflicker_hw(i, vinfo, - gp_fbdev_list[i]->fb_info->var.yres); - osd_reg_write(VPP_POSTBLEND_H_SIZE, vinfo->width); - console_unlock(); - } - break; - case VOUT_EVENT_OSD_BLANK: - blank = *(int *)para; - for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { - fb_dev = gp_fbdev_list[i]; - if (fb_dev == NULL) - continue; - console_lock(); - osd_blank(blank, fb_dev->fb_info); - console_unlock(); - } - break; - case VOUT_EVENT_OSD_DISP_AXIS: - disp_rect = (struct disp_rect_s *)para; - for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { - if (!disp_rect) - break; - - /* vout serve send only two layer axis */ - if (i >= 2) - break; - - fb_dev = gp_fbdev_list[i]; - /* - * if osd layer preblend, - * it's position is controlled by vpp. - if (fb_dev->preblend_enable) - break; - */ - fb_dev->osd_ctl.disp_start_x = disp_rect->x; - fb_dev->osd_ctl.disp_start_y = disp_rect->y; - osd_log_dbg("set disp axis: x:%d y:%d w:%d h:%d\n", - disp_rect->x, disp_rect->y, - disp_rect->w, disp_rect->h); - if (disp_rect->x + disp_rect->w > vinfo->width) - fb_dev->osd_ctl.disp_end_x = vinfo->width - 1; - else - fb_dev->osd_ctl.disp_end_x = - fb_dev->osd_ctl.disp_start_x + - disp_rect->w - 1; - if (disp_rect->y + disp_rect->h > vinfo->height) - fb_dev->osd_ctl.disp_end_y = vinfo->height - 1; - else - fb_dev->osd_ctl.disp_end_y = - fb_dev->osd_ctl.disp_start_y + - disp_rect->h - 1; - disp_rect++; - osd_log_dbg("new disp axis: x0:%d y0:%d x1:%d y1:%d\n", - fb_dev->osd_ctl.disp_start_x, - fb_dev->osd_ctl.disp_start_y, - fb_dev->osd_ctl.disp_end_x, - fb_dev->osd_ctl.disp_end_y); - console_lock(); - osddev_update_disp_axis(fb_dev, 0); - console_unlock(); - } - break; - } - return 0; -} -#endif int osd_notify_callback_viu2(struct notifier_block *block, unsigned long cmd, void *para) { @@ -2285,6 +2186,8 @@ int osd_notify_callback_viu2(struct notifier_block *block, unsigned long cmd, vinfo->name, cmd); if (!strcmp(vinfo->name, "invalid")) return -1; + osd_hw.vinfo_width[VIU2] = vinfo->width; + osd_hw.vinfo_height[VIU2] = vinfo->field_height; i = osd_meson_dev.viu2_index; switch (cmd) { case VOUT_EVENT_MODE_CHANGE: @@ -2919,9 +2822,10 @@ static ssize_t show_flush_rate(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); u32 flush_rate = 0; - osd_get_flush_rate_hw(&flush_rate); + osd_get_flush_rate_hw(fb_info->node, &flush_rate); return snprintf(buf, PAGE_SIZE, "flush_rate:[%d]\n", flush_rate); } @@ -2973,15 +2877,22 @@ static ssize_t store_antiflicker(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; unsigned int osd_antiflicker = 0; struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; + u32 output_index; ret = kstrtoint(buf, 0, &res); osd_antiflicker = res; - vinfo = get_current_vinfo(); + output_index = get_output_device_id(fb_info->node); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif if (!vinfo) { osd_log_err("get current vinfo NULL\n"); return 0; @@ -3097,9 +3008,10 @@ static ssize_t show_osd_fps(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); u32 osd_fps; - osd_get_fps(&osd_fps); + osd_get_fps(fb_info->node, &osd_fps); return snprintf(buf, 40, "%d\n", osd_fps); } @@ -3108,11 +3020,12 @@ static ssize_t store_osd_fps(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); - osd_set_fps(res); + osd_set_fps(fb_info->node, res); return count; } @@ -3199,9 +3112,10 @@ static ssize_t show_osd_background_size(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); struct display_flip_info_s disp_info; - osd_get_background_size(&disp_info); + osd_get_background_size(fb_info->node, &disp_info); return snprintf(buf, 80, "%d %d %d %d %d %d %d %d\n", disp_info.background_w, disp_info.background_h, @@ -3217,12 +3131,14 @@ static ssize_t store_osd_background_size(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int parsed[8]; - if (likely(parse_para(buf, 8, parsed) == 8)) { + if (likely(parse_para(buf, 8, parsed) == 8)) osd_set_background_size( + fb_info->node, (struct display_flip_info_s *)&parsed); - } else + else osd_log_err("set background size error\n"); return count; @@ -3285,9 +3201,10 @@ static ssize_t show_osd_hwc_enalbe(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); u32 hwc_enalbe; - osd_get_hwc_enable(&hwc_enalbe); + osd_get_hwc_enable(fb_info->node, &hwc_enalbe); return snprintf(buf, 40, "%d\n", hwc_enalbe); } @@ -3296,13 +3213,14 @@ static ssize_t store_osd_hwc_enalbe(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); if (ret < 0) return -EINVAL; - osd_set_hwc_enable(res); + osd_set_hwc_enable(fb_info->node, res); return count; } @@ -3311,6 +3229,7 @@ static ssize_t store_do_hwc(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; @@ -3318,7 +3237,7 @@ static ssize_t store_do_hwc(struct device *device, if (ret < 0) return -EINVAL; if (res) - osd_do_hwc(); + osd_do_hwc(fb_info->node); return count; } @@ -3352,13 +3271,14 @@ static ssize_t store_osd_single_step_mode(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); if (ret < 0) return -EINVAL; - osd_set_single_step_mode(res); + osd_set_single_step_mode(fb_info->node, res); return count; } @@ -3367,13 +3287,14 @@ static ssize_t store_osd_single_step(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); if (ret < 0) return -EINVAL; - osd_set_single_step(res); + osd_set_single_step(fb_info->node, res); return count; } diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 1924bfa57ef4..4a7d7c725bc0 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -324,61 +324,67 @@ static int vpp_blend_setting_default(u32 index); #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE /* sync fence relative varible. */ -static int timeline_created; -static void *osd_timeline; -static u32 cur_streamline_val; +static int timeline_created[VIU_COUNT]; +static void *osd_timeline[VIU_COUNT]; +static u32 cur_streamline_val[VIU_COUNT]; /* thread control part */ -struct kthread_worker buffer_toggle_worker; -struct task_struct *buffer_toggle_thread; -struct kthread_work buffer_toggle_work; -struct list_head post_fence_list; -struct mutex post_fence_list_lock; -struct osd_layers_fence_map_s map_layers; +struct kthread_worker buffer_toggle_worker[VIU_COUNT]; +struct task_struct *buffer_toggle_thread[VIU_COUNT]; +struct kthread_work buffer_toggle_work[VIU_COUNT]; +struct list_head post_fence_list[VIU_COUNT]; +struct mutex post_fence_list_lock[VIU_COUNT]; /*post fence mutex*/ +struct osd_layers_fence_map_s map_layers[VIU_COUNT]; struct file *displayed_bufs[HW_OSD_COUNT]; static void osd_pan_display_single_fence( struct osd_fence_map_s *fence_map); static void osd_pan_display_layers_fence( struct osd_layers_fence_map_s *fence_map); +static void osd_pan_display_single_fence_viu2( + struct osd_fence_map_s *fence_map); +static void osd_pan_display_layers_fence_viu2( + struct osd_layers_fence_map_s *fence_map); -static void *osd_timeline_create(void) +static void *osd_timeline_create(u32 output_index) { - const char *tlName = "osd_timeline"; + char tlname[32] = {}; - if (osd_timeline == NULL) { - if (osd_hw.hwc_enable) + sprintf(tlname, "osd_timeline_%d", output_index); + if (!osd_timeline[output_index]) { + if (osd_hw.hwc_enable[output_index]) /* present fence */ - cur_streamline_val = 0; + cur_streamline_val[output_index] = 0; else - cur_streamline_val = 1; - osd_timeline = aml_sync_create_timeline(tlName); + cur_streamline_val[output_index] = 1; + osd_timeline[output_index] = aml_sync_create_timeline(tlname); osd_tprintk("osd timeline create\n"); } - - return osd_timeline; + return osd_timeline[output_index]; } -static int osd_timeline_create_fence(void) +static int osd_timeline_create_fence(u32 output_index) { int out_fence_fd = -1; u32 pt_val = 0; - pt_val = cur_streamline_val + 1; - out_fence_fd = aml_sync_create_fence(osd_timeline, pt_val); + pt_val = cur_streamline_val[output_index] + 1; + out_fence_fd = aml_sync_create_fence + (osd_timeline[output_index], pt_val); osd_tprintk("osd created out pt:%d, fence_fd:%d\n", pt_val, out_fence_fd); if (out_fence_fd >= 0) - cur_streamline_val++; + cur_streamline_val[output_index]++; else pr_info("create fence returned %d", out_fence_fd); return out_fence_fd; } -static void osd_timeline_increase(void) +static void osd_timeline_increase(u32 output_index) { - aml_sync_inc_timeline(osd_timeline, 1); - osd_tprintk("osd out timeline inc\n"); + aml_sync_inc_timeline(osd_timeline[output_index], 1); + osd_tprintk("osd out timeline %d inc\n", output_index); + } static struct fence *osd_get_fenceobj(int fencefd) @@ -795,12 +801,40 @@ static void osd_vpu_power_on_viu2(void) #endif } -static int get_osd_hwc_type(void) +u32 get_output_device_id(u32 index) +{ + u32 output_index = VIU1; + + if (osd_hw.osd_meson_dev.has_viu2) { + switch (osd_hw.osd_meson_dev.cpu_id) { + case __MESON_CPU_MAJOR_ID_G12A: + case __MESON_CPU_MAJOR_ID_G12B: + if (index == osd_hw.osd_meson_dev.viu2_index) + output_index = VIU2; + else + output_index = VIU1; + break; + case __MESON_CPU_MAJOR_ID_TL1: + if (index == osd_hw.osd_meson_dev.viu2_index) + output_index = VIU2; + else + output_index = VIU1; + break; + default: + break; + } + } + return output_index; +} + +static int get_osd_hwc_type(u32 index) { int ret = 0; + u32 output_index; + output_index = get_output_device_id(index); /* new hwcomposer enable */ - if (osd_hw.hwc_enable) { + if (osd_hw.hwc_enable[output_index]) { if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) ret = OSD_G12A_NEW_HWC; else @@ -830,10 +864,10 @@ static void osd_toggle_buffer_single(struct kthread_work *work) struct osd_fence_map_s *data, *next; struct list_head saved_list; - mutex_lock(&post_fence_list_lock); - saved_list = post_fence_list; - list_replace_init(&post_fence_list, &saved_list); - mutex_unlock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[VIU1]); + saved_list = post_fence_list[VIU1]; + list_replace_init(&post_fence_list[VIU1], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU1]); list_for_each_entry_safe(data, next, &saved_list, list) { osd_pan_display_single_fence(data); list_del(&data->list); @@ -846,10 +880,10 @@ static void osd_toggle_buffer_layers(struct kthread_work *work) struct osd_layers_fence_map_s *data, *next; struct list_head saved_list; - mutex_lock(&post_fence_list_lock); - saved_list = post_fence_list; - list_replace_init(&post_fence_list, &saved_list); - mutex_unlock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[VIU1]); + saved_list = post_fence_list[VIU1]; + list_replace_init(&post_fence_list[VIU1], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU1]); list_for_each_entry_safe(data, next, &saved_list, list) { osd_pan_display_layers_fence(data); list_del(&data->list); @@ -860,38 +894,94 @@ static void osd_toggle_buffer_layers(struct kthread_work *work) static void osd_toggle_buffer(struct kthread_work *work) { - osd_hw.osd_fence[osd_hw.hwc_enable]. - toggle_buffer_handler(work); + u32 hwc_enable; + + hwc_enable = osd_hw.hwc_enable[VIU1]; + if (osd_hw.osd_fence[VIU1][hwc_enable].toggle_buffer_handler) + osd_hw.osd_fence[VIU1][hwc_enable] + .toggle_buffer_handler(work); } -static int out_fence_create(int *release_fence_fd) +static void osd_toggle_buffer_single_viu2(struct kthread_work *work) +{ + struct osd_fence_map_s *data, *next; + struct list_head saved_list; + + mutex_lock(&post_fence_list_lock[VIU2]); + saved_list = post_fence_list[VIU2]; + list_replace_init(&post_fence_list[VIU2], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU2]); + list_for_each_entry_safe(data, next, &saved_list, list) { + osd_pan_display_single_fence_viu2(data); + list_del(&data->list); + kfree(data); + } +} + +static void osd_toggle_buffer_layers_viu2(struct kthread_work *work) +{ + struct osd_layers_fence_map_s *data, *next; + struct list_head saved_list; + + mutex_lock(&post_fence_list_lock[VIU2]); + saved_list = post_fence_list[VIU2]; + list_replace_init(&post_fence_list[VIU2], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU2]); + list_for_each_entry_safe(data, next, &saved_list, list) { + osd_pan_display_layers_fence_viu2(data); + list_del(&data->list); + kfree(data); + } +} + +static void osd_toggle_buffer_viu2(struct kthread_work *work) +{ + u32 hwc_enable; + + hwc_enable = osd_hw.hwc_enable[VIU2]; + if (osd_hw.osd_fence[VIU2][hwc_enable].toggle_buffer_handler) + osd_hw.osd_fence[VIU2][hwc_enable] + .toggle_buffer_handler(work); +} + +static int out_fence_create(u32 output_index, int *release_fence_fd) { int out_fence_fd = -1; struct sched_param param = {.sched_priority = 2}; + char toggle_thread_name[32] = {}; - if (!timeline_created) { + if (!timeline_created[output_index]) { /* timeline has not been created */ - if (osd_timeline_create()) { - kthread_init_worker(&buffer_toggle_worker); - buffer_toggle_thread = kthread_run( + if (osd_timeline_create(output_index)) { + kthread_init_worker + (&buffer_toggle_worker[output_index]); + sprintf(toggle_thread_name, + "aml_buf_toggle_%d", output_index); + buffer_toggle_thread[output_index] = kthread_run( kthread_worker_fn, - &buffer_toggle_worker, - "aml_buf_toggle"); - if (IS_ERR(buffer_toggle_thread)) { + &buffer_toggle_worker[output_index], + toggle_thread_name); + if (IS_ERR(buffer_toggle_thread[output_index])) { osd_log_err("create osd toggle kthread failed"); return -1; } - sched_setscheduler(buffer_toggle_thread, - SCHED_FIFO, ¶m); - kthread_init_work( - &buffer_toggle_work, osd_toggle_buffer); - timeline_created = 1; + sched_setscheduler(buffer_toggle_thread[output_index], + SCHED_FIFO, ¶m); + if (output_index == VIU1) + kthread_init_work( + &buffer_toggle_work[output_index], + osd_toggle_buffer); + else if (output_index == VIU2) + kthread_init_work( + &buffer_toggle_work[output_index], + osd_toggle_buffer_viu2); + timeline_created[output_index] = 1; } } /* hwc_enable disable create fence every time */ - if (!osd_hw.hwc_enable) { - out_fence_fd = osd_timeline_create_fence(); + if (!osd_hw.hwc_enable[output_index]) { + out_fence_fd = osd_timeline_create_fence(output_index); if (out_fence_fd < 0) { osd_log_err("fence obj create fail\n"); out_fence_fd = -1; @@ -900,15 +990,16 @@ static int out_fence_create(int *release_fence_fd) /* hwc_enable enable create fence * when first sync request called */ - if (osd_hw.out_fence_fd == -1) { - out_fence_fd = osd_timeline_create_fence(); + if (osd_hw.out_fence_fd[output_index] == -1) { + out_fence_fd = osd_timeline_create_fence(output_index); if (out_fence_fd < 0) { osd_log_err("fence obj create fail\n"); out_fence_fd = -1; } - osd_hw.out_fence_fd = out_fence_fd; - } else - out_fence_fd = osd_hw.out_fence_fd; + osd_hw.out_fence_fd[output_index] = out_fence_fd; + } else { + out_fence_fd = osd_hw.out_fence_fd[output_index]; + } } if (release_fence_fd) *release_fence_fd = out_fence_fd; @@ -920,17 +1011,19 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request) int out_fence_fd = -1; int buf_num = 0; int in_fence_fd = -1; + u32 output_index = 0; struct osd_fence_map_s *fence_map = kzalloc(sizeof(struct osd_fence_map_s), GFP_KERNEL); - osd_hw.hwc_enable = 0; + output_index = get_output_device_id(index); + osd_hw.hwc_enable[output_index] = 0; if (request->sync_req.magic == FB_SYNC_REQUEST_MAGIC) { buf_num = find_buf_num(yres, request->sync_req.yoffset); if (!fence_map) { osd_log_err("could not allocate osd_fence_map\n"); return -ENOMEM; } - mutex_lock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[output_index]); fence_map->op = 0xffffffff; fence_map->fb_index = index; fence_map->buf_num = buf_num; @@ -944,14 +1037,14 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request) fence_map->in_fence = osd_get_fenceobj( request->sync_req.in_fen_fd); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); } else { buf_num = find_buf_num(yres, request->sync_req_old.yoffset); if (!fence_map) { osd_log_err("could not allocate osd_fence_map\n"); return -ENOMEM; } - mutex_lock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[output_index]); fence_map->op = 0xffffffff; fence_map->fb_index = index; fence_map->buf_num = buf_num; @@ -964,11 +1057,12 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request) fence_map->in_fence = osd_get_fenceobj( request->sync_req_old.in_fen_fd); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); } - list_add_tail(&fence_map->list, &post_fence_list); - mutex_unlock(&post_fence_list_lock); - kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work); + list_add_tail(&fence_map->list, &post_fence_list[output_index]); + mutex_unlock(&post_fence_list_lock[output_index]); + kthread_queue_work(&buffer_toggle_worker[output_index], + &buffer_toggle_work[output_index]); if (in_fence_fd >= 0) __close_fd(current->files, in_fence_fd); return out_fence_fd; @@ -983,6 +1077,7 @@ static int sync_render_single_fence(u32 index, u32 yres, int out_fence_fd = -1; int buf_num = 0; u32 xoffset, yoffset; + u32 output_index = 0; struct osd_fence_map_s *fence_map = NULL; if (index > OSD1) @@ -995,7 +1090,8 @@ static int sync_render_single_fence(u32 index, u32 yres, osd_log_err("could not allocate osd_fence_map\n"); return -ENOMEM; } - mutex_lock(&post_fence_list_lock); + output_index = get_output_device_id(index); + mutex_lock(&post_fence_list_lock[output_index]); fence_map->op = 0xffffffff; fence_map->fb_index = index; fence_map->buf_num = buf_num; @@ -1023,11 +1119,12 @@ static int sync_render_single_fence(u32 index, u32 yres, osd_tprintk("direct render fence fd:%d\n", fence_map->in_fd); fence_map->in_fence = osd_get_fenceobj(fence_map->in_fd); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); /* Todo: */ - list_add_tail(&fence_map->list, &post_fence_list); - mutex_unlock(&post_fence_list_lock); - kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work); + list_add_tail(&fence_map->list, &post_fence_list[output_index]); + mutex_unlock(&post_fence_list_lock[output_index]); + kthread_queue_work(&buffer_toggle_worker[output_index], + &buffer_toggle_work[output_index]); request->out_fen_fd = out_fence_fd; __close_fd(current->files, request->in_fen_fd); return out_fence_fd; @@ -1040,13 +1137,15 @@ static int sync_render_layers_fence(u32 index, u32 yres, { int out_fence_fd = -1; s32 in_fence_fd; + u32 output_index = 0; struct osd_layers_fence_map_s *fence_map = NULL; if (index > OSD_MAX) return -1; + output_index = get_output_device_id(index); in_fence_fd = request->in_fen_fd; - mutex_lock(&post_fence_list_lock); - fence_map = &map_layers; + mutex_lock(&post_fence_list_lock[output_index]); + fence_map = &map_layers[output_index]; fence_map->cmd = LAYER_SYNC; fence_map->layer_map[index].fb_index = index; /* layer_map[index].enable will update if have blank ioctl */ @@ -1087,8 +1186,8 @@ static int sync_render_layers_fence(u32 index, u32 yres, /* no longer put list, will put them via do_hwc */ fence_map->layer_map[index].in_fence = osd_get_fenceobj(in_fence_fd); fence_map->layer_map[index].out_fd = - out_fence_create(&out_fence_fd); - mutex_unlock(&post_fence_list_lock); + out_fence_create(output_index, &out_fence_fd); + mutex_unlock(&post_fence_list_lock[output_index]); osd_log_dbg(MODULE_FENCE, "sync_render_layers_fence:osd%d: ind_fd=%d,out_fd=%d\n", fence_map->layer_map[index].fb_index, fence_map->layer_map[index].in_fd, @@ -1104,31 +1203,36 @@ int osd_sync_request_render(u32 index, u32 yres, u32 phys_addr, size_t len) { - int line; + int line, hwc_enable; + u32 output_index = 0; line = get_encp_line(); + output_index = get_output_device_id(index); osd_log_dbg2(MODULE_RENDER, "enter osd_sync_request_render:encp line=%d\n", line); if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V1) - osd_hw.hwc_enable = 0; + osd_hw.hwc_enable[output_index] = 0; else if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V2) - osd_hw.hwc_enable = 1; - if (index == OSD4) - osd_hw.viu_type = VIU2; - else - osd_hw.viu_type = VIU1; - osd_hw.osd_fence[osd_hw.hwc_enable].sync_fence_handler( - index, yres, request, phys_addr, len); + osd_hw.hwc_enable[output_index] = 1; + output_index = get_output_device_id(index); + hwc_enable = osd_hw.hwc_enable[output_index]; + + if (osd_hw.osd_fence[output_index][hwc_enable].sync_fence_handler) + osd_hw.osd_fence[output_index][hwc_enable] + .sync_fence_handler(index, yres, + request, phys_addr, len); return request->out_fen_fd; } -int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) +int osd_sync_do_hwc(u32 index, struct do_hwc_cmd_s *hwc_cmd) { int out_fence_fd = -1; struct osd_layers_fence_map_s *fence_map = NULL; int line; + u32 output_index = 0; + output_index = get_output_device_id(index); line = get_encp_line(); osd_log_dbg2(MODULE_RENDER, "enter osd_sync_do_hwc:encp line=%d\n", @@ -1137,15 +1241,15 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) sizeof(struct osd_layers_fence_map_s), GFP_KERNEL); if (!fence_map) return -ENOMEM; - osd_hw.hwc_enable = 1; - mutex_lock(&post_fence_list_lock); - memcpy(fence_map, &map_layers, - sizeof(struct osd_layers_fence_map_s)); + osd_hw.hwc_enable[output_index] = 1; + mutex_lock(&post_fence_list_lock[output_index]); + memcpy(fence_map, &map_layers[output_index], + sizeof(struct osd_layers_fence_map_s)); /* clear map_layers, need alloc next add_sync ioctl */ - memset(&map_layers, 0, - sizeof(struct osd_layers_fence_map_s)); + memset(&map_layers[output_index], 0, + sizeof(struct osd_layers_fence_map_s)); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); fence_map->disp_info.background_w = hwc_cmd->disp_info.background_w; fence_map->disp_info.background_h = @@ -1164,12 +1268,14 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) hwc_cmd->disp_info.position_h; fence_map->hdr_mode = hwc_cmd->hdr_mode; /* other info set via add_sync and blank ioctl */ - list_add_tail(&fence_map->list, &post_fence_list); + list_add_tail(&fence_map->list, &post_fence_list[output_index]); /* after do_hwc, clear osd_hw.out_fence_fd */ - if (timeline_created && osd_hw.out_fence_fd) - osd_hw.out_fence_fd = -1; - mutex_unlock(&post_fence_list_lock); - kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work); + if (timeline_created[output_index] && + osd_hw.out_fence_fd[output_index]) + osd_hw.out_fence_fd[output_index] = -1; + mutex_unlock(&post_fence_list_lock[output_index]); + kthread_queue_work(&buffer_toggle_worker[output_index], + &buffer_toggle_work[output_index]); if (get_logo_loaded()) { int logo_index; @@ -1243,7 +1349,7 @@ int osd_sync_request_render(u32 index, u32 yres, return -5566; } -int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) +int osd_sync_do_hwc(u32 output_index, struct do_hwc_cmd_s *hwc_cmd) { osd_log_err("osd_do_hwc not supported\n"); return -5566; @@ -1253,7 +1359,10 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) void osd_set_enable_hw(u32 index, u32 enable) { - if (osd_hw.hwc_enable) { + u32 output_index = 0; + + output_index = get_output_device_id(index); + if (osd_hw.hwc_enable[output_index]) { if (index > OSD_MAX) return; if ((osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE) @@ -1261,11 +1370,13 @@ void osd_set_enable_hw(u32 index, u32 enable) osd_enable_hw(index, enable); else { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - mutex_lock(&post_fence_list_lock); - map_layers.layer_map[index].fb_index = index; - map_layers.layer_map[index].enable = enable; - map_layers.cmd = BLANK_CMD; - mutex_unlock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[output_index]); + map_layers[output_index].layer_map[index] + .fb_index = index; + map_layers[output_index].layer_map[index] + .enable = enable; + map_layers[output_index].cmd = BLANK_CMD; + mutex_unlock(&post_fence_list_lock[output_index]); osd_log_dbg(MODULE_BASE, "osd_set_enable_hw: osd%d,enable=%d\n", index, enable); #endif @@ -1913,6 +2024,8 @@ s64 osd_wait_vsync_event(void) int is_interlaced(struct vinfo_s *vinfo) { + if (!vinfo) + return 0; if (vinfo->mode == VMODE_CVBS) return 1; if (vinfo->height != vinfo->field_height) @@ -1923,12 +2036,19 @@ int is_interlaced(struct vinfo_s *vinfo) int osd_set_scan_mode(u32 index) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; u32 data32 = 0x0; s32 y_end = 0; + u32 output_index; + output_index = get_output_device_id(index); osd_hw.scan_mode[index] = SCAN_MODE_PROGRESSIVE; - vinfo = get_current_vinfo(); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { osd_hw.scale_workaround = 0; @@ -1944,7 +2064,7 @@ int osd_set_scan_mode(u32 index) if ((vinfo->width == 720) && (vinfo->height == 480)) { if (osd_hw.free_scale_mode[index]) { - //osd_hw.field_out_en = 1; + osd_hw.field_out_en[output_index] = 1; switch (y_end) { case 719: osd_hw.bot_type = 2; @@ -1964,7 +2084,7 @@ int osd_set_scan_mode(u32 index) } else if ((vinfo->width == 720) && (vinfo->height == 576)) { if (osd_hw.free_scale_mode[index]) { - //osd_hw.field_out_en = 1; + osd_hw.field_out_en[output_index] = 1; switch (y_end) { case 719: osd_hw.bot_type = 2; @@ -1985,7 +2105,7 @@ int osd_set_scan_mode(u32 index) } else if ((vinfo->width == 1920) && (vinfo->height == 1080)) { if (osd_hw.free_scale_mode[index]) { - //osd_hw.field_out_en = 1; + osd_hw.field_out_en[output_index] = 1; switch (y_end) { case 719: osd_hw.bot_type = 1; @@ -2008,7 +2128,7 @@ int osd_set_scan_mode(u32 index) && (osd_hw.free_scale_enable[index])) if (!(osd_hw.osd_meson_dev.afbc_type)) osd_hw.scale_workaround = 1; - osd_hw.field_out_en = 0; + osd_hw.field_out_en[output_index] = 0; } else if (((vinfo->width == 720) && (vinfo->height == 480)) || ((vinfo->width == 720) @@ -2018,10 +2138,10 @@ int osd_set_scan_mode(u32 index) osd_v_filter_mode = 6; } if (osd_hw.free_scale_mode[index]) - osd_hw.field_out_en = 0; + osd_hw.field_out_en[output_index] = 0; } else { if (osd_hw.free_scale_mode[index]) - osd_hw.field_out_en = 0; + osd_hw.field_out_en[output_index] = 0; } } } @@ -2540,11 +2660,18 @@ void osd_set_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; s32 height; + u32 output_index; + output_index = get_output_device_id(index); if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { - vinfo = get_current_vinfo(); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { if (is_interlaced(vinfo)) { @@ -2580,15 +2707,17 @@ void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1) void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; s32 temp_y0, temp_y1; + u32 output_index; - #if 0 - if (osd_hw.hwc_enable && - (osd_hw.osd_display_debug != OSD_DISP_DEBUG)) - return; - #endif - vinfo = get_current_vinfo(); + output_index = get_output_device_id(index); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif mutex_lock(&osd_mutex); if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { @@ -2625,13 +2754,12 @@ void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) if (osd_hw.free_dst_data[index].y_end >= 2159) osd_set_dummy_data(index, 0xff); osd_update_window_axis = true; - if (osd_hw.hwc_enable && - (osd_hw.osd_display_debug == OSD_DISP_DEBUG)) - osd_setting_blend(); + if (osd_hw.hwc_enable[output_index] && + (osd_hw.osd_display_debug == OSD_DISP_DEBUG)) + osd_setting_blend(output_index); mutex_unlock(&osd_mutex); } - s32 osd_get_position_from_reg( u32 index, s32 *src_x_start, s32 *src_x_end, @@ -2777,6 +2905,7 @@ void osd_enable_hw(u32 index, u32 enable) { int i = 0; int count = (pxp_mode == 1)?3:WAIT_AFBC_READY_COUNT; + u32 output_index; if (index == 0) { osd_log_info("osd[%d] enable: %d (%s)\n", @@ -2788,8 +2917,8 @@ void osd_enable_hw(u32 index, u32 enable) /* reset viu 31bit ?? */ if (!osd_hw.enable[index] && - osd_hw.osd_afbcd[index].enable && enable - && (get_osd_hwc_type() != OSD_G12A_NEW_HWC)) { + osd_hw.osd_afbcd[index].enable && enable && + (get_osd_hwc_type(index) != OSD_G12A_NEW_HWC)) { spin_lock_irqsave(&osd_lock, lock_flags); if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) { osd_reg_write(VIU_SW_RESET, 0x80000000); @@ -2817,11 +2946,13 @@ void osd_enable_hw(u32 index, u32 enable) } osd_hw.enable[index] = enable; - if (get_osd_hwc_type() != OSD_G12A_NEW_HWC) { + output_index = get_output_device_id(index); + if (get_osd_hwc_type(index) != OSD_G12A_NEW_HWC) { add_to_update_list(index, OSD_ENABLE); osd_wait_vsync_hw(); - } else if (osd_hw.hwc_enable && osd_hw.osd_display_debug) - osd_setting_blend(); + } else if (osd_hw.hwc_enable[output_index] && + osd_hw.osd_display_debug) + osd_setting_blend(output_index); } void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable) @@ -2850,11 +2981,20 @@ void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable) osd_wait_vsync_hw(); } -void osd_get_flush_rate_hw(u32 *break_rate) +void osd_get_flush_rate_hw(u32 index, u32 *break_rate) { - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; + u32 output_index; - vinfo = get_current_vinfo(); + output_index = get_output_device_id(index); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif + if (!vinfo) + return; *break_rate = vinfo->sync_duration_num / vinfo->sync_duration_den; } @@ -3139,26 +3279,33 @@ void osd_set_deband(u32 osd_deband_enable) } -void osd_get_fps(u32 *osd_fps) +void osd_get_fps(u32 index, u32 *osd_fps) { - *osd_fps = osd_hw.osd_fps; + u32 output_index; + + output_index = get_output_device_id(index); + *osd_fps = osd_hw.osd_fps[output_index]; + } -void osd_set_fps(u32 osd_fps_start) +void osd_set_fps(u32 index, u32 osd_fps_start) { static int stime, etime; + u32 output_index; - osd_hw.osd_fps_start = osd_fps_start; + output_index = get_output_device_id(index); + osd_hw.osd_fps_start[output_index] = osd_fps_start; if (osd_fps_start) { /* start to calc fps */ stime = ktime_to_us(ktime_get()); - osd_hw.osd_fps = 0; + osd_hw.osd_fps[output_index] = 0; } else { /* stop to calc fps */ etime = ktime_to_us(ktime_get()); - osd_hw.osd_fps = (osd_hw.osd_fps * 1000000) + osd_hw.osd_fps[output_index] = + (osd_hw.osd_fps[output_index] * 1000000) / (etime - stime); - osd_log_info("osd fps:=%d\n", osd_hw.osd_fps); + osd_log_info("osd fps:=%d\n", osd_hw.osd_fps[output_index]); } } @@ -3172,16 +3319,22 @@ void osd_set_display_debug(u32 osd_display_debug_enable) osd_hw.osd_display_debug = osd_display_debug_enable; } -void osd_get_background_size(struct display_flip_info_s *disp_info) +void osd_get_background_size(u32 index, struct display_flip_info_s *disp_info) { - memcpy(disp_info, &osd_hw.disp_info, - sizeof(struct display_flip_info_s)); + u32 output_index; + + output_index = get_output_device_id(index); + memcpy(disp_info, &osd_hw.disp_info[output_index], + sizeof(struct display_flip_info_s)); } -void osd_set_background_size(struct display_flip_info_s *disp_info) +void osd_set_background_size(u32 index, struct display_flip_info_s *disp_info) { - memcpy(&osd_hw.disp_info, disp_info, - sizeof(struct display_flip_info_s)); + u32 output_index; + + output_index = get_output_device_id(index); + memcpy(&osd_hw.disp_info[output_index], disp_info, + sizeof(struct display_flip_info_s)); } void osd_get_hdr_used(u32 *val) @@ -3206,22 +3359,31 @@ void osd_set_afbc_format(u32 index, u32 format, u32 inter_format) osd_hw.osd_afbcd[index].inter_format = inter_format; } -void osd_get_hwc_enable(u32 *hwc_enable) +void osd_get_hwc_enable(u32 index, u32 *hwc_enable) { - *hwc_enable = osd_hw.hwc_enable; + u32 output_index; + + output_index = get_output_device_id(index); + *hwc_enable = osd_hw.hwc_enable[output_index]; } -void osd_set_hwc_enable(u32 hwc_enable) +void osd_set_hwc_enable(u32 index, u32 hwc_enable) { - osd_hw.hwc_enable = hwc_enable; + u32 output_index; + + output_index = get_output_device_id(index); + osd_hw.hwc_enable[output_index] = hwc_enable; /* setting default hwc path */ if (!hwc_enable) - osd_setting_blend(); + osd_setting_blend(OSD1); } -void osd_do_hwc(void) +void osd_do_hwc(u32 index) { - osd_setting_blend(); + u32 output_index; + + output_index = get_output_device_id(index); + osd_setting_blend(output_index); } static void osd_set_two_ports(bool set) @@ -3261,26 +3423,36 @@ void osd_set_urgent_info(u32 ports, u32 basic_urgent) osd_set_two_ports(osd_hw.two_ports); } -void osd_set_single_step_mode(u32 osd_single_step_mode) +void osd_set_single_step_mode(u32 index, u32 osd_single_step_mode) { + u32 output_index; + + output_index = get_output_device_id(index); + if (output_index != VIU1) + return; osd_hw.osd_debug.osd_single_step_mode = osd_single_step_mode; if ((osd_hw.osd_debug.wait_fence_release) && (osd_hw.osd_debug.osd_single_step_mode == 0)) { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - osd_timeline_increase(); + osd_timeline_increase(output_index); #endif osd_hw.osd_debug.wait_fence_release = false; } } -void osd_set_single_step(u32 osd_single_step) +void osd_set_single_step(u32 index, u32 osd_single_step) { + u32 output_index; + + output_index = get_output_device_id(index); + if (output_index != VIU1) + return; osd_hw.osd_debug.osd_single_step = osd_single_step; if ((osd_hw.osd_debug.wait_fence_release) && (osd_hw.osd_debug.osd_single_step > 0)) { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - osd_timeline_increase(); + osd_timeline_increase(output_index); #endif osd_hw.osd_debug.wait_fence_release = false; } @@ -3723,30 +3895,30 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map) height_dst) / height_src - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].y_start = y_start; freescale_dst[index].x_end = x_end; freescale_dst[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_start - 1; freescale_dst[index].y_start = y_start; freescale_dst[index].y_end = y_end; @@ -3803,30 +3975,30 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map) osd_hw.dispdata[index].y_end = fence_map->dst_y + fence_map->dst_h - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].x_end = x_end; osd_hw.dispdata[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].y_end = y_end; @@ -3849,19 +4021,19 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) u32 osd_enable = 0; bool skip = false; const struct vinfo_s *vinfo; - + u32 output_index = VIU1; if (index >= OSD2) goto out; - if (timeline_created) { /* out fence created success. */ + if (timeline_created[output_index]) { /* out fence created success. */ ret = osd_wait_buf_ready(fence_map); if (ret < 0) osd_log_dbg(MODULE_BASE, "fence wait ret %d\n", ret); } if (ret) { osd_hw.buffer_alloc[index] = 1; - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; if (fence_map->op == 0xffffffff) skip = true; else @@ -3878,8 +4050,9 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) if (vinfo) { if ((strcmp(vinfo->name, "invalid")) && (strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->height; + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = + vinfo->height; } } /* Todo: */ @@ -4083,9 +4256,9 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) osd_wait_vsync_hw(); } } - if (timeline_created) { + if (timeline_created[output_index]) { if (ret) - osd_timeline_increase(); + osd_timeline_increase(output_index); else osd_log_err("------NOT signal out_fence ERROR\n"); } @@ -4096,7 +4269,11 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) out: if (fence_map->in_fence) osd_put_fenceobj(fence_map->in_fence); +} +static void osd_pan_display_single_fence_viu2(struct osd_fence_map_s *fence_map) +{ + osd_log_err("osd hwc version not support viu2\n"); } static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) @@ -4105,6 +4282,7 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) const struct color_bit_define_s *color = NULL; u32 ext_addr = 0; u32 format = 0; + u32 output_index = 0; if (index > OSD_MAX) return; @@ -4268,7 +4446,8 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) layer_map->dst_x + layer_map->dst_w - 1; osd_hw.free_dst_data[index].y_end = layer_map->dst_y + layer_map->dst_h - 1; - if (osd_hw.field_out_en) { + output_index = get_output_device_id(index); + if (osd_hw.field_out_en[output_index]) { osd_hw.free_dst_data[index].y_start /= 2; osd_hw.free_dst_data[index].y_end /= 2; } @@ -4280,31 +4459,47 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) #endif } -static void osd_pan_display_layers_fence( +static void _osd_pan_display_layers_fence( + u32 output_index, + struct vinfo_s *vinfo, struct osd_layers_fence_map_s *fence_map) { int i = 0; int ret; - int osd_count = osd_hw.osd_meson_dev.osd_count - 1; + int start_index = 0; + int backup_en = 0; + int osd_count; /* osd_count need -1 when VIU2 enable */ struct layer_fence_map_s *layer_map = NULL; - struct vinfo_s *vinfo; - if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) - osd_count = 1; - vinfo = get_current_vinfo(); if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->field_height; + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->field_height; + } + memcpy(&osd_hw.disp_info[output_index], &fence_map->disp_info, + sizeof(struct display_flip_info_s)); + if (output_index == VIU1) { + osd_count = osd_hw.osd_meson_dev.viu1_osd_count; + if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) + osd_count = 1; + start_index = 0; + backup_en = 1; + } else if (output_index == VIU2) { + start_index = osd_hw.osd_meson_dev.viu2_index; + osd_count = start_index + 1; + backup_en = 0; + } else { + osd_log_err("invald output_index=%d\n", output_index); + return; } - osd_set_background_size(&(fence_map->disp_info)); - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; - clear_backup_info(); + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; + if (backup_en) + clear_backup_info(); osd_hw.hdr_used = fence_map->hdr_mode; - for (i = 0; i < osd_count; i++) { + for (i = start_index; i < osd_count; i++) { layer_map = &fence_map->layer_map[i]; if (i != layer_map->fb_index) { osd_hw.screen_base[i] = 0; @@ -4313,7 +4508,7 @@ static void osd_pan_display_layers_fence( continue; } /* wait in fence */ - if (timeline_created && layer_map->enable + if (timeline_created[output_index] && layer_map->enable && (fence_map->cmd == LAYER_SYNC)) { ret = osd_wait_buf_ready_combine(layer_map); if (ret < 0) @@ -4321,23 +4516,24 @@ static void osd_pan_display_layers_fence( "fence wait ret %d\n", ret); } osd_pan_display_update_info(layer_map); - save_layer_info(layer_map); + if (backup_en) + save_layer_info(layer_map); } /* set hw regs */ if (osd_hw.osd_display_debug != OSD_DISP_DEBUG) - osd_setting_blend(); + osd_setting_blend(output_index); /* signal out fence */ - if (timeline_created) { + if (timeline_created[output_index]) { if (osd_hw.osd_debug.osd_single_step_mode) { /* single step mode */ if (osd_hw.osd_debug.osd_single_step > 0) { - osd_timeline_increase(); + osd_timeline_increase(output_index); osd_log_dbg(MODULE_FENCE, "signal out fence\n"); osd_hw.osd_debug.osd_single_step--; } else osd_hw.osd_debug.wait_fence_release = true; } else - osd_timeline_increase(); + osd_timeline_increase(output_index); } /*clear last displayed buffer.*/ for (i = 0; i < HW_OSD_COUNT; i++) { @@ -4347,7 +4543,7 @@ static void osd_pan_display_layers_fence( } } /* clear osd layer's order */ - for (i = 0; i < osd_count; i++) { + for (i = start_index; i < osd_count; i++) { layer_map = &fence_map->layer_map[i]; if (layer_map->buf_file) displayed_bufs[i] = layer_map->buf_file; @@ -4356,14 +4552,42 @@ static void osd_pan_display_layers_fence( osd_hw.order[i] = 0; } } + +static void osd_pan_display_layers_fence( + struct osd_layers_fence_map_s *fence_map) +{ + u32 output_index = VIU1; + struct vinfo_s *vinfo = NULL; + + vinfo = get_current_vinfo(); + + _osd_pan_display_layers_fence(output_index, + vinfo, fence_map); +} + +static void osd_pan_display_layers_fence_viu2( + struct osd_layers_fence_map_s *fence_map) +{ + u32 output_index = VIU2; + struct vinfo_s *vinfo = NULL; + +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + vinfo = get_current_vinfo2(); +#endif + + _osd_pan_display_layers_fence(output_index, + vinfo, fence_map); +} #endif void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset) { long diff_x, diff_y; + u32 output_index; if (index >= HW_OSD_COUNT) return; + output_index = get_output_device_id(index); if (xoffset != osd_hw.pandata[index].x_start || yoffset != osd_hw.pandata[index].y_start) { diff_x = xoffset - osd_hw.pandata[index].x_start; @@ -4379,8 +4603,8 @@ void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset) osd_hw.src_data[index].h = osd_hw.pandata[index].y_end - osd_hw.pandata[index].y_start + 1; add_to_update_list(index, DISP_GEOMETRY); - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; /* osd_wait_vsync_hw(); */ } #ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT @@ -4454,6 +4678,7 @@ static void osd_update_disp_freescale_enable(u32 index) struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index]; u32 data32 = 0x0; u32 shift_workaround = 0; + u32 output_index = 0; if (osd_hw.osd_meson_dev.osd_ver != OSD_HIGH_ONE) osd_reg = &hw_osd_reg_array[0]; @@ -4520,8 +4745,9 @@ static void osd_update_disp_freescale_enable(u32 index) else vf_phase_step = (src_h << 20) / dst_h; + output_index = get_output_device_id(index); #ifdef NEW_PPS_PHASE - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { struct osd_f2v_vphase_s vphase; f2v_get_vertical_phase( @@ -4552,7 +4778,7 @@ static void osd_update_disp_freescale_enable(u32 index) bot_ini_phase = 0; } #else - if (osd_hw.field_out_en) /* interface output */ + if (osd_hw.field_out_en[output_index]) /* interface output */ bot_ini_phase = ((vf_phase_step / 2) >> 4); else bot_ini_phase = 0; @@ -4564,7 +4790,7 @@ static void osd_update_disp_freescale_enable(u32 index) data32 = 0x0; if (shift_workaround) { vsc_ini_rcv_num++; - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[output_index]) vsc_bot_rcv_num++; } @@ -4586,7 +4812,7 @@ static void osd_update_disp_freescale_enable(u32 index) data32 |= (vf_bank_len & 0x7) | ((vsc_ini_rcv_num & 0xf) << 3) | ((vsc_ini_rpt_p0_num & 0x3) << 8); - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[output_index]) data32 |= ((vsc_bot_rcv_num & 0xf) << 11) | ((vsc_bot_rpt_p0_num & 0x3) << 16) | (1 << 23); @@ -4621,8 +4847,8 @@ static void osd_update_disp_freescale_enable(u32 index) VSYNCOSD_WR_MPEG_REG( osd_reg->osd_vsc_init_phase, data32); } - if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) - && (!osd_hw.hwc_enable)) { + if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) && + (!osd_hw.hwc_enable[output_index])) { osd_setting_blending_scope(index); vpp_blend_setting_default(index); } @@ -5051,7 +5277,7 @@ static void osd_update_disp_osd_rotate(u32 index) u32 data32; enum color_index_e idx; struct dispdata_s src_data; - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; int out_y_crop_start, out_y_crop_end; if (osd_hw.osd_meson_dev.cpu_id != __MESON_CPU_MAJOR_ID_G12B) @@ -5061,11 +5287,14 @@ static void osd_update_disp_osd_rotate(u32 index) src_data.y = 0; src_data.w = osd_hw.fb_gem[index].xres; src_data.h = osd_hw.fb_gem[index].yres; + src_data.h = osd_hw.fb_gem[index].yres; +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE vinfo = get_current_vinfo2(); if (!vinfo) { osd_log_err("current vinfo NULL\n"); return; } +#endif out_y_crop_start = 0; out_y_crop_end = vinfo->height; src_width = src_data.w; @@ -6418,7 +6647,8 @@ static void osd_set_freescale(u32 index, struct layer_blend_reg_s *blend_reg; u32 width, height; u32 src_height; - u32 workaround_line = 1; + u32 workaround_line = osd_hw.workaround_line; + u32 output_index = 0; layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -6430,6 +6660,7 @@ static void osd_set_freescale(u32 index, osd_hw.free_scale[index].h_enable = 1; osd_hw.free_scale[index].v_enable = 1; osd_hw.free_scale_mode[index] = 1; + output_index = get_output_device_id(index); if (index == OSD1) { osd_hw.free_src_data[index].x_start = @@ -6449,7 +6680,7 @@ static void osd_set_freescale(u32 index, * blending->screen_ratio_w >> OSD_CALC; height = (layer_blend->output_data.h - workaround_line) * blending->screen_ratio_h >> OSD_CALC; - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[output_index]) height = height >> 1; } else { osd_hw.free_src_data[index].x_start = @@ -6504,7 +6735,7 @@ static void osd_set_freescale(u32 index, width = osd_hw.dst_data[index].w; height = osd_hw.dst_data[index].h; /* interleaced case */ - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { height = height >> 1; osd_hw.free_dst_data[index].y_start >>= 1; @@ -6518,7 +6749,7 @@ static void osd_set_freescale(u32 index, osd_hw.dst_data[index].y; width = osd_hw.dst_data[index].w; height = osd_hw.dst_data[index].h; - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { height = height >> 1; osd_hw.free_dst_data[index].y_start >>= 1; } @@ -6655,9 +6886,11 @@ static void set_blend_path(struct hw_osd_blending_s *blending) struct dispdata_s output1_data; u32 index = 0; u8 input1 = 0, input2 = 0; + u32 output_index; if (!blending) return; + output_index = get_output_device_id(index); layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); #ifdef OSD_BLEND_SHIFT_WORKAROUND @@ -6703,13 +6936,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -6718,13 +6951,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) "first: set osd%d freescale\n", index); osd_set_freescale(index, blending); osd_hw.free_dst_data[index].x_start += - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; osd_hw.free_dst_data[index].x_end += - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; osd_hw.free_dst_data[index].y_start += - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; osd_hw.free_dst_data[index].y_end += - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; osd_setting_blend0_input(index, blending); osd_setting_blend0(blending); @@ -6835,13 +7068,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND_NO_DIN; layer_blend->input1_data.x = osd_hw.free_dst_data[OSD1].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[OSD1].x_end - osd_hw.free_dst_data[OSD1].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[OSD1].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[OSD1].y_end - osd_hw.free_dst_data[OSD1].y_start + 1; @@ -6879,20 +7112,20 @@ static void set_blend_path(struct hw_osd_blending_s *blending) /* save freescale output */ output1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; output1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; output1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; output1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; osd_log_dbg2(MODULE_BLEND, "position_x=%d, y=%d\n", - osd_hw.disp_info.position_x, - osd_hw.disp_info.position_y); + osd_hw.disp_info[output_index].position_x, + osd_hw.disp_info[output_index].position_y); index = blend_din_to_osd(BLEND_DIN4, blending); if (index >= OSD_MAX) @@ -6933,9 +7166,9 @@ static void set_blend_path(struct hw_osd_blending_s *blending) sizeof(struct dispdata_s)); /* adjust offset*/ layer_blend->input2_data.x += - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input2_data.y += - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; osd_setting_blend1(blending); @@ -7023,13 +7256,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND_NO_DIN; layer_blend->input1_data.x = osd_hw.free_dst_data[OSD1].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[OSD1].x_end - osd_hw.free_dst_data[OSD1].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[OSD1].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[OSD1].y_end - osd_hw.free_dst_data[OSD1].y_start + 1; @@ -7064,13 +7297,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) /* save freescale output */ output1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; output1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; output1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; output1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7082,13 +7315,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_set_freescale(index, blending); layer_blend->input1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7101,13 +7334,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_set_freescale(index, blending); layer_blend->input2_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input2_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input2_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input2_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7188,13 +7421,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_set_freescale(OSD1, blending); output1_data.x = osd_hw.free_dst_data[OSD1].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; output1_data.w = osd_hw.free_dst_data[OSD1].x_end - osd_hw.free_dst_data[OSD1].x_start + 1; output1_data.y = osd_hw.free_dst_data[OSD1].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; output1_data.h = osd_hw.free_dst_data[OSD1].y_end - osd_hw.free_dst_data[OSD1].y_start + 1; @@ -7214,13 +7447,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input2_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input2_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input2_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7372,17 +7605,29 @@ static void uniformization_fb(u32 index, blending->dst_data.h); } -static void adjust_dst_position(void) +static void adjust_dst_position(u32 output_index) { int i = 0; - int osd_count = osd_hw.osd_meson_dev.viu1_osd_count; + int osd_count = 0; + int start_index = 0; + + if (output_index == VIU1) { + osd_count = osd_hw.osd_meson_dev.viu1_osd_count; + start_index = 0; + } else if (output_index == VIU2) { + start_index = osd_hw.osd_meson_dev.viu2_index; + osd_count = start_index + 1; + } else { + osd_log_err("invald output_index=%d\n", output_index); + return; + } for (i = 0; i < osd_count; i++) { if (osd_hw.enable[i]) { osd_hw.dst_data[i].x -= - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; osd_hw.dst_data[i].y -= - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; if (osd_hw.dst_data[i].x < 0) osd_hw.dst_data[i].x = 0; if (osd_hw.dst_data[i].y < 0) @@ -7396,11 +7641,11 @@ static void adjust_dst_position(void) osd_hw.dst_data[i].h); } } - if (osd_hw.field_out_en) - osd_hw.disp_info.position_y /= 2; + if (osd_hw.field_out_en[output_index]) + osd_hw.disp_info[output_index].position_y /= 2; } -static int osd_setting_order(void) +static int osd_setting_order(u32 output_index) { #define RDMA_DETECT_REG VIU_OSD2_TCOLOR_AG2 int i; @@ -7416,14 +7661,14 @@ static int osd_setting_order(void) blending = &osd_blending; blend_reg = &(blending->blend_reg); - blending->vinfo_width = osd_hw.vinfo_width; - blending->vinfo_height = osd_hw.vinfo_height; + blending->vinfo_width = osd_hw.vinfo_width[output_index]; + blending->vinfo_height = osd_hw.vinfo_height[output_index]; blending->screen_ratio_w = - (osd_hw.disp_info.position_w << OSD_CALC) - / osd_hw.disp_info.background_w; + (osd_hw.disp_info[output_index].position_w << OSD_CALC) + / osd_hw.disp_info[output_index].background_w; blending->screen_ratio_h = - (osd_hw.disp_info.position_h << OSD_CALC) - / osd_hw.disp_info.background_h; + (osd_hw.disp_info[output_index].position_h << OSD_CALC) + / osd_hw.disp_info[output_index].background_h; blending->layer_cnt = get_available_layers(); set_blend_order(blending); @@ -7433,7 +7678,7 @@ static int osd_setting_order(void) blending->b_exchange_din = false; blending->b_exchange_blend_in = false; blending->osd1_freescale_disable = false; - adjust_dst_position(); + adjust_dst_position(output_index); uniformization_fb(OSD1, blending); /* set blend mode */ @@ -7445,8 +7690,9 @@ static int osd_setting_order(void) /* set blend path */ set_blend_path(blending); line1 = get_enter_encp_line(); - vinfo_height = osd_hw.field_out_en ? - (osd_hw.vinfo_height * 2) : osd_hw.vinfo_height; + vinfo_height = osd_hw.field_out_en[output_index] ? + (osd_hw.vinfo_height[output_index] * 2) : + osd_hw.vinfo_height[output_index]; /* if nearly vsync signal, wait vsync here */ if (line1 >= vinfo_height * line_threshold / 100) { osd_log_dbg(MODULE_RENDER, @@ -7602,8 +7848,8 @@ static void osd_setting_default_hwc(void) 0x0 << 11 | 0x0); - blend_hsize = osd_hw.disp_info.background_w; - blend_vsize = osd_hw.disp_info.background_h; + blend_hsize = osd_hw.disp_info[VIU1].background_w; + blend_vsize = osd_hw.disp_info[VIU1].background_h; VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE, blend_vsize << 16 | @@ -7620,29 +7866,29 @@ static bool set_old_hwc_freescale(u32 index) u32 x_start, x_end, y_start, y_end, height_dst, height_src; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_start - 1; osd_hw.free_dst_data[index].x_start = x_start; osd_hw.free_dst_data[index].y_start = y_start; osd_hw.free_dst_data[index].x_end = x_end; osd_hw.free_dst_data[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_start - 1; osd_hw.free_dst_data[index].x_start = x_start; osd_hw.free_dst_data[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_start - 1; osd_hw.free_dst_data[index].y_start = y_start; osd_hw.free_dst_data[index].y_end = y_end; @@ -7734,25 +7980,28 @@ static void osd_setting_viu2(void) if (!osd_hw.osd_display_debug) osd_hw.reg[OSD_ENABLE] .update_func(index); + osd_wait_vsync_hw(); } -int osd_setting_blend(void) +int osd_setting_blend(u32 output_index) { int ret; if (osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE) osd_setting_old_hwc(); else { - if (osd_hw.hwc_enable) { - if (osd_hw.viu_type == VIU1) { - ret = osd_setting_order(); + if (osd_hw.hwc_enable[output_index]) { + if (output_index == VIU1) { + ret = osd_setting_order(output_index); if (ret < 0) return -1; - } else if (osd_hw.viu_type == VIU2) + } else if (output_index == VIU2) { osd_setting_viu2(); - } else + } + } else { osd_setting_default_hwc(); + } } return 0; } @@ -8299,7 +8548,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hdr_on = false; #endif osd_hw.hw_reset_flag = HW_RESET_NONE; - osd_hw.hwc_enable = 0; + osd_hw.hwc_enable[VIU1] = 0; + osd_hw.hwc_enable[VIU2] = 0; if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { osd_hw.hw_cursor_en = 1; if (osd_hw.osd_meson_dev.has_rdma) @@ -8394,18 +8644,24 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.order[OSD1] = LAYER_1; osd_hw.order[OSD2] = LAYER_2; osd_hw.order[OSD3] = LAYER_3; - //osd_hw.osd_blend_mode = OSD_BLEND_NONE; - osd_hw.disp_info.background_w = 1920; - osd_hw.disp_info.background_h = 1080; - osd_hw.disp_info.fullscreen_w = 1920; - osd_hw.disp_info.fullscreen_h = 1080; - osd_hw.disp_info.position_x = 0; - osd_hw.disp_info.position_y = 0; - osd_hw.disp_info.position_w = 1920; - osd_hw.disp_info.position_h = 1080; - osd_hw.vinfo_width = 1920; - osd_hw.vinfo_height = 1080; - + for (idx = 0; idx < VIU_COUNT; idx++) { + osd_hw.disp_info[idx].background_w = 1920; + osd_hw.disp_info[idx].background_h = 1080; + osd_hw.disp_info[idx].fullscreen_w = 1920; + osd_hw.disp_info[idx].fullscreen_h = 1080; + osd_hw.disp_info[idx].position_x = 0; + osd_hw.disp_info[idx].position_y = 0; + osd_hw.disp_info[idx].position_w = 1920; + osd_hw.disp_info[idx].background_h = 1080; + osd_hw.vinfo_width[idx] = 1920; + osd_hw.vinfo_height[idx] = 1080; + } + if ((osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12A) || + ((osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B) && + is_meson_rev_a())) + osd_hw.workaround_line = 1; for (idx = 0; idx < osd_hw.osd_meson_dev.osd_count; idx++) { osd_hw.premult_en[idx] = 0; osd_hw.osd_afbcd[idx].format = COLOR_INDEX_32_ABGR; @@ -8525,15 +8781,26 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, } /* hwc_enable == 0 handler */ #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - osd_hw.osd_fence[DISABLE].sync_fence_handler = + osd_hw.osd_fence[VIU1][DISABLE].sync_fence_handler = sync_render_single_fence; - osd_hw.osd_fence[DISABLE].toggle_buffer_handler = + osd_hw.osd_fence[VIU1][DISABLE].toggle_buffer_handler = osd_toggle_buffer_single; /* hwc_enable == 1 handler */ - osd_hw.osd_fence[ENABLE].sync_fence_handler = + osd_hw.osd_fence[VIU1][ENABLE].sync_fence_handler = sync_render_layers_fence; - osd_hw.osd_fence[ENABLE].toggle_buffer_handler = + osd_hw.osd_fence[VIU1][ENABLE].toggle_buffer_handler = osd_toggle_buffer_layers; + if (osd_hw.osd_meson_dev.has_viu2) { + osd_hw.osd_fence[VIU2][DISABLE].sync_fence_handler = + sync_render_single_fence; + osd_hw.osd_fence[VIU2][DISABLE].toggle_buffer_handler = + osd_toggle_buffer_single_viu2; + /* hwc_enable == 1 handler */ + osd_hw.osd_fence[VIU2][ENABLE].sync_fence_handler = + sync_render_layers_fence; + osd_hw.osd_fence[VIU2][ENABLE].toggle_buffer_handler = + osd_toggle_buffer_layers_viu2; + } #endif osd_hw.fb_gem[OSD1].canvas_idx = OSD1_CANVAS_INDEX; osd_hw.fb_gem[OSD2].canvas_idx = OSD2_CANVAS_INDEX; @@ -8544,7 +8811,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_extra_canvas_alloc(); osd_hw.antiflicker_mode = 0; osd_hw.osd_deband_enable = 1; - osd_hw.out_fence_fd = -1; + osd_hw.out_fence_fd[VIU1] = -1; + osd_hw.out_fence_fd[VIU2] = -1; osd_hw.blend_bypass = 0; osd_hw.afbc_err_cnt = 0; if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) { @@ -8559,8 +8827,10 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_set_deband(osd_hw.osd_deband_enable); if (osd_hw.fb_drvier_probe) { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - INIT_LIST_HEAD(&post_fence_list); - mutex_init(&post_fence_list_lock); + INIT_LIST_HEAD(&post_fence_list[VIU1]); + mutex_init(&post_fence_list_lock[VIU1]); + INIT_LIST_HEAD(&post_fence_list[VIU2]); + mutex_init(&post_fence_list_lock[VIU2]); #endif #ifdef FIQ_VSYNC osd_hw.fiq_handle_item.handle = vsync_isr; @@ -8840,7 +9110,7 @@ void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, memcpy(&disp_tmp, &osd_hw.dispdata[OSD1], sizeof(struct pandata_s)); - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[VIU1]) { disp_tmp.y_start *= 2; disp_tmp.y_end *= 2; } @@ -8946,7 +9216,7 @@ void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, } } - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[VIU1]) osd_hw.dispdata[OSD2].y_start /= 2; osd_hw.dispdata[OSD2].x_end = osd_hw.dispdata[OSD2].x_start + @@ -9467,7 +9737,9 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) u32 x_start, x_end, y_start, y_end; bool freescale_update = false; struct pandata_s freescale_dst[HW_OSD_COUNT]; + u32 output_index; + output_index = get_output_device_id(index); phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y; osd_hw.screen_base[index] = phy_addr; osd_hw.screen_size[index] = @@ -9485,7 +9757,7 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) plane_map->src_h, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); } - if (osd_hw.hwc_enable) { + if (osd_hw.hwc_enable[output_index]) { /* just get para, need update via do_hwc */ osd_hw.order[index] = plane_map->zorder; switch (plane_map->blend_mode) { @@ -9577,30 +9849,30 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) ((plane_map->dst_y + plane_map->dst_h) * height_dst) / height_src - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].y_start = y_start; freescale_dst[index].x_end = x_end; freescale_dst[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_start - 1; freescale_dst[index].y_start = y_start; freescale_dst[index].y_end = y_end; @@ -9666,30 +9938,30 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) osd_hw.dispdata[index].y_end = plane_map->dst_y + plane_map->dst_h - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].x_end = x_end; osd_hw.dispdata[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].y_end = y_end; @@ -9717,9 +9989,11 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map) u32 x, y; struct pandata_s disp_tmp; struct pandata_s free_dst_data_backup; + u32 output_index; if (index != OSD2) return; + output_index = get_output_device_id(index); phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y; osd_hw.screen_base[index] = phy_addr; osd_hw.screen_size[index] = @@ -9817,29 +10091,29 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map) osd_hw.pandata[OSD2].y_end - osd_hw.pandata[OSD2].y_start; if (osd_hw.osd_reverse[OSD2] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].x_end = x_end; osd_hw.dispdata[index].y_end = y_end; } else if (osd_hw.osd_reverse[OSD2] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].x_end = x_end; } else if (osd_hw.osd_reverse[OSD2] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].y_end = y_end; @@ -9877,9 +10151,11 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) bool freescale_update = false; u32 osd_enable = 0; u32 format = 0; - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; + u32 output_index; - if (!osd_hw.hwc_enable) { + output_index = get_output_device_id(index); + if (!osd_hw.hwc_enable[output_index]) { if (index >= OSD2) return; } else { @@ -9888,15 +10164,20 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) } osd_hw.buffer_alloc[index] = 1; - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; + + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif - osd_enable = (plane_map->enable & 1) ? ENABLE : DISABLE; - vinfo = get_current_vinfo(); if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->height; + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; } osd_hw.osd_afbcd[index].enable = (plane_map->afbc_inter_format & AFBC_EN) >> 31; @@ -9992,7 +10273,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) osd_hw.osd_afbcd[index].phy_addr = plane_map->phy_addr; osd_hw.reg[OSD_COLOR_MODE].update_func(index); - if (!osd_hw.hwc_enable) { + if (!osd_hw.hwc_enable[output_index]) { osd_hw.reg[DISP_GEOMETRY].update_func(index); osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index ce8ec8705f3c..f86f0b29b2f2 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -102,7 +102,7 @@ extern void osd_set_block_mode_hw(u32 index, u32 mode); extern void osd_enable_3d_mode_hw(u32 index, u32 enable); extern void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable); -extern void osd_get_flush_rate_hw(u32 *break_rate); +extern void osd_get_flush_rate_hw(u32 index, u32 *break_rate); extern void osd_set_reverse_hw(u32 index, u32 reverse, u32 update); extern void osd_get_reverse_hw(u32 index, u32 *reverse); extern void osd_set_antiflicker_hw(u32 index, struct vinfo_s *vinfo, u32 yres); @@ -126,7 +126,7 @@ extern int osd_sync_request_render(u32 index, u32 yres, struct sync_req_render_s *request, u32 phys_addr, size_t len); -extern int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd); +int osd_sync_do_hwc(u32 output_index, struct do_hwc_cmd_s *hwc_cmd); extern s64 osd_wait_vsync_event(void); extern void osd_cursor_hw(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, u32 osd_w, u32 osd_h); @@ -165,8 +165,8 @@ extern void osd_get_urgent(u32 index, u32 *urgent); extern void osd_set_urgent(u32 index, u32 urgent); void osd_get_deband(u32 *osd_deband_enable); void osd_set_deband(u32 osd_deband_enable); -void osd_get_fps(u32 *osd_fps); -void osd_set_fps(u32 osd_fps_start); +void osd_get_fps(u32 index, u32 *osd_fps); +void osd_set_fps(u32 index, u32 osd_fps_start); extern void osd_get_info(u32 index, u32 *addr, u32 *width, u32 *height); void osd_update_scan_mode(void); void osd_update_3d_mode(void); @@ -180,15 +180,15 @@ int set_osd_logo_freescaler(void); int is_interlaced(struct vinfo_s *vinfo); void osd_get_display_debug(u32 *osd_display_debug_enable); void osd_set_display_debug(u32 osd_display_debug_enable); -void osd_get_background_size(struct display_flip_info_s *disp_info); -void osd_set_background_size(struct display_flip_info_s *disp_info); +void osd_get_background_size(u32 index, struct display_flip_info_s *disp_info); +void osd_set_background_size(u32 index, struct display_flip_info_s *disp_info); void osd_get_hdr_used(u32 *val); void osd_set_hdr_used(u32 val); void osd_get_afbc_format(u32 index, u32 *format, u32 *inter_format); void osd_set_afbc_format(u32 index, u32 format, u32 inter_format); -void osd_get_hwc_enable(u32 *hwc_enable); -void osd_set_hwc_enable(u32 hwc_enable); -void osd_do_hwc(void); +void osd_get_hwc_enable(u32 index, u32 *hwc_enable); +void osd_set_hwc_enable(u32 index, u32 hwc_enable); +void osd_do_hwc(u32 index); int osd_get_capbility(u32 index); void osd_backup_screen_info( u32 index, @@ -204,12 +204,12 @@ ssize_t dd_vmap_write(u32 index, const char __user *buf, int osd_set_clear(u32 index); void osd_page_flip(struct osd_plane_map_s *plane_map); void walk_through_update_list(void); -int osd_setting_blend(void); -void osd_set_hwc_enable(u32 hwc_enable); +int osd_setting_blend(u32 output_index); +void osd_set_hwc_enable(u32 index, u32 hwc_enable); void osd_set_urgent_info(u32 ports, u32 basic_urgent); void osd_get_urgent_info(u32 *ports, u32 *basic_urgent); -void osd_set_single_step_mode(u32 osd_single_step_mode); -void osd_set_single_step(u32 osd_single_step); +void osd_set_single_step_mode(u32 index, u32 osd_single_step_mode); +void osd_set_single_step(u32 index, u32 osd_single_step); void output_save_info(void); void osd_get_rotate(u32 index, u32 *osd_rotate); void osd_set_rotate(u32 index, u32 osd_rotate); @@ -218,4 +218,5 @@ void osd_get_dimm_info(u32 index, u32 *osd_dimm_layer, u32 *osd_dimm_color); void osd_set_dimm_info(u32 index, u32 osd_dimm_layer, u32 osd_dimm_color); u32 osd_get_line_n_rdma(void); void osd_set_line_n_rdma(u32 line_n_rdma); +u32 get_output_device_id(u32 index); #endif From e8bc6f758b0d5856e34a072f73c8f86b81e60c1e Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 9 Apr 2019 13:22:03 +0800 Subject: [PATCH 0493/1060] osd: osd display color abnormal when run drm [1/1] PD#SWPL-6867 Problem: osd dispaly color abnormal because osd enable not update. Solution: update osd enalbe flag in drm process. Verify: Verified u212 Change-Id: I1c2e8b62d9d5af203c95d3d0ac940fb512dd8e5e Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 4a7d7c725bc0..e31fd18bf97f 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -4688,7 +4688,8 @@ static void osd_update_disp_freescale_enable(u32 index) else vf_bank_len = 4; - if (osd_hw.hwc_enable && (index == OSD1)) + output_index = get_output_device_id(index); + if (osd_hw.hwc_enable[output_index] && (index == OSD1)) shift_workaround = osd_hw.workaround_line; #ifndef NEW_PPS_PHASE @@ -4745,7 +4746,6 @@ static void osd_update_disp_freescale_enable(u32 index) else vf_phase_step = (src_h << 20) / dst_h; - output_index = get_output_device_id(index); #ifdef NEW_PPS_PHASE if (osd_hw.field_out_en[output_index]) { struct osd_f2v_vphase_s vphase; @@ -10166,6 +10166,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) osd_hw.buffer_alloc[index] = 1; if (osd_hw.osd_fps_start[output_index]) osd_hw.osd_fps[output_index]++; + osd_enable = (plane_map->enable & 1) ? ENABLE : DISABLE; if (output_index == VIU1) vinfo = get_current_vinfo(); From b1d4b006584537b4577445391c578bc0aca27331 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Fri, 29 Mar 2019 17:16:22 +0800 Subject: [PATCH 0494/1060] osd: set osd1 scaler before osd blend [1/1] PD#SWPL-6596 Problem: bring up osd for TM2 Solution: set osd1 scaler before osd blend Verify: Verified on T962e2_ab319 Change-Id: I9e7d5fa83b2edc8e9359371695ea46fa3b39e09c Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd.h | 1 + drivers/amlogic/media/osd/osd_fb.c | 43 +- drivers/amlogic/media/osd/osd_hw.c | 836 +++++++++++++++++++--------- drivers/amlogic/media/osd/osd_reg.h | 2 +- 4 files changed, 600 insertions(+), 282 deletions(-) diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 404c53a2bdc6..03dd77399ebc 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -510,6 +510,7 @@ struct osd_device_data_s { u32 vpp_fifo_len; u32 dummy_data; u32 has_viu2; + u32 osd0_sc_independ; u32 viu1_osd_count; u32 viu2_index; struct clk *vpu_clkc; diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index c6748d489f0b..1dbe59c462f3 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -3863,6 +3863,7 @@ static struct osd_device_data_s osd_gxbb = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxtvbb = { @@ -3878,6 +3879,7 @@ static struct osd_device_data_s osd_gxtvbb = { .vpp_fifo_len = 0xfff, .dummy_data = 0x0, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxl = { @@ -3893,6 +3895,7 @@ static struct osd_device_data_s osd_gxl = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxm = { @@ -3908,6 +3911,7 @@ static struct osd_device_data_s osd_gxm = { .vpp_fifo_len = 0xfff, .dummy_data = 0x00202000,/* dummy data is different */ .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_txl = { @@ -3923,6 +3927,7 @@ static struct osd_device_data_s osd_txl = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_txlx = { @@ -3938,6 +3943,7 @@ static struct osd_device_data_s osd_txlx = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_axg = { @@ -3954,6 +3960,7 @@ static struct osd_device_data_s osd_axg = { .vpp_fifo_len = 0x400, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_g12a = { @@ -3969,6 +3976,7 @@ static struct osd_device_data_s osd_g12a = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_g12b = { @@ -3984,6 +3992,7 @@ static struct osd_device_data_s osd_g12b = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_tl1 = { @@ -3999,21 +4008,7 @@ static struct osd_device_data_s osd_tl1 = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, -}; - -static struct osd_device_data_s osd_tm2 = { - .cpu_id = __MESON_CPU_MAJOR_ID_TM2, - .osd_ver = OSD_HIGH_ONE, - .afbc_type = MALI_AFBC, - .osd_count = 4, - .has_deband = 1, - .has_lut = 1, - .has_rdma = 1, - .has_dolby_vision = 0, - .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ - .vpp_fifo_len = 0xfff,/* 2048 */ - .dummy_data = 0x00808000, - .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_sm1 = { @@ -4029,6 +4024,23 @@ static struct osd_device_data_s osd_sm1 = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, +}; + +static struct osd_device_data_s osd_tm2 = { + .cpu_id = __MESON_CPU_MAJOR_ID_TM2, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, + .osd0_sc_independ = 1, }; static const struct of_device_id meson_fb_dt_match[] = { @@ -4126,7 +4138,6 @@ static int osd_probe(struct platform_device *pdev) return -ENODEV; } } - /* get interrupt resource */ int_viu_vsync = platform_get_irq_byname(pdev, "viu-vsync"); if (int_viu_vsync == -ENXIO) { diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index e31fd18bf97f..fbceac9bd936 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -75,7 +75,6 @@ #include "osd_hw_def.h" #include "osd_fb.h" -#define OSD_BLEND_SHIFT_WORKAROUND #ifdef CONFIG_AMLOGIC_VSYNC_FIQ_ENABLE #define FIQ_VSYNC #endif @@ -5564,7 +5563,6 @@ static u32 blend_din_to_osd( return osd_index; } -#ifdef OSD_BLEND_SHIFT_WORKAROUND static u32 get_max_order(u32 order1, u32 order2) { u32 max_order = 0; @@ -5854,155 +5852,6 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending) blending->din_reoder_sel; } -#else -static void generate_blend_din_table(struct hw_osd_blending_s *blending) -{ - int i = 0; - int osd_count = osd_hw.osd_meson_dev.osd_count - 1; - - /* reorder[i] = osd[i]'s display layer */ - for (i = 0; i < OSD_BLEND_LAYERS; i++) - blending->osd_to_bdin_table[i] = -1; - blending->din_reoder_sel = 0; - switch (blending->layer_cnt) { - case 0: - break; - case 1: - for (i = 0; i < osd_count; i++) { - if (blending->reorder[i] != LAYER_UNSUPPORT) { - /* blend_din1 */ - blending->din_reoder_sel |= (i + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = i; - break; - } - } - break; - case 2: - { - int temp_index[2] = {0}; - int j = 0; - - for (i = 0; i < osd_count; i++) { - if (blending->reorder[i] != LAYER_UNSUPPORT) { - /* save the osd index */ - temp_index[j] = i; - j++; - } - } - osd_log_dbg(MODULE_BLEND, "blend_din4==%d\n", - blending->reorder[temp_index[0]]); - osd_log_dbg(MODULE_BLEND, "blend_din1==%d\n", - blending->reorder[temp_index[1]]); - /* mode A_C */ - if (blending->osd_blend_mode == OSD_BLEND_A_C) { - /* blend_din1 */ - blending->din_reoder_sel |= (temp_index[0] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[0]; - /* blend_din3 */ - blending->din_reoder_sel |= (temp_index[1] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[1]; - /* exchane vpp osd blend in order */ - if (blending->reorder[temp_index[0]] < - blending->reorder[temp_index[1]]) { - blending->b_exchange_blend_in = true; - osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n"); - } - } else { - if (blending->reorder[temp_index[0]] < - blending->reorder[temp_index[1]]) { - /* blend_din4 */ - blending->din_reoder_sel |= - (temp_index[0] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[0]; - /* blend_din1 */ - blending->din_reoder_sel |= - (temp_index[1] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[1]; - blending->b_exchange_din = true; - osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n"); - } else { - /* blend_din1 */ - blending->din_reoder_sel |= - (temp_index[0] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[0]; - /* blend_din3 */ - blending->din_reoder_sel |= - (temp_index[1] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[1]; - } - } - break; - } - case 3: - /* blend_din1 is bottom, blend_din4 is top layer */ - /* mode A_BC */ - /* osd0 always used blend_din1 */ - /* blend_din1 */ - blending->din_reoder_sel |= 1 << 0; - /* blend_din1 -- osd1 */ - blending->osd_to_bdin_table[0] = OSD1; - if (blending->reorder[OSD2] > blending->reorder[OSD3]) { - /* blend_din4 */ - blending->din_reoder_sel |= (OSD3 + 1) << 12; - /* blend_din4 -- osd3 */ - blending->osd_to_bdin_table[3] = OSD3; - - /* blend_din3 */ - blending->din_reoder_sel |= (OSD2 + 1) << 8; - /* blend_din3 -- osd2 */ - blending->osd_to_bdin_table[2] = OSD2; - } else { - /* blend_din3 */ - blending->din_reoder_sel |= (OSD2 + 1) << 12; - /* blend_din3 -- osd2 */ - blending->osd_to_bdin_table[3] = OSD2; - - /* blend_din3 */ - blending->din_reoder_sel |= (OSD3 + 1) << 8; - /* blend_din3 -- osd2 */ - blending->osd_to_bdin_table[2] = OSD3; - - } - if (blending->reorder[OSD1] < blending->reorder[OSD3]) { - if (blending->osd_blend_mode == OSD_BLEND_A_BC) { - blending->b_exchange_blend_in = true; - osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n"); - } else { - u32 temp1, temp2; - - blending->b_exchange_din = true; - osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n"); - temp1 = blending->osd_to_bdin_table[2]; - temp2 = blending->osd_to_bdin_table[3]; - blending->osd_to_bdin_table[3] = - blending->osd_to_bdin_table[0]; - blending->osd_to_bdin_table[2] = temp2; - blending->osd_to_bdin_table[0] = temp1; - temp1 = blending->din_reoder_sel & 0xf000; - temp2 = blending->din_reoder_sel & 0x0f00; - blending->din_reoder_sel = (1 << 12); - blending->din_reoder_sel |= temp1 >> 4; - blending->din_reoder_sel |= temp2 >> 8; - } - } - break; - } - osd_log_dbg(MODULE_BLEND, "osd_to_bdin_table[i]=[%x,%x,%x,%x]\n", - blending->osd_to_bdin_table[0], - blending->osd_to_bdin_table[1], - blending->osd_to_bdin_table[2], - blending->osd_to_bdin_table[3]); - blending->blend_reg.din_reoder_sel = - blending->din_reoder_sel; -} -#endif static bool is_freescale_para_changed(u32 index) { static int first[HW_OSD_COUNT - 1] = {1}; @@ -6161,13 +6010,9 @@ static void set_blend_order(struct hw_osd_blending_s *blending) static void set_blend_din(struct hw_osd_blending_s *blending) { int i = 0, osd_index; -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* workaround for shift issue */ /* blend_din_en must equal 5 */ u32 blend_din_en = 0x5; -#else - u32 blend_din_en = 0x9; -#endif if (!blending) return; @@ -6188,7 +6033,6 @@ static void set_blend_din(struct hw_osd_blending_s *blending) static void set_blend_mode(struct hw_osd_blending_s *blending) { u8 osd_blend_mode = OSD_BLEND_NONE; - //u32 osd_index; if (!blending) return; @@ -6212,11 +6056,7 @@ static void set_blend_mode(struct hw_osd_blending_s *blending) if (osd_hw.hdr_used) osd_blend_mode = OSD_BLEND_ABC; else -#ifdef OSD_BLEND_SHIFT_WORKAROUND osd_blend_mode = OSD_BLEND_AB_C; -#else - osd_blend_mode = OSD_BLEND_A_BC; -#endif break; } blending->osd_blend_mode = osd_blend_mode; @@ -6360,19 +6200,9 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) } layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* blend1_dout to blend2 */ blend_reg->din2_osd_sel = 0; -#else - /* input1 default route to blend1 */ - if (layer_blend->input1 & BYPASS_DIN) { - /* blend1_dout to dout1 */ - blend_reg->din2_osd_sel = 1; - layer_blend->input1 &= ~BYPASS_DIN; - } else - /* blend1_dout to blend2 */ - blend_reg->din2_osd_sel = 0; -#endif + if (layer_blend->input2 & BYPASS_DIN) { /* blend1_din3 bypass to dout1 */ blend_reg->din3_osd_sel = 1; @@ -6436,7 +6266,6 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) } if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) { /* blend din3 bypass,output == input */ -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->input2 == BLEND_NO_DIN) { memcpy(&layer_blend->output_data, &layer_blend->input1_data, @@ -6447,16 +6276,7 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) sizeof(struct dispdata_s)); } layer_blend->output_data.h += workaround_line; -#else - layer_blend->output_data.x = 0; - layer_blend->output_data.y = 0; - layer_blend->output_data.w = - layer_blend->input2_data.x + - layer_blend->input2_data.w; - layer_blend->output_data.h = - layer_blend->input2_data.y + - layer_blend->input2_data.h; -#endif + } else calc_max_output(blending); blend_hsize = layer_blend->output_data.w; @@ -6489,7 +6309,6 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) /* osd_blend_blend0_size share with blend2_size*/ blend_reg->osd_blend_blend0_size = blend_vsize << 16 | blend_hsize; -#ifdef OSD_BLEND_SHIFT_WORKAROUND switch (layer_blend->input2) { case BLEND1_DIN: blend1_input = 0; @@ -6499,19 +6318,7 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) blend1_input = 1; break; } -#else - switch (layer_blend->input2) { - case BLEND1_DIN: - /* blend1_dout to blend2 */ - blend_reg->din2_osd_sel = 0; - break; - default: - /* blend1_dout to dout1 */ - blend_reg->din2_osd_sel = 1; - break; - } - blend1_input = blend_reg->din2_osd_sel; -#endif + /* premult set */ blend_reg->blend2_premult_en = 3; if (blend1_input) @@ -6523,11 +6330,9 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) blend_vsize = layer_blend->output_data.h; blend_reg->osd_blend_blend0_size = blend_vsize << 16 | blend_hsize; -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* blend 0 and blend1 size need same */ blend_reg->osd_blend_blend1_size = blend_reg->osd_blend_blend0_size; -#endif } osd_log_dbg2(MODULE_BLEND, "layer_blend2->output_data:%d,%d,%d,%d\n", layer_blend->output_data.x, @@ -6566,11 +6371,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) switch (layer_blend->input1) { case BLEND1_DIN: blend_reg->postbld_src3_sel = POSTBLD_OSD2; -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->blend_core1_bypass) -#else - if (blend_reg->din3_osd_sel) -#endif blend_reg->postbld_osd1_premult = 0; else blend_reg->postbld_osd1_premult = 1; @@ -6599,11 +6400,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) switch (layer_blend->input2) { case BLEND1_DIN: blend_reg->postbld_src4_sel = POSTBLD_OSD2; -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->blend_core1_bypass) -#else - if (blend_reg->din3_osd_sel) -#endif blend_reg->postbld_osd2_premult = 0; else blend_reg->postbld_osd2_premult = 1; @@ -6638,7 +6435,6 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) blend_reg->vpp_osd2_blend_v_scope); } -/* input w, h is background */ static void osd_set_freescale(u32 index, struct hw_osd_blending_s *blending) @@ -6878,7 +6674,6 @@ static void osd_setting_blend1_input(u32 index, layer_blend->output_data.h); } -/* every output is next path input */ static void set_blend_path(struct hw_osd_blending_s *blending) { struct layer_blend_s *layer_blend; @@ -6893,9 +6688,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) output_index = get_output_device_id(index); layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); -#ifdef OSD_BLEND_SHIFT_WORKAROUND layer_blend->blend_core1_bypass = 0; -#endif switch (blending->osd_blend_mode) { case OSD_BLEND_NONE: blend_reg->postbld_osd1_premult = 0; @@ -7003,9 +6796,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) index = blend_din_to_osd(input1, blending); if (index >= OSD_MAX) return; -#ifndef OSD_BLEND_SHIFT_WORKAROUND - osd_setting_blend0_input(index, blending); -#endif if (index != OSD1) { /* here used freescale osd1/osd2 */ osd_log_dbg2(MODULE_BLEND, @@ -7013,9 +6803,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) index); osd_set_freescale(index, blending); } -#ifdef OSD_BLEND_SHIFT_WORKAROUND osd_setting_blend0_input(index, blending); -#endif osd_setting_blend0(blending); memcpy(&output1_data, &(layer_blend->output_data), sizeof(struct dispdata_s)); @@ -7031,22 +6819,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } layer_blend->input1 = BLEND_NO_DIN; layer_blend->input2 = input2; -#ifndef OSD_BLEND_SHIFT_WORKAROUND - if (osd_hw.blend_bypass) - layer_blend->input2 |= BYPASS_DIN; -#endif -#if 0 - layer_blend->input2_data.x = - osd_hw.free_dst_data[index].x_start; - layer_blend->input2_data.w = - osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start + 1; - layer_blend->input2_data.y = - osd_hw.free_dst_data[index].y_start; - layer_blend->input2_data.h = - osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start + 1; -#endif + osd_setting_blend1_input(index, blending); memcpy(&layer_blend->input2_data, &layer_blend->output_data, @@ -7134,32 +6907,10 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_log_dbg2(MODULE_BLEND, "before blend1: set osd%d freescale\n", index); osd_set_freescale(index, blending); -#ifdef OSD_BLEND_SHIFT_WORKAROUND layer_blend->input1 = BLEND_NO_DIN; /* must bypass for shift workaround */ layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN; layer_blend->blend_core1_bypass = 1; -#else - /* always route(bypass) to dout1 */ - layer_blend->input1 = BLEND_NO_DIN | BYPASS_DIN; - layer_blend->input2 = BLEND_DIN4; - if (osd_hw.blend_bypass) - layer_blend->input2 |= BYPASS_DIN; -#endif - #if 0 - layer_blend->input2_data.x = - osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; - layer_blend->input2_data.w = - osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start + 1; - layer_blend->input2_data.y = - osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; - layer_blend->input2_data.h = - osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start + 1; - #endif osd_setting_blend1_input(index, blending); memcpy(&layer_blend->input2_data, &layer_blend->output_data, @@ -7244,10 +6995,8 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND1_DIN; memcpy(&layer_blend->input1_data, &output1_data, sizeof(struct dispdata_s)); -#ifdef OSD_BLEND_SHIFT_WORKAROUND memcpy(&layer_blend->input2_data, &layer_blend->output_data, sizeof(struct dispdata_s)); -#endif osd_setting_blend2(blending); /* used osd0 freescale */ osd_set_freescale(OSD1, blending); @@ -7371,7 +7120,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } vpp_setting_blend(blending); break; -#ifdef OSD_BLEND_SHIFT_WORKAROUND case OSD_BLEND_AB_C: /* blend0 -->blend2-->sc->vpp_osd1 */ /* sc-->blend1-->blend2-->sc-->vpp_osd1 */ @@ -7476,7 +7224,563 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } vpp_setting_blend(blending); break; -#endif + } +} + +static void osd_setting_blend0_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_reg_s *blend_reg; + struct layer_blend_s *layer_blend; + u32 index = 0; + u32 bld_osd_h_start = 0, bld_osd_h_end = 0; + u32 bld_osd_v_start = 0, bld_osd_v_end = 0; + + if (!blending) + return; + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + /* blend0 only accept input1 */ + if (layer_blend->input1 & BYPASS_DIN) { + blend_reg->din0_byp_blend = 1; + layer_blend->input1 &= ~BYPASS_DIN; + } else + blend_reg->din0_byp_blend = 0; + if (layer_blend->input1 != BLEND_NO_DIN) { + /* calculate osd blend din scope */ + index = blend_din_to_osd(layer_blend->input1, blending); + if (index >= OSD_MAX) + return; + layer_blend->input1_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input1_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input1_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input1_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + bld_osd_h_start = + layer_blend->input1_data.x; + bld_osd_h_end = + layer_blend->input1_data.x + + layer_blend->input1_data.w - 1; + bld_osd_v_start = + layer_blend->input1_data.y; + bld_osd_v_end = + layer_blend->input1_data.y + + layer_blend->input1_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + } + layer_blend->output_data.x = 0; + layer_blend->output_data.y = 0; + layer_blend->output_data.w = layer_blend->input1_data.x + + layer_blend->input1_data.w; + layer_blend->output_data.h = layer_blend->input1_data.y + + layer_blend->input1_data.h; + osd_log_dbg2(MODULE_BLEND, + "blend0:input1_data[osd%d]:%d,%d,%d,%d\n", + index, + layer_blend->input1_data.x, + layer_blend->input1_data.y, + layer_blend->input1_data.w, + layer_blend->input1_data.h); + osd_log_dbg2(MODULE_BLEND, + "blend0:layer_blend->output_data:%d,%d,%d,%d\n", + layer_blend->output_data.x, + layer_blend->output_data.y, + layer_blend->output_data.w, + layer_blend->output_data.h); +} + +static void osd_setting_blend1_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + u32 index = 0; + u32 blend_hsize, blend_vsize; + u32 bld_osd_h_start = 0, bld_osd_h_end = 0; + u32 bld_osd_v_start = 0, bld_osd_v_end = 0; + /* for g12a blend shift issue */ + + if (!blending) + return; + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + /* blend1_dout to blend2 */ + blend_reg->din2_osd_sel = 0; + + if (layer_blend->input2 & BYPASS_DIN) { + /* blend1_din3 bypass to dout1 */ + blend_reg->din3_osd_sel = 1; + layer_blend->input2 &= ~BYPASS_DIN; + } else + /* blend1_din3 input to blend1 */ + blend_reg->din3_osd_sel = 0; + + if (layer_blend->input1 != BLEND_NO_DIN) { + index = blend_din_to_osd(layer_blend->input1, blending); + if (index >= OSD_MAX) + return; + layer_blend->input1_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input1_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input1_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input1_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + /* calculate osd blend din scope */ + bld_osd_h_start = + layer_blend->input1_data.x; + bld_osd_h_end = + layer_blend->input1_data.x + + layer_blend->input1_data.w - 1; + bld_osd_v_start = + layer_blend->input1_data.y; + bld_osd_v_end = + layer_blend->input1_data.y + + layer_blend->input1_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + osd_log_dbg2(MODULE_BLEND, + "blend1:input1_data(osd%d):%d,%d,%d,%d\n", + index, + layer_blend->input1_data.x, + layer_blend->input1_data.y, + layer_blend->input1_data.w, + layer_blend->input1_data.h); + } + if (layer_blend->input2 != BLEND_NO_DIN) { + index = blend_din_to_osd(layer_blend->input2, blending); + if (index >= OSD_MAX) + return; + layer_blend->input2_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input2_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input2_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input2_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + /* calculate osd blend din scope */ + bld_osd_h_start = + layer_blend->input2_data.x; + bld_osd_h_end = + layer_blend->input2_data.x + + layer_blend->input2_data.w - 1; + bld_osd_v_start = + layer_blend->input2_data.y; + bld_osd_v_end = + layer_blend->input2_data.y + + layer_blend->input2_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + osd_log_dbg2(MODULE_BLEND, + "layer_blend->input2_data:%d,%d,%d,%d\n", + layer_blend->input2_data.x, + layer_blend->input2_data.y, + layer_blend->input2_data.w, + layer_blend->input2_data.h); + } + if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) { + /* blend din3 bypass,output == input */ + if (layer_blend->input2 == BLEND_NO_DIN) { + memcpy(&layer_blend->output_data, + &layer_blend->input1_data, + sizeof(struct dispdata_s)); + } else { + memcpy(&layer_blend->output_data, + &layer_blend->input2_data, + sizeof(struct dispdata_s)); + } + } else + calc_max_output(blending); + blend_hsize = layer_blend->output_data.w; + blend_vsize = layer_blend->output_data.h; + blend_reg->osd_blend_blend1_size = + blend_vsize << 16 | blend_hsize; + + osd_log_dbg2(MODULE_BLEND, "layer_blend1->output_data:%d,%d,%d,%d\n", + layer_blend->output_data.x, + layer_blend->output_data.y, + layer_blend->output_data.w, + layer_blend->output_data.h); +} + +/* input w, h is background */ +static void osd_set_freescale_new(u32 index, + struct hw_osd_blending_s *blending) + +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + u32 width, height; + u32 src_height; + + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + if (index >= osd_hw.osd_meson_dev.viu1_osd_count) { + osd_log_err("error osd index=%d\n", index); + return; + } + osd_hw.free_scale_enable[index] = 0x10001; + osd_hw.free_scale[index].h_enable = 1; + osd_hw.free_scale[index].v_enable = 1; + osd_hw.free_scale_mode[index] = 1; + + osd_hw.free_src_data[index].x_start = + osd_hw.src_data[index].x; + osd_hw.free_src_data[index].x_end = + osd_hw.src_data[index].x + + osd_hw.src_data[index].w - 1; + osd_hw.free_src_data[index].y_start = + osd_hw.src_data[index].y; + osd_hw.free_src_data[index].y_end = + osd_hw.src_data[index].y + + osd_hw.src_data[index].h - 1; + + /* direct used dst as freescale dst */ + osd_hw.free_dst_data[index].x_start = + osd_hw.dst_data[index].x; + osd_hw.free_dst_data[index].y_start = + osd_hw.dst_data[index].y; + width = osd_hw.dst_data[index].w; + height = osd_hw.dst_data[index].h; + if (osd_hw.field_out_en) { + height = height >> 1; + osd_hw.free_dst_data[index].y_start >>= 1; + } + osd_hw.free_dst_data[index].x_end = + osd_hw.free_dst_data[index].x_start + + width - 1; + osd_hw.free_dst_data[index].y_end = + osd_hw.free_dst_data[index].y_start + + height - 1; + + src_height = osd_hw.free_src_data[index].x_end - + osd_hw.free_src_data[index].x_start + 1; + osd_set_dummy_data(index, 0xff); + osd_log_dbg2(MODULE_BLEND, "osd%d:free_src_data:%d,%d,%d,%d\n", + index, + osd_hw.free_src_data[index].x_start, + osd_hw.free_src_data[index].y_start, + osd_hw.free_src_data[index].x_end, + osd_hw.free_src_data[index].y_end); + osd_log_dbg2(MODULE_BLEND, "osd%d:free_dst_data:%d,%d,%d,%d\n", + index, + osd_hw.free_dst_data[index].x_start, + osd_hw.free_dst_data[index].y_start, + osd_hw.free_dst_data[index].x_end, + osd_hw.free_dst_data[index].y_end); +} + +/* every output is next path input */ +static void set_blend_path_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + struct dispdata_s output1_data; + u32 index = 0; + u8 input1 = 0, input2 = 0; + u32 output_index; + + if (!blending) + return; + output_index = get_output_device_id(index); + + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + layer_blend->blend_core1_bypass = 0; + switch (blending->osd_blend_mode) { + case OSD_BLEND_NONE: + blend_reg->postbld_osd1_premult = 0; + blend_reg->postbld_src4_sel = POSTBLD_CLOSE; + blend_reg->postbld_src3_sel = POSTBLD_CLOSE; + blend_reg->postbld_osd2_premult = 0; + break; + case OSD_BLEND_A: + /* sc-->blend0-->blend2-->vpp_osd1 */ + layer_blend->input1 = BLEND_DIN1; + if (osd_hw.blend_bypass) + layer_blend->input1 |= BYPASS_DIN; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + if (!blend_reg->din0_byp_blend) { + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + /* same with blend0's background */ + osd_setting_blend2(blending); + } + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_AC: + /* sc-->blend0 -->blend1-->blend2-->vpp_osd1 */ + /* sc-->blend0 & blend1-->blend2-->vpp_osd1 */ + if (!blending->b_exchange_din) { + input1 = BLEND_DIN1; + input2 = BLEND_DIN4; + } else { + input1 = BLEND_DIN4; + input2 = BLEND_DIN1; + } + layer_blend->input1 = input1; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(input1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + index = blend_din_to_osd(input2, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + layer_blend->input1 = BLEND_NO_DIN; + layer_blend->input2 = input2; + osd_setting_blend1_new(blending); + + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + + /* blend0 output-> blend2 input1 */ + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + /* blend1 output-> blend2 input2 */ + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_A_C: + /* sc-->blend0 -->blend2->vpp_osd1 */ + /* sc-->blend1 -->vpp_osd2 */ + layer_blend->input1 = BLEND_DIN1; + if (osd_hw.blend_bypass) + layer_blend->input1 |= BYPASS_DIN; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + if (!blend_reg->din0_byp_blend) { + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + /* background is same with blend0's background */ + osd_setting_blend2(blending); + } + /* save blend0/blend2 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + /* adjust input 1 offset*/ + output1_data.x += + osd_hw.disp_info[output_index].position_x; + output1_data.y += + osd_hw.disp_info[output_index].position_y; + + index = blend_din_to_osd(BLEND_DIN4, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + layer_blend->input1 = BLEND_NO_DIN; + layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN; + layer_blend->blend_core1_bypass = 1; + osd_setting_blend1_new(blending); + /* adjust input 2 offset*/ + layer_blend->output_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->output_data.y += + osd_hw.disp_info[output_index].position_y; + + if (!blending->b_exchange_blend_in) { + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + } else { + layer_blend->input1 = BLEND1_DIN; + layer_blend->input2 = BLEND2_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &output1_data, + sizeof(struct dispdata_s)); + } + vpp_setting_blend(blending); + break; + case OSD_BLEND_ABC: + /* sc->blend0 -->blend2-->vpp_osd1 */ + /* sc-->blend1 -->blend2 */ + input1 = BLEND_DIN1; + input2 = BLEND_DIN4; + layer_blend->input1 = input1; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(input1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + layer_blend->input1 = BLEND_DIN3; + layer_blend->input2 = input2; + index = blend_din_to_osd(layer_blend->input1, blending); + osd_set_freescale_new(index, blending); + index = blend_din_to_osd(layer_blend->input2, blending); + osd_set_freescale_new(index, blending); + osd_setting_blend1_new(blending); + + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_AB_C: + /* sc-->blend0 -->blend2->vpp_osd1 */ + /* sc-->blend1-->blend2-->vpp_osd1 */ + /* sc -->vpp_osd2 */ + layer_blend->input1 = BLEND_DIN1; + layer_blend->input2 = BLEND_NO_DIN; + blending->blend_din = BLEND_DIN1; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + /* din3 input to blend1 */ + layer_blend->input1 = BLEND_DIN3; + layer_blend->input2 = BLEND_NO_DIN | BYPASS_DIN; + layer_blend->blend_core1_bypass = 1; + blending->blend_din = BLEND_DIN3; + index = blend_din_to_osd(BLEND_DIN3, blending); + osd_set_freescale_new(index, blending); + osd_setting_blend1_new(blending); + + /* din1=>blend0 & din3-> blend1 ==> blend2 */ + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + output1_data.x += + osd_hw.disp_info[output_index].position_x; + output1_data.y += + osd_hw.disp_info[output_index].position_y; + osd_log_dbg2(MODULE_BLEND, "output1_data:%d,%d,%d,%d\n", + output1_data.x, + output1_data.w, + output1_data.y, + output1_data.h); + + + /* din4 ==> vpp */ + index = blend_din_to_osd(BLEND_DIN4, blending); + blending->blend_din = BLEND_DIN4; + osd_set_freescale_new(index, blending); + layer_blend->input2_data.x = + osd_hw.free_dst_data[index].x_start + + osd_hw.disp_info[output_index].position_x; + layer_blend->input2_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input2_data.y = + osd_hw.free_dst_data[index].y_start + + osd_hw.disp_info[output_index].position_y; + layer_blend->input2_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + /* 2vpp input */ + if (!blending->b_exchange_blend_in) { + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + } else { + layer_blend->input1 = BLEND1_DIN; + layer_blend->input2 = BLEND2_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->input2_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, + &output1_data, + sizeof(struct dispdata_s)); + } + vpp_setting_blend(blending); + break; } } @@ -7485,16 +7789,16 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) int i; u32 reg_offset = 2; u32 osd1_alpha_div = 0, osd2_alpha_div = 0; -#ifdef OSD_BLEND_SHIFT_WORKAROUND u32 osd_count = OSD_BLEND_LAYERS; -#else - u32 osd_count = osd_hw.osd_meson_dev.viu1_osd_count; -#endif u32 dv_core2_hsize; u32 dv_core2_vsize; if (!blend_reg) return; + /* osd0 scale position before osd blend */ + if (osd_hw.osd_meson_dev.osd0_sc_independ) + VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCALE_CTRL, 0x01); + /* osd blend ctrl */ VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_CTRL, 4 << 29| @@ -7556,7 +7860,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i, blend_reg->osd_blend_din_scope_v[i]); } -#ifdef OSD_BLEND_SHIFT_WORKAROUND else { if ((blend_reg->osd_blend_din_scope_v[i] & 0xffff) == 0) blend_reg->osd_blend_din_scope_v[i] = 0x43a0439; @@ -7564,7 +7867,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i, blend_reg->osd_blend_din_scope_v[i]); } -#endif } dv_core2_vsize = (blend_reg->osd_blend_blend0_size >> 16) & 0xfff; @@ -7679,7 +7981,8 @@ static int osd_setting_order(u32 output_index) blending->b_exchange_blend_in = false; blending->osd1_freescale_disable = false; adjust_dst_position(output_index); - uniformization_fb(OSD1, blending); + if (!osd_hw.osd_meson_dev.osd0_sc_independ) + uniformization_fb(OSD1, blending); /* set blend mode */ set_blend_mode(blending); @@ -7688,7 +7991,10 @@ static int osd_setting_order(u32 output_index) set_blend_din(blending); /* set blend path */ - set_blend_path(blending); + if (osd_hw.osd_meson_dev.osd0_sc_independ) + set_blend_path_new(blending); + else + set_blend_path(blending); line1 = get_enter_encp_line(); vinfo_height = osd_hw.field_out_en[output_index] ? (osd_hw.vinfo_height[output_index] * 2) : diff --git a/drivers/amlogic/media/osd/osd_reg.h b/drivers/amlogic/media/osd/osd_reg.h index 517ca97827f0..e2218bd572c1 100644 --- a/drivers/amlogic/media/osd/osd_reg.h +++ b/drivers/amlogic/media/osd/osd_reg.h @@ -392,7 +392,7 @@ #define VPP_OSD_SCALE_COEF_IDX 0x1dcc #define VPP_OSD_SCALE_COEF 0x1dcd #define VPP_INT_LINE_NUM 0x1dce - +#define VPP_OSD_SCALE_CTRL 0x1dff /* osd2 scaler */ #define OSD2_VSC_PHASE_STEP 0x3d00 #define OSD2_VSC_INI_PHASE 0x3d01 From ae04da094d0e168fb7355f4a6619d445aee1cde8 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 12 Apr 2019 10:34:25 +0800 Subject: [PATCH 0495/1060] osd: frame just display on half screen [1/1] PD#SWPL-7039 Problem: bring up osd for TM2 frame just display on half screen Solution: fix field_out_en value from array Verify: Verified on T962e2_ab319 Change-Id: Id07f3d813242f031125fcac11d3fa05205895448 Signed-off-by: Jian Cao --- drivers/amlogic/media/osd/osd_hw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index fbceac9bd936..98d55c506e2e 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -7430,6 +7430,7 @@ static void osd_set_freescale_new(u32 index, struct layer_blend_reg_s *blend_reg; u32 width, height; u32 src_height; + u32 output_index; layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -7437,6 +7438,7 @@ static void osd_set_freescale_new(u32 index, osd_log_err("error osd index=%d\n", index); return; } + output_index = get_output_device_id(index); osd_hw.free_scale_enable[index] = 0x10001; osd_hw.free_scale[index].h_enable = 1; osd_hw.free_scale[index].v_enable = 1; @@ -7460,7 +7462,7 @@ static void osd_set_freescale_new(u32 index, osd_hw.dst_data[index].y; width = osd_hw.dst_data[index].w; height = osd_hw.dst_data[index].h; - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { height = height >> 1; osd_hw.free_dst_data[index].y_start >>= 1; } From 40861c581d0e8b0cb95dcbb2313a5fb195085171 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Wed, 10 Apr 2019 12:21:38 +0800 Subject: [PATCH 0496/1060] osd: fix hotplug hdmi causes system crash [1/1] PD#SWPL-7009 Problem: hotplug hdmi causes system crash when unplug hdmi display mode is null, hwc hasn't received event and post frame normal but osd vsync lost, which caused wait hw vsync timeout(1s), and fd leak. Solution: when process every frame, if display mode is null, exit frame process just process fence. Verify: verified on Raven, franklin Change-Id: Icbe7cd76776e46a6ed79c6cee3ea05772cc5f9d2 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/osd/osd_hw.c | 75 ++++++++++++++++++------------ 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 98d55c506e2e..4d92fa296b54 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -1125,7 +1125,8 @@ static int sync_render_single_fence(u32 index, u32 yres, kthread_queue_work(&buffer_toggle_worker[output_index], &buffer_toggle_work[output_index]); request->out_fen_fd = out_fence_fd; - __close_fd(current->files, request->in_fen_fd); + if (request->in_fen_fd >= 0) + __close_fd(current->files, request->in_fen_fd); return out_fence_fd; } @@ -1192,8 +1193,10 @@ static int sync_render_layers_fence(u32 index, u32 yres, fence_map->layer_map[index].in_fd, fence_map->layer_map[index].out_fd); request->out_fen_fd = out_fence_fd; - __close_fd(current->files, in_fence_fd); - __close_fd(current->files, request->shared_fd); + if (in_fence_fd >= 0) + __close_fd(current->files, in_fence_fd); + if (request->shared_fd >= 0) + __close_fd(current->files, request->shared_fd); return out_fence_fd; } @@ -1997,8 +2000,16 @@ void osd_wait_vsync_hw(void) if (pxp_mode) timeout = msecs_to_jiffies(50); - else - timeout = msecs_to_jiffies(1000); + else { + struct vinfo_s *vinfo; + + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) { + timeout = msecs_to_jiffies(1); + } else + timeout = msecs_to_jiffies(1000); + } wait_event_interruptible_timeout( osd_vsync_wq, vsync_hit, timeout); } @@ -4024,6 +4035,14 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) if (index >= OSD2) goto out; + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) + goto out; + + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; + if (timeline_created[output_index]) { /* out fence created success. */ ret = osd_wait_buf_ready(fence_map); if (ret < 0) @@ -4045,15 +4064,6 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) AFBC_EN | BLOCK_SPLIT | YUV_TRANSFORM | SUPER_BLOCK_ASPECT; } - vinfo = get_current_vinfo(); - if (vinfo) { - if ((strcmp(vinfo->name, "invalid")) && - (strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width[output_index] = vinfo->width; - osd_hw.vinfo_height[output_index] = - vinfo->height; - } - } /* Todo: */ if (fence_map->ext_addr && fence_map->width && fence_map->height) { @@ -4255,17 +4265,17 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) osd_wait_vsync_hw(); } } +#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT + if (ret) + osd_ext_clone_pan(index); +#endif +out: if (timeline_created[output_index]) { if (ret) osd_timeline_increase(output_index); else osd_log_err("------NOT signal out_fence ERROR\n"); } -#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT - if (ret) - osd_ext_clone_pan(index); -#endif -out: if (fence_map->in_fence) osd_put_fenceobj(fence_map->in_fence); } @@ -4467,15 +4477,17 @@ static void _osd_pan_display_layers_fence( int ret; int start_index = 0; int backup_en = 0; - int osd_count; + int osd_count = 0; /* osd_count need -1 when VIU2 enable */ struct layer_fence_map_s *layer_map = NULL; - if (vinfo && (strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width[output_index] = vinfo->width; - osd_hw.vinfo_height[output_index] = vinfo->field_height; - } + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) + /* vout is null, release fence */ + goto out; + + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->field_height; memcpy(&osd_hw.disp_info[output_index], &fence_map->disp_info, sizeof(struct display_flip_info_s)); if (output_index == VIU1) { @@ -4521,6 +4533,7 @@ static void _osd_pan_display_layers_fence( /* set hw regs */ if (osd_hw.osd_display_debug != OSD_DISP_DEBUG) osd_setting_blend(output_index); +out: /* signal out fence */ if (timeline_created[output_index]) { if (osd_hw.osd_debug.osd_single_step_mode) { @@ -10482,12 +10495,14 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) else if (output_index == VIU2) vinfo = get_current_vinfo2(); #endif - - if (vinfo && (strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width[output_index] = vinfo->width; - osd_hw.vinfo_height[output_index] = vinfo->height; + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) { + return; } + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; + osd_hw.osd_afbcd[index].enable = (plane_map->afbc_inter_format & AFBC_EN) >> 31; if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { From c51d9a2be3170256f38a4669e09d5d7d71108b48 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Mon, 18 Feb 2019 04:33:22 -0500 Subject: [PATCH 0497/1060] hdmitx: add auto low latency mode(ALLM) [1/1] PD#SWPL-4705 Problem: Lack ALLM function Solution: Add ALLM function Verify: GXL/P212 If Rx supports ALLM, then echo 1 > /sys/class/amhdmitx/amhdmitx0/allm_mode otherwise it will set failed, cat allm_mode and will get 0. Change-Id: I00233e5a5aac133b405590e7df78c7c4805ed0ef Signed-off-by: Zongdong Jiao Conflicts: drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c --- .../vout/hdmitx/hdmi_common/hdmi_parameters.c | 19 +++ .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 37 +++--- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 76 +++++++++++- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c | 110 ++++++++++++++++-- .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 64 ++++++++++ .../amlogic/media/vout/hdmi_tx/hdmi_common.h | 7 ++ .../media/vout/hdmi_tx/hdmi_tx_module.h | 56 +++++++++ 7 files changed, 346 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c index 0340e8c30f57..9a5ad9eb00b5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -3318,3 +3318,22 @@ unsigned int hdmi_get_csc_coef( return 1; } +bool is_hdmi14_4k(enum hdmi_vic vic) +{ + bool ret = 0; + + switch (vic) { + case HDMI_3840x2160p24_16x9: + case HDMI_3840x2160p25_16x9: + case HDMI_3840x2160p30_16x9: + case HDMI_4096x2160p24_256x135: + ret = 1; + break; + default: + ret = 0; + break; + } + + return ret; +} + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index 4ca47e8ab8d9..d47c6c604fb5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -319,9 +319,9 @@ int Edid_Parse_check_HDMI_VSDB(struct hdmitx_dev *hdev, if (temp_addr >= VSpecificBoundary) ret = -1; else { - if ((buff[BlockAddr + 1] != 0x03) || - (buff[BlockAddr + 2] != 0x0C) || - (buff[BlockAddr + 3] != 0x0)) + if ((buff[BlockAddr + 1] != GET_OUI_BYTE0(HDMI_IEEE_OUI)) || + (buff[BlockAddr + 2] != GET_OUI_BYTE1(HDMI_IEEE_OUI)) || + (buff[BlockAddr + 3] != GET_OUI_BYTE2(HDMI_IEEE_OUI))) ret = -1; } return ret; @@ -1501,7 +1501,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, if ((BlockBuf[offset] == 0x03) && (BlockBuf[offset+1] == 0x0c) && (BlockBuf[offset+2] == 0x00)) { - pRXCap->IEEEOUI = 0x000c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; pRXCap->ColorDeepSupport = (count > 5) ? BlockBuf[offset+5] : 0; set_vsdb_dc_cap(pRXCap); @@ -1548,7 +1548,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, } else if ((BlockBuf[offset] == 0xd8) && (BlockBuf[offset+1] == 0x5d) && (BlockBuf[offset+2] == 0xc4)) { - pRXCap->HF_IEEEOUI = 0xd85dc4; + pRXCap->HF_IEEEOUI = HF_IEEE_OUI; pRXCap->Max_TMDS_Clock2 = BlockBuf[offset+4]; pRXCap->scdc_present = !!(BlockBuf[offset+5] & (1 << 7)); @@ -1558,6 +1558,11 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, !!(BlockBuf[offset+5] & (1 << 3)); set_vsdb_dc_420_cap(&hdmitx_device->RXCap, &BlockBuf[offset]); + if (count > 7) { + unsigned char b7 = BlockBuf[offset+7]; + + pRXCap->allm = !!(b7 & (1 << 1)); + } } offset += count; /* ignore the remaind. */ @@ -2100,9 +2105,9 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) if ((CheckSum & 0xff) == 0) hdmitx_device->RXCap.IEEEOUI = 0; else - hdmitx_device->RXCap.IEEEOUI = 0x0c03; + hdmitx_device->RXCap.IEEEOUI = HDMI_IEEE_OUI; if (zero_numbers > 120) - hdmitx_device->RXCap.IEEEOUI = 0x0c03; + hdmitx_device->RXCap.IEEEOUI = HDMI_IEEE_OUI; return 0; /* do nothing. */ } @@ -2168,14 +2173,14 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) } if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; pr_info(EDID "find IEEEOUT\n"); } else { pRXCap->IEEEOUI = 0x0; pr_info(EDID "not find IEEEOUT\n"); } - if ((pRXCap->IEEEOUI != 0x0c03) || (pRXCap->IEEEOUI == 0x0) || + if ((pRXCap->IEEEOUI != HDMI_IEEE_OUI) || (pRXCap->IEEEOUI == 0x0) || (pRXCap->VIC_count == 0)) hdmitx_edid_set_default_vic(hdmitx_device); @@ -2186,10 +2191,10 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) pRXCap->IEEEOUI = 0x0; pr_info(EDID "sink is DVI device\n"); } else - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; if (edid_zero_data(EDID_buf)) - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; if ((!pRXCap->AUD_count) && (!pRXCap->IEEEOUI)) hdmitx_edid_set_default_aud(hdmitx_device); @@ -2201,7 +2206,7 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) hdmitx_device->tmp_buf[i] = 0; if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) { - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; pr_info(EDID "Invalid edid, consider RX as HDMI device\n"); } /* update RX HDR information */ @@ -2400,7 +2405,7 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, pRXCap = &(hdev->RXCap); /* DVI case, only 8bit */ - if (pRXCap->IEEEOUI != 0x0c03) { + if (pRXCap->IEEEOUI != HDMI_IEEE_OUI) { if (para->cd != COLORDEPTH_24B) return 0; } @@ -2563,7 +2568,7 @@ void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device) /* Note: in most cases, we think that rx is tv and the default * IEEEOUI is HDMI Identifier */ - pRXCap->IEEEOUI = 0x000c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; hdmitx_device->vic_count = 0; hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; @@ -2755,6 +2760,10 @@ int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, "MaxTMDSClock2 %d MHz\n", pRXCap->Max_TMDS_Clock2 * 5); } + if (pRXCap->allm) + pos += snprintf(buffer+pos, buffer_len-pos, "ALLM: %x\n", + pRXCap->allm); + pos += snprintf(buffer+pos, buffer_len-pos, "vLatency: "); if (pRXCap->vLatency == LATENCY_INVALID_UNKNOWN) pos += snprintf(buffer+pos, buffer_len-pos, diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 4bc31062d63d..1724d90af602 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -2567,6 +2567,77 @@ static ssize_t store_valid_mode(struct device *dev, return count; } +static ssize_t show_allm_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct hdmitx_dev *hdev = &hdmitx_device; + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + + if (!pRXCap->allm) { /* Rx not support ALLM */ + pos += snprintf(buf + pos, PAGE_SIZE, "0\n\r"); + return pos; + } + + if (hdev->allm_mode == 1) + pos += snprintf(buf + pos, PAGE_SIZE, "game\n\r"); + else if (hdev->allm_mode == 2) + pos += snprintf(buf + pos, PAGE_SIZE, "graphics\n\r"); + else if (hdev->allm_mode == 3) + pos += snprintf(buf + pos, PAGE_SIZE, "photo\n\r"); + else if (hdev->allm_mode == 4) + pos += snprintf(buf + pos, PAGE_SIZE, "cinema\n\r"); + else + pos += snprintf(buf + pos, PAGE_SIZE, "0\n\r"); + + return pos; +} + +static ssize_t store_allm_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + struct rx_cap *pRXCap = &hdev->RXCap; + + pr_info("hdmitx: store allm_mode as %s\n", buf); + + if (!pRXCap->allm) /* Rx not support ALLM */ + return count; + +#define CMP_STR(str) (strncmp(buf, str, strlen(str)) == 0) + if (CMP_STR("0")) { + // disable ALLM + hdev->allm_mode = 0; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, CLEAR_ALLM_MODE); + hdmitx_construct_vsif(hdev, VT_ALLM, 0, NULL); + if (is_hdmi14_4k(hdev->cur_VIC)) + hdmitx_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL); + return count; + } + if (CMP_STR("1") || CMP_STR("game") || CMP_STR("graphics") + || CMP_STR("photo") || CMP_STR("cinema")) { + hdmitx_construct_vsif(hdev, VT_ALLM, 1, NULL); + } + if (CMP_STR("1") || CMP_STR("game")) { + hdev->allm_mode = 1; + // enable the default GAME ALLM + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_GAME); + } + if (CMP_STR("graphics")) { + hdev->allm_mode = 2; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_GRAPHICS); + } + if (CMP_STR("photo")) { + hdev->allm_mode = 3; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_PHOTO); + } + if (CMP_STR("cinema")) { + hdev->allm_mode = 4; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_CINEMA); + } + + return count; +} /**/ static ssize_t show_hdr_cap(struct device *dev, @@ -3452,6 +3523,7 @@ static DEVICE_ATTR(hdr_cap, 0444, show_hdr_cap, NULL); static DEVICE_ATTR(dv_cap, 0444, show_dv_cap, NULL); static DEVICE_ATTR(dc_cap, 0444, show_dc_cap, NULL); static DEVICE_ATTR(valid_mode, 0664, show_valid_mode, store_valid_mode); +static DEVICE_ATTR(allm_mode, 0664, show_allm_mode, store_allm_mode); static DEVICE_ATTR(aud_ch, 0664, show_aud_ch, store_aud_ch); static DEVICE_ATTR(avmute, 0664, show_avmute, store_avmute); static DEVICE_ATTR(swap, 0644, show_swap, store_swap); @@ -3845,7 +3917,7 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) } else #endif { - if (hdev->RXCap.IEEEOUI != 0x000c03) + if (hdev->RXCap.ieeeoui != HDMI_IEEEOUI) hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, DVI_MODE); else @@ -4604,6 +4676,7 @@ static int amhdmitx_probe(struct platform_device *pdev) ret = device_create_file(dev, &dev_attr_support_3d); ret = device_create_file(dev, &dev_attr_dc_cap); ret = device_create_file(dev, &dev_attr_valid_mode); + ret = device_create_file(dev, &dev_attr_allm_mode); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND register_early_suspend(&hdmitx_early_suspend_handler); @@ -4673,6 +4746,7 @@ static int amhdmitx_remove(struct platform_device *pdev) device_remove_file(dev, &dev_attr_dv_cap); device_remove_file(dev, &dev_attr_dc_cap); device_remove_file(dev, &dev_attr_valid_mode); + device_remove_file(dev, &dev_attr_allm_mode); device_remove_file(dev, &dev_attr_hpd_state); device_remove_file(dev, &dev_attr_rhpd_state); device_remove_file(dev, &dev_attr_max_exceed); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c index b1ffd00dee56..3950be833887 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c @@ -772,12 +772,12 @@ static void hdmi_tx_construct_avi_packet( *************************************/ /* - * HDMI Identifier = 0x000c03 + * HDMI Identifier = HDMI_IEEE_OUI 0x000c03 * If not, treated as a DVI Device */ static int is_dvi_device(struct rx_cap *pRXCap) { - if (pRXCap->IEEEOUI != 0x000c03) + if (pRXCap->IEEEOUI != HDMI_IEEE_OUI) return 1; else return 0; @@ -878,6 +878,29 @@ int hdmitx_set_display(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode) hdmi_set_vend_spec_infofram(hdev, 0); else ; + + switch (hdev->RXCap.allm ? hdev->allm_mode : 0) { + case 1: /* game */ + hdmitx_construct_vsif(hdev, VT_ALLM, 1, NULL); + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_GAME); + break; + case 2: /* graphics */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_GRAPHICS); + break; + case 3: /* photo */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_PHOTO); + break; + case 4: /* cinema */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_CINEMA); + break; + default: + break; + } + ret = 0; } } @@ -908,9 +931,9 @@ static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEE_OUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEE_OUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEE_OUI); VEN_DB[3] = 0x00; /* 4k x 2k Spec P156 */ if (VideoCode == HDMI_4k2k_30) { @@ -944,9 +967,9 @@ int hdmi_set_3d(struct hdmitx_dev *hdev, int type, unsigned int param) else { for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEE_OUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEE_OUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEE_OUI); VEN_DB[3] = 0x40; VEN_DB[4] = type<<4; VEN_DB[5] = param<<4; @@ -984,3 +1007,74 @@ static void hdmitx_set_spd_info(struct hdmitx_dev *hdev) SPD_DB[24] = 0x1; hdev->HWOp.SetPacket(HDMI_SOURCE_DESCRIPTION, SPD_DB, SPD_HB); } + +static void fill_hdmi4k_vsif_data(enum hdmi_vic vic, unsigned char *DB, + unsigned char *HB) +{ + if (!DB || !HB) + return; + + if (vic == HDMI_4k2k_30) + DB[4] = 0x1; + else if (vic == HDMI_4k2k_25) + DB[4] = 0x2; + else if (vic == HDMI_4k2k_24) + DB[4] = 0x3; + else if (vic == HDMI_4k2k_smpte_24) + DB[4] = 0x4; + else + return; + HB[0] = 0x81; + HB[1] = 0x01; + HB[2] = 0x5; + DB[3] = 0x20; +} + +int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, + int on, void *param) +{ + unsigned char HB[3] = {0x81, 0x1, 0}; + unsigned char len = 0; /* HB[2] = len */ + unsigned char DB[27]; /* to be fulfilled */ + unsigned int ieeeoui = 0; + + if (!hdev || type >= VT_MAX) + return 0; + memset(DB, 0, sizeof(DB)); + + switch (type) { + case VT_DEFAULT: + break; + case VT_HDMI14_4K: + ieeeoui = HDMI_IEEE_OUI; + len = 5; + if (is_hdmi14_4k(hdev->cur_VIC)) { + fill_hdmi4k_vsif_data(hdev->cur_VIC, DB, HB); + hdmitx_set_avi_vic(0); + } + break; + case VT_ALLM: + ieeeoui = HF_IEEE_OUI; + len = 5; + DB[3] = 0x1; /* Fixed value */ + if (on) { + DB[4] |= 1 << 1; /* set bit1, ALLM_MODE */ + if (is_hdmi14_4k(hdev->cur_VIC)) + hdmitx_set_avi_vic(hdev->cur_VIC); + } else { + DB[4] &= ~(1 << 1); /* clear bit1, ALLM_MODE */ + /* still send out HS_VSIF, no set AVI.VIC = 0 */ + } + break; + default: + break; + } + + HB[2] = len; + DB[0] = GET_OUI_BYTE0(ieeeoui); + DB[1] = GET_OUI_BYTE1(ieeeoui); + DB[2] = GET_OUI_BYTE2(ieeeoui); + + hdev->HWOp.SetDataPacket(HDMI_PACKET_VEND, DB, HB); + return 1; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index c7ff9fd16c3e..7ceb66a67cc3 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -68,6 +68,8 @@ struct ksv_lists_ { static struct ksv_lists_ tmp_ksv_lists; static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB); +static void hdmitx_set_datapacket(int type, unsigned char *DB, + unsigned char *HB); static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF); static int hdmitx_set_dispmode(struct hdmitx_dev *hdev); @@ -280,6 +282,11 @@ static void config_avmute(unsigned int val) } } +void hdmitx_set_avi_vic(enum hdmi_vic vic) +{ + hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, vic); +} + static int read_avmute(void) { int val; @@ -645,6 +652,7 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev) void HDMITX_Meson_Init(struct hdmitx_dev *hdev) { hdev->HWOp.SetPacket = hdmitx_set_packet; + hdev->HWOp.SetDataPacket = hdmitx_set_datapacket; hdev->HWOp.SetAudioInfoFrame = hdmitx_setaudioinfoframe; hdev->HWOp.SetDispMode = hdmitx_set_dispmode; hdev->HWOp.SetAudMode = hdmitx_set_audmode; @@ -2453,6 +2461,40 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) } } +static void hdmitx_set_datapacket(int type, unsigned char *DB, + unsigned char *HB) +{ + int i; +#if 0 + pr_info("HB: %02x %02x %02x\nDB:", HB[0], HB[1], HB[2]); + for (i = 0; (i < 24) && (i < HB[2]); i++) + pr_info(" %02x", DB[i]); + pr_info("\n"); +#endif + switch (type) { + case HDMI_PACKET_VEND: + if ((!DB) || (!HB)) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 0x0); + return; + } + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, HB[2]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, DB[0]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID1, DB[1]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, DB[2]); + for (i = 0; (i < 24) && (i < HB[2]); i++) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD0 + i, DB[3 + i]); + /* Enable VSI packet */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 1, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO1, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO2, 0x10); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 4, 1); + break; + default: + break; + } +} + static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF) @@ -5063,6 +5105,28 @@ static int hdmitx_cntl_config(struct hdmitx_dev *hdev, unsigned int cmd, case CONF_AVI_YQ01: hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv, 2, 2); break; + case CONF_ALLM_MODE: + if (argv == CLEAR_ALLM_MODE) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 0, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, 0, 0, 2); + break; + } + if (argv == GET_ALLM_MODE) { + if (hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF2) & (1 << 7)) + ret = hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF3) & 3; + else + ret = -1; + break; + } + /* set ALLM mode */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv & 3, 0, 2); + if (argv == SET_ALLM_PHOTO) { + // TODO + // Extended colorimetry field may be + // sYcc601, AdobeYcc601 or AdobeRGB + } + break; case CONF_EMP_NUMBER: hdmitx_set_reg_bits(HDMITX_TOP_EMP_CNTL0, argv, 16, 16); break; diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h index e6c8e9cc52f4..64c8e3a0c8fc 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h @@ -30,6 +30,13 @@ #define HDMITX_VIC_MASK 0xff +/* Refer to http://standards-oui.ieee.org/oui/oui.txt */ +#define HDMI_IEEE_OUI 0x000C03 +#define HF_IEEE_OUI 0xC45DD8 +#define GET_OUI_BYTE0(oui) (oui & 0xff) /* Little Endian */ +#define GET_OUI_BYTE1(oui) ((oui >> 8) & 0xff) +#define GET_OUI_BYTE2(oui) ((oui >> 16) & 0xff) + enum hdmi_vic { /* Refer to CEA 861-D */ HDMI_Unknown = 0, diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 274f5db0a169..0f3e8521f56c 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -110,6 +110,11 @@ struct rx_cap { unsigned int dc_30bit_420:1; unsigned int dc_36bit_420:1; unsigned int dc_48bit_420:1; + unsigned int max_frl_rate:4; + unsigned int fpap_start_loc:1; + unsigned int allm:1; + unsigned int mdelta:1; + unsigned int fva:1; unsigned int hdr_sup_eotf_sdr:1; unsigned int hdr_sup_eotf_hdr:1; unsigned int hdr_sup_eotf_smpte_st_2084:1; @@ -323,6 +328,12 @@ struct hdmitx_dev { struct { void (*SetPacket)(int type, unsigned char *DB, unsigned char *HB); + /* In original SetPacket, there are many policys, like + * if ((DB[4] >> 4) == T3D_FRAME_PACKING) + * Need a only pure data packet to call + */ + void (*SetDataPacket)(int type, unsigned char *DB, + unsigned char *HB); void (*SetAudioInfoFrame)(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF); int (*SetDispMode)(struct hdmitx_dev *hdmitx_device); @@ -409,6 +420,8 @@ struct hdmitx_dev { /* 0.1% clock shift, 1080p60hz->59.94hz */ unsigned int frac_rate_policy; unsigned int rxsense_policy; + /* allm_mode: 1/game, 2/graphcis, 3/photo, 4/cinema */ + unsigned int allm_mode; unsigned int sspll; /* configure for I2S: 8ch in, 2ch out */ /* 0: default setting 1:ch0/1 2:ch2/3 3:ch4/5 4:ch6/7 */ @@ -494,6 +507,13 @@ struct hdmitx_dev { #define YCC_RANGE_LIM 0 #define YCC_RANGE_FUL 1 #define YCC_RANGE_RSVD 2 +#define CONF_ALLM_MODE (CMD_CONF_OFFSET + 0X2000 + 0x04) + #define SET_ALLM_GRAPHICS 0 + #define SET_ALLM_PHOTO 1 + #define SET_ALLM_CINEMA 2 + #define SET_ALLM_GAME 3 + #define CLEAR_ALLM_MODE 0xf + #define GET_ALLM_MODE 0x10 #define CONF_VIDEO_MUTE_OP (CMD_CONF_OFFSET + 0x1000 + 0x04) #define VIDEO_MUTE 0x1 #define VIDEO_UNMUTE 0x2 @@ -596,6 +616,42 @@ extern void hdmitx_edid_buf_compare_print(struct hdmitx_dev *hdmitx_device); extern const char *hdmitx_edid_get_native_VIC(struct hdmitx_dev *hdmitx_device); +/* VSIF: Vendor Specific InfoFrame + * It has multiple purposes: + * 1. HDMI1.4 4K, HDMI_VIC=1/2/3/4, 2160p30/25/24hz, smpte24hz, AVI.VIC=0 + * In CTA-861-G, matched with AVI.VIC=95/94/93/98 + * 2. 3D application, TB/SS/FP + * 3. DolbyVision, with Len=0x18 + * 4. HDR10plus + * 5. HDMI20 3D OSD disparity / 3D dual-view / 3D independent view / ALLM + * Some functions are exclusive, but some may compound. + * Consider various state transitions carefully, such as play 3D under HDMI14 + * 4K, exit 3D under 4K, play DV under 4K, enable ALLM under 3D dual-view + */ +enum vsif_type { + /* Below 4 functions are exclusive */ + VT_HDMI14_4K = 1, + VT_T3D_VIDEO, + VT_DOLBYVISION, + VT_HDR10PLUS, + /* Maybe compound 3D dualview + ALLM */ + VT_T3D_OSD_DISPARITY = 0x10, + VT_T3D_DUALVIEW, + VT_T3D_INDEPENDVEW, + VT_ALLM, + /* default: if non-HDMI4K, no any vsif; if HDMI4k, = VT_HDMI14_4K */ + VT_DEFAULT, + VT_MAX, +}; +int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, int on, + void *param); + +/* if vic is 93 ~ 95, or 98 (HDMI14 4K), return 1 */ +bool is_hdmi14_4k(enum hdmi_vic vic); + +/* set vic to AVI.VIC */ +void hdmitx_set_avi_vic(enum hdmi_vic vic); + /* * HDMI Repeater TX I/F * RX downstream Information from rptx to rprx From 625f488cb0af86518627dc417b895097d044b449 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 22 Feb 2019 09:53:13 +0800 Subject: [PATCH 0498/1060] hdmitx: rename HDMI_IEEE_OUI to avoid conflicts [1/1] PD#SWPL-4705 Problem: In 61207 patch, the define HDMI_IEEE_OUI is conflicted with the kernel head file include/linux/hdmi.h Solution: rename HDMI_IEEE_OUI Verify: GXL/P212 Change-Id: I75a12734e85478f22edf0b48636ed86e60302b58 Signed-off-by: Zongdong Jiao Conflicts: drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c --- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 44 +++++++++---------- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 22 +++++----- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c | 20 ++++----- .../amlogic/media/vout/hdmi_tx/hdmi_common.h | 4 +- .../media/vout/hdmi_tx/hdmi_tx_module.h | 4 +- 5 files changed, 47 insertions(+), 47 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index d47c6c604fb5..aa8ccb73c8b5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -319,9 +319,9 @@ int Edid_Parse_check_HDMI_VSDB(struct hdmitx_dev *hdev, if (temp_addr >= VSpecificBoundary) ret = -1; else { - if ((buff[BlockAddr + 1] != GET_OUI_BYTE0(HDMI_IEEE_OUI)) || - (buff[BlockAddr + 2] != GET_OUI_BYTE1(HDMI_IEEE_OUI)) || - (buff[BlockAddr + 3] != GET_OUI_BYTE2(HDMI_IEEE_OUI))) + if ((buff[BlockAddr + 1] != GET_OUI_BYTE0(HDMI_IEEEOUI)) || + (buff[BlockAddr + 2] != GET_OUI_BYTE1(HDMI_IEEEOUI)) || + (buff[BlockAddr + 3] != GET_OUI_BYTE2(HDMI_IEEEOUI))) ret = -1; } return ret; @@ -1501,7 +1501,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, if ((BlockBuf[offset] == 0x03) && (BlockBuf[offset+1] == 0x0c) && (BlockBuf[offset+2] == 0x00)) { - pRXCap->IEEEOUI = HDMI_IEEE_OUI; + pRXCap->ieeeoui = HDMI_IEEEOUI; pRXCap->ColorDeepSupport = (count > 5) ? BlockBuf[offset+5] : 0; set_vsdb_dc_cap(pRXCap); @@ -1548,7 +1548,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, } else if ((BlockBuf[offset] == 0xd8) && (BlockBuf[offset+1] == 0x5d) && (BlockBuf[offset+2] == 0xc4)) { - pRXCap->HF_IEEEOUI = HF_IEEE_OUI; + pRXCap->hf_ieeeoui = HF_IEEEOUI; pRXCap->Max_TMDS_Clock2 = BlockBuf[offset+4]; pRXCap->scdc_present = !!(BlockBuf[offset+5] & (1 << 7)); @@ -2103,18 +2103,18 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) pr_info(EDID "edid blk0 checksum:%d ext_flag:%d\n", CheckSum, EDID_buf[0x7e]); if ((CheckSum & 0xff) == 0) - hdmitx_device->RXCap.IEEEOUI = 0; + hdmitx_device->RXCap.ieeeoui = 0; else - hdmitx_device->RXCap.IEEEOUI = HDMI_IEEE_OUI; + hdmitx_device->RXCap.ieeeoui = HDMI_IEEEOUI; if (zero_numbers > 120) - hdmitx_device->RXCap.IEEEOUI = HDMI_IEEE_OUI; + hdmitx_device->RXCap.ieeeoui = HDMI_IEEEOUI; return 0; /* do nothing. */ } /* Note: some DVI monitor have more than 1 block */ if ((BlockCount == 1) && (EDID_buf[0x81] == 1)) { - hdmitx_device->RXCap.IEEEOUI = 0; + hdmitx_device->RXCap.ieeeoui = 0; hdmitx_device->RXCap.VIC_count = 0x3; hdmitx_device->RXCap.VIC[0] = HDMI_720x480p60_16x9; hdmitx_device->RXCap.VIC[1] = HDMI_1280x720p60_16x9; @@ -2173,14 +2173,14 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) } if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = HDMI_IEEE_OUI; + pRXCap->ieeeoui = HDMI_IEEEOUI; pr_info(EDID "find IEEEOUT\n"); } else { - pRXCap->IEEEOUI = 0x0; + pRXCap->ieeeoui = 0x0; pr_info(EDID "not find IEEEOUT\n"); } - if ((pRXCap->IEEEOUI != HDMI_IEEE_OUI) || (pRXCap->IEEEOUI == 0x0) || + if ((pRXCap->ieeeoui != HDMI_IEEEOUI) || (pRXCap->ieeeoui == 0x0) || (pRXCap->VIC_count == 0)) hdmitx_edid_set_default_vic(hdmitx_device); @@ -2188,15 +2188,15 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) /* valid EDID & no audio tag & no IEEEOUI */ if (edid_check_valid(&EDID_buf[0]) && !hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = 0x0; + pRXCap->ieeeoui = 0x0; pr_info(EDID "sink is DVI device\n"); } else - pRXCap->IEEEOUI = HDMI_IEEE_OUI; + pRXCap->ieeeoui = HDMI_IEEEOUI; if (edid_zero_data(EDID_buf)) - pRXCap->IEEEOUI = HDMI_IEEE_OUI; + pRXCap->ieeeoui = HDMI_IEEEOUI; - if ((!pRXCap->AUD_count) && (!pRXCap->IEEEOUI)) + if ((!pRXCap->AUD_count) && (!pRXCap->ieeeoui)) hdmitx_edid_set_default_aud(hdmitx_device); edid_save_checkvalue(EDID_buf, BlockCount+1); @@ -2206,7 +2206,7 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) hdmitx_device->tmp_buf[i] = 0; if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) { - pRXCap->IEEEOUI = HDMI_IEEE_OUI; + pRXCap->ieeeoui = HDMI_IEEEOUI; pr_info(EDID "Invalid edid, consider RX as HDMI device\n"); } /* update RX HDR information */ @@ -2405,7 +2405,7 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, pRXCap = &(hdev->RXCap); /* DVI case, only 8bit */ - if (pRXCap->IEEEOUI != HDMI_IEEE_OUI) { + if (pRXCap->ieeeoui != HDMI_IEEEOUI) { if (para->cd != COLORDEPTH_24B) return 0; } @@ -2568,7 +2568,7 @@ void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device) /* Note: in most cases, we think that rx is tv and the default * IEEEOUI is HDMI Identifier */ - pRXCap->IEEEOUI = HDMI_IEEE_OUI; + pRXCap->ieeeoui = HDMI_IEEEOUI; hdmitx_device->vic_count = 0; hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; @@ -2748,14 +2748,14 @@ int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, "Speaker Allocation: %x\n", pRXCap->RxSpeakerAllocation); pos += snprintf(buffer+pos, buffer_len-pos, "Vendor: 0x%x ( %s device)\n", - pRXCap->IEEEOUI, (pRXCap->IEEEOUI)?"HDMI":"DVI"); + pRXCap->ieeeoui, (pRXCap->ieeeoui)?"HDMI":"DVI"); pos += snprintf(buffer+pos, buffer_len-pos, "MaxTMDSClock1 %d MHz\n", pRXCap->Max_TMDS_Clock1 * 5); - if (pRXCap->HF_IEEEOUI) { + if (pRXCap->hf_ieeeoui) { pos += snprintf(buffer+pos, buffer_len-pos, "Vendor2: 0x%x\n", - pRXCap->HF_IEEEOUI); + pRXCap->hf_ieeeoui); pos += snprintf(buffer+pos, buffer_len-pos, "MaxTMDSClock2 %d MHz\n", pRXCap->Max_TMDS_Clock2 * 5); } diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 1724d90af602..3c6ac3742f09 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -556,15 +556,16 @@ static int set_disp_mode_auto(void) pr_info(SYS "change to DVI mode\n"); } else if (hdev->RXCap.IEEEOUI == 0) { #else - if (hdev->RXCap.IEEEOUI == 0) { + if (hdev->RXCap.ieeeoui == 0) { #endif + if (hdev->RXCap.ieeeoui == 0) { /* DVI case judgement. In uboot, directly output HDMI * mode */ hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, DVI_MODE); pr_info(SYS "change to DVI mode\n"); - } else if ((hdev->RXCap.IEEEOUI == 0xc03) && + } else if ((hdev->RXCap.ieeeoui == 0xc03) && (hdev->HWOp.CntlConfig(hdev, CONF_GET_HDMI_DVI_MODE, 0) == DVI_MODE)) { hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, @@ -3904,7 +3905,6 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) rx_repeat_hpd_state(1); hdmitx_get_edid(hdev); hdmi_physcial_size_update(hdev); - #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) if (odroid_voutmode() == VOUTMODE_HDMI) { pr_info(VID "Sink is HDMI device\n"); @@ -3916,14 +3916,14 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) CONF_HDMI_DVI_MODE, DVI_MODE); } else #endif - { - if (hdev->RXCap.ieeeoui != HDMI_IEEEOUI) - hdev->HWOp.CntlConfig(hdev, - CONF_HDMI_DVI_MODE, DVI_MODE); - else - hdev->HWOp.CntlConfig(hdev, - CONF_HDMI_DVI_MODE, HDMI_MODE); - } +{ + if (hdev->RXCap.ieeeoui != HDMI_IEEEOUI) + hdev->HWOp.CntlConfig(hdev, + CONF_HDMI_DVI_MODE, DVI_MODE); + else + hdev->HWOp.CntlConfig(hdev, + CONF_HDMI_DVI_MODE, HDMI_MODE); +} mutex_lock(&getedid_mutex); mutex_unlock(&getedid_mutex); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c index 3950be833887..1fcd328b9191 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c @@ -772,12 +772,12 @@ static void hdmi_tx_construct_avi_packet( *************************************/ /* - * HDMI Identifier = HDMI_IEEE_OUI 0x000c03 + * HDMI Identifier = HDMI_IEEEOUI 0x000c03 * If not, treated as a DVI Device */ static int is_dvi_device(struct rx_cap *pRXCap) { - if (pRXCap->IEEEOUI != HDMI_IEEE_OUI) + if (pRXCap->ieeeoui != HDMI_IEEEOUI) return 1; else return 0; @@ -931,9 +931,9 @@ static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEE_OUI); - VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEE_OUI); - VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEE_OUI); + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEEOUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEEOUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEEOUI); VEN_DB[3] = 0x00; /* 4k x 2k Spec P156 */ if (VideoCode == HDMI_4k2k_30) { @@ -967,9 +967,9 @@ int hdmi_set_3d(struct hdmitx_dev *hdev, int type, unsigned int param) else { for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEE_OUI); - VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEE_OUI); - VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEE_OUI); + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEEOUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEEOUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEEOUI); VEN_DB[3] = 0x40; VEN_DB[4] = type<<4; VEN_DB[5] = param<<4; @@ -1046,7 +1046,7 @@ int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, case VT_DEFAULT: break; case VT_HDMI14_4K: - ieeeoui = HDMI_IEEE_OUI; + ieeeoui = HDMI_IEEEOUI; len = 5; if (is_hdmi14_4k(hdev->cur_VIC)) { fill_hdmi4k_vsif_data(hdev->cur_VIC, DB, HB); @@ -1054,7 +1054,7 @@ int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, } break; case VT_ALLM: - ieeeoui = HF_IEEE_OUI; + ieeeoui = HF_IEEEOUI; len = 5; DB[3] = 0x1; /* Fixed value */ if (on) { diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h index 64c8e3a0c8fc..08a5a4789e42 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h @@ -31,8 +31,8 @@ #define HDMITX_VIC_MASK 0xff /* Refer to http://standards-oui.ieee.org/oui/oui.txt */ -#define HDMI_IEEE_OUI 0x000C03 -#define HF_IEEE_OUI 0xC45DD8 +#define HDMI_IEEEOUI 0x000C03 +#define HF_IEEEOUI 0xC45DD8 #define GET_OUI_BYTE0(oui) (oui & 0xff) /* Little Endian */ #define GET_OUI_BYTE1(oui) ((oui >> 8) & 0xff) #define GET_OUI_BYTE2(oui) ((oui >> 16) & 0xff) diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 0f3e8521f56c..5fbbccc6ef96 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -94,9 +94,9 @@ struct rx_cap { unsigned char AUD_count; unsigned char RxSpeakerAllocation; /*vendor*/ - unsigned int IEEEOUI; + unsigned int ieeeoui; unsigned char Max_TMDS_Clock1; /* HDMI1.4b TMDS_CLK */ - unsigned int HF_IEEEOUI; /* For HDMI Forum */ + unsigned int hf_ieeeoui; /* For HDMI Forum */ unsigned int Max_TMDS_Clock2; /* HDMI2.0 TMDS_CLK */ /* CEA861-F, Table 56, Colorimetry Data Block */ unsigned int colorimetry_data; From 729b388b1a1f09cddba491592114062a14ea6dbf Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 8 Mar 2019 18:57:49 +0800 Subject: [PATCH 0499/1060] hdmitx: add dongle_mode case for low power [2/2] PD#SWPL-5302 Problem: For dongle products, it is connected to TV directly, and some parameters are different from mbox. Solution: Add dongle mode for driver's usage Verify: U211/S905Y2 Change-Id: Ibe45b167800d3b830d78ca8e9d7b67efd64d8564 Signed-off-by: Zongdong Jiao Conflicts: drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c --- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 1 + arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 1 + .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 9 +++++ .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 4 ++ .../media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c | 37 +++++++++++++++++++ .../media/vout/hdmi_tx/hdmi_tx_module.h | 1 + 6 files changed, 53 insertions(+) diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index e62cb5cb1c87..ec831fd30d79 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1075,6 +1075,7 @@ * 10:G12A */ ic_type = <10>; + dongle_mode = <0>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 46c3f1879bdd..11b4a7efe3c7 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -1085,6 +1085,7 @@ * 10:G12A */ ic_type = <10>; + dongle_mode = <0>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 3c6ac3742f09..49307d9c4220 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -4435,6 +4435,7 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) #ifdef CONFIG_OF if (pdev->dev.of_node) { + int dongle_mode = 0; memset(&hdmitx_device.config_data, 0, sizeof(struct hdmi_config_platform_data)); /* Get ic type information */ @@ -4446,6 +4447,14 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) pr_info(SYS "hdmitx_device.chip_type : %d\n", hdmitx_device.chip_type); + /* Get dongle_mode information */ + ret = of_property_read_u32(pdev->dev.of_node, "dongle_mode", + &dongle_mode); + hdmitx_device.dongle_mode = !!dongle_mode; + if (!ret) + pr_info(SYS "hdmitx_device.dongle_mode: %d\n", + hdmitx_device.dongle_mode); + ret = of_property_read_u32(pdev->dev.of_node, "repeater_tx", &val); if (!ret) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 7ceb66a67cc3..8553f3be39eb 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -2030,11 +2030,15 @@ static void set_phy_by_mode(unsigned int mode) switch (mode) { case 1: /* 5.94/4.5/3.7Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65c4); + if (hdev->dongle_mode) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb5584); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); break; case 2: /* 2.97Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6262); + if (hdev->dongle_mode) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4262); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x00000003); break; diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c index 5179fcebf996..3f0e4df5d9e5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c @@ -164,12 +164,45 @@ static bool set_hpll_hclk_v3(unsigned int m, unsigned int frac_val) return ret; /* return hpll locked status */ } +#define IS_DONGLE_MODE(hdev) \ + ((hdev->dongle_mode) \ + && (hdev->para->cs == COLORSPACE_YUV422 \ + || hdev->para->cd == COLORDEPTH_24B) \ + && (hdev->cur_VIC == HDMI_1280x720p50_16x9 \ + || hdev->cur_VIC == HDMI_1280x720p60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080i60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080i50_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080p60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080p50_16x9)) + +static void set_hpll_hclk_dongle_5940m(void) +{ + hd_write_reg(P_HHI_HDMI_PLL_CNTL0, 0x0b3a04f7); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x3, 28, 2); + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x10000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x00100140); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x2a295c00); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x65771290); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x39272000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x50540000); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x0, 29, 1); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL0); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); +} + void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk) { unsigned int m, m1, m2; + struct hdmitx_dev *hdev = get_hdmitx_device(); switch (clk) { case 5940000: + if (IS_DONGLE_MODE(hdev)) { + set_hpll_hclk_dongle_5940m(); + break; + } if (set_hpll_hclk_v1(0xf7, frac_rate ? 0x8148 : 0x10000)) break; else if (set_hpll_hclk_v2(0x7b, 0x18000)) @@ -616,6 +649,8 @@ int hdmitx_hpd_hw_op_g12a(enum hpd_op cmd) void set_hpll_sspll_g12a(enum hdmi_vic vic) { + struct hdmitx_dev *hdev = get_hdmitx_device(); + switch (vic) { case HDMI_1920x1080p60_16x9: case HDMI_1920x1080p50_16x9: @@ -632,6 +667,8 @@ void set_hpll_sspll_g12a(enum hdmi_vic vic) hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 8, 1); /* 2: 1000ppm 1: 500ppm */ hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 4, 4); + if (hdev->dongle_mode) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 4, 4, 4); /* bit[15] hdmi_dpll_sdmnc_en */ hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL3, 0, 15, 1); hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0, 29, 1); diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 5fbbccc6ef96..c6c5593427de 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -446,6 +446,7 @@ struct hdmitx_dev { unsigned int flag_3dfp:1; unsigned int flag_3dtb:1; unsigned int flag_3dss:1; + unsigned int dongle_mode:1; unsigned int drm_feature;/*Direct Rander Management*/ }; From e408a28f8bfdb18ffa7597ebfd9b98bd349633c8 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 8 Mar 2019 15:23:30 +0800 Subject: [PATCH 0500/1060] hdmitx: adjust PHY parameter with 5.1 ohm resistor [2/2] PD#SWPL-2927 Problem: No enough eye diagram when adding TMDS 5.1 ohm resistor Solution: adjust PHY parameter with 5.1 ohm resistor Verify: G12/U212 Change-Id: Ib5518613c556f9b04eb0aa374193c7a6046a7ba9 Signed-off-by: Zongdong Jiao --- drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 8553f3be39eb..f9d03d04452a 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -2036,7 +2036,7 @@ static void set_phy_by_mode(unsigned int mode) hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); break; case 2: /* 2.97Gbps */ - hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6262); + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6272); if (hdev->dongle_mode) hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4262); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); From 73f949cfea204b72cef7938fd301b7302f1c46a2 Mon Sep 17 00:00:00 2001 From: "shuanglong.wang" Date: Fri, 12 Apr 2019 13:55:06 +0800 Subject: [PATCH 0501/1060] video: compensation omxpts for pcr check [1/1] PD#SWPL-5664 Problem: pcr is probably adjust when test AL1 eyepatch test case Solution: the time is not accurate when check pcr and omx_pts differ, because omx_pts is used the value that be set, but pcr is current. Here add compensation for omx_pts Verify: verify by nts Change-Id: I3e0f6f006fd79cf7cac4148fd18da72111a333c7 Signed-off-by: shuanglong.wang Conflicts: drivers/amlogic/media/video_sink/video.c --- drivers/amlogic/media/video_sink/video.c | 26 ++++++++++++++++++------ drivers/amlogic/media/video_sink/vpp.c | 19 +---------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 1d2300c77497..78a398be67ba 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -456,8 +456,6 @@ static u32 reference_zorder = 128; static s32 black_threshold_width = 20; static s32 black_threshold_height = 30; -static u32 reference_zorder = 128; - #define MAX_ZOOM_RATIO 300 #define VPP_PREBLEND_VD_V_END_LIMIT 2304 @@ -6549,9 +6547,19 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } if (omx_secret_mode == true) { u32 system_time = timestamp_pcrscr_get(); - int diff = system_time - omx_pts; - video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT; - atomic_set(&trickmode_framedone, 1); + int diff = 0; + unsigned long delta1 = 0; + + diff = system_time - omx_pts; + if (time_setomxpts.tv_sec > 0) { + struct timeval now; + + do_gettimeofday(&now); + delta1 = (now.tv_sec - time_setomxpts.tv_sec) + * 1000000LL + + (now.tv_usec - time_setomxpts.tv_usec); + diff -= delta1 * 90 / 1000; + } if ((diff - omx_pts_interval_upper) > 0 || (diff - omx_pts_interval_lower) < 0 @@ -8350,6 +8358,9 @@ static void video_vf_unreg_provider(void) show_first_picture = false; show_first_frame_nosync = false; + time_setomxpts.tv_sec = 0; + time_setomxpts.tv_usec = 0; + #ifdef PTS_LOGGING { int pattern; @@ -8887,8 +8898,11 @@ static void set_omx_pts(u32 *p) pr_info("[set_omx_pts]tmp_pts:%d, set_from_hwc:%d,frame_num=%d, not_reset=%d\n", tmp_pts, set_from_hwc, frame_num, not_reset); - if (not_reset == 0) + if (not_reset == 0) { omx_pts = tmp_pts; + ATRACE_COUNTER("omxpts", omx_pts); + do_gettimeofday(&time_setomxpts); + } /* kodi may render first frame, then drop dozens of frames */ if (set_from_hwc == 0 && omx_run == true && frame_num <= 2 && not_reset == 0) { diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 93787f418a7c..1c89853f8c85 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -2976,10 +2976,7 @@ int vpp_set_filters( if (!input) return ret; - if (vpp_flags & VPP_FLAG_INTERLACE_IN) - vskip_step = 2; - else - vskip_step = 1; + WARN_ON(vinfo == NULL); /* use local var to avoid the input data be overwriten */ memcpy(&local_input, input, sizeof(struct disp_info_s)); @@ -3066,20 +3063,6 @@ int vpp_set_filters( if (vf->type & VIDTYPE_VSCALE_DISABLE) vpp_flags |= VPP_FLAG_VSCALE_DISABLE; -#ifndef TV_3D_FUNCTION_OPEN - if (vf->type & VIDTYPE_COMPRESS) { - src_width = vf->compWidth; - src_height = vf->compHeight; - } else { - src_width = vf->width; - src_height = vf->height; - } -#endif - - if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) - && !disable_adapted) { - if (vf->pic_mode.screen_mode != 0xff) - wide_mode = vf->pic_mode.screen_mode; if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) && !disable_adapted) { From cf2fbdeaa0c6c290fe312afb2f284b3d16feab83 Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Mon, 21 Jan 2019 17:25:19 +0800 Subject: [PATCH 0502/1060] audio: Add HBR audio info for HDMI input [2/3] PD#SWPL-3435 Problem: P321 doesn't support DTS HD decoding Solution: In HDMI RX module, we add a new field to indicate whether the input audio is HBR. With this info, hal can enable the PAO mode to decode the HBR audio. Verify: P321 Change-Id: I6fd180e6636905f5119fe1d313214d4b56d07d5e Signed-off-by: yujie.wu Conflicts: drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c --- .../media/vin/tvin/hdmirx/hdmi_rx_drv.h | 2 +- .../media/vin/tvin/hdmirx/hdmi_rx_hw.c | 33 +++++------ .../amlogic/media/frame_provider/tvin/tvin.h | 2 +- include/linux/amlogic/media/sound/misc.h | 4 ++ sound/soc/amlogic/auge/extn.c | 5 ++ sound/soc/amlogic/common/misc.c | 58 ++++++++++++++++++- sound/soc/amlogic/meson/tv.c | 15 ++++- 7 files changed, 96 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h index d35ea36e5a5d..1cf532ff9d86 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h @@ -34,7 +34,7 @@ #include "hdmi_rx_edid.h" -#define RX_VER0 "ver.2018-11-8" +#define RX_VER0 "ver.2019-01-22" /* * * diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c index b4e738def841..dc6d0255aed0 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c @@ -913,23 +913,22 @@ if (audio_info->cts != 0) { */ void rx_get_audio_status(struct rx_audio_stat_s *aud_sts) { -if ((rx.state == FSM_SIG_READY) && - (rx.pre.sw_vic != HDMI_UNKNOWN) && - (rx.pre.sw_vic != HDMI_UNSUPPORT) && - (rx.avmute_skip == 0)) { - aud_sts->aud_rcv_flag = - (rx.aud_info.aud_packet_received == 0) ? false : true; - aud_sts->aud_stb_flag = true; - aud_sts->aud_sr = rx.aud_info.real_sr; - aud_sts->aud_channel_cnt = rx.aud_info.channel_count; - aud_sts->aud_type = rx.aud_info.coding_type; - aud_sts->afifo_thres_pass = - ((hdmirx_rd_dwc(DWC_AUD_FIFO_STS) & - THS_PASS_STS) == 0) ? false : true; -} else { - memset(aud_sts, 0, - sizeof(struct rx_audio_stat_s)); -} + if ((rx.state == FSM_SIG_READY) && + (rx.pre.sw_vic != HDMI_UNKNOWN) && + (rx.pre.sw_vic != HDMI_UNSUPPORT) && + (rx.avmute_skip == 0)) { + aud_sts->aud_rcv_packet = rx.aud_info.aud_packet_received; + aud_sts->aud_stb_flag = true; + aud_sts->aud_sr = rx.aud_info.real_sr; + aud_sts->aud_channel_cnt = rx.aud_info.channel_count; + aud_sts->aud_type = rx.aud_info.coding_type; + aud_sts->afifo_thres_pass = + ((hdmirx_rd_dwc(DWC_AUD_FIFO_STS) & + THS_PASS_STS) == 0) ? false : true; + } else { + memset(aud_sts, 0, + sizeof(struct rx_audio_stat_s)); + } } EXPORT_SYMBOL(rx_get_audio_status); diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index 5a1a561a2286..3504f2912285 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -465,7 +465,7 @@ struct dfe_adcpll_para { struct rx_audio_stat_s { /*audio packets received*/ - bool aud_rcv_flag; + int aud_rcv_packet; /*audio stable status*/ bool aud_stb_flag; /*audio sample rate*/ diff --git a/include/linux/amlogic/media/sound/misc.h b/include/linux/amlogic/media/sound/misc.h index 25341c2e18be..c9e9fbda9613 100644 --- a/include/linux/amlogic/media/sound/misc.h +++ b/include/linux/amlogic/media/sound/misc.h @@ -71,6 +71,10 @@ extern int aml_get_atmos_audio_edid( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +extern int aml_get_hdmiin_audio_packet( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + #endif #endif diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index 07d31ee2e8ee..712c6aa76acf 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -800,6 +800,11 @@ static const struct snd_kcontrol_new extn_controls[] = { aml_get_hdmiin_audio_format, NULL), + SOC_ENUM_EXT("HDMIIN Audio Packet", + hdmi_in_status_enum[4], + aml_get_hdmiin_audio_packet, + NULL), + SOC_SINGLE_BOOL_EXT("HDMI ATMOS EDID Switch", 0, aml_get_atmos_audio_edid, diff --git a/sound/soc/amlogic/common/misc.c b/sound/soc/amlogic/common/misc.c index fc15a68f4de1..1b4670564d6e 100644 --- a/sound/soc/amlogic/common/misc.c +++ b/sound/soc/amlogic/common/misc.c @@ -176,6 +176,16 @@ static const char * const hdmi_in_format[] = { "WMA_PRO" }; +static const char * const hdmi_in_audio_packet[] = { + "None", + "AUDS", + "OBA", + "DST", + "HBR", + "OBM", + "MAS" +}; + const struct soc_enum hdmi_in_status_enum[] = { SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_is_stable), audio_is_stable), @@ -184,7 +194,9 @@ const struct soc_enum hdmi_in_status_enum[] = { SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_channels), hdmi_in_channels), SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_format), - hdmi_in_format) + hdmi_in_format), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_audio_packet), + hdmi_in_audio_packet) }; int aml_get_hdmiin_audio_stable( @@ -194,7 +206,8 @@ int aml_get_hdmiin_audio_stable( struct rx_audio_stat_s aud_sts; rx_get_audio_status(&aud_sts); - ucontrol->value.integer.value[0] = aud_sts.aud_rcv_flag; + ucontrol->value.integer.value[0] = + (aud_sts.aud_rcv_packet == 0) ? 0 : 1; return 0; } @@ -236,6 +249,7 @@ int aml_get_hdmiin_audio_format( return 0; } + /* call HDMI CEC API to enable arc audio */ int aml_set_atmos_audio_edid( struct snd_kcontrol *kcontrol, @@ -259,4 +273,44 @@ int aml_get_atmos_audio_edid( return 0; } +int aml_get_hdmiin_audio_packet( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rx_audio_stat_s aud_sts; + int val; + + rx_get_audio_status(&aud_sts); + + switch (aud_sts.aud_rcv_packet) { + case 0: + val = 0; + break; + case 1: + val = 1; + break; + case 2: + val = 2; + break; + case 4: + val = 3; + break; + case 8: + val = 4; + break; + case 16: + val = 5; + break; + case 32: + val = 6; + break; + default: + val = 0; + break; + } + ucontrol->value.integer.value[0] = val; + + return 0; +} + #endif diff --git a/sound/soc/amlogic/meson/tv.c b/sound/soc/amlogic/meson/tv.c index a5b00f110581..7f6c4df9f7f1 100644 --- a/sound/soc/amlogic/meson/tv.c +++ b/sound/soc/amlogic/meson/tv.c @@ -285,9 +285,17 @@ static int aml_get_spdif_audio_type( int audio_type = 0; int i; int total_num = sizeof(type_texts)/sizeof(struct spdif_audio_info); - int pc = aml_audin_read(AUDIN_SPDIF_NPCM_PCPD)>>16; + int pc_ori = aml_audin_read(AUDIN_SPDIF_NPCM_PCPD)>>16; + int pc = 0; - pc = pc&0xfff; + /* data type is 0~4 bit*/ + pc = pc_ori&0x1f; + /* check whether it has stop bit + * refer to IEC61937-1 table 9 + */ + if (pc == 0) { + pc = pc_ori&0xfff; + } for (i = 0; i < total_num; i++) { if (pc == type_texts[i].pc) { audio_type = type_texts[i].aud_type; @@ -616,6 +624,9 @@ static const struct snd_kcontrol_new aml_tv_controls[] = { SOC_ENUM_EXT("HDMIIN audio format", hdmi_in_status_enum[3], aml_get_hdmiin_audio_format, NULL), + SOC_ENUM_EXT("HDMIIN Audio Packet", hdmi_in_status_enum[4], + aml_get_hdmiin_audio_packet, + NULL), SOC_SINGLE_BOOL_EXT("HDMI ATMOS EDID Switch", 0, aml_get_atmos_audio_edid, aml_set_atmos_audio_edid), From 6c32cf605b98e9bafe32e56c140dc7220073aeaa Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Fri, 1 Mar 2019 16:29:31 +0800 Subject: [PATCH 0503/1060] audio: auge: fix spdifout clk for share buffer [1/1] PD#SWPL-4278 Problem: spdif out clk is related to tdm clk for share buffer. For play raw data 32k/44.1k, it's not correct for spdif out clk. Solution: separate spdif out clk and tdm clk Verify: x301 Change-Id: Ie6e3d7413d9577c9c80ea90e8b1f9ff4bf3eefcf Signed-off-by: Xing Wang Conflicts: sound/soc/amlogic/auge/spdif_hw.c --- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 6 ++- .../arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 6 ++- .../boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 6 ++- .../amlogic/g12a_s905d2_u200_buildroot.dts | 6 ++- .../g12a_s905d2_u200_buildroot_vccktest.dts | 6 ++- .../g12a_s905d2_u200_drm_buildroot.dts | 6 ++- .../arm/boot/dts/amlogic/g12a_s905x2_u211.dts | 6 ++- .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 6 ++- .../dts/amlogic/g12a_s905x2_u211_512m.dts | 6 ++- .../amlogic/g12a_s905x2_u211_buildroot.dts | 6 ++- .../arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 6 ++- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 6 ++- .../amlogic/g12a_s905x2_u212_buildroot.dts | 6 ++- .../arm/boot/dts/amlogic/g12a_s905y2_u220.dts | 6 ++- .../arm/boot/dts/amlogic/g12a_s905y2_u221.dts | 6 ++- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 6 ++- .../arm/boot/dts/amlogic/g12b_a311d_skt_a.dts | 6 ++- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 6 ++- .../boot/dts/amlogic/g12b_a311d_w400_a.dts | 6 ++- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 6 ++- .../amlogic/g12b_a311d_w400_buildroot_a.dts | 6 ++- .../g12b_a311d_w400_buildroot_vccktest.dts | 6 ++- .../g12b_a311d_w400_buildroot_vccktest_a.dts | 6 ++- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 6 ++- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 8 ++-- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 9 +++-- .../boot/dts/amlogic/g12a_s905d2_skt.dts | 6 ++- .../boot/dts/amlogic/g12a_s905d2_u200.dts | 6 ++- .../boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 6 ++- .../amlogic/g12a_s905d2_u200_buildroot.dts | 6 ++- .../g12a_s905d2_u200_buildroot_vccktest.dts | 6 ++- .../g12a_s905d2_u200_drm_buildroot.dts | 6 ++- .../boot/dts/amlogic/g12a_s905x2_u211.dts | 6 ++- .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 6 ++- .../dts/amlogic/g12a_s905x2_u211_512m.dts | 6 ++- .../amlogic/g12a_s905x2_u211_buildroot.dts | 6 ++- .../boot/dts/amlogic/g12a_s905x2_u212.dts | 6 ++- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 6 ++- .../amlogic/g12a_s905x2_u212_buildroot.dts | 6 ++- .../boot/dts/amlogic/g12a_s905y2_u220.dts | 6 ++- .../boot/dts/amlogic/g12a_s905y2_u221.dts | 6 ++- .../arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 6 ++- .../boot/dts/amlogic/g12b_a311d_skt_a.dts | 6 ++- .../boot/dts/amlogic/g12b_a311d_w400.dts | 6 ++- .../boot/dts/amlogic/g12b_a311d_w400_a.dts | 6 ++- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 6 ++- .../amlogic/g12b_a311d_w400_buildroot_a.dts | 6 ++- .../g12b_a311d_w400_buildroot_vccktest.dts | 6 ++- .../g12b_a311d_w400_buildroot_vccktest_a.dts | 6 ++- .../dts/amlogic/g12b_a311x_w411_buildroot.dts | 6 ++- .../amlogic/g12b_a311x_w411_buildroot_a.dts | 6 ++- sound/soc/amlogic/auge/ddr_mngr.c | 4 +- sound/soc/amlogic/auge/spdif_hw.c | 19 +++------- sound/soc/amlogic/auge/tdm.c | 37 +++++++++++++++---- 54 files changed, 244 insertions(+), 127 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index 773329f29392..03985ccee214 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -808,8 +808,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index b92cd056ee71..d1da710d8c33 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -925,8 +925,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 36d0fd115c79..fe31144f92ab 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -929,8 +929,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 80e76f34a047..0a850a2a0ce2 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -896,8 +896,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index 6b6890bc646b..3f1022173ab2 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -900,8 +900,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index b10b011b5856..3d88e88807bf 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -910,8 +910,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index 28415560c690..a807d35f8fc3 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -855,8 +855,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 81c3067a015f..680cf3aaec01 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -846,8 +846,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 819d43cf9320..872bbd3e2bab 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -842,8 +842,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 1980e58a71ad..3834590cbf6e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -898,8 +898,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index a3be7d987147..8e2b01a2518e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -899,8 +899,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 4c999c359391..c712375ba08c 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -895,8 +895,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 102bfbb9ae29..0c5958bc0ca0 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -897,8 +897,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index c8e9ea7cfb2e..5a31a2f8b6bc 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -838,8 +838,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index ddfb8ffb36bd..c6e89ae0e2de 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -801,8 +801,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 38ba1926fcb0..7a74dcada5ab 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -914,8 +914,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts index c1e044928497..6706641a7e86 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -894,8 +894,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index aaa181bc9f71..0017840ad7f7 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -881,8 +881,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index fa74a62a7380..275163b7a838 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -861,8 +861,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 95913de50b65..edcc88096646 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -986,8 +986,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index c84d2203719b..25f73afe483b 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -953,8 +953,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 8b638606b014..e83c8b1850af 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -878,8 +878,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index c999018d5e4d..fd62cd9b8d82 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -865,8 +865,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index fcf991a1616a..0b294bc4203b 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -942,8 +942,10 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 7bb218fa333c..8a725e023e40 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1247,8 +1247,10 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; @@ -1305,7 +1307,7 @@ compatible = "amlogic, tl1-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index fb49ebdc1115..1e46e5368949 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -305,6 +305,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -962,8 +963,10 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; @@ -1020,7 +1023,7 @@ compatible = "amlogic, tl1-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index 7a00994bd83e..370a0388e534 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -808,8 +808,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index 38ab2a431550..26d98f4d3175 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -926,8 +926,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 2f77ce693e97..7d3e2ba52707 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -923,8 +923,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 0a6139cf7043..8ec7270616ef 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -896,8 +896,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index b700f088315e..c3896ca3ba42 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -899,8 +899,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index f9bfd6c39e31..b7c4962d72ea 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -910,8 +910,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index 455971e9cc7f..1e6d000a33c4 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -855,8 +855,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 296f931a18c4..7021173c9ec8 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -846,8 +846,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 82c673adf3da..bd1c514de9f0 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -842,8 +842,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index ee50e8619731..d8c12d6d454d 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -898,8 +898,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index 8530a386ab17..fc4eae786f8e 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -899,8 +899,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 652dc1895682..ec3d2110ff70 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -891,8 +891,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 453319dfa442..023cf8a23706 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -897,8 +897,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index af22fb202662..ed09a41658c7 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -838,8 +838,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts index 9a41b8951c6d..6e343249e391 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -799,8 +799,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 2692b8d0ef75..def509d6ecc2 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -914,8 +914,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts index 7e829bcc1b3f..ab332404e20a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -894,8 +894,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 30b529fdc5c0..fe53c59ace64 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -880,8 +880,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index 19b70c2dbbcd..95a13fdcd15c 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -860,8 +860,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 7b2fbd20fbc8..f2dba13b152c 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -985,8 +985,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index c5dbe4acfd6a..8c23660c31de 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -952,8 +952,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index b55f74e6c59a..483cf26d612a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -878,8 +878,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index ce65118752ba..8a6d0f729a12 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -865,8 +865,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index 57f4120a70a7..47e9c788420e 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -958,8 +958,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index 0107d3111ed2..d6851e87a05e 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -927,8 +927,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 9f6e9e324f88..3652ace2690a 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -937,8 +937,8 @@ int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) && (frddrs[i].fifo_id != current_fifo_id) && (frddrs[i].dest == ss_sel)) { - pr_info(" frddr:%d, ss_sel:%d used, invalid for share buffer\n", - i, + pr_info("%s, ss_sel:%d used, not for share buffer at same time\n", + __func__, ss_sel); ret = 0; break; diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index de1f103b0b55..155060bdabc0 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -391,8 +391,8 @@ void spdifout_to_hdmitx_ctrl(int spdif_index) | spdif_index << 0 /* spdif_clk */ ); } - -void spdifout_clk_ctrl(int spdif_id, bool is_enable) +#if 0 +static void spdifout_clk_ctrl(int spdif_id, bool is_enable) { unsigned int offset, reg; @@ -402,7 +402,7 @@ void spdifout_clk_ctrl(int spdif_id, bool is_enable) /* select : mpll 0, 24m, so spdif clk:6m */ audiobus_write(reg, is_enable << 31 | 0x0 << 24 | 0x3 << 0); } - +#endif static void spdifout_fifo_ctrl(int spdif_id, int fifo_id, int bitwidth, int channels) { @@ -484,10 +484,6 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, else spdif_id = 0; - /* clk for spdif_b is always on */ - /*if (!spdif_id)*/ - //spdifout_clk_ctrl(spdif_id, /*is_enable*/true); - if (is_enable) spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); } @@ -623,16 +619,13 @@ void spdifout_play_with_zerodata(unsigned int spdif_id) src0_sel = 3; /* spdif clk */ - spdifout_clk_ctrl(spdif_id, true); - + //spdifout_clk_ctrl(spdif_id, true); + /* spdif to hdmitx */ #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) /* ODROID spdif_b only to hdmitx */ if (spdif_id == 1) - spdifout_to_hdmitx_ctrl(spdif_id); -#else - /* spdif to hdmitx */ - spdifout_to_hdmitx_ctrl(spdif_id); #endif + spdifout_to_hdmitx_ctrl(spdif_id); /* spdif ctrl */ spdifout_fifo_ctrl(spdif_id, diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 8c1ad18eab87..1f610349745e 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -103,7 +103,8 @@ struct aml_tdm { struct clk *clk; struct clk *clk_gate; struct clk *mclk; - struct clk *samesrc_sysclk; + struct clk *samesrc_srcpll; + struct clk *samesrc_clk; bool contns_clk; unsigned int id; /* bclk src selection */ @@ -761,9 +762,16 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, sharebuffer_get_mclk_fs_ratio(p_tdm->samesource_sel, &mux, &ratio); pr_info("samesource sysclk:%d\n", rate * ratio * mux); - if (p_tdm->samesrc_sysclk) - clk_set_rate(p_tdm->samesrc_sysclk, + if (!IS_ERR(p_tdm->samesrc_srcpll)) { + clk_set_rate(p_tdm->samesrc_srcpll, rate * ratio * mux); + clk_prepare_enable(p_tdm->samesrc_srcpll); + } + if (!IS_ERR(p_tdm->samesrc_clk)) { + clk_set_rate(p_tdm->samesrc_clk, + rate * ratio); + clk_prepare_enable(p_tdm->samesrc_clk); + } } if (!p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { @@ -1338,12 +1346,25 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) if (ret < 0) p_tdm->samesource_sel = -1; else { - p_tdm->samesrc_sysclk = devm_clk_get(&pdev->dev, - "samesource_sysclk"); - if (IS_ERR(p_tdm->samesrc_sysclk)) { + p_tdm->samesrc_srcpll = devm_clk_get(&pdev->dev, + "samesource_srcpll"); + if (IS_ERR(p_tdm->samesrc_srcpll)) { dev_err(&pdev->dev, - "Can't retrieve samesrc_sysclk clock\n"); - return PTR_ERR(p_tdm->samesrc_sysclk); + "Can't retrieve samesrc_srcpll clock\n"); + return PTR_ERR(p_tdm->samesrc_srcpll); + } + p_tdm->samesrc_clk = devm_clk_get(&pdev->dev, + "samesource_clk"); + if (IS_ERR(p_tdm->samesrc_clk)) { + dev_err(&pdev->dev, + "Can't retrieve samesrc_clk clock\n"); + return PTR_ERR(p_tdm->samesrc_clk); + } + ret = clk_set_parent(p_tdm->samesrc_clk, + p_tdm->samesrc_srcpll); + if (ret) { + dev_err(dev, "can't set samesource clock\n"); + return ret; } pr_info("TDM id %d samesource_sel:%d\n", p_tdm->id, From 743550e67eb8b2347499af9e1d51aae07daa3585 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 1 Mar 2019 21:48:35 +0800 Subject: [PATCH 0504/1060] audio: audio glitch at tdm startup [1/1] PD#SWPL-5219 Problem: audio glitch at tdm startup Solution: Pad 0 data to clear the remaining data in the module. Verify: Local tested. Change-Id: Iab526c6893a32030799567b57e05e7bb11b8fea0 Signed-off-by: Shuai Li Conflicts: sound/soc/amlogic/auge/tdm.c --- sound/soc/amlogic/auge/spdif.c | 3 +++ sound/soc/amlogic/auge/spdif_hw.c | 26 +++++++++++++++++++++----- sound/soc/amlogic/auge/spdif_hw.h | 4 ++++ sound/soc/amlogic/auge/tdm.c | 25 ++++++++++++++++++------- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 89c58eb862c8..e021552211ba 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -1187,6 +1187,9 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "S/PDIF Playback enable\n"); aml_frddr_enable(p_spdif->fddr, 1); + udelay(100); + aml_spdif_mute(p_spdif->actrl, + substream->stream, p_spdif->id, false); } else { dev_info(substream->pcm->card->dev, "S/PDIF Capture enable\n"); aml_toddr_enable(p_spdif->tddr, 1); diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 155060bdabc0..04172b61eb3d 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -117,6 +117,22 @@ void aml_spdif_mute( } } +void aml_spdifout_mute_without_actrl( + int index, + bool is_mute) +{ + unsigned int offset, reg; + int mute_lr = 0; + + if (is_mute) + mute_lr = 0x3; + + offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; + reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index; + + audiobus_update_bits(reg, 0x3 << 21, mute_lr << 21); +} + void aml_spdif_arb_config(struct aml_audio_controller *actrl) { /* config ddr arb */ @@ -248,8 +264,8 @@ void aml_spdif_fifo_ctrl( reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index; aml_audiobus_update_bits(actrl, reg, - 0x1<<29|0x1<<28|0x3<<21|0x1<<20|0x1<<19|0xff<<4, - 1<<29|1<<28|0x0<<21|0<<20|0<<19|0x3<<4); + 0x1<<29|0x1<<28|0x1<<20|0x1<<19|0xff<<4, + 1<<29|1<<28|0<<20|0<<19|0x3<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * index; @@ -422,8 +438,8 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; audiobus_update_bits(reg, - 0x3<<21|0x1<<20|0x1<<19|0xff<<4, - 0x0<<21|0<<20|0<<19|chmask<<4); + 0x1<<20|0x1<<19|0xff<<4, + 0<<20|0<<19|chmask<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdif_id; @@ -467,7 +483,7 @@ void spdifout_enable(int spdif_id, bool is_enable) if (!is_enable) { /* share buffer, spdif should be active, so mute it */ - audiobus_update_bits(reg, 0x3 << 21, 0x3 << 21); + /*audiobus_update_bits(reg, 0x3 << 21, 0x3 << 21);*/ return; } diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index 3e133f620fba..d2f6b96dfffc 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -40,6 +40,10 @@ extern void aml_spdif_mute( int index, bool is_mute); +extern void aml_spdifout_mute_without_actrl( + int index, + bool is_mute); + extern void aml_spdif_arb_config(struct aml_audio_controller *actrl); extern int aml_spdifin_status_check( diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 1f610349745e..ab71d3e9d65f 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -40,7 +40,8 @@ #include "tdm_hw.h" #include "sharebuffer.h" #include "vad.h" -#include "spdif.h" +#include "spdif_hw.h" + /*#define __PTM_TDM_CLK__*/ @@ -547,13 +548,23 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, sharebuffer_trigger(cmd, p_tdm->samesource_sel); } aml_frddr_enable(p_tdm->fddr, 1); + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, true); + udelay(100); + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, false); + if (p_tdm->chipinfo + && p_tdm->chipinfo->same_src_fn + && (p_tdm->samesource_sel >= 0) + && (aml_check_sharebuffer_valid(p_tdm->fddr, + p_tdm->samesource_sel))) { + aml_spdifout_mute_without_actrl(0, false); + } } else { dev_info(substream->pcm->card->dev, "tdm capture enable\n"); aml_toddr_enable(p_tdm->tddr, 1); + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, true); } - aml_tdm_enable(p_tdm->actrl, - substream->stream, p_tdm->id, true); - break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -575,13 +586,13 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, 0, substream->runtime->dma_bytes); mdelay(3); aml_frddr_enable(p_tdm->fddr, 0); - /* share buffer trigger */ + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, true); if (p_tdm->chipinfo && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, p_tdm->samesource_sel))) { - sharebuffer_trigger(cmd, p_tdm->samesource_sel); + aml_spdifout_mute_without_actrl(0, true); } } else { dev_info(substream->pcm->card->dev, "tdm capture stop\n"); @@ -1096,7 +1107,7 @@ static int aml_dai_tdm_mute_stream(struct snd_soc_dai *cpu_dai, if (stream == SNDRV_PCM_STREAM_PLAYBACK) { pr_debug("tdm playback mute: %d\n", mute); - aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, mute); + //aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, mute); } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { pr_debug("tdm capture mute: %d\n", mute); aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, mute); From 2f3e0e650aa761b20811096b3353a8f974bacd74 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Tue, 5 Mar 2019 10:45:46 +0800 Subject: [PATCH 0505/1060] audio: auge: fix spdif reset when used for share buffer [1/1] PD#SWPL-3655 Problem: spdif output 8 channel, channel map in wrong order. Solution: reset spdif before enable as soon as quickly. modification is limited for tl1 now Verify: x301 Change-Id: I224032390404be85c77d7436a9be9148df09c997 Signed-off-by: Xing Wang Conflicts: sound/soc/amlogic/auge/tdm.c --- sound/soc/amlogic/auge/sharebuffer.c | 10 +++++----- sound/soc/amlogic/auge/sharebuffer.h | 2 +- sound/soc/amlogic/auge/spdif.c | 9 ++++++++- sound/soc/amlogic/auge/spdif_hw.c | 22 ++++++++++++---------- sound/soc/amlogic/auge/spdif_hw.h | 4 ++-- sound/soc/amlogic/auge/tdm.c | 18 ++++++++++++++++++ 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index f94fd2a03b0c..855d7a6c31b0 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -68,7 +68,7 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, return 0; } -void sharebuffer_enable(int sel, bool enable) +void sharebuffer_enable(int sel, bool enable, bool reenable) { if (sel < 0) { pr_err("Not support same source\n"); @@ -77,7 +77,7 @@ void sharebuffer_enable(int sel, bool enable) // TODO: same with tdm } else if (sel < 5) { /* same source with spdif a/b */ - spdifout_enable(sel - 3, enable); + spdifout_enable(sel - 3, enable, reenable); } } @@ -127,18 +127,18 @@ int sharebuffer_free(struct snd_pcm_substream *substream, } -int sharebuffer_trigger(int cmd, int samesource_sel) +int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable) { switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - sharebuffer_enable(samesource_sel, true); + sharebuffer_enable(samesource_sel, true, reenable); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - sharebuffer_enable(samesource_sel, false); + sharebuffer_enable(samesource_sel, false, reenable); break; default: return -EINVAL; diff --git a/sound/soc/amlogic/auge/sharebuffer.h b/sound/soc/amlogic/auge/sharebuffer.h index 25dca7d09ef4..e32a9f4b77a9 100644 --- a/sound/soc/amlogic/auge/sharebuffer.h +++ b/sound/soc/amlogic/auge/sharebuffer.h @@ -21,7 +21,7 @@ extern int sharebuffer_prepare(struct snd_pcm_substream *substream, void *pfrddr, int samesource_sel); extern int sharebuffer_free(struct snd_pcm_substream *substream, void *pfrddr, int samesource_sel); -extern int sharebuffer_trigger(int cmd, int samesource_sel); +extern int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable); extern void sharebuffer_get_mclk_fs_ratio(int samesource_sel, int *pll_mclk_ratio, int *mclk_fs_ratio); diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index e021552211ba..4ad78596e0f0 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -70,6 +70,8 @@ struct spdif_chipinfo { bool eq_drc_en; /* pc, pd interrupt is separated. */ bool pcpd_separated; + /* same source, spdif re-enable */ + bool same_src_spdif_reen; }; struct aml_spdif { @@ -1500,6 +1502,7 @@ struct spdif_chipinfo tl1_spdif_a_chipinfo = { .chnum_en = true, .hold_start = true, .eq_drc_en = true, + .same_src_spdif_reen = true, }; struct spdif_chipinfo tl1_spdif_b_chipinfo = { @@ -1507,6 +1510,7 @@ struct spdif_chipinfo tl1_spdif_b_chipinfo = { .chnum_en = true, .hold_start = true, .eq_drc_en = true, + .same_src_spdif_reen = true, }; static const struct of_device_id aml_spdif_device_id[] = { @@ -1544,6 +1548,7 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) struct aml_spdif *aml_spdif = NULL; struct spdif_chipinfo *p_spdif_chipinfo; int ret = 0; + bool spdif_reenable = false; aml_spdif = devm_kzalloc(dev, sizeof(struct aml_spdif), GFP_KERNEL); @@ -1564,6 +1569,8 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) aml_spdif->clk_cont = 1; aml_spdif->chipinfo = p_spdif_chipinfo; + + spdif_reenable = p_spdif_chipinfo->same_src_spdif_reen; } else dev_warn_once(dev, "check whether to update spdif chipinfo\n"); @@ -1587,7 +1594,7 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) return -EINVAL; if (aml_spdif->clk_cont) - spdifout_play_with_zerodata(aml_spdif->id); + spdifout_play_with_zerodata(aml_spdif->id, spdif_reenable); ret = devm_snd_soc_register_component(dev, &aml_spdif_component, &aml_spdif_dai[aml_spdif->id], 1); diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 04172b61eb3d..799424868f6f 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -450,13 +450,6 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_SWAP - EE_AUDIO_SPDIFOUT_SWAP; reg = EE_AUDIO_SPDIFOUT_SWAP + offset * spdif_id; audiobus_write(reg, 1<<4); - - /* reset afifo */ - offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; - reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; - audiobus_update_bits(reg, 3<<28, 0); - audiobus_update_bits(reg, 1<<29, 1<<29); - audiobus_update_bits(reg, 1<<28, 1<<28); } static bool spdifout_is_enable(int spdif_id) @@ -470,7 +463,7 @@ static bool spdifout_is_enable(int spdif_id) return ((val >> 31) == 1); } -void spdifout_enable(int spdif_id, bool is_enable) +void spdifout_enable(int spdif_id, bool is_enable, bool reenable) { unsigned int offset, reg; @@ -487,6 +480,15 @@ void spdifout_enable(int spdif_id, bool is_enable) return; } + /* disable then for reset, to correct channel map */ + if (reenable) + audiobus_update_bits(reg, 1<<31, 0x0<<31); + + /* reset afifo */ + audiobus_update_bits(reg, 3<<28, 0); + audiobus_update_bits(reg, 1<<29, 1<<29); + audiobus_update_bits(reg, 1<<28, 1<<28); + audiobus_update_bits(reg, 1<<31, is_enable<<31); } @@ -608,7 +610,7 @@ void spdif_set_channel_status_info( audiobus_write(reg, chsts->chstat1_r << 16 | chsts->chstat0_r); } -void spdifout_play_with_zerodata(unsigned int spdif_id) +void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable) { pr_debug("%s, spdif id:%d enable:%d\n", __func__, @@ -658,7 +660,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id) frddr_init_without_mngr(frddr_index, src0_sel); /* spdif enable */ - spdifout_enable(spdif_id, true); + spdifout_enable(spdif_id, true, reenable); } } diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index d2f6b96dfffc..689dc7e715ca 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -79,7 +79,7 @@ extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, int bitwidth, int channels, bool is_enable); -extern void spdifout_enable(int spdif_id, bool is_enable); +extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable); extern int spdifin_get_sample_rate(void); @@ -90,7 +90,7 @@ extern int spdifin_get_audio_type(void); extern void spdif_set_channel_status_info( struct iec958_chsts *chsts, int spdif_id); -extern void spdifout_play_with_zerodata(unsigned int spdif_id); +extern void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable); extern void spdifout_play_with_zerodata_free(unsigned int spdif_id); extern void spdifin_set_src(int src); #endif diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index ab71d3e9d65f..15dd5bb812af 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -92,6 +92,9 @@ struct tdm_chipinfo { /* same source */ bool same_src_fn; + /* same source, spdif re-enable */ + bool same_src_spdif_reen; + /* ACODEC_ADC function */ bool adc_fn; }; @@ -518,6 +521,18 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, { struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + /* share buffer trigger */ + if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + && p_tdm->chipinfo + && p_tdm->chipinfo->same_src_fn + && (p_tdm->samesource_sel >= 0) + && (aml_check_sharebuffer_valid(p_tdm->fddr, + p_tdm->samesource_sel)) + && p_tdm->en_share) + sharebuffer_trigger(cmd, + p_tdm->samesource_sel, + p_tdm->chipinfo->same_src_spdif_reen); + switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -1242,6 +1257,7 @@ struct tdm_chipinfo tl1_tdma_chipinfo = { .clk_pad_ctl = true, .same_src_fn = true, .adc_fn = true, + .same_src_spdif_reen = true, }; struct tdm_chipinfo tl1_tdmb_chipinfo = { @@ -1251,6 +1267,7 @@ struct tdm_chipinfo tl1_tdmb_chipinfo = { .clk_pad_ctl = true, .same_src_fn = true, .adc_fn = true, + .same_src_spdif_reen = true, }; struct tdm_chipinfo tl1_tdmc_chipinfo = { @@ -1260,6 +1277,7 @@ struct tdm_chipinfo tl1_tdmc_chipinfo = { .clk_pad_ctl = true, .same_src_fn = true, .adc_fn = true, + .same_src_spdif_reen = true, }; static const struct of_device_id aml_tdm_device_id[] = { From 6acc0dda5eed68002eff077e884c025eff2f5309 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Fri, 8 Mar 2019 16:19:51 +0800 Subject: [PATCH 0506/1060] audio: auge: modify share buffer can be occupied by later module [1/2] PD#SWPL-5300 Problem: share buffer is not alaway used for tdm and spdif, but raw data needs to output by spdif. this would lead to spk silence for dual output Solution: share buffer can be occupied by later module. when tdm and spdif output in share buffer, then play spdif, spdif will release from share buffer, only frddr is only used for tdm, another new frddr is used for spdif. Verify: x301 Change-Id: Ib0c2e02e575f496c0b0911d347857ede0d0cfa14 Signed-off-by: Xing Wang --- sound/soc/amlogic/auge/ddr_mngr.c | 226 ++++++++++++++++++------------ sound/soc/amlogic/auge/ddr_mngr.h | 5 + 2 files changed, 145 insertions(+), 86 deletions(-) diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 3652ace2690a..69d96f45c661 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -921,33 +921,6 @@ struct frddr *fetch_frddr_by_src(int frddr_src) return NULL; } -/* - * check frddr_src is used by other frddr for sharebuffer - * if used, disabled the other share frddr src, the module would - * for current frddr, and the checked frddr - */ -int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) -{ - int current_fifo_id = fr->fifo_id; - unsigned int i; - int ret = 1; - - for (i = 0; i < DDRMAX; i++) { - if (frddrs[i].in_use - && (frddrs[i].fifo_id != current_fifo_id) - && (frddrs[i].dest == ss_sel)) { - - pr_info("%s, ss_sel:%d used, not for share buffer at same time\n", - __func__, - ss_sel); - ret = 0; - break; - } - } - - return ret; -} - struct frddr *aml_audio_register_frddr(struct device *dev, struct aml_audio_controller *actrl, irq_handler_t handler, void *data) @@ -976,6 +949,137 @@ static inline unsigned int return base + reg - EE_AUDIO_FRDDR_A_CTRL0; } +/* + * check frddr_src is used by other frddr for sharebuffer + * if used, disabled the other share frddr src, the module would + * for current frddr, and the checked frddr + */ +int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) +{ + int current_fifo_id = fr->fifo_id; + unsigned int i; + int ret = 1; + + for (i = 0; i < DDRMAX; i++) { + if (frddrs[i].in_use + && (frddrs[i].fifo_id != current_fifo_id) + && (frddrs[i].dest == ss_sel)) { + + pr_debug("%s, ss_sel:%d used, not for share buffer at same time\n", + __func__, + ss_sel); + ret = 0; + break; + } + } + + return ret; +} + +/* select dst for same source + * sel: share buffer req_sel 1~2 + * sel 0 is aleardy used for reg_frddr_src_sel1 + * sel 1 is for reg_frddr_src_sel2 + * sel 2 is for reg_frddr_src_sel3 + */ +static void frddr_set_sharebuffer_enable( + struct frddr *fr, int dst, int sel, bool enable) +{ + struct aml_audio_controller *actrl = fr->actrl; + unsigned int reg_base = fr->reg_base; + unsigned int reg; + int s_v = 0, s_m = 0; + + if (fr->chipinfo + && fr->chipinfo->src_sel_ctrl) { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, + reg_base); + + switch (sel) { + case 1: + s_m = 0x17 << 8; + s_v = enable ? + (dst << 8 | 1 << 12) : 0 << 8; + break; + case 2: + s_m = 0x17 << 16; + s_v = enable ? + (dst << 16 | 1 << 20) : 0 << 16; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + s_m |= 0xff << 24; + if (enable) + s_v |= (fr->channels - 1) << 24; + else + s_v |= 0x0 << 24; + } else { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, + reg_base); + + switch (sel) { + case 1: + s_m = 0xf << 4; + s_v = enable ? + (dst << 4 | 1 << 7) : 0 << 4; + break; + case 2: + s_m = 0xf << 8; + s_v = enable ? + (dst << 8 | 1 << 11) : 0 << 8; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + } + pr_debug("%s sel:%d, dst_src:%d\n", + __func__, sel, dst); + fr->ss_dest = enable ? dst : 0; + fr->ss_en = enable; + + aml_audiobus_update_bits(actrl, reg, s_m, s_v); +} + +/* + * check frddr_src is used by other frddr for sharebuffer + * if used for share frddr src, release from sharebuffer + * and used for new frddr + */ +static int aml_check_and_release_sharebuffer(struct frddr *fr, int ss_sel) +{ + int current_fifo_id = fr->fifo_id; + unsigned int i; + int ret = 1; + + for (i = 0; i < DDRMAX; i++) { + struct frddr *from = &frddrs[i]; + + if (from->in_use + && (from->fifo_id != current_fifo_id) + && from->ss_en + && (from->ss_dest == ss_sel)) { + + frddr_set_sharebuffer_enable(from, + ss_sel, + 1, + false); + + pr_debug("%s, ss_sel:%d release from share buffer, use for new playback\n", + __func__, + ss_sel); + ret = 0; + break; + } + } + + return ret; +} + int aml_frddr_set_buf(struct frddr *fr, unsigned int start, unsigned int end) { @@ -1066,6 +1170,11 @@ void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst) src_sel_en = 3; } + /* if sharebuffer in use, release it */ + if (fr->chipinfo + && fr->chipinfo->same_src_fn) + aml_check_and_release_sharebuffer(fr, dst); + aml_audiobus_update_bits(actrl, reg, 0x7, dst & 0x7); /* same source en */ @@ -1085,69 +1194,14 @@ void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst) void aml_frddr_select_dst_ss(struct frddr *fr, enum frddr_dest dst, int sel, bool enable) { - struct aml_audio_controller *actrl = fr->actrl; - unsigned int reg_base = fr->reg_base; - unsigned int reg, ss_valid; - - ss_valid = aml_check_sharebuffer_valid(fr, dst); + unsigned int ss_valid = aml_check_sharebuffer_valid(fr, dst); /* same source en */ if (fr->chipinfo && fr->chipinfo->same_src_fn - && ss_valid) { - int s_v = 0, s_m = 0; - - if (fr->chipinfo - && fr->chipinfo->src_sel_ctrl) { - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, - reg_base); - - switch (sel) { - case 1: - s_m = 0x17 << 8; - s_v = enable ? - (dst << 8 | 1 << 12) : 0 << 8; - break; - case 2: - s_m = 0x17 << 16; - s_v = enable ? - (dst << 16 | 1 << 20) : 0 << 16; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; - } - s_m |= 0xff << 24; - if (enable) - s_v |= (fr->channels - 1) << 24; - else - s_v |= 0x0 << 24; - } else { - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, - reg_base); - - switch (sel) { - case 1: - s_m = 0xf << 4; - s_v = enable ? - (dst << 4 | 1 << 7) : 0 << 4; - break; - case 2: - s_m = 0xf << 8; - s_v = enable ? - (dst << 8 | 1 << 11) : 0 << 8; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; - } - } - pr_debug("%s sel:%d, dst_src:%d\n", - __func__, sel, dst); - aml_audiobus_update_bits(actrl, reg, s_m, s_v); - } + && ss_valid + ) + frddr_set_sharebuffer_enable(fr, dst, sel, enable); } void aml_frddr_set_fifos(struct frddr *fr, diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index ab1c795b64b1..7f3131b9663b 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -214,6 +214,11 @@ struct frddr { //struct ddr_desc dscrpt; struct device *dev; enum frddr_dest dest; + + /* dest for same source, whether enable */ + enum frddr_dest ss_dest; + bool ss_en; + struct aml_audio_controller *actrl; unsigned int reg_base; unsigned int fifo_id; From 4932956e38f8879fbbb40acc3d83778af0d781d8 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Tue, 26 Feb 2019 11:45:27 +0800 Subject: [PATCH 0507/1060] audio: add kcontrol of EQ setting [1/2] PD#TV-1808,TV-1809,TV-1810,TV-1811 Problem: HW EQ on TL1 doesn't work Solution: Add kcontrol of EQ setting and getting Verify: test on X301 Change-Id: Iea1525b4a57241a99389c746c0238d96424df316 Signed-off-by: Zhe Wang Conflicts: MAINTAINERS --- MAINTAINERS | 3 +- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 5 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 5 +- sound/soc/amlogic/auge/ddr_mngr.c | 22 +- sound/soc/amlogic/auge/ddr_mngr.h | 2 +- sound/soc/amlogic/auge/effects_hw_v2.c | 76 +++-- sound/soc/amlogic/auge/effects_hw_v2.h | 15 +- sound/soc/amlogic/auge/effects_hw_v2_coeff.c | 298 ------------------ sound/soc/amlogic/auge/effects_hw_v2_coeff.h | 147 +++++++++ sound/soc/amlogic/auge/effects_v2.c | 186 +++++------ sound/soc/amlogic/auge/spdif_hw.c | 2 +- 11 files changed, 324 insertions(+), 437 deletions(-) delete mode 100644 sound/soc/amlogic/auge/effects_hw_v2_coeff.c create mode 100644 sound/soc/amlogic/auge/effects_hw_v2_coeff.h diff --git a/MAINTAINERS b/MAINTAINERS index e920bbcfc796..5207f08cd39e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13820,7 +13820,8 @@ F: include/dt-bindings/clock/* F: include/linux/amlogic/media/sound/* F: sound/soc/Kconfig F: sound/soc/Makefile -F: sound/soc/amlogic/* +F: sound/soc/amlogic/auge/* +F: sound/soc/amlogic/meson/* F: sound/soc/codecs/Kconfig F: sound/soc/codecs/Makefile F: sound/soc/codecs/amlogic/* diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 8a725e023e40..ca82670a74a8 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1398,9 +1398,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1412,7 +1409,7 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 1e46e5368949..35ee85e71db4 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1114,9 +1114,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1128,7 +1125,7 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; status = "okay"; }; diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 69d96f45c661..cba4170542bc 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -1237,28 +1237,22 @@ void aml_frddr_set_format(struct frddr *fr, fr->type = frddr_type; } - static void aml_aed_enable(struct frddr_attach *p_attach_aed, bool enable) { struct frddr *fr = fetch_frddr_by_src(p_attach_aed->attach_module); - if (check_aed_v2()) { - if (fr->chipinfo - && fr->chipinfo->src_sel_ctrl) { - struct aml_audio_controller *actrl = fr->actrl; - unsigned int reg_base = fr->reg_base; - unsigned int reg; + struct aml_audio_controller *actrl = fr->actrl; + unsigned int reg_base = fr->reg_base; + unsigned int reg; - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, - reg_base); - aml_audiobus_update_bits(actrl, - reg, 0x1 << 3, enable << 3); - } + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, reg_base); + aml_audiobus_update_bits(actrl, + reg, 0x1 << 3, enable << 3); aed_set_ctrl(enable, 0, p_attach_aed->attach_module); - aed_set_format(fr->msb, fr->type); - aed_enable(enable, fr->dest, fr->fifo_id); + aed_set_format(fr->msb, fr->type, fr->fifo_id); + aed_enable(enable); } else { if (enable) { /* frddr type and bit depth for AED */ diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index 7f3131b9663b..203c0b4cfd07 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -221,7 +221,7 @@ struct frddr { struct aml_audio_controller *actrl; unsigned int reg_base; - unsigned int fifo_id; + enum ddr_num fifo_id; unsigned int channels; unsigned int msb; diff --git a/sound/soc/amlogic/auge/effects_hw_v2.c b/sound/soc/amlogic/auge/effects_hw_v2.c index 6c1e1a60013f..e6b22ab331fe 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.c +++ b/sound/soc/amlogic/auge/effects_hw_v2.c @@ -23,17 +23,31 @@ #include "tdm_hw.h" #include "spdif_hw.h" -void aed_set_ram_coeff(int len, int *params) +void aed_set_ram_coeff(int add, int len, unsigned int *params) { int i, ctrl_v; + unsigned int *p = params; - for (i = 0; i < len; i++) { - ctrl_v = (i << 2) | (0x1 << 1) | (0x1 << 0); - eqdrc_write(AED_COEF_RAM_DATA, params[i]); + for (i = 0; i < len; i++, p++) { + ctrl_v = ((add+i) << 2) | (0x1 << 1) | (0x1 << 0); + eqdrc_write(AED_COEF_RAM_DATA, *p); eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v); } } +void aed_get_ram_coeff(int add, int len, unsigned int *params) +{ + int i, ctrl_v; + unsigned int *p = params; + + for (i = 0; i < len; i++, p++) { + ctrl_v = ((add+i) << 2) | (0x0 << 1) | (0x1 << 0); + eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v); + *p = eqdrc_read(AED_COEF_RAM_DATA); + //pr_info("%s, params[%d] = %8.8x\n", __func__, i, *p); + } +} + void aed_set_multiband_drc_coeff(int len, int *params) { int band_len = len / 3, i, j; @@ -90,7 +104,7 @@ void aed_set_fullband_drc_coeff(int len, int *params) eqdrc_write(AED_DRC_LOOPBACK_CNTL, (144 << 0)); } -static void aed_set_mixer_params(void) +void aed_set_mixer_params(void) { eqdrc_write(AED_MIX0_LL, 0x40000); eqdrc_write(AED_MIX0_RL, 0x0); @@ -129,7 +143,16 @@ void aed_nd_enable(bool enable) void aed_eq_enable(int idx, bool enable) { eqdrc_update_bits(AED_EQ_EN, 0x1 << idx, enable << idx); - eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << (5 * idx), 10 << (5 * idx)); +} + +void aed_eq_taps(unsigned int eq1_taps) +{ + if (eq1_taps > 20) { + pr_err("Error EQ1_Tap = %d\n", eq1_taps); + return; + } + eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f, eq1_taps); + eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << 5, (20 - eq1_taps) << 5); } void aed_multiband_drc_enable(bool enable) @@ -150,7 +173,7 @@ void aed_fullband_drc_enable(bool enable) ); } -void aed_set_EQ_volume( +void aed_set_volume( unsigned int master_vol, unsigned int Lch_vol, unsigned int Rch_vol) @@ -161,18 +184,30 @@ void aed_set_EQ_volume( (Rch_vol << 8) | /* channel 2 volume: 0dB */ (Lch_vol << 0) /* channel 1 volume: 0dB */ ); - eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x40); + eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x200); /*10ms*/ eqdrc_write(AED_MUTE, 0); } void aed_set_lane_and_channels(int lane_mask, int ch_mask) { + int ch_num = 0, i = 0; + int val = ch_mask & 0xff; + eqdrc_update_bits(AED_TOP_CTL, 0xff << 18 | 0xf << 14, ch_mask << 18 | lane_mask << 14); + + for (i = 0; i < 8; i++) { + if ((val & 0x1) == 0x1) + ch_num++; + val >>= 1; + } + + eqdrc_update_bits(AED_TOP_REQ_CTL, + 0xff << 12, (ch_num - 1) << 12); } -void aed_set_ctrl(bool enable, int sel, int module) +void aed_set_ctrl(bool enable, int sel, enum frddr_dest module) { int mask = 0, val = 0; @@ -194,28 +229,28 @@ void aed_set_ctrl(bool enable, int sel, int module) sel, module); return; } + eqdrc_update_bits(AED_TOP_REQ_CTL, mask, val); /* Effect Module */ - if (module >= 3) { - /* SPDIFOUT A/B */ - aml_spdifout_select_aed(enable, module - 3); - } else if (module < 3 && module >= 0) { + if (module <= TDMOUT_C && module >= TDMOUT_A) { /* TDMOUT A/B/C */ aml_tdmout_select_aed(enable, module); - } else - pr_err("unknown module:%d for AED\n", module); + } else { + /* SPDIFOUT A/B */ + aml_spdifout_select_aed(enable, module - SPDIFOUT_A); + } } -void aed_set_format(int msb, int frddr_type) +void aed_set_format(int msb, enum ddr_types frddr_type, enum ddr_num source) { eqdrc_update_bits(AED_TOP_CTL, - 0x7 << 11 | 0x1f << 6, - frddr_type << 11 | msb << 6); + 0x7 << 11 | 0x1f << 6 | 0x3 << 4, + frddr_type << 11 | msb << 6 | source << 4); } -void aed_enable(bool enable, int frddr_dst, int fifo_id) +void aed_enable(bool enable) { if (enable) { eqdrc_write(AED_ED_CNTL, 0x1); @@ -223,8 +258,6 @@ void aed_enable(bool enable, int frddr_dst, int fifo_id) eqdrc_update_bits(AED_TOP_CTL, 0x1 << 1, 0x1 << 1); eqdrc_update_bits(AED_TOP_CTL, 0x1 << 2, 0x1 << 2); - - aed_set_mixer_params(); } else eqdrc_update_bits(AED_TOP_CTL, 0x3 << 1, 0x0 << 1); @@ -234,3 +267,4 @@ void aed_enable(bool enable, int frddr_dst, int fifo_id) if (enable) eqdrc_update_bits(AED_TOP_CTL, 0x1 << 31, 0x1 << 31); } + diff --git a/sound/soc/amlogic/auge/effects_hw_v2.h b/sound/soc/amlogic/auge/effects_hw_v2.h index 7c13e7fe6436..f99e3b68c5b5 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.h +++ b/sound/soc/amlogic/auge/effects_hw_v2.h @@ -17,8 +17,10 @@ #ifndef __EFFECTS_HW_V2_H__ #define __EFFECTS_HW_V2_H__ #include +#include "ddr_mngr.h" -void aed_set_ram_coeff(int len, int *params); +void aed_set_ram_coeff(int add, int len, unsigned int *params); +void aed_get_ram_coeff(int add, int len, unsigned int *params); void aed_set_multiband_drc_coeff(int len, int *params); void aed_set_fullband_drc_coeff(int len, int *params); void aed_dc_enable(bool enable); @@ -26,12 +28,15 @@ void aed_nd_enable(bool enable); void aed_eq_enable(int idx, bool enable); void aed_multiband_drc_enable(bool enable); void aed_fullband_drc_enable(bool enable); -void aed_set_EQ_volume( +void aed_set_volume( unsigned int master_volume, unsigned int Lch_vol, unsigned int Rch_vol); void aed_set_lane_and_channels(int lane_mask, int ch_mask); -void aed_set_ctrl(bool enable, int sel, int module); -void aed_set_format(int msb, int frddr_type); -void aed_enable(bool enable, int frddr_dst, int fifo_id); +void aed_set_ctrl(bool enable, int sel, enum frddr_dest module); +void aed_set_format(int msb, enum ddr_types frddr_type, enum ddr_num source); +void aed_enable(bool enable); +void aed_set_mixer_params(void); +void aed_eq_taps(unsigned int eq1_taps); + #endif diff --git a/sound/soc/amlogic/auge/effects_hw_v2_coeff.c b/sound/soc/amlogic/auge/effects_hw_v2_coeff.c deleted file mode 100644 index 903883f4c97c..000000000000 --- a/sound/soc/amlogic/auge/effects_hw_v2_coeff.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * sound/soc/amlogic/auge/effects_hw_v2_coeff.c - * - * Copyright (C) 2018 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#define AED_EQ_LENGTH 225 -#define AED_MULTIBAND_DRC_LENGTH 18 -#define AED_FULLBAND_DRC_LENGTH 24 - -static int eq_coeff[] = { - /* 0 */ 0x7fd51b, - /* 1 */ 0x30055c9, - /* 2 */ 0x7fd51b, - /* 3 */ 0x30055e6, - /* 4 */ 0x7faa53, - /* 5 */ 0x7ed219, - /* 6 */ 0x3025bce, - /* 7 */ 0x7ed219, - /* 8 */ 0x3025e96, - /* 9 */ 0x7da6fb, - /* 10 */ 0x7ed219, - /* 11 */ 0x3025bce, - /* 12 */ 0x7ed219, - /* 13 */ 0x3025e96, - /* 14 */ 0x7da6fb, - /* 15 */ 0xdf71e0, - /* 16 */ 0x2411c40, - /* 17 */ 0xdf71e0, - /* 18 */ 0x304bd12, - /* 19 */ 0x7b58fb, - /* 20 */ 0x7d8252, - /* 21 */ 0x30bb7df, - /* 22 */ 0x771ba1, - /* 23 */ 0x30bb7df, - /* 24 */ 0x749df4, - /* 25 */ 0x79f87b, - /* 26 */ 0x31971e4, - /* 27 */ 0x6ddabe, - /* 28 */ 0x31971e4, - /* 29 */ 0x67d339, - /* 30 */ 0x84f8f3, - /* 31 */ 0x31d2c91, - /* 32 */ 0x62ebbf, - /* 33 */ 0x31d2c91, - /* 34 */ 0x67e4b1, - /* 35 */ 0x711f0e, - /* 36 */ 0x3543f10, - /* 37 */ 0x4ae2f0, - /* 38 */ 0x3543f10, - /* 39 */ 0x3c01ff, - /* 40 */ 0xaaf457, - /* 41 */ 0x3831bd5, - /* 42 */ 0xfb150, - /* 43 */ 0x3831bd5, - /* 44 */ 0x3aa5a8, - /* 45 */ 0x65b5d1, - /* 46 */ 0xe3390, - /* 47 */ 0x2226c8, - /* 48 */ 0xe3390, - /* 49 */ 0x7dc99, - /* 50 */ 0x358660, - /* 51 */ 0x6b0cc1, - /* 52 */ 0x358660, - /* 53 */ 0x3b418e, - /* 54 */ 0x1ad7f4, - /* 55 */ 0x800000, - /* 56 */ 0x0, - /* 57 */ 0x0, - /* 58 */ 0x0, - /* 59 */ 0x0, - /* 60 */ 0x800000, - /* 61 */ 0x0, - /* 62 */ 0x0, - /* 63 */ 0x0, - /* 64 */ 0x0, - /* 65 */ 0x800000, - /* 66 */ 0x0, - /* 67 */ 0x0, - /* 68 */ 0x0, - /* 69 */ 0x0, - /* 70 */ 0x800000, - /* 71 */ 0x0, - /* 72 */ 0x0, - /* 73 */ 0x0, - /* 74 */ 0x0, - /* 75 */ 0x800000, - /* 76 */ 0x0, - /* 77 */ 0x0, - /* 78 */ 0x0, - /* 79 */ 0x0, - /* 80 */ 0x800000, - /* 81 */ 0x0, - /* 82 */ 0x0, - /* 83 */ 0x0, - /* 84 */ 0x0, - /* 85 */ 0x800000, - /* 86 */ 0x0, - /* 87 */ 0x0, - /* 88 */ 0x0, - /* 89 */ 0x0, - /* 90 */ 0x800000, - /* 91 */ 0x0, - /* 92 */ 0x0, - /* 93 */ 0x0, - /* 94 */ 0x0, - /* 95 */ 0x800000, - /* 96 */ 0x0, - /* 97 */ 0x0, - /* 98 */ 0x0, - /* 99 */ 0x0, - /* 100 */ 0x800000, - /* 101 */ 0x0, - /* 102 */ 0x0, - /* 103 */ 0x0, - /* 104 */ 0x0, - /* 105 */ 0x7ed219, - /* 106 */ 0x3025bce, - /* 107 */ 0x7ed219, - /* 108 */ 0x3025e96, - /* 109 */ 0x7da6fb, - /* 110 */ 0x7ed219, - /* 111 */ 0x3025bce, - /* 112 */ 0x7ed219, - /* 113 */ 0x3025e96, - /* 114 */ 0x7da6fb, - /* 115 */ 0xdf71e0, - /* 116 */ 0x2411c40, - /* 117 */ 0xdf71e0, - /* 118 */ 0x304bd12, - /* 119 */ 0x7b58fb, - /* 120 */ 0x7d8252, - /* 121 */ 0x30bb7df, - /* 122 */ 0x771ba1, - /* 123 */ 0x30bb7df, - /* 124 */ 0x749df4, - /* 125 */ 0x79f87b, - /* 126 */ 0x31971e4, - /* 127 */ 0x6ddabe, - /* 128 */ 0x31971e4, - /* 129 */ 0x67d339, - /* 130 */ 0x84f8f3, - /* 131 */ 0x31d2c91, - /* 132 */ 0x62ebbf, - /* 133 */ 0x31d2c91, - /* 134 */ 0x67e4b1, - /* 135 */ 0x711f0e, - /* 136 */ 0x3543f10, - /* 137 */ 0x4ae2f0, - /* 138 */ 0x3543f10, - /* 139 */ 0x3c01ff, - /* 140 */ 0xaaf457, - /* 141 */ 0x3831bd5, - /* 142 */ 0xfb150, - /* 143 */ 0x3831bd5, - /* 144 */ 0x3aa5a8, - /* 145 */ 0x65b5d1, - /* 146 */ 0xe3390, - /* 147 */ 0x2226c8, - /* 148 */ 0xe3390, - /* 149 */ 0x7dc99, - /* 150 */ 0x358660, - /* 151 */ 0x6b0cc1, - /* 152 */ 0x358660, - /* 153 */ 0x3b418e, - /* 154 */ 0x1ad7f4, - /* 155 */ 0x800000, - /* 156 */ 0x0, - /* 157 */ 0x0, - /* 158 */ 0x0, - /* 159 */ 0x0, - /* 160 */ 0x800000, - /* 161 */ 0x0, - /* 162 */ 0x0, - /* 163 */ 0x0, - /* 164 */ 0x0, - /* 165 */ 0x800000, - /* 166 */ 0x0, - /* 167 */ 0x0, - /* 168 */ 0x0, - /* 169 */ 0x0, - /* 170 */ 0x800000, - /* 171 */ 0x0, - /* 172 */ 0x0, - /* 173 */ 0x0, - /* 174 */ 0x0, - /* 175 */ 0x800000, - /* 176 */ 0x0, - /* 177 */ 0x0, - /* 178 */ 0x0, - /* 179 */ 0x0, - /* 180 */ 0x800000, - /* 181 */ 0x0, - /* 182 */ 0x0, - /* 183 */ 0x0, - /* 184 */ 0x0, - /* 185 */ 0x800000, - /* 186 */ 0x0, - /* 187 */ 0x0, - /* 188 */ 0x0, - /* 189 */ 0x0, - /* 190 */ 0x800000, - /* 191 */ 0x0, - /* 192 */ 0x0, - /* 193 */ 0x0, - /* 194 */ 0x0, - /* 195 */ 0x800000, - /* 196 */ 0x0, - /* 197 */ 0x0, - /* 198 */ 0x0, - /* 199 */ 0x0, - /* 200 */ 0x800000, - /* 201 */ 0x0, - /* 202 */ 0x0, - /* 203 */ 0x0, - /* 204 */ 0x0, - /* 205 */ 0x25b, - /* 206 */ 0x4b5, - /* 207 */ 0x25b, - /* 208 */ 0x3045701, - /* 209 */ 0x7bb269, - /* 210 */ 0x7dd6da, - /* 211 */ 0x304524c, - /* 212 */ 0x7dd6da, - /* 213 */ 0x3045701, - /* 214 */ 0x7bb269, - /* 215 */ 0x7f3ee, - /* 216 */ 0xfe7dc, - /* 217 */ 0x7f3ee, - /* 218 */ 0x37f9f4a, - /* 219 */ 0x20306d, - /* 220 */ 0x482449, - /* 221 */ 0x36fb76e, - /* 222 */ 0x482449, - /* 223 */ 0x37f9f4a, - /* 224 */ 0x20306d, -}; - -static int multiband_drc_coeff[] = { - 0x34ebb, /* Low SMS coeff0 */ - 0x7f54e0, /* Low SMS coeff1 */ - 0x5188, /* Low RELEASE coeff0 */ - 0x7fae78, /* Low RELEASE coeff1 */ - 0x3263a, /* Low ATTACK coeff0 */ - 0x7cd9c6, /* Low ATTACK coeff1 */ - - 0x34ebb, /* Mid */ - 0x7f54e0, - 0x5188, - 0x7fae78, - 0x3263a, - 0x7cd9c6, - - 0x34ebb, /* High */ - 0x7f54e0, - 0x5188, - 0x7fae78, - 0x3263a, - 0x7cd9c6, -}; - -static int fullband_drc_coeff[] = { - 0x5188, /* RELEASE_COEF00 */ - 0x7fae78, /* RELEASE_COEF01 */ - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, /* RELEASE_COEF50 */ - 0x7fae78, /* RELEASE_COEF51 */ - 0x3263a, /* ATTACK_COEF00 */ - 0x7cd9c6, /* ATTACK_COEF01 */ - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, /* ATTACK_COEF50 */ - 0x7cd9c6, /* ATTACK_COEF51 */ -}; diff --git a/sound/soc/amlogic/auge/effects_hw_v2_coeff.h b/sound/soc/amlogic/auge/effects_hw_v2_coeff.h new file mode 100644 index 000000000000..02ee7e8bf212 --- /dev/null +++ b/sound/soc/amlogic/auge/effects_hw_v2_coeff.h @@ -0,0 +1,147 @@ +/* + * sound/soc/amlogic/auge/effects_hw_v2_coeff.h + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#define EQ_BAND 20 +#define FILTER_PARAM_SIZE 5 +#define DC_CUT_FILTER_RAM_ADD 0 +#define DC_CUT_FILTER_SIZE FILTER_PARAM_SIZE +#define EQ_FILTER_RAM_ADD (DC_CUT_FILTER_RAM_ADD + FILTER_PARAM_SIZE) +#define EQ_FILTER_SIZE_CH (EQ_BAND*FILTER_PARAM_SIZE) +#define EQ_FILTER_SIZE (2*EQ_FILTER_SIZE_CH) +#define CROSSOVER_FILTER_RAM_ADD (EQ_FILTER_RAM_ADD + EQ_FILTER_SIZE) +#define CROSSOVER_FILTER_SIZE (4*FILTER_PARAM_SIZE) + +#define FILTER_PARAM_BYTE 66 /*"0x%8.8x "*/ + +static unsigned int DC_CUT_COEFF[DC_CUT_FILTER_SIZE] = { + 0x7fd51b, 0x30055c9, 0x7fd51b, 0x30055e6, 0x7b1673 +}; + +static unsigned int EQ_COEFF[EQ_FILTER_SIZE] = { + /*Ch1 EQ 0~19*/ + /*0~9 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + /*10~19 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + /*Ch2 EQ 0~19*/ + /*0~9 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + /*10~19 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, +}; + +/*fiter1 fc: 120Hz; fiter2 fc: 4.5KHz*/ +static unsigned int CROSSOVER_COEFF[CROSSOVER_FILTER_SIZE] = { + /*low-pass filter1*/ + 0x25b, 0x4b5, 0x25b, 0x3045701, 0x7bb269, + /*high-pass filter1*/ + 0x7dd6da, 0x304524c, 0x7dd6da, 0x3045701, 0x7bb269, + /*low-pass filter2*/ + 0x7f3ee, 0xfe7dc, 0x7f3ee, 0x37f9f4a, 0x20306d, + /*high-pass filter2*/ + 0x482449, 0x36fb76e, 0x482449, 0x37f9f4a, 0x20306d, +}; + +#define AED_MULTIBAND_DRC_LENGTH 18 +#define AED_FULLBAND_DRC_LENGTH 24 + +static int multiband_drc_coeff[] = { + 0x34ebb, /* Low SMS coeff0 */ + 0x7f54e0, /* Low SMS coeff1 */ + 0x5188, /* Low RELEASE coeff0 */ + 0x7fae78, /* Low RELEASE coeff1 */ + 0x3263a, /* Low ATTACK coeff0 */ + 0x7cd9c6, /* Low ATTACK coeff1 */ + + 0x34ebb, /* Mid */ + 0x7f54e0, + 0x5188, + 0x7fae78, + 0x3263a, + 0x7cd9c6, + + 0x34ebb, /* High */ + 0x7f54e0, + 0x5188, + 0x7fae78, + 0x3263a, + 0x7cd9c6, +}; + +static int fullband_drc_coeff[] = { + 0x5188, /* RELEASE_COEF00 */ + 0x7fae78, /* RELEASE_COEF01 */ + 0x5188, + 0x7fae78, + 0x5188, + 0x7fae78, + 0x5188, + 0x7fae78, + 0x5188, + 0x7fae78, + 0x5188, /* RELEASE_COEF50 */ + 0x7fae78, /* RELEASE_COEF51 */ + 0x3263a, /* ATTACK_COEF00 */ + 0x7cd9c6, /* ATTACK_COEF01 */ + 0x3263a, + 0x7cd9c6, + 0x3263a, + 0x7cd9c6, + 0x3263a, + 0x7cd9c6, + 0x3263a, + 0x7cd9c6, + 0x3263a, /* ATTACK_COEF50 */ + 0x7cd9c6, /* ATTACK_COEF51 */ +}; + diff --git a/sound/soc/amlogic/auge/effects_v2.c b/sound/soc/amlogic/auge/effects_v2.c index 13e4184be61a..695ca43d1e35 100644 --- a/sound/soc/amlogic/auge/effects_v2.c +++ b/sound/soc/amlogic/auge/effects_v2.c @@ -25,7 +25,7 @@ #include "effects_v2.h" #include "effects_hw_v2.h" -#include "effects_hw_v2_coeff.c" +#include "effects_hw_v2_coeff.h" #include "ddr_mngr.h" #include "regs.h" #include "iomap.h" @@ -175,29 +175,6 @@ static int mixer_aed_write(struct snd_kcontrol *kcontrol, return 0; } -static void check_set_aed_top( - struct audioeffect *p_effect, - int mask_new, bool enable) -{ - int mask_last = p_effect->mask_en; - bool update_aed_top = false; - - pr_info("%s, mask:0x%x\n", __func__, mask_new); - - if (enable) - p_effect->mask_en |= mask_new; - else - p_effect->mask_en &= ~mask_new; - - if (enable && (!mask_last) && p_effect->mask_en) - update_aed_top = true; /* to enable */ - else if ((!enable) && mask_last && (!p_effect->mask_en)) - update_aed_top = true; /* to disable */ - - if (update_aed_top) - aml_set_aed(enable, p_effect->effect_module); -} - static int mixer_aed_enable_DC(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -207,10 +184,6 @@ static int mixer_aed_enable_DC(struct snd_kcontrol *kcontrol, aed_dc_enable(p_effect->dc_en); - check_set_aed_top(p_effect, - 0x1 << AED_DC, - p_effect->dc_en); - return 0; } @@ -223,10 +196,6 @@ static int mixer_aed_enable_ND(struct snd_kcontrol *kcontrol, aed_nd_enable(p_effect->nd_en); - check_set_aed_top(p_effect, - 0x1 << AED_ND, - p_effect->nd_en); - return 0; } @@ -234,18 +203,11 @@ static int mixer_aed_enable_EQ(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - int *p_eq_coeff = eq_coeff; - int len = ARRAY_SIZE(eq_coeff); p_effect->eq_en = ucontrol->value.integer.value[0]; - aed_set_ram_coeff(len, p_eq_coeff); aed_eq_enable(0, p_effect->eq_en); - check_set_aed_top(p_effect, - 0x1 << AED_EQ, - p_effect->eq_en); - return 0; } @@ -264,10 +226,6 @@ static int mixer_aed_enable_multiband_DRC(struct snd_kcontrol *kcontrol, aed_set_multiband_drc_coeff(len, p_multiband_coeff); aed_multiband_drc_enable(p_effect->multiband_drc_en); - check_set_aed_top(p_effect, - 0x1 << AED_MDRC, - p_effect->multiband_drc_en); - return 0; } @@ -286,42 +244,93 @@ static int mixer_aed_enable_fullband_DRC(struct snd_kcontrol *kcontrol, aed_set_fullband_drc_coeff(len, p_fullband_coeff); aed_fullband_drc_enable(p_effect->fullband_drc_en); - check_set_aed_top(p_effect, - 0x1 << AED_FDRC, - p_effect->fullband_drc_en); - return 0; } static int mixer_get_EQ_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int *val = (int *)ucontrol->value.bytes.data; - int *p = &eq_coeff[0]; + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &EQ_COEFF[0]; + int i; - memcpy(val, p, AED_EQ_LENGTH); + aed_get_ram_coeff(EQ_FILTER_RAM_ADD, EQ_FILTER_SIZE_CH, p); + + for (i = 0; i < EQ_FILTER_SIZE_CH; i++) + *value++ = cpu_to_be32(*p++); return 0; } +static int str2int(char *str, unsigned int *data, int size) +{ + int num = 0; + unsigned int temp = 0; + char *ptr = str; + unsigned int *val = data; + + while (size-- != 0) { + if ((*ptr >= '0') && (*ptr <= '9')) { + temp = temp * 16 + (*ptr - '0'); + } else if ((*ptr >= 'a') && (*ptr <= 'f')) { + temp = temp * 16 + (*ptr - 'a' + 10); + } else if (*ptr == ' ') { + *(val+num) = temp; + temp = 0; + num++; + } + ptr++; + } + + return num; +} static int mixer_set_EQ_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *params = (void *)kcontrol->private_value; + unsigned int tmp_data[FILTER_PARAM_SIZE + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[FILTER_PARAM_BYTE]; + char *p_string = &tmp_string[0]; + unsigned int *p = &EQ_COEFF[0]; + int num, i, band_id; void *data; - int *val, *p = &eq_coeff[0]; + char *val; data = kmemdup(ucontrol->value.bytes.data, - params->max, GFP_KERNEL | GFP_DMA); + FILTER_PARAM_BYTE, GFP_KERNEL | GFP_DMA); if (!data) return -ENOMEM; - val = (int *)data; - memcpy(p, val, params->max / sizeof(int)); - + val = (char *)data; + memcpy(p_string, val, FILTER_PARAM_BYTE); kfree(data); + num = str2int(p_string, p_data, FILTER_PARAM_BYTE); + band_id = tmp_data[0]; + if (num != (FILTER_PARAM_SIZE + 1) || band_id >= EQ_BAND) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } + + p_data = &tmp_data[1]; + p = &EQ_COEFF[band_id*FILTER_PARAM_SIZE]; + for (i = 0; i < FILTER_PARAM_SIZE; i++, p++, p_data++) { + *p = *p_data; + *(p + EQ_FILTER_SIZE_CH) = *p_data; + } + + p = &EQ_COEFF[band_id*FILTER_PARAM_SIZE]; + aed_set_ram_coeff((EQ_FILTER_RAM_ADD + + band_id*FILTER_PARAM_SIZE), + FILTER_PARAM_SIZE, p); + + p = &EQ_COEFF[band_id*FILTER_PARAM_SIZE + EQ_FILTER_SIZE_CH]; + aed_set_ram_coeff((EQ_FILTER_RAM_ADD + + EQ_FILTER_SIZE_CH + band_id*FILTER_PARAM_SIZE), + FILTER_PARAM_SIZE, p); + return 0; } @@ -394,7 +403,6 @@ static const char *const aed_module_texts[] = { "TDMOUT_A", "TDMOUT_B", "TDMOUT_C", - "SPDIFIN", "SPDIFOUT_A", "SPDIFOUT_B", }; @@ -429,12 +437,7 @@ static int aed_module_set_enum( p_effect->effect_module = ucontrol->value.enumerated.item[0]; /* update info to ddr and modules */ - aed_set_ctrl( - p_effect->eq_en | - p_effect->multiband_drc_en | - p_effect->fullband_drc_en, - 0, - p_effect->effect_module); + aml_set_aed(1, p_effect->effect_module); return 0; } @@ -465,7 +468,7 @@ static const struct snd_kcontrol_new snd_effect_controls[] = { mixer_aed_read, mixer_aed_enable_fullband_DRC), SND_SOC_BYTES_EXT("AED EQ Parameters", - AED_EQ_LENGTH, + (EQ_FILTER_SIZE_CH * 4), mixer_get_EQ_params, mixer_set_EQ_params), @@ -484,14 +487,6 @@ static const struct snd_kcontrol_new snd_effect_controls[] = { aed_module_get_enum, aed_module_set_enum), - SOC_SINGLE_EXT("AED Lane mask", - AED_TOP_CTL, 14, 0xF, 0, - mixer_aed_read, mixer_aed_write), - - SOC_SINGLE_EXT("AED Channel mask", - AED_TOP_CTL, 18, 0xFF, 0, - mixer_aed_read, mixer_aed_write), - SOC_SINGLE_EXT_TLV("AED Lch volume", AED_EQ_VOLUME, 0, 0xFF, 1, mixer_aed_read, mixer_aed_write, @@ -558,6 +553,20 @@ static const struct of_device_id effect_device_id[] = { }; MODULE_DEVICE_TABLE(of, effect_device_id); +static void aed_set_filter_data(void) +{ + int *p; + + /* set default filter param*/ + p = &DC_CUT_COEFF[0]; + aed_set_ram_coeff(DC_CUT_FILTER_RAM_ADD, DC_CUT_FILTER_SIZE, p); + p = &EQ_COEFF[0]; + aed_set_ram_coeff(EQ_FILTER_RAM_ADD, EQ_FILTER_SIZE, p); + p = &CROSSOVER_COEFF[0]; + aed_set_ram_coeff(CROSSOVER_FILTER_RAM_ADD, CROSSOVER_FILTER_SIZE, p); + +} + static int effect_platform_probe(struct platform_device *pdev) { struct audioeffect *p_effect; @@ -567,7 +576,6 @@ static int effect_platform_probe(struct platform_device *pdev) bool multiband_drc_enable = false; bool fullband_drc_enable = false; int lane_mask = -1, channel_mask = -1, eqdrc_module = -1; - int ret; pr_info("%s, line:%d\n", __func__, __LINE__); @@ -619,16 +627,11 @@ static int effect_platform_probe(struct platform_device *pdev) return ret; } - eqdrc_clk_set(p_effect); - - eq_enable = of_property_read_bool(pdev->dev.of_node, - "eq_enable"); - - multiband_drc_enable = of_property_read_bool(pdev->dev.of_node, - "multiband_drc_enable"); - - fullband_drc_enable = of_property_read_bool(pdev->dev.of_node, - "fullband_drc_enable"); + ret = eqdrc_clk_set(p_effect); + if (ret < 0) { + dev_err(&pdev->dev, "set eq drc module clk fail!\n"); + return -EINVAL; + } ret = of_property_read_u32(pdev->dev.of_node, "eqdrc_module", @@ -654,11 +657,8 @@ static int effect_platform_probe(struct platform_device *pdev) return -EINVAL; } - pr_info("%s \t eq_en:%d, multi-band drc en:%d, full-band drc en:%d, module:%d, lane_mask:%d, ch_mask:%d\n", + pr_info("%s \t module:%d, lane_mask:%d, ch_mask:%d\n", __func__, - eq_enable, - multiband_drc_enable, - fullband_drc_enable, eqdrc_module, lane_mask, channel_mask @@ -672,8 +672,18 @@ static int effect_platform_probe(struct platform_device *pdev) p_effect->ch_mask = channel_mask; p_effect->effect_module = eqdrc_module; + /*set eq/drc module lane & channels*/ aed_set_lane_and_channels(lane_mask, channel_mask); - aed_set_EQ_volume(0xc0, 0x30, 0x30); + /*set master & channel volume gain to 0dB*/ + aed_set_volume(0xc0, 0x30, 0x30); + /*set default mixer gain*/ + aed_set_mixer_params(); + /*all 20 bands for EQ1*/ + aed_eq_taps(EQ_BAND); + /*set default filter param*/ + aed_set_filter_data(); + /*set EQ/DRC module enable*/ + aml_set_aed(1, p_effect->effect_module); p_effect->dev = dev; s_effect = p_effect; diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 799424868f6f..88adb089d6b5 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -375,7 +375,7 @@ void aml_spdifout_select_aed(bool enable, int spdifout_id) /* select eq_drc output */ offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdifout_id; - audiobus_update_bits(reg, 0x1 << 21, enable << 21); + audiobus_update_bits(reg, 0x1 << 31, enable << 31); } void aml_spdifout_get_aed_info(int spdifout_id, From b46f77e015f275c65882ea032c7ea39c24e7e2d3 Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Tue, 26 Feb 2019 20:06:47 +0800 Subject: [PATCH 0508/1060] audio: Add tas5782 volume control [1/1] PD#SWPL-4734 Problem: There is no volume control for tas5782 Solution: Add ch1/ch2 volume control for tas5782 Verify: A113 Change-Id: I1e866a2bc024713278aea0c19cc8c91084a24b90 Signed-off-by: yujie.wu Conflicts: sound/soc/codecs/amlogic/tas5782m.c --- MAINTAINERS | 5 - sound/soc/codecs/amlogic/tas5782m.c | 762 ++++++++++++++++++++++++++++ 2 files changed, 762 insertions(+), 5 deletions(-) create mode 100644 sound/soc/codecs/amlogic/tas5782m.c diff --git a/MAINTAINERS b/MAINTAINERS index 5207f08cd39e..56602280b8ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14759,11 +14759,6 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c F: drivers/amlogic/media/common/vfm/vfm.c F: include/linux/amlogic/media/camera/* -AMLOGIC MESON TL1 PANEL DTS -M: Evoke Zhang -F: arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi -F: arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi - AMLOGIC multimedia M: Pengcheng Chen F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c diff --git a/sound/soc/codecs/amlogic/tas5782m.c b/sound/soc/codecs/amlogic/tas5782m.c new file mode 100644 index 000000000000..4befae22451a --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5782m.c @@ -0,0 +1,762 @@ +/* + * sound/soc/codecs/amlogic/tas5782m.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas5782m.h" + +#define DEV_NAME "tas5782m" + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +static void tas5782m_early_suspend(struct early_suspend *h); +static void tas5782m_late_resume(struct early_suspend *h); +#endif + +#define tas5782m_RATES (SNDRV_PCM_RATE_8000 | \ + SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +#define tas5782m_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define TAS5782M_REG_00 (0x00) +#define TAS5782M_REG_7F (0x7F) +#define TAS5782M_REG_28 (0x28) +#define TAS5782M_REG_29 (0x29) +#define TAS5782M_REG_3D (0x3D) +#define TAS5782M_REG_3E (0x3E) + + + +enum BITSIZE_MODE { + BITSIZE_MODE_16BITS = 0, + BITSIZE_MODE_20BITS = 1, + BITSIZE_MODE_24BITS = 2, + BITSIZE_MODE_32BITS = 3, +}; + +/* codec private data */ +struct tas5782m_priv { + struct i2c_client *i2c; + struct regmap *regmap; + struct snd_soc_codec *codec; + struct tas57xx_platform_data *pdata; + struct work_struct work; + + unsigned int work_mode; + unsigned int chip_offset; + + /*Platform provided EQ configuration */ + int num_eq_conf_texts; + const char **eq_conf_texts; + int eq_cfg; + struct soc_enum eq_conf_enum; + unsigned char Ch1_vol; + unsigned char Ch2_vol; + unsigned char master_vol; + unsigned int mclk; + unsigned int EQ_enum_value; + unsigned int DRC_enum_value; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +static int g_sample_bitsize = 32; + +static int tas5782m_ch1_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xff; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5782m_ch2_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xff; + uinfo->value.integer.step = 1; + + return 0; +} + + +static int tas5782m_ch1_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch1_vol; + + return 0; +} + +static int tas5782m_ch2_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch2_vol; + + return 0; +} + + +static void tas5782m_set_volume(struct snd_soc_codec *codec, + int value, int ch_num) +{ + unsigned char buf[2]; + int write_count = 0; + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + if (value < 0) + value = 0; + if (value > 255) + value = 255; + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = (ch_num == 0) ? TAS5782M_REG_3D : TAS5782M_REG_3E; + buf[1] = value; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + +} + +static int tas5782m_ch1_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch1_vol = value; + tas5782m_set_volume(codec, value, 0); + + return 0; +} + +static int tas5782m_ch2_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch2_vol = value; + tas5782m_set_volume(codec, value, 1); + + return 0; +} + + +static const struct snd_kcontrol_new tas5782m_snd_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch1 Volume", + .info = tas5782m_ch1_vol_info, + .get = tas5782m_ch1_vol_get, + .put = tas5782m_ch1_vol_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch2 Volume", + .info = tas5782m_ch2_vol_info, + .get = tas5782m_ch2_vol_get, + .put = tas5782m_ch2_vol_put, + } +}; + +static int tas5782m_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + return 0; +} + +static int tas5782m_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return 0;//-EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + return 0;//-EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + break; + default: + return 0;//-EINVAL; + } + + return 0; +} + +static int tas5782m_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + unsigned int rate; + + rate = params_rate(params); + + pr_debug("rate: %u\n", rate); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_BE: + pr_debug("24bit\n"); + /* fall through */ + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S20_3BE: + pr_debug("20bit\n"); + + break; + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + pr_debug("16bit\n"); + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tas5782m_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + pr_debug("level = %d\n", level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* Full power on */ + break; + + case SND_SOC_BIAS_STANDBY: + break; + + case SND_SOC_BIAS_OFF: + /* The chip runs through the power down sequence for us. */ + break; + } + codec->component.dapm.bias_level = level; + + return 0; +} + +static const struct snd_soc_dai_ops tas5782m_dai_ops = { + .hw_params = tas5782m_hw_params, + .set_sysclk = tas5782m_set_dai_sysclk, + .set_fmt = tas5782m_set_dai_fmt, +}; + +static struct snd_soc_dai_driver tas5782m_dai = { + .name = DEV_NAME, + .playback = { + .stream_name = "HIFI Playback", + .channels_min = 2, + .channels_max = 8, + .rates = tas5782m_RATES, + .formats = tas5782m_FORMATS, + }, + .ops = &tas5782m_dai_ops, +}; + + +static int reset_tas5782m_GPIO(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + struct tas57xx_platform_data *pdata = tas5782m->pdata; + int ret = 0; + + if (pdata->reset_pin < 0) + return 0; + + ret = devm_gpio_request_one(codec->dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, "tas5782m-reset-pin"); + + if (ret < 0) { + pr_err("failed!!! devm_gpio_request_one = %d!\n", ret); + return -1; + } + + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + udelay(1000); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + udelay(1000); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + msleep(20); + + return 0; +} + +static int tas5782m_init_i2s_tdm_mode(struct snd_soc_codec *codec, int bit_size) +{ + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int work_mod = tas5782m->work_mode; + + int tdm_aofs = 0; + unsigned char buf[8] = {0}; + int write_count = 0; + enum BITSIZE_MODE bit_value = BITSIZE_MODE_32BITS; + + write_count = 2; + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + if (bit_size == 16) + bit_value = BITSIZE_MODE_16BITS; + else if (bit_size == 20) + bit_value = BITSIZE_MODE_20BITS; + else if (bit_size == 24) + bit_value = BITSIZE_MODE_24BITS; + else if (bit_size == 32) + bit_value = BITSIZE_MODE_32BITS; + + buf[0] = TAS5782M_REG_28, buf[1] = (work_mod << 4) | bit_value; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + } else { + pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x data:0x%x\n", + __func__, __LINE__, tas5782m->i2c->addr, + tas5782m->chip_offset, buf[0], buf[1]); + } + + if (work_mod == WORK_MODE_TDM) { + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + tdm_aofs = bit_size * 2 * (tas5782m->chip_offset - 1); + + buf[0] = TAS5782M_REG_29, buf[1] = tdm_aofs; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + } else { + pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x", + __func__, __LINE__, tas5782m->i2c->addr, + tas5782m->chip_offset, buf[0]); + pr_debug("tdm_aofs:0x%x SCLKS\n", tdm_aofs); + } + } + + return 0; +} + +static void tas5782m_init_func(struct work_struct *p_work) +{ + struct tas5782m_priv *tas5782m; + struct snd_soc_codec *codec; + struct i2c_client *i2c; + int i = 0, j = 0, k = 0; + int value_count; + unsigned char buf[64] = {0}; + int write_count = 0; + int data_row = 0; + + tas5782m = container_of( + p_work, struct tas5782m_priv, work); + + codec = tas5782m->codec; + + reset_tas5782m_GPIO(codec); + + //init register + tas5782m = snd_soc_codec_get_drvdata(codec); + dev_info(codec->dev, "tas5782m_init id=%d\n", tas5782m->chip_offset); + + i2c = tas5782m->i2c; + value_count = ARRAY_SIZE(tas5782m_reg_defaults); + for (i = 0; i < value_count;) { + if (tas5782m_reg_defaults[i].reg == CFG_META_BURST) { + if (tas5782m_reg_defaults[i].def == 2) { + data_row = 1; + write_count = + tas5782m_reg_defaults[i].def; + } else { + data_row = + (tas5782m_reg_defaults[i].def + + 2) >> 1; + write_count = + tas5782m_reg_defaults[i].def + + 1; + } + i++; + + j = 0, k = 0; + for (k = 0; k < data_row; k++) { + buf[j++] = + tas5782m_reg_defaults[i+k].reg; + buf[j++] = + tas5782m_reg_defaults[i+k].def; + } + + i += data_row; + + //dump_buf(buf, k); + if (write_count != + i2c_master_send(i2c, buf, + write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + break; + } + } else { + i++; + pr_info("%s %d warning: register value error!\n", + __func__, __LINE__); + } + } + + tas5782m_init_i2s_tdm_mode(codec, g_sample_bitsize); +} + +static int tas5782m_probe(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m; + +#ifdef CONFIG_HAS_EARLYSUSPEND + tas5782m->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; + tas5782m->early_suspend.suspend = tas5782m_early_suspend; + tas5782m->early_suspend.resume = tas5782m_late_resume; + tas5782m->early_suspend.param = codec; + register_early_suspend(&(tas5782m->early_suspend)); +#endif + + tas5782m = snd_soc_codec_get_drvdata(codec); + tas5782m->codec = codec; + + INIT_WORK(&tas5782m->work, tas5782m_init_func); + schedule_work(&tas5782m->work); + + return 0; +} + +static int tas5782m_remove(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m; + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + unregister_early_suspend(&(tas5782m->early_suspend)); +#endif + tas5782m = snd_soc_codec_get_drvdata(codec); + + cancel_work_sync(&tas5782m->work); + + return 0; +} + +#ifdef CONFIG_PM +static int tas5782m_suspend(struct snd_soc_codec *codec) +{ + struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev); + + dev_info(codec->dev, "tas5782m_suspend!\n"); + + if (pdata && pdata->suspend_func) + pdata->suspend_func(); + + return 0; +} + +static int tas5782m_resume(struct snd_soc_codec *codec) +{ + struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev); + struct tas5782m_priv *tas5782m; + + dev_info(codec->dev, "tas5782m_resume!\n"); + + if (pdata && pdata->resume_func) + pdata->resume_func(); + + tas5782m = snd_soc_codec_get_drvdata(codec); + tas5782m->codec = codec; + + INIT_WORK(&tas5782m->work, tas5782m_init_func); + schedule_work(&tas5782m->work); + + + return 0; +} +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void tas5782m_early_suspend(struct early_suspend *h) +{ +} + +static void tas5782m_late_resume(struct early_suspend *h) +{ +} +#endif + +static const struct snd_soc_dapm_widget tas5782m_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC", "HIFI Playback", SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_codec_driver soc_codec_dev_tas5782m = { + .probe = tas5782m_probe, + .remove = tas5782m_remove, +#ifdef CONFIG_PM + .suspend = tas5782m_suspend, + .resume = tas5782m_resume, +#endif + .set_bias_level = tas5782m_set_bias_level, + .component_driver = { + .controls = tas5782m_snd_controls, + .num_controls = ARRAY_SIZE(tas5782m_snd_controls), + .dapm_widgets = tas5782m_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5782m_dapm_widgets), + } +}; + +/* + *static const struct regmap_config tas5782m_regmap = { + * .reg_bits = 8, + * .val_bits = 8, + * + * .max_register = tas5782m_REGISTER_COUNT, + * .reg_defaults = tas5782m_reg_defaults, + * .num_reg_defaults = + * sizeof(tas5782m_reg_defaults)/sizeof(tas5782m_reg_defaults[0]), + * .cache_type = REGCACHE_RBTREE, + *}; + */ + +static int tas5782m_parse_dts(struct tas5782m_priv *tas5782m, + struct device_node *np) +{ + int ret = 0; + int reset_pin = -1; + + reset_pin = of_get_named_gpio(np, "reset_pin", 0); + if (reset_pin < 0) { + pr_err("%s fail to get reset pin from dts!\n", __func__); + ret = -1; + } else { + pr_debug("%s pdata->reset_pin = %d!\n", __func__, reset_pin); + } + tas5782m->pdata->reset_pin = reset_pin; + + ret = of_property_read_u32(np, "work_mode", &tas5782m->work_mode); + pr_debug("tas5782m->work_mode:%d(%s)!\n", tas5782m->work_mode, + (tas5782m->work_mode == WORK_MODE_I2S)?"i2s":"tdm"); + + ret = of_property_read_u32(np, "chip_offset", &tas5782m->chip_offset); + pr_debug("tas5782m->chip_offset:%d!\n", tas5782m->chip_offset); + + return ret; +} + +static int tas5782m_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct tas5782m_priv *tas5782m; + struct tas57xx_platform_data *pdata; + int ret; + const char *codec_name = NULL; + + pr_debug("i2c->addr=0x%x\n", i2c->addr); + + tas5782m = devm_kzalloc(&i2c->dev, + sizeof(struct tas5782m_priv), GFP_KERNEL); + if (!tas5782m) + return -ENOMEM; + + + tas5782m->i2c = i2c; + /* + * tas5782m->regmap = devm_regmap_init_i2c(i2c, &tas5782m_regmap); + * if (IS_ERR(tas5782m->regmap)) { + * ret = PTR_ERR(tas5782m->regmap); + * dev_err(&i2c->dev, + * "Failed to allocate register map: %d\n", ret); + * return ret; + * } + */ + pdata = devm_kzalloc(&i2c->dev, + sizeof(struct tas57xx_platform_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + tas5782m->pdata = pdata; + + tas5782m_parse_dts(tas5782m, i2c->dev.of_node); + + if (of_property_read_string(i2c->dev.of_node, + "codec_name", &codec_name)) { + pr_info("no codec name\n"); + ret = -1; + } + pr_debug("aux name = %s\n", codec_name); + if (codec_name) + dev_set_name(&i2c->dev, "%s", codec_name); + + i2c_set_clientdata(i2c, tas5782m); + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_tas5782m, &tas5782m_dai, 1); + if (ret != 0) + dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); + + return ret; +} + +static int tas5782m_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + + return 0; +} + +static const struct i2c_device_id tas5782m_i2c_id[] = { + { "tas5782m", 0 }, + {} +}; + +static const struct of_device_id tas5782m_of_id[] = { + {.compatible = "ti, tas5782m",}, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, tas5782m_of_id); + +static struct i2c_driver tas5782m_i2c_driver = { + .driver = { + .name = DEV_NAME, + .of_match_table = tas5782m_of_id, + .owner = THIS_MODULE, + }, + .probe = tas5782m_i2c_probe, + .remove = tas5782m_i2c_remove, + .id_table = tas5782m_i2c_id, +}; + +module_i2c_driver(tas5782m_i2c_driver); + + +MODULE_DESCRIPTION("ASoC tas5782m driver"); +MODULE_AUTHOR("AML MM team"); +MODULE_LICENSE("GPL"); From 63966474c7b696d5d5a295e03aec9e32a0ea4da5 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Tue, 12 Mar 2019 16:36:39 +0800 Subject: [PATCH 0509/1060] audio: tune audio volume slew time [1/1] PD#SWPL-5845 Problem: audio playback too slow Solution: change audio volume slew time Verify: Locally test on X301 Change-Id: I48c920037cac852aaa01818bb02eaa8991c1df6b Signed-off-by: Zhe Wang --- sound/soc/amlogic/auge/effects_hw_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amlogic/auge/effects_hw_v2.c b/sound/soc/amlogic/auge/effects_hw_v2.c index e6b22ab331fe..63b0f31d1fb5 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.c +++ b/sound/soc/amlogic/auge/effects_hw_v2.c @@ -184,7 +184,7 @@ void aed_set_volume( (Rch_vol << 8) | /* channel 2 volume: 0dB */ (Lch_vol << 0) /* channel 1 volume: 0dB */ ); - eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x200); /*10ms*/ + eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x2); /*40ms from -120dB~0dB*/ eqdrc_write(AED_MUTE, 0); } From 26aa6d82a58b870f74d41c349d6cc3849c1305df Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Tue, 12 Mar 2019 14:40:20 +0800 Subject: [PATCH 0510/1060] audio: fix H-voltage when tdm disable [1/1] PD#SWPL-2952 Problem: High voltage will cause the tdmout data pin wrong I2S data which cause pop. Solution: Disable the bias of gpio. Verify: I2S data will be low when I2s closed. Change-Id: If5d68e0f30df074f528dfec21cbe297795bc4ea7 Signed-off-by: Shuai Li Conflicts: arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts sound/soc/amlogic/auge/tdm.c --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 1 + arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 1 + arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 1 + sound/soc/amlogic/auge/tdm.c | 13 +++++++++---- sound/soc/amlogic/auge/tdm_hw.c | 10 ++++++++++ sound/soc/amlogic/auge/tdm_hw.h | 1 + 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 0b294bc4203b..afed6b01ea14 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -1211,6 +1211,7 @@ "tdma_dout2_z", "tdma_dout3_z"; function = "tdma_out"; + bias-disable; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index ca82670a74a8..e44f3575ed6d 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1476,6 +1476,7 @@ "tdma_fs_z", "tdma_dout0_z"; function = "tdma_out"; + bias-disable; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 35ee85e71db4..47041842189f 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1227,6 +1227,7 @@ "tdma_fs_z", "tdma_dout0_z"; function = "tdma_out"; + bias-disable; }; }; diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 15dd5bb812af..881c31d4408c 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -592,9 +592,6 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, break; } - aml_tdm_enable(p_tdm->actrl, - substream->stream, p_tdm->id, false); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback stop\n"); memset(substream->runtime->dma_area, @@ -614,7 +611,7 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, aml_toddr_enable(p_tdm->tddr, 0); } aml_tdm_enable(p_tdm->actrl, - substream->stream, p_tdm->id, false); + substream->stream, p_tdm->id, false); break; default: return -EINVAL; @@ -877,6 +874,14 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) aml_tdm_set_format(p_tdm->actrl, &(p_tdm->setting), p_tdm->clk_sel, p_tdm->id, fmt, 1, 1); + if (p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { + int ret = clk_prepare_enable(p_tdm->mclk); + + if (ret) { + pr_err("Can't enable mclk: %d\n", ret); + return ret; + } + } capture: /* update skew for ACODEC_ADC */ diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index 2927beb5c2f5..24c079bfe39f 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -637,6 +637,16 @@ void aml_tdmout_get_aed_info(int tdmout_id, *frddrtype = (val >> 4) & 0x7; } +void aml_tdmout_enable_gain(int tdmout_id, int en) +{ + unsigned int reg, offset; + + offset = EE_AUDIO_TDMOUT_B_CTRL1 + - EE_AUDIO_TDMOUT_A_CTRL1; + reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id; + audiobus_update_bits(reg, 0x1 << 26, !!en << 26); +} + void aml_tdm_clk_pad_select( struct aml_audio_controller *actrl, int mpad, int mclk_sel, diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index 791ecaabbabe..04a7b83be8c6 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -71,6 +71,7 @@ extern void aml_tdm_arb_config( extern void aml_tdm_fifo_reset( struct aml_audio_controller *actrl, int stream, int index); +void aml_tdmout_enable_gain(int tdmout_id, int en); extern int tdmout_get_frddr_type(int bitwidth); From 856ad33f9cdf942bda6be9df2c8b35635f6ae373 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Wed, 13 Mar 2019 13:56:26 +0800 Subject: [PATCH 0511/1060] audio: add spdif/HDMI mute ctrl [1/1] PD#TV-3016 Problem: HDMI SPDIF mute interface has no effect. Solution: Add these interfaces for auge platform. Verify: Tested locally. Change-Id: I168c0940e0f2b3d94091d43c6b8190f6f833c0f1 Signed-off-by: Shuai Li Conflicts: arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts sound/soc/amlogic/auge/spdif.c --- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 11 +++- .../dts/amlogic/g12a_s905d2_skt_buildroot.dts | 11 +++- .../arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 11 +++- .../boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 11 +++- .../amlogic/g12a_s905d2_u200_buildroot.dts | 11 +++- .../g12a_s905d2_u200_buildroot_vccktest.dts | 11 +++- .../g12a_s905d2_u200_drm_buildroot.dts | 11 +++- .../arm/boot/dts/amlogic/g12a_s905x2_u211.dts | 11 +++- .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 11 +++- .../dts/amlogic/g12a_s905x2_u211_512m.dts | 11 +++- .../amlogic/g12a_s905x2_u211_buildroot.dts | 11 +++- .../arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 11 +++- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 11 +++- .../amlogic/g12a_s905x2_u212_buildroot.dts | 11 +++- .../g12a_s905x2_u212_drm_buildroot.dts | 11 +++- .../arm/boot/dts/amlogic/g12a_s905y2_u220.dts | 11 +++- .../arm/boot/dts/amlogic/g12a_s905y2_u221.dts | 11 +++- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 11 +++- .../arm/boot/dts/amlogic/g12b_a311d_skt_a.dts | 11 +++- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 11 +++- .../boot/dts/amlogic/g12b_a311d_w400_a.dts | 11 +++- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 11 +++- .../amlogic/g12b_a311d_w400_buildroot_a.dts | 11 +++- .../g12b_a311d_w400_buildroot_vccktest.dts | 11 +++- .../g12b_a311d_w400_buildroot_vccktest_a.dts | 11 +++- .../amlogic/g12b_a311d_w400_drm_buildroot.dts | 11 +++- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 12 +++- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 12 +++- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 11 +++- .../boot/dts/amlogic/g12a_s905d2_skt.dts | 11 +++- .../dts/amlogic/g12a_s905d2_skt_buildroot.dts | 11 +++- .../boot/dts/amlogic/g12a_s905d2_u200.dts | 11 +++- .../boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 11 +++- .../amlogic/g12a_s905d2_u200_buildroot.dts | 11 +++- .../g12a_s905d2_u200_buildroot_vccktest.dts | 11 +++- .../g12a_s905d2_u200_drm_buildroot.dts | 11 +++- .../boot/dts/amlogic/g12a_s905x2_u211.dts | 11 +++- .../boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 11 +++- .../dts/amlogic/g12a_s905x2_u211_512m.dts | 11 +++- .../amlogic/g12a_s905x2_u211_buildroot.dts | 11 +++- .../boot/dts/amlogic/g12a_s905x2_u212.dts | 11 +++- .../boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 11 +++- .../amlogic/g12a_s905x2_u212_buildroot.dts | 11 +++- .../g12a_s905x2_u212_drm_buildroot.dts | 11 +++- .../boot/dts/amlogic/g12a_s905y2_u220.dts | 11 +++- .../boot/dts/amlogic/g12a_s905y2_u221.dts | 11 +++- .../arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 11 +++- .../boot/dts/amlogic/g12b_a311d_skt_a.dts | 11 +++- .../boot/dts/amlogic/g12b_a311d_w400.dts | 11 +++- .../boot/dts/amlogic/g12b_a311d_w400_a.dts | 11 +++- .../dts/amlogic/g12b_a311d_w400_buildroot.dts | 11 +++- .../amlogic/g12b_a311d_w400_buildroot_a.dts | 11 +++- .../g12b_a311d_w400_buildroot_vccktest.dts | 11 +++- .../g12b_a311d_w400_buildroot_vccktest_a.dts | 11 +++- .../amlogic/g12b_a311d_w400_drm_buildroot.dts | 11 +++- .../linux/amlogic/media/sound/spdif_info.h | 6 ++ sound/soc/amlogic/auge/spdif.c | 64 ++++++++++++++++--- sound/soc/amlogic/common/spdif_info.c | 29 +++++++++ sound/soc/amlogic/meson/spdif_codec.c | 23 ------- 59 files changed, 641 insertions(+), 88 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index 03985ccee214..8ddaec0d9b1d 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -855,8 +855,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1078,6 +1080,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 597aafb225dd..f789b19df155 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -799,8 +799,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1022,6 +1024,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index d1da710d8c33..fb33cba8ad63 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -986,8 +986,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1236,6 +1238,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index fe31144f92ab..429b61242a47 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -990,8 +990,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1240,6 +1242,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 0a850a2a0ce2..bb7264df0ff0 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -943,8 +943,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1167,6 +1169,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index 3f1022173ab2..fd84e7155f3f 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -947,8 +947,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1171,6 +1173,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 3d88e88807bf..cf4942189021 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -957,8 +957,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1181,6 +1183,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index a807d35f8fc3..71e37476bb39 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -916,8 +916,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1110,6 +1112,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 680cf3aaec01..dd99fd41ab3a 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -907,8 +907,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1101,6 +1103,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 872bbd3e2bab..c31fe1f97d92 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -903,8 +903,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1097,6 +1099,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index 3834590cbf6e..d2909abb4e3a 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -945,8 +945,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1139,6 +1141,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index 8e2b01a2518e..4e52524afaba 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -960,8 +960,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1154,6 +1156,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index c712375ba08c..7705079df6d7 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -956,8 +956,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1150,6 +1152,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 0c5958bc0ca0..0baccdddc62e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -944,8 +944,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1138,6 +1140,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts index 5e882d13c814..730acc80d9fa 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts @@ -929,8 +929,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1123,6 +1125,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index 5a31a2f8b6bc..d852f40ca987 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -899,8 +899,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1115,6 +1117,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index c6e89ae0e2de..25ee4273bec6 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -862,8 +862,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1078,6 +1080,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index 7a74dcada5ab..c710f37f5030 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -975,8 +975,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1207,6 +1209,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts index 6706641a7e86..786992f41771 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -955,8 +955,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1187,6 +1189,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 0017840ad7f7..ad5d807e0ee1 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -942,8 +942,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1166,6 +1168,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index 275163b7a838..6e7a9aa864bc 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -922,8 +922,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1146,6 +1148,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index edcc88096646..252887971940 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -1047,8 +1047,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1279,6 +1281,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index 25f73afe483b..e1f7cb2cc31b 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -1014,8 +1014,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1246,6 +1248,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index e83c8b1850af..b3c03210a50a 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -939,8 +939,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1163,6 +1165,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index fd62cd9b8d82..a96636e368b3 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -926,8 +926,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1150,6 +1152,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index 8f786b06455d..11fedbaee669 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -1006,8 +1006,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1238,6 +1240,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index afed6b01ea14..8bd55cb5c1da 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -1015,8 +1015,11 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; /* * whether do asrc for pcm and resample a or b @@ -1259,6 +1262,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ groups = "pdm_dclk_z", diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index e44f3575ed6d..e83462b62db2 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1320,8 +1320,11 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + /* * whether do asrc for pcm and resample a or b @@ -1517,6 +1520,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ groups = "pdm_dclk_z", diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 47041842189f..d699f9e32df9 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1036,8 +1036,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; /* * whether do asrc for pcm and resample a or b @@ -1268,6 +1270,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ groups = "pdm_dclk_z", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index 370a0388e534..984718e3b7bf 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -855,8 +855,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1078,6 +1080,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 6aba708b2e58..6453b5621d22 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -799,8 +799,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1022,6 +1024,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index 26d98f4d3175..af2d35ce9e99 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -987,8 +987,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1237,6 +1239,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 7d3e2ba52707..0b97338aa931 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -984,8 +984,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1234,6 +1236,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 8ec7270616ef..4285b7af25b5 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -943,8 +943,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1167,6 +1169,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index c3896ca3ba42..d4197f203db4 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -946,8 +946,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1170,6 +1172,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index b7c4962d72ea..f39d7b6f2a9e 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -957,8 +957,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1181,6 +1183,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index 1e6d000a33c4..9b5b4d356673 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -916,8 +916,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1110,6 +1112,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index 7021173c9ec8..dceafa0b02e4 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -907,8 +907,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1101,6 +1103,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index bd1c514de9f0..7b6d627a5c49 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -903,8 +903,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1097,6 +1099,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index d8c12d6d454d..981f39508346 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -945,8 +945,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1139,6 +1141,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index fc4eae786f8e..ae215a6fdb2c 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -960,8 +960,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1154,6 +1156,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index ec3d2110ff70..81c1ecd44173 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -952,8 +952,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1146,6 +1148,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 023cf8a23706..fa91c3874e63 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -944,8 +944,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1138,6 +1140,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts index 9e106b9e500d..dd00ad385edc 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts @@ -942,8 +942,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1136,6 +1138,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index ed09a41658c7..1a179759a626 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -899,8 +899,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1115,6 +1117,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts index 6e343249e391..bfbb8f98038d 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -860,8 +860,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1076,6 +1078,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index def509d6ecc2..4e76414130db 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -975,8 +975,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1207,6 +1209,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts index ab332404e20a..b8b0b536adff 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -955,8 +955,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1187,6 +1189,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index fe53c59ace64..06a75498e35a 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -941,8 +941,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1165,6 +1167,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index 95a13fdcd15c..adec33b6e3cc 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -921,8 +921,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1145,6 +1147,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index f2dba13b152c..99dec00b3a7e 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -1046,8 +1046,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1278,6 +1280,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index 8c23660c31de..5c494b6360ca 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -1013,8 +1013,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1245,6 +1247,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 483cf26d612a..49489f5983eb 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -939,8 +939,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1163,6 +1165,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index 8a6d0f729a12..8f138fdfa03b 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -926,8 +926,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1150,6 +1152,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index 05c6f78a380f..cea39599b967 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -1029,8 +1029,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1261,6 +1263,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_periphs"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/include/linux/amlogic/media/sound/spdif_info.h b/include/linux/amlogic/media/sound/spdif_info.h index e9fec1776202..36df67a80f96 100644 --- a/include/linux/amlogic/media/sound/spdif_info.h +++ b/include/linux/amlogic/media/sound/spdif_info.h @@ -45,4 +45,10 @@ extern int spdif_format_get_enum( extern int spdif_format_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +#ifdef CONFIG_AMLOGIC_HDMITX +int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +#endif #endif diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 4ad78596e0f0..708d068b366f 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -74,6 +74,13 @@ struct spdif_chipinfo { bool same_src_spdif_reen; }; +enum SPDIF_SRC { + SPDIFIN_PAD = 0, + SPDIFOUT, + NOAP, + HDMIRX +}; + struct aml_spdif { struct pinctrl *pin_ctl; struct aml_audio_controller *actrl; @@ -125,7 +132,10 @@ struct aml_spdif { /* last value for pc, pd */ int pc_last; int pd_last; - bool on; + + /* mixer control vals */ + bool mute; + enum SPDIF_SRC spdifin_src; }; static const struct snd_pcm_hardware aml_spdif_hardware = { @@ -268,21 +278,44 @@ static int spdifin_audio_type_get_enum( return 0; } -/* For fake */ -static bool is_mute; -static int spdifin_src; static int aml_audio_set_spdif_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - is_mute = - ucontrol->value.integer.value[0]; + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); + struct pinctrl_state *state = NULL; + bool mute = !!ucontrol->value.integer.value[0]; + + if (IS_ERR_OR_NULL(p_spdif->pin_ctl)) { + pr_err("%s(), no pinctrl", __func__); + return 0; + } + if (mute) { + state = pinctrl_lookup_state + (p_spdif->pin_ctl, "spdif_pins_mute"); + + if (!IS_ERR_OR_NULL(state)) + pinctrl_select_state(p_spdif->pin_ctl, state); + } else { + state = pinctrl_lookup_state + (p_spdif->pin_ctl, "spdif_pins"); + + if (!IS_ERR_OR_NULL(state)) + pinctrl_select_state(p_spdif->pin_ctl, state); + } + + p_spdif->mute = mute; + return 0; } static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.integer.value[0] = is_mute; + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = p_spdif->mute; return 0; } @@ -298,7 +331,11 @@ int spdifin_source_get_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.enumerated.item[0] = spdifin_src; + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.enumerated.item[0] = p_spdif->spdifin_src; + return 0; } @@ -306,6 +343,8 @@ int spdifin_source_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); int src = ucontrol->value.enumerated.item[0]; if (src > 3) { @@ -313,7 +352,8 @@ int spdifin_source_set_enum( return -1; } spdifin_set_src(src); - spdifin_src = src; + p_spdif->spdifin_src = src; + return 0; } @@ -340,7 +380,11 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = { spdifin_src_enum, spdifin_source_get_enum, spdifin_source_set_enum), - +#ifdef CONFIG_AMLOGIC_HDMITX + SOC_SINGLE_BOOL_EXT("Audio hdmi-out mute", + 0, aml_get_hdmi_out_audio, + aml_set_hdmi_out_audio), +#endif }; static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif) diff --git a/sound/soc/amlogic/common/spdif_info.c b/sound/soc/amlogic/common/spdif_info.c index 85bd5e2bb092..87d8619d6fd4 100644 --- a/sound/soc/amlogic/common/spdif_info.c +++ b/sound/soc/amlogic/common/spdif_info.c @@ -20,6 +20,9 @@ #include #include +#ifdef CONFIG_AMLOGIC_HDMITX +#include +#endif /* * 0 -- other formats except(DD,DD+,DTS) @@ -191,3 +194,29 @@ int spdif_format_set_enum( IEC958_mode_codec = index; return 0; } + +#ifdef CONFIG_AMLOGIC_HDMITX +unsigned int aml_audio_hdmiout_mute_flag; +/* call HDMITX API to enable/disable internal audio out */ +int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = !hdmitx_ext_get_audio_status(); + + aml_audio_hdmiout_mute_flag = + ucontrol->value.integer.value[0]; + return 0; +} + +int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + bool mute = ucontrol->value.integer.value[0]; + + if (aml_audio_hdmiout_mute_flag != mute) { + hdmitx_ext_set_audio_output(!mute); + aml_audio_hdmiout_mute_flag = mute; + } + return 0; +} +#endif diff --git a/sound/soc/amlogic/meson/spdif_codec.c b/sound/soc/amlogic/meson/spdif_codec.c index 299c46c43a02..fc48405a92a3 100644 --- a/sound/soc/amlogic/meson/spdif_codec.c +++ b/sound/soc/amlogic/meson/spdif_codec.c @@ -166,29 +166,6 @@ static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol, } #ifdef CONFIG_AMLOGIC_HDMITX -/* call HDMITX API to enable/disable internal audio out */ -static int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = !hdmitx_ext_get_audio_status(); - - v_spdif_codec.aml_audio_hdmiout_mute_flag = - ucontrol->value.integer.value[0]; - return 0; -} - -static int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - bool mute = ucontrol->value.integer.value[0]; - - if (v_spdif_codec.aml_audio_hdmiout_mute_flag != mute) { - hdmitx_ext_set_audio_output(!mute); - v_spdif_codec.aml_audio_hdmiout_mute_flag = mute; - } - return 0; -} - static const char * const hdmi_out_channel_mask_texts[] = { "SPDIF", "2CH_I2S_0/1", From 7a0ca0a364874b71bcc63934429a430f63e694d1 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 15 Mar 2019 16:20:26 +0800 Subject: [PATCH 0512/1060] audio: pull down audio I2S pins [1/1] PD#TV-2362 Problem: A DC voltage is always there about 300ms. And coupled with LRCLK and SCLK which may cause a toggle an DAC side. Solution: Pull down the data pin to clear the DC level. Verify: Local verified. Change-Id: Ib7aff22c44dcec2f653b7ed29495e5e52c16e038 Signed-off-by: Shuai Li --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 8bd55cb5c1da..09a14cd69948 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -1214,7 +1214,7 @@ "tdma_dout2_z", "tdma_dout3_z"; function = "tdma_out"; - bias-disable; + bias-pull-down; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index e83462b62db2..ddf749fcc154 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1479,7 +1479,7 @@ "tdma_fs_z", "tdma_dout0_z"; function = "tdma_out"; - bias-disable; + bias-pull-down; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index d699f9e32df9..c7de423bcc70 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1229,7 +1229,7 @@ "tdma_fs_z", "tdma_dout0_z"; function = "tdma_out"; - bias-disable; + bias-pull-down; }; }; From 4b06ab36f0bb5d805a6d1231a78df239a7515be9 Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Fri, 15 Mar 2019 10:13:02 +0800 Subject: [PATCH 0513/1060] audio: Add Mute function for tas5782 [1/1] PD#SWPL-5961 Problem: There is no mute control for tas5782 Solution: Add mute function for tas 5782 Verify: A113 Change-Id: I75f8b82a359778f28494636fe76c7bc4db848643 Signed-off-by: yujie.wu --- sound/soc/codecs/amlogic/tas5782m.c | 141 ++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/sound/soc/codecs/amlogic/tas5782m.c b/sound/soc/codecs/amlogic/tas5782m.c index 4befae22451a..d7bbfe383f13 100644 --- a/sound/soc/codecs/amlogic/tas5782m.c +++ b/sound/soc/codecs/amlogic/tas5782m.c @@ -52,6 +52,7 @@ static void tas5782m_late_resume(struct early_suspend *h); SNDRV_PCM_FMTBIT_S32_LE) #define TAS5782M_REG_00 (0x00) +#define TAS5782M_REG_03 (0x03) #define TAS5782M_REG_7F (0x7F) #define TAS5782M_REG_28 (0x28) #define TAS5782M_REG_29 (0x29) @@ -85,6 +86,8 @@ struct tas5782m_priv { struct soc_enum eq_conf_enum; unsigned char Ch1_vol; unsigned char Ch2_vol; + unsigned char Ch1_mute; + unsigned char Ch2_mute; unsigned char master_vol; unsigned int mclk; unsigned int EQ_enum_value; @@ -127,6 +130,38 @@ static int tas5782m_ch2_vol_info(struct snd_kcontrol *kcontrol, } +static int tas5782m_ch1_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5782m_ch2_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->value.integer.step = 1; + + return 0; +} + + + static int tas5782m_ch1_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -150,6 +185,29 @@ static int tas5782m_ch2_vol_get(struct snd_kcontrol *kcontrol, } +static int tas5782m_ch1_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch1_mute; + + return 0; +} + +static int tas5782m_ch2_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch2_mute; + + return 0; +} + + static void tas5782m_set_volume(struct snd_soc_codec *codec, int value, int ch_num) { @@ -198,6 +256,7 @@ static int tas5782m_ch1_vol_put(struct snd_kcontrol *kcontrol, value = ucontrol->value.integer.value[0]; tas5782m->Ch1_vol = value; + value = 255 - value; tas5782m_set_volume(codec, value, 0); return 0; @@ -212,11 +271,78 @@ static int tas5782m_ch2_vol_put(struct snd_kcontrol *kcontrol, value = ucontrol->value.integer.value[0]; tas5782m->Ch2_vol = value; + value = 255 - value; tas5782m_set_volume(codec, value, 1); return 0; } +static void tas5782m_set_mute(struct snd_soc_codec *codec, + unsigned char left_mute, + unsigned char right_mute) +{ + unsigned char buf[2]; + int write_count = 0; + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_03; + buf[1] = left_mute << 4 | right_mute; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + +} + + +static int tas5782m_ch1_mute_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch1_mute = value; + tas5782m_set_mute(codec, tas5782m->Ch1_mute, tas5782m->Ch2_mute); + + return 0; +} + +static int tas5782m_ch2_mute_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch2_mute = value; + tas5782m_set_mute(codec, tas5782m->Ch1_mute, tas5782m->Ch2_mute); + + return 0; +} + + static const struct snd_kcontrol_new tas5782m_snd_controls[] = { { @@ -232,7 +358,22 @@ static const struct snd_kcontrol_new tas5782m_snd_controls[] = { .info = tas5782m_ch2_vol_info, .get = tas5782m_ch2_vol_get, .put = tas5782m_ch2_vol_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch1 Mute", + .info = tas5782m_ch1_mute_info, + .get = tas5782m_ch1_mute_get, + .put = tas5782m_ch1_mute_set, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch2 Mute", + .info = tas5782m_ch2_mute_info, + .get = tas5782m_ch2_mute_get, + .put = tas5782m_ch2_mute_set, } + }; static int tas5782m_set_dai_sysclk(struct snd_soc_dai *codec_dai, From 8ec1d0bb4e1794e999419454577dbef389cc4b25 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Thu, 21 Mar 2019 20:20:21 +0800 Subject: [PATCH 0514/1060] faudio: add I2S samesrc channel mapping to spdif [1/1] PD#SWPL-6147 Problem: I2S has 8 channels but spdif only 2. Need map every single i2s lane to spdif sharebuffer. Solution: Add the DTS setting MASKS as former does. Verify: Local tested. Change-Id: If212fc1b9c937a42778682948773874951b8a55a Signed-off-by: Shuai Li Conflicts: sound/soc/amlogic/auge/tdm.c --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 6 ++ arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++ arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 6 ++ sound/soc/amlogic/auge/sharebuffer.c | 11 +-- sound/soc/amlogic/auge/sharebuffer.h | 2 +- sound/soc/amlogic/auge/spdif_hw.c | 27 +++++-- sound/soc/amlogic/auge/spdif_hw.h | 2 +- sound/soc/amlogic/auge/tdm.c | 75 ++++++++++++++++--- 8 files changed, 112 insertions(+), 23 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 09a14cd69948..1346a44912f7 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -963,6 +963,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index ddf749fcc154..1859a11c5a24 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1268,6 +1268,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index c7de423bcc70..c898729d6000 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -984,6 +984,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index 855d7a6c31b0..1a740c4a166a 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -24,7 +24,7 @@ #include "spdif_hw.h" static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, - struct frddr *fr, int spdif_id) + struct frddr *fr, int spdif_id, int lane_i2s) { struct snd_pcm_runtime *runtime = substream->runtime; int bit_depth; @@ -36,7 +36,8 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - true); + true, + lane_i2s); /* spdif to hdmitx */ spdifout_to_hdmitx_ctrl(spdif_id); @@ -63,7 +64,7 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - false); + false, 0); return 0; } @@ -82,7 +83,7 @@ void sharebuffer_enable(int sel, bool enable, bool reenable) } int sharebuffer_prepare(struct snd_pcm_substream *substream, - void *pfrddr, int samesource_sel) + void *pfrddr, int samesource_sel, int lane_i2s) { struct frddr *fr = (struct frddr *)pfrddr; @@ -95,7 +96,7 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream, } else if (samesource_sel < 5) { /* same source with spdif a/b */ sharebuffer_spdifout_prepare(substream, - fr, samesource_sel - 3); + fr, samesource_sel - 3, lane_i2s); } /* frddr, share buffer, src_sel1 */ diff --git a/sound/soc/amlogic/auge/sharebuffer.h b/sound/soc/amlogic/auge/sharebuffer.h index e32a9f4b77a9..c8e39c591e6c 100644 --- a/sound/soc/amlogic/auge/sharebuffer.h +++ b/sound/soc/amlogic/auge/sharebuffer.h @@ -18,7 +18,7 @@ #define __AML_AUDIO_SHAREBUFFER_H__ extern int sharebuffer_prepare(struct snd_pcm_substream *substream, - void *pfrddr, int samesource_sel); + void *pfrddr, int samesource_sel, int lane_i2s); extern int sharebuffer_free(struct snd_pcm_substream *substream, void *pfrddr, int samesource_sel); extern int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable); diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 88adb089d6b5..65a78b9f7338 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -420,19 +420,31 @@ static void spdifout_clk_ctrl(int spdif_id, bool is_enable) } #endif static void spdifout_fifo_ctrl(int spdif_id, - int fifo_id, int bitwidth, int channels) + int fifo_id, int bitwidth, int channels, int lane_i2s) { unsigned int frddr_type = spdifout_get_frddr_type(bitwidth); unsigned int offset, reg, i, chmask = 0; + unsigned int swap_masks = 0; + + /* spdif always masks two channel */ + if (lane_i2s * 2 >= channels) { + pr_err("invalid lane(%d) and channels(%d)\n", + lane_i2s, channels); + return; + } for (i = 0; i < channels; i++) chmask |= (1 << i); - pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n", + swap_masks = (2 * lane_i2s) | + (2 * lane_i2s + 1) << 4; + pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits, chmask %#x, swap %#x\n", (spdif_id == 0) ? "a":"b", fifo_id, frddr_type, - bitwidth); + bitwidth, + chmask, + swap_masks); /* mask lane 0 L/R channels */ offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; @@ -449,7 +461,7 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_SWAP - EE_AUDIO_SPDIFOUT_SWAP; reg = EE_AUDIO_SPDIFOUT_SWAP + offset * spdif_id; - audiobus_write(reg, 1<<4); + audiobus_write(reg, swap_masks); } static bool spdifout_is_enable(int spdif_id) @@ -493,7 +505,7 @@ void spdifout_enable(int spdif_id, bool is_enable, bool reenable) } void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable) + int bitwidth, int channels, bool is_enable, int lane_i2s) { int spdif_id; @@ -503,7 +515,8 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, spdif_id = 0; if (is_enable) - spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); + spdifout_fifo_ctrl(spdif_id, + fifo_id, bitwidth, channels, lane_i2s); } int spdifin_get_sample_rate(void) @@ -647,7 +660,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable) /* spdif ctrl */ spdifout_fifo_ctrl(spdif_id, - frddr_index, bitwidth, runtime.channels); + frddr_index, bitwidth, runtime.channels, 0); /* channel status info */ spdif_get_channel_status_info(&chsts, sample_rate); diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index 689dc7e715ca..e15efa3abaab 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -78,7 +78,7 @@ extern void aml_spdifout_get_aed_info(int spdifout_id, extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable); + int bitwidth, int channels, bool is_enable, int lane_i2s); extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable); extern int spdifin_get_sample_rate(void); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 881c31d4408c..3b368737368b 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -119,12 +119,16 @@ struct aml_tdm { struct tdm_chipinfo *chipinfo; /* share buffer with module */ int samesource_sel; + /* share buffer lane setting from DTS */ + int lane_ss; /* virtual link for i2s to hdmitx */ int i2s2hdmitx; int acodec_adc; uint last_mpll_freq; uint last_mclk_freq; uint last_fmt; + + bool en_share; }; static const struct snd_pcm_hardware aml_tdm_hardware = { @@ -396,12 +400,11 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { sharebuffer_prepare(substream, - fr, p_tdm->samesource_sel); - /* sharebuffer default uses spdif_a */ - spdif_set_audio_clk(SPDIF_A, p_tdm->clk, - runtime->rate*128, 1); + fr, p_tdm->samesource_sel, + p_tdm->lane_ss); } /* i2s source to hdmix */ @@ -571,7 +574,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { aml_spdifout_mute_without_actrl(0, false); } } else { @@ -603,7 +607,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { aml_spdifout_mute_without_actrl(0, true); } } else { @@ -779,7 +784,8 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, && (p_tdm->chipinfo->same_src_fn) && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { int mux = 0, ratio = 0; sharebuffer_get_mclk_fs_ratio(p_tdm->samesource_sel, @@ -831,7 +837,8 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && fr - && (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel))) { + && (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel)) + && p_tdm->en_share) { sharebuffer_free(substream, fr, p_tdm->samesource_sel); } @@ -1326,6 +1333,51 @@ static const struct of_device_id aml_tdm_device_id[] = { }; MODULE_DEVICE_TABLE(of, aml_tdm_device_id); +static int check_channel_mask(const char *str) +{ + int ret = -1; + + if (!strncmp(str, "i2s_0/1", 7)) + ret = 0; + else if (!strncmp(str, "i2s_2/3", 7)) + ret = 1; + else if (!strncmp(str, "i2s_4/5", 7)) + ret = 2; + else if (!strncmp(str, "i2s_6/7", 7)) + ret = 3; + return ret; +} + +/* spdif same source with i2s */ +static void parse_samesrc_channel_mask(struct aml_tdm *p_tdm) +{ + struct device_node *node = p_tdm->dev->of_node; + struct device_node *np = NULL; + const char *str = NULL; + int ret = 0; + + /* channel mask */ + np = of_get_child_by_name(node, "Channel_Mask"); + if (np == NULL) { + pr_info("No channel mask node %s\n", + "Channel_Mask"); + return; + } + + /* If spdif is same source to i2s, + * it can be muxed to i2s 2 channels + */ + ret = of_property_read_string(np, + "Spdif_samesource_Channel_Mask", &str); + if (ret) { + pr_err("error:read Spdif_samesource_Channel_Mask\n"); + return; + } + p_tdm->lane_ss = check_channel_mask(str); + + pr_info("Channel_Mask: lane_ss = %d\n", p_tdm->lane_ss); +} + static int aml_tdm_platform_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1482,8 +1534,13 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) } p_tdm->dev = dev; + /* For debug to disable share buffer */ + p_tdm->en_share = 1; dev_set_drvdata(dev, p_tdm); + /* spdif same source with i2s */ + parse_samesrc_channel_mask(p_tdm); + ret = devm_snd_soc_register_component(dev, &aml_tdm_component, &aml_tdm_dai[p_tdm->id], 1); if (ret) { From a246df3d2ef8f61e82d8c0d6d88ee5737aed7959 Mon Sep 17 00:00:00 2001 From: Gongwei Chen Date: Thu, 21 Mar 2019 20:17:49 +0800 Subject: [PATCH 0515/1060] dts: g12a and g12b no audio output [1/1] PD#SWPL-6171 Problem: no audio output Solution: modify dts spdifout_a_mute Verify: Verify by Android P AOSP fermi Change-Id: Ie19d22326154b8f59ce06dce994f8dd072e93170 Signed-off-by: GongWei Chen --- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts | 2 +- .../boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts | 2 +- arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts | 2 +- .../arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts | 2 +- .../boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts | 2 +- arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts | 2 +- .../boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts | 2 +- arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts | 2 +- .../boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts | 2 +- .../boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts | 2 +- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index 8ddaec0d9b1d..d6686825d721 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -1084,7 +1084,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index f789b19df155..b412fe1f3230 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -1028,7 +1028,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index fb33cba8ad63..3cca9f5b501c 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -1242,7 +1242,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 429b61242a47..ecdcd1315023 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -1246,7 +1246,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index bb7264df0ff0..e5202d8e88f8 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -1173,7 +1173,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index fd84e7155f3f..7204b6f6ab18 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -1177,7 +1177,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index cf4942189021..bb768ee939a4 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -1187,7 +1187,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index d852f40ca987..b7a1be3a9273 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -1121,7 +1121,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index 25ee4273bec6..b78771e6d19d 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -1084,7 +1084,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index c710f37f5030..a88a2dd1f28c 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -1213,7 +1213,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts index 786992f41771..17376a8b4014 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -1193,7 +1193,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index ad5d807e0ee1..6ec7307196ac 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -1172,7 +1172,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index 6e7a9aa864bc..6d9492cd2aa8 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -1152,7 +1152,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 252887971940..b89aaa40a1df 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -1285,7 +1285,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index e1f7cb2cc31b..83510bc0c0ee 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -1252,7 +1252,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index b3c03210a50a..aac22ee9e0b5 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -1169,7 +1169,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index a96636e368b3..202c6190596e 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -1156,7 +1156,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index 11fedbaee669..e3f43063fe27 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -1244,7 +1244,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index 984718e3b7bf..d0fb183d0632 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -1084,7 +1084,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 6453b5621d22..8b3e7a30b2a2 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -1028,7 +1028,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index af2d35ce9e99..cf6c4c52c1ca 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -1243,7 +1243,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 0b97338aa931..996f192e1d0c 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -1240,7 +1240,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 4285b7af25b5..08970fe41d61 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -1173,7 +1173,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index d4197f203db4..e92bf361641b 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -1176,7 +1176,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index f39d7b6f2a9e..9d35b059adf0 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -1187,7 +1187,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index 1a179759a626..722c9f53d9b4 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -1121,7 +1121,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts index bfbb8f98038d..2ae7ce426f05 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -1082,7 +1082,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 4e76414130db..4e3d8fa3df25 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -1213,7 +1213,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts index b8b0b536adff..c3d6219323df 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -1193,7 +1193,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 06a75498e35a..d7016640831b 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -1171,7 +1171,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index adec33b6e3cc..078e1c1e3c33 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -1151,7 +1151,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 99dec00b3a7e..daa12b9bbced 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -1284,7 +1284,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index 5c494b6360ca..b91028e69e76 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -1251,7 +1251,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 49489f5983eb..837925bafada 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -1169,7 +1169,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index 8f138fdfa03b..0c406a175bfa 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -1156,7 +1156,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index cea39599b967..4c8d1de14882 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -1267,7 +1267,7 @@ spdifout_a_mute: spdifout_a_mute { mux { /* gpiao_10 */ groups = "GPIOAO_10"; - function = "gpio_periphs"; + function = "gpio_aobus"; }; }; }; /* end of pinctrl_aobus */ From 35d1d8035a9363943372afd45aa3bcc2cf33cf38 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Thu, 14 Mar 2019 22:16:36 +0800 Subject: [PATCH 0516/1060] audio: add soc DRC tune interface [1/3] PD#SWPL-5904 Problem: Audio DRC in SOC is out of work Solution: Add DRC tune interface Verify: Verify on X301 Change-Id: I5e8ecc6dafd7fc3805b0c3e60a6ec4c945729119 Signed-off-by: Zhe Wang --- sound/soc/amlogic/auge/effects_hw_v2.c | 142 +++++---- sound/soc/amlogic/auge/effects_hw_v2.h | 18 +- sound/soc/amlogic/auge/effects_hw_v2_coeff.h | 134 ++++---- sound/soc/amlogic/auge/effects_v2.c | 317 ++++++++++--------- 4 files changed, 349 insertions(+), 262 deletions(-) diff --git a/sound/soc/amlogic/auge/effects_hw_v2.c b/sound/soc/amlogic/auge/effects_hw_v2.c index 63b0f31d1fb5..b5db9d64587f 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.c +++ b/sound/soc/amlogic/auge/effects_hw_v2.c @@ -19,7 +19,6 @@ #include "effects_hw_v2.h" #include "regs.h" #include "iomap.h" - #include "tdm_hw.h" #include "spdif_hw.h" @@ -48,60 +47,82 @@ void aed_get_ram_coeff(int add, int len, unsigned int *params) } } -void aed_set_multiband_drc_coeff(int len, int *params) +void aed_set_multiband_drc_coeff(int band, unsigned int *params) { - int band_len = len / 3, i, j; + int i; int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00; int reg = AED_MDRC_RMS_COEF00; - for (i = 0; i < 3; i++) - for (j = 0; j < band_len; j++) - eqdrc_write(reg + i * offset + j, - params[i * band_len + j]); - - eqdrc_write(AED_MDRC_THD0, 0xf6000000); - eqdrc_write(AED_MDRC_K0, 0x20000); - eqdrc_write(AED_MDRC_OFFSET0, 0x200); - eqdrc_write(AED_MDRC_LOW_GAIN, 0x40000); - - eqdrc_write(AED_MDRC_THD1, 0xfb000000); - eqdrc_write(AED_MDRC_K1, 0x26666); - eqdrc_write(AED_MDRC_OFFSET1, 0x200); - eqdrc_write(AED_MDRC_MID_GAIN, 0x40000); - - eqdrc_write(AED_MDRC_THD2, 0xf1000000); - eqdrc_write(AED_MDRC_K2, 0x2cccc); - eqdrc_write(AED_MDRC_OFFSET2, 0x200); - eqdrc_write(AED_MDRC_HIGH_GAIN, 0x40000); + for (i = 0; i < offset; i++) { + eqdrc_write(reg + band * offset + i, + params[band * offset + i]); + } } -void aed_set_fullband_drc_coeff(int len, int *params) +void aed_get_multiband_drc_coeff(int band, unsigned int *params) { int i; + int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00; + int reg = AED_MDRC_RMS_COEF00; - for (i = 0; i < len; i++) - eqdrc_write(AED_DRC_RELEASE_COEF00 + i, - params[i]); + for (i = 0; i < offset; i++) { + *(params + band * offset + i) = + eqdrc_read(reg + band * offset + i); + } +} - eqdrc_write(AED_DRC_RMS_COEF0, 0x34ebb); - eqdrc_write(AED_DRC_RMS_COEF1, 0x7cb145); - eqdrc_write(AED_DRC_THD0, 0xf7000000); - eqdrc_write(AED_DRC_THD1, 0xf6000000); - eqdrc_write(AED_DRC_THD2, 0xec000000); - eqdrc_write(AED_DRC_THD3, 0xe2000000); - eqdrc_write(AED_DRC_THD4, 0xce000000); - eqdrc_write(AED_DRC_K0, 0x20000); - eqdrc_write(AED_DRC_K1, 0x46666); - eqdrc_write(AED_DRC_K2, 0x40000); - eqdrc_write(AED_DRC_K3, 0x39999); - eqdrc_write(AED_DRC_K4, 0x33333); - eqdrc_write(AED_DRC_K5, 0x4cccc); - eqdrc_write(AED_DRC_THD_OUT0, 0xf5e66667); - eqdrc_write(AED_DRC_THD_OUT1, 0xebe66667); - eqdrc_write(AED_DRC_THD_OUT2, 0xe2e66667); - eqdrc_write(AED_DRC_THD_OUT3, 0xd2e66667); - eqdrc_write(AED_DRC_OFFSET, 0x100); - eqdrc_write(AED_DRC_LOOPBACK_CNTL, (144 << 0)); +void aed_set_fullband_drc_coeff(int group, unsigned int *params) +{ + unsigned int *p = params; + + if (group == 0) { + eqdrc_write(AED_DRC_RELEASE_COEF00, *p++); + eqdrc_write(AED_DRC_RELEASE_COEF01, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF00, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF01, *p++); + eqdrc_write(AED_DRC_THD0, *p++); + eqdrc_write(AED_DRC_K0, *p++); + } else if (group == 1) { + eqdrc_write(AED_DRC_RELEASE_COEF10, *p++); + eqdrc_write(AED_DRC_RELEASE_COEF11, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF10, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF11, *p++); + eqdrc_write(AED_DRC_THD1, *p++); + eqdrc_write(AED_DRC_K2, *p++); + eqdrc_write(AED_DRC_THD_OUT0, eqdrc_read(AED_DRC_THD1)); + } else if (group == 2) { + eqdrc_write(AED_DRC_RMS_COEF0, *p++); + eqdrc_write(AED_DRC_RMS_COEF1, *p++); + eqdrc_write(AED_DRC_LOOPBACK_CNTL, *p++); + /*THD_OUT0 = THD1; K1 = 1.0*/ + eqdrc_write(AED_DRC_THD_OUT0, eqdrc_read(AED_DRC_THD1)); + eqdrc_write(AED_DRC_K1, 0x40000); + } +} + +void aed_get_fullband_drc_coeff(int len, unsigned int *params) +{ + unsigned int *p = params; + + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF00); + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF01); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF00); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF01); + *p++ = eqdrc_read(AED_DRC_THD0); + *p++ = eqdrc_read(AED_DRC_K0); + + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF10); + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF11); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF10); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF11); + *p++ = eqdrc_read(AED_DRC_THD1); + *p++ = eqdrc_read(AED_DRC_K2); + + *p++ = eqdrc_read(AED_DRC_RMS_COEF0); + *p++ = eqdrc_read(AED_DRC_RMS_COEF1); + *p++ = eqdrc_read(AED_DRC_LOOPBACK_CNTL); + *p++ = eqdrc_read(AED_DRC_THD_OUT0); + *p++ = eqdrc_read(AED_DRC_K1); } void aed_set_mixer_params(void) @@ -155,22 +176,29 @@ void aed_eq_taps(unsigned int eq1_taps) eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << 5, (20 - eq1_taps) << 5); } -void aed_multiband_drc_enable(bool enable) +void aed_set_multiband_drc_param(void) { - eqdrc_write(AED_MDRC_CNTL, - (1 << 16) | /* mdrc_pow_sel */ - (enable << 8) | /* mdrc_all_en */ - (7 << 3) | /* mdrc_rms_mode[2:0] */ - (7 << 0) /* mdrc_en[2:0] */ - ); + eqdrc_update_bits(AED_MDRC_CNTL, + (0x1 << 16) | (0x7 << 3) | (0x7 << 0), + (0x0 << 16) | (0x7 << 3) | (0x7 << 0)); } -void aed_fullband_drc_enable(bool enable) +void aed_set_fullband_drc_param(int tap) { - eqdrc_write(AED_DRC_CNTL, - (5 << 3) | /* drc_tap */ - (enable << 0) /* drc_en */ - ); + eqdrc_update_bits(AED_DRC_CNTL, + (0x7 << 3), (tap << 3)); +} + +void aed_set_multiband_drc_enable(bool enable) +{ + eqdrc_update_bits(AED_MDRC_CNTL, + (0x1 << 8), (enable << 8)); +} + +void aed_set_fullband_drc_enable(bool enable) +{ + eqdrc_update_bits(AED_DRC_CNTL, + (0x1 << 0), (enable << 0)); } void aed_set_volume( diff --git a/sound/soc/amlogic/auge/effects_hw_v2.h b/sound/soc/amlogic/auge/effects_hw_v2.h index f99e3b68c5b5..cfa8e0fa78a8 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.h +++ b/sound/soc/amlogic/auge/effects_hw_v2.h @@ -21,22 +21,24 @@ void aed_set_ram_coeff(int add, int len, unsigned int *params); void aed_get_ram_coeff(int add, int len, unsigned int *params); -void aed_set_multiband_drc_coeff(int len, int *params); -void aed_set_fullband_drc_coeff(int len, int *params); +void aed_set_multiband_drc_coeff(int band, unsigned int *params); +void aed_get_multiband_drc_coeff(int band, unsigned int *params); +void aed_set_fullband_drc_coeff(int group, unsigned int *params); +void aed_get_fullband_drc_coeff(int len, unsigned int *params); void aed_dc_enable(bool enable); void aed_nd_enable(bool enable); void aed_eq_enable(int idx, bool enable); -void aed_multiband_drc_enable(bool enable); -void aed_fullband_drc_enable(bool enable); -void aed_set_volume( - unsigned int master_volume, - unsigned int Lch_vol, - unsigned int Rch_vol); +void aed_set_fullband_drc_enable(bool enable); +void aed_set_multiband_drc_enable(bool enable); +void aed_set_volume(unsigned int master_volume, + unsigned int Lch_vol, unsigned int Rch_vol); void aed_set_lane_and_channels(int lane_mask, int ch_mask); void aed_set_ctrl(bool enable, int sel, enum frddr_dest module); void aed_set_format(int msb, enum ddr_types frddr_type, enum ddr_num source); void aed_enable(bool enable); void aed_set_mixer_params(void); void aed_eq_taps(unsigned int eq1_taps); +void aed_set_multiband_drc_param(void); +void aed_set_fullband_drc_param(int tap); #endif diff --git a/sound/soc/amlogic/auge/effects_hw_v2_coeff.h b/sound/soc/amlogic/auge/effects_hw_v2_coeff.h index 02ee7e8bf212..d0c943359719 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2_coeff.h +++ b/sound/soc/amlogic/auge/effects_hw_v2_coeff.h @@ -15,20 +15,25 @@ * */ -#define EQ_BAND 20 -#define FILTER_PARAM_SIZE 5 -#define DC_CUT_FILTER_RAM_ADD 0 -#define DC_CUT_FILTER_SIZE FILTER_PARAM_SIZE -#define EQ_FILTER_RAM_ADD (DC_CUT_FILTER_RAM_ADD + FILTER_PARAM_SIZE) -#define EQ_FILTER_SIZE_CH (EQ_BAND*FILTER_PARAM_SIZE) -#define EQ_FILTER_SIZE (2*EQ_FILTER_SIZE_CH) -#define CROSSOVER_FILTER_RAM_ADD (EQ_FILTER_RAM_ADD + EQ_FILTER_SIZE) -#define CROSSOVER_FILTER_SIZE (4*FILTER_PARAM_SIZE) +#ifndef __EFFECTS_HW_V2_COEFF_H__ +#define __EFFECTS_HW_V2_COEFF_H__ -#define FILTER_PARAM_BYTE 66 /*"0x%8.8x "*/ +#define EQ_BAND (20) +#define FILTER_PARAM_SIZE (5) +#define DC_CUT_FILTER_RAM_ADD (0) +#define DC_CUT_FILTER_SIZE (5) +#define EQ_FILTER_RAM_ADD (5) +#define EQ_FILTER_SIZE_CH (100) +#define EQ_FILTER_SIZE (200) +#define CROSSOVER_FILTER_RAM_ADD (205) +#define CROSSOVER_FILTER_SIZE (20) +#define CROSSOVER_FILTER_BAND (4) +#define FILTER_PARAM_BYTE (66) /*"0x%8.8x "*/ + +/* 20Hz, highpass filter */ static unsigned int DC_CUT_COEFF[DC_CUT_FILTER_SIZE] = { - 0x7fd51b, 0x30055c9, 0x7fd51b, 0x30055e6, 0x7b1673 + 0x007fc365, 0x03007935, 0x007fc365, 0x03007952, 0x007f86e7 }; static unsigned int EQ_COEFF[EQ_FILTER_SIZE] = { @@ -80,68 +85,85 @@ static unsigned int EQ_COEFF[EQ_FILTER_SIZE] = { 0x800000, 0x0, 0x0, 0x0, 0x0, }; -/*fiter1 fc: 120Hz; fiter2 fc: 4.5KHz*/ +/*fiter1 fc: 150Hz; fiter2 fc: 5KHz*/ static unsigned int CROSSOVER_COEFF[CROSSOVER_FILTER_SIZE] = { /*low-pass filter1*/ - 0x25b, 0x4b5, 0x25b, 0x3045701, 0x7bb269, + 0x00000319, 0x00000632, 0x00000319, 0x0304fa54, 0x007b1210, /*high-pass filter1*/ - 0x7dd6da, 0x304524c, 0x7dd6da, 0x3045701, 0x7bb269, + 0x007d85ef, 0x0304f422, 0x007d85ef, 0x0304fa54, 0x007b1210, /*low-pass filter2*/ - 0x7f3ee, 0xfe7dc, 0x7f3ee, 0x37f9f4a, 0x20306d, + 0x0008388a, 0x00107113, 0x0008388a, 0x0381c139, 0x001f20ee, /*high-pass filter2*/ - 0x482449, 0x36fb76e, 0x482449, 0x37f9f4a, 0x20306d, + 0x004757ed, 0x03715025, 0x004757ed, 0x0381c139, 0x001f20ee, }; -#define AED_MULTIBAND_DRC_LENGTH 18 -#define AED_FULLBAND_DRC_LENGTH 24 - -static int multiband_drc_coeff[] = { - 0x34ebb, /* Low SMS coeff0 */ - 0x7f54e0, /* Low SMS coeff1 */ +#define AED_SINGLE_BAND_DRC_SIZE (10) +#define AED_MULTIBAND_DRC_BANDS (3) +#define AED_MULTIBAND_DRC_SIZE (30) +#define MULTIBAND_DRC_PARAM_BYTE (120) /*"0x%8.8x "*/ +/*RMS:5ms, ATTACK:2ms, RELEASE:20ms*/ +static unsigned int multiband_drc_coeff[AED_MULTIBAND_DRC_SIZE] = { + 0x34ebb, /* Low RMS coeff0 */ + 0x7cb145, /* Low RMS coeff1 */ 0x5188, /* Low RELEASE coeff0 */ 0x7fae78, /* Low RELEASE coeff1 */ 0x3263a, /* Low ATTACK coeff0 */ 0x7cd9c6, /* Low ATTACK coeff1 */ + 0x0, /* Low THD0 coeff */ + 0x40000, /* Low K0 coeff */ + 0x40000, /* Low GAIN */ + 0x0, /* Low OFFSET coeff*/ - 0x34ebb, /* Mid */ - 0x7f54e0, - 0x5188, - 0x7fae78, - 0x3263a, - 0x7cd9c6, + 0x34ebb, /* Mid RMS coeff0 */ + 0x7cb145, /* Mid RMS coeff1 */ + 0x5188, /* Mid RELEASE coeff0 */ + 0x7fae78, /* Mid RELEASE coeff1 */ + 0x3263a, /* Mid ATTACK coeff0 */ + 0x7cd9c6, /* Mid ATTACK coeff1 */ + 0x0, /* Mid THD0 coeff */ + 0x40000, /* Mid K0 coeff */ + 0x0, /* Mid OFFSET coeff*/ + 0x40000, /* Mid GAIN */ - 0x34ebb, /* High */ - 0x7f54e0, - 0x5188, - 0x7fae78, - 0x3263a, - 0x7cd9c6, + 0x34ebb, /* High RMS coeff0 */ + 0x7cb145, /* High RMS coeff1 */ + 0x5188, /* High RELEASE coeff0 */ + 0x7fae78, /* High RELEASE coeff1 */ + 0x3263a, /* High ATTACK coeff0 */ + 0x7cd9c6, /* High ATTACK coeff1 */ + 0x0, /* High THD0 coeff */ + 0x40000, /* High K0 coeff */ + 0x0, /* High OFFSET coeff*/ + 0x40000, /* High GAIN */ }; -static int fullband_drc_coeff[] = { - 0x5188, /* RELEASE_COEF00 */ +#define AED_FULLBAND_DRC_SIZE (17) +#define AED_FULLBAND_DRC_BYTES (70) +#define AED_FULLBAND_DRC_OFFSET (6) +#define AED_FULLBAND_DRC_GROUP_SIZE (3) +/*K0 = 0dB; THD0 = 0; K1 = 3.0; THD1 = -70dB*/ +/*RMS:5ms, ATTACK:2ms, RELEASE:20ms*/ +/*delay: 144 sample max:255*/ +static int fullband_drc_coeff[AED_FULLBAND_DRC_SIZE] = { + 0x5188, /* RELEASE_COEF00 */ 0x7fae78, /* RELEASE_COEF01 */ - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, /* RELEASE_COEF50 */ - 0x7fae78, /* RELEASE_COEF51 */ 0x3263a, /* ATTACK_COEF00 */ 0x7cd9c6, /* ATTACK_COEF01 */ - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, /* ATTACK_COEF50 */ - 0x7cd9c6, /* ATTACK_COEF51 */ + 0x0, /* THD0 */ + 0x0, /* K0 */ + + 0x5188, /* RELEASE_COEF10 */ + 0x7fae78, /* RELEASE_COEF11 */ + 0x3263a, /* ATTACK_COEF10 */ + 0x7cd9c6, /* ATTACK_COEF11 */ + 0xdd000000, /* THD1 */ + 0xc0000, /* K2 */ + + 0x34ebb, /* RMS coeff0 */ + 0x7cb145, /* RMS coeff1 */ + 0x90, /* Delay time*/ + 0xdd000000, /* THD_OUT0 */ + 0x40000, /* K1 */ }; +#endif diff --git a/sound/soc/amlogic/auge/effects_v2.c b/sound/soc/amlogic/auge/effects_v2.c index 695ca43d1e35..86a696b1df70 100644 --- a/sound/soc/amlogic/auge/effects_v2.c +++ b/sound/soc/amlogic/auge/effects_v2.c @@ -70,7 +70,6 @@ struct audioeffect { bool eq_en; bool multiband_drc_en; bool fullband_drc_en; - int mask_en; int lane_mask; int ch_mask; @@ -175,78 +174,6 @@ static int mixer_aed_write(struct snd_kcontrol *kcontrol, return 0; } -static int mixer_aed_enable_DC(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - - p_effect->dc_en = ucontrol->value.integer.value[0]; - - aed_dc_enable(p_effect->dc_en); - - return 0; -} - -static int mixer_aed_enable_ND(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - - p_effect->nd_en = ucontrol->value.integer.value[0]; - - aed_nd_enable(p_effect->nd_en); - - return 0; -} - -static int mixer_aed_enable_EQ(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - - p_effect->eq_en = ucontrol->value.integer.value[0]; - - aed_eq_enable(0, p_effect->eq_en); - - return 0; -} - -static int mixer_aed_enable_multiband_DRC(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - int *p_multiband_coeff = multiband_drc_coeff; - int len = ARRAY_SIZE(multiband_drc_coeff); - - if (!p_effect) - return -EINVAL; - - p_effect->multiband_drc_en = ucontrol->value.integer.value[0]; - - aed_set_multiband_drc_coeff(len, p_multiband_coeff); - aed_multiband_drc_enable(p_effect->multiband_drc_en); - - return 0; -} - -static int mixer_aed_enable_fullband_DRC(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - int *p_fullband_coeff = fullband_drc_coeff; - int len = ARRAY_SIZE(fullband_drc_coeff); - - if (!p_effect) - return -EINVAL; - - p_effect->fullband_drc_en = ucontrol->value.integer.value[0]; - - aed_set_fullband_drc_coeff(len, p_fullband_coeff); - aed_fullband_drc_enable(p_effect->fullband_drc_en); - - return 0; -} - static int mixer_get_EQ_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -294,17 +221,11 @@ static int mixer_set_EQ_params(struct snd_kcontrol *kcontrol, char *p_string = &tmp_string[0]; unsigned int *p = &EQ_COEFF[0]; int num, i, band_id; - void *data; - char *val; + char *val = (char *)ucontrol->value.bytes.data; - data = kmemdup(ucontrol->value.bytes.data, - FILTER_PARAM_BYTE, GFP_KERNEL | GFP_DMA); - if (!data) + if (!val) return -ENOMEM; - - val = (char *)data; memcpy(p_string, val, FILTER_PARAM_BYTE); - kfree(data); num = str2int(p_string, p_data, FILTER_PARAM_BYTE); band_id = tmp_data[0]; @@ -334,13 +255,72 @@ static int mixer_set_EQ_params(struct snd_kcontrol *kcontrol, return 0; } +static int mixer_get_crossover_params(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &CROSSOVER_COEFF[0]; + int i; + + aed_get_ram_coeff(CROSSOVER_FILTER_RAM_ADD, CROSSOVER_FILTER_SIZE, p); + + for (i = 0; i < CROSSOVER_FILTER_SIZE; i++) + *value++ = cpu_to_be32(*p++); + + return 0; +} + +static int mixer_set_crossover_params(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int tmp_data[FILTER_PARAM_SIZE + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[FILTER_PARAM_BYTE]; + char *p_string = &tmp_string[0]; + unsigned int *p = &CROSSOVER_COEFF[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; + + if (!val) + return -ENOMEM; + memcpy(p_string, val, FILTER_PARAM_BYTE); + + num = str2int(p_string, p_data, FILTER_PARAM_BYTE); + band_id = tmp_data[0]; + if (num != (FILTER_PARAM_SIZE + 1) || + band_id >= CROSSOVER_FILTER_BAND) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } + + p_data = &tmp_data[1]; + p = &CROSSOVER_COEFF[band_id*FILTER_PARAM_SIZE]; + for (i = 0; i < FILTER_PARAM_SIZE; i++) + *p++ = *p_data++; + + p = &CROSSOVER_COEFF[band_id*FILTER_PARAM_SIZE]; + aed_set_ram_coeff((CROSSOVER_FILTER_RAM_ADD + + band_id*FILTER_PARAM_SIZE), + FILTER_PARAM_SIZE, p); + + return 0; +} + static int mixer_get_multiband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int *val = (int *)ucontrol->value.bytes.data; - int *p = &multiband_drc_coeff[0]; + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &multiband_drc_coeff[0]; + int i; - memcpy(val, p, AED_MULTIBAND_DRC_LENGTH); + for (i = 0; i < 3; i++) { + aed_get_multiband_drc_coeff(i, + p + i * AED_SINGLE_BAND_DRC_SIZE); + } + + for (i = 0; i < AED_MULTIBAND_DRC_SIZE; i++) + *value++ = cpu_to_be32(*p++); return 0; } @@ -348,19 +328,35 @@ static int mixer_get_multiband_DRC_params(struct snd_kcontrol *kcontrol, static int mixer_set_multiband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *params = (void *)kcontrol->private_value; - void *data; - int *val, *p = &multiband_drc_coeff[0]; + unsigned int tmp_data[AED_SINGLE_BAND_DRC_SIZE + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[MULTIBAND_DRC_PARAM_BYTE]; + char *p_string = &tmp_string[0]; + unsigned int *p = &multiband_drc_coeff[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; - data = kmemdup(ucontrol->value.bytes.data, - params->max, GFP_KERNEL | GFP_DMA); - if (!data) + if (!val) return -ENOMEM; + memcpy(p_string, val, MULTIBAND_DRC_PARAM_BYTE); - val = (int *)data; - memcpy(p, val, params->max / sizeof(int)); + num = str2int(p_string, p_data, MULTIBAND_DRC_PARAM_BYTE); + band_id = tmp_data[0]; + if (num != (AED_SINGLE_BAND_DRC_SIZE + 1) || + band_id >= AED_MULTIBAND_DRC_BANDS) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } - kfree(data); + /*Don't update offset and gain*/ + p_data = &tmp_data[1]; + p = &multiband_drc_coeff[band_id*AED_SINGLE_BAND_DRC_SIZE]; + for (i = 0; i < (AED_SINGLE_BAND_DRC_SIZE - 2) ; i++) + *p++ = *p_data++; + + p = &multiband_drc_coeff[0]; + aed_set_multiband_drc_coeff(band_id, p); return 0; } @@ -368,10 +364,14 @@ static int mixer_set_multiband_DRC_params(struct snd_kcontrol *kcontrol, static int mixer_get_fullband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int *val = (int *)ucontrol->value.bytes.data; - int *p = &fullband_drc_coeff[0]; + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &fullband_drc_coeff[0]; + int i; - memcpy(val, p, AED_FULLBAND_DRC_LENGTH); + aed_get_fullband_drc_coeff(AED_FULLBAND_DRC_SIZE, p); + + for (i = 0; i < AED_FULLBAND_DRC_SIZE; i++) + *value++ = cpu_to_be32(*p++); return 0; } @@ -379,19 +379,34 @@ static int mixer_get_fullband_DRC_params(struct snd_kcontrol *kcontrol, static int mixer_set_fullband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *params = (void *)kcontrol->private_value; - void *data; - int *val, *p = &fullband_drc_coeff[0]; + unsigned int tmp_data[AED_FULLBAND_DRC_OFFSET + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[AED_FULLBAND_DRC_BYTES]; + char *p_string = &tmp_string[0]; + unsigned int *p = &fullband_drc_coeff[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; - data = kmemdup(ucontrol->value.bytes.data, - params->max, GFP_KERNEL | GFP_DMA); - if (!data) + if (!val) return -ENOMEM; + memcpy(p_string, val, AED_FULLBAND_DRC_BYTES); - val = (int *)data; - memcpy(p, val, params->max / sizeof(int)); + num = str2int(p_string, p_data, AED_FULLBAND_DRC_BYTES); + band_id = tmp_data[0]; + if (num != (AED_FULLBAND_DRC_OFFSET + 1) || + band_id >= AED_FULLBAND_DRC_GROUP_SIZE) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } - kfree(data); + p_data = &tmp_data[1]; + p = &fullband_drc_coeff[band_id*AED_FULLBAND_DRC_OFFSET]; + for (i = 0; i < AED_FULLBAND_DRC_OFFSET; i++) + *p++ = *p_data++; + + p = &fullband_drc_coeff[band_id*AED_FULLBAND_DRC_OFFSET]; + aed_set_fullband_drc_coeff(band_id, p); return 0; } @@ -442,6 +457,38 @@ static int aed_module_set_enum( return 0; } +static void aed_set_filter_data(void) +{ + int *p; + + /* set default filter param*/ + p = &DC_CUT_COEFF[0]; + aed_set_ram_coeff(DC_CUT_FILTER_RAM_ADD, DC_CUT_FILTER_SIZE, p); + p = &EQ_COEFF[0]; + aed_set_ram_coeff(EQ_FILTER_RAM_ADD, EQ_FILTER_SIZE, p); + p = &CROSSOVER_COEFF[0]; + aed_set_ram_coeff(CROSSOVER_FILTER_RAM_ADD, CROSSOVER_FILTER_SIZE, p); + +} + +static void aed_set_drc_data(void) +{ + unsigned int *p = &multiband_drc_coeff[0]; + int i; + + /*set MDRC default value*/ + for (i = 0; i < AED_MULTIBAND_DRC_BANDS; i++) + aed_set_multiband_drc_coeff(i, p); + + + /*set FDRC default value*/ + p = &fullband_drc_coeff[0]; + for (i = 0; i < AED_FULLBAND_DRC_GROUP_SIZE; i++) { + aed_set_fullband_drc_coeff(i, + p + i * AED_FULLBAND_DRC_OFFSET); + } +} + static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12276, 12, 1); static const DECLARE_TLV_DB_SCALE(lr_vol_tlv, -12750, 50, 1); @@ -449,36 +496,41 @@ static const struct snd_kcontrol_new snd_effect_controls[] = { SOC_SINGLE_EXT("AED DC cut enable", AED_DC_EN, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_DC), + mixer_aed_read, mixer_aed_write), SOC_SINGLE_EXT("AED Noise Detect enable", AED_ND_CNTL, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_ND), + mixer_aed_read, mixer_aed_write), SOC_SINGLE_EXT("AED EQ enable", AED_EQ_EN, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_EQ), - - SOC_SINGLE_EXT("AED Multi-band DRC enable", - AED_MDRC_CNTL, 8, 0x1, 0, - mixer_aed_read, mixer_aed_enable_multiband_DRC), - - SOC_SINGLE_EXT("AED Full-band DRC enable", - AED_DRC_CNTL, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_fullband_DRC), + mixer_aed_read, mixer_aed_write), SND_SOC_BYTES_EXT("AED EQ Parameters", (EQ_FILTER_SIZE_CH * 4), mixer_get_EQ_params, mixer_set_EQ_params), + SOC_SINGLE_EXT("AED Multi-band DRC enable", + AED_MDRC_CNTL, 8, 0x1, 0, + mixer_aed_read, mixer_aed_write), + + SND_SOC_BYTES_EXT("AED Crossover Filter Parameters", + (CROSSOVER_FILTER_SIZE * 4), + mixer_get_crossover_params, + mixer_set_crossover_params), + SND_SOC_BYTES_EXT("AED Multi-band DRC Parameters", - AED_MULTIBAND_DRC_LENGTH, + (AED_MULTIBAND_DRC_SIZE * 4), mixer_get_multiband_DRC_params, mixer_set_multiband_DRC_params), + SOC_SINGLE_EXT("AED Full-band DRC enable", + AED_DRC_CNTL, 0, 0x1, 0, + mixer_aed_read, mixer_aed_write), + SND_SOC_BYTES_EXT("AED Full-band DRC Parameters", - AED_FULLBAND_DRC_LENGTH, + AED_FULLBAND_DRC_BYTES, mixer_get_fullband_DRC_params, mixer_set_fullband_DRC_params), @@ -524,15 +576,6 @@ int card_add_effect_v2_kcontrols(struct snd_soc_card *card) return 0; } -#if 0 -static const struct snd_soc_component_driver effect_component_drv = { - .name = DRV_NAME, - - .controls = snd_effect_controls, - .num_controls = ARRAY_SIZE(snd_effect_controls), -}; -#endif - static struct effect_chipinfo tl1_effect_chipinfo = { .v2 = true, }; @@ -553,20 +596,6 @@ static const struct of_device_id effect_device_id[] = { }; MODULE_DEVICE_TABLE(of, effect_device_id); -static void aed_set_filter_data(void) -{ - int *p; - - /* set default filter param*/ - p = &DC_CUT_COEFF[0]; - aed_set_ram_coeff(DC_CUT_FILTER_RAM_ADD, DC_CUT_FILTER_SIZE, p); - p = &EQ_COEFF[0]; - aed_set_ram_coeff(EQ_FILTER_RAM_ADD, EQ_FILTER_SIZE, p); - p = &CROSSOVER_COEFF[0]; - aed_set_ram_coeff(CROSSOVER_FILTER_RAM_ADD, CROSSOVER_FILTER_SIZE, p); - -} - static int effect_platform_probe(struct platform_device *pdev) { struct audioeffect *p_effect; @@ -682,6 +711,12 @@ static int effect_platform_probe(struct platform_device *pdev) aed_eq_taps(EQ_BAND); /*set default filter param*/ aed_set_filter_data(); + /*set multi-band drc param*/ + aed_set_multiband_drc_param(); + /*set multi/full-band drc data*/ + aed_set_drc_data(); + /*set full-band drc param, enable 2 band*/ + aed_set_fullband_drc_param(2); /*set EQ/DRC module enable*/ aml_set_aed(1, p_effect->effect_module); From 8aa35da1e33883806d16eef9c0df9422ff3560fd Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Fri, 25 Jan 2019 22:55:49 +0800 Subject: [PATCH 0517/1060] audio: auge: transfer audio data to wake word algorithm [1/3] PD#TV-3389 Problem: add vad wake engine in kernel Solution: transfer audio data to wake engine Verify: x301 Change-Id: I7f44d0141141775bb40f01dbc344a295a72c9d87 Signed-off-by: Xing Wang Conflicts: MAINTAINERS --- MAINTAINERS | 8 + arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 2 +- include/linux/amlogic/vad_api.h | 24 ++ sound/soc/amlogic/auge/vad.c | 354 ++++++++++++++++-- 4 files changed, 347 insertions(+), 41 deletions(-) create mode 100644 include/linux/amlogic/vad_api.h diff --git a/MAINTAINERS b/MAINTAINERS index 56602280b8ba..57ea7d1bdf28 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14785,6 +14785,13 @@ F: arch/arm/boot/dts/amlogic/mesong12b.dtsi F: arch/arm64/boot/dts/amlogic/g12b*_a.dts F: arch/arm64/boot/dts/amlogic/mesong12b.dtsi +AMLOGIC MESONAXG SBR DTS +M: Bing Jiang +F: arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts +F: arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts +F: sound/soc/codecs/amlogic/tas5782m.c +F: sound/soc/codecs/amlogic/tas5782m.h + AMLOGIC SM1 DTS M: Zhiqiang Liang F: arch/arm64/boot/dts/amlogic/mesongsm1.dtsi @@ -14806,6 +14813,7 @@ M: shaochan.liu F: arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi F: arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi + AMLOGIC TL1 VAD M: Wenbiao Zhang F: include/linux/amlogic/vad_api.h diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index c898729d6000..b2d1ab52a4ee 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1213,7 +1213,7 @@ * 0: in user space * 1: in kernel space */ - level = <0>; + level = <1>; status = "disabled"; }; diff --git a/include/linux/amlogic/vad_api.h b/include/linux/amlogic/vad_api.h new file mode 100644 index 000000000000..2abd5ae84487 --- /dev/null +++ b/include/linux/amlogic/vad_api.h @@ -0,0 +1,24 @@ +/* + * include/linux/amlogic/vad_api.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __VAD_API_H__ +#define __VAD_API_H__ + +extern int register_vad_callback(int (*callback)(char *, int, int, int, int)); +extern void unregister_vad_callback(void); + +#endif /* __VAD_API_H__ */ diff --git a/sound/soc/amlogic/auge/vad.c b/sound/soc/amlogic/auge/vad.c index 6738fdf63b97..8a260bbb7b5d 100644 --- a/sound/soc/amlogic/auge/vad.c +++ b/sound/soc/amlogic/auge/vad.c @@ -32,10 +32,17 @@ #include #include +#include +#include +#include + #include #include #include +#include +#include + #include "vad_hw_coeff.c" #include "vad_hw.h" #include "vad.h" @@ -44,6 +51,12 @@ #define DMA_BUFFER_BYTES_MAX (2 * 1024 * 1024) + +#define VAD_READ_FRAME_COUNT (1024 / 2) + +/*#define __VAD_DUMP_DATA__*/ +#define VAD_DUMP_FILE_NAME "/mnt/vaddump.pcm" + enum vad_level { LEVEL_USER, LEVEL_KERNEL, @@ -52,6 +65,7 @@ enum vad_level { struct vad { struct aml_audio_controller *actrl; struct device *dev; + struct input_dev *input_device; struct clk *gate; struct clk *pll; @@ -59,13 +73,13 @@ struct vad { struct toddr *tddr; - struct tasklet_struct tasklet; + char *buf; + struct task_struct *thread; struct snd_dma_buffer dma_buffer; unsigned int start_last; unsigned int end_last; unsigned int addr; - int switch_buffer; /* vad flag interrupt */ @@ -92,6 +106,15 @@ struct vad { * 0: check hot word in user space */ enum vad_level level; + + int (*callback)(char *buf, int frames, int rate, + int channels, int bitdepth); + +#ifdef __VAD_DUMP_DATA__ + struct file *fp; + mm_segment_t fs; + loff_t pos; +#endif }; static struct vad *s_vad; @@ -110,6 +133,34 @@ static struct vad *get_vad(void) return p_vad; } +static void vad_key_report(void) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad) + return; + pr_info("%s\n", __func__); + + input_event(p_vad->input_device, EV_KEY, KEY_POWER, 1); + input_sync(p_vad->input_device); + input_event(p_vad->input_device, EV_KEY, KEY_POWER, 0); + input_sync(p_vad->input_device); +} + +static void vad_input_device_init(struct vad *pvad) +{ + pvad->input_device->name = "vad_keypad"; + pvad->input_device->phys = "vad_keypad/input3"; + pvad->input_device->dev.parent = pvad->dev; + pvad->input_device->id.bustype = BUS_ISA; + pvad->input_device->id.vendor = 0x0001; + pvad->input_device->id.product = 0x0001; + pvad->input_device->id.version = 0x0100; + pvad->input_device->evbit[0] = BIT_MASK(EV_KEY); + pvad->input_device->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + set_bit(KEY_POWER, pvad->input_device->keybit); +} + static bool vad_is_enable(void) { struct vad *p_vad = get_vad(); @@ -156,46 +207,200 @@ bool vad_pdm_is_running(void) return false; } -static void vad_notify_user_space(struct device *dev) +static void vad_notify_user_space(struct vad *p_vad) { pr_info("Notify to wake up user space\n"); - pm_wakeup_event(dev, 2000); + pm_wakeup_event(p_vad->dev, 2000); + p_vad->addr = 0; + vad_key_report(); } -static int vad_engine_check(void) +/* For test */ +static int vad_in_kernel_test; +static int vad_wakeup_count; + +int register_vad_callback(int (*callback)(char *, int, int, int, int)) { - return 1; + struct vad *p_vad = get_vad(); + + if (!p_vad) + return -1; + + p_vad->callback = callback; + return 0; +} +EXPORT_SYMBOL(register_vad_callback); + +void unregister_vad_callback(void) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad) + return; + + p_vad->callback = NULL; +} +EXPORT_SYMBOL(unregister_vad_callback); + +/* transfer audio data to algorithm + * 0: no wake word found + * 1: contained wake word, should wake up system + */ +static int vad_transfer_data_to_algorithm( + struct vad *p_vad, char *buf, int frames, + int rate, int channels, int bitdepth) +{ + int ret = 0; + /* TODO: for test */ + if (vad_in_kernel_test) { + + if (vad_wakeup_count < 50) + return 0; + + vad_wakeup_count = 0; + return 1; + } + + /* Do check by algorithm */ + if (p_vad->callback != NULL) + ret = p_vad->callback(buf, frames, rate, channels, bitdepth); + + return ret; } /* Check buffer in kernel for VAD */ -static void vad_transfer_buffer_output(struct vad *p_vad) +static int vad_engine_check(struct vad *p_vad) { + unsigned char *hwbuf; + int bytes, read_bytes; + int start, end, size, last_addr, curr_addr; + int chnum, bytes_per_sample; + int frame_count = VAD_READ_FRAME_COUNT; - for (;;) { - if (vad_engine_check()) { - vad_notify_user_space(p_vad->dev); - break; + if (!p_vad->tddr || !p_vad->tddr->actrl || + !p_vad->tddr->in_use) + return 0; + + hwbuf = p_vad->dma_buffer.area; + size = p_vad->dma_buffer.bytes - 8; + start = p_vad->dma_buffer.addr; + end = start + size; + last_addr = p_vad->addr; + curr_addr = aml_toddr_get_position(p_vad->tddr); + + if (curr_addr < start || curr_addr > end || + last_addr < start || last_addr > end) { + pr_info("%s line:%d, start:%x,end:%x, addr:%x, curr_addr=%x\n", + __func__, __LINE__, + start, + end, + p_vad->addr, + curr_addr); + p_vad->addr = curr_addr; + return 0; + } + + bytes = (curr_addr - last_addr + size) % size; + chnum = p_vad->tddr->channels; + /* bytes for each sample */ + bytes_per_sample = p_vad->tddr->bitdepth >> 3; + + read_bytes = frame_count * chnum * bytes_per_sample; + if (bytes < read_bytes) { + pr_debug("%s line:%d, %d bytes, need more data\n", + __func__, __LINE__, bytes); + return 0; + } + + if (!p_vad->buf) { + p_vad->buf = kzalloc(read_bytes, GFP_KERNEL); + if (!p_vad->buf) { + pr_err("%s failed to allocate buffer for vad\n", + __func__); + return -ENOMEM; } } + memset(p_vad->buf, 0x0, read_bytes); + + pr_debug("start:%x,end:%x, curr_addr:%x, last_addr:%x, offset:%d, read_bytes:%d\n", + start, + end, + curr_addr, + last_addr, + bytes, + read_bytes); + + + if (last_addr + read_bytes <= end) { + memcpy(p_vad->buf, + hwbuf + last_addr - start, + read_bytes); + p_vad->addr = last_addr + read_bytes; + } else { + int tmp_bytes = end - last_addr; + + memcpy(p_vad->buf, + hwbuf + last_addr - start, + tmp_bytes); + memcpy(p_vad->buf + tmp_bytes, + hwbuf, + read_bytes - tmp_bytes); + p_vad->addr = start + read_bytes - tmp_bytes; + } + +#ifdef __VAD_DUMP_DATA__ + vfs_write(p_vad->fp, p_vad->buf, read_bytes, &p_vad->pos); +#endif + + return vad_transfer_data_to_algorithm(p_vad, + p_vad->buf, frame_count, + p_vad->tddr->rate, + p_vad->tddr->channels, + p_vad->tddr->bitdepth); } -static void vad_tasklet(unsigned long data) +static int vad_freeze_thread(void *data) { - struct vad *p_vad = (struct vad *)data; + struct vad *p_vad = data; - vad_transfer_buffer_output(p_vad); + if (!p_vad) + return 0; + + current->flags |= PF_NOFREEZE; + + for (;;) { + msleep_interruptible(10); + if (kthread_should_stop()) { + pr_info("%s line:%d\n", __func__, __LINE__); + + break; + } + + if (!p_vad || !p_vad->en || !p_vad->callback || + !p_vad->tddr || !p_vad->switch_buffer) { + msleep_interruptible(10); + continue; + } + + if (vad_engine_check(p_vad) > 0) + vad_notify_user_space(p_vad); + } + + dev_info(p_vad->dev, "vad: freeze thread exit\n"); + return 0; } + static irqreturn_t vad_wakeup_isr(int irq, void *data) { struct vad *p_vad = (struct vad *)data; - pr_info("%s\n", __func__); - - if (p_vad->level == LEVEL_KERNEL) - tasklet_schedule(&p_vad->tasklet); - + if (vad_in_kernel_test) { + pr_info("%s vad_wakeup_count:%d\n", __func__, vad_wakeup_count); + if ((p_vad->level == LEVEL_KERNEL) && p_vad->switch_buffer) + vad_wakeup_count++; + } return IRQ_HANDLED; } @@ -253,8 +458,33 @@ static int vad_init(struct vad *p_vad) if (p_vad->level == LEVEL_KERNEL) { flag = IRQF_SHARED | IRQF_NO_SUSPEND; - tasklet_init(&p_vad->tasklet, vad_tasklet, - (unsigned long)p_vad); + /* Start Micro/Audio Dock firmware loader thread */ + if (!p_vad->thread) { + p_vad->thread = + kthread_create(vad_freeze_thread, p_vad, + "vad_freeze_thread"); + if (IS_ERR(p_vad->thread)) { + int err = PTR_ERR(p_vad->thread); + + p_vad->thread = NULL; + dev_info(p_vad->dev, + "vad freeze: Creating thread failed\n"); + return err; + } + wake_up_process(p_vad->thread); + vad_wakeup_count = 0; + } + +#ifdef __VAD_DUMP_DATA__ + p_vad->fp = filp_open(VAD_DUMP_FILE_NAME, O_RDWR | O_CREAT, 0666); + if (IS_ERR(p_vad->fp)) { + pr_err("create file %s error/n", VAD_DUMP_FILE_NAME); + return -1; + } + p_vad->fs = get_fs(); + p_vad->pos = 0; + set_fs(KERNEL_DS); +#endif } else if (p_vad->level == LEVEL_USER) flag = IRQF_SHARED; @@ -285,8 +515,20 @@ static int vad_init(struct vad *p_vad) static void vad_deinit(struct vad *p_vad) { - if (p_vad->level == LEVEL_KERNEL) - tasklet_kill(&p_vad->tasklet); + if (p_vad->level == LEVEL_KERNEL) { +#ifdef __VAD_DUMP_DATA__ + if (p_vad->fp) { + set_fs(p_vad->fs); + filp_close(p_vad->fp, NULL); + } +#endif + if (p_vad->thread) { + kthread_stop(p_vad->thread); + p_vad->thread = NULL; + } + kfree(p_vad->buf); + p_vad->buf = NULL; + } /* free irq */ free_irq(p_vad->irq_wakeup, p_vad); @@ -302,13 +544,16 @@ static void vad_deinit(struct vad *p_vad) void vad_update_buffer(int isvad) { struct vad *p_vad = get_vad(); - unsigned int start, end, addr; + unsigned int start, end; unsigned int rd_th; - if (!p_vad || !p_vad->en || !p_vad->tddr) + if (!p_vad || !p_vad->en || !p_vad->tddr || + !p_vad->tddr->in_use || !p_vad->tddr->actrl) return; - addr = aml_toddr_get_position(p_vad->tddr); + if (p_vad->switch_buffer == isvad) + return; + p_vad->switch_buffer = isvad; if (isvad) { /* switch to vad buffer */ struct toddr *tddr = p_vad->tddr; @@ -319,34 +564,27 @@ void vad_update_buffer(int isvad) rd_th = 0x100; pr_debug("Switch to VAD buffer\n"); - pr_debug("\t ASAL start:%d, end:%d, bytes:%d, current:%d\n", + pr_debug("\t ASAL start:%x, end:%x, bytes:%d\n", tddr->start_addr, tddr->end_addr, - tddr->end_addr - tddr->start_addr, addr); + tddr->end_addr - tddr->start_addr); start = p_vad->dma_buffer.addr; end = start + p_vad->dma_buffer.bytes - 8; - pr_debug("\t VAD start:%d, end:%d, bytes:%d\n", + pr_debug("\t VAD start:%x, end:%x, bytes:%d\n", start, end, end - start); } else { pr_debug("Switch to ALSA buffer\n"); - - //addr = aml_toddr_get_addr(p_vad->tddr, VAD_WAKEUP_ADDR); - addr = aml_toddr_get_position(p_vad->tddr); - start = p_vad->start_last; end = p_vad->end_last; - rd_th = 0x40; - vad_set_trunk_data_readable(true); } - - p_vad->addr = addr; aml_toddr_set_buf(p_vad->tddr, start, end); aml_toddr_force_finish(p_vad->tddr); aml_toddr_update_fifos_rd_th(p_vad->tddr, rd_th); + p_vad->addr = 0; } int vad_transfer_chunk_data(unsigned long data, int frames) @@ -483,6 +721,9 @@ static int vad_set_enable_enum( return 0; } + if (p_vad->en == ucontrol->value.integer.value[0]) + return 0; + p_vad->en = ucontrol->value.integer.value[0]; if (p_vad->en) { @@ -576,14 +817,31 @@ static int vad_set_switch_enum( return 0; } - p_vad->switch_buffer = ucontrol->value.integer.value[0]; - if (p_vad->en) - vad_update_buffer(p_vad->switch_buffer); + vad_update_buffer(ucontrol->value.integer.value[0]); return 0; } +static int vad_test_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = vad_in_kernel_test; + + return 0; +} + +static int vad_test_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + vad_in_kernel_test = ucontrol->value.integer.value[0]; + + return 0; +} + + static const struct snd_kcontrol_new vad_controls[] = { SOC_SINGLE_BOOL_EXT("VAD enable", 0, @@ -600,6 +858,10 @@ static const struct snd_kcontrol_new vad_controls[] = { vad_get_switch_enum, vad_set_switch_enum), + SOC_SINGLE_BOOL_EXT("VAD Test", + 0, + vad_test_get_enum, + vad_test_set_enum), }; int card_add_vad_kcontrols(struct snd_soc_card *card) @@ -722,6 +984,18 @@ static int vad_platform_probe(struct platform_device *pdev) p_vad->src, p_vad->level); + p_vad->input_device = input_allocate_device(); + if (!p_vad->input_device) { + kfree(p_vad); + return -ENOMEM; + } + vad_input_device_init(p_vad); + if (input_register_device(p_vad->input_device)) { + input_free_device(p_vad->input_device); + kfree(p_vad); + return -EINVAL; + } + s_vad = p_vad; device_init_wakeup(dev, 1); From b93b3cdfb8d8b19d5dc1a8d74e1b3ef3085df059 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Mon, 25 Mar 2019 19:53:30 +0800 Subject: [PATCH 0518/1060] audio: add tdm and spdif clk fine tuning interface [1/1] PD#SWPL-5518 Problem: In DTV passthrough, the output clk drifts from input Solution: add clk fine tuning interface Verify: verify by X301 Change-Id: I969d3eb865fb1aba90f155965548454cc3040c99 Signed-off-by: Zhe Wang Conflicts: sound/soc/amlogic/auge/tdm.c --- sound/soc/amlogic/auge/audio_utils.c | 5 +- sound/soc/amlogic/auge/spdif.c | 51 ++++++++++++++++-- sound/soc/amlogic/auge/tdm.c | 81 ++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 5 deletions(-) diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 16943bc3b841..ac18fb09f4c3 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -165,6 +165,7 @@ static int loopback_tdminlb_set_enum( return 0; } +#if 0 static int snd_int_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -279,6 +280,7 @@ static int snd_byte_set(struct snd_kcontrol *kcontrol, return 0; } +#endif #define SND_BYTE(xname, type, func, xshift, xmask) \ { \ @@ -742,7 +744,7 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { loopback_tdminlb_enum, loopback_tdminlb_get_enum, loopback_tdminlb_set_enum), - +#if 0 /*TDMIN_A swap*/ SND_SWAP("TDMIN_A Ch0 Swap", TDMIN_A, in_swap_channel_enum, 0, 0x7), SND_SWAP("TDMIN_A Ch1 Swap", TDMIN_A, in_swap_channel_enum, 4, 0x7), @@ -983,6 +985,7 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { TDMOUT_C, lane2_mixer_enum, 22, 0x1), SND_MIX("TDMOUT_C Lane3 Mixer Channel", TDMOUT_C, lane3_mixer_enum, 23, 0x1), +#endif /* SPDIFIN Channel Status */ SPDIFIN_CHSTATUS("SPDIFIN Channel Status", diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 708d068b366f..b2f646f6dc27 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -51,6 +51,9 @@ /*#define __SPDIFIN_AUDIO_TYPE_HW__*/ +static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir); + struct spdif_chipinfo { enum SPDIF_ID id; @@ -357,16 +360,49 @@ int spdifin_source_set_enum( return 0; } +static int spdif_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = + clk_get_rate(p_spdif->clk_spdifout); + return 0; +} + +static int spdif_clk_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai); + + int sysclk = p_spdif->sysclk_freq; + int value = ucontrol->value.enumerated.item[0]; + + if (value > 2000000 || value < 0) { + pr_err("Fine spdif sysclk setting range(0~2000000), %d\n", + value); + return 0; + } + sysclk += (value - 1000000); + + aml_dai_set_spdif_sysclk(cpu_dai, 0, sysclk, 0); + + return 0; +} + static const struct snd_kcontrol_new snd_spdif_controls[] = { - SOC_ENUM_EXT("SPDIFIN audio samplerate", spdifin_sample_rate_enum, + SOC_ENUM_EXT("SPDIFIN audio samplerate", + spdifin_sample_rate_enum, spdifin_samplerate_get_enum, NULL), SOC_ENUM_EXT("SPDIFIN Audio Type", - spdif_audio_type_enum, - spdifin_audio_type_get_enum, - NULL), + spdif_audio_type_enum, + spdifin_audio_type_get_enum, + NULL), SOC_ENUM_EXT("Audio spdif format", spdif_format_enum, @@ -376,15 +412,22 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = { SOC_SINGLE_BOOL_EXT("Audio spdif mute", 0, aml_audio_get_spdif_mute, aml_audio_set_spdif_mute), + SOC_ENUM_EXT("Audio spdifin source", spdifin_src_enum, spdifin_source_get_enum, spdifin_source_set_enum), + #ifdef CONFIG_AMLOGIC_HDMITX SOC_SINGLE_BOOL_EXT("Audio hdmi-out mute", 0, aml_get_hdmi_out_audio, aml_set_hdmi_out_audio), #endif + + SOC_SINGLE_EXT("SPDIF CLK Fine Setting", + 0, 0, 2000000, 0, + spdif_clk_get, + spdif_clk_set), }; static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif) diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 3b368737368b..2b21e3bf03bf 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -53,6 +53,9 @@ #define TDM_C 2 #define LANE_MAX 4 +static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir); + static void dump_pcm_setting(struct pcm_setting *setting) { if (setting == NULL) @@ -153,6 +156,84 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { .channels_max = 32, }; +static int tdm_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = clk_get_rate(p_tdm->mclk); + return 0; +} + +static int tdm_clk_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + int mclk_rate = p_tdm->last_mclk_freq; + int value = ucontrol->value.enumerated.item[0]; + + if (value > 2000000 || value < 0) { + pr_err("Fine tdm clk setting range (0~2000000), %d\n", value); + return 0; + } + mclk_rate += (value - 1000000); + + aml_dai_set_tdm_sysclk(cpu_dai, 0, mclk_rate, 0); + + return 0; +} + +static int tdmin_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int clk; + int value; + + clk = meson_clk_measure(70); + if (clk >= 11000000) + value = 3; + else if (clk >= 6000000) + value = 2; + else if (clk >= 2000000) + value = 1; + else + value = 0; + + + ucontrol->value.integer.value[0] = value; + + return 0; +} + +/* current sample mode and its sample rate */ +static const char *const i2sin_clk[] = { + "0", + "3000000", + "6000000", + "12000000" +}; + +static const struct soc_enum i2sin_clk_enum[] = { + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(i2sin_clk), + i2sin_clk), +}; + + + +static const struct snd_kcontrol_new snd_tdm_controls[] = { + SOC_ENUM_EXT("I2SIn CLK", i2sin_clk_enum, + tdmin_clk_get, + NULL), + + SOC_SINGLE_EXT("TDM MCLK Fine Setting", + 0, 0, 2000000, 0, + tdm_clk_get, + tdm_clk_set), +}; + static irqreturn_t aml_tdm_ddr_isr(int irq, void *devid) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)devid; From 46dd166a016febc68135646b58e0919d3a53ef10 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Wed, 27 Mar 2019 16:37:00 +0800 Subject: [PATCH 0519/1060] audio: add HW resample for HDMIRX [1/1] PD#SWPL-6118 Problem: No resample will cause mismatch between input and output if they are not at same samplerate. Solution: Add resample for hdmirx case Verify: Local tested. Change-Id: I298e401578bf49484d6b75fd736d2a74c38508e4 Signed-off-by: Shuai Li Conflicts: sound/soc/amlogic/auge/ddr_mngr.c sound/soc/amlogic/auge/ddr_mngr.h --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 3 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 3 +- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 3 +- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 3 +- sound/soc/amlogic/auge/ddr_mngr.c | 52 +++++--- sound/soc/amlogic/auge/ddr_mngr.h | 46 ++++--- sound/soc/amlogic/auge/extn.c | 7 +- sound/soc/amlogic/auge/resample.c | 123 +++++++++++++----- sound/soc/amlogic/auge/resample.h | 8 +- sound/soc/amlogic/auge/resample_hw.c | 31 +++-- sound/soc/amlogic/auge/resample_hw.h | 32 +++-- sound/soc/amlogic/auge/spdif.c | 10 +- 12 files changed, 213 insertions(+), 108 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 1859a11c5a24..3acfad3b66b6 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1438,8 +1438,9 @@ * NONE, * TDMIN_LB, 6 * LOOPBACK, 7 + * FRHDMIRX, 8 */ - resample_module = <3>; + resample_module = <8>; status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index b2d1ab52a4ee..cebdf098dc9a 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1153,8 +1153,9 @@ * NONE, * TDMIN_LB, 6 * LOOPBACK, 7 + * FRHDMIRX, 8 */ - resample_module = <3>; + resample_module = <8>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index a7c8832248d4..e05791af1e8d 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1521,8 +1521,9 @@ * NONE, * TDMIN_LB, 6 * LOOPBACK, 7 + * FRHDMIRX, 8 */ - resample_module = <3>; + resample_module = <8>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index d265738263f0..08e7ebb2be8a 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -1520,8 +1520,9 @@ * NONE, * TDMIN_LB, 6 * LOOPBACK, 7 + * FRHDMIRX, 8 */ - resample_module = <3>; + resample_module = <8>; status = "okay"; }; diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index cba4170542bc..4ff9c1ea0bd2 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -394,10 +394,10 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh) if (to->chipinfo && to->chipinfo->src_sel_ctrl) { mask = 0xfff << 12 | 0xf << 8; - val = (thresh-1) << 12 | 2 << 8; + val = (thresh-2) << 12 | 2 << 8; } else { mask = 0xff << 16 | 0xf << 8; - val = (thresh-1) << 16 | 2 << 8; + val = (thresh-2) << 16 | 2 << 8; } aml_audiobus_update_bits(actrl, reg, mask, val); @@ -485,28 +485,29 @@ void aml_toddr_write(struct toddr *to, unsigned int val) aml_audiobus_write(actrl, reg, val); } - -void aml_toddr_set_resample(struct toddr *to, bool enable) +/* not for tl1 */ +static void aml_toddr_set_resample(struct toddr *to, bool enable) { struct aml_audio_controller *actrl = to->actrl; unsigned int reg_base = to->reg_base; unsigned int reg; reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30); + aml_audiobus_update_bits(actrl, reg, 1<<30, !!enable<<30); } - -void aml_toddr_set_resample_ab(struct toddr *to, int asrc_src_sel, bool enable) +/* tl1 after */ +static void aml_toddr_set_resample_ab(struct toddr *to, + enum resample_idx index, bool enable) { struct aml_audio_controller *actrl = to->actrl; unsigned int reg_base = to->reg_base; unsigned int reg; reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); - if (asrc_src_sel == 0) - aml_audiobus_update_bits(actrl, reg, 1 << 27, enable << 27); - else - aml_audiobus_update_bits(actrl, reg, 1 << 26, enable << 26); + if (index == RESAMPLE_A) + aml_audiobus_update_bits(actrl, reg, 1 << 27, !!enable << 27); + else if (index == RESAMPLE_B) + aml_audiobus_update_bits(actrl, reg, 1 << 26, !!enable << 26); } static void aml_resample_enable( @@ -514,12 +515,15 @@ static void aml_resample_enable( struct toddr_attach *p_attach_resample, bool enable) { - if (!to) + if (!to || !p_attach_resample) { + pr_err("%s(), NULL pointer.", __func__); return; + } if (to->chipinfo && to->chipinfo->asrc_src_sel_ctrl) { /* fix asrc_src_sel */ + /* switch (p_attach_resample->attach_module) { case LOOPBACK_A: to->asrc_src_sel = ASRC_LOOPBACK_A; @@ -531,21 +535,24 @@ static void aml_resample_enable( to->asrc_src_sel = to->fifo_id; break; } + */ + to->asrc_src_sel = p_attach_resample->attach_module; } pr_info("toddr %d selects data to %s resample_%c for module:%s\n", to->fifo_id, enable ? "enable" : "disable", - (p_attach_resample->id == 0) ? 'a' : 'b', + (p_attach_resample->id == RESAMPLE_A) ? 'a' : 'b', toddr_src_get_str(p_attach_resample->attach_module) ); if (enable) { int bitwidth = to->bitdepth; /* channels and bit depth for resample */ + if (to->chipinfo && to->chipinfo->asrc_only_left_j - && (to->src == SPDIFIN) + /*&& (to->src == SPDIFIN)*/ && (bitwidth == 32)) { struct aml_audio_controller *actrl = to->actrl; unsigned int reg_base = to->reg_base; @@ -589,13 +596,14 @@ static void aml_resample_enable( aml_toddr_set_resample(to, enable); } -void aml_set_resample(int id, bool enable, int resample_module) +void aml_set_resample(enum resample_idx id, + bool enable, enum toddr_src resample_module) { struct toddr_attach *p_attach_resample; struct toddr *to; bool update_running = false; - if (id == 0) + if (id == RESAMPLE_A) p_attach_resample = &attach_resample_a; else p_attach_resample = &attach_resample_b; @@ -1376,13 +1384,13 @@ void frddr_deinit_without_mngr(unsigned int frddr_index) audiobus_write(reg, 0x0); } -static int toddr_src_idx = -1; +static enum toddr_src toddr_src_idx = TODDR_INVAL; static const char *const toddr_src_sel_texts[] = { "TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN", "PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A", "FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB", - "RESERVED", "RESERVED", "RESERVED", "RESERVED", + "EARCRX_DMAC", "RESERVED_0", "RESERVED_1", "RESERVED_2", "VAD" }; @@ -1390,14 +1398,14 @@ static const struct soc_enum toddr_input_source_enum = SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(toddr_src_sel_texts), toddr_src_sel_texts); -int toddr_src_get(void) +enum toddr_src toddr_src_get(void) { return toddr_src_idx; } -const char *toddr_src_get_str(int idx) +const char *toddr_src_get_str(enum toddr_src idx) { - if (idx < 0 || idx > 15) + if (idx < TDMIN_A || idx > VAD) return NULL; return toddr_src_sel_texts[idx]; @@ -1415,6 +1423,8 @@ static int toddr_src_enum_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { toddr_src_idx = ucontrol->value.enumerated.item[0]; + /* also update to resample src */ + //set_resample_source(toddr_src_idx); return 0; } diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index 203c0b4cfd07..4d87dce2ab0f 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -42,18 +42,29 @@ enum ddr_types { * from tl1, add new source FRATV, FRHDMIRX, LOOPBACK_B, SPDIFIN_LB, VAD */ enum toddr_src { - TDMIN_A, - TDMIN_B, - TDMIN_C, - SPDIFIN, - PDMIN, - FRATV, /* NONE for axg, g12a, g12b */ - TDMIN_LB, - LOOPBACK_A, - FRHDMIRX, /* from tl1 chipset*/ - LOOPBACK_B, - SPDIFIN_LB, - VAD, + TODDR_INVAL = -1, + TDMIN_A = 0, + TDMIN_B = 1, + TDMIN_C = 2, + SPDIFIN = 3, + PDMIN = 4, + FRATV = 5, /* NONE for axg, g12a, g12b */ + TDMIN_LB = 6, + LOOPBACK_A = 7, + FRHDMIRX = 8, /* from tl1 chipset*/ + LOOPBACK_B = 9, + SPDIFIN_LB = 10, + EARCRX_DMAC = 11,/* from sm1 chipset */ + RESERVED_0 = 12, + RESERVED_1 = 13, + RESERVED_2 = 14, + VAD = 15, + TODDR_SRC_MAX = 16 +}; + +enum resample_idx { + RESAMPLE_A, + RESAMPLE_B }; enum resample_src { @@ -176,7 +187,7 @@ struct toddr { enum toddr_src src; unsigned int fifo_id; - unsigned int asrc_src_sel; + enum toddr_src asrc_src_sel; int is_lb; /* check whether for loopback */ int irq; @@ -193,7 +204,7 @@ enum status { struct toddr_attach { bool enable; - int id; + enum resample_idx id; int status; /* which module should be attached, * check which toddr in use should be attached @@ -258,7 +269,8 @@ unsigned int aml_toddr_read(struct toddr *to); void aml_toddr_write(struct toddr *to, unsigned int val); /* resample */ -void aml_set_resample(int id, bool enable, int resample_module); +void aml_set_resample(enum resample_idx id, + bool enable, enum toddr_src resample_module); /* power detect */ void aml_pwrdet_enable(bool enable, int pwrdet_module); /* Voice Activity Detection */ @@ -296,8 +308,8 @@ void aml_set_aed(bool enable, int aed_module); void frddr_init_without_mngr(unsigned int frddr_index, unsigned int src0_sel); void frddr_deinit_without_mngr(unsigned int frddr_index); -int toddr_src_get(void); -const char *toddr_src_get_str(int idx); +enum toddr_src toddr_src_get(void); +const char *toddr_src_get_str(enum toddr_src idx); int frddr_src_get(void); const char *frddr_src_get_str(int idx); diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index 712c6aa76acf..277761265e07 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -37,6 +37,7 @@ #include "ddr_mngr.h" #include "audio_utils.h" #include "frhdmirx_hw.h" +#include "resample.h" #include @@ -371,6 +372,7 @@ static int extn_dai_startup( struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { + resample_set_inner_rate(RESAMPLE_A); return 0; } @@ -378,6 +380,7 @@ static void extn_dai_shutdown( struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { + //resample_set(RESAMPLE_A, RATE_OFF); } static int extn_dai_prepare( @@ -401,7 +404,7 @@ static int extn_dai_prepare( } else { struct toddr *to = p_extn->tddr; unsigned int msb = 0, lsb = 0, toddr_type = 0; - unsigned int src = toddr_src_get(); + enum toddr_src src = toddr_src_get(); struct toddr_fmt fmt; if (bit_depth == 24) @@ -472,7 +475,7 @@ static int extn_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { struct extn *p_extn = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int src = toddr_src_get(); + enum toddr_src src = toddr_src_get(); switch (cmd) { case SNDRV_PCM_TRIGGER_START: diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 7c56eb1cc200..aa096072e838 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -27,8 +27,6 @@ #include #include "resample.h" -#include "resample_hw.h" -#include "ddr_mngr.h" #include "regs.h" #include "iomap.h" @@ -38,12 +36,12 @@ /*#define __PTM_RESAMPLE_CLK__*/ -#define RESAMPLE_A 0 -#define RESAMPLE_B 1 +//#define RESAMPLE_A 0 +//#define RESAMPLE_B 1 struct resample_chipinfo { int num; /* support resample a/b */ - int id; + enum resample_idx id; bool dividor_fn; }; @@ -60,15 +58,15 @@ struct audioresample { struct resample_chipinfo *chipinfo; - int id; + enum resample_idx id; /*which module should be resampled */ - int resample_module; + enum toddr_src resample_module; /* resample to the rate */ int out_rate; /* sync with auge_resample_texts */ - int asrc_rate_idx; + enum samplerate_index asrc_rate_idx; bool enable; }; @@ -77,11 +75,11 @@ struct audioresample *s_resample_a; struct audioresample *s_resample_b; -static struct audioresample *get_audioresample(int id) +static struct audioresample *get_audioresample(enum resample_idx id) { struct audioresample *p_resample; - p_resample = ((id == 0) ? s_resample_a : s_resample_b); + p_resample = ((id == RESAMPLE_A) ? s_resample_a : s_resample_b); if (!p_resample) { pr_debug("Not init audio resample\n"); @@ -93,7 +91,7 @@ static struct audioresample *get_audioresample(int id) int get_resample_module_num(void) { - struct audioresample *p_resample = get_audioresample(0); + struct audioresample *p_resample = get_audioresample(RESAMPLE_A); if (p_resample && p_resample->chipinfo) return p_resample->chipinfo->num; @@ -101,6 +99,32 @@ int get_resample_module_num(void) return 1; } +int set_resample_source(enum resample_idx id, enum toddr_src src) +{ + struct audioresample *p_resample = get_audioresample(id); + (void)p_resample; + (void)src; + //p_resample->resample_module = src; + return 0; +} + +static int set_resample_rate_index( + enum resample_idx id, enum samplerate_index index) +{ + struct audioresample *p_resample = get_audioresample(id); + + p_resample->asrc_rate_idx = index; + return 0; +} + +static enum samplerate_index get_resample_rate_index( + enum resample_idx id) +{ + struct audioresample *p_resample = get_audioresample(id); + + return p_resample->asrc_rate_idx; +} + static int resample_clk_set(struct audioresample *p_resample) { int ret = 0; @@ -126,7 +150,7 @@ static int resample_clk_set(struct audioresample *p_resample) clk_set_rate(p_resample->sclk, 48000 * CLK_RATIO); clk_set_rate(p_resample->clk, 48000 * CLK_RATIO); } - +#if 0 ret = clk_prepare_enable(p_resample->pll); if (ret) { pr_err("Can't enable pll clock: %d\n", ret); @@ -146,6 +170,7 @@ static int resample_clk_set(struct audioresample *p_resample) ret); return -EINVAL; } +#endif pr_info("%s, resample_pll:%lu, sclk:%lu, clk:%lu\n", __func__, @@ -153,9 +178,11 @@ static int resample_clk_set(struct audioresample *p_resample) clk_get_rate(p_resample->sclk), clk_get_rate(p_resample->clk)); } else { +#if 0 clk_disable_unprepare(p_resample->clk); clk_disable_unprepare(p_resample->sclk); clk_disable_unprepare(p_resample->pll); +#endif } return ret; @@ -194,25 +221,25 @@ static const char *const auge_resample_texts[] = { "Enable:192K", }; -static int resample_idx2rate(int index) +static int resample_idx2rate(enum samplerate_index index) { int rate = 0; - if (index == 0) + if (index == RATE_OFF) rate = 0; - else if (index == 1) + else if (index == RATE_32K) rate = 32000; - else if (index == 2) + else if (index == RATE_44K) rate = 44100; - else if (index == 3) + else if (index == RATE_48K) rate = 48000; - else if (index == 4) + else if (index == RATE_88K) rate = 88200; - else if (index == 5) + else if (index == RATE_96K) rate = 96000; - else if (index == 6) + else if (index == RATE_176K) rate = 176400; - else if (index == 7) + else if (index == RATE_192K) rate = 192000; return rate; @@ -238,38 +265,51 @@ static int resample_get_enum( return 0; } -int resample_set(int id, int index) +int resample_set(enum resample_idx id, enum samplerate_index index) { - int resample_rate = resample_idx2rate(index); + int resample_rate = 0; struct audioresample *p_resample = get_audioresample(id); + int ret = 0; + + pr_info("%s resample_%c to %s, last %s\n", + __func__, + (id == RESAMPLE_A) ? 'a' : 'b', + auge_resample_texts[index], + auge_resample_texts[p_resample->asrc_rate_idx]); if (!p_resample) return 0; - if (index == p_resample->asrc_rate_idx) - return 0; + //if (index == p_resample->asrc_rate_idx) + // return 0; p_resample->asrc_rate_idx = index; - pr_info("%s resample_%c %s\n", - __func__, - (id == 0) ? 'a' : 'b', - auge_resample_texts[index]); + resample_rate = resample_idx2rate(index); + ret = audio_resample_set(p_resample, (bool)index, resample_rate); + if (ret) + return ret; - if (audio_resample_set(p_resample, (bool)index, resample_rate)) - return 0; - - if ((index == 0) || (resample_rate == 0)) + if (index == RATE_OFF) resample_disable(p_resample->id); else { resample_init(p_resample->id, resample_rate); - resample_set_hw_param(p_resample->id, index - 1); + resample_set_hw_param(p_resample->id, index); } return 0; } +int resample_set_inner_rate(enum resample_idx id) +{ + enum samplerate_index index = get_resample_rate_index(id); + + pr_debug("%s() index %d\n", __func__, id); + + return resample_set(id, index); +} + static int resample_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -282,7 +322,8 @@ static int resample_set_enum( return 0; } - resample_set(p_resample->id, index); + set_resample_rate_index(p_resample->id, index); + resample_set_inner_rate(p_resample->id); return 0; } @@ -345,6 +386,10 @@ static const char *const auge_resample_module_texts[] = { "FRHDMIRX", /* from tl1 chipset*/ "LOOPBACK_B", "SPDIFIN_LB", + "RESERVED_0", + "RESERVED_1", + "RESERVED_2", + "RESERVED_3", "VAD", }; @@ -388,7 +433,6 @@ static int resample_module_set_enum( return 0; } - static const struct snd_kcontrol_new asrc_a_controls[] = { SOC_ENUM_EXT("Hardware resample enable", auge_resample_enum, @@ -566,6 +610,13 @@ static int resample_platform_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(p_resample->clk); + if (ret) { + pr_err("Can't enable resample_clk clock: %d\n", + ret); + return ret; + } + p_resample->dev = dev; if (p_chipinfo && p_chipinfo->id == 1) diff --git a/sound/soc/amlogic/auge/resample.h b/sound/soc/amlogic/auge/resample.h index a86c8c0de831..1c18d11066d2 100644 --- a/sound/soc/amlogic/auge/resample.h +++ b/sound/soc/amlogic/auge/resample.h @@ -17,10 +17,16 @@ #ifndef __AML_AUDIO_RESAMPLE_H__ #define __AML_AUDIO_RESAMPLE_H__ +#include "resample_hw.h" + extern int card_add_resample_kcontrols(struct snd_soc_card *card); -extern int resample_set(int id, int index); +extern int resample_set(enum resample_idx id, enum samplerate_index index); extern int get_resample_module_num(void); +int set_resample_source(enum resample_idx id, enum toddr_src src); + +int resample_set_inner_rate(enum resample_idx id); + #endif diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index 1722ce8eb82d..03ca3aad115c 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -40,7 +40,7 @@ static u32 resample_coef_parameters_table[7][5] = { {0x00800000, 0x0, 0x0, 0x0, 0x0}, }; -void resample_enable(int id, bool enable) +void resample_enable(enum resample_idx id, bool enable) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; @@ -58,7 +58,7 @@ void resample_enable(int id, bool enable) enable << 28); } -int resample_init(int id, int input_sr) +int resample_init(enum resample_idx id, int input_sr) { u16 Avg_cnt_init = 0; unsigned int clk_rate = 167000000;//clk81; @@ -77,15 +77,15 @@ int resample_init(int id, int input_sr) Avg_cnt_init); audiobus_update_bits(reg, - 0x3 << 26 | 0x3ff << 16 | 0xffff << 0, + 0x3 << 26 | 0x3ff << 16 | 0xffff, 0x0 << 26 | /* method0 */ RESAMPLE_CNT_CONTROL << 16 | - Avg_cnt_init << 0); + Avg_cnt_init); return 0; } -int resample_disable(int id) +int resample_disable(enum resample_idx id) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; @@ -95,15 +95,20 @@ int resample_disable(int id) return 0; } -int resample_set_hw_param(int id, int index) +int resample_set_hw_param(enum resample_idx id, + enum samplerate_index rate_index) { int i, reg, offset; + if (rate_index < RATE_32K) { + pr_info("%s(), inval index %d", __func__, rate_index); + return -EINVAL; + } offset = EE_AUDIO_RESAMPLEB_COEF0 - EE_AUDIO_RESAMPLEA_COEF0; reg = EE_AUDIO_RESAMPLEA_COEF0 + offset * id; for (i = 0; i < 5; i++) { audiobus_write((reg + i), - resample_coef_parameters_table[index][i]); + resample_coef_parameters_table[rate_index - 1][i]); } offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; @@ -113,15 +118,15 @@ int resample_set_hw_param(int id, int index) return 0; } - +/* not avail for tl1 */ void resample_src_select(int src) { audiobus_update_bits(EE_AUDIO_RESAMPLEA_CTRL0, 0x3 << 29, src << 29); } - -void resample_src_select_ab(int id, int src) +/* for tl1 and after */ +void resample_src_select_ab(enum resample_idx id, enum toddr_src src) { int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3; int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id; @@ -131,7 +136,7 @@ void resample_src_select_ab(int id, int src) src << 16); } -void resample_format_set(int id, int ch_num, int bits) +void resample_format_set(enum resample_idx id, int ch_num, int bits) { int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3; int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id; @@ -140,7 +145,7 @@ void resample_format_set(int id, int ch_num, int bits) ch_num << 8 | (bits - 1) << 0); } -int resample_ctrl_read(int id) +int resample_ctrl_read(enum resample_idx id) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; @@ -148,7 +153,7 @@ int resample_ctrl_read(int id) return audiobus_read(reg); } -void resample_ctrl_write(int id, int value) +void resample_ctrl_write(enum resample_idx id, int value) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; diff --git a/sound/soc/amlogic/auge/resample_hw.h b/sound/soc/amlogic/auge/resample_hw.h index 1ec4b16c871a..5d7c3dda2c1c 100644 --- a/sound/soc/amlogic/auge/resample_hw.h +++ b/sound/soc/amlogic/auge/resample_hw.h @@ -17,15 +17,29 @@ #ifndef __AML_AUDIO_RESAMPLE_HW_H__ #define __AML_AUDIO_RESAMPLE_HW_H__ -extern void resample_enable(int id, bool enable); -extern int resample_init(int id, int input_sr); -extern int resample_disable(int id); -extern int resample_set_hw_param(int id, int index); -extern void resample_src_select(int src); -extern void resample_src_select_ab(int id, int src); -extern void resample_format_set(int id, int ch_num, int bits); +#include "ddr_mngr.h" -extern int resample_ctrl_read(int id); -extern void resample_ctrl_write(int id, int value); +enum samplerate_index { + RATE_OFF, + RATE_32K, + RATE_44K, + RATE_48K, + RATE_88K, + RATE_96K, + RATE_176K, + RATE_192K, +}; + +extern void resample_enable(enum resample_idx id, bool enable); +extern int resample_init(enum resample_idx id, int input_sr); +extern int resample_disable(enum resample_idx id); +extern int resample_set_hw_param(enum resample_idx id, + enum samplerate_index rate_index); +extern void resample_src_select(int src); +extern void resample_src_select_ab(enum resample_idx id, enum toddr_src src); +extern void resample_format_set(enum resample_idx id, int ch_num, int bits); + +extern int resample_ctrl_read(enum resample_idx id); +extern void resample_ctrl_write(enum resample_idx id, int value); #endif diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index b2f646f6dc27..647675755c80 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -110,11 +110,11 @@ struct aml_spdif { /* * resample a/b do asrc for spdif in */ - unsigned int asrc_id; + enum resample_idx asrc_id; /* spdif in do asrc for pcm, * if raw data, disable it automatically. */ - unsigned int auto_asrc; + enum samplerate_index auto_asrc; /* check spdifin channel status for pcm or nonpcm */ struct timer_list timer; @@ -479,7 +479,7 @@ static void spdifin_audio_type_work_func(struct work_struct *work) if (val & 0x2) /* nonpcm, resample disable */ - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); else /* pcm, resample which rate ? */ resample_set(p_spdif->asrc_id, p_spdif->auto_asrc); @@ -690,7 +690,7 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) #ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disable, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); #endif #endif } @@ -1115,7 +1115,7 @@ static void aml_dai_spdif_shutdown( #ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disabled, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); #endif clk_disable_unprepare(p_spdif->clk_spdifin); clk_disable_unprepare(p_spdif->fixed_clk); From 80a53edf2488c9225d366db3eefeeac993b53995 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Sat, 30 Mar 2019 14:35:53 +0800 Subject: [PATCH 0520/1060] audio: always on DDR arb [1/1] PD#TV-3452 Problem: Toddr stuck after a long time playback. Solution: For debug usage. Verify: No need. Change-Id: Ibf4446148f5e028040d7d6527c7695f23f964f7c Signed-off-by: Shuai Li Signed-off-by: Zhe Wang --- sound/soc/amlogic/auge/ddr_mngr.c | 70 ++++++++++++++++++++++++------- sound/soc/amlogic/auge/ddr_mngr.h | 3 ++ 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 4ff9c1ea0bd2..2a704a84da09 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -102,8 +102,9 @@ static struct toddr *register_toddr_l(struct device *dev, } /* enable audio ddr arb */ mask_bit = i; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<<31|1<dev = dev; to->actrl = actrl; @@ -142,13 +143,14 @@ static int unregister_toddr_l(struct device *dev, void *data) /* disable audio ddr arb */ mask_bit = i; actrl = to->actrl; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<irq, data); to->dev = NULL; @@ -285,7 +287,7 @@ int aml_toddr_set_intrpt(struct toddr *to, unsigned int intrpt) reg = calc_toddr_address(EE_AUDIO_TODDR_A_INT_ADDR, reg_base); aml_audiobus_write(actrl, reg, intrpt); reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 0xff<<16, 4<<16); + aml_audiobus_update_bits(actrl, reg, 0xff << 16, 0x34 << 16); return 0; } @@ -323,7 +325,7 @@ unsigned int aml_toddr_get_addr(struct toddr *to, enum status_sel sel) /* reset to default, current write addr */ aml_audiobus_update_bits(actrl, reg_sel, 0xf << 8, - 0x0 << 8); + 0x2 << 8); return addr; } @@ -485,6 +487,40 @@ void aml_toddr_write(struct toddr *to, unsigned int val) aml_audiobus_write(actrl, reg, val); } + +unsigned int aml_toddr_read1(struct toddr *to) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + + return aml_audiobus_read(actrl, reg); +} + +void aml_toddr_write1(struct toddr *to, unsigned int val) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + + aml_audiobus_write(actrl, reg, val); +} + +unsigned int aml_toddr_read_status2(struct toddr *to) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_STATUS2, reg_base); + + return aml_audiobus_read(actrl, reg); +} + /* not for tl1 */ static void aml_toddr_set_resample(struct toddr *to, bool enable) { @@ -844,8 +880,9 @@ static struct frddr *register_frddr_l(struct device *dev, /* enable audio ddr arb */ mask_bit = i + 4; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<<31|1<irq, aml_ddr_isr, handler, @@ -885,13 +922,14 @@ static int unregister_frddr_l(struct device *dev, void *data) /* disable audio ddr arb */ mask_bit = i + 4; actrl = from->actrl; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<irq, data); from->dev = NULL; diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index 4d87dce2ab0f..c787662707d0 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -267,6 +267,9 @@ void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt); void aml_toddr_insert_chanum(struct toddr *to); unsigned int aml_toddr_read(struct toddr *to); void aml_toddr_write(struct toddr *to, unsigned int val); +unsigned int aml_toddr_read1(struct toddr *to); +void aml_toddr_write1(struct toddr *to, unsigned int val); +unsigned int aml_toddr_read_status2(struct toddr *to); /* resample */ void aml_set_resample(enum resample_idx id, From 4ccf3d2f04cdd550f37745e43e7deacd12756371 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Fri, 12 Apr 2019 10:51:00 +0800 Subject: [PATCH 0521/1060] audio: fixed kernel panic when resample is disabled [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-7039 Problem: Kernel Panic when resample A is disabled Solution: When resample is disabled,don't init resample Verify: Verified on T962e2_ab311 Change-Id: Id9552ffc6be40f133b828dbded4ad3f15d177ab0 Signed-off-by: Zhe Wang --- sound/soc/amlogic/auge/extn.c | 4 +++- sound/soc/amlogic/auge/resample.c | 2 +- sound/soc/amlogic/auge/resample.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index 277761265e07..78ec04f952bd 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -372,7 +372,9 @@ static int extn_dai_startup( struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - resample_set_inner_rate(RESAMPLE_A); + if (get_audioresample(RESAMPLE_A)) + resample_set_inner_rate(RESAMPLE_A); + return 0; } diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index aa096072e838..8678361c51c5 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -75,7 +75,7 @@ struct audioresample *s_resample_a; struct audioresample *s_resample_b; -static struct audioresample *get_audioresample(enum resample_idx id) +struct audioresample *get_audioresample(enum resample_idx id) { struct audioresample *p_resample; diff --git a/sound/soc/amlogic/auge/resample.h b/sound/soc/amlogic/auge/resample.h index 1c18d11066d2..b82aac34fc82 100644 --- a/sound/soc/amlogic/auge/resample.h +++ b/sound/soc/amlogic/auge/resample.h @@ -29,4 +29,6 @@ int set_resample_source(enum resample_idx id, enum toddr_src src); int resample_set_inner_rate(enum resample_idx id); +struct audioresample *get_audioresample(enum resample_idx id); + #endif From f660ba05d3aba70b90401da4f490e25e90b0ca28 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Thu, 18 Apr 2019 18:15:54 +0800 Subject: [PATCH 0522/1060] audio: enable hw resmaple pause thd [1/1] PD#TV-4638 Problem: Speaker output high frequency howling after change from pattern 615 to pattern 1 on chroma22294. The hw resampler keeps sending noise if it has no input. Solution: Enable the hw resample pause thd by default. Verify: TL1 X301. Change-Id: I076d1b80c6482661fdc3fd5808f1cc231666d07e Signed-off-by: Shuai Li --- sound/soc/amlogic/auge/resample.c | 12 ++++++------ sound/soc/amlogic/auge/resample_hw.c | 11 +++++++++++ sound/soc/amlogic/auge/resample_hw.h | 1 + 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 8678361c51c5..90791ef895f5 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -440,11 +440,11 @@ static const struct snd_kcontrol_new asrc_a_controls[] = { resample_set_enum), SOC_SINGLE_EXT_TLV("Hw resample pause enable", EE_AUDIO_RESAMPLEA_CTRL2, 24, 0x1, 0, - mixer_audiobus_read, mixer_audiobus_write, + mixer_audiobus_read, NULL, NULL), SOC_SINGLE_EXT_TLV("Hw resample pause thd", - EE_AUDIO_RESAMPLEA_CTRL2, 0, 0xffffff, 0, - mixer_audiobus_read, mixer_audiobus_write, + EE_AUDIO_RESAMPLEA_CTRL2, 11, 0x1fff, 0, + mixer_audiobus_read, NULL, NULL), SOC_ENUM_EXT("Hw resample module", auge_resample_module_enum, @@ -459,11 +459,11 @@ static const struct snd_kcontrol_new asrc_b_controls[] = { resample_set_enum), SOC_SINGLE_EXT_TLV("Hw resample b pause enable", EE_AUDIO_RESAMPLEB_CTRL2, 24, 0x1, 0, - mixer_audiobus_read, mixer_audiobus_write, + mixer_audiobus_read, NULL, NULL), SOC_SINGLE_EXT_TLV("Hw resample b pause thd", - EE_AUDIO_RESAMPLEB_CTRL2, 0, 0xffffff, 0, - mixer_audiobus_read, mixer_audiobus_write, + EE_AUDIO_RESAMPLEB_CTRL2, 11, 0x1fff, 0, + mixer_audiobus_read, NULL, NULL), SOC_ENUM_EXT("Hw resample b module", auge_resample_module_enum, diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index 03ca3aad115c..73c7dd32eef2 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -115,6 +115,7 @@ int resample_set_hw_param(enum resample_idx id, reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; audiobus_update_bits(reg, 1 << 25, 1 << 25); + resample_set_hw_pause_thd(id, 128); return 0; } @@ -160,3 +161,13 @@ void resample_ctrl_write(enum resample_idx id, int value) audiobus_write(reg, value); } + +int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd) +{ + int offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; + int reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; + + audiobus_write(reg, 1 << 24 | thd << 11); + + return 0; +} diff --git a/sound/soc/amlogic/auge/resample_hw.h b/sound/soc/amlogic/auge/resample_hw.h index 5d7c3dda2c1c..61b062921990 100644 --- a/sound/soc/amlogic/auge/resample_hw.h +++ b/sound/soc/amlogic/auge/resample_hw.h @@ -41,5 +41,6 @@ extern void resample_format_set(enum resample_idx id, int ch_num, int bits); extern int resample_ctrl_read(enum resample_idx id); extern void resample_ctrl_write(enum resample_idx id, int value); +int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd); #endif From 9146c6892434348398ce1559247eba56732c5d57 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Sun, 21 Apr 2019 19:08:07 -0700 Subject: [PATCH 0523/1060] Revert "audio: enable hw resmaple pause thd [1/1]" This reverts commit 8398f8a917504fd4f3efd82306fcce1e2a1d8b80. Change-Id: I76a3c8fc66b528b62e57630603ad3887b0b3abdc Signed-off-by: Jianxin Pan --- sound/soc/amlogic/auge/resample.c | 12 ++++++------ sound/soc/amlogic/auge/resample_hw.c | 11 ----------- sound/soc/amlogic/auge/resample_hw.h | 1 - 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 90791ef895f5..8678361c51c5 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -440,11 +440,11 @@ static const struct snd_kcontrol_new asrc_a_controls[] = { resample_set_enum), SOC_SINGLE_EXT_TLV("Hw resample pause enable", EE_AUDIO_RESAMPLEA_CTRL2, 24, 0x1, 0, - mixer_audiobus_read, NULL, + mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_SINGLE_EXT_TLV("Hw resample pause thd", - EE_AUDIO_RESAMPLEA_CTRL2, 11, 0x1fff, 0, - mixer_audiobus_read, NULL, + EE_AUDIO_RESAMPLEA_CTRL2, 0, 0xffffff, 0, + mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_ENUM_EXT("Hw resample module", auge_resample_module_enum, @@ -459,11 +459,11 @@ static const struct snd_kcontrol_new asrc_b_controls[] = { resample_set_enum), SOC_SINGLE_EXT_TLV("Hw resample b pause enable", EE_AUDIO_RESAMPLEB_CTRL2, 24, 0x1, 0, - mixer_audiobus_read, NULL, + mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_SINGLE_EXT_TLV("Hw resample b pause thd", - EE_AUDIO_RESAMPLEB_CTRL2, 11, 0x1fff, 0, - mixer_audiobus_read, NULL, + EE_AUDIO_RESAMPLEB_CTRL2, 0, 0xffffff, 0, + mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_ENUM_EXT("Hw resample b module", auge_resample_module_enum, diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index 73c7dd32eef2..03ca3aad115c 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -115,7 +115,6 @@ int resample_set_hw_param(enum resample_idx id, reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; audiobus_update_bits(reg, 1 << 25, 1 << 25); - resample_set_hw_pause_thd(id, 128); return 0; } @@ -161,13 +160,3 @@ void resample_ctrl_write(enum resample_idx id, int value) audiobus_write(reg, value); } - -int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd) -{ - int offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; - int reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; - - audiobus_write(reg, 1 << 24 | thd << 11); - - return 0; -} diff --git a/sound/soc/amlogic/auge/resample_hw.h b/sound/soc/amlogic/auge/resample_hw.h index 61b062921990..5d7c3dda2c1c 100644 --- a/sound/soc/amlogic/auge/resample_hw.h +++ b/sound/soc/amlogic/auge/resample_hw.h @@ -41,6 +41,5 @@ extern void resample_format_set(enum resample_idx id, int ch_num, int bits); extern int resample_ctrl_read(enum resample_idx id); extern void resample_ctrl_write(enum resample_idx id, int value); -int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd); #endif From 307bf38e2d24515896bd389d5a0fbd5eca592a61 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Mon, 22 Apr 2019 10:52:18 +0800 Subject: [PATCH 0524/1060] audio: enable hw resmaple pause thd [1/1] PD#TV-4638 Problem: Speaker output high frequency howling after change from pattern 615 to pattern 1 on chroma22294. The hw resampler keeps sending noise if it has no input. Solution: Enable the hw resample pause thd by default. Verify: TL1 X301. Change-Id: Ib6f0924025e155eaa8ba0e3681b307f7ff56b449 Signed-off-by: Shuai Li --- sound/soc/amlogic/auge/resample.c | 15 ++++++++------- sound/soc/amlogic/auge/resample_hw.c | 11 +++++++++++ sound/soc/amlogic/auge/resample_hw.h | 1 + 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 8678361c51c5..f3a99483eec3 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -271,18 +271,19 @@ int resample_set(enum resample_idx id, enum samplerate_index index) struct audioresample *p_resample = get_audioresample(id); int ret = 0; + if (!p_resample) + return 0; + pr_info("%s resample_%c to %s, last %s\n", __func__, (id == RESAMPLE_A) ? 'a' : 'b', auge_resample_texts[index], auge_resample_texts[p_resample->asrc_rate_idx]); - if (!p_resample) +#if 0 + if (index == p_resample->asrc_rate_idx) return 0; - - //if (index == p_resample->asrc_rate_idx) - // return 0; - +#endif p_resample->asrc_rate_idx = index; resample_rate = resample_idx2rate(index); @@ -443,7 +444,7 @@ static const struct snd_kcontrol_new asrc_a_controls[] = { mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_SINGLE_EXT_TLV("Hw resample pause thd", - EE_AUDIO_RESAMPLEA_CTRL2, 0, 0xffffff, 0, + EE_AUDIO_RESAMPLEA_CTRL2, 11, 0x1fff, 0, mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_ENUM_EXT("Hw resample module", @@ -462,7 +463,7 @@ static const struct snd_kcontrol_new asrc_b_controls[] = { mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_SINGLE_EXT_TLV("Hw resample b pause thd", - EE_AUDIO_RESAMPLEB_CTRL2, 0, 0xffffff, 0, + EE_AUDIO_RESAMPLEB_CTRL2, 11, 0x1fff, 0, mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_ENUM_EXT("Hw resample b module", diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index 03ca3aad115c..73c7dd32eef2 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -115,6 +115,7 @@ int resample_set_hw_param(enum resample_idx id, reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; audiobus_update_bits(reg, 1 << 25, 1 << 25); + resample_set_hw_pause_thd(id, 128); return 0; } @@ -160,3 +161,13 @@ void resample_ctrl_write(enum resample_idx id, int value) audiobus_write(reg, value); } + +int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd) +{ + int offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; + int reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; + + audiobus_write(reg, 1 << 24 | thd << 11); + + return 0; +} diff --git a/sound/soc/amlogic/auge/resample_hw.h b/sound/soc/amlogic/auge/resample_hw.h index 5d7c3dda2c1c..61b062921990 100644 --- a/sound/soc/amlogic/auge/resample_hw.h +++ b/sound/soc/amlogic/auge/resample_hw.h @@ -41,5 +41,6 @@ extern void resample_format_set(enum resample_idx id, int ch_num, int bits); extern int resample_ctrl_read(enum resample_idx id); extern void resample_ctrl_write(enum resample_idx id, int value); +int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd); #endif From 223ae73582c3e51fbc93a4f0ec7ef6b9d2c83628 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Tue, 22 Jan 2019 14:25:58 +0800 Subject: [PATCH 0525/1060] cpufreq: add more syspll freq info [1/1] PD#SWPL-4035 Problem: add more syspll freq info. Solution: add more syspll freq info. Verify: g12a_u200, verify pass Change-Id: I3e2a587f5ebaa20126e6ad5c37bd9d2730a75125 Signed-off-by: Hong Guo Conflicts: drivers/amlogic/clk/g12a/g12a.h --- drivers/amlogic/clk/g12a/g12a.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h index 0329c8d9443c..1c5ff7a0d862 100644 --- a/drivers/amlogic/clk/g12a/g12a.h +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -156,12 +156,6 @@ static const struct pll_rate_table g12a_pll_rate_table[] = { PLL_RATE(1896000000ULL, 158, 1, 1), /*DCO=3792M*/ PLL_RATE(1908000000ULL, 159, 1, 1), /*DCO=3816M*/ PLL_RATE(1920000000ULL, 160, 1, 1), /*DCO=3840M*/ - PLL_RATE(1932000000ULL, 161, 1, 1), /*DCO=3864M*/ - PLL_RATE(1944000000ULL, 162, 1, 1), /*DCO=3888M*/ - PLL_RATE(1956000000ULL, 163, 1, 1), /*DCO=3912M*/ - PLL_RATE(1968000000ULL, 164, 1, 1), /*DCO=3936M*/ - PLL_RATE(1980000000ULL, 165, 1, 1), /*DCO=3960M*/ - PLL_RATE(1992000000ULL, 166, 1, 1), /*DCO=3984M*/ PLL_RATE(2004000000ULL, 167, 1, 1), /*DCO=4008M*/ PLL_RATE(2016000000ULL, 168, 1, 1), /*DCO=4032M*/ PLL_RATE(2100000000ULL, 175, 1, 1), /*DCO=4200M*/ From 50d14a7d110b1ade69a3048791a398568d73e046 Mon Sep 17 00:00:00 2001 From: Yingyuan Zhu Date: Thu, 17 Jan 2019 19:02:20 +0800 Subject: [PATCH 0526/1060] jtag: meson: fix jtag pinmux settings issue [2/2] PD#SWPL-4501 Problem: Standard pinmux APIs were not used Solution: Setting pinmux instead of require for gpio Verify: tl1,g12a,g12b,axg,txl,txlx,gxl Change-Id: I0ad88f414832686d795d252f70e81a34f6cb0f9e Signed-off-by: Yingyuan Zhu Conflicts: arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm64/boot/dts/amlogic/mesontxl.dtsi --- arch/arm/boot/dts/amlogic/meson8b.dtsi | 31 +- arch/arm/boot/dts/amlogic/mesonaxg.dtsi | 29 ++ arch/arm/boot/dts/amlogic/mesong12a.dtsi | 33 +- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 29 ++ arch/arm/boot/dts/amlogic/mesongxl.dtsi | 40 ++- .../arm/boot/dts/amlogic/mesongxl_sei210.dtsi | 40 ++- arch/arm/boot/dts/amlogic/mesongxm.dtsi | 34 +- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 24 +- arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 26 +- arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 27 ++ arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 33 +- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 29 ++ arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 41 ++- .../boot/dts/amlogic/mesongxl_sei210.dtsi | 40 ++- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 34 +- arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 26 +- drivers/amlogic/jtag/meson_jtag.c | 299 +++++------------- drivers/amlogic/jtag/meson_jtag.h | 1 + 18 files changed, 443 insertions(+), 373 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/meson8b.dtsi b/arch/arm/boot/dts/amlogic/meson8b.dtsi index 320c4986f625..4c12955cb565 100644 --- a/arch/arm/boot/dts/amlogic/meson8b.dtsi +++ b/arch/arm/boot/dts/amlogic/meson8b.dtsi @@ -124,15 +124,10 @@ compatible = "amlogic, jtag"; status = "okay"; reg = <0xda004004 0x4>; - select = "apao"; /* disable apao apee */ - jtagao-gpios = <&gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0 - &gpio_ao GPIOAO_10 0 - &gpio_ao GPIOAO_11 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; securitykey { @@ -623,6 +618,15 @@ bias-pull-up; }; }; + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; + }; + }; }; pinctrl_aobus: pinctrl@c8100084 { compatible = "amlogic,meson8b-aobus-pinctrl"; @@ -681,6 +685,15 @@ function = "spdif_2"; }; }; + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "GPIOAO_8", + "GPIOAO_9", + "GPIOAO_10", + "GPIOAO_11"; + function = "gpio_aobus"; + }; + }; }; dwc2_b { compatible = "amlogic,dwc2"; diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index 3bf899700678..15a0de94ab31 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -282,6 +282,15 @@ status = "okay"; }; + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + pinctrl_aobus: pinctrl@ff800014{ compatible = "amlogic,meson-axg-aobus-pinctrl"; #address-cells = <1>; @@ -879,6 +888,16 @@ }; }; + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_ao_tdi", + "jtag_ao_tdo", + "jtag_ao_clk", + "jtag_ao_tms"; + function = "jtag_ao"; + }; + }; + }; /* end of pinctrl_aobus */ &pinctrl_periphs { @@ -1140,5 +1159,15 @@ }; }; + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_tdo_x", + "jtag_tdi_x", + "jtag_clk_x", + "jtag_tms_x"; + function = "jtag_ee"; + }; + }; + }; /* end of pinctrl_periphs */ diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index ec831fd30d79..c304dfd5a86d 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -447,15 +447,10 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; saradc:saradc { @@ -1993,6 +1988,16 @@ function = "cec_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2567,6 +2572,16 @@ drive-strength = <3>; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &pinctrl_aobus { diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 9fcd30a3acb8..f3eaf402f1ff 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -502,6 +502,15 @@ clocks = <&xtal>; }; + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + saradc:saradc { compatible = "amlogic,meson-g12a-saradc"; status = "disabled"; @@ -2075,6 +2084,16 @@ function = "pwm_a_gpioe"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2582,6 +2601,16 @@ function = "remote_out"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &gpu{ diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index b3c787f8484a..a8cda637f231 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -250,15 +250,13 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -657,23 +655,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi index dfe090d26025..c76fb65b3fcf 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -240,15 +240,13 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -643,23 +641,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index 37d28d35e718..e336565a37d6 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -284,10 +284,14 @@ jtag { compatible = "amlogic, jtag"; - status = "disabled"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXM platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ pinctrl-names = "jtag_apao_pins", "jtag_apee_pins"; - pinctrl-0 = <&jtag_apao_pins>; - pinctrl-1 = <&jtag_apee_pins>; + pinctrl-0 = <&jtag_a_pins>; + pinctrl-1 = <&jtag_b_pins>; }; psci { @@ -751,23 +755,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index fbe396c5d70d..ccec21e15cf8 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -474,16 +474,10 @@ jtag { compatible = "amlogic, jtag"; - status = "disabled"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; + status = "okay"; + select = "disable"; /* disable/apao */ + pinctrl-names="jtag_apao_pins"; + pinctrl-0=<&jtag_apao_pins>; }; saradc:saradc { @@ -1627,6 +1621,16 @@ function = "remote_out_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 1c13daa4399a..417cedf1e252 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -285,9 +285,13 @@ status = "okay"; }; - amlogic-jtag { + jtag { compatible = "amlogic, jtag"; status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; vpu { @@ -1047,6 +1051,16 @@ function = "i2c_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_7"; + function = "gpio_aobus"; + }; + }; }; &pinctrl_periphs { @@ -1387,6 +1401,16 @@ function = "pwm_d"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3"; + function = "gpio_periphs"; + }; + }; }; &gpu{ diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index f708ac673ddb..15d6e3785075 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -282,6 +282,15 @@ status = "okay"; }; + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + pinctrl_aobus: pinctrl@ff800014{ compatible = "amlogic,meson-axg-aobus-pinctrl"; #address-cells = <2>; @@ -880,6 +889,15 @@ }; }; + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_ao_tdi", + "jtag_ao_tdo", + "jtag_ao_clk", + "jtag_ao_tms"; + function = "jtag_ao"; + }; + }; }; /* end of pinctrl_aobus */ &pinctrl_periphs { @@ -1141,5 +1159,14 @@ }; }; + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_tdo_x", + "jtag_tdi_x", + "jtag_clk_x", + "jtag_tms_x"; + function = "jtag_ee"; + }; + }; }; /* end of pinctrl_periphs */ diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 11b4a7efe3c7..ac2df4a76968 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -447,15 +447,10 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; saradc:saradc { @@ -2003,6 +1998,16 @@ function = "cec_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2588,6 +2593,16 @@ drive-strength = <3>; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &pinctrl_aobus { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index ef5c20957035..5b92ba775776 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -502,6 +502,15 @@ clocks = <&xtal>; }; + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + saradc:saradc { compatible = "amlogic,meson-g12a-saradc"; status = "disabled"; @@ -2085,6 +2094,16 @@ function = "pwm_a_gpioe"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2603,6 +2622,16 @@ function = "remote_out"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &gpu{ diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index a997334c8441..e464b6bed8a7 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -237,15 +237,13 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -621,6 +619,7 @@ function = "ee_cec"; }; }; + }; /* end of pinctrl_aobus*/ &pinctrl_periphs { @@ -644,23 +643,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi index efaa61bd1434..ab1a3e8b2e74 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -240,15 +240,13 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -643,23 +641,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 92bd78b11daf..be68834f1e45 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -284,10 +284,14 @@ jtag { compatible = "amlogic, jtag"; - status = "disabled"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXM platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ pinctrl-names = "jtag_apao_pins", "jtag_apee_pins"; - pinctrl-0 = <&jtag_apao_pins>; - pinctrl-1 = <&jtag_apee_pins>; + pinctrl-0 = <&jtag_a_pins>; + pinctrl-1 = <&jtag_b_pins>; }; psci { @@ -751,23 +755,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 27a312223f2f..8b78e147be1c 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -285,9 +285,13 @@ status = "okay"; }; - amlogic-jtag { + jtag { compatible = "amlogic, jtag"; status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; vpu { @@ -1047,6 +1051,16 @@ function = "i2c_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_7"; + function = "gpio_aobus"; + }; + }; }; &pinctrl_periphs { @@ -1387,6 +1401,16 @@ function = "pwm_d"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3"; + function = "gpio_periphs"; + }; + }; }; &gpu{ diff --git a/drivers/amlogic/jtag/meson_jtag.c b/drivers/amlogic/jtag/meson_jtag.c index ddca757f80e7..e3890ac67aeb 100644 --- a/drivers/amlogic/jtag/meson_jtag.c +++ b/drivers/amlogic/jtag/meson_jtag.c @@ -101,6 +101,23 @@ static inline char *select_to_name(int select) } } +static inline int name_to_select(const char *s) +{ + int select; + + if (!strncmp(s, "disable", 7)) + select = AMLOGIC_JTAG_DISABLE; + else if (!strncmp(s, "apao", 4)) + select = AMLOGIC_JTAG_APAO; + else if (!strncmp(s, "apee", 4)) + select = AMLOGIC_JTAG_APEE; + else { + pr_err("unknown select: %s\n", s); + select = AMLOGIC_JTAG_DISABLE; + } + + return select; +} static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) { @@ -108,15 +125,7 @@ static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) unsigned long value; int ret; - if (!strncmp(s, "disable", 7)) - jdev->select = AMLOGIC_JTAG_DISABLE; - else if (!strncmp(s, "apao", 4)) - jdev->select = AMLOGIC_JTAG_APAO; - else if (!strncmp(s, "apee", 4)) - jdev->select = AMLOGIC_JTAG_APEE; - else - pr_err("unknown select: %s", s); - + jdev->select = name_to_select(s); cluster = strchr(s, ','); if (cluster != NULL) { cluster++; @@ -138,19 +147,10 @@ static int __init setup_jtag(char *p) unsigned long value; int ret; + if (!p) + return -EINVAL; jtag_select_setup = true; - - if (!strncmp(p, "disable", 7)) - jtag_select = AMLOGIC_JTAG_DISABLE; - else if (!strncmp(p, "apao", 4)) - jtag_select = AMLOGIC_JTAG_APAO; - else if (!strncmp(p, "apee", 4)) - jtag_select = AMLOGIC_JTAG_APEE; - else - jtag_select = AMLOGIC_JTAG_DISABLE; - - pr_info("jtag select %s\n", select_to_name(jtag_select)); - + jtag_select = name_to_select(p); cluster = strchr(p, ','); if (cluster != NULL) { cluster++; @@ -176,97 +176,6 @@ static int __init setup_jtag(char *p) */ __setup("jtag=", setup_jtag); - -/* - * request gpios for jtag apao. - * - * @return: 0 success, other failed - * - */ -static int aml_jtag_apao_request_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ao_gpios; - - int ngpio, i, ret; - - ngpio = jdev->ao_ngpios; - - for (i = 0; i < ngpio; i++) { - ret = devm_gpio_request(dev, gpios[i], "apao"); - if (ret) { - pr_err("can't request gpio %d", gpios[i]); - return -ENOENT; - } - pr_info("request gpio %d for apao\n", gpios[i]); - } - - return 0; -} - -static int aml_jtag_apao_free_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ao_gpios; - - int ngpio, i; - - ngpio = jdev->ao_ngpios; - - for (i = 0; i < ngpio; i++) - devm_gpio_free(dev, gpios[i]); - - return 0; -} - - -/* - * request gpios for jtag apee. - * - * @return: 0 success, other failed - * - */ -static int aml_jtag_apee_request_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ee_gpios; - - int ngpio, i, ret; - - ngpio = jdev->ee_ngpios; - - for (i = 0; i < ngpio; i++) { - ret = devm_gpio_request(dev, gpios[i], "apee"); - if (ret) { - pr_err("can't request gpio %d", gpios[i]); - return -ENOENT; - } - pr_info("request gpio %d for apee\n", gpios[i]); - } - - return 0; -} - -static int aml_jtag_apee_free_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ee_gpios; - - int ngpio, i; - - ngpio = jdev->ee_ngpios; - - for (i = 0; i < ngpio; i++) - devm_gpio_free(dev, gpios[i]); - - return 0; -} - - #ifdef CONFIG_MACH_MESON8B static int aml_jtag_select_tee(struct platform_device *pdev) @@ -274,8 +183,8 @@ static int aml_jtag_select_tee(struct platform_device *pdev) struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); uint32_t select = jdev->select; - pr_info("set state %u\n", select); set_cpus_allowed_ptr(current, cpumask_of(0)); + pr_info("meson8b select %s\n", select_to_name(jdev->select)); switch (select) { case AMLOGIC_JTAG_DISABLE: meson_secure_jtag_disable(); @@ -309,7 +218,7 @@ static int aml_jtag_select_ree(struct platform_device *pdev) pr_err("failed to iomap regs"); return -ENODEV; } - + pr_info("meson8b select %s\n", select_to_name(jdev->select)); switch (sel) { case AMLOGIC_JTAG_DISABLE: writel_relaxed(0x0, jdev->base); @@ -353,6 +262,7 @@ static unsigned long __invoke_psci_fn_smc(unsigned long function_id, struct arm_smccc_res res; arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); + return res.a0; } @@ -388,8 +298,7 @@ static int aml_jtag_select(struct platform_device *pdev) if (jdev->cluster != CLUSTER_DISABLE) select |= jdev->cluster << CLUSTER_BIT; - pr_info("set state %u\n", select); - + pr_info("select %s\n", select_to_name(select)); set_cpus_allowed_ptr(current, cpumask_of(0)); aml_set_jtag_state(state, select); set_cpus_allowed_ptr(current, cpu_all_mask); @@ -399,43 +308,64 @@ static int aml_jtag_select(struct platform_device *pdev) #endif -static void aml_jtag_setup(struct aml_jtag_dev *jdev) +static int aml_jtag_setup(struct aml_jtag_dev *jdev) { - struct platform_device *pdev = jdev->pdev; unsigned int old_select = jdev->old_select; unsigned int select = jdev->select; + struct pinctrl_state *s; + int ret; if (old_select == select) - return; - - /* free gpios */ - switch (old_select) { - case AMLOGIC_JTAG_APAO: - aml_jtag_apao_free_gpios(pdev); - break; - case AMLOGIC_JTAG_APEE: - aml_jtag_apee_free_gpios(pdev); - break; - default: - break; + return 0; + if (!jdev->jtag_pinctrl) { + jdev->jtag_pinctrl = devm_pinctrl_get(&jdev->pdev->dev); + if (IS_ERR_OR_NULL(jdev->jtag_pinctrl)) { + dev_err(&jdev->pdev->dev, "could not get pinctrl handle\n"); + return -EINVAL; + } } - - /* free gpios */ + /* set pinmux */ switch (select) { case AMLOGIC_JTAG_APAO: - aml_jtag_apao_request_gpios(pdev); + s = pinctrl_lookup_state(jdev->jtag_pinctrl, "jtag_apao_pins"); + if (IS_ERR_OR_NULL(s)) { + dev_err(&jdev->pdev->dev, + "could not get jtag_apao_pins state\n"); + return -EINVAL; + } + ret = pinctrl_select_state(jdev->jtag_pinctrl, s); + if (ret) { + dev_err(&jdev->pdev->dev, "failed to set pinctrl\n"); + return -EINVAL; + } break; case AMLOGIC_JTAG_APEE: - aml_jtag_apee_request_gpios(pdev); + s = pinctrl_lookup_state(jdev->jtag_pinctrl, "jtag_apee_pins"); + if (IS_ERR_OR_NULL(s)) { + dev_err(&jdev->pdev->dev, + "could not get jtag_apee_pins state\n"); + return -EINVAL; + } + ret = pinctrl_select_state(jdev->jtag_pinctrl, s); + if (ret) { + dev_err(&jdev->pdev->dev, "failed to set pinctrl\n"); + return -EINVAL; + } break; default: + if (old_select != AMLOGIC_JTAG_DISABLE) { + devm_pinctrl_put(jdev->jtag_pinctrl); + jdev->jtag_pinctrl = NULL; + } break; } + /* save to global */ + global_select = jdev->select; aml_jtag_select(jdev->pdev); - jdev->old_select = select; + return 0; } static ssize_t jtag_select_show(struct class *cls, @@ -448,23 +378,23 @@ static ssize_t jtag_select_show(struct class *cls, len += sprintf(buf + len, "usage:\n"); len += sprintf(buf + len, " echo [apao|apee] > select\n"); len += sprintf(buf + len, " echo [apao|apee]{,[0|1]} > select\n"); + return len; } - static ssize_t jtag_select_store(struct class *cls, struct class_attribute *attr, const char *buffer, size_t count) { struct aml_jtag_dev *jdev; + int ret; jdev = container_of(cls, struct aml_jtag_dev, cls); aml_jtag_option_parse(jdev, buffer); - /* save to global */ - global_select = jdev->select; - - aml_jtag_setup(jdev); + ret = aml_jtag_setup(jdev); + if (ret < 0) + return ret; return count; } @@ -474,63 +404,13 @@ static struct class_attribute aml_jtag_attrs[] = { __ATTR_NULL, }; - static int aml_jtag_dt_parse(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); const char *tmp; - - int ao_ngpios, ee_ngpios; - unsigned int *ao_gpios, *ee_gpios; - int ret, i, gpio; - - - ao_ngpios = of_gpio_named_count(np, "jtagao-gpios"); - if (ao_ngpios <= 0) { - pr_err("ao gpios not specified\n"); - return -EINVAL; - } - - ee_ngpios = of_gpio_named_count(np, "jtagee-gpios"); - if (ee_ngpios <= 0) { - pr_err("ee gpios not specified\n"); - return -EINVAL; - } - - jdev->ao_ngpios = ao_ngpios; - jdev->ee_ngpios = ee_ngpios; - - ao_gpios = devm_kzalloc(dev, sizeof(unsigned int) * ao_ngpios, - GFP_KERNEL); - ee_gpios = devm_kzalloc(dev, sizeof(unsigned int) * ee_ngpios, - GFP_KERNEL); - if (!ao_gpios || !ee_gpios) { - pr_err("failed to allocate memory for gpios\n"); - return -ENOMEM; - } - - for (i = 0; i < ao_ngpios; i++) { - gpio = of_get_named_gpio(dev->of_node, "jtagao-gpios", i); - if (!gpio_is_valid(gpio)) { - pr_err("gpio %d is not valid", gpio); - return -EINVAL; - } - ao_gpios[i] = gpio; - } - - for (i = 0; i < ee_ngpios; i++) { - gpio = of_get_named_gpio(dev->of_node, "jtagee-gpios", i); - if (!gpio_is_valid(gpio)) { - pr_err("gpio %d is not valid", gpio); - return -EINVAL; - } - ee_gpios[i] = gpio; - } - - jdev->ao_gpios = ao_gpios; - jdev->ee_gpios = ee_gpios; + int ret; /* otherwise set select with dt */ ret = of_property_read_string(np, "select", &tmp); @@ -538,34 +418,22 @@ static int aml_jtag_dt_parse(struct platform_device *pdev) pr_err("select not configured\n"); return -EINVAL; } - pr_info("select is configured %s\n", tmp); - - if (!strcmp(tmp, "disable")) - jdev->select = AMLOGIC_JTAG_DISABLE; - else if (!strcmp(tmp, "apao")) - jdev->select = AMLOGIC_JTAG_APAO; - else if (!strcmp(tmp, "apee")) - jdev->select = AMLOGIC_JTAG_APEE; - else - pr_err("unknown select: %s", tmp); - + jdev->select = name_to_select(tmp); return 0; } - - static int aml_jtag_probe(struct platform_device *pdev) { struct aml_jtag_dev *jdev; int ret; /* kzalloc device */ - jdev = kzalloc(sizeof(struct aml_jtag_dev), GFP_KERNEL); + jdev = devm_kzalloc(&pdev->dev, + sizeof(struct aml_jtag_dev), GFP_KERNEL); /* set driver data */ jdev->pdev = pdev; platform_set_drvdata(pdev, jdev); - ret = aml_jtag_dt_parse(pdev); if (ret) return -EINVAL; @@ -575,12 +443,8 @@ static int aml_jtag_probe(struct platform_device *pdev) if (jtag_select_setup) { jdev->select = jtag_select; jdev->cluster = jtag_cluster; - pr_info("select is replaced by boot param\n"); } - /* save to global */ - global_select = jdev->select; - /* create class attributes */ jdev->cls.name = AML_JTAG_NAME; jdev->cls.owner = THIS_MODULE; @@ -592,26 +456,25 @@ static int aml_jtag_probe(struct platform_device *pdev) } /* setup jtag */ - aml_jtag_setup(jdev); + ret = aml_jtag_setup(jdev); + if (ret < 0) { + class_unregister(&jdev->cls); + return ret; + } - pr_info("module probed ok\n"); return 0; } - static int __exit aml_jtag_remove(struct platform_device *pdev) { struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); class_unregister(&jdev->cls); platform_set_drvdata(pdev, NULL); - kfree(jdev); - pr_info("module removed ok\n"); return 0; } - static const struct of_device_id aml_jtag_dt_match[] = { { .compatible = "amlogic, jtag", @@ -619,7 +482,6 @@ static const struct of_device_id aml_jtag_dt_match[] = { {}, }; - static struct platform_driver aml_jtag_driver = { .driver = { .name = AML_JTAG_NAME, @@ -630,10 +492,8 @@ static struct platform_driver aml_jtag_driver = { .remove = __exit_p(aml_jtag_remove), }; - static int __init aml_jtag_init(void) { - pr_info("module init\n"); if (platform_driver_register(&aml_jtag_driver)) { pr_err("failed to register driver\n"); return -ENODEV; @@ -651,7 +511,6 @@ fs_initcall(aml_jtag_init); static void __exit aml_jtag_exit(void) { - pr_info("module exit\n"); platform_driver_unregister(&aml_jtag_driver); } diff --git a/drivers/amlogic/jtag/meson_jtag.h b/drivers/amlogic/jtag/meson_jtag.h index 41713a601351..1b9556cde650 100644 --- a/drivers/amlogic/jtag/meson_jtag.h +++ b/drivers/amlogic/jtag/meson_jtag.h @@ -27,6 +27,7 @@ struct aml_jtag_dev { struct platform_device *pdev; + struct pinctrl *jtag_pinctrl; struct class cls; #ifdef CONFIG_MACH_MESON8B From ef27279214d1b57a96036c1f9ab1abb0b9e3c87a Mon Sep 17 00:00:00 2001 From: jintao xu Date: Wed, 16 Jan 2019 10:14:49 +0800 Subject: [PATCH 0527/1060] omx: add two layer support [3/6] PD#SWPL-85 Problem: Need support two video layers feature Solution: 1: Add videosync. 2: amlvideo support multi-instance Verify: U212 Change-Id: I3570fad361ba5bd388dd46c51a66da056fa7a1fd Signed-off-by: jintao xu Conflicts: MAINTAINERS drivers/amlogic/media/video_processor/videosync/videosync.c --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 57ea7d1bdf28..188a9839cf25 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14803,6 +14803,11 @@ AMLOGIC SM1 CLOCK DRIVERS M: Shunzhou Jiang F: drivers/amlogic/clk/sm1/* +AMLOGIC SM1 DTS +M: shaochan.liu +F: arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi + AMLOGIC SM1 POWER CTRL DRIVERS M: Shunzhou Jiang F: drivers/amlogic/power/power_ctrl.c From cc502622702bdf688ec6bef5d6acf52928712687 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Thu, 14 Feb 2019 10:43:31 +0800 Subject: [PATCH 0528/1060] sd: add sduart not supported flag [1/1] PD#SWPL-4858 Problem: tl1 not support sduart Solution: add not supported flag in match_data Verify: verify by tl1 skt Change-Id: I651765433bb62892fad770c85a5eccd4805e7c79 Signed-off-by: Nan Li Conflicts: arch/arm/boot/dts/amlogic/tl1_pxp.dts arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts drivers/amlogic/mmc/amlsd.c --- arch/arm/boot/dts/amlogic/tl1_pxp.dts | 137 +++++++++++++++++++ arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 58 +++++--- drivers/amlogic/mmc/amlsd.c | 6 +- drivers/amlogic/mmc/amlsd_of.c | 2 + include/linux/amlogic/sd.h | 1 + 5 files changed, 184 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index d073d021f4f9..b8feffc0c7b3 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -471,6 +471,143 @@ reg-names = "ao_exit","ao"; }; + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <761000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <781000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <801000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <831000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <861000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <891000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <921000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c0>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + }; /* end of / */ &audiobus { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 1346a44912f7..e14a8d00d5fe 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -900,25 +900,47 @@ wifi{ compatible = "amlogic, aml_wifi"; status = "okay"; - interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; - irq_trigger_type = "GPIO_IRQ_LOW"; - dhd_static_buf; //dhd_static_buf support - power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pwm_b_pins1>; - pwm_config = <&wifi_pwm_conf>; - }; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; - wifi_pwm_conf:wifi_pwm_conf{ - pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_1 30040 0>; - duty-cycle = <15020>; - times = <8>; - }; - pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_3 30030 0>; - duty-cycle = <15015>; - times = <12>; + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ }; }; diff --git a/drivers/amlogic/mmc/amlsd.c b/drivers/amlogic/mmc/amlsd.c index 5cb2648709f3..25f5a53c0f6d 100644 --- a/drivers/amlogic/mmc/amlsd.c +++ b/drivers/amlogic/mmc/amlsd.c @@ -890,8 +890,10 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) host->is_sduart = 0; if (mmc && mmc->card) mmc_card_set_removed(mmc->card); - aml_uart_switch(pdata, 0); - aml_jtag_switch_ao(pdata); + if (!pdata->no_sduart) { + aml_uart_switch(pdata, 0); + aml_jtag_switch_ao(pdata); + } /* switch to 3.3V */ aml_sd_voltage_switch(mmc, MMC_SIGNAL_VOLTAGE_330); diff --git a/drivers/amlogic/mmc/amlsd_of.c b/drivers/amlogic/mmc/amlsd_of.c index fc093edddbb5..a117ef59ee0f 100644 --- a/drivers/amlogic/mmc/amlsd_of.c +++ b/drivers/amlogic/mmc/amlsd_of.c @@ -187,6 +187,8 @@ int amlsd_get_platform_data(struct platform_device *pdev, str, pdata->gpio_power); SD_PARSE_U32_PROP_DEC(child, "calc_f", prop, pdata->calc_f); + SD_PARSE_U32_PROP_DEC(child, "no_sduart", + prop, pdata->no_sduart); SD_PARSE_U32_PROP_DEC(child, "gpio_cd_level", prop, pdata->gpio_cd_level); diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 99e8c86b6faa..0e01cdd02032 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -300,6 +300,7 @@ struct amlsd_platform { unsigned int gpio_power; unsigned int power_level; unsigned int calc_f; + unsigned int no_sduart; unsigned int auto_clk_close; unsigned int vol_switch; From 641b2bb08246f79bfc63962e4a55201fc8e96b17 Mon Sep 17 00:00:00 2001 From: Bichao Zheng Date: Tue, 15 Jan 2019 16:46:00 +0800 Subject: [PATCH 0529/1060] arm: dts: update vddcpu pwm regulator voltage-table [1/1] PD#SWPL-4225 Problem: TL1 hardware update DCDC of vddcpu Solution: update vddcpu voltage-table [old] voltage range: 1021mv - 721mv step size: 10mv step: 30 [new] voltage range: 1049mv - 689mv step size: 10mv step: 36 Verify: test pass on tl1_X301_v1 tl1_skt_v1 Change-Id: I3adea525940737490197566a8c85b5b00c375ed0 Signed-off-by: Bichao Zheng Conflicts: arch/arm64/boot/dts/amlogic/mesontm2.dtsi arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts --- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 76 ++++++++++--------- arch/arm/boot/dts/amlogic/tl1_pxp.dts | 24 +++--- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 24 +++--- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 24 +++--- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 24 +++--- 5 files changed, 89 insertions(+), 83 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index ccec21e15cf8..b57049c7122f 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -492,44 +492,50 @@ vddcpu0: pwmao_d-regulator { compatible = "pwm-regulator"; - pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; regulator-name = "vddcpu0"; - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1021000>; + regulator-min-microvolt = <689000>; + regulator-max-microvolt = <1049000>; regulator-always-on; - max-duty-cycle = <1250>; + max-duty-cycle = <1500>; /* Voltage Duty-Cycle */ - voltage-table = <1021000 0>, - <1011000 3>, - <1001000 6>, - <991000 10>, - <981000 13>, - <971000 16>, - <961000 20>, - <951000 23>, - <941000 26>, - <931000 30>, - <921000 33>, - <911000 36>, - <901000 40>, - <891000 43>, - <881000 46>, - <871000 50>, - <861000 53>, - <851000 56>, - <841000 60>, - <831000 63>, - <821000 67>, - <811000 70>, - <801000 73>, - <791000 76>, - <781000 80>, - <771000 83>, - <761000 86>, - <751000 90>, - <741000 93>, - <731000 96>, - <721000 100>; + voltage-table = <1049000 0>, + <1039000 3>, + <1029000 6>, + <1019000 8>, + <1009000 11>, + <999000 14>, + <989000 17>, + <979000 20>, + <969000 23>, + <959000 26>, + <949000 29>, + <939000 31>, + <929000 34>, + <919000 37>, + <909000 40>, + <899000 43>, + <889000 45>, + <879000 48>, + <869000 51>, + <859000 54>, + <849000 56>, + <839000 59>, + <829000 62>, + <819000 65>, + <809000 68>, + <799000 70>, + <789000 73>, + <779000 76>, + <769000 79>, + <759000 81>, + <749000 84>, + <739000 87>, + <729000 89>, + <719000 92>, + <709000 95>, + <699000 98>, + <689000 100>; status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index b8feffc0c7b3..1f4eb6e7e2de 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -478,51 +478,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <781000>; + opp-microvolt = <789000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index e14a8d00d5fe..d50d4114e4e6 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -823,51 +823,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <791000>; + opp-microvolt = <799000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 3acfad3b66b6..436726743f90 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1068,51 +1068,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <791000>; + opp-microvolt = <799000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index cebdf098dc9a..300c206735a7 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -844,51 +844,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <791000>; + opp-microvolt = <799000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; From a46317b63e2b3edc612ac485a96de5d3b22585e5 Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Tue, 19 Feb 2019 13:01:57 +0800 Subject: [PATCH 0530/1060] dts: g12b: copy g12b dts [1/1] PD#SWPL-5020 Problem: copy g12b dts. Solution: copy. Verify: local. Change-Id: Ibd6423bd0cc99e98bf1d6359068f9f0719ad177f Signed-off-by: Jianxiong Pan Signed-off-by: Hong Guo Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts arch/arm/boot/dts/amlogic/g12b_pxp.dts arch/arm/boot/dts/amlogic/g12b_pxp_a.dts arch/arm/boot/dts/amlogic/mesong12b_a.dtsi arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts arch/arm64/boot/dts/amlogic/g12b_pxp.dts arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi --- arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts index 17376a8b4014..d6044c90d6b5 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { From 8df003b1c1fcf56084f23eb8ccdcd2c47ccc47f3 Mon Sep 17 00:00:00 2001 From: "changqing.gao" Date: Thu, 21 Feb 2019 17:19:06 +0800 Subject: [PATCH 0531/1060] mm: The first 1MB mem is wasted for CPU series coming after TXLX [1/1] PD#SWPL-3744 Problem: For the previous Amlogic CPU series(before TXLX), the CPU booting vector locates at physical address starting from 0x00. To avoid influencing cpu booting procedure, we have to reserve the first 1MB physical memory. But it has changed since TXLX, the normal text section can safely use 0~1M physical address. So it's no need to reserve the first 1MB in DTS. Solution: Change the starting address of usable memory from 0x100000 to 0x0 for CPU series coming after TXLX. Verify: Locally on W400 Change-Id: I2df7859a38feca48abd58459e8b231ee15ada9e2 Signed-off-by: changqing.gao Conflicts: arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts --- MAINTAINERS | 2 + .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 1696 +++++++++++++++++ 2 files changed, 1698 insertions(+) create mode 100644 arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts diff --git a/MAINTAINERS b/MAINTAINERS index 188a9839cf25..e74899514952 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14514,6 +14514,8 @@ F: drivers/amlogic/media/dtv_demod/* AMLOGIC DTV DEMOD DRIVER M: Zhiwei Yuan F: drivers/amlogic/media/dtv_demod/include/addr_atsc*.h +F: drivers/amlogic/media/dtv_demod/include/demod_dbg.h +F: drivers/amlogic/media/dtv_demod/demod_dbg.c AMLOGIC DEFENDKEY DRIVER M: Zhongfu Luo diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts new file mode 100644 index 000000000000..72b29a7a7e8c --- /dev/null +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -0,0 +1,1696 @@ +/* + * arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; +#include +#include + +#include "mesontxlx.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontxlx_r311-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "txlx_t962x_r311-1g"; + compatible = "amlogic, txlx"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_reserved>; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + //secos_reserved:linux,secos { + // status = "disabled"; + // compatible = "amlogic, aml_secos_memory"; + // reg = <0x0 0x05300000 0x0 0x2000000>; + // no-map; + //}; + + + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + + //carveout_reserved:linux,carveout-reserve { + // compatible = "amlogic, idev-mem"; + // size = <0x0 0x1000>; + //}; + + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0xd000000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x10000000>; + }; + ion_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x4C00000>; + alignment = <0x400000>; + alloc-ranges = <0x0 0x30000000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4179008(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4179008=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 5M */ + size = <0x0800000>; + alignment = <0x400000>; + alloc-ranges = <0x0 0x30000000>; + }; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + linux,phandle = <5>; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x01400000>; + alignment = <0x400000>; + alloc-ranges = <0x0 0x30000000>; + }; + }; + + amlogic_battery:dummy-battery { + compatible = "amlogic, dummy-battery"; + status = "disabled"; + }; + + amlogic_charger:dummy-charger { + compatible = "amlogic, dummy-charger"; + status = "disabled"; + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>, + <&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys { + label = "sysled"; + gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + default-state = "on"; /* keep/on/off */ + linux,default-trigger = "none"; + }; + + }; + + pwmleds { + compatible = "pwm-leds"; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&pwmleds_pins>; + + sys { + active-low; + label = "sysled"; + max-brightness = <255>; + pwms = <&pwm_AO_ab 0 50000 0>; + }; + }; + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + status = "okay"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff634558 0xc + 0xffd01084 0x4>; + interrupts = <0 8 1 + 0 9 1>; + + phy-mode= "rmii"; + mc_val_internal_phy = <0x1804>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq", + "phyirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + meson-fb { + compatible = "amlogic, meson-txlx"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "okay"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00800000 0x01800000 0x00100000>; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + /* 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + scale_mode = <1>; + /* 1920*1080*4*3 = 0x17BB000 */ + display_size_default = <1920 1080 1920 3240 32>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + logo_addr = "0x3f800000"; + }; + + ge2d { + compatible = "amlogic, ge2d-txlx"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_DOS + &clkc CLKID_CLK81 + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX>; + clock-names = "parser_top", + "demux", + "vdec", + "clk_81", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + + + amvideocap { + compatible = "amlogic, amvideocap"; + dev_name = "amvideocap.0"; + status = "disabled"; + max_size = <8>;//8M + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 6 1>; + interrupt-names = "de_irq"; + clocks = <&clkc CLKID_VPU_MUX>, + <&clkc CLKID_FCLK_DIV4>, + <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_mux", + "fclk_div4", + "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <250 500>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4179008>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + nr10bit-support = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + amlvideo { + compatible = "amlogic, amlvideo"; + dev_name = "amlvideo"; + status = "okay"; + }; + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_txlx"; + #address-cells=<1>; + #size-cells=<1>; + dev_name = "hdmirx"; + status = "okay"; + pinctrl-names = "hdmirx_pins"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux &hdmirx_d_mux>; + repeat = <0>; + interrupts = <0 56 1>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_AUDMEAS_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "hdmirx_audmeas_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + reg = <0xffd26000 0xa00000 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0xff63e000 0x2000 + 0x0 0x0 + 0xff634400 0x2000 + 0xff646000 0x2000>; + }; + + vdin0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + dev_name = "vdin0"; + status = "okay"; + reserve-iomap = "true"; + /*bit0:(1:share with codec_mm;0:cma alone)*/ + /*bit8:(1:alloc in discontinus way;0:alone in continuous way)*/ + flag_cma = <0x101>; + /* MByte, if 10bit disable: 64M(YUV422), + * if 10bit enable: 64*1.5 = 96M(YUV422) + * if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + * if support 4K2K-YUV444-10bit-WR:3840*2160*4*6 ~= 190M + * if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + * if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + * if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /* vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + }; + + vdin1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + dev_name = "vdin1"; + status = "okay"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /* vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + */ + tv_bit_mode = <1>; + }; + + tvafe { + compatible = "amlogic, tvafe-txlx"; + /*memory-region = <&tvafe_cma_reserved>;*/ + dev_name = "tvafe"; + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff642000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + dev_name = "vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + tvafe_avin_detect { + compatible = "amlogic, tvafe_avin_detect"; + dev_name = "tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_txlx"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + amvenc_avc { + compatible = "amlogic, amvenc_avc"; + //memory-region = <&amvenc_avc_reserved>; + //memory-region = <&avc_cma_reserved>; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff640000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff648000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev { + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + power_down_disable = <1>; + gpio_reset = <&gpio_ao GPIOAO_8 GPIO_ACTIVE_HIGH>; + //gpio_en = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + rtc { + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2015/01/01"; + status = "okay"; + }; + + wifi { + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + interrupts = <0 68 4>; + irq_trigger_type = "GPIO_IRQ_HIGH"; + dhd_static_buf; + power_on_pin = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf: wifi_pwm_conf { + pwm_channel1_conf { + pwms = <&pwm_cd MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_cd MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "okay"; + compatible = "amlogic, meson-mmc-txlx"; + reg = <0xffe07000 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + status = "disabled"; + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-txlx"; + reg = <0xffe05000 0x2000>; + interrupts = <0 217 1>; + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "ao_to_sd_jtag_pins", + "sd_to_ao_jtag_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-8 = <&sd_all_pins &sd_to_ao_uart_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + status = "disabled"; + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + /* "MMC_CAP_UHS_SDR12", + * "MMC_CAP_UHS_SDR25", + * "MMC_CAP_UHS_SDR50", + * "MMC_CAP_UHS_SDR104"; + */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_4 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOH_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + * 5:NON sdio device(means sd/mmc card) + */ + }; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + cvbsout { + compatible = "amlogic, cvbsout-txlx"; + dev_name = "cvbsout"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + performance = <0x1b56 0x343 + 0x1b05 0xf4 + 0x1c59 0xfc48 + 0x1b12 0x8c00 + 0xffff 0x0>; /* ending flag */ + }; + + amhdmitx: amhdmitx { + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "disabled"; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c2_h_pins>; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + */ + ic_type = <6>; + //gpio_i2c_en = <0>; + //repeater_tx = <0x1>; + //#address-cells = <2>; + //#size-cells = <2>; + //ranges; + }; + + i2c_gpio: i2c_gpio { + compatible = "i2c-gpio"; + dev_name = "i2c-gpio"; + status = "disabled"; + i2c-gpio,delay-us = <10>; /* 50 kHz */ + gpios = <&gpio GPIOH_2 0 + &gpio GPIOH_3 0>; + #address-cells = <2>; + #size-cells = <2>; + i2c-gpio,timeout-ms = <10>; + i2c_gpio_edid: i2c_gpio_edid { + compatible = "i2c-gpio"; + reg = <0x50 0x0 0x0 0x0>; + }; + }; + + aocec: aocec { + compatible = "amlogic, aocec-txlx"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TXLX"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <4>; + /*ee_cec;*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&hdmitx_aocec>; + pinctrl-1=<&hdmitx_aocecb>; + pinctrl-2=<&hdmitx_aocecb>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + + canvas { + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + rdma { + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0xffe09000 0x80 + 0xffd01008 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0xffe09080 0x20>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, meson-snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_audin_base { + reg = <0xffd03000 0x100000>; + }; + io_aiu_base { + reg = <0xFFCFFC00 0x100000>; + }; + io_eqdrc_base { + reg = <0xFFCFF000 0x100000>; + }; + io_hiu_reset_base { + reg = <0xFFCFCC00 0x100000>; + }; + io_isa_base { + reg = <0xFFD05800 0x100000>; + }; + }; + + /* AUDIO DEVICES */ + i2s_dai: I2S { + #sound-dai-cells = <0>; + /* config mpll whether same with audin */ + clocks = <&clkc CLKID_MPLL3>, + <&clkc CLKID_AMCLK_COMP>, + <&clkc CLKID_AIU_GLUE>, + <&clkc CLKID_I2S_OUT>, + <&clkc CLKID_AMCLK_MEASURE>, + <&clkc CLKID_AIFIFO2>, + <&clkc CLKID_MIXER>, + <&clkc CLKID_MIXER_IFACE>, + <&clkc CLKID_ADC>, + <&clkc CLKID_AIU_TOP>, + <&clkc CLKID_AOCLK_GATE>, + <&clkc CLKID_I2S_SPDIF>, + <&clkc CLKID_DAC_CLK>; + clock-names = "mpll", + "mclk", + "top_glue", + "i2s_out", + "amclk_measure", + "aififo2", + "aud_mixer", + "mixer_reg", + "adc", + "top_level", + "aoclk", + "aud_in", + "vdac_clk"; + compatible = "amlogic, aml-i2s-dai"; + }; + + i2s2_dai: I2S2 { + #sound-dai-cells = <0>; + /* config mpll whether same with aiu */ + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_AUDIN_MCLK_COMP>, + <&clkc CLKID_AUDIN_SCLK_COMP>, + <&clkc CLKID_AUDIN_LRCLK_COMP>; + clock-names = "audin_mpll", + "audin_mclk", + "audin_sclk", + "audin_lrclk"; + compatible = "amlogic, aml-i2s2-dai"; + }; + + spdif_dai: SPDIF { + #sound-dai-cells = <0>; + compatible = "amlogic, aml-spdif-dai"; + clocks = <&clkc CLKID_MPLL1>, + <&clkc CLKID_IEC958_INT_COMP>, + <&clkc CLKID_AMCLK_COMP>, + <&clkc CLKID_IEC958_MUX>, + <&clkc CLKID_CLK81>, + <&clkc CLKID_IEC958>, + <&clkc CLKID_IEC958_GATE>; + clock-names = + "mpll1", + "i958", + "mclk", + "spdif", + "clk_81", + "iec958", + "iec958_amclk"; + }; + + pcm_dai: PCM { + #sound-dai-cells = <0>; + compatible = "amlogic, aml-pcm-dai"; + pinctrl-names = "audio_pcm"; + /* disable pcm pin mux temporary, enable it if necessary */ + /*pinctrl-0 = <&aml_audio_pcm>;*/ + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_PCM_MCLK_COMP>, + <&clkc CLKID_PCM_SCLK_COMP>; + clock-names = "mpll0", "pcm_mclk", "pcm_sclk"; + pcm_mode = <1>; /* 0=slave mode, 1=master mode */ + }; + + i2s_plat: i2s_platform { + compatible = "amlogic, aml-i2s"; + interrupts = <0 29 1>; + }; + + pcm_plat: pcm_platform { + compatible = "amlogic, aml-pcm"; + }; + + spdif_codec: spdif_codec{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml-spdif-codec"; + pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute"; + pinctrl-0 = <&audio_spdif_out_pins>; + pinctrl-1 = <&audio_spdif_out_mute_pins>; + }; + + pcm_codec: pcm_codec{ + #sound-dai-cells = <0>; + compatible = "amlogic, pcm2BT-codec"; + }; + /* end of AUDIO DEVICES */ + + /* AUDIO board specific */ + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + amlogic_codec:txlx_acodec{ + #sound-dai-cells = <0>; + compatible = "amlogic, txlx_acodec"; + reg = <0xFF632000 0x1c>; + status = "okay"; + }; + + aml_snd_tv { + compatible = "amlogic, txlx-snd-tv"; + status = "okay"; + aml-sound-card,format = "i2s"; + aml_sound_card,name = "AML-TVAUDIO"; + pinctrl-names = "audio_i2s"; + pinctrl-0 = <&aml_audio_i2s>; + /*avout mute gpio*/ + mute_gpio-gpios = <&gpio GPIODV_5 GPIO_ACTIVE_HIGH>; + /*analog amp mute*/ + /*amp_mute_gpio-gpios = <&gpio GPIOZ_18 GPIO_ACTIVE_LOW>;*/ + aux_dev = <&tas5707>; + cpu_list = <&cpudai0 &cpudai1 &cpudai2 &cpudai3>; + codec_list = <&codec0 &codec1 &codec2 &codec3>; + plat_list = <&i2s_plat &i2s_plat &pcm_plat &i2s_plat>; + cpudai0: cpudai0 { + sound-dai = <&i2s_dai>; + }; + cpudai1: cpudai1 { + sound-dai = <&spdif_dai>; + }; + cpudai2: cpudai2 { + sound-dai = <&pcm_dai>; + }; + cpudai3: cpudai3 { + sound-dai = <&i2s2_dai>; + }; + codec0: codec0 { + sound-dai = <&amlogic_codec>; + }; + codec1: codec1 { + sound-dai = <&spdif_codec>; + }; + codec2: codec2 { + sound-dai = <&pcm_codec>; + }; + codec3: codec3 { + sound-dai = <&dummy_codec>; + }; + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Speaker0_Channel_Mask = "i2s_2/3"; + DAC0_Channel_Mask = "i2s_4/5"; + DAC1_Channel_Mask = "i2s_4/5"; + EQ_DRC_Channel_Mask = "i2s_2/3"; + Spdif_samesource_Channel_Mask = "i2s_0/1"; + }; + }; + + amaudio2 { + compatible = "amlogic, aml_amaudio2"; + status = "okay"; + interrupts = <0 48 1>; + }; + /* end of AUDIO board specific */ + + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + status = "okay"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpus"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpu_core_cluster0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <437>; + cluster_id = <0>; + node_name = "mali"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "thermal_gpu_cores"; + device_type = "gpucore"; + }; + }; + cpu_cluster0:cpu_core_cluster0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore:thermal_gpu_cores { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + dvb_swdmx { + compatible = "amlogic, dvb-swdmx"; + dev_name = "dvb_swdmx"; + status = "okay"; + cbus_base = <0x1800>; + asyncfifo0_reg_base = <0x2800>; + asyncfifo1_reg_base = <0x9800>; + asyncfifo2_reg_base = <0x2400>; + reset_base = <0x0400>; + parser_sub_ptr_base = <0x3800>; + + ts_in_count = <3>; + s2p_count = <2>; + asyncfifo_count = <2>; + + asyncfifo_buf_len = <0x80000>; + + path_num = <2>; + path0_ts = <2>;/*0~2 for ts, 16 for hiu */ + path0_dmx = <0>; + path0_asyncfifo = <0>; + path1_ts = <2>; + path1_dmx = <1>; + path1_asyncfifo = <1>; + + /*dmxdev_num = <4>;*/ + + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + aml_dtv_demod { + compatible = "amlogic, ddemod-txlx"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + + reg = <0xff644000 0x2000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + status = "disabled"; + dtv_demod0 = "AMLDEMOD"; + fe0_dtv_demod = <0>; + fe0_ts = <2>; + fe0_dev = <0>; + dtv_demod0_mem = <0>; + dtv_demod0_spectrum = <1>; + dtv_demod0_cma_flag = <1>; + dtv_demod0_cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + tuner0 = "si2151_tuner"; + tuner0_i2c_adap_id = <2>; + tuner0_i2c_addr = <0x60>; + //tuner0_reset_value = <0>; + //tuner0_reset_gpio = "GPIOY_10" ; /*GPIOX_8 76*/ + fe0_tuner = <0>; + atv_demod0 = "aml_atv_demod"; + fe0_atv_demod = <0>; + }; + + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <2150>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpus 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpu_cluster0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&control>; + cooling-device = <&gpu 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&control>; + cooling-device = <&gpucore 0 2>; + contribution = <1024>; + }; + }; + }; + }; + +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_h_pins>; + + tas5707: tas5707@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + codec_name = "tas5707"; + reg = <0x1B>; + reset_pin = <&gpio GPIODV_4 GPIO_ACTIVE_LOW>; + eq_enable = <0>; + drc_enable = <0>; + status = "okay"; + }; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_dv_pins>; +}; + +&pinctrl_periphs { + /*i2s*/ + aml_audio_i2s: aml_audio_i2s { + mux { + groups = "i2s_mclk_h", + "i2s_sclk_h", + "i2s_lrclk_h", + "i2s_dout01_h6"; + function = "i2s"; + }; + }; + /*spdif*/ + audio_spdif_out_pins: audio_spdif_out_pins { + mux { + groups = "spdif_out_dv"; + function = "spdif_out"; + }; + }; + audio_spdif_out_mute_pins: audio_spdif_out_mute_pins { + mux { + groups = "GPIODV_6"; + function = "gpio_periphs"; + }; + }; + /*pcm*/ + aml_audio_pcm: aml_audio_pcm { + mux { + groups = + "pcm_clk_a_dv", + "pcm_fs_a_dv", + "pcm_in_a_dv", + "pcm_out_a_dv"; + function = "pcm_a"; + }; + }; + + /*lcd_extern*/ + lcd_extern_off_pins:lcd_extern_off_pin { + mux { + groups = "GPIOH_2", + "GPIOH_3"; + function = "gpio_periphs"; + /*output-high;*/ + output-low; + /*input-enable;*/ + }; + }; + + /*backlight*/ + bl_pwm_on_pins:bl_pwm_on_pin { + mux { + groups = "pwm_b"; + function = "pwm_b"; + }; + }; + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { + mux { + groups = "pwm_b"; + function = "pwm_b"; + }; + }; + bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z7"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_6", + "GPIOZ_7"; + function = "gpio_periphs"; + output-low; + }; + }; +}; + +&uart_A { + status = "okay"; +}; + +&audio_data{ + status = "okay"; +}; + +&pwm_AO_ab { + status = "okay"; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_a_pins>; + cs-gpios = <&gpio GPIOZ_3 0>; +}; From b0848aa3b8aa56125ddac336ee1e09de21e82753 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Wed, 23 Jan 2019 13:14:25 +0800 Subject: [PATCH 0532/1060] vbi: use dma alloc instead reserved memory [1/1] PD#SWPL-4510 Problem: do not use reserved memory Solution: use dma_alloc_coherent instead reserved memory Verify: x301 Change-Id: I6498772809c8f1f48a7d4dd24aa18433eff3e618 Signed-off-by: Nian Jing Conflicts: arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 114 ++++++++++++++++++ arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 9 -- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 114 ++++++++++++++++++ arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts | 8 -- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 8 -- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 9 -- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 9 -- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 9 -- .../boot/dts/amlogic/txlx_t962e_r321.dts | 8 -- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 8 -- .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 8 -- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 8 -- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 8 -- .../boot/dts/amlogic/txlx_t962x_r314.dts | 8 -- .../amlogic/media/vin/tvin/tvafe/tvafe_vbi.c | 43 +++---- 15 files changed, 248 insertions(+), 123 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index d50d4114e4e6..fcd83598d511 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -110,6 +110,38 @@ alignment = <0x400000>; }; + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -445,6 +477,88 @@ tv_bit_mode = <0x15>; }; + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + unifykey { compatible = "amlogic, unifykey"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 436726743f90..6c1486fef32d 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -136,13 +136,6 @@ alignment = <0x400000>; }; - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; - /*di CMA pool */ di_cma_reserved:linux,di_cma { compatible = "shared-dma-pool"; @@ -571,10 +564,8 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; cvbsout { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 300c206735a7..81f2a08ef6cb 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -128,6 +128,38 @@ alignment = <0x400000>; }; + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -466,6 +498,88 @@ tv_bit_mode = <0x15>; }; + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + unifykey { compatible = "amlogic, unifykey"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index 3d8cb6352dac..6c1350049843 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -162,12 +162,6 @@ alignment = <0x400000>; }; - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x1f800000 0x800000>; - }; }; /* for external keypad */ @@ -568,11 +562,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index c99e90f27afb..913250053e81 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -153,12 +153,6 @@ alignment = <0x400000>; }; - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0 0x30000000>; - }; }; /* for external keypad */ @@ -611,11 +605,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 81ff45f15d12..50b99d0d4cb8 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -166,13 +166,6 @@ size = <0x01400000>; alignment = <0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; }; amlogic_battery:dummy-battery { @@ -575,11 +568,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index 4ad29dbd091c..c44468a42e94 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -163,13 +163,6 @@ size = <0x01400000>; alignment = <0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0 0x30000000>; - }; }; amlogic_battery:dummy-battery { @@ -571,11 +564,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index f4e21c905bfb..24e1b93a9ad3 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -169,13 +169,6 @@ alignment = <0x400000>; alloc-ranges = <0x0 0x30000000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; }; amlogic_battery:dummy-battery { @@ -578,11 +571,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index 2382792628c0..f66847df76bc 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -161,12 +161,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; /* for external keypad */ @@ -567,11 +561,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 503e35b48481..d2899aa2d515 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -152,12 +152,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; /* for external keypad */ @@ -610,11 +604,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index f9646d3694c6..e9dc340f3a8e 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -164,12 +164,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -572,11 +566,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 8348ffb6e196..c89d29b78dd1 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -164,12 +164,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -572,11 +566,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index e7d7721e6393..0cacff78d2b8 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -164,12 +164,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -571,11 +565,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 5c8a29eff0f5..a44d15fc93e0 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -165,12 +165,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -573,11 +567,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c index ee3257828357..cd9d01e6c8ac 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include /* #include */ @@ -1513,6 +1514,7 @@ static int vbi_probe(struct platform_device *pdev) int ret = 0; struct resource *res; struct vbi_dev_s *vbi_dev; + dma_addr_t vbi_dma_addr; /* allocate memory for the per-device structure */ vbi_dev = kzalloc(sizeof(struct vbi_dev_s), GFP_KERNEL); @@ -1520,7 +1522,7 @@ static int vbi_probe(struct platform_device *pdev) ret = -ENOMEM; goto fail_kzalloc_mem; } - memset(vbi_dev, 0, sizeof(struct vbi_dev_s)); + memset(vbi_dev, 0, sizeof(struct vbi_dev_s)); vbi_mem_start = 0; /* connect the file operations with cdev */ @@ -1547,34 +1549,27 @@ static int vbi_probe(struct platform_device *pdev) goto fail_create_dbg_file; } - /* get device memory */ - res = &vbi_memobj; - ret = of_reserved_mem_device_init(&pdev->dev); - if (ret == 0) - tvafe_pr_info("\n vbi memory resource done.\n"); - else - tvafe_pr_info("vbi: can't get memory resource\n"); - vbi_dev->mem_start = res->start; - vbi_dev->mem_size = res->end - res->start + 1; - if (vbi_dev->mem_size > DECODER_VBI_SIZE) - vbi_dev->mem_size = DECODER_VBI_SIZE; - tvafe_pr_info(": start_addr is:0x%x, size is:0x%x\n", - vbi_dev->mem_start, vbi_dev->mem_size); + /*vbi memory alloc*/ + vbi_dev->mem_size = DECODER_VBI_SIZE; + vbi_dev->pac_addr_start = dma_alloc_coherent(&pdev->dev, + vbi_dev->mem_size, &vbi_dma_addr, GFP_KERNEL); + vbi_dev->mem_start = (unsigned int)vbi_dma_addr; + if (vbi_dev->pac_addr_start == NULL) { + tvafe_pr_err(": dma_alloc_coherent failed!!!\n"); + goto fail_alloc_mem; + } + tvafe_pr_info("vbi: dma_alloc phy start_addr is:0x%x, size is:0x%x\n", + vbi_dev->mem_start, vbi_dev->mem_size); - /* remap the package vbi hardware address for our conversion */ - vbi_dev->pac_addr_start = phys_to_virt(vbi_dev->mem_start); - /*ioremap_nocache(vbi_dev->mem_start, vbi_dev->mem_size);*/ memset(vbi_dev->pac_addr_start, 0, vbi_dev->mem_size); vbi_dev->mem_size = vbi_dev->mem_size/2; vbi_dev->mem_size >>= 4; vbi_dev->mem_size <<= 4; vbi_mem_start = vbi_dev->mem_start; vbi_dev->pac_addr_end = vbi_dev->pac_addr_start + vbi_dev->mem_size - 1; - if (vbi_dev->pac_addr_start == NULL) - tvafe_pr_err(": ioremap error!!!\n"); - else - tvafe_pr_info(": vbi_dev->pac_addr_start=0x%p, end:0x%p, size:0x%x .......\n", - vbi_dev->pac_addr_start, vbi_dev->pac_addr_end, vbi_dev->mem_size); + tvafe_pr_info(": vbi_dev->pac_addr_start=0x%p, end:0x%p, size:0x%x\n", + vbi_dev->pac_addr_start, vbi_dev->pac_addr_end, + vbi_dev->mem_size); vbi_dev->pac_addr = vbi_dev->pac_addr_start; mutex_init(&vbi_dev->mutex); @@ -1643,7 +1638,9 @@ static int vbi_remove(struct platform_device *pdev) mutex_destroy(&vbi_dev->mutex); tasklet_kill(&vbi_dev->tsklt_slicer); if (vbi_dev->pac_addr_start) - iounmap(vbi_dev->pac_addr_start); + dma_free_coherent(vbi_dev->dev, vbi_dev->mem_size, + vbi_dev->pac_addr_start, + (dma_addr_t)&vbi_dev->mem_start); vfree(vbi_dev->slicer); device_destroy(vbi_clsp, MKDEV(MAJOR(vbi_id), 0)); cdev_del(&vbi_dev->cdev); From 16bcc9b900c4b5edcb303e92740b4c8609bd62f4 Mon Sep 17 00:00:00 2001 From: "bing.jiang" Date: Wed, 23 Jan 2019 09:35:18 +0800 Subject: [PATCH 0533/1060] dts: Add new dts files for S400 SBR [1/3] PD#SWPL-4435 Problem: adapt Soundbar solution to S400 SBR platform Solution: new dts file axg_s400_v03sbr.dts changed from axg_s400_v03.dts add reference remote control mapping in mesonaxg.dtsi add tas5782m Verify: S400+D621 A113D Change-Id: I6feee3993192656eb66b7ee5a9ff6c85d22075e4 Signed-off-by: bing.jiang Signed-off-by: yujie.wu Conflicts: MAINTAINERS sound/soc/codecs/amlogic/tas5782m.c --- MAINTAINERS | 20 +- arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts | 1695 +++++++++++++++++ .../configs/meson64_a32_smarthome_defconfig | 1 + .../boot/dts/amlogic/axg_s400_v03sbr.dts | 1695 +++++++++++++++++ .../arm64/configs/meson64_smarthome_defconfig | 1 + sound/soc/codecs/amlogic/Kconfig | 12 + sound/soc/codecs/amlogic/Makefile | 2 + sound/soc/codecs/amlogic/tas5782m.h | 1521 +++++++++++++++ 8 files changed, 4943 insertions(+), 4 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts create mode 100644 arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts create mode 100644 sound/soc/codecs/amlogic/tas5782m.h diff --git a/MAINTAINERS b/MAINTAINERS index e74899514952..1070790644b6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14815,10 +14815,22 @@ M: Shunzhou Jiang F: drivers/amlogic/power/power_ctrl.c F: include/linux/amlogic/power_ctrl.h -AMLOGIC SM1 DTS -M: shaochan.liu -F: arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi -F: arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi +AMLOGIC MESONAXG S400 GVA SBR DTS +M: Yeping Miao +F: arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts +F: arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts + +AMLOGIC TL1 DTS +M: Huijie Huang +F: arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +F: arch/arm/boot/dts/amlogic/tl1_t962x2_x301_2g.dts +F: arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +F: arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts + +AMLOGIC TM2 PINCTRL DRIVER +M: Qianggui Song +F: drivers/amlogic/pinctrl/pinctrl-meson-tm2.c +F: include/dt-bindings/gpio/meson-tm2-gpio.h AMLOGIC TL1 VAD diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts new file mode 100644 index 000000000000..55f80117e55f --- /dev/null +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -0,0 +1,1695 @@ +/* + * arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/*#include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x3e000000 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + alloc-ranges = <0x3e000000 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0xFFE07800 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + misc{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0xF00000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0xffe09000 0x80 + 0xffd01008 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0xffe09080 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0xf9800000 0x400000 + 0xff646000 0x2000 + 0xf9f00000 0x100000 + PCIE_PHY_REG PCIE_PHY_SIZE + PCIE_RESET_REG PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0xfa000000 0x400000 + 0xff648000 0x2000 + 0xfa400000 0x100000 + PCIE_PHY_REG PCIE_PHY_SIZE + PCIE_RESET_REG PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF632000 0x2000>; + }; + audiobus_base { + reg = <0xFF642000 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0xffe07000 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0xffe05000 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; + key_num = <6>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106>; + key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 0>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + aml_pca9557: aml_pca9557@0x1f { + compatible = "aml, ledring"; + reg = <0x1f>; + mode = <0>; /*0: 6-led 1: 4key+2led */ + key_num = <4>; + led_dev_name = "aml_ledring"; + key_dev_name = "aml_pca_key"; + key_name = "mute", "pause", "vol+", "vol-"; + key_value = <200 201 202 203>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disabled"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disabled"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + }; + + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disabled"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disabled"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disabled"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236"; + reg = <0x3c>; + status = "disabled"; + led1_r { + label="LED1_R"; + reg_offset = <24>; + }; + led1_g { + label="LED1_G"; + reg_offset = <23>; + }; + led1_b { + label="LED1_B"; + reg_offset = <22>; + }; + led2_r { + label="LED2_R"; + reg_offset = <21>; + }; + led2_g { + label="LED2_G"; + reg_offset = <20>; + }; + led2_b { + label="LED2_B"; + reg_offset = <19>; + }; + led3_r { + label="LED3_R"; + reg_offset = <18>; + }; + led3_g { + label="LED3_G"; + reg_offset = <17>; + }; + led3_b { + label="LED3_B"; + reg_offset = <16>; + }; + led4_r { + label="LED4_R"; + reg_offset = <15>; + }; + led4_g { + label="LED4_G"; + reg_offset = <14>; + }; + led4_b { + label="LED4_B"; + reg_offset = <13>; + }; + led5_r { + label="LED5_R"; + reg_offset = <36>; + }; + led5_g { + label="LED5_G"; + reg_offset = <35>; + }; + led5_b { + label="LED5_B"; + reg_offset = <34>; + }; + led6_r { + label="LED6_R"; + reg_offset = <33>; + }; + led6_g { + label="LED6_G"; + reg_offset = <32>; + }; + led6_b { + label="LED6_B"; + reg_offset = <31>; + }; + led7_r { + label="LED7_R"; + reg_offset = <30>; + }; + led7_g { + label="LED7_G"; + reg_offset = <29>; + }; + led7_b { + label="LED7_B"; + reg_offset = <28>; + }; + led8_r { + label="LED8_R"; + reg_offset = <27>; + }; + led8_g { + label="LED8_G"; + reg_offset = <26>; + }; + led8_b { + label="LED8_B"; + reg_offset = <25>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <22>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + >; + }; + }; diff --git a/arch/arm/configs/meson64_a32_smarthome_defconfig b/arch/arm/configs/meson64_a32_smarthome_defconfig index d7d9c56f2164..8705513d42aa 100644 --- a/arch/arm/configs/meson64_a32_smarthome_defconfig +++ b/arch/arm/configs/meson64_a32_smarthome_defconfig @@ -425,6 +425,7 @@ CONFIG_AMLOGIC_SND_CODEC_PCM2BT=y CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y +CONFIG_AMLOGIC_SND_SOC_TAS5782M=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts new file mode 100644 index 000000000000..2ed30851891d --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -0,0 +1,1695 @@ +/* + * arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/* #include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x0 0x3e000000 0x0 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + misc{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0xF00000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0x0 0xffe09080 0x0 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xf9800000 0x0 0x400000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xf9f00000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xfa000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfa400000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0x0 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF632000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe07000 0x0 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe05000 0x0 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; + key_num = <6>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106>; + key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + tas5707_36: tas5707_36@36 { + compatible = "ti, tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti, tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board : /dev/i2c-1 */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + aml_pca9557: aml_pca9557@0x1f { + compatible = "aml, ledring"; + reg = <0x1f>; + mode = <0>; /*0: 6-led 1: 4key+2led */ + key_num = <4>; + led_dev_name = "aml_ledring"; + key_dev_name = "aml_pca_key"; + key_name = "mute", "pause", "vol+", "vol-"; + key_value = <200 201 202 203>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disabled"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disabled"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + }; + + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disabled"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disabled"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disabled"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236"; + reg = <0x3c>; + status = "disabled"; + led1_r { + label="LED1_R"; + reg_offset = <24>; + }; + led1_g { + label="LED1_G"; + reg_offset = <23>; + }; + led1_b { + label="LED1_B"; + reg_offset = <22>; + }; + led2_r { + label="LED2_R"; + reg_offset = <21>; + }; + led2_g { + label="LED2_G"; + reg_offset = <20>; + }; + led2_b { + label="LED2_B"; + reg_offset = <19>; + }; + led3_r { + label="LED3_R"; + reg_offset = <18>; + }; + led3_g { + label="LED3_G"; + reg_offset = <17>; + }; + led3_b { + label="LED3_B"; + reg_offset = <16>; + }; + led4_r { + label="LED4_R"; + reg_offset = <15>; + }; + led4_g { + label="LED4_G"; + reg_offset = <14>; + }; + led4_b { + label="LED4_B"; + reg_offset = <13>; + }; + led5_r { + label="LED5_R"; + reg_offset = <36>; + }; + led5_g { + label="LED5_G"; + reg_offset = <35>; + }; + led5_b { + label="LED5_B"; + reg_offset = <34>; + }; + led6_r { + label="LED6_R"; + reg_offset = <33>; + }; + led6_g { + label="LED6_G"; + reg_offset = <32>; + }; + led6_b { + label="LED6_B"; + reg_offset = <31>; + }; + led7_r { + label="LED7_R"; + reg_offset = <30>; + }; + led7_g { + label="LED7_G"; + reg_offset = <29>; + }; + led7_b { + label="LED7_B"; + reg_offset = <28>; + }; + led8_r { + label="LED8_R"; + reg_offset = <27>; + }; + led8_g { + label="LED8_G"; + reg_offset = <26>; + }; + led8_b { + label="LED8_B"; + reg_offset = <25>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <22>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + >; + }; + }; diff --git a/arch/arm64/configs/meson64_smarthome_defconfig b/arch/arm64/configs/meson64_smarthome_defconfig index 171ceffa64d1..a82fb252a5ea 100644 --- a/arch/arm64/configs/meson64_smarthome_defconfig +++ b/arch/arm64/configs/meson64_smarthome_defconfig @@ -417,6 +417,7 @@ CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015S=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y +CONFIG_AMLOGIC_SND_SOC_TAS5782M=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y diff --git a/sound/soc/codecs/amlogic/Kconfig b/sound/soc/codecs/amlogic/Kconfig index b4cd38258572..f0573fc444cf 100644 --- a/sound/soc/codecs/amlogic/Kconfig +++ b/sound/soc/codecs/amlogic/Kconfig @@ -101,6 +101,18 @@ config AMLOGIC_SND_CODEC_TL1_ACODEC #Third part codecs # Amlogic add codecs + +config AMLOGIC_SND_SOC_TAS5782M + bool "Texas Instruments TAS5782M amplifier" + depends on AMLOGIC_SND_SOC_CODECS + depends on I2C + default n + help + Enable support for Texas Instruments TAS5782M CODEC. + Select this if your TAS5782M is connected via an I2C bus. + Enable support for Texas Instruments TAS5782M CODEC. + Select this if your TAS5782M is connected via an I2C bus. + config AMLOGIC_SND_SOC_TAS5707 bool "Texas Instruments TAS5707 amplifier" depends on AMLOGIC_SND_SOC_CODECS diff --git a/sound/soc/codecs/amlogic/Makefile b/sound/soc/codecs/amlogic/Makefile index e1fdb3b653d7..348a63471f87 100644 --- a/sound/soc/codecs/amlogic/Makefile +++ b/sound/soc/codecs/amlogic/Makefile @@ -12,6 +12,7 @@ snd-soc-aml_codec_txlx_acodec-objs := aml_codec_txlx_acodec.o snd-soc-aml_codec_tl1_acodec-objs := aml_codec_tl1_acodec.o #Third part codecs +snd-soc-tas5782m-objs := tas5782m.o snd-soc-tas5707-objs := tas5707.o snd-soc-tlv320adc3101-objs := tlv320adc3101.o snd-soc-pcm186x-objs := pcm186x.o pcm186x-i2c.o pcm186x-spi.o @@ -31,6 +32,7 @@ obj-$(CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC) += snd-soc-aml_codec_txlx_acodec.o obj-$(CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC) += snd-soc-aml_codec_tl1_acodec.o #Third part codecs +obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5782M) += snd-soc-tas5782m.o obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5707) += snd-soc-tas5707.o obj-$(CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101) += snd-soc-tlv320adc3101.o obj-$(CONFIG_AMLOGIC_SND_SOC_PCM186X) += snd-soc-pcm186x.o diff --git a/sound/soc/codecs/amlogic/tas5782m.h b/sound/soc/codecs/amlogic/tas5782m.h new file mode 100644 index 000000000000..6cc83d0e5cc0 --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5782m.h @@ -0,0 +1,1521 @@ +/* + * sound/soc/codecs/amlogic/tas5782m.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#ifndef _TAS5782M_H +#define _TAS5782M_H + +#include + + +#define CFG_META_SWITCH (255) +#define CFG_META_DELAY (254) +#define CFG_META_BURST (253) + +#define WORK_MODE_I2S 0 +#define WORK_MODE_TDM 1 + +#define WORK_MODE WORK_MODE_I2S + +static const struct reg_default tas5782m_reg_defaults[] = { + //program memory + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x11 }, + { CFG_META_BURST, 2 }, + { 0x01, 0x11 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x03, 0x11 }, + { CFG_META_BURST, 2 }, + { 0x2a, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x25, 0x18 }, + { CFG_META_BURST, 2 }, + { 0x0d, 0x10 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x00 }, + + //Sample rate update + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x80 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + + // speed 03-48k 04-96k + //dynamically reading speed + { CFG_META_BURST, 2 }, + { 0x22, 0x03 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x00 }, + + //write coefficients of various components + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x28, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x34, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x40, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x24, 0x00 }, + { 0x20, 0xc4 }, + { 0x9c, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x11 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x12 }, + { CFG_META_BURST, 21 }, + { 0x44, 0xff }, + { 0x84, 0x59 }, + { 0x16, 0xff }, + { 0x84, 0x59 }, + { 0x16, 0xff }, + { 0x84, 0x59 }, + { 0x16, 0x70 }, + { 0x46, 0x2b }, + { 0x3b, 0x9d }, + { 0x85, 0x0d }, + { 0xe2, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x13 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x13 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x4f }, + { 0x9d, 0xf9 }, + { 0x35, 0xb0 }, + { 0x62, 0x06 }, + { 0xcb, 0x4f }, + { 0x9d, 0xf9 }, + { 0x35, 0x49 }, + { 0xe6, 0x9d }, + { 0x16, 0xd5 }, + { 0x55, 0x55 }, + { 0x56, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7c }, + { 0xb6, 0xa4 }, + { 0xbc, 0x83 }, + { 0x49, 0x5b }, + { 0x44, 0x7c }, + { 0xb6, 0xa4 }, + { 0xbc, 0x7c }, + { 0xb1, 0x2c }, + { 0x1e, 0x86 }, + { 0x87, 0xc5 }, + { 0x49, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x05 }, + { 0xb7, 0x5c }, + { 0x1f, 0x05 }, + { 0xb7, 0x5c }, + { 0x1f, 0x05 }, + { 0xb7, 0x5c }, + { 0x1f, 0x49 }, + { 0xe6, 0x9d }, + { 0x16, 0xd5 }, + { 0x55, 0x55 }, + { 0x56, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x08 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x44, 0x08 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 5 }, + { 0x58, 0x00 }, + { 0xe2, 0xc4 }, + { 0x6b, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { 0x02, 0xbb }, + { 0x06, 0x00 }, + { 0x03, 0x69 }, + { 0xc5, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1b }, + { CFG_META_BURST, 21 }, + { 0x08, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0xf9 }, + { 0xda, 0xbc }, + { 0x21, 0xfc }, + { 0x58, 0x8b }, + { 0x89, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1b }, + { CFG_META_BURST, 41 }, + { 0x1c, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { 0x02, 0xbb }, + { 0x06, 0x00 }, + { 0x03, 0x69 }, + { 0xc5, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0xf9 }, + { 0xda, 0xbc }, + { 0x21, 0xfc }, + { 0x58, 0x8b }, + { 0x89, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1b }, + { CFG_META_BURST, 41 }, + { 0x44, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { 0x02, 0xbb }, + { 0x06, 0x00 }, + { 0x03, 0x69 }, + { 0xc5, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0xf9 }, + { 0xda, 0xbc }, + { 0x21, 0xfc }, + { 0x58, 0x8b }, + { 0x89, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1c }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x20, 0x1c }, + { 0x1b, 0xf0 }, + { 0x41, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x24, 0x04 }, + { 0x0c, 0x37 }, + { 0x14, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x2c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x34, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x38, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x40, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x44, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x48, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x58, 0x00 }, + { 0x00, 0x00 }, + { 0x01, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x5c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x60, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x64, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x68, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x74, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x78, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x7c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x08, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x0c, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x10, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x14, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x18, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x20, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x24, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x28, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x2c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x30, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x34, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x38, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x3c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x40, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x44, 0x00 }, + { 0x00, 0x00 }, + { 0x1b, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x48, 0x00 }, + { 0x00, 0x00 }, + { 0x1b, 0x00 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x50, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x54, 0x04 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x58, 0x04 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x14, 0x00 }, + { 0xce, 0xc0 }, + { 0x8a, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x18, 0x0a }, + { 0x0a, 0xae }, + { 0xd2, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x03, 0x69 }, + { 0xd0, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x20, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x28, 0x75 }, + { 0xf5, 0x51 }, + { 0x2e, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x2c, 0x00 }, + { 0x00, 0x57 }, + { 0x62, 0x00 }, + + //swap command + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x23 }, + { CFG_META_BURST, 5 }, + { 0x14, 0x00 }, + { 0x00, 0x00 }, + { 0x01, 0x00 }, + + //register tuning + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x07, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x08, 0x20 }, + { CFG_META_BURST, 2 }, + { 0x55, 0x07 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x3d, 0x30 }, + { CFG_META_BURST, 2 }, + { 0x3e, 0x30 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x01 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x00 }, + + //Unmute the device + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x03, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x2a, 0x11 }, + + //start set volume + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x3d, 0x4f }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x3e, 0x4f }, + //end set volume +}; + +#endif From 5da86d3349a7c0e942c23139078252b5eeed30f0 Mon Sep 17 00:00:00 2001 From: Yinming Ding Date: Thu, 14 Feb 2019 13:59:19 +0800 Subject: [PATCH 0534/1060] device: amlogic: Add config for dtv tuner si2169 [2/3] PD#SWPL-2763 Problem: Add config for dtv tuner si2169 Solution: Add dtv tuner si2169 as default Temp disable spdif pin mux and uart_A because GPIO conflict Verify: Verified by R314 Change-Id: I2557043e9d34ef8db8048eab9cd53d04c26c29c4 Signed-off-by: Yinming Ding Conflicts: arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts --- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 92 +++++++++++-------- .../boot/dts/amlogic/txlx_t962x_r314.dts | 91 ++++++++++-------- 2 files changed, 103 insertions(+), 80 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 24e1b93a9ad3..16a8f9fb5760 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -623,21 +623,24 @@ }; tuner: tuner { - status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + compatible = "amlogic, tuner"; + status = "disabled"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { compatible = "amlogic, atv-demod"; - status = "okay"; + status = "disabled"; tuner = <&tuner>; btsc_sap_mode = <1>; /* pinctrl-names="atvdemod_agc_pins"; */ @@ -1207,8 +1210,9 @@ #sound-dai-cells = <0>; compatible = "amlogic, aml-spdif-codec"; pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute"; - pinctrl-0 = <&audio_spdif_out_pins>; - pinctrl-1 = <&audio_spdif_out_mute_pins>; + /* disable spdif pin mux temporary, enable it if necessary */ + /*pinctrl-0 = <&audio_spdif_out_pins>;*/ + /*pinctrl-1 = <&audio_spdif_out_mute_pins>;*/ }; pcm_codec: pcm_codec{ @@ -1335,12 +1339,17 @@ compatible = "amlogic, dvb"; dev_name = "dvb"; status = "okay"; - fe0_mode = "internal"; - fe0_tuner = <&tuner>; - /*"parallel","serial","disable"*/ - ts2 = "parallel"; - ts2_control = <0>; - ts2_invert = <0>; + fe0_mode = "external"; + fe0_demod = "Si2168"; + fe0_i2c_adap_id = <&i2c1>; + fe0_demod_i2c_addr = <0x64>; + fe0_ts = <0>; + fe0_reset_value = <0>; + fe0_reset_gpio = <&gpio GPIODV_6 GPIO_ACTIVE_HIGH>; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; interrupts = <0 23 1 0 5 1 0 53 1 @@ -1355,16 +1364,31 @@ "dvr1_irq", "dvrfill0_fill", "dvrfill1_flush"; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; clocks = <&clkc CLKID_DEMUX &clkc CLKID_ASYNC_FIFO &clkc CLKID_AHB_ARB0 &clkc CLKID_DOS_PARSER>; clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; }; + + dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:spi,2:cimax + cimax { + io_type = <1>;//0:spi,1:usb + usb { + rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + }; + }; + }; + aml_dtv_demod { compatible = "amlogic, ddemod-txlx"; dev_name = "aml_dtv_demod"; - status = "okay"; + status = "disabled"; //pinctrl-names="dtvdemod_agc"; //pinctrl-0=<&dtvdemod_agc>; @@ -1386,28 +1410,6 @@ cma_mem_size = <8>; memory-region = <&demod_cma_reserved>;//<&demod_reserved>; }; - dvbfe { - compatible = "amlogic, dvbfe"; - dev_name = "dvbfe"; - status = "disabled"; - dtv_demod0 = "AMLDEMOD"; - fe0_dtv_demod = <0>; - fe0_ts = <2>; - fe0_dev = <0>; - dtv_demod0_mem = <0>; - dtv_demod0_spectrum = <1>; - dtv_demod0_cma_flag = <1>; - dtv_demod0_cma_mem_size = <8>; - memory-region = <&demod_cma_reserved>;//<&demod_reserved>; - tuner0 = "si2151_tuner"; - tuner0_i2c_adap_id = <2>; - tuner0_i2c_addr = <0x60>; - //tuner0_reset_value = <0>; - //tuner0_reset_gpio = "GPIOY_10" ; /*GPIOX_8 76*/ - fe0_tuner = <0>; - atv_demod0 = "aml_atv_demod"; - fe0_atv_demod = <0>; - }; thermal-zones { soc_thermal { @@ -1612,10 +1614,19 @@ output-low; }; }; + dvb_s_ts0_pins: dvb_s_ts0_pins { + mux { + groups = "tsin_d0_a_dv", + "tsin_clk_a_dv", + "tsin_sop_a_dv", + "tsin_valid_a_dv"; + function = "tsin_a"; + }; + }; }; &uart_A { - status = "okay"; + status = "disabled"; }; &audio_data{ @@ -1640,3 +1651,4 @@ pinctrl-0 = <&spi_a_pins>; cs-gpios = <&gpio GPIOZ_3 0>; }; + diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index a44d15fc93e0..3c25f458df97 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -619,21 +619,24 @@ }; tuner: tuner { - status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + compatible = "amlogic, tuner"; + status = "disabled"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { compatible = "amlogic, atv-demod"; - status = "okay"; + status = "disabled"; tuner = <&tuner>; btsc_sap_mode = <1>; /* pinctrl-names="atvdemod_agc_pins"; */ @@ -1203,8 +1206,9 @@ #sound-dai-cells = <0>; compatible = "amlogic, aml-spdif-codec"; pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute"; - pinctrl-0 = <&audio_spdif_out_pins>; - pinctrl-1 = <&audio_spdif_out_mute_pins>; + /* disable spdif pin mux temporary, enable it if necessary */ + /*pinctrl-0 = <&audio_spdif_out_pins>;*/ + /*pinctrl-1 = <&audio_spdif_out_mute_pins>;*/ }; pcm_codec: pcm_codec{ @@ -1331,12 +1335,17 @@ compatible = "amlogic, dvb"; dev_name = "dvb"; status = "okay"; - fe0_mode = "internal"; - fe0_tuner = <&tuner>; - /*"parallel","serial","disable"*/ - ts2 = "parallel"; - ts2_control = <0>; - ts2_invert = <0>; + fe0_mode = "external"; + fe0_demod = "Si2168"; + fe0_i2c_adap_id = <&i2c1>; + fe0_demod_i2c_addr = <0x64>; + fe0_ts = <0>; + fe0_reset_value = <0>; + fe0_reset_gpio = <&gpio GPIODV_6 GPIO_ACTIVE_HIGH>; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; interrupts = <0 23 1 0 5 1 0 53 1 @@ -1351,16 +1360,31 @@ "dvr1_irq", "dvrfill0_fill", "dvrfill1_flush"; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; clocks = <&clkc CLKID_DEMUX &clkc CLKID_ASYNC_FIFO &clkc CLKID_AHB_ARB0 &clkc CLKID_DOS_PARSER>; clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; }; + + dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:spi,2:cimax + cimax { + io_type = <1>;//0:spi,1:usb + usb { + rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + }; + }; + }; + aml_dtv_demod { compatible = "amlogic, ddemod-txlx"; dev_name = "aml_dtv_demod"; - status = "okay"; + status = "disabled"; //pinctrl-names="dtvdemod_agc"; //pinctrl-0=<&dtvdemod_agc>; @@ -1382,28 +1406,6 @@ cma_mem_size = <8>; memory-region = <&demod_cma_reserved>;//<&demod_reserved>; }; - dvbfe { - compatible = "amlogic, dvbfe"; - dev_name = "dvbfe"; - status = "disabled"; - dtv_demod0 = "AMLDEMOD"; - fe0_dtv_demod = <0>; - fe0_ts = <2>; - fe0_dev = <0>; - dtv_demod0_mem = <0>; - dtv_demod0_spectrum = <1>; - dtv_demod0_cma_flag = <1>; - dtv_demod0_cma_mem_size = <8>; - memory-region = <&demod_cma_reserved>;//<&demod_reserved>; - tuner0 = "si2151_tuner"; - tuner0_i2c_adap_id = <2>; - tuner0_i2c_addr = <0x60>; - //tuner0_reset_value = <0>; - //tuner0_reset_gpio = "GPIOY_10" ; /*GPIOX_8 76*/ - fe0_tuner = <0>; - atv_demod0 = "aml_atv_demod"; - fe0_atv_demod = <0>; - }; thermal-zones { soc_thermal { @@ -1608,10 +1610,19 @@ output-low; }; }; + dvb_s_ts0_pins: dvb_s_ts0_pins { + mux { + groups = "tsin_d0_a_dv", + "tsin_clk_a_dv", + "tsin_sop_a_dv", + "tsin_valid_a_dv"; + function = "tsin_a"; + }; + }; }; &uart_A { - status = "okay"; + status = "disabled"; }; &audio_data{ From b1f23539d727c2036d530d68939da036c89a51fd Mon Sep 17 00:00:00 2001 From: Wenfeng Guo Date: Wed, 20 Feb 2019 16:20:10 +0800 Subject: [PATCH 0535/1060] deinterlace: fix 480i error into pulldown [1/1] PD#TV-1949 Problem: 480i error into pulldown (by yanling) Solution: 1. add flm22_comlev3 (by yanling); Verify: tl1 txlx Change-Id: Ib5c168deb1327df0e803831dcf9f13e05faaa915 Signed-off-by: Wenfeng Guo Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c --- .../deinterlace/film_mode_fmw/film_fw1.c | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c index cd6b46782d14..9fefa75f52c2 100644 --- a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c @@ -1159,6 +1159,10 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, int flm22_comlev1 = pPar->flm22_comlev1; int flm22_comnum = pPar->flm22_comnum; + int dif_flag; + int flm22_min; + int flm22_th; + int cFlg = pFlg[HISDETNUM - 1]; int rFlg[4] = { 2, 3, 4, 1 }; @@ -1558,7 +1562,16 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, nFlm22Lvl -= nT1; } - if (flm22_flag) { + /* ---------------------- */ + /*DI:PQ patch fix 480i error into pulldown22(by yanling)*/ + flm22_min = nDif01[HISDIFNUM-1] > nDif01[HISDIFNUM-2] + ? nDif01[HISDIFNUM-2] : nDif01[HISDIFNUM-1]; + flm22_th = flm22_min/2; + dif_flag = abs(nDif01[HISDIFNUM-1]-nDif01[HISDIFNUM-2]) + > flm22_th ? 1:0; + dif_flag = nDif01[HISDIFNUM-1] > (1<<16) ? dif_flag : 0; + if (flm22_flag && dif_flag) { + /* ---------------------- */ if (pFlg[HISDETNUM-1] == 3 || pFlg[HISDETNUM-1] == 1) { if (comsum > flm22_comnum) { @@ -1581,8 +1594,9 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, if (nFlgCk21 < flm22_chk21_sml) nFlm22Lvl = nFlm22Lvl + flm22_comlev1 - nFlgCk21; if (prt_flg) { - pr_info("nFlm22Lvl=%d, nFlgCk20=%d, nFlgCk21=%d\n", - nFlm22Lvl, nFlgCk20, nFlgCk21); + pr_info("nFlm22Lvl=%d, nFlgCk20=%d, nFlgCk21=%d,flm22_min=%d,flm22_th=%d\n", + nFlm22Lvl, nFlgCk20, nFlgCk21, + flm22_min, flm22_th); } } /* for sony-mp3 */ From ccca5b9ee37c0599fede875813ab244a5623365d Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Mon, 14 Jan 2019 15:53:22 +0800 Subject: [PATCH 0536/1060] CPUFREQ: Setting different cpufreq tables according to efuse information. [1/1] PD#SWPL-4035 Problem: Setting different cpufreq tables according to efuse information. Solution: Setting different cpufreq tables according to efuse information. Verify: g12a_u200, verify pass Change-Id: I1bf571f332244f5727ef3cd8743f215f71248146 Signed-off-by: Hong Guo Conflicts: drivers/amlogic/cpufreq/meson-cpufreq.c --- MAINTAINERS | 1 + .../arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 160 ++++++++++++++++++ .../boot/dts/amlogic/g12a_s905d2_u200.dts | 160 ++++++++++++++++++ drivers/amlogic/cpufreq/meson-cpufreq.c | 134 ++++++++------- drivers/amlogic/cpufreq/meson-cpufreq.h | 70 ++++++++ drivers/base/power/opp/of.c | 98 +++++++++++ include/linux/pm_opp.h | 17 ++ 7 files changed, 578 insertions(+), 62 deletions(-) create mode 100644 drivers/amlogic/cpufreq/meson-cpufreq.h diff --git a/MAINTAINERS b/MAINTAINERS index 1070790644b6..76de795ede0d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14417,6 +14417,7 @@ F: sound/soc/codecs/amlogic/ad82584f.h AMLOGIC CPUFREQS DRIVER M: hong guo +F: drivers/amlogic/cpufreq/meson-cpufreq.h F: drivers/amlogic/cpufreq/meson-cpufreq.c F: drivers/amlogic/clk/clk-cpu-fclk-composite.c diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index 3cca9f5b501c..795a7982de73 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -809,6 +809,122 @@ }; }; + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + cpufreq-meson { compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; @@ -818,6 +934,50 @@ }; /* end of / */ +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index cf6c4c52c1ca..b092b2b77ad5 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -810,6 +810,122 @@ }; }; + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + cpufreq-meson { compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; @@ -819,6 +935,50 @@ }; /* end of / */ +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>; + //<&cpu_opp_table1>, + //<&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index 700e793854bc..2f0c26edfd3f 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -30,60 +30,18 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include "../../regulator/internal.h" +#include #include "../../base/power/opp/opp.h" -/* Currently we support only two clusters */ -#define MAX_CLUSTERS 2 - -/*core power supply*/ -#define CORE_SUPPLY "cpu" - -/* Core Clocks */ -#define CORE_CLK "core_clk" -#define LOW_FREQ_CLK_PARENT "low_freq_clk_parent" -#define HIGH_FREQ_CLK_PARENT "high_freq_clk_parent" - -static struct thermal_cooling_device *cdev[MAX_CLUSTERS]; -static struct clk *clk[MAX_CLUSTERS]; -static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; - -/* Default voltage_tolerance */ -#define DEF_VOLT_TOL 0 - -/*mid rate for set parent,Khz*/ -static unsigned int mid_rate = (1000*1000); -static unsigned int gap_rate = (10*1000*1000); - -struct meson_cpufreq_driver_data { - struct device *cpu_dev; - struct regulator *reg; - /* voltage tolerance in percentage */ - unsigned int volt_tol; - struct clk *high_freq_clk_p; - struct clk *low_freq_clk_p; -}; - -#ifdef CONFIG_ARCH_MESON64_ODROIDN2 -#define OF_NODE_CPU_OPP_0 "/cpu_opp_table0/" /* Core A53 */ -#define OF_NODE_CPU_OPP_1 "/cpu_opp_table1/" /* Core A73 */ - -static unsigned long max_freq[2] = { - 1896000, /* defalut freq for A53 is 1.896GHz */ - 1800000 /* defalut freq for A73 is 1.800GHz */ -}; -#endif - -static DEFINE_PER_CPU(unsigned int, physical_cluster); - -static struct mutex cluster_lock[MAX_CLUSTERS]; +#include "meson-cpufreq.h" static unsigned int meson_cpufreq_get_rate(unsigned int cpu) { @@ -346,6 +304,70 @@ static inline u32 get_table_max(struct cpufreq_frequency_table *table) return max_freq; } +int get_cpufreq_tables_efuse(u32 cur_cluster) +{ + int ret, efuse_info; + u32 freq, vol; + + efuse_info = scpi_get_cpuinfo(cur_cluster, &freq, &vol); + if (efuse_info) + pr_err("%s,get invalid efuse_info = %d by mailbox!\n", + __func__, efuse_info); + + pr_info("%s:efuse info for cpufreq = %u\n", __func__, freq); + WARN_ON(freq && freq < EFUSE_CPUFREQ_MIN); + freq = DIV_ROUND_UP(freq, CLK_DIV) * CLK_DIV; + pr_info("%s:efuse adjust cpufreq = %u\n", __func__, freq); + if (freq >= hispeed_cpufreq_max) + ret = HISPEED_INDEX; + else if (freq >= medspeed_cpufreq_max && freq < hispeed_cpufreq_max) + ret = MEDSPEED_INDEX; + else + ret = LOSPEED_INDEX; + + return ret; +} + +int choose_cpufreq_tables_index(const struct device_node *np, u32 cur_cluster) +{ + int ret = 0; + + cpufreq_tables_supply = of_property_read_bool(np, "diff_tables_supply"); + if (cpufreq_tables_supply) { + /*choose appropriate cpufreq tables according efuse info*/ + if (of_property_read_u32(np, "hispeed_cpufreq_max", + &hispeed_cpufreq_max)) { + pr_err("%s:don't find the node \n", + __func__); + hispeed_cpufreq_max = 0; + return ret; + } + + if (of_property_read_u32(np, "medspeed_cpufreq_max", + &medspeed_cpufreq_max)) { + pr_err("%s:don't find the node \n", + __func__); + medspeed_cpufreq_max = 0; + return ret; + } + + if (of_property_read_u32(np, "lospeed_cpufreq_max", + &lospeed_cpufreq_max)) { + pr_err("%s:don't find the node \n", + __func__); + lospeed_cpufreq_max = 0; + return ret; + } + + ret = get_cpufreq_tables_efuse(cur_cluster); + pr_info("%s:hispeed_max %u,medspeed_max %u,lospeed_max %u,tables_index %u\n", + __func__, hispeed_cpufreq_max, + medspeed_cpufreq_max, lospeed_cpufreq_max, ret); + + } + + return ret; +} /* CPU initialization */ static int meson_cpufreq_init(struct cpufreq_policy *policy) { @@ -358,11 +380,7 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) unsigned int transition_latency = CPUFREQ_ETERNAL; unsigned int volt_tol = 0; unsigned long freq_hz = 0; - int cpu = 0; - int ret = 0; -#ifdef CONFIG_ARCH_MESON64_ODROIDN2 - int i = 0; -#endif + int cpu = 0, ret = 0, tables_index; if (!policy) { pr_err("invalid cpufreq_policy\n"); @@ -435,15 +453,12 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) volt_tol = DEF_VOLT_TOL; pr_info("value of voltage_tolerance %u\n", volt_tol); - if (cur_cluster < MAX_CLUSTERS) { - int cpu; - + if (cur_cluster < MAX_CLUSTERS) cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); - for_each_cpu(cpu, policy->cpus) - per_cpu(physical_cluster, cpu) = cur_cluster; - } - ret = dev_pm_opp_of_cpumask_add_table(policy->cpus); + tables_index = choose_cpufreq_tables_index(np, cur_cluster); + ret = dev_pm_opp_of_cpumask_add_table_indexed(policy->cpus, + tables_index); if (ret) { pr_err("%s: init_opp_table failed, cpu: %d, cluster: %d, err: %d\n", __func__, cpu_dev->id, cur_cluster, ret); @@ -589,11 +604,6 @@ static int meson_cpufreq_exit(struct cpufreq_policy *policy) if (cpufreq_data == NULL) return 0; - if (cur_cluster < MAX_CLUSTERS) { - cpufreq_cooling_unregister(cdev[cur_cluster]); - cdev[cur_cluster] = NULL; - } - cpu_dev = get_cpu_device(policy->cpu); if (!cpu_dev) { pr_err("%s: failed to get cpu%d device\n", __func__, diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.h b/drivers/amlogic/cpufreq/meson-cpufreq.h new file mode 100644 index 000000000000..be5002697042 --- /dev/null +++ b/drivers/amlogic/cpufreq/meson-cpufreq.h @@ -0,0 +1,70 @@ +/* + * drivers/amlogic/cpufreq/meson-cpufreq.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __MESON_CPUFREQ_H +#define __MESON_CPUFREQ_H +/* Currently we support only two clusters */ +#define MAX_CLUSTERS 2 + +/*core power supply*/ +#define CORE_SUPPLY "cpu" + +/* Core Clocks */ +#define CORE_CLK "core_clk" +#define LOW_FREQ_CLK_PARENT "low_freq_clk_parent" +#define HIGH_FREQ_CLK_PARENT "high_freq_clk_parent" + +static struct clk *clk[MAX_CLUSTERS]; +static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; + +/* Default voltage_tolerance */ +#define DEF_VOLT_TOL 0 +#define CLK_DIV 12 +#define EFUSE_CPUFREQ_MIN 1500 +/*mid rate for set parent,Khz*/ +static unsigned int mid_rate = (1000 * 1000); +static unsigned int gap_rate = (10 * 1000 * 1000); + +/*whether use different tables or not*/ +bool cpufreq_tables_supply; +static unsigned int hispeed_cpufreq_max; +static unsigned int medspeed_cpufreq_max; +static unsigned int lospeed_cpufreq_max; +enum cpufreq_index { + LOSPEED_INDEX, + MEDSPEED_INDEX, + HISPEED_INDEX +}; + +struct meson_cpufreq_driver_data { + struct device *cpu_dev; + struct regulator *reg; + /* voltage tolerance in percentage */ + unsigned int volt_tol; + struct clk *high_freq_clk_p; + struct clk *low_freq_clk_p; +}; + +static struct mutex cluster_lock[MAX_CLUSTERS]; +static unsigned int meson_cpufreq_get_rate(unsigned int cpu); +static unsigned int meson_cpufreq_set_rate(struct cpufreq_policy *policy, + u32 cur_cluster, u32 rate); +static int meson_regulator_set_volate(struct regulator *regulator, int old_uv, + int new_uv, int tol_uv); +int get_cpufreq_tables_efuse(u32 cur_cluster); +int choose_cpufreq_tables_index(const struct device_node *np, u32 cur_cluster); +#endif /* __MESON_CPUFREQ_H */ diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index 69379443e5eb..e13a3037effb 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -471,6 +471,59 @@ int dev_pm_opp_of_add_table(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table); +#ifdef CONFIG_AMLOGIC_MODIFY +/** + * dev_pm_opp_of_add_table_indexed() - Initialize indexed opp + *table from device tree + * @dev: device pointer used to lookup OPP table. + * @index: Index number. + * + * Register the initial OPP table with the OPP library for given device only + * using the "operating-points-v2" property. + * + * Return: + * 0 On success OR + * Duplicate OPPs (both freq and volt are same) and opp->available + * -EEXIST Freq are same and volt are different OR + * Duplicate OPPs (both freq and volt are same) and !opp->available + * -ENOMEM Memory allocation failure + * -ENODEV when 'operating-points' property is not found or is invalid data + * in device node. + * -ENODATA when empty 'operating-points' property is found + * -EINVAL when invalid entries are found in opp-v2 table + */ +int dev_pm_opp_of_add_table_indexed(struct device *dev, int index) +{ + struct device_node *opp_np; + int ret, count; + +again: + opp_np = of_parse_phandle(dev->of_node, "operating-points-v2", index); + if (!opp_np) { + /* + * If only one phandle is present, then the same OPP table + * applies for all index requests. + */ + count = of_count_phandle_with_args(dev->of_node, + "operating-points-v2", NULL); + if (count <= index) { + pr_err("%s,count %d must smaller than index %d!\n", + __func__, count, index); + index = 0; + goto again; + } + + return -ENODEV; + } + + ret = _of_add_opp_table_v2(dev, opp_np); + of_node_put(opp_np); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed); +#endif + /* CPU device specific helpers */ /** @@ -534,6 +587,51 @@ int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask) } EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table); +#ifdef CONFIG_AMLOGIC_MODIFY +/** + * dev_pm_opp_of_cpumask_add_table_index() - Adds OPP table for @cpumask + * @cpumask: cpumask for which OPP table needs to be added. + * + * This adds the OPP tables for CPUs present in the @cpumask. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +int dev_pm_opp_of_cpumask_add_table_indexed(const struct cpumask *cpumask, + int index) +{ + struct device *cpu_dev; + int cpu, ret = 0; + + WARN_ON(cpumask_empty(cpumask)); + + for_each_cpu(cpu, cpumask) { + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) { + pr_err("%s: failed to get cpu%d device\n", __func__, + cpu); + continue; + } + + ret = dev_pm_opp_of_add_table_indexed(cpu_dev, index); + if (ret) { + pr_err("%s: couldn't find opp table for cpu:%d, %d\n", + __func__, cpu, ret); + + /* Free all other OPPs */ + dev_pm_opp_of_cpumask_remove_table(cpumask); + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table_indexed); +#endif + /* * Works only for OPP v2 bindings. * diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index f6bc76501912..21effa78c27f 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -207,6 +207,11 @@ static inline void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask int dev_pm_opp_of_add_table(struct device *dev); void dev_pm_opp_of_remove_table(struct device *dev); int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask); +#ifdef CONFIG_AMLOGIC_MODIFY +int dev_pm_opp_of_add_table_indexed(struct device *dev, int index); +int dev_pm_opp_of_cpumask_add_table_indexed(const struct cpumask *cpumask, + int index); +#endif void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask); int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask); #else @@ -224,6 +229,18 @@ static inline int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask) return -ENOTSUPP; } +#ifdef CONFIG_AMLOGIC_MODIFY +int dev_pm_opp_of_add_table_indexed(struct device *dev, int index) +{ + return -ENOTSUPP; +} + +int dev_pm_opp_of_cpumask_add_table_indexed(const struct cpumask *cpumask, + int index) +{ + return -ENOTSUPP; +} +#endif static inline void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask) { } From fb722a947a71aff0fc373026c7f655fd87b24295 Mon Sep 17 00:00:00 2001 From: Huan Biao Date: Thu, 28 Feb 2019 09:51:56 +0800 Subject: [PATCH 0537/1060] arm: dts: add ipa parameter [1/1] PD#SWPL-5198 Problem: tl1 thermal cts case fail. Solution: tl1 add thermal dts. Verify: tl1 x301 pass. Change-Id: I47f8e295f0ddc546f4540a8edd96556755ceef66 Signed-off-by: Huan Biao Conflicts: arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 12 +++---- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 34 +++++++++++++++++-- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 6c1486fef32d..6c135b59028d 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -995,9 +995,9 @@ }; }; ddr_thermal: ddr_thermal { - polling-delay = <1000>; - polling-delay-passive = <250>; - sustainable-power = <1680>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { @@ -1023,9 +1023,9 @@ }; }; sar_thermal: sar_thermal { - polling-delay = <1000>; - polling-delay-passive = <250>; - sustainable-power = <1680>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; thermal-sensors = <&s_tsensor 2>; trips { sswitch_on: trip-point@0 { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 81f2a08ef6cb..fd1faa459f7d 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -922,9 +922,9 @@ }; }; ddr_thermal: ddr_thermal { - polling-delay = <1000>; - polling-delay-passive = <250>; - sustainable-power = <1460>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { @@ -949,6 +949,34 @@ }; }; }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; }; /*thermal zone end*/ /*DCDC for MP8756GD*/ From 564ce6cd6854b70bd4b1f544779bfe04976b395b Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Thu, 28 Feb 2019 20:00:22 +0800 Subject: [PATCH 0538/1060] tvafe: fix pali recognize for palcn [1/1] PD#SWPL-3395 Problem: recognized fsc358 flag when signal weak Solution: increase fsc358-flag recognized threshold avoid fsc443 be recognized as fsc358 Verify: verify on x301 Change-Id: I7b759bd0621c153e5abd3dee8fdf55a2426400a7 Signed-off-by: Nian Jing Conflicts: drivers/amlogic/atv_demod/atv_demod_ops.c drivers/amlogic/atv_demod/atvdemod_func.c --- drivers/amlogic/atv_demod/atv_demod_ops.c | 16 +++-- drivers/amlogic/atv_demod/atvdemod_func.c | 60 +++++++++++++++++++ .../amlogic/media/vin/tvin/tvafe/tvafe_cvd.c | 19 +++--- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index 9fd8cad431b6..baadebe19f72 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -252,7 +252,8 @@ static void atv_demod_set_params(struct dvb_frontend *fe, * but when the input signal frequency offset -0.25MHz, * demod will be unlocked. That's very strange. */ - if (reconfig || amlatvdemod_devp->std != p->param.std || + if (reconfig || !priv->scanning || + amlatvdemod_devp->std != p->param.std || amlatvdemod_devp->audmode != p->param.audmode || amlatvdemod_devp->if_freq != p->if_freq || amlatvdemod_devp->if_inv != p->if_inv || @@ -653,9 +654,16 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, #endif } else { /* V4L2_COLOR_STD_PAL */ - amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); - broad_std = aml_audiomode_autodet(v4l2_fe); - audio = atvdemod_fmt_2_v4l2_std(broad_std); + if (cvbs_std == TVIN_SIG_FMT_CVBS_PAL_M || + cvbs_std == TVIN_SIG_FMT_CVBS_PAL_CN) { + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + audio = V4L2_STD_PAL_M; + } else { + amlatvdemod_set_std( + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); + broad_std = aml_audiomode_autodet(v4l2_fe); + audio = atvdemod_fmt_2_v4l2_std(broad_std); + } #if 0 /* Why do this to me? We need support PAL_M.*/ if (audio == V4L2_STD_PAL_M) { audio = atvdemod_fmt_2_v4l2_std(broad_std_except_pal_m); diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 90c953673c89..29e41687b3b5 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -261,6 +261,66 @@ void atv_dmd_misc(void) carrier_amplif_val); } + if (audio_atv_ov) { + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0x8000015); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x18, 0x7ffff); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x0f000); + atvaudio_ctrl_read(®); + atvaudio_ctrl_write(reg & (~0x3)); + audio_atv_ov_flag = 1; + } else { + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0xf400000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x18, 0xc000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x1f000); + atvaudio_ctrl_read(®); + atvaudio_ctrl_write(reg | 0x3); + audio_atv_ov_flag = 0; + } +} + +void atv_dmd_ring_filter(bool on) +{ + if (!is_meson_tl1_cpu()) + return; + + if (on) { + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8274bf); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x2aa526); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x2d19e4); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8274bf); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x2aa526); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x2d19e4); + + /* enable filter */ + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x1); + } else { + /* default value */ + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8423F6); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0xFF86A967); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x37FE45); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0xFF86A967); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x3C223B); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8423F6); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0xFF86A967); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x37FE45); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0xFF86A967); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x3C223B); + + /* disable filter */ + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0); + } + + pr_dbg("%s do atv_dmd_ring_filter %d ...\n", __func__, on); } void atv_dmd_non_std_set(bool enable) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index dc3977e7fd91..5f6a80e49014 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -920,19 +920,14 @@ void tvafe_cvd2_get_signal_status(struct tvafe_cvd2_s *cvd2) !cvd2->hw_data[2].secam_detected) cvd2->hw.secam_detected = false; - if (cnt_dbg_en) { - - tvafe_pr_info("[%d]:cvd2->hw.acc3xx_cnt =%d,cvd2->hw.acc4xx_cnt=%d,acc425_cnt=%d\n", - __LINE__, - cvd2->hw.acc3xx_cnt, cvd2->hw.acc4xx_cnt, cvd2->hw.acc425_cnt); - tvafe_pr_info("[%d]:cvd2->hw.fsc_358=%d,cvd2->hw.fsc_425=%d,cvd2->hw.fsc_443 =%d\n", - __LINE__, - cvd2->hw.fsc_358, cvd2->hw.fsc_425, cvd2->hw.fsc_443); - } + if (cnt_dbg_en & 1) + tvafe_pr_info("acc4xx_cnt=%d,acc425_cnt=%d,acc3xx_cnt=%d,acc358_cnt=%d\n", + cvd2->hw.acc4xx_cnt, cvd2->hw.acc425_cnt, + cvd2->hw.acc3xx_cnt, cvd2->hw.acc358_cnt); if (cvd2->hw.acc3xx_cnt > CNT_VLD_TH) { if (cvd2->hw.acc358_cnt > - (cvd2->hw.acc3xx_cnt - (cvd2->hw.acc3xx_cnt>>2))) { + (cvd2->hw.acc3xx_cnt - (cvd2->hw.acc3xx_cnt>>3))) { cvd2->hw.fsc_358 = true; cvd2->hw.fsc_425 = false; @@ -958,8 +953,8 @@ void tvafe_cvd2_get_signal_status(struct tvafe_cvd2_s *cvd2) } if (++ cvd2->hw_data_cur >= 3) cvd2->hw_data_cur = 0; - if (cnt_dbg_en) - tvafe_pr_info("[%d]:cvd2->hw.fsc_358=%d,cvd2->hw.fsc_425=%d,cvd2->hw.fsc_443 =%d\n", + if (cnt_dbg_en & 2) + tvafe_pr_info("[%d]:hw.fsc_358=%d,hw.fsc_425=%d,hw.fsc_443 =%d\n", __LINE__, cvd2->hw.fsc_358, cvd2->hw.fsc_425, cvd2->hw.fsc_443); From 445dee0e6bcb38343ac2005ad6f1b5efa75874cf Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 20 Nov 2018 18:38:38 +0800 Subject: [PATCH 0539/1060] backlight: update ldim setting for tl1 [1/1] PD#SWPL-2762 Problem: ldim is changed for tl1 Solution: update ldim setting for tl1 Verify: x301 Change-Id: I21b10f27f4d1776db664c62fa7358b38801c7f53 Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h --- MAINTAINERS | 1 + .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 1063 ++++++++++++++++ .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 41 + .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 1063 ++++++++++++++++ .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 1066 +++++++++++++++++ drivers/amlogic/media/vout/backlight/aml_bl.c | 13 +- .../media/vout/backlight/aml_ldim/Makefile | 2 +- .../media/vout/backlight/aml_ldim/ldim_drv.c | 485 ++------ .../media/vout/backlight/aml_ldim/ldim_drv.h | 34 +- .../media/vout/backlight/aml_ldim/ldim_func.c | 382 ------ .../media/vout/backlight/aml_ldim/ldim_hw.c | 1021 ++++++++++++++++ .../media/vout/backlight/aml_ldim/ldim_reg.h | 2 +- 12 files changed, 4420 insertions(+), 753 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi create mode 100644 drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c diff --git a/MAINTAINERS b/MAINTAINERS index 76de795ede0d..b00b95ef06db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14748,6 +14748,7 @@ F: arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi AMLOGIC BACKLIGHT LDIM DRIVER M: Evoke Zhang F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_spi.c +F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c AMLOGIC CAMERA DRIVER M: Guosong Zhou diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi new file mode 100644 index 000000000000..04ac12492173 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -0,0 +1,1063 @@ +/* + * arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3", + "GPIOH_8","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 06526f26ba9c..491ffb5cabb6 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -948,6 +948,47 @@ */ ldim_dev_index = <2>; }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; }; bl_pwm_conf:bl_pwm_conf{ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi new file mode 100644 index 000000000000..906c6c5f8884 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -0,0 +1,1063 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3", + "GPIOH_8","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi new file mode 100644 index 000000000000..c75c6c7b4df2 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -0,0 +1,1066 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index e6859f81c63e..275c99fe89e0 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -1526,7 +1526,8 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, bconf->power_on_delay = bl_para[3]; bconf->power_off_delay = bl_para[4]; } - ret = of_property_read_u32(child, "bl_ldim_mode", &bl_para[0]); + ret = of_property_read_u32(child, "bl_ldim_region_row_col", + &bl_para[0]); if (ret == 0) bconf->ldim_flag = 1; @@ -1594,10 +1595,11 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, ret = of_property_read_u32(child, "bl_pwm_en_sequence_reverse", &val); if (ret) { - BLPR("don't find bl_pwm_en_sequence_reverse\n"); bconf->en_sequence_reverse = 0; - } else + } else { bconf->en_sequence_reverse = val; + BLPR("find bl_pwm_en_sequence_reverse: %d\n", val); + } bl_pwm->pwm_duty = bl_pwm->pwm_duty_min; /* init pwm config */ @@ -2038,6 +2040,9 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, struct device_node *child; struct bl_pwm_config_s *bl_pwm = NULL; + if (bl_debug_print_flag) + BLPR("%s\n", __func__); + ret = of_property_read_u32(blnode, "bl_pwm_config", &pwm_phandle); if (ret) { BLERR("not match bl_pwm_config node\n"); @@ -2101,8 +2106,6 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); } - BLPR("%s ok\n", __func__); - return ret; } diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile b/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile index bc2132eb8332..1d695bb17d3a 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile @@ -3,6 +3,6 @@ # obj-$(CONFIG_AMLOGIC_LOCAL_DIMMING) = aml_ldim.o ldim_dev_drv.o ldim_spi.o \ ob3350_bl.o global_bl.o iw7027_bl.o -aml_ldim-objs := ldim_drv.o ldim_func.o +aml_ldim-objs := ldim_drv.o ldim_func.o ldim_hw.o diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index 7ec078de3694..5035be5d237c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -309,258 +309,22 @@ static void ldim_db_load_update(struct LDReg_s *mLDReg, ldim_db_para_print(mLDReg); } -static void ldim_stts_initial_txlx(unsigned int resolution) -{ - Wr_reg(LDIM_STTS_CTRL0, 7 << 2); - ldim_set_matrix_ycbcr2rgb(); - ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); -} - static void ldim_stts_initial(unsigned int pic_h, unsigned int pic_v, unsigned int BLK_Vnum, unsigned int BLK_Hnum) { - unsigned int resolution, resolution_region, blk_height, blk_width; - unsigned int row_start, col_start; - - BLK_Vnum = (BLK_Vnum == 0) ? 1 : BLK_Vnum; - BLK_Hnum = (BLK_Hnum == 0) ? 1 : BLK_Hnum; LDIMPR("%s: %d %d %d %d\n", __func__, pic_h, pic_v, BLK_Vnum, BLK_Hnum); ldim_fw_para.hist_col = BLK_Vnum; ldim_fw_para.hist_row = BLK_Hnum; - resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); - /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ - if (ldim_dev.ldim_op_func == NULL) { LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->stts_init) - ldim_dev.ldim_op_func->stts_init(resolution); - - resolution_region = 0; - - blk_height = (pic_v - 8) / BLK_Vnum; - blk_width = (pic_h - 8) / BLK_Hnum; - row_start = (pic_v - (blk_height * BLK_Vnum)) >> 1; - col_start = (pic_h - (blk_width * BLK_Hnum)) >> 1; - ldim_set_region(0, blk_height, blk_width, - row_start, col_start, BLK_Hnum); -} - -static int LDIM_Update_Matrix(int NewBlMatrix[], int BlMatrixNum) -{ - int data; - - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - if (data & (1 << 12)) { /*bl_ram_mode=1;*/ - if (LDIM_RD_32Bits(REG_LD_BLMAT_RAM_MISC) & 0x10000) - /*Previous Matrix is not used*/ - goto Previous_Matrix; - else { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - NewBlMatrix, BlMatrixNum); - LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, - (BlMatrixNum & 0x1ff) | (1 << 16)); - /*set Matrix update ready*/ - - return 0; - } - } else { /*bl_ram_mode=0*/ - /*set ram_clk_sel=0, ram_bus_sel = 0*/ - data = data & (~(3 << 9)); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - NewBlMatrix, BlMatrixNum); - data = data | (3 << 9); /*set ram_clk_sel=1, ram_bus_sel = 1*/ - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - return 0; + if (ldim_dev.ldim_op_func->stts_init) { + ldim_dev.ldim_op_func->stts_init(pic_h, pic_v, + BLK_Vnum, BLK_Hnum); } - -Previous_Matrix: - return 1; -} - -static void ldim_initial_txlx(unsigned int ldim_bl_en, - unsigned int ldim_hvcnt_bypass) -{ - unsigned int i; - unsigned int data; - unsigned int *arrayTmp; - - arrayTmp = kcalloc(1536, sizeof(unsigned int), GFP_KERNEL); - if (arrayTmp == NULL) { - LDIMERR("%s malloc error\n", __func__); - return; - } - - /* LD_FRM_SIZE */ - data = ((nPRM.reg_LD_pic_RowMax & 0xfff)<<16) | - (nPRM.reg_LD_pic_ColMax & 0xfff); - LDIM_WR_32Bits(REG_LD_FRM_SIZE, data); - - /* LD_RGB_MOD */ - data = ((0 & 0xfff) << 20) | - ((nPRM.reg_LD_RGBmapping_demo & 0x1) << 19) | - ((nPRM.reg_LD_X_LUT_interp_mode[2] & 0x1) << 18) | - ((nPRM.reg_LD_X_LUT_interp_mode[1] & 0x1) << 17) | - ((nPRM.reg_LD_X_LUT_interp_mode[0] & 0x1) << 16) | - ((0 & 0x1) << 15) | - ((nPRM.reg_LD_BkLit_LPFmod & 0x7) << 12) | - ((nPRM.reg_LD_Litshft & 0x7) << 8) | - ((nPRM.reg_LD_BackLit_Xtlk & 0x1) << 7) | - ((nPRM.reg_LD_BkLit_Intmod & 0x1) << 6) | - ((nPRM.reg_LD_BkLUT_Intmod & 0x1) << 5) | - ((nPRM.reg_LD_BkLit_curmod & 0x1) << 4) | - ((nPRM.reg_LD_BackLit_mode & 0x3)); - LDIM_WR_32Bits(REG_LD_RGB_MOD, data); - - /* LD_BLK_HVNUM */ - data = ((nPRM.reg_LD_Reflect_Vnum & 0x7) << 20) | - ((nPRM.reg_LD_Reflect_Hnum & 0x7) << 16) | - ((nPRM.reg_LD_BLK_Vnum & 0x3f) << 8) | - ((nPRM.reg_LD_BLK_Hnum & 0x3f)); - LDIM_WR_32Bits(REG_LD_BLK_HVNUM, data); - - /* LD_HVGAIN */ - data = ((nPRM.reg_LD_Vgain & 0xfff) << 16) | - (nPRM.reg_LD_Hgain & 0xfff); - LDIM_WR_32Bits(REG_LD_HVGAIN, data); - - /* LD_BKLIT_VLD */ - data = 0; - for (i = 0; i < 32; i++) - if (nPRM.reg_LD_BkLit_valid[i]) - data = data | (1 << i); - LDIM_WR_32Bits(REG_LD_BKLIT_VLD, data); - - /* LD_BKLIT_PARAM */ - data = ((nPRM.reg_LD_BkLit_Celnum & 0xff) << 16) | - (nPRM.reg_BL_matrix_AVG & 0xfff); - LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); - - /* LD_LIT_GAIN_COMP */ - data = ((nPRM.reg_LD_Litgain & 0xfff) << 16) | - (nPRM.reg_BL_matrix_Compensate & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - - /* LD_FRM_RST_POS */ - data = (1 << 16) | (5); /* h=1,v=5 :ldim_param_frm_rst_pos */ - LDIM_WR_32Bits(REG_LD_FRM_RST_POS, data); - - /* LD_FRM_BL_START_POS */ - data = (1 << 16) | (6); /* ldim_param_frm_bl_start_pos; */ - LDIM_WR_32Bits(REG_LD_FRM_BL_START_POS, data); - - /* REG_LD_FRM_HBLAN_VHOLS */ - data = ((nPRM.reg_LD_LUT_VHo_LS & 0x7) << 16) | - ((6 & 0x1fff)) ; /*frm_hblank_num */ - LDIM_WR_32Bits(REG_LD_FRM_HBLAN_VHOLS, data); - - /* REG_LD_XLUT_DEMO_ROI_XPOS */ - data = ((nPRM.reg_LD_xlut_demo_roi_xend & 0x1fff) << 16) | - (nPRM.reg_LD_xlut_demo_roi_xstart & 0x1fff); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_XPOS, data); - - /* REG_LD_XLUT_DEMO_ROI_YPOS */ - data = ((nPRM.reg_LD_xlut_demo_roi_yend & 0x1fff) << 16) | - (nPRM.reg_LD_xlut_demo_roi_ystart & 0x1fff); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_YPOS, data); - - /* REG_LD_XLUT_DEMO_ROI_CTRL */ - data = ((nPRM.reg_LD_xlut_oroi_enable & 0x1) << 1) | - (nPRM.reg_LD_xlut_iroi_enable & 0x1); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_CTRL, data); - - /*LD_BLMAT_RAM_MISC*/ - LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, 384 & 0x1ff); - - /* X_idx: 12*16 */ - LDIM_WR_BASE_LUT(REG_LD_RGB_IDX_BASE, nPRM.X_idx[0], 16, 16); - - /* X_nrm[16]: 4 * 16 */ - LDIM_WR_BASE_LUT(REG_LD_RGB_NRMW_BASE_TXLX, nPRM.X_nrm[0], 4, 16); - - /*reg_LD_BLK_Hidx[33]: 14*33 */ - LDIM_WR_BASE_LUT(REG_LD_BLK_HIDX_BASE_TXLX, - nPRM.reg_LD_BLK_Hidx, 16, 33); - - /* reg_LD_BLK_Vidx[25]: 14*25 */ - LDIM_WR_BASE_LUT(REG_LD_BLK_VIDX_BASE_TXLX, - nPRM.reg_LD_BLK_Vidx, 16, 25); - - /* reg_LD_LUT_VHk_pos[32]/reg_LD_LUT_VHk_neg[32]: u8 */ - for (i = 0; i < 32; i++) - arrayTmp[i] = nPRM.reg_LD_LUT_VHk_pos[i]; - for (i = 0; i < 32; i++) - arrayTmp[32+i] = nPRM.reg_LD_LUT_VHk_neg[i]; - LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); - - /* reg_LD_LUT_VHo_pos[32]/reg_LD_LUT_VHo_neg[32]: s8 */ - for (i = 0; i < 32; i++) - arrayTmp[i] = nPRM.reg_LD_LUT_VHo_pos[i]; - for (i = 0; i < 32; i++) - arrayTmp[32+i] = nPRM.reg_LD_LUT_VHo_neg[i]; - LDIM_WR_BASE_LUT(REG_LD_LUT_VHO_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); - - /* reg_LD_LUT_HHk[32]:u8 */ - LDIM_WR_BASE_LUT(REG_LD_LUT_HHK_BASE_TXLX, nPRM.reg_LD_LUT_HHk, 8, 32); - - /*reg_LD_Reflect_Hdgr[20],reg_LD_Reflect_Vdgr[20], - * reg_LD_Reflect_Xdgr[4] - */ - for (i = 0; i < 20; i++) - arrayTmp[i] = nPRM.reg_LD_Reflect_Hdgr[i]; - for (i = 0; i < 20; i++) - arrayTmp[20+i] = nPRM.reg_LD_Reflect_Vdgr[i]; - for (i = 0; i < 4; i++) - arrayTmp[40+i] = nPRM.reg_LD_Reflect_Xdgr[i]; - LDIM_WR_BASE_LUT(REG_LD_REFLECT_DGR_BASE_TXLX, arrayTmp, 8, 44); - - /*reg_LD_LUT_Hdg_LEXT[8]/reg_LD_LUT_Vdg_LEXT[8]/reg_LD_LUT_VHk_LEXT[8]*/ - for (i = 0; i < 8; i++) - arrayTmp[i] = (nPRM.reg_LD_LUT_Hdg_LEXT_TXLX[i] & 0x3ff) | - ((nPRM.reg_LD_LUT_VHk_LEXT_TXLX[i] & 0x3ff) << 10) | - ((nPRM.reg_LD_LUT_Vdg_LEXT_TXLX[i] & 0x3ff) << 20); - LDIM_WR_BASE_LUT_DRT(REG_LD_LUT_LEXT_BASE_TXLX, arrayTmp, 8); - - /*reg_LD_LUT_Hdg[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_HDG_BASE_TXLX, - nPRM.reg_LD_LUT_Hdg_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_Vdg[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_VDG_BASE_TXLX, - nPRM.reg_LD_LUT_Vdg_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_VHk[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_BASE_TXLX, - nPRM.reg_LD_LUT_VHk_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_Id[16][24]: u3*16*24=u3*384 */ - LDIM_WR_BASE_LUT(REG_LD_LUT_ID_BASE_TXLX, nPRM.reg_LD_LUT_Id, 4, 384); - - /*enable the CBUS configure the RAM*/ - /*LD_MISC_CTRL0 {reg_blmat_ram_mode, - *1'h0,ram_bus_sel,ram_clk_sel,ram_clk_gate_en, - *2'h0,reg_hvcnt_bypass,reg_demo_synmode,reg_ldbl_synmode, - *reg_ldim_bl_en,soft_bl_start,reg_soft_rst) - */ - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = (data & (~(3 << 9))) | (1 << 8); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - /*X_lut[3][16][16]*/ - LDIM_WR_BASE_LUT_DRT(REG_LD_RGB_LUT_BASE, nPRM.X_lut2[0][0], 3*16*16); - data = 0 | (0 << 1) | ((ldim_bl_en & 0x1) << 2) | - (ldim_hvcnt_bypass << 5) | (1 << 8) | - (3 << 9) | (1 << 12); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - LDIM_Update_Matrix(nPRM.BL_matrix, 16 * 24); - - kfree(arrayTmp); } static void LDIM_Initial(unsigned int pic_h, unsigned int pic_v, @@ -591,105 +355,23 @@ static void LDIM_Initial(unsigned int pic_h, unsigned int pic_v, LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->ldim_init) - ldim_dev.ldim_op_func->ldim_init(ldim_bl_en, ldim_hvcnt_bypass); -} - -static void ldim_update_matrix(unsigned int mode) -{ - unsigned int data; - int bl_matrix[8] = {0}; - unsigned int reg_BL_matrix_Compensate = 0x0; - int bl_matrix_1[8] = {0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_1 = 0xfff; - int bl_matrix_2[8] = {0xfff, 0xfff, 0xfff, 0x000, 0x000, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_2 = 0xbff; - int bl_matrix_3[8] = {0, 0, 0, 0xfff, 0, 0, 0, 0}; - unsigned int reg_BL_matrix_Compensate_3 = 0x1ff; - int bl_matrix_4[8] = {0xfff, 0xfff, 0xfff, 0, 0xfff, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_4 = 0xdff; - - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = data & (~(3<<4)); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - /* gMatrix_LUT: s12*100 ==> max to 8*8 enum ##r/w ram method*/ - if (mode == 0) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data|(reg_BL_matrix_Compensate&0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 1) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_1[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_1 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 2) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_2[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data|(reg_BL_matrix_Compensate_2 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 3) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_3[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_3 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 4) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_4[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_4 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + if (ldim_dev.ldim_op_func->ldim_init) { + ldim_dev.ldim_op_func->ldim_init(&nPRM, + ldim_bl_en, ldim_hvcnt_bypass); } - /* disable the CBUS configure the RAM */ - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = data | (3<<4); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); } -static void ldim_update_txlx(void) -{ - unsigned int data; - - if (ldim_avg_update_en) { - /* LD_BKLIT_PARAM */ - data = LDIM_RD_32Bits(REG_LD_BKLIT_PARAM); - data = (data&(~0xfff)) | (nPRM.reg_BL_matrix_AVG&0xfff); - LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); - - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = (data&(~0xfff)) | - (nPRM.reg_BL_matrix_Compensate & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } - - if (ldim_matrix_update_en) - LDIM_Update_Matrix(nPRM.BL_matrix, ldim_blk_row*ldim_blk_col); - -} - -static void ldim_update_setting(void) +static void ldim_remap_update(void) { if (ldim_dev.ldim_op_func == NULL) { if (brightness_vs_cnt == 0) LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->update_setting) - ldim_dev.ldim_op_func->update_setting(); + if (ldim_dev.ldim_op_func->remap_update) { + ldim_dev.ldim_op_func->remap_update(&nPRM, + ldim_avg_update_en, ldim_matrix_update_en); + } } static irqreturn_t ldim_vsync_isr(int irq, void *dev_id) @@ -706,7 +388,7 @@ static irqreturn_t ldim_vsync_isr(int irq, void *dev_id) if (ldim_func_en) { if (ldim_avg_update_en) - ldim_update_setting(); + ldim_remap_update(); if (ldim_hist_en) { /*schedule_work(&ldim_on_vs_work);*/ @@ -1293,7 +975,7 @@ static void ldim_get_matrix_info(void) } pr_info("current black_frm: %d\n", ldim_fw_para.black_frm); - pr_info("spi transfer_matrix:\n"); + pr_info("ldim_dev brightness transfer_matrix:\n"); for (i = 0; i < ldim_blk_row; i++) { len = 0; for (j = 0; j < ldim_blk_col; j++) { @@ -1662,7 +1344,8 @@ static int ldim_on_init(void) { int ret = 0; - LDIMPR("%s\n", __func__); + if (ldim_debug_print) + LDIMPR("%s\n", __func__); /* init ldim */ ldim_stts_initial(ldim_config.hsize, ldim_config.vsize, @@ -1775,6 +1458,45 @@ struct aml_ldim_driver_s *aml_ldim_get_driver(void) return &ldim_driver; } +/* ****************************************************** + * local dimming dummy function for virtual ldim dev + * ****************************************************** + */ +static int ldim_virtual_smr(unsigned short *buf, unsigned char len) +{ + return 0; +} + +static int ldim_virtual_power_on(void) +{ + return 0; +} + +static int ldim_virtual_power_off(void) +{ + return 0; +} + +static int ldim_virtual_driver_update(struct aml_ldim_driver_s *ldim_drv) +{ + ldim_drv->device_power_on = ldim_virtual_power_on; + ldim_drv->device_power_off = ldim_virtual_power_off; + ldim_drv->device_bri_update = ldim_virtual_smr; + + return 0; +} + +static int ldim_dev_add_virtual_driver(struct aml_ldim_driver_s *ldim_drv) +{ + LDIMPR("%s\n", __func__); + + ldim_virtual_driver_update(ldim_drv); + ldim_drv->init(); + + return 0; +} +/* ****************************************************** */ + static int ldim_open(struct inode *inode, struct file *file) { struct ldim_dev_s *devp; @@ -2356,16 +2078,6 @@ static ssize_t ldim_attr_store(struct class *cla, pr_info("reg_addr: 0x%x=0x%x, readback: 0x%x\n", reg_addr, reg_val, LDIM_RD_32Bits(reg_addr)); } - } else if (!strcmp(parm[0], "update_matrix")) { - unsigned int mode = 0; - - if (parm[1] != NULL) { - if (kstrtouint(parm[1], 10, &mode) < 0) - goto ldim_attr_store_err; - - ldim_update_matrix(mode); - pr_info("mode: %d\n", mode); - } } else if (!strcmp(parm[0], "bl_remap_curve")) { if (parm[1] != NULL) { if (!strcmp(parm[1], "r")) { @@ -2855,7 +2567,8 @@ static ssize_t ldim_attr_store(struct class *cla, ldim_fw_para.Dbprint_lv); } else if (!strcmp(parm[0], "info")) { pr_info("ldim_drv_ver: %s\n", LDIM_DRV_VER); - ldim_driver.config_print(); + if (ldim_driver.config_print) + ldim_driver.config_print(); pr_info("\nldim_blk_row = %d\n" "ldim_blk_col = %d\n" "ldim_hist_row = %d\n" @@ -2944,10 +2657,32 @@ static ssize_t ldim_func_en_store(struct class *class, return count; } +static ssize_t ldim_para_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len = sprintf(buf, "boost_gain=%d\n", ldim_fw_para.boost_gain); + + return len; +} + +static ssize_t ldim_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len = ldim_hw_reg_dump(buf); + + return len; +} + static struct class_attribute aml_ldim_class_attrs[] = { __ATTR(attr, 0644, ldim_attr_show, ldim_attr_store), __ATTR(func_en, 0644, ldim_func_en_show, ldim_func_en_store), + __ATTR(para, 0644, ldim_para_show, NULL), + __ATTR(dump, 0644, ldim_dump_show, NULL), __ATTR_NULL, }; @@ -3000,7 +2735,8 @@ int aml_ldim_get_config_dts(struct device_node *child) LDIMERR("failed to get ldim_dev_index\n"); else ldim_driver.dev_index = (unsigned char)para[0]; - LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); + if (ldim_driver.dev_index < 0xff) + LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); return 0; } @@ -3032,7 +2768,8 @@ int aml_ldim_get_config_unifykey(unsigned char *buf) /* get ldim_dev_index 1byte*/ ldim_driver.dev_index = *(p + LCD_UKEY_BL_LDIM_DEV_INDEX); - LDIMPR("get dev_index = %d\n", ldim_driver.dev_index); + if (ldim_driver.dev_index < 0xff) + LDIMPR("get dev_index = %d\n", ldim_driver.dev_index); return 0; } @@ -3192,17 +2929,52 @@ ldim_malloc_err0: } static struct ldim_operate_func_s ldim_op_func_txlx = { - .update_setting = ldim_update_txlx, + .h_region_max = 24, + .v_region_max = 16, + .total_region_max = 384, + .remap_update = ldim_remap_update_txlx, .stts_init = ldim_stts_initial_txlx, .ldim_init = ldim_initial_txlx, }; static struct ldim_operate_func_s ldim_op_func_tl1 = { - .update_setting = NULL, - .stts_init = NULL, + .h_region_max = 31, + .v_region_max = 16, + .total_region_max = 128, + .remap_update = NULL, + .stts_init = ldim_stts_initial_tl1, .ldim_init = NULL, }; +static int ldim_region_num_check(struct ldim_operate_func_s *ldim_func) +{ + unsigned short temp; + + if (ldim_func == NULL) { + LDIMERR("%s: ldim_func is NULL\n", __func__); + return -1; + } + + if (ldim_config.row > ldim_func->v_region_max) { + LDIMERR("%s: blk row (%d) is out of support (%d)\n", + __func__, ldim_config.row, ldim_func->v_region_max); + return -1; + } + if (ldim_config.col > ldim_func->h_region_max) { + LDIMERR("%s: blk col (%d) is out of support (%d)\n", + __func__, ldim_config.col, ldim_func->h_region_max); + return -1; + } + temp = ldim_config.row * ldim_config.col; + if (temp > ldim_func->total_region_max) { + LDIMERR("%s: blk total region (%d) is out of support (%d)\n", + __func__, temp, ldim_func->total_region_max); + return -1; + } + + return 0; +} + int aml_ldim_probe(struct platform_device *pdev) { int ret = 0; @@ -3250,6 +3022,9 @@ int aml_ldim_probe(struct platform_device *pdev) devp->ldim_op_func = NULL; break; } + ret = ldim_region_num_check(devp->ldim_op_func); + if (ret) + return -1; ret = aml_ldim_malloc(ldim_blk_row, ldim_blk_col); if (ret) { @@ -3320,12 +3095,18 @@ int aml_ldim_probe(struct platform_device *pdev) goto err; } ldim_vsync_irq = bl_drv->res_ldim_vsync_irq->start; - LDIMPR("ldim_vsync_irq: %d\n", ldim_vsync_irq); + if (ldim_debug_print) + LDIMPR("ldim_vsync_irq: %d\n", ldim_vsync_irq); if (request_irq(ldim_vsync_irq, ldim_vsync_isr, IRQF_SHARED, - "ldim_vsync", (void *)"ldim_vsync")) + "ldim_vsync", (void *)"ldim_vsync")) { LDIMERR("can't request ldim_vsync_irq\n"); - else - LDIMPR("request ldim_vsync_irq successful\n"); + } else { + if (ldim_debug_print) + LDIMPR("request ldim_vsync_irq successful\n"); + } + + if (bl_drv->bconf->method != BL_CTRL_LOCAL_DIMMING) + ldim_dev_add_virtual_driver(&ldim_driver); ldim_driver.valid_flag = 1; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index 6c44b2a23122..d186f59ab69e 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -26,8 +26,7 @@ /*20181101: fix ldim_op_func null mistake, add new spi api support */ /*20181203: add 50/60hz change & iw7027 error handle support */ /*20181220: add tl1 support*/ -/*20190103: add analog pwm support*/ -#define LDIM_DRV_VER "20190103" +#define LDIM_DRV_VER "20181220" extern unsigned char ldim_debug_print; @@ -41,25 +40,36 @@ extern int LD_remap_lut[16][32]; /*========================================*/ struct ldim_operate_func_s { - void (*update_setting)(void); - void (*stts_init)(unsigned int resolution); - void (*ldim_init)(unsigned int bl_en, unsigned int hvcnt_bypass); + unsigned short h_region_max; + unsigned short v_region_max; + unsigned short total_region_max; + void (*remap_update)(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en); + void (*stts_init)(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); + void (*ldim_init)(struct LDReg_s *nPRM, + unsigned int bl_en, unsigned int hvcnt_bypass); }; /*========================================*/ extern int ldim_round(int ix, int ib); -extern void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, - unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, - unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en); -extern void ldim_set_region(unsigned int resolution, unsigned int blk_height, - unsigned int blk_width, unsigned int row_start, unsigned int col_start, - unsigned int blk_hnum); extern void LD_ConLDReg(struct LDReg_s *Reg); extern void ld_fw_cfg_once(struct LDReg_s *nPRM); -extern void ldim_stts_read_region(unsigned int nrow, unsigned int ncol); +/* ldim hw */ +extern int ldim_hw_reg_dump(char *buf); +extern void ldim_stts_read_region(unsigned int nrow, unsigned int ncol); extern void ldim_set_matrix_ycbcr2rgb(void); extern void ldim_set_matrix_rgb2ycbcr(int mode); +extern void ldim_initial_txlx(struct LDReg_s *nPRM, + unsigned int ldim_bl_en, unsigned int ldim_hvcnt_bypass); +extern void ldim_stts_initial_txlx(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); +extern void ldim_stts_initial_tl1(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); +extern void ldim_remap_update_txlx(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en); + #endif diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c index 606cd542e203..613c6a728507 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c @@ -38,9 +38,6 @@ #define MIN(a, b) ((a < b) ? a:b) #endif -#define Wr(reg, val) Wr_reg(reg, val) -#define Rd(reg) Rd_reg(reg) - static int LD_BLK_Hidx[33] = { /* S14* 33 */ -1920, -1440, -960, -480, 0, 480, @@ -246,385 +243,6 @@ int ldim_round(int ix, int ib) return ld_rst; } -/***** local dimming stts functions begin *****/ -/*hist mode: 0: comp0 hist only, 1: Max(comp0,1,2) for hist, - *2: the hist of all comp0,1,2 are calculated - */ -/*lpf_en 1: 1,2,1 filter on before finding max& hist*/ -/*rd_idx_auto_inc_mode 0: no self increase, 1: read index increase after - *read a 25/48 block, 2: increases every read and lock sub-idx - */ -/*one_ram_en 1: one ram mode; 0:double ram mode*/ -void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, - unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, - unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en) -{ - int data32; - - Wr(LDIM_STTS_GCLK_CTRL0, 0x0); - Wr(LDIM_STTS_WIDTHM1_HEIGHTM1, resolution); - - data32 = 0x80000000 | ((pix_drop_mode & 0x3) << 29); - data32 = data32 | ((eol_en & 0x1) << 28); - data32 = data32 | ((one_ram_en & 0x1) << 27); - data32 = data32 | ((hist_mode & 0x3) << 22); - data32 = data32 | ((lpf_en & 0x1) << 21); - data32 = data32 | ((rd_idx_auto_inc_mode & 0xff) << 14); - Wr(LDIM_STTS_HIST_REGION_IDX, data32); -} - -void ldim_set_region(unsigned int resolution, unsigned int blk_height, - unsigned int blk_width, unsigned int row_start, unsigned int col_start, - unsigned int blk_hnum) -{ - unsigned int hend0, hend1, hend2, hend3, hend4, hend5, - hend6, hend7, hend8, hend9, hend10, hend11, hend12, - hend13, hend14, hend15, hend16, hend17, hend18, - hend19, hend20, hend21, hend22, hend23; - unsigned int vend0, vend1, vend2, vend3, vend4, vend5, - vend6, vend7, vend8, vend9, vend10, vend11, - vend12, vend13, vend14, vend15; - unsigned int data32, k, h_index[24], v_index[16]; - - if (resolution == 0) { - h_index[0] = col_start + blk_width - 1; - for (k = 1; k < 24; k++) { - h_index[k] = h_index[k-1] + blk_width; - if (h_index[k] > 4095) - h_index[k] = 4095; /* clip U12 */ - } - v_index[0] = row_start + blk_height - 1; - for (k = 1; k < 16; k++) { - v_index[k] = v_index[k-1] + blk_height; - if (v_index[k] > 4095) - v_index[k] = 4095; /* clip U12 */ - } - hend0 = h_index[0];/*col_start + blk_width - 1;*/ - hend1 = h_index[1];/*hend0 + blk_width;*/ - hend2 = h_index[2];/*hend1 + blk_width;*/ - hend3 = h_index[3];/*hend2 + blk_width;*/ - hend4 = h_index[4];/*hend3 + blk_width;*/ - hend5 = h_index[5];/*hend4 + blk_width;*/ - hend6 = h_index[6];/*hend5 + blk_width;*/ - hend7 = h_index[7];/*hend6 + blk_width;*/ - hend8 = h_index[8];/*hend7 + blk_width;*/ - hend9 = h_index[9];/*hend8 + blk_width;*/ - hend10 = h_index[10];/*hend9 + blk_width ;*/ - hend11 = h_index[11];/*hend10 + blk_width;*/ - hend12 = h_index[12];/*hend11 + blk_width;*/ - hend13 = h_index[13];/*hend12 + blk_width;*/ - hend14 = h_index[14];/*hend13 + blk_width;*/ - hend15 = h_index[15];/*hend14 + blk_width;*/ - hend16 = h_index[16];/*hend15 + blk_width;*/ - hend17 = h_index[17];/*hend16 + blk_width;*/ - hend18 = h_index[18];/*hend17 + blk_width;*/ - hend19 = h_index[19];/*hend18 + blk_width;*/ - hend20 = h_index[20];/*hend19 + blk_width ;*/ - hend21 = h_index[21];/*hend20 + blk_width;*/ - hend22 = h_index[22];/*hend21 + blk_width;*/ - hend23 = h_index[23];/*hend22 + blk_width;*/ - vend0 = v_index[0];/*row_start + blk_height - 1;*/ - vend1 = v_index[1];/*vend0 + blk_height;*/ - vend2 = v_index[2];/*vend1 + blk_height;*/ - vend3 = v_index[3];/*vend2 + blk_height;*/ - vend4 = v_index[4];/*vend3 + blk_height;*/ - vend5 = v_index[5];/*vend4 + blk_height;*/ - vend6 = v_index[6];/*vend5 + blk_height;*/ - vend7 = v_index[7];/*vend6 + blk_height;*/ - vend8 = v_index[8];/*vend7 + blk_height;*/ - vend9 = v_index[9];/*vend8 + blk_height;*/ - vend10 = v_index[10];/*vend9 + blk_height;*/ - vend11 = v_index[11];/*vend10 + blk_height;*/ - vend12 = v_index[12];/*vend11 + blk_height;*/ - vend13 = v_index[13];/*vend12 + blk_height;*/ - vend14 = v_index[14];/*vend13 + blk_height;*/ - vend15 = v_index[15];/*vend14 + blk_height;*/ - - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); - Wr(LDIM_STTS_HIST_SET_REGION, ((((row_start & 0x1fff) << 16) - & 0xffff0000) | (col_start & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend1 & 0x1fff) << 16) - | (hend0 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend1 & 0x1fff) << 16) - | (vend0 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend3 & 0x1fff) << 16) - | (hend2 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend3 & 0x1fff) << 16) - | (vend2 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend5 & 0x1fff) << 16) - | (hend4 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend5 & 0x1fff) << 16) - | (vend4 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend7 & 0x1fff) << 16) - | (hend6 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend7 & 0x1fff) << 16) - | (vend6 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend9 & 0x1fff) << 16) - | (hend8 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend9 & 0x1fff) << 16) - | (vend8 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend11 & 0x1fff) << 16) - | (hend10 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend11 & 0x1fff) << 16) - | (vend10 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend13 & 0x1fff) << 16) - | (hend12 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend13 & 0x1fff) << 16) - | (vend12 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend15 & 0x1fff) << 16) - | (hend14 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend15 & 0x1fff) << 16) - | (vend14 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend17 & 0x1fff) << 16) - | (hend16 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend19 & 0x1fff) << 16) - | (hend18 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend21 & 0x1fff) << 16) - | (hend20 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend23 & 0x1fff) << 16) - | (hend22 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, blk_hnum); /*h region number*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0); /*line_n_int_num*/ - } else if (resolution == 1) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); - Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); - Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260);*/ - } else if (resolution == 2) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/*hv00*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/*h01*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/*v01*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/*h23*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/*v23*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/*h45*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/*v45*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/*h67*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/*v67*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h89*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v89*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1011*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1011*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1213*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1213*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1415*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1415*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1617*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1819*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2021*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2223*/ - } else if (resolution == 3) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); - Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); - Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); - Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); - Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 4) { /* 5x6 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 5) { /* 8x2 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); - Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 6) { /* 2x1 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); - Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 7) { /* 2x2 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 8) { /* 3x5 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); - Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); - Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 9) { /* 4x3 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 10) { /* 6x8 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); - Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } -} - -static unsigned int invalid_val_cnt; -void ldim_stts_read_region(unsigned int nrow, unsigned int ncol) -{ - unsigned int i, j, k; - unsigned int data32; - struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - - if (invalid_val_cnt > 0xfffffff) - invalid_val_cnt = 0; - - Wr(LDIM_STTS_HIST_REGION_IDX, Rd(LDIM_STTS_HIST_REGION_IDX) - & 0xffffc000); - data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); - - for (i = 0; i < nrow; i++) { - for (j = 0; j < ncol; j++) { - data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); - for (k = 0; k < 17; k++) { - if (k == 16) { - data32 = Rd(LDIM_STTS_HIST_READ_REGION); - ldim_drv->max_rgb[i * ncol + j] - = data32; - } else { - data32 = Rd(LDIM_STTS_HIST_READ_REGION); - ldim_drv->hist_matrix[i * ncol * 16 + - j * 16 + k] = data32; - } - if (!(data32 & 0x40000000)) - invalid_val_cnt++; - } - } - } -} - -/* VDIN_MATRIX_YUV601_RGB */ -/* -16 1.164 0 1.596 0 */ -/* -128 1.164 -0.391 -0.813 0 */ -/* -128 1.164 2.018 0 0 */ -/*{0x07c00600, 0x00000600, 0x04a80000, 0x066204a8, 0x1e701cbf, 0x04a80812, - * 0x00000000, 0x00000000, 0x00000000,}, - */ -void ldim_set_matrix_ycbcr2rgb(void) -{ - Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); /* enable matrix */ - - Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x07c00600); - Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x00000600); - Wr(LDIM_STTS_MATRIX_COEF00_01, 0x04a80000); - Wr(LDIM_STTS_MATRIX_COEF02_10, 0x066204a8); - Wr(LDIM_STTS_MATRIX_COEF11_12, 0x1e701cbf); - Wr(LDIM_STTS_MATRIX_COEF20_21, 0x04a80812); - Wr(LDIM_STTS_MATRIX_COEF22, 0x00000000); - Wr(LDIM_STTS_MATRIX_OFFSET0_1, 0x00000000); - Wr(LDIM_STTS_MATRIX_OFFSET2, 0x00000000); -} - -void ldim_set_matrix_rgb2ycbcr(int mode) -{ - Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); - if (mode == 0) {/*ycbcr not full range, 601 conversion*/ - Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x0); - Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x0); - /* 0.257 0.504 0.098 */ - /* -0.148 -0.291 0.439 */ - /* 0.439 -0.368 -0.071 */ - Wr(LDIM_STTS_MATRIX_COEF00_01, (0x107 << 16) | 0x204); - Wr(LDIM_STTS_MATRIX_COEF02_10, (0x64 << 16) | 0x1f68); - Wr(LDIM_STTS_MATRIX_COEF11_12, (0x1ed6 << 16) | 0x1c2); - Wr(LDIM_STTS_MATRIX_COEF20_21, (0x1c2 << 16) | 0x1e87); - Wr(LDIM_STTS_MATRIX_COEF22, 0x1fb7); - - Wr(LDIM_STTS_MATRIX_OFFSET2, 0x0200); - } else if (mode == 1) {/*ycbcr full range, 601 conversion*/ - /* todo */ - } -} - int Round(int iX, int iB) { int Rst = 0; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c new file mode 100644 index 000000000000..7d2dcc1f83b1 --- /dev/null +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c @@ -0,0 +1,1021 @@ +/* + * drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ldim_drv.h" +#include "ldim_reg.h" + +#define Wr(reg, val) Wr_reg(reg, val) +#define Rd(reg) Rd_reg(reg) + +static int LDIM_Update_Matrix(int NewBlMatrix[], int BlMatrixNum) +{ + int data; + + data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); + if (data & (1 << 12)) { /*bl_ram_mode=1;*/ + if (LDIM_RD_32Bits(REG_LD_BLMAT_RAM_MISC) & 0x10000) + /*Previous Matrix is not used*/ + goto Previous_Matrix; + else { + LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, + NewBlMatrix, BlMatrixNum); + LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, + (BlMatrixNum & 0x1ff) | (1 << 16)); + /*set Matrix update ready*/ + + return 0; + } + } else { /*bl_ram_mode=0*/ + /*set ram_clk_sel=0, ram_bus_sel = 0*/ + data = data & (~(3 << 9)); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, + NewBlMatrix, BlMatrixNum); + data = data | (3 << 9); /*set ram_clk_sel=1, ram_bus_sel = 1*/ + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + return 0; + } + +Previous_Matrix: + return 1; +} + +void ldim_initial_txlx(struct LDReg_s *nPRM, + unsigned int ldim_bl_en, unsigned int ldim_hvcnt_bypass) +{ + unsigned int i; + unsigned int data; + unsigned int *arrayTmp; + + arrayTmp = kcalloc(1536, sizeof(unsigned int), GFP_KERNEL); + if (arrayTmp == NULL) { + LDIMERR("%s malloc error\n", __func__); + return; + } + + /* LD_FRM_SIZE */ + data = ((nPRM->reg_LD_pic_RowMax & 0xfff)<<16) | + (nPRM->reg_LD_pic_ColMax & 0xfff); + LDIM_WR_32Bits(REG_LD_FRM_SIZE, data); + + /* LD_RGB_MOD */ + data = ((0 & 0xfff) << 20) | + ((nPRM->reg_LD_RGBmapping_demo & 0x1) << 19) | + ((nPRM->reg_LD_X_LUT_interp_mode[2] & 0x1) << 18) | + ((nPRM->reg_LD_X_LUT_interp_mode[1] & 0x1) << 17) | + ((nPRM->reg_LD_X_LUT_interp_mode[0] & 0x1) << 16) | + ((0 & 0x1) << 15) | + ((nPRM->reg_LD_BkLit_LPFmod & 0x7) << 12) | + ((nPRM->reg_LD_Litshft & 0x7) << 8) | + ((nPRM->reg_LD_BackLit_Xtlk & 0x1) << 7) | + ((nPRM->reg_LD_BkLit_Intmod & 0x1) << 6) | + ((nPRM->reg_LD_BkLUT_Intmod & 0x1) << 5) | + ((nPRM->reg_LD_BkLit_curmod & 0x1) << 4) | + ((nPRM->reg_LD_BackLit_mode & 0x3)); + LDIM_WR_32Bits(REG_LD_RGB_MOD, data); + + /* LD_BLK_HVNUM */ + data = ((nPRM->reg_LD_Reflect_Vnum & 0x7) << 20) | + ((nPRM->reg_LD_Reflect_Hnum & 0x7) << 16) | + ((nPRM->reg_LD_BLK_Vnum & 0x3f) << 8) | + ((nPRM->reg_LD_BLK_Hnum & 0x3f)); + LDIM_WR_32Bits(REG_LD_BLK_HVNUM, data); + + /* LD_HVGAIN */ + data = ((nPRM->reg_LD_Vgain & 0xfff) << 16) | + (nPRM->reg_LD_Hgain & 0xfff); + LDIM_WR_32Bits(REG_LD_HVGAIN, data); + + /* LD_BKLIT_VLD */ + data = 0; + for (i = 0; i < 32; i++) + if (nPRM->reg_LD_BkLit_valid[i]) + data = data | (1 << i); + LDIM_WR_32Bits(REG_LD_BKLIT_VLD, data); + + /* LD_BKLIT_PARAM */ + data = ((nPRM->reg_LD_BkLit_Celnum & 0xff) << 16) | + (nPRM->reg_BL_matrix_AVG & 0xfff); + LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); + + /* LD_LIT_GAIN_COMP */ + data = ((nPRM->reg_LD_Litgain & 0xfff) << 16) | + (nPRM->reg_BL_matrix_Compensate & 0xfff); + LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + + /* LD_FRM_RST_POS */ + data = (1 << 16) | (5); /* h=1,v=5 :ldim_param_frm_rst_pos */ + LDIM_WR_32Bits(REG_LD_FRM_RST_POS, data); + + /* LD_FRM_BL_START_POS */ + data = (1 << 16) | (6); /* ldim_param_frm_bl_start_pos; */ + LDIM_WR_32Bits(REG_LD_FRM_BL_START_POS, data); + + /* REG_LD_FRM_HBLAN_VHOLS */ + data = ((nPRM->reg_LD_LUT_VHo_LS & 0x7) << 16) | + ((6 & 0x1fff)) ; /*frm_hblank_num */ + LDIM_WR_32Bits(REG_LD_FRM_HBLAN_VHOLS, data); + + /* REG_LD_XLUT_DEMO_ROI_XPOS */ + data = ((nPRM->reg_LD_xlut_demo_roi_xend & 0x1fff) << 16) | + (nPRM->reg_LD_xlut_demo_roi_xstart & 0x1fff); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_XPOS, data); + + /* REG_LD_XLUT_DEMO_ROI_YPOS */ + data = ((nPRM->reg_LD_xlut_demo_roi_yend & 0x1fff) << 16) | + (nPRM->reg_LD_xlut_demo_roi_ystart & 0x1fff); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_YPOS, data); + + /* REG_LD_XLUT_DEMO_ROI_CTRL */ + data = ((nPRM->reg_LD_xlut_oroi_enable & 0x1) << 1) | + (nPRM->reg_LD_xlut_iroi_enable & 0x1); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_CTRL, data); + + /*LD_BLMAT_RAM_MISC*/ + LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, 384 & 0x1ff); + + /* X_idx: 12*16 */ + LDIM_WR_BASE_LUT(REG_LD_RGB_IDX_BASE, nPRM->X_idx[0], 16, 16); + + /* X_nrm[16]: 4 * 16 */ + LDIM_WR_BASE_LUT(REG_LD_RGB_NRMW_BASE_TXLX, nPRM->X_nrm[0], 4, 16); + + /*reg_LD_BLK_Hidx[33]: 14*33 */ + LDIM_WR_BASE_LUT(REG_LD_BLK_HIDX_BASE_TXLX, + nPRM->reg_LD_BLK_Hidx, 16, 33); + + /* reg_LD_BLK_Vidx[25]: 14*25 */ + LDIM_WR_BASE_LUT(REG_LD_BLK_VIDX_BASE_TXLX, + nPRM->reg_LD_BLK_Vidx, 16, 25); + + /* reg_LD_LUT_VHk_pos[32]/reg_LD_LUT_VHk_neg[32]: u8 */ + for (i = 0; i < 32; i++) + arrayTmp[i] = nPRM->reg_LD_LUT_VHk_pos[i]; + for (i = 0; i < 32; i++) + arrayTmp[32+i] = nPRM->reg_LD_LUT_VHk_neg[i]; + LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); + + /* reg_LD_LUT_VHo_pos[32]/reg_LD_LUT_VHo_neg[32]: s8 */ + for (i = 0; i < 32; i++) + arrayTmp[i] = nPRM->reg_LD_LUT_VHo_pos[i]; + for (i = 0; i < 32; i++) + arrayTmp[32+i] = nPRM->reg_LD_LUT_VHo_neg[i]; + LDIM_WR_BASE_LUT(REG_LD_LUT_VHO_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); + + /* reg_LD_LUT_HHk[32]:u8 */ + LDIM_WR_BASE_LUT(REG_LD_LUT_HHK_BASE_TXLX, nPRM->reg_LD_LUT_HHk, 8, 32); + + /*reg_LD_Reflect_Hdgr[20],reg_LD_Reflect_Vdgr[20], + * reg_LD_Reflect_Xdgr[4] + */ + for (i = 0; i < 20; i++) + arrayTmp[i] = nPRM->reg_LD_Reflect_Hdgr[i]; + for (i = 0; i < 20; i++) + arrayTmp[20+i] = nPRM->reg_LD_Reflect_Vdgr[i]; + for (i = 0; i < 4; i++) + arrayTmp[40+i] = nPRM->reg_LD_Reflect_Xdgr[i]; + LDIM_WR_BASE_LUT(REG_LD_REFLECT_DGR_BASE_TXLX, arrayTmp, 8, 44); + + /*reg_LD_LUT_Hdg_LEXT[8]/reg_LD_LUT_Vdg_LEXT[8]/reg_LD_LUT_VHk_LEXT[8]*/ + for (i = 0; i < 8; i++) + arrayTmp[i] = (nPRM->reg_LD_LUT_Hdg_LEXT_TXLX[i] & 0x3ff) | + ((nPRM->reg_LD_LUT_VHk_LEXT_TXLX[i] & 0x3ff) << 10) | + ((nPRM->reg_LD_LUT_Vdg_LEXT_TXLX[i] & 0x3ff) << 20); + LDIM_WR_BASE_LUT_DRT(REG_LD_LUT_LEXT_BASE_TXLX, arrayTmp, 8); + + /*reg_LD_LUT_Hdg[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_HDG_BASE_TXLX, + nPRM->reg_LD_LUT_Hdg_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_Vdg[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_VDG_BASE_TXLX, + nPRM->reg_LD_LUT_Vdg_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_VHk[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_BASE_TXLX, + nPRM->reg_LD_LUT_VHk_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_Id[16][24]: u3*16*24=u3*384 */ + LDIM_WR_BASE_LUT(REG_LD_LUT_ID_BASE_TXLX, nPRM->reg_LD_LUT_Id, 4, 384); + + /*enable the CBUS configure the RAM*/ + /*LD_MISC_CTRL0 {reg_blmat_ram_mode, + *1'h0,ram_bus_sel,ram_clk_sel,ram_clk_gate_en, + *2'h0,reg_hvcnt_bypass,reg_demo_synmode,reg_ldbl_synmode, + *reg_ldim_bl_en,soft_bl_start,reg_soft_rst) + */ + data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); + data = (data & (~(3 << 9))) | (1 << 8); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + /*X_lut[3][16][16]*/ + LDIM_WR_BASE_LUT_DRT(REG_LD_RGB_LUT_BASE, nPRM->X_lut2[0][0], 3*16*16); + + data = 0 | (0 << 1) | ((ldim_bl_en & 0x1) << 2) | + (ldim_hvcnt_bypass << 5) | (1 << 8) | + (3 << 9) | (1 << 12); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + LDIM_Update_Matrix(nPRM->BL_matrix, 16 * 24); + + kfree(arrayTmp); +} + +static unsigned int ldim_hw_reg_dump_table[] = { + LDIM_STTS_GCLK_CTRL0, + LDIM_STTS_WIDTHM1_HEIGHTM1, + LDIM_STTS_CTRL0, + LDIM_STTS_HIST_REGION_IDX, +}; + +int ldim_hw_reg_dump(char *buf) +{ + unsigned int reg, data32; + int i, size, len = 0; + + size = sizeof(ldim_hw_reg_dump_table) / sizeof(unsigned int); + for (i = 0; i < size; i++) { + reg = ldim_hw_reg_dump_table[i]; + data32 = Rd(reg); + len += sprintf(buf+len, "0x%x = 0x%08x\n", reg, data32); + } + + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + for (i = 0; i < 23; i++) { + reg = LDIM_STTS_HIST_SET_REGION; + data32 = Rd(reg); + len += sprintf(buf+len, "0x%x = 0x%08x\n", reg, data32); + } + + return len; +} + +/***** local dimming stts functions begin *****/ +/*hist mode: 0: comp0 hist only, 1: Max(comp0,1,2) for hist, + *2: the hist of all comp0,1,2 are calculated + */ +/*lpf_en 1: 1,2,1 filter on before finding max& hist*/ +/*rd_idx_auto_inc_mode 0: no self increase, 1: read index increase after + *read a 25/48 block, 2: increases every read and lock sub-idx + */ +/*one_ram_en 1: one ram mode; 0:double ram mode*/ +static void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, + unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, + unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en) +{ + int data32; + + Wr(LDIM_STTS_GCLK_CTRL0, 0x0); + Wr(LDIM_STTS_WIDTHM1_HEIGHTM1, resolution); + + data32 = 0x80000000 | ((pix_drop_mode & 0x3) << 29); + data32 = data32 | ((eol_en & 0x1) << 28); + data32 = data32 | ((one_ram_en & 0x1) << 27); + data32 = data32 | ((hist_mode & 0x3) << 22); + data32 = data32 | ((lpf_en & 0x1) << 21); + data32 = data32 | ((rd_idx_auto_inc_mode & 0xff) << 14); + Wr(LDIM_STTS_HIST_REGION_IDX, data32); +} + +static void ldim_stts_set_region_txlx(unsigned int resolution, + unsigned int blk_height, unsigned int blk_width, + unsigned int row_start, unsigned int col_start, + unsigned int blk_hnum) +{ + unsigned int hend0, hend1, hend2, hend3, hend4, hend5, + hend6, hend7, hend8, hend9, hend10, hend11, hend12, + hend13, hend14, hend15, hend16, hend17, hend18, + hend19, hend20, hend21, hend22, hend23; + unsigned int vend0, vend1, vend2, vend3, vend4, vend5, + vend6, vend7, vend8, vend9, vend10, vend11, + vend12, vend13, vend14, vend15; + unsigned int data32, k, h_index[24], v_index[16]; + + if (resolution == 0) { + h_index[0] = col_start + blk_width - 1; + for (k = 1; k < 24; k++) { + h_index[k] = h_index[k-1] + blk_width; + if (h_index[k] > 4095) + h_index[k] = 4095; /* clip U12 */ + } + v_index[0] = row_start + blk_height - 1; + for (k = 1; k < 16; k++) { + v_index[k] = v_index[k-1] + blk_height; + if (v_index[k] > 4095) + v_index[k] = 4095; /* clip U12 */ + } + hend0 = h_index[0];/*col_start + blk_width - 1;*/ + hend1 = h_index[1];/*hend0 + blk_width;*/ + hend2 = h_index[2];/*hend1 + blk_width;*/ + hend3 = h_index[3];/*hend2 + blk_width;*/ + hend4 = h_index[4];/*hend3 + blk_width;*/ + hend5 = h_index[5];/*hend4 + blk_width;*/ + hend6 = h_index[6];/*hend5 + blk_width;*/ + hend7 = h_index[7];/*hend6 + blk_width;*/ + hend8 = h_index[8];/*hend7 + blk_width;*/ + hend9 = h_index[9];/*hend8 + blk_width;*/ + hend10 = h_index[10];/*hend9 + blk_width ;*/ + hend11 = h_index[11];/*hend10 + blk_width;*/ + hend12 = h_index[12];/*hend11 + blk_width;*/ + hend13 = h_index[13];/*hend12 + blk_width;*/ + hend14 = h_index[14];/*hend13 + blk_width;*/ + hend15 = h_index[15];/*hend14 + blk_width;*/ + hend16 = h_index[16];/*hend15 + blk_width;*/ + hend17 = h_index[17];/*hend16 + blk_width;*/ + hend18 = h_index[18];/*hend17 + blk_width;*/ + hend19 = h_index[19];/*hend18 + blk_width;*/ + hend20 = h_index[20];/*hend19 + blk_width ;*/ + hend21 = h_index[21];/*hend20 + blk_width;*/ + hend22 = h_index[22];/*hend21 + blk_width;*/ + hend23 = h_index[23];/*hend22 + blk_width;*/ + vend0 = v_index[0];/*row_start + blk_height - 1;*/ + vend1 = v_index[1];/*vend0 + blk_height;*/ + vend2 = v_index[2];/*vend1 + blk_height;*/ + vend3 = v_index[3];/*vend2 + blk_height;*/ + vend4 = v_index[4];/*vend3 + blk_height;*/ + vend5 = v_index[5];/*vend4 + blk_height;*/ + vend6 = v_index[6];/*vend5 + blk_height;*/ + vend7 = v_index[7];/*vend6 + blk_height;*/ + vend8 = v_index[8];/*vend7 + blk_height;*/ + vend9 = v_index[9];/*vend8 + blk_height;*/ + vend10 = v_index[10];/*vend9 + blk_height;*/ + vend11 = v_index[11];/*vend10 + blk_height;*/ + vend12 = v_index[12];/*vend11 + blk_height;*/ + vend13 = v_index[13];/*vend12 + blk_height;*/ + vend14 = v_index[14];/*vend13 + blk_height;*/ + vend15 = v_index[15];/*vend14 + blk_height;*/ + + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, + ((((row_start & 0x1fff) << 16) & 0xffff0000) | + (col_start & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend1 & 0x1fff) << 16) + | (hend0 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend1 & 0x1fff) << 16) + | (vend0 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend3 & 0x1fff) << 16) + | (hend2 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend3 & 0x1fff) << 16) + | (vend2 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend5 & 0x1fff) << 16) + | (hend4 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend5 & 0x1fff) << 16) + | (vend4 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend7 & 0x1fff) << 16) + | (hend6 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend7 & 0x1fff) << 16) + | (vend6 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend9 & 0x1fff) << 16) + | (hend8 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend9 & 0x1fff) << 16) + | (vend8 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend11 & 0x1fff) << 16) + | (hend10 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend11 & 0x1fff) << 16) + | (vend10 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend13 & 0x1fff) << 16) + | (hend12 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend13 & 0x1fff) << 16) + | (vend12 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend15 & 0x1fff) << 16) + | (hend14 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend15 & 0x1fff) << 16) + | (vend14 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend17 & 0x1fff) << 16) + | (hend16 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend19 & 0x1fff) << 16) + | (hend18 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend21 & 0x1fff) << 16) + | (hend20 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend23 & 0x1fff) << 16) + | (hend22 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, blk_hnum); /*h region number*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0); /*line_n_int_num*/ + } else if (resolution == 1) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); + Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260);*/ + } else if (resolution == 2) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/*hv00*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/*h01*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/*v01*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/*h23*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/*v23*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/*h45*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/*v45*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/*h67*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/*v67*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h89*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v89*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1011*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1011*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1213*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1213*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1415*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1415*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1617*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1819*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2021*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2223*/ + } else if (resolution == 3) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); + Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); + Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 4) { /* 5x6 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 5) { /* 8x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 6) { /* 2x1 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 7) { /* 2x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 8) { /* 3x5 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 9) { /* 4x3 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 10) { /* 6x8 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } +} + +static void ldim_stts_set_region_tl1( + unsigned int resolution, + /* 0: auto calc by height/width/row_start/col_start + * 1: 720p + * 2: 1080p + */ + unsigned int height, unsigned int width, + unsigned int blk_height, unsigned int blk_width, + unsigned int row_start, unsigned int col_start, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int data32, h_region_num; + unsigned int heightm1, widthm1; + unsigned int lights_mode = 0; + unsigned int hend[24], vend[16], i; + + memset(hend, 0, (sizeof(unsigned int) * 24)); + memset(vend, 0, (sizeof(unsigned int) * 16)); + + /* 0:normal 1:>24 h region */ + if (blk_hnum > 24) + lights_mode = 1; + h_region_num = blk_hnum; + if (ldim_debug_print) { + pr_info("%s: lights_mode=%d, h_region_num=%d\n", + __func__, lights_mode, h_region_num); + } + + heightm1 = height - 1; + widthm1 = width - 1; + + if (resolution == 0) { + hend[0] = col_start + blk_width - 1; + for (i = 1; i < 24; i++) { + hend[i] = (hend[i-1] + blk_width >= widthm1) ? + hend[i-1] : (hend[i-1] + blk_width); + } + vend[0] = row_start + blk_height - 1; + for (i = 1; i < 16; i++) { + vend[i] = (vend[i-1] + blk_height >= heightm1) ? + vend[i-1] : (vend[i-1] + blk_height); + } + + if (lights_mode == 1) { /* 31 h region */ + vend[8] = (hend[23] + blk_width >= widthm1) ? + hend[23] : (hend[23] + blk_width); + for (i = 9; i < 16; i++) { + vend[i] = (vend[i-1] + blk_width >= widthm1) ? + vend[i-1] : (vend[i-1] + blk_width); + } + } + + Wr_reg_bits(LDIM_STTS_CTRL0, lights_mode, 22, 2); + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, + ((((row_start & 0x1fff) << 16) & 0xffff0000) | + (col_start & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[1] & 0x1fff) << 16) | + (hend[0] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[1] & 0x1fff) << 16) | + (vend[0] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[3] & 0x1fff) << 16) | + (hend[2] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[3] & 0x1fff) << 16) | + (vend[2] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[5] & 0x1fff) << 16) | + (hend[4] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[5] & 0x1fff) << 16) | + (vend[4] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[7] & 0x1fff) << 16) | + (hend[6] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[7] & 0x1fff) << 16) | + (vend[6] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[9] & 0x1fff) << 16) | + (hend[8] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[9] & 0x1fff) << 16) | + (vend[8] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[11] & 0x1fff) << 16) | + (hend[10] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[11] & 0x1fff) << 16) | + (vend[10] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[13] & 0x1fff) << 16) | + (hend[12] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[13] & 0x1fff) << 16) | + (vend[12] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[15] & 0x1fff) << 16) | + (hend[14] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[15] & 0x1fff) << 16) | + (vend[14] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[17] & 0x1fff) << 16) | + (hend[16] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[19] & 0x1fff) << 16) | + (hend[18] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[21] & 0x1fff) << 16) | + (hend[20] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[23] & 0x1fff) << 16) | + (hend[22] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, h_region_num); /*h region number*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0); /* line_n_int_num */ + } else if (resolution == 1) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); + Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260); */ + } else if (resolution == 2) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/* hv00 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/* h01 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/* v01 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/* h23 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/* v23 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/* h45 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/* v45 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/* h67 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/* v67 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h89 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v89 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1011 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1011 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1213 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1213 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1415 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1415 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1617 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1819 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h2021 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h2223 */ + } else if (resolution == 3) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); + Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); + Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 4) { /* 5x6 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 5) { /* 8x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 6) { /* 2x1 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 7) { /* 2x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 8) { /* 3x5 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 9) { /* 4x3 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 10) { /* 6x8 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } +} + +void ldim_stts_initial_txlx(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int resolution, blk_height, blk_width; + unsigned int row_start, col_start; + + blk_vnum = (blk_vnum == 0) ? 1 : blk_vnum; + blk_hnum = (blk_hnum == 0) ? 1 : blk_hnum; + + resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); + /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ + + blk_height = (pic_v - 8) / blk_vnum; + blk_width = (pic_h - 8) / blk_hnum; + row_start = (pic_v - (blk_height * blk_vnum)) >> 1; + col_start = (pic_h - (blk_width * blk_hnum)) >> 1; + + Wr_reg(LDIM_STTS_CTRL0, 7 << 2); + ldim_set_matrix_ycbcr2rgb(); + ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); + + ldim_stts_set_region_txlx(0, blk_height, blk_width, + row_start, col_start, blk_hnum); +} + +void ldim_stts_initial_tl1(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int resolution, blk_height, blk_width; + unsigned int row_start, col_start; + + blk_vnum = (blk_vnum == 0) ? 1 : blk_vnum; + blk_hnum = (blk_hnum == 0) ? 1 : blk_hnum; + + resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); + /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ + + blk_height = (pic_v - 8) / blk_vnum; + blk_width = (pic_h - 8) / blk_hnum; + row_start = (pic_v - (blk_height * blk_vnum)) >> 1; + col_start = (pic_h - (blk_width * blk_hnum)) >> 1; + + ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); + ldim_set_matrix_ycbcr2rgb(); + /*0:di 1:vdin 2:null 3:postblend 4:vpp out 5:vd1 6:vd2 7:osd1*/ + Wr_reg_bits(LDIM_STTS_CTRL0, 3, 3, 3); + + ldim_stts_set_region_tl1(0, pic_v, pic_h, blk_height, blk_width, + row_start, col_start, blk_vnum, blk_hnum); +} + +static unsigned int invalid_val_cnt; +void ldim_stts_read_region(unsigned int nrow, unsigned int ncol) +{ + unsigned int i, j, k; + unsigned int data32; + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + + if (invalid_val_cnt > 0xfffffff) + invalid_val_cnt = 0; + + Wr(LDIM_STTS_HIST_REGION_IDX, Rd(LDIM_STTS_HIST_REGION_IDX) + & 0xffffc000); + data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); + + for (i = 0; i < nrow; i++) { + for (j = 0; j < ncol; j++) { + data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); + for (k = 0; k < 17; k++) { + if (k == 16) { + data32 = Rd(LDIM_STTS_HIST_READ_REGION); + ldim_drv->max_rgb[i * ncol + j] + = data32; + } else { + data32 = Rd(LDIM_STTS_HIST_READ_REGION); + ldim_drv->hist_matrix[i * ncol * 16 + + j * 16 + k] = data32; + } + if (!(data32 & 0x40000000)) + invalid_val_cnt++; + } + } + } +} + +/* VDIN_MATRIX_YUV601_RGB */ +/* -16 1.164 0 1.596 0 */ +/* -128 1.164 -0.391 -0.813 0 */ +/* -128 1.164 2.018 0 0 */ +/*{0x07c00600, 0x00000600, 0x04a80000, 0x066204a8, 0x1e701cbf, 0x04a80812, + * 0x00000000, 0x00000000, 0x00000000,}, + */ +void ldim_set_matrix_ycbcr2rgb(void) +{ + Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); /* enable matrix */ + + Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x07c00600); + Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x00000600); + Wr(LDIM_STTS_MATRIX_COEF00_01, 0x04a80000); + Wr(LDIM_STTS_MATRIX_COEF02_10, 0x066204a8); + Wr(LDIM_STTS_MATRIX_COEF11_12, 0x1e701cbf); + Wr(LDIM_STTS_MATRIX_COEF20_21, 0x04a80812); + Wr(LDIM_STTS_MATRIX_COEF22, 0x00000000); + Wr(LDIM_STTS_MATRIX_OFFSET0_1, 0x00000000); + Wr(LDIM_STTS_MATRIX_OFFSET2, 0x00000000); +} + +void ldim_set_matrix_rgb2ycbcr(int mode) +{ + Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); + if (mode == 0) {/*ycbcr not full range, 601 conversion*/ + Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x0); + Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x0); + /* 0.257 0.504 0.098 */ + /* -0.148 -0.291 0.439 */ + /* 0.439 -0.368 -0.071 */ + Wr(LDIM_STTS_MATRIX_COEF00_01, (0x107 << 16) | 0x204); + Wr(LDIM_STTS_MATRIX_COEF02_10, (0x64 << 16) | 0x1f68); + Wr(LDIM_STTS_MATRIX_COEF11_12, (0x1ed6 << 16) | 0x1c2); + Wr(LDIM_STTS_MATRIX_COEF20_21, (0x1c2 << 16) | 0x1e87); + Wr(LDIM_STTS_MATRIX_COEF22, 0x1fb7); + + Wr(LDIM_STTS_MATRIX_OFFSET2, 0x0200); + } else if (mode == 1) {/*ycbcr full range, 601 conversion*/ + /* todo */ + } +} + +void ldim_remap_update_txlx(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en) +{ + unsigned int data; + + if (avg_update_en) { + /* LD_BKLIT_PARAM */ + data = LDIM_RD_32Bits(REG_LD_BKLIT_PARAM); + data = (data & (~0xfff)) | (nPRM->reg_BL_matrix_AVG & 0xfff); + LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); + + /* compensate */ + data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); + data = (data & (~0xfff)) | + (nPRM->reg_BL_matrix_Compensate & 0xfff); + LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + } + + if (matrix_update_en) { + data = nPRM->reg_LD_BLK_Vnum * nPRM->reg_LD_BLK_Hnum; + LDIM_Update_Matrix(nPRM->BL_matrix, data); + } +} diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h index 6fe28b425554..297dafa379c3 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h @@ -23,8 +23,8 @@ #define ASSIST_SPARE8_REG1 0x1f58 /*gxtvbb new add*/ -#define LDIM_STTS_CTRL0 0x1ac1 #define LDIM_STTS_GCLK_CTRL0 0x1ac0 +#define LDIM_STTS_CTRL0 0x1ac1 #define LDIM_STTS_WIDTHM1_HEIGHTM1 0x1ac2 #define LDIM_STTS_MATRIX_COEF00_01 0x1ac3 #define LDIM_STTS_MATRIX_COEF02_10 0x1ac4 From 0abca5cf8f1daa77690514ea3cdbcb2d70a72f15 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 3 Jan 2019 06:40:26 -0500 Subject: [PATCH 0540/1060] backlight: ldim: add analog pwm support [1/1] PD#SWPL-3702 Problem: local dimming need analog pwm function Solution: add analog pwm support Verify: x301 Change-Id: I502bb7505947c1f3670f44d0d307f9546f1d57fd Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c include/linux/amlogic/media/vout/lcd/aml_ldim.h --- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 19 ++++++++++++++++++- .../vout/backlight/aml_ldim/ldim_dev_drv.c | 8 ++++++++ .../media/vout/backlight/aml_ldim/ldim_drv.h | 3 ++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 491ffb5cabb6..c2b4d6e69336 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -979,7 +979,7 @@ bl_level_attr = <255 10 /*max, min*/ 128 128>; /*mid, mid_mapping*/ bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ - bl_power_attr = <0 /*en_gpio_index*/ + bl_power_attr = <0xff /*en_gpio_index*/ 1 0 /*on_value, off_value*/ 200 200>; /*on_delay(ms), off_delay(ms)*/ bl_ldim_region_row_col = <1 1>; @@ -989,6 +989,23 @@ */ ldim_dev_index = <1>; }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; }; bl_pwm_conf:bl_pwm_conf{ diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index 9dab744e1622..2876a9141e90 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -91,6 +91,14 @@ struct ldim_dev_config_s ldim_dev_config = { .pwm_duty_max = 100, .pwm_duty_min = 10, }, + .analog_pwm_config = { + .pwm_method = BL_PWM_POSITIVE, + .pwm_port = BL_PWM_MAX, + .pwm_freq = 1000, + .pwm_duty_max = 100, + .pwm_duty_min = 10, + }, + .dim_range_update = NULL, .bl_regnum = 0, diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index d186f59ab69e..76c23ce4b7f6 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -26,7 +26,8 @@ /*20181101: fix ldim_op_func null mistake, add new spi api support */ /*20181203: add 50/60hz change & iw7027 error handle support */ /*20181220: add tl1 support*/ -#define LDIM_DRV_VER "20181220" +/*20190103: add analog pwm support*/ +#define LDIM_DRV_VER "20190103" extern unsigned char ldim_debug_print; From 52398cc6cada06c182451cb00075480d647b433b Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 14 Jan 2019 20:56:01 +0800 Subject: [PATCH 0541/1060] backlight: ldim: add dev reg access api support [1/1] PD#TV-1481 Problem: need ldim_dev reg access uniform api Solution: add ldim_dev reg access uniform api Verify: x301 Change-Id: I72756d178ef70aac1f8b7fef842468f2e27a0ffe Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c --- .../amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index 2876a9141e90..9dab744e1622 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -91,14 +91,6 @@ struct ldim_dev_config_s ldim_dev_config = { .pwm_duty_max = 100, .pwm_duty_min = 10, }, - .analog_pwm_config = { - .pwm_method = BL_PWM_POSITIVE, - .pwm_port = BL_PWM_MAX, - .pwm_freq = 1000, - .pwm_duty_max = 100, - .pwm_duty_min = 10, - }, - .dim_range_update = NULL, .bl_regnum = 0, From 45845922e5fd425a95ae69ce7599d365a1bdcefe Mon Sep 17 00:00:00 2001 From: "shaochan.liu" Date: Thu, 28 Mar 2019 20:10:48 +0800 Subject: [PATCH 0542/1060] lcd: add lcd_driver support for tm2 [2/2] PD#SWPL-6398 Problem: add lcd_driver support Solution: add lcd_chip_tm2 and panel.dtsi Verify: ab301 Change-Id: I3cb5b67826ea2612e69b206168497771d5ced4b2 Signed-off-by: shaochan.liu Conflicts: MAINTAINERS arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts drivers/amlogic/media/vout/lcd/lcd_debug.c drivers/amlogic/media/vout/lcd/lcd_phy_config.c drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c drivers/amlogic/media/vout/lcd/lcd_tcon.c drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c --- MAINTAINERS | 12 +- .../amlogic/mesontm2_t962x3_ab301-panel.dtsi | 1066 +++++++++++++++++ .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 589 +++++++++ .../arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 5 + .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 1 + .../amlogic/mesontm2_t962x3_ab301-panel.dtsi | 1066 +++++++++++++++++ .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 589 +++++++++ .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 22 + .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 3 +- drivers/amlogic/media/vout/backlight/aml_bl.c | 10 + .../media/vout/backlight/aml_ldim/ldim_drv.c | 1 + .../amlogic/media/vout/lcd/lcd_clk_config.c | 1 + drivers/amlogic/media/vout/lcd/lcd_debug.c | 30 + .../amlogic/media/vout/lcd/lcd_phy_config.c | 566 +++++++++ .../media/vout/lcd/lcd_tablet/lcd_drv.c | 84 +- drivers/amlogic/media/vout/lcd/lcd_tcon.c | 2 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 19 +- drivers/amlogic/media/vout/lcd/lcd_vout.c | 10 + include/linux/amlogic/media/vout/lcd/aml_bl.h | 1 + .../linux/amlogic/media/vout/lcd/lcd_vout.h | 1 + 20 files changed, 4058 insertions(+), 20 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi create mode 100644 arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi create mode 100644 arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi create mode 100644 drivers/amlogic/media/vout/lcd/lcd_phy_config.c diff --git a/MAINTAINERS b/MAINTAINERS index b00b95ef06db..5fcd9917cdf1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14834,10 +14834,16 @@ M: Qianggui Song F: drivers/amlogic/pinctrl/pinctrl-meson-tm2.c F: include/dt-bindings/gpio/meson-tm2-gpio.h +AMLOGIC MESON TM2 CLOCK DRIVER +M: Jian Hu +F: driver/amlogic/clk/tm2/* -AMLOGIC TL1 VAD -M: Wenbiao Zhang -F: include/linux/amlogic/vad_api.h +AMLOGIC MESON TM2 LCD DTS +M: Shaochan Liu +F: arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi +F: arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi AMLOGIC SM1 S905X3 DTS M: Xiaoliang Wang diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi new file mode 100644 index 000000000000..e190a8a91098 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi @@ -0,0 +1,1066 @@ +/* + * arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tm2"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi new file mode 100644 index 000000000000..1842e68c7d0d --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -0,0 +1,589 @@ +/* + * arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 9fa15f293e1d..dbb1a8556fcb 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -19,6 +19,7 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab301-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB301"; @@ -1894,6 +1895,10 @@ status = "okay"; }; +&pwm_cd { + status = "okay"; +}; + &saradc { status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 5847b2b3073d..0648d6cf6c8d 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -19,6 +19,7 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab309-panel.dtsi" / { model = "Amlogic TM2 T962X3 AB309"; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi new file mode 100644 index 000000000000..e0c2c99489ba --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi @@ -0,0 +1,1066 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tm2"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi new file mode 100644 index 000000000000..8f0ad5ea1bf0 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -0,0 +1,589 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 08e7ebb2be8a..52aaa1423871 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -19,6 +19,7 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab301-panel.dtsi" / { model = "Amlogic TM2 T962E2 AB301"; @@ -92,6 +93,14 @@ linux,contiguous-region; }; + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + /* codec shared reserved */ codec_mm_reserved:linux,codec_mm_reserved { compatible = "amlogic, codec-mm-reserved"; @@ -1659,6 +1668,15 @@ output-low; }; }; +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; }; /* end of pinctrl_periphs */ @@ -1854,6 +1872,10 @@ status = "okay"; }; +&pwm_cd { + status = "okay"; +}; + &saradc { status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 9a7baefae854..69b23ed7db54 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -19,9 +19,10 @@ #include "mesontm2.dtsi" #include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab309-panel.dtsi" / { - model = "Amlogic TM2 T962E2 AB319"; + model = "Amlogic TM2 T962X3 AB309"; amlogic-dt-id = "tm2_t962x3_ab309"; compatible = "amlogic, tm2_t962x3_ab309"; diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index 275c99fe89e0..bec1f9996a15 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -3376,6 +3376,12 @@ static struct bl_data_s bl_data_sm1 = { .pwm_reg = pwm_reg_txlx, }; +static struct bl_data_s bl_data_tm2 = { + .chip_type = BL_CHIP_TM2, + .chip_name = "tm2", + .pwm_reg = pwm_reg_txlx, +}; + static const struct of_device_id bl_dt_match_table[] = { { .compatible = "amlogic, backlight-gxl", @@ -3413,6 +3419,10 @@ static const struct of_device_id bl_dt_match_table[] = { .compatible = "amlogic, backlight-sm1", .data = &bl_data_sm1, }, + { + .compatible = "amlogic, backlight-tm2", + .data = &bl_data_tm2, + }, {}, }; #endif diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index 5035be5d237c..6cfe4d25df26 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -3013,6 +3013,7 @@ int aml_ldim_probe(struct platform_device *pdev) /* ldim_op_func */ switch (bl_drv->data->chip_type) { case BL_CHIP_TL1: + case BL_CHIP_TM2: devp->ldim_op_func = &ldim_op_func_tl1; break; case BL_CHIP_TXLX: diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index cd776721a2d7..8f143badc2bf 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -2871,6 +2871,7 @@ static void lcd_clk_config_chip_init(struct lcd_clk_config_s *cConf) cConf->data = &lcd_clk_data_g12b_path0; break; case LCD_CHIP_TL1: + case LCD_CHIP_TM2: cConf->data = &lcd_clk_data_tl1; break; default: diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index bab975064fa4..0914100baeaf 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -597,6 +597,35 @@ static int lcd_info_print(char *buf, int offset) return len; } +static void lcd_reg_print_serializer(char *buf, int offset) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg0, reg1; + int n, len = 0; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + reg0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg0 = HHI_LVDS_TX_PHY_CNTL0; + reg1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } + + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, "\nserializer regs:\n"); + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, + "HHI_LVDS_TX_PHY_CNTL0 [0x%04x] = 0x%08x\n", + reg0, lcd_hiu_read(reg0)); + len += snprintf((buf+len), n, + "HHI_LVDS_TX_PHY_CNTL1 [0x%04x] = 0x%08x\n", + reg1, lcd_hiu_read(reg1)); +} + static int lcd_reg_print_ttl(char *buf, int offset) { unsigned int reg; @@ -4464,6 +4493,7 @@ int lcd_debug_probe(void) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: + case LCD_CHIP_TM2: lcd_debug_info_reg = &lcd_debug_info_reg_tl1; lcd_debug_info_if_lvds.reg_dump_phy = lcd_reg_print_phy_analog_tl1; diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c new file mode 100644 index 000000000000..93e3042d0d2a --- /dev/null +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c @@ -0,0 +1,566 @@ +/* + * drivers/amlogic/media/vout/lcd/lcd_phy_config.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lcd_reg.h" +#include "lcd_phy_config.h" +#include "lcd_common.h" + +static unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf) +{ + unsigned int channel_on = 0; + + if (pconf->lcd_control.lvds_config->dual_port == 0) { + if (pconf->lcd_control.lvds_config->lane_reverse == 0) { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0xf; + break; + case 8: + channel_on = 0x1f; + break; + case 10: + default: + channel_on = 0x3f; + break; + } + } else { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0x3c; + break; + case 8: + channel_on = 0x3e; + break; + case 10: + default: + channel_on = 0x3f; + break; + } + } + if (pconf->lcd_control.lvds_config->port_swap == 1) + channel_on = (channel_on << 6); /* use channel B */ + } else { + if (pconf->lcd_control.lvds_config->lane_reverse == 0) { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0x3cf; + break; + case 8: + channel_on = 0x7df; + break; + case 10: + default: + channel_on = 0xfff; + break; + } + } else { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0xf3c; + break; + case 8: + channel_on = 0xfbe; + break; + case 10: + default: + channel_on = 0xfff; + break; + } + } + } + return channel_on; +} + +void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; + unsigned int data32, size; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lvds_config_s *lvds_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + lvds_conf = pconf->lcd_control.lvds_config; + if (status) { + vswing = lvds_conf->phy_vswing & 0xf; + preem = lvds_conf->phy_preem & 0xf; + clk_vswing = lvds_conf->phy_clk_vswing & 0xf; + clk_preem = lvds_conf->phy_clk_preem & 0xf; + if (lcd_debug_print_flag) + LCDPR("vswing=0x%x, prrem=0x%x\n", vswing, preem); + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + default: + if (vswing > 7) { + LCDERR("%s: invalid vswing=0x%x, use default\n", + __func__, vswing); + vswing = LVDS_PHY_VSWING_DFT; + } + if (preem > 7) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = LVDS_PHY_PREEM_DFT; + } + if (clk_vswing > 3) { + LCDERR( + "%s: invalid clk_vswing=0x%x, use default\n", + __func__, clk_vswing); + clk_vswing = LVDS_PHY_CLK_VSWING_DFT; + } + if (clk_preem > 7) { + LCDERR( + "%s: invalid clk_preem=0x%x, use default\n", + __func__, clk_preem); + clk_preem = LVDS_PHY_CLK_PREEM_DFT; + } + channel_on = lcd_lvds_channel_on_value(pconf); + + data32 = LVDS_PHY_CNTL1_G9TV | + (vswing << 26) | (preem << 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + data32 = LVDS_PHY_CNTL2_G9TV; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + data32 = LVDS_PHY_CNTL3_G9TV | + (channel_on << 16) | + (clk_vswing << 8) | + (clk_preem << 5); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + break; + } + } else { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + break; + } + } +} + +void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem, ext_pullup; + unsigned int data32, size; + unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct vbyone_config_s *vbyone_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + vbyone_conf = pconf->lcd_control.vbyone_config; + if (status) { + ext_pullup = (vbyone_conf->phy_vswing >> 4) & 0x3; + vswing = vbyone_conf->phy_vswing & 0xf; + preem = vbyone_conf->phy_preem & 0xf; + if (lcd_debug_print_flag) { + LCDPR("vswing=0x%x, prrem=0x%x\n", + vbyone_conf->phy_vswing, preem); + } + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0x1; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + if (ext_pullup) { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xf02027a0 | vswing); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + default: + if (vswing > 7) { + LCDERR("%s: invalid vswing=0x%x, use default\n", + __func__, vswing); + vswing = VX1_PHY_VSWING_DFT; + } + if (preem > 7) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = VX1_PHY_PREEM_DFT; + } + if (ext_pullup) { + data32 = VX1_PHY_CNTL1_G9TV_PULLUP | + (vswing << 3); + } else { + data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | + (rinner_table[ext_pullup] << 8); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + data32 = VX1_PHY_CNTL3_G9TV; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + break; + } + } else { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + break; + } + } +} + +void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem; + unsigned int data32, size, cntl16; + struct mlvds_config_s *mlvds_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + mlvds_conf = pconf->lcd_control.mlvds_config; + if (status) { + vswing = mlvds_conf->phy_vswing & 0xf; + preem = mlvds_conf->phy_preem & 0xf; + if (lcd_debug_print_flag) + LCDPR("vswing=0x%x, prrem=0x%x\n", vswing, preem); + + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + cntl16 = (mlvds_conf->pi_clk_sel << 12); + cntl16 |= 0x80000000; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, cntl16); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + } +} + +void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem; + unsigned int data32, size, cntl16; + struct p2p_config_s *p2p_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + p2p_conf = pconf->lcd_control.p2p_config; + if (status) { + vswing = p2p_conf->phy_vswing & 0xf; + preem = p2p_conf->phy_preem & 0xf; + if (lcd_debug_print_flag) + LCDPR("vswing=0x%x, prrem=0x%x\n", vswing, preem); + + switch (p2p_conf->p2p_type) { + case P2P_CEDS: + case P2P_CMPI: + case P2P_ISP: + case P2P_EPI: + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0x1; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027a0 | vswing); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + case P2P_CHPI: /* low common mode */ + case P2P_CSPI: + case P2P_USIT: + size = sizeof(p2p_low_common_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0x1; + } + data32 = p2p_low_common_phy_preem_tl1[preem]; + cntl16 = 0x80000000; + if (p2p_conf->p2p_type == P2P_CHPI) { + /* weakly pull down */ + data32 &= ~((1 << 19) | (1 << 3)); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xfe60027f); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, cntl16); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + default: + LCDERR("%s: invalid p2p_type %d\n", + __func__, p2p_conf->p2p_type); + break; + } + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + } +} + +void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int phy_reg, phy_bit, phy_width; + unsigned int lane_cnt; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (status) { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_G12A: + case LCD_CHIP_G12B: + case LCD_CHIP_SM1: + /* HHI_MIPI_CNTL0 */ + /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL0, + (0xa487 << 16) | (0x8 << 0)); + + /* HHI_MIPI_CNTL1 */ + /* DIF_REF_CTL2:15-0bit; bandgap bit16 */ + lcd_hiu_write(HHI_MIPI_CNTL1, + (0x1 << 16) | (0x002e << 0)); + + /* HHI_MIPI_CNTL2 */ + /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL2, + (0x2680 << 16) | (0x45a << 0)); + break; + default: /* LCD_CHIP_AXG */ + /* HHI_MIPI_CNTL0 */ + /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 0x1b8, 16, 10); + lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 26, 1); /* bandgap */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 29, 1); /* current */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 31, 1); + lcd_hiu_setb(HHI_MIPI_CNTL0, 0x8, 0, 16); + + /* HHI_MIPI_CNTL1 */ + /* DIF_REF_CTL2:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL1, (0x001e << 0)); + + /* HHI_MIPI_CNTL2 */ + /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL2, + (0x26e0 << 16) | (0x459 << 0)); + break; + } + + phy_reg = HHI_MIPI_CNTL2; + phy_bit = MIPI_PHY_LANE_BIT; + phy_width = MIPI_PHY_LANE_WIDTH; + switch (pconf->lcd_control.mipi_config->lane_num) { + case 1: + lane_cnt = DSI_LANE_COUNT_1; + break; + case 2: + lane_cnt = DSI_LANE_COUNT_2; + break; + case 3: + lane_cnt = DSI_LANE_COUNT_3; + break; + case 4: + lane_cnt = DSI_LANE_COUNT_4; + break; + default: + lane_cnt = 0; + break; + } + lcd_hiu_setb(phy_reg, lane_cnt, phy_bit, phy_width); + } else { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_G12A: + case LCD_CHIP_G12B: + case LCD_CHIP_SM1: + lcd_hiu_write(HHI_MIPI_CNTL0, 0); + lcd_hiu_write(HHI_MIPI_CNTL1, 0); + lcd_hiu_write(HHI_MIPI_CNTL2, 0); + break; + default:/* LCD_CHIP_AXG */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 16, 10); + lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 31, 1); + lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 0, 16); + lcd_hiu_write(HHI_MIPI_CNTL1, 0x6); + lcd_hiu_write(HHI_MIPI_CNTL2, 0x00200000); + break; + } + } +} diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 02659768e24c..57db7a9100f1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -376,7 +376,9 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_vcbus_write(ENCL_INBUF_CNTL1, (1 << 14) | (h_active - 1)); + case LCD_CHIP_TM2: + /*[15:14]: 2'b10 or 2'b01*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); break; default: @@ -412,6 +414,19 @@ static void lcd_ttl_control_set(struct lcd_config_s *pconf) static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) { unsigned int phy_div; + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } if (pconf->lcd_control.lvds_config->dual_port) phy_div = 2; @@ -421,7 +436,15 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) /* set fifo_clk_sel: div 7 */ lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (1 << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, @@ -482,10 +505,18 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) (1 << 12) | /* g_select //0:R, 1:G, 2:B, 3:0 */ (2 << 14)); /* b_select //0:R, 1:G, 2:B, 3:0 */ - lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); - - if (lane_reverse) - lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); + lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); + break; + default: + lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); + if (lane_reverse) + lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + break; + } lcd_vcbus_write(LVDS_GEN_CNTL, (lcd_vcbus_read(LVDS_GEN_CNTL) | @@ -512,6 +543,20 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) { unsigned int lcd_bits; unsigned int div_sel, phy_div; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } phy_div = pconf->lcd_control.vbyone_config->phy_div; lcd_bits = pconf->lcd_basic.lcd_bits; @@ -533,7 +578,15 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) /* set fifo_clk_sel */ lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, @@ -726,7 +779,22 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* lcd_vcbus_setb(LCD_PORT_SWAP, 1, 8, 1);//reverse lane output order */ /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ - lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1); + /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + break; + default: + lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + break; + } + lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); + lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); /*force vencl clk enable, otherwise, it might auto turn off by mipi DSI diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index 76a90b826679..b4fd006ff7b9 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -649,7 +649,7 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_tcon_data = &tcon_data_tl1; + case LCD_CHIP_TM2: switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 28a231f15634..d06ce74856a9 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -379,7 +379,9 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_vcbus_write(ENCL_INBUF_CNTL1, (1 << 14) | (h_active - 1)); + case LCD_CHIP_TM2: + /*[15:14]: 2'b10 or 2'b01*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); break; default: @@ -407,6 +409,7 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: + case LCD_CHIP_TM2: reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; break; @@ -427,6 +430,7 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); switch (lcd_drv->data->chip_type) { /* pn swap */ case LCD_CHIP_TL1: + case LCD_CHIP_TM2: lcd_hiu_setb(reg_cntl0, 1, 2, 1); break; default: @@ -496,12 +500,9 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - ch_swap0 = 0x3210; - ch_swap1 = 0x7654; - ch_swap2 = 0xba98; - lcd_vcbus_write(LVDS_CH_SWAP0, ch_swap0); - lcd_vcbus_write(LVDS_CH_SWAP1, ch_swap1); - lcd_vcbus_write(LVDS_CH_SWAP2, ch_swap2); + case LCD_CHIP_TM2: + lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); + lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); break; default: lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); @@ -635,6 +636,7 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: + case LCD_CHIP_TM2: reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; break; @@ -667,6 +669,7 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); switch (lcd_drv->data->chip_type) { /* pn swap */ case LCD_CHIP_TL1: + case LCD_CHIP_TM2: lcd_hiu_setb(reg_cntl0, 1, 2, 1); break; default: @@ -766,6 +769,7 @@ static void lcd_vbyone_hw_filter(int flag) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: + case LCD_CHIP_TM2: if (flag) { lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xffff); lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0xf); @@ -1450,6 +1454,7 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: + case LCD_CHIP_TM2: reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index f804126f766e..95c87fd6612f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -1371,6 +1371,12 @@ static struct lcd_data_s lcd_data_sm1 = { .reg_map_table = &lcd_reg_axg[0], }; +static struct lcd_data_s lcd_data_tm2 = { + .chip_type = LCD_CHIP_TM2, + .chip_name = "tm2", + .reg_map_table = &lcd_reg_tl1[0], +}; + static const struct of_device_id lcd_dt_match_table[] = { { .compatible = "amlogic, lcd-gxl", @@ -1408,6 +1414,10 @@ static const struct of_device_id lcd_dt_match_table[] = { .compatible = "amlogic, lcd-sm1", .data = &lcd_data_sm1, }, + { + .compatible = "amlogic, lcd-tm2", + .data = &lcd_data_tm2, + }, {}, }; #endif diff --git a/include/linux/amlogic/media/vout/lcd/aml_bl.h b/include/linux/amlogic/media/vout/lcd/aml_bl.h index 04dc80b0171b..4b33bcb24076 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_bl.h +++ b/include/linux/amlogic/media/vout/lcd/aml_bl.h @@ -51,6 +51,7 @@ enum bl_chip_type_e { BL_CHIP_G12B, BL_CHIP_TL1, BL_CHIP_SM1, + BL_CHIP_TM2, BL_CHIP_MAX, }; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 62fbc8b07952..d7a3632ee928 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -93,6 +93,7 @@ enum lcd_chip_e { LCD_CHIP_G12B, /* 6 */ LCD_CHIP_TL1, /* 7 */ LCD_CHIP_SM1, /* 8 */ + LCD_CHIP_TM2, /* 9 */ LCD_CHIP_MAX, }; From 2c1e50bcca1f67bfb68cc70967209ac280393247 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 8 Mar 2019 18:57:49 +0800 Subject: [PATCH 0543/1060] hdmitx: add dongle_mode case for low power [2/2] PD#SWPL-5302 Problem: For dongle products, it is connected to TV directly, and some parameters are different from mbox. Solution: Add dongle mode for driver's usage Verify: U211/S905Y2 Change-Id: Ibe45b167800d3b830d78ca8e9d7b67efd64d8564 Signed-off-by: Zongdong Jiao Conflicts: drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c --- drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c index 3f0e4df5d9e5..9bd4e86af390 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c @@ -194,7 +194,6 @@ static void set_hpll_hclk_dongle_5940m(void) void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk) { - unsigned int m, m1, m2; struct hdmitx_dev *hdev = get_hdmitx_device(); switch (clk) { From 4cc9254223fd4680e8bbcf29180f03d55a2f0b93 Mon Sep 17 00:00:00 2001 From: Bichao Zheng Date: Fri, 1 Mar 2019 14:33:02 +0800 Subject: [PATCH 0544/1060] irblaster: meson: refactored irblaster driver [1/1] PD#SWPL-1856 Problem: refactored irblaster code Solution: 1. Refactor the code according to the core, provider, and consumer frameworks. 2. Provide software encode to let irblaster work according to different protocols 3. Provide a unified consumer interface to allow other consumer drivers to use irblaster. Verify: test pass on g12a_u200_v1 Change-Id: Ifd841ef0ed741b7fd721defc25691744ea2103f0 Signed-off-by: Bichao Zheng Conflicts: arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm64/boot/dts/amlogic/axg_s410.dts arch/arm64/boot/dts/amlogic/mesontxl.dtsi --- MAINTAINERS | 13 +- arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts | 8 - arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts | 8 - arch/arm/boot/dts/amlogic/mesonaxg.dtsi | 20 +- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 20 +- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 18 +- arch/arm/boot/dts/amlogic/mesongxl.dtsi | 22 + arch/arm/boot/dts/amlogic/mesongxm.dtsi | 22 + arch/arm/boot/dts/amlogic/mesontl1.dtsi | 5 +- arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 19 +- arch/arm/configs/meson64_a32_defconfig | 4 +- .../boot/dts/amlogic/axg_s400_v03gva.dts | 8 - arch/arm64/boot/dts/amlogic/axg_s410.dts | 1421 +++++++++++++++++ .../boot/dts/amlogic/axg_s420_v03gva.dts | 8 - arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 20 +- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 20 +- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 18 +- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 21 + arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 22 + arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 5 +- arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 20 +- arch/arm64/configs/meson64_defconfig | 4 +- drivers/amlogic/Makefile | 2 +- drivers/amlogic/irblaster/Kconfig | 31 +- drivers/amlogic/irblaster/Makefile | 10 +- drivers/amlogic/irblaster/aml-irblaster.c | 430 +++++ drivers/amlogic/irblaster/core.c | 366 +++++ drivers/amlogic/irblaster/encoder.c | 267 ++++ drivers/amlogic/irblaster/irblaster-meson.c | 415 +++++ .../amlogic/irblaster/irblaster-nec-encoder.c | 180 +++ .../amlogic/irblaster/irblaster-rca-encoder.c | 99 ++ drivers/amlogic/irblaster/sysfs.c | 275 ++++ include/linux/amlogic/irblaster.h | 121 ++ include/linux/amlogic/irblaster_consumer.h | 55 + include/linux/amlogic/irblaster_encoder.h | 97 ++ 35 files changed, 3946 insertions(+), 128 deletions(-) create mode 100644 arch/arm64/boot/dts/amlogic/axg_s410.dts create mode 100644 drivers/amlogic/irblaster/aml-irblaster.c create mode 100644 drivers/amlogic/irblaster/core.c create mode 100644 drivers/amlogic/irblaster/encoder.c create mode 100644 drivers/amlogic/irblaster/irblaster-meson.c create mode 100644 drivers/amlogic/irblaster/irblaster-nec-encoder.c create mode 100644 drivers/amlogic/irblaster/irblaster-rca-encoder.c create mode 100644 drivers/amlogic/irblaster/sysfs.c create mode 100644 include/linux/amlogic/irblaster.h create mode 100644 include/linux/amlogic/irblaster_consumer.h create mode 100644 include/linux/amlogic/irblaster_encoder.h diff --git a/MAINTAINERS b/MAINTAINERS index 5fcd9917cdf1..85a81814e1f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14060,13 +14060,6 @@ AMLOGIC AXG ADD AO CLK M: Yun Cai F: drivers/amlogic/clk/axg/axg_ao.c -AMLOGIC Irblaster driver -M: Zan Peng -F: drivers/amlogic/irblaster/irblaster.c -F: drivers/amlogic/irblaster/irblaster.h -F: drivers/amlogic/irblaster/Kconfig -F: drivers/amlogic/irblaster/Makefile - AMLOGIC AXG ADD CLKMSR INTERFACE M: wang xing F: include/linux/amlogic/clk_measure.h @@ -14422,9 +14415,9 @@ F: drivers/amlogic/cpufreq/meson-cpufreq.c F: drivers/amlogic/clk/clk-cpu-fclk-composite.c AMLOGIC Irblaster driver -M: yu.tu -F: drivers/amlogic/irblaster/meson-irblaster.c -F: drivers/amlogic/irblaster/meson-irblaster.h +M: Bichao.Zheng +F: drivers/amlogic/irblaster/* +F: include/linux/amlogic/irblaster* AMLOGIC THERMAL DRIVER M: Huan Biao diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts index 38895bcc911d..6969131e354c 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts @@ -421,14 +421,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - vpu { compatible = "amlogic, vpu-axg"; dev_name = "vpu"; diff --git a/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts index 594190f2d64b..f49e3e48a097 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts @@ -316,14 +316,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index 15a0de94ab31..afc6d9c11ca5 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -466,6 +466,16 @@ clock-names = "clk_i2c"; clock-frequency = <100000>; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -741,16 +751,6 @@ }; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0xff8000c0 0x10>, - <0xff800040 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; - saradc:saradc { compatible = "amlogic,meson-axg-saradc"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index c304dfd5a86d..b8aeaeec1e8d 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -744,6 +744,17 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -1327,15 +1338,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0xff80014c 0x10>, - <0xff800040 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "okay"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index f3eaf402f1ff..b13e3f39a8df 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -810,6 +810,15 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -1438,15 +1447,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0xff80014c 0x10>, - <0xff800040 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index a8cda637f231..419d03bbd5f5 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -520,6 +520,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -632,6 +640,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index e336565a37d6..9c74f5a7953d 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -627,6 +627,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -732,6 +740,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index b57049c7122f..f9ec2f20488a 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -879,11 +879,12 @@ max_frame_time = <200>; }; - meson_irblaster: irblaster@14c { + irblaster: meson-irblaster@14c { compatible = "amlogic, meson_irblaster"; reg = <0x14c 0x10>, <0x40 0x4>; - interrupts = <0 198 1>; + #irblaster-cells = <2>; + interrupts = ; status = "disabled"; }; diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 417cedf1e252..8c7a8c066e3e 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -838,12 +838,12 @@ status = "disabled"; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + status = "disabled"; }; @@ -1028,6 +1028,13 @@ }; }; + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao6"; + function = "ir_out"; + }; + }; + pwmleds_pins:pwmleds { mux { diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 948702e23717..f07a46f44ceb 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -363,7 +363,9 @@ CONFIG_AMLOGIC_WIFI=y CONFIG_AMLOGIC_BT_DEVICE=y CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PCIE=y -CONFIG_AMLOGIC_IRBLASTER=y +CONFIG_AMLOGIC_IRBLASTER_CORE=y +CONFIG_AMLOGIC_IRBLASTER_MESON=y +CONFIG_AMLOGIC_IRBLASTER_PROTOCOL=y CONFIG_AMLOGIC_IIO=y CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_DDR_TOOL=y diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts index f805271bbd23..a2e2f418e02b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts @@ -421,14 +421,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - vpu { compatible = "amlogic, vpu-axg"; dev_name = "vpu"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s410.dts b/arch/arm64/boot/dts/amlogic/axg_s410.dts new file mode 100644 index 000000000000..0e16cedf2cd1 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/axg_s410.dts @@ -0,0 +1,1421 @@ +/* + * arch/arm64/boot/dts/amlogic/axg_s410.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +//#include "mesonaxg_s400-panel.dtsi" +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s410_1g"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x8000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x0 0x3e000000 0x0 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + misc{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0xF00000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x3C00000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0x0 0xffe09080 0x0 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xf9800000 0x0 0x400000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xf9f00000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disable"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xfa000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfa400000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0x0 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disable"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "disable"; + }; + + /* Audio Related start */ + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF632000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + audiolocker_base { + reg = <0x0 0xFF64A000 0x0 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdma>; + frame-master = <&aml_tdma>; + suffix-name = "alsaPORT-pcm"; + cpu{ + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + suffix-name = "alsaPORT-i2sPlayback"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + prefix-names = "5707_A", "5707_B"; + sound-dai = <&tas5707_36 &tas5707_3a + &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + * enable external loopback + * and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "disable"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "disable"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30040 0>; + duty-cycle = <15020>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30030 0>; + duty-cycle = <15015>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe07000 0x0 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <8>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe05000 0x0 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-fb"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d"; + dev_name = "ge2d"; + status = "disable"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_GE2D_GATE>, + <&clkc CLKID_G2D>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "disable"; + key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; + key_num = <6>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106>; + key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "disable"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "disable"; +}; + +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_4 0>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "okay"; + }; +}; + +/* for mic board */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + aml_pca9557: aml_pca9557@0x1f { + compatible = "aml, ledring"; + reg = <0x1f>; + mode = <0>; /*0: 6-led 1: 4key+2led */ + key_num = <4>; + led_dev_name = "aml_ledring"; + key_dev_name = "aml_pca_key"; + key_name = "mute", "pause", "vol+", "vol-"; + key_value = <200 201 202 203>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disable"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disable"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disable"; + }; + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disable"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disable"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disable"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236"; + reg = <0x3c>; + status = "disable"; + led1_r { + label="LED1_R"; + reg_offset = <24>; + }; + led1_g { + label="LED1_G"; + reg_offset = <23>; + }; + led1_b { + label="LED1_B"; + reg_offset = <22>; + }; + led2_r { + label="LED2_R"; + reg_offset = <21>; + }; + led2_g { + label="LED2_G"; + reg_offset = <20>; + }; + led2_b { + label="LED2_B"; + reg_offset = <19>; + }; + led3_r { + label="LED3_R"; + reg_offset = <18>; + }; + led3_g { + label="LED3_G"; + reg_offset = <17>; + }; + led3_b { + label="LED3_B"; + reg_offset = <16>; + }; + led4_r { + label="LED4_R"; + reg_offset = <15>; + }; + led4_g { + label="LED4_G"; + reg_offset = <14>; + }; + led4_b { + label="LED4_B"; + reg_offset = <13>; + }; + led5_r { + label="LED5_R"; + reg_offset = <36>; + }; + led5_g { + label="LED5_G"; + reg_offset = <35>; + }; + led5_b { + label="LED5_B"; + reg_offset = <34>; + }; + led6_r { + label="LED6_R"; + reg_offset = <33>; + }; + led6_g { + label="LED6_G"; + reg_offset = <32>; + }; + led6_b { + label="LED6_B"; + reg_offset = <31>; + }; + led7_r { + label="LED7_R"; + reg_offset = <30>; + }; + led7_g { + label="LED7_G"; + reg_offset = <29>; + }; + led7_b { + label="LED7_B"; + reg_offset = <28>; + }; + led8_r { + label="LED8_R"; + reg_offset = <27>; + }; + led8_g { + label="LED8_G"; + reg_offset = <26>; + }; + led8_b { + label="LED8_B"; + reg_offset = <25>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1>; + dai-tdm-lane-slot-mask-out = <0 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmin_b>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = + "tdmb_slv_sclk", + "tdmb_slv_fs", + "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts index 6f3198ecf3f0..08207f9e8c83 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts @@ -316,14 +316,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index 15d6e3785075..ecc71cff7fef 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -467,6 +467,16 @@ clock-names = "clk_i2c"; clock-frequency = <100000>; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -742,16 +752,6 @@ }; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0x0 0xff8000c0 0x0 0x10>, - <0x0 0xff800040 0x0 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; - saradc:saradc { compatible = "amlogic,meson-axg-saradc"; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index ac2df4a76968..f1d13fdf7c34 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -754,6 +754,17 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0x14c 0x0 0x10>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -1337,15 +1348,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0x0 0xff80014c 0x0 0x10>, - <0x0 0xff800040 0x0 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "okay"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 5b92ba775776..86098ac55816 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -820,6 +820,15 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0x14c 0x0 0x10>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -1448,15 +1457,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0x0 0xff80014c 0x0 0x10>, - <0x0 0xff800040 0x0 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index e464b6bed8a7..aa7b9950261b 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -507,6 +507,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -620,6 +628,19 @@ }; }; + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index be68834f1e45..24ba0cc5069a 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -627,6 +627,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -732,6 +740,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 7eeb51c079dd..fd55efc15ec5 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -900,11 +900,12 @@ max_frame_time = <200>; }; - meson_irblaster: irblaster@14c { + irblaster: meson-irblaster@14c { compatible = "amlogic, meson_irblaster"; reg = <0x0 0x14c 0x0 0x10>, <0x0 0x40 0x0 0x4>; - interrupts = <0 198 1>; + #irblaster-cells = <2>; + interrupts = ; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 8b78e147be1c..0b4a3af42277 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -838,15 +838,14 @@ status = "disabled"; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + status = "disabled"; }; - remote: rc@8040 { compatible = "amlogic, aml_remote"; dev_name = "meson-remote"; @@ -1028,6 +1027,13 @@ }; }; + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao6"; + function = "ir_out"; + }; + }; + pwmleds_pins:pwmleds { mux { diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 62100c08089c..9fb51faf6dde 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -358,7 +358,9 @@ CONFIG_AMLOGIC_WIFI=y CONFIG_AMLOGIC_BT_DEVICE=y CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PCIE=y -CONFIG_AMLOGIC_IRBLASTER=y +CONFIG_AMLOGIC_IRBLASTER_CORE=y +CONFIG_AMLOGIC_IRBLASTER_MESON=y +CONFIG_AMLOGIC_IRBLASTER_PROTOCOL=y CONFIG_AMLOGIC_IIO=y CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_DDR_TOOL=y diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index 4ef2059bbd30..69d054f2b64b 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -101,7 +101,7 @@ obj-$(CONFIG_AMLOGIC_POWER) += power/ obj-$(CONFIG_AMLOGIC_PCIE) += pci/ -obj-$(CONFIG_AMLOGIC_IRBLASTER) += irblaster/ +obj-$(CONFIG_AMLOGIC_IRBLASTER_CORE) += irblaster/ obj-$(CONFIG_AMLOGIC_IIO) += iio/ diff --git a/drivers/amlogic/irblaster/Kconfig b/drivers/amlogic/irblaster/Kconfig index 6c35ae80350a..6e35faa39216 100644 --- a/drivers/amlogic/irblaster/Kconfig +++ b/drivers/amlogic/irblaster/Kconfig @@ -1,11 +1,34 @@ # -# Input core configuration +# Amlogic IRBLASTER # -config AMLOGIC_IRBLASTER - bool "Amlogic irblaster device surport" + +menuconfig AMLOGIC_IRBLASTER_CORE + tristate "Amlogic IRBLASTER Support" default n help - Say Y here if you want to use the amlogic irblaster. + This is the core code of amlogic irblaster. Say Y you + can use the core api to implement the irblaster controller driver + and use the api in the core to control the irblaster. + This option alone add core code. +if AMLOGIC_IRBLASTER_CORE +config AMLOGIC_IRBLASTER_MESON + tristate "Amlogic Meson SoC irblaster driver" + default n + help + This enable irblaster support for soc mesom (irblaster communication + controller) available in Amlogic Meson SoCs. + If you want to use meson irblaster interface, + say Y here.If you are not sure, say N. +config AMLOGIC_IRBLASTER_PROTOCOL + tristate "Add Amlogic Meson irblaster encode" + default n + help + This enables encode mode support for the irblaster (communication + controller) available in Amlogic Meson SoCs. + If you want to use meson irblaster interface, + say Y here.If you are not sure, say N. + +endif diff --git a/drivers/amlogic/irblaster/Makefile b/drivers/amlogic/irblaster/Makefile index c406f7a50d1b..22c05b0257b6 100644 --- a/drivers/amlogic/irblaster/Makefile +++ b/drivers/amlogic/irblaster/Makefile @@ -1,6 +1,4 @@ -# -# Makefile for the remote control drivers -# - -# Each configuration option enables a list of files. -obj-$(CONFIG_AMLOGIC_IRBLASTER) += irblaster.o meson-irblaster.o +obj-$(CONFIG_AMLOGIC_IRBLASTER_CORE) += core.o sysfs.o +obj-$(CONFIG_AMLOGIC_IRBLASTER_MESON) += irblaster-meson.o aml-irblaster.o +obj-$(CONFIG_AMLOGIC_IRBLASTER_PROTOCOL) += encoder.o irblaster-nec-encoder.o \ + irblaster-rca-encoder.o diff --git a/drivers/amlogic/irblaster/aml-irblaster.c b/drivers/amlogic/irblaster/aml-irblaster.c new file mode 100644 index 000000000000..79c7d27b2fb5 --- /dev/null +++ b/drivers/amlogic/irblaster/aml-irblaster.c @@ -0,0 +1,430 @@ +/* + * drivers/amlogic/irblaster/aml-irblaster.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AO_IR_BLASTER_ADDR0 (0x0) +#define AO_IR_BLASTER_ADDR1 (0x4) +#define AO_IR_BLASTER_ADDR2 (0x8) +#define AO_IR_BLASTER_ADDR3 (0xc) + +#define DEFAULT_CARRIER_FREQ (38000) +#define DEFAULT_DUTY_CYCLE (50) +#define BLASTER_DEVICE_COUNT (32) + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#define DEFAULT_IRBLASTER_PROTOCOL IRBLASTER_PROTOCOL_NEC +#endif + +#define IR_TX_EVENT_SIZE 4 +#define IR_TX_BUFFER_SIZE 1024 + +struct tx_event { + struct list_head list; + unsigned int size; + unsigned int buffer[IR_TX_BUFFER_SIZE]; +}; + +DECLARE_KFIFO(fifo, struct tx_event *, IR_TX_EVENT_SIZE); + +struct aml_irblaster_dev { + struct irblaster_chip chip; + struct device *dev; + struct task_struct *thread; + struct completion blaster_completion; + struct mutex lock; + spinlock_t irblaster_lock; /* use to send data */ + void __iomem *reg_base; + void __iomem *reset_base; + unsigned int winnum; + unsigned int winarray[MAX_PLUSE]; +}; + +static struct aml_irblaster_dev * +to_aml_irblaster(struct irblaster_chip *chip) +{ + return container_of(chip, struct aml_irblaster_dev, chip); +} + +static struct tx_event *event_get(struct aml_irblaster_dev *cw) +{ + struct tx_event *ev = NULL; + + ev = devm_kzalloc(cw->dev, + sizeof(struct tx_event), GFP_KERNEL); + return ev; +} + +static void event_put(struct aml_irblaster_dev *cw, struct tx_event *ev) +{ + devm_kfree(cw->dev, ev); +} + +static int send_bit(struct aml_irblaster_dev *cw, unsigned int hightime, + unsigned int lowtime, unsigned int cycle) +{ + unsigned int count_delay; + uint32_t val; + int n = 0; + int tb[3] = { + 1, 10, 100 + }; + /* + * MODULATOR_TB: + * 00: system clock clk + * 01: mpeg_xtal3_tick + * 10: mpeg_1uS_tick + * 11: mpeg_10uS_tick + * lowtime<1024,n=0,timebase=1us + * 1024<=lowtime<10240,n=1,timebase=10us + * AO_IR_BLASTER_ADDR2 + * bit12: output level(or modulation enable/disable:1=enable) + * bit[11:10]: Timebase : + * 00=1us + * 01=10us + * 10=100us + * 11=Modulator clock + * bit[9:0]: Count of timebase units to delay + */ + count_delay = (((hightime + cycle/2) / cycle) - 1) & 0x3ff; + val = (0x10000 | (1 << 12)) | (3 << 10) | (count_delay << 0); + writel_relaxed(val, cw->reg_base + AO_IR_BLASTER_ADDR2); + + /* + * lowtime<1024,n=0,timebase=1us + * 1024<=lowtime<10240,n=1,timebase=10us + * 10240<=lowtime,n=2,timebase=100us + */ + n = lowtime >> 10; + if (n > 0 && n < 10) + n = 1; + else if (n >= 10) + n = 2; + lowtime = (lowtime + (tb[n] >> 1))/tb[n]; + count_delay = (lowtime-1) & 0x3ff; + val = (0x10000 | (0 << 12)) | + (n << 10) | (count_delay << 0); + writel_relaxed(val, cw->reg_base + AO_IR_BLASTER_ADDR2); + + return 0; +} + +static void send_all_frame(struct aml_irblaster_dev *cw) +{ + int i, k; + int exp = 0x00; + unsigned int *pData; + unsigned int consumerir_cycle; + unsigned int high_ct, low_ct; + unsigned long cnt, flags; + + consumerir_cycle = 1000 / (cw->chip.state.freq / 1000); + + /*reset*/ + writel_relaxed(readl_relaxed(cw->reset_base) | + (1 << 23), cw->reset_base); + udelay(2); + writel_relaxed(readl_relaxed(cw->reset_base) & + ~(1 << 23), cw->reset_base); + + /* + * 1.disable ir blaster + * 2.set the modulator_tb = 2'10; mpeg_1uS_tick 1us + */ + writel_relaxed((1 << 2) | (2 << 12) | (1<<2), + cw->reg_base + AO_IR_BLASTER_ADDR0); + + /* + * 1. set mod_high_count = 13 + * 2. set mod_low_count = 13 + * 3. 60khz 8, 38k-13us, 12 + */ + high_ct = consumerir_cycle * cw->chip.state.duty/100; + low_ct = consumerir_cycle - high_ct; + writel_relaxed(((high_ct - 1) << 16) | ((low_ct - 1) << 0), + cw->reg_base + AO_IR_BLASTER_ADDR1); + + /* Setting this bit to 1 initializes the output to be high.*/ + writel_relaxed(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + ~(1 << 2), cw->reg_base + AO_IR_BLASTER_ADDR0); + + /*enable irblaster*/ + writel_relaxed(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) | + (1 << 0), cw->reg_base + AO_IR_BLASTER_ADDR0); + + k = cw->winnum; +#define SEND_BIT_NUM 64 + exp = cw->winnum / SEND_BIT_NUM; + pData = cw->winarray; + + while (exp) { + spin_lock_irqsave(&cw->irblaster_lock, flags); + for (i = 0; i < SEND_BIT_NUM/2; i++) { + send_bit(cw, *pData, *(pData+1), consumerir_cycle); + pData += 2; + } + + spin_unlock_irqrestore(&cw->irblaster_lock, flags); + cnt = jiffies + msecs_to_jiffies(1000); + while (!(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<24)) && time_is_after_eq_jiffies(cnt)) + ; + + cnt = jiffies + msecs_to_jiffies(1000); + while ((readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<26)) && time_is_after_eq_jiffies(cnt)) + ; + + /*reset*/ + writel_relaxed(readl_relaxed(cw->reset_base) | (1 << 23), + cw->reset_base); + udelay(2); + writel_relaxed(readl_relaxed(cw->reset_base) & ~(1 << 23), + cw->reset_base); + exp--; + } + + exp = (cw->winnum % SEND_BIT_NUM) & (~(1)); + spin_lock_irqsave(&cw->irblaster_lock, flags); + for (i = 0; i < exp; ) { + send_bit(cw, *pData, *(pData+1), consumerir_cycle); + pData += 2; + i += 2; + } + + spin_unlock_irqrestore(&cw->irblaster_lock, flags); + cnt = jiffies + msecs_to_jiffies(1000); + while (!(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<24)) && time_is_after_eq_jiffies(cnt)) + ; + + cnt = jiffies + msecs_to_jiffies(1000); + while ((readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<26)) && time_is_after_eq_jiffies(cnt)) + ; + + complete(&cw->blaster_completion); +} + +int aml_irblaster_send(struct irblaster_chip *chip, + unsigned int *data, + unsigned int len) +{ + int i, ret; + struct tx_event *ev; + struct aml_irblaster_dev *irblaster_dev = to_aml_irblaster(chip); + + init_completion(&irblaster_dev->blaster_completion); + ev = event_get(irblaster_dev); + ev->size = len; + for (i = 0; i < ev->size; i++) + ev->buffer[i] = data[i]; + + /* to send cycle */ + kfifo_put(&fifo, (const struct tx_event *)ev); + /* to wake up ir_tx_thread */ + wake_up_process(irblaster_dev->thread); + /* return after processing */ + ret = wait_for_completion_interruptible_timeout + (&irblaster_dev->blaster_completion, + msecs_to_jiffies(chip->sum_time / 1000)); + if (!ret) { + pr_err("failed to send all data ret = %d\n", ret); + return -ETIMEDOUT; + } + + return 0; +} + +static int ir_tx_thread(void *data) +{ + int retval, i; + unsigned long cnt; + struct aml_irblaster_dev *irblaster_dev + = (struct aml_irblaster_dev *)data; + struct tx_event *ev = NULL; + + while (!kthread_should_stop()) { + retval = kfifo_len(&fifo); + if (retval <= 0) { + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + schedule(); + continue; + } + + retval = kfifo_get(&fifo, &ev); + if (retval) { + irblaster_dev->winnum = ev->size; + for (i = 0; i < irblaster_dev->winnum; i++) + irblaster_dev->winarray[i] = ev->buffer[i]; + + send_all_frame(irblaster_dev); + event_put(irblaster_dev, ev); + cnt = jiffies + msecs_to_jiffies(1000); + while (!(readl_relaxed(irblaster_dev->reg_base + + AO_IR_BLASTER_ADDR0) & (1<<24)) && + time_is_after_eq_jiffies(cnt)) + ; + + cnt = jiffies + msecs_to_jiffies(1000); + while ((readl_relaxed(irblaster_dev->reg_base + + AO_IR_BLASTER_ADDR0) & (1<<26)) && + time_is_after_eq_jiffies(cnt)) + ; + + } else + pr_err("kfifo_get fail\n"); + } + + return 0; +} + +static struct irblaster_ops aml_irblaster_ops = { + .send = aml_irblaster_send, +}; + +static int aml_irblaster_probe(struct platform_device *pdev) +{ + struct aml_irblaster_dev *irblaster_dev = NULL; + struct resource *reg_mem = NULL; + struct resource *reset_mem = NULL; + void __iomem *reg_base = NULL; + void __iomem *reset_base = NULL; + int err; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "pdev->dev.of_node == NULL!\n"); + return -EINVAL; + } + + irblaster_dev = devm_kzalloc(&pdev->dev, + sizeof(struct aml_irblaster_dev), + GFP_KERNEL); + if (!irblaster_dev) + return -ENOMEM; + + platform_set_drvdata(pdev, irblaster_dev); + irblaster_dev->dev = &pdev->dev; + + reg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!IS_ERR_OR_NULL(reg_mem)) { + reg_base = devm_ioremap_resource(&pdev->dev, reg_mem); + if (IS_ERR(reg_base)) { + dev_err(&pdev->dev, "reg0: cannot obtain I/O memory region.\n"); + return PTR_ERR(reg_base); + } + } else { + dev_err(&pdev->dev, "get IORESOURCE_MEM error.\n"); + return PTR_ERR(reg_base); + } + + reset_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!IS_ERR_OR_NULL(reset_mem)) { + reset_base = devm_ioremap_resource(&pdev->dev, + reset_mem); + if (IS_ERR(reset_base)) { + dev_err(&pdev->dev, "reg1: cannot obtain I/O memory region.\n"); + return PTR_ERR(reset_base); + } + } else { + dev_err(&pdev->dev, "get IORESOURCE_MEM error.\n"); + return PTR_ERR(reset_mem); + } + + spin_lock_init(&irblaster_dev->irblaster_lock); + init_completion(&irblaster_dev->blaster_completion); + irblaster_dev->reg_base = reg_base; + irblaster_dev->reset_base = reset_base; + irblaster_dev->chip.dev = &pdev->dev; + irblaster_dev->chip.ops = &aml_irblaster_ops; + irblaster_dev->chip.of_irblaster_n_cells = 2; + irblaster_dev->chip.state.freq = DEFAULT_CARRIER_FREQ; + irblaster_dev->chip.state.duty = DEFAULT_DUTY_CYCLE; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + irblaster_dev->chip.state.protocol = DEFAULT_IRBLASTER_PROTOCOL; + irblaster_set_protocol(&irblaster_dev->chip, + DEFAULT_IRBLASTER_PROTOCOL); +#endif + err = irblasterchip_add(&irblaster_dev->chip); + if (err < 0) { + dev_err(&pdev->dev, "failed to register irblaster chip: %d\n", + err); + return err; + } + + irblaster_dev->thread = kthread_run(ir_tx_thread, irblaster_dev, + "ir-blaster-thread"); + + return 0; +} + +static int aml_irblaster_remove(struct platform_device *pdev) +{ + struct aml_irblaster_dev *irblaster_dev = platform_get_drvdata(pdev); + + irblasterchip_remove(&irblaster_dev->chip); + + return 0; +} + +static const struct of_device_id irblaster_dt_match[] = { + { + .compatible = "amlogic, aml_irblaster", + }, + {}, +}; + +static struct platform_driver aml_irblaster_driver = { + .probe = aml_irblaster_probe, + .remove = aml_irblaster_remove, + .suspend = NULL, + .resume = NULL, + .driver = { + .name = "aml-irblaster", + .owner = THIS_MODULE, + .of_match_table = irblaster_dt_match, + }, +}; + +static int __init aml_irblaster_init(void) +{ + return platform_driver_register(&aml_irblaster_driver); +} + +static void __exit aml_irblaster_exit(void) +{ + platform_driver_unregister(&aml_irblaster_driver); +} + +fs_initcall_sync(aml_irblaster_init); +module_exit(aml_irblaster_exit); +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic ir blaster driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/irblaster/core.c b/drivers/amlogic/irblaster/core.c new file mode 100644 index 000000000000..dfc5b7897ff5 --- /dev/null +++ b/drivers/amlogic/irblaster/core.c @@ -0,0 +1,366 @@ +/* + * drivers/amlogic/irblaster/core.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +void irblaster_chip_data_clear(struct irblaster_chip *chip) +{ + chip->buffer = NULL; + chip->buffer_len = 0; + chip->sum_time = 0; +} + +/** + * irblaster_send() - send raw level data + * @chip: irblaster controller + * @data: raw level data (us) + * @len: raw len + */ +int irblaster_send(struct irblaster_chip *chip, unsigned int *data, + unsigned int len) +{ + unsigned int sum_time = 0; + int err, i; + + if (!chip || (len % 2 == 1) || len == 0 || len > MAX_PLUSE) { + pr_err("%s(): parameter error\n", __func__); + return -EINVAL; + } + + for (i = 0; i < len; i++) + sum_time += data[i]; + + chip->buffer = data; + chip->buffer_len = len; + chip->sum_time = sum_time; + + if (chip->ops->send) { + err = chip->ops->send(chip, data, len); + if (err) + return err; + } else { + pr_err("%s(): irblaster func %s not found\n", + __func__, __func__); + return -EINVAL; + } + + irblaster_chip_data_clear(chip); + + return 0; +} + +/** + * irblaster_set_freq() - set irblaster freq + * @chip: irblaster controller + * @freq: irblaster freq (HZ) + */ +int irblaster_set_freq(struct irblaster_chip *chip, unsigned int freq) +{ + int ret; + + if (!chip || freq <= 0) + return -EINVAL; + + if (chip->ops->set_freq) { + ret = chip->ops->set_freq(chip, freq); + if (ret) + return -EINVAL; + } + + chip->state.freq = freq; + + return 0; +} + +/** + * irblaster_get_freq() - get irblaster freq + * @chip: irblaster controller + */ +unsigned int irblaster_get_freq(struct irblaster_chip *chip) +{ + unsigned int freq; + + if (!chip) + return -EINVAL; + + if (chip->ops->get_freq) { + freq = chip->ops->get_freq(chip); + if (freq == 0) + return -EINVAL; + } else { + freq = chip->state.freq; + } + + return freq; +} + +/** + * irblaster_set_duty() - set irblaster duty + * @chip: irblaster controller + * @duty: irblaster duty + */ +int irblaster_set_duty(struct irblaster_chip *chip, unsigned int duty) +{ + int ret; + + if (!chip || duty <= 0 || duty > 100) + return -EINVAL; + + if (chip->ops->set_duty) { + ret = chip->ops->set_duty(chip, duty); + if (ret) + return -EINVAL; + } + + chip->state.duty = duty; + + return 0; +} + +/** + * irblaster_set_duty() - set irblaster duty + * @chip: irblaster controller + * @duty: irblaster duty + */ +unsigned int irblaster_get_duty(struct irblaster_chip *chip) +{ + unsigned int duty; + + if (chip->ops->get_duty) { + duty = chip->ops->get_duty(chip); + if (duty == 0) + return -EINVAL; + } else { + duty = chip->state.duty; + } + + return duty; +} + +/** + * irblasterchip_remove() - remove a irblaster Controller + * @chip: the irblaster chip to remove + * @Returns: 0 on success or a negative error code on failure. + */ +int irblasterchip_remove(struct irblaster_chip *chip) +{ + mutex_lock(&irblaster_lock); + list_del_init(&chip->list); + + if (chip->dev) + of_node_put(chip->dev->of_node); + + irblasterchip_sysfs_unexport(chip); + mutex_unlock(&irblaster_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(irblasterchip_remove); + +static bool irblaster_ops_check(struct irblaster_ops *ops) +{ + /* These one interfaces are the most basic of the irblaster */ + if (ops->send) + return true; + + return false; +} + +/** + * irblasterchip_add() - register a new irblaster Controller + * @chip: the irblaster chip to add + * @Returns: 0 on success or a negative error code on failure. + */ +int irblasterchip_add(struct irblaster_chip *chip) +{ + if (!chip || !chip->dev || !chip->ops) + return -EINVAL; + + if (!irblaster_ops_check(chip->ops)) + return -EINVAL; + + mutex_lock(&irblaster_lock); + atomic_set(&chip->request, IRBLASTER_EXPORTED); + INIT_LIST_HEAD(&chip->list); + list_add(&chip->list, &irblaster_chips); + irblasterchip_sysfs_export(chip); + mutex_unlock(&irblaster_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(irblasterchip_add); + +/** + * irblaster_put() - release a irblaster controller + * @chip: irblaster controller + */ +void irblaster_put(struct irblaster_chip *chip) +{ + if (!chip) + return; + + mutex_lock(&irblaster_lock); + atomic_set(&chip->request, IRBLASTER_EXPORTED); + irblaster_chip_data_clear(chip); + irblasterchip_sysfs_export(chip); + mutex_unlock(&irblaster_lock); +} +EXPORT_SYMBOL_GPL(irblaster_put); + +static struct irblaster_chip *of_node_to_irblasterchip(struct device_node *np) +{ + struct irblaster_chip *chip; + + mutex_lock(&irblaster_lock); + list_for_each_entry(chip, &irblaster_chips, list) + if (chip->dev && chip->dev->of_node == np) { + mutex_unlock(&irblaster_lock); + if (atomic_read(&chip->request) == IRBLASTER_REQUESTED) + return ERR_PTR(-EPROBE_DEFER); + return chip; + } + + mutex_unlock(&irblaster_lock); + return ERR_PTR(-EPROBE_DEFER); +} + +static int irblaster_set_default_state(struct irblaster_chip *pc, + const struct of_phandle_args *args) +{ + int ret; + + if (pc->of_irblaster_n_cells < 2 || + args->args[0] <= 0 || args->args[1] > 100) + return -EINVAL; + + pc->state.freq = args->args[0]; + pc->state.duty = args->args[1]; + + ret = irblaster_set_freq(pc, pc->state.freq); + if (ret) + return -EINVAL; + + ret = irblaster_set_duty(pc, pc->state.duty); + if (ret) + return -EINVAL; + + return 0; +} + +/** + * of_irblaster_get() - request a irblaster via the irblaster framework + * @np: device node to get the irblaster from + * @con_id: consumer name + * + * Returns the irblaster controller parsed from the phandle and index + * specified in the "irblaster-config" property of a device tree node + * or a negative error-code on failure. Values parsed from the device + * tree are stored in the returned irblaster device object. + * + * Returns: A pointer to the requested irblaster controller or an ERR_PTR() + * -encoded error code on failure. + */ +struct irblaster_chip *of_irblaster_get(struct device_node *np, + const char *con_id) +{ + struct of_phandle_args args; + struct irblaster_chip *pc; + int err, index = 0; + + err = of_parse_phandle_with_args(np, "irblaster-config", + "#irblaster-cells", index, + &args); + if (err) { + pr_err("%s(): can't parse \"irblaster-config\" property\n", + __func__); + return ERR_PTR(err); + } + + pc = of_node_to_irblasterchip(args.np); + if (IS_ERR(pc)) { + pr_err("%s(): irblaster chip not found\n", __func__); + pc = ERR_PTR(-EINVAL); + goto put; + } + + if (args.args_count != pc->of_irblaster_n_cells) { + pr_err("%s: wrong #irblaster-cells for %s\n", np->full_name, + args.np->full_name); + pc = ERR_PTR(-EINVAL); + goto put; + } + + err = irblaster_set_default_state(pc, &args); + if (err < 0) { + pr_err("%s(): irblaster get state fail\n", __func__); + pc = ERR_PTR(-EINVAL); + goto put; + } + + atomic_set(&pc->request, IRBLASTER_REQUESTED); + irblasterchip_sysfs_unexport(pc); +put: + of_node_put(args.np); + + return pc; +} +EXPORT_SYMBOL_GPL(of_irblaster_get); + +static void devm_irblaster_release(struct device *dev, void *res) +{ + irblaster_put(*(struct irblaster_chip **)res); +} + +/** + * devm_of_irblaster_get() - resource managed of_irblaster_get() + * @dev: device for irblaster consumer + * @np: device node to get the irblaster from + * @con_id: consumer name + * + * This function performs like of_irblaster_get() but the acquired irblaster + * device will automatically be released on driver detach. + * + * Returns: A pointer to the requested irblaster device or an ERR_PTR()-encoded + * error code on failure. + */ +struct irblaster_chip *devm_of_irblaster_get(struct device *dev, + struct device_node *np, + const char *con_id) +{ + struct irblaster_chip **dr, *chip; + + dr = devres_alloc(devm_irblaster_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + chip = of_irblaster_get(np, con_id); + if (!IS_ERR(chip)) { + *dr = chip; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return chip; +} +EXPORT_SYMBOL_GPL(devm_of_irblaster_get); diff --git a/drivers/amlogic/irblaster/encoder.c b/drivers/amlogic/irblaster/encoder.c new file mode 100644 index 000000000000..757fa18f8fa8 --- /dev/null +++ b/drivers/amlogic/irblaster/encoder.c @@ -0,0 +1,267 @@ +/* + * drivers/amlogic/irblaster/encoder.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int irblaster_raw_gen_pulse_space(unsigned int *data, + unsigned int *max, + unsigned int pulse_width, + unsigned int space_width, + unsigned int len) +{ + if (!*max) + return -ENOBUFS; + data[len - *max] = pulse_width; + if (!--*max) + return -ENOBUFS; + data[len - *max] = space_width; + --*max; + + return 0; +} + +/** + * irblaster_raw_gen() - Encode data to raw events with pulse-length modulation. + * @data: Pointer to data + * @timings: Pulse distance modulation timings. + * @raw: Data bits to encode. + * @Returns: buff len on success. + * + * Encodes the @n least significant bits of @data using space-distance + * modulation with the timing characteristics described by @timings, writing up + * to data using the *data pointer. + */ +int irblaster_raw_gen(unsigned int *data, + const struct irblaster_raw_timings *timings, + u32 raw) +{ + int i, ret, max; + int len = timings->data_size; + unsigned int space; + + max = len; + if (timings->header_pulse) { + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->header_pulse, + timings->header_space, + len); + if (ret) + return ret; + } + + if (timings->msb_first) { + for (i = timings->raw_nbits - 1; i >= 0; --i) { + space = timings->bit_space[(raw >> i) & 1]; + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->bit_pulse, + space, len); + if (ret) + return ret; + } + } else { + for (i = 0; i < timings->raw_nbits; ++i, raw >>= 1) { + space = timings->bit_space[raw & 1]; + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->bit_pulse, + space, len); + if (ret) + return ret; + } + } + + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->trailer_pulse, + timings->trailer_space, + len); + if (ret) + return ret; + + return len; +} + +unsigned int protocol_show_select(struct irblaster_chip *chip, char *buf) +{ + struct irblaster_raw_handler *protocol; + unsigned int len = 0; + + mutex_lock(&irblaster_raw_handler_lock); + list_for_each_entry(protocol, &irblaster_raw_handler_list, list) { + if (chip->protocol && + chip->state.protocol == protocol->protocol) + len += scnprintf(buf + len, PAGE_SIZE - len, "[%s] ", + protocol->name); + else + len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", + protocol->name); + } + + len += scnprintf(len + buf, PAGE_SIZE - len, "\n"); + mutex_unlock(&irblaster_raw_handler_lock); + + return len; +} + +unsigned int protocol_store_select(const char *buf) +{ + struct irblaster_raw_handler *protocol; + + mutex_lock(&irblaster_raw_handler_lock); + list_for_each_entry(protocol, &irblaster_raw_handler_list, list) { + if (sysfs_streq(buf, protocol->name)) { + mutex_unlock(&irblaster_raw_handler_lock); + return protocol->protocol; + } + } + mutex_unlock(&irblaster_raw_handler_lock); + + return 0; +} + +/** + * irblaster_raw_handler_register() + * - register a new raw_handle + * @ir_raw_handler: the raw_handle to add + * @Returns: 0 on success + */ +int irblaster_raw_handler_register(struct irblaster_raw_handler *ir_raw_handler) +{ + mutex_lock(&irblaster_raw_handler_lock); + list_add_tail(&ir_raw_handler->list, &irblaster_raw_handler_list); + mutex_unlock(&irblaster_raw_handler_lock); + + return 0; +} +EXPORT_SYMBOL(irblaster_raw_handler_register); + +/** + * irblaster_raw_handler_unregister() + * - unregister a raw_handle + * @ir_raw_handler: the raw_handle to remove + */ +void irblaster_raw_handler_unregister(struct irblaster_raw_handler + *ir_raw_handler) +{ + mutex_lock(&irblaster_raw_handler_lock); + list_del(&ir_raw_handler->list); + mutex_unlock(&irblaster_raw_handler_lock); +} +EXPORT_SYMBOL(irblaster_raw_handler_unregister); + +/** + * irblaster_send_key() - send key with addr and commmand + * @chip: irblaster controller + * @addr: remote control ID + * @commmand: key + */ +int irblaster_send_key(struct irblaster_chip *chip, unsigned int addr, + unsigned int commmand) +{ + int ret; + unsigned int *data; + + if (!chip) + return -EINVAL; + + if (chip->ops->send_key) { + ret = chip->ops->send_key(chip, addr, commmand); + if (ret) { + pr_err("%s(): irblaster_send fail\n", + __func__); + return -EINVAL; + } + } else { + data = kzalloc(sizeof(uint32_t) * MAX_PLUSE, GFP_KERNEL); + if (!data) + return -ENOMEM; + + if (chip->protocol->encode) { + ret = chip->protocol->encode(chip->state.protocol, + addr, commmand, data); + if (ret <= 0) { + pr_err("%s(): irblaster encode fail\n", + __func__); + goto err; + } + } else { + pr_err("%s(): irblaster func %s not found\n", + __func__, __func__); + goto err; + } + + ret = irblaster_send(chip, data, + chip->protocol->timing->data_size); + if (ret) { + pr_err("%s(): irblaster_send fail\n", __func__); + goto err; + } + + kfree(data); + } + + return 0; +err: + kfree(data); + return -EINVAL; +} + +/** + * irblaster_set_protocol() - set irblaster protocol + * @chip: irblaster controller + * @ir_protocol: irblaster protocol + */ +int irblaster_set_protocol(struct irblaster_chip *chip, + enum irblaster_protocol ir_protocol) +{ + struct irblaster_raw_handler *protocol; + + if (!chip || ir_protocol < 0 || ir_protocol >= IRBLASTER_PROTOCOL_MAX) + return -EINVAL; + + mutex_lock(&irblaster_raw_handler_lock); + + list_for_each_entry(protocol, &irblaster_raw_handler_list, list) + if (protocol->protocol == ir_protocol) { + chip->state.protocol = ir_protocol; + chip->protocol = protocol; + mutex_unlock(&irblaster_raw_handler_lock); + return 0; + } + + mutex_unlock(&irblaster_raw_handler_lock); + pr_err("%s(): irblaster protocol is not found\n", __func__); + + return -EINVAL; +} + +/** + * irblaster_get_protocol() - get irblaster protocol + * @chip: irblaster controller + */ +enum irblaster_protocol irblaster_get_protocol(struct irblaster_chip *chip) +{ + if (!chip) + return -EINVAL; + + return chip->state.protocol; +} diff --git a/drivers/amlogic/irblaster/irblaster-meson.c b/drivers/amlogic/irblaster/irblaster-meson.c new file mode 100644 index 000000000000..41a7f526bce6 --- /dev/null +++ b/drivers/amlogic/irblaster/irblaster-meson.c @@ -0,0 +1,415 @@ +/* + * drivers/amlogic/irblaster/irblaster-meson.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Amlogic AO_IR_BLASTER_ADDR0 bits */ +#define BLASTER_BUSY BIT(26) +#define BLASTER_FIFO_FULL BIT(25) +#define BLASTER_FIFO_EMPTY BIT(24) +#define BLASTER_FIFO_LEVEL (0xff << 16) +#define BLASTER_MODULATOR_TB_SYSTEM_CLOCK (0x0 << 12) +#define BLASTER_MODULATOR_TB_XTAL3_TICK (0x1 << 12) +#define BLASTER_MODULATOR_TB_1US_TICK (0x2 << 12) +#define BLASTER_MODULATOR_TB_10US_TICK (0x3 << 12) +#define BLASTER_SLOW_CLOCK_DIV (0xff << 4) +#define BLASTER_SLOW_CLOCK_MODE BIT(3) +#define BLASTER_INIT_HIGH BIT(2) +#define BLASTER_INIT_LOW BIT(1) +#define BLASTER_ENABLE BIT(0) + +/* Amlogic AO_IR_BLASTER_ADDR1 bits */ +#define BLASTER_MODULATION_LOW_COUNT(c) ((c) << 16) +#define BLASTER_MODULATION_HIGH_COUNT(c) ((c) << 0) + +/* Amlogic AO_IR_BLASTER_ADDR2 bits */ +#define BLASTER_WRITE_FIFO BIT(16) +#define BLASTER_MODULATION_ENABLE BIT(12) +#define BLASTER_TIMEBASE_1US (0x0 << 10) +#define BLASTER_TIMEBASE_10US (0x1 << 10) +#define BLASTER_TIMEBASE_100US (0x2 << 10) +#define BLASTER_TIMEBASE_MODULATION_CLOCK (0x3 << 10) + +/* Amlogic AO_IR_BLASTER_ADDR3 bits */ +#define BLASTER_FIFO_THD_PENDING BIT(16) +#define BLASTER_FIFO_IRQ_ENABLE BIT(8) +#define BLASTER_FIFO_IRQ_THRESHOLD(c) (((c) & 0xff) << 0) + +#define DEFAULT_CARRIER_FREQ (38000) +#define DEFAULT_DUTY_CYCLE (50) + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#define DEFAULT_IRBLASTER_PROTOCOL IRBLASTER_PROTOCOL_NEC +#endif + +#define LIMIT_DUTY (25) +#define MAX_DUTY (75) +#define LIMIT_FREQ (25000) +#define MAX_FREQ (60000) +#define COUNT_DELAY_MASK (0X3ff) +#define TIMEBASE_SHIFT (10) +#define BLASTER_KFIFO_SIZE (4) + +#define AO_IR_BLASTER_ADDR0 (0x0) +#define AO_IR_BLASTER_ADDR1 (0x4) +#define AO_IR_BLASTER_ADDR2 (0x8) +#define AO_IR_BLASTER_ADDR3 (0xc) +#define AO_RTI_GEN_CTNL_REG0 (0x0) + +#define CONSUMERIR_TRANSMIT 0x5500 +#define GET_CARRIER 0x5501 +#define SET_CARRIER 0x5502 +#define SET_DUTYCYCLE 0x5503 + +struct meson_irblaster_dev { + struct device *dev; + struct work_struct blaster_work; + struct irblaster_chip chip; + struct completion blaster_completion; + unsigned int count; + unsigned int irq; + unsigned int buffer_size; + unsigned int *buffer; + spinlock_t irblaster_lock; /* use to send data */ + void __iomem *reg_base; + void __iomem *reset_base; +}; + +static void meson_irblaster_tasklet(unsigned long data); +DECLARE_TASKLET_DISABLED(irblaster_tasklet, meson_irblaster_tasklet, 0); + +static struct meson_irblaster_dev * +to_meson_irblaster(struct irblaster_chip *chip) +{ + return container_of(chip, struct meson_irblaster_dev, chip); +} + +static void blaster_initialize(struct meson_irblaster_dev *dev) +{ + unsigned int carrier_cycle = 1000 / (dev->chip.state.freq / 1000); + unsigned int high_ct, low_ct; + + /* + *1. disable ir blaster + *2. set the modulator_tb = 2'10; mpeg_1uS_tick 1us + *3. set initializes the output to be high + */ + writel_relaxed((~BLASTER_ENABLE) & (BLASTER_MODULATOR_TB_1US_TICK | + BLASTER_INIT_HIGH), dev->reg_base + AO_IR_BLASTER_ADDR0); + /* + *1. set mod_high_count = 13 + *2. set mod_low_count = 13 + *3. 60khz-8us, 38k-13us + */ + high_ct = carrier_cycle * dev->chip.state.duty / 100; + low_ct = carrier_cycle - high_ct; + writel_relaxed((BLASTER_MODULATION_LOW_COUNT(low_ct - 1) | + BLASTER_MODULATION_HIGH_COUNT(high_ct - 1)), + dev->reg_base + AO_IR_BLASTER_ADDR1); + /*mask initialize output to be high*/ + writel_relaxed(readl_relaxed(dev->reg_base + AO_IR_BLASTER_ADDR0) & + ~BLASTER_INIT_HIGH, + dev->reg_base + AO_IR_BLASTER_ADDR0); + /* + *1. set fifo irq enable + *2. set fifo irq threshold + */ + writel_relaxed(BLASTER_FIFO_IRQ_ENABLE | + BLASTER_FIFO_IRQ_THRESHOLD(8), + dev->reg_base + AO_IR_BLASTER_ADDR3); + /*enable irblaster*/ + writel_relaxed(readl_relaxed(dev->reg_base + AO_IR_BLASTER_ADDR0) | + BLASTER_ENABLE, + dev->reg_base + AO_IR_BLASTER_ADDR0); +} + +static int write_to_fifo(struct meson_irblaster_dev *dev, + unsigned int hightime, + unsigned int lowtime) +{ + unsigned int count_delay; + unsigned int cycle = 1000 / (dev->chip.state.freq / 1000); + u32 val; + int n = 0; + int tb[3] = { + 1, 10, 100 + }; + + /* + * hightime: modulator signal. + * MODULATOR_TB: + * 00: system clock + * 01: mpeg_xtal3_tick + * 10: mpeg_1uS_tick + * 11: mpeg_10uS_tick + * + * AO_IR_BLASTER_ADDR2 + * bit12: output level(or modulation enable/disable:1=enable) + * bit[11:10]: Timebase : + * 00=1us + * 01=10us + * 10=100us + * 11=Modulator clock + * bit[9:0]: Count of timebase units to delay + */ + + count_delay = (((hightime + cycle / 2) / cycle) - 1) & COUNT_DELAY_MASK; + val = (BLASTER_WRITE_FIFO | BLASTER_MODULATION_ENABLE | + BLASTER_TIMEBASE_MODULATION_CLOCK | (count_delay << 0)); + writel_relaxed(val, dev->reg_base + AO_IR_BLASTER_ADDR2); + + /* + * lowtime<1024,n=0,timebase=1us + * 1024<=lowtime<10240,n=1,timebase=10us + * 10240<=lowtime,n=2,timebase=100us + */ + n = lowtime >> 10; + if (n > 0 && n < 10) + n = 1; + else if (n >= 10) + n = 2; + lowtime = (lowtime + (tb[n] >> 1)) / tb[n]; + count_delay = (lowtime - 1) & COUNT_DELAY_MASK; + val = (BLASTER_WRITE_FIFO & (~BLASTER_MODULATION_ENABLE)) | + (n << TIMEBASE_SHIFT) | (count_delay << 0); + writel_relaxed(val, dev->reg_base + AO_IR_BLASTER_ADDR2); + + return 0; +} + +static void send_all_data(struct meson_irblaster_dev *dev) +{ + int i; + unsigned int *pdata = NULL; + unsigned long flags; + + pdata = &dev->buffer[dev->count]; + spin_lock_irqsave(&dev->irblaster_lock, flags); + for (i = 0; (i < 120) && (dev->count < dev->buffer_size);) { + write_to_fifo(dev, *pdata, *(pdata + 1)); + pdata += 2; + dev->count += 2; + i += 2; + } + spin_unlock_irqrestore(&dev->irblaster_lock, flags); +} + +int meson_irblaster_send(struct irblaster_chip *chip, + unsigned int *data, + unsigned int len) +{ + int ret, i, sum_time = 0; + unsigned int high_ct, low_ct; + unsigned int cycle; + struct meson_irblaster_dev *irblaster_dev = to_meson_irblaster(chip); + + init_completion(&irblaster_dev->blaster_completion); + irblaster_dev->buffer = data; + irblaster_dev->buffer_size = len; + irblaster_dev->count = 0; + + for (i = 0; i < irblaster_dev->buffer_size; i++) + sum_time = sum_time + data[i]; + + /* + * 1. set mod_high_count = 13 + * 2. set mod_low_count = 13 + * 3. 60khz-8us, 38k-13us + */ + cycle = 1000 / (irblaster_dev->chip.state.freq / 1000); + high_ct = cycle * irblaster_dev->chip.state.duty / 100; + low_ct = cycle - high_ct; + writel_relaxed((BLASTER_MODULATION_LOW_COUNT(low_ct - 1) | + BLASTER_MODULATION_HIGH_COUNT(high_ct - 1)), + irblaster_dev->reg_base + AO_IR_BLASTER_ADDR1); + + send_all_data(irblaster_dev); + ret = wait_for_completion_interruptible_timeout + (&irblaster_dev->blaster_completion, + msecs_to_jiffies(sum_time / 1000)); + if (!ret) { + pr_err("failed to send all data ret = %d\n", ret); + return -ETIMEDOUT; + } + + return 0; +} + +static struct irblaster_ops meson_irblaster_ops = { + .send = meson_irblaster_send, +}; + +static void meson_irblaster_tasklet(unsigned long data) +{ + struct meson_irblaster_dev *dev = (struct meson_irblaster_dev *)data; + + if (dev->count < dev->buffer_size) + send_all_data(dev); +} + +static irqreturn_t meson_blaster_interrupt(int irq, void *dev_id) +{ + struct meson_irblaster_dev *dev = dev_id; + + /*clear pending bit*/ + writel_relaxed(readl_relaxed(dev->reg_base + AO_IR_BLASTER_ADDR3) & + (~BLASTER_FIFO_THD_PENDING), + dev->reg_base + AO_IR_BLASTER_ADDR3); + + if (dev->count >= dev->buffer_size) { + complete(&dev->blaster_completion); + return IRQ_HANDLED; + } + + tasklet_schedule(&irblaster_tasklet); + return IRQ_HANDLED; +} + +static int meson_irblaster_probe(struct platform_device *pdev) +{ + struct meson_irblaster_dev *irblaster_dev = NULL; + struct resource *reg_mem = NULL; + void __iomem *reg_base = NULL; + int err, ret; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "pdev->dev.of_node == NULL!\n"); + return -EINVAL; + } + + irblaster_dev = devm_kzalloc(&pdev->dev, + sizeof(struct meson_irblaster_dev), + GFP_KERNEL); + if (!irblaster_dev) + return -ENOMEM; + + spin_lock_init(&irblaster_dev->irblaster_lock); + platform_set_drvdata(pdev, irblaster_dev); + irblaster_dev->dev = &pdev->dev; + + reg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!IS_ERR_OR_NULL(reg_mem)) { + reg_base = devm_ioremap_resource(&pdev->dev, reg_mem); + if (IS_ERR(reg_base)) { + dev_err(&pdev->dev, "reg0: cannot obtain I/O memory region.\n"); + return PTR_ERR(reg_base); + } + } else { + dev_err(&pdev->dev, "get IORESOURCE_MEM error.\n"); + return PTR_ERR(reg_base); + } + + irblaster_dev->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!irblaster_dev->irq) { + dev_err(&pdev->dev, "irq: Failed to request irq number.\n"); + return -ENODEV; + } + + init_completion(&irblaster_dev->blaster_completion); + ret = devm_request_irq(&pdev->dev, irblaster_dev->irq, + meson_blaster_interrupt, + IRQF_TRIGGER_RISING, + dev_name(&pdev->dev), + irblaster_dev); + if (ret) { + pr_err("Failed to request irq.\n"); + return ret; + } + + irblaster_dev->reg_base = reg_base; + irblaster_dev->chip.dev = &pdev->dev; + irblaster_dev->chip.ops = &meson_irblaster_ops; + irblaster_dev->chip.of_irblaster_n_cells = 2; + irblaster_dev->chip.state.freq = DEFAULT_CARRIER_FREQ; + irblaster_dev->chip.state.duty = DEFAULT_DUTY_CYCLE; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + irblaster_dev->chip.state.protocol = DEFAULT_IRBLASTER_PROTOCOL; + irblaster_set_protocol(&irblaster_dev->chip, + DEFAULT_IRBLASTER_PROTOCOL); +#endif + err = irblasterchip_add(&irblaster_dev->chip); + if (err < 0) { + dev_err(&pdev->dev, "failed to register irblaster chip: %d\n", + err); + return err; + } + + irblaster_tasklet.data = (unsigned long)irblaster_dev; + tasklet_enable(&irblaster_tasklet); + + /*initial blaster*/ + blaster_initialize(irblaster_dev); + + return 0; +} + +static int meson_irblaster_remove(struct platform_device *pdev) +{ + struct meson_irblaster_dev *irblaster_dev = platform_get_drvdata(pdev); + + tasklet_disable(&irblaster_tasklet); + tasklet_kill(&irblaster_tasklet); + irblasterchip_remove(&irblaster_dev->chip); + + return 0; +} + +static const struct of_device_id irblaster_dt_match[] = { + { + .compatible = "amlogic, meson_irblaster", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, irblaster_dt_match); + +static struct platform_driver meson_irblaster_driver = { + .probe = meson_irblaster_probe, + .remove = meson_irblaster_remove, + .driver = { + .name = "meson_irblaster", + .owner = THIS_MODULE, + .of_match_table = irblaster_dt_match, + }, +}; + +static int __init meson_irblaster_init(void) +{ + return platform_driver_register(&meson_irblaster_driver); +} + +static void __exit meson_irblaster_exit(void) +{ + platform_driver_unregister(&meson_irblaster_driver); +} + +fs_initcall_sync(meson_irblaster_init); +module_exit(meson_irblaster_exit); +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic ir blaster driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/irblaster/irblaster-nec-encoder.c b/drivers/amlogic/irblaster/irblaster-nec-encoder.c new file mode 100644 index 000000000000..107383ff3729 --- /dev/null +++ b/drivers/amlogic/irblaster/irblaster-nec-encoder.c @@ -0,0 +1,180 @@ +/* + * drivers/amlogic/irblaster/irblaster-nec-encoder.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include + +#define NEC_NBITS 32 +#define NEC_UNIT 562 /* ns */ +#define NEC_HEADER_PULSE 9000 +#define NEC_HEADER_SPACE 4500 +#define NEC_BIT_PULSE 560 +#define NEC_BIT_0_SPACE 560 +#define NEC_BIT_1_SPACE 1690 +#define NEC_TRAILER_PULSE 560 +#define NEC_TRAILER_SPACE 5600 /* even longer in reality */ + +static struct irblaster_raw_timings irblaster_nec_timings = { + .header_pulse = NEC_HEADER_PULSE, + .header_space = NEC_HEADER_SPACE, + .bit_pulse = NEC_BIT_PULSE, + .bit_space[0] = NEC_BIT_0_SPACE, + .bit_space[1] = NEC_BIT_1_SPACE, + .trailer_pulse = NEC_TRAILER_PULSE, + .trailer_space = NEC_TRAILER_SPACE, + .msb_first = 0, + .raw_nbits = NEC_NBITS, + .data_size = (NEC_NBITS + 2) * 2, +}; + +static u32 irblaster_nec32_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr = 0, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr_inv = addr & 0xff; + addr = addrs & 0xff; + data_inv = data & 0xff; + + return data_inv << 24 | + data << 16 | + addr_inv << 8 | + addr; +} + +static u32 irblaster_necx_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr = addrs & 0xff; + addr_inv = addr & 0xff; + data_inv = data ^ 0xff; + + return data_inv << 24 | + data << 16 | + addr_inv << 8 | + addr; +} + +static u32 irblaster_nec_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr = addrs & 0xff; + addr_inv = addr ^ 0xff; + data_inv = data ^ 0xff; + + return data_inv << 24 | + data << 16 | + addr_inv << 8 | + addr; +} + +int irblaster_nec_encode(enum irblaster_protocol protocol, + unsigned int addr, + unsigned int commmand, + unsigned int *data) +{ + u32 raw, ret; + + if (protocol >= IRBLASTER_PROTOCOL_MAX) + return -ENODEV; + + /* Convert a NEC scancode to raw NEC data */ + switch (protocol) { + case IRBLASTER_PROTOCOL_NEC: + raw = irblaster_nec_scancode_to_raw(protocol, addr, commmand); + break; + case IRBLASTER_PROTOCOL_NECX: + raw = irblaster_necx_scancode_to_raw(protocol, addr, commmand); + break; + case IRBLASTER_PROTOCOL_NEC32: + raw = irblaster_nec32_scancode_to_raw(protocol, addr, commmand); + break; + default: + raw = irblaster_nec_scancode_to_raw(protocol, addr, commmand); + break; + } + + /* Modulate the raw data using a pulse distance modulation */ + ret = irblaster_raw_gen(data, &irblaster_nec_timings, raw); + if (ret < 0) + return ret; + + return ret; +} + +static struct irblaster_raw_handler irblaster_nec_handler[] = { + { + .name = "NEC", + .protocol = IRBLASTER_PROTOCOL_NEC, + .encode = irblaster_nec_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_nec_timings, + }, + { + .name = "NECX", + .protocol = IRBLASTER_PROTOCOL_NECX, + .encode = irblaster_nec_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_nec_timings, + }, + { + .name = "NEC32", + .protocol = IRBLASTER_PROTOCOL_NEC32, + .encode = irblaster_nec_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_nec_timings, + } +}; + +static int __init irblaster_nec_decode_init(void) +{ + int i; + + for (i = 0; i < sizeof(irblaster_nec_handler) / + sizeof(struct irblaster_raw_handler); i++) + irblaster_raw_handler_register(irblaster_nec_handler + i); + + return 0; +} + +static void __exit irblaster_nec_decode_exit(void) +{ + int i; + + for (i = 0; i < sizeof(irblaster_nec_handler) / + sizeof(struct irblaster_raw_handler); i++) + irblaster_raw_handler_unregister(irblaster_nec_handler + i); +} + +fs_initcall(irblaster_nec_decode_init); +module_exit(irblaster_nec_decode_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("NEC IR protocol decoder"); diff --git a/drivers/amlogic/irblaster/irblaster-rca-encoder.c b/drivers/amlogic/irblaster/irblaster-rca-encoder.c new file mode 100644 index 000000000000..21068b608ca0 --- /dev/null +++ b/drivers/amlogic/irblaster/irblaster-rca-encoder.c @@ -0,0 +1,99 @@ +/* + * drivers/amlogic/irblaster/irblaster-rca-encoder.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include + +#define RCA_NBITS 24 +#define RCA_UNIT 500 /* ns */ +#define RCA_HEADER_PULSE 4000 +#define RCA_HEADER_SPACE 4000 +#define RCA_BIT_PULSE 500 +#define RCA_BIT_0_SPACE 1000 +#define RCA_BIT_1_SPACE 2000 +#define RCA_TRAILER_PULSE 500 +#define RCA_TRAILER_SPACE 5600 /* even longer in reality */ + +static struct irblaster_raw_timings irblaster_rca_timings = { + .header_pulse = RCA_HEADER_PULSE, + .header_space = RCA_HEADER_SPACE, + .bit_pulse = RCA_BIT_PULSE, + .bit_space[0] = RCA_BIT_0_SPACE, + .bit_space[1] = RCA_BIT_1_SPACE, + .trailer_pulse = RCA_TRAILER_PULSE, + .trailer_space = RCA_TRAILER_SPACE, + .msb_first = 1, + .raw_nbits = RCA_NBITS, + .data_size = (RCA_NBITS + 2) * 2, +}; + +static u32 irblaster_rca_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr = addrs & 0x0f; + addr_inv = addr ^ 0x0f; + data_inv = data ^ 0xff; + + return addr << 20 | + data << 12 | + addr_inv << 8 | + data_inv; +} + +int irblaster_rca_encode(enum irblaster_protocol protocol, unsigned int addr, + unsigned int commmand, unsigned int *data) +{ + u32 raw, ret; + + /* Convert a RCA scancode to raw rca data */ + raw = irblaster_rca_scancode_to_raw(protocol, addr, commmand); + + /* Modulate the raw data using a pulse distance modulation */ + ret = irblaster_raw_gen(data, &irblaster_rca_timings, raw); + if (ret < 0) + return ret; + + return ret; +} + +static struct irblaster_raw_handler irblaster_rca_handler = { + .name = "RCA", + .protocol = IRBLASTER_PROTOCOL_RCA, + .encode = irblaster_rca_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_rca_timings, +}; + +static int __init irblaster_rca_decode_init(void) +{ + return irblaster_raw_handler_register(&irblaster_rca_handler); +} + +static void __exit irblaster_rca_decode_exit(void) +{ + irblaster_raw_handler_unregister(&irblaster_rca_handler); +} + +fs_initcall(irblaster_rca_decode_init); +module_exit(irblaster_rca_decode_exit); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("RCA IR protocol decoder"); diff --git a/drivers/amlogic/irblaster/sysfs.c b/drivers/amlogic/irblaster/sysfs.c new file mode 100644 index 000000000000..650be648b476 --- /dev/null +++ b/drivers/amlogic/irblaster/sysfs.c @@ -0,0 +1,275 @@ +/* + * drivers/amlogic/irblaster/sysfs.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#include +#endif +static ssize_t send_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + int i = 0, j = 0, m = 0; + int val, ret; + char tone[PS_SIZE]; + unsigned int *buffer; + + buffer = kzalloc(sizeof(uint32_t) * MAX_PLUSE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + mutex_lock(&chip->sys_lock); + while (buf[i] != '\0') { + if (buf[i] == 's') { + tone[j] = '\0'; + ret = kstrtoint(tone, 10, &val); + if (ret) { + pr_err("Invalid tone\n"); + mutex_unlock(&chip->sys_lock); + return ret; + } + buffer[m] = val * 10; + j = 0; + i++; + m++; + if (m >= MAX_PLUSE) + break; + continue; + } + tone[j] = buf[i]; + i++; + j++; + if (j >= PS_SIZE) { + pr_err("send timing value is out of range\n"); + mutex_unlock(&chip->sys_lock); + kfree(buffer); + return -ENOMEM; + } + } + + ret = irblaster_send(chip, buffer, m); + if (ret) + pr_err("send raw data fail\n"); + + irblaster_chip_data_clear(chip); + mutex_unlock(&chip->sys_lock); + kfree(buffer); + + return ret ? : count; +} + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static ssize_t send_key_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + unsigned int addr, command; + int ret; + + ret = sscanf(buf, "%x %x", &addr, &command); + if (ret != 2) { + pr_err("Can't parse addr and command,usage:[addr command]\n"); + return -EINVAL; + } + mutex_lock(&chip->sys_lock); + ret = irblaster_send_key(chip, addr, command); + if (ret) + pr_err("send key fail\n"); + + mutex_unlock(&chip->sys_lock); + + return ret ? : count; +} +#endif + +static ssize_t carrier_freq_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", chip->state.freq); +} + +static ssize_t carrier_freq_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + int ret = 0, val; + + ret = kstrtoint(buf, 10, &val); + if (ret) { + pr_err("Invalid input for carrier_freq\n"); + return ret; + } + + mutex_lock(&chip->sys_lock); + ret = irblaster_set_freq(chip, val); + if (ret) + pr_err("set freq fail\n"); + + mutex_unlock(&chip->sys_lock); + + return ret ? : count; +} + +static ssize_t duty_cycle_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", chip->state.duty); +} + +static ssize_t duty_cycle_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + int ret = 0, val; + + ret = kstrtoint(buf, 10, &val); + if (ret) { + pr_err("Invalid input for duty_cycle\n"); + return ret; + } + + mutex_lock(&chip->sys_lock); + ret = irblaster_set_duty(chip, val); + if (ret) + pr_err("set duty fail\n"); + + mutex_unlock(&chip->sys_lock); + + return ret ? : count; +} + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static ssize_t protocol_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + unsigned int len; + + len = protocol_show_select(chip, buf); + + return len; +} + +static ssize_t protocol_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + unsigned int ret, protocol; + + protocol = protocol_store_select(buf); + if (protocol >= IRBLASTER_PROTOCOL_MAX) + pr_err("protocol is not found\n"); + + ret = irblaster_set_protocol(chip, protocol); + if (ret) + pr_err("set protocol fail\n"); + + return ret ? : count; +} +#endif + +//static DEVICE_ATTR(debug, 0644, show_debug, store_debug); +static DEVICE_ATTR_WO(send); +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static DEVICE_ATTR_WO(send_key); +#endif +static DEVICE_ATTR_RW(carrier_freq); +static DEVICE_ATTR_RW(duty_cycle); +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static DEVICE_ATTR_RW(protocol); +#endif + +static struct attribute *irblaster_chip_attrs[] = { +// &dev_attr_debug.attr, + &dev_attr_send.attr, +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + &dev_attr_send_key.attr, +#endif + &dev_attr_carrier_freq.attr, + &dev_attr_duty_cycle.attr, +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + &dev_attr_protocol.attr, +#endif + NULL, +}; +ATTRIBUTE_GROUPS(irblaster_chip); + +static struct class irblaster_class = { + .name = "irblaster", + .owner = THIS_MODULE, + .dev_groups = irblaster_chip_groups, +}; + +static int irblasterchip_sysfs_match(struct device *parent, const void *data) +{ + return dev_get_drvdata(parent) == data; +} + +void irblasterchip_sysfs_export(struct irblaster_chip *chip) +{ + struct device *parent; + + /* + * If device_create() fails the irblaster_chip is still usable by + * the kernel its just not exported. + */ + parent = device_create(&irblaster_class, chip->dev, MKDEV(0, 0), chip, + "irblaster%d", chip->base); + if (IS_ERR(parent)) { + dev_warn(chip->dev, + "device_create failed for irblaster_chip sysfs export\n"); + } + + mutex_init(&chip->sys_lock); +} + +void irblasterchip_sysfs_unexport(struct irblaster_chip *chip) +{ + struct device *parent; + + parent = class_find_device(&irblaster_class, NULL, chip, + irblasterchip_sysfs_match); + if (parent) { + /* for class_find_device() */ + put_device(parent); + device_unregister(parent); + } +} + +static int __init irblaster_sysfs_init(void) +{ + return class_register(&irblaster_class); +} +subsys_initcall(irblaster_sysfs_init); diff --git a/include/linux/amlogic/irblaster.h b/include/linux/amlogic/irblaster.h new file mode 100644 index 000000000000..b9cbf432ef5e --- /dev/null +++ b/include/linux/amlogic/irblaster.h @@ -0,0 +1,121 @@ +/* + * include/linux/amlogic/irblaster.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __LINUX_IRBLASTER_H +#define __LINUX_IRBLASTER_H + +#include +#include +#include +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#include +#endif + +#define MAX_PLUSE 256 +#define PS_SIZE 10 + +struct irblaster_chip; + +static DEFINE_MUTEX(irblaster_lock); +static LIST_HEAD(irblaster_chips); + +/** + * enum irblaster_idle - Whether the controller is occupied + * @IRBLASTER_EXPORTED: Controlled by the sysfs sys/class/irblaster + * @IRBLASTER_REQUESTED: Controlled by consumer driver + */ +enum irblaster_idle { + IRBLASTER_EXPORTED, + IRBLASTER_REQUESTED +}; + +/** + * struct irblaster_ops - irblaster controller operations + * @send: send raw level data + * @send_key: send key according to the protocol + * @set_freq: set irblaster freq + * @get_freq: get irblaster freq + * @set_duty: set irblaster duty + * @get_duty: get irblaster duty + */ +struct irblaster_ops { + int (*send)(struct irblaster_chip *chip, + unsigned int *data, unsigned int len); +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + int (*send_key)(struct irblaster_chip *chip, + unsigned int addr, int commmand); + /* int (*set_protocol)(struct irblaster_chip *chip, */ + /* enum irblaster_protocol protocol);*/ +#endif + int (*set_freq)(struct irblaster_chip *chip, unsigned int freq); + unsigned int (*get_freq)(struct irblaster_chip *chip); + int (*set_duty)(struct irblaster_chip *chip, unsigned int duty); + unsigned int (*get_duty)(struct irblaster_chip *chip); +}; + +struct irblaster_state { + unsigned int freq; + unsigned int duty; + int enabled; + int idle; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + enum irblaster_protocol protocol; +#endif +}; + +/** + * struct irblaster_chip - abstract a irblaster controller + * @dev: device providing the irblaster + * @list: list node for internal use + * @ops: callbacks for this irblaster controller + * @base: number of first irblaster controlled by this chip + * @of_irblaster_n_cells: number of cells expected in the device tree + * irblaster specifier + * @state: irblaster controller status + * @buffer: data + * @buffer_len: data len + * @sum_time: total time + * @request: whether the controller is occupied + */ +struct irblaster_chip { + struct device *dev; + struct list_head list; + struct irblaster_ops *ops; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + struct irblaster_raw_handler *protocol; +#endif + struct irblaster_state state; + struct mutex sys_lock; /* use to sysfs */ + unsigned int base; + unsigned int of_irblaster_n_cells; + /* unsigned int buffer[MAX_PLUSE]; */ + unsigned int *buffer; + unsigned int buffer_len; + unsigned int sum_time; + atomic_t request; +}; + +/* irblaster sysfs APIs */ +void irblasterchip_sysfs_export(struct irblaster_chip *chip); +void irblasterchip_sysfs_unexport(struct irblaster_chip *chip); + +/* irblaster provider APIs */ +int irblasterchip_add(struct irblaster_chip *chip); +int irblasterchip_remove(struct irblaster_chip *chip); +void irblaster_chip_data_clear(struct irblaster_chip *chip); + +#endif /* __LINUX_IRBLASTER_H */ diff --git a/include/linux/amlogic/irblaster_consumer.h b/include/linux/amlogic/irblaster_consumer.h new file mode 100644 index 000000000000..48f65330f247 --- /dev/null +++ b/include/linux/amlogic/irblaster_consumer.h @@ -0,0 +1,55 @@ +/* + * include/linux/amlogic/irblaster_consumer.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __LINUX_IRBLASTER_CONSUMER_H +#define __LINUX_IRBLASTER_CONSUMER_H + +#include +#include +#include +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#include +#endif + +struct irblaster_chip; + +/* irblaster user APIs */ +int irblaster_send(struct irblaster_chip *chip, + unsigned int *data, + unsigned int len); +int irblaster_set_freq(struct irblaster_chip *chip, + unsigned int freq); +unsigned int irblaster_get_freq(struct irblaster_chip *chip); +int irblaster_set_duty(struct irblaster_chip *chip, unsigned int duty); +unsigned int irblaster_get_duty(struct irblaster_chip *chip); +struct irblaster_chip *of_irblaster_get(struct device_node *np, + const char *con_id); +struct irblaster_chip *devm_of_irblaster_get(struct device *dev, + struct device_node *np, + const char *con_id); +void irblaster_put(struct irblaster_chip *chip); + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +int irblaster_send_key(struct irblaster_chip *chip, + unsigned int addr, + unsigned int commmand); +int irblaster_set_protocol(struct irblaster_chip *chip, + enum irblaster_protocol ir_protocol); +enum irblaster_protocol irblaster_get_protocol(struct irblaster_chip *chip); +#endif + +#endif /* __LINUX_IRBLASTER_CONSUMER_H */ diff --git a/include/linux/amlogic/irblaster_encoder.h b/include/linux/amlogic/irblaster_encoder.h new file mode 100644 index 000000000000..db0642f0fac4 --- /dev/null +++ b/include/linux/amlogic/irblaster_encoder.h @@ -0,0 +1,97 @@ +/* + * include/linux/amlogic/irblaster_encoder.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __LINUX_ENCODER_H +#define __LINUX_ENCODER_H + +#include +#include +#include + +struct irblaster_chip; +int irblaster_send(struct irblaster_chip *chip, unsigned int *data, + unsigned int len); + +static DEFINE_MUTEX(irblaster_raw_handler_lock); +static LIST_HEAD(irblaster_raw_handler_list); + +/** + * enum irblaster_protocol - protocol of irblaster + * add a new protocol here + * @IRBLASTER_PROTOCOL_MAX: Maximum number of support protocol + * please add a new protocol before this + */ +enum irblaster_protocol { + IRBLASTER_PROTOCOL_NEC, + IRBLASTER_PROTOCOL_NECX, + IRBLASTER_PROTOCOL_NEC32, + IRBLASTER_PROTOCOL_RCA, + IRBLASTER_PROTOCOL_MAX +}; + +#define IRBLASTER_PROTOCOL_BIT_NEC BIT_ULL(IRBLASTER_PROTOCOL_NEC) +#define IRBLASTER_PROTOCOL_BIT_NECX BIT_ULL(IRBLASTER_PROTOCOL_NECX) +#define IRBLASTER_PROTOCOL_BIT_NEC32 BIT_ULL(IRBLASTER_PROTOCOL_NEC32) +#define IRBLASTER_PROTOCOL_BIT_RCA BIT_ULL(IRBLASTER_PROTOCOL_RCA) + +/** + * struct irblaster_raw_timings - pulse-length modulation timings + * @header_pulse: duration of header pulse in ns (0 for none) + * @bit_space: duration of bit space in ns + * @bit_pulse: duration of bit pulse (for logic 0 and 1) in ns + * @trailer_space: duration of trailer space in ns + * @msb_first: 1 if most significant bit is sent first + * @raw_nbits: raw bit len + * @data_size: the total length of the array + */ +struct irblaster_raw_timings { + unsigned int header_pulse; + unsigned int header_space; + unsigned int bit_pulse; + unsigned int bit_space[2]; + unsigned int trailer_pulse; + unsigned int trailer_space; + unsigned int msb_first:1; + unsigned int raw_nbits; + unsigned int data_size; +}; + +struct irblaster_raw_handler { + struct list_head list; + char *name; + int protocol; /* which are handled by this handler */ + int (*encode)(enum irblaster_protocol protocol, unsigned int addr, + unsigned int commmand, unsigned int *data); + struct irblaster_raw_timings *timing; + struct mutex encode_lock; /* use to function encode */ + u32 freq; + u32 duty; +}; + +/* irblaster encode APIs */ +int irblaster_raw_handler_register(struct irblaster_raw_handler + *ir_raw_handler); +void irblaster_raw_handler_unregister(struct irblaster_raw_handler + *ir_raw_handler); +int irblaster_raw_gen(unsigned int *data, + const struct irblaster_raw_timings *timings, + u32 raw); + +unsigned int protocol_store_select(const char *buf); +unsigned int protocol_show_select(struct irblaster_chip *chip, char *buf); + +#endif /* __LINUX_ENCODER_H */ From e150b88405af864fe5da45c942e8b0f2eb8024aa Mon Sep 17 00:00:00 2001 From: "qingwei.xu" Date: Thu, 14 Mar 2019 10:16:13 +0800 Subject: [PATCH 0545/1060] dts: Ion and vdin0 CMA Memory Optimization [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-5896 Problem: The memory consumption of modules ion and vdin0 is too large Solution: Ion CMA memory optimization to 32M,vdin0 to 160M Verify: X301ã€T309 Change-Id: If9e54390baeda6d330bb2c96b14ef3975333a2f1 Signed-off-by: qingwei.xu --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 4 ++-- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 6c135b59028d..277abd768868 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -97,7 +97,7 @@ ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x8000000>; + size = <0x2000000>; alignment = <0x400000>; }; @@ -489,7 +489,7 @@ *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M */ - cma_size = <190>; + cma_size = <160>; interrupts = <0 83 1>; rdma-irq = <2>; clocks = <&clkc CLKID_FCLK_DIV5>, diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index fd1faa459f7d..1fed35eef24d 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -106,7 +106,7 @@ ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x8000000>; + size = <0x2000000>; alignment = <0x400000>; }; @@ -450,7 +450,7 @@ *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M */ - cma_size = <190>; + cma_size = <160>; interrupts = <0 83 1>; rdma-irq = <2>; clocks = <&clkc CLKID_FCLK_DIV5>, From 036f4aecf80e9c9b5129a071f1f1884b6c697961 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Fri, 22 Mar 2019 13:23:36 +0800 Subject: [PATCH 0546/1060] CPUFREQ: Setting different cpufreq tables. [1/1] PD#SWPL-4035 Problem: Setting different cpufreq tables. Solution: Setting different cpufreq tables. Verify: g12a_u200, verify pass Change-Id: If93f1baa1f50aeeed6e3d7f9d2ffeb1e0a5b4e02 Signed-off-by: Hong Guo --- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index b092b2b77ad5..cd3d653df59f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -941,9 +941,9 @@ hispeed_cpufreq_max = <2100>; medspeed_cpufreq_max = <1908>; lospeed_cpufreq_max = <1800>; - operating-points-v2 = <&cpu_opp_table0>; - //<&cpu_opp_table1>, - //<&cpu_opp_table2>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; }; &CPU1 { From 7c17db27ab1e5ac92969c7120d2052a30bc87079 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Fri, 22 Mar 2019 19:42:12 +0800 Subject: [PATCH 0547/1060] sd: optimize sduart not supported flag [1/1] PD#SWPL-4858 Problem: Soc not support sduart Solution: add not supported flag in dts Verify: verify by tl1 skt Change-Id: Ifd1f975bd13b150aac9d99f60423ab4f0b903c98 Signed-off-by: Nan Li Conflicts: drivers/amlogic/mmc/amlsd.c --- arch/arm64/boot/dts/amlogic/axg_s410.dts | 2 +- drivers/amlogic/mmc/amlsd.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/axg_s410.dts b/arch/arm64/boot/dts/amlogic/axg_s410.dts index 0e16cedf2cd1..a1ba6c854777 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s410.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s410.dts @@ -10,7 +10,7 @@ * * 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 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * */ diff --git a/drivers/amlogic/mmc/amlsd.c b/drivers/amlogic/mmc/amlsd.c index 25f5a53c0f6d..60e76076713f 100644 --- a/drivers/amlogic/mmc/amlsd.c +++ b/drivers/amlogic/mmc/amlsd.c @@ -675,6 +675,9 @@ static int aml_is_sduart(struct amlsd_platform *pdata) struct amlsd_host *host = pdata->host; struct sd_emmc_status *ista = (struct sd_emmc_status *)&vstat; + if (pdata->no_sduart) + return 0; + mutex_lock(&host->pinmux_lock); pc = aml_devm_pinctrl_get_select(host, "sd_to_ao_uart_pins"); @@ -867,8 +870,10 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) } } else { pr_info("normal card in\n"); - aml_uart_switch(pdata, 0); - aml_jtag_switch_ao(pdata); + if (!pdata->no_sduart) { + aml_uart_switch(pdata, 0); + aml_jtag_switch_ao(pdata); + } if (host->data->chip_type == MMC_CHIP_G12A) host->is_sduart = 0; if (pdata->caps & MMC_CAP_4_BIT_DATA) From a752a685cd2355bc1a43e183c791f22967d82901 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Wed, 27 Mar 2019 18:32:44 +0800 Subject: [PATCH 0548/1060] cpu_affinity: restore the original cpu affinity correctly [1/1] PD#SWPL-5595 Problem: set_cpus_allowed_ptr(current, cpu_all_mask) is always errorly called to retore CPU affinity for current task. In some cases, the current may be a bounded kworker thread, and we should not set its CPU affinity to all CPUs Solution: Save the original CPU affinity and restore it Verify: W400 revB Change-Id: I3cd65e79791563af9dacc09639b8645b97979c44 Signed-off-by: Jiamin Ma Conflicts: drivers/amlogic/efuse/efuse_hw64.c --- arch/arm/mach-meson/meson-secure.c | 8 +++- drivers/amlogic/audioinfo/audio_data.c | 4 +- drivers/amlogic/efuse/efuse_hw64.c | 16 +++++--- drivers/amlogic/jtag/meson_jtag.c | 8 +++- drivers/amlogic/mmc/amlsd.c | 10 ++++- drivers/amlogic/tee/tee.c | 55 -------------------------- 6 files changed, 34 insertions(+), 67 deletions(-) diff --git a/arch/arm/mach-meson/meson-secure.c b/arch/arm/mach-meson/meson-secure.c index d7931ed33f65..b9f03d2cf2c4 100644 --- a/arch/arm/mach-meson/meson-secure.c +++ b/arch/arm/mach-meson/meson-secure.c @@ -155,10 +155,12 @@ uint32_t meson_secure_mem_flash_size(void) int32_t meson_secure_mem_ge2d_access(uint32_t msec) { int ret = -1; + struct cpumask org_cpumask; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = meson_smc_hal_api(TRUSTZONE_HAL_API_MEMCONFIG_GE2D, msec); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } @@ -184,15 +186,17 @@ EXPORT_SYMBOL(meson_secure_jtag_apee); int meson_trustzone_efuse(void *arg) { int ret; + struct cpumask org_cpumask; if (!arg) return -1; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = meson_smc_hal_api(TRUSTZONE_HAL_API_EFUSE, __pa(arg)); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } diff --git a/drivers/amlogic/audioinfo/audio_data.c b/drivers/amlogic/audioinfo/audio_data.c index f5494c3eb2ce..f41136863eb7 100644 --- a/drivers/amlogic/audioinfo/audio_data.c +++ b/drivers/amlogic/audioinfo/audio_data.c @@ -101,12 +101,14 @@ int meson_efuse_fn_smc_query_audioinfo(struct efuse_hal_api_arg *arg) int meson_trustzone_audio_info_get(struct efuse_hal_api_arg *arg) { int ret; + struct cpumask org_cpumask; if (!arg) return -1; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = meson_efuse_fn_smc_query_audioinfo(arg); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } diff --git a/drivers/amlogic/efuse/efuse_hw64.c b/drivers/amlogic/efuse/efuse_hw64.c index 6da11f489755..4e4ae939300c 100644 --- a/drivers/amlogic/efuse/efuse_hw64.c +++ b/drivers/amlogic/efuse/efuse_hw64.c @@ -74,13 +74,15 @@ static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) int meson_trustzone_efuse(struct efuse_hal_api_arg *arg) { int ret; + struct cpumask org_cpumask; if (!arg) return -1; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); - ret = meson_efuse_fn_smc(arg); - set_cpus_allowed_ptr(current, cpu_all_mask); + ret = meson64_efuse_fn_smc(arg); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } @@ -122,13 +124,15 @@ unsigned long efuse_aml_sec_boot_check(unsigned long nType, unsigned long efuse_amlogic_set(char *buf, size_t count) { unsigned long ret; + struct cpumask org_cpumask; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = efuse_aml_sec_boot_check(AML_D_P_W_EFUSE_AMLOGIC, (unsigned long)buf, (unsigned long)count, 0); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } @@ -160,12 +164,14 @@ ssize_t efuse_get_max(void) { struct efuse_hal_api_arg arg; int ret; + struct cpumask org_cpumask; arg.cmd = EFUSE_HAL_API_USER_MAX; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); - ret = meson_trustzone_efuse_get_max(&arg); - set_cpus_allowed_ptr(current, cpu_all_mask); + ret = meson64_trustzone_efuse_get_max(&arg); + set_cpus_allowed_ptr(current, &org_cpumask); if (ret == 0) { pr_info("ERROR: can not get efuse user max bytes!!!\n"); diff --git a/drivers/amlogic/jtag/meson_jtag.c b/drivers/amlogic/jtag/meson_jtag.c index e3890ac67aeb..a080ef5574bb 100644 --- a/drivers/amlogic/jtag/meson_jtag.c +++ b/drivers/amlogic/jtag/meson_jtag.c @@ -182,7 +182,9 @@ static int aml_jtag_select_tee(struct platform_device *pdev) { struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); uint32_t select = jdev->select; + struct cpumask org_cpumask; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); pr_info("meson8b select %s\n", select_to_name(jdev->select)); switch (select) { @@ -200,7 +202,7 @@ static int aml_jtag_select_tee(struct platform_device *pdev) writel_relaxed(0x0, jdev->base); break; } - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return 0; } @@ -291,6 +293,7 @@ static int aml_jtag_select(struct platform_device *pdev) struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); unsigned int select = jdev->select; unsigned int state = AMLOGIC_JTAG_STATE_OFF; + struct cpumask org_cpumask; if (select != AMLOGIC_JTAG_DISABLE) state = AMLOGIC_JTAG_STATE_ON; @@ -299,9 +302,10 @@ static int aml_jtag_select(struct platform_device *pdev) select |= jdev->cluster << CLUSTER_BIT; pr_info("select %s\n", select_to_name(select)); + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); aml_set_jtag_state(state, select); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return 0; } diff --git a/drivers/amlogic/mmc/amlsd.c b/drivers/amlogic/mmc/amlsd.c index 60e76076713f..3b9100677659 100644 --- a/drivers/amlogic/mmc/amlsd.c +++ b/drivers/amlogic/mmc/amlsd.c @@ -753,16 +753,22 @@ void jtag_set_state(unsigned int state, unsigned int select) void jtag_select_ao(void) { + struct cpumask org_cpumask; + + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); jtag_set_state(AMLOGIC_JTAG_STATE_ON, AMLOGIC_JTAG_APAO); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); } void jtag_select_sd(void) { + struct cpumask org_cpumask; + + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); jtag_set_state(AMLOGIC_JTAG_STATE_ON, AMLOGIC_JTAG_APEE); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); } #endif diff --git a/drivers/amlogic/tee/tee.c b/drivers/amlogic/tee/tee.c index b10634f238b4..1c2e3ebd1693 100644 --- a/drivers/amlogic/tee/tee.c +++ b/drivers/amlogic/tee/tee.c @@ -21,8 +21,6 @@ #include #include -#include -#include #include #define DRIVER_NAME "tee_info" @@ -73,25 +71,12 @@ static int tee_msg_os_revision(uint32_t *major, uint32_t *minor) struct arm_smccc_res smccc; struct tee_smc_calls_revision_result result; } res; - long cpu; - - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } arm_smccc_smc(TEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc); *major = res.result.major; *minor = res.result.minor; - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); return 0; } @@ -101,25 +86,12 @@ static int tee_msg_api_revision(uint32_t *major, uint32_t *minor) struct arm_smccc_res smccc; struct tee_smc_calls_revision_result result; } res; - long cpu; - - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } arm_smccc_smc(TEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc); *major = res.result.major; *minor = res.result.minor; - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); return 0; } @@ -165,23 +137,10 @@ static CLASS_ATTR(api_version, 0644, tee_api_version_show, static int tee_load_firmware(uint32_t index, uint32_t vdec, bool is_swap) { struct arm_smccc_res res; - long cpu; - - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW, index, vdec, is_swap, 0, 0, 0, 0, &res); - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); return res.a0; } @@ -200,26 +159,12 @@ EXPORT_SYMBOL(tee_load_video_fw_swap); bool tee_enabled(void) { struct arm_smccc_res res; - long cpu; if (disable_flag == 1) return false; /*return false;*/ /*disable tee load temporary*/ - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } - arm_smccc_smc(TEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res); - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); - if (res.a0 == TEE_MSG_UID_0 && res.a1 == TEE_MSG_UID_1 && res.a2 == TEE_MSG_UID_2 && res.a3 == TEE_MSG_UID_3) return true; From abad8a7c46f91c869dcb49c764c3e8bcaf4521db Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Fri, 15 Mar 2019 19:20:40 +0800 Subject: [PATCH 0549/1060] tvafe: add control for tvconfig snow config [1/1] PD#SWPL-5985 Problem: display snow when snow config disabled Solution: add control for tvconfig snow config Verify: verify it on x301 Change-Id: I3466efc98577f2403f3a6cd638ad7dbf70ce34dc Signed-off-by: Nian Jing Conflicts: include/linux/amlogic/media/frame_provider/tvin/tvin.h --- drivers/amlogic/media/vin/tvin/tvafe/tvafe.c | 33 +++++++++++++++++-- drivers/amlogic/media/vin/tvin/tvafe/tvafe.h | 5 ++- .../amlogic/media/vin/tvin/tvafe/tvafe_cvd.c | 6 ++-- .../media/vin/tvin/tvafe/tvafe_debug.c | 12 +++++++ .../amlogic/media/frame_provider/tvin/tvin.h | 4 +++ 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index 9192297e4b59..9d5cc275f907 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -101,6 +101,8 @@ static int cutwindow_val_h_level2 = 18; static int cutwindow_val_h_level3 = 20; static int cutwindow_val_h_level4 = 62;/*48-->62 for ntsc-m*/ +/*tvconfig snow config*/ +static bool snow_cfg; /*1: snow function on;*/ /*0: off snow function*/ bool tvafe_snow_function_flag; @@ -820,6 +822,18 @@ static bool tvafe_cvbs_get_secam_phase(struct tvin_frontend_s *fe) } +bool tvafe_get_snow_cfg(void) +{ + return snow_cfg; +} +EXPORT_SYMBOL(tvafe_get_snow_cfg); + +void tvafe_set_snow_cfg(bool cfg) +{ + snow_cfg = cfg; +} +EXPORT_SYMBOL(tvafe_set_snow_cfg); + /**check frame skip,only for av input*/ static bool tvafe_cvbs_check_frame_skip(struct tvin_frontend_s *fe) { @@ -890,6 +904,7 @@ static long tvafe_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = 0; + unsigned int snowcfg = 0; void __user *argp = (void __user *)arg; struct tvafe_dev_s *devp = file->private_data; struct tvafe_info_s *tvafe = &devp->tvafe; @@ -905,8 +920,8 @@ static long tvafe_ioctl(struct file *file, return -EPERM; mutex_lock(&devp->afe_mutex); - if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { - + if (!(devp->flags & TVAFE_FLAG_DEV_OPENED) && + cmd != TVIN_IOC_S_AFE_SONWCFG) { tvafe_pr_info("%s, tvafe device is disable, ignore the command %d\n", __func__, cmd); mutex_unlock(&devp->afe_mutex); @@ -934,6 +949,20 @@ static long tvafe_ioctl(struct file *file, break; } + case TVIN_IOC_S_AFE_SONWCFG: + /*tl1/txhd tvconfig snow en/disable*/ + if (copy_from_user(&snowcfg, argp, + sizeof(unsigned int))) { + tvafe_pr_info("snowcfg: get param err\n"); + ret = -EINVAL; + break; + } + if (snowcfg == 1) + tvafe_set_snow_cfg(true); + else + tvafe_set_snow_cfg(false); + tvafe_pr_info("tvconfig snow:%d\n", snow_cfg); + break; case TVIN_IOC_S_AFE_SONWON: devp->flags |= TVAFE_FLAG_DEV_SNOW_FLAG; tvafe_snow_function_flag = true; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h index 7fe836ff993c..0c42042b9369 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h @@ -32,7 +32,7 @@ /* ************************************************* */ /* *** macro definitions ********************************************* */ /* *********************************************************** */ -#define TVAFE_VER "Ref.2018/06/27" +#define TVAFE_VER "Ref.2019/03/18" /* used to set the flag of tvafe_dev_s */ #define TVAFE_FLAG_DEV_OPENED 0x00000010 @@ -94,6 +94,9 @@ struct tvafe_dev_s { unsigned int sizeof_tvafe_dev_s; }; +bool tvafe_get_snow_cfg(void); +void tvafe_set_snow_cfg(bool cfg); + typedef int (*hook_func_t)(void); extern void aml_fe_hook_cvd(hook_func_t atv_mode, hook_func_t cvd_hv_lock, hook_func_t get_fmt); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 5f6a80e49014..31ffdde86ca5 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -27,6 +27,7 @@ #include #include "../tvin_global.h" #include "../tvin_format_table.h" +#include "tvafe.h" #include "tvafe_regs.h" #include "tvafe_cvd.h" #include "tvafe_debug.h" @@ -418,8 +419,9 @@ static void tvafe_cvd2_write_mode_reg(struct tvafe_cvd2_s *cvd2, } /*setting for txhd snow*/ - if (tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_get_snow_cfg() && + (tvafe_cpu_type() == CPU_TYPE_TXHD || + tvafe_cpu_type() == CPU_TYPE_TL1)) { W_APB_BIT(CVD2_OUTPUT_CONTROL, 3, 5, 2); W_APB_REG(ACD_REG_6C, 0x80500000); } diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c index 0518189f1b24..dd4745534441 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c @@ -256,6 +256,18 @@ static ssize_t tvafe_store(struct device *dev, } } else if (!strncmp(buff, "afe_ver", strlen("afe_ver"))) { tvafe_pr_info("tvafe version : %s\n", TVAFE_VER); + } else if (!strncmp(buff, "snowcfg", strlen("snowcfg"))) { + if (kstrtoul(parm[1], 10, &val) < 0) { + kfree(buf_orig); + return -EINVAL; + } + if (val) { + tvafe_set_snow_cfg(true); + tvafe_pr_info("[tvafe..]hadware snow cfg en\n"); + } else { + tvafe_set_snow_cfg(false); + tvafe_pr_info("[tvafe..]hadware snow cfg dis\n"); + } } else if (!strncmp(buff, "snowon", strlen("snowon"))) { if (kstrtoul(parm[1], 10, &val) < 0) { kfree(buf_orig); diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index 3504f2912285..ba25340c5c8a 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -445,6 +445,10 @@ struct tvafe_pin_mux_s { #define TVIN_IOC_LOAD_REG _IOW(_TM_T, 0x20, struct am_regs_s) #define TVIN_IOC_S_AFE_SONWON _IO(_TM_T, 0x22) #define TVIN_IOC_S_AFE_SONWOFF _IO(_TM_T, 0x23) +#define TVIN_IOC_G_VDIN_HIST _IOW(_TM_T, 0x24, struct vdin_hist_s) +#define TVIN_IOC_S_VDIN_V4L2START _IOW(_TM_T, 0x25, struct vdin_v4l2_param_s) +#define TVIN_IOC_S_VDIN_V4L2STOP _IO(_TM_T, 0x26) +#define TVIN_IOC_S_AFE_SONWCFG _IOW(_TM_T, 0x27, unsigned int) /* *function defined applied for other driver From e0a7cb799d6be4843431d968ed66a1fdf2beef26 Mon Sep 17 00:00:00 2001 From: Yeping Miao Date: Mon, 18 Mar 2019 14:02:41 +0800 Subject: [PATCH 0550/1060] dts: GVA on SBR platform [1/1] PD#SWPL-4760 Problem: Port GVA on S400 SBR platform Solution: Port GVA on S400 SBR platform Verify: S400_SBR A113D Change-Id: I615e9457ba83df1c30829aa8ce01b6bc6072929f Signed-off-by: Yeping Miao Conflicts: MAINTAINERS --- MAINTAINERS | 1 - .../boot/dts/amlogic/axg_s400_v03gva_sbr.dts | 1679 +++++++++++++++++ .../boot/dts/amlogic/axg_s400_v03gva_sbr.dts | 1639 ++++++++++++++++ 3 files changed, 3318 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts create mode 100644 arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts diff --git a/MAINTAINERS b/MAINTAINERS index 85a81814e1f2..a41f4f758650 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11487,7 +11487,6 @@ F: arch/alpha/kernel/srm_env.c STABLE BRANCH M: Greg Kroah-Hartman -M: Sasha Levin L: stable@vger.kernel.org S: Supported F: Documentation/stable_kernel_rules.txt diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts new file mode 100644 index 000000000000..1174f5283fb8 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts @@ -0,0 +1,1679 @@ +/* + * arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/*#include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03gva_sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x3e000000 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + alloc-ranges = <0x3e000000 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0xFFE07800 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + factory{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0xffe09000 0x80 + 0xffd01008 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0xffe09080 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0xf9800000 0x400000 + 0xff646000 0x2000 + 0xf9f00000 0x100000 + PCIE_PHY_REG PCIE_PHY_SIZE + PCIE_RESET_REG PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0xfa000000 0x400000 + 0xff648000 0x2000 + 0xfa400000 0x100000 + PCIE_PHY_REG PCIE_PHY_SIZE + PCIE_RESET_REG PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disable"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF632000 0x2000>; + }; + audiobus_base { + reg = <0xFF642000 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0xffe07000 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0xffe05000 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; + key_num = <6>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106>; + key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "okay"; + }; +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 0>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + aml_pca9557: aml_pca9557@0x1f { + compatible = "amlogic,pca9557_keypad"; + reg = <0x1f>; + key_num = <4>; + key_name = "fdr", "hotword", "pause", "mute"; + key_value = <106 105 139 116>; + key_index_mask = <0x4 0x8 0x10 0x20>; + key_input_mask = <0x3C>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disable"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disable"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disable"; + }; + + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disable"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disable"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disable"; + }; + cy8c4014_08: cy8c4014_08@08 { + compatible = "cy8c4014"; + #sound-dai-cells = <0>; + reg = <0x8>; + status = "okay"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236,gva"; + reg = <0x3c>; + status = "okay"; + led1_b { + label="LED1_B"; + reg_offset = <1>; + }; + led1_g { + label="LED1_G"; + reg_offset = <2>; + }; + led1_r { + label="LED1_R"; + reg_offset = <3>; + }; + led2_b { + label="LED2_B"; + reg_offset = <4>; + }; + led2_g { + label="LED2_G"; + reg_offset = <5>; + }; + led2_r { + label="LED2_R"; + reg_offset = <6>; + }; + led3_b { + label="LED3_B"; + reg_offset = <7>; + }; + led3_g { + label="LED3_G"; + reg_offset = <8>; + }; + led3_r { + label="LED3_R"; + reg_offset = <9>; + }; + led4_b { + label="LED4_B"; + reg_offset = <10>; + }; + led4_g { + label="LED4_G"; + reg_offset = <11>; + }; + led4_r { + label="LED4_R"; + reg_offset = <12>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <45>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ + >; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts new file mode 100644 index 000000000000..e03817b5ed24 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts @@ -0,0 +1,1639 @@ +/* + * arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/* #include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03gva_sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x0 0x3e000000 0x0 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + factory{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0x0 0xffe09080 0x0 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xf9800000 0x0 0x400000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xf9f00000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xfa000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfa400000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0x0 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF632000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe07000 0x0 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe05000 0x0 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; + key_num = <6>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106>; + key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_6:key_6{ + key-name = "gva_certs"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "okay"; + }; +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + tas5707_36: tas5707_36@36 { + compatible = "ti, tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 0>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + aml_pca9557: aml_pca9557@0x1f { + compatible = "amlogic,pca9557_keypad"; + reg = <0x1f>; + key_num = <4>; + key_name = "fdr", "hotword", "pause", "mute"; + key_value = <106 105 139 116>; + key_index_mask = <0x4 0x8 0x10 0x20>; + key_input_mask = <0x3C>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disable"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disable"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disable"; + }; + + cy8c4014_08: cy8c4014_08@08 { + compatible = "cy8c4014"; + #sound-dai-cells = <0>; + reg = <0x8>; + status = "okay"; + }; + + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236,gva"; + reg = <0x3c>; + status = "okay"; + led1_b { + label="LED1_B"; + reg_offset = <1>; + }; + led1_g { + label="LED1_G"; + reg_offset = <2>; + }; + led1_r { + label="LED1_R"; + reg_offset = <3>; + }; + led2_b { + label="LED2_B"; + reg_offset = <4>; + }; + led2_g { + label="LED2_G"; + reg_offset = <5>; + }; + led2_r { + label="LED2_R"; + reg_offset = <6>; + }; + led3_b { + label="LED3_B"; + reg_offset = <7>; + }; + led3_g { + label="LED3_G"; + reg_offset = <8>; + }; + led3_r { + label="LED3_R"; + reg_offset = <9>; + }; + led4_b { + label="LED4_B"; + reg_offset = <10>; + }; + led4_g { + label="LED4_G"; + reg_offset = <11>; + }; + led4_r { + label="LED4_R"; + reg_offset = <12>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <45>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ + >; + }; +}; From c1fe5f27130c179c7bf96d9987653504ca3f37c0 Mon Sep 17 00:00:00 2001 From: Zhuo Wang Date: Tue, 2 Apr 2019 13:43:59 +0800 Subject: [PATCH 0551/1060] ethernet: reset ethernet when resume [1/1] PD#SWPL-6608 Problem: system will report tx error somethime after resume Solution: reset ethernet when resume Verify: verify on u200 board Change-Id: I9863a8a50c08addd4e2d8c024f46a2e7568c28b4 Signed-off-by: Zhuo Wang Conflicts: drivers/net/ethernet/stmicro/stmmac/stmmac_main.c --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 35ce8e105346..99e074a489bc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -124,8 +124,15 @@ static void stmmac_exit_fs(struct net_device *dev); #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) +/*won't be valid unless enable amlogic priv code*/ +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +#undef TX_MONITOR +#endif + +#ifdef TX_MONITOR static struct workqueue_struct *moniter_tx_wq; static struct delayed_work moniter_tx_worker; +#endif /** * stmmac_verify_args - verify the driver parameters. * Description: it checks the driver parameters and set a default in case of @@ -1877,8 +1884,9 @@ static int stmmac_open(struct net_device *dev) napi_enable(&priv->napi); netif_start_queue(dev); - +#ifdef TX_MONITOR queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); +#endif return 0; lpiirq_error: @@ -2721,14 +2729,18 @@ static int stmmac_poll(struct napi_struct *napi, int budget) * netdev structure and arrange for the device to be reset to a sane state * in order to transmit a new packet. */ +#ifdef TX_MONITOR unsigned int timeout_err; +#endif static void stmmac_tx_timeout(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); /* Clear Tx resources and restart transmitting again */ stmmac_tx_err(priv); +#ifdef TX_MONITOR timeout_err = 1; +#endif } /** @@ -3266,12 +3278,13 @@ static int stmmac_hw_init(struct stmmac_priv *priv) return 0; } +#ifdef TX_MONITOR struct stmmac_priv *priv_monitor; static void moniter_tx_handler(struct work_struct *work) { if (priv_monitor) { if (timeout_err) { - pr_info("recover eth\n"); + pr_info("reset eth\n"); stmmac_release(priv_monitor->dev); stmmac_open(priv_monitor->dev); timeout_err = 0; @@ -3281,6 +3294,7 @@ static void moniter_tx_handler(struct work_struct *work) } queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); } +#endif /** * stmmac_dvr_probe * @device: device pointer @@ -3299,8 +3313,10 @@ int stmmac_dvr_probe(struct device *device, struct net_device *ndev = NULL; struct stmmac_priv *priv; +#ifdef TX_MONITOR moniter_tx_wq = create_singlethread_workqueue("eth_moniter_tx_wq"); INIT_DELAYED_WORK(&moniter_tx_worker, moniter_tx_handler); +#endif ndev = alloc_etherdev(sizeof(struct stmmac_priv)); if (!ndev) return -ENOMEM; @@ -3452,7 +3468,9 @@ int stmmac_dvr_probe(struct device *device, ret = gmac_create_sysfs( mdiobus_get_phy(priv->mii, priv->plat->phy_addr), priv->ioaddr); #endif +#ifdef TX_MONITOR priv_monitor = priv; +#endif return ret; error_netdev_register: @@ -3523,7 +3541,9 @@ int stmmac_suspend(struct device *dev) struct stmmac_priv *priv = netdev_priv(ndev); unsigned long flags; +#ifdef TX_MONITOR cancel_delayed_work_sync(&moniter_tx_worker); +#endif if (!ndev || !netif_running(ndev)) return 0; @@ -3641,8 +3661,10 @@ int stmmac_resume(struct device *dev) if (priv->phydev) phy_start(priv->phydev); +#ifdef TX_MONITOR queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); timeout_err = 1; +#endif return 0; } EXPORT_SYMBOL_GPL(stmmac_resume); From f82abc79403296706e87b7b05684a4568e8d44de Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Fri, 22 Mar 2019 14:12:05 +0800 Subject: [PATCH 0552/1060] ramdump: write compressed data [2/2] PD#SWPL-6193 Problem: ramdump need write compressed data to persist storage device. But if we write it under uboot, it may cause journal and block bitmap mismatch due to different version of file system. This caused kernel panic after ramdump finished. Solution: Write compressed data under kernel. This change also removed some extern function of ramdump since we use sticky register to store ramdump information. Verify: p212 Change-Id: Idd83ec6ead4783918b90a39cf716fd3117402278 Signed-off-by: Tao Zeng Conflicts: arch/arm/boot/dts/amlogic/mesonaxg.dtsi arch/arm/boot/dts/amlogic/mesong12a.dtsi arch/arm/boot/dts/amlogic/mesongxl.dtsi arch/arm/boot/dts/amlogic/mesongxm.dtsi arch/arm/boot/dts/amlogic/mesontl1.dtsi arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm/boot/dts/amlogic/mesontxlx.dtsi arch/arm64/boot/dts/amlogic/mesonaxg.dtsi arch/arm64/boot/dts/amlogic/mesong12a.dtsi arch/arm64/boot/dts/amlogic/mesongxl.dtsi arch/arm64/boot/dts/amlogic/mesongxm.dtsi arch/arm64/boot/dts/amlogic/mesontxl.dtsi arch/arm64/boot/dts/amlogic/mesontxlx.dtsi drivers/amlogic/memory_ext/ram_dump.c include/linux/amlogic/ramdump.h --- arch/arm/boot/dts/amlogic/mesonaxg.dtsi | 3 + arch/arm/boot/dts/amlogic/mesong12a.dtsi | 3 + arch/arm/boot/dts/amlogic/mesong12b.dtsi | 3 +- arch/arm/boot/dts/amlogic/mesongxl.dtsi | 3 + arch/arm/boot/dts/amlogic/mesongxm.dtsi | 3 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 1 + arch/arm/boot/dts/amlogic/mesontl1.dtsi | 3 + arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 3 + arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 4 +- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 3 + arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 7 +- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 3 + arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 3 + arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 1 + arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 1 + arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 3 + drivers/amlogic/memory_ext/ram_dump.c | 403 ++++++++++++++------- drivers/amlogic/reboot/reboot.c | 12 - include/linux/amlogic/ramdump.h | 4 +- 19 files changed, 323 insertions(+), 143 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index afc6d9c11ca5..96331fde716e 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -280,6 +280,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index b8aeaeec1e8d..d926815858c3 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -442,6 +442,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index b13e3f39a8df..45b6d9e93b4f 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -562,6 +562,7 @@ status = "okay"; reg = <0xFF6345E0 4>; reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; soc { @@ -1459,7 +1460,7 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index 419d03bbd5f5..9125cf8609e4 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -245,6 +245,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xC88345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index 9c74f5a7953d..d85f15302be3 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -280,6 +280,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xC88345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index debf56856b83..4434665e29f6 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -456,6 +456,7 @@ status = "okay"; reg = <0xFF6345E0 4>; reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi index f9ec2f20488a..fdea55461771 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1.dtsi @@ -255,6 +255,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; securitykey { diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 8c7a8c066e3e..061ed8102c58 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -283,6 +283,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index ecc71cff7fef..ff04a7444754 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -155,7 +155,6 @@ <0x0 0xff80023c 0x0 0x4>; }; - secmon { compatible = "amlogic, secmon"; memory-region = <&secmon_reserved>; @@ -280,6 +279,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index f1d13fdf7c34..87763ac66ddd 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -442,6 +442,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 86098ac55816..4223513c2c04 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -562,6 +562,7 @@ status = "okay"; reg = <0x0 0xFF6345E0 0x0 4>; reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; soc { @@ -1469,7 +1470,7 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; @@ -1685,7 +1686,7 @@ thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { - temperature = <65000>; + temperature = <60000>; hysteresis = <5000>; type = "passive"; }; @@ -1695,7 +1696,7 @@ type = "passive"; }; phot: trip-point@2 { - temperature = <95000>; + temperature = <85000>; hysteresis = <5000>; type = "hot"; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index aa7b9950261b..a0b68a157774 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -232,6 +232,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xC88345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 24ba0cc5069a..bd6a808a5200 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -280,6 +280,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xC88345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 6baae096db75..05adbf3dcd3a 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -456,6 +456,7 @@ status = "okay"; reg = <0x0 0xFF6345E0 0x0 4>; reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index fd55efc15ec5..6c32bb7070b1 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -256,6 +256,7 @@ status = "okay"; reg = <0x0 0xFF6345E0 0x0 4>; reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; vpu { diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 0b4a3af42277..13e13ef9996c 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -283,6 +283,9 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { diff --git a/drivers/amlogic/memory_ext/ram_dump.c b/drivers/amlogic/memory_ext/ram_dump.c index 3634ad4fb818..5290a82aaeb1 100644 --- a/drivers/amlogic/memory_ext/ram_dump.c +++ b/drivers/amlogic/memory_ext/ram_dump.c @@ -26,38 +26,39 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include #include static unsigned long ramdump_base __initdata; static unsigned long ramdump_size __initdata; static bool ramdump_disable __initdata; +#define WAIT_TIMEOUT (40ULL * 1000 * 1000 * 1000) + struct ramdump { unsigned long mem_base; unsigned long mem_size; - struct mutex lock; - struct kobject *kobj; - struct work_struct clear_work; + unsigned long long tick; + void *mnt_buf; + const char *storage_device; + struct delayed_work work; int disable; }; static struct ramdump *ram; -static void meson_set_reboot_reason(int reboot_reason) -{ - struct arm_smccc_res smccc; - - arm_smccc_smc(SET_REBOOT_REASON, - reboot_reason, 0, 0, 0, 0, 0, 0, &smccc); - return; -} - static int __init early_ramdump_para(char *buf) { int ret; @@ -84,94 +85,10 @@ static int __init early_ramdump_para(char *buf) ramdump_disable = 1; } } - if (ramdump_disable) - meson_set_reboot_reason(MESON_NORMAL_BOOT); - return 0; } early_param("ramdump", early_ramdump_para); -static ssize_t ramdump_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - void *p = NULL; -#ifndef CONFIG_64BIT - struct page *page, *pages[1]; -#endif - - if (!ram->mem_base || off >= ram->mem_size) - return 0; - -#ifndef CONFIG_64BIT - page = phys_to_page(ram->mem_base + off); - pages[0] = page; - p = vmap(pages, 1, VM_MAP, PAGE_KERNEL); - if (!p) { - pr_info("%s, map %lx, %d failed, page:%p, pfn:%lx\n", - __func__, (unsigned long)(ram->mem_base + off), - count, page, page_to_pfn(page)); - return -EINVAL; - } -#else - p = (void *)(ram->mem_base + off); -#endif - if (off + count > ram->mem_size) - count = ram->mem_size - off; - mutex_lock(&ram->lock); - memcpy(buf, p, count); - mutex_unlock(&ram->lock); - - /* debug when read end */ - if (off + count >= ram->mem_size) - pr_info("%s, p=%p %p, off:%lli, c:%zi\n", - __func__, buf, p, off, count); -#ifndef CONFIG_64BIT - vunmap(p); -#endif - return count; -} - -int ramdump_disabled(void) -{ - if (ram) - return ram->disable; - return 0; -} -EXPORT_SYMBOL(ramdump_disabled); - -static ssize_t ramdump_bin_write(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - if (!ram->mem_size) - return -EINVAL; - - if (ram->mem_base && !strncmp("reboot", buf, 6)) - kernel_restart("RAM-DUMP finished\n"); - - if (!strncmp("disable", buf, 7)) { - ram->disable = 1; - meson_set_reboot_reason(MESON_NORMAL_BOOT); - } - if (!strncmp("enable", buf, 6)) { - ram->disable = 0; - meson_set_reboot_reason(MESON_KERNEL_PANIC); - } - - return count; -} - -static struct bin_attribute ramdump_attr = { - .attr = { - .name = "compmsg", - .mode = S_IRUGO | S_IWUSR, - }, - .read = ramdump_bin_read, - .write = ramdump_bin_write, -}; - /* * clear memory to avoid large amount of memory not used. * for ramdom data, it's hard to compress @@ -279,9 +196,242 @@ void ramdump_sync_data(void) } #endif +#ifdef CONFIG_64BIT +static void free_reserved_highmem(unsigned long start, unsigned long end) +{ +} +#else +static void free_reserved_highmem(unsigned long start, unsigned long end) +{ + for (; start < end; ) { + free_highmem_page(phys_to_page(start)); + start += PAGE_SIZE; + } +} +#endif + +static void free_reserved_mem(unsigned long start, unsigned long size) +{ + unsigned long end = PAGE_ALIGN(start + size); + struct page *page, *epage; + + page = phys_to_page(start); + if (PageHighMem(page)) { + free_reserved_highmem(start, end); + } else { + epage = phys_to_page(end); + if (!PageHighMem(epage)) { + free_reserved_area(__va(start), + __va(end), 0, "ramdump"); + } else { + /* reserved area cross zone */ + struct zone *zone; + unsigned long bound; + + zone = page_zone(page); + bound = zone_end_pfn(zone); + free_reserved_area(__va(start), + __va(bound << PAGE_SHIFT), + 0, "ramdump"); + zone = page_zone(epage); + bound = zone->zone_start_pfn; + free_reserved_highmem(bound << PAGE_SHIFT, end); + } + } +} + +static int check_storage_mounted(char **root) +{ + int fd, cnt, ret = 0; + char mnt_dev[64] = {}, *mnt_ptr, *root_dir; + + fd = sys_open("/proc/mounts", O_RDONLY, 0); + if (!fd) { + pr_debug("%s, open mounts failed:%d\n", __func__, fd); + return -EINVAL; + } + cnt = sys_read(fd, ram->mnt_buf, PAGE_SIZE); + if (cnt < 0) { + pr_debug("%s, read mounts failed:%d\n", __func__, cnt); + ret = -ENODEV; + goto exit; + } + pr_debug("read:%d, %s\n", cnt, (char *)ram->mnt_buf); + sprintf(mnt_dev, "/dev/block/%s", ram->storage_device); + mnt_ptr = strstr((char *)ram->mnt_buf, mnt_dev); + if (mnt_ptr) { + pr_debug("%s, find %s in buffer, ptr:%p\n", + __func__, mnt_dev, mnt_ptr); + root_dir = strstr(mnt_ptr, " "); + root_dir++; + *root = root_dir; + pr_debug("mount:%s root:%s\n", mnt_ptr, root_dir); + } else + ret = -ENODEV; +exit: + sys_close(fd); + return ret; +} + +static size_t save_data(int fd) +{ + unsigned long saved = 0, off = 0, s = 0, e; + void *buffer; + int block = (1 << (PAGE_SHIFT + MAX_ORDER - 1)), wsize = 0, ret, i; + struct vm_struct *area; + struct page *page, **pages = NULL; + + area = get_vm_area(block, VM_ALLOC); + if (!area) { + pr_err("%s, get vma failed\n", __func__); + return -ENOMEM; + } + + pages = kzalloc(sizeof(unsigned long) * MAX_ORDER_NR_PAGES, GFP_KERNEL); + if (!pages) + goto out; + + buffer = area->addr; + while (saved < ram->mem_size) { + s = ram->mem_size - saved; + if (s >= block) + wsize = block; + else + wsize = s; + + s = ram->mem_base + off; + e = s + PAGE_ALIGN(wsize); + + page = phys_to_page(s); + for (i = 0; i < MAX_ORDER_NR_PAGES; i++) { + pages[i] = page; + page++; + } + ret = map_kernel_range_noflush((unsigned long)buffer, + PAGE_ALIGN(wsize), + PAGE_KERNEL, + pages); + if (!ret) { + pr_err("map page:%lx failed\n", page_to_pfn(page)); + goto out; + } + ret = sys_write(fd, buffer, wsize); + if (ret != wsize) { + unmap_kernel_range((unsigned long)buffer, + PAGE_ALIGN(wsize)); + pr_err("%s, write failed\n", __func__); + goto out; + } + unmap_kernel_range((unsigned long)buffer, PAGE_ALIGN(wsize)); + free_reserved_mem(s, PAGE_ALIGN(wsize)); + saved += wsize; + off += wsize; + pr_debug("%s, write %08lx, size:%08x, saved:%08lx, off:%lx\n", + __func__, s, wsize, saved, off); + } +out: + free_vm_area(area); + kfree(pages); + pr_info("%s, write %08lx, size:%08x, saved:%08lx, off:%lx\n", + __func__, s, wsize, saved, off); + return saved; +} + +#define OPEN_FLAGS (O_WRONLY | O_CREAT | O_DSYNC | O_TRUNC) + +static void wait_to_save(struct work_struct *work) +{ + char *root; + int fd, ret = 0; + int need_reboot = 0; + + if ((sched_clock() - ram->tick) >= WAIT_TIMEOUT) { + pr_err("can't find mounted device, free saved data\n"); + need_reboot = 3; + goto exit; + } + + if (!check_storage_mounted(&root)) { + char wname[64] = {}, *next_token; + + /* write compressed data to storage device */ + next_token = strstr(root, " "); + if (next_token) + *next_token = '\0'; + sprintf(wname, "%s/crashdump-1.bin", root); + fd = sys_open(wname, OPEN_FLAGS, 0644); + if (fd < 0) { + pr_info("open %s failed:%d\n", wname, fd); + need_reboot = 3; + goto exit; + } + ret = save_data(fd); + if (ret != ram->mem_size) { + pr_err("write size %d not match %ld\n", + ret, ram->mem_size); + } + sys_fsync(fd); + sys_close(fd); + sys_sync(); + need_reboot = 1; + } else + schedule_delayed_work(&ram->work, 500); + +exit: + /* Nomatter what happened, reboot must be done in this function */ + if (need_reboot) { + if (need_reboot & 0x1) + kfree(ram->mnt_buf); + if (need_reboot & 0x02) + free_reserved_mem(ram->mem_base, ram->mem_size); + kernel_restart("RAM-DUMP finished"); + } +} + static int __init ramdump_probe(struct platform_device *pdev) { void __iomem *p = NULL; + struct device_node *np; + unsigned long dts_memory[2] = {0}, total_mem; + struct resource *res; + unsigned int dump_set; + int ret; + void __iomem *base; + const char *dev_name = NULL; + + np = of_find_node_by_name(NULL, "memory"); + if (!np) + return -EINVAL; + +#ifdef CONFIG_64BIT + ret = of_property_read_u64_array(np, "linux,usable-memory", + (u64 *)&dts_memory, 2); + if (ret) + ret = of_property_read_u64_array(np, "reg", + (u64 *)&dts_memory, 2); +#else + ret = of_property_read_u32_array(np, "linux,usable-memory", + (u32 *)&dts_memory, 2); + if (ret) + ret = of_property_read_u32_array(np, "reg", + (u32 *)&dts_memory, 2); +#endif + if (ret) + pr_info("can't get dts memory\n"); + else + pr_info("MEMORY:[%lx+%lx]\n", dts_memory[0], dts_memory[1]); + of_node_put(np); + + /* + * memory in dts is [start_addr size] patten. For amlogic soc, + * ddr address range is started from 0x0, usually start_addr in + * dts should be started with 0x0, but some soc must reserve a + * small framgment of memory at 0x0 for start up code. So start_addr + * can be 0x100000/0x1000000. But we always using 0x0 to get real + * DDR size for ramdump. So we using following formula to get total + * DDR size. + */ + total_mem = dts_memory[0] + dts_memory[1]; ram = kzalloc(sizeof(struct ramdump), GFP_KERNEL); if (!ram) @@ -290,44 +440,52 @@ static int __init ramdump_probe(struct platform_device *pdev) if (ramdump_disable) ram->disable = 1; + np = pdev->dev.of_node; + ret = of_property_read_string(np, "store_device", &dev_name); + if (!ret) { + ram->storage_device = dev_name; + pr_info("%s, storage device:%s\n", __func__, dev_name); + } + if (!ramdump_base || !ramdump_size) { pr_info("NO valid ramdump args:%lx %lx\n", ramdump_base, ramdump_size); } else { - #ifdef CONFIG_64BIT - p = ioremap_cache(ramdump_base, ramdump_size); - ram->mem_base = (unsigned long)p; - ram->mem_size = ramdump_size; - #else ram->mem_base = ramdump_base; ram->mem_size = ramdump_size; - #endif pr_info("%s, mem_base:%p, %lx, size:%lx\n", __func__, p, ramdump_base, ramdump_size); } - ram->kobj = kobject_create_and_add("mdump", kernel_kobj); - if (!ram->kobj) { - pr_err("%s, create sysfs failed\n", __func__); - goto err; + + if (!ram->disable) { + if (!ram->mem_base) { /* No compressed data */ + INIT_DELAYED_WORK(&ram->work, lazy_clear_work); + } else { /* with compressed data */ + INIT_DELAYED_WORK(&ram->work, wait_to_save); + ram->tick = sched_clock(); + ram->mnt_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + WARN_ON(!ram->mnt_buf); + } + schedule_delayed_work(&ram->work, 1); } - ramdump_attr.size = ram->mem_size; - if (sysfs_create_bin_file(ram->kobj, &ramdump_attr)) { - pr_err("%s, create sysfs1 failed\n", __func__); - goto err1; - } - mutex_init(&ram->lock); - if (!ram->disable && !ram->mem_size) { - INIT_WORK(&ram->clear_work, lazy_clear_work); - schedule_work(&ram->clear_work); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "PREG_STICKY_REG8"); + if (res) { + base = devm_ioremap(&pdev->dev, res->start, + res->end - res->start); + if (!base) { + pr_err("%s, map reg failed\n", __func__); + goto err; + } + dump_set = readl(base); + dump_set &= ~RAMDUMP_STICKY_DATA_MASK; + dump_set |= ((total_mem >> 20) | AMLOGIC_KERNEL_BOOTED); + writel(dump_set, base); + pr_info("%s, set sticky to %x\n", __func__, dump_set); } return 0; -err1: - kobject_put(ram->kobj); err: -#ifdef CONFIG_64BIT - iounmap((void *)ram->mem_base); -#endif kfree(ram); return -EINVAL; @@ -335,11 +493,6 @@ err: static int ramdump_remove(struct platform_device *pdev) { - sysfs_remove_bin_file(ram->kobj, &ramdump_attr); -#ifdef CONFIG_64BIT - iounmap((void *)ram->mem_base); -#endif - kobject_put(ram->kobj); kfree(ram); return 0; } diff --git a/drivers/amlogic/reboot/reboot.c b/drivers/amlogic/reboot/reboot.c index 235d12dc4a6a..80cf73760a48 100644 --- a/drivers/amlogic/reboot/reboot.c +++ b/drivers/amlogic/reboot/reboot.c @@ -33,10 +33,6 @@ #include #include #include -#ifdef CONFIG_AMLOGIC_RAMDUMP -#include -#define RAMDUMP_REPLACE_MSG "ramdump disabled, replase panic to normal\n" -#endif /* CONFIG_AMLOGIC_RAMDUMP */ static u32 psci_function_id_restart; static u32 psci_function_id_poweroff; @@ -72,15 +68,7 @@ static u32 parse_reason(const char *cmd) } else { if (kernel_panic) { if (strcmp(kernel_panic, "kernel_panic") == 0) { - #ifdef CONFIG_AMLOGIC_RAMDUMP - if (ramdump_disabled()) { - reboot_reason = MESON_NORMAL_BOOT; - pr_info(RAMDUMP_REPLACE_MSG); - } else - reboot_reason = MESON_KERNEL_PANIC; - #else reboot_reason = MESON_KERNEL_PANIC; - #endif } } diff --git a/include/linux/amlogic/ramdump.h b/include/linux/amlogic/ramdump.h index 5dc0c4219e04..8782418c1113 100644 --- a/include/linux/amlogic/ramdump.h +++ b/include/linux/amlogic/ramdump.h @@ -20,7 +20,9 @@ #define SET_REBOOT_REASON 0x82000049 -extern int ramdump_disabled(void); +#define AMLOGIC_KERNEL_BOOTED 0x8000 +#define RAMDUMP_STICKY_DATA_MASK 0xFFFF + extern void ramdump_sync_data(void); #endif /* __RAMDUMP_H__ */ From c73ef5f4303dcfb89f2bc0be6741c1f92780c242 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 8 Apr 2019 14:24:11 +0800 Subject: [PATCH 0553/1060] vlock: add phase lock pll mode [1/1] PD#SWPL-6899 Problem: enable vlock phase lock function in pll mode Solution: 1.when phase lock on, and when phase lock flag not assert disable ss. 2.after phase lock flag assert, restore ss Verify: tl1 Change-Id: I2f9f6ec76468b1043c1b7ec99b2daa4f9d69ae60 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/enhancement/amvecm/vlock.c --- .../amlogic/media/enhancement/amvecm/amvecm.c | 2 +- .../enhancement/amvecm/amvecm_vlock_regmap.h | 3 +- .../media/enhancement/amvecm/arch/vpp_regs.h | 4 +- .../amlogic/media/enhancement/amvecm/vlock.c | 135 ++++++++++++++---- .../amlogic/media/enhancement/amvecm/vlock.h | 2 +- .../amlogic/media/vout/lcd/lcd_clk_config.c | 27 ++++ 6 files changed, 139 insertions(+), 34 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 430ea828330e..e92a2320bfcc 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -6545,7 +6545,7 @@ static const struct vecm_match_data_s vecm_dt_tl1 = { .vlk_support = true, .vlk_new_fsm = 1, .vlk_hwver = vlock_hw_ver2, - .vlk_phlock_en = false, + .vlk_phlock_en = true, }; static const struct of_device_id aml_vecm_dt_match[] = { diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index 862b4faad881..45e74bfaa81b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -75,12 +75,11 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { #define VLOCK_PHASE_REG_SIZE 9 static struct vlock_regs_s vlock_pll_phase_setting[VLOCK_PHASE_REG_SIZE] = { - {0x3004, 0x00620680}, + {0x3004, 0x00604680}, {0x3009, 0x06000000}, {0x300a, 0x00600000}, {0x300b, 0x06000000}, {0x300c, 0x00600000}, - {0x3025, 0x00002000}, {0x3027, 0x00022002}, {0x3028, 0x00001000}, diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h index 48f1be555193..0f8e1bc534a9 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h @@ -331,7 +331,7 @@ #define VPU_VLOCK_RO_LINE_PIX_ADJ 0x3013 #define VPU_VLOCK_RO_OUTPUT_00_01 0x3014 #define VPU_VLOCK_RO_OUTPUT_10_11 0x3015 -#define VPU_VLOCK_MX4096 0x3016 +#define VPU_VLOCK_MX4096 0x3016 #define VPU_VLOCK_STBDET_WIN0_WIN1 0x3017 #define VPU_VLOCK_STBDET_CLP 0x3018 #define VPU_VLOCK_STBDET_ABS_WIN0 0x3019 @@ -339,7 +339,7 @@ #define VPU_VLOCK_STBDET_SGN_WIN0 0x301b #define VPU_VLOCK_STBDET_SGN_WIN1 0x301c #define VPU_VLOCK_ADJ_EN_SYNC_CTRL 0x301d -#define VPU_VLOCK_GCLK_EN 0x301e +#define VPU_VLOCK_GCLK_EN 0x301e #define VPU_VLOCK_LOOP1_ACCUM_LMT 0x301f #define VPU_VLOCK_RO_M_INT_FRAC 0x3020 #define VPU_VLOCK_RO_PH_DIS 0x3021 diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index f9405f1b6c07..4f589a0f2f59 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -212,6 +212,14 @@ void vlock_set_panel_pll(u32 m, u32 frac) vlock_set_panel_pll_frac(frac); } +void vlock_set_panel_ss(u32 onoff) +{ + if (onoff) + lcd_ss_enable(1); + else + lcd_ss_enable(0); +} + /*returen 1: use phase lock*/ int phase_lock_check(void) { @@ -775,6 +783,10 @@ static bool vlock_disable_step2(void) pr_info(">>>[%s]\n", __func__); } + /*restore ss setting*/ + if (!vlock.ss_sts) + vlock_set_panel_ss(true); + return ret; } @@ -1595,7 +1607,6 @@ void vlock_status_init(void) /* vlock.phlock_percent = phlock_percent; */ vlock_clear_frame_counter(); - pr_info("%s vlock_en:%d\n", __func__, vlock_en); } @@ -1636,7 +1647,7 @@ void vlock_set_phase_en(u32 en) if (en) vlock.phlock_en = true; else - vlock.dtdata->vlk_phlock_en = false; + vlock.phlock_en = false; pr_info("vlock phlock_en=%d\n", en); } @@ -1645,22 +1656,18 @@ void vlock_phaselock_check(struct stvlock_sig_sts *pvlock, { /*vs_i*/ u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); - u32 val; - static u32 cnt = 48; + u32 val, pre; - if (vlock.dtdata->vlk_phlock_en) { - if (cnt++ > 50) { + if (vlock.phlock_en) { + if ((pvlock->frame_cnt_in%100) == 0) { ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + pre = READ_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT); val = (ia * (100 + vlock.phlock_percent))/200; - WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); - cnt = 0; - #if 0 - /*reset*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); - #endif + if (val != pre) { + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); + vlock_reset(1); + vlock_reset(0); + } } } } @@ -1670,10 +1677,10 @@ bool vlock_get_phlock_flag(void) u32 flag; u32 sts; - if (!vlock.dtdata->vlk_phlock_en) - return false; + if (!vlock.phlock_en) + return false; - flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 17; + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 16; flag = flag&0x01; if (vlock.dtdata->vlk_new_fsm) @@ -1692,7 +1699,7 @@ bool vlock_get_vlock_flag(void) u32 flag; u32 sts; - flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 16; + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 17; flag = flag&0x01; if (vlock.dtdata->vlk_new_fsm) @@ -1825,6 +1832,11 @@ u32 vlock_fsm_to_en_func(struct stvlock_sig_sts *pvlock, vinfo = get_current_vinfo(); vlock_enable_step1(vf, vinfo, pvlock->input_hz, pvlock->output_hz); + if (IS_PLL_MODE(vlock_mode) && + pvlock->phlock_en) { + vlock_set_panel_ss(false); + pvlock->ss_sts = false; + } ret = 1; } @@ -1840,8 +1852,9 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, if ((pvlock->frame_cnt_in <= 3) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/ + vlock_reset(1); /*clear first 3 frame internal cnt*/ WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); @@ -1851,9 +1864,10 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { /*cal accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ /*cal accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ + vlock_reset(0); if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("%s -1\n", __func__); } else if (pvlock->frame_cnt_in == 5) { @@ -1870,12 +1884,11 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, input_vs_cnt*125/100); WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, input_vs_cnt*70/100); - /*cal accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ /*cal accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); - + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + vlock_reset(0); /* * tl1 auto pll,swich clk need after *several frames @@ -1897,6 +1910,68 @@ u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, return ret; } +void vlock_fsm_check_lock_sts(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 frqlock_sts = vlock_get_vlock_flag(); + u32 phlock_sts = vlock_get_phlock_flag(); + u32 pherr; + static u32 rstflag; + + /*check frq lock*/ + if (pvlock->frqlock_sts != frqlock_sts) { + pr_info("frq lock sts(%d,%d) cnt:%d\n", pvlock->frqlock_sts, + frqlock_sts, pvlock->frame_cnt_in); + pvlock->frqlock_sts = frqlock_sts; + } + + /*check phase error*/ + if (IS_PLL_MODE(vlock_mode) && + pvlock->phlock_en) { + /*after frq lock, then enable phase lock*/ + /*check phase err*/ + pherr = READ_VPP_REG(VPU_VLOCK_RO_PH_ERR) & 0xffffff; + if (pherr & 0x800000) + pherr = 0xffffff - pherr + 1;/*negative value*/ + + if (rstflag) { + rstflag = false; + vlock_reset(0); + } else if (pherr > 0x1ff) { + if ((pvlock->frame_cnt_in%80) == 0) { + vlock_reset(1); + rstflag = true; + } + } + } + + /*check phase lock*/ + if (pvlock->phlock_en && + (pvlock->phlock_sts != phlock_sts)) { + pr_info("ph lock sts(%d,%d) cnt:%d\n", pvlock->phlock_sts, + phlock_sts, pvlock->frame_cnt_in); + pvlock->phlock_sts = phlock_sts; + if (phlock_sts && !pvlock->ss_sts && + (pvlock->frame_cnt_in > 25)) { + vlock_set_panel_ss(true); + pvlock->ss_sts = true; + } + } + + /*pretect and enable ss*/ + if (IS_PLL_MODE(vlock_mode) && + pvlock->phlock_en) { + /*error check*/ + if ((pvlock->frame_cnt_in >= 3500) && (!pvlock->ss_sts)) { + pr_info("vlock warning: set back ss on(%d, %d)\n", + frqlock_sts, phlock_sts); + pvlock->pll_mode_pause = true; + pvlock->ss_sts = true; + vlock_set_panel_ss(true); + } + } +} + u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, struct vframe_s *vf) { @@ -1907,7 +1982,8 @@ u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, (IS_MANUAL_MODE(vlock_mode))) { if (IS_MANUAL_ENC_MODE(vlock_mode)) vlock_enable_step3_enc(); - else if (IS_MANUAL_PLL_MODE(vlock_mode)) + else if (IS_MANUAL_PLL_MODE(vlock_mode) && + (!pvlock->pll_mode_pause)) vlock_enable_step3_pll(); else if (IS_MANUAL_SOFTENC_MODE(vlock_mode)) vlock_enable_step3_soft_enc(); @@ -1918,6 +1994,9 @@ u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, /*check phase*/ vlock_phaselock_check(pvlock, vf); + + vlock_fsm_check_lock_sts(pvlock, vf); + return ret; } diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index a1008a3bfca7..628f72a80700 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2019/4/02a" +#define VLOCK_VER "Ref.2019/4/10a finetune phase lock" #define VLOCK_REG_NUM 33 diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 8f143badc2bf..295059c010ec 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -2228,6 +2228,33 @@ lcd_set_spread_spectrum_end: LCDPR("%s\n", __func__); } +/* design for vlock, don't save ss_level to clk_config */ +int lcd_ss_enable(unsigned int flag) +{ + unsigned int level; + unsigned long flags = 0; + int ret = -1; + + spin_lock_irqsave(&lcd_clk_lock, flags); + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + goto lcd_ss_enable_end; + } + + if (clk_conf.data->set_ss_level) { + level = flag ? clk_conf.ss_level : 0; + clk_conf.data->set_ss_level(level); + } + +lcd_ss_enable_end: + spin_unlock_irqrestore(&lcd_clk_lock, flags); + + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + return ret; +} + int lcd_encl_clk_msr(void) { unsigned int clk_mux; From 22daa717bade6425ecc6b1fb23797ec83aa044ca Mon Sep 17 00:00:00 2001 From: Yeping Miao Date: Wed, 3 Apr 2019 14:07:55 +0800 Subject: [PATCH 0554/1060] dts: Improve axg_s400_v03sbr.dts [1/1] PD#SWPL-6696 Problem: Pad key '+' cannot work Solution: Add to pad key support list Add more key support for SBR remote Verify: S400 S400_SBR A113D Change-Id: I9bdc3053f2b3ce778e9c2f682fcf31ac054887b4 Signed-off-by: Yeping Miao --- arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts | 37 +++++++++++++++---- .../boot/dts/amlogic/axg_s400_v03sbr.dts | 37 +++++++++++++++---- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts index 55f80117e55f..b09543d0e9dc 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -847,15 +847,15 @@ adc_keypad { compatible = "amlogic, adc_keypad"; status = "okay"; - key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; - key_num = <6>; + key_name = "power", "vol-", "sos+", "wifi", "<<", ">>", "vol+"; + key_num = <7>; io-channels = <&saradc SARADC_CH0>; io-channel-names = "key-chan-0"; key_chan = ; - key_code = <116 114 115 139 105 106>; - key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 - key_tolerance = <40 40 40 40 40 40>; + SARADC_CH0 SARADC_CH0 SARADC_CH0 SARADC_CH0>; + key_code = <116 114 115 139 105 106 107>; + key_val = <0 143 266 389 512 635 840>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; }; unifykey{ @@ -1666,7 +1666,7 @@ mapname = "amlogic-remote-3"; customcode = <0xa4e8>; /* Reference Remote Control */ release_delay = <80>; - size = <22>; + size = <45>; keymap = < REMOTE_KEY(0xc7, 200) /* power */ REMOTE_KEY(0x93, 201) /* eject-->input source */ @@ -1690,6 +1690,29 @@ REMOTE_KEY(0x68, 219) /* HFILT */ REMOTE_KEY(0x69, 220) /* Loundness */ REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ >; }; }; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts index 2ed30851891d..026f07e4e50b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -847,15 +847,15 @@ adc_keypad { compatible = "amlogic, adc_keypad"; status = "okay"; - key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; - key_num = <6>; + key_name = "power", "vol-", "sos+", "wifi", "<<", ">>", "vol+"; + key_num = <7>; io-channels = <&saradc SARADC_CH0>; io-channel-names = "key-chan-0"; key_chan = ; - key_code = <116 114 115 139 105 106>; - key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 - key_tolerance = <40 40 40 40 40 40>; + SARADC_CH0 SARADC_CH0 SARADC_CH0 SARADC_CH0>; + key_code = <116 114 115 139 105 106 107>; + key_val = <0 143 266 389 512 635 840>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; }; unifykey{ @@ -1666,7 +1666,7 @@ mapname = "amlogic-remote-3"; customcode = <0xa4e8>; /* Reference Remote Control */ release_delay = <80>; - size = <22>; + size = <45>; keymap = < REMOTE_KEY(0xc7, 200) /* power */ REMOTE_KEY(0x93, 201) /* eject-->input source */ @@ -1690,6 +1690,29 @@ REMOTE_KEY(0x68, 219) /* HFILT */ REMOTE_KEY(0x69, 220) /* Loundness */ REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ >; }; }; From 4c4a043503ef7d2c38a7fb27da85526be7a93bb3 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Fri, 19 Apr 2019 19:27:56 +0800 Subject: [PATCH 0555/1060] vlock: disable some log [1/1] PD#SWPL-6994 Problem: disable some log Solution: disable some log Verify: tl1 Change-Id: I53ceafbd35445f60d6c59ff9fd2632e8a6fc794f Signed-off-by: Yong Qin --- drivers/amlogic/media/enhancement/amvecm/vlock.c | 11 ++++++++--- drivers/amlogic/media/enhancement/amvecm/vlock.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 4f589a0f2f59..6fba57dfe9b4 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -1920,7 +1920,9 @@ void vlock_fsm_check_lock_sts(struct stvlock_sig_sts *pvlock, /*check frq lock*/ if (pvlock->frqlock_sts != frqlock_sts) { - pr_info("frq lock sts(%d,%d) cnt:%d\n", pvlock->frqlock_sts, + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("frq lock sts(%d,%d) cnt:%d\n", + pvlock->frqlock_sts, frqlock_sts, pvlock->frame_cnt_in); pvlock->frqlock_sts = frqlock_sts; } @@ -1948,7 +1950,9 @@ void vlock_fsm_check_lock_sts(struct stvlock_sig_sts *pvlock, /*check phase lock*/ if (pvlock->phlock_en && (pvlock->phlock_sts != phlock_sts)) { - pr_info("ph lock sts(%d,%d) cnt:%d\n", pvlock->phlock_sts, + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("ph lock sts(%d,%d) cnt:%d\n", + pvlock->phlock_sts, phlock_sts, pvlock->frame_cnt_in); pvlock->phlock_sts = phlock_sts; if (phlock_sts && !pvlock->ss_sts && @@ -1963,7 +1967,8 @@ void vlock_fsm_check_lock_sts(struct stvlock_sig_sts *pvlock, pvlock->phlock_en) { /*error check*/ if ((pvlock->frame_cnt_in >= 3500) && (!pvlock->ss_sts)) { - pr_info("vlock warning: set back ss on(%d, %d)\n", + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock warning: set back ss on(%d, %d)\n", frqlock_sts, phlock_sts); pvlock->pll_mode_pause = true; pvlock->ss_sts = true; diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index 628f72a80700..07e6e37cca9f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2019/4/10a finetune phase lock" +#define VLOCK_VER "Ref.2019/4/19:disable some log" #define VLOCK_REG_NUM 33 From c7d4cff22ff454d6249c41be360f3fd238aa3e19 Mon Sep 17 00:00:00 2001 From: Xiaoming Sui Date: Mon, 15 Apr 2019 20:38:47 +0800 Subject: [PATCH 0556/1060] avsync: spdif: fix the avsync for ms12 [1/4] PD#SWPL-5837 Problem: dtv is out of avsync when dolby ms12 certificate Solution: when the audio is played, recalculate the apts to sync pcrsrc when pcrmaster. Verify: X301 Change-Id: I199383aa1c0de1b4f0ec646d9d066910b3bb2b42 Signed-off-by: Xiaoming Sui --- sound/soc/amlogic/auge/spdif.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 647675755c80..62dd3a2cf782 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -376,19 +376,35 @@ static int spdif_clk_set(struct snd_kcontrol *kcontrol, { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int mpll_freq = 0; + int ret; int sysclk = p_spdif->sysclk_freq; int value = ucontrol->value.enumerated.item[0]; - if (value > 2000000 || value < 0) { pr_err("Fine spdif sysclk setting range(0~2000000), %d\n", value); return 0; } - sysclk += (value - 1000000); - - aml_dai_set_spdif_sysclk(cpu_dai, 0, sysclk, 0); - + value = value - 1000000; + sysclk += value; + /* pr_info("spdif_set %d to %d,diff %d\n", + * p_spdif->sysclk_freq,sysclk,value); + */ + mpll_freq = sysclk * 4; + p_spdif->sysclk_freq = sysclk; + clk_set_rate(p_spdif->sysclk, mpll_freq); + clk_set_rate(p_spdif->clk_spdifout, p_spdif->sysclk_freq); + ret = clk_prepare_enable(p_spdif->sysclk); + if (ret) { + pr_err("Can't enable pcm sysclk clock: %d\n", ret); + return 0; + } + ret = clk_prepare_enable(p_spdif->clk_spdifout); + if (ret) { + pr_err("Can't enable clk_spdifout clock: %d\n", ret); + return 0; + } return 0; } From 77215197e08d5b759f65c0193673c4faa2d71106 Mon Sep 17 00:00:00 2001 From: Hong Guo Date: Thu, 18 Apr 2019 16:42:01 +0800 Subject: [PATCH 0557/1060] supsend: update gx_pm driver [1/1] PD#SWPL-7226 Problem: update gx_pm driver Solution: update gx_pm driver Verify: test pass on tl1_x309 Change-Id: If078b0744cb8ce46029d77512d5755f4d40c2014 Signed-off-by: Hong Guo Conflicts: arch/arm/boot/dts/amlogic/mesontxl.dtsi arch/arm64/boot/dts/amlogic/mesontl1.dtsi arch/arm64/boot/dts/amlogic/mesontxl.dtsi --- MAINTAINERS | 13 +- arch/arm/boot/dts/amlogic/mesonaxg.dtsi | 7 +- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 6 +- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 6 +- arch/arm/boot/dts/amlogic/mesong12b_a.dtsi | 6 +- arch/arm/boot/dts/amlogic/mesongxl.dtsi | 7 +- .../arm/boot/dts/amlogic/mesongxl_sei210.dtsi | 7 +- arch/arm/boot/dts/amlogic/mesongxm.dtsi | 7 +- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 6 +- arch/arm/boot/dts/amlogic/mesontl1.dtsi | 2142 ----------------- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 8 +- arch/arm/boot/dts/amlogic/mesontxlx.dtsi | 9 +- arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 6 +- arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 6 +- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 6 +- arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 4 +- arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 7 +- .../boot/dts/amlogic/mesongxl_sei210.dtsi | 7 +- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 7 +- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 6 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 8 +- arch/arm64/boot/dts/amlogic/mesontxlx.dtsi | 9 +- drivers/amlogic/pm/gx_pm.c | 35 +- 23 files changed, 107 insertions(+), 2218 deletions(-) delete mode 100644 arch/arm/boot/dts/amlogic/mesontl1.dtsi diff --git a/MAINTAINERS b/MAINTAINERS index a41f4f758650..678bff30a24f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14059,6 +14059,13 @@ AMLOGIC AXG ADD AO CLK M: Yun Cai F: drivers/amlogic/clk/axg/axg_ao.c +AMLOGIC Irblaster driver +M: Zan Peng +F: drivers/amlogic/irblaster/irblaster.c +F: drivers/amlogic/irblaster/irblaster.h +F: drivers/amlogic/irblaster/Kconfig +F: drivers/amlogic/irblaster/Makefile + AMLOGIC AXG ADD CLKMSR INTERFACE M: wang xing F: include/linux/amlogic/clk_measure.h @@ -14414,9 +14421,9 @@ F: drivers/amlogic/cpufreq/meson-cpufreq.c F: drivers/amlogic/clk/clk-cpu-fclk-composite.c AMLOGIC Irblaster driver -M: Bichao.Zheng -F: drivers/amlogic/irblaster/* -F: include/linux/amlogic/irblaster* +M: yu.tu +F: drivers/amlogic/irblaster/meson-irblaster.c +F: drivers/amlogic/irblaster/meson-irblaster.h AMLOGIC THERMAL DRIVER M: Huan Biao diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index 96331fde716e..50f35d5820ec 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -147,15 +147,14 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; device_name = "aml_pm"; status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; - secmon { compatible = "amlogic, secmon"; memory-region = <&secmon_reserved>; diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index d926815858c3..9dbd9237d9ab 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -183,12 +183,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 45b6d9e93b4f..ad995402c1d1 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -245,12 +245,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi index 2b1a806f56bb..32ba3e4542e4 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -245,12 +245,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index 9125cf8609e4..e159aa654d17 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -159,11 +159,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0xc81000a8 0x4>, - <0xc810023c 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi index c76fb65b3fcf..dfc36e9bce33 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -161,11 +161,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0xc81000a8 0x4 - 0xc810023c 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index d85f15302be3..0fe9914d6301 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -302,11 +302,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0xc81000a8 0x4>, - <0xc810023c 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 4434665e29f6..0092cbe0741d 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -183,12 +183,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontl1.dtsi deleted file mode 100644 index fdea55461771..000000000000 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ /dev/null @@ -1,2142 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/mesontl1.dtsi - * - * Copyright (C) 2018 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mesong12a-bifrost.dtsi" - -/ { - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - cpus:cpus { - #address-cells = <1>; - #size-cells = <0>; - #cooling-cells = <2>;/* min followed by max */ - CPU0:cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x0>; - //timer=<&timer_a>; - enable-method = "psci"; - clocks = <&clkc CLKID_CPU_CLK>, - <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; - clock-names = "core_clk", - "low_freq_clk_parent", - "high_freq_clk_parent"; - operating-points-v2 = <&cpu_opp_table0>; - cpu-supply = <&vddcpu0>; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU1:cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x1>; - //timer=<&timer_b>; - enable-method = "psci"; - clocks = <&clkc CLKID_CPU_CLK>, - <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; - clock-names = "core_clk", - "low_freq_clk_parent", - "high_freq_clk_parent"; - operating-points-v2 = <&cpu_opp_table0>; - cpu-supply = <&vddcpu0>; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU2:cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x2>; - //timer=<&timer_c>; - enable-method = "psci"; - clocks = <&clkc CLKID_CPU_CLK>, - <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; - clock-names = "core_clk", - "low_freq_clk_parent", - "high_freq_clk_parent"; - operating-points-v2 = <&cpu_opp_table0>; - cpu-supply = <&vddcpu0>; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU3:cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0x3>; - //timer=<&timer_d>; - enable-method = "psci"; - clocks = <&clkc CLKID_CPU_CLK>, - <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; - clock-names = "core_clk", - "low_freq_clk_parent", - "high_freq_clk_parent"; - operating-points-v2 = <&cpu_opp_table0>; - cpu-supply = <&vddcpu0>; - //cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - timer_bc { - compatible = "arm, meson-bc-timer"; - reg = <0xffd0f190 0x4 0xffd0f194 0x4>; - timer_name = "Meson TimerF"; - clockevent-rating =<300>; - clockevent-shift =<20>; - clockevent-features =<0x23>; - interrupts = <0 60 1>; - bit_enable =<16>; - bit_mode =<12>; - bit_resolution =<0>; - }; - - arm_pmu { - compatible = "arm,cortex-a15-pmu"; - /* clusterb-enabled; */ - interrupts = ; - reg = <0xff634680 0x4>; - cpumasks = <0xf>; - /* default 10ms */ - relax-timer-ns = <10000000>; - /* default 10000us */ - max-wait-cnt = <10000>; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0xffc01000 0x1000>, - <0xffc02000 0x0100>; - interrupts = ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - scpi_clocks { - compatible = "arm, scpi-clks"; - - scpi_dvfs: scpi_clocks@0 { - compatible = "arm, scpi-clk-indexed"; - #clock-cells = <1>; - clock-indices = <0>; - clock-output-names = "vcpu"; - }; - }; - - secmon { - compatible = "amlogic, secmon"; - memory-region = <&secmon_reserved>; - in_base_func = <0x82000020>; - out_base_func = <0x82000021>; - reserve_mem_size = <0x00300000>; - }; - - securitykey { - compatible = "amlogic, securitykey"; - status = "okay"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - - mailbox: mhu@ff63c400 { - compatible = "amlogic, meson_mhu"; - reg = <0xff63c400 0x4c>, /* MHU registers */ - <0xfffd7000 0x800>; /* Payload area */ - interrupts = <0 209 1>, /* low priority interrupt */ - <0 210 1>; /* high priority interrupt */ - #mbox-cells = <1>; - mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; - mboxes = <&mailbox 0 &mailbox 1>; - }; - - cpu_iomap { - compatible = "amlogic, iomap"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - io_cbus_base { - reg = <0xffd00000 0x101000>; - }; - io_apb_base { - reg = <0xffe01000 0x19f000>; - }; - io_aobus_base { - reg = <0xff800000 0x100000>; - }; - io_vapb_base { - reg = <0xff900000 0x200000>; - }; - io_hiu_base { - reg = <0xff63c000 0x2000>; - }; - }; - - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; - - meson_suspend: pm { - compatible = "amlogic, pm"; - /*gxbaby-suspend;*/ - status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; - }; - - cpuinfo { - compatible = "amlogic, cpuinfo"; - status = "okay"; - cpuinfo_cmd = <0x82000044>; - }; - - reboot { - compatible = "amlogic,reboot"; - sys_reset = <0x84000009>; - sys_poweroff = <0x84000008>; - }; - - ram-dump { - compatible = "amlogic, ram_dump"; - status = "okay"; - reg = <0xFF6345E0 4>; - reg-names = "PREG_STICKY_REG8"; - store_device = "data"; - }; - - securitykey { - compatible = "amlogic, securitykey"; - status = "okay"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - - vpu { - compatible = "amlogic, vpu-tl1"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <7>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ - }; - - ethmac: ethernet@ff3f0000 { - compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; - reg = <0xff3f0000 0x10000 - 0xff634540 0x8 - 0xff64c000 0xa0>; - reg-names = "eth_base", "eth_cfg", "eth_pll"; - interrupts = <0 8 1>; - interrupt-names = "macirq"; - status = "disabled"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; - analog_val = <0x20200000 0x0000c000 0x00000023>; - }; - - pinctrl_aobus: pinctrl@ff800014 { - compatible = "amlogic,meson-tl1-aobus-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio_ao: ao-bank@ff800014 { - reg = <0xff800014 0x8>, - <0xff800024 0x14>, - <0xff80001c 0x8>; - reg-names = "mux", "gpio", "drive-strength"; - gpio-controller; - #gpio-cells = <2>; - }; - - aoceca_mux:aoceca_mux { - mux { - groups = "cec_ao_a"; - function = "cec_ao"; - }; - }; - - aocecb_mux:aocecb_mux { - mux { - groups = "cec_ao_b"; - function = "cec_ao"; - }; - }; - }; - - pinctrl_periphs: pinctrl@ff6346c0 { - compatible = "amlogic,meson-tl1-periphs-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio: banks@ff6346c0 { - reg = <0xff6346c0 0x40>, - <0xff6344e8 0x18>, - <0xff634520 0x18>, - <0xff634440 0x4c>, - <0xff634740 0x1c>; - reg-names = "mux", - "pull", - "pull-enable", - "gpio", - "drive-strength"; - gpio-controller; - #gpio-cells = <2>; - }; - - - hdmirx_a_mux:hdmirx_a_mux { - mux { - groups = "hdmirx_a_hpd", "hdmirx_a_det", - "hdmirx_a_sda", "hdmirx_a_sck"; - function = "hdmirx_a"; - }; - }; - - hdmirx_b_mux:hdmirx_b_mux { - mux { - groups = "hdmirx_b_hpd", "hdmirx_b_det", - "hdmirx_b_sda", "hdmirx_b_sck"; - function = "hdmirx_b"; - }; - }; - - hdmirx_c_mux:hdmirx_c_mux { - mux { - groups = "hdmirx_c_hpd", "hdmirx_c_det", - "hdmirx_c_sda", "hdmirx_c_sck"; - function = "hdmirx_c"; - }; - }; - - }; - - dwc3: dwc3@ff500000 { - compatible = "synopsys, dwc3"; - status = "disabled"; - reg = <0xff500000 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - clocks = <&clkc CLKID_USB_GENERAL>; - clock-names = "dwc_general"; - }; - - usb2_phy_v2: usb2phy@ffe09000 { - compatible = "amlogic, amlogic-new-usb2-v2"; - status = "disabled"; - reg = <0xffe09000 0x80 - 0xffd01008 0x100 - 0xff636000 0x2000 - 0xff63a000 0x2000 - 0xff658000 0x2000>; - pll-setting-1 = <0x09400414>; - pll-setting-2 = <0x927E0000>; - pll-setting-3 = <0xac5f69e5>; - pll-setting-4 = <0xfe18>; - pll-setting-5 = <0x8000fff>; - pll-setting-6 = <0x78000>; - pll-setting-7 = <0xe0004>; - pll-setting-8 = <0xe000c>; - version = <1>; - }; - - usb3_phy_v2: usb3phy@ffe09080 { - compatible = "amlogic, amlogic-new-usb3-v2"; - status = "disabled"; - reg = <0xffe09080 0x20>; - phy-reg = <0xff646000>; - phy-reg-size = <0x2000>; - usb2-phy-reg = <0xffe09000>; - usb2-phy-reg-size = <0x80>; - interrupts = <0 16 4>; - }; - - dwc2_a: dwc2_a@ff400000 { - compatible = "amlogic, dwc2"; - status = "disabled"; - device_name = "dwc2_a"; - reg = <0xff400000 0x40000>; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "v2"; - phy-reg = <0xffe09000>; - phy-reg-size = <0xa0>; - /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ - /** 0x2: amlogic-v2 phy **/ - phy-interface = <0x2>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR>; - clock-names = "usb_general", - "usb1"; - }; - - wdt: watchdog@0xffd0f0d0 { - compatible = "amlogic, meson-wdt"; - status = "okay"; - default_timeout=<10>; - reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ - reset_watchdog_time=<2>; - shutdown_timeout=<10>; - firmware_timeout=<6>; - suspend_timeout=<6>; - reg = <0xffd0f0d0 0x10>; - clock-names = "xtal"; - clocks = <&xtal>; - }; - - jtag { - compatible = "amlogic, jtag"; - status = "okay"; - select = "disable"; /* disable/apao */ - pinctrl-names="jtag_apao_pins"; - pinctrl-0=<&jtag_apao_pins>; - }; - - saradc:saradc { - compatible = "amlogic,meson-g12a-saradc"; - status = "disabled"; - #io-channel-cells = <1>; - clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; - clock-names = "xtal", "saradc_clk"; - interrupts = ; - reg = <0xff809000 0x48>; - }; - - vddcpu0: pwmao_d-regulator { - compatible = "pwm-regulator"; - pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; - regulator-name = "vddcpu0"; - regulator-min-microvolt = <689000>; - regulator-max-microvolt = <1049000>; - regulator-always-on; - max-duty-cycle = <1500>; - /* Voltage Duty-Cycle */ - voltage-table = <1049000 0>, - <1039000 3>, - <1029000 6>, - <1019000 8>, - <1009000 11>, - <999000 14>, - <989000 17>, - <979000 20>, - <969000 23>, - <959000 26>, - <949000 29>, - <939000 31>, - <929000 34>, - <919000 37>, - <909000 40>, - <899000 43>, - <889000 45>, - <879000 48>, - <869000 51>, - <859000 54>, - <849000 56>, - <839000 59>, - <829000 62>, - <819000 65>, - <809000 68>, - <799000 70>, - <789000 73>, - <779000 76>, - <769000 79>, - <759000 81>, - <749000 84>, - <739000 87>, - <729000 89>, - <719000 92>, - <709000 95>, - <699000 98>, - <689000 100>; - status = "okay"; - }; - - aml_dma { - compatible = "amlogic,aml_txlx_dma"; - reg = <0xff63e000 0x48>; - interrupts = <0 180 1>; - - aml_aes { - compatible = "amlogic,aes_g12a_dma"; - dev_name = "aml_aes_dma"; - status = "okay"; - }; - - aml_sha { - compatible = "amlogic,sha_dma"; - dev_name = "aml_sha_dma"; - status = "okay"; - }; - }; - - rng { - compatible = "amlogic,meson-rng"; - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xff630218 0x4>; - quality = /bits/ 16 <1000>; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - hiubus: hiubus@ff63c000 { - compatible = "simple-bus"; - reg = <0xff63c000 0x2000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xff63c000 0x2000>; - - clkc: clock-controller@0 { - compatible = "amlogic,tl1-clkc"; - #clock-cells = <1>; - reg = <0x0 0x3fc>; - }; - };/* end of hiubus*/ - - audiobus: audiobus@0xff600000 { - compatible = "amlogic, audio-controller", "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xff600000 0x10000>; - ranges = <0x0 0xff600000 0x10000>; - - clkaudio:audio_clocks { - compatible = "amlogic, tl1-audio-clocks"; - #clock-cells = <1>; - reg = <0x0 0xb0>; - }; - - ddr_manager { - compatible = "amlogic, tl1-audio-ddr-manager"; - interrupts = < - GIC_SPI 148 IRQ_TYPE_EDGE_RISING - GIC_SPI 149 IRQ_TYPE_EDGE_RISING - GIC_SPI 150 IRQ_TYPE_EDGE_RISING - GIC_SPI 48 IRQ_TYPE_EDGE_RISING - GIC_SPI 152 IRQ_TYPE_EDGE_RISING - GIC_SPI 153 IRQ_TYPE_EDGE_RISING - GIC_SPI 154 IRQ_TYPE_EDGE_RISING - GIC_SPI 49 IRQ_TYPE_EDGE_RISING - >; - interrupt-names = - "toddr_a", "toddr_b", "toddr_c", - "toddr_d", - "frddr_a", "frddr_b", "frddr_c", - "frddr_d"; - }; - };/* end of audiobus*/ - - /* Sound iomap */ - aml_snd_iomap { - compatible = "amlogic, snd-iomap"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - pdm_bus { - reg = <0xFF601000 0x400>; - }; - audiobus_base { - reg = <0xFF600000 0x1000>; - }; - audiolocker_base { - reg = <0xFF601400 0x400>; - }; - eqdrc_base { - reg = <0xFF602000 0x2000>; - }; - reset_base { - reg = <0xFFD01000 0x1000>; - }; - vad_base { - reg = <0xFF601800 0x800>; - }; - }; - - cbus: cbus@ffd00000 { - compatible = "simple-bus"; - reg = <0xffd00000 0x27000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xffd00000 0x27000>; - - clk-measure@18004 { - compatible = "amlogic,tl1-measure"; - reg = <0x18004 0x4 0x1800c 0x4>; - }; - - i2c0: i2c@1f000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1f000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c1: i2c@1e000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1e000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c2: i2c@1d000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1d000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c3: i2c@1c000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x1c000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - gpio_intc: interrupt-controller@f080 { - compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-tl1-gpio-intc"; - reg = <0xf080 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = - <64 65 66 67 68 69 70 71>; - status = "okay"; - }; - - pwm_ab: pwm@1b000 { - compatible = "amlogic,tl1-ee-pwm"; - reg = <0x1b000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - /* default xtal 24m clkin0-clkin2 and - * clkin1-clkin3 should be set the same - */ - status = "disabled"; - }; - - pwm_cd: pwm@1a000 { - compatible = "amlogic,tl1-ee-pwm"; - reg = <0x1a000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_ef: pwm@19000 { - compatible = "amlogic,tl1-ee-pwm"; - reg = <0x19000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - spicc0: spi@13000 { - compatible = "amlogic,meson-tl1-spicc", - "amlogic,meson-g12a-spicc"; - reg = <0x13000 0x44>; - interrupts = ; - clocks = <&clkc CLKID_SPICC0>, - <&clkc CLKID_SPICC0_COMP>; - clock-names = "core", "comp"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spicc1: spi@15000 { - compatible = "amlogic,meson-tl1-spicc", - "amlogic,meson-g12a-spicc"; - reg = <0x15000 0x44>; - interrupts = ; - clocks = <&clkc CLKID_SPICC1>, - <&clkc CLKID_SPICC1_COMP>; - clock-names = "core", "comp"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - }; - - aobus: aobus@ff800000 { - compatible = "simple-bus"; - reg = <0xff800000 0xb000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xff800000 0xb000>; - - cpu_version { - reg = <0x220 0x4>; - }; - - aoclkc: clock-controller@0 { - compatible = "amlogic,tl1-aoclkc"; - #clock-cells = <1>; - reg = <0x0 0x1000>; - }; - - pwm_AO_ab: pwm@7000 { - compatible = "amlogic,tl1-ao-pwm"; - reg = <0x7000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_AO_cd: pwm@2000 { - compatible = "amlogic,tl1-ao-pwm"; - reg = <0x2000 0x20>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - uart_AO: serial@3000 { - compatible = "amlogic, meson-uart"; - reg = <0x3000 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <2>; - fifosize = < 64 >; - //pinctrl-names = "default"; - //pinctrl-0 = <&ao_a_uart_pins>; - /* 0 not support; 1 support */ - support-sysrq = <0>; - }; - - uart_AO_B: serial@4000 { - compatible = "amlogic, meson-uart"; - reg = <0x4000 0x18>; - interrupts = <0 197 1>; - status = "disabled"; - clocks = <&xtal>; - clock-names = "clk_uart"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_b_uart_pins1>; - }; - - remote: rc@8040 { - compatible = "amlogic, aml_remote"; - reg = <0x8040 0x44>, - <0x8000 0x20>; - status = "okay"; - protocol = ; - interrupts = ; - pinctrl-names = "default"; - pinctrl-0 = <&remote_pins>; - map = <&custom_maps>; - max_frame_time = <200>; - }; - - irblaster: meson-irblaster@14c { - compatible = "amlogic, meson_irblaster"; - reg = <0x14c 0x10>, - <0x40 0x4>; - #irblaster-cells = <2>; - interrupts = ; - status = "disabled"; - }; - - i2c_AO: i2c@5000 { - compatible = "amlogic,meson-i2c"; - status = "disabled"; - reg = <0x05000 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - clock-frequency = <100000>; - }; - - i2c_AO_slave:i2c_slave@6000 { - compatible = "amlogic, meson-i2c-slave"; - status = "disabled"; - reg = <0x6000 0x20>; - interrupts = ; - pinctrl-names="default"; - pinctrl-0=<&i2c_ao_slave_pins>; - }; - };/* end of aobus */ - - ion_dev { - compatible = "amlogic, ion_dev"; - status = "okay"; - memory-region = <&ion_cma_reserved>; - };/* end of ion_dev*/ - }; /* end of soc*/ - - custom_maps: custom_maps { - mapnum = <3>; - map0 = <&map_0>; - map1 = <&map_1>; - map2 = <&map_2>; - map_0: map_0{ - mapname = "amlogic-remote-1"; - customcode = <0xfb04>; - release_delay = <80>; - size = <44>; /*keymap size*/ - keymap = ; - }; - - map_1: map_1{ - mapname = "amlogic-remote-2"; - customcode = <0xfe01>; - release_delay = <80>; - size = <53>; - keymap = ; - }; - - map_2: map_2{ - mapname = "amlogic-remote-3"; - customcode = <0xbd02>; - release_delay = <80>; - size = <17>; - keymap = ; - }; - }; - - uart_A: serial@ffd24000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd24000 0x18>; - interrupts = <0 26 1>; - status = "disabled"; - clocks = <&xtal - &clkc CLKID_UART0>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 128 >; - pinctrl-names = "default"; - pinctrl-0 = <&a_uart_pins>; - }; - - uart_B: serial@ffd23000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd23000 0x18>; - interrupts = <0 75 1>; - status = "disabled"; - clocks = <&xtal - &clkc CLKID_UART1>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&b_uart_pins>; - }; - - uart_C: serial@ffd22000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd22000 0x18>; - interrupts = <0 93 1>; - status = "disabled"; - clocks = <&xtal - &clkc CLKID_UART1>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&c_uart_pins>; - }; - - sd_emmc_c: emmc@ffe07000 { - status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; - reg = <0xffe07000 0x800>; - interrupts = <0 191 1>; - pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; - pinctrl-0 = <&emmc_clk_cmd_pins>; - pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - /* mmc-ddr-1_8v; */ - /* mmc-hs200-1_8v; */ - - max-frequency = <200000000>; - non-removable; - disable-wp; - emmc { - pinname = "emmc"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - /*caps defined in dts*/ - tx_delay = <0>; - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; - card_type = <1>; - /* 1:mmc card(include eMMC), - * 2:sd card(include tSD) - */ - }; - }; - - sd_emmc_b: sd@ffe05000 { - status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; - reg = <0xffe05000 0x800>; - interrupts = <0 190 1>; - - pinctrl-names = "sd_all_pins", - "sd_clk_cmd_pins", - "sd_1bit_pins", - "sd_clk_cmd_uart_pins", - "sd_1bit_uart_pins", - "sd_to_ao_uart_pins", - "ao_to_sd_uart_pins", - "sd_to_ao_jtag_pins", - "ao_to_sd_jtag_pins"; - pinctrl-0 = <&sd_all_pins>; - pinctrl-1 = <&sd_clk_cmd_pins>; - pinctrl-2 = <&sd_1bit_pins>; - pinctrl-3 = <&sd_to_ao_uart_clr_pins - &sd_clk_cmd_pins &ao_to_sd_uart_pins>; - pinctrl-4 = <&sd_to_ao_uart_clr_pins - &sd_1bit_pins &ao_to_sd_uart_pins>; - pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - disable-wp; - sd { - pinname = "sd"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; - jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; - gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; - card_type = <5>; - /* 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card - */ - }; - }; - - spifc: spifc@ffd14000 { - compatible = "amlogic,aml-spi-nor"; - status = "disabled"; - - reg = <0xffd14000 0x80>; - pinctrl-names = "default"; - pinctrl-0 = <&spifc_all_pins>; - clock-names = "core"; - clocks = <&clkc CLKID_CLK81>; - - spi-nor@0 { - compatible = "jedec,spi-nor"; - spifc-frequency = <40000000>; - read-capability = <4>;/* dual read 1_1_2 */ - spifc-io-width = <4>; - }; - }; - - slc_nand: nand-controller@0xFFE07800 { - compatible = "amlogic, aml_mtd_nand"; - status = "disabled"; - reg = <0xFFE07800 0x200>; - interrupts = <0 34 1>; - - pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; - pinctrl-0 = <&all_nand_pins>; - pinctrl-1 = <&all_nand_pins>; - pinctrl-2 = <&nand_cs_pins>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>; - clock-names = "core", "clkin"; - - device_id = <0>; - /*fip/tpl configurations, must be same - *with uboot if bl_mode was set as 1 - *bl_mode: 0 compact mode;1 descrete mode - *if bl_mode was set as 1,fip configuration will work - */ - bl_mode = <1>; - /*copy count of fip*/ - fip_copies = <4>; - /*size of each fip copy*/ - fip_size = <0x200000>; - nand_clk_ctrl = <0xFFE07000>; - /*partions defined in dts*/ - }; - - mesonstream { - compatible = "amlogic, codec, streambuf"; - status = "okay"; - clocks = <&clkc CLKID_U_PARSER - &clkc CLKID_DEMUX - &clkc CLKID_AHB_ARB0 - &clkc CLKID_DOS - &clkc CLKID_VDEC_MUX - &clkc CLKID_HCODEC_MUX - &clkc CLKID_HEVC_MUX - &clkc CLKID_HEVCF_MUX>; - clock-names = "parser_top", - "demux", - "ahbarb0", - "vdec", - "clk_vdec_mux", - "clk_hcodec_mux", - "clk_hevc_mux", - "clk_hevcb_mux"; - }; - - vcodec-dec { - compatible = "amlogic, vcodec-dec"; - status = "okay"; - }; - - vdec { - compatible = "amlogic, vdec"; - status = "okay"; - interrupts = <0 3 1 - 0 23 1 - 0 32 1 - 0 43 1 - 0 44 1 - 0 45 1>; - interrupt-names = "vsync", - "demux", - "parser", - "mailbox_0", - "mailbox_1", - "mailbox_2"; - }; - - canvas: canvas { - compatible = "amlogic, meson, canvas"; - status = "okay"; - reg = <0xff638000 0x2000>; - }; - - codec_io: codec_io { - compatible = "amlogic, codec_io"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base{ - reg = <0xffd00000 0x100000>; - }; - io_dos_base{ - reg = <0xff620000 0x10000>; - }; - io_hiubus_base{ - reg = <0xff63c000 0x2000>; - }; - io_aobus_base{ - reg = <0xff800000 0x10000>; - }; - io_vcbus_base{ - reg = <0xff900000 0x40000>; - }; - io_dmc_base{ - reg = <0xff638000 0x2000>; - }; - io_efuse_base{ - reg = <0xff630000 0x2000>; - }; - }; - - rdma { - compatible = "amlogic, meson-tl1, rdma"; - status = "okay"; - interrupts = <0 89 1>; - interrupt-names = "rdma"; - }; - - meson_fb: fb { - compatible = "amlogic, meson-tl1"; - memory-region = <&logo_reserved>; - status = "disabled"; - interrupts = <0 3 1 - 0 56 1 - 0 89 1>; - interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; - /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ - display_mode_default = "1080p60hz"; - scale_mode = <1>; - /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ - display_size_default = <1920 1080 1920 2160 32>; - /*1920*1080*4*3 = 0x17BB000*/ - clocks = <&clkc CLKID_VPU_CLKC_MUX>; - clock-names = "vpu_clkc"; - }; - - ge2d { - compatible = "amlogic, ge2d-g12a"; - status = "okay"; - interrupts = <0 146 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xff940000 0x10000>; - }; - - meson-amvideom { - compatible = "amlogic, amvideom"; - status = "okay"; - interrupts = <0 3 1>; - interrupt-names = "vsync"; - }; - - ionvideo { - compatible = "amlogic, ionvideo"; - status = "okay"; - }; - - amlvideo { - compatible = "amlogic, amlvideo"; - status = "okay"; - }; - - vdac { - compatible = "amlogic, vdac-tl1"; - status = "okay"; - }; - - ddr_bandwidth { - compatible = "amlogic, ddr-bandwidth"; - status = "okay"; - reg = <0xff638000 0x100 - 0xff638c00 0x100>; - interrupts = <0 52 1>; - interrupt-names = "ddr_bandwidth"; - }; - - dmc_monitor { - compatible = "amlogic, dmc_monitor"; - status = "okay"; - reg_base = <0xff638800>; - interrupts = ; - }; - - efuse: efuse{ - compatible = "amlogic, efuse"; - read_cmd = <0x82000030>; - write_cmd = <0x82000031>; - get_max_cmd = <0x82000033>; - key = <&efusekey>; - clocks = <&clkc CLKID_EFUSE>; - clock-names = "efuse_clk"; - status = "disabled"; - }; - - efusekey:efusekey{ - keynum = <4>; - key0 = <&key_0>; - key1 = <&key_1>; - key2 = <&key_2>; - key3 = <&key_3>; - key_0:key_0{ - keyname = "mac"; - offset = <0>; - size = <6>; - }; - key_1:key_1{ - keyname = "mac_bt"; - offset = <6>; - size = <6>; - }; - key_2:key_2{ - keyname = "mac_wifi"; - offset = <12>; - size = <6>; - }; - key_3:key_3{ - keyname = "usid"; - offset = <18>; - size = <16>; - }; - }; -}; /* end of / */ - -&pinctrl_aobus { - sd_to_ao_uart_clr_pins: sd_to_ao_uart_clr_pins { - mux { - groups = "GPIOAO_0", - "GPIOAO_1", - "GPIOAO_2", - "GPIOAO_3", - "GPIOAO_4", - "GPIOAO_5", - "GPIOAO_6", - "GPIOAO_7", - "GPIOAO_8", - "GPIOAO_9", - "GPIOAO_10", - "GPIOAO_11", - "GPIOE_0", - "GPIOE_1", - "GPIOE_2", - "GPIO_TEST_N"; - function = "gpio_aobus"; - }; - }; - - sd_to_ao_uart_pins: sd_to_ao_uart_pins { - mux { - groups = "uart_ao_a_tx", - "uart_ao_a_rx", - "uart_ao_a_cts", - "uart_ao_a_rts"; - function = "uart_ao_a"; - bias-pull-up; - input-enable; - }; - }; - - remote_pins:remote_pin { - mux { - groups = "remote_input_ao"; - function = "remote_input_ao"; - }; - }; - - pwm_ao_a_pins: pwm_ao_a { - mux { - groups = "pwm_ao_a"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_a_hiz_pins: pwm_ao_a_hiz { - mux { - groups = "pwm_ao_a_hiz"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_b_pins: pwm_ao_b { - mux { - groups = "pwm_ao_b"; - function = "pwm_ao_b"; - }; - }; - - pwm_ao_c_pins1: pwm_ao_c_pins1 { - mux { - groups = "pwm_ao_c_4"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_c_pins2: pwm_ao_c_pins2 { - mux { - groups = "pwm_ao_c_6"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_c_hiz_pins1: pwm_ao_c_hiz1 { - mux { - groups = "pwm_ao_c_hiz_4"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_c_hiz_pins2: pwm_ao_c_hiz2 { - mux { - groups = "pwm_ao_c_hiz_7"; - function = "pwm_ao_c"; - }; - }; - - pwm_ao_d_pins1: pwm_ao_d_pins1 { - mux { - groups = "pwm_ao_d_5"; - function = "pwm_ao_d"; - }; - }; - - pwm_ao_d_pins2: pwm_ao_d_pins2 { - mux { - groups = "pwm_ao_d_10"; - function = "pwm_ao_d"; - }; - }; - - pwm_ao_d_pins3: pwm_ao_d_pins3 { - mux { - groups = "pwm_ao_d_e"; - function = "pwm_ao_d"; - }; - }; - - pwm_a_e2: pwm_a_e2 { - mux { - groups = "pwm_a_e2"; - function = "pwm_a_e2"; - }; - }; - - i2c_ao_2_pins:i2c_ao_2 { - mux { - groups = "i2c_ao_sck_2", - "i2c_ao_sda_3"; - function = "i2c_ao"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c_ao_e_pins:i2c_ao_e { - mux { - groups = "i2c_ao_sck_e", - "i2c_ao_sda_e"; - function = "i2c_ao"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c_ao_slave_pins:i2c_ao_slave { - mux { - groups = "i2c_ao_slave_sck", - "i2c_ao_slave_sda"; - function = "i2c_ao_slave"; - }; - }; - - ao_uart_pins:ao_uart { - mux { - groups = "uart_ao_a_rx", - "uart_ao_a_tx"; - function = "uart_ao_a"; - }; - }; - - ao_b_uart_pins1:ao_b_uart1 { - mux { - groups = "uart_ao_b_tx_2", - "uart_ao_b_rx_3"; - function = "uart_ao_b"; - }; - }; - - ao_b_uart_pins2:ao_b_uart2 { - mux { - groups = "uart_ao_b_tx_8", - "uart_ao_b_rx_9"; - function = "uart_ao_b"; - }; - }; - - irblaster_pins:irblaster_pin { - mux { - groups = "remote_out_ao"; - function = "remote_out_ao"; - }; - }; - - irblaster_pins1:irblaster_pin1 { - mux { - groups = "remote_out_ao9"; - function = "remote_out_ao"; - }; - }; - - jtag_apao_pins:jtag_apao_pin { - mux { - groups = "jtag_a_tdi", - "jtag_a_tdo", - "jtag_a_clk", - "jtag_a_tms"; - function = "jtag_a"; - }; - }; -}; - -&pinctrl_periphs { - /* sdemmc portC */ - emmc_clk_cmd_pins: emmc_clk_cmd_pins { - mux { - groups = "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - emmc_conf_pull_up: emmc_conf_pull_up { - mux { - groups = "emmc_nand_d7", - "emmc_nand_d6", - "emmc_nand_d5", - "emmc_nand_d4", - "emmc_nand_d3", - "emmc_nand_d2", - "emmc_nand_d1", - "emmc_nand_d0", - "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - emmc_conf_pull_done: emmc_conf_pull_done { - mux { - groups = "emmc_nand_ds"; - function = "emmc"; - input-enable; - bias-pull-down; - drive-strength = <3>; - }; - }; - - /* sdemmc portB */ - sd_clk_cmd_pins: sd_clk_cmd_pins { - mux { - groups = "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - sd_all_pins: sd_all_pins { - mux { - groups = "sdcard_d0", - "sdcard_d1", - "sdcard_d2", - "sdcard_d3", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - sd_1bit_pins: sd_1bit_pins { - mux { - groups = "sdcard_d0", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - ao_to_sd_uart_pins: ao_to_sd_uart_pins { - mux { - groups = "uart_ao_a_rx_c", - "uart_ao_a_tx_c", - "uart_ao_a_rx_w3", - "uart_ao_a_tx_w2", - "uart_ao_a_rx_w7", - "uart_ao_a_tx_w6", - "uart_ao_a_rx_w11", - "uart_ao_a_tx_w10"; - function = "uart_ao_a_ee"; - bias-pull-up; - input-enable; - }; - }; - - all_nand_pins: all_nand_pins { - mux { - groups = "emmc_nand_d0", - "emmc_nand_d1", - "emmc_nand_d2", - "emmc_nand_d3", - "emmc_nand_d4", - "emmc_nand_d5", - "emmc_nand_d6", - "emmc_nand_d7", - "nand_ce0", - "nand_ale", - "nand_cle", - "nand_wen_clk", - "nand_ren_wr"; - function = "nand"; - input-enable; - drive-strength = <3>; - }; - }; - - nand_cs_pins:nand_cs { - mux { - groups = "nand_ce0"; - function = "nand"; - drive-strength = <3>; - }; - }; - - /* sdemmc portA */ - sdio_clk_cmd_pins: sdio_clk_cmd_pins { - mux { - groups = "sdio_clk", - "sdio_cmd"; - function = "sdio"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - sdio_all_pins: sdio_all_pins { - mux { - groups = "sdio_d0", - "sdio_d1", - "sdio_d2", - "sdio_d3", - "sdio_clk", - "sdio_cmd"; - function = "sdio"; - input-enable; - bias-pull-up; - drive-strength = <3>; - }; - }; - - spifc_cs_pin:spifc_cs_pin { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_pulldown: spifc_pulldown { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - bias-pull-down; - }; - }; - - spifc_pullup: spifc_pullup { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_all_pins: spifc_all_pins { - mux { - groups = "nor_d", - "nor_q", - "nor_c", - "nor_hold", - "nor_wp"; - function = "nor"; - input-enable; - bias-pull-down; - }; - }; - - pwm_a_pins: pwm_a { - mux { - groups = "pwm_a"; - function = "pwm_a"; - }; - }; - - pwm_b_pins1: pwm_b_pins1 { - mux { - groups = "pwm_b_c"; - function = "pwm_b"; - }; - }; - - pwm_b_pins2: pwm_b_pins2 { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - - pwm_c_pins1: pwm_c_pins1 { - mux { - groups = "pwm_c_dv"; - function = "pwm_c"; - }; - }; - - pwm_c_pins2: pwm_c_pins2 { - mux { - groups = "pwm_c_h"; - function = "pwm_c"; - }; - }; - - pwm_c_pins3: pwm_c_pins3 { - mux { - groups = "pwm_c_z"; - function = "pwm_c"; - }; - }; - - pwm_d_pins1: pwm_d_pins1 { - mux { - groups = "pwm_d_dv"; - function = "pwm_d"; - }; - }; - - pwm_d_pins2: pwm_d_pins2 { - mux { - groups = "pwm_d_z"; - function = "pwm_d"; - }; - }; - - pwm_e_pins1: pwm_e1 { - mux { - groups = "pwm_e_dv"; - function = "pwm_e"; - }; - }; - - pwm_e_pins2: pwm_e2 { - mux { - groups = "pwm_e_z"; - function = "pwm_e"; - }; - }; - - pwm_f_pins1: pwm_f_pins1 { - mux { - groups = "pwm_f_dv"; - function = "pwm_f"; - }; - }; - - pwm_f_pins2: pwm_f_pins2 { - mux { - groups = "pwm_f_z"; - function = "pwm_f"; - }; - }; - - i2c0_c_pins:i2c0_c { - mux { - groups = "i2c0_sda_c", - "i2c0_sck_c"; - function = "i2c0"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c0_dv_pins:i2c0_dv { - mux { - groups = "i2c0_sda_dv", - "i2c0_sck_dv"; - function = "i2c0"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c1_z_pins:i2c1_z { - mux { - groups = "i2c1_sda_z", - "i2c1_sck_z"; - function = "i2c1"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c1_h_pins:i2c1_h { - mux { - groups = "i2c1_sda_h", - "i2c1_sck_h"; - function = "i2c1"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c2_h_pins:i2c2_h { - mux { - groups = "i2c2_sda_h", - "i2c2_sck_h"; - function = "i2c2"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c2_z_pins:i2c2_z { - mux { - groups = "i2c2_sda_z", - "i2c2_sck_z"; - function = "i2c2"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c3_h1_pins:i2c3_h1 { - mux { - groups = "i2c3_sda_h1", - "i2c3_sck_h0"; - function = "i2c3"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c3_h20_pins:i2c3_h3 { - mux { - groups = "i2c3_sda_h20", - "i2c3_sck_h19"; - function = "i2c3"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c3_dv_pins:i2c3_dv { - mux { - groups = "i2c3_sda_dv", - "i2c3_sck_dv"; - function = "i2c3"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - i2c3_c_pins:i2c3_c { - mux { - groups = "i2c3_sda_c", - "i2c3_sck_c"; - function = "i2c3"; - bias-pull-up; - drive-strength = <3>; - }; - }; - - spicc0_pins_h: spicc0_pins_h { - mux { - groups = "spi0_mosi_h", - "spi0_miso_h", - "spi0_clk_h"; - function = "spi0"; - drive-strength = <1>; - }; - }; - - spicc1_pins_dv: spicc1_pins_dv { - mux { - groups = "spi1_mosi_dv", - "spi1_miso_dv", - "spi1_clk_dv"; - function = "spi1"; - drive-strength = <1>; - }; - }; - - internal_eth_pins: internal_eth_pins { - mux { - groups = "eth_link_led", - "eth_act_led"; - function = "eth"; - }; - }; - - internal_gpio_pins: internal_gpio_pins { - mux { - groups = "GPIOZ_14", - "GPIOZ_15"; - function = "gpio_periphs"; - bias-disable; - input-enable; - }; - }; - - external_eth_pins: external_eth_pins { - mux { - groups = "eth_mdio", - "eth_mdc", - "eth_rgmii_rx_clk", - "eth_rx_dv", - "eth_rxd0", - "eth_rxd1", - "eth_rxd2_rgmii", - "eth_rxd3_rgmii", - "eth_rgmii_tx_clk", - "eth_txen", - "eth_txd0", - "eth_txd1", - "eth_txd2_rgmii", - "eth_txd3_rgmii"; - function = "eth"; - drive-strength = <3>; - }; - }; - - a_uart_pins:a_uart { - mux { - groups = "uart_a_tx", - "uart_a_rx", - "uart_a_cts", - "uart_a_rts"; - function = "uart_a"; - }; - }; - - b_uart_pins:b_uart { - mux { - groups = "uart_b_tx", - "uart_b_rx"; - function = "uart_b"; - }; - }; - - c_uart_pins:c_uart { - mux { - groups = "uart_c_tx", - "uart_c_rx"; - function = "uart_c"; - }; - }; - - lcd_vbyone_pins: lcd_vbyone_pin { - mux { - groups = "vx1_lockn","vx1_htpdn"; - function = "vx1"; - }; - }; - lcd_vbyone_off_pins: lcd_vbyone_off_pin { - mux { - groups = "GPIOH_15","GPIOH_16"; - function = "gpio_periphs"; - input-enable; - }; - }; - - lcd_tcon_pins: lcd_tcon_pin { - mux { - groups = "tcon_0","tcon_1","tcon_2","tcon_3", - "tcon_4","tcon_5","tcon_6","tcon_7", - "tcon_8","tcon_9","tcon_10","tcon_11", - "tcon_12","tcon_13","tcon_14","tcon_15", - "tcon_lock"; - function = "tcon"; - }; - }; - lcd_tcon_off_pins: lcd_tcon_off_pin { - mux { - groups = "GPIOH_0","GPIOH_1","GPIOH_2","GPIOH_3", - "GPIOH_4","GPIOH_5","GPIOH_6","GPIOH_7", - "GPIOH_8","GPIOH_9","GPIOH_10","GPIOH_11", - "GPIOH_12","GPIOH_13","GPIOH_14","GPIOH_15", - "GPIOH_16"; - function = "gpio_periphs"; - input-enable; - }; - }; -}; diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 3312fafdb537..9fc0d76c0a8d 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -242,12 +242,12 @@ #clock-cells = <0>; }; - meson_suspend: pm { + aml_pm { compatible = "amlogic, pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; cpuinfo { diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 061ed8102c58..3c862a26570d 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -159,13 +159,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; - device_name = "aml_pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index ff04a7444754..c0359bacd525 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -147,12 +147,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; device_name = "aml_pm"; status = "okay"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 87763ac66ddd..ebd0f3f74299 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -183,12 +183,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 4223513c2c04..5c76da13a913 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -245,12 +245,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index e6a0ebcdbc03..cc0941f5b5c8 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -249,8 +249,8 @@ compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index a0b68a157774..8c1a63984a74 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -147,11 +147,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xc81000a8 0x0 0x4>, - <0x0 0xc810023c 0x0 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi index ab1a3e8b2e74..f5e6e9151ece 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -161,11 +161,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xc81000a8 0x0 0x4 - 0x0 0xc810023c 0x0 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index bd6a808a5200..c41cf0ff5ad8 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -302,11 +302,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xc81000a8 0x0 0x4>, - <0x0 0xc810023c 0x0 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 05adbf3dcd3a..23f3e1456fc2 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -183,12 +183,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 6c32bb7070b1..1985984093f5 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -231,12 +231,12 @@ #clock-cells = <0>; }; - meson_suspend: pm { + aml_pm { compatible = "amlogic, pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; cpuinfo { diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 13e13ef9996c..0e3f4eb7b886 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -159,13 +159,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; - device_name = "aml_pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { diff --git a/drivers/amlogic/pm/gx_pm.c b/drivers/amlogic/pm/gx_pm.c index 8228001d15b3..951a3dc4b7ed 100644 --- a/drivers/amlogic/pm/gx_pm.c +++ b/drivers/amlogic/pm/gx_pm.c @@ -218,8 +218,9 @@ static int __init meson_pm_probe(struct platform_device *pdev) { struct device_node *cpu_node; struct device_node *state_node; - int count = 0; + int count = 0, ret; u32 ver = psci_get_version(); + u32 paddr = 0; pr_info("enter meson_pm_probe!\n"); @@ -245,11 +246,26 @@ static int __init meson_pm_probe(struct platform_device *pdev) suspend_set_ops(&meson_gx_ops); } - debug_reg = of_iomap(pdev->dev.of_node, 0); - exit_reg = of_iomap(pdev->dev.of_node, 1); + ret = of_property_read_u32(pdev->dev.of_node, + "debug_reg", &paddr); + if (!ret) { + pr_debug("debug_reg: 0x%x\n", paddr); + debug_reg = ioremap(paddr, 0x4); + if (IS_ERR_OR_NULL(debug_reg)) + goto uniomap; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "exit_reg", &paddr); + if (!ret) { + pr_debug("exit_reg: 0x%x\n", paddr); + exit_reg = ioremap(paddr, 0x4); + if (IS_ERR_OR_NULL(exit_reg)) + goto uniomap; + } + device_create_file(&pdev->dev, &dev_attr_suspend_reason); device_create_file(&pdev->dev, &dev_attr_time_out); - device_rename(&pdev->dev, "aml_pm"); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND if (lgcy_early_suspend_init()) return -1; @@ -258,9 +274,13 @@ static int __init meson_pm_probe(struct platform_device *pdev) pr_info("meson_pm_probe done\n"); return 0; +uniomap: + if (debug_reg) + iounmap(debug_reg); + return -ENXIO; } -static int __exit meson_pm_remove(struct platform_device *pdev) +static int meson_pm_remove(struct platform_device *pdev) { return 0; } @@ -277,12 +297,13 @@ static struct platform_driver meson_pm_driver = { .owner = THIS_MODULE, .of_match_table = amlogic_pm_dt_match, }, - .remove = __exit_p(meson_pm_remove), + .probe = meson_pm_probe, + .remove = meson_pm_remove, }; static int __init meson_pm_init(void) { - return platform_driver_probe(&meson_pm_driver, meson_pm_probe); + return platform_driver_register(&meson_pm_driver); } late_initcall(meson_pm_init); From 0f40816dece102445af68042989209a346ed2a5e Mon Sep 17 00:00:00 2001 From: Qianggui Song Date: Fri, 18 Jan 2019 11:26:47 +0800 Subject: [PATCH 0558/1060] ir: add ir learning function [1/1] PD#SWPL-4130 Problem: No ir learning function in current source code Solution: Provide two ways to use ir learning function 1. sysfs /*start learning*/ echo 1 > /sys/class/remote/amremote/ir_learnning /*get data*/ cat /sys/class/remote/amremote/learned_pulse /*stop learning*/ echo 0 > /sys/class/remote/amremote/ir_learnning 2. ioctl /*start/stop learnning 1/0*/ REMOTE_IOC_SET_IR_LEARING /*get raw data*/ REMOTE_IOC_GET_RAW_DATA Verify: U200 and W400 Change-Id: Ibb03838402d9baa6e910b3162ffcc63b57048890 Signed-off-by: Qianggui Song Conflicts: drivers/amlogic/input/remote/remote_meson.h --- drivers/amlogic/input/remote/rc_common.h | 5 + drivers/amlogic/input/remote/remote_cdev.c | 88 ++++++++ drivers/amlogic/input/remote/remote_core.h | 19 +- drivers/amlogic/input/remote/remote_meson.c | 206 ++++++++++++++++++- drivers/amlogic/input/remote/remote_meson.h | 67 ++++-- drivers/amlogic/input/remote/remote_regmap.c | 12 +- drivers/amlogic/input/remote/sysfs.c | 189 ++++++++++++++++- 7 files changed, 556 insertions(+), 30 deletions(-) diff --git a/drivers/amlogic/input/remote/rc_common.h b/drivers/amlogic/input/remote/rc_common.h index 34203557c19b..fdc6b8f09d0a 100644 --- a/drivers/amlogic/input/remote/rc_common.h +++ b/drivers/amlogic/input/remote/rc_common.h @@ -86,5 +86,10 @@ struct ir_sw_decode_para { #define REMOTE_IOC_SET_KEY_MAPPING_TAB _IOW('I', 4, __u32) #define REMOTE_IOC_SET_SW_DECODE_PARA _IOW('I', 5, __u32) #define REMOTE_IOC_GET_DATA_VERSION _IOR('I', 121, __u32) +#define REMOTE_IOC_SET_IR_LEARNING _IOW('I', 6, __u32) +#define REMOTE_IOC_GET_IR_LEARNING _IOR('I', 7, __u32) +#define REMOTE_IOC_GET_RAW_DATA _IOR('I', 8, __u32) +#define REMOTE_IOC_GET_SUM_CNT0 _IOR('I', 9, __u32) +#define REMOTE_IOC_GET_SUM_CNT1 _IOR('I', 10, __u32) #endif diff --git a/drivers/amlogic/input/remote/remote_cdev.c b/drivers/amlogic/input/remote/remote_cdev.c index 60d1be2a74c1..ea996e3712f0 100644 --- a/drivers/amlogic/input/remote/remote_cdev.c +++ b/drivers/amlogic/input/remote/remote_cdev.c @@ -48,6 +48,7 @@ static long remote_ioctl(struct file *file, unsigned int cmd, void __user *parg = (void __user *)arg; unsigned long flags; u32 value; + u8 val; int retval = 0; if (!parg) { @@ -126,6 +127,93 @@ static long remote_ioctl(struct file *file, unsigned int cmd, } chip->r_dev->max_frame_time = sw_data.max_frame_time; break; + case REMOTE_IOC_GET_IR_LEARNING: + if (copy_to_user(parg, &chip->r_dev->ir_learning_on, + sizeof(u8))) { + retval = -EFAULT; + goto err; + } + break; + + case REMOTE_IOC_SET_IR_LEARNING: + /*reset demudolation and carrier detect*/ + if (chip->r_dev->demod_enable) + demod_reset(chip); + + if (copy_from_user(&val, parg, sizeof(u8))) { + retval = -EFAULT; + goto err; + } + + chip->r_dev->ir_learning_on = !!val; + if (!!val) { + if (remote_pulses_malloc(chip) < 0) { + retval = -ENOMEM; + goto err; + } + chip->set_register_config(chip, REMOTE_TYPE_RAW_NEC); + /*backup protocol*/ + chip->r_dev->protocol = chip->protocol; + chip->protocol = REMOTE_TYPE_RAW_NEC; + } else { + chip->protocol = chip->r_dev->protocol; + chip->set_register_config(chip, chip->protocol); + remote_pulses_free(chip); + chip->r_dev->ir_learning_done = false; + } + break; + + case REMOTE_IOC_GET_RAW_DATA: + if (copy_to_user(parg, chip->r_dev->pulses, + sizeof(struct pulse_group) + + chip->r_dev->max_learned_pulse * + sizeof(unsigned int))) { + retval = -EFAULT; + goto err; + } + /*clear to prepear next frame*/ + memset(chip->r_dev->pulses, 0, sizeof(struct pulse_group) + + chip->r_dev->max_learned_pulse * + sizeof(unsigned int)); + + if (chip->r_dev->demod_enable) + demod_reset(chip); + + /*finish reading data ,enable state machine */ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), + BIT(15)); + + chip->r_dev->ir_learning_done = false; + + break; + + case REMOTE_IOC_GET_SUM_CNT0: + if (chip->r_dev->demod_enable) { + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT0, + &value); + if (copy_to_user(parg, &value, sizeof(u32))) { + retval = -EFAULT; + goto err; + } + } else { + retval = -EFAULT; + goto err; + } + break; + + case REMOTE_IOC_GET_SUM_CNT1: + if (chip->r_dev->demod_enable) { + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT1, + &value); + if (copy_to_user(parg, &value, sizeof(u32))) { + retval = -EFAULT; + goto err; + } + } else { + retval = -EFAULT; + goto err; + } + break; default: retval = -ENOTTY; diff --git a/drivers/amlogic/input/remote/remote_core.h b/drivers/amlogic/input/remote/remote_core.h index 6b2d623991f3..b0f72517c271 100644 --- a/drivers/amlogic/input/remote/remote_core.h +++ b/drivers/amlogic/input/remote/remote_core.h @@ -58,7 +58,11 @@ enum raw_event_type { RAW_STOP_EVENT = (1 << 3), }; - +struct pulse_group { + int len; + /*bit 0-30 durations, bit31: level*/ + unsigned int pulse[0]; +}; struct remote_raw_handle; struct remote_dev { @@ -75,6 +79,19 @@ struct remote_dev { unsigned long delay_off; int led_blink; + /*for ir learnning feature*/ +#define MAX_LEARNED_PULSE 256 + /*ir learnning switch*/ + u8 ir_learning_on; + u8 ir_learning_done; + u8 demod_enable; + u8 use_fifo; + u8 auto_report; + int max_learned_pulse; + int protocol; + struct timer_list learning_done; + struct pulse_group *pulses; + struct timer_list timer_keyup; unsigned long keyup_jiffies; unsigned long keyup_delay; diff --git a/drivers/amlogic/input/remote/remote_meson.c b/drivers/amlogic/input/remote/remote_meson.c index cba24836aa19..c9b61cf5e89b 100644 --- a/drivers/amlogic/input/remote/remote_meson.c +++ b/drivers/amlogic/input/remote/remote_meson.c @@ -43,10 +43,51 @@ #include static void amlremote_tasklet(unsigned long data); - +static void learning_done_workqueue(struct work_struct *work); +static void get_fifo_data_work(struct work_struct *work); DECLARE_TASKLET_DISABLED(tasklet, amlremote_tasklet, 0); +static void learning_done_workqueue(struct work_struct *work) +{ + struct delayed_work *w = container_of(work, struct delayed_work, work); + struct remote_chip *chip = + container_of(w, struct remote_chip, ir_workqueue); + char *envp[2] = { "LEARN_DONE", NULL}; + + kobject_uevent_env(&chip->dev->kobj, KOBJ_CHANGE, envp); +} + +int remote_pulses_malloc(struct remote_chip *chip) +{ + struct remote_dev *r_dev = chip->r_dev; + int len = r_dev->max_learned_pulse; + int ret = 0; + + if (r_dev->pulses) { + dev_info(chip->dev, "ir learning pulse already exists\n"); + return -EEXIST; + } + + r_dev->pulses = kzalloc(sizeof(struct pulse_group) + + len * sizeof(unsigned int), GFP_KERNEL); + + if (!r_dev->pulses) { + dev_err(chip->dev, "ir learning pulse alloc err\n"); + ret = -ENOMEM; + } + + return ret; +} + +void remote_pulses_free(struct remote_chip *chip) +{ + struct remote_dev *r_dev = chip->r_dev; + + kfree(r_dev->pulses); + r_dev->pulses = NULL; +} + int remote_reg_read(struct remote_chip *chip, unsigned char id, unsigned int reg, unsigned int *val) { @@ -73,6 +114,19 @@ int remote_reg_write(struct remote_chip *chip, unsigned char id, return 0; } +int remote_reg_update_bits(struct remote_chip *chip, unsigned char id, + unsigned int reg, unsigned int mask, unsigned int val) +{ + int orig = 0; + + remote_reg_read(chip, id, reg, &orig); + orig &= ~mask; + orig |= val & mask; + remote_reg_write(chip, id, reg, orig); + + return 0; +} + int ir_scancode_sort(struct ir_map_tab *ir_map) { bool is_sorted; @@ -300,9 +354,64 @@ static void amlremote_tasklet(unsigned long data) } +static void get_fifo_data_work(struct work_struct *work) +{ + struct remote_chip *chip = + container_of(work, struct remote_chip, fifo_work); + struct remote_dev *r_dev = chip->r_dev; + int val = 0; + int is_fifo_pending = 0; + int is_fifo_timeout = 0; + int is_fifo_empty = 0; + u32 duration = 0; + + remote_reg_read(chip, MULTI_IR_ID, REG_FIFO, &val); + is_fifo_pending = (val >> 30) & 0x01; + is_fifo_timeout = (val >> 29) & 0x01; + is_fifo_empty = (val >> 27) & 0x01; + + /*disable interrupt*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, GENMASK(22, 23), 0); + + if (is_fifo_pending || is_fifo_timeout) { + /*clear state*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, + GENMASK(29, 30), GENMASK(29, 30)); + + for (; !is_fifo_empty; ) { + + remote_reg_read(chip, MULTI_IR_ID, REG_WITH, &val); + val = val & GENMASK(12, 0); + + duration = val; + r_dev->pulses->pulse[r_dev->pulses->len] = duration; + + if (r_dev->pulses->len % 2 == 1) + r_dev->pulses->pulse[r_dev->pulses->len] + |= BIT(31); + + r_dev->pulses->len++; + + remote_reg_read(chip, MULTI_IR_ID, REG_FIFO, &val); + is_fifo_empty = (val >> 27) & 0x01; + + } + } + + /*enable interrupt*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, GENMASK(22, 23), + GENMASK(22, 23)); + + if (r_dev->auto_report) + mod_timer(&r_dev->learning_done, + jiffies + msecs_to_jiffies(50)); +} + static irqreturn_t ir_interrupt(int irq, void *dev_id) { struct remote_chip *rc = (struct remote_chip *)dev_id; + struct remote_dev *r_dev = rc->r_dev; + struct pulse_group *pgs; int contr_status = 0; int val = 0; u32 duration; @@ -312,12 +421,40 @@ static irqreturn_t ir_interrupt(int irq, void *dev_id) remote_reg_read(rc, MULTI_IR_ID, REG_REG1, &val); val = (val & 0x1FFF0000) >> 16; - sprintf(buf, "d:%d\n", val); + sprintf(buf, "duration:%d\n", val); debug_log_printk(rc->r_dev, buf); /** *software decode multiple protocols by using Time Measurement of *multif-format IR controller */ + + if (r_dev->ir_learning_on && !r_dev->ir_learning_done) { + pgs = r_dev->pulses; + if (pgs->len >= r_dev->max_learned_pulse) { + remote_reg_update_bits(rc, MULTI_IR_ID, REG_REG1, + BIT(15), 0); + return IRQ_HANDLED; + } + if (!r_dev->use_fifo) { + if (r_dev->auto_report) + mod_timer(&r_dev->learning_done, + jiffies + msecs_to_jiffies(50)); + /*get pulse durations unit:10us*/ + pgs->pulse[pgs->len] = val & GENMASK(30, 0); + /*get pulse level*/ + remote_reg_read(rc, MULTI_IR_ID, REG_STATUS, &val); + val = !!((val >> 8) & 0x01); + pgs->pulse[pgs->len] &= ~BIT(31); + if (val) + pgs->pulse[pgs->len] |= BIT(31); + + r_dev->pulses->len++; + } else { + schedule_work(&rc->fifo_work); + } + return IRQ_HANDLED; + } + if (MULTI_IR_SOFTWARE_DECODE(rc->protocol)) { rc->ir_work = MULTI_IR_ID; duration = val*10*1000; @@ -508,6 +645,18 @@ static int ir_get_devtree_pdata(struct platform_device *pdev) } dev_info(chip->dev, "led_blink_frq = %ld\n", chip->r_dev->delay_on); + ret = of_property_read_bool(pdev->dev.of_node, "demod_enable"); + if (ret) + chip->r_dev->demod_enable = 1; + + ret = of_property_read_bool(pdev->dev.of_node, "use_fifo"); + if (ret) + chip->r_dev->use_fifo = 1; + + ret = of_property_read_bool(pdev->dev.of_node, "auto_report"); + if (ret) + chip->r_dev->auto_report = 1; + p = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(p)) { dev_err(chip->dev, "pinctrl error, %ld\n", PTR_ERR(p)); @@ -554,6 +703,47 @@ static int ir_get_devtree_pdata(struct platform_device *pdev) return 0; } +void demod_init(struct remote_chip *chip) +{ + int val; + unsigned int mask; + + mask = GENMASK(29, 16) | BIT(31); + val = BIT(31) | (0x1FF << 16); + + remote_reg_update_bits(chip, MULTI_IR_ID, REG_DEMOD_CNTL1, mask, val); +} + +void demod_reset(struct remote_chip *chip) +{ + unsigned int mask; + + mask = BIT(30); + remote_reg_update_bits(chip, MULTI_IR_ID, REG_DEMOD_CNTL0, mask, mask); +} + +static void ir_learning_done(unsigned long cookie) +{ + + struct remote_dev *dev = (struct remote_dev *)cookie; + struct remote_chip *chip = (struct remote_chip *) dev->platform_data; + unsigned long flags; + + if (dev->pulses->len < 3) { + dev->pulses->len = 0; + return; + } + + spin_lock_irqsave(&chip->slock, flags); + dev->ir_learning_done = true; + spin_unlock_irqrestore(&chip->slock, flags); + + /*data recive done*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), 0); + schedule_delayed_work(&chip->ir_workqueue, msecs_to_jiffies(100)); + +} + static int ir_hardware_init(struct platform_device *pdev) { int ret; @@ -646,6 +836,7 @@ static int remote_probe(struct platform_device *pdev) chip->r_dev->set_custom_code = set_custom_code; chip->r_dev->is_valid_custom = is_valid_custom; chip->r_dev->is_next_repeat = is_next_repeat; + chip->r_dev->max_learned_pulse = MAX_LEARNED_PULSE; chip->set_register_config = ir_register_default_config; platform_set_drvdata(pdev, chip); @@ -669,6 +860,11 @@ static int remote_probe(struct platform_device *pdev) led_trigger_register_simple("rc_feedback", &dev->led_feedback); + setup_timer(&dev->learning_done, ir_learning_done, (unsigned long)dev); + if (dev->demod_enable) + demod_init(chip); + INIT_DELAYED_WORK(&chip->ir_workqueue, learning_done_workqueue); + INIT_WORK(&chip->fifo_work, get_fifo_data_work); return 0; error_register_remote: @@ -748,6 +944,12 @@ static int remote_suspend(struct device *dev) { struct remote_chip *chip = dev_get_drvdata(dev); + if (chip->r_dev->ir_learning_on) { + cancel_work_sync(&chip->fifo_work); + del_timer_sync(&chip->r_dev->learning_done); + cancel_delayed_work_sync(&chip->ir_workqueue); + } + if (is_pm_freeze_mode()) return 0; diff --git a/drivers/amlogic/input/remote/remote_meson.h b/drivers/amlogic/input/remote/remote_meson.h index 35950a5fe118..79dcb5e1c50e 100644 --- a/drivers/amlogic/input/remote/remote_meson.h +++ b/drivers/amlogic/input/remote/remote_meson.h @@ -25,8 +25,13 @@ #define IR_DATA_IS_VALID(data) (data & 0x8) #define IR_CONTROLLER_BUSY(x) ((x >> 7) & 0x1) - #define CURSOR_MOVE_ACCELERATE {0, 2, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18} +/*bit 31: enable fifo mode + * bit 21-23: time out/level trigger interrupt + * bit 13-20: trigger interrupt when receive specified numbers of pulse + * bit 0-12: trigger interrupt when time out + */ +#define FIFO_REG_VAL ((1 << 31) | (7 << 21) | (80 << 13) | (5000 << 0)) enum IR_CONTR_NUMBER { MULTI_IR_ID = 0, @@ -104,6 +109,8 @@ struct remote_chip { struct remote_range reg_duration; char *dev_name; int protocol; + struct delayed_work ir_workqueue; + struct work_struct fifo_work; dev_t chr_devno; struct class *chr_class; @@ -167,27 +174,36 @@ enum { }; enum remote_reg { - REG_LDR_ACTIVE = 0x00 << 2, - REG_LDR_IDLE = 0x01 << 2, - REG_LDR_REPEAT = 0x02 << 2, - REG_BIT_0 = 0x03 << 2, - REG_REG0 = 0x04 << 2, - REG_FRAME = 0x05 << 2, - REG_STATUS = 0x06 << 2, - REG_REG1 = 0x07 << 2, - REG_REG2 = 0x08 << 2, - REG_DURATN2 = 0x09 << 2, - REG_DURATN3 = 0x0a << 2, - REG_FRAME1 = 0x0b << 2, - REG_STATUS1 = 0x0c << 2, - REG_STATUS2 = 0x0d << 2, - REG_REG3 = 0x0e << 2, - REG_FRAME_RSV0 = 0x0f << 2, - REG_FRAME_RSV1 = 0x10 << 2, - REG_FILTE = 0x11 << 2, - REG_IRQ_CTL = 0x12 << 2, - REG_WIDTH_NEW = 0x14 << 2, - REG_REPEAT_DET = 0x15 << 2 + REG_LDR_ACTIVE = 0x00 << 2, + REG_LDR_IDLE = 0x01 << 2, + REG_LDR_REPEAT = 0x02 << 2, + REG_BIT_0 = 0x03 << 2, + REG_REG0 = 0x04 << 2, + REG_FRAME = 0x05 << 2, + REG_STATUS = 0x06 << 2, + REG_REG1 = 0x07 << 2, + REG_REG2 = 0x08 << 2, + REG_DURATN2 = 0x09 << 2, + REG_DURATN3 = 0x0a << 2, + REG_FRAME1 = 0x0b << 2, + REG_STATUS1 = 0x0c << 2, + REG_STATUS2 = 0x0d << 2, + REG_REG3 = 0x0e << 2, + REG_FRAME_RSV0 = 0x0f << 2, + REG_FRAME_RSV1 = 0x10 << 2, + REG_IRQ_CTL = 0x12 << 2, + REG_FIFO = 0x13 << 2, + REG_WITH = 0x14 << 2, + REG_REPEAT_DET = 0x15 << 2, + REG_DEMOD_CNTL0 = 0x20 << 2, + REG_DEMOD_CNTL1 = 0x21 << 2, + REG_DEMOD_IIR_THD = 0x22 << 2, + REG_DEMOD_THD0 = 0x23 << 2, + REG_DEMOD_THD1 = 0x24 << 2, + REG_DEMOD_SUM_CNT0 = 0x25 << 2, + REG_DEMOD_SUM_CNT1 = 0x26 << 2, + REG_DEMOD_CNT0 = 0x27 << 2, + REG_DEMOD_CNT1 = 0x28 << 2 }; int ir_register_default_config(struct remote_chip *chip, int type); @@ -199,11 +215,18 @@ int remote_reg_read(struct remote_chip *chip, unsigned char id, unsigned int reg, unsigned int *val); int remote_reg_write(struct remote_chip *chip, unsigned char id, unsigned int reg, unsigned int val); +int remote_reg_update_bits(struct remote_chip *chip, unsigned char id, + unsigned int reg, unsigned int mask, unsigned int val); int ir_scancode_sort(struct ir_map_tab *ir_map); struct ir_map_tab_list *seek_map_tab(struct remote_chip *chip, int custom_code); +const struct aml_remote_reg_proto **ir_get_proto_reg(void); void ir_tab_free(struct ir_map_tab_list *ir_map_list); #if defined(CONFIG_IR_HK_LIRC_HELPER) extern void remote_wakeup_decode_type(int dec_type); #endif +int remote_pulses_malloc(struct remote_chip *chip); +void remote_pulses_free(struct remote_chip *chip); +void demod_reset(struct remote_chip *chip); +void demod_init(struct remote_chip *chip); #endif diff --git a/drivers/amlogic/input/remote/remote_regmap.c b/drivers/amlogic/input/remote/remote_regmap.c index 93c9697822b3..f1b506c626bf 100644 --- a/drivers/amlogic/input/remote/remote_regmap.c +++ b/drivers/amlogic/input/remote/remote_regmap.c @@ -88,7 +88,7 @@ static struct remote_reg_map regs_default_nec_sw[] = { { REG_LDR_IDLE, 0}, { REG_LDR_REPEAT, 0}, { REG_BIT_0, 0}, - { REG_REG0, ((3 << 28) | (0xFA0 << 12) | (9))}, + { REG_REG0, ((7 << 28) | (0xFA0 << 12) | (9))}, { REG_STATUS, 0}, { REG_REG1, 0x8574}, { REG_REG2, 0x02}, @@ -569,6 +569,11 @@ const struct aml_remote_reg_proto *remote_reg_proto[] = { NULL }; +const struct aml_remote_reg_proto **ir_get_proto_reg(void) +{ + return remote_reg_proto; +} + static int ir_contr_init(struct remote_chip *chip, int type, unsigned char id) { const struct aml_remote_reg_proto **reg_proto = remote_reg_proto; @@ -623,6 +628,11 @@ static int ir_contr_init(struct remote_chip *chip, int type, unsigned char id) chip->ir_contr[id].get_custom_code = (*reg_proto)->get_custom_code; chip->ir_contr[id].set_custom_code = (*reg_proto)->set_custom_code; + if (chip->r_dev->ir_learning_on && chip->r_dev->use_fifo) + remote_reg_write(chip, id, REG_FIFO, FIFO_REG_VAL); + else + remote_reg_write(chip, id, REG_FIFO, 0); + return 0; } diff --git a/drivers/amlogic/input/remote/sysfs.c b/drivers/amlogic/input/remote/sysfs.c index b7df3e5a276f..5bd084cd9a04 100644 --- a/drivers/amlogic/input/remote/sysfs.c +++ b/drivers/amlogic/input/remote/sysfs.c @@ -43,16 +43,29 @@ static ssize_t protocol_show(struct device *dev, struct device_attribute *attr, char *buf) { struct remote_chip *chip = dev_get_drvdata(dev); + const struct aml_remote_reg_proto **supported_proto = + ir_get_proto_reg(); + int len; if (ENABLE_LEGACY_IR(chip->protocol)) - return sprintf(buf, "protocol=%s&%s (0x%x)\n", + len = sprintf(buf, "current protocol = %s&%s (0x%x)\n", chip->ir_contr[LEGACY_IR_ID].proto_name, chip->ir_contr[MULTI_IR_ID].proto_name, chip->protocol); + else + len = sprintf(buf, "currnet protocol = %s (0x%x)\n", + chip->ir_contr[MULTI_IR_ID].proto_name, + chip->protocol); - return sprintf(buf, "protocol=%s (0x%x)\n", - chip->ir_contr[MULTI_IR_ID].proto_name, - chip->protocol); + len += sprintf(buf + len, "supported protocol:\n"); + + for ( ; (*supported_proto) != NULL ; ) { + len += sprintf(buf + len, "%s (0x%x)\n", + ((*supported_proto)->name), ((*supported_proto)->protocol)); + supported_proto++; + } + + return len; } static ssize_t protocol_store(struct device *dev, @@ -308,6 +321,169 @@ static ssize_t led_frq_store(struct device *dev, return count; } +static ssize_t ir_learning_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + return sprintf(buf, "%d\n", r_dev->ir_learning_on); +} + +static ssize_t ir_learning_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret = 0; + int val = 0; + + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + ret = kstrtoint(buf, 0, &val); + if (ret != 0) + return -EINVAL; + if (r_dev->ir_learning_on == val) + return count; + + disable_irq(chip->irqno); + mutex_lock(&chip->file_lock); + r_dev->ir_learning_on = !!val; + if (!!val) { + if (r_dev->demod_enable) + demod_reset(chip); + + if (remote_pulses_malloc(chip) < 0) { + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + return -ENOMEM; + } + chip->set_register_config(chip, REMOTE_TYPE_RAW_NEC); + r_dev->protocol = chip->protocol;/*backup protocol*/ + chip->protocol = REMOTE_TYPE_RAW_NEC; + } else { + chip->protocol = r_dev->protocol; + chip->set_register_config(chip, chip->protocol); + remote_pulses_free(chip); + chip->r_dev->ir_learning_done = false; + } + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + return count; +} + +static ssize_t learned_pulse_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int len = 0; + int i = 0; + + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + if (!r_dev->pulses) + return len; + + disable_irq(chip->irqno); + mutex_lock(&chip->file_lock); + for (i = 0; i < r_dev->pulses->len; i++) + len += sprintf(buf + len, "%lds", + r_dev->pulses->pulse[i] & GENMASK(30, 0)); + + len += sprintf(buf + len, "\n"); + + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), BIT(15)); + + r_dev->ir_learning_done = false; + + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + + return len; +} + +static ssize_t learned_pulse_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + if (!r_dev->pulses) + return count; + + disable_irq(chip->irqno); + mutex_lock(&chip->file_lock); + if (buf[0] == 'c') { + memset(r_dev->pulses, 0, sizeof(struct pulse_group) + + r_dev->max_learned_pulse * sizeof(u32)); + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), + BIT(15)); + + r_dev->ir_learning_done = false; + } + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + return count; +} + +static ssize_t sum_cnt0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int val = 0; + struct remote_chip *chip = dev_get_drvdata(dev); + + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT0, &val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t sum_cnt1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + int val = 0; + struct remote_chip *chip = dev_get_drvdata(dev); + + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT1, &val); + + return sprintf(buf, "%d\n", val); + +} + +static ssize_t use_fifo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct remote_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", chip->r_dev->use_fifo); +} + +static ssize_t use_fifo_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int val = 0; + int len = 0; + struct remote_chip *chip = dev_get_drvdata(dev); + + len = kstrtoint(buf, 0, &val); + + if (len != 0) { + dev_err(chip->dev, "input parameter error\n"); + return -EINVAL; + } + + chip->r_dev->use_fifo = val; + + return count; +} + +DEVICE_ATTR_RW(use_fifo); +DEVICE_ATTR_RO(sum_cnt0); +DEVICE_ATTR_RO(sum_cnt1); +DEVICE_ATTR_RW(learned_pulse); +DEVICE_ATTR_RW(ir_learning); DEVICE_ATTR_RW(led_frq); DEVICE_ATTR_RW(led_blink); DEVICE_ATTR_RW(repeat_enable); @@ -326,6 +502,11 @@ static struct attribute *remote_attrs[] = { &dev_attr_debug_log.attr, &dev_attr_led_blink.attr, &dev_attr_led_frq.attr, + &dev_attr_ir_learning.attr, + &dev_attr_learned_pulse.attr, + &dev_attr_sum_cnt0.attr, + &dev_attr_sum_cnt1.attr, + &dev_attr_use_fifo.attr, NULL, }; From 145da5c2c8cbe2025d6f77a43889df4c6bc7a429 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Mon, 1 Apr 2019 18:38:41 +0800 Subject: [PATCH 0559/1060] vbi: fix vbi teletext no vcnt [1/1] PD#TV-3444 Problem: vbi teletext no vcnt vbi dump failed adc dump failed Solution: set 0x126[26]=1 fix dump issue fix adcdump issue Verify: test on x301 Change-Id: I7111a86f0259d2e57f06f885a1c8058d9578dc88 Signed-off-by: Nian Jing Conflicts: drivers/amlogic/media/vin/tvin/tvafe/tvafe.h --- drivers/amlogic/media/vin/tvin/tvafe/tvafe.h | 2 +- .../amlogic/media/vin/tvin/tvafe/tvafe_cvd.c | 10 +---- .../amlogic/media/vin/tvin/tvafe/tvafe_cvd.h | 2 +- .../media/vin/tvin/tvafe/tvafe_debug.c | 39 +++++++++++++++---- .../amlogic/media/vin/tvin/tvafe/tvafe_vbi.c | 26 +++++++------ 5 files changed, 50 insertions(+), 29 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h index 0c42042b9369..c1b08ca3f650 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h @@ -32,7 +32,7 @@ /* ************************************************* */ /* *** macro definitions ********************************************* */ /* *********************************************************** */ -#define TVAFE_VER "Ref.2019/03/18" +#define TVAFE_VER "Ref.2019/04/24" /* used to set the flag of tvafe_dev_s */ #define TVAFE_FLAG_DEV_OPENED 0x00000010 diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 31ffdde86ca5..21bc2e93c3c9 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -321,6 +321,8 @@ static void tvafe_cvd2_memory_init(struct tvafe_cvd2_mem_s *mem, cvd_vbi_mem_set(vbi_start, vbi_size); /*open front lpf for av ring*/ W_APB_BIT(ACD_REG_26, 1, 8, 1); + /*for vbi vcnt*/ + W_APB_BIT(ACD_REG_26, 1, 26, 1); #endif } @@ -2013,16 +2015,8 @@ inline bool tvafe_cvd2_no_sig(struct tvafe_cvd2_s *cvd2, struct tvafe_cvd2_mem_s *mem) { static bool ret; - static int time_flag; tvafe_cvd2_get_signal_status(cvd2); - - /*TVAFE register status need more time to be stable.*/ - /*for double time delay.*/ - time_flag++; - if (time_flag%2 != 0) - return ret; - /* get signal status from HW */ /* search video mode */ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h index 0a851375ea83..b6641539ccdf 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h @@ -32,7 +32,7 @@ /* vbi start line: unit is hcount value */ #define VBI_START_CC 0x54 #define VBI_START_WSS 0x54 -#define VBI_START_TT 0x82 +#define VBI_START_TT 0x64 #define VBI_START_VPS 0x82 /* cvd2 function enable/disable defines*/ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c index dd4745534441..98a1694bdcf0 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c @@ -31,6 +31,7 @@ #include "tvafe_regs.h" #include "tvafe_debug.h" #include "tvafe.h" +#include "../vdin/vdin_ctl.h" bool disableapi; bool force_stable; @@ -383,6 +384,9 @@ static ssize_t tvafe_dumpmem_store(struct device *dev, struct tvafe_dev_s *devp; char delim1[3] = " "; char delim2[2] = "\n"; + unsigned int highmem_flag = 0; + unsigned long highaddr; + int i; strcat(delim1, delim2); if (!buff) @@ -415,15 +419,34 @@ static ssize_t tvafe_dumpmem_store(struct device *dev, kfree(buf_orig); return len; } - if (devp->cma_config_flag == 1) - buf = codec_mm_phys_to_virt(devp->mem.start); - else + highmem_flag = + PageHighMem(phys_to_page(devp->mem.start)); + pr_info("highmem_flag:%d\n", highmem_flag); + if (devp->cma_config_flag == 1 && + highmem_flag != 0) { + /*tvafe dts config 5M memory*/ + for (i = 0; + i < devp->cma_mem_size / SZ_1M; + i++) { + highaddr = devp->mem.start + i * SZ_1M; + buf = vdin_vmap(highaddr, SZ_1M); + if (!buf) { + pr_info("vdin_vmap error\n"); + return len; + } + pr_info("buf:0x%p\n", buf); + /*vdin_dma_flush(devp, buf, SZ_1M, DMA_FROM_DEVICE);*/ + vfs_write(filp, buf, SZ_1M, &pos); + vdin_unmap_phyaddr(buf); + } + } else { buf = phys_to_virt(devp->mem.start); - vfs_write(filp, buf, devp->mem.size, &pos); - tvafe_pr_info("write buffer %2d of %s.\n", - devp->mem.size, parm[1]); - tvafe_pr_info("devp->mem.start %x .\n", - devp->mem.start); + vfs_write(filp, buf, devp->mem.size, &pos); + tvafe_pr_info("write buffer %2d of %s.\n", + devp->mem.size, parm[1]); + tvafe_pr_info("devp->mem.start %x .\n", + devp->mem.start); + } vfs_fsync(filp, 0); filp_close(filp, NULL); set_fs(old_fs); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c index cd9d01e6c8ac..c1b7f73374bf 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c @@ -133,7 +133,7 @@ static void vbi_data_type_set(struct vbi_dev_s *devp) W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE23, vbi_data_type); W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE24, vbi_data_type); W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE25, vbi_data_type); - W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE26, vbi_data_type); + /*W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE26, vbi_data_type);*/ } static void vbi_dto_set(struct vbi_dev_s *devp) @@ -380,10 +380,12 @@ static irqreturn_t vbi_isr(int irq, void *dev_id) spin_unlock_irqrestore(&devp->vbi_isr_lock, flags); return IRQ_HANDLED; } + if (devp->vbi_start == false) { spin_unlock_irqrestore(&devp->vbi_isr_lock, flags); return IRQ_HANDLED; } + if (devp->tasklet_enable) tasklet_schedule(&devp->tsklt_slicer); spin_unlock_irqrestore(&devp->vbi_isr_lock, flags); @@ -640,7 +642,8 @@ static void vbi_slicer_task(unsigned long arg) ret = init_cc_data_sync(devp); if (!ret) return; - + if (vbi_dbg_en & 2) + tvafe_pr_info("pac_addr:%p\n", devp->pac_addr); if (devp->pac_addr > devp->pac_addr_end) devp->pac_addr = devp->pac_addr_start; @@ -1305,7 +1308,6 @@ static void vbi_dump_mem(char *path, struct vbi_dev_s *devp) { struct file *filp = NULL; loff_t pos = 0; - void *buf = NULL; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); @@ -1315,15 +1317,10 @@ static void vbi_dump_mem(char *path, struct vbi_dev_s *devp) tvafe_pr_info("create %s error.\n", path); return; } - buf = phys_to_virt(devp->mem_start); - if (buf == NULL) { - tvafe_pr_info("buf is null!!!.\n"); - return; - } - vfs_write(filp, buf, devp->mem_size, &pos); + vfs_write(filp, devp->pac_addr_start, devp->mem_size, &pos); tvafe_pr_info("write buffer addr:0x%p size: %2u to %s.\n", - buf, devp->mem_size, path); + devp->pac_addr_start, devp->mem_size, path); vfs_fsync(filp, 0); filp_close(filp, NULL); set_fs(old_fs); @@ -1443,6 +1440,10 @@ static ssize_t vbi_store(struct device *dev, vbi_buffer->data_wmode = val; tvafe_pr_info("data_wmode:%d\n", vbi_buffer->data_wmode); } else if (!strncmp(parm[0], "start", strlen("start"))) { + W_APB_REG(ACD_REG_22, 0x07080000); + /* manuel reset vbi */ + W_APB_REG(ACD_REG_22, 0x87080000); + W_APB_REG(ACD_REG_22, 0x04080000); vbi_hw_init(devp); vbi_slicer_start(devp); /* enable data capture function */ @@ -1451,10 +1452,11 @@ static ssize_t vbi_store(struct device *dev, devp->vs_delay = VBI_VS_DELAY; tvafe_pr_info("start done!!!\n"); } else if (!strncmp(parm[0], "stop", strlen("stop"))) { - vbi_slicer_stop(vbi_slicer); /* disable data capture function */ devp->tasklet_enable = false; devp->vbi_start = false; + init_cc_data_flag = 0; + vbi_slicer_stop(vbi_slicer); /* manuel reset vbi */ /* vbi reset release, vbi agent enable*/ W_VBI_APB_REG(ACD_REG_22, 0x06080000); @@ -1475,6 +1477,7 @@ static ssize_t vbi_store(struct device *dev, tvafe_pr_info(" set slicer type to %d\n", vbi_slicer->type); } else if (!strncmp(parm[0], "open", strlen("open"))) { + tasklet_enable(&devp->tsklt_slicer); vbi_ringbuffer_init(vbi_buffer, NULL, VBI_DEFAULT_BUFFER_PACKAGE_NUM); devp->slicer->type = VBI_TYPE_NULL; @@ -1490,6 +1493,7 @@ static ssize_t vbi_store(struct device *dev, tvafe_pr_err("request_irq fail\n"); tvafe_pr_info(" open ok.\n"); } else if (!strncmp(parm[0], "release", strlen("release"))) { + tasklet_disable(&devp->tsklt_slicer); ret = vbi_slicer_free(devp, vbi_slicer); devp->tasklet_enable = false; devp->vbi_start = false; /*disable data capture function*/ From 9dd11cea146a342053c521cab3faca6192c31a7b Mon Sep 17 00:00:00 2001 From: "yuegui.he" Date: Wed, 17 Oct 2018 20:54:36 +0800 Subject: [PATCH 0560/1060] dts: emmc: uboot enable emmc config [2/3] PD#SWPL-736 Problem: The s400 emmc platform uboot cannot be loaded into kernel normally Solution: enable enable emmc node in dtb by fdt command. and modify malloc max size to 18M. Verify: s400 Change-Id: Iaef58f1b05a952793d414eb82ac476d88d910fe1 Signed-off-by: yuegui.he Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts --- MAINTAINERS | 22 + arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts | 1313 ---------------- .../boot/dts/amlogic/axg_s400emmc_512m.dts | 1331 ----------------- 3 files changed, 22 insertions(+), 2644 deletions(-) delete mode 100644 arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts delete mode 100644 arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts diff --git a/MAINTAINERS b/MAINTAINERS index 678bff30a24f..c4ba5ed396a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14749,6 +14749,28 @@ M: Evoke Zhang F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_spi.c F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c +AMLOGIC MESON TL1 DTS +M: Xingyu Chen +M: Bo Yang +F: arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +F: arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +F: arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +F: arch/arm64/boot/dts/amlogic/mesontl1* +F: arch/arm64/boot/dts/amlogic/tl1_t962x2_* + +AMLOGIC MESON TL1 PANEL DTS +M: Evoke Zhang +F: arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +F: drivers/amlogic/media/vout/lcd/lcd_phy_config.c +F: drivers/amlogic/media/vout/lcd/lcd_phy_config.h + +AMLOGIC MESONAXG RSR DTS +M: Yeping Miao +F: arch/arm64/boot/dts/amlogic/axg_rsr.dts +F: arch/arm64/boot/dts/amlogic/axg_rsr_v03.dts + AMLOGIC CAMERA DRIVER M: Guosong Zhou F: arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts deleted file mode 100644 index 6969131e354c..000000000000 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts +++ /dev/null @@ -1,1313 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/dts-v1/; - -#include "mesonaxg.dtsi" -#include "mesonaxg_s400-panel.dtsi" -/ { - model = "Amlogic"; - amlogic-dt-id = "axg_s400_v03gva"; - compatible = "amlogic, axg"; - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - serial0 = &uart_AO; - serial1 = &uart_A; - }; - - memory@00000000 { - device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - /* global autoconfigured region for contiguous allocations */ - ramoops@0x07400000 { - compatible = "ramoops"; - reg = <0x07400000 0x00100000>; - record-size = <0x8000>; - console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; - }; - - secmon_reserved:linux,secmon { - compatible = "shared-dma-pool"; - reusable; - size = <0x400000>; - alignment = <0x400000>; - alloc-ranges = <0x05000000 0x400000>; - }; - - secos_reserved:linux,secos { - status = "disable"; - compatible = "amlogic, aml_secos_memory"; - reg = <0x05300000 0x2000000>; - no-map; - }; - fb_reserved:linux,meson-fb { - //compatible = "amlogic, fb-memory"; - //reg = <0x3e000000 0x1f00000>; - compatible = "shared-dma-pool"; - reusable; - size = <0x2000000>; - alignment = <0x400000>; - alloc-ranges = <0x3e000000 0x2000000>; - }; - }; - mtd_nand { - compatible = "amlogic, aml_mtd_nand"; - dev_name = "mtdnand"; - status = "okay"; - reg = <0xFFE07800 0x200>; - interrupts = < 0 34 1 >; - pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; - pinctrl-0 = <&all_nand_pins>; - pinctrl-1 = <&all_nand_pins>; - pinctrl-2 = <&nand_cs_pins>; - device_id = <0>; - - /*fip/tpl configurations, must be same - * with uboot if bl_mode was set as 1 - * bl_mode: 0 compact mode; 1 descrete mode - * if bl_mode was set as 1, fip configeration will work - */ - bl_mode = <1>; - /*copy count of fip*/ - fip_copies = <4>; - /*size of each fip copy */ - fip_size = <0x200000>; - nand_clk_ctrl = <0xFFE07000>; - plat-names = "bootloader","nandnormal"; - plat-num = <2>; - plat-part-0 = <&bootloader>; - plat-part-1 = <&nandnormal>; - bootloader: bootloader{ - enable_pad ="ce0"; - busy_pad = "rb0"; - timming_mode = "mode5"; - bch_mode = "bch8_1k"; - t_rea = <20>; - t_rhoh = <15>; - chip_num = <1>; - part_num = <0>; - rb_detect = <1>; - }; - nandnormal: nandnormal{ - enable_pad ="ce0"; - busy_pad = "rb0"; - timming_mode = "mode5"; - bch_mode = "bch8_1k"; - plane_mode = "twoplane"; - t_rea = <20>; - t_rhoh = <15>; - chip_num = <2>; - part_num = <3>; - partition = <&nand_partitions>; - rb_detect = <1>; - }; - nand_partitions:nand_partition{ - /* - * if bl_mode is 1, tpl size was generate by - * fip_copies * fip_size which - * will not skip bad when calculating - * the partition size; - * - * if bl_mode is 0, - * tpl partition must be comment out. - */ - tpl{ - offset=<0x0 0x0>; - size=<0x0 0x0>; - }; - recovery{ - offset=<0x0 0x0>; - size=<0x0 0x1000000>; - }; - boot{ - offset=<0x0 0x0>; - size=<0x0 0x1000000>; - }; - system{ - offset=<0x0 0x0>; - size=<0x0 0x11800000>; - }; - factory{ - offset=<0x0 0x0>; - size=<0x0 0x1000000>; - }; - data{ - offset=<0xffffffff 0xffffffff>; - size=<0x0 0x0>; - }; - }; - }; - - - ethmac: ethernet@0xff3f0000 { - compatible = "amlogic, gxbb-eth-dwmac"; - reg = <0xff3f0000 0x10000 - 0xff634540 0x8>; - interrupts = <0 8 1>; - pinctrl-names = "external_eth_pins"; - pinctrl-0 = <&external_eth_pins>; - mc_val_internal_phy = <0x1800>; - mc_val_external_phy = <0x1621>; - interrupt-names = "macirq"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - internal_phy=<0>; - }; - - aml_sensor0: aml-sensor@0 { - compatible = "amlogic, aml-thermal"; - device_name = "thermal"; - #thermal-sensor-cells = <1>; - cooling_devices { - cpufreq_cool_cluster0 { - min_state = <1000000>; - dyn_coeff = <140>; - cluster_id = <0>; - node_name = "cpufreq_cool0"; - device_type = "cpufreq"; - }; - cpucore_cool_cluster0 { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - }; - cpufreq_cool0:cpufreq_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - }; - thermal-zones { - soc_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <1050>; - - thermal-sensors = <&aml_sensor0 3>; - - trips { - switch_on: trip-point@0 { - temperature = <70000>; - hysteresis = <1000>; - type = "passive"; - }; - control: trip-point@1 { - temperature = <80000>; - hysteresis = <1000>; - type = "passive"; - }; - hot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - critical: trip-point@3 { - temperature = <260000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - cpufreq_cooling_map { - trip = <&control>; - cooling-device = <&cpufreq_cool0 0 4>; - contribution = <1024>; - }; - cpucore_cooling_map { - trip = <&control>; - cooling-device = <&cpucore_cool0 0 3>; - contribution = <1024>; - }; - }; - }; - }; - - dwc3: dwc3@ff500000 { - compatible = "synopsys, dwc3"; - status = "okay"; - reg = <0xff500000 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy>, <&usb3_phy>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - clocks = <&clkc CLKID_USB_GENERAL>; - clock-names = "dwc_general"; - }; - - usb2_phy: usb2phy@ffe09000 { - compatible = "amlogic, amlogic-new-usb2"; - status = "okay"; - portnum = <4>; - reg = <0xffe09000 0x80 - 0xffd01008 0x4>; - }; - - usb3_phy: usb3phy@ffe09080 { - compatible = "amlogic, amlogic-new-usb3"; - status = "okay"; - portnum = <0>; - reg = <0xffe09080 0x20>; - interrupts = <0 16 4>; - otg = <1>; - gpio-vbus-power = "GPIOAO_5"; - gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; - }; - - dwc2_a { - compatible = "amlogic, dwc2"; - device_name = "dwc2_a"; - reg = <0xff400000 0x40000>; - status = "okay"; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "gxl"; - /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ - controller-type = <3>; - phy-reg = <0xffe09000>; - phy-reg-size = <0xa0>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR - &clkc CLKID_USB1>; - clock-names = "usb_general", - "usb1", - "usb1_to_ddr"; - }; - - pcie_A: pcieA@f9800000 { - compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; - reg = <0xf9800000 0x400000 - 0xff646000 0x2000 - 0xf9f00000 0x100000 - PCIE_PHY_REG PCIE_PHY_SIZE - PCIE_RESET_REG PCIE_RESET_SIZE>; - reg-names = "elbi", "cfg", "config", "phy", "reset"; - reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; - interrupts = <0 177 0>; - #interrupt-cells = <1>; - bus-range = <0x0 0xff>; - #address-cells = <3>; - #size-cells = <2>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; - device_type = "pci"; - ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>; - /* non-prefetchable memory */ - num-lanes = <1>; - pcie-num = <1>; - - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_PCIE_PLL - &clkc CLKID_MIPI_ENABLE_GATE - &clkc CLKID_MIPI_BANDGAP_GATE - &clkc CLKID_PCIE_A - &clkc CLKID_PCIE_CML_EN0>; - clock-names = "pcie_general", - "pcie_refpll", - "pcie_mipi_enable_gate", - "pcie_mipi_bandgap_gate", - "pcie", - "port"; - /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ - gpio-type = <2>; - status = "okay"; - }; - - pcie_B: pcieB@fa000000 { - compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; - reg = <0xfa000000 0x400000 - 0xff648000 0x2000 - 0xfa400000 0x100000 - PCIE_PHY_REG PCIE_PHY_SIZE - PCIE_RESET_REG PCIE_RESET_SIZE>; - reg-names = "elbi", "cfg", "config", "phy", "reset"; - reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; - interrupts = <0 167 0>; - #interrupt-cells = <1>; - bus-range = <0x0 0xff>; - #address-cells = <3>; - #size-cells = <2>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; - device_type = "pci"; - ranges = <0x81000000 0 0 0xfa500000 0x0 0x10000 - /* downstream I/O */ - 0x82000000 0 0xfa510000 0xfa510000 0 0x002f0000>; - /* non-prefetchable memory */ - num-lanes = <1>; - pcie-num = <2>; - - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_PCIE_PLL - &clkc CLKID_MIPI_ENABLE_GATE - &clkc CLKID_MIPI_BANDGAP_GATE - &clkc CLKID_PCIE_B - &clkc CLKID_PCIE_CML_EN1>; - clock-names = "pcie_general", - "pcie_refpll", - "pcie_mipi_enable_gate", - "pcie_mipi_bandgap_gate", - "pcie", - "port"; - /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ - gpio-type = <1>; - status = "okay"; - }; - - - uart_A: serial@ffd24000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd24000 0x18>; - interrupts = <0 26 1>; - status = "okay"; - clocks = <&xtal - &clkc CLKID_UART0>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 128 >; - pinctrl-names = "default"; - pinctrl-0 = <&a_uart_pins>; - }; - - uart_B: serial@ffd23000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd23000 0x18>; - interrupts = <0 75 1>; - status = "disable"; - clocks = <&xtal - &clkc CLKID_UART1>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&b_uart_pins>; - }; - - vpu { - compatible = "amlogic, vpu-axg"; - dev_name = "vpu"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <3>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - }; - - vout { - compatible = "amlogic, vout"; - dev_name = "vout"; - status = "okay"; - }; - - /* Sound iomap */ - aml_snd_iomap { - compatible = "amlogic, snd-iomap"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - pdm_bus { - reg = <0xFF632000 0x2000>; - }; - audiobus_base { - reg = <0xFF642000 0x2000>; - }; - }; - pdm_codec:dummy{ - #sound-dai-cells = <0>; - compatible = "amlogic, pdm_dummy_codec"; - status = "okay"; - }; - dummy_codec:dummy{ - #sound-dai-cells = <0>; - compatible = "amlogic, aml_dummy_codec"; - status = "okay"; - }; - - auge_sound { - compatible = "amlogic, axg-sound-card"; - aml-audio-card,name = "AML-AUGESOUND"; - - aml-audio-card,loopback = <&aml_loopback>; - - aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; - - aml-audio-card,dai-link@0 { - format = "dsp_a"; - mclk-fs = <512>; - //continuous-clock; - //bitclock-inversion; - //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - tdmacpu: cpu { - sound-dai = <&aml_tdma>; - dai-tdm-slot-tx-mask = - <1>; - dai-tdm-slot-rx-mask = - <1>; - dai-tdm-slot-num = <1>; - dai-tdm-slot-width = <32>; - system-clock-frequency = <512000>; - }; - tdmacodec: codec { - sound-dai = <&dummy_codec &dummy_codec>; - }; - }; - - aml-audio-card,dai-link@1 { - format = "i2s"; - mclk-fs = <256>; - //continuous-clock; - //bitclock-inversion; - //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; - cpu { - sound-dai = <&aml_tdmb>; - dai-tdm-slot-tx-mask = <1 1>; - dai-tdm-slot-rx-mask = <1 1>; - dai-tdm-slot-num = <2>; - dai-tdm-slot-width = <32>; - system-clock-frequency = <12288000>; - }; - codec { - /* - * prefix-names = "3101_A", "3101_B", - * "3101_C", "3101_D"; - * sound-dai = <&tlv320adc3101_32 - * &tlv320adc3101_30 - * &tlv320adc3101_34 - * &tlv320adc3101_36>; - */ - sound-dai = <&tlv320adc3101_32 &dummy_codec>; - }; - }; - - aml-audio-card,dai-link@2 { - format = "i2s"; - mclk-fs = <256>; - //continuous-clock; - //bitclock-inversion; - //frame-inversion; - //bitclock-master = <&aml_tdmc>; - //frame-master = <&aml_tdmc>; - cpu { - sound-dai = <&aml_tdmc>; - dai-tdm-slot-tx-mask = <1 1>; - dai-tdm-slot-rx-mask = <1 1>; - dai-tdm-slot-num = <2>; - dai-tdm-slot-width = <32>; - system-clock-frequency = <12288000>; - }; - codec { - prefix-names = "5707_A", "5707_B"; - sound-dai = <&tas5707_36 &tas5707_3a - &dummy_codec>; - }; - }; - - aml-audio-card,dai-link@3 { - mclk-fs = <256>; - cpu { - sound-dai = <&aml_pdm>; - }; - codec { - /* - *enable external loopback - *and tlv320adc3101 as loopback - */ - /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ - /* - * enable internal loopback - * or disable loopback - */ - sound-dai = <&pdm_codec>; - }; - }; - - aml-audio-card,dai-link@4 { - mclk-fs = <128>; - cpu { - sound-dai = <&aml_spdif>; - system-clock-frequency = <6144000>; - }; - codec { - sound-dai = <&dummy_codec>; - }; - }; - }; - - bt-dev{ - compatible = "amlogic, bt-dev"; - dev_name = "bt-dev"; - status = "okay"; - gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; - }; - - wifi{ - compatible = "amlogic, aml_wifi"; - dev_name = "aml_wifi"; - status = "okay"; - interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; - interrupts = < 0 67 4>; - irq_trigger_type = "GPIO_IRQ_LOW"; - power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; - power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - dhd_static_buf; //if use bcm wifi, config dhd_static_buf - pinctrl-names = "default"; - pinctrl-0 = <&wifi_32k_pins>; - pwm_config = <&wifi_pwm_conf>; - }; - - wifi_pwm_conf:wifi_pwm_conf{ - pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_0 30541 0>; - duty-cycle = <15270>; - times = <10>; - }; - pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_2 30500 0>; - duty-cycle = <15250>; - times = <12>; - }; - }; - - sd_emmc_c: emmc@ffe07000 { - status = "disabled"; - compatible = "amlogic, meson-mmc-axg"; - reg = <0xffe07000 0x2000>; - interrupts = <0 218 1>; - pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; - pinctrl-0 = <&emmc_clk_cmd_pins>; - pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - mmc-ddr-1_8v; - mmc-hs200-1_8v; - - max-frequency = <200000000>; - non-removable; - disable-wp; - emmc { - pinname = "emmc"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - caps = "MMC_CAP_8_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_1_8V_DDR", - "MMC_CAP_HW_RESET", - "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; - f_min = <400000>; - f_max = <200000000>; - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; - card_type = <1>; - /* 1:mmc card(include eMMC), - * 2:sd card(include tSD) - */ - }; - }; - - sd_emmc_b:sdio@ffe05000 { - status = "okay"; - compatible = "amlogic, meson-mmc-axg"; - reg = <0xffe05000 0x2000>; - interrupts = <0 217 4>; - pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; - pinctrl-0 = <&sdio_clk_cmd_pins>; - pinctrl-1 = <&sdio_all_pins>; - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - non-removable; - disable-wp; - sdio { - pinname = "sdio"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_CAP_UHS_SDR104", - "MMC_PM_KEEP_POWER", - "MMC_CAP_SDIO_IRQ"; - f_min = <400000>; - f_max = <200000000>; - max_req_size = <0x20000>; /**128KB*/ - card_type = <3>; - /* 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card - */ - }; - }; - - partitions: partitions{ - parts = <11>; - part-0 = <&logo>; - part-1 = <&recovery>; - part-2 = <&rsv>; - part-3 = <&tee>; - part-4 = <&crypt>; - part-5 = <&misc>; - part-6 = <&instaboot>; - part-7 = <&boot>; - part-8 = <&system>; - part-9 = <&cache>; - part-10 = <&data>; - - logo:logo{ - pname = "logo"; - size = <0x0 0x2000000>; - mask = <1>; - }; - recovery:recovery{ - pname = "recovery"; - size = <0x0 0x2000000>; - mask = <1>; - }; - rsv:rsv{ - pname = "rsv"; - size = <0x0 0x800000>; - mask = <1>; - }; - tee:tee{ - pname = "tee"; - size = <0x0 0x800000>; - mask = <1>; - }; - crypt:crypt{ - pname = "crypt"; - size = <0x0 0x2000000>; - mask = <1>; - }; - misc:misc{ - pname = "misc"; - size = <0x0 0x2000000>; - mask = <1>; - }; - instaboot:instaboot{ - pname = "instaboot"; - size = <0x0 0x400000>; - mask = <1>; - }; - boot:boot - { - pname = "boot"; - size = <0x0 0x2000000>; - mask = <1>; - }; - system:system - { - pname = "system"; - size = <0x0 0x80000000>; - mask = <1>; - }; - cache:cache - { - pname = "cache"; - size = <0x0 0x20000000>; - mask = <2>; - }; - data:data - { - pname = "data"; - size = <0xffffffff 0xffffffff>; - mask = <4>; - }; - }; - - meson-fb { - compatible = "amlogic, meson-axg"; - memory-region = <&fb_reserved>; - dev_name = "meson-fb"; - status = "okay"; - interrupts = <0 3 1 - 0 89 1>; - interrupt-names = "viu-vsync", "rdma"; - mem_size = <0x00300000 0x1800000 0x00000000>; - /* uboot logo,fb0/fb1 memory size */ - display_mode_default = "1080p60hz"; - scale_mode = <0>; - /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ - display_size_default = <768 1024 768 2048 32>; - /*768*1024*4*2 = 0x600000*/ - mem_alloc = <1>; - logo_addr = "0x3e000000"; - pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ - }; - - ge2d { - compatible = "amlogic, ge2d-axg"; - dev_name = "ge2d"; - status = "okay"; - interrupts = <0 150 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xff940000 0x10000>; - }; - - adc_keypad { - compatible = "amlogic, adc_keypad"; - status = "okay"; - key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; - key_num = <6>; - io-channels = <&saradc SARADC_CH0>; - io-channel-names = "key-chan-0"; - key_chan = ; - key_code = <116 114 115 139 105 106>; - key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 - key_tolerance = <40 40 40 40 40 40>; - }; - - unifykey{ - compatible = "amlogic, unifykey"; - status = "ok"; - - unifykey-num = <6>; - unifykey-index-0 = <&keysn_0>; - unifykey-index-1 = <&keysn_1>; - unifykey-index-2 = <&keysn_2>; - unifykey-index-3 = <&keysn_3>; - unifykey-index-4 = <&keysn_4>; - unifykey-index-5 = <&keysn_5>; - - keysn_0: key_0{ - key-name = "usid"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_1:key_1{ - key-name = "mac"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_2:key_2{ - key-name = "secure_boot_set"; - key-device = "efuse"; - key-permit = "write"; - }; - keysn_3:key_3{ - key-name = "mac_bt"; - key-device = "normal"; - key-permit = "read","write","del"; - key-type = "mac"; - }; - keysn_4:key_4{ - key-name = "mac_wifi"; - key-device = "normal"; - key-permit = "read","write","del"; - key-type = "mac"; - }; - keysn_5:key_5{ - key-name = "deviceid"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - };//End unifykey - audio_data: audio_data { - compatible = "amlogic, audio_data"; - query_licence_cmd = <0x82000050>; - status = "okay"; - }; -}; /* end of / */ -&efuse { - status = "ok"; -}; - -&pwm_ab { - status = "okay"; -}; -/* Audio Related start */ -/* for spk board */ -&i2c1 { - status = "okay"; - pinctrl-names="default"; - pinctrl-0=<&b_i2c_master>; - - tlv320adc3101_32: tlv320adc3101_32@32 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x19>; - differential_pair = <1>; - status = "okay"; - }; - - tas5707_36: tas5707_36@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "okay"; - reset_pin = <&gpio_ao GPIOAO_4 0>; - }; - - tas5707_3a: tas5707_3a@3a { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1d>; - status = "okay"; - }; -}; - -/* for mic board */ -&i2c_AO { - status = "okay"; - pinctrl-names="default"; - pinctrl-0=<&ao_i2c_master_pin2>; - - aml_pca9557: aml_pca9557@0x1f { - compatible = "amlogic,pca9557_keypad"; - reg = <0x1f>; - key_num = <4>; - key_name = "fdr", "hotword", "pause", "mute"; - key_value = <106 105 139 116>; - key_index_mask = <0x4 0x8 0x10 0x20>; - key_input_mask = <0x3C>; - status = "okay"; - }; - - tlv320adc3101_30: tlv320adc3101_30@30 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x18>; - status = "disable"; - }; - tlv320adc3101_34: tlv320adc3101_34@30 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x1a>; - status = "disable"; - }; - tlv320adc3101_36: tlv320adc3101_36@30 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "disable"; - }; - - es7243_10: es7243_10@10 { - compatible = "MicArray_0"; - #sound-dai-cells = <0>; - reg = <0x10>; - status = "disable"; - }; - es7243_12: es7243_12@12 { - compatible = "MicArray_1"; - #sound-dai-cells = <0>; - reg = <0x12>; - status = "disable"; - }; - es7243_13: es7243_13@13 { - compatible = "MicArray_2"; - #sound-dai-cells = <0>; - reg = <0x13>; - status = "disable"; - }; - cy8c4014_08: cy8c4014_08@08 { - compatible = "cy8c4014"; - #sound-dai-cells = <0>; - reg = <0x8>; - status = "okay"; - }; - is31fl3236a: is31f3236a@0x78 { - compatible = "issi,is31fl3236,gva"; - reg = <0x3c>; - status = "okay"; - led1_b { - label="LED1_B"; - reg_offset = <1>; - }; - led1_g { - label="LED1_G"; - reg_offset = <2>; - }; - led1_r { - label="LED1_R"; - reg_offset = <3>; - }; - led2_b { - label="LED2_B"; - reg_offset = <4>; - }; - led2_g { - label="LED2_G"; - reg_offset = <5>; - }; - led2_r { - label="LED2_R"; - reg_offset = <6>; - }; - led3_b { - label="LED3_B"; - reg_offset = <7>; - }; - led3_g { - label="LED3_G"; - reg_offset = <8>; - }; - led3_r { - label="LED3_R"; - reg_offset = <9>; - }; - led4_b { - label="LED4_B"; - reg_offset = <10>; - }; - led4_g { - label="LED4_G"; - reg_offset = <11>; - }; - led4_r { - label="LED4_R"; - reg_offset = <12>; - }; - }; -}; - -&audiobus { - aml_tdma: tdma { - compatible = "amlogic, axg-snd-tdma"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <1 0>; - dai-tdm-lane-slot-mask-out = <0 1>; - dai-tdm-clk-sel = <0>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_A - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll"; - pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; - }; - - aml_tdmb: tdmb { - compatible = "amlogic, axg-snd-tdmb"; - #sound-dai-cells = <0>; - /*dai-tdm-lane-slot-mask-in = <1 1 1 1>;*/ - dai-tdm-lane-slot-mask-in = <0 0 0 1>; - dai-tdm-clk-sel = <1>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_B - &clkc CLKID_MPLL1>; - clock-names = "mclk", "clk_srcpll"; - pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; - }; - - aml_tdmc: tdmc { - compatible = "amlogic, axg-snd-tdmc"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <0 1 0 0>; - dai-tdm-lane-slot-mask-out = <0 0 1 1>; - dai-tdm-clk-sel = <2>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_C - &clkc CLKID_MPLL2>; - clock-names = "mclk", "clk_srcpll"; - pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; - }; - - aml_spdif: spdif { - compatible = "amlogic, axg-snd-spdif"; - #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 - &clkc CLKID_FCLK_DIV4 - &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; - clock-names = "sysclk", "fixed_clk", "gate_spdifin", - "gate_spdifout", "clk_spdifin", "clk_spdifout"; - interrupts = - ; - - interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; - pinctrl-0 = <&spdifout &spdifin>; - status = "okay"; - }; - aml_pdm: pdm { - compatible = "amlogic, axg-snd-pdm"; - #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ - status = "okay"; - }; - - aml_loopback: loopback { - compatible = "amlogic, snd-loopback"; - - /* - * external loopback clock config - * enable clk while pdm record data - */ - /*clocks = <&clkc CLKID_MPLL1>;*/ - /*clock-names = "datalb_mpll";*/ - - /* - * 0: out rate = in data rate; - * 1: out rate = loopback data rate; - */ - - lb_mode = <0>; - - /* datain src - * 0: tdmin_a; - * 1: tdmin_b; - * 2: tdmin_c; - * 3: spdifin; - * 4: pdmin; - */ - datain_src = <4>; - datain_chnum = <4>; - datain_chmask = <0x3>; - - /* tdmin_lb src - * 0: tdmoutA - * 1: tdmoutB - * 2: tdmoutC - * 3: PAD_tdminA - * 4: PAD_tdminB - * 5: PAD_tdminC - */ - - /*if tdmin_lb >= 3, use external loopback*/ - datalb_src = <2>; - datalb_chnum = <2>; - /*config which data pin as loopback*/ - /*datalb-lane-mask-in = <0 0 0 1>;*/ - datalb_chmask = <0x3>; - - status = "okay"; - }; -}; /* end of audiobus */ - -&pinctrl_periphs { - tdmout_a: tdmout_a { - mux { - groups = "tdma_sclk", - "tdma_fs"; - function = "tdma_out"; - }; - }; - - tdmout_a_data: tdmout_a_data { - mux { - groups = "tdma_dout1_x15"; - function = "tdma_out"; - }; - }; - - tdmin_a: tdmin_a { - mux { - groups = "tdma_din0"; - function = "tdma_in"; - }; - }; - - tdmb_mclk: tdmb_mclk { - mux { - groups = "mclk_b"; - function = "mclk_b"; - }; - }; - - tdmout_b: tdmout_b { - mux { - groups = "tdmb_sclk", - "tdmb_fs"; - function = "tdmb_out"; - }; - }; - // tdmin and tdmout are the same pins. can't use at same time - tdmin_b:tdmin_b { - mux { - groups = "tdmb_din0", - "tdmb_din1", - "tdmb_din2_a12", - "tdmb_din3_a13"; - function = "tdmb_in"; - }; - }; - - tdmc_mclk: tdmc_mclk { - mux { - groups = "mclk_a"; - function = "mclk_a"; - }; - }; - - tdmout_c:tdmout_c { - mux { - groups = "tdmc_sclk", - "tdmc_fs", - "tdmc_dout0", - "tdmc_dout2_a6", - "tdmc_dout3_a7"; - function = "tdmc_out"; - }; - }; - - - tdmin_c:tdmin_c { - mux { - groups = "tdmc_din1"; - function = "tdmc_in"; - }; - }; - - spdifout: spidfout { - mux { - groups = "spdif_out_a20"; - function = "spdif_out"; - }; - }; - - spdifin: spidfin { - mux { - groups = "spdif_in_a19"; - function = "spdif_in"; - }; - }; - - pdmin: pdmin { - mux { - groups = "pdm_dclk_a14", - "pdm_din0", - "pdm_din1", - "pdm_din2", - "pdm_din3"; - function = "pdm"; - }; - }; - - bl_pwm_on_pins: bl_pwm_on_pin { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - bl_pwm_off_pins:bl_pwm_off_pin { - mux { - pins = "GPIOZ_4"; - function = "gpio_periphs"; - output-high; - }; - }; -}; /* end of pinctrl_periphs */ -/* Audio Related End */ - -&aobus{ - uart_AO: serial@3000 { - compatible = "amlogic, meson-uart"; - reg = <0x3000 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <1>; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_uart_pins>; - support-sysrq = <0>; /* 0 not support , 1 support */ - }; - - uart_AO_B: serial@4000 { - compatible = "amlogic, meson-uart"; - reg = <0x4000 0x18>; - interrupts = <0 197 1>; - status = "disable"; - clocks = <&xtal>; - clock-names = "clk_uart"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_b_uart_pins>; - }; -}; - -&audio_data{ - status = "okay"; -}; diff --git a/arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts b/arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts deleted file mode 100644 index da16137a1c10..000000000000 --- a/arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts +++ /dev/null @@ -1,1331 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/axg_s400emmc.dts - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/dts-v1/; - -#include "mesonaxg.dtsi" -#include "mesonaxg_s400-panel.dtsi" -#include "partition_mbox_normal.dtsi" -/ { - model = "Amlogic"; - amlogic-dt-id = "axg_s400emmc_512m"; - compatible = "amlogic, axg"; - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - serial0 = &uart_AO; - serial1 = &uart_A; - }; - - ion_dev { - compatible = "amlogic, ion_dev"; - memory-region = <&ion_reserved>; - }; - - memory@00000000 { - device_type = "memory"; - linux,usable-memory = <0x000000 0x20000000>; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - /* global autoconfigured region for contiguous allocations */ - ramoops@0x07400000 { - compatible = "ramoops"; - reg = <0x07400000 0x00100000>; - record-size = <0x8000>; - console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; - }; - - secmon_reserved:linux,secmon { - compatible = "shared-dma-pool"; - reusable; - size = <0x400000>; - alignment = <0x400000>; - alloc-ranges = <0x05000000 0x400000>; - }; - - secos_reserved:linux,secos { - status = "disable"; - compatible = "amlogic, aml_secos_memory"; - reg = <0x05300000 0x2000000>; - no-map; - }; - fb_reserved:linux,meson-fb { - //compatible = "amlogic, fb-memory"; - //reg = <0x3e000000 0x1f00000>; - compatible = "shared-dma-pool"; - reusable; - size = <0x2000000>; - alignment = <0x400000>; - alloc-ranges = <0x3e000000 0x2000000>; - }; - - ion_reserved:linux,ion-dev { - compatible = "shared-dma-pool"; - reusable; - size = <0x2000000>; - alignment = <0x400000>; - }; - }; - mtd_nand { - compatible = "amlogic, aml_mtd_nand"; - dev_name = "mtdnand"; - status = "disable"; - reg = <0xFFE07800 0x200>; - interrupts = < 0 34 1 >; - pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; - pinctrl-0 = <&all_nand_pins>; - pinctrl-1 = <&all_nand_pins>; - pinctrl-2 = <&nand_cs_pins>; - device_id = <0>; - - /*fip/tpl configurations, must be same - * with uboot if bl_mode was set as 1 - * bl_mode: 0 compact mode; 1 descrete mode - * if bl_mode was set as 1, fip configeration will work - */ - bl_mode = <1>; - /*copy count of fip*/ - fip_copies = <4>; - /*size of each fip copy */ - fip_size = <0x200000>; - nand_clk_ctrl = <0xFFE07000>; - plat-names = "bootloader","nandnormal"; - plat-num = <2>; - plat-part-0 = <&bootloader>; - plat-part-1 = <&nandnormal>; - bootloader: bootloader{ - enable_pad ="ce0"; - busy_pad = "rb0"; - timming_mode = "mode5"; - bch_mode = "bch8_1k"; - t_rea = <20>; - t_rhoh = <15>; - chip_num = <1>; - part_num = <0>; - rb_detect = <1>; - }; - nandnormal: nandnormal{ - enable_pad ="ce0"; - busy_pad = "rb0"; - timming_mode = "mode5"; - bch_mode = "bch8_1k"; - plane_mode = "twoplane"; - t_rea = <20>; - t_rhoh = <15>; - chip_num = <2>; - part_num = <3>; - partition = <&nand_partitions>; - rb_detect = <1>; - }; - nand_partitions:nand_partition{ - /* - * if bl_mode is 1, tpl size was generate by - * fip_copies * fip_size which - * will not skip bad when calculating - * the partition size; - * - * if bl_mode is 0, - * tpl partition must be comment out. - */ - tpl{ - offset=<0x0 0x0>; - size=<0x0 0x0>; - }; - logo{ - offset=<0x0 0x0>; - size=<0x0 0x200000>; - }; - recovery{ - offset=<0x0 0x0>; - size=<0x0 0x1000000>; - }; - boot{ - offset=<0x0 0x0>; - size=<0x0 0xF00000>; - }; - system{ - offset=<0x0 0x0>; - size=<0x0 0x11800000>; - }; - data{ - offset=<0xffffffff 0xffffffff>; - size=<0x0 0x0>; - }; - }; - }; - - - ethmac: ethernet@0xff3f0000 { - compatible = "amlogic, gxbb-eth-dwmac"; - reg = <0xff3f0000 0x10000 - 0xff634540 0x8>; - interrupts = <0 8 1>; - pinctrl-names = "external_eth_pins"; - pinctrl-0 = <&external_eth_pins>; - mc_val_internal_phy = <0x1800>; - mc_val_external_phy = <0x1621>; - interrupt-names = "macirq"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - internal_phy=<0>; - }; - - aml_sensor0: aml-sensor@0 { - compatible = "amlogic, aml-thermal"; - device_name = "thermal"; - #thermal-sensor-cells = <1>; - cooling_devices { - cpufreq_cool_cluster0 { - min_state = <1000000>; - dyn_coeff = <140>; - cluster_id = <0>; - node_name = "cpufreq_cool0"; - device_type = "cpufreq"; - }; - cpucore_cool_cluster0 { - min_state = <1>; - dyn_coeff = <0>; - cluster_id = <0>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - }; - cpufreq_cool0:cpufreq_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - }; - thermal-zones { - soc_thermal { - polling-delay = <1000>; - polling-delay-passive = <100>; - sustainable-power = <1050>; - - thermal-sensors = <&aml_sensor0 3>; - - trips { - switch_on: trip-point@0 { - temperature = <70000>; - hysteresis = <1000>; - type = "passive"; - }; - control: trip-point@1 { - temperature = <80000>; - hysteresis = <1000>; - type = "passive"; - }; - hot: trip-point@2 { - temperature = <85000>; - hysteresis = <5000>; - type = "hot"; - }; - critical: trip-point@3 { - temperature = <260000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - cpufreq_cooling_map { - trip = <&control>; - cooling-device = <&cpufreq_cool0 0 4>; - contribution = <1024>; - }; - cpucore_cooling_map { - trip = <&control>; - cooling-device = <&cpucore_cool0 0 3>; - contribution = <1024>; - }; - }; - }; - }; - - dwc3: dwc3@ff500000 { - compatible = "synopsys, dwc3"; - status = "okay"; - reg = <0xff500000 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy>, <&usb3_phy>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - clocks = <&clkc CLKID_USB_GENERAL>; - clock-names = "dwc_general"; - }; - - usb2_phy: usb2phy@ffe09000 { - compatible = "amlogic, amlogic-new-usb2"; - status = "okay"; - portnum = <4>; - reg = <0xffe09000 0x80 - 0xffd01008 0x4>; - }; - - usb3_phy: usb3phy@ffe09080 { - compatible = "amlogic, amlogic-new-usb3"; - status = "okay"; - portnum = <0>; - reg = <0xffe09080 0x20>; - interrupts = <0 16 4>; - otg = <1>; - gpio-vbus-power = "GPIOAO_5"; - gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; - }; - - dwc2_a { - compatible = "amlogic, dwc2"; - device_name = "dwc2_a"; - reg = <0xff400000 0x40000>; - status = "okay"; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "gxl"; - /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ - controller-type = <3>; - phy-reg = <0xffe09000>; - phy-reg-size = <0xa0>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR - &clkc CLKID_USB1>; - clock-names = "usb_general", - "usb1", - "usb1_to_ddr"; - }; - - pcie_A: pcieA@f9800000 { - compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; - reg = <0xf9800000 0x400000 - 0xff646000 0x2000 - 0xf9f00000 0x100000 - PCIE_PHY_REG PCIE_PHY_SIZE - PCIE_RESET_REG PCIE_RESET_SIZE>; - reg-names = "elbi", "cfg", "config", "phy", "reset"; - reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; - interrupts = <0 177 0>; - #interrupt-cells = <1>; - bus-range = <0x0 0xff>; - #address-cells = <3>; - #size-cells = <2>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; - device_type = "pci"; - ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>; - /* non-prefetchable memory */ - num-lanes = <1>; - pcie-num = <1>; - - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_PCIE_PLL - &clkc CLKID_MIPI_ENABLE_GATE - &clkc CLKID_MIPI_BANDGAP_GATE - &clkc CLKID_PCIE_A - &clkc CLKID_PCIE_CML_EN0>; - clock-names = "pcie_general", - "pcie_refpll", - "pcie_mipi_enable_gate", - "pcie_mipi_bandgap_gate", - "pcie", - "port"; - /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ - gpio-type = <2>; - status = "okay"; - }; - - pcie_B: pcieB@fa000000 { - compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; - reg = <0xfa000000 0x400000 - 0xff648000 0x2000 - 0xfa400000 0x100000 - PCIE_PHY_REG PCIE_PHY_SIZE - PCIE_RESET_REG PCIE_RESET_SIZE>; - reg-names = "elbi", "cfg", "config", "phy", "reset"; - reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; - interrupts = <0 167 0>; - #interrupt-cells = <1>; - bus-range = <0x0 0xff>; - #address-cells = <3>; - #size-cells = <2>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; - device_type = "pci"; - ranges = <0x81000000 0 0 0xfa500000 0x0 0x10000 - /* downstream I/O */ - 0x82000000 0 0xfa510000 0xfa510000 0 0x002f0000>; - /* non-prefetchable memory */ - num-lanes = <1>; - pcie-num = <2>; - - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_PCIE_PLL - &clkc CLKID_MIPI_ENABLE_GATE - &clkc CLKID_MIPI_BANDGAP_GATE - &clkc CLKID_PCIE_B - &clkc CLKID_PCIE_CML_EN1>; - clock-names = "pcie_general", - "pcie_refpll", - "pcie_mipi_enable_gate", - "pcie_mipi_bandgap_gate", - "pcie", - "port"; - /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ - gpio-type = <1>; - status = "okay"; - }; - - - uart_A: serial@ffd24000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd24000 0x18>; - interrupts = <0 26 1>; - status = "okay"; - clocks = <&xtal - &clkc CLKID_UART0>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 128 >; - pinctrl-names = "default"; - pinctrl-0 = <&a_uart_pins>; - }; - - uart_B: serial@ffd23000 { - compatible = "amlogic, meson-uart"; - reg = <0xffd23000 0x18>; - interrupts = <0 75 1>; - status = "disable"; - clocks = <&xtal - &clkc CLKID_UART1>; - clock-names = "clk_uart", - "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&b_uart_pins>; - }; - - vpu { - compatible = "amlogic, vpu-axg"; - dev_name = "vpu"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <3>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - }; - - vout { - compatible = "amlogic, vout"; - dev_name = "vout"; - status = "okay"; - }; - - /* Sound iomap */ - aml_snd_iomap { - compatible = "amlogic, snd-iomap"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - pdm_bus { - reg = <0xFF632000 0x2000>; - }; - audiobus_base { - reg = <0xFF642000 0x2000>; - }; - }; - pdm_codec:dummy{ - #sound-dai-cells = <0>; - compatible = "amlogic, pdm_dummy_codec"; - status = "okay"; - }; - dummy_codec:dummy{ - #sound-dai-cells = <0>; - compatible = "amlogic, aml_dummy_codec"; - status = "okay"; - }; - - auge_sound { - compatible = "amlogic, axg-sound-card"; - aml-audio-card,name = "AML-AUGESOUND"; - - aml-audio-card,loopback = <&aml_loopback>; - - aml-audio-card,dai-link@0 { - format = "dsp_a"; - mclk-fs = <512>; - //continuous-clock; - //bitclock-inversion; - //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-pcm"; - tdmacpu: cpu { - sound-dai = <&aml_tdma>; - dai-tdm-slot-tx-mask = - <1 1 1 1 1 1 1 1>; - dai-tdm-slot-rx-mask = - <1 1 1 1 1 1 1 1>; - dai-tdm-slot-num = <8>; - dai-tdm-slot-width = <32>; - system-clock-frequency = <24576000>; - }; - tdmacodec: codec { - sound-dai = <&dummy_codec &dummy_codec>; - }; - }; - - aml-audio-card,dai-link@1 { - format = "i2s"; - mclk-fs = <256>; - //continuous-clock; - //bitclock-inversion; - //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; - //bitclock-master = <&tdmbcodec>; - //frame-master = <&tdmbcodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - //suffix-name = "alsaPORT-i2s"; - cpu { - sound-dai = <&aml_tdmb>; - dai-tdm-slot-tx-mask = <1 1>; - dai-tdm-slot-rx-mask = <1 1>; - dai-tdm-slot-num = <2>; - dai-tdm-slot-width = <32>; - system-clock-frequency = <12288000>; - }; - codec { - /* - * prefix-names = "3101_A", "3101_B", - * "3101_C", "3101_D"; - * sound-dai = <&tlv320adc3101_32 - * &tlv320adc3101_30 - * &tlv320adc3101_34 - * &tlv320adc3101_36>; - */ - sound-dai = <&tlv320adc3101_32 &dummy_codec>; - }; - }; - - aml-audio-card,dai-link@2 { - format = "i2s"; - mclk-fs = <256>; - continuous-clock; - //bitclock-inversion; - //frame-inversion; - //bitclock-master = <&aml_tdmc>; - //frame-master = <&aml_tdmc>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-i2s"; - cpu { - sound-dai = <&aml_tdmc>; - dai-tdm-slot-tx-mask = <1 1>; - dai-tdm-slot-rx-mask = <1 1>; - dai-tdm-slot-num = <2>; - dai-tdm-slot-width = <32>; - system-clock-frequency = <12288000>; - }; - codec { - prefix-names = "5707_A", "5707_B"; - sound-dai = <&tas5707_36 &tas5707_3a - &dummy_codec>; - }; - }; - - aml-audio-card,dai-link@3 { - mclk-fs = <64>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-pdm"; - cpu { - sound-dai = <&aml_pdm>; - }; - codec { - /* - *enable external loopback - *and tlv320adc3101 as loopback - */ - /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ - /* - * enable internal loopback - * or disable loopback - */ - sound-dai = <&pdm_codec>; - }; - }; - - aml-audio-card,dai-link@4 { - mclk-fs = <128>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-spdif"; - cpu { - sound-dai = <&aml_spdif>; - system-clock-frequency = <6144000>; - }; - codec { - sound-dai = <&dummy_codec>; - }; - }; - }; - - bt-dev{ - compatible = "amlogic, bt-dev"; - dev_name = "bt-dev"; - status = "okay"; - gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; - }; - - wifi{ - compatible = "amlogic, aml_wifi"; - dev_name = "aml_wifi"; - status = "okay"; - interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; - irq_trigger_type = "GPIO_IRQ_LOW"; - power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; - power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - dhd_static_buf; //if use bcm wifi, config dhd_static_buf - pinctrl-names = "default"; - pinctrl-0 = <&wifi_32k_pins>; - pwm_config = <&wifi_pwm_conf>; - }; - - wifi_pwm_conf:wifi_pwm_conf{ - pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_0 30541 0>; - duty-cycle = <15270>; - times = <10>; - }; - pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_2 30500 0>; - duty-cycle = <15250>; - times = <12>; - }; - }; - - sd_emmc_c: emmc@ffe07000 { - status = "okay"; - compatible = "amlogic, meson-mmc-axg"; - reg = <0xffe07000 0x2000>; - interrupts = <0 218 1>; - pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; - pinctrl-0 = <&emmc_clk_cmd_pins>; - pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - mmc-ddr-1_8v; - mmc-hs200-1_8v; - - max-frequency = <200000000>; - non-removable; - disable-wp; - emmc { - pinname = "emmc"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - caps = "MMC_CAP_8_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_1_8V_DDR", - "MMC_CAP_HW_RESET", - "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - f_min = <400000>; - f_max = <100000000>; - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - tx_delay = <8>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; - card_type = <1>; - /* 1:mmc card(include eMMC), - * 2:sd card(include tSD) - */ - }; - }; - - sd_emmc_b:sdio@ffe05000 { - status = "okay"; - compatible = "amlogic, meson-mmc-axg"; - reg = <0xffe05000 0x2000>; - interrupts = <0 217 4>; - pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; - pinctrl-0 = <&sdio_clk_cmd_pins>; - pinctrl-1 = <&sdio_all_pins>; - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - non-removable; - disable-wp; - sdio { - pinname = "sdio"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_UHS_SDR12", - "MMC_CAP_UHS_SDR25", - "MMC_CAP_UHS_SDR50", - "MMC_CAP_UHS_SDR104", - "MMC_PM_KEEP_POWER", - "MMC_CAP_SDIO_IRQ"; - f_min = <400000>; - f_max = <200000000>; - max_req_size = <0x20000>; /**128KB*/ - card_type = <3>; - /* 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card - */ - }; - }; - - partitions: partitions{ - parts = <14>; - part-0 = <&logo>; - part-1 = <&recovery>; - part-2 = <&rsv>; - part-3 = <&tee>; - part-4 = <&crypt>; - part-5 = <&misc>; - part-6 = <&instaboot>; - part-7 = <&boot>; - part-8 = <&vendor>; - part-9 = <&odm>; - part-10 = <&system>; - part-11 = <&cache>; - part-12 = <&udisk>; - part-13 = <&data>; - - logo:logo{ - pname = "logo"; - size = <0x0 0x2000000>; - mask = <1>; - }; - recovery:recovery{ - pname = "recovery"; - size = <0x0 0x2000000>; - mask = <1>; - }; - rsv:rsv{ - pname = "rsv"; - size = <0x0 0x800000>; - mask = <1>; - }; - tee:tee{ - pname = "tee"; - size = <0x0 0x800000>; - mask = <1>; - }; - crypt:crypt{ - pname = "crypt"; - size = <0x0 0x2000000>; - mask = <1>; - }; - misc:misc{ - pname = "misc"; - size = <0x0 0x2000000>; - mask = <1>; - }; - instaboot:instaboot{ - pname = "instaboot"; - size = <0x0 0x400000>; - mask = <1>; - }; - boot:boot - { - pname = "boot"; - size = <0x0 0x2000000>; - mask = <1>; - }; - vendor:vendor - { - pname = "vendor"; - size = <0x0 0x10000000>; - mask = <1>; - }; - odm:odm - { - pname = "odm"; - size = <0x0 0x10000000>; - mask = <1>; - }; - system:system - { - pname = "system"; - size = <0x0 0x82000000>; - mask = <1>; - }; - cache:cache - { - pname = "cache"; - size = <0x0 0x20000000>; - mask = <2>; - }; - udisk:udisk - { - pname = "udisk"; - size = <0x0 0x20000000>; - mask = <2>; - }; - data:data - { - pname = "data"; - size = <0xffffffff 0xffffffff>; - mask = <4>; - }; - }; - - meson-fb { - compatible = "amlogic, meson-axg"; - memory-region = <&fb_reserved>; - dev_name = "meson-fb"; - status = "okay"; - interrupts = <0 3 1 - 0 89 1>; - interrupt-names = "viu-vsync", "rdma"; - mem_size = <0x00300000 0x1800000 0x00000000>; - /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x0b51000*/ - display_mode_default = "720p60hz"; - scale_mode = <0>; - /*1280*720*4*2 = 0xA8C000*/ - display_size_default = <1280 720 1280 1440 32>; - /*768*1024*4*2 = 0x600000*/ - logo_addr = "0x3e000000"; - pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ - }; - - ge2d { - compatible = "amlogic, ge2d-axg"; - dev_name = "ge2d"; - status = "okay"; - interrupts = <0 150 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xff940000 0x10000>; - }; - - adc_keypad { - compatible = "amlogic, adc_keypad"; - status = "okay"; - key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; - key_num = <6>; - io-channels = <&saradc SARADC_CH0>; - io-channel-names = "key-chan-0"; - key_chan = ; - key_code = <116 114 115 139 105 106>; - key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 - key_tolerance = <40 40 40 40 40 40>; - }; - - unifykey{ - compatible = "amlogic, unifykey"; - status = "ok"; - - unifykey-num = <6>; - unifykey-index-0 = <&keysn_0>; - unifykey-index-1 = <&keysn_1>; - unifykey-index-2 = <&keysn_2>; - unifykey-index-3 = <&keysn_3>; - unifykey-index-4 = <&keysn_4>; - unifykey-index-5 = <&keysn_5>; - - keysn_0: key_0{ - key-name = "usid"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_1:key_1{ - key-name = "mac"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - keysn_2:key_2{ - key-name = "secure_boot_set"; - key-device = "efuse"; - key-permit = "write"; - }; - keysn_3:key_3{ - key-name = "mac_bt"; - key-device = "normal"; - key-permit = "read","write","del"; - key-type = "mac"; - }; - keysn_4:key_4{ - key-name = "mac_wifi"; - key-device = "normal"; - key-permit = "read","write","del"; - key-type = "mac"; - }; - keysn_5:key_5{ - key-name = "deviceid"; - key-device = "normal"; - key-permit = "read","write","del"; - }; - };//End unifykey - -}; /* end of / */ -&efuse { - status = "ok"; -}; - -&pwm_ab { - status = "okay"; -}; -/* Audio Related start */ -/* for spk board */ -&i2c1 { - status = "okay"; - pinctrl-names="default"; - pinctrl-0=<&b_i2c_master>; - - tlv320adc3101_32: tlv320adc3101_32@32 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x19>; - differential_pair = <1>; - status = "okay"; - }; - - tas5707_36: tas5707_36@36 { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "okay"; - reset_pin = <&gpio_ao GPIOAO_4 0>; - }; - - tas5707_3a: tas5707_3a@3a { - compatible = "ti,tas5707"; - #sound-dai-cells = <0>; - reg = <0x1d>; - status = "okay"; - }; -}; - -/* for mic board */ -&i2c_AO { - status = "okay"; - pinctrl-names="default"; - pinctrl-0=<&ao_i2c_master_pin2>; - - pca9557: pca9557@0x1f { - compatible = "nxp,pca9557"; - reg = <0x1f>; - status = "okay"; - }; - tlv320adc3101_30: tlv320adc3101_30@30 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x18>; - status = "disable"; - }; - tlv320adc3101_34: tlv320adc3101_34@30 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x1a>; - status = "disable"; - }; - tlv320adc3101_36: tlv320adc3101_36@30 { - compatible = "ti,tlv320adc3101"; - #sound-dai-cells = <0>; - reg = <0x1b>; - status = "disable"; - }; -}; - -&audiobus { - aml_tdma: tdma { - compatible = "amlogic, axg-snd-tdma"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <1 0>; - dai-tdm-lane-slot-mask-out = <0 1>; - dai-tdm-clk-sel = <0>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_A - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll"; - pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; - }; - - aml_tdmb: tdmb { - compatible = "amlogic, axg-snd-tdmb"; - #sound-dai-cells = <0>; - /*dai-tdm-lane-slot-mask-in = <1 1 1 1>;*/ - dai-tdm-lane-slot-mask-in = <0 0 0 1>; - dai-tdm-clk-sel = <1>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_B - &clkc CLKID_MPLL1>; - clock-names = "mclk", "clk_srcpll"; - pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; - }; - - aml_tdmc: tdmc { - compatible = "amlogic, axg-snd-tdmc"; - #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <0 1 0 0>; - dai-tdm-lane-slot-mask-out = <0 0 1 1>; - dai-tdm-clk-sel = <2>; - clocks = <&clkaudio CLKID_AUDIO_MCLK_C - &clkc CLKID_MPLL2>; - clock-names = "mclk", "clk_srcpll"; - pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; - }; - - aml_spdif: spdif { - compatible = "amlogic, axg-snd-spdif"; - #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 - &clkc CLKID_FCLK_DIV4 - &clkaudio CLKID_AUDIO_SPDIFIN - &clkaudio CLKID_AUDIO_SPDIFOUT - &clkaudio CLKID_AUDIO_SPDIFIN_CTRL - &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; - clock-names = "sysclk", "fixed_clk", "gate_spdifin", - "gate_spdifout", "clk_spdifin", "clk_spdifout"; - interrupts = - ; - - interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; - pinctrl-0 = <&spdifout &spdifin>; - - /* - * whether do asrc for pcm. - * if raw data, asrc is disabled automatically - * 0: "Disable", - * 1: "Enable:32K", - * 2: "Enable:44K", - * 3: "Enable:48K", - * 4: "Enable:88K", - * 5: "Enable:96K", - * 6: "Enable:176K", - * 7: "Enable:192K", - */ - auto_asrc = <0>; - status = "okay"; - }; - aml_pdm: pdm { - compatible = "amlogic, axg-snd-pdm"; - #sound-dai-cells = <0>; - clocks = <&clkaudio CLKID_AUDIO_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - filter_mode = <1>; /* mode 0~4, defalut:1 */ - status = "okay"; - }; - - aml_loopback: loopback { - compatible = "amlogic, snd-loopback"; - /* - * external loopback clock config - * enable clk while pdm record data - */ - /*clocks = <&clkc CLKID_MPLL1>;*/ - /*clock-names = "datalb_mpll";*/ - - /* - * 0: out rate = in data rate; - * 1: out rate = loopback data rate; - */ - lb_mode = <0>; - - /* datain src - * 0: tdmin_a; - * 1: tdmin_b; - * 2: tdmin_c; - * 3: spdifin; - * 4: pdmin; - */ - datain_src = <4>; - datain_chnum = <8>; - datain_chmask = <0x7f>; - - /* tdmin_lb src - * 0: tdmoutA - * 1: tdmoutB - * 2: tdmoutC - * 3: PAD_tdminA - * 4: PAD_tdminB - * 5: PAD_tdminC - */ - /*if tdmin_lb >= 3, use external loopback*/ - datalb_src = <2>; - datalb_chnum = <2>; - /*config which data pin as loopback*/ - /*datalb-lane-mask-in = <0 0 0 1>;*/ - datalb_chmask = <0x1>; - - status = "okay"; - }; - - audioresample: resample { - compatible = "amlogic, axg-resample"; - clocks = <&clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_MCLK_F - &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; - clock-names = "resample_pll", "resample_src", "resample_clk"; - /*same with toddr_src - * TDMIN_A, - * TDMIN_B, - * TDMIN_C, - * SPDIFIN, - * PDMIN, - * NONE, - * TDMIN_LB, - * LOOPBACK, - */ - resample_module = <3>; - status = "okay"; - }; - aml_pwrdet: pwrdet { - compatible = "amlogic, axg-power-detect"; - - interrupts = ; - interrupt-names = "pwrdet_irq"; - - /* pwrdet source sel - * 7: loopback; - * 6: tdmin_lb; - * 5: reserved; - * 4: pdmin; - * 3: spdifin; - * 2: tdmin_c; - * 1: tdmin_b; - * 0: tdmin_a; - */ - pwrdet_src = <4>; - - hi_th = <0x70000>; - lo_th = <0x16000>; - - status = "disabled"; - }; -}; /* end of audiobus */ - -&pinctrl_periphs { - tdmout_a: tdmout_a { - mux { - groups = "tdma_sclk", - "tdma_fs"; - function = "tdma_out"; - }; - }; - - tdmout_a_data: tdmout_a_data { - mux { - groups = "tdma_dout1_x15"; - function = "tdma_out"; - }; - }; - - tdmin_a: tdmin_a { - mux { - groups = "tdma_din0"; - function = "tdma_in"; - }; - }; - - tdmb_mclk: tdmb_mclk { - mux { - groups = "mclk_b"; - function = "mclk_b"; - }; - }; - - tdmout_b: tdmout_b { - mux { - groups = "tdmb_sclk", - "tdmb_fs"; - function = "tdmb_out"; - }; - }; - // tdmin and tdmout are the same pins. can't use at same time - tdmin_b:tdmin_b { - mux { - groups = "tdmb_din0", - "tdmb_din1", - "tdmb_din2_a12", - "tdmb_din3_a13"; - function = "tdmb_in"; - }; - }; - - tdmc_mclk: tdmc_mclk { - mux { - groups = "mclk_a"; - function = "mclk_a"; - }; - }; - - tdmout_c:tdmout_c { - mux { - groups = "tdmc_sclk", - "tdmc_fs", - "tdmc_dout0", - "tdmc_dout2_a6", - "tdmc_dout3_a7"; - function = "tdmc_out"; - }; - }; - - - tdmin_c:tdmin_c { - mux { - groups = "tdmc_din1"; - function = "tdmc_in"; - }; - }; - - spdifout: spidfout { - mux { - groups = "spdif_out_a20"; - function = "spdif_out"; - }; - }; - - spdifin: spidfin { - mux { - groups = "spdif_in_a19"; - function = "spdif_in"; - }; - }; - - pdmin: pdmin { - mux { - groups = "pdm_dclk_a14", - "pdm_din0", - "pdm_din1", - "pdm_din2", - "pdm_din3"; - function = "pdm"; - }; - }; - - bl_pwm_on_pins: bl_pwm_on_pin { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - bl_pwm_off_pins:bl_pwm_off_pin { - mux { - pins = "GPIOZ_4"; - function = "gpio_periphs"; - output-high; - }; - }; -}; /* end of pinctrl_periphs */ -/* Audio Related End */ - -&aobus{ - uart_AO: serial@3000 { - compatible = "amlogic, meson-uart"; - reg = <0x3000 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <1>; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_uart_pins>; - support-sysrq = <0>; /* 0 not support , 1 support */ - }; - - uart_AO_B: serial@4000 { - compatible = "amlogic, meson-uart"; - reg = <0x4000 0x18>; - interrupts = <0 197 1>; - status = "disable"; - clocks = <&xtal>; - clock-names = "clk_uart"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_b_uart_pins>; - }; -}; - -&audio_data{ - status = "okay"; -}; From 00f6381291bc7d7293ceba3fb78cfbedb56c3cf7 Mon Sep 17 00:00:00 2001 From: long yu Date: Thu, 21 Feb 2019 15:22:01 +0800 Subject: [PATCH 0561/1060] storage: emmc: Add HS400 busmode support for G12B-RevB [1/1] PD#SWPL-5040 Problem: not support HS400 busmode Solution: add HS400 busmode support for G12B-RevB Verify: T962X-R311,TL1-T962X2_X301,G12B-W400 Change-Id: I11a1f47b9473fa341c7d754a51d6e270551758a7 Signed-off-by: long yu Conflicts: arch/arm/boot/dts/amlogic/mesong12b.dtsi arch/arm64/boot/dts/amlogic/mesong12b.dtsi drivers/amlogic/mmc/aml_sd_emmc_v3.c drivers/mmc/core/mmc.c --- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 6 +- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 3 +- .../boot/dts/amlogic/g12b_a311d_w400.dts | 6 +- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 3 +- drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c | 2 +- drivers/amlogic/mmc/aml_sd_emmc.c | 16 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 303 +++++++++++++++++- drivers/mmc/core/mmc.c | 21 +- include/linux/amlogic/aml_sd_emmc_v3.h | 15 +- include/linux/amlogic/sd.h | 1 + include/linux/mmc/emmc_partitions.h | 8 + 11 files changed, 346 insertions(+), 38 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 6ec7307196ac..918d73b5fa97 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -1220,9 +1220,9 @@ /* "MMC_CAP_1_8V_DDR", */ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_A"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; f_max = <200000000>; }; diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index ad995402c1d1..46136a04e28a 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1460,9 +1460,10 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index d7016640831b..f4ba4b707225 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -1219,9 +1219,9 @@ /* "MMC_CAP_1_8V_DDR", */ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_A"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; f_max = <200000000>; }; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 5c76da13a913..14280a9e0a11 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1470,9 +1470,10 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c b/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c index 6ee8f916ee55..091278958054 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c +++ b/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c @@ -27,7 +27,7 @@ #include "g12a.h" static const char * const sd_emmc_parent_names[] = { "xtal", "fclk_div2", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0_pll" }; + "fclk_div3", "fclk_div5", "fclk_div2p5", "mpll2", "mpll3", "gp0_pll" }; static struct clk_mux sd_emmc_p0_mux_A = { .reg = (void *)HHI_SD_EMMC_CLK_CNTL, diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index c623bd291a0f..5a11b761ff5a 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3327,6 +3327,16 @@ static int meson_mmc_probe(struct platform_device *pdev) #endif /* CONFIG_MESON_CPU_EMULATOR */ } pr_info("%s() : success!\n", __func__); + if (host->ctrl_ver >= 3) { + ret = device_create_file(&pdev->dev, &dev_attr_emmc_eyetest); + if (ret) + dev_warn(mmc_dev(host->mmc), + "Unable to creat sysfs attributes\n"); + ret = device_create_file(&pdev->dev, &dev_attr_emmc_clktest); + if (ret) + dev_warn(mmc_dev(host->mmc), + "Unable to creat sysfs attributes\n"); + } return 0; free_host: @@ -3614,9 +3624,11 @@ static struct meson_mmc_data mmc_data_g12b = { .sdmmc.hs.core_phase = 1, .sdmmc.ddr.core_phase = 2, .sdmmc.ddr.tx_phase = 0, - .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.core_phase = 2, .sdmmc.hs2.tx_phase = 0, - .sdmmc.hs4.tx_delay = 0, + .sdmmc.hs4.tx_phase = 0, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, .sdmmc.sdr104.tx_phase = 0, diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index eac2a066ceb2..16cdcf16fe03 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -231,10 +231,34 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, if (aml_card_type_mmc(pdata)) { if ((clk_ios >= 200000000) && conf->ddr) { - src0_clk = devm_clk_get(host->dev, "clkin2"); + if (host->data->chip_type == MMC_CHIP_G12B) + src0_clk = devm_clk_get(host->dev, "clkin3"); + else + src0_clk = devm_clk_get(host->dev, "clkin2"); ret = clk_set_parent(host->mux_parent[0], src0_clk); if (ret) - pr_warn("set src0: div5 as comp0 parent error\n"); + pr_warn("set src0 as comp0 parent error\n"); + ret = clk_set_parent(host->mux_clk, + host->mux_parent[0]); + if (ret) + pr_warn("set comp0 as mux_clk parent error\n"); + } else if (((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) + && (clk_ios >= 166000000)) { + src0_clk = devm_clk_get(host->dev, "clkin3"); + if (ret) + pr_warn("not get clkin3\n"); + if (host->data->chip_type == MMC_CHIP_TL1) { + ret = clk_set_rate(src0_clk, 792000000); + if (ret) + pr_warn("not set tl1-792\n"); + } + pr_warn("set rate clkin3>>>>>>>>clk:%lu\n", + clk_get_rate(src0_clk)); + ret = clk_set_parent(host->mux_parent[0], + src0_clk); + if (ret) + pr_warn("set src0 as comp0 parent error\n"); ret = clk_set_parent(host->mux_clk, host->mux_parent[0]); if (ret) @@ -274,11 +298,11 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, pdata->stop_clk = 0; } #endif - pr_debug("actual_clock :%u, HHI_nand: 0x%x\n", + pr_info("actual_clock :%u, HHI_nand: 0x%x\n", mmc->actual_clock, readl(host->clksrc_base + (HHI_NAND_CLK_CNTL << 2))); - pr_debug("[%s] after clock: 0x%x\n", + pr_info("[%s] after clock: 0x%x\n", __func__, readl(host->base + SD_EMMC_CLOCK_V3)); return ret; @@ -315,6 +339,18 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, */ if (pdata->tx_delay != 0) clkc->tx_delay = pdata->tx_delay; + + if (((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) + && aml_card_type_mmc(pdata)) { + clkc->core_phase = para->hs4.core_phase; + clkc->tx_phase = para->hs4.tx_phase; + + irq_en |= (1<<17); + writel(irq_en, + host->base + SD_EMMC_IRQ_EN); + /*improve CMD setup time by half SD_CLK cycle*/ + } } pr_info("%s: try set sd/emmc to HS400 mode\n", mmc_hostname(host->mmc)); @@ -612,7 +648,7 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) } static int aml_sd_emmc_cali_v3(struct mmc_host *mmc, - u8 opcode, u8 *blk_test, u32 blksz, u32 blocks) + u8 opcode, u8 *blk_test, u32 blksz, u32 blocks, u8 *pattern) { struct amlsd_platform *pdata = mmc_priv(mmc); struct amlsd_host *host = pdata->host; @@ -623,7 +659,14 @@ static int aml_sd_emmc_cali_v3(struct mmc_host *mmc, struct scatterlist sg; cmd.opcode = opcode; - cmd.arg = ((SZ_1M * (36 + 3)) / 512); + if (!strcmp(pattern, MMC_PATTERN_NAME)) + cmd.arg = MMC_PATTERN_OFFSET; + else if (!strcmp(pattern, MMC_MAGIC_NAME)) + cmd.arg = MMC_MAGIC_OFFSET; + else if (!strcmp(pattern, MMC_RANDOM_NAME)) + cmd.arg = MMC_RANDOM_OFFSET; + else if (!strcmp(pattern, MMC_DTB_NAME)) + cmd.arg = MMC_DTB_OFFSET; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; stop.opcode = MMC_STOP_TRANSMISSION; @@ -647,6 +690,28 @@ static int aml_sd_emmc_cali_v3(struct mmc_host *mmc, return data.error | cmd.error; } +static int emmc_test_bus(struct mmc_host *mmc) +{ + int err = 0; + u32 blksz = 512; + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 40, MMC_PATTERN_NAME); + if (err) + return err; + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 80, MMC_RANDOM_NAME); + if (err) + return err; + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 40, MMC_MAGIC_NAME); + if (err) + return err; + return err; +} + static int emmc_send_cmd(struct mmc_host *mmc, u32 opcode, u32 arg, unsigned int flags) { @@ -721,7 +786,7 @@ RETRY: if (line_x < 9) aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, - host->blk_test, blksz, 40); + host->blk_test, blksz, 40, MMC_PATTERN_NAME); else aml_sd_emmc_cmd_v3(mmc); host->is_tunning = 0; @@ -991,7 +1056,6 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) struct amlsd_host *host = pdata->host; u32 intf3 = readl(host->base + SD_EMMC_INTF3); struct intf3 *gintf3 = (struct intf3 *)&(intf3); - u32 blksz = 512; int i, err = 0; int match[32]; int best_start = -1, best_size = -1; @@ -1006,19 +1070,17 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) emmc_ds_data_alignment(mmc); update_all_line_eyetest(mmc); host->is_tunning = 1; - for (i = 0; i < 32; i++) { - gintf3->ds_sht_m += 1; - writel(intf3, host->base + SD_EMMC_INTF3); - pdata->intf3 = intf3; - err = aml_sd_emmc_cali_v3(mmc, - MMC_READ_MULTIPLE_BLOCK, - host->blk_test, blksz, 20); + for (i = 0; i < 64; i++) { + err = emmc_test_bus(mmc); pr_debug("intf3: 0x%x, err[%d]: %d\n", readl(host->base + SD_EMMC_INTF3), i, err); if (!err) match[i] = 0; else match[i] = -1; + gintf3->ds_sht_m += 1; + writel(intf3, host->base + SD_EMMC_INTF3); + pdata->intf3 = intf3; } for (i = 0; i < 32; i++) { if (match[i] == 0) { @@ -1056,6 +1118,7 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) gintf3->ds_sht_m = best_start + best_size / 2; writel(intf3, host->base + SD_EMMC_INTF3); pdata->intf3 = intf3; + pdata->win_start = best_start; pr_info("ds_sht:%u, window:%d, intf3:0x%x, clock:0x%x", gintf3->ds_sht_m, best_size, readl(host->base + SD_EMMC_INTF3), @@ -1066,6 +1129,98 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) #endif +static int emmc_data_alignment(struct mmc_host *mmc, int best_size) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay1 = readl(host->base + SD_EMMC_DELAY1_V3); + u32 delay2 = readl(host->base + SD_EMMC_DELAY2_V3); + u32 intf3 = readl(host->base + SD_EMMC_INTF3); + struct intf3 *gintf3 = (struct intf3 *)&(intf3); + u32 delay1_bak = delay1; + u32 delay2_bak = delay2; + u32 intf3_bak = intf3; + int line_x, i, err = 0, win_new, blksz = 512; + u32 d[8]; + + host->is_tunning = 1; + gintf3->ds_sht_m = pdata->win_start + 4; + writel(intf3, host->base + SD_EMMC_INTF3); + for (line_x = 0; line_x < 8; line_x++) { + for (i = 0; i < 20; i++) { + if (line_x < 5) { + delay1 += (1 << 6*line_x); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + } else { + delay2 += (1 << 6*(line_x - 5)); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + } + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 40, MMC_RANDOM_NAME); + if (err) { + pr_info("[%s]adjust line_x[%d]:%d\n", + __func__, line_x, i); + d[line_x] = i; + delay1 = delay1_bak; + delay2 = delay2_bak; + writel(delay1_bak, + host->base + SD_EMMC_DELAY1_V3); + writel(delay2_bak, + host->base + SD_EMMC_DELAY2_V3); + break; + } + } + if (i == 20) { + pr_info("[%s][%d] return set default value", + __func__, __LINE__); + writel(delay1_bak, host->base + SD_EMMC_DELAY1_V3); + writel(delay2_bak, host->base + SD_EMMC_DELAY2_V3); + writel(intf3_bak, host->base + SD_EMMC_INTF3); + host->is_tunning = 0; + return -1; + } + } + delay1 += (d[0]<<0)|(d[1]<<6)|(d[2]<<12)|(d[3]<<18)|(d[4]<<24); + delay2 += (d[5]<<0)|(d[6]<<6)|(d[7]<<12); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("delay1:0x%x, delay2:0x%x\n", + readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + gintf3->ds_sht_m = 0; + writel(intf3, host->base + SD_EMMC_INTF3); + win_new = emmc_ds_manual_sht(mmc); + if (win_new < best_size) { + pr_info("[%s][%d] win_new:%d < win_old:%d,set default!", + __func__, __LINE__, win_new, best_size); + writel(delay1_bak, host->base + SD_EMMC_DELAY1_V3); + writel(delay2_bak, host->base + SD_EMMC_DELAY2_V3); + writel(intf3_bak, host->base + SD_EMMC_INTF3); + pr_info("intf3:0x%x, delay1:0x%x, delay2:0x%x\n", + readl(host->base + SD_EMMC_INTF3), + readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + } + host->is_tunning = 0; + return 0; +} + +static void aml_emmc_hs400_Revb(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay2 = 0; + int win_size = 0; + + delay2 = readl(host->base + SD_EMMC_DELAY2_V3); + delay2 += (pdata->cmd_c<<24); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("[%s], delay1: 0x%x, delay2: 0x%x\n", + __func__, readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + win_size = emmc_ds_manual_sht(mmc); + emmc_data_alignment(mmc, win_size); +} /* test clock, return delay cells for one cycle */ static unsigned int aml_sd_emmc_clktest(struct mmc_host *mmc) @@ -1383,6 +1538,50 @@ RETRY: return 0; } +int aml_emmc_hs200_tl1(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 vclkc = readl(host->base + SD_EMMC_CLOCK_V3); + struct sd_emmc_clock_v3 *clkc = (struct sd_emmc_clock_v3 *)&vclkc; + struct para_e *para = &(host->data->sdmmc); + u32 clk_bak = 0; + u32 delay2 = 0, count = 0; + int i, err = 0; + + clk_bak = vclkc; + clkc->tx_phase = para->hs4.tx_phase; + clkc->core_phase = para->hs4.core_phase; + clkc->tx_delay = para->hs4.tx_delay; + if (pdata->tx_delay != 0) + clkc->tx_delay = pdata->tx_delay; + writel(vclkc, host->base + SD_EMMC_CLOCK_V3); + pr_info("[%s][%d] clk config:0x%x\n", + __func__, __LINE__, readl(host->base + SD_EMMC_CLOCK_V3)); + for (i = 0; i < 63; i++) { + delay2 += (1 << 24); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + err = emmc_eyetest_log(mmc, 9); + if (err) + continue; + count = fbinary(pdata->align[9]); + if (((count >= 10) && (count <= 22)) + || ((count >= 45) && (count <= 56))) + break; + } + if (i == 63) + pr_err("[%s]no find cmd timing\n", __func__); + pdata->cmd_c = (delay2 >> 24); + pr_info("cmd->u64eyet:0x%016llx\n", + pdata->align[9]); + writel(0, host->base + SD_EMMC_DELAY2_V3); + writel(clk_bak, host->base + SD_EMMC_CLOCK_V3); + pr_info("[%s][%d] clk config:0x%x\n", + __func__, __LINE__, readl(host->base + SD_EMMC_CLOCK_V3)); + return 0; + +} + int __attribute__((unused)) aml_emmc_hs200_timming(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); @@ -1643,6 +1842,9 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) intf3 |= (1<<22); writel(intf3, (host->base + SD_EMMC_INTF3)); pdata->intf3 = intf3; + if ((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) + aml_emmc_hs200_tl1(mmc); err = 0; } @@ -1657,7 +1859,76 @@ int aml_post_hs400_timming(struct mmc_host *mmc) { int ret = 0; aml_sd_emmc_clktest(mmc); - ret = emmc_ds_manual_sht(mmc); + if (host->data->chip_type == MMC_CHIP_TL1) + aml_emmc_hs400_tl1(mmc); + else if (host->data->chip_type == MMC_CHIP_G12B) + aml_emmc_hs400_Revb(mmc); + else + aml_emmc_hs400_general(mmc); return 0; } +ssize_t emmc_eyetest_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct amlsd_host *host = dev_get_drvdata(dev); + struct mmc_host *mmc = host->mmc; + + mmc_claim_host(mmc); + update_all_line_eyetest(mmc); + mmc_release_host(mmc); + return sprintf(buf, "%s\n", "Emmc all lines eyetest.\n"); +} + +ssize_t emmc_clktest_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct amlsd_host *host = dev_get_drvdata(dev); + struct mmc_host *mmc = host->mmc; + u32 intf3 = readl(host->base + SD_EMMC_INTF3); + struct intf3 *gintf3 = (struct intf3 *)&(intf3); + u32 clktest = 0, delay_cell = 0, clktest_log = 0, count = 0; + u32 vcfg = readl(host->base + SD_EMMC_CFG); + int i = 0; + unsigned int cycle = 0; + + writel(0, (host->base + SD_EMMC_ADJUST_V3)); + + /* one cycle = xxx(ps) */ + cycle = (1000000000 / mmc->actual_clock) * 1000; + vcfg &= ~(1 << 23); + writel(vcfg, host->base + SD_EMMC_CFG); + gintf3->clktest_exp = 8; + gintf3->clktest_on_m = 1; + writel(intf3, host->base + SD_EMMC_INTF3); + clktest_log = readl(host->base + SD_EMMC_CLKTEST_LOG); + clktest = readl(host->base + SD_EMMC_CLKTEST_OUT); + while (!(clktest_log & 0x80000000)) { + udelay(1); + i++; + clktest_log = readl(host->base + SD_EMMC_CLKTEST_LOG); + clktest = readl(host->base + SD_EMMC_CLKTEST_OUT); + if (i > 4000) { + pr_warn("[%s] [%d] emmc clktest error\n", + __func__, __LINE__); + break; + } + } + if (clktest_log & 0x80000000) { + clktest = readl(host->base + SD_EMMC_CLKTEST_OUT); + count = clktest / (1 << 8); + if (vcfg & 0x4) + delay_cell = ((cycle / 2) / count); + else + delay_cell = (cycle / count); + } + pr_info("%s [%d] clktest : %u, delay_cell: %d, count: %u\n", + __func__, __LINE__, clktest, delay_cell, count); + intf3 = readl(host->base + SD_EMMC_INTF3); + gintf3->clktest_on_m = 0; + writel(intf3, host->base + SD_EMMC_INTF3); + vcfg = readl(host->base + SD_EMMC_CFG); + vcfg |= (1 << 23); + writel(vcfg, host->base + SD_EMMC_CFG); + return count; +} diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 20eb4014953f..2cc865d03902 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1131,7 +1131,10 @@ static int mmc_select_hs400(struct mmc_card *card) unsigned int max_dtr; int err = 0; u8 val; - +#ifdef CONFIG_AMLOGIC_MMC + u8 raw_driver_strength = card->ext_csd.raw_driver_strength; + u8 ds = (host->caps >> 23) & 0x7; +#endif /* * HS400 mode requires 8-bit bus width */ @@ -1175,13 +1178,25 @@ static int mmc_select_hs400(struct mmc_card *card) /* Switch card to HS400 */ #ifdef CONFIG_AMLOGIC_MMC - if (card->ext_csd.raw_driver_strength & (1 << 4)) { + if (ds) { + if (ds & (1 << 0)) { + raw_driver_strength &= (1 << 0); + pr_info("%s:use ds type0\n", + mmc_hostname(host)); + /*3 -> type4 -> MMC_CAP_DRIVER_TYPED*/ + } else if (ds & (1 << 3)) { + raw_driver_strength &= ~(1 << 1); + pr_info("%s:use ds type4\n", + mmc_hostname(host)); + } + } + if (raw_driver_strength & (1 << 1)) { val = (0x4 << EXT_CSD_DRV_STR_SHIFT) | EXT_CSD_TIMING_HS400; pr_info("%s: support driver strength type 4\n", mmc_hostname(host)); - } else if (card->ext_csd.raw_driver_strength & (1 << 1)) { + } else if (raw_driver_strength & (1 << 4)) { val = (0x1 << EXT_CSD_DRV_STR_SHIFT) | EXT_CSD_TIMING_HS400; diff --git a/include/linux/amlogic/aml_sd_emmc_v3.h b/include/linux/amlogic/aml_sd_emmc_v3.h index 8e9d96e02562..de6dab799145 100644 --- a/include/linux/amlogic/aml_sd_emmc_v3.h +++ b/include/linux/amlogic/aml_sd_emmc_v3.h @@ -29,15 +29,14 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id); int aml_post_hs400_timming(struct mmc_host *mmc); -/* extern ssize_t emmc_eyetest_show(struct device *dev, - * struct device_attribute *attr, char *buf); - */ +extern ssize_t emmc_eyetest_show(struct device *dev, + struct device_attribute *attr, char *buf); -/* extern ssize_t emmc_clktest_show(struct device *dev, - * struct device_attribute *attr, char *buf); - */ -/* DEVICE_ATTR(emmc_eyetest, S_IRUGO, emmc_eyetest_show, NULL);*/ -/*DEVICE_ATTR(emmc_clktest, S_IRUGO, emmc_clktest_show, NULL);*/ +extern ssize_t emmc_clktest_show(struct device *dev, + struct device_attribute *attr, char *buf); + +DEVICE_ATTR(emmc_eyetest, 0444, emmc_eyetest_show, NULL); +DEVICE_ATTR(emmc_clktest, 0444, emmc_clktest_show, NULL); #endif diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 0e01cdd02032..9cdf7151807c 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -282,6 +282,7 @@ struct amlsd_platform { unsigned int dly1; unsigned int dly2; unsigned int intf3; + unsigned int win_start; unsigned int irq_sdio_sleep; unsigned int clock; /* signalling voltage (1.8V or 3.3V) */ diff --git a/include/linux/mmc/emmc_partitions.h b/include/linux/mmc/emmc_partitions.h index aea6f695827b..e9adda0e4819 100644 --- a/include/linux/mmc/emmc_partitions.h +++ b/include/linux/mmc/emmc_partitions.h @@ -25,6 +25,14 @@ #define SZ_1M 0x00100000 +#define MMC_PATTERN_NAME "pattern" +#define MMC_PATTERN_OFFSET ((SZ_1M*(36+3))/512) +#define MMC_MAGIC_NAME "magic" +#define MMC_MAGIC_OFFSET ((SZ_1M*(36+6))/512) +#define MMC_RANDOM_NAME "random" +#define MMC_RANDOM_OFFSET ((SZ_1M*(36+7))/512) +#define MMC_DTB_NAME "dtb" +#define MMC_DTB_OFFSET ((SZ_1M*(36+4))/512) /* the size of bootloader partition */ #define MMC_BOOT_PARTITION_SIZE (4*SZ_1M) From 8e0290520c9c43fb7b81d8332ab68e3a53fc9703 Mon Sep 17 00:00:00 2001 From: long yu Date: Mon, 25 Mar 2019 17:46:07 +0800 Subject: [PATCH 0562/1060] emmc: backward compatible with all HS400 clock sources [1/1] PD#SWPL-6294 Problem: TL1 and G12B uses clkin3,TXLX uses clkin2 Solution: unifying the HS400 source clock name in DTS Verify: TL1-T962X2_X301 G12B-Reva G12B-Revb Change-Id: I7acaf7b4392d757955f43a0b17ac1fad84f53d26 Signed-off-by: Long Yu Conflicts: arch/arm/boot/dts/amlogic/mesontm2.dtsi arch/arm64/boot/dts/amlogic/mesontm2.dtsi --- arch/arm/boot/dts/amlogic/mesong12b.dtsi | 3 +-- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 3 +-- arch/arm64/boot/dts/amlogic/mesong12b.dtsi | 3 +-- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 3 +-- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 20 ++++++++++---------- 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 46136a04e28a..d8de3401792d 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -1460,10 +1460,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 9fc0d76c0a8d..71a34fac554b 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1264,9 +1264,8 @@ <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, <&clkc CLKID_FCLK_DIV2P5>, - <&clkc CLKID_GP0_PLL>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index 14280a9e0a11..52dfb944a987 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -1470,10 +1470,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 1985984093f5..c04adf1ac279 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1246,9 +1246,8 @@ <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, <&clkc CLKID_FCLK_DIV2P5>, - <&clkc CLKID_GP0_PLL>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 16cdcf16fe03..56e3871ddddd 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -231,10 +231,9 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, if (aml_card_type_mmc(pdata)) { if ((clk_ios >= 200000000) && conf->ddr) { - if (host->data->chip_type == MMC_CHIP_G12B) - src0_clk = devm_clk_get(host->dev, "clkin3"); - else - src0_clk = devm_clk_get(host->dev, "clkin2"); + src0_clk = devm_clk_get(host->dev, "clkin2"); + if (ret) + pr_warn("not get clkin2\n"); ret = clk_set_parent(host->mux_parent[0], src0_clk); if (ret) pr_warn("set src0 as comp0 parent error\n"); @@ -245,16 +244,17 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, } else if (((host->data->chip_type == MMC_CHIP_TL1) || (host->data->chip_type == MMC_CHIP_G12B)) && (clk_ios >= 166000000)) { - src0_clk = devm_clk_get(host->dev, "clkin3"); + src0_clk = devm_clk_get(host->dev, "clkin2"); if (ret) - pr_warn("not get clkin3\n"); - if (host->data->chip_type == MMC_CHIP_TL1) { + pr_warn("not get clkin2\n"); + if ((host->data->chip_type == MMC_CHIP_TL1) + && (clk_ios <= 198000000)) { ret = clk_set_rate(src0_clk, 792000000); if (ret) - pr_warn("not set tl1-792\n"); + pr_warn("not set tl1-gp0\n"); } - pr_warn("set rate clkin3>>>>>>>>clk:%lu\n", - clk_get_rate(src0_clk)); + pr_warn("set rate clkin2>>>>>>>>clk:%lu\n", + clk_get_rate(src0_clk)); ret = clk_set_parent(host->mux_parent[0], src0_clk); if (ret) From a96b816a30c0f538f48ecb231c0a6fedb5393e7d Mon Sep 17 00:00:00 2001 From: Long Yu Date: Mon, 15 Apr 2019 16:40:25 +0800 Subject: [PATCH 0563/1060] emmc: Clear the value of txdelay in legacy mode on the resume process [1/1] PD#SWPL-7181 Problem: switch to high-speed from hs200 failed for resume process. Solution: set tx_delay as 0 for legacy mode. clear cfg_cmd_setup Verify: verify by TL1 Change-Id: I5dbb1bbc391da864464bf137837a2b0f54ccda42 Signed-off-by: Long Yu Conflicts: arch/arm/boot/dts/amlogic/mesontl1.dtsi arch/arm64/boot/dts/amlogic/mesontl1.dtsi --- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 56e3871ddddd..c00fcb4b3853 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -392,6 +392,11 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->tx_phase = para->sdr104.tx_phase; } else { ctrl->ddr = 0; + clkc->tx_delay = 0; + clkc->core_phase = para->init.core_phase; + clkc->tx_phase = para->init.tx_phase; + irq_en &= ~(1<<17); + writel(irq_en, host->base + SD_EMMC_IRQ_EN); /* timing == MMC_TIMING_LEGACY */ if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; From faad940baf39231fa056eb93c8eac41057119f93 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 26 Sep 2018 09:12:30 +0800 Subject: [PATCH 0564/1060] cec: for support multi-logical address [1/2] PD#SWPL-418 Problem: cec: for support mult-logical address Solution: 1.add interface: remove logical address 2.for support multi-logical address Verify: r311 r321 Change-Id: I9ea8b1004f43fb84855d41dd684c117fa5cbd7ae Signed-off-by: Yong Qin Conflicts: drivers/amlogic/cec/hdmi_ao_cec.c drivers/amlogic/cec/hdmi_ao_cec.h --- drivers/amlogic/cec/hdmi_ao_cec.c | 179 ++++++++++-------------------- drivers/amlogic/cec/hdmi_ao_cec.h | 7 +- 2 files changed, 63 insertions(+), 123 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 90ac72ffdf76..820a69f1e534 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -575,7 +575,6 @@ void cecb_irq_handle(void) static irqreturn_t cecb_isr(int irq, void *dev_instance) { - /*CEC_INFO("cecb_isr\n");*/ cecb_irq_handle(); return IRQ_HANDLED; } @@ -608,7 +607,7 @@ static void ao_cecb_init(void) hdmirx_set_bits_top(TOP_EDID_GEN_CNTL, EDID_AUTO_CEC_EN, 11, 1); /* enable all cec irq */ - /*cec_irq_enable(true);*/ + cec_irq_enable(true); /* clear all wake up source */ hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0); /* cec enable */ @@ -652,7 +651,7 @@ static void ao_cecb_init(void) /* Release SW reset */ cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); - if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) { + if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { reg = 0; reg |= (0 << 6);/*curb_err_init*/ reg |= (0 << 5);/*en_chk_sbitlow*/ @@ -661,7 +660,7 @@ static void ao_cecb_init(void) } /* Enable all AO_CECB interrupt sources */ - /*cec_irq_enable(true);*/ + cec_irq_enable(true); hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK); } } @@ -693,7 +692,7 @@ void eecec_irq_enable(bool enable) writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN) & ~CECB_IRQ_EN_MASK, cec_dev->cec_reg + AO_CECB_INTR_MASKN); - CEC_INFO("cecb enable:int mask:0x%x\n", + CEC_INFO("ao enable:int mask:0x%x\n", readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)); } } @@ -727,8 +726,7 @@ int cecrx_hw_init(void) return 0; } */ - -int dump_cecrx_reg(char *b) +static int dump_cecrx_reg(char *b) { int i = 0, s = 0; unsigned char reg; @@ -908,7 +906,7 @@ void cec_logicaddr_set(int l_add) /* save logical address for suspend/wake up */ cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4); cec_dev->cec_info.addr_enable = (1 << l_add); - if (ee_cec == CEC_B) { + if (ee_cec) { /* set ee_cec logical addr */ if (l_add < 8) hdmirx_cec_write(DWC_CEC_ADDR_L, 1 << l_add); @@ -935,6 +933,7 @@ void cec_logicaddr_set(int l_add) } void ceca_addr_add(unsigned int l_add) + { unsigned int addr; unsigned int i; @@ -942,7 +941,7 @@ void ceca_addr_add(unsigned int l_add) /* check if the logical addr is exist ? */ for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { addr = aocec_rd_reg(i); - if ((addr & 0x10) && ((addr & 0xf) == (l_add & 0xf))) { + if ((addr & 0xf) == (l_add & 0xf)) { CEC_INFO("add 0x%x exist\n", l_add); return; } @@ -976,7 +975,7 @@ void cecb_addr_add(unsigned int l_add) hdmirx_cec_write(DWC_CEC_ADDR_L, addr); } else { addr = hdmirx_cec_read(DWC_CEC_ADDR_H); - addr |= (1 << (l_add - 8)); + addr |= (1 << (l_add - 8))|0x80; hdmirx_cec_write(DWC_CEC_ADDR_H, addr); } CEC_INFO("cec b add addr %d\n", l_add); @@ -984,21 +983,18 @@ void cecb_addr_add(unsigned int l_add) void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add) { - /* save logical address for suspend/wake up */ - cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4); - - if (cec_sel == CEC_B) + if (cec_sel) cecb_addr_add(l_add); else ceca_addr_add(l_add); } -void cec_logicaddr_remove(unsigned int cec_sel, unsigned int l_add) +void cec_logicaddr_remove(unsigned int l_add) { unsigned int addr; unsigned int i; - if (cec_sel == CEC_B) { + if (ee_cec) { if (l_add < 8) { addr = hdmirx_cec_read(DWC_CEC_ADDR_L); addr &= ~(1 << l_add); @@ -1024,50 +1020,45 @@ void cec_logicaddr_remove(unsigned int cec_sel, unsigned int l_add) } } -void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en) +void cec_restore_logical_addr(unsigned int addr_en) { unsigned int i; unsigned int addr_enable = addr_en; - cec_clear_all_logical_addr(cec_sel); + cec_clear_all_logical_addr(ee_cec); for (i = 0; i < 15; i++) { if (addr_enable & 0x1) - cec_logicaddr_add(cec_sel, i); + cec_logicaddr_add(ee_cec, i); addr_enable = addr_enable >> 1; } } -void ceca_hw_reset(void) +void cec_hw_reset(void) { - writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); - /* Enable gated clock (Normal mode). */ - cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1); - /* Release SW reset */ - udelay(100); - cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); - - /* Enable all AO_CEC interrupt sources */ - /*cec_irq_enable(true);*/ - - /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ - - /* Cec arbitration 3/5/7 bit time set. */ - cec_arbit_bit_time_set(3, 0x118, 0); - cec_arbit_bit_time_set(5, 0x000, 0); - cec_arbit_bit_time_set(7, 0x2aa, 0); -} - -void cec_hw_reset(unsigned int cec_sel) -{ - if (cec_sel == CEC_B) { + if (ee_cec) { ao_cecb_init(); /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ } else { - ceca_hw_reset(); + writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); + /* Enable gated clock (Normal mode). */ + cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1); + /* Release SW reset */ + udelay(100); + cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); + + /* Enable all AO_CEC interrupt sources */ + cec_irq_enable(true); + + /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ + + /* Cec arbitration 3/5/7 bit time set. */ + cec_arbit_bit_time_set(3, 0x118, 0); + cec_arbit_bit_time_set(5, 0x000, 0); + cec_arbit_bit_time_set(7, 0x2aa, 0); } /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ - cec_restore_logical_addr(cec_sel, cec_dev->cec_info.addr_enable); + cec_restore_logical_addr(cec_dev->cec_info.addr_enable); } void cec_rx_buf_clear(void) @@ -1119,9 +1110,9 @@ void cec_clear_all_logical_addr(unsigned int cec_sel) { CEC_INFO("clear all logical addr\n"); - if (cec_sel == CEC_B) { + if (cec_sel) { hdmirx_cec_write(DWC_CEC_ADDR_L, 0); - hdmirx_cec_write(DWC_CEC_ADDR_H, 0); + hdmirx_cec_write(DWC_CEC_ADDR_H, 0x80); } else { aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); aocec_wr_reg(CEC_LOGICAL_ADDR1, 0); @@ -1171,10 +1162,7 @@ int cec_rx_buf_check(void) if (ee_cec == CEC_B) { cecrx_check_irq_enable(); cecb_irq_handle(); - } else { - rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG); - if (rx_num_msg) - CEC_INFO("rx msg num:0x%02x\n", rx_num_msg); + return 0; } return rx_num_msg; } @@ -1416,7 +1404,7 @@ int cec_ll_tx(const unsigned char *msg, unsigned char len) * address already set. Must clear it before poll again */ if (is_poll_message(msg[0])) - cec_clear_all_logical_addr(cec_sel); + cec_clear_all_logical_addr(ee_cec); /* * for CEC CTS 9.3. Android will try 3 poll message if got NACK @@ -1451,7 +1439,7 @@ try_again: return CEC_FAIL_BUSY; } - if (cec_sel == CEC_B) + if (ee_cec) ret = cecb_trigle_tx(msg, len); else ret = ceca_trigle_tx(msg, len); @@ -1592,7 +1580,7 @@ static void ao_ceca_init(void) cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); /* Enable all AO_CEC interrupt sources */ - /*cec_irq_enable(true);*/ + cec_irq_enable(true); cec_arbit_bit_time_set(3, 0x118, 0); cec_arbit_bit_time_set(5, 0x000, 0); @@ -1695,7 +1683,7 @@ unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag) /* void cec_keep_reset(void) { - if (ee_cec == CEC_B) + if (ee_cec) cecb_hw_reset(); else writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); @@ -1714,21 +1702,16 @@ static void cec_pre_init(void) wake_ok = 0; pr_info("cec: wake up flag:%x\n", reg); - if (cec_dev->cec_num > 1) { - ao_ceca_init(); + if (ee_cec) { ao_cecb_init(); + /*cec_logicaddr_set(cec_dev->cec_info.log_addr);*/ } else { - if (ee_cec == CEC_B) - ao_cecb_init(); - else - ao_ceca_init(); + ao_ceca_init(); } //need restore all logical address - if (cec_dev->cec_num > 1) - cec_restore_logical_addr(CEC_B, cec_dev->cec_info.addr_enable); - else - cec_restore_logical_addr(ee_cec, cec_dev->cec_info.addr_enable); + cec_restore_logical_addr(cec_dev->cec_info.addr_enable); + } static int cec_late_check_rx_buffer(void) @@ -2496,30 +2479,21 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, } else if (token && strncmp(token, "clraddr", 7) == 0) { cec_dev->cec_info.addr_enable = 0; cec_clear_all_logical_addr(ee_cec); - } else if (token && strncmp(token, "clralladdr", 10) == 0) { - cec_dev->cec_info.addr_enable = 0; - cec_clear_all_logical_addr(0); - cec_clear_all_logical_addr(1); } else if (token && strncmp(token, "addaddr", 7) == 0) { token = strsep(&cur, delim); /*string to int*/ if (!token || kstrtouint(token, 16, &addr) < 0) return count; cec_dev->cec_info.addr_enable |= (1 << (addr & 0xf)); - if (cec_dev->cec_num > 1) - cec_logicaddr_add(CEC_B, addr); - else - cec_logicaddr_add(ee_cec, addr); + cec_logicaddr_add(ee_cec, addr); } else if (token && strncmp(token, "rmaddr", 6) == 0) { token = strsep(&cur, delim); /*string to int*/ if (!token || kstrtouint(token, 16, &addr) < 0) return count; + cec_dev->cec_info.addr_enable &= ~(1 << (addr & 0xf)); - if (cec_dev->cec_num > 1) - cec_logicaddr_remove(CEC_B, addr); - else - cec_logicaddr_remove(ee_cec, addr); + cec_logicaddr_remove(addr); } else { if (token) CEC_ERR("no cmd:%s\n", token); @@ -2714,8 +2688,6 @@ void cec_dump_info(void) struct hdmi_port_info *port; CEC_ERR("driver date:%s\n", CEC_DRIVER_VERSION); - CEC_ERR("chip type:0x%x\n", - get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR)); CEC_ERR("cec sel:%d\n", ee_cec); CEC_ERR("cec_num:%d\n", cec_dev->cec_num); CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); @@ -2743,33 +2715,15 @@ void cec_dump_info(void) kfree(port); } - if (cec_dev->cec_num > 1) { + if (ee_cec) { CEC_ERR("addrL 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_L)); CEC_ERR("addrH 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_H)); - + } else { CEC_ERR("addr0 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0)); CEC_ERR("addr1 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR1)); CEC_ERR("addr2 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR2)); CEC_ERR("addr3 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR3)); CEC_ERR("addr4 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR4)); - } else { - if (ee_cec == CEC_B) { - CEC_ERR("addrL 0x%x\n", - hdmirx_cec_read(DWC_CEC_ADDR_L)); - CEC_ERR("addrH 0x%x\n", - hdmirx_cec_read(DWC_CEC_ADDR_H)); - } else { - CEC_ERR("addr0 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR0)); - CEC_ERR("addr1 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR1)); - CEC_ERR("addr2 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR2)); - CEC_ERR("addr3 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR3)); - CEC_ERR("addr4 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR4)); - } } CEC_ERR("addr_enable:0x%x\n", cec_dev->cec_info.addr_enable); } @@ -2939,11 +2893,7 @@ static long hdmitx_cec_ioctl(struct file *f, case CEC_IOC_ADD_LOGICAL_ADDR: tmp = arg & 0xf; /*cec_logicaddr_set(tmp);*/ - /*cec_logicaddr_add(ee_cec, tmp);*/ - if (cec_dev->cec_num > 1) - cec_logicaddr_add(CEC_B, tmp); - else - cec_logicaddr_add(ee_cec, tmp); + cec_logicaddr_add(ee_cec, tmp); cec_dev->cec_info.addr_enable |= (1 << tmp); /* add by hal, to init some data structure */ @@ -2955,10 +2905,7 @@ static long hdmitx_cec_ioctl(struct file *f, break; case CEC_IOC_CLR_LOGICAL_ADDR: - if (cec_dev->cec_num > 1) - cec_clear_all_logical_addr(CEC_B); - else - cec_clear_all_logical_addr(ee_cec); + cec_clear_all_logical_addr(ee_cec); cec_dev->cec_info.addr_enable = 0; break; @@ -3436,16 +3383,15 @@ static int aml_cec_probe(struct platform_device *pdev) CEC_ERR("irq cnt:%d\n", of_irq_count(node)); if (of_get_property(node, "interrupt-names", NULL)) { r = of_property_read_string(node, "interrupt-names", &irq_name); - if (cec_dev->cec_num > 1) { - /* request two int source */ - CEC_ERR("request_irq two irq src\n"); - r = request_irq(cec_dev->irq_ceca, &ceca_isr, - IRQF_SHARED, irq_name, (void *)cec_dev); + if (!r && !ee_cec) { + r = request_irq(irq_idx, &ceca_isr, IRQF_SHARED, + irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("aocec irq request fail\n"); - - r = request_irq(cec_dev->irq_cecb, &cecb_isr, - IRQF_SHARED, irq_name, (void *)cec_dev); + } + if (!r && ee_cec) { + r = request_irq(irq_idx, &cecb_isr, IRQF_SHARED, + irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("cecb irq request fail\n"); } else { @@ -3581,10 +3527,7 @@ static int aml_cec_suspend_noirq(struct device *dev) int ret = 0; CEC_INFO("cec suspend noirq\n"); - if (cec_dev->cec_num > 1) - cec_clear_all_logical_addr(CEC_B); - else - cec_clear_all_logical_addr(ee_cec); + cec_clear_all_logical_addr(ee_cec); if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev); diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 9ea6ec37170f..04e35ad35a9f 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -541,11 +541,8 @@ void aocec_irq_enable(bool enable); extern void dump_reg(void); #endif extern void cec_dump_info(void); -extern void cec_hw_reset(unsigned int cec_sel); -extern void cec_restore_logical_addr(unsigned int cec_sel, - unsigned int addr_en); +extern void cec_hw_reset(void); +extern void cec_restore_logical_addr(unsigned int addr_en); extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); extern void cec_clear_all_logical_addr(unsigned int cec_sel); -extern int dump_cecrx_reg(char *b); - #endif /* __AO_CEC_H__ */ From 42565ac96b46a8140636bdc8fc606ffeb5bec0a1 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 26 Sep 2018 09:14:40 +0800 Subject: [PATCH 0565/1060] cec: for support multi-logical address [2/2] PD#SWPL-418 Problem: cec: support multi-logical address Solution: 1.enable cec_a, cec_b 2.enable two interrupt 3.enable two pinmux oa_7, ao_8 4.cec_a only send all msg 5.cec_b only receive all msg 6.discard ceca broadcast msg Verify: r311 r321 Change-Id: I8f983ed6ad329ca5ec0144587a7ad1f03ad68031 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/cec/hdmi_ao_cec.c --- drivers/amlogic/cec/hdmi_ao_cec.c | 211 +++++++++++++++++++++--------- drivers/amlogic/cec/hdmi_ao_cec.h | 5 +- 2 files changed, 151 insertions(+), 65 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 820a69f1e534..3f1fe333bb57 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -242,8 +242,7 @@ unsigned int waiting_aocec_free(unsigned int r) while (readl(cec_dev->cec_reg + r) & (1<<23)) {\ if (cnt++ == 3500) { \ pr_info("waiting aocec %x free time out\n", r);\ - if (cec_dev->proble_finish) \ - cec_hw_reset(CEC_A);\ + cec_hw_reset(CEC_A);\ break;\ } \ } \ @@ -575,6 +574,7 @@ void cecb_irq_handle(void) static irqreturn_t cecb_isr(int irq, void *dev_instance) { + /*CEC_INFO("cecb_isr\n");*/ cecb_irq_handle(); return IRQ_HANDLED; } @@ -692,7 +692,7 @@ void eecec_irq_enable(bool enable) writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN) & ~CECB_IRQ_EN_MASK, cec_dev->cec_reg + AO_CECB_INTR_MASKN); - CEC_INFO("ao enable:int mask:0x%x\n", + CEC_INFO("cecb enable:int mask:0x%x\n", readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)); } } @@ -906,7 +906,7 @@ void cec_logicaddr_set(int l_add) /* save logical address for suspend/wake up */ cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4); cec_dev->cec_info.addr_enable = (1 << l_add); - if (ee_cec) { + if (ee_cec == CEC_B) { /* set ee_cec logical addr */ if (l_add < 8) hdmirx_cec_write(DWC_CEC_ADDR_L, 1 << l_add); @@ -975,7 +975,7 @@ void cecb_addr_add(unsigned int l_add) hdmirx_cec_write(DWC_CEC_ADDR_L, addr); } else { addr = hdmirx_cec_read(DWC_CEC_ADDR_H); - addr |= (1 << (l_add - 8))|0x80; + addr |= (1 << (l_add - 8)); hdmirx_cec_write(DWC_CEC_ADDR_H, addr); } CEC_INFO("cec b add addr %d\n", l_add); @@ -983,18 +983,18 @@ void cecb_addr_add(unsigned int l_add) void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add) { - if (cec_sel) + if (cec_sel == CEC_B) cecb_addr_add(l_add); else ceca_addr_add(l_add); } -void cec_logicaddr_remove(unsigned int l_add) +void cec_logicaddr_remove(unsigned int cec_sel, unsigned int l_add) { unsigned int addr; unsigned int i; - if (ee_cec) { + if (cec_sel == CEC_B) { if (l_add < 8) { addr = hdmirx_cec_read(DWC_CEC_ADDR_L); addr &= ~(1 << l_add); @@ -1020,45 +1020,50 @@ void cec_logicaddr_remove(unsigned int l_add) } } -void cec_restore_logical_addr(unsigned int addr_en) +void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en) { unsigned int i; unsigned int addr_enable = addr_en; - cec_clear_all_logical_addr(ee_cec); + cec_clear_all_logical_addr(cec_sel); for (i = 0; i < 15; i++) { if (addr_enable & 0x1) - cec_logicaddr_add(ee_cec, i); + cec_logicaddr_add(cec_sel, i); addr_enable = addr_enable >> 1; } } -void cec_hw_reset(void) +void ceca_hw_reset(void) { - if (ee_cec) { + writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); + /* Enable gated clock (Normal mode). */ + cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1); + /* Release SW reset */ + udelay(100); + cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); + + /* Enable all AO_CEC interrupt sources */ + cec_irq_enable(true); + + /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ + + /* Cec arbitration 3/5/7 bit time set. */ + cec_arbit_bit_time_set(3, 0x118, 0); + cec_arbit_bit_time_set(5, 0x000, 0); + cec_arbit_bit_time_set(7, 0x2aa, 0); +} + +void cec_hw_reset(unsigned int cec_sel) +{ + if (cec_sel == CEC_B) { ao_cecb_init(); /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ } else { - writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); - /* Enable gated clock (Normal mode). */ - cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1); - /* Release SW reset */ - udelay(100); - cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); - - /* Enable all AO_CEC interrupt sources */ - cec_irq_enable(true); - - /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ - - /* Cec arbitration 3/5/7 bit time set. */ - cec_arbit_bit_time_set(3, 0x118, 0); - cec_arbit_bit_time_set(5, 0x000, 0); - cec_arbit_bit_time_set(7, 0x2aa, 0); + ceca_hw_reset(); } /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ - cec_restore_logical_addr(cec_dev->cec_info.addr_enable); + cec_restore_logical_addr(cec_sel, cec_dev->cec_info.addr_enable); } void cec_rx_buf_clear(void) @@ -1110,9 +1115,9 @@ void cec_clear_all_logical_addr(unsigned int cec_sel) { CEC_INFO("clear all logical addr\n"); - if (cec_sel) { + if (cec_sel == CEC_B) { hdmirx_cec_write(DWC_CEC_ADDR_L, 0); - hdmirx_cec_write(DWC_CEC_ADDR_H, 0x80); + hdmirx_cec_write(DWC_CEC_ADDR_H, 0); } else { aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); aocec_wr_reg(CEC_LOGICAL_ADDR1, 0); @@ -1162,7 +1167,10 @@ int cec_rx_buf_check(void) if (ee_cec == CEC_B) { cecrx_check_irq_enable(); cecb_irq_handle(); - return 0; + } else { + rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG); + if (rx_num_msg) + CEC_INFO("rx msg num:0x%02x\n", rx_num_msg); } return rx_num_msg; } @@ -1404,7 +1412,7 @@ int cec_ll_tx(const unsigned char *msg, unsigned char len) * address already set. Must clear it before poll again */ if (is_poll_message(msg[0])) - cec_clear_all_logical_addr(ee_cec); + cec_clear_all_logical_addr(cec_sel); /* * for CEC CTS 9.3. Android will try 3 poll message if got NACK @@ -1439,7 +1447,7 @@ try_again: return CEC_FAIL_BUSY; } - if (ee_cec) + if (cec_sel == CEC_B) ret = cecb_trigle_tx(msg, len); else ret = ceca_trigle_tx(msg, len); @@ -1683,7 +1691,7 @@ unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag) /* void cec_keep_reset(void) { - if (ee_cec) + if (ee_cec == CEC_B) cecb_hw_reset(); else writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); @@ -1702,16 +1710,21 @@ static void cec_pre_init(void) wake_ok = 0; pr_info("cec: wake up flag:%x\n", reg); - if (ee_cec) { - ao_cecb_init(); - /*cec_logicaddr_set(cec_dev->cec_info.log_addr);*/ - } else { + if (cec_dev->cec_num > 1) { ao_ceca_init(); + ao_cecb_init(); + } else { + if (ee_cec == CEC_B) + ao_cecb_init(); + else + ao_ceca_init(); } //need restore all logical address - cec_restore_logical_addr(cec_dev->cec_info.addr_enable); - + if (cec_dev->cec_num > 1) + cec_restore_logical_addr(CEC_B, cec_dev->cec_info.addr_enable); + else + cec_restore_logical_addr(ee_cec, cec_dev->cec_info.addr_enable); } static int cec_late_check_rx_buffer(void) @@ -2159,7 +2172,37 @@ static ssize_t port_num_show(struct class *cla, static ssize_t dump_reg_show(struct class *cla, struct class_attribute *attr, char *b) { - return dump_cecrx_reg(b); + int i, s = 0; + + if (ee_cec == CEC_B) + return dump_cecrx_reg(b); + + s += sprintf(b + s, "TX buffer:\n"); + for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) + s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i)); + + for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) { + s += sprintf(b + s, "%s:%2x\n", + cec_reg_name1[i], aocec_rd_reg(i + 0x10)); + } + + s += sprintf(b + s, "RX buffer:\n"); + for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) + s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i + 0x80)); + + for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) { + s += sprintf(b + s, "%s:%2x\n", + cec_reg_name2[i], aocec_rd_reg(i + 0x90)); + } + + if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { + for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) { + s += sprintf(b + s, "%s:%2x\n", + ceca_reg_name3[i], aocec_rd_reg(i + 0xA0)); + } + } + + return s; } static ssize_t arc_port_show(struct class *cla, @@ -2479,21 +2522,30 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, } else if (token && strncmp(token, "clraddr", 7) == 0) { cec_dev->cec_info.addr_enable = 0; cec_clear_all_logical_addr(ee_cec); + } else if (token && strncmp(token, "clralladdr", 10) == 0) { + cec_dev->cec_info.addr_enable = 0; + cec_clear_all_logical_addr(0); + cec_clear_all_logical_addr(1); } else if (token && strncmp(token, "addaddr", 7) == 0) { token = strsep(&cur, delim); /*string to int*/ if (!token || kstrtouint(token, 16, &addr) < 0) return count; cec_dev->cec_info.addr_enable |= (1 << (addr & 0xf)); - cec_logicaddr_add(ee_cec, addr); + if (cec_dev->cec_num > 1) + cec_logicaddr_add(CEC_B, addr); + else + cec_logicaddr_add(ee_cec, addr); } else if (token && strncmp(token, "rmaddr", 6) == 0) { token = strsep(&cur, delim); /*string to int*/ if (!token || kstrtouint(token, 16, &addr) < 0) return count; - cec_dev->cec_info.addr_enable &= ~(1 << (addr & 0xf)); - cec_logicaddr_remove(addr); + if (cec_dev->cec_num > 1) + cec_logicaddr_remove(CEC_B, addr); + else + cec_logicaddr_remove(ee_cec, addr); } else { if (token) CEC_ERR("no cmd:%s\n", token); @@ -2715,15 +2767,33 @@ void cec_dump_info(void) kfree(port); } - if (ee_cec) { + if (cec_dev->cec_num > 1) { CEC_ERR("addrL 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_L)); CEC_ERR("addrH 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_H)); - } else { + CEC_ERR("addr0 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0)); CEC_ERR("addr1 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR1)); CEC_ERR("addr2 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR2)); CEC_ERR("addr3 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR3)); CEC_ERR("addr4 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR4)); + } else { + if (ee_cec == CEC_B) { + CEC_ERR("addrL 0x%x\n", + hdmirx_cec_read(DWC_CEC_ADDR_L)); + CEC_ERR("addrH 0x%x\n", + hdmirx_cec_read(DWC_CEC_ADDR_H)); + } else { + CEC_ERR("addr0 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR0)); + CEC_ERR("addr1 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR1)); + CEC_ERR("addr2 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR2)); + CEC_ERR("addr3 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR3)); + CEC_ERR("addr4 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR4)); + } } CEC_ERR("addr_enable:0x%x\n", cec_dev->cec_info.addr_enable); } @@ -2894,6 +2964,10 @@ static long hdmitx_cec_ioctl(struct file *f, tmp = arg & 0xf; /*cec_logicaddr_set(tmp);*/ cec_logicaddr_add(ee_cec, tmp); + if (cec_dev->cec_num > 1) + cec_logicaddr_add(CEC_B, tmp); + else + cec_logicaddr_add(ee_cec, tmp); cec_dev->cec_info.addr_enable |= (1 << tmp); /* add by hal, to init some data structure */ @@ -2905,7 +2979,10 @@ static long hdmitx_cec_ioctl(struct file *f, break; case CEC_IOC_CLR_LOGICAL_ADDR: - cec_clear_all_logical_addr(ee_cec); + if (cec_dev->cec_num > 1) + cec_clear_all_logical_addr(CEC_B); + else + cec_clear_all_logical_addr(ee_cec); cec_dev->cec_info.addr_enable = 0; break; @@ -3203,6 +3280,7 @@ static int aml_cec_probe(struct platform_device *pdev) input_free_device(cec_dev->cec_info.remote_cec_dev); } +#ifdef CONFIG_OF /* config: read from dts */ r = of_property_read_u32(node, "cec_sel", &(cec_dev->cec_num)); if (r) { @@ -3383,15 +3461,16 @@ static int aml_cec_probe(struct platform_device *pdev) CEC_ERR("irq cnt:%d\n", of_irq_count(node)); if (of_get_property(node, "interrupt-names", NULL)) { r = of_property_read_string(node, "interrupt-names", &irq_name); - if (!r && !ee_cec) { - r = request_irq(irq_idx, &ceca_isr, IRQF_SHARED, - irq_name, (void *)cec_dev); + if (cec_dev->cec_num > 1) { + /* request two int source */ + CEC_ERR("request_irq two irq src\n"); + r = request_irq(cec_dev->irq_ceca, &ceca_isr, + IRQF_SHARED, irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("aocec irq request fail\n"); - } - if (!r && ee_cec) { - r = request_irq(irq_idx, &cecb_isr, IRQF_SHARED, - irq_name, (void *)cec_dev); + + r = request_irq(cec_dev->irq_cecb, &cecb_isr, + IRQF_SHARED, irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("cecb irq request fail\n"); } else { @@ -3411,12 +3490,15 @@ static int aml_cec_probe(struct platform_device *pdev) } } - last_cec_msg = devm_kzalloc(&pdev->dev, - sizeof(*last_cec_msg), GFP_KERNEL); - if (!last_cec_msg) { - CEC_ERR("allocate last_cec_msg failed\n"); - ret = -ENOMEM; - goto tag_cec_msg_alloc_err; + /* if (ee_cec == CEC_A) */ + { + last_cec_msg = devm_kzalloc(&pdev->dev, + sizeof(*last_cec_msg), GFP_KERNEL); + if (!last_cec_msg) { + CEC_ERR("allocate last_cec_msg failed\n"); + ret = -ENOMEM; + goto tag_cec_msg_alloc_err; + } } #ifdef CONFIG_HAS_EARLYSUSPEND @@ -3527,7 +3609,10 @@ static int aml_cec_suspend_noirq(struct device *dev) int ret = 0; CEC_INFO("cec suspend noirq\n"); - cec_clear_all_logical_addr(ee_cec); + if (cec_dev->cec_num > 1) + cec_clear_all_logical_addr(CEC_B); + else + cec_clear_all_logical_addr(ee_cec); if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev); diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 04e35ad35a9f..1be44c6b00b8 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -541,8 +541,9 @@ void aocec_irq_enable(bool enable); extern void dump_reg(void); #endif extern void cec_dump_info(void); -extern void cec_hw_reset(void); -extern void cec_restore_logical_addr(unsigned int addr_en); +extern void cec_hw_reset(unsigned int cec_sel); +extern void cec_restore_logical_addr(unsigned int cec_sel, + unsigned int addr_en); extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); extern void cec_clear_all_logical_addr(unsigned int cec_sel); #endif /* __AO_CEC_H__ */ From 472272230ea218fc4e3023d3ce26df4071e6d53f Mon Sep 17 00:00:00 2001 From: Lei Qian Date: Mon, 5 Nov 2018 20:22:13 +0800 Subject: [PATCH 0566/1060] cec: revert changesy [1/1] PD#SWPL-418 Problem: TXL can't bootup Solution: revert it Verify: p321 Revert "cec: for support multi-logical address [2/2]" This reverts commit cc185dc81dc63317c8498e7fcc4726c6f48ed03d. Revert "cec: for support multi-logical address [1/2]" This reverts commit b7922078ea9e7a8ce6cfb7592fb5293a5fd3e9a2. Change-Id: I1cef0ac194464d75ffff3fe765f15b5f944406b2 Signed-off-by: Lei Qian Conflicts: drivers/amlogic/cec/hdmi_ao_cec.c --- arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts | 7 +- arch/arm64/boot/dts/amlogic/atom.dts | 7 +- .../boot/dts/amlogic/txlx_t962e_r321.dts | 7 +- drivers/amlogic/cec/hdmi_ao_cec.c | 737 +++++------------- drivers/amlogic/cec/hdmi_ao_cec.h | 13 +- .../media/vin/tvin/hdmirx/hdmi_rx_drv.h | 2 +- .../media/vin/tvin/hdmirx/hdmi_rx_wrapper.c | 2 +- .../media/vout/hdmi_tx/hdmi_tx_cec_20.h | 1 - 8 files changed, 229 insertions(+), 547 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index 6c1350049843..ebd0bb8b8bcc 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -994,7 +994,6 @@ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <4>; /*all port number*/ /*ee_cec;*/ - cec_sel = <2>; output = <1>; /*output port number*/ /*arc support port:bit 0-3, according to portmap*/ arc_port_mask = <0x8>; @@ -1002,9 +1001,9 @@ 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec &hdmitx_aocecb1>; - pinctrl-1=<&hdmitx_aocec &hdmitx_aocecb1>; - pinctrl-2=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-0=<&hdmitx_aocec>; + pinctrl-1=<&hdmitx_aocecb>; + pinctrl-2=<&hdmitx_aocecb>; reg = <0xFF80023c 0x4 0xFF800000 0x400>; reg-names = "ao_exit","ao"; diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index 647052c5c84d..803c0ff619c8 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -992,16 +992,15 @@ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <4>; /*all port number*/ /*ee_cec;*/ - cec_sel = <2>; output = <1>; arc_port_mask = <0x8>; interrupts = <0 205 1 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec &hdmitx_aocecb1>; - pinctrl-1=<&hdmitx_aocec &hdmitx_aocecb1>; - pinctrl-2=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-0=<&hdmitx_aocec>; + pinctrl-1=<&hdmitx_aocecb>; + pinctrl-2=<&hdmitx_aocecb>; reg = <0x0 0xFF80023c 0x0 0x4 0x0 0xFF800000 0x0 0x400>; reg-names = "ao_exit","ao"; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index f66847df76bc..8377fd440860 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -993,7 +993,6 @@ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <4>; /*all port number*/ /*ee_cec;*/ - cec_sel = <2>; output = <1>; /*output port number*/ /*arc support port:bit 0-3, according to portmap*/ arc_port_mask = <0x8>; @@ -1001,9 +1000,9 @@ 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec &hdmitx_aocecb1>; - pinctrl-1=<&hdmitx_aocec &hdmitx_aocecb1>; - pinctrl-2=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-0=<&hdmitx_aocec>; + pinctrl-1=<&hdmitx_aocecb>; + pinctrl-2=<&hdmitx_aocecb>; reg = <0x0 0xFF80023c 0x0 0x4 0x0 0xFF800000 0x0 0x400>; reg-names = "ao_exit","ao"; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 3f1fe333bb57..bf9929de5552 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -98,15 +98,13 @@ struct ao_cec_dev { unsigned long dev_type; struct device_node *node; unsigned int port_num; /*total input hdmi port number*/ - unsigned int cec_num; unsigned int arc_port; unsigned int output; unsigned int hal_flag; unsigned int phy_addr; unsigned int port_seq; unsigned int cpu_type; - unsigned long irq_ceca; - unsigned long irq_cecb; + unsigned long irq_cec; void __iomem *exit_reg; void __iomem *cec_reg; void __iomem *hdmi_rxreg; @@ -242,7 +240,7 @@ unsigned int waiting_aocec_free(unsigned int r) while (readl(cec_dev->cec_reg + r) & (1<<23)) {\ if (cnt++ == 3500) { \ pr_info("waiting aocec %x free time out\n", r);\ - cec_hw_reset(CEC_A);\ + cec_hw_reset();\ break;\ } \ } \ @@ -396,7 +394,7 @@ void cec_dbg_init(void) stdbgflg.hal_cmd_bypass = 0; } -void cecb_hw_reset(void) +void cecrx_hw_reset(void) { /* cec disable */ if (!cec_dev->plat_data->ee_to_ao) @@ -422,7 +420,7 @@ static void cecrx_check_irq_enable(void) } } -static int cecb_trigle_tx(const unsigned char *msg, unsigned char len) +static int cecrx_trigle_tx(const unsigned char *msg, unsigned char len) { int i = 0, size = 0; int lock; @@ -433,7 +431,7 @@ static int cecb_trigle_tx(const unsigned char *msg, unsigned char len) lock = hdmirx_cec_read(DWC_CEC_LOCK); if (lock) { CEC_ERR("recevie msg in tx\n"); - cecb_irq_handle(); + cecrx_irq_handle(); return -1; } if (hdmirx_cec_read(DWC_CEC_CTRL) & 0x01) @@ -481,7 +479,7 @@ static inline void cecrx_clear_irq(unsigned int flags) writel(flags, cec_dev->cec_reg + AO_CECB_INTR_CLR); } -static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) +static int cec_pick_msg(unsigned char *msg, unsigned char *out_len) { int i, size; int len; @@ -506,7 +504,7 @@ static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) return 0; } -void cecb_irq_handle(void) +void cecrx_irq_handle(void) { uint32_t intr_cec; uint32_t lock; @@ -519,6 +517,8 @@ void cecb_irq_handle(void) if (intr_cec != 0) cecrx_clear_irq(intr_cec); + if (!ee_cec) + return; if (cec_dev->plat_data->ee_to_ao) shift = 16; /* TX DONE irq, increase tx buffer pointer */ @@ -529,7 +529,7 @@ void cecb_irq_handle(void) lock = hdmirx_cec_read(DWC_CEC_LOCK); /* EOM irq, message is coming */ if ((intr_cec & CEC_IRQ_RX_EOM) || lock) { - cecb_pick_msg(rx_msg, &rx_len); + cec_pick_msg(rx_msg, &rx_len); complete(&cec_dev->rx_ok); new_msg = 1; dwork = &cec_dev->cec_work; @@ -572,10 +572,9 @@ void cecb_irq_handle(void) } } -static irqreturn_t cecb_isr(int irq, void *dev_instance) +static irqreturn_t cecb_rx_isr(int irq, void *dev_instance) { - /*CEC_INFO("cecb_isr\n");*/ - cecb_irq_handle(); + cecrx_irq_handle(); return IRQ_HANDLED; } @@ -584,8 +583,107 @@ static void ao_cecb_init(void) unsigned long data32; unsigned int reg; - cecb_hw_reset(); + if (!cec_dev->plat_data->ee_to_ao) + return; + reg = (0 << 31) | + (0 << 30) | + (1 << 28) | /* clk_div0/clk_div1 in turn */ + ((732-1) << 12) | /* Div_tcnt1 */ + ((733-1) << 0); /* Div_tcnt0 */ + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + reg = (0 << 13) | + ((11-1) << 12) | + ((8-1) << 0); + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); + + reg = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + reg |= (1 << 31); + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + + udelay(200); + reg |= (1 << 30); + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + + reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + reg |= (0x01 << 14); /* xtal gate */ + writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + + data32 = 0; + data32 |= (7 << 12); /* filter_del */ + data32 |= (1 << 8); /* filter_tick: 1us */ + data32 |= (1 << 3); /* enable system clock */ + data32 |= 0 << 1; /* [2:1] cntl_clk: */ + /* 0=Disable clk (Power-off mode); */ + /* 1=Enable gated clock (Normal mode); */ + /* 2=Enable free-run clk (Debug mode). */ + data32 |= 1 << 0; /* [0] sw_reset: 1=Reset */ + writel(data32, cec_dev->cec_reg + AO_CECB_GEN_CNTL); + /* Enable gated clock (Normal mode). */ + cec_set_reg_bits(AO_CECB_GEN_CNTL, 1, 1, 1); + /* Release SW reset */ + cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); + + if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { + reg = 0; + reg |= (0 << 6);/*curb_err_init*/ + reg |= (0 << 5);/*en_chk_sbitlow*/ + reg |= (2 << 0);/*rise_del_max*/ + hdmirx_cec_write(DWC_CEC_CTRL2, reg); + } + + /* Enable all AO_CECB interrupt sources */ + cec_irq_enable(true); + hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK); +} + +void eecec_irq_enable(bool enable) +{ + if (cec_dev->cpu_type < MESON_CPU_MAJOR_ID_TXLX) { + if (enable) + hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, + EE_CEC_IRQ_EN_MASK); + else { + hdmirx_cec_write(DWC_AUD_CEC_ICLR, + (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | + EE_CEC_IRQ_EN_MASK)); + hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, + hdmirx_cec_read(DWC_AUD_CEC_IEN) & + ~EE_CEC_IRQ_EN_MASK); + hdmirx_cec_write(DWC_AUD_CEC_IEN_CLR, + (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | + EE_CEC_IRQ_EN_MASK)); + } + CEC_INFO("ee enable:int mask:0x%x\n", + hdmirx_cec_read(DWC_AUD_CEC_IEN)); + } else { + if (enable) + writel(CECB_IRQ_EN_MASK, + cec_dev->cec_reg + AO_CECB_INTR_MASKN); + else + writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN) + & ~CECB_IRQ_EN_MASK, + cec_dev->cec_reg + AO_CECB_INTR_MASKN); + CEC_INFO("ao move enable:int mask:0x%x\n", + readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)); + } +} + +void cec_irq_enable(bool enable) +{ + if (ee_cec) + eecec_irq_enable(enable); + else + aocec_irq_enable(enable); +} + +int cecrx_hw_init(void) +{ + unsigned int data32; + + if (!ee_cec) + return -1; + cecrx_hw_reset(); if (!cec_dev->plat_data->ee_to_ao) { /* set cec clk 32768k */ data32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL); @@ -612,120 +710,13 @@ static void ao_cecb_init(void) hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0); /* cec enable */ hdmirx_set_bits_dwc(DWC_DMI_DISABLE_IF, 1, 5, 1); - } else { - reg = (0 << 31) | - (0 << 30) | - (1 << 28) | /* clk_div0/clk_div1 in turn */ - ((732-1) << 12) |/* Div_tcnt1 */ - ((733-1) << 0); /* Div_tcnt0 */ - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - reg = (0 << 13) | - ((11-1) << 12) | - ((8-1) << 0); - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); - - reg = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - reg |= (1 << 31); - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - - udelay(200); - reg |= (1 << 30); - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - - reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - reg |= (0x01 << 14); /* xtal gate */ - writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - - data32 = 0; - data32 |= (7 << 12); /* filter_del */ - data32 |= (1 << 8); /* filter_tick: 1us */ - data32 |= (1 << 3); /* enable system clock */ - data32 |= 0 << 1; /* [2:1] cntl_clk: */ - /* 0=Disable clk (Power-off mode); */ - /* 1=Enable gated clock (Normal mode); */ - /* 2=Enable free-run clk (Debug mode). */ - data32 |= 1 << 0; /* [0] sw_reset: 1=Reset */ - writel(data32, cec_dev->cec_reg + AO_CECB_GEN_CNTL); - /* Enable gated clock (Normal mode). */ - cec_set_reg_bits(AO_CECB_GEN_CNTL, 1, 1, 1); - /* Release SW reset */ - cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); - - if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { - reg = 0; - reg |= (0 << 6);/*curb_err_init*/ - reg |= (0 << 5);/*en_chk_sbitlow*/ - reg |= (2 << 0);/*rise_del_max*/ - hdmirx_cec_write(DWC_CEC_CTRL2, reg); - } - - /* Enable all AO_CECB interrupt sources */ - cec_irq_enable(true); - hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK); - } -} - -void eecec_irq_enable(bool enable) -{ - if (cec_dev->cpu_type < MESON_CPU_MAJOR_ID_TXLX) { - if (enable) - hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, - EE_CEC_IRQ_EN_MASK); - else { - hdmirx_cec_write(DWC_AUD_CEC_ICLR, - (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | - EE_CEC_IRQ_EN_MASK)); - hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, - hdmirx_cec_read(DWC_AUD_CEC_IEN) & - ~EE_CEC_IRQ_EN_MASK); - hdmirx_cec_write(DWC_AUD_CEC_IEN_CLR, - (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | - EE_CEC_IRQ_EN_MASK)); - } - CEC_INFO("cecb enable:int mask:0x%x\n", - hdmirx_cec_read(DWC_AUD_CEC_IEN)); - } else { - if (enable) - writel(CECB_IRQ_EN_MASK, - cec_dev->cec_reg + AO_CECB_INTR_MASKN); - else - writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN) - & ~CECB_IRQ_EN_MASK, - cec_dev->cec_reg + AO_CECB_INTR_MASKN); - CEC_INFO("cecb enable:int mask:0x%x\n", - readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)); - } -} - -void cec_irq_enable(bool enable) -{ - if (cec_dev->cec_num > 1) { - eecec_irq_enable(enable); - aocec_irq_enable(enable); - } else { - if (ee_cec == CEC_B) - eecec_irq_enable(enable); - else - aocec_irq_enable(enable); - } -} - -/* -int cecrx_hw_init(void) -{ - unsigned int data32; - - if (ee_cec == CEC_A) - return -1; - - cecb_hw_reset(); - - ao_cecb_init(); + } else + ao_cecb_init(); cec_logicaddr_set(cec_dev->cec_info.log_addr); return 0; } -*/ + static int dump_cecrx_reg(char *b) { int i = 0, s = 0; @@ -905,137 +896,34 @@ void cec_logicaddr_set(int l_add) { /* save logical address for suspend/wake up */ cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4); - cec_dev->cec_info.addr_enable = (1 << l_add); - if (ee_cec == CEC_B) { + if (ee_cec) { /* set ee_cec logical addr */ if (l_add < 8) hdmirx_cec_write(DWC_CEC_ADDR_L, 1 << l_add); else - hdmirx_cec_write(DWC_CEC_ADDR_H, 1 << (l_add - 8)); + hdmirx_cec_write(DWC_CEC_ADDR_H, 1 << (l_add - 8)|0x80); CEC_INFO("set cecb logical addr:0x%x\n", l_add); - } else { - /*clear all logical address*/ - aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR1, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR2, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR3, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR4, 0); - cec_hw_buf_clear(); - aocec_wr_reg(CEC_LOGICAL_ADDR0, (l_add & 0xf)); - udelay(100); - aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | (l_add & 0xf)); - if (cec_msg_dbg_en) - CEC_INFO("set cec alogical addr:0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR0)); + return; } + aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); + cec_hw_buf_clear(); + aocec_wr_reg(CEC_LOGICAL_ADDR0, (l_add & 0xf)); + udelay(100); + aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | (l_add & 0xf)); + if (cec_msg_dbg_en) + CEC_INFO("set cec alogical addr:0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR0)); } -void ceca_addr_add(unsigned int l_add) - +void cec_hw_reset(void) { - unsigned int addr; - unsigned int i; - - /* check if the logical addr is exist ? */ - for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { - addr = aocec_rd_reg(i); - if ((addr & 0xf) == (l_add & 0xf)) { - CEC_INFO("add 0x%x exist\n", l_add); - return; - } + if (ee_cec) { + cecrx_hw_init(); + return; } - /* find a empty place */ - for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { - addr = aocec_rd_reg(i); - if (addr & 0x10) { - CEC_INFO(" skip 0x%x ,val=0x%x\n", i, addr); - continue; - } else { - cec_hw_buf_clear(); - aocec_wr_reg(i, (l_add & 0xf)); - udelay(100); - aocec_wr_reg(i, (l_add & 0xf)|0x10); - CEC_INFO("cec a add addr %d at 0x%x\n", - l_add, i); - break; - } - } -} - -void cecb_addr_add(unsigned int l_add) -{ - unsigned int addr; - - if (l_add < 8) { - addr = hdmirx_cec_read(DWC_CEC_ADDR_L); - addr |= (1 << l_add); - hdmirx_cec_write(DWC_CEC_ADDR_L, addr); - } else { - addr = hdmirx_cec_read(DWC_CEC_ADDR_H); - addr |= (1 << (l_add - 8)); - hdmirx_cec_write(DWC_CEC_ADDR_H, addr); - } - CEC_INFO("cec b add addr %d\n", l_add); -} - -void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add) -{ - if (cec_sel == CEC_B) - cecb_addr_add(l_add); - else - ceca_addr_add(l_add); -} - -void cec_logicaddr_remove(unsigned int cec_sel, unsigned int l_add) -{ - unsigned int addr; - unsigned int i; - - if (cec_sel == CEC_B) { - if (l_add < 8) { - addr = hdmirx_cec_read(DWC_CEC_ADDR_L); - addr &= ~(1 << l_add); - hdmirx_cec_write(DWC_CEC_ADDR_L, addr); - } else { - addr = hdmirx_cec_read(DWC_CEC_ADDR_H); - addr &= ~(1 << (l_add - 8)); - hdmirx_cec_write(DWC_CEC_ADDR_H, addr); - } - CEC_INFO("cec b remove addr %d\n", l_add); - } else { - for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { - addr = aocec_rd_reg(i); - if ((addr & 0xf) == (l_add & 0xf)) { - aocec_wr_reg(i, (addr & 0xf)); - udelay(100); - aocec_wr_reg(i, 0); - cec_hw_buf_clear(); - CEC_INFO("cec a rm addr %d at 0x%x\n", - l_add, i); - } - } - } -} - -void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en) -{ - unsigned int i; - unsigned int addr_enable = addr_en; - - cec_clear_all_logical_addr(cec_sel); - for (i = 0; i < 15; i++) { - if (addr_enable & 0x1) - cec_logicaddr_add(cec_sel, i); - - addr_enable = addr_enable >> 1; - } -} - -void ceca_hw_reset(void) -{ writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); /* Enable gated clock (Normal mode). */ cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1); @@ -1046,24 +934,15 @@ void ceca_hw_reset(void) /* Enable all AO_CEC interrupt sources */ cec_irq_enable(true); - /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ + cec_logicaddr_set(cec_dev->cec_info.log_addr); /* Cec arbitration 3/5/7 bit time set. */ cec_arbit_bit_time_set(3, 0x118, 0); cec_arbit_bit_time_set(5, 0x000, 0); cec_arbit_bit_time_set(7, 0x2aa, 0); -} -void cec_hw_reset(unsigned int cec_sel) -{ - if (cec_sel == CEC_B) { - ao_cecb_init(); - /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ - } else { - ceca_hw_reset(); - } - /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ - cec_restore_logical_addr(cec_sel, cec_dev->cec_info.addr_enable); + CEC_INFO("hw reset :logical addr:0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR0)); } void cec_rx_buf_clear(void) @@ -1111,21 +990,16 @@ static bool need_nack_repeat_msg(const unsigned char *msg, int len, int t) return false; } -void cec_clear_all_logical_addr(unsigned int cec_sel) +static void cec_clear_logical_addr(void) { - CEC_INFO("clear all logical addr\n"); + CEC_INFO("clear logical addr\n"); - if (cec_sel == CEC_B) { + if (ee_cec) { hdmirx_cec_write(DWC_CEC_ADDR_L, 0); - hdmirx_cec_write(DWC_CEC_ADDR_H, 0); - } else { + hdmirx_cec_write(DWC_CEC_ADDR_H, 0x80); + } else aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR1, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR2, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR3, 0); - aocec_wr_reg(CEC_LOGICAL_ADDR4, 0); - } - /*udelay(100);*/ + udelay(100); } void cec_enable_arc_pin(bool enable) @@ -1145,7 +1019,7 @@ void cec_enable_arc_pin(bool enable) if (enable) data |= 0x02; else - data &= 0xfffffffd; + data &= 0xffffffffd; wr_reg_hhi(HHI_HDMIRX_ARC_CNTL, data); CEC_INFO("set arc en:%d, reg:%x\n", enable, data); } else { @@ -1162,20 +1036,22 @@ EXPORT_SYMBOL(cec_enable_arc_pin); int cec_rx_buf_check(void) { - unsigned int rx_num_msg = 0; + unsigned int rx_num_msg; - if (ee_cec == CEC_B) { + if (ee_cec) { cecrx_check_irq_enable(); - cecb_irq_handle(); - } else { - rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG); - if (rx_num_msg) - CEC_INFO("rx msg num:0x%02x\n", rx_num_msg); + cecrx_irq_handle(); + return 0; } + + rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG); + if (rx_num_msg) + CEC_INFO("rx msg num:0x%02x\n", rx_num_msg); + return rx_num_msg; } -int ceca_rx_irq_handle(unsigned char *msg, unsigned char *len) +int cec_ll_rx(unsigned char *msg, unsigned char *len) { int i; int ret = -1; @@ -1192,16 +1068,6 @@ int ceca_rx_irq_handle(unsigned char *msg, unsigned char *len) return ret; } - /* when use two cec ip, cec a only send msg, discard all rx msg */ - if (cec_dev->cec_num > 1) { - writel((1 << 2), cec_dev->cec_reg + AO_CEC_INTR_CLR); - aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); - aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); - cec_rx_buf_clear(); - CEC_INFO("discard msg\n"); - return ret; - } - *len = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1; for (i = 0; i < (*len) && i < MAX_MSG; i++) @@ -1213,7 +1079,7 @@ int ceca_rx_irq_handle(unsigned char *msg, unsigned char *len) if (cec_msg_dbg_en && *len > 1) { pos = 0; pos += sprintf(msg_log_buf + pos, - "cec: rx len: %d dat: ", *len); + "CEC: rx msg len: %d dat: ", *len); for (i = 0; i < (*len); i++) pos += sprintf(msg_log_buf + pos, "%02x ", msg[i]); pos += sprintf(msg_log_buf + pos, "\n"); @@ -1233,7 +1099,7 @@ int ceca_rx_irq_handle(unsigned char *msg, unsigned char *len) /* using the cec pin as fiq gpi to assist the bus arbitration */ /* return value: 1: successful 0: error */ -static int ceca_trigle_tx(const unsigned char *msg, int len) +static int cec_ll_trigle_tx(const unsigned char *msg, int len) { int i; unsigned int n; @@ -1249,11 +1115,11 @@ static int ceca_trigle_tx(const unsigned char *msg, int len) break; if (!(j--)) { - CEC_INFO("ceca waiting busy timeout\n"); + CEC_INFO("waiting busy timeout\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); cec_timeout_cnt++; if (cec_timeout_cnt > 0x08) - cec_hw_reset(CEC_A); + cec_hw_reset(); break; } msleep(20); @@ -1270,7 +1136,7 @@ static int ceca_trigle_tx(const unsigned char *msg, int len) if (cec_msg_dbg_en) { pos = 0; pos += sprintf(msg_log_buf + pos, - "cec: tx len: %d dat: ", len); + "CEC: tx msg len: %d dat: ", len); for (n = 0; n < len; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg[n]); @@ -1288,7 +1154,7 @@ static int ceca_trigle_tx(const unsigned char *msg, int len) return -1; } -void ceca_tx_irq_handle(void) +void tx_irq_handle(void) { unsigned int tx_status = aocec_rd_reg(CEC_TX_MSG_STATUS); @@ -1306,12 +1172,9 @@ void ceca_tx_irq_handle(void) case TX_ERROR: if (cec_msg_dbg_en) - CEC_ERR("TX ERROR!\n"); + CEC_ERR("TX ERROR!!!\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); - ceca_hw_reset(); - if (cec_dev->cec_num <= 1) - cec_restore_logical_addr(CEC_A, - cec_dev->cec_info.addr_enable); + cec_hw_reset(); cec_tx_result = CEC_FAIL_NACK; break; @@ -1392,27 +1255,14 @@ static bool check_physical_addr_valid(int timeout) int cec_ll_tx(const unsigned char *msg, unsigned char len) { int ret = -1; - int t; + int t = msecs_to_jiffies(ee_cec ? 2000 : 5000); int retry = 2; - unsigned int cec_sel; - - /* only use cec a send msg */ - if (cec_dev->cec_num > 1) - cec_sel = CEC_A; - else - cec_sel = ee_cec; - - t = msecs_to_jiffies((cec_sel == CEC_B) ? 2000 : 5000); if (len == 0) return CEC_FAIL_NONE; - /* - * AO CEC controller will ack poll message itself if logical - * address already set. Must clear it before poll again - */ if (is_poll_message(msg[0])) - cec_clear_all_logical_addr(cec_sel); + cec_clear_logical_addr(); /* * for CEC CTS 9.3. Android will try 3 poll message if got NACK @@ -1421,7 +1271,7 @@ int cec_ll_tx(const unsigned char *msg, unsigned char len) * waveform seen on CEC bus. And did not pass CTS * specification of 9.3 */ - if ((cec_sel == CEC_A) && need_nack_repeat_msg(msg, len, t)) { + if (!ee_cec && need_nack_repeat_msg(msg, len, t)) { if (!memcmp(msg, last_cec_msg->msg, len)) { CEC_INFO("NACK repeat message:%x\n", len); return CEC_FAIL_NACK; @@ -1447,10 +1297,10 @@ try_again: return CEC_FAIL_BUSY; } - if (cec_sel == CEC_B) - ret = cecb_trigle_tx(msg, len); + if (ee_cec) + ret = cecrx_trigle_tx(msg, len); else - ret = ceca_trigle_tx(msg, len); + ret = cec_ll_trigle_tx(msg, len); if (ret < 0) { /* we should increase send idx if busy */ CEC_INFO("tx busy\n"); @@ -1468,7 +1318,7 @@ try_again: /* timeout or interrupt */ if (ret == 0) { CEC_ERR("tx timeout\n"); - cec_hw_reset(cec_sel); + cec_hw_reset(); } ret = CEC_FAIL_OTHER; } else { @@ -1483,7 +1333,7 @@ try_again: } mutex_unlock(&cec_dev->cec_mutex); - if (cec_sel == CEC_A) { + if (!ee_cec) { last_cec_msg->last_result = ret; if (ret == CEC_FAIL_NACK) { memcpy(last_cec_msg->msg, msg, len); @@ -1589,10 +1439,6 @@ static void ao_ceca_init(void) /* Enable all AO_CEC interrupt sources */ cec_irq_enable(true); - - cec_arbit_bit_time_set(3, 0x118, 0); - cec_arbit_bit_time_set(5, 0x000, 0); - cec_arbit_bit_time_set(7, 0x2aa, 0); } void cec_arbit_bit_time_set(unsigned int bit_set, @@ -1688,16 +1534,13 @@ unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag) return readl(cec_dev->cec_reg + AO_DEBUG_REG1); } -/* void cec_keep_reset(void) { - if (ee_cec == CEC_B) - cecb_hw_reset(); + if (ee_cec) + cecrx_hw_reset(); else writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); } -*/ - /* * cec hw module init before allocate logical address */ @@ -1710,21 +1553,15 @@ static void cec_pre_init(void) wake_ok = 0; pr_info("cec: wake up flag:%x\n", reg); - if (cec_dev->cec_num > 1) { - ao_ceca_init(); - ao_cecb_init(); + if (ee_cec) { + cecrx_hw_init(); } else { - if (ee_cec == CEC_B) - ao_cecb_init(); - else - ao_ceca_init(); - } + ao_ceca_init(); - //need restore all logical address - if (cec_dev->cec_num > 1) - cec_restore_logical_addr(CEC_B, cec_dev->cec_info.addr_enable); - else - cec_restore_logical_addr(ee_cec, cec_dev->cec_info.addr_enable); + cec_arbit_bit_time_set(3, 0x118, 0); + cec_arbit_bit_time_set(5, 0x000, 0); + cec_arbit_bit_time_set(7, 0x2aa, 0); + } } static int cec_late_check_rx_buffer(void) @@ -1738,7 +1575,7 @@ static int cec_late_check_rx_buffer(void) /* * start another check if rx buffer is full */ - if ((-1) == ceca_rx_irq_handle(rx_msg, &rx_len)) { + if ((-1) == cec_ll_rx(rx_msg, &rx_len)) { CEC_INFO("buffer got unrecorgnized msg\n"); cec_rx_buf_clear(); return 0; @@ -1983,7 +1820,7 @@ static void cec_rx_process(void) case CEC_OC_SET_STREAM_PATH: cec_set_stream_path(msg); /* wake up if in early suspend */ - if (cec_dev->cec_suspend != CEC_POWER_ON) + if (cec_dev->cec_suspend == CEC_EARLY_SUSPEND) cec_key_report(0); break; @@ -2005,7 +1842,7 @@ static void cec_rx_process(void) case CEC_OC_USER_CONTROL_PRESSED: /* wake up by key function */ - if (cec_dev->cec_suspend != CEC_POWER_ON) { + if (cec_dev->cec_suspend == CEC_EARLY_SUSPEND) { if (msg[2] == 0x40 || msg[2] == 0x6d) cec_key_report(0); } @@ -2074,19 +1911,18 @@ static void cec_task(struct work_struct *work) queue_delayed_work(cec_dev->cec_thread, dwork, CEC_FRAME_DELAY); } -static irqreturn_t ceca_isr(int irq, void *dev_instance) +static irqreturn_t ceca_isr_handler(int irq, void *dev_instance) { unsigned int intr_stat = 0; struct delayed_work *dwork; - /*CEC_INFO("ceca_isr\n");*/ dwork = &cec_dev->cec_work; intr_stat = cec_intr_stat(); if (intr_stat & (1<<1)) { /* aocec tx intr */ - ceca_tx_irq_handle(); + tx_irq_handle(); return IRQ_HANDLED; } - if ((-1) == ceca_rx_irq_handle(rx_msg, &rx_len)) + if ((-1) == cec_ll_rx(rx_msg, &rx_len)) return IRQ_HANDLED; complete(&cec_dev->rx_ok); @@ -2174,7 +2010,7 @@ static ssize_t dump_reg_show(struct class *cla, { int i, s = 0; - if (ee_cec == CEC_B) + if (ee_cec) return dump_cecrx_reg(b); s += sprintf(b + s, "TX buffer:\n"); @@ -2370,7 +2206,7 @@ static ssize_t fun_cfg_store(struct class *cla, struct class_attribute *attr, return -EINVAL; cec_config(val, 1); if (val == 0) - cec_clear_all_logical_addr(ee_cec);/*cec_keep_reset();*/ + cec_clear_logical_addr();/*cec_keep_reset();*/ else cec_pre_init(); return count; @@ -2512,40 +2348,6 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, CEC_ERR("wao addr:0x%x, val:0x%x", val, addr); } else if (token && strncmp(token, "preinit", 7) == 0) { cec_pre_init(); - } else if (token && strncmp(token, "setaddr", 7) == 0) { - token = strsep(&cur, delim); - /*string to int*/ - if (!token || kstrtouint(token, 16, &addr) < 0) - return count; - - cec_logicaddr_set(addr); - } else if (token && strncmp(token, "clraddr", 7) == 0) { - cec_dev->cec_info.addr_enable = 0; - cec_clear_all_logical_addr(ee_cec); - } else if (token && strncmp(token, "clralladdr", 10) == 0) { - cec_dev->cec_info.addr_enable = 0; - cec_clear_all_logical_addr(0); - cec_clear_all_logical_addr(1); - } else if (token && strncmp(token, "addaddr", 7) == 0) { - token = strsep(&cur, delim); - /*string to int*/ - if (!token || kstrtouint(token, 16, &addr) < 0) - return count; - cec_dev->cec_info.addr_enable |= (1 << (addr & 0xf)); - if (cec_dev->cec_num > 1) - cec_logicaddr_add(CEC_B, addr); - else - cec_logicaddr_add(ee_cec, addr); - } else if (token && strncmp(token, "rmaddr", 6) == 0) { - token = strsep(&cur, delim); - /*string to int*/ - if (!token || kstrtouint(token, 16, &addr) < 0) - return count; - cec_dev->cec_info.addr_enable &= ~(1 << (addr & 0xf)); - if (cec_dev->cec_num > 1) - cec_logicaddr_remove(CEC_B, addr); - else - cec_logicaddr_remove(ee_cec, addr); } else { if (token) CEC_ERR("no cmd:%s\n", token); @@ -2609,19 +2411,12 @@ static ssize_t hdmitx_cec_read(struct file *f, char __user *buf, if ((cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL))) rx_len = 0; - /*CEC_ERR("read msg start\n");*/ ret = wait_for_completion_timeout(&cec_dev->rx_ok, CEC_FRAME_DELAY); - if (ret <= 0) { - /*CEC_ERR("read msg ret=0\n");*/ + if (ret <= 0) return ret; - } - - if (rx_len == 0) { - /*CEC_ERR("read msg rx_len=0\n");*/ + if (rx_len == 0) return 0; - } - /*CEC_ERR("read msg end\n");*/ if (copy_to_user(buf, rx_msg, rx_len)) return -EINVAL; return rx_len; @@ -2739,9 +2534,6 @@ void cec_dump_info(void) { struct hdmi_port_info *port; - CEC_ERR("driver date:%s\n", CEC_DRIVER_VERSION); - CEC_ERR("cec sel:%d\n", ee_cec); - CEC_ERR("cec_num:%d\n", cec_dev->cec_num); CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); CEC_ERR("wk_logic_addr:0x%x\n", cec_dev->wakup_data.wk_logic_addr); CEC_ERR("wk_phy_addr:0x%x\n", cec_dev->wakup_data.wk_phy_addr); @@ -2766,36 +2558,6 @@ void cec_dump_info(void) init_cec_port_info(port, cec_dev); kfree(port); } - - if (cec_dev->cec_num > 1) { - CEC_ERR("addrL 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_L)); - CEC_ERR("addrH 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_H)); - - CEC_ERR("addr0 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0)); - CEC_ERR("addr1 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR1)); - CEC_ERR("addr2 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR2)); - CEC_ERR("addr3 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR3)); - CEC_ERR("addr4 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR4)); - } else { - if (ee_cec == CEC_B) { - CEC_ERR("addrL 0x%x\n", - hdmirx_cec_read(DWC_CEC_ADDR_L)); - CEC_ERR("addrH 0x%x\n", - hdmirx_cec_read(DWC_CEC_ADDR_H)); - } else { - CEC_ERR("addr0 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR0)); - CEC_ERR("addr1 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR1)); - CEC_ERR("addr2 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR2)); - CEC_ERR("addr3 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR3)); - CEC_ERR("addr4 0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR4)); - } - } - CEC_ERR("addr_enable:0x%x\n", cec_dev->cec_info.addr_enable); } static long hdmitx_cec_ioctl(struct file *f, @@ -2912,7 +2674,7 @@ static long hdmitx_cec_ioctl(struct file *f, cec_dev->hal_flag &= ~(tmp); CEC_INFO("disable CEC\n"); /*cec_keep_reset();*/ - cec_clear_all_logical_addr(ee_cec); + cec_clear_logical_addr(); } break; @@ -2962,28 +2724,18 @@ static long hdmitx_cec_ioctl(struct file *f, case CEC_IOC_ADD_LOGICAL_ADDR: tmp = arg & 0xf; - /*cec_logicaddr_set(tmp);*/ - cec_logicaddr_add(ee_cec, tmp); - if (cec_dev->cec_num > 1) - cec_logicaddr_add(CEC_B, tmp); - else - cec_logicaddr_add(ee_cec, tmp); - cec_dev->cec_info.addr_enable |= (1 << tmp); - + cec_logicaddr_set(tmp); /* add by hal, to init some data structure */ cec_dev->cec_info.log_addr = tmp; cec_dev->cec_info.power_status = POWER_ON; + cec_dev->cec_info.vendor_id = cec_dev->v_data.vendor_id; strncpy(cec_dev->cec_info.osd_name, cec_dev->v_data.cec_osd_string, 14); break; case CEC_IOC_CLR_LOGICAL_ADDR: - if (cec_dev->cec_num > 1) - cec_clear_all_logical_addr(CEC_B); - else - cec_clear_all_logical_addr(ee_cec); - cec_dev->cec_info.addr_enable = 0; + cec_clear_logical_addr(); break; case CEC_IOC_SET_DEV_TYPE: @@ -3170,15 +2922,6 @@ static const struct of_device_id aml_cec_dt_match[] = { }; #endif -static void cec_node_val_init(void) -{ - /* initial main logical address */ - cec_dev->cec_info.log_addr = 0; - /* all logical address disable */ - cec_dev->cec_info.addr_enable = 0; - cec_dev->cec_info.open_count.counter = 0; -} - static int aml_cec_probe(struct platform_device *pdev) { struct device *cdev; @@ -3186,7 +2929,7 @@ static int aml_cec_probe(struct platform_device *pdev) const struct of_device_id *of_id; #ifdef CONFIG_OF struct device_node *node = pdev->dev.of_node; - int r; + int irq_idx = 0, r; const char *irq_name = NULL; struct pinctrl *pin; struct vendor_info_data *vend; @@ -3250,7 +2993,7 @@ static int aml_cec_probe(struct platform_device *pdev) } else CEC_ERR("unable to get matched device\n"); - cec_node_val_init(); + cec_dev->cec_info.open_count.counter = 0; init_completion(&cec_dev->rx_ok); init_completion(&cec_dev->tx_ok); mutex_init(&cec_dev->cec_mutex); @@ -3281,20 +3024,11 @@ static int aml_cec_probe(struct platform_device *pdev) } #ifdef CONFIG_OF - /* config: read from dts */ - r = of_property_read_u32(node, "cec_sel", &(cec_dev->cec_num)); - if (r) { - CEC_ERR("not find 'port_num'\n"); - cec_dev->cec_num = 0; - } else { - CEC_ERR("use two cec ip\n"); - } - /* if using EE CEC */ if (of_property_read_bool(node, "ee_cec")) - ee_cec = CEC_B; + ee_cec = 1; else - ee_cec = CEC_A; + ee_cec = 0; CEC_ERR("using cec:%d\n", ee_cec); /* pinmux set */ if (of_get_property(node, "pinctrl-names", NULL)) { @@ -3305,7 +3039,7 @@ static int aml_cec_probe(struct platform_device *pdev) if (IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) CEC_ERR("get sleep state error!\n"); /*get active state*/ - if (ee_cec == CEC_B) { + if (ee_cec) { cec_dev->dbg_dev->pins->default_state = pinctrl_lookup_state(pin, "hdmitx_aocecb"); if (IS_ERR(cec_dev->dbg_dev->pins->default_state)) { @@ -3317,7 +3051,7 @@ static int aml_cec_probe(struct platform_device *pdev) CEC_ERR("get default error0\n"); CEC_ERR("use default cec\n"); /*force use default*/ - ee_cec = CEC_A; + ee_cec = 0; } } else { cec_dev->dbg_dev->pins->default_state = @@ -3330,7 +3064,6 @@ static int aml_cec_probe(struct platform_device *pdev) if (ret > 0) CEC_ERR("select state error:0x%x\n", ret); } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ao_exit"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -3341,8 +3074,7 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->exit_reg = (void *)base; } else - CEC_ERR("no ao_exit regs\n"); - + CEC_ERR("no ao_exit regs\n") res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ao"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -3366,8 +3098,7 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->hdmi_rxreg = (void *)base; } else - CEC_ERR("no hdmirx regs\n"); - + CEC_ERR("no hdmirx regs\n") res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -3389,8 +3120,7 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->periphs_reg = (void *)base; } else - CEC_ERR("no periphs regs\n"); - + CEC_ERR("no periphs regs\n") r = of_property_read_u32(node, "port_num", &(cec_dev->port_num)); if (r) { CEC_ERR("not find 'port_num'\n"); @@ -3450,48 +3180,32 @@ static int aml_cec_probe(struct platform_device *pdev) } if (of_irq_count(node) > 1) { - /* need enable two irq */ - cec_dev->irq_cecb = of_irq_get(node, 0);/*cecb int*/ - cec_dev->irq_ceca = of_irq_get(node, 1);/*ceca int*/ + if (ee_cec) + irq_idx = of_irq_get(node, 0); + else + irq_idx = of_irq_get(node, 1); } else { - cec_dev->irq_cecb = of_irq_get(node, 0); - cec_dev->irq_ceca = cec_dev->irq_cecb; + irq_idx = of_irq_get(node, 0); } - - CEC_ERR("irq cnt:%d\n", of_irq_count(node)); + cec_dev->irq_cec = irq_idx; + CEC_ERR("irq cnt:%d,cur no:%d\n", of_irq_count(node), irq_idx); if (of_get_property(node, "interrupt-names", NULL)) { r = of_property_read_string(node, "interrupt-names", &irq_name); - if (cec_dev->cec_num > 1) { - /* request two int source */ - CEC_ERR("request_irq two irq src\n"); - r = request_irq(cec_dev->irq_ceca, &ceca_isr, - IRQF_SHARED, irq_name, (void *)cec_dev); + if (!r && !ee_cec) { + r = request_irq(irq_idx, &ceca_isr_handler, IRQF_SHARED, + irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("aocec irq request fail\n"); - - r = request_irq(cec_dev->irq_cecb, &cecb_isr, - IRQF_SHARED, irq_name, (void *)cec_dev); + } + if (!r && ee_cec) { + r = request_irq(irq_idx, &cecb_rx_isr, IRQF_SHARED, + irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("cecb irq request fail\n"); - } else { - if (!r && (ee_cec == CEC_A)) { - r = request_irq(cec_dev->irq_ceca, &ceca_isr, - IRQF_SHARED, irq_name, (void *)cec_dev); - if (r < 0) - CEC_INFO("aocec irq request fail\n"); - } - - if (!r && (ee_cec == CEC_B)) { - r = request_irq(cec_dev->irq_cecb, &cecb_isr, - IRQF_SHARED, irq_name, (void *)cec_dev); - if (r < 0) - CEC_INFO("cecb irq request fail\n"); - } } } - /* if (ee_cec == CEC_A) */ - { + if (!ee_cec) { last_cec_msg = devm_kzalloc(&pdev->dev, sizeof(*last_cec_msg), GFP_KERNEL); if (!last_cec_msg) { @@ -3533,15 +3247,7 @@ static int aml_cec_probe(struct platform_device *pdev) return 0; tag_cec_msg_alloc_err: - if (cec_dev->cec_num > 1) { - free_irq(cec_dev->irq_ceca, (void *)cec_dev); - free_irq(cec_dev->irq_cecb, (void *)cec_dev); - } else { - if (ee_cec == CEC_B) - free_irq(cec_dev->irq_cecb, (void *)cec_dev); - else - free_irq(cec_dev->irq_ceca, (void *)cec_dev); - } + free_irq(cec_dev->irq_cec, (void *)cec_dev); tag_cec_reg_map_err: input_free_device(cec_dev->cec_info.remote_cec_dev); tag_cec_alloc_input_err: @@ -3562,15 +3268,7 @@ tag_cec_devm_err: static int aml_cec_remove(struct platform_device *pdev) { CEC_INFO("cec uninit!\n"); - if (cec_dev->cec_num > 1) { - free_irq(cec_dev->irq_ceca, (void *)cec_dev); - free_irq(cec_dev->irq_cecb, (void *)cec_dev); - } else { - if (ee_cec == CEC_B) - free_irq(cec_dev->irq_cecb, (void *)cec_dev); - else - free_irq(cec_dev->irq_ceca, (void *)cec_dev); - } + free_irq(cec_dev->irq_cec, (void *)cec_dev); kfree(last_cec_msg); if (cec_dev->cec_thread) { @@ -3609,11 +3307,6 @@ static int aml_cec_suspend_noirq(struct device *dev) int ret = 0; CEC_INFO("cec suspend noirq\n"); - if (cec_dev->cec_num > 1) - cec_clear_all_logical_addr(CEC_B); - else - cec_clear_all_logical_addr(ee_cec); - if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev); else diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 1be44c6b00b8..52d2458fa1f6 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -56,10 +56,6 @@ enum cecbver { #define L_1 1 #define L_2 2 #define L_3 3 - -#define CEC_A 0 -#define CEC_B 1 - /* #define CEC_FUNC_MASK 0 #define ONE_TOUCH_PLAY_MASK 1 @@ -532,7 +528,7 @@ int __attribute__((weak))hdmirx_get_connect_info(void) #ifdef CONFIG_AMLOGIC_AO_CEC unsigned int aocec_rd_reg(unsigned long addr); void aocec_wr_reg(unsigned long addr, unsigned long data); -void cecb_irq_handle(void); +void cecrx_irq_handle(void); void cec_logicaddr_set(int l_add); void cec_arbit_bit_time_set(unsigned int bit_set, unsigned int time_set, unsigned int flag); @@ -541,9 +537,6 @@ void aocec_irq_enable(bool enable); extern void dump_reg(void); #endif extern void cec_dump_info(void); -extern void cec_hw_reset(unsigned int cec_sel); -extern void cec_restore_logical_addr(unsigned int cec_sel, - unsigned int addr_en); -extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); -extern void cec_clear_all_logical_addr(unsigned int cec_sel); +extern void cec_hw_reset(void); + #endif /* __AO_CEC_H__ */ diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h index 1cf532ff9d86..456ea13d1623 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h @@ -472,7 +472,7 @@ extern void rx_send_hpd_pulse(void); /* irq */ extern void rx_irq_en(bool enable); extern irqreturn_t irq_handler(int irq, void *params); -extern void cecb_irq_handle(void); +extern void cecrx_irq_handle(void); /* user interface */ extern int pc_mode_en; diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c index bcc318d55c14..b672f283a685 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c @@ -311,7 +311,7 @@ static int hdmi_rx_ctrl_irq_handler(void) hdmirx_rd_dwc(DWC_AUD_CEC_ISTS) & hdmirx_rd_dwc(DWC_AUD_CEC_IEN); if (intr_aud_cec != 0) { - cecb_irq_handle(); + cecrx_irq_handle(); hdmirx_wr_dwc(DWC_AUD_CEC_ICLR, intr_aud_cec); } } diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h index 2e46deb17d8e..8689c9849a60 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h @@ -314,7 +314,6 @@ struct cec_global_info_t { unsigned int cec_version; unsigned char power_status; unsigned char log_addr; - unsigned int addr_enable; unsigned char menu_status; unsigned char osd_name[16]; struct input_dev *remote_cec_dev; /* cec input device */ From c0102386e4169b1ced3e4f446744c81243db25c5 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Tue, 6 Nov 2018 09:31:51 +0800 Subject: [PATCH 0567/1060] cec: for support multi-logical address [1/1] PD#SWPL-418 Problem: cec: support multi-logical address Solution: if working on multi-logical address, enable two ip 1.enable cec_a, cec_b 2.enable two interrupt 3.enable two pinmux oa_7, ao_8 4.cec_a only send all msg 5.cec_b only receive all msg 6.discard ceca broadcast msg Verify: r311 r321 p321 Change-Id: I1dc93429876ede951657102bcd7d41a500946719 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/cec/hdmi_ao_cec.c drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h --- arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts | 7 +- arch/arm64/boot/dts/amlogic/atom.dts | 7 +- .../boot/dts/amlogic/txlx_t962e_r321.dts | 7 +- drivers/amlogic/cec/hdmi_ao_cec.c | 741 +++++++++++++----- drivers/amlogic/cec/hdmi_ao_cec.h | 13 +- .../media/vin/tvin/hdmirx/hdmi_rx_drv.h | 4 +- .../media/vin/tvin/hdmirx/hdmi_rx_wrapper.c | 2 +- .../media/vout/hdmi_tx/hdmi_tx_cec_20.h | 1 + 8 files changed, 551 insertions(+), 231 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index ebd0bb8b8bcc..6c1350049843 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -994,6 +994,7 @@ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <4>; /*all port number*/ /*ee_cec;*/ + cec_sel = <2>; output = <1>; /*output port number*/ /*arc support port:bit 0-3, according to portmap*/ arc_port_mask = <0x8>; @@ -1001,9 +1002,9 @@ 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocecb>; + pinctrl-0=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-1=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-2=<&hdmitx_aocec &hdmitx_aocecb1>; reg = <0xFF80023c 0x4 0xFF800000 0x400>; reg-names = "ao_exit","ao"; diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index 803c0ff619c8..647052c5c84d 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -992,15 +992,16 @@ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <4>; /*all port number*/ /*ee_cec;*/ + cec_sel = <2>; output = <1>; arc_port_mask = <0x8>; interrupts = <0 205 1 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocecb>; + pinctrl-0=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-1=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-2=<&hdmitx_aocec &hdmitx_aocecb1>; reg = <0x0 0xFF80023c 0x0 0x4 0x0 0xFF800000 0x0 0x400>; reg-names = "ao_exit","ao"; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index 8377fd440860..f66847df76bc 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -993,6 +993,7 @@ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ port_num = <4>; /*all port number*/ /*ee_cec;*/ + cec_sel = <2>; output = <1>; /*output port number*/ /*arc support port:bit 0-3, according to portmap*/ arc_port_mask = <0x8>; @@ -1000,9 +1001,9 @@ 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocecb>; + pinctrl-0=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-1=<&hdmitx_aocec &hdmitx_aocecb1>; + pinctrl-2=<&hdmitx_aocec &hdmitx_aocecb1>; reg = <0x0 0xFF80023c 0x0 0x4 0x0 0xFF800000 0x0 0x400>; reg-names = "ao_exit","ao"; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index bf9929de5552..548ec1f412f5 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -98,13 +98,15 @@ struct ao_cec_dev { unsigned long dev_type; struct device_node *node; unsigned int port_num; /*total input hdmi port number*/ + unsigned int cec_num; unsigned int arc_port; unsigned int output; unsigned int hal_flag; unsigned int phy_addr; unsigned int port_seq; unsigned int cpu_type; - unsigned long irq_cec; + unsigned long irq_ceca; + unsigned long irq_cecb; void __iomem *exit_reg; void __iomem *cec_reg; void __iomem *hdmi_rxreg; @@ -240,7 +242,7 @@ unsigned int waiting_aocec_free(unsigned int r) while (readl(cec_dev->cec_reg + r) & (1<<23)) {\ if (cnt++ == 3500) { \ pr_info("waiting aocec %x free time out\n", r);\ - cec_hw_reset();\ + cec_hw_reset(CEC_A);\ break;\ } \ } \ @@ -394,7 +396,7 @@ void cec_dbg_init(void) stdbgflg.hal_cmd_bypass = 0; } -void cecrx_hw_reset(void) +void cecb_hw_reset(void) { /* cec disable */ if (!cec_dev->plat_data->ee_to_ao) @@ -420,7 +422,7 @@ static void cecrx_check_irq_enable(void) } } -static int cecrx_trigle_tx(const unsigned char *msg, unsigned char len) +static int cecb_trigle_tx(const unsigned char *msg, unsigned char len) { int i = 0, size = 0; int lock; @@ -431,7 +433,7 @@ static int cecrx_trigle_tx(const unsigned char *msg, unsigned char len) lock = hdmirx_cec_read(DWC_CEC_LOCK); if (lock) { CEC_ERR("recevie msg in tx\n"); - cecrx_irq_handle(); + cecb_irq_handle(); return -1; } if (hdmirx_cec_read(DWC_CEC_CTRL) & 0x01) @@ -479,7 +481,7 @@ static inline void cecrx_clear_irq(unsigned int flags) writel(flags, cec_dev->cec_reg + AO_CECB_INTR_CLR); } -static int cec_pick_msg(unsigned char *msg, unsigned char *out_len) +static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) { int i, size; int len; @@ -504,7 +506,7 @@ static int cec_pick_msg(unsigned char *msg, unsigned char *out_len) return 0; } -void cecrx_irq_handle(void) +void cecb_irq_handle(void) { uint32_t intr_cec; uint32_t lock; @@ -517,8 +519,6 @@ void cecrx_irq_handle(void) if (intr_cec != 0) cecrx_clear_irq(intr_cec); - if (!ee_cec) - return; if (cec_dev->plat_data->ee_to_ao) shift = 16; /* TX DONE irq, increase tx buffer pointer */ @@ -529,7 +529,7 @@ void cecrx_irq_handle(void) lock = hdmirx_cec_read(DWC_CEC_LOCK); /* EOM irq, message is coming */ if ((intr_cec & CEC_IRQ_RX_EOM) || lock) { - cec_pick_msg(rx_msg, &rx_len); + cecb_pick_msg(rx_msg, &rx_len); complete(&cec_dev->rx_ok); new_msg = 1; dwork = &cec_dev->cec_work; @@ -572,9 +572,10 @@ void cecrx_irq_handle(void) } } -static irqreturn_t cecb_rx_isr(int irq, void *dev_instance) +static irqreturn_t cecb_isr(int irq, void *dev_instance) { - cecrx_irq_handle(); + /*CEC_INFO("cecb_isr\n");*/ + cecb_irq_handle(); return IRQ_HANDLED; } @@ -583,107 +584,8 @@ static void ao_cecb_init(void) unsigned long data32; unsigned int reg; - if (!cec_dev->plat_data->ee_to_ao) - return; + cecb_hw_reset(); - reg = (0 << 31) | - (0 << 30) | - (1 << 28) | /* clk_div0/clk_div1 in turn */ - ((732-1) << 12) | /* Div_tcnt1 */ - ((733-1) << 0); /* Div_tcnt0 */ - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - reg = (0 << 13) | - ((11-1) << 12) | - ((8-1) << 0); - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); - - reg = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - reg |= (1 << 31); - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - - udelay(200); - reg |= (1 << 30); - writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - - reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - reg |= (0x01 << 14); /* xtal gate */ - writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - - data32 = 0; - data32 |= (7 << 12); /* filter_del */ - data32 |= (1 << 8); /* filter_tick: 1us */ - data32 |= (1 << 3); /* enable system clock */ - data32 |= 0 << 1; /* [2:1] cntl_clk: */ - /* 0=Disable clk (Power-off mode); */ - /* 1=Enable gated clock (Normal mode); */ - /* 2=Enable free-run clk (Debug mode). */ - data32 |= 1 << 0; /* [0] sw_reset: 1=Reset */ - writel(data32, cec_dev->cec_reg + AO_CECB_GEN_CNTL); - /* Enable gated clock (Normal mode). */ - cec_set_reg_bits(AO_CECB_GEN_CNTL, 1, 1, 1); - /* Release SW reset */ - cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); - - if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { - reg = 0; - reg |= (0 << 6);/*curb_err_init*/ - reg |= (0 << 5);/*en_chk_sbitlow*/ - reg |= (2 << 0);/*rise_del_max*/ - hdmirx_cec_write(DWC_CEC_CTRL2, reg); - } - - /* Enable all AO_CECB interrupt sources */ - cec_irq_enable(true); - hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK); -} - -void eecec_irq_enable(bool enable) -{ - if (cec_dev->cpu_type < MESON_CPU_MAJOR_ID_TXLX) { - if (enable) - hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, - EE_CEC_IRQ_EN_MASK); - else { - hdmirx_cec_write(DWC_AUD_CEC_ICLR, - (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | - EE_CEC_IRQ_EN_MASK)); - hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, - hdmirx_cec_read(DWC_AUD_CEC_IEN) & - ~EE_CEC_IRQ_EN_MASK); - hdmirx_cec_write(DWC_AUD_CEC_IEN_CLR, - (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | - EE_CEC_IRQ_EN_MASK)); - } - CEC_INFO("ee enable:int mask:0x%x\n", - hdmirx_cec_read(DWC_AUD_CEC_IEN)); - } else { - if (enable) - writel(CECB_IRQ_EN_MASK, - cec_dev->cec_reg + AO_CECB_INTR_MASKN); - else - writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN) - & ~CECB_IRQ_EN_MASK, - cec_dev->cec_reg + AO_CECB_INTR_MASKN); - CEC_INFO("ao move enable:int mask:0x%x\n", - readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)); - } -} - -void cec_irq_enable(bool enable) -{ - if (ee_cec) - eecec_irq_enable(enable); - else - aocec_irq_enable(enable); -} - -int cecrx_hw_init(void) -{ - unsigned int data32; - - if (!ee_cec) - return -1; - cecrx_hw_reset(); if (!cec_dev->plat_data->ee_to_ao) { /* set cec clk 32768k */ data32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL); @@ -710,13 +612,120 @@ int cecrx_hw_init(void) hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0); /* cec enable */ hdmirx_set_bits_dwc(DWC_DMI_DISABLE_IF, 1, 5, 1); - } else - ao_cecb_init(); + } else { + reg = (0 << 31) | + (0 << 30) | + (1 << 28) | /* clk_div0/clk_div1 in turn */ + ((732-1) << 12) |/* Div_tcnt1 */ + ((733-1) << 0); /* Div_tcnt0 */ + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + reg = (0 << 13) | + ((11-1) << 12) | + ((8-1) << 0); + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); + + reg = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + reg |= (1 << 31); + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + + udelay(200); + reg |= (1 << 30); + writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + + reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + reg |= (0x01 << 14); /* xtal gate */ + writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + + data32 = 0; + data32 |= (7 << 12); /* filter_del */ + data32 |= (1 << 8); /* filter_tick: 1us */ + data32 |= (1 << 3); /* enable system clock */ + data32 |= 0 << 1; /* [2:1] cntl_clk: */ + /* 0=Disable clk (Power-off mode); */ + /* 1=Enable gated clock (Normal mode); */ + /* 2=Enable free-run clk (Debug mode). */ + data32 |= 1 << 0; /* [0] sw_reset: 1=Reset */ + writel(data32, cec_dev->cec_reg + AO_CECB_GEN_CNTL); + /* Enable gated clock (Normal mode). */ + cec_set_reg_bits(AO_CECB_GEN_CNTL, 1, 1, 1); + /* Release SW reset */ + cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); + + if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { + reg = 0; + reg |= (0 << 6);/*curb_err_init*/ + reg |= (0 << 5);/*en_chk_sbitlow*/ + reg |= (2 << 0);/*rise_del_max*/ + hdmirx_cec_write(DWC_CEC_CTRL2, reg); + } + + /* Enable all AO_CECB interrupt sources */ + cec_irq_enable(true); + hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK); + } +} + +void eecec_irq_enable(bool enable) +{ + if (cec_dev->cpu_type < MESON_CPU_MAJOR_ID_TXLX) { + if (enable) + hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, + EE_CEC_IRQ_EN_MASK); + else { + hdmirx_cec_write(DWC_AUD_CEC_ICLR, + (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | + EE_CEC_IRQ_EN_MASK)); + hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, + hdmirx_cec_read(DWC_AUD_CEC_IEN) & + ~EE_CEC_IRQ_EN_MASK); + hdmirx_cec_write(DWC_AUD_CEC_IEN_CLR, + (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) | + EE_CEC_IRQ_EN_MASK)); + } + CEC_INFO("cecb enable:int mask:0x%x\n", + hdmirx_cec_read(DWC_AUD_CEC_IEN)); + } else { + if (enable) + writel(CECB_IRQ_EN_MASK, + cec_dev->cec_reg + AO_CECB_INTR_MASKN); + else + writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN) + & ~CECB_IRQ_EN_MASK, + cec_dev->cec_reg + AO_CECB_INTR_MASKN); + CEC_INFO("cecb enable:int mask:0x%x\n", + readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)); + } +} + +void cec_irq_enable(bool enable) +{ + if (cec_dev->cec_num > 1) { + eecec_irq_enable(enable); + aocec_irq_enable(enable); + } else { + if (ee_cec == CEC_B) + eecec_irq_enable(enable); + else + aocec_irq_enable(enable); + } +} + +/* +int cecrx_hw_init(void) +{ + unsigned int data32; + + if (ee_cec == CEC_A) + return -1; + + cecb_hw_reset(); + + ao_cecb_init(); cec_logicaddr_set(cec_dev->cec_info.log_addr); return 0; } - +*/ static int dump_cecrx_reg(char *b) { int i = 0, s = 0; @@ -896,34 +905,139 @@ void cec_logicaddr_set(int l_add) { /* save logical address for suspend/wake up */ cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4); - if (ee_cec) { + cec_dev->cec_info.addr_enable = (1 << l_add); + if (ee_cec == CEC_B) { /* set ee_cec logical addr */ if (l_add < 8) hdmirx_cec_write(DWC_CEC_ADDR_L, 1 << l_add); else - hdmirx_cec_write(DWC_CEC_ADDR_H, 1 << (l_add - 8)|0x80); + hdmirx_cec_write(DWC_CEC_ADDR_H, 1 << (l_add - 8)); CEC_INFO("set cecb logical addr:0x%x\n", l_add); + } else { + /*clear all logical address*/ + aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR1, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR2, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR3, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR4, 0); - return; + cec_hw_buf_clear(); + aocec_wr_reg(CEC_LOGICAL_ADDR0, (l_add & 0xf)); + udelay(100); + aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | (l_add & 0xf)); + if (cec_msg_dbg_en) + CEC_INFO("set cec alogical addr:0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR0)); } - aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); - cec_hw_buf_clear(); - aocec_wr_reg(CEC_LOGICAL_ADDR0, (l_add & 0xf)); - udelay(100); - aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | (l_add & 0xf)); - if (cec_msg_dbg_en) - CEC_INFO("set cec alogical addr:0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR0)); } -void cec_hw_reset(void) +void ceca_addr_add(unsigned int l_add) { - if (ee_cec) { - cecrx_hw_init(); - return; + unsigned int addr; + unsigned int i; + + /* check if the logical addr is exist ? */ + for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { + addr = aocec_rd_reg(i); + if ((addr & 0x10) && ((addr & 0xf) == (l_add & 0xf))) { + CEC_INFO("add 0x%x exist\n", l_add); + return; + } } + /* find a empty place */ + for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { + addr = aocec_rd_reg(i); + if (addr & 0x10) { + CEC_INFO(" skip 0x%x ,val=0x%x\n", i, addr); + continue; + } else { + cec_hw_buf_clear(); + aocec_wr_reg(i, (l_add & 0xf)); + udelay(100); + aocec_wr_reg(i, (l_add & 0xf)|0x10); + CEC_INFO("cec a add addr %d at 0x%x\n", + l_add, i); + break; + } + } +} + +void cecb_addr_add(unsigned int l_add) +{ + unsigned int addr; + + if (l_add < 8) { + addr = hdmirx_cec_read(DWC_CEC_ADDR_L); + addr |= (1 << l_add); + hdmirx_cec_write(DWC_CEC_ADDR_L, addr); + } else { + addr = hdmirx_cec_read(DWC_CEC_ADDR_H); + addr |= (1 << (l_add - 8)); + hdmirx_cec_write(DWC_CEC_ADDR_H, addr); + } + CEC_INFO("cec b add addr %d\n", l_add); +} + +void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add) +{ + /* save logical address for suspend/wake up */ + cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4); + + if (cec_sel == CEC_B) + cecb_addr_add(l_add); + else + ceca_addr_add(l_add); +} + +void cec_logicaddr_remove(unsigned int cec_sel, unsigned int l_add) +{ + unsigned int addr; + unsigned int i; + + if (cec_sel == CEC_B) { + if (l_add < 8) { + addr = hdmirx_cec_read(DWC_CEC_ADDR_L); + addr &= ~(1 << l_add); + hdmirx_cec_write(DWC_CEC_ADDR_L, addr); + } else { + addr = hdmirx_cec_read(DWC_CEC_ADDR_H); + addr &= ~(1 << (l_add - 8)); + hdmirx_cec_write(DWC_CEC_ADDR_H, addr); + } + CEC_INFO("cec b remove addr %d\n", l_add); + } else { + for (i = CEC_LOGICAL_ADDR0; i <= CEC_LOGICAL_ADDR4; i++) { + addr = aocec_rd_reg(i); + if ((addr & 0xf) == (l_add & 0xf)) { + aocec_wr_reg(i, (addr & 0xf)); + udelay(100); + aocec_wr_reg(i, 0); + cec_hw_buf_clear(); + CEC_INFO("cec a rm addr %d at 0x%x\n", + l_add, i); + } + } + } +} + +void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en) +{ + unsigned int i; + unsigned int addr_enable = addr_en; + + cec_clear_all_logical_addr(cec_sel); + for (i = 0; i < 15; i++) { + if (addr_enable & 0x1) + cec_logicaddr_add(cec_sel, i); + + addr_enable = addr_enable >> 1; + } +} + +void ceca_hw_reset(void) +{ writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); /* Enable gated clock (Normal mode). */ cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1); @@ -934,15 +1048,24 @@ void cec_hw_reset(void) /* Enable all AO_CEC interrupt sources */ cec_irq_enable(true); - cec_logicaddr_set(cec_dev->cec_info.log_addr); + /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ /* Cec arbitration 3/5/7 bit time set. */ cec_arbit_bit_time_set(3, 0x118, 0); cec_arbit_bit_time_set(5, 0x000, 0); cec_arbit_bit_time_set(7, 0x2aa, 0); +} - CEC_INFO("hw reset :logical addr:0x%x\n", - aocec_rd_reg(CEC_LOGICAL_ADDR0)); +void cec_hw_reset(unsigned int cec_sel) +{ + if (cec_sel == CEC_B) { + ao_cecb_init(); + /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ + } else { + ceca_hw_reset(); + } + /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ + cec_restore_logical_addr(cec_sel, cec_dev->cec_info.addr_enable); } void cec_rx_buf_clear(void) @@ -990,16 +1113,21 @@ static bool need_nack_repeat_msg(const unsigned char *msg, int len, int t) return false; } -static void cec_clear_logical_addr(void) +void cec_clear_all_logical_addr(unsigned int cec_sel) { - CEC_INFO("clear logical addr\n"); + CEC_INFO("clear all logical addr\n"); - if (ee_cec) { + if (cec_sel == CEC_B) { hdmirx_cec_write(DWC_CEC_ADDR_L, 0); - hdmirx_cec_write(DWC_CEC_ADDR_H, 0x80); - } else + hdmirx_cec_write(DWC_CEC_ADDR_H, 0); + } else { aocec_wr_reg(CEC_LOGICAL_ADDR0, 0); - udelay(100); + aocec_wr_reg(CEC_LOGICAL_ADDR1, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR2, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR3, 0); + aocec_wr_reg(CEC_LOGICAL_ADDR4, 0); + } + /*udelay(100);*/ } void cec_enable_arc_pin(bool enable) @@ -1019,7 +1147,7 @@ void cec_enable_arc_pin(bool enable) if (enable) data |= 0x02; else - data &= 0xffffffffd; + data &= 0xfffffffd; wr_reg_hhi(HHI_HDMIRX_ARC_CNTL, data); CEC_INFO("set arc en:%d, reg:%x\n", enable, data); } else { @@ -1036,22 +1164,20 @@ EXPORT_SYMBOL(cec_enable_arc_pin); int cec_rx_buf_check(void) { - unsigned int rx_num_msg; + unsigned int rx_num_msg = 0; - if (ee_cec) { + if (ee_cec == CEC_B) { cecrx_check_irq_enable(); - cecrx_irq_handle(); - return 0; + cecb_irq_handle(); + } else { + rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG); + if (rx_num_msg) + CEC_INFO("rx msg num:0x%02x\n", rx_num_msg); } - - rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG); - if (rx_num_msg) - CEC_INFO("rx msg num:0x%02x\n", rx_num_msg); - return rx_num_msg; } -int cec_ll_rx(unsigned char *msg, unsigned char *len) +int ceca_rx_irq_handle(unsigned char *msg, unsigned char *len) { int i; int ret = -1; @@ -1068,6 +1194,16 @@ int cec_ll_rx(unsigned char *msg, unsigned char *len) return ret; } + /* when use two cec ip, cec a only send msg, discard all rx msg */ + if (cec_dev->cec_num > 1) { + writel((1 << 2), cec_dev->cec_reg + AO_CEC_INTR_CLR); + aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); + aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); + cec_rx_buf_clear(); + CEC_INFO("discard msg\n"); + return ret; + } + *len = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1; for (i = 0; i < (*len) && i < MAX_MSG; i++) @@ -1079,7 +1215,7 @@ int cec_ll_rx(unsigned char *msg, unsigned char *len) if (cec_msg_dbg_en && *len > 1) { pos = 0; pos += sprintf(msg_log_buf + pos, - "CEC: rx msg len: %d dat: ", *len); + "cec: rx len: %d dat: ", *len); for (i = 0; i < (*len); i++) pos += sprintf(msg_log_buf + pos, "%02x ", msg[i]); pos += sprintf(msg_log_buf + pos, "\n"); @@ -1099,7 +1235,7 @@ int cec_ll_rx(unsigned char *msg, unsigned char *len) /* using the cec pin as fiq gpi to assist the bus arbitration */ /* return value: 1: successful 0: error */ -static int cec_ll_trigle_tx(const unsigned char *msg, int len) +static int ceca_trigle_tx(const unsigned char *msg, int len) { int i; unsigned int n; @@ -1115,11 +1251,11 @@ static int cec_ll_trigle_tx(const unsigned char *msg, int len) break; if (!(j--)) { - CEC_INFO("waiting busy timeout\n"); + CEC_INFO("ceca waiting busy timeout\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); cec_timeout_cnt++; if (cec_timeout_cnt > 0x08) - cec_hw_reset(); + cec_hw_reset(CEC_A); break; } msleep(20); @@ -1136,7 +1272,7 @@ static int cec_ll_trigle_tx(const unsigned char *msg, int len) if (cec_msg_dbg_en) { pos = 0; pos += sprintf(msg_log_buf + pos, - "CEC: tx msg len: %d dat: ", len); + "cec: tx len: %d dat: ", len); for (n = 0; n < len; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg[n]); @@ -1154,7 +1290,7 @@ static int cec_ll_trigle_tx(const unsigned char *msg, int len) return -1; } -void tx_irq_handle(void) +void ceca_tx_irq_handle(void) { unsigned int tx_status = aocec_rd_reg(CEC_TX_MSG_STATUS); @@ -1172,9 +1308,12 @@ void tx_irq_handle(void) case TX_ERROR: if (cec_msg_dbg_en) - CEC_ERR("TX ERROR!!!\n"); + CEC_ERR("TX ERROR!\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); - cec_hw_reset(); + ceca_hw_reset(); + if (cec_dev->cec_num <= 1) + cec_restore_logical_addr(CEC_A, + cec_dev->cec_info.addr_enable); cec_tx_result = CEC_FAIL_NACK; break; @@ -1255,14 +1394,27 @@ static bool check_physical_addr_valid(int timeout) int cec_ll_tx(const unsigned char *msg, unsigned char len) { int ret = -1; - int t = msecs_to_jiffies(ee_cec ? 2000 : 5000); + int t; int retry = 2; + unsigned int cec_sel; + + /* only use cec a send msg */ + if (cec_dev->cec_num > 1) + cec_sel = CEC_A; + else + cec_sel = ee_cec; + + t = msecs_to_jiffies((cec_sel == CEC_B) ? 2000 : 5000); if (len == 0) return CEC_FAIL_NONE; + /* + * AO CEC controller will ack poll message itself if logical + * address already set. Must clear it before poll again + */ if (is_poll_message(msg[0])) - cec_clear_logical_addr(); + cec_clear_all_logical_addr(cec_sel); /* * for CEC CTS 9.3. Android will try 3 poll message if got NACK @@ -1271,7 +1423,7 @@ int cec_ll_tx(const unsigned char *msg, unsigned char len) * waveform seen on CEC bus. And did not pass CTS * specification of 9.3 */ - if (!ee_cec && need_nack_repeat_msg(msg, len, t)) { + if ((cec_sel == CEC_A) && need_nack_repeat_msg(msg, len, t)) { if (!memcmp(msg, last_cec_msg->msg, len)) { CEC_INFO("NACK repeat message:%x\n", len); return CEC_FAIL_NACK; @@ -1297,10 +1449,10 @@ try_again: return CEC_FAIL_BUSY; } - if (ee_cec) - ret = cecrx_trigle_tx(msg, len); + if (cec_sel == CEC_B) + ret = cecb_trigle_tx(msg, len); else - ret = cec_ll_trigle_tx(msg, len); + ret = ceca_trigle_tx(msg, len); if (ret < 0) { /* we should increase send idx if busy */ CEC_INFO("tx busy\n"); @@ -1318,7 +1470,7 @@ try_again: /* timeout or interrupt */ if (ret == 0) { CEC_ERR("tx timeout\n"); - cec_hw_reset(); + cec_hw_reset(cec_sel); } ret = CEC_FAIL_OTHER; } else { @@ -1333,7 +1485,7 @@ try_again: } mutex_unlock(&cec_dev->cec_mutex); - if (!ee_cec) { + if (cec_sel == CEC_A) { last_cec_msg->last_result = ret; if (ret == CEC_FAIL_NACK) { memcpy(last_cec_msg->msg, msg, len); @@ -1439,6 +1591,10 @@ static void ao_ceca_init(void) /* Enable all AO_CEC interrupt sources */ cec_irq_enable(true); + + cec_arbit_bit_time_set(3, 0x118, 0); + cec_arbit_bit_time_set(5, 0x000, 0); + cec_arbit_bit_time_set(7, 0x2aa, 0); } void cec_arbit_bit_time_set(unsigned int bit_set, @@ -1534,13 +1690,16 @@ unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag) return readl(cec_dev->cec_reg + AO_DEBUG_REG1); } +/* void cec_keep_reset(void) { - if (ee_cec) - cecrx_hw_reset(); + if (ee_cec == CEC_B) + cecb_hw_reset(); else writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL); } +*/ + /* * cec hw module init before allocate logical address */ @@ -1553,15 +1712,21 @@ static void cec_pre_init(void) wake_ok = 0; pr_info("cec: wake up flag:%x\n", reg); - if (ee_cec) { - cecrx_hw_init(); - } else { + if (cec_dev->cec_num > 1) { ao_ceca_init(); - - cec_arbit_bit_time_set(3, 0x118, 0); - cec_arbit_bit_time_set(5, 0x000, 0); - cec_arbit_bit_time_set(7, 0x2aa, 0); + ao_cecb_init(); + } else { + if (ee_cec == CEC_B) + ao_cecb_init(); + else + ao_ceca_init(); } + + //need restore all logical address + if (cec_dev->cec_num > 1) + cec_restore_logical_addr(CEC_B, cec_dev->cec_info.addr_enable); + else + cec_restore_logical_addr(ee_cec, cec_dev->cec_info.addr_enable); } static int cec_late_check_rx_buffer(void) @@ -1575,7 +1740,7 @@ static int cec_late_check_rx_buffer(void) /* * start another check if rx buffer is full */ - if ((-1) == cec_ll_rx(rx_msg, &rx_len)) { + if ((-1) == ceca_rx_irq_handle(rx_msg, &rx_len)) { CEC_INFO("buffer got unrecorgnized msg\n"); cec_rx_buf_clear(); return 0; @@ -1820,7 +1985,7 @@ static void cec_rx_process(void) case CEC_OC_SET_STREAM_PATH: cec_set_stream_path(msg); /* wake up if in early suspend */ - if (cec_dev->cec_suspend == CEC_EARLY_SUSPEND) + if (cec_dev->cec_suspend != CEC_POWER_ON) cec_key_report(0); break; @@ -1842,7 +2007,7 @@ static void cec_rx_process(void) case CEC_OC_USER_CONTROL_PRESSED: /* wake up by key function */ - if (cec_dev->cec_suspend == CEC_EARLY_SUSPEND) { + if (cec_dev->cec_suspend != CEC_POWER_ON) { if (msg[2] == 0x40 || msg[2] == 0x6d) cec_key_report(0); } @@ -1911,18 +2076,19 @@ static void cec_task(struct work_struct *work) queue_delayed_work(cec_dev->cec_thread, dwork, CEC_FRAME_DELAY); } -static irqreturn_t ceca_isr_handler(int irq, void *dev_instance) +static irqreturn_t ceca_isr(int irq, void *dev_instance) { unsigned int intr_stat = 0; struct delayed_work *dwork; + /*CEC_INFO("ceca_isr\n");*/ dwork = &cec_dev->cec_work; intr_stat = cec_intr_stat(); if (intr_stat & (1<<1)) { /* aocec tx intr */ - tx_irq_handle(); + ceca_tx_irq_handle(); return IRQ_HANDLED; } - if ((-1) == cec_ll_rx(rx_msg, &rx_len)) + if ((-1) == ceca_rx_irq_handle(rx_msg, &rx_len)) return IRQ_HANDLED; complete(&cec_dev->rx_ok); @@ -2010,7 +2176,7 @@ static ssize_t dump_reg_show(struct class *cla, { int i, s = 0; - if (ee_cec) + if (ee_cec == CEC_B) return dump_cecrx_reg(b); s += sprintf(b + s, "TX buffer:\n"); @@ -2206,7 +2372,7 @@ static ssize_t fun_cfg_store(struct class *cla, struct class_attribute *attr, return -EINVAL; cec_config(val, 1); if (val == 0) - cec_clear_logical_addr();/*cec_keep_reset();*/ + cec_clear_all_logical_addr(ee_cec);/*cec_keep_reset();*/ else cec_pre_init(); return count; @@ -2348,6 +2514,40 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, CEC_ERR("wao addr:0x%x, val:0x%x", val, addr); } else if (token && strncmp(token, "preinit", 7) == 0) { cec_pre_init(); + } else if (token && strncmp(token, "setaddr", 7) == 0) { + token = strsep(&cur, delim); + /*string to int*/ + if (!token || kstrtouint(token, 16, &addr) < 0) + return count; + + cec_logicaddr_set(addr); + } else if (token && strncmp(token, "clraddr", 7) == 0) { + cec_dev->cec_info.addr_enable = 0; + cec_clear_all_logical_addr(ee_cec); + } else if (token && strncmp(token, "clralladdr", 10) == 0) { + cec_dev->cec_info.addr_enable = 0; + cec_clear_all_logical_addr(0); + cec_clear_all_logical_addr(1); + } else if (token && strncmp(token, "addaddr", 7) == 0) { + token = strsep(&cur, delim); + /*string to int*/ + if (!token || kstrtouint(token, 16, &addr) < 0) + return count; + cec_dev->cec_info.addr_enable |= (1 << (addr & 0xf)); + if (cec_dev->cec_num > 1) + cec_logicaddr_add(CEC_B, addr); + else + cec_logicaddr_add(ee_cec, addr); + } else if (token && strncmp(token, "rmaddr", 6) == 0) { + token = strsep(&cur, delim); + /*string to int*/ + if (!token || kstrtouint(token, 16, &addr) < 0) + return count; + cec_dev->cec_info.addr_enable &= ~(1 << (addr & 0xf)); + if (cec_dev->cec_num > 1) + cec_logicaddr_remove(CEC_B, addr); + else + cec_logicaddr_remove(ee_cec, addr); } else { if (token) CEC_ERR("no cmd:%s\n", token); @@ -2411,12 +2611,19 @@ static ssize_t hdmitx_cec_read(struct file *f, char __user *buf, if ((cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL))) rx_len = 0; + /*CEC_ERR("read msg start\n");*/ ret = wait_for_completion_timeout(&cec_dev->rx_ok, CEC_FRAME_DELAY); - if (ret <= 0) + if (ret <= 0) { + /*CEC_ERR("read msg ret=0\n");*/ return ret; - if (rx_len == 0) - return 0; + } + if (rx_len == 0) { + /*CEC_ERR("read msg rx_len=0\n");*/ + return 0; + } + + /*CEC_ERR("read msg end\n");*/ if (copy_to_user(buf, rx_msg, rx_len)) return -EINVAL; return rx_len; @@ -2534,6 +2741,9 @@ void cec_dump_info(void) { struct hdmi_port_info *port; + CEC_ERR("driver date:%s\n", CEC_DRIVER_VERSION); + CEC_ERR("cec sel:%d\n", ee_cec); + CEC_ERR("cec_num:%d\n", cec_dev->cec_num); CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); CEC_ERR("wk_logic_addr:0x%x\n", cec_dev->wakup_data.wk_logic_addr); CEC_ERR("wk_phy_addr:0x%x\n", cec_dev->wakup_data.wk_phy_addr); @@ -2558,6 +2768,36 @@ void cec_dump_info(void) init_cec_port_info(port, cec_dev); kfree(port); } + + if (cec_dev->cec_num > 1) { + CEC_ERR("addrL 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_L)); + CEC_ERR("addrH 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_H)); + + CEC_ERR("addr0 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0)); + CEC_ERR("addr1 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR1)); + CEC_ERR("addr2 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR2)); + CEC_ERR("addr3 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR3)); + CEC_ERR("addr4 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR4)); + } else { + if (ee_cec == CEC_B) { + CEC_ERR("addrL 0x%x\n", + hdmirx_cec_read(DWC_CEC_ADDR_L)); + CEC_ERR("addrH 0x%x\n", + hdmirx_cec_read(DWC_CEC_ADDR_H)); + } else { + CEC_ERR("addr0 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR0)); + CEC_ERR("addr1 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR1)); + CEC_ERR("addr2 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR2)); + CEC_ERR("addr3 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR3)); + CEC_ERR("addr4 0x%x\n", + aocec_rd_reg(CEC_LOGICAL_ADDR4)); + } + } + CEC_ERR("addr_enable:0x%x\n", cec_dev->cec_info.addr_enable); } static long hdmitx_cec_ioctl(struct file *f, @@ -2674,7 +2914,7 @@ static long hdmitx_cec_ioctl(struct file *f, cec_dev->hal_flag &= ~(tmp); CEC_INFO("disable CEC\n"); /*cec_keep_reset();*/ - cec_clear_logical_addr(); + cec_clear_all_logical_addr(ee_cec); } break; @@ -2724,18 +2964,28 @@ static long hdmitx_cec_ioctl(struct file *f, case CEC_IOC_ADD_LOGICAL_ADDR: tmp = arg & 0xf; - cec_logicaddr_set(tmp); + /*cec_logicaddr_set(tmp);*/ + /*cec_logicaddr_add(ee_cec, tmp);*/ + if (cec_dev->cec_num > 1) + cec_logicaddr_add(CEC_B, tmp); + else + cec_logicaddr_add(ee_cec, tmp); + cec_dev->cec_info.addr_enable |= (1 << tmp); + /* add by hal, to init some data structure */ cec_dev->cec_info.log_addr = tmp; cec_dev->cec_info.power_status = POWER_ON; - cec_dev->cec_info.vendor_id = cec_dev->v_data.vendor_id; strncpy(cec_dev->cec_info.osd_name, cec_dev->v_data.cec_osd_string, 14); break; case CEC_IOC_CLR_LOGICAL_ADDR: - cec_clear_logical_addr(); + if (cec_dev->cec_num > 1) + cec_clear_all_logical_addr(CEC_B); + else + cec_clear_all_logical_addr(ee_cec); + cec_dev->cec_info.addr_enable = 0; break; case CEC_IOC_SET_DEV_TYPE: @@ -2922,6 +3172,15 @@ static const struct of_device_id aml_cec_dt_match[] = { }; #endif +static void cec_node_val_init(void) +{ + /* initial main logical address */ + cec_dev->cec_info.log_addr = 0; + /* all logical address disable */ + cec_dev->cec_info.addr_enable = 0; + cec_dev->cec_info.open_count.counter = 0; +} + static int aml_cec_probe(struct platform_device *pdev) { struct device *cdev; @@ -2929,7 +3188,7 @@ static int aml_cec_probe(struct platform_device *pdev) const struct of_device_id *of_id; #ifdef CONFIG_OF struct device_node *node = pdev->dev.of_node; - int irq_idx = 0, r; + int r; const char *irq_name = NULL; struct pinctrl *pin; struct vendor_info_data *vend; @@ -2993,7 +3252,7 @@ static int aml_cec_probe(struct platform_device *pdev) } else CEC_ERR("unable to get matched device\n"); - cec_dev->cec_info.open_count.counter = 0; + cec_node_val_init(); init_completion(&cec_dev->rx_ok); init_completion(&cec_dev->tx_ok); mutex_init(&cec_dev->cec_mutex); @@ -3024,11 +3283,20 @@ static int aml_cec_probe(struct platform_device *pdev) } #ifdef CONFIG_OF + /* config: read from dts */ + r = of_property_read_u32(node, "cec_sel", &(cec_dev->cec_num)); + if (r) { + CEC_ERR("not find 'port_num'\n"); + cec_dev->cec_num = 0; + } else { + CEC_ERR("use two cec ip\n"); + } + /* if using EE CEC */ if (of_property_read_bool(node, "ee_cec")) - ee_cec = 1; + ee_cec = CEC_B; else - ee_cec = 0; + ee_cec = CEC_A; CEC_ERR("using cec:%d\n", ee_cec); /* pinmux set */ if (of_get_property(node, "pinctrl-names", NULL)) { @@ -3039,7 +3307,7 @@ static int aml_cec_probe(struct platform_device *pdev) if (IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) CEC_ERR("get sleep state error!\n"); /*get active state*/ - if (ee_cec) { + if (ee_cec == CEC_B) { cec_dev->dbg_dev->pins->default_state = pinctrl_lookup_state(pin, "hdmitx_aocecb"); if (IS_ERR(cec_dev->dbg_dev->pins->default_state)) { @@ -3051,7 +3319,7 @@ static int aml_cec_probe(struct platform_device *pdev) CEC_ERR("get default error0\n"); CEC_ERR("use default cec\n"); /*force use default*/ - ee_cec = 0; + ee_cec = CEC_A; } } else { cec_dev->dbg_dev->pins->default_state = @@ -3064,6 +3332,7 @@ static int aml_cec_probe(struct platform_device *pdev) if (ret > 0) CEC_ERR("select state error:0x%x\n", ret); } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ao_exit"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -3074,7 +3343,8 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->exit_reg = (void *)base; } else - CEC_ERR("no ao_exit regs\n") + CEC_ERR("no ao_exit regs\n"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ao"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -3098,7 +3368,8 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->hdmi_rxreg = (void *)base; } else - CEC_ERR("no hdmirx regs\n") + CEC_ERR("no hdmirx regs\n"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -3120,7 +3391,8 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->periphs_reg = (void *)base; } else - CEC_ERR("no periphs regs\n") + CEC_ERR("no periphs regs\n"); + r = of_property_read_u32(node, "port_num", &(cec_dev->port_num)); if (r) { CEC_ERR("not find 'port_num'\n"); @@ -3180,32 +3452,48 @@ static int aml_cec_probe(struct platform_device *pdev) } if (of_irq_count(node) > 1) { - if (ee_cec) - irq_idx = of_irq_get(node, 0); - else - irq_idx = of_irq_get(node, 1); + /* need enable two irq */ + cec_dev->irq_cecb = of_irq_get(node, 0);/*cecb int*/ + cec_dev->irq_ceca = of_irq_get(node, 1);/*ceca int*/ } else { - irq_idx = of_irq_get(node, 0); + cec_dev->irq_cecb = of_irq_get(node, 0); + cec_dev->irq_ceca = cec_dev->irq_cecb; } - cec_dev->irq_cec = irq_idx; - CEC_ERR("irq cnt:%d,cur no:%d\n", of_irq_count(node), irq_idx); + + CEC_ERR("irq cnt:%d\n", of_irq_count(node)); if (of_get_property(node, "interrupt-names", NULL)) { r = of_property_read_string(node, "interrupt-names", &irq_name); - if (!r && !ee_cec) { - r = request_irq(irq_idx, &ceca_isr_handler, IRQF_SHARED, - irq_name, (void *)cec_dev); + if (cec_dev->cec_num > 1) { + /* request two int source */ + CEC_ERR("request_irq two irq src\n"); + r = request_irq(cec_dev->irq_ceca, &ceca_isr, + IRQF_SHARED, irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("aocec irq request fail\n"); - } - if (!r && ee_cec) { - r = request_irq(irq_idx, &cecb_rx_isr, IRQF_SHARED, - irq_name, (void *)cec_dev); + + r = request_irq(cec_dev->irq_cecb, &cecb_isr, + IRQF_SHARED, irq_name, (void *)cec_dev); if (r < 0) CEC_INFO("cecb irq request fail\n"); + } else { + if (!r && (ee_cec == CEC_A)) { + r = request_irq(cec_dev->irq_ceca, &ceca_isr, + IRQF_SHARED, irq_name, (void *)cec_dev); + if (r < 0) + CEC_INFO("aocec irq request fail\n"); + } + + if (!r && (ee_cec == CEC_B)) { + r = request_irq(cec_dev->irq_cecb, &cecb_isr, + IRQF_SHARED, irq_name, (void *)cec_dev); + if (r < 0) + CEC_INFO("cecb irq request fail\n"); + } } } - if (!ee_cec) { + /* if (ee_cec == CEC_A) */ + { last_cec_msg = devm_kzalloc(&pdev->dev, sizeof(*last_cec_msg), GFP_KERNEL); if (!last_cec_msg) { @@ -3247,7 +3535,15 @@ static int aml_cec_probe(struct platform_device *pdev) return 0; tag_cec_msg_alloc_err: - free_irq(cec_dev->irq_cec, (void *)cec_dev); + if (cec_dev->cec_num > 1) { + free_irq(cec_dev->irq_ceca, (void *)cec_dev); + free_irq(cec_dev->irq_cecb, (void *)cec_dev); + } else { + if (ee_cec == CEC_B) + free_irq(cec_dev->irq_cecb, (void *)cec_dev); + else + free_irq(cec_dev->irq_ceca, (void *)cec_dev); + } tag_cec_reg_map_err: input_free_device(cec_dev->cec_info.remote_cec_dev); tag_cec_alloc_input_err: @@ -3268,7 +3564,15 @@ tag_cec_devm_err: static int aml_cec_remove(struct platform_device *pdev) { CEC_INFO("cec uninit!\n"); - free_irq(cec_dev->irq_cec, (void *)cec_dev); + if (cec_dev->cec_num > 1) { + free_irq(cec_dev->irq_ceca, (void *)cec_dev); + free_irq(cec_dev->irq_cecb, (void *)cec_dev); + } else { + if (ee_cec == CEC_B) + free_irq(cec_dev->irq_cecb, (void *)cec_dev); + else + free_irq(cec_dev->irq_ceca, (void *)cec_dev); + } kfree(last_cec_msg); if (cec_dev->cec_thread) { @@ -3307,6 +3611,11 @@ static int aml_cec_suspend_noirq(struct device *dev) int ret = 0; CEC_INFO("cec suspend noirq\n"); + if (cec_dev->cec_num > 1) + cec_clear_all_logical_addr(CEC_B); + else + cec_clear_all_logical_addr(ee_cec); + if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state)) ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev); else diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 52d2458fa1f6..1be44c6b00b8 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -56,6 +56,10 @@ enum cecbver { #define L_1 1 #define L_2 2 #define L_3 3 + +#define CEC_A 0 +#define CEC_B 1 + /* #define CEC_FUNC_MASK 0 #define ONE_TOUCH_PLAY_MASK 1 @@ -528,7 +532,7 @@ int __attribute__((weak))hdmirx_get_connect_info(void) #ifdef CONFIG_AMLOGIC_AO_CEC unsigned int aocec_rd_reg(unsigned long addr); void aocec_wr_reg(unsigned long addr, unsigned long data); -void cecrx_irq_handle(void); +void cecb_irq_handle(void); void cec_logicaddr_set(int l_add); void cec_arbit_bit_time_set(unsigned int bit_set, unsigned int time_set, unsigned int flag); @@ -537,6 +541,9 @@ void aocec_irq_enable(bool enable); extern void dump_reg(void); #endif extern void cec_dump_info(void); -extern void cec_hw_reset(void); - +extern void cec_hw_reset(unsigned int cec_sel); +extern void cec_restore_logical_addr(unsigned int cec_sel, + unsigned int addr_en); +extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); +extern void cec_clear_all_logical_addr(unsigned int cec_sel); #endif /* __AO_CEC_H__ */ diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h index 456ea13d1623..d35ea36e5a5d 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h @@ -34,7 +34,7 @@ #include "hdmi_rx_edid.h" -#define RX_VER0 "ver.2019-01-22" +#define RX_VER0 "ver.2018-11-8" /* * * @@ -472,7 +472,7 @@ extern void rx_send_hpd_pulse(void); /* irq */ extern void rx_irq_en(bool enable); extern irqreturn_t irq_handler(int irq, void *params); -extern void cecrx_irq_handle(void); +extern void cecb_irq_handle(void); /* user interface */ extern int pc_mode_en; diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c index b672f283a685..bcc318d55c14 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c @@ -311,7 +311,7 @@ static int hdmi_rx_ctrl_irq_handler(void) hdmirx_rd_dwc(DWC_AUD_CEC_ISTS) & hdmirx_rd_dwc(DWC_AUD_CEC_IEN); if (intr_aud_cec != 0) { - cecrx_irq_handle(); + cecb_irq_handle(); hdmirx_wr_dwc(DWC_AUD_CEC_ICLR, intr_aud_cec); } } diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h index 8689c9849a60..2e46deb17d8e 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h @@ -314,6 +314,7 @@ struct cec_global_info_t { unsigned int cec_version; unsigned char power_status; unsigned char log_addr; + unsigned int addr_enable; unsigned char menu_status; unsigned char osd_name[16]; struct input_dev *remote_cec_dev; /* cec input device */ From 6d0682cd8eec02a4dd92809cec937df641ada308 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 21 Nov 2018 16:00:23 +0800 Subject: [PATCH 0568/1060] cec: auto shutdown case crash [1/1] PD#SWPL-2258 Problem: 1.running autoshutdown cause device crashed Solution: 1.optimize cec power on proble flow Verify: 1.p212 Change-Id: Ia78c76cdb4b72a1a275628b3ad77ea6d71696d89 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/cec/hdmi_ao_cec.h --- drivers/amlogic/cec/hdmi_ao_cec.c | 24 ++++++++++-------------- drivers/amlogic/cec/hdmi_ao_cec.h | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 548ec1f412f5..2baf3ff9259d 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -607,7 +607,7 @@ static void ao_cecb_init(void) hdmirx_set_bits_top(TOP_EDID_GEN_CNTL, EDID_AUTO_CEC_EN, 11, 1); /* enable all cec irq */ - cec_irq_enable(true); + /*cec_irq_enable(true);*/ /* clear all wake up source */ hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0); /* cec enable */ @@ -660,7 +660,7 @@ static void ao_cecb_init(void) } /* Enable all AO_CECB interrupt sources */ - cec_irq_enable(true); + /*cec_irq_enable(true);*/ hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK); } } @@ -1046,7 +1046,7 @@ void ceca_hw_reset(void) cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); /* Enable all AO_CEC interrupt sources */ - cec_irq_enable(true); + /*cec_irq_enable(true);*/ /* cec_logicaddr_set(cec_dev->cec_info.log_addr); */ @@ -1590,7 +1590,7 @@ static void ao_ceca_init(void) cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1); /* Enable all AO_CEC interrupt sources */ - cec_irq_enable(true); + /*cec_irq_enable(true);*/ cec_arbit_bit_time_set(3, 0x118, 0); cec_arbit_bit_time_set(5, 0x000, 0); @@ -3282,7 +3282,6 @@ static int aml_cec_probe(struct platform_device *pdev) input_free_device(cec_dev->cec_info.remote_cec_dev); } -#ifdef CONFIG_OF /* config: read from dts */ r = of_property_read_u32(node, "cec_sel", &(cec_dev->cec_num)); if (r) { @@ -3492,15 +3491,12 @@ static int aml_cec_probe(struct platform_device *pdev) } } - /* if (ee_cec == CEC_A) */ - { - last_cec_msg = devm_kzalloc(&pdev->dev, - sizeof(*last_cec_msg), GFP_KERNEL); - if (!last_cec_msg) { - CEC_ERR("allocate last_cec_msg failed\n"); - ret = -ENOMEM; - goto tag_cec_msg_alloc_err; - } + last_cec_msg = devm_kzalloc(&pdev->dev, + sizeof(*last_cec_msg), GFP_KERNEL); + if (!last_cec_msg) { + CEC_ERR("allocate last_cec_msg failed\n"); + ret = -ENOMEM; + goto tag_cec_msg_alloc_err; } #ifdef CONFIG_HAS_EARLYSUSPEND diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 1be44c6b00b8..563948d70397 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,7 +19,7 @@ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2019/3/25\n" +#define CEC_DRIVER_VERSION "Ver 2018/11/21\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" From 590814cd2c9c7b2d738c19f9f1b8d36f0e65ec5d Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Thu, 10 Jan 2019 14:52:03 +0800 Subject: [PATCH 0569/1060] cec: framework suspend condition error [1/1] PD#SWPL-3715 Problem: set startup to TV,when DVD power on,the platform autoshutdown after enter HDMI source Solution: suspend condition is wrong when not in suspend mode. Verify: TL1 (X301_T962x2) Change-Id: I057cfe6b9a7f5806fa54eac063c02a7e3dc0179e Signed-off-by: Yong Qin Conflicts: drivers/amlogic/cec/hdmi_ao_cec.c drivers/amlogic/cec/hdmi_ao_cec.h --- drivers/amlogic/cec/hdmi_ao_cec.c | 26 +++++++++++++++----------- drivers/amlogic/cec/hdmi_ao_cec.h | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 2baf3ff9259d..81be897d483e 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -147,8 +147,10 @@ static int phy_addr_test; enum { HDMI_OPTION_WAKEUP = 1, HDMI_OPTION_ENABLE_CEC = 2, + /*frame work pw on, 1:pw on 0:suspend*/ HDMI_OPTION_SYSTEM_CEC_CONTROL = 3, HDMI_OPTION_SET_LANG = 5, + /*have cec framework*/ HDMI_OPTION_SERVICE_FLAG = 16, }; @@ -161,7 +163,7 @@ static struct hrtimer start_bit_check; static unsigned char rx_msg[MAX_MSG]; static unsigned char rx_len; static unsigned int new_msg; -static bool wake_ok = 1; +/*static bool wake_ok = 1;*/ static bool ee_cec; static bool pin_status; static unsigned int cec_msg_dbg_en; @@ -1705,13 +1707,14 @@ void cec_keep_reset(void) */ static void cec_pre_init(void) { + #if 0 unsigned int reg = readl(cec_dev->cec_reg + AO_RTI_STATUS_REG1); reg &= 0xfffff; if ((reg & 0xffff) == 0xffff) wake_ok = 0; pr_info("cec: wake up flag:%x\n", reg); - + #endif if (cec_dev->cec_num > 1) { ao_ceca_init(); ao_cecb_init(); @@ -1936,12 +1939,13 @@ static void cec_rx_process(void) opcode = msg[1]; switch (opcode) { case CEC_OC_ACTIVE_SOURCE: - if (wake_ok == 0) { + /*if (wake_ok == 0) */ + { int phy_addr = msg[2] << 8 | msg[3]; if (phy_addr == 0xffff) break; - wake_ok = 1; + /*wake_ok = 1;*/ phy_addr |= (initiator << 16); writel(phy_addr, cec_dev->cec_reg + AO_RTI_STATUS_REG1); CEC_INFO("found wake up source:%x", phy_addr); @@ -2031,9 +2035,8 @@ static void cec_rx_process(void) break; default: - CEC_ERR("unsupported command:%x\n", opcode); - CEC_ERR("wake_ok=%d,hal_flag=0x%x\n", - wake_ok, cec_dev->hal_flag); + CEC_ERR("cec unsupported cmd:0x%x, halflg:0x%x\n", + opcode, cec_dev->hal_flag); break; } new_msg = 0; @@ -2042,10 +2045,12 @@ static void cec_rx_process(void) static bool cec_service_suspended(void) { /* service is not enabled */ - if (!(cec_dev->hal_flag & (1 << HDMI_OPTION_SERVICE_FLAG))) - return false; + /*if (!(cec_dev->hal_flag & (1 << HDMI_OPTION_SERVICE_FLAG)))*/ + /* return false;*/ + if (!(cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL))) return true; + return false; } @@ -2057,8 +2062,7 @@ static void cec_task(struct work_struct *work) cec_cfg = cec_config(0, 0); if (cec_cfg & CEC_FUNC_CFG_CEC_ON) { /*cec module on*/ - if (cec_dev && (!wake_ok || cec_service_suspended()) - && !(cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL))) + if (cec_dev && (/*!wake_ok || */cec_service_suspended())) cec_rx_process(); /*for check rx buffer for old chip version, cec rx irq process*/ diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 563948d70397..593512881f3e 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,7 +19,7 @@ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2018/11/21\n" +#define CEC_DRIVER_VERSION "Ver 2019/1/10\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" From 98d31275236409649bd7462bdcef92a133224cae Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 14 Jan 2019 16:50:12 +0800 Subject: [PATCH 0570/1060] cec: ceca register access fail [1/1] PD#SWPL-4133 Problem: cec a register access fail and cause watchdog reboot Solution: reduce wait counter, and check clk register Verify: P215 Change-Id: Ic9d97e1eca9428ffd0c4a6bfe008cd9d8303075b Signed-off-by: Yong Qin Conflicts: drivers/amlogic/cec/hdmi_ao_cec.c --- drivers/amlogic/cec/hdmi_ao_cec.c | 45 +++++++++---------------------- drivers/amlogic/cec/hdmi_ao_cec.h | 5 +++- 2 files changed, 16 insertions(+), 34 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 81be897d483e..3ec47c342ddd 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -224,10 +224,15 @@ unsigned int waiting_aocec_free(unsigned int r) { unsigned int cnt = 0; int ret = true; + char *s; while (readl(cec_dev->cec_reg + r) & (1<<23)) { if (cnt++ >= 3500) { pr_info("waiting aocec %x free time out %d\n", r, cnt); + s = kmalloc(2048, GFP_KERNEL); + dump_cecrx_reg(s); + CEC_ERR("%s\n", s); + kfree(s); if (cec_dev->proble_finish) cec_hw_reset(CEC_A); ret = false; @@ -244,7 +249,8 @@ unsigned int waiting_aocec_free(unsigned int r) while (readl(cec_dev->cec_reg + r) & (1<<23)) {\ if (cnt++ == 3500) { \ pr_info("waiting aocec %x free time out\n", r);\ - cec_hw_reset(CEC_A);\ + if (cec_dev->proble_finish) \ + cec_hw_reset(CEC_A);\ break;\ } \ } \ @@ -728,7 +734,8 @@ int cecrx_hw_init(void) return 0; } */ -static int dump_cecrx_reg(char *b) + +int dump_cecrx_reg(char *b) { int i = 0, s = 0; unsigned char reg; @@ -2178,37 +2185,7 @@ static ssize_t port_num_show(struct class *cla, static ssize_t dump_reg_show(struct class *cla, struct class_attribute *attr, char *b) { - int i, s = 0; - - if (ee_cec == CEC_B) - return dump_cecrx_reg(b); - - s += sprintf(b + s, "TX buffer:\n"); - for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) - s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i)); - - for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) { - s += sprintf(b + s, "%s:%2x\n", - cec_reg_name1[i], aocec_rd_reg(i + 0x10)); - } - - s += sprintf(b + s, "RX buffer:\n"); - for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) - s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i + 0x80)); - - for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) { - s += sprintf(b + s, "%s:%2x\n", - cec_reg_name2[i], aocec_rd_reg(i + 0x90)); - } - - if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { - for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) { - s += sprintf(b + s, "%s:%2x\n", - ceca_reg_name3[i], aocec_rd_reg(i + 0xA0)); - } - } - - return s; + return dump_cecrx_reg(b); } static ssize_t arc_port_show(struct class *cla, @@ -2746,6 +2723,8 @@ void cec_dump_info(void) struct hdmi_port_info *port; CEC_ERR("driver date:%s\n", CEC_DRIVER_VERSION); + CEC_ERR("chip type:0x%x\n", + get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR)); CEC_ERR("cec sel:%d\n", ee_cec); CEC_ERR("cec_num:%d\n", cec_dev->cec_num); CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 593512881f3e..4c7be4314a87 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,7 +19,8 @@ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2019/1/10\n" + +#define CEC_DRIVER_VERSION "Ver 2019/1/14\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" @@ -546,4 +547,6 @@ extern void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en); extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); extern void cec_clear_all_logical_addr(unsigned int cec_sel); +extern int dump_cecrx_reg(char *b); + #endif /* __AO_CEC_H__ */ From de6ccab8c89710da7714f3014d038fe0eddb04bc Mon Sep 17 00:00:00 2001 From: Hang Cheng Date: Mon, 25 Mar 2019 19:05:54 +0800 Subject: [PATCH 0571/1060] cec: remove func that may cause deadlock [1/1] PD#SWPL-5836 Problem: kernel panic when read cec reg Solution: remove func that might cause sleep in spinlock, so as to avoid deadlock Verify: S805X-P241 Change-Id: I8394f69bdbeff6673c795a221c08ef76164c5bdb Signed-off-by: Hang Cheng Conflicts: drivers/amlogic/cec/hdmi_ao_cec.h --- drivers/amlogic/cec/hdmi_ao_cec.c | 5 ----- drivers/amlogic/cec/hdmi_ao_cec.h | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 3ec47c342ddd..264925381deb 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -224,15 +224,10 @@ unsigned int waiting_aocec_free(unsigned int r) { unsigned int cnt = 0; int ret = true; - char *s; while (readl(cec_dev->cec_reg + r) & (1<<23)) { if (cnt++ >= 3500) { pr_info("waiting aocec %x free time out %d\n", r, cnt); - s = kmalloc(2048, GFP_KERNEL); - dump_cecrx_reg(s); - CEC_ERR("%s\n", s); - kfree(s); if (cec_dev->proble_finish) cec_hw_reset(CEC_A); ret = false; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 4c7be4314a87..e5f5fbb95f71 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -20,7 +20,7 @@ -#define CEC_DRIVER_VERSION "Ver 2019/1/14\n" +#define CEC_DRIVER_VERSION "Ver 2019/3/25\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" From bbbf5c116eddd8ff9e3d24098418f554b1cc38fa Mon Sep 17 00:00:00 2001 From: Guosong Zhou Date: Fri, 28 Dec 2018 21:17:04 -0500 Subject: [PATCH 0572/1060] camera: add dvp camera [1/1] PD#OTT-1204 Problem: don't support dvp camera Solution: add dvp camera gc2145 camera driver Verify: test pass on U200 Change-Id: I0451160d013cd15b32a11469926fe8be4c35c466 Signed-off-by: Guosong Zhou Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts drivers/amlogic/media/camera/common/vm.c drivers/amlogic/media/camera/common/vm.h drivers/amlogic/media/camera/gc2145.c --- drivers/amlogic/media/camera/common/vm.c | 81 ++++++++---------------- drivers/amlogic/media/camera/common/vm.h | 7 -- drivers/amlogic/media/camera/gc2145.c | 19 +++--- 3 files changed, 36 insertions(+), 71 deletions(-) diff --git a/drivers/amlogic/media/camera/common/vm.c b/drivers/amlogic/media/camera/common/vm.c index b5ceeabd83ff..231ab58ab19f 100644 --- a/drivers/amlogic/media/camera/common/vm.c +++ b/drivers/amlogic/media/camera/common/vm.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -1635,9 +1634,22 @@ static int simulate_task(void *data) *********************************************** */ -int alloc_vm_canvas(struct vm_device_s *vdevp) +int vm_buffer_init(struct vm_device_s *vdevp) { - int j; + int i, j; + u32 canvas_width, canvas_height; + u32 decbuf_size; + resource_size_t buf_start; + unsigned int buf_size; + int buf_num = 0; + int local_pool_size = 0; + + init_completion(&vdevp->vb_start_sema); + init_completion(&vdevp->vb_done_sema); + + buf_start = vdevp->buffer_start; + buf_size = vdevp->buffer_size; + if (vdevp->index == 0) { for (j = 0; j < MAX_CANVAS_INDEX; j++) { memset(&(vdevp->vm_canvas[j]), -1, sizeof(int)); @@ -1660,25 +1672,6 @@ int alloc_vm_canvas(struct vm_device_s *vdevp) } } - return 0; -} - -int vm_buffer_init(struct vm_device_s *vdevp) -{ - int i; - u32 canvas_width, canvas_height; - u32 decbuf_size; - resource_size_t buf_start; - unsigned int buf_size; - int buf_num = 0; - int local_pool_size = 0; - - init_completion(&vdevp->vb_start_sema); - init_completion(&vdevp->vb_done_sema); - - buf_start = vdevp->buffer_start; - buf_size = vdevp->buffer_size; - if (!buf_start || !buf_size) goto exit; @@ -2016,20 +2009,6 @@ int init_vm_device(struct vm_device_s *vdevp, struct platform_device *pdev) vdevp->task_running = 0; memset(&vdevp->output_para, 0, sizeof(struct vm_output_para)); sprintf(vdevp->name, "%s%d", RECEIVER_NAME, vdevp->index); - sprintf(vdevp->vf_provider_name, "%s%d", "vdin", vdevp->index); - - snprintf(vdevp->vfm_map_chain, VM_MAP_NAME_SIZE, - "%s %s", vdevp->vf_provider_name, - vdevp->name); - snprintf(vdevp->vfm_map_id, VM_MAP_NAME_SIZE, - "vm-map-%d", vdevp->index); - if (vfm_map_add(vdevp->vfm_map_id, - vdevp->vfm_map_chain) < 0) { - pr_err("vm pipeline map creation failed %s.\n", - vdevp->vfm_map_id); - goto fail_create_dev_file; - } - vf_receiver_init(&vdevp->vm_vf_recv, vdevp->name, &vm_vf_receiver, vdevp); @@ -2204,12 +2183,7 @@ static int vm_driver_probe(struct platform_device *pdev) } vm_device[vdevp->index] = vdevp; vdevp->pdev = pdev; - platform_set_drvdata(pdev, vdevp); - ret = alloc_vm_canvas(vdevp); - if (ret != 0) { - pr_err("alloc vm canvas failed\n"); - return ret; - } + vm_buffer_init(vdevp); ret = init_vm_device(vdevp, pdev); if (ret != 0) @@ -2227,23 +2201,22 @@ static int vm_driver_probe(struct platform_device *pdev) static int vm_drv_remove(struct platform_device *plat_dev) { int i; - struct vm_device_s *vdevp; - - vdevp = platform_get_drvdata(plat_dev); for (i = 0; i < MAX_CANVAS_INDEX; i++) { - if ((vdevp != NULL) && - (vdevp->vm_canvas[i] >= 0)) { + if ((vm_device[0] != NULL) && + (vm_device[0]->vm_canvas[i] >= 0)) { canvas_pool_map_free_canvas( - vdevp->vm_canvas[i]); - memset(&(vdevp->vm_canvas[i]), + vm_device[0]->vm_canvas[i]); + memset(&(vm_device[0]->vm_canvas[i]), + -1, sizeof(int)); + } + if ((vm_device[1] != NULL) && + (vm_device[1]->vm_canvas[i] >= 0)) { + canvas_pool_map_free_canvas( + vm_device[1]->vm_canvas[i]); + memset(&(vm_device[1]->vm_canvas[i]), -1, sizeof(int)); } - } - - if (vdevp->vfm_map_id[0]) { - vfm_map_remove(vdevp->vfm_map_id); - vdevp->vfm_map_id[0] = 0; } uninit_vm_device(plat_dev); diff --git a/drivers/amlogic/media/camera/common/vm.h b/drivers/amlogic/media/camera/common/vm.h index 9c297e25da7f..4ae2bdd01983 100644 --- a/drivers/amlogic/media/camera/common/vm.h +++ b/drivers/amlogic/media/camera/common/vm.h @@ -47,9 +47,6 @@ #define VM_IOC_CONFIG_FRAME _IOW(VM_IOC_MAGIC, 0X02, unsigned int) #define MAX_CANVAS_INDEX 12 -#define VM_MAP_NAME_SIZE 100 -#define VM_PROVIDER_NAME_SIZE 10 - struct vm_device_s { unsigned int index; char name[20]; @@ -76,9 +73,6 @@ struct vm_device_s { struct vm_output_para output_para; struct completion vb_start_sema; struct completion vb_done_sema; - char vf_provider_name[VM_PROVIDER_NAME_SIZE]; - char vfm_map_id[VM_MAP_NAME_SIZE]; - char vfm_map_chain[VM_MAP_NAME_SIZE]; int vm_canvas[MAX_CANVAS_INDEX]; }; @@ -95,7 +89,6 @@ struct display_frame_s { int start_vm_task(struct vm_device_s *vdevp); int start_simulate_task(void); -int alloc_vm_canvas(struct vm_device_s *vdevp); extern int get_vm_status(void); extern void set_vm_status(int flag); diff --git a/drivers/amlogic/media/camera/gc2145.c b/drivers/amlogic/media/camera/gc2145.c index b194a8577078..66769880468e 100644 --- a/drivers/amlogic/media/camera/gc2145.c +++ b/drivers/amlogic/media/camera/gc2145.c @@ -503,8 +503,7 @@ static struct v4l2_frmsize_discrete static struct v4l2_frmsize_discrete gc2145_pic_resolution[] = { {1600, 1200}, - {800, 600}, - {640, 480} + {800, 600} }; #ifndef GC2145_MIRROR @@ -1819,23 +1818,23 @@ void GC2145_set_resolution(struct gc2145_device *dev, int height, int width) if ((width * height < 1600 * 1200)) { while (1) { - buf[0] = gc2145_uxga[i].addr; - buf[1] = gc2145_uxga[i].val; - if (gc2145_uxga[i].val == 0xff && - gc2145_uxga[i].addr == 0xff) { - pr_info("success in gc2145_uxga.\n"); + buf[0] = gc2145_svga[i].addr; + buf[1] = gc2145_svga[i].val; + if (gc2145_svga[i].val == 0xff && + gc2145_svga[i].addr == 0xff) { + pr_info("success in gc2145_svga.\n"); break; } if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in gc2145_uxga.\n"); + pr_err("fail in gc2145_svga.\n"); return; } i++; } gc2145_frmintervals_active.numerator = 1; gc2145_frmintervals_active.denominator = 15; - GC2145_h_active = 1600; - GC2145_v_active = 1200; + GC2145_h_active = 800; + GC2145_v_active = 600; mdelay(80); } else if (width * height >= 1200 * 1600) { buf[0] = 0xfe; From e7cd693aa9d226dcb42d76a31caa7217e0b8e42d Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Tue, 1 Jan 2019 17:55:48 +0800 Subject: [PATCH 0573/1060] camera: all sources are displayed as black screen except DTV. PD#SWPL-3776 Problem: all sources are displayed as black screen except DTV Solution: Revert "camera: add dvp camera [1/1]" Verify: verify by x301 Change-Id: I3f094ed18de4be382798515e5c68eb5505df2373 Signed-off-by: nengwen.chen Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts drivers/amlogic/media/camera/common/vm.c drivers/amlogic/media/camera/gc2145.c --- MAINTAINERS | 13 - .../arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 33 - arch/arm/configs/meson64_a32_defconfig | 3 - .../boot/dts/amlogic/g12a_s905d2_u200.dts | 87 - arch/arm64/configs/meson64_defconfig | 3 - drivers/amlogic/media/Kconfig | 1 - drivers/amlogic/media/Makefile | 1 - drivers/amlogic/media/camera/Kconfig | 559 --- drivers/amlogic/media/camera/Makefile | 15 - .../amlogic/media/camera/common/cam_prober.c | 1792 --------- .../media/camera/common/config_parser.c | 1822 --------- .../media/camera/common/config_parser.h | 301 -- .../amlogic/media/camera/common/flashlight.c | 249 -- .../amlogic/media/camera/common/plat_ctrl.c | 208 - .../amlogic/media/camera/common/plat_ctrl.h | 47 - drivers/amlogic/media/camera/common/vm.c | 2293 ----------- drivers/amlogic/media/camera/common/vm.h | 133 - drivers/amlogic/media/camera/common/vm_log.h | 44 - drivers/amlogic/media/camera/common/vmcls.h | 189 - drivers/amlogic/media/camera/gc2145.c | 3454 ----------------- .../amlogic/media/common/canvas/canvas_mgr.c | 3 + .../linux/amlogic/media/camera/aml_cam_info.h | 142 - .../linux/amlogic/media/camera/flashlight.h | 34 - include/linux/amlogic/media/camera/vmapi.h | 63 - 24 files changed, 3 insertions(+), 11486 deletions(-) delete mode 100644 drivers/amlogic/media/camera/Kconfig delete mode 100644 drivers/amlogic/media/camera/Makefile delete mode 100644 drivers/amlogic/media/camera/common/cam_prober.c delete mode 100644 drivers/amlogic/media/camera/common/config_parser.c delete mode 100644 drivers/amlogic/media/camera/common/config_parser.h delete mode 100644 drivers/amlogic/media/camera/common/flashlight.c delete mode 100644 drivers/amlogic/media/camera/common/plat_ctrl.c delete mode 100644 drivers/amlogic/media/camera/common/plat_ctrl.h delete mode 100644 drivers/amlogic/media/camera/common/vm.c delete mode 100644 drivers/amlogic/media/camera/common/vm.h delete mode 100644 drivers/amlogic/media/camera/common/vm_log.h delete mode 100644 drivers/amlogic/media/camera/common/vmcls.h delete mode 100644 drivers/amlogic/media/camera/gc2145.c delete mode 100644 include/linux/amlogic/media/camera/aml_cam_info.h delete mode 100644 include/linux/amlogic/media/camera/flashlight.h delete mode 100644 include/linux/amlogic/media/camera/vmapi.h diff --git a/MAINTAINERS b/MAINTAINERS index c4ba5ed396a4..66ad4a45dcf4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14771,19 +14771,6 @@ M: Yeping Miao F: arch/arm64/boot/dts/amlogic/axg_rsr.dts F: arch/arm64/boot/dts/amlogic/axg_rsr_v03.dts -AMLOGIC CAMERA DRIVER -M: Guosong Zhou -F: arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts -F: arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts -F: arch/arm64/configs/meson64_defconfig -F: arch/arm/configs/meson64_a32_defconfig -F: drivers/amlogic/media/Kconfig -F: drivers/amlogic/media/Makefile -F: drivers/amlogic/media/camera/* -F: drivers/amlogic/media/common/canvas/canvas_mgr.c -F: drivers/amlogic/media/common/vfm/vfm.c -F: include/linux/amlogic/media/camera/* - AMLOGIC multimedia M: Pengcheng Chen F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index 795a7982de73..e4393da38f16 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -1017,13 +1017,6 @@ }; }; -&i2c2 { - status = "disabled"; - pinctrl-names="default"; - pinctrl-0=<&i2c2_master_pins2>; - clock-frequency = <100000>; -}; - &i2c3 { status = "okay"; pinctrl-names="default"; @@ -1363,32 +1356,6 @@ }; }; - clk12_24_z_pins:clk12_24_z_pins { - mux { - groups = "clk12_24_z"; - function = "clk12_24_ee"; - drive-strength = <3>; - }; - }; - - gen_clk_ee_z: gen_clk_ee_z { - mux { - groups="gen_clk_ee_z"; - function="gen_clk_ee"; - drive-strength = <3>; - }; - }; - - cam_dvp_pins:cam_dvp_pins { - mux { - groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", - "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", - "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", - "bt656_a_din6", "bt656_a_din7"; - function = "bt656"; - }; - }; - }; /* end of pinctrl_periphs */ &pinctrl_aobus { diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index f07a46f44ceb..c4d9059d1f60 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -329,9 +329,6 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y -CONFIG_AMLOGIC_VIDEO_CAPTURE=y -CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y -CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145=y CONFIG_AMLOGIC_DTV_DEMOD=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index cd3d653df59f..3c6981089c0c 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -150,12 +150,6 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; - vm0_cma_reserved:linux,vm0_cma { - compatible = "shared-dma-pool"; - reusable; - size = <0x0 0x2000000>; - alignment = <0x0 0x400000>; - }; }; gpioleds { @@ -302,54 +296,6 @@ dev_name = "ionvideo"; status = "okay"; }; - vm0 { - compatible = "amlogic, vm"; - memory-region = <&vm0_cma_reserved>; - dev_name = "vm0"; - status = "disabled"; - vm_id = <0>; - }; - - amvdec_656in { - /*bt656 gpio conflict with i2c0*/ - compatible = "amlogic, amvdec_656in"; - dev_name = "amvdec_656in"; - status = "disabled"; - reg = <0x0 0xffe02000 0x0 0x7c>; - clocks = <&clkc CLKID_BT656_COMP>, - <&clkc CLKID_BT656>; - clock-names = "cts_bt656_clk1", - "clk_gate_bt656"; - /* bt656in1, bt656in2 */ - bt656in1 { - bt656_id = <1>; - status = "disabled"; - }; - }; - - aml_cams { - compatible = "amlogic, cams_prober"; - status = "disabled"; - pinctrl-names="default"; - pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; - clocks = <&clkc CLKID_GEN_CLK>; - clock-names = "g12a_24m"; - cam_0{ - cam_name = "gc2145"; - front_back = <0>; - /*u200 i2c2 gpio conflict with ethmac*/ - camera-i2c-bus = <&i2c2>; - gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; - gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; - mirror_flip = <1>; - vertical_flip = <1>; - spread_spectrum = <0>; - bt_path = "gpio"; - bt_path_count = <1>; - vdin_path = <0>; - status = "okay"; - }; - }; gpio_keypad{ compatible = "amlogic, gpio_keypad"; @@ -1018,13 +964,6 @@ }; }; -&i2c2 { - status = "disabled"; - pinctrl-names="default"; - pinctrl-0=<&i2c2_master_pins2>; - clock-frequency = <100000>; -}; - &i2c3 { status = "okay"; pinctrl-names="default"; @@ -1364,32 +1303,6 @@ }; }; - clk12_24_z_pins:clk12_24_z_pins { - mux { - groups = "clk12_24_z"; - function = "clk12_24_ee"; - drive-strength = <3>; - }; - }; - - gen_clk_ee_z: gen_clk_ee_z { - mux { - groups="gen_clk_ee_z"; - function="gen_clk_ee"; - drive-strength = <3>; - }; - }; - - cam_dvp_pins:cam_dvp_pins { - mux { - groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", - "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", - "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", - "bt656_a_din6", "bt656_a_din7"; - function = "bt656"; - }; - }; - }; /* end of pinctrl_periphs */ &pinctrl_aobus { diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 9fb51faf6dde..f201b5de6668 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -324,9 +324,6 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y -CONFIG_AMLOGIC_VIDEO_CAPTURE=y -CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y -CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145=y CONFIG_AMLOGIC_DTV_DEMOD=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y diff --git a/drivers/amlogic/media/Kconfig b/drivers/amlogic/media/Kconfig index ded82c05b026..bc316278ce43 100644 --- a/drivers/amlogic/media/Kconfig +++ b/drivers/amlogic/media/Kconfig @@ -94,7 +94,6 @@ source "drivers/amlogic/media/video_processor/Kconfig" source "drivers/amlogic/media/enhancement/Kconfig" source "drivers/amlogic/media/gdc/Kconfig" source "drivers/amlogic/media/algorithm/Kconfig" -source "drivers/amlogic/media/camera/Kconfig" endif source "drivers/amlogic/media/dtv_demod/Kconfig" endmenu diff --git a/drivers/amlogic/media/Makefile b/drivers/amlogic/media/Makefile index 12f643b1e1d9..dfb73164f565 100644 --- a/drivers/amlogic/media/Makefile +++ b/drivers/amlogic/media/Makefile @@ -12,4 +12,3 @@ obj-$(CONFIG_AMLOGIC_DTV_DEMOD) += dtv_demod/ obj-$(CONFIG_AMLOGIC_MEDIA_GDC) += gdc/ obj-$(CONFIG_AMLOGIC_MEDIA_ALGORITHM) += algorithm/ -obj-$(CONFIG_AMLOGIC_VIDEO_CAPTURE) += camera/ \ No newline at end of file diff --git a/drivers/amlogic/media/camera/Kconfig b/drivers/amlogic/media/camera/Kconfig deleted file mode 100644 index 41d08be16cb7..000000000000 --- a/drivers/amlogic/media/camera/Kconfig +++ /dev/null @@ -1,559 +0,0 @@ -menu "Amlogic Camera Support" - -config AMLOGIC_VIDEO_CAPTURE - tristate "Amlogic Platform Capture Driver" - depends on !SPARC32 && !SPARC64 &&!AMLOGIC_CAMERA_ENABLE - select VIDEOBUF_VMALLOC - depends on MEDIA_SUPPORT - select VIDEO_DEV - select VIDEO_V4L2 - default n - ---help--- - Amlogic capture driver interface in v4l style. - it can not work well together with - AMLOGIC_CAMERA_ENABLE - Say Y here if you want this driver. - -config AMLOGIC_CAPTURE_FRAME_ROTATE - bool "Enable function to support frame rotation" - depends on AMLOGIC_VIDEO_CAPTURE - default n - ---help--- - It will support frame rotation when enable this config - It will support frame rotation when enable this config - It will support frame rotation when enable this config - It will support frame rotation when enable this config - -config AMLOGIC_VM_DISABLE_VIDEOLAYER - bool "Force disable Videolayer when use vm" - depends on AMLOGIC_VIDEO_CAPTURE - default n - ---help--- - It will disable amvideo provider when enable this config - It will disable amvideo provider when enable this config - It will disable amvideo provider when enable this config - It will disable amvideo provider when enable this config - -config AMLOGIC_VIDEO_CAPTURE_PROBE - bool "Force check whether camera devices exist" - depends on AMLOGIC_VIDEO_CAPTURE - default n - ---help--- - Probe whether the camera devices exist by trying to read its - i2c port. It may cost some time, say Y here if you want it. - Probe whether the camera devices exist by trying to read its - i2c port. It may cost some time, say Y here if you want it. - -config AMLCAP_LOG_TIME_USEFORFRAMES - bool "Print Out The Time(ms) For Process A Frame" - depends on AMLOGIC_VIDEO_CAPTURE - default n - ---help--- - Print out the time used for process a frame, only for developers. - Print out the time used for process a frame, only for developers. - Print out the time used for process a frame, only for developers. - Print out the time used for process a frame, only for developers. - -config AMLOGIC_VIDEO_CAPTURE_GT2005 - tristate "Amlogic Platform Capture Driver for GT2005" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC0307 - tristate "Amlogic Platform Capture Driver for GC0307" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC0308 - tristate "Amlogic Platform Capture Driver for GC0308" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC0328 - tristate "Amlogic Platform Capture Driver for GC0328" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN_BT656IN - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC0329 - tristate "Amlogic Platform Capture Driver for GC0329" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC2015 - tristate "Amlogic Platform Capture Driver for GC2015" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC2035 - tristate "Amlogic Platform Capture Driver for GC2035" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC2155 - tristate "Amlogic Platform Capture Driver for GC2155" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_GC2145 - tristate "Amlogic Platform Capture Driver for GC2145" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_OV5640 - tristate "Amlogic Platform Capture Driver for OV5640" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_OV5642 - tristate "Amlogic Platform Capture Driver for OV5642" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -choice - prompt "OV5642 AUTO FOCUS FIRMWARE" - depends on AMLOGIC_VIDEO_CAPTURE_OV5642 - default NO_AUTO_FUCOS - -config NO_AUTO_FUCOS - bool "NONE" - ---help--- - no auto focus - no auto focus - no auto focus - no auto focus - -config AD5820 - bool "AD5820" - ---help--- - AD5820 - AD5820 - AD5820 - AD5820 - -config DW9714 - bool "DW9714" - ---help--- - DW9714 - DW9714 - DW9714 - DW9714 - -config AP5120 - bool "AP5120" - ---help--- - AP5120 - AP5120 - AP5120 - AP5120 - -endchoice - -config AMLOGIC_VIDEO_CAPTURE_OV7675 - tristate "Amlogic Platform Capture Driver for OV7675" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_OV2655 - tristate "Amlogic Platform Capture Driver for OV2655" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_SP0838 - tristate "Amlogic Platform Capture Driver for SP0838" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select VIDEOBUF_RESOURCE - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_SP2518 - tristate "Amlogic Platform Capture Driver for SP2518" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select VIDEOBUF_RESOURCE - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_SP0A19 - tristate "Amlogic Platform Capture Driver for SP0A19" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_SP1628 - tristate "Amlogic Platform Capture Driver for SP1628" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_HI253 - tristate "Amlogic Platform Capture Driver for HI253" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_HI704 - tristate "Amlogic Platform Capture Driver for HI704" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_HM2057 - tristate "Amlogic Platform Capture Driver for HM2057" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_HM5065 - tristate "Amlogic Platform Capture Driver for HM5065" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_HM1375 - tristate "Amlogic Platform Capture Driver for HM1375" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_OV3660 - tristate "Amlogic Platform Capture Driver for OV3660" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_OV5647 - tristate "Amlogic Platform Capture Driver for OV5647" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - - -config AMLOGIC_VIDEO_CAPTURE_HI2056 - tristate "Amlogic Platform Capture Driver for HI2056" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_MIPI - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_NT99250 - tristate "Amlogic Platform Capture Driver for NT99250" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_NT99252 - tristate "Amlogic Platform Capture Driver for NT99252" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_NT99340 - tristate "Amlogic Platform Capture Driver for NT99340" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_AR0543 - tristate "Amlogic Platform Capture Driver for AR0543" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEO_CAPTURE_AR0833 - tristate "Amlogic Platform Capture Driver for AR0833" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - - -config AMLOGIC_VIDEO_CAPTURE_BF3720 - tristate "Amlogic Platform Capture Driver for BF3720" - depends on AMLOGIC_VIDEO_CAPTURE - select VIDEOBUF_VMALLOC - select AMLOGIC_VIDEOIN_MANAGER - select TVIN - select TVIN_BT656 - select TVIN_VDIN - default n - ---help--- - Amlogic capture driver. - Say Y here if you want this driver. - Amlogic capture driver. - Say Y here if you want this driver. - -config AMLOGIC_VIDEOIN_MANAGER - tristate "amlogic video manager" - default n - ---help--- - this a test for video manager - -endmenu diff --git a/drivers/amlogic/media/camera/Makefile b/drivers/amlogic/media/camera/Makefile deleted file mode 100644 index 04fb18c468d9..000000000000 --- a/drivers/amlogic/media/camera/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for the amlogic platform camera interface device drivers. -# -amlflash-objs := common/flashlight.o -amlcamera-objs := common/plat_ctrl.o -#common/util.o -amlvm-objs := common/vm.o -cam_prober-objs := common/cam_prober.o common/config_parser.o -gc2145dri-objs := gc2145.o - -obj-y += amlflash.o -obj-y += amlvm.o -obj-y += amlcamera.o -obj-y += cam_prober.o -obj-$(CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145) += gc2145dri.o diff --git a/drivers/amlogic/media/camera/common/cam_prober.c b/drivers/amlogic/media/camera/common/cam_prober.c deleted file mode 100644 index 98fe53121c85..000000000000 --- a/drivers/amlogic/media/camera/common/cam_prober.c +++ /dev/null @@ -1,1792 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/cam_prober.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CONFIG_ARCH_MESON8 - -static struct platform_device *cam_pdev; -static struct clk *cam_clk; -static unsigned int bt_path_count; - -static unsigned int camera0_pwdn_pin; -static unsigned int camera0_rst_pin; -static unsigned int camera1_pwdn_pin; -static unsigned int camera1_rst_pin; - -static struct aml_cam_info_s *temp_cam; - -static int aml_camera_read_buff(struct i2c_adapter *adapter, - unsigned short dev_addr, char *buf, - int addr_len, int data_len) -{ - int i2c_flag = -1; - struct i2c_msg msgs[] = {{ - .addr = dev_addr, .flags = 0, - .len = addr_len, .buf = buf, - }, { - .addr = dev_addr, .flags = I2C_M_RD, - .len = data_len, .buf = buf, - } - }; - - i2c_flag = i2c_transfer(adapter, msgs, 2); - - return i2c_flag; -} - -static int aml_camera_write_buff(struct i2c_adapter *adapter, - unsigned short dev_addr, char *buf, int len) -{ - struct i2c_msg msg[] = {{ - .addr = dev_addr, .flags = 0, /*I2C_M_TEN*/ - .len = len, .buf = buf, - } - }; - - if (i2c_transfer(adapter, msg, 1) < 0) - return -1; - else - return 0; -} - -static int aml_i2c_get_byte(struct i2c_adapter *adapter, - unsigned short dev_addr, unsigned short addr) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - - if (aml_camera_read_buff(adapter, dev_addr, buff, 2, 1) < 0) - return -1; - return buff[0]; -} - -static int aml_i2c_put_byte(struct i2c_adapter *adapter, - unsigned short dev_addr, unsigned short addr, - unsigned char data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - buff[2] = data; - if (aml_camera_write_buff(adapter, dev_addr, buff, 3) < 0) - return -1; - return 0; -} - -static int aml_i2c_get_byte_add8(struct i2c_adapter *adapter, - unsigned short dev_addr, - unsigned short addr) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)(addr & 0xff); - - if (aml_camera_read_buff(adapter, dev_addr, buff, 1, 1) < 0) - return -1; - return buff[0]; -} - -static int aml_i2c_put_byte_add8(struct i2c_adapter *adapter, - unsigned short dev_addr, - unsigned short addr, unsigned char data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)(addr & 0xff); - buff[1] = data; - if (aml_camera_write_buff(adapter, dev_addr, buff, 2) < 0) - return -1; - return 0; -} - -int aml_i2c_put_word(struct i2c_adapter *adapter, unsigned short dev_addr, - unsigned short addr, unsigned short data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - buff[2] = (unsigned char)((data >> 8) & 0xff); - buff[3] = (unsigned char)(data & 0xff); - if (aml_camera_write_buff(adapter, dev_addr, buff, 4) < 0) - return -1; - return 0; -} - -static int aml_i2c_get_word(struct i2c_adapter *adapter, - unsigned short dev_addr, unsigned short addr) -{ - int ret; - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - if (aml_camera_read_buff(adapter, dev_addr, buff, 2, 2) < 0) - return -1; - ret = (buff[0] << 8) | (buff[1]); - return ret; -} - -static int aml_i2c_get_word_add8(struct i2c_adapter *adapter, - unsigned short dev_addr, - unsigned short addr) -{ - int ret; - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - if (aml_camera_read_buff(adapter, dev_addr, buff, 2, 2) < 0) - return -1; - ret = buff[0] | (buff[1] << 8); - return ret; -} - -static int aml_i2c_put_word_add8(struct i2c_adapter *adapter, - unsigned short dev_addr, unsigned char addr, - unsigned short data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)(addr & 0xff); - buff[1] = (unsigned char)(data >> 8 & 0xff); - buff[2] = (unsigned char)(data & 0xff); - if (aml_camera_write_buff(adapter, dev_addr, buff, 3) < 0) - return -1; - return 0; -} - - -extern struct i2c_client * -i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0307 -int gc0307_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x21, 0x00); - if (reg == 0x99) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0308 -int gc0308_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x21, 0x00); - if (reg == 0x9b) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0328 -int gc0328_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x21, 0xf0); - if (reg == 0x9d) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0329 -int gc0329_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - aml_i2c_put_byte_add8(adapter, 0x31, 0xfc, 0x16); /*select page 0*/ - reg = aml_i2c_get_byte_add8(adapter, 0x31, 0x00); - if (reg == 0xc0) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2015 -int gc2015_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x30, 0x00); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x30, 0x01); - if (reg[0] == 0x20 && reg[1] == 0x05) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM2057 -int hm2057_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x24, 0x0001); - reg[1] = aml_i2c_get_byte(adapter, 0x24, 0x0002); - if (reg[0] == 0x20 && reg[1] == 0x56) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2035 -int gc2035_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf0); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf1); - if (reg[0] == 0x20 && reg[1] == 0x35) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2155 -int gc2155_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf0); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf1); - if (reg[0] == 0x21 && reg[1] == 0x55) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GT2005 -int gt2005_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x0000); - reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x0001); - if (reg[0] == 0x51 && reg[1] == 0x38) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV2659 -int ov2659_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x30, 0x300a); - reg[1] = aml_i2c_get_byte(adapter, 0x30, 0x300b); - if (reg[0] == 0x26 && reg[1] == 0x56) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3640 -int ov3640_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); - reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); - if (reg[0] == 0x36 && reg[1] == 0x4c) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3660 -int ov3660_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); - reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); - if (reg[0] == 0x36 && reg[1] == 0x60) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5640 -int ov5640_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); - reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); - if (reg[0] == 0x56 && reg[1] == 0x40) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5642 -int ov5642_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); - reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); - if (reg[0] == 0x56 && reg[1] == 0x42) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV7675 -int ov7675_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x21, 0x0a); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x21, 0x0b); - if (reg[0] == 0x76 && reg[1] == 0x73) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0A19 -int sp0a19_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x21, 0x02); - if (reg == 0xa6) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP2518 -int sp2518_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x30, 0x02); - pr_info("sp2518 chip id reg = %x .\n", reg); - if (reg == 0x53) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0838 -int sp0838_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x18, 0x02); - if (reg == 0x27) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI253 -int hi253_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg; - - reg = aml_i2c_get_byte_add8(adapter, 0x20, 0x04); - if (reg == 0x92) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM5065 -int hm5065_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x1F, 0x0000); - reg[1] = aml_i2c_get_byte(adapter, 0x1F, 0x0001); - if (reg[0] == 0x03 && reg[1] == 0x9e) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM1375 -int hm1375_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x24, 0x0001); - reg[1] = aml_i2c_get_byte(adapter, 0x24, 0x0002); - pr_info("hm1375_v4l2_probe: device ID: 0x%x%x", reg[0], reg[1]); - if ((reg[0] == 0x13 || reg[0] == 0x03) && reg[1] == 0x75) - ret = 1; - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI2056 -int hi2056_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x24, 0x0001); - reg[1] = aml_i2c_get_byte(adapter, 0x24, 0x0002); - pr_info("reg[0]=%x, reg[1]=%x\n", reg[0], reg[1]); - if (reg[0] == 0x20 && reg[1] == 0x56) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5647 -int ov5647_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte(adapter, 0x36, 0x300a); - reg[1] = aml_i2c_get_byte(adapter, 0x36, 0x300b); - pr_info("reg[0]:%x,reg[1]:%x\n", reg[0], reg[1]); - if (reg[0] == 0x56 && reg[1] == 0x47) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0543 -int ar0543_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0, reg_val; - - reg_val = aml_i2c_get_word(adapter, 0x36, 0x3000); - pr_info("reg:0x%x\n", reg_val); - if (reg_val == 0x4800) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0833 -int ar0833_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0, reg_val; - - reg_val = aml_i2c_get_word(adapter, 0x36, 0x3000); - pr_info("reg:0x%x\n", reg_val); - if (reg_val == 0x4B03) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP1628 -int sp1628_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0x02); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xa0); - if (reg[0] == 0x16 && reg[1] == 0x28) - ret = 1; - return ret; -} -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3720 -int bf3720_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfc); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfd); - if (reg[0] == 0x37 && reg[1] == 0x20) - ret = 1; - return ret; -} -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3703 -int __init bf3703_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfc); /*i2c addr:0x6f*/ - reg[1] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfd); - if (reg[0] == 0x37 && reg[1] == 0x03) - ret = 1; - return ret; -} -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3920 -int __init bf3920_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfc); /*i2c addr:0x6f*/ - reg[1] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfd); - if (reg[0] == 0x39 && reg[1] == 0x20) - ret = 1; - return ret; -} -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145 -int __init gc2145_v4l2_probe(struct i2c_adapter *adapter) -{ - int ret = 0; - unsigned char reg[2]; - - reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf0); - reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf1); - /*datasheet chip id is error*/ - if (reg[0] == 0x21 && reg[1] == 0x45) - ret = 1; - pr_info("%s, ret = %d\n", __func__, ret); - return ret; -} -#endif - -struct aml_cam_dev_info_s { - unsigned char addr; - char *name; - unsigned char pwdn; - enum resolution_size max_cap_size; - aml_cam_probe_fun_t probe_func; -}; - -static const struct aml_cam_dev_info_s cam_devs[] = { -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0307 - { - .addr = 0x21, - .name = "gc0307", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = gc0307_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0308 - { - .addr = 0x21, - .name = "gc0308", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = gc0308_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0328 - { - .addr = 0x21, - .name = "gc0328", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = gc0328_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0329 - { - .addr = 0x31, - .name = "gc0329", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = gc0329_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2015 - { - .addr = 0x30, - .name = "gc2015", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = gc2015_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM2057 - { - .addr = 0x24, - .name = "hm2057", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = hm2057_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2035 - { - .addr = 0x3c, - .name = "gc2035", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = gc2035_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2155 - { - .addr = 0x3c, - .name = "gc2155", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = gc2155_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GT2005 - { - .addr = 0x3c, - .name = "gt2005", - .pwdn = 0, - .max_cap_size = SIZE_1600X1200, - .probe_func = gt2005_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV2659 - { - .addr = 0x30, - .name = "ov2659", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = ov2659_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3640 - { - .addr = 0x3c, - .name = "ov3640", - .pwdn = 1, - .max_cap_size = SIZE_2048X1536; - .probe_func = ov3640_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3660 - { - .addr = 0x3c, - .name = "ov3660", - .pwdn = 1, - .max_cap_size = SIZE_2048X1536, - .probe_func = ov3660_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5640 - { - .addr = 0x3c, - .name = "ov5640", - .pwdn = 1, - .max_cap_size = SIZE_2592X1944, - .probe_func = ov5640_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5642 - { - .addr = 0x3c, - .name = "ov5642", - .pwdn = 1, - .max_cap_size = SIZE_2592X1944, - .probe_func = ov5642_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5647 - { - .addr = 0x36, /* really value should be 0x6c */ - .name = "ov5647", .pwdn = 1, .max_cap_size = SIZE_2592X1944, - .probe_func = ov5647_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV7675 - { - .addr = 0x21, - .name = "ov7675", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = ov7675_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0A19 - { - .addr = 0x21, - .name = "sp0a19", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = sp0a19_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0838 - { - .addr = 0x18, - .name = "sp0838", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = sp0838_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP2518 - { - .addr = 0x30, - .name = "sp2518", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = sp2518_v4l2_probe, - }, -#endif - -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI253 - { - .addr = 0x20, - .name = "hi253", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = hi253_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM5065 - { - .addr = 0x1f, - .name = "hm5065", - .pwdn = 0, - .max_cap_size = SIZE_2592X1944, - .probe_func = hm5065_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM1375 - { - .addr = 0x24, - .name = "hm1375", - .pwdn = 1, - .max_cap_size = SIZE_1280X1024, - .probe_func = hm1375_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI2056 - { - .addr = 0x24, - .name = "mipi-hi2056", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = hi2056_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0543 - { - .addr = 0x36, - .name = "ar0543", - .pwdn = 0, - .max_cap_size = SIZE_2592X1944, - .probe_func = ar0543_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0833 - { - .addr = 0x36, - .name = "ar0833", - .pwdn = 0, - .max_cap_size = SIZE_2592X1944, - .probe_func = ar0833_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP1628 - { - .addr = 0x3c, - .name = "sp1628", - .pwdn = 1, - .max_cap_size = SIZE_1280X960, - .probe_func = sp1628_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3720 - { - .addr = 0x6e, - .name = "bf3720", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = bf3720_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3703 - { - .addr = 0x6e, - .name = "bf3703", - .pwdn = 1, - .max_cap_size = SIZE_640X480, - .probe_func = bf3703_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3920 - { - .addr = 0x6e, - .name = "bf3920", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = bf3920_v4l2_probe, - }, -#endif -#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145 - { - .addr = 0x3c, - .name = "gc2145", - .pwdn = 1, - .max_cap_size = SIZE_1600X1200, - .probe_func = gc2145_v4l2_probe, - }, -#endif -}; - -static const struct aml_cam_dev_info_s *get_cam_info_by_name(const char *name) -{ - int i; - - if (!name) - return NULL; - /*pr_info("cam_devs num is %d\n", ARRAY_SIZE(cam_devs));*/ - for (i = 0; i < ARRAY_SIZE(cam_devs); i++) { - if (!strcmp(name, cam_devs[i].name)) { - pr_info("camera dev %s found\n", cam_devs[i].name); - pr_info("camera i2c addr: 0x%x\n", cam_devs[i].addr); - return &cam_devs[i]; - } - } - return NULL; -} - -struct res_item { - enum resolution_size size; - char *name; -}; - -static const struct res_item res_item_array[] = { - {SIZE_320X240, "320X240"}, { - SIZE_640X480, "640X480" - }, {SIZE_720X405, "720X405"}, { - SIZE_800X600, "800X600" - }, {SIZE_960X540, "960X540"}, { - SIZE_1024X576, "1024X576" - }, {SIZE_960X720, "960X720"}, { - SIZE_1024X768, "1024X768" - }, {SIZE_1280X720, "1280X720"}, { - SIZE_1152X864, "1152X864" - }, {SIZE_1366X768, "1366X768"}, { - SIZE_1280X960, "1280X960" - }, {SIZE_1280X1024, "1280X1024"}, { - SIZE_1400X1050, "1400X1050" - }, {SIZE_1600X900, "1600X900"}, { - SIZE_1600X1200, "1600X1200" - }, {SIZE_1920X1080, "1920X1080"}, { - SIZE_1792X1344, "1792X1344" - }, {SIZE_2048X1152, "2048X1152"}, { - SIZE_2048X1536, "2048X1536" - }, {SIZE_2304X1728, "2304X1728"}, { - SIZE_2560X1440, "2560X1440" - }, {SIZE_2592X1944, "2592X1944"}, { - SIZE_3072X1728, "3072X1728" - }, {SIZE_2816X2112, "2816X2112"}, { - SIZE_3072X2304, "3072X2304" - }, {SIZE_3200X2400, "3200X2400"}, { - SIZE_3264X2448, "3264X2448" - }, {SIZE_3840X2160, "3840X2160"}, { - SIZE_3456X2592, "3456X2592" - }, {SIZE_3600X2700, "3600X2700"}, { - SIZE_4096X2304, "4096X2304" - }, {SIZE_3672X2754, "3672X2754"}, { - SIZE_3840X2880, "3840X2880" - }, {SIZE_4000X3000, "4000X3000"}, { - SIZE_4608X2592, "4608X2592" - }, {SIZE_4096X3072, "4096X3072"}, { - SIZE_4800X3200, "4800X3200" - }, {SIZE_5120X2880, "5120X2880"}, { - SIZE_5120X3840, "5120X3840" - }, {SIZE_6400X4800, "6400X480"}, - -}; - -static enum resolution_size get_res_size(const char *res_str) -{ - enum resolution_size ret = SIZE_NULL; - const struct res_item *item; - int i; - - if (!res_str) - return SIZE_NULL; - for (i = 0; i < ARRAY_SIZE(res_item_array); i++) { - item = &res_item_array[i]; - if (!strcmp(item->name, res_str)) { - ret = item->size; - return ret; - } - } - - return ret; -} - -static inline void GXBB_cam_enable_clk(void) -{ - struct clk *clk; - - clk = clk_get(&cam_pdev->dev, "clk_camera_24"); - if (IS_ERR(clk)) { - pr_info("cannot get camera m-clock\n"); - clk = NULL; - } else { - cam_clk = clk; - clk_prepare_enable(clk); - } -} - -static inline void GXBB_cam_disable_clk(int spread_spectrum) -{ - if (cam_clk) { - clk_disable_unprepare(cam_clk); - clk_put(cam_clk); - } -} - -static inline void GX12_cam_enable_clk(void) -{ - struct clk *clk; - unsigned long clk_rate; - - clk = devm_clk_get(&cam_pdev->dev, "g12a_24m"); - if (IS_ERR(clk)) { - pr_info("cannot get camera m-clock\n"); - clk = NULL; - } else { - cam_clk = clk; - clk_set_rate(clk, 24000000); - clk_prepare_enable(clk); - clk_rate = clk_get_rate(clk); - } -} - -static inline void GX12_cam_disable_clk(int spread_spectrum) -{ - if (cam_clk) { - clk_disable_unprepare(cam_clk); - devm_clk_put(&cam_pdev->dev, cam_clk); - pr_info("Success disable mclk\n"); - } -} - -static inline void cam_enable_clk(int clk, int spread_spectrum) -{ - pr_err("camera mclk enable failed, unsupport chip\n"); -} - -static inline void cam_disable_clk(int spread_spectrum) -{ - pr_err("camera mclk disable failed, unsupport chip\n"); -} - -/*static struct platform_device *cam_pdev;*/ - -void aml_cam_init(struct aml_cam_info_s *cam_dev) -{ - /*select XTAL as camera clock*/ - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) - GXBB_cam_enable_clk(); - else if ((get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_G12B)) - GX12_cam_enable_clk(); - else - cam_enable_clk(cam_dev->mclk, cam_dev->spread_spectrum); - - /*coding style need: msleep < 20ms can sleep for up to 20ms*/ - msleep(20); - /*set camera power enable*/ - if (!cam_dev->front_back) { - cam_dev->pwdn_pin = camera0_pwdn_pin; - cam_dev->rst_pin = camera0_rst_pin; - } else { - cam_dev->pwdn_pin = camera1_pwdn_pin; - cam_dev->rst_pin = camera1_rst_pin; - } - - gpio_direction_output(cam_dev->pwdn_pin, cam_dev->pwdn_act); - - msleep(20); - - gpio_direction_output(cam_dev->pwdn_pin, !(cam_dev->pwdn_act)); - - msleep(20); - - gpio_direction_output(cam_dev->rst_pin, 0); - - msleep(20); - - gpio_direction_output(cam_dev->rst_pin, 1); - - msleep(20); - - pr_info("aml_cams: %s init OK\n", cam_dev->name); - -} - -void aml_cam_uninit(struct aml_cam_info_s *cam_dev) -{ - int ret; - - pr_info("aml_cams: %s uninit.\n", cam_dev->name); - /*set camera power disable*/ - /*coding style need: msleep < 20ms can sleep for up to 20ms*/ - /*msleep(20);*/ - - ret = gpio_direction_output(cam_dev->pwdn_pin, cam_dev->pwdn_act); - if (ret < 0) - pr_info("aml_cam_uninit pwdn_pin output pwdn_act failed\n"); - - msleep(20); - - ret = gpio_direction_output(cam_dev->rst_pin, 0); - if (ret < 0) - pr_info("aml_cam_uninit rst_pin output rst_pin failed\n"); - - msleep(20); - - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) - GXBB_cam_disable_clk(cam_dev->spread_spectrum); - else if ((get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_G12B)) - GX12_cam_disable_clk(cam_dev->spread_spectrum); - else - cam_disable_clk(cam_dev->spread_spectrum); -} - -void aml_cam_flash(struct aml_cam_info_s *cam_dev, int is_on) -{ - int ret; - - if (cam_dev->flash_support) { - pr_info("aml_cams: %s flash %s.\n", - cam_dev->name, is_on ? "on" : "off"); - - ret = gpio_direction_output(cam_dev->flash_ctrl_pin, - cam_dev->flash_ctrl_level ? is_on : !is_on); - if (ret < 0) - pr_info("aml_cam_flash flash_ctrl_pin output failed\n"); - } -} - -void aml_cam_torch(struct aml_cam_info_s *cam_dev, int is_on) -{ - int ret; - - if (cam_dev->torch_support) { - pr_info("aml_cams: %s torch %s.\n", - cam_dev->name, is_on ? "on" : "off"); - - ret = gpio_direction_output(cam_dev->torch_ctrl_pin, - cam_dev->torch_ctrl_level ? is_on : !is_on); - if (ret < 0) - pr_info("aml_cam_torch torch_ctrl_pin output failed\n"); - } -} - -static struct list_head cam_head = LIST_HEAD_INIT(cam_head); - -#define DEBUG_DUMP_CAM_INFO - -static int fill_csi_dev(struct device_node *p_node, - struct aml_cam_info_s *cam_dev) -{ - const char *str; - int ret = 0; - - ret = of_property_read_string(p_node, "clk_channel", &str); - if (ret) { - pr_info("failed to read clock channel, \"a or b\"\n"); - cam_dev->clk_channel = CLK_CHANNEL_A; - } else { - pr_info("clock channel:clk %s\n", str); - if (strncmp("a", str, 1) == 0) - cam_dev->clk_channel = CLK_CHANNEL_A; - else - cam_dev->clk_channel = CLK_CHANNEL_B; - } - - return ret; - -} -static int fill_cam_dev(struct device_node *p_node, - struct aml_cam_info_s *cam_dev) -{ - const char *str; - int ret = 0; - const struct aml_cam_dev_info_s *cam_info = NULL; - struct device_node *adapter_node = NULL; - struct i2c_adapter *adapter = NULL; - unsigned int mclk = 0; - unsigned int vcm_mode = 0; - - if (!p_node || !cam_dev) - return -1; - - ret = of_property_read_u32(p_node, "front_back", &cam_dev->front_back); - if (ret) { - pr_info("get camera name failed!\n"); - goto err_out; - } - - ret = of_property_read_string(p_node, "cam_name", &cam_dev->name); - if (ret) { - pr_info("get camera name failed!\n"); - goto err_out; - } - - cam_dev->pwdn_pin = of_get_named_gpio(p_node, "gpio_pwdn-gpios", 0); - if (cam_dev->pwdn_pin == 0) { - pr_info("%s: failed to map gpio_pwdn !\n", cam_dev->name); - goto err_out; - } - - ret = gpio_request(cam_dev->pwdn_pin, "camera"); - if (ret < 0) - pr_info("aml_cam_init pwdn_pin request failed\n"); - - if (!cam_dev->front_back) - camera0_pwdn_pin = cam_dev->pwdn_pin; - else - camera1_pwdn_pin = cam_dev->pwdn_pin; - - cam_dev->rst_pin = of_get_named_gpio(p_node, "gpio_rst-gpios", 0); - if (cam_dev->rst_pin == 0) { - pr_info("%s: failed to map gpio_rst !\n", cam_dev->name); - goto err_out; - } - ret = gpio_request(cam_dev->rst_pin, "camera"); - if (ret < 0) - pr_info("aml_cam_init rst_pin request failed\n"); - - if (!cam_dev->front_back) - camera0_rst_pin = cam_dev->rst_pin; - else - camera1_rst_pin = cam_dev->rst_pin; - - cam_info = get_cam_info_by_name(cam_dev->name); - if (cam_info == NULL) { - pr_info("camera %s is not support\n", cam_dev->name); - ret = -1; - goto err_out; - } - - of_property_read_u32(p_node, "spread_spectrum", - &cam_dev->spread_spectrum); - - ret = of_property_read_string(p_node, "bt_path", &str); - if (ret) { - pr_info("failed to read bt_path\n"); - cam_dev->bt_path = BT_PATH_GPIO; - } else { - pr_info("bt_path :%d\n", cam_dev->bt_path); - if (strncmp("csi", str, 3) == 0) - cam_dev->bt_path = BT_PATH_CSI2; - else if (strncmp("gpio_b", str, 6) == 0) - cam_dev->bt_path = BT_PATH_GPIO_B; - else - cam_dev->bt_path = BT_PATH_GPIO; - } - of_property_read_u32(p_node, "bt_path_count", &cam_dev->bt_path_count); - bt_path_count = cam_dev->bt_path_count; - - cam_dev->pwdn_act = cam_info->pwdn; - cam_dev->i2c_addr = cam_info->addr; - pr_info("camer addr: 0x%x\n", cam_dev->i2c_addr); - pr_info("camer i2c bus: %d\n", cam_dev->i2c_bus_num); - - adapter_node = of_parse_phandle(p_node, "camera-i2c-bus", 0); - if (adapter_node) { - adapter = of_find_i2c_adapter_by_node(adapter_node); - of_node_put(adapter_node); - if (adapter == NULL) { - pr_err("%s, failed parse camera-i2c-bus\n", - __func__); - return -1; - } - } - - if (adapter && cam_info->probe_func) { - aml_cam_init(cam_dev); - if (cam_info->probe_func(adapter) != 1) { - pr_info("camera %s not on board\n", cam_dev->name); - ret = -1; - aml_cam_uninit(cam_dev); - goto err_out; - } - aml_cam_uninit(cam_dev); - } else { - pr_err("can not do probe function\n"); - ret = -1; - goto err_out; - } - - of_property_read_u32(p_node, "mirror_flip", &cam_dev->m_flip); - of_property_read_u32(p_node, "vertical_flip", &cam_dev->v_flip); - of_property_read_u32(p_node, "vdin_path", &cam_dev->vdin_path); - - ret = of_property_read_string(p_node, "max_cap_size", &str); - if (ret) - pr_info("failed to read max_cap_size\n"); - else { - pr_info("max_cap_size :%s\n", str); - cam_dev->max_cap_size = get_res_size(str); - } - if (cam_dev->max_cap_size == SIZE_NULL) - cam_dev->max_cap_size = cam_info->max_cap_size; - - ret = of_property_read_u32(p_node, "mclk", &mclk); - if (ret) - cam_dev->mclk = 24000; - else - cam_dev->mclk = mclk; - - ret = of_property_read_u32(p_node, "vcm_mode", &vcm_mode); - if (ret) - cam_dev->vcm_mode = 0; - else - cam_dev->vcm_mode = vcm_mode; - pr_info("vcm mode is %d\n", cam_dev->vcm_mode); - - ret = of_property_read_u32(p_node, "flash_support", - &cam_dev->flash_support); - if (cam_dev->flash_support) { - of_property_read_u32(p_node, "flash_ctrl_level", - &cam_dev->flash_ctrl_level); - ret = of_property_read_string(p_node, "flash_ctrl_pin", &str); - if (ret) { - pr_info("%s: failed to get flash_ctrl_pin!\n", - cam_dev->name); - cam_dev->flash_support = 0; - } else { - cam_dev->flash_ctrl_pin = of_get_named_gpio(p_node, - "flash_ctrl_pin", 0); - if (cam_dev->flash_ctrl_pin == 0) { - pr_info("%s: failed to map flash_ctrl_pin !\n", - cam_dev->name); - cam_dev->flash_support = 0; - cam_dev->flash_ctrl_level = 0; - } - ret = gpio_request(cam_dev->flash_ctrl_pin, "camera"); - if (ret < 0) - pr_info("camera flash_ctrl_pin request failed\n"); - } - } - - ret = of_property_read_u32(p_node, "torch_support", - &cam_dev->torch_support); - if (cam_dev->torch_support) { - of_property_read_u32(p_node, "torch_ctrl_level", - &cam_dev->torch_ctrl_level); - ret = of_property_read_string(p_node, "torch_ctrl_pin", &str); - if (ret) { - pr_info("%s: failed to get torch_ctrl_pin!\n", - cam_dev->name); - cam_dev->torch_support = 0; - } else { - cam_dev->torch_ctrl_pin = of_get_named_gpio(p_node, - "torch_ctrl_level", 0); - ret = gpio_request(cam_dev->torch_ctrl_pin, "camera"); - if (ret < 0) - pr_info("camera torch_ctrl_pin request failed\n"); - } - } - - ret = of_property_read_string(p_node, "interface", &str); - if (ret) { - pr_info("failed to read camera interface \"mipi or dvp\"\n"); - cam_dev->interface = CAM_DVP; - } else { - pr_info("camera interface:%s\n", str); - if (strncmp("dvp", str, 1) == 0) - cam_dev->interface = CAM_DVP; - else - cam_dev->interface = CAM_MIPI; - } - if (cam_dev->interface == CAM_MIPI) { - ret = fill_csi_dev(p_node, cam_dev); - if (ret < 0) - goto err_out; - } - - ret = of_property_read_string(p_node, "bayer_fmt", &str); - if (ret) { - pr_info("failed to read camera bayer fmt\n"); - cam_dev->bayer_fmt = TVIN_GBRG; - } else { - pr_info("color format:%s\n", str); - if (strncmp("BGGR", str, 4) == 0) - cam_dev->bayer_fmt = TVIN_BGGR; - else if (strncmp("RGGB", str, 4) == 0) - cam_dev->bayer_fmt = TVIN_RGGB; - else if (strncmp("GBRG", str, 4) == 0) - cam_dev->bayer_fmt = TVIN_GBRG; - else if (strncmp("GRBG", str, 4) == 0) - cam_dev->bayer_fmt = TVIN_GRBG; - else - cam_dev->bayer_fmt = TVIN_GBRG; - } - - ret = of_property_read_string(p_node, "config_path", &cam_dev->config); - if (ret) - pr_info("failed to read config_file path\n"); - else - pr_info("config path :%s\n", cam_dev->config); - -#ifdef DEBUG_DUMP_CAM_INFO - pr_info("=======cam %s info=======\n" - "i2c_bus_num: %d\n" - "pwdn_act: %d\n" - "front_back: %d\n" - "m_flip: %d\n" - "v_flip: %d\n" - "i2c_addr: 0x%x\n" - "config path:%s\n" - "bt_path:%d\n", - cam_dev->name, cam_dev->i2c_bus_num, cam_dev->pwdn_act, - cam_dev->front_back, cam_dev->m_flip, cam_dev->v_flip, - cam_dev->i2c_addr, cam_dev->config, cam_dev->bt_path); -#endif /* DEBUG_DUMP_CAM_INFO */ - - ret = 0; - -err_out: - return ret; -} - -static int do_read_work(char argn, char **argv) -{ - unsigned int dev_addr, reg_addr, data_len = 1, result; - unsigned int i2c_bus; - struct i2c_adapter *adapter; - - if (argn < 4) { - pr_err("args num error"); - return -1; - } - - if (!strncmp(argv[1], "i2c_bus_ao", 9)) - i2c_bus = 4; - else if (!strncmp(argv[1], "i2c_bus_0", 9)) - i2c_bus = 0; - else if (!strncmp(argv[1], "i2c_bus_1", 9)) - i2c_bus = 1; - else if (!strncmp(argv[1], "i2c_bus_2", 9)) - i2c_bus = 2; - else if (!strncmp(argv[1], "i2c_bus_3", 9)) - i2c_bus = 3; - else { - pr_err("bus name error!\n"); - return -1; - } - - adapter = i2c_get_adapter(i2c_bus); - - if (adapter == NULL) { - pr_info("no adapter!\n"); - return -1; - } - - dev_addr = kstrtol(argv[2], 16, NULL); - reg_addr = kstrtol(argv[3], 16, NULL); - if (argn == 5) { - pr_info("argv[4] is %s\n", argv[4]); - data_len = kstrtol(argv[4], 16, NULL); - } - - if (reg_addr > 256) { - if (data_len != 2) { - result = aml_i2c_get_byte(adapter, dev_addr, reg_addr); - pr_info("register [0x%04x]=0x%02x\n", reg_addr, result); - } else { - result = aml_i2c_get_word(adapter, dev_addr, reg_addr); - pr_info("register [0x%04x]=0x%04x\n", reg_addr, result); - } - } else { - if (data_len != 2) { - result = aml_i2c_get_byte_add8(adapter, - dev_addr, reg_addr); - pr_info("register [0x%02x]=0x%02x\n", reg_addr, result); - } else { - result = aml_i2c_get_word_add8(adapter, - dev_addr, reg_addr); - pr_info("register [0x%02x]=0x%04x\n", reg_addr, result); - } - } - - return 0; -} - -static int do_write_work(char argn, char **argv) -{ - unsigned int dev_addr, reg_addr, reg_val, data_len = 1, ret = 0; - unsigned int i2c_bus; - struct i2c_adapter *adapter; - - if (argn < 5) { - pr_err("args num error"); - return -1; - } - - if (!strncmp(argv[1], "i2c_bus_0", 9)) - i2c_bus = 0; - else if (!strncmp(argv[1], "i2c_bus_1", 9)) - i2c_bus = 1; - else if (!strncmp(argv[1], "i2c_bus_2", 9)) - i2c_bus = 2; - else if (!strncmp(argv[1], "i2c_bus_3", 9)) - i2c_bus = 3; - else if (!strncmp(argv[1], "i2c_bus_ao", 9)) - i2c_bus = 4; - else { - pr_err("bus name error!\n"); - return -1; - } - - adapter = i2c_get_adapter(i2c_bus); - - if (adapter == NULL) { - pr_info("no adapter!\n"); - return -1; - } - - dev_addr = kstrtol(argv[2], 16, NULL); - reg_addr = kstrtol(argv[3], 16, NULL); - reg_val = kstrtol(argv[4], 16, NULL); - if (argn == 6) - data_len = kstrtol(argv[5], 16, NULL); - if (reg_addr > 256) { - if (data_len != 2) { - if (aml_i2c_put_byte(adapter, dev_addr, - reg_addr, reg_val) < 0) { - pr_err("write error\n"); - ret = -1; - } else { - pr_info("write ok\n"); - ret = 0; - } - } else { - if (aml_i2c_put_word(adapter, dev_addr, - reg_addr, reg_val) < 0) { - pr_err("write error\n"); - ret = -1; - } else { - pr_info("write ok\n"); - ret = 0; - } - } - } else { - if (data_len != 2) { - if (aml_i2c_put_byte_add8(adapter, dev_addr, - reg_addr, reg_val) < 0) { - pr_err("write error\n"); - ret = -1; - } else { - pr_info("write ok\n"); - ret = 0; - } - } else { - if (aml_i2c_put_word_add8(adapter, dev_addr, - reg_addr, reg_val) < 0) { - pr_err("write error\n"); - ret = -1; - } else { - pr_info("write ok\n"); - ret = 0; - } - } - } - - return ret; -} - -static struct class *cam_clsp; - -static ssize_t show_help(struct class *class, struct class_attribute *attr, - char *buf) -{ - ssize_t size = 0; - - pr_info( - "echo [read | write] i2c_bus_type device_address register_address [value] [data_len] > i2c_debug\n" - "i2c_bus_type are: i2c_bus_ao, i2c_bus_a, i2c_bus_b, i2c_bus_c, i2c_bus_d\n" - "e.g.: echo read i2c_bus_ao 0x3c 0x18 1\n" - " echo write i2c_bus_ao 0x3c 0x18 0x24 1\n"); - return size; -} - -static ssize_t store_i2c_debug(struct class *class, - struct class_attribute *attr, const char *buf, - size_t count) -{ - int argn; - char *buf_work, *p, *para; - char cmd; - char *argv[6]; - - buf_work = kstrdup(buf, GFP_KERNEL); - p = buf_work; - - for (argn = 0; argn < 6; argn++) { - para = strsep(&p, " "); - if (para == NULL) - break; - argv[argn] = para; - pr_info("argv[%d] = %s\n", argn, para); - } - - if (argn < 4 || argn > 6) - goto end; - - cmd = argv[0][0]; - switch (cmd) { - case 'r': - case 'R': - do_read_work(argn, argv); - break; - case 'w': - case 'W': - do_write_work(argn, argv); - break; - } - return count; -end: - pr_err("error command!\n"); - kfree(buf_work); - return -EINVAL; -} - -static LIST_HEAD(info_head); - -static ssize_t cam_info_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - struct list_head *p; - struct aml_cam_info_s *cam_info = NULL; - int count = 0; - - if (!list_empty(&info_head)) { - count += sprintf(&buf[count], - "name\t\tversion\t\t\t\tface_dir\t" - "i2c_addr\n"); - list_for_each(p, &info_head) { - cam_info = list_entry(p, struct aml_cam_info_s, - info_entry); - } - } - return count; -} - -static struct class_attribute aml_cam_attrs[] = { - __ATTR(i2c_debug, 0644, show_help, store_i2c_debug), - __ATTR_RO(cam_info), __ATTR(help, 0644, show_help, NULL), - __ATTR_NULL, -}; - -int aml_cam_info_reg(struct aml_cam_info_s *cam_info) -{ - int ret = -1; - - if (cam_info) { - list_add(&cam_info->info_entry, &info_head); - ret = 0; - } - return ret; -} - -int aml_cam_info_unreg(struct aml_cam_info_s *cam_info) -{ - int ret = -1; - struct list_head *p, *n; - struct aml_cam_info_s *tmp_info = NULL; - - if (cam_info) { - list_for_each_safe(p, n, &info_head) { - tmp_info = list_entry(p, struct aml_cam_info_s, - info_entry); - if (tmp_info == cam_info) { - list_del(p); - return 0; - } - } - } - return ret; -} - -static int aml_cams_probe(struct platform_device *pdev) -{ - struct device_node *cams_node = pdev->dev.of_node; - struct device_node *child; - struct i2c_board_info board_info; - struct i2c_adapter *adapter = NULL; - struct device_node *adapter_node = NULL; - struct timeval camera_start; - struct timeval camera_end; - int i; - unsigned long time_use = 0; - - temp_cam = kzalloc(sizeof(struct aml_cam_info_s), GFP_KERNEL); - if (!temp_cam) - return -ENOMEM; - - cam_pdev = pdev; - do_gettimeofday(&camera_start); - for_each_child_of_node(cams_node, child) { - - memset(temp_cam, 0, sizeof(struct aml_cam_info_s)); - - if (fill_cam_dev(child, temp_cam)) - continue; - - /*register exist camera*/ - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, temp_cam->name, I2C_NAME_SIZE); - - adapter_node = of_parse_phandle(child, "camera-i2c-bus", 0); - if (adapter_node) { - adapter = of_get_i2c_adapter_by_node(adapter_node); - of_node_put(adapter_node); - if (adapter == NULL) { - pr_err("%s, failed parse camera-i2c-bus\n", - __func__); - return -1; - } - } else { - pr_err("adapter node is NULL.\n"); - return -1; - } - board_info.addr = temp_cam->i2c_addr; - board_info.platform_data = temp_cam; - pr_info("new i2c device\n"); - /*i2c_new_existing_device(adapter, &board_info)*/ - i2c_new_device(adapter, &board_info); - } - do_gettimeofday(&camera_end); - time_use = (camera_end.tv_sec - camera_start.tv_sec) * 1000 + - (camera_end.tv_usec - camera_start.tv_usec) / 1000; - pr_info("camera probe cost time = %ldms\n", time_use); - - pr_info("aml probe finish\n"); - cam_clsp = class_create(THIS_MODULE, "aml_camera"); - for (i = 0; aml_cam_attrs[i].attr.name; i++) { - if (class_create_file(cam_clsp, &aml_cam_attrs[i]) < 0) - return -1; - } - - return 0; -} - -static int aml_cams_remove(struct platform_device *pdev) -{ - if (camera0_pwdn_pin != 0) - gpio_free(camera0_pwdn_pin); - if (camera0_rst_pin != 0) - gpio_free(camera0_rst_pin); - if (camera1_pwdn_pin != 0) - gpio_free(camera1_pwdn_pin); - if (camera1_rst_pin != 0) - gpio_free(camera1_rst_pin); - - kfree(temp_cam); - temp_cam = NULL; - - return 0; -} - -static const struct of_device_id cams_prober_dt_match[] = {{ - .compatible = - "amlogic, cams_prober", - }, {}, -}; - -static struct platform_driver aml_cams_prober_driver = { - .probe = aml_cams_probe, .remove = aml_cams_remove, .driver = { - .name = - "aml_cams_prober", .owner = THIS_MODULE, .of_match_table = - cams_prober_dt_match, - }, -}; - -static int __init aml_cams_prober_init(void) -{ - if (platform_driver_register(&aml_cams_prober_driver)) { - pr_err("aml_cams_probre_driver register failed\n"); - return -ENODEV; - } - - return 0; -} - -static void __exit aml_cams_prober_exit(void) -{ - bt_path_count = 0; - platform_driver_unregister(&aml_cams_prober_driver); -} - -module_init(aml_cams_prober_init); -module_exit(aml_cams_prober_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Amlogic Cameras prober driver"); - diff --git a/drivers/amlogic/media/camera/common/config_parser.c b/drivers/amlogic/media/camera/common/config_parser.c deleted file mode 100644 index 9ee62e745702..000000000000 --- a/drivers/amlogic/media/camera/common/config_parser.c +++ /dev/null @@ -1,1822 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/config_parser.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include "config_parser.h" -#include -#include -#include -#include - -static struct file *fp; -mm_segment_t fs; - -char *aet_key = "aet_start"; -char *hw_key = "hw_start"; -char *effect_key = "effect_start"; -char *capture_key = "capture_start"; -char *scenes_key = "scenes_start"; -char *wb_key = "wb_start"; -char *wave_key = "wave_start"; -char *lens_key = "lens_start"; -char *gamma_key = "gamma_start"; -char *wb_sensor_key = "mwb_sensor_start"; -char *version_key = "version_start"; -char *cm_key = "cm_start"; -char *nr_key = "nr_start"; -char *peaking_key = "peaking_start"; - -struct buffer_para_s { - char *buffer; - int data_start; - int data_size; - int buffer_len; -}; - -void *realloc_mem(char *buffer, int new_size, int *old_size) -{ - char *tmp = vmalloc(new_size); - - if (*old_size >= new_size) { - vfree(tmp); - return buffer; - } - - if (tmp != NULL) { - memcpy(tmp, buffer, *old_size); - *old_size = new_size; - vfree(buffer); - return tmp; - } else - return NULL; -} - -/* - *************************************** - *Name : camera_open_config - *Input : *config_file - *Output : file size - *function : open the firware file, and return total size - *************************************** - */ - -int camera_open_config(const char *config_file) -{ - loff_t file_size; - struct inode *inode = NULL; - - fp = filp_open(config_file, O_RDONLY, 0); - if (IS_ERR(fp)) { - pr_err("read config file error"); - return -1; - } - - inode = fp->f_path.dentry->d_inode; - file_size = inode->i_size; - fs = get_fs(); - set_fs(KERNEL_DS); - - return file_size; - -} - -/* - *********************************** - *Name : camera_read_config - *Input : offset - *length, read length - *buf, return buffer - *Output : - *function : read data to buffer - *********************************** - */ - -int camera_read_config(int offset, int length, char *buf) -{ - loff_t pos = offset; - - vfs_read(fp, buf, length, &pos); - return 0; -} - -/* - ********************************** - *Name : camera_close_config - *Input : - *Output : - *function : close file - ********************************** - */ - -int camera_close_config(void) -{ - set_fs(fs); - filp_close(fp, NULL); - return 0; -} - -static int camera_read_buff(struct i2c_adapter *adapter, - unsigned short i2c_addr, char *buf, int addr_len, - int data_len) -{ - int i2c_flag = -1; - - struct i2c_msg msgs[] = {{ - .addr = i2c_addr, .flags = 0, - .len = addr_len, .buf = buf, - }, { - .addr = i2c_addr, .flags = I2C_M_RD, - .len = data_len, .buf = buf, - } - }; - - i2c_flag = i2c_transfer(adapter, msgs, 2); - - return i2c_flag; -} - -static int camera_write_buff(struct i2c_adapter *adapter, - unsigned short i2c_addr, char *buf, int len) -{ - struct i2c_msg msg[] = {{ - .addr = i2c_addr, .flags = 0, /* |I2C_M_TEN, */ - .len = len, .buf = buf, - } - - }; - - if (i2c_transfer(adapter, msg, 1) < 0) - return -1; - else - return 0; -} - -int my_i2c_put_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, - unsigned short addr, unsigned char data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - buff[2] = data; - if (camera_write_buff(adapter, i2c_addr, buff, 3) < 0) - return -1; - return 0; -} - -int my_i2c_put_byte_add8(struct i2c_adapter *adapter, unsigned short i2c_addr, - char *buf, int len) -{ - if (camera_write_buff(adapter, i2c_addr, buf, len) < 0) - return -1; - return 0; -} - -int my_i2c_get_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, - unsigned short addr) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - - if (camera_read_buff(adapter, i2c_addr, buff, 2, 1) < 0) - return -1; - return buff[0]; -} - -int my_i2c_get_word(struct i2c_adapter *adapter, unsigned short i2c_addr) -{ - unsigned char buff[4]; - unsigned short data; - - buff[0] = 0; - - if (camera_read_buff(adapter, i2c_addr, buff, 1, 2) < 0) - return -1; - - data = buff[0]; - data = (data << 8) | buff[1]; - - return data; -} - -char *search_string(struct buffer_para_s *buf_para, int *offset, int *remained, - char *start, char *end) -{ - char *iter, *pter, *buffer; - int data_start, data_size, buffer_len; - int add = 0; - - buffer = buf_para->buffer; - data_start = buf_para->data_start; - data_size = buf_para->data_size; - buffer_len = buf_para->buffer_len; - iter = strstr(buffer + data_start, start); - while (iter == NULL) { - if (iter == NULL && *remained < strlen(start)) { - pr_err("wrong config file"); - return NULL; - } - memset(buffer, 0, buffer_len); - if (*remained < BUFFER_SIZE) { - camera_read_config(*offset - strlen(start), - *remained, buffer); /* check bounds */ - *offset += *remained - strlen(start); - data_size = *remained; - *remained = 0; - data_start = 0; - } else { - camera_read_config(*offset - strlen(start), - BUFFER_SIZE, buffer);/* check bounds */ - *offset += BUFFER_SIZE - strlen(start); - data_size = BUFFER_SIZE; - *remained -= BUFFER_SIZE; - data_start = 0; - } - iter = strstr(buffer, start); - } - data_start = iter - buffer; - /*** check **/ - if (data_start > 512) { - data_size -= data_start; - memmove(buffer, iter, data_size); - *(buffer + data_size) = '\0'; - iter = buffer; - data_start = 0; - } - pter = strstr(iter + strlen(start), end); - while (pter == NULL) { - if (pter == NULL && *remained < strlen(end)) { - pr_err("wrong config file"); - return NULL; - } - buffer = - (char *)realloc_mem(buffer, data_size + BUFFER_SIZE + 1, - &buffer_len); - if (buffer == NULL) { - pr_err("realloc failed\n"); - return NULL; - } - if (*remained < BUFFER_SIZE) { - camera_read_config(*offset, *remained, - buffer + data_size); /* check bounds */ - add = *remained; - *offset += *remained; - *remained = 0; - } else { - camera_read_config(*offset, BUFFER_SIZE, - buffer + data_size); /* check bounds */ - add = BUFFER_SIZE; - *remained -= BUFFER_SIZE; - *offset += BUFFER_SIZE; - } - *(buffer + data_size + add) = '\0'; - pter = strstr(buffer + data_size - strlen(end), end); - data_size += add; - } - /* if realloc ,iter is invalid,so recalculate */ - iter = buffer + data_start; - data_start = pter - buffer; - - buf_para->buffer = buffer; - buf_para->data_start = data_start; - buf_para->data_size = data_size; - buf_para->buffer_len = buffer_len; - return iter; -} - -char *search_key(struct buffer_para_s *buf_para, int *offset, int *remained) -{ - char *iter, *buffer; - int data_start, data_size, buffer_len; - int add = 0; - - buffer = buf_para->buffer; - data_start = buf_para->data_start; - data_size = buf_para->data_size; - buffer_len = buf_para->buffer_len; - - iter = strstr(buffer + data_start, "["); - while (iter == NULL) { - if (iter == NULL && *remained < 20) { - pr_err("file end\n"); - return NULL; - } - memset(buffer, 0, buffer_len); - if (*remained < BUFFER_SIZE) { - camera_read_config(*offset, - *remained, buffer); /* check bounds */ - *offset += *remained; - data_size = *remained; - *remained = 0; - data_start = 0; - } else { - camera_read_config(*offset, - BUFFER_SIZE, buffer); /* check bounds */ - *offset += BUFFER_SIZE; - data_size = BUFFER_SIZE; - *remained -= BUFFER_SIZE; - data_start = 0; - } - iter = strstr(buffer, "["); - } - data_start = iter - buffer; - /*** check **/ - if (data_start + 20 > data_size) { /* ensure we have an complete key */ - buffer = - (char *)realloc_mem(buffer, data_size + BUFFER_SIZE + 1, - &buffer_len); - if (buffer == NULL) { - pr_err("realloc failed\n"); - return NULL; - } - if (*remained < BUFFER_SIZE) { - camera_read_config(*offset, *remained, - buffer + data_size); /* check bounds */ - add = *remained; - *offset += *remained; - *remained = 0; - - } else { - camera_read_config(*offset, BUFFER_SIZE, - buffer + data_size); /* check bounds */ - add = BUFFER_SIZE; - *remained -= BUFFER_SIZE; - *offset += BUFFER_SIZE; - } - *(buffer + data_size + add) = '\0'; - data_size += add; - } -/* if realloc ,iter is invalid,so recalculate */ - iter = buffer + data_start; - - buf_para->buffer = buffer; - buf_para->data_start = data_start; - buf_para->data_size = data_size; - buf_para->buffer_len = buffer_len; - return iter; -} - -int parse_head(char *buffer, int *sum) -{ - int ret; - char *iter; - - iter = strstr(buffer, "sum"); - if (iter == NULL) - return -WRONG_FORMAT; - iter += 4; /* point to value */ - ret = kstrtoint(iter, 10, sum); - return 0; -} - -int parse_body_head(char *buffer, int *no, int check, char *name) -{ - int ret; - char *iter; - - iter = strstr(buffer, "no"); - iter += 3; - ret = kstrtoint(iter, 10, no); - iter = strstr(iter, "name"); - iter += 5; - ret = kstrtos8(name, 16, iter); - return 0; -} -int parse_aet_element_info(char **iter, struct sensor_aet_info_s *info) -{ - int ret; - - *iter = strstr(*iter, "export"); - *iter += 7; - ret = kstrtouint(*iter, 16, &(info->fmt_main_fr)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->fmt_capture)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->fmt_hactive)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->fmt_vactive)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->fmt_rated_fr)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->fmt_min_fr)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->tbl_max_step)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->tbl_rated_step)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->tbl_max_gain)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(info->tbl_min_gain)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, - 16, &(info->format_transfer_parameter)); - *iter = strstr(*iter, ","); - *iter += 1; - return 0; - -} - -int parse_aet_element_tbl(char **iter, struct sensor_aet_s *tbl) -{ - int ret; - - ret = kstrtouint(*iter, 16, &(tbl->exp)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->ag)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->vts)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->gain)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->fr)); - *iter = strstr(*iter, ","); - *iter += 1; - return 0; -} - -int parse_last_aet_element_tbl(char **iter, struct sensor_aet_s *tbl) -{ - int ret; - - ret = kstrtouint(*iter, 16, &(tbl->exp)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->ag)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->vts)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->gain)); - *iter = strstr(*iter, ","); - *iter += 1; - ret = kstrtouint(*iter, 16, &(tbl->fr)); - return 0; -} - -int parse_effect(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int ret1, ret2, ret3, sum, check, i; - char *iter; - - iter = search_string(buf_para, offset, remained, "effect_start]", - "[effect]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (ret1 != 0) - return -HEAD_FAILED; - cf->eff.sum = sum; - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, - remained, "[effect]", "[effect"); - if (iter == NULL) - return -WRONG_FORMAT; - ret2 = parse_body_head(iter, &(cf->eff.eff[check].num), check, - cf->eff.eff[check].name); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - i = 0; - while (i < EFFECT_MAX && iter != NULL) { - ret3 = kstrtouint(iter, - 16, &(cf->eff.eff[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != EFFECT_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; -} - -int parse_aet(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int sum, ret, check, i; - char *iter; - - iter = search_string(buf_para, offset, remained, "aet_start]", "[aet]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret = parse_head(iter, &sum); - if (sum <= 0) - return -HEAD_FAILED; - cf->aet.sum = sum; - /**parser body***/ - for (i = 0; i < sum; i++) { - cf->aet.aet[i].info = - kmalloc(sizeof(struct sensor_aet_info_s), 0); - if ((cf->aet.aet[i].info) == NULL) { - while (i-- > 0) - kfree(cf->aet.aet[i].info); - return -NO_MEM; - } - } /* alloc head */ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, - remained, "[aet]", "[aet"); - if (iter == NULL) { - pr_err("aet wrong config format\n"); - ret = -WRONG_FORMAT; - goto clean; - } - ret = parse_body_head(iter, &(cf->aet.aet[check].num), check, - cf->aet.aet[check].name); - if (ret != 0) { - ret = -HEAD_FAILED; - goto clean; - } - ret = parse_aet_element_info(&iter, cf->aet.aet[check].info); - if (ret != 0) { - ret = -BODY_ELEMENT_FAILED; - goto clean; - } - - cf->aet.aet[check].aet_table = - vmalloc(sizeof(struct sensor_aet_s) * - (cf->aet.aet[check].info->tbl_max_step + 1)); - if ((cf->aet.aet[check].aet_table) == NULL) { - for (i = 0; i < check; i++) - vfree(cf->aet.aet[i].aet_table); - ret = -NO_MEM; - goto clean; - } - for (i = 0; i <= cf->aet.aet[check].info->tbl_max_step; i++) { - if (i == cf->aet.aet[check].info->tbl_max_step) { - ret = parse_last_aet_element_tbl( - &iter, &(cf->aet.aet[check].aet_table[i])); - } else - ret = parse_aet_element_tbl(&iter, - &(cf->aet.aet[check].aet_table[i])); - if (ret != 0) { - ret = -BODY_ELEMENT_FAILED; - goto clean_table; - } - } - check++; - } - return 0; - -clean_table: - for (i = 0; i <= check; i++) - vfree(cf->aet.aet[i].aet_table); -clean: - for (i = 0; i < sum; i++) - kfree(cf->aet.aet[i].info); - return ret; -} - -int parse_hw(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int ret1, ret2, ret3, sum, check, i; - char *iter = NULL; - char *eter = NULL; - - iter = search_string(buf_para, offset, remained, "hw_start]", "[hw]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (ret1 != 0) - return -HEAD_FAILED; - cf->hw.sum = sum; - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, remained, "[hw]", "[hw"); - if (iter == NULL) - return -WRONG_FORMAT; - ret2 = parse_body_head(iter, &(cf->hw.hw[check].num), check, - cf->hw.hw[check].name); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - eter = strstr(iter, ";"); - if (eter == NULL) - return -WRONG_FORMAT; - i = 0; - while (iter < eter) { - ret3 = kstrtouint(iter, - 16, &(cf->hw.hw[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; -} - -int parse_wb(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int ret1, ret2, ret3, sum, check, i; - char *iter = NULL; - char *eter = NULL; - - iter = search_string(buf_para, offset, remained, "wb_start]", "[wb]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (ret1 != 0) - return -HEAD_FAILED; - cf->wb.sum = sum; - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, remained, "[wb]", "[wb"); - if (iter == NULL) - return -WRONG_FORMAT; - ret2 = parse_body_head(iter, &(cf->wb.wb[check].num), check, - cf->wb.wb[check].name); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - eter = strstr(iter, ";"); - if (eter == NULL) - return -WRONG_FORMAT; - i = 0; - while (iter < eter) { - ret3 = kstrtouint(iter, - 16, &(cf->wb.wb[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - - } - if (i != WB_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; - -} - -int parse_capture(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int ret1, ret2, ret3, sum, check, i; - char *iter = NULL; - char *eter = NULL; - - iter = search_string(buf_para, offset, remained, "capture_start]", - "[capture]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (ret1 != 0) - return -HEAD_FAILED; - cf->capture.sum = sum; - /* pr_err("capture sum:%d\n",sum); */ - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, remained, "[capture]", - "[capture"); - if (iter == NULL) { - pr_err("search wrong\n"); - return -WRONG_FORMAT; - } - ret2 = parse_body_head(iter, - &(cf->capture.capture[check].num), check, - cf->capture.capture[check].name); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - /* pr_err("name:%s\n",cf->capture.capture[check].name); */ - iter = strstr(iter, "export"); - if (iter == NULL) { - pr_err("iter is NULL\n"); - return -WRONG_FORMAT; - } - iter += 7; - eter = strstr(iter, ";"); - if (eter == NULL) - return -WRONG_FORMAT; - i = 0; - while (iter < eter) { - ret3 = kstrtouint(iter, - 16, &(cf->capture.capture[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != CAPTURE_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; - -} - -int parse_wave(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int i, ret; - char *iter = NULL; - char *eter = NULL; - - iter = search_string(buf_para, offset, remained, "wave_start]", - "[wave_end]"); - if (iter == NULL) - return -WRONG_FORMAT; - iter = strstr(iter, "export"); - iter += 7; - eter = strstr(iter, ";"); - if (eter == NULL) - return -WRONG_FORMAT; - i = 0; - while (iter < eter) { - ret = kstrtouint(iter, 16, &(cf->wave.export[i])); - /* pr_err("wave:%x\n",cf->wave.export[i]); */ - iter = strstr(iter, ","); - i++; - if (iter == NULL) - break; - iter += 1; - } - if (i != WAVE_MAX) - return -CHECK_LEN_FAILED; - return 0; -} - -int parse_scene(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int sum, ret1, ret2, ret3, check, i; - char *iter = NULL; - char *eter = NULL; - - iter = search_string(buf_para, offset, remained, "scenes_start]", - "[scenes]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (sum <= 0) - return -HEAD_FAILED; - cf->scene.sum = sum; - - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, - remained, "[scenes]", "[scenes"); - if (iter == NULL) { - pr_err("scene wrong config format\n"); - return -WRONG_FORMAT; - } - ret2 = parse_body_head(iter, &((cf->scene.scene[check]).num), - check, (cf->scene.scene[check].name)); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - eter = strstr(iter, ";"); - if (eter == NULL) - return -WRONG_FORMAT; - i = 0; - while (iter < eter) { - ret3 = kstrtouint(iter, - 16, &(cf->scene.scene[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != SCENE_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; -} - -int parse_lens(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int sum, ret1, ret2, ret3, check, i; - char *iter = NULL; - char *eter = NULL; - - iter = search_string(buf_para, offset, - remained, "lens_start]", "[lens]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (sum <= 0) - return -HEAD_FAILED; - cf->lens.sum = sum; - - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, - remained, "[lens]", "[lens"); - if (iter == NULL) { - pr_err("lens wrong config format\n"); - return -WRONG_FORMAT; - } - ret2 = parse_body_head(iter, - &((cf->lens.lens[check]).num), - check, - (cf->lens.lens[check].name)); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - eter = strstr(iter, ";"); - if (eter == NULL) - return -WRONG_FORMAT; - i = 0; - while (iter < eter) { - ret3 = kstrtouint(iter, - 16, &(cf->lens.lens[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != LENS_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; -} - -int parse_gamma(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int i, ret; - char *iter; - - iter = search_string(buf_para, offset, remained, "gamma_start]", - "[gamma_end]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - iter = strstr(iter, "export"); - iter += 7; - for (i = 0; i < GAMMA_MAX && iter != NULL;) { - ret = kstrtouint(iter, 16, &(cf->gamma.gamma_r[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != GAMMA_MAX) - return -CHECK_LEN_FAILED; - for (i = 0; i < GAMMA_MAX && iter != NULL;) { - ret = kstrtouint(iter, 16, &(cf->gamma.gamma_g[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != GAMMA_MAX) - return -CHECK_LEN_FAILED; - for (i = 0; i < GAMMA_MAX && iter != NULL;) { - ret = kstrtouint(iter, - 16, &(cf->gamma.gamma_b[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != GAMMA_MAX) - return -CHECK_LEN_FAILED; - return 0; -} - -int parse_wb_sensor(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int i, ret; - char *iter; - - iter = search_string(buf_para, offset, remained, "mwb_sensor_start]", - "[mwb_sensor_end]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - iter = strstr(iter, "export"); - iter += 7; - i = 0; - while (i < WB_SENSOR_MAX && iter != NULL) { - ret = kstrtouint(iter, 16, &(cf->wb_sensor_data.export[i])); - /* pr_err("wb sensor:%x\n",cf->wb_sensor_data.export[i]); */ - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != WB_SENSOR_MAX) - return -CHECK_LEN_FAILED; - return 0; -} - -int parse_version(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - char *iter, *end; - int len = 0; - - iter = search_string(buf_para, offset, remained, "version_start]", - "[version_end]"); - if (iter == NULL) - return -WRONG_FORMAT; - iter = strstr(iter, "Date"); - iter += 5; - end = strstr(iter, "Module"); - if (end == NULL) - return -WRONG_FORMAT; - len = end - iter; - memcpy(cf->version.date, iter, len); - cf->version.date[len] = '\0'; - - iter = end + 7; - end = strstr(iter, "Version"); - if (end == NULL) - return -WRONG_FORMAT; - len = end - iter; - memcpy(cf->version.module, iter, len); - cf->version.module[len] = '\0'; - - iter = end + 8; - end = strstr(iter, "[version"); - if (end == NULL) - return -WRONG_FORMAT; - len = end - iter; - memcpy(cf->version.version, iter, len); - cf->version.version[len] = '\0'; - pr_info("version:%s", cf->version.version); - return 0; -} - -int parse_cm(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int i; - int ret; - char *iter; - - iter = search_string(buf_para, offset, - remained, "cm_start]", "[cm_end]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser body***/ - iter = strstr(iter, "export"); - iter += 7; - i = 0; - while (i < CM_MAX && iter != NULL) { - ret = kstrtouint(iter, 16, &(cf->cm.export[i])); - /* pr_err("cm:%x\n",cf->cm.export[i]); */ - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != CM_MAX) - return -CHECK_LEN_FAILED; - return 0; -} - -int parse_nr(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int ret1, ret2, ret3, sum, check, i; - char *iter; - - iter = search_string(buf_para, offset, remained, "nr_start]", "[nr]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (ret1 != 0) - return -HEAD_FAILED; - cf->nr.sum = sum; - /* pr_err("nr sum:%d\n",sum); */ - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, remained, "[nr]", "[nr"); - if (iter == NULL) { - pr_err("search wrong\n"); - return -WRONG_FORMAT; - } - ret2 = parse_body_head(iter, &(cf->nr.nr[check].num), check, - cf->nr.nr[check].name); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - i = 0; - while (i < NR_MAX && iter != NULL) { - ret3 = kstrtouint(iter, 16, - &(cf->nr.nr[check].export[i])); - /* pr_err("nr:%x\n",cf->nr.nr[check].export[i]); */ - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != NR_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; -} - -int parse_peaking(struct configure_s *cf, struct buffer_para_s *buf_para, - int *remained, int *offset) -{ - int ret1, ret2, ret3, sum, check, i; - char *iter; - - iter = search_string(buf_para, offset, remained, "peaking_start]", - "[peaking]"); - if (iter == NULL) - return -WRONG_FORMAT; - /***parser head***/ - ret1 = parse_head(iter, &sum); - if (ret1 != 0) - return -HEAD_FAILED; - cf->peaking.sum = sum; - /* pr_err("peaking sum:%d\n",sum); */ - /**parser body***/ - check = 0; - while (check < sum) { - iter = search_string(buf_para, offset, remained, "[peaking]", - "[peaking"); - if (iter == NULL) { - pr_err("search wrong\n"); - return -WRONG_FORMAT; - } - ret2 = parse_body_head(iter, - &(cf->peaking.peaking[check].num), check, - cf->peaking.peaking[check].name); - if (ret2 != 0) - return -BODY_HEAD_FAILED; - iter = strstr(iter, "export"); - iter += 7; - i = 0; - while (i < PEAKING_MAX && iter != NULL) { - ret3 = kstrtouint(iter, - 16, &(cf->peaking.peaking[check].export[i])); - i++; - iter = strstr(iter, ","); - if (iter == NULL) - break; - iter += 1; - } - if (i != PEAKING_MAX) - return -CHECK_LEN_FAILED; - check++; - } - if (check != sum) - return -CHECK_FAILED; - return 0; -} - -int parse_config(const char *path, struct configure_s *cf) -{ - char *buffer, *iter; - int file_size; - int remained_size; - int read_offset = 0; - int ret = 0; - struct buffer_para_s buf_para; - - buffer = vmalloc(BUFFER_SIZE + 1);/*(char *)*/ - if (buffer == NULL) - return -NO_MEM; - - buf_para.buffer = buffer; - - memset(cf, 0, sizeof(struct configure_s)); - file_size = camera_open_config(path); - if (file_size < 0) { - pr_err("open failed :%d\n", file_size); - ret = -READ_ERROR; - goto clean_mem; - } else if (file_size == 0) { - pr_err("file is null\n"); - ret = -READ_ERROR; - goto clean_all; - } else { - if (file_size < BUFFER_SIZE) { - camera_read_config(0, file_size, buffer); - remained_size = 0; - read_offset = file_size; - *(buffer + file_size) = '\0'; - } else { - camera_read_config(0, BUFFER_SIZE, buffer); - remained_size = file_size - BUFFER_SIZE; - read_offset = BUFFER_SIZE; - *(buffer + BUFFER_SIZE) = '\0'; - } - } - buf_para.data_start = 0; - buf_para.data_size = read_offset; - buf_para.buffer_len = BUFFER_SIZE; - - while (read_offset <= file_size) { - iter = search_key(&buf_para, &read_offset, &remained_size); - if (iter == NULL) { - pr_info("finish parse file\n"); - return 0; - } - iter += 1; - buf_para.data_start += 1; - switch (*iter) { - case 'a': - if (memcmp(iter, aet_key, strlen(aet_key)) == 0) { - cf->aet_valid = 1; - ret = parse_aet(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->aet_valid = 0; - pr_err("aet invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(aet_key); - break; - case 'h': - if (memcmp(iter, hw_key, strlen(hw_key)) == 0) { - cf->hw_valid = 1; - ret = parse_hw(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->hw_valid = 0; - pr_err("hw invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(hw_key); - break; - case 'e': - if (memcmp(iter, effect_key, strlen(effect_key)) == 0) { - cf->effect_valid = 1; - ret = parse_effect(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->effect_valid = 0; - pr_err("effect invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(effect_key); - break; - case 'w': - if (*(iter + 1) == 'b') { - if (memcmp(iter, wb_key, strlen(wb_key)) == 0) { - cf->wb_valid = 1; - ret = parse_wb(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->wb_valid = 0; - pr_err("wb invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(wb_key); - } else if (*(iter + 1) == 'a') { - if (memcmp(iter, wave_key, - strlen(wave_key)) == 0) { - cf->wave_valid = 1; - ret = parse_wave(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->wave_valid = 0; - pr_err("wave invalid :%d\n", - ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(wave_key); - } else - buf_para.data_start += 1; - - break; - case 's': - if (memcmp(iter, scenes_key, - strlen(scenes_key)) == 0) { - cf->scene_valid = 1; - ret = parse_scene(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->scene_valid = 0; - pr_err("scene invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(scenes_key); - break; - case 'c': - if (*(iter + 1) == 'a') { - if (memcmp(iter, capture_key, - strlen(capture_key)) == 0) { - cf->capture_valid = 1; - ret = parse_capture(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->capture_valid = 0; - pr_err("capture invalid :%d\n", - ret); - goto clean_all; - } - } else - buf_para.data_start += - strlen(capture_key); - } else if (*(iter + 1) == 'm') { - if (memcmp(iter, cm_key, strlen(cm_key)) == 0) { - cf->cm_valid = 1; - ret = parse_cm(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->cm_valid = 0; - pr_err("cm invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(cm_key); - } else - buf_para.data_start += 1; - break; - case 'l': - if (memcmp(iter, lens_key, strlen(lens_key)) == 0) { - cf->lens_valid = 1; - ret = parse_lens(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->lens_valid = 0; - pr_err("lens invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(lens_key); - break; - case 'g': - if (memcmp(iter, gamma_key, strlen(gamma_key)) == 0) { - cf->gamma_valid = 1; - ret = parse_gamma(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->gamma_valid = 0; - pr_err("gamma invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(gamma_key); - break; - case 'm': - if (memcmp(iter, wb_sensor_key, - strlen(wb_sensor_key)) == 0) { - cf->wb_sensor_data_valid = 1; - ret = parse_wb_sensor(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->wb_sensor_data_valid = 0; - pr_err("wb sensor data invalid :%d\n", - ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(wb_sensor_key); - break; - case 'v': - if (memcmp(iter, version_key, - strlen(version_key)) == 0) { - cf->version_info_valid = 1; - ret = parse_version(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->version_info_valid = 0; - pr_err("version info invalid :%d\n", - ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(version_key); - break; - case 'n': - if (memcmp(iter, nr_key, strlen(nr_key)) == 0) { - cf->nr_valid = 1; - ret = parse_nr(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->nr_valid = 0; - pr_err("nr invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(nr_key); - break; - case 'p': - if (memcmp(iter, peaking_key, - strlen(peaking_key)) == 0) { - cf->peaking_valid = 1; - ret = parse_peaking(cf, &buf_para, - &remained_size, &read_offset); - if (ret != 0) { - cf->peaking_valid = 0; - pr_err("peaking invalid :%d\n", ret); - goto clean_all; - } - } else - buf_para.data_start += strlen(peaking_key); - break; - default: - buf_para.data_start += 1; - break; - } - } - ret = 0; - -clean_all: - camera_close_config(); -clean_mem: - vfree(buf_para.buffer); - return ret; -} - -struct hw_para_s { - char name[20]; - int size; - int *array; -}; - -struct hw_para_s hw_para[] = { - {"TOP", XML_TOP, NULL}, {"TP", XML_TP, NULL}, {"CG", XML_CG, NULL}, { - "LENS_SHADING", XML_LS, NULL - }, {"DFT", XML_DP, NULL}, { - "DMS", XML_DM, NULL - }, {"MATRIX", XML_CSC, NULL}, { - "PEAKING", XML_SH, NULL - }, {"NR", XML_NR, NULL}, {"AWB", XML_AWB, NULL}, - {"AE", XML_AE, NULL}, {"AF", XML_AF, NULL}, {"BLNR", XML_BN, NULL}, { - "DBG", XML_DBG, NULL - }, {"GC", XML_GC, NULL}, {"", 0, NULL} -}; - -void init_hw_para(struct xml_default_regs_s *reg) -{ - hw_para[0].array = &(reg->top.reg_map[0]); - hw_para[1].array = &(reg->tp.reg_map[0]); - hw_para[2].array = &(reg->cg.reg_map[0]); - hw_para[3].array = &(reg->ls.reg_map[0]); - hw_para[4].array = &(reg->dp.reg_map[0]); - hw_para[5].array = &(reg->dm.reg_map[0]); - hw_para[6].array = &(reg->csc.reg_map[0]); - hw_para[7].array = &(reg->sharp.reg_map[0]); - hw_para[8].array = &(reg->nr.reg_map[0]); - hw_para[9].array = &(reg->awb_reg.reg_map[0]); - hw_para[10].array = &(reg->ae_reg.reg_map[0]); - hw_para[11].array = &(reg->af_reg.reg_map[0]); - hw_para[12].array = &(reg->bn.reg_map[0]); - hw_para[13].array = &(reg->dbg.reg_map[0]); - hw_para[14].array = &(reg->gc.reg_map[0]); -} - -/* call back functions */ - -unsigned int get_aet_max_step(void *priv) -{ - struct camera_priv_data_s *camera_priv_data = - (struct camera_priv_data_s *)priv; - if (camera_priv_data == NULL || - camera_priv_data->sensor_aet_info == NULL) { - pr_err("get_aet_max_step null\n"); - WARN_ON((!camera_priv_data) || - (!camera_priv_data->sensor_aet_info)); - } - return camera_priv_data->sensor_aet_info->tbl_max_step; -} - -unsigned int get_aet_max_gain(void *priv) -{ - struct camera_priv_data_s *camera_priv_data = - (struct camera_priv_data_s *)priv; - if (camera_priv_data == NULL || - camera_priv_data->sensor_aet_info == NULL) { - pr_err("get_aet_max_gain null\n"); - WARN_ON((!camera_priv_data) || - (!camera_priv_data->sensor_aet_info)); - } - return camera_priv_data->sensor_aet_info->tbl_max_gain; -} - -unsigned int get_aet_min_gain(void *priv) -{ - struct camera_priv_data_s *camera_priv_data = - (struct camera_priv_data_s *)priv; - if (camera_priv_data == NULL || - camera_priv_data->sensor_aet_info == NULL) { - pr_err("get_aet_min_gain null\n"); - WARN_ON((!camera_priv_data) || - (!camera_priv_data->sensor_aet_info)); - } - return camera_priv_data->sensor_aet_info->tbl_min_gain; -} - -unsigned int get_aet_current_step(void *priv) -{ - struct camera_priv_data_s *camera_priv_data = - (struct camera_priv_data_s *)priv; - if (camera_priv_data == NULL || - camera_priv_data->sensor_aet_info == NULL) { - pr_err("get_aet_current_step null\n"); - WARN_ON((!camera_priv_data) || - (!camera_priv_data->sensor_aet_info)); - } - return camera_priv_data->sensor_aet_step; -} - -unsigned int get_aet_current_gain(void *priv) -{ - struct sensor_aet_s *sensor_aet_table; - unsigned int sensor_aet_step; - struct camera_priv_data_s *camera_priv_data = - (struct camera_priv_data_s *)priv; - if (camera_priv_data == NULL) - WARN_ON(!camera_priv_data); - - sensor_aet_table = - camera_priv_data->sensor_aet_table; - sensor_aet_step = camera_priv_data->sensor_aet_step; - - if (sensor_aet_table == NULL) { - pr_err("get_aet_current_gain null\n"); - WARN_ON(!sensor_aet_table); - } - return sensor_aet_table[sensor_aet_step].gain; -} - -unsigned int get_aet_new_gain(void *priv, unsigned int new_step) -{ - struct camera_priv_data_s *camera_priv_data = - (struct camera_priv_data_s *)priv; - struct sensor_aet_s *sensor_aet_table; - - if (camera_priv_data == NULL) - WARN_ON(!camera_priv_data); - sensor_aet_table = - camera_priv_data->sensor_aet_table; - if (sensor_aet_table == NULL) { - pr_err("get_aet_current_gain null\n"); - WARN_ON(!sensor_aet_table); - } - return sensor_aet_table[new_step].gain; -} - -int generate_para(struct cam_parameter_s *para, struct para_index_s pindex, - struct configure_s *cf) -{ - int i = 0; - int j = 0; - struct xml_scenes_s *scene; - struct xml_default_regs_s *reg; - struct xml_effect_manual_s *effect; - struct xml_wb_manual_s *wb; - struct xml_capture_s *capture; - struct wave_s *wave; - - /**init callback func**/ - para->cam_function.set_af_new_step = NULL; - if (cf->aet_valid == 1) { - para->cam_function.get_aet_current_step = get_aet_current_step; - para->cam_function.get_aet_max_step = get_aet_max_step; - para->cam_function.get_aet_current_gain = get_aet_current_gain; - para->cam_function.get_aet_min_gain = get_aet_min_gain; - para->cam_function.get_aet_max_gain = get_aet_max_gain; - para->cam_function.get_aet_gain_by_step = get_aet_new_gain; - - } - /**init scenes**/ - if (cf->scene_valid == 1) { - para->xml_scenes = - vmalloc(sizeof(struct xml_scenes_s)); - if (para->xml_scenes == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - scene = para->xml_scenes; - memcpy(&(scene->ae), - cf->scene.scene[pindex.scenes_index].export, - AE_LEN * sizeof(unsigned int)); - memcpy(&(scene->awb), - cf->scene.scene[pindex.scenes_index].export + AE_LEN, - AWB_LEN * sizeof(unsigned int)); - memcpy(&(scene->af), - cf->scene.scene[pindex.scenes_index].export + - (AE_LEN + AWB_LEN), - AF_LEN * sizeof(unsigned int)); - } else - para->xml_scenes = NULL; - - /**init hw**/ - if (cf->hw_valid == 1) { - para->xml_regs_map = vmalloc(sizeof(struct xml_default_regs_s)); - if (para->xml_regs_map == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - reg = para->xml_regs_map; - init_hw_para(reg); - for (i = 0; i < cf->hw.sum; i++) { - if ((strcmp(hw_para[i].name, cf->hw.hw[i].name)) == 0) { - for (j = 0; j < hw_para[i].size; j++) - hw_para[i].array[j] = - cf->hw.hw[i].export[j]; - } - } - - } else - para->xml_regs_map = NULL; - /** init gamma **/ - if (cf->gamma_valid == 1) { - if (para->xml_regs_map == NULL) { - para->xml_regs_map = - vmalloc(sizeof(struct xml_default_regs_s)); - if (para->xml_regs_map == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - } - reg = para->xml_regs_map; - memcpy(reg->lut_gc.gamma_r, cf->gamma.gamma_r, - GAMMA_MAX * sizeof(unsigned short)); - memcpy(reg->lut_gc.gamma_g, cf->gamma.gamma_g, - GAMMA_MAX * sizeof(unsigned short)); - memcpy(reg->lut_gc.gamma_b, cf->gamma.gamma_b, - GAMMA_MAX * sizeof(unsigned short)); - } - /**init effect**/ - if (cf->effect_valid == 1) { - para->xml_effect_manual = - kmalloc(sizeof(struct xml_effect_manual_s), 0); - if (para->xml_effect_manual == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - effect = para->xml_effect_manual; - memcpy(effect->csc.reg_map, - cf->eff.eff[pindex.effect_index].export, - EFFECT_MAX * sizeof(unsigned int)); - } else - para->xml_effect_manual = NULL; - /**init wb**/ - if (cf->wb_valid == 1) { - para->xml_wb_manual = - kmalloc(sizeof(struct xml_wb_manual_s), 0); - if (para->xml_wb_manual == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - wb = para->xml_wb_manual; - memcpy(wb->reg_map, cf->wb.wb[pindex.wb_index].export, - 2 * sizeof(unsigned int)); - } else - para->xml_wb_manual = NULL; - - /**init capture**/ - if (cf->capture_valid == 1) { - para->xml_capture = vmalloc(sizeof(struct xml_capture_s)); - if (para->xml_capture == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - capture = para->xml_capture; - capture->ae_try_max_cnt = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[0]); - capture->sigle_count = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[3]); - capture->skip_step = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[4]); - capture->multi_capture_num = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[5]); - capture->af_mode = (enum cam_scanmode_e)(cf->capture. - capture[pindex.capture_index].export[2]); - capture->eyetime = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[6]); - capture->pretime = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[7]); - capture->postime = (unsigned int)(cf->capture. - capture[pindex.capture_index].export[8]); - } else - para->xml_capture = NULL; - /**init wave**/ - if (cf->wave_valid == 1) { - para->xml_wave = kmalloc(sizeof(struct wave_s), 0); - if (para->xml_wave == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - wave = para->xml_wave; - memcpy(wave, cf->wave.export, WAVE_MAX * sizeof(unsigned int)); - } else - para->xml_wave = NULL; - return 0; -} - -void free_para(struct cam_parameter_s *para) -{ - if (para->xml_peripheral != NULL) { - kfree(para->xml_peripheral); - para->xml_peripheral = NULL; - } - if (para->xml_scenes != NULL) { - vfree(para->xml_scenes); - para->xml_scenes = NULL; - } - if (para->xml_regs_map != NULL) { - vfree(para->xml_regs_map); - para->xml_regs_map = NULL; - } - if (para->xml_effect_manual != NULL) { - kfree(para->xml_effect_manual); - para->xml_effect_manual = NULL; - } - if (para->xml_wb_manual != NULL) { - kfree(para->xml_wb_manual); - para->xml_wb_manual = NULL; - } - if (para->xml_capture != NULL) { - vfree(para->xml_capture); - para->xml_capture = NULL; - } - if (para->xml_wave != NULL) { - kfree(para->xml_wave); - para->xml_wave = NULL; - } -} - -int update_fmt_para(int width, int height, struct cam_parameter_s *para, - struct para_index_s *pindex, struct configure_s *cf) -{ - int i = 0; - struct xml_default_regs_s *reg; - - if (cf->lens_valid == 1) { - while (i < cf->lens.sum) { - if (cf->lens.lens[i].export[0] == width && - cf->lens.lens[i].export[1] == height) - break; - i++; - } - if (i < cf->lens.sum) - pindex->lens_index = i; - else { - pr_info("width:%x,height:%x no match lens param\n", - width, height); - pindex->lens_index = 0; - } - /** init lens **/ - if (para->xml_regs_map == NULL) { - para->xml_regs_map = - vmalloc(sizeof(struct xml_default_regs_s)); - if (para->xml_regs_map == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - } - reg = para->xml_regs_map; - memcpy(reg->lnsd.reg_map, - cf->lens.lens[pindex->lens_index].export + 2, - (LENS_MAX - 2) * sizeof(unsigned int)); - } - - i = 0; - if (cf->nr_valid == 1) { - while (i < cf->nr.sum) { - if (cf->nr.nr[i].export[0] == width && - cf->nr.nr[i].export[1] == height) - break; - i++; - } - if (i < cf->nr.sum) - pindex->nr_index = i; - else { - pr_info("width:%x,height:%x no match nr param\n", - width, height); - pindex->nr_index = 0; - } - /** init nr **/ - if (para->xml_regs_map == NULL) { - para->xml_regs_map = - vmalloc(sizeof(struct xml_default_regs_s)); - if (para->xml_regs_map == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - } - reg = para->xml_regs_map; - memcpy(reg->nr.reg_map, cf->nr.nr[pindex->nr_index].export + 2, - (NR_MAX - 2) * sizeof(unsigned int)); - } - - i = 0; - if (cf->peaking_valid == 1) { - while (i < cf->peaking.sum) { - if (cf->peaking.peaking[i].export[0] == width && - cf->peaking.peaking[i].export[1] == height) - break; - i++; - } - if (i < cf->peaking.sum) - pindex->peaking_index = i; - else { - pr_info("width:%x,height:%x no match peaking param\n", - width, height); - pindex->peaking_index = 0; - } - /** init sharp **/ - if (para->xml_regs_map == NULL) { - para->xml_regs_map = - vmalloc(sizeof(struct xml_default_regs_s)); - if (para->xml_regs_map == NULL) { - pr_err("alloc mem failed\n"); - return -ENOMEM; - } - } - reg = para->xml_regs_map; - memcpy(reg->sharp.reg_map, - cf->peaking.peaking[pindex->peaking_index].export + 2, - (PEAKING_MAX - 2) * sizeof(unsigned int)); - } - return 0; -} diff --git a/drivers/amlogic/media/camera/common/config_parser.h b/drivers/amlogic/media/camera/common/config_parser.h deleted file mode 100644 index c5e78026e9fe..000000000000 --- a/drivers/amlogic/media/camera/common/config_parser.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/config_parser.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef CONFIG_PARSER -#define CONFIG_PARSER - -#include -#include -#include -#include -#include -#include - -#define EFFECT_ITEM_MAX 16 -#define AET_ITEM_MAX 32 -#define HW_ITEM_MAX 16 -#define WB_ITEM_MAX 10 -#define CAPTURE_ITEM_MAX 9 -#define NR_ITEM_MAX 5 -#define PEAKING_ITEM_MAX 5 -#define LENS_ITEM_MAX 5 -#define SCENE_ITEM_MAX 1 -#define EFFECT_MAX 18 -#define HW_MAX 64 -#define WB_MAX 2 -#define GAMMA_MAX 257 -#define SCENE_MAX 281 -#define WB_SENSOR_MAX 4 -#define CAPTURE_MAX 8 -#define LENS_MAX 1027 -#define WAVE_MAX 12 -#define CM_MAX 188 -#define NR_MAX 15 -#define PEAKING_MAX 35 -#define AE_LEN 119 -#define AWB_LEN 120 -#define AF_LEN 42 -#define BUFFER_SIZE 1024 - -enum error_code { - NO_MEM = 1, - READ_ERROR, - WRONG_FORMAT, - CHECK_LEN_FAILED, - CHECK_FAILED, - HEAD_FAILED, - BODY_HEAD_FAILED, - BODY_ELEMENT_FAILED, -}; - -struct effect_type { - int num; - char name[40]; - unsigned int export[EFFECT_MAX]; -}; - -struct effect_struct { - int sum; - struct effect_type eff[EFFECT_ITEM_MAX]; -}; - -struct hw_type { - int num; - char name[40]; - int export[HW_MAX]; -}; - -struct hw_struct { - int sum; - struct hw_type hw[HW_ITEM_MAX]; -}; - -struct wb_type { - int num; - char name[40]; - int export[2]; -}; - -struct wb_struct { - int sum; - struct wb_type wb[WB_ITEM_MAX]; -}; - -struct scene_type { - int num; - char name[40]; - int export[SCENE_MAX]; -}; - -struct scene_struct { - int sum; - struct scene_type scene[SCENE_ITEM_MAX]; -}; - -struct capture_type { - int num; - char name[40]; - int export[CAPTURE_ITEM_MAX]; -}; - -struct capture_struct { - int sum; - struct capture_type capture[CAPTURE_MAX]; -}; - -struct sensor_aet_s { - unsigned int exp; - unsigned int ag; - unsigned int vts; - unsigned int gain; - unsigned int fr; -}; -/* sensor_aet_t */ - -struct sensor_aet_info_s { - unsigned int fmt_main_fr; - unsigned int fmt_capture; /* false: preview, true: capture */ - unsigned int fmt_hactive; - unsigned int fmt_vactive; - unsigned int fmt_rated_fr; - unsigned int fmt_min_fr; - unsigned int tbl_max_step; - unsigned int tbl_rated_step; - unsigned int tbl_max_gain; - unsigned int tbl_min_gain; - unsigned int format_transfer_parameter; -}; -/* sensor_aet_info_t */ - -struct aet_type { - int num; - char name[40]; - struct sensor_aet_info_s *info; - struct sensor_aet_s *aet_table; -}; - -struct aet_struct { - int sum; - struct aet_type aet[AET_ITEM_MAX]; -}; - -struct wave_struct { - int export[WAVE_MAX]; -}; - -struct lens_type { - int num; - char name[40]; - int export[LENS_MAX]; -}; - -struct lens_struct { - int sum; - struct lens_type lens[LENS_ITEM_MAX]; -}; - -struct gamma_struct { - unsigned int gamma_r[GAMMA_MAX]; - unsigned int gamma_g[GAMMA_MAX]; - unsigned int gamma_b[GAMMA_MAX]; -}; - -struct wb_sensor_struct { - int export[WB_SENSOR_MAX]; -}; - -struct version_struct { - char date[40]; - char module[30]; - char version[30]; -}; - -struct cm_struct { - int export[CM_MAX]; -}; - -struct nr_type { - int num; - char name[40]; - int export[NR_MAX]; -}; - -struct nr_struct { - int sum; - struct nr_type nr[NR_ITEM_MAX]; -}; - -struct peaking_type { - int num; - char name[40]; - int export[PEAKING_MAX]; -}; - -struct peaking_struct { - int sum; - struct peaking_type peaking[PEAKING_ITEM_MAX]; -}; - -struct configure_s { - struct effect_struct eff; - int effect_valid; - struct hw_struct hw; - int hw_valid; - struct aet_struct aet; - int aet_valid; - struct capture_struct capture; - int capture_valid; - struct scene_struct scene; - int scene_valid; - struct wb_struct wb; - int wb_valid; - struct wave_struct wave; - int wave_valid; - struct lens_struct lens; - int lens_valid; - struct gamma_struct gamma; - int gamma_valid; - struct wb_sensor_struct wb_sensor_data; - int wb_sensor_data_valid; - struct version_struct version; - int version_info_valid; - struct cm_struct cm; - int cm_valid; - struct nr_struct nr; - int nr_valid; - struct peaking_struct peaking; - int peaking_valid; -}; - -struct para_index_s { - unsigned int effect_index; - unsigned int scenes_index; - unsigned int wb_index; - unsigned int capture_index; - unsigned int nr_index; - unsigned int peaking_index; - unsigned int lens_index; -}; - -struct wb_pair_t { - enum camera_wb_flip_e wb; - char *name; -}; - -struct effect_pair_t { - enum camera_special_effect_e effect; - char *name; -}; - -struct sensor_dg_s { - unsigned short r; - unsigned short g; - unsigned short b; - unsigned short dg_default; -}; - -struct camera_priv_data_s { - struct sensor_aet_info_s - *sensor_aet_info; /* point to 1 of up to 16 aet information */ - struct sensor_aet_s *sensor_aet_table; - unsigned int sensor_aet_step; /* current step of the current aet */ - struct configure_s *configure; -}; - -int parse_config(const char *path, struct configure_s *cf); -int generate_para(struct cam_parameter_s *para, struct para_index_s pindex, - struct configure_s *cf); -void free_para(struct cam_parameter_s *para); -int update_fmt_para(int width, int height, struct cam_parameter_s *para, - struct para_index_s *pindex, struct configure_s *cf); - -unsigned int get_aet_current_step(void *priv); -unsigned int get_aet_current_gain(void *pirv); -unsigned int get_aet_min_gain(void *priv); -unsigned int get_aet_max_gain(void *priv); -unsigned int get_aet_max_step(void *priv); -unsigned int get_aet_gain_by_step(void *priv, unsigned int new_step); - -int my_i2c_put_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, - unsigned short addr, unsigned char data); -int my_i2c_put_byte_add8(struct i2c_adapter *adapter, unsigned short i2c_addr, - char *buf, int len); -int my_i2c_get_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, - unsigned short addr); -int my_i2c_get_word(struct i2c_adapter *adapter, unsigned short i2c_addr); -#endif - diff --git a/drivers/amlogic/media/camera/common/flashlight.c b/drivers/amlogic/media/camera/common/flashlight.c deleted file mode 100644 index 51018d997832..000000000000 --- a/drivers/amlogic/media/camera/common/flashlight.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/flashlight.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define FLASHLIGHT_MODULE_NAME "flashlight" -#define FLASHLIGHT_DRIVER_NAME "flashlight" -#define FLASHLIGHT_DEVICE_NAME "flashlight" -#define FLASHLIGHT_CLASS_NAME "flashlight" - -static dev_t flashlight_devno; -static struct cdev *flashlight_cdev; -static struct device *devp; - -static enum aml_plat_flashlight_status_s flashlight_flag = FLASHLIGHT_OFF; - -static ssize_t flashlight_ctrl_store(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count); -static ssize_t flashlightflag_show(struct class *cla, - struct class_attribute *attr, char *buf); -static ssize_t flashlightflag_store(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count); -static int flashlight_open(struct inode *inode, struct file *file); -static int flashlight_release(struct inode *inode, struct file *file); -static int flashlight_probe(struct platform_device *pdev); -static int flashlight_remove(struct platform_device *pdev); - -static struct platform_driver flashlight_driver = { - .probe = flashlight_probe, .remove = flashlight_remove, .driver = { - .name = - FLASHLIGHT_DRIVER_NAME, .owner = THIS_MODULE, - }, -}; - -static const struct file_operations flashlight_fops = { - .open = flashlight_open, .release = flashlight_release, -}; - -static struct class_attribute flashlight_class_attrs[] = { - __ATTR(flashlight_ctrl, 0644, NULL, flashlight_ctrl_store), - __ATTR(flashlightflag, 0644, flashlightflag_show, - flashlightflag_store), - __ATTR_NULL -}; -static struct class flashlight_class = { - .name = FLASHLIGHT_CLASS_NAME, - .class_attrs = flashlight_class_attrs, - .owner = THIS_MODULE, - }; - -static ssize_t flashlight_ctrl_store(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - struct aml_plat_flashlight_data_s *pdata = NULL; - struct device *dev = NULL; - - dev = devp; - pdata = (struct aml_plat_flashlight_data_s *)dev->platform_data; - if (pdata == NULL) { - pr_err("%s platform data is required!\n", __func__); - return -1; - } - if (!strncmp(buf, "0", 1)) { - if (pdata->flashlight_off) - pdata->flashlight_off(); - } else if (!strncmp(buf, "1", 1)) { - if (pdata->flashlight_on) - pdata->flashlight_on(); - } else { - pr_err("%s:%s error!Not support this parameter\n", - FLASHLIGHT_MODULE_NAME, __func__); - return -EINVAL; - } - return count; -} - -static ssize_t flashlightflag_show(struct class *cla, - struct class_attribute *attr, char *buf) -{ - sprintf(buf, "%d", (int)flashlight_flag); - return strlen(buf); -} - -static ssize_t flashlightflag_store(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - if (!strlen(buf)) - pr_info("%s parameter is required!\n", __func__); - flashlight_flag = (enum aml_plat_flashlight_status_s)(buf[0] - '0'); - return count; -} - -static int flashlight_open(struct inode *inode, struct file *file) -{ - return 0; -} - -static int flashlight_release(struct inode *inode, struct file *file) -{ - return 0; -} - -static int flashlight_probe(struct platform_device *pdev) -{ - int ret; - struct aml_plat_flashlight_data_s *pdata = NULL; - - ret = alloc_chrdev_region(&flashlight_devno, 0, - 1, FLASHLIGHT_DRIVER_NAME); - if (ret < 0) { - pr_err("%s:%s failed to allocate major number\n", - FLASHLIGHT_MODULE_NAME, __func__); - ret = -ENODEV; - goto out; - } - ret = class_register(&flashlight_class); - if (ret < 0) { - pr_err("%s:%s failed to register class\n", - FLASHLIGHT_MODULE_NAME, __func__); - goto error1; - } - flashlight_cdev = cdev_alloc(); - if (!flashlight_cdev) { - pr_err("%s:%s: failed to allocate memory\n", - FLASHLIGHT_MODULE_NAME, __func__); - ret = -ENOMEM; - goto error2; - } - cdev_init(flashlight_cdev, &flashlight_fops); - flashlight_cdev->owner = THIS_MODULE; - ret = cdev_add(flashlight_cdev, flashlight_devno, 1); - if (ret) { - pr_err("%s:%s: failed to add device\n", - FLASHLIGHT_MODULE_NAME, __func__); - goto error3; - } - devp = device_create(&flashlight_class, NULL, flashlight_devno, NULL, - FLASHLIGHT_DEVICE_NAME); - if (IS_ERR(devp)) { - pr_err("%s:%s failed to create device node\n", - FLASHLIGHT_MODULE_NAME, __func__); - ret = PTR_ERR(devp); - goto error3; - } - pr_info("%s:%s device %s created\n", FLASHLIGHT_MODULE_NAME, - __func__, FLASHLIGHT_DEVICE_NAME); - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "platform data is required!\n"); - ret = -EINVAL; - goto error4; - } - devp->platform_data = pdata; - return 0; -error4: - device_destroy(NULL, flashlight_devno); -error3: - cdev_del(flashlight_cdev); -error2: - class_unregister(&flashlight_class); -error1: - unregister_chrdev_region(flashlight_devno, 1); -out: - return ret; -} - -static int flashlight_remove(struct platform_device *pdev) -{ - unregister_chrdev_region(flashlight_devno, 1); - class_unregister(&flashlight_class); - device_destroy(NULL, flashlight_devno); - cdev_del(flashlight_cdev); - return 0; -} - -int set_flashlight(bool mode) -{ - struct aml_plat_flashlight_data_s *pdata = NULL; - - if (devp && devp->platform_data) { - pdata = devp->platform_data; - if (!mode) { - if (pdata->flashlight_off) - pdata->flashlight_off(); - } else { - if (pdata->flashlight_on) - pdata->flashlight_on(); - } - } - return 0; -} -EXPORT_SYMBOL(set_flashlight); - -enum aml_plat_flashlight_status_s get_flashlightflag(void) -{ - return flashlight_flag; -} -EXPORT_SYMBOL(get_flashlightflag); - -static int __init flashlight_init(void) -{ - int ret = -1; - - ret = platform_driver_register(&flashlight_driver); - if (ret != 0) { - pr_err("failed to register flashlight driver,error %d\n", ret); - return -ENODEV; - } - return ret; -} - -static void __exit flashlight_exit(void) -{ - platform_driver_unregister(&flashlight_driver); -} - -module_init(flashlight_init); -module_exit(flashlight_exit); - -MODULE_DESCRIPTION("AMLOGIC flashlight driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("amlogic"); diff --git a/drivers/amlogic/media/camera/common/plat_ctrl.c b/drivers/amlogic/media/camera/common/plat_ctrl.c deleted file mode 100644 index 44aa8bd8e8b9..000000000000 --- a/drivers/amlogic/media/camera/common/plat_ctrl.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/plat_ctrl.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "plat_ctrl.h" - -/**************************************************************** - * i2c functions - * **************************************************************/ -static int camera_read_buff(struct i2c_client *client, char *buf, int addr_len, - int data_len) -{ - int i2c_flag = -1; - struct i2c_msg msgs[] = {{ - .addr = client->addr, .flags = 0, - .len = addr_len, .buf = buf, - }, { - .addr = client->addr, .flags = I2C_M_RD, - .len = data_len, .buf = buf, - } - }; - - i2c_flag = i2c_transfer(client->adapter, msgs, 2); - - return i2c_flag; -} - -static int camera_write_buff(struct i2c_client *client, char *buf, int len) -{ - struct i2c_msg msg[] = {{ - .addr = client->addr, .flags = 0, /* |I2C_M_TEN, */ - .len = len, .buf = buf, - } - - }; - - if (i2c_transfer(client->adapter, msg, 1) < 0) { - pr_err("i2c error\n"); - return -1; - } else - return 0; -} - -int i2c_get_byte(struct i2c_client *client, unsigned short addr) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - - if (camera_read_buff(client, buff, 2, 1) < 0) - return -1; - return buff[0]; -} - -int i2c_get_byte_add8(struct i2c_client *client, unsigned char addr) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)(addr & 0xff); - - if (camera_read_buff(client, buff, 1, 1) < 0) - return -1; - return buff[0]; -} - -int i2c_get_word(struct i2c_client *client, unsigned short addr) -{ - unsigned short data; - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - - if (camera_read_buff(client, buff, 2, 2) < 0) - return -1; - - data = buff[0]; - data = (data << 8) | buff[1]; - return data; -} - -int i2c_put_byte(struct i2c_client *client, unsigned short addr, - unsigned char data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - buff[2] = data; - if (camera_write_buff(client, buff, 3) < 0) - return -1; - return 0; -} - -int i2c_put_word(struct i2c_client *client, unsigned short addr, - unsigned short data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)((addr >> 8) & 0xff); - buff[1] = (unsigned char)(addr & 0xff); - buff[2] = (unsigned char)((data >> 8) & 0xff); - buff[3] = (unsigned char)(data & 0xff); - - if (camera_write_buff(client, buff, 4) < 0) - return -1; - return 0; -} - -int i2c_put_byte_add8_new(struct i2c_client *client, unsigned char addr, - unsigned char data) -{ - unsigned char buff[4]; - - buff[0] = (unsigned char)(addr & 0xff); - buff[1] = (unsigned char)(data & 0xff); - if (camera_write_buff(client, buff, 2) < 0) - return -1; - return 0; -} - -int i2c_put_byte_add8(struct i2c_client *client, char *buf, int len) -{ - if (camera_write_buff(client, buf, len) < 0) - return -1; - return 0; -} - -int cam_i2c_send_msg(struct i2c_client *client, struct cam_i2c_msg_s i2c_msg) -{ - unsigned char buff[4]; - - switch (i2c_msg.type) { - case ADDR16_DATA16: - buff[0] = (unsigned char)((i2c_msg.addr >> 8) & 0xff); - buff[1] = (unsigned char)(i2c_msg.addr & 0xff); - buff[2] = (unsigned char)((i2c_msg.data >> 8) & 0xff); - buff[3] = (unsigned char)(i2c_msg.data & 0xff); - if (camera_write_buff(client, buff, 4) < 0) - return -1; - break; - case ADDR16_DATA8: - buff[0] = (unsigned char)((i2c_msg.addr >> 8) & 0xff); - buff[1] = (unsigned char)(i2c_msg.addr & 0xff); - buff[2] = (unsigned char)(i2c_msg.data & 0xff); - if (camera_write_buff(client, buff, 3) < 0) - return -1; - break; - case ADDR8_DATA16: - buff[0] = (unsigned char)(i2c_msg.addr & 0xff); - buff[1] = (unsigned char)((i2c_msg.data >> 8) & 0xff); - buff[2] = (unsigned char)(i2c_msg.data & 0xff); - if (camera_write_buff(client, buff, 3) < 0) - return -1; - break; - case ADDR8_DATA8: - buff[0] = (unsigned char)(i2c_msg.addr & 0xff); - buff[1] = (unsigned char)(i2c_msg.data & 0xff); - if (camera_write_buff(client, buff, 2) < 0) - return -1; - break; - case TIME_DELAY: - msleep(i2c_msg.data); - break; - default: - break; - } - return 0; -} - diff --git a/drivers/amlogic/media/camera/common/plat_ctrl.h b/drivers/amlogic/media/camera/common/plat_ctrl.h deleted file mode 100644 index 6bcb6cbfc264..000000000000 --- a/drivers/amlogic/media/camera/common/plat_ctrl.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/plat_ctrl.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _AMLOGIC_CAMERA_PLAT_CTRL_H -#define _AMLOGIC_CAMERA_PLAT_CTRL_H - -#define ADDR8_DATA8 0 -#define ADDR16_DATA8 1 -#define ADDR16_DATA16 2 -#define ADDR8_DATA16 3 -#define TIME_DELAY 0xfe -#define END_OF_SCRIPT 0xff - -struct cam_i2c_msg_s { - unsigned char type; - unsigned short addr; - unsigned short data; -}; - -extern int i2c_get_byte(struct i2c_client *client, unsigned short addr); -extern int i2c_get_word(struct i2c_client *client, unsigned short addr); -extern int i2c_get_byte_add8(struct i2c_client *client, unsigned char addr); -extern int i2c_put_byte(struct i2c_client *client, unsigned short addr, - unsigned char data); -extern int i2c_put_word(struct i2c_client *client, unsigned short addr, - unsigned short data); -extern int i2c_put_byte_add8_new(struct i2c_client *client, unsigned char addr, - unsigned char data); -extern int i2c_put_byte_add8(struct i2c_client *client, char *buf, int len); -extern int cam_i2c_send_msg(struct i2c_client *client, - struct cam_i2c_msg_s i2c_msg); - -#endif /* _AMLOGIC_CAMERA_PLAT_CTRL_H. */ diff --git a/drivers/amlogic/media/camera/common/vm.c b/drivers/amlogic/media/camera/common/vm.c deleted file mode 100644 index 231ab58ab19f..000000000000 --- a/drivers/amlogic/media/camera/common/vm.c +++ /dev/null @@ -1,2293 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/vm.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "vm_log.h" -#include "vm.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/*class property info.*/ -#include "vmcls.h" - -/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#if 1 -#define GE2D_NV -#endif - -#if 0 -static unsigned int amlvm_time_log_enable; -module_param(amlvm_time_log_enable, uint, 0644); -MODULE_PARM_DESC(amlvm_time_log_enable, "enable vm time log when get frames"); -#endif - -#define MAX_VF_POOL_SIZE 8 - -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -/*same as tvin pool*/ -static int VM_POOL_SIZE = 6; -static int VF_POOL_SIZE = 6; -static int VM_CANVAS_ID = 24; -/*same as tvin pool*/ -#endif - - -/*the counter of VM*/ -#define VM_MAX_DEVS 2 - -static struct vm_device_s *vm_device[VM_MAX_DEVS]; - -/* static bool isvmused; */ - -static void vm_cache_this_flush(unsigned int buf_start, - unsigned int buf_size, - struct vm_init_s *info); - -static inline void vm_vf_put_from_provider(struct vframe_s *vf, - unsigned int vdin_id); -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -#define INCPTR(p) ptr_atomic_wrap_inc(&p) -#endif - -#ifdef CONFIG_AMLOGIC_CAPTURE_FRAME_ROTATE -static int vmdecbuf_size[] = { - 0x13B3000,/* 5M */ - 0xc00000,/* 3M */ - 0x753000,/* 2M */ - 0x4b0000,/* 1M3 */ - 0x300000,/* 1M */ - 0x12c000,/* VGA */ - 0x4b000,/* QVGA */ -}; -static struct v4l2_frmsize_discrete canvas_config_wh[] = { - {2624, 2624}, - {2048, 2048}, - {1600, 1600}, - {1280, 1280}, - {1024, 1024}, - {640, 640}, - {320, 320}, -}; -#else -static int vmdecbuf_size[] = { - 0xEE5000,/* 5M */ - 0x900000,/* 3M */ - 0x591000,/* 2M */ - 0x384000,/* 1M3 */ - 0x240000,/* 1M */ - 0xF0000,/* VGA */ - 0x3C000,/* QVGA */ -}; -static struct v4l2_frmsize_discrete canvas_config_wh[] = { - {2624, 1984}, - {2048, 1536}, - {1600, 1216}, - {1280, 960}, - {1024, 768}, - {640, 512}, - {320, 256}, -}; -#endif -#define GE2D_ENDIAN_SHIFT 24 -#define GE2D_ENDIAN_MASK (0x1 << GE2D_ENDIAN_SHIFT) -#define GE2D_BIG_ENDIAN (0 << GE2D_ENDIAN_SHIFT) -#define GE2D_LITTLE_ENDIAN (1 << GE2D_ENDIAN_SHIFT) - -#define PROVIDER_NAME "vm" - -static dev_t vm_devno; -static struct class *vm_clsp; - -#define VM_DEV_NAME "vm" -#define RECEIVER_NAME "vm" -#define VM_CLS_NAME "vm" - -static DEFINE_SPINLOCK(lock); - -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -static inline void ptr_atomic_wrap_inc(u32 *ptr) -{ - u32 i = *ptr; - - i++; - if (i >= VM_POOL_SIZE) - i = 0; - *ptr = i; -} -#endif - -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -static struct vframe_s vfpool[MAX_VF_POOL_SIZE]; -static s32 vfbuf_use[MAX_VF_POOL_SIZE]; -static s32 fill_ptr, get_ptr, putting_ptr, put_ptr; -#endif - -atomic_t waiting_flag = ATOMIC_INIT(0); - -static inline struct vframe_s *vm_vf_get_from_provider(unsigned int vdin_id); -static inline struct vframe_s *vm_vf_peek_from_provider(unsigned int vdin_id); -static inline void vm_vf_put_from_provider(struct vframe_s *vf, - unsigned int vdin_id); -static struct vframe_receiver_op_s *vf_vm_unreg_provider( - struct vm_device_s *vdevp); -static struct vframe_receiver_op_s *vf_vm_reg_provider(struct vm_device_s - *vdevp); -static void stop_vm_task(struct vm_device_s *vdevp); -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -static int prepare_vframe(struct vframe_s *vf); -#endif - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - -/* - *********************************************** - * - * buffer op for video sink. - * - *********************************************** - */ - -#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -static struct vframe_s *local_vf_peek(unsigned int vdin_id) -{ - struct vframe_s *vf = NULL; - - vf = vm_vf_peek_from_provider(vdin_id); - if (vf) { - if (vm_device[vdin_id]->vm_skip_count > 0) { - vm_device[vdin_id]->vm_skip_count--; - vm_vf_get_from_provider(vdin_id); - vm_vf_put_from_provider(vf, vdin_id); - vf = NULL; - } - } - return vf; -} - -static struct vframe_s *local_vf_get(unsigned int vdin_id) -{ - return vm_vf_get_from_provider(vdin_id); -} - -static void local_vf_put(struct vframe_s *vf, unsigned int vdin_id) -{ - if (vf) - vm_vf_put_from_provider(vf, vdin_id); -} -#else - -static inline u32 index2canvas(u32 index) -{ - int i; - int start_canvas, count; - u32 canvas_tab[6]; - struct vdin_v4l2_ops_s *vops = get_vdin_v4l2_ops(); - - vops->get_tvin_canvas_info(&start_canvas, &count); - VM_POOL_SIZE = count; - VF_POOL_SIZE = count; - VM_CANVAS_ID = start_canvas; - for (i = 0; i < count; i++) - canvas_tab[i] = VM_CANVAS_INDEX + i; - return canvas_tab[index]; -} - -static struct vframe_s *vm_vf_peek(void *op_arg, unsigned int vdin_id) -{ - struct vframe_s *vf = NULL; - - vf = vm_vf_peek_from_provider(vdin_id); - if (vf) { - if (vm_device[vdin_id]->vm_skip_count > 0) { - vm_device[vdin_id]->vm_skip_count--; - vm_vf_get_from_provider(vdin_id); - vm_vf_put_from_provider(vf, vdin_id); - vf = NULL; - } - } - return vf; -} - -static struct vframe_s *vm_vf_get(void *op_arg, unsigned int vdin_id) -{ - return vm_vf_get_from_provider(vdin_id); -} - -static void vm_vf_put(struct vframe_s *vf, void *op_arg) -{ - prepare_vframe(vf); -} - -static int vm_vf_states(struct vframe_states *states, void *op_arg) -{ - return 0; -} - -static struct vframe_s *local_vf_peek(void) -{ - if (get_ptr == fill_ptr) - return NULL; - return &vfpool[get_ptr]; -} - -static struct vframe_s *local_vf_get(unsigned int vdin_id) -{ - struct vframe_s *vf; - - if (get_ptr == fill_ptr) - return NULL; - vf = &vfpool[get_ptr]; - INCPTR(get_ptr); - return vf; -} - -static void local_vf_put(struct vframe_s *vf, unsigned int vdin_id) -{ - int i; - int canvas_addr; - - if (!vf) - return; - INCPTR(putting_ptr); - for (i = 0; i < VF_POOL_SIZE; i++) { - canvas_addr = index2canvas(i); - if (vf->canvas0Addr == canvas_addr) { - vfbuf_use[i] = 0; - vm_vf_put_from_provider(vf, vdin_id); - } - } -} -#endif - -#if 0 -static int local_vf_states(struct vframe_states *states) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&lock, flags); - states->vf_pool_size = VF_POOL_SIZE; - - i = put_ptr - fill_ptr; - if (i < 0) - i += VF_POOL_SIZE; - states->buf_free_num = i; - - i = putting_ptr - put_ptr; - if (i < 0) - i += VF_POOL_SIZE; - states->buf_recycle_num = i; - - i = fill_ptr - get_ptr; - if (i < 0) - i += VF_POOL_SIZE; - states->buf_avail_num = i; - - spin_unlock_irqrestore(&lock, flags); - return 0; -} -#endif - -static int vm_receiver_event_fun(int type, void *data, void *private_data) -{ - struct vm_device_s *vdevp = (struct vm_device_s *)private_data; - - switch (type) { - case VFRAME_EVENT_PROVIDER_VFRAME_READY: - /* if (atomic_read(&waiting_flag)) { */ - wake_up_interruptible(&vdevp->frame_ready); - /* atomic_set(&waiting_flag, 0); */ - /* } */ - /* up(&vb_start_sema); */ - /* printk("vdin %d frame ready !!!!!\n", vdevp->index); */ - break; - case VFRAME_EVENT_PROVIDER_START: - /* printk("vm register!!!!!\n"); */ - vf_vm_reg_provider(vdevp); - vdevp->vm_skip_count = 0; - vdevp->test_zoom = 0; - break; - case VFRAME_EVENT_PROVIDER_UNREG: - /* printk("vm unregister!!!!!\n"); */ - vm_local_init(); - vf_vm_unreg_provider(vdevp); - /* printk("vm unregister succeed!!!!!\n"); */ - break; - default: - break; - } - return 0; -} - -static struct vframe_receiver_op_s vm_vf_receiver = { - .event_cb = vm_receiver_event_fun -}; - -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -static const struct vframe_operations_s vm_vf_provider = { - .peek = vm_vf_peek, - .get = vm_vf_get, - .put = vm_vf_put, - .vf_states = vm_vf_states, -}; - -static struct vframe_provider_s vm_vf_prov; -#endif - - -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -int get_unused_vm_index(void) -{ - int i; - - for (i = 0; i < VF_POOL_SIZE; i++) { - if (vfbuf_use[i] == 0) - return i; - } - return -1; -} -static int prepare_vframe(struct vframe_s *vf) -{ - struct vframe_s *new_vf; - int index; - - index = get_unused_vm_index(); - if (index < 0) - return -1; - new_vf = &vfpool[fill_ptr]; - memcpy(new_vf, vf, sizeof(struct vframe_s)); - vfbuf_use[index]++; - INCPTR(fill_ptr); - return 0; -} -#endif - -/* - ************************************************ - * - * buffer op for decoder, camera, etc. - * - ************************************************** - */ - -/* static const vframe_provider_t *vfp = NULL; */ - -void vm_local_init(void) -{ -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - int i; - - for (i = 0; i < MAX_VF_POOL_SIZE; i++) - vfbuf_use[i] = 0; - fill_ptr = get_ptr = putting_ptr = put_ptr = 0; -#endif -} - -static struct vframe_receiver_op_s *vf_vm_unreg_provider( - struct vm_device_s *vdevp) -{ - /* ulong flags; */ -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - vf_unreg_provider(&vm_vf_prov); -#endif - stop_vm_task(vdevp); - /* spin_lock_irqsave(&lock, flags); */ - /* vfp = NULL; */ - /* spin_unlock_irqrestore(&lock, flags); */ - return (struct vframe_receiver_op_s *)NULL; -} -EXPORT_SYMBOL(vf_vm_unreg_provider); - -static struct vframe_receiver_op_s *vf_vm_reg_provider(struct vm_device_s - *vdevp) -{ - ulong flags; - /* int ret; */ - spin_lock_irqsave(&lock, flags); - spin_unlock_irqrestore(&lock, flags); - vm_buffer_init(vdevp); -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - vf_reg_provider(&vm_vf_prov); -#endif - start_vm_task(vdevp); -#if 0 - start_simulate_task(); -#endif - return &vm_vf_receiver; -} -EXPORT_SYMBOL(vf_vm_reg_provider); - -static inline struct vframe_s *vm_vf_peek_from_provider(unsigned int vdin_id) -{ - struct vframe_provider_s *vfp; - struct vframe_s *vf; - char name[20]; - - sprintf(name, "%s%d", RECEIVER_NAME, vdin_id); - vfp = vf_get_provider(name); - if (!(vfp && vfp->ops && vfp->ops->peek)) - return NULL; - vf = vfp->ops->peek(vfp->op_arg); - return vf; -} - -static inline struct vframe_s *vm_vf_get_from_provider(unsigned int vdin_id) -{ - struct vframe_provider_s *vfp; - char name[20]; - - sprintf(name, "%s%d", RECEIVER_NAME, vdin_id); - vfp = vf_get_provider(name); - if (!(vfp && vfp->ops && vfp->ops->peek)) - return NULL; - return vfp->ops->get(vfp->op_arg); -} - -static inline void vm_vf_put_from_provider(struct vframe_s *vf, - unsigned int vdin_id) -{ - struct vframe_provider_s *vfp; - char name[20]; - - sprintf(name, "%s%d", RECEIVER_NAME, vdin_id); - vfp = vf_get_provider(name); - if (!(vfp && vfp->ops && vfp->ops->peek)) - return; - vfp->ops->put(vf, vfp->op_arg); -} - -/* - *********************************************** - * - * main task functions. - * - *********************************************** - */ - -static unsigned int print_ifmt; -/* module_param(print_ifmt, unsigned int, 0644); */ -/* MODULE_PARM_DESC(print_ifmt, "print input format\n"); */ - -static int get_input_format(struct vframe_s *vf) -{ - int format = GE2D_FORMAT_M24_NV21; - - if (vf->type & VIDTYPE_VIU_422) { - if (vf->type & VIDTYPE_INTERLACE_BOTTOM) - format = GE2D_FORMAT_S16_YUV422 | - (GE2D_FORMAT_S16_YUV422B & (3 << 3)); - else if (vf->type & VIDTYPE_INTERLACE_TOP) - format = GE2D_FORMAT_S16_YUV422 | - (GE2D_FORMAT_S16_YUV422T & (3 << 3)); - else - format = GE2D_FORMAT_S16_YUV422; - } else if (vf->type & VIDTYPE_VIU_NV21) { - if (vf->type & VIDTYPE_INTERLACE_BOTTOM) - format = GE2D_FORMAT_M24_NV21 | - (GE2D_FORMAT_M24_NV21B & (3 << 3)); - else if (vf->type & VIDTYPE_INTERLACE_TOP) - format = GE2D_FORMAT_M24_NV21 | - (GE2D_FORMAT_M24_NV21T & (3 << 3)); - else - format = GE2D_FORMAT_M24_NV21; - } else { - if (vf->type & VIDTYPE_INTERLACE_BOTTOM) - format = GE2D_FORMAT_M24_YUV420 | - (GE2D_FMT_M24_YUV420B & (3 << 3)); - else if (vf->type & VIDTYPE_INTERLACE_TOP) - format = GE2D_FORMAT_M24_YUV420 | - (GE2D_FORMAT_M24_YUV420T & (3 << 3)); - else - format = GE2D_FORMAT_M24_YUV420; - } - if (print_ifmt == 1) { - pr_debug("VIDTYPE_VIU_NV21=%x, vf->type=%x\n", - VIDTYPE_VIU_NV21, vf->type); - pr_debug("format=%x, w=%d, h=%d\n", - format, vf->width, vf->height); - print_ifmt = 0; - } - return format; -} - -#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER -static int calc_zoom(int *top, int *left, int *bottom, int *right, int zoom) -{ - u32 screen_width, screen_height; - s32 start, end; - s32 video_top, video_left, temp; - u32 video_width, video_height; - u32 ratio_x = 0; - u32 ratio_y = 0; - - if (zoom < 100) - zoom = 100; - - video_top = *top; - video_left = *left; - video_width = *right - *left + 1; - video_height = *bottom - *top + 1; - - screen_width = video_width * zoom / 100; - screen_height = video_height * zoom / 100; - - ratio_x = (video_width << 18) / screen_width; - if (ratio_x * screen_width < (video_width << 18)) - ratio_x++; - ratio_y = (video_height << 18) / screen_height; - - /* vertical */ - start = video_top + video_height / 2 - (video_height << 17) / ratio_y; - end = (video_height << 18) / ratio_y + start - 1; - - if (start < video_top) { - temp = ((video_top - start) * ratio_y) >> 18; - *top = temp; - } else - *top = 0; - - temp = *top + (video_height * ratio_y >> 18); - *bottom = (temp <= (video_height - 1)) ? temp : (video_height - 1); - - /* horizontal */ - start = video_left + video_width / 2 - (video_width << 17) / ratio_x; - end = (video_width << 18) / ratio_x + start - 1; - if (start < video_left) { - temp = ((video_left - start) * ratio_x) >> 18; - *left = temp; - } else - *left = 0; - - temp = *left + (video_width * ratio_x >> 18); - *right = (temp <= (video_width - 1)) ? temp : (video_width - 1); - return 0; -} -#endif - -static int get_input_frame(struct display_frame_s *frame, struct vframe_s *vf, - int zoom) -{ - int ret = 0; - int top, left, bottom, right; - - if (!vf) - return -1; - - frame->frame_top = 0; - frame->frame_left = 0; - frame->frame_width = vf->width; - frame->frame_height = vf->height; - top = 0; - left = 0; - bottom = vf->height - 1; - right = vf->width - 1; -#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - ret = calc_zoom(&top, &left, &bottom, &right, zoom); -#else - ret = get_curren_frame_para(&top, &left, &bottom, &right); -#endif - if (ret >= 0) { - frame->content_top = top & (~1); - frame->content_left = left & (~1); - frame->content_width = vf->width - 2 * frame->content_left; - frame->content_height = vf->height - 2 * frame->content_top; - } else { - frame->content_top = 0; - frame->content_left = 0; - frame->content_width = vf->width; - frame->content_height = vf->height; - } - return 0; -} - -static int get_output_format(int v4l2_format) -{ - int format = GE2D_FORMAT_S24_YUV444; - - switch (v4l2_format) { - case V4L2_PIX_FMT_RGB565X: - format = GE2D_FORMAT_S16_RGB_565; - break; - case V4L2_PIX_FMT_YUV444: - format = GE2D_FORMAT_S24_YUV444; - break; - case V4L2_PIX_FMT_VYUY: - format = GE2D_FORMAT_S16_YUV422; - break; - case V4L2_PIX_FMT_BGR24: - format = GE2D_FORMAT_S24_RGB; - break; - case V4L2_PIX_FMT_RGB24: - format = GE2D_FORMAT_S24_BGR; - break; - case V4L2_PIX_FMT_NV12: -#ifdef GE2D_NV - format = GE2D_FORMAT_M24_NV12; - break; -#endif - case V4L2_PIX_FMT_NV21: -#ifdef GE2D_NV - format = GE2D_FORMAT_M24_NV21; - break; -#endif - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - format = GE2D_FORMAT_S8_Y; - break; - default: - break; - } - return format; -} - - -struct vm_dma_contig_memory { - u32 magic; - void *vaddr; - dma_addr_t dma_handle; - unsigned long size; - int is_userptr; -}; - -int is_need_ge2d_pre_process(struct vm_output_para output_para) -{ - int ret = 0; - - switch (output_para.v4l2_format) { - case V4L2_PIX_FMT_RGB565X: - case V4L2_PIX_FMT_YUV444: - case V4L2_PIX_FMT_VYUY: - case V4L2_PIX_FMT_BGR24: - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - ret = 1; - break; - default: - break; - } - return ret; -} - -int is_need_sw_post_process(struct vm_output_para output_para) -{ - int ret = 0; - - switch (output_para.v4l2_memory) { - case MAGIC_DC_MEM: - case MAGIC_RE_MEM: - goto exit; - case MAGIC_SG_MEM: - case MAGIC_VMAL_MEM: - default: - ret = 1; - break; - } -exit: - return ret; -} - -int get_canvas_index(int v4l2_format, int *depth) -{ - int canvas = vm_device[0]->vm_canvas[0]; - *depth = 16; - switch (v4l2_format) { - case V4L2_PIX_FMT_RGB565X: - case V4L2_PIX_FMT_VYUY: - canvas = vm_device[0]->vm_canvas[0]; - *depth = 16; - break; - case V4L2_PIX_FMT_YUV444: - case V4L2_PIX_FMT_BGR24: - case V4L2_PIX_FMT_RGB24: - canvas = vm_device[0]->vm_canvas[1]; - *depth = 24; - break; - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: -#ifdef GE2D_NV - canvas = vm_device[0]->vm_canvas[2] | - (vm_device[0]->vm_canvas[3] << 8); -#else - canvas = vm_device[0]->vm_canvas[2] | - (vm_device[0]->vm_canvas[3] << 8) | - (vm_device[0]->vm_canvas[4] << 16); -#endif - *depth = 12; - break; - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - canvas = vm_device[0]->vm_canvas[5] | - (vm_device[0]->vm_canvas[6] << 8) | - (vm_device[0]->vm_canvas[7] << 16); - *depth = 12; - break; - default: - break; - } - return canvas; -} - -int get_canvas_index_res(int ext_canvas, int v4l2_format, int *depth, int width, - int height, unsigned int buf) -{ - int canvas = ext_canvas; - *depth = 16; - switch (v4l2_format) { - case V4L2_PIX_FMT_RGB565X: - case V4L2_PIX_FMT_VYUY: - canvas = ext_canvas & 0xff; - *depth = 16; - canvas_config(canvas, - (unsigned long)buf, - width * 2, height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - break; - case V4L2_PIX_FMT_YUV444: - case V4L2_PIX_FMT_BGR24: - case V4L2_PIX_FMT_RGB24: - canvas = ext_canvas & 0xff; - *depth = 24; - canvas_config(canvas, - (unsigned long)buf, - width * 3, height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - break; - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - canvas_config(ext_canvas & 0xff, - (unsigned long)buf, - width, height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config((ext_canvas & 0xff00) >> 8, - (unsigned long)(buf + width * height), - width, height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas = ext_canvas & 0xffff; - *depth = 12; - break; - case V4L2_PIX_FMT_YVU420: - case V4L2_PIX_FMT_YUV420: - canvas_config(ext_canvas & 0xff, - (unsigned long)buf, - width, height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config((ext_canvas & 0xff00) >> 8, - (unsigned long)(buf + width * height), - width / 2, height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config((ext_canvas & 0xff0000) >> 16, - (unsigned long)(buf + width * height * 5 / 4), - width / 2, height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas = ext_canvas & 0xffffff; - *depth = 12; - break; - default: - break; - } - return canvas; -} - -#if 0 -static void vm_dump_mem(char *path, void *phy_addr, struct vm_output_para *para) -{ - struct file *filp = NULL; - loff_t pos = 0; - void *buf = NULL; - unsigned int size = para->bytesperline * para->height; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - filp = filp_open(path, O_RDWR | O_CREAT, 0666); - - if (IS_ERR(filp)) { - pr_err("create %s error.\n", path); - return; - } - - - buf = phys_to_virt((unsigned long)phy_addr); - vfs_write(filp, buf, size, &pos); - - vfs_fsync(filp, 0); - filp_close(filp, NULL); - set_fs(old_fs); -} - -static void vm_x_mem(char *path, struct vm_output_para *para) -{ - struct file *filp = NULL; - loff_t pos = 0; - void *buf = NULL; - unsigned int size = para->bytesperline * para->height; - unsigned int canvas_index = para->index; - struct canvas_s cv; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - filp = filp_open(path, O_CREAT | O_RDWR | O_APPEND, 0666); - - if (IS_ERR(filp)) { - pr_err("failed to create %s, error %p.\n", - path, filp); - return; - } - - for (; canvas_index != 0; canvas_index >>= 8) { - canvas_read(canvas_index & 0xff, &cv); - /* printk("index=%lx,canvas.addr=%lx, w=%d, h=%d\n", */ - /* canvas_index, cv.addr, cv.width, cv.height); */ - - buf = phys_to_virt(cv.addr); - - size = cv.width * cv.height; - - vfs_write(filp, buf, size, &pos); - vfs_fsync(filp, 0); - } - filp_close(filp, NULL); - set_fs(old_fs); -} -#endif - -int vm_fill_this_buffer(struct videobuf_buffer *vb, - struct vm_output_para *para, struct vm_init_s *info) - -{ - int depth = 0; - int ret = 0; - int canvas_index = -1; - int v4l2_format = V4L2_PIX_FMT_YUV444; - int magic = 0; - int ext_canvas; - struct videobuf_buffer buf = {0}; - - if (!info) - return -1; - if (info->vdin_id >= VM_MAX_DEVS) { - pr_err("beyond the device array bound .\n"); - return -1; - } - /* if (info->isused == false) */ - /* return -2; */ -#if 0 - if (!vb) - goto exit; -#else - if (!vb) { - buf.width = 640; - buf.height = 480; - v4l2_format = V4L2_PIX_FMT_YUV444; - vb = &buf; - } - - if (!vm_device[info->vdin_id]->task_running) - return -1; -#endif - - v4l2_format = para->v4l2_format; - magic = para->v4l2_memory; - switch (magic) { - case MAGIC_DC_MEM: - /* mem = vb->priv; */ - canvas_config(vm_device[0]->vm_canvas[11], - (dma_addr_t)para->vaddr, - vb->bytesperline, vb->height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_index = vm_device[0]->vm_canvas[11]; - depth = (vb->bytesperline << 3) / vb->width; - break; - case MAGIC_RE_MEM: - if (para->ext_canvas != 0) - canvas_index = get_canvas_index_res( - para->ext_canvas, v4l2_format, - &depth, vb->width, - (para->height == 0) ? vb->height : para->height, - (unsigned int)para->vaddr); - else if (info->vdin_id == 0) { - ext_canvas = ((vm_device[0]->vm_canvas[3]) | - (vm_device[0]->vm_canvas[4] << 8) | - (vm_device[0]->vm_canvas[5] << 16)); - canvas_index = - get_canvas_index_res(ext_canvas, - v4l2_format, &depth, vb->width, - vb->height, (unsigned int)para->vaddr); - } else { - ext_canvas = ((vm_device[1]->vm_canvas[0]) | - (vm_device[1]->vm_canvas[1] << 8) | - (vm_device[1]->vm_canvas[2] << 16)); - canvas_index = - get_canvas_index_res(ext_canvas, - v4l2_format, &depth, vb->width, - vb->height, (unsigned int)para->vaddr); - } - break; - case MAGIC_SG_MEM: - case MAGIC_VMAL_MEM: - if (vm_device[info->vdin_id]->buffer_start && - vm_device[info->vdin_id]->buffer_size) - canvas_index = get_canvas_index(v4l2_format, &depth); - break; - default: - canvas_index = vm_device[0]->vm_canvas[0]; - break; - } - vm_device[info->vdin_id]->output_para.width = vb->width; - vm_device[info->vdin_id]->output_para.height = vb->height; - vm_device[info->vdin_id]->output_para.bytesperline = - (vb->width * depth) >> 3; - vm_device[info->vdin_id]->output_para.index = canvas_index; - vm_device[info->vdin_id]->output_para.v4l2_format = v4l2_format; - vm_device[info->vdin_id]->output_para.v4l2_memory = magic; - vm_device[info->vdin_id]->output_para.mirror = para->mirror; - vm_device[info->vdin_id]->output_para.zoom = para->zoom; - vm_device[info->vdin_id]->output_para.angle = para->angle; - vm_device[info->vdin_id]->output_para.vaddr = para->vaddr; - vm_device[info->vdin_id]->output_para.ext_canvas = - (magic == MAGIC_RE_MEM) ? para->ext_canvas : 0; - complete(&vm_device[info->vdin_id]->vb_start_sema); - wait_for_completion(&vm_device[info->vdin_id]->vb_done_sema); - if (magic == MAGIC_RE_MEM) - vm_cache_this_flush((unsigned int)para->vaddr, - para->bytesperline * - para->height, info); - - return ret; -} - -/* - *for decoder input processing - * 1. output window should 1:1 as source frame size - * 2. keep the frame ratio - * 3. input format should be YUV420 , output format should be YUV444 - */ - -int vm_ge2d_pre_process(struct vframe_s *vf, - struct ge2d_context_s *context, - struct config_para_ex_s *ge2d_config, - struct vm_output_para output_para, - unsigned int index) -{ - int ret; - int src_top, src_left, src_width, src_height; - struct canvas_s cs0, cs1, cs2, cd; - int current_mirror = 0; - int cur_angle = 0; - struct display_frame_s input_frame = {0}; - - ret = get_input_frame(&input_frame, vf, output_para.zoom); - src_top = input_frame.content_top; - src_left = input_frame.content_left; - src_width = input_frame.content_width; - src_height = input_frame.content_height; - if (vm_device[index]->test_zoom) { - vm_device[index]->test_zoom = 0; - pr_debug("top is %d , left is %d\n", - input_frame.content_top, - input_frame.content_left); - pr_debug("width is %d , height is %d\n", - input_frame.content_width, - input_frame.content_height); - } -#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - current_mirror = output_para.mirror; - if (current_mirror < 0) - current_mirror = 0; -#else - current_mirror = camera_mirror_flag; -#endif - - cur_angle = output_para.angle; - if (current_mirror == 1) - cur_angle = (360 - cur_angle % 360); - else - cur_angle = cur_angle % 360; - - /* data operating. */ - ge2d_config->alu_const_color = 0; /* 0x000000ff; */ - ge2d_config->bitmask_en = 0; - ge2d_config->src1_gb_alpha = 0;/* 0xff; */ - ge2d_config->dst_xy_swap = 0; - - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; - canvas_read(output_para.index & 0xff, &cd); - ge2d_config->dst_planes[0].addr = cd.addr; - ge2d_config->dst_planes[0].w = cd.width; - ge2d_config->dst_planes[0].h = cd.height; - ge2d_config->src_key.key_enable = 0; - ge2d_config->src_key.key_mask = 0; - ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; - ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config->src_para.format = get_input_format(vf); - ge2d_config->src_para.fill_color_en = 0; - ge2d_config->src_para.fill_mode = 0; - ge2d_config->src_para.x_rev = 0; - ge2d_config->src_para.y_rev = 0; - ge2d_config->src_para.color = 0xffffffff; - ge2d_config->src_para.top = 0; - ge2d_config->src_para.left = 0; - ge2d_config->src_para.width = vf->width; - ge2d_config->src_para.height = vf->height; - ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config->dst_para.canvas_index = output_para.index & 0xff; -#ifdef GE2D_NV - if ((output_para.v4l2_format != V4L2_PIX_FMT_YUV420) - && (output_para.v4l2_format != V4L2_PIX_FMT_YVU420)) - ge2d_config->dst_para.canvas_index = output_para.index; -#endif - ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config->dst_para.format = - get_output_format(output_para.v4l2_format) | - GE2D_LITTLE_ENDIAN; - ge2d_config->dst_para.fill_color_en = 0; - ge2d_config->dst_para.fill_mode = 0; - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - ge2d_config->dst_para.color = 0; - ge2d_config->dst_para.top = 0; - ge2d_config->dst_para.left = 0; - ge2d_config->dst_para.width = output_para.width; - ge2d_config->dst_para.height = output_para.height; - - if (current_mirror == 1) { - ge2d_config->dst_para.x_rev = 1; - ge2d_config->dst_para.y_rev = 0; - } else if (current_mirror == 2) { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 1; - } else { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - } - - if (cur_angle == 90) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.x_rev ^= 1; - } else if (cur_angle == 180) { - ge2d_config->dst_para.x_rev ^= 1; - ge2d_config->dst_para.y_rev ^= 1; - } else if (cur_angle == 270) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.y_rev ^= 1; - } - - if (ge2d_context_config_ex(context, ge2d_config) < 0) { - pr_err("++ge2d configing error.\n"); - return -1; - } - stretchblt_noalpha(context, src_left, src_top, - src_width, src_height, 0, 0, - output_para.width, output_para.height); - - /* for cr of yuv420p or yuv420sp. */ - if ((output_para.v4l2_format == V4L2_PIX_FMT_YUV420) - || (output_para.v4l2_format == V4L2_PIX_FMT_YVU420)) { - /* for cb. */ - canvas_read((output_para.index >> 8) & 0xff, &cd); - ge2d_config->dst_planes[0].addr = cd.addr; - ge2d_config->dst_planes[0].w = cd.width; - ge2d_config->dst_planes[0].h = cd.height; - ge2d_config->dst_para.canvas_index = - (output_para.index >> 8) & 0xff; -#ifndef GE2D_NV - ge2d_config->dst_para.format = - GE2D_FORMAT_S8_CB | GE2D_LITTLE_ENDIAN; -#else - ge2d_config->dst_para.format = - GE2D_FORMAT_S8_CR | GE2D_LITTLE_ENDIAN; -#endif - ge2d_config->dst_para.width = output_para.width / 2; - ge2d_config->dst_para.height = output_para.height / 2; - ge2d_config->dst_xy_swap = 0; - - if (current_mirror == 1) { - ge2d_config->dst_para.x_rev = 1; - ge2d_config->dst_para.y_rev = 0; - } else if (current_mirror == 2) { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 1; - } else { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - } - - if (cur_angle == 90) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.x_rev ^= 1; - } else if (cur_angle == 180) { - ge2d_config->dst_para.x_rev ^= 1; - ge2d_config->dst_para.y_rev ^= 1; - } else if (cur_angle == 270) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.y_rev ^= 1; - } - - if (ge2d_context_config_ex(context, ge2d_config) < 0) { - pr_err("++ge2d configing error.\n"); - return -1; - } - stretchblt_noalpha(context, src_left, src_top, - src_width, src_height, - 0, 0, ge2d_config->dst_para.width, - ge2d_config->dst_para.height); - } -#ifndef GE2D_NV - else if (output_para.v4l2_format == V4L2_PIX_FMT_NV12 || - output_para.v4l2_format == V4L2_PIX_FMT_NV21) { - canvas_read((output_para.index >> 8) & 0xff, &cd); - ge2d_config->dst_planes[0].addr = cd.addr; - ge2d_config->dst_planes[0].w = cd.width; - ge2d_config->dst_planes[0].h = cd.height; - ge2d_config->dst_para.canvas_index = - (output_para.index >> 8) & 0xff; - ge2d_config->dst_para.format = - GE2D_FORMAT_S8_CB | GE2D_LITTLE_ENDIAN; - ge2d_config->dst_para.width = output_para.width / 2; - ge2d_config->dst_para.height = output_para.height / 2; - ge2d_config->dst_xy_swap = 0; - - if (current_mirror == 1) { - ge2d_config->dst_para.x_rev = 1; - ge2d_config->dst_para.y_rev = 0; - } else if (current_mirror == 2) { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 1; - } else { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - } - - if (cur_angle == 90) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.x_rev ^= 1; - } else if (cur_angle == 180) { - ge2d_config->dst_para.x_rev ^= 1; - ge2d_config->dst_para.y_rev ^= 1; - } else if (cur_angle == 270) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.y_rev ^= 1; - } - - if (ge2d_context_config_ex(context, ge2d_config) < 0) { - pr_err("++ge2d configing error.\n"); - return -1; - } - stretchblt_noalpha(context, src_left, src_top, - src_width, src_height, 0, 0, - ge2d_config->dst_para.width, - ge2d_config->dst_para.height); - } -#endif - - /* for cb of yuv420p or yuv420sp. */ - if (output_para.v4l2_format == V4L2_PIX_FMT_YUV420 || - output_para.v4l2_format == V4L2_PIX_FMT_YVU420 -#ifndef GE2D_NV - || output_para.v4l2_format == V4L2_PIX_FMT_NV12 || - output_para.v4l2_format == V4L2_PIX_FMT_NV21 -#endif - ) { - canvas_read((output_para.index >> 16) & 0xff, &cd); - ge2d_config->dst_planes[0].addr = cd.addr; - ge2d_config->dst_planes[0].w = cd.width; - ge2d_config->dst_planes[0].h = cd.height; - ge2d_config->dst_para.canvas_index = - (output_para.index >> 16) & 0xff; -#ifndef GE2D_NV - ge2d_config->dst_para.format = - GE2D_FORMAT_S8_CR | GE2D_LITTLE_ENDIAN; -#else - ge2d_config->dst_para.format = - GE2D_FORMAT_S8_CB | GE2D_LITTLE_ENDIAN; -#endif - ge2d_config->dst_para.width = output_para.width / 2; - ge2d_config->dst_para.height = output_para.height / 2; - ge2d_config->dst_xy_swap = 0; - - if (current_mirror == 1) { - ge2d_config->dst_para.x_rev = 1; - ge2d_config->dst_para.y_rev = 0; - } else if (current_mirror == 2) { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 1; - } else { - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - } - - if (cur_angle == 90) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.x_rev ^= 1; - } else if (cur_angle == 180) { - ge2d_config->dst_para.x_rev ^= 1; - ge2d_config->dst_para.y_rev ^= 1; - } else if (cur_angle == 270) { - ge2d_config->dst_xy_swap = 1; - ge2d_config->dst_para.y_rev ^= 1; - } - - if (ge2d_context_config_ex(context, ge2d_config) < 0) { - pr_err("++ge2d configing error.\n"); - return -1; - } - stretchblt_noalpha(context, src_left, - src_top, src_width, src_height, - 0, 0, ge2d_config->dst_para.width, - ge2d_config->dst_para.height); - } - return output_para.index; -} - -int vm_sw_post_process(int canvas, uintptr_t addr, unsigned int index) -{ - int poss = 0, posd = 0; - int i = 0; - void __iomem *buffer_y_start; - void __iomem *buffer_u_start; - void __iomem *buffer_v_start = 0; - struct io_mapping *mapping_wc; - int offset = 0; - struct canvas_s canvas_work_y; - struct canvas_s canvas_work_u; - struct canvas_s canvas_work_v; - struct vm_output_para output_para = vm_device[index]->output_para; - - if (!addr) - return -1; - mapping_wc = io_mapping_create_wc(vm_device[index]->buffer_start, - vm_device[index]->buffer_size); - if (!mapping_wc) - return -1; - canvas_read(canvas & 0xff, &canvas_work_y); - offset = 0; - buffer_y_start = io_mapping_map_atomic_wc(mapping_wc, offset); - if (buffer_y_start == NULL) { - pr_err(" vm.postprocess:mapping buffer error\n"); - io_mapping_free(mapping_wc); - return -1; - } - if (output_para.v4l2_format == V4L2_PIX_FMT_BGR24 || - output_para.v4l2_format == V4L2_PIX_FMT_RGB24 || - output_para.v4l2_format == V4L2_PIX_FMT_RGB565X) { - for (i = 0; i < output_para.height; i++) { - memcpy((void *)(addr + poss), - (void *)(buffer_y_start + posd), - output_para.bytesperline); - poss += output_para.bytesperline; - posd += canvas_work_y.width; - } - io_mapping_unmap_atomic(buffer_y_start); - - } else if (output_para.v4l2_format == V4L2_PIX_FMT_NV12 || - output_para.v4l2_format == V4L2_PIX_FMT_NV21) { -#ifdef GE2D_NV - unsigned int uv_width = output_para.width; - unsigned int uv_height = output_para.height >> 1; - - posd = 0; - for (i = output_para.height; i > 0; i--) { /* copy y */ - memcpy((void *)(addr + poss), - (void *)(buffer_y_start + posd), - output_para.width); - poss += output_para.width; - posd += canvas_work_y.width; - } - io_mapping_unmap_atomic(buffer_y_start); - - posd = 0; - canvas_read((canvas >> 8) & 0xff, &canvas_work_u); - offset = canvas_work_u.addr - canvas_work_y.addr; - buffer_u_start = io_mapping_map_atomic_wc(mapping_wc, offset); - for (i = uv_height; i > 0; i--) { /* copy uv */ - memcpy((void *)(addr + poss), - (void *)(buffer_u_start + posd), uv_width); - poss += uv_width; - posd += canvas_work_u.width; - } - - io_mapping_unmap_atomic(buffer_u_start); -#else - char *dst_buff = NULL; - char *src_buff = NULL; - char *src2_buff = NULL; - - canvas_read((canvas >> 8) & 0xff, &canvas_work_u); - poss = posd = 0; - for (i = 0; i < output_para.height; i += 2) { /* copy y */ - memcpy((void *)(addr + poss), - (void *)(buffer_y_start + posd), - output_para.width); - poss += output_para.width; - posd += canvas_work_y.width; - memcpy((void *)(addr + poss), - (void *)(buffer_y_start + posd), - output_para.width); - poss += output_para.width; - posd += canvas_work_y.width; - } - io_mapping_unmap_atomic(buffer_y_start); - - posd = 0; - canvas_read((canvas >> 16) & 0xff, &canvas_work_v); - offset = canvas_work_u.addr - canvas_work_y.addr; - buffer_u_start = io_mapping_map_atomic_wc(mapping_wc, offset); - offset = canvas_work_v.addr - canvas_work_y.addr; - buffer_v_start = io_mapping_map_atomic_wc(mapping_wc, offset); - - dst_buff = (char *)addr + - output_para.width * output_para.height; - src_buff = (char *)buffer_u_start; - src2_buff = (char *)buffer_v_start; - if (output_para.v4l2_format == V4L2_PIX_FMT_NV12) { - for (i = 0 ; i < output_para.height / 2; i++) { - interleave_uv(src_buff, src2_buff, - dst_buff, output_para.width / 2); - src_buff += canvas_work_u.width; - src2_buff += canvas_work_v.width; - dst_buff += output_para.width; - } - } else { - for (i = 0 ; i < output_para.height / 2; i++) { - interleave_uv(src2_buff, src_buff, - dst_buff, output_para.width / 2); - src_buff += canvas_work_u.width; - src2_buff += canvas_work_v.width; - dst_buff += output_para.width; - } - } - - - io_mapping_unmap_atomic(buffer_u_start); - io_mapping_unmap_atomic(buffer_v_start); -#endif - } else if ((output_para.v4l2_format == V4L2_PIX_FMT_YUV420) - || (output_para.v4l2_format == V4L2_PIX_FMT_YVU420)) { - int uv_width = output_para.width >> 1; - int uv_height = output_para.height >> 1; - - posd = 0; - for (i = output_para.height; i > 0; i--) { /* copy y */ - memcpy((void *)(addr + poss), - (void *)(buffer_y_start + posd), - output_para.width); - poss += output_para.width; - posd += canvas_work_y.width; - } - io_mapping_unmap_atomic(buffer_y_start); - - posd = 0; - canvas_read((canvas >> 8) & 0xff, &canvas_work_u); - offset = canvas_work_u.addr - canvas_work_y.addr; - buffer_u_start = io_mapping_map_atomic_wc(mapping_wc, offset); - - canvas_read((canvas >> 16) & 0xff, &canvas_work_v); - offset = canvas_work_v.addr - canvas_work_y.addr; - buffer_v_start = io_mapping_map_atomic_wc(mapping_wc, offset); - -#ifndef GE2D_NV - if (output_para.v4l2_format == V4L2_PIX_FMT_YUV420) -#else - if (output_para.v4l2_format == V4L2_PIX_FMT_YVU420) { -#endif - for (i = uv_height; i > 0; i--) { /* copy y */ - memcpy((void *)(addr + poss), - (void *)(buffer_u_start + posd), - uv_width); - poss += uv_width; - posd += canvas_work_u.width; - } - posd = 0; - for (i = uv_height; i > 0; i--) { /* copy y */ - memcpy((void *)(addr + poss), - (void *)(buffer_v_start + posd), - uv_width); - poss += uv_width; - posd += canvas_work_v.width; - } - } else { - for (i = uv_height; i > 0; i--) { /* copy v */ - memcpy((void *)(addr + poss), - (void *)(buffer_v_start + posd), - uv_width); - poss += uv_width; - posd += canvas_work_v.width; - } - posd = 0; - for (i = uv_height; i > 0; i--) { /* copy u */ - memcpy((void *)(addr + poss), - (void *)(buffer_u_start + posd), - uv_width); - poss += uv_width; - posd += canvas_work_u.width; - } - } - io_mapping_unmap_atomic(buffer_u_start); - io_mapping_unmap_atomic(buffer_v_start); -} - - if (mapping_wc) - io_mapping_free(mapping_wc); - - return 0; -} - -static struct task_struct *simulate_task_fd; - -static bool is_vf_available(unsigned int vdin_id) -{ - bool ret = ((local_vf_peek(vdin_id) != NULL) || - (!vm_device[vdin_id]->task_running)); - return ret; -} - -/* static int reset_frame = 1; */ -static int vm_task(void *data) -{ - int ret = 0; - struct vframe_s *vf; - int src_canvas; - struct vm_device_s *devp = (struct vm_device_s *) data; - struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; - struct ge2d_context_s *context = create_ge2d_work_queue(); - struct config_para_ex_s ge2d_config; - -#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES - struct timeval start; - struct timeval end; - unsigned long time_use = 0; -#endif - memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); - sched_setscheduler(current, SCHED_FIFO, ¶m); - allow_signal(SIGTERM); - while (1) { - ret = wait_for_completion_interruptible( - &devp->vb_start_sema); - - if (kthread_should_stop()) { - complete(&devp->vb_done_sema); - break; - } - - /* wait for frame from 656 provider until 500ms runs out */ - wait_event_interruptible_timeout(devp->frame_ready, - is_vf_available(devp->index), - msecs_to_jiffies(2000)); - - if (!devp->task_running) { - ret = -1; - goto vm_exit; - } - - /* start to convert frame. */ -#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES - do_gettimeofday(&start); -#endif - vf = local_vf_get(devp->index); - - if (vf) { - src_canvas = vf->canvas0Addr; - - /* step1 convert 422 format to other format.*/ - if (is_need_ge2d_pre_process(devp->output_para)) - src_canvas = vm_ge2d_pre_process(vf, context, - &ge2d_config, devp->output_para, - devp->index); -#if 0 - if (devp->dump == 2) { - vm_dump_mem(devp->dump_path, - (void *)output_para.vaddr, &output_para); - devp->dump = 0; - } -#endif - local_vf_put(vf, devp->index); -#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES - do_gettimeofday(&end); - time_use = (end.tv_sec - start.tv_sec) * 1000 + - (end.tv_usec - start.tv_usec) / 1000; - pr_debug("step 1, ge2d use: %ldms\n", time_use); - do_gettimeofday(&start); -#endif - - /* step2 copy to user memory. */ - - if (is_need_sw_post_process(devp->output_para)) - vm_sw_post_process(src_canvas, - devp->output_para.vaddr, devp->index); - -#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES - do_gettimeofday(&end); - time_use = (end.tv_sec - start.tv_sec) * 1000 + - (end.tv_usec - start.tv_usec) / 1000; - pr_debug("step 2, memcpy use: %ldms\n", time_use); -#endif - } - if (kthread_should_stop()) { - complete(&devp->vb_done_sema); - break; - } - complete(&devp->vb_done_sema); - } -vm_exit: - destroy_ge2d_work_queue(context); - while (!kthread_should_stop()) { - /*may not call stop, wait.. - *it is killed by SIGTERM,eixt on - *down_interruptible. - *if not call stop,this thread - *may on do_exit and - *kthread_stop may not work good; - */ - msleep(20);/*default 10ms*/ - } - return ret; -} - -/*simulate v4l2 device to request*/ -/*filling buffer,only for test use*/ -static int simulate_task(void *data) -{ - while (1) { - msleep(50); - pr_debug("simulate succeed\n"); - } - return 0; -} - -/* - *********************************************** - * - * init functions. - * - *********************************************** - */ - -int vm_buffer_init(struct vm_device_s *vdevp) -{ - int i, j; - u32 canvas_width, canvas_height; - u32 decbuf_size; - resource_size_t buf_start; - unsigned int buf_size; - int buf_num = 0; - int local_pool_size = 0; - - init_completion(&vdevp->vb_start_sema); - init_completion(&vdevp->vb_done_sema); - - buf_start = vdevp->buffer_start; - buf_size = vdevp->buffer_size; - - if (vdevp->index == 0) { - for (j = 0; j < MAX_CANVAS_INDEX; j++) { - memset(&(vdevp->vm_canvas[j]), -1, sizeof(int)); - vdevp->vm_canvas[j] = - canvas_pool_map_alloc_canvas("vm0"); - if (vdevp->vm_canvas[j] < 0) { - pr_err("alloc vm0_canvas %d failed\n", j); - return -1; - } - } - } else { - for (j = 0; j < MAX_CANVAS_INDEX; j++) { - memset(&(vdevp->vm_canvas[j]), -1, sizeof(int)); - vdevp->vm_canvas[j] = - canvas_pool_map_alloc_canvas("vm1"); - if (vdevp->vm_canvas[j] < 0) { - pr_err("alloc vm1_canvas %d failed\n", j); - return -1; - } - } - } - - if (!buf_start || !buf_size) - goto exit; - - for (i = 0; i < ARRAY_SIZE(vmdecbuf_size); i++) { - if (buf_size >= vmdecbuf_size[i]) - break; - } - if (i == ARRAY_SIZE(vmdecbuf_size)) { - pr_debug("vmbuf size=%d less than the smallest vmbuf size%d\n", - buf_size, vmdecbuf_size[i - 1]); - return -1; - } - - canvas_width = canvas_config_wh[i].width;/* 1920; */ - canvas_height = canvas_config_wh[i].height;/* 1200; */ - decbuf_size = vmdecbuf_size[i];/* 0x700000; */ - buf_num = buf_size / decbuf_size; - - if (buf_num > 0) - local_pool_size = 1; - else { - local_pool_size = 0; - pr_debug("need at least one buffer to handle 1920*1080 data.\n"); - } - - for (i = 0; i < local_pool_size; i++) { - canvas_config((vdevp->vm_canvas[0] + i), - (unsigned long)(buf_start + i * decbuf_size), - canvas_width * 2, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config((vdevp->vm_canvas[2] + i), - (unsigned long)(buf_start + i * decbuf_size), - canvas_width * 3, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config((vdevp->vm_canvas[4] + i), - (unsigned long)(buf_start + i * decbuf_size / 2), - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config(vdevp->vm_canvas[6] + i, - (unsigned long)(buf_start + - (i + 1)*decbuf_size / 2), - canvas_width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - - canvas_config((vdevp->vm_canvas[8] + i), - (unsigned long)(buf_start + - (i + 1)*decbuf_size / 2), - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config((vdevp->vm_canvas[10] + i), - (unsigned long)(buf_start + - (i + 3)*decbuf_size / 4), - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - vfbuf_use[i] = 0; -#endif - } - -exit: - return 0; - -} - -int start_vm_task(struct vm_device_s *vdevp) -{ - /* init the device. */ - vm_local_init(); - if (!vdevp->task) { - vdevp->task = kthread_create(vm_task, vdevp, vdevp->name); - if (IS_ERR(vdevp->task)) { - pr_err("thread creating error.\n"); - return -1; - } - init_waitqueue_head(&vdevp->frame_ready); - wake_up_process(vdevp->task); - } - vdevp->task_running = 1; - return 0; -} - -int start_simulate_task(void) -{ - if (!simulate_task_fd) { - simulate_task_fd = kthread_create(simulate_task, 0, "vm"); - if (IS_ERR(simulate_task_fd)) { - pr_err("thread creating error.\n"); - return -1; - } - wake_up_process(simulate_task_fd); - } - return 0; -} - - -void stop_vm_task(struct vm_device_s *vdevp) -{ - if (vdevp->task) { - vdevp->task_running = 0; - send_sig(SIGTERM, vdevp->task, 1); - complete(&vdevp->vb_start_sema); - wake_up_interruptible(&vdevp->frame_ready); - kthread_stop(vdevp->task); - vdevp->task = NULL; - } - vm_local_init(); -} - - -/* - ********************************************************************** - * - * global status. - * - ********************************************************************** - */ - -static int vm_enable_flag; - -int get_vm_status(void) -{ - return vm_enable_flag; -} - -void set_vm_status(int flag) -{ - if (flag >= 0) - vm_enable_flag = flag; - else - vm_enable_flag = 0; -} - -/* - ********************************************************************** - * - * file op section. - * - ********************************************************************** - */ - -void unset_vm_buf_res(struct vm_init_s *info) -{ - info->buffer_start = 0; -} - -static void vm_cache_this_flush(unsigned int buf_start, unsigned int buf_size, - struct vm_init_s *info) -{ - struct vm_device_s *devp = vm_device[info->vdin_id]; - - if (devp->dev) { - if ((buf_start >= info->buffer_start) && - ((buf_start + buf_size) <= (info->buffer_start + - info->vm_buf_size))) - dma_sync_single_for_cpu(devp->dev, - buf_start, buf_size, DMA_FROM_DEVICE); - } -} - -static int vm_open(struct inode *inode, struct file *file) -{ - struct ge2d_context_s *context = NULL; - - pr_info("open one vm device\n"); - file->private_data = context; - /* vm_device.open_count++; */ - return 0; -} - -static long vm_ioctl(struct file *filp, unsigned int cmd, unsigned long args) -{ - int ret = 0; - struct ge2d_context_s *context; - void __user *argp; - - context = (struct ge2d_context_s *)filp->private_data; - argp = (void __user *)args; - switch (cmd) { - case VM_IOC_2OSD0: - break; - case VM_IOC_ENABLE_PP: - break; - case VM_IOC_CONFIG_FRAME: - break; - default: - return -ENOIOCTLCMD; - } - return ret; -} - -static int vm_release(struct inode *inode, struct file *file) -{ - struct ge2d_context_s *context = - (struct ge2d_context_s *)file->private_data; - - if (context && (destroy_ge2d_work_queue(context) == 0)) { - /* vm_device.open_count--; */ - return 0; - } - pr_info("release one vm device\n"); - return -1; -} - -/* - ********************************************************************** - * - * file op init section. - * - ********************************************************************** - */ - -static const struct file_operations vm_fops = { - .owner = THIS_MODULE, - .open = vm_open, - .unlocked_ioctl = vm_ioctl, - .release = vm_release, -}; - -static ssize_t vm_attr_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ssize_t len = 0; - struct vm_device_s *devp; - - devp = dev_get_drvdata(dev); - if (devp->task_running == 0) { - len += sprintf(buf + len, "vm does not start\n"); - return len; - } - - len += sprintf((char *)buf + len, "vm parameters below\n"); - - return len; -} - -static ssize_t vm_attr_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct vm_device_s *devp; - unsigned int n = 0; - char *buf_orig, *ps, *token; - char *parm[6] = {NULL}; - - if (!buf) - return len; - - buf_orig = kstrdup(buf, GFP_KERNEL); - /* printk(KERN_INFO "input cmd : %s",buf_orig); */ - devp = dev_get_drvdata(dev); - if (devp->task_running == 0) { - len += sprintf((char *)buf + len, "vm does not start\n"); - return len; - } - - ps = buf_orig; - while (1) { - if (n >= ARRAY_SIZE(parm)) { - pr_err("parm array overflow.\n"); -#if 0 - pr_err("n=%d,ARRAY_SIZE(parm)=%d\n", - n, ARRAY_SIZE(parm)); -#endif - return len; - } - token = strsep(&ps, "\n"); - if (token == NULL) - break; - if (*token == '\0') - continue; - parm[n++] = token; - } - - if (strcmp(parm[0], "before") == 0) { - devp->dump = 1; - devp->dump_path = parm[1]; - pr_debug("this not support\n"); - } else if (strcmp(parm[0], "after") == 0) { - devp->dump = 2; - devp->dump_path = parm[1]; - pr_debug("after ge2d processed, store to %s\n", parm[1]); - } - - kfree(buf_orig); - return len; -} - -static DEVICE_ATTR(dump, 0664, vm_attr_show, vm_attr_store); - -static int vm_add_cdev(struct cdev *cdevp, - const struct file_operations *fops, - int minor) -{ - int ret; - dev_t devno = MKDEV(MAJOR(vm_devno), minor); - - cdev_init(cdevp, fops); - cdevp->owner = THIS_MODULE; - ret = cdev_add(cdevp, devno, 1); - return ret; -} - -int init_vm_device(struct vm_device_s *vdevp, struct platform_device *pdev) -{ - int ret = 0; - - ret = vm_add_cdev(&vdevp->cdev, &vm_fops, vdevp->index); - if (ret) { - pr_err("%s: failed to add cdev. !\n", __func__); - goto fail_add_cdev; - } - vdevp->dev = device_create(vm_clsp, &pdev->dev, MKDEV(MAJOR(vm_devno), - vdevp->index), - NULL, "%s%d", VM_DEV_NAME, vdevp->index); - if (IS_ERR(vdevp->dev)) { - pr_err("%s: failed to create device. !\n", __func__); - ret = PTR_ERR(vdevp->dev); - goto fail_create_device; - } - ret = device_create_file(vdevp->dev, &dev_attr_dump); - if (ret < 0) { - pr_err("%s: fail to create vdin attribute files.\n", __func__); - goto fail_create_dev_file; - } - - dev_set_drvdata(vdevp->dev, vdevp); - platform_set_drvdata(pdev, vdevp); - - /* if (vm_buffer_init(vdevp) < 0) */ - /* goto unregister_dev; */ -#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER - vf_provider_init(&vm_vf_prov, PROVIDER_NAME, &vm_vf_provider, NULL); -#endif - /* vf_reg_provider(&vm_vf_prov); */ - vdevp->task = NULL; - vdevp->task_running = 0; - memset(&vdevp->output_para, 0, sizeof(struct vm_output_para)); - sprintf(vdevp->name, "%s%d", RECEIVER_NAME, vdevp->index); - vf_receiver_init(&vdevp->vm_vf_recv, vdevp->name, - &vm_vf_receiver, vdevp); - - vf_reg_receiver(&vdevp->vm_vf_recv); - return 0; - - /* unregister_dev: */ -fail_create_dev_file: - device_destroy(vm_clsp, MKDEV(MAJOR(vm_devno), vdevp->index)); -fail_create_device: - cdev_del(&vdevp->cdev); -fail_add_cdev: - kfree(vdevp); - return ret; - -} - -int uninit_vm_device(struct platform_device *plat_dev) -{ - struct vm_device_s *vdevp; - - vdevp = platform_get_drvdata(plat_dev); - /* stop_vm_task(vdevp); */ - device_remove_file(vdevp->dev, &dev_attr_dump); - device_destroy(vm_clsp, MKDEV(MAJOR(vm_devno), vdevp->index)); - cdev_del(&vdevp->cdev); - vm_device[vdevp->index] = NULL; - - /* free drvdata */ - dev_set_drvdata(vdevp->dev, NULL); - platform_set_drvdata(plat_dev, NULL); - kfree(vdevp); - return 0; -} - -int vm_init_resource(size_t size, struct vm_init_s *info) -{ - struct vm_device_s *devp; -#ifdef CONFIG_CMA - devp = vm_device[info->vdin_id]; - if (size == 0) - return -1; - if (info->vm_pages && info->vm_buf_size != 0) { - - dma_release_from_contiguous(&devp->pdev->dev, - info->vm_pages, - info->vm_buf_size / PAGE_SIZE); - } - info->vm_pages = dma_alloc_from_contiguous(&devp->pdev->dev, - size / PAGE_SIZE, 0); - if (info->vm_pages) { - dma_addr_t phys; - - phys = page_to_phys(info->vm_pages); - info->buffer_start = phys; - info->vm_buf_size = size; - if (info->bt_path_count == 1) { - if (info->vdin_id == 0) - info->isused = true; - else - info->isused = false; - } else { - info->isused = true; - } - info->mem_alloc_succeed = true; - return 0; - } - - info->mem_alloc_succeed = false; - pr_err("CMA failed to allocate dma buffer\n"); - return -ENOMEM; -#else - if (size == 0) - return -1; - info->buffer_start = vm_device[info->vdin_id]->buffer_start; - info->vm_buf_size = vm_device[info->vdin_id]->buffer_size; - info->mem_alloc_succeed = true; - info->isused = true; - return 0; -#endif -} -EXPORT_SYMBOL(vm_init_resource); - -void vm_deinit_resource(struct vm_init_s *info) -{ -#ifdef CONFIG_CMA - struct vm_device_s *devp; - - devp = vm_device[info->vdin_id]; - if (info->vm_buf_size == 0) { - pr_warn("vm buf size equals 0\n"); - return; - } - unset_vm_buf_res(info); - - if (info->vm_pages) { - dma_release_from_contiguous(&devp->pdev->dev, - info->vm_pages, - info->vm_buf_size / PAGE_SIZE); - info->vm_buf_size = 0; - info->vm_pages = NULL; - info->isused = false; - info->mem_alloc_succeed = false; - } -#else - if (info->vm_buf_size) { - info->buffer_start = 0; - info->vm_buf_size = 0; - info->isused = false; - info->mem_alloc_succeed = false; - } -#endif -} -EXPORT_SYMBOL(vm_deinit_resource); - - -/******************************************************************* - * - * interface for Linux driver - * - * ******************************************************************/ - -static int vm_mem_device_init(struct reserved_mem *rmem, struct device *dev) -{ - struct platform_device *pdev = container_of(dev, - struct platform_device, dev); - struct vm_device_s *vdevp = platform_get_drvdata(pdev); - unsigned long mem_start, mem_end; - - vdevp->buffer_start = rmem->base; - vdevp->buffer_size = rmem->size; - mem_start = rmem->base; - mem_end = rmem->base + rmem->size - 1; - pr_info("init vm memsource %lx->%lx\n", mem_start, mem_end); - return 0; -} - -static const struct reserved_mem_ops rmem_vm_ops = { - .device_init = vm_mem_device_init, -}; - -static int __init vm_mem_setup(struct reserved_mem *rmem) -{ - rmem->ops = &rmem_vm_ops; - pr_info("vm share mem setup\n"); - return 0; -} - -/* MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0xff, LOG_LEVEL_DESC, LOG_MASK_DESC); */ - - -/* for driver. */ -static int vm_driver_probe(struct platform_device *pdev) -{ - int idx; - int ret; - struct vm_device_s *vdevp; - - pr_info("vm memory init\n"); - /* malloc vdev */ - vdevp = kmalloc(sizeof(struct vm_device_s), GFP_KERNEL); - if (!vdevp) - return -ENOMEM; - - memset(vdevp, 0, sizeof(struct vm_device_s)); - - if (pdev->dev.of_node) { - ret = of_property_read_u32(pdev->dev.of_node, - "vm_id", &(vdevp->index)); - if (ret) - pr_err("don't find vm id.\n"); - } - vm_device[vdevp->index] = vdevp; - vdevp->pdev = pdev; - - vm_buffer_init(vdevp); - ret = init_vm_device(vdevp, pdev); - if (ret != 0) - return ret; - idx = of_reserved_mem_device_init(&pdev->dev); - if (idx == 0) - pr_info("vm probe done\n"); - else - pr_info("malloc reserved memory failed !\n"); - - /* init_vm_device(vdevp, pdev); */ - return 0; -} - -static int vm_drv_remove(struct platform_device *plat_dev) -{ - int i; - - for (i = 0; i < MAX_CANVAS_INDEX; i++) { - if ((vm_device[0] != NULL) && - (vm_device[0]->vm_canvas[i] >= 0)) { - canvas_pool_map_free_canvas( - vm_device[0]->vm_canvas[i]); - memset(&(vm_device[0]->vm_canvas[i]), - -1, sizeof(int)); - } - if ((vm_device[1] != NULL) && - (vm_device[1]->vm_canvas[i] >= 0)) { - canvas_pool_map_free_canvas( - vm_device[1]->vm_canvas[i]); - memset(&(vm_device[1]->vm_canvas[i]), - -1, sizeof(int)); - } - } - - uninit_vm_device(plat_dev); - return 0; -} - -static const struct of_device_id amlogic_vm_dt_match[] = { - { - .compatible = "amlogic, vm", - }, - {}, -}; - -/* general interface for a linux driver .*/ -static struct platform_driver vm_drv = { - .probe = vm_driver_probe, - .remove = vm_drv_remove, - .driver = { - .name = "vm", - .owner = THIS_MODULE, - .of_match_table = amlogic_vm_dt_match, - } -}; - -static int __init -vm_init_module(void) -{ - int ret = 0; - - pr_info("vm_init .\n"); - ret = alloc_chrdev_region(&vm_devno, 0, VM_MAX_DEVS, VM_DEV_NAME); - if (ret < 0) { - pr_err("%s: failed to allocate major number\n", __func__); - goto fail_alloc_cdev_region; - } - vm_clsp = class_create(THIS_MODULE, VM_CLS_NAME); - if (IS_ERR(vm_clsp)) { - ret = PTR_ERR(vm_clsp); - pr_err("%s: failed to create class\n", __func__); - goto fail_class_create; - } - ret = platform_driver_register(&vm_drv); - if (ret) { - pr_err("Failed to register vm driver (error=%d\n", - ret); - goto fail_pdrv_register; - } - return 0; - -fail_pdrv_register: - class_destroy(vm_clsp); -fail_class_create: - unregister_chrdev_region(vm_devno, VM_MAX_DEVS); -fail_alloc_cdev_region: - return ret; -} - -static void __exit -vm_remove_module(void) -{ - /* class_remove_file(vm_clsp, &class_attr_dump); */ - class_destroy(vm_clsp); - unregister_chrdev_region(vm_devno, VM_MAX_DEVS); - platform_driver_unregister(&vm_drv); - pr_info("vm module removed.\n"); -} - -module_init(vm_init_module); -module_exit(vm_remove_module); -RESERVEDMEM_OF_DECLARE(vm, "amlogic, vm_memory", vm_mem_setup); - -MODULE_DESCRIPTION("Amlogic Video Input Manager"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Simon Zheng "); diff --git a/drivers/amlogic/media/camera/common/vm.h b/drivers/amlogic/media/camera/common/vm.h deleted file mode 100644 index 4ae2bdd01983..000000000000 --- a/drivers/amlogic/media/camera/common/vm.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/vm.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _VM_INCLUDE__ -#define _VM_INCLUDE__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/************************************* - ** - ** macro define - ** - *************************************/ - -#define VM_IOC_MAGIC 'P' -#define VM_IOC_2OSD0 _IOW(VM_IOC_MAGIC, 0x00, unsigned int) -#define VM_IOC_ENABLE_PP _IOW(VM_IOC_MAGIC, 0X01, unsigned int) -#define VM_IOC_CONFIG_FRAME _IOW(VM_IOC_MAGIC, 0X02, unsigned int) -#define MAX_CANVAS_INDEX 12 - -struct vm_device_s { - unsigned int index; - char name[20]; - struct platform_device *pdev; - int dump; - char *dump_path; - unsigned int open_count; - int major; - unsigned int dbg_enable; - /* struct class *cla; */ - struct cdev cdev; - struct device *dev; - resource_size_t buffer_start; - unsigned int buffer_size; -#ifdef CONFIG_CMA - ulong cma_pool_size; -#endif - struct vframe_receiver_s vm_vf_recv; - struct task_struct *task; - wait_queue_head_t frame_ready; - int task_running; - int vm_skip_count; - int test_zoom; - struct vm_output_para output_para; - struct completion vb_start_sema; - struct completion vb_done_sema; - int vm_canvas[MAX_CANVAS_INDEX]; -}; - -struct display_frame_s { - int frame_top; - int frame_left; - int frame_width; - int frame_height; - int content_top; - int content_left; - int content_width; - int content_height; -}; - -int start_vm_task(struct vm_device_s *vdevp); -int start_simulate_task(void); - -extern int get_vm_status(void); -extern void set_vm_status(int flag); - -/* for vm device op. */ -extern int init_vm_device(struct vm_device_s *vdevp, - struct platform_device *pdev); -extern int uninit_vm_device(struct platform_device *plat_dev); - -/* for vm device class op. */ -extern struct class *init_vm_cls(void); - -/* for thread of vm. */ -extern int start_vpp_task(void); -extern void stop_vpp_task(void); - -/* for vm private member. */ -extern void set_vm_buf_info(resource_size_t start, unsigned int size); -extern void get_vm_buf_info(resource_size_t *start, unsigned int *size, - struct io_mapping **mapping); - -/* vm buffer op. */ -extern int vm_buffer_init(struct vm_device_s *vdevp); -extern void vm_local_init(void); - -extern void vm_deinit_resource(struct vm_init_s *info); - -static DEFINE_MUTEX(vm_mutex); - -/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TV */ -#if 1 -#define CANVAS_WIDTH_ALIGN 32 -#else -#define CANVAS_WIDTH_ALIGN 8 -#endif - -#define MAGIC_SG_MEM 0x17890714 -#define MAGIC_DC_MEM 0x0733ac61 -#define MAGIC_VMAL_MEM 0x18221223 -#define MAGIC_RE_MEM 0x123039dc - -#endif /* _VM_INCLUDE__ */ diff --git a/drivers/amlogic/media/camera/common/vm_log.h b/drivers/amlogic/media/camera/common/vm_log.h deleted file mode 100644 index 4733cad79af5..000000000000 --- a/drivers/amlogic/media/camera/common/vm_log.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/vm_log.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VM_LOG_H -#define VM_LOG_H - -#define DEBUG -#ifdef DEBUG -#define AMLOG 1 -#define LOG_LEVEL_VAR amlog_level_ppmgr -#define LOG_MASK_VAR amlog_mask_ppmgr -#endif - -#define LOG_LEVEL_HIGH 0x00f -#define LOG_LEVEL_1 0x001 -#define LOG_LEVEL_LOW 0x000 - -#define LOG_LEVEL_DESC \ -"[0x00]LOW[0X01]LEVEL1[0xf]HIGH" - -#define LOG_MASK_INIT 0x001 -#define LOG_MASK_IOCTL 0x002 -#define LOG_MASK_HARDWARE 0x004 -#define LOG_MASK_CONFIG 0x008 -#define LOG_MASK_WORK 0x010 -#define LOG_MASK_DESC \ -"[0x01]:INIT,[0x02]:IOCTL,[0x04]:HARDWARE,[0x08]LOG_MASK_CONFIG[0x10]LOG_MASK_WORK" - -#endif - diff --git a/drivers/amlogic/media/camera/common/vmcls.h b/drivers/amlogic/media/camera/common/vmcls.h deleted file mode 100644 index 3e81c379225a..000000000000 --- a/drivers/amlogic/media/camera/common/vmcls.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * drivers/amlogic/media/camera/common/vmcls.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#define VM_CLASS_NAME "vm" - -extern void interleave_uv(unsigned char *pU, unsigned char *pV, - unsigned char *pUV, unsigned int size_u_or_v); - -static ssize_t show_vm_info(struct class *cla, struct class_attribute *attr, - char *buf) -{ -#if 0 - resource_size_t bstart; - unsigned int bsize; - - get_vm_buf_info(&bstart, &bsize, NULL); - return snprintf(buf, 80, "buffer:\n start:%x.\tsize:%d\n", - (unsigned int)bstart, bsize / (1024 * 1024)); -#endif - return 0; -} - -static char attr_dat0[3] = "-1"; -static ssize_t read_attr0(struct class *cla, struct class_attribute *attr, - char *buf) -{ - return snprintf(buf, 3, "%s", attr_dat0); -} - -static ssize_t write_attr0(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - /* struct display_device *dsp = dev_get_drvdata(dev); */ - ssize_t ret = -EINVAL; - - if (count <= 2) { - int i = 0; - - if (buf[0] == '-') { - attr_dat0[0] = '-'; - i = 1; - ret++; - } - if ((buf[i] >= '0') && (buf[i] <= '9')) { - attr_dat0[i] = buf[i]; - attr_dat0[i + 1] = '\0'; - ret++; - } else { - attr_dat0[0] = '-'; - attr_dat0[1] = '1'; /* default -1; */ - ret = -EINVAL; - } - } - - return ret; -} - -static char attr_dat1[3] = "-1"; -static ssize_t read_attr1(struct class *cla, struct class_attribute *attr, - char *buf) -{ - return snprintf(buf, 3, "%s", attr_dat1); -} - -static ssize_t write_attr1(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - /* struct display_device *dsp = dev_get_drvdata(dev); */ - ssize_t ret = -EINVAL; - - if (count <= 2) { - int i = 0; - - if (buf[0] == '-') { - attr_dat1[0] = '-'; - i = 1; - ret++; - } - if ((buf[i] >= '0') && (buf[i] <= '9')) { - attr_dat1[i] = buf[i]; - attr_dat1[i + 1] = '\0'; - ret++; - } else { - attr_dat1[0] = '-'; - attr_dat1[1] = '1'; /* default -1; */ - ret = -EINVAL; - } - } - - return ret; -} -int disable_gt2005; - -static ssize_t read_attr2(struct class *cla, struct class_attribute *attr, - char *buf) -{ - return disable_gt2005; -} - -static ssize_t write_attr2(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - /* struct display_device *dsp = dev_get_drvdata(dev); */ - ssize_t ret = -EINVAL; - - if (count <= 2) - disable_gt2005 = buf[0]; - - return ret; -} - -int camera_mirror_flag; /* 0: disable, 1: l&r mirror,2 t-b mirror */ - -static ssize_t mirror_read(struct class *cla, struct class_attribute *attr, - char *buf) -{ - if (camera_mirror_flag == 1) - return snprintf(buf, 80, - "currnet mirror mode is l-r mirror mode. value is: %d.\n", - camera_mirror_flag); - else if (camera_mirror_flag == 2) - return snprintf(buf, 80, - "currnet mirror mode is t-b mirror mode. value is: %d.\n", - camera_mirror_flag); - else - return snprintf(buf, 80, - "currnet mirror mode is normal mode. value is: %d.\n", - camera_mirror_flag); -} - -static ssize_t mirror_write(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - ssize_t size; - char *endp = "1"; - - camera_mirror_flag = kstrtoul(buf, 0, (unsigned long *)endp); - size = endp - buf; - return count; -} - -static struct class_attribute vm_class_attrs[] = { - __ATTR(info, 0644, - show_vm_info, NULL), - __ATTR(attr0, 0644, - read_attr0, write_attr0), - __ATTR(attr1, 0644, - read_attr1, write_attr1), - __ATTR(attr2, 0644, - read_attr2, write_attr2), - __ATTR(mirror, 0644, - mirror_read, mirror_write), - __ATTR_NULL -}; - -static struct class vm_class = { - .name = VM_CLASS_NAME, - .class_attrs = vm_class_attrs, - }; - -struct class *init_vm_cls() - { - int ret = 0; - - ret = class_register(&vm_class); - if (ret < 0) { - pr_err("error create vm class\n"); - return NULL; - } - return &vm_class; - } diff --git a/drivers/amlogic/media/camera/gc2145.c b/drivers/amlogic/media/camera/gc2145.c deleted file mode 100644 index 66769880468e..000000000000 --- a/drivers/amlogic/media/camera/gc2145.c +++ /dev/null @@ -1,3454 +0,0 @@ -/* - * drivers/amlogic/media/camera/gc2145.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_HAS_WAKELOCK -#include -#endif -#include -#include -#include -#include -#include -#include "common/plat_ctrl.h" -#include -#include -#include -#include "common/vm.h" - -#define GC2145_CAMERA_MODULE_NAME "gc2145" - -/* Wake up at about 30 fps */ -#define WAKE_NUMERATOR 30 -#define WAKE_DENOMINATOR 1001 -#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ - -#define MAGIC_RE_MEM 0x123039dc -#define CAMERA_USER_CANVAS_INDEX 0x4e - -#define GC2145_CAMERA_MAJOR_VERSION 0 -#define GC2145_CAMERA_MINOR_VERSION 7 -#define GC2145_CAMERA_RELEASE 0 -#define GC2145_CAMERA_VERSION \ - KERNEL_VERSION(GC2145_CAMERA_MAJOR_VERSION, \ - GC2145_CAMERA_MINOR_VERSION, \ - GC2145_CAMERA_RELEASE) - -#define GC2145_DRIVER_VERSION "GC2145-COMMON-01-140722" - -/*unsigned short DGain_shutter,AGain_shutter,*/ -/*DGain_shutterH,DGain_shutterL,AGain_shutterH,*/ -/*AGain_shutterL,shutterH,shutterL,shutter;*/ -/*unsigned short UXGA_Cap = 0;*/ - -static struct i2c_client *g_i2c_client; -static u32 cur_reg; -static u8 cur_val; -static u8 is_first_time_open; - -enum DCAMERA_FLICKER { - - DCAMERA_FLICKER_50HZ = 0, - - DCAMERA_FLICKER_60HZ, - - FLICKER_MAX - -}; - -/*static unsigned short Antiflicker = DCAMERA_FLICKER_50HZ;*/ - -#define GC2145_NORMAL_Y0ffset 0x08 -#define GC2145_LOWLIGHT_Y0ffset 0x20 - -MODULE_DESCRIPTION("gc2145 On Board"); -MODULE_AUTHOR("amlogic-sh"); -MODULE_LICENSE("GPL v2"); - -static unsigned int video_nr = -1; /* videoX start number, -1 is autodetect. */ - -static unsigned int debug; -/* module_param(debug, uint, 0644); */ -/* MODULE_PARM_DESC(debug, "activates debug info"); */ - -static unsigned int vid_limit = 16; -/* module_param(vid_limit, uint, 0644); */ -/* MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); */ - -//static int vidio_set_fmt_ticks; - -static int GC2145_h_active = 640; /* 800; */ -static int GC2145_v_active = 480; /* 600; */ - -static int gc2145_have_open; - -static struct v4l2_fract gc2145_frmintervals_active = { - .numerator = 1, - .denominator = 15, -}; - -static int gc2145_night_or_normal; /* add by sp_yjp,20120905 */ -static struct vdin_v4l2_ops_s *vops; -/* supported controls */ -static struct v4l2_queryctrl gc2145_qctrl[] = { - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_MENU, - .name = "white balance", - .minimum = CAM_WB_AUTO, - .maximum = CAM_WB_FLUORESCENT, - .step = 0x1, - .default_value = CAM_WB_AUTO, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0, - .maximum = 8, - .step = 0x1, - .default_value = 4, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_COLORFX, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "effect", - .minimum = 0, - .maximum = 6, - .step = 0x1, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .type = V4L2_CTRL_TYPE_MENU, - .name = "banding", - .minimum = CAM_BANDING_50HZ, - .maximum = CAM_BANDING_60HZ, - .step = 0x1, - .default_value = CAM_BANDING_50HZ, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "scene mode", - .minimum = 0, - .maximum = 1, - .step = 0x1, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "flip on horizontal", - .minimum = 0, - .maximum = 1, - .step = 0x1, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "flip on vertical", - .minimum = 0, - .maximum = 1, - .step = 0x1, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_ZOOM_ABSOLUTE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Zoom, Absolute", - .minimum = 100, - .maximum = 300, - .step = 20, - .default_value = 100, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_ROTATE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Rotate", - .minimum = 0, - .maximum = 270, - .step = 90, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER, - } -}; -struct v4l2_querymenu gc2145_qmenu_wbmode[] = { - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .index = CAM_WB_AUTO, - .name = "auto", - .reserved = 0, - }, { - .id = V4L2_CID_DO_WHITE_BALANCE, - .index = CAM_WB_CLOUD, - .name = "cloudy-daylight", - .reserved = 0, - }, { - .id = V4L2_CID_DO_WHITE_BALANCE, - .index = CAM_WB_INCANDESCENCE, - .name = "incandescent", - .reserved = 0, - }, { - .id = V4L2_CID_DO_WHITE_BALANCE, - .index = CAM_WB_DAYLIGHT, - .name = "daylight", - .reserved = 0, - }, { - .id = V4L2_CID_DO_WHITE_BALANCE, - .index = CAM_WB_FLUORESCENT, - .name = "fluorescent", - .reserved = 0, - }, { - .id = V4L2_CID_DO_WHITE_BALANCE, - .index = CAM_WB_WARM_FLUORESCENT, - .name = "warm-fluorescent", - .reserved = 0, - }, -}; - -struct v4l2_querymenu gc2145_qmenu_anti_banding_mode[] = { - { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .index = CAM_BANDING_50HZ, - .name = "50hz", - .reserved = 0, - }, { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .index = CAM_BANDING_60HZ, - .name = "60hz", - .reserved = 0, - }, -}; -static struct v4l2_frmivalenum gc2145_frmivalenum[] = { - { - .index = 0, - .pixel_format = V4L2_PIX_FMT_NV21, - .width = 352, - .height = 288, - .type = V4L2_FRMIVAL_TYPE_DISCRETE, - { - .discrete = { - .numerator = 1, - .denominator = 30,/* 15 */ - } - } - }, { - .index = 0, - .pixel_format = V4L2_PIX_FMT_NV21, - .width = 640, - .height = 480, - .type = V4L2_FRMIVAL_TYPE_DISCRETE, - { - .discrete = { - .numerator = 1, - .denominator = 30,/* 15 */ - } - } - }, { - .index = 1, - .pixel_format = V4L2_PIX_FMT_NV21, - .width = 1600, - .height = 1200, - .type = V4L2_FRMIVAL_TYPE_DISCRETE, - { - .discrete = { - .numerator = 1, - .denominator = 5, - } - } - }, -}; - - -struct gc2145_qmenu_set_s { - __u32 id; - int num; - struct v4l2_querymenu *gc2145_qmenu; -}; - -struct gc2145_qmenu_set_s gc2145_qmenu_set[] = { - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .num = ARRAY_SIZE(gc2145_qmenu_wbmode), - .gc2145_qmenu = gc2145_qmenu_wbmode, - }, { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .num = ARRAY_SIZE(gc2145_qmenu_anti_banding_mode), - .gc2145_qmenu = gc2145_qmenu_anti_banding_mode, - }, -}; - -static int vidioc_querymenu(struct file *file, void *priv, - struct v4l2_querymenu *a) -{ - int i, j; - - for (i = 0; i < ARRAY_SIZE(gc2145_qmenu_set); i++) { - if (a->id && a->id == gc2145_qmenu_set[i].id) { - for (j = 0; j < gc2145_qmenu_set[i].num; j++) { - if (a->index == - gc2145_qmenu_set[i].gc2145_qmenu[j].index) { - memcpy(a, - &(gc2145_qmenu_set[i].gc2145_qmenu[j]), - sizeof(*a)); - return 0; - } - } - } - } - return -EINVAL; -} - -#define dprintk(dev, level, fmt, arg...) \ - v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) - -/* - * ------------------------------------------------------------------ - * Basic structures - * ------------------------------------------------------------------ - */ - -struct gc2145_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; -}; - -static struct gc2145_fmt formats[] = { - { - .name = "RGB565 (BE)", - .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ - .depth = 16, - }, { - .name = "RGB888 (24)", - .fourcc = V4L2_PIX_FMT_RGB24, /* 24 RGB-8-8-8 */ - .depth = 24, - }, { - .name = "BGR888 (24)", - .fourcc = V4L2_PIX_FMT_BGR24, /* 24 BGR-8-8-8 */ - .depth = 24, - }, { - .name = "12 Y/CbCr 4:2:0", - .fourcc = V4L2_PIX_FMT_NV12, - .depth = 12, - }, { - .name = "12 Y/CbCr 4:2:0", - .fourcc = V4L2_PIX_FMT_NV21, - .depth = 12, - }, { - .name = "YUV420P", - .fourcc = V4L2_PIX_FMT_YUV420, - .depth = 12, - }, { - .name = "YVU420P", - .fourcc = V4L2_PIX_FMT_YVU420, - .depth = 12, - } -}; - -static struct gc2145_fmt *get_format(struct v4l2_format *f) -{ - struct gc2145_fmt *fmt; - unsigned int k; - - for (k = 0; k < ARRAY_SIZE(formats); k++) { - fmt = &formats[k]; - if (fmt->fourcc == f->fmt.pix.pixelformat) - break; - } - - if (k == ARRAY_SIZE(formats)) - return NULL; - - return &formats[k]; -} - -struct sg_to_addr { - int pos; - struct scatterlist *sg; -}; - -/* buffer for one video frame */ -struct gc2145_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct gc2145_fmt *fmt; - - unsigned int canvas_id; -}; - -struct gc2145_dmaqueue { - struct list_head active; - - /* thread for generating video stream*/ - struct task_struct *kthread; - wait_queue_head_t wq; - /* Counters to control fps rate */ - int frame; - int ini_jiffies; -}; - -static LIST_HEAD(gc2145_devicelist); - -struct gc2145_device { - struct list_head gc2145_devicelist; - struct v4l2_subdev sd; - struct v4l2_device v4l2_dev; - - spinlock_t slock; - struct mutex mutex; - - int users; - - /* various device info */ - struct video_device *vdev; - - struct gc2145_dmaqueue vidq; - - /* Several counters */ - unsigned long jiffies; - - /* Input Number */ - int input; - - /* platform device data from board initting. */ - struct aml_cam_info_s cam_info; - -#ifdef CONFIG_HAS_WAKELOCK - /* wake lock */ - struct wake_lock wake_lock; -#endif - - /* Control 'registers' */ - int qctl_regs[ARRAY_SIZE(gc2145_qctrl)]; - struct vm_init_s vminfo; -}; - -static inline struct gc2145_device *to_dev(struct v4l2_subdev *sd) -{ - return container_of(sd, struct gc2145_device, sd); -} - -struct gc2145_fh { - struct gc2145_device *dev; - - /* video capture */ - struct gc2145_fmt *fmt; - unsigned int width, height; - struct videobuf_queue vb_vidq; - - struct videobuf_res_privdata res; - enum v4l2_buf_type type; - int input; /* Input Number on bars */ - int stream_on; - unsigned int f_flags; -}; - -/* - *static inline struct gc2145_fh *to_fh(struct gc2145_device *dev) - *{ - * return container_of(dev, struct gc2145_fh, dev); - *} - */ - -static struct v4l2_frmsize_discrete - gc2145_prev_resolution[] = { - /* should include 352x288 and 640x480,*/ - /*those two size are used for recording*/ - {352, 288}, - {640, 480}, -}; - -static struct v4l2_frmsize_discrete gc2145_pic_resolution[] = { - {1600, 1200}, - {800, 600} -}; - -#ifndef GC2145_MIRROR -#define GC2145_MIRROR 0 -#endif -#ifndef GC2145_FLIP -#define GC2145_FLIP 0 -#endif - -/* - *------------------------------------------------------------------ - * reg spec of GC2145 - * ------------------------------------------------------------------ - */ - -struct aml_camera_i2c_fig_s GC2145_script[] = { - /*SENSORDB("GC2145_Sensor_Init"}*/ - {0xfe, 0xf0}, - {0xfe, 0xf0}, - {0xfe, 0xf0}, - {0xfc, 0x06}, - {0xf6, 0x00}, - {0xf7, 0x1d}, - {0xf8, 0x84}, - {0xfa, 0x00}, - {0xf9, 0xfe}, - {0xf2, 0x00}, - /*ISP reg*/ - {0xfe, 0x00}, - {0x03, 0x04}, - {0x04, 0xe2}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x04}, - {0x0e, 0xc0}, - {0x0f, 0x06}, - {0x10, 0x52}, - {0x12, 0x2e}, - {0x17, 0x14}, /*mirror*/ - {0x18, 0x22}, - {0x19, 0x0e}, - {0x1a, 0x01}, - {0x1b, 0x4b}, - {0x1c, 0x07}, - {0x1d, 0x10}, - {0x1e, 0x88}, - {0x1f, 0x78}, - {0x20, 0x03}, - {0x21, 0x40}, - {0x22, 0xa0}, - {0x24, 0x16}, - {0x25, 0x01}, - {0x26, 0x10}, - {0x2d, 0x60}, - {0x30, 0x01}, - {0x31, 0x90}, - {0x33, 0x06}, - {0x34, 0x01}, - /*ISP reg*/ - {0xfe, 0x00}, - {0x80, 0x7f}, - {0x81, 0x26}, - {0x82, 0xfa}, - {0x83, 0x00}, - {0x84, 0x02}, - {0x86, 0x01},/*0x03*/ - {0x88, 0x03}, - {0x89, 0x03}, - {0x85, 0x08}, - {0x8a, 0x00}, - {0x8b, 0x00}, - {0xb0, 0x55}, - {0xc3, 0x00}, - {0xc4, 0x80}, - {0xc5, 0x90}, - {0xc6, 0x3b}, - {0xc7, 0x46}, - {0xec, 0x06}, - {0xed, 0x04}, - {0xee, 0x60}, - {0xef, 0x90}, - {0xb6, 0x01}, - {0x90, 0x01}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x04}, - {0x96, 0xb0}, - {0x97, 0x06}, - {0x98, 0x40}, - /*BLK*/ - {0xfe, 0x00}, - {0x40, 0x42}, - {0x41, 0x00}, - {0x43, 0x5b}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x20}, - {0x67, 0x20}, - {0x68, 0x20}, - {0x69, 0x20}, - {0x76, 0x00}, - {0x6a, 0x08}, - {0x6b, 0x08}, - {0x6c, 0x08}, - {0x6d, 0x08}, - {0x6e, 0x08}, - {0x6f, 0x08}, - {0x70, 0x08}, - {0x71, 0x08}, - {0x76, 0x00}, - {0x72, 0xf0}, - {0x7e, 0x3c}, - {0x7f, 0x00}, - {0xfe, 0x02}, - {0x48, 0x15}, - {0x49, 0x00}, - {0x4b, 0x0b}, - {0xfe, 0x00}, - /*AEC*/ - {0xfe, 0x01}, - {0x01, 0x04}, - {0x02, 0xc0}, - {0x03, 0x04}, - {0x04, 0x90}, - {0x05, 0x30}, - {0x06, 0x90}, - {0x07, 0x30}, - {0x08, 0x80}, - {0x09, 0x00}, - {0x0a, 0x82}, - {0x0b, 0x11}, - {0x0c, 0x10}, - {0x11, 0x10}, - {0x13, 0x7b}, - {0x17, 0x00}, - {0x1c, 0x11}, - {0x1e, 0x61}, - {0x1f, 0x35}, - {0x20, 0x40}, - {0x22, 0x40}, - {0x23, 0x20}, - {0xfe, 0x02}, - {0x0f, 0x04}, - {0xfe, 0x01}, - {0x12, 0x35}, - {0x15, 0xb0}, - {0x10, 0x31}, - {0x3e, 0x28}, - {0x3f, 0xb0}, - {0x40, 0x90}, - {0x41, 0x0f}, - /*INTPEE*/ - {0xfe, 0x02}, - {0x90, 0x6c}, - {0x91, 0x03}, - {0x92, 0xcb}, - {0x94, 0x33}, - {0x95, 0x84}, - {0x97, 0x65}, - {0xa2, 0x11}, - {0xfe, 0x00}, - /*DNDD*/ - {0xfe, 0x02}, - {0x80, 0xc1}, - {0x81, 0x08}, - {0x82, 0x05}, - {0x83, 0x08}, - {0x84, 0x0a}, - {0x86, 0xf0}, - {0x87, 0x50}, - {0x88, 0x15}, - {0x89, 0xb0}, - {0x8a, 0x30}, - {0x8b, 0x10}, - /*ASDE*/ - {0xfe, 0x01}, - {0x21, 0x04}, - {0xfe, 0x02}, - {0xa3, 0x50}, - {0xa4, 0x20}, - {0xa5, 0x40}, - {0xa6, 0x80}, - {0xab, 0x40}, - {0xae, 0x0c}, - {0xb3, 0x46}, - {0xb4, 0x64}, - {0xb6, 0x38}, - {0xb7, 0x01}, - {0xb9, 0x2b}, - {0x3c, 0x04}, - {0x3d, 0x15}, - {0x4b, 0x06}, - {0x4c, 0x20}, - {0xfe, 0x00}, - - /*gamma1*/ -#if 1 - {0xfe, 0x02}, - {0x10, 0x09}, - {0x11, 0x0d}, - {0x12, 0x13}, - {0x13, 0x19}, - {0x14, 0x27}, - {0x15, 0x37}, - {0x16, 0x45}, - {0x17, 0x53}, - {0x18, 0x69}, - {0x19, 0x7d}, - {0x1a, 0x8f}, - {0x1b, 0x9d}, - {0x1c, 0xa9}, - {0x1d, 0xbd}, - {0x1e, 0xcd}, - {0x1f, 0xd9}, - {0x20, 0xe3}, - {0x21, 0xea}, - {0x22, 0xef}, - {0x23, 0xf5}, - {0x24, 0xf9}, - {0x25, 0xff}, -#else - {0xfe, 0x02}, - {0x10, 0x0a}, - {0x11, 0x12}, - {0x12, 0x19}, - {0x13, 0x1f}, - {0x14, 0x2c}, - {0x15, 0x38}, - {0x16, 0x42}, - {0x17, 0x4e}, - {0x18, 0x63}, - {0x19, 0x76}, - {0x1a, 0x87}, - {0x1b, 0x96}, - {0x1c, 0xa2}, - {0x1d, 0xb8}, - {0x1e, 0xcb}, - {0x1f, 0xd8}, - {0x20, 0xe2}, - {0x21, 0xe9}, - {0x22, 0xf0}, - {0x23, 0xf8}, - {0x24, 0xfd}, - {0x25, 0xff}, - {0xfe, 0x00}, -#endif - {0xfe, 0x00}, - {0xc6, 0x20}, - {0xc7, 0x2b}, - /*gamma2*/ -#if 1 - {0xfe, 0x02}, - {0x26, 0x0f}, - {0x27, 0x14}, - {0x28, 0x19}, - {0x29, 0x1e}, - {0x2a, 0x27}, - {0x2b, 0x33}, - {0x2c, 0x3b}, - {0x2d, 0x45}, - {0x2e, 0x59}, - {0x2f, 0x69}, - {0x30, 0x7c}, - {0x31, 0x89}, - {0x32, 0x98}, - {0x33, 0xae}, - {0x34, 0xc0}, - {0x35, 0xcf}, - {0x36, 0xda}, - {0x37, 0xe2}, - {0x38, 0xe9}, - {0x39, 0xf3}, - {0x3a, 0xf9}, - {0x3b, 0xff}, -#else - /*Gamma outdoor*/ - {0xfe, 0x02}, - {0x26, 0x17}, - {0x27, 0x18}, - {0x28, 0x1c}, - {0x29, 0x20}, - {0x2a, 0x28}, - {0x2b, 0x34}, - {0x2c, 0x40}, - {0x2d, 0x49}, - {0x2e, 0x5b}, - {0x2f, 0x6d}, - {0x30, 0x7d}, - {0x31, 0x89}, - {0x32, 0x97}, - {0x33, 0xac}, - {0x34, 0xc0}, - {0x35, 0xcf}, - {0x36, 0xda}, - {0x37, 0xe5}, - {0x38, 0xec}, - {0x39, 0xf8}, - {0x3a, 0xfd}, - {0x3b, 0xff}, -#endif - /*YCP*/ - {0xfe, 0x02}, - {0xd1, 0x32}, - {0xd2, 0x32}, - {0xd3, 0x40}, - {0xd6, 0xf0}, - {0xd7, 0x10}, - {0xd8, 0xda}, - {0xdd, 0x14}, - {0xde, 0x86}, - {0xed, 0x80}, - {0xee, 0x00}, - {0xef, 0x3f}, - {0xd8, 0xd8}, - /*abs*/ - {0xfe, 0x01}, - {0x9f, 0x40}, - /*LSC*/ - {0xfe, 0x01}, - {0xc2, 0x14}, - {0xc3, 0x0d}, - {0xc4, 0x0c}, - {0xc8, 0x15}, - {0xc9, 0x0d}, - {0xca, 0x0a}, - {0xbc, 0x24}, - {0xbd, 0x10}, - {0xbe, 0x0b}, - {0xb6, 0x25}, - {0xb7, 0x16}, - {0xb8, 0x15}, - {0xc5, 0x00}, - {0xc6, 0x00}, - {0xc7, 0x00}, - {0xcb, 0x00}, - {0xcc, 0x00}, - {0xcd, 0x00}, - {0xbf, 0x07}, - {0xc0, 0x00}, - {0xc1, 0x00}, - {0xb9, 0x00}, - {0xba, 0x00}, - {0xbb, 0x00}, - {0xaa, 0x01}, - {0xab, 0x01}, - {0xac, 0x00}, - {0xad, 0x05}, - {0xae, 0x06}, - {0xaf, 0x0e}, - {0xb0, 0x0b}, - {0xb1, 0x07}, - {0xb2, 0x06}, - {0xb3, 0x17}, - {0xb4, 0x0e}, - {0xb5, 0x0e}, - {0xd0, 0x09}, - {0xd1, 0x00}, - {0xd2, 0x00}, - {0xd6, 0x08}, - {0xd7, 0x00}, - {0xd8, 0x00}, - {0xd9, 0x00}, - {0xda, 0x00}, - {0xdb, 0x00}, - {0xd3, 0x0a}, - {0xd4, 0x00}, - {0xd5, 0x00}, - {0xa4, 0x00}, - {0xa5, 0x00}, - {0xa6, 0x77}, - {0xa7, 0x77}, - {0xa8, 0x77}, - {0xa9, 0x77}, - {0xa1, 0x80}, - {0xa2, 0x80}, - {0xfe, 0x01}, - {0xdf, 0x0d}, - {0xdc, 0x25}, - {0xdd, 0x30}, - {0xe0, 0x77}, - {0xe1, 0x80}, - {0xe2, 0x77}, - {0xe3, 0x90}, - {0xe6, 0x90}, - {0xe7, 0xa0}, - {0xe8, 0x90}, - {0xe9, 0xa0}, - {0xfe, 0x00}, - /*AWB*/ - {0xfe, 0x01}, - {0x4f, 0x00}, - {0x4f, 0x00}, - {0x4b, 0x01}, - {0x4f, 0x00}, - {0x4c, 0x01}, /*D75*/ - {0x4d, 0x71}, - {0x4e, 0x01}, - {0x4c, 0x01}, - {0x4d, 0x91}, - {0x4e, 0x01}, - {0x4c, 0x01}, - {0x4d, 0x70}, - {0x4e, 0x01}, - {0x4c, 0x01}, /*D65*/ - {0x4d, 0x90}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0xb0}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0x8f}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0x6f}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0xaf}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0xd0}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0xf0}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0xcf}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0xef}, - {0x4e, 0x02}, - {0x4c, 0x01},/*D50*/ - {0x4d, 0x6e}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8e}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xae}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xce}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x4d}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x6d}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8d}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xad}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xcd}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x4c}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x6c}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8c}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xac}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xcc}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xcb}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x4b}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x6b}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8b}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xab}, - {0x4e, 0x03}, - {0x4c, 0x01},/*CWF*/ - {0x4d, 0x8a}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0xaa}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0xca}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0xca}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0xc9}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0x8a}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0x89}, - {0x4e, 0x04}, - {0x4c, 0x01}, - {0x4d, 0xa9}, - {0x4e, 0x04}, - {0x4c, 0x02},/*tl84*/ - {0x4d, 0x0b}, - {0x4e, 0x05}, - {0x4c, 0x02}, - {0x4d, 0x0a}, - {0x4e, 0x05}, - {0x4c, 0x01}, - {0x4d, 0xeb}, - {0x4e, 0x05}, - {0x4c, 0x01}, - {0x4d, 0xea}, - {0x4e, 0x05}, - {0x4c, 0x02}, - {0x4d, 0x09}, - {0x4e, 0x05}, - {0x4c, 0x02}, - {0x4d, 0x29}, - {0x4e, 0x05}, - {0x4c, 0x02}, - {0x4d, 0x2a}, - {0x4e, 0x05}, - {0x4c, 0x02}, - {0x4d, 0x4a}, - {0x4e, 0x05}, - /*{0x4c , 0x02},*/ - /*{0x4d , 0x6a},*/ - /*{0x4e , 0x06},*/ - {0x4c, 0x02}, - {0x4d, 0x8a}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0x49}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0x69}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0x89}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0xa9}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0x48}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0x68}, - {0x4e, 0x06}, - {0x4c, 0x02}, - {0x4d, 0x69}, - {0x4e, 0x06}, - {0x4c, 0x02},/*H*/ - {0x4d, 0xca}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xc9}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xe9}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x09}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xc8}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xe8}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xa7}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xc7}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xe7}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x07}, - {0x4e, 0x07}, - {0x4f, 0x01}, - {0x50, 0x80}, - {0x51, 0xa8}, - {0x52, 0x47}, - {0x53, 0x38}, - {0x54, 0xc7}, - {0x56, 0x0e}, - {0x58, 0x08}, - {0x5b, 0x00}, - {0x5c, 0x74}, - {0x5d, 0x8b}, - {0x61, 0xdb}, - {0x62, 0xb8}, - {0x63, 0x86}, - {0x64, 0xc0}, - {0x65, 0x04}, - {0x67, 0xa8}, - {0x68, 0xb0}, - {0x69, 0x00}, - {0x6a, 0xa8}, - {0x6b, 0xb0}, - {0x6c, 0xaf}, - {0x6d, 0x8b}, - {0x6e, 0x50}, - {0x6f, 0x18}, - {0x73, 0xf0}, - {0x70, 0x0d}, - {0x71, 0x60}, - {0x72, 0x80}, - {0x74, 0x01}, - {0x75, 0x01}, - {0x7f, 0x0c}, - {0x76, 0x70}, - {0x77, 0x58}, - {0x78, 0xa0}, - {0x79, 0x5e}, - {0x7a, 0x54}, - {0x7b, 0x58}, - {0xfe, 0x00}, - /*CC*/ - {0xfe, 0x02}, - {0xc0, 0x01}, - {0xc1, 0x44}, - {0xc2, 0xfd}, - {0xc3, 0x04}, - {0xc4, 0xF0}, - {0xc5, 0x48}, - {0xc6, 0xfd}, - {0xc7, 0x46}, - {0xc8, 0xfd}, - {0xc9, 0x02}, - {0xca, 0xe0}, - {0xcb, 0x45}, - {0xcc, 0xec}, - {0xcd, 0x48}, - {0xce, 0xf0}, - {0xcf, 0xf0}, - {0xe3, 0x0c}, - {0xe4, 0x4b}, - {0xe5, 0xe0}, - /*ABS*/ - {0xfe, 0x01}, - {0x9f, 0x40}, - {0xfe, 0x00}, - /*OUTPUT*/ - {0xfe, 0x00}, - {0xf2, 0x0f}, - /*dark sun*/ - {0xfe, 0x02}, - {0x40, 0xbf}, - {0x46, 0xcf}, - {0xfe, 0x00}, - /*frame rate 50Hz*/ - {0xfe, 0x00}, - {0x05, 0x01}, - {0x06, 0x56}, - {0x07, 0x00}, - {0x08, 0x32}, - {0xfe, 0x01}, - {0x25, 0x00}, - {0x26, 0xfa}, - {0x27, 0x04}, - {0x28, 0xe2}, /*20fps*/ - {0x29, 0x06}, - {0x2a, 0xd6}, /*14fps*/ - {0x2b, 0x07}, - {0x2c, 0xd0}, /*12fps*/ - {0x2d, 0x0b}, - {0x2e, 0xb8}, /*8fps*/ - {0xfe, 0x00}, - - /*SENSORDB("GC2145_Sensor_SVGA"},*/ - - {0xfe, 0x00}, - {0xfd, 0x01}, - {0xfa, 0x00}, - /*crop window*/ - {0xfe, 0x00}, - {0x90, 0x01}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x02}, - {0x96, 0x58}, - {0x97, 0x03}, - {0x98, 0x20}, - {0x99, 0x11}, - {0x9a, 0x06}, - /*AWB*/ - {0xfe, 0x00}, - {0xec, 0x02}, - {0xed, 0x02}, - {0xee, 0x30}, - {0xef, 0x48}, - {0xfe, 0x02}, - {0x9d, 0x08}, - {0xfe, 0x01}, - {0x74, 0x00}, - /*AEC*/ - {0xfe, 0x01}, - {0x01, 0x04}, - {0x02, 0x60}, - {0x03, 0x02}, - {0x04, 0x48}, - {0x05, 0x18}, - {0x06, 0x50}, - {0x07, 0x10}, - {0x08, 0x38}, - {0x0a, 0x80}, - {0x21, 0x04}, - {0xfe, 0x00}, - {0x20, 0x03}, - {0xfe, 0x00}, - {0xff, 0xff}, -}; - -struct aml_camera_i2c_fig_s gc2145_svga[] = { - {0xfe, 0x00}, - {0xb6, 0x01}, - {0xfd, 0x01}, - {0xfa, 0x11}, - /*crop window*/ - {0xfe, 0x00}, - {0x90, 0x01}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x02}, - {0x96, 0x5a}, - {0x97, 0x03}, - {0x98, 0x22}, - {0x99, 0x11}, - {0x9a, 0x06}, - /*AWB*/ - {0xfe, 0x00}, - {0xec, 0x02}, - {0xed, 0x02}, - {0xee, 0x30}, - {0xef, 0x48}, - {0xfe, 0x02}, - {0x9d, 0x08}, - {0xfe, 0x01}, - {0x74, 0x00}, - /*AEC*/ - {0xfe, 0x01}, - {0x01, 0x04}, - {0x02, 0x60}, - {0x03, 0x02}, - {0x04, 0x48}, - {0x05, 0x18}, - {0x06, 0x50}, - {0x07, 0x10}, - {0x08, 0x38}, - {0x0a, 0x80}, - {0x21, 0x04}, - {0xfe, 0x00}, - {0x20, 0x03}, - {0xfe, 0x00}, - {0xff, 0xff}, -}; - -struct aml_camera_i2c_fig_s gc2145_uxga[] = { - {0xfe, 0x00}, - {0xfd, 0x00}, - {0xfa, 0x11}, - /*crop window*/ - {0xfe, 0x00}, - {0x90, 0x01}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x04}, - {0x96, 0xb2}, - {0x97, 0x06}, - {0x98, 0x42}, - {0x99, 0x11}, - {0x9a, 0x06}, - /*AWB*/ - {0xfe, 0x00}, - {0xec, 0x06}, - {0xed, 0x04}, - {0xee, 0x60}, - {0xef, 0x90}, - {0xfe, 0x01}, - {0x74, 0x01}, - /*AEC*/ - {0xfe, 0x01}, - {0x01, 0x04}, - {0x02, 0xc0}, - {0x03, 0x04}, - {0x04, 0x90}, - {0x05, 0x30}, - {0x06, 0x90}, - {0x07, 0x30}, - {0x08, 0x80}, - {0x0a, 0x82}, - {0xfe, 0x01}, - {0x21, 0x15}, - {0xfe, 0x00}, - {0x20, 0x15}, - {0xfe, 0x00}, - {0xff, 0xff}, -}; - -struct aml_camera_i2c_fig_s gc2145_1280x960[] = { - /*1280X960*/ - {0xfe, 0x00}, - {0xfa, 0x11}, - {0xfd, 0x00}, - {0x1c, 0x05}, - /*crop window*/ - {0xfe, 0x00}, - {0x99, 0x55}, - {0x9a, 0x06}, - {0x9b, 0x00}, - {0x9c, 0x00}, - {0x9d, 0x01}, - {0x9e, 0x23}, - {0x9f, 0x00}, - {0xa0, 0x00}, - {0xa1, 0x01}, - {0xa2, 0x23}, - {0x90, 0x01}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x03}, - {0x96, 0xc0}, - {0x97, 0x05}, - {0x98, 0x00}, - - /*AWB*/ - {0xfe, 0x00}, - {0xec, 0x06}, - {0xed, 0x04}, - {0xee, 0x60}, - {0xef, 0x90}, - {0xfe, 0x01}, - {0x74, 0x01}, - /*AEC*/ - {0xfe, 0x01}, - {0x01, 0x04}, - {0x02, 0xc0}, - {0x03, 0x04}, - {0x04, 0x90}, - {0x05, 0x30}, - {0x06, 0x90}, - {0x07, 0x30}, - {0x08, 0x80}, - {0x0a, 0x82}, - {0x21, 0x15}, - {0xfe, 0x00}, - {0x20, 0x15}, - {0xfe, 0x00}, -}; - -struct aml_camera_i2c_fig_s gc2145_FLICKER_50HZ[] = { - {0xfe, 0x00}, - {0x05, 0x01}, - {0x06, 0x56}, - {0x07, 0x00}, - {0x08, 0x32}, - {0xfe, 0x01}, - {0x25, 0x00}, - {0x26, 0xfa}, - {0x27, 0x04}, - {0x28, 0xe2}, /*20fps*/ - {0x29, 0x06}, - {0x2a, 0xd6}, /*14fps*/ - {0x2b, 0x07}, - {0x2c, 0xd0}, /*12fps*/ - {0x2d, 0x0b}, - {0x2e, 0xb8}, /*8fps*/ - {0xfe, 0x00}, - {0xff, 0xff}, -}; -struct aml_camera_i2c_fig_s gc2145_FLICKER_60HZ[] = { - {0x05, 0x01},/*hb*/ - {0x06, 0x58}, - {0x07, 0x00},/*vb*/ - {0x08, 0x32}, - {0xfe, 0x01}, - {0x25, 0x00},/*step*/ - {0x26, 0xd0}, - {0x27, 0x04},/*level1*/ - {0x28, 0xe0}, - {0x29, 0x06},/*level2*/ - {0x2a, 0x80}, - {0x2b, 0x08},/*level3*/ - {0x2c, 0x20}, - {0x2d, 0x0b},/*level4*/ - {0x2e, 0x60}, - {0xfe, 0x00}, - {0xff, 0xff}, -}; - -/* load GC2145 parameters */ -void GC2145_init_regs(struct gc2145_device *dev) -{ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - int i = 0; - - if (!dev->vminfo.isused) - return; - - while (1) { - if (GC2145_script[i].val == 0xff && - GC2145_script[i].addr == 0xff) { - pr_info("GC2145_write_regs success in initial.\n"); - break; - } - if ((i2c_put_byte_add8_new(client, GC2145_script[i].addr, - GC2145_script[i].val)) < 0) { - pr_err("fail in initial GC2145.\n"); - return; - } - i++; - } -} - -/* - ************************************************************************ - * FUNCTION - * GC2145_set_param_wb - * - * DESCRIPTION - * wb setting. - * - * PARAMETERS - * none - * - * RETURNS - * None - * - * GLOBALS AFFECTED - * - ************************************************************************ - */ - -void GC2145_set_param_wb(struct gc2145_device *dev, - enum camera_wb_flip_e para) /* white balance */ -{ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - unsigned int temp = 0; - - if (!dev->vminfo.isused) - return; - - i2c_put_byte_add8_new(client, 0xfe, 0x00); - temp = i2c_get_byte_add8(client, 0x82); - - switch (para) { - - case CAM_WB_AUTO:/* auto */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0xb3, 0x61); - i2c_put_byte_add8_new(client, 0xb4, 0x40); - i2c_put_byte_add8_new(client, 0xb5, 0x61); - i2c_put_byte_add8_new(client, 0x82, temp|0x2); - break; - - case CAM_WB_CLOUD: /* cloud */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); - i2c_put_byte_add8_new(client, 0xb3, 0x58); - i2c_put_byte_add8_new(client, 0xb4, 0x40); - i2c_put_byte_add8_new(client, 0xb5, 0x50); - break; - - case CAM_WB_DAYLIGHT: /* */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); - i2c_put_byte_add8_new(client, 0xb3, 0x70); - i2c_put_byte_add8_new(client, 0xb4, 0x40); - i2c_put_byte_add8_new(client, 0xb5, 0x50); - break; - - case CAM_WB_INCANDESCENCE: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); - i2c_put_byte_add8_new(client, 0xb3, 0x50); - i2c_put_byte_add8_new(client, 0xb4, 0x40); - i2c_put_byte_add8_new(client, 0xb5, 0xa8); - break; - - case CAM_WB_TUNGSTEN: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); - i2c_put_byte_add8_new(client, 0xb3, 0xa0); - i2c_put_byte_add8_new(client, 0xb4, 0x45); - i2c_put_byte_add8_new(client, 0xb5, 0x40); - break; - - case CAM_WB_FLUORESCENT: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); - i2c_put_byte_add8_new(client, 0xb3, 0x72); - i2c_put_byte_add8_new(client, 0xb4, 0x40); - i2c_put_byte_add8_new(client, 0xb5, 0x5b); - break; - - case CAM_WB_MANUAL: - /* TODO */ - break; - default: - break; - } - - -} /* GC2145_set_param_wb */ - -/* - ************************************************************************ - * FUNCTION - * GC2145_set_param_exposure - * - * DESCRIPTION - * exposure setting. - * - * PARAMETERS - * none - * - * RETURNS - * None - * - * GLOBALS AFFECTED - * - ************************************************************************ - */ - -void GC2145_set_param_exposure(struct gc2145_device *dev, - enum camera_exposure_e para) -{ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - - if (!dev->vminfo.isused) - return; - - switch (para) { - - case EXPOSURE_N4_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x55); /*target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - - - case EXPOSURE_N3_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x60); /*target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - - case EXPOSURE_N2_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x65); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - - case EXPOSURE_N1_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x70); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - case EXPOSURE_0_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x7b); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - case EXPOSURE_P1_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x85); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - case EXPOSURE_P2_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x90); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - case EXPOSURE_P3_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x95); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - case EXPOSURE_P4_STEP: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0xa0); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - - default: - i2c_put_byte_add8_new(client, 0xfe, 0x01); - i2c_put_byte_add8_new(client, 0x13, 0x7b); /* target_y */ - i2c_put_byte_add8_new(client, 0xfe, 0x00); - break; - /* break; */ - - } - -} /* GC2145_set_param_exposure */ - -/* - ************************************************************************ - * FUNCTION - * GC2145_set_param_effect - * - * DESCRIPTION - * effect setting. - * - * PARAMETERS - * none - * - * RETURNS - * None - * - * GLOBALS AFFECTED - * - ************************************************************************ - */ - -void GC2145_set_param_effect(struct gc2145_device *dev, - enum camera_effect_flip_e para) -{ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - - if (!dev->vminfo.isused) - return; - - switch (para) { - case CAM_EFFECT_ENC_NORMAL: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x83, 0xe0); - break; - - case CAM_EFFECT_ENC_GRAYSCALE: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x83, 0x12); - break; - - case CAM_EFFECT_ENC_SEPIA: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x83, 0x82); - break; - - case CAM_EFFECT_ENC_SEPIAGREEN: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x43, 0x52); - break; - - case CAM_EFFECT_ENC_SEPIABLUE: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x43, 0x62); - break; - - case CAM_EFFECT_ENC_COLORINV: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x83, 0x01); - break; - - default: - i2c_put_byte_add8_new(client, 0xfe, 0x00); - i2c_put_byte_add8_new(client, 0x83, 0xe0); - break; - } - -} /* GC2145_set_param_effect */ - -/* - ************************************************************************ - * FUNCTION - * GC2145_NightMode - * - * DESCRIPTION - * This function night mode of GC2145. - * - * PARAMETERS - * none - * - * RETURNS - * None - * - * GLOBALS AFFECTED - * - ************************************************************************ - */ - -void GC2145_set_night_mode(struct gc2145_device *dev, - enum camera_night_mode_flip_e enable) -{ - -} - -void GC2145_set_param_banding(struct gc2145_device *dev, - enum camera_banding_flip_e banding) -{ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - unsigned char buf[4]; - int i = 0; - - switch (banding) { - case CAM_BANDING_50HZ: - while (1) { - buf[0] = gc2145_FLICKER_50HZ[i].addr; - buf[1] = gc2145_FLICKER_50HZ[i].val; - if (gc2145_FLICKER_50HZ[i].val == 0xff && - gc2145_FLICKER_50HZ[i].addr == 0xff) { - pr_err("success in gc2145_FLICKER_50HZ gc2145\n"); - break; - } - if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in gc2145_FLICKER_50HZ gc2145\n"); - return; - } - i++; - } - break; - case CAM_BANDING_60HZ: - while (1) { - buf[0] = gc2145_FLICKER_60HZ[i].addr; - buf[1] = gc2145_FLICKER_60HZ[i].val; - if (gc2145_FLICKER_60HZ[i].val == 0xff && - gc2145_FLICKER_60HZ[i].addr == 0xff) { - pr_err("success in gc2145_FLICKER_60HZ gc2145\n"); - break; - } - if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in gc2145_FLICKER_60HZ gc2145\n"); - return; - } - i++; - } - break; - default: - break; - } - -} - -static int set_flip(struct gc2145_device *dev) -{ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - unsigned char temp; - unsigned char buf[2]; - - if (!dev->vminfo.isused) - return 0; - - i2c_put_byte_add8_new(client, 0xfe, 0x00); - - temp = i2c_get_byte_add8(client, 0x17); - temp &= 0xfc; - temp |= dev->cam_info.m_flip << 0; - temp |= dev->cam_info.v_flip << 1; - buf[0] = 0x17; - buf[1] = temp; - if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in setting sensor orientation\n"); - return -1; - } - - return 0; -} - -void GC2145_set_resolution(struct gc2145_device *dev, int height, int width) -{ - unsigned char buf[4]; - unsigned int value; - unsigned int pid = 0, shutter; - unsigned int i = 0; - static unsigned int shutter_l; - static unsigned int shutter_h; - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - - pr_info("%s :wxh = %d x %d\n", __func__, width, height); - - if (!dev->vminfo.isused) - return; - - if ((width * height < 1600 * 1200)) { - while (1) { - buf[0] = gc2145_svga[i].addr; - buf[1] = gc2145_svga[i].val; - if (gc2145_svga[i].val == 0xff && - gc2145_svga[i].addr == 0xff) { - pr_info("success in gc2145_svga.\n"); - break; - } - if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in gc2145_svga.\n"); - return; - } - i++; - } - gc2145_frmintervals_active.numerator = 1; - gc2145_frmintervals_active.denominator = 15; - GC2145_h_active = 800; - GC2145_v_active = 600; - mdelay(80); - } else if (width * height >= 1200 * 1600) { - buf[0] = 0xfe; - buf[1] = 0x00; - i2c_put_byte_add8(client, buf, 2); - - buf[0] = 0xb6; - buf[1] = 0x00; - i2c_put_byte_add8(client, buf, 2); - - buf[0] = 0x03; - value = i2c_get_byte_add8(client, 0x03); - shutter_l = value; - /*printk(KERN_INFO"set camera 0x03=0x%x\n", value);*/ - pid |= (value << 8); - - buf[0] = 0x04; - value = i2c_get_byte_add8(client, 0x04); - shutter_h = value; - /*printk(KERN_INFO"set camera 0x04=0x%x\n", value);*/ - pid |= (value & 0x1f); - - shutter = pid; - /*printk(KERN_INFO "set camera shutter=0x%x\n", shutter);*/ - - while (1) { - buf[0] = gc2145_uxga[i].addr; - buf[1] = gc2145_uxga[i].val; - if (gc2145_uxga[i].val == 0xff && - gc2145_uxga[i].addr == 0xff) { - pr_info("gc2145_write_regs success in gc2145_uxga.\n"); - break; - } - if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in gc2145_uxga.\n"); - return; - } - i++; - } - - shutter = shutter / 2; - if (shutter < 1) - shutter = 1; - - buf[0] = 0x03; - buf[1] = ((shutter >> 8) & 0xff); - i2c_put_byte_add8(client, buf, 2); - - buf[0] = 0x04; - buf[1] = (shutter & 0x1f); - i2c_put_byte_add8(client, buf, 2); - - gc2145_frmintervals_active.denominator = 5; - gc2145_frmintervals_active.numerator = 1; - GC2145_h_active = 1600; - GC2145_v_active = 1200; - mdelay(130); - } - set_flip(dev); -} /* GC2145_set_resolution */ - -unsigned char v4l_2_gc2145(int val) -{ - int ret = val / 0x20; - - if (ret < 4) - return ret * 0x20 + 0x80; - else if (ret < 8) - return ret * 0x20 + 0x20; - else - return 0; -} - -static int convert_canvas_index(unsigned int v4l2_format, - unsigned int start_canvas) -{ - int canvas = start_canvas; - - switch (v4l2_format) { - case V4L2_PIX_FMT_RGB565X: - case V4L2_PIX_FMT_VYUY: - canvas = start_canvas; - break; - case V4L2_PIX_FMT_YUV444: - case V4L2_PIX_FMT_BGR24: - case V4L2_PIX_FMT_RGB24: - canvas = start_canvas; - break; - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV21: - canvas = start_canvas | ((start_canvas + 1) << 8); - break; - case V4L2_PIX_FMT_YVU420: - case V4L2_PIX_FMT_YUV420: - if (v4l2_format == V4L2_PIX_FMT_YUV420) - canvas = start_canvas | ((start_canvas + 1) << 8) | - ((start_canvas + 2) << 16); - else - canvas = start_canvas | ((start_canvas + 2) << 8) | - ((start_canvas + 1) << 16); - break; - default: - break; - } - return canvas; -} - -static int gc2145_setting(struct gc2145_device *dev, int PROP_ID, int value) -{ - int ret = 0; - /* unsigned char cur_val; */ - struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); - - if (!dev->vminfo.isused) - return 0; - /*here register not finished */ - switch (PROP_ID) { - - case V4L2_CID_BRIGHTNESS: - dprintk(dev, 1, "setting brightned:%d\n", v4l_2_gc2145(value)); - ret = i2c_put_byte_add8_new(client, 0xdc, v4l_2_gc2145(value)); - break; - case V4L2_CID_CONTRAST: - ret = i2c_put_byte_add8_new(client, 0xde, value); - break; - case V4L2_CID_SATURATION: - ret = i2c_put_byte_add8_new(client, 0xd9, value); - break; - case V4L2_CID_DO_WHITE_BALANCE: - if (gc2145_qctrl[0].default_value != value) { - gc2145_qctrl[0].default_value = value; - GC2145_set_param_wb(dev, value); - pr_info("set camera white_balance=%d.\n ", - value); - } - break; - case V4L2_CID_EXPOSURE: - if (gc2145_qctrl[1].default_value != value) { - gc2145_qctrl[1].default_value = value; - GC2145_set_param_exposure(dev, value); - pr_info("set camera exposure=%d.\n", - value); - } - break; - case V4L2_CID_COLORFX: - if (gc2145_qctrl[2].default_value != value) { - gc2145_qctrl[2].default_value = value; - /* GC2145_set_param_effect(dev,value); */ - pr_info("set camera effect=%d.\n", - value); - } - break; - case V4L2_CID_WHITENESS: - if (gc2145_qctrl[3].default_value != value) { - gc2145_qctrl[3].default_value = value; - pr_info("@@@SP_000:GC2145_set_param_banding,value=%d\n", - value); - GC2145_set_param_banding(dev, value); - pr_info("@@@SP_111:gc2145_night_or_normal = %d", - gc2145_night_or_normal); - GC2145_set_night_mode(dev, gc2145_night_or_normal); - pr_info("set camera banding=%d.\n", - value); - } - break; - case V4L2_CID_BLUE_BALANCE: - if (gc2145_qctrl[4].default_value != value) { - gc2145_qctrl[4].default_value = value; - pr_info("@@@SP_222:GC2145_set_night_mode,night mode=%d\n", - value); - pr_info("@@@SP_333:gc2145_night_or_normal = %d", - gc2145_night_or_normal); - GC2145_set_night_mode(dev, value); - pr_info("set camera scene mode=%d.\n", - value); - } - break; - case V4L2_CID_HFLIP: /* set flip on H. */ - value = value & 0x3; - if (gc2145_qctrl[5].default_value != value) { - gc2145_qctrl[5].default_value = value; - pr_info(" set camera h filp =%d.\n ", value); - } - break; - case V4L2_CID_VFLIP: /* set flip on V. */ - break; - case V4L2_CID_ZOOM_ABSOLUTE: - if (gc2145_qctrl[7].default_value != value) - gc2145_qctrl[7].default_value = value; - break; - case V4L2_CID_ROTATE: - if (gc2145_qctrl[8].default_value != value) { - gc2145_qctrl[8].default_value = value; - pr_info(" set camera rotate =%d.\n ", value); - } - break; - default: - ret = -1; - break; - } - return ret; -} - -static void power_down_gc2145(struct gc2145_device *dev) -{ - -} - -/* - *------------------------------------------------------------------ - * DMA and thread functions - * ------------------------------------------------------------------ - */ - -#define TSTAMP_MIN_Y 24 -#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) -#define TSTAMP_INPUT_X 10 -#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) - -static void gc2145_fillbuff(struct gc2145_fh *fh, struct gc2145_buffer *buf) -{ - int ret; - void *vbuf; - struct vm_output_para para = {0}; - struct gc2145_device *dev = fh->dev; - - if (dev->vminfo.mem_alloc_succeed) - vbuf = (void *)videobuf_to_res(&buf->vb); - else - vbuf = videobuf_to_vmalloc(&buf->vb); - dprintk(dev, 1, "%s\n", __func__); - if (!vbuf) - return; - /* 0x18221223 indicate the memory type is MAGIC_VMAL_MEM*/ - if (dev->vminfo.mem_alloc_succeed) { - if (buf->canvas_id == 0) - buf->canvas_id = convert_canvas_index(fh->fmt->fourcc, - CAMERA_USER_CANVAS_INDEX + buf->vb.i * 3); - para.v4l2_memory = MAGIC_RE_MEM; - } else - para.v4l2_memory = MAGIC_VMAL_MEM; - para.mirror = gc2145_qctrl[5].default_value & 3;/* not set */ - para.v4l2_format = fh->fmt->fourcc; - para.zoom = gc2145_qctrl[7].default_value; - para.angle = gc2145_qctrl[8].default_value; - para.vaddr = (uintptr_t)vbuf; - /* para.ext_canvas = buf->canvas_id; */ - para.ext_canvas = 0; - para.width = buf->vb.width; - para.height = buf->vb.height; - dev->vminfo.vdin_id = dev->cam_info.vdin_path; - ret = vm_fill_this_buffer(&buf->vb, ¶, &dev->vminfo); - /*if the vm is not used by sensor ,*/ - /*we let vm_fill_this_buffer() return -2*/ - if (ret == -2) - msleep(40); - buf->vb.state = VIDEOBUF_DONE; -} - -static void gc2145_thread_tick(struct gc2145_fh *fh) -{ - struct gc2145_buffer *buf; - struct gc2145_device *dev = fh->dev; - struct gc2145_dmaqueue *dma_q = &dev->vidq; - - unsigned long flags = 0; - - dprintk(dev, 1, "Thread tick\n"); - if (!fh->stream_on) { - dprintk(dev, 1, "sensor doesn't stream on\n"); - return; - } - spin_lock_irqsave(&dev->slock, flags); - if (list_empty(&dma_q->active)) { - dprintk(dev, 1, "No active queue to serve\n"); - goto unlock; - } - - buf = list_entry(dma_q->active.next, - struct gc2145_buffer, vb.queue); - dprintk(dev, 1, "%s\n", __func__); - dprintk(dev, 1, "list entry get buf is %p\n", buf); - - if (!(fh->f_flags & O_NONBLOCK)) { - /* Nobody is waiting on this buffer, return */ - if (!waitqueue_active(&buf->vb.done)) - goto unlock; - } - buf->vb.state = VIDEOBUF_ACTIVE; - - list_del(&buf->vb.queue); - - do_gettimeofday(&buf->vb.ts); - - /* Fill buffer */ - spin_unlock_irqrestore(&dev->slock, flags); - gc2145_fillbuff(fh, buf); - dprintk(dev, 1, "filled buffer %p\n", buf); - - wake_up(&buf->vb.done); - dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); - return; -unlock: - spin_unlock_irqrestore(&dev->slock, flags); -} - -#define frames_to_ms(frames) \ - ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) - -static void gc2145_sleep(struct gc2145_fh *fh) -{ - struct gc2145_device *dev = fh->dev; - struct gc2145_dmaqueue *dma_q = &dev->vidq; - - DECLARE_WAITQUEUE(wait, current); - - dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__, - (unsigned long)dma_q); - - add_wait_queue(&dma_q->wq, &wait); - if (kthread_should_stop()) - goto stop_task; - - /* Calculate time to wake up */ - /* timeout = msecs_to_jiffies(frames_to_ms(1)); */ - - gc2145_thread_tick(fh); - - schedule_timeout_interruptible(2); - -stop_task: - remove_wait_queue(&dma_q->wq, &wait); - try_to_freeze(); -} - -static int gc2145_thread(void *data) -{ - struct gc2145_fh *fh = data; - struct gc2145_device *dev = fh->dev; - - dprintk(dev, 1, "thread started\n"); - - set_freezable(); - - for (; ;) { - gc2145_sleep(fh); - - if (kthread_should_stop()) - break; - } - dprintk(dev, 1, "thread: exit\n"); - return 0; -} - -static int gc2145_start_thread(struct gc2145_fh *fh) -{ - struct gc2145_device *dev = fh->dev; - struct gc2145_dmaqueue *dma_q = &dev->vidq; - - dma_q->frame = 0; - dma_q->ini_jiffies = jiffies; - - dprintk(dev, 1, "%s\n", __func__); - - dma_q->kthread = kthread_run(gc2145_thread, fh, "gc2145"); - - if (IS_ERR(dma_q->kthread)) { - v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); - return PTR_ERR(dma_q->kthread); - } - /* Wakes thread */ - wake_up_interruptible(&dma_q->wq); - - dprintk(dev, 1, "returning from %s\n", __func__); - return 0; -} - -static void gc2145_stop_thread(struct gc2145_dmaqueue *dma_q) -{ - struct gc2145_device *dev = - container_of(dma_q, struct gc2145_device, vidq); - - dprintk(dev, 1, "%s\n", __func__); - /* shutdown control thread */ - if (dma_q->kthread) { - kthread_stop(dma_q->kthread); - dma_q->kthread = NULL; - } -} - -/* - *------------------------------------------------------------------ - * Videobuf operations - * ------------------------------------------------------------------ - */ - -static int -vmall_buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct gc2145_fh *fh = vq->priv_data; - struct gc2145_device *dev = fh->dev; - /* int bytes = fh->fmt->depth >> 3 ; */ - *size = (fh->width * fh->height * fh->fmt->depth) >> 3; - if (*count == 0) - *count = 32; - - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; - - dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, - *count, *size); - - return 0; -} - -static int -res_buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct videobuf_res_privdata *res = vq->priv_data; - struct gc2145_fh *fh = container_of(res, struct gc2145_fh, res); - struct gc2145_device *dev = fh->dev; - /* int bytes = fh->fmt->depth >> 3 ; */ - int height = fh->height; - - if (height == 1080) - height = 1088; - *size = (fh->width * height * fh->fmt->depth) >> 3; - if (*count == 0) - *count = 32; - - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; - - dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, - *count, *size); - - return 0; -} - -static void free_vmall_buffer(struct videobuf_queue *vq, - struct gc2145_buffer *buf) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - - fh = vq->priv_data; - dev = fh->dev; - - dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); - - videobuf_waiton(vq, &buf->vb, 0, 0); - if (in_interrupt()) - WARN_ON(1); - videobuf_vmalloc_free(&buf->vb); - dprintk(dev, 1, "free_vmall_buffer: freed\n"); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static void free_res_buffer(struct videobuf_queue *vq, - struct gc2145_buffer *buf) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct videobuf_res_privdata *res = vq->priv_data; - - fh = container_of(res, struct gc2145_fh, res); - dev = fh->dev; - - dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); - - videobuf_waiton(vq, &buf->vb, 0, 0); - if (in_interrupt()) - WARN_ON(1); - videobuf_res_free(vq, &buf->vb); - dprintk(dev, 1, "free_res_buffer: freed\n"); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -#define norm_maxw() 1920 -#define norm_maxh() 1600 -static int -vmall_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct gc2145_buffer *buf; - int rc; - - fh = vq->priv_data; - dev = fh->dev; - buf = container_of(vb, struct gc2145_buffer, vb); - /* int bytes = fh->fmt->depth >> 3 ; */ - dprintk(dev, 1, "%s, field=%d\n", __func__, field); - - WARN_ON(fh->fmt == NULL); - - if (fh->width < 48 || fh->width > norm_maxw() || - fh->height < 32 || fh->height > norm_maxh()) - return -EINVAL; - - buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; - if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - /* These properties only change when queue is idle, see s_fmt */ - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - - /* precalculate_bars(fh); */ - - if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - - return 0; - -fail: - free_vmall_buffer(vq, buf); - return rc; -} - -static int -res_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct gc2145_buffer *buf; - int rc; - struct videobuf_res_privdata *res = vq->priv_data; - - fh = container_of(res, struct gc2145_fh, res); - dev = fh->dev; - buf = container_of(vb, struct gc2145_buffer, vb); - dprintk(dev, 1, "%s, field=%d\n", __func__, field); - - WARN_ON(fh->fmt == NULL); - - if (fh->width < 48 || fh->width > norm_maxw() || - fh->height < 32 || fh->height > norm_maxh()) - return -EINVAL; - - buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; - if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - /* These properties only change when queue is idle, see s_fmt */ - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - - /* precalculate_bars(fh); */ - - if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - - return 0; - -fail: - free_res_buffer(vq, buf); - return rc; -} - -static void -res_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct gc2145_dmaqueue *vidq; - struct gc2145_buffer *buf = container_of(vb, struct gc2145_buffer, vb); - struct videobuf_res_privdata *res = vq->priv_data; - - fh = container_of(res, struct gc2145_fh, res); - dev = fh->dev; - vidq = &dev->vidq; - - dprintk(dev, 1, "%s\n", __func__); - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); -} - -static void -vmall_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct gc2145_dmaqueue *vidq; - struct gc2145_buffer *buf = container_of(vb, struct gc2145_buffer, vb); - - fh = vq->priv_data; - dev = fh->dev; - vidq = &dev->vidq; - - dprintk(dev, 1, "%s\n", __func__); - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); -} - -static void res_buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct gc2145_buffer *buf = - container_of(vb, struct gc2145_buffer, vb); - struct videobuf_res_privdata *res = vq->priv_data; - - fh = container_of(res, struct gc2145_fh, res); - dev = (struct gc2145_device *)fh->dev; - - dprintk(dev, 1, "%s\n", __func__); - - free_res_buffer(vq, buf); -} - -static void vmall_buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct gc2145_fh *fh; - struct gc2145_device *dev; - struct gc2145_buffer *buf = - container_of(vb, struct gc2145_buffer, vb); - fh = vq->priv_data; - dev = (struct gc2145_device *)fh->dev; - - dprintk(dev, 1, "%s\n", __func__); - - free_vmall_buffer(vq, buf); -} - -static struct videobuf_queue_ops gc2145_video_vmall_qops = { - .buf_setup = vmall_buffer_setup, - .buf_prepare = vmall_buffer_prepare, - .buf_queue = vmall_buffer_queue, - .buf_release = vmall_buffer_release, -}; - -static struct videobuf_queue_ops gc2145_video_res_qops = { - .buf_setup = res_buffer_setup, - .buf_prepare = res_buffer_prepare, - .buf_queue = res_buffer_queue, - .buf_release = res_buffer_release, -}; - -/* - *------------------------------------------------------------------ - * IOCTL vidioc handling - * ------------------------------------------------------------------ - */ - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - - strcpy(cap->driver, "gc2145"); - strcpy(cap->card, "gc2145.canvas"); - if (dev->cam_info.front_back == 0) - strcat(cap->card, "back"); - else - strcat(cap->card, "front"); - - strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); - cap->version = GC2145_CAMERA_VERSION; - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING - | V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct gc2145_fmt *fmt; - - if (f->index >= ARRAY_SIZE(formats)) - return -EINVAL; - - fmt = &formats[f->index]; - - strlcpy(f->description, fmt->name, sizeof(f->description)); - f->pixelformat = fmt->fourcc; - return 0; -} -static int vidioc_enum_frameintervals(struct file *file, void *priv, - struct v4l2_frmivalenum *fival) -{ - unsigned int k; - - if (fival->index > ARRAY_SIZE(gc2145_frmivalenum)) - return -EINVAL; - - for (k = 0; k < ARRAY_SIZE(gc2145_frmivalenum); k++) { - if ((fival->index == gc2145_frmivalenum[k].index) && - (fival->pixel_format == - gc2145_frmivalenum[k].pixel_format) && - (fival->width == gc2145_frmivalenum[k].width) && - (fival->height == gc2145_frmivalenum[k].height)) { - memcpy(fival, &gc2145_frmivalenum[k], - sizeof(struct v4l2_frmivalenum)); - return 0; - } - } - - return -EINVAL; - -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct gc2145_fh *fh = priv; - - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; - f->fmt.pix.field = fh->vb_vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - struct gc2145_fmt *fmt; - enum v4l2_field field; - unsigned int maxw, maxh; - - fmt = get_format(f); - if (!fmt) { - dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n", - f->fmt.pix.pixelformat); - return -EINVAL; - } - - field = f->fmt.pix.field; - - if (field == V4L2_FIELD_ANY) - field = V4L2_FIELD_INTERLACED; - else if (field != V4L2_FIELD_INTERLACED) { - dprintk(dev, 1, "Field type invalid.\n"); - return -EINVAL; - } - - maxw = norm_maxw(); - maxh = norm_maxh(); - - f->fmt.pix.field = field; - v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, - &f->fmt.pix.height, 32, maxh, 0, 0); - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -/*FIXME: This seems to be generic enough to be at videodev2 */ -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct gc2145_fh *fh = priv; - struct videobuf_queue *q = &fh->vb_vidq; - struct gc2145_device *dev = fh->dev; - int ret; - - f->fmt.pix.width = (f->fmt.pix.width + - (CANVAS_WIDTH_ALIGN - 1)) & - (~(CANVAS_WIDTH_ALIGN - 1)); - if ((f->fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) || - (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)) - f->fmt.pix.width = (f->fmt.pix.width + - (CANVAS_WIDTH_ALIGN * 2 - 1)) & - (~(CANVAS_WIDTH_ALIGN * 2 - 1)); - - ret = vidioc_try_fmt_vid_cap(file, fh, f); - if (ret < 0) - return ret; - - mutex_lock(&q->vb_lock); - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - dprintk(fh->dev, 1, "%s queue busy\n", __func__); - ret = -EBUSY; - goto out; - } - - fh->fmt = get_format(f); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vb_vidq.field = f->fmt.pix.field; - fh->type = f->type; -#if 0 - set_flip(dev); - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { - vidio_set_fmt_ticks = 1; - GC2145_set_resolution(dev, fh->height, fh->width); - } else if (vidio_set_fmt_ticks == 1) - GC2145_set_resolution(dev, fh->height, fh->width); -#else - GC2145_set_resolution(dev, fh->height, fh->width); -#endif - ret = 0; -out: - mutex_unlock(&q->vb_lock); - - return ret; -} - -static int vidioc_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *parms) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - struct v4l2_captureparm *cp = &parms->parm.capture; - - dprintk(dev, 3, "vidioc_g_parm\n"); - if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memset(cp, 0, sizeof(struct v4l2_captureparm)); - cp->capability = V4L2_CAP_TIMEPERFRAME; - - cp->timeperframe = gc2145_frmintervals_active; - pr_debug("g_parm,deno=%d, numerator=%d\n", - cp->timeperframe.denominator, - cp->timeperframe.numerator); - return 0; -} - - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct gc2145_fh *fh = priv; - - return videobuf_reqbufs(&fh->vb_vidq, p); -} - -static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct gc2145_fh *fh = priv; - int ret = videobuf_querybuf(&fh->vb_vidq, p); - - if (get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { - if (ret == 0) - p->reserved = convert_canvas_index(fh->fmt->fourcc, - CAMERA_USER_CANVAS_INDEX + - p->index * 3); - else - p->reserved = 0; - } - return ret; -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct gc2145_fh *fh = priv; - - return videobuf_qbuf(&fh->vb_vidq, p); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct gc2145_fh *fh = priv; - - return videobuf_dqbuf(&fh->vb_vidq, p, - file->f_flags & O_NONBLOCK); -} - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct gc2145_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct gc2145_fh *fh = priv; - struct vdin_parm_s para; - unsigned int vdin_path; - int ret = 0; - - pr_info("vidioc_streamon+++\n "); - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - memset(¶, 0, sizeof(para)); - para.port = TVIN_PORT_CAMERA; - para.fmt = TVIN_SIG_FMT_MAX; - para.frame_rate = gc2145_frmintervals_active.denominator; - para.h_active = GC2145_h_active; - para.v_active = GC2145_v_active; - para.hsync_phase = 1; - para.vsync_phase = 1; - para.hs_bp = 0; - para.vs_bp = 3; - para.bt_path = fh->dev->cam_info.bt_path; - vdin_path = fh->dev->cam_info.vdin_path; - para.cfmt = TVIN_YUV422; - para.dfmt = TVIN_NV21; - para.scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; - - if (is_first_time_open == 0) { - para.skip_count = 4; - is_first_time_open = 1; - } else - para.skip_count = 0; - - ret = videobuf_streamon(&fh->vb_vidq); - if (ret == 0) { - if (fh->dev->vminfo.isused) { - vops->start_tvin_service(vdin_path, ¶); - fh->stream_on = 1; - } - } - - return ret; -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct gc2145_fh *fh = priv; - unsigned int vdin_path; - int ret = 0; - - pr_info("vidioc_streamoff+++\n "); - vdin_path = fh->dev->cam_info.vdin_path; - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - ret = videobuf_streamoff(&fh->vb_vidq); - if (ret == 0) { - if (fh->dev->vminfo.isused) - vops->stop_tvin_service(vdin_path); - fh->stream_on = 0; - } - return ret; -} - -static int vidioc_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *fsize) -{ - int ret = 0, i = 0; - struct gc2145_fmt *fmt = NULL; - struct v4l2_frmsize_discrete *frmsize = NULL; - - for (i = 0; i < ARRAY_SIZE(formats); i++) { - if (formats[i].fourcc == fsize->pixel_format) { - fmt = &formats[i]; - break; - } - } - if (fmt == NULL) - return -EINVAL; - if ((fmt->fourcc == V4L2_PIX_FMT_NV21) - || (fmt->fourcc == V4L2_PIX_FMT_NV12) - || (fmt->fourcc == V4L2_PIX_FMT_YVU420) - || (fmt->fourcc == V4L2_PIX_FMT_YUV420)) { - if (fsize->index >= ARRAY_SIZE(gc2145_prev_resolution)) - return -EINVAL; - frmsize = &gc2145_prev_resolution[fsize->index]; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = frmsize->width; - fsize->discrete.height = frmsize->height; - } else if (fmt->fourcc == V4L2_PIX_FMT_RGB24) { - if (fsize->index >= ARRAY_SIZE(gc2145_pic_resolution)) - return -EINVAL; - frmsize = &gc2145_pic_resolution[fsize->index]; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = frmsize->width; - fsize->discrete.height = frmsize->height; - } - return ret; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i) -{ - return 0; -} - -/* only one input in this sample driver */ -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) -{ - /* if (inp->index >= NUM_INPUTS) */ - /* return -EINVAL; */ - - inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_525_60; - sprintf(inp->name, "Camera %u", inp->index); - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - - *i = dev->input; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - - /* if (i >= NUM_INPUTS) */ - /* return -EINVAL; */ - - dev->input = i; - /* precalculate_bars(fh); */ - - return 0; -} - -/* --- controls ---------------------------------------------- */ -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(gc2145_qctrl); i++) - if (qc->id && qc->id == gc2145_qctrl[i].id) { - memcpy(qc, &(gc2145_qctrl[i]), - sizeof(*qc)); - return 0; - } - - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - int i; - - for (i = 0; i < ARRAY_SIZE(gc2145_qctrl); i++) - if (ctrl->id == gc2145_qctrl[i].id) { - ctrl->value = dev->qctl_regs[i]; - return 0; - } - - return -EINVAL; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct gc2145_fh *fh = priv; - struct gc2145_device *dev = fh->dev; - int i; - - for (i = 0; i < ARRAY_SIZE(gc2145_qctrl); i++) - if (ctrl->id == gc2145_qctrl[i].id) { - if (ctrl->value < gc2145_qctrl[i].minimum || - ctrl->value > gc2145_qctrl[i].maximum || - gc2145_setting(dev, ctrl->id, ctrl->value) < 0) - return -ERANGE; - dev->qctl_regs[i] = ctrl->value; - return 0; - } - return -EINVAL; -} - -/* - *------------------------------------------------------------------ - * File operations for the device - * ----------------------------------------------------------------- - */ - -static int gc2145_open(struct file *file) -{ - struct gc2145_device *dev = video_drvdata(file); - struct gc2145_fh *fh = NULL; - int retval = 0; - - dev->vminfo.vdin_id = dev->cam_info.vdin_path; - dev->vminfo.bt_path_count = dev->cam_info.bt_path_count; - -#if CONFIG_CMA - vm_init_resource(16 * SZ_1M, &dev->vminfo); -#endif - if (dev->vminfo.isused) { - pr_info("%s, front_back = %d\n", - __func__, dev->cam_info.front_back); - aml_cam_init(&dev->cam_info); - } - - GC2145_init_regs(dev); - msleep(40); - mutex_lock(&dev->mutex); - dev->users++; - if (dev->users > 1) { - dev->users--; - pr_err("gc2145 device is opened, device is busy\n"); - mutex_unlock(&dev->mutex); - return -EBUSY; - } - - dprintk(dev, 1, "open %s type=%s users=%d\n", - video_device_node_name(dev->vdev), - v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - init_waitqueue_head(&dev->vidq.wq); - spin_lock_init(&dev->slock); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (fh == NULL) { - dev->users--; - retval = -ENOMEM; - } - mutex_unlock(&dev->mutex); - - if (retval) - return retval; - -#ifdef CONFIG_HAS_WAKELOCK - wake_lock(&(dev->wake_lock)); -#endif - - file->private_data = fh; - fh->dev = dev; - - fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fh->fmt = &formats[0]; - fh->width = 1600;/* 640//zyy */ - fh->height = 1198;/* 1200;//480 */ - fh->stream_on = 0; - fh->f_flags = file->f_flags; - /* Resets frame counters */ - /*dev->jiffies = jiffies;*/ - - /* TVIN_SIG_FMT_CAMERA_640X480P_30Hz, */ - /* TVIN_SIG_FMT_CAMERA_800X600P_30Hz, */ - /* TVIN_SIG_FMT_CAMERA_1024X768P_30Hz, // 190 */ - /* TVIN_SIG_FMT_CAMERA_1920X1080P_30Hz, */ - /* TVIN_SIG_FMT_CAMERA_1280X720P_30Hz, */ - - if (dev->vminfo.mem_alloc_succeed) { - fh->res.start = dev->vminfo.buffer_start; - fh->res.end = dev->vminfo.buffer_start + - dev->vminfo.vm_buf_size - 1; - fh->res.magic = MAGIC_RE_MEM; - fh->res.priv = NULL; - videobuf_queue_res_init(&fh->vb_vidq, - &gc2145_video_res_qops, NULL, - &dev->slock, fh->type, - V4L2_FIELD_INTERLACED, - sizeof(struct gc2145_buffer), - (void *)&fh->res, NULL); - } else { - videobuf_queue_vmalloc_init(&fh->vb_vidq, - &gc2145_video_vmall_qops, NULL, - &dev->slock, fh->type, - V4L2_FIELD_INTERLACED, - sizeof(struct gc2145_buffer), fh, NULL); - } - - gc2145_start_thread(fh); - gc2145_have_open = 1; - return 0; -} - -static ssize_t -gc2145_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct gc2145_fh *fh = file->private_data; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); - } - return 0; -} - -static unsigned int -gc2145_poll(struct file *file, struct poll_table_struct *wait) -{ - struct gc2145_fh *fh = file->private_data; - struct gc2145_device *dev = fh->dev; - struct videobuf_queue *q = &fh->vb_vidq; - - dprintk(dev, 1, "%s\n", __func__); - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return POLLERR; - - return videobuf_poll_stream(file, q, wait); -} - -static int gc2145_close(struct file *file) -{ - struct gc2145_fh *fh = file->private_data; - struct gc2145_device *dev = fh->dev; - struct gc2145_dmaqueue *vidq = &dev->vidq; - struct video_device *vdev = video_devdata(file); - unsigned int vdin_path; - - vdin_path = fh->dev->cam_info.vdin_path; - gc2145_have_open = 0; - is_first_time_open = 0; - - gc2145_stop_thread(vidq); - videobuf_stop(&fh->vb_vidq); - if (fh->stream_on) { - if (dev->vminfo.isused) { - pr_info("%s, vdin_path = %d\n", - __func__, vdin_path); - vops->stop_tvin_service(vdin_path); - } - } - videobuf_mmap_free(&fh->vb_vidq); - kfree(fh); - - mutex_lock(&dev->mutex); - dev->users--; - mutex_unlock(&dev->mutex); - - dprintk(dev, 1, "close called (dev=%s, users=%d)\n", - video_device_node_name(vdev), dev->users); -#if 1 - GC2145_h_active = 640; /* 800//zyy */ - GC2145_v_active = 480; /* 1200;//600 */ - gc2145_qctrl[0].default_value = 0; - gc2145_qctrl[1].default_value = 4; - gc2145_qctrl[2].default_value = 0; - gc2145_qctrl[3].default_value = 0; - gc2145_qctrl[4].default_value = 0; - - gc2145_qctrl[5].default_value = 0; - gc2145_qctrl[7].default_value = 100; - gc2145_qctrl[8].default_value = 0; - gc2145_frmintervals_active.numerator = 1; - gc2145_frmintervals_active.denominator = 15; - power_down_gc2145(dev); -#endif - aml_cam_uninit(&dev->cam_info); -#ifdef CONFIG_HAS_WAKELOCK - wake_unlock(&(dev->wake_lock)); -#endif -#ifdef CONFIG_CMA - vm_deinit_resource(&dev->vminfo); -#endif - return 0; -} - -static int gc2145_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct gc2145_fh *fh = file->private_data; - struct gc2145_device *dev = fh->dev; - int ret; - - dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); - - ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); - - dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, - ret); - - return ret; -} - -static const struct v4l2_file_operations gc2145_fops = { - .owner = THIS_MODULE, - .open = gc2145_open, - .release = gc2145_close, - .read = gc2145_read, - .poll = gc2145_poll, - .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .mmap = gc2145_mmap, -}; - -static const struct v4l2_ioctl_ops gc2145_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_s_std = vidioc_s_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_querymenu = vidioc_querymenu, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - .vidioc_g_parm = vidioc_g_parm, - .vidioc_enum_frameintervals = vidioc_enum_frameintervals, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif -}; - -static struct video_device gc2145_template = { - .name = "gc2145_v4l", - .fops = &gc2145_fops, - .ioctl_ops = &gc2145_ioctl_ops, - .release = video_device_release, - .tvnorms = V4L2_STD_525_60, -}; - -static const struct v4l2_subdev_core_ops gc2145_core_ops = { - /*.g_chip_ident = gc2145_g_chip_ident,*/ -}; - -static const struct v4l2_subdev_ops gc2145_ops = { - .core = &gc2145_core_ops, -}; - -static ssize_t gc2145_show(struct device *dev, struct device_attribute *attr, - char *_buf) -{ - return sprintf(_buf, "0x%02x=0x%02x\n", cur_reg, cur_val); -} - -static u32 strtol(const char *nptr, int base) -{ - u32 ret; - - if (!nptr || (base != 16 && base != 10 && base != 8)) { - pr_err("%s(): NULL pointer input\n", __func__); - return -1; - } - for (ret = 0; *nptr; nptr++) { - if ((base == 16 && *nptr >= 'A' && *nptr <= 'F') || - (base == 16 && *nptr >= 'a' && *nptr <= 'f') || - (base >= 10 && *nptr >= '0' && *nptr <= '9') || - (base >= 8 && *nptr >= '0' && *nptr <= '7')) { - ret *= base; - if (base == 16 && *nptr >= 'A' && *nptr <= 'F') - ret += *nptr - 'A' + 10; - else if (base == 16 && *nptr >= 'a' && *nptr <= 'f') - ret += *nptr - 'a' + 10; - else if (base >= 10 && *nptr >= '0' && *nptr <= '9') - ret += *nptr - '0'; - else if (base >= 8 && *nptr >= '0' && *nptr <= '7') - ret += *nptr - '0'; - } else - return ret; - } - return ret; -} - -static ssize_t gc2145_store(struct device *dev, - struct device_attribute *attr, - const char *_buf, size_t _count) -{ - const char *p = _buf; - u16 reg; - u8 val; - - if (!strncmp(_buf, "get", strlen("get"))) { - p += strlen("get"); - cur_reg = (u32)strtol(p, 16); - val = i2c_get_byte_add8(g_i2c_client, cur_reg); - pr_info("%s(): get 0x%04x=0x%02x\n", - __func__, cur_reg, val); - cur_val = val; - } else if (!strncmp(_buf, "put", strlen("put"))) { - p += strlen("put"); - reg = strtol(p, 16); - p = strchr(_buf, '='); - if (p) { - ++p; - val = strtol(p, 16); - i2c_put_byte_add8_new(g_i2c_client, reg, val); - pr_info("%s(): set 0x%04x=0x%02x\n", - __func__, reg, val); - } else - pr_info("%s(): Bad string format input!\n", __func__); - } else - pr_info("%s(): Bad string format input!\n", __func__); - - return _count; -} - -static ssize_t name_show(struct device *dev, - struct device_attribute *attr, - char *_buf) -{ - strcpy(_buf, "GC2145"); - return 4; -} - -static struct device *gc2145_dev; -static struct class *gc2145_class; -static DEVICE_ATTR(gc2145, 0444, gc2145_show, gc2145_store);/*0666*/ -static DEVICE_ATTR(name, 0444, name_show, NULL); - -#define EMDOOR_DEBUG_GC2145 1 -#ifdef EMDOOR_DEBUG_GC2145 -unsigned int gc2145_reg_addr; -static struct i2c_client *gc2145_client; - -static ssize_t gc2145_show_mine(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - unsigned char dat; - - dat = i2c_get_byte_add8(gc2145_client, gc2145_reg_addr); - return sprintf(buf, "REG[0x%x]=0x%x\n", gc2145_reg_addr, dat); -} - -static ssize_t gc2145_store_mine(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) -{ - int tmp; - unsigned short reg; - unsigned char val; - - tmp = kstrtoul(buf, 16, NULL); - /* sscanf(buf, "%du", &tmp); */ - if (tmp < 0xff) - gc2145_reg_addr = tmp; - else { - reg = (tmp >> 8) & 0xFFFF; /* reg */ - gc2145_reg_addr = reg; - val = tmp & 0xFF; /* val */ - i2c_put_byte_add8_new(gc2145_client, reg, val); - } - - return count; -} - - -static struct kobj_attribute gc2145_attribute = __ATTR(gc2145, 0444, - gc2145_show_mine, gc2145_store_mine); - - -static struct attribute *gc2145_attrs[] = { - &gc2145_attribute.attr, - NULL, -}; - - -static const struct attribute_group gc2145_group = { - .attrs = gc2145_attrs, -}; -#endif - -static int gc2145_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - struct gc2145_device *t; - struct v4l2_subdev *sd; - struct aml_cam_info_s *plat_dat; - int ret; - - vops = get_vdin_v4l2_ops(); - v4l_info(client, "chip found @ 0x%x (%s)\n", - client->addr << 1, client->adapter->name); - t = kzalloc(sizeof(*t), GFP_KERNEL); - /* modify correct i2c addr--- 0x30 */ - client->addr = 0x3c; - if (t == NULL) { - pr_err("%s, no memory", __func__); - return -ENOMEM; - } - snprintf(t->v4l2_dev.name, sizeof(t->v4l2_dev.name), - "%s-%03d", "gc2145", 0); - ret = v4l2_device_register(NULL, &t->v4l2_dev); - if (ret) { - pr_info("%s, v4l2 device register failed", __func__); - kfree(t); - kfree(client); - return ret; - } - - sd = &t->sd; - v4l2_i2c_subdev_init(sd, client, &gc2145_ops); - - plat_dat = (struct aml_cam_info_s *)client->dev.platform_data; - /* test if devices exist. */ - memset(&t->vminfo, 0, sizeof(struct vm_init_s)); - /* Now create a video4linux device */ - mutex_init(&t->mutex); - - /* Now create a video4linux device */ - t->vdev = video_device_alloc(); - if (t->vdev == NULL) { - kfree(t); - kfree(client); - return -ENOMEM; - } - memcpy(t->vdev, &gc2145_template, sizeof(*t->vdev)); - t->vdev->v4l2_dev = &t->v4l2_dev; - video_set_drvdata(t->vdev, t); - -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_init(&(t->wake_lock), WAKE_LOCK_SUSPEND, "gc2145"); -#endif - - /* Register it */ - if (plat_dat) { - memcpy(&t->cam_info, plat_dat, sizeof(struct aml_cam_info_s)); - pr_info("%s, front_back = %d\n", - __func__, plat_dat->front_back); - video_nr = plat_dat->front_back; - } else { - pr_err("camera gc2145: have no platform data\n"); - kfree(t); - return -1; - } - - t->cam_info.version = GC2145_DRIVER_VERSION; - if (aml_cam_info_reg(&t->cam_info) < 0) - pr_err("reg caminfo error\n"); - err = video_register_device(t->vdev, VFL_TYPE_GRABBER, video_nr); - if (err < 0) { - video_device_release(t->vdev); - kfree(t); - return err; - } - - gc2145_class = class_create(THIS_MODULE, "gc2145"); - if (IS_ERR(gc2145_class)) { - pr_err("Create class gc2145 fail.\n"); - return -ENOMEM; - } - - gc2145_dev = device_create(gc2145_class, NULL, - MKDEV(0, 1), NULL, "dev"); - device_create_file(gc2145_dev, &dev_attr_gc2145); - device_create_file(gc2145_dev, &dev_attr_name); - - g_i2c_client = client; - -#ifdef EMDOOR_DEBUG_GC2145 - gc2145_client = client; - err = sysfs_create_group(&client->dev.kobj, &gc2145_group); -#endif - - return 0; -} - -static int gc2145_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct gc2145_device *t = to_dev(sd); - - video_unregister_device(t->vdev); - v4l2_device_unregister_subdev(sd); -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_destroy(&(t->wake_lock)); -#endif - aml_cam_info_unreg(&t->cam_info); - kfree(t); - return 0; -} - - -static const struct i2c_device_id gc2145_id[] = { - { "gc2145", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gc2145_id); - -static struct i2c_driver gc2145_i2c_driver = { - .driver = { - .name = "gc2145", - }, - .probe = gc2145_probe, - .remove = gc2145_remove, - .id_table = gc2145_id, -}; - -module_i2c_driver(gc2145_i2c_driver); - diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index db416df15659..3bad9b121991 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -521,6 +521,9 @@ static void canvas_pool_config(void) canvas_pool_register_const_canvas(0x70, 0x77, "ppmgr"); canvas_pool_register_const_canvas(0xe4, 0xef, "encoder"); canvas_pool_register_const_canvas(0x40, 0x48, "osd"); +#ifdef CONFIG_AMLOGIC_VIDEOIN_MANAGER + canvas_pool_register_const_canvas(0x4e, 0x5f, "vm"); +#endif canvas_pool_register_const_canvas(0xc0, 0xd7, "amlvideo2"); /*please add static canvas later. */ } diff --git a/include/linux/amlogic/media/camera/aml_cam_info.h b/include/linux/amlogic/media/camera/aml_cam_info.h deleted file mode 100644 index b669ef4f466a..000000000000 --- a/include/linux/amlogic/media/camera/aml_cam_info.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * include/linux/amlogic/media/camera/aml_cam_info.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef __AML_CAM_DEV__ -#define __AML_CAM_DEV__ -#include -#include -#include -#include -#include -#include - -#define FRONT_CAM 0 -#define BACK_CAM 1 - -enum resolution_size { - SIZE_NULL = 0, SIZE_176X144, /* 4:3 */ - SIZE_320X240, /* 4:3 */ - SIZE_352X288, /* 4:3 */ - SIZE_640X480, /* 0.3M 4:3 */ - SIZE_720X405, /* 0.3M 16:9 */ - SIZE_800X600, /* 0.5M 4:3 */ - SIZE_960X540, /* 0.5M 16:9 */ - SIZE_1024X576, /* 0.6M 16:9 */ - SIZE_960X720, /* 0.7M 4:3 */ - SIZE_1024X768, /* 0.8M 4:3 */ - SIZE_1280X720, /* 0.9M 16:9 */ - SIZE_1152X864, /* 1M 4:3 */ - SIZE_1366X768, /* 1M 16:9 */ - SIZE_1280X960, /* 1.2M 4:3 */ - SIZE_1280X1024, /* 1.3M 16:9. */ - SIZE_1400X1050, /* 1.5M 4:3 */ - SIZE_1600X900, /* 1.5M 16:9 */ - SIZE_1600X1200, /* 2M 4:3 */ - SIZE_1920X1080, /* 2M 16:9 */ - SIZE_1792X1344, /* 2.4M 4:3 */ - SIZE_2048X1152, /* 2.4M 16:9 */ - SIZE_2048X1536, /* 3.2M 4:3 */ - SIZE_2304X1728, /* 4M 4:3 */ - SIZE_2560X1440, /* 4M 16:9 */ - SIZE_2592X1944, /* 5M 4:3 */ - SIZE_3072X1728, /* 5M 16:9 */ - SIZE_2816X2112, /* 6M 4:3 */ - SIZE_3264X1836, /* 6m 16:9 */ - SIZE_3072X2304, /* 7M 4:3 */ - SIZE_3200X2400, /* 7.5M 4:3 */ - SIZE_3264X2448, /* 8M 4:3 */ - SIZE_3840X2160, /* 8M 16:9 */ - SIZE_3456X2592, /* 9M 4:3 */ - SIZE_3600X2700, /* 9.5M 4:3 */ - SIZE_4096X2304, /* 9.5M 16:9 */ - SIZE_3672X2754, /* 10M 4:3 */ - SIZE_3840X2880, /* 11M 4:3 */ - SIZE_4000X3000, /* 12M 4:3 */ - SIZE_4608X2592, /* 12M 16:9 */ - SIZE_4096X3072, /* 12.5M 4:3 */ - SIZE_4800X3200, /* 15M 4:3 */ - SIZE_5120X2880, /* 15M 16:9 */ - SIZE_5120X3840, /* 20M 4:3 */ - SIZE_6400X4800, /* 30M 4:3 */ -}; - -typedef int (*aml_cam_probe_fun_t)(struct i2c_adapter *); - -struct aml_cam_info_s { - struct list_head info_entry; - const char *name; - unsigned int i2c_bus_num; - unsigned int pwdn_act; - unsigned int front_back; /* front is 0, back is 1 */ - unsigned int m_flip; - unsigned int v_flip; - unsigned int flash; - unsigned int auto_focus; - unsigned int i2c_addr; - const char *motor_driver; - const char *resolution; - const char *version; - unsigned int mclk; - unsigned int flash_support; - unsigned int flash_ctrl_level; - unsigned int torch_support; - unsigned int torch_ctrl_level; - unsigned int vcm_mode; - unsigned int spread_spectrum; - unsigned int vdin_path; - unsigned int bt_path_count; - enum bt_path_e bt_path; - enum cam_interface_e interface; - enum clk_channel_e clk_channel; - /* gpio_t pwdn_pin; */ - /* gpio_t rst_pin; */ - /* gpio_t flash_ctrl_pin; */ - /* gpio_t torch_ctrl_pin; */ - unsigned int pwdn_pin; - unsigned int rst_pin; - unsigned int flash_ctrl_pin; - unsigned int torch_ctrl_pin; - enum resolution_size max_cap_size; - enum tvin_color_fmt_e bayer_fmt; - const char *config; - struct pinctrl *camera_pin_ctrl; -}; -/* aml_cam_info_t */ - -struct aml_camera_i2c_fig_s { - unsigned short addr; - unsigned char val; -}; - -struct aml_camera_i2c_fig0_s { - unsigned short addr; - unsigned short val; -}; - -struct aml_camera_i2c_fig1_s { - unsigned char addr; - unsigned char val; -}; - -extern void aml_cam_init(struct aml_cam_info_s *cam_dev); -extern void aml_cam_uninit(struct aml_cam_info_s *cam_dev); -extern void aml_cam_flash(struct aml_cam_info_s *cam_dev, int is_on); -extern void aml_cam_torch(struct aml_cam_info_s *cam_dev, int is_on); -extern int aml_cam_info_reg(struct aml_cam_info_s *cam_info); -extern int aml_cam_info_unreg(struct aml_cam_info_s *cam_info); - -#endif /* __AML_CAM_DEV__ */ diff --git a/include/linux/amlogic/media/camera/flashlight.h b/include/linux/amlogic/media/camera/flashlight.h deleted file mode 100644 index d59437251385..000000000000 --- a/include/linux/amlogic/media/camera/flashlight.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * include/linux/amlogic/media/camera/flashlight.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _VIDEO_AMLOGIC_FLASHLIGHT_INCLUDE_ -#define _VIDEO_AMLOGIC_FLASHLIGHT_INCLUDE_ -struct aml_plat_flashlight_data_s { - void (*flashlight_on)(void); - void (*flashlight_off)(void); -}; - -enum aml_plat_flashlight_status_s { - FLASHLIGHT_AUTO = 0, - FLASHLIGHT_ON, - FLASHLIGHT_OFF, - FLASHLIGHT_TORCH, - FLASHLIGHT_RED_EYE, -}; - -#endif - diff --git a/include/linux/amlogic/media/camera/vmapi.h b/include/linux/amlogic/media/camera/vmapi.h deleted file mode 100644 index b1d832eda9db..000000000000 --- a/include/linux/amlogic/media/camera/vmapi.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * include/linux/amlogic/media/camera/vmapi.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VM_API_INCLUDE_ -#define VM_API_INCLUDE_ - -struct vm_output_para { - int width; - int height; - int bytesperline; - int v4l2_format; - int index; - int v4l2_memory; - int zoom; /* set -1 as invalid */ - int mirror; /* set -1 as invalid */ - int angle; - uintptr_t vaddr;/*unsigned*/ - unsigned int ext_canvas; -}; -/*struct vm_output_para*/ -struct videobuf_buffer; -struct vb2_buffer; - -struct vm_init_s { - size_t vm_buf_size; - struct page *vm_pages; - resource_size_t buffer_start; - unsigned int vdin_id; - unsigned int bt_path_count; - bool isused; - bool mem_alloc_succeed; -}; -/*struct vm_init_s*/ - -int vm_fill_this_buffer(struct videobuf_buffer *vb, struct vm_output_para *para, - struct vm_init_s *info); -int vm_fill_buffer(struct videobuf_buffer *vb, struct vm_output_para *para); - -int vm_fill_buffer2(struct vb2_buffer *vb, struct vm_output_para *para); - -#ifdef CONFIG_CMA -int vm_init_buf(size_t size); -int vm_init_resource(size_t size, struct vm_init_s *info); -void vm_deinit_buf(void); -void vm_deinit_resource(struct vm_init_s *info); -void vm_reserve_cma(void); -#endif - -#endif /* VM_API_INCLUDE_ */ From 041b4d5d79b0ebb8f3f8dc77f1929780ce11314c Mon Sep 17 00:00:00 2001 From: Guosong Zhou Date: Wed, 2 Jan 2019 06:00:30 -0500 Subject: [PATCH 0574/1060] camera: add dvp camera [1/1] PD#OTT-1204 Problem: don't support dvp camera Solution: add dvp camera gc2145 camera driver Verify: test pass on U200 Change-Id: I5927d49a93952587af7bb460a5c405293d692153 Signed-off-by: Guosong Zhou Conflicts: MAINTAINERS arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts --- MAINTAINERS | 13 + .../arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 39 +- arch/arm/configs/meson64_a32_defconfig | 3 + .../boot/dts/amlogic/g12a_s905d2_u200.dts | 87 + arch/arm64/configs/meson64_defconfig | 3 + drivers/amlogic/media/Kconfig | 1 + drivers/amlogic/media/Makefile | 1 + drivers/amlogic/media/camera/Kconfig | 559 +++ drivers/amlogic/media/camera/Makefile | 15 + .../amlogic/media/camera/common/cam_prober.c | 1792 +++++++++ .../media/camera/common/config_parser.c | 1822 +++++++++ .../media/camera/common/config_parser.h | 301 ++ .../amlogic/media/camera/common/flashlight.c | 249 ++ .../amlogic/media/camera/common/plat_ctrl.c | 208 + .../amlogic/media/camera/common/plat_ctrl.h | 47 + drivers/amlogic/media/camera/common/vm.c | 2309 +++++++++++ drivers/amlogic/media/camera/common/vm.h | 139 + drivers/amlogic/media/camera/common/vm_log.h | 44 + drivers/amlogic/media/camera/common/vmcls.h | 189 + drivers/amlogic/media/camera/gc2145.c | 3453 +++++++++++++++++ .../amlogic/media/common/canvas/canvas_mgr.c | 3 - .../linux/amlogic/media/camera/aml_cam_info.h | 142 + .../linux/amlogic/media/camera/flashlight.h | 34 + include/linux/amlogic/media/camera/vmapi.h | 63 + 24 files changed, 11510 insertions(+), 6 deletions(-) create mode 100644 drivers/amlogic/media/camera/Kconfig create mode 100644 drivers/amlogic/media/camera/Makefile create mode 100644 drivers/amlogic/media/camera/common/cam_prober.c create mode 100644 drivers/amlogic/media/camera/common/config_parser.c create mode 100644 drivers/amlogic/media/camera/common/config_parser.h create mode 100644 drivers/amlogic/media/camera/common/flashlight.c create mode 100644 drivers/amlogic/media/camera/common/plat_ctrl.c create mode 100644 drivers/amlogic/media/camera/common/plat_ctrl.h create mode 100644 drivers/amlogic/media/camera/common/vm.c create mode 100644 drivers/amlogic/media/camera/common/vm.h create mode 100644 drivers/amlogic/media/camera/common/vm_log.h create mode 100644 drivers/amlogic/media/camera/common/vmcls.h create mode 100644 drivers/amlogic/media/camera/gc2145.c create mode 100644 include/linux/amlogic/media/camera/aml_cam_info.h create mode 100644 include/linux/amlogic/media/camera/flashlight.h create mode 100644 include/linux/amlogic/media/camera/vmapi.h diff --git a/MAINTAINERS b/MAINTAINERS index 66ad4a45dcf4..c4ba5ed396a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14771,6 +14771,19 @@ M: Yeping Miao F: arch/arm64/boot/dts/amlogic/axg_rsr.dts F: arch/arm64/boot/dts/amlogic/axg_rsr_v03.dts +AMLOGIC CAMERA DRIVER +M: Guosong Zhou +F: arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +F: arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +F: arch/arm64/configs/meson64_defconfig +F: arch/arm/configs/meson64_a32_defconfig +F: drivers/amlogic/media/Kconfig +F: drivers/amlogic/media/Makefile +F: drivers/amlogic/media/camera/* +F: drivers/amlogic/media/common/canvas/canvas_mgr.c +F: drivers/amlogic/media/common/vfm/vfm.c +F: include/linux/amlogic/media/camera/* + AMLOGIC multimedia M: Pengcheng Chen F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index e4393da38f16..837e58fc94ad 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -155,8 +155,8 @@ vm0_cma_reserved:linux,vm0_cma { compatible = "shared-dma-pool"; reusable; - size = <0x2000000>; - alignment = <0x400000>; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; }; }; @@ -317,7 +317,7 @@ compatible = "amlogic, amvdec_656in"; dev_name = "amvdec_656in"; status = "disabled"; - reg = <0xffe02000 0x7c>; + reg = <0x0 0xffe02000 0x0 0x7c>; clocks = <&clkc CLKID_BT656_COMP>, <&clkc CLKID_BT656>; clock-names = "cts_bt656_clk1", @@ -1017,6 +1017,13 @@ }; }; +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + &i2c3 { status = "okay"; pinctrl-names="default"; @@ -1356,6 +1363,32 @@ }; }; + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + }; /* end of pinctrl_periphs */ &pinctrl_aobus { diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index c4d9059d1f60..f07a46f44ceb 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -329,6 +329,9 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y +CONFIG_AMLOGIC_VIDEO_CAPTURE=y +CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y +CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145=y CONFIG_AMLOGIC_DTV_DEMOD=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index 3c6981089c0c..cd3d653df59f 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -150,6 +150,12 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; }; gpioleds { @@ -296,6 +302,54 @@ dev_name = "ionvideo"; status = "okay"; }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; gpio_keypad{ compatible = "amlogic, gpio_keypad"; @@ -964,6 +1018,13 @@ }; }; +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + &i2c3 { status = "okay"; pinctrl-names="default"; @@ -1303,6 +1364,32 @@ }; }; + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + }; /* end of pinctrl_periphs */ &pinctrl_aobus { diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index f201b5de6668..9fb51faf6dde 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -324,6 +324,9 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y +CONFIG_AMLOGIC_VIDEO_CAPTURE=y +CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y +CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145=y CONFIG_AMLOGIC_DTV_DEMOD=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y diff --git a/drivers/amlogic/media/Kconfig b/drivers/amlogic/media/Kconfig index bc316278ce43..ded82c05b026 100644 --- a/drivers/amlogic/media/Kconfig +++ b/drivers/amlogic/media/Kconfig @@ -94,6 +94,7 @@ source "drivers/amlogic/media/video_processor/Kconfig" source "drivers/amlogic/media/enhancement/Kconfig" source "drivers/amlogic/media/gdc/Kconfig" source "drivers/amlogic/media/algorithm/Kconfig" +source "drivers/amlogic/media/camera/Kconfig" endif source "drivers/amlogic/media/dtv_demod/Kconfig" endmenu diff --git a/drivers/amlogic/media/Makefile b/drivers/amlogic/media/Makefile index dfb73164f565..12f643b1e1d9 100644 --- a/drivers/amlogic/media/Makefile +++ b/drivers/amlogic/media/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_AMLOGIC_DTV_DEMOD) += dtv_demod/ obj-$(CONFIG_AMLOGIC_MEDIA_GDC) += gdc/ obj-$(CONFIG_AMLOGIC_MEDIA_ALGORITHM) += algorithm/ +obj-$(CONFIG_AMLOGIC_VIDEO_CAPTURE) += camera/ \ No newline at end of file diff --git a/drivers/amlogic/media/camera/Kconfig b/drivers/amlogic/media/camera/Kconfig new file mode 100644 index 000000000000..41d08be16cb7 --- /dev/null +++ b/drivers/amlogic/media/camera/Kconfig @@ -0,0 +1,559 @@ +menu "Amlogic Camera Support" + +config AMLOGIC_VIDEO_CAPTURE + tristate "Amlogic Platform Capture Driver" + depends on !SPARC32 && !SPARC64 &&!AMLOGIC_CAMERA_ENABLE + select VIDEOBUF_VMALLOC + depends on MEDIA_SUPPORT + select VIDEO_DEV + select VIDEO_V4L2 + default n + ---help--- + Amlogic capture driver interface in v4l style. + it can not work well together with + AMLOGIC_CAMERA_ENABLE + Say Y here if you want this driver. + +config AMLOGIC_CAPTURE_FRAME_ROTATE + bool "Enable function to support frame rotation" + depends on AMLOGIC_VIDEO_CAPTURE + default n + ---help--- + It will support frame rotation when enable this config + It will support frame rotation when enable this config + It will support frame rotation when enable this config + It will support frame rotation when enable this config + +config AMLOGIC_VM_DISABLE_VIDEOLAYER + bool "Force disable Videolayer when use vm" + depends on AMLOGIC_VIDEO_CAPTURE + default n + ---help--- + It will disable amvideo provider when enable this config + It will disable amvideo provider when enable this config + It will disable amvideo provider when enable this config + It will disable amvideo provider when enable this config + +config AMLOGIC_VIDEO_CAPTURE_PROBE + bool "Force check whether camera devices exist" + depends on AMLOGIC_VIDEO_CAPTURE + default n + ---help--- + Probe whether the camera devices exist by trying to read its + i2c port. It may cost some time, say Y here if you want it. + Probe whether the camera devices exist by trying to read its + i2c port. It may cost some time, say Y here if you want it. + +config AMLCAP_LOG_TIME_USEFORFRAMES + bool "Print Out The Time(ms) For Process A Frame" + depends on AMLOGIC_VIDEO_CAPTURE + default n + ---help--- + Print out the time used for process a frame, only for developers. + Print out the time used for process a frame, only for developers. + Print out the time used for process a frame, only for developers. + Print out the time used for process a frame, only for developers. + +config AMLOGIC_VIDEO_CAPTURE_GT2005 + tristate "Amlogic Platform Capture Driver for GT2005" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC0307 + tristate "Amlogic Platform Capture Driver for GC0307" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC0308 + tristate "Amlogic Platform Capture Driver for GC0308" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC0328 + tristate "Amlogic Platform Capture Driver for GC0328" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN_BT656IN + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC0329 + tristate "Amlogic Platform Capture Driver for GC0329" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC2015 + tristate "Amlogic Platform Capture Driver for GC2015" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC2035 + tristate "Amlogic Platform Capture Driver for GC2035" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC2155 + tristate "Amlogic Platform Capture Driver for GC2155" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_GC2145 + tristate "Amlogic Platform Capture Driver for GC2145" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_OV5640 + tristate "Amlogic Platform Capture Driver for OV5640" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_OV5642 + tristate "Amlogic Platform Capture Driver for OV5642" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +choice + prompt "OV5642 AUTO FOCUS FIRMWARE" + depends on AMLOGIC_VIDEO_CAPTURE_OV5642 + default NO_AUTO_FUCOS + +config NO_AUTO_FUCOS + bool "NONE" + ---help--- + no auto focus + no auto focus + no auto focus + no auto focus + +config AD5820 + bool "AD5820" + ---help--- + AD5820 + AD5820 + AD5820 + AD5820 + +config DW9714 + bool "DW9714" + ---help--- + DW9714 + DW9714 + DW9714 + DW9714 + +config AP5120 + bool "AP5120" + ---help--- + AP5120 + AP5120 + AP5120 + AP5120 + +endchoice + +config AMLOGIC_VIDEO_CAPTURE_OV7675 + tristate "Amlogic Platform Capture Driver for OV7675" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_OV2655 + tristate "Amlogic Platform Capture Driver for OV2655" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_SP0838 + tristate "Amlogic Platform Capture Driver for SP0838" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select VIDEOBUF_RESOURCE + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_SP2518 + tristate "Amlogic Platform Capture Driver for SP2518" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select VIDEOBUF_RESOURCE + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_SP0A19 + tristate "Amlogic Platform Capture Driver for SP0A19" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_SP1628 + tristate "Amlogic Platform Capture Driver for SP1628" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_HI253 + tristate "Amlogic Platform Capture Driver for HI253" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_HI704 + tristate "Amlogic Platform Capture Driver for HI704" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_HM2057 + tristate "Amlogic Platform Capture Driver for HM2057" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_HM5065 + tristate "Amlogic Platform Capture Driver for HM5065" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_HM1375 + tristate "Amlogic Platform Capture Driver for HM1375" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_OV3660 + tristate "Amlogic Platform Capture Driver for OV3660" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_OV5647 + tristate "Amlogic Platform Capture Driver for OV5647" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + + +config AMLOGIC_VIDEO_CAPTURE_HI2056 + tristate "Amlogic Platform Capture Driver for HI2056" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_MIPI + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_NT99250 + tristate "Amlogic Platform Capture Driver for NT99250" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_NT99252 + tristate "Amlogic Platform Capture Driver for NT99252" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_NT99340 + tristate "Amlogic Platform Capture Driver for NT99340" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_AR0543 + tristate "Amlogic Platform Capture Driver for AR0543" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEO_CAPTURE_AR0833 + tristate "Amlogic Platform Capture Driver for AR0833" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + + +config AMLOGIC_VIDEO_CAPTURE_BF3720 + tristate "Amlogic Platform Capture Driver for BF3720" + depends on AMLOGIC_VIDEO_CAPTURE + select VIDEOBUF_VMALLOC + select AMLOGIC_VIDEOIN_MANAGER + select TVIN + select TVIN_BT656 + select TVIN_VDIN + default n + ---help--- + Amlogic capture driver. + Say Y here if you want this driver. + Amlogic capture driver. + Say Y here if you want this driver. + +config AMLOGIC_VIDEOIN_MANAGER + tristate "amlogic video manager" + default n + ---help--- + this a test for video manager + +endmenu diff --git a/drivers/amlogic/media/camera/Makefile b/drivers/amlogic/media/camera/Makefile new file mode 100644 index 000000000000..04fb18c468d9 --- /dev/null +++ b/drivers/amlogic/media/camera/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the amlogic platform camera interface device drivers. +# +amlflash-objs := common/flashlight.o +amlcamera-objs := common/plat_ctrl.o +#common/util.o +amlvm-objs := common/vm.o +cam_prober-objs := common/cam_prober.o common/config_parser.o +gc2145dri-objs := gc2145.o + +obj-y += amlflash.o +obj-y += amlvm.o +obj-y += amlcamera.o +obj-y += cam_prober.o +obj-$(CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145) += gc2145dri.o diff --git a/drivers/amlogic/media/camera/common/cam_prober.c b/drivers/amlogic/media/camera/common/cam_prober.c new file mode 100644 index 000000000000..98fe53121c85 --- /dev/null +++ b/drivers/amlogic/media/camera/common/cam_prober.c @@ -0,0 +1,1792 @@ +/* + * drivers/amlogic/media/camera/common/cam_prober.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIG_ARCH_MESON8 + +static struct platform_device *cam_pdev; +static struct clk *cam_clk; +static unsigned int bt_path_count; + +static unsigned int camera0_pwdn_pin; +static unsigned int camera0_rst_pin; +static unsigned int camera1_pwdn_pin; +static unsigned int camera1_rst_pin; + +static struct aml_cam_info_s *temp_cam; + +static int aml_camera_read_buff(struct i2c_adapter *adapter, + unsigned short dev_addr, char *buf, + int addr_len, int data_len) +{ + int i2c_flag = -1; + struct i2c_msg msgs[] = {{ + .addr = dev_addr, .flags = 0, + .len = addr_len, .buf = buf, + }, { + .addr = dev_addr, .flags = I2C_M_RD, + .len = data_len, .buf = buf, + } + }; + + i2c_flag = i2c_transfer(adapter, msgs, 2); + + return i2c_flag; +} + +static int aml_camera_write_buff(struct i2c_adapter *adapter, + unsigned short dev_addr, char *buf, int len) +{ + struct i2c_msg msg[] = {{ + .addr = dev_addr, .flags = 0, /*I2C_M_TEN*/ + .len = len, .buf = buf, + } + }; + + if (i2c_transfer(adapter, msg, 1) < 0) + return -1; + else + return 0; +} + +static int aml_i2c_get_byte(struct i2c_adapter *adapter, + unsigned short dev_addr, unsigned short addr) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + + if (aml_camera_read_buff(adapter, dev_addr, buff, 2, 1) < 0) + return -1; + return buff[0]; +} + +static int aml_i2c_put_byte(struct i2c_adapter *adapter, + unsigned short dev_addr, unsigned short addr, + unsigned char data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + buff[2] = data; + if (aml_camera_write_buff(adapter, dev_addr, buff, 3) < 0) + return -1; + return 0; +} + +static int aml_i2c_get_byte_add8(struct i2c_adapter *adapter, + unsigned short dev_addr, + unsigned short addr) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)(addr & 0xff); + + if (aml_camera_read_buff(adapter, dev_addr, buff, 1, 1) < 0) + return -1; + return buff[0]; +} + +static int aml_i2c_put_byte_add8(struct i2c_adapter *adapter, + unsigned short dev_addr, + unsigned short addr, unsigned char data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)(addr & 0xff); + buff[1] = data; + if (aml_camera_write_buff(adapter, dev_addr, buff, 2) < 0) + return -1; + return 0; +} + +int aml_i2c_put_word(struct i2c_adapter *adapter, unsigned short dev_addr, + unsigned short addr, unsigned short data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + buff[2] = (unsigned char)((data >> 8) & 0xff); + buff[3] = (unsigned char)(data & 0xff); + if (aml_camera_write_buff(adapter, dev_addr, buff, 4) < 0) + return -1; + return 0; +} + +static int aml_i2c_get_word(struct i2c_adapter *adapter, + unsigned short dev_addr, unsigned short addr) +{ + int ret; + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + if (aml_camera_read_buff(adapter, dev_addr, buff, 2, 2) < 0) + return -1; + ret = (buff[0] << 8) | (buff[1]); + return ret; +} + +static int aml_i2c_get_word_add8(struct i2c_adapter *adapter, + unsigned short dev_addr, + unsigned short addr) +{ + int ret; + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + if (aml_camera_read_buff(adapter, dev_addr, buff, 2, 2) < 0) + return -1; + ret = buff[0] | (buff[1] << 8); + return ret; +} + +static int aml_i2c_put_word_add8(struct i2c_adapter *adapter, + unsigned short dev_addr, unsigned char addr, + unsigned short data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)(addr & 0xff); + buff[1] = (unsigned char)(data >> 8 & 0xff); + buff[2] = (unsigned char)(data & 0xff); + if (aml_camera_write_buff(adapter, dev_addr, buff, 3) < 0) + return -1; + return 0; +} + + +extern struct i2c_client * +i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0307 +int gc0307_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x21, 0x00); + if (reg == 0x99) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0308 +int gc0308_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x21, 0x00); + if (reg == 0x9b) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0328 +int gc0328_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x21, 0xf0); + if (reg == 0x9d) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0329 +int gc0329_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + aml_i2c_put_byte_add8(adapter, 0x31, 0xfc, 0x16); /*select page 0*/ + reg = aml_i2c_get_byte_add8(adapter, 0x31, 0x00); + if (reg == 0xc0) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2015 +int gc2015_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x30, 0x00); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x30, 0x01); + if (reg[0] == 0x20 && reg[1] == 0x05) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM2057 +int hm2057_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x24, 0x0001); + reg[1] = aml_i2c_get_byte(adapter, 0x24, 0x0002); + if (reg[0] == 0x20 && reg[1] == 0x56) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2035 +int gc2035_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf0); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf1); + if (reg[0] == 0x20 && reg[1] == 0x35) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2155 +int gc2155_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf0); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf1); + if (reg[0] == 0x21 && reg[1] == 0x55) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GT2005 +int gt2005_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x0000); + reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x0001); + if (reg[0] == 0x51 && reg[1] == 0x38) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV2659 +int ov2659_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x30, 0x300a); + reg[1] = aml_i2c_get_byte(adapter, 0x30, 0x300b); + if (reg[0] == 0x26 && reg[1] == 0x56) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3640 +int ov3640_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); + reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); + if (reg[0] == 0x36 && reg[1] == 0x4c) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3660 +int ov3660_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); + reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); + if (reg[0] == 0x36 && reg[1] == 0x60) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5640 +int ov5640_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); + reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); + if (reg[0] == 0x56 && reg[1] == 0x40) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5642 +int ov5642_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x3c, 0x300a); + reg[1] = aml_i2c_get_byte(adapter, 0x3c, 0x300b); + if (reg[0] == 0x56 && reg[1] == 0x42) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV7675 +int ov7675_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x21, 0x0a); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x21, 0x0b); + if (reg[0] == 0x76 && reg[1] == 0x73) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0A19 +int sp0a19_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x21, 0x02); + if (reg == 0xa6) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP2518 +int sp2518_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x30, 0x02); + pr_info("sp2518 chip id reg = %x .\n", reg); + if (reg == 0x53) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0838 +int sp0838_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x18, 0x02); + if (reg == 0x27) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI253 +int hi253_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg; + + reg = aml_i2c_get_byte_add8(adapter, 0x20, 0x04); + if (reg == 0x92) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM5065 +int hm5065_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x1F, 0x0000); + reg[1] = aml_i2c_get_byte(adapter, 0x1F, 0x0001); + if (reg[0] == 0x03 && reg[1] == 0x9e) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM1375 +int hm1375_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x24, 0x0001); + reg[1] = aml_i2c_get_byte(adapter, 0x24, 0x0002); + pr_info("hm1375_v4l2_probe: device ID: 0x%x%x", reg[0], reg[1]); + if ((reg[0] == 0x13 || reg[0] == 0x03) && reg[1] == 0x75) + ret = 1; + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI2056 +int hi2056_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x24, 0x0001); + reg[1] = aml_i2c_get_byte(adapter, 0x24, 0x0002); + pr_info("reg[0]=%x, reg[1]=%x\n", reg[0], reg[1]); + if (reg[0] == 0x20 && reg[1] == 0x56) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5647 +int ov5647_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte(adapter, 0x36, 0x300a); + reg[1] = aml_i2c_get_byte(adapter, 0x36, 0x300b); + pr_info("reg[0]:%x,reg[1]:%x\n", reg[0], reg[1]); + if (reg[0] == 0x56 && reg[1] == 0x47) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0543 +int ar0543_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0, reg_val; + + reg_val = aml_i2c_get_word(adapter, 0x36, 0x3000); + pr_info("reg:0x%x\n", reg_val); + if (reg_val == 0x4800) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0833 +int ar0833_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0, reg_val; + + reg_val = aml_i2c_get_word(adapter, 0x36, 0x3000); + pr_info("reg:0x%x\n", reg_val); + if (reg_val == 0x4B03) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP1628 +int sp1628_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0x02); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xa0); + if (reg[0] == 0x16 && reg[1] == 0x28) + ret = 1; + return ret; +} +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3720 +int bf3720_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfc); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfd); + if (reg[0] == 0x37 && reg[1] == 0x20) + ret = 1; + return ret; +} +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3703 +int __init bf3703_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfc); /*i2c addr:0x6f*/ + reg[1] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfd); + if (reg[0] == 0x37 && reg[1] == 0x03) + ret = 1; + return ret; +} +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3920 +int __init bf3920_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfc); /*i2c addr:0x6f*/ + reg[1] = aml_i2c_get_byte_add8(adapter, 0x6e, 0xfd); + if (reg[0] == 0x39 && reg[1] == 0x20) + ret = 1; + return ret; +} +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145 +int __init gc2145_v4l2_probe(struct i2c_adapter *adapter) +{ + int ret = 0; + unsigned char reg[2]; + + reg[0] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf0); + reg[1] = aml_i2c_get_byte_add8(adapter, 0x3c, 0xf1); + /*datasheet chip id is error*/ + if (reg[0] == 0x21 && reg[1] == 0x45) + ret = 1; + pr_info("%s, ret = %d\n", __func__, ret); + return ret; +} +#endif + +struct aml_cam_dev_info_s { + unsigned char addr; + char *name; + unsigned char pwdn; + enum resolution_size max_cap_size; + aml_cam_probe_fun_t probe_func; +}; + +static const struct aml_cam_dev_info_s cam_devs[] = { +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0307 + { + .addr = 0x21, + .name = "gc0307", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = gc0307_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0308 + { + .addr = 0x21, + .name = "gc0308", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = gc0308_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0328 + { + .addr = 0x21, + .name = "gc0328", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = gc0328_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC0329 + { + .addr = 0x31, + .name = "gc0329", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = gc0329_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2015 + { + .addr = 0x30, + .name = "gc2015", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = gc2015_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM2057 + { + .addr = 0x24, + .name = "hm2057", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = hm2057_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2035 + { + .addr = 0x3c, + .name = "gc2035", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = gc2035_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2155 + { + .addr = 0x3c, + .name = "gc2155", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = gc2155_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GT2005 + { + .addr = 0x3c, + .name = "gt2005", + .pwdn = 0, + .max_cap_size = SIZE_1600X1200, + .probe_func = gt2005_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV2659 + { + .addr = 0x30, + .name = "ov2659", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = ov2659_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3640 + { + .addr = 0x3c, + .name = "ov3640", + .pwdn = 1, + .max_cap_size = SIZE_2048X1536; + .probe_func = ov3640_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV3660 + { + .addr = 0x3c, + .name = "ov3660", + .pwdn = 1, + .max_cap_size = SIZE_2048X1536, + .probe_func = ov3660_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5640 + { + .addr = 0x3c, + .name = "ov5640", + .pwdn = 1, + .max_cap_size = SIZE_2592X1944, + .probe_func = ov5640_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5642 + { + .addr = 0x3c, + .name = "ov5642", + .pwdn = 1, + .max_cap_size = SIZE_2592X1944, + .probe_func = ov5642_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV5647 + { + .addr = 0x36, /* really value should be 0x6c */ + .name = "ov5647", .pwdn = 1, .max_cap_size = SIZE_2592X1944, + .probe_func = ov5647_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_OV7675 + { + .addr = 0x21, + .name = "ov7675", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = ov7675_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0A19 + { + .addr = 0x21, + .name = "sp0a19", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = sp0a19_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP0838 + { + .addr = 0x18, + .name = "sp0838", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = sp0838_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP2518 + { + .addr = 0x30, + .name = "sp2518", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = sp2518_v4l2_probe, + }, +#endif + +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI253 + { + .addr = 0x20, + .name = "hi253", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = hi253_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM5065 + { + .addr = 0x1f, + .name = "hm5065", + .pwdn = 0, + .max_cap_size = SIZE_2592X1944, + .probe_func = hm5065_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HM1375 + { + .addr = 0x24, + .name = "hm1375", + .pwdn = 1, + .max_cap_size = SIZE_1280X1024, + .probe_func = hm1375_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_HI2056 + { + .addr = 0x24, + .name = "mipi-hi2056", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = hi2056_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0543 + { + .addr = 0x36, + .name = "ar0543", + .pwdn = 0, + .max_cap_size = SIZE_2592X1944, + .probe_func = ar0543_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_AR0833 + { + .addr = 0x36, + .name = "ar0833", + .pwdn = 0, + .max_cap_size = SIZE_2592X1944, + .probe_func = ar0833_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_SP1628 + { + .addr = 0x3c, + .name = "sp1628", + .pwdn = 1, + .max_cap_size = SIZE_1280X960, + .probe_func = sp1628_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3720 + { + .addr = 0x6e, + .name = "bf3720", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = bf3720_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3703 + { + .addr = 0x6e, + .name = "bf3703", + .pwdn = 1, + .max_cap_size = SIZE_640X480, + .probe_func = bf3703_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_BF3920 + { + .addr = 0x6e, + .name = "bf3920", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = bf3920_v4l2_probe, + }, +#endif +#ifdef CONFIG_AMLOGIC_VIDEO_CAPTURE_GC2145 + { + .addr = 0x3c, + .name = "gc2145", + .pwdn = 1, + .max_cap_size = SIZE_1600X1200, + .probe_func = gc2145_v4l2_probe, + }, +#endif +}; + +static const struct aml_cam_dev_info_s *get_cam_info_by_name(const char *name) +{ + int i; + + if (!name) + return NULL; + /*pr_info("cam_devs num is %d\n", ARRAY_SIZE(cam_devs));*/ + for (i = 0; i < ARRAY_SIZE(cam_devs); i++) { + if (!strcmp(name, cam_devs[i].name)) { + pr_info("camera dev %s found\n", cam_devs[i].name); + pr_info("camera i2c addr: 0x%x\n", cam_devs[i].addr); + return &cam_devs[i]; + } + } + return NULL; +} + +struct res_item { + enum resolution_size size; + char *name; +}; + +static const struct res_item res_item_array[] = { + {SIZE_320X240, "320X240"}, { + SIZE_640X480, "640X480" + }, {SIZE_720X405, "720X405"}, { + SIZE_800X600, "800X600" + }, {SIZE_960X540, "960X540"}, { + SIZE_1024X576, "1024X576" + }, {SIZE_960X720, "960X720"}, { + SIZE_1024X768, "1024X768" + }, {SIZE_1280X720, "1280X720"}, { + SIZE_1152X864, "1152X864" + }, {SIZE_1366X768, "1366X768"}, { + SIZE_1280X960, "1280X960" + }, {SIZE_1280X1024, "1280X1024"}, { + SIZE_1400X1050, "1400X1050" + }, {SIZE_1600X900, "1600X900"}, { + SIZE_1600X1200, "1600X1200" + }, {SIZE_1920X1080, "1920X1080"}, { + SIZE_1792X1344, "1792X1344" + }, {SIZE_2048X1152, "2048X1152"}, { + SIZE_2048X1536, "2048X1536" + }, {SIZE_2304X1728, "2304X1728"}, { + SIZE_2560X1440, "2560X1440" + }, {SIZE_2592X1944, "2592X1944"}, { + SIZE_3072X1728, "3072X1728" + }, {SIZE_2816X2112, "2816X2112"}, { + SIZE_3072X2304, "3072X2304" + }, {SIZE_3200X2400, "3200X2400"}, { + SIZE_3264X2448, "3264X2448" + }, {SIZE_3840X2160, "3840X2160"}, { + SIZE_3456X2592, "3456X2592" + }, {SIZE_3600X2700, "3600X2700"}, { + SIZE_4096X2304, "4096X2304" + }, {SIZE_3672X2754, "3672X2754"}, { + SIZE_3840X2880, "3840X2880" + }, {SIZE_4000X3000, "4000X3000"}, { + SIZE_4608X2592, "4608X2592" + }, {SIZE_4096X3072, "4096X3072"}, { + SIZE_4800X3200, "4800X3200" + }, {SIZE_5120X2880, "5120X2880"}, { + SIZE_5120X3840, "5120X3840" + }, {SIZE_6400X4800, "6400X480"}, + +}; + +static enum resolution_size get_res_size(const char *res_str) +{ + enum resolution_size ret = SIZE_NULL; + const struct res_item *item; + int i; + + if (!res_str) + return SIZE_NULL; + for (i = 0; i < ARRAY_SIZE(res_item_array); i++) { + item = &res_item_array[i]; + if (!strcmp(item->name, res_str)) { + ret = item->size; + return ret; + } + } + + return ret; +} + +static inline void GXBB_cam_enable_clk(void) +{ + struct clk *clk; + + clk = clk_get(&cam_pdev->dev, "clk_camera_24"); + if (IS_ERR(clk)) { + pr_info("cannot get camera m-clock\n"); + clk = NULL; + } else { + cam_clk = clk; + clk_prepare_enable(clk); + } +} + +static inline void GXBB_cam_disable_clk(int spread_spectrum) +{ + if (cam_clk) { + clk_disable_unprepare(cam_clk); + clk_put(cam_clk); + } +} + +static inline void GX12_cam_enable_clk(void) +{ + struct clk *clk; + unsigned long clk_rate; + + clk = devm_clk_get(&cam_pdev->dev, "g12a_24m"); + if (IS_ERR(clk)) { + pr_info("cannot get camera m-clock\n"); + clk = NULL; + } else { + cam_clk = clk; + clk_set_rate(clk, 24000000); + clk_prepare_enable(clk); + clk_rate = clk_get_rate(clk); + } +} + +static inline void GX12_cam_disable_clk(int spread_spectrum) +{ + if (cam_clk) { + clk_disable_unprepare(cam_clk); + devm_clk_put(&cam_pdev->dev, cam_clk); + pr_info("Success disable mclk\n"); + } +} + +static inline void cam_enable_clk(int clk, int spread_spectrum) +{ + pr_err("camera mclk enable failed, unsupport chip\n"); +} + +static inline void cam_disable_clk(int spread_spectrum) +{ + pr_err("camera mclk disable failed, unsupport chip\n"); +} + +/*static struct platform_device *cam_pdev;*/ + +void aml_cam_init(struct aml_cam_info_s *cam_dev) +{ + /*select XTAL as camera clock*/ + if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) + GXBB_cam_enable_clk(); + else if ((get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) || + (get_cpu_type() == MESON_CPU_MAJOR_ID_G12B)) + GX12_cam_enable_clk(); + else + cam_enable_clk(cam_dev->mclk, cam_dev->spread_spectrum); + + /*coding style need: msleep < 20ms can sleep for up to 20ms*/ + msleep(20); + /*set camera power enable*/ + if (!cam_dev->front_back) { + cam_dev->pwdn_pin = camera0_pwdn_pin; + cam_dev->rst_pin = camera0_rst_pin; + } else { + cam_dev->pwdn_pin = camera1_pwdn_pin; + cam_dev->rst_pin = camera1_rst_pin; + } + + gpio_direction_output(cam_dev->pwdn_pin, cam_dev->pwdn_act); + + msleep(20); + + gpio_direction_output(cam_dev->pwdn_pin, !(cam_dev->pwdn_act)); + + msleep(20); + + gpio_direction_output(cam_dev->rst_pin, 0); + + msleep(20); + + gpio_direction_output(cam_dev->rst_pin, 1); + + msleep(20); + + pr_info("aml_cams: %s init OK\n", cam_dev->name); + +} + +void aml_cam_uninit(struct aml_cam_info_s *cam_dev) +{ + int ret; + + pr_info("aml_cams: %s uninit.\n", cam_dev->name); + /*set camera power disable*/ + /*coding style need: msleep < 20ms can sleep for up to 20ms*/ + /*msleep(20);*/ + + ret = gpio_direction_output(cam_dev->pwdn_pin, cam_dev->pwdn_act); + if (ret < 0) + pr_info("aml_cam_uninit pwdn_pin output pwdn_act failed\n"); + + msleep(20); + + ret = gpio_direction_output(cam_dev->rst_pin, 0); + if (ret < 0) + pr_info("aml_cam_uninit rst_pin output rst_pin failed\n"); + + msleep(20); + + if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) + GXBB_cam_disable_clk(cam_dev->spread_spectrum); + else if ((get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) || + (get_cpu_type() == MESON_CPU_MAJOR_ID_G12B)) + GX12_cam_disable_clk(cam_dev->spread_spectrum); + else + cam_disable_clk(cam_dev->spread_spectrum); +} + +void aml_cam_flash(struct aml_cam_info_s *cam_dev, int is_on) +{ + int ret; + + if (cam_dev->flash_support) { + pr_info("aml_cams: %s flash %s.\n", + cam_dev->name, is_on ? "on" : "off"); + + ret = gpio_direction_output(cam_dev->flash_ctrl_pin, + cam_dev->flash_ctrl_level ? is_on : !is_on); + if (ret < 0) + pr_info("aml_cam_flash flash_ctrl_pin output failed\n"); + } +} + +void aml_cam_torch(struct aml_cam_info_s *cam_dev, int is_on) +{ + int ret; + + if (cam_dev->torch_support) { + pr_info("aml_cams: %s torch %s.\n", + cam_dev->name, is_on ? "on" : "off"); + + ret = gpio_direction_output(cam_dev->torch_ctrl_pin, + cam_dev->torch_ctrl_level ? is_on : !is_on); + if (ret < 0) + pr_info("aml_cam_torch torch_ctrl_pin output failed\n"); + } +} + +static struct list_head cam_head = LIST_HEAD_INIT(cam_head); + +#define DEBUG_DUMP_CAM_INFO + +static int fill_csi_dev(struct device_node *p_node, + struct aml_cam_info_s *cam_dev) +{ + const char *str; + int ret = 0; + + ret = of_property_read_string(p_node, "clk_channel", &str); + if (ret) { + pr_info("failed to read clock channel, \"a or b\"\n"); + cam_dev->clk_channel = CLK_CHANNEL_A; + } else { + pr_info("clock channel:clk %s\n", str); + if (strncmp("a", str, 1) == 0) + cam_dev->clk_channel = CLK_CHANNEL_A; + else + cam_dev->clk_channel = CLK_CHANNEL_B; + } + + return ret; + +} +static int fill_cam_dev(struct device_node *p_node, + struct aml_cam_info_s *cam_dev) +{ + const char *str; + int ret = 0; + const struct aml_cam_dev_info_s *cam_info = NULL; + struct device_node *adapter_node = NULL; + struct i2c_adapter *adapter = NULL; + unsigned int mclk = 0; + unsigned int vcm_mode = 0; + + if (!p_node || !cam_dev) + return -1; + + ret = of_property_read_u32(p_node, "front_back", &cam_dev->front_back); + if (ret) { + pr_info("get camera name failed!\n"); + goto err_out; + } + + ret = of_property_read_string(p_node, "cam_name", &cam_dev->name); + if (ret) { + pr_info("get camera name failed!\n"); + goto err_out; + } + + cam_dev->pwdn_pin = of_get_named_gpio(p_node, "gpio_pwdn-gpios", 0); + if (cam_dev->pwdn_pin == 0) { + pr_info("%s: failed to map gpio_pwdn !\n", cam_dev->name); + goto err_out; + } + + ret = gpio_request(cam_dev->pwdn_pin, "camera"); + if (ret < 0) + pr_info("aml_cam_init pwdn_pin request failed\n"); + + if (!cam_dev->front_back) + camera0_pwdn_pin = cam_dev->pwdn_pin; + else + camera1_pwdn_pin = cam_dev->pwdn_pin; + + cam_dev->rst_pin = of_get_named_gpio(p_node, "gpio_rst-gpios", 0); + if (cam_dev->rst_pin == 0) { + pr_info("%s: failed to map gpio_rst !\n", cam_dev->name); + goto err_out; + } + ret = gpio_request(cam_dev->rst_pin, "camera"); + if (ret < 0) + pr_info("aml_cam_init rst_pin request failed\n"); + + if (!cam_dev->front_back) + camera0_rst_pin = cam_dev->rst_pin; + else + camera1_rst_pin = cam_dev->rst_pin; + + cam_info = get_cam_info_by_name(cam_dev->name); + if (cam_info == NULL) { + pr_info("camera %s is not support\n", cam_dev->name); + ret = -1; + goto err_out; + } + + of_property_read_u32(p_node, "spread_spectrum", + &cam_dev->spread_spectrum); + + ret = of_property_read_string(p_node, "bt_path", &str); + if (ret) { + pr_info("failed to read bt_path\n"); + cam_dev->bt_path = BT_PATH_GPIO; + } else { + pr_info("bt_path :%d\n", cam_dev->bt_path); + if (strncmp("csi", str, 3) == 0) + cam_dev->bt_path = BT_PATH_CSI2; + else if (strncmp("gpio_b", str, 6) == 0) + cam_dev->bt_path = BT_PATH_GPIO_B; + else + cam_dev->bt_path = BT_PATH_GPIO; + } + of_property_read_u32(p_node, "bt_path_count", &cam_dev->bt_path_count); + bt_path_count = cam_dev->bt_path_count; + + cam_dev->pwdn_act = cam_info->pwdn; + cam_dev->i2c_addr = cam_info->addr; + pr_info("camer addr: 0x%x\n", cam_dev->i2c_addr); + pr_info("camer i2c bus: %d\n", cam_dev->i2c_bus_num); + + adapter_node = of_parse_phandle(p_node, "camera-i2c-bus", 0); + if (adapter_node) { + adapter = of_find_i2c_adapter_by_node(adapter_node); + of_node_put(adapter_node); + if (adapter == NULL) { + pr_err("%s, failed parse camera-i2c-bus\n", + __func__); + return -1; + } + } + + if (adapter && cam_info->probe_func) { + aml_cam_init(cam_dev); + if (cam_info->probe_func(adapter) != 1) { + pr_info("camera %s not on board\n", cam_dev->name); + ret = -1; + aml_cam_uninit(cam_dev); + goto err_out; + } + aml_cam_uninit(cam_dev); + } else { + pr_err("can not do probe function\n"); + ret = -1; + goto err_out; + } + + of_property_read_u32(p_node, "mirror_flip", &cam_dev->m_flip); + of_property_read_u32(p_node, "vertical_flip", &cam_dev->v_flip); + of_property_read_u32(p_node, "vdin_path", &cam_dev->vdin_path); + + ret = of_property_read_string(p_node, "max_cap_size", &str); + if (ret) + pr_info("failed to read max_cap_size\n"); + else { + pr_info("max_cap_size :%s\n", str); + cam_dev->max_cap_size = get_res_size(str); + } + if (cam_dev->max_cap_size == SIZE_NULL) + cam_dev->max_cap_size = cam_info->max_cap_size; + + ret = of_property_read_u32(p_node, "mclk", &mclk); + if (ret) + cam_dev->mclk = 24000; + else + cam_dev->mclk = mclk; + + ret = of_property_read_u32(p_node, "vcm_mode", &vcm_mode); + if (ret) + cam_dev->vcm_mode = 0; + else + cam_dev->vcm_mode = vcm_mode; + pr_info("vcm mode is %d\n", cam_dev->vcm_mode); + + ret = of_property_read_u32(p_node, "flash_support", + &cam_dev->flash_support); + if (cam_dev->flash_support) { + of_property_read_u32(p_node, "flash_ctrl_level", + &cam_dev->flash_ctrl_level); + ret = of_property_read_string(p_node, "flash_ctrl_pin", &str); + if (ret) { + pr_info("%s: failed to get flash_ctrl_pin!\n", + cam_dev->name); + cam_dev->flash_support = 0; + } else { + cam_dev->flash_ctrl_pin = of_get_named_gpio(p_node, + "flash_ctrl_pin", 0); + if (cam_dev->flash_ctrl_pin == 0) { + pr_info("%s: failed to map flash_ctrl_pin !\n", + cam_dev->name); + cam_dev->flash_support = 0; + cam_dev->flash_ctrl_level = 0; + } + ret = gpio_request(cam_dev->flash_ctrl_pin, "camera"); + if (ret < 0) + pr_info("camera flash_ctrl_pin request failed\n"); + } + } + + ret = of_property_read_u32(p_node, "torch_support", + &cam_dev->torch_support); + if (cam_dev->torch_support) { + of_property_read_u32(p_node, "torch_ctrl_level", + &cam_dev->torch_ctrl_level); + ret = of_property_read_string(p_node, "torch_ctrl_pin", &str); + if (ret) { + pr_info("%s: failed to get torch_ctrl_pin!\n", + cam_dev->name); + cam_dev->torch_support = 0; + } else { + cam_dev->torch_ctrl_pin = of_get_named_gpio(p_node, + "torch_ctrl_level", 0); + ret = gpio_request(cam_dev->torch_ctrl_pin, "camera"); + if (ret < 0) + pr_info("camera torch_ctrl_pin request failed\n"); + } + } + + ret = of_property_read_string(p_node, "interface", &str); + if (ret) { + pr_info("failed to read camera interface \"mipi or dvp\"\n"); + cam_dev->interface = CAM_DVP; + } else { + pr_info("camera interface:%s\n", str); + if (strncmp("dvp", str, 1) == 0) + cam_dev->interface = CAM_DVP; + else + cam_dev->interface = CAM_MIPI; + } + if (cam_dev->interface == CAM_MIPI) { + ret = fill_csi_dev(p_node, cam_dev); + if (ret < 0) + goto err_out; + } + + ret = of_property_read_string(p_node, "bayer_fmt", &str); + if (ret) { + pr_info("failed to read camera bayer fmt\n"); + cam_dev->bayer_fmt = TVIN_GBRG; + } else { + pr_info("color format:%s\n", str); + if (strncmp("BGGR", str, 4) == 0) + cam_dev->bayer_fmt = TVIN_BGGR; + else if (strncmp("RGGB", str, 4) == 0) + cam_dev->bayer_fmt = TVIN_RGGB; + else if (strncmp("GBRG", str, 4) == 0) + cam_dev->bayer_fmt = TVIN_GBRG; + else if (strncmp("GRBG", str, 4) == 0) + cam_dev->bayer_fmt = TVIN_GRBG; + else + cam_dev->bayer_fmt = TVIN_GBRG; + } + + ret = of_property_read_string(p_node, "config_path", &cam_dev->config); + if (ret) + pr_info("failed to read config_file path\n"); + else + pr_info("config path :%s\n", cam_dev->config); + +#ifdef DEBUG_DUMP_CAM_INFO + pr_info("=======cam %s info=======\n" + "i2c_bus_num: %d\n" + "pwdn_act: %d\n" + "front_back: %d\n" + "m_flip: %d\n" + "v_flip: %d\n" + "i2c_addr: 0x%x\n" + "config path:%s\n" + "bt_path:%d\n", + cam_dev->name, cam_dev->i2c_bus_num, cam_dev->pwdn_act, + cam_dev->front_back, cam_dev->m_flip, cam_dev->v_flip, + cam_dev->i2c_addr, cam_dev->config, cam_dev->bt_path); +#endif /* DEBUG_DUMP_CAM_INFO */ + + ret = 0; + +err_out: + return ret; +} + +static int do_read_work(char argn, char **argv) +{ + unsigned int dev_addr, reg_addr, data_len = 1, result; + unsigned int i2c_bus; + struct i2c_adapter *adapter; + + if (argn < 4) { + pr_err("args num error"); + return -1; + } + + if (!strncmp(argv[1], "i2c_bus_ao", 9)) + i2c_bus = 4; + else if (!strncmp(argv[1], "i2c_bus_0", 9)) + i2c_bus = 0; + else if (!strncmp(argv[1], "i2c_bus_1", 9)) + i2c_bus = 1; + else if (!strncmp(argv[1], "i2c_bus_2", 9)) + i2c_bus = 2; + else if (!strncmp(argv[1], "i2c_bus_3", 9)) + i2c_bus = 3; + else { + pr_err("bus name error!\n"); + return -1; + } + + adapter = i2c_get_adapter(i2c_bus); + + if (adapter == NULL) { + pr_info("no adapter!\n"); + return -1; + } + + dev_addr = kstrtol(argv[2], 16, NULL); + reg_addr = kstrtol(argv[3], 16, NULL); + if (argn == 5) { + pr_info("argv[4] is %s\n", argv[4]); + data_len = kstrtol(argv[4], 16, NULL); + } + + if (reg_addr > 256) { + if (data_len != 2) { + result = aml_i2c_get_byte(adapter, dev_addr, reg_addr); + pr_info("register [0x%04x]=0x%02x\n", reg_addr, result); + } else { + result = aml_i2c_get_word(adapter, dev_addr, reg_addr); + pr_info("register [0x%04x]=0x%04x\n", reg_addr, result); + } + } else { + if (data_len != 2) { + result = aml_i2c_get_byte_add8(adapter, + dev_addr, reg_addr); + pr_info("register [0x%02x]=0x%02x\n", reg_addr, result); + } else { + result = aml_i2c_get_word_add8(adapter, + dev_addr, reg_addr); + pr_info("register [0x%02x]=0x%04x\n", reg_addr, result); + } + } + + return 0; +} + +static int do_write_work(char argn, char **argv) +{ + unsigned int dev_addr, reg_addr, reg_val, data_len = 1, ret = 0; + unsigned int i2c_bus; + struct i2c_adapter *adapter; + + if (argn < 5) { + pr_err("args num error"); + return -1; + } + + if (!strncmp(argv[1], "i2c_bus_0", 9)) + i2c_bus = 0; + else if (!strncmp(argv[1], "i2c_bus_1", 9)) + i2c_bus = 1; + else if (!strncmp(argv[1], "i2c_bus_2", 9)) + i2c_bus = 2; + else if (!strncmp(argv[1], "i2c_bus_3", 9)) + i2c_bus = 3; + else if (!strncmp(argv[1], "i2c_bus_ao", 9)) + i2c_bus = 4; + else { + pr_err("bus name error!\n"); + return -1; + } + + adapter = i2c_get_adapter(i2c_bus); + + if (adapter == NULL) { + pr_info("no adapter!\n"); + return -1; + } + + dev_addr = kstrtol(argv[2], 16, NULL); + reg_addr = kstrtol(argv[3], 16, NULL); + reg_val = kstrtol(argv[4], 16, NULL); + if (argn == 6) + data_len = kstrtol(argv[5], 16, NULL); + if (reg_addr > 256) { + if (data_len != 2) { + if (aml_i2c_put_byte(adapter, dev_addr, + reg_addr, reg_val) < 0) { + pr_err("write error\n"); + ret = -1; + } else { + pr_info("write ok\n"); + ret = 0; + } + } else { + if (aml_i2c_put_word(adapter, dev_addr, + reg_addr, reg_val) < 0) { + pr_err("write error\n"); + ret = -1; + } else { + pr_info("write ok\n"); + ret = 0; + } + } + } else { + if (data_len != 2) { + if (aml_i2c_put_byte_add8(adapter, dev_addr, + reg_addr, reg_val) < 0) { + pr_err("write error\n"); + ret = -1; + } else { + pr_info("write ok\n"); + ret = 0; + } + } else { + if (aml_i2c_put_word_add8(adapter, dev_addr, + reg_addr, reg_val) < 0) { + pr_err("write error\n"); + ret = -1; + } else { + pr_info("write ok\n"); + ret = 0; + } + } + } + + return ret; +} + +static struct class *cam_clsp; + +static ssize_t show_help(struct class *class, struct class_attribute *attr, + char *buf) +{ + ssize_t size = 0; + + pr_info( + "echo [read | write] i2c_bus_type device_address register_address [value] [data_len] > i2c_debug\n" + "i2c_bus_type are: i2c_bus_ao, i2c_bus_a, i2c_bus_b, i2c_bus_c, i2c_bus_d\n" + "e.g.: echo read i2c_bus_ao 0x3c 0x18 1\n" + " echo write i2c_bus_ao 0x3c 0x18 0x24 1\n"); + return size; +} + +static ssize_t store_i2c_debug(struct class *class, + struct class_attribute *attr, const char *buf, + size_t count) +{ + int argn; + char *buf_work, *p, *para; + char cmd; + char *argv[6]; + + buf_work = kstrdup(buf, GFP_KERNEL); + p = buf_work; + + for (argn = 0; argn < 6; argn++) { + para = strsep(&p, " "); + if (para == NULL) + break; + argv[argn] = para; + pr_info("argv[%d] = %s\n", argn, para); + } + + if (argn < 4 || argn > 6) + goto end; + + cmd = argv[0][0]; + switch (cmd) { + case 'r': + case 'R': + do_read_work(argn, argv); + break; + case 'w': + case 'W': + do_write_work(argn, argv); + break; + } + return count; +end: + pr_err("error command!\n"); + kfree(buf_work); + return -EINVAL; +} + +static LIST_HEAD(info_head); + +static ssize_t cam_info_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + struct list_head *p; + struct aml_cam_info_s *cam_info = NULL; + int count = 0; + + if (!list_empty(&info_head)) { + count += sprintf(&buf[count], + "name\t\tversion\t\t\t\tface_dir\t" + "i2c_addr\n"); + list_for_each(p, &info_head) { + cam_info = list_entry(p, struct aml_cam_info_s, + info_entry); + } + } + return count; +} + +static struct class_attribute aml_cam_attrs[] = { + __ATTR(i2c_debug, 0644, show_help, store_i2c_debug), + __ATTR_RO(cam_info), __ATTR(help, 0644, show_help, NULL), + __ATTR_NULL, +}; + +int aml_cam_info_reg(struct aml_cam_info_s *cam_info) +{ + int ret = -1; + + if (cam_info) { + list_add(&cam_info->info_entry, &info_head); + ret = 0; + } + return ret; +} + +int aml_cam_info_unreg(struct aml_cam_info_s *cam_info) +{ + int ret = -1; + struct list_head *p, *n; + struct aml_cam_info_s *tmp_info = NULL; + + if (cam_info) { + list_for_each_safe(p, n, &info_head) { + tmp_info = list_entry(p, struct aml_cam_info_s, + info_entry); + if (tmp_info == cam_info) { + list_del(p); + return 0; + } + } + } + return ret; +} + +static int aml_cams_probe(struct platform_device *pdev) +{ + struct device_node *cams_node = pdev->dev.of_node; + struct device_node *child; + struct i2c_board_info board_info; + struct i2c_adapter *adapter = NULL; + struct device_node *adapter_node = NULL; + struct timeval camera_start; + struct timeval camera_end; + int i; + unsigned long time_use = 0; + + temp_cam = kzalloc(sizeof(struct aml_cam_info_s), GFP_KERNEL); + if (!temp_cam) + return -ENOMEM; + + cam_pdev = pdev; + do_gettimeofday(&camera_start); + for_each_child_of_node(cams_node, child) { + + memset(temp_cam, 0, sizeof(struct aml_cam_info_s)); + + if (fill_cam_dev(child, temp_cam)) + continue; + + /*register exist camera*/ + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, temp_cam->name, I2C_NAME_SIZE); + + adapter_node = of_parse_phandle(child, "camera-i2c-bus", 0); + if (adapter_node) { + adapter = of_get_i2c_adapter_by_node(adapter_node); + of_node_put(adapter_node); + if (adapter == NULL) { + pr_err("%s, failed parse camera-i2c-bus\n", + __func__); + return -1; + } + } else { + pr_err("adapter node is NULL.\n"); + return -1; + } + board_info.addr = temp_cam->i2c_addr; + board_info.platform_data = temp_cam; + pr_info("new i2c device\n"); + /*i2c_new_existing_device(adapter, &board_info)*/ + i2c_new_device(adapter, &board_info); + } + do_gettimeofday(&camera_end); + time_use = (camera_end.tv_sec - camera_start.tv_sec) * 1000 + + (camera_end.tv_usec - camera_start.tv_usec) / 1000; + pr_info("camera probe cost time = %ldms\n", time_use); + + pr_info("aml probe finish\n"); + cam_clsp = class_create(THIS_MODULE, "aml_camera"); + for (i = 0; aml_cam_attrs[i].attr.name; i++) { + if (class_create_file(cam_clsp, &aml_cam_attrs[i]) < 0) + return -1; + } + + return 0; +} + +static int aml_cams_remove(struct platform_device *pdev) +{ + if (camera0_pwdn_pin != 0) + gpio_free(camera0_pwdn_pin); + if (camera0_rst_pin != 0) + gpio_free(camera0_rst_pin); + if (camera1_pwdn_pin != 0) + gpio_free(camera1_pwdn_pin); + if (camera1_rst_pin != 0) + gpio_free(camera1_rst_pin); + + kfree(temp_cam); + temp_cam = NULL; + + return 0; +} + +static const struct of_device_id cams_prober_dt_match[] = {{ + .compatible = + "amlogic, cams_prober", + }, {}, +}; + +static struct platform_driver aml_cams_prober_driver = { + .probe = aml_cams_probe, .remove = aml_cams_remove, .driver = { + .name = + "aml_cams_prober", .owner = THIS_MODULE, .of_match_table = + cams_prober_dt_match, + }, +}; + +static int __init aml_cams_prober_init(void) +{ + if (platform_driver_register(&aml_cams_prober_driver)) { + pr_err("aml_cams_probre_driver register failed\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit aml_cams_prober_exit(void) +{ + bt_path_count = 0; + platform_driver_unregister(&aml_cams_prober_driver); +} + +module_init(aml_cams_prober_init); +module_exit(aml_cams_prober_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Amlogic Cameras prober driver"); + diff --git a/drivers/amlogic/media/camera/common/config_parser.c b/drivers/amlogic/media/camera/common/config_parser.c new file mode 100644 index 000000000000..9ee62e745702 --- /dev/null +++ b/drivers/amlogic/media/camera/common/config_parser.c @@ -0,0 +1,1822 @@ +/* + * drivers/amlogic/media/camera/common/config_parser.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include "config_parser.h" +#include +#include +#include +#include + +static struct file *fp; +mm_segment_t fs; + +char *aet_key = "aet_start"; +char *hw_key = "hw_start"; +char *effect_key = "effect_start"; +char *capture_key = "capture_start"; +char *scenes_key = "scenes_start"; +char *wb_key = "wb_start"; +char *wave_key = "wave_start"; +char *lens_key = "lens_start"; +char *gamma_key = "gamma_start"; +char *wb_sensor_key = "mwb_sensor_start"; +char *version_key = "version_start"; +char *cm_key = "cm_start"; +char *nr_key = "nr_start"; +char *peaking_key = "peaking_start"; + +struct buffer_para_s { + char *buffer; + int data_start; + int data_size; + int buffer_len; +}; + +void *realloc_mem(char *buffer, int new_size, int *old_size) +{ + char *tmp = vmalloc(new_size); + + if (*old_size >= new_size) { + vfree(tmp); + return buffer; + } + + if (tmp != NULL) { + memcpy(tmp, buffer, *old_size); + *old_size = new_size; + vfree(buffer); + return tmp; + } else + return NULL; +} + +/* + *************************************** + *Name : camera_open_config + *Input : *config_file + *Output : file size + *function : open the firware file, and return total size + *************************************** + */ + +int camera_open_config(const char *config_file) +{ + loff_t file_size; + struct inode *inode = NULL; + + fp = filp_open(config_file, O_RDONLY, 0); + if (IS_ERR(fp)) { + pr_err("read config file error"); + return -1; + } + + inode = fp->f_path.dentry->d_inode; + file_size = inode->i_size; + fs = get_fs(); + set_fs(KERNEL_DS); + + return file_size; + +} + +/* + *********************************** + *Name : camera_read_config + *Input : offset + *length, read length + *buf, return buffer + *Output : + *function : read data to buffer + *********************************** + */ + +int camera_read_config(int offset, int length, char *buf) +{ + loff_t pos = offset; + + vfs_read(fp, buf, length, &pos); + return 0; +} + +/* + ********************************** + *Name : camera_close_config + *Input : + *Output : + *function : close file + ********************************** + */ + +int camera_close_config(void) +{ + set_fs(fs); + filp_close(fp, NULL); + return 0; +} + +static int camera_read_buff(struct i2c_adapter *adapter, + unsigned short i2c_addr, char *buf, int addr_len, + int data_len) +{ + int i2c_flag = -1; + + struct i2c_msg msgs[] = {{ + .addr = i2c_addr, .flags = 0, + .len = addr_len, .buf = buf, + }, { + .addr = i2c_addr, .flags = I2C_M_RD, + .len = data_len, .buf = buf, + } + }; + + i2c_flag = i2c_transfer(adapter, msgs, 2); + + return i2c_flag; +} + +static int camera_write_buff(struct i2c_adapter *adapter, + unsigned short i2c_addr, char *buf, int len) +{ + struct i2c_msg msg[] = {{ + .addr = i2c_addr, .flags = 0, /* |I2C_M_TEN, */ + .len = len, .buf = buf, + } + + }; + + if (i2c_transfer(adapter, msg, 1) < 0) + return -1; + else + return 0; +} + +int my_i2c_put_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, + unsigned short addr, unsigned char data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + buff[2] = data; + if (camera_write_buff(adapter, i2c_addr, buff, 3) < 0) + return -1; + return 0; +} + +int my_i2c_put_byte_add8(struct i2c_adapter *adapter, unsigned short i2c_addr, + char *buf, int len) +{ + if (camera_write_buff(adapter, i2c_addr, buf, len) < 0) + return -1; + return 0; +} + +int my_i2c_get_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, + unsigned short addr) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + + if (camera_read_buff(adapter, i2c_addr, buff, 2, 1) < 0) + return -1; + return buff[0]; +} + +int my_i2c_get_word(struct i2c_adapter *adapter, unsigned short i2c_addr) +{ + unsigned char buff[4]; + unsigned short data; + + buff[0] = 0; + + if (camera_read_buff(adapter, i2c_addr, buff, 1, 2) < 0) + return -1; + + data = buff[0]; + data = (data << 8) | buff[1]; + + return data; +} + +char *search_string(struct buffer_para_s *buf_para, int *offset, int *remained, + char *start, char *end) +{ + char *iter, *pter, *buffer; + int data_start, data_size, buffer_len; + int add = 0; + + buffer = buf_para->buffer; + data_start = buf_para->data_start; + data_size = buf_para->data_size; + buffer_len = buf_para->buffer_len; + iter = strstr(buffer + data_start, start); + while (iter == NULL) { + if (iter == NULL && *remained < strlen(start)) { + pr_err("wrong config file"); + return NULL; + } + memset(buffer, 0, buffer_len); + if (*remained < BUFFER_SIZE) { + camera_read_config(*offset - strlen(start), + *remained, buffer); /* check bounds */ + *offset += *remained - strlen(start); + data_size = *remained; + *remained = 0; + data_start = 0; + } else { + camera_read_config(*offset - strlen(start), + BUFFER_SIZE, buffer);/* check bounds */ + *offset += BUFFER_SIZE - strlen(start); + data_size = BUFFER_SIZE; + *remained -= BUFFER_SIZE; + data_start = 0; + } + iter = strstr(buffer, start); + } + data_start = iter - buffer; + /*** check **/ + if (data_start > 512) { + data_size -= data_start; + memmove(buffer, iter, data_size); + *(buffer + data_size) = '\0'; + iter = buffer; + data_start = 0; + } + pter = strstr(iter + strlen(start), end); + while (pter == NULL) { + if (pter == NULL && *remained < strlen(end)) { + pr_err("wrong config file"); + return NULL; + } + buffer = + (char *)realloc_mem(buffer, data_size + BUFFER_SIZE + 1, + &buffer_len); + if (buffer == NULL) { + pr_err("realloc failed\n"); + return NULL; + } + if (*remained < BUFFER_SIZE) { + camera_read_config(*offset, *remained, + buffer + data_size); /* check bounds */ + add = *remained; + *offset += *remained; + *remained = 0; + } else { + camera_read_config(*offset, BUFFER_SIZE, + buffer + data_size); /* check bounds */ + add = BUFFER_SIZE; + *remained -= BUFFER_SIZE; + *offset += BUFFER_SIZE; + } + *(buffer + data_size + add) = '\0'; + pter = strstr(buffer + data_size - strlen(end), end); + data_size += add; + } + /* if realloc ,iter is invalid,so recalculate */ + iter = buffer + data_start; + data_start = pter - buffer; + + buf_para->buffer = buffer; + buf_para->data_start = data_start; + buf_para->data_size = data_size; + buf_para->buffer_len = buffer_len; + return iter; +} + +char *search_key(struct buffer_para_s *buf_para, int *offset, int *remained) +{ + char *iter, *buffer; + int data_start, data_size, buffer_len; + int add = 0; + + buffer = buf_para->buffer; + data_start = buf_para->data_start; + data_size = buf_para->data_size; + buffer_len = buf_para->buffer_len; + + iter = strstr(buffer + data_start, "["); + while (iter == NULL) { + if (iter == NULL && *remained < 20) { + pr_err("file end\n"); + return NULL; + } + memset(buffer, 0, buffer_len); + if (*remained < BUFFER_SIZE) { + camera_read_config(*offset, + *remained, buffer); /* check bounds */ + *offset += *remained; + data_size = *remained; + *remained = 0; + data_start = 0; + } else { + camera_read_config(*offset, + BUFFER_SIZE, buffer); /* check bounds */ + *offset += BUFFER_SIZE; + data_size = BUFFER_SIZE; + *remained -= BUFFER_SIZE; + data_start = 0; + } + iter = strstr(buffer, "["); + } + data_start = iter - buffer; + /*** check **/ + if (data_start + 20 > data_size) { /* ensure we have an complete key */ + buffer = + (char *)realloc_mem(buffer, data_size + BUFFER_SIZE + 1, + &buffer_len); + if (buffer == NULL) { + pr_err("realloc failed\n"); + return NULL; + } + if (*remained < BUFFER_SIZE) { + camera_read_config(*offset, *remained, + buffer + data_size); /* check bounds */ + add = *remained; + *offset += *remained; + *remained = 0; + + } else { + camera_read_config(*offset, BUFFER_SIZE, + buffer + data_size); /* check bounds */ + add = BUFFER_SIZE; + *remained -= BUFFER_SIZE; + *offset += BUFFER_SIZE; + } + *(buffer + data_size + add) = '\0'; + data_size += add; + } +/* if realloc ,iter is invalid,so recalculate */ + iter = buffer + data_start; + + buf_para->buffer = buffer; + buf_para->data_start = data_start; + buf_para->data_size = data_size; + buf_para->buffer_len = buffer_len; + return iter; +} + +int parse_head(char *buffer, int *sum) +{ + int ret; + char *iter; + + iter = strstr(buffer, "sum"); + if (iter == NULL) + return -WRONG_FORMAT; + iter += 4; /* point to value */ + ret = kstrtoint(iter, 10, sum); + return 0; +} + +int parse_body_head(char *buffer, int *no, int check, char *name) +{ + int ret; + char *iter; + + iter = strstr(buffer, "no"); + iter += 3; + ret = kstrtoint(iter, 10, no); + iter = strstr(iter, "name"); + iter += 5; + ret = kstrtos8(name, 16, iter); + return 0; +} +int parse_aet_element_info(char **iter, struct sensor_aet_info_s *info) +{ + int ret; + + *iter = strstr(*iter, "export"); + *iter += 7; + ret = kstrtouint(*iter, 16, &(info->fmt_main_fr)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->fmt_capture)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->fmt_hactive)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->fmt_vactive)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->fmt_rated_fr)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->fmt_min_fr)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->tbl_max_step)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->tbl_rated_step)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->tbl_max_gain)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(info->tbl_min_gain)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, + 16, &(info->format_transfer_parameter)); + *iter = strstr(*iter, ","); + *iter += 1; + return 0; + +} + +int parse_aet_element_tbl(char **iter, struct sensor_aet_s *tbl) +{ + int ret; + + ret = kstrtouint(*iter, 16, &(tbl->exp)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->ag)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->vts)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->gain)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->fr)); + *iter = strstr(*iter, ","); + *iter += 1; + return 0; +} + +int parse_last_aet_element_tbl(char **iter, struct sensor_aet_s *tbl) +{ + int ret; + + ret = kstrtouint(*iter, 16, &(tbl->exp)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->ag)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->vts)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->gain)); + *iter = strstr(*iter, ","); + *iter += 1; + ret = kstrtouint(*iter, 16, &(tbl->fr)); + return 0; +} + +int parse_effect(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int ret1, ret2, ret3, sum, check, i; + char *iter; + + iter = search_string(buf_para, offset, remained, "effect_start]", + "[effect]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (ret1 != 0) + return -HEAD_FAILED; + cf->eff.sum = sum; + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, + remained, "[effect]", "[effect"); + if (iter == NULL) + return -WRONG_FORMAT; + ret2 = parse_body_head(iter, &(cf->eff.eff[check].num), check, + cf->eff.eff[check].name); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + i = 0; + while (i < EFFECT_MAX && iter != NULL) { + ret3 = kstrtouint(iter, + 16, &(cf->eff.eff[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != EFFECT_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; +} + +int parse_aet(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int sum, ret, check, i; + char *iter; + + iter = search_string(buf_para, offset, remained, "aet_start]", "[aet]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret = parse_head(iter, &sum); + if (sum <= 0) + return -HEAD_FAILED; + cf->aet.sum = sum; + /**parser body***/ + for (i = 0; i < sum; i++) { + cf->aet.aet[i].info = + kmalloc(sizeof(struct sensor_aet_info_s), 0); + if ((cf->aet.aet[i].info) == NULL) { + while (i-- > 0) + kfree(cf->aet.aet[i].info); + return -NO_MEM; + } + } /* alloc head */ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, + remained, "[aet]", "[aet"); + if (iter == NULL) { + pr_err("aet wrong config format\n"); + ret = -WRONG_FORMAT; + goto clean; + } + ret = parse_body_head(iter, &(cf->aet.aet[check].num), check, + cf->aet.aet[check].name); + if (ret != 0) { + ret = -HEAD_FAILED; + goto clean; + } + ret = parse_aet_element_info(&iter, cf->aet.aet[check].info); + if (ret != 0) { + ret = -BODY_ELEMENT_FAILED; + goto clean; + } + + cf->aet.aet[check].aet_table = + vmalloc(sizeof(struct sensor_aet_s) * + (cf->aet.aet[check].info->tbl_max_step + 1)); + if ((cf->aet.aet[check].aet_table) == NULL) { + for (i = 0; i < check; i++) + vfree(cf->aet.aet[i].aet_table); + ret = -NO_MEM; + goto clean; + } + for (i = 0; i <= cf->aet.aet[check].info->tbl_max_step; i++) { + if (i == cf->aet.aet[check].info->tbl_max_step) { + ret = parse_last_aet_element_tbl( + &iter, &(cf->aet.aet[check].aet_table[i])); + } else + ret = parse_aet_element_tbl(&iter, + &(cf->aet.aet[check].aet_table[i])); + if (ret != 0) { + ret = -BODY_ELEMENT_FAILED; + goto clean_table; + } + } + check++; + } + return 0; + +clean_table: + for (i = 0; i <= check; i++) + vfree(cf->aet.aet[i].aet_table); +clean: + for (i = 0; i < sum; i++) + kfree(cf->aet.aet[i].info); + return ret; +} + +int parse_hw(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int ret1, ret2, ret3, sum, check, i; + char *iter = NULL; + char *eter = NULL; + + iter = search_string(buf_para, offset, remained, "hw_start]", "[hw]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (ret1 != 0) + return -HEAD_FAILED; + cf->hw.sum = sum; + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, remained, "[hw]", "[hw"); + if (iter == NULL) + return -WRONG_FORMAT; + ret2 = parse_body_head(iter, &(cf->hw.hw[check].num), check, + cf->hw.hw[check].name); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + eter = strstr(iter, ";"); + if (eter == NULL) + return -WRONG_FORMAT; + i = 0; + while (iter < eter) { + ret3 = kstrtouint(iter, + 16, &(cf->hw.hw[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; +} + +int parse_wb(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int ret1, ret2, ret3, sum, check, i; + char *iter = NULL; + char *eter = NULL; + + iter = search_string(buf_para, offset, remained, "wb_start]", "[wb]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (ret1 != 0) + return -HEAD_FAILED; + cf->wb.sum = sum; + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, remained, "[wb]", "[wb"); + if (iter == NULL) + return -WRONG_FORMAT; + ret2 = parse_body_head(iter, &(cf->wb.wb[check].num), check, + cf->wb.wb[check].name); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + eter = strstr(iter, ";"); + if (eter == NULL) + return -WRONG_FORMAT; + i = 0; + while (iter < eter) { + ret3 = kstrtouint(iter, + 16, &(cf->wb.wb[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + + } + if (i != WB_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; + +} + +int parse_capture(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int ret1, ret2, ret3, sum, check, i; + char *iter = NULL; + char *eter = NULL; + + iter = search_string(buf_para, offset, remained, "capture_start]", + "[capture]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (ret1 != 0) + return -HEAD_FAILED; + cf->capture.sum = sum; + /* pr_err("capture sum:%d\n",sum); */ + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, remained, "[capture]", + "[capture"); + if (iter == NULL) { + pr_err("search wrong\n"); + return -WRONG_FORMAT; + } + ret2 = parse_body_head(iter, + &(cf->capture.capture[check].num), check, + cf->capture.capture[check].name); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + /* pr_err("name:%s\n",cf->capture.capture[check].name); */ + iter = strstr(iter, "export"); + if (iter == NULL) { + pr_err("iter is NULL\n"); + return -WRONG_FORMAT; + } + iter += 7; + eter = strstr(iter, ";"); + if (eter == NULL) + return -WRONG_FORMAT; + i = 0; + while (iter < eter) { + ret3 = kstrtouint(iter, + 16, &(cf->capture.capture[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != CAPTURE_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; + +} + +int parse_wave(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int i, ret; + char *iter = NULL; + char *eter = NULL; + + iter = search_string(buf_para, offset, remained, "wave_start]", + "[wave_end]"); + if (iter == NULL) + return -WRONG_FORMAT; + iter = strstr(iter, "export"); + iter += 7; + eter = strstr(iter, ";"); + if (eter == NULL) + return -WRONG_FORMAT; + i = 0; + while (iter < eter) { + ret = kstrtouint(iter, 16, &(cf->wave.export[i])); + /* pr_err("wave:%x\n",cf->wave.export[i]); */ + iter = strstr(iter, ","); + i++; + if (iter == NULL) + break; + iter += 1; + } + if (i != WAVE_MAX) + return -CHECK_LEN_FAILED; + return 0; +} + +int parse_scene(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int sum, ret1, ret2, ret3, check, i; + char *iter = NULL; + char *eter = NULL; + + iter = search_string(buf_para, offset, remained, "scenes_start]", + "[scenes]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (sum <= 0) + return -HEAD_FAILED; + cf->scene.sum = sum; + + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, + remained, "[scenes]", "[scenes"); + if (iter == NULL) { + pr_err("scene wrong config format\n"); + return -WRONG_FORMAT; + } + ret2 = parse_body_head(iter, &((cf->scene.scene[check]).num), + check, (cf->scene.scene[check].name)); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + eter = strstr(iter, ";"); + if (eter == NULL) + return -WRONG_FORMAT; + i = 0; + while (iter < eter) { + ret3 = kstrtouint(iter, + 16, &(cf->scene.scene[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != SCENE_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; +} + +int parse_lens(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int sum, ret1, ret2, ret3, check, i; + char *iter = NULL; + char *eter = NULL; + + iter = search_string(buf_para, offset, + remained, "lens_start]", "[lens]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (sum <= 0) + return -HEAD_FAILED; + cf->lens.sum = sum; + + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, + remained, "[lens]", "[lens"); + if (iter == NULL) { + pr_err("lens wrong config format\n"); + return -WRONG_FORMAT; + } + ret2 = parse_body_head(iter, + &((cf->lens.lens[check]).num), + check, + (cf->lens.lens[check].name)); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + eter = strstr(iter, ";"); + if (eter == NULL) + return -WRONG_FORMAT; + i = 0; + while (iter < eter) { + ret3 = kstrtouint(iter, + 16, &(cf->lens.lens[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != LENS_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; +} + +int parse_gamma(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int i, ret; + char *iter; + + iter = search_string(buf_para, offset, remained, "gamma_start]", + "[gamma_end]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + iter = strstr(iter, "export"); + iter += 7; + for (i = 0; i < GAMMA_MAX && iter != NULL;) { + ret = kstrtouint(iter, 16, &(cf->gamma.gamma_r[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != GAMMA_MAX) + return -CHECK_LEN_FAILED; + for (i = 0; i < GAMMA_MAX && iter != NULL;) { + ret = kstrtouint(iter, 16, &(cf->gamma.gamma_g[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != GAMMA_MAX) + return -CHECK_LEN_FAILED; + for (i = 0; i < GAMMA_MAX && iter != NULL;) { + ret = kstrtouint(iter, + 16, &(cf->gamma.gamma_b[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != GAMMA_MAX) + return -CHECK_LEN_FAILED; + return 0; +} + +int parse_wb_sensor(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int i, ret; + char *iter; + + iter = search_string(buf_para, offset, remained, "mwb_sensor_start]", + "[mwb_sensor_end]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + iter = strstr(iter, "export"); + iter += 7; + i = 0; + while (i < WB_SENSOR_MAX && iter != NULL) { + ret = kstrtouint(iter, 16, &(cf->wb_sensor_data.export[i])); + /* pr_err("wb sensor:%x\n",cf->wb_sensor_data.export[i]); */ + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != WB_SENSOR_MAX) + return -CHECK_LEN_FAILED; + return 0; +} + +int parse_version(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + char *iter, *end; + int len = 0; + + iter = search_string(buf_para, offset, remained, "version_start]", + "[version_end]"); + if (iter == NULL) + return -WRONG_FORMAT; + iter = strstr(iter, "Date"); + iter += 5; + end = strstr(iter, "Module"); + if (end == NULL) + return -WRONG_FORMAT; + len = end - iter; + memcpy(cf->version.date, iter, len); + cf->version.date[len] = '\0'; + + iter = end + 7; + end = strstr(iter, "Version"); + if (end == NULL) + return -WRONG_FORMAT; + len = end - iter; + memcpy(cf->version.module, iter, len); + cf->version.module[len] = '\0'; + + iter = end + 8; + end = strstr(iter, "[version"); + if (end == NULL) + return -WRONG_FORMAT; + len = end - iter; + memcpy(cf->version.version, iter, len); + cf->version.version[len] = '\0'; + pr_info("version:%s", cf->version.version); + return 0; +} + +int parse_cm(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int i; + int ret; + char *iter; + + iter = search_string(buf_para, offset, + remained, "cm_start]", "[cm_end]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser body***/ + iter = strstr(iter, "export"); + iter += 7; + i = 0; + while (i < CM_MAX && iter != NULL) { + ret = kstrtouint(iter, 16, &(cf->cm.export[i])); + /* pr_err("cm:%x\n",cf->cm.export[i]); */ + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != CM_MAX) + return -CHECK_LEN_FAILED; + return 0; +} + +int parse_nr(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int ret1, ret2, ret3, sum, check, i; + char *iter; + + iter = search_string(buf_para, offset, remained, "nr_start]", "[nr]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (ret1 != 0) + return -HEAD_FAILED; + cf->nr.sum = sum; + /* pr_err("nr sum:%d\n",sum); */ + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, remained, "[nr]", "[nr"); + if (iter == NULL) { + pr_err("search wrong\n"); + return -WRONG_FORMAT; + } + ret2 = parse_body_head(iter, &(cf->nr.nr[check].num), check, + cf->nr.nr[check].name); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + i = 0; + while (i < NR_MAX && iter != NULL) { + ret3 = kstrtouint(iter, 16, + &(cf->nr.nr[check].export[i])); + /* pr_err("nr:%x\n",cf->nr.nr[check].export[i]); */ + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != NR_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; +} + +int parse_peaking(struct configure_s *cf, struct buffer_para_s *buf_para, + int *remained, int *offset) +{ + int ret1, ret2, ret3, sum, check, i; + char *iter; + + iter = search_string(buf_para, offset, remained, "peaking_start]", + "[peaking]"); + if (iter == NULL) + return -WRONG_FORMAT; + /***parser head***/ + ret1 = parse_head(iter, &sum); + if (ret1 != 0) + return -HEAD_FAILED; + cf->peaking.sum = sum; + /* pr_err("peaking sum:%d\n",sum); */ + /**parser body***/ + check = 0; + while (check < sum) { + iter = search_string(buf_para, offset, remained, "[peaking]", + "[peaking"); + if (iter == NULL) { + pr_err("search wrong\n"); + return -WRONG_FORMAT; + } + ret2 = parse_body_head(iter, + &(cf->peaking.peaking[check].num), check, + cf->peaking.peaking[check].name); + if (ret2 != 0) + return -BODY_HEAD_FAILED; + iter = strstr(iter, "export"); + iter += 7; + i = 0; + while (i < PEAKING_MAX && iter != NULL) { + ret3 = kstrtouint(iter, + 16, &(cf->peaking.peaking[check].export[i])); + i++; + iter = strstr(iter, ","); + if (iter == NULL) + break; + iter += 1; + } + if (i != PEAKING_MAX) + return -CHECK_LEN_FAILED; + check++; + } + if (check != sum) + return -CHECK_FAILED; + return 0; +} + +int parse_config(const char *path, struct configure_s *cf) +{ + char *buffer, *iter; + int file_size; + int remained_size; + int read_offset = 0; + int ret = 0; + struct buffer_para_s buf_para; + + buffer = vmalloc(BUFFER_SIZE + 1);/*(char *)*/ + if (buffer == NULL) + return -NO_MEM; + + buf_para.buffer = buffer; + + memset(cf, 0, sizeof(struct configure_s)); + file_size = camera_open_config(path); + if (file_size < 0) { + pr_err("open failed :%d\n", file_size); + ret = -READ_ERROR; + goto clean_mem; + } else if (file_size == 0) { + pr_err("file is null\n"); + ret = -READ_ERROR; + goto clean_all; + } else { + if (file_size < BUFFER_SIZE) { + camera_read_config(0, file_size, buffer); + remained_size = 0; + read_offset = file_size; + *(buffer + file_size) = '\0'; + } else { + camera_read_config(0, BUFFER_SIZE, buffer); + remained_size = file_size - BUFFER_SIZE; + read_offset = BUFFER_SIZE; + *(buffer + BUFFER_SIZE) = '\0'; + } + } + buf_para.data_start = 0; + buf_para.data_size = read_offset; + buf_para.buffer_len = BUFFER_SIZE; + + while (read_offset <= file_size) { + iter = search_key(&buf_para, &read_offset, &remained_size); + if (iter == NULL) { + pr_info("finish parse file\n"); + return 0; + } + iter += 1; + buf_para.data_start += 1; + switch (*iter) { + case 'a': + if (memcmp(iter, aet_key, strlen(aet_key)) == 0) { + cf->aet_valid = 1; + ret = parse_aet(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->aet_valid = 0; + pr_err("aet invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(aet_key); + break; + case 'h': + if (memcmp(iter, hw_key, strlen(hw_key)) == 0) { + cf->hw_valid = 1; + ret = parse_hw(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->hw_valid = 0; + pr_err("hw invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(hw_key); + break; + case 'e': + if (memcmp(iter, effect_key, strlen(effect_key)) == 0) { + cf->effect_valid = 1; + ret = parse_effect(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->effect_valid = 0; + pr_err("effect invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(effect_key); + break; + case 'w': + if (*(iter + 1) == 'b') { + if (memcmp(iter, wb_key, strlen(wb_key)) == 0) { + cf->wb_valid = 1; + ret = parse_wb(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->wb_valid = 0; + pr_err("wb invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(wb_key); + } else if (*(iter + 1) == 'a') { + if (memcmp(iter, wave_key, + strlen(wave_key)) == 0) { + cf->wave_valid = 1; + ret = parse_wave(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->wave_valid = 0; + pr_err("wave invalid :%d\n", + ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(wave_key); + } else + buf_para.data_start += 1; + + break; + case 's': + if (memcmp(iter, scenes_key, + strlen(scenes_key)) == 0) { + cf->scene_valid = 1; + ret = parse_scene(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->scene_valid = 0; + pr_err("scene invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(scenes_key); + break; + case 'c': + if (*(iter + 1) == 'a') { + if (memcmp(iter, capture_key, + strlen(capture_key)) == 0) { + cf->capture_valid = 1; + ret = parse_capture(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->capture_valid = 0; + pr_err("capture invalid :%d\n", + ret); + goto clean_all; + } + } else + buf_para.data_start += + strlen(capture_key); + } else if (*(iter + 1) == 'm') { + if (memcmp(iter, cm_key, strlen(cm_key)) == 0) { + cf->cm_valid = 1; + ret = parse_cm(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->cm_valid = 0; + pr_err("cm invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(cm_key); + } else + buf_para.data_start += 1; + break; + case 'l': + if (memcmp(iter, lens_key, strlen(lens_key)) == 0) { + cf->lens_valid = 1; + ret = parse_lens(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->lens_valid = 0; + pr_err("lens invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(lens_key); + break; + case 'g': + if (memcmp(iter, gamma_key, strlen(gamma_key)) == 0) { + cf->gamma_valid = 1; + ret = parse_gamma(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->gamma_valid = 0; + pr_err("gamma invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(gamma_key); + break; + case 'm': + if (memcmp(iter, wb_sensor_key, + strlen(wb_sensor_key)) == 0) { + cf->wb_sensor_data_valid = 1; + ret = parse_wb_sensor(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->wb_sensor_data_valid = 0; + pr_err("wb sensor data invalid :%d\n", + ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(wb_sensor_key); + break; + case 'v': + if (memcmp(iter, version_key, + strlen(version_key)) == 0) { + cf->version_info_valid = 1; + ret = parse_version(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->version_info_valid = 0; + pr_err("version info invalid :%d\n", + ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(version_key); + break; + case 'n': + if (memcmp(iter, nr_key, strlen(nr_key)) == 0) { + cf->nr_valid = 1; + ret = parse_nr(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->nr_valid = 0; + pr_err("nr invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(nr_key); + break; + case 'p': + if (memcmp(iter, peaking_key, + strlen(peaking_key)) == 0) { + cf->peaking_valid = 1; + ret = parse_peaking(cf, &buf_para, + &remained_size, &read_offset); + if (ret != 0) { + cf->peaking_valid = 0; + pr_err("peaking invalid :%d\n", ret); + goto clean_all; + } + } else + buf_para.data_start += strlen(peaking_key); + break; + default: + buf_para.data_start += 1; + break; + } + } + ret = 0; + +clean_all: + camera_close_config(); +clean_mem: + vfree(buf_para.buffer); + return ret; +} + +struct hw_para_s { + char name[20]; + int size; + int *array; +}; + +struct hw_para_s hw_para[] = { + {"TOP", XML_TOP, NULL}, {"TP", XML_TP, NULL}, {"CG", XML_CG, NULL}, { + "LENS_SHADING", XML_LS, NULL + }, {"DFT", XML_DP, NULL}, { + "DMS", XML_DM, NULL + }, {"MATRIX", XML_CSC, NULL}, { + "PEAKING", XML_SH, NULL + }, {"NR", XML_NR, NULL}, {"AWB", XML_AWB, NULL}, + {"AE", XML_AE, NULL}, {"AF", XML_AF, NULL}, {"BLNR", XML_BN, NULL}, { + "DBG", XML_DBG, NULL + }, {"GC", XML_GC, NULL}, {"", 0, NULL} +}; + +void init_hw_para(struct xml_default_regs_s *reg) +{ + hw_para[0].array = &(reg->top.reg_map[0]); + hw_para[1].array = &(reg->tp.reg_map[0]); + hw_para[2].array = &(reg->cg.reg_map[0]); + hw_para[3].array = &(reg->ls.reg_map[0]); + hw_para[4].array = &(reg->dp.reg_map[0]); + hw_para[5].array = &(reg->dm.reg_map[0]); + hw_para[6].array = &(reg->csc.reg_map[0]); + hw_para[7].array = &(reg->sharp.reg_map[0]); + hw_para[8].array = &(reg->nr.reg_map[0]); + hw_para[9].array = &(reg->awb_reg.reg_map[0]); + hw_para[10].array = &(reg->ae_reg.reg_map[0]); + hw_para[11].array = &(reg->af_reg.reg_map[0]); + hw_para[12].array = &(reg->bn.reg_map[0]); + hw_para[13].array = &(reg->dbg.reg_map[0]); + hw_para[14].array = &(reg->gc.reg_map[0]); +} + +/* call back functions */ + +unsigned int get_aet_max_step(void *priv) +{ + struct camera_priv_data_s *camera_priv_data = + (struct camera_priv_data_s *)priv; + if (camera_priv_data == NULL || + camera_priv_data->sensor_aet_info == NULL) { + pr_err("get_aet_max_step null\n"); + WARN_ON((!camera_priv_data) || + (!camera_priv_data->sensor_aet_info)); + } + return camera_priv_data->sensor_aet_info->tbl_max_step; +} + +unsigned int get_aet_max_gain(void *priv) +{ + struct camera_priv_data_s *camera_priv_data = + (struct camera_priv_data_s *)priv; + if (camera_priv_data == NULL || + camera_priv_data->sensor_aet_info == NULL) { + pr_err("get_aet_max_gain null\n"); + WARN_ON((!camera_priv_data) || + (!camera_priv_data->sensor_aet_info)); + } + return camera_priv_data->sensor_aet_info->tbl_max_gain; +} + +unsigned int get_aet_min_gain(void *priv) +{ + struct camera_priv_data_s *camera_priv_data = + (struct camera_priv_data_s *)priv; + if (camera_priv_data == NULL || + camera_priv_data->sensor_aet_info == NULL) { + pr_err("get_aet_min_gain null\n"); + WARN_ON((!camera_priv_data) || + (!camera_priv_data->sensor_aet_info)); + } + return camera_priv_data->sensor_aet_info->tbl_min_gain; +} + +unsigned int get_aet_current_step(void *priv) +{ + struct camera_priv_data_s *camera_priv_data = + (struct camera_priv_data_s *)priv; + if (camera_priv_data == NULL || + camera_priv_data->sensor_aet_info == NULL) { + pr_err("get_aet_current_step null\n"); + WARN_ON((!camera_priv_data) || + (!camera_priv_data->sensor_aet_info)); + } + return camera_priv_data->sensor_aet_step; +} + +unsigned int get_aet_current_gain(void *priv) +{ + struct sensor_aet_s *sensor_aet_table; + unsigned int sensor_aet_step; + struct camera_priv_data_s *camera_priv_data = + (struct camera_priv_data_s *)priv; + if (camera_priv_data == NULL) + WARN_ON(!camera_priv_data); + + sensor_aet_table = + camera_priv_data->sensor_aet_table; + sensor_aet_step = camera_priv_data->sensor_aet_step; + + if (sensor_aet_table == NULL) { + pr_err("get_aet_current_gain null\n"); + WARN_ON(!sensor_aet_table); + } + return sensor_aet_table[sensor_aet_step].gain; +} + +unsigned int get_aet_new_gain(void *priv, unsigned int new_step) +{ + struct camera_priv_data_s *camera_priv_data = + (struct camera_priv_data_s *)priv; + struct sensor_aet_s *sensor_aet_table; + + if (camera_priv_data == NULL) + WARN_ON(!camera_priv_data); + sensor_aet_table = + camera_priv_data->sensor_aet_table; + if (sensor_aet_table == NULL) { + pr_err("get_aet_current_gain null\n"); + WARN_ON(!sensor_aet_table); + } + return sensor_aet_table[new_step].gain; +} + +int generate_para(struct cam_parameter_s *para, struct para_index_s pindex, + struct configure_s *cf) +{ + int i = 0; + int j = 0; + struct xml_scenes_s *scene; + struct xml_default_regs_s *reg; + struct xml_effect_manual_s *effect; + struct xml_wb_manual_s *wb; + struct xml_capture_s *capture; + struct wave_s *wave; + + /**init callback func**/ + para->cam_function.set_af_new_step = NULL; + if (cf->aet_valid == 1) { + para->cam_function.get_aet_current_step = get_aet_current_step; + para->cam_function.get_aet_max_step = get_aet_max_step; + para->cam_function.get_aet_current_gain = get_aet_current_gain; + para->cam_function.get_aet_min_gain = get_aet_min_gain; + para->cam_function.get_aet_max_gain = get_aet_max_gain; + para->cam_function.get_aet_gain_by_step = get_aet_new_gain; + + } + /**init scenes**/ + if (cf->scene_valid == 1) { + para->xml_scenes = + vmalloc(sizeof(struct xml_scenes_s)); + if (para->xml_scenes == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + scene = para->xml_scenes; + memcpy(&(scene->ae), + cf->scene.scene[pindex.scenes_index].export, + AE_LEN * sizeof(unsigned int)); + memcpy(&(scene->awb), + cf->scene.scene[pindex.scenes_index].export + AE_LEN, + AWB_LEN * sizeof(unsigned int)); + memcpy(&(scene->af), + cf->scene.scene[pindex.scenes_index].export + + (AE_LEN + AWB_LEN), + AF_LEN * sizeof(unsigned int)); + } else + para->xml_scenes = NULL; + + /**init hw**/ + if (cf->hw_valid == 1) { + para->xml_regs_map = vmalloc(sizeof(struct xml_default_regs_s)); + if (para->xml_regs_map == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + reg = para->xml_regs_map; + init_hw_para(reg); + for (i = 0; i < cf->hw.sum; i++) { + if ((strcmp(hw_para[i].name, cf->hw.hw[i].name)) == 0) { + for (j = 0; j < hw_para[i].size; j++) + hw_para[i].array[j] = + cf->hw.hw[i].export[j]; + } + } + + } else + para->xml_regs_map = NULL; + /** init gamma **/ + if (cf->gamma_valid == 1) { + if (para->xml_regs_map == NULL) { + para->xml_regs_map = + vmalloc(sizeof(struct xml_default_regs_s)); + if (para->xml_regs_map == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + } + reg = para->xml_regs_map; + memcpy(reg->lut_gc.gamma_r, cf->gamma.gamma_r, + GAMMA_MAX * sizeof(unsigned short)); + memcpy(reg->lut_gc.gamma_g, cf->gamma.gamma_g, + GAMMA_MAX * sizeof(unsigned short)); + memcpy(reg->lut_gc.gamma_b, cf->gamma.gamma_b, + GAMMA_MAX * sizeof(unsigned short)); + } + /**init effect**/ + if (cf->effect_valid == 1) { + para->xml_effect_manual = + kmalloc(sizeof(struct xml_effect_manual_s), 0); + if (para->xml_effect_manual == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + effect = para->xml_effect_manual; + memcpy(effect->csc.reg_map, + cf->eff.eff[pindex.effect_index].export, + EFFECT_MAX * sizeof(unsigned int)); + } else + para->xml_effect_manual = NULL; + /**init wb**/ + if (cf->wb_valid == 1) { + para->xml_wb_manual = + kmalloc(sizeof(struct xml_wb_manual_s), 0); + if (para->xml_wb_manual == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + wb = para->xml_wb_manual; + memcpy(wb->reg_map, cf->wb.wb[pindex.wb_index].export, + 2 * sizeof(unsigned int)); + } else + para->xml_wb_manual = NULL; + + /**init capture**/ + if (cf->capture_valid == 1) { + para->xml_capture = vmalloc(sizeof(struct xml_capture_s)); + if (para->xml_capture == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + capture = para->xml_capture; + capture->ae_try_max_cnt = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[0]); + capture->sigle_count = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[3]); + capture->skip_step = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[4]); + capture->multi_capture_num = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[5]); + capture->af_mode = (enum cam_scanmode_e)(cf->capture. + capture[pindex.capture_index].export[2]); + capture->eyetime = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[6]); + capture->pretime = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[7]); + capture->postime = (unsigned int)(cf->capture. + capture[pindex.capture_index].export[8]); + } else + para->xml_capture = NULL; + /**init wave**/ + if (cf->wave_valid == 1) { + para->xml_wave = kmalloc(sizeof(struct wave_s), 0); + if (para->xml_wave == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + wave = para->xml_wave; + memcpy(wave, cf->wave.export, WAVE_MAX * sizeof(unsigned int)); + } else + para->xml_wave = NULL; + return 0; +} + +void free_para(struct cam_parameter_s *para) +{ + if (para->xml_peripheral != NULL) { + kfree(para->xml_peripheral); + para->xml_peripheral = NULL; + } + if (para->xml_scenes != NULL) { + vfree(para->xml_scenes); + para->xml_scenes = NULL; + } + if (para->xml_regs_map != NULL) { + vfree(para->xml_regs_map); + para->xml_regs_map = NULL; + } + if (para->xml_effect_manual != NULL) { + kfree(para->xml_effect_manual); + para->xml_effect_manual = NULL; + } + if (para->xml_wb_manual != NULL) { + kfree(para->xml_wb_manual); + para->xml_wb_manual = NULL; + } + if (para->xml_capture != NULL) { + vfree(para->xml_capture); + para->xml_capture = NULL; + } + if (para->xml_wave != NULL) { + kfree(para->xml_wave); + para->xml_wave = NULL; + } +} + +int update_fmt_para(int width, int height, struct cam_parameter_s *para, + struct para_index_s *pindex, struct configure_s *cf) +{ + int i = 0; + struct xml_default_regs_s *reg; + + if (cf->lens_valid == 1) { + while (i < cf->lens.sum) { + if (cf->lens.lens[i].export[0] == width && + cf->lens.lens[i].export[1] == height) + break; + i++; + } + if (i < cf->lens.sum) + pindex->lens_index = i; + else { + pr_info("width:%x,height:%x no match lens param\n", + width, height); + pindex->lens_index = 0; + } + /** init lens **/ + if (para->xml_regs_map == NULL) { + para->xml_regs_map = + vmalloc(sizeof(struct xml_default_regs_s)); + if (para->xml_regs_map == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + } + reg = para->xml_regs_map; + memcpy(reg->lnsd.reg_map, + cf->lens.lens[pindex->lens_index].export + 2, + (LENS_MAX - 2) * sizeof(unsigned int)); + } + + i = 0; + if (cf->nr_valid == 1) { + while (i < cf->nr.sum) { + if (cf->nr.nr[i].export[0] == width && + cf->nr.nr[i].export[1] == height) + break; + i++; + } + if (i < cf->nr.sum) + pindex->nr_index = i; + else { + pr_info("width:%x,height:%x no match nr param\n", + width, height); + pindex->nr_index = 0; + } + /** init nr **/ + if (para->xml_regs_map == NULL) { + para->xml_regs_map = + vmalloc(sizeof(struct xml_default_regs_s)); + if (para->xml_regs_map == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + } + reg = para->xml_regs_map; + memcpy(reg->nr.reg_map, cf->nr.nr[pindex->nr_index].export + 2, + (NR_MAX - 2) * sizeof(unsigned int)); + } + + i = 0; + if (cf->peaking_valid == 1) { + while (i < cf->peaking.sum) { + if (cf->peaking.peaking[i].export[0] == width && + cf->peaking.peaking[i].export[1] == height) + break; + i++; + } + if (i < cf->peaking.sum) + pindex->peaking_index = i; + else { + pr_info("width:%x,height:%x no match peaking param\n", + width, height); + pindex->peaking_index = 0; + } + /** init sharp **/ + if (para->xml_regs_map == NULL) { + para->xml_regs_map = + vmalloc(sizeof(struct xml_default_regs_s)); + if (para->xml_regs_map == NULL) { + pr_err("alloc mem failed\n"); + return -ENOMEM; + } + } + reg = para->xml_regs_map; + memcpy(reg->sharp.reg_map, + cf->peaking.peaking[pindex->peaking_index].export + 2, + (PEAKING_MAX - 2) * sizeof(unsigned int)); + } + return 0; +} diff --git a/drivers/amlogic/media/camera/common/config_parser.h b/drivers/amlogic/media/camera/common/config_parser.h new file mode 100644 index 000000000000..c5e78026e9fe --- /dev/null +++ b/drivers/amlogic/media/camera/common/config_parser.h @@ -0,0 +1,301 @@ +/* + * drivers/amlogic/media/camera/common/config_parser.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef CONFIG_PARSER +#define CONFIG_PARSER + +#include +#include +#include +#include +#include +#include + +#define EFFECT_ITEM_MAX 16 +#define AET_ITEM_MAX 32 +#define HW_ITEM_MAX 16 +#define WB_ITEM_MAX 10 +#define CAPTURE_ITEM_MAX 9 +#define NR_ITEM_MAX 5 +#define PEAKING_ITEM_MAX 5 +#define LENS_ITEM_MAX 5 +#define SCENE_ITEM_MAX 1 +#define EFFECT_MAX 18 +#define HW_MAX 64 +#define WB_MAX 2 +#define GAMMA_MAX 257 +#define SCENE_MAX 281 +#define WB_SENSOR_MAX 4 +#define CAPTURE_MAX 8 +#define LENS_MAX 1027 +#define WAVE_MAX 12 +#define CM_MAX 188 +#define NR_MAX 15 +#define PEAKING_MAX 35 +#define AE_LEN 119 +#define AWB_LEN 120 +#define AF_LEN 42 +#define BUFFER_SIZE 1024 + +enum error_code { + NO_MEM = 1, + READ_ERROR, + WRONG_FORMAT, + CHECK_LEN_FAILED, + CHECK_FAILED, + HEAD_FAILED, + BODY_HEAD_FAILED, + BODY_ELEMENT_FAILED, +}; + +struct effect_type { + int num; + char name[40]; + unsigned int export[EFFECT_MAX]; +}; + +struct effect_struct { + int sum; + struct effect_type eff[EFFECT_ITEM_MAX]; +}; + +struct hw_type { + int num; + char name[40]; + int export[HW_MAX]; +}; + +struct hw_struct { + int sum; + struct hw_type hw[HW_ITEM_MAX]; +}; + +struct wb_type { + int num; + char name[40]; + int export[2]; +}; + +struct wb_struct { + int sum; + struct wb_type wb[WB_ITEM_MAX]; +}; + +struct scene_type { + int num; + char name[40]; + int export[SCENE_MAX]; +}; + +struct scene_struct { + int sum; + struct scene_type scene[SCENE_ITEM_MAX]; +}; + +struct capture_type { + int num; + char name[40]; + int export[CAPTURE_ITEM_MAX]; +}; + +struct capture_struct { + int sum; + struct capture_type capture[CAPTURE_MAX]; +}; + +struct sensor_aet_s { + unsigned int exp; + unsigned int ag; + unsigned int vts; + unsigned int gain; + unsigned int fr; +}; +/* sensor_aet_t */ + +struct sensor_aet_info_s { + unsigned int fmt_main_fr; + unsigned int fmt_capture; /* false: preview, true: capture */ + unsigned int fmt_hactive; + unsigned int fmt_vactive; + unsigned int fmt_rated_fr; + unsigned int fmt_min_fr; + unsigned int tbl_max_step; + unsigned int tbl_rated_step; + unsigned int tbl_max_gain; + unsigned int tbl_min_gain; + unsigned int format_transfer_parameter; +}; +/* sensor_aet_info_t */ + +struct aet_type { + int num; + char name[40]; + struct sensor_aet_info_s *info; + struct sensor_aet_s *aet_table; +}; + +struct aet_struct { + int sum; + struct aet_type aet[AET_ITEM_MAX]; +}; + +struct wave_struct { + int export[WAVE_MAX]; +}; + +struct lens_type { + int num; + char name[40]; + int export[LENS_MAX]; +}; + +struct lens_struct { + int sum; + struct lens_type lens[LENS_ITEM_MAX]; +}; + +struct gamma_struct { + unsigned int gamma_r[GAMMA_MAX]; + unsigned int gamma_g[GAMMA_MAX]; + unsigned int gamma_b[GAMMA_MAX]; +}; + +struct wb_sensor_struct { + int export[WB_SENSOR_MAX]; +}; + +struct version_struct { + char date[40]; + char module[30]; + char version[30]; +}; + +struct cm_struct { + int export[CM_MAX]; +}; + +struct nr_type { + int num; + char name[40]; + int export[NR_MAX]; +}; + +struct nr_struct { + int sum; + struct nr_type nr[NR_ITEM_MAX]; +}; + +struct peaking_type { + int num; + char name[40]; + int export[PEAKING_MAX]; +}; + +struct peaking_struct { + int sum; + struct peaking_type peaking[PEAKING_ITEM_MAX]; +}; + +struct configure_s { + struct effect_struct eff; + int effect_valid; + struct hw_struct hw; + int hw_valid; + struct aet_struct aet; + int aet_valid; + struct capture_struct capture; + int capture_valid; + struct scene_struct scene; + int scene_valid; + struct wb_struct wb; + int wb_valid; + struct wave_struct wave; + int wave_valid; + struct lens_struct lens; + int lens_valid; + struct gamma_struct gamma; + int gamma_valid; + struct wb_sensor_struct wb_sensor_data; + int wb_sensor_data_valid; + struct version_struct version; + int version_info_valid; + struct cm_struct cm; + int cm_valid; + struct nr_struct nr; + int nr_valid; + struct peaking_struct peaking; + int peaking_valid; +}; + +struct para_index_s { + unsigned int effect_index; + unsigned int scenes_index; + unsigned int wb_index; + unsigned int capture_index; + unsigned int nr_index; + unsigned int peaking_index; + unsigned int lens_index; +}; + +struct wb_pair_t { + enum camera_wb_flip_e wb; + char *name; +}; + +struct effect_pair_t { + enum camera_special_effect_e effect; + char *name; +}; + +struct sensor_dg_s { + unsigned short r; + unsigned short g; + unsigned short b; + unsigned short dg_default; +}; + +struct camera_priv_data_s { + struct sensor_aet_info_s + *sensor_aet_info; /* point to 1 of up to 16 aet information */ + struct sensor_aet_s *sensor_aet_table; + unsigned int sensor_aet_step; /* current step of the current aet */ + struct configure_s *configure; +}; + +int parse_config(const char *path, struct configure_s *cf); +int generate_para(struct cam_parameter_s *para, struct para_index_s pindex, + struct configure_s *cf); +void free_para(struct cam_parameter_s *para); +int update_fmt_para(int width, int height, struct cam_parameter_s *para, + struct para_index_s *pindex, struct configure_s *cf); + +unsigned int get_aet_current_step(void *priv); +unsigned int get_aet_current_gain(void *pirv); +unsigned int get_aet_min_gain(void *priv); +unsigned int get_aet_max_gain(void *priv); +unsigned int get_aet_max_step(void *priv); +unsigned int get_aet_gain_by_step(void *priv, unsigned int new_step); + +int my_i2c_put_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, + unsigned short addr, unsigned char data); +int my_i2c_put_byte_add8(struct i2c_adapter *adapter, unsigned short i2c_addr, + char *buf, int len); +int my_i2c_get_byte(struct i2c_adapter *adapter, unsigned short i2c_addr, + unsigned short addr); +int my_i2c_get_word(struct i2c_adapter *adapter, unsigned short i2c_addr); +#endif + diff --git a/drivers/amlogic/media/camera/common/flashlight.c b/drivers/amlogic/media/camera/common/flashlight.c new file mode 100644 index 000000000000..51018d997832 --- /dev/null +++ b/drivers/amlogic/media/camera/common/flashlight.c @@ -0,0 +1,249 @@ +/* + * drivers/amlogic/media/camera/common/flashlight.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define FLASHLIGHT_MODULE_NAME "flashlight" +#define FLASHLIGHT_DRIVER_NAME "flashlight" +#define FLASHLIGHT_DEVICE_NAME "flashlight" +#define FLASHLIGHT_CLASS_NAME "flashlight" + +static dev_t flashlight_devno; +static struct cdev *flashlight_cdev; +static struct device *devp; + +static enum aml_plat_flashlight_status_s flashlight_flag = FLASHLIGHT_OFF; + +static ssize_t flashlight_ctrl_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count); +static ssize_t flashlightflag_show(struct class *cla, + struct class_attribute *attr, char *buf); +static ssize_t flashlightflag_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count); +static int flashlight_open(struct inode *inode, struct file *file); +static int flashlight_release(struct inode *inode, struct file *file); +static int flashlight_probe(struct platform_device *pdev); +static int flashlight_remove(struct platform_device *pdev); + +static struct platform_driver flashlight_driver = { + .probe = flashlight_probe, .remove = flashlight_remove, .driver = { + .name = + FLASHLIGHT_DRIVER_NAME, .owner = THIS_MODULE, + }, +}; + +static const struct file_operations flashlight_fops = { + .open = flashlight_open, .release = flashlight_release, +}; + +static struct class_attribute flashlight_class_attrs[] = { + __ATTR(flashlight_ctrl, 0644, NULL, flashlight_ctrl_store), + __ATTR(flashlightflag, 0644, flashlightflag_show, + flashlightflag_store), + __ATTR_NULL +}; +static struct class flashlight_class = { + .name = FLASHLIGHT_CLASS_NAME, + .class_attrs = flashlight_class_attrs, + .owner = THIS_MODULE, + }; + +static ssize_t flashlight_ctrl_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct aml_plat_flashlight_data_s *pdata = NULL; + struct device *dev = NULL; + + dev = devp; + pdata = (struct aml_plat_flashlight_data_s *)dev->platform_data; + if (pdata == NULL) { + pr_err("%s platform data is required!\n", __func__); + return -1; + } + if (!strncmp(buf, "0", 1)) { + if (pdata->flashlight_off) + pdata->flashlight_off(); + } else if (!strncmp(buf, "1", 1)) { + if (pdata->flashlight_on) + pdata->flashlight_on(); + } else { + pr_err("%s:%s error!Not support this parameter\n", + FLASHLIGHT_MODULE_NAME, __func__); + return -EINVAL; + } + return count; +} + +static ssize_t flashlightflag_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + sprintf(buf, "%d", (int)flashlight_flag); + return strlen(buf); +} + +static ssize_t flashlightflag_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + if (!strlen(buf)) + pr_info("%s parameter is required!\n", __func__); + flashlight_flag = (enum aml_plat_flashlight_status_s)(buf[0] - '0'); + return count; +} + +static int flashlight_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int flashlight_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int flashlight_probe(struct platform_device *pdev) +{ + int ret; + struct aml_plat_flashlight_data_s *pdata = NULL; + + ret = alloc_chrdev_region(&flashlight_devno, 0, + 1, FLASHLIGHT_DRIVER_NAME); + if (ret < 0) { + pr_err("%s:%s failed to allocate major number\n", + FLASHLIGHT_MODULE_NAME, __func__); + ret = -ENODEV; + goto out; + } + ret = class_register(&flashlight_class); + if (ret < 0) { + pr_err("%s:%s failed to register class\n", + FLASHLIGHT_MODULE_NAME, __func__); + goto error1; + } + flashlight_cdev = cdev_alloc(); + if (!flashlight_cdev) { + pr_err("%s:%s: failed to allocate memory\n", + FLASHLIGHT_MODULE_NAME, __func__); + ret = -ENOMEM; + goto error2; + } + cdev_init(flashlight_cdev, &flashlight_fops); + flashlight_cdev->owner = THIS_MODULE; + ret = cdev_add(flashlight_cdev, flashlight_devno, 1); + if (ret) { + pr_err("%s:%s: failed to add device\n", + FLASHLIGHT_MODULE_NAME, __func__); + goto error3; + } + devp = device_create(&flashlight_class, NULL, flashlight_devno, NULL, + FLASHLIGHT_DEVICE_NAME); + if (IS_ERR(devp)) { + pr_err("%s:%s failed to create device node\n", + FLASHLIGHT_MODULE_NAME, __func__); + ret = PTR_ERR(devp); + goto error3; + } + pr_info("%s:%s device %s created\n", FLASHLIGHT_MODULE_NAME, + __func__, FLASHLIGHT_DEVICE_NAME); + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "platform data is required!\n"); + ret = -EINVAL; + goto error4; + } + devp->platform_data = pdata; + return 0; +error4: + device_destroy(NULL, flashlight_devno); +error3: + cdev_del(flashlight_cdev); +error2: + class_unregister(&flashlight_class); +error1: + unregister_chrdev_region(flashlight_devno, 1); +out: + return ret; +} + +static int flashlight_remove(struct platform_device *pdev) +{ + unregister_chrdev_region(flashlight_devno, 1); + class_unregister(&flashlight_class); + device_destroy(NULL, flashlight_devno); + cdev_del(flashlight_cdev); + return 0; +} + +int set_flashlight(bool mode) +{ + struct aml_plat_flashlight_data_s *pdata = NULL; + + if (devp && devp->platform_data) { + pdata = devp->platform_data; + if (!mode) { + if (pdata->flashlight_off) + pdata->flashlight_off(); + } else { + if (pdata->flashlight_on) + pdata->flashlight_on(); + } + } + return 0; +} +EXPORT_SYMBOL(set_flashlight); + +enum aml_plat_flashlight_status_s get_flashlightflag(void) +{ + return flashlight_flag; +} +EXPORT_SYMBOL(get_flashlightflag); + +static int __init flashlight_init(void) +{ + int ret = -1; + + ret = platform_driver_register(&flashlight_driver); + if (ret != 0) { + pr_err("failed to register flashlight driver,error %d\n", ret); + return -ENODEV; + } + return ret; +} + +static void __exit flashlight_exit(void) +{ + platform_driver_unregister(&flashlight_driver); +} + +module_init(flashlight_init); +module_exit(flashlight_exit); + +MODULE_DESCRIPTION("AMLOGIC flashlight driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("amlogic"); diff --git a/drivers/amlogic/media/camera/common/plat_ctrl.c b/drivers/amlogic/media/camera/common/plat_ctrl.c new file mode 100644 index 000000000000..44aa8bd8e8b9 --- /dev/null +++ b/drivers/amlogic/media/camera/common/plat_ctrl.c @@ -0,0 +1,208 @@ +/* + * drivers/amlogic/media/camera/common/plat_ctrl.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "plat_ctrl.h" + +/**************************************************************** + * i2c functions + * **************************************************************/ +static int camera_read_buff(struct i2c_client *client, char *buf, int addr_len, + int data_len) +{ + int i2c_flag = -1; + struct i2c_msg msgs[] = {{ + .addr = client->addr, .flags = 0, + .len = addr_len, .buf = buf, + }, { + .addr = client->addr, .flags = I2C_M_RD, + .len = data_len, .buf = buf, + } + }; + + i2c_flag = i2c_transfer(client->adapter, msgs, 2); + + return i2c_flag; +} + +static int camera_write_buff(struct i2c_client *client, char *buf, int len) +{ + struct i2c_msg msg[] = {{ + .addr = client->addr, .flags = 0, /* |I2C_M_TEN, */ + .len = len, .buf = buf, + } + + }; + + if (i2c_transfer(client->adapter, msg, 1) < 0) { + pr_err("i2c error\n"); + return -1; + } else + return 0; +} + +int i2c_get_byte(struct i2c_client *client, unsigned short addr) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + + if (camera_read_buff(client, buff, 2, 1) < 0) + return -1; + return buff[0]; +} + +int i2c_get_byte_add8(struct i2c_client *client, unsigned char addr) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)(addr & 0xff); + + if (camera_read_buff(client, buff, 1, 1) < 0) + return -1; + return buff[0]; +} + +int i2c_get_word(struct i2c_client *client, unsigned short addr) +{ + unsigned short data; + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + + if (camera_read_buff(client, buff, 2, 2) < 0) + return -1; + + data = buff[0]; + data = (data << 8) | buff[1]; + return data; +} + +int i2c_put_byte(struct i2c_client *client, unsigned short addr, + unsigned char data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + buff[2] = data; + if (camera_write_buff(client, buff, 3) < 0) + return -1; + return 0; +} + +int i2c_put_word(struct i2c_client *client, unsigned short addr, + unsigned short data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)((addr >> 8) & 0xff); + buff[1] = (unsigned char)(addr & 0xff); + buff[2] = (unsigned char)((data >> 8) & 0xff); + buff[3] = (unsigned char)(data & 0xff); + + if (camera_write_buff(client, buff, 4) < 0) + return -1; + return 0; +} + +int i2c_put_byte_add8_new(struct i2c_client *client, unsigned char addr, + unsigned char data) +{ + unsigned char buff[4]; + + buff[0] = (unsigned char)(addr & 0xff); + buff[1] = (unsigned char)(data & 0xff); + if (camera_write_buff(client, buff, 2) < 0) + return -1; + return 0; +} + +int i2c_put_byte_add8(struct i2c_client *client, char *buf, int len) +{ + if (camera_write_buff(client, buf, len) < 0) + return -1; + return 0; +} + +int cam_i2c_send_msg(struct i2c_client *client, struct cam_i2c_msg_s i2c_msg) +{ + unsigned char buff[4]; + + switch (i2c_msg.type) { + case ADDR16_DATA16: + buff[0] = (unsigned char)((i2c_msg.addr >> 8) & 0xff); + buff[1] = (unsigned char)(i2c_msg.addr & 0xff); + buff[2] = (unsigned char)((i2c_msg.data >> 8) & 0xff); + buff[3] = (unsigned char)(i2c_msg.data & 0xff); + if (camera_write_buff(client, buff, 4) < 0) + return -1; + break; + case ADDR16_DATA8: + buff[0] = (unsigned char)((i2c_msg.addr >> 8) & 0xff); + buff[1] = (unsigned char)(i2c_msg.addr & 0xff); + buff[2] = (unsigned char)(i2c_msg.data & 0xff); + if (camera_write_buff(client, buff, 3) < 0) + return -1; + break; + case ADDR8_DATA16: + buff[0] = (unsigned char)(i2c_msg.addr & 0xff); + buff[1] = (unsigned char)((i2c_msg.data >> 8) & 0xff); + buff[2] = (unsigned char)(i2c_msg.data & 0xff); + if (camera_write_buff(client, buff, 3) < 0) + return -1; + break; + case ADDR8_DATA8: + buff[0] = (unsigned char)(i2c_msg.addr & 0xff); + buff[1] = (unsigned char)(i2c_msg.data & 0xff); + if (camera_write_buff(client, buff, 2) < 0) + return -1; + break; + case TIME_DELAY: + msleep(i2c_msg.data); + break; + default: + break; + } + return 0; +} + diff --git a/drivers/amlogic/media/camera/common/plat_ctrl.h b/drivers/amlogic/media/camera/common/plat_ctrl.h new file mode 100644 index 000000000000..6bcb6cbfc264 --- /dev/null +++ b/drivers/amlogic/media/camera/common/plat_ctrl.h @@ -0,0 +1,47 @@ +/* + * drivers/amlogic/media/camera/common/plat_ctrl.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _AMLOGIC_CAMERA_PLAT_CTRL_H +#define _AMLOGIC_CAMERA_PLAT_CTRL_H + +#define ADDR8_DATA8 0 +#define ADDR16_DATA8 1 +#define ADDR16_DATA16 2 +#define ADDR8_DATA16 3 +#define TIME_DELAY 0xfe +#define END_OF_SCRIPT 0xff + +struct cam_i2c_msg_s { + unsigned char type; + unsigned short addr; + unsigned short data; +}; + +extern int i2c_get_byte(struct i2c_client *client, unsigned short addr); +extern int i2c_get_word(struct i2c_client *client, unsigned short addr); +extern int i2c_get_byte_add8(struct i2c_client *client, unsigned char addr); +extern int i2c_put_byte(struct i2c_client *client, unsigned short addr, + unsigned char data); +extern int i2c_put_word(struct i2c_client *client, unsigned short addr, + unsigned short data); +extern int i2c_put_byte_add8_new(struct i2c_client *client, unsigned char addr, + unsigned char data); +extern int i2c_put_byte_add8(struct i2c_client *client, char *buf, int len); +extern int cam_i2c_send_msg(struct i2c_client *client, + struct cam_i2c_msg_s i2c_msg); + +#endif /* _AMLOGIC_CAMERA_PLAT_CTRL_H. */ diff --git a/drivers/amlogic/media/camera/common/vm.c b/drivers/amlogic/media/camera/common/vm.c new file mode 100644 index 000000000000..c994df2a3fec --- /dev/null +++ b/drivers/amlogic/media/camera/common/vm.c @@ -0,0 +1,2309 @@ +/* + * drivers/amlogic/media/camera/common/vm.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vm_log.h" +#include "vm.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/*class property info.*/ +#include "vmcls.h" + +/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#if 1 +#define GE2D_NV +#endif + +#if 0 +static unsigned int amlvm_time_log_enable; +module_param(amlvm_time_log_enable, uint, 0644); +MODULE_PARM_DESC(amlvm_time_log_enable, "enable vm time log when get frames"); +#endif + +#define MAX_VF_POOL_SIZE 8 + +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +/*same as tvin pool*/ +static int VM_POOL_SIZE = 6; +static int VF_POOL_SIZE = 6; +static int VM_CANVAS_ID = 24; +/*same as tvin pool*/ +#endif + + +/*the counter of VM*/ +#define VM_MAX_DEVS 2 + +static struct vm_device_s *vm_device[VM_MAX_DEVS]; + +/* static bool isvmused; */ + +static void vm_cache_this_flush(unsigned int buf_start, + unsigned int buf_size, + struct vm_init_s *info); + +static inline void vm_vf_put_from_provider(struct vframe_s *vf, + unsigned int vdin_id); +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +#define INCPTR(p) ptr_atomic_wrap_inc(&p) +#endif + +#ifdef CONFIG_AMLOGIC_CAPTURE_FRAME_ROTATE +static int vmdecbuf_size[] = { + 0x13B3000,/* 5M */ + 0xc00000,/* 3M */ + 0x753000,/* 2M */ + 0x4b0000,/* 1M3 */ + 0x300000,/* 1M */ + 0x12c000,/* VGA */ + 0x4b000,/* QVGA */ +}; +static struct v4l2_frmsize_discrete canvas_config_wh[] = { + {2624, 2624}, + {2048, 2048}, + {1600, 1600}, + {1280, 1280}, + {1024, 1024}, + {640, 640}, + {320, 320}, +}; +#else +static int vmdecbuf_size[] = { + 0xEE5000,/* 5M */ + 0x900000,/* 3M */ + 0x591000,/* 2M */ + 0x384000,/* 1M3 */ + 0x240000,/* 1M */ + 0xF0000,/* VGA */ + 0x3C000,/* QVGA */ +}; +static struct v4l2_frmsize_discrete canvas_config_wh[] = { + {2624, 1984}, + {2048, 1536}, + {1600, 1216}, + {1280, 960}, + {1024, 768}, + {640, 512}, + {320, 256}, +}; +#endif +#define GE2D_ENDIAN_SHIFT 24 +#define GE2D_ENDIAN_MASK (0x1 << GE2D_ENDIAN_SHIFT) +#define GE2D_BIG_ENDIAN (0 << GE2D_ENDIAN_SHIFT) +#define GE2D_LITTLE_ENDIAN (1 << GE2D_ENDIAN_SHIFT) + +#define PROVIDER_NAME "vm" + +static dev_t vm_devno; +static struct class *vm_clsp; + +#define VM_DEV_NAME "vm" +#define RECEIVER_NAME "vm" +#define VM_CLS_NAME "vm" + +static DEFINE_SPINLOCK(lock); + +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +static inline void ptr_atomic_wrap_inc(u32 *ptr) +{ + u32 i = *ptr; + + i++; + if (i >= VM_POOL_SIZE) + i = 0; + *ptr = i; +} +#endif + +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +static struct vframe_s vfpool[MAX_VF_POOL_SIZE]; +static s32 vfbuf_use[MAX_VF_POOL_SIZE]; +static s32 fill_ptr, get_ptr, putting_ptr, put_ptr; +#endif + +atomic_t waiting_flag = ATOMIC_INIT(0); + +static inline struct vframe_s *vm_vf_get_from_provider(unsigned int vdin_id); +static inline struct vframe_s *vm_vf_peek_from_provider(unsigned int vdin_id); +static inline void vm_vf_put_from_provider(struct vframe_s *vf, + unsigned int vdin_id); +static struct vframe_receiver_op_s *vf_vm_unreg_provider( + struct vm_device_s *vdevp); +static struct vframe_receiver_op_s *vf_vm_reg_provider(struct vm_device_s + *vdevp); +static void stop_vm_task(struct vm_device_s *vdevp); +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +static int prepare_vframe(struct vframe_s *vf); +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +/* + *********************************************** + * + * buffer op for video sink. + * + *********************************************** + */ + +#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +static struct vframe_s *local_vf_peek(unsigned int vdin_id) +{ + struct vframe_s *vf = NULL; + + vf = vm_vf_peek_from_provider(vdin_id); + if (vf) { + if (vm_device[vdin_id]->vm_skip_count > 0) { + vm_device[vdin_id]->vm_skip_count--; + vm_vf_get_from_provider(vdin_id); + vm_vf_put_from_provider(vf, vdin_id); + vf = NULL; + } + } + return vf; +} + +static struct vframe_s *local_vf_get(unsigned int vdin_id) +{ + return vm_vf_get_from_provider(vdin_id); +} + +static void local_vf_put(struct vframe_s *vf, unsigned int vdin_id) +{ + if (vf) + vm_vf_put_from_provider(vf, vdin_id); +} +#else + +static inline u32 index2canvas(u32 index) +{ + int i; + int start_canvas, count; + u32 canvas_tab[6]; + struct vdin_v4l2_ops_s *vops = get_vdin_v4l2_ops(); + + vops->get_tvin_canvas_info(&start_canvas, &count); + VM_POOL_SIZE = count; + VF_POOL_SIZE = count; + VM_CANVAS_ID = start_canvas; + for (i = 0; i < count; i++) + canvas_tab[i] = VM_CANVAS_INDEX + i; + return canvas_tab[index]; +} + +static struct vframe_s *vm_vf_peek(void *op_arg, unsigned int vdin_id) +{ + struct vframe_s *vf = NULL; + + vf = vm_vf_peek_from_provider(vdin_id); + if (vf) { + if (vm_device[vdin_id]->vm_skip_count > 0) { + vm_device[vdin_id]->vm_skip_count--; + vm_vf_get_from_provider(vdin_id); + vm_vf_put_from_provider(vf, vdin_id); + vf = NULL; + } + } + return vf; +} + +static struct vframe_s *vm_vf_get(void *op_arg, unsigned int vdin_id) +{ + return vm_vf_get_from_provider(vdin_id); +} + +static void vm_vf_put(struct vframe_s *vf, void *op_arg) +{ + prepare_vframe(vf); +} + +static int vm_vf_states(struct vframe_states *states, void *op_arg) +{ + return 0; +} + +static struct vframe_s *local_vf_peek(void) +{ + if (get_ptr == fill_ptr) + return NULL; + return &vfpool[get_ptr]; +} + +static struct vframe_s *local_vf_get(unsigned int vdin_id) +{ + struct vframe_s *vf; + + if (get_ptr == fill_ptr) + return NULL; + vf = &vfpool[get_ptr]; + INCPTR(get_ptr); + return vf; +} + +static void local_vf_put(struct vframe_s *vf, unsigned int vdin_id) +{ + int i; + int canvas_addr; + + if (!vf) + return; + INCPTR(putting_ptr); + for (i = 0; i < VF_POOL_SIZE; i++) { + canvas_addr = index2canvas(i); + if (vf->canvas0Addr == canvas_addr) { + vfbuf_use[i] = 0; + vm_vf_put_from_provider(vf, vdin_id); + } + } +} +#endif + +#if 0 +static int local_vf_states(struct vframe_states *states) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&lock, flags); + states->vf_pool_size = VF_POOL_SIZE; + + i = put_ptr - fill_ptr; + if (i < 0) + i += VF_POOL_SIZE; + states->buf_free_num = i; + + i = putting_ptr - put_ptr; + if (i < 0) + i += VF_POOL_SIZE; + states->buf_recycle_num = i; + + i = fill_ptr - get_ptr; + if (i < 0) + i += VF_POOL_SIZE; + states->buf_avail_num = i; + + spin_unlock_irqrestore(&lock, flags); + return 0; +} +#endif + +static int vm_receiver_event_fun(int type, void *data, void *private_data) +{ + struct vm_device_s *vdevp = (struct vm_device_s *)private_data; + + switch (type) { + case VFRAME_EVENT_PROVIDER_VFRAME_READY: + /* if (atomic_read(&waiting_flag)) { */ + wake_up_interruptible(&vdevp->frame_ready); + /* atomic_set(&waiting_flag, 0); */ + /* } */ + /* up(&vb_start_sema); */ + /* printk("vdin %d frame ready !!!!!\n", vdevp->index); */ + break; + case VFRAME_EVENT_PROVIDER_START: + /* printk("vm register!!!!!\n"); */ + vf_vm_reg_provider(vdevp); + vdevp->vm_skip_count = 0; + vdevp->test_zoom = 0; + break; + case VFRAME_EVENT_PROVIDER_UNREG: + /* printk("vm unregister!!!!!\n"); */ + vm_local_init(); + vf_vm_unreg_provider(vdevp); + /* printk("vm unregister succeed!!!!!\n"); */ + break; + default: + break; + } + return 0; +} + +static struct vframe_receiver_op_s vm_vf_receiver = { + .event_cb = vm_receiver_event_fun +}; + +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +static const struct vframe_operations_s vm_vf_provider = { + .peek = vm_vf_peek, + .get = vm_vf_get, + .put = vm_vf_put, + .vf_states = vm_vf_states, +}; + +static struct vframe_provider_s vm_vf_prov; +#endif + + +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +int get_unused_vm_index(void) +{ + int i; + + for (i = 0; i < VF_POOL_SIZE; i++) { + if (vfbuf_use[i] == 0) + return i; + } + return -1; +} +static int prepare_vframe(struct vframe_s *vf) +{ + struct vframe_s *new_vf; + int index; + + index = get_unused_vm_index(); + if (index < 0) + return -1; + new_vf = &vfpool[fill_ptr]; + memcpy(new_vf, vf, sizeof(struct vframe_s)); + vfbuf_use[index]++; + INCPTR(fill_ptr); + return 0; +} +#endif + +/* + ************************************************ + * + * buffer op for decoder, camera, etc. + * + ************************************************** + */ + +/* static const vframe_provider_t *vfp = NULL; */ + +void vm_local_init(void) +{ +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + int i; + + for (i = 0; i < MAX_VF_POOL_SIZE; i++) + vfbuf_use[i] = 0; + fill_ptr = get_ptr = putting_ptr = put_ptr = 0; +#endif +} + +static struct vframe_receiver_op_s *vf_vm_unreg_provider( + struct vm_device_s *vdevp) +{ + /* ulong flags; */ +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + vf_unreg_provider(&vm_vf_prov); +#endif + stop_vm_task(vdevp); + /* spin_lock_irqsave(&lock, flags); */ + /* vfp = NULL; */ + /* spin_unlock_irqrestore(&lock, flags); */ + return (struct vframe_receiver_op_s *)NULL; +} +EXPORT_SYMBOL(vf_vm_unreg_provider); + +static struct vframe_receiver_op_s *vf_vm_reg_provider(struct vm_device_s + *vdevp) +{ + ulong flags; + /* int ret; */ + spin_lock_irqsave(&lock, flags); + spin_unlock_irqrestore(&lock, flags); + vm_buffer_init(vdevp); +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + vf_reg_provider(&vm_vf_prov); +#endif + start_vm_task(vdevp); +#if 0 + start_simulate_task(); +#endif + return &vm_vf_receiver; +} +EXPORT_SYMBOL(vf_vm_reg_provider); + +static inline struct vframe_s *vm_vf_peek_from_provider(unsigned int vdin_id) +{ + struct vframe_provider_s *vfp; + struct vframe_s *vf; + char name[20]; + + sprintf(name, "%s%d", RECEIVER_NAME, vdin_id); + vfp = vf_get_provider(name); + if (!(vfp && vfp->ops && vfp->ops->peek)) + return NULL; + vf = vfp->ops->peek(vfp->op_arg); + return vf; +} + +static inline struct vframe_s *vm_vf_get_from_provider(unsigned int vdin_id) +{ + struct vframe_provider_s *vfp; + char name[20]; + + sprintf(name, "%s%d", RECEIVER_NAME, vdin_id); + vfp = vf_get_provider(name); + if (!(vfp && vfp->ops && vfp->ops->peek)) + return NULL; + return vfp->ops->get(vfp->op_arg); +} + +static inline void vm_vf_put_from_provider(struct vframe_s *vf, + unsigned int vdin_id) +{ + struct vframe_provider_s *vfp; + char name[20]; + + sprintf(name, "%s%d", RECEIVER_NAME, vdin_id); + vfp = vf_get_provider(name); + if (!(vfp && vfp->ops && vfp->ops->peek)) + return; + vfp->ops->put(vf, vfp->op_arg); +} + +/* + *********************************************** + * + * main task functions. + * + *********************************************** + */ + +static unsigned int print_ifmt; +/* module_param(print_ifmt, unsigned int, 0644); */ +/* MODULE_PARM_DESC(print_ifmt, "print input format\n"); */ + +static int get_input_format(struct vframe_s *vf) +{ + int format = GE2D_FORMAT_M24_NV21; + + if (vf->type & VIDTYPE_VIU_422) { + if (vf->type & VIDTYPE_INTERLACE_BOTTOM) + format = GE2D_FORMAT_S16_YUV422 | + (GE2D_FORMAT_S16_YUV422B & (3 << 3)); + else if (vf->type & VIDTYPE_INTERLACE_TOP) + format = GE2D_FORMAT_S16_YUV422 | + (GE2D_FORMAT_S16_YUV422T & (3 << 3)); + else + format = GE2D_FORMAT_S16_YUV422; + } else if (vf->type & VIDTYPE_VIU_NV21) { + if (vf->type & VIDTYPE_INTERLACE_BOTTOM) + format = GE2D_FORMAT_M24_NV21 | + (GE2D_FORMAT_M24_NV21B & (3 << 3)); + else if (vf->type & VIDTYPE_INTERLACE_TOP) + format = GE2D_FORMAT_M24_NV21 | + (GE2D_FORMAT_M24_NV21T & (3 << 3)); + else + format = GE2D_FORMAT_M24_NV21; + } else { + if (vf->type & VIDTYPE_INTERLACE_BOTTOM) + format = GE2D_FORMAT_M24_YUV420 | + (GE2D_FMT_M24_YUV420B & (3 << 3)); + else if (vf->type & VIDTYPE_INTERLACE_TOP) + format = GE2D_FORMAT_M24_YUV420 | + (GE2D_FORMAT_M24_YUV420T & (3 << 3)); + else + format = GE2D_FORMAT_M24_YUV420; + } + if (print_ifmt == 1) { + pr_debug("VIDTYPE_VIU_NV21=%x, vf->type=%x\n", + VIDTYPE_VIU_NV21, vf->type); + pr_debug("format=%x, w=%d, h=%d\n", + format, vf->width, vf->height); + print_ifmt = 0; + } + return format; +} + +#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER +static int calc_zoom(int *top, int *left, int *bottom, int *right, int zoom) +{ + u32 screen_width, screen_height; + s32 start, end; + s32 video_top, video_left, temp; + u32 video_width, video_height; + u32 ratio_x = 0; + u32 ratio_y = 0; + + if (zoom < 100) + zoom = 100; + + video_top = *top; + video_left = *left; + video_width = *right - *left + 1; + video_height = *bottom - *top + 1; + + screen_width = video_width * zoom / 100; + screen_height = video_height * zoom / 100; + + ratio_x = (video_width << 18) / screen_width; + if (ratio_x * screen_width < (video_width << 18)) + ratio_x++; + ratio_y = (video_height << 18) / screen_height; + + /* vertical */ + start = video_top + video_height / 2 - (video_height << 17) / ratio_y; + end = (video_height << 18) / ratio_y + start - 1; + + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + *top = temp; + } else + *top = 0; + + temp = *top + (video_height * ratio_y >> 18); + *bottom = (temp <= (video_height - 1)) ? temp : (video_height - 1); + + /* horizontal */ + start = video_left + video_width / 2 - (video_width << 17) / ratio_x; + end = (video_width << 18) / ratio_x + start - 1; + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + *left = temp; + } else + *left = 0; + + temp = *left + (video_width * ratio_x >> 18); + *right = (temp <= (video_width - 1)) ? temp : (video_width - 1); + return 0; +} +#endif + +static int get_input_frame(struct display_frame_s *frame, struct vframe_s *vf, + int zoom) +{ + int ret = 0; + int top, left, bottom, right; + + if (!vf) + return -1; + + frame->frame_top = 0; + frame->frame_left = 0; + frame->frame_width = vf->width; + frame->frame_height = vf->height; + top = 0; + left = 0; + bottom = vf->height - 1; + right = vf->width - 1; +#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + ret = calc_zoom(&top, &left, &bottom, &right, zoom); +#else + ret = get_curren_frame_para(&top, &left, &bottom, &right); +#endif + if (ret >= 0) { + frame->content_top = top & (~1); + frame->content_left = left & (~1); + frame->content_width = vf->width - 2 * frame->content_left; + frame->content_height = vf->height - 2 * frame->content_top; + } else { + frame->content_top = 0; + frame->content_left = 0; + frame->content_width = vf->width; + frame->content_height = vf->height; + } + return 0; +} + +static int get_output_format(int v4l2_format) +{ + int format = GE2D_FORMAT_S24_YUV444; + + switch (v4l2_format) { + case V4L2_PIX_FMT_RGB565X: + format = GE2D_FORMAT_S16_RGB_565; + break; + case V4L2_PIX_FMT_YUV444: + format = GE2D_FORMAT_S24_YUV444; + break; + case V4L2_PIX_FMT_VYUY: + format = GE2D_FORMAT_S16_YUV422; + break; + case V4L2_PIX_FMT_BGR24: + format = GE2D_FORMAT_S24_RGB; + break; + case V4L2_PIX_FMT_RGB24: + format = GE2D_FORMAT_S24_BGR; + break; + case V4L2_PIX_FMT_NV12: +#ifdef GE2D_NV + format = GE2D_FORMAT_M24_NV12; + break; +#endif + case V4L2_PIX_FMT_NV21: +#ifdef GE2D_NV + format = GE2D_FORMAT_M24_NV21; + break; +#endif + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + format = GE2D_FORMAT_S8_Y; + break; + default: + break; + } + return format; +} + + +struct vm_dma_contig_memory { + u32 magic; + void *vaddr; + dma_addr_t dma_handle; + unsigned long size; + int is_userptr; +}; + +int is_need_ge2d_pre_process(struct vm_output_para output_para) +{ + int ret = 0; + + switch (output_para.v4l2_format) { + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_YUV444: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + ret = 1; + break; + default: + break; + } + return ret; +} + +int is_need_sw_post_process(struct vm_output_para output_para) +{ + int ret = 0; + + switch (output_para.v4l2_memory) { + case MAGIC_DC_MEM: + case MAGIC_RE_MEM: + goto exit; + case MAGIC_SG_MEM: + case MAGIC_VMAL_MEM: + default: + ret = 1; + break; + } +exit: + return ret; +} + +int get_canvas_index(int v4l2_format, int *depth) +{ + int canvas = vm_device[0]->vm_canvas[0]; + *depth = 16; + switch (v4l2_format) { + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_VYUY: + canvas = vm_device[0]->vm_canvas[0]; + *depth = 16; + break; + case V4L2_PIX_FMT_YUV444: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB24: + canvas = vm_device[0]->vm_canvas[1]; + *depth = 24; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: +#ifdef GE2D_NV + canvas = vm_device[0]->vm_canvas[2] | + (vm_device[0]->vm_canvas[3] << 8); +#else + canvas = vm_device[0]->vm_canvas[2] | + (vm_device[0]->vm_canvas[3] << 8) | + (vm_device[0]->vm_canvas[4] << 16); +#endif + *depth = 12; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + canvas = vm_device[0]->vm_canvas[5] | + (vm_device[0]->vm_canvas[6] << 8) | + (vm_device[0]->vm_canvas[7] << 16); + *depth = 12; + break; + default: + break; + } + return canvas; +} + +int get_canvas_index_res(int ext_canvas, int v4l2_format, int *depth, int width, + int height, unsigned int buf) +{ + int canvas = ext_canvas; + *depth = 16; + switch (v4l2_format) { + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_VYUY: + canvas = ext_canvas & 0xff; + *depth = 16; + canvas_config(canvas, + (unsigned long)buf, + width * 2, height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + break; + case V4L2_PIX_FMT_YUV444: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB24: + canvas = ext_canvas & 0xff; + *depth = 24; + canvas_config(canvas, + (unsigned long)buf, + width * 3, height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + canvas_config(ext_canvas & 0xff, + (unsigned long)buf, + width, height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config((ext_canvas & 0xff00) >> 8, + (unsigned long)(buf + width * height), + width, height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas = ext_canvas & 0xffff; + *depth = 12; + break; + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV420: + canvas_config(ext_canvas & 0xff, + (unsigned long)buf, + width, height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config((ext_canvas & 0xff00) >> 8, + (unsigned long)(buf + width * height), + width / 2, height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config((ext_canvas & 0xff0000) >> 16, + (unsigned long)(buf + width * height * 5 / 4), + width / 2, height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas = ext_canvas & 0xffffff; + *depth = 12; + break; + default: + break; + } + return canvas; +} + +#if 0 +static void vm_dump_mem(char *path, void *phy_addr, struct vm_output_para *para) +{ + struct file *filp = NULL; + loff_t pos = 0; + void *buf = NULL; + unsigned int size = para->bytesperline * para->height; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + filp = filp_open(path, O_RDWR | O_CREAT, 0666); + + if (IS_ERR(filp)) { + pr_err("create %s error.\n", path); + return; + } + + + buf = phys_to_virt((unsigned long)phy_addr); + vfs_write(filp, buf, size, &pos); + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); +} + +static void vm_x_mem(char *path, struct vm_output_para *para) +{ + struct file *filp = NULL; + loff_t pos = 0; + void *buf = NULL; + unsigned int size = para->bytesperline * para->height; + unsigned int canvas_index = para->index; + struct canvas_s cv; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + filp = filp_open(path, O_CREAT | O_RDWR | O_APPEND, 0666); + + if (IS_ERR(filp)) { + pr_err("failed to create %s, error %p.\n", + path, filp); + return; + } + + for (; canvas_index != 0; canvas_index >>= 8) { + canvas_read(canvas_index & 0xff, &cv); + /* printk("index=%lx,canvas.addr=%lx, w=%d, h=%d\n", */ + /* canvas_index, cv.addr, cv.width, cv.height); */ + + buf = phys_to_virt(cv.addr); + + size = cv.width * cv.height; + + vfs_write(filp, buf, size, &pos); + vfs_fsync(filp, 0); + } + filp_close(filp, NULL); + set_fs(old_fs); +} +#endif + +int vm_fill_this_buffer(struct videobuf_buffer *vb, + struct vm_output_para *para, struct vm_init_s *info) + +{ + int depth = 0; + int ret = 0; + int canvas_index = -1; + int v4l2_format = V4L2_PIX_FMT_YUV444; + int magic = 0; + int ext_canvas; + struct videobuf_buffer buf = {0}; + + if (!info) + return -1; + if (info->vdin_id >= VM_MAX_DEVS) { + pr_err("beyond the device array bound .\n"); + return -1; + } + /* if (info->isused == false) */ + /* return -2; */ +#if 0 + if (!vb) + goto exit; +#else + if (!vb) { + buf.width = 640; + buf.height = 480; + v4l2_format = V4L2_PIX_FMT_YUV444; + vb = &buf; + } + + if (!vm_device[info->vdin_id]->task_running) + return -1; +#endif + + v4l2_format = para->v4l2_format; + magic = para->v4l2_memory; + switch (magic) { + case MAGIC_DC_MEM: + /* mem = vb->priv; */ + canvas_config(vm_device[0]->vm_canvas[11], + (dma_addr_t)para->vaddr, + vb->bytesperline, vb->height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_index = vm_device[0]->vm_canvas[11]; + depth = (vb->bytesperline << 3) / vb->width; + break; + case MAGIC_RE_MEM: + if (para->ext_canvas != 0) + canvas_index = get_canvas_index_res( + para->ext_canvas, v4l2_format, + &depth, vb->width, + (para->height == 0) ? vb->height : para->height, + (unsigned int)para->vaddr); + else if (info->vdin_id == 0) { + ext_canvas = ((vm_device[0]->vm_canvas[3]) | + (vm_device[0]->vm_canvas[4] << 8) | + (vm_device[0]->vm_canvas[5] << 16)); + canvas_index = + get_canvas_index_res(ext_canvas, + v4l2_format, &depth, vb->width, + vb->height, (unsigned int)para->vaddr); + } else { + ext_canvas = ((vm_device[1]->vm_canvas[0]) | + (vm_device[1]->vm_canvas[1] << 8) | + (vm_device[1]->vm_canvas[2] << 16)); + canvas_index = + get_canvas_index_res(ext_canvas, + v4l2_format, &depth, vb->width, + vb->height, (unsigned int)para->vaddr); + } + break; + case MAGIC_SG_MEM: + case MAGIC_VMAL_MEM: + if (vm_device[info->vdin_id]->buffer_start && + vm_device[info->vdin_id]->buffer_size) + canvas_index = get_canvas_index(v4l2_format, &depth); + break; + default: + canvas_index = vm_device[0]->vm_canvas[0]; + break; + } + vm_device[info->vdin_id]->output_para.width = vb->width; + vm_device[info->vdin_id]->output_para.height = vb->height; + vm_device[info->vdin_id]->output_para.bytesperline = + (vb->width * depth) >> 3; + vm_device[info->vdin_id]->output_para.index = canvas_index; + vm_device[info->vdin_id]->output_para.v4l2_format = v4l2_format; + vm_device[info->vdin_id]->output_para.v4l2_memory = magic; + vm_device[info->vdin_id]->output_para.mirror = para->mirror; + vm_device[info->vdin_id]->output_para.zoom = para->zoom; + vm_device[info->vdin_id]->output_para.angle = para->angle; + vm_device[info->vdin_id]->output_para.vaddr = para->vaddr; + vm_device[info->vdin_id]->output_para.ext_canvas = + (magic == MAGIC_RE_MEM) ? para->ext_canvas : 0; + complete(&vm_device[info->vdin_id]->vb_start_sema); + wait_for_completion(&vm_device[info->vdin_id]->vb_done_sema); + if (magic == MAGIC_RE_MEM) + vm_cache_this_flush((unsigned int)para->vaddr, + para->bytesperline * + para->height, info); + + return ret; +} + +/* + *for decoder input processing + * 1. output window should 1:1 as source frame size + * 2. keep the frame ratio + * 3. input format should be YUV420 , output format should be YUV444 + */ + +int vm_ge2d_pre_process(struct vframe_s *vf, + struct ge2d_context_s *context, + struct config_para_ex_s *ge2d_config, + struct vm_output_para output_para, + unsigned int index) +{ + int ret; + int src_top, src_left, src_width, src_height; + struct canvas_s cs0, cs1, cs2, cd; + int current_mirror = 0; + int cur_angle = 0; + struct display_frame_s input_frame = {0}; + + ret = get_input_frame(&input_frame, vf, output_para.zoom); + src_top = input_frame.content_top; + src_left = input_frame.content_left; + src_width = input_frame.content_width; + src_height = input_frame.content_height; + if (vm_device[index]->test_zoom) { + vm_device[index]->test_zoom = 0; + pr_debug("top is %d , left is %d\n", + input_frame.content_top, + input_frame.content_left); + pr_debug("width is %d , height is %d\n", + input_frame.content_width, + input_frame.content_height); + } +#ifdef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + current_mirror = output_para.mirror; + if (current_mirror < 0) + current_mirror = 0; +#else + current_mirror = camera_mirror_flag; +#endif + + cur_angle = output_para.angle; + if (current_mirror == 1) + cur_angle = (360 - cur_angle % 360); + else + cur_angle = cur_angle % 360; + + /* data operating. */ + ge2d_config->alu_const_color = 0; /* 0x000000ff; */ + ge2d_config->bitmask_en = 0; + ge2d_config->src1_gb_alpha = 0;/* 0xff; */ + ge2d_config->dst_xy_swap = 0; + + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + canvas_read(output_para.index & 0xff, &cd); + ge2d_config->dst_planes[0].addr = cd.addr; + ge2d_config->dst_planes[0].w = cd.width; + ge2d_config->dst_planes[0].h = cd.height; + ge2d_config->src_key.key_enable = 0; + ge2d_config->src_key.key_mask = 0; + ge2d_config->src_key.key_mode = 0; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config->src_para.format = get_input_format(vf); + ge2d_config->src_para.fill_color_en = 0; + ge2d_config->src_para.fill_mode = 0; + ge2d_config->src_para.x_rev = 0; + ge2d_config->src_para.y_rev = 0; + ge2d_config->src_para.color = 0xffffffff; + ge2d_config->src_para.top = 0; + ge2d_config->src_para.left = 0; + ge2d_config->src_para.width = vf->width; + ge2d_config->src_para.height = vf->height; + ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config->dst_para.canvas_index = output_para.index & 0xff; +#ifdef GE2D_NV + if ((output_para.v4l2_format != V4L2_PIX_FMT_YUV420) + && (output_para.v4l2_format != V4L2_PIX_FMT_YVU420)) + ge2d_config->dst_para.canvas_index = output_para.index; +#endif + ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config->dst_para.format = + get_output_format(output_para.v4l2_format) | + GE2D_LITTLE_ENDIAN; + ge2d_config->dst_para.fill_color_en = 0; + ge2d_config->dst_para.fill_mode = 0; + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + ge2d_config->dst_para.color = 0; + ge2d_config->dst_para.top = 0; + ge2d_config->dst_para.left = 0; + ge2d_config->dst_para.width = output_para.width; + ge2d_config->dst_para.height = output_para.height; + + if (current_mirror == 1) { + ge2d_config->dst_para.x_rev = 1; + ge2d_config->dst_para.y_rev = 0; + } else if (current_mirror == 2) { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 1; + } else { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + } + + if (cur_angle == 90) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.x_rev ^= 1; + } else if (cur_angle == 180) { + ge2d_config->dst_para.x_rev ^= 1; + ge2d_config->dst_para.y_rev ^= 1; + } else if (cur_angle == 270) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.y_rev ^= 1; + } + + if (ge2d_context_config_ex(context, ge2d_config) < 0) { + pr_err("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(context, src_left, src_top, + src_width, src_height, 0, 0, + output_para.width, output_para.height); + + /* for cr of yuv420p or yuv420sp. */ + if ((output_para.v4l2_format == V4L2_PIX_FMT_YUV420) + || (output_para.v4l2_format == V4L2_PIX_FMT_YVU420)) { + /* for cb. */ + canvas_read((output_para.index >> 8) & 0xff, &cd); + ge2d_config->dst_planes[0].addr = cd.addr; + ge2d_config->dst_planes[0].w = cd.width; + ge2d_config->dst_planes[0].h = cd.height; + ge2d_config->dst_para.canvas_index = + (output_para.index >> 8) & 0xff; +#ifndef GE2D_NV + ge2d_config->dst_para.format = + GE2D_FORMAT_S8_CB | GE2D_LITTLE_ENDIAN; +#else + ge2d_config->dst_para.format = + GE2D_FORMAT_S8_CR | GE2D_LITTLE_ENDIAN; +#endif + ge2d_config->dst_para.width = output_para.width / 2; + ge2d_config->dst_para.height = output_para.height / 2; + ge2d_config->dst_xy_swap = 0; + + if (current_mirror == 1) { + ge2d_config->dst_para.x_rev = 1; + ge2d_config->dst_para.y_rev = 0; + } else if (current_mirror == 2) { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 1; + } else { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + } + + if (cur_angle == 90) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.x_rev ^= 1; + } else if (cur_angle == 180) { + ge2d_config->dst_para.x_rev ^= 1; + ge2d_config->dst_para.y_rev ^= 1; + } else if (cur_angle == 270) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.y_rev ^= 1; + } + + if (ge2d_context_config_ex(context, ge2d_config) < 0) { + pr_err("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(context, src_left, src_top, + src_width, src_height, + 0, 0, ge2d_config->dst_para.width, + ge2d_config->dst_para.height); + } +#ifndef GE2D_NV + else if (output_para.v4l2_format == V4L2_PIX_FMT_NV12 || + output_para.v4l2_format == V4L2_PIX_FMT_NV21) { + canvas_read((output_para.index >> 8) & 0xff, &cd); + ge2d_config->dst_planes[0].addr = cd.addr; + ge2d_config->dst_planes[0].w = cd.width; + ge2d_config->dst_planes[0].h = cd.height; + ge2d_config->dst_para.canvas_index = + (output_para.index >> 8) & 0xff; + ge2d_config->dst_para.format = + GE2D_FORMAT_S8_CB | GE2D_LITTLE_ENDIAN; + ge2d_config->dst_para.width = output_para.width / 2; + ge2d_config->dst_para.height = output_para.height / 2; + ge2d_config->dst_xy_swap = 0; + + if (current_mirror == 1) { + ge2d_config->dst_para.x_rev = 1; + ge2d_config->dst_para.y_rev = 0; + } else if (current_mirror == 2) { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 1; + } else { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + } + + if (cur_angle == 90) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.x_rev ^= 1; + } else if (cur_angle == 180) { + ge2d_config->dst_para.x_rev ^= 1; + ge2d_config->dst_para.y_rev ^= 1; + } else if (cur_angle == 270) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.y_rev ^= 1; + } + + if (ge2d_context_config_ex(context, ge2d_config) < 0) { + pr_err("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(context, src_left, src_top, + src_width, src_height, 0, 0, + ge2d_config->dst_para.width, + ge2d_config->dst_para.height); + } +#endif + + /* for cb of yuv420p or yuv420sp. */ + if (output_para.v4l2_format == V4L2_PIX_FMT_YUV420 || + output_para.v4l2_format == V4L2_PIX_FMT_YVU420 +#ifndef GE2D_NV + || output_para.v4l2_format == V4L2_PIX_FMT_NV12 || + output_para.v4l2_format == V4L2_PIX_FMT_NV21 +#endif + ) { + canvas_read((output_para.index >> 16) & 0xff, &cd); + ge2d_config->dst_planes[0].addr = cd.addr; + ge2d_config->dst_planes[0].w = cd.width; + ge2d_config->dst_planes[0].h = cd.height; + ge2d_config->dst_para.canvas_index = + (output_para.index >> 16) & 0xff; +#ifndef GE2D_NV + ge2d_config->dst_para.format = + GE2D_FORMAT_S8_CR | GE2D_LITTLE_ENDIAN; +#else + ge2d_config->dst_para.format = + GE2D_FORMAT_S8_CB | GE2D_LITTLE_ENDIAN; +#endif + ge2d_config->dst_para.width = output_para.width / 2; + ge2d_config->dst_para.height = output_para.height / 2; + ge2d_config->dst_xy_swap = 0; + + if (current_mirror == 1) { + ge2d_config->dst_para.x_rev = 1; + ge2d_config->dst_para.y_rev = 0; + } else if (current_mirror == 2) { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 1; + } else { + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + } + + if (cur_angle == 90) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.x_rev ^= 1; + } else if (cur_angle == 180) { + ge2d_config->dst_para.x_rev ^= 1; + ge2d_config->dst_para.y_rev ^= 1; + } else if (cur_angle == 270) { + ge2d_config->dst_xy_swap = 1; + ge2d_config->dst_para.y_rev ^= 1; + } + + if (ge2d_context_config_ex(context, ge2d_config) < 0) { + pr_err("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(context, src_left, + src_top, src_width, src_height, + 0, 0, ge2d_config->dst_para.width, + ge2d_config->dst_para.height); + } + return output_para.index; +} + +int vm_sw_post_process(int canvas, uintptr_t addr, unsigned int index) +{ + int poss = 0, posd = 0; + int i = 0; + void __iomem *buffer_y_start; + void __iomem *buffer_u_start; + void __iomem *buffer_v_start = 0; + struct io_mapping *mapping_wc; + int offset = 0; + struct canvas_s canvas_work_y; + struct canvas_s canvas_work_u; + struct canvas_s canvas_work_v; + struct vm_output_para output_para = vm_device[index]->output_para; + + if (!addr) + return -1; + mapping_wc = io_mapping_create_wc(vm_device[index]->buffer_start, + vm_device[index]->buffer_size); + if (!mapping_wc) + return -1; + canvas_read(canvas & 0xff, &canvas_work_y); + offset = 0; + buffer_y_start = io_mapping_map_atomic_wc(mapping_wc, offset); + if (buffer_y_start == NULL) { + pr_err(" vm.postprocess:mapping buffer error\n"); + io_mapping_free(mapping_wc); + return -1; + } + if (output_para.v4l2_format == V4L2_PIX_FMT_BGR24 || + output_para.v4l2_format == V4L2_PIX_FMT_RGB24 || + output_para.v4l2_format == V4L2_PIX_FMT_RGB565X) { + for (i = 0; i < output_para.height; i++) { + memcpy((void *)(addr + poss), + (void *)(buffer_y_start + posd), + output_para.bytesperline); + poss += output_para.bytesperline; + posd += canvas_work_y.width; + } + io_mapping_unmap_atomic(buffer_y_start); + + } else if (output_para.v4l2_format == V4L2_PIX_FMT_NV12 || + output_para.v4l2_format == V4L2_PIX_FMT_NV21) { +#ifdef GE2D_NV + unsigned int uv_width = output_para.width; + unsigned int uv_height = output_para.height >> 1; + + posd = 0; + for (i = output_para.height; i > 0; i--) { /* copy y */ + memcpy((void *)(addr + poss), + (void *)(buffer_y_start + posd), + output_para.width); + poss += output_para.width; + posd += canvas_work_y.width; + } + io_mapping_unmap_atomic(buffer_y_start); + + posd = 0; + canvas_read((canvas >> 8) & 0xff, &canvas_work_u); + offset = canvas_work_u.addr - canvas_work_y.addr; + buffer_u_start = io_mapping_map_atomic_wc(mapping_wc, offset); + for (i = uv_height; i > 0; i--) { /* copy uv */ + memcpy((void *)(addr + poss), + (void *)(buffer_u_start + posd), uv_width); + poss += uv_width; + posd += canvas_work_u.width; + } + + io_mapping_unmap_atomic(buffer_u_start); +#else + char *dst_buff = NULL; + char *src_buff = NULL; + char *src2_buff = NULL; + + canvas_read((canvas >> 8) & 0xff, &canvas_work_u); + poss = posd = 0; + for (i = 0; i < output_para.height; i += 2) { /* copy y */ + memcpy((void *)(addr + poss), + (void *)(buffer_y_start + posd), + output_para.width); + poss += output_para.width; + posd += canvas_work_y.width; + memcpy((void *)(addr + poss), + (void *)(buffer_y_start + posd), + output_para.width); + poss += output_para.width; + posd += canvas_work_y.width; + } + io_mapping_unmap_atomic(buffer_y_start); + + posd = 0; + canvas_read((canvas >> 16) & 0xff, &canvas_work_v); + offset = canvas_work_u.addr - canvas_work_y.addr; + buffer_u_start = io_mapping_map_atomic_wc(mapping_wc, offset); + offset = canvas_work_v.addr - canvas_work_y.addr; + buffer_v_start = io_mapping_map_atomic_wc(mapping_wc, offset); + + dst_buff = (char *)addr + + output_para.width * output_para.height; + src_buff = (char *)buffer_u_start; + src2_buff = (char *)buffer_v_start; + if (output_para.v4l2_format == V4L2_PIX_FMT_NV12) { + for (i = 0 ; i < output_para.height / 2; i++) { + interleave_uv(src_buff, src2_buff, + dst_buff, output_para.width / 2); + src_buff += canvas_work_u.width; + src2_buff += canvas_work_v.width; + dst_buff += output_para.width; + } + } else { + for (i = 0 ; i < output_para.height / 2; i++) { + interleave_uv(src2_buff, src_buff, + dst_buff, output_para.width / 2); + src_buff += canvas_work_u.width; + src2_buff += canvas_work_v.width; + dst_buff += output_para.width; + } + } + + + io_mapping_unmap_atomic(buffer_u_start); + io_mapping_unmap_atomic(buffer_v_start); +#endif + } else if ((output_para.v4l2_format == V4L2_PIX_FMT_YUV420) + || (output_para.v4l2_format == V4L2_PIX_FMT_YVU420)) { + int uv_width = output_para.width >> 1; + int uv_height = output_para.height >> 1; + + posd = 0; + for (i = output_para.height; i > 0; i--) { /* copy y */ + memcpy((void *)(addr + poss), + (void *)(buffer_y_start + posd), + output_para.width); + poss += output_para.width; + posd += canvas_work_y.width; + } + io_mapping_unmap_atomic(buffer_y_start); + + posd = 0; + canvas_read((canvas >> 8) & 0xff, &canvas_work_u); + offset = canvas_work_u.addr - canvas_work_y.addr; + buffer_u_start = io_mapping_map_atomic_wc(mapping_wc, offset); + + canvas_read((canvas >> 16) & 0xff, &canvas_work_v); + offset = canvas_work_v.addr - canvas_work_y.addr; + buffer_v_start = io_mapping_map_atomic_wc(mapping_wc, offset); + +#ifndef GE2D_NV + if (output_para.v4l2_format == V4L2_PIX_FMT_YUV420) +#else + if (output_para.v4l2_format == V4L2_PIX_FMT_YVU420) { +#endif + for (i = uv_height; i > 0; i--) { /* copy y */ + memcpy((void *)(addr + poss), + (void *)(buffer_u_start + posd), + uv_width); + poss += uv_width; + posd += canvas_work_u.width; + } + posd = 0; + for (i = uv_height; i > 0; i--) { /* copy y */ + memcpy((void *)(addr + poss), + (void *)(buffer_v_start + posd), + uv_width); + poss += uv_width; + posd += canvas_work_v.width; + } + } else { + for (i = uv_height; i > 0; i--) { /* copy v */ + memcpy((void *)(addr + poss), + (void *)(buffer_v_start + posd), + uv_width); + poss += uv_width; + posd += canvas_work_v.width; + } + posd = 0; + for (i = uv_height; i > 0; i--) { /* copy u */ + memcpy((void *)(addr + poss), + (void *)(buffer_u_start + posd), + uv_width); + poss += uv_width; + posd += canvas_work_u.width; + } + } + io_mapping_unmap_atomic(buffer_u_start); + io_mapping_unmap_atomic(buffer_v_start); +} + + if (mapping_wc) + io_mapping_free(mapping_wc); + + return 0; +} + +static struct task_struct *simulate_task_fd; + +static bool is_vf_available(unsigned int vdin_id) +{ + bool ret = ((local_vf_peek(vdin_id) != NULL) || + (!vm_device[vdin_id]->task_running)); + return ret; +} + +/* static int reset_frame = 1; */ +static int vm_task(void *data) +{ + int ret = 0; + struct vframe_s *vf; + int src_canvas; + struct vm_device_s *devp = (struct vm_device_s *) data; + struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; + struct ge2d_context_s *context = create_ge2d_work_queue(); + struct config_para_ex_s ge2d_config; + +#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES + struct timeval start; + struct timeval end; + unsigned long time_use = 0; +#endif + memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); + sched_setscheduler(current, SCHED_FIFO, ¶m); + allow_signal(SIGTERM); + while (1) { + ret = wait_for_completion_interruptible( + &devp->vb_start_sema); + + if (kthread_should_stop()) { + complete(&devp->vb_done_sema); + break; + } + + /* wait for frame from 656 provider until 500ms runs out */ + wait_event_interruptible_timeout(devp->frame_ready, + is_vf_available(devp->index), + msecs_to_jiffies(2000)); + + if (!devp->task_running) { + ret = -1; + goto vm_exit; + } + + /* start to convert frame. */ +#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES + do_gettimeofday(&start); +#endif + vf = local_vf_get(devp->index); + + if (vf) { + src_canvas = vf->canvas0Addr; + + /* step1 convert 422 format to other format.*/ + if (is_need_ge2d_pre_process(devp->output_para)) + src_canvas = vm_ge2d_pre_process(vf, context, + &ge2d_config, devp->output_para, + devp->index); +#if 0 + if (devp->dump == 2) { + vm_dump_mem(devp->dump_path, + (void *)output_para.vaddr, &output_para); + devp->dump = 0; + } +#endif + local_vf_put(vf, devp->index); +#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES + do_gettimeofday(&end); + time_use = (end.tv_sec - start.tv_sec) * 1000 + + (end.tv_usec - start.tv_usec) / 1000; + pr_debug("step 1, ge2d use: %ldms\n", time_use); + do_gettimeofday(&start); +#endif + + /* step2 copy to user memory. */ + + if (is_need_sw_post_process(devp->output_para)) + vm_sw_post_process(src_canvas, + devp->output_para.vaddr, devp->index); + +#ifdef CONFIG_AMLCAP_LOG_TIME_USEFORFRAMES + do_gettimeofday(&end); + time_use = (end.tv_sec - start.tv_sec) * 1000 + + (end.tv_usec - start.tv_usec) / 1000; + pr_debug("step 2, memcpy use: %ldms\n", time_use); +#endif + } + if (kthread_should_stop()) { + complete(&devp->vb_done_sema); + break; + } + complete(&devp->vb_done_sema); + } +vm_exit: + destroy_ge2d_work_queue(context); + while (!kthread_should_stop()) { + /*may not call stop, wait.. + *it is killed by SIGTERM,eixt on + *down_interruptible. + *if not call stop,this thread + *may on do_exit and + *kthread_stop may not work good; + */ + msleep(20);/*default 10ms*/ + } + return ret; +} + +/*simulate v4l2 device to request*/ +/*filling buffer,only for test use*/ +static int simulate_task(void *data) +{ + while (1) { + msleep(50); + pr_debug("simulate succeed\n"); + } + return 0; +} + +/* + *********************************************** + * + * init functions. + * + *********************************************** + */ + +int vm_buffer_init(struct vm_device_s *vdevp) +{ + int i, j; + u32 canvas_width, canvas_height; + u32 decbuf_size; + resource_size_t buf_start; + unsigned int buf_size; + int buf_num = 0; + int local_pool_size = 0; + + init_completion(&vdevp->vb_start_sema); + init_completion(&vdevp->vb_done_sema); + + buf_start = vdevp->buffer_start; + buf_size = vdevp->buffer_size; + + if (vdevp->index == 0) { + for (j = 0; j < MAX_CANVAS_INDEX; j++) { + memset(&(vdevp->vm_canvas[j]), -1, sizeof(int)); + vdevp->vm_canvas[j] = + canvas_pool_map_alloc_canvas("vm0"); + if (vdevp->vm_canvas[j] < 0) { + pr_err("alloc vm0_canvas %d failed\n", j); + return -1; + } + } + } else { + for (j = 0; j < MAX_CANVAS_INDEX; j++) { + memset(&(vdevp->vm_canvas[j]), -1, sizeof(int)); + vdevp->vm_canvas[j] = + canvas_pool_map_alloc_canvas("vm1"); + if (vdevp->vm_canvas[j] < 0) { + pr_err("alloc vm1_canvas %d failed\n", j); + return -1; + } + } + } + + if (!buf_start || !buf_size) + goto exit; + + for (i = 0; i < ARRAY_SIZE(vmdecbuf_size); i++) { + if (buf_size >= vmdecbuf_size[i]) + break; + } + if (i == ARRAY_SIZE(vmdecbuf_size)) { + pr_debug("vmbuf size=%d less than the smallest vmbuf size%d\n", + buf_size, vmdecbuf_size[i - 1]); + return -1; + } + + canvas_width = canvas_config_wh[i].width;/* 1920; */ + canvas_height = canvas_config_wh[i].height;/* 1200; */ + decbuf_size = vmdecbuf_size[i];/* 0x700000; */ + buf_num = buf_size / decbuf_size; + + if (buf_num > 0) + local_pool_size = 1; + else { + local_pool_size = 0; + pr_debug("need at least one buffer to handle 1920*1080 data.\n"); + } + + for (i = 0; i < local_pool_size; i++) { + canvas_config((vdevp->vm_canvas[0] + i), + (unsigned long)(buf_start + i * decbuf_size), + canvas_width * 2, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config((vdevp->vm_canvas[2] + i), + (unsigned long)(buf_start + i * decbuf_size), + canvas_width * 3, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config((vdevp->vm_canvas[4] + i), + (unsigned long)(buf_start + i * decbuf_size / 2), + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(vdevp->vm_canvas[6] + i, + (unsigned long)(buf_start + + (i + 1)*decbuf_size / 2), + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + + canvas_config((vdevp->vm_canvas[8] + i), + (unsigned long)(buf_start + + (i + 1)*decbuf_size / 2), + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config((vdevp->vm_canvas[10] + i), + (unsigned long)(buf_start + + (i + 3)*decbuf_size / 4), + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + vfbuf_use[i] = 0; +#endif + } + +exit: + return 0; + +} + +int start_vm_task(struct vm_device_s *vdevp) +{ + /* init the device. */ + vm_local_init(); + if (!vdevp->task) { + vdevp->task = kthread_create(vm_task, vdevp, vdevp->name); + if (IS_ERR(vdevp->task)) { + pr_err("thread creating error.\n"); + return -1; + } + init_waitqueue_head(&vdevp->frame_ready); + wake_up_process(vdevp->task); + } + vdevp->task_running = 1; + return 0; +} + +int start_simulate_task(void) +{ + if (!simulate_task_fd) { + simulate_task_fd = kthread_create(simulate_task, 0, "vm"); + if (IS_ERR(simulate_task_fd)) { + pr_err("thread creating error.\n"); + return -1; + } + wake_up_process(simulate_task_fd); + } + return 0; +} + + +void stop_vm_task(struct vm_device_s *vdevp) +{ + if (vdevp->task) { + vdevp->task_running = 0; + send_sig(SIGTERM, vdevp->task, 1); + complete(&vdevp->vb_start_sema); + wake_up_interruptible(&vdevp->frame_ready); + kthread_stop(vdevp->task); + vdevp->task = NULL; + } + vm_local_init(); +} + + +/* + ********************************************************************** + * + * global status. + * + ********************************************************************** + */ + +static int vm_enable_flag; + +int get_vm_status(void) +{ + return vm_enable_flag; +} + +void set_vm_status(int flag) +{ + if (flag >= 0) + vm_enable_flag = flag; + else + vm_enable_flag = 0; +} + +/* + ********************************************************************** + * + * file op section. + * + ********************************************************************** + */ + +void unset_vm_buf_res(struct vm_init_s *info) +{ + info->buffer_start = 0; +} + +static void vm_cache_this_flush(unsigned int buf_start, unsigned int buf_size, + struct vm_init_s *info) +{ + struct vm_device_s *devp = vm_device[info->vdin_id]; + + if (devp->dev) { + if ((buf_start >= info->buffer_start) && + ((buf_start + buf_size) <= (info->buffer_start + + info->vm_buf_size))) + dma_sync_single_for_cpu(devp->dev, + buf_start, buf_size, DMA_FROM_DEVICE); + } +} + +static int vm_open(struct inode *inode, struct file *file) +{ + struct ge2d_context_s *context = NULL; + + pr_info("open one vm device\n"); + file->private_data = context; + /* vm_device.open_count++; */ + return 0; +} + +static long vm_ioctl(struct file *filp, unsigned int cmd, unsigned long args) +{ + int ret = 0; + struct ge2d_context_s *context; + void __user *argp; + + context = (struct ge2d_context_s *)filp->private_data; + argp = (void __user *)args; + switch (cmd) { + case VM_IOC_2OSD0: + break; + case VM_IOC_ENABLE_PP: + break; + case VM_IOC_CONFIG_FRAME: + break; + default: + return -ENOIOCTLCMD; + } + return ret; +} + +static int vm_release(struct inode *inode, struct file *file) +{ + struct ge2d_context_s *context = + (struct ge2d_context_s *)file->private_data; + + if (context && (destroy_ge2d_work_queue(context) == 0)) { + /* vm_device.open_count--; */ + return 0; + } + pr_info("release one vm device\n"); + return -1; +} + +/* + ********************************************************************** + * + * file op init section. + * + ********************************************************************** + */ + +static const struct file_operations vm_fops = { + .owner = THIS_MODULE, + .open = vm_open, + .unlocked_ioctl = vm_ioctl, + .release = vm_release, +}; + +static ssize_t vm_attr_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ssize_t len = 0; + struct vm_device_s *devp; + + devp = dev_get_drvdata(dev); + if (devp->task_running == 0) { + len += sprintf(buf + len, "vm does not start\n"); + return len; + } + + len += sprintf((char *)buf + len, "vm parameters below\n"); + + return len; +} + +static ssize_t vm_attr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vm_device_s *devp; + unsigned int n = 0; + char *buf_orig, *ps, *token; + char *parm[6] = {NULL}; + + if (!buf) + return len; + + buf_orig = kstrdup(buf, GFP_KERNEL); + /* printk(KERN_INFO "input cmd : %s",buf_orig); */ + devp = dev_get_drvdata(dev); + if (devp->task_running == 0) { + len += sprintf((char *)buf + len, "vm does not start\n"); + return len; + } + + ps = buf_orig; + while (1) { + if (n >= ARRAY_SIZE(parm)) { + pr_err("parm array overflow.\n"); +#if 0 + pr_err("n=%d,ARRAY_SIZE(parm)=%d\n", + n, ARRAY_SIZE(parm)); +#endif + return len; + } + token = strsep(&ps, "\n"); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } + + if (strcmp(parm[0], "before") == 0) { + devp->dump = 1; + devp->dump_path = parm[1]; + pr_debug("this not support\n"); + } else if (strcmp(parm[0], "after") == 0) { + devp->dump = 2; + devp->dump_path = parm[1]; + pr_debug("after ge2d processed, store to %s\n", parm[1]); + } + + kfree(buf_orig); + return len; +} + +static DEVICE_ATTR(dump, 0664, vm_attr_show, vm_attr_store); + +static int vm_add_cdev(struct cdev *cdevp, + const struct file_operations *fops, + int minor) +{ + int ret; + dev_t devno = MKDEV(MAJOR(vm_devno), minor); + + cdev_init(cdevp, fops); + cdevp->owner = THIS_MODULE; + ret = cdev_add(cdevp, devno, 1); + return ret; +} + +int init_vm_device(struct vm_device_s *vdevp, struct platform_device *pdev) +{ + int ret = 0; + + ret = vm_add_cdev(&vdevp->cdev, &vm_fops, vdevp->index); + if (ret) { + pr_err("%s: failed to add cdev. !\n", __func__); + goto fail_add_cdev; + } + vdevp->dev = device_create(vm_clsp, &pdev->dev, MKDEV(MAJOR(vm_devno), + vdevp->index), + NULL, "%s%d", VM_DEV_NAME, vdevp->index); + if (IS_ERR(vdevp->dev)) { + pr_err("%s: failed to create device. !\n", __func__); + ret = PTR_ERR(vdevp->dev); + goto fail_create_device; + } + ret = device_create_file(vdevp->dev, &dev_attr_dump); + if (ret < 0) { + pr_err("%s: fail to create vdin attribute files.\n", __func__); + goto fail_create_dev_file; + } + + dev_set_drvdata(vdevp->dev, vdevp); + platform_set_drvdata(pdev, vdevp); + + /* if (vm_buffer_init(vdevp) < 0) */ + /* goto unregister_dev; */ +#ifndef CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER + vf_provider_init(&vm_vf_prov, PROVIDER_NAME, &vm_vf_provider, NULL); +#endif + /* vf_reg_provider(&vm_vf_prov); */ + vdevp->task = NULL; + vdevp->task_running = 0; + memset(&vdevp->output_para, 0, sizeof(struct vm_output_para)); + sprintf(vdevp->name, "%s%d", RECEIVER_NAME, vdevp->index); + sprintf(vdevp->vf_provider_name, "%s%d", "vdin", vdevp->index); + + snprintf(vdevp->vfm_map_chain, VM_MAP_NAME_SIZE, + "%s %s", vdevp->vf_provider_name, + vdevp->name); + snprintf(vdevp->vfm_map_id, VM_MAP_NAME_SIZE, + "vm-map-%d", vdevp->index); + if (vfm_map_add(vdevp->vfm_map_id, + vdevp->vfm_map_chain) < 0) { + pr_err("vm pipeline map creation failed %s.\n", + vdevp->vfm_map_id); + goto fail_create_dev_file; + } + + vf_receiver_init(&vdevp->vm_vf_recv, vdevp->name, + &vm_vf_receiver, vdevp); + + vf_reg_receiver(&vdevp->vm_vf_recv); + return 0; + + /* unregister_dev: */ +fail_create_dev_file: + device_destroy(vm_clsp, MKDEV(MAJOR(vm_devno), vdevp->index)); +fail_create_device: + cdev_del(&vdevp->cdev); +fail_add_cdev: + kfree(vdevp); + return ret; + +} + +int uninit_vm_device(struct platform_device *plat_dev) +{ + struct vm_device_s *vdevp; + + vdevp = platform_get_drvdata(plat_dev); + /* stop_vm_task(vdevp); */ + device_remove_file(vdevp->dev, &dev_attr_dump); + device_destroy(vm_clsp, MKDEV(MAJOR(vm_devno), vdevp->index)); + cdev_del(&vdevp->cdev); + vm_device[vdevp->index] = NULL; + + /* free drvdata */ + dev_set_drvdata(vdevp->dev, NULL); + platform_set_drvdata(plat_dev, NULL); + kfree(vdevp); + return 0; +} + +int vm_init_resource(size_t size, struct vm_init_s *info) +{ + struct vm_device_s *devp; +#ifdef CONFIG_CMA + devp = vm_device[info->vdin_id]; + if (size == 0) + return -1; + if (info->vm_pages && info->vm_buf_size != 0) { + + dma_release_from_contiguous(&devp->pdev->dev, + info->vm_pages, + info->vm_buf_size / PAGE_SIZE); + } + info->vm_pages = dma_alloc_from_contiguous(&devp->pdev->dev, + size / PAGE_SIZE, 0); + if (info->vm_pages) { + dma_addr_t phys; + + phys = page_to_phys(info->vm_pages); + info->buffer_start = phys; + info->vm_buf_size = size; + if (info->bt_path_count == 1) { + if (info->vdin_id == 0) + info->isused = true; + else + info->isused = false; + } else { + info->isused = true; + } + info->mem_alloc_succeed = true; + return 0; + } + + info->mem_alloc_succeed = false; + pr_err("CMA failed to allocate dma buffer\n"); + return -ENOMEM; +#else + if (size == 0) + return -1; + info->buffer_start = vm_device[info->vdin_id]->buffer_start; + info->vm_buf_size = vm_device[info->vdin_id]->buffer_size; + info->mem_alloc_succeed = true; + info->isused = true; + return 0; +#endif +} +EXPORT_SYMBOL(vm_init_resource); + +void vm_deinit_resource(struct vm_init_s *info) +{ +#ifdef CONFIG_CMA + struct vm_device_s *devp; + + devp = vm_device[info->vdin_id]; + if (info->vm_buf_size == 0) { + pr_warn("vm buf size equals 0\n"); + return; + } + unset_vm_buf_res(info); + + if (info->vm_pages) { + dma_release_from_contiguous(&devp->pdev->dev, + info->vm_pages, + info->vm_buf_size / PAGE_SIZE); + info->vm_buf_size = 0; + info->vm_pages = NULL; + info->isused = false; + info->mem_alloc_succeed = false; + } +#else + if (info->vm_buf_size) { + info->buffer_start = 0; + info->vm_buf_size = 0; + info->isused = false; + info->mem_alloc_succeed = false; + } +#endif +} +EXPORT_SYMBOL(vm_deinit_resource); + + +/******************************************************************* + * + * interface for Linux driver + * + * ******************************************************************/ + +static int vm_mem_device_init(struct reserved_mem *rmem, struct device *dev) +{ + struct platform_device *pdev = container_of(dev, + struct platform_device, dev); + struct vm_device_s *vdevp = platform_get_drvdata(pdev); + unsigned long mem_start, mem_end; + + vdevp->buffer_start = rmem->base; + vdevp->buffer_size = rmem->size; + mem_start = rmem->base; + mem_end = rmem->base + rmem->size - 1; + pr_info("init vm memsource %lx->%lx\n", mem_start, mem_end); + return 0; +} + +static const struct reserved_mem_ops rmem_vm_ops = { + .device_init = vm_mem_device_init, +}; + +static int __init vm_mem_setup(struct reserved_mem *rmem) +{ + rmem->ops = &rmem_vm_ops; + pr_info("vm share mem setup\n"); + return 0; +} + +/* MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0xff, LOG_LEVEL_DESC, LOG_MASK_DESC); */ + + +/* for driver. */ +static int vm_driver_probe(struct platform_device *pdev) +{ + int idx; + int ret; + struct vm_device_s *vdevp; + + pr_info("vm memory init\n"); + /* malloc vdev */ + vdevp = kmalloc(sizeof(struct vm_device_s), GFP_KERNEL); + if (!vdevp) + return -ENOMEM; + + memset(vdevp, 0, sizeof(struct vm_device_s)); + + if (pdev->dev.of_node) { + ret = of_property_read_u32(pdev->dev.of_node, + "vm_id", &(vdevp->index)); + if (ret) + pr_err("don't find vm id.\n"); + } + vm_device[vdevp->index] = vdevp; + vdevp->pdev = pdev; + platform_set_drvdata(pdev, vdevp); + vm_buffer_init(vdevp); + ret = init_vm_device(vdevp, pdev); + if (ret != 0) + return ret; + idx = of_reserved_mem_device_init(&pdev->dev); + if (idx == 0) + pr_info("vm probe done\n"); + else + pr_info("malloc reserved memory failed !\n"); + + /* init_vm_device(vdevp, pdev); */ + return 0; +} + +static int vm_drv_remove(struct platform_device *plat_dev) +{ + int i; + struct vm_device_s *vdevp; + + vdevp = platform_get_drvdata(plat_dev); + + for (i = 0; i < MAX_CANVAS_INDEX; i++) { + if ((vdevp != NULL) && + (vdevp->vm_canvas[i] >= 0)) { + canvas_pool_map_free_canvas( + vdevp->vm_canvas[i]); + memset(&(vdevp->vm_canvas[i]), + -1, sizeof(int)); + } + } + + if (vdevp->vfm_map_id[0]) { + vfm_map_remove(vdevp->vfm_map_id); + vdevp->vfm_map_id[0] = 0; + } + + uninit_vm_device(plat_dev); + return 0; +} + +static const struct of_device_id amlogic_vm_dt_match[] = { + { + .compatible = "amlogic, vm", + }, + {}, +}; + +/* general interface for a linux driver .*/ +static struct platform_driver vm_drv = { + .probe = vm_driver_probe, + .remove = vm_drv_remove, + .driver = { + .name = "vm", + .owner = THIS_MODULE, + .of_match_table = amlogic_vm_dt_match, + } +}; + +static int __init +vm_init_module(void) +{ + int ret = 0; + + pr_info("vm_init .\n"); + ret = alloc_chrdev_region(&vm_devno, 0, VM_MAX_DEVS, VM_DEV_NAME); + if (ret < 0) { + pr_err("%s: failed to allocate major number\n", __func__); + goto fail_alloc_cdev_region; + } + vm_clsp = class_create(THIS_MODULE, VM_CLS_NAME); + if (IS_ERR(vm_clsp)) { + ret = PTR_ERR(vm_clsp); + pr_err("%s: failed to create class\n", __func__); + goto fail_class_create; + } + ret = platform_driver_register(&vm_drv); + if (ret) { + pr_err("Failed to register vm driver (error=%d\n", + ret); + goto fail_pdrv_register; + } + return 0; + +fail_pdrv_register: + class_destroy(vm_clsp); +fail_class_create: + unregister_chrdev_region(vm_devno, VM_MAX_DEVS); +fail_alloc_cdev_region: + return ret; +} + +static void __exit +vm_remove_module(void) +{ + /* class_remove_file(vm_clsp, &class_attr_dump); */ + class_destroy(vm_clsp); + unregister_chrdev_region(vm_devno, VM_MAX_DEVS); + platform_driver_unregister(&vm_drv); + pr_info("vm module removed.\n"); +} + +module_init(vm_init_module); +module_exit(vm_remove_module); +RESERVEDMEM_OF_DECLARE(vm, "amlogic, vm_memory", vm_mem_setup); + +MODULE_DESCRIPTION("Amlogic Video Input Manager"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Simon Zheng "); diff --git a/drivers/amlogic/media/camera/common/vm.h b/drivers/amlogic/media/camera/common/vm.h new file mode 100644 index 000000000000..50305fcde63e --- /dev/null +++ b/drivers/amlogic/media/camera/common/vm.h @@ -0,0 +1,139 @@ +/* + * drivers/amlogic/media/camera/common/vm.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _VM_INCLUDE__ +#define _VM_INCLUDE__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/************************************* + ** + ** macro define + ** + *************************************/ + +#define VM_IOC_MAGIC 'P' +#define VM_IOC_2OSD0 _IOW(VM_IOC_MAGIC, 0x00, unsigned int) +#define VM_IOC_ENABLE_PP _IOW(VM_IOC_MAGIC, 0X01, unsigned int) +#define VM_IOC_CONFIG_FRAME _IOW(VM_IOC_MAGIC, 0X02, unsigned int) +#define MAX_CANVAS_INDEX 12 + +#define VM_MAP_NAME_SIZE 100 +#define VM_PROVIDER_NAME_SIZE 10 + +struct vm_device_s { + unsigned int index; + char name[20]; + struct platform_device *pdev; + int dump; + char *dump_path; + unsigned int open_count; + int major; + unsigned int dbg_enable; + /* struct class *cla; */ + struct cdev cdev; + struct device *dev; + resource_size_t buffer_start; + unsigned int buffer_size; +#ifdef CONFIG_CMA + ulong cma_pool_size; +#endif + struct vframe_receiver_s vm_vf_recv; + struct task_struct *task; + wait_queue_head_t frame_ready; + int task_running; + int vm_skip_count; + int test_zoom; + struct vm_output_para output_para; + struct completion vb_start_sema; + struct completion vb_done_sema; + char vf_provider_name[VM_PROVIDER_NAME_SIZE]; + char vfm_map_id[VM_MAP_NAME_SIZE]; + char vfm_map_chain[VM_MAP_NAME_SIZE]; + int vm_canvas[MAX_CANVAS_INDEX]; +}; + +struct display_frame_s { + int frame_top; + int frame_left; + int frame_width; + int frame_height; + int content_top; + int content_left; + int content_width; + int content_height; +}; + +int start_vm_task(struct vm_device_s *vdevp); +int start_simulate_task(void); + +extern int get_vm_status(void); +extern void set_vm_status(int flag); + +/* for vm device op. */ +extern int init_vm_device(struct vm_device_s *vdevp, + struct platform_device *pdev); +extern int uninit_vm_device(struct platform_device *plat_dev); + +/* for vm device class op. */ +extern struct class *init_vm_cls(void); + +/* for thread of vm. */ +extern int start_vpp_task(void); +extern void stop_vpp_task(void); + +/* for vm private member. */ +extern void set_vm_buf_info(resource_size_t start, unsigned int size); +extern void get_vm_buf_info(resource_size_t *start, unsigned int *size, + struct io_mapping **mapping); + +/* vm buffer op. */ +extern int vm_buffer_init(struct vm_device_s *vdevp); +extern void vm_local_init(void); + +extern void vm_deinit_resource(struct vm_init_s *info); + +static DEFINE_MUTEX(vm_mutex); + +/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TV */ +#if 1 +#define CANVAS_WIDTH_ALIGN 32 +#else +#define CANVAS_WIDTH_ALIGN 8 +#endif + +#define MAGIC_SG_MEM 0x17890714 +#define MAGIC_DC_MEM 0x0733ac61 +#define MAGIC_VMAL_MEM 0x18221223 +#define MAGIC_RE_MEM 0x123039dc + +#endif /* _VM_INCLUDE__ */ diff --git a/drivers/amlogic/media/camera/common/vm_log.h b/drivers/amlogic/media/camera/common/vm_log.h new file mode 100644 index 000000000000..4733cad79af5 --- /dev/null +++ b/drivers/amlogic/media/camera/common/vm_log.h @@ -0,0 +1,44 @@ +/* + * drivers/amlogic/media/camera/common/vm_log.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef VM_LOG_H +#define VM_LOG_H + +#define DEBUG +#ifdef DEBUG +#define AMLOG 1 +#define LOG_LEVEL_VAR amlog_level_ppmgr +#define LOG_MASK_VAR amlog_mask_ppmgr +#endif + +#define LOG_LEVEL_HIGH 0x00f +#define LOG_LEVEL_1 0x001 +#define LOG_LEVEL_LOW 0x000 + +#define LOG_LEVEL_DESC \ +"[0x00]LOW[0X01]LEVEL1[0xf]HIGH" + +#define LOG_MASK_INIT 0x001 +#define LOG_MASK_IOCTL 0x002 +#define LOG_MASK_HARDWARE 0x004 +#define LOG_MASK_CONFIG 0x008 +#define LOG_MASK_WORK 0x010 +#define LOG_MASK_DESC \ +"[0x01]:INIT,[0x02]:IOCTL,[0x04]:HARDWARE,[0x08]LOG_MASK_CONFIG[0x10]LOG_MASK_WORK" + +#endif + diff --git a/drivers/amlogic/media/camera/common/vmcls.h b/drivers/amlogic/media/camera/common/vmcls.h new file mode 100644 index 000000000000..3e81c379225a --- /dev/null +++ b/drivers/amlogic/media/camera/common/vmcls.h @@ -0,0 +1,189 @@ +/* + * drivers/amlogic/media/camera/common/vmcls.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#define VM_CLASS_NAME "vm" + +extern void interleave_uv(unsigned char *pU, unsigned char *pV, + unsigned char *pUV, unsigned int size_u_or_v); + +static ssize_t show_vm_info(struct class *cla, struct class_attribute *attr, + char *buf) +{ +#if 0 + resource_size_t bstart; + unsigned int bsize; + + get_vm_buf_info(&bstart, &bsize, NULL); + return snprintf(buf, 80, "buffer:\n start:%x.\tsize:%d\n", + (unsigned int)bstart, bsize / (1024 * 1024)); +#endif + return 0; +} + +static char attr_dat0[3] = "-1"; +static ssize_t read_attr0(struct class *cla, struct class_attribute *attr, + char *buf) +{ + return snprintf(buf, 3, "%s", attr_dat0); +} + +static ssize_t write_attr0(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + /* struct display_device *dsp = dev_get_drvdata(dev); */ + ssize_t ret = -EINVAL; + + if (count <= 2) { + int i = 0; + + if (buf[0] == '-') { + attr_dat0[0] = '-'; + i = 1; + ret++; + } + if ((buf[i] >= '0') && (buf[i] <= '9')) { + attr_dat0[i] = buf[i]; + attr_dat0[i + 1] = '\0'; + ret++; + } else { + attr_dat0[0] = '-'; + attr_dat0[1] = '1'; /* default -1; */ + ret = -EINVAL; + } + } + + return ret; +} + +static char attr_dat1[3] = "-1"; +static ssize_t read_attr1(struct class *cla, struct class_attribute *attr, + char *buf) +{ + return snprintf(buf, 3, "%s", attr_dat1); +} + +static ssize_t write_attr1(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + /* struct display_device *dsp = dev_get_drvdata(dev); */ + ssize_t ret = -EINVAL; + + if (count <= 2) { + int i = 0; + + if (buf[0] == '-') { + attr_dat1[0] = '-'; + i = 1; + ret++; + } + if ((buf[i] >= '0') && (buf[i] <= '9')) { + attr_dat1[i] = buf[i]; + attr_dat1[i + 1] = '\0'; + ret++; + } else { + attr_dat1[0] = '-'; + attr_dat1[1] = '1'; /* default -1; */ + ret = -EINVAL; + } + } + + return ret; +} +int disable_gt2005; + +static ssize_t read_attr2(struct class *cla, struct class_attribute *attr, + char *buf) +{ + return disable_gt2005; +} + +static ssize_t write_attr2(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + /* struct display_device *dsp = dev_get_drvdata(dev); */ + ssize_t ret = -EINVAL; + + if (count <= 2) + disable_gt2005 = buf[0]; + + return ret; +} + +int camera_mirror_flag; /* 0: disable, 1: l&r mirror,2 t-b mirror */ + +static ssize_t mirror_read(struct class *cla, struct class_attribute *attr, + char *buf) +{ + if (camera_mirror_flag == 1) + return snprintf(buf, 80, + "currnet mirror mode is l-r mirror mode. value is: %d.\n", + camera_mirror_flag); + else if (camera_mirror_flag == 2) + return snprintf(buf, 80, + "currnet mirror mode is t-b mirror mode. value is: %d.\n", + camera_mirror_flag); + else + return snprintf(buf, 80, + "currnet mirror mode is normal mode. value is: %d.\n", + camera_mirror_flag); +} + +static ssize_t mirror_write(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + ssize_t size; + char *endp = "1"; + + camera_mirror_flag = kstrtoul(buf, 0, (unsigned long *)endp); + size = endp - buf; + return count; +} + +static struct class_attribute vm_class_attrs[] = { + __ATTR(info, 0644, + show_vm_info, NULL), + __ATTR(attr0, 0644, + read_attr0, write_attr0), + __ATTR(attr1, 0644, + read_attr1, write_attr1), + __ATTR(attr2, 0644, + read_attr2, write_attr2), + __ATTR(mirror, 0644, + mirror_read, mirror_write), + __ATTR_NULL +}; + +static struct class vm_class = { + .name = VM_CLASS_NAME, + .class_attrs = vm_class_attrs, + }; + +struct class *init_vm_cls() + { + int ret = 0; + + ret = class_register(&vm_class); + if (ret < 0) { + pr_err("error create vm class\n"); + return NULL; + } + return &vm_class; + } diff --git a/drivers/amlogic/media/camera/gc2145.c b/drivers/amlogic/media/camera/gc2145.c new file mode 100644 index 000000000000..3150faf2663b --- /dev/null +++ b/drivers/amlogic/media/camera/gc2145.c @@ -0,0 +1,3453 @@ +/* + * drivers/amlogic/media/camera/gc2145.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_WAKELOCK +#include +#endif +#include +#include +#include +#include +#include +#include "common/plat_ctrl.h" +#include +#include +#include +#include "common/vm.h" + +#define GC2145_CAMERA_MODULE_NAME "gc2145" + +/* Wake up at about 30 fps */ +#define WAKE_NUMERATOR 30 +#define WAKE_DENOMINATOR 1001 +#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ + +#define MAGIC_RE_MEM 0x123039dc +#define CAMERA_USER_CANVAS_INDEX 0x4e + +#define GC2145_CAMERA_MAJOR_VERSION 0 +#define GC2145_CAMERA_MINOR_VERSION 7 +#define GC2145_CAMERA_RELEASE 0 +#define GC2145_CAMERA_VERSION \ + KERNEL_VERSION(GC2145_CAMERA_MAJOR_VERSION, \ + GC2145_CAMERA_MINOR_VERSION, \ + GC2145_CAMERA_RELEASE) + +#define GC2145_DRIVER_VERSION "GC2145-COMMON-01-140722" + +/*unsigned short DGain_shutter,AGain_shutter,*/ +/*DGain_shutterH,DGain_shutterL,AGain_shutterH,*/ +/*AGain_shutterL,shutterH,shutterL,shutter;*/ +/*unsigned short UXGA_Cap = 0;*/ + +static struct i2c_client *g_i2c_client; +static u32 cur_reg; +static u8 cur_val; +static u8 is_first_time_open; + +enum DCAMERA_FLICKER { + + DCAMERA_FLICKER_50HZ = 0, + + DCAMERA_FLICKER_60HZ, + + FLICKER_MAX + +}; + +/*static unsigned short Antiflicker = DCAMERA_FLICKER_50HZ;*/ + +#define GC2145_NORMAL_Y0ffset 0x08 +#define GC2145_LOWLIGHT_Y0ffset 0x20 + +MODULE_DESCRIPTION("gc2145 On Board"); +MODULE_AUTHOR("amlogic-sh"); +MODULE_LICENSE("GPL v2"); + +static unsigned int video_nr = -1; /* videoX start number, -1 is autodetect. */ + +static unsigned int debug; +/* module_param(debug, uint, 0644); */ +/* MODULE_PARM_DESC(debug, "activates debug info"); */ + +static unsigned int vid_limit = 16; +/* module_param(vid_limit, uint, 0644); */ +/* MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); */ + +//static int vidio_set_fmt_ticks; + +static int GC2145_h_active = 640; /* 800; */ +static int GC2145_v_active = 480; /* 600; */ + +static int gc2145_have_open; + +static struct v4l2_fract gc2145_frmintervals_active = { + .numerator = 1, + .denominator = 15, +}; + +static int gc2145_night_or_normal; /* add by sp_yjp,20120905 */ +static struct vdin_v4l2_ops_s *vops; +/* supported controls */ +static struct v4l2_queryctrl gc2145_qctrl[] = { + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_MENU, + .name = "white balance", + .minimum = CAM_WB_AUTO, + .maximum = CAM_WB_FLUORESCENT, + .step = 0x1, + .default_value = CAM_WB_AUTO, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0, + .maximum = 8, + .step = 0x1, + .default_value = 4, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_COLORFX, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "effect", + .minimum = 0, + .maximum = 6, + .step = 0x1, + .default_value = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "banding", + .minimum = CAM_BANDING_50HZ, + .maximum = CAM_BANDING_60HZ, + .step = 0x1, + .default_value = CAM_BANDING_50HZ, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "scene mode", + .minimum = 0, + .maximum = 1, + .step = 0x1, + .default_value = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "flip on horizontal", + .minimum = 0, + .maximum = 1, + .step = 0x1, + .default_value = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "flip on vertical", + .minimum = 0, + .maximum = 1, + .step = 0x1, + .default_value = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_ZOOM_ABSOLUTE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Zoom, Absolute", + .minimum = 100, + .maximum = 300, + .step = 20, + .default_value = 100, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_ROTATE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Rotate", + .minimum = 0, + .maximum = 270, + .step = 90, + .default_value = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, + } +}; +struct v4l2_querymenu gc2145_qmenu_wbmode[] = { + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .index = CAM_WB_AUTO, + .name = "auto", + .reserved = 0, + }, { + .id = V4L2_CID_DO_WHITE_BALANCE, + .index = CAM_WB_CLOUD, + .name = "cloudy-daylight", + .reserved = 0, + }, { + .id = V4L2_CID_DO_WHITE_BALANCE, + .index = CAM_WB_INCANDESCENCE, + .name = "incandescent", + .reserved = 0, + }, { + .id = V4L2_CID_DO_WHITE_BALANCE, + .index = CAM_WB_DAYLIGHT, + .name = "daylight", + .reserved = 0, + }, { + .id = V4L2_CID_DO_WHITE_BALANCE, + .index = CAM_WB_FLUORESCENT, + .name = "fluorescent", + .reserved = 0, + }, { + .id = V4L2_CID_DO_WHITE_BALANCE, + .index = CAM_WB_WARM_FLUORESCENT, + .name = "warm-fluorescent", + .reserved = 0, + }, +}; + +struct v4l2_querymenu gc2145_qmenu_anti_banding_mode[] = { + { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .index = CAM_BANDING_50HZ, + .name = "50hz", + .reserved = 0, + }, { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .index = CAM_BANDING_60HZ, + .name = "60hz", + .reserved = 0, + }, +}; +static struct v4l2_frmivalenum gc2145_frmivalenum[] = { + { + .index = 0, + .pixel_format = V4L2_PIX_FMT_NV21, + .width = 352, + .height = 288, + .type = V4L2_FRMIVAL_TYPE_DISCRETE, + { + .discrete = { + .numerator = 1, + .denominator = 30,/* 15 */ + } + } + }, { + .index = 0, + .pixel_format = V4L2_PIX_FMT_NV21, + .width = 640, + .height = 480, + .type = V4L2_FRMIVAL_TYPE_DISCRETE, + { + .discrete = { + .numerator = 1, + .denominator = 30,/* 15 */ + } + } + }, { + .index = 1, + .pixel_format = V4L2_PIX_FMT_NV21, + .width = 1600, + .height = 1200, + .type = V4L2_FRMIVAL_TYPE_DISCRETE, + { + .discrete = { + .numerator = 1, + .denominator = 5, + } + } + }, +}; + + +struct gc2145_qmenu_set_s { + __u32 id; + int num; + struct v4l2_querymenu *gc2145_qmenu; +}; + +struct gc2145_qmenu_set_s gc2145_qmenu_set[] = { + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .num = ARRAY_SIZE(gc2145_qmenu_wbmode), + .gc2145_qmenu = gc2145_qmenu_wbmode, + }, { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .num = ARRAY_SIZE(gc2145_qmenu_anti_banding_mode), + .gc2145_qmenu = gc2145_qmenu_anti_banding_mode, + }, +}; + +static int vidioc_querymenu(struct file *file, void *priv, + struct v4l2_querymenu *a) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(gc2145_qmenu_set); i++) { + if (a->id && a->id == gc2145_qmenu_set[i].id) { + for (j = 0; j < gc2145_qmenu_set[i].num; j++) { + if (a->index == + gc2145_qmenu_set[i].gc2145_qmenu[j].index) { + memcpy(a, + &(gc2145_qmenu_set[i].gc2145_qmenu[j]), + sizeof(*a)); + return 0; + } + } + } + } + return -EINVAL; +} + +#define dprintk(dev, level, fmt, arg...) \ + v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) + +/* + * ------------------------------------------------------------------ + * Basic structures + * ------------------------------------------------------------------ + */ + +struct gc2145_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; +}; + +static struct gc2145_fmt formats[] = { + { + .name = "RGB565 (BE)", + .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ + .depth = 16, + }, { + .name = "RGB888 (24)", + .fourcc = V4L2_PIX_FMT_RGB24, /* 24 RGB-8-8-8 */ + .depth = 24, + }, { + .name = "BGR888 (24)", + .fourcc = V4L2_PIX_FMT_BGR24, /* 24 BGR-8-8-8 */ + .depth = 24, + }, { + .name = "12 Y/CbCr 4:2:0", + .fourcc = V4L2_PIX_FMT_NV12, + .depth = 12, + }, { + .name = "12 Y/CbCr 4:2:0", + .fourcc = V4L2_PIX_FMT_NV21, + .depth = 12, + }, { + .name = "YUV420P", + .fourcc = V4L2_PIX_FMT_YUV420, + .depth = 12, + }, { + .name = "YVU420P", + .fourcc = V4L2_PIX_FMT_YVU420, + .depth = 12, + } +}; + +static struct gc2145_fmt *get_format(struct v4l2_format *f) +{ + struct gc2145_fmt *fmt; + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + fmt = &formats[k]; + if (fmt->fourcc == f->fmt.pix.pixelformat) + break; + } + + if (k == ARRAY_SIZE(formats)) + return NULL; + + return &formats[k]; +} + +struct sg_to_addr { + int pos; + struct scatterlist *sg; +}; + +/* buffer for one video frame */ +struct gc2145_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct gc2145_fmt *fmt; + + unsigned int canvas_id; +}; + +struct gc2145_dmaqueue { + struct list_head active; + + /* thread for generating video stream*/ + struct task_struct *kthread; + wait_queue_head_t wq; + /* Counters to control fps rate */ + int frame; + int ini_jiffies; +}; + +static LIST_HEAD(gc2145_devicelist); + +struct gc2145_device { + struct list_head gc2145_devicelist; + struct v4l2_subdev sd; + struct v4l2_device v4l2_dev; + + spinlock_t slock; + struct mutex mutex; + + int users; + + /* various device info */ + struct video_device *vdev; + + struct gc2145_dmaqueue vidq; + + /* Several counters */ + unsigned long jiffies; + + /* Input Number */ + int input; + + /* platform device data from board initting. */ + struct aml_cam_info_s cam_info; + +#ifdef CONFIG_HAS_WAKELOCK + /* wake lock */ + struct wake_lock wake_lock; +#endif + + /* Control 'registers' */ + int qctl_regs[ARRAY_SIZE(gc2145_qctrl)]; + struct vm_init_s vminfo; +}; + +static inline struct gc2145_device *to_dev(struct v4l2_subdev *sd) +{ + return container_of(sd, struct gc2145_device, sd); +} + +struct gc2145_fh { + struct gc2145_device *dev; + + /* video capture */ + struct gc2145_fmt *fmt; + unsigned int width, height; + struct videobuf_queue vb_vidq; + + struct videobuf_res_privdata res; + enum v4l2_buf_type type; + int input; /* Input Number on bars */ + int stream_on; + unsigned int f_flags; +}; + +/* + *static inline struct gc2145_fh *to_fh(struct gc2145_device *dev) + *{ + * return container_of(dev, struct gc2145_fh, dev); + *} + */ + +static struct v4l2_frmsize_discrete + gc2145_prev_resolution[] = { + /* should include 352x288 and 640x480,*/ + /*those two size are used for recording*/ + {352, 288}, + {640, 480}, +}; + +static struct v4l2_frmsize_discrete gc2145_pic_resolution[] = { + {1600, 1200}, + {800, 600} +}; + +#ifndef GC2145_MIRROR +#define GC2145_MIRROR 0 +#endif +#ifndef GC2145_FLIP +#define GC2145_FLIP 0 +#endif + +/* + *------------------------------------------------------------------ + * reg spec of GC2145 + * ------------------------------------------------------------------ + */ + +struct aml_camera_i2c_fig_s GC2145_script[] = { + /*SENSORDB("GC2145_Sensor_Init"}*/ + {0xfe, 0xf0}, + {0xfe, 0xf0}, + {0xfe, 0xf0}, + {0xfc, 0x06}, + {0xf6, 0x00}, + {0xf7, 0x1d}, + {0xf8, 0x84}, + {0xfa, 0x00}, + {0xf9, 0xfe}, + {0xf2, 0x00}, + /*ISP reg*/ + {0xfe, 0x00}, + {0x03, 0x04}, + {0x04, 0xe2}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x04}, + {0x0e, 0xc0}, + {0x0f, 0x06}, + {0x10, 0x52}, + {0x12, 0x2e}, + {0x17, 0x14}, /*mirror*/ + {0x18, 0x22}, + {0x19, 0x0e}, + {0x1a, 0x01}, + {0x1b, 0x4b}, + {0x1c, 0x07}, + {0x1d, 0x10}, + {0x1e, 0x88}, + {0x1f, 0x78}, + {0x20, 0x03}, + {0x21, 0x40}, + {0x22, 0xa0}, + {0x24, 0x16}, + {0x25, 0x01}, + {0x26, 0x10}, + {0x2d, 0x60}, + {0x30, 0x01}, + {0x31, 0x90}, + {0x33, 0x06}, + {0x34, 0x01}, + /*ISP reg*/ + {0xfe, 0x00}, + {0x80, 0x7f}, + {0x81, 0x26}, + {0x82, 0xfa}, + {0x83, 0x00}, + {0x84, 0x02}, + {0x86, 0x01},/*0x03*/ + {0x88, 0x03}, + {0x89, 0x03}, + {0x85, 0x08}, + {0x8a, 0x00}, + {0x8b, 0x00}, + {0xb0, 0x55}, + {0xc3, 0x00}, + {0xc4, 0x80}, + {0xc5, 0x90}, + {0xc6, 0x3b}, + {0xc7, 0x46}, + {0xec, 0x06}, + {0xed, 0x04}, + {0xee, 0x60}, + {0xef, 0x90}, + {0xb6, 0x01}, + {0x90, 0x01}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x04}, + {0x96, 0xb0}, + {0x97, 0x06}, + {0x98, 0x40}, + /*BLK*/ + {0xfe, 0x00}, + {0x40, 0x42}, + {0x41, 0x00}, + {0x43, 0x5b}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x20}, + {0x67, 0x20}, + {0x68, 0x20}, + {0x69, 0x20}, + {0x76, 0x00}, + {0x6a, 0x08}, + {0x6b, 0x08}, + {0x6c, 0x08}, + {0x6d, 0x08}, + {0x6e, 0x08}, + {0x6f, 0x08}, + {0x70, 0x08}, + {0x71, 0x08}, + {0x76, 0x00}, + {0x72, 0xf0}, + {0x7e, 0x3c}, + {0x7f, 0x00}, + {0xfe, 0x02}, + {0x48, 0x15}, + {0x49, 0x00}, + {0x4b, 0x0b}, + {0xfe, 0x00}, + /*AEC*/ + {0xfe, 0x01}, + {0x01, 0x04}, + {0x02, 0xc0}, + {0x03, 0x04}, + {0x04, 0x90}, + {0x05, 0x30}, + {0x06, 0x90}, + {0x07, 0x30}, + {0x08, 0x80}, + {0x09, 0x00}, + {0x0a, 0x82}, + {0x0b, 0x11}, + {0x0c, 0x10}, + {0x11, 0x10}, + {0x13, 0x7b}, + {0x17, 0x00}, + {0x1c, 0x11}, + {0x1e, 0x61}, + {0x1f, 0x35}, + {0x20, 0x40}, + {0x22, 0x40}, + {0x23, 0x20}, + {0xfe, 0x02}, + {0x0f, 0x04}, + {0xfe, 0x01}, + {0x12, 0x35}, + {0x15, 0xb0}, + {0x10, 0x31}, + {0x3e, 0x28}, + {0x3f, 0xb0}, + {0x40, 0x90}, + {0x41, 0x0f}, + /*INTPEE*/ + {0xfe, 0x02}, + {0x90, 0x6c}, + {0x91, 0x03}, + {0x92, 0xcb}, + {0x94, 0x33}, + {0x95, 0x84}, + {0x97, 0x65}, + {0xa2, 0x11}, + {0xfe, 0x00}, + /*DNDD*/ + {0xfe, 0x02}, + {0x80, 0xc1}, + {0x81, 0x08}, + {0x82, 0x05}, + {0x83, 0x08}, + {0x84, 0x0a}, + {0x86, 0xf0}, + {0x87, 0x50}, + {0x88, 0x15}, + {0x89, 0xb0}, + {0x8a, 0x30}, + {0x8b, 0x10}, + /*ASDE*/ + {0xfe, 0x01}, + {0x21, 0x04}, + {0xfe, 0x02}, + {0xa3, 0x50}, + {0xa4, 0x20}, + {0xa5, 0x40}, + {0xa6, 0x80}, + {0xab, 0x40}, + {0xae, 0x0c}, + {0xb3, 0x46}, + {0xb4, 0x64}, + {0xb6, 0x38}, + {0xb7, 0x01}, + {0xb9, 0x2b}, + {0x3c, 0x04}, + {0x3d, 0x15}, + {0x4b, 0x06}, + {0x4c, 0x20}, + {0xfe, 0x00}, + + /*gamma1*/ +#if 1 + {0xfe, 0x02}, + {0x10, 0x09}, + {0x11, 0x0d}, + {0x12, 0x13}, + {0x13, 0x19}, + {0x14, 0x27}, + {0x15, 0x37}, + {0x16, 0x45}, + {0x17, 0x53}, + {0x18, 0x69}, + {0x19, 0x7d}, + {0x1a, 0x8f}, + {0x1b, 0x9d}, + {0x1c, 0xa9}, + {0x1d, 0xbd}, + {0x1e, 0xcd}, + {0x1f, 0xd9}, + {0x20, 0xe3}, + {0x21, 0xea}, + {0x22, 0xef}, + {0x23, 0xf5}, + {0x24, 0xf9}, + {0x25, 0xff}, +#else + {0xfe, 0x02}, + {0x10, 0x0a}, + {0x11, 0x12}, + {0x12, 0x19}, + {0x13, 0x1f}, + {0x14, 0x2c}, + {0x15, 0x38}, + {0x16, 0x42}, + {0x17, 0x4e}, + {0x18, 0x63}, + {0x19, 0x76}, + {0x1a, 0x87}, + {0x1b, 0x96}, + {0x1c, 0xa2}, + {0x1d, 0xb8}, + {0x1e, 0xcb}, + {0x1f, 0xd8}, + {0x20, 0xe2}, + {0x21, 0xe9}, + {0x22, 0xf0}, + {0x23, 0xf8}, + {0x24, 0xfd}, + {0x25, 0xff}, + {0xfe, 0x00}, +#endif + {0xfe, 0x00}, + {0xc6, 0x20}, + {0xc7, 0x2b}, + /*gamma2*/ +#if 1 + {0xfe, 0x02}, + {0x26, 0x0f}, + {0x27, 0x14}, + {0x28, 0x19}, + {0x29, 0x1e}, + {0x2a, 0x27}, + {0x2b, 0x33}, + {0x2c, 0x3b}, + {0x2d, 0x45}, + {0x2e, 0x59}, + {0x2f, 0x69}, + {0x30, 0x7c}, + {0x31, 0x89}, + {0x32, 0x98}, + {0x33, 0xae}, + {0x34, 0xc0}, + {0x35, 0xcf}, + {0x36, 0xda}, + {0x37, 0xe2}, + {0x38, 0xe9}, + {0x39, 0xf3}, + {0x3a, 0xf9}, + {0x3b, 0xff}, +#else + /*Gamma outdoor*/ + {0xfe, 0x02}, + {0x26, 0x17}, + {0x27, 0x18}, + {0x28, 0x1c}, + {0x29, 0x20}, + {0x2a, 0x28}, + {0x2b, 0x34}, + {0x2c, 0x40}, + {0x2d, 0x49}, + {0x2e, 0x5b}, + {0x2f, 0x6d}, + {0x30, 0x7d}, + {0x31, 0x89}, + {0x32, 0x97}, + {0x33, 0xac}, + {0x34, 0xc0}, + {0x35, 0xcf}, + {0x36, 0xda}, + {0x37, 0xe5}, + {0x38, 0xec}, + {0x39, 0xf8}, + {0x3a, 0xfd}, + {0x3b, 0xff}, +#endif + /*YCP*/ + {0xfe, 0x02}, + {0xd1, 0x32}, + {0xd2, 0x32}, + {0xd3, 0x40}, + {0xd6, 0xf0}, + {0xd7, 0x10}, + {0xd8, 0xda}, + {0xdd, 0x14}, + {0xde, 0x86}, + {0xed, 0x80}, + {0xee, 0x00}, + {0xef, 0x3f}, + {0xd8, 0xd8}, + /*abs*/ + {0xfe, 0x01}, + {0x9f, 0x40}, + /*LSC*/ + {0xfe, 0x01}, + {0xc2, 0x14}, + {0xc3, 0x0d}, + {0xc4, 0x0c}, + {0xc8, 0x15}, + {0xc9, 0x0d}, + {0xca, 0x0a}, + {0xbc, 0x24}, + {0xbd, 0x10}, + {0xbe, 0x0b}, + {0xb6, 0x25}, + {0xb7, 0x16}, + {0xb8, 0x15}, + {0xc5, 0x00}, + {0xc6, 0x00}, + {0xc7, 0x00}, + {0xcb, 0x00}, + {0xcc, 0x00}, + {0xcd, 0x00}, + {0xbf, 0x07}, + {0xc0, 0x00}, + {0xc1, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x00}, + {0xaa, 0x01}, + {0xab, 0x01}, + {0xac, 0x00}, + {0xad, 0x05}, + {0xae, 0x06}, + {0xaf, 0x0e}, + {0xb0, 0x0b}, + {0xb1, 0x07}, + {0xb2, 0x06}, + {0xb3, 0x17}, + {0xb4, 0x0e}, + {0xb5, 0x0e}, + {0xd0, 0x09}, + {0xd1, 0x00}, + {0xd2, 0x00}, + {0xd6, 0x08}, + {0xd7, 0x00}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xd3, 0x0a}, + {0xd4, 0x00}, + {0xd5, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x77}, + {0xa7, 0x77}, + {0xa8, 0x77}, + {0xa9, 0x77}, + {0xa1, 0x80}, + {0xa2, 0x80}, + {0xfe, 0x01}, + {0xdf, 0x0d}, + {0xdc, 0x25}, + {0xdd, 0x30}, + {0xe0, 0x77}, + {0xe1, 0x80}, + {0xe2, 0x77}, + {0xe3, 0x90}, + {0xe6, 0x90}, + {0xe7, 0xa0}, + {0xe8, 0x90}, + {0xe9, 0xa0}, + {0xfe, 0x00}, + /*AWB*/ + {0xfe, 0x01}, + {0x4f, 0x00}, + {0x4f, 0x00}, + {0x4b, 0x01}, + {0x4f, 0x00}, + {0x4c, 0x01}, /*D75*/ + {0x4d, 0x71}, + {0x4e, 0x01}, + {0x4c, 0x01}, + {0x4d, 0x91}, + {0x4e, 0x01}, + {0x4c, 0x01}, + {0x4d, 0x70}, + {0x4e, 0x01}, + {0x4c, 0x01}, /*D65*/ + {0x4d, 0x90}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0xb0}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0x8f}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0x6f}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0xaf}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0xd0}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0xf0}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0xcf}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0xef}, + {0x4e, 0x02}, + {0x4c, 0x01},/*D50*/ + {0x4d, 0x6e}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8e}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xae}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xce}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x4d}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x6d}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8d}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xad}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xcd}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x4c}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x6c}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8c}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xac}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xcc}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xcb}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x4b}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x6b}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8b}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xab}, + {0x4e, 0x03}, + {0x4c, 0x01},/*CWF*/ + {0x4d, 0x8a}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0xaa}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0xca}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0xca}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0xc9}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0x8a}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0x89}, + {0x4e, 0x04}, + {0x4c, 0x01}, + {0x4d, 0xa9}, + {0x4e, 0x04}, + {0x4c, 0x02},/*tl84*/ + {0x4d, 0x0b}, + {0x4e, 0x05}, + {0x4c, 0x02}, + {0x4d, 0x0a}, + {0x4e, 0x05}, + {0x4c, 0x01}, + {0x4d, 0xeb}, + {0x4e, 0x05}, + {0x4c, 0x01}, + {0x4d, 0xea}, + {0x4e, 0x05}, + {0x4c, 0x02}, + {0x4d, 0x09}, + {0x4e, 0x05}, + {0x4c, 0x02}, + {0x4d, 0x29}, + {0x4e, 0x05}, + {0x4c, 0x02}, + {0x4d, 0x2a}, + {0x4e, 0x05}, + {0x4c, 0x02}, + {0x4d, 0x4a}, + {0x4e, 0x05}, + /*{0x4c , 0x02},*/ + /*{0x4d , 0x6a},*/ + /*{0x4e , 0x06},*/ + {0x4c, 0x02}, + {0x4d, 0x8a}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0x49}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0x69}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0x89}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0xa9}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0x48}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0x68}, + {0x4e, 0x06}, + {0x4c, 0x02}, + {0x4d, 0x69}, + {0x4e, 0x06}, + {0x4c, 0x02},/*H*/ + {0x4d, 0xca}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xc9}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xe9}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x09}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xc8}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xe8}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xa7}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xc7}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xe7}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x07}, + {0x4e, 0x07}, + {0x4f, 0x01}, + {0x50, 0x80}, + {0x51, 0xa8}, + {0x52, 0x47}, + {0x53, 0x38}, + {0x54, 0xc7}, + {0x56, 0x0e}, + {0x58, 0x08}, + {0x5b, 0x00}, + {0x5c, 0x74}, + {0x5d, 0x8b}, + {0x61, 0xdb}, + {0x62, 0xb8}, + {0x63, 0x86}, + {0x64, 0xc0}, + {0x65, 0x04}, + {0x67, 0xa8}, + {0x68, 0xb0}, + {0x69, 0x00}, + {0x6a, 0xa8}, + {0x6b, 0xb0}, + {0x6c, 0xaf}, + {0x6d, 0x8b}, + {0x6e, 0x50}, + {0x6f, 0x18}, + {0x73, 0xf0}, + {0x70, 0x0d}, + {0x71, 0x60}, + {0x72, 0x80}, + {0x74, 0x01}, + {0x75, 0x01}, + {0x7f, 0x0c}, + {0x76, 0x70}, + {0x77, 0x58}, + {0x78, 0xa0}, + {0x79, 0x5e}, + {0x7a, 0x54}, + {0x7b, 0x58}, + {0xfe, 0x00}, + /*CC*/ + {0xfe, 0x02}, + {0xc0, 0x01}, + {0xc1, 0x44}, + {0xc2, 0xfd}, + {0xc3, 0x04}, + {0xc4, 0xF0}, + {0xc5, 0x48}, + {0xc6, 0xfd}, + {0xc7, 0x46}, + {0xc8, 0xfd}, + {0xc9, 0x02}, + {0xca, 0xe0}, + {0xcb, 0x45}, + {0xcc, 0xec}, + {0xcd, 0x48}, + {0xce, 0xf0}, + {0xcf, 0xf0}, + {0xe3, 0x0c}, + {0xe4, 0x4b}, + {0xe5, 0xe0}, + /*ABS*/ + {0xfe, 0x01}, + {0x9f, 0x40}, + {0xfe, 0x00}, + /*OUTPUT*/ + {0xfe, 0x00}, + {0xf2, 0x0f}, + /*dark sun*/ + {0xfe, 0x02}, + {0x40, 0xbf}, + {0x46, 0xcf}, + {0xfe, 0x00}, + /*frame rate 50Hz*/ + {0xfe, 0x00}, + {0x05, 0x01}, + {0x06, 0x56}, + {0x07, 0x00}, + {0x08, 0x32}, + {0xfe, 0x01}, + {0x25, 0x00}, + {0x26, 0xfa}, + {0x27, 0x04}, + {0x28, 0xe2}, /*20fps*/ + {0x29, 0x06}, + {0x2a, 0xd6}, /*14fps*/ + {0x2b, 0x07}, + {0x2c, 0xd0}, /*12fps*/ + {0x2d, 0x0b}, + {0x2e, 0xb8}, /*8fps*/ + {0xfe, 0x00}, + + /*SENSORDB("GC2145_Sensor_SVGA"},*/ + + {0xfe, 0x00}, + {0xfd, 0x01}, + {0xfa, 0x00}, + /*crop window*/ + {0xfe, 0x00}, + {0x90, 0x01}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x02}, + {0x96, 0x58}, + {0x97, 0x03}, + {0x98, 0x20}, + {0x99, 0x11}, + {0x9a, 0x06}, + /*AWB*/ + {0xfe, 0x00}, + {0xec, 0x02}, + {0xed, 0x02}, + {0xee, 0x30}, + {0xef, 0x48}, + {0xfe, 0x02}, + {0x9d, 0x08}, + {0xfe, 0x01}, + {0x74, 0x00}, + /*AEC*/ + {0xfe, 0x01}, + {0x01, 0x04}, + {0x02, 0x60}, + {0x03, 0x02}, + {0x04, 0x48}, + {0x05, 0x18}, + {0x06, 0x50}, + {0x07, 0x10}, + {0x08, 0x38}, + {0x0a, 0x80}, + {0x21, 0x04}, + {0xfe, 0x00}, + {0x20, 0x03}, + {0xfe, 0x00}, + {0xff, 0xff}, +}; + +struct aml_camera_i2c_fig_s gc2145_svga[] = { + {0xfe, 0x00}, + {0xb6, 0x01}, + {0xfd, 0x01}, + {0xfa, 0x11}, + /*crop window*/ + {0xfe, 0x00}, + {0x90, 0x01}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x02}, + {0x96, 0x5a}, + {0x97, 0x03}, + {0x98, 0x22}, + {0x99, 0x11}, + {0x9a, 0x06}, + /*AWB*/ + {0xfe, 0x00}, + {0xec, 0x02}, + {0xed, 0x02}, + {0xee, 0x30}, + {0xef, 0x48}, + {0xfe, 0x02}, + {0x9d, 0x08}, + {0xfe, 0x01}, + {0x74, 0x00}, + /*AEC*/ + {0xfe, 0x01}, + {0x01, 0x04}, + {0x02, 0x60}, + {0x03, 0x02}, + {0x04, 0x48}, + {0x05, 0x18}, + {0x06, 0x50}, + {0x07, 0x10}, + {0x08, 0x38}, + {0x0a, 0x80}, + {0x21, 0x04}, + {0xfe, 0x00}, + {0x20, 0x03}, + {0xfe, 0x00}, + {0xff, 0xff}, +}; + +struct aml_camera_i2c_fig_s gc2145_uxga[] = { + {0xfe, 0x00}, + {0xfd, 0x00}, + {0xfa, 0x11}, + /*crop window*/ + {0xfe, 0x00}, + {0x90, 0x01}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x04}, + {0x96, 0xb2}, + {0x97, 0x06}, + {0x98, 0x42}, + {0x99, 0x11}, + {0x9a, 0x06}, + /*AWB*/ + {0xfe, 0x00}, + {0xec, 0x06}, + {0xed, 0x04}, + {0xee, 0x60}, + {0xef, 0x90}, + {0xfe, 0x01}, + {0x74, 0x01}, + /*AEC*/ + {0xfe, 0x01}, + {0x01, 0x04}, + {0x02, 0xc0}, + {0x03, 0x04}, + {0x04, 0x90}, + {0x05, 0x30}, + {0x06, 0x90}, + {0x07, 0x30}, + {0x08, 0x80}, + {0x0a, 0x82}, + {0xfe, 0x01}, + {0x21, 0x15}, + {0xfe, 0x00}, + {0x20, 0x15}, + {0xfe, 0x00}, + {0xff, 0xff}, +}; + +struct aml_camera_i2c_fig_s gc2145_1280x960[] = { + /*1280X960*/ + {0xfe, 0x00}, + {0xfa, 0x11}, + {0xfd, 0x00}, + {0x1c, 0x05}, + /*crop window*/ + {0xfe, 0x00}, + {0x99, 0x55}, + {0x9a, 0x06}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x01}, + {0x9e, 0x23}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x01}, + {0xa2, 0x23}, + {0x90, 0x01}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x03}, + {0x96, 0xc0}, + {0x97, 0x05}, + {0x98, 0x00}, + + /*AWB*/ + {0xfe, 0x00}, + {0xec, 0x06}, + {0xed, 0x04}, + {0xee, 0x60}, + {0xef, 0x90}, + {0xfe, 0x01}, + {0x74, 0x01}, + /*AEC*/ + {0xfe, 0x01}, + {0x01, 0x04}, + {0x02, 0xc0}, + {0x03, 0x04}, + {0x04, 0x90}, + {0x05, 0x30}, + {0x06, 0x90}, + {0x07, 0x30}, + {0x08, 0x80}, + {0x0a, 0x82}, + {0x21, 0x15}, + {0xfe, 0x00}, + {0x20, 0x15}, + {0xfe, 0x00}, +}; + +struct aml_camera_i2c_fig_s gc2145_FLICKER_50HZ[] = { + {0xfe, 0x00}, + {0x05, 0x01}, + {0x06, 0x56}, + {0x07, 0x00}, + {0x08, 0x32}, + {0xfe, 0x01}, + {0x25, 0x00}, + {0x26, 0xfa}, + {0x27, 0x04}, + {0x28, 0xe2}, /*20fps*/ + {0x29, 0x06}, + {0x2a, 0xd6}, /*14fps*/ + {0x2b, 0x07}, + {0x2c, 0xd0}, /*12fps*/ + {0x2d, 0x0b}, + {0x2e, 0xb8}, /*8fps*/ + {0xfe, 0x00}, + {0xff, 0xff}, +}; +struct aml_camera_i2c_fig_s gc2145_FLICKER_60HZ[] = { + {0x05, 0x01},/*hb*/ + {0x06, 0x58}, + {0x07, 0x00},/*vb*/ + {0x08, 0x32}, + {0xfe, 0x01}, + {0x25, 0x00},/*step*/ + {0x26, 0xd0}, + {0x27, 0x04},/*level1*/ + {0x28, 0xe0}, + {0x29, 0x06},/*level2*/ + {0x2a, 0x80}, + {0x2b, 0x08},/*level3*/ + {0x2c, 0x20}, + {0x2d, 0x0b},/*level4*/ + {0x2e, 0x60}, + {0xfe, 0x00}, + {0xff, 0xff}, +}; + +/* load GC2145 parameters */ +void GC2145_init_regs(struct gc2145_device *dev) +{ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + int i = 0; + + if (!dev->vminfo.isused) + return; + + while (1) { + if (GC2145_script[i].val == 0xff && + GC2145_script[i].addr == 0xff) { + pr_info("GC2145_write_regs success in initial.\n"); + break; + } + if ((i2c_put_byte_add8_new(client, GC2145_script[i].addr, + GC2145_script[i].val)) < 0) { + pr_err("fail in initial GC2145.\n"); + return; + } + i++; + } +} + +/* + ************************************************************************ + * FUNCTION + * GC2145_set_param_wb + * + * DESCRIPTION + * wb setting. + * + * PARAMETERS + * none + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + ************************************************************************ + */ + +void GC2145_set_param_wb(struct gc2145_device *dev, + enum camera_wb_flip_e para) /* white balance */ +{ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + unsigned int temp = 0; + + if (!dev->vminfo.isused) + return; + + i2c_put_byte_add8_new(client, 0xfe, 0x00); + temp = i2c_get_byte_add8(client, 0x82); + + switch (para) { + + case CAM_WB_AUTO:/* auto */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0xb3, 0x61); + i2c_put_byte_add8_new(client, 0xb4, 0x40); + i2c_put_byte_add8_new(client, 0xb5, 0x61); + i2c_put_byte_add8_new(client, 0x82, temp|0x2); + break; + + case CAM_WB_CLOUD: /* cloud */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); + i2c_put_byte_add8_new(client, 0xb3, 0x58); + i2c_put_byte_add8_new(client, 0xb4, 0x40); + i2c_put_byte_add8_new(client, 0xb5, 0x50); + break; + + case CAM_WB_DAYLIGHT: /* */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); + i2c_put_byte_add8_new(client, 0xb3, 0x70); + i2c_put_byte_add8_new(client, 0xb4, 0x40); + i2c_put_byte_add8_new(client, 0xb5, 0x50); + break; + + case CAM_WB_INCANDESCENCE: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); + i2c_put_byte_add8_new(client, 0xb3, 0x50); + i2c_put_byte_add8_new(client, 0xb4, 0x40); + i2c_put_byte_add8_new(client, 0xb5, 0xa8); + break; + + case CAM_WB_TUNGSTEN: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); + i2c_put_byte_add8_new(client, 0xb3, 0xa0); + i2c_put_byte_add8_new(client, 0xb4, 0x45); + i2c_put_byte_add8_new(client, 0xb5, 0x40); + break; + + case CAM_WB_FLUORESCENT: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x82, temp&(~0x02)); + i2c_put_byte_add8_new(client, 0xb3, 0x72); + i2c_put_byte_add8_new(client, 0xb4, 0x40); + i2c_put_byte_add8_new(client, 0xb5, 0x5b); + break; + + case CAM_WB_MANUAL: + /* TODO */ + break; + default: + break; + } + + +} /* GC2145_set_param_wb */ + +/* + ************************************************************************ + * FUNCTION + * GC2145_set_param_exposure + * + * DESCRIPTION + * exposure setting. + * + * PARAMETERS + * none + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + ************************************************************************ + */ + +void GC2145_set_param_exposure(struct gc2145_device *dev, + enum camera_exposure_e para) +{ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + + if (!dev->vminfo.isused) + return; + + switch (para) { + + case EXPOSURE_N4_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x55); /*target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + + + case EXPOSURE_N3_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x60); /*target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + + case EXPOSURE_N2_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x65); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + + case EXPOSURE_N1_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x70); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + case EXPOSURE_0_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x7b); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + case EXPOSURE_P1_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x85); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + case EXPOSURE_P2_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x90); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + case EXPOSURE_P3_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x95); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + case EXPOSURE_P4_STEP: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0xa0); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + + default: + i2c_put_byte_add8_new(client, 0xfe, 0x01); + i2c_put_byte_add8_new(client, 0x13, 0x7b); /* target_y */ + i2c_put_byte_add8_new(client, 0xfe, 0x00); + break; + /* break; */ + + } + +} /* GC2145_set_param_exposure */ + +/* + ************************************************************************ + * FUNCTION + * GC2145_set_param_effect + * + * DESCRIPTION + * effect setting. + * + * PARAMETERS + * none + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + ************************************************************************ + */ + +void GC2145_set_param_effect(struct gc2145_device *dev, + enum camera_effect_flip_e para) +{ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + + if (!dev->vminfo.isused) + return; + + switch (para) { + case CAM_EFFECT_ENC_NORMAL: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x83, 0xe0); + break; + + case CAM_EFFECT_ENC_GRAYSCALE: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x83, 0x12); + break; + + case CAM_EFFECT_ENC_SEPIA: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x83, 0x82); + break; + + case CAM_EFFECT_ENC_SEPIAGREEN: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x43, 0x52); + break; + + case CAM_EFFECT_ENC_SEPIABLUE: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x43, 0x62); + break; + + case CAM_EFFECT_ENC_COLORINV: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x83, 0x01); + break; + + default: + i2c_put_byte_add8_new(client, 0xfe, 0x00); + i2c_put_byte_add8_new(client, 0x83, 0xe0); + break; + } + +} /* GC2145_set_param_effect */ + +/* + ************************************************************************ + * FUNCTION + * GC2145_NightMode + * + * DESCRIPTION + * This function night mode of GC2145. + * + * PARAMETERS + * none + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + ************************************************************************ + */ + +void GC2145_set_night_mode(struct gc2145_device *dev, + enum camera_night_mode_flip_e enable) +{ + +} + +void GC2145_set_param_banding(struct gc2145_device *dev, + enum camera_banding_flip_e banding) +{ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + unsigned char buf[4]; + int i = 0; + + switch (banding) { + case CAM_BANDING_50HZ: + while (1) { + buf[0] = gc2145_FLICKER_50HZ[i].addr; + buf[1] = gc2145_FLICKER_50HZ[i].val; + if (gc2145_FLICKER_50HZ[i].val == 0xff && + gc2145_FLICKER_50HZ[i].addr == 0xff) { + pr_err("success in gc2145_FLICKER_50HZ gc2145\n"); + break; + } + if ((i2c_put_byte_add8(client, buf, 2)) < 0) { + pr_err("fail in gc2145_FLICKER_50HZ gc2145\n"); + return; + } + i++; + } + break; + case CAM_BANDING_60HZ: + while (1) { + buf[0] = gc2145_FLICKER_60HZ[i].addr; + buf[1] = gc2145_FLICKER_60HZ[i].val; + if (gc2145_FLICKER_60HZ[i].val == 0xff && + gc2145_FLICKER_60HZ[i].addr == 0xff) { + pr_err("success in gc2145_FLICKER_60HZ gc2145\n"); + break; + } + if ((i2c_put_byte_add8(client, buf, 2)) < 0) { + pr_err("fail in gc2145_FLICKER_60HZ gc2145\n"); + return; + } + i++; + } + break; + default: + break; + } + +} + +static int set_flip(struct gc2145_device *dev) +{ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + unsigned char temp; + unsigned char buf[2]; + + if (!dev->vminfo.isused) + return 0; + + i2c_put_byte_add8_new(client, 0xfe, 0x00); + + temp = i2c_get_byte_add8(client, 0x17); + temp &= 0xfc; + temp |= dev->cam_info.m_flip << 0; + temp |= dev->cam_info.v_flip << 1; + buf[0] = 0x17; + buf[1] = temp; + if ((i2c_put_byte_add8(client, buf, 2)) < 0) { + pr_err("fail in setting sensor orientation\n"); + return -1; + } + + return 0; +} + +void GC2145_set_resolution(struct gc2145_device *dev, int height, int width) +{ + unsigned char buf[4]; + unsigned int value; + unsigned int pid = 0, shutter; + unsigned int i = 0; + static unsigned int shutter_l; + static unsigned int shutter_h; + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + + pr_info("%s :wxh = %d x %d\n", __func__, width, height); + + if (!dev->vminfo.isused) + return; + + if ((width * height < 1600 * 1200)) { + while (1) { + buf[0] = gc2145_svga[i].addr; + buf[1] = gc2145_svga[i].val; + if (gc2145_svga[i].val == 0xff && + gc2145_svga[i].addr == 0xff) { + pr_info("success in gc2145_svga.\n"); + break; + } + if ((i2c_put_byte_add8(client, buf, 2)) < 0) { + pr_err("fail in gc2145_svga.\n"); + return; + } + i++; + } + gc2145_frmintervals_active.numerator = 1; + gc2145_frmintervals_active.denominator = 15; + GC2145_h_active = 800; + GC2145_v_active = 600; + mdelay(80); + } else if (width * height >= 1200 * 1600) { + buf[0] = 0xfe; + buf[1] = 0x00; + i2c_put_byte_add8(client, buf, 2); + + buf[0] = 0xb6; + buf[1] = 0x00; + i2c_put_byte_add8(client, buf, 2); + + buf[0] = 0x03; + value = i2c_get_byte_add8(client, 0x03); + shutter_l = value; + /*printk(KERN_INFO"set camera 0x03=0x%x\n", value);*/ + pid |= (value << 8); + + buf[0] = 0x04; + value = i2c_get_byte_add8(client, 0x04); + shutter_h = value; + /*printk(KERN_INFO"set camera 0x04=0x%x\n", value);*/ + pid |= (value & 0x1f); + + shutter = pid; + /*printk(KERN_INFO "set camera shutter=0x%x\n", shutter);*/ + + while (1) { + buf[0] = gc2145_uxga[i].addr; + buf[1] = gc2145_uxga[i].val; + if (gc2145_uxga[i].val == 0xff && + gc2145_uxga[i].addr == 0xff) { + pr_info("gc2145_write_regs success in gc2145_uxga.\n"); + break; + } + if ((i2c_put_byte_add8(client, buf, 2)) < 0) { + pr_err("fail in gc2145_uxga.\n"); + return; + } + i++; + } + + shutter = shutter / 2; + if (shutter < 1) + shutter = 1; + + buf[0] = 0x03; + buf[1] = ((shutter >> 8) & 0xff); + i2c_put_byte_add8(client, buf, 2); + + buf[0] = 0x04; + buf[1] = (shutter & 0x1f); + i2c_put_byte_add8(client, buf, 2); + + gc2145_frmintervals_active.denominator = 5; + gc2145_frmintervals_active.numerator = 1; + GC2145_h_active = 1600; + GC2145_v_active = 1200; + mdelay(130); + } + set_flip(dev); +} /* GC2145_set_resolution */ + +unsigned char v4l_2_gc2145(int val) +{ + int ret = val / 0x20; + + if (ret < 4) + return ret * 0x20 + 0x80; + else if (ret < 8) + return ret * 0x20 + 0x20; + else + return 0; +} + +static int convert_canvas_index(unsigned int v4l2_format, + unsigned int start_canvas) +{ + int canvas = start_canvas; + + switch (v4l2_format) { + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_VYUY: + canvas = start_canvas; + break; + case V4L2_PIX_FMT_YUV444: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB24: + canvas = start_canvas; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + canvas = start_canvas | ((start_canvas + 1) << 8); + break; + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV420: + if (v4l2_format == V4L2_PIX_FMT_YUV420) + canvas = start_canvas | ((start_canvas + 1) << 8) | + ((start_canvas + 2) << 16); + else + canvas = start_canvas | ((start_canvas + 2) << 8) | + ((start_canvas + 1) << 16); + break; + default: + break; + } + return canvas; +} + +static int gc2145_setting(struct gc2145_device *dev, int PROP_ID, int value) +{ + int ret = 0; + /* unsigned char cur_val; */ + struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); + + if (!dev->vminfo.isused) + return 0; + /*here register not finished */ + switch (PROP_ID) { + + case V4L2_CID_BRIGHTNESS: + dprintk(dev, 1, "setting brightned:%d\n", v4l_2_gc2145(value)); + ret = i2c_put_byte_add8_new(client, 0xdc, v4l_2_gc2145(value)); + break; + case V4L2_CID_CONTRAST: + ret = i2c_put_byte_add8_new(client, 0xde, value); + break; + case V4L2_CID_SATURATION: + ret = i2c_put_byte_add8_new(client, 0xd9, value); + break; + case V4L2_CID_DO_WHITE_BALANCE: + if (gc2145_qctrl[0].default_value != value) { + gc2145_qctrl[0].default_value = value; + GC2145_set_param_wb(dev, value); + pr_info("set camera white_balance=%d.\n ", + value); + } + break; + case V4L2_CID_EXPOSURE: + if (gc2145_qctrl[1].default_value != value) { + gc2145_qctrl[1].default_value = value; + GC2145_set_param_exposure(dev, value); + pr_info("set camera exposure=%d.\n", + value); + } + break; + case V4L2_CID_COLORFX: + if (gc2145_qctrl[2].default_value != value) { + gc2145_qctrl[2].default_value = value; + /* GC2145_set_param_effect(dev,value); */ + pr_info("set camera effect=%d.\n", + value); + } + break; + case V4L2_CID_WHITENESS: + if (gc2145_qctrl[3].default_value != value) { + gc2145_qctrl[3].default_value = value; + pr_info("@@@SP_000:GC2145_set_param_banding,value=%d\n", + value); + GC2145_set_param_banding(dev, value); + pr_info("@@@SP_111:gc2145_night_or_normal = %d", + gc2145_night_or_normal); + GC2145_set_night_mode(dev, gc2145_night_or_normal); + pr_info("set camera banding=%d.\n", + value); + } + break; + case V4L2_CID_BLUE_BALANCE: + if (gc2145_qctrl[4].default_value != value) { + gc2145_qctrl[4].default_value = value; + pr_info("@@@SP_222:GC2145_set_night_mode,night mode=%d\n", + value); + pr_info("@@@SP_333:gc2145_night_or_normal = %d", + gc2145_night_or_normal); + GC2145_set_night_mode(dev, value); + pr_info("set camera scene mode=%d.\n", + value); + } + break; + case V4L2_CID_HFLIP: /* set flip on H. */ + value = value & 0x3; + if (gc2145_qctrl[5].default_value != value) { + gc2145_qctrl[5].default_value = value; + pr_info(" set camera h filp =%d.\n ", value); + } + break; + case V4L2_CID_VFLIP: /* set flip on V. */ + break; + case V4L2_CID_ZOOM_ABSOLUTE: + if (gc2145_qctrl[7].default_value != value) + gc2145_qctrl[7].default_value = value; + break; + case V4L2_CID_ROTATE: + if (gc2145_qctrl[8].default_value != value) { + gc2145_qctrl[8].default_value = value; + pr_info(" set camera rotate =%d.\n ", value); + } + break; + default: + ret = -1; + break; + } + return ret; +} + +static void power_down_gc2145(struct gc2145_device *dev) +{ + +} + +/* + *------------------------------------------------------------------ + * DMA and thread functions + * ------------------------------------------------------------------ + */ + +#define TSTAMP_MIN_Y 24 +#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) +#define TSTAMP_INPUT_X 10 +#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) + +static void gc2145_fillbuff(struct gc2145_fh *fh, struct gc2145_buffer *buf) +{ + int ret; + void *vbuf; + struct vm_output_para para = {0}; + struct gc2145_device *dev = fh->dev; + + if (dev->vminfo.mem_alloc_succeed) + vbuf = (void *)videobuf_to_res(&buf->vb); + else + vbuf = videobuf_to_vmalloc(&buf->vb); + dprintk(dev, 1, "%s\n", __func__); + if (!vbuf) + return; + /* 0x18221223 indicate the memory type is MAGIC_VMAL_MEM*/ + if (dev->vminfo.mem_alloc_succeed) { + if (buf->canvas_id == 0) + buf->canvas_id = convert_canvas_index(fh->fmt->fourcc, + CAMERA_USER_CANVAS_INDEX + buf->vb.i * 3); + para.v4l2_memory = MAGIC_RE_MEM; + } else + para.v4l2_memory = MAGIC_VMAL_MEM; + para.mirror = gc2145_qctrl[5].default_value & 3;/* not set */ + para.v4l2_format = fh->fmt->fourcc; + para.zoom = gc2145_qctrl[7].default_value; + para.angle = gc2145_qctrl[8].default_value; + para.vaddr = (uintptr_t)vbuf; + /* para.ext_canvas = buf->canvas_id; */ + para.ext_canvas = 0; + para.width = buf->vb.width; + para.height = buf->vb.height; + dev->vminfo.vdin_id = dev->cam_info.vdin_path; + ret = vm_fill_this_buffer(&buf->vb, ¶, &dev->vminfo); + /*if the vm is not used by sensor ,*/ + /*we let vm_fill_this_buffer() return -2*/ + if (ret == -2) + msleep(40); + buf->vb.state = VIDEOBUF_DONE; +} + +static void gc2145_thread_tick(struct gc2145_fh *fh) +{ + struct gc2145_buffer *buf; + struct gc2145_device *dev = fh->dev; + struct gc2145_dmaqueue *dma_q = &dev->vidq; + + unsigned long flags = 0; + + dprintk(dev, 1, "Thread tick\n"); + if (!fh->stream_on) { + dprintk(dev, 1, "sensor doesn't stream on\n"); + return; + } + spin_lock_irqsave(&dev->slock, flags); + if (list_empty(&dma_q->active)) { + dprintk(dev, 1, "No active queue to serve\n"); + goto unlock; + } + + buf = list_entry(dma_q->active.next, + struct gc2145_buffer, vb.queue); + dprintk(dev, 1, "%s\n", __func__); + dprintk(dev, 1, "list entry get buf is %p\n", buf); + + if (!(fh->f_flags & O_NONBLOCK)) { + /* Nobody is waiting on this buffer, return */ + if (!waitqueue_active(&buf->vb.done)) + goto unlock; + } + buf->vb.state = VIDEOBUF_ACTIVE; + + list_del(&buf->vb.queue); + + do_gettimeofday(&buf->vb.ts); + + /* Fill buffer */ + spin_unlock_irqrestore(&dev->slock, flags); + gc2145_fillbuff(fh, buf); + dprintk(dev, 1, "filled buffer %p\n", buf); + + wake_up(&buf->vb.done); + dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); + return; +unlock: + spin_unlock_irqrestore(&dev->slock, flags); +} + +#define frames_to_ms(frames) \ + ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) + +static void gc2145_sleep(struct gc2145_fh *fh) +{ + struct gc2145_device *dev = fh->dev; + struct gc2145_dmaqueue *dma_q = &dev->vidq; + + DECLARE_WAITQUEUE(wait, current); + + dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__, + (unsigned long)dma_q); + + add_wait_queue(&dma_q->wq, &wait); + if (kthread_should_stop()) + goto stop_task; + + /* Calculate time to wake up */ + /* timeout = msecs_to_jiffies(frames_to_ms(1)); */ + + gc2145_thread_tick(fh); + + schedule_timeout_interruptible(2); + +stop_task: + remove_wait_queue(&dma_q->wq, &wait); + try_to_freeze(); +} + +static int gc2145_thread(void *data) +{ + struct gc2145_fh *fh = data; + struct gc2145_device *dev = fh->dev; + + dprintk(dev, 1, "thread started\n"); + + set_freezable(); + + for (; ;) { + gc2145_sleep(fh); + + if (kthread_should_stop()) + break; + } + dprintk(dev, 1, "thread: exit\n"); + return 0; +} + +static int gc2145_start_thread(struct gc2145_fh *fh) +{ + struct gc2145_device *dev = fh->dev; + struct gc2145_dmaqueue *dma_q = &dev->vidq; + + dma_q->frame = 0; + dma_q->ini_jiffies = jiffies; + + dprintk(dev, 1, "%s\n", __func__); + + dma_q->kthread = kthread_run(gc2145_thread, fh, "gc2145"); + + if (IS_ERR(dma_q->kthread)) { + v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); + return PTR_ERR(dma_q->kthread); + } + /* Wakes thread */ + wake_up_interruptible(&dma_q->wq); + + dprintk(dev, 1, "returning from %s\n", __func__); + return 0; +} + +static void gc2145_stop_thread(struct gc2145_dmaqueue *dma_q) +{ + struct gc2145_device *dev = + container_of(dma_q, struct gc2145_device, vidq); + + dprintk(dev, 1, "%s\n", __func__); + /* shutdown control thread */ + if (dma_q->kthread) { + kthread_stop(dma_q->kthread); + dma_q->kthread = NULL; + } +} + +/* + *------------------------------------------------------------------ + * Videobuf operations + * ------------------------------------------------------------------ + */ + +static int +vmall_buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct gc2145_fh *fh = vq->priv_data; + struct gc2145_device *dev = fh->dev; + /* int bytes = fh->fmt->depth >> 3 ; */ + *size = (fh->width * fh->height * fh->fmt->depth) >> 3; + if (*count == 0) + *count = 32; + + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + + dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, + *count, *size); + + return 0; +} + +static int +res_buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct videobuf_res_privdata *res = vq->priv_data; + struct gc2145_fh *fh = container_of(res, struct gc2145_fh, res); + struct gc2145_device *dev = fh->dev; + /* int bytes = fh->fmt->depth >> 3 ; */ + int height = fh->height; + + if (height == 1080) + height = 1088; + *size = (fh->width * height * fh->fmt->depth) >> 3; + if (*count == 0) + *count = 32; + + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + + dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, + *count, *size); + + return 0; +} + +static void free_vmall_buffer(struct videobuf_queue *vq, + struct gc2145_buffer *buf) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + + fh = vq->priv_data; + dev = fh->dev; + + dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); + + videobuf_waiton(vq, &buf->vb, 0, 0); + if (in_interrupt()) + WARN_ON(1); + videobuf_vmalloc_free(&buf->vb); + dprintk(dev, 1, "free_vmall_buffer: freed\n"); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static void free_res_buffer(struct videobuf_queue *vq, + struct gc2145_buffer *buf) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct videobuf_res_privdata *res = vq->priv_data; + + fh = container_of(res, struct gc2145_fh, res); + dev = fh->dev; + + dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); + + videobuf_waiton(vq, &buf->vb, 0, 0); + if (in_interrupt()) + WARN_ON(1); + videobuf_res_free(vq, &buf->vb); + dprintk(dev, 1, "free_res_buffer: freed\n"); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +#define norm_maxw() 1920 +#define norm_maxh() 1600 +static int +vmall_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct gc2145_buffer *buf; + int rc; + + fh = vq->priv_data; + dev = fh->dev; + buf = container_of(vb, struct gc2145_buffer, vb); + /* int bytes = fh->fmt->depth >> 3 ; */ + dprintk(dev, 1, "%s, field=%d\n", __func__, field); + + WARN_ON(fh->fmt == NULL); + + if (fh->width < 48 || fh->width > norm_maxw() || + fh->height < 32 || fh->height > norm_maxh()) + return -EINVAL; + + buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; + if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + /* These properties only change when queue is idle, see s_fmt */ + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + + /* precalculate_bars(fh); */ + + if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) + goto fail; + } + + buf->vb.state = VIDEOBUF_PREPARED; + + return 0; + +fail: + free_vmall_buffer(vq, buf); + return rc; +} + +static int +res_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct gc2145_buffer *buf; + int rc; + struct videobuf_res_privdata *res = vq->priv_data; + + fh = container_of(res, struct gc2145_fh, res); + dev = fh->dev; + buf = container_of(vb, struct gc2145_buffer, vb); + dprintk(dev, 1, "%s, field=%d\n", __func__, field); + + WARN_ON(fh->fmt == NULL); + + if (fh->width < 48 || fh->width > norm_maxw() || + fh->height < 32 || fh->height > norm_maxh()) + return -EINVAL; + + buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; + if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + /* These properties only change when queue is idle, see s_fmt */ + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + + /* precalculate_bars(fh); */ + + if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) + goto fail; + } + + buf->vb.state = VIDEOBUF_PREPARED; + + return 0; + +fail: + free_res_buffer(vq, buf); + return rc; +} + +static void +res_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct gc2145_dmaqueue *vidq; + struct gc2145_buffer *buf = container_of(vb, struct gc2145_buffer, vb); + struct videobuf_res_privdata *res = vq->priv_data; + + fh = container_of(res, struct gc2145_fh, res); + dev = fh->dev; + vidq = &dev->vidq; + + dprintk(dev, 1, "%s\n", __func__); + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); +} + +static void +vmall_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct gc2145_dmaqueue *vidq; + struct gc2145_buffer *buf = container_of(vb, struct gc2145_buffer, vb); + + fh = vq->priv_data; + dev = fh->dev; + vidq = &dev->vidq; + + dprintk(dev, 1, "%s\n", __func__); + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); +} + +static void res_buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct gc2145_buffer *buf = + container_of(vb, struct gc2145_buffer, vb); + struct videobuf_res_privdata *res = vq->priv_data; + + fh = container_of(res, struct gc2145_fh, res); + dev = (struct gc2145_device *)fh->dev; + + dprintk(dev, 1, "%s\n", __func__); + + free_res_buffer(vq, buf); +} + +static void vmall_buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct gc2145_fh *fh; + struct gc2145_device *dev; + struct gc2145_buffer *buf = + container_of(vb, struct gc2145_buffer, vb); + fh = vq->priv_data; + dev = (struct gc2145_device *)fh->dev; + + dprintk(dev, 1, "%s\n", __func__); + + free_vmall_buffer(vq, buf); +} + +static struct videobuf_queue_ops gc2145_video_vmall_qops = { + .buf_setup = vmall_buffer_setup, + .buf_prepare = vmall_buffer_prepare, + .buf_queue = vmall_buffer_queue, + .buf_release = vmall_buffer_release, +}; + +static struct videobuf_queue_ops gc2145_video_res_qops = { + .buf_setup = res_buffer_setup, + .buf_prepare = res_buffer_prepare, + .buf_queue = res_buffer_queue, + .buf_release = res_buffer_release, +}; + +/* + *------------------------------------------------------------------ + * IOCTL vidioc handling + * ------------------------------------------------------------------ + */ + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + + strcpy(cap->driver, "gc2145"); + strcpy(cap->card, "gc2145.canvas"); + if (dev->cam_info.front_back == 0) + strcat(cap->card, "back"); + else + strcat(cap->card, "front"); + + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); + cap->version = GC2145_CAMERA_VERSION; + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING + | V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct gc2145_fmt *fmt; + + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + fmt = &formats[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + return 0; +} +static int vidioc_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) +{ + unsigned int k; + + if (fival->index > ARRAY_SIZE(gc2145_frmivalenum)) + return -EINVAL; + + for (k = 0; k < ARRAY_SIZE(gc2145_frmivalenum); k++) { + if ((fival->index == gc2145_frmivalenum[k].index) && + (fival->pixel_format == + gc2145_frmivalenum[k].pixel_format) && + (fival->width == gc2145_frmivalenum[k].width) && + (fival->height == gc2145_frmivalenum[k].height)) { + memcpy(fival, &gc2145_frmivalenum[k], + sizeof(struct v4l2_frmivalenum)); + return 0; + } + } + + return -EINVAL; + +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct gc2145_fh *fh = priv; + + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vb_vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + struct gc2145_fmt *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; + + fmt = get_format(f); + if (!fmt) { + dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) + field = V4L2_FIELD_INTERLACED; + else if (field != V4L2_FIELD_INTERLACED) { + dprintk(dev, 1, "Field type invalid.\n"); + return -EINVAL; + } + + maxw = norm_maxw(); + maxh = norm_maxh(); + + f->fmt.pix.field = field; + v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, + &f->fmt.pix.height, 32, maxh, 0, 0); + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +/*FIXME: This seems to be generic enough to be at videodev2 */ +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct gc2145_fh *fh = priv; + struct videobuf_queue *q = &fh->vb_vidq; + struct gc2145_device *dev = fh->dev; + int ret; + + f->fmt.pix.width = (f->fmt.pix.width + + (CANVAS_WIDTH_ALIGN - 1)) & + (~(CANVAS_WIDTH_ALIGN - 1)); + if ((f->fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) || + (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)) + f->fmt.pix.width = (f->fmt.pix.width + + (CANVAS_WIDTH_ALIGN * 2 - 1)) & + (~(CANVAS_WIDTH_ALIGN * 2 - 1)); + + ret = vidioc_try_fmt_vid_cap(file, fh, f); + if (ret < 0) + return ret; + + mutex_lock(&q->vb_lock); + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + dprintk(fh->dev, 1, "%s queue busy\n", __func__); + ret = -EBUSY; + goto out; + } + + fh->fmt = get_format(f); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vb_vidq.field = f->fmt.pix.field; + fh->type = f->type; +#if 0 + set_flip(dev); + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { + vidio_set_fmt_ticks = 1; + GC2145_set_resolution(dev, fh->height, fh->width); + } else if (vidio_set_fmt_ticks == 1) + GC2145_set_resolution(dev, fh->height, fh->width); +#else + GC2145_set_resolution(dev, fh->height, fh->width); +#endif + ret = 0; +out: + mutex_unlock(&q->vb_lock); + + return ret; +} + +static int vidioc_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *parms) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + struct v4l2_captureparm *cp = &parms->parm.capture; + + dprintk(dev, 3, "vidioc_g_parm\n"); + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memset(cp, 0, sizeof(struct v4l2_captureparm)); + cp->capability = V4L2_CAP_TIMEPERFRAME; + + cp->timeperframe = gc2145_frmintervals_active; + pr_debug("g_parm,deno=%d, numerator=%d\n", + cp->timeperframe.denominator, + cp->timeperframe.numerator); + return 0; +} + + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + struct gc2145_fh *fh = priv; + + return videobuf_reqbufs(&fh->vb_vidq, p); +} + +static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct gc2145_fh *fh = priv; + int ret = videobuf_querybuf(&fh->vb_vidq, p); + + if (get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { + if (ret == 0) + p->reserved = convert_canvas_index(fh->fmt->fourcc, + CAMERA_USER_CANVAS_INDEX + + p->index * 3); + else + p->reserved = 0; + } + return ret; +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct gc2145_fh *fh = priv; + + return videobuf_qbuf(&fh->vb_vidq, p); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct gc2145_fh *fh = priv; + + return videobuf_dqbuf(&fh->vb_vidq, p, + file->f_flags & O_NONBLOCK); +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct gc2145_fh *fh = priv; + + return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); +} +#endif + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct gc2145_fh *fh = priv; + struct vdin_parm_s para; + unsigned int vdin_path; + int ret = 0; + + pr_info("vidioc_streamon+++\n "); + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + memset(¶, 0, sizeof(para)); + para.port = TVIN_PORT_CAMERA; + para.fmt = TVIN_SIG_FMT_MAX; + para.frame_rate = gc2145_frmintervals_active.denominator; + para.h_active = GC2145_h_active; + para.v_active = GC2145_v_active; + para.hsync_phase = 1; + para.vsync_phase = 1; + para.hs_bp = 0; + para.vs_bp = 3; + para.bt_path = fh->dev->cam_info.bt_path; + vdin_path = fh->dev->cam_info.vdin_path; + para.cfmt = TVIN_YUV422; + para.dfmt = TVIN_NV21; + para.scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + + if (is_first_time_open == 0) { + para.skip_count = 4; + is_first_time_open = 1; + } else + para.skip_count = 0; + + ret = videobuf_streamon(&fh->vb_vidq); + if (ret == 0) { + if (fh->dev->vminfo.isused) { + vops->start_tvin_service(vdin_path, ¶); + fh->stream_on = 1; + } + } + + return ret; +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct gc2145_fh *fh = priv; + unsigned int vdin_path; + int ret = 0; + + pr_info("vidioc_streamoff+++\n "); + vdin_path = fh->dev->cam_info.vdin_path; + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + ret = videobuf_streamoff(&fh->vb_vidq); + if (ret == 0) { + if (fh->dev->vminfo.isused) + vops->stop_tvin_service(vdin_path); + fh->stream_on = 0; + } + return ret; +} + +static int vidioc_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + int ret = 0, i = 0; + struct gc2145_fmt *fmt = NULL; + struct v4l2_frmsize_discrete *frmsize = NULL; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (formats[i].fourcc == fsize->pixel_format) { + fmt = &formats[i]; + break; + } + } + if (fmt == NULL) + return -EINVAL; + if ((fmt->fourcc == V4L2_PIX_FMT_NV21) + || (fmt->fourcc == V4L2_PIX_FMT_NV12) + || (fmt->fourcc == V4L2_PIX_FMT_YVU420) + || (fmt->fourcc == V4L2_PIX_FMT_YUV420)) { + if (fsize->index >= ARRAY_SIZE(gc2145_prev_resolution)) + return -EINVAL; + frmsize = &gc2145_prev_resolution[fsize->index]; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = frmsize->width; + fsize->discrete.height = frmsize->height; + } else if (fmt->fourcc == V4L2_PIX_FMT_RGB24) { + if (fsize->index >= ARRAY_SIZE(gc2145_pic_resolution)) + return -EINVAL; + frmsize = &gc2145_pic_resolution[fsize->index]; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = frmsize->width; + fsize->discrete.height = frmsize->height; + } + return ret; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i) +{ + return 0; +} + +/* only one input in this sample driver */ +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + /* if (inp->index >= NUM_INPUTS) */ + /* return -EINVAL; */ + + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_525_60; + sprintf(inp->name, "Camera %u", inp->index); + + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + + *i = dev->input; + + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + + /* if (i >= NUM_INPUTS) */ + /* return -EINVAL; */ + + dev->input = i; + /* precalculate_bars(fh); */ + + return 0; +} + +/* --- controls ---------------------------------------------- */ +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(gc2145_qctrl); i++) + if (qc->id && qc->id == gc2145_qctrl[i].id) { + memcpy(qc, &(gc2145_qctrl[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(gc2145_qctrl); i++) + if (ctrl->id == gc2145_qctrl[i].id) { + ctrl->value = dev->qctl_regs[i]; + return 0; + } + + return -EINVAL; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct gc2145_fh *fh = priv; + struct gc2145_device *dev = fh->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(gc2145_qctrl); i++) + if (ctrl->id == gc2145_qctrl[i].id) { + if (ctrl->value < gc2145_qctrl[i].minimum || + ctrl->value > gc2145_qctrl[i].maximum || + gc2145_setting(dev, ctrl->id, ctrl->value) < 0) + return -ERANGE; + dev->qctl_regs[i] = ctrl->value; + return 0; + } + return -EINVAL; +} + +/* + *------------------------------------------------------------------ + * File operations for the device + * ----------------------------------------------------------------- + */ + +static int gc2145_open(struct file *file) +{ + struct gc2145_device *dev = video_drvdata(file); + struct gc2145_fh *fh = NULL; + int retval = 0; + + dev->vminfo.vdin_id = dev->cam_info.vdin_path; + dev->vminfo.bt_path_count = dev->cam_info.bt_path_count; + +#if CONFIG_CMA + vm_init_resource(16 * SZ_1M, &dev->vminfo); +#endif + if (dev->vminfo.isused) { + pr_info("%s, front_back = %d\n", + __func__, dev->cam_info.front_back); + aml_cam_init(&dev->cam_info); + } + + GC2145_init_regs(dev); + msleep(40); + mutex_lock(&dev->mutex); + dev->users++; + if (dev->users > 1) { + dev->users--; + pr_err("gc2145 device is opened, device is busy\n"); + mutex_unlock(&dev->mutex); + return -EBUSY; + } + + dprintk(dev, 1, "open %s type=%s users=%d\n", + video_device_node_name(dev->vdev), + v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); + + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + init_waitqueue_head(&dev->vidq.wq); + spin_lock_init(&dev->slock); + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (fh == NULL) { + dev->users--; + retval = -ENOMEM; + } + mutex_unlock(&dev->mutex); + + if (retval) + return retval; + +#ifdef CONFIG_HAS_WAKELOCK + wake_lock(&(dev->wake_lock)); +#endif + + file->private_data = fh; + fh->dev = dev; + + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fh->fmt = &formats[0]; + fh->width = 1600;/* 640//zyy */ + fh->height = 1198;/* 1200;//480 */ + fh->stream_on = 0; + fh->f_flags = file->f_flags; + /* Resets frame counters */ + /*dev->jiffies = jiffies;*/ + + /* TVIN_SIG_FMT_CAMERA_640X480P_30Hz, */ + /* TVIN_SIG_FMT_CAMERA_800X600P_30Hz, */ + /* TVIN_SIG_FMT_CAMERA_1024X768P_30Hz, // 190 */ + /* TVIN_SIG_FMT_CAMERA_1920X1080P_30Hz, */ + /* TVIN_SIG_FMT_CAMERA_1280X720P_30Hz, */ + + if (dev->vminfo.mem_alloc_succeed) { + fh->res.start = dev->vminfo.buffer_start; + fh->res.end = dev->vminfo.buffer_start + + dev->vminfo.vm_buf_size - 1; + fh->res.magic = MAGIC_RE_MEM; + fh->res.priv = NULL; + videobuf_queue_res_init(&fh->vb_vidq, + &gc2145_video_res_qops, NULL, + &dev->slock, fh->type, + V4L2_FIELD_INTERLACED, + sizeof(struct gc2145_buffer), + (void *)&fh->res, NULL); + } else { + videobuf_queue_vmalloc_init(&fh->vb_vidq, + &gc2145_video_vmall_qops, NULL, + &dev->slock, fh->type, + V4L2_FIELD_INTERLACED, + sizeof(struct gc2145_buffer), fh, NULL); + } + + gc2145_start_thread(fh); + gc2145_have_open = 1; + return 0; +} + +static ssize_t +gc2145_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct gc2145_fh *fh = file->private_data; + + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, + file->f_flags & O_NONBLOCK); + } + return 0; +} + +static unsigned int +gc2145_poll(struct file *file, struct poll_table_struct *wait) +{ + struct gc2145_fh *fh = file->private_data; + struct gc2145_device *dev = fh->dev; + struct videobuf_queue *q = &fh->vb_vidq; + + dprintk(dev, 1, "%s\n", __func__); + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return POLLERR; + + return videobuf_poll_stream(file, q, wait); +} + +static int gc2145_close(struct file *file) +{ + struct gc2145_fh *fh = file->private_data; + struct gc2145_device *dev = fh->dev; + struct gc2145_dmaqueue *vidq = &dev->vidq; + struct video_device *vdev = video_devdata(file); + unsigned int vdin_path; + + vdin_path = fh->dev->cam_info.vdin_path; + gc2145_have_open = 0; + is_first_time_open = 0; + + gc2145_stop_thread(vidq); + videobuf_stop(&fh->vb_vidq); + if (fh->stream_on) { + if (dev->vminfo.isused) { + pr_info("%s, vdin_path = %d\n", + __func__, vdin_path); + vops->stop_tvin_service(vdin_path); + } + } + videobuf_mmap_free(&fh->vb_vidq); + kfree(fh); + + mutex_lock(&dev->mutex); + dev->users--; + mutex_unlock(&dev->mutex); + + dprintk(dev, 1, "close called (dev=%s, users=%d)\n", + video_device_node_name(vdev), dev->users); +#if 1 + GC2145_h_active = 640; /* 800//zyy */ + GC2145_v_active = 480; /* 1200;//600 */ + gc2145_qctrl[0].default_value = 0; + gc2145_qctrl[1].default_value = 4; + gc2145_qctrl[2].default_value = 0; + gc2145_qctrl[3].default_value = 0; + gc2145_qctrl[4].default_value = 0; + + gc2145_qctrl[5].default_value = 0; + gc2145_qctrl[7].default_value = 100; + gc2145_qctrl[8].default_value = 0; + gc2145_frmintervals_active.numerator = 1; + gc2145_frmintervals_active.denominator = 15; + power_down_gc2145(dev); +#endif + aml_cam_uninit(&dev->cam_info); +#ifdef CONFIG_HAS_WAKELOCK + wake_unlock(&(dev->wake_lock)); +#endif +#ifdef CONFIG_CMA + vm_deinit_resource(&dev->vminfo); +#endif + return 0; +} + +static int gc2145_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct gc2145_fh *fh = file->private_data; + struct gc2145_device *dev = fh->dev; + int ret; + + dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + + ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); + + dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, + ret); + + return ret; +} + +static const struct v4l2_file_operations gc2145_fops = { + .owner = THIS_MODULE, + .open = gc2145_open, + .release = gc2145_close, + .read = gc2145_read, + .poll = gc2145_poll, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = gc2145_mmap, +}; + +static const struct v4l2_ioctl_ops gc2145_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_querymenu = vidioc_querymenu, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_enum_framesizes = vidioc_enum_framesizes, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +}; + +static struct video_device gc2145_template = { + .name = "gc2145_v4l", + .fops = &gc2145_fops, + .ioctl_ops = &gc2145_ioctl_ops, + .release = video_device_release, + .tvnorms = V4L2_STD_525_60, +}; + +static const struct v4l2_subdev_core_ops gc2145_core_ops = { + /*.g_chip_ident = gc2145_g_chip_ident,*/ +}; + +static const struct v4l2_subdev_ops gc2145_ops = { + .core = &gc2145_core_ops, +}; + +static ssize_t gc2145_show(struct device *dev, struct device_attribute *attr, + char *_buf) +{ + return sprintf(_buf, "0x%02x=0x%02x\n", cur_reg, cur_val); +} + +static u32 strtol(const char *nptr, int base) +{ + u32 ret; + + if (!nptr || (base != 16 && base != 10 && base != 8)) { + pr_err("%s(): NULL pointer input\n", __func__); + return -1; + } + for (ret = 0; *nptr; nptr++) { + if ((base == 16 && *nptr >= 'A' && *nptr <= 'F') || + (base == 16 && *nptr >= 'a' && *nptr <= 'f') || + (base >= 10 && *nptr >= '0' && *nptr <= '9') || + (base >= 8 && *nptr >= '0' && *nptr <= '7')) { + ret *= base; + if (base == 16 && *nptr >= 'A' && *nptr <= 'F') + ret += *nptr - 'A' + 10; + else if (base == 16 && *nptr >= 'a' && *nptr <= 'f') + ret += *nptr - 'a' + 10; + else if (base >= 10 && *nptr >= '0' && *nptr <= '9') + ret += *nptr - '0'; + else if (base >= 8 && *nptr >= '0' && *nptr <= '7') + ret += *nptr - '0'; + } else + return ret; + } + return ret; +} + +static ssize_t gc2145_store(struct device *dev, + struct device_attribute *attr, + const char *_buf, size_t _count) +{ + const char *p = _buf; + u16 reg; + u8 val; + + if (!strncmp(_buf, "get", strlen("get"))) { + p += strlen("get"); + cur_reg = (u32)strtol(p, 16); + val = i2c_get_byte_add8(g_i2c_client, cur_reg); + pr_info("%s(): get 0x%04x=0x%02x\n", + __func__, cur_reg, val); + cur_val = val; + } else if (!strncmp(_buf, "put", strlen("put"))) { + p += strlen("put"); + reg = strtol(p, 16); + p = strchr(_buf, '='); + if (p) { + ++p; + val = strtol(p, 16); + i2c_put_byte_add8_new(g_i2c_client, reg, val); + pr_info("%s(): set 0x%04x=0x%02x\n", + __func__, reg, val); + } else + pr_info("%s(): Bad string format input!\n", __func__); + } else + pr_info("%s(): Bad string format input!\n", __func__); + + return _count; +} + +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, + char *_buf) +{ + strcpy(_buf, "GC2145"); + return 4; +} + +static struct device *gc2145_dev; +static struct class *gc2145_class; +static DEVICE_ATTR(gc2145, 0444, gc2145_show, gc2145_store);/*0666*/ +static DEVICE_ATTR(name, 0444, name_show, NULL); + +#define EMDOOR_DEBUG_GC2145 1 +#ifdef EMDOOR_DEBUG_GC2145 +unsigned int gc2145_reg_addr; +static struct i2c_client *gc2145_client; + +static ssize_t gc2145_show_mine(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + unsigned char dat; + + dat = i2c_get_byte_add8(gc2145_client, gc2145_reg_addr); + return sprintf(buf, "REG[0x%x]=0x%x\n", gc2145_reg_addr, dat); +} + +static ssize_t gc2145_store_mine(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int tmp; + unsigned short reg; + unsigned char val; + + tmp = kstrtoul(buf, 16, NULL); + /* sscanf(buf, "%du", &tmp); */ + if (tmp < 0xff) + gc2145_reg_addr = tmp; + else { + reg = (tmp >> 8) & 0xFFFF; /* reg */ + gc2145_reg_addr = reg; + val = tmp & 0xFF; /* val */ + i2c_put_byte_add8_new(gc2145_client, reg, val); + } + + return count; +} + + +static struct kobj_attribute gc2145_attribute = __ATTR(gc2145, 0444, + gc2145_show_mine, gc2145_store_mine); + + +static struct attribute *gc2145_attrs[] = { + &gc2145_attribute.attr, + NULL, +}; + + +static const struct attribute_group gc2145_group = { + .attrs = gc2145_attrs, +}; +#endif + +static int gc2145_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + struct gc2145_device *t; + struct v4l2_subdev *sd; + struct aml_cam_info_s *plat_dat; + int ret; + + vops = get_vdin_v4l2_ops(); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + t = kzalloc(sizeof(*t), GFP_KERNEL); + /* modify correct i2c addr--- 0x30 */ + client->addr = 0x3c; + if (t == NULL) { + pr_err("%s, no memory", __func__); + return -ENOMEM; + } + snprintf(t->v4l2_dev.name, sizeof(t->v4l2_dev.name), + "%s-%03d", "gc2145", 0); + ret = v4l2_device_register(NULL, &t->v4l2_dev); + if (ret) { + pr_info("%s, v4l2 device register failed", __func__); + kfree(t); + kfree(client); + return ret; + } + + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &gc2145_ops); + + plat_dat = (struct aml_cam_info_s *)client->dev.platform_data; + /* test if devices exist. */ + memset(&t->vminfo, 0, sizeof(struct vm_init_s)); + /* Now create a video4linux device */ + mutex_init(&t->mutex); + + /* Now create a video4linux device */ + t->vdev = video_device_alloc(); + if (t->vdev == NULL) { + kfree(t); + kfree(client); + return -ENOMEM; + } + memcpy(t->vdev, &gc2145_template, sizeof(*t->vdev)); + t->vdev->v4l2_dev = &t->v4l2_dev; + video_set_drvdata(t->vdev, t); + +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_init(&(t->wake_lock), WAKE_LOCK_SUSPEND, "gc2145"); +#endif + + /* Register it */ + if (plat_dat) { + memcpy(&t->cam_info, plat_dat, sizeof(struct aml_cam_info_s)); + pr_info("%s, front_back = %d\n", + __func__, plat_dat->front_back); + video_nr = plat_dat->front_back; + } else { + pr_err("camera gc2145: have no platform data\n"); + kfree(t); + return -1; + } + + t->cam_info.version = GC2145_DRIVER_VERSION; + if (aml_cam_info_reg(&t->cam_info) < 0) + pr_err("reg caminfo error\n"); + err = video_register_device(t->vdev, VFL_TYPE_GRABBER, video_nr); + if (err < 0) { + video_device_release(t->vdev); + kfree(t); + return err; + } + + gc2145_class = class_create(THIS_MODULE, "gc2145"); + if (IS_ERR(gc2145_class)) { + pr_err("Create class gc2145 fail.\n"); + return -ENOMEM; + } + gc2145_dev = device_create(gc2145_class, NULL, + MKDEV(0, 1), NULL, "dev"); + device_create_file(gc2145_dev, &dev_attr_gc2145); + device_create_file(gc2145_dev, &dev_attr_name); + + g_i2c_client = client; + +#ifdef EMDOOR_DEBUG_GC2145 + gc2145_client = client; + err = sysfs_create_group(&client->dev.kobj, &gc2145_group); +#endif + + return 0; +} + +static int gc2145_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc2145_device *t = to_dev(sd); + + video_unregister_device(t->vdev); + v4l2_device_unregister_subdev(sd); +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_destroy(&(t->wake_lock)); +#endif + aml_cam_info_unreg(&t->cam_info); + kfree(t); + return 0; +} + + +static const struct i2c_device_id gc2145_id[] = { + { "gc2145", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, gc2145_id); + +static struct i2c_driver gc2145_i2c_driver = { + .driver = { + .name = "gc2145", + }, + .probe = gc2145_probe, + .remove = gc2145_remove, + .id_table = gc2145_id, +}; + +module_i2c_driver(gc2145_i2c_driver); + diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index 3bad9b121991..db416df15659 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -521,9 +521,6 @@ static void canvas_pool_config(void) canvas_pool_register_const_canvas(0x70, 0x77, "ppmgr"); canvas_pool_register_const_canvas(0xe4, 0xef, "encoder"); canvas_pool_register_const_canvas(0x40, 0x48, "osd"); -#ifdef CONFIG_AMLOGIC_VIDEOIN_MANAGER - canvas_pool_register_const_canvas(0x4e, 0x5f, "vm"); -#endif canvas_pool_register_const_canvas(0xc0, 0xd7, "amlvideo2"); /*please add static canvas later. */ } diff --git a/include/linux/amlogic/media/camera/aml_cam_info.h b/include/linux/amlogic/media/camera/aml_cam_info.h new file mode 100644 index 000000000000..b669ef4f466a --- /dev/null +++ b/include/linux/amlogic/media/camera/aml_cam_info.h @@ -0,0 +1,142 @@ +/* + * include/linux/amlogic/media/camera/aml_cam_info.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __AML_CAM_DEV__ +#define __AML_CAM_DEV__ +#include +#include +#include +#include +#include +#include + +#define FRONT_CAM 0 +#define BACK_CAM 1 + +enum resolution_size { + SIZE_NULL = 0, SIZE_176X144, /* 4:3 */ + SIZE_320X240, /* 4:3 */ + SIZE_352X288, /* 4:3 */ + SIZE_640X480, /* 0.3M 4:3 */ + SIZE_720X405, /* 0.3M 16:9 */ + SIZE_800X600, /* 0.5M 4:3 */ + SIZE_960X540, /* 0.5M 16:9 */ + SIZE_1024X576, /* 0.6M 16:9 */ + SIZE_960X720, /* 0.7M 4:3 */ + SIZE_1024X768, /* 0.8M 4:3 */ + SIZE_1280X720, /* 0.9M 16:9 */ + SIZE_1152X864, /* 1M 4:3 */ + SIZE_1366X768, /* 1M 16:9 */ + SIZE_1280X960, /* 1.2M 4:3 */ + SIZE_1280X1024, /* 1.3M 16:9. */ + SIZE_1400X1050, /* 1.5M 4:3 */ + SIZE_1600X900, /* 1.5M 16:9 */ + SIZE_1600X1200, /* 2M 4:3 */ + SIZE_1920X1080, /* 2M 16:9 */ + SIZE_1792X1344, /* 2.4M 4:3 */ + SIZE_2048X1152, /* 2.4M 16:9 */ + SIZE_2048X1536, /* 3.2M 4:3 */ + SIZE_2304X1728, /* 4M 4:3 */ + SIZE_2560X1440, /* 4M 16:9 */ + SIZE_2592X1944, /* 5M 4:3 */ + SIZE_3072X1728, /* 5M 16:9 */ + SIZE_2816X2112, /* 6M 4:3 */ + SIZE_3264X1836, /* 6m 16:9 */ + SIZE_3072X2304, /* 7M 4:3 */ + SIZE_3200X2400, /* 7.5M 4:3 */ + SIZE_3264X2448, /* 8M 4:3 */ + SIZE_3840X2160, /* 8M 16:9 */ + SIZE_3456X2592, /* 9M 4:3 */ + SIZE_3600X2700, /* 9.5M 4:3 */ + SIZE_4096X2304, /* 9.5M 16:9 */ + SIZE_3672X2754, /* 10M 4:3 */ + SIZE_3840X2880, /* 11M 4:3 */ + SIZE_4000X3000, /* 12M 4:3 */ + SIZE_4608X2592, /* 12M 16:9 */ + SIZE_4096X3072, /* 12.5M 4:3 */ + SIZE_4800X3200, /* 15M 4:3 */ + SIZE_5120X2880, /* 15M 16:9 */ + SIZE_5120X3840, /* 20M 4:3 */ + SIZE_6400X4800, /* 30M 4:3 */ +}; + +typedef int (*aml_cam_probe_fun_t)(struct i2c_adapter *); + +struct aml_cam_info_s { + struct list_head info_entry; + const char *name; + unsigned int i2c_bus_num; + unsigned int pwdn_act; + unsigned int front_back; /* front is 0, back is 1 */ + unsigned int m_flip; + unsigned int v_flip; + unsigned int flash; + unsigned int auto_focus; + unsigned int i2c_addr; + const char *motor_driver; + const char *resolution; + const char *version; + unsigned int mclk; + unsigned int flash_support; + unsigned int flash_ctrl_level; + unsigned int torch_support; + unsigned int torch_ctrl_level; + unsigned int vcm_mode; + unsigned int spread_spectrum; + unsigned int vdin_path; + unsigned int bt_path_count; + enum bt_path_e bt_path; + enum cam_interface_e interface; + enum clk_channel_e clk_channel; + /* gpio_t pwdn_pin; */ + /* gpio_t rst_pin; */ + /* gpio_t flash_ctrl_pin; */ + /* gpio_t torch_ctrl_pin; */ + unsigned int pwdn_pin; + unsigned int rst_pin; + unsigned int flash_ctrl_pin; + unsigned int torch_ctrl_pin; + enum resolution_size max_cap_size; + enum tvin_color_fmt_e bayer_fmt; + const char *config; + struct pinctrl *camera_pin_ctrl; +}; +/* aml_cam_info_t */ + +struct aml_camera_i2c_fig_s { + unsigned short addr; + unsigned char val; +}; + +struct aml_camera_i2c_fig0_s { + unsigned short addr; + unsigned short val; +}; + +struct aml_camera_i2c_fig1_s { + unsigned char addr; + unsigned char val; +}; + +extern void aml_cam_init(struct aml_cam_info_s *cam_dev); +extern void aml_cam_uninit(struct aml_cam_info_s *cam_dev); +extern void aml_cam_flash(struct aml_cam_info_s *cam_dev, int is_on); +extern void aml_cam_torch(struct aml_cam_info_s *cam_dev, int is_on); +extern int aml_cam_info_reg(struct aml_cam_info_s *cam_info); +extern int aml_cam_info_unreg(struct aml_cam_info_s *cam_info); + +#endif /* __AML_CAM_DEV__ */ diff --git a/include/linux/amlogic/media/camera/flashlight.h b/include/linux/amlogic/media/camera/flashlight.h new file mode 100644 index 000000000000..d59437251385 --- /dev/null +++ b/include/linux/amlogic/media/camera/flashlight.h @@ -0,0 +1,34 @@ +/* + * include/linux/amlogic/media/camera/flashlight.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _VIDEO_AMLOGIC_FLASHLIGHT_INCLUDE_ +#define _VIDEO_AMLOGIC_FLASHLIGHT_INCLUDE_ +struct aml_plat_flashlight_data_s { + void (*flashlight_on)(void); + void (*flashlight_off)(void); +}; + +enum aml_plat_flashlight_status_s { + FLASHLIGHT_AUTO = 0, + FLASHLIGHT_ON, + FLASHLIGHT_OFF, + FLASHLIGHT_TORCH, + FLASHLIGHT_RED_EYE, +}; + +#endif + diff --git a/include/linux/amlogic/media/camera/vmapi.h b/include/linux/amlogic/media/camera/vmapi.h new file mode 100644 index 000000000000..b1d832eda9db --- /dev/null +++ b/include/linux/amlogic/media/camera/vmapi.h @@ -0,0 +1,63 @@ +/* + * include/linux/amlogic/media/camera/vmapi.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef VM_API_INCLUDE_ +#define VM_API_INCLUDE_ + +struct vm_output_para { + int width; + int height; + int bytesperline; + int v4l2_format; + int index; + int v4l2_memory; + int zoom; /* set -1 as invalid */ + int mirror; /* set -1 as invalid */ + int angle; + uintptr_t vaddr;/*unsigned*/ + unsigned int ext_canvas; +}; +/*struct vm_output_para*/ +struct videobuf_buffer; +struct vb2_buffer; + +struct vm_init_s { + size_t vm_buf_size; + struct page *vm_pages; + resource_size_t buffer_start; + unsigned int vdin_id; + unsigned int bt_path_count; + bool isused; + bool mem_alloc_succeed; +}; +/*struct vm_init_s*/ + +int vm_fill_this_buffer(struct videobuf_buffer *vb, struct vm_output_para *para, + struct vm_init_s *info); +int vm_fill_buffer(struct videobuf_buffer *vb, struct vm_output_para *para); + +int vm_fill_buffer2(struct vb2_buffer *vb, struct vm_output_para *para); + +#ifdef CONFIG_CMA +int vm_init_buf(size_t size); +int vm_init_resource(size_t size, struct vm_init_s *info); +void vm_deinit_buf(void); +void vm_deinit_resource(struct vm_init_s *info); +void vm_reserve_cma(void); +#endif + +#endif /* VM_API_INCLUDE_ */ From 298aa2d9dd18f8fd25d1ac3e46205d4556e17f71 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Mon, 29 Oct 2018 11:30:34 +0800 Subject: [PATCH 0575/1060] atv_demod: switch channel with the script, the ATV shows no signal [1/1] PD#SWPL-791 Problem: Switch channel with the script lasts 14 hours, the ATV shows no signal. Solution: To avoid conflict, don't need to check the CLK and PLL states in atv demod write and read function. Verify: verified by p321 Change-Id: I033c54f14541ed540dfce1b9c4e21d2b5a8b9487 Signed-off-by: nengwen.chen Conflicts: drivers/amlogic/atv_demod/atv_demod_ops.c --- drivers/amlogic/atv_demod/atv_demod_ops.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index baadebe19f72..bba68d7d9297 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -390,10 +390,8 @@ static int atv_demod_set_config(struct dvb_frontend *fe, void *priv_cfg) case AML_ATVDEMOD_RESUME: if (priv->state == ATVDEMOD_STATE_SLEEP) { - if (!atv_demod_enter_mode(fe)) { + if (!atv_demod_enter_mode(fe)) priv->state = ATVDEMOD_STATE_WORK; - priv->standby = false; - } } break; From 3c693dd285441d469cbd056307897ad8c768d5dc Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Thu, 8 Nov 2018 19:57:53 +0800 Subject: [PATCH 0576/1060] atv_demod: pc bad value in panic after change source [1/1] PD#SWPL-1636 Problem: 1.pc bad value in kernel panic after change source. 2.System crash down when change source. Solution: optimize atv demod code. Verify: verified by p321 Change-Id: I655d1253950475dfb49ae1b174597797000adb73 Signed-off-by: nengwen.chen Conflicts: drivers/amlogic/atv_demod/atv_demod_ops.c --- drivers/amlogic/atv_demod/atv_demod_ops.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index bba68d7d9297..4b9f589fb7a2 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -73,8 +73,7 @@ void aml_fe_get_atvaudio_state(int *state) /* scan mode need mute */ if (priv->state == ATVDEMOD_STATE_WORK && !priv->scanning - && !priv->standby - && av_status) { + && !priv->standby) { retrieve_vpll_carrier_lock(&vpll_lock); retrieve_vpll_carrier_line_lock(&line_lock); if ((vpll_lock == 0) && (line_lock == 0)) { @@ -87,9 +86,9 @@ void aml_fe_get_atvaudio_state(int *state) } } else { *state = 0; - pr_audio("ATV state[%d], scan[%d], standby[%d], av[%d].\n", - priv->state, priv->scanning, - priv->standby, av_status); + pr_audio("%s, ATV in state[%d], scanning[%d], standby[%d].\n", + __func__, priv->state, + priv->scanning, priv->standby); } /* If the atv signal is locked, it means there is audio data, @@ -173,9 +172,6 @@ int atv_demod_leave_mode(struct dvb_frontend *fe) struct atv_demod_priv *priv = fe->analog_demod_priv; priv->state = ATVDEMOD_STATE_IDEL; - priv->standby = true; - - usleep_range(30 * 1000, 30 * 1000 + 100); if (priv->afc.disable) priv->afc.disable(&priv->afc); @@ -287,6 +283,8 @@ static void atv_demod_set_params(struct dvb_frontend *fe, /* for searching mute audio */ priv->standby = false; } + + priv->standby = false; } static int atv_demod_has_signal(struct dvb_frontend *fe, u16 *signal) @@ -390,8 +388,10 @@ static int atv_demod_set_config(struct dvb_frontend *fe, void *priv_cfg) case AML_ATVDEMOD_RESUME: if (priv->state == ATVDEMOD_STATE_SLEEP) { - if (!atv_demod_enter_mode(fe)) + if (!atv_demod_enter_mode(fe)) { priv->state = ATVDEMOD_STATE_WORK; + priv->standby = false; + } } break; From cf6568a019dfeadf55f7a68ab3eb8305757fb2d0 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Wed, 5 Dec 2018 13:37:41 +0800 Subject: [PATCH 0577/1060] atv_demod: modify atv demod code [1/1] PD#SWPL-2295 Problem: 1.modify atv demod code for coverity. 2.add ntsc-m ring filter for t962x2. 3.merge code optimization from android l. 4.add tuner compatible info in dts for tuner debug. Solution: 1.modify atv demod code for coverity. 2.add ntsc-m ring filter for t962x2. 3.merge code optimization from android l. 4.add tuner compatible info in dts for tuner debug. Verify: verified by einstein Change-Id: I9696aa628315ee11f0c9dd279c7cc03797f04331 Signed-off-by: nengwen.chen Conflicts: arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts drivers/amlogic/atv_demod/atv_demod_access.c drivers/amlogic/atv_demod/atv_demod_driver.c drivers/amlogic/atv_demod/atv_demod_ops.c drivers/amlogic/atv_demod/atvdemod_func.c --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 1 + arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 1 + arch/arm/boot/dts/amlogic/txl_t950_p341.dts | 1 + arch/arm/boot/dts/amlogic/txl_t960_p346.dts | 1 + arch/arm/boot/dts/amlogic/txl_t962_p320.dts | 1 + arch/arm/boot/dts/amlogic/txl_t962_p321.dts | 1 + .../boot/dts/amlogic/txl_t962_p321_720p.dts | 1 + arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts | 1 + .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 1 + .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 1 + .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 1 + arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 14 +- arch/arm64/boot/dts/amlogic/txl_t950_p341.dts | 1 + arch/arm64/boot/dts/amlogic/txl_t960_p346.dts | 1 + arch/arm64/boot/dts/amlogic/txl_t962_p320.dts | 1 + arch/arm64/boot/dts/amlogic/txl_t962_p321.dts | 1 + .../boot/dts/amlogic/txl_t962_p321_720p.dts | 1 + .../boot/dts/amlogic/txlx_t962e_r321.dts | 1 + .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 1 + .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 1 + .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 1 + .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 1 + .../boot/dts/amlogic/txlx_t962x_r314.dts | 14 +- drivers/amlogic/atv_demod/atv_demod_access.c | 36 ++++- drivers/amlogic/atv_demod/atv_demod_access.h | 2 + drivers/amlogic/atv_demod/atv_demod_debug.c | 5 +- drivers/amlogic/atv_demod/atv_demod_driver.c | 32 ++--- drivers/amlogic/atv_demod/atv_demod_driver.h | 4 +- drivers/amlogic/atv_demod/atv_demod_ops.c | 33 +++-- drivers/amlogic/atv_demod/atv_demod_v4l2.c | 2 +- drivers/amlogic/atv_demod/atvauddemod_func.c | 8 +- drivers/amlogic/atv_demod/atvdemod_func.c | 124 +++++++++--------- drivers/amlogic/atv_demod/atvdemod_func.h | 1 + 33 files changed, 172 insertions(+), 124 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index fcd83598d511..5870e7a1593c 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -993,6 +993,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c0>; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 1fed35eef24d..d54452b0bdb4 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1042,6 +1042,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c0>; diff --git a/arch/arm/boot/dts/amlogic/txl_t950_p341.dts b/arch/arm/boot/dts/amlogic/txl_t950_p341.dts index 4f53cadaa1f1..55f8f37e8dfe 100644 --- a/arch/arm/boot/dts/amlogic/txl_t950_p341.dts +++ b/arch/arm/boot/dts/amlogic/txl_t950_p341.dts @@ -436,6 +436,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txl_t960_p346.dts b/arch/arm/boot/dts/amlogic/txl_t960_p346.dts index 454b1f112f5f..fc5beecdcbf1 100644 --- a/arch/arm/boot/dts/amlogic/txl_t960_p346.dts +++ b/arch/arm/boot/dts/amlogic/txl_t960_p346.dts @@ -437,6 +437,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p320.dts b/arch/arm/boot/dts/amlogic/txl_t962_p320.dts index 154b9f41532c..ca71b184ee52 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p320.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p320.dts @@ -427,6 +427,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "si2151_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts index d2b48c43b38e..9f464fe4c5a7 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts @@ -448,6 +448,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts index 5ddaf04b9e8d..fddd1d154825 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -448,6 +448,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index 6c1350049843..05a3a8be78ee 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -618,6 +618,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "si2151_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 913250053e81..2aa758832650 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -662,6 +662,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "si2151_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 50b99d0d4cb8..b03caca8d328 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -620,6 +620,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index c44468a42e94..db5f94fcb1df 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -616,6 +616,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 16a8f9fb5760..5e6f851f96d9 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -624,14 +624,12 @@ tuner: tuner { compatible = "amlogic, tuner"; - status = "disabled"; - tuner_cur = <0>; /* default use tuner */ - tuner_num = <1>; /* tuner number, multi tuner support */ - tuner_name_0 = "mxl661_tuner"; - tuner_i2c_adap_0 = <&i2c1>; - tuner_i2c_addr_0 = <0x60>; - tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode_0 = <0>; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ diff --git a/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts b/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts index c3ad02ce19b3..ecf2c7e4b754 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts @@ -436,6 +436,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts b/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts index 1d3a079c0a09..e4321378c211 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts @@ -436,6 +436,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts index b87e7e04187d..6fd359f256d5 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts @@ -427,6 +427,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "si2151_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts index d0b8ad511a58..c68566302ff9 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts @@ -440,6 +440,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts index 5aa2c625fd53..8d28468048bf 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -440,6 +440,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "r842_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index f66847df76bc..7d6b5a8d66cb 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -617,6 +617,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "si2151_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index d2899aa2d515..d0f142bc37f7 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -661,6 +661,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "si2151_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index e9dc340f3a8e..2225bcf0656d 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -618,6 +618,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index c89d29b78dd1..ff5f8f246645 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -618,6 +618,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index 0cacff78d2b8..d15cab0023e6 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -617,6 +617,7 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 3c25f458df97..5750072fe2ff 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -620,14 +620,12 @@ tuner: tuner { compatible = "amlogic, tuner"; - status = "disabled"; - tuner_cur = <0>; /* default use tuner */ - tuner_num = <1>; /* tuner number, multi tuner support */ - tuner_name_0 = "mxl661_tuner"; - tuner_i2c_adap_0 = <&i2c1>; - tuner_i2c_addr_0 = <0x60>; - tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode_0 = <0>; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ diff --git a/drivers/amlogic/atv_demod/atv_demod_access.c b/drivers/amlogic/atv_demod/atv_demod_access.c index 390c5d02cf91..de48c0bfd7d9 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.c +++ b/drivers/amlogic/atv_demod/atv_demod_access.c @@ -82,9 +82,9 @@ int atvaudiodem_reg_read(unsigned int reg, unsigned int *val) return 0; } } - - if (amlatvdemod_devp->audio_reg_base) - *val = readl(amlatvdemod_devp->audio_reg_base + reg); +#endif + if (amlatvdemod_devp->audiodemod_reg_base) + *val = readl(amlatvdemod_devp->audiodemod_reg_base + reg); return 0; } @@ -101,8 +101,32 @@ int atvaudiodem_reg_write(unsigned int reg, unsigned int val) } } + if (amlatvdemod_devp->audiodemod_reg_base) + writel(val, (amlatvdemod_devp->audiodemod_reg_base + reg)); + + return 0; +} + +int atvaudio_reg_read(unsigned int *val) +{ + /* only 0xffd0d340 read */ + /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ + /* bit1: Din5, 0 = atv_demod, 1 = adec */ + /* bit2: L/R swap for adec audio data */ if (amlatvdemod_devp->audio_reg_base) - writel(val, (amlatvdemod_devp->audio_reg_base + reg)); + *val = readl(amlatvdemod_devp->audio_reg_base); + + return 0; +} + +int atvaudio_reg_write(unsigned int val) +{ + /* only 0xffd0d340 write */ + /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ + /* bit1: Din5, 0 = atv_demod, 1 = adec */ + /* bit2: L/R swap for adec audio data */ + if (amlatvdemod_devp->audio_reg_base) + writel(val, amlatvdemod_devp->audio_reg_base); return 0; } @@ -152,10 +176,10 @@ void atv_dmd_wr_reg(unsigned char block, unsigned char reg, unsigned long data) unsigned long atv_dmd_rd_reg(unsigned char block, unsigned char reg) { - unsigned long data = 0; + unsigned int data = 0; unsigned int reg_addr = (block << 8) + reg * 4; - amlatvdemod_reg_read(reg_addr, (unsigned int *)&data); + amlatvdemod_reg_read(reg_addr, &data); return data; } diff --git a/drivers/amlogic/atv_demod/atv_demod_access.h b/drivers/amlogic/atv_demod/atv_demod_access.h index 51b21821b46a..d346a5a70c12 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.h +++ b/drivers/amlogic/atv_demod/atv_demod_access.h @@ -25,6 +25,8 @@ extern int amlatvdemod_reg_read(unsigned int reg, unsigned int *val); extern int amlatvdemod_reg_write(unsigned int reg, unsigned int val); extern int atvaudiodem_reg_read(unsigned int reg, unsigned int *val); extern int atvaudiodem_reg_write(unsigned int reg, unsigned int val); +extern int atvaudio_reg_read(unsigned int *val); +extern int atvaudio_reg_write(unsigned int val); extern int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val); extern int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val); extern int amlatvdemod_periphs_reg_read(unsigned int reg, unsigned int *val); diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index ff8e6e18d163..0a62ab442803 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -96,6 +96,8 @@ DEBUGFS_CREATE_NODE(audio_a2_power_threshold, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_shift, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_lpr, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(audio_atv_ov, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(audio_atv_ov_flag, 0640, dentry, u32)\ } @@ -178,12 +180,11 @@ static ssize_t debugfs_write(struct file *file, const char __user *userbuf, char buf[20] = { 0 }; int len = ARRAY_SIZE(debugfs_dentry); + memset(buf, 0, sizeof(buf)); count = min_t(size_t, count, (sizeof(buf) - 1)); if (copy_from_user(buf, userbuf, count)) return -EFAULT; - buf[count] = 0; - /*i = sscanf(buf, "%d", &val);*/ i = kstrtoint(buf, 0, &val); if (i == 0) { diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index ceb4f299f0a0..67a2264364fa 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -548,7 +548,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - pr_err("get demod memory resource fail.\n"); + pr_err("no demod memory resource.\n"); goto fail_get_resource; } @@ -566,7 +566,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { - pr_err("no hiu demod memory resource.\n"); + pr_err("no hiu memory resource.\n"); dev->hiu_reg_base = NULL; } else { size_io_reg = resource_size(res); @@ -584,7 +584,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 2); if (!res) { - pr_err("no periphs demod memory resource.\n"); + pr_err("no periphs memory resource.\n"); dev->periphs_reg_base = NULL; } else { size_io_reg = resource_size(res); @@ -602,29 +602,31 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 3); if (!res) { - pr_err("no audio demod memory resource.\n"); - dev->audio_reg_base = NULL; + pr_err("no audiodemod memory resource.\n"); + dev->audiodemod_reg_base = NULL; } else { size_io_reg = resource_size(res); - dev->audio_reg_base = devm_ioremap_nocache( + dev->audiodemod_reg_base = devm_ioremap_nocache( &pdev->dev, res->start, size_io_reg); - if (!dev->audio_reg_base) { - pr_err("audio ioremap failed.\n"); + if (!dev->audiodemod_reg_base) { + pr_err("audiodemod ioremap failed.\n"); goto fail_get_resource; } - pr_info("audio start = 0x%p, size = 0x%x, base = 0x%p.\n", + pr_info("audiodemod start = 0x%p, size = 0x%x, base = 0x%p.\n", (void *) res->start, size_io_reg, - dev->audio_reg_base); + dev->audiodemod_reg_base); } + /* add for audio system control */ if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { - /* add for audio system control */ - dev->audio_demod_reg_base = ioremap( - round_down(0xffd0d340, 0x3), 4); + dev->audio_reg_base = ioremap(round_down(0xffd0d340, 0x3), 4); - pr_info("audio_demod_reg_base = 0x%p.\n", - dev->audio_demod_reg_base); + pr_info("audio_reg_base = 0x%p.\n", dev->audio_reg_base); + } else if (is_meson_tl1_cpu()) { + dev->audio_reg_base = ioremap(round_down(0xff600340, 0x3), 4); + + pr_info("audio_reg_base = 0x%p.\n", dev->audio_reg_base); } aml_atvdemod_dt_parse(dev); diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.h b/drivers/amlogic/atv_demod/atv_demod_driver.h index 55d67a5eddc7..d4ac1eff666a 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.h +++ b/drivers/amlogic/atv_demod/atv_demod_driver.h @@ -66,10 +66,10 @@ struct aml_atvdemod_device { bool tuner_attached; void __iomem *demod_reg_base; - void __iomem *audio_reg_base; + void __iomem *audiodemod_reg_base; void __iomem *hiu_reg_base; void __iomem *periphs_reg_base; - void __iomem *audio_demod_reg_base; + void __iomem *audio_reg_base; unsigned int reg_23cf; /* IIR filter */ int btsc_sap_mode; /*0: off 1:monitor 2:auto */ diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index 4b9f589fb7a2..a7b2a5a93039 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -539,6 +539,7 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, int i = 0; int try_vfmt_cnt = 300; int varify_cnt = 0; + int cvbs_std = 0; v4l2_std_id std_bk = 0; unsigned int broad_std = 0; unsigned int audio = 0; @@ -550,12 +551,12 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, __func__); break; } - std_bk = aml_fe_hook_get_fmt(); - if (std_bk) { + cvbs_std = aml_fe_hook_get_fmt(); + if (cvbs_std) { varify_cnt++; - pr_dbg("get varify_cnt:%d, cnt:%d, std_bk:0x%x\n", + pr_dbg("get cvbs_std varify_cnt:%d, cnt:%d, cvbs_std:0x%x\n", varify_cnt, i, - (unsigned int) std_bk); + (unsigned int) cvbs_std); if (((v4l2_fe->tuner_id == AM_TUNER_R840 || v4l2_fe->tuner_id == AM_TUNER_R842) && varify_cnt > 0) @@ -592,13 +593,13 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, usleep_range(30 * 1000, 30 * 1000 + 100); } - pr_dbg("get std_bk cnt:%d, std_bk: 0x%x\n", - i, (unsigned int) std_bk); + pr_dbg("get cvbs_std cnt:%d, cvbs_std: 0x%x\n", + i, (unsigned int) cvbs_std); - if (std_bk == 0) { + if (cvbs_std == 0) { pr_err("%s: failed to get video fmt, assume PAL.\n", __func__); - std_bk = TVIN_SIG_FMT_CVBS_PAL_I; + cvbs_std = TVIN_SIG_FMT_CVBS_PAL_I; p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_DK; p->frequency += 1; p->audmode = V4L2_STD_PAL_DK; @@ -613,7 +614,7 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, usleep_range(20 * 1000, 20 * 1000 + 100); } - std_bk = atvdemod_fe_tvin_fmt_to_v4l2_std(std_bk); + std_bk = atvdemod_fe_tvin_fmt_to_v4l2_std(cvbs_std); } else { /* Only search std by user setting, * so no need tvafe identify signal. @@ -630,9 +631,14 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, if (std_bk & V4L2_COLOR_STD_NTSC) { #if 1 /* For TV Signal Generator(TG39) test, NTSC need support other audio.*/ - amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); - broad_std = aml_audiomode_autodet(v4l2_fe); - audio = atvdemod_fmt_2_v4l2_std(broad_std); + if (cvbs_std == TVIN_SIG_FMT_CVBS_NTSC_M) { + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + audio = V4L2_STD_NTSC_M; + } else { + amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC); + broad_std = aml_audiomode_autodet(v4l2_fe); + audio = atvdemod_fmt_2_v4l2_std(broad_std); + } #if 0 /* I don't know what's going on here */ if (audio == V4L2_STD_PAL_M) audio = V4L2_STD_NTSC_M; @@ -652,8 +658,7 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, #endif } else { /* V4L2_COLOR_STD_PAL */ - if (cvbs_std == TVIN_SIG_FMT_CVBS_PAL_M || - cvbs_std == TVIN_SIG_FMT_CVBS_PAL_CN) { + if (cvbs_std == TVIN_SIG_FMT_CVBS_PAL_M) { broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; audio = V4L2_STD_PAL_M; } else { diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.c b/drivers/amlogic/atv_demod/atv_demod_v4l2.c index beaad44f9670..4e228f6badcb 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.c +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.c @@ -587,7 +587,7 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, return 0; } -static int v4l2_frontend_ioctl_properties(struct file *filp, +static long v4l2_frontend_ioctl_properties(struct file *filp, unsigned int cmd, void *parg) { struct v4l2_frontend *v4l2_fe = video_get_drvdata(video_devdata(filp)); diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index b787edccbbe5..080db0f4c544 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -1355,14 +1355,10 @@ void set_output_left_right_exchange(unsigned int ch) { unsigned int read = 0; - if (amlatvdemod_devp->audio_demod_reg_base == NULL) - return; - - read = readl(amlatvdemod_devp->audio_demod_reg_base); + atvaudio_reg_read(&read); if ((read & (1 << 2)) != ((ch & 0x01) << 2)) - writel((read & ~(1 << 2)) | ((ch & 0x01) << 2), - amlatvdemod_devp->audio_demod_reg_base); + atvaudio_reg_write((read & ~(1 << 2)) | ((ch & 0x01) << 2)); } #endif /* __ATVAUDDEMOD_FUN_H */ diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 29e41687b3b5..bd3fd41bbb04 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -96,6 +96,9 @@ unsigned int audio_a2_threshold = 0x800; unsigned int audio_a2_delay = 10; unsigned int audio_nicam_delay = 100; +unsigned int audio_atv_ov; +unsigned int audio_atv_ov_flag; + enum AUDIO_SCAN_ID { ID_PAL_I = 0, ID_PAL_M, @@ -268,8 +271,7 @@ void atv_dmd_misc(void) 0x18, 0x7ffff); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); - atvaudio_ctrl_read(®); - atvaudio_ctrl_write(reg & (~0x3)); + atvaudio_reg_write(0x0); audio_atv_ov_flag = 1; } else { atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, @@ -278,8 +280,7 @@ void atv_dmd_misc(void) 0x18, 0xc000); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); - atvaudio_ctrl_read(®); - atvaudio_ctrl_write(reg | 0x3); + atvaudio_reg_write(0x7); audio_atv_ov_flag = 0; } } @@ -301,26 +302,11 @@ void atv_dmd_ring_filter(bool on) atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0x1d175c); atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x2d19e4); - /* enable filter */ atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x1); - } else { - /* default value */ - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8423F6); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x37FE45); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x3C223B); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8423F6); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x37FE45); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x3C223B); - - /* disable filter */ + } else atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0); - } - pr_dbg("%s do atv_dmd_ring_filter %d ...\n", __func__, on); + pr_err("%s do atv_dmd_ring_filter %d ...\n", __func__, on); } void atv_dmd_non_std_set(bool enable) @@ -551,7 +537,8 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I)) { + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M)) { gp_coeff_1[0] = 0x57777; gp_coeff_1[1] = 0xdd777; gp_coeff_1[2] = 0x7d777; @@ -1803,6 +1790,12 @@ int atvdemod_init(void) pr_err("%s do atv_dmd_misc ...\n", __func__); atv_dmd_misc(); + if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || + broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) + atv_dmd_ring_filter(true); + else + atv_dmd_ring_filter(false); + pr_err("%s do atv_dmd_soft_reset ...\n", __func__); /*4.software reset*/ atv_dmd_soft_reset(); @@ -1950,14 +1943,14 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) unsigned long carrier_power_average_max = 0; unsigned long carrier_power_average[4] = {0}; unsigned long temp_data = 0; - int carrier_lock_count = 0; - int lock = 0; + int lock = 0, line_lock = 0; int broad_std_final = 0; int num = 0, i = 0, final_id = 0; int delay_ms = 10, delay_ms_default = 10; int cur_std = ID_PAL_DK; bool secam_signal = false; - + bool ntsc_signal = false; + bool has_audio = false; #if 0 temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); temp_data = temp_data | 0x80;/* 0x40 */ @@ -1976,7 +1969,10 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: - + ntsc_signal = true; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + break; +#if 0 /* ntsc will try other audio */ broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M; atvdemod_init(); temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); @@ -1984,7 +1980,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ return broad_std; - +#endif case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2: case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3: @@ -2158,9 +2154,15 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; cur_std = ID_PAL_M; - p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M; - p->frequency += 1; - p->audmode = V4L2_STD_PAL_M; + if (!ntsc_signal) { + p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M; + p->frequency += 1; + p->audmode = V4L2_STD_PAL_M; + } else { + p->std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M; + p->frequency += 1; + p->audmode = V4L2_STD_NTSC_M; + } delay_ms = delay_ms_default; break; @@ -2188,32 +2190,37 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) /* enable audio detect function */ temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80;/* 0x40 */ + temp_data = temp_data | 0x87;/* 0x40 */ atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); usleep_range(delay_ms * 1000, delay_ms * 1000 + 100); - carrier_lock_count = 0; + /* ----------------judgment signal state--------------------- */ i = 4; + has_audio = false; while (i--) { retrieve_vpll_carrier_lock(&lock); - if (lock == 0) + line_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); + if (lock == 0 && (line_lock & 0x10) == 0) { + has_audio = true; break; - carrier_lock_count++; - if (carrier_lock_count >= 20) { - pr_err("%s step2, retrieve_vpll_carrier_lock failed\n", - __func__); - /* return broad_std; */ } + usleep_range(6000, 9000); } /* ----------------read carrier_power--------------------- */ - for (i = 0; i < 100; i++) { - carrier_power = - atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x03); - carrier_power_max += carrier_power; + if (has_audio) { + for (i = 0; i < 100; i++) { + carrier_power = atv_dmd_rd_reg( + APB_BLOCK_ADDR_SIF_STG_2, 0x03); + carrier_power_max += carrier_power; + } + carrier_power = carrier_power_max/i; + } else { + carrier_power = 0; + pr_err("[%s] pll and line unlock.\n", __func__); } - carrier_power = carrier_power_max/i; + carrier_power_max = 0; pr_err("[%s] [num:%d] [broad_std:%d] audio carrier power: %lu. @@@@@@@@@@\n", __func__, num, broad_std, carrier_power); @@ -2226,7 +2233,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) void aml_audio_valume_gain_set(unsigned int audio_gain) { - unsigned long audio_gain_data, temp_data; + unsigned long audio_gain_data = 0, temp_data = 0; if (audio_gain > 0xfff) { pr_err("Error: atv in gain max 7.998, min 0.002! gain = value/512\n"); @@ -2241,7 +2248,7 @@ void aml_audio_valume_gain_set(unsigned int audio_gain) unsigned int aml_audio_valume_gain_get(void) { - unsigned long audio_gain_data; + unsigned long audio_gain_data = 0; audio_gain_data = atv_dmd_rd_word(APB_BLOCK_ADDR_MONO_PROC, 0x52); audio_gain_data = audio_gain_data & 0xfff; @@ -2250,7 +2257,7 @@ unsigned int aml_audio_valume_gain_get(void) void aml_fix_PWM_adjust(int enable) { - unsigned long temp_data; + unsigned long temp_data = 0; /* * temp_data = atv_dmd_rd_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08); * temp_data = temp_data | 0x01; @@ -2271,16 +2278,15 @@ void aml_fix_PWM_adjust(int enable) void aml_audio_overmodulation(int enable) { - static int ov_flag; - unsigned long tmp_v; - unsigned long tmp_v1; + unsigned long tmp_v = 0; + unsigned long tmp_v1 = 0; u32 Broadcast_Standard = broad_std; if (enable && Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) { tmp_v = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x28); tmp_v = tmp_v&0xffff; - if (tmp_v >= 0x10 && ov_flag == 0) { + if (tmp_v > 0x10 && audio_atv_ov_flag == 0) { tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); tmp_v1 = (tmp_v1&0xffffff)|(1<<24); @@ -2288,19 +2294,12 @@ void aml_audio_overmodulation(int enable) atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x14, 0x8000015); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x1c, 0x0f000); - } else if (tmp_v >= 0x2500 && ov_flag == 0) { - tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); - tmp_v1 = (tmp_v1&0xffffff)|(1<<24); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x14, 0xf400015); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x18, 0xc000); + 0x18, 0x7ffff); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); - ov_flag = 1; - } else if (tmp_v <= 0x10 && ov_flag == 1) { + atvaudio_reg_write(0x0); + audio_atv_ov_flag = 1; + } else if (tmp_v <= 0x10 && audio_atv_ov_flag == 1) { tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); tmp_v1 = (tmp_v1&0xffffff)|(0<<24); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); @@ -2310,7 +2309,8 @@ void aml_audio_overmodulation(int enable) 0x18, 0xc000); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); - ov_flag = 0; + atvaudio_reg_write(0x7); + audio_atv_ov_flag = 0; } } } diff --git a/drivers/amlogic/atv_demod/atvdemod_func.h b/drivers/amlogic/atv_demod/atvdemod_func.h index 530982c45cda..30ef9b8f9ef8 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.h +++ b/drivers/amlogic/atv_demod/atvdemod_func.h @@ -64,6 +64,7 @@ extern void read_version_register(void); extern void check_communication_interface(void); extern void power_on_receiver(void); extern void atv_dmd_misc(void); +extern void atv_dmd_ring_filter(bool on); extern void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, int Tuner_Input_IF_inverted, int GDE_Curve, From e1707ab901ec637bc49f0aeef2ea9b65f3993a44 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Mon, 10 Dec 2018 20:06:41 +0800 Subject: [PATCH 0578/1060] atv_demod: reduce atv demod debug info when searching. [1/1] PD#SWPL-2712 Problem: reduce atv demod debug info when searching. Solution: reduce atv demod debug info when searching. Verify: verified by r311 Change-Id: I01f1cebabdacdea4bb7695c2133b99157d8db19d Signed-off-by: nengwen.chen Conflicts: drivers/amlogic/atv_demod/atvdemod_func.c --- drivers/amlogic/atv_demod/atv_demod_ops.c | 2 +- drivers/amlogic/atv_demod/atvdemod_func.c | 50 +++++++++++------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index a7b2a5a93039..f5f5515a7eae 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -303,7 +303,7 @@ static int atv_demod_has_signal(struct dvb_frontend *fe, u16 *signal) __func__, vpll_lock, line_lock); } else { *signal = V4L2_TIMEDOUT; - pr_info("%s unlocked [vpll_lock: 0x%x, line_lock:0x%x]\n", + pr_dbg("%s unlocked [vpll_lock: 0x%x, line_lock:0x%x]\n", __func__, vpll_lock, line_lock); } diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index bd3fd41bbb04..b239adef0e69 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -306,7 +306,7 @@ void atv_dmd_ring_filter(bool on) } else atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0); - pr_err("%s do atv_dmd_ring_filter %d ...\n", __func__, on); + pr_dbg("%s do atv_dmd_ring_filter %d ...\n", __func__, on); } void atv_dmd_non_std_set(bool enable) @@ -530,7 +530,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, int gd_coeff[6] = { 0 }; int gd_bypass = 0; - pr_info("ATV-DMD configure receiver register\n"); + pr_dbg("ATV-DMD configure receiver register\n"); if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J) || @@ -947,7 +947,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } sif_fm_gain -= 2; /*avoid sound overflow@guanzhong*/ /*FE PATH*/ - pr_info("ATV-DMD configure mixer\n"); + pr_dbg("ATV-DMD configure mixer\n"); if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { tmp_int = (Tuner_IF_Frequency/125000); if (Tuner_Input_IF_inverted == 0x0) @@ -959,19 +959,19 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, mixer3_bypass = 0; } else { tmp_int = (Tuner_IF_Frequency/125000); - pr_info("ATV-DMD configure mixer 1\n"); + pr_dbg("ATV-DMD configure mixer 1\n"); if (Tuner_Input_IF_inverted == 0x0) mixer1 = 0xe8 - tmp_int; else mixer1 = tmp_int - 0x18; - pr_info("ATV-DMD configure mixer 2\n"); + pr_dbg("ATV-DMD configure mixer 2\n"); mixer3 = 0x30; mixer3_bypass = 0x1; } - pr_info("ATV-DMD configure mixer 3\n"); + pr_dbg("ATV-DMD configure mixer 3\n"); atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, mixer1); atv_dmd_wr_word(APB_BLOCK_ADDR_MIXER_3, 0x0, (((mixer3 & 0xff) << 8) | (mixer3_bypass & 0xff))); @@ -987,7 +987,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*GP Filter*/ - pr_info("ATV-DMD configure GP_filter\n"); + pr_dbg("ATV-DMD configure GP_filter\n"); if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { cv = gp_cv_g1; atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x0, @@ -1098,7 +1098,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*CRVY*/ - pr_info("ATV-DMD configure CRVY\n"); + pr_dbg("ATV-DMD configure CRVY\n"); if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { crvy_reg_1 = 0xFF; crvy_reg_2 = 0x00; @@ -1108,12 +1108,12 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x29, crvy_reg_1); - pr_info("ATV-DMD configure rcvy 2\n"); - pr_info("ATV-DMD configure rcvy, crvy_reg_2 = %x\n", crvy_reg_2); + pr_dbg("ATV-DMD configure rcvy 2\n"); + pr_dbg("ATV-DMD configure rcvy, crvy_reg_2 = %x\n", crvy_reg_2); atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x20, crvy_reg_2); /*SOUND SUPPRESS*/ - pr_info("ATV-DMD configure sound suppress\n"); + pr_dbg("ATV-DMD configure sound suppress\n"); if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) || (sound_format == 0)) @@ -1122,7 +1122,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_VD_IF, 0x02, 0x00); /*SIF*/ - pr_info("ATV-DMD configure sif\n"); + pr_dbg("ATV-DMD configure sif\n"); if (!(Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV)) { atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x03, sif_ic_bw); atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x01, sif_fi_mx); @@ -1166,7 +1166,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*VAGC*/ - pr_info("ATV-DMD configure vagc\n"); + pr_dbg("ATV-DMD configure vagc\n"); atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x48, 0x9B6F2C00); /*bw select mode*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x37, 0x1C); @@ -1196,7 +1196,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x12, (freq_hz_cvrt & 0xff)); /*OUTPUT STAGE*/ - pr_info("ATV-DMD configure output stage\n"); + pr_dbg("ATV-DMD configure output stage\n"); if (Broadcast_Standard != AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x0, 0x00); atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x1, 0x40); @@ -1206,7 +1206,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*GDE FILTER*/ - pr_info("ATV-DMD configure gde filter\n"); + pr_dbg("ATV-DMD configure gde filter\n"); if (GDE_Curve == 0) { gd_coeff[0] = 0x020; /*12'sd32;*/ gd_coeff[1] = 0xf5f; /*-12'sd161;*/ @@ -1253,7 +1253,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*PWM*/ - pr_info("ATV-DMD configure pwm\n"); + pr_dbg("ATV-DMD configure pwm\n"); atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x00, 0x1f40); /*4KHz*/ atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x04, 0xc8); /*26 dB dynamic range*/ @@ -1337,7 +1337,7 @@ int retrieve_vpll_carrier_afc(void) if ((pll_lock == 1) || (line_lock == 0x10)) { /*if pll unlock, afc is invalid*/ - pr_info("[afc invalid] pll: %d, line: %d, line_strong: %d, field: %d.\n", + pr_dbg("[afc invalid] pll: %d, line: %d, line_strong: %d, field: %d.\n", pll_lock, line_lock, line_lock_strong, field_lock); @@ -1783,11 +1783,11 @@ int atvdemod_init(void) { /* 1.set system clock when atv enter*/ - pr_err("%s do configure_receiver ...\n", __func__); - if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + pr_dbg("%s do configure_receiver ...\n", __func__); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()) sound_format = 1; configure_receiver(broad_std, if_freq, if_inv, gde_curve, sound_format); - pr_err("%s do atv_dmd_misc ...\n", __func__); + pr_dbg("%s do atv_dmd_misc ...\n", __func__); atv_dmd_misc(); if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || @@ -1796,7 +1796,7 @@ int atvdemod_init(void) else atv_dmd_ring_filter(false); - pr_err("%s do atv_dmd_soft_reset ...\n", __func__); + pr_dbg("%s do atv_dmd_soft_reset ...\n", __func__); /*4.software reset*/ atv_dmd_soft_reset(); @@ -1812,7 +1812,7 @@ int atvdemod_init(void) mix1_freq = atv_dmd_rd_byte(APB_BLOCK_ADDR_MIXER_1, 0x0); - pr_err("%s done\n", __func__); + pr_info("%s done\n", __func__); return 0; } @@ -1915,16 +1915,16 @@ void atv_dmd_set_std(void) if_inv = amlatvdemod_devp->if_inv; } - pr_info("[%s] set broad_std %d, hz_cvrt 0x%x, offset %d.\n", + pr_dbg("[%s] set broad_std %d, hz_cvrt 0x%x, offset %d.\n", __func__, broad_std, freq_hz_cvrt, amlatvdemod_devp->fre_offset); - pr_info("[%s] set std color %s, audio type %s.\n", + pr_dbg("[%s] set std color %s, audio type %s.\n", __func__, v4l2_std_to_str((0xff000000 & amlatvdemod_devp->std)), v4l2_std_to_str((0xffffff & amlatvdemod_devp->std))); - pr_info("[%s] set if_freq %d, if_inv %d.\n", + pr_dbg("[%s] set if_freq %d, if_inv %d.\n", __func__, amlatvdemod_devp->if_freq, amlatvdemod_devp->if_inv); From 9ed2178ee9568db70d71389657f8fa434bf7c736 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Fri, 7 Dec 2018 21:41:43 +0800 Subject: [PATCH 0579/1060] atv_demod: atv demod code optimization for audio [1/1] PD#TV-1448 Problem: 1.atv demod code optimization for audio 2.amlogic-4.9-dev Solution: atv demod code optimization for audio Verify: verified by einstein Change-Id: Ic1c6a26ef97fbaf288ae37f2761c0df83ec7cf1e Signed-off-by: nengwen.chen Conflicts: drivers/amlogic/atv_demod/atv_demod_monitor.c drivers/amlogic/atv_demod/atvdemod_func.c --- drivers/amlogic/atv_demod/atv_demod_access.c | 4 +- drivers/amlogic/atv_demod/atv_demod_access.h | 4 +- drivers/amlogic/atv_demod/atv_demod_afc.c | 3 +- drivers/amlogic/atv_demod/atv_demod_driver.c | 2 +- drivers/amlogic/atv_demod/atv_demod_monitor.c | 9 ++- drivers/amlogic/atv_demod/atvauddemod_func.c | 34 +++++--- drivers/amlogic/atv_demod/atvauddemod_func.h | 1 + drivers/amlogic/atv_demod/atvdemod_func.c | 78 +++++++++++++++---- 8 files changed, 99 insertions(+), 36 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_access.c b/drivers/amlogic/atv_demod/atv_demod_access.c index de48c0bfd7d9..177700edcfbd 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.c +++ b/drivers/amlogic/atv_demod/atv_demod_access.c @@ -107,7 +107,7 @@ int atvaudiodem_reg_write(unsigned int reg, unsigned int val) return 0; } -int atvaudio_reg_read(unsigned int *val) +int atvaudio_ctrl_read(unsigned int *val) { /* only 0xffd0d340 read */ /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ @@ -119,7 +119,7 @@ int atvaudio_reg_read(unsigned int *val) return 0; } -int atvaudio_reg_write(unsigned int val) +int atvaudio_ctrl_write(unsigned int val) { /* only 0xffd0d340 write */ /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ diff --git a/drivers/amlogic/atv_demod/atv_demod_access.h b/drivers/amlogic/atv_demod/atv_demod_access.h index d346a5a70c12..85c579c58b65 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.h +++ b/drivers/amlogic/atv_demod/atv_demod_access.h @@ -25,8 +25,8 @@ extern int amlatvdemod_reg_read(unsigned int reg, unsigned int *val); extern int amlatvdemod_reg_write(unsigned int reg, unsigned int val); extern int atvaudiodem_reg_read(unsigned int reg, unsigned int *val); extern int atvaudiodem_reg_write(unsigned int reg, unsigned int val); -extern int atvaudio_reg_read(unsigned int *val); -extern int atvaudio_reg_write(unsigned int val); +extern int atvaudio_ctrl_read(unsigned int *val); +extern int atvaudio_ctrl_write(unsigned int val); extern int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val); extern int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val); extern int amlatvdemod_periphs_reg_read(unsigned int reg, unsigned int *val); diff --git a/drivers/amlogic/atv_demod/atv_demod_afc.c b/drivers/amlogic/atv_demod/atv_demod_afc.c index b4647cd0a2f9..b2ffce0018b0 100644 --- a/drivers/amlogic/atv_demod/atv_demod_afc.c +++ b/drivers/amlogic/atv_demod/atv_demod_afc.c @@ -158,7 +158,8 @@ void atv_demod_afc_do_work(struct work_struct *work) return; } - if (!afc->lock || (afc->lock && !field_lock)) { + /* add "(lock && !field_lock)", horizontal synchronization test NG */ + if (!afc->lock/* || (afc->lock && !field_lock)*/) { afc->status = AFC_LOCK_STATUS_POST_UNLOCK; afc->pre_lock_cnt = 0; param->frequency -= afc->offset * 1000; diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index 67a2264364fa..ecb770297038 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -45,7 +45,7 @@ #include "atvauddemod_func.h" -#define AMLATVDEMOD_VER "V2.04" +#define AMLATVDEMOD_VER "V2.05" struct aml_atvdemod_device *amlatvdemod_devp; diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.c b/drivers/amlogic/atv_demod/atv_demod_monitor.c index 72c42ddbe2b6..e35e733bc6d9 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.c +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.c @@ -43,12 +43,18 @@ bool atvdemod_timer_en = true; static void atv_demod_monitor_do_work(struct work_struct *work) { + int vpll_lock = 0, line_lock = 0; struct atv_demod_monitor *monitor = container_of(work, struct atv_demod_monitor, work); if (!monitor->state) return; + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + if ((vpll_lock != 0) || (line_lock != 0)) + return; + if (atvdemod_mixer_tune_en) atvdemod_mixer_tune(); @@ -61,8 +67,7 @@ static void atv_demod_monitor_do_work(struct work_struct *work) if (audio_thd_en) audio_thd_det(); - if (atvaudio_det_outputmode_en && - (is_meson_txlx_cpu() || is_meson_txhd_cpu())) + if (atvaudio_det_outputmode_en) atvauddemod_set_outputmode(); if (atvdemod_det_nonstd_en) diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index 080db0f4c544..c352ea562fe8 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -49,6 +49,13 @@ unsigned int audio_thd_threshold2 = 0xf00; unsigned int audio_a2_auto = 1; unsigned int audio_a2_power_threshold = 0x1800; +static int last_nicam_lock = -1; +static int last_nicam_mono_flag = -1; +static int last_stereo_flag = -1; +static int last_dual_flag = -1; +static int last_sap_flag = -1; +static int last_mode = -1; + #undef pr_info #define pr_info(args...)\ do {\ @@ -885,7 +892,7 @@ void set_btsc_outputmode(uint32_t outmode) uint32_t reg_value = 0; uint32_t tmp_value = 0, tmp_value1 = 0; int stereo_flag = 0, sap_flag = 0; - static int last_stereo_flag = -1, last_sap_flag = -1, last_mode = -1; + /*static int last_stereo_flag = -1,last_sap_flag = -1,last_mode = -1;*/ update_btsc_mode(1, &stereo_flag, &sap_flag); @@ -996,7 +1003,7 @@ void set_a2_eiaj_outputmode(uint32_t outmode) uint32_t reg_value = 0; uint32_t tmp_value = 0; int stereo_flag = 0, dual_flag = 0; - static int last_stereo_flag = -1, last_dual_flag = -1, last_mode = -1; + /*static int last_stereo_flag = -1,last_dual_flag = -1, last_mode=-1;*/ update_a2_eiaj_mode(audio_a2_auto, &stereo_flag, &dual_flag); @@ -1089,8 +1096,8 @@ void set_nicam_outputmode(uint32_t outmode) uint32_t tmp_value = 0; int nicam_mono_flag = 0, nicam_stereo_flag = 0, nicam_dual_flag = 0; int nicam_lock = 0; - static int last_nicam_lock = -1, last_nicam_mono_flag = -1; - static int last_stereo_flag = -1, last_dual_flag = -1, last_mode = -1; + /*static int last_nicam_lock = -1, last_nicam_mono_flag = -1;*/ + /*static int last_stereo_flag = -1,last_dual_flag = -1, last_mode=-1;*/ update_nicam_mode(&nicam_lock, &nicam_mono_flag, &nicam_stereo_flag, &nicam_dual_flag); @@ -1106,11 +1113,6 @@ void set_nicam_outputmode(uint32_t outmode) */ reg_value = adec_rd_reg(ADDR_ADEC_CTRL); - pr_info("# pll lock: 0x%lx.\n", - atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x43)&0x01); - pr_info("# line lock: 0x%lx.\n", - atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f)&0x10); - pr_info("%s nicam_lock:%d, regval:0x%x, signal_mode:%d, outmode:%d\n", __func__, nicam_lock, reg_value, signal_audmode, outmode); @@ -1351,14 +1353,24 @@ void audio_thd_det(void) } } +void set_outputmode_status_init(void) +{ + last_nicam_lock = -1; + last_nicam_mono_flag = -1; + last_stereo_flag = -1; + last_dual_flag = -1; + last_sap_flag = -1; + last_mode = -1; +} + void set_output_left_right_exchange(unsigned int ch) { unsigned int read = 0; - atvaudio_reg_read(&read); + atvaudio_ctrl_read(&read); if ((read & (1 << 2)) != ((ch & 0x01) << 2)) - atvaudio_reg_write((read & ~(1 << 2)) | ((ch & 0x01) << 2)); + atvaudio_ctrl_write((read & ~(1 << 2)) | ((ch & 0x01) << 2)); } #endif /* __ATVAUDDEMOD_FUN_H */ diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.h b/drivers/amlogic/atv_demod/atvauddemod_func.h index fcdb246b7f2d..361b55639458 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.h +++ b/drivers/amlogic/atv_demod/atvauddemod_func.h @@ -39,6 +39,7 @@ void update_nicam_mode(int *nicam_flag, int *nicam_mono_flag, int *nicam_stereo_flag, int *nicam_dual_flag); void update_btsc_mode(int auto_en, int *stereo_flag, int *sap_flag); void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag); +void set_outputmode_status_init(void); void set_output_left_right_exchange(unsigned int ch); diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index b239adef0e69..fa5a08c0c806 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -40,6 +40,7 @@ unsigned int broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC; unsigned int aud_std = AUDIO_STANDARD_NICAM_DK; unsigned int aud_mode = AUDIO_OUTMODE_STEREO; bool aud_auto = true; +bool aud_reinit; unsigned long over_threshold = 0xffff; unsigned long input_amplitude = 0xffff; @@ -185,6 +186,8 @@ void power_on_receiver(void) void atv_dmd_misc(void) { + unsigned int reg = 0; + if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { pr_info("broad_std is SECAM_L, no need config misc\n"); return; @@ -271,7 +274,8 @@ void atv_dmd_misc(void) 0x18, 0x7ffff); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); - atvaudio_reg_write(0x0); + atvaudio_ctrl_read(®); + atvaudio_ctrl_write(reg & (~0x3)); audio_atv_ov_flag = 1; } else { atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, @@ -280,7 +284,8 @@ void atv_dmd_misc(void) 0x18, 0xc000); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); - atvaudio_reg_write(0x7); + atvaudio_ctrl_read(®); + atvaudio_ctrl_write(reg | 0x3); audio_atv_ov_flag = 0; } } @@ -1648,6 +1653,7 @@ int amlfmt_aud_standard(int broad_std) int std = 0; int nicam_lock = 0; uint32_t reg_value = 0; + int vpll_lock = 0, line_lock = 0; switch (broad_std) { case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: @@ -1657,6 +1663,9 @@ int amlfmt_aud_standard(int broad_std) adec_soft_reset(); msleep(audio_a2_delay); + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + /* maybe need wait */ reg_value = adec_rd_reg(CARRIER_MAG_REPORT); pr_info("\n%s 0x%x\n", __func__, (reg_value>>16)&0xffff); @@ -1687,10 +1696,10 @@ int amlfmt_aud_standard(int broad_std) adec_soft_reset(); msleep(audio_nicam_delay); /* need wait */ - pr_info("pll lock: 0x%lx.\n", - atv_dmd_rd_byte(0x06, 0x43) & 0x01); - pr_info("line lock: 0x%lx.\n", - atv_dmd_rd_byte(0x0f, 0x4f) & 0x10); + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); nicam_lock = (reg_value>>28)&1; pr_info("\n%s 0x%x\n", __func__, reg_value); @@ -1716,10 +1725,10 @@ int amlfmt_aud_standard(int broad_std) adec_soft_reset(); mdelay(audio_nicam_delay); /* need wait */ - pr_info("pll lock: 0x%lx.\n", - atv_dmd_rd_byte(0x06, 0x43) & 0x01); - pr_info("line lock: 0x%lx.\n", - atv_dmd_rd_byte(0x0f, 0x4f) & 0x10); + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); nicam_lock = (reg_value>>28)&1; pr_info("\n%s 0x%x\n", __func__, reg_value); @@ -1750,7 +1759,17 @@ int amlfmt_aud_standard(int broad_std) adec_soft_reset(); break; } - pr_err("%s detect aud std:%d\n", __func__, std); + + if ((vpll_lock == 0) && (line_lock == 0)) { + aud_reinit = false; + } else { + aud_reinit = true; + pr_err("pll lock: 0x%x, line lock: 0x%x.\n", + vpll_lock, line_lock); + } + + pr_err("%s detect aud std:%d, aud_reinit:%d.\n", __func__, + std, aud_reinit); return std; } @@ -1762,8 +1781,11 @@ int atvauddemod_init(void) if (aud_auto) aud_std = amlfmt_aud_standard(broad_std); - /* configure_adec(aud_std); */ - /* adec_soft_reset(); */ + else { + configure_adec(aud_std); + adec_soft_reset(); + } + set_outputmode_status_init(); set_outputmode(aud_std, aud_mode); } else { /* for non support adec */ @@ -1776,7 +1798,13 @@ int atvauddemod_init(void) void atvauddemod_set_outputmode(void) { - set_outputmode(aud_std, aud_mode); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()) { + if (aud_reinit) { + /* before maybe need check afc status */ + atvauddemod_init(); + } else + set_outputmode(aud_std, aud_mode); + } } int atvdemod_init(void) @@ -1950,6 +1978,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) int cur_std = ID_PAL_DK; bool secam_signal = false; bool ntsc_signal = false; + bool pal_signal = false; bool has_audio = false; #if 0 temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); @@ -1963,6 +1992,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + pal_signal = true; break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I: @@ -2065,7 +2095,8 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) } } - if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) { + if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M + && pal_signal) { /*the max except palm*/ carrier_power_average[final_id] = 0; final_id = 0; @@ -2093,6 +2124,12 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; break; } + /* pal signal and pal-m power max, + * so set to second max std. + */ + broad_std = broad_std_except_pal_m; + pr_err("%s:pal signal and pal-m power max, set broad_std:%d\n", + __func__, broad_std); } p->std = V4L2_COLOR_STD_PAL; @@ -2280,6 +2317,7 @@ void aml_audio_overmodulation(int enable) { unsigned long tmp_v = 0; unsigned long tmp_v1 = 0; + unsigned int reg = 0; u32 Broadcast_Standard = broad_std; if (enable && Broadcast_Standard == @@ -2297,8 +2335,11 @@ void aml_audio_overmodulation(int enable) 0x18, 0x7ffff); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); - atvaudio_reg_write(0x0); + atvaudio_ctrl_read(®); + atvaudio_ctrl_write(reg & (~0x3)); audio_atv_ov_flag = 1; + pr_info("tmp_v[0x%lx] > 0x10 && audio_atv_ov_flag == 0.\n", + tmp_v); } else if (tmp_v <= 0x10 && audio_atv_ov_flag == 1) { tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); tmp_v1 = (tmp_v1&0xffffff)|(0<<24); @@ -2309,8 +2350,11 @@ void aml_audio_overmodulation(int enable) 0x18, 0xc000); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); - atvaudio_reg_write(0x7); + atvaudio_ctrl_read(®); + atvaudio_ctrl_write(reg | 0x3); audio_atv_ov_flag = 0; + pr_info("tmp_v[0x%lx] <= 0x10 && audio_atv_ov_flag == 1.\n", + tmp_v); } } } From 536830727f436a802b15efa9d0c8c669106cdf64 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Fri, 21 Dec 2018 13:18:02 +0800 Subject: [PATCH 0580/1060] atv_demod: modify atv demod code [1/1] PD#SWPL-3469 Problem: 1.add mono audio only config. 2.fix offset -0.5M lose channel when scanning. 3.fix a2 audio mono mode detection threshold. 4.add audio detection when scanning. 5.Ver: V2.06. Solution: add mono audio only config Verify: verified by einstein Change-Id: I774d7aa42ffbfcbec58b9b21f05368c5166331c8 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_debug.c | 1 + drivers/amlogic/atv_demod/atv_demod_driver.c | 2 +- drivers/amlogic/atv_demod/atv_demod_ops.c | 41 +++--- drivers/amlogic/atv_demod/atv_demod_v4l2.c | 28 +++- drivers/amlogic/atv_demod/atv_demod_v4l2.h | 3 +- drivers/amlogic/atv_demod/atvauddemod_func.c | 118 +++++++++++++++- drivers/amlogic/atv_demod/atvdemod_func.c | 134 +++++++++++++++---- drivers/amlogic/atv_demod/atvdemod_func.h | 3 +- drivers/amlogic/atv_demod/aud_demod_reg.h | 5 + 9 files changed, 285 insertions(+), 50 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index 0a62ab442803..551ef3bbed3b 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -94,6 +94,7 @@ DEBUGFS_CREATE_NODE(audio_nicam_delay, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_a2_auto, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_a2_power_threshold, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(audio_a2_carrier_report, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_shift, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_lpr, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_atv_ov, 0640, dentry, u32)\ diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index ecb770297038..ab7a6411e5ef 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -45,7 +45,7 @@ #include "atvauddemod_func.h" -#define AMLATVDEMOD_VER "V2.05" +#define AMLATVDEMOD_VER "V2.06" struct aml_atvdemod_device *amlatvdemod_devp; diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index f5f5515a7eae..b243b71bf731 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -241,7 +241,7 @@ static void atv_demod_set_params(struct dvb_frontend *fe, (p->tuner_id == AM_TUNER_SI2151) || (p->tuner_id == AM_TUNER_SI2159) || (p->tuner_id == AM_TUNER_MXL661)) - reconfig = true; + reconfig = false; /* In general, demod does not need to be reconfigured * if parameters such as STD remain unchanged, @@ -262,7 +262,7 @@ static void atv_demod_set_params(struct dvb_frontend *fe, amlatvdemod_devp->tuner_id = p->tuner_id; atv_dmd_set_std(); - + atvdemod_init(!priv->scanning); } else atv_dmd_soft_reset(); @@ -531,7 +531,7 @@ static v4l2_std_id atvdemod_fe_tvin_fmt_to_v4l2_std(int fmt) static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, int auto_search_std, v4l2_std_id *video_fmt, - unsigned int *audio_fmt) + unsigned int *audio_fmt, unsigned int *soundsys) { struct dvb_frontend *fe = &v4l2_fe->fe; struct v4l2_analog_parameters *p = &v4l2_fe->params; @@ -675,10 +675,17 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, #endif } - pr_info("autodet audio mode %d, [%s][0x%x]\n", - broad_std, v4l2_std_to_str(audio), audio); - *audio_fmt = audio; + + /* for audio standard detection */ + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()) { + *soundsys = amlfmt_aud_standard(broad_std); + *soundsys = (*soundsys << 16) | 0x00FFFF; + } else + *soundsys = 0xFFFFFF; + + pr_info("autodet audio broad_std %d, [%s][0x%x] soundsys[0x%x]\n", + broad_std, v4l2_std_to_str(audio), audio, *soundsys); } static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, @@ -820,8 +827,9 @@ static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, static int atvdemod_fe_set_property(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp) { - struct dvb_frontend *fe = &amlatvdemod_devp->v4l2_fe.fe; + struct dvb_frontend *fe = &v4l2_fe->fe; struct atv_demod_priv *priv = fe->analog_demod_priv; + struct v4l2_analog_parameters *params = &v4l2_fe->params; pr_dbg("%s: cmd = 0x%x.\n", __func__, tvp->cmd); @@ -829,8 +837,10 @@ static int atvdemod_fe_set_property(struct v4l2_frontend *v4l2_fe, case V4L2_SOUND_SYS: /* aud_mode = tvp->data & 0xFF; */ amlatvdemod_devp->soundsys = tvp->data & 0xFF; - if (amlatvdemod_devp->soundsys != 0xFF) + if (amlatvdemod_devp->soundsys != 0xFF) { aud_mode = amlatvdemod_devp->soundsys; + params->soundsys = aud_mode; + } priv->sound_sys.output_mode = tvp->data & 0xFF; break; @@ -888,6 +898,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) int tuner_status_cnt_local = tuner_status_cnt; v4l2_std_id std_bk = 0; unsigned int audio = 0; + unsigned int soundsys = 0; int double_check_cnt = 1; int auto_search_std = 0; int search_count = 0; @@ -929,6 +940,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) */ if (p->std == 0) { p->std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M; + /* p->std = V4L2_COLOR_STD_PAL | V4L2_STD_DK; */ auto_search_std = 0x01; pr_dbg("[%s] user std is 0, so set it to NTSC | M.\n", __func__); @@ -1072,21 +1084,13 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) pr_dbg("[%s] freq: [%d] pll lock success\n", __func__, p->frequency); -#if 0 /* In get_pll_status has line_lock check.*/ - if (fee->tuner->drv->id == AM_TUNER_MXL661) { - fe->ops.analog_ops.get_atv_status(fe, - &atv_status); - if (atv_status.atv_lock) - usleep_range(30 * 1000, - 30 * 1000 + 100); - } -#endif + ret = atvdemod_fe_afc_closer(v4l2_fe, minafcfreq, maxafcfreq + ATV_AFC_500KHZ, 1); if (ret == 0) { atvdemod_fe_try_analog_format(v4l2_fe, auto_search_std, - &std_bk, &audio); + &std_bk, &audio, &soundsys); pr_info("[%s] freq:%d, std_bk:0x%x, audmode:0x%x, search OK.\n", __func__, p->frequency, @@ -1097,6 +1101,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) p->std = std_bk; /*avoid std unenable */ p->frequency -= 1; + p->soundsys = soundsys; std_bk = 0; audio = 0; } diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.c b/drivers/amlogic/atv_demod/atv_demod_v4l2.c index 4e228f6badcb..48447500c6a9 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.c +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.c @@ -494,7 +494,7 @@ static unsigned int v4l2_frontend_poll(struct file *filp, poll_wait(filp, &fepriv->events.wait_queue, pts); if (fepriv->events.eventw != fepriv->events.eventr) { - pr_dbg("%s: POLLIN | POLLRDNORM | POLLPRI.\n", __func__); + pr_dbg("%s: POLLIN | POLLRDNORM | POLLPRI.\n", __func__); return (POLLIN | POLLRDNORM | POLLPRI); } @@ -538,11 +538,13 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp, struct file *file) { int r = 0; + struct v4l2_analog_parameters *params = &v4l2_fe->params; v4l2_property_dump(v4l2_fe, true, tvp); switch (tvp->cmd) { case V4L2_TUNE: + v4l2_set_frontend(v4l2_fe, params); break; case V4L2_SOUND_SYS: case V4L2_SLOW_SEARCH_MODE: @@ -553,6 +555,20 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, return r; } break; + case V4L2_FREQUENCY: + params->frequency = tvp->data; + break; + case V4L2_STD: + /* std & 0xFF000000: color std */ + /* std & 0x00FFFFFF: audio std */ + if (tvp->data & 0xFF000000) + params->std = (tvp->data & 0xFF000000); + if (tvp->data & 0x00FFFFFF) { + params->audmode = params->std & 0xFFFFFF; + params->std = (tvp->data & 0xFF000000) + | (params->audmode); + } + break; default: return -EINVAL; } @@ -564,6 +580,7 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp, struct file *file) { int r = 0; + struct v4l2_analog_parameters *params = &v4l2_fe->params; switch (tvp->cmd) { case V4L2_SOUND_SYS: @@ -575,7 +592,14 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, return r; } break; - + case V4L2_FREQUENCY: + tvp->data = params->frequency; + break; + case V4L2_STD: + /* std & 0xFF000000: color std */ + /* std & 0x00FFFFFF: audio std */ + tvp->data = params->std; + break; default: pr_dbg("%s: V4L2 property %d doesn't exist\n", __func__, tvp->cmd); diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.h b/drivers/amlogic/atv_demod/atv_demod_v4l2.h index 0683c94878ec..ba31acc6287e 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.h +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.h @@ -92,7 +92,8 @@ #define V4L2_TUNE 1 #define V4L2_SOUND_SYS 2 #define V4L2_SLOW_SEARCH_MODE 3 - +#define V4L2_FREQUENCY 4 +#define V4L2_STD 5 struct v4l2_frontend; diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index c352ea562fe8..10d5dd923509 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -48,6 +48,7 @@ unsigned int audio_thd_threshold2 = 0xf00; unsigned int audio_a2_auto = 1; unsigned int audio_a2_power_threshold = 0x1800; +unsigned int audio_a2_carrier_report = 0x600; static int last_nicam_lock = -1; static int last_nicam_mono_flag = -1; @@ -717,6 +718,101 @@ void set_nicam_l(void) aa = (int)((FCLK-5.85e6)/FCLK*1024.0*1024.0*16.0); adec_wr_reg(0x110, aa); } + +void set_mono_m(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x2); + + set_filter(filter_50k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_50k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(4.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + set_lpf15k(); + set_deem(0); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + adec_wr_reg((ADDR_SEL_CTRL), 0x1000); + + set_lpf15k(); + set_deem(0); +} + +void set_mono_dk(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0xa); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + +void set_mono_i(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x7); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.0e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + +void set_mono_bg(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x8); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(5.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + +void set_mono_l(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x9); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + static void set_standard(uint32_t standard) { pr_info("\n<<<<<<<<<<<<<<< start configure register\n"); @@ -766,6 +862,26 @@ static void set_standard(uint32_t standard) pr_info("<<<<<<<<<<<<<<< Set NICAM L and Test\n"); set_nicam_l(); break; + case AUDIO_STANDARD_MONO_M: + pr_info("<<<<<<<<<<<<<<< Set mono M and Test\n"); + set_mono_m(); + break; + case AUDIO_STANDARD_MONO_DK: + pr_info("<<<<<<<<<<<<<<< Set mono DK and Test\n"); + set_mono_dk(); + break; + case AUDIO_STANDARD_MONO_I: + pr_info("<<<<<<<<<<<<<<< Set mono I and Test\n"); + set_mono_i(); + break; + case AUDIO_STANDARD_MONO_BG: + pr_info("<<<<<<<<<<<<<<< Set mono BG and Test\n"); + set_mono_bg(); + break; + case AUDIO_STANDARD_MONO_L: + pr_info("<<<<<<<<<<<<<<< Set mono L and Test\n"); + set_mono_l(); + break; } pr_info("\n<<<<<<<<<<<<<<< configure register finished\n"); @@ -789,7 +905,7 @@ void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag) if (auto_en) { reg_value = adec_rd_reg(CARRIER_MAG_REPORT); - if (((reg_value >> 16) & 0xffff) < 0x400) { + if (((reg_value >> 16) & 0xffff) < audio_a2_carrier_report) { *stereo_flag = 0; *dual_flag = 0; } else { diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index fa5a08c0c806..1139cc447bf7 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -41,6 +41,7 @@ unsigned int aud_std = AUDIO_STANDARD_NICAM_DK; unsigned int aud_mode = AUDIO_OUTMODE_STEREO; bool aud_auto = true; bool aud_reinit; +bool aud_mono_only; unsigned long over_threshold = 0xffff; unsigned long input_amplitude = 0xffff; @@ -139,6 +140,9 @@ void atv_dmd_soft_reset(void) atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x0); atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x1); atv_dmd_wr_long(0x1d, 0x0, 0x1037);/* enable dac */ + + /* for +-0.5M scanning lose */ + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc010301); } void atv_dmd_input_clk_32m(void) @@ -1658,6 +1662,14 @@ int amlfmt_aud_standard(int broad_std) switch (broad_std) { case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_M; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_A2_K; configure_adec(std); adec_soft_reset(); @@ -1668,7 +1680,8 @@ int amlfmt_aud_standard(int broad_std) /* maybe need wait */ reg_value = adec_rd_reg(CARRIER_MAG_REPORT); - pr_info("\n%s 0x%x\n", __func__, (reg_value>>16)&0xffff); + pr_info("\n%s CARRIER_MAG_REPORT: 0x%x\n", + __func__, (reg_value >> 16) & 0xffff); if (((reg_value>>16)&0xffff) > audio_a2_threshold) { std = AUDIO_STANDARD_A2_K; if (amlatvdemod_devp->soundsys == 0xFF) @@ -1686,11 +1699,27 @@ int amlfmt_aud_standard(int broad_std) } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_M; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_EIAJ; configure_adec(std); adec_soft_reset(); break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_BG; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_BG; configure_adec(std); adec_soft_reset(); @@ -1701,8 +1730,9 @@ int amlfmt_aud_standard(int broad_std) retrieve_vpll_carrier_line_lock(&line_lock); reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); - nicam_lock = (reg_value>>28)&1; - pr_info("\n%s 0x%x\n", __func__, reg_value); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); if (nicam_lock) { std = AUDIO_STANDARD_NICAM_BG; if (amlatvdemod_devp->soundsys == 0xFF) @@ -1720,6 +1750,14 @@ int amlfmt_aud_standard(int broad_std) } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_DK; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_DK; configure_adec(std); adec_soft_reset(); @@ -1730,8 +1768,9 @@ int amlfmt_aud_standard(int broad_std) retrieve_vpll_carrier_line_lock(&line_lock); reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); - nicam_lock = (reg_value>>28)&1; - pr_info("\n%s 0x%x\n", __func__, reg_value); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); if (nicam_lock) { std = AUDIO_STANDARD_NICAM_DK; if (amlatvdemod_devp->soundsys == 0xFF) @@ -1749,14 +1788,74 @@ int amlfmt_aud_standard(int broad_std) } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_I; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_I; configure_adec(std); adec_soft_reset(); + msleep(audio_nicam_delay); + /* need wait */ + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); + if (nicam_lock) { + std = AUDIO_STANDARD_NICAM_I; + if (amlatvdemod_devp->soundsys == 0xFF) + aud_mode = AUDIO_OUTMODE_NICAM_STEREO; + else + aud_mode = amlatvdemod_devp->soundsys; + } else { + std = AUDIO_STANDARD_MONO_I; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_L; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_L; configure_adec(std); adec_soft_reset(); + msleep(audio_nicam_delay); + /* need wait */ + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); + if (nicam_lock) { + std = AUDIO_STANDARD_NICAM_L; + if (amlatvdemod_devp->soundsys == 0xFF) + aud_mode = AUDIO_OUTMODE_NICAM_STEREO; + else + aud_mode = amlatvdemod_devp->soundsys; + } else { + std = AUDIO_STANDARD_MONO_L; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + } break; } @@ -1807,7 +1906,7 @@ void atvauddemod_set_outputmode(void) } } -int atvdemod_init(void) +int atvdemod_init(bool on) { /* 1.set system clock when atv enter*/ @@ -1818,8 +1917,8 @@ int atvdemod_init(void) pr_dbg("%s do atv_dmd_misc ...\n", __func__); atv_dmd_misc(); - if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || - broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) + if (on && (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || + broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC)) atv_dmd_ring_filter(true); else atv_dmd_ring_filter(false); @@ -1955,9 +2054,6 @@ void atv_dmd_set_std(void) pr_dbg("[%s] set if_freq %d, if_inv %d.\n", __func__, amlatvdemod_devp->if_freq, amlatvdemod_devp->if_inv); - - if (atvdemod_init()) - pr_info("[%s]: atv restart error.\n", __func__); } int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) @@ -1980,11 +2076,6 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) bool ntsc_signal = false; bool pal_signal = false; bool has_audio = false; -#if 0 - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80;/* 0x40 */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); -#endif switch (broad_std) { case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: @@ -2002,15 +2093,6 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) ntsc_signal = true; broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; break; -#if 0 /* ntsc will try other audio */ - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M; - atvdemod_init(); - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data & (~0x80); /* 0xbf; */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ - return broad_std; -#endif case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2: case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3: @@ -2020,7 +2102,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; } else { broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L; - atvdemod_init(); + atvdemod_init(false); temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); diff --git a/drivers/amlogic/atv_demod/atvdemod_func.h b/drivers/amlogic/atv_demod/atvdemod_func.h index 30ef9b8f9ef8..57149c934722 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.h +++ b/drivers/amlogic/atv_demod/atvdemod_func.h @@ -70,7 +70,7 @@ extern void configure_receiver(int Broadcast_Standard, int Tuner_Input_IF_inverted, int GDE_Curve, int sound_format); extern int atvdemod_clk_init(void); -extern int atvdemod_init(void); +extern int atvdemod_init(bool on); extern void atvdemod_uninit(void); extern void atv_dmd_set_std(void); extern void retrieve_adc_power(int *adc_level); @@ -204,6 +204,7 @@ extern void retrieve_frequency_offset(int *freq_offset); extern void retrieve_field_lock(int *lock); extern void set_atvdemod_scan_mode(int val); extern int atvauddemod_init(void); +extern int amlfmt_aud_standard(int broad_std); extern void atvauddemod_set_outputmode(void); /*from amldemod/amlfrontend.c*/ diff --git a/drivers/amlogic/atv_demod/aud_demod_reg.h b/drivers/amlogic/atv_demod/aud_demod_reg.h index cacc8ca00962..4f9547ee1635 100644 --- a/drivers/amlogic/atv_demod/aud_demod_reg.h +++ b/drivers/amlogic/atv_demod/aud_demod_reg.h @@ -318,6 +318,11 @@ #define AUDIO_STANDARD_INDIAN 0x0F #define AUDIO_STANDARD_BTSC_SA 0x10 #define AUDIO_STANDARD_MONO_ONLY 0x11 +#define AUDIO_STANDARD_MONO_BG 0x12 +#define AUDIO_STANDARD_MONO_DK 0x13 +#define AUDIO_STANDARD_MONO_I 0x14 +#define AUDIO_STANDARD_MONO_M 0x15 +#define AUDIO_STANDARD_MONO_L 0x16 #define AUDIO_OUTMODE_MONO 0 #define AUDIO_OUTMODE_STEREO 1 From 590cc2a22132885532da5a427a4d839c63767a36 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Mon, 25 Feb 2019 10:10:27 +0800 Subject: [PATCH 0581/1060] atv_demod: Add audio carrier offset detect [1/1] PD#TV-2564 Problem: Torture room teset report SND0810 sound carrier deviation Solution: Add audio carrier offset detect Verify: verified by x301 Change-Id: I2d715891fb268452f95e05f998864e9b7321ff38 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_debug.c | 1 + drivers/amlogic/atv_demod/atv_demod_monitor.c | 4 ++ drivers/amlogic/atv_demod/atvauddemod_func.c | 38 ++++++++++++++++++- drivers/amlogic/atv_demod/atvauddemod_func.h | 1 + 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index 551ef3bbed3b..6535e0910880 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -57,6 +57,7 @@ DEBUGFS_CREATE_NODE(over_threshold, 0640, dentry, u64)\ DEBUGFS_CREATE_NODE(input_amplitude, 0640, dentry, u64)\ DEBUGFS_CREATE_NODE(atvaudio_det_outputmode_en, 0640, dentry, bool)\ + DEBUGFS_CREATE_NODE(audio_carrier_offset_det_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(audio_det_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(non_std_en, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(atvdemod_det_nonstd_en, 0640, dentry, bool)\ diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.c b/drivers/amlogic/atv_demod/atv_demod_monitor.c index e35e733bc6d9..54c867c67436 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.c +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.c @@ -34,6 +34,7 @@ bool atvdemod_det_snr_en = true; bool audio_thd_en; bool atvdemod_det_nonstd_en; bool atvaudio_det_outputmode_en = true; +bool audio_carrier_offset_det_en; unsigned int atvdemod_timer_delay = 100; /* 1s */ unsigned int atvdemod_timer_delay2 = 10; /* 100ms */ @@ -70,6 +71,9 @@ static void atv_demod_monitor_do_work(struct work_struct *work) if (atvaudio_det_outputmode_en) atvauddemod_set_outputmode(); + if (audio_carrier_offset_det_en) + audio_carrier_offset_det(); + if (atvdemod_det_nonstd_en) atv_dmd_non_std_set(true); } diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index 10d5dd923509..9fea4fd1613e 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -60,7 +60,12 @@ static int last_mode = -1; #undef pr_info #define pr_info(args...)\ do {\ - if (ademod_debug_en)\ + if (ademod_debug_en & 0x1)\ + printk(args);\ + } while (0) +#define pr_carr(args...)\ + do {\ + if (ademod_debug_en & 0x2)\ printk(args);\ } while (0) #undef pr_dbg @@ -1469,6 +1474,37 @@ void audio_thd_det(void) } } +void audio_carrier_offset_det(void) +{ + unsigned int carrier_freq = 0, report = 0; + int threshold = 0; + + report = adec_rd_reg(DC_REPORT); + carrier_freq = adec_rd_reg(ADDR_DDC_FREQ0); + + pr_carr("\n\nreport: 0x%x.\n", report); + pr_carr("read carrier_freq: 0x%x.\n", carrier_freq); + report = report & 0xFFFF; + + if (report > (1 << 15)) + threshold = report - (1 << 16); + else + threshold = report; + + threshold = threshold >> 8; + pr_carr("threshold: %d.\n", threshold); + + if (threshold > 30) { + carrier_freq = carrier_freq - 0x100; + adec_wr_reg(ADDR_DDC_FREQ0, carrier_freq); + } else if (threshold < -30) { + carrier_freq = carrier_freq + 0x100; + adec_wr_reg(ADDR_DDC_FREQ0, carrier_freq); + } + + pr_carr("write carrier_freq: 0x%x.\n", carrier_freq); +} + void set_outputmode_status_init(void) { last_nicam_lock = -1; diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.h b/drivers/amlogic/atv_demod/atvauddemod_func.h index 361b55639458..c71037ffd6cd 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.h +++ b/drivers/amlogic/atv_demod/atvauddemod_func.h @@ -32,6 +32,7 @@ void configure_adec(int Audio_mode); void adec_soft_reset(void); void audio_thd_init(void); void audio_thd_det(void); +void audio_carrier_offset_det(void); void set_nicam_outputmode(uint32_t outmode); void set_a2_eiaj_outputmode(uint32_t outmode); void set_btsc_outputmode(uint32_t outmode); From 9ddf9c182ef34cbc1be1e2aa2e1bf4b8f3afd36b Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Thu, 28 Feb 2019 14:43:14 +0800 Subject: [PATCH 0582/1060] atv_demod: Fix non standard for analog signal [1/1] PD#TV-1549, PD#TV-2829, PD#TV-2830 Problem: Fix non standard for analog signal. Solution: 1.Add non standard config 3 for analog signal. 2.Fix non standard default value. 3.Fix audio control register an bits. 4.After correcting the frequency offset success, reset tuner to prevent audio from identifying errors. Verify: verified by x301 Change-Id: I65335dbe9ce9dc66d4ccaae3c1ff591660790616 Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_access.c | 12 ++- drivers/amlogic/atv_demod/atv_demod_driver.c | 4 +- drivers/amlogic/atv_demod/atv_demod_ops.c | 20 +++++ drivers/amlogic/atv_demod/atvauddemod_func.c | 11 ++- drivers/amlogic/atv_demod/atvdemod_func.c | 89 ++++++++++++-------- 5 files changed, 96 insertions(+), 40 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_access.c b/drivers/amlogic/atv_demod/atv_demod_access.c index 177700edcfbd..9f08b56d9dbe 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.c +++ b/drivers/amlogic/atv_demod/atv_demod_access.c @@ -109,10 +109,14 @@ int atvaudiodem_reg_write(unsigned int reg, unsigned int val) int atvaudio_ctrl_read(unsigned int *val) { - /* only 0xffd0d340 read */ + /* only [0xffd0d340](others)/[0xff60074c](tl1) write */ + /* others: */ /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ /* bit1: Din5, 0 = atv_demod, 1 = adec */ /* bit2: L/R swap for adec audio data */ + /* TL1: */ + /* bit19: L/R swap for adec audio data */ + /* bit20: I2s select in_src, 0 = atv_demod, 1 = adec */ if (amlatvdemod_devp->audio_reg_base) *val = readl(amlatvdemod_devp->audio_reg_base); @@ -121,10 +125,14 @@ int atvaudio_ctrl_read(unsigned int *val) int atvaudio_ctrl_write(unsigned int val) { - /* only 0xffd0d340 write */ + /* only 0xffd0d340(others)/0xff60074c(tl1) write */ + /* others: */ /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ /* bit1: Din5, 0 = atv_demod, 1 = adec */ /* bit2: L/R swap for adec audio data */ + /* TL1: */ + /* bit19: L/R swap for adec audio data */ + /* bit20: I2s select in_src, 0 = atv_demod, 1 = adec */ if (amlatvdemod_devp->audio_reg_base) writel(val, amlatvdemod_devp->audio_reg_base); diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index ab7a6411e5ef..40518d3dc435 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -45,7 +45,7 @@ #include "atvauddemod_func.h" -#define AMLATVDEMOD_VER "V2.06" +#define AMLATVDEMOD_VER "V2.07" struct aml_atvdemod_device *amlatvdemod_devp; @@ -624,7 +624,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) pr_info("audio_reg_base = 0x%p.\n", dev->audio_reg_base); } else if (is_meson_tl1_cpu()) { - dev->audio_reg_base = ioremap(round_down(0xff600340, 0x3), 4); + dev->audio_reg_base = ioremap(round_down(0xff60074c, 0x3), 4); pr_info("audio_reg_base = 0x%p.\n", dev->audio_reg_base); } diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index b243b71bf731..53f0afc7a153 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -815,6 +815,26 @@ static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, } } + /* After correcting the frequency offset success, + * need to set up tuner. + */ + if (fe->ops.tuner_ops.set_analog_params) { + params.frequency = p->frequency; + params.mode = p->afc_range; + params.audmode = p->audmode; + params.std = p->std; + fe->ops.tuner_ops.set_analog_params(fe, + ¶ms); + + if (tuner_id == AM_TUNER_SI2151 || + tuner_id == AM_TUNER_SI2159 || + tuner_id == AM_TUNER_R840 || + tuner_id == AM_TUNER_R842) + usleep_range(10 * 1000, 10 * 1000 + 100); + else if (tuner_id == AM_TUNER_MXL661) + usleep_range(30 * 1000, 30 * 1000 + 100); + } + freq_success = p->frequency; ktime_get_ts(&success_time); pr_dbg("[%s] get afc %d khz done, freq %u.\n", diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index 9fea4fd1613e..ed25bdf36636 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -1521,8 +1521,15 @@ void set_output_left_right_exchange(unsigned int ch) atvaudio_ctrl_read(&read); - if ((read & (1 << 2)) != ((ch & 0x01) << 2)) - atvaudio_ctrl_write((read & ~(1 << 2)) | ((ch & 0x01) << 2)); + if (is_meson_tl1_cpu()) { /* bit[19] */ + if ((read & (1 << 19)) != ((ch & 0x01) << 19)) + atvaudio_ctrl_write((read & ~(1 << 19)) | + ((ch & 0x01) << 19)); + } else { /* bit[2] */ + if ((read & (1 << 2)) != ((ch & 0x01) << 2)) + atvaudio_ctrl_write((read & ~(1 << 2)) | + ((ch & 0x01) << 2)); + } } #endif /* __ATVAUDDEMOD_FUN_H */ diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 1139cc447bf7..6d4a8c3e8abd 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -59,7 +59,7 @@ int sum2_thd_h; int sum2_thd_l = 0x7fffffff; unsigned int atv_video_gain; -unsigned int carrier_amplif_val = 0xc030901; +unsigned int carrier_amplif_val = 0xc010301;/*0xc030901;*/ unsigned int extra_input_fil_val = 0x1030501; bool aud_dmd_jilinTV; unsigned int if_freq = 4250000; /*PAL-DK:3250000;NTSC-M:4250000*/ @@ -140,9 +140,6 @@ void atv_dmd_soft_reset(void) atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x0); atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x1); atv_dmd_wr_long(0x1d, 0x0, 0x1037);/* enable dac */ - - /* for +-0.5M scanning lose */ - atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc010301); } void atv_dmd_input_clk_32m(void) @@ -200,12 +197,13 @@ void atv_dmd_misc(void) atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x38); /*zhuangwei*/ /*cpu.write_byte(8'h1A,8'h0E,8'h06);//zhuangwei*/ /*cpu.write_byte(8'h19,8'h01,8'h7f);//zhuangwei*/ - atv_dmd_wr_byte(0x0f, 0x45, 0x90); /*zhuangwei*/ + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x45, 0x90); /*zhuangwei*/ - atv_dmd_wr_long(0x0f, 0x44, 0x5c8808c1);/*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x5c8808c1);/*zhuangwei*/ if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || amlatvdemod_devp->tuner_id == AM_TUNER_R842) { - atv_dmd_wr_long(0x0f, 0x3c, reg_23cf);/*zhuangwei*/ + /*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x3c, reg_23cf); /*guanzhong@20150804a*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1); if (is_meson_txhd_cpu()) { @@ -226,47 +224,58 @@ void atv_dmd_misc(void) /*dezhi@20150610a 0x1a maybe better?!*/ /* atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0x19); */ } else { - atv_dmd_wr_long(0x0f, 0x3c, 0x88188832);/*zhuangwei*/ + /*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x3c, 0x88188832); atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46170200); } if (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661) { - atv_dmd_wr_long(0x0c, 0x04, 0xbffa0000) ;/*test in sky*/ - atv_dmd_wr_long(0x0c, 0x00, 0x6f4000);/*test in sky*/ + /*test in sky*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xbffa0000); + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x00, 0x6f4000); /*guanzhong@20151013 fix nonstd def is:0x0c010301;0x0c020601*/ - atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c030901); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc030901); } else { /*zhuangwei 0xdafa0000*/ - atv_dmd_wr_long(0x0c, 0x04, 0xc8fa0000); - atv_dmd_wr_long(0x0c, 0x00, 0x554000);/*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xc8fa0000); + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x00, 0x554000); } - atv_dmd_wr_long(0x19, 0x04, 0xdafa0000);/*zhuangwei*/ - atv_dmd_wr_long(0x19, 0x00, 0x4a4000);/*zhuangwei*/ - /*atv_dmd_wr_byte(0x0c,0x01,0x28);//pwd-out gain*/ - /*atv_dmd_wr_byte(0x0c,0x04,0xc0);//pwd-out offset*/ + /*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS_24M, 0x04, 0xdafa0000); + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS_24M, 0x00, 0x4a4000); + /*atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x01, 0x28);//pwd-out gain*/ + /*atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xc0);//pwd-out offset*/ aml_audio_valume_gain_set(audio_gain_val); /* 20160121 fix audio demodulation over */ - atv_dmd_wr_long(0x09, 0x00, 0x1030501); - atv_dmd_wr_long(0x09, 0x04, 0x1900000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1030501); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x04, 0x1900000); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x367C0831); if (aud_dmd_jilinTV) - atv_dmd_wr_long(0x09, 0x00, 0x2030503); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x2030503); if (non_std_en == 1) { - atv_dmd_wr_long(0x09, 0x00, 0x2030503); - atv_dmd_wr_long(0x0f, 0x44, 0x7c8808c1); - atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c010801); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x2030503); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x7c8808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc010801); } else if (non_std_en == 2) { /* fix vsync signal is too weak */ - atv_dmd_wr_long(0x09, 0x00, 0x1030501); - atv_dmd_wr_long(0x0f, 0x44, 0x8c0808c1); - atv_dmd_wr_long(0x0f, 0x0c, 0x387c0831); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1030501); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x8c0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x387c0831); atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc030901); + } else if (non_std_en == 3) { /* for Hisence */ + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1030501); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x8c0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x387c0831); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc020901); } else { - atv_dmd_wr_long(0x09, 0x00, extra_input_fil_val); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, + extra_input_fil_val); if (atv_video_gain) - atv_dmd_wr_long(0x0f, 0x44, atv_video_gain); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, + atv_video_gain); else - atv_dmd_wr_long(0x0f, 0x44, 0xfc0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0xfc0808c1); atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, carrier_amplif_val); } @@ -279,7 +288,10 @@ void atv_dmd_misc(void) atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); atvaudio_ctrl_read(®); - atvaudio_ctrl_write(reg & (~0x3)); + if (is_meson_tl1_cpu()) + atvaudio_ctrl_write(reg & (~0x100000));/* bit20 */ + else + atvaudio_ctrl_write(reg & (~0x3));/* bit[1-0] */ audio_atv_ov_flag = 1; } else { atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, @@ -289,7 +301,10 @@ void atv_dmd_misc(void) atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); atvaudio_ctrl_read(®); - atvaudio_ctrl_write(reg | 0x3); + if (is_meson_tl1_cpu()) + atvaudio_ctrl_write(reg | 0x100000);/* bit20 */ + else + atvaudio_ctrl_write(reg | 0x3);/* bit[1-0] */ audio_atv_ov_flag = 0; } } @@ -2418,8 +2433,11 @@ void aml_audio_overmodulation(int enable) atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); atvaudio_ctrl_read(®); - atvaudio_ctrl_write(reg & (~0x3)); - audio_atv_ov_flag = 1; + if (is_meson_tl1_cpu()) /* bit20 */ + atvaudio_ctrl_write(reg & (~0x100000)); + else + atvaudio_ctrl_write(reg & (~0x3));/* bit[1-0] */ + /* audio_atv_ov_flag = 1;*/ /* Enter and hold */ pr_info("tmp_v[0x%lx] > 0x10 && audio_atv_ov_flag == 0.\n", tmp_v); } else if (tmp_v <= 0x10 && audio_atv_ov_flag == 1) { @@ -2433,7 +2451,10 @@ void aml_audio_overmodulation(int enable) atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); atvaudio_ctrl_read(®); - atvaudio_ctrl_write(reg | 0x3); + if (is_meson_tl1_cpu()) /* bit20 */ + atvaudio_ctrl_write(reg | 0x100000); + else + atvaudio_ctrl_write(reg | 0x3);/* bit[1-0] */ audio_atv_ov_flag = 0; pr_info("tmp_v[0x%lx] <= 0x10 && audio_atv_ov_flag == 1.\n", tmp_v); From f5a2657d70a1ba9fa607ceebc94a174025badcdf Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Mon, 11 Mar 2019 14:00:31 +0800 Subject: [PATCH 0583/1060] atv_demod: Fix ATV audio output noise when switching channels to play [1/1] PD#SWPL-2297, PD#SWPL-5450, PD#TV-2311 Problem: Fix ATV audio output noise when switching channels to play. Solution: 1.Add the judgment of SNR to prevent the weak signal from entering the OV mode. 2.Wait for the signal to be completely stable before OV detection. 3.OV detection is turned off by default, and will be turned on again when non-standard signals are encountered. 4.The OV detection moves from afc timer to monitor. 5.Optimize detection of A2/FM. 6.atv demod ver: V2.08. Verify: verified by x301 Change-Id: I3064230472ce51e1192a2d08ef6cc6f4ba10abaa Signed-off-by: nengwen.chen --- drivers/amlogic/atv_demod/atv_demod_afc.c | 8 ----- drivers/amlogic/atv_demod/atv_demod_debug.c | 4 +++ drivers/amlogic/atv_demod/atv_demod_driver.c | 2 +- drivers/amlogic/atv_demod/atv_demod_monitor.c | 14 +++++++- drivers/amlogic/atv_demod/atv_demod_monitor.h | 2 ++ drivers/amlogic/atv_demod/atvauddemod_func.c | 34 ++++++++++++++----- drivers/amlogic/atv_demod/atvdemod_func.c | 5 +++ 7 files changed, 50 insertions(+), 19 deletions(-) diff --git a/drivers/amlogic/atv_demod/atv_demod_afc.c b/drivers/amlogic/atv_demod/atv_demod_afc.c index b2ffce0018b0..3cf5d956c8fa 100644 --- a/drivers/amlogic/atv_demod/atv_demod_afc.c +++ b/drivers/amlogic/atv_demod/atv_demod_afc.c @@ -107,7 +107,6 @@ void atv_demod_afc_do_work(struct work_struct *work) int freq_offset = 100; int tmp = 0; int field_lock = 0; - static int audio_overmodul; if (afc->state == false) return; @@ -125,13 +124,6 @@ void atv_demod_afc_do_work(struct work_struct *work) afc->pre_step = 0; - if (afc->lock) { - if (0 == ((audio_overmodul++) % 10)) { - aml_audio_overmodulation(1); - audio_overmodul = 0; - } - } - retrieve_frequency_offset(&freq_offset); if (++(afc->wave_cnt) <= afc_wave_cnt) {/*40ms*/ diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index 6535e0910880..284eeb838218 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -87,6 +87,7 @@ DEBUGFS_CREATE_NODE(atvdemod_timer_delay2, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(atvdemod_mixer_tune_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(atvdemod_overmodulated_en, 0640, dentry, bool)\ + DEBUGFS_CREATE_NODE(atv_audio_overmodulated_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(audio_thd_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(pwm_kp, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_val, 0640, dentry, u32)\ @@ -116,6 +117,7 @@ DEBUGFS_CREATE_FILE(sum2_thd_h, 0640, dentry, fops, int)\ DEBUGFS_CREATE_FILE(sum2_thd_l, 0640, dentry, fops, int)\ DEBUGFS_CREATE_FILE(afc_default, 0640, dentry, fops, int)\ + DEBUGFS_CREATE_FILE(snr_threshold, 0640, dentry, fops, int)\ } @@ -131,6 +133,7 @@ DEBUGFS_DENTRY_DEFINE(sum1_thd_l); DEBUGFS_DENTRY_DEFINE(sum2_thd_h); DEBUGFS_DENTRY_DEFINE(sum2_thd_l); DEBUGFS_DENTRY_DEFINE(afc_default); +DEBUGFS_DENTRY_DEFINE(snr_threshold); struct dentry_value *debugfs_dentry[] = { DEBUGFS_DENTRY_VALUE(non_std_thld_4c_h), @@ -142,6 +145,7 @@ struct dentry_value *debugfs_dentry[] = { DEBUGFS_DENTRY_VALUE(sum2_thd_h), DEBUGFS_DENTRY_VALUE(sum2_thd_l), DEBUGFS_DENTRY_VALUE(afc_default), + DEBUGFS_DENTRY_VALUE(snr_threshold), }; static int debugfs_open(struct inode *node, struct file *file) diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index 40518d3dc435..e5dd53434193 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -45,7 +45,7 @@ #include "atvauddemod_func.h" -#define AMLATVDEMOD_VER "V2.07" +#define AMLATVDEMOD_VER "V2.08" struct aml_atvdemod_device *amlatvdemod_devp; diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.c b/drivers/amlogic/atv_demod/atv_demod_monitor.c index 54c867c67436..726b019a45f3 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.c +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.c @@ -29,6 +29,7 @@ static DEFINE_MUTEX(monitor_mutex); bool atvdemod_mixer_tune_en; bool atvdemod_overmodulated_en; +bool atv_audio_overmodulated_en; bool audio_det_en; bool atvdemod_det_snr_en = true; bool audio_thd_en; @@ -53,8 +54,12 @@ static void atv_demod_monitor_do_work(struct work_struct *work) retrieve_vpll_carrier_lock(&vpll_lock); retrieve_vpll_carrier_line_lock(&line_lock); - if ((vpll_lock != 0) || (line_lock != 0)) + if ((vpll_lock != 0) || (line_lock != 0)) { + monitor->lock_cnt = 0; return; + } + + monitor->lock_cnt++; if (atvdemod_mixer_tune_en) atvdemod_mixer_tune(); @@ -62,6 +67,11 @@ static void atv_demod_monitor_do_work(struct work_struct *work) if (atvdemod_overmodulated_en) atvdemod_video_overmodulated(); + if (atv_audio_overmodulated_en) { + if (monitor->lock_cnt % 10 == 0) + aml_audio_overmodulation(1); + } + if (atvdemod_det_snr_en) atvdemod_det_snr_serice(); @@ -112,6 +122,7 @@ static void atv_demod_monitor_enable(struct atv_demod_monitor *monitor) ATVDEMOD_INTERVAL * atvdemod_timer_delay; add_timer(&monitor->timer); monitor->state = true; + monitor->lock_cnt = 0; } mutex_unlock(&monitor->mtx); @@ -143,6 +154,7 @@ void atv_demod_monitor_init(struct atv_demod_monitor *monitor) monitor->state = false; monitor->lock = false; + monitor->lock_cnt = 0; monitor->disable = atv_demod_monitor_disable; monitor->enable = atv_demod_monitor_enable; diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.h b/drivers/amlogic/atv_demod/atv_demod_monitor.h index b9c1e6ad3b88..95c5a2b59b31 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.h +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.h @@ -34,6 +34,8 @@ struct atv_demod_monitor { bool state; bool lock; + unsigned int lock_cnt; + void (*disable)(struct atv_demod_monitor *monitor); void (*enable)(struct atv_demod_monitor *monitor); }; diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index ed25bdf36636..889fc4469609 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -48,7 +48,7 @@ unsigned int audio_thd_threshold2 = 0xf00; unsigned int audio_a2_auto = 1; unsigned int audio_a2_power_threshold = 0x1800; -unsigned int audio_a2_carrier_report = 0x600; +unsigned int audio_a2_carrier_report = 0xc00; static int last_nicam_lock = -1; static int last_nicam_mono_flag = -1; @@ -392,7 +392,9 @@ void set_a2k(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); adec_wr_reg((ADDR_SEL_CTRL), 0x1000); } @@ -428,7 +430,9 @@ void set_a2g(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2bg(void) @@ -462,7 +466,9 @@ void set_a2bg(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2dk1(void) @@ -496,7 +502,9 @@ void set_a2dk1(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2dk2(void) @@ -530,7 +538,9 @@ void set_a2dk2(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2dk3(void) @@ -564,7 +574,9 @@ void set_a2dk3(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_eiaj(void) @@ -903,13 +915,15 @@ void update_car_power_measure(int *sc1_power, int *sc2_power) void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag) { - uint32_t reg_value; - uint32_t stereo_power, dual_power; + uint32_t reg_value = 0; + uint32_t stereo_power = 0, dual_power = 0; msleep(a2_detect_delay); if (auto_en) { reg_value = adec_rd_reg(CARRIER_MAG_REPORT); + pr_info("%s CARRIER_MAG_REPORT: 0x%x [threshold: 0x%x].\n", + __func__, reg_value, audio_a2_carrier_report); if (((reg_value >> 16) & 0xffff) < audio_a2_carrier_report) { *stereo_flag = 0; *dual_flag = 0; @@ -920,6 +934,8 @@ void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag) } } else { reg_value = adec_rd_reg(POWER_REPORT); + pr_info("%s POWER_REPORT: 0x%x [threshold: 0x%x].\n", + __func__, reg_value, audio_a2_power_threshold); stereo_power = reg_value & 0xffff; dual_power = (reg_value >> 16) & 0xffff; diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 6d4a8c3e8abd..4d17b9684813 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -66,6 +66,7 @@ unsigned int if_freq = 4250000; /*PAL-DK:3250000;NTSC-M:4250000*/ unsigned int if_inv; int afc_default = CARR_AFC_DEFAULT_VAL; +int snr_threshold = 30; /* @@ -2417,6 +2418,10 @@ void aml_audio_overmodulation(int enable) unsigned int reg = 0; u32 Broadcast_Standard = broad_std; + /* False entry on weak signal */ + if (atvdemod_get_snr() < snr_threshold) + return; + if (enable && Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) { tmp_v = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x28); From 2b75a9c818360030d1da648b1739061046a61154 Mon Sep 17 00:00:00 2001 From: "nengwen.chen" Date: Wed, 9 Jan 2019 20:41:49 +0800 Subject: [PATCH 0584/1060] atv_demod: modify atv demod support multi tuner load [1/3] PD#TV-1539 Problem: modify atv demod support multi tuner load. Solution: 1.add fine tune. 2.add set/get if info. 3.add tuner type set/get. 4.add multi tuner config in dts. 5.atv demod ver: V2.09. Verify: verified by x301 Change-Id: I23328bfab3d3508db67cef3e327002563eb1a87e Signed-off-by: nengwen.chen Conflicts: arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts --- arch/arm/boot/dts/amlogic/tl1_pxp.dts | 14 +- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 14 +- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 18 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 14 +- arch/arm/boot/dts/amlogic/txl_t950_p341.dts | 14 +- arch/arm/boot/dts/amlogic/txl_t960_p346.dts | 14 +- arch/arm/boot/dts/amlogic/txl_t962_p320.dts | 14 +- arch/arm/boot/dts/amlogic/txl_t962_p321.dts | 14 +- .../boot/dts/amlogic/txl_t962_p321_720p.dts | 14 +- arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts | 14 +- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 14 +- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 14 +- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 14 +- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 11 + .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 11 +- arch/arm64/boot/dts/amlogic/txl_t950_p341.dts | 14 +- arch/arm64/boot/dts/amlogic/txl_t960_p346.dts | 14 +- arch/arm64/boot/dts/amlogic/txl_t962_p320.dts | 14 +- arch/arm64/boot/dts/amlogic/txl_t962_p321.dts | 14 +- .../boot/dts/amlogic/txl_t962_p321_720p.dts | 14 +- .../boot/dts/amlogic/txlx_t962e_r321.dts | 14 +- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 14 +- .../boot/dts/amlogic/txlx_t962x_r311_1g.dts | 14 +- .../boot/dts/amlogic/txlx_t962x_r311_2g.dts | 14 +- .../boot/dts/amlogic/txlx_t962x_r311_720p.dts | 14 +- .../boot/dts/amlogic/txlx_t962x_r314.dts | 14 +- drivers/amlogic/atv_demod/atv_demod_driver.c | 269 ++++++++++++------ drivers/amlogic/atv_demod/atv_demod_driver.h | 19 +- drivers/amlogic/atv_demod/atv_demod_ops.c | 12 +- drivers/amlogic/atv_demod/atv_demod_ops.h | 1 + drivers/amlogic/atv_demod/atv_demod_v4l2.c | 82 +++++- drivers/amlogic/atv_demod/atv_demod_v4l2.h | 4 + drivers/amlogic/atv_demod/atvdemod_func.c | 33 ++- include/linux/amlogic/aml_atvdemod.h | 1 + 34 files changed, 510 insertions(+), 273 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index 1f4eb6e7e2de..6506f548685a 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -536,15 +536,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 5870e7a1593c..e6b01cbda6e9 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -995,15 +995,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ }; bt-dev{ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 277abd768868..36f7b0916a55 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1116,15 +1116,19 @@ tuner: tuner { status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) - * SLAVE_XTAL_SHARE(3) + * MASTER_TO_SLAVE_XTAL_IN(1) + * MASTER_TO_SLAVE_XTAL_OUT(2) + * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <38>; /* when tuner_xtal_mode = 3, set 25 */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index d54452b0bdb4..07096d100802 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1044,15 +1044,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ }; bt-dev{ diff --git a/arch/arm/boot/dts/amlogic/txl_t950_p341.dts b/arch/arm/boot/dts/amlogic/txl_t950_p341.dts index 55f8f37e8dfe..065c204a1e9f 100644 --- a/arch/arm/boot/dts/amlogic/txl_t950_p341.dts +++ b/arch/arm/boot/dts/amlogic/txl_t950_p341.dts @@ -438,17 +438,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t960_p346.dts b/arch/arm/boot/dts/amlogic/txl_t960_p346.dts index fc5beecdcbf1..9c05ca3ebea2 100644 --- a/arch/arm/boot/dts/amlogic/txl_t960_p346.dts +++ b/arch/arm/boot/dts/amlogic/txl_t960_p346.dts @@ -439,17 +439,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p320.dts b/arch/arm/boot/dts/amlogic/txl_t962_p320.dts index ca71b184ee52..79f71365fc7d 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p320.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p320.dts @@ -429,12 +429,14 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts index 9f464fe4c5a7..43f3db1cdad5 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts @@ -450,17 +450,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts index fddd1d154825..590514c96443 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -450,17 +450,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index 05a3a8be78ee..852b21a3a12e 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -620,12 +620,14 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 2aa758832650..7567223a9e31 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -664,12 +664,14 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts index b03caca8d328..ead887e15a43 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -622,15 +622,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index db5f94fcb1df..d5bb1f240177 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -618,15 +618,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 5e6f851f96d9..3173d0411f70 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -624,12 +624,23 @@ tuner: tuner { compatible = "amlogic, tuner"; +<<<<<<< HEAD status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; tuner_i2c_addr = <0x60>; tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ tuner_xtal_mode = <0>; +======= + status = "disabled"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; +>>>>>>> 374c6b2... atv_demod: modify atv demod support multi tuner load [1/3] /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index e05791af1e8d..4006eadcfdc0 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1166,15 +1166,12 @@ status = "okay"; tuner_cur = <0>; /* default use tuner */ tuner_num = <1>; /* tuner number, multi tuner support */ - tuner_name_0 = "mxl661_tuner"; + tuner_name_0 = "si2151_tuner"; tuner_i2c_adap_0 = <&i2c0>; tuner_i2c_addr_0 = <0x60>; - tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode_0 = <3>; - /* NO_SHARE_XTAL(0) - * SLAVE_XTAL_SHARE(3) - */ - tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts b/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts index ecf2c7e4b754..2dcf8572fd33 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts @@ -438,17 +438,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts b/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts index e4321378c211..8731df171276 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts @@ -438,17 +438,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts index 6fd359f256d5..374583ed929f 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts @@ -429,12 +429,14 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts index c68566302ff9..c52c595488a4 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts @@ -442,17 +442,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts index 8d28468048bf..89f0f7f7476b 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -442,17 +442,19 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index 7d6b5a8d66cb..b9bad6469003 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -619,12 +619,14 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index d0f142bc37f7..27d6b6ff27b6 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -663,12 +663,14 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index 2225bcf0656d..994f158790d5 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -620,15 +620,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index ff5f8f246645..28bd90a38a98 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -620,15 +620,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index d15cab0023e6..1efc5e3fe69c 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -619,15 +619,17 @@ tuner: tuner { compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 5750072fe2ff..3c25f458df97 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -620,12 +620,14 @@ tuner: tuner { compatible = "amlogic, tuner"; - status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + status = "disabled"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index e5dd53434193..93bb20530d09 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -45,7 +45,7 @@ #include "atvauddemod_func.h" -#define AMLATVDEMOD_VER "V2.08" +#define AMLATVDEMOD_VER "V2.09" struct aml_atvdemod_device *amlatvdemod_devp; @@ -66,7 +66,7 @@ static ssize_t aml_atvdemod_store(struct class *class, unsigned long tmp = 0, data = 0; struct aml_atvdemod_device *dev = container_of(class, struct aml_atvdemod_device, cls); - struct atv_demod_priv *priv = dev->v4l2_fe.fe.analog_demod_priv; + /*struct atv_demod_priv *priv = dev->v4l2_fe.fe.analog_demod_priv;*/ buf_orig = kstrdup(buf, GFP_KERNEL); ps = buf_orig; @@ -82,11 +82,12 @@ static ssize_t aml_atvdemod_store(struct class *class, if (parm[0] == NULL) goto EXIT; - +#if 0 if (priv->state != ATVDEMOD_STATE_WORK) { pr_info("atvdemod_state not work ....\n"); goto EXIT; } +#endif if (!strncmp(parm[0], "init", 4)) { ret = atv_demod_enter_mode(&dev->v4l2_fe.fe); @@ -271,6 +272,7 @@ static ssize_t aml_atvdemod_store(struct class *class, struct analog_parameters params; struct v4l2_analog_parameters *p = NULL; unsigned int std = 0; + unsigned int freq = 0; fe = &dev->v4l2_fe.fe; p = &dev->v4l2_fe.params; @@ -280,7 +282,12 @@ static ssize_t aml_atvdemod_store(struct class *class, else std = p->std; - params.frequency = p->frequency; + if (parm[2] && kstrtoul(parm[2], 0, &tmp) == 0) + freq = tmp; + else + freq = p->frequency; + + params.frequency = freq; params.mode = p->afc_range; params.audmode = p->audmode; params.std = std; @@ -310,11 +317,40 @@ static ssize_t aml_atvdemod_store(struct class *class, v4l2_std_to_str((0xffffff & dev->std))); pr_info("[atvdemod] audmode: 0x%x\n", dev->audmode); pr_info("[atvdemod] flag: %d\n", p->flag); - pr_info("[atvdemod] tuner_id: %d\n", dev->tuner_id); + pr_info("[atvdemod] tuner_cur: %d\n", dev->tuner_cur); + pr_info("[atvdemod] tuner_id: %d\n", + dev->tuners[dev->tuner_cur].cfg.id); pr_info("[atvdemod] if_freq: %d\n", dev->if_freq); pr_info("[atvdemod] if_inv: %d\n", dev->if_inv); pr_info("[atvdemod] fre_offset: %d\n", dev->fre_offset); pr_info("[atvdemod] version: %s.\n", AMLATVDEMOD_VER); + } else if (!strncmp(parm[0], "attach_tuner", 12)) { + int tuner_id = 0; + + if (parm[1] && kstrtoul(parm[1], 10, &tmp) == 0) { + val = tmp; + + for (i = 0; i < dev->tuner_num; ++i) { + if (dev->tuners[i].cfg.id == val) { + tuner_id = dev->tuners[i].cfg.id; + break; + } + } + + if (tuner_id == 0 || dev->tuner_cur == i) { + pr_err("%s: set nonsupport or the same tuner %d.\n", + __func__, val); + goto EXIT; + } + + dev->tuner_cur = i; + + ret = aml_attach_tuner(dev); + if (ret) + pr_info("attach_tuner error.\n"); + else + pr_info("attach_tuner %d done.\n", tuner_id); + } } else pr_dbg("invalid command\n"); @@ -350,7 +386,9 @@ static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) struct device_node *node_i2c = NULL; unsigned int val = 0; const char *str = NULL; + char buf[20] = { 0 }; int ret = 0; + int i = 0; node = pdev->dev->of_node; if (node == NULL) { @@ -382,8 +420,7 @@ static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) pdev->agc_pin = NULL; pr_err("can't find agc pinmux.\n"); } else { - pr_err("atvdemod agc pinmux name: %s\n", - pdev->pin_name); + pr_err("atvdemod agc pinmux name: %s\n", pdev->pin_name); } ret = of_property_read_u32(node, "btsc_sap_mode", &val); @@ -394,119 +431,176 @@ static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) /* get tuner config node */ node_tuner = of_parse_phandle(node, "tuner", 0); - if (node_tuner) { - ret = of_property_read_string(node_tuner, "tuner_name", &str); - if (ret) - pr_err("can't find tuner.\n"); - else { - if (!strncmp(str, "mxl661_tuner", 12)) - pdev->tuner_id = AM_TUNER_MXL661; - else if (!strncmp(str, "si2151_tuner", 12)) - pdev->tuner_id = AM_TUNER_SI2151; - else if (!strncmp(str, "si2159_tuner", 12)) - pdev->tuner_id = AM_TUNER_SI2159; - else if (!strncmp(str, "r840_tuner", 10)) - pdev->tuner_id = AM_TUNER_R840; - else if (!strncmp(str, "r842_tuner", 10)) - pdev->tuner_id = AM_TUNER_R842; - else - pr_err("nonsupport tuner: %s.\n", str); + if (!node_tuner) { + pr_err("can't find tuner node.\n"); + return; + } + + ret = of_property_read_u32(node_tuner, "tuner_num", &val); + if (ret == 0) + pdev->tuner_num = val; + else { + pr_err("can't find tuner_num.\n"); + return; + } + + pdev->tuners = kcalloc(pdev->tuner_num, sizeof(struct aml_tuner), + GFP_KERNEL); + if (!pdev->tuners) { + /* pr_err("can't kcalloc for tuners.\n"); */ + return; + } + + ret = of_property_read_u32(node_tuner, "tuner_cur", &val); + if (ret) { + pr_err("can't find tuner_cur, use default 0.\n"); + pdev->tuner_cur = -1; + } else + pdev->tuner_cur = val; + + for (i = 0; i < pdev->tuner_num; ++i) { + snprintf(buf, sizeof(buf), "tuner_name_%d", i); + ret = of_property_read_string(node_tuner, buf, &str); + if (ret) { + pr_err("can't find tuner %d.\n", i); + continue; } - node_i2c = of_parse_phandle(node_tuner, "tuner_i2c_adap", 0); + if (!strncmp(str, "mxl661_tuner", 12)) + pdev->tuners[i].cfg.id = AM_TUNER_MXL661; + else if (!strncmp(str, "si2151_tuner", 12)) + pdev->tuners[i].cfg.id = AM_TUNER_SI2151; + else if (!strncmp(str, "si2159_tuner", 12)) + pdev->tuners[i].cfg.id = AM_TUNER_SI2159; + else if (!strncmp(str, "r840_tuner", 10)) + pdev->tuners[i].cfg.id = AM_TUNER_R840; + else if (!strncmp(str, "r842_tuner", 10)) + pdev->tuners[i].cfg.id = AM_TUNER_R842; + else { + pr_err("can't support tuner: %s.\n", str); + pdev->tuners[i].cfg.id = AM_TUNER_NONE; + } + + snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", i); + node_i2c = of_parse_phandle(node_tuner, buf, 0); if (node_i2c) { - pdev->i2c_adp = of_find_i2c_adapter_by_node(node_i2c); + pdev->tuners[i].i2c_adp = + of_find_i2c_adapter_by_node(node_i2c); of_node_put(node_i2c); - if (!pdev->i2c_adp) + if (!pdev->tuners[i].i2c_adp) pr_err("can't find tuner_i2c_adap.\n"); } - ret = of_property_read_u32(node_tuner, "tuner_i2c_addr", &val); + snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_i2c_addr.\n"); else - pdev->i2c_addr = val; + pdev->tuners[i].cfg.i2c_addr = val; - ret = of_property_read_u32(node_tuner, "tuner_xtal", &val); + snprintf(buf, sizeof(buf), "tuner_xtal_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_xtal.\n"); else - pdev->tuner_xtal = val; + pdev->tuners[i].cfg.xtal = val; - ret = of_property_read_u32(node_tuner, "tuner_xtal_mode", &val); + snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_xtal_mode.\n"); else - pdev->tuner_xtal_mode = val; + pdev->tuners[i].cfg.xtal_mode = val; - ret = of_property_read_u32(node_tuner, "tuner_xtal_cap", &val); + snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_xtal_cap.\n"); else - pdev->tuner_xtal_cap = val; + pdev->tuners[i].cfg.xtal_cap = val; - of_node_put(node_tuner); + pr_err("find tuner %d.\n", i); } + + of_node_put(node_tuner); } -int aml_attach_demod_tuner(struct aml_atvdemod_device *dev) +int aml_attach_demod(struct aml_atvdemod_device *dev) { void *p = NULL; struct v4l2_frontend *v4l2_fe = &dev->v4l2_fe; struct dvb_frontend *fe = &v4l2_fe->fe; - struct tuner_config cfg = { 0 }; - if (!dev->analog_attached) { - p = v4l2_attach(aml_atvdemod_attach, fe, v4l2_fe, - dev->i2c_adp, dev->i2c_addr, dev->tuner_id); - if (p != NULL) - dev->analog_attached = true; - else { - pr_err("%s: attach demod error.\n", __func__); - return -1; - } + if (dev->tuner_cur < 0) { + pr_err("%s: dev->tuner_cur [%d] error.\n", + __func__, dev->tuner_cur); + return -1; } - p = NULL; + p = v4l2_attach(aml_atvdemod_attach, fe, v4l2_fe, + dev->tuners[dev->tuner_cur].i2c_adp, + dev->tuners[dev->tuner_cur].cfg.i2c_addr, + dev->tuners[dev->tuner_cur].cfg.id); + if (p != NULL) + dev->analog_attached = true; + else { + pr_err("%s: attach demod error.\n", __func__); + return -1; + } - cfg.id = dev->tuner_id; - cfg.i2c_addr = dev->i2c_addr; - cfg.xtal = dev->tuner_xtal; - cfg.xtal_mode = dev->tuner_xtal_mode; - cfg.xtal_cap = dev->tuner_xtal_cap; + return 0; +} - if (!dev->tuner_attached) { - switch (dev->tuner_id) { - case AM_TUNER_R840: - p = v4l2_attach(r840_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_R842: - p = v4l2_attach(r842_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_SI2151: - p = v4l2_attach(si2151_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_SI2159: - p = v4l2_attach(si2159_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_MXL661: - p = v4l2_attach(mxl661_attach, fe, - dev->i2c_adp, &cfg); - break; - } +int aml_attach_tuner(struct aml_atvdemod_device *dev) +{ + void *p = NULL; + struct v4l2_frontend *v4l2_fe = &dev->v4l2_fe; + struct dvb_frontend *fe = &v4l2_fe->fe; + struct tuner_config *cfg = NULL; - if (p != NULL) - dev->tuner_attached = true; - else { - pr_err("%s: attach tuner [%d] error.\n", - __func__, dev->tuner_id); - return -1; - } + if (dev->tuner_cur < 0) { + pr_err("%s: dev->tuner_cur [%d] error.\n", + __func__, dev->tuner_cur); + return -1; + } + + cfg = &dev->tuners[dev->tuner_cur].cfg; + + switch (cfg->id) { + case AM_TUNER_R840: + p = v4l2_attach(r840_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_R842: + p = v4l2_attach(r842_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_SI2151: + p = v4l2_attach(si2151_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_SI2159: + p = v4l2_attach(si2159_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_MXL661: + p = v4l2_attach(mxl661_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + default: + pr_err("%s: Nonsupport tuner [%d].\n", __func__, cfg->id); + break; + } + + if (p != NULL) { + dev->tuner_attached = true; + v4l2_fe->tuner_id = cfg->id; + v4l2_fe->i2c.addr = cfg->i2c_addr; + v4l2_fe->i2c.adapter = dev->tuners[dev->tuner_cur].i2c_adp; + } else { + pr_err("%s: attach tuner [%d] error.\n", __func__, cfg->id); + return -1; } return 0; @@ -631,12 +725,11 @@ static int aml_atvdemod_probe(struct platform_device *pdev) aml_atvdemod_dt_parse(dev); - aml_attach_demod_tuner(dev); + aml_attach_demod(dev); + aml_attach_tuner(dev); dev->v4l2_fe.dev = dev->dev; - dev->v4l2_fe.tuner_id = dev->tuner_id; - dev->v4l2_fe.i2c.addr = dev->i2c_addr; - dev->v4l2_fe.i2c.adapter = dev->i2c_adp; + ret = v4l2_resister_frontend(&dev->v4l2_fe); if (ret < 0) { pr_err("resister v4l2 fail.\n"); @@ -655,6 +748,7 @@ fail_register_v4l2: fail_get_resource: class_unregister(&dev->cls); fail_class_register: + kfree(dev->tuners); kfree(dev); pr_info("%s: fail.\n", __func__); @@ -676,6 +770,7 @@ static int aml_atvdemod_remove(struct platform_device *pdev) amlatvdemod_devp = NULL; + kfree(dev->tuners); kfree(dev); pr_info("%s: OK.\n", __func__); diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.h b/drivers/amlogic/atv_demod/atv_demod_driver.h index d4ac1eff666a..60a368543603 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.h +++ b/drivers/amlogic/atv_demod/atv_demod_driver.h @@ -38,18 +38,20 @@ struct aml_atvdemod_parameters { unsigned int reserved; }; +struct aml_tuner { + struct tuner_config cfg; + unsigned int i2c_adapter_id; + struct i2c_adapter *i2c_adp; +}; + struct aml_atvdemod_device { char *name; struct class cls; struct device *dev; - unsigned int tuner_id; - unsigned int tuner_xtal; - unsigned int tuner_xtal_mode; - unsigned int tuner_xtal_cap; - unsigned int i2c_addr; - unsigned int i2c_adapter_id; - struct i2c_adapter *i2c_adp; + unsigned int tuner_num; + int tuner_cur; + struct aml_tuner *tuners; unsigned int if_freq; unsigned int if_inv; @@ -94,6 +96,7 @@ struct aml_atvdemod_device { extern struct aml_atvdemod_device *amlatvdemod_devp; -extern int aml_attach_demod_tuner(struct aml_atvdemod_device *dev); +extern int aml_attach_demod(struct aml_atvdemod_device *dev); +extern int aml_attach_tuner(struct aml_atvdemod_device *dev); #endif /* __ATV_DEMOD_DRIVER_H__ */ diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index 53f0afc7a153..f980075a51d3 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -252,14 +252,12 @@ static void atv_demod_set_params(struct dvb_frontend *fe, amlatvdemod_devp->std != p->param.std || amlatvdemod_devp->audmode != p->param.audmode || amlatvdemod_devp->if_freq != p->if_freq || - amlatvdemod_devp->if_inv != p->if_inv || - amlatvdemod_devp->tuner_id != p->tuner_id) { + amlatvdemod_devp->if_inv != p->if_inv) { amlatvdemod_devp->std = p->param.std; amlatvdemod_devp->audmode = p->param.audmode; amlatvdemod_devp->if_freq = p->if_freq; amlatvdemod_devp->if_inv = p->if_inv; - amlatvdemod_devp->tuner_id = p->tuner_id; atv_dmd_set_std(); atvdemod_init(!priv->scanning); @@ -865,7 +863,11 @@ static int atvdemod_fe_set_property(struct v4l2_frontend *v4l2_fe, break; case V4L2_SLOW_SEARCH_MODE: - tvp->data = slow_mode; + slow_mode = tvp->data; + break; + + case V4L2_SIF_OVER_MODULATION: + priv->sound_sys.sif_over_modulation = tvp->data; break; default: @@ -890,7 +892,7 @@ static int atvdemod_fe_get_property(struct v4l2_frontend *v4l2_fe, break; case V4L2_SLOW_SEARCH_MODE: - slow_mode = tvp->data; + tvp->data = slow_mode; break; default: diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.h b/drivers/amlogic/atv_demod/atv_demod_ops.h index 775c5ecf686b..8417722acdf9 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.h +++ b/drivers/amlogic/atv_demod/atv_demod_ops.h @@ -49,6 +49,7 @@ struct atv_demod_sound_system { unsigned int audio_std; unsigned int input_mode; unsigned int output_mode; + int sif_over_modulation; }; struct atv_demod_priv { diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.c b/drivers/amlogic/atv_demod/atv_demod_v4l2.c index 48447500c6a9..7e4fb017c422 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.c +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.c @@ -456,12 +456,11 @@ static int v4l2_frontend_read_status(struct v4l2_frontend *v4l2_fe, if (!status) return -1; -#if 0 - if (analog_ops->tuner_status) - analog_ops->tuner_status(&v4l2_fe->fe, status); + + if (analog_ops->has_signal) + analog_ops->has_signal(&v4l2_fe->fe, (u16 *) status); else if (tuner_ops->get_status) - tuner_ops->get_status(&v4l2_fe->fe, status); -#endif + tuner_ops->get_status(&v4l2_fe->fe, (u32 *) status); return ret; } @@ -538,6 +537,10 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp, struct file *file) { int r = 0; +#if 0 + int i = 0; + int id = 0; +#endif struct v4l2_analog_parameters *params = &v4l2_fe->params; v4l2_property_dump(v4l2_fe, true, tvp); @@ -548,6 +551,7 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, break; case V4L2_SOUND_SYS: case V4L2_SLOW_SEARCH_MODE: + case V4L2_SIF_OVER_MODULATION: /* Allow the frontend to override outgoing properties */ if (v4l2_fe->ops.set_property) { r = v4l2_fe->ops.set_property(v4l2_fe, tvp); @@ -569,6 +573,45 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, | (params->audmode); } break; + case V4L2_FINE_TUNE: + params->frequency += tvp->data; + break; + case V4L2_TUNER_TYPE: +#if 0 /* This supports dynamically setting the tuner type */ + for (i = 0; i < amlatvdemod_devp->tuner_num; ++i) { + if (amlatvdemod_devp->tuners[i].cfg.id == tvp->data) { + id = amlatvdemod_devp->tuners[i].cfg.id; + break; + } + } + + if (id == 0) { + pr_err("%s: nonsupport tuner %d.\n", + __func__, tvp->data); + return -EINVAL; + } + + if (amlatvdemod_devp->tuner_cur == i) { + pr_err("%s: the same tuner %d.\n", + __func__, i); + break; + } + + if (amlatvdemod_devp->tuner_attached) { + if (v4l2_fe->fe.ops.tuner_ops.release) + v4l2_fe->fe.ops.tuner_ops.release(&v4l2_fe->fe); + } + + v4l2_fe->tuner_id = id; + if (aml_attach_tuner(amlatvdemod_devp) < 0) { + pr_err("%s: attach tuner %d error.\n", + __func__, id); + return -EINVAL; + } +#endif + break; + case V4L2_TUNER_IF_FREQ: + break; default: return -EINVAL; } @@ -580,6 +623,7 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp, struct file *file) { int r = 0; + int i = 0; struct v4l2_analog_parameters *params = &v4l2_fe->params; switch (tvp->cmd) { @@ -600,6 +644,18 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, /* std & 0x00FFFFFF: audio std */ tvp->data = params->std; break; + case V4L2_TUNER_TYPE: + i = amlatvdemod_devp->tuner_cur; + if (i < 0) { + pr_err("%s: Has not been set tuner type.\n", __func__); + tvp->data = 0; + return -EINVAL; + } + tvp->data = amlatvdemod_devp->tuners[i].cfg.id; + break; + case V4L2_TUNER_IF_FREQ: + tvp->data = amlatvdemod_devp->if_freq; + break; default: pr_dbg("%s: V4L2 property %d doesn't exist\n", __func__, tvp->cmd); @@ -764,11 +820,19 @@ static int v4l2_frontend_open(struct file *filp) struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; /* Because tuner ko insmod after demod, so need check */ - if (!amlatvdemod_devp->tuner_attached - || !amlatvdemod_devp->analog_attached) { - ret = aml_attach_demod_tuner(amlatvdemod_devp); + if (!amlatvdemod_devp->analog_attached) { + ret = aml_attach_demod(amlatvdemod_devp); if (ret < 0) { - pr_err("%s: attach demod or tuner %d error.\n", + pr_err("%s: attach demod %d error.\n", + __func__, v4l2_fe->tuner_id); + return -EBUSY; + } + } + + if (!amlatvdemod_devp->tuner_attached) { + ret = aml_attach_tuner(amlatvdemod_devp); + if (ret < 0) { + pr_err("%s: attach tuner %d error.\n", __func__, v4l2_fe->tuner_id); return -EBUSY; } diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.h b/drivers/amlogic/atv_demod/atv_demod_v4l2.h index ba31acc6287e..6fc3078090e4 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.h +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.h @@ -94,6 +94,10 @@ #define V4L2_SLOW_SEARCH_MODE 3 #define V4L2_FREQUENCY 4 #define V4L2_STD 5 +#define V4L2_FINE_TUNE 6 +#define V4L2_SIF_OVER_MODULATION 7 +#define V4L2_TUNER_TYPE 8 +#define V4L2_TUNER_IF_FREQ 9 struct v4l2_frontend; diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 4d17b9684813..c22a63b4c423 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -201,8 +201,10 @@ void atv_dmd_misc(void) atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x45, 0x90); /*zhuangwei*/ atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x5c8808c1);/*zhuangwei*/ - if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || - amlatvdemod_devp->tuner_id == AM_TUNER_R842) { + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R840 || + amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R842) { /*zhuangwei*/ atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x3c, reg_23cf); /*guanzhong@20150804a*/ @@ -230,7 +232,8 @@ void atv_dmd_misc(void) atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46170200); } - if (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661) { + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_MXL661) { /*test in sky*/ atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xbffa0000); atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x00, 0x6f4000); @@ -1005,8 +1008,10 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03180e0f); else atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03150e0f); - if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || - amlatvdemod_devp->tuner_id == AM_TUNER_R842) { + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R840 || + amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R842) { /*config pwm for tuner r840*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_SE, 1, 0xf); } @@ -1283,8 +1288,10 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x04, 0xc8); /*26 dB dynamic range*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0xa); - if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || - amlatvdemod_devp->tuner_id == AM_TUNER_R842) { + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R840 || + amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R842) { /*config pwm for tuner r840*/ atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0, 0xc80); /* guanzhong for Tuner AGC shock */ @@ -1972,6 +1979,8 @@ void atvdemod_uninit(void) void atv_dmd_set_std(void) { v4l2_std_id ptstd = amlatvdemod_devp->std; + int tuner_index = amlatvdemod_devp->tuner_cur; + int tuner_id = amlatvdemod_devp->tuners[tuner_index].cfg.id; /* set broad standard of tuner*/ if (((ptstd & V4L2_COLOR_STD_PAL) @@ -2049,11 +2058,11 @@ void atv_dmd_set_std(void) } /* Tuner returns the if and signal inverted states */ - if ((amlatvdemod_devp->tuner_id == AM_TUNER_R840) || - (amlatvdemod_devp->tuner_id == AM_TUNER_R842) || - (amlatvdemod_devp->tuner_id == AM_TUNER_SI2151) || - (amlatvdemod_devp->tuner_id == AM_TUNER_SI2159) || - (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661)) { + if ((tuner_id == AM_TUNER_R840) || + (tuner_id == AM_TUNER_R842) || + (tuner_id == AM_TUNER_SI2151) || + (tuner_id == AM_TUNER_SI2159) || + (tuner_id == AM_TUNER_MXL661)) { if_freq = amlatvdemod_devp->if_freq; if_inv = amlatvdemod_devp->if_inv; } diff --git a/include/linux/amlogic/aml_atvdemod.h b/include/linux/amlogic/aml_atvdemod.h index 29519f089d9e..ad6914aaa3d1 100644 --- a/include/linux/amlogic/aml_atvdemod.h +++ b/include/linux/amlogic/aml_atvdemod.h @@ -124,6 +124,7 @@ extern void aml_fe_get_atvaudio_state(int *state); /* For attach tuner driver start*/ enum tuner_type { + AM_TUNER_NONE = 0, AM_TUNER_SI2176 = 1, AM_TUNER_SI2196 = 2, AM_TUNER_FQ1216 = 3, From ac05ed73efd978d8cb7d89afdc67b97bc37ae668 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 3 Apr 2019 18:53:20 +0800 Subject: [PATCH 0585/1060] debug: enable ftrace_ramoops [1/2] PD#SWPL-6028 Problem: enable ftrce in ramoops Solution: enable ftrce in ramoops Verify: u200 Change-Id: I2403bf82c342416b7c34f2115b14dce623406997 Signed-off-by: Jianxin Pan Conflicts: arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts --- arch/arm/boot/dts/amlogic/atom.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_a113d_skt.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_a113x_skt.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_s400.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_s400_v03.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_s420.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_s420_v03.dts | 3 +-- arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 3 +-- arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts | 3 +-- arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts | 3 +-- arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts | 3 +-- arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts | 3 +-- arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts | 3 +-- .../dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts | 4 +--- .../dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts | 3 +-- .../boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p212_2g.dts | 4 ++-- arch/arm/boot/dts/amlogic/gxl_p230_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts | 4 +--- arch/arm/boot/dts/amlogic/gxl_p231_1g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p231_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p241_1g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p400_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_p401_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxm_q200_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/gxm_q201_1g.dts | 5 ++--- arch/arm/boot/dts/amlogic/gxm_q201_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/gxm_skt.dts | 3 +-- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 8 ++++++++ arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 8 ++++++++ arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts | 3 +-- arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts | 3 +-- arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts | 3 +-- arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts | 3 +-- arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts | 3 +-- arch/arm/configs/meson64_a32_defconfig | 4 ++-- arch/arm64/boot/dts/amlogic/atom.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts | 5 ++--- arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s400.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s400_v03.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s420.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s420_v03.dts | 3 +-- arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts | 4 ++-- arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts | 5 ++--- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts | 3 +-- .../boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts | 3 +-- .../dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts | 3 +-- .../dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts | 3 +-- .../boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts | 3 +-- .../boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts | 5 ++--- arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/gxm_skt.dts | 3 +-- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 2 +- arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 2 +- arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts | 3 +-- arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts | 3 +-- arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts | 3 +-- arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts | 3 +-- arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts | 3 +-- arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts | 3 +-- arch/arm64/configs/meson64_defconfig | 1 + 112 files changed, 133 insertions(+), 220 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/atom.dts b/arch/arm/boot/dts/amlogic/atom.dts index b2a9b477dc26..84357efa8f38 100644 --- a/arch/arm/boot/dts/amlogic/atom.dts +++ b/arch/arm/boot/dts/amlogic/atom.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts index a43193324bcf..0b3b51ccfd3e 100644 --- a/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts @@ -49,8 +49,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts b/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts index 1902ef3d8ac0..5d7728f24089 100644 --- a/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts +++ b/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s400.dts b/arch/arm/boot/dts/amlogic/axg_s400.dts index 3884ee3256c9..06011dbf03e1 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03.dts index d8cf6fd0d07b..8fe15edbbc6f 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts index b09543d0e9dc..3f5ae0fec5b5 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s420.dts b/arch/arm/boot/dts/amlogic/axg_s420.dts index 104e35fa2746..fda588bb3b3e 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s420_v03.dts b/arch/arm/boot/dts/amlogic/axg_s420_v03.dts index f9da32c0821a..05ab48dde9d9 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420_v03.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420_v03.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts index f49e3e48a097..83595b360b8b 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index d6686825d721..3ce2558e9538 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index 837e58fc94ad..39979b7caf8e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index ecdcd1315023..6fd0b595c93e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index 71e37476bb39..e15e7125e640 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index dd99fd41ab3a..b38fec03dbd2 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index c31fe1f97d92..ef84c49e8ecd 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -57,8 +57,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index 4e52524afaba..fdaeda8ca429 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 7705079df6d7..f9e7e6c2a43b 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index b7a1be3a9273..631b434a2a04 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -57,8 +57,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index a88a2dd1f28c..69825190259d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index 918d73b5fa97..0a4eece69d97 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts index 6d9492cd2aa8..f92c26d42cf6 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index b89aaa40a1df..c1b36a44699f 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index 83510bc0c0ee..c972c12c8a58 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index aac22ee9e0b5..8e469c08a44d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -58,10 +58,8 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index 202c6190596e..7edfad7e86b7 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index e3f43063fe27..10b88c0b4f98 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts index c03256ed4713..336df9026d36 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts @@ -56,9 +56,9 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts index c1944cc88ba5..fe328fc6093f 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index bdb46750131d..535dd4e5bf46 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -56,10 +56,8 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts index 5fdbc780e00e..de8e236c9d66 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts index 0a35a0dfe4f7..396c7592ebd4 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 2365af310a9a..5fb51e8e1171 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -53,8 +53,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts index feab09e7e205..5aa26fa17678 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index af46fd2edaec..b3c37a77262e 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts index aa85f76b0ef2..99991056161b 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index bd8fa63f3cc1..102e11007bba 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts index 46a4b3276009..2e82adb434d6 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts @@ -51,8 +51,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts index 2bb9708797db..8fa3a3f97578 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts @@ -51,8 +51,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts index f68747e8b572..e7468cd8a789 100644 --- a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts index 722771f0e370..78687fb85166 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts index e695359c349b..32725adaacfd 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts @@ -54,8 +54,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts b/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts index c1ac3945fdd6..46823dce61e4 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts @@ -55,9 +55,8 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; -}; + ftrace-size = <0x20000>; + }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts b/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts index b70073f2e5c6..0b77e079f71c 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxm_skt.dts b/arch/arm/boot/dts/amlogic/gxm_skt.dts index b6ff2bba3430..4eba9826cd4a 100644 --- a/arch/arm/boot/dts/amlogic/gxm_skt.dts +++ b/arch/arm/boot/dts/amlogic/gxm_skt.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index b946f2c46727..e6cf660d0bb3 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -59,7 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; + ftrace-size = <0x20000>; pmsg-size = <0x8000>; }; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 0dbf2b0d1d2d..0169f2515c98 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -59,7 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; + ftrace-size = <0x20000>; pmsg-size = <0x8000>; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index e6b01cbda6e9..94ff98893b71 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -51,6 +51,14 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + secmon_reserved: linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 36f7b0916a55..e75ca27909e0 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -52,6 +52,14 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + secmon_reserved: linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index 852b21a3a12e..64ab38cfbda2 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 7567223a9e31..5b9852267027 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -57,8 +57,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts index ead887e15a43..600835e2d8e9 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -61,8 +61,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index d5bb1f240177..d5e262d28dc8 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 3173d0411f70..10289ebbab0d 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -61,8 +61,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index f07a46f44ceb..963dd38cbff3 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -489,10 +489,10 @@ CONFIG_AMLOGIC_SND_CODEC_PCM2BT=y CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015S=y +CONFIG_AMLOGIC_SND_SOC_TAS5805=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y -CONFIG_AMLOGIC_SND_SOC_TAS5805=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y CONFIG_AMLOGIC_SND_SOC_SSM3525=y @@ -597,6 +597,7 @@ CONFIG_SQUASHFS=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_FTRACE=y CONFIG_PSTORE_RAM=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y @@ -625,7 +626,6 @@ CONFIG_LSM_MMAP_MIN_ADDR=0 CONFIG_HARDENED_USERCOPY=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y -CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index 647052c5c84d..4021f1de6300 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts index e9f86802b3cc..3e052619aa8b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -49,9 +49,8 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; -}; + ftrace-size = <0x20000>; + }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts index d3407d8dd797..65a00e75f37f 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 4098f87e1557..58383abc24c8 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts index 25d394141807..ee09047cbdcb 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts index a2e2f418e02b..63336e786088 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts index 026f07e4e50b..c37f4f6e2677 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts index 6b30d540f730..445b84940a96 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts @@ -53,8 +53,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s420.dts b/arch/arm64/boot/dts/amlogic/axg_s420.dts index ddc988d71ee9..6f1c708d9ea4 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts index b2ce78745814..6033259c5f37 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts index 08207f9e8c83..b01bb73f12be 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index d0fb183d0632..76eb019352c5 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index cd3d653df59f..639e2e62f50c 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -59,10 +59,10 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 996f192e1d0c..07b674175fb0 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -54,13 +54,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - ramoops@0x07400000 { + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index 9b5b4d356673..08d52a09a004 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index dceafa0b02e4..1dce4d3bf867 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 7b6d627a5c49..7e8d963e1e41 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index ae215a6fdb2c..23ed588c6b72 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 81c1ecd44173..b742fe8b87a7 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index 722c9f53d9b4..738792decd23 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index 4e3d8fa3df25..171aec33996d 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts index c3d6219323df..f20a7b708125 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index f4ba4b707225..377595fcbffe 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts index 078e1c1e3c33..7f1418567299 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index daa12b9bbced..2ffeeab99849 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts index b91028e69e76..e86e01060d83 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 837925bafada..280a07ab75af 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts index 0c406a175bfa..ac5ca3645b64 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index 4c8d1de14882..f22c04a4c4fa 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index 47e9c788420e..63f6b0d72f9b 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index d6851e87a05e..a37936e0870b 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index df862e17defe..302ea680e67f 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts index 101ad78b2091..6adc66fb6a92 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index 5c38487443f2..841f7da52be9 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts index 35b9af46f645..a7b5e439da75 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts index a45c09ec3f90..db2416922a41 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 92f6e7d9ceef..b334aca4f65b 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -53,8 +53,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts index dadb59aed48a..66db66c9f860 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index 5d9833ba1592..854b833d2170 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts index f569d0799fc5..f915038df6cd 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index 6bfe499fead6..ca8d72a56763 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts index bb6cc479e20c..41ce3a54edcc 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts @@ -51,8 +51,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts index f316571920da..e8555c961e91 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts @@ -51,8 +51,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts index 5140780d2f7f..cf3440bfd7f8 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts index d3bc6cd8c294..6bddb2bcd189 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts index e8dcafa47c2e..b5e51bcbd530 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts @@ -54,8 +54,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts b/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts index 4e7b21493617..0340ebf2682f 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts @@ -55,9 +55,8 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; -}; + ftrace-size = <0x20000>; + }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts index 9fc21ce39103..cde470e1fd8e 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxm_skt.dts b/arch/arm64/boot/dts/amlogic/gxm_skt.dts index 90dde409de72..148290c04da6 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_skt.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 86b4482d0a2d..438cd2c1ec8d 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -59,7 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; + ftrace-size = <0x20000>; pmsg-size = <0x8000>; }; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index f25c4a4a754a..a4f4f963a265 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -59,7 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; + ftrace-size = <0x20000>; pmsg-size = <0x8000>; }; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index b9bad6469003..d281ce3b80c0 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 27d6b6ff27b6..c3030551b899 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index 994f158790d5..df6523b6500c 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 28bd90a38a98..95975254a527 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index 1efc5e3fe69c..70d11b2dba28 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 3c25f458df97..3b1058718814 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 9fb51faf6dde..ddc21eb7bc80 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -588,6 +588,7 @@ CONFIG_SQUASHFS=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_FTRACE=y CONFIG_PSTORE_RAM=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y From e94805a6460620257d14d8b9d75c138fe770411d Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Thu, 4 Apr 2019 20:02:57 +0800 Subject: [PATCH 0586/1060] dts: debug: enable ftrace_ramoops for new dts [1/1] PD#SWPL-6028 Problem: enable ftrce in ramoops for new dtbs Solution: enable ftrce in ramoops for new dtbs Verify: X301 Change-Id: I0643329a873a310d1078ebd898fec2d3cb75d43c Signed-off-by: Jianxin Pan --- arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts | 3 +-- arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 1 - arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts | 1 - arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts | 3 +-- arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts | 1 - arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts | 1 - 6 files changed, 2 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts index 1174f5283fb8..b8df36eec9d3 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index e6cf660d0bb3..bfeb017456e4 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -60,7 +60,6 @@ record-size = <0x8000>; console-size = <0x8000>; ftrace-size = <0x20000>; - pmsg-size = <0x8000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts index 0169f2515c98..6e45aa64729f 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -60,7 +60,6 @@ record-size = <0x8000>; console-size = <0x8000>; ftrace-size = <0x20000>; - pmsg-size = <0x8000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts index e03817b5ed24..c91bc36f0861 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts index 438cd2c1ec8d..0709022cd4ec 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -60,7 +60,6 @@ record-size = <0x8000>; console-size = <0x8000>; ftrace-size = <0x20000>; - pmsg-size = <0x8000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts index a4f4f963a265..12b669b1fe7f 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -60,7 +60,6 @@ record-size = <0x8000>; console-size = <0x8000>; ftrace-size = <0x20000>; - pmsg-size = <0x8000>; }; secmon_reserved:linux,secmon { From fc3b3a7e3d87fe528bb9cd655e540d4e4a3b45c7 Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Wed, 17 Apr 2019 11:26:58 +0800 Subject: [PATCH 0587/1060] amvecm: fix sm1 green screen when play videos [1/1] PD#SWPL-7302 Problem: sm1 green screen when play videos Solution: add chip support Verify: s905D3 Change-Id: I50c0a9f889d72b65157a973bfe1df8dce10db64a Signed-off-by: Bencheng Jing Conflicts: drivers/amlogic/media/enhancement/amvecm/amve.c --- .../amlogic/media/enhancement/amvecm/amve.c | 9 +++ .../amlogic/media/enhancement/amvecm/amve.h | 1 + .../amlogic/media/enhancement/amvecm/amvecm.c | 15 +++-- .../media/enhancement/amvecm/set_hdr2_v0.c | 8 --- .../amlogic/media/enhancement/amvecm/vlock.c | 66 +++++++++++++++---- 5 files changed, 72 insertions(+), 27 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index ec20427479b3..53b6dd9e890e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -1324,6 +1324,9 @@ void amvecm_3d_sync_process(void) #define SR_NOSCALE_LEVEL 0x10 static void amve_sr_reg_setting(unsigned int adaptive_level) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) + goto g12_sr_reg_setting; if (adaptive_level & SR_SD_SCALE_LEVEL) am_set_regmap(&sr1reg_sd_scale); else if (adaptive_level & SR_HD_SCALE_LEVEL) @@ -1340,6 +1343,12 @@ static void amve_sr_reg_setting(unsigned int adaptive_level) am_set_regmap(&sr1reg_cvbs); else if (adaptive_level & SR_NOSCALE_LEVEL) am_set_regmap(&sr1reg_hv_noscale); + return; +g12_sr_reg_setting: + /*for g12a and g12b, load sr0 cvbs table when output cvbs mode*/ + if (adaptive_level & SR_CVBS_LEVEL) + am_set_regmap(&sr0reg_cvbs); + return; } void amve_sharpness_adaptive_setting(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index 6963dfe5473c..02110178715a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -157,6 +157,7 @@ extern void amve_sharpness_adaptive_setting(struct vframe_s *vf, extern void amve_sharpness_init(void); extern struct am_regs_s sr1reg_sd_scale; extern struct am_regs_s sr1reg_hd_scale; +extern struct am_regs_s sr0reg_cvbs; extern struct am_regs_s sr1reg_cvbs; extern struct am_regs_s sr1reg_hv_noscale; extern void amvecm_fresh_overscan(struct vframe_s *vf); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index e92a2320bfcc..7a0e6d43e252 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -131,7 +131,7 @@ unsigned int atv_source_flg; static int vdj_mode_flg; struct am_vdj_mode_s vdj_mode_s; -void __iomem *amvecm_hiu_reg_base;/* = *ioremap(0xc883c000, 0x2000); */ +/*void __iomem *amvecm_hiu_reg_base;*//* = *ioremap(0xc883c000, 0x2000); */ static int debug_amvecm; module_param(debug_amvecm, int, 0664); @@ -724,6 +724,7 @@ static ssize_t amvecm_vlock_store(struct class *cla, sel = VLOCK_SUPPORT; } else if (!strncmp(parm[0], "enable", 6)) { vecm_latch_flag |= FLAG_VLOCK_EN; + vlock_set_en(true); } else if (!strncmp(parm[0], "disable", 7)) { vecm_latch_flag |= FLAG_VLOCK_DIS; } else if (!strncmp(parm[0], "status", 6)) { @@ -1110,7 +1111,8 @@ int amvecm_on_vs( /* add some flag to trigger */ if (vf) { /*gxlx sharpness adaptive setting*/ - if (is_meson_gxlx_cpu()) + if (is_meson_gxlx_cpu() || is_meson_g12a_cpu() + || is_meson_g12b_cpu() || is_meson_sm1_cpu()) amve_sharpness_adaptive_setting(vf, sps_h_en, sps_v_en); amvecm_bricon_process( @@ -6847,16 +6849,19 @@ static struct platform_driver aml_vecm_driver = { static int __init aml_vecm_init(void) { - unsigned int hiu_reg_base; + /*unsigned int hiu_reg_base;*/ pr_info("%s:module init\n", __func__); + #if 0 /* remap the hiu bus */ if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_g12a_cpu() || is_meson_g12b_cpu()) + is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu()) hiu_reg_base = 0xff63c000; else hiu_reg_base = 0xc883c000; amvecm_hiu_reg_base = ioremap(hiu_reg_base, 0x2000); + #endif if (platform_driver_register(&aml_vecm_driver)) { pr_err("failed to register bl driver module\n"); return -ENODEV; @@ -6868,7 +6873,7 @@ static int __init aml_vecm_init(void) static void __exit aml_vecm_exit(void) { pr_info("%s:module exit\n", __func__); - iounmap(amvecm_hiu_reg_base); + /*iounmap(amvecm_hiu_reg_base);*/ platform_driver_unregister(&aml_vecm_driver); } diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index d4ab598a4dc5..f28f66561c79 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -1301,14 +1301,6 @@ void set_hdr_matrix( adpscl_alpha[i] = 10 * in_luma * (1 << adp_scal_shift) / out_luma; - if (hdr_mtx_param->p_sel & HDR_SDR) { - if (i == 0) - adpscl_shift[i] = adp_scal_shift; - else - adpscl_shift[i] = adp_scal_shift - 2; - } else - adpscl_shift[i] = adp_scal_shift; - adpscl_ys_coef[i] = 1 << adp_scal_shift; adpscl_beta_s[i] = 0; diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 6fba57dfe9b4..49477b525bef 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -315,10 +315,9 @@ static void vlock_enable(bool enable) { unsigned int tmp_value; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu()) { if (vlock_mode & VLOCK_MODE_MANUAL_PLL) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 20, 1); /*vlsi suggest config:don't enable load signal, *on gxtvbb this load signal will effect SSG, @@ -352,6 +351,9 @@ static void vlock_enable(bool enable) /*WRITE_VPP_REG(VPU_VLOCK_CTRL, 0);*/ } } + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s] (%d)\n", __func__, enable); } static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) { @@ -361,6 +363,9 @@ static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) return; for (i = 0; i < len; i++) WRITE_VPP_REG(vlock_regs[i].addr, vlock_regs[i].val); + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]\n", __func__); } static void vlock_setting(struct vframe_s *vf, unsigned int input_hz, unsigned int output_hz) @@ -568,19 +573,18 @@ static void vlock_setting(struct vframe_s *vf, else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) /* Input Vsync source select from hdmi-rx */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 16, 3); + + /*enable vlock*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 31, 1); } void vlock_vmode_check(void) { const struct vinfo_s *vinfo; - unsigned int t0, t1, hiu_reg_addr; + unsigned int t0, t1; if (vlock_en == 0) return; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + vinfo = get_current_vinfo(); vlock_vmode_changed = 0; if ((vlock_notify_event == VOUT_EVENT_MODE_CHANGE) || @@ -813,10 +817,13 @@ static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, vlock_sync_limit_flag = 0; vlock_vmode_changed = 0; vlock_dis_cnt = 0; - vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + /*vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE;*/ vlock_pll_stable_cnt = 0; vlock_log_cnt = 0; vlock_enc_stable_flag = 0; + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } void vlock_log_start(void) @@ -944,6 +951,8 @@ static void vlock_enable_step3_enc(void) vlock_reg_get(); vlock_log_cnt++; } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } static void vlock_enable_step3_soft_enc(void) @@ -1052,7 +1061,7 @@ static void vlock_enable_step3_soft_enc(void) WRITE_VPP_REG(ENCL_VIDEO_MAX_LNCNT, pre_enc_max_line + line_adj); if (!(vlock_debug & VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS)) - WRITE_VPP_REG(ENCL_MAX_LINE_SWITCH_POINT, + WRITE_VPP_REG(enc_max_line_switch_addr, pre_enc_max_pixel + pixel_adj); last_i_vsync = READ_VPP_REG(0x3011); @@ -1069,7 +1078,10 @@ static void vlock_enable_step3_soft_enc(void) vlock_reg_get(); vlock_log_cnt++; } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } + /*check pll adj value (0x3020),otherwise may cause blink*/ static void vlock_pll_adj_limit_check(unsigned int *pll_val) { @@ -1092,6 +1104,7 @@ static void vlock_pll_adj_limit_check(unsigned int *pll_val) } } } + static void vlock_enable_step3_pll(void) { unsigned int m_reg_value, tmp_value, abs_val; @@ -2137,16 +2150,16 @@ void vlock_fsm_monitor(struct vframe_s *vf) */ void vlock_process(struct vframe_s *vf) { - if (probe_ok == 0) + if (probe_ok == 0 || !vlock_en) return; if (vlock_debug & VLOCK_DEBUG_FSM_DIS) return; /* todo:vlock processs only for tv chip */ - if (is_meson_gxtvbb_cpu() || - is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_txhd_cpu()) { + if (vlock.dtdata->vlk_new_fsm) + vlock_fsm_monitor(vf); + else { if (vf != NULL) amve_vlock_process(vf); else @@ -2216,6 +2229,7 @@ void vlock_status(void) pr_info("vlock_debug:0x%x\n", vlock_debug); pr_info("vlock_dynamic_adjust:%d\n", vlock_dynamic_adjust); pr_info("vlock_state:%d\n", vlock_state); + pr_info("vecm_latch_flag:0x%x\n", vecm_latch_flag); pr_info("vlock_sync_limit_flag:%d\n", vlock_sync_limit_flag); pr_info("pre_hiu_reg_m:0x%x\n", pre_hiu_reg_m); pr_info("pre_hiu_reg_frac:0x%x\n", pre_hiu_reg_frac); @@ -2296,8 +2310,17 @@ void vlock_reg_dump(void) void vdin_vlock_input_sel(unsigned int type, enum vframe_source_type_e source_type) { + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) + return; + /* + *1:fromhdmi rx , + *2:from tv-decoder, + *3:from dvin, + *4:from dvin, + *5:from 2nd bt656 + */ vlock_intput_type = type & VIDTYPE_TYPEMASK; - if ((vlock_intput_type == 0) || + if ((vlock_intput_type == VIDTYPE_PROGRESSIVE) || (vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) return; if (vlock_intput_type == VIDTYPE_INTERLACE_TOP) { @@ -2377,6 +2400,7 @@ void vlock_param_config(struct device_node *node) vlock_mode &= ~VLOCK_MODE_MANUAL_MIX_PLL_ENC; vlock_mode |= VLOCK_MODE_MANUAL_PLL; } + pr_info("param_config vlock_en:%d\n", vlock_en); } int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, @@ -2425,5 +2449,19 @@ int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, return 0; } +static int __init phlock_phase_config(char *str) +{ + unsigned char *ptr = str; + + pr_info("%s: bootargs is %s.\n", __func__, str); + if (strstr(ptr, "1")) + vlock.phlock_percent = 99; + else + vlock.phlock_percent = 40; + + return 0; +} +__setup("video_reverse=", phlock_phase_config); + /*video lock end*/ From 13e6f8bf4f4e5e94c8cf5c3f553c20ef28655b6a Mon Sep 17 00:00:00 2001 From: Dezhi Kong Date: Mon, 12 Nov 2018 18:00:29 +0800 Subject: [PATCH 0588/1060] vdin: optimize game mode process [1/1] PD#SWPL-2145 Problem: HDMI Rx Video path display latency of Game mode and Normal mode Solution: optimize game mode Verify: T962X-R311 Change-Id: Ib0a41915dfb088495c976d56ab812f90e31602f4 Signed-off-by: Dezhi Kong Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c --- drivers/amlogic/media/vin/tvin/vdin/Makefile | 5 ++ .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 2 +- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 66 ++++++++++++++----- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 11 +++- 4 files changed, 66 insertions(+), 18 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/Makefile b/drivers/amlogic/media/vin/tvin/vdin/Makefile index 7f0c556e4178..b8092e9aa0d4 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/Makefile +++ b/drivers/amlogic/media/vin/tvin/vdin/Makefile @@ -1,6 +1,11 @@ # # Makefile for Vdin. # +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +ccflags-y := -DDEBUG_SUPPORT +else +ccflags-y := -DDEBUG +endif obj-$(CONFIG_AMLOGIC_MEDIA_VDIN) = tvin_vdin.o tvin_vdin-objs += vdin_v4l2.o tvin_vdin-objs += vdin_vf.o diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 2303780d425c..bf2f00dc429d 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -907,7 +907,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("vdin_irq_flag: %d, vdin_rest_flag: %d, irq_cnt: %d, rdma_irq_cnt: %d\n", devp->vdin_irq_flag, devp->vdin_reset_flag, devp->irq_cnt, devp->rdma_irq_cnt); - pr_info("rdma_enable : %d\n", devp->rdma_enable); + pr_info("game_mode : %d\n", devp->game_mode); pr_info("dolby_input : %d\n", devp->dv.dolby_input); if ((devp->cma_config_en != 1) || !(devp->cma_config_flag & 0x100)) pr_info("dolby_mem_start = %ld, dolby_mem_size = %d\n", diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index c5f93547e171..323351c2d5ef 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -87,6 +87,8 @@ static unsigned int use_reserved_mem; static int canvas_config_mode = 2; static bool work_mode_simple; static int max_ignore_frames = 2; +/*game_mode_switch_frames:min num is 5 by 1080p60hz input test*/ +static int game_mode_switch_frames = 10; static int ignore_frames; static unsigned int dv_work_delby; /* viu isr select: @@ -113,6 +115,9 @@ MODULE_PARM_DESC(dv_work_delby, "dv_work_delby"); module_param(viu_hw_irq, bool, 0664); MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); + +module_param(game_mode_switch_frames, int, 0664); +MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch frames"); #endif static bool vdin_dbg_en; @@ -267,10 +272,20 @@ static void vdin_game_mode_check(struct vdin_dev_s *devp) (devp->parm.port != TVIN_PORT_CVBS3)) { if (devp->h_active > 720 && ((devp->parm.info.fps == 50) || (devp->parm.info.fps == 60))) - devp->game_mode = 3; + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); else - devp->game_mode = 1; - } else + devp->game_mode = VDIN_GAME_MODE_0; + } else if (game_mode == 2)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1); + else if (game_mode == 3)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + else if (game_mode == 4)/*for debug force game mode*/ + devp->game_mode = VDIN_GAME_MODE_0; + else if (game_mode == 5)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + else devp->game_mode = 0; } /* @@ -377,10 +392,7 @@ static void vdin_rdma_irq(void *arg) return; } -static struct rdma_op_s vdin_rdma_op = { - vdin_rdma_irq, - NULL -}; +static struct rdma_op_s vdin_rdma_op[VDIN_MAX_DEVS]; #endif /* @@ -539,6 +551,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->abnormal_cnt = 0; devp->last_wr_vfe = NULL; irq_max_count = 0; + vdin_drop_cnt = 0; /* devp->stamp_valid = false; */ devp->stamp = 0; devp->cycle = 0; @@ -615,6 +628,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) #endif devp->irq_cnt = 0; devp->rdma_irq_cnt = 0; + devp->frame_cnt = 0; if (time_en) pr_info("vdin.%d start time: %ums, run time:%ums.\n", devp->index, jiffies_to_msecs(jiffies), @@ -1267,7 +1281,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) goto irq_handled; } if (devp->last_wr_vfe && (devp->flags&VDIN_FLAG_RDMA_ENABLE) && - !(devp->game_mode & (1 << 1))) { + !(devp->game_mode & VDIN_GAME_MODE_1) && + !(devp->game_mode & VDIN_GAME_MODE_2)) { /*dolby vision metadata process*/ if (dv_dbg_mask & DV_UPDATE_DATA_MODE_DELBY_WORK && devp->dv.dv_config) { @@ -1459,8 +1474,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) /*if vdin-nr,di must get * vdin current field type which di pre will read */ - if ((vdin2nr || (devp->flags & VDIN_FLAG_RDMA_ENABLE)) && - !(devp->game_mode & (1 << 1))) + if (vdin2nr || (devp->flags & VDIN_FLAG_RDMA_ENABLE)) curr_wr_vf->type = devp->curr_field_type; else curr_wr_vf->type = last_field_type; @@ -1516,9 +1530,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (devp->parm.port <= TVIN_PORT_CVBS3)) vdin_set_display_ratio(devp, curr_wr_vf); if ((devp->flags&VDIN_FLAG_RDMA_ENABLE) && - !(devp->game_mode & (1 << 1))) { + !(devp->game_mode & VDIN_GAME_MODE_1)) { devp->last_wr_vfe = curr_wr_vfe; - } else { + } else if (!(devp->game_mode & VDIN_GAME_MODE_2)) { /*dolby vision metadata process*/ if (dv_dbg_mask & DV_UPDATE_DATA_MODE_DELBY_WORK && devp->dv.dv_config) { @@ -1552,6 +1566,14 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (devp->vfp->skip_vf_num > 0) vdin_vf_disp_mode_update(curr_wr_vfe, devp->vfp); } + /*switch to game mode 2 from game mode 1,otherwise may appear blink*/ + if ((devp->frame_cnt >= game_mode_switch_frames) && + (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN)) { + if (vdin_dbg_en) + pr_info("switch game mode (%d-->5)\n", devp->game_mode); + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + } + /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); if (devp->afbce_mode == 0) @@ -1574,7 +1596,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) next_wr_vfe->vf.ready_clock[0] = sched_clock(); if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || - (devp->game_mode & (1 << 1))) { + (devp->game_mode & VDIN_GAME_MODE_1)) { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (((devp->dv.dolby_input & (1 << devp->index)) || (devp->dv.dv_flag && is_dolby_vision_enable())) && @@ -1585,7 +1607,18 @@ irqreturn_t vdin_isr(int irq, void *dev_id) #endif vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else if (devp->game_mode & VDIN_GAME_MODE_2) { + provider_vf_put(next_wr_vfe, devp->vfp); + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (vdin_dbg_en) { + next_wr_vfe->vf.ready_clock[1] = sched_clock(); + pr_info("vdin put latency %lld us. first %lld us.\n", + func_div(next_wr_vfe->vf.ready_clock[1], 1000), + func_div(next_wr_vfe->vf.ready_clock[0], 1000)); + } } + devp->frame_cnt++; irq_handled: /*hdmi skip policy should adapt to all drop vframe case*/ @@ -2442,9 +2475,10 @@ static int vdin_drv_probe(struct platform_device *pdev) } } vdin_devp[vdevp->index] = vdevp; -#ifdef CONFIG_AML_RDMA - vdin_rdma_op.arg = vdin_devp; - vdevp->rdma_handle = rdma_register(&vdin_rdma_op, +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + vdin_rdma_op[vdevp->index].irq_cb = vdin_rdma_irq; + vdin_rdma_op[vdevp->index].arg = vdevp; + vdevp->rdma_handle = rdma_register(&vdin_rdma_op[vdevp->index], NULL, RDMA_TABLE_SIZE); pr_info("%s:vdin.%d rdma hanld %d.\n", __func__, vdevp->index, vdevp->rdma_handle); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 2ffd0eba9ccd..b1c4605f689e 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -45,7 +45,7 @@ #include "vdin_vf.h" #include "vdin_regs.h" -#define VDIN_VER "Ref.2018/11/07a" +#define VDIN_VER "Ref.2018/11/21a" /*the counter of vdin*/ #define VDIN_MAX_DEVS 2 @@ -85,6 +85,12 @@ #define VDIN_BYPASS_VGA_CHECK 0x00000008 #define VDIN_CANVAS_MAX_CNT 9 +/*values of vdin game mode process flag */ +#define VDIN_GAME_MODE_0 (1 << 0) +#define VDIN_GAME_MODE_1 (1 << 1) +#define VDIN_GAME_MODE_2 (1 << 2) +#define VDIN_GAME_MODE_SWITCH_EN (1 << 3) + /*flag for flush vdin buff*/ #define VDIN_FLAG_BLACK_SCREEN_ON 1 #define VDIN_FLAG_BLACK_SCREEN_OFF 0 @@ -312,6 +318,8 @@ struct vdin_dev_s { *game_mode: *bit0:enable/disable *bit1:for true bypas and put vframe in advance one vsync + *bit2:for true bypas and put vframe in advance two vsync, + *vdin & vpp read/write same buffer may happen */ unsigned int game_mode; unsigned int rdma_enable; @@ -330,6 +338,7 @@ struct vdin_dev_s { /*use frame rate to cal duraton*/ unsigned int use_frame_rate; unsigned int irq_cnt; + unsigned int frame_cnt; unsigned int rdma_irq_cnt; unsigned int vdin_irq_flag; unsigned int vdin_reset_flag; From 5377cc1d10541b034359a6beb255911c8707bff9 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Thu, 13 Dec 2018 17:16:31 +0800 Subject: [PATCH 0589/1060] tvin: vdin: vdin afbce fix header size bug [1/1] PD#SWPL-3208 Problem: vdin afbce scaler, display abnormal. Solution: fix afbce header size problem. Verify: TL1 X301 Change-Id: I461b4aa809ceddbe18cf7f6f49e8152b43b86076 Signed-off-by: Xuhua Zhang Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c --- drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index f463278d2098..d431e3449aae 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -72,8 +72,8 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) CODEC_MM_FLAGS_DMA; unsigned int max_buffer_num = min_buf_num; unsigned int i; - /*afbce head need 1036800 byte at most*/ - unsigned int afbce_head_size_byte = PAGE_SIZE * 300;/*1.2M*/ + /*head_size:3840*2160*3*9/32*/ + unsigned int afbce_head_size_byte = PAGE_SIZE * 1712; /*afbce map_table need 218700 byte at most*/ unsigned int afbce_table_size_byte = PAGE_SIZE * 60;/*0.3M*/ unsigned int afbce_mem_used; @@ -283,7 +283,7 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) /* 1 block = 32 * 4 pixle = 128 pixel */ /* there is a header in one block, a header has 4 bytes */ /* set fm_head_paddr start */ - frame_head_size = roundup(devp->h_active * devp->v_active, 128); + frame_head_size = (int)roundup(devp->vfmem_size, 128); /*h_active * v_active / 128 * 4 = frame_head_size*/ frame_head_size = devp->h_active * devp->v_active / 32; frame_head_size = PAGE_ALIGN(frame_head_size); From 3a82a83266f8bfc1c9ee3e3a5cfaf7de02ea4277 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Fri, 28 Dec 2018 14:58:49 +0800 Subject: [PATCH 0590/1060] tvin: vdin: add vdin afbce memory power ctrl [1/1] PD#SWPL-3635 Problem: Miss vdin afbce memory power ctrl. Solution: Add vdin afbce memory power ctrl. Verify: x301_tl1 Change-Id: I94946e3d16027083688735d68b9d023b6bc5c8bf Signed-off-by: Xuhua Zhang Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c --- .../amlogic/media/vin/tvin/vdin/vdin_afbce.c | 175 +++++++++++++----- .../amlogic/media/vin/tvin/vdin/vdin_afbce.h | 7 +- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 2 + .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 50 ++++- 4 files changed, 182 insertions(+), 52 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index d431e3449aae..c003c62b232b 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -370,35 +370,47 @@ void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, if (offset == 0) { if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_AFBCE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN0_OUT_MIF_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 0, VDIN0_OUT_AFBCE_BIT, 1); } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_AFBCE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 0, VDIN0_OUT_MIF_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN0_OUT_AFBCE_BIT, 1); } } else { if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_AFBCE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN1_MIF_ENABLE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN1_OUT_MIF_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 0, VDIN1_OUT_AFBCE_BIT, 1); } else if (sel == VDIN_OUTPUT_TO_AFBCE) { /*sel vdin1 afbce: not support in sw now, *just reserved interface */ - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_AFBCE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN1_MIF_ENABLE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 0, VDIN1_OUT_MIF_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN1_OUT_AFBCE_BIT, 1); } } } - +/* static void afbce_wr(uint32_t reg, const uint32_t val) { wr(0, reg, val); } - +*/ void vdin_afbce_config(struct vdin_dev_s *devp) { unsigned int offset = devp->addr_offset; @@ -432,6 +444,12 @@ void vdin_afbce_config(struct vdin_dev_s *devp) return; } +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA + pr_info("##############################################\n"); + pr_info("vdin afbce must use RDMA,but it not be opened\n"); + pr_info("##############################################\n"); +#endif + enc_win_bgn_h = 0; enc_win_end_h = devp->h_active - 1; enc_win_bgn_v = 0; @@ -467,103 +485,137 @@ void vdin_afbce_config(struct vdin_dev_s *devp) //bit size of uncompression mode uncmp_size = (((((16*uncmp_bits*sblk_num)+7)>>3)+31)/32)<<1; - W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 3, 1);//vpu arb axi_enable - W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 7, 1);//vpu arb axi_enable + rdma_write_reg_bits(devp->rdma_handle, + VDIN_WRARB_REQEN_SLV, 0x1, 3, 1);//vpu arb axi_enable + rdma_write_reg_bits(devp->rdma_handle, + VDIN_WRARB_REQEN_SLV, 0x1, 7, 1);//vpu arb axi_enable - afbce_wr(AFBCE_MODE, + rdma_write_reg(devp->rdma_handle, AFBCE_MODE, (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | (hold_line_num & 0x7f) << 16 | (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); - W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_luma_en & 0x1), 0, 1);//loosy - W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_chrm_en & 0x1), 4, 1);//loosy + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_QUANT_ENABLE, (lossy_luma_en & 0x1), 0, 1);//loosy + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_QUANT_ENABLE, (lossy_chrm_en & 0x1), 4, 1);//loosy - afbce_wr(AFBCE_SIZE_IN, + if (devp->afbce_lossy_en == 1) { + rdma_write_reg(devp->rdma_handle, + AFBCE_QUANT_ENABLE, 0xc11); + pr_info("afbce use lossy compression mode\n"); + } + + rdma_write_reg(devp->rdma_handle, AFBCE_SIZE_IN, ((devp->h_active & 0x1fff) << 16) | // hsize_in of afbc input ((devp->v_active & 0x1fff) << 0) // vsize_in of afbc input ); - afbce_wr(AFBCE_BLK_SIZE_IN, + rdma_write_reg(devp->rdma_handle, AFBCE_BLK_SIZE_IN, ((hblksize_out & 0x1fff) << 16) | // out blk hsize ((vblksize_out & 0x1fff) << 0) // out blk vsize ); //head addr of compressed data - afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[0]); + rdma_write_reg(devp->rdma_handle, AFBCE_HEAD_BADDR, + devp->afbce_info->fm_head_paddr[0]); - W_VCBUS_BIT(AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);//uncmp_size + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);//uncmp_size /* how to set reg when we use crop ? */ // scope of hsize_in ,should be a integer multipe of 32 // scope of vsize_in ,should be a integer multipe of 4 - afbce_wr(AFBCE_PIXEL_IN_HOR_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_PIXEL_IN_HOR_SCOPE, ((enc_win_end_h & 0x1fff) << 16) | ((enc_win_bgn_h & 0x1fff) << 0)); // scope of hsize_in ,should be a integer multipe of 32 // scope of vsize_in ,should be a integer multipe of 4 - afbce_wr(AFBCE_PIXEL_IN_VER_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_PIXEL_IN_VER_SCOPE, ((enc_win_end_v & 0x1fff) << 16) | ((enc_win_bgn_v & 0x1fff) << 0)); - afbce_wr(AFBCE_CONV_CTRL, lbuf_depth);//fix 256 + rdma_write_reg(devp->rdma_handle, + AFBCE_CONV_CTRL, lbuf_depth);//fix 256 - afbce_wr(AFBCE_MIF_HOR_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_MIF_HOR_SCOPE, ((blk_out_bgn_h & 0x3ff) << 16) | // scope of out blk hsize ((blk_out_end_h & 0xfff) << 0) // scope of out blk vsize ); - afbce_wr(AFBCE_MIF_VER_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_MIF_VER_SCOPE, ((blk_out_bgn_v & 0x3ff) << 16) | // scope of out blk hsize ((blk_out_end_v & 0xfff) << 0) // scope of out blk vsize ); - afbce_wr(AFBCE_FORMAT, + rdma_write_reg(devp->rdma_handle, AFBCE_FORMAT, (reg_format_mode & 0x3) << 8 | (uncmp_bits & 0xf) << 4 | (uncmp_bits & 0xf)); - afbce_wr(AFBCE_DEFCOLOR_1, + rdma_write_reg(devp->rdma_handle, AFBCE_DEFCOLOR_1, ((def_color_3 & 0xfff) << 12) | // def_color_a ((def_color_0 & 0xfff) << 0) // def_color_y ); - afbce_wr(AFBCE_DEFCOLOR_2, + rdma_write_reg(devp->rdma_handle, AFBCE_DEFCOLOR_2, ((def_color_2 & 0xfff) << 12) | // def_color_v ((def_color_1 & 0xfff) << 0) // def_color_u ); - //cur_mmu_used += Rd(AFBCE_MMU_NUM); //4k addr have used in every frame; + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MMU_RMIF_CTRL4, devp->afbce_info->table_paddr, 0, 32); + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - W_VCBUS_BIT(AFBCE_MMU_RMIF_CTRL4, devp->afbce_info->table_paddr, 0, 32); - W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - - W_VCBUS_BIT(AFBCE_ENABLE, 1, 8, 1);//enable afbce + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_ENABLE, 1, 12, 1); //set afbce pulse mode + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_ENABLE, 0, 8, 1);//disable afbce } void vdin_afbce_maptable_init(struct vdin_dev_s *devp) { unsigned int i, j; - unsigned int *ptable = NULL; + unsigned int highmem_flag = 0; + unsigned long ptable = 0; unsigned int *vtable = NULL; unsigned int body; unsigned int size; size = roundup(devp->afbce_info->frame_body_size, 4096); + ptable = devp->afbce_info->fm_table_paddr[0]; + if (devp->cma_config_flag == 0x101) + highmem_flag = PageHighMem(phys_to_page(ptable)); + else + highmem_flag = PageHighMem(phys_to_page(ptable)); + for (i = 0; i < devp->vfmem_max_cnt; i++) { - ptable = (unsigned int *) - (devp->afbce_info->fm_table_paddr[i]&0xffffffff); - if (devp->cma_config_flag == 0x101) - vtable = codec_mm_phys_to_virt((unsigned long)ptable); - else if (devp->cma_config_flag == 0) - vtable = phys_to_virt((unsigned long)ptable); + ptable = devp->afbce_info->fm_table_paddr[i]; + if (highmem_flag == 0) { + if (devp->cma_config_flag == 0x101) + vtable = codec_mm_phys_to_virt(ptable); + else if (devp->cma_config_flag == 0) + vtable = phys_to_virt(ptable); + else + vtable = phys_to_virt(ptable); + } else { + vtable = (unsigned int *)codec_mm_vmap( + ptable, + devp->afbce_info->frame_table_size); + } + body = devp->afbce_info->fm_body_paddr[i]&0xffffffff; for (j = 0; j < size; j += 4096) { *vtable = ((j + body) >> 12) & 0x000fffff; vtable++; } + + if (highmem_flag) + codec_mm_unmap_phyaddr((void *)vtable); } } @@ -584,7 +636,40 @@ void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); else #endif - afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); - W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); + { + pr_info("afbce must use RDMA.\n"); + } + + vdin_afbce_clear_writedown_flag(devp); } +void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp) +{ + rdma_write_reg(devp->rdma_handle, AFBCE_CLR_FLAG, 1); +} + +/* return 1: write down*/ +int vdin_afbce_read_writedown_flag(void) +{ + int val1, val2; + + val1 = rd_bits(0, AFBCE_STA_FLAGT, 0, 1); + val2 = rd_bits(0, AFBCE_STA_FLAGT, 2, 2); + + if ((val1 == 1) || (val2 == 0)) + return 1; + else + return 0; +} + +void vdin_afbce_hw_disable(void) +{ + /*can not use RDMA*/ + W_VCBUS_BIT(AFBCE_ENABLE, 0, 8, 1);//disable afbce +} + +void vdin_afbce_hw_enable(struct vdin_dev_s *devp) +{ + //enable afbce + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 8, 1); +} diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h index feb2d086eca4..9cc81e3a47f6 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h @@ -307,7 +307,10 @@ extern void vdin_afbce_cma_release(struct vdin_dev_s *devp); extern void vdin_afbce_config(struct vdin_dev_s *devp); extern void vdin_afbce_maptable_init(struct vdin_dev_s *devp); extern void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, -unsigned int rdma_enable, struct vf_entry *vfe); - + unsigned int rdma_enable, struct vf_entry *vfe); +extern void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp); +extern int vdin_afbce_read_writedown_flag(void); +extern void vdin_afbce_hw_disable(void); +extern void vdin_afbce_hw_enable(struct vdin_dev_s *devp); #endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index bf2f00dc429d..d23608a1760a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -558,6 +558,7 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, } vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos); + codec_mm_unmap_phyaddr(buf_head); pr_info("write buffer %2d of %2u head to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -573,6 +574,7 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos); + codec_mm_unmap_phyaddr(buf_table); pr_info("write buffer %2d of %2u table to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 323351c2d5ef..edff45914d7f 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -78,6 +78,8 @@ static unsigned int vdin_addr_offset[VDIN_MAX_DEVS] = {0, 0x80}; static struct vdin_dev_s *vdin_devp[VDIN_MAX_DEVS]; static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; +static int afbc_init_flag; +static int afbc_write_down_flag; /* * canvas_config_mode * 0: canvas_config in driver probe @@ -421,10 +423,10 @@ void vdin_start_dec(struct vdin_dev_s *devp) pr_info("[vdin]%s null error.\n", __func__); return; } + if (devp->frontend && devp->frontend->sm_ops) { sm_ops = devp->frontend->sm_ops; sm_ops->get_sig_property(devp->frontend, &devp->prop); - if (!(devp->flags & VDIN_FLAG_V4L2_DEBUG)) devp->parm.info.cfmt = devp->prop.color_format; if ((devp->parm.dest_width != 0) || @@ -447,7 +449,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->prop.ve = devp->debug.cutwin.ve; } } - /*gxbb/gxl/gxm use clkb as vdin clk, *for clkb is low speed,wich is enough for 1080p process, *gxtvbb/txl use vpu clk for process 4k @@ -488,7 +489,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) vdin_fix_nonstd_vsync(devp); - /*reverse / disable reverse write buffer*/ vdin_wr_reverse(devp->addr_offset, devp->parm.h_reverse, @@ -509,6 +509,8 @@ void vdin_start_dec(struct vdin_dev_s *devp) } } #endif + + afbc_write_down_flag = 0; /* h_active/v_active will be used by bellow calling */ if (devp->afbce_mode == 0) { if (canvas_config_mode == 1) @@ -519,6 +521,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_afbce_maptable_init(devp); vdin_afbce_config(devp); } + #if 0 if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) @@ -629,6 +632,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->irq_cnt = 0; devp->rdma_irq_cnt = 0; devp->frame_cnt = 0; + if (time_en) pr_info("vdin.%d start time: %ums, run time:%ums.\n", devp->index, jiffies_to_msecs(jiffies), @@ -645,6 +649,8 @@ void vdin_start_dec(struct vdin_dev_s *devp) */ void vdin_stop_dec(struct vdin_dev_s *devp) { + int afbc_write_down_test_times = 7; + /* avoid null pointer oops */ if (!devp || !devp->frontend) return; @@ -655,7 +661,15 @@ void vdin_stop_dec(struct vdin_dev_s *devp) } #endif disable_irq_nosync(devp->irq); - vdin_hw_disable(devp->addr_offset); + afbc_init_flag = 0; + + while (++afbc_write_down_flag < afbc_write_down_test_times) { + if (vdin_afbce_read_writedown_flag() == 0) + usleep_range(5000, 5001); + else + break; + } + if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && devp->frontend->dec_ops && devp->frontend->dec_ops->stop && @@ -663,6 +677,8 @@ void vdin_stop_dec(struct vdin_dev_s *devp) ((devp->flags & VDIN_FLAG_SNOW_FLAG) == 0))) devp->frontend->dec_ops->stop(devp->frontend, devp->parm.port); + vdin_hw_disable(devp->addr_offset); + vdin_set_default_regmap(devp->addr_offset); /*only for vdin0*/ if (devp->urgent_en && (devp->index == 0)) @@ -679,6 +695,10 @@ void vdin_stop_dec(struct vdin_dev_s *devp) #endif vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; + + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + vdin_afbce_hw_disable(); + #ifdef CONFIG_CMA if (devp->afbce_mode == 1) vdin_afbce_cma_release(devp); @@ -687,7 +707,6 @@ void vdin_stop_dec(struct vdin_dev_s *devp) #endif vdin_dolby_addr_release(devp, devp->vfp->size); - switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0, VPU_MEM_POWER_DOWN); memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s)); @@ -1201,6 +1220,8 @@ static u64 func_div(u64 cur, u32 divid) return cur; } + + /* *VDIN_FLAG_RDMA_ENABLE=1 * provider_vf_put(devp->last_wr_vfe, devp->vfp); @@ -1251,6 +1272,19 @@ irqreturn_t vdin_isr(int irq, void *dev_id) offset = devp->addr_offset; + if (afbc_init_flag == 0) { + afbc_init_flag = 1; + /*set mem power on*/ + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + vdin_afbce_hw_enable(devp); + return IRQ_HANDLED; + } + } else if (afbc_init_flag == 1) { + afbc_init_flag = 2; + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + return IRQ_HANDLED; + } + isr_log(devp->vfp); devp->irq_cnt++; /* debug interrupt interval time @@ -1872,6 +1906,9 @@ static int vdin_open(struct inode *inode, struct file *file) return 0; } + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_ON); + devp->flags |= VDIN_FLAG_FS_OPENED; /* request irq */ @@ -1917,6 +1954,9 @@ static int vdin_release(struct inode *inode, struct file *file) return 0; } + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_DOWN); + devp->flags &= (~VDIN_FLAG_FS_OPENED); if (devp->flags & VDIN_FLAG_DEC_STARTED) { devp->flags |= VDIN_FLAG_DEC_STOP_ISR; From fd574b0180f4e5427901cafe803e099ada17d041 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Thu, 16 May 2019 15:19:02 +0900 Subject: [PATCH 0591/1060] ODROID:Merge BSP 2019.04 (fix build err.) Change-Id: Ib0add39b6824cb0abafe96e9bd514770d5f437e5 --- drivers/amlogic/cec/hdmi_ao_cec.c | 65 +++++++++--- drivers/amlogic/cec/hdmi_ao_cec.h | 5 +- drivers/amlogic/cpufreq/meson-cpufreq.c | 128 +++++++++++++++++++++--- drivers/amlogic/cpufreq/meson-cpufreq.h | 10 ++ drivers/amlogic/efuse/efuse_hw64.c | 12 +-- 5 files changed, 186 insertions(+), 34 deletions(-) diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 264925381deb..bda868058e9c 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -65,7 +65,7 @@ static struct early_suspend aocec_suspend_handler; #define CEC_FRAME_DELAY msecs_to_jiffies(400) -#define CEC_DEV_NAME "aocec" +#define CEC_DEV_NAME "cec" #define CEC_POWER_ON (0 << 0) #define CEC_EARLY_SUSPEND (1 << 0) @@ -484,6 +484,49 @@ static inline void cecrx_clear_irq(unsigned int flags) writel(flags, cec_dev->cec_reg + AO_CECB_INTR_CLR); } +/* max length = 14+1 */ +#define OSD_NAME_DEV 1 +const uint8_t dev_osd_name[1][16] = { + {1, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x63, 0x61, 0x73, 0x74}, +}; + +const uint8_t dev_vendor_id[1][3] = { + {0, 0, 0}, +}; + +static bool cec_message_op(unsigned char *msg, unsigned char len) +{ + int i, j; + + if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) { + CEC_ERR("bad iniator with self:%s", msg_log_buf); + return false; + } + switch (msg[1]) { + case 0x47: + /* OSD name */ + if (len > 16) + break; + for (j = 0; j < OSD_NAME_DEV; j++) { + for (i = 2; i < len; i++) { + if (msg[i] != dev_osd_name[j][i-1]) + break; + } + if (i == len) { + cec_set_dev_info(dev_osd_name[j][0]); + CEC_INFO("specific dev:%d", dev_osd_name[j][0]); + } + } + break; + case 0x87: + /* verdor ID */ + break; + default: + break; + } + return true; +} + static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) { int i, size; @@ -500,11 +543,10 @@ static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) /* clr CEC lock bit */ hdmirx_cec_write(DWC_CEC_LOCK, 0); CEC_INFO("%s", msg_log_buf); - if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) { - *out_len = 0; - CEC_ERR("bad iniator with self:%s", msg_log_buf); - } else + if (cec_message_op(msg, len)) *out_len = len; + else + *out_len = 0; pin_status = 1; return 0; } @@ -521,6 +563,8 @@ void cecb_irq_handle(void) /* clear irq */ if (intr_cec != 0) cecrx_clear_irq(intr_cec); + else + CEC_INFO_L(L_1, "err cec intsts:0\n"); if (cec_dev->plat_data->ee_to_ao) shift = 16; @@ -654,7 +698,7 @@ static void ao_cecb_init(void) /* Release SW reset */ cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); - if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) { reg = 0; reg |= (0 << 6);/*curb_err_init*/ reg |= (0 << 5);/*en_chk_sbitlow*/ @@ -2627,11 +2671,6 @@ static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf, if (cec_cfg & CEC_FUNC_CFG_CEC_ON) { /*cec module on*/ ret = cec_ll_tx(tempbuf, size); - if (ret == CEC_FAIL_NACK) { - return -1; - } else { - return size; - } } else { CEC_ERR("err:cec module disabled\n"); } @@ -3016,7 +3055,9 @@ static char *aml_cec_class_devnode(struct device *dev, umode_t *mode) { if (mode) { *mode = 0666; - } + CEC_INFO("mode is %x\n", *mode); + } else + CEC_INFO("mode is null\n"); return NULL; } diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index e5f5fbb95f71..5613c5cf66f3 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -23,7 +23,7 @@ #define CEC_DRIVER_VERSION "Ver 2019/3/25\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) -#define CEC_DEV_NAME "aocec" +#define CEC_DEV_NAME "cec" #define CEC_EARLY_SUSPEND (1 << 0) #define CEC_DEEP_SUSPEND (1 << 1) @@ -494,7 +494,8 @@ extern uint32_t hdmirx_rd_dwc(uint16_t addr); extern void hdmirx_wr_dwc(uint16_t addr, uint32_t data); extern unsigned int rd_reg_hhi(unsigned int offset); extern void wr_reg_hhi(unsigned int offset, unsigned int val); - +extern int cec_set_dev_info(uint8_t dev_idx); +int __attribute__((weak))cec_set_dev_info(uint8_t dev_idx); #else static inline unsigned long hdmirx_rd_top(unsigned long addr) { diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index 2f0c26edfd3f..019ab621d695 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -43,6 +43,16 @@ #include "../../base/power/opp/opp.h" #include "meson-cpufreq.h" +#ifdef CONFIG_ARCH_MESON64_ODROIDN2 +#define OF_NODE_CPU_OPP_0 "/cpu_opp_table0/" /* Core A53 */ +#define OF_NODE_CPU_OPP_1 "/cpu_opp_table1/" /* Core A73 */ + +static unsigned long max_freq[2] = { + 1896000, /* defalut freq for A53 is 1.896GHz */ + 1800000 /* defalut freq for A73 is 1.800GHz */ +}; +#endif + static unsigned int meson_cpufreq_get_rate(unsigned int cpu) { @@ -261,7 +271,10 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, } } + freqs.old = freq_old / 1000; + freqs.new = freq_new / 1000; /*scale clock frequency*/ + cpufreq_freq_transition_begin(policy, &freqs); ret = meson_cpufreq_set_rate(policy, cur_cluster, freq_new / 1000); if (ret) { @@ -274,6 +287,7 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, } return ret; } + cpufreq_freq_transition_end(policy, &freqs, ret); /*cpufreq down,change voltage after frequency*/ if (freq_new < freq_old) { ret = meson_regulator_set_volate(cpu_reg, volt_old, @@ -281,8 +295,12 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, if (ret) { pr_err("failed to scale volt %u %u down: %d\n", volt_new, volt_tol, ret); - meson_cpufreq_set_rate(policy, cur_cluster, + freqs.old = freq_new / 1000; + freqs.new = freq_old / 1000; + cpufreq_freq_transition_begin(policy, &freqs); + ret = meson_cpufreq_set_rate(policy, cur_cluster, freq_old / 1000); + cpufreq_freq_transition_end(policy, &freqs, ret); } } @@ -368,6 +386,69 @@ int choose_cpufreq_tables_index(const struct device_node *np, u32 cur_cluster) return ret; } + +static int meson_cpufreq_transition_notifier(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + struct meson_cpufreq_driver_data *cpufreq_data = + to_meson_dvfs_cpu_nb(nb); + struct cpufreq_policy *policy = cpufreq_data->policy; + struct clk *dsu_clk = cpufreq_data->clk_dsu; + struct clk *dsu_cpu_parent = policy->clk; + struct clk *dsu_pre_parent = cpufreq_data->clk_dsu_pre; + int ret = 0; + static bool first_set = true; + + if (!dsu_clk || !dsu_cpu_parent || !dsu_pre_parent) + return 0; + + pr_debug("%s,event %ld,freq->old_rate =%u,freq->new_rate =%u!\n", + __func__, val, freq->old, freq->new); + switch (val) { + case CPUFREQ_PRECHANGE: + if (freq->new > MID_RATE) { + pr_debug("%s,dsu clk switch parent to dsu pre!\n", + __func__); + if (first_set) { + clk_set_rate(dsu_pre_parent, MID_RATE * 1000); + first_set = false; + pr_info("first set gp1 pll to 1.5G!\n"); + } + if (__clk_get_enable_count(dsu_pre_parent) == 0) { + ret = clk_prepare_enable(dsu_pre_parent); + if (ret) { + pr_err("%s: CPU%d gp1 pll enable failed\n", + __func__, policy->cpu); + return ret; + } + } + + ret = clk_set_parent(dsu_clk, dsu_pre_parent); + } + + return ret; + case CPUFREQ_POSTCHANGE: + if (freq->new <= MID_RATE) { + pr_debug("%s,dsu clk switch parent to cpu!\n", + __func__); + ret = clk_set_parent(dsu_clk, dsu_cpu_parent); + if (__clk_get_enable_count(dsu_pre_parent) >= 1) + clk_disable_unprepare(dsu_pre_parent); + + } + + return ret; + default: + return 0; + } + return 0; +} + +static struct notifier_block meson_cpufreq_notifier_block = { + .notifier_call = meson_cpufreq_transition_notifier, +}; + /* CPU initialization */ static int meson_cpufreq_init(struct cpufreq_policy *policy) { @@ -377,10 +458,14 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) struct regulator *cpu_reg = NULL; struct meson_cpufreq_driver_data *cpufreq_data; struct clk *low_freq_clk_p, *high_freq_clk_p = NULL; + struct clk *dsu_clk, *dsu_pre_parent; unsigned int transition_latency = CPUFREQ_ETERNAL; unsigned int volt_tol = 0; unsigned long freq_hz = 0; int cpu = 0, ret = 0, tables_index; +#ifdef CONFIG_ARCH_MESON64_ODROIDN2 + int i = 0; +#endif if (!policy) { pr_err("invalid cpufreq_policy\n"); @@ -441,6 +526,18 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) goto free_clk; } + dsu_clk = of_clk_get_by_name(np, DSU_CLK); + if (IS_ERR(dsu_clk)) { + dsu_clk = NULL; + pr_debug("%s: ignor dsu clk!\n", __func__); + } + + dsu_pre_parent = of_clk_get_by_name(np, DSU_PRE_PARENT); + if (IS_ERR(dsu_pre_parent)) { + dsu_pre_parent = NULL; + pr_debug("%s: ignor dsu pre parent clk!\n", __func__); + } + cpu_reg = devm_regulator_get(cpu_dev, CORE_SUPPLY); if (IS_ERR(cpu_reg)) { pr_err("%s:failed to get regulator, %ld\n", __func__, @@ -495,11 +592,22 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) if (of_property_read_u32(np, "clock-latency", &transition_latency)) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpufreq_data->freq_transition = meson_cpufreq_notifier_block; + ret = cpufreq_register_notifier(&cpufreq_data->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { + dev_err(cpu_dev, "failed to register cpufreq notifier!\n"); + goto fail_cpufreq_unregister; + } + cpufreq_data->cpu_dev = cpu_dev; cpufreq_data->low_freq_clk_p = low_freq_clk_p; cpufreq_data->high_freq_clk_p = high_freq_clk_p; + cpufreq_data->clk_dsu = dsu_clk; + cpufreq_data->clk_dsu_pre = dsu_pre_parent; cpufreq_data->reg = cpu_reg; cpufreq_data->volt_tol = volt_tol; + cpufreq_data->policy = policy; policy->driver_data = cpufreq_data; policy->clk = clk[cur_cluster]; policy->cpuinfo.transition_latency = transition_latency; @@ -520,6 +628,9 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu); return ret; +fail_cpufreq_unregister: + cpufreq_unregister_notifier(&cpufreq_data->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); free_opp_table: if (policy->freq_table != NULL) { dev_pm_opp_free_cpufreq_table(cpu_dev, @@ -638,7 +749,8 @@ static struct cpufreq_driver meson_cpufreq_driver = { .name = "arm-big-little", .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | - CPUFREQ_NEED_INITIAL_FREQ_CHECK, + CPUFREQ_NEED_INITIAL_FREQ_CHECK | + CPUFREQ_ASYNC_NOTIFICATION, .verify = cpufreq_generic_frequency_table_verify, .target_index = meson_cpufreq_set_target, .get = meson_cpufreq_get_rate, @@ -649,8 +761,6 @@ static struct cpufreq_driver meson_cpufreq_driver = { .resume = meson_cpufreq_resume, }; -static int meson_cpufreq_register_notifier(void) { return 0; } -static int meson_cpufreq_unregister_notifier(void) { return 0; } static int meson_cpufreq_probe(struct platform_device *pdev) { struct device *cpu_dev; @@ -688,14 +798,6 @@ static int meson_cpufreq_probe(struct platform_device *pdev) if (ret) { pr_err("%s: Failed registering platform driver, err: %d\n", __func__, ret); - } else { - ret = meson_cpufreq_register_notifier(); - if (ret) { - cpufreq_unregister_driver(&meson_cpufreq_driver); - } else { - pr_err("%s: Registered platform drive\n", - __func__); - } } return ret; @@ -703,8 +805,6 @@ static int meson_cpufreq_probe(struct platform_device *pdev) static int meson_cpufreq_remove(struct platform_device *pdev) { - meson_cpufreq_unregister_notifier(); - return cpufreq_unregister_driver(&meson_cpufreq_driver); } diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.h b/drivers/amlogic/cpufreq/meson-cpufreq.h index be5002697042..d5508c5a3f37 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.h +++ b/drivers/amlogic/cpufreq/meson-cpufreq.h @@ -27,6 +27,10 @@ #define CORE_CLK "core_clk" #define LOW_FREQ_CLK_PARENT "low_freq_clk_parent" #define HIGH_FREQ_CLK_PARENT "high_freq_clk_parent" +#define DSU_CLK "dsu_clk" +#define DSU_PRE_PARENT "dsu_pre_parent" +#define to_meson_dvfs_cpu_nb(_nb) container_of(_nb, \ + struct meson_cpufreq_driver_data, freq_transition) static struct clk *clk[MAX_CLUSTERS]; static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; @@ -38,6 +42,8 @@ static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; /*mid rate for set parent,Khz*/ static unsigned int mid_rate = (1000 * 1000); static unsigned int gap_rate = (10 * 1000 * 1000); +static struct cpufreq_freqs freqs; +#define MID_RATE (1500 * 1000) /*whether use different tables or not*/ bool cpufreq_tables_supply; @@ -53,10 +59,14 @@ enum cpufreq_index { struct meson_cpufreq_driver_data { struct device *cpu_dev; struct regulator *reg; + struct cpufreq_policy *policy; /* voltage tolerance in percentage */ unsigned int volt_tol; struct clk *high_freq_clk_p; struct clk *low_freq_clk_p; + struct clk *clk_dsu; + struct clk *clk_dsu_pre; + struct notifier_block freq_transition; }; static struct mutex cluster_lock[MAX_CLUSTERS]; diff --git a/drivers/amlogic/efuse/efuse_hw64.c b/drivers/amlogic/efuse/efuse_hw64.c index 4e4ae939300c..f73959033bf9 100644 --- a/drivers/amlogic/efuse/efuse_hw64.c +++ b/drivers/amlogic/efuse/efuse_hw64.c @@ -33,7 +33,7 @@ #include #include -static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) +static long meson64_efuse_fn_smc(struct efuse_hal_api_arg *arg) { long ret; unsigned int cmd, offset, size; @@ -71,7 +71,7 @@ static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) return 0; } -int meson_trustzone_efuse(struct efuse_hal_api_arg *arg) +int meson64_trustzone_efuse(struct efuse_hal_api_arg *arg) { int ret; struct cpumask org_cpumask; @@ -103,7 +103,7 @@ unsigned long efuse_aml_sec_boot_check(unsigned long nType, memcpy((void *)sharemem_input_base, (const void *)pBuffer, nLength); - __flush_dcache_area(sharemem_input_base, nLength); + //__flush_dcache_area(sharemem_input_base, nLength); asm __volatile__("" : : : "memory"); @@ -137,7 +137,7 @@ unsigned long efuse_amlogic_set(char *buf, size_t count) return ret; } -ssize_t meson_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) +ssize_t meson64_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) { ssize_t ret; unsigned int cmd; @@ -193,7 +193,7 @@ ssize_t _efuse_read(char *buf, size_t count, loff_t *ppos) arg.size = count; arg.buffer = (unsigned long)buf; arg.retcnt = (unsigned long)&retcnt; - ret = meson_trustzone_efuse(&arg); + ret = meson64_trustzone_efuse(&arg); if (ret == 0) { *ppos += retcnt; return retcnt; @@ -217,7 +217,7 @@ ssize_t _efuse_write(const char *buf, size_t count, loff_t *ppos) arg.buffer = (unsigned long)buf; arg.retcnt = (unsigned long)&retcnt; - ret = meson_trustzone_efuse(&arg); + ret = meson64_trustzone_efuse(&arg); if (ret == 0) { *ppos = retcnt; return retcnt; From 2f83851d0efa345459fe25a33f8abfd8a0f24b60 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Tue, 8 Jan 2019 15:35:23 +0800 Subject: [PATCH 0592/1060] tvin: vdin: fix TXLX ATv channel switching crash [1/1] PD#SWPL-3964 Problem: ATv channel switching crash Solution: stop vdin, close afbc need judge platform, there is not afbce on txlx Verify: verify by einstein Change-Id: Ibcff1da47b9fdca7e1758b0d45e7d6800bfc8080 Signed-off-by: Xuhua Zhang --- drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index edff45914d7f..55772068a67f 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -663,11 +663,13 @@ void vdin_stop_dec(struct vdin_dev_s *devp) disable_irq_nosync(devp->irq); afbc_init_flag = 0; - while (++afbc_write_down_flag < afbc_write_down_test_times) { - if (vdin_afbce_read_writedown_flag() == 0) - usleep_range(5000, 5001); - else - break; + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + while (++afbc_write_down_flag < afbc_write_down_test_times) { + if (vdin_afbce_read_writedown_flag() == 0) + usleep_range(5000, 5001); + else + break; + } } if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && From 2a39427909c52e769fe496a11f39a140c3641812 Mon Sep 17 00:00:00 2001 From: xuhua zhang Date: Wed, 17 Oct 2018 20:20:01 +0800 Subject: [PATCH 0593/1060] vdin: add vdin1 histgram [1/1] PD#SWPL-3059 Problem: vdin1 hisgram and screencap cannot be used simultaneously Solution: add vdin1 histgram,and make hist and screencap function to be compatible Verify: txlx r311 Change-Id: I759d1cdc69d59015ce845898990088eb6943cc41 Signed-off-by: xuhua zhang Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c include/linux/amlogic/media/frame_provider/tvin/tvin.h --- .../video_processor/video_dev/amlvideo2.c | 1 + .../amlogic/media/vin/tvin/vdin/vdin_ctl.c | 6 + .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 155 +++++++++++++++++- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 14 ++ .../amlogic/media/frame_provider/tvin/tvin.h | 1 - .../media/frame_provider/tvin/tvin_v4l2.h | 5 + 6 files changed, 179 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index df62d822f7fc..ccbde7be3392 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -5061,6 +5061,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) } para.dest_hactive = dst_w; para.dest_vactive = dst_h; + para.reserved |= PARAM_STATE_SCREENCAP; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; if ((para.port == TVIN_PORT_VIU1_VIDEO) || diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index 6522883a82f5..1fc52f0206b2 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -1743,7 +1743,13 @@ static inline void vdin_set_hist_mux(struct vdin_dev_s *devp) /* use 11: form matrix1 din */ wr_bits(devp->addr_offset, VDIN_HIST_CTRL, 3, HIST_HIST_DIN_SEL_BIT, HIST_HIST_DIN_SEL_WID); + + /*for project get vdin1 hist*/ + //if (devp->index == 1) + // wr_bits(devp->addr_offset, VDIN_WR_CTRL2, 1, 8, 1); } + + /* urgent ctr config */ /*if vdin fifo over up_th,will trigger increase * urgent responds to vdin write, diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 55772068a67f..893520ca374e 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -80,6 +80,7 @@ static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; static int afbc_init_flag; static int afbc_write_down_flag; +static unsigned int pr_times; /* * canvas_config_mode * 0: canvas_config in driver probe @@ -142,6 +143,8 @@ static unsigned int vdin_drop_cnt; module_param(vdin_drop_cnt, uint, 0664); MODULE_PARM_DESC(vdin_drop_cnt, "vdin_drop_cnt"); +struct vdin_hist_s vdin1_hist; +struct vdin_v4l2_param_s vdin_v4l2_param; static int irq_max_count; @@ -756,17 +759,31 @@ int start_tvin_service(int no, struct vdin_parm_s *para) pr_info("v_active:%d;scan_mode:%d**\n", para->v_active, para->scan_mode); } + + if (devp->index == 1) { + devp->parm.reserved |= para->reserved; + pr_info("vdin1 add reserved = 0x%lx\n", para->reserved); + pr_info("vdin1 all reserved = 0x%x\n", devp->parm.reserved); + } devp->start_time = jiffies_to_msecs(jiffies); if (devp->flags & VDIN_FLAG_DEC_STARTED) { pr_err("%s: port 0x%x, decode started already.\n", __func__, para->port); - ret = -EBUSY; - return ret; + if ((devp->parm.reserved & PARAM_STATE_SCREENCAP) && + (devp->parm.reserved & PARAM_STATE_HISTGRAM) && + (devp->index == 1)) + return 0; + else + return -EBUSY; } if ((para->port != TVIN_PORT_VIU1) || (viu_hw_irq != 0)) { ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, devp->irq_name, (void *)devp); + if (ret != 0) { + pr_info("vdin_v4l2_isr request irq error.\n"); + return -1; + } devp->flags |= VDIN_FLAG_ISR_REQ; /*disable vsync irq until vdin configured completely*/ disable_irq_nosync(devp->irq); @@ -867,6 +884,14 @@ int stop_tvin_service(int no) unsigned int end_time; devp = vdin_devp[no]; + if ((devp->parm.reserved & PARAM_STATE_HISTGRAM) && + (devp->parm.reserved & PARAM_STATE_SCREENCAP) && + (devp->index == 1)) { + pr_info("stop vdin v4l2 screencap.\n"); + devp->parm.reserved &= ~PARAM_STATE_SCREENCAP; + return 0; + } + if (!(devp->flags&VDIN_FLAG_DEC_STARTED)) { pr_err("%s:decode hasn't started.\n", __func__); return -EBUSY; @@ -1222,7 +1247,34 @@ static u64 func_div(u64 cur, u32 divid) return cur; } +static void vdin_hist_tgt(struct vdin_dev_s *devp, struct vframe_s *vf) +{ + int ave_luma; + int pix_sum; + ulong flags; + spin_lock_irqsave(&devp->hist_lock, flags); + vdin1_hist.sum = vf->prop.hist.luma_sum; + pix_sum = vf->prop.hist.pixel_sum; + vdin1_hist.height = vf->prop.hist.height; + vdin1_hist.width = vf->prop.hist.width; + + if ((vdin1_hist.height == 0) || (vdin1_hist.width == 0)) { + spin_unlock_irqrestore(&devp->hist_lock, flags); + return; + } + + vdin1_hist.ave = + vdin1_hist.sum/(vdin1_hist.height * vdin1_hist.width); + + ave_luma = vdin1_hist.ave; + ave_luma = (ave_luma - 16) < 0 ? 0 : (ave_luma - 16); + vdin1_hist.ave = ave_luma*255/(235-16); + if (vdin1_hist.ave > 255) + vdin1_hist.ave = 255; + + spin_unlock_irqrestore(&devp->hist_lock, flags); +} /* *VDIN_FLAG_RDMA_ENABLE=1 @@ -1765,6 +1817,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) vdin_set_vframe_prop_info(curr_wr_vf, devp); vdin_backup_histgram(curr_wr_vf, devp); + vdin_hist_tgt(devp, curr_wr_vf); if (devp->frontend && devp->frontend->dec_ops) { decops = devp->frontend->dec_ops; @@ -2006,6 +2059,9 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int callmaster_status = 0; struct vdin_dev_s *devp = NULL; void __user *argp = (void __user *)arg; + struct vdin_parm_s param; + ulong flags; + struct vdin_hist_s vdin1_hist_temp; /* Get the per-device structure that contains this cdev */ devp = file->private_data; @@ -2379,6 +2435,100 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) devp->auto_ratio_en); } break; + case TVIN_IOC_GET_LATENCY_MODE: + mutex_unlock(&devp->fe_lock); + if (copy_to_user(argp, + &(devp->prop.latency), + sizeof(struct tvin_latency_s))) { + mutex_unlock(&devp->fe_lock); + ret = -EFAULT; + pr_info("TVIN_IOC_GET_ALLM_MODE err\n\n"); + break; + } + pr_info("allm mode-%d,IT=%d,CN=%d\n\n", + devp->prop.latency.allm_mode, + devp->prop.latency.it_content, + devp->prop.latency.cn_type); + mutex_unlock(&devp->fe_lock); + break; + case TVIN_IOC_G_VDIN_HIST: + if (devp->index == 0) { + pr_info("TVIN_IOC_G_VDIN_HIST cann't be used at vdin0\n"); + break; + } + + spin_lock_irqsave(&devp->hist_lock, flags); + vdin1_hist_temp.sum = vdin1_hist.sum; + vdin1_hist_temp.width = vdin1_hist.width; + vdin1_hist_temp.height = vdin1_hist.height; + vdin1_hist_temp.ave = vdin1_hist.ave; + spin_unlock_irqrestore(&devp->hist_lock, flags); + if (vdin_dbg_en) { + if (pr_times++ > 10) { + pr_times = 0; + pr_info("-:h=%d,w=%d,a=%d\n", + vdin1_hist_temp.height, + vdin1_hist_temp.width, + vdin1_hist_temp.ave); + } + } + + if ((vdin1_hist.height == 0) || (vdin1_hist.width == 0)) + ret = -EFAULT; + else if (copy_to_user(argp, + &vdin1_hist_temp, + sizeof(struct vdin_hist_s))) { + pr_info("vdin1_hist copy fail\n"); + ret = -EFAULT; + } + break; + case TVIN_IOC_S_VDIN_V4L2START: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_VDIN_V4L2START cann't be used at vdin0\n"); + break; + } + if (devp->flags & VDIN_FLAG_ISR_REQ) + free_irq(devp->irq, (void *)devp); + + if (copy_from_user(&vdin_v4l2_param, argp, + sizeof(struct vdin_v4l2_param_s))) { + pr_info("vdin_v4l2_param copy fail\n"); + return -EFAULT; + } + memset(¶m, 0, sizeof(struct vdin_parm_s)); + param.port = TVIN_PORT_VIU1; + param.reserved |= PARAM_STATE_HISTGRAM; + param.h_active = vdin_v4l2_param.width; + param.v_active = vdin_v4l2_param.height; + /* use 1280X720 for histgram*/ + if ((vdin_v4l2_param.width > 1280) && + (vdin_v4l2_param.height > 720)) { + devp->debug.scaler4w = 1280; + devp->debug.scaler4h = 720; + devp->debug.dest_cfmt = TVIN_YUV422; + devp->flags |= VDIN_FLAG_MANUAL_CONVERSION; + } + param.frame_rate = vdin_v4l2_param.fps; + param.cfmt = TVIN_YUV422; + param.dfmt = TVIN_YUV422; + param.scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + param.fmt = TVIN_SIG_FMT_MAX; + //devp->flags |= VDIN_FLAG_V4L2_DEBUG; + devp->hist_bar_enable = 1; + devp->index = 1; + start_tvin_service(devp->index, ¶m); + break; + + case TVIN_IOC_S_VDIN_V4L2STOP: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_VDIN_V4L2STOP cann't be used at vdin0\n"); + break; + } + devp->parm.reserved &= ~PARAM_STATE_HISTGRAM; + devp->flags &= (~VDIN_FLAG_ISR_REQ); + devp->flags &= (~VDIN_FLAG_FS_OPENED); + stop_tvin_service(devp->index); + break; default: ret = -ENOIOCTLCMD; /* pr_info("%s %d is not supported command\n", __func__, cmd); */ @@ -2655,6 +2805,7 @@ static int vdin_drv_probe(struct platform_device *pdev) vdevp->flags &= (~VDIN_FLAG_FS_OPENED); mutex_init(&vdevp->fe_lock); spin_lock_init(&vdevp->isr_lock); + spin_lock_init(&vdevp->hist_lock); vdevp->frontend = NULL; /* @todo vdin_addr_offset */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index b1c4605f689e..69062dc65bc8 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -205,6 +205,7 @@ struct vdin_dev_s { struct timer_list timer; spinlock_t isr_lock; + spinlock_t hist_lock; struct mutex fe_lock; struct clk *msr_clk; unsigned int msr_clk_val; @@ -348,6 +349,19 @@ struct vdin_dev_s { struct dentry *dbg_root; /*dbg_fs*/ }; +struct vdin_hist_s { + ulong sum; + int width; + int height; + int ave; +}; + +struct vdin_v4l2_param_s { + int width; + int height; + int fps; +}; + extern struct vframe_provider_s *vf_get_provider_by_name( const char *provider_name); extern bool enable_reset; diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index ba25340c5c8a..51cf4be4cf38 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -448,7 +448,6 @@ struct tvafe_pin_mux_s { #define TVIN_IOC_G_VDIN_HIST _IOW(_TM_T, 0x24, struct vdin_hist_s) #define TVIN_IOC_S_VDIN_V4L2START _IOW(_TM_T, 0x25, struct vdin_v4l2_param_s) #define TVIN_IOC_S_VDIN_V4L2STOP _IO(_TM_T, 0x26) -#define TVIN_IOC_S_AFE_SONWCFG _IOW(_TM_T, 0x27, unsigned int) /* *function defined applied for other driver diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h index 493bc9a22051..b1233faf5e3d 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h @@ -742,6 +742,10 @@ enum cam_interface_e { CAM_MIPI, }; +#define PARAM_STATE_NULL 0x00000000 +#define PARAM_STATE_HISTGRAM 0x00000001 +#define PARAM_STATE_SCREENCAP 0x00000002 + /* *********************************************************************** */ /* *** IOCTL command definitions ***************************************** */ @@ -813,6 +817,7 @@ struct vdin_parm_s { unsigned short skip_count; /* for skip frame */ struct csi_parm_s csi_hw_info; + /*for reserved */ uintptr_t reserved; }; From 08d2167794d50da0600cc6b8692ea414b7c30b8d Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Mon, 14 Jan 2019 15:09:35 +0800 Subject: [PATCH 0594/1060] tvin: vdin: add interface to get signalinfo [1/1] PD#TV-2083 Problem: TVIN_IOC_G_SIG_INFO not complete enough Solution: add interface to get signalinfo Verify: Verify on TL1 Change-Id: I32f198f14dfcc1f8a8ee1f19c4065bd7d4d5dccc Signed-off-by: Xuhua Zhang Conflicts: include/linux/amlogic/media/frame_provider/tvin/tvin.h --- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 22 +++++++++++++++++++ .../amlogic/media/frame_provider/tvin/tvin.h | 13 +++++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 893520ca374e..fc88eff0bf7a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -2282,6 +2282,28 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_unlock(&devp->fe_lock); break; } + case TVIN_IOC_G_FRONTEND_INFO: { + struct tvin_frontend_info_s info; + + if ((!devp) || (!devp->fmt_info_p) || (!devp->curr_wr_vfe)) { + ret = -EFAULT; + break; + } + + memset(&info, 0, sizeof(struct tvin_frontend_info_s)); + mutex_lock(&devp->fe_lock); + info.cfmt = devp->parm.info.cfmt; + info.fps = devp->parm.info.fps; + info.colordepth = devp->prop.colordepth; + info.scan_mode = devp->fmt_info_p->scan_mode; + info.height = devp->curr_wr_vfe->vf.height; + info.width = devp->curr_wr_vfe->vf.width; + if (copy_to_user(argp, &info, + sizeof(struct tvin_frontend_info_s))) + ret = -EFAULT; + mutex_unlock(&devp->fe_lock); + break; + } case TVIN_IOC_G_BUF_INFO: { struct tvin_buf_info_s buf_info; memset(&buf_info, 0, sizeof(buf_info)); diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index 51cf4be4cf38..bf2dbba442a8 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -312,6 +312,15 @@ struct tvin_info_s { unsigned int is_dvi; }; +struct tvin_frontend_info_s { + enum tvin_scan_mode_e scan_mode; + enum tvin_color_fmt_e cfmt; + unsigned int fps; + unsigned int width; + unsigned int height; + unsigned int colordepth; +}; + struct tvin_buf_info_s { unsigned int vf_size; unsigned int buf_count; @@ -432,6 +441,10 @@ struct tvafe_pin_mux_s { enum tvin_force_color_range_e) #define TVIN_IOC_GAME_MODE _IOW(_TM_T, 0x4b, unsigned int) #define TVIN_IOC_SET_AUTO_RATIO_EN _IOW(_TM_T, 0x4c, unsigned int) +#define TVIN_IOC_GET_LATENCY_MODE _IOR(_TM_T, 0x4d,\ + struct tvin_latency_s) +#define TVIN_IOC_G_FRONTEND_INFO _IOR(_TM_T, 0x4e,\ + struct tvin_frontend_info_s) /* TVAFE */ #define TVIN_IOC_S_AFE_VGA_PARM _IOW(_TM_T, 0x16, struct tvafe_vga_parm_s) From 490fe0831d037dcfb2598bfe749426e963653401 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Fri, 1 Mar 2019 20:12:38 +0800 Subject: [PATCH 0595/1060] tvin: vdin: add vdin1 scaler preview for vdin0 preview [1/1] PD#SWPL-4115 Problem: vdin preview error when input 4K Solution: use vdin1 as double write function Verify: x301 Change-Id: I4ed15dd5c445ed3c38b4a2535be075210dcbdac7 Signed-off-by: Xuhua Zhang Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h --- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 2 +- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 373 +++++++++++++++--- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 4 +- 3 files changed, 318 insertions(+), 61 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index d23608a1760a..ffceaa70d2ab 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -953,7 +953,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) devp->afbce_info->frame_body_size); } } - + pr_info("tl1 preview flag = %d\n", tl1_vdin1_preview_flag); pr_info("Vdin driver version : %s\n", VDIN_VER); } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index fc88eff0bf7a..5b430be653a6 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -78,9 +78,15 @@ static unsigned int vdin_addr_offset[VDIN_MAX_DEVS] = {0, 0x80}; static struct vdin_dev_s *vdin_devp[VDIN_MAX_DEVS]; static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; -static int afbc_init_flag; -static int afbc_write_down_flag; +static int afbc_init_flag[VDIN_MAX_DEVS]; +static int afbc_write_down_flag[VDIN_MAX_DEVS]; static unsigned int pr_times; +unsigned int tl1_vdin1_preview_flag; +static unsigned int tl1_vdin1_data_readied; +static unsigned int tl1_vdin1_canvas_addr; +static unsigned int tl1_vdin1_height; +static unsigned int tl1_vdin1_width; +spinlock_t tl1_preview_lock; /* * canvas_config_mode * 0: canvas_config in driver probe @@ -89,10 +95,12 @@ static unsigned int pr_times; */ static int canvas_config_mode = 2; static bool work_mode_simple; -static int max_ignore_frames = 2; +static int phase_lock_flag; +static int max_ignore_frames[2] = {2, 2}; /*game_mode_switch_frames:min num is 5 by 1080p60hz input test*/ static int game_mode_switch_frames = 10; -static int ignore_frames; +static int game_mode_phlock_switch_frames = 60; +static int ignore_frames[2] = {0, 0}; static unsigned int dv_work_delby; /* viu isr select: * enable viu_hw_irq for the bandwidth is enough on gxbb/gxtvbb and laters ic @@ -107,11 +115,11 @@ MODULE_PARM_DESC(canvas_config_mode, "canvas configure mode"); module_param(work_mode_simple, bool, 0664); MODULE_PARM_DESC(work_mode_simple, "enable/disable simple work mode"); -module_param(max_ignore_frames, int, 0664); -MODULE_PARM_DESC(max_ignore_frames, "ignore first frames"); +//module_param(max_ignore_frames, int, 0664); +//MODULE_PARM_DESC(max_ignore_frames, "ignore first frames"); -module_param(ignore_frames, int, 0664); -MODULE_PARM_DESC(ignore_frames, "ignore first frames"); +//module_param(ignore_frames, int, 0664); +//MODULE_PARM_DESC(ignore_frames, "ignore first frames"); module_param(dv_work_delby, uint, 0664); MODULE_PARM_DESC(dv_work_delby, "dv_work_delby"); @@ -224,8 +232,11 @@ int vdin_open_fe(enum tvin_port_e port, int index, struct vdin_dev_s *devp) if (devp->msr_clk != NULL) clk_prepare_enable(devp->msr_clk); - if (devp->frontend->dec_ops && devp->frontend->dec_ops->open) - ret = devp->frontend->dec_ops->open(devp->frontend, port); + if (tl1_vdin1_preview_flag == 0) { + if (devp->frontend->dec_ops && devp->frontend->dec_ops->open) + ret = + devp->frontend->dec_ops->open(devp->frontend, port); + } /* check open status */ if (ret) return 1; @@ -513,7 +524,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) } #endif - afbc_write_down_flag = 0; + afbc_write_down_flag[devp->index] = 0; /* h_active/v_active will be used by bellow calling */ if (devp->afbce_mode == 0) { if (canvas_config_mode == 1) @@ -640,6 +651,13 @@ void vdin_start_dec(struct vdin_dev_s *devp) pr_info("vdin.%d start time: %ums, run time:%ums.\n", devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); + + if ((devp->afbce_mode == 1) && is_meson_tl1_cpu() && + (devp->h_active >= 1920) && (devp->v_active >= 1080)) { + spin_lock_init(&tl1_preview_lock); + tl1_vdin1_preview_flag = 1; + max_ignore_frames[devp->index] = 9; + } } /* @@ -664,10 +682,12 @@ void vdin_stop_dec(struct vdin_dev_s *devp) } #endif disable_irq_nosync(devp->irq); - afbc_init_flag = 0; + afbc_init_flag[devp->index] = 0; + max_ignore_frames[devp->index] = 2; if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { - while (++afbc_write_down_flag < afbc_write_down_test_times) { + while (++afbc_write_down_flag[devp->index] < + afbc_write_down_test_times) { if (vdin_afbce_read_writedown_flag() == 0) usleep_range(5000, 5001); else @@ -719,8 +739,9 @@ void vdin_stop_dec(struct vdin_dev_s *devp) rdma_clear(devp->rdma_handle); #endif devp->flags &= (~VDIN_FLAG_RDMA_ENABLE); - ignore_frames = 0; + ignore_frames[devp->index] = 0; devp->cycle = 0; + /* clear color para*/ memset(&devp->prop, 0, sizeof(devp->prop)); if (time_en) @@ -748,6 +769,12 @@ int start_tvin_service(int no, struct vdin_parm_s *para) __func__, no); return -1; } + + if (tl1_vdin1_preview_flag == 1) { + pr_err("[vdin]%s vdin%d use for preview, return.\n", + __func__, no); + return -1; + } fmt = devp->parm.info.fmt; if (vdin_dbg_en) { pr_info("**[%s]cfmt:%d;dfmt:%d;dest_hactive:%d;", @@ -1284,7 +1311,7 @@ static void vdin_hist_tgt(struct vdin_dev_s *devp, struct vframe_s *vf) */ irqreturn_t vdin_isr(int irq, void *dev_id) { - ulong flags = 0; + ulong flags = 0, flags1 = 0; struct vdin_dev_s *devp = (struct vdin_dev_s *)dev_id; enum tvin_sm_status_e state; @@ -1326,15 +1353,15 @@ irqreturn_t vdin_isr(int irq, void *dev_id) offset = devp->addr_offset; - if (afbc_init_flag == 0) { - afbc_init_flag = 1; + if (afbc_init_flag[devp->index] == 0) { + afbc_init_flag[devp->index] = 1; /*set mem power on*/ if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { vdin_afbce_hw_enable(devp); return IRQ_HANDLED; } - } else if (afbc_init_flag == 1) { - afbc_init_flag = 2; + } else if (afbc_init_flag[devp->index] == 1) { + afbc_init_flag[devp->index] = 2; if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) return IRQ_HANDLED; } @@ -1389,6 +1416,27 @@ irqreturn_t vdin_isr(int irq, void *dev_id) devp->dv.dv_crc_check = true; if ((devp->dv.dv_crc_check == true) || (!(dv_dbg_mask & DV_CRC_CHECK))) { + spin_lock_irqsave(&tl1_preview_lock, flags1); + if ((devp->index == 0) && + (tl1_vdin1_preview_flag == 1)) { + if (tl1_vdin1_data_readied == 1) { + tl1_vdin1_data_readied = 0; + devp->last_wr_vfe->vf.canvas0Addr = + tl1_vdin1_canvas_addr; + devp->last_wr_vfe->vf.height = + tl1_vdin1_height; + devp->last_wr_vfe->vf.width = + tl1_vdin1_width; + } + } else if ((devp->index == 1) && + (tl1_vdin1_preview_flag == 1)) { + tl1_vdin1_canvas_addr = + devp->last_wr_vfe->vf.canvas0Addr; + tl1_vdin1_height = devp->last_wr_vfe->vf.height; + tl1_vdin1_width = devp->last_wr_vfe->vf.width; + tl1_vdin1_data_readied = 1; + } + spin_unlock_irqrestore(&tl1_preview_lock, flags1); provider_vf_put(devp->last_wr_vfe, devp->vfp); if (time_en) { devp->last_wr_vfe->vf.ready_clock[1] = @@ -1408,16 +1456,23 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_vf_disp_mode_update(devp->last_wr_vfe, devp->vfp); devp->last_wr_vfe = NULL; + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) - vf_notify_receiver("dv_vdin", - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + if (((devp->dv.dolby_input & (1 << devp->index)) || + (devp->dv.dv_flag && is_dolby_vision_enable())) + && (devp->dv.dv_config == true)) + vf_notify_receiver("dv_vdin", + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + else #endif - vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } } /*check vs is valid base on the time during continuous vs*/ if (vdin_check_cycle(devp) && (!(isr_flag & VDIN_BYPASS_CYC_CHECK)) @@ -1491,7 +1546,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) pre_prop->vdin_hdr_Flag = prop->vdin_hdr_Flag; pre_prop->color_fmt_range = prop->color_fmt_range; pre_prop->dest_cfmt = prop->dest_cfmt; - ignore_frames = 0; + ignore_frames[devp->index] = 0; vdin_drop_cnt++; goto irq_handled; } @@ -1526,8 +1581,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) VFRAME_PHASE_DB : VFRAME_PHASE_DR; - if (ignore_frames < max_ignore_frames) { - ignore_frames++; + if (ignore_frames[devp->index] < max_ignore_frames[devp->index]) { + ignore_frames[devp->index]++; devp->vdin_irq_flag = 12; vdin_drop_cnt++; goto irq_handled; @@ -1538,27 +1593,43 @@ irqreturn_t vdin_isr(int irq, void *dev_id) devp->vdin_irq_flag = 13; vdin_drop_cnt++; if (devp->flags&VDIN_FLAG_RDMA_ENABLE) - ignore_frames = 0; + ignore_frames[devp->index] = 0; goto irq_handled; } next_wr_vfe = provider_vf_peek(devp->vfp); if (!next_wr_vfe) { - devp->vdin_irq_flag = 14; - vdin_drop_cnt++; - vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ - goto irq_handled; + /*add for force vdin buffer recycle*/ + if (devp->flags & VDIN_FLAG_FORCE_RECYCLE) { + next_wr_vfe = receiver_vf_get(devp->vfp); + if (next_wr_vfe) + receiver_vf_put(&next_wr_vfe->vf, devp->vfp); + else + pr_err("[vdin.%d]force recycle error,no buffer in ready list", + devp->index); + } else { + devp->vdin_irq_flag = 14; + vdin_drop_cnt++; + vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ + goto irq_handled; + } } + + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) - vdin2nr = vf_notify_receiver("dv_vdin", - VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); - else + if (((devp->dv.dolby_input & (1 << devp->index)) || + (devp->dv.dv_flag && is_dolby_vision_enable())) && + (devp->dv.dv_config == true)) + vdin2nr = vf_notify_receiver("dv_vdin", + VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + else #endif - vdin2nr = vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + vdin2nr = vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + } /*if vdin-nr,di must get * vdin current field type which di pre will read */ @@ -1635,8 +1706,32 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_dolby_addr_update(devp, next_wr_vfe->vf.index); } else devp->dv.dv_crc_check = true; + if ((devp->dv.dv_crc_check == true) || (!(dv_dbg_mask & DV_CRC_CHECK))) { + spin_lock_irqsave(&tl1_preview_lock, flags1); + if ((devp->index == 0) && + (tl1_vdin1_preview_flag == 1)) { + if (tl1_vdin1_data_readied == 1) { + tl1_vdin1_data_readied = 0; + curr_wr_vfe->vf.canvas0Addr = + tl1_vdin1_canvas_addr; + curr_wr_vfe->vf.height = + tl1_vdin1_height; + curr_wr_vfe->vf.width = + tl1_vdin1_width; + } + } else if ((devp->index == 1) && + (tl1_vdin1_preview_flag == 1)) { + tl1_vdin1_canvas_addr = + curr_wr_vfe->vf.canvas0Addr; + tl1_vdin1_height = + curr_wr_vfe->vf.height; + tl1_vdin1_width = + curr_wr_vfe->vf.width; + tl1_vdin1_data_readied = 1; + } + spin_unlock_irqrestore(&tl1_preview_lock, flags1); provider_vf_put(curr_wr_vfe, devp->vfp); if (vdin_dbg_en) { curr_wr_vfe->vf.ready_clock[1] = sched_clock(); @@ -1685,25 +1780,63 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || (devp->game_mode & VDIN_GAME_MODE_1)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) - vf_notify_receiver("dv_vdin", - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + if (((devp->dv.dolby_input & (1 << devp->index)) || + (devp->dv.dv_flag && is_dolby_vision_enable())) + && (devp->dv.dv_config == true)) + vf_notify_receiver("dv_vdin", + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + else #endif + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } else if (devp->game_mode & VDIN_GAME_MODE_2) { + spin_lock_irqsave(&tl1_preview_lock, flags1); + if ((devp->index == 0) && + (tl1_vdin1_preview_flag == 1)) { + if (tl1_vdin1_data_readied == 1) { + tl1_vdin1_data_readied = 0; + next_wr_vfe->vf.canvas0Addr = + tl1_vdin1_canvas_addr; + next_wr_vfe->vf.height = + tl1_vdin1_height; + next_wr_vfe->vf.width = + tl1_vdin1_width; + } + } else if ((devp->index == 1) && + (tl1_vdin1_preview_flag == 1)) { + tl1_vdin1_canvas_addr = + next_wr_vfe->vf.canvas0Addr; + tl1_vdin1_height = + next_wr_vfe->vf.height; + tl1_vdin1_width = + next_wr_vfe->vf.width; + tl1_vdin1_data_readied = 1; + } + spin_unlock_irqrestore(&tl1_preview_lock, flags1); + provider_vf_put(next_wr_vfe, devp->vfp); + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } else if (devp->game_mode & VDIN_GAME_MODE_2) { - provider_vf_put(next_wr_vfe, devp->vfp); - vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - if (vdin_dbg_en) { - next_wr_vfe->vf.ready_clock[1] = sched_clock(); - pr_info("vdin put latency %lld us. first %lld us.\n", - func_div(next_wr_vfe->vf.ready_clock[1], 1000), - func_div(next_wr_vfe->vf.ready_clock[0], 1000)); + if (vdin_dbg_en) { + next_wr_vfe->vf.ready_clock[1] = + sched_clock(); + pr_info("vdin put latency %lld us.first %lld us\n", + func_div(next_wr_vfe->vf.ready_clock[1], + 1000), + func_div(next_wr_vfe->vf.ready_clock[0], + 1000)); + } } } devp->frame_cnt++; @@ -2001,6 +2134,7 @@ static int vdin_open(struct inode *inode, struct file *file) static int vdin_release(struct inode *inode, struct file *file) { struct vdin_dev_s *devp = file->private_data; + struct vdin_dev_s *devp_vdin1 = vdin_devp[1]; if (!(devp->flags & VDIN_FLAG_FS_OPENED)) { if (vdin_dbg_en) @@ -2034,6 +2168,28 @@ static int vdin_release(struct inode *inode, struct file *file) file->private_data = NULL; + if (tl1_vdin1_preview_flag == 1) { + tl1_vdin1_preview_flag = 0; + devp_vdin1->flags &= (~VDIN_FLAG_FS_OPENED); + if (devp_vdin1->flags & VDIN_FLAG_DEC_STARTED) { + devp_vdin1->flags |= VDIN_FLAG_DEC_STOP_ISR; + vdin_stop_dec(devp_vdin1); + /* init flag */ + devp_vdin1->flags &= ~VDIN_FLAG_DEC_STOP_ISR; + /* clear the flag of decode started */ + devp_vdin1->flags &= (~VDIN_FLAG_DEC_STARTED); + } + if (devp_vdin1->flags & VDIN_FLAG_DEC_OPENED) { + vdin_close_fe(devp_vdin1); + devp_vdin1->flags &= (~VDIN_FLAG_DEC_OPENED); + } + devp_vdin1->flags &= (~VDIN_FLAG_SNOW_FLAG); + + /* free irq */ + if (devp_vdin1->flags & VDIN_FLAG_ISR_REQ) + free_irq(devp_vdin1->irq, (void *)devp_vdin1); + devp_vdin1->flags &= (~VDIN_FLAG_ISR_REQ); + } /* reset the hardware limit to vertical [0-1079] */ /* WRITE_VCBUS_REG(VPP_PREBLEND_VD1_V_START_END, 0x00000437); */ /*if (vdin_dbg_en)*/ @@ -2058,6 +2214,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) long ret = 0; int callmaster_status = 0; struct vdin_dev_s *devp = NULL; + struct vdin_dev_s *devp_vdin1 = NULL; void __user *argp = (void __user *)arg; struct vdin_parm_s param; ulong flags; @@ -2149,7 +2306,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) de_fmt_flag = 0; fmt = devp->parm.info.fmt = parm.info.fmt; } - devp->fmt_info_p = + devp->fmt_info_p = (struct tvin_format_s *)tvin_get_fmt_info(fmt); if (!devp->fmt_info_p) { pr_err("TVIN_IOC_START_DEC(%d) error, fmt is null\n", @@ -2164,6 +2321,61 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_START_DEC port %s, decode started ok\n\n", tvin_port_str(devp->parm.port)); mutex_unlock(&devp->fe_lock); + + devp_vdin1 = vdin_devp[1]; + mutex_lock(&devp_vdin1->fe_lock); + if ((tl1_vdin1_preview_flag == 1) && + !(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) { + msleep(150); + devp_vdin1->flags |= VDIN_FLAG_FS_OPENED; + if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) { + ret = request_irq(devp_vdin1->irq, vdin_isr, + IRQF_SHARED, + devp_vdin1->irq_name, + (void *)devp_vdin1); + if (ret != 0) { + pr_info("tl1_vdin1_preview request irq error.\n"); + return -1; + } + devp_vdin1->flags |= VDIN_FLAG_ISR_REQ; + disable_irq_nosync(devp_vdin1->irq); + /*init queue*/ + init_waitqueue_head(&devp_vdin1->queue); + } + + devp_vdin1->unstable_flag = false; + devp_vdin1->parm.info.fmt = fmt; + devp_vdin1->parm.port = devp->parm.port; + devp_vdin1->fmt_info_p = (struct tvin_format_s *) + tvin_get_fmt_info(fmt); + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) { + ret = vdin_open_fe(devp_vdin1->parm.port, + 0, devp_vdin1); + if (ret) { + pr_err("TVIN_IOC_OPEN(%d) failed to open port 0x%x\n", + devp_vdin1->index, + devp_vdin1->parm.port); + ret = -EFAULT; + mutex_unlock(&devp_vdin1->fe_lock); + break; + } + } + + devp_vdin1->flags |= VDIN_FLAG_DEC_OPENED; + devp_vdin1->flags |= VDIN_FLAG_FORCE_RECYCLE; + + devp_vdin1->debug.scaler4w = 1280; + devp_vdin1->debug.scaler4h = 720; + devp_vdin1->debug.dest_cfmt = TVIN_YUV422; + devp_vdin1->flags |= VDIN_FLAG_MANUAL_CONVERSION; + + vdin_start_dec(devp_vdin1); + devp_vdin1->flags |= VDIN_FLAG_DEC_STARTED; + + pr_info("TVIN_IOC_START_DEC port %s, vdin1 used for preview\n", + tvin_port_str(devp_vdin1->parm.port)); + } + mutex_unlock(&devp_vdin1->fe_lock); break; } case TVIN_IOC_STOP_DEC: { @@ -2190,6 +2402,30 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (vdin_dbg_en) pr_info("TVIN_IOC_STOP_DEC(%d) port %s, decode stop ok\n\n", parm->index, tvin_port_str(parm->port)); + + if (tl1_vdin1_preview_flag == 1) { + devp_vdin1 = vdin_devp[1]; + msleep(20); + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) { + pr_err("TVIN_IOC_STOP_DEC(%d) decode havn't started\n", + devp_vdin1->index); + ret = -EPERM; + mutex_unlock(&devp->fe_lock); + break; + } + devp_vdin1->flags |= VDIN_FLAG_DEC_STOP_ISR; + vdin_stop_dec(devp_vdin1); + /* init flag */ + devp_vdin1->flags &= ~VDIN_FLAG_DEC_STOP_ISR; + /* devp->flags &= ~VDIN_FLAG_FORCE_UNSTABLE; */ + /* clear the flag of decode started */ + devp_vdin1->flags &= (~VDIN_FLAG_DEC_STARTED); + if (vdin_dbg_en) + pr_info("vdin1 TVIN_IOC_STOP_DEC(%d) port %s stop ok\n\n", + parm->index, + tvin_port_str(parm->port)); + } + mutex_unlock(&devp->fe_lock); reset_tvin_smr(parm->index); break; @@ -2240,6 +2476,25 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_CLOSE(%d) port %s closed ok\n\n", parm->index, tvin_port_str(port)); + + if (tl1_vdin1_preview_flag == 1) { + msleep(20); + devp_vdin1 = vdin_devp[1]; + tl1_vdin1_preview_flag = 0; + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) { + pr_err("TVIN_IOC_CLOSE(%d) you have not opened port\n", + devp_vdin1->index); + ret = -EPERM; + mutex_unlock(&devp->fe_lock); + break; + } + vdin_close_fe(devp_vdin1); + devp_vdin1->flags &= (~VDIN_FLAG_DEC_OPENED); + if (vdin_dbg_en) + pr_info("vdin1 TVIN_IOC_CLOSE(%d) port %s closed ok\n\n", + parm->index, + tvin_port_str(port)); + } mutex_unlock(&devp->fe_lock); break; } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 69062dc65bc8..1295cf44ece1 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -45,7 +45,7 @@ #include "vdin_vf.h" #include "vdin_regs.h" -#define VDIN_VER "Ref.2018/11/21a" +#define VDIN_VER "Ref.2019/03/01" /*the counter of vdin*/ #define VDIN_MAX_DEVS 2 @@ -362,6 +362,8 @@ struct vdin_v4l2_param_s { int fps; }; +extern unsigned int tl1_vdin1_preview_flag; + extern struct vframe_provider_s *vf_get_provider_by_name( const char *provider_name); extern bool enable_reset; From 6464fb3452694cfab28c81b91a821d3bddb14091 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Thu, 28 Mar 2019 23:43:08 +0800 Subject: [PATCH 0596/1060] vdin: fixed the issue of mem mapping from vmap. [1/1] PD#SWPL-6196 Problem: the memory issue cause to kernel crash. Solution: 1. add flush cache when the mem oper end. 2. unmap addr which from vmap in vdin driver. Verify: X301 Change-Id: Id6efe2b009fe64ad753d51eb06784bd4e66f5e87 Signed-off-by: Nanxin Qin Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c --- .../media/video_processor/pic_dev/picdec.c | 2 + .../amlogic/media/vin/tvin/vdin/vdin_afbce.c | 29 ++- .../amlogic/media/vin/tvin/vdin/vdin_ctl.c | 106 +++++++- .../amlogic/media/vin/tvin/vdin/vdin_ctl.h | 12 +- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 242 +++++++----------- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 91 ++++--- 6 files changed, 285 insertions(+), 197 deletions(-) diff --git a/drivers/amlogic/media/video_processor/pic_dev/picdec.c b/drivers/amlogic/media/video_processor/pic_dev/picdec.c index 7d28ea390ed1..451718bf9fe0 100644 --- a/drivers/amlogic/media/video_processor/pic_dev/picdec.c +++ b/drivers/amlogic/media/video_processor/pic_dev/picdec.c @@ -778,6 +778,7 @@ static int picdec_memset_phyaddr(ulong phys, u32 size, u32 val) if (!p) return -1; memset(p, val, span); + codec_mm_dma_flush(p, span, DMA_TO_DEVICE); codec_mm_unmap_phyaddr(p); } return 0; @@ -887,6 +888,7 @@ static int copy_phybuf_to_file(ulong phys, u32 size, p = codec_mm_vmap(addr, span); if (!p) return -1; + codec_mm_dma_flush(p, span, DMA_FROM_DEVICE); vfs_write(fp, (char *)p, span, &pos); pos += span; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index c003c62b232b..35032f402671 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -583,6 +583,7 @@ void vdin_afbce_maptable_init(struct vdin_dev_s *devp) unsigned int *vtable = NULL; unsigned int body; unsigned int size; + void *p = NULL; size = roundup(devp->afbce_info->frame_body_size, 4096); @@ -602,20 +603,40 @@ void vdin_afbce_maptable_init(struct vdin_dev_s *devp) else vtable = phys_to_virt(ptable); } else { - vtable = (unsigned int *)codec_mm_vmap( - ptable, + vtable = (unsigned int *)vdin_vmap(ptable, devp->afbce_info->frame_table_size); + if (vdin_dbg_en) { + pr_err("----vdin vmap v: %p, p: %lx, size: %d\n", + vtable, ptable, + devp->afbce_info->frame_table_size); + } + if (!vtable) { + pr_err("vmap fail, size: %d.\n", + devp->afbce_info->frame_table_size); + return; + } + } - + p = vtable; body = devp->afbce_info->fm_body_paddr[i]&0xffffffff; for (j = 0; j < size; j += 4096) { *vtable = ((j + body) >> 12) & 0x000fffff; vtable++; } + /* clean tail data. */ + memset(vtable, 0, devp->afbce_info->frame_table_size - + ((char *)vtable - (char *)p)); + + vdin_dma_flush(devp, p, + devp->afbce_info->frame_table_size, + DMA_TO_DEVICE); + if (highmem_flag) - codec_mm_unmap_phyaddr((void *)vtable); + vdin_unmap_phyaddr(p); + + vtable = NULL; } } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index 1fc52f0206b2..af904757df26 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -160,6 +163,79 @@ static unsigned int vpu_reg_27af = 0x3; #define pr_info(fmt, ...) #endif +u8 *vdin_vmap(ulong addr, u32 size) +{ + u8 *vaddr = NULL; + struct page **pages = NULL; + u32 i, npages, offset = 0; + ulong phys, page_start; + /*pgprot_t pgprot = pgprot_noncached(PAGE_KERNEL);*/ + pgprot_t pgprot = PAGE_KERNEL; + + if (!PageHighMem(phys_to_page(addr))) + return phys_to_virt(addr); + + offset = offset_in_page(addr); + page_start = addr - offset; + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + for (i = 0; i < npages; i++) { + phys = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(phys >> PAGE_SHIFT); + } + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("the phy(%lx) vmaped fail, size: %d\n", + page_start, npages << PAGE_SHIFT); + kfree(pages); + return NULL; + } + + kfree(pages); + + if (vdin_dbg_en) { + pr_info("[vdin HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", + __func__, page_start, vaddr, npages << PAGE_SHIFT); + } + + return vaddr + offset; +} + +void vdin_unmap_phyaddr(u8 *vaddr) +{ + void *addr = (void *)(PAGE_MASK & (ulong)vaddr); + + if (is_vmalloc_or_module_addr(vaddr)) { + if (vdin_dbg_en) + pr_info("----vdin unmap v: %p\n", addr); + vunmap(addr); + } +} + +void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr, + int size, enum dma_data_direction dir) +{ + ulong phy_addr; + + if (is_vmalloc_or_module_addr(vaddr)) { + phy_addr = page_to_phys(vmalloc_to_page(vaddr)) + + offset_in_page(vaddr); + if (phy_addr && PageHighMem(phys_to_page(phy_addr))) { + if (vdin_dbg_en) + pr_info("----vdin flush v: %p, p: %lx\n", + vaddr, phy_addr); + dma_sync_single_for_device(&devp->this_pdev->dev, + phy_addr, size, dir); + } + return; + } +} + /*reset reg mif value of vdin0: * VDIN_WR_CTRL \VDIN_COM_CTRL0\ VDIN_MISC_CTRL */ @@ -3526,12 +3602,12 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) if ((devp->cma_config_flag & 0x100) && devp->cma_config_en) devp->vfp->dv_buf_ori[index] = - codec_mm_vmap(devp->vfmem_start[index] + + vdin_vmap(devp->vfmem_start[index] + devp->vfmem_size-dolby_size_byte, dolby_size_byte); else devp->vfp->dv_buf_ori[index] = - codec_mm_vmap(devp->mem_start + + vdin_vmap(devp->mem_start + devp->mem_size - dolby_size_byte * (devp->canvas_max_num - index), @@ -3548,15 +3624,32 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size) { unsigned int alloc_size; + int highmem_flag; + int index; alloc_size = dolby_size_byte*size; if (devp->dv.dv_dma_vaddr) dma_free_coherent(&devp->this_pdev->dev, alloc_size, devp->dv.dv_dma_vaddr, devp->dv.dv_dma_paddr); devp->dv.dv_dma_vaddr = NULL; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag) { + for (index = 0; index < size; index++) { + if (devp->vfp->dv_buf_ori[index]) { + vdin_unmap_phyaddr( + devp->vfp->dv_buf_ori[index]); + devp->vfp->dv_buf_ori[index] = NULL; + } + } + } } -static void vdin_dolby_metadata_swap(char *buf) +static void vdin_dolby_metadata_swap(struct vdin_dev_s *devp, char *buf) { char ext; unsigned int i, j; @@ -3568,6 +3661,8 @@ static void vdin_dolby_metadata_swap(char *buf) buf[i*16+15-j] = ext; } } + + vdin_dma_flush(devp, buf, dolby_size_byte, DMA_TO_DEVICE); } #define swap32(num) \ @@ -3665,7 +3760,8 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index) for (count = 0; count < META_RETRY_MAX; count++) { if (dv_dbg_mask & DV_READ_MODE_AXI) { memcpy(p, devp->vfp->dv_buf_vmem[index], 128); - vdin_dolby_metadata_swap(c); + vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE); + vdin_dolby_metadata_swap(devp, c); } else { wr(offset, VDIN_DOLBY_DSC_CTRL3, 0); wr(offset, VDIN_DOLBY_DSC_CTRL2, 0xd180c0d5); @@ -3678,7 +3774,9 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index) if ((i == 31) && (multimeta_flag == 0)) break; } + vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE); } + meta_size = (c[3] << 8) | c[4]; crc = p[31]; crc_result = crc32(0, p, 124); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h index 178c74a0a387..fcdf2974d439 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h @@ -17,7 +17,11 @@ #ifndef __TVIN_VDIN_CTL_H #define __TVIN_VDIN_CTL_H - +#include +#include +#include +#include +#include #include "vdin_drv.h" #define DV_SWAP_EN (1 << 0) @@ -111,10 +115,16 @@ struct ldim_max_s { #endif extern unsigned int game_mode; +extern bool vdin_dbg_en; /* ************************************************************************ */ /* ******** GLOBAL FUNCTION CLAIM ******** */ /* ************************************************************************ */ +extern u8 *vdin_vmap(ulong addr, u32 size); +extern void vdin_unmap_phyaddr(u8 *vaddr); +extern void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr, + int size, enum dma_data_direction dir); + extern void vdin_set_vframe_prop_info(struct vframe_s *vf, struct vdin_dev_s *devp); extern void LDIM_Initial_2(int pic_h, int pic_v, int BLK_Vnum, diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index ffceaa70d2ab..588b5eb5ba87 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -343,14 +343,15 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, for (j = 0; j < count; j++) { highaddr = phys + j * devp->canvas_w; - buf = codec_mm_vmap(highaddr, span); + buf = vdin_vmap(highaddr, span); if (!buf) { - pr_info("codec_mm_vmap error\n"); + pr_info("vdin_vmap error\n"); return; } + vdin_dma_flush(devp, buf, span, DMA_FROM_DEVICE); vfs_write(filp, buf, span, &pos); - codec_mm_unmap_phyaddr(buf); + vdin_unmap_phyaddr(buf); } pr_info("high-mem write buffer %2d of %2u to %s.\n", buf_num, devp->canvas_max_num, path); @@ -448,14 +449,16 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) for (j = 0; j < count; j++) { highaddr = phys + j * devp->canvas_w; - buf = codec_mm_vmap(highaddr, span); + buf = vdin_vmap(highaddr, span); if (!buf) { - pr_info("codec_mm_vmap error\n"); + pr_info("vdin_vmap error\n"); return; } + vdin_dma_flush(devp, buf, span, + DMA_FROM_DEVICE); vfs_write(filp, buf, span, &pos); - codec_mm_unmap_phyaddr(buf); + vdin_unmap_phyaddr(buf); } pr_info("high-mem write buffer %2d of %2u to %s.\n", i, devp->canvas_max_num, path); @@ -496,10 +499,8 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } - if (devp->cma_config_flag == 0x101) - highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); - else - highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + highmem_flag = PageHighMem( + phys_to_page(devp->afbce_info->fm_body_paddr[0])); if (highmem_flag == 0) { /*low mem area*/ @@ -532,11 +533,11 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, } else { /*high mem area*/ pr_info("high mem area\n"); - buf_head = codec_mm_vmap( + buf_head = vdin_vmap( devp->afbce_info->fm_head_paddr[buf_num], devp->afbce_info->frame_head_size); - buf_table = codec_mm_vmap( + buf_table = vdin_vmap( devp->afbce_info->fm_table_paddr[buf_num], devp->afbce_info->frame_table_size); @@ -557,8 +558,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } + vdin_dma_flush(devp, buf_head, + devp->afbce_info->frame_head_size, + DMA_FROM_DEVICE); vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos); - codec_mm_unmap_phyaddr(buf_head); + if (highmem_flag) + vdin_unmap_phyaddr(buf_head); pr_info("write buffer %2d of %2u head to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -573,8 +578,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, pr_info("create %s table error.\n", buff); return; } + vdin_dma_flush(devp, buf_table, + devp->afbce_info->frame_table_size, + DMA_FROM_DEVICE); vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos); - codec_mm_unmap_phyaddr(buf_table); + if (highmem_flag) + vdin_unmap_phyaddr(buf_table); pr_info("write buffer %2d of %2u table to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -600,27 +609,29 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, for (j = 0; j < count; j++) { highaddr = phys + j * span; - vbuf = codec_mm_vmap(highaddr, span); + vbuf = vdin_vmap(highaddr, span); if (!vbuf) { - pr_info("codec_mm_vmap error\n"); + pr_info("vdin_vmap error\n"); return; } + vdin_dma_flush(devp, vbuf, span, DMA_FROM_DEVICE); vfs_write(filp, vbuf, span, &pos); - codec_mm_unmap_phyaddr(vbuf); + vdin_unmap_phyaddr(vbuf); } if (remain) { span = devp->afbce_info->frame_body_size - remain; highaddr = phys + span; - vbuf = codec_mm_vmap(highaddr, remain); + vbuf = vdin_vmap(highaddr, remain); if (!vbuf) { - pr_info("codec_mm_vmap1 error\n"); + pr_info("vdin_vmap1 error\n"); return; } - vfs_write(filp, vbuf, span, &pos); - codec_mm_unmap_phyaddr(vbuf); + vdin_dma_flush(devp, vbuf, remain, DMA_FROM_DEVICE); + vfs_write(filp, vbuf, remain, &pos); + vdin_unmap_phyaddr(vbuf); } } pr_info("write buffer %2d of %2u body to %s.\n", @@ -631,119 +642,6 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, set_fs(old_fs); } -static void vdin_dump_afbce_mem(char *path, struct vdin_dev_s *devp) -{ - struct file *filp = NULL; - loff_t pos = 0; - void *buf_head = NULL; - void *buf_table = NULL; - void *buf_body = NULL; - unsigned char buff[100]; - unsigned int i; - mm_segment_t old_fs = get_fs(); - - if ((devp->cma_config_flag & 0x1) && - (devp->cma_mem_alloc == 0)) { - pr_info("%s:no cma alloc mem!!!\n", __func__); - return; - } - - if (devp->cma_config_flag == 0x101) { - buf_head = codec_mm_phys_to_virt( - devp->afbce_info->head_paddr); - buf_table = codec_mm_phys_to_virt( - devp->afbce_info->table_paddr); - buf_body = codec_mm_phys_to_virt( - devp->afbce_info->fm_body_paddr[0]); - - pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->head_paddr, - (devp->afbce_info->table_paddr), - devp->afbce_info->fm_body_paddr[0]); - } else if (devp->cma_config_flag == 0) { - buf_head = phys_to_virt( - devp->afbce_info->head_paddr); - buf_table = phys_to_virt( - devp->afbce_info->table_paddr); - buf_body = phys_to_virt( - devp->afbce_info->fm_body_paddr[0]); - - pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->head_paddr, - (devp->afbce_info->table_paddr), - devp->afbce_info->fm_body_paddr[0]); - } - - set_fs(KERNEL_DS); - - /* write header bin start */ - strcpy(buff, path); - strcat(buff, "_header.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s header error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_head, - devp->afbce_info->frame_head_size, &pos); - buf_head += devp->afbce_info->frame_head_size; - pr_info("write buffer %2d(0x%x bytes) of %2u head to %s.\n", - i, devp->afbce_info->frame_head_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write header bin end */ - - /* write table bin start */ - pos = 0; - strcpy(buff, path); - strcat(buff, "_table.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s table error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_table, - devp->afbce_info->frame_table_size, &pos); - buf_table += devp->afbce_info->frame_table_size; - pr_info("write buffer %2d(0x%x bytes) of %2u table to %s.\n", - i, devp->afbce_info->frame_table_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write table bin end */ - - /* write body bin start */ - pos = 0; - strcpy(buff, path); - strcat(buff, "_body.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s body error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_body, - devp->afbce_info->frame_body_size, &pos); - buf_body += devp->afbce_info->frame_body_size; - pr_info("write buffer %2d(0x%x bytes) of %2u body to %s.\n", - i, devp->afbce_info->frame_body_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write body bin end */ - - set_fs(old_fs); -} - static void dump_other_mem(char *path, unsigned int start, unsigned int offset) { @@ -1101,21 +999,30 @@ static void vdin_dump_histgram(struct vdin_dev_s *devp) } /*type: 1:nv21 2:yuv422 3:yuv444*/ -static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) +static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type, + char *path) { - char *md_path_head = "/storage/B8F7-DBD0/afbce/a0_1header.bin"; - char *md_path_body = "/storage/B8F7-DBD0/afbce/a0_1body.bin"; - unsigned int i; + char md_path_head[100], md_path_body[100]; + unsigned int i, j; + int highmem_flag = 0; unsigned int size = 0; + unsigned int span = 0; + unsigned int remain = 0; + unsigned int count = 0; + unsigned long highaddr; + unsigned long phys; long val; struct file *filp = NULL; loff_t pos = 0; mm_segment_t old_fs; void *head_dts = NULL; void *body_dts = NULL; + void *vbuf = NULL; if (kstrtol(type, 10, &val) < 0) return; + if (!path) + return; if (!devp->curr_wr_vfe) { devp->curr_wr_vfe = provider_vf_get(devp->vfp); @@ -1125,6 +1032,9 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) } } + sprintf(md_path_head, "%s_1header.bin", path); + sprintf(md_path_body, "%s_1body.bin", path); + i = devp->curr_wr_vfe->af_num; devp->curr_wr_vfe->vf.type = VIDTYPE_VIU_SINGLE_PLANE | VIDTYPE_VIU_FIELD | VIDTYPE_COMPRESS | VIDTYPE_SCATTER; @@ -1146,8 +1056,18 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) devp->curr_wr_vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; devp->curr_wr_vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; - head_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_head_paddr[i]); - body_dts = codec_mm_phys_to_virt(devp->afbce_info->fm_body_paddr[i]); + highmem_flag = PageHighMem( + phys_to_page(devp->afbce_info->fm_body_paddr[0])); + if (highmem_flag == 0) { + pr_info("low mem area\n"); + head_dts = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[i]); + } else { + pr_info("high mem area\n"); + head_dts = vdin_vmap( + devp->afbce_info->fm_head_paddr[i], + devp->afbce_info->frame_head_size); + } old_fs = get_fs(); set_fs(KERNEL_DS); @@ -1160,6 +1080,8 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) size = vfs_read(filp, head_dts, devp->afbce_info->frame_head_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(head_dts); vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -1175,8 +1097,30 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) return; } - size = vfs_read(filp, body_dts, - devp->afbce_info->frame_body_size, &pos); + if (highmem_flag == 0) { + body_dts = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[i]); + + size = vfs_read(filp, body_dts, + devp->afbce_info->frame_body_size, &pos); + } else { + span = SZ_1M; + count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span); + remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span); + phys = devp->afbce_info->fm_body_paddr[i]; + + + for (j = 0; j < count; j++) { + highaddr = phys + j * span; + vbuf = vdin_vmap(highaddr, span); + if (!vbuf) { + pr_info("vdin_vmap error\n"); + return; + } + vfs_read(filp, vbuf, span, &pos); + vdin_unmap_phyaddr(vbuf); + } + } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -1187,6 +1131,7 @@ static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type) vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } + static void vdin_write_mem( struct vdin_dev_s *devp, char *type, char *path, char *md_path) @@ -1272,13 +1217,14 @@ static void vdin_write_mem( span = devp->canvas_active_w; for (j = 0; j < count; j++) { highaddr = addr + j * devp->canvas_w; - dts = codec_mm_vmap(highaddr, span); + dts = vdin_vmap(highaddr, span); if (!dts) { - pr_info("codec_mm_vmap error\n"); + pr_info("vdin_vmap error\n"); return; } vfs_read(filp, dts, span, &pos); - codec_mm_unmap_phyaddr(dts); + vdin_dma_flush(devp, dts, span, DMA_TO_DEVICE); + vdin_unmap_phyaddr(dts); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -1790,8 +1736,8 @@ start_chk: } else if (!strcmp(parm[0], "force_recycle")) { devp->flags |= VDIN_FLAG_FORCE_RECYCLE; } else if (!strcmp(parm[0], "read_pic_afbce")) { - if (parm[1]) - vdin_write_afbce_mem(devp, parm[1]); + if (parm[1] && parm[2]) + vdin_write_afbce_mem(devp, parm[1], parm[2]); else pr_err("miss parameters.\n"); } else if (!strcmp(parm[0], "read_pic")) { @@ -2160,7 +2106,7 @@ start_chk: buf_num = val; vdin_dump_one_afbce_mem(parm[1], devp, buf_num); } else if (parm[1] != NULL) { - vdin_dump_afbce_mem(parm[1], devp); + vdin_dump_one_afbce_mem(parm[1], devp, 0); } } else { pr_info("unknown command\n"); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 5b430be653a6..6475d725150b 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -131,7 +131,7 @@ module_param(game_mode_switch_frames, int, 0664); MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch frames"); #endif -static bool vdin_dbg_en; +bool vdin_dbg_en; module_param(vdin_dbg_en, bool, 0664); MODULE_PARM_DESC(vdin_dbg_en, "enable/disable vdin debug information"); @@ -622,14 +622,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) #endif vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_START, NULL); - if ((devp->parm.port != TVIN_PORT_VIU1) || - (viu_hw_irq != 0)) { - /*enable irq */ - enable_irq(devp->irq); - if (vdin_dbg_en) - pr_info("****[%s]enable_irq ifdef VDIN_V2****\n", - __func__); - } if (vdin_dbg_en) pr_info("****[%s]ok!****\n", __func__); @@ -654,7 +646,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) if ((devp->afbce_mode == 1) && is_meson_tl1_cpu() && (devp->h_active >= 1920) && (devp->v_active >= 1080)) { - spin_lock_init(&tl1_preview_lock); tl1_vdin1_preview_flag = 1; max_ignore_frames[devp->index] = 9; } @@ -724,14 +715,16 @@ void vdin_stop_dec(struct vdin_dev_s *devp) if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) vdin_afbce_hw_disable(); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + vdin_dolby_addr_release(devp, devp->vfp->size); +#endif + #ifdef CONFIG_CMA if (devp->afbce_mode == 1) vdin_afbce_cma_release(devp); else if (devp->afbce_mode == 0) vdin_cma_release(devp); #endif - vdin_dolby_addr_release(devp, devp->vfp->size); - switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0, VPU_MEM_POWER_DOWN); memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s)); @@ -803,18 +796,7 @@ int start_tvin_service(int no, struct vdin_parm_s *para) else return -EBUSY; } - if ((para->port != TVIN_PORT_VIU1) || - (viu_hw_irq != 0)) { - ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, - devp->irq_name, (void *)devp); - if (ret != 0) { - pr_info("vdin_v4l2_isr request irq error.\n"); - return -1; - } - devp->flags |= VDIN_FLAG_ISR_REQ; - /*disable vsync irq until vdin configured completely*/ - disable_irq_nosync(devp->irq); - } + vdin_clk_onoff(devp, true); /*config the vdin use default value*/ vdin_set_default_regmap(devp->addr_offset); @@ -896,6 +878,16 @@ int start_tvin_service(int no, struct vdin_parm_s *para) devp->flags |= VDIN_FLAG_DEC_OPENED; devp->flags |= VDIN_FLAG_DEC_STARTED; + if ((para->port != TVIN_PORT_VIU1) || + (viu_hw_irq != 0)) { + ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, + devp->irq_name, (void *)devp); + if (ret != 0) { + pr_info("vdin_v4l2_isr request irq error.\n"); + return -1; + } + devp->flags |= VDIN_FLAG_ISR_REQ; + } return 0; } EXPORT_SYMBOL(start_tvin_service); @@ -2316,6 +2308,16 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } vdin_start_dec(devp); + + if ((devp->parm.port != TVIN_PORT_VIU1) || + (viu_hw_irq != 0)) { + /*enable irq */ + enable_irq(devp->irq); + if (vdin_dbg_en) + pr_info("****[%s]enable_irq ifdef VDIN_V2****\n", + __func__); + } + devp->flags |= VDIN_FLAG_DEC_STARTED; if (vdin_dbg_en) pr_info("TVIN_IOC_START_DEC port %s, decode started ok\n\n", @@ -2326,29 +2328,19 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_lock(&devp_vdin1->fe_lock); if ((tl1_vdin1_preview_flag == 1) && !(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) { - msleep(150); + /*msleep(150);*/ devp_vdin1->flags |= VDIN_FLAG_FS_OPENED; - if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) { - ret = request_irq(devp_vdin1->irq, vdin_isr, - IRQF_SHARED, - devp_vdin1->irq_name, - (void *)devp_vdin1); - if (ret != 0) { - pr_info("tl1_vdin1_preview request irq error.\n"); - return -1; - } - devp_vdin1->flags |= VDIN_FLAG_ISR_REQ; - disable_irq_nosync(devp_vdin1->irq); - /*init queue*/ - init_waitqueue_head(&devp_vdin1->queue); - } devp_vdin1->unstable_flag = false; devp_vdin1->parm.info.fmt = fmt; devp_vdin1->parm.port = devp->parm.port; devp_vdin1->fmt_info_p = (struct tvin_format_s *) - tvin_get_fmt_info(fmt); + tvin_get_fmt_info(fmt); + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) { + /*init queue*/ + init_waitqueue_head(&devp_vdin1->queue); + ret = vdin_open_fe(devp_vdin1->parm.port, 0, devp_vdin1); if (ret) { @@ -2372,6 +2364,23 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) vdin_start_dec(devp_vdin1); devp_vdin1->flags |= VDIN_FLAG_DEC_STARTED; + if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) { + ret = request_irq(devp_vdin1->irq, vdin_isr, + IRQF_SHARED, + devp_vdin1->irq_name, + (void *)devp_vdin1); + if (ret != 0) { + pr_info("tl1_vdin1_preview request irq error.\n"); + return -1; + } + devp_vdin1->flags |= VDIN_FLAG_ISR_REQ; + } else { + enable_irq(devp_vdin1->irq); + if (vdin_dbg_en) + pr_info("****[%s]enable_vdin1_irq****\n", + __func__); + } + pr_info("TVIN_IOC_START_DEC port %s, vdin1 used for preview\n", tvin_port_str(devp_vdin1->parm.port)); } @@ -3050,6 +3059,8 @@ static int vdin_drv_probe(struct platform_device *pdev) else vdevp->color_depth_mode = 0; + /* use for tl1 vdin1 preview */ + spin_lock_init(&tl1_preview_lock); /*set afbce mode*/ ret = of_property_read_u32(pdev->dev.of_node, "afbce_bit_mode", &vdevp->afbce_mode); From d2c943d677ef1720375f10b1460c6dcbfb54ab89 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 27 Mar 2019 11:19:21 +0800 Subject: [PATCH 0597/1060] vdin: sync vdin0 & vdin1 buffer for afbc mode to avoid garbage screen [1/1] PD#SWPL-3431 Problem: enter hdmi 4k port will flash garbage screen with afbc mode Solution: sync vdin0 & vdin1 buffer for afbc mode Verify: x301 Change-Id: I443a9be2ed619a5cd2b6229f15814d8b856c5535 Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c --- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 42 ++- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 291 +++++++++++++++--- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 4 + 3 files changed, 291 insertions(+), 46 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 588b5eb5ba87..61bb73038383 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -850,8 +850,11 @@ static void vdin_dump_state(struct vdin_dev_s *devp) i, devp->afbce_info->fm_body_paddr[i], devp->afbce_info->frame_body_size); } + if (is_meson_tl1_cpu()) { + pr_info("tl1 preview flag = %d\n", + tl1_vdin1_preview_flag); + } } - pr_info("tl1 preview flag = %d\n", tl1_vdin1_preview_flag); pr_info("Vdin driver version : %s\n", VDIN_VER); } @@ -2108,6 +2111,43 @@ start_chk: } else if (parm[1] != NULL) { vdin_dump_one_afbce_mem(parm[1], devp, 0); } + } else if (!strcmp(parm[0], "skip_frame_debug")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &skip_frame_debug) == 0) + pr_info("set skip_frame_debug: %d\n", + skip_frame_debug); + } else { + pr_info("skip_frame_debug: %d\n", skip_frame_debug); + } + } else if (!strcmp(parm[0], "afbc_preview_drop_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, + &vdin_afbc_preview_force_drop_frame_cnt) == 0) + pr_info("set vdin_afbc_preview_force_drop_frame_cnt: %d\n", + vdin_afbc_preview_force_drop_frame_cnt); + } else { + pr_info("vdin_afbc_preview_force_drop_frame_cnt: %d\n", + vdin_afbc_preview_force_drop_frame_cnt); + } + } else if (!strcmp(parm[0], "afbc_drop_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, + &vdin_afbc_force_drop_frame_cnt) == 0) + pr_info("set vdin_afbc_force_drop_frame_cnt: %d\n", + vdin_afbc_force_drop_frame_cnt); + } else { + pr_info("vdin_afbc_force_drop_frame_cnt: %d\n", + vdin_afbc_force_drop_frame_cnt); + } + } else if (!strcmp(parm[0], "max_ignore_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &max_ignore_frame_cnt) == 0) + pr_info("set max_ignore_frame_cnt: %d\n", + max_ignore_frame_cnt); + } else { + pr_info("max_ignore_frame_cnt: %d\n", + max_ignore_frame_cnt); + } } else { pr_info("unknown command\n"); } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 6475d725150b..758661dd8605 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -96,12 +96,22 @@ spinlock_t tl1_preview_lock; static int canvas_config_mode = 2; static bool work_mode_simple; static int phase_lock_flag; -static int max_ignore_frames[2] = {2, 2}; +static int max_ignore_frames[2] = {2, 1}; /*game_mode_switch_frames:min num is 5 by 1080p60hz input test*/ static int game_mode_switch_frames = 10; static int game_mode_phlock_switch_frames = 60; static int ignore_frames[2] = {0, 0}; static unsigned int dv_work_delby; + +static int tl1_vdin1_preview_ready_flag; +static unsigned int vdin_afbc_force_drop_frame = 1; +static struct vf_entry *vfe_drop_force; + +unsigned int vdin_afbc_preview_force_drop_frame_cnt = 1; +unsigned int vdin_afbc_force_drop_frame_cnt = 2; +unsigned int max_ignore_frame_cnt = 2; +unsigned int skip_frame_debug; + /* viu isr select: * enable viu_hw_irq for the bandwidth is enough on gxbb/gxtvbb and laters ic */ @@ -115,18 +125,12 @@ MODULE_PARM_DESC(canvas_config_mode, "canvas configure mode"); module_param(work_mode_simple, bool, 0664); MODULE_PARM_DESC(work_mode_simple, "enable/disable simple work mode"); -//module_param(max_ignore_frames, int, 0664); -//MODULE_PARM_DESC(max_ignore_frames, "ignore first frames"); - -//module_param(ignore_frames, int, 0664); -//MODULE_PARM_DESC(ignore_frames, "ignore first frames"); +module_param(viu_hw_irq, bool, 0664); +MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); module_param(dv_work_delby, uint, 0664); MODULE_PARM_DESC(dv_work_delby, "dv_work_delby"); -module_param(viu_hw_irq, bool, 0664); -MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); - module_param(game_mode_switch_frames, int, 0664); MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch frames"); #endif @@ -209,13 +213,18 @@ int vdin_open_fe(enum tvin_port_e port, int index, struct vdin_dev_s *devp) devp->frontend = fe; devp->parm.port = port; - /* for atv snow function */ - if ((port == TVIN_PORT_CVBS3) && - (devp->parm.info.fmt == TVIN_SIG_FMT_NULL)) - devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; - else - devp->parm.info.fmt = TVIN_SIG_FMT_NULL; - devp->parm.info.status = TVIN_SIG_STATUS_NULL; + /* don't change parm.info for tl1_vdin1_preview, + * for it should follow vdin0 parm.info + */ + if (tl1_vdin1_preview_flag == 0) { + /* for atv snow function */ + if ((port == TVIN_PORT_CVBS3) && + (devp->parm.info.fmt == TVIN_SIG_FMT_NULL)) + devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; + else + devp->parm.info.fmt = TVIN_SIG_FMT_NULL; + devp->parm.info.status = TVIN_SIG_STATUS_NULL; + } /* clear color para*/ memset(&devp->pre_prop, 0, sizeof(devp->pre_prop)); /* clear color para*/ @@ -644,10 +653,22 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); - if ((devp->afbce_mode == 1) && is_meson_tl1_cpu() && - (devp->h_active >= 1920) && (devp->v_active >= 1080)) { - tl1_vdin1_preview_flag = 1; - max_ignore_frames[devp->index] = 9; + if ((devp->afbce_mode == 1) && is_meson_tl1_cpu()) { + if ((devp->h_active >= 1920) && (devp->v_active >= 1080)) { + tl1_vdin1_preview_flag = 1; + tl1_vdin1_data_readied = 0; + tl1_vdin1_preview_ready_flag = 0; + vdin_afbc_force_drop_frame = + vdin_afbc_preview_force_drop_frame_cnt; + pr_info("vdin.%d tl1_vdin1_preview state init\n", + devp->index); + } else { + tl1_vdin1_preview_flag = 0; + vdin_afbc_force_drop_frame = + vdin_afbc_force_drop_frame_cnt; + } + vfe_drop_force = NULL; + max_ignore_frames[devp->index] = max_ignore_frame_cnt; } } @@ -674,7 +695,6 @@ void vdin_stop_dec(struct vdin_dev_s *devp) #endif disable_irq_nosync(devp->irq); afbc_init_flag[devp->index] = 0; - max_ignore_frames[devp->index] = 2; if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { while (++afbc_write_down_flag[devp->index] < @@ -685,6 +705,10 @@ void vdin_stop_dec(struct vdin_dev_s *devp) break; } } + if (is_meson_tl1_cpu() && (tl1_vdin1_preview_flag == 1)) { + if (devp->index == 1) + tl1_vdin1_preview_flag = 0; + } if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && devp->frontend->dec_ops && @@ -1295,6 +1319,47 @@ static void vdin_hist_tgt(struct vdin_dev_s *devp, struct vframe_s *vf) spin_unlock_irqrestore(&devp->hist_lock, flags); } +static bool vdin_skip_frame_check(struct vdin_dev_s *devp) +{ + ulong flags = 0; + int skip_flag = 0; + + spin_lock_irqsave(&tl1_preview_lock, flags); + if (devp->afbce_mode == 0) { + spin_unlock_irqrestore(&tl1_preview_lock, flags); + return false; + } + + if (tl1_vdin1_preview_flag == 1) { + if (tl1_vdin1_preview_ready_flag == 0) { + skip_flag = 1; + } else { + if (vdin_afbc_force_drop_frame > 0) { + vdin_afbc_force_drop_frame--; + skip_flag = 1; + } + } + } else { + if (vdin_afbc_force_drop_frame > 0) { + vdin_afbc_force_drop_frame--; + skip_flag = 1; + } + } + + if (skip_flag) { + vfe_drop_force = receiver_vf_get(devp->vfp); + if (vfe_drop_force) + receiver_vf_put(&vfe_drop_force->vf, devp->vfp); + else + pr_info("vdin.%d: skip vf get error\n", devp->index); + spin_unlock_irqrestore(&tl1_preview_lock, flags); + return true; + } + + spin_unlock_irqrestore(&tl1_preview_lock, flags); + return false; +} + /* *VDIN_FLAG_RDMA_ENABLE=1 * provider_vf_put(devp->last_wr_vfe, devp->vfp); @@ -1333,6 +1398,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!devp->frontend) { devp->vdin_irq_flag = 1; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } @@ -1374,6 +1443,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_hw_disable(offset); devp->flags &= ~VDIN_FLAG_DEC_STOP_ISR; devp->vdin_irq_flag = 2; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } @@ -1385,8 +1458,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) /*save the first field stamp*/ devp->stamp = stamp; devp->vdin_irq_flag = 3; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } + /* use RDMA and not game mode */ if (devp->last_wr_vfe && (devp->flags&VDIN_FLAG_RDMA_ENABLE) && !(devp->game_mode & VDIN_GAME_MODE_1) && !(devp->game_mode & VDIN_GAME_MODE_2)) { @@ -1419,6 +1497,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id) tl1_vdin1_height; devp->last_wr_vfe->vf.width = tl1_vdin1_width; + tl1_vdin1_preview_ready_flag = 1; + } else { + tl1_vdin1_preview_ready_flag = 0; } } else if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { @@ -1440,6 +1521,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } else { devp->vdin_irq_flag = 15; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1459,17 +1544,34 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vf_notify_receiver("dv_vdin", VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + else { #endif - vf_notify_receiver(devp->name, + if (vdin_skip_frame_check(devp)) { + devp->vdin_irq_flag = 16; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + NULL); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } +#endif } } /*check vs is valid base on the time during continuous vs*/ if (vdin_check_cycle(devp) && (!(isr_flag & VDIN_BYPASS_CYC_CHECK)) && (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) { devp->vdin_irq_flag = 4; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1495,6 +1597,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (state != TVIN_SM_STATUS_STABLE)) && (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) { devp->vdin_irq_flag = 6; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1509,6 +1615,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) VIDTYPE_INTERLACE_BOTTOM) ) { devp->vdin_irq_flag = 7; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1539,6 +1649,11 @@ irqreturn_t vdin_isr(int irq, void *dev_id) pre_prop->color_fmt_range = prop->color_fmt_range; pre_prop->dest_cfmt = prop->dest_cfmt; ignore_frames[devp->index] = 0; + devp->vdin_irq_flag = 20; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1564,6 +1679,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) decops = devp->frontend->dec_ops; if (decops->decode_isr(devp->frontend, devp->hcnt64) == TVIN_BUF_SKIP) { devp->vdin_irq_flag = 8; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1572,10 +1691,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) curr_wr_vf->phase = sm_ops->get_secam_phase(devp->frontend) ? VFRAME_PHASE_DB : VFRAME_PHASE_DR; - if (ignore_frames[devp->index] < max_ignore_frames[devp->index]) { - ignore_frames[devp->index]++; devp->vdin_irq_flag = 12; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + ignore_frames[devp->index]++; vdin_drop_cnt++; goto irq_handled; } @@ -1583,6 +1705,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (sm_ops->check_frame_skip && sm_ops->check_frame_skip(devp->frontend)) { devp->vdin_irq_flag = 13; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; if (devp->flags&VDIN_FLAG_RDMA_ENABLE) ignore_frames[devp->index] = 0; @@ -1601,6 +1727,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) devp->index); } else { devp->vdin_irq_flag = 14; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ goto irq_handled; @@ -1712,6 +1842,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id) tl1_vdin1_height; curr_wr_vfe->vf.width = tl1_vdin1_width; + tl1_vdin1_preview_ready_flag = 1; + } else { + tl1_vdin1_preview_ready_flag = 0; } } else if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { @@ -1734,6 +1867,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } else { devp->vdin_irq_flag = 15; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1742,11 +1879,44 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_vf_disp_mode_update(curr_wr_vfe, devp->vfp); } /*switch to game mode 2 from game mode 1,otherwise may appear blink*/ - if ((devp->frame_cnt >= game_mode_switch_frames) && - (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN)) { - if (vdin_dbg_en) - pr_info("switch game mode (%d-->5)\n", devp->game_mode); - devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + if (is_meson_tl1_cpu()) { + if (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN) { + /* make sure phase lock for next few frames */ + if (vlock_get_phlock_flag()) + phase_lock_flag++; + if (phase_lock_flag >= game_mode_phlock_switch_frames) { + if (vdin_dbg_en) { + pr_info("switch game mode (%d-->5), frame_cnt=%d\n", + devp->game_mode, + devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_2); + } + } +#if 0 + if (phase_lock_flag >= game_mode_phlock_switch_frames) { + if (!vlock_get_phlock_flag()) + phase_lock_flag = 0; + if (vdin_dbg_en) { + pr_info( + "switch game mode to %d, frame_cnt=%d\n", + devp->game_mode, devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + } +#endif + } else { + if ((devp->frame_cnt >= game_mode_switch_frames) && + (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN)) { + if (vdin_dbg_en) { + pr_info( + "switch game mode (%d-->5), frame_cnt=%d\n", + devp->game_mode, devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + } } /* prepare for next input data */ @@ -1772,6 +1942,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || (devp->game_mode & VDIN_GAME_MODE_1)) { + /* not RDMA, or game mode 1 */ if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); @@ -1783,13 +1954,27 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vf_notify_receiver("dv_vdin", VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + else { #endif - vf_notify_receiver(devp->name, + if (vdin_skip_frame_check(devp)) { + devp->vdin_irq_flag = 17; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + NULL); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } +#endif } } else if (devp->game_mode & VDIN_GAME_MODE_2) { + /* game mode 2 */ spin_lock_irqsave(&tl1_preview_lock, flags1); if ((devp->index == 0) && (tl1_vdin1_preview_flag == 1)) { @@ -1801,6 +1986,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id) tl1_vdin1_height; next_wr_vfe->vf.width = tl1_vdin1_width; + tl1_vdin1_preview_ready_flag = 1; + } else { + tl1_vdin1_preview_ready_flag = 0; } } else if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { @@ -1818,23 +2006,34 @@ irqreturn_t vdin_isr(int irq, void *dev_id) //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { - vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - if (vdin_dbg_en) { - next_wr_vfe->vf.ready_clock[1] = - sched_clock(); - pr_info("vdin put latency %lld us.first %lld us\n", + if (vdin_skip_frame_check(devp)) { + devp->vdin_irq_flag = 18; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + if (vdin_dbg_en) { + next_wr_vfe->vf.ready_clock[1] = + sched_clock(); + pr_info("vdin put latency %lld us.first %lld us\n", func_div(next_wr_vfe->vf.ready_clock[1], - 1000), + 1000), func_div(next_wr_vfe->vf.ready_clock[0], - 1000)); + 1000)); + } } } } devp->frame_cnt++; irq_handled: - /*hdmi skip policy should adapt to all drop vframe case*/ + /*hdmi skip policy should adapt to all drop front vframe case*/ if ((devp->vfp->skip_vf_num > 0) && (vf_drop_cnt < vdin_drop_cnt)) vdin_vf_disp_mode_skip(devp->vfp); @@ -2334,8 +2533,9 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) devp_vdin1->unstable_flag = false; devp_vdin1->parm.info.fmt = fmt; devp_vdin1->parm.port = devp->parm.port; + devp_vdin1->parm.info.status = TVIN_SIG_STATUS_STABLE; devp_vdin1->fmt_info_p = (struct tvin_format_s *) - tvin_get_fmt_info(fmt); + tvin_get_fmt_info(fmt); if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) { /*init queue*/ @@ -2371,7 +2571,8 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (void *)devp_vdin1); if (ret != 0) { pr_info("tl1_vdin1_preview request irq error.\n"); - return -1; + mutex_unlock(&devp_vdin1->fe_lock); + break; } devp_vdin1->flags |= VDIN_FLAG_ISR_REQ; } else { diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 1295cf44ece1..0b0bc076eafe 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -363,6 +363,10 @@ struct vdin_v4l2_param_s { }; extern unsigned int tl1_vdin1_preview_flag; +extern unsigned int vdin_afbc_preview_force_drop_frame_cnt; +extern unsigned int vdin_afbc_force_drop_frame_cnt; +extern unsigned int max_ignore_frame_cnt; +extern unsigned int skip_frame_debug; extern struct vframe_provider_s *vf_get_provider_by_name( const char *provider_name); From dc0d79e6fa2658f2dd99b52501479dece1fc5b48 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 5 Apr 2019 20:52:27 +0800 Subject: [PATCH 0598/1060] vdin: config vdin mif/afbc path directly [1/1] PD#SWPL-6277 Problem: switch hdmi port maybe display green screen Solution: 1.optimize vdin stop sequence, reduce afbc state polling interval, and rest afbc to get a clean state 2.change vdin mif/afbc patch directly, not rdma method, for vdin0/1 rdma are independent Verify: x301 Change-Id: I0ddf5d27dcfc0fd930eeb681f876c4c5e92e8d70 Signed-off-by: Evoke Zhang --- .../amlogic/media/vin/tvin/vdin/vdin_afbce.c | 32 +++++++----- .../amlogic/media/vin/tvin/vdin/vdin_afbce.h | 1 + .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 50 +++++++++++-------- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index 35032f402671..f34179b1205e 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -363,6 +363,7 @@ void vdin_afbce_cma_release(struct vdin_dev_s *devp) devp->cma_mem_alloc = 0; } +/*can not use RDMA, because vdin0/1 both use the register */ void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, enum vdin_output_mif_e sel) { @@ -370,37 +371,37 @@ void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, if (offset == 0) { if (sel == VDIN_OUTPUT_TO_MIF) { - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_MIF_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_AFBCE_BIT, 1); } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_MIF_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_AFBCE_BIT, 1); } } else { if (sel == VDIN_OUTPUT_TO_MIF) { - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_MIF_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_AFBCE_BIT, 1); } else if (sel == VDIN_OUTPUT_TO_AFBCE) { /*sel vdin1 afbce: not support in sw now, *just reserved interface */ - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_MIF_BIT, 1); - rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_AFBCE_BIT, 1); } } @@ -694,3 +695,10 @@ void vdin_afbce_hw_enable(struct vdin_dev_s *devp) //enable afbce rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 8, 1); } + +void vdin_afbce_soft_reset(void) +{ + W_VCBUS_BIT(AFBCE_MODE, 0, 30, 1); + W_VCBUS_BIT(AFBCE_MODE, 1, 30, 1); + W_VCBUS_BIT(AFBCE_MODE, 0, 30, 1); +} diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h index 9cc81e3a47f6..b2a6882eea2f 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h @@ -312,5 +312,6 @@ extern void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp); extern int vdin_afbce_read_writedown_flag(void); extern void vdin_afbce_hw_disable(void); extern void vdin_afbce_hw_enable(struct vdin_dev_s *devp); +extern void vdin_afbce_soft_reset(void); #endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 758661dd8605..12850dc6ed96 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -79,7 +79,6 @@ static struct vdin_dev_s *vdin_devp[VDIN_MAX_DEVS]; static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; static int afbc_init_flag[VDIN_MAX_DEVS]; -static int afbc_write_down_flag[VDIN_MAX_DEVS]; static unsigned int pr_times; unsigned int tl1_vdin1_preview_flag; static unsigned int tl1_vdin1_data_readied; @@ -107,8 +106,8 @@ static int tl1_vdin1_preview_ready_flag; static unsigned int vdin_afbc_force_drop_frame = 1; static struct vf_entry *vfe_drop_force; -unsigned int vdin_afbc_preview_force_drop_frame_cnt = 1; -unsigned int vdin_afbc_force_drop_frame_cnt = 2; +unsigned int vdin_afbc_preview_force_drop_frame_cnt; +unsigned int vdin_afbc_force_drop_frame_cnt; unsigned int max_ignore_frame_cnt = 2; unsigned int skip_frame_debug; @@ -533,7 +532,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) } #endif - afbc_write_down_flag[devp->index] = 0; /* h_active/v_active will be used by bellow calling */ if (devp->afbce_mode == 0) { if (canvas_config_mode == 1) @@ -682,7 +680,8 @@ void vdin_start_dec(struct vdin_dev_s *devp) */ void vdin_stop_dec(struct vdin_dev_s *devp) { - int afbc_write_down_test_times = 7; + int afbc_write_down_timeout = 500; /* 50ms to cover a 24Hz vsync */ + int i = 0; /* avoid null pointer oops */ if (!devp || !devp->frontend) @@ -693,16 +692,19 @@ void vdin_stop_dec(struct vdin_dev_s *devp) return; } #endif + disable_irq_nosync(devp->irq); afbc_init_flag[devp->index] = 0; if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { - while (++afbc_write_down_flag[devp->index] < - afbc_write_down_test_times) { - if (vdin_afbce_read_writedown_flag() == 0) - usleep_range(5000, 5001); - else + while (i++ < afbc_write_down_timeout) { + if (vdin_afbce_read_writedown_flag()) break; + usleep_range(100, 105); + } + if (i >= afbc_write_down_timeout) { + pr_info("vdin.%d afbc write done timeout\n", + devp->index); } } if (is_meson_tl1_cpu() && (tl1_vdin1_preview_flag == 1)) { @@ -736,8 +738,10 @@ void vdin_stop_dec(struct vdin_dev_s *devp) vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { vdin_afbce_hw_disable(); + vdin_afbce_soft_reset(); + } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION vdin_dolby_addr_release(devp, devp->vfp->size); @@ -1414,17 +1418,16 @@ irqreturn_t vdin_isr(int irq, void *dev_id) offset = devp->addr_offset; - if (afbc_init_flag[devp->index] == 0) { - afbc_init_flag[devp->index] = 1; - /*set mem power on*/ - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + if (afbc_init_flag[devp->index] == 0) { + afbc_init_flag[devp->index] = 1; + /*set mem power on*/ vdin_afbce_hw_enable(devp); return IRQ_HANDLED; - } - } else if (afbc_init_flag[devp->index] == 1) { - afbc_init_flag[devp->index] = 2; - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + } else if (afbc_init_flag[devp->index] == 1) { + afbc_init_flag[devp->index] = 2; return IRQ_HANDLED; + } } isr_log(devp->vfp); @@ -1436,8 +1439,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) */ spin_lock_irqsave(&devp->isr_lock, flags); - /* W_VCBUS_BIT(VDIN_MISC_CTRL, 0, 0, 2); */ - devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); + if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + /* no need reset mif under afbc mode */ + devp->vdin_reset_flag = 0; + } else { + /* W_VCBUS_BIT(VDIN_MISC_CTRL, 0, 0, 2); */ + devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); + } if ((devp->flags & VDIN_FLAG_DEC_STOP_ISR) && (!(isr_flag & VDIN_BYPASS_STOP_CHECK))) { vdin_hw_disable(offset); From 6aa334dcd939b9d4459d5a33a6775a6c6aa02787 Mon Sep 17 00:00:00 2001 From: Nian Jing Date: Thu, 4 Apr 2019 20:46:46 +0800 Subject: [PATCH 0599/1060] vdin: add vdin support for tm2 [1/1] PD#SWPL-6701 Problem: Need vdin supprt for sm2 Solution: add vdin support for tm2 Verify: test pass on tm2 ab311 Change-Id: I57d7b3014938011d18c5e168f18c78e4fa542fc7 Signed-off-by: Nian Jing Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c drivers/amlogic/media/vin/tvin/viu/viuin.c --- .../media/vin/tvin/bt656/bt656_601_in.c | 3 +- .../amlogic/media/vin/tvin/vdin/vdin_ctl.c | 52 ++++++++++++++----- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 50 +++++++++++++----- drivers/amlogic/media/vin/tvin/viu/viuin.c | 14 +++-- 4 files changed, 87 insertions(+), 32 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c index 0feac45d341b..4f02b42017ae 100644 --- a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c +++ b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c @@ -1129,7 +1129,8 @@ static int amvdec_656in_probe(struct platform_device *pdev) if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { hw_cnt = 1; } else if (is_meson_gxbb_cpu()) { hw_cnt = 2; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index af904757df26..e2f649ca63a1 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -663,7 +663,9 @@ static void vdin_set_meas_mux(unsigned int offset, enum tvin_port_e port_, meas_mux = MEAS_MUX_656_B; else if ((is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && (bt_path == BT_PATH_GPIO)) + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && + (bt_path == BT_PATH_GPIO)) meas_mux = MEAS_MUX_656; else pr_info("cpu not define or do not support bt656"); @@ -774,7 +776,9 @@ void vdin_set_top(unsigned int offset, VDI9_ASFIFO_CTRL_BIT, VDI9_ASFIFO_CTRL_WID); } else if ((is_meson_gxm_cpu() || is_meson_gxl_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && (bt_path == BT_PATH_GPIO)) { + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && + (bt_path == BT_PATH_GPIO)) { vdin_mux = VDIN_MUX_656; wr_bits(offset, VDIN_ASFIFO_CTRL0, 0xe4, VDI1_ASFIFO_CTRL_BIT, VDI1_ASFIFO_CTRL_WID); @@ -822,18 +826,36 @@ void vdin_set_top(unsigned int offset, if (port != TVIN_PORT_VIU1) wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xe4, VDI6_ASFIFO_CTRL_BIT, VDI6_ASFIFO_CTRL_WID); - else - wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, - VDI6_ASFIFO_CTRL_BIT, VDI6_ASFIFO_CTRL_WID); + else { + if (/*is_meson_gxlx2_cpu() || */is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xd4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + else + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + } break; case 0xc0: /* viu2 */ vdin_mux = VDIN_MUX_VIU_2; if (port != TVIN_PORT_VIU2) wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xe4, VDI8_ASFIFO_CTRL_BIT, VDI8_ASFIFO_CTRL_WID); - else - wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, - VDI8_ASFIFO_CTRL_BIT, VDI8_ASFIFO_CTRL_WID); + else { + if (/*is_meson_gxlx2_cpu() || */is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xd4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + else + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + } break; case 0x100:/* mipi in mybe need modify base on truth */ vdin_mux = VDIN_MUX_MIPI; @@ -1568,7 +1590,8 @@ void vdin_set_matrix(struct vdin_dev_s *devp) */ wr_bits(offset, VDIN_MATRIX_CTRL, 0, VDIN_MATRIX1_EN_BIT, VDIN_MATRIX1_EN_WID); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1601,7 +1624,8 @@ void vdin_set_matrix(struct vdin_dev_s *devp) devp->prop.color_fmt_range, devp->prop.vdin_hdr_Flag, devp->color_range_mode); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1636,7 +1660,8 @@ void vdin_set_matrixs(struct vdin_dev_s *devp, unsigned char id, { switch (id) { case 0: - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1686,7 +1711,8 @@ void vdin_set_prob_xy(unsigned int offset, devp->prop.color_fmt_range, devp->prop.vdin_hdr_Flag, devp->color_range_mode); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -2699,6 +2725,8 @@ void vdin_set_default_regmap(unsigned int offset) is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() || is_meson_tl1_cpu()) wr(offset, VDIN_LFIFO_CTRL, 0x00000f00); + else if (is_meson_tm2_cpu()) + wr(offset, VDIN_LFIFO_CTRL, 0xc0020f00); else wr(offset, VDIN_LFIFO_CTRL, 0x00000780); /* [15:14] clkgate.bbar = 0/(auto, off, on, on) */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 12850dc6ed96..b74bcde44b5e 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -296,8 +296,14 @@ static void vdin_game_mode_check(struct vdin_dev_s *devp) (devp->parm.port != TVIN_PORT_CVBS3)) { if (devp->h_active > 720 && ((devp->parm.info.fps == 50) || (devp->parm.info.fps == 60))) - devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | - VDIN_GAME_MODE_SWITCH_EN); + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + } else { + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_1); + } else devp->game_mode = VDIN_GAME_MODE_0; } else if (game_mode == 2)/*for debug force game mode*/ @@ -591,7 +597,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_hw_enable(devp->addr_offset); vdin_set_all_regs(devp); - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { if (devp->afbce_mode == 0) vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); else if (devp->afbce_mode == 1) @@ -651,7 +657,8 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); - if ((devp->afbce_mode == 1) && is_meson_tl1_cpu()) { + if ((devp->afbce_mode == 1) && + (is_meson_tl1_cpu() || is_meson_tm2_cpu())) { if ((devp->h_active >= 1920) && (devp->v_active >= 1080)) { tl1_vdin1_preview_flag = 1; tl1_vdin1_data_readied = 0; @@ -696,7 +703,8 @@ void vdin_stop_dec(struct vdin_dev_s *devp) disable_irq_nosync(devp->irq); afbc_init_flag[devp->index] = 0; - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) + && (devp->afbce_mode == 1)) { while (i++ < afbc_write_down_timeout) { if (vdin_afbce_read_writedown_flag()) break; @@ -738,7 +746,8 @@ void vdin_stop_dec(struct vdin_dev_s *devp) vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) + && (devp->afbce_mode == 1)) { vdin_afbce_hw_disable(); vdin_afbce_soft_reset(); } @@ -1418,7 +1427,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) offset = devp->addr_offset; - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) + && (devp->afbce_mode == 1)) { if (afbc_init_flag[devp->index] == 0) { afbc_init_flag[devp->index] = 1; /*set mem power on*/ @@ -1887,7 +1897,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_vf_disp_mode_update(curr_wr_vfe, devp->vfp); } /*switch to game mode 2 from game mode 1,otherwise may appear blink*/ - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { if (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN) { /* make sure phase lock for next few frames */ if (vlock_get_phlock_flag()) @@ -2293,7 +2303,8 @@ static int vdin_open(struct inode *inode, struct file *file) return 0; } - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + if ((devp->afbce_mode == 1) && + (is_meson_tl1_cpu() || is_meson_tm2_cpu())) switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_ON); devp->flags |= VDIN_FLAG_FS_OPENED; @@ -2342,7 +2353,8 @@ static int vdin_release(struct inode *inode, struct file *file) return 0; } - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) + if ((devp->afbce_mode == 1) && + (is_meson_tl1_cpu() || is_meson_tm2_cpu())) switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_DOWN); devp->flags &= (~VDIN_FLAG_FS_OPENED); @@ -2991,7 +3003,11 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EFAULT; } memset(¶m, 0, sizeof(struct vdin_parm_s)); - param.port = TVIN_PORT_VIU1; + if (is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + param.port = TVIN_PORT_VIU1_WB0_VPP; + else + param.port = TVIN_PORT_VIU1; param.reserved |= PARAM_STATE_HISTGRAM; param.h_active = vdin_v4l2_param.width; param.v_active = vdin_v4l2_param.height; @@ -3277,7 +3293,10 @@ static int vdin_drv_probe(struct platform_device *pdev) vdevp->afbce_mode = 0; pr_info("no afbce mode found, use normal mode\n"); } else { - if ((is_meson_tl1_cpu()) && (vdevp->index == 0)) { + vdevp->afbce_mode = val & 0xf; + vdevp->afbce_lossy_en = (val>>4)&0xf; + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) && + (vdevp->index == 0)) { /* just use afbce at vdin0 */ pr_info("afbce mode = %d\n", vdevp->afbce_mode); vdevp->afbce_info = devm_kzalloc(vdevp->dev, @@ -3309,12 +3328,15 @@ static int vdin_drv_probe(struct platform_device *pdev) if (is_meson_gxbb_cpu() && vdevp->index) vdin_addr_offset[vdevp->index] = 0x70; else if ((is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && vdevp->index) + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && vdevp->index) vdin_addr_offset[vdevp->index] = 0x100; vdevp->addr_offset = vdin_addr_offset[vdevp->index]; vdevp->flags = 0; /*canvas align number*/ - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) vdevp->canvas_align = 64; else vdevp->canvas_align = 32; diff --git a/drivers/amlogic/media/vin/tvin/viu/viuin.c b/drivers/amlogic/media/vin/tvin/viu/viuin.c index 3fe16a66aaae..5da1da6ce8b2 100644 --- a/drivers/amlogic/media/vin/tvin/viu/viuin.c +++ b/drivers/amlogic/media/vin/tvin/viu/viuin.c @@ -178,8 +178,9 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) /*open the venc to vdin path*/ switch (rd_bits_viu(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0: - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) viu_mux = 0x4; else viu_mux = 0x8; @@ -213,7 +214,9 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) wr_viu(VPU_VIU2VDIN_HDN_CTRL, 0x40f00); } else wr_bits_viu(VPU_VIU2VDIN_HDN_CTRL, devp->parm.h_active, 0, 14); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { if (((port >= TVIN_PORT_VIU1_WB0_VD1) && (port <= TVIN_PORT_VIU1_WB0_POST_BLEND)) || ((port >= TVIN_PORT_VIU2_WB0_VD1) && @@ -308,8 +311,9 @@ static void viuin_close(struct tvin_frontend_s *fe) if (open_cnt) open_cnt--; if (open_cnt == 0) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { wr_viu(VPU_VIU_VDIN_IF_MUX_CTRL, 0); wr_viu(VPP_WRBAK_CTRL, 0); From 696db5f90369d3645eaca01eca16dcbb322f9b81 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 10 Apr 2019 10:07:39 +0800 Subject: [PATCH 0600/1060] vdin: ignore v4l2start/stop ioctl when vdin1 used for preview [1/1] PD#SWPL-6840 Problem: hdmi port can't screencap Solution: ignore v4l2start/stop ioctl when vdin1 used for preview Verify: x301 Change-Id: I26e7b057177a0b7ed203c04bd3008c2a34793b4a Signed-off-by: Evoke Zhang --- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index b74bcde44b5e..9fd8e5823079 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -86,6 +86,8 @@ static unsigned int tl1_vdin1_canvas_addr; static unsigned int tl1_vdin1_height; static unsigned int tl1_vdin1_width; spinlock_t tl1_preview_lock; + +static unsigned int tl1_vdin1_capture_flag; /* * canvas_config_mode * 0: canvas_config in driver probe @@ -657,9 +659,8 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); - if ((devp->afbce_mode == 1) && - (is_meson_tl1_cpu() || is_meson_tm2_cpu())) { - if ((devp->h_active >= 1920) && (devp->v_active >= 1080)) { + if (devp->afbce_mode == 1) { + if (is_meson_tl1_cpu()) { tl1_vdin1_preview_flag = 1; tl1_vdin1_data_readied = 0; tl1_vdin1_preview_ready_flag = 0; @@ -667,10 +668,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_afbc_preview_force_drop_frame_cnt; pr_info("vdin.%d tl1_vdin1_preview state init\n", devp->index); - } else { - tl1_vdin1_preview_flag = 0; - vdin_afbc_force_drop_frame = - vdin_afbc_force_drop_frame_cnt; } vfe_drop_force = NULL; max_ignore_frames[devp->index] = max_ignore_frame_cnt; @@ -801,9 +798,10 @@ int start_tvin_service(int no, struct vdin_parm_s *para) } if (tl1_vdin1_preview_flag == 1) { - pr_err("[vdin]%s vdin%d use for preview, return.\n", + tl1_vdin1_capture_flag = 1; + pr_info("[vdin]%s vdin%d already enabled for preview.\n", __func__, no); - return -1; + return 0; } fmt = devp->parm.info.fmt; if (vdin_dbg_en) { @@ -939,6 +937,13 @@ int stop_tvin_service(int no) struct vdin_dev_s *devp; unsigned int end_time; + if (tl1_vdin1_preview_flag == 1) { + tl1_vdin1_capture_flag = 0; + pr_info("[vdin]%s vdin%d is used for preview.\n", + __func__, no); + return 0; + } + devp = vdin_devp[no]; if ((devp->parm.reserved & PARAM_STATE_HISTGRAM) && (devp->parm.reserved & PARAM_STATE_SCREENCAP) && @@ -1551,7 +1556,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_vf_disp_mode_update(devp->last_wr_vfe, devp->vfp); devp->last_wr_vfe = NULL; - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && + (tl1_vdin1_capture_flag == 0)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -1755,7 +1761,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && + (tl1_vdin1_capture_flag == 0)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -1961,7 +1968,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || (devp->game_mode & VDIN_GAME_MODE_1)) { /* not RDMA, or game mode 1 */ - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && + (tl1_vdin1_capture_flag == 0)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -2020,7 +2028,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } spin_unlock_irqrestore(&tl1_preview_lock, flags1); provider_vf_put(next_wr_vfe, devp->vfp); - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && + (tl1_vdin1_capture_flag == 0)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -2994,6 +3003,10 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_S_VDIN_V4L2START cann't be used at vdin0\n"); break; } + if ((tl1_vdin1_preview_flag) && (devp->index == 1)) { + pr_info("TVIN_IOC_S_VDIN_V4L2START ignore for vdin1 is already enabled\n"); + break; + } if (devp->flags & VDIN_FLAG_ISR_REQ) free_irq(devp->irq, (void *)devp); @@ -3035,6 +3048,10 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_S_VDIN_V4L2STOP cann't be used at vdin0\n"); break; } + if ((tl1_vdin1_preview_flag) && (devp->index == 1)) { + pr_info("TVIN_IOC_S_VDIN_V4L2STOP ignore for vdin1 used for preview\n"); + break; + } devp->parm.reserved &= ~PARAM_STATE_HISTGRAM; devp->flags &= (~VDIN_FLAG_ISR_REQ); devp->flags &= (~VDIN_FLAG_FS_OPENED); From b36a407baca2a34d24b4fc489a455fffb162f019 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 15 Apr 2019 19:30:10 +0800 Subject: [PATCH 0601/1060] vdin: support dynamic dest_cfmt changing [1/1] PD#TV-4306 Problem: vdin afbc will show green screen when hdmirx change dest_cfmt after stable Solution: dynamic config vdin afbc with cfmt Verify: x301 Change-Id: I404c47934f090222a2cdd7cf98b619826cd92cc7 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vin/tvin/tvin_global.h | 9 +++ .../amlogic/media/vin/tvin/vdin/vdin_afbce.c | 68 ++++++++++++++++++- .../amlogic/media/vin/tvin/vdin/vdin_afbce.h | 1 + .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 14 +++- 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvin_global.h b/drivers/amlogic/media/vin/tvin/tvin_global.h index c6d053b06416..14f2cb43853f 100644 --- a/drivers/amlogic/media/vin/tvin/tvin_global.h +++ b/drivers/amlogic/media/vin/tvin/tvin_global.h @@ -116,6 +116,15 @@ static inline uint32_t R_APB_BIT(uint32_t reg, return val; } +static inline void W_VCBUS(uint32_t reg, const uint32_t value) +{ + aml_write_vcbus(reg, value); +} + +static inline uint32_t R_VCBUS(uint32_t reg) +{ + return aml_read_vcbus(reg); +} static inline void W_VCBUS_BIT(uint32_t reg, const uint32_t value, diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index f34179b1205e..b79291f75e56 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -412,10 +412,76 @@ static void afbce_wr(uint32_t reg, const uint32_t val) wr(0, reg, val); } */ +#define VDIN_AFBCE_HOLD_LINE_NUM 4 +void vdin_afbce_update(struct vdin_dev_s *devp) +{ + int hold_line_num = VDIN_AFBCE_HOLD_LINE_NUM; + int reg_format_mode;/* 0:444 1:422 2:420 */ + int reg_fmt444_comb; + int sblk_num; + int uncmp_bits; + int uncmp_size; + + if (devp->index != 0) { + pr_info("cat not use afbce on vdin1 at the moment\n"); + return; + } + +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA + pr_info("##############################################\n"); + pr_info("vdin afbce must use RDMA,but it not be opened\n"); + pr_info("##############################################\n"); +#endif + + if ((devp->prop.dest_cfmt == TVIN_YUV444) && (devp->h_active > 2048)) + reg_fmt444_comb = 1; + else + reg_fmt444_comb = 0; + + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) { + reg_format_mode = 2; + sblk_num = 12; + } else if ((devp->prop.dest_cfmt == TVIN_YUV422) || + (devp->prop.dest_cfmt == TVIN_YUYV422) || + (devp->prop.dest_cfmt == TVIN_YVYU422) || + (devp->prop.dest_cfmt == TVIN_UYVY422) || + (devp->prop.dest_cfmt == TVIN_VYUY422)) { + reg_format_mode = 1; + sblk_num = 16; + } else { + reg_format_mode = 0; + sblk_num = 24; + } + uncmp_bits = devp->source_bitdepth; + + /* bit size of uncompression mode */ + uncmp_size = (((((16*uncmp_bits*sblk_num)+7)>>3)+31)/32)<<1; + /* + *pr_info("%s: dest_cfmt=%d, reg_format_mode=%d, uncmp_bits=%d, + * sblk_num=%d, uncmp_size=%d\n", + * __func__, devp->prop.dest_cfmt, reg_format_mode, + * uncmp_bits, sblk_num, uncmp_size); + */ + + rdma_write_reg(devp->rdma_handle, AFBCE_MODE, + (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | + (hold_line_num & 0x7f) << 16 | + (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); + + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);/* uncmp_size */ + + rdma_write_reg(devp->rdma_handle, AFBCE_FORMAT, + (reg_format_mode & 0x3) << 8 | + (uncmp_bits & 0xf) << 4 | + (uncmp_bits & 0xf)); +} + void vdin_afbce_config(struct vdin_dev_s *devp) { unsigned int offset = devp->addr_offset; - int hold_line_num = 4; + int hold_line_num = VDIN_AFBCE_HOLD_LINE_NUM; int lbuf_depth = 256; int lossy_luma_en = 0; int lossy_chrm_en = 0; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h index b2a6882eea2f..08ad76fcf68c 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h @@ -304,6 +304,7 @@ extern void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, enum vdin_output_mif_e sel); extern unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp); extern void vdin_afbce_cma_release(struct vdin_dev_s *devp); +extern void vdin_afbce_update(struct vdin_dev_s *devp); extern void vdin_afbce_config(struct vdin_dev_s *devp); extern void vdin_afbce_maptable_init(struct vdin_dev_s *devp); extern void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 9fd8e5823079..df1da53fdf0d 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -1655,8 +1655,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) pre_prop = &devp->pre_prop; if ((prop->color_format != pre_prop->color_format) || (prop->vdin_hdr_Flag != pre_prop->vdin_hdr_Flag) || - (prop->color_fmt_range != pre_prop->color_fmt_range)) + (prop->color_fmt_range != pre_prop->color_fmt_range)) { vdin_set_matrix(devp); + if (skip_frame_debug) { + pr_info("vdin.%d color_format changed\n", + devp->index); + } + } if (prop->dest_cfmt != pre_prop->dest_cfmt) { vdin_set_bitdepth(devp); vdin_source_bitdepth_reinit(devp); @@ -1667,6 +1672,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_set_top(devp->addr_offset, devp->parm.port, devp->prop.color_format, devp->h_active, devp->bt_path); + if (devp->afbce_mode) + vdin_afbce_update(devp); + if (skip_frame_debug) { + pr_info("vdin.%d dest_cfmt changed: %d->%d\n", + devp->index, + pre_prop->dest_cfmt, prop->dest_cfmt); + } } pre_prop->color_format = prop->color_format; pre_prop->vdin_hdr_Flag = prop->vdin_hdr_Flag; From a67d5c06d585e0c57090f1c76aeae685307e7a2d Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 19 Apr 2019 11:30:42 +0800 Subject: [PATCH 0602/1060] vdin: recycle garbage frame for afbc mode [1/1] PD#TV-4335 Problem: switch tvin signals will flash garbage screen Solution: recycle barbage frame for afbc mode Verify: x301 Change-Id: I17c13b5db7a506403aa5ac74568b7a9e16c075c0 Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c | 10 ---------- drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c | 6 ++---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 61bb73038383..22b0204d35c2 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -2119,16 +2119,6 @@ start_chk: } else { pr_info("skip_frame_debug: %d\n", skip_frame_debug); } - } else if (!strcmp(parm[0], "afbc_preview_drop_cnt")) { - if (parm[1] != NULL) { - if (kstrtouint(parm[1], 10, - &vdin_afbc_preview_force_drop_frame_cnt) == 0) - pr_info("set vdin_afbc_preview_force_drop_frame_cnt: %d\n", - vdin_afbc_preview_force_drop_frame_cnt); - } else { - pr_info("vdin_afbc_preview_force_drop_frame_cnt: %d\n", - vdin_afbc_preview_force_drop_frame_cnt); - } } else if (!strcmp(parm[0], "afbc_drop_cnt")) { if (parm[1] != NULL) { if (kstrtouint(parm[1], 10, diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index df1da53fdf0d..c90c5eabf1d6 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -108,8 +108,7 @@ static int tl1_vdin1_preview_ready_flag; static unsigned int vdin_afbc_force_drop_frame = 1; static struct vf_entry *vfe_drop_force; -unsigned int vdin_afbc_preview_force_drop_frame_cnt; -unsigned int vdin_afbc_force_drop_frame_cnt; +unsigned int vdin_afbc_force_drop_frame_cnt = 2; unsigned int max_ignore_frame_cnt = 2; unsigned int skip_frame_debug; @@ -664,13 +663,12 @@ void vdin_start_dec(struct vdin_dev_s *devp) tl1_vdin1_preview_flag = 1; tl1_vdin1_data_readied = 0; tl1_vdin1_preview_ready_flag = 0; - vdin_afbc_force_drop_frame = - vdin_afbc_preview_force_drop_frame_cnt; pr_info("vdin.%d tl1_vdin1_preview state init\n", devp->index); } vfe_drop_force = NULL; max_ignore_frames[devp->index] = max_ignore_frame_cnt; + vdin_afbc_force_drop_frame = vdin_afbc_force_drop_frame_cnt; } } From 67e7d72cdfb86fb79ca3841df9a86c0431cce6d5 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Sat, 20 Apr 2019 17:55:10 +0800 Subject: [PATCH 0603/1060] vdin: disable afbce under 4k resolution [1/1] PD#SWPL-7511 Problem: no need enable vdin afbce under 4k, it is no help for bandwidth with these resolution Solution: only enable vdin afbce for 4k resolution Verify: x301 Change-Id: I283efd872004846d158ef6c9addbd1e666d2f61a Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c --- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 2 + .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 52 +++++++++++-------- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 1 + 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 22b0204d35c2..43396339946a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -828,6 +828,8 @@ static void vdin_dump_state(struct vdin_dev_s *devp) devp->dv.dv_flag, devp->dv.dv_config, devp->prop.dolby_vision); pr_info("size of struct vdin_dev_s: %d\n", devp->vdin_dev_ssize); + pr_info("afbce_flag: %d\n", devp->afbce_flag); + pr_info("afbce_mode: %d\n", devp->afbce_mode); if (devp->afbce_mode == 1) { for (i = 0; i < devp->vfmem_max_cnt; i++) { pr_info("head(%d) addr:0x%lx, size:0x%x\n", diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index c90c5eabf1d6..15e26736d1d5 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -78,8 +78,10 @@ static unsigned int vdin_addr_offset[VDIN_MAX_DEVS] = {0, 0x80}; static struct vdin_dev_s *vdin_devp[VDIN_MAX_DEVS]; static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; -static int afbc_init_flag[VDIN_MAX_DEVS]; static unsigned int pr_times; + +/* afbce related */ +static int afbc_init_flag[VDIN_MAX_DEVS]; unsigned int tl1_vdin1_preview_flag; static unsigned int tl1_vdin1_data_readied; static unsigned int tl1_vdin1_canvas_addr; @@ -522,6 +524,17 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_wr_reverse(devp->addr_offset, devp->parm.h_reverse, devp->parm.v_reverse); + + /* check if need enable afbce */ + if (devp->afbce_flag == 1) { + if ((devp->h_active > 1920) && (devp->v_active > 1080)) + devp->afbce_mode = 1; + else + devp->afbce_mode = 0; + pr_info("vdin%d afbce_mode: %d\n", + devp->index, devp->afbce_mode); + } + #ifdef CONFIG_CMA vdin_cma_malloc_mode(devp); if (devp->afbce_mode == 1) { @@ -598,12 +611,10 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_hw_enable(devp->addr_offset); vdin_set_all_regs(devp); - if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { - if (devp->afbce_mode == 0) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); - else if (devp->afbce_mode == 1) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); - } + if (devp->afbce_mode == 0) + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); + else if (devp->afbce_mode == 1) + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && (devp->frontend) && @@ -698,8 +709,7 @@ void vdin_stop_dec(struct vdin_dev_s *devp) disable_irq_nosync(devp->irq); afbc_init_flag[devp->index] = 0; - if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) - && (devp->afbce_mode == 1)) { + if (devp->afbce_mode == 1) { while (i++ < afbc_write_down_timeout) { if (vdin_afbce_read_writedown_flag()) break; @@ -741,8 +751,7 @@ void vdin_stop_dec(struct vdin_dev_s *devp) vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; - if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) - && (devp->afbce_mode == 1)) { + if (devp->afbce_mode == 1) { vdin_afbce_hw_disable(); vdin_afbce_soft_reset(); } @@ -1430,8 +1439,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) offset = devp->addr_offset; - if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) - && (devp->afbce_mode == 1)) { + if (devp->afbce_mode == 1) { if (afbc_init_flag[devp->index] == 0) { afbc_init_flag[devp->index] = 1; /*set mem power on*/ @@ -1452,7 +1460,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) */ spin_lock_irqsave(&devp->isr_lock, flags); - if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) { + if (devp->afbce_mode == 1) { /* no need reset mif under afbc mode */ devp->vdin_reset_flag = 0; } else { @@ -2322,8 +2330,7 @@ static int vdin_open(struct inode *inode, struct file *file) return 0; } - if ((devp->afbce_mode == 1) && - (is_meson_tl1_cpu() || is_meson_tm2_cpu())) + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu())) switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_ON); devp->flags |= VDIN_FLAG_FS_OPENED; @@ -2372,8 +2379,7 @@ static int vdin_release(struct inode *inode, struct file *file) return 0; } - if ((devp->afbce_mode == 1) && - (is_meson_tl1_cpu() || is_meson_tm2_cpu())) + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu())) switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_DOWN); devp->flags &= (~VDIN_FLAG_FS_OPENED); @@ -3317,21 +3323,21 @@ static int vdin_drv_probe(struct platform_device *pdev) ret = of_property_read_u32(pdev->dev.of_node, "afbce_bit_mode", &vdevp->afbce_mode); if (ret) { - vdevp->afbce_mode = 0; - pr_info("no afbce mode found, use normal mode\n"); + vdevp->afbce_flag = 0; } else { - vdevp->afbce_mode = val & 0xf; + vdevp->afbce_flag = val & 0xf; vdevp->afbce_lossy_en = (val>>4)&0xf; if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) && (vdevp->index == 0)) { /* just use afbce at vdin0 */ - pr_info("afbce mode = %d\n", vdevp->afbce_mode); + pr_info("afbce flag = %d\n", vdevp->afbce_flag); + pr_info("afbce loosy en = %d\n", vdevp->afbce_lossy_en); vdevp->afbce_info = devm_kzalloc(vdevp->dev, sizeof(struct vdin_afbce_s), GFP_KERNEL); if (!vdevp->afbce_info) goto fail_kzalloc_vdev; } else { - vdevp->afbce_mode = 0; + vdevp->afbce_flag = 0; pr_info("get afbce from dts, but chip cannot support\n"); } } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 0b0bc076eafe..351930233869 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -329,6 +329,7 @@ struct vdin_dev_s { * 1: use afbce non-mmu mode: head/body addr set by code * 2: use afbce mmu mode: head set by code, body addr assigning by hw */ + unsigned int afbce_flag; unsigned int afbce_mode; unsigned int canvas_config_mode; bool prehsc_en; From df9b1e15a3dd3c43c632c8c1d6a81abb44dcf88e Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 22 Apr 2019 18:30:02 +0800 Subject: [PATCH 0604/1060] vdin: revert ignore v4l2start/stop ioctl when vdin1 used for preview [1/1] PD#SWPL-7324 Problem: tvafe work abnormal when use vdin1 preview Solution: revert the previous commit for v4l2start/stop Verify: x301 This reverts commit 81c1e1449c5e7362dc263bea76e134ba8fd25265. Change-Id: I8cdefececb8b01cb86426684a6c700bc9bf8b615 Signed-off-by: Evoke Zhang --- .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 15e26736d1d5..838aaf8af96e 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -88,8 +88,6 @@ static unsigned int tl1_vdin1_canvas_addr; static unsigned int tl1_vdin1_height; static unsigned int tl1_vdin1_width; spinlock_t tl1_preview_lock; - -static unsigned int tl1_vdin1_capture_flag; /* * canvas_config_mode * 0: canvas_config in driver probe @@ -669,13 +667,18 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); - if (devp->afbce_mode == 1) { - if (is_meson_tl1_cpu()) { + if ((devp->afbce_mode == 1) && + (is_meson_tl1_cpu() || is_meson_tm2_cpu())) { + if ((devp->h_active >= 1920) && (devp->v_active >= 1080)) { tl1_vdin1_preview_flag = 1; tl1_vdin1_data_readied = 0; tl1_vdin1_preview_ready_flag = 0; pr_info("vdin.%d tl1_vdin1_preview state init\n", devp->index); + } else { + tl1_vdin1_preview_flag = 0; + vdin_afbc_force_drop_frame = + vdin_afbc_force_drop_frame_cnt; } vfe_drop_force = NULL; max_ignore_frames[devp->index] = max_ignore_frame_cnt; @@ -805,10 +808,9 @@ int start_tvin_service(int no, struct vdin_parm_s *para) } if (tl1_vdin1_preview_flag == 1) { - tl1_vdin1_capture_flag = 1; - pr_info("[vdin]%s vdin%d already enabled for preview.\n", + pr_err("[vdin]%s vdin%d use for preview, return.\n", __func__, no); - return 0; + return -1; } fmt = devp->parm.info.fmt; if (vdin_dbg_en) { @@ -944,13 +946,6 @@ int stop_tvin_service(int no) struct vdin_dev_s *devp; unsigned int end_time; - if (tl1_vdin1_preview_flag == 1) { - tl1_vdin1_capture_flag = 0; - pr_info("[vdin]%s vdin%d is used for preview.\n", - __func__, no); - return 0; - } - devp = vdin_devp[no]; if ((devp->parm.reserved & PARAM_STATE_HISTGRAM) && (devp->parm.reserved & PARAM_STATE_SCREENCAP) && @@ -1562,8 +1557,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_vf_disp_mode_update(devp->last_wr_vfe, devp->vfp); devp->last_wr_vfe = NULL; - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && - (tl1_vdin1_capture_flag == 0)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -1779,8 +1773,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && - (tl1_vdin1_capture_flag == 0)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -1986,8 +1979,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || (devp->game_mode & VDIN_GAME_MODE_1)) { /* not RDMA, or game mode 1 */ - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && - (tl1_vdin1_capture_flag == 0)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -2046,8 +2038,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } spin_unlock_irqrestore(&tl1_preview_lock, flags1); provider_vf_put(next_wr_vfe, devp->vfp); - if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1) && - (tl1_vdin1_capture_flag == 0)) { + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { //if (vdin_dbg_en) //pr_info("vdin1 preview dont notify receiver.\n"); } else { @@ -3019,10 +3010,6 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_S_VDIN_V4L2START cann't be used at vdin0\n"); break; } - if ((tl1_vdin1_preview_flag) && (devp->index == 1)) { - pr_info("TVIN_IOC_S_VDIN_V4L2START ignore for vdin1 is already enabled\n"); - break; - } if (devp->flags & VDIN_FLAG_ISR_REQ) free_irq(devp->irq, (void *)devp); @@ -3064,10 +3051,6 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_S_VDIN_V4L2STOP cann't be used at vdin0\n"); break; } - if ((tl1_vdin1_preview_flag) && (devp->index == 1)) { - pr_info("TVIN_IOC_S_VDIN_V4L2STOP ignore for vdin1 used for preview\n"); - break; - } devp->parm.reserved &= ~PARAM_STATE_HISTGRAM; devp->flags &= (~VDIN_FLAG_ISR_REQ); devp->flags &= (~VDIN_FLAG_FS_OPENED); From 8985bac67d958275e788cee9e1bf97c06d8233b7 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Thu, 16 May 2019 16:28:18 +0900 Subject: [PATCH 0605/1060] ODROID:Merge BSP 2019.04 (fix build err-vin) Change-Id: I4bf9a1634e613e768dcc48248c6e4ff9f3f3d239 --- drivers/amlogic/media/vin/tvin/tvin_global.h | 14 ++++ .../amlogic/media/vin/tvin/vdin/vdin_afbce.c | 24 +++--- .../amlogic/media/vin/tvin/vdin/vdin_ctl.c | 24 ++++-- .../amlogic/media/vin/tvin/vdin/vdin_debug.c | 12 +++ .../amlogic/media/vin/tvin/vdin/vdin_drv.c | 79 ++++++++++++------- .../amlogic/media/vin/tvin/vdin/vdin_drv.h | 7 +- drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c | 10 ++- .../amlogic/media/frame_provider/tvin/tvin.h | 28 +++++-- 8 files changed, 136 insertions(+), 62 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/tvin_global.h b/drivers/amlogic/media/vin/tvin/tvin_global.h index 14f2cb43853f..78f4b4029f1a 100644 --- a/drivers/amlogic/media/vin/tvin/tvin_global.h +++ b/drivers/amlogic/media/vin/tvin/tvin_global.h @@ -447,6 +447,19 @@ struct tvin_hdr_info_s { unsigned int hdr_check_cnt; }; +enum tvin_cn_type_e { + GRAPHICS, + PHOTO, + CINEMA, + GAME, +}; + +struct tvin_latency_s { + bool allm_mode; + bool it_content; + enum tvin_cn_type_e cn_type; +}; + struct tvin_sig_property_s { enum tvin_trans_fmt trans_fmt; enum tvin_color_fmt_e color_format; @@ -473,6 +486,7 @@ struct tvin_sig_property_s { bool low_latency;/*is low latency dolby mode*/ uint8_t fps; unsigned int skip_vf_num;/*skip pre vframe num*/ + struct tvin_latency_s latency; }; #define TVAFE_VF_POOL_SIZE 6 /* 8 */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index b79291f75e56..14dd11f39557 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -79,8 +79,6 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) unsigned int afbce_mem_used; unsigned int frame_head_size; unsigned int mmu_used; - //unsigned long afbce_head_phy_addr; - //unsigned long afbce_table_phy_addr; unsigned long body_start_paddr; if (devp->rdma_enable) @@ -285,8 +283,7 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) /* set fm_head_paddr start */ frame_head_size = (int)roundup(devp->vfmem_size, 128); /*h_active * v_active / 128 * 4 = frame_head_size*/ - frame_head_size = devp->h_active * devp->v_active / 32; - frame_head_size = PAGE_ALIGN(frame_head_size); + frame_head_size = PAGE_ALIGN(frame_head_size / 32); devp->afbce_info->frame_head_size = frame_head_size; @@ -711,18 +708,19 @@ void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, unsigned int rdma_enable, struct vf_entry *vfe) { unsigned char i; - unsigned int cur_mmu_used; i = vfe->af_num; - cur_mmu_used = devp->afbce_info->fm_table_paddr[i] / 4; + vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; -#ifdef CONFIG_AML_RDMA - if (rdma_enable) - rdma_write_reg_bits(devp->rdma_handle, - AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); - rdma_write_reg(devp->rdma_handle, - AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - else +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + if (rdma_enable) { + rdma_write_reg(devp->rdma_handle, AFBCE_HEAD_BADDR, + devp->afbce_info->fm_head_paddr[i]); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_MMU_RMIF_CTRL4, + devp->afbce_info->fm_table_paddr[i], 0, 32); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 0, 1); + } else #endif { pr_info("afbce must use RDMA.\n"); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index e2f649ca63a1..89820b29f765 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -541,6 +541,8 @@ void vdin_get_format_convert(struct vdin_dev_s *devp) format_convert = VDIN_FORMAT_CONVERT_YUV_NV21; else if (devp->prop.dest_cfmt == TVIN_NV12) format_convert = VDIN_FORMAT_CONVERT_YUV_NV12; + else if (devp->prop.dest_cfmt == TVIN_YUV444) + format_convert = VDIN_FORMAT_CONVERT_YUV_YUV444; else format_convert = VDIN_FORMAT_CONVERT_YUV_YUV422; break; @@ -1552,9 +1554,10 @@ static void vdin_set_color_matrix0_g12a(unsigned int offset, VDIN_MATRIX_COEF_INDEX_BIT, VDIN_MATRIX_COEF_INDEX_WID); wr(offset, - VDIN_MATRIX_PRE_OFFSET0_1, matrix_tbl->pre_offset0_1); + VDIN_HDR2_MATRIXI_PRE_OFFSET0_1, + matrix_tbl->pre_offset0_1); wr(offset, - VDIN_MATRIX_PRE_OFFSET2, matrix_tbl->pre_offset2); + VDIN_HDR2_MATRIXI_PRE_OFFSET2, matrix_tbl->pre_offset2); wr(offset, VDIN_HDR2_MATRIXI_COEF00_01, matrix_tbl->coef00_01); wr(offset, VDIN_HDR2_MATRIXI_COEF02_10, matrix_tbl->coef02_10); wr(offset, VDIN_HDR2_MATRIXI_COEF11_12, matrix_tbl->coef11_12); @@ -2043,7 +2046,7 @@ void vdin_set_wr_ctrl_vsync(struct vdin_dev_s *devp, hconv_mode = 2; swap_cbcr = 0; } -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) { rdma_write_reg_bits(devp->rdma_handle, VDIN_WR_CTRL+devp->addr_offset, @@ -2137,9 +2140,10 @@ unsigned int vdin_get_total_v(unsigned int offset) void vdin_set_canvas_id(struct vdin_dev_s *devp, unsigned int rdma_enable, unsigned int canvas_id) { -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { rdma_write_reg_bits(devp->rdma_handle, VDIN_COM_CTRL0+devp->addr_offset, 1, VDIN_FORCEGOLINE_EN_BIT, 1); @@ -2163,7 +2167,7 @@ unsigned int vdin_get_canvas_id(unsigned int offset) void vdin_set_chma_canvas_id(struct vdin_dev_s *devp, unsigned int rdma_enable, unsigned int canvas_id) { -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) rdma_write_reg_bits(devp->rdma_handle, VDIN_WR_CTRL2+devp->addr_offset, @@ -4195,6 +4199,14 @@ u32 vdin_get_curr_field_type(struct vdin_dev_s *devp) type &= (~VIDTYPE_VIU_SINGLE_PLANE); } + + if (devp->afbce_mode == 1) { + type |= VIDTYPE_COMPRESS; + type |= VIDTYPE_SCATTER; + if (devp->afbce_lossy_en == 1) + type |= VIDTYPE_COMPRESS_LOSS; + } + return type; } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 43396339946a..cb3065f309b2 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -1583,6 +1583,9 @@ start_chk: } else if (!strcmp(parm[1], "video")) { param.port = TVIN_PORT_VIU1_VIDEO; pr_info(" port is TVIN_PORT_VIU_VIDEO\n"); + } else if (!strcmp(parm[1], "viu_wb0_vpp")) { + param.port = TVIN_PORT_VIU1_WB0_VPP; + pr_info(" port is TVIN_PORT_VIU1_WB0_VPP\n"); } else if (!strcmp(parm[1], "viu_wb0_vd1")) { param.port = TVIN_PORT_VIU1_WB0_VD1; pr_info(" port is TVIN_PORT_VIU_WB0_VD1\n"); @@ -1598,6 +1601,9 @@ start_chk: } else if (!strcmp(parm[1], "viu_wb0_post_blend")) { param.port = TVIN_PORT_VIU1_WB0_POST_BLEND; pr_info(" port is TVIN_PORT_VIU_WB0_POST_BLEND\n"); + } else if (!strcmp(parm[1], "viu_wb1_vpp")) { + param.port = TVIN_PORT_VIU1_WB1_VPP; + pr_info(" port is TVIN_PORT_VIU1_WB1_VPP\n"); } else if (!strcmp(parm[1], "viu_wb1_vd1")) { param.port = TVIN_PORT_VIU1_WB1_VD1; pr_info(" port is TVIN_PORT_VIU_WB1_VD1\n"); @@ -1619,6 +1625,9 @@ start_chk: } else if (!strcmp(parm[1], "video2")) { param.port = TVIN_PORT_VIU2_VIDEO; pr_info(" port is TVIN_PORT_VIU_VIDEO\n"); + } else if (!strcmp(parm[1], "viu2_wb0_vpp")) { + param.port = TVIN_PORT_VIU2_WB0_VPP; + pr_info(" port is TVIN_PORT_VIU2_WB0_VPP\n"); } else if (!strcmp(parm[1], "viu2_wb0_vd1")) { param.port = TVIN_PORT_VIU2_WB0_VD1; pr_info(" port is TVIN_PORT_VIU_WB0_VD1\n"); @@ -1634,6 +1643,9 @@ start_chk: } else if (!strcmp(parm[1], "viu2_wb0_post_blend")) { param.port = TVIN_PORT_VIU2_WB0_POST_BLEND; pr_info(" port is TVIN_PORT_VIU_WB0_POST_BLEND\n"); + } else if (!strcmp(parm[1], "viu2_wb1_vpp")) { + param.port = TVIN_PORT_VIU2_WB1_VPP; + pr_info(" port is TVIN_PORT_VIU2_WB1_VPP\n"); } else if (!strcmp(parm[1], "viu2_wb1_vd1")) { param.port = TVIN_PORT_VIU2_WB1_VD1; pr_info(" port is TVIN_PORT_VIU_WB1_VD1\n"); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 838aaf8af96e..d8bf617eeb5a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -133,6 +133,10 @@ MODULE_PARM_DESC(dv_work_delby, "dv_work_delby"); module_param(game_mode_switch_frames, int, 0664); MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch frames"); + +module_param(game_mode_phlock_switch_frames, int, 0664); +MODULE_PARM_DESC(game_mode_phlock_switch_frames, + "game mode switch frames for phase_lock"); #endif bool vdin_dbg_en; @@ -318,6 +322,9 @@ static void vdin_game_mode_check(struct vdin_dev_s *devp) VDIN_GAME_MODE_SWITCH_EN); else devp->game_mode = 0; + + pr_info("%s: game_mode flag=%d, game_mode=%d\n", + __func__, game_mode, devp->game_mode); } /* *based on the bellow parameters: @@ -368,17 +375,24 @@ static void vdin_vf_init(struct vdin_dev_s *devp) /*if output fmt is nv21 or nv12 , * use the two continuous canvas for one field */ - if ((devp->prop.dest_cfmt == TVIN_NV12) || - (devp->prop.dest_cfmt == TVIN_NV21)) { - chromaid = + if (devp->afbce_mode == 0) { + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) { + chromaid = (vdin_canvas_ids[index][(vf->index<<1)+1])<<8; - addr = - vdin_canvas_ids[index][vf->index<<1] | - chromaid; - } else - addr = vdin_canvas_ids[index][vf->index]; + addr = + vdin_canvas_ids[index][vf->index<<1] | + chromaid; + } else + addr = vdin_canvas_ids[index][vf->index]; - vf->canvas0Addr = vf->canvas1Addr = addr; + vf->canvas0Addr = vf->canvas1Addr = addr; + } else if (devp->afbce_mode == 1) { + vf->compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + vf->compBodyAddr = devp->afbce_info->fm_body_paddr[i]; + vf->compWidth = devp->h_active; + vf->compHeight = devp->v_active; + } /* set source type & mode */ vdin_set_source_type(devp, vf); @@ -414,7 +428,7 @@ static void vdin_vf_init(struct vdin_dev_s *devp) } } -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA static void vdin_rdma_irq(void *arg) { struct vdin_dev_s *devp = arg; @@ -623,7 +637,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->frontend->dec_ops->start(devp->frontend, devp->parm.info.fmt); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA /*it is better put after all reg init*/ if (devp->rdma_enable && devp->rdma_handle > 0) devp->flags |= VDIN_FLAG_RDMA_ENABLE; @@ -661,6 +675,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->irq_cnt = 0; devp->rdma_irq_cnt = 0; devp->frame_cnt = 0; + phase_lock_flag = 0; if (time_en) pr_info("vdin.%d start time: %ums, run time:%ums.\n", @@ -772,7 +787,7 @@ void vdin_stop_dec(struct vdin_dev_s *devp) switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0, VPU_MEM_POWER_DOWN); memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s)); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA rdma_clear(devp->rdma_handle); #endif devp->flags &= (~VDIN_FLAG_RDMA_ENABLE); @@ -1957,19 +1972,20 @@ irqreturn_t vdin_isr(int irq, void *dev_id) /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - if (devp->afbce_mode == 0) + if (devp->afbce_mode == 0) { vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr&0xff)); - else if (devp->afbce_mode == 1) + + /* prepare for chroma canvas*/ + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) + vdin_set_chma_canvas_id(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), + (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } else if (devp->afbce_mode == 1) { vdin_afbce_set_next_frame(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); - - /* prepare for chroma canvas*/ - if ((devp->prop.dest_cfmt == TVIN_NV12) || - (devp->prop.dest_cfmt == TVIN_NV21)) - vdin_set_chma_canvas_id(devp, - (devp->flags&VDIN_FLAG_RDMA_ENABLE), - (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } devp->curr_wr_vfe = next_wr_vfe; /* debug for video latency */ @@ -2075,7 +2091,7 @@ irq_handled: vdin_vf_disp_mode_skip(devp->vfp); spin_unlock_irqrestore(&devp->isr_lock, flags); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (devp->flags & VDIN_FLAG_RDMA_ENABLE) rdma_config(devp->rdma_handle, (devp->rdma_enable&1) ? @@ -2233,18 +2249,19 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - if (devp->afbce_mode == 0) + if (devp->afbce_mode == 0) { vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr&0xff)); - else if (devp->afbce_mode == 1) - vdin_afbce_set_next_frame(devp, - (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) vdin_set_chma_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } else if (devp->afbce_mode == 1) { + vdin_afbce_set_next_frame(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); + } devp->curr_wr_vfe = next_wr_vfe; vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -2252,7 +2269,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) irq_handled: spin_unlock_irqrestore(&devp->isr_lock, flags); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (devp->flags & VDIN_FLAG_RDMA_ENABLE) rdma_config(devp->rdma_handle, (devp->rdma_enable&1) ? @@ -2594,7 +2611,8 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) devp_vdin1->debug.scaler4w = 1280; devp_vdin1->debug.scaler4h = 720; - devp_vdin1->debug.dest_cfmt = TVIN_YUV422; + /* vdin1 follow vdin0 afbc dest_cfmt */ + devp_vdin1->debug.dest_cfmt = devp->prop.dest_cfmt; devp_vdin1->flags |= VDIN_FLAG_MANUAL_CONVERSION; vdin_start_dec(devp_vdin1); @@ -3174,6 +3192,7 @@ static int vdin_drv_probe(struct platform_device *pdev) int ret = 0; struct vdin_dev_s *vdevp; struct resource *res; + unsigned int val; unsigned int urgent_en = 0; unsigned int bit_mode = VDIN_WR_COLOR_DEPTH_8BIT; /* const void *name; */ @@ -3304,7 +3323,7 @@ static int vdin_drv_probe(struct platform_device *pdev) spin_lock_init(&tl1_preview_lock); /*set afbce mode*/ ret = of_property_read_u32(pdev->dev.of_node, - "afbce_bit_mode", &vdevp->afbce_mode); + "afbce_bit_mode", &val); if (ret) { vdevp->afbce_flag = 0; } else { @@ -3486,7 +3505,7 @@ static int vdin_drv_remove(struct platform_device *pdev) vdevp = platform_get_drvdata(pdev); ret = cancel_delayed_work(&vdevp->vlock_dwork); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA rdma_unregister(vdevp->rdma_handle); #endif mutex_destroy(&vdevp->fe_lock); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 351930233869..927c8c56cf8a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -36,8 +36,8 @@ #include #include #include -#ifdef CONFIG_AML_RDMA -#include +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA +#include #endif /* Local Headers */ @@ -331,6 +331,7 @@ struct vdin_dev_s { */ unsigned int afbce_flag; unsigned int afbce_mode; + unsigned int afbce_lossy_en; unsigned int canvas_config_mode; bool prehsc_en; bool vshrk_en; @@ -406,5 +407,7 @@ extern bool is_dolby_vision_enable(void); extern void vdin_debugfs_init(struct vdin_dev_s *vdevp); extern void vdin_debugfs_exit(struct vdin_dev_s *vdevp); +extern bool vlock_get_phlock_flag(void); + #endif /* __TVIN_VDIN_DRV_H */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c index afd3446df7f0..6c01f41d583f 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c @@ -1018,7 +1018,10 @@ void vdin_vf_disp_mode_update(struct vf_entry *vfe, struct vf_pool *p) p->disp_index[0] = 0; vfe->vf.index_disp = p->disp_index[0]; - p->disp_mode[p->disp_index[p->skip_vf_num]] = VFRAME_DISP_MODE_OK; + if (p->disp_mode[p->disp_index[p->skip_vf_num]] != + VFRAME_DISP_MODE_SKIP) + p->disp_mode[p->disp_index[p->skip_vf_num]] = + VFRAME_DISP_MODE_OK; for (i = p->skip_vf_num - 1; i < VFRAME_DISP_MAX_NUM; i--) p->disp_mode[p->disp_index[i]] = VFRAME_DISP_MODE_UNKNOWN; } @@ -1030,8 +1033,7 @@ void vdin_vf_disp_mode_update(struct vf_entry *vfe, struct vf_pool *p) void vdin_vf_disp_mode_skip(struct vf_pool *p) { unsigned int i; - - for (i = p->skip_vf_num - 1; i < VFRAME_DISP_MAX_NUM; i--) - p->disp_mode[i] = VFRAME_DISP_MODE_SKIP; + for (i = 0; i <= p->skip_vf_num; i++) + p->disp_mode[p->disp_index[i]] = VFRAME_DISP_MODE_SKIP; } diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index bf2dbba442a8..fe41e165f1e6 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -64,11 +64,13 @@ enum tvin_port_e { TVIN_PORT_VIU1_WB0_VD2, TVIN_PORT_VIU1_WB0_OSD1, TVIN_PORT_VIU1_WB0_OSD2, + TVIN_PORT_VIU1_WB0_VPP, TVIN_PORT_VIU1_WB0_POST_BLEND, TVIN_PORT_VIU1_WB1_VD1, TVIN_PORT_VIU1_WB1_VD2, TVIN_PORT_VIU1_WB1_OSD1, TVIN_PORT_VIU1_WB1_OSD2, + TVIN_PORT_VIU1_WB1_VPP, TVIN_PORT_VIU1_WB1_POST_BLEND, TVIN_PORT_VIU2 = 0x0000C000, TVIN_PORT_VIU2_VIDEO, @@ -76,11 +78,13 @@ enum tvin_port_e { TVIN_PORT_VIU2_WB0_VD2, TVIN_PORT_VIU2_WB0_OSD1, TVIN_PORT_VIU2_WB0_OSD2, + TVIN_PORT_VIU2_WB0_VPP, TVIN_PORT_VIU2_WB0_POST_BLEND, TVIN_PORT_VIU2_WB1_VD1, TVIN_PORT_VIU2_WB1_VD2, TVIN_PORT_VIU2_WB1_OSD1, TVIN_PORT_VIU2_WB1_OSD2, + TVIN_PORT_VIU2_WB1_VPP, TVIN_PORT_VIU2_WB1_POST_BLEND, TVIN_PORT_MIPI = 0x00010000, TVIN_PORT_ISP = 0x00020000, @@ -461,18 +465,12 @@ struct tvafe_pin_mux_s { #define TVIN_IOC_G_VDIN_HIST _IOW(_TM_T, 0x24, struct vdin_hist_s) #define TVIN_IOC_S_VDIN_V4L2START _IOW(_TM_T, 0x25, struct vdin_v4l2_param_s) #define TVIN_IOC_S_VDIN_V4L2STOP _IO(_TM_T, 0x26) +#define TVIN_IOC_S_AFE_SONWCFG _IOW(_TM_T, 0x27, unsigned int) /* *function defined applied for other driver */ -/* - *adc pll ctl, atv demod & tvafe use the same adc module - * module index: atv demod:0x01; tvafe:0x2 - */ - -/* extern void adc_set_pll_cntl(bool on, unsigned int module_sel);*/ - struct dfe_adcpll_para { unsigned int adcpllctl; unsigned int demodctl; @@ -501,8 +499,24 @@ struct rx_audio_stat_s { int aud_type; /* indicate if audio fifo start threshold is crossed */ bool afifo_thres_pass; + /* + * 0 [ch1 ch2] + * 1,2,3 [ch1 ch2 ch3 ch4] + * 4,8 [ch1 ch2 ch5 ch6] + * 5,6,7,9,10,11 [ch1 ch2 ch3 ch4 ch5 ch6] + * 12,16,24,28 [ch1 ch2 ch5 ch6 ch7 ch8] + * 20 [ch1 ch2 ch7 ch8] + * 21,22,23[ch1 ch2 ch3 ch4 ch7 ch8] + * all others [all of 8ch] + */ + int aud_alloc; }; +extern void adc_pll_down(void); +/*ADC_EN_ATV_DEMOD 0x1*/ +/*ADC_EN_TVAFE 0x2*/ +/*ADC_EN_DTV_DEMOD 0x4*/ +/*ADC_EN_DTV_DEMODPLL 0x8*/ extern int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara); extern void tvafe_set_ddemod_default(void);/* add for dtv demod*/ extern void rx_get_audio_status(struct rx_audio_stat_s *aud_sts); From f5b15e8f365aff6c81c022a48e0a7c0fb2bf8f7a Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Thu, 16 May 2019 17:12:26 +0900 Subject: [PATCH 0606/1060] ODROID:Merge BSP 2019.04 (fix build err-hdmitx) Change-Id: I119ba16c916f751483670dc879558f527f9f271e --- drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 3 +-- drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 49307d9c4220..7d5dd1fbbf7a 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -554,11 +554,10 @@ static int set_disp_mode_auto(void) hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, DVI_MODE); pr_info(SYS "change to DVI mode\n"); - } else if (hdev->RXCap.IEEEOUI == 0) { + } else if (hdev->RXCap.ieeeoui == 0) { #else if (hdev->RXCap.ieeeoui == 0) { #endif - if (hdev->RXCap.ieeeoui == 0) { /* DVI case judgement. In uboot, directly output HDMI * mode */ diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c index 9bd4e86af390..3f0e4df5d9e5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c @@ -194,6 +194,7 @@ static void set_hpll_hclk_dongle_5940m(void) void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk) { + unsigned int m, m1, m2; struct hdmitx_dev *hdev = get_hdmitx_device(); switch (clk) { From 41cd4eff81215e331f569ccd5101eefa716e073f Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 28 Nov 2018 09:36:58 +0800 Subject: [PATCH 0607/1060] lcd: update pll setting for tl1 tcon_pll performance [1/1] PD#172587 Problem: tcon pll performance is not good when frac enabled with old setting Solution: update tcon pll setting Verify: x301 Change-Id: Ib5deb5c643afa243876c0e4703f835e503fffc2e Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/lcd/lcd_clk_config.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 295059c010ec..33a3e28d9385 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -517,6 +517,8 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_LVDS: + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000704ad); + mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200704ad); mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300704ad); @@ -525,7 +527,8 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); mdelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); + //lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); mdelay(10); @@ -541,6 +544,8 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) mdelay(10); break; case LCD_VBYONE: + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000f04f7); + mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200f04f7); mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300f04f7); @@ -563,6 +568,8 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) mdelay(10); break; case LCD_P2P: + lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000f04e1); + mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200604e1); mdelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300604e1); From 2e5edbe58c31243b401b5446ae57ad7516f14a70 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 28 Nov 2018 18:23:22 +0800 Subject: [PATCH 0608/1060] lcd: update phy disable setting for tl1 [1/1] PD#SWPL-2399 Problem: Power consumption for tl1 lcd suspend need improved Solution: shutdown tl1 phy when lcd disable Verify: skt x309 Change-Id: Ibce3539c5193b1f9347ff71882bab2604666a76e Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c --- .../amlogic/media/vout/lcd/lcd_clk_config.c | 3 + drivers/amlogic/media/vout/lcd/lcd_reg.h | 2 + .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 85 ++++++++++++++++--- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 33a3e28d9385..5f25afc056a6 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -2448,6 +2448,9 @@ void lcd_clk_disable(void) if (table[i].flag == LCD_CLK_CTRL_EN) { lcd_hiu_setb(table[i].reg, 0, table[i].bit, table[i].len); + } else if (table[i].flag == LCD_CLK_CTRL_RST) { + lcd_hiu_setb(table[i].reg, 1, + table[i].bit, table[i].len); } i++; } diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index a3e2d3bf4e53..ab3ee4f03f63 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -854,7 +854,9 @@ #define VBO_TMCHK_VDE_STATE_H 0x14f7 #define VBO_INTR_STATE 0x14f8 #define VBO_INFILTER_CTRL 0x14f9 +#define VBO_INFILTER_TICK_PERIOD_L 0x14f9 #define VBO_INSGN_CTRL 0x14fa +#define VBO_INFILTER_TICK_PERIOD_H 0x1477 /* ******************************** * Video Interface: VENC_VCBUS_BASE = 0x1b diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index d06ce74856a9..425ddcd5d270 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -134,9 +134,30 @@ static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) break; } } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + break; + } } } @@ -208,9 +229,30 @@ static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) break; } } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + break; + } } } @@ -276,9 +318,21 @@ static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); } } @@ -837,6 +891,7 @@ static void lcd_vbyone_cdr_training_hold(struct vbyone_config_s *vx1_conf, static void lcd_vbyone_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int lane_count, byte_mode, region_num, hsize, vsize, color_fmt; int vin_color, vin_bpp; @@ -918,7 +973,17 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ - lcd_vbyone_hw_filter(0); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + break; + default: + lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + break; + } lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); From 306d4ca98a58975b68287fc540cf9a3fb43faab0 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 7 Dec 2018 11:27:24 +0800 Subject: [PATCH 0609/1060] lcd: update tcon_pll lock setting for tl1 [1/1] PD#SWPL-2983 Problem: tcon_pll lock is affected by VDDEE voltage Solution: change tcon_pll lock setting to avoid VDDEE effection Verify: x301 Change-Id: I2f9d4638274fe3acdf5d8954b3670e7c108782e1 Signed-off-by: Evoke Zhang --- .../amlogic/media/vout/lcd/lcd_clk_config.c | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 5f25afc056a6..f4a6dfcfca73 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -518,88 +518,92 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_LVDS: lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000704ad); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200704ad); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300704ad); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10508000); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - mdelay(10); + udelay(10); //lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340704ad); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x142e04ad); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); - mdelay(10); + udelay(10); break; case LCD_VBYONE: lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000f04f7); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200f04f7); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300f04f7); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10110000); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340f04f7); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x140f04f7); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - mdelay(10); + udelay(10); break; case LCD_P2P: lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000f04e1); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200604e1); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300604e1); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10208000); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340604e1); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x14af04e1); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - mdelay(10); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); - mdelay(10); + udelay(10); break; default: break; } #endif ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1); - if (ret) + if (ret) { LCDERR("hpll lock failed\n"); + } else { + udelay(100); + lcd_hiu_setb(HHI_TCON_PLL_CNTL2, 1, 5, 1); + } if (cConf->ss_level > 0) lcd_set_pll_ss_tl1(cConf->ss_level); From 397e21325d20e736958e2d4ddb693f951b666dd9 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 10 Dec 2018 14:08:48 +0800 Subject: [PATCH 0610/1060] vpp: update ofifo vs_pol config for tl1 [1/1] PD#SWPL-3049 Problem: vpp ofifo positive vs_pol can't fit all the display situation Solution: change vpp ofifo vs_pol to negative Verify: x301 Change-Id: I539c3514c0f3638a9d90c9c4a71a6c9863dac79a Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c --- drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c | 1 - drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 57db7a9100f1..c3442ec380db 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -376,7 +376,6 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: /*[15:14]: 2'b10 or 2'b01*/ lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 425ddcd5d270..ae082689e9df 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -433,7 +433,6 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: /*[15:14]: 2'b10 or 2'b01*/ lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); From 6f911494ca0d89029d057e1910132c2315787f86 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 23 Nov 2018 13:10:06 +0800 Subject: [PATCH 0611/1060] lcd: add od support for tl1 tcon [1/1] PD#SWPL-2759 Problem: need over-driver function for tl1 tcon Solution: add tcon cma memory and od setting support Verify: x301 Change-Id: I926d221fef3317be8b3879a35298035ac9babcce Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tcon.c drivers/amlogic/media/vout/lcd/lcd_vout.c --- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 2 + arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 8 + drivers/amlogic/media/vout/lcd/lcd_common.c | 4 +- drivers/amlogic/media/vout/lcd/lcd_tcon.c | 173 +++++++++--------- drivers/amlogic/media/vout/lcd/lcd_tcon.h | 16 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 2 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 16 +- drivers/amlogic/media/vout/lcd/lcd_vout.c | 54 +++++- 8 files changed, 173 insertions(+), 102 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index c2b4d6e69336..444ee3768d6b 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -44,6 +44,8 @@ pinctrl-2 = <&lcd_tcon_pins>; pinctrl-3 = <&lcd_tcon_off_pins>; pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + tcon_mem_addr = <0x71000000>; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 07096d100802..5951680f5336 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -103,6 +103,14 @@ alloc-ranges = <0x7f800000 0x800000>; }; + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x71000000 0xc00000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index 471cd968fa25..48d605b2c432 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -390,11 +390,11 @@ void lcd_tcon_pinmux_set(int status) pconf->pin = devm_pinctrl_get_select(lcd_drv->dev, lcd_tcon_pinmux_str[index]); if (IS_ERR(pconf->pin)) { - LCDERR("set vbyone pinmux %s error\n", + LCDERR("set tcon pinmux %s error\n", lcd_tcon_pinmux_str[index]); } else { if (lcd_debug_print_flag) { - LCDPR("set vbyone pinmux %s: %p\n", + LCDPR("set tcon pinmux %s: %p\n", lcd_tcon_pinmux_str[index], pconf->pin); } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index b4fd006ff7b9..ed6e1f7ca016 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -36,13 +36,19 @@ #include "lcd_common.h" #include "lcd_reg.h" #include "lcd_tcon.h" -#include "tcon_ceds.h" +/*#include "tcon_ceds.h"*/ #define TCON_INTR_MASKN_VAL 0x0 /* default mask all */ -static struct reserved_mem tcon_fb_rmem = {.base = 0, .size = 0}; +static struct tcon_rmem_s tcon_rmem = { + .flag = 0, + .mem_vaddr = NULL, + .mem_paddr = 0, + .mem_size = 0, +}; static struct lcd_tcon_data_s *lcd_tcon_data; +static struct delayed_work lcd_tcon_delayed_work; static int lcd_tcon_valid_check(void) { @@ -112,7 +118,7 @@ static void lcd_tcon_od_check(unsigned char *table) if (((table[reg] >> bit) & 1) == 0) return; - if (lcd_tcon_data->axi_offset_addr == 0) { + if (tcon_rmem.flag == 0) { table[reg] &= ~(1 << bit); LCDPR("%s: invalid fb, disable od function\n", __func__); } @@ -163,22 +169,22 @@ static int lcd_tcon_top_set_tl1(void) TCON_AXI_OFST0, TCON_AXI_OFST1, TCON_AXI_OFST2 }; unsigned int addr[3] = {0, 0, 0}; - unsigned int size[3] = {0, 0, 0}; + unsigned int size[3] = {4162560, 4162560, 1960440}; int i; LCDPR("lcd tcon top set\n"); - if (lcd_tcon_data->axi_offset_addr == 0) { - LCDERR("%s: invalid axi_offset_addr\n", __func__); - } else { - addr[0] = lcd_tcon_data->axi_offset_addr; + if (tcon_rmem.flag) { + addr[0] = tcon_rmem.mem_paddr; addr[1] = addr[0] + size[0]; addr[2] = addr[1] + size[1]; for (i = 0; i < 3; i++) { lcd_tcon_write(axi_reg[i], addr[i]); - LCDPR("set tcon axi_offset_addr[%d]: 0x%08x\n", + LCDPR("set tcon axi_mem_paddr[%d]: 0x%08x\n", i, addr[i]); } + } else { + LCDERR("%s: invalid axi_mem\n", __func__); } lcd_tcon_write(TCON_CLK_CTRL, 0x001f); @@ -246,13 +252,15 @@ static void lcd_tcon_intr_init(struct aml_lcd_drv_s *lcd_drv) return; } tcon_irq = lcd_drv->res_tcon_irq->start; - LCDPR("tcon_irq: %d\n", tcon_irq); + if (lcd_debug_print_flag) + LCDPR("tcon_irq: %d\n", tcon_irq); if (request_irq(tcon_irq, lcd_tcon_isr, IRQF_SHARED, "lcd_tcon", (void *)"lcd_tcon")) LCDERR("can't request lcd_tcon irq\n"); else { - LCDPR("request lcd_tcon successful\n"); + if (lcd_debug_print_flag) + LCDPR("request lcd_tcon irq successful\n"); } lcd_tcon_write(TCON_INTR_MASKN, TCON_INTR_MASKN_VAL); @@ -262,18 +270,7 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) { int key_len, reg_len, ret; - /* init reserved memory */ - ret = of_reserved_mem_device_init(lcd_drv->dev); - if ((ret != 0) && ((void *)tcon_fb_rmem.base == NULL)) { - LCDERR("failed to init tcon axi reserved memory\n"); - } else { - lcd_tcon_data->axi_offset_addr = - virt_to_phys((void *)tcon_fb_rmem.base); - } - LCDPR("tcon axi_offset_addr = 0x%08x\n", - lcd_tcon_data->axi_offset_addr); - -#if 0 +#if 1 /* get reg table from unifykey */ reg_len = lcd_tcon_data->reg_table_len; if (lcd_tcon_data->reg_table == NULL) { @@ -301,6 +298,7 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) __func__); return -1; } + LCDPR("tcon: load unifykey len: %d\n", key_len); #else reg_len = lcd_tcon_data->reg_table_len; lcd_tcon_data->reg_table = uhd_tcon_setting_ceds_h10; @@ -311,8 +309,8 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) __func__); return -1; } + LCDPR("tcon: load default table len: %d\n", key_len); #endif - LCDPR("tcon: load key len: %d\n", key_len); lcd_tcon_intr_init(lcd_drv); @@ -329,7 +327,7 @@ static void lcd_tcon_config_delayed(struct work_struct *work) while (key_init_flag == 0) { if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) break; - msleep(LCD_UNIFYKEY_RETRY_INTERVAL); + msleep(20); key_init_flag = key_unify_get_init_flag(); } LCDPR("tcon: key_init_flag=%d, i=%d\n", key_init_flag, i); @@ -429,10 +427,12 @@ int lcd_tcon_info_print(char *buf, int offset) "tcon info:\n" "core_reg_width: %d\n" "reg_table_len: %d\n" - "axi_offset_addr: 0x%08x\n\n", + "axi_mem paddr: 0x%lx\n" + "axi_mem size: 0x%x\n\n", lcd_tcon_data->core_reg_width, lcd_tcon_data->reg_table_len, - lcd_tcon_data->axi_offset_addr); + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); return len; } @@ -498,8 +498,8 @@ int lcd_tcon_od_set(int flag) } if (flag) { - if (lcd_tcon_data->axi_offset_addr == 0) { - LCDERR("%s: invalid fb, disable od function\n", + if (tcon_rmem.flag == 0) { + LCDERR("%s: invalid memory, disable od function\n", __func__); return -1; } @@ -534,11 +534,11 @@ int lcd_tcon_od_get(void) ret = lcd_tcon_valid_check(); if (ret) - return -1; + return 0; if (lcd_tcon_data->reg_core_od == REG_LCD_TCON_MAX) { LCDERR("%s: invalid od reg\n", __func__); - return -1; + return 0; } reg = lcd_tcon_data->reg_core_od; @@ -627,14 +627,14 @@ static struct lcd_tcon_data_s tcon_data_tl1 = { .reg_top_ctrl = TCON_TOP_CTRL, .bit_en = BIT_TOP_EN_TL1, - .reg_core_od = REG_LCD_TCON_MAX, + .reg_core_od = REG_CORE_OD_TL1, .bit_od_en = BIT_OD_EN_TL1, - .reg_core_ctrl_timing_base = REG_CORE_CTRL_TIMING_BASE_TL1, + .reg_core_ctrl_timing_base = REG_LCD_TCON_MAX, .ctrl_timing_offset = CTRL_TIMING_OFFSET_TL1, .ctrl_timing_cnt = CTRL_TIMING_CNT_TL1, - .axi_offset_addr = 0, + .axi_mem_size = 0xc00000, .reg_table = NULL, .tcon_enable = lcd_tcon_enable_tl1, @@ -642,17 +642,16 @@ static struct lcd_tcon_data_s tcon_data_tl1 = { int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) { - struct cma *cma; - unsigned int mem_size; int key_init_flag = 0; int ret = 0; + lcd_tcon_data = NULL; switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: + lcd_tcon_data = &tcon_data_tl1; lcd_tcon_data->tcon_valid = 1; break; default: @@ -660,7 +659,6 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) } break; default: - lcd_tcon_data = NULL; break; } if (lcd_tcon_data == NULL) @@ -671,59 +669,64 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) if (ret) { LCDERR("tcon: init reserved memory failed\n"); } else { - if ((void *)tcon_rmem.mem_paddr == NULL) { #ifdef CONFIG_CMA - cma = dev_get_cma_area(lcd_drv->dev); - if (cma) { - tcon_rmem.mem_paddr = cma_get_base(cma); - LCDPR("tcon axi_mem base:0x%lx, size:0x%lx\n", - (unsigned long)tcon_rmem.mem_paddr, - cma_get_size(cma)); - - mem_size = lcd_tcon_data->axi_mem_size; - tcon_rmem.mem_vaddr = dma_alloc_from_contiguous( - lcd_drv->dev, - (mem_size >> PAGE_SHIFT), - 0); - if (tcon_rmem.mem_vaddr == NULL) { - LCDERR("tcon axi_mem alloc failed\n"); - } else { - LCDPR("tcon axi_mem dma_alloc=0x%x\n", - mem_size); - tcon_rmem.mem_size = mem_size; - tcon_rmem.flag = 2; /* cma memory */ - } - } else { - LCDERR("tcon: NO CMA\n"); - } -#else + tcon_rmem.mem_vaddr = dma_alloc_coherent(lcd_drv->dev, + lcd_tcon_data->axi_mem_size, + &tcon_rmem.mem_paddr, + GFP_KERNEL); + if (tcon_rmem.mem_vaddr == NULL) { LCDERR("tcon axi_mem alloc failed\n"); -#endif + tcon_rmem.mem_paddr = 0; } else { - tcon_rmem.flag = 1; /* reserved memory */ - mem_size = tcon_rmem.mem_size; - LCDPR("tcon axi_mem base:0x%lx, size:0x%x\n", - (unsigned long)tcon_rmem.mem_paddr, mem_size); + tcon_rmem.mem_size = lcd_tcon_data->axi_mem_size; + tcon_rmem.flag = 1; + LCDPR("tcon: axi_mem base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); } +#else + if ((void *)tcon_rmem.mem_paddr == NULL) { + LCDERR("tcon axi_mem alloc failed\n"); + } else { + tcon_rmem.flag = 1; + LCDPR("tcon: axi_mem base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); + } +#endif } INIT_DELAYED_WORK(&lcd_tcon_delayed_work, lcd_tcon_config_delayed); - ret = lcd_tcon_config(lcd_drv); + key_init_flag = key_unify_get_init_flag(); + if (key_init_flag) { + ret = lcd_tcon_config(lcd_drv); + } else { + if (lcd_drv->workqueue) { + queue_delayed_work(lcd_drv->workqueue, + &lcd_tcon_delayed_work, + msecs_to_jiffies(2000)); + } else { + schedule_delayed_work(&lcd_tcon_delayed_work, + msecs_to_jiffies(2000)); + } + } return ret; } int lcd_tcon_remove(struct aml_lcd_drv_s *lcd_drv) { - if (tcon_rmem.flag == 2) { + if (tcon_rmem.flag) { LCDPR("tcon free memory: base:0x%lx, size:0x%x\n", (unsigned long)tcon_rmem.mem_paddr, tcon_rmem.mem_size); #ifdef CONFIG_CMA - dma_release_from_contiguous(lcd_drv->dev, + dma_free_coherent(lcd_drv->dev, tcon_rmem.mem_size, tcon_rmem.mem_vaddr, - tcon_rmem.mem_size >> PAGE_SHIFT); + (dma_addr_t)&tcon_rmem.mem_paddr); +#else + /* to do */ #endif } @@ -741,26 +744,18 @@ static int __init tcon_fb_device_init(struct reserved_mem *rmem, return 0; } -static const struct reserved_mem_ops rmem_tcon_fb_ops = { - .device_init = rmem_tcon_fb_device_init, +static const struct reserved_mem_ops tcon_fb_ops = { + .device_init = tcon_fb_device_init, }; -static int __init rmem_tcon_fb_setup(struct reserved_mem *rmem) +static int __init tcon_fb_setup(struct reserved_mem *rmem) { - /* - * phys_addr_t align = PAGE_SIZE; - * phys_addr_t mask = align - 1; - * if ((rmem->base & mask) || (rmem->size & mask)) { - * LCDERR("Reserved memory: incorrect alignment of region\n"); - * return -EINVAL; - * } - */ - tcon_fb_rmem.base = rmem->base; - tcon_fb_rmem.size = rmem->size; - rmem->ops = &rmem_tcon_fb_ops; - LCDPR("tcon: Reserved memory: created fb at 0x%p, size %ld MiB\n", - (void *)rmem->base, (unsigned long)rmem->size / SZ_1M); + tcon_rmem.mem_paddr = rmem->base; + tcon_rmem.mem_size = rmem->size; + rmem->ops = &tcon_fb_ops; + LCDPR("tcon: Reserved memory: created fb at 0x%lx, size %ld MiB\n", + (unsigned long)rmem->base, (unsigned long)rmem->size / SZ_1M); return 0; } -RESERVEDMEM_OF_DECLARE(fb, "amlogic, lcd_tcon-memory", rmem_tcon_fb_setup); +RESERVEDMEM_OF_DECLARE(fb, "amlogic, lcd_tcon-memory", tcon_fb_setup); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.h b/drivers/amlogic/media/vout/lcd/lcd_tcon.h index 8f210e623767..e557923d8cea 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.h +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.h @@ -17,6 +17,9 @@ #ifndef __AML_LCD_TCON_H__ #define __AML_LCD_TCON_H__ +#include +#include +#include #include #define REG_LCD_TCON_MAX 0xffff @@ -37,12 +40,19 @@ struct lcd_tcon_data_s { unsigned int ctrl_timing_offset; unsigned int ctrl_timing_cnt; - unsigned int axi_offset_addr; + unsigned int axi_mem_size; unsigned char *reg_table; int (*tcon_enable)(struct lcd_config_s *pconf); }; +struct tcon_rmem_s { + unsigned char flag; + void *mem_vaddr; + phys_addr_t mem_paddr; + unsigned int mem_size; +}; + /* ********************************** * tcon config * ********************************** @@ -54,8 +64,8 @@ struct lcd_tcon_data_s { #define BIT_TOP_EN_TL1 4 -#define REG_CORE_OD_TL1 0x5c -#define BIT_OD_EN_TL1 6 +#define REG_CORE_OD_TL1 0x247 +#define BIT_OD_EN_TL1 0 #define REG_CORE_CTRL_TIMING_BASE_TL1 0x1b #define CTRL_TIMING_OFFSET_TL1 12 #define CTRL_TIMING_CNT_TL1 0 diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index ae082689e9df..495960d84a71 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -1854,9 +1854,9 @@ int lcd_tv_driver_init(void) lcd_mlvds_phy_set(pconf, 1); break; case LCD_P2P: + lcd_tcon_pinmux_set(1); lcd_p2p_control_set(pconf); lcd_p2p_phy_set(pconf, 1); - lcd_tcon_pinmux_set(1); break; default: break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index cbe6cef7f9ce..5f06f58815d1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -776,13 +776,17 @@ static int lcd_init_load_from_dts(struct lcd_config_s *pconf, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); /* lock pinmux if lcd in on */ - switch (pconf->lcd_basic.lcd_type) { - case LCD_VBYONE: - if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) { + switch (pconf->lcd_basic.lcd_type) { + case LCD_VBYONE: lcd_vbyone_pinmux_set(1); - break; - default: - break; + break; + case LCD_P2P: + lcd_tcon_pinmux_set(1); + break; + default: + break; + } } return ret; diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 95c87fd6612f..afd37fe31e6c 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -1008,7 +1008,8 @@ static int lcd_fops_create(void) return -1; } - LCDPR("%s OK\n", __func__); + if (lcd_debug_print_flag) + LCDPR("%s OK\n", __func__); return 0; } @@ -1315,6 +1316,57 @@ static int lcd_config_probe(struct platform_device *pdev) return 0; } +static int lcd_vsync_irq_init(void) +{ + if (lcd_driver->res_vsync_irq) { + if (request_irq(lcd_driver->res_vsync_irq->start, + lcd_vsync_isr, IRQF_SHARED, + "lcd_vsync", (void *)"lcd_vsync")) { + LCDERR("can't request lcd_vsync_irq\n"); + } else { + if (lcd_debug_print_flag) + LCDPR("request lcd_vsync_irq successful\n"); + } + } + + if (lcd_driver->res_vsync2_irq) { + if (request_irq(lcd_driver->res_vsync2_irq->start, + lcd_vsync2_isr, IRQF_SHARED, + "lcd_vsync2", (void *)"lcd_vsync2")) { + LCDERR("can't request lcd_vsync2_irq\n"); + } else { + if (lcd_debug_print_flag) + LCDPR("request lcd_vsync2_irq successful\n"); + } + } + + /* add timer to monitor hpll frequency */ + init_timer(&lcd_vsync_none_timer); + /* lcd_vsync_none_timer.data = NULL; */ + lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler; + lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL; + /*add_timer(&lcd_vsync_none_timer);*/ + /*LCDPR("add lcd_vsync_none_timer handler\n"); */ + + return 0; +} + +static void lcd_vsync_irq_remove(void) +{ + if (lcd_driver->res_vsync_irq) + free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync"); + + if (lcd_driver->res_vsync2_irq) { + free_irq(lcd_driver->res_vsync2_irq->start, + (void *)"lcd_vsync"); + } + + if (lcd_driver->vsync_none_timer_flag) { + del_timer_sync(&lcd_vsync_none_timer); + lcd_driver->vsync_none_timer_flag = 0; + } +} + #ifdef CONFIG_OF static struct lcd_data_s lcd_data_gxl = { From d0533b8c2b754b15740458cc75876979320cb1d1 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Wed, 12 Dec 2018 16:33:29 +0800 Subject: [PATCH 0612/1060] lcd: update p2p config and pll setting for tl1 [1/1] PD#SWPL-3108 Problem: 1. tcon pll don't support spread spectrum yet 2. no p2p parameters config Solution: 1. add p2p config parameters 2. enable tl1 clk parameters auto generate 3. add tl1 tcon_pll spread spectrum support 4. update clk spread spectrum api: set ss_level(hex val): echo level >/sys/class/lcd/ss set ss_freq(hex val): echo freq >/sys/class/lcd/ss set ss_mode(hex val): echo mode >/sys/class/lcd/ss set ss advance(hex val, [15:12]=mode, [11:8]=freq, [7:0]=level): echo >/sys/class/lcd/ss show ss_level, ss_freq, ss_mode: cat /sys/class/lcd/ss Verify: x301 Change-Id: I99eeca84290403fe766b17673ba9b0f7429fae26 Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi drivers/amlogic/media/vout/lcd/lcd_clk_config.c drivers/amlogic/media/vout/lcd/lcd_common.h drivers/amlogic/media/vout/lcd/lcd_debug.c drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c drivers/amlogic/media/vout/lcd/lcd_vout.c include/linux/amlogic/media/vout/lcd/lcd_vout.h --- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 157 ++---- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 133 +---- .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 137 +---- .../amlogic/media/vout/lcd/lcd_clk_config.c | 512 ++++++++++++------ .../amlogic/media/vout/lcd/lcd_clk_config.h | 20 +- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 58 +- drivers/amlogic/media/vout/lcd/lcd_common.h | 6 +- drivers/amlogic/media/vout/lcd/lcd_debug.c | 133 +++-- drivers/amlogic/media/vout/lcd/lcd_reg.c | 4 +- .../media/vout/lcd/lcd_tablet/lcd_tablet.c | 31 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 55 +- .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 84 ++- drivers/amlogic/media/vout/lcd/lcd_vout.c | 20 +- .../linux/amlogic/media/vout/lcd/lcd_vout.h | 26 +- 14 files changed, 748 insertions(+), 628 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 04ac12492173..56002255b208 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -205,7 +205,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -216,7 +216,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable */ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = <0 0 1 50 /*panel power on*/ @@ -247,7 +247,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -258,7 +258,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -302,7 +302,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -335,7 +335,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -346,7 +346,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -381,7 +381,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -392,7 +392,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -407,7 +407,7 @@ 0xff 0 0 0>; /*ending*/ backlight_index = <2>; }; - p2p_0{ + p2p{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface *(lvds, vbyone, minilvds, p2p) @@ -433,16 +433,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -459,7 +458,7 @@ p2p_1{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -478,20 +477,19 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -507,7 +505,7 @@ p2p_2{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -526,20 +524,19 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -555,7 +552,7 @@ p2p_3{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -574,110 +571,20 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 0 0 1 20 /*panel power on*/ - 2 0 0 10 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - mlvds_0{ - model_name = "mlvds_1080p"; - interface = "minilvds"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) - */ - basic_setting = < - 1920 1080 /*h_active, v_active*/ - 2200 1125 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 2080 2720 /*h_period_min, max*/ - 2200 1125 /*v_period_min, max*/ - 133940000 156000000>; /*pclk_min, max*/ - lcd_timing = < - 44 148 0 /*hs_width, hs_bp, hs_pol*/ - 5 30 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 3 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - minilvds_attr = < - 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ - 0 /* pn_swap */ - 0>; /* bit_swap */ - phy_attr=<0xf 0>; /* vswing_level, preem_level */ - - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 0 0 1 20 /*panel power on*/ - 2 0 0 10 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - mlvds_1{ - model_name = "mlvds_768p"; - interface = "minilvds";/*lcd_interface - *(lvds, vbyone, minilvds, p2p) - */ - basic_setting = < - 1366 768 /*h_active, v_active*/ - 1560 806 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 1460 2000 /*h_period_min, max*/ - 784 1015 /*v_period_min, max*/ - 50000000 85000000>; /*pclk_min, max*/ - lcd_timing = < - 56 64 0 /*hs_width, hs_bp, hs_pol*/ - 3 28 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 3 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - minilvds_attr = < - 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ - 0 /* pn_swap */ - 0>; /* bit_swap */ - phy_attr=<0xf 0>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 444ee3768d6b..f1377e3286a1 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -425,7 +425,7 @@ basic_setting = < 3840 2160 /*h_active, v_active*/ 5000 2250 /*h_period, v_period*/ - 10 /*lcd_bits */ + 8 /*lcd_bits */ 16 9>; /*screen_widht, screen_height*/ range_setting = < 4240 5100 /*h_period_min, max*/ @@ -443,16 +443,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -469,7 +468,7 @@ p2p_1{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -492,16 +491,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -517,7 +515,7 @@ p2p_2{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -540,16 +538,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -565,7 +562,7 @@ p2p_3{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -588,106 +585,16 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 0 0 1 20 /*panel power on*/ - 2 0 0 10 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - mlvds_0{ - model_name = "mlvds_1080p"; - interface = "minilvds"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) - */ - basic_setting = < - 1920 1080 /*h_active, v_active*/ - 2200 1125 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 2080 2720 /*h_period_min, max*/ - 2200 1125 /*v_period_min, max*/ - 133940000 156000000>; /*pclk_min, max*/ - lcd_timing = < - 44 148 0 /*hs_width, hs_bp, hs_pol*/ - 5 30 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 0 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - minilvds_attr = < - 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ - 0 /* pn_swap */ - 0>; /* bit_swap */ - phy_attr=<0xf 0>; /* vswing_level, preem_level */ - - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 0 0 1 20 /*panel power on*/ - 2 0 0 10 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - mlvds_1{ - model_name = "mlvds_768p"; - interface = "minilvds";/*lcd_interface - *(lvds, vbyone, minilvds, p2p) - */ - basic_setting = < - 1366 768 /*h_active, v_active*/ - 1560 806 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 1460 2000 /*h_period_min, max*/ - 784 1015 /*v_period_min, max*/ - 50000000 85000000>; /*pclk_min, max*/ - lcd_timing = < - 56 64 0 /*hs_width, hs_bp, hs_pol*/ - 3 28 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 0 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - minilvds_attr = < - 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ - 0 /* pn_swap */ - 0>; /* bit_swap */ - phy_attr=<0xf 0>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi index 1842e68c7d0d..52428857a45a 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -240,30 +240,32 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; p2p_1{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -286,30 +288,31 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < + 0 0 1 20 /*panel power on*/ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; p2p_2{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -332,30 +335,31 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < + 0 0 1 20 /*panel power on*/ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; p2p_3{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) + *(lvds, vbyone, mlvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -378,109 +382,24 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, + * 4=chpi + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<0xf 1>; /* vswing_level, preem_level */ - - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 2 0 0 10 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - mlvds_0{ - model_name = "mlvds_1080p"; - interface = "minilvds"; /*lcd_interface - *(lvds, vbyone, minilvds, p2p) - */ - basic_setting = < - 1920 1080 /*h_active, v_active*/ - 2200 1125 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 2080 2720 /*h_period_min, max*/ - 2200 1125 /*v_period_min, max*/ - 133940000 156000000>; /*pclk_min, max*/ - lcd_timing = < - 44 148 0 /*hs_width, hs_bp, hs_pol*/ - 5 30 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 0 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - minilvds_attr = < - 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ - 0 /* pn_swap */ - 0>; /* bit_swap */ - phy_attr=<0xf 0>; /* vswing_level, preem_level */ - - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 2 0 0 10 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - mlvds_1{ - model_name = "mlvds_768p"; - interface = "minilvds";/*lcd_interface - *(lvds, vbyone, minilvds, p2p) - */ - basic_setting = < - 1366 768 /*h_active, v_active*/ - 1560 806 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 1460 2000 /*h_period_min, max*/ - 784 1015 /*v_period_min, max*/ - 50000000 85000000>; /*pclk_min, max*/ - lcd_timing = < - 56 64 0 /*hs_width, hs_bp, hs_pol*/ - 3 28 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 0 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - minilvds_attr = < - 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ - 0 /* pn_swap */ - 0>; /* bit_swap */ - phy_attr=<0xf 0>; /* vswing_level, preem_level */ + phy_attr=<3 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < + 0 0 1 20 /*panel power on*/ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index f4a6dfcfca73..d93f45d563cc 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -47,9 +47,11 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */ .pll_od1_sel = 0, .pll_od2_sel = 0, .pll_od3_sel = 0, - .pll_pi_div_sel = 0, /* for tcon */ + .pll_tcon_div_sel = 0, .pll_level = 0, .ss_level = 0, + .ss_freq = 0, + .ss_mode = 0, .div_sel = 0, .xd = 0, .pll_fout = 0, @@ -163,7 +165,7 @@ pll_lock_end_g12a: return ret; } -static void lcd_set_pll_ss_txl(unsigned int ss_level) +static void lcd_set_pll_ss_level_txl(unsigned int level) { unsigned int pll_ctrl3, pll_ctrl4; @@ -172,15 +174,13 @@ static void lcd_set_pll_ss_txl(unsigned int ss_level) pll_ctrl3 &= ~((0xf << 10) | (1 << 14)); pll_ctrl4 &= ~(0x3 << 2); - ss_level = (ss_level >= SS_LEVEL_MAX_TXL) ? 0 : ss_level; - pll_ctrl3 |= pll_ss_reg_txl[ss_level][0]; - pll_ctrl4 |= pll_ss_reg_txl[ss_level][1]; + pll_ctrl3 |= pll_ss_reg_txl[level][0]; + pll_ctrl4 |= pll_ss_reg_txl[level][1]; lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4); - LCDPR("set pll spread spectrum: %s\n", - lcd_pll_ss_table_txl[ss_level]); + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_txl[level]); } static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) @@ -217,10 +217,10 @@ static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); if (cConf->ss_level > 0) - lcd_set_pll_ss_txl(cConf->ss_level); + lcd_set_pll_ss_level_txl(cConf->ss_level); } -static void lcd_set_pll_ss_txlx(unsigned int ss_level) +static void lcd_set_pll_ss_level_txlx(unsigned int level) { unsigned int pll_ctrl3, pll_ctrl4, pll_ctrl5; @@ -231,17 +231,15 @@ static void lcd_set_pll_ss_txlx(unsigned int ss_level) pll_ctrl4 &= ~(0x3 << 2); pll_ctrl5 &= ~(0x3 << 30); - ss_level = (ss_level >= SS_LEVEL_MAX_TXLX) ? 0 : ss_level; - pll_ctrl3 |= pll_ss_reg_txlx[ss_level][0]; - pll_ctrl4 |= pll_ss_reg_txlx[ss_level][1]; - pll_ctrl5 |= pll_ss_reg_txlx[ss_level][2]; + pll_ctrl3 |= pll_ss_reg_txlx[level][0]; + pll_ctrl4 |= pll_ss_reg_txlx[level][1]; + pll_ctrl5 |= pll_ss_reg_txlx[level][2]; lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4); lcd_hiu_write(HHI_HDMI_PLL_CNTL5, pll_ctrl5); - LCDPR("set pll spread spectrum: %s\n", - lcd_pll_ss_table_txlx[ss_level]); + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_txlx[level]); } static void lcd_set_pll_txlx(struct lcd_clk_config_s *cConf) @@ -275,7 +273,7 @@ static void lcd_set_pll_txlx(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); if (cConf->ss_level > 0) - lcd_set_pll_ss_txlx(cConf->ss_level); + lcd_set_pll_ss_level_txlx(cConf->ss_level); } static void lcd_set_pll_axg(struct lcd_clk_config_s *cConf) @@ -477,40 +475,90 @@ static void lcd_set_hpll_g12b(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); } -static void lcd_set_pll_ss_tl1(unsigned int ss_level) +static void lcd_set_pll_ss_level_tl1(unsigned int level) { - LCDPR("%s: todo\n", __func__); + unsigned int pll_ctrl2; + unsigned int dep_sel, str_m; + + pll_ctrl2 = lcd_hiu_read(HHI_TCON_PLL_CNTL2); + pll_ctrl2 &= ~((1 << 15) | (0xf << 16) | (0xf << 28)); + + if (level > 0) { + dep_sel = pll_ss_reg_tl1[level][0]; + str_m = pll_ss_reg_tl1[level][1]; + dep_sel = (dep_sel > 10) ? 10 : dep_sel; + str_m = (str_m > 10) ? 10 : str_m; + pll_ctrl2 |= ((1 << 15) | (dep_sel << 28) | (str_m << 16)); + } + lcd_hiu_write(HHI_TCON_PLL_CNTL2, pll_ctrl2); + + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_tl1[level]); +} + +static void lcd_set_pll_ss_advance_tl1(unsigned int freq, unsigned int mode) +{ + unsigned int pll_ctrl2; + + pll_ctrl2 = lcd_hiu_read(HHI_TCON_PLL_CNTL2); + pll_ctrl2 &= ~(0x7 << 24); /* ss_freq */ + pll_ctrl2 |= (freq << 24); + pll_ctrl2 &= ~(0x3 << 22); /* ss_mode */ + pll_ctrl2 |= (mode << 22); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, pll_ctrl2); + + LCDPR("set pll spread spectrum: freq=%d, mode=%d\n", freq, mode); } static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) { -#if 0 +#if 1 unsigned int pll_ctrl, pll_ctrl1; + unsigned int tcon_div_table[5][3] = { + {1, 0, 1}, + {0, 0, 1}, + {0, 1, 1}, + {0, 0, 0}, + {0, 1, 0}, + }; + unsigned int tcon_div_sel = cConf->pll_tcon_div_sel; int ret; if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); pll_ctrl = ((0x3 << 17) | /* gate ctrl */ - (1 << LCD_PLL_RST_TL1) | + (tcon_div_table[tcon_div_sel][2] << 16) | (cConf->pll_n << LCD_PLL_N_TL1) | (cConf->pll_m << LCD_PLL_M_TL1) | (cConf->pll_od3_sel << LCD_PLL_OD3_TL1) | (cConf->pll_od2_sel << LCD_PLL_OD2_TL1) | (cConf->pll_od1_sel << LCD_PLL_OD1_TL1)); - pll_ctrl1 = (1 << 28) | (1 << 23) | - ((1 << 20) | (cConf->pll_frac << 0)); + pll_ctrl1 = (1 << 28) | + (tcon_div_table[tcon_div_sel][0] << 22) | + (tcon_div_table[tcon_div_sel][1] << 21) | + ((1 << 20) | /* sdm_en */ + (cConf->pll_frac << 0)); lcd_hiu_write(HHI_TCON_PLL_CNTL0, pll_ctrl); + udelay(10); + lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_RST_TL1, 1); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_EN_TL1, 1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, pll_ctrl1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x000100c0); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x008300c0); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, 26, 1); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); #else struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int ret; @@ -605,8 +653,10 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) lcd_hiu_setb(HHI_TCON_PLL_CNTL2, 1, 5, 1); } - if (cConf->ss_level > 0) - lcd_set_pll_ss_tl1(cConf->ss_level); + if (cConf->ss_level > 0) { + lcd_set_pll_ss_level_tl1(cConf->ss_level); + lcd_set_pll_ss_advance_tl1(cConf->ss_freq, cConf->ss_mode); + } } static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cConf) @@ -919,8 +969,7 @@ static int check_pll_txl(struct lcd_clk_config_s *cConf, return done; } -static int check_pll_tl1_mlvds(struct lcd_clk_config_s *cConf, - unsigned int pll_fvco) +static int check_pll_vco(struct lcd_clk_config_s *cConf, unsigned int pll_fvco) { struct lcd_clk_data_s *data = cConf->data; unsigned int m, n; @@ -953,8 +1002,7 @@ static int check_pll_tl1_mlvds(struct lcd_clk_config_s *cConf, } #define PLL_FVCO_ERR_MAX 2 /* kHz */ -static int check_pll_od_tl1_mlvds(struct lcd_clk_config_s *cConf, - unsigned int pll_fout) +static int check_pll_od(struct lcd_clk_config_s *cConf, unsigned int pll_fout) { struct lcd_clk_data_s *data = cConf->data; unsigned int od1_sel, od2_sel, od3_sel, od1, od2, od3; @@ -1005,7 +1053,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) { unsigned int pll_fout, pll_fvco, bit_rate; unsigned int clk_div_in, clk_div_out; - unsigned int clk_div_sel, xd, pi_div_sel; + unsigned int clk_div_sel, xd, tcon_div_sel = 0, phy_div = 1; + unsigned int od1, od2, od3; struct lcd_clk_config_s *cConf = get_lcd_clk_config(); int done; @@ -1078,8 +1127,24 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) clk_div_sel, pll_fout); } done = check_pll_txl(cConf, pll_fout); - if (done) + if (done == 0) goto generate_clk_done_txl; + done = 0; + if (pconf->lcd_control.lvds_config->dual_port) + phy_div = 2; + else + phy_div = 1; + od1 = od_table[cConf->pll_od1_sel]; + od2 = od_table[cConf->pll_od2_sel]; + od3 = od_table[cConf->pll_od3_sel]; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + if (tcon_div_table[tcon_div_sel] == + phy_div * od1 * od2 * od3) { + cConf->pll_tcon_div_sel = tcon_div_sel; + done = 1; + break; + } + } break; case LCD_VBYONE: cConf->div_sel_max = CLK_DIV_SEL_MAX; @@ -1111,32 +1176,32 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) cConf->div_sel); } done = check_pll_txl(cConf, pll_fout); + if (done == 0) + goto generate_clk_done_txl; + done = 0; + od1 = od_table[cConf->pll_od1_sel]; + od2 = od_table[cConf->pll_od2_sel]; + od3 = od_table[cConf->pll_od3_sel]; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + if (tcon_div_table[tcon_div_sel] == od1 * od2 * od3) { + cConf->pll_tcon_div_sel = tcon_div_sel; + done = 1; + break; + } + } break; case LCD_MLVDS: - /* must go through div4 for clk phase */ - for (tcon_div_sel = 3; tcon_div_sel < 5; tcon_div_sel++) { - pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + bit_rate = pconf->lcd_control.mlvds_config->bit_rate / 1000; + for (tcon_div_sel = 1; tcon_div_sel < 3; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel] * 4; done = check_pll_vco(cConf, pll_fvco); - if (done == 0) - continue; - cConf->xd_max = CRT_VID_DIV_MAX; - for (xd = 1; xd <= cConf->xd_max; xd++) { - clk_div_out = cConf->fout * xd; - if (clk_div_out > cConf->data->div_out_fmax) - continue; - if (lcd_debug_print_flag == 2) { - LCDPR( - "fout=%d, xd=%d, clk_div_out=%d\n", - cConf->fout, xd, clk_div_out); - } - for (clk_div_sel = CLK_DIV_SEL_1; - clk_div_sel < CLK_DIV_SEL_MAX; - clk_div_sel++) { - clk_div_in = clk_vid_pll_div_calc( - clk_div_out, clk_div_sel, - CLK_DIV_O2I); - if (clk_div_in > - cConf->data->div_in_fmax) + if (done) { + clk_div_sel = CLK_DIV_SEL_1; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > + cConf->data->div_out_fmax) continue; if (lcd_debug_print_flag == 2) { LCDPR("fout=%d, xd=%d\n", @@ -1178,7 +1243,7 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) continue; cConf->xd = xd; cConf->div_sel = clk_div_sel; - cConf->pll_pi_div_sel = pi_div_sel; + cConf->pll_tcon_div_sel = tcon_div_sel; pll_fout = clk_div_in; if (lcd_debug_print_flag == 2) { LCDPR("clk_div_sel=%s(%d)\n", @@ -1187,11 +1252,10 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) clk_div_sel); LCDPR("pll_fout=%d\n", pll_fout); - LCDPR("pi_clk_sel=%d\n", - pi_div_sel); + LCDPR("tcon_div_sel=%d\n", + tcon_div_sel); } - done = check_pll_od_tl1_mlvds( - cConf, pll_fout); + done = check_pll_od(cConf, pll_fout); if (done) goto generate_clk_done_txl; } @@ -1199,28 +1263,49 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) } break; case LCD_P2P: - clk_div_sel = CLK_DIV_SEL_1; - xd = 1; - clk_div_out = cConf->fout * xd; - if (clk_div_out > cConf->data->div_out_fmax) - goto generate_clk_done_txl; - if (lcd_debug_print_flag == 2) { - LCDPR("fout=%d, xd=%d, clk_div_out=%d\n", - cConf->fout, xd, clk_div_out); + bit_rate = pconf->lcd_control.p2p_config->bit_rate / 1000; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + done = check_pll_vco(cConf, pll_fvco); + if (done == 0) + continue; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + continue; + if (lcd_debug_print_flag == 2) { + LCDPR( + "fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + for (clk_div_sel = CLK_DIV_SEL_1; + clk_div_sel < CLK_DIV_SEL_MAX; + clk_div_sel++) { + clk_div_in = clk_vid_pll_div_calc( + clk_div_out, clk_div_sel, + CLK_DIV_O2I); + if (clk_div_in > + cConf->data->div_in_fmax) + continue; + cConf->xd = xd; + cConf->div_sel = clk_div_sel; + cConf->pll_tcon_div_sel = tcon_div_sel; + pll_fout = clk_div_in; + if (lcd_debug_print_flag == 2) { + LCDPR("clk_div_sel=%s(%d)\n", + lcd_clk_div_sel_table[clk_div_sel], + clk_div_sel); + LCDPR( + "pll_fout=%d, tcon_div_sel=%d\n", + pll_fout, tcon_div_sel); + } + done = check_pll_od(cConf, pll_fout); + if (done) + goto generate_clk_done_txl; + } + } } - clk_div_in = clk_vid_pll_div_calc(clk_div_out, - clk_div_sel, CLK_DIV_O2I); - if (clk_div_in > cConf->data->div_in_fmax) - goto generate_clk_done_txl; - cConf->xd = xd; - cConf->div_sel = clk_div_sel; - pll_fout = clk_div_in; - if (lcd_debug_print_flag == 2) { - LCDPR("clk_div_sel=%s(index %d), pll_fout=%d\n", - lcd_clk_div_sel_table[clk_div_sel], - clk_div_sel, pll_fout); - } - done = check_pll_txl(cConf, pll_fout); if (done) goto generate_clk_done_txl; break; @@ -2032,7 +2117,9 @@ static void lcd_clk_config_init_print_dft(void) "div_in_fmax: %d\n" "div_out_fmax: %d\n" "xd_out_fmax: %d\n" - "ss_level_max: %d\n\n", + "ss_level_max: %d\n" + "ss_freq_max: %d\n" + "ss_mode_max: %d\n\n", data->pll_m_max, data->pll_m_min, data->pll_n_max, data->pll_n_min, data->pll_od_fb, data->pll_frac_range, @@ -2041,7 +2128,8 @@ static void lcd_clk_config_init_print_dft(void) data->pll_vco_fmax, data->pll_vco_fmin, data->pll_out_fmax, data->pll_out_fmin, data->div_in_fmax, data->div_out_fmax, - data->xd_out_fmax, data->ss_level_max); + data->xd_out_fmax, data->ss_level_max, + data->ss_freq_max, data->ss_mode_max); } static void lcd_clk_config_init_print_axg(void) @@ -2063,8 +2151,7 @@ static void lcd_clk_config_init_print_axg(void) "pll_vco_fmin: %d\n" "pll_out_fmax: %d\n" "pll_out_fmin: %d\n" - "xd_out_fmax: %d\n" - "ss_level_max: %d\n\n", + "xd_out_fmax: %d\n\n", data->vclk_sel, data->pll_m_max, data->pll_m_min, data->pll_n_max, data->pll_n_min, @@ -2073,7 +2160,7 @@ static void lcd_clk_config_init_print_axg(void) data->pll_ref_fmax, data->pll_ref_fmin, data->pll_vco_fmax, data->pll_vco_fmin, data->pll_out_fmax, data->pll_out_fmin, - data->xd_out_fmax, data->ss_level_max); + data->xd_out_fmax); } static int lcd_clk_config_print_dft(char *buf, int offset) @@ -2083,28 +2170,31 @@ static int lcd_clk_config_print_dft(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "lcd clk config:\n" - "pll_mode: %d\n" - "pll_m: %d\n" - "pll_n: %d\n" - "pll_frac: 0x%03x\n" - "pll_fvco: %dkHz\n" - "pll_od1: %d\n" - "pll_od2: %d\n" - "pll_od3: %d\n" - "pll_pi_div_sel: %d\n" - "pll_out: %dkHz\n" - "div_sel: %s(index %d)\n" - "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "pll_mode: %d\n" + "pll_m: %d\n" + "pll_n: %d\n" + "pll_frac: 0x%03x\n" + "pll_fvco: %dkHz\n" + "pll_od1: %d\n" + "pll_od2: %d\n" + "pll_od3: %d\n" + "pll_tcon_div_sel: %d\n" + "pll_out: %dkHz\n" + "div_sel: %s(index %d)\n" + "xd: %d\n" + "fout: %dkHz\n" + "ss_level: %d\n" + "ss_freq: %d\n" + "ss_mode: %d\n\n", clk_conf.pll_mode, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_od2_sel, - clk_conf.pll_od3_sel, clk_conf.pll_pi_div_sel, + clk_conf.pll_od3_sel, clk_conf.pll_tcon_div_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout, clk_conf.ss_level, + clk_conf.ss_freq, clk_conf.ss_mode); return len; } @@ -2123,12 +2213,11 @@ static int lcd_clk_config_print_axg(char *buf, int offset) "pll_od: %d\n" "pll_out: %dkHz\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_fout, - clk_conf.xd, clk_conf.fout, clk_conf.ss_level); + clk_conf.xd, clk_conf.fout); return len; } @@ -2149,13 +2238,12 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) "pll_od: %d\n" "pll_out: %dkHz\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.data->vclk_sel, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_fout, - clk_conf.xd, clk_conf.fout, clk_conf.ss_level); + clk_conf.xd, clk_conf.fout); } else { len += snprintf((buf+len), n, "lcd clk config:\n" @@ -2170,8 +2258,7 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) "pll_out: %dkHz\n" "div_sel: %s(index %d)\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.data->vclk_sel, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, @@ -2179,7 +2266,7 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) clk_conf.pll_od3_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout); } return len; @@ -2200,43 +2287,100 @@ void lcd_clk_generate_parameter(struct lcd_config_s *pconf) clk_conf.data->clk_generate_parameter(pconf); } -static char lcd_ss_invalid_str[10] = {'i', 'n', 'v', 'a', 'l', 'i', 'd', '\0',}; -char *lcd_get_spread_spectrum(void) +int lcd_get_ss(char *buf) { - char *ss_str = lcd_ss_invalid_str; - unsigned int level; + unsigned int temp; + int len = 0; - level = clk_conf.ss_level; - if (clk_conf.data) { - level = (level >= clk_conf.data->ss_level_max) ? 0 : level; - if (clk_conf.data->pll_ss_table) - ss_str = clk_conf.data->pll_ss_table[level]; + if (clk_conf.data == NULL) { + len += sprintf(buf+len, "lcd clk config data is null\n"); + return len; + } + if (clk_conf.data->ss_level_max == 0) { + len += sprintf(buf+len, "lcd spread spectrum is invalid\n"); + return len; } - return ss_str; + temp = (clk_conf.ss_level >= clk_conf.data->ss_level_max) ? + 0 : clk_conf.ss_level; + if (clk_conf.data->ss_level_table) { + len += sprintf(buf+len, "ss_level: %s\n", + clk_conf.data->ss_level_table[temp]); + } + temp = (clk_conf.ss_freq >= clk_conf.data->ss_freq_max) ? + 0 : clk_conf.ss_freq; + if (clk_conf.data->ss_freq_table) { + len += sprintf(buf+len, "ss_freq: %s\n", + clk_conf.data->ss_freq_table[temp]); + } + temp = (clk_conf.ss_mode >= clk_conf.data->ss_mode_max) ? + 0 : clk_conf.ss_mode; + if (clk_conf.data->ss_mode_table) { + len += sprintf(buf+len, "ss_mode: %s\n", + clk_conf.data->ss_mode_table[temp]); + } + + return len; } -void lcd_set_spread_spectrum(unsigned int ss_level) +int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode) { unsigned long flags = 0; + int ret = -1; spin_lock_irqsave(&lcd_clk_lock, flags); if (clk_conf.data == NULL) { LCDERR("%s: clk config data is null\n", __func__); - goto lcd_set_spread_spectrum_end; + goto lcd_set_ss_end; + } + if (level < 0xff) { + if (level >= clk_conf.data->ss_level_max) { + LCDERR("%s: ss_level %d is out of support (max %d)\n", + __func__, level, clk_conf.data->ss_level_max); + goto lcd_set_ss_end; + } + } + if (freq < 0xff) { + if (freq >= clk_conf.data->ss_freq_max) { + LCDERR("%s: ss_freq %d is out of support (max %d)\n", + __func__, freq, clk_conf.data->ss_freq_max); + goto lcd_set_ss_end; + } + } + if (mode < 0xff) { + if (mode >= clk_conf.data->ss_freq_max) { + LCDERR("%s: ss_mode %d is out of support (max %d)\n", + __func__, mode, clk_conf.data->ss_mode_max); + goto lcd_set_ss_end; + } } - clk_conf.ss_level = (ss_level >= clk_conf.data->ss_level_max) ? - 0 : ss_level; - if (clk_conf.data->set_spread_spectrum) - clk_conf.data->set_spread_spectrum(clk_conf.ss_level); + if (clk_conf.data->set_ss_level) { + if (level < 0xff) { + clk_conf.ss_level = level; + clk_conf.data->set_ss_level(level); + } + } -lcd_set_spread_spectrum_end: + ret = 0; + if (clk_conf.data->set_ss_advance) { + if ((freq == 0xff) && (mode == 0xff)) + goto lcd_set_ss_end; + if (freq < 0xff) + clk_conf.ss_freq = freq; + if (mode < 0xff) + clk_conf.ss_mode = mode; + clk_conf.data->set_ss_advance(clk_conf.ss_freq, + clk_conf.ss_mode); + } + +lcd_set_ss_end: spin_unlock_irqrestore(&lcd_clk_lock, flags); if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + return ret; } /* design for vlock, don't save ss_level to clk_config */ @@ -2573,16 +2717,22 @@ static struct lcd_clk_data_s lcd_clk_data_gxl = { .div_in_fmax = CLK_DIV_IN_MAX_GXL, .div_out_fmax = CRT_VID_CLK_IN_MAX_GXL, .xd_out_fmax = ENCL_CLK_IN_MAX_GXL, - .ss_level_max = SS_LEVEL_MAX_GXL, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, .clk_gate_optional_switch = NULL, @@ -2609,16 +2759,22 @@ static struct lcd_clk_data_s lcd_clk_data_txl = { .div_in_fmax = CLK_DIV_IN_MAX_TXL, .div_out_fmax = CRT_VID_CLK_IN_MAX_TXL, .xd_out_fmax = ENCL_CLK_IN_MAX_TXL, - .ss_level_max = SS_LEVEL_MAX_TXL, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = lcd_pll_ss_table_txl, + + .ss_level_max = sizeof(lcd_ss_level_table_txl) / sizeof(char *), + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = lcd_ss_level_table_txl, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = lcd_set_pll_ss_txl, + .set_ss_level = lcd_set_pll_ss_level_txl, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, .clk_gate_optional_switch = NULL, @@ -2645,16 +2801,22 @@ static struct lcd_clk_data_s lcd_clk_data_txlx = { .div_in_fmax = CLK_DIV_IN_MAX_TXLX, .div_out_fmax = CRT_VID_CLK_IN_MAX_TXLX, .xd_out_fmax = ENCL_CLK_IN_MAX_TXLX, - .ss_level_max = SS_LEVEL_MAX_TXLX, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = lcd_pll_ss_table_txlx, + + .ss_level_max = sizeof(lcd_ss_level_table_txlx) / sizeof(char *), + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = lcd_ss_level_table_txlx, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = lcd_set_pll_ss_txlx, + .set_ss_level = lcd_set_pll_ss_level_txlx, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txlx, .clk_gate_switch = lcd_clk_gate_switch_dft, .clk_gate_optional_switch = NULL, @@ -2681,16 +2843,22 @@ static struct lcd_clk_data_s lcd_clk_data_axg = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_AXG, .xd_out_fmax = ENCL_CLK_IN_MAX_AXG, - .ss_level_max = SS_LEVEL_MAX_AXG, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_axg, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_axg, .clk_gate_switch = lcd_clk_gate_switch_axg, .clk_gate_optional_switch = NULL, @@ -2717,16 +2885,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path0 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, .clk_path_valid = 1, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_g12a_path0, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_hpll_g12a, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clk_gate_optional_switch = NULL, @@ -2753,16 +2927,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path1 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_GP0_G12A, .clk_path_valid = 1, .vclk_sel = 1, .pll_ctrl_table = pll_ctrl_table_g12a_path1, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clk_gate_optional_switch = NULL, @@ -2789,16 +2969,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path0 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, .clk_path_valid = 1, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_g12a_path0, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_hpll_g12a, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clk_gate_optional_switch = NULL, @@ -2825,16 +3011,22 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path1 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_GP0_G12A, .clk_path_valid = 1, .vclk_sel = 1, .pll_ctrl_table = pll_ctrl_table_g12a_path1, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, .clk_gate_optional_switch = NULL, @@ -2861,16 +3053,22 @@ static struct lcd_clk_data_s lcd_clk_data_tl1 = { .div_in_fmax = CLK_DIV_IN_MAX_TL1, .div_out_fmax = CRT_VID_CLK_IN_MAX_TL1, .xd_out_fmax = ENCL_CLK_IN_MAX_TL1, - .ss_level_max = SS_LEVEL_MAX_TL1, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_tl1, - .pll_ss_table = NULL, + + .ss_level_max = sizeof(lcd_ss_level_table_tl1) / sizeof(char *), + .ss_freq_max = sizeof(lcd_ss_freq_table_tl1) / sizeof(char *), + .ss_mode_max = sizeof(lcd_ss_mode_table_tl1) / sizeof(char *), + .ss_level_table = lcd_ss_level_table_tl1, + .ss_freq_table = lcd_ss_freq_table_tl1, + .ss_mode_table = lcd_ss_mode_table_tl1, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = lcd_set_pll_ss_level_tl1, + .set_ss_advance = lcd_set_pll_ss_advance_tl1, .clk_set = lcd_clk_set_tl1, .clk_gate_switch = lcd_clk_gate_switch_dft, .clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1, diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 9044c5994b2f..487117d55f63 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -58,16 +58,22 @@ struct lcd_clk_data_s { unsigned int div_in_fmax; unsigned int div_out_fmax; unsigned int xd_out_fmax; - unsigned int ss_level_max; unsigned char clk_path_valid; unsigned char vclk_sel; struct lcd_clk_ctrl_s *pll_ctrl_table; - char **pll_ss_table; + + unsigned int ss_level_max; + unsigned int ss_freq_max; + unsigned int ss_mode_max; + char **ss_level_table; + char **ss_freq_table; + char **ss_mode_table; void (*clk_generate_parameter)(struct lcd_config_s *pconf); void (*pll_frac_generate)(struct lcd_config_s *pconf); - void (*set_spread_spectrum)(unsigned int ss_level); + void (*set_ss_level)(unsigned int level); + void (*set_ss_advance)(unsigned int freq, unsigned int mode); void (*clk_set)(struct lcd_config_s *pconf); void (*clk_gate_switch)(struct aml_lcd_drv_s *lcd_drv, int status); void (*clk_gate_optional_switch)(struct aml_lcd_drv_s *lcd_drv, @@ -92,11 +98,13 @@ struct lcd_clk_config_s { /* unit: kHz */ unsigned int pll_od1_sel; unsigned int pll_od2_sel; unsigned int pll_od3_sel; - unsigned int pll_pi_div_sel; /* for tcon */ + unsigned int pll_tcon_div_sel; unsigned int pll_level; unsigned int pll_frac; unsigned int pll_fout; unsigned int ss_level; + unsigned int ss_freq; + unsigned int ss_mode; unsigned int div_sel; unsigned int xd; unsigned int div_sel_max; @@ -131,8 +139,8 @@ extern struct lcd_clk_config_s *get_lcd_clk_config(void); extern int lcd_clk_config_print(char *buf, int offset); extern int lcd_encl_clk_msr(void); extern void lcd_pll_reset(void); -extern char *lcd_get_spread_spectrum(void); -extern void lcd_set_spread_spectrum(unsigned int ss_level); +extern int lcd_get_ss(char *buf); +extern int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode); extern void lcd_clk_update(struct lcd_config_s *pconf); extern void lcd_clk_set(struct lcd_config_s *pconf); extern void lcd_clk_disable(void); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index 2bf31f6f5efd..041b3b292590 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -239,13 +239,8 @@ * Spread Spectrum * ********************************** */ -#define SS_LEVEL_MAX_GXL 0 -#define SS_LEVEL_MAX_AXG 0 -#define SS_LEVEL_MAX_GP0_G12A 0 -#define SS_LEVEL_MAX_HPLL_G12A 0 -#define SS_LEVEL_MAX_TXL 5 -static char *lcd_pll_ss_table_txl[] = { +static char *lcd_ss_level_table_txl[] = { "0, disable", "1, +/-0.3%", "2, +/-0.4%", @@ -253,8 +248,7 @@ static char *lcd_pll_ss_table_txl[] = { "4, +/-1.2%", }; -#define SS_LEVEL_MAX_TXLX 6 -static char *lcd_pll_ss_table_txlx[] = { +static char *lcd_ss_level_table_txlx[] = { "0, disable", "1, +/-0.3%", "2, +/-0.5%", @@ -263,7 +257,35 @@ static char *lcd_pll_ss_table_txlx[] = { "5, +/-3.0%", }; -#define SS_LEVEL_MAX_TL1 0 +static char *lcd_ss_level_table_tl1[] = { + "0, disable", + "1, 5000ppm", + "2, 10000ppm", + "3, 15000ppm", + "4, 20000ppm", + "5, 25000ppm", + "6, 30000ppm", + "7, 35000ppm", + "8, 40000ppm", + "9, 45000ppm", + "10, 50000ppm", +}; + +static char *lcd_ss_freq_table_tl1[] = { + "0, 29.5KHz", + "1, 31.5KHz", + "2, 50KHz", + "3, 75KHz", + "4, 100KHz", + "5, 150KHz", + "6, 200KHz", +}; + +static char *lcd_ss_mode_table_tl1[] = { + "0, center ss", + "1, up ss", + "2, down ss", +}; static unsigned int pll_ss_reg_txl[][2] = { @@ -275,7 +297,6 @@ static unsigned int pll_ss_reg_txl[][2] = { {((1 << 14) | (0xc << 10)), (0x3 << 2)}, /* 4: +/-1.2% */ }; - static unsigned int pll_ss_reg_txlx[][3] = { /* cntl3 cntl4 cntl5 */ { 0, 0, 0}, /* disable */ @@ -286,6 +307,21 @@ static unsigned int pll_ss_reg_txlx[][3] = { {((1 << 14) | (0xa << 10)), (0x3 << 2), (0x2 << 30)}, /* 5: +/-3.0% */ }; +static unsigned int pll_ss_reg_tl1[][2] = { + /* dep_sel, str_m */ + { 0, 0}, /* 0: disable */ + {10, 1}, /* 1: +/-0.25% */ + {10, 2}, /* 2: +/-0.50% */ + {10, 3}, /* 3: +/-0.75% */ + {10, 4}, /* 4: +/-1.00% */ + {10, 5}, /* 5: +/-1.25% */ + {10, 6}, /* 1: +/-1.50% */ + {10, 7}, /* 2: +/-1.75% */ + {10, 8}, /* 3: +/-2.00% */ + {10, 9}, /* 4: +/-2.25% */ + {10, 10}, /* 5: +/-2.50% */ +}; + /* ********************************** * pll control * ********************************** @@ -356,7 +392,7 @@ static const unsigned int od_table[6] = { 1, 2, 4, 8, 16, 32 }; -static const unsigned int pi_div_table[2] = {2, 4}; +static const unsigned int tcon_div_table[5] = {1, 2, 4, 8, 16}; static char *lcd_clk_div_sel_table[] = { "1", diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index aa31da107db0..cf51a9e23879 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -34,11 +34,7 @@ /* 20180928: tl1 support, optimize clk config */ /* 20181012: tl1 support tcon */ /* 20181212: tl1 update p2p config and pll setting */ -/* 20181225: update phy config */ -/* 20190108: tl1 support tablet mode */ -/* 20190115: tl1 tcon all interface support */ -/* 20190225: optimize unifykey read flow to avoid crash */ -#define LCD_DRV_VERSION "20190225" +#define LCD_DRV_VERSION "20181212" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 0914100baeaf..24a763566ebc 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -102,9 +102,14 @@ static const char *lcd_common_usage_str = { "\n" " echo > test ; show lcd bist pattern(1~7), 0=disable bist\n" "\n" -" echo w > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" -" echo r > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" -" echo d > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" +" echo level > ss ; set lcd clk spread spectrum level\n" +" echo freq > ss ; set lcd clk spread spectrum freq\n" +" echo mode > ss ; set lcd clk spread spectrum mode\n" +" cat ss ; show lcd clk spread spectrum information\n" +"\n" +" echo w > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" +" echo r > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" +" echo d > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" "\n" " echo <0|1> > print ; 0=disable debug print; 1=enable debug print\n" " cat print ; read current debug print flag\n" @@ -465,28 +470,24 @@ static int lcd_info_print_p2p(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, - "p2p_type 0x%x\n" + "p2p_type %d\n" "lane_num %d\n" "channel_sel1 0x%08x\n" "channel_sel1 0x%08x\n" - "clk_phase 0x%04x\n" "pn_swap %u\n" "bit_swap %u\n" - "phy_vswing 0x%x\n" - "phy_preem 0x%x\n" "bit_rate %dHz\n" - "pi_clk_sel 0x%03x\n\n", + "phy_vswing 0x%x\n" + "phy_preem 0x%x\n\n", + pconf->lcd_control.p2p_config->p2p_type, pconf->lcd_control.p2p_config->lane_num, pconf->lcd_control.p2p_config->channel_sel0, pconf->lcd_control.p2p_config->channel_sel1, - pconf->lcd_control.p2p_config->clk_phase, pconf->lcd_control.p2p_config->pn_swap, pconf->lcd_control.p2p_config->bit_swap, - pconf->lcd_timing.bit_rate, - pconf->lcd_control.p2p_config->phy_vswing, - pconf->lcd_control.p2p_config->phy_preem, pconf->lcd_control.p2p_config->bit_rate, - pconf->lcd_control.p2p_config->pi_clk_sel); + pconf->lcd_control.p2p_config->phy_vswing, + pconf->lcd_control.p2p_config->phy_preem); len += lcd_tcon_info_print((buf+len), (len+offset)); @@ -2067,24 +2068,21 @@ static ssize_t lcd_debug_change_store(struct class *class, break; case 'p': p2p_conf = pconf->lcd_control.p2p_config; - ret = sscanf(buf, "p2p %x %d %x %x %d %d", + ret = sscanf(buf, "p2p %d %d %x %x %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); if (ret == 6) { - p2p_conf->lane_num = val[0]; - p2p_conf->channel_sel0 = val[1]; - p2p_conf->channel_sel1 = val[2]; - p2p_conf->clk_phase = val[3]; + p2p_conf->p2p_type = val[0]; + p2p_conf->lane_num = val[1]; + p2p_conf->channel_sel0 = val[2]; + p2p_conf->channel_sel1 = val[3]; p2p_conf->pn_swap = val[4]; p2p_conf->bit_swap = val[5]; pr_info("change p2p config:\n" - "p2p_type=0x%x, lane_num=%d,\n" + "p2p_type=%d, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" - "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->lane_num, - p2p_conf->channel_sel0, - p2p_conf->channel_sel1, - p2p_conf->clk_phase, + p2p_conf->p2p_type, p2p_conf->lane_num, + p2p_conf->channel_sel0, p2p_conf->channel_sel1, p2p_conf->pn_swap, p2p_conf->bit_swap); lcd_debug_change_clk_change(pconf->lcd_timing.lcd_clk); pconf->change_flag = 1; @@ -2385,24 +2383,81 @@ static ssize_t lcd_debug_fr_policy_store(struct class *class, static ssize_t lcd_debug_ss_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "get lcd pll spread spectrum: %s\n", - lcd_get_spread_spectrum()); + int len; + + len = lcd_get_ss(buf); + return len; } static ssize_t lcd_debug_ss_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; - unsigned int temp = 0; + unsigned int value = 0, temp; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - ret = kstrtouint(buf, 10, &temp); - if (ret) { - pr_info("invalid data\n"); - return -EINVAL; + temp = lcd_drv->lcd_config->lcd_timing.ss_level; + switch (buf[0]) { + case 'l': + ret = sscanf(buf, "level %x", &value); + if (ret == 1) { + value &= 0xff; + ret = lcd_set_ss(value, 0xff, 0xff); + if (ret == 0) { + temp &= ~(0xff); + temp |= value; + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'f': + ret = sscanf(buf, "freq %x", &value); + if (ret == 1) { + value &= 0xf; + ret = lcd_set_ss(0xff, value, 0xff); + if (ret == 0) { + temp &= ~((0xf << LCD_CLK_SS_BIT_FREQ) << 8); + temp |= ((value << LCD_CLK_SS_BIT_FREQ) << 8); + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'm': + ret = sscanf(buf, "mode %x", &value); + if (ret == 1) { + value &= 0xf; + ret = lcd_set_ss(0xff, 0xff, value); + if (ret == 0) { + temp &= ~((0xf << LCD_CLK_SS_BIT_MODE) << 8); + temp |= ((value << LCD_CLK_SS_BIT_MODE) << 8); + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + default: + ret = kstrtouint(buf, 16, &value); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } + value &= 0xffff; + temp = value >> 8; + ret = lcd_set_ss((value & 0xff), + ((temp >> LCD_CLK_SS_BIT_FREQ) & 0xf), + ((temp >> LCD_CLK_SS_BIT_MODE) & 0xf)); + if (ret == 0) + lcd_drv->lcd_config->lcd_timing.ss_level = value; + break; } - lcd_drv->lcd_config->lcd_timing.ss_level = temp; - lcd_set_spread_spectrum(temp); return count; } @@ -2525,9 +2580,9 @@ static ssize_t lcd_debug_mute_store(struct class *class, } static void lcd_debug_reg_write(unsigned int reg, unsigned int data, - unsigned int type) + unsigned int bus) { - switch (type) { + switch (bus) { case 0: /* vcbus */ lcd_vcbus_write(reg, data); pr_info("write vcbus [0x%04x] = 0x%08x, readback 0x%08x\n", @@ -3545,19 +3600,17 @@ static ssize_t lcd_p2p_debug_store(struct class *class, struct p2p_config_s *p2p_conf; p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; - ret = sscanf(buf, "%x %d %x %x %d %d", + ret = sscanf(buf, "%d %d %x %x %d %d", &p2p_conf->p2p_type, &p2p_conf->lane_num, &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, &p2p_conf->pn_swap, &p2p_conf->bit_swap); if (ret == 6) { pr_info("set p2p config:\n" - "p2p_type=0x%x, lane_num=%d,\n" + "p2p_type=%d, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" - "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->lane_num, + p2p_conf->p2p_type, p2p_conf->lane_num, p2p_conf->channel_sel0, p2p_conf->channel_sel1, - p2p_conf->clk_phase, p2p_conf->pn_swap, p2p_conf->bit_swap); lcd_debug_config_update(); } else { diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.c b/drivers/amlogic/media/vout/lcd/lcd_reg.c index 690bc666d051..2824b04914b0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.c +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.c @@ -195,7 +195,7 @@ static inline void __iomem *check_lcd_tcon_reg(unsigned int _reg) reg_offset = LCD_REG_OFFSET(_reg); if (reg_offset >= lcd_reg_map[reg_bus].size) { - LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg); + LCDERR("invalid tcon reg offset: 0x%04x\n", _reg); return NULL; } p = lcd_reg_map[reg_bus].p + reg_offset; @@ -214,7 +214,7 @@ static inline void __iomem *check_lcd_tcon_reg_byte(unsigned int _reg) reg_offset = LCD_REG_OFFSET_BYTE(_reg); if (reg_offset >= lcd_reg_map[reg_bus].size) { - LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg); + LCDERR("invalid tcon reg offset: 0x%04x\n", _reg); return NULL; } p = lcd_reg_map[reg_bus].p + reg_offset; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 81ed0a6fb22e..4bf4862aa3b8 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -719,7 +719,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_timing.lcd_clk = 60; } else { pconf->lcd_timing.fr_adjust_type = (unsigned char)(para[0]); - pconf->lcd_timing.ss_level = (unsigned char)(para[1]); + pconf->lcd_timing.ss_level = para[1]; pconf->lcd_timing.clk_auto = (unsigned char)(para[2]); if (para[3] > 0) { pconf->lcd_timing.lcd_clk = para[3]; @@ -1162,18 +1162,17 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) static void lcd_config_init(struct lcd_config_s *pconf) { struct lcd_clk_config_s *cconf = get_lcd_clk_config(); - unsigned int ss_level; - unsigned int clk; + unsigned int temp; unsigned int sync_duration, h_period, v_period; - clk = pconf->lcd_timing.lcd_clk; + temp = pconf->lcd_timing.lcd_clk; h_period = pconf->lcd_basic.h_period; v_period = pconf->lcd_basic.v_period; - if (clk < 200) { /* regard as frame_rate */ - sync_duration = clk * 100; - pconf->lcd_timing.lcd_clk = clk * h_period * v_period; + if (temp < 200) { /* regard as frame_rate */ + sync_duration = temp * 100; + pconf->lcd_timing.lcd_clk = temp * h_period * v_period; } else { /* regard as pixel clock */ - sync_duration = ((clk / h_period) * 100) / v_period; + sync_duration = ((temp / h_period) * 100) / v_period; } pconf->lcd_timing.sync_duration_num = sync_duration; pconf->lcd_timing.sync_duration_den = 100; @@ -1186,13 +1185,23 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_tablet_config_update(pconf); lcd_clk_generate_parameter(pconf); - ss_level = pconf->lcd_timing.ss_level; if (cconf->data) { - cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? - 0 : ss_level; + temp = pconf->lcd_timing.ss_level & 0xff; + cconf->ss_level = (temp >= cconf->data->ss_level_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_FREQ) & 0xf; + cconf->ss_freq = (temp >= cconf->data->ss_freq_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf; + cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? + 0 : temp; } else { LCDERR("%s: clk config data is null\n", __func__); cconf->ss_level = 0; + cconf->ss_freq = 0; + cconf->ss_mode = 0; } lcd_tablet_config_post_update(pconf); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 495960d84a71..3822445bed76 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -314,7 +314,15 @@ static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x06020602); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 30, 1); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); + break; + } lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); } else { @@ -338,11 +346,22 @@ static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) static void lcd_encl_tcon_set(struct lcd_config_s *pconf) { + unsigned int lcd_bits; + lcd_vcbus_write(L_RGB_BASE_ADDR, 0); lcd_vcbus_write(L_RGB_COEFF_ADDR, 0x400); aml_lcd_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, NULL); - switch (pconf->lcd_basic.lcd_bits) { + switch (pconf->lcd_basic.lcd_type) { + case LCD_MLVDS: + case LCD_P2P: + lcd_bits = 10; + break; + default: + lcd_bits = pconf->lcd_basic.lcd_bits; + break; + } + switch (lcd_bits) { case 8: lcd_vcbus_write(L_DITH_CNTL_ADDR, 0x400); break; @@ -1512,10 +1531,22 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int reg_cntl0, reg_cntl1; + unsigned int phy_div; + unsigned int channel_sel0, channel_sel1; if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + /* phy_div: 0=div6, 1=div 7, 2=div8, 3=div10 */ + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: /* 8/10 coding */ + phy_div = 3; + break; + default: + phy_div = 2; + break; + } + switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: case LCD_CHIP_TM2: @@ -1529,7 +1560,7 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) } /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ - lcd_hiu_write(reg_cntl0, (2 << 6)); + lcd_hiu_write(reg_cntl0, (phy_div << 6)); /* serializer_en[27:16] */ lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); /* pn swap[2] */ @@ -1541,9 +1572,11 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) lcd_hiu_setb(reg_cntl1, 1, 31, 1); /* channel swap default no swap */ - lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); - lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); - lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); + channel_sel0 = pconf->lcd_control.p2p_config->channel_sel0; + channel_sel1 = pconf->lcd_control.p2p_config->channel_sel1; + lcd_vcbus_write(LVDS_CH_SWAP0, (channel_sel0 & 0xff)); + lcd_vcbus_write(LVDS_CH_SWAP1, ((channel_sel0 >> 8) & 0xff)); + lcd_vcbus_write(LVDS_CH_SWAP2, (channel_sel1 & 0xff)); lcd_tcon_enable(pconf); } @@ -1697,7 +1730,7 @@ static void lcd_p2p_config_set(struct lcd_config_s *pconf) break; } - pconf->lcd_timing.bit_rate = bit_rate * 1000; + pconf->lcd_control.p2p_config->bit_rate = bit_rate * 1000; if (lcd_debug_print_flag) { LCDPR("lane_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", @@ -1718,6 +1751,9 @@ void lcd_tv_clk_config_change(struct lcd_config_s *pconf) case LCD_MLVDS: lcd_mlvds_config_set(pconf); break; + case LCD_P2P: + lcd_p2p_config_set(pconf); + break; default: break; } @@ -1758,6 +1794,9 @@ void lcd_tv_config_update(struct lcd_config_s *pconf) case LCD_MLVDS: lcd_mlvds_config_set(pconf); break; + case LCD_P2P: + lcd_p2p_config_set(pconf); + break; default: break; } @@ -1855,8 +1894,8 @@ int lcd_tv_driver_init(void) break; case LCD_P2P: lcd_tcon_pinmux_set(1); - lcd_p2p_control_set(pconf); lcd_p2p_phy_set(pconf, 1); + lcd_p2p_control_set(pconf); break; default: break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index 5f06f58815d1..1c15bbce865a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -801,6 +801,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, struct device_node *child; struct lvds_config_s *lvdsconf; struct vbyone_config_s *vx1_conf; + struct p2p_config_s *p2p_conf; child = of_get_child_by_name(dev->of_node, pconf->lcd_propname); if (child == NULL) { @@ -877,9 +878,9 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_timing.lcd_clk = 60; } else { pconf->lcd_timing.fr_adjust_type = (unsigned char)(para[0]); - pconf->lcd_timing.ss_level = (unsigned char)(para[1]); + pconf->lcd_timing.ss_level = para[1]; pconf->lcd_timing.clk_auto = (unsigned char)(para[2]); - pconf->lcd_timing.lcd_clk = (unsigned char)(para[3]); + pconf->lcd_timing.lcd_clk = para[3]; } switch (pconf->lcd_basic.lcd_type) { @@ -1006,6 +1007,33 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, } break; case LCD_P2P: + p2p_conf = pconf->lcd_control.p2p_config; + ret = of_property_read_u32_array(child, "p2p_attr", + ¶[0], 6); + if (ret) { + LCDERR("failed to get p2p_attr\n"); + } else { + p2p_conf->p2p_type = para[0]; + p2p_conf->lane_num = para[1]; + p2p_conf->channel_sel0 = para[2]; + p2p_conf->channel_sel1 = para[3]; + p2p_conf->pn_swap = para[4]; + p2p_conf->bit_swap = para[5]; + } + ret = of_property_read_u32_array(child, "phy_attr", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get phy_attr\n"); + } else { + p2p_conf->phy_vswing = para[0]; + p2p_conf->phy_preem = para[1]; + if (lcd_debug_print_flag) { + LCDPR("phy vswing=0x%x, preem=0x%x\n", + p2p_conf->phy_vswing, + p2p_conf->phy_preem); + } + } break; default: LCDERR("invalid lcd type\n"); @@ -1027,6 +1055,7 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) struct aml_lcd_unifykey_header_s lcd_header; struct lvds_config_s *lvdsconf = pconf->lcd_control.lvds_config; struct vbyone_config_s *vx1_conf = pconf->lcd_control.vbyone_config; + struct p2p_config_s *p2p_conf = pconf->lcd_control.p2p_config; int ret; para = kmalloc((sizeof(unsigned char) * LCD_UKEY_LCD_SIZE), GFP_KERNEL); @@ -1201,6 +1230,27 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; lvdsconf->lane_reverse = 0; } + } else if (pconf->lcd_basic.lcd_type == LCD_P2P) { + p2p_conf->p2p_type = (*(p + LCD_UKEY_IF_ATTR_0) | + ((*(p + LCD_UKEY_IF_ATTR_0 + 1)) << 8)); + p2p_conf->lane_num = (*(p + LCD_UKEY_IF_ATTR_1) | + ((*(p + LCD_UKEY_IF_ATTR_1 + 1)) << 8)); + p2p_conf->channel_sel0 = (*(p + LCD_UKEY_IF_ATTR_2) | + ((*(p + LCD_UKEY_IF_ATTR_2 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_3) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_3 + 1)) << 24)); + p2p_conf->channel_sel1 = (*(p + LCD_UKEY_IF_ATTR_4) | + ((*(p + LCD_UKEY_IF_ATTR_4 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_5) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_5 + 1)) << 24)); + p2p_conf->pn_swap = (*(p + LCD_UKEY_IF_ATTR_6) | + ((*(p + LCD_UKEY_IF_ATTR_6 + 1)) << 8)); + p2p_conf->bit_swap = (*(p + LCD_UKEY_IF_ATTR_7) | + ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)); + p2p_conf->phy_vswing = (*(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8)); + p2p_conf->phy_preem = (*(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8)); } else LCDERR("unsupport lcd_type: %d\n", pconf->lcd_basic.lcd_type); @@ -1265,19 +1315,19 @@ static void lcd_vmode_init(struct lcd_config_s *pconf) static void lcd_config_init(struct lcd_config_s *pconf) { struct lcd_clk_config_s *cconf = get_lcd_clk_config(); - unsigned int ss_level; - unsigned int clk; + unsigned int temp; if (pconf->lcd_timing.lcd_clk == 0) /* default 0 for 60hz */ pconf->lcd_timing.lcd_clk = 60; else LCDPR("custome clk: %d\n", pconf->lcd_timing.lcd_clk); - clk = pconf->lcd_timing.lcd_clk; - if (clk < 200) { /* regard as frame_rate */ - pconf->lcd_timing.lcd_clk = clk * pconf->lcd_basic.h_period * + temp = pconf->lcd_timing.lcd_clk; + if (temp < 200) { /* regard as frame_rate */ + pconf->lcd_timing.lcd_clk = temp * pconf->lcd_basic.h_period * pconf->lcd_basic.v_period; - } else /* regard as pixel clock */ - pconf->lcd_timing.lcd_clk = clk; + } else { /* regard as pixel clock */ + pconf->lcd_timing.lcd_clk = temp; + } pconf->lcd_timing.lcd_clk_dft = pconf->lcd_timing.lcd_clk; pconf->lcd_timing.h_period_dft = pconf->lcd_basic.h_period; @@ -1287,13 +1337,23 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_vmode_init(pconf); lcd_tv_config_update(pconf); lcd_clk_generate_parameter(pconf); - ss_level = pconf->lcd_timing.ss_level; if (cconf->data) { - cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? - 0 : ss_level; + temp = pconf->lcd_timing.ss_level & 0xff; + cconf->ss_level = (temp >= cconf->data->ss_level_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_FREQ) & 0xf; + cconf->ss_freq = (temp >= cconf->data->ss_freq_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf; + cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? + 0 : temp; } else { LCDERR("%s: clk config data is null\n", __func__); cconf->ss_level = 0; + cconf->ss_freq = 0; + cconf->ss_mode = 0; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index afd37fe31e6c..21989a345e37 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -48,6 +48,7 @@ #endif #include "lcd_reg.h" #include "lcd_common.h" +#include "lcd_clk_config.h" #define LCD_CDEV_NAME "lcd" @@ -129,15 +130,14 @@ static struct mlvds_config_s lcd_mlvds_config = { static struct p2p_config_s lcd_p2p_config = { .p2p_type = P2P_MAX, - .port_num = 6, .lane_num = 12, .channel_sel0 = 0x76543210, .channel_sel1 = 0xba98, - .clk_phase = 0, .pn_swap = 0, .bit_swap = 0, .phy_vswing = 0, .phy_preem = 0, + .bit_rate = 0, }; static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff}; @@ -260,8 +260,7 @@ static void lcd_power_ctrl(int status) #ifdef CONFIG_AMLOGIC_LCD_EXTERN struct aml_lcd_extern_driver_s *ext_drv; #endif - unsigned int i, index, wait, temp; - int value = -1; + unsigned int i, index, value, temp; int ret = 0; LCDPR("%s: %d\n", __func__, status); @@ -314,19 +313,6 @@ static void lcd_power_ctrl(int status) break; #endif case LCD_POWER_TYPE_WAIT_GPIO: - index = power_step->index; - lcd_cpu_gpio_set(index, LCD_GPIO_INPUT); - LCDPR("lcd_power_type_wait_gpio wait\n"); - for (wait = 0; wait < power_step->delay; wait++) { - value = lcd_cpu_gpio_get(index); - if (value == power_step->value) { - LCDPR("wait_gpio %d ok\n", value); - break; - } - mdelay(1); - } - if (wait == power_step->delay) - LCDERR("wait_gpio %d timeout!\n", value); break; case LCD_POWER_TYPE_CLK_SS: temp = lcd_driver->lcd_config->lcd_timing.ss_level; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index d7a3632ee928..3f59733aa4c7 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -138,18 +138,19 @@ struct lcd_basic_s { #define LCD_CLK_PLL_CHANGE (1 << 1) struct lcd_timing_s { unsigned char clk_auto; /* clk parameters auto generation */ + unsigned char fr_adjust_type; /* 0=clock, 1=htotal, 2=vtotal */ + unsigned char clk_change; /* internal used */ unsigned int lcd_clk; /* pixel clock(unit: Hz) */ unsigned int lcd_clk_dft; /* internal used */ unsigned int bit_rate; /* Hz */ unsigned int h_period_dft; /* internal used */ unsigned int v_period_dft; /* internal used */ - unsigned char clk_change; /* internal used */ unsigned int pll_ctrl; /* pll settings */ unsigned int div_ctrl; /* divider settings */ unsigned int clk_ctrl; /* clock settings */ - - unsigned char fr_adjust_type; /* 0=clock, 1=htotal, 2=vtotal */ - unsigned char ss_level; + unsigned int ss_level; /* [15:12]: ss_freq, [11:8]: ss_mode, + * [7:0]: ss_level + */ unsigned int sync_duration_num; unsigned int sync_duration_den; @@ -340,28 +341,24 @@ struct mlvds_config_s { enum p2p_type_e { P2P_CEDS = 0, + P2P_CSPI, P2P_CMPI, P2P_ISP, - P2P_EPI, - P2P_CHPI = 0x10, /* low common mode */ - P2P_CSPI, - P2P_USIT, + P2P_CHPI, P2P_MAX, }; struct p2p_config_s { unsigned int p2p_type; - unsigned int port_num; unsigned int lane_num; unsigned int channel_sel0; unsigned int channel_sel1; - unsigned int clk_phase; /* [13:12]=clk01_pi_sel, - * [11:8]=pi2, [7:4]=pi1, [3:0]=pi0 - */ unsigned int pn_swap; unsigned int bit_swap; /* MSB/LSB reverse */ unsigned int phy_vswing; unsigned int phy_preem; + /* internal used */ + unsigned int bit_rate; /* Hz */ }; struct lcd_control_config_s { @@ -383,6 +380,8 @@ enum lcd_power_type_e { LCD_POWER_TYPE_PMU, LCD_POWER_TYPE_SIGNAL, LCD_POWER_TYPE_EXTERN, + LCD_POWER_TYPE_WAIT_GPIO, + LCD_POWER_TYPE_CLK_SS, LCD_POWER_TYPE_MAX, }; @@ -395,6 +394,9 @@ enum lcd_pmu_gpio_e { LCD_PMU_GPIO_MAX, }; +#define LCD_CLK_SS_BIT_FREQ 0 +#define LCD_CLK_SS_BIT_MODE 4 + #define LCD_GPIO_MAX 0xff #define LCD_GPIO_OUTPUT_LOW 0 #define LCD_GPIO_OUTPUT_HIGH 1 From b264fa4d5c7947ef6bc24f0d984164e78a1cb896 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 11 Dec 2018 18:23:31 +0800 Subject: [PATCH 0613/1060] arm: dts: x301 & t309: enable panel unifykey support for tvconfig [1/1] PD#SWPL-2761 Problem: not support tvconfig yet Solution: 1.enable key_valid in panel dtsi 2.enable fr_auto_policy in panel dtsi 3.enable clk ss for lvds and vbyone in panel dtsi 4.also fix some coverity errors Verify: x301 Change-Id: I00dd5ff621cfbc3f100bbe6045a35c8f917ade29 Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi --- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 33 +++---------------- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 18 +++++----- .../amlogic/media/vout/lcd/lcd_clk_config.c | 11 ++++--- drivers/amlogic/media/vout/lcd/lcd_debug.c | 6 ++-- drivers/amlogic/media/vout/lcd/lcd_vout.c | 2 +- 5 files changed, 25 insertions(+), 45 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 56002255b208..2a0773eb1fff 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -78,7 +78,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 15 /*clk_ss_level*/ + 6 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -163,7 +163,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 15 /*clk_ss_level*/ + 6 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -205,7 +205,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -247,7 +247,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -335,7 +335,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -788,29 +788,6 @@ bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ 2 0 /*pwm1 gpio_index, gpio_off*/ 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ - }; - backlight_3{ - index = <3>; - bl_name = "pwm_combo_ldim_test"; - bl_level_default_uboot_kernel = <31 100>; - bl_level_attr = <255 10 /*max, min*/ - 128 128>; /*mid, mid_mapping*/ - bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ - bl_power_attr = <0 /*en_gpio_index*/ - 1 0 /*on_value, off_value*/ - 410 110>; /*on_delay(ms), off_delay(ms)*/ - bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ - 0 0>; /*pwm_1 range*/ - bl_pwm_combo_port = "PWM_C","PWM_D"; - bl_pwm_combo_attr = <1 /*pwm0 method*/ - 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 100 25 /*pwm0 duty_max(%), duty_min(%)*/ - 1 /*pwm1 method*/ - 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ - 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ - bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ - 2 0 /*pwm1 gpio_index, gpio_off*/ - 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ bl_ldim_region_row_col = <2 10>; }; backlight_4{ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index f1377e3286a1..dccb879f8b4c 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -20,8 +20,8 @@ compatible = "amlogic, lcd-tl1"; status = "okay"; mode = "tv"; - fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ - key_valid = <0>; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; clocks = <&clkc CLKID_VCLK2_ENCL &clkc CLKID_VCLK2_VENCL &clkc CLKID_TCON @@ -82,7 +82,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 6 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -171,7 +171,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 6 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -215,7 +215,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -257,7 +257,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -345,7 +345,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 1 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -612,7 +612,7 @@ lcd_extern{ compatible = "amlogic, lcd_extern"; status = "okay"; - key_valid = <0>; + key_valid = <1>; i2c_bus = "i2c_bus_1"; extern_0{ @@ -712,7 +712,7 @@ backlight{ compatible = "amlogic, backlight-tl1"; status = "okay"; - key_valid = <0>; + key_valid = <1>; pinctrl-names = "pwm_on","pwm_vs_on", "pwm_combo_0_1_on", "pwm_combo_0_vs_1_on", diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index d93f45d563cc..22b60474b451 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -2337,21 +2337,24 @@ int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode) if (level < 0xff) { if (level >= clk_conf.data->ss_level_max) { LCDERR("%s: ss_level %d is out of support (max %d)\n", - __func__, level, clk_conf.data->ss_level_max); + __func__, level, + (clk_conf.data->ss_level_max - 1)); goto lcd_set_ss_end; } } if (freq < 0xff) { if (freq >= clk_conf.data->ss_freq_max) { LCDERR("%s: ss_freq %d is out of support (max %d)\n", - __func__, freq, clk_conf.data->ss_freq_max); + __func__, freq, + (clk_conf.data->ss_freq_max - 1)); goto lcd_set_ss_end; } } if (mode < 0xff) { - if (mode >= clk_conf.data->ss_freq_max) { + if (mode >= clk_conf.data->ss_mode_max) { LCDERR("%s: ss_mode %d is out of support (max %d)\n", - __func__, mode, clk_conf.data->ss_mode_max); + __func__, mode, + (clk_conf.data->ss_mode_max - 1)); goto lcd_set_ss_end; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 24a763566ebc..1df55070a175 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -2399,7 +2399,7 @@ static ssize_t lcd_debug_ss_store(struct class *class, temp = lcd_drv->lcd_config->lcd_timing.ss_level; switch (buf[0]) { case 'l': - ret = sscanf(buf, "level %x", &value); + ret = sscanf(buf, "level %d", &value); if (ret == 1) { value &= 0xff; ret = lcd_set_ss(value, 0xff, 0xff); @@ -2414,7 +2414,7 @@ static ssize_t lcd_debug_ss_store(struct class *class, } break; case 'f': - ret = sscanf(buf, "freq %x", &value); + ret = sscanf(buf, "freq %d", &value); if (ret == 1) { value &= 0xf; ret = lcd_set_ss(0xff, value, 0xff); @@ -2429,7 +2429,7 @@ static ssize_t lcd_debug_ss_store(struct class *class, } break; case 'm': - ret = sscanf(buf, "mode %x", &value); + ret = sscanf(buf, "mode %d", &value); if (ret == 1) { value &= 0xf; ret = lcd_set_ss(0xff, 0xff, value); diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 21989a345e37..8ac00e499d1e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -289,7 +289,7 @@ static void lcd_power_ctrl(int status) break; case LCD_POWER_TYPE_SIGNAL: if (status) - ret = lcd_driver->driver_init(); + lcd_driver->driver_init(); else lcd_driver->driver_disable(); break; From 0b6f5784ae5afe85ea50b28ae747ac542a0d75ee Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 27 Dec 2018 17:17:47 +0800 Subject: [PATCH 0614/1060] lcd: update panel parameters for tl1 [1/1] PD#SWPL-3109 Problem: tl1 tcon parameters need update Solution: 1.update tcon parameters for tl1 2.add minilvds support Verify: x301 Change-Id: Ia9c1defb25f43b2b352400e2ab55c6a74b55d688 Signed-off-by: Evoke Zhang Conflicts: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi drivers/amlogic/media/vout/lcd/lcd_clk_config.c drivers/amlogic/media/vout/lcd/lcd_debug.c --- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 135 +++++++++++++--- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 149 ++++++++++++++---- .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 129 ++++++++++++--- .../dts/amlogic/mesontxlx_r311-panel.dtsi | 14 +- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 44 +++--- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 44 +++--- .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 40 +++-- .../amlogic/media/vout/lcd/lcd_clk_config.c | 61 +++---- drivers/amlogic/media/vout/lcd/lcd_debug.c | 42 +++-- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 75 +++------ .../amlogic/media/vout/lcd/lcd_tv/lcd_tv.c | 52 ++++++ drivers/amlogic/media/vout/lcd/lcd_vout.c | 4 +- .../linux/amlogic/media/vout/lcd/lcd_vout.h | 6 +- 13 files changed, 511 insertions(+), 284 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 2a0773eb1fff..7e87a902df23 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -216,7 +216,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable */ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /* vswing_level, preem_level */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = <0 0 1 50 /*panel power on*/ @@ -258,7 +258,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -302,7 +302,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -346,7 +346,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -392,7 +392,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -407,7 +407,7 @@ 0xff 0 0 0>; /*ending*/ backlight_index = <2>; }; - p2p{ + p2p_0{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface *(lvds, vbyone, minilvds, p2p) @@ -433,15 +433,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -458,7 +458,7 @@ p2p_1{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -481,15 +481,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -505,7 +505,7 @@ p2p_2{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -528,15 +528,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -552,7 +552,7 @@ p2p_3{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -575,16 +575,105 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index dccb879f8b4c..309b6138b82b 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -91,9 +91,7 @@ 0 /*pn_swap*/ 0 /*port_swap*/ 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/ - 0 0>; /*clk vswing_level, preem_level*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -136,9 +134,7 @@ 0 /*pn_swap*/ 0 /*port_swap*/ 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/ - 0 0>; /*clk vswing_level, preem_level*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -180,9 +176,7 @@ 0 /*pn_swap*/ 0 /*port_swap*/ 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/ - 0 0>; /*clk vswing_level, preem_level*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -226,7 +220,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable */ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /* vswing_level, preem_level */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = <0 0 1 50 /*panel power on*/ @@ -268,7 +262,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -312,7 +306,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -356,7 +350,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -402,7 +396,7 @@ vbyone_intr_enable = < 1 /*vbyone_intr_enable*/ 3>; /*vbyone_vsync_intr_enable*/ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -417,10 +411,10 @@ 0xff 0 0 0>; /*ending*/ backlight_index = <2>; }; - p2p{ + p2p_0{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -443,15 +437,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -468,7 +462,7 @@ p2p_1{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -491,15 +485,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -515,7 +509,7 @@ p2p_2{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -538,15 +532,15 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < @@ -562,7 +556,7 @@ p2p_3{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -585,16 +579,105 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi index 52428857a45a..4a6b224c157d 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -240,32 +240,29 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < - 0 0 1 20 /*panel power on*/ - 3 2 0 200 /* extern init voltage */ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; p2p_1{ model_name = "p2p_ceds"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -288,31 +285,29 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < - 0 0 1 20 /*panel power on*/ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; p2p_2{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -335,31 +330,29 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < - 0 0 1 20 /*panel power on*/ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; p2p_3{ model_name = "p2p_chpi"; interface = "p2p"; /*lcd_interface - *(lvds, vbyone, mlvds, p2p) + *(lvds, vbyone, minilvds, p2p) */ basic_setting = < 3840 2160 /*h_active, v_active*/ @@ -382,24 +375,108 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 4 /* teyp: 0=ceds, 1=cspi, 2=cmpi, 3=isp, - * 4=chpi - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ 0 /* pn_swap */ 0>; /* bit_swap */ - phy_attr=<3 0>; /*vswing_level, preem_level*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ /* power step: type, index, value, delay(ms) */ power_on_step = < - 0 0 1 20 /*panel power on*/ 2 0 0 10 /*signal enable*/ 0xff 0 0 0>; /*ending*/ power_off_step = < 2 0 0 10 /*signal disable*/ - 0 0 0 100 /*panel power off*/ 0xff 0 0 0>; /*ending*/ backlight_index = <0xff>; }; diff --git a/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi index 3e9c828df85d..ea0e28527e84 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi @@ -683,10 +683,10 @@ bl_level_attr = <255 10 /*max, min*/ 128 128>; /*mid, mid_mapping*/ bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ - bl_power_attr = <0xff /*en_gpio_index*/ - 1 0 /*on_value, off_value*/ - 200 200>; /* on_delay(ms), off_delay(ms)*/ - bl_ldim_region_row_col = <1 1>; + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; bl_ldim_mode = <1>; /*0=left/right side *1=top/bottom side *2=direct @@ -701,9 +701,9 @@ 128 128>; /*mid, mid_mapping*/ bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ bl_power_attr = <0 /*en_gpio_index*/ - 1 0 /*on_value, off_value*/ - 200 200>; /*on_delay(ms), off_delay(ms)*/ - bl_ldim_region_row_col = <1 10>; + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; bl_ldim_mode = <1>; /*0=left/right side *1=top/bottom side *2=direct diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 906c6c5f8884..36852e1d3f90 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -433,10 +433,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -482,10 +481,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -530,10 +528,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -578,10 +575,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -622,14 +618,14 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -667,14 +663,14 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi index c75c6c7b4df2..2e38f339e816 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -436,10 +436,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -485,10 +484,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -533,10 +531,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -581,10 +578,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -625,14 +621,14 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -670,14 +666,14 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 3 /*clk_ss_level*/ + 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi index 8f0ad5ea1bf0..42191edb6668 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -240,10 +240,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -286,10 +285,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x0 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -332,10 +330,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 6 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -378,10 +375,9 @@ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < - 0x10 /* p2p_teyp: - * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, - * 0x10=chpi, 0x11=cspi, 0x12=usit - */ + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ 12 /* channel_num */ 0x76543210 /* channel_sel0 */ 0xba98 /* channel_sel1 */ @@ -425,9 +421,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ + 0x12304567 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -468,9 +464,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x76543210 /* channel_sel0 */ - 0xba98 /* channel_sel1 */ - 0x660 /* clk_phase */ + 0x45603012 /* channel_sel0 */ + 0x0 /* channel_sel1 */ + 0xaa0 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 22b60474b451..f027f80b9c4d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -513,12 +513,13 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) { #if 1 unsigned int pll_ctrl, pll_ctrl1; - unsigned int tcon_div_table[5][3] = { - {1, 0, 1}, - {0, 0, 1}, - {0, 1, 1}, - {0, 0, 0}, - {0, 1, 0}, + unsigned int tcon_div[5][3] = { + /* div_mux, div2/4_sel, div4_bypass */ + {1, 0, 1}, /* div1 */ + {0, 0, 1}, /* div2 */ + {0, 1, 1}, /* div4 */ + {0, 0, 0}, /* div8 */ + {0, 1, 0}, /* div16 */ }; unsigned int tcon_div_sel = cConf->pll_tcon_div_sel; int ret; @@ -526,15 +527,15 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); pll_ctrl = ((0x3 << 17) | /* gate ctrl */ - (tcon_div_table[tcon_div_sel][2] << 16) | + (tcon_div[tcon_div_sel][2] << 16) | (cConf->pll_n << LCD_PLL_N_TL1) | (cConf->pll_m << LCD_PLL_M_TL1) | (cConf->pll_od3_sel << LCD_PLL_OD3_TL1) | (cConf->pll_od2_sel << LCD_PLL_OD2_TL1) | (cConf->pll_od1_sel << LCD_PLL_OD1_TL1)); pll_ctrl1 = (1 << 28) | - (tcon_div_table[tcon_div_sel][0] << 22) | - (tcon_div_table[tcon_div_sel][1] << 21) | + (tcon_div[tcon_div_sel][0] << 22) | + (tcon_div[tcon_div_sel][1] << 21) | ((1 << 20) | /* sdm_en */ (cConf->pll_frac << 0)); @@ -1192,32 +1193,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) break; case LCD_MLVDS: bit_rate = pconf->lcd_control.mlvds_config->bit_rate / 1000; - for (tcon_div_sel = 1; tcon_div_sel < 3; tcon_div_sel++) { - pll_fvco = bit_rate * tcon_div_table[tcon_div_sel] * 4; - done = check_pll_vco(cConf, pll_fvco); - if (done) { - clk_div_sel = CLK_DIV_SEL_1; - cConf->xd_max = CRT_VID_DIV_MAX; - for (xd = 1; xd <= cConf->xd_max; xd++) { - clk_div_out = cConf->fout * xd; - if (clk_div_out > - cConf->data->div_out_fmax) - continue; - if (lcd_debug_print_flag == 2) { - LCDPR("fout=%d, xd=%d\n", - cConf->fout, xd); - LCDPR("clk_div_out=%d\n", - clk_div_out); - } - done = check_pll_od(cConf, pll_fout); - if (done) - goto generate_clk_done_txl; - } - } - } - break; - case LCD_P2P: - for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + /* must go through div4 for clk phase */ + for (tcon_div_sel = 3; tcon_div_sel < 5; tcon_div_sel++) { pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; done = check_pll_vco(cConf, pll_fvco); if (done == 0) @@ -1236,8 +1213,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) clk_div_sel < CLK_DIV_SEL_MAX; clk_div_sel++) { clk_div_in = clk_vid_pll_div_calc( - clk_div_out, - clk_div_sel, CLK_DIV_O2I); + clk_div_out, clk_div_sel, + CLK_DIV_O2I); if (clk_div_in > cConf->data->div_in_fmax) continue; @@ -1247,13 +1224,11 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) pll_fout = clk_div_in; if (lcd_debug_print_flag == 2) { LCDPR("clk_div_sel=%s(%d)\n", - lcd_clk_div_sel_table[ - clk_div_sel], + lcd_clk_div_sel_table[clk_div_sel], clk_div_sel); - LCDPR("pll_fout=%d\n", - pll_fout); - LCDPR("tcon_div_sel=%d\n", - tcon_div_sel); + LCDPR( + "pll_fout=%d, tcon_div_sel=%d\n", + pll_fout, tcon_div_sel); } done = check_pll_od(cConf, pll_fout); if (done) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 1df55070a175..733378127855 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -606,7 +606,6 @@ static void lcd_reg_print_serializer(char *buf, int offset) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: reg0 = HHI_LVDS_TX_PHY_CNTL0_TL1; reg1 = HHI_LVDS_TX_PHY_CNTL1_TL1; break; @@ -708,6 +707,8 @@ static int lcd_reg_print_lvds(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\nlvds regs:\n"); n = lcd_debug_info_len(len + offset); @@ -725,16 +726,6 @@ static int lcd_reg_print_lvds(char *buf, int offset) len += snprintf((buf+len), n, "LCD_PORT_SWAP [0x%04x] = 0x%08x\n", reg, lcd_vcbus_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_LVDS_TX_PHY_CNTL0; - len += snprintf((buf+len), n, - "LVDS_PHY_CNTL0 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_LVDS_TX_PHY_CNTL1; - len += snprintf((buf+len), n, - "LVDS_PHY_CNTL1 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); return len; } @@ -744,6 +735,8 @@ static int lcd_reg_print_vbyone(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\nvbyone regs:\n"); n = lcd_debug_info_len(len + offset); @@ -788,11 +781,6 @@ static int lcd_reg_print_vbyone(char *buf, int offset) len += snprintf((buf+len), n, "VX1_INTR_STATE [0x%04x] = 0x%08x\n", reg, lcd_vcbus_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_LVDS_TX_PHY_CNTL0; - len += snprintf((buf+len), n, - "VX1_PHY_CNTL0 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); return len; } @@ -883,6 +871,8 @@ static int lcd_reg_print_mlvds(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\nmlvds regs:\n"); @@ -994,6 +984,8 @@ static int lcd_reg_print_p2p(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\np2p regs:\n"); @@ -3630,6 +3622,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) unsigned int data32, vswing, preem, ext_pullup; unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; + if (lcd_drv->data->chip_type == LCD_CHIP_TL1) { + LCDPR("%s: not support yet\n", __func__); + return; + } + pconf = lcd_drv->lcd_config; type = pconf->lcd_basic.lcd_type; switch (type) { @@ -3824,31 +3821,30 @@ static ssize_t lcd_phy_debug_show(struct class *class, preem = pconf->lcd_control.lvds_config->phy_preem; clk_vswing = pconf->lcd_control.lvds_config->phy_clk_vswing; clk_preem = pconf->lcd_control.lvds_config->phy_clk_preem; - len += sprintf(buf+len, "%s:\n", __func__); + len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); - len += sprintf(buf+len, - "clk_vswing=0x%x, clk_preemphasis=0x%x\n", - clk_vswing, clk_preem); + if (lcd_drv->data->chip_type <= LCD_CHIP_TXLX) { + len += sprintf(buf+len, + "clk_vswing=0x%x, clk_preemphasis=0x%x\n", + clk_vswing, clk_preem); + } break; case LCD_VBYONE: vswing = pconf->lcd_control.vbyone_config->phy_vswing; preem = pconf->lcd_control.vbyone_config->phy_preem; - len += sprintf(buf+len, "%s:\n", __func__); len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); break; case LCD_MLVDS: vswing = pconf->lcd_control.mlvds_config->phy_vswing; preem = pconf->lcd_control.mlvds_config->phy_preem; - len += sprintf(buf+len, "%s:\n", __func__); len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); break; case LCD_P2P: vswing = pconf->lcd_control.p2p_config->phy_vswing; preem = pconf->lcd_control.p2p_config->phy_preem; - len += sprintf(buf+len, "%s:\n", __func__); len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 3822445bed76..ec0337a3bcf6 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -594,13 +594,16 @@ static void lcd_lvds_disable(void) lcd_vcbus_setb(LVDS_GEN_CNTL, 0, 3, 1); /* disable lvds fifo */ } -static void lcd_mlvds_clk_util_set(struct lcd_config_s *pconf) +static void lcd_mlvds_control_set(struct lcd_config_s *pconf) { - unsigned int lcd_bits, div_sel; + unsigned int div_sel; + unsigned int channel_sel0, channel_sel1; - lcd_bits = pconf->lcd_basic.lcd_bits; + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); - switch (lcd_bits) { + /* phy_div: 0=div6, 1=div 7, 2=div8, 3=div10 */ + switch (pconf->lcd_basic.lcd_bits) { case 6: div_sel = 0; break; @@ -612,60 +615,24 @@ static void lcd_mlvds_clk_util_set(struct lcd_config_s *pconf) break; } - /* set fifo_clk_sel */ + /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); - /* set cntl_ser_en: 8-channel to 1 */ + /* serializer_en[27:16] */ lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + /* pn swap[2] */ + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 1, 2, 1); - /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, - (1 << 30) | (0 << 25) | (1 << 24)); - /* decoupling fifo write enable after fifo enable */ + /* fifo enable[30], phy_clock gating[24] */ + lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, (1 << 30) | (1 << 24)); + /* fifo write enable[31] */ lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); -} -static void lcd_mlvds_control_set(struct lcd_config_s *pconf) -{ - unsigned int bit_num = 1; - - if (lcd_debug_print_flag) - LCDPR("%s\n", __func__); - - lcd_mlvds_clk_util_set(pconf); - - switch (pconf->lcd_basic.lcd_bits) { - case 10: - bit_num = 0; - break; - case 8: - bit_num = 1; - break; - case 6: - bit_num = 2; - break; - case 4: - bit_num = 3; - break; - default: - bit_num = 1; - break; - } - - lcd_vcbus_write(LVDS_PACK_CNTL_ADDR, - (1 << 0) | // repack //[1:0] - (0 << 3) | // reserve - (0 << 4) | // lsb first - (0 << 5) | // pn swap - (1 << 6) | // dual port - (0 << 7) | // use tcon control - (bit_num << 8) | // 0:10bits, 1:8bits, 2:6bits, 3:4bits. - (0 << 10) | //r_select //0:R, 1:G, 2:B, 3:0 - (1 << 12) | //g_select //0:R, 1:G, 2:B, 3:0 - (2 << 14)); //b_select //0:R, 1:G, 2:B, 3:0; - - lcd_vcbus_write(LVDS_GEN_CNTL, - (lcd_vcbus_read(LVDS_GEN_CNTL) | (1 << 4) | (0x3 << 0))); - lcd_vcbus_setb(LVDS_GEN_CNTL, 1, 3, 1); + /* channel swap default no swap */ + channel_sel0 = pconf->lcd_control.mlvds_config->channel_sel0; + channel_sel1 = pconf->lcd_control.mlvds_config->channel_sel1; + lcd_vcbus_write(LVDS_CH_SWAP0, (channel_sel0 & 0xff)); + lcd_vcbus_write(LVDS_CH_SWAP1, ((channel_sel0 >> 8) & 0xff)); + lcd_vcbus_write(LVDS_CH_SWAP2, (channel_sel1 & 0xff)); lcd_tcon_enable(pconf); } @@ -673,8 +640,6 @@ static void lcd_mlvds_control_set(struct lcd_config_s *pconf) static void lcd_mlvds_disable(void) { lcd_tcon_disable(); - - lcd_vcbus_setb(LVDS_GEN_CNTL, 0, 3, 1); /* disable lvds fifo */ } #if 0 diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index 1c15bbce865a..b692ed4f0454 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -801,6 +801,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, struct device_node *child; struct lvds_config_s *lvdsconf; struct vbyone_config_s *vx1_conf; + struct mlvds_config_s *mlvds_conf; struct p2p_config_s *p2p_conf; child = of_get_child_by_name(dev->of_node, pconf->lcd_propname); @@ -1006,6 +1007,35 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, } } break; + case LCD_MLVDS: + mlvds_conf = pconf->lcd_control.mlvds_config; + ret = of_property_read_u32_array(child, "minilvds_attr", + ¶[0], 6); + if (ret) { + LCDERR("failed to get minilvds_attr\n"); + } else { + mlvds_conf->channel_num = para[0]; + mlvds_conf->channel_sel0 = para[1]; + mlvds_conf->channel_sel1 = para[2]; + mlvds_conf->clk_phase = para[3]; + mlvds_conf->pn_swap = para[4]; + mlvds_conf->bit_swap = para[5]; + } + ret = of_property_read_u32_array(child, "phy_attr", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get phy_attr\n"); + } else { + mlvds_conf->phy_vswing = para[0]; + mlvds_conf->phy_preem = para[1]; + if (lcd_debug_print_flag) { + LCDPR("phy vswing=0x%x, preem=0x%x\n", + mlvds_conf->phy_vswing, + mlvds_conf->phy_preem); + } + } + break; case LCD_P2P: p2p_conf = pconf->lcd_control.p2p_config; ret = of_property_read_u32_array(child, "p2p_attr", @@ -1055,6 +1085,7 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) struct aml_lcd_unifykey_header_s lcd_header; struct lvds_config_s *lvdsconf = pconf->lcd_control.lvds_config; struct vbyone_config_s *vx1_conf = pconf->lcd_control.vbyone_config; + struct mlvds_config_s *mlvds_conf = pconf->lcd_control.mlvds_config; struct p2p_config_s *p2p_conf = pconf->lcd_control.p2p_config; int ret; @@ -1230,6 +1261,27 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; lvdsconf->lane_reverse = 0; } + } else if (pconf->lcd_basic.lcd_type == LCD_MLVDS) { + mlvds_conf->channel_num = (*(p + LCD_UKEY_IF_ATTR_0) | + ((*(p + LCD_UKEY_IF_ATTR_0 + 1)) << 8)) & 0xff; + mlvds_conf->channel_sel0 = (*(p + LCD_UKEY_IF_ATTR_1) | + ((*(p + LCD_UKEY_IF_ATTR_1 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_2) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_2 + 1)) << 24)); + mlvds_conf->channel_sel1 = (*(p + LCD_UKEY_IF_ATTR_3) | + ((*(p + LCD_UKEY_IF_ATTR_3 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_4) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_4 + 1)) << 24)); + mlvds_conf->clk_phase = (*(p + LCD_UKEY_IF_ATTR_5) | + ((*(p + LCD_UKEY_IF_ATTR_5 + 1)) << 8)); + mlvds_conf->pn_swap = (*(p + LCD_UKEY_IF_ATTR_6) | + ((*(p + LCD_UKEY_IF_ATTR_6 + 1)) << 8)) & 0xff; + mlvds_conf->bit_swap = (*(p + LCD_UKEY_IF_ATTR_7) | + ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; + mlvds_conf->phy_vswing = (*(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8)) & 0xff; + mlvds_conf->phy_preem = (*(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8)) & 0xff; } else if (pconf->lcd_basic.lcd_type == LCD_P2P) { p2p_conf->p2p_type = (*(p + LCD_UKEY_IF_ATTR_0) | ((*(p + LCD_UKEY_IF_ATTR_0 + 1)) << 8)); diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 8ac00e499d1e..75493ac3b469 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -116,9 +116,9 @@ static struct vbyone_config_s lcd_vbyone_config = { }; static struct mlvds_config_s lcd_mlvds_config = { - .channel_num = 12, + .channel_num = 6, .channel_sel0 = 0x76543210, - .channel_sel1 = 0xba98, + .channel_sel1 = 0, .clk_phase = 0, .pn_swap = 0, .bit_swap = 0, diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 3f59733aa4c7..03347253355c 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -341,10 +341,12 @@ struct mlvds_config_s { enum p2p_type_e { P2P_CEDS = 0, - P2P_CSPI, P2P_CMPI, P2P_ISP, - P2P_CHPI, + P2P_EPI, + P2P_CHPI = 10, /* low common mode */ + P2P_CSPI, + P2P_USIT, P2P_MAX, }; From 07a8cee21c83f7973bd44f15e33b8853ed22a569 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 25 Dec 2018 13:10:00 +0800 Subject: [PATCH 0615/1060] lcd: update phy config for tl1 [1/1] PD#SWPL-3109 Problem: tl1 tcon phy config need update Solution: 1.update tcon phy config for tl1 2.optimize phy config with independent file Verify: x301 Change-Id: I869cab8fc28fc9d323ca0365fc6eead1c6bc53d7 Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_phy_config.c drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c --- drivers/amlogic/media/vout/lcd/Makefile | 4 +- drivers/amlogic/media/vout/lcd/lcd_common.c | 66 ----- drivers/amlogic/media/vout/lcd/lcd_common.h | 59 +--- drivers/amlogic/media/vout/lcd/lcd_debug.c | 140 ++------- .../amlogic/media/vout/lcd/lcd_phy_config.c | 28 +- .../amlogic/media/vout/lcd/lcd_phy_config.h | 87 ++++++ .../media/vout/lcd/lcd_tablet/lcd_drv.c | 180 ------------ .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 271 ------------------ 8 files changed, 129 insertions(+), 706 deletions(-) create mode 100644 drivers/amlogic/media/vout/lcd/lcd_phy_config.h diff --git a/drivers/amlogic/media/vout/lcd/Makefile b/drivers/amlogic/media/vout/lcd/Makefile index c5dab0196ad2..8b3baf15ebf1 100644 --- a/drivers/amlogic/media/vout/lcd/Makefile +++ b/drivers/amlogic/media/vout/lcd/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_AMLOGIC_LCD) += lcd_vout.o lcd_reg.o lcd_common.o lcd_notify.o \ - lcd_debug.o lcd_clk_config.o lcd_unifykey.o \ - lcd_tcon.o + lcd_debug.o lcd_clk_config.o lcd_phy_config.o \ + lcd_unifykey.o lcd_tcon.o obj-$(CONFIG_AMLOGIC_LCD_TV) += lcd_tv/ obj-$(CONFIG_AMLOGIC_LCD_TABLET) += lcd_tablet/ obj-$(CONFIG_AMLOGIC_LCD_EXTERN) += lcd_extern/ diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index 48d605b2c432..ca87abc9d3b0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -401,72 +401,6 @@ void lcd_tcon_pinmux_set(int status) pconf->pinmux_flag = index; } -unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf) -{ - unsigned int channel_on = 0; - - if (pconf->lcd_control.lvds_config->dual_port == 0) { - if (pconf->lcd_control.lvds_config->lane_reverse == 0) { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0xf; - break; - case 8: - channel_on = 0x1f; - break; - case 10: - default: - channel_on = 0x3f; - break; - } - } else { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0x3c; - break; - case 8: - channel_on = 0x3e; - break; - case 10: - default: - channel_on = 0x3f; - break; - } - } - if (pconf->lcd_control.lvds_config->port_swap == 1) - channel_on = (channel_on << 6); /* use channel B */ - } else { - if (pconf->lcd_control.lvds_config->lane_reverse == 0) { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0x3cf; - break; - case 8: - channel_on = 0x7df; - break; - case 10: - default: - channel_on = 0xfff; - break; - } - } else { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0xf3c; - break; - case 8: - channel_on = 0xfbe; - break; - case 10: - default: - channel_on = 0xfff; - break; - } - } - } - return channel_on; -} - int lcd_power_load_from_dts(struct lcd_config_s *pconf, struct device_node *child) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index cf51a9e23879..55da663315d4 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -34,57 +34,11 @@ /* 20180928: tl1 support, optimize clk config */ /* 20181012: tl1 support tcon */ /* 20181212: tl1 update p2p config and pll setting */ -#define LCD_DRV_VERSION "20181212" +/* 20181225: update phy config */ +#define LCD_DRV_VERSION "20181225" #define VPP_OUT_SATURATE (1 << 0) -/* -------------------------- */ -/* lvsd phy parameters define */ -/* -------------------------- */ -#define LVDS_PHY_CNTL1_G9TV 0x606cca80 -#define LVDS_PHY_CNTL2_G9TV 0x0000006c -#define LVDS_PHY_CNTL3_G9TV 0x00000800 - -#define LVDS_PHY_CNTL1_TL1 0x6c60ca80 -#define LVDS_PHY_CNTL2_TL1 0x00000070 -#define LVDS_PHY_CNTL3_TL1 0x03ff0c00 -/* -------------------------- */ - -/* -------------------------- */ -/* vbyone phy parameters define */ -/* -------------------------- */ -#define VX1_PHY_CNTL1_G9TV 0x6e0ec900 -#define VX1_PHY_CNTL1_G9TV_PULLUP 0x6e0f4d00 -#define VX1_PHY_CNTL2_G9TV 0x0000007c -#define VX1_PHY_CNTL3_G9TV 0x00ff0800 -/* -------------------------- */ - -/* -------------------------- */ -/* minilvds phy parameters define */ -/* -------------------------- */ -#define MLVDS_PHY_CNTL1_TL1 0x6c60ca80 -#define MLVDS_PHY_CNTL2_TL1 0x00000070 -#define MLVDS_PHY_CNTL3_TL1 0x03ff0c00 - - -/* ******** mipi_dsi_phy ******** */ -/* bit[15:11] */ -#define MIPI_PHY_LANE_BIT 11 -#define MIPI_PHY_LANE_WIDTH 5 - -/* MIPI-DSI */ -#define DSI_LANE_0 (1 << 4) -#define DSI_LANE_1 (1 << 3) -#define DSI_LANE_CLK (1 << 2) -#define DSI_LANE_2 (1 << 1) -#define DSI_LANE_3 (1 << 0) -#define DSI_LANE_COUNT_1 (DSI_LANE_CLK | DSI_LANE_0) -#define DSI_LANE_COUNT_2 (DSI_LANE_CLK | DSI_LANE_0 | DSI_LANE_1) -#define DSI_LANE_COUNT_3 (DSI_LANE_CLK | DSI_LANE_0 |\ - DSI_LANE_1 | DSI_LANE_2) -#define DSI_LANE_COUNT_4 (DSI_LANE_CLK | DSI_LANE_0 |\ - DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3) - extern struct mutex lcd_vout_mutex; extern unsigned char lcd_resume_flag; extern int lcd_vout_serve_bypass; @@ -101,7 +55,7 @@ extern unsigned int lcd_cpu_gpio_get(unsigned int index); extern void lcd_ttl_pinmux_set(int status); extern void lcd_vbyone_pinmux_set(int status); extern void lcd_tcon_pinmux_set(int status); -extern unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf); + extern int lcd_power_load_from_dts(struct lcd_config_s *pconf, struct device_node *child); extern int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, @@ -118,6 +72,13 @@ extern void lcd_clk_change(struct lcd_config_s *pconf); extern void lcd_venc_change(struct lcd_config_s *pconf); extern void lcd_if_enable_retry(struct lcd_config_s *pconf); +/* lcd phy */ +extern void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status); + /* lcd tcon */ extern unsigned int lcd_tcon_reg_read(unsigned int addr); extern void lcd_tcon_reg_write(unsigned int addr, unsigned int val); diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 733378127855..63dc64b035fc 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -3617,10 +3617,7 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); struct lcd_config_s *pconf; - struct lvds_config_s *lvdsconf; - int type; - unsigned int data32, vswing, preem, ext_pullup; - unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; + struct lvds_config_s *lvds_conf; if (lcd_drv->data->chip_type == LCD_CHIP_TL1) { LCDPR("%s: not support yet\n", __func__); @@ -3628,55 +3625,29 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) } pconf = lcd_drv->lcd_config; - type = pconf->lcd_basic.lcd_type; - switch (type) { + switch (pconf->lcd_basic.lcd_type) { case LCD_LVDS: - lvdsconf = pconf->lcd_control.lvds_config; + lvds_conf = pconf->lcd_control.lvds_config; if (cnt == 4) { - if ((para[0] > 7) || (para[1] > 7) || - (para[2] > 3) || (para[3] > 7)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preem=%d\n", - para[0], para[1]); - pr_info("clk vswing=%d, preem=%d\n", - para[2], para[3]); - return; - } + lvds_conf->phy_vswing = para[0]; + lvds_conf->phy_preem = para[1]; + lvds_conf->phy_clk_vswing = para[2]; + lvds_conf->phy_clk_preem = para[3]; - lvdsconf->phy_vswing = para[0]; - lvdsconf->phy_preem = para[1]; - lvdsconf->phy_clk_vswing = para[2]; - lvdsconf->phy_clk_preem = para[3]; - - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 26) | (0x7 << 0)); - data32 |= ((para[0] << 26) | (para[1] << 0)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL3); - data32 &= ~((0x3 << 8) | (0x7 << 5)); - data32 |= ((para[2] << 8) | (para[3] << 5)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_lvds_phy_set(pconf, 1); LCDPR("%s:\n", __func__); pr_info("vswing=0x%x, preemphasis=0x%x\n", para[0], para[1]); - pr_info("clk_vswing=0x%x, clk_preem=0x%x\n", + pr_info("clk_vswing=0x%x, clk_preem=0x%x\n", para[2], para[3]); } else if (cnt == 2) { - if ((para[0] > 7) || (para[1] > 7)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preem=%d\n", - para[0], para[1]); - return; - } + lvds_conf->phy_vswing = para[0]; + lvds_conf->phy_preem = para[1]; - lvdsconf->phy_vswing = para[0]; - lvdsconf->phy_preem = para[1]; - - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 26) | (0x7 << 0)); - data32 |= ((para[0] << 26) | (para[1] << 0)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_lvds_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3687,33 +3658,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; case LCD_VBYONE: if (cnt >= 2) { - ext_pullup = (para[0] >> 4) & 0x3; - vswing = para[0] & 0xf; - preem = para[1]; - if ((vswing > 7) || (preem > 7)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preemphasis=%d\n", - vswing, preem); - return; - } - pconf->lcd_control.vbyone_config->phy_vswing = para[0]; pconf->lcd_control.vbyone_config->phy_preem = para[1]; - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 3) | (1 << 10) | - (1 << 15) | (1 << 16)); - data32 |= (vswing << 3); - if (ext_pullup) - data32 |= ((1 << 10) | (1 << 16)); - else - data32 |= (1 << 15); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL2); - data32 &= ~((0x7 << 20) | (0xf << 8)); - data32 |= ((preem << 20) | - (rinner_table[ext_pullup] << 8)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_vbyone_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3724,34 +3673,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; case LCD_MLVDS: if (cnt >= 2) { - if ((para[0] > 7) || (para[1] > 3)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preemphasis=%d\n", - para[0], para[1]); - return; - } - pconf->lcd_control.mlvds_config->phy_vswing = para[0]; pconf->lcd_control.mlvds_config->phy_preem = para[1]; - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 3) | (0x7 << 0) | (0x3 << 23)); - data32 |= ((para[0] << 3) | (para[0] << 0) | - (para[1] << 23)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL2); - data32 &= ~((0x3 << 14) | (0x3 << 12) | - (0x3 << 26) | (0x3 << 24)); - data32 |= ((para[1] << 14) | (para[1] << 12) | - (para[1] << 26) | (para[1] << 24)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL3); - data32 &= ~((0x3 << 6) | (0x3 << 4) | - (0x3 << 2) | (0x3 << 0) | (0x3 << 30)); - data32 |= ((para[1] << 6) | (para[1] << 4) | - (para[1] << 2) | (para[1] << 0) | - (para[1] << 30)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_mlvds_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3762,34 +3688,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; case LCD_P2P: if (cnt >= 2) { - if ((para[0] > 7) || (para[1] > 3)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preemphasis=%d\n", - para[0], para[1]); - return; - } - pconf->lcd_control.p2p_config->phy_vswing = para[0]; pconf->lcd_control.p2p_config->phy_preem = para[1]; - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 3) | (0x7 << 0) | (0x3 << 23)); - data32 |= ((para[0] << 3) | (para[0] << 0) | - (para[1] << 23)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL2); - data32 &= ~((0x3 << 14) | (0x3 << 12) | - (0x3 << 26) | (0x3 << 24)); - data32 |= ((para[1] << 14) | (para[1] << 12) | - (para[1] << 26) | (para[1] << 24)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL3); - data32 &= ~((0x3 << 6) | (0x3 << 4) | - (0x3 << 2) | (0x3 << 0) | (0x3 << 30)); - data32 |= ((para[1] << 6) | (para[1] << 4) | - (para[1] << 2) | (para[1] << 0) | - (para[1] << 30)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_p2p_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3800,7 +3703,8 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; default: LCDERR("%s: not support lcd_type: %s\n", - __func__, lcd_type_type_to_str(type)); + __func__, + lcd_type_type_to_str(pconf->lcd_basic.lcd_type)); break; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c index 93e3042d0d2a..ad9ac39337d1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c @@ -115,7 +115,6 @@ void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / sizeof(unsigned int); if (preem >= size) { @@ -181,7 +180,6 @@ void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) } else { switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); @@ -230,7 +228,6 @@ void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / sizeof(unsigned int); if (preem >= size) { @@ -239,13 +236,8 @@ void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) preem = 0x1; } data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; - if (ext_pullup) { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, - 0xff2027e0 | vswing); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, - 0xf02027a0 | vswing); - } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xf02027a0 | vswing); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); @@ -289,7 +281,6 @@ void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) } else { switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); @@ -318,7 +309,7 @@ void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) { unsigned int vswing, preem; - unsigned int data32, size, cntl16; + unsigned int data32, size; struct mlvds_config_s *mlvds_conf; if (lcd_debug_print_flag) @@ -342,9 +333,7 @@ void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027e0 | vswing); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - cntl16 = (mlvds_conf->pi_clk_sel << 12); - cntl16 |= 0x80000000; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, cntl16); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); @@ -433,10 +422,11 @@ void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) preem = 0x1; } data32 = p2p_low_common_phy_preem_tl1[preem]; - cntl16 = 0x80000000; if (p2p_conf->p2p_type == P2P_CHPI) { - /* weakly pull down */ - data32 &= ~((1 << 19) | (1 << 3)); + /* cntl[30]=1, weakly pull down */ + cntl16 = 0x80000000; + } else { + cntl16 = 0x80000000; } lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xfe60027f); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); @@ -488,7 +478,6 @@ void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) switch (lcd_drv->data->chip_type) { case LCD_CHIP_G12A: case LCD_CHIP_G12B: - case LCD_CHIP_SM1: /* HHI_MIPI_CNTL0 */ /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ lcd_hiu_write(HHI_MIPI_CNTL0, @@ -549,7 +538,6 @@ void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) switch (lcd_drv->data->chip_type) { case LCD_CHIP_G12A: case LCD_CHIP_G12B: - case LCD_CHIP_SM1: lcd_hiu_write(HHI_MIPI_CNTL0, 0); lcd_hiu_write(HHI_MIPI_CNTL1, 0); lcd_hiu_write(HHI_MIPI_CNTL2, 0); diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.h b/drivers/amlogic/media/vout/lcd/lcd_phy_config.h new file mode 100644 index 000000000000..3ed875e5c38b --- /dev/null +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.h @@ -0,0 +1,87 @@ +/* + * drivers/amlogic/media/vout/lcd/lcd_phy_config.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __AML_LCD_PHY_CONFIG_H__ +#define __AML_LCD_PHY_CONFIG_H__ + +/* -------------------------- */ +/* lvsd phy parameters define */ +/* -------------------------- */ +#define LVDS_PHY_CNTL1_G9TV 0x606cca80 +#define LVDS_PHY_CNTL2_G9TV 0x0000006c +#define LVDS_PHY_CNTL3_G9TV 0x00000800 + +#define LVDS_PHY_CNTL1_TXHD 0x6c60ca80 +#define LVDS_PHY_CNTL2_TXHD 0x00000070 +#define LVDS_PHY_CNTL3_TXHD 0x03ff0c00 +/* -------------------------- */ + +/* -------------------------- */ +/* vbyone phy parameters define */ +/* -------------------------- */ +#define VX1_PHY_CNTL1_G9TV 0x6e0ec900 +#define VX1_PHY_CNTL1_G9TV_PULLUP 0x6e0f4d00 +#define VX1_PHY_CNTL2_G9TV 0x0000007c +#define VX1_PHY_CNTL3_G9TV 0x00ff0800 +/* -------------------------- */ + +/* -------------------------- */ +/* minilvds phy parameters define */ +/* -------------------------- */ +#define MLVDS_PHY_CNTL1_TXHD 0x6c60ca80 +#define MLVDS_PHY_CNTL2_TXHD 0x00000070 +#define MLVDS_PHY_CNTL3_TXHD 0x03ff0c00 +/* -------------------------- */ + +/* ******** MIPI_DSI_PHY ******** */ +/* bit[15:11] */ +#define MIPI_PHY_LANE_BIT 11 +#define MIPI_PHY_LANE_WIDTH 5 + +/* MIPI-DSI */ +#define DSI_LANE_0 (1 << 4) +#define DSI_LANE_1 (1 << 3) +#define DSI_LANE_CLK (1 << 2) +#define DSI_LANE_2 (1 << 1) +#define DSI_LANE_3 (1 << 0) +#define DSI_LANE_COUNT_1 (DSI_LANE_CLK | DSI_LANE_0) +#define DSI_LANE_COUNT_2 (DSI_LANE_CLK | DSI_LANE_0 | DSI_LANE_1) +#define DSI_LANE_COUNT_3 (DSI_LANE_CLK | DSI_LANE_0 |\ + DSI_LANE_1 | DSI_LANE_2) +#define DSI_LANE_COUNT_4 (DSI_LANE_CLK | DSI_LANE_0 |\ + DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3) + +static unsigned int lvds_vx1_p2p_phy_preem_tl1[] = { + 0x06020602, + 0x26022602, + 0x46024602, + 0x66026602, + 0x86028602, + 0xa602a602, + 0xf602f602, +}; + +static unsigned int p2p_low_common_phy_preem_tl1[] = { + 0x070b070b, + 0x170b170b, + 0x370b370b, + 0x770b770b, + 0xf70bf70b, + 0xff0bff0b, +}; + +#endif diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index c3442ec380db..7398c8537a97 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -60,186 +60,6 @@ static int lcd_type_supported(struct lcd_config_s *pconf) return ret; } -static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.lvds_config->phy_vswing; - preem = pconf->lcd_control.lvds_config->phy_preem; - clk_vswing = pconf->lcd_control.lvds_config->phy_clk_vswing; - clk_preem = pconf->lcd_control.lvds_config->phy_clk_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - channel_on = lcd_lvds_channel_on_value(pconf); - - if (preem > 7) { - LCDERR("%s: wrong preem=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - if (clk_vswing > 3) { - LCDERR("%s: wrong clk_vswing=%d, use default\n", - __func__, clk_vswing); - clk_vswing = LVDS_PHY_CLK_VSWING_DFT; - } - if (clk_preem > 7) { - LCDERR("%s: wrong clk_preem=%d, use default\n", - __func__, clk_preem); - clk_preem = LVDS_PHY_CLK_PREEM_DFT; - } - - data32 = LVDS_PHY_CNTL1_G9TV | - (vswing << 26) | (preem << 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = LVDS_PHY_CNTL2_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = LVDS_PHY_CNTL3_G9TV | - (channel_on << 16) | - (clk_vswing << 8) | (clk_preem << 5); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem, ext_pullup; - unsigned int data32; - unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - ext_pullup = (pconf->lcd_control.vbyone_config->phy_vswing >> 4) - & 0x3; - vswing = pconf->lcd_control.vbyone_config->phy_vswing & 0xf; - preem = pconf->lcd_control.vbyone_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = VX1_PHY_VSWING_DFT; - } - if (preem > 7) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = VX1_PHY_PREEM_DFT; - } - if (ext_pullup) - data32 = VX1_PHY_CNTL1_G9TV_PULLUP | (vswing << 3); - else - data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | - (rinner_table[ext_pullup] << 8); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = VX1_PHY_CNTL3_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int phy_reg, phy_bit, phy_width; - unsigned int lane_cnt; - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - - if (status) { - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_G12A: - case LCD_CHIP_G12B: - case LCD_CHIP_SM1: - /* HHI_MIPI_CNTL0 */ - /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL0, - (0xa487 << 16) | (0x8 << 0)); - - /* HHI_MIPI_CNTL1 */ - /* DIF_REF_CTL2:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL1, - (0x1 << 16) | (0x002e << 0)); - - /* HHI_MIPI_CNTL2 */ - /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL2, - (0x2680 << 16) | (0x45a << 0)); - break; - default: /* LCD_CHIP_AXG */ - /* HHI_MIPI_CNTL0 */ - /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 0x1b8, 16, 10); - lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 26, 1); /* bandgap */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 29, 1); /* current */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 31, 1); - lcd_hiu_setb(HHI_MIPI_CNTL0, 0x8, 0, 16); - - /* HHI_MIPI_CNTL1 */ - /* DIF_REF_CTL2:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL1, (0x001e << 0)); - - /* HHI_MIPI_CNTL2 */ - /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL2, - (0x26e0 << 16) | (0xfc59 << 0)); - break; - } - - phy_reg = HHI_MIPI_CNTL2; - phy_bit = MIPI_PHY_LANE_BIT; - phy_width = MIPI_PHY_LANE_WIDTH; - switch (pconf->lcd_control.mipi_config->lane_num) { - case 1: - lane_cnt = DSI_LANE_COUNT_1; - break; - case 2: - lane_cnt = DSI_LANE_COUNT_2; - break; - case 3: - lane_cnt = DSI_LANE_COUNT_3; - break; - case 4: - lane_cnt = DSI_LANE_COUNT_4; - break; - default: - lane_cnt = 0; - break; - } - lcd_hiu_setb(phy_reg, lane_cnt, phy_bit, phy_width); - } else { - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_G12A: - case LCD_CHIP_G12B: - case LCD_CHIP_SM1: - lcd_hiu_write(HHI_MIPI_CNTL0, 0); - lcd_hiu_write(HHI_MIPI_CNTL1, 0); - lcd_hiu_write(HHI_MIPI_CNTL2, 0); - break; - default:/* LCD_CHIP_AXG */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 16, 10); - lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 31, 1); - lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 0, 16); - lcd_hiu_write(HHI_MIPI_CNTL1, 0x6); - lcd_hiu_write(HHI_MIPI_CNTL2, 0x00200000); - break; - } - } -} - static void lcd_encl_tcon_set(struct lcd_config_s *pconf) { struct lcd_timing_s *tcon_adr = &pconf->lcd_timing; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index ec0337a3bcf6..4cefe9c73864 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -73,277 +73,6 @@ static int lcd_type_supported(struct lcd_config_s *pconf) return ret; } -static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) -{ - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - unsigned int vswing, preem, ext_pullup; - unsigned int data32; - unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - ext_pullup = (pconf->lcd_control.vbyone_config->phy_vswing >> 4) - & 0x3; - vswing = pconf->lcd_control.vbyone_config->phy_vswing & 0xf; - preem = pconf->lcd_control.vbyone_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = VX1_PHY_VSWING_DFT; - } - if (preem > 7) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = VX1_PHY_PREEM_DFT; - } - - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_TL1: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xf02027af); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x26022602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x26022602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x26022602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x26022602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x26022602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x26022602); - break; - default: - if (ext_pullup) { - data32 = VX1_PHY_CNTL1_G9TV_PULLUP | - (vswing << 3); - } else { - data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); - } - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | - (rinner_table[ext_pullup] << 8); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = VX1_PHY_CNTL3_G9TV; - /*lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x00000a7c);*/ - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - break; - } - } else { - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_TL1: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); - break; - default: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - break; - } - } -} - -static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) -{ - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.lvds_config->phy_vswing; - preem = pconf->lcd_control.lvds_config->phy_preem; - clk_vswing = pconf->lcd_control.lvds_config->phy_clk_vswing; - clk_preem = pconf->lcd_control.lvds_config->phy_clk_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - channel_on = lcd_lvds_channel_on_value(pconf); - - if (preem > 7) { - LCDERR("%s: wrong preem=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - if (clk_vswing > 3) { - LCDERR("%s: wrong clk_vswing=%d, use default\n", - __func__, clk_vswing); - clk_vswing = LVDS_PHY_CLK_VSWING_DFT; - } - if (clk_preem > 7) { - LCDERR("%s: wrong clk_preem=%d, use default\n", - __func__, clk_preem); - clk_preem = LVDS_PHY_CLK_PREEM_DFT; - } - - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_TL1: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027ef); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); - break; - default: - data32 = LVDS_PHY_CNTL1_G9TV | - (vswing << 26) | (preem << 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = LVDS_PHY_CNTL2_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = LVDS_PHY_CNTL3_G9TV | - (channel_on << 16) | - (clk_vswing << 8) | (clk_preem << 5); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - break; - } - } else { - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_TL1: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); - break; - default: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - break; - } - } -} - -static void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.mlvds_config->phy_vswing; - preem = pconf->lcd_control.mlvds_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - if (preem > 3) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - - data32 = MLVDS_PHY_CNTL1_TL1 | - (vswing << 3) | (vswing << 0) | (preem << 23); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = MLVDS_PHY_CNTL2_TL1 | - (preem << 14) | (preem << 12) | - (preem << 26) | (preem << 24); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = MLVDS_PHY_CNTL3_TL1 | - (preem << 6) | (preem << 4) | - (preem << 2) | (preem << 0) | (preem << 30); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) -{ - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027af); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0x06020602); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - switch (pconf->lcd_control.p2p_config->p2p_type) { - case P2P_CHPI: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); - lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 30, 1); - break; - default: - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0x06020602); - break; - } - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0x06020602); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); - } -} - static void lcd_encl_tcon_set(struct lcd_config_s *pconf) { unsigned int lcd_bits; From 10e90d694fe5786f7a9fd204467ce79099151ad9 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Mon, 7 Jan 2019 03:40:44 -0500 Subject: [PATCH 0616/1060] lcd: add tablet mode lvds & vbyone support for tl1 [1/1] PD#TV-2080 Problem: need tablet mode support for tl1 Solution: add tablet mode support for tl1 Verify: x301 Change-Id: Ic7a6ae94255b6152236ab0d991bce9d748d670ac Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c --- drivers/amlogic/media/vout/lcd/lcd_common.h | 3 +- .../media/vout/lcd/lcd_tablet/lcd_drv.c | 56 +++++++++++++------ .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 10 ++-- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 55da663315d4..398a1a408642 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -35,7 +35,8 @@ /* 20181012: tl1 support tcon */ /* 20181212: tl1 update p2p config and pll setting */ /* 20181225: update phy config */ -#define LCD_DRV_VERSION "20181225" +/* 20190108: tl1 support tablet mode */ +#define LCD_DRV_VERSION "20190108" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 7398c8537a97..7d62f25f515b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -232,12 +232,12 @@ static void lcd_ttl_control_set(struct lcd_config_s *pconf) static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int phy_div; unsigned int reg_cntl0, reg_cntl1; switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; break; @@ -253,12 +253,11 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) phy_div = 1; /* set fifo_clk_sel: div 7 */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (1 << 6)); + lcd_hiu_write(reg_cntl0, (1 << 6)); /* set cntl_ser_en: 8-channel to 1 */ lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); switch (lcd_drv->data->chip_type) { /* pn swap */ case LCD_CHIP_TL1: - case LCD_CHIP_TM2: lcd_hiu_setb(reg_cntl0, 1, 2, 1); break; default: @@ -266,18 +265,20 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static void lcd_lvds_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int bit_num = 1; unsigned int pn_swap, port_swap, lane_reverse; unsigned int dual_port, fifo_mode; unsigned int lvds_repack = 1; + unsigned int ch_swap0, ch_swap1, ch_swap2; if (lcd_debug_print_flag) LCDPR("%s\n", __func__); @@ -326,9 +327,12 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: - lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); - lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); + ch_swap0 = 0x3210; + ch_swap1 = 0x7654; + ch_swap2 = 0xba98; + lcd_vcbus_write(LVDS_CH_SWAP0, ch_swap0); + lcd_vcbus_write(LVDS_CH_SWAP1, ch_swap1); + lcd_vcbus_write(LVDS_CH_SWAP2, ch_swap2); break; default: lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); @@ -367,7 +371,6 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; break; @@ -395,12 +398,11 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) break; } /* set fifo_clk_sel */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); + lcd_hiu_write(reg_cntl0, (div_sel << 6)); /* set cntl_ser_en: 8-channel to 1 */ lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); switch (lcd_drv->data->chip_type) { /* pn swap */ case LCD_CHIP_TL1: - case LCD_CHIP_TM2: lcd_hiu_setb(reg_cntl0, 1, 2, 1); break; default: @@ -408,15 +410,16 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, int hsize, int vsize) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int sublane_num; int region_size[4]; int tmp; @@ -480,6 +483,16 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, lcd_vcbus_setb(VBO_CTRL_H, 0x1, 9, 1); /* lcd_vcbus_setb(VBO_CTRL_L,enable,0,1); */ + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); + lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); + lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); + break; + default: + break; + } + return 0; } @@ -520,6 +533,7 @@ static void lcd_vbyone_wait_timing_stable(void) static void lcd_vbyone_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int lane_count, byte_mode, region_num, hsize, vsize, color_fmt; int vin_color, vin_bpp; @@ -602,7 +616,6 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); @@ -626,6 +639,8 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) static void lcd_vbyone_disable(void) { lcd_vcbus_setb(VBO_CTRL_L, 0, 0, 1); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 1); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 0, 1); } static void lcd_tablet_vbyone_wait_stable(void) @@ -640,7 +655,7 @@ static void lcd_tablet_vbyone_wait_stable(void) __func__, lcd_vcbus_read(VBO_STATUS_L), (5000 - i)); } -static void lcd_vx1_wait_hpd(void) +static void lcd_vbyone_wait_hpd(void) { int i = 0; @@ -653,12 +668,17 @@ static void lcd_vx1_wait_hpd(void) udelay(50); } mdelay(10); - if (lcd_vcbus_read(VBO_STATUS_L) & 0x40) + if (lcd_vcbus_read(VBO_STATUS_L) & 0x40) { LCDPR("%s: hpd=%d\n", __func__, ((lcd_vcbus_read(VBO_STATUS_L) >> 6) & 0x1)); - else + } else { LCDPR("%s: hpd=%d, i=%d\n", __func__, ((lcd_vcbus_read(VBO_STATUS_L) >> 6) & 0x1), i); + /* force low only actived for actual hpd is low */ + lcd_vcbus_setb(VBO_INSGN_CTRL, 1, 2, 2); + } + + usleep_range(10000, 10500); /* add 10ms delay for compatibility */ } static unsigned int vbyone_lane_num[] = { @@ -869,7 +889,7 @@ int lcd_tablet_driver_init(void) case LCD_VBYONE: lcd_vbyone_pinmux_set(1); lcd_vbyone_control_set(pconf); - lcd_vx1_wait_hpd(); + lcd_vbyone_wait_hpd(); lcd_vbyone_phy_set(pconf, 1); lcd_tablet_vbyone_wait_stable(); break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 4cefe9c73864..bdf87ca12ee5 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -345,16 +345,16 @@ static void lcd_mlvds_control_set(struct lcd_config_s *pconf) } /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); + lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0_TL1, (div_sel << 6)); /* serializer_en[27:16] */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0_TL1, 0xfff, 16, 12); /* pn swap[2] */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 1, 2, 1); + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0_TL1, 1, 2, 1); /* fifo enable[30], phy_clock gating[24] */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, (1 << 30) | (1 << 24)); + lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1_TL1, (1 << 30) | (1 << 24)); /* fifo write enable[31] */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1_TL1, 1, 31, 1); /* channel swap default no swap */ channel_sel0 = pconf->lcd_control.mlvds_config->channel_sel0; From f36bd33120a3e76e8bc1bbfe5414475f1b7ba404 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 10 Jan 2019 12:56:06 +0800 Subject: [PATCH 0617/1060] lcd: tcon: add chpi bbc init support for tl1 [1/1] PD#SWPL-3739 Problem: need bbc flow to init channel for tcon chpi Solution: add bbc flow support Verify: x301 Change-Id: I15a3e9a85fdf62359768ce8931374f9c730b49d1 Signed-off-by: Evoke Zhang Conflicts: drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c --- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 12 +- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 12 +- .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 12 +- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 12 +- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 12 +- .../amlogic/mesontm2_t962x3_ab309-panel.dtsi | 12 +- .../amlogic/media/vout/lcd/lcd_clk_config.c | 113 ++++-------------- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 3 + drivers/amlogic/media/vout/lcd/lcd_common.h | 3 +- drivers/amlogic/media/vout/lcd/lcd_debug.c | 72 +++++++++-- .../amlogic/media/vout/lcd/lcd_phy_config.c | 13 +- drivers/amlogic/media/vout/lcd/lcd_reg.h | 7 +- .../media/vout/lcd/lcd_tablet/lcd_drv.c | 20 +--- drivers/amlogic/media/vout/lcd/lcd_tcon.c | 72 +++++++++-- .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 64 +++++----- 15 files changed, 234 insertions(+), 205 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 7e87a902df23..4ed977ea70a0 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -623,9 +623,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -668,9 +668,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 309b6138b82b..d3f8d73e3563 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -627,9 +627,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -672,9 +672,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi index 4a6b224c157d..4bf042efe1bc 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -421,9 +421,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -464,9 +464,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 36852e1d3f90..a902618fa296 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -623,9 +623,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -668,9 +668,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 2e38f339e816..9c7fd79eccae 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -626,9 +626,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -671,9 +671,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi index 42191edb6668..6f74572fb3b0 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -421,9 +421,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x12304567 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ @@ -464,9 +464,9 @@ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < 6 /* channel_num */ - 0x45603012 /* channel_sel0 */ - 0x0 /* channel_sel1 */ - 0xaa0 /* clk_phase */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ 0 /* pn_swap */ 0>; /* bit_swap */ phy_attr=<0xf 0>; /* vswing_level, preem_level */ diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index f027f80b9c4d..dddf40625884 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -511,7 +511,6 @@ static void lcd_set_pll_ss_advance_tl1(unsigned int freq, unsigned int mode) static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) { -#if 1 unsigned int pll_ctrl, pll_ctrl1; unsigned int tcon_div[5][3] = { /* div_mux, div2/4_sel, div4_bypass */ @@ -551,101 +550,16 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x000100c0); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, 0x0100c0, 0, 24); udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x008300c0); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, 0x8300c0, 0, 24); udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, 26, 1); udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1); udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); -#else - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - int ret; - switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { - case LCD_LVDS: - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000704ad); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200704ad); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300704ad); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10508000); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - udelay(10); - //lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340704ad); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x142e04ad); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); - udelay(10); - break; - case LCD_VBYONE: - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000f04f7); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200f04f7); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300f04f7); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10110000); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340f04f7); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x140f04f7); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - udelay(10); - break; - case LCD_P2P: - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x000f04e1); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x200604e1); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x300604e1); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL1, 0x10208000); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x340604e1); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL0, 0x14af04e1); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); - udelay(10); - break; - default: - break; - } -#endif ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1); if (ret) { LCDERR("hpll lock failed\n"); @@ -746,11 +660,28 @@ static void lcd_set_dsi_phy_clk(int sel) static void lcd_set_tcon_clk(struct lcd_config_s *pconf) { + unsigned int freq, val; + if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); switch (pconf->lcd_basic.lcd_type) { case LCD_MLVDS: + val = pconf->lcd_control.mlvds_config->clk_phase & 0xfff; + lcd_hiu_setb(HHI_TCON_PLL_CNTL1, (val & 0xf), 24, 4); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, ((val >> 4) & 0xf), 28, 4); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, ((val >> 8) & 0xf), 24, 4); + + /* tcon_clk */ + if (pconf->lcd_timing.lcd_clk >= 100000000) /* 25M */ + freq = 25000000; + else /* 12.5M */ + freq = 12500000; + if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) { + clk_set_rate(lcd_clktree.tcon_clk, freq); + clk_prepare_enable(lcd_clktree.tcon_clk); + } + break; case LCD_P2P: if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) { clk_set_rate(lcd_clktree.tcon_clk, 50000000); @@ -867,6 +798,12 @@ static unsigned int clk_vid_pll_div_calc(unsigned int clk, else clk_ret = clk * 5 / 2; break; + case CLK_DIV_SEL_4p67: + if (dir == CLK_DIV_I2O) + clk_ret = clk * 3 / 14; + else + clk_ret = clk * 14 / 3; + break; default: clk_ret = clk; LCDERR("clk_div_sel: Invalid parameter\n"); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index 041b3b292590..cfbdd410a857 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -410,6 +410,7 @@ static char *lcd_clk_div_sel_table[] = { "14", "15", "2.5", + "4.67", "invalid", }; @@ -432,6 +433,7 @@ enum div_sel_e { CLK_DIV_SEL_14, /* 12 */ CLK_DIV_SEL_15, /* 13 */ CLK_DIV_SEL_2p5, /* 14 */ + CLK_DIV_SEL_4p67, /* 15 */ CLK_DIV_SEL_MAX, }; @@ -452,6 +454,7 @@ static unsigned int lcd_clk_div_table[][3] = { {CLK_DIV_SEL_14, 0x3f80, 1,}, {CLK_DIV_SEL_15, 0x7f80, 2,}, {CLK_DIV_SEL_2p5, 0x5294, 2,}, + {CLK_DIV_SEL_4p67, 0x0ccc, 1,}, {CLK_DIV_SEL_MAX, 0xffff, 0,}, }; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 398a1a408642..419551066a40 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -36,7 +36,8 @@ /* 20181212: tl1 update p2p config and pll setting */ /* 20181225: update phy config */ /* 20190108: tl1 support tablet mode */ -#define LCD_DRV_VERSION "20190108" +/* 20190115: tl1 tcon all interface support */ +#define LCD_DRV_VERSION "20190115" #define VPP_OUT_SATURATE (1 << 0) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 63dc64b035fc..e8d023eabb0b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -428,7 +428,7 @@ static int lcd_info_print_mlvds(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "channel_num %d\n" - "channel_sel1 0x%08x\n" + "channel_sel0 0x%08x\n" "channel_sel1 0x%08x\n" "clk_phase 0x%04x\n" "pn_swap %u\n" @@ -472,7 +472,7 @@ static int lcd_info_print_p2p(char *buf, int offset) len += snprintf((buf+len), n, "p2p_type %d\n" "lane_num %d\n" - "channel_sel1 0x%08x\n" + "channel_sel0 0x%08x\n" "channel_sel1 0x%08x\n" "pn_swap %u\n" "bit_swap %u\n" @@ -971,9 +971,9 @@ static int lcd_reg_print_mlvds(char *buf, int offset) len += snprintf((buf+len), n, "TCON_INTR_MASKN [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); - reg = TCON_INTR; + reg = TCON_INTR_RO; len += snprintf((buf+len), n, - "TCON_INTR [0x%04x] = 0x%08x\n", + "TCON_INTR_RO [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); return len; @@ -1069,9 +1069,9 @@ static int lcd_reg_print_p2p(char *buf, int offset) len += snprintf((buf+len), n, "TCON_INTR_MASKN [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); - reg = TCON_INTR; + reg = TCON_INTR_RO; len += snprintf((buf+len), n, - "TCON_INTR [0x%04x] = 0x%08x\n", + "TCON_INTR_RO [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); return len; @@ -3619,11 +3619,6 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) struct lcd_config_s *pconf; struct lvds_config_s *lvds_conf; - if (lcd_drv->data->chip_type == LCD_CHIP_TL1) { - LCDPR("%s: not support yet\n", __func__); - return; - } - pconf = lcd_drv->lcd_config; switch (pconf->lcd_basic.lcd_type) { case LCD_LVDS: @@ -3891,6 +3886,61 @@ static ssize_t lcd_tcon_debug_store(struct class *class, lcd_tcon_reg_save(parm[2], size); else pr_info("invalid save path\n"); + } else if (strcmp(parm[1], "rb") == 0) { + if (parm[2] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + pr_info("read tcon byte [0x%04x] = 0x%02x\n", + temp, lcd_tcon_read_byte(temp)); + } + } else if (strcmp(parm[1], "wb") == 0) { + if (parm[3] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + ret = kstrtouint(parm[3], 16, &val); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + data = (unsigned char)val; + lcd_tcon_write_byte(temp, data); + pr_info( + "write tcon byte [0x%04x] = 0x%02x, readback 0x%02x\n", + temp, data, lcd_tcon_read_byte(temp)); + } + } else if (strcmp(parm[1], "r") == 0) { + if (parm[2] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + pr_info("read tcon [0x%04x] = 0x%08x\n", + temp, lcd_tcon_read(temp)); + } + } else if (strcmp(parm[1], "w") == 0) { + if (parm[3] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + ret = kstrtouint(parm[3], 16, &val); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + lcd_tcon_write(temp, val); + pr_info( + "write tcon [0x%04x] = 0x%08x, readback 0x%08x\n", + temp, val, lcd_tcon_read(temp)); + } } } else if (strcmp(parm[0], "table") == 0) { if (parm[1] == NULL) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c index ad9ac39337d1..bdc31b171ab5 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c @@ -309,7 +309,7 @@ void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) { unsigned int vswing, preem; - unsigned int data32, size; + unsigned int data32, size, cntl16; struct mlvds_config_s *mlvds_conf; if (lcd_debug_print_flag) @@ -333,7 +333,9 @@ void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027e0 | vswing); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + cntl16 = (mlvds_conf->pi_clk_sel << 12); + cntl16 |= 0x80000000; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, cntl16); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); @@ -422,11 +424,10 @@ void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) preem = 0x1; } data32 = p2p_low_common_phy_preem_tl1[preem]; + cntl16 = 0x80000000; if (p2p_conf->p2p_type == P2P_CHPI) { - /* cntl[30]=1, weakly pull down */ - cntl16 = 0x80000000; - } else { - cntl16 = 0x80000000; + /* weakly pull down */ + data32 &= ~((1 << 19) | (1 << 3)); } lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xfe60027f); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index ab3ee4f03f63..c3ca21e03af1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -981,8 +981,13 @@ #define TCON_GPO_CTRL0 0x2015 #define TCON_GPO_CTRL1 0x2016 #define TCON_GPO_CTRL2 0x2017 +#define TCON_INTR_WR 0x2020 +#define TCON_INTR_CLR 0x2021 #define TCON_INTR_MASKN 0x2022 -#define TCON_INTR 0x2023 /* read only */ +#define TCON_INTR_RO 0x2023 /* read only */ + +#define P2P_CH_SWAP0 0x4200 +#define P2P_CH_SWAP1 0x4201 /* ******************************** * Video post-processing: VPP_VCBUS_BASE = 0x1d diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 7d62f25f515b..16682e91c15f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -278,7 +278,6 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) unsigned int pn_swap, port_swap, lane_reverse; unsigned int dual_port, fifo_mode; unsigned int lvds_repack = 1; - unsigned int ch_swap0, ch_swap1, ch_swap2; if (lcd_debug_print_flag) LCDPR("%s\n", __func__); @@ -327,12 +326,8 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - ch_swap0 = 0x3210; - ch_swap1 = 0x7654; - ch_swap2 = 0xba98; - lcd_vcbus_write(LVDS_CH_SWAP0, ch_swap0); - lcd_vcbus_write(LVDS_CH_SWAP1, ch_swap1); - lcd_vcbus_write(LVDS_CH_SWAP2, ch_swap2); + lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); + lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); break; default: lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); @@ -419,7 +414,6 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, int hsize, int vsize) { - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int sublane_num; int region_size[4]; int tmp; @@ -483,16 +477,6 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, lcd_vcbus_setb(VBO_CTRL_H, 0x1, 9, 1); /* lcd_vcbus_setb(VBO_CTRL_L,enable,0,1); */ - switch (lcd_drv->data->chip_type) { /* pn swap */ - case LCD_CHIP_TL1: - lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); - lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); - lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); - break; - default: - break; - } - return 0; } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index ed6e1f7ca016..c8039f2499f9 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -163,7 +163,7 @@ void lcd_tcon_core_reg_update(void) } } -static int lcd_tcon_top_set_tl1(void) +static int lcd_tcon_top_set_tl1(struct lcd_config_s *pconf) { unsigned int axi_reg[3] = { TCON_AXI_OFST0, TCON_AXI_OFST1, TCON_AXI_OFST2 @@ -188,7 +188,18 @@ static int lcd_tcon_top_set_tl1(void) } lcd_tcon_write(TCON_CLK_CTRL, 0x001f); - lcd_tcon_write(TCON_TOP_CTRL, 0x8999); + if (pconf->lcd_basic.lcd_type == LCD_P2P) { + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: + lcd_tcon_write(TCON_TOP_CTRL, 0x8199); + break; + default: + lcd_tcon_write(TCON_TOP_CTRL, 0x8999); + break; + } + } else { + lcd_tcon_write(TCON_TOP_CTRL, 0x8999); + } lcd_tcon_write(TCON_PLLLOCK_CNTL, 0x0037); lcd_tcon_write(TCON_RST_CTRL, 0x003f); lcd_tcon_write(TCON_RST_CTRL, 0x0000); @@ -198,8 +209,46 @@ static int lcd_tcon_top_set_tl1(void) return 0; } +static void lcd_tcon_chpi_bbc_init_tl1(int delay) +{ + unsigned int data32; + + udelay(delay); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL1, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL1, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL2, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL2, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL3, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL3, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL4, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL4, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL7, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL7, 1, 19, 1); + LCDPR("%s: delay: %dus\n", __func__, delay); + + data32 = 0x06020602; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027ef); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); +} + static int lcd_tcon_enable_tl1(struct lcd_config_s *pconf) { + unsigned int n = 10; int ret; ret = lcd_tcon_valid_check(); @@ -207,16 +256,23 @@ static int lcd_tcon_enable_tl1(struct lcd_config_s *pconf) return -1; /* step 1: tcon top */ - lcd_tcon_top_set_tl1(); + lcd_tcon_top_set_tl1(pconf); /* step 2: tcon_core_reg_update */ lcd_tcon_core_reg_update(); + if (pconf->lcd_basic.lcd_type == LCD_P2P) { + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: + lcd_tcon_chpi_bbc_init_tl1(n); + break; + default: + break; + } + } /* step 3: tcon_top_output_set */ - lcd_tcon_write(TCON_OUT_CH_SEL1, 0xba98); /* out swap for ch8~11 */ - LCDPR("set tcon ch_sel: 0x%08x, 0x%08x\n", - lcd_tcon_read(TCON_OUT_CH_SEL0), - lcd_tcon_read(TCON_OUT_CH_SEL1)); + lcd_tcon_write(TCON_OUT_CH_SEL0, 0x76543210); + lcd_tcon_write(TCON_OUT_CH_SEL1, 0xba98); /* step 4: tcon_intr_mask */ lcd_tcon_write(TCON_INTR_MASKN, TCON_INTR_MASKN_VAL); @@ -232,7 +288,7 @@ static irqreturn_t lcd_tcon_isr(int irq, void *dev_id) if ((lcd_drv->lcd_status & LCD_STATUS_IF_ON) == 0) return IRQ_HANDLED; - temp = lcd_tcon_read(TCON_INTR); + temp = lcd_tcon_read(TCON_INTR_RO); if (temp & 0x2) { LCDPR("%s: tcon sw_reset triggered\n", __func__); lcd_tcon_core_reg_update(); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index bdf87ca12ee5..71c4bc579490 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -252,7 +252,6 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) unsigned int pn_swap, port_swap, lane_reverse; unsigned int dual_port, fifo_mode; unsigned int lvds_repack = 1; - unsigned int ch_swap0, ch_swap1, ch_swap2; if (lcd_debug_print_flag) LCDPR("%s\n", __func__); @@ -301,7 +300,6 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - case LCD_CHIP_TM2: lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); break; @@ -356,12 +354,10 @@ static void lcd_mlvds_control_set(struct lcd_config_s *pconf) /* fifo write enable[31] */ lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1_TL1, 1, 31, 1); - /* channel swap default no swap */ channel_sel0 = pconf->lcd_control.mlvds_config->channel_sel0; channel_sel1 = pconf->lcd_control.mlvds_config->channel_sel1; - lcd_vcbus_write(LVDS_CH_SWAP0, (channel_sel0 & 0xff)); - lcd_vcbus_write(LVDS_CH_SWAP1, ((channel_sel0 >> 8) & 0xff)); - lcd_vcbus_write(LVDS_CH_SWAP2, (channel_sel1 & 0xff)); + lcd_vcbus_write(P2P_CH_SWAP0, channel_sel0); + lcd_vcbus_write(P2P_CH_SWAP1, channel_sel1); lcd_tcon_enable(pconf); } @@ -452,7 +448,6 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, int hsize, int vsize) { - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int sublane_num; int region_size[4]; int tmp; @@ -516,16 +511,6 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, lcd_vcbus_setb(VBO_CTRL_H, 0x1, 9, 1); /* lcd_vcbus_setb(VBO_CTRL_L,enable,0,1); */ - switch (lcd_drv->data->chip_type) { /* pn swap */ - case LCD_CHIP_TL1: - lcd_vcbus_write(LVDS_CH_SWAP0, 0x3210); - lcd_vcbus_write(LVDS_CH_SWAP1, 0x7654); - lcd_vcbus_write(LVDS_CH_SWAP2, 0xba98); - break; - default: - break; - } - return 0; } @@ -1265,12 +1250,10 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) /* fifo write enable[31] */ lcd_hiu_setb(reg_cntl1, 1, 31, 1); - /* channel swap default no swap */ channel_sel0 = pconf->lcd_control.p2p_config->channel_sel0; channel_sel1 = pconf->lcd_control.p2p_config->channel_sel1; - lcd_vcbus_write(LVDS_CH_SWAP0, (channel_sel0 & 0xff)); - lcd_vcbus_write(LVDS_CH_SWAP1, ((channel_sel0 >> 8) & 0xff)); - lcd_vcbus_write(LVDS_CH_SWAP2, (channel_sel1 & 0xff)); + lcd_vcbus_write(P2P_CH_SWAP0, channel_sel0); + lcd_vcbus_write(P2P_CH_SWAP1, channel_sel1); lcd_tcon_enable(pconf); } @@ -1353,7 +1336,7 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) { unsigned int bit_rate, pclk; unsigned int lcd_bits, channel_num; - unsigned int channel_sel0, channel_sel1, pi_clk_sel; + unsigned int channel_sel0, channel_sel1, pi_clk_sel = 0; unsigned int i, temp; if (lcd_debug_print_flag) @@ -1373,27 +1356,30 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) } /* pi_clk select */ - /* mlvds channel: //tx 10 channels - * 0: d0_a - * 1: d1_a - * 2: d2_a - * 3: clk_a - * 4: d0_b - * 5: d1_b - * 6: d2_b - * 7: clk_b - */ channel_sel0 = pconf->lcd_control.mlvds_config->channel_sel0; channel_sel1 = pconf->lcd_control.mlvds_config->channel_sel1; - pi_clk_sel = 0; + /* mlvds channel: //tx 12 channels + * 0: clk_a + * 1: d0_a + * 2: d1_a + * 3: d2_a + * 4: d3_a + * 5: d4_a + * 6: clk_b + * 7: d0_b + * 8: d1_b + * 9: d2_b + * 10: d3_b + * 11: d4_b + */ for (i = 0; i < 8; i++) { temp = (channel_sel0 >> (i*4)) & 0xf; - if ((temp == 3) || (temp == 7)) + if ((temp == 0) || (temp == 6)) pi_clk_sel |= (1 << i); } - for (i = 0; i < 2; i++) { + for (i = 0; i < 4; i++) { temp = (channel_sel1 >> (i*4)) & 0xf; - if ((temp == 3) || (temp == 7)) + if ((temp == 0) || (temp == 6)) pi_clk_sel |= (1 << (i + 8)); } pconf->lcd_control.mlvds_config->pi_clk_sel = pi_clk_sel; @@ -1416,6 +1402,12 @@ static void lcd_p2p_config_set(struct lcd_config_s *pconf) lane_num = pconf->lcd_control.p2p_config->lane_num; pclk = pconf->lcd_timing.lcd_clk / 1000; switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CEDS: + if (pclk >= 600000) + bit_rate = pclk * 3 * lcd_bits / lane_num; + else + bit_rate = pclk * (3 * lcd_bits + 4) / lane_num; + break; case P2P_CHPI: /* 8/10 coding */ bit_rate = (pclk * 3 * lcd_bits * 10 / 8) / lane_num; break; From a615f6903ba85b75dcfdda4a9244ec12a40e30be Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Tue, 22 Jan 2019 18:29:31 +0800 Subject: [PATCH 0618/1060] lcd: optimize tcon_pll for tl1 [1/1] PD#SWPL-3493 Problem: tl1 can imporve tcon_pll performance Solution: 1.update tcon_pll cntl2 register 2.extend ss_level to 12 level Verify: x301 Change-Id: Id10479196529083d2bf5048695a682793a4945ca Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/lcd/lcd_clk_config.c | 4 ++-- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index dddf40625884..bb0f94153ce9 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -546,7 +546,7 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, pll_ctrl1); udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x0000110c); udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); udelay(10); @@ -558,7 +558,7 @@ static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1); udelay(10); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x0000300c); ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1); if (ret) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index cfbdd410a857..49ca5d520273 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -269,6 +269,8 @@ static char *lcd_ss_level_table_tl1[] = { "8, 40000ppm", "9, 45000ppm", "10, 50000ppm", + "11, 55000ppm", + "12, 60000ppm", }; static char *lcd_ss_freq_table_tl1[] = { @@ -315,11 +317,13 @@ static unsigned int pll_ss_reg_tl1[][2] = { {10, 3}, /* 3: +/-0.75% */ {10, 4}, /* 4: +/-1.00% */ {10, 5}, /* 5: +/-1.25% */ - {10, 6}, /* 1: +/-1.50% */ - {10, 7}, /* 2: +/-1.75% */ - {10, 8}, /* 3: +/-2.00% */ - {10, 9}, /* 4: +/-2.25% */ - {10, 10}, /* 5: +/-2.50% */ + {10, 6}, /* 6: +/-1.50% */ + {10, 7}, /* 7: +/-1.75% */ + {10, 8}, /* 8: +/-2.00% */ + {10, 9}, /* 9: +/-2.25% */ + {10, 10}, /* 10: +/-2.50% */ + {11, 10}, /* 11: +/-2.75% */ + {12, 10}, /* 12: +/-3.00% */ }; /* ********************************** From 4c356db442f7a81aa98828d6a805ca155ec2f75c Mon Sep 17 00:00:00 2001 From: Shaochan Liu Date: Tue, 5 Mar 2019 10:58:00 +0800 Subject: [PATCH 0619/1060] lcd: add more panel clk ss step for tl1 [2/2] PD#SWPL-5290 Problem: add more panel clk ss step for tl1 Solution: change 5000ppm to 2000ppm for a step Verify: verify by t962x2-x301 Change-Id: Id8e6795f657cc4edf1fa0411721f741e87a0fcba Signed-off-by: Shaochan Liu Conflicts: drivers/amlogic/media/vout/lcd/lcd_common.h --- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 22 +++--- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 24 +++--- .../boot/dts/amlogic/mesontl1_t309-panel.dtsi | 4 +- .../boot/dts/amlogic/mesontl1_x301-panel.dtsi | 4 +- drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h | 76 ++++++++++++++++--- drivers/amlogic/media/vout/lcd/lcd_common.h | 4 +- 6 files changed, 94 insertions(+), 40 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi index 4ed977ea70a0..61ad4836468c 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -78,7 +78,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 6 /*clk_ss_level*/ + 15 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -163,7 +163,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 6 /*clk_ss_level*/ + 15 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -205,7 +205,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -247,7 +247,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -335,7 +335,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -381,7 +381,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -477,7 +477,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -524,7 +524,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -571,7 +571,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -618,7 +618,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < @@ -663,7 +663,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi index d3f8d73e3563..94e1f33e507c 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -82,7 +82,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 6 /*clk_ss_level*/ + 15 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -167,7 +167,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 6 /*clk_ss_level*/ + 15 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ lvds_attr = < @@ -209,7 +209,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -251,7 +251,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -339,7 +339,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -385,7 +385,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 1 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ vbyone_attr = < @@ -433,7 +433,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -481,7 +481,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -528,7 +528,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -575,7 +575,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ p2p_attr = < @@ -622,7 +622,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < @@ -667,7 +667,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi index a902618fa296..7831799e1bda 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -618,7 +618,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < @@ -663,7 +663,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi index 9c7fd79eccae..31be33cef753 100644 --- a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -621,7 +621,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < @@ -666,7 +666,7 @@ *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, * 4=hdmi_mode) */ - 0 /*clk_ss_level*/ + 3 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 0>; /*pixel_clk(unit in Hz)*/ minilvds_attr = < diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index 49ca5d520273..041d6b65a6ea 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -259,18 +259,36 @@ static char *lcd_ss_level_table_txlx[] = { static char *lcd_ss_level_table_tl1[] = { "0, disable", - "1, 5000ppm", - "2, 10000ppm", - "3, 15000ppm", - "4, 20000ppm", - "5, 25000ppm", - "6, 30000ppm", - "7, 35000ppm", - "8, 40000ppm", - "9, 45000ppm", - "10, 50000ppm", - "11, 55000ppm", - "12, 60000ppm", + "1, 2000ppm", + "2, 4000ppm", + "3, 6000ppm", + "4, 8000ppm", + "5, 10000ppm", + "6, 12000ppm", + "7, 14000ppm", + "8, 16000ppm", + "9, 18000ppm", + "10, 20000ppm", + "11, 22000ppm", + "12, 24000ppm", + "13, 25000ppm", + "14, 28000ppm", + "15, 30000ppm", + "16, 32000ppm", + "17, 33000ppm", + "18, 36000ppm", + "19, 38500ppm", + "20, 40000ppm", + "21, 42000ppm", + "22, 44000ppm", + "23, 45000ppm", + "24, 48000ppm", + "25, 50000ppm", + "26, 50000ppm", + "27, 54000ppm", + "28, 55000ppm", + "29, 55000ppm", + "30, 60000ppm", }; static char *lcd_ss_freq_table_tl1[] = { @@ -311,6 +329,7 @@ static unsigned int pll_ss_reg_txlx[][3] = { static unsigned int pll_ss_reg_tl1[][2] = { /* dep_sel, str_m */ +#if 0 { 0, 0}, /* 0: disable */ {10, 1}, /* 1: +/-0.25% */ {10, 2}, /* 2: +/-0.50% */ @@ -324,6 +343,39 @@ static unsigned int pll_ss_reg_tl1[][2] = { {10, 10}, /* 10: +/-2.50% */ {11, 10}, /* 11: +/-2.75% */ {12, 10}, /* 12: +/-3.00% */ +#else + { 0, 0}, /* 0: disable */ + { 4, 1}, /* 1: +/-0.1% */ + { 4, 2}, /* 2: +/-0.2% */ + { 4, 3}, /* 3: +/-0.3% */ + { 4, 4}, /* 4: +/-0.4% */ + { 4, 5}, /* 5: +/-0.5% */ + { 4, 6}, /* 6: +/-0.6% */ + { 4, 7}, /* 7: +/-0.7% */ + { 4, 8}, /* 8: +/-0.8% */ + { 4, 9}, /* 9: +/-0.9% */ + { 4, 10}, /* 10: +/-1.0% */ + { 11, 4}, /* 11: +/-1.1% */ + { 12, 4}, /* 12: +/-1.2% */ + { 10, 5}, /* 13: +/-1.25% */ + { 8, 7}, /* 14: +/-1.4% */ + { 6, 10}, /* 15: +/-1.5% */ + { 8, 8}, /* 16: +/-1.6% */ + { 11, 6}, /* 17: +/-1.65% */ + { 8, 9}, /* 18: +/-1.8% */ + { 11, 7}, /* 19: +/-1.925% */ + { 10, 8}, /* 20: +/-2.0% */ + { 12, 7}, /* 21: +/-2.1% */ + { 11, 8}, /* 22: +/-2.2% */ + { 9, 10}, /* 23: +/-2.25% */ + { 12, 8}, /* 24: +/-2.4% */ + { 10, 10}, /* 25: +/-2.5% */ + { 10, 10}, /* 26: +/-2.5% */ + { 12, 9}, /* 27: +/-2.7% */ + { 11, 10}, /* 28: +/-2.75% */ + { 11, 10}, /* 29: +/-2.75% */ + { 12, 10}, /* 30: +/-3.0% */ +#endif }; /* ********************************** diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 419551066a40..1c571c1bb148 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -37,7 +37,9 @@ /* 20181225: update phy config */ /* 20190108: tl1 support tablet mode */ /* 20190115: tl1 tcon all interface support */ -#define LCD_DRV_VERSION "20190115" +/* 20190225: optimize unifykey read flow to avoid crash */ +/* 20190308: add more panel clk_ss_level step for tl1 */ +#define LCD_DRV_VERSION "20190308" #define VPP_OUT_SATURATE (1 << 0) From 37512b57520a78738f3b4ff00d553dcfe8b87d09 Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Fri, 8 Mar 2019 13:47:14 +0800 Subject: [PATCH 0620/1060] lcd: add vbyone large vswing support for tl1 [1/1] PD#SWPL-5665 Problem: some vbyone panel need large vswing Solution: add large vswing support for vbyone Verify: x301 Change-Id: I2e0e9ab6a73dab292e104a92b341867ceb5ecdbb Signed-off-by: Evoke Zhang --- drivers/amlogic/media/vout/lcd/lcd_phy_config.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c index bdc31b171ab5..dd307f6ace62 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c @@ -236,8 +236,13 @@ void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) preem = 0x1; } data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, - 0xf02027a0 | vswing); + if (ext_pullup) { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xf02027a0 | vswing); + } lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); From 6e46f0c9925424f4d838549a5037710b36e2c538 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Thu, 16 May 2019 18:27:59 +0900 Subject: [PATCH 0621/1060] ODROID:Merge BSP 2019.04 (fix build err-vout_lcd) Change-Id: I92e6c903fa96763251844080d268bd5e74030ae9 --- .../amlogic/media/vout/lcd/lcd_clk_config.c | 2 - .../amlogic/media/vout/lcd/lcd_tv/lcd_drv.c | 15 +--- drivers/amlogic/media/vout/lcd/lcd_vout.c | 68 ++++--------------- .../linux/amlogic/media/vout/lcd/lcd_vout.h | 4 +- 4 files changed, 18 insertions(+), 71 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index bb0f94153ce9..10200e2549c1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -1129,7 +1129,6 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) } break; case LCD_MLVDS: - bit_rate = pconf->lcd_control.mlvds_config->bit_rate / 1000; /* must go through div4 for clk phase */ for (tcon_div_sel = 3; tcon_div_sel < 5; tcon_div_sel++) { pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; @@ -1175,7 +1174,6 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) } break; case LCD_P2P: - bit_rate = pconf->lcd_control.p2p_config->bit_rate / 1000; for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; done = check_pll_vco(cConf, pll_fvco); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index 71c4bc579490..d72795132f4a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -588,7 +588,6 @@ static void lcd_vbyone_cdr_training_hold(struct vbyone_config_s *vx1_conf, static void lcd_vbyone_control_set(struct lcd_config_s *pconf) { - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int lane_count, byte_mode, region_num, hsize, vsize, color_fmt; int vin_color, vin_bpp; @@ -670,17 +669,7 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_TL1: - lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); - lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); - lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); - lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); - break; - default: - lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); - break; - } + lcd_vbyone_hw_filter(0); lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); @@ -1416,7 +1405,7 @@ static void lcd_p2p_config_set(struct lcd_config_s *pconf) break; } - pconf->lcd_control.p2p_config->bit_rate = bit_rate * 1000; + pconf->lcd_timing.bit_rate = bit_rate * 1000; if (lcd_debug_print_flag) { LCDPR("lane_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 75493ac3b469..b49246bcdf77 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -137,7 +137,6 @@ static struct p2p_config_s lcd_p2p_config = { .bit_swap = 0, .phy_vswing = 0, .phy_preem = 0, - .bit_rate = 0, }; static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff}; @@ -260,7 +259,8 @@ static void lcd_power_ctrl(int status) #ifdef CONFIG_AMLOGIC_LCD_EXTERN struct aml_lcd_extern_driver_s *ext_drv; #endif - unsigned int i, index, value, temp; + unsigned int i, index, wait, temp; + int value = -1; int ret = 0; LCDPR("%s: %d\n", __func__, status); @@ -313,6 +313,19 @@ static void lcd_power_ctrl(int status) break; #endif case LCD_POWER_TYPE_WAIT_GPIO: + index = power_step->index; + lcd_cpu_gpio_set(index, LCD_GPIO_INPUT); + LCDPR("lcd_power_type_wait_gpio wait\n"); + for (wait = 0; wait < power_step->delay; wait++) { + value = lcd_cpu_gpio_get(index); + if (value == power_step->value) { + LCDPR("wait_gpio %d ok\n", value); + break; + } + mdelay(1); + } + if (wait == power_step->delay) + LCDERR("wait_gpio %d timeout!\n", value); break; case LCD_POWER_TYPE_CLK_SS: temp = lcd_driver->lcd_config->lcd_timing.ss_level; @@ -1302,57 +1315,6 @@ static int lcd_config_probe(struct platform_device *pdev) return 0; } -static int lcd_vsync_irq_init(void) -{ - if (lcd_driver->res_vsync_irq) { - if (request_irq(lcd_driver->res_vsync_irq->start, - lcd_vsync_isr, IRQF_SHARED, - "lcd_vsync", (void *)"lcd_vsync")) { - LCDERR("can't request lcd_vsync_irq\n"); - } else { - if (lcd_debug_print_flag) - LCDPR("request lcd_vsync_irq successful\n"); - } - } - - if (lcd_driver->res_vsync2_irq) { - if (request_irq(lcd_driver->res_vsync2_irq->start, - lcd_vsync2_isr, IRQF_SHARED, - "lcd_vsync2", (void *)"lcd_vsync2")) { - LCDERR("can't request lcd_vsync2_irq\n"); - } else { - if (lcd_debug_print_flag) - LCDPR("request lcd_vsync2_irq successful\n"); - } - } - - /* add timer to monitor hpll frequency */ - init_timer(&lcd_vsync_none_timer); - /* lcd_vsync_none_timer.data = NULL; */ - lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler; - lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL; - /*add_timer(&lcd_vsync_none_timer);*/ - /*LCDPR("add lcd_vsync_none_timer handler\n"); */ - - return 0; -} - -static void lcd_vsync_irq_remove(void) -{ - if (lcd_driver->res_vsync_irq) - free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync"); - - if (lcd_driver->res_vsync2_irq) { - free_irq(lcd_driver->res_vsync2_irq->start, - (void *)"lcd_vsync"); - } - - if (lcd_driver->vsync_none_timer_flag) { - del_timer_sync(&lcd_vsync_none_timer); - lcd_driver->vsync_none_timer_flag = 0; - } -} - #ifdef CONFIG_OF static struct lcd_data_s lcd_data_gxl = { diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 03347253355c..60fc89d65e7a 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -344,7 +344,7 @@ enum p2p_type_e { P2P_CMPI, P2P_ISP, P2P_EPI, - P2P_CHPI = 10, /* low common mode */ + P2P_CHPI = 0x10, /* low common mode */ P2P_CSPI, P2P_USIT, P2P_MAX, @@ -359,8 +359,6 @@ struct p2p_config_s { unsigned int bit_swap; /* MSB/LSB reverse */ unsigned int phy_vswing; unsigned int phy_preem; - /* internal used */ - unsigned int bit_rate; /* Hz */ }; struct lcd_control_config_s { From cd3580450b160721b1d48504043e9ac17415d695 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Tue, 30 Oct 2018 19:33:47 +0800 Subject: [PATCH 0622/1060] sdio: optimize sd & wifi TDMA [1/1] PD#SWPL-1908 Problem: sdio wifi error TDMA. Solution: optimize host reg value set error. Verify: u211 & u212 Change-Id: I0e0d52ac2bce42cf163f0065d46badc938832a65 Signed-off-by: Nan Li Conflicts: drivers/amlogic/mmc/aml_sd_emmc.c drivers/amlogic/mmc/aml_sd_emmc_v3.c drivers/amlogic/mmc/amlsd_of.c include/linux/amlogic/sd.h --- drivers/amlogic/mmc/aml_sd_emmc.c | 1 + drivers/amlogic/mmc/aml_sd_emmc_v3.c | 15 ++++----------- drivers/amlogic/mmc/amlsd_of.c | 2 -- include/linux/amlogic/sd.h | 8 +++----- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 5a11b761ff5a..2f5e2a48c9d7 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -1917,6 +1917,7 @@ static void aml_sd_emmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } pdata->irq_sdio_sleep = 1; } + pdata->irq_sdio_sleep = 1; spin_unlock_irqrestore(&host->mrq_lock, flags); diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index c00fcb4b3853..723a20e83009 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -284,12 +284,10 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, /* (re)start clock, if non-zero */ if (clk_ios) { - if (pdata->calc_f) { - vclkc = readl(host->base + SD_EMMC_CLOCK_V3); - pdata->clk_lay.source - = clk_get_rate(host->cfg_div_clk) * clkc->div; - pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); - } + vclkc = readl(host->base + SD_EMMC_CLOCK_V3); + pdata->clk_lay.source + = clk_get_rate(host->cfg_div_clk) * clkc->div; + pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); vcfg = readl(host->base + SD_EMMC_CFG); conf->stop_clk = 0; @@ -392,11 +390,6 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->tx_phase = para->sdr104.tx_phase; } else { ctrl->ddr = 0; - clkc->tx_delay = 0; - clkc->core_phase = para->init.core_phase; - clkc->tx_phase = para->init.tx_phase; - irq_en &= ~(1<<17); - writel(irq_en, host->base + SD_EMMC_IRQ_EN); /* timing == MMC_TIMING_LEGACY */ if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; diff --git a/drivers/amlogic/mmc/amlsd_of.c b/drivers/amlogic/mmc/amlsd_of.c index a117ef59ee0f..fc093edddbb5 100644 --- a/drivers/amlogic/mmc/amlsd_of.c +++ b/drivers/amlogic/mmc/amlsd_of.c @@ -187,8 +187,6 @@ int amlsd_get_platform_data(struct platform_device *pdev, str, pdata->gpio_power); SD_PARSE_U32_PROP_DEC(child, "calc_f", prop, pdata->calc_f); - SD_PARSE_U32_PROP_DEC(child, "no_sduart", - prop, pdata->no_sduart); SD_PARSE_U32_PROP_DEC(child, "gpio_cd_level", prop, pdata->gpio_cd_level); diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 9cdf7151807c..c43069e7ef3c 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -282,7 +282,6 @@ struct amlsd_platform { unsigned int dly1; unsigned int dly2; unsigned int intf3; - unsigned int win_start; unsigned int irq_sdio_sleep; unsigned int clock; /* signalling voltage (1.8V or 3.3V) */ @@ -301,7 +300,6 @@ struct amlsd_platform { unsigned int gpio_power; unsigned int power_level; unsigned int calc_f; - unsigned int no_sduart; unsigned int auto_clk_close; unsigned int vol_switch; @@ -1545,7 +1543,7 @@ struct sd_emmc_config { /*[18] Spare, ??? need check*/ u32 spare:1; /*[19] Use this descriptor - *even if its owner bit is ???0???бь?ии. + *even if its owner bit is ???0???б??ии. */ u32 ignore_owner:1; /*[20] Check data strobe in HS400.*/ @@ -1578,7 +1576,7 @@ struct sd_emmc_status { *any one of blocks CRC error. */ u32 txd_err:1; - /*[9] SD/eMMC controller doesn???и║?ииt own descriptor. + /*[9] SD/eMMC controller doesn???и??ииt own descriptor. *The owner bit is set cfg_ignore_owner to ignore this error. */ u32 desc_err:1; @@ -1622,7 +1620,7 @@ struct sd_emmc_irq_en { u32 rxd_err:8; /*[8] TX data CRC error. */ u32 txd_err:1; - /*[9] SD/eMMC controller doesn???и║?ииt own descriptor. */ + /*[9] SD/eMMC controller doesn???и??ииt own descriptor. */ u32 desc_err:1; /*[10] Response CRC error.*/ u32 resp_err:1; From f5c42df116f60ede5fae189e18731cae9543fe37 Mon Sep 17 00:00:00 2001 From: Ruixuan Li Date: Mon, 26 Nov 2018 20:53:39 +0800 Subject: [PATCH 0623/1060] emmc: modify cophase for tl1 [1/1] PD#172587 Problem: emmc data crc error Solution: modify cophase under kernel for tl1 Verify: test pass on skt Change-Id: Id4997ef2288a53e6f401744664aaf6b05cf36e38 Signed-off-by: Ruixuan Li Conflicts: arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 28 ------------------- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 18 ++++++++++++ drivers/amlogic/mmc/aml_sd_emmc.c | 2 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 18 ++++++++++-- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 94ff98893b71..8c23c7170502 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -1443,34 +1443,6 @@ }; }; /* end of pinctrl_aobus */ -&audio_data{ - status = "okay"; -}; - -&i2c2 { - status = "okay"; - pinctrl-names="default"; - pinctrl-0=<&i2c2_z_pins>; - clock-frequency = <400000>; - - tas5805: tas5805@36 { - compatible = "ti,tas5805"; - #sound-dai-cells = <0>; - codec_name = "tas5805"; - reg = <0x2d>; - status = "disable"; - }; - - ad82584f: ad82584f@62 { - compatible = "ESMT, ad82584f"; - #sound-dai-cells = <0>; - reg = <0x31>; - status = "okay"; - reset_pin = <&gpio_ao GPIOAO_6 0>; - }; - -}; - &sd_emmc_c { status = "okay"; emmc { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 5951680f5336..d7b961dc9d2a 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1529,6 +1529,24 @@ }; }; +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + &sd_emmc_b { status = "okay"; sd { diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 2f5e2a48c9d7..170120d8b21f 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -3648,7 +3648,7 @@ static struct meson_mmc_data mmc_data_tl1 = { .sdmmc.init.core_phase = 3, .sdmmc.init.tx_phase = 0, .sdmmc.init.rx_phase = 0, - .sdmmc.hs.core_phase = 1, + .sdmmc.hs.core_phase = 3, .sdmmc.ddr.core_phase = 2, .sdmmc.hs2.core_phase = 2, .sdmmc.hs4.tx_delay = 0, diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 723a20e83009..2a73765f7981 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -116,6 +116,7 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host) u32 vconf = 0; struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf; struct mmc_phase *init = &(host->data->sdmmc.init); + struct mmc_phase *calc = &(host->data->sdmmc.calc); writel(0, host->base + SD_EMMC_ADJUST_V3); writel(0, host->base + SD_EMMC_DELAY1_V3); @@ -133,6 +134,11 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host) pclkc->core_phase = init->core_phase; /* 2: 180 phase */ pclkc->rx_phase = init->rx_phase; pclkc->tx_phase = init->tx_phase; + if ((host->data->chip_type >= MMC_CHIP_G12A) + && (host->data->chip_type != MMC_CHIP_TL1)) { + pclkc->core_phase = calc->core_phase; + pclkc->tx_phase = calc->tx_phase; + } pclkc->always_on = 1; /* Keep clock always on */ writel(vclkc, host->base + SD_EMMC_CLOCK_V3); @@ -369,7 +375,9 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, /* overide co-phase by dts */ if (pdata->co_phase) clkc->core_phase = pdata->co_phase; - if (pdata->calc_f) { + if ((pdata->calc_f) + && ((host->data->chip_type >= MMC_CHIP_G12A) + && (host->data->chip_type != MMC_CHIP_TL1))) { clkc->core_phase = para->calc.core_phase; clkc->tx_phase = para->calc.tx_phase; } @@ -381,7 +389,9 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, || (host->data->chip_type == MMC_CHIP_TXLX) || (host->data->chip_type == MMC_CHIP_G12A)) clkc->core_phase = para->sd_hs.core_phase; - if (pdata->calc_f) { + if ((pdata->calc_f) + && ((host->data->chip_type >= MMC_CHIP_G12A) + && (host->data->chip_type != MMC_CHIP_TL1))) { clkc->core_phase = para->calc.core_phase; clkc->tx_phase = para->calc.tx_phase; } @@ -397,7 +407,9 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, } } - if (pdata->calc_f) { + if ((pdata->calc_f) + && ((host->data->chip_type >= MMC_CHIP_G12A) + && (host->data->chip_type != MMC_CHIP_TL1))) { if (timing <= MMC_TIMING_SD_HS) { ret = aml_fixdiv_calc(&fixdiv, &pdata->clk_lay); if (!ret) { From 2fdbf349bdab495dd2a33ebd44c02b24acc252b9 Mon Sep 17 00:00:00 2001 From: Ruixuan Li Date: Mon, 26 Nov 2018 15:16:55 +0800 Subject: [PATCH 0624/1060] arm: dts: tl1: config device on portB with dts [1/1] PD#172587 Problem: configuration for portB in dtsi can not support the sdcard and sdio at same time. Solution: move the device configuration into dts. SKT->SDCARD REF->SDIO Verify: test pass on tl1 skt and ref board Signed-off-by: Ruixuan Li Change-Id: I6d1da7a8d0d8d901c4a40a74f04973c155188ade Conflicts: arch/arm/boot/dts/amlogic/tl1_pxp.dts arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts drivers/amlogic/mmc/amlsd.c --- arch/arm/boot/dts/amlogic/tl1_pxp.dts | 2 - arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 26 +-------- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 56 +++++++++++++++---- drivers/amlogic/mmc/amlsd.c | 7 ++- 4 files changed, 50 insertions(+), 41 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index 6506f548685a..15bf6a776194 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -599,7 +599,6 @@ f_min = <400000>; f_max = <200000000>; max_req_size = <0x20000>; /**128KB*/ - no_sduart = <1>; gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; @@ -609,7 +608,6 @@ */ }; }; - }; /* end of / */ &audiobus { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 8c23c7170502..9bbe37348fff 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -1016,14 +1016,7 @@ tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ }; - bt-dev{ - compatible = "amlogic, bt-dev"; - status = "okay"; - gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; - }; - - wifi{ - compatible = "amlogic, aml_wifi"; + sd_emmc_b: sd@ffe05000 { status = "okay"; compatible = "amlogic, meson-mmc-tl1"; reg = <0xffe05000 0x800>; @@ -1058,7 +1051,6 @@ f_min = <400000>; f_max = <200000000>; max_req_size = <0x20000>; /**128KB*/ - no_sduart = <1>; gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; @@ -1461,18 +1453,6 @@ }; }; -&sd_emmc_b { - status = "okay"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE"; /**ptm debug */ - f_min = <400000>; - f_max = <200000000>; - }; -}; - &spifc { status = "disabled"; spi-nor@0 { @@ -1633,10 +1613,6 @@ }; }; -&pwm_ab { - status = "okay"; -}; - &efuse { status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index d7b961dc9d2a..f2623c53ddeb 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1096,6 +1096,51 @@ }; }; + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; }; /* end of / */ &i2c0 { @@ -1547,17 +1592,6 @@ }; }; -&sd_emmc_b { - status = "okay"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE"; /**ptm debug */ - f_min = <400000>; - f_max = <200000000>; - }; -}; &spifc { status = "disabled"; diff --git a/drivers/amlogic/mmc/amlsd.c b/drivers/amlogic/mmc/amlsd.c index 3b9100677659..14b24fb62507 100644 --- a/drivers/amlogic/mmc/amlsd.c +++ b/drivers/amlogic/mmc/amlsd.c @@ -861,7 +861,8 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) return 1; pdata->is_in = true; pdata->gpio_cd_sta = true; - if (aml_is_sduart(pdata)) { + if ((host->data->chip_type < MMC_CHIP_TL1) + && aml_is_sduart(pdata)) { aml_uart_switch(pdata, 1); pr_info("Uart in\n"); mmc->caps &= ~MMC_CAP_4_BIT_DATA; @@ -876,7 +877,7 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) } } else { pr_info("normal card in\n"); - if (!pdata->no_sduart) { + if (host->data->chip_type < MMC_CHIP_TL1) { aml_uart_switch(pdata, 0); aml_jtag_switch_ao(pdata); } @@ -901,7 +902,7 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) host->is_sduart = 0; if (mmc && mmc->card) mmc_card_set_removed(mmc->card); - if (!pdata->no_sduart) { + if (host->data->chip_type < MMC_CHIP_TL1) { aml_uart_switch(pdata, 0); aml_jtag_switch_ao(pdata); } From 715f14bd5039e67f71bc5bd1778e83996754466e Mon Sep 17 00:00:00 2001 From: Long Yu Date: Fri, 14 Dec 2018 17:13:36 +0800 Subject: [PATCH 0625/1060] storage: emmc: Add HS400 busmode support for TL1 [1/1] PD#SWPL-2311 Problem: not support HS400 busmode Solution: add HS400 busmode support for TL1 Verify: TL1-T962X2_X301 Change-Id: I95ac19e9c0c5b84c9225602cda6964aaaee4151e Signed-off-by: Long Yu Conflicts: arch/arm/boot/dts/amlogic/mesontm2.dtsi arch/arm64/boot/dts/amlogic/mesontm2.dtsi arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts drivers/amlogic/mmc/aml_sd_emmc_v3.c --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 5 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 5 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 5 +- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 5 +- drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c | 2 +- drivers/amlogic/mmc/aml_sd_emmc.c | 5 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 115 +++++++++++------- drivers/mmc/core/mmc.c | 9 +- include/linux/amlogic/sd.h | 1 + 9 files changed, 95 insertions(+), 57 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 71a34fac554b..fe76232097df 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1263,9 +1263,10 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV2P5>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_GP0_PLL>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index f2623c53ddeb..40e05554ac88 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1567,10 +1567,9 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; - f_max = <200000000>; + f_max = <198000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index c04adf1ac279..6796136e6520 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1245,9 +1245,10 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV2P5>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_GP0_PLL>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 52aaa1423871..b7b0e565b7b3 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -1719,10 +1719,9 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; - f_max = <200000000>; + f_max = <198000000>; }; }; diff --git a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c index 37c37402f025..b5479b615f49 100644 --- a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c +++ b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c @@ -27,7 +27,7 @@ #include "tl1.h" PNAME(sd_emmc_parent_names) = { "xtal", "fclk_div2", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0" }; + "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0_pll" }; /*sd_emmc B*/ static MUX(sd_emmc_p0_mux_B, HHI_SD_EMMC_CLK_CNTL, 0x7, 25, sd_emmc_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED); diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 170120d8b21f..beb76d967503 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -2619,7 +2619,7 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) mmc_hostname(host->mmc), vstat, virqc); host->status = HOST_RSP_CRC_ERR; - mrq->cmd->error = -EILSEQ; + mrq->cmd->error = -EBADMSG; } else if (ista->resp_timeout) { if (host->is_tunning == 0) pr_err("%s: resp_timeout,vstat:0x%x,virqc:%x\n", @@ -3651,7 +3651,8 @@ static struct meson_mmc_data mmc_data_tl1 = { .sdmmc.hs.core_phase = 3, .sdmmc.ddr.core_phase = 2, .sdmmc.hs2.core_phase = 2, - .sdmmc.hs4.tx_delay = 0, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, }; diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index 2a73765f7981..a72089fc325a 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -247,20 +247,14 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, host->mux_parent[0]); if (ret) pr_warn("set comp0 as mux_clk parent error\n"); - } else if (((host->data->chip_type == MMC_CHIP_TL1) - || (host->data->chip_type == MMC_CHIP_G12B)) + } else if ((host->data->chip_type == MMC_CHIP_TL1) && (clk_ios >= 166000000)) { - src0_clk = devm_clk_get(host->dev, "clkin2"); + src0_clk = devm_clk_get(host->dev, "clkin3"); if (ret) - pr_warn("not get clkin2\n"); - if ((host->data->chip_type == MMC_CHIP_TL1) - && (clk_ios <= 198000000)) { - ret = clk_set_rate(src0_clk, 792000000); - if (ret) - pr_warn("not set tl1-gp0\n"); - } - pr_warn("set rate clkin2>>>>>>>>clk:%lu\n", - clk_get_rate(src0_clk)); + pr_warn("not get GP0\n"); + ret = clk_set_rate(src0_clk, 792000000); + pr_warn("set rate gp0>>>>>>>>>clk:%lu\n", + clk_get_rate(src0_clk)); ret = clk_set_parent(host->mux_parent[0], src0_clk); if (ret) @@ -306,7 +300,7 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, mmc->actual_clock, readl(host->clksrc_base + (HHI_NAND_CLK_CNTL << 2))); - pr_info("[%s] after clock: 0x%x\n", + pr_debug("[%s] after clock: 0x%x\n", __func__, readl(host->base + SD_EMMC_CLOCK_V3)); return ret; @@ -325,11 +319,21 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, u8 clk_div = 0; struct para_e *para = &(host->data->sdmmc); unsigned int fixdiv = 0, ret = 0; + u32 irq_en = readl(host->base + SD_EMMC_IRQ_EN); vctrl = readl(host->base + SD_EMMC_CFG); if ((timing == MMC_TIMING_MMC_HS400) || (timing == MMC_TIMING_MMC_DDR52) || (timing == MMC_TIMING_UHS_DDR50)) { + + if (timing == MMC_TIMING_MMC_DDR52) { + if (aml_card_type_mmc(pdata)) { + clkc->core_phase = para->ddr.core_phase; + clkc->tx_phase = para->ddr.tx_phase; + } + pr_info("%s: try set sd/emmc to DDR mode\n", + mmc_hostname(host->mmc)); + } if (timing == MMC_TIMING_MMC_HS400) { /*ctrl->chk_ds = 1;*/ if (host->data->chip_type >= MMC_CHIP_TXLX) { @@ -344,8 +348,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, if (pdata->tx_delay != 0) clkc->tx_delay = pdata->tx_delay; - if (((host->data->chip_type == MMC_CHIP_TL1) - || (host->data->chip_type == MMC_CHIP_G12B)) + if ((host->data->chip_type == MMC_CHIP_TL1) && aml_card_type_mmc(pdata)) { clkc->core_phase = para->hs4.core_phase; clkc->tx_phase = para->hs4.tx_phase; @@ -364,12 +367,6 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, if (clk_div & 0x01) clk_div++; clkc->div = clk_div / 2; - if (aml_card_type_mmc(pdata)) { - clkc->core_phase = para->ddr.core_phase; - clkc->tx_phase = para->ddr.tx_phase; - } - pr_info("%s: try set sd/emmc to DDR mode\n", - mmc_hostname(host->mmc)); } else if (timing == MMC_TIMING_MMC_HS) { clkc->core_phase = para->hs.core_phase; /* overide co-phase by dts */ @@ -734,7 +731,7 @@ static int emmc_send_cmd(struct mmc_host *mmc, u32 opcode, err = mmc_wait_for_cmd(mmc, &cmd, 3); if (err) { - pr_info("[%s][%d] cmd:0x%x send error\n", + pr_debug("[%s][%d] cmd:0x%x send error\n", __func__, __LINE__, cmd.opcode); return err; } @@ -822,9 +819,10 @@ RETRY: eyetest_out1 = readl(host->base + SD_EMMC_EYETEST_OUT1); gintf3->eyetest_on = 0; writel(intf3, host->base + SD_EMMC_INTF3); + writel(0, host->base + SD_EMMC_ADJUST_V3); pdata->intf3 = intf3; pdata->align[line_x] = ((tmp | eyetest_out1) << 32) | eyetest_out0; - pr_debug("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", + pr_info("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", readl(host->base + SD_EMMC_DELAY1_V3), readl(host->base + SD_EMMC_DELAY2_V3), pdata->align[line_x], line_x); @@ -949,6 +947,25 @@ static void update_all_line_eyetest(struct mmc_host *mmc) } } +static unsigned int tl1_emmc_line_timing(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay1 = 0, delay2 = 0, count = 12; + + delay1 = (count<<0)|(count<<6)|(count<<12) + |(count<<18)|(count<<24); + delay2 = (count<<0)|(count<<6)|(count<<12) + |(pdata->cmd_c<<24); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("[%s], delay1: 0x%x, delay2: 0x%x\n", + __func__, readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + return 0; + +} + static unsigned int get_emmc_cmd_win(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); @@ -1067,21 +1084,18 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) u32 intf3 = readl(host->base + SD_EMMC_INTF3); struct intf3 *gintf3 = (struct intf3 *)&(intf3); int i, err = 0; - int match[32]; + int match[64]; int best_start = -1, best_size = -1; int cur_start = -1, cur_size = 0; - sd_emmc_debug = 0x2000; - update_all_line_eyetest(mmc); - emmc_ds_core_align(mmc); - update_all_line_eyetest(mmc); - emmc_all_data_line_alignment(mmc); - update_all_line_eyetest(mmc); - emmc_ds_data_alignment(mmc); - update_all_line_eyetest(mmc); host->is_tunning = 1; for (i = 0; i < 64; i++) { - err = emmc_test_bus(mmc); + gintf3->ds_sht_m += 1; + writel(intf3, host->base + SD_EMMC_INTF3); + pdata->intf3 = intf3; + err = aml_sd_emmc_cali_v3(mmc, + MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 20); pr_debug("intf3: 0x%x, err[%d]: %d\n", readl(host->base + SD_EMMC_INTF3), i, err); if (!err) @@ -1092,7 +1106,7 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) writel(intf3, host->base + SD_EMMC_INTF3); pdata->intf3 = intf3; } - for (i = 0; i < 32; i++) { + for (i = 0; i < 64; i++) { if (match[i] == 0) { if (cur_start < 0) cur_start = i; @@ -1133,11 +1147,31 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) gintf3->ds_sht_m, best_size, readl(host->base + SD_EMMC_INTF3), readl(host->base + SD_EMMC_CLOCK_V3)); + pr_info("adjust:0x%x\n", readl(host->base + SD_EMMC_ADJUST_V3)); host->is_tunning = 0; return 0; } #endif +static void aml_emmc_hs400_general(struct mmc_host *mmc) +{ + + update_all_line_eyetest(mmc); + emmc_ds_core_align(mmc); + update_all_line_eyetest(mmc); + emmc_all_data_line_alignment(mmc); + update_all_line_eyetest(mmc); + emmc_ds_data_alignment(mmc); + update_all_line_eyetest(mmc); + emmc_ds_manual_sht(mmc); +} + +static void aml_emmc_hs400_tl1(struct mmc_host *mmc) +{ + + tl1_emmc_line_timing(mmc); + emmc_ds_manual_sht(mmc); +} static int emmc_data_alignment(struct mmc_host *mmc, int best_size) { @@ -1560,7 +1594,6 @@ int aml_emmc_hs200_tl1(struct mmc_host *mmc) int i, err = 0; clk_bak = vclkc; - clkc->tx_phase = para->hs4.tx_phase; clkc->core_phase = para->hs4.core_phase; clkc->tx_delay = para->hs4.tx_delay; if (pdata->tx_delay != 0) @@ -1576,14 +1609,12 @@ int aml_emmc_hs200_tl1(struct mmc_host *mmc) continue; count = fbinary(pdata->align[9]); if (((count >= 10) && (count <= 22)) - || ((count >= 45) && (count <= 56))) + || ((count >= 43) && (count <= 56))) break; } if (i == 63) pr_err("[%s]no find cmd timing\n", __func__); pdata->cmd_c = (delay2 >> 24); - pr_info("cmd->u64eyet:0x%016llx\n", - pdata->align[9]); writel(0, host->base + SD_EMMC_DELAY2_V3); writel(clk_bak, host->base + SD_EMMC_CLOCK_V3); pr_info("[%s][%d] clk config:0x%x\n", @@ -1852,8 +1883,7 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) intf3 |= (1<<22); writel(intf3, (host->base + SD_EMMC_INTF3)); pdata->intf3 = intf3; - if ((host->data->chip_type == MMC_CHIP_TL1) - || (host->data->chip_type == MMC_CHIP_G12B)) + if (host->data->chip_type == MMC_CHIP_TL1) aml_emmc_hs200_tl1(mmc); err = 0; } @@ -1867,12 +1897,11 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) } int aml_post_hs400_timming(struct mmc_host *mmc) { - int ret = 0; + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; aml_sd_emmc_clktest(mmc); if (host->data->chip_type == MMC_CHIP_TL1) aml_emmc_hs400_tl1(mmc); - else if (host->data->chip_type == MMC_CHIP_G12B) - aml_emmc_hs400_Revb(mmc); else aml_emmc_hs400_general(mmc); return 0; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 2cc865d03902..17d5f4afae9b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1207,15 +1207,20 @@ static int mmc_select_hs400(struct mmc_card *card) pr_info("%s: no support driver strength type 1 and 4\n", mmc_hostname(host)); } + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, val, + card->ext_csd.generic_cmd6_time, + true, true, true); #else val = EXT_CSD_TIMING_HS400 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; -#endif err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, true, false, true); +#endif + if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1226,9 +1231,11 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); +#ifndef CONFIG_AMLOGIC_MMC err = mmc_switch_status(card); if (err) goto out_err; +#endif return 0; diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index c43069e7ef3c..f8be3c567e72 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -332,6 +332,7 @@ struct amlsd_platform { u64 align[10]; int base_line; unsigned int count; + unsigned int cmd_c; unsigned int delay_cell; /* int order; */ unsigned int rx_err; From 4013b0b4aba77551307511169e0c35a855def782 Mon Sep 17 00:00:00 2001 From: long yu Date: Fri, 15 Mar 2019 15:38:47 +0800 Subject: [PATCH 0626/1060] storage: emmc: reduce cmd/ds/data pins driver strength for TL1 SOC [1/1] PD#SWPL-5334 Problem: TX window is not stable Solution: Reduce the drive capability of emmc controller pins Verify: TL1-T962X2_X301 Change-Id: Ib641c66131c2dee41eb68fb262f4770f431676b9 Signed-off-by: long yu Conflicts: arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 6 +++--- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 5 +++-- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 3 ++- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 6 +++--- arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts | 5 +++-- arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts | 3 ++- drivers/mmc/core/mmc.c | 2 +- 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index fe76232097df..a73419883d6f 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1766,7 +1766,7 @@ function = "emmc"; input-enable; bias-pull-up; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1785,7 +1785,7 @@ function = "emmc"; input-enable; bias-pull-up; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1795,7 +1795,7 @@ function = "emmc"; input-enable; bias-pull-down; - drive-strength = <3>; + drive-strength = <2>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index e75ca27909e0..32f770d77116 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1613,11 +1613,12 @@ "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <200000000>; + f_max = <198000000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 40e05554ac88..10284c7e10fc 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1566,7 +1566,8 @@ /* "MMC_CAP_1_8V_DDR", */ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; f_max = <198000000>; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 6796136e6520..893619991cd7 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1749,7 +1749,7 @@ function = "emmc"; input-enable; bias-pull-up; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1768,7 +1768,7 @@ function = "emmc"; input-enable; bias-pull-up; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1778,7 +1778,7 @@ function = "emmc"; input-enable; bias-pull-down; - drive-strength = <3>; + drive-strength = <2>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 4006eadcfdc0..d0a7f01374a9 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1716,9 +1716,10 @@ "MMC_CAP_ERASE", "MMC_CAP_CMD23", "MMC_CAP_DRIVER_TYPE_D"; - //caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <50000000>; + f_max = <198000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index b7b0e565b7b3..859e6f182e9f 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -1718,7 +1718,8 @@ "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; f_max = <198000000>; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 17d5f4afae9b..d9e78340f9b0 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1184,7 +1184,7 @@ static int mmc_select_hs400(struct mmc_card *card) pr_info("%s:use ds type0\n", mmc_hostname(host)); /*3 -> type4 -> MMC_CAP_DRIVER_TYPED*/ - } else if (ds & (1 << 3)) { + } else if (ds & (1 << 2)) { raw_driver_strength &= ~(1 << 1); pr_info("%s:use ds type4\n", mmc_hostname(host)); From c50512adc4854d2057de692821b8b69ebed7e5cc Mon Sep 17 00:00:00 2001 From: "ruixuan.li" Date: Tue, 2 Apr 2019 11:11:56 +0800 Subject: [PATCH 0627/1060] tm2: emmc run hs200 busmode [1/1] PD#SWPL-5658 Problem: emmc run high speed now Solution: modify dts Verify: passed on t962e2_ab319 Change-Id: Iedef30bed9547e7f57c883077462f1762c55fda3 Signed-off-by: ruixuan.li Conflicts: arch/arm/boot/dts/amlogic/mesontm2.dtsi arch/arm64/boot/dts/amlogic/mesontm2.dtsi arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts drivers/amlogic/mmc/aml_sd_emmc_v3.c --- arch/arm/boot/dts/amlogic/mesontm2.dtsi | 5 +- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 12 ++-- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 8 +-- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 2 +- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 5 +- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 11 ++-- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 9 +-- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 2 +- drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c | 2 +- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 65 ++++++++++--------- include/linux/amlogic/sd.h | 2 + 11 files changed, 63 insertions(+), 60 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index a73419883d6f..24206c8a855a 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1263,10 +1263,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&clkc CLKID_GP0_PLL>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index a6ea1f07e6b0..84bee34048c9 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1229,7 +1229,7 @@ sd_emmc_b: sdio@ffe05000 { status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0xffe05000 0x800>; interrupts = <0 190 4>; @@ -1275,7 +1275,7 @@ /* sd_emmc_b: sd@ffe05000 { * status = "okay"; - * compatible = "amlogic, meson-mmc-tl1"; + * compatible = "amlogic, meson-mmc-tm2"; * reg = <0xffe05000 0x800>; * interrupts = <0 190 1>; * @@ -1754,11 +1754,11 @@ "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23", - "MMC_CAP_DRIVER_TYPE_D"; - //caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <50000000>; + f_max = <200000000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index 68276f3539b7..d82054c016bd 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -1177,7 +1177,7 @@ sd_emmc_b: sd@ffe05000 { status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0xffe05000 0x800>; interrupts = <0 190 1>; @@ -1630,14 +1630,14 @@ "MMC_CAP_MMC_HIGHSPEED", "MMC_CAP_SD_HIGHSPEED", "MMC_CAP_NONREMOVABLE", - /*"MMC_CAP_1_8V_DDR",*/ + "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - //caps2 = "MMC_CAP2_HS200"; + caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <50000000>; + f_max = <200000000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 0648d6cf6c8d..627c2cd3c9af 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1178,7 +1178,7 @@ sd_emmc_b: sd@ffe05000 { status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0xffe05000 0x800>; interrupts = <0 190 1>; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 893619991cd7..1285089a7d03 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1245,10 +1245,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&clkc CLKID_GP0_PLL>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core","clkin0","clkin1","clkin2","clkin3","xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index d0a7f01374a9..33ad01a591ee 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1222,7 +1222,7 @@ sd_emmc_b: sdio@ffe05000 { status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0x0 0xffe05000 0x0 0x800>; interrupts = <0 190 4>; @@ -1267,7 +1267,7 @@ }; /* sd_emmc_b: sd@ffe05000 { * status = "okay"; - * compatible = "amlogic, meson-mmc-tl1"; + * compatible = "amlogic, meson-mmc-tm2"; * reg = <0xffe05000 0x800>; * interrupts = <0 190 1>; * @@ -1714,12 +1714,11 @@ "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23", - "MMC_CAP_DRIVER_TYPE_D"; + "MMC_CAP_CMD23"; caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <198000000>; + f_max = <200000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index d2f8ed3368bf..0846d02cedbb 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -18,7 +18,7 @@ /dts-v1/; #include "mesontm2.dtsi" -#include "partition_mbox_normal.dtsi" +#include "partition_mbox_normal_P_32.dtsi" / { model = "Amlogic TM2 T962E2 AB319"; @@ -1629,13 +1629,14 @@ "MMC_CAP_MMC_HIGHSPEED", "MMC_CAP_SD_HIGHSPEED", "MMC_CAP_NONREMOVABLE", - /*"MMC_CAP_1_8V_DDR",*/ + "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; - /*caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";*/ + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <50000000>; + f_max = <200000000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 69b23ed7db54..7917bbe08dd3 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -1177,7 +1177,7 @@ sd_emmc_b: sd@ffe05000 { status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0x0 0xffe05000 0x0 0x800>; interrupts = <0 190 1>; diff --git a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c index b5479b615f49..8ee3df8cc4f2 100644 --- a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c +++ b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c @@ -27,7 +27,7 @@ #include "tl1.h" PNAME(sd_emmc_parent_names) = { "xtal", "fclk_div2", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0_pll" }; + "fclk_div3", "fclk_div5", "fclk_div2p5", "mpll2", "mpll3", "gp0_pll" }; /*sd_emmc B*/ static MUX(sd_emmc_p0_mux_B, HHI_SD_EMMC_CLK_CNTL, 0x7, 25, sd_emmc_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED); diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index a72089fc325a..f3e7e26c11b8 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -116,7 +116,6 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host) u32 vconf = 0; struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf; struct mmc_phase *init = &(host->data->sdmmc.init); - struct mmc_phase *calc = &(host->data->sdmmc.calc); writel(0, host->base + SD_EMMC_ADJUST_V3); writel(0, host->base + SD_EMMC_DELAY1_V3); @@ -134,11 +133,6 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host) pclkc->core_phase = init->core_phase; /* 2: 180 phase */ pclkc->rx_phase = init->rx_phase; pclkc->tx_phase = init->tx_phase; - if ((host->data->chip_type >= MMC_CHIP_G12A) - && (host->data->chip_type != MMC_CHIP_TL1)) { - pclkc->core_phase = calc->core_phase; - pclkc->tx_phase = calc->tx_phase; - } pclkc->always_on = 1; /* Keep clock always on */ writel(vclkc, host->base + SD_EMMC_CLOCK_V3); @@ -247,13 +241,19 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, host->mux_parent[0]); if (ret) pr_warn("set comp0 as mux_clk parent error\n"); - } else if ((host->data->chip_type == MMC_CHIP_TL1) + } else if (((host->data->chip_type >= MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) && (clk_ios >= 166000000)) { - src0_clk = devm_clk_get(host->dev, "clkin3"); + src0_clk = devm_clk_get(host->dev, "clkin2"); if (ret) - pr_warn("not get GP0\n"); + pr_warn("not get clkin2\n"); + if ((host->data->chip_type == MMC_CHIP_TL1) + && (clk_ios <= 198000000)) { ret = clk_set_rate(src0_clk, 792000000); - pr_warn("set rate gp0>>>>>>>>>clk:%lu\n", + if (ret) + pr_warn("not set tl1-gp0\n"); + } + pr_warn("set rate clkin2>>>>>>>>clk:%lu\n", clk_get_rate(src0_clk)); ret = clk_set_parent(host->mux_parent[0], src0_clk); @@ -284,10 +284,12 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, /* (re)start clock, if non-zero */ if (clk_ios) { + if (pdata->calc_f) { vclkc = readl(host->base + SD_EMMC_CLOCK_V3); pdata->clk_lay.source = clk_get_rate(host->cfg_div_clk) * clkc->div; pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); + } vcfg = readl(host->base + SD_EMMC_CFG); conf->stop_clk = 0; @@ -300,7 +302,7 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, mmc->actual_clock, readl(host->clksrc_base + (HHI_NAND_CLK_CNTL << 2))); - pr_debug("[%s] after clock: 0x%x\n", + pr_info("[%s] after clock: 0x%x\n", __func__, readl(host->base + SD_EMMC_CLOCK_V3)); return ret; @@ -348,7 +350,8 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, if (pdata->tx_delay != 0) clkc->tx_delay = pdata->tx_delay; - if ((host->data->chip_type == MMC_CHIP_TL1) + if (((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) && aml_card_type_mmc(pdata)) { clkc->core_phase = para->hs4.core_phase; clkc->tx_phase = para->hs4.tx_phase; @@ -372,9 +375,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, /* overide co-phase by dts */ if (pdata->co_phase) clkc->core_phase = pdata->co_phase; - if ((pdata->calc_f) - && ((host->data->chip_type >= MMC_CHIP_G12A) - && (host->data->chip_type != MMC_CHIP_TL1))) { + if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; clkc->tx_phase = para->calc.tx_phase; } @@ -386,9 +387,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, || (host->data->chip_type == MMC_CHIP_TXLX) || (host->data->chip_type == MMC_CHIP_G12A)) clkc->core_phase = para->sd_hs.core_phase; - if ((pdata->calc_f) - && ((host->data->chip_type >= MMC_CHIP_G12A) - && (host->data->chip_type != MMC_CHIP_TL1))) { + if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; clkc->tx_phase = para->calc.tx_phase; } @@ -397,6 +396,11 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->tx_phase = para->sdr104.tx_phase; } else { ctrl->ddr = 0; + clkc->tx_delay = 0; + clkc->core_phase = para->init.core_phase; + clkc->tx_phase = para->init.tx_phase; + irq_en &= ~(1<<17); + writel(irq_en, host->base + SD_EMMC_IRQ_EN); /* timing == MMC_TIMING_LEGACY */ if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; @@ -404,9 +408,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, } } - if ((pdata->calc_f) - && ((host->data->chip_type >= MMC_CHIP_G12A) - && (host->data->chip_type != MMC_CHIP_TL1))) { + if (pdata->calc_f) { if (timing <= MMC_TIMING_SD_HS) { ret = aml_fixdiv_calc(&fixdiv, &pdata->clk_lay); if (!ret) { @@ -801,7 +803,7 @@ RETRY: eyetest_log = readl(host->base + SD_EMMC_EYETEST_LOG); if (!(geyetest_log->eyetest_done & 0x1)) { - pr_debug("testing eyetest times:0x%x,out:0x%x,0x%x,line:%d\n", + pr_warn("testing eyetest times:0x%x,out:0x%x,0x%x,line:%d\n", readl(host->base + SD_EMMC_EYETEST_LOG), eyetest_out0, eyetest_out1, line_x); gintf3->eyetest_on = 0; @@ -822,7 +824,7 @@ RETRY: writel(0, host->base + SD_EMMC_ADJUST_V3); pdata->intf3 = intf3; pdata->align[line_x] = ((tmp | eyetest_out1) << 32) | eyetest_out0; - pr_info("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", + pr_debug("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", readl(host->base + SD_EMMC_DELAY1_V3), readl(host->base + SD_EMMC_DELAY2_V3), pdata->align[line_x], line_x); @@ -1090,12 +1092,7 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) host->is_tunning = 1; for (i = 0; i < 64; i++) { - gintf3->ds_sht_m += 1; - writel(intf3, host->base + SD_EMMC_INTF3); - pdata->intf3 = intf3; - err = aml_sd_emmc_cali_v3(mmc, - MMC_READ_MULTIPLE_BLOCK, - host->blk_test, blksz, 20); + err = emmc_test_bus(mmc); pr_debug("intf3: 0x%x, err[%d]: %d\n", readl(host->base + SD_EMMC_INTF3), i, err); if (!err) @@ -1594,6 +1591,7 @@ int aml_emmc_hs200_tl1(struct mmc_host *mmc) int i, err = 0; clk_bak = vclkc; + clkc->tx_phase = para->hs4.tx_phase; clkc->core_phase = para->hs4.core_phase; clkc->tx_delay = para->hs4.tx_delay; if (pdata->tx_delay != 0) @@ -1609,12 +1607,14 @@ int aml_emmc_hs200_tl1(struct mmc_host *mmc) continue; count = fbinary(pdata->align[9]); if (((count >= 10) && (count <= 22)) - || ((count >= 43) && (count <= 56))) + || ((count >= 45) && (count <= 56))) break; } if (i == 63) pr_err("[%s]no find cmd timing\n", __func__); pdata->cmd_c = (delay2 >> 24); + pr_info("cmd->u64eyet:0x%016llx\n", + pdata->align[9]); writel(0, host->base + SD_EMMC_DELAY2_V3); writel(clk_bak, host->base + SD_EMMC_CLOCK_V3); pr_info("[%s][%d] clk config:0x%x\n", @@ -1883,7 +1883,8 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) intf3 |= (1<<22); writel(intf3, (host->base + SD_EMMC_INTF3)); pdata->intf3 = intf3; - if (host->data->chip_type == MMC_CHIP_TL1) + if ((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) aml_emmc_hs200_tl1(mmc); err = 0; } @@ -1902,6 +1903,8 @@ int aml_post_hs400_timming(struct mmc_host *mmc) aml_sd_emmc_clktest(mmc); if (host->data->chip_type == MMC_CHIP_TL1) aml_emmc_hs400_tl1(mmc); + else if (host->data->chip_type == MMC_CHIP_G12B) + aml_emmc_hs400_Revb(mmc); else aml_emmc_hs400_general(mmc); return 0; diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index f8be3c567e72..a044f8924a34 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -282,6 +282,7 @@ struct amlsd_platform { unsigned int dly1; unsigned int dly2; unsigned int intf3; + unsigned int win_start; unsigned int irq_sdio_sleep; unsigned int clock; /* signalling voltage (1.8V or 3.3V) */ @@ -300,6 +301,7 @@ struct amlsd_platform { unsigned int gpio_power; unsigned int power_level; unsigned int calc_f; + unsigned int no_sduart; unsigned int auto_clk_close; unsigned int vol_switch; From 408c93df790165741ca28a6f2034285332130d65 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Fri, 17 May 2019 13:34:14 +0900 Subject: [PATCH 0628/1060] ODROID:Merge BSP 2019.04 (fix build err-vout_lcd) Change-Id: I88e5f27cfe00dc5a103fc82a519e0ed088448847 --- drivers/amlogic/media/vout/lcd/lcd_debug.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index e8d023eabb0b..97dd57ccb16d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -470,7 +470,7 @@ static int lcd_info_print_p2p(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, - "p2p_type %d\n" + "p2p_type 0x%x\n" "lane_num %d\n" "channel_sel0 0x%08x\n" "channel_sel1 0x%08x\n" @@ -485,7 +485,7 @@ static int lcd_info_print_p2p(char *buf, int offset) pconf->lcd_control.p2p_config->channel_sel1, pconf->lcd_control.p2p_config->pn_swap, pconf->lcd_control.p2p_config->bit_swap, - pconf->lcd_control.p2p_config->bit_rate, + pconf->lcd_timing.bit_rate, pconf->lcd_control.p2p_config->phy_vswing, pconf->lcd_control.p2p_config->phy_preem); @@ -2060,7 +2060,7 @@ static ssize_t lcd_debug_change_store(struct class *class, break; case 'p': p2p_conf = pconf->lcd_control.p2p_config; - ret = sscanf(buf, "p2p %d %d %x %x %d %d", + ret = sscanf(buf, "p2p %x %d %x %x %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); if (ret == 6) { p2p_conf->p2p_type = val[0]; @@ -2070,7 +2070,7 @@ static ssize_t lcd_debug_change_store(struct class *class, p2p_conf->pn_swap = val[4]; p2p_conf->bit_swap = val[5]; pr_info("change p2p config:\n" - "p2p_type=%d, lane_num=%d,\n" + "p2p_type=0x%x, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" "pn_swap=%d, bit_swap=%d\n", p2p_conf->p2p_type, p2p_conf->lane_num, @@ -3592,13 +3592,13 @@ static ssize_t lcd_p2p_debug_store(struct class *class, struct p2p_config_s *p2p_conf; p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; - ret = sscanf(buf, "%d %d %x %x %d %d", + ret = sscanf(buf, "%x %d %x %x %d %d", &p2p_conf->p2p_type, &p2p_conf->lane_num, &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, &p2p_conf->pn_swap, &p2p_conf->bit_swap); if (ret == 6) { pr_info("set p2p config:\n" - "p2p_type=%d, lane_num=%d,\n" + "p2p_type=0x%x, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" "pn_swap=%d, bit_swap=%d\n", p2p_conf->p2p_type, p2p_conf->lane_num, From 819ccca2b3956e47787362155e8b8c081cb9289e Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Sat, 29 Dec 2018 19:14:23 +0800 Subject: [PATCH 0629/1060] audio: auge: fix sharebuffer channel map [1/1] PD#SWPL-2645 Problem: play ddp source, then play pcm source, no sound Solution: 1. fix same source control and channel map issue 2. i2s 8ch, spdif 2ch, channels are not mapped, make spdif 8 channel mask 3. when same source used, keep mpll use same mpll Verify: x301 Change-Id: I2fe4bbcbcbfff0a1c1a6cebf61d1da5aba9b7a9d Signed-off-by: Xing Wang Conflicts: arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts sound/soc/amlogic/auge/ddr_mngr.c sound/soc/amlogic/auge/sharebuffer.c sound/soc/amlogic/auge/spdif_hw.c sound/soc/amlogic/auge/spdif_hw.h --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 6 +- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 6 +- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 6 +- sound/soc/amlogic/auge/ddr_mngr.c | 67 +++++++++++++++++-- sound/soc/amlogic/auge/sharebuffer.c | 7 +- sound/soc/amlogic/auge/spdif_hw.c | 22 +++--- sound/soc/amlogic/auge/spdif_hw.h | 4 +- 8 files changed, 82 insertions(+), 42 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 32f770d77116..fa172a9e9ef7 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1250,10 +1250,8 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL1 - &clkaudio CLKID_AUDIO_SPDIFOUT_A>; - clock-names = "mclk", "clk_srcpll", - "samesource_srcpll", "samesource_clk"; + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 10284c7e10fc..4fc4802831d6 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1161,10 +1161,8 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL1 - &clkaudio CLKID_AUDIO_SPDIFOUT_A>; - clock-names = "mclk", "clk_srcpll", - "samesource_srcpll", "samesource_clk"; + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index 33ad01a591ee..e9283634ea64 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -1328,10 +1328,8 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL1 - &clkaudio CLKID_AUDIO_SPDIFOUT_A>; - clock-names = "mclk", "clk_srcpll", - "samesource_srcpll", "samesource_clk"; + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 859e6f182e9f..12abf8274d01 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -1339,10 +1339,8 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL1 - &clkaudio CLKID_AUDIO_SPDIFOUT_A>; - clock-names = "mclk", "clk_srcpll", - "samesource_srcpll", "samesource_clk"; + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdma_mclk &tdmout_a>; diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 2a704a84da09..5e72772151f3 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -1011,8 +1011,8 @@ int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) && (frddrs[i].fifo_id != current_fifo_id) && (frddrs[i].dest == ss_sel)) { - pr_debug("%s, ss_sel:%d used, not for share buffer at same time\n", - __func__, + pr_info(" frddr:%d, ss_sel:%d used, invalid for share buffer\n", + i, ss_sel); ret = 0; break; @@ -1240,14 +1240,69 @@ void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst) void aml_frddr_select_dst_ss(struct frddr *fr, enum frddr_dest dst, int sel, bool enable) { - unsigned int ss_valid = aml_check_sharebuffer_valid(fr, dst); + struct aml_audio_controller *actrl = fr->actrl; + unsigned int reg_base = fr->reg_base; + unsigned int reg, ss_valid; + + ss_valid = aml_check_sharebuffer_valid(fr, dst); /* same source en */ if (fr->chipinfo && fr->chipinfo->same_src_fn - && ss_valid - ) - frddr_set_sharebuffer_enable(fr, dst, sel, enable); + && ss_valid) { + int s_v = 0, s_m = 0; + + if (fr->chipinfo + && fr->chipinfo->src_sel_ctrl) { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, + reg_base); + + switch (sel) { + case 1: + s_m = 0x17 << 8; + s_v = enable ? + (dst << 8 | 1 << 12) : 0 << 8; + break; + case 2: + s_m = 0x17 << 16; + s_v = enable ? + (dst << 16 | 1 << 20) : 0 << 16; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + s_m |= 0xff << 24; + if (enable) + s_v |= (fr->channels - 1) << 24; + else + s_v |= 0x0 << 24; + } else { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, + reg_base); + + switch (sel) { + case 1: + s_m = 0xf << 4; + s_v = enable ? + (dst << 4 | 1 << 7) : 0 << 4; + break; + case 2: + s_m = 0xf << 8; + s_v = enable ? + (dst << 8 | 1 << 11) : 0 << 8; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + } + pr_debug("%s sel:%d, dst_src:%d\n", + __func__, sel, dst); + aml_audiobus_update_bits(actrl, reg, s_m, s_v); + } } void aml_frddr_set_fifos(struct frddr *fr, diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index 1a740c4a166a..1ad5695427b5 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -36,8 +36,7 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - true, - lane_i2s); + true); /* spdif to hdmitx */ spdifout_to_hdmitx_ctrl(spdif_id); @@ -64,7 +63,7 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - false, 0); + false); return 0; } @@ -96,7 +95,7 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream, } else if (samesource_sel < 5) { /* same source with spdif a/b */ sharebuffer_spdifout_prepare(substream, - fr, samesource_sel - 3, lane_i2s); + fr, samesource_sel - 3); } /* frddr, share buffer, src_sel1 */ diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 65a78b9f7338..86c9e50e3c25 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -420,18 +420,13 @@ static void spdifout_clk_ctrl(int spdif_id, bool is_enable) } #endif static void spdifout_fifo_ctrl(int spdif_id, - int fifo_id, int bitwidth, int channels, int lane_i2s) + int fifo_id, int bitwidth, int channels) { unsigned int frddr_type = spdifout_get_frddr_type(bitwidth); unsigned int offset, reg, i, chmask = 0; - unsigned int swap_masks = 0; - /* spdif always masks two channel */ - if (lane_i2s * 2 >= channels) { - pr_err("invalid lane(%d) and channels(%d)\n", - lane_i2s, channels); - return; - } + for (i = 0; i < channels; i++) + chmask |= (1 << i); for (i = 0; i < channels; i++) chmask |= (1 << i); @@ -450,8 +445,8 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; audiobus_update_bits(reg, - 0x1<<20|0x1<<19|0xff<<4, - 0<<20|0<<19|chmask<<4); + 0x3<<21|0x1<<20|0x1<<19|0xff<<4, + 0x0<<21|0<<20|0<<19|chmask<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdif_id; @@ -505,7 +500,7 @@ void spdifout_enable(int spdif_id, bool is_enable, bool reenable) } void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable, int lane_i2s) + int bitwidth, int channels, bool is_enable) { int spdif_id; @@ -515,8 +510,7 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, spdif_id = 0; if (is_enable) - spdifout_fifo_ctrl(spdif_id, - fifo_id, bitwidth, channels, lane_i2s); + spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); } int spdifin_get_sample_rate(void) @@ -660,7 +654,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable) /* spdif ctrl */ spdifout_fifo_ctrl(spdif_id, - frddr_index, bitwidth, runtime.channels, 0); + frddr_index, bitwidth, runtime.channels); /* channel status info */ spdif_get_channel_status_info(&chsts, sample_rate); diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index e15efa3abaab..d981ed079997 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -78,8 +78,8 @@ extern void aml_spdifout_get_aed_info(int spdifout_id, extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable, int lane_i2s); -extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable); + int bitwidth, int channels, bool is_enable); +extern void spdifout_enable(int spdif_id, bool is_enable); extern int spdifin_get_sample_rate(void); From 0400796f77a1a3c58cd0eed3c3ab58b4dff5690b Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Tue, 15 Jan 2019 17:15:34 +0800 Subject: [PATCH 0630/1060] dts: tl1: enable resample for tl1 [1/2] PD#SWPL-3365 Problem: not resample for audio in, so output in wrong sample rate Solution: 1. enable resample in dts 2. fix to check whether resample is needed Verify: x301 Change-Id: I99238cc21a00ab53df6a1f8ab1703bc9ab48cbaa Signed-off-by: Xing Wang Conflicts: sound/soc/amlogic/auge/ddr_mngr.c sound/soc/amlogic/auge/resample.c sound/soc/amlogic/auge/spdif.c --- sound/soc/amlogic/auge/ddr_mngr.c | 7 +++---- sound/soc/amlogic/auge/resample.c | 11 +++++++---- sound/soc/amlogic/auge/spdif.c | 6 ++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 5e72772151f3..884720c7d533 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -494,9 +494,8 @@ unsigned int aml_toddr_read1(struct toddr *to) unsigned int reg_base = to->reg_base; unsigned int reg; - reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); - - return aml_audiobus_read(actrl, reg); + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); + aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30); } void aml_toddr_write1(struct toddr *to, unsigned int val) @@ -578,7 +577,7 @@ static void aml_resample_enable( pr_info("toddr %d selects data to %s resample_%c for module:%s\n", to->fifo_id, enable ? "enable" : "disable", - (p_attach_resample->id == RESAMPLE_A) ? 'a' : 'b', + (p_attach_resample->id == 0) ? 'a' : 'b', toddr_src_get_str(p_attach_resample->attach_module) ); diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index f3a99483eec3..21e6f4de92f6 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -286,10 +286,13 @@ int resample_set(enum resample_idx id, enum samplerate_index index) #endif p_resample->asrc_rate_idx = index; - resample_rate = resample_idx2rate(index); - ret = audio_resample_set(p_resample, (bool)index, resample_rate); - if (ret) - return ret; + pr_info("%s resample_%c %s\n", + __func__, + (id == 0) ? 'a' : 'b', + auge_resample_texts[index]); + + if (audio_resample_set(p_resample, (bool)index, resample_rate)) + return 0; if (index == RATE_OFF) resample_disable(p_resample->id); diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 62dd3a2cf782..ba24b1fe333d 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -51,9 +51,6 @@ /*#define __SPDIFIN_AUDIO_TYPE_HW__*/ -static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir); - struct spdif_chipinfo { enum SPDIF_ID id; @@ -708,6 +705,7 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, RATE_OFF); #endif +#endif #endif } if (intrpt_status & 0x10) @@ -1131,7 +1129,7 @@ static void aml_dai_spdif_shutdown( #ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disabled, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) - resample_set(p_spdif->asrc_id, RATE_OFF); + resample_set(p_spdif->asrc_id, 0); #endif clk_disable_unprepare(p_spdif->clk_spdifin); clk_disable_unprepare(p_spdif->fixed_clk); From 4c7fb7757a4f5dcea859d3022046de0efca423be Mon Sep 17 00:00:00 2001 From: "yujie.wu" Date: Fri, 8 Mar 2019 13:51:10 +0800 Subject: [PATCH 0631/1060] audio: Merge code from RSR project [1/2] PD#SWPL-5495 Problem: There is some improvement code on RSR project, we need to merge them back to trunk. Solution: Merge the code from rsr branch Verify: A113 Change-Id: I0ba11c8ff412db659ff2f10bfc00d63c49f84bb5 Signed-off-by: yujie.wu Conflicts: sound/soc/amlogic/auge/tdm.c --- arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts | 2 +- .../boot/dts/amlogic/axg_s400_v03sbr.dts | 2 +- sound/soc/amlogic/auge/spdif_hw.c | 14 +++++- sound/soc/amlogic/auge/tdm.c | 43 ++++--------------- 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts index 3f5ae0fec5b5..7727ce8768a4 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -546,7 +546,7 @@ aml-audio-card,dai-link@2 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; + continuous-clock; //bitclock-inversion; //frame-inversion; //bitclock-master = <&aml_tdmc>; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts index c37f4f6e2677..6f86df42574a 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -546,7 +546,7 @@ aml-audio-card,dai-link@2 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; + continuous-clock; //bitclock-inversion; //frame-inversion; //bitclock-master = <&aml_tdmc>; diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 86c9e50e3c25..69009946d047 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -516,16 +516,28 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, int spdifin_get_sample_rate(void) { unsigned int val; + /*EE_AUDIO_SPDIFIN_STAT0*/ + /*r_width_max bit17:8 (the max width of two edge;)*/ + unsigned int max_width = 0; val = audiobus_read(EE_AUDIO_SPDIFIN_STAT0); /* NA when check min width of two edges */ if (((val >> 18) & 0x3ff) == 0x3ff) - return 0x7; + return 7; + + /*check the max width of two edge when spdifin sr=32kHz*/ + /*if max_width is more than 0x2f0(magic number),*/ + /*sr(32kHz) is unavailable*/ + max_width = ((val >> 8) & 0x3ff); + + if ((((val >> 28) & 0x7) == 0) && (max_width == 0x3ff)) + return 7; return (val >> 28) & 0x7; } + static int spdifin_get_channel_status(int sel) { unsigned int val; diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 2b21e3bf03bf..4349e5664428 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -156,35 +156,6 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { .channels_max = 32, }; -static int tdm_clk_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); - struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); - - ucontrol->value.enumerated.item[0] = clk_get_rate(p_tdm->mclk); - return 0; -} - -static int tdm_clk_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); - struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); - - int mclk_rate = p_tdm->last_mclk_freq; - int value = ucontrol->value.enumerated.item[0]; - - if (value > 2000000 || value < 0) { - pr_err("Fine tdm clk setting range (0~2000000), %d\n", value); - return 0; - } - mclk_rate += (value - 1000000); - - aml_dai_set_tdm_sysclk(cpu_dai, 0, mclk_rate, 0); - - return 0; -} static int tdmin_clk_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -226,14 +197,10 @@ static const struct soc_enum i2sin_clk_enum[] = { static const struct snd_kcontrol_new snd_tdm_controls[] = { SOC_ENUM_EXT("I2SIn CLK", i2sin_clk_enum, tdmin_clk_get, - NULL), - - SOC_SINGLE_EXT("TDM MCLK Fine Setting", - 0, 0, 2000000, 0, - tdm_clk_get, - tdm_clk_set), + NULL) }; + static irqreturn_t aml_tdm_ddr_isr(int irq, void *devid) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)devid; @@ -1194,8 +1161,14 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, static int aml_dai_tdm_probe(struct snd_soc_dai *cpu_dai) { + int ret = 0; struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + ret = snd_soc_add_dai_controls(cpu_dai, snd_tdm_controls, + ARRAY_SIZE(snd_tdm_controls)); + if (ret < 0) + pr_err("%s, failed add snd spdif controls\n", __func__); + /* config ddr arb */ aml_tdm_arb_config(p_tdm->actrl); From e1d727fcc22e8649334a9deaf11852b450452279 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Wed, 20 Mar 2019 22:44:51 +0800 Subject: [PATCH 0632/1060] audio: auge: add sound card for sm1 [2/2] PD#SWPL-6151 Problem: sound card for sm1 Solution: add sound card for sm1 Verify: ac200 Change-Id: I4f65472af7a8399fb6fe003db608158e11bed566 Signed-off-by: Xing Wang Conflicts: sound/soc/amlogic/auge/ddr_mngr.c sound/soc/amlogic/auge/ddr_mngr.h sound/soc/amlogic/auge/spdif.c sound/soc/amlogic/auge/tdm.c --- MAINTAINERS | 1 + sound/soc/amlogic/auge/Makefile | 5 +- sound/soc/amlogic/auge/audio_clks.c | 4 + sound/soc/amlogic/auge/audio_clks.h | 1 + sound/soc/amlogic/auge/audio_utils.c | 7 +- sound/soc/amlogic/auge/ddr_mngr.c | 17 +- sound/soc/amlogic/auge/ddr_mngr.h | 36 +- sound/soc/amlogic/auge/earc.c | 792 +++++++++++++++++++++ sound/soc/amlogic/auge/earc_hw.c | 87 +++ sound/soc/amlogic/auge/earc_hw.h | 26 + sound/soc/amlogic/auge/iomap.c | 81 +++ sound/soc/amlogic/auge/iomap.h | 16 + sound/soc/amlogic/auge/loopback_hw.c | 12 +- sound/soc/amlogic/auge/pdm.c | 86 ++- sound/soc/amlogic/auge/pdm.h | 10 +- sound/soc/amlogic/auge/pdm_hw.c | 21 + sound/soc/amlogic/auge/pdm_hw.h | 4 + sound/soc/amlogic/auge/pdm_match_table.c | 53 ++ sound/soc/amlogic/auge/regs.h | 269 ++++++- sound/soc/amlogic/auge/sm1,clocks.c | 376 ++++++++++ sound/soc/amlogic/auge/spdif.c | 92 +-- sound/soc/amlogic/auge/spdif_match_table.c | 126 ++++ sound/soc/amlogic/auge/tdm.c | 240 +++---- sound/soc/amlogic/auge/tdm_hw.c | 109 ++- sound/soc/amlogic/auge/tdm_hw.h | 13 +- sound/soc/amlogic/auge/tdm_match_table.c | 186 +++++ sound/soc/amlogic/auge/vad_dev.c | 2 +- 27 files changed, 2325 insertions(+), 347 deletions(-) create mode 100644 sound/soc/amlogic/auge/earc.c create mode 100644 sound/soc/amlogic/auge/earc_hw.c create mode 100644 sound/soc/amlogic/auge/earc_hw.h create mode 100644 sound/soc/amlogic/auge/pdm_match_table.c create mode 100644 sound/soc/amlogic/auge/sm1,clocks.c create mode 100644 sound/soc/amlogic/auge/spdif_match_table.c create mode 100644 sound/soc/amlogic/auge/tdm_match_table.c diff --git a/MAINTAINERS b/MAINTAINERS index c4ba5ed396a4..f0721818943c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14434,6 +14434,7 @@ F: include/linux/amlogic/meson_cooldev.h AMLOGIC G12A Audio DRIVER M: Xing Wang F: sound/soc/amlogic/auge/* +F: sound/soc/codec/amlogic/* AMLOGIC G12A BL_EXTERN LP8556 DRIVER M: Weiming Liu diff --git a/sound/soc/amlogic/auge/Makefile b/sound/soc/amlogic/auge/Makefile index 4cf47bec8853..91825bf36d6c 100644 --- a/sound/soc/amlogic/auge/Makefile +++ b/sound/soc/amlogic/auge/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \ axg,clocks.o \ g12a,clocks.o \ tl1,clocks.o \ + sm1,clocks.o \ card.o \ card_utils.o \ tdm.o \ @@ -32,4 +33,6 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \ frhdmirx_hw.o \ vad.o \ vad_hw.o \ - vad_dev.o + vad_dev.o \ + earc.o \ + earc_hw.o diff --git a/sound/soc/amlogic/auge/audio_clks.c b/sound/soc/amlogic/auge/audio_clks.c index 1f0dd6fc1b54..e02f2a562b07 100644 --- a/sound/soc/amlogic/auge/audio_clks.c +++ b/sound/soc/amlogic/auge/audio_clks.c @@ -36,6 +36,10 @@ static const struct of_device_id audio_clocks_of_match[] = { .compatible = "amlogic, tl1-audio-clocks", .data = &tl1_audio_clks_init, }, + { + .compatible = "amlogic, sm1-audio-clocks", + .data = &sm1_audio_clks_init, + }, {}, }; MODULE_DEVICE_TABLE(of, audio_clocks_of_match); diff --git a/sound/soc/amlogic/auge/audio_clks.h b/sound/soc/amlogic/auge/audio_clks.h index 359fbfc5560f..56a0a67b1d31 100644 --- a/sound/soc/amlogic/auge/audio_clks.h +++ b/sound/soc/amlogic/auge/audio_clks.h @@ -93,6 +93,7 @@ struct audio_clk_init { extern struct audio_clk_init axg_audio_clks_init; extern struct audio_clk_init g12a_audio_clks_init; extern struct audio_clk_init tl1_audio_clks_init; +extern struct audio_clk_init sm1_audio_clks_init; struct clk_chipinfo { /* force clock source as oscin(24M) */ diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index ac18fb09f4c3..505f9944bf75 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -711,6 +711,9 @@ static int tdmout_c_binv_set_enum( SND_ENUM(xname, type, CTRL0, xenum, xshift, xmask) #define SND_SWAP(xname, type, xenum, xshift, xmask) \ + SND_ENUM(xname, type, SWAP0, xenum, xshift, xmask) + +#define SND_SPDIFOUT_SWAP(xname, type, xenum, xshift, xmask) \ SND_ENUM(xname, type, SWAP, xenum, xshift, xmask) #define TDM_MASK(xname, type, func) \ @@ -992,9 +995,9 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { spdif_channel_status_enum), /*SPDIFOUT swap*/ - SND_SWAP("SPDIFOUT Lane0 Left Channel Swap", + SND_SPDIFOUT_SWAP("SPDIFOUT Lane0 Left Channel Swap", SPDIFOUT, out_swap_channel_enum, 0, 0x7), - SND_SWAP("SPDIFOUT Lane0 Right Channel Swap", + SND_SPDIFOUT_SWAP("SPDIFOUT Lane0 Right Channel Swap", SPDIFOUT, out_swap_channel_enum, 4, 0x7), /*SPDIFOUT mixer*/ SND_MIX("SPDIFOUT Mixer Channel", diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 884720c7d533..af7560a86a1b 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -1482,7 +1482,7 @@ static const char *const toddr_src_sel_texts[] = { "TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN", "PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A", "FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB", - "EARCRX_DMAC", "RESERVED_0", "RESERVED_1", "RESERVED_2", + "EARCRX_DMAC", "RESERVED", "RESERVED", "RESERVED", "VAD" }; @@ -1608,6 +1608,15 @@ static struct ddr_chipinfo tl1_ddr_chipinfo = { .wakeup = 2, }; +static struct ddr_chipinfo sm1_ddr_chipinfo = { + .same_src_fn = true, + .ugt = true, + .src_sel_ctrl = true, + .asrc_src_sel_ctrl = true, + .fifo_num = 4, + .wakeup = 2, +}; + static const struct of_device_id aml_ddr_mngr_device_id[] = { { .compatible = "amlogic, axg-audio-ddr-manager", @@ -1621,6 +1630,10 @@ static const struct of_device_id aml_ddr_mngr_device_id[] = { .compatible = "amlogic, tl1-audio-ddr-manager", .data = &tl1_ddr_chipinfo, }, + { + .compatible = "amlogic, sm1-audio-ddr-manager", + .data = &sm1_ddr_chipinfo, + }, {}, }; MODULE_DEVICE_TABLE(of, aml_ddr_mngr_device_id); @@ -1684,6 +1697,8 @@ static int aml_ddr_mngr_platform_probe(struct platform_device *pdev) && (p_ddr_chipinfo->fifo_num == 4)) { toddrs[DDR_D].irq = platform_get_irq_byname(pdev, "toddr_d"); frddrs[DDR_D].irq = platform_get_irq_byname(pdev, "frddr_d"); + if (toddrs[DDR_D].irq < 0 || frddrs[DDR_D].irq < 0) + dev_err(&pdev->dev, "check irq for DDR_D\n"); ddr_num = p_ddr_chipinfo->fifo_num; } diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index c787662707d0..2327ef569ce3 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -42,29 +42,19 @@ enum ddr_types { * from tl1, add new source FRATV, FRHDMIRX, LOOPBACK_B, SPDIFIN_LB, VAD */ enum toddr_src { - TODDR_INVAL = -1, - TDMIN_A = 0, - TDMIN_B = 1, - TDMIN_C = 2, - SPDIFIN = 3, - PDMIN = 4, - FRATV = 5, /* NONE for axg, g12a, g12b */ - TDMIN_LB = 6, - LOOPBACK_A = 7, - FRHDMIRX = 8, /* from tl1 chipset*/ - LOOPBACK_B = 9, - SPDIFIN_LB = 10, - EARCRX_DMAC = 11,/* from sm1 chipset */ - RESERVED_0 = 12, - RESERVED_1 = 13, - RESERVED_2 = 14, - VAD = 15, - TODDR_SRC_MAX = 16 -}; - -enum resample_idx { - RESAMPLE_A, - RESAMPLE_B + TDMIN_A, + TDMIN_B, + TDMIN_C, + SPDIFIN, + PDMIN, + FRATV, /* NONE for axg, g12a, g12b */ + TDMIN_LB, + LOOPBACK_A, + FRHDMIRX, /* from tl1 chipset*/ + LOOPBACK_B, + SPDIFIN_LB, + EARCRX_DMAC, /* from sm1 chipset */ + VAD, }; enum resample_src { diff --git a/sound/soc/amlogic/auge/earc.c b/sound/soc/amlogic/auge/earc.c new file mode 100644 index 000000000000..124ac6919739 --- /dev/null +++ b/sound/soc/amlogic/auge/earc.c @@ -0,0 +1,792 @@ +/* + * sound/soc/amlogic/auge/earc.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * Audio External Input/Out drirver + * such as fratv, frhdmirx + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddr_mngr.h" +#include "earc_hw.h" + +#define DRV_NAME "EARC" + +struct earc { + struct aml_audio_controller *actrl; + struct device *dev; + + struct clk *clk_rx_gate; + struct clk *clk_rx_cmdc; + struct clk *clk_rx_dmac; + struct clk *clk_rx_cmdc_srcpll; + struct clk *clk_rx_dmac_srcpll; + struct clk *clk_tx_gate; + struct clk *clk_tx_cmdc; + struct clk *clk_tx_dmac; + struct clk *clk_tx_cmdc_srcpll; + struct clk *clk_tx_dmac_srcpll; + + struct toddr *tddr; + struct frddr *fddr; + + int irq_rx_cmdc; + int irq_rx_dmac; + int irq_tx_cmdc; + int irq_tx_dmac; + + int sysclk_freq; +}; + +#define PREALLOC_BUFFER_MAX (256 * 1024) + +#define EARC_RATES (SNDRV_PCM_RATE_8000_192000) +#define EARC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_pcm_hardware earc_hardware = { + .info = + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_PAUSE, + + .formats = EARC_FORMATS, + + .period_bytes_min = 64, + .period_bytes_max = 128 * 1024, + .periods_min = 2, + .periods_max = 1024, + .buffer_bytes_max = 256 * 1024, + + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 32, +}; + +static irqreturn_t earc_ddr_isr(int irq, void *devid) +{ + struct snd_pcm_substream *substream = + (struct snd_pcm_substream *)devid; + + if (!snd_pcm_running(substream)) + return IRQ_HANDLED; + + snd_pcm_period_elapsed(substream); + + return IRQ_HANDLED; +} + +static irqreturn_t earc_rx_cmdc_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static irqreturn_t earc_rx_dmac_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static irqreturn_t earc_tx_cmdc_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static irqreturn_t earc_tx_dmac_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static int earc_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct earc *p_earc; + int ret = 0; + + pr_info("asoc debug: %s-%d\n", __func__, __LINE__); + + p_earc = (struct earc *)dev_get_drvdata(dev); + + snd_soc_set_runtime_hwparams(substream, &earc_hardware); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + p_earc->fddr = aml_audio_register_frddr(dev, + p_earc->actrl, + earc_ddr_isr, substream); + if (p_earc->fddr == NULL) { + dev_err(dev, "failed to claim from ddr\n"); + return -ENXIO; + } + if (p_earc->irq_tx_cmdc > 0) { + ret = request_irq(p_earc->irq_tx_cmdc, + earc_tx_cmdc_isr, 0, "tx_cmdc", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim irq_tx_cmdc %u\n", + p_earc->irq_tx_cmdc); + return ret; + } + } + if (p_earc->irq_tx_dmac > 0) { + ret = request_irq(p_earc->irq_tx_dmac, + earc_tx_dmac_isr, 0, "tx_dmac", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim irq_tx_dmac %u\n", + p_earc->irq_tx_dmac); + return ret; + } + } + } else { + p_earc->tddr = aml_audio_register_toddr(dev, + p_earc->actrl, + earc_ddr_isr, substream); + if (p_earc->tddr == NULL) { + dev_err(dev, "failed to claim to ddr\n"); + return -ENXIO; + } + + ret = request_irq(p_earc->irq_rx_cmdc, + earc_rx_cmdc_isr, 0, "rx_cmdc", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim irq_rx_cmdc %u\n", + p_earc->irq_rx_cmdc); + return ret; + } + ret = request_irq(p_earc->irq_rx_dmac, + earc_rx_dmac_isr, 0, "rx_dmac", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim rx_dmac %u\n", + p_earc->irq_rx_dmac); + return ret; + } + } + + runtime->private_data = p_earc; + + return 0; +} + +static int earc_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = runtime->private_data; + + pr_info("asoc debug: %s-%d\n", __func__, __LINE__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + aml_audio_unregister_frddr(p_earc->dev, substream); + + if (p_earc->irq_tx_cmdc > 0) + free_irq(p_earc->irq_tx_cmdc, p_earc); + + if (p_earc->irq_tx_dmac > 0) + free_irq(p_earc->irq_tx_dmac, p_earc); + } else { + aml_audio_unregister_toddr(p_earc->dev, substream); + free_irq(p_earc->irq_rx_cmdc, p_earc); + free_irq(p_earc->irq_rx_dmac, p_earc); + } + runtime->private_data = NULL; + + return 0; +} + +static int earc_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +} + +static int earc_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + + return 0; +} + +static int earc_trigger(struct snd_pcm_substream *substream, int cmd) +{ + return 0; +} + +static int earc_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = runtime->private_data; + unsigned int start_addr, end_addr, int_addr; + + start_addr = runtime->dma_addr; + end_addr = start_addr + runtime->dma_bytes - 8; + int_addr = frames_to_bytes(runtime, runtime->period_size) / 8; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + struct frddr *fr = p_earc->fddr; + + aml_frddr_set_buf(fr, start_addr, end_addr); + aml_frddr_set_intrpt(fr, int_addr); + } else { + struct toddr *to = p_earc->tddr; + + aml_toddr_set_buf(to, start_addr, end_addr); + aml_toddr_set_intrpt(to, int_addr); + } + + return 0; +} + +static snd_pcm_uframes_t earc_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = runtime->private_data; + unsigned int addr, start_addr; + snd_pcm_uframes_t frames; + + start_addr = runtime->dma_addr; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr = aml_frddr_get_position(p_earc->fddr); + else + addr = aml_toddr_get_position(p_earc->tddr); + + frames = bytes_to_frames(runtime, addr - start_addr); + if (frames > runtime->buffer_size) + frames = 0; + + return frames; +} + +int earc_silence(struct snd_pcm_substream *substream, int channel, + snd_pcm_uframes_t pos, snd_pcm_uframes_t count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + char *ppos; + int n; + + n = frames_to_bytes(runtime, count); + ppos = runtime->dma_area + frames_to_bytes(runtime, pos); + memset(ppos, 0, n); + + return 0; +} + +static int earc_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + return snd_pcm_lib_default_mmap(substream, vma); +} + +static struct snd_pcm_ops earc_ops = { + .open = earc_open, + .close = earc_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = earc_hw_params, + .hw_free = earc_hw_free, + .prepare = earc_prepare, + .trigger = earc_trigger, + .pointer = earc_pointer, + .silence = earc_silence, + .mmap = earc_mmap, +}; + +static int earc_new(struct snd_soc_pcm_runtime *rtd) +{ + return snd_pcm_lib_preallocate_pages_for_all( + rtd->pcm, SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, + PREALLOC_BUFFER_MAX, + PREALLOC_BUFFER_MAX); +} + +struct snd_soc_platform_driver earc_platform = { + .ops = &earc_ops, + .pcm_new = earc_new, +}; + +static int earc_dai_probe(struct snd_soc_dai *cpu_dai) +{ + pr_info("asoc debug: %s-%d\n", __func__, __LINE__); + + return 0; +} + +static int earc_dai_remove(struct snd_soc_dai *cpu_dai) +{ + return 0; +} + +static int earc_dai_prepare( + struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int bit_depth = snd_pcm_format_width(runtime->format); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + struct frddr *fr = p_earc->fddr; + enum frddr_dest dst = frddr_src_get(); + + pr_info("%s Expected frddr dst:%s\n", + __func__, + frddr_src_get_str(dst)); + + aml_frddr_select_dst(fr, dst); + aml_frddr_set_fifos(fr, 0x40, 0x20); + } else { + struct toddr *to = p_earc->tddr; + unsigned int msb = 0, lsb = 0, toddr_type = 0; + unsigned int src = EARCRX_DMAC; + struct toddr_fmt fmt; + + if (bit_depth == 24) + toddr_type = 4; + else + toddr_type = 0; + + pr_info("%s Expected toddr src:%s\n", + __func__, + toddr_src_get_str(src)); + + msb = bit_depth - 1; + + pr_info("%s m:%d, n:%d\n", __func__, msb, lsb); + + fmt.type = toddr_type; + fmt.msb = msb; + fmt.lsb = lsb; + fmt.endian = 0; + fmt.bit_depth = bit_depth; + fmt.ch_num = runtime->channels; + fmt.rate = runtime->rate; + + aml_toddr_select_src(to, src); + aml_toddr_set_format(to, &fmt); + aml_toddr_set_fifos(to, 0x40); + + earcrx_cmdc_init(); + earcrx_dmac_init(); + earc_arc_init(); + + } + + return 0; +} + +static int earc_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dev_info(substream->pcm->card->dev, "eARC/ARC TX enable\n"); + + aml_frddr_enable(p_earc->fddr, true); + } else { + dev_info(substream->pcm->card->dev, "eARC/ARC RX enable\n"); + + aml_toddr_enable(p_earc->tddr, true); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dev_info(substream->pcm->card->dev, "eARC/ARC TX disable\n"); + + aml_frddr_enable(p_earc->fddr, false); + } else { + dev_info(substream->pcm->card->dev, "eARC/ARC RX disable\n"); + + aml_toddr_enable(p_earc->tddr, false); + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int earc_dai_hw_params( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int rate = params_rate(params); + int ret = 0; + + pr_info("%s:rate:%d, sysclk:%d\n", + __func__, + rate, + p_earc->sysclk_freq); + + return ret; +} + +static int earc_dai_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + pr_info("asoc earc_dai_set_fmt, %#x, %p\n", fmt, p_earc); + + return 0; +} + +static int earc_dai_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + p_earc->sysclk_freq = freq; + pr_info("earc_dai_set_sysclk, %d, %d, %d\n", + clk_id, freq, dir); + + clk_set_rate(p_earc->clk_rx_cmdc, 2000000); + clk_set_rate(p_earc->clk_rx_dmac, 24576000); + + pr_info("earc rx cmdc clk:%lu rx dmac clk:%lu\n", + clk_get_rate(p_earc->clk_rx_cmdc), + clk_get_rate(p_earc->clk_rx_dmac)); + + return 0; +} + +static int earc_dai_startup( + struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + int ret; + + /* enable clock gate */ + if (!IS_ERR(p_earc->clk_rx_gate)) { + ret = clk_prepare_enable(p_earc->clk_rx_gate); + if (ret) { + pr_err("Can't enable earc rx_gate: %d\n", ret); + goto err; + } + } + + audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x1 << 6); + + /* enable clock */ + if (!IS_ERR(p_earc->clk_rx_cmdc)) { + ret = clk_prepare_enable(p_earc->clk_rx_cmdc); + if (ret) { + pr_err("Can't enable earc clk_rx_cmdc: %d\n", ret); + goto err; + } + } + if (!IS_ERR(p_earc->clk_rx_dmac)) { + ret = clk_prepare_enable(p_earc->clk_rx_dmac); + if (ret) { + pr_err("Can't enable earc clk_rx_dmac: %d\n", ret); + goto err; + } + } + if (!IS_ERR(p_earc->clk_tx_cmdc)) { + ret = clk_prepare_enable(p_earc->clk_tx_cmdc); + if (ret) { + pr_err("Can't enable earc clk_tx_cmdc: %d\n", ret); + goto err; + } + } + if (!IS_ERR(p_earc->clk_tx_dmac)) { + ret = clk_prepare_enable(p_earc->clk_tx_dmac); + if (ret) { + pr_err("Can't enable earc clk_tx_dmac: %d\n", ret); + goto err; + } + } + + return 0; +err: + pr_err("failed enable clock\n"); + return -EINVAL; +} + + +static void earc_dai_shutdown( + struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + /* disable clock and gate */ + if (!IS_ERR(p_earc->clk_rx_cmdc)) + clk_disable_unprepare(p_earc->clk_rx_cmdc); + if (!IS_ERR(p_earc->clk_rx_dmac)) + clk_disable_unprepare(p_earc->clk_rx_dmac); + if (!IS_ERR(p_earc->clk_tx_cmdc)) + clk_disable_unprepare(p_earc->clk_tx_cmdc); + if (!IS_ERR(p_earc->clk_tx_dmac)) + clk_disable_unprepare(p_earc->clk_tx_dmac); + if (!IS_ERR(p_earc->clk_rx_gate)) + clk_disable_unprepare(p_earc->clk_rx_gate); + + audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x0 << 6); +} + +static struct snd_soc_dai_ops earc_dai_ops = { + .prepare = earc_dai_prepare, + .trigger = earc_dai_trigger, + .hw_params = earc_dai_hw_params, + .set_fmt = earc_dai_set_fmt, + .set_sysclk = earc_dai_set_sysclk, + .startup = earc_dai_startup, + .shutdown = earc_dai_shutdown, +}; + +static struct snd_soc_dai_driver earc_dai[] = { + { + .name = "EARC/ARC", + .id = 0, + .probe = earc_dai_probe, + .remove = earc_dai_remove, + .playback = { + .channels_min = 1, + .channels_max = 32, + .rates = EARC_RATES, + .formats = EARC_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 32, + .rates = EARC_RATES, + .formats = EARC_FORMATS, + }, + .ops = &earc_dai_ops, + }, +}; + +static const struct snd_kcontrol_new earc_controls[] = { + + +}; + +static const struct snd_soc_component_driver earc_component = { + .controls = earc_controls, + .num_controls = ARRAY_SIZE(earc_controls), + .name = DRV_NAME, +}; + +static const struct of_device_id earc_device_id[] = { + { + .compatible = "amlogic, sm1-snd-earc", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, earc_device_id); + +static int earc_platform_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct device_node *node_prt = NULL; + struct platform_device *pdev_parent; + struct device *dev = &pdev->dev; + struct aml_audio_controller *actrl = NULL; + struct earc *p_earc = NULL; + int ret = 0; + + + p_earc = devm_kzalloc(dev, sizeof(struct earc), GFP_KERNEL); + if (!p_earc) + return -ENOMEM; + + p_earc->dev = dev; + dev_set_drvdata(dev, p_earc); + + /* get audio controller */ + node_prt = of_get_parent(node); + if (node_prt == NULL) + return -ENXIO; + + pdev_parent = of_find_device_by_node(node_prt); + of_node_put(node_prt); + actrl = (struct aml_audio_controller *) + platform_get_drvdata(pdev_parent); + p_earc->actrl = actrl; + + /* clock gate */ + p_earc->clk_rx_gate = devm_clk_get(&pdev->dev, "rx_gate"); + if (IS_ERR(p_earc->clk_rx_gate)) { + dev_err(&pdev->dev, + "Can't get earc gate\n"); + return PTR_ERR(p_earc->clk_rx_gate); + } + /* RX */ + p_earc->clk_rx_cmdc = devm_clk_get(&pdev->dev, "rx_cmdc"); + if (IS_ERR(p_earc->clk_rx_cmdc)) { + dev_err(&pdev->dev, + "Can't get clk_rx_cmdc\n"); + return PTR_ERR(p_earc->clk_rx_cmdc); + } + p_earc->clk_rx_dmac = devm_clk_get(&pdev->dev, "rx_dmac"); + if (IS_ERR(p_earc->clk_rx_dmac)) { + dev_err(&pdev->dev, + "Can't get clk_rx_dmac\n"); + return PTR_ERR(p_earc->clk_rx_dmac); + } + p_earc->clk_rx_cmdc_srcpll = devm_clk_get(&pdev->dev, "rx_cmdc_srcpll"); + if (IS_ERR(p_earc->clk_rx_cmdc_srcpll)) { + dev_err(&pdev->dev, + "Can't get clk_rx_cmdc_srcpll\n"); + return PTR_ERR(p_earc->clk_rx_cmdc_srcpll); + } + p_earc->clk_rx_dmac_srcpll = devm_clk_get(&pdev->dev, "rx_dmac_srcpll"); + if (IS_ERR(p_earc->clk_rx_dmac_srcpll)) { + dev_err(&pdev->dev, + "Can't get clk_rx_dmac_srcpll\n"); + return PTR_ERR(p_earc->clk_rx_dmac_srcpll); + } + ret = clk_set_parent(p_earc->clk_rx_cmdc, p_earc->clk_rx_cmdc_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_rx_cmdc parent clock\n"); + ret = PTR_ERR(p_earc->clk_rx_cmdc); + return ret; + } + ret = clk_set_parent(p_earc->clk_rx_dmac, p_earc->clk_rx_dmac_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_rx_dmac parent clock\n"); + ret = PTR_ERR(p_earc->clk_rx_dmac); + return ret; + } + + /* TX */ + p_earc->clk_tx_cmdc = devm_clk_get(&pdev->dev, "tx_cmdc"); + if (IS_ERR(p_earc->clk_tx_cmdc)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + p_earc->clk_tx_dmac = devm_clk_get(&pdev->dev, "tx_dmac"); + if (IS_ERR(p_earc->clk_tx_dmac)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + p_earc->clk_tx_cmdc_srcpll = devm_clk_get(&pdev->dev, "tx_cmdc_srcpll"); + if (IS_ERR(p_earc->clk_tx_cmdc_srcpll)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + p_earc->clk_tx_dmac_srcpll = devm_clk_get(&pdev->dev, "tx_dmac_srcpll"); + if (IS_ERR(p_earc->clk_tx_dmac_srcpll)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + if (!IS_ERR(p_earc->clk_tx_cmdc) && + !IS_ERR(p_earc->clk_tx_cmdc_srcpll)) { + ret = clk_set_parent(p_earc->clk_tx_cmdc, + p_earc->clk_tx_cmdc_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_tx_cmdc parent clock\n"); + ret = PTR_ERR(p_earc->clk_tx_cmdc); + return ret; + } + } + if (!IS_ERR(p_earc->clk_tx_dmac) && + !IS_ERR(p_earc->clk_tx_dmac_srcpll)) { + ret = clk_set_parent(p_earc->clk_tx_dmac, + p_earc->clk_tx_dmac_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_tx_dmac parent clock\n"); + ret = PTR_ERR(p_earc->clk_tx_dmac); + return ret; + } + } + + /* irqs */ + p_earc->irq_rx_cmdc = + platform_get_irq_byname(pdev, "rx_cmdc"); + if (p_earc->irq_rx_cmdc < 0) { + dev_err(dev, "platform get irq rx_cmdc failed\n"); + return p_earc->irq_rx_cmdc; + } + p_earc->irq_rx_dmac = + platform_get_irq_byname(pdev, "rx_dmac"); + if (p_earc->irq_rx_dmac < 0) { + dev_err(dev, "platform get irq rx_dmac failed\n"); + return p_earc->irq_rx_dmac; + } + p_earc->irq_tx_cmdc = + platform_get_irq_byname(pdev, "tx_cmdc"); + if (p_earc->irq_tx_cmdc < 0) + dev_err(dev, "platform get irq tx_cmdc failed, Check whether support eARC TX\n"); + p_earc->irq_tx_dmac = + platform_get_irq_byname(pdev, "tx_dmac"); + if (p_earc->irq_tx_dmac < 0) + dev_err(dev, "platform get irq tx_dmac failed, Check whether support eARC TX\n"); + + ret = snd_soc_register_component(&pdev->dev, + &earc_component, + earc_dai, + ARRAY_SIZE(earc_dai)); + if (ret) { + dev_err(&pdev->dev, + "snd_soc_register_component failed\n"); + return ret; + } + + pr_info("%s, register soc platform\n", __func__); + + return devm_snd_soc_register_platform(dev, &earc_platform); +} + +struct platform_driver earc_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = earc_device_id, + }, + .probe = earc_platform_probe, +}; +module_platform_driver(earc_driver); + +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic eARC/ARC TX/RX ASoc driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("Platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, earc_device_id); diff --git a/sound/soc/amlogic/auge/earc_hw.c b/sound/soc/amlogic/auge/earc_hw.c new file mode 100644 index 000000000000..2974d4e89046 --- /dev/null +++ b/sound/soc/amlogic/auge/earc_hw.c @@ -0,0 +1,87 @@ +/* + * sound/soc/amlogic/auge/earc_hw.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#include + +#include "earc_hw.h" + + +void earcrx_cmdc_init(void) +{ + /* set irq mask */ + earcrx_top_write(EARCRX_CMDC_INT_MASK, + (0 << 15) | /* idle2_int */ + (0 << 14) | /* idle1_int */ + (0 << 13) | /* disc2_int */ + (0 << 12) | /* disc1_int */ + (0 << 11) | /* earc_int */ + (1 << 10) | /* hb_status_int */ + (0 << 9) | /* losthb_int */ + (0 << 8) | /* timeout_int */ + (0 << 7) | /* status_ch_int */ + (0 << 6) | /* int_rec_invalid_id */ + (0 << 5) | /* int_rec_invalid_offset */ + (0 << 4) | /* int_rec_unexp */ + (0 << 3) | /* int_rec_ecc_err */ + (0 << 2) | /* int_rec_parity_err */ + (0 << 1) | /* int_recv_packet */ + (0 << 0) /* int_rec_time_out */ + ); +} + +void earcrx_dmac_init(void) +{ + earcrx_dmac_write(EARCRX_DMAC_TOP_CTRL0, 1 << 31); /* reg_top_work_en */ + earcrx_dmac_write(EARCRX_DMAC_SYNC_CTRL0, + (1 << 31) | /* reg_work_en */ + (1 << 30) | /* reg_rst_afifo_out_n */ + (1 << 29) | /* reg_rst_afifo_in_n */ + (1 << 16) | /* reg_ana_buf_data_sel_en */ + (3 << 12) | /* reg_ana_buf_data_sel */ + (7 << 8) | /* reg_ana_clr_cnt */ + (7 << 4) /* reg_ana_set_cnt */ + ); + earcrx_dmac_write(EARCRX_ERR_CORRECT_CTRL0, + (1 << 29) | /* reg_rst_afifo_out_n */ + (1 << 28) /* reg_rst_afifo_in_n */ + ); + earcrx_dmac_write(EARCRX_DMAC_UBIT_CTRL0, + (1 << 31) | /* reg_work_enable */ + (47 << 16) | /* reg_fifo_thd */ + (1 << 12) | /* reg_user_lr */ + (29 << 0) /* reg_data_bit */ + ); + earcrx_dmac_write(EARCRX_ANA_RST_CTRL0, 1 << 31); + earcrx_dmac_write(EARCRX_ERR_CORRECT_CTRL0, 1 << 31); /* reg_work_en */ +} + +void earc_arc_init(void) +{ + earcrx_dmac_write(EARCRX_SPDIFIN_CTRL0, + (1 << 31) | /* reg_work_en */ + (1 << 30) | /* reg_chnum_sel */ + (1 << 25) | /* reg_findpapb_en */ + (0xFFF<<12) /* reg_nonpcm2pcm_th */ + ); + earcrx_dmac_write(EARCRX_SPDIFIN_CTRL2, + (1 << 14) | /* reg_earc_auto */ + (1 << 13) /* reg_earcin_papb_lr */ + ); + earcrx_dmac_write(EARCRX_SPDIFIN_CTRL3, + (0xEC37<<16) | /* reg_earc_pa_value */ + (0x5A5A<<0) /* reg_earc_pb_value */ + ); +} diff --git a/sound/soc/amlogic/auge/earc_hw.h b/sound/soc/amlogic/auge/earc_hw.h new file mode 100644 index 000000000000..aeb0107daaff --- /dev/null +++ b/sound/soc/amlogic/auge/earc_hw.h @@ -0,0 +1,26 @@ +/* + * sound/soc/amlogic/auge/earc_hw.h + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#ifndef __EARC_HW_H__ +#define __EARC_HW_H__ + +#include "regs.h" +#include "iomap.h" + +extern void earcrx_cmdc_init(void); +extern void earcrx_dmac_init(void); +extern void earc_arc_init(void); +#endif diff --git a/sound/soc/amlogic/auge/iomap.c b/sound/soc/amlogic/auge/iomap.c index 58bef78704ad..e196591b3328 100644 --- a/sound/soc/amlogic/auge/iomap.c +++ b/sound/soc/amlogic/auge/iomap.c @@ -231,6 +231,87 @@ void vad_update_bits(unsigned int reg, } EXPORT_SYMBOL(vad_update_bits); +int earcrx_cmdc_read(unsigned int reg) +{ + int ret, val = 0; + + ret = aml_snd_read(IO_EARCRX_CMDC, reg, &val); + + if (ret) { + pr_err("read audio reg %x error %d\n", reg, ret); + return -1; + } + return val; +} +EXPORT_SYMBOL(earcrx_cmdc_read); + +void earcrx_cmdc_write(unsigned int reg, unsigned int val) +{ + aml_snd_write(IO_EARCRX_CMDC, reg, val); +} +EXPORT_SYMBOL(earcrx_cmdc_write); + +void earcrx_cmdc_update_bits(unsigned int reg, + unsigned int mask, unsigned int val) +{ + aml_snd_update_bits(IO_EARCRX_CMDC, reg, mask, val); +} +EXPORT_SYMBOL(earcrx_cmdc_update_bits); + +int earcrx_dmac_read(unsigned int reg) +{ + int ret, val = 0; + + ret = aml_snd_read(IO_EARCRX_DMAC, reg, &val); + + if (ret) { + pr_err("read audio reg %x error %d\n", reg, ret); + return -1; + } + return val; +} +EXPORT_SYMBOL(earcrx_dmac_read); + +void earcrx_dmac_write(unsigned int reg, unsigned int val) +{ + aml_snd_write(IO_EARCRX_DMAC, reg, val); +} +EXPORT_SYMBOL(earcrx_dmac_write); + +void earcrx_dmac_update_bits(unsigned int reg, + unsigned int mask, unsigned int val) +{ + aml_snd_update_bits(IO_EARCRX_DMAC, reg, mask, val); +} +EXPORT_SYMBOL(earcrx_dmac_update_bits); + +int earcrx_top_read(unsigned int reg) +{ + int ret, val = 0; + + ret = aml_snd_read(IO_EARCRX_TOP, reg, &val); + + if (ret) { + pr_err("read audio reg %x error %d\n", reg, ret); + return -1; + } + return val; +} +EXPORT_SYMBOL(earcrx_top_read); + +void earcrx_top_write(unsigned int reg, unsigned int val) +{ + aml_snd_write(IO_EARCRX_TOP, reg, val); +} +EXPORT_SYMBOL(earcrx_top_write); + +void earcrx_top_update_bits(unsigned int reg, + unsigned int mask, unsigned int val) +{ + aml_snd_update_bits(IO_EARCRX_TOP, reg, mask, val); +} +EXPORT_SYMBOL(earcrx_top_update_bits); + static int snd_iomap_probe(struct platform_device *pdev) { struct resource res; diff --git a/sound/soc/amlogic/auge/iomap.h b/sound/soc/amlogic/auge/iomap.h index ae3c9287cc48..07b8b54c2d89 100644 --- a/sound/soc/amlogic/auge/iomap.h +++ b/sound/soc/amlogic/auge/iomap.h @@ -25,6 +25,9 @@ enum{ IO_EQDRC_BUS, IO_RESET, IO_VAD, + IO_EARCRX_CMDC, + IO_EARCRX_DMAC, + IO_EARCRX_TOP, IO_MAX, }; @@ -58,4 +61,17 @@ extern int vad_read(unsigned int reg); extern void vad_write(unsigned int reg, unsigned int val); extern void vad_update_bits(unsigned int reg, unsigned int mask, unsigned int val); + +extern int earcrx_cmdc_read(unsigned int reg); +extern void earcrx_cmdc_write(unsigned int reg, unsigned int val); +extern void earcrx_cmdc_update_bits(unsigned int reg, + unsigned int mask, unsigned int val); +extern int earcrx_dmac_read(unsigned int reg); +extern void earcrx_dmac_write(unsigned int reg, unsigned int val); +extern void earcrx_dmac_update_bits(unsigned int reg, + unsigned int mask, unsigned int val); +extern int earcrx_top_read(unsigned int reg); +extern void earcrx_top_write(unsigned int reg, unsigned int val); +extern void earcrx_top_update_bits(unsigned int reg, + unsigned int mask, unsigned int val); #endif diff --git a/sound/soc/amlogic/auge/loopback_hw.c b/sound/soc/amlogic/auge/loopback_hw.c index 6e4538cd2f41..15144b9dde7e 100644 --- a/sound/soc/amlogic/auge/loopback_hw.c +++ b/sound/soc/amlogic/auge/loopback_hw.c @@ -71,8 +71,8 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) if (id >= 0 && id <= 2) { /* tdmout_a, tdmout_b, tdmout_c */ - reg_base = EE_AUDIO_TDMOUT_A_SWAP; - offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP; + reg_base = EE_AUDIO_TDMOUT_A_SWAP0; + offset = EE_AUDIO_TDMOUT_B_SWAP0 - EE_AUDIO_TDMOUT_A_SWAP0; } else if (id < 6) { /*lb_cfg->datalb_src for pad tdm in, *pad from tdmin_a, tdmin_b, tdmin_c @@ -115,8 +115,8 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) audiobus_write( reg, lb_cfg->datalb_chmask); - reg_base = EE_AUDIO_TDMIN_A_SWAP; - offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP; + reg_base = EE_AUDIO_TDMIN_A_SWAP0; + offset = EE_AUDIO_TDMIN_B_SWAP0 - EE_AUDIO_TDMIN_A_SWAP0; } else { pr_err("unsupport datalb_src\n"); return; @@ -124,7 +124,7 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) if (lb_cfg->datain_datalb_total > 8) { audiobus_write( - EE_AUDIO_TDMIN_LB_SWAP, + EE_AUDIO_TDMIN_LB_SWAP0, lb_cfg->datalb_chswap); audiobus_write(EE_AUDIO_TDMIN_LB_MASK0, 3); @@ -134,7 +134,7 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) } else { /*swap same as tdmout */ reg = reg_base + offset * id; - audiobus_write(EE_AUDIO_TDMIN_LB_SWAP, + audiobus_write(EE_AUDIO_TDMIN_LB_SWAP0, audiobus_read(reg)); /*mask same as datalb*/ diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index 5dc48e116749..72540b46961f 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -30,6 +30,7 @@ #include "pdm.h" #include "pdm_hw.h" +#include "pdm_match_table.c" #include "audio_io.h" #include "iomap.h" #include "regs.h" @@ -166,6 +167,46 @@ static int pdm_dclk_set_enum( return 0; } +static const char *const pdm_train_texts[] = { + "Disabled", + "Enable", +}; + +static const struct soc_enum pdm_train_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(pdm_train_texts), + pdm_train_texts); + +static int pdm_train_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = p_pdm->train_en; + + return 0; +} + +static int pdm_train_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); + + if (!p_pdm->chipinfo || + !p_pdm->chipinfo->train || + (p_pdm->train_en == ucontrol->value.enumerated.item[0])) + return 0; + + p_pdm->train_en = ucontrol->value.enumerated.item[0]; + + if (p_pdm->clk_on) + pdm_train_en(p_pdm->train_en); + + return 0; +} static const struct snd_kcontrol_new snd_pdm_controls[] = { /* which set */ @@ -184,7 +225,13 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = { pdm_dclk_enum, pdm_dclk_get_enum, pdm_dclk_set_enum), + + SOC_ENUM_EXT("PDM Train", + pdm_train_enum, + pdm_train_get_enum, + pdm_train_set_enum), }; + #if 0 static int pdm_mute_val_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -332,11 +379,19 @@ static irqreturn_t aml_pdm_isr_handler(int irq, void *data) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; + int train_sts = pdm_train_sts(); pr_debug("%s\n", __func__); snd_pcm_period_elapsed(substream); + if (train_sts) { + pr_debug("%s train result:0x%x\n", + __func__, + train_sts); + pdm_train_clr(); + } + return IRQ_HANDLED; } @@ -842,6 +897,9 @@ int aml_pdm_dai_startup(struct snd_pcm_substream *substream, pdm_running_create_controls(card, p_pdm); } #endif + + p_pdm->clk_on = true; + return 0; err: pr_err("failed enable clock\n"); @@ -860,6 +918,8 @@ void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream, } #endif + p_pdm->clk_on = false; + /* disable clock and gate */ clk_disable_unprepare(p_pdm->clk_pdm_dclk); clk_disable_unprepare(p_pdm->clk_pdm_sysclk); @@ -897,32 +957,6 @@ static const struct snd_soc_component_driver aml_pdm_component = { .name = DRV_NAME, }; -static struct pdm_chipinfo g12a_pdm_chipinfo = { - .mute_fn = true, - .truncate_data = false, -}; - -static struct pdm_chipinfo tl1_pdm_chipinfo = { - .mute_fn = true, - .truncate_data = false, -}; - -static const struct of_device_id aml_pdm_device_id[] = { - { - .compatible = "amlogic, axg-snd-pdm", - }, - { - .compatible = "amlogic, g12a-snd-pdm", - .data = &g12a_pdm_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-pdm", - .data = &tl1_pdm_chipinfo, - }, - {} -}; -MODULE_DEVICE_TABLE(of, aml_pdm_device_id); - static int snd_soc_of_get_slot_mask( struct device_node *np, const char *prop_name, diff --git a/sound/soc/amlogic/auge/pdm.h b/sound/soc/amlogic/auge/pdm.h index 43100b836780..39bf6ab11efb 100644 --- a/sound/soc/amlogic/auge/pdm.h +++ b/sound/soc/amlogic/auge/pdm.h @@ -54,6 +54,8 @@ struct pdm_chipinfo { bool mute_fn; /* truncate invalid data when filter init */ bool truncate_data; + /* train */ + bool train; }; struct aml_pdm { @@ -78,12 +80,16 @@ struct aml_pdm { int dclk_idx; /* PCM or Raw Data */ int bypass; - /* PDM clk on/off */ - bool clk_on; /* lane mask in, each lane carries two channels */ int lane_mask_in; + /* PDM clk on/off, only clk on, pdm registers can be accessed */ + bool clk_on; + + /* train */ + bool train_en; + struct pdm_chipinfo *chipinfo; struct snd_kcontrol *controls[PDM_RUN_MAX]; }; diff --git a/sound/soc/amlogic/auge/pdm_hw.c b/sound/soc/amlogic/auge/pdm_hw.c index d814c04f8faf..1b4d2e19e5b2 100644 --- a/sound/soc/amlogic/auge/pdm_hw.c +++ b/sound/soc/amlogic/auge/pdm_hw.c @@ -487,3 +487,24 @@ void pdm_init_truncate_data(int freq) aml_pdm_write(PDM_MASK_NUM, mask_val); } + +void pdm_train_en(bool en) +{ + aml_pdm_update_bits(PDM_CTRL, + 0x1 << 19, + en << 19); +} + +void pdm_train_clr(void) +{ + aml_pdm_update_bits(PDM_CTRL, + 0x1 << 18, + 0x1 << 18); +} + +int pdm_train_sts(void) +{ + int val = aml_pdm_read(PDM_STS); + + return ((val >> 4) & 0xff); +} diff --git a/sound/soc/amlogic/auge/pdm_hw.h b/sound/soc/amlogic/auge/pdm_hw.h index b7ad4737dbd8..b1d8424e8e7a 100644 --- a/sound/soc/amlogic/auge/pdm_hw.h +++ b/sound/soc/amlogic/auge/pdm_hw.h @@ -50,6 +50,10 @@ extern void pdm_set_mute_channel(int mute_chmask); extern void pdm_init_truncate_data(int freq); +extern void pdm_train_en(bool en); +extern void pdm_train_clr(void); +extern int pdm_train_sts(void); + extern int pdm_hcic_shift_gain; extern int pdm_dclk; diff --git a/sound/soc/amlogic/auge/pdm_match_table.c b/sound/soc/amlogic/auge/pdm_match_table.c new file mode 100644 index 000000000000..850b5093f990 --- /dev/null +++ b/sound/soc/amlogic/auge/pdm_match_table.c @@ -0,0 +1,53 @@ +/* + * sound/soc/amlogic/auge/pdm_match_table.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +static struct pdm_chipinfo g12a_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, +}; + +static struct pdm_chipinfo tl1_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, +}; + +static struct pdm_chipinfo sm1_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, + .train = true, +}; + +static const struct of_device_id aml_pdm_device_id[] = { + { + .compatible = "amlogic, axg-snd-pdm", + }, + { + .compatible = "amlogic, g12a-snd-pdm", + .data = &g12a_pdm_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-pdm", + .data = &tl1_pdm_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-pdm", + .data = &sm1_pdm_chipinfo, + }, + + {} +}; +MODULE_DEVICE_TABLE(of, aml_pdm_device_id); diff --git a/sound/soc/amlogic/auge/regs.h b/sound/soc/amlogic/auge/regs.h index 7bf3d4ed5690..2a97ec10431b 100644 --- a/sound/soc/amlogic/auge/regs.h +++ b/sound/soc/amlogic/auge/regs.h @@ -108,6 +108,10 @@ enum clk_sel { #define EE_AUDIO_CLK_SPDIFIN_LB_CTRL 0x02f #define EE_AUDIO_CLK_EQDRC_CTRL0 0x030 #define EE_AUDIO_VAD_CLK_CTRL 0x031 +#define EE_AUDIO_EARCTX_CMDC_CLK_CTRL 0x032 +#define EE_AUDIO_EARCTX_DMAC_CLK_CTRL 0x033 +#define EE_AUDIO_EARCRX_CMDC_CLK_CTRL 0x034 +#define EE_AUDIO_EARCRX_DMAC_CLK_CTRL 0x035 /* * AUDIO TODDR @@ -204,56 +208,93 @@ enum clk_sel { #define EE_AUDIO_LB_STS 0x0b6 #define EE_AUDIO_TDMIN_A_CTRL 0x0c0 -#define EE_AUDIO_TDMIN_A_SWAP 0x0c1 +#define EE_AUDIO_TDMIN_A_SWAP0 0x0c1 +#define EE_AUDIO_TDMIN_A_SWAP1 0x260 #define EE_AUDIO_TDMIN_A_MASK0 0x0c2 #define EE_AUDIO_TDMIN_A_MASK1 0x0c3 #define EE_AUDIO_TDMIN_A_MASK2 0x0c4 #define EE_AUDIO_TDMIN_A_MASK3 0x0c5 +#define EE_AUDIO_TDMIN_A_MASK4 0x261 +#define EE_AUDIO_TDMIN_A_MASK5 0x262 +#define EE_AUDIO_TDMIN_A_MASK6 0x263 +#define EE_AUDIO_TDMIN_A_MASK7 0x264 #define EE_AUDIO_TDMIN_A_STAT 0x0c6 #define EE_AUDIO_TDMIN_A_MUTE_VAL 0x0c7 #define EE_AUDIO_TDMIN_A_MUTE0 0x0c8 #define EE_AUDIO_TDMIN_A_MUTE1 0x0c9 #define EE_AUDIO_TDMIN_A_MUTE2 0x0ca #define EE_AUDIO_TDMIN_A_MUTE3 0x0cb +#define EE_AUDIO_TDMIN_A_MUTE4 0x265 +#define EE_AUDIO_TDMIN_A_MUTE5 0x266 +#define EE_AUDIO_TDMIN_A_MUTE6 0x267 +#define EE_AUDIO_TDMIN_A_MUTE7 0x268 #define EE_AUDIO_TDMIN_B_CTRL 0x0d0 -#define EE_AUDIO_TDMIN_B_SWAP 0x0d1 +#define EE_AUDIO_TDMIN_B_SWAP0 0x0d1 +#define EE_AUDIO_TDMIN_B_SWAP1 0x270 #define EE_AUDIO_TDMIN_B_MASK0 0x0d2 #define EE_AUDIO_TDMIN_B_MASK1 0x0d3 #define EE_AUDIO_TDMIN_B_MASK2 0x0d4 #define EE_AUDIO_TDMIN_B_MASK3 0x0d5 +#define EE_AUDIO_TDMIN_B_MASK4 0x271 +#define EE_AUDIO_TDMIN_B_MASK5 0x272 +#define EE_AUDIO_TDMIN_B_MASK6 0x273 +#define EE_AUDIO_TDMIN_B_MASK7 0x274 #define EE_AUDIO_TDMIN_B_STAT 0x0d6 #define EE_AUDIO_TDMIN_B_MUTE_VAL 0x0d7 #define EE_AUDIO_TDMIN_B_MUTE0 0x0d8 #define EE_AUDIO_TDMIN_B_MUTE1 0x0d9 #define EE_AUDIO_TDMIN_B_MUTE2 0x0da #define EE_AUDIO_TDMIN_B_MUTE3 0x0db +#define EE_AUDIO_TDMIN_B_MUTE4 0x275 +#define EE_AUDIO_TDMIN_B_MUTE5 0x276 +#define EE_AUDIO_TDMIN_B_MUTE6 0x277 +#define EE_AUDIO_TDMIN_B_MUTE7 0x278 #define EE_AUDIO_TDMIN_C_CTRL 0x0e0 +#define EE_AUDIO_TDMIN_C_SWAP0 0x0e1 +#define EE_AUDIO_TDMIN_C_SWAP1 0x280 #define EE_AUDIO_TDMIN_C_SWAP 0x0e1 #define EE_AUDIO_TDMIN_C_MASK0 0x0e2 #define EE_AUDIO_TDMIN_C_MASK1 0x0e3 #define EE_AUDIO_TDMIN_C_MASK2 0x0e4 #define EE_AUDIO_TDMIN_C_MASK3 0x0e5 +#define EE_AUDIO_TDMIN_C_MASK4 0x281 +#define EE_AUDIO_TDMIN_C_MASK5 0x282 +#define EE_AUDIO_TDMIN_C_MASK6 0x283 +#define EE_AUDIO_TDMIN_C_MASK7 0x284 #define EE_AUDIO_TDMIN_C_STAT 0x0e6 #define EE_AUDIO_TDMIN_C_MUTE_VAL 0x0e7 #define EE_AUDIO_TDMIN_C_MUTE0 0x0e8 #define EE_AUDIO_TDMIN_C_MUTE1 0x0e9 #define EE_AUDIO_TDMIN_C_MUTE2 0x0ea #define EE_AUDIO_TDMIN_C_MUTE3 0x0eb +#define EE_AUDIO_TDMIN_C_MUTE4 0x285 +#define EE_AUDIO_TDMIN_C_MUTE5 0x286 +#define EE_AUDIO_TDMIN_C_MUTE6 0x287 +#define EE_AUDIO_TDMIN_C_MUTE7 0x288 #define EE_AUDIO_TDMIN_LB_CTRL 0x0f0 -#define EE_AUDIO_TDMIN_LB_SWAP 0x0f1 +#define EE_AUDIO_TDMIN_LB_SWAP0 0x0f1 +#define EE_AUDIO_TDMIN_LB_SWAP1 0x290 #define EE_AUDIO_TDMIN_LB_MASK0 0x0f2 #define EE_AUDIO_TDMIN_LB_MASK1 0x0f3 #define EE_AUDIO_TDMIN_LB_MASK2 0x0f4 #define EE_AUDIO_TDMIN_LB_MASK3 0x0f5 +#define EE_AUDIO_TDMIN_LB_MASK4 0x291 +#define EE_AUDIO_TDMIN_LB_MASK5 0x292 +#define EE_AUDIO_TDMIN_LB_MASK6 0x293 +#define EE_AUDIO_TDMIN_LB_MASK7 0x294 #define EE_AUDIO_TDMIN_LB_STAT 0x0f6 #define EE_AUDIO_TDMIN_LB_MUTE_VAL 0x0f7 #define EE_AUDIO_TDMIN_LB_MUTE0 0x0f8 #define EE_AUDIO_TDMIN_LB_MUTE1 0x0f9 #define EE_AUDIO_TDMIN_LB_MUTE2 0x0fa #define EE_AUDIO_TDMIN_LB_MUTE3 0x0fb +#define EE_AUDIO_TDMIN_LB_MUTE4 0x295 +#define EE_AUDIO_TDMIN_LB_MUTE5 0x296 +#define EE_AUDIO_TDMIN_LB_MUTE6 0x297 +#define EE_AUDIO_TDMIN_LB_MUTE7 0x298 /* * AUDIO OUTPUT @@ -315,53 +356,89 @@ enum clk_sel { #define EE_AUDIO_TDMOUT_A_CTRL0 0x140 #define EE_AUDIO_TDMOUT_A_CTRL1 0x141 -#define EE_AUDIO_TDMOUT_A_SWAP 0x142 +#define EE_AUDIO_TDMOUT_A_CTRL2 0x2a0 +#define EE_AUDIO_TDMOUT_A_SWAP0 0x142 +#define EE_AUDIO_TDMOUT_A_SWAP1 0x2a1 #define EE_AUDIO_TDMOUT_A_MASK0 0x143 #define EE_AUDIO_TDMOUT_A_MASK1 0x144 #define EE_AUDIO_TDMOUT_A_MASK2 0x145 #define EE_AUDIO_TDMOUT_A_MASK3 0x146 +#define EE_AUDIO_TDMOUT_A_MASK4 0x2a4 +#define EE_AUDIO_TDMOUT_A_MASK5 0x2a5 +#define EE_AUDIO_TDMOUT_A_MASK6 0x2a6 +#define EE_AUDIO_TDMOUT_A_MASK7 0x2a7 #define EE_AUDIO_TDMOUT_A_STAT 0x147 #define EE_AUDIO_TDMOUT_A_GAIN0 0x148 #define EE_AUDIO_TDMOUT_A_GAIN1 0x149 +#define EE_AUDIO_TDMOUT_A_GAIN2 0x2a2 +#define EE_AUDIO_TDMOUT_A_GAIN3 0x2a3 #define EE_AUDIO_TDMOUT_A_MUTE_VAL 0x14a #define EE_AUDIO_TDMOUT_A_MUTE0 0x14b #define EE_AUDIO_TDMOUT_A_MUTE1 0x14c #define EE_AUDIO_TDMOUT_A_MUTE2 0x14d #define EE_AUDIO_TDMOUT_A_MUTE3 0x14e +#define EE_AUDIO_TDMOUT_A_MUTE4 0x2a8 +#define EE_AUDIO_TDMOUT_A_MUTE5 0x2a9 +#define EE_AUDIO_TDMOUT_A_MUTE6 0x2aa +#define EE_AUDIO_TDMOUT_A_MUTE7 0x2ab #define EE_AUDIO_TDMOUT_A_MASK_VAL 0x14f #define EE_AUDIO_TDMOUT_B_CTRL0 0x150 #define EE_AUDIO_TDMOUT_B_CTRL1 0x151 -#define EE_AUDIO_TDMOUT_B_SWAP 0x152 +#define EE_AUDIO_TDMOUT_B_CTRL2 0x2b0 +#define EE_AUDIO_TDMOUT_B_SWAP0 0x152 +#define EE_AUDIO_TDMOUT_B_SWAP1 0x2b1 #define EE_AUDIO_TDMOUT_B_MASK0 0x153 #define EE_AUDIO_TDMOUT_B_MASK1 0x154 #define EE_AUDIO_TDMOUT_B_MASK2 0x155 #define EE_AUDIO_TDMOUT_B_MASK3 0x156 +#define EE_AUDIO_TDMOUT_B_MASK4 0x2b4 +#define EE_AUDIO_TDMOUT_B_MASK5 0x2b5 +#define EE_AUDIO_TDMOUT_B_MASK6 0x2b6 +#define EE_AUDIO_TDMOUT_B_MASK7 0x2b7 #define EE_AUDIO_TDMOUT_B_STAT 0x157 #define EE_AUDIO_TDMOUT_B_GAIN0 0x158 #define EE_AUDIO_TDMOUT_B_GAIN1 0x159 +#define EE_AUDIO_TDMOUT_B_GAIN2 0x2b2 +#define EE_AUDIO_TDMOUT_B_GAIN3 0x2b3 #define EE_AUDIO_TDMOUT_B_MUTE_VAL 0x15a #define EE_AUDIO_TDMOUT_B_MUTE0 0x15b #define EE_AUDIO_TDMOUT_B_MUTE1 0x15c #define EE_AUDIO_TDMOUT_B_MUTE2 0x15d #define EE_AUDIO_TDMOUT_B_MUTE3 0x15e +#define EE_AUDIO_TDMOUT_B_MUTE4 0x2b8 +#define EE_AUDIO_TDMOUT_B_MUTE5 0x2b9 +#define EE_AUDIO_TDMOUT_B_MUTE6 0x2ba +#define EE_AUDIO_TDMOUT_B_MUTE7 0x2bb #define EE_AUDIO_TDMOUT_B_MASK_VAL 0x15f #define EE_AUDIO_TDMOUT_C_CTRL0 0x160 #define EE_AUDIO_TDMOUT_C_CTRL1 0x161 -#define EE_AUDIO_TDMOUT_C_SWAP 0x162 +#define EE_AUDIO_TDMOUT_C_CTRL2 0x2c0 +#define EE_AUDIO_TDMOUT_C_SWAP0 0x162 +#define EE_AUDIO_TDMOUT_C_SWAP1 0x2c1 #define EE_AUDIO_TDMOUT_C_MASK0 0x163 #define EE_AUDIO_TDMOUT_C_MASK1 0x164 #define EE_AUDIO_TDMOUT_C_MASK2 0x165 #define EE_AUDIO_TDMOUT_C_MASK3 0x166 +#define EE_AUDIO_TDMOUT_C_MASK4 0x2c4 +#define EE_AUDIO_TDMOUT_C_MASK5 0x2c5 +#define EE_AUDIO_TDMOUT_C_MASK6 0x2c6 +#define EE_AUDIO_TDMOUT_C_MASK7 0x2c7 #define EE_AUDIO_TDMOUT_C_STAT 0x167 #define EE_AUDIO_TDMOUT_C_GAIN0 0x168 #define EE_AUDIO_TDMOUT_C_GAIN1 0x169 +#define EE_AUDIO_TDMOUT_C_GAIN2 0x2c2 +#define EE_AUDIO_TDMOUT_C_GAIN3 0x2c3 #define EE_AUDIO_TDMOUT_C_MUTE_VAL 0x16a #define EE_AUDIO_TDMOUT_C_MUTE0 0x16b #define EE_AUDIO_TDMOUT_C_MUTE1 0x16c #define EE_AUDIO_TDMOUT_C_MUTE2 0x16d #define EE_AUDIO_TDMOUT_C_MUTE3 0x16e +#define EE_AUDIO_TDMOUT_C_MUTE4 0x2c8 +#define EE_AUDIO_TDMOUT_C_MUTE5 0x2c9 +#define EE_AUDIO_TDMOUT_C_MUTE6 0x2ca +#define EE_AUDIO_TDMOUT_C_MUTE7 0x2cb #define EE_AUDIO_TDMOUT_C_MASK_VAL 0x16f /* @@ -847,4 +924,184 @@ enum clk_sel { #define VAD_IN_SEL1 0x030 #define VAD_TO_DDR 0x031 +/* + * eARC + */ +/* eARC RX CMDC */ +#define EARC_RX_CMDC_TOP_CTRL0 0x000 +#define EARC_RX_CMDC_TOP_CTRL1 0x001 +#define EARC_RX_CMDC_TOP_CTRL2 0x002 +#define EARC_RX_CMDC_TIMER_CTRL0 0x003 +#define EARC_RX_CMDC_TIMER_CTRL1 0x004 +#define EARC_RX_CMDC_TIMER_CTRL2 0x005 +#define EARC_RX_CMDC_TIMER_CTRL3 0x006 +#define EARC_RX_CMDC_VSM_CTRL0 0x007 +#define EARC_RX_CMDC_VSM_CTRL1 0x008 +#define EARC_RX_CMDC_VSM_CTRL2 0x009 +#define EARC_RX_CMDC_VSM_CTRL3 0x00a +#define EARC_RX_CMDC_VSM_CTRL4 0x00b +#define EARC_RX_CMDC_VSM_CTRL5 0x00c +#define EARC_RX_CMDC_VSM_CTRL6 0x00d +#define EARC_RX_CMDC_VSM_CTRL7 0x00e +#define EARC_RX_CMDC_VSM_CTRL8 0x00f +#define EARC_RX_CMDC_VSM_CTRL9 0x010 +#define EARC_RX_CMDC_SENDER_CTRL0 0x011 +#define EARC_RX_CMDC_PACKET_CTRL0 0x012 +#define EARC_RX_CMDC_PACKET_CTRL1 0x013 +#define EARC_RX_CMDC_PACKET_CTRL2 0x014 +#define EARC_RX_CMDC_PACKET_CTRL3 0x015 +#define EARC_RX_CMDC_PACKET_CTRL4 0x016 +#define EARC_RX_CMDC_PACKET_CTRL5 0x017 +#define EARC_RX_CMDC_PACKET_CTRL6 0x018 +#define EARC_RX_CMDC_BIPHASE_CTRL0 0x019 +#define EARC_RX_CMDC_BIPHASE_CTRL1 0x01a +#define EARC_RX_CMDC_BIPHASE_CTRL2 0x01b +#define EARC_RX_CMDC_BIPHASE_CTRL3 0x01c +#define EARC_RX_CMDC_DEVICE_ID_CTRL 0x01d +#define EARC_RX_CMDC_DEVICE_WDATA 0x01e +#define EARC_RX_CMDC_DEVICE_RDATA 0x01f +#define EARC_RX_ANA_CTRL0 0x020 +#define EARC_RX_ANA_CTRL1 0x021 +#define EARC_RX_ANA_CTRL2 0x022 +#define EARC_RX_ANA_CTRL3 0x023 +#define EARC_RX_ANA_CTRL4 0x024 +#define EARC_RX_ANA_CTRL5 0x025 +#define EARC_RX_ANA_STAT0 0x026 +#define EARC_RX_CMDC_STATUS0 0x027 +#define EARC_RX_CMDC_STATUS1 0x028 +#define EARC_RX_CMDC_STATUS2 0x029 +#define EARC_RX_CMDC_STATUS3 0x02a +#define EARC_RX_CMDC_STATUS4 0x02b +#define EARC_RX_CMDC_STATUS5 0x02c +#define EARC_RX_CMDC_STATUS6 0x02d +/* eARC TX CMDC */ +#define EARC_TX_CMDC_TOP_CTRL0 0x030 +#define EARC_TX_CMDC_TOP_CTRL1 0x031 +#define EARC_TX_CMDC_TOP_CTRL2 0x032 +#define EARC_TX_CMDC_TIMER_CTRL0 0x033 +#define EARC_TX_CMDC_TIMER_CTRL1 0x034 +#define EARC_TX_CMDC_TIMER_CTRL2 0x035 +#define EARC_TX_CMDC_TIMER_CTRL3 0x036 +#define EARC_TX_CMDC_VSM_CTRL0 0x037 +#define EARC_TX_CMDC_VSM_CTRL1 0x038 +#define EARC_TX_CMDC_VSM_CTRL2 0x039 +#define EARC_TX_CMDC_VSM_CTRL3 0x03a +#define EARC_TX_CMDC_VSM_CTRL4 0x03b +#define EARC_TX_CMDC_VSM_CTRL5 0x03c +#define EARC_TX_CMDC_VSM_CTRL6 0x03d +#define EARC_TX_CMDC_VSM_CTRL7 0x03e +#define EARC_TX_CMDC_VSM_CTRL8 0x03f +#define EARC_TX_CMDC_VSM_CTRL9 0x041 +#define EARC_TX_CMDC_SENDER_CTRL0 0x042 +#define EARC_TX_CMDC_PACKET_CTRL0 0x043 +#define EARC_TX_CMDC_PACKET_CTRL1 0x044 +#define EARC_TX_CMDC_PACKET_CTRL2 0x045 +#define EARC_TX_CMDC_PACKET_CTRL3 0x046 +#define EARC_TX_CMDC_PACKET_CTRL4 0x047 +#define EARC_TX_CMDC_PACKET_CTRL5 0x048 +#define EARC_TX_CMDC_PACKET_CTRL6 0x049 +#define EARC_TX_CMDC_BIPHASE_CTRL0 0x04a +#define EARC_TX_CMDC_BIPHASE_CTRL1 0x04b +#define EARC_TX_CMDC_BIPHASE_CTRL2 0x04c +#define EARC_TX_CMDC_BIPHASE_CTRL3 0x04d +#define EARC_TX_CMDC_DEVICE_ID_CTRL 0x04e +#define EARC_TX_CMDC_DEVICE_WDATA 0x04f +#define EARC_TX_CMDC_DEVICE_RDATA 0x050 +#define EARC_TX_CMDC_MASTER_CTRL 0x051 +#define EARC_TX_ANA_CTRL0 0x052 +#define EARC_TX_ANA_CTRL1 0x053 +#define EARC_TX_ANA_CTRL2 0x054 +#define EARC_TX_ANA_CTRL3 0x055 +#define EARC_TX_ANA_CTRL4 0x056 +#define EARC_TX_ANA_CTRL5 0x057 +#define EARC_TX_ANA_STAT0 0x058 +#define EARC_TX_CMDC_STATUS0 0x059 +#define EARC_TX_CMDC_STATUS1 0x05a +#define EARC_TX_CMDC_STATUS2 0x05b +#define EARC_TX_CMDC_STATUS3 0x05c +#define EARC_TX_CMDC_STATUS4 0x05d +#define EARC_TX_CMDC_STATUS5 0x05e +#define EARC_TX_CMDC_STATUS6 0x05f +/* eARC RX DMAC */ +#define EARCRX_DMAC_TOP_CTRL0 0x000 +#define EARCRX_DMAC_SYNC_CTRL0 0x001 +#define EARCRX_DMAC_SYNC_STAT0 0x002 +#define EARCRX_SPDIFIN_SAMPLE_CTRL0 0x003 +#define EARCRX_SPDIFIN_SAMPLE_CTRL1 0x004 +#define EARCRX_SPDIFIN_SAMPLE_CTRL2 0x005 +#define EARCRX_SPDIFIN_SAMPLE_CTRL3 0x006 +#define EARCRX_SPDIFIN_SAMPLE_CTRL4 0x007 +#define EARCRX_SPDIFIN_SAMPLE_CTRL5 0x008 +#define EARCRX_SPDIFIN_SAMPLE_STAT0 0x009 +#define EARCRX_SPDIFIN_SAMPLE_STAT1 0x00a +#define EARCRX_SPDIFIN_MUTE_VAL 0x00b +#define EARCRX_SPDIFIN_CTRL0 0x00c +#define EARCRX_SPDIFIN_CTRL1 0x00d +#define EARCRX_SPDIFIN_CTRL2 0x00e +#define EARCRX_SPDIFIN_CTRL3 0x00f +#define EARCRX_SPDIFIN_STAT0 0x010 +#define EARCRX_SPDIFIN_STAT1 0x011 +#define EARCRX_SPDIFIN_STAT2 0x012 +#define EARCRX_DMAC_UBIT_CTRL0 0x013 +#define EARCRX_IU_RDATA 0x014 +#define EARCRX_DMAC_UBIT_STAT0 0x015 +#define EARCRX_ERR_CORRECT_CTRL0 0x016 +#define EARCRX_ERR_CORRECT_STAT0 0x017 +#define EARCRX_ANA_RST_CTRL0 0x018 +#define EARCRX_ANA_RST_CTRL1 0x019 +/* eARC TX DMAC */ +#define EARCTX_DMAC_TOP_CTRL0 0x000 +#define EARCTX_MUTE_VAL 0x001 +#define EARCTX_SPDIFOUT_GAIN0 0x002 +#define EARCTX_SPDIFOUT_GAIN1 0x003 +#define EARCTX_SPDIFOUT_CTRL0 0x004 +#define EARCTX_SPDIFOUT_CTRL1 0x005 +#define EARCTX_SPDIFOUT_PREAMB 0x006 +#define EARCTX_SPDIFOUT_SWAP 0x007 +#define EARCTX_ERR_CORRT_CTRL0 0x008 +#define EARCTX_ERR_CORRT_CTRL1 0x009 +#define EARCTX_ERR_CORRT_CTRL2 0x00a +#define EARCTX_ERR_CORRT_CTRL3 0x00b +#define EARCTX_ERR_CORRT_CTRL4 0x00c +#define EARCTX_ERR_CORRT_STAT0 0x00d +#define EARCTX_SPDIFOUT_CHSTS0 0x00e +#define EARCTX_SPDIFOUT_CHSTS1 0x00f +#define EARCTX_SPDIFOUT_CHSTS2 0x010 +#define EARCTX_SPDIFOUT_CHSTS3 0x011 +#define EARCTX_SPDIFOUT_CHSTS4 0x012 +#define EARCTX_SPDIFOUT_CHSTS5 0x013 +#define EARCTX_SPDIFOUT_CHSTS6 0x014 +#define EARCTX_SPDIFOUT_CHSTS7 0x015 +#define EARCTX_SPDIFOUT_CHSTS8 0x016 +#define EARCTX_SPDIFOUT_CHSTS9 0x017 +#define EARCTX_SPDIFOUT_CHSTSA 0x018 +#define EARCTX_SPDIFOUT_CHSTSB 0x019 +#define EARCTX_FE_CTRL0 0x01a +#define EARCTX_FE_STAT0 0x01b +#define EARCTX_SPDIFOUT_STAT 0x01c +/* eARC RX */ +#define EARCRX_TOP_CTRL0 0x000 +#define EARCRX_DMAC_INT_MASK 0x001 +#define EARCRX_DMAC_INT_PENDING 0x002 +#define EARCRX_CMDC_INT_MASK 0x003 +#define EARCRX_CMDC_INT_PENDING 0x004 +#define EARCRX_ANA_CTRL0 0x005 +#define EARCRX_ANA_CTRL1 0x006 +#define EARCRX_ANA_STAT0 0x007 +#define EARCRX_PLL_CTRL0 0x008 +#define EARCRX_PLL_CTRL1 0x009 +#define EARCRX_PLL_CTRL2 0x00a +#define EARCRX_PLL_CTRL3 0x00b +#define EARCRX_PLL_STAT0 0x00c +/* eARC TX */ +#define EARCTX_TOP_CTRL0 0x000 +#define EARCTX_DMAC_INT_MASK 0x001 +#define EARCTX_DMAC_INT_PENDING 0x002 +#define EARCTX_CMDC_INT_MASK 0x003 +#define EARCTX_CMDC_INT_PENDING 0x004 +#define EARCTX_ANA_CTRL0 0x005 +#define EARCTX_ANA_CTRL1 0x006 +#define EARCTX_ANA_CTRL2 0x007 +#define EARCTX_ANA_STAT0 0x008 + #endif diff --git a/sound/soc/amlogic/auge/sm1,clocks.c b/sound/soc/amlogic/auge/sm1,clocks.c new file mode 100644 index 000000000000..762186e1f22a --- /dev/null +++ b/sound/soc/amlogic/auge/sm1,clocks.c @@ -0,0 +1,376 @@ +/* + * sound/soc/amlogic/auge/sm1,clocks.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#undef pr_fmt +#define pr_fmt(fmt) "sm1_audio_clocks: " fmt + +#include + +#include "audio_clks.h" +#include "regs.h" + +static spinlock_t aclk_lock; + +static const char *const mclk_parent_names[] = { + "mpll0", "mpll1", "mpll2", "mpll3", "hifi_pll", + "fclk_div3", "fclk_div4", "fclk_div5"}; + +static const char *const audioclk_parent_names[] = { + "mclk_a", "mclk_b", "mclk_c", "mclk_d", "mclk_e", + "mclk_f", "i_slv_sclk_a", "i_slv_sclk_b", "i_slv_sclk_c", + "i_slv_sclk_d", "i_slv_sclk_e", "i_slv_sclk_f", "i_slv_sclk_g", + "i_slv_sclk_h", "i_slv_sclk_i", "i_slv_sclk_j"}; + +CLOCK_GATE(audio_ddr_arb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 0); +CLOCK_GATE(audio_pdm, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 1); +CLOCK_GATE(audio_tdmina, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 2); +CLOCK_GATE(audio_tdminb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 3); +CLOCK_GATE(audio_tdminc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 4); +CLOCK_GATE(audio_tdminlb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 5); +CLOCK_GATE(audio_tdmouta, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 6); +CLOCK_GATE(audio_tdmoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 7); +CLOCK_GATE(audio_tdmoutc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 8); +CLOCK_GATE(audio_frddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 9); +CLOCK_GATE(audio_frddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 10); +CLOCK_GATE(audio_frddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 11); +CLOCK_GATE(audio_toddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 12); +CLOCK_GATE(audio_toddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 13); +CLOCK_GATE(audio_toddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 14); +CLOCK_GATE(audio_loopbacka, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 15); +CLOCK_GATE(audio_spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 16); +CLOCK_GATE(audio_spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 17); +CLOCK_GATE(audio_resamplea, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 18); +CLOCK_GATE(audio_reserved0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 19); +CLOCK_GATE(audio_toram, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 20); +CLOCK_GATE(audio_spdifoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 21); +CLOCK_GATE(audio_eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 22); +CLOCK_GATE(audio_reserved1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 23); +CLOCK_GATE(audio_reserved2, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 24); +CLOCK_GATE(audio_reserved3, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 25); +CLOCK_GATE(audio_resampleb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 26); +CLOCK_GATE(audio_tovad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 27); +CLOCK_GATE(audio_audiolocker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 28); +CLOCK_GATE(audio_spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 29); +CLOCK_GATE(audio_reserved4, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 30); +CLOCK_GATE(audio_reserved5, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31); + +CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0); +CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1); +CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2); +CLOCK_GATE(audio_earc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6); + +static struct clk_gate *sm1_audio_clk_gates[] = { + &audio_ddr_arb, + &audio_pdm, + &audio_tdmina, + &audio_tdminb, + &audio_tdminc, + &audio_tdminlb, + &audio_tdmouta, + &audio_tdmoutb, + &audio_tdmoutc, + &audio_frddra, + &audio_frddrb, + &audio_frddrc, + &audio_toddra, + &audio_toddrb, + &audio_toddrc, + &audio_loopbacka, + &audio_spdifin, + &audio_spdifout, + &audio_resamplea, + &audio_reserved0, + &audio_toram, + &audio_spdifoutb, + &audio_eqdrc, + &audio_reserved1, + &audio_reserved2, + &audio_reserved3, + &audio_resampleb, + &audio_tovad, + &audio_audiolocker, + &audio_spdifin_lb, + &audio_reserved4, + &audio_reserved5, + + &audio_frddrd, + &audio_toddrd, + &audio_loopbackb, + &audio_earc, +}; + +/* Array of all clocks provided by this provider */ +static struct clk_hw *sm1_audio_clk_hws[] = { + [CLKID_AUDIO_GATE_DDR_ARB] = &audio_ddr_arb.hw, + [CLKID_AUDIO_GATE_PDM] = &audio_pdm.hw, + [CLKID_AUDIO_GATE_TDMINA] = &audio_tdmina.hw, + [CLKID_AUDIO_GATE_TDMINB] = &audio_tdminb.hw, + [CLKID_AUDIO_GATE_TDMINC] = &audio_tdminc.hw, + [CLKID_AUDIO_GATE_TDMINLB] = &audio_tdminlb.hw, + [CLKID_AUDIO_GATE_TDMOUTA] = &audio_tdmouta.hw, + [CLKID_AUDIO_GATE_TDMOUTB] = &audio_tdmoutb.hw, + [CLKID_AUDIO_GATE_TDMOUTC] = &audio_tdmoutc.hw, + [CLKID_AUDIO_GATE_FRDDRA] = &audio_frddra.hw, + [CLKID_AUDIO_GATE_FRDDRB] = &audio_frddrb.hw, + [CLKID_AUDIO_GATE_FRDDRC] = &audio_frddrc.hw, + [CLKID_AUDIO_GATE_TODDRA] = &audio_toddra.hw, + [CLKID_AUDIO_GATE_TODDRB] = &audio_toddrb.hw, + [CLKID_AUDIO_GATE_TODDRC] = &audio_toddrc.hw, + [CLKID_AUDIO_GATE_LOOPBACKA] = &audio_loopbacka.hw, + [CLKID_AUDIO_GATE_SPDIFIN] = &audio_spdifin.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_A] = &audio_spdifout.hw, + [CLKID_AUDIO_GATE_RESAMPLEA] = &audio_resamplea.hw, + [CLKID_AUDIO_GATE_RESERVED0] = &audio_reserved0.hw, + [CLKID_AUDIO_GATE_TORAM] = &audio_toram.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_B] = &audio_spdifoutb.hw, + [CLKID_AUDIO_GATE_EQDRC] = &audio_eqdrc.hw, + [CLKID_AUDIO_GATE_RESERVED1] = &audio_reserved1.hw, + [CLKID_AUDIO_GATE_RESERVED2] = &audio_reserved2.hw, + [CLKID_AUDIO_GATE_RESERVED3] = &audio_reserved3.hw, + [CLKID_AUDIO_GATE_RESAMPLEB] = &audio_resampleb.hw, + [CLKID_AUDIO_GATE_TOVAD] = &audio_tovad.hw, + [CLKID_AUDIO_GATE_AUDIOLOCKER] = &audio_audiolocker.hw, + [CLKID_AUDIO_GATE_SPDIFIN_LB] = &audio_spdifin_lb.hw, + [CLKID_AUDIO_GATE_RESERVED4] = &audio_reserved4.hw, + [CLKID_AUDIO_GATE_RESERVED5] = &audio_reserved5.hw, + + [CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw, + [CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw, + [CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw, + [CLKID_AUDIO_GATE_EARCRX] = &audio_earc.hw, +}; + +static int sm1_clk_gates_init(struct clk **clks, void __iomem *iobase) +{ + int clkid; + + if (ARRAY_SIZE(sm1_audio_clk_gates) != MCLK_BASE) { + pr_err("check clk gates number\n"); + return -EINVAL; + } + + for (clkid = 0; clkid < MCLK_BASE; clkid++) { + sm1_audio_clk_gates[clkid]->reg = iobase; + clks[clkid] = clk_register(NULL, sm1_audio_clk_hws[clkid]); + WARN_ON(IS_ERR_OR_NULL(clks[clkid])); + } + + return 0; +} + +/* mclk_a */ +CLOCK_COM_MUX(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 31); +/* mclk_b */ +CLOCK_COM_MUX(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 31); +/* mclk_c */ +CLOCK_COM_MUX(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 31); +/* mclk_d */ +CLOCK_COM_MUX(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 31); +/* mclk_e */ +CLOCK_COM_MUX(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 31); +/* mclk_f */ +CLOCK_COM_MUX(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 31); +/* spdifin */ +CLOCK_COM_MUX(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0, 8); +CLOCK_COM_GATE(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 31); +/* spdifout */ +CLOCK_COM_MUX(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 31); +/* audio resample_a */ +CLOCK_COM_MUX(resample_a, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8); +CLOCK_COM_GATE(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31); +/* audio locker_out */ +CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24); +CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8); +CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31); +/* audio locker_in */ +CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8); +CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8); +CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15); +/* pdmin0 */ +CLOCK_COM_MUX(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0x7, 24); +CLOCK_COM_DIV(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0, 16); +CLOCK_COM_GATE(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 31); +/* pdmin1 */ +CLOCK_COM_MUX(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0x7, 24); +CLOCK_COM_DIV(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0, 16); +CLOCK_COM_GATE(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 31); +/* spdifout b*/ +CLOCK_COM_MUX(spdifout_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio resample_b */ +CLOCK_COM_MUX(resample_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0, 8); +CLOCK_COM_GATE(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 31); +/* spdifin_lb, div is a fake */ +CLOCK_COM_MUX(spdifin_lb, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x1, 30); +CLOCK_COM_DIV(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 29); +CLOCK_COM_GATE(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio eqdrc */ +CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24); +CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16); +CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31); +/* audio vad */ +CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31); +/* EARC TX CMDC */ +CLOCK_COM_MUX(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 31); +/* EARC TX DMAC */ +CLOCK_COM_MUX(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 31); +/* EARC RX CMDC */ +CLOCK_COM_MUX(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 31); +/* EARC RX DMAC */ +CLOCK_COM_MUX(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 31); + +static int sm1_clks_init(struct clk **clks, void __iomem *iobase) +{ + IOMAP_COM_CLK(mclk_a, iobase); + clks[CLKID_AUDIO_MCLK_A] = REGISTER_CLK_COM(mclk_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_A])); + + IOMAP_COM_CLK(mclk_b, iobase); + clks[CLKID_AUDIO_MCLK_B] = REGISTER_CLK_COM(mclk_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_B])); + + IOMAP_COM_CLK(mclk_c, iobase); + clks[CLKID_AUDIO_MCLK_C] = REGISTER_CLK_COM(mclk_c); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_C])); + + IOMAP_COM_CLK(mclk_d, iobase); + clks[CLKID_AUDIO_MCLK_D] = REGISTER_CLK_COM(mclk_d); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_D])); + + IOMAP_COM_CLK(mclk_e, iobase); + clks[CLKID_AUDIO_MCLK_E] = REGISTER_CLK_COM(mclk_e); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_E])); + + IOMAP_COM_CLK(mclk_f, iobase); + clks[CLKID_AUDIO_MCLK_F] = REGISTER_CLK_COM(mclk_f); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_F])); + + IOMAP_COM_CLK(spdifin, iobase); + clks[CLKID_AUDIO_SPDIFIN] = REGISTER_CLK_COM(spdifin); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN])); + + IOMAP_COM_CLK(spdifout, iobase); + clks[CLKID_AUDIO_SPDIFOUT_A] = REGISTER_CLK_COM(spdifout); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_A])); + + IOMAP_COM_CLK(resample_a, iobase); + clks[CLKID_AUDIO_RESAMPLE_A] = REGISTER_AUDIOCLK_COM(resample_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_A])); + + IOMAP_COM_CLK(locker_out, iobase); + clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT])); + + IOMAP_COM_CLK(locker_in, iobase); + clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN])); + + IOMAP_COM_CLK(pdmin0, iobase); + clks[CLKID_AUDIO_PDMIN0] = REGISTER_CLK_COM(pdmin0); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN0])); + + IOMAP_COM_CLK(pdmin1, iobase); + clks[CLKID_AUDIO_PDMIN1] = REGISTER_CLK_COM(pdmin1); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN1])); + + IOMAP_COM_CLK(spdifout_b, iobase); + clks[CLKID_AUDIO_SPDIFOUT_B] = REGISTER_CLK_COM(spdifout_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_B])); + + IOMAP_COM_CLK(resample_b, iobase); + clks[CLKID_AUDIO_RESAMPLE_B] = REGISTER_AUDIOCLK_COM(resample_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_B])); + + IOMAP_COM_CLK(spdifin_lb, iobase); + clks[CLKID_AUDIO_SPDIFIN_LB] = REGISTER_CLK_COM(spdifin_lb); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_LB])); + + IOMAP_COM_CLK(eqdrc, iobase); + clks[CLKID_AUDIO_EQDRC] = REGISTER_CLK_COM(eqdrc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_EQDRC])); + + IOMAP_COM_CLK(vad, iobase); + clks[CLKID_AUDIO_VAD] = REGISTER_CLK_COM(vad); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_VAD])); + + IOMAP_COM_CLK(earctx_cmdc, iobase); + clks[CLKID_EARCTX_CMDC] = REGISTER_CLK_COM(earctx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_CMDC])); + + IOMAP_COM_CLK(earctx_dmac, iobase); + clks[CLKID_EARCTX_DMAC] = REGISTER_CLK_COM(earctx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_DMAC])); + + IOMAP_COM_CLK(earcrx_cmdc, iobase); + clks[CLKID_EARCRX_CMDC] = REGISTER_CLK_COM(earcrx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_CMDC])); + + IOMAP_COM_CLK(earcrx_dmac, iobase); + clks[CLKID_EARCRX_DMAC] = REGISTER_CLK_COM(earcrx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_DMAC])); + + return 0; +} + +struct audio_clk_init sm1_audio_clks_init = { + .clk_num = NUM_AUDIO_CLKS, + .clk_gates = sm1_clk_gates_init, + .clks = sm1_clks_init, +}; diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index ba24b1fe333d..dbc00d86f268 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -33,15 +33,15 @@ #include #include - #include "ddr_mngr.h" #include "spdif_hw.h" +#include "spdif_match_table.c" #include "audio_utils.h" #include "resample.h" #include "resample_hw.h" #include "spdif.h" -#define DRV_NAME "aml_spdif" +#define DRV_NAME "snd_spdif" /* Debug by PTM when bringup */ /*#define __PTM_SPDIF_CLK__*/ @@ -51,28 +51,8 @@ /*#define __SPDIFIN_AUDIO_TYPE_HW__*/ -struct spdif_chipinfo { - enum SPDIF_ID id; - - /* add ch_cnt to ch_num */ - bool chnum_en; - /* - * axg, clear all irq bits - * after axg, such as g12a, clear each bits - * Reg_clr_interrupt[7:0] for each bit of irq_status[7:0]; - */ - bool clr_irq_all_bits; - /* no PaPb irq */ - bool irq_no_papb; - /* reg_hold_start_en; 1: add delay to match TDM out when share buff; */ - bool hold_start; - /* eq/drc */ - bool eq_drc_en; - /* pc, pd interrupt is separated. */ - bool pcpd_separated; - /* same source, spdif re-enable */ - bool same_src_spdif_reen; -}; +static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir); enum SPDIF_SRC { SPDIFIN_PAD = 0, @@ -1575,70 +1555,6 @@ static int aml_spdif_parse_of(struct platform_device *pdev) return 0; } -struct spdif_chipinfo axg_spdif_chipinfo = { - .id = SPDIF_A, - .irq_no_papb = true, - .clr_irq_all_bits = true, - .pcpd_separated = true, -}; - -struct spdif_chipinfo g12a_spdif_a_chipinfo = { - .id = SPDIF_A, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, - .pcpd_separated = true, -}; - -struct spdif_chipinfo g12a_spdif_b_chipinfo = { - .id = SPDIF_B, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, - .pcpd_separated = true, -}; - -struct spdif_chipinfo tl1_spdif_a_chipinfo = { - .id = SPDIF_A, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, - .same_src_spdif_reen = true, -}; - -struct spdif_chipinfo tl1_spdif_b_chipinfo = { - .id = SPDIF_B, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, - .same_src_spdif_reen = true, -}; - -static const struct of_device_id aml_spdif_device_id[] = { - { - .compatible = "amlogic, axg-snd-spdif", - .data = &axg_spdif_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-spdif-a", - .data = &g12a_spdif_a_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-spdif-b", - .data = &g12a_spdif_b_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-spdif-a", - .data = &tl1_spdif_a_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-spdif-b", - .data = &tl1_spdif_b_chipinfo, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, aml_spdif_device_id); - static int aml_spdif_platform_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; diff --git a/sound/soc/amlogic/auge/spdif_match_table.c b/sound/soc/amlogic/auge/spdif_match_table.c new file mode 100644 index 000000000000..025301585292 --- /dev/null +++ b/sound/soc/amlogic/auge/spdif_match_table.c @@ -0,0 +1,126 @@ +/* + * sound/soc/amlogic/auge/spdif_match_table.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#define SPDIF_A 0 +#define SPDIF_B 1 + +struct spdif_chipinfo { + unsigned int id; + + /* add ch_cnt to ch_num */ + bool chnum_en; + /* + * axg, clear all irq bits + * after axg, such as g12a, clear each bits + * Reg_clr_interrupt[7:0] for each bit of irq_status[7:0]; + */ + bool clr_irq_all_bits; + /* no PaPb irq */ + bool irq_no_papb; + /* reg_hold_start_en; 1: add delay to match TDM out when share buff; */ + bool hold_start; + /* eq/drc */ + bool eq_drc_en; + /* pc, pd interrupt is separated. */ + bool pcpd_separated; + /* same source, spdif re-enable */ + bool same_src_spdif_reen; +}; + +struct spdif_chipinfo axg_spdif_chipinfo = { + .id = SPDIF_A, + .irq_no_papb = true, + .clr_irq_all_bits = true, + .pcpd_separated = true, +}; + +struct spdif_chipinfo g12a_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, + .pcpd_separated = true, +}; + +struct spdif_chipinfo g12a_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, + .pcpd_separated = true, +}; + +struct spdif_chipinfo tl1_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo tl1_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo sm1_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo sm1_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +static const struct of_device_id aml_spdif_device_id[] = { + { + .compatible = "amlogic, axg-snd-spdif", + .data = &axg_spdif_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-spdif-a", + .data = &g12a_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-spdif-b", + .data = &g12a_spdif_b_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-spdif-a", + .data = &tl1_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-spdif-b", + .data = &tl1_spdif_b_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-spdif-a", + .data = &sm1_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-spdif-b", + .data = &sm1_spdif_b_chipinfo, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, aml_spdif_device_id); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 4349e5664428..d71769c7f4f4 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -42,16 +42,12 @@ #include "vad.h" #include "spdif_hw.h" +#include "tdm_match_table.c" /*#define __PTM_TDM_CLK__*/ -#define DRV_NAME "aml_tdm" - -#define TDM_A 0 -#define TDM_B 1 -#define TDM_C 2 -#define LANE_MAX 4 +#define DRV_NAME "snd_tdm" static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir); @@ -79,29 +75,6 @@ static void dump_pcm_setting(struct pcm_setting *setting) pr_debug("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in); } -struct tdm_chipinfo { - /* device id */ - unsigned int id; - - /* no eco, sclk_ws_inv for out */ - bool sclk_ws_inv; - - /* output en (oe) for pinmux */ - bool oe_fn; - - /* clk pad */ - bool clk_pad_ctl; - - /* same source */ - bool same_src_fn; - - /* same source, spdif re-enable */ - bool same_src_spdif_reen; - - /* ACODEC_ADC function */ - bool adc_fn; -}; - struct aml_tdm { struct pcm_setting setting; struct pinctrl *pin_ctl; @@ -124,6 +97,7 @@ struct aml_tdm { int samesource_sel; /* share buffer lane setting from DTS */ int lane_ss; + int mclk_pad; /* virtual link for i2s to hdmitx */ int i2s2hdmitx; int acodec_adc; @@ -132,6 +106,7 @@ struct aml_tdm { uint last_fmt; bool en_share; + unsigned int lane_cnt; }; static const struct snd_pcm_hardware aml_tdm_hardware = { @@ -706,6 +681,7 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, unsigned int lane_mask; unsigned int set_num = 0; unsigned int i; + //unsigned int swap0_val = 0, swap1_val = 0, lane_chs = 0; pr_debug("asoc channels:%d, slots:%d\n", channels, setting->slots); @@ -717,6 +693,7 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, return -EINVAL; } +#if 1 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { // set lanes mask acordingly if (p_tdm->chipinfo @@ -734,7 +711,7 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, } swap_val = 0x76543210; aml_tdm_set_lane_channel_swap(p_tdm->actrl, - stream, p_tdm->id, swap_val); + stream, p_tdm->id, swap_val, 0x0); } else { if (p_tdm->chipinfo && p_tdm->chipinfo->oe_fn @@ -756,29 +733,83 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, } aml_tdm_set_lane_channel_swap(p_tdm->actrl, - stream, p_tdm->id, swap_val); + stream, p_tdm->id, swap_val, 0x0); } +#else + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (p_tdm->chipinfo + && p_tdm->chipinfo->oe_fn + && p_tdm->setting.lane_oe_mask_out) + lane_mask = setting->lane_oe_mask_out; + else + lane_mask = setting->lane_mask_out; + } else { + if (p_tdm->chipinfo + && p_tdm->chipinfo->oe_fn + && p_tdm->setting.lane_oe_mask_in) + lane_mask = setting->lane_oe_mask_in; + else + lane_mask = setting->lane_mask_in; + } + /* lane mask */ + for (i = 0; i < 4; i++) { + if (((1 << i) & lane_mask) && lanes) { + aml_tdm_set_channel_mask(p_tdm->actrl, + stream, p_tdm->id, i, setting->tx_mask); + lanes--; + } + } + + /* channel swap */ + for (i = 0; i < p_tdm->lane_cnt; i++) { + if ((1 << i) & lane_mask) { + swap0_val |= (1 << (2 * i)) - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + swap0_val |= (1 << (2 * i + 1)) - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + + if (i >= LANE_MAX1) { + swap1_val |= (1 << (2 * (i - LANE_MAX1))) - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + swap1_val |= (1 << (2 * (i - LANE_MAX1) + 1)) + - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + } + } + } + aml_tdm_set_lane_channel_swap(p_tdm->actrl, + stream, p_tdm->id, swap0_val, swap1_val); +#endif return 0; } static int aml_tdm_set_clk_pad(struct aml_tdm *p_tdm) { - unsigned int mpad, mclk_sel; + int mpad_offset = 0; + /* mclk pad + * does mclk need? + * mclk from which mclk source, mclk_a/b/c/d/e/f + * mclk pad controlled by dts, mclk source according to id + */ + if (p_tdm->chipinfo && (!p_tdm->chipinfo->mclkpad_no_offset)) + mpad_offset = 1; - // TODO: update pad - if (p_tdm->id >= 1) { - mpad = p_tdm->id - 1; - mclk_sel = p_tdm->id; - } else { - mpad = 0; - mclk_sel = 0; - } - - /* clk pad */ - aml_tdm_clk_pad_select(p_tdm->actrl, mpad, mclk_sel, - p_tdm->id, p_tdm->clk_sel); + aml_tdm_clk_pad_select(p_tdm->actrl, + p_tdm->mclk_pad, + mpad_offset, + p_tdm->id, + p_tdm->id, + p_tdm->clk_sel); return 0; } @@ -815,7 +846,7 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - if (p_tdm->chipinfo && p_tdm->chipinfo->clk_pad_ctl) { + if (p_tdm->chipinfo && (!p_tdm->chipinfo->no_mclkpad_ctrl)) { ret = aml_tdm_set_clk_pad(p_tdm); if (ret) return ret; @@ -852,7 +883,7 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, } if (!p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { - pr_debug("%s(), enable mclk for %s", __func__, cpu_dai->name); + pr_debug("%s(), enable mclk for %s\n", __func__, cpu_dai->name); ret = clk_prepare_enable(p_tdm->mclk); if (ret) { pr_err("Can't enable mclk: %d\n", ret); @@ -1280,113 +1311,6 @@ static const struct snd_soc_component_driver aml_tdm_component = { .name = DRV_NAME, }; -struct tdm_chipinfo axg_tdma_chipinfo = { - .id = TDM_A, -}; - -struct tdm_chipinfo axg_tdmb_chipinfo = { - .id = TDM_B, -}; - -struct tdm_chipinfo axg_tdmc_chipinfo = { - .id = TDM_C, -}; - -struct tdm_chipinfo g12a_tdma_chipinfo = { - .id = TDM_A, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, -}; - -struct tdm_chipinfo g12a_tdmb_chipinfo = { - .id = TDM_B, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, -}; - -struct tdm_chipinfo g12a_tdmc_chipinfo = { - .id = TDM_C, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, -}; - -struct tdm_chipinfo tl1_tdma_chipinfo = { - .id = TDM_A, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, - .adc_fn = true, - .same_src_spdif_reen = true, -}; - -struct tdm_chipinfo tl1_tdmb_chipinfo = { - .id = TDM_B, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, - .adc_fn = true, - .same_src_spdif_reen = true, -}; - -struct tdm_chipinfo tl1_tdmc_chipinfo = { - .id = TDM_C, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, - .adc_fn = true, - .same_src_spdif_reen = true, -}; - -static const struct of_device_id aml_tdm_device_id[] = { - { - .compatible = "amlogic, axg-snd-tdma", - .data = &axg_tdma_chipinfo, - }, - { - .compatible = "amlogic, axg-snd-tdmb", - .data = &axg_tdmb_chipinfo, - }, - { - .compatible = "amlogic, axg-snd-tdmc", - .data = &axg_tdmc_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-tdma", - .data = &g12a_tdma_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-tdmb", - .data = &g12a_tdmb_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-tdmc", - .data = &g12a_tdmc_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-tdma", - .data = &tl1_tdma_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-tdmb", - .data = &tl1_tdmb_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-tdmc", - .data = &tl1_tdmc_chipinfo, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, aml_tdm_device_id); - static int check_channel_mask(const char *str) { int ret = -1; @@ -1456,6 +1380,10 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) } p_tdm->chipinfo = p_chipinfo; p_tdm->id = p_chipinfo->id; + if (!p_chipinfo->lane_cnt) + p_chipinfo->lane_cnt = LANE_MAX1; + else + p_tdm->lane_cnt = p_chipinfo->lane_cnt; pr_info("%s, tdm ID = %u\n", __func__, p_tdm->id); /* get audio controller */ @@ -1587,6 +1515,12 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) /*return PTR_ERR(p_tdm->pin_ctl);*/ } + /* mclk pad ctrl */ + ret = of_property_read_u32(node, "mclk_pad", + &p_tdm->mclk_pad); + if (ret < 0) + p_tdm->mclk_pad = -1; /* not use mclk in defalut. */ + p_tdm->dev = dev; /* For debug to disable share buffer */ p_tdm->en_share = 1; diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index 24c079bfe39f..85594e98238c 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -545,10 +545,20 @@ void aml_tdm_set_channel_mask( unsigned int offset, reg; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; + if (lane >= LANE_MAX1) + offset = EE_AUDIO_TDMOUT_B_MASK4 + - EE_AUDIO_TDMOUT_A_MASK4; + else + offset = EE_AUDIO_TDMOUT_B_MASK0 + - EE_AUDIO_TDMOUT_A_MASK0; reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; } else { - offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; + if (lane >= LANE_MAX1) + offset = EE_AUDIO_TDMIN_B_MASK4 + - EE_AUDIO_TDMIN_A_MASK4; + else + offset = EE_AUDIO_TDMIN_B_MASK0 + - EE_AUDIO_TDMIN_A_MASK0; reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; } @@ -557,27 +567,39 @@ void aml_tdm_set_channel_mask( void aml_tdm_set_lane_channel_swap( struct aml_audio_controller *actrl, - int stream, int index, int swap) + int stream, int index, int swap0, int swap1) { unsigned int offset, reg; + pr_debug("\t %s swap0 = %#x, swap1 = %#x\n", + (stream == SNDRV_PCM_STREAM_PLAYBACK) ? "tdmout" : "tdmin", + swap0, + swap1); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - // set lanes mask acordingly - offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; - reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; + offset = EE_AUDIO_TDMOUT_B_SWAP0 + - EE_AUDIO_TDMOUT_A_SWAP0; + reg = EE_AUDIO_TDMOUT_A_SWAP0 + offset * index; + aml_audiobus_write(actrl, reg, swap0); - pr_debug("\ttdmout swap val = %#x\n", swap); - offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP; - reg = EE_AUDIO_TDMOUT_A_SWAP + offset * index; - aml_audiobus_write(actrl, reg, swap); + if (swap1) { + offset = EE_AUDIO_TDMOUT_B_SWAP1 + - EE_AUDIO_TDMOUT_A_SWAP1; + reg = EE_AUDIO_TDMOUT_A_SWAP1 + offset * index; + aml_audiobus_write(actrl, reg, swap1); + } } else { - offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; - reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; + offset = EE_AUDIO_TDMIN_B_SWAP0 + - EE_AUDIO_TDMIN_A_SWAP0; + reg = EE_AUDIO_TDMIN_A_SWAP0 + offset * index; + aml_audiobus_write(actrl, reg, swap0); - pr_debug("\ttdmin swap val = %#x\n", swap); - offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP; - reg = EE_AUDIO_TDMIN_A_SWAP + offset * index; - aml_audiobus_write(actrl, reg, swap); + if (swap1) { + offset = EE_AUDIO_TDMIN_B_SWAP1 + - EE_AUDIO_TDMIN_A_SWAP1; + reg = EE_AUDIO_TDMIN_A_SWAP1 + offset * index; + aml_audiobus_write(actrl, reg, swap1); + } } } @@ -649,27 +671,39 @@ void aml_tdmout_enable_gain(int tdmout_id, int en) void aml_tdm_clk_pad_select( struct aml_audio_controller *actrl, - int mpad, int mclk_sel, + int mpad, int mpad_offset, int mclk_sel, int tdm_index, int clk_sel) { unsigned int reg, mask_offset, val_offset; - // TODO: fix mclk - if (mpad == 0) { - mask_offset = 0x7 << 0; - val_offset = mclk_sel << 0; - } else if (mpad == 1) { - mask_offset = 0x7 << 4; - val_offset = mclk_sel << 4; - } else { - pr_err("unknown tdm mpad:%d\n", mpad); - return; - } - reg = EE_AUDIO_MST_PAD_CTRL0(0); - aml_audiobus_update_bits(actrl, reg, - mask_offset, val_offset); + if (mpad >= 0) { + switch (mpad) { + case 0: + mask_offset = 0x7 << 0; + val_offset = mclk_sel << 0; + break; + case 1: + mask_offset = 0x7 << 4; + val_offset = mclk_sel << 4; + break; + default: + mask_offset = 0; + val_offset = 0; + pr_info("unknown tdm mpad:%d\n", mpad); + break; + } - reg = EE_AUDIO_MST_PAD_CTRL1(0); + reg = EE_AUDIO_MST_PAD_CTRL0(mpad_offset); + if (actrl) + aml_audiobus_update_bits(actrl, reg, + mask_offset, val_offset); + else + audiobus_update_bits(reg, + mask_offset, val_offset); + } else + pr_warn("mclk is not configured\n"); + + reg = EE_AUDIO_MST_PAD_CTRL1(mpad_offset); switch (tdm_index) { case 0: mask_offset = 0x7 << 16 | 0x7 << 0; @@ -684,12 +718,15 @@ void aml_tdm_clk_pad_select( val_offset = clk_sel << 24 | clk_sel << 8; break; default: - pr_err("unknown tdm index:%d\n", tdm_index); + pr_err("unknown mclk pad, tdm index:%d\n", tdm_index); return; } - aml_audiobus_update_bits(actrl, reg, - mask_offset, val_offset); - + if (actrl) + aml_audiobus_update_bits(actrl, reg, + mask_offset, val_offset); + else + audiobus_update_bits(reg, + mask_offset, val_offset); } void i2s_to_hdmitx_ctrl(int tdm_index) diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index 04a7b83be8c6..68cedb46fad5 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -21,6 +21,15 @@ #include "audio_io.h" #include "regs.h" +#define TDM_A 0 +#define TDM_B 1 +#define TDM_C 2 + +#define LANE_MAX0 2 +#define LANE_MAX1 4 +#define LANE_MAX2 6 +#define LANE_MAX3 8 + // TODO: fix me, now based by tl1 enum tdmin_src { PAD_TDMINA_DIN = 0, @@ -118,7 +127,7 @@ extern void aml_tdm_set_channel_mask( extern void aml_tdm_set_lane_channel_swap( struct aml_audio_controller *actrl, - int stream, int index, int swap); + int stream, int index, int swap0, int swap1); extern void aml_tdm_set_bclk_ratio( struct aml_audio_controller *actrl, @@ -139,7 +148,7 @@ extern void aml_tdmout_get_aed_info(int tdmout_id, extern void aml_tdm_clk_pad_select( struct aml_audio_controller *actrl, - int mpad, int mclk_sel, + int mpad, int mpad_offset, int mclk_sel, int tdm_index, int clk_sel); extern void i2s_to_hdmitx_ctrl(int tdm_index); diff --git a/sound/soc/amlogic/auge/tdm_match_table.c b/sound/soc/amlogic/auge/tdm_match_table.c new file mode 100644 index 000000000000..fd56921b4f45 --- /dev/null +++ b/sound/soc/amlogic/auge/tdm_match_table.c @@ -0,0 +1,186 @@ +/* + * sound/soc/amlogic/auge/tdm_match_table.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +struct tdm_chipinfo { + /* device id */ + unsigned int id; + + /* lane max count */ + unsigned int lane_cnt; + + /* no eco, sclk_ws_inv for out */ + bool sclk_ws_inv; + + /* output en (oe) for pinmux */ + bool oe_fn; + + /* clk pad */ + bool no_mclkpad_ctrl; + + /* same source */ + bool same_src_fn; + + /* same source, spdif re-enable */ + bool same_src_spdif_reen; + + /* ACODEC_ADC function */ + bool adc_fn; + + /* mclk pad offset */ + bool mclkpad_no_offset; +}; + + +struct tdm_chipinfo axg_tdma_chipinfo = { + .id = TDM_A, + .no_mclkpad_ctrl = true, +}; + +struct tdm_chipinfo axg_tdmb_chipinfo = { + .id = TDM_B, + .no_mclkpad_ctrl = true, +}; + +struct tdm_chipinfo axg_tdmc_chipinfo = { + .id = TDM_C, + .no_mclkpad_ctrl = true, +}; + +struct tdm_chipinfo g12a_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .mclkpad_no_offset = true, +}; + +struct tdm_chipinfo g12a_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .mclkpad_no_offset = true, +}; + +struct tdm_chipinfo g12a_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .mclkpad_no_offset = true, +}; + +struct tdm_chipinfo tl1_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, +}; + +struct tdm_chipinfo tl1_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, +}; + +struct tdm_chipinfo tl1_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, +}; + +struct tdm_chipinfo sm1_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX0, +}; + +struct tdm_chipinfo sm1_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX3, +}; + +struct tdm_chipinfo sm1_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX1, +}; + +static const struct of_device_id aml_tdm_device_id[] = { + { + .compatible = "amlogic, axg-snd-tdma", + .data = &axg_tdma_chipinfo, + }, + { + .compatible = "amlogic, axg-snd-tdmb", + .data = &axg_tdmb_chipinfo, + }, + { + .compatible = "amlogic, axg-snd-tdmc", + .data = &axg_tdmc_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-tdma", + .data = &g12a_tdma_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-tdmb", + .data = &g12a_tdmb_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-tdmc", + .data = &g12a_tdmc_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-tdma", + .data = &tl1_tdma_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-tdmb", + .data = &tl1_tdmb_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-tdmc", + .data = &tl1_tdmc_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-tdma", + .data = &sm1_tdma_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-tdmb", + .data = &sm1_tdmb_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-tdmc", + .data = &sm1_tdmc_chipinfo, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, aml_tdm_device_id); diff --git a/sound/soc/amlogic/auge/vad_dev.c b/sound/soc/amlogic/auge/vad_dev.c index 9af68606481a..178632629c48 100644 --- a/sound/soc/amlogic/auge/vad_dev.c +++ b/sound/soc/amlogic/auge/vad_dev.c @@ -155,7 +155,7 @@ static int __init vad_init(void) goto err2; } - pr_info("Register %s", DRV_NAME); + pr_info("Register %s\n", DRV_NAME); return 0; err2: From cb813f2cf20600a5674f958239c8d91e0234e813 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Sat, 23 Mar 2019 18:12:24 +0800 Subject: [PATCH 0633/1060] audio: auge: support earc rx for sm1 [1/2] PD#SWPL-5389 Problem: earc rx dmac reset and clk issue Solution: fix earc rx dmac and clk Verify: ac200 Change-Id: Ie8e5582f1ee358a8cf694965c9963ae1eeb6685a Signed-off-by: Xing Wang --- sound/soc/amlogic/auge/earc.c | 21 +++++++++--- sound/soc/amlogic/auge/earc_hw.c | 59 ++++++++++++++++++++++++++------ sound/soc/amlogic/auge/earc_hw.h | 1 + 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/sound/soc/amlogic/auge/earc.c b/sound/soc/amlogic/auge/earc.c index 124ac6919739..355e7db3a8b3 100644 --- a/sound/soc/amlogic/auge/earc.c +++ b/sound/soc/amlogic/auge/earc.c @@ -373,7 +373,9 @@ static int earc_dai_prepare( unsigned int src = EARCRX_DMAC; struct toddr_fmt fmt; - if (bit_depth == 24) + if (bit_depth == 32) + toddr_type = 3; + else if (bit_depth == 24) toddr_type = 4; else toddr_type = 0; @@ -382,9 +384,14 @@ static int earc_dai_prepare( __func__, toddr_src_get_str(src)); - msb = bit_depth - 1; + msb = 28 - 1; + if (bit_depth == 16) + lsb = 28 - bit_depth; + else + lsb = 4; - pr_info("%s m:%d, n:%d\n", __func__, msb, lsb); + pr_info("%s m:%d, n:%d, toddr type:%d\n", + __func__, msb, lsb, toddr_type); fmt.type = toddr_type; fmt.msb = msb; @@ -424,6 +431,8 @@ static int earc_dai_trigger(struct snd_pcm_substream *substream, int cmd, dev_info(substream->pcm->card->dev, "eARC/ARC RX enable\n"); aml_toddr_enable(p_earc->tddr, true); + + earc_rx_enable(true); } break; case SNDRV_PCM_TRIGGER_STOP: @@ -436,6 +445,8 @@ static int earc_dai_trigger(struct snd_pcm_substream *substream, int cmd, } else { dev_info(substream->pcm->card->dev, "eARC/ARC RX disable\n"); + earc_rx_enable(false); + aml_toddr_enable(p_earc->tddr, false); } break; @@ -481,8 +492,8 @@ static int earc_dai_set_sysclk(struct snd_soc_dai *cpu_dai, pr_info("earc_dai_set_sysclk, %d, %d, %d\n", clk_id, freq, dir); - clk_set_rate(p_earc->clk_rx_cmdc, 2000000); - clk_set_rate(p_earc->clk_rx_dmac, 24576000); + clk_set_rate(p_earc->clk_rx_cmdc, 10000000); + clk_set_rate(p_earc->clk_rx_dmac, 250000000); pr_info("earc rx cmdc clk:%lu rx dmac clk:%lu\n", clk_get_rate(p_earc->clk_rx_cmdc), diff --git a/sound/soc/amlogic/auge/earc_hw.c b/sound/soc/amlogic/auge/earc_hw.c index 2974d4e89046..0b217bb2cad0 100644 --- a/sound/soc/amlogic/auge/earc_hw.c +++ b/sound/soc/amlogic/auge/earc_hw.c @@ -40,32 +40,26 @@ void earcrx_cmdc_init(void) (0 << 1) | /* int_recv_packet */ (0 << 0) /* int_rec_time_out */ ); + + earcrx_top_write(EARCRX_ANA_CTRL0, 0x90884814); + earcrx_top_write(EARCRX_PLL_CTRL3, 0x242000); + earcrx_top_write(EARCRX_PLL_CTRL0, 0x10800400); } void earcrx_dmac_init(void) { - earcrx_dmac_write(EARCRX_DMAC_TOP_CTRL0, 1 << 31); /* reg_top_work_en */ earcrx_dmac_write(EARCRX_DMAC_SYNC_CTRL0, - (1 << 31) | /* reg_work_en */ - (1 << 30) | /* reg_rst_afifo_out_n */ - (1 << 29) | /* reg_rst_afifo_in_n */ (1 << 16) | /* reg_ana_buf_data_sel_en */ (3 << 12) | /* reg_ana_buf_data_sel */ (7 << 8) | /* reg_ana_clr_cnt */ (7 << 4) /* reg_ana_set_cnt */ ); - earcrx_dmac_write(EARCRX_ERR_CORRECT_CTRL0, - (1 << 29) | /* reg_rst_afifo_out_n */ - (1 << 28) /* reg_rst_afifo_in_n */ - ); earcrx_dmac_write(EARCRX_DMAC_UBIT_CTRL0, - (1 << 31) | /* reg_work_enable */ (47 << 16) | /* reg_fifo_thd */ (1 << 12) | /* reg_user_lr */ (29 << 0) /* reg_data_bit */ ); earcrx_dmac_write(EARCRX_ANA_RST_CTRL0, 1 << 31); - earcrx_dmac_write(EARCRX_ERR_CORRECT_CTRL0, 1 << 31); /* reg_work_en */ } void earc_arc_init(void) @@ -85,3 +79,48 @@ void earc_arc_init(void) (0x5A5A<<0) /* reg_earc_pb_value */ ); } + +void earc_rx_enable(bool enable) +{ + if (enable) { + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 1 << 30, /* reg_rst_afifo_out_n */ + 1 << 30); + + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 1 << 29, /* reg_rst_afifo_in_n */ + 0x1 << 29); + + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 1 << 29, /* reg_rst_afifo_out_n */ + 1 << 29 + ); + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 1 << 28, /* reg_rst_afifo_in_n */ + 1 << 28 /* reg_rst_afifo_in_n */ + ); + } else { + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 0x3 << 29, + 0x0 << 29); + + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 0x3 << 28, 0x0 << 28); + } + + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 1 << 31, /* reg_work_en */ + enable << 31); + + earcrx_dmac_update_bits(EARCRX_DMAC_UBIT_CTRL0, + 1 << 31, /* reg_work_enable */ + enable << 31); + + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 1 << 31, + enable << 31); /* reg_work_en */ + + earcrx_dmac_update_bits(EARCRX_DMAC_TOP_CTRL0, + 1 << 31, + enable << 31); /* reg_top_work_en */ +} diff --git a/sound/soc/amlogic/auge/earc_hw.h b/sound/soc/amlogic/auge/earc_hw.h index aeb0107daaff..1630733add2f 100644 --- a/sound/soc/amlogic/auge/earc_hw.h +++ b/sound/soc/amlogic/auge/earc_hw.h @@ -23,4 +23,5 @@ extern void earcrx_cmdc_init(void); extern void earcrx_dmac_init(void); extern void earc_arc_init(void); +extern void earc_rx_enable(bool enable); #endif From 43aed42f18f93d6cb4f4ea6debb781b0f8636306 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Thu, 28 Mar 2019 18:31:04 +0800 Subject: [PATCH 0634/1060] audio: support 16ch i2s playback for SM1 [1/1] PD#SWPL-5430 Problem: new function lane 6 and lane 8 Solution: support max 16 channel playback Verify: sm1_ac200, verify pass Change-Id: I3af42a0b68bca8804afa042ad4a506a379b9bf86 Signed-off-by: Zhe Wang Conflicts: sound/soc/amlogic/auge/tdm.c --- .../arm/boot/dts/amlogic/sm1_s905d3_ac200.dts | 14 +++- sound/soc/amlogic/auge/sm1,clocks.c | 6 +- sound/soc/amlogic/auge/tdm.c | 82 ++++++++++++------- sound/soc/amlogic/auge/tdm_hw.c | 53 +++++++++--- sound/soc/amlogic/auge/tdm_hw.h | 6 +- sound/soc/codecs/amlogic/ad82584f.c | 2 +- sound/soc/codecs/amlogic/aml_codec_t9015.c | 2 +- 7 files changed, 115 insertions(+), 50 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts index bfeb017456e4..4cd84e09025b 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -1100,6 +1100,8 @@ #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <0 1 0 0>; dai-tdm-lane-slot-mask-out = <1 0 0 0>; + //dai-tdm-lane-slot-mask-in = <0 0 0 0 0 0 0 0>; + //dai-tdm-lane-slot-mask-out = <1 1 1 1 1 1 1 1>; dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 @@ -1304,11 +1306,21 @@ drive-strength = <2>; }; }; + tdmout_b: tdmout_b { - mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + mux { /* GPIOA_1, GPIOA_2, GPIOA_3, GPIOA_4, */ + /* GPIOA_5, GPIOA_6, GPIOA_7, GPIOA_8, */ + /* GPIOA_9, GPIOA_0*/ groups = "tdmb_sclk", "tdmb_fs", "tdmb_dout0"; + //"tdmb_dout1", + //"tdmb_dout2", + //"tdmb_dout3_a", + //"tdmb_dout4_a", + //"tdmb_dout5_a", + //"tdmb_dout6_a", + //"tdmb_dout7_a0"; function = "tdmb_out"; drive-strength = <2>; }; diff --git a/sound/soc/amlogic/auge/sm1,clocks.c b/sound/soc/amlogic/auge/sm1,clocks.c index 762186e1f22a..6a234b2f3552 100644 --- a/sound/soc/amlogic/auge/sm1,clocks.c +++ b/sound/soc/amlogic/auge/sm1,clocks.c @@ -70,7 +70,7 @@ CLOCK_GATE(audio_reserved5, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31); CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0); CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1); CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2); -CLOCK_GATE(audio_earc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6); +CLOCK_GATE(audio_earcrx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6); static struct clk_gate *sm1_audio_clk_gates[] = { &audio_ddr_arb, @@ -109,7 +109,7 @@ static struct clk_gate *sm1_audio_clk_gates[] = { &audio_frddrd, &audio_toddrd, &audio_loopbackb, - &audio_earc, + &audio_earcrx, }; /* Array of all clocks provided by this provider */ @@ -150,7 +150,7 @@ static struct clk_hw *sm1_audio_clk_hws[] = { [CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw, [CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw, [CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw, - [CLKID_AUDIO_GATE_EARCRX] = &audio_earc.hw, + [CLKID_AUDIO_GATE_EARCRX] = &audio_earcrx.hw, }; static int sm1_clk_gates_init(struct clk **clks, void __iomem *iobase) diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index d71769c7f4f4..cfaf181b3f87 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -123,7 +123,7 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { .period_bytes_max = 256 * 1024 * 2, .periods_min = 2, .periods_max = 1024, - .buffer_bytes_max = 512 * 1024 * 2, + .buffer_bytes_max = 1024 * 1024, .rate_min = 8000, .rate_max = 384000, @@ -592,7 +592,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, aml_tdm_enable(p_tdm->actrl, substream->stream, p_tdm->id, true); udelay(100); - aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, false); + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, + false, p_tdm->lane_cnt); if (p_tdm->chipinfo && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) @@ -625,7 +626,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, 0, substream->runtime->dma_bytes); mdelay(3); aml_frddr_enable(p_tdm->fddr, 0); - aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, true); + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, + true, p_tdm->lane_cnt); if (p_tdm->chipinfo && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) @@ -677,32 +679,31 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, unsigned int channels, int stream) { struct pcm_setting *setting = &p_tdm->setting; - unsigned int lanes, swap_val; + unsigned int lanes, swap_val = 0, swap_val1 = 0; unsigned int lane_mask; unsigned int set_num = 0; unsigned int i; - //unsigned int swap0_val = 0, swap1_val = 0, lane_chs = 0; - pr_debug("asoc channels:%d, slots:%d\n", channels, setting->slots); + pr_debug("asoc channels:%d, slots:%d, lane_cnt:%d\n", + channels, setting->slots, p_tdm->lane_cnt); - swap_val = 0; - // calc lanes by channels and slots + /* calc lanes by channels and slots */ lanes = (channels - 1) / setting->slots + 1; - if (lanes > 4) { + if (lanes > p_tdm->lane_cnt) { pr_err("lanes setting error\n"); return -EINVAL; } #if 1 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - // set lanes mask acordingly + /* set lanes mask acordingly */ if (p_tdm->chipinfo && p_tdm->chipinfo->oe_fn && p_tdm->setting.lane_oe_mask_out) lane_mask = setting->lane_oe_mask_out; else lane_mask = setting->lane_mask_out; - for (i = 0; i < 4; i++) { + for (i = 0; i < p_tdm->lane_cnt; i++) { if (((1 << i) & lane_mask) && lanes) { aml_tdm_set_channel_mask(p_tdm->actrl, stream, p_tdm->id, i, setting->tx_mask); @@ -710,8 +711,10 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, } } swap_val = 0x76543210; + if (p_tdm->lane_cnt > LANE_MAX1) + swap_val1 = 0xfedcba98; aml_tdm_set_lane_channel_swap(p_tdm->actrl, - stream, p_tdm->id, swap_val, 0x0); + stream, p_tdm->id, swap_val, swap_val1); } else { if (p_tdm->chipinfo && p_tdm->chipinfo->oe_fn @@ -720,20 +723,31 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, else lane_mask = setting->lane_mask_in; - for (i = 0; i < 4; i++) { + for (i = 0; i < p_tdm->lane_cnt; i++) { if (i < lanes) aml_tdm_set_channel_mask(p_tdm->actrl, stream, p_tdm->id, i, setting->rx_mask); - if ((1 << i) & lane_mask) { - // each lane only L/R masked - pr_info("tdmin set lane %d\n", i); - swap_val |= (i * 2) << (set_num++ * 4); - swap_val |= (i * 2 + 1) << (set_num++ * 4); + if (((1 << i) & lane_mask) && (i < LANE_MAX1)) { + /* each lane only L/R masked */ + pr_debug("tdmin set lane %d\n", i); + swap_val |= (i * 2) << + (set_num++ * LANE_MAX1); + swap_val |= (i * 2 + 1) << + (set_num++ * LANE_MAX1); + } + if (((1 << i) & lane_mask) && (i >= LANE_MAX1) + && (i < LANE_MAX3)) { + /* each lane only L/R masked */ + pr_debug("tdmin set lane %d\n", i); + swap_val1 |= (i * 2) << + (set_num++ * LANE_MAX1); + swap_val1 |= (i * 2 + 1) << + (set_num++ * LANE_MAX1); } } aml_tdm_set_lane_channel_swap(p_tdm->actrl, - stream, p_tdm->id, swap_val, 0x0); + stream, p_tdm->id, swap_val, swap_val1); } #else @@ -1110,6 +1124,7 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, lanes_lb_cnt); pr_debug("\tslots(%d), slot_width(%d)\n", slots, slot_width); + p_tdm->setting.tx_mask = tx_mask; p_tdm->setting.rx_mask = rx_mask; p_tdm->setting.slots = slots; @@ -1174,11 +1189,11 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, in_src = ACODEC_ADC; } - if (in_lanes >= 0 && in_lanes <= 4) + if (in_lanes > 0 && in_lanes <= LANE_MAX3) aml_tdm_set_slot_in(p_tdm->actrl, p_tdm->id, in_src, slot_width); - if (out_lanes >= 0 && out_lanes <= 4) + if (out_lanes > 0 && out_lanes <= LANE_MAX3) aml_tdm_set_slot_out(p_tdm->actrl, p_tdm->id, slots, slot_width, force_oe, oe_val); @@ -1218,11 +1233,14 @@ static int aml_dai_tdm_mute_stream(struct snd_soc_dai *cpu_dai, struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - pr_debug("tdm playback mute: %d\n", mute); - //aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, mute); + pr_debug("tdm playback mute: %d, lane_cnt = %d\n", + mute, p_tdm->lane_cnt); + //aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, + // mute, p_tdm->lane_cnt); } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { pr_debug("tdm capture mute: %d\n", mute); - aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, mute); + aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, + mute, p_tdm->lane_cnt); } return 0; } @@ -1272,7 +1290,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = { .remove = aml_dai_tdm_remove, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rates = AML_DAI_TDM_RATES, .formats = AML_DAI_TDM_FORMATS, }, @@ -1292,7 +1310,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = { .remove = aml_dai_tdm_remove, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rates = AML_DAI_TDM_RATES, .formats = AML_DAI_TDM_FORMATS, }, @@ -1382,9 +1400,10 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) p_tdm->id = p_chipinfo->id; if (!p_chipinfo->lane_cnt) p_chipinfo->lane_cnt = LANE_MAX1; - else - p_tdm->lane_cnt = p_chipinfo->lane_cnt; - pr_info("%s, tdm ID = %u\n", __func__, p_tdm->id); + + p_tdm->lane_cnt = p_chipinfo->lane_cnt; + pr_info("%s, tdm ID = %u, lane_cnt = %d\n", __func__, + p_tdm->id, p_tdm->lane_cnt); /* get audio controller */ node_prt = of_get_parent(node); @@ -1487,6 +1506,11 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) if (ret < 0) p_tdm->setting.lane_lb_mask_in = 0x0; + dev_info(&pdev->dev, + "lane_mask_out = %x, lane_oe_mask_out = %x\n", + p_tdm->setting.lane_mask_out, + p_tdm->setting.lane_oe_mask_out); + p_tdm->clk = devm_clk_get(&pdev->dev, "clk_srcpll"); if (IS_ERR(p_tdm->clk)) { dev_err(&pdev->dev, "Can't retrieve mpll2 clock\n"); diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index 85594e98238c..97dc1d593438 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -545,21 +545,27 @@ void aml_tdm_set_channel_mask( unsigned int offset, reg; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (lane >= LANE_MAX1) + if (lane >= LANE_MAX1) { offset = EE_AUDIO_TDMOUT_B_MASK4 - EE_AUDIO_TDMOUT_A_MASK4; - else + reg = EE_AUDIO_TDMOUT_A_MASK4 + offset * index; + lane -= LANE_MAX1; + } else { offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; - reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; + reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; + } } else { - if (lane >= LANE_MAX1) + if (lane >= LANE_MAX1) { offset = EE_AUDIO_TDMIN_B_MASK4 - EE_AUDIO_TDMIN_A_MASK4; - else + reg = EE_AUDIO_TDMIN_A_MASK4 + offset * index; + lane -= LANE_MAX1; + } else { offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; - reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; + reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; + } } aml_audiobus_write(actrl, reg + lane, mask); @@ -749,12 +755,13 @@ void i2s_to_hdmitx_disable(void) void aml_tdm_mute_playback( struct aml_audio_controller *actrl, int tdm_index, - bool mute) + bool mute, + int lane_cnt) { unsigned int offset, reg; unsigned int mute_mask = 0xffffffff; unsigned int mute_val = 0; - int i = 0, lanes = 4; + int i = 0; if (mute) mute_val = 0xffffffff; @@ -762,19 +769,29 @@ void aml_tdm_mute_playback( offset = EE_AUDIO_TDMOUT_B_MUTE0 - EE_AUDIO_TDMOUT_A_MUTE0; reg = EE_AUDIO_TDMOUT_A_MUTE0 + offset * tdm_index; - for (i = 0; i < lanes; i++) + for (i = 0; i < LANE_MAX1; i++) aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); + + if (lane_cnt > LANE_MAX1) { + offset = EE_AUDIO_TDMOUT_B_MUTE4 + - EE_AUDIO_TDMOUT_A_MUTE4; + reg = EE_AUDIO_TDMOUT_A_MUTE4 + offset * tdm_index; + for (i = 0; i < LANE_MAX1; i++) + aml_audiobus_update_bits(actrl, reg + i, + mute_mask, mute_val); + } } void aml_tdm_mute_capture( struct aml_audio_controller *actrl, int tdm_index, - bool mute) + bool mute, + int lane_cnt) { unsigned int offset, reg; unsigned int mute_mask = 0xffffffff; unsigned int mute_val = 0; - int i = 0, lanes = 4; + int i = 0; if (mute) mute_val = 0xffffffff; @@ -782,7 +799,17 @@ void aml_tdm_mute_capture( offset = EE_AUDIO_TDMIN_B_MUTE0 - EE_AUDIO_TDMIN_A_MUTE0; reg = EE_AUDIO_TDMIN_A_MUTE0 + offset * tdm_index; - for (i = 0; i < lanes; i++) - aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); + for (i = 0; i < LANE_MAX1; i++) + aml_audiobus_update_bits(actrl, reg + i, + mute_mask, mute_val); + + if (lane_cnt > LANE_MAX1) { + offset = EE_AUDIO_TDMIN_B_MUTE4 + - EE_AUDIO_TDMIN_A_MUTE4; + reg = EE_AUDIO_TDMIN_A_MUTE4 + offset * tdm_index; + for (i = 0; i < LANE_MAX1; i++) + aml_audiobus_update_bits(actrl, reg + i, + mute_mask, mute_val); + } } diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index 68cedb46fad5..b47bf1e7c793 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -156,9 +156,11 @@ extern void i2s_to_hdmitx_disable(void); void aml_tdm_mute_playback( struct aml_audio_controller *actrl, int index, - bool mute); + bool mute, + int lane_cnt); void aml_tdm_mute_capture( struct aml_audio_controller *actrl, int tdm_index, - bool mute); + bool mute, + int lane_cnt); #endif diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index da82c73f6565..60b2598032fe 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -728,7 +728,7 @@ static struct snd_soc_dai_driver ad82584f_dai = { .playback = { .stream_name = "HIFI Playback", .channels_min = 2, - .channels_max = 8, + .channels_max = 16, .rates = AD82584F_RATES, .formats = AD82584F_FORMATS, }, diff --git a/sound/soc/codecs/amlogic/aml_codec_t9015.c b/sound/soc/codecs/amlogic/aml_codec_t9015.c index 1ec6891d9912..533f0f4192bf 100644 --- a/sound/soc/codecs/amlogic/aml_codec_t9015.c +++ b/sound/soc/codecs/amlogic/aml_codec_t9015.c @@ -480,7 +480,7 @@ struct snd_soc_dai_driver aml_T9015_audio_dai[] = { .playback = { .stream_name = "HIFI Playback", .channels_min = 2, - .channels_max = 8, + .channels_max = 16, .rates = T9015_AUDIO_STEREO_RATES, .formats = T9015_AUDIO_FORMATS, }, From 24b7a869563e4f58cafb22d98ed53ee7a5501763 Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Fri, 5 Apr 2019 14:42:48 +0800 Subject: [PATCH 0635/1060] audio: TM2 audio basic function bringup [1/1] PD#SWPL-6721 Problem: TM2 bringup Solution: audio basic function bringup Verify: Verified on T962e2_ab311 Change-Id: Ic48ded3964ea87e40c4d683d71a50bbdc1975f91 Signed-off-by: Zhe Wang Conflicts: arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts --- MAINTAINERS | 1 - arch/arm/boot/dts/amlogic/mesontm2.dtsi | 17 +- .../arm/boot/dts/amlogic/tm2_t962e2_ab311.dts | 118 ++++-- .../arm/boot/dts/amlogic/tm2_t962e2_ab319.dts | 151 ++++--- .../arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 116 ++++-- .../arm/boot/dts/amlogic/tm2_t962x3_ab309.dts | 131 +++--- arch/arm64/boot/dts/amlogic/mesontm2.dtsi | 19 +- .../boot/dts/amlogic/tm2_t962e2_ab311.dts | 157 +++++-- .../boot/dts/amlogic/tm2_t962e2_ab319.dts | 153 ++++--- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 145 +++++-- .../boot/dts/amlogic/tm2_t962x3_ab309.dts | 151 ++++--- .../dt-bindings/clock/amlogic,tm2-audio-clk.h | 97 +++++ sound/soc/amlogic/auge/Makefile | 1 + sound/soc/amlogic/auge/audio_clks.c | 4 + sound/soc/amlogic/auge/audio_clks.h | 1 + sound/soc/amlogic/auge/audio_controller.c | 1 + sound/soc/amlogic/auge/card.c | 9 +- sound/soc/amlogic/auge/ddr_mngr.c | 6 +- sound/soc/amlogic/auge/earc.c | 5 +- sound/soc/amlogic/auge/pdm_match_table.c | 10 + sound/soc/amlogic/auge/spdif_match_table.c | 22 + sound/soc/amlogic/auge/tdm_match_table.c | 36 ++ sound/soc/amlogic/auge/tm2,clocks.c | 392 ++++++++++++++++++ 23 files changed, 1337 insertions(+), 406 deletions(-) create mode 100644 include/dt-bindings/clock/amlogic,tm2-audio-clk.h create mode 100644 sound/soc/amlogic/auge/tm2,clocks.c diff --git a/MAINTAINERS b/MAINTAINERS index f0721818943c..c4ba5ed396a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14434,7 +14434,6 @@ F: include/linux/amlogic/meson_cooldev.h AMLOGIC G12A Audio DRIVER M: Xing Wang F: sound/soc/amlogic/auge/* -F: sound/soc/codec/amlogic/* AMLOGIC G12A BL_EXTERN LP8556 DRIVER M: Weiming Liu diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 24206c8a855a..9fe495b604dd 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include "mesong12a-bifrost.dtsi" #include @@ -634,7 +634,7 @@ ranges = <0x0 0xff600000 0x10000>; clkaudio:audio_clocks { - compatible = "amlogic, tl1-audio-clocks"; + compatible = "amlogic, tm2-audio-clocks"; #clock-cells = <1>; reg = <0x0 0xb0>; }; @@ -676,13 +676,22 @@ reg = <0xFF601400 0x400>; }; eqdrc_base { - reg = <0xFF602000 0x2000>; + reg = <0xFF602000 0x1000>; }; reset_base { reg = <0xFFD01000 0x1000>; }; vad_base { - reg = <0xFF601800 0x800>; + reg = <0xFF601800 0x400>; + }; + earcrx_cdmc_base { + reg = <0xFF603800 0x30>; + }; + earcrx_dmac_base { + reg = <0xFF603C00 0x20>; + }; + earcrx_top_base { + reg = <0xFF603E00 0x10>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts index 84bee34048c9..198bcf976d6f 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -287,7 +287,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -361,7 +361,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -417,6 +416,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -438,6 +438,17 @@ }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1327,7 +1338,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; @@ -1366,7 +1377,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1381,7 +1392,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1398,8 +1409,27 @@ status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL1 @@ -1439,7 +1469,7 @@ }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1451,34 +1481,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1486,6 +1493,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1508,7 +1546,7 @@ /* max 0xff, each bit for one channel */ channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1529,7 +1567,7 @@ */ resample_module = <3>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1596,25 +1634,27 @@ /* audio pin mux */ tdma_mclk: tdma_mclk { - mux { /* GPIOZ_0 */ - groups = "mclk0_z"; + mux { /* GPIOH_4 */ + groups = "mclk0_h"; function = "mclk0"; }; }; tdmout_a: tdmout_a { - mux { /* GPIOH_5, GPIOH_6, GPIOH_7 */ + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ groups = "tdma_fs_h", "tdma_sclk_h", - "tdma_dout0_h"; + "tdma_dout0_h", + "tdma_dout1_h"; function = "tdma_out"; bias-pull-down; }; }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts index d82054c016bd..05e180596693 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -256,6 +256,7 @@ reg = <0xff632000 0x1c>; tdmout_index = <0>; tdmin_index = <0>; + dat1_ch_sel = <1>; }; aml_dtv_demod { @@ -284,7 +285,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -322,7 +323,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -358,7 +358,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -400,6 +399,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -413,6 +413,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -433,6 +434,17 @@ sound-dai = <&dummy_codec>; }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1232,7 +1244,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; @@ -1247,7 +1259,7 @@ "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdma_mclk &tdmout_a>; + pinctrl-0 = ; /* * 0: tdmout_a; @@ -1271,7 +1283,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1286,7 +1298,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1298,16 +1310,35 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_c &tdmin_c>; + pinctrl-0 = ; status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A @@ -1339,13 +1370,13 @@ * 7: "Enable:192K", */ asrc_id = <0>; - auto_asrc = <0>; + auto_asrc = <3>; status = "okay"; }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1357,34 +1388,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1392,6 +1400,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1401,9 +1440,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1415,9 +1451,9 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1438,7 +1474,7 @@ */ resample_module = <3>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1495,7 +1531,7 @@ * 0: in user space * 1: in kernel space */ - level = <0>; + level = <1>; status = "disabled"; }; @@ -1505,38 +1541,31 @@ /* audio pin mux */ tdma_mclk: tdma_mclk { - mux { /* GPIOZ_0 */ - groups = "mclk0_z"; + mux { /* GPIOH_4 */ + groups = "mclk0_h"; function = "mclk0"; }; }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ - groups = "tdma_sclk_z", - "tdma_fs_z", - "tdma_dout0_z", - "tdma_dout2_z", - "tdma_dout3_z"; + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; function = "tdma_out"; bias-pull-down; }; }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; -#if 0 //verify tdm/i2s in - tdmin_a: tdmin_a { - mux { /* GPIOZ_7 */ - groups = "tdma_din0_z"; - function = "tdma_in"; - }; - }; -#endif + tdmout_c: tdmout_c { mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ groups = "tdmc_sclk", diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index dbb1a8556fcb..ceb7f6dd2f1c 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -288,7 +288,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -326,7 +326,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -362,7 +361,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -418,6 +416,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -439,6 +438,17 @@ }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1328,7 +1338,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; @@ -1367,7 +1377,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1382,7 +1392,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1399,8 +1409,27 @@ status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL1 @@ -1440,7 +1469,7 @@ }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1452,34 +1481,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1487,6 +1493,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1509,7 +1546,7 @@ /* max 0xff, each bit for one channel */ channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1530,7 +1567,7 @@ */ resample_module = <3>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1604,18 +1641,21 @@ }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ groups = "tdma_sclk_z", "tdma_fs_z", - "tdma_dout0_z"; + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; function = "tdma_out"; bias-pull-down; }; }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts index 627c2cd3c9af..246c3c4333f1 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -257,6 +257,7 @@ reg = <0xff632000 0x1c>; tdmout_index = <0>; tdmin_index = <0>; + dat1_ch_sel = <1>; }; aml_dtv_demod { @@ -285,7 +286,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -323,7 +324,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -359,7 +359,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -401,6 +400,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -414,6 +414,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -434,6 +435,17 @@ sound-dai = <&dummy_codec>; }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1233,7 +1245,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; @@ -1248,7 +1260,7 @@ "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdma_mclk &tdmout_a>; + pinctrl-0 = ; /* * 0: tdmout_a; @@ -1272,7 +1284,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1287,7 +1299,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1299,16 +1311,35 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_c &tdmin_c>; + pinctrl-0 = ; status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A @@ -1340,13 +1371,13 @@ * 7: "Enable:192K", */ asrc_id = <0>; - auto_asrc = <0>; + auto_asrc = <3>; status = "okay"; }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1358,34 +1389,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1393,6 +1401,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1402,9 +1441,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1416,9 +1452,9 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1439,7 +1475,7 @@ */ resample_module = <3>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1496,7 +1532,7 @@ * 0: in user space * 1: in kernel space */ - level = <0>; + level = <1>; status = "disabled"; }; @@ -1530,14 +1566,7 @@ function = "tdma_in"; }; }; -#if 0 //verify tdm/i2s in - tdmin_a: tdmin_a { - mux { /* GPIOZ_7 */ - groups = "tdma_din0_z"; - function = "tdma_in"; - }; - }; -#endif + tdmout_c: tdmout_c { mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ groups = "tdmc_sclk", diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 1285089a7d03..8cf08ee2768a 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1,5 +1,5 @@ /* - * arch/arm64/boot/dts/amlogic/mesontl1.dtsi + * arch/arm64/boot/dts/amlogic/mesontm2.dtsi * * Copyright (C) 2018 Amlogic, Inc. All rights reserved. * @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include "mesong12a-bifrost.dtsi" #include @@ -616,7 +616,7 @@ ranges = <0x0 0x0 0x0 0xff600000 0x0 0x10000>; clkaudio:audio_clocks { - compatible = "amlogic, tl1-audio-clocks"; + compatible = "amlogic, tm2-audio-clocks"; #clock-cells = <1>; reg = <0x0 0x0 0x0 0xb0>; }; @@ -658,13 +658,22 @@ reg = <0x0 0xFF601400 0x0 0x400>; }; eqdrc_base { - reg = <0x0 0xFF602000 0x0 0x2000>; + reg = <0x0 0xFF602000 0x0 0x1000>; }; reset_base { reg = <0x0 0xFFD01000 0x0 0x1000>; }; vad_base { - reg = <0x0 0xFF601800 0x0 0x800>; + reg = <0x0 0xFF601800 0x0 0x400>; + }; + earcrx_cdmc_base { + reg = <0x0 0xFF603800 0x0 0x30>; + }; + earcrx_dmac_base { + reg = <0x0 0xFF603C00 0x0 0x20>; + }; + earcrx_top_base { + reg = <0x0 0xFF603E00 0x0 0x10>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts index e9283634ea64..105cc544cf9d 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -283,7 +283,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -291,7 +291,7 @@ aml-audio-card,dai-link@0 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; + continuous-clock; //bitclock-inversion; //frame-inversion; /* master mode */ @@ -322,8 +322,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; - format = "i2s"; mclk-fs = <256>; //continuous-clock; @@ -358,8 +356,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; - format = "i2s"; mclk-fs = <256>; //continuous-clock; @@ -400,6 +396,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -413,6 +410,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -434,6 +432,17 @@ }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1356,7 +1365,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1371,7 +1380,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1388,8 +1397,32 @@ status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL1 @@ -1429,7 +1462,7 @@ }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1441,30 +1474,6 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; @@ -1476,6 +1485,38 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1498,7 +1539,7 @@ /* max 0xff, each bit for one channel */ channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1520,7 +1561,7 @@ */ resample_module = <8>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1546,31 +1587,63 @@ status = "disabled"; }; + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + status = "disabled"; + }; }; /* end of audiobus */ &pinctrl_periphs { /* audio pin mux */ tdma_mclk: tdma_mclk { - mux { /* GPIOZ_0 */ - groups = "mclk0_z"; + mux { /* GPIOH_4 */ + groups = "mclk0_h"; function = "mclk0"; }; }; tdmout_a: tdmout_a { - mux { /* GPIOH_5, GPIOH_6, GPIOH_7 */ + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ groups = "tdma_fs_h", "tdma_sclk_h", - "tdma_dout0_h"; + "tdma_dout0_h", + "tdma_dout1_h"; function = "tdma_out"; bias-pull-down; }; }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts index 0846d02cedbb..44146fe78453 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -256,6 +256,7 @@ reg = <0x0 0xff632000 0x0 0x1c>; tdmout_index = <0>; tdmin_index = <0>; + dat1_ch_sel = <1>; }; aml_dtv_demod { @@ -283,7 +284,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -321,7 +322,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -357,7 +357,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -399,6 +398,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -412,6 +412,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -432,9 +433,20 @@ sound-dai = <&dummy_codec>; }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; - /* Audio Related end */ + dvb { compatible = "amlogic, dvb"; status = "okay"; @@ -1231,7 +1243,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; @@ -1246,7 +1258,7 @@ "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdma_mclk &tdmout_a>; + pinctrl-0 = ; /* * 0: tdmout_a; @@ -1270,7 +1282,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1285,7 +1297,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1297,16 +1309,35 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_c &tdmin_c>; + pinctrl-0 = ; status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A @@ -1338,13 +1369,13 @@ * 7: "Enable:192K", */ asrc_id = <0>; - auto_asrc = <0>; + auto_asrc = <3>; status = "okay"; }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1356,34 +1387,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1391,6 +1399,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1400,9 +1439,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1414,9 +1450,9 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1437,7 +1473,7 @@ */ resample_module = <3>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1494,7 +1530,7 @@ * 0: in user space * 1: in kernel space */ - level = <0>; + level = <1>; status = "disabled"; }; @@ -1504,38 +1540,31 @@ /* audio pin mux */ tdma_mclk: tdma_mclk { - mux { /* GPIOZ_0 */ - groups = "mclk0_z"; + mux { /* GPIOH_4 */ + groups = "mclk0_h"; function = "mclk0"; }; }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ - groups = "tdma_sclk_z", - "tdma_fs_z", - "tdma_dout0_z", - "tdma_dout2_z", - "tdma_dout3_z"; + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; function = "tdma_out"; bias-pull-down; }; }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; -#if 0 //verify tdm/i2s in - tdmin_a: tdmin_a { - mux { /* GPIOZ_7 */ - groups = "tdma_din0_z"; - function = "tdma_in"; - }; - }; -#endif + tdmout_c: tdmout_c { mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ groups = "tdmc_sclk", diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 12abf8274d01..a3e311123d4c 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -292,7 +292,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -330,7 +330,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -366,7 +365,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -408,6 +406,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -421,6 +420,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -442,6 +442,17 @@ }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1367,7 +1378,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1382,7 +1393,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1399,8 +1410,27 @@ status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL1 @@ -1418,6 +1448,7 @@ pinctrl-names = "spdif_pins", "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; pinctrl-1 = <&spdifout_a_mute>; @@ -1440,7 +1471,7 @@ }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1452,34 +1483,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1487,6 +1495,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1509,7 +1548,7 @@ /* max 0xff, each bit for one channel */ channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1531,7 +1570,7 @@ */ resample_module = <8>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1557,6 +1596,41 @@ status = "disabled"; }; + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; }; /* end of audiobus */ &pinctrl_periphs { @@ -1580,8 +1654,9 @@ }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts index 7917bbe08dd3..15662fe68e95 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -257,6 +257,7 @@ reg = <0x0 0xff632000 0x0 0x1c>; tdmout_index = <0>; tdmin_index = <0>; + dat1_ch_sel = <1>; }; aml_dtv_demod { @@ -284,7 +285,7 @@ }; auge_sound { - compatible = "amlogic, tl1-sound-card"; + compatible = "amlogic, tm2-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; @@ -322,7 +323,6 @@ }; aml-audio-card,dai-link@1 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -358,7 +358,6 @@ }; aml-audio-card,dai-link@2 { - status = "disabled"; format = "i2s"; mclk-fs = <256>; @@ -400,6 +399,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -413,6 +413,7 @@ aml-audio-card,dai-link@5 { mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; cpu { sound-dai = <&spdifb>; system-clock-frequency = <6144000>; @@ -433,6 +434,17 @@ sound-dai = <&dummy_codec>; }; }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; }; /* Audio Related end */ @@ -1232,7 +1244,7 @@ &audiobus { tdma:tdm@0 { - compatible = "amlogic, tl1-snd-tdma"; + compatible = "amlogic, tm2-snd-tdma"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; @@ -1247,7 +1259,7 @@ "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdma_mclk &tdmout_a>; + pinctrl-0 = ; /* * 0: tdmout_a; @@ -1271,7 +1283,7 @@ }; tdmb:tdm@1 { - compatible = "amlogic, tl1-snd-tdmb"; + compatible = "amlogic, tm2-snd-tdmb"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1286,7 +1298,7 @@ }; tdmc:tdm@2 { - compatible = "amlogic, tl1-snd-tdmc"; + compatible = "amlogic, tm2-snd-tdmc"; #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0 0 0>; @@ -1298,16 +1310,35 @@ clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_c &tdmin_c>; + pinctrl-0 = ; status = "okay"; }; + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; spdifa:spdif@0 { - compatible = "amlogic, tl1-snd-spdif-a"; + compatible = "amlogic, tm2-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A @@ -1339,13 +1370,13 @@ * 7: "Enable:192K", */ asrc_id = <0>; - auto_asrc = <0>; + auto_asrc = <3>; status = "okay"; }; spdifb:spdif@1 { - compatible = "amlogic, tl1-snd-spdif-b"; + compatible = "amlogic, tm2-snd-spdif-b"; #sound-dai-cells = <0>; clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ @@ -1357,34 +1388,11 @@ status = "okay"; }; - pdm:pdm { - compatible = "amlogic, tl1-snd-pdm"; - #sound-dai-cells = <0>; - - clocks = <&clkaudio CLKID_AUDIO_GATE_PDM - &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_PDMIN0 - &clkaudio CLKID_AUDIO_PDMIN1>; - clock-names = "gate", - "sysclk_srcpll", - "dclk_srcpll", - "pdm_dclk", - "pdm_sysclk"; - - pinctrl-names = "pdm_pins"; - pinctrl-0 = <&pdmin>; - - /* mode 0~4, defalut:1 */ - filter_mode = <1>; - - status = "okay"; - }; - extn:extn { compatible = "amlogic, snd-extn"; #sound-dai-cells = <0>; + interrupts = ; interrupt-names = "irq_frhdmirx"; @@ -1392,6 +1400,37 @@ status = "okay"; }; + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + aed:effect { compatible = "amlogic, snd-effect-v2"; #sound-dai-cells = <0>; @@ -1401,9 +1440,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1415,9 +1451,9 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; - status = "okay"; + status = "disable"; }; asrca: resample@0 { @@ -1438,7 +1474,7 @@ */ resample_module = <3>; - status = "okay"; + status = "disabled"; }; asrcb: resample@1 { @@ -1495,7 +1531,7 @@ * 0: in user space * 1: in kernel space */ - level = <0>; + level = <1>; status = "disabled"; }; @@ -1505,38 +1541,31 @@ /* audio pin mux */ tdma_mclk: tdma_mclk { - mux { /* GPIOZ_0 */ - groups = "mclk0_z"; + mux { /* GPIOH_4 */ + groups = "mclk0_h"; function = "mclk0"; }; }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ - groups = "tdma_sclk_z", - "tdma_fs_z", - "tdma_dout0_z", - "tdma_dout2_z", - "tdma_dout3_z"; + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; function = "tdma_out"; bias-pull-down; }; }; tdmin_a: tdmin_a { - mux { /* GPIOZ_9 */ - groups = "tdma_din2_z"; + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; function = "tdma_in"; }; }; -#if 0 //verify tdm/i2s in - tdmin_a: tdmin_a { - mux { /* GPIOZ_7 */ - groups = "tdma_din0_z"; - function = "tdma_in"; - }; - }; -#endif + tdmout_c: tdmout_c { mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ groups = "tdmc_sclk", diff --git a/include/dt-bindings/clock/amlogic,tm2-audio-clk.h b/include/dt-bindings/clock/amlogic,tm2-audio-clk.h new file mode 100644 index 000000000000..a70cf1ef636b --- /dev/null +++ b/include/dt-bindings/clock/amlogic,tm2-audio-clk.h @@ -0,0 +1,97 @@ +/* + * include/dt-bindings/clock/amlogic,tm2-audio-clk.h + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __TM2_AUDIO_CLK_H__ +#define __TM2_AUDIO_CLK_H__ + +/* + * CLKID audio index values + */ + +#define CLKID_AUDIO_GATE_DDR_ARB 0 +#define CLKID_AUDIO_GATE_PDM 1 +#define CLKID_AUDIO_GATE_TDMINA 2 +#define CLKID_AUDIO_GATE_TDMINB 3 +#define CLKID_AUDIO_GATE_TDMINC 4 +#define CLKID_AUDIO_GATE_TDMINLB 5 +#define CLKID_AUDIO_GATE_TDMOUTA 6 +#define CLKID_AUDIO_GATE_TDMOUTB 7 +#define CLKID_AUDIO_GATE_TDMOUTC 8 +#define CLKID_AUDIO_GATE_FRDDRA 9 +#define CLKID_AUDIO_GATE_FRDDRB 10 +#define CLKID_AUDIO_GATE_FRDDRC 11 +#define CLKID_AUDIO_GATE_TODDRA 12 +#define CLKID_AUDIO_GATE_TODDRB 13 +#define CLKID_AUDIO_GATE_TODDRC 14 +#define CLKID_AUDIO_GATE_LOOPBACKA 15 +#define CLKID_AUDIO_GATE_SPDIFIN 16 +#define CLKID_AUDIO_GATE_SPDIFOUT_A 17 +#define CLKID_AUDIO_GATE_RESAMPLEA 18 +#define CLKID_AUDIO_GATE_RESERVED0 19 +#define CLKID_AUDIO_GATE_RESERVED1 20 +#define CLKID_AUDIO_GATE_SPDIFOUT_B 21 +#define CLKID_AUDIO_GATE_EQDRC 22 +#define CLKID_AUDIO_GATE_RESERVED2 23 +#define CLKID_AUDIO_GATE_RESERVED3 24 +#define CLKID_AUDIO_GATE_RESERVED4 25 +#define CLKID_AUDIO_GATE_RESAMPLEB 26 +#define CLKID_AUDIO_GATE_TOVAD 27 +#define CLKID_AUDIO_GATE_AUDIOLOCKER 28 +#define CLKID_AUDIO_GATE_SPDIFIN_LB 29 +#define CLKID_AUDIO_GATE_FRATV 30 +#define CLKID_AUDIO_GATE_FRHDMIRX 31 + +/* Gate En1 */ +#define CLKID_AUDIO_GATE_FRDDRD 32 +#define CLKID_AUDIO_GATE_TODDRD 33 +#define CLKID_AUDIO_GATE_LOOPBACKB 34 +#define CLKID_AUDIO_GATE_FRDDRE 35 +#define CLKID_AUDIO_GATE_TODDRE 36 +#define CLKID_AUDIO_GATE_EARCTX 37 +#define CLKID_AUDIO_GATE_EARCRX 38 +#define CLKID_AUDIO_GATE_RESAMPLEB_OLD 39 +#define CLKID_AUDIO_GATE_LOCKER 40 + +#define CLKID_AUDIO_GATE_MAX 41 + +#define MCLK_BASE CLKID_AUDIO_GATE_MAX +#define CLKID_AUDIO_MCLK_A (MCLK_BASE + 0) +#define CLKID_AUDIO_MCLK_B (MCLK_BASE + 1) +#define CLKID_AUDIO_MCLK_C (MCLK_BASE + 2) +#define CLKID_AUDIO_MCLK_D (MCLK_BASE + 3) +#define CLKID_AUDIO_MCLK_E (MCLK_BASE + 4) +#define CLKID_AUDIO_MCLK_F (MCLK_BASE + 5) + +#define CLKID_AUDIO_SPDIFIN (MCLK_BASE + 6) +#define CLKID_AUDIO_SPDIFOUT_A (MCLK_BASE + 7) +#define CLKID_AUDIO_RESAMPLE_A (MCLK_BASE + 8) +#define CLKID_AUDIO_LOCKER_OUT (MCLK_BASE + 9) +#define CLKID_AUDIO_LOCKER_IN (MCLK_BASE + 10) +#define CLKID_AUDIO_PDMIN0 (MCLK_BASE + 11) +#define CLKID_AUDIO_PDMIN1 (MCLK_BASE + 12) +#define CLKID_AUDIO_SPDIFOUT_B (MCLK_BASE + 13) +#define CLKID_AUDIO_RESAMPLE_B (MCLK_BASE + 14) +#define CLKID_AUDIO_SPDIFIN_LB (MCLK_BASE + 15) +#define CLKID_AUDIO_EQDRC (MCLK_BASE + 16) +#define CLKID_AUDIO_VAD (MCLK_BASE + 17) +#define CLKID_EARCTX_CMDC (MCLK_BASE + 18) +#define CLKID_EARCTX_DMAC (MCLK_BASE + 19) +#define CLKID_EARCRX_CMDC (MCLK_BASE + 20) +#define CLKID_EARCRX_DMAC (MCLK_BASE + 21) + +#define NUM_AUDIO_CLKS (MCLK_BASE + 22) +#endif /* __TM2_AUDIO_CLK_H__ */ diff --git a/sound/soc/amlogic/auge/Makefile b/sound/soc/amlogic/auge/Makefile index 91825bf36d6c..b8d6cc8eb8e8 100644 --- a/sound/soc/amlogic/auge/Makefile +++ b/sound/soc/amlogic/auge/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \ g12a,clocks.o \ tl1,clocks.o \ sm1,clocks.o \ + tm2,clocks.o \ card.o \ card_utils.o \ tdm.o \ diff --git a/sound/soc/amlogic/auge/audio_clks.c b/sound/soc/amlogic/auge/audio_clks.c index e02f2a562b07..4aa82c362867 100644 --- a/sound/soc/amlogic/auge/audio_clks.c +++ b/sound/soc/amlogic/auge/audio_clks.c @@ -40,6 +40,10 @@ static const struct of_device_id audio_clocks_of_match[] = { .compatible = "amlogic, sm1-audio-clocks", .data = &sm1_audio_clks_init, }, + { + .compatible = "amlogic, tm2-audio-clocks", + .data = &tm2_audio_clks_init, + }, {}, }; MODULE_DEVICE_TABLE(of, audio_clocks_of_match); diff --git a/sound/soc/amlogic/auge/audio_clks.h b/sound/soc/amlogic/auge/audio_clks.h index 56a0a67b1d31..ede4ec982ced 100644 --- a/sound/soc/amlogic/auge/audio_clks.h +++ b/sound/soc/amlogic/auge/audio_clks.h @@ -94,6 +94,7 @@ extern struct audio_clk_init axg_audio_clks_init; extern struct audio_clk_init g12a_audio_clks_init; extern struct audio_clk_init tl1_audio_clks_init; extern struct audio_clk_init sm1_audio_clks_init; +extern struct audio_clk_init tm2_audio_clks_init; struct clk_chipinfo { /* force clock source as oscin(24M) */ diff --git a/sound/soc/amlogic/auge/audio_controller.c b/sound/soc/amlogic/auge/audio_controller.c index 1b50eacb3ff0..04845c530853 100644 --- a/sound/soc/amlogic/auge/audio_controller.c +++ b/sound/soc/amlogic/auge/audio_controller.c @@ -104,6 +104,7 @@ static int register_audio_controller(struct platform_device *pdev, /* gate on all clks on bringup stage, need gate separately */ aml_audiobus_write(actrl, EE_AUDIO_CLK_GATE_EN0, 0xffffffff); + aml_audiobus_write(actrl, EE_AUDIO_CLK_GATE_EN1, 0xffffffff); return 0; } diff --git a/sound/soc/amlogic/auge/card.c b/sound/soc/amlogic/auge/card.c index 3e7c82cd0ca2..4550fbca4fbf 100644 --- a/sound/soc/amlogic/auge/card.c +++ b/sound/soc/amlogic/auge/card.c @@ -877,6 +877,10 @@ static const struct of_device_id auge_of_match[] = { .compatible = "amlogic, tl1-sound-card", .data = &tl1_chipset_info, }, + { + .compatible = "amlogic, tm2-sound-card", + .data = &tl1_chipset_info, + }, {}, }; MODULE_DEVICE_TABLE(of, auge_of_match); @@ -919,9 +923,8 @@ static int aml_card_probe(struct platform_device *pdev) ret = aml_card_parse_of(np, priv); if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "%s, parse error %d\n", - __func__, ret); + dev_err(dev, "%s, parse error %d\n", + __func__, ret); goto err; } diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index af7560a86a1b..a12a337ce159 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -406,7 +406,7 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh) if (to->chipinfo && to->chipinfo->ugt) { reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 0x0 << 0, 0x1 << 0); + aml_audiobus_update_bits(actrl, reg, 0x1, 0x1); } } @@ -1317,8 +1317,8 @@ void aml_frddr_set_fifos(struct frddr *fr, (depth - 1)<<24 | (thresh - 1)<<16 | 2<<8); if (fr->chipinfo && fr->chipinfo->ugt) { - reg = calc_toddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 0x0 << 0, 0x1 << 0); + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base); + aml_audiobus_update_bits(actrl, reg, 0x1, 0x1); } } diff --git a/sound/soc/amlogic/auge/earc.c b/sound/soc/amlogic/auge/earc.c index 355e7db3a8b3..30b5f30d0aec 100644 --- a/sound/soc/amlogic/auge/earc.c +++ b/sound/soc/amlogic/auge/earc.c @@ -625,6 +625,9 @@ static const struct of_device_id earc_device_id[] = { { .compatible = "amlogic, sm1-snd-earc", }, + { + .compatible = "amlogic, tm2-snd-earc", + }, {}, }; @@ -664,7 +667,7 @@ static int earc_platform_probe(struct platform_device *pdev) if (IS_ERR(p_earc->clk_rx_gate)) { dev_err(&pdev->dev, "Can't get earc gate\n"); - return PTR_ERR(p_earc->clk_rx_gate); + /*return PTR_ERR(p_earc->clk_rx_gate);*/ } /* RX */ p_earc->clk_rx_cmdc = devm_clk_get(&pdev->dev, "rx_cmdc"); diff --git a/sound/soc/amlogic/auge/pdm_match_table.c b/sound/soc/amlogic/auge/pdm_match_table.c index 850b5093f990..27ce1dd6b5e5 100644 --- a/sound/soc/amlogic/auge/pdm_match_table.c +++ b/sound/soc/amlogic/auge/pdm_match_table.c @@ -31,6 +31,12 @@ static struct pdm_chipinfo sm1_pdm_chipinfo = { .train = true, }; +static struct pdm_chipinfo tm2_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, + .train = true, +}; + static const struct of_device_id aml_pdm_device_id[] = { { .compatible = "amlogic, axg-snd-pdm", @@ -47,6 +53,10 @@ static const struct of_device_id aml_pdm_device_id[] = { .compatible = "amlogic, sm1-snd-pdm", .data = &sm1_pdm_chipinfo, }, + { + .compatible = "amlogic, tm2-snd-pdm", + .data = &tm2_pdm_chipinfo, + }, {} }; diff --git a/sound/soc/amlogic/auge/spdif_match_table.c b/sound/soc/amlogic/auge/spdif_match_table.c index 025301585292..c88929e55561 100644 --- a/sound/soc/amlogic/auge/spdif_match_table.c +++ b/sound/soc/amlogic/auge/spdif_match_table.c @@ -92,6 +92,20 @@ struct spdif_chipinfo sm1_spdif_b_chipinfo = { .eq_drc_en = true, }; +struct spdif_chipinfo tm2_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo tm2_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + static const struct of_device_id aml_spdif_device_id[] = { { .compatible = "amlogic, axg-snd-spdif", @@ -121,6 +135,14 @@ static const struct of_device_id aml_spdif_device_id[] = { .compatible = "amlogic, sm1-snd-spdif-b", .data = &sm1_spdif_b_chipinfo, }, + { + .compatible = "amlogic, tm2-snd-spdif-a", + .data = &tm2_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-spdif-b", + .data = &tm2_spdif_b_chipinfo, + }, {}, }; MODULE_DEVICE_TABLE(of, aml_spdif_device_id); diff --git a/sound/soc/amlogic/auge/tdm_match_table.c b/sound/soc/amlogic/auge/tdm_match_table.c index fd56921b4f45..38534778ae3a 100644 --- a/sound/soc/amlogic/auge/tdm_match_table.c +++ b/sound/soc/amlogic/auge/tdm_match_table.c @@ -132,6 +132,30 @@ struct tdm_chipinfo sm1_tdmc_chipinfo = { .lane_cnt = LANE_MAX1, }; +struct tdm_chipinfo tm2_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX0, +}; + +struct tdm_chipinfo tm2_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX3, +}; + +struct tdm_chipinfo tm2_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX1, +}; + static const struct of_device_id aml_tdm_device_id[] = { { .compatible = "amlogic, axg-snd-tdma", @@ -181,6 +205,18 @@ static const struct of_device_id aml_tdm_device_id[] = { .compatible = "amlogic, sm1-snd-tdmc", .data = &sm1_tdmc_chipinfo, }, + { + .compatible = "amlogic, tm2-snd-tdma", + .data = &tm2_tdma_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-tdmb", + .data = &tm2_tdmb_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-tdmc", + .data = &tm2_tdmc_chipinfo, + }, {}, }; MODULE_DEVICE_TABLE(of, aml_tdm_device_id); diff --git a/sound/soc/amlogic/auge/tm2,clocks.c b/sound/soc/amlogic/auge/tm2,clocks.c new file mode 100644 index 000000000000..aed576ec4ded --- /dev/null +++ b/sound/soc/amlogic/auge/tm2,clocks.c @@ -0,0 +1,392 @@ +/* + * sound/soc/amlogic/auge/tm2_clocks.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#undef pr_fmt +#define pr_fmt(fmt) "tm2_audio_clocks: " fmt + +#include + +#include "audio_clks.h" +#include "regs.h" + +static spinlock_t aclk_lock; + +static const char *const mclk_parent_names[] = { + "mpll0", "mpll1", "mpll2", "mpll3", "hifi_pll", + "fclk_div3", "fclk_div4", "fclk_div5"}; + +static const char *const audioclk_parent_names[] = { + "mclk_a", "mclk_b", "mclk_c", "mclk_d", "mclk_e", + "mclk_f", "i_slv_sclk_a", "i_slv_sclk_b", "i_slv_sclk_c", + "i_slv_sclk_d", "i_slv_sclk_e", "i_slv_sclk_f", "i_slv_sclk_g", + "i_slv_sclk_h", "i_slv_sclk_i", "i_slv_sclk_j"}; + +CLOCK_GATE(audio_ddr_arb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 0); +CLOCK_GATE(audio_pdm, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 1); +CLOCK_GATE(audio_tdmina, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 2); +CLOCK_GATE(audio_tdminb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 3); +CLOCK_GATE(audio_tdminc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 4); +CLOCK_GATE(audio_tdminlb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 5); +CLOCK_GATE(audio_tdmouta, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 6); +CLOCK_GATE(audio_tdmoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 7); +CLOCK_GATE(audio_tdmoutc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 8); +CLOCK_GATE(audio_frddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 9); +CLOCK_GATE(audio_frddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 10); +CLOCK_GATE(audio_frddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 11); +CLOCK_GATE(audio_toddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 12); +CLOCK_GATE(audio_toddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 13); +CLOCK_GATE(audio_toddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 14); +CLOCK_GATE(audio_loopbacka, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 15); +CLOCK_GATE(audio_spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 16); +CLOCK_GATE(audio_spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 17); +CLOCK_GATE(audio_resamplea, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 18); +CLOCK_GATE(audio_reserved0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 19); +CLOCK_GATE(audio_reserved1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 20); +CLOCK_GATE(audio_spdifoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 21); +CLOCK_GATE(audio_eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 22); +CLOCK_GATE(audio_reserved2, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 23); +CLOCK_GATE(audio_reserved3, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 24); +CLOCK_GATE(audio_reserved4, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 25); +CLOCK_GATE(audio_resampleb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 26); +CLOCK_GATE(audio_tovad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 27); +CLOCK_GATE(audio_audiolocker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 28); +CLOCK_GATE(audio_spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 29); +CLOCK_GATE(audio_fratv, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 30); +CLOCK_GATE(audio_frhdmirx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31); + +CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0); +CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1); +CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2); +CLOCK_GATE(audio_frddre, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 3); +CLOCK_GATE(audio_toddre, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 4); +CLOCK_GATE(audio_earctx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 5); +CLOCK_GATE(audio_earcrx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6); +CLOCK_GATE(audio_resampleb_old, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 7); +CLOCK_GATE(audio_locker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 8); + + +static struct clk_gate *tm2_audio_clk_gates[] = { + &audio_ddr_arb, + &audio_pdm, + &audio_tdmina, + &audio_tdminb, + &audio_tdminc, + &audio_tdminlb, + &audio_tdmouta, + &audio_tdmoutb, + &audio_tdmoutc, + &audio_frddra, + &audio_frddrb, + &audio_frddrc, + &audio_toddra, + &audio_toddrb, + &audio_toddrc, + &audio_loopbacka, + &audio_spdifin, + &audio_spdifout, + &audio_resamplea, + &audio_reserved0, + &audio_reserved1, + &audio_spdifoutb, + &audio_eqdrc, + &audio_reserved2, + &audio_reserved3, + &audio_reserved4, + &audio_resampleb, + &audio_tovad, + &audio_audiolocker, + &audio_spdifin_lb, + &audio_fratv, + &audio_frhdmirx, + + &audio_frddrd, + &audio_toddrd, + &audio_loopbackb, + &audio_frddre, + &audio_toddre, + &audio_earctx, + &audio_earcrx, + &audio_resampleb_old, + &audio_locker, +}; + +/* Array of all clocks provided by this provider */ +static struct clk_hw *tm2_audio_clk_hws[] = { + [CLKID_AUDIO_GATE_DDR_ARB] = &audio_ddr_arb.hw, + [CLKID_AUDIO_GATE_PDM] = &audio_pdm.hw, + [CLKID_AUDIO_GATE_TDMINA] = &audio_tdmina.hw, + [CLKID_AUDIO_GATE_TDMINB] = &audio_tdminb.hw, + [CLKID_AUDIO_GATE_TDMINC] = &audio_tdminc.hw, + [CLKID_AUDIO_GATE_TDMINLB] = &audio_tdminlb.hw, + [CLKID_AUDIO_GATE_TDMOUTA] = &audio_tdmouta.hw, + [CLKID_AUDIO_GATE_TDMOUTB] = &audio_tdmoutb.hw, + [CLKID_AUDIO_GATE_TDMOUTC] = &audio_tdmoutc.hw, + [CLKID_AUDIO_GATE_FRDDRA] = &audio_frddra.hw, + [CLKID_AUDIO_GATE_FRDDRB] = &audio_frddrb.hw, + [CLKID_AUDIO_GATE_FRDDRC] = &audio_frddrc.hw, + [CLKID_AUDIO_GATE_TODDRA] = &audio_toddra.hw, + [CLKID_AUDIO_GATE_TODDRB] = &audio_toddrb.hw, + [CLKID_AUDIO_GATE_TODDRC] = &audio_toddrc.hw, + [CLKID_AUDIO_GATE_LOOPBACKA] = &audio_loopbacka.hw, + [CLKID_AUDIO_GATE_SPDIFIN] = &audio_spdifin.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_A] = &audio_spdifout.hw, + [CLKID_AUDIO_GATE_RESAMPLEA] = &audio_resamplea.hw, + [CLKID_AUDIO_GATE_RESERVED0] = &audio_reserved0.hw, + [CLKID_AUDIO_GATE_RESERVED1] = &audio_reserved1.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_B] = &audio_spdifoutb.hw, + [CLKID_AUDIO_GATE_EQDRC] = &audio_eqdrc.hw, + [CLKID_AUDIO_GATE_RESERVED2] = &audio_reserved2.hw, + [CLKID_AUDIO_GATE_RESERVED3] = &audio_reserved3.hw, + [CLKID_AUDIO_GATE_RESERVED4] = &audio_reserved4.hw, + [CLKID_AUDIO_GATE_RESAMPLEB] = &audio_resampleb.hw, + [CLKID_AUDIO_GATE_TOVAD] = &audio_tovad.hw, + [CLKID_AUDIO_GATE_AUDIOLOCKER] = &audio_audiolocker.hw, + [CLKID_AUDIO_GATE_SPDIFIN_LB] = &audio_spdifin_lb.hw, + [CLKID_AUDIO_GATE_FRATV] = &audio_fratv.hw, + [CLKID_AUDIO_GATE_FRHDMIRX] = &audio_frhdmirx.hw, + + [CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw, + [CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw, + [CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw, + [CLKID_AUDIO_GATE_FRDDRE] = &audio_frddre.hw, + [CLKID_AUDIO_GATE_TODDRE] = &audio_toddre.hw, + [CLKID_AUDIO_GATE_EARCTX] = &audio_earctx.hw, + [CLKID_AUDIO_GATE_EARCRX] = &audio_earcrx.hw, + [CLKID_AUDIO_GATE_RESAMPLEB_OLD] = &audio_resampleb_old.hw, + [CLKID_AUDIO_GATE_LOCKER] = &audio_locker.hw, +}; + +static int tm2_clk_gates_init(struct clk **clks, void __iomem *iobase) +{ + int clkid; + + if (ARRAY_SIZE(tm2_audio_clk_gates) != MCLK_BASE) { + pr_err("check clk gates number\n"); + return -EINVAL; + } + + for (clkid = 0; clkid < MCLK_BASE; clkid++) { + tm2_audio_clk_gates[clkid]->reg = iobase; + clks[clkid] = clk_register(NULL, tm2_audio_clk_hws[clkid]); + WARN_ON(IS_ERR_OR_NULL(clks[clkid])); + } + + return 0; +} + +/* mclk_a */ +CLOCK_COM_MUX(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 31); +/* mclk_b */ +CLOCK_COM_MUX(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 31); +/* mclk_c */ +CLOCK_COM_MUX(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 31); +/* mclk_d */ +CLOCK_COM_MUX(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 31); +/* mclk_e */ +CLOCK_COM_MUX(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 31); +/* mclk_f */ +CLOCK_COM_MUX(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 31); +/* spdifin */ +CLOCK_COM_MUX(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0, 8); +CLOCK_COM_GATE(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 31); +/* spdifout */ +CLOCK_COM_MUX(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 31); +/* audio resample_a */ +CLOCK_COM_MUX(resample_a, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8); +CLOCK_COM_GATE(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31); +/* audio locker_out */ +CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24); +CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8); +CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31); +/* audio locker_in */ +CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8); +CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8); +CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15); +/* pdmin0 */ +CLOCK_COM_MUX(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0x7, 24); +CLOCK_COM_DIV(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0, 16); +CLOCK_COM_GATE(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 31); +/* pdmin1 */ +CLOCK_COM_MUX(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0x7, 24); +CLOCK_COM_DIV(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0, 16); +CLOCK_COM_GATE(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 31); +/* spdifout b*/ +CLOCK_COM_MUX(spdifout_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio resample_b */ +CLOCK_COM_MUX(resample_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0, 8); +CLOCK_COM_GATE(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 31); +/* spdifin_lb, div is a fake */ +CLOCK_COM_MUX(spdifin_lb, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x1, 30); +CLOCK_COM_DIV(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 29); +CLOCK_COM_GATE(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio eqdrc */ +CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24); +CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16); +CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31); +/* audio vad */ +CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31); +/* EARC TX CMDC */ +CLOCK_COM_MUX(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 31); +/* EARC TX DMAC */ +CLOCK_COM_MUX(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 31); +/* EARC RX CMDC */ +CLOCK_COM_MUX(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 31); +/* EARC RX DMAC */ +CLOCK_COM_MUX(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 31); + +static int tm2_clks_init(struct clk **clks, void __iomem *iobase) +{ + IOMAP_COM_CLK(mclk_a, iobase); + clks[CLKID_AUDIO_MCLK_A] = REGISTER_CLK_COM(mclk_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_A])); + + IOMAP_COM_CLK(mclk_b, iobase); + clks[CLKID_AUDIO_MCLK_B] = REGISTER_CLK_COM(mclk_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_B])); + + IOMAP_COM_CLK(mclk_c, iobase); + clks[CLKID_AUDIO_MCLK_C] = REGISTER_CLK_COM(mclk_c); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_C])); + + IOMAP_COM_CLK(mclk_d, iobase); + clks[CLKID_AUDIO_MCLK_D] = REGISTER_CLK_COM(mclk_d); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_D])); + + IOMAP_COM_CLK(mclk_e, iobase); + clks[CLKID_AUDIO_MCLK_E] = REGISTER_CLK_COM(mclk_e); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_E])); + + IOMAP_COM_CLK(mclk_f, iobase); + clks[CLKID_AUDIO_MCLK_F] = REGISTER_CLK_COM(mclk_f); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_F])); + + IOMAP_COM_CLK(spdifin, iobase); + clks[CLKID_AUDIO_SPDIFIN] = REGISTER_CLK_COM(spdifin); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN])); + + IOMAP_COM_CLK(spdifout, iobase); + clks[CLKID_AUDIO_SPDIFOUT_A] = REGISTER_CLK_COM(spdifout); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_A])); + + IOMAP_COM_CLK(resample_a, iobase); + clks[CLKID_AUDIO_RESAMPLE_A] = REGISTER_AUDIOCLK_COM(resample_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_A])); + + IOMAP_COM_CLK(locker_out, iobase); + clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT])); + + IOMAP_COM_CLK(locker_in, iobase); + clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN])); + + IOMAP_COM_CLK(pdmin0, iobase); + clks[CLKID_AUDIO_PDMIN0] = REGISTER_CLK_COM(pdmin0); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN0])); + + IOMAP_COM_CLK(pdmin1, iobase); + clks[CLKID_AUDIO_PDMIN1] = REGISTER_CLK_COM(pdmin1); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN1])); + + IOMAP_COM_CLK(spdifout_b, iobase); + clks[CLKID_AUDIO_SPDIFOUT_B] = REGISTER_CLK_COM(spdifout_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_B])); + + IOMAP_COM_CLK(resample_b, iobase); + clks[CLKID_AUDIO_RESAMPLE_B] = REGISTER_AUDIOCLK_COM(resample_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_B])); + + IOMAP_COM_CLK(spdifin_lb, iobase); + clks[CLKID_AUDIO_SPDIFIN_LB] = REGISTER_CLK_COM(spdifin_lb); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_LB])); + + IOMAP_COM_CLK(eqdrc, iobase); + clks[CLKID_AUDIO_EQDRC] = REGISTER_CLK_COM(eqdrc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_EQDRC])); + + IOMAP_COM_CLK(vad, iobase); + clks[CLKID_AUDIO_VAD] = REGISTER_CLK_COM(vad); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_VAD])); + + IOMAP_COM_CLK(earctx_cmdc, iobase); + clks[CLKID_EARCTX_CMDC] = REGISTER_CLK_COM(earctx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_CMDC])); + + IOMAP_COM_CLK(earctx_dmac, iobase); + clks[CLKID_EARCTX_DMAC] = REGISTER_CLK_COM(earctx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_DMAC])); + + IOMAP_COM_CLK(earcrx_cmdc, iobase); + clks[CLKID_EARCRX_CMDC] = REGISTER_CLK_COM(earcrx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_CMDC])); + + IOMAP_COM_CLK(earcrx_dmac, iobase); + clks[CLKID_EARCRX_DMAC] = REGISTER_CLK_COM(earcrx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_DMAC])); + + return 0; +} + +struct audio_clk_init tm2_audio_clks_init = { + .clk_num = NUM_AUDIO_CLKS, + .clk_gates = tm2_clk_gates_init, + .clks = tm2_clks_init, +}; From 39aa653f77e5f2bd73c4132b9cc6d17561fb9bdf Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Fri, 12 Apr 2019 17:54:48 +0800 Subject: [PATCH 0636/1060] audio: TM2: bringup AMP ti5805 on ab301 [1/1] PD#SWPL-7074 Problem: speaker doesn't work Solution: bringup AMP ti5805 on ab301 Verify: Verified on T962x3_ab301 Change-Id: Icb27691b4fd5a1e54070c4a6d3d3c68cdf3a60b7 Signed-off-by: Zhe Wang Conflicts: arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts --- .../arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 15 +- .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 11 +- sound/soc/amlogic/auge/tdm.c | 6 +- sound/soc/amlogic/auge/tdm_match_table.c | 2 +- sound/soc/codecs/amlogic/tas5805.c | 948 +++-- sound/soc/codecs/amlogic/tas5805.h | 3044 +++++++---------- 6 files changed, 1937 insertions(+), 2089 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index ceb7f6dd2f1c..7cf4e6f08500 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -321,7 +321,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = ; + sound-dai = <&tl1_codec &tas5805>; }; }; @@ -1641,12 +1641,10 @@ }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3*/ groups = "tdma_sclk_z", "tdma_fs_z", - "tdma_dout0_z", - "tdma_dout2_z", - "tdma_dout3_z"; + "tdma_dout0_z"; function = "tdma_out"; bias-pull-down; }; @@ -1753,12 +1751,13 @@ pinctrl-0=<&i2c2_z_pins>; clock-frequency = <400000>; - tas5805: tas5805@36 { + tas5805: tas5805@5c { compatible = "ti,tas5805"; #sound-dai-cells = <0>; codec_name = "tas5805"; - reg = <0x2d>; - status = "disable"; + reg = <0x2e>; + reset_pin = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + status = "okay"; }; ad82584f: ad82584f@62 { diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index a3e311123d4c..497aa79460ae 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -325,7 +325,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = ; + sound-dai = <&tl1_codec &tas5805>; }; }; @@ -1644,7 +1644,7 @@ }; tdmout_a: tdmout_a { - mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3*/ groups = "tdma_sclk_z", "tdma_fs_z", "tdma_dout0_z"; @@ -1763,12 +1763,13 @@ pinctrl-0=<&i2c2_z_pins>; clock-frequency = <400000>; - tas5805: tas5805@36 { + tas5805: tas5805@5c { compatible = "ti,tas5805"; #sound-dai-cells = <0>; codec_name = "tas5805"; - reg = <0x2d>; - status = "disable"; + reg = <0x2e>; + reset_pin = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + status = "okay"; }; ad82584f: ad82584f@62 { diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index cfaf181b3f87..9e4bab0e2663 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -684,13 +684,11 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, unsigned int set_num = 0; unsigned int i; - pr_debug("asoc channels:%d, slots:%d, lane_cnt:%d\n", - channels, setting->slots, p_tdm->lane_cnt); - /* calc lanes by channels and slots */ lanes = (channels - 1) / setting->slots + 1; if (lanes > p_tdm->lane_cnt) { - pr_err("lanes setting error\n"); + pr_err("set lane error! asoc channels:%d, slots:%d, lane_cnt:%d\n", + channels, setting->slots, p_tdm->lane_cnt); return -EINVAL; } diff --git a/sound/soc/amlogic/auge/tdm_match_table.c b/sound/soc/amlogic/auge/tdm_match_table.c index 38534778ae3a..75195c57ee0a 100644 --- a/sound/soc/amlogic/auge/tdm_match_table.c +++ b/sound/soc/amlogic/auge/tdm_match_table.c @@ -137,7 +137,7 @@ struct tdm_chipinfo tm2_tdma_chipinfo = { .sclk_ws_inv = true, .oe_fn = true, .same_src_fn = true, - .lane_cnt = LANE_MAX0, + .lane_cnt = LANE_MAX1, }; struct tdm_chipinfo tm2_tdmb_chipinfo = { diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c index c7c89f84f748..84fb189b00e8 100644 --- a/sound/soc/codecs/amlogic/tas5805.c +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -52,7 +52,6 @@ #define TAS5805M_REG_29 (0x29) #define TAS5805M_REG_2A (0x2a) #define TAS5805M_REG_2B (0x2b) -#define TAS5805M_SDOUT_SEL (0x30) #define TAS5805M_REG_35 (0x35) #define TAS5805M_DIG_VAL_CTL (0x4c) #define TAS5805M_REG_7F (0x7f) @@ -63,7 +62,7 @@ #define TAS5805M_BOOK_00 (0x00) #define TAS5805M_BOOK_8C (0x8c) -#define TAS5805M_VOLUME_MAX (158) +#define TAS5805M_VOLUME_MAX (578) #define TAS5805M_VOLUME_MIN (0) const uint32_t tas5805m_volume[] = { @@ -147,86 +146,513 @@ const uint32_t tas5805m_volume[] = { 0x0002DD96, //77, -33dB 0x00033718, //78, -32dB 0x00039B87, //79, -31dB - 0x00040C37, //80, -30dB - 0x00048AA7, //81, -29dB - 0x00051884, //82, -28dB - 0x0005B7B1, //83, -27dB - 0x00066A4A, //84, -26dB - 0x000732AE, //85, -25dB - 0x00081385, //86, -24dB - 0x00090FCC, //87, -23dB - 0x000A2ADB, //88, -22dB - 0x000B6873, //89, -21dB - 0x000CCCCD, //90, -20dB - 0x000E5CA1, //91, -19dB - 0x00101D3F, //92, -18dB - 0x0012149A, //93, -17dB - 0x00144961, //94, -16dB - 0x0016C311, //95, -15dB - 0x00198A13, //96, -14dB - 0x001CA7D7, //97, -13dB - 0x002026F3, //98, -12dB - 0x00241347, //99, -11dB - 0x00287A27, //100, -10dB - 0x002D6A86, //101, -9dB - 0x0032F52D, //102, -8dB - 0x00392CEE, //103, -7dB - 0x004026E7, //104, -6dB - 0x0047FACD, //105, -5dB - 0x0050C336, //106, -4dB - 0x005A9DF8, //107, -3dB - 0x0065AC8C, //108, -2dB - 0x00721483, //109, -1dB - 0x00800000, //110, 0dB - 0x008F9E4D, //111, 1dB - 0x00A12478, //112, 2dB - 0x00B4CE08, //113, 3dB - 0x00CADDC8, //114, 4dB - 0x00E39EA9, //115, 5dB - 0x00FF64C1, //116, 6dB - 0x011E8E6A, //117, 7dB - 0x0141857F, //118, 8dB - 0x0168C0C6, //119, 9dB - 0x0194C584, //120, 10dB - 0x01C62940, //121, 11dB - 0x01FD93C2, //122, 12dB - 0x023BC148, //123, 13dB - 0x02818508, //124, 14dB - 0x02CFCC01, //125, 15dB - 0x0327A01A, //126, 16dB - 0x038A2BAD, //127, 17dB - 0x03F8BD7A, //128, 18dB - 0x0474CD1B, //129, 19dB - 0x05000000, //130, 20dB - 0x059C2F02, //131, 21dB - 0x064B6CAE, //132, 22dB - 0x07100C4D, //133, 23dB - 0x07ECA9CD, //134, 24dB - 0x08E43299, //135, 25dB - 0x09F9EF8E, //136, 26dB - 0x0B319025, //137, 27dB - 0x0C8F36F2, //138, 28dB - 0x0E1787B8, //139, 29dB - 0x0FCFB725, //140, 30dB - 0x11BD9C84, //141, 31dB - 0x13E7C594, //142, 32dB - 0x16558CCB, //143, 33dB - 0x190F3254, //144, 34dB - 0x1C1DF80E, //145, 35dB - 0x1F8C4107, //146, 36dB - 0x2365B4BF, //147, 37dB - 0x27B766C2, //148, 38dB - 0x2C900313, //149, 39dB - 0x32000000, //150, 40dB - 0x3819D612, //151, 41dB - 0x3EF23ECA, //152, 42dB - 0x46A07B07, //153, 43dB - 0x4F3EA203, //154, 44dB - 0x58E9F9F9, //155, 45dB - 0x63C35B8E, //156, 46dB - 0x6FEFA16D, //157, 47dB - 0x7D982575, //158, 48dB + 0x00040C37, //80 -30 + 0x00041B3C, //81 -29.875 + 0x00042A79, //82 -29.75 + 0x000439EE, //83 -29.625 + 0x0004499D, //84 -29.5 + 0x00045986, //85 -29.375 + 0x000469AA, //86 -29.25 + 0x00047A0A, //87 -29.125 + 0x00048AA7, //88 -29 + 0x00049B81, //89 -28.875 + 0x0004AC9A, //90 -28.75 + 0x0004BDF2, //91 -28.625 + 0x0004CF8B, //92 -28.5 + 0x0004E165, //93 -28.375 + 0x0004F381, //94 -28.25 + 0x000505E0, //95 -28.125 + 0x00051884, //96 -28 + 0x00052B6D, //97 -27.875 + 0x00053E9C, //98 -27.75 + 0x00055212, //99 -27.625 + 0x000565D0, //100 -27.5 + 0x000579D8, //101 -27.375 + 0x00058E2A, //102 -27.25 + 0x0005A2C7, //103 -27.125 + 0x0005B7B1, //104 -27 + 0x0005CCE8, //105 -26.875 + 0x0005E26E, //106 -26.75 + 0x0005F844, //107 -26.625 + 0x00060E6C, //108 -26.5 + 0x000624E5, //109 -26.375 + 0x00063BB1, //110 -26.25 + 0x000652D3, //111 -26.125 + 0x00066A4A, //112 -26 + 0x00068218, //113 -25.875 + 0x00069A3E, //114 -25.75 + 0x0006B2BF, //115 -25.625 + 0x0006CB9A, //116 -25.5 + 0x0006E4D1, //117 -25.375 + 0x0006FE66, //118 -25.25 + 0x0007185A, //119 -25.125 + 0x000732AE, //120 -25 + 0x00074D63, //121 -24.875 + 0x0007687C, //122 -24.75 + 0x000783FA, //123 -24.625 + 0x00079FDD, //124 -24.5 + 0x0007BC28, //125 -24.375 + 0x0007D8DC, //126 -24.25 + 0x0007F5FA, //127 -24.125 + 0x00081385, //128 -24 + 0x0008317D, //129 -23.875 + 0x00084FE4, //130 -23.75 + 0x00086EBC, //131 -23.625 + 0x00088E07, //132 -23.5 + 0x0008ADC6, //133 -23.375 + 0x0008CDFA, //134 -23.25 + 0x0008EEA6, //135 -23.125 + 0x00090FCB, //136 -23 + 0x0009316C, //137 -22.875 + 0x00095389, //138 -22.75 + 0x00097624, //139 -22.625 + 0x00099940, //140 -22.5 + 0x0009BCDF, //141 -22.375 + 0x0009E101, //142 -22.25 + 0x000A05AA, //143 -22.125 + 0x000A2ADA, //144 -22 + 0x000A5095, //145 -21.875 + 0x000A76DC, //146 -21.75 + 0x000A9DB0, //147 -21.625 + 0x000AC515, //148 -21.5 + 0x000AED0C, //149 -21.375 + 0x000B1597, //150 -21.25 + 0x000B3EB9, //151 -21.125 + 0x000B6873, //152 -21 + 0x000B92C8, //153 -20.875 + 0x000BBDBA, //154 -20.75 + 0x000BE94C, //155 -20.625 + 0x000C157F, //156 -20.5 + 0x000C4256, //157 -20.375 + 0x000C6FD4, //158 -20.25 + 0x000C9DFB, //159 -20.125 + 0x000CCCCC, //160 -20 + 0x000CFC4C, //161 -19.875 + 0x000D2C7B, //162 -19.75 + 0x000D5D5E, //163 -19.625 + 0x000D8EF6, //164 -19.5 + 0x000DC146, //165 -19.375 + 0x000DF451, //166 -19.25 + 0x000E2819, //167 -19.125 + 0x000E5CA1, //168 -19 + 0x000E91EC, //169 -18.875 + 0x000EC7FD, //170 -18.75 + 0x000EFED6, //171 -18.625 + 0x000F367B, //172 -18.5 + 0x000F6EEF, //173 -18.375 + 0x000FA834, //174 -18.25 + 0x000FE24E, //175 -18.125 + 0x00101D3F, //176 -18 + 0x0010590B, //177 -17.875 + 0x001095B4, //178 -17.75 + 0x0010D33F, //179 -17.625 + 0x001111AE, //180 -17.5 + 0x00115105, //181 -17.375 + 0x00119147, //182 -17.25 + 0x0011D278, //183 -17.125 + 0x0012149A, //184 -17 + 0x001257B2, //185 -16.875 + 0x00129BC2, //186 -16.75 + 0x0012E0CF, //187 -16.625 + 0x001326DD, //188 -16.5 + 0x00136DEE, //189 -16.375 + 0x0013B607, //190 -16.25 + 0x0013FF2C, //191 -16.125 + 0x00144960, //192 -16 + 0x001494A8, //193 -15.875 + 0x0014E107, //194 -15.75 + 0x00152E81, //195 -15.625 + 0x00157D1A, //196 -15.5 + 0x0015CCD8, //197 -15.375 + 0x00161DBD, //198 -15.25 + 0x00166FCE, //199 -15.125 + 0x0016C310, //200 -15 + 0x00171787, //201 -14.875 + 0x00176D38, //202 -14.75 + 0x0017C426, //203 -14.625 + 0x00181C57, //204 -14.5 + 0x001875CF, //205 -14.375 + 0x0018D093, //206 -14.25 + 0x00192CA8, //207 -14.125 + 0x00198A13, //208 -14 + 0x0019E8D8, //209 -13.875 + 0x001A48FD, //210 -13.75 + 0x001AAA87, //211 -13.625 + 0x001B0D7B, //212 -13.5 + 0x001B71DD, //213 -13.375 + 0x001BD7B5, //214 -13.25 + 0x001C3F06, //215 -13.125 + 0x001CA7D7, //216 -13 + 0x001D122D, //217 -12.875 + 0x001D7E0D, //218 -12.75 + 0x001DEB7D, //219 -12.625 + 0x001E5A84, //220 -12.5 + 0x001ECB27, //221 -12.375 + 0x001F3D6B, //222 -12.25 + 0x001FB158, //223 -12.125 + 0x002026F3, //224 -12 + 0x00209E42, //225 -11.875 + 0x0021174C, //226 -11.75 + 0x00219217, //227 -11.625 + 0x00220EA9, //228 -11.5 + 0x00228D0A, //229 -11.375 + 0x00230D40, //230 -11.25 + 0x00238F52, //231 -11.125 + 0x00241346, //232 -11 + 0x00249924, //233 -10.875 + 0x002520F3, //234 -10.75 + 0x0025AABA, //235 -10.625 + 0x00263680, //236 -10.5 + 0x0026C44D, //237 -10.375 + 0x00275427, //238 -10.25 + 0x0027E618, //239 -10.125 + 0x00287A26, //240 -10 + 0x0029105A, //241 -9.875 + 0x0029A8BB, //242 -9.75 + 0x002A4351, //243 -9.625 + 0x002AE025, //244 -9.5 + 0x002B7F3F, //245 -9.375 + 0x002C20A8, //246 -9.25 + 0x002CC467, //247 -9.125 + 0x002D6A86, //248 -9 + 0x002E130D, //249 -8.875 + 0x002EBE06, //250 -8.75 + 0x002F6B79, //251 -8.625 + 0x00301B70, //252 -8.5 + 0x0030CDF4, //253 -8.375 + 0x0031830E, //254 -8.25 + 0x00323AC8, //255 -8.125 + 0x0032F52C, //256 -8 + 0x0033B244, //257 -7.875 + 0x0034721A, //258 -7.75 + 0x003534B7, //259 -7.625 + 0x0035FA26, //260 -7.5 + 0x0036C272, //261 -7.375 + 0x00378DA5, //262 -7.25 + 0x00385BCB, //263 -7.125 + 0x00392CED, //264 -7 + 0x003A0117, //265 -6.875 + 0x003AD855, //266 -6.75 + 0x003BB2B1, //267 -6.625 + 0x003C9038, //268 -6.5 + 0x003D70F5, //269 -6.375 + 0x003E54F3, //270 -6.25 + 0x003F3C40, //271 -6.125 + 0x004026E7, //272 -6 + 0x004114F4, //273 -5.875 + 0x00420675, //274 -5.75 + 0x0042FB77, //275 -5.625 + 0x0043F405, //276 -5.5 + 0x0044F02E, //277 -5.375 + 0x0045EFFE, //278 -5.25 + 0x0046F384, //279 -5.125 + 0x0047FACC, //280 -5 + 0x004905E6, //281 -4.875 + 0x004A14DF, //282 -4.75 + 0x004B27C5, //283 -4.625 + 0x004C3EA8, //284 -4.5 + 0x004D5995, //285 -4.375 + 0x004E789C, //286 -4.25 + 0x004F9BCD, //287 -4.125 + 0x0050C335, //288 -4 + 0x0051EEE6, //289 -3.875 + 0x00531EEF, //290 -3.75 + 0x00545361, //291 -3.625 + 0x00558C4B, //292 -3.5 + 0x0056C9BE, //293 -3.375 + 0x00580BCB, //294 -3.25 + 0x00595283, //295 -3.125 + 0x005A9DF7, //296 -3 + 0x005BEE3A, //297 -2.875 + 0x005D435C, //298 -2.75 + 0x005E9D70, //299 -2.625 + 0x005FFC88, //300 -2.5 + 0x006160B7, //301 -2.375 + 0x0062CA10, //302 -2.25 + 0x006438A6, //303 -2.125 + 0x0065AC8C, //304 -2 + 0x006725D6, //305 -1.875 + 0x0068A498, //306 -1.75 + 0x006A28E6, //307 -1.625 + 0x006BB2D6, //308 -1.5 + 0x006D427B, //309 -1.375 + 0x006ED7EB, //310 -1.25 + 0x0070733B, //311 -1.125 + 0x00721482, //312 -1 + 0x0073BBD6, //313 -0.875 + 0x0075694C, //314 -0.75 + 0x00771CFC, //315 -0.625 + 0x0078D6FC, //316 -0.5 + 0x007A9765, //317 -0.375 + 0x007C5E4E, //318 -0.25 + 0x007E2BCE, //319 -0.125 + 0x00800000, //320 0 + 0x0081DAFA, //321 0.125 + 0x0083BCD7, //322 0.25 + 0x0085A5B1, //323 0.375 + 0x008795A0, //324 0.5 + 0x00898CBF, //325 0.625 + 0x008B8B2A, //326 0.75 + 0x008D90FA, //327 0.875 + 0x008F9E4C, //328 1 + 0x0091B33C, //329 1.125 + 0x0093CFE5, //330 1.25 + 0x0095F464, //331 1.375 + 0x009820D7, //332 1.5 + 0x009A555A, //333 1.625 + 0x009C920D, //334 1.75 + 0x009ED70C, //335 1.875 + 0x00A12477, //336 2 + 0x00A37A6E, //337 2.125 + 0x00A5D90F, //338 2.25 + 0x00A8407C, //339 2.375 + 0x00AAB0D4, //340 2.5 + 0x00AD2A39, //341 2.625 + 0x00AFACCC, //342 2.75 + 0x00B238B0, //343 2.875 + 0x00B4CE07, //344 3 + 0x00B76CF4, //345 3.125 + 0x00BA159B, //346 3.25 + 0x00BCC81F, //347 3.375 + 0x00BF84A6, //348 3.5 + 0x00C24B54, //349 3.625 + 0x00C51C4F, //350 3.75 + 0x00C7F7BE, //351 3.875 + 0x00CADDC7, //352 4 + 0x00CDCE92, //353 4.125 + 0x00D0CA46, //354 4.25 + 0x00D3D10B, //355 4.375 + 0x00D6E30C, //356 4.5 + 0x00DA0072, //357 4.625 + 0x00DD2966, //358 4.75 + 0x00E05E15, //359 4.875 + 0x00E39EA8, //360 5 + 0x00E6EB4E, //361 5.125 + 0x00EA4431, //362 5.25 + 0x00EDA980, //363 5.375 + 0x00F11B69, //364 5.5 + 0x00F49A1B, //365 5.625 + 0x00F825C5, //366 5.75 + 0x00FBBE96, //367 5.875 + 0x00FF64C1, //368 6 + 0x01031876, //369 6.125 + 0x0106D9E8, //370 6.25 + 0x010AA94A, //371 6.375 + 0x010E86CF, //372 6.5 + 0x011272AB, //373 6.625 + 0x01166D15, //374 6.75 + 0x011A7643, //375 6.875 + 0x011E8E6A, //376 7 + 0x0122B5C2, //377 7.125 + 0x0126EC84, //378 7.25 + 0x012B32EA, //379 7.375 + 0x012F892C, //380 7.5 + 0x0133EF86, //381 7.625 + 0x01386634, //382 7.75 + 0x013CED72, //383 7.875 + 0x0141857E, //384 8 + 0x01462E96, //385 8.125 + 0x014AE8F9, //386 8.25 + 0x014FB4E8, //387 8.375 + 0x015492A3, //388 8.5 + 0x0159826D, //389 8.625 + 0x015E8488, //390 8.75 + 0x01639939, //391 8.875 + 0x0168C0C5, //392 9 + 0x016DFB71, //393 9.125 + 0x01734985, //394 9.25 + 0x0178AB48, //395 9.375 + 0x017E2104, //396 9.5 + 0x0183AB02, //397 9.625 + 0x0189498F, //398 9.75 + 0x018EFCF5, //399 9.875 + 0x0194C583, //400 10 + 0x019AA387, //401 10.125 + 0x01A09751, //402 10.25 + 0x01A6A131, //403 10.375 + 0x01ACC179, //404 10.5 + 0x01B2F87D, //405 10.625 + 0x01B94691, //406 10.75 + 0x01BFAC0A, //407 10.875 + 0x01C62940, //408 11 + 0x01CCBE8A, //409 11.125 + 0x01D36C42, //410 11.25 + 0x01DA32C2, //411 11.375 + 0x01E11266, //412 11.5 + 0x01E80B8C, //413 11.625 + 0x01EF1E92, //414 11.75 + 0x01F64BD9, //415 11.875 + 0x01FD93C1, //416 12 + 0x0204F6AE, //417 12.125 + 0x020C7504, //418 12.25 + 0x02140F28, //419 12.375 + 0x021BC582, //420 12.5 + 0x0223987A, //421 12.625 + 0x022B887B, //422 12.75 + 0x023395F0, //423 12.875 + 0x023BC147, //424 13 + 0x02440AEE, //425 13.125 + 0x024C7356, //426 13.25 + 0x0254FAF2, //427 13.375 + 0x025DA234, //428 13.5 + 0x02666992, //429 13.625 + 0x026F5184, //430 13.75 + 0x02785A83, //431 13.875 + 0x02818508, //432 14 + 0x028AD191, //433 14.125 + 0x0294409B, //434 14.25 + 0x029DD2A7, //435 14.375 + 0x02A78836, //436 14.5 + 0x02B161CD, //437 14.625 + 0x02BB5FF1, //438 14.75 + 0x02C5832A, //439 14.875 + 0x02CFCC01, //440 15 + 0x02DA3B02, //441 15.125 + 0x02E4D0BA, //442 15.25 + 0x02EF8DB9, //443 15.375 + 0x02FA7292, //444 15.5 + 0x03057FD7, //445 15.625 + 0x0310B61F, //446 15.75 + 0x031C1602, //447 15.875 + 0x0327A01A, //448 16 + 0x03335504, //449 16.125 + 0x033F355F, //450 16.25 + 0x034B41CC, //451 16.375 + 0x03577AEF, //452 16.5 + 0x0363E16D, //453 16.625 + 0x037075EF, //454 16.75 + 0x037D3920, //455 16.875 + 0x038A2BAC, //456 17 + 0x03974E44, //457 17.125 + 0x03A4A19A, //458 17.25 + 0x03B22662, //459 17.375 + 0x03BFDD55, //460 17.5 + 0x03CDC72C, //461 17.625 + 0x03DBE4A4, //462 17.75 + 0x03EA367D, //463 17.875 + 0x03F8BD79, //464 18 + 0x04077A5E, //465 18.125 + 0x04166DF2, //466 18.25 + 0x04259902, //467 18.375 + 0x0434FC5C, //468 18.5 + 0x044498CF, //469 18.625 + 0x04546F30, //470 18.75 + 0x04648056, //471 18.875 + 0x0474CD1B, //472 19 + 0x0485565C, //473 19.125 + 0x04961CFA, //474 19.25 + 0x04A721D8, //475 19.375 + 0x04B865DE, //476 19.5 + 0x04C9E9F5, //477 19.625 + 0x04DBAF0C, //478 19.75 + 0x04EDB613, //479 19.875 + 0x05000000, //480 20 + 0x05128DCA, //481 20.125 + 0x0525606D, //482 20.25 + 0x053878EA, //483 20.375 + 0x054BD842, //484 20.5 + 0x055F7F7E, //485 20.625 + 0x05736FA7, //486 20.75 + 0x0587A9CD, //487 20.875 + 0x059C2F01, //488 21 + 0x05B1005B, //489 21.125 + 0x05C61EF5, //490 21.25 + 0x05DB8BEE, //491 21.375 + 0x05F14868, //492 21.5 + 0x0607558B, //493 21.625 + 0x061DB482, //494 21.75 + 0x0634667C, //495 21.875 + 0x064B6CAD, //496 22 + 0x0662C84F, //497 22.125 + 0x067A7A9D, //498 22.25 + 0x069284DB, //499 22.375 + 0x06AAE84D, //500 22.5 + 0x06C3A63F, //501 22.625 + 0x06DCC001, //502 22.75 + 0x06F636E8, //503 22.875 + 0x07100C4D, //504 23 + 0x072A418F, //505 23.125 + 0x0744D811, //506 23.25 + 0x075FD13C, //507 23.375 + 0x077B2E7F, //508 23.5 + 0x0796F14D, //509 23.625 + 0x07B31B1F, //510 23.75 + 0x07CFAD73, //511 23.875 + 0x07ECA9CD, //512 24 + 0x080A11B5, //513 24.125 + 0x0827E6BD, //514 24.25 + 0x08462A77, //515 24.375 + 0x0864DE80, //516 24.5 + 0x08840477, //517 24.625 + 0x08A39E04, //518 24.75 + 0x08C3ACD3, //519 24.875 + 0x08E43298, //520 25 + 0x0905310C, //521 25.125 + 0x0926A9EF, //522 25.25 + 0x09489F07, //523 25.375 + 0x096B1222, //524 25.5 + 0x098E0512, //525 25.625 + 0x09B179B2, //526 25.75 + 0x09D571E3, //527 25.875 + 0x09F9EF8E, //528 26 + 0x0A1EF4A1, //529 26.125 + 0x0A448314, //530 26.25 + 0x0A6A9CE4, //531 26.375 + 0x0A914416, //532 26.5 + 0x0AB87AB7, //533 26.625 + 0x0AE042DB, //534 26.75 + 0x0B089E9E, //535 26.875 + 0x0B319024, //536 27 + 0x0B5B1998, //537 27.125 + 0x0B853D2F, //538 27.25 + 0x0BAFFD24, //539 27.375 + 0x0BDB5BBC, //540 27.5 + 0x0C075B43, //541 27.625 + 0x0C33FE0E, //542 27.75 + 0x0C61467B, //543 27.875 + 0x0C8F36F2, //544 28 + 0x0CBDD1E0, //545 28.125 + 0x0CED19C0, //546 28.25 + 0x0D1D1113, //547 28.375 + 0x0D4DBA63, //548 28.5 + 0x0D7F1845, //549 28.625 + 0x0DB12D58, //550 28.75 + 0x0DE3FC43, //551 28.875 + 0x0E1787B8, //552 29 + 0x0E4BD272, //553 29.125 + 0x0E80DF37, //554 29.25 + 0x0EB6B0D7, //555 29.375 + 0x0EED4A2D, //556 29.5 + 0x0F24AE1D, //557 29.625 + 0x0F5CDF98, //558 29.75 + 0x0F95E199, //559 29.875 + 0x0FCFB724, //560 30 + 0x11BD9C84, //561 31dB + 0x13E7C594, //562 32dB + 0x16558CCB, //563 33dB + 0x190F3254, //564 34dB + 0x1C1DF80E, //565 35dB + 0x1F8C4107, //566 36dB + 0x2365B4BF, //567 37dB + 0x27B766C2, //568 38dB + 0x2C900313, //569 39dB + 0x32000000, //570 40dB + 0x3819D612, //571 41dB + 0x3EF23ECA, //572 42dB + 0x46A07B07, //573 43dB + 0x4F3EA203, //574 44dB + 0x58E9F9F9, //575 45dB + 0x63C35B8E, //576 46dB + 0x6FEFA16D, //577 47dB + 0x7D982575, //578 48dB }; +#define TAS5805_EQPARAM_LENGTH 610 +#define TAS5805_EQ_LENGTH 245 +#define FILTER_PARAM_BYTE 244 +static int m_eq_tab[TAS5805_EQPARAM_LENGTH][2] = {0}; +#define TAS5805_DRC_PARAM_LENGTH 29 +#define TAS5805_DRC_PARAM_COUNT 58 +static int m_drc_tab[TAS5805_DRC_PARAM_LENGTH][2] = {0}; struct tas5805m_priv { struct regmap *regmap; @@ -306,7 +732,6 @@ static void tas5805m_set_volume(struct snd_soc_codec *codec, int vol) uint8_t byte3; uint8_t byte2; uint8_t byte1; - pr_info("%s(), vol = %d\n", __func__, vol); index = get_volume_index(vol); volume_hex = tas5805m_volume[index]; @@ -392,21 +817,129 @@ static int tas5805m_mute_locked_get(struct snd_kcontrol *kcontrol, return 0; } +static int tas5805_set_EQ_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_get_EQ_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_set_DRC_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_get_DRC_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_set_DRC_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + void *data; + char tmp_string[TAS5805_DRC_PARAM_COUNT]; + char *p_string = &tmp_string[0]; + u8 *val; + unsigned int i = 0; + + data = kmemdup(ucontrol->value.bytes.data, + TAS5805_DRC_PARAM_COUNT, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + val = (u8 *)data; + memcpy(p_string, val, TAS5805_DRC_PARAM_COUNT); + + for (i = 0; i < TAS5805_DRC_PARAM_COUNT/2; i++) { + m_drc_tab[i][0] = tmp_string[2*i]; + m_drc_tab[i][1] = tmp_string[2*i+1]; + } + + for (i = 0; i < TAS5805_DRC_PARAM_LENGTH; i++) + snd_soc_write(codec, m_drc_tab[i][0], m_drc_tab[i][1]); + + kfree(data); + return 0; +} + +static int tas5805_get_DRC_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + + +static int tas5805_set_EQ_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + void *data; + char tmp_string[TAS5805_EQ_LENGTH]; + char *p_string = &tmp_string[0]; + u8 *val; + int band_id; + unsigned int i = 0, j = 0; + + data = kmemdup(ucontrol->value.bytes.data, + TAS5805_EQ_LENGTH, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + val = (u8 *) data; + memcpy(p_string, val, TAS5805_EQ_LENGTH); + band_id = tmp_string[0]; + for (j = 0, i = band_id * FILTER_PARAM_BYTE / 2; + j < FILTER_PARAM_BYTE / 2; i++, j++) { + m_eq_tab[i][0] = tmp_string[2*j+1]; + m_eq_tab[i][1] = tmp_string[2*j+2]; + } + if (band_id == 4) { + for (i = 0; i < TAS5805_EQPARAM_LENGTH; i++) + snd_soc_write(codec, m_eq_tab[i][0], m_eq_tab[i][1]); + } + kfree(data); + return 0; +} + +static int tas5805_get_EQ_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + + static const struct snd_kcontrol_new tas5805m_vol_control[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", + .name = "AMP Master Volume", .info = tas5805m_vol_info, .get = tas5805m_vol_locked_get, .put = tas5805m_vol_locked_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Maser Volume Mute", + .name = "AMP Maser Volume Mute", .info = tas5805m_mute_info, .get = tas5805m_mute_locked_get, .put = tas5805m_mute_locked_put, - } + }, + SOC_SINGLE_BOOL_EXT("AMP Set EQ Enable", 0, + tas5805_get_EQ_enum, tas5805_set_EQ_enum), + SOC_SINGLE_BOOL_EXT("AMP Set DRC Enable", 0, + tas5805_get_DRC_enum, tas5805_set_DRC_enum), + SND_SOC_BYTES_EXT("AMP EQ table", TAS5805_EQ_LENGTH, + tas5805_get_EQ_param, tas5805_set_EQ_param), + SND_SOC_BYTES_EXT("AMP DRC table", TAS5805_DRC_PARAM_COUNT, + tas5805_get_DRC_param, tas5805_set_DRC_param), }; static int tas5805m_set_bias_level(struct snd_soc_codec *codec, @@ -434,54 +967,6 @@ static int tas5805m_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int tas5805m_snd_probe(struct snd_soc_codec *codec) -{ - struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_add_codec_controls(codec, tas5805m_vol_control, - ARRAY_SIZE(tas5805m_vol_control)); - - tas5805m->codec = codec; - return ret; -} - -static int tas5805m_snd_suspend(struct snd_soc_codec *codec) -{ - dev_info(codec->dev, "tas5805m_suspend!\n"); - tas5805m_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int tas5805m_snd_resume(struct snd_soc_codec *codec) -{ - int ret; - struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - - dev_info(codec->dev, "tas5805m_snd_resume!\n"); - ret = - regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, - ARRAY_SIZE(tas5805m_init_sequence)); - if (ret != 0) { - dev_err(codec->dev, "Failed to initialize TAS5805M: %d\n", ret); - goto err; - } - - tas5805m_set_volume(codec, tas5805m->vol); - tas5805m_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -err: - return ret; -} - -static struct snd_soc_codec_driver soc_codec_tas5805m = { - .probe = tas5805m_snd_probe, - .suspend = tas5805m_snd_suspend, - .resume = tas5805m_snd_resume, - .set_bias_level = tas5805m_set_bias_level, -}; - static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *codec_dai) { @@ -510,10 +995,140 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, break; } } + return 0; +} +static int reset_tas5805m_GPIO(struct device *dev) +{ + struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + int ret = 0; + + if (pdata->reset_pin < 0) + return 0; + + ret = devm_gpio_request_one(dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, + "tas5805m-reset-pin"); + if (ret < 0) + return -1; + + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + mdelay(1); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + mdelay(5); return 0; } +static int tas5805m_snd_suspend(struct snd_soc_codec *codec) +{ + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + dev_info(codec->dev, "tas5805m_suspend!\n"); + tas5805m_set_bias_level(codec, SND_SOC_BIAS_OFF); + + if (pdata->reset_pin) + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + udelay(10); + return 0; +} + + +static int tas5805m_reg_init(struct snd_soc_codec *codec) +{ + int i, j = 0; + + for (j = 0; j < ARRAY_SIZE(tas5805m_reset); j++) { + snd_soc_write(codec, tas5805m_reset[j][0], + tas5805m_reset[j][1]); + }; + mdelay(10); + for (i = 0; i < ARRAY_SIZE(tas5805m_init_sequence); i++) { + snd_soc_write(codec, tas5805m_init_sequence[i][0], + tas5805m_init_sequence[i][1]); + }; + return 0; + +} + +static int tas5805m_snd_resume(struct snd_soc_codec *codec) +{ + int ret; + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + dev_info(codec->dev, "tas5805m_snd_resume!\n"); + + if (pdata->reset_pin) + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + + mdelay(3); + + ret = tas5805m_reg_init(codec); +// regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, +// ARRAY_SIZE(tas5805m_init_sequence)); + if (ret != 0) { + dev_err(codec->dev, "Failed to initialize TAS5805M: %d\n", ret); + goto err; + } + + tas5805m_set_volume(codec, tas5805m->vol); + tas5805m_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +err: + return ret; +} + + + + +static int tas5805m_probe(struct snd_soc_codec *codec) +{ + int ret; + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + +// ret = +// regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, +// ARRAY_SIZE(tas5805m_init_sequence)); + mdelay(20); + ret = tas5805m_reg_init(codec); + if (ret != 0) + goto err; + + if (tas5805m) + tas5805m_set_volume(codec, tas5805m->vol); + + snd_soc_add_codec_controls(codec, tas5805m_vol_control, + ARRAY_SIZE(tas5805m_vol_control)); + tas5805m->codec = codec; + return 0; + +err: + return ret; + +} + +static int tas5805m_remove(struct snd_soc_codec *codec) +{ + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + + if (pdata->reset_pin) + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + + udelay(10); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_tas5805m = { + .probe = tas5805m_probe, + .remove = tas5805m_remove, + .suspend = tas5805m_snd_suspend, + .resume = tas5805m_snd_resume, + .set_bias_level = tas5805m_set_bias_level, +}; + static const struct snd_soc_dai_ops tas5805m_dai_ops = { //.digital_mute = tas5805m_mute, .trigger = tas5805m_trigger, @@ -531,29 +1146,6 @@ static struct snd_soc_dai_driver tas5805m_dai = { .ops = &tas5805m_dai_ops, }; -static int reset_tas5805m_GPIO(struct device *dev) -{ - struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); - struct tas5805m_platform_data *pdata = tas5805m->pdata; - int ret = 0; - - if (pdata->reset_pin < 0) - return 0; - - ret = devm_gpio_request_one(dev, pdata->reset_pin, - GPIOF_OUT_INIT_LOW, - "tas5805m-reset-pin"); - if (ret < 0) - return -1; - - gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); - mdelay(1); - gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); - mdelay(1); - - return 0; -} - static int tas5805m_parse_dt( struct tas5805m_priv *tas5805m, struct device_node *np) @@ -574,34 +1166,6 @@ static int tas5805m_parse_dt( return ret; } -static int tas5805m_probe(struct device *dev, struct regmap *regmap) -{ - int ret; - - reset_tas5805m_GPIO(dev); - ret = - regmap_register_patch(regmap, tas5805m_init_sequence, - ARRAY_SIZE(tas5805m_init_sequence)); - if (ret != 0) { - dev_err(dev, "Failed to initialize TAS5805M: %d\n", ret); - goto err; - } - - ret = - snd_soc_register_codec(dev, &soc_codec_tas5805m, &tas5805m_dai, 1); - if (ret != 0) { - dev_err(dev, "Failed to register CODEC: %d\n", ret); - goto err; - } - - return 0; - -err: - return ret; - -} - - static int tas5805m_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -609,6 +1173,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c, struct regmap_config config = tas5805m_regmap; struct tas5805m_priv *tas5805m; struct tas5805m_platform_data *pdata; + int ret = 0; tas5805m = devm_kzalloc(&i2c->dev, sizeof(struct tas5805m_priv), GFP_KERNEL); @@ -634,19 +1199,20 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c, dev_set_drvdata(&i2c->dev, tas5805m); - return tas5805m_probe(&i2c->dev, regmap); -} + ret = + snd_soc_register_codec(&i2c->dev, &soc_codec_tas5805m, + &tas5805m_dai, 1); + if (ret != 0) + return -ENOMEM; -static int tas5805m_remove(struct device *dev) -{ - snd_soc_unregister_codec(dev); + reset_tas5805m_GPIO(&i2c->dev); - return 0; + return ret; } static int tas5805m_i2c_remove(struct i2c_client *i2c) { - tas5805m_remove(&i2c->dev); + devm_kfree(&i2c->dev, i2c_get_clientdata(i2c)); return 0; } diff --git a/sound/soc/codecs/amlogic/tas5805.h b/sound/soc/codecs/amlogic/tas5805.h index 5f3fdeb41b4d..46a211548eb3 100644 --- a/sound/soc/codecs/amlogic/tas5805.h +++ b/sound/soc/codecs/amlogic/tas5805.h @@ -1,1885 +1,1169 @@ #include -static const struct reg_sequence tas5805m_init_sequence[] = { - {0x00, 0x00}, - {0x7f, 0x00}, - {0x03, 0x02}, - {0x01, 0x11}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x29, 0x7c}, - {0x03, 0x02}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x29, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x46, 0x11}, - {0x03, 0x0f}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x02, 0x11},//Fsw=384kHz, BD Mode, 1SPW Mode - {0x66, 0x85}, - {0x6b, 0x03},//Enable SS - {0x6c, 0x03},//Set Tri-freq to 24Hz, SS range 336~432kHz - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x24, 0x00}, - {0x25, 0x28}, - {0x26, 0x7a}, - {0x27, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x28, 0x00}, - {0x29, 0x28}, - {0x2a, 0x7a}, - {0x2b, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x0b}, - {0x28, 0x00}, - {0x29, 0x80}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x0b}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x18, 0x00}, - {0x19, 0x80}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x24, 0x00}, - {0x25, 0x80}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x24, 0x00}, - {0x25, 0x28}, - {0x26, 0x7a}, - {0x27, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x28, 0x00}, - {0x29, 0x28}, - {0x2a, 0x7a}, - {0x2b, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x30, 0x00}, - {0x31, 0xe2}, - {0x32, 0xc4}, - {0x33, 0x6b}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x14, 0x00}, - {0x15, 0x80}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x1c, 0x00}, - {0x1d, 0x80}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x2c, 0x00}, - {0x2d, 0x80}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x34, 0x00}, - {0x35, 0x80}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x4c, 0x00}, - {0x4d, 0x80}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x57}, - {0x5f, 0x62}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x60, 0x00}, - {0x61, 0x03}, - {0x62, 0x69}, - {0x63, 0xd0}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x64, 0x00}, - {0x65, 0xce}, - {0x66, 0xc0}, - {0x67, 0x8a}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x68, 0x40}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x6c, 0x05}, - {0x6d, 0x1f}, - {0x6e, 0x97}, - {0x6f, 0x37}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x18, 0x7a}, - {0x19, 0xe0}, - {0x1a, 0x68}, - {0x1b, 0xc9}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0xae}, - {0x1f, 0xc3}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x2c, 0x00}, - {0x2d, 0x80}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x31}, - {0x48, 0x40}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x32}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x33}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x34}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x35}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x29}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x08, 0x00}, - {0x09, 0x80}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x48, 0x7f}, - {0x49, 0xff}, - {0x4a, 0xff}, - {0x4b, 0xff}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x58, 0x00}, - {0x59, 0x06}, - {0x5a, 0xd3}, - {0x5b, 0x72}, - {0x5c, 0x00}, - {0x5d, 0x02}, - {0x5e, 0xbb}, - {0x5f, 0x06}, - {0x60, 0x00}, - {0x61, 0x03}, - {0x62, 0x69}, - {0x63, 0xc5}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0xf9}, - {0x71, 0xda}, - {0x72, 0xbc}, - {0x73, 0x21}, - {0x74, 0xfc}, - {0x75, 0x58}, - {0x76, 0x8b}, - {0x77, 0x89}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2b}, - {0x34, 0x00}, - {0x35, 0x06}, - {0x36, 0xd3}, - {0x37, 0x72}, - {0x38, 0x00}, - {0x39, 0x02}, - {0x3a, 0xbb}, - {0x3b, 0x06}, - {0x3c, 0x00}, - {0x3d, 0x03}, - {0x3e, 0x69}, - {0x3f, 0xc5}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0xf9}, - {0x4d, 0xda}, - {0x4e, 0xbc}, - {0x4f, 0x21}, - {0x50, 0xfc}, - {0x51, 0x58}, - {0x52, 0x8b}, - {0x53, 0x89}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x34, 0x7f}, - {0x35, 0xff}, - {0x36, 0xff}, - {0x37, 0xff}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x30, 0x00}, - {0x31, 0x06}, - {0x32, 0xd3}, - {0x33, 0x72}, - {0x34, 0x00}, - {0x35, 0x02}, - {0x36, 0xbb}, - {0x37, 0x06}, - {0x38, 0x00}, - {0x39, 0x03}, - {0x3a, 0x69}, - {0x3b, 0xc5}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0xf9}, - {0x49, 0xda}, - {0x4a, 0xbc}, - {0x4b, 0x21}, - {0x4c, 0xfc}, - {0x4d, 0x58}, - {0x4e, 0x8b}, - {0x4f, 0x89}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x5c, 0x7f}, - {0x5d, 0xff}, - {0x5e, 0xff}, - {0x5f, 0xff}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x70, 0x7f}, - {0x71, 0xff}, - {0x72, 0xff}, - {0x73, 0xff}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2b}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2b}, - {0x0c, 0x7f}, - {0x0d, 0xff}, - {0x0e, 0xff}, - {0x0f, 0xff}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2b}, - {0x20, 0x7f}, - {0x21, 0xff}, - {0x22, 0xff}, - {0x23, 0xff}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2e}, - {0x40, 0x7f}, - {0x41, 0xff}, - {0x42, 0xff}, - {0x43, 0xff}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2e}, - {0x54, 0x7f}, - {0x55, 0xff}, - {0x56, 0xff}, - {0x57, 0xff}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x18, 0x00}, - {0x19, 0x80}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x1c, 0x40}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x20, 0x40}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, +//#define TAS5805_REGISTER_COUNT 1879 + +static const int tas5805m_reset[][2] = { +//RESET + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x02 }, + { 0x01, 0x11 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x02 }, +}; + +static const int tas5805m_init_sequence[][2] = { + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x46, 0x11 }, + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x02 }, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x78, 0x80 }, + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x61, 0x0b }, + { 0x60, 0x01 }, + + { 0x00, 0x00 }, + { 0x02, 0x11 },//Fsw=384kHz, BD Mode, 1SPW Mode + { 0x66, 0x85 }, + { 0x6b, 0x03 },//Enable SS + { 0x6c, 0x03 },//Set Tri-freq to 24Hz, SS range 336~432kHz + { 0x3a, 0xf8 }, + { 0x53, 0x00 }, + { 0x54, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x66, 0x87 }, + { 0x7f, 0x8c }, + { 0x00, 0x29 }, + { 0x18, 0x00 }, + { 0x19, 0x80 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x80 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x00, 0x2a }, + { 0x24, 0x00 }, + { 0x25, 0x28 }, + { 0x26, 0x7a }, + { 0x27, 0x27 }, + { 0x28, 0x00 }, + { 0x29, 0x28 }, + { 0x2a, 0x7a }, + { 0x2b, 0x27 }, + { 0x30, 0x00 }, + { 0x31, 0xe2 }, + { 0x32, 0xc4 }, + { 0x33, 0x6b }, + { 0x00, 0x2c }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x80 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x80 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x80 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x80 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x80 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0xae }, + { 0x5f, 0xc3 }, + { 0x60, 0x01 }, + { 0x61, 0x12 }, + { 0x62, 0x6e }, + { 0x63, 0x98 }, + { 0x64, 0x08 }, + { 0x65, 0x13 }, + { 0x66, 0x85 }, + { 0x67, 0x62 }, + { 0x68, 0x40 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x04 }, + { 0x6d, 0xc1 }, + { 0x6e, 0xff }, + { 0x6f, 0x93 }, + { 0x00, 0x2d }, + { 0x18, 0x7b }, + { 0x19, 0x3e }, + { 0x1a, 0x00 }, + { 0x1b, 0x6d }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0xae }, + { 0x1f, 0xc3 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x80 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0xaa }, + { 0x00, 0x24 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x25 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x26 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x27 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x28 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x29 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x00, 0x2e }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x2f }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x1c, 0x08 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x00, 0x2a }, + { 0x48, 0x00 }, + { 0x49, 0x05 }, + { 0x4a, 0x83 }, + { 0x4b, 0x2a }, + { 0x4c, 0x00 }, + { 0x4d, 0x05 }, + { 0x4e, 0x83 }, + { 0x4f, 0x2a }, + { 0x50, 0x00 }, + { 0x51, 0x05 }, + { 0x52, 0x83 }, + { 0x53, 0x2a }, + { 0x54, 0x7d }, + { 0x55, 0xa1 }, + { 0x56, 0x77 }, + { 0x57, 0x3d }, + { 0x58, 0x84 }, + { 0x59, 0xa7 }, + { 0x5a, 0x04 }, + { 0x5b, 0xdf }, + { 0x00, 0x00 }, + { 0x7f, 0x8c }, + { 0x00, 0x2b }, + { 0x34, 0x00 }, + { 0x35, 0x1b }, + { 0x36, 0x4b }, + { 0x37, 0x98 }, + { 0x38, 0x00 }, + { 0x39, 0x1b }, + { 0x3a, 0x4b }, + { 0x3b, 0x98 }, + { 0x3c, 0x00 }, + { 0x3d, 0x0d }, + { 0x3e, 0xa6 }, + { 0x3f, 0x86 }, + { 0x40, 0x00 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0xff }, + { 0x49, 0x81 }, + { 0x4a, 0x47 }, + { 0x4b, 0xae }, + { 0x4c, 0xf9 }, + { 0x4d, 0x06 }, + { 0x4e, 0x21 }, + { 0x4f, 0xa9 }, + { 0x50, 0xfe }, + { 0x51, 0x01 }, + { 0x52, 0xc0 }, + { 0x53, 0x79 }, + { 0x54, 0x00 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x00, 0x2d }, + { 0x58, 0x02 }, + { 0x59, 0xa3 }, + { 0x5a, 0x9a }, + { 0x5b, 0xcc }, + { 0x5c, 0x02 }, + { 0x5d, 0xa3 }, + { 0x5e, 0x9a }, + { 0x5f, 0xcc }, + { 0x60, 0x00 }, + { 0x61, 0x44 }, + { 0x62, 0x32 }, + { 0x63, 0x13 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x00 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0xff }, + { 0x6d, 0x81 }, + { 0x6e, 0x47 }, + { 0x6f, 0xae }, + { 0x70, 0xf9 }, + { 0x71, 0x06 }, + { 0x72, 0x21 }, + { 0x73, 0xa9 }, + { 0x74, 0xfe }, + { 0x75, 0x01 }, + { 0x76, 0xc0 }, + { 0x77, 0x79 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x00 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0xaa }, + { 0x00, 0x2e }, + { 0x40, 0x06 }, + { 0x41, 0x55 }, + { 0x42, 0xaf }, + { 0x43, 0xd8 }, + { 0x44, 0x06 }, + { 0x45, 0x55 }, + { 0x46, 0xaf }, + { 0x47, 0xd8 }, + { 0x48, 0x06 }, + { 0x49, 0x55 }, + { 0x4a, 0xaf }, + { 0x4b, 0xd8 }, + { 0x4c, 0x51 }, + { 0x4d, 0xe5 }, + { 0x4e, 0x7f }, + { 0x4f, 0x65 }, + { 0x50, 0xc2 }, + { 0x51, 0xde }, + { 0x52, 0x41 }, + { 0x53, 0xd5 }, + { 0x00, 0x2b }, + { 0x20, 0x58 }, + { 0x21, 0x3b }, + { 0x22, 0x2f }, + { 0x23, 0x3d }, + { 0x24, 0xa7 }, + { 0x25, 0xc4 }, + { 0x26, 0xd0 }, + { 0x27, 0xc3 }, + { 0x28, 0x58 }, + { 0x29, 0x3b }, + { 0x2a, 0x2f }, + { 0x2b, 0x3d }, + { 0x2c, 0x51 }, + { 0x2d, 0xe5 }, + { 0x2e, 0x7f }, + { 0x2f, 0x65 }, + { 0x30, 0xc2 }, + { 0x31, 0xde }, + { 0x32, 0x41 }, + { 0x33, 0xd5 }, + { 0x0c, 0x58 }, + { 0x0d, 0x3b }, + { 0x0e, 0x2f }, + { 0x0f, 0x3d }, + { 0x10, 0xa7 }, + { 0x11, 0xc4 }, + { 0x12, 0xd0 }, + { 0x13, 0xc3 }, + { 0x14, 0x58 }, + { 0x15, 0x3b }, + { 0x16, 0x2f }, + { 0x17, 0x3d }, + { 0x18, 0x51 }, + { 0x19, 0xe5 }, + { 0x1a, 0x7f }, + { 0x1b, 0x65 }, + { 0x1c, 0xc2 }, + { 0x1d, 0xde }, + { 0x1e, 0x41 }, + { 0x1f, 0xd5 }, + { 0x00, 0x2a }, + { 0x34, 0x00 }, + { 0x35, 0x05 }, + { 0x36, 0x83 }, + { 0x37, 0x2a }, + { 0x38, 0x00 }, + { 0x39, 0x05 }, + { 0x3a, 0x83 }, + { 0x3b, 0x2a }, + { 0x3c, 0x00 }, + { 0x3d, 0x05 }, + { 0x3e, 0x83 }, + { 0x3f, 0x2a }, + { 0x40, 0x7d }, + { 0x41, 0xa1 }, + { 0x42, 0x77 }, + { 0x43, 0x3d }, + { 0x44, 0x84 }, + { 0x45, 0xa7 }, + { 0x46, 0x04 }, + { 0x47, 0xdf }, + { 0x00, 0x00 }, + { 0x7f, 0x8c }, + { 0x00, 0x2d }, + { 0x30, 0x02 }, + { 0x31, 0xa3 }, + { 0x32, 0x9a }, + { 0x33, 0xcc }, + { 0x34, 0x02 }, + { 0x35, 0xa3 }, + { 0x36, 0x9a }, + { 0x37, 0xcc }, + { 0x38, 0x00 }, + { 0x39, 0x06 }, + { 0x3a, 0xd3 }, + { 0x3b, 0x72 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x00 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0xff }, + { 0x45, 0x81 }, + { 0x46, 0x47 }, + { 0x47, 0xae }, + { 0x48, 0xf9 }, + { 0x49, 0x06 }, + { 0x4a, 0x21 }, + { 0x4b, 0xa9 }, + { 0x4c, 0xfe }, + { 0x4d, 0x01 }, + { 0x4e, 0xc0 }, + { 0x4f, 0x79 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x00 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0xaa }, + { 0x00, 0x2a }, + { 0x5c, 0x7d }, + { 0x5d, 0xa6 }, + { 0x5e, 0xfa }, + { 0x5f, 0x66 }, + { 0x60, 0x82 }, + { 0x61, 0x59 }, + { 0x62, 0x05 }, + { 0x63, 0x9a }, + { 0x64, 0x7d }, + { 0x65, 0xa6 }, + { 0x66, 0xfa }, + { 0x67, 0x66 }, + { 0x68, 0x7d }, + { 0x69, 0xa1 }, + { 0x6a, 0x77 }, + { 0x6b, 0x3d }, + { 0x6c, 0x84 }, + { 0x6d, 0xa7 }, + { 0x6e, 0x04 }, + { 0x6f, 0xdf }, + { 0x70, 0x7d }, + { 0x71, 0xa6 }, + { 0x72, 0xfa }, + { 0x73, 0x66 }, + { 0x74, 0x82 }, + { 0x75, 0x59 }, + { 0x76, 0x05 }, + { 0x77, 0x9a }, + { 0x78, 0x7d }, + { 0x79, 0xa6 }, + { 0x7a, 0xfa }, + { 0x7b, 0x66 }, + { 0x7c, 0x7d }, + { 0x7d, 0xa1 }, + { 0x7e, 0x77 }, + { 0x7f, 0x3d }, + { 0x00, 0x2b }, + { 0x08, 0x84 }, + { 0x09, 0xa7 }, + { 0x0a, 0x04 }, + { 0x0b, 0xdf }, + { 0x00, 0x2e }, + { 0x54, 0x06 }, + { 0x55, 0x55 }, + { 0x56, 0xaf }, + { 0x57, 0xd8 }, + { 0x58, 0x06 }, + { 0x59, 0x55 }, + { 0x5a, 0xaf }, + { 0x5b, 0xd8 }, + { 0x5c, 0x06 }, + { 0x5d, 0x55 }, + { 0x5e, 0xaf }, + { 0x5f, 0xd8 }, + { 0x60, 0x51 }, + { 0x61, 0xe5 }, + { 0x62, 0x7f }, + { 0x63, 0x65 }, + { 0x64, 0xc2 }, + { 0x65, 0xde }, + { 0x66, 0x41 }, + { 0x67, 0xd5 }, + { 0x00, 0x00 }, + { 0x7f, 0x8c }, + { 0x00, 0x2e }, + { 0x10, 0x00 }, + { 0x11, 0x80 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x80 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x08, 0x00 }, + { 0x09, 0x80 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x18, 0x00 }, + { 0x19, 0x80 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x40 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x40 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + //Register Tuning - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x30, 0x00}, - {0x60, 0x00}, - {0x62, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x4c, 0x30}, - {0x4d, 0x30}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x02, 0x11},//Fsw=384kHz, 1SPW Mode - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x03, 0x03}, - {0x35, 0x11}, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x30, 0x00 }, + { 0x4c, 0x30 }, + { 0x03, 0x03 }, + { 0x02, 0x11 },//Fsw=384kHz, 1SPW Mode + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x78, 0x80 }, }; struct tas5805m_platform_data { From b157b2fb93746a3d5c0e75992ca915ca3a64345e Mon Sep 17 00:00:00 2001 From: Zhe Wang Date: Wed, 17 Apr 2019 13:38:43 +0800 Subject: [PATCH 0637/1060] audio: TM2 bringup: enable ADC for linein [1/1] PD#SWPL-7027 Problem: audio path AVin is on audio Solution: enable ADC for linein Verify: Verify on AB311 Change-Id: Iea1d694e0b605d62596635d85416d33f56dbbcb2 Signed-off-by: Zhe Wang Conflicts: arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts sound/soc/codecs/amlogic/ad82584f.c --- MAINTAINERS | 1 + arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 2 +- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 1 + arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 1 + .../boot/dts/amlogic/tl1_t962x2_x301_1g.dts | 1920 +++++++++++++++++ .../arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 3 +- .../boot/dts/amlogic/tl1_t962x2_t309.dts | 1819 ++++++++++++++++ .../boot/dts/amlogic/tl1_t962x2_x301_1g.dts | 1880 ++++++++++++++++ .../boot/dts/amlogic/tl1_t962x2_x301_2g.dts | 1875 ++++++++++++++++ .../boot/dts/amlogic/tm2_t962x3_ab301.dts | 3 +- sound/soc/amlogic/auge/tdm_match_table.c | 7 +- sound/soc/codecs/amlogic/ad82584f.c | 19 +- sound/soc/codecs/amlogic/tas5805.c | 12 +- 13 files changed, 7525 insertions(+), 18 deletions(-) create mode 100644 arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts create mode 100644 arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts create mode 100644 arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts create mode 100644 arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts diff --git a/MAINTAINERS b/MAINTAINERS index c4ba5ed396a4..f0721818943c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14434,6 +14434,7 @@ F: include/linux/amlogic/meson_cooldev.h AMLOGIC G12A Audio DRIVER M: Xing Wang F: sound/soc/amlogic/auge/* +F: sound/soc/codec/amlogic/* AMLOGIC G12A BL_EXTERN LP8556 DRIVER M: Weiming Liu diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 9bbe37348fff..0138f07b5ace 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -243,7 +243,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&ad82584f &tl1_codec>; + sound-dai = ; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index fa172a9e9ef7..8804f2322a20 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -302,6 +302,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; sound-dai = <&ad82584f &tl1_codec>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 4fc4802831d6..b53d4529fa30 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -262,6 +262,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; sound-dai = <&ad82584f &tl1_codec>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts new file mode 100644 index 000000000000..44d93df9490e --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -0,0 +1,1920 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 X301"; + amlogic-dt-id = "tl1_t962x2_x301-1g"; + compatible = "amlogic, tl1_t962x2_x301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x3ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0xd000000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + alloc-ranges = <0x00000000 0x30000000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + alloc-ranges = <0x00000000 0x30000000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + alloc-ranges = <0x00000000 0x30000000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index 7cf4e6f08500..b024f19337ea 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -321,7 +321,8 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&tl1_codec &tas5805>; + prefix-names = "AMP"; + sound-dai = <&tas5805 &tl1_codec>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts new file mode 100644 index 000000000000..0c8977295e6e --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -0,0 +1,1819 @@ +/* + * arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_t309-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 T309"; + amlogic-dt-id = "tl1_t962x2_t309"; + compatible = "amlogic, tl1_t962x2_t309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + pinctrl-names="dtvdemod_agc_pins"; + pinctrl-0=<&dtvdemod_agc_pins>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * MASTER_TO_SLAVE_XTAL_IN(1) + * MASTER_TO_SLAVE_XTAL_OUT(2) + * SLAVE_XTAL_OUT(3) + */ + tuner_xtal_cap_0 = <38>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + pinctrl-names="atvdemod_agc_pins"; + pinctrl-0=<&atvdemod_agc_pins>; + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + * FRHDMIRX, 8 + */ + resample_module = <8>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x0 0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x0 0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x0 0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x0 0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x0 0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts new file mode 100644 index 000000000000..93566583937c --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -0,0 +1,1880 @@ +/* + * arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 X301"; + amlogic-dt-id = "tl1_t962x2_x301-1g"; + compatible = "amlogic, tl1_t962x2_x301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0xd000000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + alloc-ranges = <0x0 0x30000000 0x0 0x10000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x00000000 0x0 0x30000000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x30000000 0x0 0x10000000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x30000000 0x0 0x10000000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x00000000 0x0 0x30000000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x00000000 0x0 0x30000000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts new file mode 100644 index 000000000000..17b68c35d97e --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts @@ -0,0 +1,1875 @@ +/* + * arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 X301"; + amlogic-dt-id = "tl1_t962x2_x301-2g"; + compatible = "amlogic, tl1_t962x2_x301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + * FRHDMIRX, 8 + */ + resample_module = <8>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts index 497aa79460ae..735d303f8cf7 100644 --- a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -325,7 +325,8 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&tl1_codec &tas5805>; + prefix-names = "AMP"; + sound-dai = <&tas5805 &tl1_codec>; }; }; diff --git a/sound/soc/amlogic/auge/tdm_match_table.c b/sound/soc/amlogic/auge/tdm_match_table.c index 75195c57ee0a..4fb318c38857 100644 --- a/sound/soc/amlogic/auge/tdm_match_table.c +++ b/sound/soc/amlogic/auge/tdm_match_table.c @@ -137,7 +137,8 @@ struct tdm_chipinfo tm2_tdma_chipinfo = { .sclk_ws_inv = true, .oe_fn = true, .same_src_fn = true, - .lane_cnt = LANE_MAX1, + .adc_fn = true, + .lane_cnt = LANE_MAX3, }; struct tdm_chipinfo tm2_tdmb_chipinfo = { @@ -145,7 +146,8 @@ struct tdm_chipinfo tm2_tdmb_chipinfo = { .sclk_ws_inv = true, .oe_fn = true, .same_src_fn = true, - .lane_cnt = LANE_MAX3, + .adc_fn = true, + .lane_cnt = LANE_MAX1, }; struct tdm_chipinfo tm2_tdmc_chipinfo = { @@ -153,6 +155,7 @@ struct tdm_chipinfo tm2_tdmc_chipinfo = { .sclk_ws_inv = true, .oe_fn = true, .same_src_fn = true, + .adc_fn = true, .lane_cnt = LANE_MAX1, }; diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index 60b2598032fe..3fd69a66ea92 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -36,15 +36,15 @@ static const DECLARE_TLV_DB_SCALE(mvol_tlv, -10300, 50, 1); static const DECLARE_TLV_DB_SCALE(chvol_tlv, -10300, 50, 1); static const struct snd_kcontrol_new ad82584f_snd_controls[] = { - SOC_SINGLE_TLV("AMP Master Volume", MVOL, 0, + SOC_SINGLE_TLV("Master Volume", MVOL, 0, 0xff, 1, mvol_tlv), - SOC_SINGLE_TLV("AMP Ch1 Volume", C1VOL, 0, + SOC_SINGLE_TLV("Ch1 Volume", C1VOL, 0, 0xff, 1, chvol_tlv), - SOC_SINGLE_TLV("AMP Ch2 Volume", C2VOL, 0, + SOC_SINGLE_TLV("Ch2 Volume", C2VOL, 0, 0xff, 1, chvol_tlv), - SOC_SINGLE("AMP Ch1 Switch", MUTE, 5, 1, 1), - SOC_SINGLE("AMP Ch2 Switch", MUTE, 4, 1, 1), + SOC_SINGLE("Ch1 Switch", MUTE, 5, 1, 1), + SOC_SINGLE("Ch2 Switch", MUTE, 4, 1, 1), }; static int ad82584f_reg_init(struct snd_soc_codec *codec); @@ -827,8 +827,13 @@ static int ad82584f_init(struct snd_soc_codec *codec) /* eq and drc */ ad82584f_set_eq_drc(codec); - /*unmute,default power-on is mute.*/ - /*snd_soc_write(codec, 0x02, 0x00);*/ + /* for de-pop */ + udelay(100); + + snd_soc_write(codec, MVOL, 0x11); + + /* unmute, default power-on is mute. */ + snd_soc_write(codec, MUTE, 0x00); return 0; } diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c index 84fb189b00e8..e6f8d21c10a1 100644 --- a/sound/soc/codecs/amlogic/tas5805.c +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -920,25 +920,25 @@ static int tas5805_get_EQ_param(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new tas5805m_vol_control[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "AMP Master Volume", + .name = "Master Volume", .info = tas5805m_vol_info, .get = tas5805m_vol_locked_get, .put = tas5805m_vol_locked_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "AMP Maser Volume Mute", + .name = "Maser Volume Mute", .info = tas5805m_mute_info, .get = tas5805m_mute_locked_get, .put = tas5805m_mute_locked_put, }, - SOC_SINGLE_BOOL_EXT("AMP Set EQ Enable", 0, + SOC_SINGLE_BOOL_EXT("Set EQ Enable", 0, tas5805_get_EQ_enum, tas5805_set_EQ_enum), - SOC_SINGLE_BOOL_EXT("AMP Set DRC Enable", 0, + SOC_SINGLE_BOOL_EXT("Set DRC Enable", 0, tas5805_get_DRC_enum, tas5805_set_DRC_enum), - SND_SOC_BYTES_EXT("AMP EQ table", TAS5805_EQ_LENGTH, + SND_SOC_BYTES_EXT("EQ table", TAS5805_EQ_LENGTH, tas5805_get_EQ_param, tas5805_set_EQ_param), - SND_SOC_BYTES_EXT("AMP DRC table", TAS5805_DRC_PARAM_COUNT, + SND_SOC_BYTES_EXT("DRC table", TAS5805_DRC_PARAM_COUNT, tas5805_get_DRC_param, tas5805_set_DRC_param), }; From 3a03ee7c2e3d365d52a940243e4fe84cae890378 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Fri, 17 May 2019 14:56:01 +0900 Subject: [PATCH 0638/1060] ODROID-N2: Merge amlogic BSP 2019.0415 (fix build err) Change-Id: I1987cce33154a36658b066f44ce1463d267d0043 --- .../media/enhancement/amvecm/amcm_regmap.h | 166 ++++++++++++++++++ sound/soc/amlogic/auge/ddr_mngr.c | 76 ++------ sound/soc/amlogic/auge/ddr_mngr.h | 36 ++-- sound/soc/amlogic/auge/resample.c | 11 +- sound/soc/amlogic/auge/sharebuffer.c | 7 +- sound/soc/amlogic/auge/spdif.c | 46 ++--- sound/soc/amlogic/auge/spdif_hw.c | 22 ++- sound/soc/amlogic/auge/spdif_hw.h | 4 +- sound/soc/amlogic/auge/tdm.c | 52 ++++-- 9 files changed, 272 insertions(+), 148 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h index 1c2c3d30bf89..bf8a1aa37064 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h @@ -918,6 +918,172 @@ static struct am_regs_s cmreg_enhancement = { } }; +/*sr0 sharpness reg*/ +struct am_regs_s sr0reg_cvbs = { + 109, + { + {REG_TYPE_VCBUS, SHARP0_SHARP_HVSIZE, 0xffffffff, 0x02d00240}, + {REG_TYPE_VCBUS, SHARP0_SHARP_HVBLANK_NUM, 0xffffffff, 0x00001e58}, + {REG_TYPE_VCBUS, SHARP0_NR_GAUSSIAN_MODE, 0xffffffff, 0x00000010}, + {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_L, 0xffffffff, 0x56667ac8}, + {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_H, 0xffffffff, 0x00000004}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_LIMIT, + 0xffffffff, 0x50845e00}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_LIMIT, + 0xffffffff, 0x508d5000}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_LIMIT, + 0xffffffff, 0x3d3d1f00}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_LIMIT, + 0xffffffff, 0x38390c00}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_LPF_MODE, 0xffffffff, 0x22202220}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_LPF_MODE, 0xffffffff, 0x22202220}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_HP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_HP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_BP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BLEND_GAIN, 0xffffffff, 0x38402840}, + {REG_TYPE_VCBUS, SHARP0_NR_ALPY_SSD_GAIN_OFST, + 0xffffffff, 0x0000103e}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_TH_RATE, + 0xffffffff, 0x0a195040}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_LIMIT, + 0xffffffff, 0x3f003f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_TH_RATE, + 0xffffffff, 0x0a195040}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_LIMIT, + 0xffffffff, 0x3f003f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0_MIN_MAX, 0xffffffff, 0x003f003f}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIERR_CORING, + 0xffffffff, 0x00000003}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_TH_RATE, + 0xffffffff, 0x00180014}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_LIMIT, + 0xffffffff, 0x00103f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIN_MAX, 0xffffffff, 0x003f003f}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIERR_CORING, + 0xffffffff, 0x00010001}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_TH_RATE, + 0xffffffff, 0x0018000a}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_LIMIT, + 0xffffffff, 0x00402000}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIN_MAX, 0xffffffff, 0x0000003f}, + {REG_TYPE_VCBUS, SHARP0_PK_FINALGAIN_HP_BP, + 0xffffffff, 0x00001414}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_HORZ_CORE_GAIN, + 0xffffffff, 0x08140214}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_VERT_CORE_GAIN, + 0xffffffff, 0x08140214}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_ADPT_MISC, + 0xffffffff, 0x2806c814}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_STATIC, 0xffffffff, 0x2203f03f}, + {REG_TYPE_VCBUS, SHARP0_PK_NR_ENABLE, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_PK_DRT_SAD_MISC, 0xffffffff, 0x12120018}, + {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xffffffff, 0x00000407}, + {REG_TYPE_VCBUS, SHARP0_TI_DIR_CORE_ALPHA, 0xffffffff, 0x0a00003f}, + {REG_TYPE_VCBUS, SHARP0_CTI_DIR_ALPHA, 0xffffffff, 0x0400003f}, + {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DF_GAIN, 0xffffffff, 0x0c0c0c0c}, + {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DIR_AC_DBG, 0xffffffff, 0x56ee0000}, + {REG_TYPE_VCBUS, SHARP0_HCTI_FLT_CLP_DC, 0xffffffff, 0x05555300}, + {REG_TYPE_VCBUS, SHARP0_HCTI_BST_GAIN, 0xffffffff, 0x050a0a00}, + {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xffffffff, 0x03030303}, + {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, + {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_1, 0xffffffff, 0x4b055014}, + {REG_TYPE_VCBUS, SHARP0_HCTI_OS_MARGIN, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_HLTI_FLT_CLP_DC, 0xffffffff, 0x00152100}, + {REG_TYPE_VCBUS, SHARP0_HLTI_BST_GAIN, 0xffffffff, 0x06060600}, + {REG_TYPE_VCBUS, SHARP0_HLTI_BST_CORE, 0xffffffff, 0x03030303}, + {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, + {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_1, 0xffffffff, 0x66635e24}, + {REG_TYPE_VCBUS, SHARP0_HLTI_OS_MARGIN, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_VLTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, + {REG_TYPE_VCBUS, SHARP0_VLTI_BST_GAIN, 0xffffffff, 0x00202020}, + {REG_TYPE_VCBUS, SHARP0_VLTI_BST_CORE, 0xffffffff, 0x00050503}, + {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, + {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, + {REG_TYPE_VCBUS, SHARP0_VCTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, + {REG_TYPE_VCBUS, SHARP0_VCTI_BST_GAIN, 0xffffffff, 0x00101010}, + {REG_TYPE_VCBUS, SHARP0_VCTI_BST_CORE, 0xffffffff, 0x00050503}, + {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, + {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, + {REG_TYPE_VCBUS, SHARP0_SHARP_3DLIMIT, 0xffffffff, 0x03c0021c}, + /*{REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CTRL, 0xffffffff, 0x0018103c},*/ + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_MISC, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_SR3_SAD_CTRL, 0xffffffff, 0x060606ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL0, 0xffffffff, 0x00000ffc}, + {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL1, 0xffffffff, 0x112020cc}, + {REG_TYPE_VCBUS, SHARP0_DEJ_CTRL, 0xffffffff, 0x0000000f}, + {REG_TYPE_VCBUS, SHARP0_DEJ_ALPHA, 0xffffffff, 0x0f0f4646}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_EN, 0xffffffff, 0x00000037}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_0, + 0xffffffff, 0x0405050c}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_1, + 0xffffffff, 0x01040708}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_2, + 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_OFST, + 0xffffffff, 0x000e000e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_CTRL, + 0xffffffff, 0x1392281c}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_0TO3, + 0xffffffff, 0xffffc81e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_4TO6, + 0xffffffff, 0x001832ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_0TO3, + 0xffffffff, 0xffffc81e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_4TO6, + 0xffffffff, 0x001832ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_MADSAD, + 0xffffffff, 0x00000048}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_VR2MAX, + 0xffffffff, 0xffffec20}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_PARAM0, + 0xffffffff, 0x000a2010}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_THETA, + 0xffffffff, 0xfec96420}, + {REG_TYPE_VCBUS, SHARP0_SATPRT_CTRL, 0xffffffff, 0x00054006}, + {REG_TYPE_VCBUS, SHARP0_SATPRT_DIVM, 0xffffffff, 0x00808080}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_CTRL, 0xffffffff, 0x06e222fa}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_YC_THRD, + 0xffffffff, 0x97659765}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_RANDLUT, + 0xffffffff, 0x00249249}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_PXI_THRD, + 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_Y, 0xffffffff, 0x60a52f20}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_U, 0xffffffff, 0x60a52f27}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_V, 0xffffffff, 0x60a52f22}, + {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_L, + 0xffffffff, 0x56667ac8}, + {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_H, + 0xffffffff, 0x00000004}, + {0} + } +}; + /*sr1 sharpness reg*/ struct am_regs_s sr1reg_sd_scale = { 109, diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index a12a337ce159..8cd7392e88d4 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -494,8 +494,9 @@ unsigned int aml_toddr_read1(struct toddr *to) unsigned int reg_base = to->reg_base; unsigned int reg; - reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30); + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + + return aml_audiobus_read(actrl, reg); } void aml_toddr_write1(struct toddr *to, unsigned int val) @@ -577,7 +578,7 @@ static void aml_resample_enable( pr_info("toddr %d selects data to %s resample_%c for module:%s\n", to->fifo_id, enable ? "enable" : "disable", - (p_attach_resample->id == 0) ? 'a' : 'b', + (p_attach_resample->id == RESAMPLE_A) ? 'a' : 'b', toddr_src_get_str(p_attach_resample->attach_module) ); @@ -1010,8 +1011,8 @@ int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) && (frddrs[i].fifo_id != current_fifo_id) && (frddrs[i].dest == ss_sel)) { - pr_info(" frddr:%d, ss_sel:%d used, invalid for share buffer\n", - i, + pr_debug("%s, ss_sel:%d used, not for share buffer at same time\n", + __func__, ss_sel); ret = 0; break; @@ -1239,69 +1240,14 @@ void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst) void aml_frddr_select_dst_ss(struct frddr *fr, enum frddr_dest dst, int sel, bool enable) { - struct aml_audio_controller *actrl = fr->actrl; - unsigned int reg_base = fr->reg_base; - unsigned int reg, ss_valid; - - ss_valid = aml_check_sharebuffer_valid(fr, dst); + unsigned int ss_valid = aml_check_sharebuffer_valid(fr, dst); /* same source en */ if (fr->chipinfo && fr->chipinfo->same_src_fn - && ss_valid) { - int s_v = 0, s_m = 0; - - if (fr->chipinfo - && fr->chipinfo->src_sel_ctrl) { - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, - reg_base); - - switch (sel) { - case 1: - s_m = 0x17 << 8; - s_v = enable ? - (dst << 8 | 1 << 12) : 0 << 8; - break; - case 2: - s_m = 0x17 << 16; - s_v = enable ? - (dst << 16 | 1 << 20) : 0 << 16; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; - } - s_m |= 0xff << 24; - if (enable) - s_v |= (fr->channels - 1) << 24; - else - s_v |= 0x0 << 24; - } else { - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, - reg_base); - - switch (sel) { - case 1: - s_m = 0xf << 4; - s_v = enable ? - (dst << 4 | 1 << 7) : 0 << 4; - break; - case 2: - s_m = 0xf << 8; - s_v = enable ? - (dst << 8 | 1 << 11) : 0 << 8; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; - } - } - pr_debug("%s sel:%d, dst_src:%d\n", - __func__, sel, dst); - aml_audiobus_update_bits(actrl, reg, s_m, s_v); - } + && ss_valid + ) + frddr_set_sharebuffer_enable(fr, dst, sel, enable); } void aml_frddr_set_fifos(struct frddr *fr, @@ -1482,7 +1428,7 @@ static const char *const toddr_src_sel_texts[] = { "TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN", "PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A", "FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB", - "EARCRX_DMAC", "RESERVED", "RESERVED", "RESERVED", + "EARCRX_DMAC", "RESERVED_0", "RESERVED_1", "RESERVED_2", "VAD" }; diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index 2327ef569ce3..c787662707d0 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -42,19 +42,29 @@ enum ddr_types { * from tl1, add new source FRATV, FRHDMIRX, LOOPBACK_B, SPDIFIN_LB, VAD */ enum toddr_src { - TDMIN_A, - TDMIN_B, - TDMIN_C, - SPDIFIN, - PDMIN, - FRATV, /* NONE for axg, g12a, g12b */ - TDMIN_LB, - LOOPBACK_A, - FRHDMIRX, /* from tl1 chipset*/ - LOOPBACK_B, - SPDIFIN_LB, - EARCRX_DMAC, /* from sm1 chipset */ - VAD, + TODDR_INVAL = -1, + TDMIN_A = 0, + TDMIN_B = 1, + TDMIN_C = 2, + SPDIFIN = 3, + PDMIN = 4, + FRATV = 5, /* NONE for axg, g12a, g12b */ + TDMIN_LB = 6, + LOOPBACK_A = 7, + FRHDMIRX = 8, /* from tl1 chipset*/ + LOOPBACK_B = 9, + SPDIFIN_LB = 10, + EARCRX_DMAC = 11,/* from sm1 chipset */ + RESERVED_0 = 12, + RESERVED_1 = 13, + RESERVED_2 = 14, + VAD = 15, + TODDR_SRC_MAX = 16 +}; + +enum resample_idx { + RESAMPLE_A, + RESAMPLE_B }; enum resample_src { diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 21e6f4de92f6..f3a99483eec3 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -286,13 +286,10 @@ int resample_set(enum resample_idx id, enum samplerate_index index) #endif p_resample->asrc_rate_idx = index; - pr_info("%s resample_%c %s\n", - __func__, - (id == 0) ? 'a' : 'b', - auge_resample_texts[index]); - - if (audio_resample_set(p_resample, (bool)index, resample_rate)) - return 0; + resample_rate = resample_idx2rate(index); + ret = audio_resample_set(p_resample, (bool)index, resample_rate); + if (ret) + return ret; if (index == RATE_OFF) resample_disable(p_resample->id); diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index 1ad5695427b5..1a740c4a166a 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -36,7 +36,8 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - true); + true, + lane_i2s); /* spdif to hdmitx */ spdifout_to_hdmitx_ctrl(spdif_id); @@ -63,7 +64,7 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - false); + false, 0); return 0; } @@ -95,7 +96,7 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream, } else if (samesource_sel < 5) { /* same source with spdif a/b */ sharebuffer_spdifout_prepare(substream, - fr, samesource_sel - 3); + fr, samesource_sel - 3, lane_i2s); } /* frddr, share buffer, src_sel1 */ diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index dbc00d86f268..6ad5326d7139 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -39,7 +39,6 @@ #include "audio_utils.h" #include "resample.h" #include "resample_hw.h" -#include "spdif.h" #define DRV_NAME "snd_spdif" @@ -80,7 +79,7 @@ struct aml_spdif { /* external connect */ struct extcon_dev *edev; - enum SPDIF_ID id; + unsigned int id; struct spdif_chipinfo *chipinfo; unsigned int clk_cont; /* CONTINUOUS CLOCK */ @@ -158,20 +157,6 @@ static const char *const spdifin_samplerate[] = { "192000" }; -struct aml_spdif *spdif_priv[SPDIF_ID_CNT]; -int spdif_set_audio_clk(enum SPDIF_ID id, - struct clk *clk_src, int rate, bool same) -{ - if (spdif_priv[id]->on && same) { - pr_debug("spdif priority"); - return 0; - } - - clk_set_parent(spdif_priv[id]->clk_spdifout, clk_src); - clk_set_rate(spdif_priv[id]->clk_spdifout, rate); - return 0; -} - static int spdifin_samplerate_get_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -685,7 +670,6 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, RATE_OFF); #endif -#endif #endif } if (intrpt_status & 0x10) @@ -763,7 +747,6 @@ static int aml_spdif_open(struct snd_pcm_substream *substream) snd_soc_set_runtime_hwparams(substream, &aml_spdif_hardware); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - p_spdif->on = 1; p_spdif->fddr = aml_audio_register_frddr(dev, p_spdif->actrl, aml_spdif_ddr_isr, substream); @@ -809,7 +792,6 @@ static int aml_spdif_close(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { aml_audio_unregister_frddr(p_spdif->dev, substream); - p_spdif->on = 0; } else { aml_audio_unregister_toddr(p_spdif->dev, substream); free_irq(p_spdif->irq_spdifin, p_spdif); @@ -823,7 +805,7 @@ static int aml_spdif_close(struct snd_pcm_substream *substream) } /* clear extcon status */ - if (p_spdif->id == SPDIF_A) { + if (p_spdif->id == 0) { extcon_set_state(p_spdif->edev, EXTCON_SPDIFIN_SAMPLERATE, 0); @@ -969,7 +951,7 @@ static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd) pr_debug("%s spdif_%s, clk continuous:%d\n", __func__, - (p_spdif->id == SPDIF_A) ? "a":"b", + (p_spdif->id == 0) ? "a":"b", p_spdif->clk_cont); /* keep frddr when probe, after spdif_frddr_init done @@ -1025,7 +1007,7 @@ static int aml_dai_spdif_startup( if (p_spdif->clk_cont) { pr_info("spdif_%s keep clk continuous\n", - (p_spdif->id == SPDIF_A) ? "a":"b"); + (p_spdif->id == 0) ? "a":"b"); return 0; } /* enable clock gate */ @@ -1098,7 +1080,7 @@ static void aml_dai_spdif_shutdown( if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (p_spdif->clk_cont) { pr_info("spdif_%s keep clk continuous\n", - (p_spdif->id == SPDIF_A) ? "a":"b"); + (p_spdif->id == 0) ? "a":"b"); return; } @@ -1109,7 +1091,7 @@ static void aml_dai_spdif_shutdown( #ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disabled, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); #endif clk_disable_unprepare(p_spdif->clk_spdifin); clk_disable_unprepare(p_spdif->fixed_clk); @@ -1135,10 +1117,10 @@ static int aml_dai_spdif_prepare( struct iec958_chsts chsts; switch (p_spdif->id) { - case SPDIF_A: + case 0: dst = SPDIFOUT_A; break; - case SPDIF_B: + case 1: dst = SPDIFOUT_B; break; default: @@ -1287,9 +1269,6 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "S/PDIF Playback disable\n"); - memset(substream->runtime->dma_area, - 0, substream->runtime->dma_bytes); - mdelay(3); aml_frddr_enable(p_spdif->fddr, 0); } else { dev_info(substream->pcm->card->dev, "S/PDIF Capture disable\n"); @@ -1360,10 +1339,8 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif) mpll_freq = p_spdif->sysclk_freq * 58 / 2; /* 96k */ #endif clk_set_rate(p_spdif->sysclk, mpll_freq); - //clk_set_rate(p_spdif->clk_spdifout, - // p_spdif->sysclk_freq); - spdif_set_audio_clk(p_spdif->id, - p_spdif->sysclk, p_spdif->sysclk_freq, 0); + clk_set_rate(p_spdif->clk_spdifout, + p_spdif->sysclk_freq); ret = clk_prepare_enable(p_spdif->sysclk); if (ret) { @@ -1458,7 +1435,7 @@ static int aml_spdif_parse_of(struct platform_device *pdev) int ret = 0; /* clock for spdif in */ - if (p_spdif->id == SPDIF_A) { + if (p_spdif->id == 0) { /* clock gate */ p_spdif->gate_spdifin = devm_clk_get(dev, "gate_spdifin"); if (IS_ERR(p_spdif->gate_spdifin)) { @@ -1592,7 +1569,6 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) dev_warn_once(dev, "check whether to update spdif chipinfo\n"); - spdif_priv[aml_spdif->id] = aml_spdif; pr_debug("%s, spdif ID = %u\n", __func__, aml_spdif->id); /* get audio controller */ diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 69009946d047..930e723b126d 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -420,13 +420,18 @@ static void spdifout_clk_ctrl(int spdif_id, bool is_enable) } #endif static void spdifout_fifo_ctrl(int spdif_id, - int fifo_id, int bitwidth, int channels) + int fifo_id, int bitwidth, int channels, int lane_i2s) { unsigned int frddr_type = spdifout_get_frddr_type(bitwidth); unsigned int offset, reg, i, chmask = 0; + unsigned int swap_masks = 0; - for (i = 0; i < channels; i++) - chmask |= (1 << i); + /* spdif always masks two channel */ + if (lane_i2s * 2 >= channels) { + pr_err("invalid lane(%d) and channels(%d)\n", + lane_i2s, channels); + return; + } for (i = 0; i < channels; i++) chmask |= (1 << i); @@ -445,8 +450,8 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; audiobus_update_bits(reg, - 0x3<<21|0x1<<20|0x1<<19|0xff<<4, - 0x0<<21|0<<20|0<<19|chmask<<4); + 0x1<<20|0x1<<19|0xff<<4, + 0<<20|0<<19|chmask<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdif_id; @@ -500,7 +505,7 @@ void spdifout_enable(int spdif_id, bool is_enable, bool reenable) } void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable) + int bitwidth, int channels, bool is_enable, int lane_i2s) { int spdif_id; @@ -510,7 +515,8 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, spdif_id = 0; if (is_enable) - spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); + spdifout_fifo_ctrl(spdif_id, + fifo_id, bitwidth, channels, lane_i2s); } int spdifin_get_sample_rate(void) @@ -666,7 +672,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable) /* spdif ctrl */ spdifout_fifo_ctrl(spdif_id, - frddr_index, bitwidth, runtime.channels); + frddr_index, bitwidth, runtime.channels, 0); /* channel status info */ spdif_get_channel_status_info(&chsts, sample_rate); diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index d981ed079997..e15efa3abaab 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -78,8 +78,8 @@ extern void aml_spdifout_get_aed_info(int spdifout_id, extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable); -extern void spdifout_enable(int spdif_id, bool is_enable); + int bitwidth, int channels, bool is_enable, int lane_i2s); +extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable); extern int spdifin_get_sample_rate(void); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 9e4bab0e2663..1b185f4048e7 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -120,7 +120,7 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { SNDRV_PCM_FMTBIT_S32_LE, .period_bytes_min = 64, - .period_bytes_max = 256 * 1024 * 2, + .period_bytes_max = 256 * 1024, .periods_min = 2, .periods_max = 1024, .buffer_bytes_max = 1024 * 1024, @@ -131,6 +131,35 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { .channels_max = 32, }; +static int tdm_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = clk_get_rate(p_tdm->mclk); + return 0; +} + +static int tdm_clk_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + int mclk_rate = p_tdm->last_mclk_freq; + int value = ucontrol->value.enumerated.item[0]; + + if (value > 2000000 || value < 0) { + pr_err("Fine tdm clk setting range (0~2000000), %d\n", value); + return 0; + } + mclk_rate += (value - 1000000); + + aml_dai_set_tdm_sysclk(cpu_dai, 0, mclk_rate, 0); + + return 0; +} static int tdmin_clk_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -172,10 +201,16 @@ static const struct soc_enum i2sin_clk_enum[] = { static const struct snd_kcontrol_new snd_tdm_controls[] = { SOC_ENUM_EXT("I2SIn CLK", i2sin_clk_enum, tdmin_clk_get, - NULL) + NULL), + + SOC_SINGLE_EXT("TDM MCLK Fine Setting", + 0, 0, 2000000, 0, + tdm_clk_get, + tdm_clk_set), }; + static irqreturn_t aml_tdm_ddr_isr(int irq, void *devid) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)devid; @@ -435,8 +470,6 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, i2s_to_hdmitx_ctrl(p_tdm->id); aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, substream); - } else { - i2s_to_hdmitx_disable(); } fifo_id = aml_frddr_get_fifo_id(fr); @@ -580,14 +613,6 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback enable\n"); - /* share buffer trigger */ - if (p_tdm->chipinfo - && p_tdm->chipinfo->same_src_fn - && (p_tdm->samesource_sel >= 0) - && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { - sharebuffer_trigger(cmd, p_tdm->samesource_sel); - } aml_frddr_enable(p_tdm->fddr, 1); aml_tdm_enable(p_tdm->actrl, substream->stream, p_tdm->id, true); @@ -622,9 +647,6 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback stop\n"); - memset(substream->runtime->dma_area, - 0, substream->runtime->dma_bytes); - mdelay(3); aml_frddr_enable(p_tdm->fddr, 0); aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, true, p_tdm->lane_cnt); From e3701d133e624c5bbded2a2691d25a08678ac038 Mon Sep 17 00:00:00 2001 From: "huaihao.guo" Date: Fri, 2 Nov 2018 19:10:19 +0800 Subject: [PATCH 0639/1060] deinterface: add afbc support on g12a and txlx [1/1] PD#SWPL-1618 Problem: Add afbc support on g12a and txlx Solution: add afbc support on g12a and txlx Verify: T962X-R311, U200(G12A) Change-Id: Ia0cce8516a98653b01c3bc628e812c3a81b1df59 Signed-off-by: huaihao.guo Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c drivers/amlogic/media/deinterlace/deinterlace_hw.c --- drivers/amlogic/media/deinterlace/deinterlace.c | 2 +- drivers/amlogic/media/deinterlace/deinterlace_hw.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 355aaa3c22bc..7544b5200968 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-18a"; +static const char version_s[] = "2018-11-06a"; static int bypass_state = 1; static int bypass_all; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 3918d70e8680..32d3b050fcd6 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -1007,9 +1007,9 @@ bool afbc_is_supported(void) /*currently support txlx and g12a*/ if (is_meson_txlx_cpu() - || is_meson_g12a_cpu() - /*|| is_meson_tl1_cpu()*/) - ret = false; + || cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + ret = true; + return ret; } From 32376b037b5e13b53936109e244220709c252f0a Mon Sep 17 00:00:00 2001 From: "huaihao.guo" Date: Fri, 23 Nov 2018 10:31:02 +0800 Subject: [PATCH 0640/1060] deinterface: temporary remove afbc support on chip after g12a [1/1] PD#172587 Problem: afbc now support on chip txlx and g12a, but we use cpu_after_eq(G12A) to judge if afbc is support or not. Solution: use is_meson_g12a_cpu() replace cpu_after_eq(G12A). Verify: u200(g12a),t962x_r311 Change-Id: I3fb7ed54f7137fada97481177e40a2543cf8df9f Signed-off-by: huaihao guo --- drivers/amlogic/media/deinterlace/deinterlace_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 32d3b050fcd6..4b0a0b00caa8 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -1007,7 +1007,7 @@ bool afbc_is_supported(void) /*currently support txlx and g12a*/ if (is_meson_txlx_cpu() - || cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + || is_meson_g12a_cpu()) ret = true; return ret; From 8e075a7ced85bd8a83a9471fc652ac94ab25da37 Mon Sep 17 00:00:00 2001 From: "wenfeng.guo" Date: Tue, 20 Nov 2018 19:38:43 +0800 Subject: [PATCH 0641/1060] deinterlace: fix CMA layout adaptation di_cma_reserved [1/1] PD#SWPL-2308 Problem: CMA layout adaptation di_cma_reserved cause crash Solution: fix CMA layout adaptation di_cma_reserved Verify: P321 Change-Id: Ia24e811a02d47d70afa1c06361fd0852c357394c Signed-off-by: wenfeng.guo Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c drivers/amlogic/media/deinterlace/deinterlace_hw.c drivers/amlogic/media/deinterlace/deinterlace_hw.h --- drivers/amlogic/media/deinterlace/deinterlace_hw.c | 5 ----- drivers/amlogic/media/deinterlace/deinterlace_hw.h | 13 ------------- 2 files changed, 18 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 4b0a0b00caa8..3e0437ad754c 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -330,11 +330,6 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, if (!lmv_lock_win_en) return; - if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { - pr_debug("%s: only support G12A and after chips.\n", __func__); - return; - } - tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); if (tmp == NULL) { di_print("err:di_vmap failed\n"); diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index 17622be59b4a..e18198410946 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -187,18 +187,5 @@ extern u8 *di_vmap(ulong addr, u32 size, bool *bflg); extern void di_unmap_phyaddr(u8 *vaddr); extern int di_print(const char *fmt, ...); -#define DI_MC_SW_OTHER (1<<0) -#define DI_MC_SW_REG (1<<1) -//#define DI_MC_SW_POST (1<<2) -#define DI_MC_SW_IC (1<<2) - -#define DI_MC_SW_ON_MASK (DI_MC_SW_REG | DI_MC_SW_OTHER | DI_MC_SW_IC) - -extern void di_patch_post_update_mc(void); -extern void di_patch_post_update_mc_sw(unsigned int cmd, bool on); - -extern void di_rst_protect(bool on); -extern void di_pre_nr_wr_done_sel(bool on); -extern void di_arb_sw(bool on); #endif From 5bc20f13a4b5d80647615ea7bcf762c253cfa5e0 Mon Sep 17 00:00:00 2001 From: "wenfeng.guo" Date: Mon, 12 Nov 2018 10:54:08 +0800 Subject: [PATCH 0642/1060] deinterlace: add support for tl1 [1/1] PD#172587 Problem: bringup tl1 Solution: add deinterlace driver support for tl1 Verify: verified on tl1 x301 Change-Id: I3bf008a4f948cdc2c11f14f81944695d6a185b14 Signed-off-by: wenfeng.guo Conflicts: arch/arm/boot/dts/amlogic/tl1_pxp.dts arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts drivers/amlogic/media/deinterlace/deinterlace.c drivers/amlogic/media/deinterlace/deinterlace_dbg.c drivers/amlogic/media/deinterlace/deinterlace_hw.c drivers/amlogic/media/deinterlace/nr_drv.c --- arch/arm/boot/dts/amlogic/tl1_pxp.dts | 47 ++++++++++++++++ arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 40 ++++++++++++++ arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 53 +++++++++++++++---- .../amlogic/media/deinterlace/deinterlace.c | 23 ++++---- .../media/deinterlace/deinterlace_dbg.c | 3 +- .../media/deinterlace/deinterlace_hw.c | 8 +-- drivers/amlogic/media/deinterlace/nr_drv.c | 11 ++-- 7 files changed, 147 insertions(+), 38 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index 15bf6a776194..fe0ded0bce4a 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -101,6 +101,21 @@ alignment = <0x400000>; }; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -119,6 +134,38 @@ memory-region = <&codec_mm_cma &codec_mm_reserved>; }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + vout { compatible = "amlogic, vout"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 0138f07b5ace..d522d468e1ff 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -150,6 +150,21 @@ alignment = <0x400000>; }; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -181,6 +196,31 @@ status = "okay"; }; + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + vout { compatible = "amlogic, vout"; status = "okay"; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index b53d4529fa30..451945169e29 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -136,20 +136,26 @@ alignment = <0x400000>; }; - /*demod_reserved:linux,demod { - * compatible = "amlogic, demod-mem"; - * size = <0x800000>; //8M //100m 0x6400000 - * alloc-ranges = <0x0 0x30000000>; - * //multi-use; - * //no-map; - *}; - */ + demod_reserved:linux,demod { + compatible = "amlogic, demod-mem"; + size = <0x800000>; //8M //100m 0x6400000 + alloc-ranges = <0x0 0x30000000>; + //multi-use; + //no-map; + }; - demod_cma_reserved:linux,demod_cma { + /*di CMA pool */ + di_cma_reserved:linux,di_cma { compatible = "shared-dma-pool"; reusable; - /* 8M */ - size = <0x0800000>; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; alignment = <0x400000>; }; @@ -199,6 +205,31 @@ status = "okay"; }; + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + vout { compatible = "amlogic, vout"; status = "okay"; diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 7544b5200968..207ebabbf95a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-11-06a"; +static const char version_s[] = "2018-11-12a"; static int bypass_state = 1; static int bypass_all; @@ -5105,7 +5105,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_sm1_cpu()) { + is_meson_tl1_cpu()) { di_post_read_reverse_irq(overturn, mc_pre_flag, post_blend_en ? mcpre_en : false); /* disable mc for first 2 fieldes mv unreliable */ @@ -5887,7 +5887,7 @@ static void di_unreg_process_irq(void) di_hw_uninit(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu() || is_meson_sm1_cpu()) { + || is_meson_tl1_cpu()) { di_pre_gate_control(false, mcpre_en); nr_gate_control(false); } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { @@ -5900,7 +5900,7 @@ static void di_unreg_process_irq(void) di_hw_disable(mcpre_en); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu() || is_meson_sm1_cpu()) { + || is_meson_tl1_cpu()) { enable_di_post_mif(GATE_OFF); di_post_gate_control(false); di_top_gate_control(false, false); @@ -6013,8 +6013,7 @@ static void di_pre_size_change(unsigned short width, is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu() || - is_meson_sm1_cpu()) + is_meson_tl1_cpu()) film_mode_win_config(width, height); } if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) @@ -6448,8 +6447,7 @@ static int di_task_handle(void *data) } } if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu() || - is_meson_sm1_cpu()) { + || is_meson_tl1_cpu()) { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, de_devp->clkb_max_rate); @@ -7397,8 +7395,7 @@ static void set_di_flag(void) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu() || - is_meson_sm1_cpu()) { + is_meson_tl1_cpu()) { mcpre_en = true; mc_mem_alloc = true; pulldown_enable = false; @@ -7416,8 +7413,7 @@ static void set_di_flag(void) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu() || - is_meson_sm1_cpu()) { + is_meson_tl1_cpu()) { full_422_pack = true; } @@ -7429,8 +7425,7 @@ static void set_di_flag(void) } post_hold_line = (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu() || - is_meson_sm1_cpu())?10:17; + || is_meson_tl1_cpu())?10:17; } else { post_hold_line = 8; /*2019-01-10: from VLSI feijun*/ mcpre_en = false; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index 63f6102111f2..a65a546bd46d 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -254,8 +254,7 @@ void dump_di_reg_g12(void) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu() || - is_meson_sm1_cpu()) + is_meson_tl1_cpu()) base_addr = 0xff900000; else base_addr = 0xd0100000; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 3e0437ad754c..fb4e8783e63c 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -468,7 +468,7 @@ void di_hw_init(bool pd_enable, bool mc_enable) switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu() || is_meson_sm1_cpu()) + || is_meson_tl1_cpu()) di_top_gate_control(true, true); else if (is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_gxlx_cpu()) @@ -481,7 +481,7 @@ void di_hw_init(bool pd_enable, bool mc_enable) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_g12b_cpu() || is_meson_tl1_cpu()) { /* vpp fifo max size on txl :128*3=384[0x180] */ /* di fifo max size on txl :96*3=288[0x120] */ @@ -517,7 +517,7 @@ void di_hw_init(bool pd_enable, bool mc_enable) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_g12b_cpu() || is_meson_tl1_cpu()) { di_pre_gate_control(true, true); di_post_gate_control(true); @@ -535,7 +535,7 @@ void di_hw_init(bool pd_enable, bool mc_enable) mc_di_param_init(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_g12a_cpu() || is_meson_sm1_cpu() || + is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) { di_pre_gate_control(false, true); diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index bd0496fdac41..55a29942d5f1 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -356,8 +356,7 @@ static void linebuffer_config(unsigned short width) static void nr2_config(unsigned short width, unsigned short height) { if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu() || - is_meson_sm1_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu()) { DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 2, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 15, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 17, 1); @@ -406,8 +405,7 @@ void nr_all_config(unsigned short width, unsigned short height, if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) cue_config(nr_param.pcue_parm, field_type); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu() || - is_meson_sm1_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu()) { linebuffer_config(width); nr4_config(nr_param.pnr4_parm, width, height); } @@ -829,8 +827,7 @@ void nr_process_in_irq(void) if (dnr_en) dnr_process(&dnr_param); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() - || is_meson_g12a_cpu() || is_meson_tl1_cpu() || - is_meson_sm1_cpu()) { + || is_meson_g12a_cpu() || is_meson_tl1_cpu()) { noise_meter_process(nr_param.pnr4_parm, nr_param.frame_count); luma_enhancement_process(nr_param.pnr4_parm, nr_param.frame_count); @@ -1206,7 +1203,7 @@ void nr_hw_init(void) void nr_gate_control(bool gate) { if (!is_meson_txlx_cpu() && !is_meson_g12a_cpu() - && !is_meson_g12b_cpu() && !is_meson_sm1_cpu() + && !is_meson_g12b_cpu() && !is_meson_tl1_cpu()) return; if (gate) { From cd21f1c613293a9b22ef0932a7612b48ef6e508d Mon Sep 17 00:00:00 2001 From: Jihong Sui Date: Wed, 28 Nov 2018 16:23:05 +0800 Subject: [PATCH 0643/1060] deinterlace: there's a change to hang in shutdown [1/1] PD#OTT-778 Problem: 1.kernel received reboot command, but hang in shutdown Solution: move tasklet_disable behind tasklet_kill Verify: P321 Change-Id: I994c21c5aeb42dbbb4e3b50ccac8376db4d4039d Signed-off-by: Jihong Sui --- drivers/amlogic/media/deinterlace/deinterlace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 207ebabbf95a..fcd87dd30faa 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-11-12a"; +static const char version_s[] = "2018-11-28b"; static int bypass_state = 1; static int bypass_all; From 56e2c4d447ddca8bdc54b9fd3c619e5e8980d6f9 Mon Sep 17 00:00:00 2001 From: Jihong Sui Date: Fri, 7 Dec 2018 10:40:26 +0800 Subject: [PATCH 0644/1060] deinterlace: pq: adjust cue setting for tl1 [1/1] PD#SWPL-2984 Problem: VLSI(yanling.liu) fine-tune cue setting for TL1. Solution: add new setting. Verify: tl1 Change-Id: I99c32d994687650dc851dd2fb8c0464e8ffd21b5 Signed-off-by: Jihong Sui Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c --- drivers/amlogic/media/deinterlace/deinterlace.c | 2 +- drivers/amlogic/media/deinterlace/nr_drv.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index fcd87dd30faa..d403c8a7cc54 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-11-28b"; +static const char version_s[] = "2018-12-07a"; static int bypass_state = 1; static int bypass_all; diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index 55a29942d5f1..5d41ea73a702 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -743,6 +743,16 @@ module_param_named(glb_fieldck_en, glb_fieldck_en, bool, 0644); void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff) { struct CUE_PARM_s *pcue_parm = nr_param.pcue_parm; + unsigned int mask1, mask2; + + if (is_meson_tl1_cpu()) { + /*value from VLSI(yanling.liu) 2018-12-07: */ + mask1 = 0x50332; + mask2 = 0x00054357; + } else { /*ori value*/ + mask1 = 0x50323; + mask2 = 0x00054375; + } if (frame_diff > pcue_parm->glb_mot_framethr) { pcue_parm->frame_count = pcue_parm->frame_count > 0 ? @@ -767,10 +777,10 @@ void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff) /* for clockfuliness clip */ if (pcue_parm->field_count > (pcue_parm->glb_mot_fieldnum - 6)) { - Wr(NR2_CUE_MODE, 0x50323|(Rd(NR2_CUE_MODE)&0xc00)); + Wr(NR2_CUE_MODE, mask1|(Rd(NR2_CUE_MODE)&0xc00)); Wr(NR2_CUE_CON_MOT_TH, 0x03010e01); } else { - Wr(NR2_CUE_MODE, 0x00054375|(Rd(NR2_CUE_MODE)&0xc00)); + Wr(NR2_CUE_MODE, mask2|(Rd(NR2_CUE_MODE)&0xc00)); Wr(NR2_CUE_CON_MOT_TH, 0xa03c8c3c); } } From 70cac90710e96163ec07578811281b97f1364efc Mon Sep 17 00:00:00 2001 From: huaihao guo Date: Tue, 11 Dec 2018 21:07:12 +0800 Subject: [PATCH 0645/1060] deinterlace: Add AFBC support on TL1 [1/1] PD#SWPL-3113 Problem: Add AFBC support on TL1 Solution: Add AFBC support on TL1 Verify: T962x2-x301 Change-Id: Ib4f40f6ca0cbb1553bf4f76848d1649822dda3e8 Signed-off-by: huaihao.guo --- .../amlogic/media/deinterlace/deinterlace.c | 2 +- .../media/deinterlace/deinterlace_hw.c | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index d403c8a7cc54..e857580f8f77 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-12-07a"; +static const char version_s[] = "2018-12-12a"; static int bypass_state = 1; static int bypass_all; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index fb4e8783e63c..6581e6c72859 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -986,8 +986,9 @@ static enum eAFBC_DEC afbc_get_decnub(void) sel_dec = eAFBC_DEC1; else if (is_meson_g12a_cpu()) sel_dec = AFBC_DEC_SEL; - - + /* TL1 only have AFBC0 */ + else if (is_meson_tl1_cpu()) + sel_dec = eAFBC_DEC0; return sel_dec; } @@ -1002,9 +1003,9 @@ bool afbc_is_supported(void) /*currently support txlx and g12a*/ if (is_meson_txlx_cpu() - || is_meson_g12a_cpu()) + || is_meson_g12a_cpu() + || is_meson_tl1_cpu()) ret = true; - return ret; } @@ -1052,7 +1053,19 @@ void enable_afbc_input(struct vframe_s *vf) out_height = h_aligned>>1; } RDMA_WR(reg[eAFBC_MODE], r); - RDMA_WR(reg[eAFBC_CONV_CTRL], 0x100); + r = 0x100; + /* TL1 add bit[13:12]: fmt_mode; 0:yuv444; 1:yuv422; 2:yuv420 + * di does not support yuv444, so for fmt yuv444 di will bypass+ + */ + if (is_meson_tl1_cpu()) { + if (vf->type & VIDTYPE_VIU_444) + r |= (0 << 12); + else if (vf->type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + RDMA_WR(reg[eAFBC_CONV_CTRL], r); u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; RDMA_WR(reg[eAFBC_DEC_DEF_COLOR], @@ -1131,10 +1144,15 @@ static void afbcx_sw(bool on) /*g12a*/ (reg_ctrl == VD1_AFBCD0_MISC_CTRL)?0:1, 8, 1); RDMA_WR(reg_en, 0x1600); RDMA_WR_BITS(VIUB_MISC_CTRL0, 1, 16, 1); + /*TL1 add mem control bit */ + if (is_meson_tl1_cpu()) + RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 1, 22, 1); } else { RDMA_WR(reg_ctrl, tmp); RDMA_WR(reg_en, 0x1600); RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); + if (is_meson_tl1_cpu()) + RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 0, 22, 1); } // printk("%s,on[%d],CTRL[0x%x],en[0x%x]\n", __func__, on, // RDMA_RD(VD1_AFBCD0_MISC_CTRL), From 0a23be6422ee6a1caca52248ec80a79a71e0304d Mon Sep 17 00:00:00 2001 From: Jihong Sui Date: Tue, 18 Dec 2018 21:56:38 +0800 Subject: [PATCH 0646/1060] deinterlace: pq: adjust pulldown setting for tl1 [1/1] PD#SWPL-3182 Problem: 1.VLSI(Feijun) fine-tune pulldown setting for TL1, G12A/B; 2.fine tune combing_glbmot_radprat by VLSI(yanling.liu); Solution: finetune setting. Verify: tl1 Change-Id: Ie65cec8b216752600dfd54ee6be5302150282774 Signed-off-by: Jihong Sui --- .../amlogic/media/deinterlace/deinterlace.c | 12 ++++----- .../media/deinterlace/deinterlace_hw.c | 25 +++++++++++++------ .../media/deinterlace/deinterlace_mtn.c | 7 +++++- .../media/deinterlace/deinterlace_mtn.h | 2 ++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index e857580f8f77..7356b0059d66 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -4895,10 +4895,10 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, /*it means use previous field for MC*/ /*else not pulldown,mcdi_mcpreflag is 2*/ /*it means use forward & previous field for MC*/ - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 2; } else { - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 1; post_blend_mode = 1; } @@ -4935,8 +4935,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_post_stru.di_mcvecrd_mif.canvas_num = di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; mc_pre_flag = is_meson_txl_cpu()?0:(overturn?1:0); - if (is_meson_txlx_cpu() || is_meson_gxlx_cpu() || - is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) invert_mv = true; else if (!overturn) di_post_stru.di_buf2_mif.canvas0_addr0 = @@ -4948,10 +4947,10 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, /*it means use previous field for MC*/ /*else not pulldown,mcdi_mcpreflag is 2*/ /*it means use forward & previous field for MC*/ - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 2; } else { - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 1; post_blend_mode = 1; } @@ -7447,6 +7446,7 @@ static void set_di_flag(void) pldn_dly1 = 2; } + mtn_int_combing_glbmot(); } static const struct reserved_mem_ops rmem_di_ops = { diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 6581e6c72859..02ad68b41753 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -2731,11 +2731,22 @@ void di_post_switch_buffer( DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, di_mcvecrd_mif->vecrd_offset, 12, 3); if (di_mcvecrd_mif->blend_en) { - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - mcen_mode, 0, 2); - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 1, 11, 1); - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - 3, 18, 2); + if (blend_mode == 1) { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mcen_mode, 0, 2); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 0, 11, 1); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 2, 18, 2); + } else { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mcen_mode, 0, 2); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 1, 11, 1); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 3, 18, 2); + + } } else { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); @@ -3183,7 +3194,7 @@ void di_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 1, 30, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 1, 30, 1); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + if (is_meson_txlx_cpu()) { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, pre_flag, 8, 2); flag_val = (pre_flag != 2) ? 0 : 1; @@ -3227,7 +3238,7 @@ void di_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 0, 30, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 0, 30, 1); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + if (is_meson_txlx_cpu()) { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, pre_flag, 8, 2); flag_val = (pre_flag != 2) ? 0 : 1; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index a42619564157..ec80205bac43 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -295,7 +295,12 @@ struct combing_status_s *adpative_combing_config(unsigned int width, cmb_param.prog_flag = prog; return &cmb_status; } - +void mtn_int_combing_glbmot(void) +{ + if (is_meson_tl1_cpu()) {/*from VLSI yanling.liu*/ + combing_glbmot_radprat[0] = 30; + } +} void adpative_combing_exit(void) { } diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h index 019e01273ebe..206d1c307543 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h @@ -44,4 +44,6 @@ int adaptive_combing_fixing( unsigned int field_diff, unsigned int frame_diff, int bit_mode); void adpative_combing_exit(void); +extern void mtn_int_combing_glbmot(void); + #endif From e7af75d340a5295828da18e6acb07b4f8c173395 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Tue, 25 Dec 2018 11:03:01 +0800 Subject: [PATCH 0647/1060] di: disable afbc on tl1 [1/1] PD#SWPL-3413 Problem: when playing SD/HD/VP9/H265 video, there are 3 veritcal lines on the picture. Solution: disable afbc Verify: verified on tl1 Change-Id: I839d8f26aefdf2c71272d8d3e7bf93e4c3294491 Signed-off-by: Yong Qin --- drivers/amlogic/media/deinterlace/deinterlace.c | 2 +- drivers/amlogic/media/deinterlace/deinterlace_hw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 7356b0059d66..fe75742759ec 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-12-12a"; +static const char version_s[] = "2018-12-25a"; static int bypass_state = 1; static int bypass_all; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 02ad68b41753..479f16cb6af9 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -1004,7 +1004,7 @@ bool afbc_is_supported(void) /*currently support txlx and g12a*/ if (is_meson_txlx_cpu() || is_meson_g12a_cpu() - || is_meson_tl1_cpu()) + /*|| is_meson_tl1_cpu()*/) ret = true; return ret; From 0c513a2b817b97cce8c194567d845e92d0cfc3de Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Thu, 28 Feb 2019 15:30:09 +0800 Subject: [PATCH 0648/1060] di: TL1 enable lmv_lock_win_en cause crash [1/1] PD#SWPL-4999 Problem: use vmalloc in interrupt context Solution: move di_map to cma allocate function(kernel thread) Verify: verified by t962x2_x301 Change-Id: I8cf8d9caf9703ba039b32da98d2382a4c875de30 Signed-off-by: zhiwei.yuan --- .../amlogic/media/deinterlace/deinterlace.c | 35 +++++++++++++++++-- .../amlogic/media/deinterlace/deinterlace.h | 2 ++ .../media/deinterlace/deinterlace_hw.c | 17 ++++----- .../media/deinterlace/deinterlace_hw.h | 3 +- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index fe75742759ec..b83cefff8e5c 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -1878,6 +1878,7 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp) unsigned int start_time, end_time, delta_time; struct di_buf_s *buf_p = NULL; int itmp, alloc_cnt = 0; + u8 *tmp; start_time = jiffies_to_msecs(jiffies); queue_for_each_entry(buf_p, ptmp, QUEUE_LOCAL_FREE, list) { @@ -1923,6 +1924,18 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp) di_pre_stru.mtn_size + di_pre_stru.count_size + di_pre_stru.mv_size; + tmp = di_vmap(buf_p->mcinfo_adr, + di_pre_stru.mcinfo_size, + &buf_p->bflg_vmap); + + if (buf_p->bflg_vmap == true) + buf_p->mcinfo_vaddr = + (unsigned short *)tmp; + else { + buf_p->mcinfo_vaddr = NULL; + pr_err("DI: %s vmap fail\n", + __func__); + } } } } @@ -1987,6 +2000,12 @@ static void di_cma_release(struct di_dev_s *devp) } if ((ii >= USED_LOCAL_BUF_MAX) && (buf_p->pages != NULL)) { + + if (buf_p->bflg_vmap == true) { + di_unmap_phyaddr((u8 *)buf_p->mcinfo_vaddr); + buf_p->bflg_vmap = false; + } + if (dma_release_from_contiguous(&(devp->pdev->dev), buf_p->pages, devp->buffer_size >> PAGE_SHIFT)) { @@ -2049,6 +2068,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) unsigned int mv_canvas_width = width, canvas_align_width = 32; unsigned long di_post_mem = 0, nrds_mem = 0; struct di_buf_s *keep_buf = di_post_stru.keep_buf; + u8 *tmp; if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) canvas_align_width = 64; @@ -2182,6 +2202,18 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) de_devp->mem_start + di_buf_size * i + nr_size + mtn_size + count_size + mv_size; + tmp = di_vmap(di_buf->mcinfo_adr, + di_pre_stru.mcinfo_size, + &di_buf->bflg_vmap); + + if (di_buf->bflg_vmap == true) + di_buf->mcinfo_vaddr = + (unsigned short *)tmp; + else { + di_buf->mcinfo_vaddr = NULL; + pr_err("DI: %s vmap fail\n", + __func__); + } } di_buf->canvas_config_flag = 2; } @@ -4281,8 +4313,7 @@ static irqreturn_t de_irq(int irq, void *dev_instance) is_meson_txhd_cpu()) mc_pre_mv_irq(); calc_lmv_base_mcinfo((di_pre_stru.cur_height>>1), - di_pre_stru.di_wr_buf->mcinfo_adr, - di_pre_stru.mcinfo_size); + di_pre_stru.di_wr_buf->mcinfo_vaddr); } nr_process_in_irq(); if ((data32&0x200) && de_devp->nrds_enable) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 0e38fdd681de..9aa19e26558a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -117,6 +117,8 @@ struct di_buf_s { int cnt_canvas_idx; unsigned long mcinfo_adr; int mcinfo_canvas_idx; + unsigned short *mcinfo_vaddr; + bool bflg_vmap; unsigned long mcvec_adr; int mcvec_canvas_idx; struct mcinfo_pre_s { diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 479f16cb6af9..ecea8354e008 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -314,28 +314,25 @@ static struct mcinfo_lmv_s lines_mv[540]; static short offset_lmv = 100; module_param_named(offset_lmv, offset_lmv, short, 0644); -void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, - unsigned int mcinfo_size) +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr) { unsigned short i, top_str, bot_str, top_end, bot_end, j = 0; - unsigned short *mcinfo_vadr = NULL, lck_num; + unsigned short lck_num; unsigned short flg_m1 = 0, flg_i = 0, nLmvLckSt = 0; unsigned short lmv_lckstext[3] = {0, 0, 0}, nLmvLckEd; unsigned short lmv_lckedext[3] = {0, 0, 0}, nLmvLckNum; - bool bflg_vmap = false; - u8 *tmp; + //bool bflg_vmap = false; //mcinfo_vadr = (unsigned short *)phys_to_virt(mcinfo_adr); if (!lmv_lock_win_en) return; - tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); - if (tmp == NULL) { + //tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); + if (mcinfo_vadr == NULL) { di_print("err:di_vmap failed\n"); return; } - mcinfo_vadr = (unsigned short *)tmp; for (i = 0; i < (vf_height>>1); i++) { lmvs_init(&lines_mv[i], *(mcinfo_vadr+i)); @@ -350,8 +347,8 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, pr_info("\n"); } } - if (bflg_vmap) - di_unmap_phyaddr(tmp); + //if (bflg_vmap) + //di_unmap_phyaddr(tmp); pr_mcinfo_cnt ? pr_mcinfo_cnt-- : (pr_mcinfo_cnt = 0); top_str = 0; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index e18198410946..b464f562bc03 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -165,8 +165,7 @@ void enable_di_post_mif(enum gate_mode_e mode); void di_hw_uninit(void); void combing_pd22_window_config(unsigned int width, unsigned int height); void calc_lmv_init(void); -void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, - unsigned int mcinfo_size); +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr); void init_field_mode(unsigned short height); void film_mode_win_config(unsigned int width, unsigned int height); void pulldown_vof_win_config(struct pulldown_detected_s *wins); From 50ae6deb5992e2a125dfd2c8dcc943b708a93e9c Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Thu, 28 Feb 2019 11:17:17 +0800 Subject: [PATCH 0649/1060] di: support the interlace format from vdin afbc [2/2] PD#SWPL-5205 Problem: support afbc from vdin and decoder on tl1 Solution: 1.add this function 2.support from vdin and decoder Verify: tl1 Change-Id: I258d40ad5706f4a9a5749298dd9a33a9b4bbafa2 Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c drivers/amlogic/media/deinterlace/deinterlace_hw.c --- .../amlogic/media/deinterlace/deinterlace.c | 127 +++++- .../amlogic/media/deinterlace/deinterlace.h | 10 + .../media/deinterlace/deinterlace_dbg.c | 26 +- .../media/deinterlace/deinterlace_dbg.h | 3 + .../media/deinterlace/deinterlace_hw.c | 365 ++++++++++-------- .../media/deinterlace/deinterlace_hw.h | 35 +- 6 files changed, 379 insertions(+), 187 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index b83cefff8e5c..19dcdb48b3b0 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-12-25a"; +static const char version_s[] = "2019-03-05a"; static int bypass_state = 1; static int bypass_all; @@ -272,6 +272,8 @@ static int di_receiver_event_fun(int type, void *data, void *arg); static void di_uninit_buf(unsigned int disable_mirror); static void log_buffer_state(unsigned char *tag); /* static void put_get_disp_buf(void); */ +static unsigned int isbypass_flag; +static unsigned int needbypass_flag; static const struct vframe_receiver_op_s di_vf_receiver = { @@ -526,27 +528,57 @@ int get_di_dump_state_flag(void) } /*--------------------------*/ +static void parse_param_di(char *buf_orig, char **parm) +{ + char *ps, *token; + unsigned int n = 0; + char delim1[3] = " "; + char delim2[2] = "\n"; + + ps = buf_orig; + strcat(delim1, delim2); + while (1) { + token = strsep(&ps, delim1); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } +} + static ssize_t store_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + u32 val; + char *buf_orig, *parm[8] = {NULL}; + + buf_orig = kstrdup(buf, GFP_KERNEL); + parse_param_di(buf_orig, (char **)&parm); if (strncmp(buf, "buf", 3) == 0) { struct di_buf_s *di_buf_tmp = 0; - if (kstrtoul(buf + 3, 16, (unsigned long *)&di_buf_tmp)) + if (kstrtoul(buf + 3, 16, (unsigned long *)&di_buf_tmp)) { + kfree(buf_orig); return count; + } dump_di_buf(di_buf_tmp); } else if (strncmp(buf, "vframe", 6) == 0) { vframe_t *vf = 0; - if (kstrtoul(buf + 6, 16, (unsigned long *)&vf)) + if (kstrtoul(buf + 6, 16, (unsigned long *)&vf)) { + kfree(buf_orig); return count; + } dump_vframe(vf); } else if (strncmp(buf, "pool", 4) == 0) { unsigned long idx = 0; - if (kstrtoul(buf + 4, 10, &idx)) + if (kstrtoul(buf + 4, 10, &idx)) { + kfree(buf_orig); return count; + } dump_pool(get_queue_by_idx(idx)); } else if (strncmp(buf, "state", 4) == 0) { dump_state(); @@ -576,10 +608,13 @@ store_dbg(struct device *dev, } else if (strncmp(buf, "pstep", 5) == 0) { pre_run_flag = DI_RUN_FLAG_STEP; } else if (strncmp(buf, "dumpreg", 7) == 0) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { dump_di_reg_g12(); - else + dump_afbcd_reg(); + } else pr_info("add new debugfs: cat /sys/kernel/debug/di/dumpreg\n"); + } else if (strncmp(buf, "dumpafbc", 8) == 0) { + dump_afbcd_reg(); } else if (strncmp(buf, "dumpmif", 7) == 0) { dump_mif_size_state(&di_pre_stru, &di_post_stru); } else if (strncmp(buf, "recycle_buf", 11) == 0) { @@ -589,10 +624,37 @@ store_dbg(struct device *dev, di_vf_put(di_vf_get(NULL), NULL); } else if (strncmp(buf, "mem_map", 7) == 0) { dump_buf_addr(di_buf_local, MAX_LOCAL_BUF_NUM * 2); + } else if (strncmp(buf, "afbc_on", 7) == 0) { + if (kstrtoint(parm[1], 10, &val) < 0) { + kfree(buf_orig); + return count; + } + if (!val) + afbc_sw(false); + afbc_disable_flag = val > 0 ? 0:1; + pr_info("afbc_disable_flag:%d\n", afbc_disable_flag); } else { - pr_info("DI no support cmd %s!!!\n", buf); + pr_info("DI no support cmd %s\n", buf); + pr_info("supported cmd list:\n"); + pr_info("\t vframe\n"); + pr_info("\t state\n"); + pr_info("\t prog_proc_config 0/1\n"); + pr_info("\t init_flag 0/1\n"); + pr_info("\t run\n"); + pr_info("\t pause\n"); + pr_info("\t step\n"); + pr_info("\t prun\n"); + pr_info("\t ppause\n"); + pr_info("\t pstep\n"); + pr_info("\t dumpreg\n"); + pr_info("\t dumpmif\n"); + pr_info("\t recycle_buf\n"); + pr_info("\t recycle_post\n"); + pr_info("\t mem_map\n"); + pr_info("\t afbc_on 0/1\n"); } + kfree(buf_orig); return count; } static int __init di_read_canvas_reverse(char *str) @@ -1548,6 +1610,7 @@ unsigned char is_bypass(vframe_t *vf_in) int ret = 0; static vframe_t vf_tmp; + isbypass_flag = true; if (di_debug_flag & 0x10000) /* for debugging */ return (di_debug_flag >> 17) & 0x1; @@ -1627,7 +1690,7 @@ unsigned char is_bypass(vframe_t *vf_in) ) return 1; } - + isbypass_flag = false; return 0; } @@ -2456,6 +2519,11 @@ static void dump_state(void) dump_state_flag = 1; pr_info("version %s, init_flag %d, is_bypass %d\n", version_s, init_flag, is_bypass(NULL)); + pr_info("isbypass_flag %d, needbypass_flag %d\n", + isbypass_flag, needbypass_flag); + pr_info("di_pre_stru.bypass_flag=%d\n", + di_pre_stru.bypass_flag); + pr_info("afbcd support %d\n", afbc_is_supported()); pr_info("recovery_flag = %d, recovery_log_reason=%d, di_blocking=%d", recovery_flag, recovery_log_reason, di_blocking); pr_info("recovery_log_queue_idx=%d, recovery_log_di_buf=0x%p\n", @@ -2863,6 +2931,7 @@ static void pre_de_process(void) } else config_di_mif(&di_pre_stru.di_chan2_mif, di_pre_stru.di_chan2_buf_dup_p); + config_di_wr_mif(&di_pre_stru.di_nrwr_mif, &di_pre_stru.di_mtnwr_mif, di_pre_stru.di_wr_buf); @@ -2916,9 +2985,6 @@ static void pre_de_process(void) * we need to only leave one mask open * to prevent multiple entry for de_irq */ - - - enable_di_pre_aml(&di_pre_stru.di_inp_mif, &di_pre_stru.di_mem_mif, &di_pre_stru.di_chan2_mif, @@ -3464,10 +3530,13 @@ static unsigned char pre_de_buf_config(void) if (vframe == NULL) return 0; - if (vframe->type & VIDTYPE_COMPRESS) { + /*for support compress from dec*/ + if (IS_COMP_MODE(vframe->type) && + (!is_from_vdin(vframe))) { vframe->width = vframe->compWidth; vframe->height = vframe->compHeight; } + di_print("DI: get %dth vf[0x%p] from frontend %u ms.\n", di_pre_stru.in_seq, vframe, jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); @@ -3602,15 +3671,25 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); di_buf->vframe->width, di_buf->vframe->height, di_buf->vframe->source_type); - if (di_buf->type & VIDTYPE_COMPRESS) { - di_pre_stru.cur_width = - di_buf->vframe->compWidth; - di_pre_stru.cur_height = - di_buf->vframe->compHeight; + + if (IS_COMP_MODE(di_buf->vframe->type)) { + if (IS_VDIN_SRC(di_buf->vframe->source_type) && + IS_I_SRC(di_buf->vframe->type)) { + di_pre_stru.cur_width = + di_buf->vframe->compWidth; + di_pre_stru.cur_height = + di_buf->vframe->compHeight*2; + } else { + di_pre_stru.cur_width = + di_buf->vframe->compWidth; + di_pre_stru.cur_height = + di_buf->vframe->compHeight; + } } else { di_pre_stru.cur_width = di_buf->vframe->width; di_pre_stru.cur_height = di_buf->vframe->height; } + di_pre_stru.cur_prog_flag = is_progressive(di_buf->vframe); if (di_pre_stru.cur_prog_flag) { @@ -3890,7 +3969,11 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); vframe_type_name[di_buf->di_wr_linked_buf->type], di_buf->di_wr_linked_buf->index); #endif - if (di_pre_stru.cur_inp_type & VIDTYPE_COMPRESS) { + + /*for support compress from dec*/ + if (IS_COMP_MODE(di_pre_stru.cur_inp_type) && + (!(di_pre_stru.cur_inp_type & VIDTYPE_VIU_422))) { + /*compress type and not from vdin*/ di_pre_stru.di_inp_buf->vframe->width = di_pre_stru.di_inp_buf->vframe->compWidth; di_pre_stru.di_inp_buf->vframe->height = @@ -3945,7 +4028,6 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); if (bypass_state == 0) di_buf->vframe->type |= VIDTYPE_PRE_INTERLACE; } - if (is_bypass_post()) { if (bypass_post_state == 0) di_pre_stru.source_change_flag = 1; @@ -5914,6 +5996,7 @@ static void di_unreg_process_irq(void) adpative_combing_exit(); enable_di_pre_mif(false, mcpre_en); afbc_reg_sw(false); + afbc_input_sw(false); di_hw_uninit(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() @@ -6084,6 +6167,7 @@ static void di_pre_size_change(unsigned short width, static bool need_bypass(struct vframe_s *vf) { + needbypass_flag = true; if (vf->type & VIDTYPE_MVC) return true; @@ -6117,6 +6201,7 @@ static bool need_bypass(struct vframe_s *vf) (vf->width > 720)) return true; + needbypass_flag = false; return false; } @@ -6240,6 +6325,10 @@ static void di_reg_process_irq(void) calc_lmv_init(); first_field_type = (vframe->type & VIDTYPE_TYPEMASK); + + //pr_info("%s , %d\n", __func__, __LINE__); + //pr_info("filed type:0x%x, in H=%d, V=%d\n", + // first_field_type, vframe->width, nr_height); di_pre_size_change(vframe->width, nr_height, first_field_type); diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 9aa19e26558a..c594d61a0b9f 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -75,6 +75,16 @@ #endif #endif +#define IS_VDIN_SRC(src) ( \ + (src == VFRAME_SOURCE_TYPE_TUNER) || \ + (src == VFRAME_SOURCE_TYPE_CVBS) || \ + (src == VFRAME_SOURCE_TYPE_COMP) || \ + (src == VFRAME_SOURCE_TYPE_HDMI)) + +#define IS_I_SRC(vftype) (vftype & VIDTYPE_INTERLACE_BOTTOM) + +#define IS_COMP_MODE(vftype) (vftype & VIDTYPE_COMPRESS) + enum process_fun_index_e { PROCESS_FUN_NULL = 0, PROCESS_FUN_DI, diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index a65a546bd46d..0a3094c293eb 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -34,6 +34,7 @@ #include #include "register.h" #include "deinterlace_dbg.h" +#include "deinterlace_hw.h" #include "di_pps.h" #include "nr_downscale.h" #include @@ -630,7 +631,9 @@ void dump_mif_size_state(struct di_pre_stru_s *pre_stru_p, { pr_info("======pre mif status======\n"); pr_info("DI_PRE_CTRL=0x%x\n", Rd(DI_PRE_CTRL)); - pr_info("DI_PRE_SIZE=0x%x\n", Rd(DI_PRE_SIZE)); + pr_info("DI_PRE_SIZE H=%d, V=%d\n", + (Rd(DI_PRE_SIZE)>>16)&0xffff, + Rd(DI_PRE_SIZE)&0xffff); pr_info("DNR_HVSIZE=0x%x\n", Rd(DNR_HVSIZE)); if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { pr_info("CONTWR_CAN_SIZE=0x%x\n", Rd(0x37ec)); @@ -1045,6 +1048,27 @@ void dump_buf_addr(struct di_buf_s *di_buf, unsigned int num) } } +void dump_afbcd_reg(void) +{ + u32 i; + u32 afbc_reg; + + pr_info("---- dump afbc eAFBC_DEC0 reg -----\n"); + for (i = 0; i < AFBC_REG_INDEX_NUB; i++) { + afbc_reg = reg_AFBC[eAFBC_DEC0][i]; + pr_info("reg 0x%x val:0x%x\n", afbc_reg, RDMA_RD(afbc_reg)); + } + pr_info("---- dump afbc eAFBC_DEC1 reg -----\n"); + for (i = 0; i < AFBC_REG_INDEX_NUB; i++) { + afbc_reg = reg_AFBC[eAFBC_DEC1][i]; + pr_info("reg 0x%x val:0x%x\n", afbc_reg, RDMA_RD(afbc_reg)); + } + pr_info("reg 0x%x val:0x%x\n", + VD1_AFBCD0_MISC_CTRL, RDMA_RD(VD1_AFBCD0_MISC_CTRL)); + pr_info("reg 0x%x val:0x%x\n", + VD2_AFBCD1_MISC_CTRL, RDMA_RD(VD2_AFBCD1_MISC_CTRL)); +} + /*2018-08-17 add debugfs*/ /*same as dump_state*/ static int seq_file_di_state_show(struct seq_file *seq, void *v) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.h b/drivers/amlogic/media/deinterlace/deinterlace_dbg.h index ab4cbd98f4b1..21e83a9f8291 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.h @@ -18,6 +18,8 @@ #define _DI_DBG_H #include "deinterlace.h" +extern const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB]; + void parse_cmd_params(char *buf_orig, char **parm); void dump_di_pre_stru(struct di_pre_stru_s *di_pre_stru_p); void dump_di_post_stru(struct di_post_stru_s *di_post_stru_p); @@ -28,6 +30,7 @@ void dump_di_reg_g12(void); void print_di_buf(struct di_buf_s *di_buf, int format); void dump_pre_mif_state(void); void dump_post_mif_reg(void); +void dump_afbcd_reg(void); void dump_buf_addr(struct di_buf_s *di_buf, unsigned int num); void dump_mif_size_state(struct di_pre_stru_s *pre, struct di_post_stru_s *post); diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index ecea8354e008..d5dcfea92590 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "deinterlace_hw.h" #include "register.h" #include "register_nr4.h" @@ -59,6 +60,7 @@ module_param_named(pq_load_dbg, pq_load_dbg, uint, 0644); static bool pd22_flg_calc_en = true; static unsigned int ctrl_regs[SKIP_CTRE_NUM]; +u32 afbc_disable_flag; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA extern u32 VSYNC_RD_MPEG_REG(u32 adr); @@ -815,6 +817,96 @@ void enable_di_pre_aml( ); } } + +const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB] = { + { + AFBC_ENABLE, + AFBC_MODE, + AFBC_SIZE_IN, + AFBC_DEC_DEF_COLOR, + AFBC_CONV_CTRL, + AFBC_LBUF_DEPTH, + AFBC_HEAD_BADDR, + AFBC_BODY_BADDR, + AFBC_SIZE_OUT, + AFBC_OUT_YSCOPE, + AFBC_STAT, + AFBC_VD_CFMT_CTRL, + AFBC_VD_CFMT_W, + AFBC_MIF_HOR_SCOPE, + AFBC_MIF_VER_SCOPE, + AFBC_PIXEL_HOR_SCOPE, + AFBC_PIXEL_VER_SCOPE, + AFBC_VD_CFMT_H, + }, + { + VD2_AFBC_ENABLE, + VD2_AFBC_MODE, + VD2_AFBC_SIZE_IN, + VD2_AFBC_DEC_DEF_COLOR, + VD2_AFBC_CONV_CTRL, + VD2_AFBC_LBUF_DEPTH, + VD2_AFBC_HEAD_BADDR, + VD2_AFBC_BODY_BADDR, + VD2_AFBC_OUT_XSCOPE, + VD2_AFBC_OUT_YSCOPE, + VD2_AFBC_STAT, + VD2_AFBC_VD_CFMT_CTRL, + VD2_AFBC_VD_CFMT_W, + VD2_AFBC_MIF_HOR_SCOPE, + VD2_AFBC_MIF_VER_SCOPE, + VD2_AFBC_PIXEL_HOR_SCOPE, + VD2_AFBC_PIXEL_VER_SCOPE, + VD2_AFBC_VD_CFMT_H, + + }, + +}; + +static enum eAFBC_DEC afbc_get_decnub(void) +{ + enum eAFBC_DEC sel_dec = eAFBC_DEC0; + /* info from vlsi feijun + * gxl:have 1, AFBC_dec0 + * txlx:have 2, di only can use 1 + * g12a:have 2, di can use 2 + * tl1: have 1, AFBC_dec0 + */ + if (is_meson_gxl_cpu()) + sel_dec = eAFBC_DEC0; + else if (is_meson_txlx_cpu()) + sel_dec = eAFBC_DEC1; + else if (is_meson_g12a_cpu()) + sel_dec = eAFBC_DEC1; + else if (is_meson_tl1_cpu()) + sel_dec = eAFBC_DEC0; + return sel_dec; +} + +static const unsigned int *afbc_get_regbase(void) +{ + return ®_AFBC[afbc_get_decnub()][0]; +} + +bool afbc_is_supported(void) +{ + bool ret = false; + + if (afbc_disable_flag) + return false; + + /*currently support txlx and g12a*/ + if (is_meson_txlx_cpu()) + ret = false; + else if (is_meson_g12a_cpu()) + ret = false; + else if (is_meson_tl1_cpu()) + ret = true; + + return ret; + +} + /* * after g12a, framereset will not reset simple * wr mif of pre such as mtn&cont&mv&mcinfo wr @@ -899,157 +991,76 @@ void enable_afbc_input(struct vframe_s *vf) } #endif -enum eAFBC_REG { - eAFBC_ENABLE, - eAFBC_MODE, - eAFBC_SIZE_IN, - eAFBC_DEC_DEF_COLOR, - eAFBC_CONV_CTRL, - eAFBC_LBUF_DEPTH, - eAFBC_HEAD_BADDR, - eAFBC_BODY_BADDR, - eAFBC_SIZE_OUT, - eAFBC_OUT_YSCOPE, - eAFBC_STAT, - eAFBC_VD_CFMT_CTRL, - eAFBC_VD_CFMT_W, - eAFBC_MIF_HOR_SCOPE, - eAFBC_MIF_VER_SCOPE, - eAFBC_PIXEL_HOR_SCOPE, - eAFBC_PIXEL_VER_SCOPE, - eAFBC_VD_CFMT_H, -}; -enum eAFBC_DEC { - eAFBC_DEC0, - eAFBC_DEC1, -}; -#define AFBC_REG_INDEX_NUB (18) -#define AFBC_DEC_NUB (2) - -const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB] = { - { - AFBC_ENABLE, - AFBC_MODE, - AFBC_SIZE_IN, - AFBC_DEC_DEF_COLOR, - AFBC_CONV_CTRL, - AFBC_LBUF_DEPTH, - AFBC_HEAD_BADDR, - AFBC_BODY_BADDR, - AFBC_SIZE_OUT, - AFBC_OUT_YSCOPE, - AFBC_STAT, - AFBC_VD_CFMT_CTRL, - AFBC_VD_CFMT_W, - AFBC_MIF_HOR_SCOPE, - AFBC_MIF_VER_SCOPE, - AFBC_PIXEL_HOR_SCOPE, - AFBC_PIXEL_VER_SCOPE, - AFBC_VD_CFMT_H, - }, - { - VD2_AFBC_ENABLE, - VD2_AFBC_MODE, - VD2_AFBC_SIZE_IN, - VD2_AFBC_DEC_DEF_COLOR, - VD2_AFBC_CONV_CTRL, - VD2_AFBC_LBUF_DEPTH, - VD2_AFBC_HEAD_BADDR, - VD2_AFBC_BODY_BADDR, - VD2_AFBC_OUT_XSCOPE, - VD2_AFBC_OUT_YSCOPE, - VD2_AFBC_STAT, - VD2_AFBC_VD_CFMT_CTRL, - VD2_AFBC_VD_CFMT_W, - VD2_AFBC_MIF_HOR_SCOPE, - VD2_AFBC_MIF_VER_SCOPE, - VD2_AFBC_PIXEL_HOR_SCOPE, - VD2_AFBC_PIXEL_VER_SCOPE, - VD2_AFBC_VD_CFMT_H, - - }, - -}; -#define AFBC_DEC_SEL (eAFBC_DEC1) - - -static enum eAFBC_DEC afbc_get_decnub(void) -{ - enum eAFBC_DEC sel_dec = eAFBC_DEC0; - - if (is_meson_gxl_cpu()) - sel_dec = eAFBC_DEC0; - else if (is_meson_txlx_cpu()) - sel_dec = eAFBC_DEC1; - else if (is_meson_g12a_cpu()) - sel_dec = AFBC_DEC_SEL; - /* TL1 only have AFBC0 */ - else if (is_meson_tl1_cpu()) - sel_dec = eAFBC_DEC0; - return sel_dec; -} - -static const unsigned int *afbc_get_regbase(void) -{ - return ®_AFBC[afbc_get_decnub()][0]; -} - -bool afbc_is_supported(void) -{ - bool ret = false; - - /*currently support txlx and g12a*/ - if (is_meson_txlx_cpu() - || is_meson_g12a_cpu() - /*|| is_meson_tl1_cpu()*/) - ret = true; - return ret; - -} - -#define AFBC_DEC_SEL (eAFBC_DEC1) -void enable_afbc_input(struct vframe_s *vf) +u32 enable_afbc_input(struct vframe_s *vf) { unsigned int r, u, v, w_aligned, h_aligned; - unsigned int out_height = 0; - unsigned int vfmt_rpt_first = 1, vt_ini_phase = 0; const unsigned int *reg = afbc_get_regbase(); + unsigned int vfmt_rpt_first = 1, vt_ini_phase = 0; + unsigned int out_height = 0; if (!afbc_is_supported()) - return; + return false; - if ((vf->type & VIDTYPE_COMPRESS)) { - // only reg for the first time + if (vf->type & VIDTYPE_COMPRESS) { + /*only reg for the first time*/ afbc_reg_sw(true); - afbc_sw_trig(true); + afbc_sw(true); } else { - afbc_sw_trig(false); - return; + afbc_sw(false); + return false; } - w_aligned = round_up((vf->width-1), 32); - h_aligned = round_up((vf->height-1), 4); + + w_aligned = round_up((vf->width), 32); + /*if (di_pre_stru.cur_inp_type & VIDTYPE_INTERLACE)*/ + if ((vf->type & VIDTYPE_INTERLACE) && + (vf->type & VIDTYPE_VIU_422)) + h_aligned = round_up((vf->height/2), 4);/*from vdin and is i */ + else + h_aligned = round_up((vf->height), 4); + + /*AFBCD working mode config*/ r = (3 << 24) | (10 << 16) | (1 << 14) | /*burst1 1*/ (vf->bitdepth & BITDEPTH_MASK); + if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ if (vf->type & VIDTYPE_SCATTER) r |= (1<<29); + out_height = h_aligned; - if ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { - r |= 0x40; - vt_ini_phase = 0xc; - out_height = h_aligned>>1; - } else if ((vf->type & VIDTYPE_TYPEMASK) == - VIDTYPE_INTERLACE_BOTTOM) { - r |= 0x80; - vt_ini_phase = 0x4; - vfmt_rpt_first = 0; - out_height = h_aligned>>1; + if (!(vf->type & VIDTYPE_VIU_422)) { + /*from dec, process P as i*/ + if ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + r |= 0x40; + vt_ini_phase = 0xc; + vfmt_rpt_first = 1; + out_height = h_aligned>>1; + } else if ((vf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_BOTTOM) { + r |= 0x80; + vt_ini_phase = 0x4; + vfmt_rpt_first = 0; + out_height = h_aligned>>1; + } } RDMA_WR(reg[eAFBC_MODE], r); + + r = 0x1600; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + /* un compress mode data from vdin bit block order is + * different with from dos + */ + if (!(vf->type & VIDTYPE_VIU_422)) + r |= (1 << 19); /* dos_uncomp */ + + if (vf->type & VIDTYPE_COMB_MODE) + r |= (1 << 20); + } + RDMA_WR(reg[eAFBC_ENABLE], r); + r = 0x100; /* TL1 add bit[13:12]: fmt_mode; 0:yuv444; 1:yuv422; 2:yuv420 * di does not support yuv444, so for fmt yuv444 di will bypass+ @@ -1063,12 +1074,21 @@ void enable_afbc_input(struct vframe_s *vf) r |= (2 << 12); } RDMA_WR(reg[eAFBC_CONV_CTRL], r); + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; RDMA_WR(reg[eAFBC_DEC_DEF_COLOR], 0x3FF00000 | /*Y,bit20+*/ 0x80 << (u + 10) | 0x80 << v); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + RDMA_WR(reg[eAFBC_DEC_DEF_COLOR], + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ RDMA_WR(reg[eAFBC_VD_CFMT_CTRL], (1 << 21) |/* HFORMATTER_YC_RATIO_2_1 */ @@ -1077,25 +1097,46 @@ void enable_afbc_input(struct vframe_s *vf) (vt_ini_phase << 8) | (16 << 1)|/* VFORMATTER_PHASE_BIT */ 0);/* different with inp */ + #if 0 + if (((vf->width-1) != RDMA_RD(reg[eAFBC_PIXEL_HOR_SCOPE])) || + ((vf->height-1) != RDMA_RD(reg[eAFBC_PIXEL_VER_SCOPE]))) { + pr_info("[afbc] in vf type=0x%x\n", vf->type); + /*pr_info("cur_inp_type=0x%x\n", di_pre_stru.cur_inp_type);*/ + pr_info("[afbc] w_aligned=%d, h_aligned=%d\n", + w_aligned, h_aligned); + pr_info("[afbc] vfwidth=%d, vfheight=%d\n", + vf->width, vf->height); + pr_info("[afbc] out_height=%d\n", out_height); + } + #endif + if (vf->type & VIDTYPE_VIU_444) + RDMA_WR(reg[eAFBC_VD_CFMT_W], + (w_aligned << 16) | (w_aligned/2)); + else + RDMA_WR(reg[eAFBC_VD_CFMT_W], + (w_aligned << 16) | (w_aligned)); - RDMA_WR(reg[eAFBC_VD_CFMT_W], - (w_aligned << 16) | (w_aligned/2)); RDMA_WR(reg[eAFBC_MIF_HOR_SCOPE], - (0 << 16) | ((w_aligned>>5) - 1)); + (0 << 16) | ((w_aligned>>5)-1)); RDMA_WR(reg[eAFBC_MIF_VER_SCOPE], - (0 << 16) | ((h_aligned>>2) - 1)); + (0 << 16) | ((h_aligned>>2)-1)); RDMA_WR(reg[eAFBC_PIXEL_HOR_SCOPE], - (0 << 16) | (vf->width - 1)); + (0 << 16) | (vf->width-1)); + RDMA_WR(reg[eAFBC_PIXEL_VER_SCOPE], + 0 << 16 | (vf->height-1)); + RDMA_WR(reg[eAFBC_VD_CFMT_H], out_height); - RDMA_WR(reg[eAFBC_PIXEL_VER_SCOPE], - 0 << 16 | (vf->height-1)); - RDMA_WR(reg[eAFBC_SIZE_IN], h_aligned | w_aligned << 16); + RDMA_WR(reg[eAFBC_SIZE_IN], (vf->height) | w_aligned << 16); RDMA_WR(reg[eAFBC_SIZE_OUT], out_height | w_aligned << 16); + RDMA_WR(reg[eAFBC_HEAD_BADDR], vf->compHeadAddr>>4); RDMA_WR(reg[eAFBC_BODY_BADDR], vf->compBodyAddr>>4); + + return true; } + static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ { unsigned int reg_ctrl; @@ -1110,6 +1151,7 @@ static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ RDMA_WR_BITS(reg_ctrl, 0x55, 0, 8); } + static void afbcx_sw(bool on) /*g12a*/ { unsigned int tmp; @@ -1137,9 +1179,10 @@ static void afbcx_sw(bool on) /*g12a*/ | (1<<12) | (1<<9); RDMA_WR(reg_ctrl, tmp); + /*0:vd1 to di 1:vd2 to di */ RDMA_WR_BITS(VD2_AFBCD1_MISC_CTRL, (reg_ctrl == VD1_AFBCD0_MISC_CTRL)?0:1, 8, 1); - RDMA_WR(reg_en, 0x1600); + /*RDMA_WR(reg_en, 0x1600);*/ RDMA_WR_BITS(VIUB_MISC_CTRL0, 1, 16, 1); /*TL1 add mem control bit */ if (is_meson_tl1_cpu()) @@ -1154,8 +1197,6 @@ static void afbcx_sw(bool on) /*g12a*/ // printk("%s,on[%d],CTRL[0x%x],en[0x%x]\n", __func__, on, // RDMA_RD(VD1_AFBCD0_MISC_CTRL), // RDMA_RD(VD1_AFBCD0_MISC_CTRL)); - - } static void afbc_sw_old(bool on)/*txlx*/ { @@ -1172,7 +1213,6 @@ static void afbc_sw_old(bool on)/*txlx*/ reg_en = VD2_AFBC_ENABLE; } - if (on) { /* DI inp(current data) switch to AFBC */ if (RDMA_RD_BITS(VIU_MISC_CTRL0, 29, 1) != 1) @@ -1192,26 +1232,20 @@ static void afbc_sw_old(bool on)/*txlx*/ } else { RDMA_WR(reg_en, 0); /* afbc to vpp(replace vd1) enable */ - if (RDMA_RD_BITS(VIU_MISC_CTRL1, 0, 1) != 0 || RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) != 0) { RDMA_WR_BITS(VIU_MISC_CTRL1, 0, 0, 1); RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); } - - } } static bool afbc_is_used(void) { bool ret = false; - if (RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) == 1) ret = true; - //di_print("%s:%d\n",__func__,ret); - return ret; } static void afbc_power_sw(bool on) @@ -1229,15 +1263,21 @@ static void afbc_power_sw(bool on) switch_vpu_mem_pd_vmod(vpu_sel, on?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) afbcx_power_sw(dec_sel, on); - } + static int afbc_reg_unreg_flag; +void afbc_sw(bool on) +{ + if (is_meson_gxl_cpu() || is_meson_txlx_cpu()) + afbc_sw_old(on); + else + afbcx_sw(on); +} + void afbc_reg_sw(bool on) { - if (!afbc_is_supported()) return; @@ -1246,25 +1286,18 @@ void afbc_reg_sw(bool on) afbc_reg_unreg_flag = 1; } if ((!on) && afbc_reg_unreg_flag) { - afbc_sw_trig(false); + afbc_sw(false); afbc_power_sw(false); afbc_reg_unreg_flag = 0; } - -} -static void afbc_sw(bool on) -{ - if (is_meson_gxl_cpu() || is_meson_txlx_cpu()) - afbc_sw_old(on); - else - afbcx_sw(on); - } +#if 0 void afbc_sw_trig(bool on) { afbc_sw(on); } -static void afbc_input_sw(bool on) +#endif +void afbc_input_sw(bool on) { const unsigned int *reg = afbc_get_regbase(); unsigned int reg_AFBC_ENABLE; @@ -3631,9 +3664,11 @@ static void di_pre_data_mif_ctrl(bool enable) if (Rd_reg_bits(VIU_MISC_CTRL1, 0, 1) == 1) RDMA_WR_BITS(VD2_AFBC_ENABLE, 0, 8, 1); #else - /* disable AFBC input */ - if (afbc_is_used()) - afbc_input_sw(false); + /* + * disable AFBC input at unreg + */ + //if (afbc_is_used()) + // afbc_input_sw(false); #endif } diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index b464f562bc03..ec70fa5e8fa7 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -27,6 +27,34 @@ #define SKIP_CTRE_NUM 13 +enum eAFBC_REG { + eAFBC_ENABLE, /*0x1ae0*/ + eAFBC_MODE, /*0x1ae1*/ + eAFBC_SIZE_IN, /*0x1ae2*/ + eAFBC_DEC_DEF_COLOR, /*0x1ae3*/ + eAFBC_CONV_CTRL, /*0x1ae4*/ + eAFBC_LBUF_DEPTH, /*0x1ae5*/ + eAFBC_HEAD_BADDR, /*0x1ae6*/ + eAFBC_BODY_BADDR, /*0x1ae7*/ + eAFBC_SIZE_OUT, /*0x1ae8*/ + eAFBC_OUT_YSCOPE, /*0x1ae9*/ + eAFBC_STAT, /*0x1aea*/ + eAFBC_VD_CFMT_CTRL, /*0x1aeb*/ + eAFBC_VD_CFMT_W, /*0x1aec*/ + eAFBC_MIF_HOR_SCOPE, /*0x1aed*/ + eAFBC_MIF_VER_SCOPE, /*0x1aee*/ + eAFBC_PIXEL_HOR_SCOPE, /*0x1aef*/ + eAFBC_PIXEL_VER_SCOPE, /*0x1af0*/ + eAFBC_VD_CFMT_H, /*0x1af1*/ +}; + +enum eAFBC_DEC { + eAFBC_DEC0, + eAFBC_DEC1, +}; +#define AFBC_REG_INDEX_NUB (18) +#define AFBC_DEC_NUB (2) + struct DI_MIF_s { unsigned short luma_x_start0; unsigned short luma_x_end0; @@ -91,6 +119,7 @@ struct di_pq_parm_s { struct list_head list; }; +extern u32 afbc_disable_flag; void read_pulldown_info(unsigned int *glb_frm_mot_num, unsigned int *glb_fid_mot_num); void read_new_pulldown_info(struct FlmModReg_t *pFMRegp); @@ -109,7 +138,7 @@ void enable_di_pre_aml( struct DI_SIM_MIF_s *di_contwr_mif, unsigned char madi_en, unsigned char pre_field_num, unsigned char pre_vdin_link); -void enable_afbc_input(struct vframe_s *vf); +u32 enable_afbc_input(struct vframe_s *vf); void mc_pre_mv_irq(void); void enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif, @@ -179,7 +208,9 @@ void di_txl_patch_prog(int prog_flg, unsigned int cnt, bool mc_en); bool afbc_is_supported(void); //extern void afbc_power_sw(bool on); extern void afbc_reg_sw(bool on); -extern void afbc_sw_trig(bool on); +/*extern void afbc_sw_trig(bool on);*/ +extern void afbc_sw(bool on); +extern void afbc_input_sw(bool on); extern void dump_vd2_afbc(void); extern u8 *di_vmap(ulong addr, u32 size, bool *bflg); From ca322d7a1b1361568e9fbbc9a8d01ebfee4ec418 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 13 Mar 2019 20:12:58 +0800 Subject: [PATCH 0650/1060] di: 1080p,the screen display anormal [1/1] PD#SWPL-5874 Problem: 1080p the screen display anormal Solution: compress mode, modify vdin frame type. Verify: tl1 Change-Id: Ic1ee1472105861c8debce2a1645f70ed617fd132 Signed-off-by: Yong Qin --- drivers/amlogic/media/deinterlace/deinterlace.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 19dcdb48b3b0..8edd0675f1f4 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-05a"; +static const char version_s[] = "2019-03-13b"; static int bypass_state = 1; static int bypass_all; @@ -3531,10 +3531,15 @@ static unsigned char pre_de_buf_config(void) return 0; /*for support compress from dec*/ - if (IS_COMP_MODE(vframe->type) && - (!is_from_vdin(vframe))) { - vframe->width = vframe->compWidth; - vframe->height = vframe->compHeight; + if (IS_COMP_MODE(vframe->type)) { + if (IS_VDIN_SRC(vframe->source_type) + && IS_I_SRC(vframe->type)) { + vframe->width = vframe->compWidth; + vframe->height = vframe->compHeight*2; + } else { + vframe->width = vframe->compWidth; + vframe->height = vframe->compHeight; + } } di_print("DI: get %dth vf[0x%p] from frontend %u ms.\n", @@ -3970,7 +3975,7 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); di_buf->di_wr_linked_buf->index); #endif - /*for support compress from dec*/ + /*for support compress from dec, not from vdin*/ if (IS_COMP_MODE(di_pre_stru.cur_inp_type) && (!(di_pre_stru.cur_inp_type & VIDTYPE_VIU_422))) { /*compress type and not from vdin*/ From e5cf70280decfb509716bbdfc67bcafa3b03bf33 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 6 Mar 2019 18:51:42 +0800 Subject: [PATCH 0651/1060] di: pretect reg unreg flow [1/1] PD#SWPL-4918 Problem: when reg unreg event called too fast, di cause system crash Solution: pretect reg and unreg flow Verify: tl1 Change-Id: I9b3e28c2b0b709d4f53f60b1f044a390933117ce Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c --- .../amlogic/media/deinterlace/deinterlace.c | 102 +++++++++++++++--- 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 8edd0675f1f4..10ba49afc806 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-13b"; +static const char version_s[] = "2019-03-14b"; static int bypass_state = 1; static int bypass_all; @@ -266,6 +266,8 @@ static long same_field_bot_count; static int post_hold_line = 8; /*2019-01-10: from VLSI feijun from 17 to 8*/ static int post_urgent = 1; +static struct mutex di_event_mutex; + /*pre process speed debug */ static int pre_process_time; static int di_receiver_event_fun(int type, void *data, void *arg); @@ -3465,8 +3467,14 @@ static unsigned char pre_de_buf_config(void) bool bit10_pack_patch = false; unsigned int width_roundup = 2; - if (di_blocking || !atomic_read(&de_devp->mem_flag)) + if (di_blocking || !atomic_read(&de_devp->mem_flag) + || di_pre_stru.unreg_req_flag) { + if (di_pre_stru.unreg_req_flag) + pr_info("DI: %s fail unreg_req_flag=%d\n", __func__, + di_pre_stru.unreg_req_flag); return 0; + } + if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) || (queue_empty(QUEUE_LOCAL_FREE))) return 0; @@ -5989,6 +5997,8 @@ static void di_unreg_process_irq(void) ulong flags = 0; spin_lock_irqsave(&plist_lock, flags); #endif + + pr_info("DI: %s S\n", __func__); init_flag = 0; mirror_disable = get_blackout_policy(); di_lock_irqfiq_save(irq_flag2); @@ -6053,6 +6063,7 @@ static void di_unreg_process_irq(void) up(&di_sema); } #endif + pr_info("DI: %s E\n", __func__); } static void di_reg_process(void) @@ -6228,7 +6239,6 @@ static void di_reg_process_irq(void) if (pre_run_flag == DI_RUN_FLAG_STEP) pre_run_flag = DI_RUN_FLAG_STEP_DONE; - vframe = vf_peek(VFM_NAME); if (vframe) { @@ -6601,7 +6611,10 @@ static void di_pre_process_irq(struct di_pre_stru_s *pre_stru_p) } for (i = 0; i < 2; i++) { - if (active_flag) + if (active_flag && (!pre_stru_p->unreg_req_flag_irq + && !pre_stru_p->unreg_req_flag + && !pre_stru_p->reg_req_flag_irq + && !pre_stru_p->reg_req_flag)) di_process(); } log_buffer_state("pro"); @@ -6634,19 +6647,45 @@ static int di_receiver_event_fun(int type, void *data, void *arg) { int i; ulong flags; + char *provider_name = (char *)data; + u32 sts = 0; if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) { + sts = di_pre_stru.vdin2nr; return di_pre_stru.vdin2nr; } else if (type == VFRAME_EVENT_PROVIDER_UNREG) { + mutex_lock(&di_event_mutex); + pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n", __func__, is_bypass(NULL), trick_mode, bypass_all); - pr_info("%s: vf_notify_receiver unreg\n", __func__); + pr_info("DI: %s: unreg\n", __func__); + pr_info("DI: provider name:%s\n", provider_name); - di_pre_stru.unreg_req_flag = 1; + if (di_pre_stru.reg_req_flag || + di_pre_stru.reg_req_flag_irq) + pr_info("DI: warning reg_req_flag is %d,%d\n", + di_pre_stru.reg_req_flag, + di_pre_stru.reg_req_flag_irq); di_pre_stru.vdin_source = false; + + /*check reg process, and waiting reg*/ + di_pre_stru.unreg_req_flag_cnt = 0; + while (di_pre_stru.reg_req_flag || + di_pre_stru.reg_req_flag_irq) { + msleep(20); + if (di_pre_stru.unreg_req_flag_cnt++ > + di_reg_unreg_cnt) { + pr_err("DI : reg to unreg timeout!!!\n"); + di_reg_process(); + break; + } + } + di_pre_stru.unreg_req_flag = 1; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); + /*check unreg process*/ di_pre_stru.unreg_req_flag_cnt = 0; while (di_pre_stru.unreg_req_flag) { + /*waitting di_unreg_process_irq finish*/ usleep_range(10000, 10001); if (di_pre_stru.unreg_req_flag_cnt++ > di_reg_unreg_cnt) { @@ -6674,10 +6713,12 @@ static int di_receiver_event_fun(int type, void *data, void *arg) if (di_pre_stru.vdin_source) DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); #endif + mutex_unlock(&di_event_mutex); + pr_info("DI:ureg f\n"); } else if (type == VFRAME_EVENT_PROVIDER_RESET) { di_blocking = 1; - pr_dbg("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__); + pr_info("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__); if (is_bypass(NULL) || bypass_state || di_pre_stru.bypass_flag) { @@ -6690,7 +6731,7 @@ static int di_receiver_event_fun(int type, void *data, void *arg) } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) { di_blocking = 1; - pr_dbg("%s: vf_notify_receiver ligth unreg\n", __func__); + pr_info("%s: vf_notify_receiver ligth unreg\n", __func__); light_unreg: spin_lock_irqsave(&plist_lock, flags); @@ -6706,7 +6747,7 @@ light_unreg: } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) { unsigned char vf_put_flag = 0; - pr_dbg( + pr_info( "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n", __func__); /* @@ -6834,29 +6875,52 @@ light_unreg: } #endif } else if (type == VFRAME_EVENT_PROVIDER_REG) { - char *provider_name = (char *)data; + /*char *provider_name = (char *)data;*/ char *receiver_name = NULL; + mutex_lock(&di_event_mutex); + if (de_devp->flags & DI_SUSPEND_FLAG) { pr_err("[DI] reg event device hasn't resumed\n"); + mutex_unlock(&di_event_mutex); return -1; } if (reg_flag) { pr_err("[DI] no muti instance.\n"); + mutex_unlock(&di_event_mutex); return -1; } - pr_info("%s: vframe provider reg %s\n", __func__, - provider_name); + pr_info("DI: %s: reg\n", __func__); + pr_info("DI: provider name:%s\n", provider_name); bypass_state = 0; - di_pre_stru.reg_req_flag = 1; + if (di_pre_stru.unreg_req_flag || + di_pre_stru.unreg_req_flag_irq) + pr_info("DI: warning unreg_req_flag is %d,%d\n", + di_pre_stru.unreg_req_flag, + di_pre_stru.unreg_req_flag_irq); trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); + /*check unreg process*/ + di_pre_stru.reg_req_flag_cnt = 0; + while (di_pre_stru.unreg_req_flag || + di_pre_stru.unreg_req_flag_irq) { + msleep(20); + if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { + pr_err("%s:unreg to reg timeout!!!\n", + __func__); + di_unreg_process(); + break; + } + } + + di_pre_stru.reg_req_flag = 1; + /*check reg process*/ di_pre_stru.reg_req_flag_cnt = 0; while (di_pre_stru.reg_req_flag) { usleep_range(10000, 10001); if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { reg_unreg_timeout_cnt++; - pr_dbg("%s:reg_req_flag timeout!!!\n", + pr_err("%s:reg_req_flag timeout!!!\n", __func__); break; } @@ -6881,6 +6945,8 @@ light_unreg: } else { pr_info("%s error receiver is null.\n", __func__); } + mutex_unlock(&di_event_mutex); + pr_info("DI:reg f\n"); } #ifdef DET3D else if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) { @@ -6897,9 +6963,9 @@ light_unreg: VFRAME_EVENT_PROVIDER_FR_END_HINT, data); } - return 0; + return sts; } - +#if 0 static void fast_process(void) { int i; @@ -6956,6 +7022,7 @@ static void fast_process(void) } } } +#endif static vframe_t *di_vf_peek(void *arg) { @@ -6974,7 +7041,7 @@ static vframe_t *di_vf_peek(void *arg) log_buffer_state("pek"); - fast_process(); + /*fast_process(); qy temp */ #ifdef SUPPORT_START_FRAME_HOLD if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) { int ready_count = list_count(QUEUE_POST_READY); @@ -7754,6 +7821,7 @@ static int di_probe(struct platform_device *pdev) device_create_file(di_devp->dev, &dev_attr_tvp_region); pd_device_files_add(di_devp->dev); nr_drv_init(di_devp->dev); + mutex_init(&di_event_mutex); init_flag = 0; reg_flag = 0; From 4590122d39b4cdc7d90d3f57e1d495ed29a819cf Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 18 Mar 2019 17:20:09 +0800 Subject: [PATCH 0652/1060] di: exit play local 4k video flashing [1/1] PD#SWPL-5877 Problem: 1.afbc mode, play h.265 local video, when exit playing, screen will flashing sometimes. 2.when exit playing, there cost 5s time. Solution: 4k video di bypass, afbc hw module used by vpp, when DI unreg, needn't to disable AFBC moudule. Verify: tl1 Change-Id: I2ac66a145a009042d286dda50e7259657f4bfc8e Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c --- .../amlogic/media/deinterlace/deinterlace.c | 43 ++++++------------- .../media/deinterlace/deinterlace_hw.c | 35 +++++++-------- 2 files changed, 30 insertions(+), 48 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 10ba49afc806..54a6efc48f74 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-14b"; +static const char version_s[] = "2019-03-19"; static int bypass_state = 1; static int bypass_all; @@ -274,8 +274,8 @@ static int di_receiver_event_fun(int type, void *data, void *arg); static void di_uninit_buf(unsigned int disable_mirror); static void log_buffer_state(unsigned char *tag); /* static void put_get_disp_buf(void); */ -static unsigned int isbypass_flag; -static unsigned int needbypass_flag; +static unsigned int isbypass_flag = true; +static unsigned int needbypass_flag = true; static const struct vframe_receiver_op_s di_vf_receiver = { @@ -6010,8 +6010,15 @@ static void di_unreg_process_irq(void) #endif adpative_combing_exit(); enable_di_pre_mif(false, mcpre_en); - afbc_reg_sw(false); - afbc_input_sw(false); + /*disable afbc module when afbc working in DI*/ + #if 0 + if (IS_COMP_MODE(di_pre_stru.cur_inp_type) && + (!needbypass_flag && !isbypass_flag)) { + pr_info("DI: disable afbc\n"); + afbc_reg_sw(false); + afbc_input_sw(false); + } + #endif di_hw_uninit(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() @@ -6667,19 +6674,6 @@ static int di_receiver_event_fun(int type, void *data, void *arg) di_pre_stru.reg_req_flag, di_pre_stru.reg_req_flag_irq); di_pre_stru.vdin_source = false; - - /*check reg process, and waiting reg*/ - di_pre_stru.unreg_req_flag_cnt = 0; - while (di_pre_stru.reg_req_flag || - di_pre_stru.reg_req_flag_irq) { - msleep(20); - if (di_pre_stru.unreg_req_flag_cnt++ > - di_reg_unreg_cnt) { - pr_err("DI : reg to unreg timeout!!!\n"); - di_reg_process(); - break; - } - } di_pre_stru.unreg_req_flag = 1; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); /*check unreg process*/ @@ -6900,19 +6894,6 @@ light_unreg: di_pre_stru.unreg_req_flag_irq); trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); - /*check unreg process*/ - di_pre_stru.reg_req_flag_cnt = 0; - while (di_pre_stru.unreg_req_flag || - di_pre_stru.unreg_req_flag_irq) { - msleep(20); - if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { - pr_err("%s:unreg to reg timeout!!!\n", - __func__); - di_unreg_process(); - break; - } - } - di_pre_stru.reg_req_flag = 1; /*check reg process*/ di_pre_stru.reg_req_flag_cnt = 0; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index d5dcfea92590..c4f2aed2f002 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -1136,7 +1136,7 @@ u32 enable_afbc_input(struct vframe_s *vf) return true; } - +#if 0 static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ { unsigned int reg_ctrl; @@ -1151,23 +1151,23 @@ static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ RDMA_WR_BITS(reg_ctrl, 0x55, 0, 8); } - +#endif static void afbcx_sw(bool on) /*g12a*/ { unsigned int tmp; unsigned int mask; unsigned int reg_ctrl, reg_en; enum eAFBC_DEC dec_sel; + const unsigned int *reg = afbc_get_regbase(); dec_sel = afbc_get_decnub(); if (dec_sel == eAFBC_DEC0) { reg_ctrl = VD1_AFBCD0_MISC_CTRL; - reg_en = AFBC_ENABLE; } else { reg_ctrl = VD2_AFBCD1_MISC_CTRL; - reg_en = VD2_AFBC_ENABLE; } + reg_en = reg[eAFBC_ENABLE]; mask = (3<<20) | (1<<12) | (1<<9); /*clear*/ @@ -1194,24 +1194,15 @@ static void afbcx_sw(bool on) /*g12a*/ if (is_meson_tl1_cpu()) RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 0, 22, 1); } -// printk("%s,on[%d],CTRL[0x%x],en[0x%x]\n", __func__, on, -// RDMA_RD(VD1_AFBCD0_MISC_CTRL), -// RDMA_RD(VD1_AFBCD0_MISC_CTRL)); } static void afbc_sw_old(bool on)/*txlx*/ { enum eAFBC_DEC dec_sel; unsigned int reg_en; + const unsigned int *reg = afbc_get_regbase(); dec_sel = afbc_get_decnub(); - - if (dec_sel == eAFBC_DEC0) { - //reg_ctrl = VD1_AFBCD0_MISC_CTRL; - reg_en = AFBC_ENABLE; - } else { - //reg_ctrl = VD2_AFBCD1_MISC_CTRL; - reg_en = VD2_AFBC_ENABLE; - } + reg_en = reg[eAFBC_ENABLE]; if (on) { /* DI inp(current data) switch to AFBC */ @@ -1253,6 +1244,7 @@ static void afbc_power_sw(bool on) /*afbc*/ enum eAFBC_DEC dec_sel; unsigned int vpu_sel; + unsigned int reg_ctrl; dec_sel = afbc_get_decnub(); if (dec_sel == eAFBC_DEC0) @@ -1263,8 +1255,17 @@ static void afbc_power_sw(bool on) switch_vpu_mem_pd_vmod(vpu_sel, on?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) - afbcx_power_sw(dec_sel, on); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (dec_sel == eAFBC_DEC0) + reg_ctrl = VD1_AFBCD0_MISC_CTRL; + else + reg_ctrl = VD2_AFBCD1_MISC_CTRL; + if (on) + RDMA_WR_BITS(reg_ctrl, 0, 0, 8); + else + RDMA_WR_BITS(reg_ctrl, 0x55, 0, 8); + } + /*afbcx_power_sw(dec_sel, on);*/ } static int afbc_reg_unreg_flag; From c348b65736eda7779a8a0349c4a47cda0dc230bf Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 20 Mar 2019 12:44:48 +0800 Subject: [PATCH 0653/1060] di: flash green when play 265 SD video [1/1] PD#SWPL-6097 Problem: flash green garbages when play h.265 SD video Solution: afbc input not enable Verify: tl1 Change-Id: I310eeb6d922ab8b9035c815afc4e967c0e5390ff Signed-off-by: Yong Qin --- drivers/amlogic/media/deinterlace/deinterlace.c | 3 ++- drivers/amlogic/media/deinterlace/deinterlace_hw.c | 4 ++-- drivers/amlogic/media/deinterlace/deinterlace_hw.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 54a6efc48f74..b2bd24368ad9 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-19"; +static const char version_s[] = "2019-03-20a"; static int bypass_state = 1; static int bypass_all; @@ -6011,6 +6011,7 @@ static void di_unreg_process_irq(void) adpative_combing_exit(); enable_di_pre_mif(false, mcpre_en); /*disable afbc module when afbc working in DI*/ + afbc_reg_unreg_flag = 0; #if 0 if (IS_COMP_MODE(di_pre_stru.cur_inp_type) && (!needbypass_flag && !isbypass_flag)) { diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index c4f2aed2f002..69736cb628f9 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -1268,7 +1268,7 @@ static void afbc_power_sw(bool on) /*afbcx_power_sw(dec_sel, on);*/ } -static int afbc_reg_unreg_flag; +int afbc_reg_unreg_flag; void afbc_sw(bool on) { if (is_meson_gxl_cpu() || is_meson_txlx_cpu()) @@ -3646,7 +3646,7 @@ static void di_pre_data_mif_ctrl(bool enable) afbc_input_sw(true); } else { DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) | 0x1); - afbc_input_sw(false); + /*afbc_input_sw(false);*/ } #endif /* nrwr no clk gate en=0 */ diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index ec70fa5e8fa7..130d8a72eda2 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -212,6 +212,7 @@ extern void afbc_reg_sw(bool on); extern void afbc_sw(bool on); extern void afbc_input_sw(bool on); extern void dump_vd2_afbc(void); +extern int afbc_reg_unreg_flag; extern u8 *di_vmap(ulong addr, u32 size, bool *bflg); extern void di_unmap_phyaddr(u8 *vaddr); From d289c1307c2f8d27e75be8457035c0053d5993e3 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Fri, 22 Mar 2019 14:36:17 +0800 Subject: [PATCH 0654/1060] di: The last frame of the video flash garbage [1/1] PD#SWPL-6070 Problem: flash garbages when unreg process. Solution: can't speed down the clkb rate, there is a mirror mode Verify: tl1 Change-Id: I5fcc29a1cda196992a457f40fee31992f4bc1528 Signed-off-by: Yong Qin --- drivers/amlogic/media/deinterlace/deinterlace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index b2bd24368ad9..7014349d4787 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-20a"; +static const char version_s[] = "2019-03-22va"; static int bypass_state = 1; static int bypass_all; @@ -6543,11 +6543,14 @@ static int di_task_handle(void *data) di_pre_stru.disable_req_flag) && (di_pre_stru.pre_de_busy == 0)) { di_unreg_process(); + #if 0 + /* if mirror mode, can't speed down the clk*/ /* set min rate for power saving */ if (de_devp->vpu_clkb) { clk_set_rate(de_devp->vpu_clkb, de_devp->clkb_min_rate); } + #endif } if (di_pre_stru.reg_req_flag_irq || di_pre_stru.reg_req_flag) { From 08290d7ec9f1363cd38a9f4be217eed6600d5f97 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 25 Mar 2019 16:12:14 +0800 Subject: [PATCH 0655/1060] di: av to dtv , black screen [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD#SWPL-6096 Problem: from local av switch to dtv,black screen,then search channel Solution: revert the modification "62617" Verify: tl1 Change-Id: I49ae627b9f0b1f6a776e5cbffc723a43e85cee72 Signed-off-by: Yong Qin --- .../amlogic/media/deinterlace/deinterlace.c | 76 +++++-------------- 1 file changed, 19 insertions(+), 57 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 7014349d4787..f82acd268a81 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-22va"; +static const char version_s[] = "2019-03-25va"; static int bypass_state = 1; static int bypass_all; @@ -266,8 +266,6 @@ static long same_field_bot_count; static int post_hold_line = 8; /*2019-01-10: from VLSI feijun from 17 to 8*/ static int post_urgent = 1; -static struct mutex di_event_mutex; - /*pre process speed debug */ static int pre_process_time; static int di_receiver_event_fun(int type, void *data, void *arg); @@ -3467,14 +3465,8 @@ static unsigned char pre_de_buf_config(void) bool bit10_pack_patch = false; unsigned int width_roundup = 2; - if (di_blocking || !atomic_read(&de_devp->mem_flag) - || di_pre_stru.unreg_req_flag) { - if (di_pre_stru.unreg_req_flag) - pr_info("DI: %s fail unreg_req_flag=%d\n", __func__, - di_pre_stru.unreg_req_flag); + if (di_blocking || !atomic_read(&de_devp->mem_flag)) return 0; - } - if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) || (queue_empty(QUEUE_LOCAL_FREE))) return 0; @@ -5997,8 +5989,6 @@ static void di_unreg_process_irq(void) ulong flags = 0; spin_lock_irqsave(&plist_lock, flags); #endif - - pr_info("DI: %s S\n", __func__); init_flag = 0; mirror_disable = get_blackout_policy(); di_lock_irqfiq_save(irq_flag2); @@ -6071,7 +6061,6 @@ static void di_unreg_process_irq(void) up(&di_sema); } #endif - pr_info("DI: %s E\n", __func__); } static void di_reg_process(void) @@ -6247,6 +6236,7 @@ static void di_reg_process_irq(void) if (pre_run_flag == DI_RUN_FLAG_STEP) pre_run_flag = DI_RUN_FLAG_STEP_DONE; + vframe = vf_peek(VFM_NAME); if (vframe) { @@ -6622,10 +6612,7 @@ static void di_pre_process_irq(struct di_pre_stru_s *pre_stru_p) } for (i = 0; i < 2; i++) { - if (active_flag && (!pre_stru_p->unreg_req_flag_irq - && !pre_stru_p->unreg_req_flag - && !pre_stru_p->reg_req_flag_irq - && !pre_stru_p->reg_req_flag)) + if (active_flag) di_process(); } log_buffer_state("pro"); @@ -6659,31 +6646,21 @@ static int di_receiver_event_fun(int type, void *data, void *arg) int i; ulong flags; char *provider_name = (char *)data; - u32 sts = 0; if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) { - sts = di_pre_stru.vdin2nr; return di_pre_stru.vdin2nr; } else if (type == VFRAME_EVENT_PROVIDER_UNREG) { - mutex_lock(&di_event_mutex); - pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n", __func__, is_bypass(NULL), trick_mode, bypass_all); + di_pre_stru.vdin_source = false; pr_info("DI: %s: unreg\n", __func__); pr_info("DI: provider name:%s\n", provider_name); - if (di_pre_stru.reg_req_flag || - di_pre_stru.reg_req_flag_irq) - pr_info("DI: warning reg_req_flag is %d,%d\n", - di_pre_stru.reg_req_flag, - di_pre_stru.reg_req_flag_irq); - di_pre_stru.vdin_source = false; di_pre_stru.unreg_req_flag = 1; + di_pre_stru.vdin_source = false; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); - /*check unreg process*/ di_pre_stru.unreg_req_flag_cnt = 0; while (di_pre_stru.unreg_req_flag) { - /*waitting di_unreg_process_irq finish*/ usleep_range(10000, 10001); if (di_pre_stru.unreg_req_flag_cnt++ > di_reg_unreg_cnt) { @@ -6711,12 +6688,11 @@ static int di_receiver_event_fun(int type, void *data, void *arg) if (di_pre_stru.vdin_source) DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); #endif - mutex_unlock(&di_event_mutex); - pr_info("DI:ureg f\n"); + pr_info("DI: unreg f\n"); } else if (type == VFRAME_EVENT_PROVIDER_RESET) { di_blocking = 1; - pr_info("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__); + pr_dbg("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__); if (is_bypass(NULL) || bypass_state || di_pre_stru.bypass_flag) { @@ -6729,7 +6705,7 @@ static int di_receiver_event_fun(int type, void *data, void *arg) } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) { di_blocking = 1; - pr_info("%s: vf_notify_receiver ligth unreg\n", __func__); + pr_dbg("%s: vf_notify_receiver ligth unreg\n", __func__); light_unreg: spin_lock_irqsave(&plist_lock, flags); @@ -6745,7 +6721,7 @@ light_unreg: } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) { unsigned char vf_put_flag = 0; - pr_info( + pr_dbg( "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n", __func__); /* @@ -6873,39 +6849,28 @@ light_unreg: } #endif } else if (type == VFRAME_EVENT_PROVIDER_REG) { - /*char *provider_name = (char *)data;*/ char *receiver_name = NULL; - mutex_lock(&di_event_mutex); - if (de_devp->flags & DI_SUSPEND_FLAG) { pr_err("[DI] reg event device hasn't resumed\n"); - mutex_unlock(&di_event_mutex); return -1; } if (reg_flag) { pr_err("[DI] no muti instance.\n"); - mutex_unlock(&di_event_mutex); return -1; } - pr_info("DI: %s: reg\n", __func__); - pr_info("DI: provider name:%s\n", provider_name); + pr_info("%s: vframe provider reg %s\n", __func__, + provider_name); bypass_state = 0; - if (di_pre_stru.unreg_req_flag || - di_pre_stru.unreg_req_flag_irq) - pr_info("DI: warning unreg_req_flag is %d,%d\n", - di_pre_stru.unreg_req_flag, - di_pre_stru.unreg_req_flag_irq); - - trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); di_pre_stru.reg_req_flag = 1; - /*check reg process*/ + trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); + /*check unreg process*/ di_pre_stru.reg_req_flag_cnt = 0; while (di_pre_stru.reg_req_flag) { usleep_range(10000, 10001); if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { reg_unreg_timeout_cnt++; - pr_err("%s:reg_req_flag timeout!!!\n", + pr_dbg("%s:reg_req_flag timeout!!!\n", __func__); break; } @@ -6930,8 +6895,7 @@ light_unreg: } else { pr_info("%s error receiver is null.\n", __func__); } - mutex_unlock(&di_event_mutex); - pr_info("DI:reg f\n"); + pr_info("DI: reg f\n"); } #ifdef DET3D else if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) { @@ -6948,9 +6912,9 @@ light_unreg: VFRAME_EVENT_PROVIDER_FR_END_HINT, data); } - return sts; + return 0; } -#if 0 + static void fast_process(void) { int i; @@ -7007,7 +6971,6 @@ static void fast_process(void) } } } -#endif static vframe_t *di_vf_peek(void *arg) { @@ -7026,7 +6989,7 @@ static vframe_t *di_vf_peek(void *arg) log_buffer_state("pek"); - /*fast_process(); qy temp */ + fast_process(); #ifdef SUPPORT_START_FRAME_HOLD if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) { int ready_count = list_count(QUEUE_POST_READY); @@ -7806,7 +7769,6 @@ static int di_probe(struct platform_device *pdev) device_create_file(di_devp->dev, &dev_attr_tvp_region); pd_device_files_add(di_devp->dev); nr_drv_init(di_devp->dev); - mutex_init(&di_event_mutex); init_flag = 0; reg_flag = 0; From f2d5089e0bf5a71c6d789fe9bc4a99a185936184 Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Thu, 14 Mar 2019 14:31:38 +0800 Subject: [PATCH 0656/1060] di: "DI: di_init_buf vmap fail" is seen when power on [1/1] PD#SWPL-5908 Problem: execute vmap when di reserved memory is disable Solution: skip memory calculation in init buf while using cma Verify: verified by t962x2_x301 Change-Id: Ib0c2e422f61f2b4182109cb7bbb3107029363ce0 Signed-off-by: zhiwei.yuan --- .../amlogic/media/deinterlace/deinterlace.c | 72 ++++++++++++------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index f82acd268a81..b58ddd481343 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -2240,46 +2240,62 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) if (prog_flag) { di_buf->canvas_height = canvas_height; - di_buf->nr_adr = de_devp->mem_start + - di_buf_size * i; + + //use reserved memory + if (de_devp->flag_cma == 0) + di_buf->nr_adr = de_devp->mem_start + + di_buf_size * i; + di_buf->canvas_config_flag = 1; } else { di_buf->canvas_height = (canvas_height>>1); di_buf->canvas_height = roundup(di_buf->canvas_height, canvas_align_width); - di_buf->nr_adr = de_devp->mem_start + - di_buf_size * i; - di_buf->mtn_adr = de_devp->mem_start + - di_buf_size * i + - nr_size; - di_buf->cnt_adr = de_devp->mem_start + - di_buf_size * i + - nr_size + mtn_size; - if (mc_mem_alloc) { - di_buf->mcvec_adr = de_devp->mem_start + + //use reserved memory + if (de_devp->flag_cma == 0) { + di_buf->nr_adr = de_devp->mem_start + + di_buf_size * i; + di_buf->mtn_adr = de_devp->mem_start + di_buf_size * i + - nr_size + mtn_size + count_size; - di_buf->mcinfo_adr = - de_devp->mem_start + - di_buf_size * i + nr_size + - mtn_size + count_size + mv_size; - tmp = di_vmap(di_buf->mcinfo_adr, - di_pre_stru.mcinfo_size, - &di_buf->bflg_vmap); + nr_size; + di_buf->cnt_adr = de_devp->mem_start + + di_buf_size * i + + nr_size + mtn_size; + + if (mc_mem_alloc) { + di_buf->mcvec_adr = + de_devp->mem_start + + di_buf_size * i + + nr_size + mtn_size + + count_size; + di_buf->mcinfo_adr = + de_devp->mem_start + + di_buf_size * i + + nr_size + + mtn_size + + count_size + mv_size; + tmp = di_vmap( + di_buf->mcinfo_adr, + di_pre_stru. + mcinfo_size, + &di_buf->bflg_vmap); if (di_buf->bflg_vmap == true) di_buf->mcinfo_vaddr = - (unsigned short *)tmp; + (unsigned short *)tmp; else { di_buf->mcinfo_vaddr = NULL; pr_err("DI: %s vmap fail\n", __func__); } + } } + di_buf->canvas_config_flag = 2; } + di_buf->index = i; di_buf->vframe = &(vframe_local[i]); di_buf->vframe->private_data = di_buf; @@ -2299,8 +2315,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) up(&di_sema); } #endif - di_post_mem = de_devp->mem_start + - di_buf_size*de_devp->buf_num_avail; + + //use reserved memory + if (de_devp->flag_cma == 0) + di_post_mem = de_devp->mem_start + + di_buf_size*de_devp->buf_num_avail; if (post_wr_en && post_wr_support) { di_post_buf_size = nr_width * canvas_height * 2; /* pre buffer must 2 more than post buffer */ @@ -2348,8 +2367,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) (nr_width << 1); di_buf->canvas_height = canvas_height; di_buf->canvas_config_flag = 1; - di_buf->nr_adr = di_post_mem + - di_post_buf_size*i; + + //use reserved memory + if (de_devp->flag_cma == 0) + di_buf->nr_adr = di_post_mem + + di_post_buf_size*i; } queue_in(di_buf, QUEUE_POST_FREE); } From 5e600034e6257d5c6648ad6d7da27828cf02d841 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Tue, 26 Mar 2019 17:01:44 +0800 Subject: [PATCH 0657/1060] di: monkey test di cause crash [1/1] PD#SWPL-6133 Problem: monkey test di cause crash,when is di reg processing, unreg event attach, and released the di buffer, so cause crash. Solution: every unreg event received, need waitting reg process had done. Verify: tl1 Change-Id: I2f2bb068ed65ab14ab4f09de96b64d7290da5914 Signed-off-by: Yong Qin --- .../amlogic/media/deinterlace/deinterlace.c | 38 ++++++++++++++----- .../amlogic/media/deinterlace/deinterlace.h | 1 + 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index b58ddd481343..ad47b79ccbe1 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -105,7 +105,7 @@ static int mpeg2vdin_en; #endif static int queue_print_flag = -1; -static int di_reg_unreg_cnt = 100; +static int di_reg_unreg_cnt = 1000; static bool overturn; static bool check_start_drop_prog; static bool mcpre_en = true; @@ -113,7 +113,7 @@ static bool mcpre_en = true; static bool mc_mem_alloc; static unsigned int di_pre_rdma_enable; - +static struct mutex di_event_mutex; static unsigned int di_force_bit_mode = 10; module_param(di_force_bit_mode, uint, 0664); @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-25va"; +static const char version_s[] = "2019-03-27a"; static int bypass_state = 1; static int bypass_all; @@ -617,6 +617,8 @@ store_dbg(struct device *dev, dump_afbcd_reg(); } else if (strncmp(buf, "dumpmif", 7) == 0) { dump_mif_size_state(&di_pre_stru, &di_post_stru); + } else if (strncmp(buf, "dumppostmif", 11) == 0) { + dump_post_mif_reg(); } else if (strncmp(buf, "recycle_buf", 11) == 0) { recycle_keep_buffer(); } else if (strncmp(buf, "recycle_post", 12) == 0) { @@ -648,6 +650,7 @@ store_dbg(struct device *dev, pr_info("\t pstep\n"); pr_info("\t dumpreg\n"); pr_info("\t dumpmif\n"); + pr_info("\t dumppostmif\n"); pr_info("\t recycle_buf\n"); pr_info("\t recycle_post\n"); pr_info("\t mem_map\n"); @@ -2135,7 +2138,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) canvas_align_width = 64; - + pr_info("di: %s -S\n", __func__); frame_count = 0; disp_frame_count = 0; cur_post_ready_di_buf = NULL; @@ -2383,6 +2386,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) nr_ds_buf_init(de_devp->flag_cma, nrds_mem, &(de_devp->pdev->dev)); } + pr_info("di: %s -E\n", __func__); return 0; } @@ -6258,6 +6262,7 @@ static void di_reg_process_irq(void) if (pre_run_flag == DI_RUN_FLAG_STEP) pre_run_flag = DI_RUN_FLAG_STEP_DONE; + di_pre_stru.reg_irq_busy = true; vframe = vf_peek(VFM_NAME); @@ -6269,6 +6274,7 @@ static void di_reg_process_irq(void) } di_pre_stru.bypass_flag = true; di_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); + di_pre_stru.reg_irq_busy = false; return; } else { di_pre_stru.bypass_flag = false; @@ -6357,6 +6363,8 @@ static void di_reg_process_irq(void) spin_unlock_irqrestore(&plist_lock, flags); #endif } + if (!reg_flag) + pr_err("di: warning unreg in reg irq\n"); calc_lmv_init(); first_field_type = (vframe->type & VIDTYPE_TYPEMASK); @@ -6381,6 +6389,7 @@ static void di_reg_process_irq(void) init_flag = 1; di_pre_stru.reg_req_flag_irq = 1; } + di_pre_stru.reg_irq_busy = false; } static void di_process(void) @@ -6672,6 +6681,7 @@ static int di_receiver_event_fun(int type, void *data, void *arg) if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) { return di_pre_stru.vdin2nr; } else if (type == VFRAME_EVENT_PROVIDER_UNREG) { + mutex_lock(&di_event_mutex); pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n", __func__, is_bypass(NULL), trick_mode, bypass_all); di_pre_stru.vdin_source = false; @@ -6682,8 +6692,9 @@ static int di_receiver_event_fun(int type, void *data, void *arg) di_pre_stru.vdin_source = false; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); di_pre_stru.unreg_req_flag_cnt = 0; - while (di_pre_stru.unreg_req_flag) { - usleep_range(10000, 10001); + while (di_pre_stru.unreg_req_flag || + di_pre_stru.reg_irq_busy) { + usleep_range(1000, 1001); if (di_pre_stru.unreg_req_flag_cnt++ > di_reg_unreg_cnt) { reg_unreg_timeout_cnt++; @@ -6710,6 +6721,7 @@ static int di_receiver_event_fun(int type, void *data, void *arg) if (di_pre_stru.vdin_source) DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); #endif + mutex_unlock(&di_event_mutex); pr_info("DI: unreg f\n"); } else if (type == VFRAME_EVENT_PROVIDER_RESET) { di_blocking = 1; @@ -6872,12 +6884,16 @@ light_unreg: #endif } else if (type == VFRAME_EVENT_PROVIDER_REG) { char *receiver_name = NULL; + + mutex_lock(&di_event_mutex); if (de_devp->flags & DI_SUSPEND_FLAG) { pr_err("[DI] reg event device hasn't resumed\n"); + mutex_unlock(&di_event_mutex); return -1; } if (reg_flag) { pr_err("[DI] no muti instance.\n"); + mutex_unlock(&di_event_mutex); return -1; } pr_info("%s: vframe provider reg %s\n", __func__, @@ -6889,7 +6905,7 @@ light_unreg: /*check unreg process*/ di_pre_stru.reg_req_flag_cnt = 0; while (di_pre_stru.reg_req_flag) { - usleep_range(10000, 10001); + usleep_range(1000, 1001); if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { reg_unreg_timeout_cnt++; pr_dbg("%s:reg_req_flag timeout!!!\n", @@ -6917,6 +6933,7 @@ light_unreg: } else { pr_info("%s error receiver is null.\n", __func__); } + mutex_unlock(&di_event_mutex); pr_info("DI: reg f\n"); } #ifdef DET3D @@ -6936,7 +6953,7 @@ light_unreg: return 0; } - +#if 0 static void fast_process(void) { int i; @@ -6993,7 +7010,7 @@ static void fast_process(void) } } } - +#endif static vframe_t *di_vf_peek(void *arg) { vframe_t *vframe_ret = NULL; @@ -7011,7 +7028,7 @@ static vframe_t *di_vf_peek(void *arg) log_buffer_state("pek"); - fast_process(); + /*fast_process();*/ #ifdef SUPPORT_START_FRAME_HOLD if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) { int ready_count = list_count(QUEUE_POST_READY); @@ -7791,6 +7808,7 @@ static int di_probe(struct platform_device *pdev) device_create_file(di_devp->dev, &dev_attr_tvp_region); pd_device_files_add(di_devp->dev); nr_drv_init(di_devp->dev); + mutex_init(&di_event_mutex); init_flag = 0; reg_flag = 0; diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index c594d61a0b9f..333a7cae8325 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -299,6 +299,7 @@ struct di_pre_stru_s { int reg_req_flag; int reg_req_flag_irq; int reg_req_flag_cnt; + int reg_irq_busy; int force_unreg_req_flag; int disable_req_flag; /* current source info */ From f0f35b4b77ecb14c0d186e03a4147e0c8ce2abf5 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Thu, 4 Apr 2019 16:16:58 +0800 Subject: [PATCH 0658/1060] di: change clkb frq from 500 to 667 [1/1] PD#SWPL-6762 Problem: di clkb frq is not right Solution: change from 500 to 667 Verify: tl1 Change-Id: I9c62bb9936630937f19d8a6b490a8266d73a268c Signed-off-by: Yong Qin --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++++-- arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts | 6 ++++-- arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts | 6 ++++-- arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++++-- arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts | 6 ++++-- arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts | 6 ++++-- drivers/amlogic/media/deinterlace/deinterlace.c | 14 +++++++++++++- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 8804f2322a20..d06066405695 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -201,9 +201,11 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; + "vpu_clkb_composite", + "vpu_mux"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts index 44d93df9490e..a6112b2d1208 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -223,9 +223,11 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; + "vpu_clkb_composite", + "vpu_mux"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts index b024f19337ea..150fcd11af7f 100644 --- a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -220,9 +220,11 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; + "vpu_clkb_composite", + "vpu_mux"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts index 0c8977295e6e..5d167bdcb22b 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -214,9 +214,11 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; + "vpu_clkb_composite", + "vpu_mux"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts index 93566583937c..b084bd913b91 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -220,9 +220,11 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; + "vpu_clkb_composite", + "vpu_mux"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts index 17b68c35d97e..1361015cae0b 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts @@ -214,9 +214,11 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>; + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite"; + "vpu_clkb_composite", + "vpu_mux"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index ad47b79ccbe1..89ecdfb0da27 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -7652,6 +7652,7 @@ static void di_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev) int ret = 0; unsigned int tmp_clk[2] = {0, 0}; struct clk *vpu_clk = NULL; + struct clk *clkb_tmp_comp = NULL; vpu_clk = clk_get(dev, "vpu_mux"); if (IS_ERR(vpu_clk)) @@ -7672,9 +7673,20 @@ static void di_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev) pdev->clkb_max_rate); #ifdef CLK_TREE_SUPPORT pdev->vpu_clkb = clk_get(dev, "vpu_clkb_composite"); + clkb_tmp_comp = clk_get(dev, "vpu_clkb_tmp_composite"); + if (IS_ERR(clkb_tmp_comp)) + pr_err("clkb_tmp_comp error\n"); + else { + if (!IS_ERR(vpu_clk)) + clk_set_parent(clkb_tmp_comp, vpu_clk); + } + if (IS_ERR(pdev->vpu_clkb)) pr_err("%s: get vpu clkb gate error.\n", __func__); - clk_set_rate(pdev->vpu_clkb, pdev->clkb_min_rate); + else { + clk_set_rate(pdev->vpu_clkb, pdev->clkb_min_rate); + pr_info("get clkb rate:%ld\n", clk_get_rate(pdev->vpu_clkb)); + } #endif } From d5edafddec69e5540b593d9ec47e52506a98d461 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 1 Apr 2019 14:56:44 +0800 Subject: [PATCH 0659/1060] di: bringup for tm2 [1/1] PD#SWPL-6575 Problem: chip bring up Solution: 1.add tm2 chip id for tm2 2.add h scaling down function for tm2 Verify: tm2 Change-Id: I364d7c07be331d81ef546357445225c6071f8e3c Signed-off-by: Yong Qin Conflicts: drivers/amlogic/media/deinterlace/deinterlace.c drivers/amlogic/media/deinterlace/deinterlace_dbg.c drivers/amlogic/media/deinterlace/deinterlace_hw.c drivers/amlogic/media/deinterlace/nr_drv.c --- .../amlogic/media/deinterlace/deinterlace.c | 56 ++++++++++++++--- .../amlogic/media/deinterlace/deinterlace.h | 1 + .../media/deinterlace/deinterlace_dbg.c | 3 +- .../media/deinterlace/deinterlace_hw.c | 23 +++---- .../media/deinterlace/deinterlace_mtn.c | 2 +- drivers/amlogic/media/deinterlace/di_pps.c | 62 ++++++++++++++++++- drivers/amlogic/media/deinterlace/di_pps.h | 9 +++ drivers/amlogic/media/deinterlace/nr_drv.c | 39 +++++------- drivers/amlogic/media/deinterlace/register.h | 9 +++ 9 files changed, 158 insertions(+), 46 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 89ecdfb0da27..958264921114 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-03-27a"; +static const char version_s[] = "2019-0401:TM2 bring up"; static int bypass_state = 1; static int bypass_all; @@ -3482,6 +3482,11 @@ module_param_named(pps_position, pps_position, uint, 0644); static unsigned int pre_enable_mask = 3;/*bit0:ma bit1:mc*/ module_param_named(pre_enable_mask, pre_enable_mask, uint, 0644); +static bool pre_hsc_down_en; +module_param_named(pre_hsc_down_en, pre_hsc_down_en, bool, 0644); +static int pre_hsc_down_width = 480; +module_param_named(pre_hsc_down_width, pre_hsc_down_width, int, 0644); + static unsigned char pre_de_buf_config(void) { struct di_buf_s *di_buf = NULL; @@ -4026,7 +4031,15 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); } if (pps_dsth != di_buf->vframe->height) di_buf->vframe->height = pps_dsth; + } else if (de_devp->h_sc_down_en) { + if (pre_hsc_down_width != di_buf->vframe->width) { + pr_info("di: hscd %d to %d\n", di_buf->vframe->width, + pre_hsc_down_width); + di_buf->vframe->width = pre_hsc_down_width; + di_pre_stru.width_bk = pre_hsc_down_width; + } } + if (di_force_bit_mode == 10) { di_buf->vframe->bitdepth |= (BITDEPTH_Y10); if (full_422_pack) @@ -4782,6 +4795,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_end_y = zoom_end_y_lines; di_height = di_end_y - di_start_y + 1; di_height = di_height / (di_vscale_skip_count_real + 1); + /* make sure the height is even number */ if (di_height%2) di_height++; @@ -5248,7 +5262,9 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) { + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { di_post_read_reverse_irq(overturn, mc_pre_flag, post_blend_en ? mcpre_en : false); /* disable mc for first 2 fieldes mv unreliable */ @@ -6039,7 +6055,8 @@ static void di_unreg_process_irq(void) di_hw_uninit(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { di_pre_gate_control(false, mcpre_en); nr_gate_control(false); } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { @@ -6052,7 +6069,8 @@ static void di_unreg_process_irq(void) di_hw_disable(mcpre_en); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { enable_di_post_mif(GATE_OFF); di_post_gate_control(false); di_top_gate_control(false, false); @@ -6165,7 +6183,8 @@ static void di_pre_size_change(unsigned short width, is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) film_mode_win_config(width, height); } if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) @@ -6197,6 +6216,15 @@ static void di_pre_size_change(unsigned short width, pps_h = di_pre_stru.cur_height>>1; di_pps_config(1, pps_w, pps_h, pps_dstw, (pps_dsth>>1)); } + + if (de_devp->h_sc_down_en) { + pps_w = di_pre_stru.cur_width; + di_inp_hsc_setting(pps_w, pre_hsc_down_width); + } else { + di_inp_hsc_setting(di_pre_stru.cur_width, + di_pre_stru.cur_width); + } + di_interrupt_ctrl(di_pre_stru.madi_enable, det3d_en?1:0, de_devp->nrds_enable, @@ -6295,6 +6323,8 @@ static void di_reg_process_irq(void) } de_devp->nrds_enable = nrds_en; de_devp->pps_enable = pps_en; + /*di pre h scaling down: sm1 tm2*/ + de_devp->h_sc_down_en = pre_hsc_down_en; switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); if (post_wr_en && post_wr_support) diwr_set_power_control(1); @@ -6613,7 +6643,8 @@ static int di_task_handle(void *data) } } if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + || is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, de_devp->clkb_max_rate); @@ -7573,7 +7604,8 @@ static void set_di_flag(void) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) { + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { mcpre_en = true; mc_mem_alloc = true; pulldown_enable = false; @@ -7591,7 +7623,8 @@ static void set_di_flag(void) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) { + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { full_422_pack = true; } @@ -7603,7 +7636,8 @@ static void set_di_flag(void) } post_hold_line = (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu())?10:17; + || is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu())?10:17; } else { post_hold_line = 8; /*2019-01-10: from VLSI feijun*/ mcpre_en = false; @@ -7613,7 +7647,7 @@ static void set_di_flag(void) use_2_interlace_buff = 0; di_force_bit_mode = 8; } - if (is_meson_tl1_cpu()) + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) pulldown_enable = true; if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) intr_mode = 3; @@ -7731,6 +7765,8 @@ static int di_probe(struct platform_device *pdev) "nrds-enable", &(di_devp->nrds_enable)); ret = of_property_read_u32(pdev->dev.of_node, "pps-enable", &(di_devp->pps_enable)); + /*di pre h scaling down :sm1 tm2*/ + di_devp->h_sc_down_en = pre_hsc_down_en; if (di_devp->flag_cma >= 1) { #ifdef CONFIG_CMA diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 333a7cae8325..9b9ad1f610ad 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -247,6 +247,7 @@ struct di_dev_s { unsigned int post_wr_support; unsigned int nrds_enable; unsigned int pps_enable; + u32 h_sc_down_en;/*sm1, tm2 ...*/ /*struct mutex cma_mutex;*/ unsigned int flag_cma; struct page *total_pages; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index 0a3094c293eb..2a844dcc350a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -255,7 +255,8 @@ void dump_di_reg_g12(void) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) base_addr = 0xff900000; else base_addr = 0xd0100000; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 69736cb628f9..231332c3db91 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -467,7 +467,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) di_top_gate_control(true, true); else if (is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_gxlx_cpu()) @@ -480,8 +481,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || - is_meson_tl1_cpu()) { + is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu()) { /* vpp fifo max size on txl :128*3=384[0x180] */ /* di fifo max size on txl :96*3=288[0x120] */ fifo_size_vpp = 0x180; @@ -516,8 +517,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || - is_meson_tl1_cpu()) { + is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu()) { di_pre_gate_control(true, true); di_post_gate_control(true); } @@ -536,7 +537,7 @@ void di_hw_init(bool pd_enable, bool mc_enable) is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) { + is_meson_tl1_cpu() || is_meson_tm2_cpu()) { di_pre_gate_control(false, true); di_post_gate_control(false); di_top_gate_control(false, false); @@ -878,7 +879,7 @@ static enum eAFBC_DEC afbc_get_decnub(void) sel_dec = eAFBC_DEC1; else if (is_meson_g12a_cpu()) sel_dec = eAFBC_DEC1; - else if (is_meson_tl1_cpu()) + else if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) sel_dec = eAFBC_DEC0; return sel_dec; } @@ -900,7 +901,7 @@ bool afbc_is_supported(void) ret = false; else if (is_meson_g12a_cpu()) ret = false; - else if (is_meson_tl1_cpu()) + else if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) ret = true; return ret; @@ -1065,7 +1066,7 @@ u32 enable_afbc_input(struct vframe_s *vf) /* TL1 add bit[13:12]: fmt_mode; 0:yuv444; 1:yuv422; 2:yuv420 * di does not support yuv444, so for fmt yuv444 di will bypass+ */ - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { if (vf->type & VIDTYPE_VIU_444) r |= (0 << 12); else if (vf->type & VIDTYPE_VIU_422) @@ -1185,13 +1186,13 @@ static void afbcx_sw(bool on) /*g12a*/ /*RDMA_WR(reg_en, 0x1600);*/ RDMA_WR_BITS(VIUB_MISC_CTRL0, 1, 16, 1); /*TL1 add mem control bit */ - if (is_meson_tl1_cpu()) + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 1, 22, 1); } else { RDMA_WR(reg_ctrl, tmp); RDMA_WR(reg_en, 0x1600); RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); - if (is_meson_tl1_cpu()) + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 0, 22, 1); } } diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index ec80205bac43..43957cd403f9 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -297,7 +297,7 @@ struct combing_status_s *adpative_combing_config(unsigned int width, } void mtn_int_combing_glbmot(void) { - if (is_meson_tl1_cpu()) {/*from VLSI yanling.liu*/ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) {/*from VLSI yanling.liu*/ combing_glbmot_radprat[0] = 30; } } diff --git a/drivers/amlogic/media/deinterlace/di_pps.c b/drivers/amlogic/media/deinterlace/di_pps.c index 750be0179d03..302555429af8 100644 --- a/drivers/amlogic/media/deinterlace/di_pps.c +++ b/drivers/amlogic/media/deinterlace/di_pps.c @@ -388,10 +388,12 @@ static void f2v_get_vertical_phase(unsigned int zoom_ratio, vphase->phase = (offset_out - offset_in) >> 2; } } + /* * patch 1: inp scaler 0: di wr scaler + * support: TM2 + * not support: SM1 */ - void di_pps_config(unsigned char path, int src_w, int src_h, int dst_w, int dst_h) { @@ -1325,3 +1327,61 @@ RESTART: } #endif +/* + * di pre h scaling down function + * only have h scaling down + * support: sm1 tm2 ... + * 0x37b0 ~ 0x37b5 + */ +void di_inp_hsc_setting(uint32_t src_w, uint32_t dst_w) +{ + uint32_t i; + uint32_t hsc_en; + uint32_t horz_phase_step; + int *filt_coef0 = di_filt_coef0; + /*int *filt_coef1 = di_filt_coef1;*/ + /*int *filt_coef2 = di_filt_coef2;*/ + + if (src_w == dst_w) { + hsc_en = 0; + } else { + hsc_en = 1; + /*write horz filter coefs*/ + RDMA_WR(DI_VIU_HSC_COEF_IDX, 0x0100); + for (i = 0; i < 33; i++) + RDMA_WR(DI_VIU_HSC_COEF, filt_coef0[i]); /*bicubic*/ + + horz_phase_step = (src_w << 20) / dst_w; + horz_phase_step = (horz_phase_step << 4); + RDMA_WR(DI_VIU_HSC_WIDTHM1, (src_w-1)<<16 | (dst_w-1)); + RDMA_WR(DI_VIU_HSC_PHASE_STEP, horz_phase_step); + RDMA_WR(DI_VIU_HSC_PHASE_CTRL, 0); + } + RDMA_WR(DI_VIU_HSC_CTRL, + (4 << 20) | /* initial receive number*/ + (0 << 12) | /* initial pixel ptr*/ + (1 << 10) | /* repeat first pixel number*/ + (0 << 8) | /* sp422 mode*/ + (4 << 4) | /* horz scaler bank length*/ + (0 << 2) | /* phase0 always en*/ + (0 << 1) | /* nearest_en*/ + (hsc_en<<0)); /* hsc_en*/ +} + +/* + * 0x37b0 ~ 0x37b5 + */ +void dump_hdownscler_reg(unsigned int base_addr) +{ + unsigned int i = 0x374e; + + pr_info("-----dump hdownscler start-----\n"); + for (i = 0x37b0; i < 0x37b5; i++) { + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, RDMA_RD(i)); + } + pr_info("-----dump hdownscler end-----\n"); +} + + diff --git a/drivers/amlogic/media/deinterlace/di_pps.h b/drivers/amlogic/media/deinterlace/di_pps.h index 9ec789eb3b8e..a607364651f3 100644 --- a/drivers/amlogic/media/deinterlace/di_pps.h +++ b/drivers/amlogic/media/deinterlace/di_pps.h @@ -54,6 +54,12 @@ enum f2v_vphase_type_e { F2V_TYPE_MAX }; /* frame to video conversion type */ #endif + +enum hdr2_scaler_e { + hdr2_scaler_postdi = 0, + hdr2_scaler_predi = 1, +}; + struct pps_f2v_vphase_s { unsigned char rcv_num; unsigned char rpt_num; @@ -99,4 +105,7 @@ struct pps_frame_par_s { void di_pps_config(unsigned char path, int src_w, int src_h, int dst_w, int dst_h); void dump_pps_reg(unsigned int base_addr); +void di_inp_hsc_setting(uint32_t src_w, uint32_t dst_w); +void dump_hdownscler_reg(unsigned int base_addr); + #endif diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index 5d41ea73a702..76a1ba248e08 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -280,7 +280,7 @@ static void dnr_config(struct DNR_PARM_s *dnr_parm_p, DI_Wr(DNR_DM_CTRL, Rd(DNR_DM_CTRL)|(1 << 11)); DI_Wr_reg_bits(DNR_CTRL, dnr_en?1:0, 16, 1); /* dm for sd, hd will slower */ - if (is_meson_tl1_cpu()) + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) DI_Wr(DNR_CTRL, 0x1df00 | (0x03 << 18)); //5 line else DI_Wr(DNR_CTRL, 0x1df00); @@ -356,7 +356,8 @@ static void linebuffer_config(unsigned short width) static void nr2_config(unsigned short width, unsigned short height) { if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) { DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 2, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 15, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 17, 1); @@ -405,7 +406,8 @@ void nr_all_config(unsigned short width, unsigned short height, if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) cue_config(nr_param.pcue_parm, field_type); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) { linebuffer_config(width); nr4_config(nr_param.pnr4_parm, width, height); } @@ -597,7 +599,7 @@ static void dnr_process(struct DNR_PARM_s *pDnrPrm) #endif int ll, lr; - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { ll = Rd(DNR_RO_GBS_STAT_LR); lr = Rd(DNR_RO_GBS_STAT_LL); } else { @@ -745,7 +747,7 @@ void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff) struct CUE_PARM_s *pcue_parm = nr_param.pcue_parm; unsigned int mask1, mask2; - if (is_meson_tl1_cpu()) { + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { /*value from VLSI(yanling.liu) 2018-12-07: */ mask1 = 0x50332; mask2 = 0x00054357; @@ -837,7 +839,8 @@ void nr_process_in_irq(void) if (dnr_en) dnr_process(&dnr_param); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() - || is_meson_g12a_cpu() || is_meson_tl1_cpu()) { + || is_meson_g12a_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) { noise_meter_process(nr_param.pnr4_parm, nr_param.frame_count); luma_enhancement_process(nr_param.pnr4_parm, nr_param.frame_count); @@ -1074,19 +1077,11 @@ static void nr4_param_init(struct NR4_PARM_s *nr4_parm_p) nr4_parm_p->sw_nr4_sad2gain_lut[14] = 14; nr4_parm_p->sw_nr4_sad2gain_lut[15] = 9; - if (is_meson_tl1_cpu()) { - nr4_parm_p->sw_nr4_noise_thd = 32; - nr4_parm_p->sw_nr4_noise_sel = 0; - nr4_parm_p->sw_nr4_noise_ctrl_dm_en = 0; - nr4_parm_p->sw_nr4_scene_change_thd2 = 80; - nr4_parm_p->sw_dm_scene_change_en = 0; - } else { - nr4_parm_p->sw_nr4_noise_thd = 32; - nr4_parm_p->sw_nr4_noise_sel = 0; - nr4_parm_p->sw_nr4_noise_ctrl_dm_en = 0; - nr4_parm_p->sw_nr4_scene_change_thd2 = 80; - nr4_parm_p->sw_dm_scene_change_en = 0; - } + nr4_parm_p->sw_nr4_noise_thd = 32; + nr4_parm_p->sw_nr4_noise_sel = 0; + nr4_parm_p->sw_nr4_noise_ctrl_dm_en = 0; + nr4_parm_p->sw_nr4_scene_change_thd2 = 80; + nr4_parm_p->sw_dm_scene_change_en = 0; } static void cue_param_init(struct CUE_PARM_s *cue_parm_p) @@ -1197,7 +1192,7 @@ void nr_hw_init(void) { nr_gate_control(true); - if (is_meson_tl1_cpu()) + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) DI_Wr(DNR_CTRL, 0x1df00|(0x03<<18));//5 line else DI_Wr(DNR_CTRL, 0x1df00); @@ -1213,8 +1208,8 @@ void nr_hw_init(void) void nr_gate_control(bool gate) { if (!is_meson_txlx_cpu() && !is_meson_g12a_cpu() - && !is_meson_g12b_cpu() - && !is_meson_tl1_cpu()) + && !is_meson_g12b_cpu() && !is_meson_sm1_cpu() + && !is_meson_tl1_cpu() && !is_meson_tm2_cpu()) return; if (gate) { /* enable nr auto gate */ diff --git a/drivers/amlogic/media/deinterlace/register.h b/drivers/amlogic/media/deinterlace/register.h index 5ce602d7f00c..5d8a36acb1de 100644 --- a/drivers/amlogic/media/deinterlace/register.h +++ b/drivers/amlogic/media/deinterlace/register.h @@ -212,6 +212,15 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, #define DI_HSC_INI_PAT_CTRL 0x376b #define DI_SC_GCLK_CTRL 0x376c #define DI_SC_HOLD_LINE 0x376d + +/* DI H DOWN SCALER */ +#define DI_VIU_HSC_WIDTHM1 0x37b0 +#define DI_VIU_HSC_PHASE_STEP 0x37b1 +#define DI_VIU_HSC_CTRL 0x37b2 +#define DI_VIU_HSC_PHASE_CTRL 0x37b3 +#define DI_VIU_HSC_COEF 0x37b4 +#define DI_VIU_HSC_COEF_IDX 0x37b5 + /* NR DOWNSAMPLE */ #define NRDSWR_X 0x37f9 #define NRDSWR_Y 0x37fa From f70db4be008cca262cb4e17a63e37687d9791cb8 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Thu, 11 Apr 2019 14:06:56 +0800 Subject: [PATCH 0660/1060] Revert "di: change clkb frq from 500 to 667 [1/1]" This reverts commit c75a783c4278f4b8c97dedadc72f44d49461dc4f. Change-Id: I2bf82f1ceeebc1377d45b76ee1d2563811c154ca Signed-off-by: Yong Qin --- arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++---- arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts | 6 ++---- arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++---- arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts | 6 ++---- arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts | 6 ++---- drivers/amlogic/media/deinterlace/deinterlace.c | 14 +------------- 6 files changed, 11 insertions(+), 33 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index d06066405695..8804f2322a20 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -201,11 +201,9 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>, - <&clkc CLKID_VPU_MUX>; + <&clkc CLKID_VPU_CLKB_COMP>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite", - "vpu_mux"; + "vpu_clkb_composite"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts index a6112b2d1208..44d93df9490e 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -223,11 +223,9 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>, - <&clkc CLKID_VPU_MUX>; + <&clkc CLKID_VPU_CLKB_COMP>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite", - "vpu_mux"; + "vpu_clkb_composite"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts index 5d167bdcb22b..0c8977295e6e 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -214,11 +214,9 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>, - <&clkc CLKID_VPU_MUX>; + <&clkc CLKID_VPU_CLKB_COMP>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite", - "vpu_mux"; + "vpu_clkb_composite"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts index b084bd913b91..93566583937c 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -220,11 +220,9 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>, - <&clkc CLKID_VPU_MUX>; + <&clkc CLKID_VPU_CLKB_COMP>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite", - "vpu_mux"; + "vpu_clkb_composite"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts index 1361015cae0b..17b68c35d97e 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts @@ -214,11 +214,9 @@ 0 40 1>; interrupt-names = "pre_irq", "post_irq"; clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, - <&clkc CLKID_VPU_CLKB_COMP>, - <&clkc CLKID_VPU_MUX>; + <&clkc CLKID_VPU_CLKB_COMP>; clock-names = "vpu_clkb_tmp_composite", - "vpu_clkb_composite", - "vpu_mux"; + "vpu_clkb_composite"; clock-range = <334 667>; /* buffer-size = <3621952>;(yuv422 8bit) */ buffer-size = <4074560>;/*yuv422 fullpack*/ diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 958264921114..e5c990112aba 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -7686,7 +7686,6 @@ static void di_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev) int ret = 0; unsigned int tmp_clk[2] = {0, 0}; struct clk *vpu_clk = NULL; - struct clk *clkb_tmp_comp = NULL; vpu_clk = clk_get(dev, "vpu_mux"); if (IS_ERR(vpu_clk)) @@ -7707,20 +7706,9 @@ static void di_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev) pdev->clkb_max_rate); #ifdef CLK_TREE_SUPPORT pdev->vpu_clkb = clk_get(dev, "vpu_clkb_composite"); - clkb_tmp_comp = clk_get(dev, "vpu_clkb_tmp_composite"); - if (IS_ERR(clkb_tmp_comp)) - pr_err("clkb_tmp_comp error\n"); - else { - if (!IS_ERR(vpu_clk)) - clk_set_parent(clkb_tmp_comp, vpu_clk); - } - if (IS_ERR(pdev->vpu_clkb)) pr_err("%s: get vpu clkb gate error.\n", __func__); - else { - clk_set_rate(pdev->vpu_clkb, pdev->clkb_min_rate); - pr_info("get clkb rate:%ld\n", clk_get_rate(pdev->vpu_clkb)); - } + clk_set_rate(pdev->vpu_clkb, pdev->clkb_min_rate); #endif } From 1257af5e204b1a7be8bacb48abe9325ebdfb0d0c Mon Sep 17 00:00:00 2001 From: Wenfeng Guo Date: Thu, 10 Jan 2019 16:19:58 +0800 Subject: [PATCH 0661/1060] deinterlace: fix tl1 in 1080i has small sawtooth [1/1] PD#SWPL-4072 Problem: tl1 1080i in some dark scenes and roller coasters have small sawtooth Solution: adjust a set of registers with special motion Verify: tl1 Change-Id: Idbe62e823f1c6c683b67d000978de1862c8e3162 Signed-off-by: Wenfeng Guo --- .../amlogic/media/deinterlace/deinterlace.c | 12 ++++++++++++ .../media/deinterlace/deinterlace_mtn.c | 18 ++++++++++++++++++ .../media/deinterlace/deinterlace_mtn.h | 1 + 3 files changed, 31 insertions(+) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index e5c990112aba..41a1c61665d4 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -3937,6 +3937,18 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); } } } else { + /*********************************/ + if ((di_buf->vframe->width >= 1920) && + (di_buf->vframe->height >= 1080) && + is_meson_tl1_cpu()) { + if (combing_fix_en) { + combing_fix_en = false; + fix_tl1_1080i_sawtooth_patch(); + } + } else + combing_fix_en = true; + + /*********************************/ if ( di_pre_stru.di_chan2_buf_dup_p == NULL) { di_pre_stru.field_count_for_cont = 0; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index 43957cd403f9..b9a3562fb430 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -629,6 +629,24 @@ static int di_debug_readreg; module_param(di_debug_readreg, int, 0644); MODULE_PARM_DESC(di_debug_readreg, "di_debug_readreg"); +/*from VLSI yanling.liu, the patch fix TL1 1080I in some dark */ +/*scenes and roller coasters have small sawtooth, when turn off*/ +/*combing_fix_en, set the registers*/ +void fix_tl1_1080i_sawtooth_patch(void) +{ + DI_Wr(0x1741, 0x0A0A1A22); + DI_Wr(0x1742, 0x0a100101); + DI_Wr(0x1743, 0x01020420); + DI_Wr(0x1744, 0x32210404); + DI_Wr(0x17a9, 0x0a100505); + DI_Wr(0x17aa, 0x04040101); + DI_Wr(0x17ab, 0x0a0a0a0a); + DI_Wr(0x17ac, 0x0f100101); + DI_Wr(0x17ad, 0x04040606); + DI_Wr(0x17ae, 0x02030202); + DI_Wr(0x17af, 0x60020a60); +} + int adaptive_combing_fixing( struct combing_status_s *cmb_status, unsigned int field_diff, diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h index 206d1c307543..13cc468c7e07 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h @@ -39,6 +39,7 @@ struct combing_status_s *adpative_combing_config(unsigned int width, unsigned int height, enum vframe_source_type_e src_type, bool prog, enum tvin_sig_fmt_e fmt); +extern void fix_tl1_1080i_sawtooth_patch(void); int adaptive_combing_fixing( struct combing_status_s *cmb_status, unsigned int field_diff, unsigned int frame_diff, From 7104d5ed925a60601af15bb512b552b6ba818151 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Fri, 19 Apr 2019 10:15:51 +0800 Subject: [PATCH 0662/1060] di: small window bottom of the screen is blank [1/1] PD#TV-4708 Problem: small window, bottom of the screen is covered by blank on the online video Solution: vline is odd, mif out is not right Verify: verify on TL1 Change-Id: I39eb0cdfd2f4b200a09a9c8b779f509caf6dea37 Signed-off-by: Yong Qin --- drivers/amlogic/media/deinterlace/deinterlace.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 41a1c61665d4..c532ec85d3e4 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-0401:TM2 bring up"; +static const char version_s[] = "2019-0419a:vscale_skip v is odd"; static int bypass_state = 1; static int bypass_all; @@ -4809,8 +4809,14 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_height = di_height / (di_vscale_skip_count_real + 1); /* make sure the height is even number */ - if (di_height%2) - di_height++; + if (di_height%2) { + /*for skip mode,post only half line-1*/ + if (((di_height > 150) && (di_height < 500)) && + di_vscale_skip_count_real) + di_height = di_height - 3; + else + di_height++; + } if (Rd(DI_POST_SIZE) != ((di_width - 1) | ((di_height - 1) << 16)) || di_post_stru.buf_type != di_buf->di_buf_dup_p[0]->type || From ebbc51cfa62b11012c04e47fa310a8ce3e838239 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Mon, 22 Apr 2019 20:18:23 +0800 Subject: [PATCH 0663/1060] di: small window bottom of the screen no video [1/1] PD#TV-4708 Problem: small window,v scaling mode, bottom of the screen is no video. Solution: vline is odd, mif out is not more enouth Verify: verify on TL1 Change-Id: I2ac35af3632e8b14df5c773b322d4b2d64b050ba Signed-off-by: Yong Qin --- drivers/amlogic/media/deinterlace/deinterlace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index c532ec85d3e4..7374b002873d 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2019-0419a:vscale_skip v is odd"; +static const char version_s[] = "2019-0422b:vscale_skip v is odd"; static int bypass_state = 1; static int bypass_all; @@ -4811,7 +4811,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, /* make sure the height is even number */ if (di_height%2) { /*for skip mode,post only half line-1*/ - if (((di_height > 150) && (di_height < 500)) && + if (((di_height > 150) && (di_height < 1080)) && di_vscale_skip_count_real) di_height = di_height - 3; else From 8c30037ad1593c0bbc7bb3fe1f261a175d94f79a Mon Sep 17 00:00:00 2001 From: Wenfeng Guo Date: Tue, 16 Apr 2019 16:06:37 +0800 Subject: [PATCH 0664/1060] di: fix TL1 cave video 1080i 60hz have drawing [1/1] PD#SWPL-7006 Problem: TL1 cave video 1080i 60hz have drawing. Solution: dark scenes don't into pulldown32 by vlsi yanling Verify: TL1 Signed Change-Id: Ib77c0f99940c416943baa9b9a8a02a059b274e5b Signed-off-by: Wenfeng Guo --- .../amlogic/media/deinterlace/deinterlace.c | 3 +- .../media/deinterlace/deinterlace_hw.c | 6 +++ .../media/deinterlace/deinterlace_hw.h | 13 ++++++ .../deinterlace/film_mode_fmw/film_fw1.c | 46 +++++++++++++++---- .../deinterlace/film_mode_fmw/film_vof_soft.h | 12 +++-- .../amlogic/media/deinterlace/pulldown_drv.c | 9 +++- .../amlogic/media/deinterlace/pulldown_drv.h | 2 +- 7 files changed, 76 insertions(+), 15 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 7374b002873d..777354bcb744 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -3172,7 +3172,8 @@ static void pre_de_done_buf_config(void) &glb_field_mot_num); if (pulldown_enable) pulldown_detection(&post_wr_buf->pd_config, - di_pre_stru.mtn_status, overturn); + di_pre_stru.mtn_status, overturn, + di_pre_stru.di_inp_buf->vframe); if (combing_fix_en) cur_lev = adaptive_combing_fixing( di_pre_stru.mtn_status, diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 231332c3db91..c0da406757a6 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -330,6 +330,11 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr) if (!lmv_lock_win_en) return; + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + pr_debug("%s: only support G12A and after chips.\n", __func__); + return; + } + //tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); if (mcinfo_vadr == NULL) { di_print("err:di_vmap failed\n"); @@ -992,6 +997,7 @@ void enable_afbc_input(struct vframe_s *vf) } #endif +#define AFBC_DEC_SEL (eAFBC_DEC1) u32 enable_afbc_input(struct vframe_s *vf) { diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index 130d8a72eda2..d85c8b3202ab 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -218,5 +218,18 @@ extern u8 *di_vmap(ulong addr, u32 size, bool *bflg); extern void di_unmap_phyaddr(u8 *vaddr); extern int di_print(const char *fmt, ...); +#define DI_MC_SW_OTHER (1<<0) +#define DI_MC_SW_REG (1<<1) +//#define DI_MC_SW_POST (1<<2) +#define DI_MC_SW_IC (1<<2) + +#define DI_MC_SW_ON_MASK (DI_MC_SW_REG | DI_MC_SW_OTHER | DI_MC_SW_IC) + +extern void di_patch_post_update_mc(void); +extern void di_patch_post_update_mc_sw(unsigned int cmd, bool on); + +extern void di_rst_protect(bool on); +extern void di_pre_nr_wr_done_sel(bool on); +extern void di_arb_sw(bool on); #endif diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c index 9fefa75f52c2..609d08bf59d1 100644 --- a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c @@ -17,7 +17,9 @@ #include #include +#include #include "film_vof_soft.h" +#include "../deinterlace.h" static int DIweavedetec(struct sFlmSftPar *pPar, int nDif01); @@ -68,6 +70,8 @@ UINT8 FlmVOFSftInt(struct sFlmSftPar *pPar) pPar->dif01rate = 20; pPar->flag_di01th = 0; pPar->numthd = 60; + pPar->flm32_dif02_gap_th = 7; + pPar->flm32_luma_th = 90; pPar->sF32Dif02M0 = 4096;/* mpeg-4096, cvbs-8192 */ pPar->sF32Dif02M1 = 4096; @@ -230,6 +234,7 @@ static int dif01_ratio = 10; module_param(dif01_ratio, int, 0644); MODULE_PARM_DESC(dif01_ratio, "dif01_ratio"); + int comsum; int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, @@ -239,7 +244,8 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, UINT32 glb_field_mot_num, unsigned int *combing_row_num, - unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse) + unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse, + struct vframe_s *vf) { static UINT32 DIF01[HISDIFNUM]; /* Last one is global */ static UINT32 DIF02[HISDIFNUM]; /* Last one is global */ @@ -374,7 +380,7 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, } /* --------------------------------------------------------- */ /* Film-Detection */ - nS1 = FlmDetSft(&pRDat, nDIF01, nDIF02, nT0, pPar); + nS1 = FlmDetSft(&pRDat, nDIF01, nDIF02, nT0, pPar, vf); nS0 = FlmModsDet(&pRDat, rROFldDif01[0], rROFrmDif02[0]); /* --------------------------------------------------------- */ @@ -601,12 +607,12 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, /* nDif02: Frame Difference */ /* WND: The index of Window */ int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, - int WND, struct sFlmSftPar *pPar) + int WND, struct sFlmSftPar *pPar, struct vframe_s *vf) { int nT0 = 0; /* 3-2 */ - Flm32DetSft(pRDat, nDif02, nDif01, pPar); + Flm32DetSft(pRDat, nDif02, nDif01, pPar, vf); /* Film2-2 Detection */ /* debug0304 */ @@ -619,7 +625,7 @@ int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, /* pFlm02[0:nLEN-1] : recursive, 0-2 dif */ /* pFlm01[0:nLEN-1] : recursive, 0-1 dif */ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, - int *nDif01, struct sFlmSftPar *pPar) + int *nDif01, struct sFlmSftPar *pPar, struct vframe_s *vf) { int sFrmDifAvgRat = pPar->sFrmDifAvgRat; /* 16; //0~32 */ /* The Large Decision should be: (large>average+LgDifThrd) */ @@ -627,7 +633,6 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int sF32StpWgt01 = pPar->sF32StpWgt01; /* 15; */ int sF32StpWgt02 = pPar->sF32StpWgt02; /* 15; */ int sF32DifLgRat = pPar->sF32DifLgRat; /* 16; Dif>Rat*Min-->Larger */ - /* int sF32DifSmRat = 16; //Dif*Rat Smaller */ UINT8 *pFlm02 = pRDat->pFrm32; @@ -661,6 +666,29 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int nFlgChk2 = 0; int nFlgChk3 = 0; /* for Mit32VHLine */ + int luma_avg = 0; + int flm32_dif02_gap = 0; + + int flm32_luma_th = pPar->flm32_luma_th; // APL th + int flm32_dif02_gap_th = pPar->flm32_dif02_gap_th; + + /* ============================================= */ + /*patch for dark scenes don't into pulldown32 by vlsi yanling*/ + if (vf == NULL || !IS_VDIN_SRC(vf->source_type)) + luma_avg = flm32_luma_th; + else { + if (vf->prop.hist.pixel_sum > 0) + luma_avg = vf->prop.hist.luma_sum / + vf->prop.hist.pixel_sum; + else + luma_avg = flm32_luma_th; + } + if (luma_avg < flm32_luma_th) + flm32_dif02_gap = flm32_dif02_gap_th * 2; + else + flm32_dif02_gap = flm32_dif02_gap_th; + /*---------------------------------*/ + prt_flg = ((pr_pd >> 2) & 0x1); if (prt_flg) sprintf(debug_str, "#Dbg32:\n"); @@ -759,7 +787,6 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, nFlgChk1 = 0; nFlgChk2 = 0; } - /* ============================================= */ nT2 = 5 * nDif02[HISDIFNUM - 1] / (nMn + sFrmDifLgTDif + 1); nT2 = nT2>>1; @@ -779,7 +806,10 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, if (nSTP > 16) nSTP = 16; - + /*patch for dark scenes don't into pulldown32 by vlsi yanling*/ + if (((nMx + nMn/2) / (nMn + 1)) < flm32_dif02_gap) + nSTP = 0; + /*---------------*/ for (nT0 = 1; nT0 < HISDETNUM; nT0++) { pFlm02[nT0 - 1] = pFlm02[nT0]; pFlm02t[nT0 - 1] = pFlm02t[nT0]; diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h index d5c2d4802772..0fa9ac8fcee8 100644 --- a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h @@ -18,6 +18,8 @@ #ifndef _FLMVOFSFT_H_ #define _FLMVOFSFT_H_ #include +#include + /* Film Detection and VOF detection Software implementation */ /* Designer: Xin.Hu@amlogic.com */ /* Date: 12/06/13 */ @@ -129,6 +131,9 @@ struct sFlmSftPar { int flag_di01th; int numthd; + int flm32_dif02_gap_th; + int flm32_luma_th; + UINT32 sF32Dif02M0; /* mpeg-4096, cvbs-8192 */ UINT32 sF32Dif02M1; /* mpeg-4096, cvbs-8192 */ unsigned int field_count; @@ -163,7 +168,8 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, UINT32 glb_field_mot_num, unsigned int *cmb_row_num, - unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse); + unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse, + struct vframe_s *vf); /* length of pFlm01/nDif01: [0:5]; */ /* iDx: index of minimum dif02 ([0:5] */ @@ -174,7 +180,7 @@ int Cal32Flm01(UINT8 *pFlm01, int *nDif01, int iDx, struct sFlmSftPar *pPar); /* nDif02: Frame Difference */ /* WND: The index of Window */ int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, int WND, - struct sFlmSftPar *pPar); + struct sFlmSftPar *pPar, struct vframe_s *vf); int VOFDetSub1(int *PREWV, int *nCNum, int nMod, UINT32 *nRCmb, int nROW, struct sFlmSftPar *pPar); @@ -186,7 +192,7 @@ int VOFDetSft(int *VOFWnd, int *nCNum, int *nGCmb, /* */ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int *nDif01, - struct sFlmSftPar *pPar); + struct sFlmSftPar *pPar, struct vframe_s *vf); /* Film2-2 Detection */ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, diff --git a/drivers/amlogic/media/deinterlace/pulldown_drv.c b/drivers/amlogic/media/deinterlace/pulldown_drv.c index 94544a2f16be..7ab71aaed144 100644 --- a/drivers/amlogic/media/deinterlace/pulldown_drv.c +++ b/drivers/amlogic/media/deinterlace/pulldown_drv.c @@ -112,7 +112,7 @@ module_param(cmb_3point_rrat, uint, 0644); MODULE_PARM_DESC(cmb_3point_rrat, "cmb_3point_rrat/n"); unsigned int pulldown_detection(struct pulldown_detected_s *res, - struct combing_status_s *cmb_sts, bool reverse) + struct combing_status_s *cmb_sts, bool reverse, struct vframe_s *vf) { unsigned int glb_frame_mot_num, glb_field_mot_num, i; unsigned int mot_row = 0, mot_max = 0, ntmp = 0; @@ -142,7 +142,8 @@ unsigned int pulldown_detection(struct pulldown_detected_s *res, &cmb_sts->cmb_row_num, &cmb_sts->frame_diff_avg, &pd_param, - reverse); + reverse, + vf); difflag = dectres.dif01flag; if (dectres.rFlmPstMod == 1) @@ -411,6 +412,10 @@ static struct pd_param_s pd_params[] = { &(pd_param.flag_di01th) }, { "numthd", &(pd_param.numthd) }, + { "flm32_dif02_gap_th", + &(pd_param.flm32_dif02_gap_th) }, + { "flm32_luma_th", + &(pd_param.flm32_luma_th) }, { "sF32Dif02M0", &(pd_param.sF32Dif02M0) }, /* mpeg-4096, cvbs-8192 */ { "sF32Dif02M1", diff --git a/drivers/amlogic/media/deinterlace/pulldown_drv.h b/drivers/amlogic/media/deinterlace/pulldown_drv.h index 912119bc78f8..e670f0f5db36 100644 --- a/drivers/amlogic/media/deinterlace/pulldown_drv.h +++ b/drivers/amlogic/media/deinterlace/pulldown_drv.h @@ -46,7 +46,7 @@ struct pulldown_detected_s { unsigned char pulldown_init(unsigned short width, unsigned short height); unsigned int pulldown_detection(struct pulldown_detected_s *res, - struct combing_status_s *cmb_sts, bool reverse); + struct combing_status_s *cmb_sts, bool reverse, struct vframe_s *vf); void pulldown_vof_win_vshift(struct pulldown_detected_s *wins, unsigned short v_offset); From ff66238b3e4f6dd70b0d2b6d921c3095924b1c0f Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Fri, 17 May 2019 17:28:49 +0900 Subject: [PATCH 0665/1060] ODROID-N2:Merge amlogic BSP 2019.0415 Change-Id: I0eab66ee8951fe297a7c831f6b90652314a4972a --- .../boot/dts/amlogic/meson64_odroidn2.dts | 23 ++++++++++++------- .../dts/amlogic/mesong12_odroid_common.dtsi | 7 ------ arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi | 21 +++++++++++++++++ 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts index dce418715d71..554d0d882cf7 100644 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts +++ b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts @@ -17,7 +17,7 @@ /dts-v1/; -#include "mesong12b.dtsi" +#include "mesong12b_a.dtsi" #include "mesong12_odroid_common.dtsi" / { @@ -39,8 +39,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -49,6 +48,7 @@ size = <0x0 0x400000>; alignment = <0x0 0x400000>; alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; }; secos_reserved:linux,secos { @@ -95,11 +95,6 @@ size = <0x0 0x02800000>; alignment = <0x0 0x400000>; }; - /* POST PROCESS MANAGER */ - ppmgr_reserved:linux,ppmgr { - compatible = "shared-dma-pool"; - size = <0x0 0x0>; - }; codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -107,6 +102,7 @@ size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; + clear-map; }; /* codec shared reserved */ codec_mm_reserved:linux,codec_mm_reserved { @@ -133,6 +129,17 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; cvbsout { diff --git a/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi b/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi index f6ff8991ad8d..b004a8e5e871 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi @@ -46,13 +46,6 @@ status = "okay"; }; - ppmgr { - compatible = "amlogic, ppmgr"; - memory-region = <&ppmgr_reserved>; - dev_name = "ppmgr"; - status = "okay"; - }; - ionvideo { compatible = "amlogic, ionvideo"; dev_name = "ionvideo"; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index cc0941f5b5c8..e3772a416528 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -688,6 +688,16 @@ status = "disabled"; }; + spifc: spifc@14000 { + status = "disabled"; + compatible = "amlogic,aml-spi-nor"; + reg = <0x0 0x14000 0x0 0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&spifc_all_pins>; + clocks = <&clkc CLKID_CLK81>; + clock-names = "core"; + }; + spicc1: spi@15000 { compatible = "amlogic,meson-g12b-spicc", "amlogic,meson-g12a-spicc"; @@ -2438,6 +2448,17 @@ }; }; + spifc_all_pins: spifc_all_pins { + mux { + groups = "nor_d", + "nor_q", + "nor_c"; + function = "nor"; + input-enable; + bias-pull-up; + }; + }; + spicc1_pins: spicc1_pins { mux { groups = "spi1_mosi", From 0f1ea98bbeb58c01d57be29b160b2460485edf94 Mon Sep 17 00:00:00 2001 From: afl1 Date: Wed, 29 May 2019 12:24:18 +0200 Subject: [PATCH 0666/1060] Revert "ODROID-COMMON: slipstream Amlogic drivers" This reverts commit 5ef121eb61cd925cb56f7811d481fe7c91686ccb. --- drivers/amlogic/media_modules/Makefile | 5 - .../media_modules/amvdec_ports/Makefile | 11 - .../amvdec_ports/aml_vcodec_adapt.c | 720 - .../amvdec_ports/aml_vcodec_adapt.h | 65 - .../amvdec_ports/aml_vcodec_dec.c | 1837 --- .../amvdec_ports/aml_vcodec_dec.h | 109 - .../amvdec_ports/aml_vcodec_dec_drv.c | 345 - .../amvdec_ports/aml_vcodec_dec_pm.c | 206 - .../amvdec_ports/aml_vcodec_dec_pm.h | 34 - .../amvdec_ports/aml_vcodec_drv.h | 428 - .../amvdec_ports/aml_vcodec_util.c | 122 - .../amvdec_ports/aml_vcodec_util.h | 94 - .../amvdec_ports/aml_vcodec_vfm.c | 205 - .../amvdec_ports/aml_vcodec_vfm.h | 57 - .../amvdec_ports/aml_vcodec_vfq.h | 112 - .../amvdec_ports/decoder/h264_parse.c | 389 - .../amvdec_ports/decoder/h264_parse.h | 141 - .../amvdec_ports/decoder/h264_stream.c | 111 - .../amvdec_ports/decoder/h264_stream.h | 39 - .../amvdec_ports/decoder/utils.h | 31 - .../amvdec_ports/decoder/vdec_h264_if.c | 736 - .../amvdec_ports/test/Android.mk | 23 - .../amvdec_ports/test/vcodec_m2m_test.c | 292 - .../amvdec_ports/vdec_drv_base.h | 64 - .../media_modules/amvdec_ports/vdec_drv_if.c | 138 - .../media_modules/amvdec_ports/vdec_drv_if.h | 110 - drivers/amlogic/media_modules/common/Makefile | 2 - .../media_modules/common/chips/chips.c | 187 - .../media_modules/common/chips/chips.h | 40 - .../common/chips/decoder_cpu_ver_info.c | 161 - .../common/chips/decoder_cpu_ver_info.h | 55 - .../media_modules/common/firmware/Makefile | 3 - .../common/firmware/firmware_cfg.h | 32 - .../common/firmware/firmware_drv.c | 936 -- .../common/firmware/firmware_priv.h | 118 - .../common/firmware/firmware_type.c | 119 - .../common/firmware/firmware_type.h | 95 - .../media_modules/common/media_clock/Makefile | 6 - .../common/media_clock/clk/clk.c | 456 - .../common/media_clock/clk/clk.h | 172 - .../common/media_clock/clk/clk_priv.h | 38 - .../common/media_clock/clk/clkg12.c | 1037 -- .../common/media_clock/switch/amports_gate.c | 201 - .../common/media_clock/switch/amports_gate.h | 32 - .../media_modules/frame_provider/Makefile | 1 - .../frame_provider/decoder/Makefile | 12 - .../frame_provider/decoder/avs/Makefile | 2 - .../frame_provider/decoder/avs/avs.c | 1944 --- .../frame_provider/decoder/avs/avs.h | 91 - .../frame_provider/decoder/avs/avsp_trans.c | 5065 ------ .../frame_provider/decoder/avs2/Makefile | 2 - .../frame_provider/decoder/avs2/avs2_bufmgr.c | 2203 --- .../frame_provider/decoder/avs2/avs2_global.h | 1681 -- .../frame_provider/decoder/avs2/vavs2.c | 7786 ---------- .../frame_provider/decoder/avs2/vavs2.h | 26 - .../frame_provider/decoder/h264/Makefile | 6 - .../frame_provider/decoder/h264/vh264.c | 4461 ------ .../frame_provider/decoder/h264/vh264.h | 27 - .../frame_provider/decoder/h264/vh264_4k2k.c | 1809 --- .../frame_provider/decoder/h264/vh264_mvc.c | 1732 --- .../decoder/h264_multi/Makefile | 2 - .../decoder/h264_multi/h264_dpb.c | 5907 ------- .../decoder/h264_multi/h264_dpb.h | 952 -- .../decoder/h264_multi/vmh264.c | 9030 ----------- .../frame_provider/decoder/h265/Makefile | 2 - .../frame_provider/decoder/h265/vh265.c | 12740 ---------------- .../frame_provider/decoder/h265/vh265.h | 27 - .../frame_provider/decoder/mjpeg/Makefile | 5 - .../frame_provider/decoder/mjpeg/vmjpeg.c | 969 -- .../decoder/mjpeg/vmjpeg_multi.c | 1292 -- .../frame_provider/decoder/mpeg12/Makefile | 5 - .../frame_provider/decoder/mpeg12/vmpeg12.c | 2223 --- .../frame_provider/decoder/mpeg12/vmpeg12.h | 26 - .../decoder/mpeg12/vmpeg12_multi.c | 2854 ---- .../frame_provider/decoder/mpeg4/Makefile | 5 - .../frame_provider/decoder/mpeg4/vmpeg4.c | 1270 -- .../frame_provider/decoder/mpeg4/vmpeg4.h | 26 - .../decoder/mpeg4/vmpeg4_multi.c | 2033 --- .../frame_provider/decoder/real/Makefile | 2 - .../frame_provider/decoder/real/vreal.c | 1054 -- .../frame_provider/decoder/real/vreal.h | 26 - .../frame_provider/decoder/utils/Makefile | 7 - .../decoder/utils/amlogic_fbc_hook.c | 104 - .../decoder/utils/amlogic_fbc_hook.h | 55 - .../decoder/utils/amstream_profile.c | 54 - .../frame_provider/decoder/utils/amvdec.c | 1161 -- .../frame_provider/decoder/utils/amvdec.h | 91 - .../decoder/utils/config_parser.c | 64 - .../decoder/utils/config_parser.h | 21 - .../decoder/utils/decoder_bmmu_box.c | 560 - .../decoder/utils/decoder_bmmu_box.h | 67 - .../decoder/utils/decoder_mmu_box.c | 404 - .../decoder/utils/decoder_mmu_box.h | 48 - .../frame_provider/decoder/utils/firmware.h | 41 - .../decoder/utils/frame_check.c | 1161 -- .../decoder/utils/frame_check.h | 111 - .../frame_provider/decoder/utils/secprot.c | 75 - .../frame_provider/decoder/utils/secprot.h | 39 - .../frame_provider/decoder/utils/utils.c | 71 - .../frame_provider/decoder/utils/vdec.c | 4862 ------ .../frame_provider/decoder/utils/vdec.h | 449 - .../frame_provider/decoder/utils/vdec_input.c | 1106 -- .../frame_provider/decoder/utils/vdec_input.h | 175 - .../decoder/utils/vdec_profile.c | 477 - .../decoder/utils/vdec_profile.h | 40 - .../frame_provider/decoder/utils/vdec_trace.h | 149 - .../frame_provider/decoder/vc1/Makefile | 2 - .../frame_provider/decoder/vc1/vvc1.c | 1287 -- .../frame_provider/decoder/vp9/Makefile | 2 - .../frame_provider/decoder/vp9/vvp9.c | 9855 ------------ .../frame_provider/decoder/vp9/vvp9.h | 23 - .../amlogic/media_modules/frame_sink/Makefile | 1 - .../media_modules/frame_sink/encoder/Makefile | 2 - .../frame_sink/encoder/h264/Makefile | 1 - .../frame_sink/encoder/h264/encoder.c | 4310 ------ .../frame_sink/encoder/h264/encoder.h | 471 - .../frame_sink/encoder/h265/Makefile | 1 - .../frame_sink/encoder/h265/vmm.h | 665 - .../frame_sink/encoder/h265/vpu.c | 2049 --- .../frame_sink/encoder/h265/vpu.h | 310 - .../include/dummy-for-git-empty-dir | 0 .../media_modules/stream_input/Makefile | 17 - .../stream_input/amports/Makefile | 2 - .../media_modules/stream_input/amports/adec.c | 414 - .../media_modules/stream_input/amports/adec.h | 32 - .../stream_input/amports/amports_priv.h | 54 - .../stream_input/amports/amstream.c | 4134 ----- .../stream_input/amports/amstream_profile.c | 54 - .../stream_input/parser/esparser.c | 970 -- .../stream_input/parser/esparser.h | 152 - .../stream_input/parser/hw_demux/Makefile | 8 - .../parser/hw_demux/aml_demod_gt.h | 89 - .../stream_input/parser/hw_demux/aml_dmx.c | 5683 ------- .../stream_input/parser/hw_demux/aml_dvb.c | 2902 ---- .../stream_input/parser/hw_demux/aml_dvb.h | 414 - .../parser/hw_demux/aml_dvb_reg.h | 58 - .../parser/hw_demux/c_stb_define.h | 1217 -- .../parser/hw_demux/c_stb_regs_define.h | 814 - .../parser/hw_demux/dvb_ci/Makefile | 15 - .../parser/hw_demux/dvb_ci/aml_ci.c | 754 - .../parser/hw_demux/dvb_ci/aml_ci.h | 102 - .../parser/hw_demux/dvb_ci/aml_pcmcia.c | 199 - .../parser/hw_demux/dvb_ci/aml_pcmcia.h | 59 - .../parser/hw_demux/dvb_ci/aml_spi.c | 1666 -- .../parser/hw_demux/dvb_ci/aml_spi.h | 81 - .../parser/hw_demux/dvb_ci/cimax/aml_cimax.c | 279 - .../parser/hw_demux/dvb_ci/cimax/aml_cimax.h | 61 - .../hw_demux/dvb_ci/cimax/aml_cimax_spi.c | 2139 --- .../hw_demux/dvb_ci/cimax/aml_cimax_spi.h | 20 - .../hw_demux/dvb_ci/cimax/aml_cimax_usb.c | 1714 --- .../hw_demux/dvb_ci/cimax/aml_cimax_usb.h | 20 - .../dvb_ci/cimax/aml_cimax_usb_priv.h | 22 - .../dvb_ci/cimax/dvb_ca_en50221_cimax.c | 1910 --- .../dvb_ci/cimax/dvb_ca_en50221_cimax.h | 144 - .../hw_demux/dvb_ci/cimax/dvb_ringbuffer.c | 381 - .../hw_demux/dvb_ci/cimax/dvb_ringbuffer.h | 280 - .../parser/hw_demux/dvb_ci/cimax/dvbdev.c | 968 -- .../parser/hw_demux/dvb_ci/cimax/dvbdev.h | 299 - .../hw_demux/dvb_ci/cimax/usb/COPYING.LESSER | 499 - .../hw_demux/dvb_ci/cimax/usb/README.txt | 61 - .../dvb_ci/cimax/usb/SRC/99-cimax+usb.rules | 4 - .../hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt | 85 - .../hw_demux/dvb_ci/cimax/usb/SRC/Makefile | 35 - .../hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h | 424 - .../dvb_ci/cimax/usb/SRC/cimax+usb-driver.c | 2535 --- .../dvb_ci/cimax/usb/SRC/cimax+usb-driver.h | 362 - .../dvb_ci/cimax/usb/SRC/cimax+usb_config.c | 684 - .../dvb_ci/cimax/usb/SRC/cimax+usb_config.h | 58 - .../dvb_ci/cimax/usb/SRC/cimax+usb_fw.c | 325 - .../dvb_ci/cimax/usb/SRC/cimax+usb_fw.h | 61 - .../dvb_ci/cimax/usb/SRC/cimax+usb_handle.h | 46 - .../dvb_ci/cimax/usb/SRC/cimax+usb_time.c | 130 - .../dvb_ci/cimax/usb/SRC/cimax+usb_time.h | 92 - .../dvb_ci/cimax/usb/firmware/cimax+usb.cfg | 97 - .../cimax/usb/firmware/cimax+usb_ms.cfg | 136 - .../stream_input/parser/psparser.c | 1152 -- .../stream_input/parser/psparser.h | 142 - .../stream_input/parser/rmparser.c | 337 - .../stream_input/parser/rmparser.h | 136 - .../stream_input/parser/streambuf.c | 451 - .../stream_input/parser/streambuf.h | 141 - .../stream_input/parser/streambuf_reg.h | 114 - .../stream_input/parser/thread_rw.c | 626 - .../stream_input/parser/thread_rw.h | 53 - .../stream_input/parser/tsdemux.c | 1196 -- .../stream_input/parser/tsdemux.h | 103 - .../stream_input/subtitle/subtitle.c | 715 - .../stream_input/subtitle/subtitle.h | 24 - .../stream_input/tv_frontend/Makefile | 16 - .../stream_input/tv_frontend/aml_fe.c | 1372 -- .../stream_input/tv_frontend/aml_fe.h | 212 - .../tv_frontend/atv_demod/atvdemod_frontend.c | 791 - .../tv_frontend/atv_demod/atvdemod_func.c | 2163 --- .../tv_frontend/atv_demod/atvdemod_func.h | 323 - .../tv_frontend/dtv_demod/aml_demod.c | 725 - .../tv_frontend/dtv_demod/amlfrontend.c | 1402 -- .../tv_frontend/dtv_demod/demod_func.c | 2996 ---- .../tv_frontend/dtv_demod/dvbc_func.c | 1331 -- .../tv_frontend/dtv_demod/dvbt_func.c | 2188 --- .../tv_frontend/dtv_demod/i2c_func.c | 42 - .../include/acf_filter_coefficient.h | 414 - .../dtv_demod/include/addr_dtmb_che.h | 77 - .../dtv_demod/include/addr_dtmb_che_bit.h | 266 - .../dtv_demod/include/addr_dtmb_front.h | 70 - .../dtv_demod/include/addr_dtmb_front_bit.h | 331 - .../dtv_demod/include/addr_dtmb_sync.h | 53 - .../dtv_demod/include/addr_dtmb_sync_bit.h | 110 - .../dtv_demod/include/addr_dtmb_top.h | 90 - .../dtv_demod/include/addr_dtmb_top_bit.h | 178 - .../dtv_demod/include/aml_dtv_demod_reg.h | 28 - .../dtv_demod/include/amlfrontend.h | 86 - .../dtv_demod/include/demod_func.h | 626 - .../tv_frontend/dtv_demod/tuner_func.c | 189 - firmware/h264_enc.bin | Bin 76288 -> 0 bytes firmware/video/h264_enc.bin | Bin 76288 -> 0 bytes firmware/video/video_ucode.bin | Bin 1671680 -> 0 bytes firmware/video_ucode.bin | Bin 1671680 -> 0 bytes 217 files changed, 162813 deletions(-) delete mode 100644 drivers/amlogic/media_modules/Makefile delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/Makefile delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/test/Android.mk delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c delete mode 100644 drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h delete mode 100644 drivers/amlogic/media_modules/common/Makefile delete mode 100644 drivers/amlogic/media_modules/common/chips/chips.c delete mode 100644 drivers/amlogic/media_modules/common/chips/chips.h delete mode 100644 drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c delete mode 100644 drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h delete mode 100644 drivers/amlogic/media_modules/common/firmware/Makefile delete mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_cfg.h delete mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_drv.c delete mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_priv.h delete mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_type.c delete mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_type.h delete mode 100644 drivers/amlogic/media_modules/common/media_clock/Makefile delete mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clk.c delete mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clk.h delete mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h delete mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c delete mode 100644 drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c delete mode 100644 drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs2/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h265/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/real/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_trace.h delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vc1/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vp9/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c delete mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h delete mode 100644 drivers/amlogic/media_modules/frame_sink/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c delete mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h delete mode 100644 drivers/amlogic/media_modules/include/dummy-for-git-empty-dir delete mode 100644 drivers/amlogic/media_modules/stream_input/Makefile delete mode 100644 drivers/amlogic/media_modules/stream_input/amports/Makefile delete mode 100644 drivers/amlogic/media_modules/stream_input/amports/adec.c delete mode 100644 drivers/amlogic/media_modules/stream_input/amports/adec.h delete mode 100644 drivers/amlogic/media_modules/stream_input/amports/amports_priv.h delete mode 100644 drivers/amlogic/media_modules/stream_input/amports/amstream.c delete mode 100644 drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/esparser.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/esparser.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/psparser.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/psparser.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/rmparser.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/rmparser.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/streambuf.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/streambuf.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/thread_rw.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/thread_rw.h delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/tsdemux.c delete mode 100644 drivers/amlogic/media_modules/stream_input/parser/tsdemux.h delete mode 100644 drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c delete mode 100644 drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/Makefile delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_frontend.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/amlfrontend.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h delete mode 100644 drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c delete mode 100644 firmware/h264_enc.bin delete mode 100644 firmware/video/h264_enc.bin delete mode 100644 firmware/video/video_ucode.bin delete mode 100755 firmware/video_ucode.bin diff --git a/drivers/amlogic/media_modules/Makefile b/drivers/amlogic/media_modules/Makefile deleted file mode 100644 index 018c8feff897..000000000000 --- a/drivers/amlogic/media_modules/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-y += common/ -obj-y += frame_provider/ -obj-y += frame_sink/ -obj-y += stream_input/ -obj-y += amvdec_ports/ diff --git a/drivers/amlogic/media_modules/amvdec_ports/Makefile b/drivers/amlogic/media_modules/amvdec_ports/Makefile deleted file mode 100644 index 5ce0a7fcc114..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -obj-m += amvdec_ports.o -amvdec_ports-objs += aml_vcodec_dec_drv.o -amvdec_ports-objs += aml_vcodec_dec.o -amvdec_ports-objs += aml_vcodec_dec_pm.o -amvdec_ports-objs += aml_vcodec_util.o -amvdec_ports-objs += aml_vcodec_adapt.o -amvdec_ports-objs += aml_vcodec_vfm.o -amvdec_ports-objs += vdec_drv_if.o -amvdec_ports-objs += decoder/vdec_h264_if.o -amvdec_ports-objs += decoder/h264_parse.o -amvdec_ports-objs += decoder/h264_stream.o diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c deleted file mode 100644 index 5a3f71b7016e..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c +++ /dev/null @@ -1,720 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../stream_input/amports/adec.h" -#include "../stream_input/parser/streambuf.h" -#include "../stream_input/parser/streambuf_reg.h" -#include "../stream_input/parser/tsdemux.h" -#include "../stream_input/parser/psparser.h" -#include "../stream_input/parser/esparser.h" -#include "../frame_provider/decoder/utils/vdec.h" -#include "../common/media_clock/switch/amports_gate.h" -#include -#include "aml_vcodec_adapt.h" -#include - -#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) -#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) -#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) -#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) -#define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2) -#define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256) - -#define PTS_OUTSIDE (1) -#define SYNC_OUTSIDE (2) -#define USE_V4L_PORTS (0x80) - -//#define DATA_DEBUG - -static int def_4k_vstreambuf_sizeM = - (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); -static int def_vstreambuf_sizeM = - (DEFAULT_VIDEO_BUFFER_SIZE >> 20); - -static int slow_input = 0; - -static int use_bufferlevelx10000 = 10000; -static unsigned int amstream_buf_num = BUF_MAX_NUM; - -static struct stream_buf_s bufs[BUF_MAX_NUM] = { - { - .reg_base = VLD_MEM_VIFIFO_REG_BASE, - .type = BUF_TYPE_VIDEO, - .buf_start = 0, - .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, - .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = AIU_MEM_AIFIFO_REG_BASE, - .type = BUF_TYPE_AUDIO, - .buf_start = 0, - .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, - .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = 0, - .type = BUF_TYPE_SUBTITLE, - .buf_start = 0, - .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, - .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = 0, - .type = BUF_TYPE_USERDATA, - .buf_start = 0, - .buf_size = 0, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = HEVC_STREAM_REG_BASE, - .type = BUF_TYPE_HEVC, - .buf_start = 0, - .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, - .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, - .first_tstamp = INVALID_PTS - }, -}; - -static void set_cfg_info(struct aml_vdec_adapt *vdec) -{ - unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); - - vdec->port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_FRAME/* | PORT_TYPE_ES*/); - vdec->port.flag |= PORT_FLAG_VFORMAT; - vdec->dec_prop.format = vdec->format; - vdec->dec_prop.width = 1920; - vdec->dec_prop.height = 1080; - vdec->dec_prop.rate = 3200; - vdec->dec_prop.param = (void *)sync_mode; -} - -static void set_vdec_mode(struct vdec_s *vdec) -{ - //vdec->type = VDEC_TYPE_SINGLE; - vdec->type = VDEC_TYPE_FRAME_BLOCK; -} - -static void set_vdec_vfm(struct vdec_s *vdec) -{ - vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO; -} - -static int enable_hardware(struct stream_port_s *port) -{ - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) - return -1; - - amports_switch_gate("demux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) - amports_switch_gate("parser_top", 1); - - if (port->type & PORT_TYPE_VIDEO) { - amports_switch_gate("vdec", 1); - - if (has_hevc_vdec()) { - if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) - vdec_poweron(VDEC_HEVC); - - if ((port->type & PORT_TYPE_HEVC) == 0) - vdec_poweron(VDEC_1); - } else { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) - vdec_poweron(VDEC_1); - } - } - - return 0; -} - -static int disable_hardware(struct stream_port_s *port) -{ - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) - return -1; - - if ((port->type & PORT_TYPE_VIDEO) - && get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (has_hevc_vdec()) - vdec_poweroff(VDEC_HEVC); - - vdec_poweroff(VDEC_1); -#else - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX - && port->vformat == VFORMAT_H264 - && bufs[BUF_TYPE_VIDEO].for_4k) - vdec_poweroff(VDEC_HEVC); - - if ((port->vformat == VFORMAT_HEVC - || port->vformat == VFORMAT_VP9)) - vdec_poweroff(VDEC_HEVC); - else - vdec_poweroff(VDEC_1); -#endif - amports_switch_gate("vdec", 0); - } - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) - amports_switch_gate("parser_top", 0); - - amports_switch_gate("demux", 0); - - return 0; -} - -static int reset_canuse_buferlevel(int levelx10000) -{ - int i; - struct stream_buf_s *p = NULL; - - if (levelx10000 >= 0 && levelx10000 <= 10000) - use_bufferlevelx10000 = levelx10000; - else - use_bufferlevelx10000 = 10000; - for (i = 0; i < amstream_buf_num; i++) { - p = &bufs[i]; - p->canusebuf_size = ((p->buf_size / 1024) * - use_bufferlevelx10000 / 10000) * 1024; - p->canusebuf_size += 1023; - p->canusebuf_size &= ~1023; - - if (p->canusebuf_size > p->buf_size) - p->canusebuf_size = p->buf_size; - } - - return 0; -} - -static void change_vbufsize(struct vdec_s *vdec, - struct stream_buf_s *pvbuf) -{ - if (pvbuf->buf_start != 0) { - pr_info("streambuf is alloced before\n"); - return; - } - - if (pvbuf->for_4k) { - pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M; - - if (vdec->port_flag & PORT_FLAG_DRM) - pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP; - - if ((pvbuf->buf_size > 30 * SZ_1M) - && (codec_mm_get_total_size() < 220 * SZ_1M)) { - /*if less than 250M, used 20M for 4K & 265*/ - pvbuf->buf_size = pvbuf->buf_size >> 1; - } - } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { - if (vdec->port_flag & PORT_FLAG_DRM) - pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; - } else { - pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; - if (vdec->port_flag & PORT_FLAG_DRM) - pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; - } - - reset_canuse_buferlevel(10000); -} - -static void user_buffer_init(void) -{ - struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA]; - - pubuf->buf_size = 0; - pubuf->buf_start = 0; - pubuf->buf_wp = 0; - pubuf->buf_rp = 0; -} - -static void audio_component_release(struct stream_port_s *port, - struct stream_buf_s *pbuf, int release_num) -{ - switch (release_num) { - default: - case 0: - case 4: - esparser_release(pbuf); - case 3: - adec_release(port->vformat); - case 2: - stbuf_release(pbuf, false); - case 1: - ; - } -} - -static int audio_component_init(struct stream_port_s *port, - struct stream_buf_s *pbuf) -{ - int r; - - if ((port->flag & PORT_FLAG_AFORMAT) == 0) { - pr_err("aformat not set\n"); - return 0; - } - - r = stbuf_init(pbuf, NULL, false); - if (r < 0) - return r; - - r = adec_init(port); - if (r < 0) { - audio_component_release(port, pbuf, 2); - return r; - } - - if (port->type & PORT_TYPE_ES) { - r = esparser_init(pbuf, NULL); - if (r < 0) { - audio_component_release(port, pbuf, 3); - return r; - } - } - - pbuf->flag |= BUF_FLAG_IN_USE; - - return 0; -} - -static void video_component_release(struct stream_port_s *port, -struct stream_buf_s *pbuf, int release_num) -{ - struct aml_vdec_adapt *ada_ctx - = container_of(port, struct aml_vdec_adapt, port); - struct vdec_s *vdec = ada_ctx->vdec; - - struct vdec_s *slave = NULL; - bool is_multidec = !vdec_single(vdec); - - switch (release_num) { - default: - case 0: - case 4: { - if ((port->type & PORT_TYPE_FRAME) == 0) - esparser_release(pbuf); - } - - case 3: { - if (vdec->slave) - slave = vdec->slave; - vdec_release(vdec); - - if (slave) - vdec_release(slave); - vdec = NULL; - } - - case 2: { - if ((port->type & PORT_TYPE_FRAME) == 0) - stbuf_release(pbuf, is_multidec); - } - - case 1: - ; - } -} - -static int video_component_init(struct stream_port_s *port, - struct stream_buf_s *pbuf) -{ - int ret = -1; - struct aml_vdec_adapt *ada_ctx - = container_of(port, struct aml_vdec_adapt, port); - struct vdec_s *vdec = ada_ctx->vdec; - - if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { - pr_err("vformat not set\n"); - return -EPERM; - } - - if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088 - || port->vformat == VFORMAT_H264_4K2K) { - pbuf->for_4k = 1; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX - && port->vformat == VFORMAT_H264) - vdec_poweron(VDEC_HEVC); - } else - pbuf->for_4k = 0; - - if (port->type & PORT_TYPE_FRAME) { - ret = vdec_init(vdec, pbuf->for_4k); - if (ret < 0) { - pr_err("video_component_init %d, failed\n", __LINE__); - video_component_release(port, pbuf, 2); - return ret; - } - - return 0; - } - - change_vbufsize(vdec, pbuf); - - if (has_hevc_vdec()) { - if (port->type & PORT_TYPE_MPTS) { - if (pbuf->type == BUF_TYPE_HEVC) - vdec_poweroff(VDEC_1); - else - vdec_poweroff(VDEC_HEVC); - } - } - - ret = stbuf_init(pbuf, vdec, false); - if (ret < 0) { - pr_err("video_component_init %d, stbuf_init failed\n", __LINE__); - return ret; - } - - /* todo: set path based on port flag */ - ret = vdec_init(vdec, pbuf->for_4k); - if (ret < 0) { - pr_err("video_component_init %d, vdec_init failed\n", __LINE__); - video_component_release(port, pbuf, 2); - return ret; - } - - if (vdec_dual(vdec)) { - ret = vdec_init(vdec->slave, pbuf->for_4k); - if (ret < 0) { - pr_err("video_component_init %d, vdec_init failed\n", - __LINE__); - video_component_release(port, pbuf, 2); - return ret; - } - } - - if (port->type & PORT_TYPE_ES) { - ret = esparser_init(pbuf, vdec); - if (ret < 0) { - video_component_release(port, pbuf, 3); - pr_err("esparser_init() failed\n"); - return ret; - } - } - - pbuf->flag |= BUF_FLAG_IN_USE; - - vdec_connect(vdec); - - return 0; -} - -static int vdec_ports_release(struct stream_port_s *port) -{ - struct aml_vdec_adapt *ada_ctx - = container_of(port, struct aml_vdec_adapt, port); - struct vdec_s *vdec = ada_ctx->vdec; - - struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - struct vdec_s *slave = NULL; - - if (has_hevc_vdec()) { - if (port->vformat == VFORMAT_HEVC - || port->vformat == VFORMAT_VP9) - pvbuf = &bufs[BUF_TYPE_HEVC]; - } - - if (port->type & PORT_TYPE_MPTS) { - tsync_pcr_stop(); - tsdemux_release(); - } - - if (port->type & PORT_TYPE_MPPS) - psparser_release(); - - if (port->type & PORT_TYPE_VIDEO) - video_component_release(port, pvbuf, 0); - - if (port->type & PORT_TYPE_AUDIO) - audio_component_release(port, pabuf, 0); - - if (port->type & PORT_TYPE_SUB) - //sub_port_release(port, psbuf); - - if (vdec) { - if (vdec->slave) - slave = vdec->slave; - - vdec_release(vdec); - - if (slave) - vdec_release(slave); - vdec = NULL; - } - - port->pcr_inited = 0; - port->flag = 0; - - return 0; -} - -static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) -{ - int ret = -1; - struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - struct stream_port_s *port = &vdec_adapt->port; - struct vdec_s *vdec = NULL; - - /* create the vdec instance.*/ - vdec = vdec_create(port, NULL); - if (IS_ERR_OR_NULL(vdec)) - return -1; - - /* set v4l2 ctx */ - vdec->private = vdec_adapt->ctx; - - vdec_adapt->vdec = vdec; - vdec->sys_info = &vdec_adapt->dec_prop; - vdec->sys_info_store = vdec_adapt->dec_prop; - vdec->vf_receiver_name = vdec_adapt->recv_name; - - /* set video format and sys info */ - vdec_set_format(vdec, vdec_adapt->dec_prop.format); - set_vdec_mode(vdec); - set_vdec_vfm(vdec); - - stbuf_fetch_init(); - - user_buffer_init(); - - if ((port->type & PORT_TYPE_AUDIO) - && (port->flag & PORT_FLAG_AFORMAT)) { - ret = audio_component_init(port, pabuf); - if (ret < 0) { - pr_err("audio_component_init failed\n"); - goto error1; - } - } - - if ((port->type & PORT_TYPE_VIDEO) - && (vdec->port_flag & PORT_FLAG_VFORMAT)) { - pvbuf->for_4k = 0; - if (has_hevc_vdec()) { - if (port->vformat == VFORMAT_HEVC - || port->vformat == VFORMAT_VP9) - pvbuf = &bufs[BUF_TYPE_HEVC]; - } - - ret = video_component_init(port, pvbuf); - if (ret < 0) { - pr_err("video_component_init failed\n"); - goto error2; - } - } - - /* connect vdec at the end after all HW initialization */ - if ((port->type & PORT_TYPE_VIDEO) - && (vdec->port_flag & PORT_FLAG_VFORMAT)) - vdec_connect(vdec); - - return 0; - -//error3: - //video_component_release(port, pvbuf, 0); -error2: - audio_component_release(port, pabuf, 0); -error1: - return ret; -} - -int video_decoder_init(struct aml_vdec_adapt *vdec) -{ - int ret = -1; - - /* sets configure data */ - set_cfg_info(vdec); - - /* init hw and gate*/ - ret = enable_hardware(&vdec->port); - if (ret < 0) { - pr_info("enable hw fail.\n"); - goto out; - } - - /* init the buffer work space and connect vdec.*/ - ret = vdec_ports_init(vdec); - if (ret < 0) { - pr_info("vdec ports init fail.\n"); - goto out; - } -out: - return ret; -} - -int video_decoder_release(struct aml_vdec_adapt *vdec) -{ - int ret = -1; - struct stream_port_s *port = &vdec->port; - - ret = vdec_ports_release(port); - if (ret < 0) { - pr_info("vdec ports release fail.\n"); - goto out; - } - - /* disable gates */ - ret = disable_hardware(port); - if (ret < 0) { - pr_info("disable hw fail.\n"); - goto out; - } -out: - return ret; -} - -int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, - const char *buf, unsigned int count) -{ - int ret = -1; - int try_cnt = 100; - struct stream_port_s *port = &ada_ctx->port; - struct vdec_s *vdec = ada_ctx->vdec; - struct stream_buf_s *pbuf = NULL; - - if (has_hevc_vdec()) { - pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : - &bufs[BUF_TYPE_VIDEO]; - } else - pbuf = &bufs[BUF_TYPE_VIDEO]; - - /*if (!(port_get_inited(priv))) { - r = video_decoder_init(priv); - if (r < 0) - return r; - }*/ - - do { - if (vdec->port_flag & PORT_FLAG_DRM) - ret = drm_write(ada_ctx->filp, pbuf, buf, count); - else - ret = esparser_write(ada_ctx->filp, pbuf, buf, count); - } while (ret == -EAGAIN && try_cnt--); - - if (slow_input) { - pr_info("slow_input: es codec write size %x\n", ret); - msleep(10); - } - -#ifdef DATA_DEBUG - /* dump to file */ - //dump_write(vbuf, size); - //pr_info("vbuf: %p, size: %u, ret: %d\n", vbuf, size, ret); -#endif - - return ret; -} - -int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) -{ - struct vdec_s *vdec = ada_ctx->vdec; - - if (vdec->input.have_frame_num > 8) - return 0; - else - return 1; -} - -int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, - const char *buf, unsigned int count, unsigned long int timestamp) -{ - int ret = -1; - int try_cnt = 10; - struct vdec_s *vdec = ada_ctx->vdec; - - /* set timestamp */ - vdec_set_timestamp(vdec, timestamp); - - do { - ret = vdec_write_vframe(vdec, buf, count); - if (ret == -EAGAIN) { - /*vdec_input_level(&vdec->input);*/ - msleep(20); - } - } while (ret == -EAGAIN && try_cnt--); - - if (slow_input) { - pr_info("slow_input: frame codec write size %d\n", ret); - msleep(30); - } - -#ifdef DATA_DEBUG - /* dump to file */ - dump_write(buf, count); -#endif - aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", - ada_ctx->ctx->id, buf, count, ret, crc32(0, buf, count)); - - return ret; -} - -void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) -{ - struct vdec_s *vdec = ada_ctx->vdec; - - if (vdec) - vdec_set_eos(vdec, true); -} - -int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) -{ - struct vdec_s *vdec = ada_ctx->vdec; - int ret = 0; - - if (vdec) { - vdec_set_eos(vdec, false); - ret = vdec_reset(vdec); - } - - return ret; -} - -bool is_input_ready(struct aml_vdec_adapt *ada_ctx) -{ - struct vdec_s *vdec = ada_ctx->vdec; - int state = VDEC_STATUS_UNINITIALIZED; - - if (vdec) { - state = vdec_get_status(vdec); - - if (state == VDEC_STATUS_CONNECTED - || state == VDEC_STATUS_ACTIVE) - return true; - } - - return false; -} diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h deleted file mode 100644 index da4553f50970..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef VDEC_ADAPT_H -#define VDEC_ADAPT_H - -#include -#include -#include "../stream_input/parser/streambuf.h" -#include "aml_vcodec_drv.h" - -struct aml_vdec_adapt { - enum vformat_e format; - void *vsi; - int32_t failure; - uint32_t inst_addr; - unsigned int signaled; - struct aml_vcodec_ctx *ctx; - struct platform_device *dev; - wait_queue_head_t wq; - struct file *filp; - struct vdec_s *vdec; - struct stream_port_s port; - struct dec_sysinfo dec_prop; - char *recv_name; -}; - -int video_decoder_init(struct aml_vdec_adapt *ada_ctx); - -int video_decoder_release(struct aml_vdec_adapt *ada_ctx); - -int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, - const char *buf, unsigned int count); - -int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, - const char *buf, unsigned int count, unsigned long int timestamp); - -int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); - -void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); - -int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); - -extern void dump_write(const char __user *buf, size_t count); - -bool is_input_ready(struct aml_vdec_adapt *ada_ctx); - -#endif /* VDEC_ADAPT_H */ - diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c deleted file mode 100644 index 20dd5d5346b4..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c +++ /dev/null @@ -1,1837 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include - -#include "aml_vcodec_drv.h" -#include "aml_vcodec_dec.h" -//#include "aml_vcodec_intr.h" -#include "aml_vcodec_util.h" -#include "vdec_drv_if.h" -#include "aml_vcodec_dec_pm.h" -#include -#include -#include -#include "aml_vcodec_adapt.h" - -#include "aml_vcodec_vfm.h" - -#define OUT_FMT_IDX 0 -#define CAP_FMT_IDX 1//3 - -#define AML_VDEC_MIN_W 64U -#define AML_VDEC_MIN_H 64U -#define DFT_CFG_WIDTH AML_VDEC_MIN_W -#define DFT_CFG_HEIGHT AML_VDEC_MIN_H - -//#define USEC_PER_SEC 1000000 - -#define call_void_memop(vb, op, args...) \ - do { \ - if ((vb)->vb2_queue->mem_ops->op) \ - (vb)->vb2_queue->mem_ops->op(args); \ - } while (0) - -static struct aml_video_fmt aml_video_formats[] = { - { - .fourcc = V4L2_PIX_FMT_H264, - .type = AML_FMT_DEC, - .num_planes = 1, - }, -/* { - .fourcc = V4L2_PIX_FMT_VP8, - .type = AML_FMT_DEC, - .num_planes = 1, - }, - { - .fourcc = V4L2_PIX_FMT_VP9, - .type = AML_FMT_DEC, - .num_planes = 1, - },*/ - { - .fourcc = V4L2_PIX_FMT_NV12, - .type = AML_FMT_FRAME, - .num_planes = 2, - }, -}; - -static const struct aml_codec_framesizes aml_vdec_framesizes[] = { - { - .fourcc = V4L2_PIX_FMT_H264, - .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, - AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, - }, -/* { - .fourcc = V4L2_PIX_FMT_VP8, - .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, - AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, - }, - { - .fourcc = V4L2_PIX_FMT_VP9, - .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, - AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, - },*/ -}; - -#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(aml_vdec_framesizes) -#define NUM_FORMATS ARRAY_SIZE(aml_video_formats) - -static struct aml_video_fmt *aml_vdec_find_format(struct v4l2_format *f) -{ - struct aml_video_fmt *fmt; - unsigned int k; - - for (k = 0; k < NUM_FORMATS; k++) { - fmt = &aml_video_formats[k]; - if (fmt->fourcc == f->fmt.pix_mp.pixelformat) - return fmt; - } - - return NULL; -} - -static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx, - enum v4l2_buf_type type) -{ - if (V4L2_TYPE_IS_OUTPUT(type)) - return &ctx->q_data[AML_Q_DATA_SRC]; - - return &ctx->q_data[AML_Q_DATA_DST]; -} - -static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) -{ - static const struct v4l2_event ev_src_ch = { - .type = V4L2_EVENT_SOURCE_CHANGE, - .u.src_change.changes = - V4L2_EVENT_SRC_CH_RESOLUTION, - }; - - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); -} - -static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) -{ - aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - - aml_decoder_flush(ctx->ada_ctx); -} - -static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) -{ - unsigned int dpbsize = 0; - int ret; - - if (vdec_if_get_param(ctx, - GET_PARAM_PIC_INFO, - &ctx->last_decoded_picinfo)) { - aml_v4l2_err("[%d] Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", - ctx->id); - return; - } - - if (ctx->last_decoded_picinfo.visible_width == 0 || - ctx->last_decoded_picinfo.visible_height == 0 || - ctx->last_decoded_picinfo.coded_width == 0 || - ctx->last_decoded_picinfo.coded_height == 0) { - aml_v4l2_err("Cannot get correct pic info"); - return; - } - - if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || - (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height)) - return; - - aml_v4l2_debug(4, - "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", - ctx->id, ctx->last_decoded_picinfo.visible_width, - ctx->last_decoded_picinfo.visible_height, - ctx->picinfo.visible_width, ctx->picinfo.visible_height, - ctx->last_decoded_picinfo.coded_width, - ctx->last_decoded_picinfo.coded_width); - - ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize); - if (dpbsize == 0) - aml_v4l2_err("[%d] Incorrect dpb size, ret=%d", ctx->id, ret); - - ctx->dpb_size = dpbsize; -} - -int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) -{ - struct vb2_buffer *dst_buf = NULL; - struct vdec_fb *pfb; - struct aml_video_dec_buf *dst_buf_info, *info; - struct vb2_v4l2_buffer *dst_vb2_v4l2; - int try_cnt = 10; - - aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - - do { - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - if (dst_buf) - break; - aml_v4l2_debug(3, "[%d] waitting enough dst buffers.", ctx->id); - msleep(20); - } while (try_cnt--); - - if (!dst_buf) - return -1; - - dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); - dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb); - - pfb = &dst_buf_info->frame_buffer; - //pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); - pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); - pfb->base_y.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_y.dma_addr)); - pfb->base_y.size = ctx->picinfo.y_len_sz; - - //pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); - pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); - pfb->base_c.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_c.dma_addr)); - pfb->base_c.size = ctx->picinfo.c_len_sz; - pfb->status = FB_ST_NORMAL; - - aml_v4l2_debug(4, "[%d] id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx", - ctx->id, dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, - &pfb->base_c.dma_addr, pfb->base_y.size, pfb->base_c.size); - - //mutex_lock(&ctx->lock); - dst_buf_info->used = true; - //mutex_unlock(&ctx->lock); - - v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); - - *out_fb = pfb; - - info = container_of(pfb, struct aml_video_dec_buf, frame_buffer); - - return 0; -} -EXPORT_SYMBOL(get_fb_from_queue); - -int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) -{ - struct aml_video_dec_buf *dstbuf; - - pr_info("[%d] %s() [%d]\n", ctx->id, __func__, __LINE__); - - if (in_fb == NULL) { - aml_v4l2_debug(4, "[%d] No free frame buffer", ctx->id); - return -1; - } - - aml_v4l2_debug(4, "[%d] tmp_frame_addr = 0x%p", ctx->id, in_fb); - - dstbuf = container_of(in_fb, struct aml_video_dec_buf, frame_buffer); - - mutex_lock(&ctx->lock); - - if (!dstbuf->used) - goto out; - - aml_v4l2_debug(4, - "[%d] status=%x queue id=%d to rdy_queue", - ctx->id, in_fb->status, - dstbuf->vb.vb2_buf.index); - - v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb); - - dstbuf->used = false; -out: - mutex_unlock(&ctx->lock); - - return 0; - -} -EXPORT_SYMBOL(put_fb_to_queue); - -void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) -{ - int cnt; - struct aml_video_dec_buf *dstbuf = NULL; - struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; - - dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); - - aml_v4l2_debug(4,"%s() [%d], base_y: %zu, idx: %u\n", - __FUNCTION__, __LINE__, fb->base_y.size, dstbuf->vb.vb2_buf.index); - aml_v4l2_debug(4,"%s() [%d], base_c: %zu, idx: %u\n", - __FUNCTION__, __LINE__, fb->base_c.size, dstbuf->vb.vb2_buf.index); - - dstbuf->vb.vb2_buf.timestamp = vf->timestamp; - aml_v4l2_debug(4, "[%d] %s() [%d], timestamp: %llx", - ctx->id, __func__, __LINE__, vf->timestamp); - - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->base_y.bytes_used); - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->base_c.bytes_used); - - dstbuf->ready_to_display = true; - - aml_v4l2_debug(4, "[%d]status=%x queue id=%d to done_list %d", - ctx->id, fb->status, dstbuf->vb.vb2_buf.index, - dstbuf->queued_in_vb2); - - cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); - aml_v4l2_debug(4, "[%d] %s() [%d], owned_by_drv_count: %d", - ctx->id, __func__, __LINE__, cnt); - aml_v4l2_debug(4, "[%d] %s() [%d], y_va: %p, vf_h: %lx", - ctx->id, __func__, __LINE__, dstbuf->frame_buffer.base_y.va, - dstbuf->frame_buffer.vf_handle); - - if (vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { - dstbuf->lastframe = true; - dstbuf->vb.flags = V4L2_BUF_FLAG_LAST; - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); - ctx->has_receive_eos = true; - pr_info("[%d] recevie a empty frame.\n", ctx->id); - } - - v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_FLUSHING && - ctx->has_receive_eos) { - ctx->state = AML_STATE_FLUSHED; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)", - ctx->id, __func__); - } - mutex_unlock(&ctx->state_lock); - - ctx->decoded_frame_cnt++; -} - -static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) -{ - int ret = -1; - - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - - ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out); - if (ret) { - aml_v4l2_err("[%d] Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); - return -1; - } - - if (!*out) { - aml_v4l2_debug(4, "[%d] No display frame buffer", ctx->id); - return -1; - } - - return ret; -} - -static int is_vdec_ready(struct aml_vcodec_ctx *ctx) -{ - struct aml_vcodec_dev *dev = ctx->dev; - - if (!is_input_ready(ctx->ada_ctx)) { - pr_err("[%d] %s() the decoder intput has not ready.\n", - ctx->id, __func__); - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - return 0; - } - - if (ctx->state == AML_STATE_PROBE) { - int buf_ready_num; - - /* is there enough dst bufs for decoding? */ - buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); - if (buf_ready_num < ctx->dpb_size) { - aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.\n", - ctx->id, buf_ready_num); - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - v4l2_m2m_try_schedule(ctx->m2m_ctx); - msleep(60); - return 0; - } - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_PROBE) { - ctx->state = AML_STATE_READY; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", - ctx->id, __func__); - } - mutex_unlock(&ctx->state_lock); - } - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_READY) { - ctx->state = AML_STATE_ACTIVE; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", - ctx->id, __func__); - } - mutex_unlock(&ctx->state_lock); - - return 1; -} - -static void aml_vdec_worker(struct work_struct *work) -{ - struct aml_vcodec_ctx *ctx = - container_of(work, struct aml_vcodec_ctx, decode_work); - struct aml_vcodec_dev *dev = ctx->dev; - struct vb2_buffer *src_buf; - struct aml_vcodec_mem buf; - bool res_chg = false; - int ret; - struct aml_video_dec_buf *src_buf_info; - struct vb2_v4l2_buffer *src_vb2_v4l2; - - aml_v4l2_debug(4, "[%d] entry [%d] [%s]", ctx->id, __LINE__, __func__); - - aml_vdec_lock(ctx); - - if (ctx->state < AML_STATE_INIT || - ctx->state > AML_STATE_FLUSHED) { - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - aml_vdec_unlock(ctx); - return; - } - - if (!is_vdec_ready(ctx)) { - pr_err("[%d] %s() the decoder has not ready.\n", - ctx->id, __func__); - aml_vdec_unlock(ctx); - return; - } - - src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - if (src_buf == NULL) { - pr_err("[%d] src_buf empty!\n", ctx->id); - aml_vdec_unlock(ctx); - return; - } - - src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf); - src_buf_info = container_of(src_vb2_v4l2, struct aml_video_dec_buf, vb); - - if (src_buf_info->lastframe) { - //the empty data use to flushed the decoder. - aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id); - - src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - - /* sets eos data for vdec input. */ - aml_vdec_flush_decoder(ctx); - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_ACTIVE) { - ctx->state = AML_STATE_FLUSHING;// prepare flushing - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)", - ctx->id, __func__); - } - mutex_unlock(&ctx->state_lock); - - aml_vdec_unlock(ctx); - return; - } - - buf.va = vb2_plane_vaddr(src_buf, 0); - buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); - //buf.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), buf.dma_addr)); - - buf.size = (size_t)src_buf->planes[0].bytesused; - if (!buf.va) { - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - aml_v4l2_err("[%d] id=%d src_addr is NULL!!", - ctx->id, src_buf->index); - aml_vdec_unlock(ctx); - return; - } - aml_v4l2_debug(4, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", - ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); - - src_buf_info->used = true; - - //pr_err("%s() [%d], size: 0x%zx, crc: 0x%x\n", - //__func__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); - - /* pts = (time / 10e6) * (90k / fps) */ - aml_v4l2_debug(4, "[%d] %s() timestamp: 0x%llx", ctx->id , __func__, - src_buf->timestamp); - - ret = vdec_if_decode(ctx, &buf, src_buf->timestamp, &res_chg); - if (ret > 0) { - /* - * we only return src buffer with VB2_BUF_STATE_DONE - * when decode success without resolution change - */ - src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); - } else if (ret == -EAGAIN) { - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - aml_vdec_unlock(ctx); - return; - } else { - src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - if (ret == -EIO) { - //mutex_lock(&ctx->lock); - src_buf_info->error = true; - //mutex_unlock(&ctx->lock); - } - v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); - } - - if (!ret && res_chg) { - if (0) aml_vdec_pic_info_update(ctx); - /* - * On encountering a resolution change in the stream. - * The driver must first process and decode all - * remaining buffers from before the resolution change - * point, so call flush decode here - */ - if (0) aml_vdec_flush_decoder(ctx); - /* - * After all buffers containing decoded frames from - * before the resolution change point ready to be - * dequeued on the CAPTURE queue, the driver sends a - * V4L2_EVENT_SOURCE_CHANGE event for source change - * type V4L2_EVENT_SRC_CH_RESOLUTION - */ - if (0) aml_vdec_queue_res_chg_event(ctx); - } - - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - aml_vdec_unlock(ctx); -} - -static void aml_reset_worker(struct work_struct *work) -{ - struct aml_vcodec_ctx *ctx = - container_of(work, struct aml_vcodec_ctx, reset_work); - struct aml_video_dec_buf *buf = NULL; - - aml_vdec_lock(ctx); - - if (ctx->state == AML_STATE_ABORT) { - pr_err("[%d] %s() the decoder will be exited.\n", - ctx->id, __func__); - aml_vdec_unlock(ctx); - return; - } - - /* fast enque capture buffers. */ - list_for_each_entry(buf, &ctx->capture_list, node) { - if (buf->que_in_m2m) - v4l2_m2m_buf_queue(ctx->m2m_ctx, &buf->vb); - } - - if (aml_codec_reset(ctx->ada_ctx)) { - ctx->state = AML_STATE_ABORT; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", - ctx->id, __func__); - aml_vdec_unlock(ctx); - return; - } - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_RESET) { - ctx->state = AML_STATE_READY; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", - ctx->id, __func__); - - v4l2_m2m_try_schedule(ctx->m2m_ctx); - } - mutex_unlock(&ctx->state_lock); - - aml_vdec_unlock(ctx); -} - -void try_to_capture(struct aml_vcodec_ctx *ctx) -{ - int ret = 0; - struct vdec_fb *fb = NULL; - - ret = get_display_buffer(ctx, &fb); - if (ret) { - aml_v4l2_debug(4, "[%d] %s() [%d], the que have no disp buf,ret: %d", - ctx->id, __func__, __LINE__, ret); - return; - } - - trans_vframe_to_user(ctx, fb); -} -EXPORT_SYMBOL_GPL(try_to_capture); - -static int vdec_thread(void *data) -{ - struct aml_vdec_thread *thread = - (struct aml_vdec_thread *) data; - struct aml_vcodec_ctx *ctx = - (struct aml_vcodec_ctx *) thread->priv; - - for (;;) { - aml_v4l2_debug(3, "[%d] %s() state: %d", ctx->id, - __func__, ctx->state); - - if (down_interruptible(&thread->sem)) - break; - - if (thread->stop) - break; - - thread->func(ctx); - } - - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } - - return 0; -} - -void aml_thread_notify(struct aml_vcodec_ctx *ctx, - enum aml_thread_type type) -{ - struct aml_vdec_thread *thread = NULL; - - list_for_each_entry(thread, &ctx->vdec_thread_list, node) { - if (thread->task == NULL) - continue; - - if (thread->type == type) - up(&thread->sem); - } -} -EXPORT_SYMBOL_GPL(aml_thread_notify); - -int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, - enum aml_thread_type type, const char *thread_name) -{ - struct aml_vdec_thread *thread; - int ret = 0; - - thread = kzalloc(sizeof(*thread), GFP_KERNEL); - if (thread == NULL) - return -ENOMEM; - - thread->type = type; - thread->func = func; - thread->priv = ctx; - sema_init(&thread->sem, 0); - - thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name); - if (IS_ERR(thread->task)) { - ret = PTR_ERR(thread->task); - thread->task = NULL; - goto err; - } - - list_add(&thread->node, &ctx->vdec_thread_list); - - return 0; - -err: - kfree(thread); - - return ret; -} -EXPORT_SYMBOL_GPL(aml_thread_start); - -void aml_thread_stop(struct aml_vcodec_ctx *ctx) -{ - struct aml_vdec_thread *thread = NULL; - - while (!list_empty(&ctx->vdec_thread_list)) { - thread = list_entry(ctx->vdec_thread_list.next, - struct aml_vdec_thread, node); - list_del(&thread->node); - thread->stop = true; - up(&thread->sem); - kthread_stop(thread->task); - thread->task = NULL; - kfree(thread); - } -} -EXPORT_SYMBOL_GPL(aml_thread_stop); - -static int vidioc_try_decoder_cmd(struct file *file, void *priv, - struct v4l2_decoder_cmd *cmd) -{ - switch (cmd->cmd) { - case V4L2_DEC_CMD_STOP: - case V4L2_DEC_CMD_START: - if (cmd->flags != 0) { - aml_v4l2_err("cmd->flags=%u", cmd->flags); - return -EINVAL; - } - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_decoder_cmd(struct file *file, void *priv, - struct v4l2_decoder_cmd *cmd) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - struct vb2_queue *src_vq, *dst_vq; - int ret; - - ret = vidioc_try_decoder_cmd(file, priv, cmd); - if (ret) - return ret; - - aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", - ctx->id, __func__, __LINE__, cmd->cmd); - dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - switch (cmd->cmd) { - case V4L2_DEC_CMD_STOP: - - if (ctx->state != AML_STATE_ACTIVE) - return 0; - - src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (!vb2_is_streaming(src_vq)) { - pr_err("[%d] Output stream is off. No need to flush.\n", ctx->id); - return 0; - } - - if (!vb2_is_streaming(dst_vq)) { - pr_err("[%d] Capture stream is off. No need to flush.\n", ctx->id); - return 0; - } - - /* flush src */ - v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); - v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention - - break; - - case V4L2_DEC_CMD_START: - aml_v4l2_debug(4, "[%d] CMD V4L2_DEC_CMD_START ", ctx->id); - vb2_clear_last_buffer_dequeued(dst_vq);//pay attention - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int vidioc_decoder_streamon(struct file *file, void *priv, - enum v4l2_buf_type i) -{ - struct v4l2_fh *fh = file->private_data; - struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); - struct aml_vcodec_dev *dev = ctx->dev; - struct vb2_queue *q; - int ret = 0; - - ret = v4l2_m2m_ioctl_streamon(file, priv, i); - - q = v4l2_m2m_get_vq(fh->m2m_ctx, i); - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_FLUSHED) { - if (!V4L2_TYPE_IS_OUTPUT(q->type)) { - ctx->state = AML_STATE_RESET; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", - ctx->id, __func__); - queue_work(dev->reset_workqueue, &ctx->reset_work); - } - } - mutex_unlock(&ctx->state_lock); - - return ret; -} - -void aml_vdec_unlock(struct aml_vcodec_ctx *ctx) -{ - mutex_unlock(&ctx->dev->dec_mutex); -} - -void aml_vdec_lock(struct aml_vcodec_ctx *ctx) -{ - mutex_lock(&ctx->dev->dec_mutex); -} - -void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) -{ - aml_vdec_lock(ctx); - - ctx->state = AML_STATE_ABORT; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", - ctx->id, __func__); - - vdec_if_deinit(ctx); - - aml_vdec_unlock(ctx); -} - -void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) -{ - struct aml_q_data *q_data; - - ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex; - ctx->fh.m2m_ctx = ctx->m2m_ctx; - ctx->fh.ctrl_handler = &ctx->ctrl_hdl; - INIT_WORK(&ctx->decode_work, aml_vdec_worker); - INIT_WORK(&ctx->reset_work, aml_reset_worker); - ctx->colorspace = V4L2_COLORSPACE_REC709; - ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; - ctx->quantization = V4L2_QUANTIZATION_DEFAULT; - ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; - ctx->dev->dec_capability = VCODEC_CAPABILITY_4K_DISABLED;//disable 4k - - q_data = &ctx->q_data[AML_Q_DATA_SRC]; - memset(q_data, 0, sizeof(struct aml_q_data)); - q_data->visible_width = DFT_CFG_WIDTH; - q_data->visible_height = DFT_CFG_HEIGHT; - q_data->fmt = &aml_video_formats[OUT_FMT_IDX]; - q_data->field = V4L2_FIELD_NONE; - - q_data->sizeimage[0] = (1024 * 1024);//DFT_CFG_WIDTH * DFT_CFG_HEIGHT; //1m - q_data->bytesperline[0] = 0; - - q_data = &ctx->q_data[AML_Q_DATA_DST]; - memset(q_data, 0, sizeof(struct aml_q_data)); - q_data->visible_width = DFT_CFG_WIDTH; - q_data->visible_height = DFT_CFG_HEIGHT; - q_data->coded_width = DFT_CFG_WIDTH; - q_data->coded_height = DFT_CFG_HEIGHT; - q_data->fmt = &aml_video_formats[CAP_FMT_IDX]; - q_data->field = V4L2_FIELD_NONE; - - v4l_bound_align_image(&q_data->coded_width, - AML_VDEC_MIN_W, - AML_VDEC_MAX_W, 4, - &q_data->coded_height, - AML_VDEC_MIN_H, - AML_VDEC_MAX_H, 5, 6); - - q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height; - q_data->bytesperline[0] = q_data->coded_width; - q_data->sizeimage[1] = q_data->sizeimage[0] / 2; - q_data->bytesperline[1] = q_data->coded_width; - - ctx->state = AML_STATE_IDLE; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)", - ctx->id, __func__); -} - -static int vidioc_vdec_qbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - - if (ctx->state == AML_STATE_ABORT) { - aml_v4l2_err("[%d] Call on QBUF after unrecoverable error", - ctx->id); - return -EIO; - } - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_vdec_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - - if (ctx->state == AML_STATE_ABORT) { - aml_v4l2_err("[%d] Call on DQBUF after unrecoverable error", - ctx->id); - return -EIO; - } - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_vdec_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - strlcpy(cap->driver, AML_VCODEC_DEC_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, AML_PLATFORM_STR, sizeof(cap->bus_info)); - strlcpy(cap->card, AML_PLATFORM_STR, sizeof(cap->card)); - - return 0; -} - -static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) -{ - switch (sub->type) { - case V4L2_EVENT_EOS: - return v4l2_event_subscribe(fh, sub, 2, NULL); - case V4L2_EVENT_SOURCE_CHANGE: - return v4l2_src_change_event_subscribe(fh, sub); - default: - return v4l2_ctrl_subscribe_event(fh, sub); - } -} - -static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt) -{ - struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; - int i; - - pix_fmt_mp->field = V4L2_FIELD_NONE; - - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - pix_fmt_mp->num_planes = 1; - pix_fmt_mp->plane_fmt[0].bytesperline = 0; - } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - int tmp_w, tmp_h; - - pix_fmt_mp->height = clamp(pix_fmt_mp->height, - AML_VDEC_MIN_H, - AML_VDEC_MAX_H); - pix_fmt_mp->width = clamp(pix_fmt_mp->width, - AML_VDEC_MIN_W, - AML_VDEC_MAX_W); - - /* - * Find next closer width align 64, heign align 64, size align - * 64 rectangle - * Note: This only get default value, the real HW needed value - * only available when ctx in AML_STATE_PROBE state - */ - tmp_w = pix_fmt_mp->width; - tmp_h = pix_fmt_mp->height; - v4l_bound_align_image(&pix_fmt_mp->width, - AML_VDEC_MIN_W, - AML_VDEC_MAX_W, 6, - &pix_fmt_mp->height, - AML_VDEC_MIN_H, - AML_VDEC_MAX_H, 6, 9); - - if (pix_fmt_mp->width < tmp_w && - (pix_fmt_mp->width + 64) <= AML_VDEC_MAX_W) - pix_fmt_mp->width += 64; - if (pix_fmt_mp->height < tmp_h && - (pix_fmt_mp->height + 64) <= AML_VDEC_MAX_H) - pix_fmt_mp->height += 64; - - aml_v4l2_debug(4, - "before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d", - tmp_w, tmp_h, pix_fmt_mp->width, - pix_fmt_mp->height, - pix_fmt_mp->width * pix_fmt_mp->height); - - pix_fmt_mp->num_planes = fmt->num_planes; - pix_fmt_mp->plane_fmt[0].sizeimage = - pix_fmt_mp->width * pix_fmt_mp->height; - pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width; - - if (pix_fmt_mp->num_planes == 2) { - pix_fmt_mp->plane_fmt[1].sizeimage = - (pix_fmt_mp->width * pix_fmt_mp->height) / 2; - pix_fmt_mp->plane_fmt[1].bytesperline = - pix_fmt_mp->width; - } - } - - for (i = 0; i < pix_fmt_mp->num_planes; i++) - memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0, - sizeof(pix_fmt_mp->plane_fmt[0].reserved)); - - pix_fmt_mp->flags = 0; - memset(&pix_fmt_mp->reserved, 0x0, sizeof(pix_fmt_mp->reserved)); - return 0; -} - -static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct aml_video_fmt *fmt; - - fmt = aml_vdec_find_format(f); - if (!fmt) { - f->fmt.pix.pixelformat = aml_video_formats[CAP_FMT_IDX].fourcc; - fmt = aml_vdec_find_format(f); - } - - return vidioc_try_fmt(f, fmt); -} - -static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; - struct aml_video_fmt *fmt; - - fmt = aml_vdec_find_format(f); - if (!fmt) { - f->fmt.pix.pixelformat = aml_video_formats[OUT_FMT_IDX].fourcc; - fmt = aml_vdec_find_format(f); - } - - if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { - aml_v4l2_err("sizeimage of output format must be given"); - return -EINVAL; - } - - return vidioc_try_fmt(f, fmt); -} - -static int vidioc_vdec_g_selection(struct file *file, void *priv, - struct v4l2_selection *s) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - struct aml_q_data *q_data; - - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - q_data = &ctx->q_data[AML_Q_DATA_DST]; - - switch (s->target) { - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - s->r.left = 0; - s->r.top = 0; - s->r.width = ctx->picinfo.visible_width; - s->r.height = ctx->picinfo.visible_height; - break; - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - s->r.left = 0; - s->r.top = 0; - s->r.width = ctx->picinfo.coded_width; - s->r.height = ctx->picinfo.coded_height; - break; - case V4L2_SEL_TGT_COMPOSE: - if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) { - /* set to default value if header info not ready yet*/ - s->r.left = 0; - s->r.top = 0; - s->r.width = q_data->visible_width; - s->r.height = q_data->visible_height; - } - break; - default: - return -EINVAL; - } - - if (ctx->state < AML_STATE_PROBE) { - /* set to default value if header info not ready yet*/ - s->r.left = 0; - s->r.top = 0; - s->r.width = q_data->visible_width; - s->r.height = q_data->visible_height; - return 0; - } - - return 0; -} - -static int vidioc_vdec_s_selection(struct file *file, void *priv, - struct v4l2_selection *s) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - switch (s->target) { - case V4L2_SEL_TGT_COMPOSE: - s->r.left = 0; - s->r.top = 0; - s->r.width = ctx->picinfo.visible_width; - s->r.height = ctx->picinfo.visible_height; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int vidioc_vdec_s_fmt(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - struct v4l2_pix_format_mplane *pix_mp; - struct aml_q_data *q_data; - int ret = 0; - struct aml_video_fmt *fmt; - - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - - q_data = aml_vdec_get_q_data(ctx, f->type); - if (!q_data) - return -EINVAL; - - pix_mp = &f->fmt.pix_mp; - if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && - vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) { - aml_v4l2_err("[%d] out_q_ctx buffers already requested", ctx->id); - } - - if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && - vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) { - aml_v4l2_err("[%d] cap_q_ctx buffers already requested", ctx->id); - } - - fmt = aml_vdec_find_format(f); - if (fmt == NULL) { - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - f->fmt.pix.pixelformat = - aml_video_formats[OUT_FMT_IDX].fourcc; - fmt = aml_vdec_find_format(f); - } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - f->fmt.pix.pixelformat = - aml_video_formats[CAP_FMT_IDX].fourcc; - fmt = aml_vdec_find_format(f); - } - } - - q_data->fmt = fmt; - vidioc_try_fmt(f, q_data->fmt); - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage; - q_data->coded_width = pix_mp->width; - q_data->coded_height = pix_mp->height; - - aml_v4l2_debug(4, "[%d] %s() [%d], w: %d, h: %d, size: %d", - ctx->id, __func__, __LINE__, pix_mp->width, pix_mp->height, - pix_mp->plane_fmt[0].sizeimage); - - ctx->colorspace = f->fmt.pix_mp.colorspace; - ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; - ctx->quantization = f->fmt.pix_mp.quantization; - ctx->xfer_func = f->fmt.pix_mp.xfer_func; - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_IDLE) { - ret = vdec_if_init(ctx, q_data->fmt->fourcc); - if (ret) { - aml_v4l2_err("[%d]: vdec_if_init() fail ret=%d", - ctx->id, ret); - mutex_unlock(&ctx->state_lock); - return -EINVAL; - } - ctx->state = AML_STATE_INIT; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)", - ctx->id, __func__); - } - mutex_unlock(&ctx->state_lock); - } - - return 0; -} - -static int vidioc_enum_framesizes(struct file *file, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - int i = 0; - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - - if (fsize->index != 0) - return -EINVAL; - - for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) { - if (fsize->pixel_format != aml_vdec_framesizes[i].fourcc) - continue; - - fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - fsize->stepwise = aml_vdec_framesizes[i].stepwise; - if (!(ctx->dev->dec_capability & - VCODEC_CAPABILITY_4K_DISABLED)) { - aml_v4l2_debug(4, "[%d] 4K is enabled", ctx->id); - fsize->stepwise.max_width = - VCODEC_DEC_4K_CODED_WIDTH; - fsize->stepwise.max_height = - VCODEC_DEC_4K_CODED_HEIGHT; - } - aml_v4l2_debug(4, "[%d] %x, %d %d %d %d %d %d", - ctx->id, ctx->dev->dec_capability, - fsize->stepwise.min_width, - fsize->stepwise.max_width, - fsize->stepwise.step_width, - fsize->stepwise.min_height, - fsize->stepwise.max_height, - fsize->stepwise.step_height); - return 0; - } - - return -EINVAL; -} - -static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue) -{ - struct aml_video_fmt *fmt; - int i, j = 0; - - for (i = 0; i < NUM_FORMATS; i++) { - if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC)) - continue; - if (!output_queue && - (aml_video_formats[i].type != AML_FMT_FRAME)) - continue; - - if (j == f->index) - break; - ++j; - } - - if (i == NUM_FORMATS) - return -EINVAL; - - fmt = &aml_video_formats[i]; - f->pixelformat = fmt->fourcc; - - return 0; -} - -static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, - struct v4l2_fmtdesc *f) -{ - return vidioc_enum_fmt(f, false); -} - -static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - return vidioc_enum_fmt(f, true); -} - -static int vidioc_vdec_g_fmt(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); - struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct vb2_queue *vq; - struct aml_q_data *q_data; - - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); - if (!vq) { - aml_v4l2_err("[%d] no vb2 queue for type=%d", ctx->id, f->type); - return -EINVAL; - } - - q_data = aml_vdec_get_q_data(ctx, f->type); - - pix_mp->field = V4L2_FIELD_NONE; - pix_mp->colorspace = ctx->colorspace; - pix_mp->ycbcr_enc = ctx->ycbcr_enc; - pix_mp->quantization = ctx->quantization; - pix_mp->xfer_func = ctx->xfer_func; - - if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && - (ctx->state >= AML_STATE_PROBE)) { - /* Until STREAMOFF is called on the CAPTURE queue - * (acknowledging the event), the driver operates as if - * the resolution hasn't changed yet. - * So we just return picinfo yet, and update picinfo in - * stop_streaming hook function - */ - /* it is used for alloc the decode buffer size. */ - q_data->sizeimage[0] = ctx->picinfo.y_len_sz; - q_data->sizeimage[1] = ctx->picinfo.c_len_sz; - - /* it is used for alloc the EGL image buffer size. */ - q_data->coded_width = ctx->picinfo.coded_width; - q_data->coded_height = ctx->picinfo.coded_height; - - q_data->bytesperline[0] = ctx->picinfo.coded_width; - q_data->bytesperline[1] = ctx->picinfo.coded_height; - - /* - * Width and height are set to the dimensions - * of the movie, the buffer is bigger and - * further processing stages should crop to this - * rectangle. - */ - pix_mp->width = q_data->coded_width; - pix_mp->height = q_data->coded_height; - - /* - * Set pixelformat to the format in which mt vcodec - * outputs the decoded frame - */ - pix_mp->num_planes = q_data->fmt->num_planes; - pix_mp->pixelformat = q_data->fmt->fourcc; - pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; - pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; - pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; - pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; - } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - /* - * This is run on OUTPUT - * The buffer contains compressed image - * so width and height have no meaning. - * Assign value here to pass v4l2-compliance test - */ - pix_mp->width = q_data->visible_width; - pix_mp->height = q_data->visible_height; - pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; - pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; - pix_mp->pixelformat = q_data->fmt->fourcc; - pix_mp->num_planes = q_data->fmt->num_planes; - } else { - pix_mp->width = q_data->coded_width; - pix_mp->height = q_data->coded_height; - pix_mp->num_planes = q_data->fmt->num_planes; - pix_mp->pixelformat = q_data->fmt->fourcc; - pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; - pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; - pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; - pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; - - aml_v4l2_debug(4, "[%d] type=%d state=%d Format information could not be read, not ready yet!", - ctx->id, f->type, ctx->state); - } - - return 0; -} - -/*int vidioc_vdec_g_ctrl(struct file *file, void *fh, - struct v4l2_control *a) -{ - struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); - - if (a->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) - a->value = 20; - - return 0; -}*/ - -static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, - unsigned int *nplanes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vq); - struct aml_q_data *q_data; - unsigned int i; - - q_data = aml_vdec_get_q_data(ctx, vq->type); - - if (q_data == NULL) { - aml_v4l2_err("[%d] vq->type=%d err", ctx->id, vq->type); - return -EINVAL; - } - - if (*nplanes) { - for (i = 0; i < *nplanes; i++) { - if (sizes[i] < q_data->sizeimage[i]) - return -EINVAL; - //alloc_devs[i] = &ctx->dev->plat_dev->dev; - alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm - } - } else { - if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - *nplanes = 2; - else - *nplanes = 1; - - for (i = 0; i < *nplanes; i++) { - sizes[i] = q_data->sizeimage[i]; - //alloc_devs[i] = &ctx->dev->plat_dev->dev; - alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm - } - } - - pr_info("[%d] type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", - ctx->id, vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]); - - return 0; -} - -static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct aml_q_data *q_data; - int i; - - aml_v4l2_debug(4, "[%d] (%d) id=%d", - ctx->id, vb->vb2_queue->type, vb->index); - - q_data = aml_vdec_get_q_data(ctx, vb->vb2_queue->type); - - for (i = 0; i < q_data->fmt->num_planes; i++) { - if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { - aml_v4l2_err("[%d] data will not fit into plane %d (%lu < %d)", - ctx->id, i, vb2_plane_size(vb, i), - q_data->sizeimage[i]); - } - } - - return 0; -} - -static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf = NULL; - struct aml_vcodec_mem src_mem; - unsigned int dpb = 0; - - vb2_v4l2 = to_vb2_v4l2_buffer(vb); - buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - - aml_v4l2_debug(3, "[%d] %s(), vb: %p, type: %d, idx: %d, state: %d, used: %d", - ctx->id, __func__, vb, vb->vb2_queue->type, - vb->index, vb->state, buf->used); - /* - * check if this buffer is ready to be used after decode - */ - if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { - aml_v4l2_debug(3, "[%d] %s() [%d], y_va: %p, vf_h: %lx, state: %d", ctx->id, - __func__, __LINE__, buf->frame_buffer.base_y.va, - buf->frame_buffer.vf_handle, buf->frame_buffer.status); - - if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { - aml_v4l2_debug(3, "[%d] enque capture buf idx %d, %p\n", - ctx->id, vb->index, vb); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); - buf->que_in_m2m = true; - buf->queued_in_vb2 = true; - buf->queued_in_v4l2 = true; - buf->ready_to_display = false; - - /*save capture bufs to be used for resetting config.*/ - list_add(&buf->node, &ctx->capture_list); - } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { - buf->queued_in_vb2 = false; - buf->queued_in_v4l2 = true; - buf->ready_to_display = false; - - /* recycle vf */ - video_vf_put(ctx->ada_ctx->recv_name, - &buf->frame_buffer, ctx->id); - } - return; - } - - v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); - - if (ctx->state != AML_STATE_INIT) { - aml_v4l2_debug(4, "[%d] already init driver %d", - ctx->id, ctx->state); - return; - } - - vb2_v4l2 = to_vb2_v4l2_buffer(vb); - buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - if (buf->lastframe) { - /* This shouldn't happen. Just in case. */ - aml_v4l2_err("[%d] Invalid flush buffer.", ctx->id); - v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - return; - } - - src_mem.va = vb2_plane_vaddr(vb, 0); - src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - src_mem.size = (size_t)vb->planes[0].bytesused; - if (vdec_if_probe(ctx, &src_mem, NULL)) - return; - - if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) { - pr_err("[%d] GET_PARAM_PICTURE_INFO err\n", ctx->id); - return; - } - - if (vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpb)) { - pr_err("[%d] GET_PARAM_DPB_SIZE err\n", ctx->id); - return; - } - - ctx->dpb_size = dpb; - ctx->last_decoded_picinfo = ctx->picinfo; - aml_vdec_queue_res_chg_event(ctx); - - mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_INIT) { - ctx->state = AML_STATE_PROBE; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", - ctx->id, __func__); - } - mutex_unlock(&ctx->state_lock); -} - -static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf = NULL; - bool buf_error; - - vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); - buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - - //mutex_lock(&ctx->lock); - if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - buf->queued_in_v4l2 = false; - buf->queued_in_vb2 = false; - } - buf_error = buf->error; - //mutex_unlock(&ctx->lock); - - if (buf_error) { - aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); - ctx->state = AML_STATE_ABORT; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", - ctx->id, __func__); - } -} - -static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb, - struct vb2_v4l2_buffer, vb2_buf); - struct aml_video_dec_buf *buf = container_of(vb2_v4l2, - struct aml_video_dec_buf, vb); - unsigned int size, phy_addr = 0; - char *owner = __getname(); - - aml_v4l2_debug(4, "[%d] (%d) id=%d", - ctx->id, vb->vb2_queue->type, vb->index); - - if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - buf->used = false; - buf->ready_to_display = false; - buf->queued_in_v4l2 = false; - buf->frame_buffer.status = FB_ST_NORMAL; - } else { - buf->lastframe = false; - } - - /* codec_mm buffers count */ - if (V4L2_TYPE_IS_OUTPUT(vb->type)) { - size = vb->planes[0].length; - phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id); - strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); - buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; - - buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, - phy_addr, size, vb->index); - aml_v4l2_debug(3, "[%d] IN alloc, addr: %x, size: %u, idx: %u", - ctx->id, phy_addr, size, vb->index); - } else { - size = vb->planes[0].length; - phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id); - strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); - buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; - - buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, - phy_addr, size, vb->index); - aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", - ctx->id, phy_addr, size, vb->index); - - size = vb->planes[1].length; - phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); - buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, - phy_addr, size, vb->index); - aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", - ctx->id, phy_addr, size, vb->index); - } - - __putname(owner); - - return 0; -} - -static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf = NULL; - int i; - - for (i = 0; i < q->num_buffers; ++i) { - vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); - buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - if (IS_ERR_OR_NULL(buf->mem[0])) - return; - - if (V4L2_TYPE_IS_OUTPUT(q->bufs[i]->type)) { - v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); - - aml_v4l2_debug(3, "[%d] IN clean, addr: %lx, size: %u, idx: %u", - ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); - buf->mem[0] = NULL; - continue; - } - - v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); - v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); - - aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", - ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); - aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", - ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); - buf->mem[0] = NULL; - buf->mem[1] = NULL; - } -} - -static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); - - ctx->has_receive_eos = false; - v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true); - - return 0; -} - -static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) -{ - struct aml_video_dec_buf *buf = NULL; - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); - int i; - - aml_v4l2_debug(3, "[%d] (%d) state=(%x) frame_cnt=%d", - ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt); - - codec_mm_bufs_cnt_clean(q); - - if (V4L2_TYPE_IS_OUTPUT(q->type)) { - while (v4l2_m2m_src_buf_remove(ctx->m2m_ctx)); - return; - } - - while (v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)); - - for (i = 0; i < q->num_buffers; ++i) { - if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { - q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; - atomic_dec(&q->owned_by_drv_count); - } - vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); - buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - buf->frame_buffer.status = FB_ST_FREE; - } -} - -static void m2mops_vdec_device_run(void *priv) -{ - struct aml_vcodec_ctx *ctx = priv; - struct aml_vcodec_dev *dev = ctx->dev; - - aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - - queue_work(dev->decode_workqueue, &ctx->decode_work); -} - -void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) -{ - aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - - if (ctx->state < AML_STATE_ACTIVE || - ctx->state > AML_STATE_FLUSHED) - return; - - aml_thread_notify(ctx, AML_THREAD_CAPTURE); -} - -static int m2mops_vdec_job_ready(void *m2m_priv) -{ - struct aml_vcodec_ctx *ctx = m2m_priv; - - aml_v4l2_debug(4, "[%d] %s(), state: %d", ctx->id, - __func__, ctx->state); - - if (ctx->state < AML_STATE_PROBE || - ctx->state > AML_STATE_FLUSHED) - return 0; - - return 1; -} - -static void m2mops_vdec_job_abort(void *priv) -{ - struct aml_vcodec_ctx *ctx = priv; - - aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - - ctx->state = AML_STATE_ABORT; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", - ctx->id, __func__); - - wake_up(&ctx->m2m_ctx->finished); -} - -static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) -{ - struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl); - int ret = 0; - - aml_v4l2_debug(4, "%s() [%d]", __func__, __LINE__); - - switch (ctrl->id) { - case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - if (ctx->state >= AML_STATE_PROBE) { - ctrl->val = ctx->dpb_size; - } else { - pr_err("Seqinfo not ready.\n"); - ctrl->val = 0; - } - break; - default: - ret = -EINVAL; - } - return ret; -} - -static const struct v4l2_ctrl_ops aml_vcodec_dec_ctrl_ops = { - .g_volatile_ctrl = aml_vdec_g_v_ctrl, -}; - -int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx) -{ - struct v4l2_ctrl *ctrl; - - v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1); - - ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl, - &aml_vcodec_dec_ctrl_ops, - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, - 0, 32, 1, 1); - ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - - if (ctx->ctrl_hdl.error) { - aml_v4l2_err("[%d] Adding control failed %d", - ctx->id, ctx->ctrl_hdl.error); - return ctx->ctrl_hdl.error; - } - - v4l2_ctrl_handler_setup(&ctx->ctrl_hdl); - return 0; -} - -static void m2mops_vdec_lock(void *m2m_priv) -{ - struct aml_vcodec_ctx *ctx = m2m_priv; - - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - mutex_lock(&ctx->dev->dev_mutex); -} - -static void m2mops_vdec_unlock(void *m2m_priv) -{ - struct aml_vcodec_ctx *ctx = m2m_priv; - - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - mutex_unlock(&ctx->dev->dev_mutex); -} - -const struct v4l2_m2m_ops aml_vdec_m2m_ops = { - .device_run = m2mops_vdec_device_run, - .job_ready = m2mops_vdec_job_ready, - .job_abort = m2mops_vdec_job_abort, - .lock = m2mops_vdec_lock, - .unlock = m2mops_vdec_unlock, -}; - -static const struct vb2_ops aml_vdec_vb2_ops = { - .queue_setup = vb2ops_vdec_queue_setup, - .buf_prepare = vb2ops_vdec_buf_prepare, - .buf_queue = vb2ops_vdec_buf_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .buf_init = vb2ops_vdec_buf_init, - .buf_finish = vb2ops_vdec_buf_finish, - .start_streaming = vb2ops_vdec_start_streaming, - .stop_streaming = vb2ops_vdec_stop_streaming, -}; - -const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = { - .vidioc_streamon = vidioc_decoder_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, - .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, - .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//?? - //.vidioc_g_ctrl = vidioc_vdec_g_ctrl, - - .vidioc_qbuf = vidioc_vdec_qbuf, - .vidioc_dqbuf = vidioc_vdec_dqbuf, - - .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, - .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out_mplane, - - .vidioc_s_fmt_vid_cap_mplane = vidioc_vdec_s_fmt, - .vidioc_s_fmt_vid_out_mplane = vidioc_vdec_s_fmt, - .vidioc_g_fmt_vid_cap_mplane = vidioc_vdec_g_fmt, - .vidioc_g_fmt_vid_out_mplane = vidioc_vdec_g_fmt, - - .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - - .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - - .vidioc_querycap = vidioc_vdec_querycap, - .vidioc_subscribe_event = vidioc_vdec_subscribe_evt, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_selection = vidioc_vdec_g_selection, - .vidioc_s_selection = vidioc_vdec_s_selection, - - .vidioc_decoder_cmd = vidioc_decoder_cmd, - .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd, -}; - -int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - struct aml_vcodec_ctx *ctx = priv; - int ret = 0; - - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - src_vq->io_modes = VB2_DMABUF | VB2_MMAP; - src_vq->drv_priv = ctx; - src_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); - src_vq->ops = &aml_vdec_vb2_ops; - src_vq->mem_ops = &vb2_dma_contig_memops; - src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = &ctx->dev->dev_mutex; - - ret = vb2_queue_init(src_vq); - if (ret) { - aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(output)", ctx->id); - return ret; - } - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; - dst_vq->drv_priv = ctx; - dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); - dst_vq->ops = &aml_vdec_vb2_ops; - dst_vq->mem_ops = &vb2_dma_contig_memops; - dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - dst_vq->lock = &ctx->dev->dev_mutex; - - ret = vb2_queue_init(dst_vq); - if (ret) { - vb2_queue_release(src_vq); - aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(capture)", ctx->id); - } - - return ret; -} - diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h deleted file mode 100644 index 6f884c4321ed..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _AML_VCODEC_DEC_H_ -#define _AML_VCODEC_DEC_H_ - -#include -#include -#include - -#define VCODEC_CAPABILITY_4K_DISABLED 0x10 -#define VCODEC_DEC_4K_CODED_WIDTH 4096U -#define VCODEC_DEC_4K_CODED_HEIGHT 2304U -#define AML_VDEC_MAX_W 2048U -#define AML_VDEC_MAX_H 1088U - -#define AML_VDEC_IRQ_STATUS_DEC_SUCCESS 0x10000 -#define V4L2_BUF_FLAG_LAST 0x00100000 - -/** - * struct vdec_fb - decoder frame buffer - * @base_y : Y plane memory info - * @base_c : C plane memory info - * @status : frame buffer status (vdec_fb_status) - */ -struct vdec_fb { - unsigned long vf_handle; - struct aml_vcodec_mem base_y; - struct aml_vcodec_mem base_c; - unsigned int status; -}; - -/** - * struct aml_video_dec_buf - Private data related to each VB2 buffer. - * @b: VB2 buffer - * @list: link list - * @used: Capture buffer contain decoded frame data and keep in - * codec data structure - * @ready_to_display: Capture buffer not display yet - * @queued_in_vb2: Capture buffer is queue in vb2 - * @queued_in_v4l2: Capture buffer is in v4l2 driver, but not in vb2 - * queue yet - * @lastframe: Intput buffer is last buffer - EOS - * @error: An unrecoverable error occurs on this buffer. - * @frame_buffer: Decode status, and buffer information of Capture buffer - * - * Note : These status information help us track and debug buffer state - */ -struct aml_video_dec_buf { - struct vb2_v4l2_buffer vb; - struct list_head list; - - struct vdec_fb frame_buffer; - struct codec_mm_s *mem[2]; - char mem_onwer[32]; - struct list_head node; - bool used; - bool ready_to_display; - bool que_in_m2m; - bool queued_in_vb2; - bool queued_in_v4l2; - bool lastframe; - bool error; -}; - -extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops; -extern const struct v4l2_m2m_ops aml_vdec_m2m_ops; - - -/* - * aml_vdec_lock/aml_vdec_unlock are for ctx instance to - * get/release lock before/after access decoder hw. - * aml_vdec_lock get decoder hw lock and set curr_ctx - * to ctx instance that get lock - */ -void aml_vdec_unlock(struct aml_vcodec_ctx *ctx); -void aml_vdec_lock(struct aml_vcodec_ctx *ctx); -int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq); -void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx); -void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx); -int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx); - -void vdec_device_vf_run(struct aml_vcodec_ctx *ctx); - -void try_to_capture(struct aml_vcodec_ctx *ctx); -void aml_thread_notify(struct aml_vcodec_ctx *ctx, - enum aml_thread_type type); -int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, - enum aml_thread_type type, const char *thread_name); -void aml_thread_stop(struct aml_vcodec_ctx *ctx); - -#endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c deleted file mode 100644 index 53b25c492605..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c +++ /dev/null @@ -1,345 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "aml_vcodec_drv.h" -#include "aml_vcodec_dec.h" -#include "aml_vcodec_dec_pm.h" -//#include "aml_vcodec_intr.h" -#include "aml_vcodec_util.h" -#include "aml_vcodec_vfm.h" - -#define VDEC_HW_ACTIVE 0x10 -#define VDEC_IRQ_CFG 0x11 -#define VDEC_IRQ_CLR 0x10 -#define VDEC_IRQ_CFG_REG 0xa4 - -module_param(aml_v4l2_dbg_level, int, 0644); -module_param(aml_vcodec_dbg, bool, 0644); - -static int fops_vcodec_open(struct file *file) -{ - struct aml_vcodec_dev *dev = video_drvdata(file); - struct aml_vcodec_ctx *ctx = NULL; - struct aml_video_dec_buf *aml_buf = NULL; - int ret = 0; - struct vb2_queue *src_vq; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - aml_buf = kzalloc(sizeof(*aml_buf), GFP_KERNEL); - if (!aml_buf) { - kfree(ctx); - return -ENOMEM; - } - - mutex_lock(&dev->dev_mutex); - ctx->empty_flush_buf = aml_buf; - ctx->id = dev->id_counter++; - v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); - INIT_LIST_HEAD(&ctx->list); - INIT_LIST_HEAD(&ctx->capture_list); - INIT_LIST_HEAD(&ctx->vdec_thread_list); - dev->filp = file; - ctx->dev = dev; - init_waitqueue_head(&ctx->queue); - mutex_init(&ctx->state_lock); - mutex_init(&ctx->lock); - init_waitqueue_head(&ctx->wq); - - ctx->type = AML_INST_DECODER; - ret = aml_vcodec_dec_ctrls_setup(ctx); - if (ret) { - aml_v4l2_err("Failed to setup vcodec controls"); - goto err_ctrls_setup; - } - ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, - &aml_vcodec_dec_queue_init); - if (IS_ERR((__force void *)ctx->m2m_ctx)) { - ret = PTR_ERR((__force void *)ctx->m2m_ctx); - aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret); - goto err_m2m_ctx_init; - } - src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq; - ctx->empty_flush_buf->lastframe = true; - aml_vcodec_dec_set_default_params(ctx); - - ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap"); - if (ret) { - aml_v4l2_err("Failed to creat capture thread."); - goto err_creat_thread; - } - - list_add(&ctx->list, &dev->ctx_list); - - mutex_unlock(&dev->dev_mutex); - pr_info("[%d] %s decoder\n", ctx->id, dev_name(&dev->plat_dev->dev)); - - return ret; - - /* Deinit when failure occurred */ -err_creat_thread: - v4l2_m2m_ctx_release(ctx->m2m_ctx); -err_m2m_ctx_init: - v4l2_ctrl_handler_free(&ctx->ctrl_hdl); -err_ctrls_setup: - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - kfree(ctx->empty_flush_buf); - kfree(ctx); - mutex_unlock(&dev->dev_mutex); - - return ret; -} - -static int fops_vcodec_release(struct file *file) -{ - struct aml_vcodec_dev *dev = video_drvdata(file); - struct aml_vcodec_ctx *ctx = fh_to_ctx(file->private_data); - - pr_info("[%d] release decoder\n", ctx->id); - mutex_lock(&dev->dev_mutex); - - /* - * Call v4l2_m2m_ctx_release before aml_vcodec_dec_release. First, it - * makes sure the worker thread is not running after vdec_if_deinit. - * Second, the decoder will be flushed and all the buffers will be - * returned in stop_streaming. - */ - aml_vcodec_dec_release(ctx); - v4l2_m2m_ctx_release(ctx->m2m_ctx); - - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - v4l2_ctrl_handler_free(&ctx->ctrl_hdl); - - aml_thread_stop(ctx); - - list_del_init(&ctx->list); - kfree(ctx->empty_flush_buf); - kfree(ctx); - mutex_unlock(&dev->dev_mutex); - return 0; -} - -static const struct v4l2_file_operations aml_vcodec_fops = { - .owner = THIS_MODULE, - .open = fops_vcodec_open, - .release = fops_vcodec_release, - .poll = v4l2_m2m_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = v4l2_m2m_fop_mmap, -}; - -static int aml_vcodec_probe(struct platform_device *pdev) -{ - struct aml_vcodec_dev *dev; - struct video_device *vfd_dec; - int ret = 0; - - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - INIT_LIST_HEAD(&dev->ctx_list); - dev->plat_dev = pdev; - - mutex_init(&dev->dec_mutex); - mutex_init(&dev->dev_mutex); - spin_lock_init(&dev->irqlock); - - snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", - "[/AML_V4L2_VDEC]"); - - ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); - if (ret) { - aml_v4l2_err("v4l2_device_register err=%d", ret); - goto err_res; - } - - init_waitqueue_head(&dev->queue); - - vfd_dec = video_device_alloc(); - if (!vfd_dec) { - aml_v4l2_err("Failed to allocate video device"); - ret = -ENOMEM; - goto err_dec_alloc; - } - - vfd_dec->fops = &aml_vcodec_fops; - vfd_dec->ioctl_ops = &aml_vdec_ioctl_ops; - vfd_dec->release = video_device_release; - vfd_dec->lock = &dev->dev_mutex; - vfd_dec->v4l2_dev = &dev->v4l2_dev; - vfd_dec->vfl_dir = VFL_DIR_M2M; - vfd_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | - V4L2_CAP_STREAMING; - - snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s", - AML_VCODEC_DEC_NAME); - video_set_drvdata(vfd_dec, dev); - dev->vfd_dec = vfd_dec; - platform_set_drvdata(pdev, dev); - - dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops); - if (IS_ERR((__force void *)dev->m2m_dev_dec)) { - aml_v4l2_err("Failed to init mem2mem dec device"); - ret = PTR_ERR((__force void *)dev->m2m_dev_dec); - goto err_dec_mem_init; - } - - dev->decode_workqueue = - alloc_ordered_workqueue(AML_VCODEC_DEC_NAME, - WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->decode_workqueue) { - aml_v4l2_err("Failed to create decode workqueue"); - ret = -EINVAL; - goto err_event_workq; - } - - dev->reset_workqueue = - alloc_ordered_workqueue("aml-vcodec-reset", - WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->reset_workqueue) { - aml_v4l2_err("Failed to create decode workqueue"); - ret = -EINVAL; - destroy_workqueue(dev->decode_workqueue); - goto err_event_workq; - } - - //dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); - - ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26); - if (ret) { - pr_err("Failed to register video device\n"); - goto err_dec_reg; - } - - pr_info("decoder registered as /dev/video%d\n", vfd_dec->num); - - return 0; - -err_dec_reg: - destroy_workqueue(dev->reset_workqueue); - destroy_workqueue(dev->decode_workqueue); -err_event_workq: - v4l2_m2m_release(dev->m2m_dev_dec); -err_dec_mem_init: - video_unregister_device(vfd_dec); -err_dec_alloc: - v4l2_device_unregister(&dev->v4l2_dev); -err_res: - - return ret; -} - -static const struct of_device_id aml_vcodec_match[] = { - {.compatible = "amlogic, vcodec-dec",}, - {}, -}; - -MODULE_DEVICE_TABLE(of, aml_vcodec_match); - -static int aml_vcodec_dec_remove(struct platform_device *pdev) -{ - struct aml_vcodec_dev *dev = platform_get_drvdata(pdev); - - flush_workqueue(dev->reset_workqueue); - destroy_workqueue(dev->reset_workqueue); - - flush_workqueue(dev->decode_workqueue); - destroy_workqueue(dev->decode_workqueue); - - if (dev->m2m_dev_dec) - v4l2_m2m_release(dev->m2m_dev_dec); - - if (dev->vfd_dec) - video_unregister_device(dev->vfd_dec); - - v4l2_device_unregister(&dev->v4l2_dev); - - return 0; -} - -/*static void aml_vcodec_dev_release(struct device *dev) -{ -}*/ - -static struct platform_driver aml_vcodec_dec_driver = { - .probe = aml_vcodec_probe, - .remove = aml_vcodec_dec_remove, - .driver = { - .name = AML_VCODEC_DEC_NAME, - .of_match_table = aml_vcodec_match, - }, -}; - -/* -static struct platform_device aml_vcodec_dec_device = { - .name = AML_VCODEC_DEC_NAME, - .dev.release = aml_vcodec_dev_release, -};*/ - -module_platform_driver(aml_vcodec_dec_driver); - -/* -static int __init amvdec_ports_init(void) -{ - int ret; - - ret = platform_device_register(&aml_vcodec_dec_device); - if (ret) - return ret; - - ret = platform_driver_register(&aml_vcodec_dec_driver); - if (ret) - platform_device_unregister(&aml_vcodec_dec_device); - - return ret; -} - -static void __exit amvdec_ports_exit(void) -{ - platform_driver_unregister(&aml_vcodec_dec_driver); - platform_device_unregister(&aml_vcodec_dec_device); -} - -module_init(amvdec_ports_init); -module_exit(amvdec_ports_exit); -*/ - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("AML video codec V4L2 decoder driver"); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c deleted file mode 100644 index c801e871b397..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c +++ /dev/null @@ -1,206 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include - -#include "aml_vcodec_dec_pm.h" -#include "aml_vcodec_util.h" -//#include "aml_vpu.h" - -int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *amldev) -{ - struct device_node *node; - struct platform_device *pdev; - struct aml_vcodec_pm *pm; - int ret = 0; - - pdev = amldev->plat_dev; - pm = &amldev->pm; - pm->amldev = amldev; - node = of_parse_phandle(pdev->dev.of_node, "larb", 0); - if (!node) { - aml_v4l2_err("of_parse_phandle larb fail!"); - return -1; - } - - pdev = of_find_device_by_node(node); - if (WARN_ON(!pdev)) { - of_node_put(node); - return -1; - } - pm->larbvdec = &pdev->dev; - pdev = amldev->plat_dev; - pm->dev = &pdev->dev; - - pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll"); - if (IS_ERR(pm->vcodecpll)) { - aml_v4l2_err("devm_clk_get vcodecpll fail"); - ret = PTR_ERR(pm->vcodecpll); - } - - pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2"); - if (IS_ERR(pm->univpll_d2)) { - aml_v4l2_err("devm_clk_get univpll_d2 fail"); - ret = PTR_ERR(pm->univpll_d2); - } - - pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel"); - if (IS_ERR(pm->clk_cci400_sel)) { - aml_v4l2_err("devm_clk_get clk_cci400_sel fail"); - ret = PTR_ERR(pm->clk_cci400_sel); - } - - pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel"); - if (IS_ERR(pm->vdec_sel)) { - aml_v4l2_err("devm_clk_get vdec_sel fail"); - ret = PTR_ERR(pm->vdec_sel); - } - - pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll"); - if (IS_ERR(pm->vdecpll)) { - aml_v4l2_err("devm_clk_get vdecpll fail"); - ret = PTR_ERR(pm->vdecpll); - } - - pm->vencpll = devm_clk_get(&pdev->dev, "vencpll"); - if (IS_ERR(pm->vencpll)) { - aml_v4l2_err("devm_clk_get vencpll fail"); - ret = PTR_ERR(pm->vencpll); - } - - pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel"); - if (IS_ERR(pm->venc_lt_sel)) { - aml_v4l2_err("devm_clk_get venc_lt_sel fail"); - ret = PTR_ERR(pm->venc_lt_sel); - } - - pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src"); - if (IS_ERR(pm->vdec_bus_clk_src)) { - aml_v4l2_err("devm_clk_get vdec_bus_clk_src"); - ret = PTR_ERR(pm->vdec_bus_clk_src); - } - - pm_runtime_enable(&pdev->dev); - - return ret; -} - -void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev) -{ - pm_runtime_disable(dev->pm.dev); -} - -void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm) -{ - int ret; - - ret = pm_runtime_get_sync(pm->dev); - if (ret) - aml_v4l2_err("pm_runtime_get_sync fail %d", ret); -} - -void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm) -{ - int ret; - - ret = pm_runtime_put_sync(pm->dev); - if (ret) - aml_v4l2_err("pm_runtime_put_sync fail %d", ret); -} - -void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm) -{ - int ret; - - ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000); - if (ret) - aml_v4l2_err("clk_set_rate vcodecpll fail %d", ret); - - ret = clk_set_rate(pm->vencpll, 800 * 1000000); - if (ret) - aml_v4l2_err("clk_set_rate vencpll fail %d", ret); - - ret = clk_prepare_enable(pm->vcodecpll); - if (ret) - aml_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret); - - ret = clk_prepare_enable(pm->vencpll); - if (ret) - aml_v4l2_err("clk_prepare_enable vencpll fail %d", ret); - - ret = clk_prepare_enable(pm->vdec_bus_clk_src); - if (ret) - aml_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d", - ret); - - ret = clk_prepare_enable(pm->venc_lt_sel); - if (ret) - aml_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret); - - ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src); - if (ret) - aml_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d", - ret); - - ret = clk_prepare_enable(pm->univpll_d2); - if (ret) - aml_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret); - - ret = clk_prepare_enable(pm->clk_cci400_sel); - if (ret) - aml_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret); - - ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2); - if (ret) - aml_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d", - ret); - - ret = clk_prepare_enable(pm->vdecpll); - if (ret) - aml_v4l2_err("clk_prepare_enable vdecpll fail %d", ret); - - ret = clk_prepare_enable(pm->vdec_sel); - if (ret) - aml_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret); - - ret = clk_set_parent(pm->vdec_sel, pm->vdecpll); - if (ret) - aml_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret); - - //ret = aml_smi_larb_get(pm->larbvdec); - if (ret) - aml_v4l2_err("aml_smi_larb_get larbvdec fail %d", ret); - -} - -void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm) -{ - //aml_smi_larb_put(pm->larbvdec); - clk_disable_unprepare(pm->vdec_sel); - clk_disable_unprepare(pm->vdecpll); - clk_disable_unprepare(pm->univpll_d2); - clk_disable_unprepare(pm->clk_cci400_sel); - clk_disable_unprepare(pm->venc_lt_sel); - clk_disable_unprepare(pm->vdec_bus_clk_src); - clk_disable_unprepare(pm->vencpll); - clk_disable_unprepare(pm->vcodecpll); -} diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h deleted file mode 100644 index ccdf313f0ca8..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - -#ifndef _AML_VCODEC_DEC_PM_H_ -#define _AML_VCODEC_DEC_PM_H_ - -#include "aml_vcodec_drv.h" - -int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *dev); -void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev); - -void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm); -void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm); -void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm); -void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm); - -#endif /* _AML_VCODEC_DEC_PM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h deleted file mode 100644 index 4b638992af93..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h +++ /dev/null @@ -1,428 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _AML_VCODEC_DRV_H_ -#define _AML_VCODEC_DRV_H_ - -#include -#include -#include -#include -#include -#include -#include "aml_vcodec_util.h" - -#define AML_VCODEC_DRV_NAME "aml_vcodec_drv" -#define AML_VCODEC_DEC_NAME "aml-vcodec-dec" -#define AML_VCODEC_ENC_NAME "aml-vcodec-enc" -#define AML_PLATFORM_STR "platform:amlogic" - -#define AML_VCODEC_MAX_PLANES 3 -#define AML_V4L2_BENCHMARK 0 -#define WAIT_INTR_TIMEOUT_MS 1000 - -/** - * enum aml_hw_reg_idx - AML hw register base index - */ -enum aml_hw_reg_idx { - VDEC_SYS, - VDEC_MISC, - VDEC_LD, - VDEC_TOP, - VDEC_CM, - VDEC_AD, - VDEC_AV, - VDEC_PP, - VDEC_HWD, - VDEC_HWQ, - VDEC_HWB, - VDEC_HWG, - NUM_MAX_VDEC_REG_BASE, - /* h264 encoder */ - VENC_SYS = NUM_MAX_VDEC_REG_BASE, - /* vp8 encoder */ - VENC_LT_SYS, - NUM_MAX_VCODEC_REG_BASE -}; - -/** - * enum aml_instance_type - The type of an AML Vcodec instance. - */ -enum aml_instance_type { - AML_INST_DECODER = 0, - AML_INST_ENCODER = 1, -}; - -/** - * enum aml_instance_state - The state of an AML Vcodec instance. - * @AML_STATE_IDLE - default state when instance is created - * @AML_STATE_INIT - vcodec instance is initialized - * @AML_STATE_PROBE - vdec/venc had sps/pps header parsed/encoded - * @AML_STATE_ACTIVE - vdec is ready for work. - * @AML_STATE_FLUSHING - vdec is flushing. Only used by decoder - * @AML_STATE_FLUSHED - decoder has transacted the last frame. - * @AML_STATE_RESET - decoder has be reset after flush. - * @AML_STATE_ABORT - vcodec should be aborted - */ -enum aml_instance_state { - AML_STATE_IDLE, - AML_STATE_INIT, - AML_STATE_PROBE, - AML_STATE_READY, - AML_STATE_ACTIVE, - AML_STATE_FLUSHING, - AML_STATE_FLUSHED, - AML_STATE_RESET, - AML_STATE_ABORT, -}; - -/** - * struct aml_encode_param - General encoding parameters type - */ -enum aml_encode_param { - AML_ENCODE_PARAM_NONE = 0, - AML_ENCODE_PARAM_BITRATE = (1 << 0), - AML_ENCODE_PARAM_FRAMERATE = (1 << 1), - AML_ENCODE_PARAM_INTRA_PERIOD = (1 << 2), - AML_ENCODE_PARAM_FORCE_INTRA = (1 << 3), - AML_ENCODE_PARAM_GOP_SIZE = (1 << 4), -}; - -enum aml_fmt_type { - AML_FMT_DEC = 0, - AML_FMT_ENC = 1, - AML_FMT_FRAME = 2, -}; - -/** - * struct aml_video_fmt - Structure used to store information about pixelformats - */ -struct aml_video_fmt { - u32 fourcc; - enum aml_fmt_type type; - u32 num_planes; -}; - -/** - * struct aml_codec_framesizes - Structure used to store information about - * framesizes - */ -struct aml_codec_framesizes { - u32 fourcc; - struct v4l2_frmsize_stepwise stepwise; -}; - -/** - * struct aml_q_type - Type of queue - */ -enum aml_q_type { - AML_Q_DATA_SRC = 0, - AML_Q_DATA_DST = 1, -}; - -/** - * struct aml_q_data - Structure used to store information about queue - */ -struct aml_q_data { - unsigned int visible_width; - unsigned int visible_height; - unsigned int coded_width; - unsigned int coded_height; - enum v4l2_field field; - unsigned int bytesperline[AML_VCODEC_MAX_PLANES]; - unsigned int sizeimage[AML_VCODEC_MAX_PLANES]; - struct aml_video_fmt *fmt; -}; - -/** - * struct aml_enc_params - General encoding parameters - * @bitrate: target bitrate in bits per second - * @num_b_frame: number of b frames between p-frame - * @rc_frame: frame based rate control - * @rc_mb: macroblock based rate control - * @seq_hdr_mode: H.264 sequence header is encoded separately or joined - * with the first frame - * @intra_period: I frame period - * @gop_size: group of picture size, it's used as the intra frame period - * @framerate_num: frame rate numerator. ex: framerate_num=30 and - * framerate_denom=1 menas FPS is 30 - * @framerate_denom: frame rate denominator. ex: framerate_num=30 and - * framerate_denom=1 menas FPS is 30 - * @h264_max_qp: Max value for H.264 quantization parameter - * @h264_profile: V4L2 defined H.264 profile - * @h264_level: V4L2 defined H.264 level - * @force_intra: force/insert intra frame - */ -struct aml_enc_params { - unsigned int bitrate; - unsigned int num_b_frame; - unsigned int rc_frame; - unsigned int rc_mb; - unsigned int seq_hdr_mode; - unsigned int intra_period; - unsigned int gop_size; - unsigned int framerate_num; - unsigned int framerate_denom; - unsigned int h264_max_qp; - unsigned int h264_profile; - unsigned int h264_level; - unsigned int force_intra; -}; - -/** - * struct aml_vcodec_pm - Power management data structure - */ -struct aml_vcodec_pm { - struct clk *vdec_bus_clk_src; - struct clk *vencpll; - - struct clk *vcodecpll; - struct clk *univpll_d2; - struct clk *clk_cci400_sel; - struct clk *vdecpll; - struct clk *vdec_sel; - struct clk *vencpll_d2; - struct clk *venc_sel; - struct clk *univpll1_d2; - struct clk *venc_lt_sel; - struct device *larbvdec; - struct device *larbvenc; - struct device *larbvenclt; - struct device *dev; - struct aml_vcodec_dev *amldev; -}; - -/** - * struct vdec_pic_info - picture size information - * @visible_width: picture width - * @visible_height: picture height - * @coded_width: picture buffer width (64 aligned up from pic_w) - * @coded_height: picture buffer heiht (64 aligned up from pic_h) - * @y_bs_sz: Y bitstream size - * @c_bs_sz: CbCr bitstream size - * @y_len_sz: additional size required to store decompress information for y - * plane - * @c_len_sz: additional size required to store decompress information for cbcr - * plane - * E.g. suppose picture size is 176x144, - * buffer size will be aligned to 176x160. - */ -struct vdec_pic_info { - unsigned int visible_width; - unsigned int visible_height; - unsigned int coded_width; - unsigned int coded_height; - unsigned int y_bs_sz; - unsigned int c_bs_sz; - unsigned int y_len_sz; - unsigned int c_len_sz; -}; - -enum aml_thread_type { - AML_THREAD_OUTPUT, - AML_THREAD_CAPTURE, -}; - -typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx); - -struct aml_vdec_thread { - struct list_head node; - spinlock_t lock; - struct semaphore sem; - struct task_struct *task; - enum aml_thread_type type; - void *priv; - int stop; - - aml_thread_func func; -}; - -/** - * struct aml_vcodec_ctx - Context (instance) private data. - * - * @type: type of the instance - decoder or encoder - * @dev: pointer to the aml_vcodec_dev of the device - * @list: link to ctx_list of aml_vcodec_dev - * @fh: struct v4l2_fh - * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context - * @q_data: store information of input and output queue - * of the context - * @id: index of the context that this structure describes - * @state: state of the context - * @param_change: indicate encode parameter type - * @enc_params: encoding parameters - * @dec_if: hooked decoder driver interface - * @enc_if: hoooked encoder driver interface - * @drv_handle: driver handle for specific decode/encode instance - * - * @picinfo: store picture info after header parsing - * @dpb_size: store dpb count after header parsing - * @int_cond: variable used by the waitqueue - * @int_type: type of the last interrupt - * @queue: waitqueue that can be used to wait for this context to - * finish - * @irq_status: irq status - * - * @ctrl_hdl: handler for v4l2 framework - * @decode_work: worker for the decoding - * @encode_work: worker for the encoding - * @last_decoded_picinfo: pic information get from latest decode - * @empty_flush_buf: a fake size-0 capture buffer that indicates flush - * - * @colorspace: enum v4l2_colorspace; supplemental to pixelformat - * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding - * @quantization: enum v4l2_quantization, colorspace quantization - * @xfer_func: enum v4l2_xfer_func, colorspace transfer function - * @lock: protect variables accessed by V4L2 threads and worker thread such as - * aml_video_dec_buf. - */ -struct aml_vcodec_ctx { - enum aml_instance_type type; - struct aml_vcodec_dev *dev; - struct list_head list; - - struct v4l2_fh fh; - struct v4l2_m2m_ctx *m2m_ctx; - struct aml_vdec_adapt *ada_ctx; - struct aml_q_data q_data[2]; - int id; - struct mutex state_lock; - enum aml_instance_state state; - enum aml_encode_param param_change; - struct aml_enc_params enc_params; - - const struct vdec_common_if *dec_if; - const struct venc_common_if *enc_if; - unsigned long drv_handle; - - struct vdec_pic_info picinfo; - int dpb_size; - - int int_cond; - int int_type; - wait_queue_head_t queue; - unsigned int irq_status; - - struct v4l2_ctrl_handler ctrl_hdl; - struct work_struct decode_work; - struct work_struct encode_work; - struct work_struct reset_work; - struct vdec_pic_info last_decoded_picinfo; - struct aml_video_dec_buf *empty_flush_buf; - - enum v4l2_colorspace colorspace; - enum v4l2_ycbcr_encoding ycbcr_enc; - enum v4l2_quantization quantization; - enum v4l2_xfer_func xfer_func; - - int decoded_frame_cnt; - struct mutex lock; - wait_queue_head_t wq; - bool has_receive_eos; - struct list_head capture_list; - struct list_head vdec_thread_list; -}; - -/** - * struct aml_vcodec_dev - driver data - * @v4l2_dev: V4L2 device to register video devices for. - * @vfd_dec: Video device for decoder - * @vfd_enc: Video device for encoder. - * - * @m2m_dev_dec: m2m device for decoder - * @m2m_dev_enc: m2m device for encoder. - * @plat_dev: platform device - * @vpu_plat_dev: aml vpu platform device - * @alloc_ctx: VB2 allocator context - * (for allocations without kernel mapping). - * @ctx_list: list of struct aml_vcodec_ctx - * @irqlock: protect data access by irq handler and work thread - * @curr_ctx: The context that is waiting for codec hardware - * - * @reg_base: Mapped address of AML Vcodec registers. - * - * @id_counter: used to identify current opened instance - * - * @encode_workqueue: encode work queue - * - * @int_cond: used to identify interrupt condition happen - * @int_type: used to identify what kind of interrupt condition happen - * @dev_mutex: video_device lock - * @queue: waitqueue for waiting for completion of device commands - * - * @dec_irq: decoder irq resource - * @enc_irq: h264 encoder irq resource - * @enc_lt_irq: vp8 encoder irq resource - * - * @dec_mutex: decoder hardware lock - * @enc_mutex: encoder hardware lock. - * - * @pm: power management control - * @dec_capability: used to identify decode capability, ex: 4k - * @enc_capability: used to identify encode capability - */ -struct aml_vcodec_dev { - struct v4l2_device v4l2_dev; - struct video_device *vfd_dec; - struct video_device *vfd_enc; - struct file *filp; - - struct v4l2_m2m_dev *m2m_dev_dec; - struct v4l2_m2m_dev *m2m_dev_enc; - struct platform_device *plat_dev; - struct platform_device *vpu_plat_dev;//?? - struct vb2_alloc_ctx *alloc_ctx;//?? - struct list_head ctx_list; - spinlock_t irqlock; - struct aml_vcodec_ctx *curr_ctx; - void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE]; - - unsigned long id_counter; - - struct workqueue_struct *decode_workqueue; - struct workqueue_struct *encode_workqueue; - struct workqueue_struct *reset_workqueue; - int int_cond; - int int_type; - struct mutex dev_mutex; - wait_queue_head_t queue; - - int dec_irq; - int enc_irq; - int enc_lt_irq; - - struct mutex dec_mutex; - struct mutex enc_mutex; - - struct aml_vcodec_pm pm; - unsigned int dec_capability; - unsigned int enc_capability; -}; - -static inline struct aml_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh) -{ - return container_of(fh, struct aml_vcodec_ctx, fh); -} - -static inline struct aml_vcodec_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) -{ - return container_of(ctrl->handler, struct aml_vcodec_ctx, ctrl_hdl); -} - -#endif /* _AML_VCODEC_DRV_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c deleted file mode 100644 index 0026c6a2ad40..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include - -#include "aml_vcodec_drv.h" -#include "aml_vcodec_util.h" -//#include "aml_vpu.h" - -/* For encoder, this will enable logs in venc/*/ -bool aml_vcodec_dbg; -EXPORT_SYMBOL(aml_vcodec_dbg); - -/* The log level of v4l2 encoder or decoder driver. - * That is, files under aml-vcodec/. - */ -int aml_v4l2_dbg_level; -EXPORT_SYMBOL(aml_v4l2_dbg_level); - -void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, - unsigned int reg_idx) -{ - struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; - - if (!data || reg_idx >= NUM_MAX_VCODEC_REG_BASE) { - aml_v4l2_err("Invalid arguments, reg_idx=%d", reg_idx); - return NULL; - } - return ctx->dev->reg_base[reg_idx]; -} -EXPORT_SYMBOL(aml_vcodec_get_reg_addr); - -int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, - struct aml_vcodec_mem *mem) -{ - unsigned long size = mem->size; - struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; - struct device *dev = &ctx->dev->plat_dev->dev; - - //mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); - mem->va = codec_mm_dma_alloc_coherent(dev_name(dev), size, - &mem->dma_addr, GFP_KERNEL, 0); - if (!mem->va) { - aml_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev), - size); - return -ENOMEM; - } - - memset(mem->va, 0, size); - - aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); - aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, - (unsigned long)mem->dma_addr); - aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); - - return 0; -} -EXPORT_SYMBOL(aml_vcodec_mem_alloc); - -void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, - struct aml_vcodec_mem *mem) -{ - unsigned long size = mem->size; - struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; - struct device *dev = &ctx->dev->plat_dev->dev; - - if (!mem->va) { - aml_v4l2_err("%s dma_free size=%ld failed!", dev_name(dev), - size); - return; - } - - aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); - aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, - (unsigned long)mem->dma_addr); - aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); - - dma_free_coherent(dev, size, mem->va, mem->dma_addr); - mem->va = NULL; - mem->dma_addr = 0; - mem->size = 0; -} -EXPORT_SYMBOL(aml_vcodec_mem_free); - -void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev, - struct aml_vcodec_ctx *ctx) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->irqlock, flags); - dev->curr_ctx = ctx; - spin_unlock_irqrestore(&dev->irqlock, flags); -} -EXPORT_SYMBOL(aml_vcodec_set_curr_ctx); - -struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev) -{ - unsigned long flags; - struct aml_vcodec_ctx *ctx; - - spin_lock_irqsave(&dev->irqlock, flags); - ctx = dev->curr_ctx; - spin_unlock_irqrestore(&dev->irqlock, flags); - return ctx; -} -EXPORT_SYMBOL(aml_vcodec_get_curr_ctx); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h deleted file mode 100644 index 894cfb24b89c..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _AML_VCODEC_UTIL_H_ -#define _AML_VCODEC_UTIL_H_ - -#include -#include -#include - -#define DEBUG - -struct aml_vcodec_mem { - size_t size; - void *va; - dma_addr_t dma_addr; - unsigned int bytes_used; -}; - -struct aml_vcodec_ctx; -struct aml_vcodec_dev; - -extern int aml_v4l2_dbg_level; -extern bool aml_vcodec_dbg; - - -#if defined(DEBUG) - -#define aml_v4l2_debug(level, fmt, args...) \ - do { \ - if (aml_v4l2_dbg_level >= level) \ - pr_info(fmt "\n", ##args); \ - } while (0) - -#define aml_v4l2_debug_enter() aml_v4l2_debug(3, "+") -#define aml_v4l2_debug_leave() aml_v4l2_debug(3, "-") - -#define aml_vcodec_debug(h, fmt, args...) \ - do { \ - if (aml_vcodec_dbg) \ - pr_info("[%d]: %s() " fmt "\n", \ - ((struct aml_vcodec_ctx *)h->ctx)->id, \ - __func__, ##args); \ - } while (0) - -#define aml_vcodec_debug_enter(h) aml_vcodec_debug(h, "+") -#define aml_vcodec_debug_leave(h) aml_vcodec_debug(h, "-") - -#else - -#define aml_v4l2_debug(level, fmt, args...) -#define aml_v4l2_debug_enter() -#define aml_v4l2_debug_leave() - -#define aml_vcodec_debug(h, fmt, args...) -#define aml_vcodec_debug_enter(h) -#define aml_vcodec_debug_leave(h) - -#endif - -#define aml_v4l2_err(fmt, args...) \ - pr_err("[ERR]" fmt "\n", ##args) - -#define aml_vcodec_err(h, fmt, args...) \ - pr_err("[ERR][%d]" fmt "\n", \ - ((struct aml_vcodec_ctx *)h->ctx)->id, ##args) - -void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, - unsigned int reg_idx); -int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, - struct aml_vcodec_mem *mem); -void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, - struct aml_vcodec_mem *mem); -void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev, - struct aml_vcodec_ctx *ctx); -struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev); - -#endif /* _AML_VCODEC_UTIL_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c deleted file mode 100644 index ac48b9c08330..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include "aml_vcodec_vfm.h" -#include "aml_vcodec_vfq.h" -#include "aml_vcodec_util.h" -#include "aml_vcodec_adapt.h" -#include - -#define RECEIVER_NAME "v4l2-video" -#define PROVIDER_NAME "v4l2-video" - -static struct vframe_s *vdec_vf_peek(void *op_arg) -{ - struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; - - return vfq_peek(&vfm->vf_que); -} - -static struct vframe_s *vdec_vf_get(void *op_arg) -{ - struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; - - return vfq_pop(&vfm->vf_que); -} - -static void vdec_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; - - vf_put(vf, vfm->recv_name); - vf_notify_provider(vfm->recv_name, VFRAME_EVENT_RECEIVER_PUT, NULL); -} - -static int vdec_event_cb(int type, void *data, void *private_data) -{ - - if (type & VFRAME_EVENT_RECEIVER_PUT) { - } else if (type & VFRAME_EVENT_RECEIVER_GET) { - } else if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) { - } - return 0; -} - -static int vdec_vf_states(struct vframe_states *states, void *op_arg) -{ - struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; - - states->vf_pool_size = POOL_SIZE; - states->buf_recycle_num = 0; - states->buf_free_num = POOL_SIZE - vfq_level(&vfm->vf_que); - states->buf_avail_num = vfq_level(&vfm->vf_que); - - return 0; -} - -void video_vf_put(char *receiver, struct vdec_fb *fb, int id) -{ - struct vframe_provider_s *vfp = vf_get_provider(receiver); - struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; - - aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d", - id, vfp->name, vf, vf->index); - - if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) - vf_put(vf, receiver); -} - -static const struct vframe_operations_s vf_provider = { - .peek = vdec_vf_peek, - .get = vdec_vf_get, - .put = vdec_vf_put, - .event_cb = vdec_event_cb, - .vf_states = vdec_vf_states, -}; - -static int video_receiver_event_fun(int type, void *data, void *private_data) -{ - int ret = 0; - struct vframe_states states; - struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data; - - //aml_v4l2_debug(4, "[%d] type: %d, vfm: %p", vfm->ctx->id, type, vfm); - - switch (type) { - case VFRAME_EVENT_PROVIDER_UNREG: { - if (vf_get_receiver(vfm->prov_name)) { - aml_v4l2_debug(4, "[%d] unreg %s provider.", - vfm->ctx->id, vfm->prov_name); - vf_unreg_provider(&vfm->vf_prov); - } - - break; - } - - case VFRAME_EVENT_PROVIDER_START: { - if (vf_get_receiver(vfm->prov_name)) { - aml_v4l2_debug(4, "[%d] reg %s provider.", - vfm->ctx->id, vfm->prov_name); - vf_provider_init(&vfm->vf_prov, vfm->prov_name, - &vf_provider, vfm); - vf_reg_provider(&vfm->vf_prov); - vf_notify_receiver(vfm->prov_name, - VFRAME_EVENT_PROVIDER_START, NULL); - } - - vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]); - - break; - } - - case VFRAME_EVENT_PROVIDER_QUREY_STATE: { - vdec_vf_states(&states, vfm); - if (states.buf_avail_num > 0) - ret = RECEIVER_ACTIVE; - break; - } - - case VFRAME_EVENT_PROVIDER_VFRAME_READY: { - if (vfq_level(&vfm->vf_que) > POOL_SIZE - 1) - ret = -1; - - if (!vf_peek(vfm->recv_name)) - ret = -1; - - vfm->vf = vf_get(vfm->recv_name); - if (!vfm->vf) - ret = -1; - - if (ret < 0) { - pr_err("[%d] receiver vf err.\n", vfm->ctx->id); - break; - } - - vfq_push(&vfm->vf_que, vfm->vf); - - /*vf_notify_receiver(vfm->prov_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);*/ - - /* schedule capture work. */ - vdec_device_vf_run(vfm->ctx); - - aml_v4l2_debug(2, "[%d] FROM (%s) vf: %p, idx: %d", - vfm->ctx->id, vf_get_provider(vfm->recv_name)->name, - vfm->vf, vfm->vf->index); - break; - } - - default: - aml_v4l2_debug(4, "[%d] the vf event is %d", vfm->ctx->id, type); - } - - return ret; -} - -static const struct vframe_receiver_op_s vf_receiver = { - .event_cb = video_receiver_event_fun -}; - -struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm) -{ - return vfq_peek(&vfm->vf_que); -} - -struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) -{ - return vfq_pop(&vfm->vf_que); -} - -int vcodec_vfm_init(struct vcodec_vfm_s *vfm) -{ - snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", - RECEIVER_NAME, vfm->ctx->id); - snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", - PROVIDER_NAME, vfm->ctx->id); - - vfm->ada_ctx->recv_name = vfm->recv_name; - - vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm); - vf_reg_receiver(&vfm->vf_recv); - - return 0; -} - -void vcodec_vfm_release(struct vcodec_vfm_s *vfm) -{ - vf_unreg_receiver(&vfm->vf_recv); -} - diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h deleted file mode 100644 index bcd88757f21f..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __AML_VCODEC_VFM_H_ -#define __AML_VCODEC_VFM_H_ - -#include "aml_vcodec_vfq.h" -#include "aml_vcodec_drv.h" -#include "aml_vcodec_dec.h" -#include -#include - -#define VF_NAME_SIZE (32) -#define POOL_SIZE (64) - -struct vcodec_vfm_s { - struct aml_vcodec_ctx *ctx; - struct aml_vdec_adapt *ada_ctx; - struct vfq_s vf_que; - struct vframe_s *vf; - struct vframe_s *pool[POOL_SIZE + 1]; - char recv_name[VF_NAME_SIZE]; - char prov_name[VF_NAME_SIZE]; - struct vframe_provider_s vf_prov; - struct vframe_receiver_s vf_recv; -}; - -int vcodec_vfm_init(struct vcodec_vfm_s *vfm); - -void vcodec_vfm_release(struct vcodec_vfm_s *vfm); - -struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm); - -struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm); - -int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb); -int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb); - -void video_vf_put(char *receiver, struct vdec_fb *fb, int id); - -#endif /* __AML_VCODEC_VFM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h deleted file mode 100644 index e19c53ca0a28..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __AML_VCODEC_VFQ_H_ -#define __AML_VCODEC_VFQ_H_ - -#include -#include - -struct vfq_s { - int rp; - int wp; - int size; - int pre_rp; - int pre_wp; - struct vframe_s **pool; -}; - -static inline void vfq_lookup_start(struct vfq_s *q) -{ - q->pre_rp = q->rp; - q->pre_wp = q->wp; -} -static inline void vfq_lookup_end(struct vfq_s *q) -{ - q->rp = q->pre_rp; - q->wp = q->pre_wp; -} - -static inline void vfq_init(struct vfq_s *q, u32 size, struct vframe_s **pool) -{ - q->rp = q->wp = 0; - q->size = size; - q->pool = pool; -} - -static inline bool vfq_empty(struct vfq_s *q) -{ - return q->rp == q->wp; -} - -static inline void vfq_push(struct vfq_s *q, struct vframe_s *vf) -{ - int wp = q->wp; - - /*ToDo*/ - smp_mb(); - - q->pool[wp] = vf; - - /*ToDo*/ - smp_wmb(); - - q->wp = (wp == (q->size - 1)) ? 0 : (wp + 1); -} - -static inline struct vframe_s *vfq_pop(struct vfq_s *q) -{ - struct vframe_s *vf; - int rp; - - if (vfq_empty(q)) - return NULL; - - rp = q->rp; - - /*ToDo*/ - smp_rmb(); - - vf = q->pool[rp]; - - /*ToDo*/ - smp_mb(); - - q->rp = (rp == (q->size - 1)) ? 0 : (rp + 1); - - return vf; -} - -static inline struct vframe_s *vfq_peek(struct vfq_s *q) -{ - return (vfq_empty(q)) ? NULL : q->pool[q->rp]; -} - -static inline int vfq_level(struct vfq_s *q) -{ - int level = q->wp - q->rp; - - if (level < 0) - level += q->size; - - return level; -} - -#endif /* __AML_VCODEC_VFQ_H_ */ - diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c deleted file mode 100644 index 1c3b73dfb7be..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include "h264_parse.h" -#include "h264_stream.h" - -static unsigned char h264_exp_golomb_bits[256] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -}; - -static unsigned char ZZ_SCAN[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -static unsigned char ZZ_SCAN8[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - -unsigned int h264_u(struct h264_stream_t *s, unsigned int n) -{ - //if (n % 8 == 0) { - // return h264_stream_read_bytes(s, n / 8); - //} - return h264_stream_read_bits(s, n); -} - -unsigned int h264_ue(struct h264_stream_t *s) -{ - unsigned int bits, read; - unsigned char coded; - - bits = 0; - while (true) { - if (h264_stream_bytes_remaining(s) < 1) { - read = h264_stream_peek_bits(s, s->bit_pos) << - (8 - s->bit_pos); - break; - } - - read = h264_stream_peek_bits(s, 8); - if (bits > 16) - break; - - if (read) - break; - - h264_stream_read_bits(s, 8); - bits += 8; - } - - coded = h264_exp_golomb_bits[read]; - h264_stream_read_bits(s, coded); - bits += coded; - return h264_stream_read_bits(s, bits + 1) - 1; -} - -int h264_se(struct h264_stream_t *s) -{ - unsigned int ret; - - ret = h264_ue(s); - if (!(ret & 0x1)) { - ret >>= 1; - return (int)(-ret); - } - - return (ret + 1) >> 1; -} - -void h264_f(struct h264_stream_t *s, unsigned int n, unsigned int pattern) -{ - unsigned int val = h264_u(s, n); - - if (val != pattern) { - pr_err("fixed-pattern doesn't match. expected: %x actual: %x\n", - pattern, (unsigned int)val); - return; - } -} - -void h264_rbsp_trailing_bits(struct h264_stream_t *s) -{ - h264_f(s, 1, 1); - h264_f(s, s->bit_pos, 0); -} - -// syntax for scaling list matrix values -void Scaling_List(int *scalingList, int sizeOfScalingList, - bool *UseDefaultScalingMatrix, struct h264_stream_t *s) -{ - int j, scanj; - int delta_scale, lastScale, nextScale; - - lastScale = 8; - nextScale = 8; - - for (j = 0; j < sizeOfScalingList; j++) { - scanj = (sizeOfScalingList == 16) ? ZZ_SCAN[j] : ZZ_SCAN8[j]; - - if (nextScale != 0) { - delta_scale = h264_ue(s); - nextScale = (lastScale + delta_scale + 256) % 256; - *UseDefaultScalingMatrix = - (bool) (scanj == 0 && nextScale == 0); - } - - scalingList[scanj] = (nextScale == 0) ? lastScale : nextScale; - lastScale = scalingList[scanj]; - } -} - -void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps) -{ - unsigned int i, n_ScalingList; - - sps->profile_idc = h264_u(s, 8); - - if ((sps->profile_idc != BASELINE) && - (sps->profile_idc != MAIN) && - (sps->profile_idc != EXTENDED) && - (sps->profile_idc != FREXT_HP) && - (sps->profile_idc != FREXT_Hi10P) && - (sps->profile_idc != FREXT_Hi422) && - (sps->profile_idc != FREXT_Hi444) && - (sps->profile_idc != FREXT_CAVLC444) - && (sps->profile_idc != MVC_HIGH) - && (sps->profile_idc != STEREO_HIGH)) { - pr_err("Invalid Profile IDC (%d) encountered.\n", - sps->profile_idc); - return; - } - - sps->constrained_set0_flag = h264_u(s, 1); - sps->constrained_set1_flag = h264_u(s, 1); - sps->constrained_set2_flag = h264_u(s, 1); - h264_u(s, 5); // reserved_zero_5bits - sps->level_idc = h264_u(s, 8); - sps->seq_parameter_set_id = h264_ue(s); - - // Fidelity Range Extensions stuff - sps->chroma_format_idc = 1; - sps->bit_depth_luma_minus8 = 0; - sps->bit_depth_chroma_minus8 = 0; - sps->lossless_qpprime_flag = 0; - sps->separate_colour_plane_flag = 0; - - if ((sps->profile_idc == FREXT_HP) || - (sps->profile_idc == FREXT_Hi10P) || - (sps->profile_idc == FREXT_Hi422) || - (sps->profile_idc == FREXT_Hi444) || - (sps->profile_idc == FREXT_CAVLC444)) { - sps->chroma_format_idc = h264_ue(s); - - if (sps->chroma_format_idc == YUV444) - sps->separate_colour_plane_flag = h264_u(s, 1); - - sps->bit_depth_luma_minus8 = h264_ue(s); - sps->bit_depth_chroma_minus8 = h264_ue(s); - //checking; - if ((sps->bit_depth_luma_minus8 + 8 > sizeof(unsigned short) * 8) || - (sps->bit_depth_chroma_minus8 + 8 > sizeof(unsigned short) * 8)) { - pr_err("Source picture has higher bit depth than imgpel data type.\n"); - pr_err("Please recompile with larger data type for imgpel.\n"); - } - - sps->lossless_qpprime_flag = h264_u(s, 1); - sps->seq_scaling_matrix_present_flag = h264_u(s, 1); - if (sps->seq_scaling_matrix_present_flag) { - n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12; - for (i = 0; i < n_ScalingList; i++) { - sps->seq_scaling_list_present_flag[i] = h264_u(s, 1); - if (sps->seq_scaling_list_present_flag[i]) { - if (i < 6) - Scaling_List(sps->ScalingList4x4[i], 16, - &sps->UseDefaultScalingMatrix4x4Flag[i], s); - else - Scaling_List(sps->ScalingList8x8[i - 6], - 64, &sps->UseDefaultScalingMatrix8x8Flag[i - 6], s); - } - } - } - } - - sps->log2_max_frame_num_minus4 = h264_ue(s); - sps->pic_order_cnt_type = h264_ue(s); - if (sps->pic_order_cnt_type == 0) { - sps->log2_max_pic_order_cnt_lsb_minus4 = h264_ue(s); - } else if (sps->pic_order_cnt_type == 1) { - sps->delta_pic_order_always_zero_flag = h264_se(s); - sps->offset_for_non_ref_pic = h264_se(s); - sps->offset_for_top_to_bottom_field = h264_se(s); - sps->num_ref_frames_in_poc_cycle = h264_se(s); - for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) - sps->offset_for_ref_frame[i] = h264_se(s); - } - - sps->num_ref_frames = h264_ue(s); - sps->gaps_in_frame_num_value_allowed_flag = h264_u(s, 1); - sps->pic_width_in_mbs_minus1 = h264_ue(s); - sps->pic_height_in_map_units_minus1 = h264_ue(s); - sps->frame_mbs_only_flag = h264_u(s, 1); - if (!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = h264_u(s, 1); - - sps->direct_8x8_inference_flag = h264_u(s, 1); - sps->frame_cropping_flag = h264_u(s, 1); - if (sps->frame_cropping_flag) { - sps->frame_crop_left_offset = h264_ue(s); - sps->frame_crop_right_offset = h264_ue(s); - sps->frame_crop_top_offset = h264_ue(s); - sps->frame_crop_bottom_offset = h264_ue(s); - } - - sps->vui_parameters_present_flag = h264_u(s, 1); - //if (sps->vui_parameters_present_flag) { - // sps->vui_parameters = h264_vui_parameters(s); - //} - h264_rbsp_trailing_bits(s); -} - -void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps) -{ - pps->pic_parameter_set_id = h264_ue(s); - pps->seq_parameter_set_id = h264_ue(s); - pps->entropy_coding_mode_flag = h264_u(s, 1); - pps->pic_order_present_flag = h264_u(s, 1); - pps->num_slice_groups_minus1 = h264_ue(s); - if (pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = h264_ue(s); - if (pps->slice_group_map_type == 0) { - pps->run_length_minus1 = h264_ue(s); - } else if (pps->slice_group_map_type == 2) { - pps->top_left = h264_ue(s); - pps->bottom_right = h264_ue(s); - } else if (pps->slice_group_map_type == 3 || - pps->slice_group_map_type == 4 || - pps->slice_group_map_type == 5) { - pps->slice_group_change_direction_flag = h264_u(s, 1); - pps->slice_group_change_rate_minus1 = h264_ue(s); - } else if (pps->slice_group_map_type == 6) { - pps->pic_size_in_map_units_minus1 = h264_ue(s); - pps->slice_group_id = h264_ue(s); - } - } - pps->num_ref_idx_l0_active_minus1 = h264_ue(s); - pps->num_ref_idx_l1_active_minus1 = h264_ue(s); - pps->weighted_pred_flag = h264_u(s, 1); - pps->weighted_bipred_idc = h264_u(s, 2); - pps->pic_init_qp_minus26 = h264_se(s); - pps->pic_init_qs_minus26 = h264_se(s); - pps->chroma_qp_index_offset = h264_se(s); - pps->deblocking_filter_control_present_flag = h264_u(s, 1); - pps->constrained_intra_pred_flag = h264_u(s, 1); - pps->redundant_pic_cnt_present_flag = h264_u(s, 1); - h264_rbsp_trailing_bits(s); -} - -void h264_sps_info(struct h264_SPS_t *sps) -{ - int i; - - pr_info("sequence_parameter_set {\n"); - pr_info(" profile_idc: %d\n", sps->profile_idc); - pr_info(" constraint_set0_flag: %d\n", sps->constrained_set0_flag); - pr_info(" constraint_set1_flag: %d\n", sps->constrained_set1_flag); - pr_info(" constraint_set2_flag: %d\n", sps->constrained_set2_flag); - pr_info(" level_idc: %d\n", sps->level_idc); - pr_info(" seq_parameter_set_id: %d\n", sps->seq_parameter_set_id); - - pr_info(" log2_max_frame_num_minus4: %d\n", - sps->log2_max_frame_num_minus4); - pr_info(" pic_order_cnt_type: %d\n", sps->pic_order_cnt_type); - if (sps->pic_order_cnt_type == 0) { - pr_info(" log2_max_pic_order_cnt_lsb_minus4: %d\n", - sps->log2_max_pic_order_cnt_lsb_minus4); - } else if (sps->pic_order_cnt_type == 1) { - pr_info(" delta_pic_order_always_zero_flag: %d\n", - sps->delta_pic_order_always_zero_flag); - pr_info(" offset_for_non_ref_pic: %d\n", - sps->offset_for_non_ref_pic); - pr_info(" offset_for_top_to_bottom_field: %d\n", - sps->offset_for_top_to_bottom_field); - pr_info(" num_ref_frames_in_pic_order_cnt_cycle: %d\n", - sps->num_ref_frames_in_poc_cycle); - for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) { - pr_info(" offset_for_ref_frame[%d]: %d\n", i, - sps->offset_for_ref_frame[i]); - } - } - pr_info(" num_ref_frames: %d\n", sps->num_ref_frames); - pr_info(" gaps_in_frame_num_value_allowed_flag: %d\n", - sps->gaps_in_frame_num_value_allowed_flag); - pr_info(" pic_width_in_mbs_minus1: %d\n", - sps->pic_width_in_mbs_minus1); - pr_info(" pic_height_in_map_units_minus1: %d\n", - sps->pic_height_in_map_units_minus1); - pr_info(" frame_mbs_only_flag: %d\n", - sps->frame_mbs_only_flag); - pr_info(" mb_adaptive_frame_field_flag: %d\n", - sps->mb_adaptive_frame_field_flag); - pr_info(" direct_8x8_inference_flag: %d\n", - sps->direct_8x8_inference_flag); - pr_info(" frame_cropping_flag: %d\n", - sps->frame_cropping_flag); - if (sps->frame_cropping_flag) { - pr_info(" frame_crop_left_offset: %d\n", - sps->frame_crop_left_offset); - pr_info(" frame_crop_right_offset: %d\n", - sps->frame_crop_right_offset); - pr_info(" frame_crop_top_offset: %d\n", - sps->frame_crop_top_offset); - pr_info(" frame_crop_bottom_offset: %d\n", - sps->frame_crop_bottom_offset); - } - pr_info(" vui_parameters_present_flag: %d\n", - sps->vui_parameters_present_flag); - //if (sps->vui_parameters_present_flag) { - // h264_print_vui_parameters(sps->vui_parameters); - //} - - pr_info(" }\n"); -} - -void h264_pps_info(struct h264_PPS_t *pps) -{ - pr_info("pic_parameter_set {\n"); - pr_info(" pic_parameter_set_id: %d\n", - pps->pic_parameter_set_id); - pr_info(" seq_parameter_set_id: %d\n", - pps->seq_parameter_set_id); - pr_info(" entropy_coding_mode_flag: %d\n", - pps->entropy_coding_mode_flag); - pr_info(" pic_order_present_flag: %d\n", - pps->pic_order_present_flag); - pr_info(" num_slice_groups_minus1: %d\n", - pps->num_slice_groups_minus1); - // FIXME: Code for slice groups is missing here. - pr_info(" num_ref_idx_l0_active_minus1: %d\n", - pps->num_ref_idx_l0_active_minus1); - pr_info(" num_ref_idx_l1_active_minus1: %d\n", - pps->num_ref_idx_l1_active_minus1); - pr_info(" weighted_pred_flag: %d\n", pps->weighted_pred_flag); - pr_info(" weighted_bipred_idc: %d\n", pps->weighted_bipred_idc); - pr_info(" pic_init_qp_minus26: %d\n", pps->pic_init_qp_minus26); - pr_info(" pic_init_qs_minus26: %d\n", pps->pic_init_qs_minus26); - pr_info(" chroma_qp_index_offset: %d\n", - pps->chroma_qp_index_offset); - pr_info(" deblocking_filter_control_present_flag: %d\n", - pps->deblocking_filter_control_present_flag); - pr_info(" constrained_intra_pred_flag: %d\n", - pps->constrained_intra_pred_flag); - pr_info(" redundant_pic_cnt_present_flag: %d\n", - pps->redundant_pic_cnt_present_flag); - pr_info(" }\n"); -} - diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h deleted file mode 100644 index e54e4d3665ff..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _H264_PARSE_H -#define _H264_PARSE_H - -#include "h264_stream.h" - -enum color_model { - CM_UNKNOWN = -1, - CM_YUV = 0, - CM_RGB = 1, - CM_XYZ = 2 -}; - -enum color_format { - CF_UNKNOWN = -1, //!< Unknown color format - YUV400 = 0, //!< Monochrome - YUV420 = 1, //!< 4:2:0 - YUV422 = 2, //!< 4:2:2 - YUV444 = 3 //!< 4:4:4 -}; - -enum pixel_format { - PF_UNKNOWN = -1, //!< Unknown color ordering - UYVY = 0, //!< UYVY - YUY2 = 1, //!< YUY2 - YUYV = 1, //!< YUYV - YVYU = 2, //!< YVYU - BGR = 3, //!< BGR - V210 = 4 //!< Video Clarity 422 format (10 bits) -}; - -//AVC Profile IDC definitions -enum profile_idc{ - NO_PROFILE = 0, //!< disable profile checking for experimental coding (enables FRExt, but disables MV) - FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4" - BASELINE = 66, //!< YUV 4:2:0/8 "Baseline" - MAIN = 77, //!< YUV 4:2:0/8 "Main" - EXTENDED = 88, //!< YUV 4:2:0/8 "Extended" - FREXT_HP = 100, //!< YUV 4:2:0/8 "High" - FREXT_Hi10P = 110, //!< YUV 4:2:0/10 "High 10" - FREXT_Hi422 = 122, //!< YUV 4:2:2/10 "High 4:2:2" - FREXT_Hi444 = 244, //!< YUV 4:4:4/14 "High 4:4:4" - MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High" - STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High" -}; - -/* sequence parameter set */ -struct h264_SPS_t { - bool vailid; - unsigned int profile_idc; - bool constrained_set0_flag; - bool constrained_set1_flag; - bool constrained_set2_flag; - bool constrained_set3_flag; - unsigned int level_idc; - unsigned int seq_parameter_set_id; - unsigned int chroma_format_idc; - bool seq_scaling_matrix_present_flag; - int seq_scaling_list_present_flag[12]; - int ScalingList4x4[6][16]; - int ScalingList8x8[6][64]; - bool UseDefaultScalingMatrix4x4Flag[6]; - bool UseDefaultScalingMatrix8x8Flag[6]; - unsigned int bit_depth_luma_minus8; - unsigned int bit_depth_chroma_minus8; - unsigned int log2_max_frame_num_minus4; - unsigned int pic_order_cnt_type; - unsigned int log2_max_pic_order_cnt_lsb_minus4; - bool delta_pic_order_always_zero_flag; - int offset_for_non_ref_pic; - int offset_for_top_to_bottom_field; - unsigned int num_ref_frames_in_poc_cycle; - int offset_for_ref_frame[255]; - int num_ref_frames; - bool gaps_in_frame_num_value_allowed_flag; - unsigned int pic_width_in_mbs_minus1; - unsigned int pic_height_in_map_units_minus1; - bool frame_mbs_only_flag; - bool mb_adaptive_frame_field_flag; - bool direct_8x8_inference_flag; - bool frame_cropping_flag; - unsigned int frame_crop_left_offset; - unsigned int frame_crop_right_offset; - unsigned int frame_crop_top_offset; - unsigned int frame_crop_bottom_offset; - bool vui_parameters_present_flag; - //h264_vui_parameters_t *vui_parameters; - unsigned separate_colour_plane_flag; - int lossless_qpprime_flag; -}; - -/* pic parameter set */ -struct h264_PPS_t { - int pic_parameter_set_id; - int seq_parameter_set_id; - int entropy_coding_mode_flag; - int pic_order_present_flag; - int num_slice_groups_minus1; - int slice_group_map_type; - int run_length_minus1; - int top_left; - int bottom_right; - int slice_group_change_direction_flag; - int slice_group_change_rate_minus1; - int pic_size_in_map_units_minus1; - int slice_group_id; - int num_ref_idx_l0_active_minus1; - int num_ref_idx_l1_active_minus1; - int weighted_pred_flag; - int weighted_bipred_idc; - int pic_init_qp_minus26; - int pic_init_qs_minus26; - int chroma_qp_index_offset; - int deblocking_filter_control_present_flag; - int constrained_intra_pred_flag; - int redundant_pic_cnt_present_flag; -}; - -void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps); -void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps); - -void h264_sps_info(struct h264_SPS_t *sps); -void h264_pps_info(struct h264_PPS_t *pps); - -#endif //_H264_PARSE_H diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c deleted file mode 100644 index 3061568309fc..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include "h264_stream.h" - -void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size) -{ - s->data = data; - s->size = size; - s->bit_pos = 7; - s->byte_pos = 0; -} - -unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n) -{ - unsigned int ret = 0; - unsigned char b = 0; - int i; - - if (n == 0) - return 0; - - for (i = 0; i < n; ++i) { - if (h264_stream_bits_remaining(s) == 0) - ret <<= n - i - 1; - - b = s->data[s->byte_pos]; - if (n - i <= 32) - ret = ret << 1 | BITAT(b, s->bit_pos); - - if (s->bit_pos == 0) { - s->bit_pos = 7; - s->byte_pos++; - } else - s->bit_pos--; - } - - return ret; -} - -unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n) -{ - int prev_bit_pos = s->bit_pos; - int prev_byte_pos = s->byte_pos; - unsigned int ret = h264_stream_read_bits(s, n); - - s->bit_pos = prev_bit_pos; - s->byte_pos = prev_byte_pos; - - return ret; -} - -unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n) -{ - unsigned int ret = 0; - int i; - - if (n == 0) - return 0; - - for (i = 0; i < n; ++i) { - if (h264_stream_bytes_remaining(s) == 0) { - ret <<= (n - i - 1) * 8; - break; - } - - if (n - i <= 4) - ret = ret << 8 | s->data[s->byte_pos]; - - s->byte_pos++; - } - - return ret; -} - -unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n) -{ - int prev_byte_pos = s->byte_pos; - unsigned int ret = h264_stream_read_bytes(s, n); - - s->byte_pos = prev_byte_pos; - - return ret; -} - -int h264_stream_bits_remaining(struct h264_stream_t *s) -{ - return (s->size - s->byte_pos) * 8 + s->bit_pos; -} - -int h264_stream_bytes_remaining(struct h264_stream_t *s) -{ - return s->size - s->byte_pos; -} - diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h deleted file mode 100644 index d6d2eac88b93..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _H264_STREAM_H -#define _H264_STREAM_H - -#include "utils.h" - -struct h264_stream_t { - unsigned char *data; - unsigned int size; - int bit_pos; - int byte_pos; -}; - -void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size); -unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n); -unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n); -unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n); -unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n); -int h264_stream_bits_remaining(struct h264_stream_t *s); -int h264_stream_bytes_remaining(struct h264_stream_t *s); - -#endif //_H264_STREAM_H - diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h deleted file mode 100644 index 26b155271916..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _UTILS_H -#define _UTILS_H - -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define CLAMP(x, low, high) \ - (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) -#define BITAT(x, n) ((x & (1 << n)) == (1 << n)) - -typedef unsigned char uint8_t; -typedef int int32_t; -typedef unsigned int uint32_t; - -#endif //_UTILS_H diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c deleted file mode 100644 index 324d30ec2ef5..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c +++ /dev/null @@ -1,736 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include "../vdec_drv_if.h" -#include "../aml_vcodec_util.h" -#include "../aml_vcodec_dec.h" -//#include "../aml_vcodec_intr.h" -#include "../aml_vcodec_adapt.h" -#include "../vdec_drv_base.h" -#include "../aml_vcodec_vfm.h" -#include "h264_stream.h" -#include "h264_parse.h" -#include - -/* h264 NALU type */ -#define NAL_NON_IDR_SLICE 0x01 -#define NAL_IDR_SLICE 0x05 -#define NAL_H264_SEI 0x06 -#define NAL_H264_SPS 0x07 -#define NAL_H264_PPS 0x08 - -#define NAL_TYPE(value) ((value) & 0x1F) - -#define BUF_PREDICTION_SZ (64 * 1024)//(32 * 1024) - -#define MB_UNIT_LEN 16 - -/* motion vector size (bytes) for every macro block */ -#define HW_MB_STORE_SZ 64 - -#define H264_MAX_FB_NUM 17 -#define HDR_PARSING_BUF_SZ 1024 - -#define HEADER_BUFFER_SIZE (32 * 1024) - -/** - * struct h264_fb - h264 decode frame buffer information - * @vdec_fb_va : virtual address of struct vdec_fb - * @y_fb_dma : dma address of Y frame buffer (luma) - * @c_fb_dma : dma address of C frame buffer (chroma) - * @poc : picture order count of frame buffer - * @reserved : for 8 bytes alignment - */ -struct h264_fb { - uint64_t vdec_fb_va; - uint64_t y_fb_dma; - uint64_t c_fb_dma; - int32_t poc; - uint32_t reserved; -}; - -/** - * struct h264_ring_fb_list - ring frame buffer list - * @fb_list : frame buffer arrary - * @read_idx : read index - * @write_idx : write index - * @count : buffer count in list - */ -struct h264_ring_fb_list { - struct h264_fb fb_list[H264_MAX_FB_NUM]; - unsigned int read_idx; - unsigned int write_idx; - unsigned int count; - unsigned int reserved; -}; - -/** - * struct vdec_h264_dec_info - decode information - * @dpb_sz : decoding picture buffer size - * @resolution_changed : resoltion change happen - * @realloc_mv_buf : flag to notify driver to re-allocate mv buffer - * @reserved : for 8 bytes alignment - * @bs_dma : Input bit-stream buffer dma address - * @y_fb_dma : Y frame buffer dma address - * @c_fb_dma : C frame buffer dma address - * @vdec_fb_va : VDEC frame buffer struct virtual address - */ -struct vdec_h264_dec_info { - uint32_t dpb_sz; - uint32_t resolution_changed; - uint32_t realloc_mv_buf; - uint32_t reserved; - uint64_t bs_dma; - uint64_t y_fb_dma; - uint64_t c_fb_dma; - uint64_t vdec_fb_va; -}; - -/** - * struct vdec_h264_vsi - shared memory for decode information exchange - * between VPU and Host. - * The memory is allocated by VPU then mapping to Host - * in vpu_dec_init() and freed in vpu_dec_deinit() - * by VPU. - * AP-W/R : AP is writer/reader on this item - * VPU-W/R: VPU is write/reader on this item - * @hdr_buf : Header parsing buffer (AP-W, VPU-R) - * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R) - * @mv_buf_dma : HW working motion vector buffer dma address (AP-W, VPU-R) - * @list_free : free frame buffer ring list (AP-W/R, VPU-W) - * @list_disp : display frame buffer ring list (AP-R, VPU-W) - * @dec : decode information (AP-R, VPU-W) - * @pic : picture information (AP-R, VPU-W) - * @crop : crop information (AP-R, VPU-W) - */ -struct vdec_h264_vsi { - unsigned char hdr_buf[HDR_PARSING_BUF_SZ]; - char *header_buf; - int sps_size; - int pps_size; - int sei_size; - int head_offset; - uint64_t pred_buf_dma; - uint64_t mv_buf_dma[H264_MAX_FB_NUM]; - struct h264_ring_fb_list list_free; - struct h264_ring_fb_list list_disp; - struct vdec_h264_dec_info dec; - struct vdec_pic_info pic; - struct v4l2_rect crop; -}; - -/** - * struct vdec_h264_inst - h264 decoder instance - * @num_nalu : how many nalus be decoded - * @ctx : point to aml_vcodec_ctx - * @pred_buf : HW working predication buffer - * @mv_buf : HW working motion vector buffer - * @vpu : VPU instance - * @vsi : VPU shared information - */ -struct vdec_h264_inst { - unsigned int num_nalu; - struct aml_vcodec_ctx *ctx; - struct aml_vcodec_mem pred_buf; - struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM]; - //struct vdec_vpu_inst vpu; - struct aml_vdec_adapt vdec; - struct vdec_h264_vsi *vsi; - struct vcodec_vfm_s vfm; -}; - -#define DUMP_FILE_NAME "/data/dump/dump.tmp" -static struct file *filp; -static loff_t file_pos; - -void dump_write(const char __user *buf, size_t count) -{ - mm_segment_t old_fs; - - if (!filp) - return; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (count != vfs_write(filp, buf, count, &file_pos)) - pr_err("Failed to write file\n"); - - set_fs(old_fs); -} - -void dump_init(void) -{ - filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644); - if (IS_ERR(filp)) { - pr_err("open dump file failed\n"); - filp = NULL; - } -} - -void dump_deinit(void) -{ - if (filp) { - filp_close(filp, current->files); - filp = NULL; - file_pos = 0; - } -} - -void swap_uv(void *uv, int size) -{ - int i; - __u16 *p = uv; - - size /= 2; - - for (i = 0; i < size; i++, p++) - *p = __swab16(*p); -} - -static void get_pic_info(struct vdec_h264_inst *inst, - struct vdec_pic_info *pic) -{ - *pic = inst->vsi->pic; - - aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", - pic->visible_width, pic->visible_height, - pic->coded_width, pic->coded_height); - aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, - pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); -} - -static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr) -{ - cr->left = inst->vsi->crop.left; - cr->top = inst->vsi->crop.top; - cr->width = inst->vsi->crop.width; - cr->height = inst->vsi->crop.height; - - aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", - cr->left, cr->top, cr->width, cr->height); -} - -static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz) -{ - *dpb_sz = inst->vsi->dec.dpb_sz; - aml_vcodec_debug(inst, "sz=%d", *dpb_sz); -} - -static int find_start_code(unsigned char *data, unsigned int data_sz) -{ - if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) - return 3; - - if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && - data[3] == 1) - return 4; - - return -1; -} - -static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) -{ - struct vdec_h264_inst *inst = NULL; - int ret = -1; - - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) - return -ENOMEM; - - inst->ctx = ctx; - - inst->vdec.format = VFORMAT_H264; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; - inst->vfm.ctx = ctx; - inst->vfm.ada_ctx = &inst->vdec; - - vcodec_vfm_init(&inst->vfm); - - ret = video_decoder_init(&inst->vdec); - if (ret) { - aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); - goto error_free_inst; - } - - /* probe info from the stream */ - inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); - if (!inst->vsi) { - ret = -ENOMEM; - goto error_free_inst; - } - - /* alloc the header buffer to be used cache sps or spp etc.*/ - inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); - if (!inst->vsi) { - ret = -ENOMEM; - goto error_free_vsi; - } - - inst->vsi->pic.visible_width = 1920; - inst->vsi->pic.visible_height = 1080; - inst->vsi->pic.coded_width = 1920; - inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); - - aml_vcodec_debug(inst, "H264 Instance >> %p", inst); - - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; - - dump_init(); - - return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); - *h_vdec = 0; - - return ret; -} - -static int refer_buffer_num(int level_idc, int poc_cnt, - int mb_width, int mb_height) -{ - int max_ref_num = 27; - int size, size_margin = 6; - int pic_size = mb_width * mb_height * 384; - - switch (level_idc) { - case 9: - size = 152064; - break; - case 10: - size = 152064; - break; - case 11: - size = 345600; - break; - case 12: - size = 912384; - break; - case 13: - size = 912384; - break; - case 20: - size = 912384; - break; - case 21: - size = 1824768; - break; - case 22: - size = 3110400; - break; - case 30: - size = 3110400; - break; - case 31: - size = 6912000; - break; - case 32: - size = 7864320; - break; - case 40: - size = 12582912; - break; - case 41: - size = 12582912; - break; - case 42: - size = 13369344; - break; - case 50: - size = 42393600; - break; - case 51: - case 52: - default: - size = 70778880; - break; - } - - size /= pic_size; - size = size + 1; /* need more buffers */ - - if (poc_cnt > size) - size = poc_cnt; - - size = size + size_margin; - if (size > max_ref_num) - size = max_ref_num; - - return size; -} - -static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) -{ - struct vdec_pic_info *pic = &inst->vsi->pic; - struct vdec_h264_dec_info *dec = &inst->vsi->dec; - struct v4l2_rect *rect = &inst->vsi->crop; - unsigned int mb_w, mb_h, width, height; - unsigned int crop_unit_x = 0, crop_unit_y = 0; - unsigned int poc_cnt = 0; - - mb_w = sps->pic_width_in_mbs_minus1 + 1; - mb_h = sps->pic_height_in_map_units_minus1 + 1; - - width = mb_w << 4; // 16 - height = (2 - sps->frame_mbs_only_flag) * (mb_h << 4); - - if (sps->frame_cropping_flag) { - if (0 == sps->chroma_format_idc) {// monochrome - crop_unit_x = 1; - crop_unit_y = 2 - sps->frame_mbs_only_flag; - } else if (1 == sps->chroma_format_idc) {// 4:2:0 - crop_unit_x = 2; - crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag); - } else if (2 == sps->chroma_format_idc) {// 4:2:2 - crop_unit_x = 2; - crop_unit_y = 2 - sps->frame_mbs_only_flag; - } else {// 3 == sps.chroma_format_idc // 4:4:4 - crop_unit_x = 1; - crop_unit_y = 2 - sps->frame_mbs_only_flag; - } - } - - width -= crop_unit_x * (sps->frame_crop_left_offset + - sps->frame_crop_right_offset); - height -= crop_unit_y * (sps->frame_crop_top_offset + - sps->frame_crop_bottom_offset); - - /* fill visible area size that be used for EGL. */ - pic->visible_width = width; - pic->visible_height = height; - - /* calc visible ares. */ - rect->left = 0; - rect->top = 0; - rect->width = pic->visible_width; - rect->height = pic->visible_height; - - /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(mb_w, 4) << 4; - pic->coded_height = ALIGN(mb_h, 4) << 4; - pic->y_len_sz = pic->coded_width * pic->coded_height; - pic->c_len_sz = pic->y_len_sz >> 1; - - /* calc DPB size */ - poc_cnt = sps->pic_order_cnt_type; - if (!poc_cnt) - poc_cnt = (sps->log2_max_pic_order_cnt_lsb_minus4 + 4) << 1; - - dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); - - pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", - inst->ctx->id, pic->coded_width, pic->coded_height, - pic->visible_width, pic->visible_height, dec->dpb_sz); -} - -static int vdec_h264_probe(unsigned long h_vdec, - struct aml_vcodec_mem *bs, void *out) -{ - struct vdec_h264_inst *inst = - (struct vdec_h264_inst *)h_vdec; - struct h264_stream_t s; - struct h264_SPS_t *sps; - unsigned int nal_type; - int nal_idx; - int real_data_pos, real_data_size; - unsigned char *buf = (unsigned char *)bs->va; - unsigned int size = bs->size; - - nal_idx = find_start_code(buf, size); - if (nal_idx < 0) - return -1; - - nal_type = NAL_TYPE(buf[nal_idx]); - if (nal_type != NAL_H264_SPS) - return -1; - - /* start code plus nal type. */ - real_data_pos = nal_idx + 1; - real_data_size = size - real_data_pos; - - sps = kzalloc(sizeof(struct h264_SPS_t), GFP_KERNEL); - if (sps == NULL) - return -ENOMEM; - - h264_stream_set(&s, &buf[real_data_pos], real_data_size); - h264_sps_parse(&s, sps); - //h264_sps_info(sps); - - fill_vdec_params(inst, sps); - - kfree(sps); - - return 0; -} - -static void vdec_h264_deinit(unsigned long h_vdec) -{ - struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - - if (!inst) - return; - - aml_vcodec_debug_enter(inst); - - video_decoder_release(&inst->vdec); - - vcodec_vfm_release(&inst->vfm); - - dump_deinit(); - - if (inst->vsi && inst->vsi->header_buf) - kfree(inst->vsi->header_buf); - - if (inst->vsi) - kfree(inst->vsi); - - kfree(inst); -} - -static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out) -{ - return get_fb_from_queue(inst->ctx, out); -} - -static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) -{ - struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; - - aml_vcodec_debug(inst, "%s() [%d], vfm: %p", - __func__, __LINE__, &inst->vfm); - - vf = peek_video_frame(&inst->vfm); - if (!vf) { - aml_vcodec_debug(inst, "there is no vframe."); - *out = NULL; - return; - } - - vf = get_video_frame(&inst->vfm); - if (!vf) { - aml_vcodec_debug(inst, "the vframe is avalid."); - *out = NULL; - return; - } - - atomic_set(&vf->use_cnt, 1); - - aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", - __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); - - fb = (struct vdec_fb *)vf->v4l_mem_handle; - fb->vf_handle = (unsigned long)vf; - fb->status = FB_ST_DISPLAY; - - *out = fb; - - //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); - //dump_write(fb->base_y.va, fb->base_y.bytes_used); - //dump_write(fb->base_c.va, fb->base_c.bytes_used); - - /* convert yuv format. */ - //swap_uv(fb->base_c.va, fb->base_c.size); - - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_y.va, - (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_c.va, - (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); -} - -static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg) -{ - struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - struct aml_vdec_adapt *vdec = &inst->vdec; - int nal_start_idx = 0; - int err = 0; - unsigned int nal_start; - unsigned int nal_type; - unsigned char *buf; - unsigned int buf_sz; - int ret = 0; - - /* bs NULL means flush decoder */ - if (bs == NULL) - return 0;//vpu_dec_reset(vpu); - - buf = (unsigned char *)bs->va; - buf_sz = bs->size; - nal_start_idx = find_start_code(buf, buf_sz); - if (nal_start_idx < 0) - goto err_free_fb_out; - - nal_start = buf[nal_start_idx]; - nal_type = NAL_TYPE(buf[nal_start_idx]); - aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, buf_sz); - - if (nal_type == NAL_H264_SPS) { - if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { - err = -EILSEQ; - goto err_free_fb_out; - } - inst->vsi->sps_size = buf_sz; - memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); - inst->vsi->head_offset += inst->vsi->sps_size; - } else if (nal_type == NAL_H264_PPS) { - //buf_sz -= nal_start_idx; - if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { - err = -EILSEQ; - goto err_free_fb_out; - } - inst->vsi->pps_size = buf_sz; - memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); - inst->vsi->head_offset += inst->vsi->pps_size; - } else if (nal_type == NAL_H264_SEI) { - if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { - err = -EILSEQ; - goto err_free_fb_out; - } - inst->vsi->sei_size = buf_sz; - memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); - inst->vsi->head_offset += inst->vsi->sei_size; - } else { - char *write_buf = vmalloc(inst->vsi->head_offset + buf_sz); - - memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset); - memcpy(write_buf + inst->vsi->head_offset, buf, buf_sz); - - ret = vdec_vframe_write(vdec, write_buf, - inst->vsi->head_offset + buf_sz, timestamp); - - aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", - write_buf, inst->vsi->head_offset + buf_sz, ret); - - memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); - inst->vsi->head_offset = 0; - inst->vsi->sps_size = 0; - inst->vsi->pps_size = 0; - inst->vsi->sei_size = 0; - - vfree(write_buf); - } - - //err = vpu_dec_start(vpu, data, 2); - /*if (err) - goto err_free_fb_out;*/ - -#if 0 - *res_chg = inst->vsi->dec.resolution_changed; - if (*res_chg) { - struct vdec_pic_info pic; - - aml_vcodec_debug(inst, "- resolution changed -"); - get_pic_info(inst, &pic); - - if (inst->vsi->dec.realloc_mv_buf) { - err = alloc_mv_buf(inst, &pic); - if (err) - goto err_free_fb_out; - } - } -#endif - if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) { - /* wait decoder done interrupt */ - //err = aml_vcodec_wait_for_done_ctx(inst->ctx, aml_INST_IRQ_RECEIVED, WAIT_INTR_TIMEOUT_MS); - /*if (err) - goto err_free_fb_out;*/ - - //vpu_dec_end(vpu); - } - return ret; - -err_free_fb_out: - //put_fb_to_free(inst, fb); - aml_vcodec_err(inst, "NALU[%d] err=%d", inst->num_nalu, err); - - return err; -} - -static int vdec_h264_get_param(unsigned long h_vdec, - enum vdec_get_param_type type, void *out) -{ - int ret = 0; - struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - - if (!inst) { - pr_err("the h264 inst of dec is void."); - return -1; - } - - switch (type) { - case GET_PARAM_DISP_FRAME_BUFFER: - vdec_h264_get_vf(inst, out); - break; - - case GET_PARAM_FREE_FRAME_BUFFER: - ret = vdec_h264_get_fb(inst, out); - break; - - case GET_PARAM_PIC_INFO: - get_pic_info(inst, out); - break; - - case GET_PARAM_DPB_SIZE: - get_dpb_size(inst, out); - break; - - case GET_PARAM_CROP_INFO: - get_crop_info(inst, out); - break; - - default: - aml_vcodec_err(inst, "invalid get parameter type=%d", type); - ret = -EINVAL; - } - - return ret; -} - -static struct vdec_common_if vdec_h264_if = { - vdec_h264_init, - vdec_h264_probe, - vdec_h264_decode, - vdec_h264_get_param, - vdec_h264_deinit, -}; - -struct vdec_common_if *get_h264_dec_comm_if(void); - -struct vdec_common_if *get_h264_dec_comm_if(void) -{ - return &vdec_h264_if; -} diff --git a/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk b/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk deleted file mode 100644 index d9652fb23b4a..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk +++ /dev/null @@ -1,23 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := vcode_m2m -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := vcodec_m2m_test.c -LOCAL_ARM_MODE := arm - -LOCAL_C_INCLUDES := \ - $(JNI_H_INCLUDE) \ - $(BOARD_AML_VENDOR_PATH)/vendor/amlogic/external/ffmpeg - -LOCAL_SHARED_LIBRARIES := \ - libamffmpeg - -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) - -LOCAL_PREBUILT_LIBS:= \ -# libavcodec:ffmpeg/lib/libavcodec.so \ - -include $(BUILD_MULTI_PREBUILT) diff --git a/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c b/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c deleted file mode 100644 index 5bed46c1644e..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c +++ /dev/null @@ -1,292 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#define INBUF_SIZE (4096) -#define DUMP_DIR "/mnt/video_frames" - -typedef struct VcodecCtx { - AVFormatContext *fmt_ctx; - AVStream *stream; - int nb_streams; - int vst_idx; - char *filename; - pthread_t tid; - pthread_mutex_t pthread_mutex; - pthread_cond_t pthread_cond; -} VcodecCtx; - -static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, - char *filename) -{ - FILE *f; - int i; - - printf("wrap: %d, xsize: %d, ysize: %d, filename: %s\n", wrap, xsize, ysize, filename); - - f = fopen(filename,"w+"); - fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); - - for (i = 0; i < ysize; i++) - fwrite(buf + i * wrap, 1, xsize, f); - fclose(f); -} - -static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, - const char *filename) -{ - char buf[1024]; - int ret; - - ret = avcodec_send_packet(dec_ctx, pkt); - if (ret < 0) { - fprintf(stderr, "Error sending a packet for decoding\n"); - return; - } - - while (ret >= 0) { - ret = avcodec_receive_frame(dec_ctx, frame); - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) - return; - else if (ret < 0) { - fprintf(stderr, "Error during decoding, ret: %s\n", av_err2str(ret)); - break; - } - - //fprintf(stderr, "saving frame %3d\n", dec_ctx->frame_number); - fflush(stdout); - - /* the picture is allocated by the decoder. no need to free it */ - snprintf(buf, sizeof(buf), "%s/frame-%d", filename, dec_ctx->frame_number); - pgm_save(frame->data[0], frame->linesize[0], - frame->width, frame->height, buf); - } -} - -static void* read_thread(void *arg) -{ - int ret, err; - AVFormatContext *ic = NULL; - AVCodecContext *dec_ctx = NULL; - AVStream *stream = NULL; - AVCodec *codec = NULL; - AVPacket pkt1, *pkt = &pkt1; - AVFrame *frame = NULL; - int vst_idx = 0; - int has_video = 0; - unsigned int st_idx = 0; - VcodecCtx *vctx = arg; - - printf("entry read thread, tid: %ld.\n", vctx->tid); - - ic = avformat_alloc_context(); - if (!ic) { - fprintf(stderr, "Could not allocate avformat context.\n"); - return NULL; - } - - err = avformat_open_input(&ic, vctx->filename, NULL, NULL); - if (err < 0) { - fprintf(stderr, "Could not open avformat input.\n"); - return NULL; - } - - err = avformat_find_stream_info(ic, NULL); - if (err < 0) { - fprintf(stderr, "find stream info err.\n"); - return NULL; - } - - for (st_idx = 0; st_idx < ic->nb_streams; st_idx++) { - AVStream *st = ic->streams[st_idx]; - - enum AVMediaType type = st->codecpar->codec_type; - st->discard = AVDISCARD_ALL; - - if (type == AVMEDIA_TYPE_VIDEO) { - st->discard = AVDISCARD_NONE; - vctx->vst_idx = st_idx; - has_video = 1; - break; - } - } - - if (!has_video) { - fprintf(stderr, "no video stream.\n"); - return NULL; - } - - stream = ic->streams[vctx->vst_idx]; - - //codec = avcodec_find_decoder(stream->codecpar->codec_id); - codec = avcodec_find_decoder_by_name("h264_v4l2m2m"); - if (!codec) { - fprintf(stderr, "Unsupported codec with id %d for input stream %d\n", - stream->codecpar->codec_id, stream->index); - return NULL; - } - - dec_ctx = avcodec_alloc_context3(codec); - if (!dec_ctx) { - fprintf(stderr, "Could not allocate video codec context\n"); - return NULL; - } - - err = avcodec_parameters_to_context(dec_ctx, stream->codecpar); - if (err < 0) { - fprintf(stderr, "Could not set paras to context\n"); - return NULL; - } - - av_codec_set_pkt_timebase(dec_ctx, stream->time_base); - dec_ctx->framerate = stream->avg_frame_rate; - - if (avcodec_open2(dec_ctx, codec, NULL) < 0) { - fprintf(stderr, "Could not open codec for input stream %d\n", - stream->index); - return NULL; - } - - printf("fmt ctx: %p, stream: %p, video st idx: %d, num: %d\n", - ic, stream, vst_idx, ic->nb_streams); - printf("format: %s\n",ic->iformat->name); - - ic->flags |= AVFMT_FLAG_GENPTS; - ic->debug = 0xff; - - //if (ic->pb) - // ic->pb->eof_reached = 0; - - frame = av_frame_alloc(); - if (!frame) { - fprintf(stderr, "Could not allocate video frame\n"); - return NULL; - } - - for (;;) { - ret = av_read_frame(ic, pkt); - if (ret < 0) { - if (ret == AVERROR_EOF || avio_feof(ic->pb)) { - printf("read data end, ret: %d.\n", ret); - break; - } - - if (ic->pb && ic->pb->error) - break; - - printf("read data fail, ret: %d.\n", ret); - continue; - } - - if (pkt->stream_index == vctx->vst_idx) { - //packet_queue_put(&is->audioq, pkt); - printf("read video data size: %d.\n", pkt->size); - if (pkt->size) - decode(dec_ctx, frame, pkt, DUMP_DIR); - } else - av_packet_unref(pkt); - } - - /* flush the decoder */ - decode(dec_ctx, frame, NULL, DUMP_DIR); - - avcodec_free_context(&dec_ctx); - av_frame_free(&frame); - - if (ic) - avformat_close_input(&ic); - - printf("read thread exit.\n"); - - pthread_mutex_lock(&vctx->pthread_mutex); - pthread_cond_signal(&vctx->pthread_cond); - pthread_mutex_unlock(&vctx->pthread_mutex); - - return NULL; -} - - -static int open_input_file(const char *filename) -{ - int ret; - VcodecCtx *vctx; - pthread_t pid = pthread_self(); - - vctx = av_mallocz(sizeof(VcodecCtx)); - if (!vctx) - return -1; - - vctx->filename = av_strdup(filename); - if (!vctx->filename) - return -1; - - pthread_mutex_init(&vctx->pthread_mutex, NULL); - pthread_cond_init(&vctx->pthread_cond, NULL); - - ret = pthread_create(&vctx->tid, NULL, read_thread, (void *)vctx); - if (ret == 0) { - pthread_setname_np(pid, "read_thread"); - - pthread_mutex_lock(&vctx->pthread_mutex); - pthread_cond_wait(&vctx->pthread_cond, &vctx->pthread_mutex); - pthread_mutex_unlock(&vctx->pthread_mutex); - } - - printf("creat the read thread, ret: %d.\n", ret); - - return 0; -} - -int main(int argc, char **argv) -{ - int ret; - const char *filename, *outfilename; - - if (argc < 2) { - fprintf(stderr, "Usage: %s \n ==> %s/frame-123\n", argv[0], DUMP_DIR); - exit(0); - } - - filename = argv[1]; - outfilename = argv[2]; - - mkdir(DUMP_DIR, 0664); - - /*set debug level*/ - //av_log_set_level(AV_LOG_DEBUG); - - av_register_all(); - - ret = open_input_file(filename); - if (ret < 0) { - fprintf(stderr, "open input file fail.\n"); - goto out; - } - -out: - return ret < 0; -} diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h deleted file mode 100644 index dfe5d27457df..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _VDEC_DRV_BASE_ -#define _VDEC_DRV_BASE_ - -#include "aml_vcodec_drv.h" - -#include "vdec_drv_if.h" - -struct vdec_common_if { - /** - * (*init)() - initialize decode driver - * @ctx : [in] aml v4l2 context - * @h_vdec : [out] driver handle - */ - int (*init)(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec); - - int (*probe)(unsigned long h_vdec, - struct aml_vcodec_mem *bs, void *out); - - /** - * (*decode)() - trigger decode - * @h_vdec : [in] driver handle - * @bs : [in] input bitstream - * @fb : [in] frame buffer to store decoded frame - * @res_chg : [out] resolution change happen - */ - int (*decode)(unsigned long h_vdec, struct aml_vcodec_mem *bs, - unsigned long int pts, bool *res_chg); - - /** - * (*get_param)() - get driver's parameter - * @h_vdec : [in] driver handle - * @type : [in] input parameter type - * @out : [out] buffer to store query result - */ - int (*get_param)(unsigned long h_vdec, - enum vdec_get_param_type type, void *out); - - /** - * (*deinit)() - deinitialize driver. - * @h_vdec : [in] driver handle to be deinit - */ - void (*deinit)(unsigned long h_vdec); -}; - -#endif diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c deleted file mode 100644 index d981260b1361..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include - -#include "vdec_drv_if.h" -#include "aml_vcodec_dec.h" -#include "vdec_drv_base.h" -#include "aml_vcodec_dec_pm.h" -//#include "aml_vpu.h" - -const struct vdec_common_if *get_h264_dec_comm_if(void); -const struct vdec_common_if *get_vp8_dec_comm_if(void); -const struct vdec_common_if *get_vp9_dec_comm_if(void); - -int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) -{ - int ret = 0; - - switch (fourcc) { - case V4L2_PIX_FMT_H264: - ctx->dec_if = get_h264_dec_comm_if(); - break; - /*case V4L2_PIX_FMT_VP8: - ctx->dec_if = get_vp8_dec_comm_if(); - break; - case V4L2_PIX_FMT_VP9: - ctx->dec_if = get_vp9_dec_comm_if(); - break;*/ - default: - return -EINVAL; - } - - aml_vdec_lock(ctx); - //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp - ret = ctx->dec_if->init(ctx, &ctx->drv_handle); - //aml_vcodec_dec_clock_off(&ctx->dev->pm); - aml_vdec_unlock(ctx); - - return ret; -} - -int vdec_if_probe(struct aml_vcodec_ctx *ctx, - struct aml_vcodec_mem *bs, void *out) -{ - int ret = 0; - - aml_vdec_lock(ctx); - ret = ctx->dec_if->probe(ctx->drv_handle, bs, out); - aml_vdec_unlock(ctx); - - return ret; -} - -int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg) -{ - int ret = 0; - - if (bs) { - if ((bs->dma_addr & 63) != 0) { - aml_v4l2_err("bs dma_addr should 64 byte align"); - return -EINVAL; - } - } - - /*if (fb) { - if (((fb->base_y.dma_addr & 511) != 0) || - ((fb->base_c.dma_addr & 511) != 0)) { - aml_v4l2_err("frame buffer dma_addr should 512 byte align"); - return -EINVAL; - } - }*/ - - if (ctx->drv_handle == 0) - return -EIO; - - //aml_vdec_lock(ctx); - - aml_vcodec_set_curr_ctx(ctx->dev, ctx); - //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp - //enable_irq(ctx->dev->dec_irq); - ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg); - //disable_irq(ctx->dev->dec_irq); - //aml_vcodec_dec_clock_off(&ctx->dev->pm); - aml_vcodec_set_curr_ctx(ctx->dev, NULL); - - //aml_vdec_unlock(ctx); - - return ret; -} - -int vdec_if_get_param(struct aml_vcodec_ctx *ctx, - enum vdec_get_param_type type, void *out) -{ - int ret = 0; - - if (ctx->drv_handle == 0) - return -EIO; - - //aml_vdec_lock(ctx); - ret = ctx->dec_if->get_param(ctx->drv_handle, type, out); - //aml_vdec_unlock(ctx); - - return ret; -} - -void vdec_if_deinit(struct aml_vcodec_ctx *ctx) -{ - if (ctx->drv_handle == 0) - return; - - //aml_vdec_lock(ctx); - //aml_vcodec_dec_clock_on(&ctx->dev->pm); - ctx->dec_if->deinit(ctx->drv_handle); - //aml_vcodec_dec_clock_off(&ctx->dev->pm); - //aml_vdec_unlock(ctx); - - ctx->drv_handle = 0; -} diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h deleted file mode 100644 index c6f461a15ba7..000000000000 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _VDEC_DRV_IF_H_ -#define _VDEC_DRV_IF_H_ - -#include "aml_vcodec_drv.h" -#include "aml_vcodec_dec.h" -#include "aml_vcodec_util.h" - - -/** - * struct vdec_fb_status - decoder frame buffer status - * @FB_ST_NORMAL : initial state - * @FB_ST_DISPLAY : frmae buffer is ready to be displayed - * @FB_ST_FREE : frame buffer is not used by decoder any more - */ -enum vdec_fb_status { - FB_ST_NORMAL, - FB_ST_DISPLAY, - FB_ST_FREE -}; - -/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER, - * the caller does not own the returned buffer. The buffer will not be - * released before vdec_if_deinit. - * GET_PARAM_DISP_FRAME_BUFFER : get next displayable frame buffer, - * struct vdec_fb** - * GET_PARAM_FREE_FRAME_BUFFER : get non-referenced framebuffer, vdec_fb** - * GET_PARAM_PIC_INFO : get picture info, struct vdec_pic_info* - * GET_PARAM_CROP_INFO : get crop info, struct v4l2_crop* - * GET_PARAM_DPB_SIZE : get dpb size, unsigned int* - */ -enum vdec_get_param_type { - GET_PARAM_DISP_FRAME_BUFFER, - GET_PARAM_FREE_FRAME_BUFFER, - GET_PARAM_PIC_INFO, - GET_PARAM_CROP_INFO, - GET_PARAM_DPB_SIZE -}; - -/** - * struct vdec_fb_node - decoder frame buffer node - * @list : list to hold this node - * @fb : point to frame buffer (vdec_fb), fb could point to frame buffer and - * working buffer this is for maintain buffers in different state - */ -struct vdec_fb_node { - struct list_head list; - struct vdec_fb *fb; -}; - -/** - * vdec_if_init() - initialize decode driver - * @ctx : [in] v4l2 context - * @fourcc : [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9.. - */ -int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc); - -int vdec_if_probe(struct aml_vcodec_ctx *ctx, - struct aml_vcodec_mem *bs, void *out); - -/** - * vdec_if_deinit() - deinitialize decode driver - * @ctx : [in] v4l2 context - * - */ -void vdec_if_deinit(struct aml_vcodec_ctx *ctx); - -/** - * vdec_if_decode() - trigger decode - * @ctx : [in] v4l2 context - * @bs : [in] input bitstream - * @fb : [in] frame buffer to store decoded frame, when null menas parse - * header only - * @res_chg : [out] resolution change happens if current bs have different - * picture width/height - * Note: To flush the decoder when reaching EOF, set input bitstream as NULL. - * - * Return: 0 on success. -EIO on unrecoverable error. - */ -int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg); - -/** - * vdec_if_get_param() - get driver's parameter - * @ctx : [in] v4l2 context - * @type : [in] input parameter type - * @out : [out] buffer to store query result - */ -int vdec_if_get_param(struct aml_vcodec_ctx *ctx, enum vdec_get_param_type type, - void *out); - -#endif diff --git a/drivers/amlogic/media_modules/common/Makefile b/drivers/amlogic/media_modules/common/Makefile deleted file mode 100644 index 77ce080249db..000000000000 --- a/drivers/amlogic/media_modules/common/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += media_clock/ -obj-y += firmware/ diff --git a/drivers/amlogic/media_modules/common/chips/chips.c b/drivers/amlogic/media_modules/common/chips/chips.c deleted file mode 100644 index 63d55ba9fe99..000000000000 --- a/drivers/amlogic/media_modules/common/chips/chips.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/chips/chips.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../../stream_input/amports/amports_priv.h" -#include "../../frame_provider/decoder/utils/vdec.h" -#include "chips.h" -#include -#include -#include "decoder_cpu_ver_info.h" - -#define VIDEO_FIRMWARE_FATHER_NAME "video" - -/* - *#define MESON_CPU_MAJOR_ID_M6 0x16 - *#define MESON_CPU_MAJOR_ID_M6TV 0x17 - *#define MESON_CPU_MAJOR_ID_M6TVL 0x18 - *#define MESON_CPU_MAJOR_ID_M8 0x19 - *#define MESON_CPU_MAJOR_ID_MTVD 0x1A - *#define MESON_CPU_MAJOR_ID_M8B 0x1B - *#define MESON_CPU_MAJOR_ID_MG9TV 0x1C - *#define MESON_CPU_MAJOR_ID_M8M2 0x1D - *#define MESON_CPU_MAJOR_ID_GXBB 0x1F - *#define MESON_CPU_MAJOR_ID_GXTVBB 0x20 - *#define MESON_CPU_MAJOR_ID_GXL 0x21 - *#define MESON_CPU_MAJOR_ID_GXM 0x22 - *#define MESON_CPU_MAJOR_ID_TXL 0x23 - */ -struct type_name { - - int type; - - const char *name; -}; -static const struct type_name cpu_type_name[] = { - {AM_MESON_CPU_MAJOR_ID_M6, "m6"}, - {AM_MESON_CPU_MAJOR_ID_M6TV, "m6tv"}, - {AM_MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"}, - {AM_MESON_CPU_MAJOR_ID_M8, "m8"}, - {AM_MESON_CPU_MAJOR_ID_MTVD, "mtvd"}, - {AM_MESON_CPU_MAJOR_ID_M8B, "m8b"}, - {AM_MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"}, - {AM_MESON_CPU_MAJOR_ID_M8M2, "m8"}, - {AM_MESON_CPU_MAJOR_ID_GXBB, "gxbb"}, - {AM_MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"}, - {AM_MESON_CPU_MAJOR_ID_GXL, "gxl"}, - {AM_MESON_CPU_MAJOR_ID_GXM, "gxm"}, - {AM_MESON_CPU_MAJOR_ID_TXL, "txl"}, - {AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"}, - {AM_MESON_CPU_MAJOR_ID_G12A, "g12a"}, - {AM_MESON_CPU_MAJOR_ID_G12B, "g12b"}, - {AM_MESON_CPU_MAJOR_ID_SM1, "sm1"}, - {AM_MESON_CPU_MAJOR_ID_TL1, "tl1"}, - {AM_MESON_CPU_MAJOR_ID_TM2, "tm2"}, - {0, NULL}, -}; - -static const char *get_type_name(const struct type_name *typename, int size, - int type) -{ - - const char *name = "unknown"; - - int i; - - for (i = 0; i < size; i++) { - - if (type == typename[i].type) - - name = typename[i].name; - - } - - return name; -} - -const char *get_cpu_type_name(void) -{ - - return get_type_name(cpu_type_name, - sizeof(cpu_type_name) / sizeof(struct type_name), - get_cpu_major_id()); -} -EXPORT_SYMBOL(get_cpu_type_name); - -/* - *enum vformat_e { - * VFORMAT_MPEG12 = 0, - * VFORMAT_MPEG4, - * VFORMAT_H264, - * VFORMAT_MJPEG, - * VFORMAT_REAL, - * VFORMAT_JPEG, - * VFORMAT_VC1, - * VFORMAT_AVS, - * VFORMAT_YUV, - * VFORMAT_H264MVC, - * VFORMAT_H264_4K2K, - * VFORMAT_HEVC, - * VFORMAT_H264_ENC, - * VFORMAT_JPEG_ENC, - * VFORMAT_VP9, -* VFORMAT_AVS2, - * VFORMAT_MAX - *}; - */ -static const struct type_name vformat_type_name[] = { - {VFORMAT_MPEG12, "mpeg12"}, - {VFORMAT_MPEG4, "mpeg4"}, - {VFORMAT_H264, "h264"}, - {VFORMAT_MJPEG, "mjpeg"}, - {VFORMAT_REAL, "real"}, - {VFORMAT_JPEG, "jpeg"}, - {VFORMAT_VC1, "vc1"}, - {VFORMAT_AVS, "avs"}, - {VFORMAT_YUV, "yuv"}, - {VFORMAT_H264MVC, "h264mvc"}, - {VFORMAT_H264_4K2K, "h264_4k"}, - {VFORMAT_HEVC, "hevc"}, - {VFORMAT_H264_ENC, "h264_enc"}, - {VFORMAT_JPEG_ENC, "jpeg_enc"}, - {VFORMAT_VP9, "vp9"}, - {VFORMAT_AVS2, "avs2"}, - {VFORMAT_YUV, "yuv"}, - {0, NULL}, -}; - -const char *get_video_format_name(enum vformat_e type) -{ - - return get_type_name(vformat_type_name, - sizeof(vformat_type_name) / sizeof(struct type_name), type); -} -EXPORT_SYMBOL(get_video_format_name); - -static struct chip_vdec_info_s current_chip_info; - -struct chip_vdec_info_s *get_current_vdec_chip(void) -{ - - return ¤t_chip_info; -} -EXPORT_SYMBOL(get_current_vdec_chip); - -bool check_efuse_chip(int vformat) -{ - unsigned int status, i = 0; - int type[] = {15, 14, 11, 2}; /* avs2, vp9, h265, h264 */ - - status = (READ_EFUSE_REG(EFUSE_LIC2) >> 8 & 0xf); - if (!status) - return false; - - do { - if ((status & 1) && (type[i] == vformat)) - return true; - i++; - } while (status >>= 1); - - return false; -} -EXPORT_SYMBOL(check_efuse_chip); - diff --git a/drivers/amlogic/media_modules/common/chips/chips.h b/drivers/amlogic/media_modules/common/chips/chips.h deleted file mode 100644 index 003e9d2bf689..000000000000 --- a/drivers/amlogic/media_modules/common/chips/chips.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/chips/chips.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef UCODE_MANAGER_HEADER -#define UCODE_MANAGER_HEADER -#include "../media_clock/clk/clk_priv.h" - -struct chip_vdec_info_s { - - int cpu_type; - - struct video_firmware_s *firmware; - - struct chip_vdec_clk_s *clk_mgr[VDEC_MAX]; - - struct clk_set_setting *clk_setting_array; -}; - -const char *get_cpu_type_name(void); -const char *get_video_format_name(enum vformat_e type); - -struct chip_vdec_info_s *get_current_vdec_chip(void); - -bool check_efuse_chip(int vformat); - -#endif diff --git a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c deleted file mode 100644 index 7818a21b4844..000000000000 --- a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include "decoder_cpu_ver_info.h" - -#define DECODE_CPU_VER_ID_NODE_NAME "cpu_ver_name" -#define AM_SUCESS 0 -#define MAJOR_ID_START AM_MESON_CPU_MAJOR_ID_M6 - -static enum AM_MESON_CPU_MAJOR_ID cpu_ver_id = AM_MESON_CPU_MAJOR_ID_MAX; - -static enum AM_MESON_CPU_MAJOR_ID cpu_ver_info[AM_MESON_CPU_MAJOR_ID_MAX - MAJOR_ID_START]= -{ - AM_MESON_CPU_MAJOR_ID_M6, - AM_MESON_CPU_MAJOR_ID_M6TV, - AM_MESON_CPU_MAJOR_ID_M6TVL, - AM_MESON_CPU_MAJOR_ID_M8, - AM_MESON_CPU_MAJOR_ID_MTVD, - AM_MESON_CPU_MAJOR_ID_M8B, - AM_MESON_CPU_MAJOR_ID_MG9TV, - AM_MESON_CPU_MAJOR_ID_M8M2, - AM_MESON_CPU_MAJOR_ID_UNUSE, - AM_MESON_CPU_MAJOR_ID_GXBB, - AM_MESON_CPU_MAJOR_ID_GXTVBB, - AM_MESON_CPU_MAJOR_ID_GXL, - AM_MESON_CPU_MAJOR_ID_GXM, - AM_MESON_CPU_MAJOR_ID_TXL, - AM_MESON_CPU_MAJOR_ID_TXLX, - AM_MESON_CPU_MAJOR_ID_AXG, - AM_MESON_CPU_MAJOR_ID_GXLX, - AM_MESON_CPU_MAJOR_ID_TXHD, - AM_MESON_CPU_MAJOR_ID_G12A, - AM_MESON_CPU_MAJOR_ID_G12B, - AM_MESON_CPU_MAJOR_ID_GXLX2, - AM_MESON_CPU_MAJOR_ID_SM1, - AM_MESON_CPU_MAJOR_ID_RES_0x2c, - AM_MESON_CPU_MAJOR_ID_RES_0x2d, - AM_MESON_CPU_MAJOR_ID_TL1, - AM_MESON_CPU_MAJOR_ID_TM2, -}; - -static const struct of_device_id cpu_ver_of_match[] = { - { - .compatible = "amlogic, cpu-major-id-axg", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_AXG - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-g12a", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_G12A - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-gxl", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXL - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-gxm", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXM - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-txl", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXL - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-txlx", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXLX - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-sm1", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_SM1 - MAJOR_ID_START], - }, - - { - .compatible = "amlogic, cpu-major-id-tl1", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TL1 - MAJOR_ID_START], - }, - { - .compatible = "amlogic, cpu-major-id-tm2", - .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TM2 - MAJOR_ID_START], - }, - {}, -}; - -static bool get_cpu_id_from_dtb(enum AM_MESON_CPU_MAJOR_ID *pidType) -{ - struct device_node *pNode = NULL; - struct platform_device* pDev = NULL; - const struct of_device_id *pMatch = NULL; - - pNode = of_find_node_by_name(NULL, DECODE_CPU_VER_ID_NODE_NAME); - if (NULL == pNode) { - pr_err("No find node.\n"); - return -EINVAL; - } - - pDev = of_find_device_by_node(pNode); - if (NULL == pDev) - return -EINVAL; - - pMatch = of_match_device(cpu_ver_of_match, &pDev->dev); - if (NULL == pMatch) { - pr_err("No find of_match_device\n"); - return -EINVAL; - } - - *pidType = *(enum AM_MESON_CPU_MAJOR_ID *)pMatch->data; - - return AM_SUCESS; -} - -static void initial_cpu_id(void) -{ - enum AM_MESON_CPU_MAJOR_ID id_type = AM_MESON_CPU_MAJOR_ID_MAX; - - if (AM_SUCESS == get_cpu_id_from_dtb(&id_type)) - cpu_ver_id = id_type; - else - cpu_ver_id = (enum AM_MESON_CPU_MAJOR_ID)get_cpu_type(); - - if (AM_MESON_CPU_MAJOR_ID_G12B == cpu_ver_id) - if (is_meson_rev_b()) - cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1; -} - -enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void) -{ - if (AM_MESON_CPU_MAJOR_ID_MAX == cpu_ver_id) - initial_cpu_id(); - - return cpu_ver_id; -} -EXPORT_SYMBOL(get_cpu_major_id); diff --git a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h deleted file mode 100644 index 494f5f6fdbfd..000000000000 --- a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef DECODER_CPU_VER_INFO_H -#define DECODER_CPU_VER_INFO_H - -enum AM_MESON_CPU_MAJOR_ID -{ - AM_MESON_CPU_MAJOR_ID_M6 = 0x16, - AM_MESON_CPU_MAJOR_ID_M6TV = 0x17, - AM_MESON_CPU_MAJOR_ID_M6TVL = 0x18, - AM_MESON_CPU_MAJOR_ID_M8 = 0x19, - AM_MESON_CPU_MAJOR_ID_MTVD = 0x1A, - AM_MESON_CPU_MAJOR_ID_M8B = 0x1B, - AM_MESON_CPU_MAJOR_ID_MG9TV = 0x1C, - AM_MESON_CPU_MAJOR_ID_M8M2 = 0x1D, - AM_MESON_CPU_MAJOR_ID_UNUSE = 0x1E, - AM_MESON_CPU_MAJOR_ID_GXBB = 0x1F, - AM_MESON_CPU_MAJOR_ID_GXTVBB = 0x20, - AM_MESON_CPU_MAJOR_ID_GXL = 0x21, - AM_MESON_CPU_MAJOR_ID_GXM = 0x22, - AM_MESON_CPU_MAJOR_ID_TXL = 0x23, - AM_MESON_CPU_MAJOR_ID_TXLX = 0x24, - AM_MESON_CPU_MAJOR_ID_AXG = 0x25, - AM_MESON_CPU_MAJOR_ID_GXLX = 0x26, - AM_MESON_CPU_MAJOR_ID_TXHD = 0x27, - AM_MESON_CPU_MAJOR_ID_G12A = 0x28, - AM_MESON_CPU_MAJOR_ID_G12B = 0x29, - AM_MESON_CPU_MAJOR_ID_GXLX2 = 0x2a, - AM_MESON_CPU_MAJOR_ID_SM1 = 0x2b, - AM_MESON_CPU_MAJOR_ID_RES_0x2c, - AM_MESON_CPU_MAJOR_ID_RES_0x2d, - AM_MESON_CPU_MAJOR_ID_TL1 = 0x2e, - AM_MESON_CPU_MAJOR_ID_TM2 = 0x2f, - AM_MESON_CPU_MAJOR_ID_MAX, -}; - -enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void); -#endif diff --git a/drivers/amlogic/media_modules/common/firmware/Makefile b/drivers/amlogic/media_modules/common/firmware/Makefile deleted file mode 100644 index 748039cc1f71..000000000000 --- a/drivers/amlogic/media_modules/common/firmware/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-m += firmware.o -firmware-objs += firmware_drv.o -firmware-objs += firmware_type.o diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h deleted file mode 100644 index e23ac2ad41dd..000000000000 --- a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * drivers/amlogic/media/common/firmware/firmware_cfg.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/*all firmwares in one bin.*/ -{VIDEO_MISC, VIDEO_PACKAGE, "video_ucode.bin"}, - -/* Note: if the addition of new package has the same name */ -/* as the firmware in the video_ucode.bin, the firmware */ -/* in the video_ucode.bin will be ignored yet, because the */ -/* video_ucode.bin will always be processed in the end */ -{VIDEO_ENCODE, VIDEO_PACKAGE, "h264_enc.bin"}, - - -/*firmware for a special format, to replace the format in the package.*/ -/*{VIDEO_DECODE, VIDEO_FW_FILE, "h265.bin"},*/ -/*{VIDEO_DECODE, VIDEO_FW_FILE, "h264.bin"},*/ -/*{VIDEO_DECODE, VIDEO_FW_FILE, "h264_multi.bin"},*/ - diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c deleted file mode 100644 index f1ea44526448..000000000000 --- a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * drivers/amlogic/media/common/firmware/firmware.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../../stream_input/amports/amports_priv.h" -#include "../../frame_provider/decoder/utils/vdec.h" -#include "firmware_priv.h" -#include "../chips/chips.h" -#include -#include -#include -#include -#include -#include -#include -#include "../chips/decoder_cpu_ver_info.h" - -/* major.minor */ -#define PACK_VERS "v0.1" - -#define CLASS_NAME "firmware_codec" -#define DEV_NAME "firmware_vdec" -#define DIR "video" -#define FRIMWARE_SIZE (64 * 1024) /*64k*/ -#define BUFF_SIZE (1024 * 1024 * 2) - -#define FW_LOAD_FORCE (0x1) -#define FW_LOAD_TRY (0X2) - -/*the first 256 bytes are signature data*/ -#define SEC_OFFSET (256) - -#define PACK ('P' << 24 | 'A' << 16 | 'C' << 8 | 'K') -#define CODE ('C' << 24 | 'O' << 16 | 'D' << 8 | 'E') - -static DEFINE_MUTEX(mutex); - -static struct ucode_file_info_s ucode_info[] = { -#include "firmware_cfg.h" -}; - -static const struct file_operations fw_fops = { - .owner = THIS_MODULE -}; - -struct fw_mgr_s *g_mgr; -struct fw_dev_s *g_dev; - -static u32 debug; -static u32 detail; - -int get_firmware_data(unsigned int format, char *buf) -{ - int data_len, ret = -1; - struct fw_mgr_s *mgr = g_mgr; - struct fw_info_s *info; - - pr_info("[%s], the fw (%s) will be loaded.\n", - tee_enabled() ? "TEE" : "LOCAL", - get_fw_format_name(format)); - - if (tee_enabled()) - return 0; - - mutex_lock(&mutex); - - if (list_empty(&mgr->fw_head)) { - pr_info("the info list is empty.\n"); - goto out; - } - - list_for_each_entry(info, &mgr->fw_head, node) { - if (format != info->format) - continue; - - data_len = info->data->head.data_size; - memcpy(buf, info->data->data, data_len); - ret = data_len; - - break; - } -out: - mutex_unlock(&mutex); - - return ret; -} -EXPORT_SYMBOL(get_firmware_data); - -int get_data_from_name(const char *name, char *buf) -{ - int data_len, ret = -1; - struct fw_mgr_s *mgr = g_mgr; - struct fw_info_s *info; - char *fw_name = __getname(); - - if (fw_name == NULL) - return -ENOMEM; - - strcat(fw_name, name); - strcat(fw_name, ".bin"); - - mutex_lock(&mutex); - - if (list_empty(&mgr->fw_head)) { - pr_info("the info list is empty.\n"); - goto out; - } - - list_for_each_entry(info, &mgr->fw_head, node) { - if (strcmp(fw_name, info->name)) - continue; - - data_len = info->data->head.data_size; - memcpy(buf, info->data->data, data_len); - ret = data_len; - - break; - } -out: - mutex_unlock(&mutex); - - __putname(fw_name); - - return ret; -} -EXPORT_SYMBOL(get_data_from_name); - -static int fw_probe(char *buf) -{ - int magic = 0; - - memcpy(&magic, buf, sizeof(int)); - return magic; -} - -static int request_firmware_from_sys(const char *file_name, - char *buf, int size) -{ - int ret = -1; - const struct firmware *fw; - int magic, offset = 0; - - pr_info("Try to load %s ...\n", file_name); - - ret = request_firmware(&fw, file_name, g_dev->dev); - if (ret < 0) { - pr_info("Error : %d can't load the %s.\n", ret, file_name); - goto err; - } - - if (fw->size > size) { - pr_info("Not enough memory size for ucode.\n"); - ret = -ENOMEM; - goto release; - } - - magic = fw_probe((char *)fw->data); - if (magic != PACK && magic != CODE) { - if (fw->size < SEC_OFFSET) { - pr_info("This is an invalid firmware file.\n"); - goto release; - } - - magic = fw_probe((char *)fw->data + SEC_OFFSET); - if (magic != PACK) { - pr_info("The firmware file is not packet.\n"); - goto release; - } - - offset = SEC_OFFSET; - } - - memcpy(buf, (char *)fw->data + offset, fw->size - offset); - - pr_info("load firmware size : %zd, Name : %s.\n", - fw->size, file_name); - ret = fw->size; -release: - release_firmware(fw); -err: - return ret; -} - -int request_decoder_firmware_on_sys(enum vformat_e format, - const char *file_name, char *buf, int size) -{ - int ret; - - ret = get_data_from_name(file_name, buf); - if (ret < 0) - pr_info("Get firmware fail.\n"); - - if (ret > size) { - pr_info("Not enough memory.\n"); - return -ENOMEM; - } - - return ret; -} -int get_decoder_firmware_data(enum vformat_e format, - const char *file_name, char *buf, int size) -{ - int ret; - - ret = request_decoder_firmware_on_sys(format, file_name, buf, size); - if (ret < 0) - pr_info("get_decoder_firmware_data %s for format %d failed!\n", - file_name, format); - - return ret; -} -EXPORT_SYMBOL(get_decoder_firmware_data); - -static unsigned long fw_mgr_lock(struct fw_mgr_s *mgr) -{ - unsigned long flags; - - spin_lock_irqsave(&mgr->lock, flags); - return flags; -} - -static void fw_mgr_unlock(struct fw_mgr_s *mgr, unsigned long flags) -{ - spin_unlock_irqrestore(&mgr->lock, flags); -} - -static void fw_add_info(struct fw_info_s *info) -{ - unsigned long flags; - struct fw_mgr_s *mgr = g_mgr; - - flags = fw_mgr_lock(mgr); - list_add(&info->node, &mgr->fw_head); - fw_mgr_unlock(mgr, flags); -} - -static void fw_del_info(struct fw_info_s *info) -{ - unsigned long flags; - struct fw_mgr_s *mgr = g_mgr; - - flags = fw_mgr_lock(mgr); - list_del(&info->node); - kfree(info); - fw_mgr_unlock(mgr, flags); -} - -static void fw_info_walk(void) -{ - struct fw_mgr_s *mgr = g_mgr; - struct fw_info_s *info; - - if (list_empty(&mgr->fw_head)) { - pr_info("the info list is empty.\n"); - return; - } - - list_for_each_entry(info, &mgr->fw_head, node) { - if (IS_ERR_OR_NULL(info->data)) - continue; - - pr_info("name : %s.\n", info->name); - pr_info("ver : %s.\n", - info->data->head.version); - pr_info("crc : 0x%x.\n", - info->data->head.checksum); - pr_info("size : %d.\n", - info->data->head.data_size); - pr_info("maker: %s.\n", - info->data->head.maker); - pr_info("from : %s.\n", info->src_from); - pr_info("date : %s.\n\n", - info->data->head.date); - } -} - -static void fw_files_info_walk(void) -{ - struct fw_mgr_s *mgr = g_mgr; - struct fw_files_s *files; - - if (list_empty(&mgr->files_head)) { - pr_info("the file list is empty.\n"); - return; - } - - list_for_each_entry(files, &mgr->files_head, node) { - pr_info("type : %s.\n", !files->fw_type ? - "VIDEO_DECODE" : files->fw_type == 1 ? - "VIDEO_ENCODE" : "VIDEO_MISC"); - pr_info("from : %s.\n", !files->file_type ? - "VIDEO_PACKAGE" : "VIDEO_FW_FILE"); - pr_info("path : %s.\n", files->path); - pr_info("name : %s.\n\n", files->name); - } -} - -static ssize_t info_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct fw_mgr_s *mgr = g_mgr; - struct fw_info_s *info; - unsigned int secs = 0; - struct tm tm; - - mutex_lock(&mutex); - - if (list_empty(&mgr->fw_head)) { - pbuf += sprintf(pbuf, "No firmware.\n"); - goto out; - } - - list_for_each_entry(info, &mgr->fw_head, node) { - if (IS_ERR_OR_NULL(info->data)) - continue; - - if (detail) { - pr_info("%-5s: %s\n", "name", info->name); - pr_info("%-5s: %s\n", "ver", - info->data->head.version); - pr_info("%-5s: 0x%x\n", "sum", - info->data->head.checksum); - pr_info("%-5s: %d\n", "size", - info->data->head.data_size); - pr_info("%-5s: %s\n", "maker", - info->data->head.maker); - pr_info("%-5s: %s\n", "from", - info->src_from); - pr_info("%-5s: %s\n\n", "date", - info->data->head.date); - continue; - } - - secs = info->data->head.time - - sys_tz.tz_minuteswest * 60; - time_to_tm(secs, 0, &tm); - - pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %-8s, %s %s\n", - "fmt:", info->data->head.format, - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, - "cmtid:", info->data->head.commit, - "chgid:", info->data->head.change_id, - "mk:", info->data->head.maker); - } -out: - mutex_unlock(&mutex); - - return pbuf - buf; -} - -static ssize_t info_store(struct class *cls, - struct class_attribute *attr, const char *buf, size_t count) -{ - if (kstrtoint(buf, 0, &detail) < 0) - return -EINVAL; - - return count; -} - -static int fw_info_fill(void) -{ - int ret = 0, i, len; - struct fw_mgr_s *mgr = g_mgr; - struct fw_files_s *files; - int info_size = ARRAY_SIZE(ucode_info); - char *path = __getname(); - const char *name; - - if (path == NULL) - return -ENOMEM; - - for (i = 0; i < info_size; i++) { - name = ucode_info[i].name; - if (IS_ERR_OR_NULL(name)) - break; - - len = snprintf(path, PATH_MAX, "%s/%s", DIR, - ucode_info[i].name); - if (len >= PATH_MAX) - continue; - - files = kzalloc(sizeof(struct fw_files_s), GFP_KERNEL); - if (files == NULL) { - __putname(path); - return -ENOMEM; - } - - files->file_type = ucode_info[i].file_type; - files->fw_type = ucode_info[i].fw_type; - strncpy(files->path, path, sizeof(files->path)); - files->path[sizeof(files->path) - 1] = '\0'; - strncpy(files->name, name, sizeof(files->name)); - files->name[sizeof(files->name) - 1] = '\0'; - - list_add(&files->node, &mgr->files_head); - } - - __putname(path); - - if (debug) - fw_files_info_walk(); - - return ret; -} - -static int fw_data_check_sum(struct firmware_s *fw) -{ - unsigned int crc; - - crc = crc32_le(~0U, fw->data, fw->head.data_size); - - /*pr_info("firmware crc result : 0x%x\n", crc ^ ~0U);*/ - - return fw->head.checksum != (crc ^ ~0U) ? 0 : 1; -} - -static int fw_data_filter(struct firmware_s *fw, - struct fw_info_s *fw_info) -{ - struct fw_mgr_s *mgr = g_mgr; - struct fw_info_s *info, *tmp; - int cpu = fw_get_cpu(fw->head.cpu); - - if (mgr->cur_cpu < cpu) { - kfree(fw_info); - kfree(fw); - return -1; - } - - /* the encode fw need to ignoring filtering rules. */ - if (fw_info->format == FIRMWARE_MAX) - return 0; - - list_for_each_entry_safe(info, tmp, &mgr->fw_head, node) { - if (info->format != fw_info->format) - continue; - - if (IS_ERR_OR_NULL(info->data)) { - fw_del_info(info); - return 0; - } - - /* high priority of VIDEO_FW_FILE */ - if (info->file_type == VIDEO_FW_FILE) { - pr_info("the %s need to priority proc.\n",info->name); - kfree(fw_info); - kfree(fw); - return 1; - } - - /* the cpu ver is lower and needs to be filtered */ - if (cpu < fw_get_cpu(info->data->head.cpu)) { - if (debug) - pr_info("keep the newer fw (%s) and ignore the older fw (%s).\n", - info->name, fw_info->name); - kfree(fw_info); - kfree(fw); - return 1; - } - - /* removes not match fw from info list */ - if (debug) - pr_info("drop the old fw (%s) will be load the newer fw (%s).\n", - info->name, fw_info->name); - kfree(info->data); - fw_del_info(info); - } - - return 0; -} - -static int fw_check_pack_version(char *buf) -{ - struct package_s *pack = NULL; - int major, minor, major_fw, minor_fw, ver = 0; - int ret; - - pack = (struct package_s *) buf; - ret = sscanf(PACK_VERS, "v%x.%x", &major, &minor); - if (ret != 2) - return -1; - - ver = (major << 16 | minor); - - if (debug) - pr_info("the package has %d fws totally.\n", pack->head.total); - - major_fw = (pack->head.version >> 16) & 0xff; - minor_fw = pack->head.version & 0xff; - - if (major < major_fw) { - pr_info("the pack ver v%d.%d too higher to unsupport.\n", - major_fw, minor_fw); - return -1; - } - - if (ver != pack->head.version) { - pr_info("the fw pack ver v%d.%d is too lower.\n", major_fw, minor_fw); - pr_info("it may work abnormally so need to be update in time.\n"); - } - - return 0; -} - -static int fw_package_parse(struct fw_files_s *files, - char *buf, int size) -{ - int ret = 0; - struct package_info_s *pack_info; - struct fw_info_s *info; - struct firmware_s *data; - char *pack_data; - int info_len, len; - int try_cnt = 100; - char *path = __getname(); - - if (path == NULL) - return -ENOMEM; - - pack_data = ((struct package_s *)buf)->data; - pack_info = (struct package_info_s *)pack_data; - info_len = sizeof(struct package_info_s); - - do { - if (!pack_info->head.length) - break; - - len = snprintf(path, PATH_MAX, "%s/%s", DIR, - pack_info->head.name); - if (len >= PATH_MAX) - continue; - - info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL); - if (info == NULL) { - ret = -ENOMEM; - goto out; - } - - data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); - if (data == NULL) { - kfree(info); - ret = -ENOMEM; - goto out; - } - - info->file_type = files->file_type; - strncpy(info->src_from, files->name, - sizeof(info->src_from)); - info->src_from[sizeof(info->src_from) - 1] = '\0'; - strncpy(info->name, pack_info->head.name, - sizeof(info->name)); - info->name[sizeof(info->name) - 1] = '\0'; - info->format = get_fw_format(pack_info->head.format); - - len = pack_info->head.length; - memcpy(data, pack_info->data, len); - - pack_data += (pack_info->head.length + info_len); - pack_info = (struct package_info_s *)pack_data; - - if (!fw_data_check_sum(data)) { - pr_info("check sum fail !\n"); - kfree(data); - kfree(info); - goto out; - } - - if (fw_data_filter(data, info)) - continue; - - if (debug) - pr_info("adds %s to the fw list.\n", info->name); - - info->data = data; - fw_add_info(info); - } while (try_cnt--); -out: - __putname(path); - - return ret; -} - -static int fw_code_parse(struct fw_files_s *files, - char *buf, int size) -{ - struct fw_info_s *info; - - info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL); - if (info == NULL) - return -ENOMEM; - - info->data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); - if (info->data == NULL) { - kfree(info); - return -ENOMEM; - } - - info->file_type = files->file_type; - strncpy(info->src_from, files->name, - sizeof(info->src_from)); - info->src_from[sizeof(info->src_from) - 1] = '\0'; - memcpy(info->data, buf, size); - - if (!fw_data_check_sum(info->data)) { - pr_info("check sum fail !\n"); - kfree(info->data); - kfree(info); - return -1; - } - - if (debug) - pr_info("adds %s to the fw list.\n", info->name); - - fw_add_info(info); - - return 0; -} - -static int get_firmware_from_sys(const char *path, - char *buf, int size) -{ - int len = 0; - - len = request_firmware_from_sys(path, buf, size); - if (len < 0) - pr_info("get data from fsys fail.\n"); - - return len; -} - -static int fw_data_binding(void) -{ - int ret = 0, magic = 0; - struct fw_mgr_s *mgr = g_mgr; - struct fw_files_s *files, *tmp; - char *buf = NULL; - int size; - - if (list_empty(&mgr->files_head)) { - pr_info("the file list is empty.\n"); - return 0; - } - - buf = vmalloc(BUFF_SIZE); - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - memset(buf, 0, BUFF_SIZE); - - list_for_each_entry_safe(files, tmp, &mgr->files_head, node) { - size = get_firmware_from_sys(files->path, buf, BUFF_SIZE); - magic = fw_probe(buf); - - if (files->file_type == VIDEO_PACKAGE && magic == PACK) { - if (!fw_check_pack_version(buf)) - ret = fw_package_parse(files, buf, size); - } else if (files->file_type == VIDEO_FW_FILE && magic == CODE) { - ret = fw_code_parse(files, buf, size); - } else { - list_del(&files->node); - kfree(files); - pr_info("invaild file type.\n"); - } - - memset(buf, 0, BUFF_SIZE); - } - - if (debug) - fw_info_walk(); - - vfree(buf); - - return ret; -} - -static int fw_pre_load(void) -{ - if (fw_info_fill() < 0) { - pr_info("Get path fail.\n"); - return -1; - } - - if (fw_data_binding() < 0) { - pr_info("Set data fail.\n"); - return -1; - } - - return 0; -} - -static int fw_mgr_init(void) -{ - g_mgr = kzalloc(sizeof(struct fw_mgr_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(g_mgr)) - return -ENOMEM; - - g_mgr->cur_cpu = get_cpu_major_id(); - INIT_LIST_HEAD(&g_mgr->files_head); - INIT_LIST_HEAD(&g_mgr->fw_head); - spin_lock_init(&g_mgr->lock); - - return 0; -} - -static void fw_ctx_clean(void) -{ - struct fw_mgr_s *mgr = g_mgr; - struct fw_files_s *files; - struct fw_info_s *info; - unsigned long flags; - - flags = fw_mgr_lock(mgr); - while (!list_empty(&mgr->files_head)) { - files = list_entry(mgr->files_head.next, - struct fw_files_s, node); - list_del(&files->node); - kfree(files); - } - - while (!list_empty(&mgr->fw_head)) { - info = list_entry(mgr->fw_head.next, - struct fw_info_s, node); - list_del(&info->node); - kfree(info->data); - kfree(info); - } - fw_mgr_unlock(mgr, flags); -} - -int video_fw_reload(int mode) -{ - int ret = 0; - struct fw_mgr_s *mgr = g_mgr; - - if (tee_enabled()) - return 0; - - mutex_lock(&mutex); - - if (mode & FW_LOAD_FORCE) { - fw_ctx_clean(); - - ret = fw_pre_load(); - if (ret < 0) - pr_err("The fw reload fail.\n"); - } else if (mode & FW_LOAD_TRY) { - if (!list_empty(&mgr->fw_head)) { - pr_info("The fw has been loaded.\n"); - goto out; - } - - ret = fw_pre_load(); - if (ret < 0) - pr_err("The fw try to reload fail.\n"); - } -out: - mutex_unlock(&mutex); - - return ret; -} -EXPORT_SYMBOL(video_fw_reload); - -static ssize_t reload_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - - pbuf += sprintf(pbuf, "The fw reload usage.\n"); - pbuf += sprintf(pbuf, "> set 1 means that the fw is forced to update\n"); - pbuf += sprintf(pbuf, "> set 2 means that the fw is try to reload\n"); - - return pbuf - buf; -} - -static ssize_t reload_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int ret = -1; - unsigned int val; - - ret = kstrtoint(buf, 0, &val); - if (ret != 0) - return -EINVAL; - - ret = video_fw_reload(val); - if (ret < 0) - pr_err("fw reload fail.\n"); - - return size; -} - -static ssize_t debug_show(struct class *cls, - struct class_attribute *attr, char *buf) -{ - return sprintf(buf, "%x\n", debug); -} - -static ssize_t debug_store(struct class *cls, - struct class_attribute *attr, const char *buf, size_t count) -{ - if (kstrtoint(buf, 0, &debug) < 0) - return -EINVAL; - - return count; -} - -static struct class_attribute fw_class_attrs[] = { - __ATTR(info, 0664, info_show, info_store), - __ATTR(reload, 0664, reload_show, reload_store), - __ATTR(debug, 0664, debug_show, debug_store), - __ATTR_NULL -}; - -static struct class fw_class = { - .name = CLASS_NAME, - .class_attrs = fw_class_attrs, -}; - -static int fw_driver_init(void) -{ - int ret = -1; - - g_dev = kzalloc(sizeof(struct fw_dev_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(g_dev)) - return -ENOMEM; - - g_dev->dev_no = MKDEV(AMSTREAM_MAJOR, 100); - - ret = register_chrdev_region(g_dev->dev_no, 1, DEV_NAME); - if (ret < 0) { - pr_info("Can't get major number %d.\n", AMSTREAM_MAJOR); - goto err; - } - - cdev_init(&g_dev->cdev, &fw_fops); - g_dev->cdev.owner = THIS_MODULE; - - ret = cdev_add(&g_dev->cdev, g_dev->dev_no, 1); - if (ret) { - pr_info("Error %d adding cdev fail.\n", ret); - goto err; - } - - ret = class_register(&fw_class); - if (ret < 0) { - pr_info("Failed in creating class.\n"); - goto err; - } - - g_dev->dev = device_create(&fw_class, NULL, - g_dev->dev_no, NULL, DEV_NAME); - if (IS_ERR_OR_NULL(g_dev->dev)) { - pr_info("Create device failed.\n"); - ret = -ENODEV; - goto err; - } - - pr_info("Registered firmware driver success.\n"); -err: - return ret; -} - -static void fw_driver_exit(void) -{ - cdev_del(&g_dev->cdev); - device_destroy(&fw_class, g_dev->dev_no); - class_unregister(&fw_class); - unregister_chrdev_region(g_dev->dev_no, 1); - kfree(g_dev); - kfree(g_mgr); -} - -static int __init fw_module_init(void) -{ - int ret = -1; - - ret = fw_driver_init(); - if (ret) { - pr_info("Error %d firmware driver init fail.\n", ret); - goto err; - } - - ret = fw_mgr_init(); - if (ret) { - pr_info("Error %d firmware mgr init fail.\n", ret); - goto err; - } - - ret = fw_pre_load(); - if (ret) { - pr_info("Error %d firmware pre load fail.\n", ret); - goto err; - } -err: - return ret; -} - -static void __exit fw_module_exit(void) -{ - fw_ctx_clean(); - fw_driver_exit(); - pr_info("Firmware driver cleaned up.\n"); -} - -module_init(fw_module_init); -module_exit(fw_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Nanxin Qin "); diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_priv.h b/drivers/amlogic/media_modules/common/firmware/firmware_priv.h deleted file mode 100644 index b8c4da876246..000000000000 --- a/drivers/amlogic/media_modules/common/firmware/firmware_priv.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * drivers/amlogic/media/common/firmware/firmware.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#ifndef __VIDEO_FIRMWARE_PRIV_HEAD_ -#define __VIDEO_FIRMWARE_PRIV_HEAD_ -#include -#include -#include -#include -#include "firmware_type.h" - -struct fw_mgr_s { - struct list_head fw_head; - struct list_head files_head; - spinlock_t lock; - int cur_cpu; -}; - -struct fw_files_s { - struct list_head node; - int fw_type; - int file_type; - char name[32]; - char path[64]; -}; - -struct ucode_file_info_s { - int fw_type; - int file_type; - const char *name; -}; - -struct fw_info_s { - struct list_head node; - char name[32]; - char src_from[32]; - int file_type; - unsigned int format; - struct firmware_s *data; -}; - -struct fw_head_s { - int magic; - int checksum; - char name[32]; - char cpu[16]; - char format[32]; - char version[32]; - char maker[32]; - char date[32]; - char commit[16]; - int data_size; - unsigned int time; - char change_id[16]; - char reserved[112]; -}; - -struct firmware_s { - union { - struct fw_head_s head; - char buf[512]; - }; - char data[0]; -}; - -struct package_head_s { - int magic; - int size; - int checksum; - int total; - int version; - char reserved[128]; -}; - -struct package_s { - union { - struct package_head_s head; - char buf[256]; - }; - char data[0]; -}; - -struct info_head_s { - char name[32]; - char format[32]; - char cpu[32]; - int length; -}; - -struct package_info_s { - union { - struct info_head_s head; - char buf[256]; - }; - char data[0]; -}; - -struct fw_dev_s { - struct cdev cdev; - struct device *dev; - dev_t dev_no; -}; - -#endif diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.c b/drivers/amlogic/media_modules/common/firmware/firmware_type.c deleted file mode 100644 index 609ff6e8611d..000000000000 --- a/drivers/amlogic/media_modules/common/firmware/firmware_type.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include "firmware_type.h" -#include "../chips/decoder_cpu_ver_info.h" - -static const struct format_name_s format_name[] = { - {VIDEO_DEC_MPEG12, "mpeg12"}, - {VIDEO_DEC_MPEG12_MULTI, "mpeg12_multi"}, - {VIDEO_DEC_MPEG4_3, "mpeg4_3"}, - {VIDEO_DEC_MPEG4_4, "mpeg4_4"}, - {VIDEO_DEC_MPEG4_4_MULTI, "mpeg4_4_multi"}, - {VIDEO_DEC_MPEG4_5, "xvid"}, - {VIDEO_DEC_MPEG4_5_MULTI, "xvid_multi"}, - {VIDEO_DEC_H263, "h263"}, - {VIDEO_DEC_H263_MULTI, "h263_multi"}, - {VIDEO_DEC_MJPEG, "mjpeg"}, - {VIDEO_DEC_MJPEG_MULTI, "mjpeg_multi"}, - {VIDEO_DEC_REAL_V8, "real_v8"}, - {VIDEO_DEC_REAL_V9, "real_v9"}, - {VIDEO_DEC_VC1, "vc1"}, - {VIDEO_DEC_VC1_G12A, "vc1_g12a"}, - {VIDEO_DEC_AVS, "avs"}, - {VIDEO_DEC_AVS_GXM, "avs_gxm"}, - {VIDEO_DEC_AVS_NOCABAC, "avs_no_cabac"}, - {VIDEO_DEC_H264, "h264"}, - {VIDEO_DEC_H264_MVC, "h264_mvc"}, - {VIDEO_DEC_H264_MVC_GXM, "h264_mvc_gxm"}, - {VIDEO_DEC_H264_MULTI, "h264_multi"}, - {VIDEO_DEC_H264_MULTI_MMU, "h264_multi_mmu"}, - {VIDEO_DEC_H264_MULTI_GXM, "h264_multi_gxm"}, - {VIDEO_DEC_HEVC, "hevc"}, - {VIDEO_DEC_HEVC_MMU, "hevc_mmu"}, - {VIDEO_DEC_HEVC_MMU_SWAP, "hevc_mmu_swap"}, - {VIDEO_DEC_HEVC_G12A, "hevc_g12a"}, - {VIDEO_DEC_VP9, "vp9"}, - {VIDEO_DEC_VP9_MMU, "vp9_mmu"}, - {VIDEO_DEC_VP9_G12A, "vp9_g12a"}, - {VIDEO_DEC_AVS2, "avs2"}, - {VIDEO_DEC_AVS2_MMU, "avs2_mmu"}, - {VIDEO_ENC_H264, "h264_enc"}, - {VIDEO_ENC_JPEG, "jpeg_enc"}, - {FIRMWARE_MAX, "unknown"}, -}; - -static const struct cpu_type_s cpu_type[] = { - {AM_MESON_CPU_MAJOR_ID_GXL, "gxl"}, - {AM_MESON_CPU_MAJOR_ID_GXM, "gxm"}, - {AM_MESON_CPU_MAJOR_ID_TXL, "txl"}, - {AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"}, - {AM_MESON_CPU_MAJOR_ID_AXG, "axg"}, - {AM_MESON_CPU_MAJOR_ID_GXLX, "gxlx"}, - {AM_MESON_CPU_MAJOR_ID_TXHD, "txhd"}, - {AM_MESON_CPU_MAJOR_ID_G12A, "g12a"}, - {AM_MESON_CPU_MAJOR_ID_G12B, "g12b"}, - {AM_MESON_CPU_MAJOR_ID_GXLX2, "gxlx2"}, - {AM_MESON_CPU_MAJOR_ID_SM1, "sm1"}, - {AM_MESON_CPU_MAJOR_ID_TL1, "tl1"}, - {AM_MESON_CPU_MAJOR_ID_TM2, "tm2"}, -}; - -const char *get_fw_format_name(unsigned int format) -{ - const char *name = "unknown"; - int i, size = ARRAY_SIZE(format_name); - - for (i = 0; i < size; i++) { - if (format == format_name[i].format) - name = format_name[i].name; - } - - return name; -} -EXPORT_SYMBOL(get_fw_format_name); - -unsigned int get_fw_format(const char *name) -{ - unsigned int format = FIRMWARE_MAX; - int i, size = ARRAY_SIZE(format_name); - - for (i = 0; i < size; i++) { - if (!strcmp(name, format_name[i].name)) - format = format_name[i].format; - } - - return format; -} -EXPORT_SYMBOL(get_fw_format); - -int fw_get_cpu(const char *name) -{ - int type = 0; - int i, size = ARRAY_SIZE(cpu_type); - - for (i = 0; i < size; i++) { - if (!strcmp(name, cpu_type[i].name)) - type = cpu_type[i].type; - } - - return type; -} -EXPORT_SYMBOL(fw_get_cpu); - diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.h b/drivers/amlogic/media_modules/common/firmware/firmware_type.h deleted file mode 100644 index 6c1b3f7bcd7e..000000000000 --- a/drivers/amlogic/media_modules/common/firmware/firmware_type.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __VIDEO_FIRMWARE_FORMAT_ -#define __VIDEO_FIRMWARE_FORMAT_ - -#include - -/* example: #define VIDEO_DEC_AV1 TAG('A', 'V', '1', '-')*/ -#define TAG(a, b, c, d)\ - ((a << 24) | (b << 16) | (c << 8) | d) - -/* fws define */ -#define VIDEO_DEC_MPEG12 (0) -#define VIDEO_DEC_MPEG4_3 (1) -#define VIDEO_DEC_MPEG4_4 (2) -#define VIDEO_DEC_MPEG4_5 (3) -#define VIDEO_DEC_H263 (4) -#define VIDEO_DEC_MJPEG (5) -#define VIDEO_DEC_MJPEG_MULTI (6) -#define VIDEO_DEC_REAL_V8 (7) -#define VIDEO_DEC_REAL_V9 (8) -#define VIDEO_DEC_VC1 (9) -#define VIDEO_DEC_AVS (10) -#define VIDEO_DEC_H264 (11) -#define VIDEO_DEC_H264_4k2K (12) -#define VIDEO_DEC_H264_4k2K_SINGLE (13) -#define VIDEO_DEC_H264_MVC (14) -#define VIDEO_DEC_H264_MULTI (15) -#define VIDEO_DEC_HEVC (16) -#define VIDEO_DEC_HEVC_MMU (17) -#define VIDEO_DEC_VP9 (18) -#define VIDEO_DEC_VP9_MMU (19) -#define VIDEO_ENC_H264 (20) -#define VIDEO_ENC_JPEG (21) -#define VIDEO_DEC_H264_MULTI_MMU (23) -#define VIDEO_DEC_HEVC_G12A (24) -#define VIDEO_DEC_VP9_G12A (25) -#define VIDEO_DEC_AVS2 (26) -#define VIDEO_DEC_AVS2_MMU (27) -#define VIDEO_DEC_AVS_GXM (28) -#define VIDEO_DEC_AVS_NOCABAC (29) -#define VIDEO_DEC_H264_MULTI_GXM (30) -#define VIDEO_DEC_H264_MVC_GXM (31) -#define VIDEO_DEC_VC1_G12A (32) -#define VIDEO_DEC_MPEG12_MULTI TAG('M', '1', '2', 'M') -#define VIDEO_DEC_MPEG4_4_MULTI TAG('M', '4', '4', 'M') -#define VIDEO_DEC_MPEG4_5_MULTI TAG('M', '4', '5', 'M') -#define VIDEO_DEC_H263_MULTI TAG('2', '6', '3', 'M') -#define VIDEO_DEC_HEVC_MMU_SWAP TAG('2', '6', '5', 'S') -/* ... */ -#define FIRMWARE_MAX (UINT_MAX) - -#define VIDEO_PACKAGE (0) -#define VIDEO_FW_FILE (1) - -#define VIDEO_DECODE (0) -#define VIDEO_ENCODE (1) -#define VIDEO_MISC (2) - -#define OPTEE_VDEC_LEGENCY (0) -#define OPTEE_VDEC (1) -#define OPTEE_VDEC_HEVC (2) - -struct format_name_s { - unsigned int format; - const char *name; -}; - -struct cpu_type_s { - int type; - const char *name; -}; - -const char *get_fw_format_name(unsigned int format); -unsigned int get_fw_format(const char *name); -int fw_get_cpu(const char *name); - -#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/Makefile b/drivers/amlogic/media_modules/common/media_clock/Makefile deleted file mode 100644 index 975b5e57c452..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-m += media_clock.o -media_clock-objs += ../chips/chips.o -media_clock-objs += clk/clkg12.o -media_clock-objs += clk/clk.o -media_clock-objs += switch/amports_gate.o -media_clock-objs += ../chips/decoder_cpu_ver_info.o diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c deleted file mode 100644 index b60a08d0805b..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/clk/clk.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../../../frame_provider/decoder/utils/vdec.h" -#include "../../chips/chips.h" -#include "clk_priv.h" -#include -#include "../../chips/decoder_cpu_ver_info.h" - -#define p_vdec() (get_current_vdec_chip()->clk_mgr[VDEC_1]) -#define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2]) -#define p_vdec_hcodec() (get_current_vdec_chip()->clk_mgr[VDEC_HCODEC]) -#define p_vdec_hevc() (get_current_vdec_chip()->clk_mgr[VDEC_HEVC]) -#define p_vdec_hevc_back() (get_current_vdec_chip()->clk_mgr[VDEC_HEVCB]) - -static int clock_source_wxhxfps_saved[VDEC_MAX + 1]; - -#define IF_HAVE_RUN(p, fn)\ - do {\ - if (p && p->fn)\ - p->fn();\ - } while (0) -/* - *#define IF_HAVE_RUN_P1_RET(p, fn, p1)\ - * do {\ - * pr_debug("%s-----%d\n", __func__, clk);\ - * if (p && p->fn)\ - * return p->fn(p1);\ - * else\ - * return -1;\ - * } while (0) - * - *#define IF_HAVE_RUN_RET(p, fn)\ - * do {\ - * if (p && p->fn)\ - * return p->fn();\ - * else\ - * return 0;\ - * } while (0) - */ - -int vdec_clock_init(void) -{ - if (p_vdec() && p_vdec()->clock_init) - return p_vdec()->clock_init(); - else - return 0; -} -EXPORT_SYMBOL(vdec_clock_init); - -/* - *clk ==0 : - * to be release. - * released shared clk, - *clk ==1 :default low clk - *clk ==2 :default high clk - */ -int vdec_clock_set(int clk) -{ - pr_debug("%s-----%d\n", __func__, clk); - if (p_vdec() && p_vdec()->clock_set) - return p_vdec()->clock_set(clk); - else - return -1; -} -EXPORT_SYMBOL(vdec_clock_set); - -void vdec_clock_enable(void) -{ - vdec_clock_set(1); -} -EXPORT_SYMBOL(vdec_clock_enable); - -void vdec_clock_hi_enable(void) -{ - vdec_clock_set(2); -} -EXPORT_SYMBOL(vdec_clock_hi_enable); - -void vdec_clock_on(void) -{ - IF_HAVE_RUN(p_vdec(), clock_on); -} -EXPORT_SYMBOL(vdec_clock_on); - -void vdec_clock_off(void) -{ - IF_HAVE_RUN(p_vdec(), clock_off); - clock_source_wxhxfps_saved[VDEC_1] = 0; -} -EXPORT_SYMBOL(vdec_clock_off); - -int vdec2_clock_set(int clk) -{ - pr_debug("%s-----%d\n", __func__, clk); - if (p_vdec2() && p_vdec2()->clock_set) - return p_vdec2()->clock_set(clk); - else - return -1; -} -EXPORT_SYMBOL(vdec2_clock_set); - -void vdec2_clock_enable(void) -{ - vdec2_clock_set(1); -} -EXPORT_SYMBOL(vdec2_clock_enable); - -void vdec2_clock_hi_enable(void) -{ - vdec2_clock_set(2); -} -EXPORT_SYMBOL(vdec2_clock_hi_enable); - -void vdec2_clock_on(void) -{ - IF_HAVE_RUN(p_vdec2(), clock_on); -} -EXPORT_SYMBOL(vdec2_clock_on); - -void vdec2_clock_off(void) -{ - IF_HAVE_RUN(p_vdec2(), clock_off); - clock_source_wxhxfps_saved[VDEC_2] = 0; -} -EXPORT_SYMBOL(vdec2_clock_off); - -int hcodec_clock_set(int clk) -{ - pr_debug("%s-----%d\n", __func__, clk); - if (p_vdec_hcodec() && p_vdec_hcodec()->clock_set) - return p_vdec_hcodec()->clock_set(clk); - else - return -1; -} -EXPORT_SYMBOL(hcodec_clock_set); - -void hcodec_clock_enable(void) -{ - hcodec_clock_set(1); -} -EXPORT_SYMBOL(hcodec_clock_enable); - -void hcodec_clock_hi_enable(void) -{ - hcodec_clock_set(2); -} -EXPORT_SYMBOL(hcodec_clock_hi_enable); - -void hcodec_clock_on(void) -{ - IF_HAVE_RUN(p_vdec_hcodec(), clock_on); -} -EXPORT_SYMBOL(hcodec_clock_on); - -void hcodec_clock_off(void) -{ - IF_HAVE_RUN(p_vdec_hcodec(), clock_off); - clock_source_wxhxfps_saved[VDEC_HCODEC] = 0; -} -EXPORT_SYMBOL(hcodec_clock_off); - -int hevc_back_clock_init(void) -{ - if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_init) - return p_vdec_hevc_back()->clock_init(); - else - return 0; -} -EXPORT_SYMBOL(hevc_back_clock_init); - -int hevc_back_clock_set(int clk) -{ - pr_debug("%s-----%d\n", __func__, clk); - if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_set) - return p_vdec_hevc_back()->clock_set(clk); - else - return -1; -} -EXPORT_SYMBOL(hevc_back_clock_set); - -void hevc_back_clock_enable(void) -{ - hevc_back_clock_set(1); -} -EXPORT_SYMBOL(hevc_back_clock_enable); - -void hevc_back_clock_hi_enable(void) -{ - hevc_back_clock_set(2); -} -EXPORT_SYMBOL(hevc_back_clock_hi_enable); - -int hevc_clock_init(void) -{ - if (p_vdec_hevc() && p_vdec_hevc()->clock_init) - return p_vdec_hevc()->clock_init(); - else - return 0; -} -EXPORT_SYMBOL(hevc_clock_init); - -int hevc_clock_set(int clk) -{ - pr_debug("%s-----%d\n", __func__, clk); - if (p_vdec_hevc() && p_vdec_hevc()->clock_set) - return p_vdec_hevc()->clock_set(clk); - else - return -1; -} -EXPORT_SYMBOL(hevc_clock_set); - -void hevc_clock_enable(void) -{ - hevc_clock_set(1); -} -EXPORT_SYMBOL(hevc_clock_enable); - -void hevc_clock_hi_enable(void) -{ - hevc_clock_set(2); -} -EXPORT_SYMBOL(hevc_clock_hi_enable); - -void hevc_back_clock_on(void) -{ - IF_HAVE_RUN(p_vdec_hevc_back(), clock_on); -} -EXPORT_SYMBOL(hevc_back_clock_on); - -void hevc_back_clock_off(void) -{ - IF_HAVE_RUN(p_vdec_hevc_back(), clock_off); - clock_source_wxhxfps_saved[VDEC_HEVCB] = 0; -} -EXPORT_SYMBOL(hevc_back_clock_off); - -void hevc_clock_on(void) -{ - IF_HAVE_RUN(p_vdec_hevc(), clock_on); -} -EXPORT_SYMBOL(hevc_clock_on); - -void hevc_clock_off(void) -{ - IF_HAVE_RUN(p_vdec_hevc(), clock_off); - clock_source_wxhxfps_saved[VDEC_HEVC] = 0; -} -EXPORT_SYMBOL(hevc_clock_off); - -int vdec_source_get(enum vdec_type_e core) -{ - return clock_source_wxhxfps_saved[core]; -} -EXPORT_SYMBOL(vdec_source_get); - -int vdec_clk_get(enum vdec_type_e core) -{ - return get_current_vdec_chip()->clk_mgr[core]->clock_get(core); -} -EXPORT_SYMBOL(vdec_clk_get); - -int get_clk_with_source(int format, int w_x_h_fps) -{ - struct clk_set_setting *p_setting; - int i; - int clk = -2; - - p_setting = get_current_vdec_chip()->clk_setting_array; - if (!p_setting || format < 0 || format > VFORMAT_MAX) { - pr_info("error on get_clk_with_source ,%p,%d\n", - p_setting, format); - return -1; /*no setting found. */ - } - p_setting = &p_setting[format]; - for (i = 0; i < MAX_CLK_SET; i++) { - if (p_setting->set[i].wh_X_fps > w_x_h_fps) { - clk = p_setting->set[i].clk_Mhz; - break; - } - } - return clk; -} -EXPORT_SYMBOL(get_clk_with_source); - -int vdec_source_changed_for_clk_set(int format, int width, int height, int fps) -{ - int clk = get_clk_with_source(format, width * height * fps); - int ret_clk; - - if (clk < 0) { - pr_info("can't get valid clk for source ,%d,%d,%d\n", - width, height, fps); - if (format >= 1920 && width >= 1080 && fps >= 30) - clk = 2; /*default high clk */ - else - clk = 0; /*default clk. */ - } - if (width * height * fps == 0) - clk = 0; - /* - *clk == 0 - *is used for set default clk; - *if used supper clk. - *changed to default min clk. - */ - - if (format == VFORMAT_HEVC || format == VFORMAT_VP9 - || format == VFORMAT_AVS2) { - ret_clk = hevc_clock_set(clk); - clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - ret_clk = hevc_back_clock_set(clk); - clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps; - } - } else if (format == VFORMAT_H264_ENC || format == VFORMAT_JPEG_ENC) { - ret_clk = hcodec_clock_set(clk); - clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps; - } else if (format == VFORMAT_H264_4K2K && - get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_M8) { - ret_clk = vdec2_clock_set(clk); - clock_source_wxhxfps_saved[VDEC_2] = width * height * fps; - ret_clk = vdec_clock_set(clk); - clock_source_wxhxfps_saved[VDEC_1] = width * height * fps; - } else { - ret_clk = vdec_clock_set(clk); - clock_source_wxhxfps_saved[VDEC_1] = width * height * fps; - } - return ret_clk; -} -EXPORT_SYMBOL(vdec_source_changed_for_clk_set); - -static int register_vdec_clk_mgr_per_cpu(int cputype, - enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr) -{ - - struct chip_vdec_clk_s *mgr; - - if (cputype != get_cpu_major_id() || vdec_type >= VDEC_MAX) { - /* - *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n", - *vdec_type, cputype); - */ - return 0; /* ignore don't needed firmare. */ - } - mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL); - if (!mgr) - return -ENOMEM; - *mgr = *t_mgr; - /* - *pr_info("register vdec clk mgr for vdec[%d]\n", vdec_type); - */ - if (mgr->clock_init) { - if (mgr->clock_init()) { - kfree(mgr); - return -ENOMEM; - } - } - get_current_vdec_chip()->clk_mgr[vdec_type] = mgr; - return 0; -} - -int register_vdec_clk_mgr(int cputype[], enum vdec_type_e vdec_type, - struct chip_vdec_clk_s *t_mgr) -{ - int i = 0; - - while (cputype[i] > 0) { - register_vdec_clk_mgr_per_cpu(cputype[i], vdec_type, t_mgr); - i++; - } - return 0; -} -EXPORT_SYMBOL(register_vdec_clk_mgr); - -int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type) -{ - kfree(get_current_vdec_chip()->clk_mgr[vdec_type]); - - return 0; -} -EXPORT_SYMBOL(unregister_vdec_clk_mgr); - -static int register_vdec_clk_setting_per_cpu(int cputype, - struct clk_set_setting *setting, int size) -{ - - struct clk_set_setting *p_setting; - - if (cputype != get_cpu_major_id()) { - /* - *pr_info("ignore clk_set_setting for cpu=%d\n", - *cputype); - */ - return 0; /* ignore don't needed this setting . */ - } - p_setting = kmalloc(size, GFP_KERNEL); - if (!p_setting) - return -ENOMEM; - memcpy(p_setting, setting, size); - - pr_info("register clk_set_setting cpu[%d]\n", cputype); - - get_current_vdec_chip()->clk_setting_array = p_setting; - return 0; -} - -int register_vdec_clk_setting(int cputype[], - struct clk_set_setting *p_seting, int size) -{ - int i = 0; - - while (cputype[i] > 0) { - register_vdec_clk_setting_per_cpu(cputype[i], p_seting, size); - i++; - } - return 0; -} -EXPORT_SYMBOL(register_vdec_clk_setting); - -int unregister_vdec_clk_setting(void) -{ - kfree(get_current_vdec_chip()->clk_setting_array); - - return 0; -} -EXPORT_SYMBOL(unregister_vdec_clk_setting); - diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h deleted file mode 100644 index 9e6c02588b8b..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/clk/clk.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VDEC_CHIP_CLK_HEADER -#define VDEC_CHIP_CLK_HEADER -#include -#include -#include -#include "clk_priv.h" -#include - -#ifndef INCLUDE_FROM_ARCH_CLK_MGR -int vdec_clock_init(void); -int vdec_clock_set(int clk); -int vdec2_clock_set(int clk); - -int hcodec_clock_set(int clk); -int hevc_clock_init(void); -int hevc_clock_set(int clk); - -void vdec_clock_on(void); -void vdec_clock_off(void); -void vdec2_clock_on(void); - -void vdec2_clock_off(void); -void hcodec_clock_on(void); -void hcodec_clock_off(void); -void hevc_clock_on(void); -void hevc_clock_off(void); - -int hevc_back_clock_init(void); -void hevc_back_clock_on(void); -void hevc_back_clock_off(void); -int hevc_back_clock_set(int clk); -void hevc_back_clock_enable(void); -void hevc_back_clock_hi_enable(void); - -int vdec_source_get(enum vdec_type_e core); -int vdec_clk_get(enum vdec_type_e core); - -int vdec_source_changed_for_clk_set(int format, int width, int height, int fps); -int get_clk_with_source(int format, int w_x_h_fps); - -void vdec_clock_enable(void); -void vdec_clock_hi_enable(void); -void hcodec_clock_enable(void); -void hcodec_clock_hi_enable(void); -void hevc_clock_enable(void); -void hevc_clock_hi_enable(void); -void vdec2_clock_enable(void); -void vdec2_clock_hi_enable(void); -void set_clock_gate(struct gate_switch_node *nodes, int num); - -#endif -int register_vdec_clk_mgr(int cputype[], - enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr); - -int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type); - -int register_vdec_clk_setting(int cputype[], - struct clk_set_setting *p_seting, int size); - -int unregister_vdec_clk_setting(void); - -#ifdef INCLUDE_FROM_ARCH_CLK_MGR -static struct chip_vdec_clk_s vdec_clk_mgr __initdata = { - .clock_init = vdec_clock_init, - .clock_set = vdec_clock_set, - .clock_on = vdec_clock_on, - .clock_off = vdec_clock_off, - .clock_get = vdec_clock_get, -}; - -#ifdef VDEC_HAS_VDEC2 -static struct chip_vdec_clk_s vdec2_clk_mgr __initdata = { - .clock_set = vdec2_clock_set, - .clock_on = vdec2_clock_on, - .clock_off = vdec2_clock_off, - .clock_get = vdec_clock_get, -}; -#endif - -#ifdef VDEC_HAS_HEVC -static struct chip_vdec_clk_s vdec_hevc_clk_mgr __initdata = { - .clock_init = hevc_clock_init, - .clock_set = hevc_clock_set, - .clock_on = hevc_clock_on, - .clock_off = hevc_clock_off, - .clock_get = vdec_clock_get, -}; -static struct chip_vdec_clk_s vdec_hevc_back_clk_mgr __initdata = { - .clock_init = hevc_back_clock_init, - .clock_set = hevc_back_clock_set, - .clock_on = hevc_back_clock_on, - .clock_off = hevc_back_clock_off, - .clock_get = vdec_clock_get, -}; -#endif - -#ifdef VDEC_HAS_VDEC_HCODEC -static struct chip_vdec_clk_s vdec_hcodec_clk_mgr __initdata = { - .clock_set = hcodec_clock_set, - .clock_on = hcodec_clock_on, - .clock_off = hcodec_clock_off, - .clock_get = vdec_clock_get, -}; -#endif - -static int __init vdec_init_clk(void) -{ - int cpus[] = CLK_FOR_CPU; - - register_vdec_clk_mgr(cpus, VDEC_1, &vdec_clk_mgr); -#ifdef VDEC_HAS_VDEC2 - register_vdec_clk_mgr(cpus, VDEC_2, &vdec2_clk_mgr); -#endif -#ifdef VDEC_HAS_HEVC - register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr); - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) - register_vdec_clk_mgr(cpus, VDEC_HEVCB, &vdec_hevc_back_clk_mgr); -#endif -#ifdef VDEC_HAS_VDEC_HCODEC - register_vdec_clk_mgr(cpus, VDEC_HCODEC, &vdec_hcodec_clk_mgr); -#endif - -#ifdef VDEC_HAS_CLK_SETTINGS - register_vdec_clk_setting(cpus, - clks_for_formats, sizeof(clks_for_formats)); -#endif - return 0; -} - -static void __exit vdec_clk_exit(void) -{ - unregister_vdec_clk_mgr(VDEC_1); -#ifdef VDEC_HAS_VDEC2 - unregister_vdec_clk_mgr(VDEC_2); -#endif -#ifdef VDEC_HAS_HEVC - unregister_vdec_clk_mgr(VDEC_HEVC); -#endif -#ifdef VDEC_HAS_VDEC_HCODEC - unregister_vdec_clk_mgr(VDEC_HCODEC); -#endif -#ifdef VDEC_HAS_CLK_SETTINGS - unregister_vdec_clk_setting(); -#endif - pr_info("media clock exit.\n"); -} - -#define ARCH_VDEC_CLK_INIT()\ - module_init(vdec_init_clk) - -#define ARCH_VDEC_CLK_EXIT()\ - module_exit(vdec_clk_exit) - -#endif -#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h b/drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h deleted file mode 100644 index 60b7be09d6e9..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/clk/clk_priv.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef AMPORTS_CLK_PRIV_HEADER -#define AMPORTS_CLK_PRIV_HEADER - -struct clk_set { - u32 wh_X_fps; /* [x*y*fps */ - u32 clk_Mhz; /*min MHZ */ -}; -#define MAX_CLK_SET 6 -struct clk_set_setting { - struct clk_set set[MAX_CLK_SET]; -}; - -struct chip_vdec_clk_s { - int (*clock_get)(enum vdec_type_e core); - int (*clock_init)(void); - int (*clock_set)(int clk); - void (*clock_on)(void); - void (*clock_off)(void); - void (*clock_prepare_switch)(void); -}; -#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c b/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c deleted file mode 100644 index f045bd320889..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c +++ /dev/null @@ -1,1037 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/clk/clkgx.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../frame_provider/decoder/utils/vdec.h" -#include -#include "clk_priv.h" -#include - -#include -#include "../switch/amports_gate.h" -#include "../../chips/decoder_cpu_ver_info.h" - -#define MHz (1000000) -#define debug_print pr_info -#define TL1_HEVC_MAX_CLK (800) - -//#define NO_CLKTREE - -/* set gp0 648M vdec use gp0 clk*/ -#define VDEC1_648M() \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (0), 0, 16) - -#define HEVC_648M() \ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16) - -/*set gp0 1296M vdec use gp0 clk div2*/ -#define VDEC1_648M_DIV() \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (1), 0, 16) - -#define HEVC_648M_DIV() \ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16) - -#define VDEC1_WITH_GP_PLL() \ - ((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00) -#define HEVC_WITH_GP_PLL() \ - ((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000) - -#define VDEC1_CLOCK_ON() \ - do { if (is_meson_m8_cpu()) { \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ - WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ - } else { \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \ - WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ - } \ - } while (0) - -#define VDEC2_CLOCK_ON() do {\ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \ - WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\ - } while (0) - -#define HCODEC_CLOCK_ON() do {\ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \ - WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\ - } while (0) -#define HEVC_CLOCK_ON() do {\ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 15, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \ - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\ - } while (0) -#define VDEC1_SAFE_CLOCK() do {\ - WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \ - READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \ - WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\ - } while (0) - -#define VDEC1_CLOCK_OFF() \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 8, 1) -#define VDEC2_CLOCK_OFF() \ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1) -#define HCODEC_CLOCK_OFF() \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1) -#define HEVC_SAFE_CLOCK() do { \ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ - (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ - (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\ - WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 15, 1);\ - } while (0) - -#define HEVC_CLOCK_OFF() do {\ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1);\ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1);\ -}while(0) - -static int clock_real_clk[VDEC_MAX + 1]; - -static unsigned int set_frq_enable, vdec_frq, hevc_frq, hevcb_frq; - -#ifdef NO_CLKTREE -static struct gp_pll_user_handle_s *gp_pll_user_vdec, *gp_pll_user_hevc; -static bool is_gp0_div2 = true; - -static int gp_pll_user_cb_vdec(struct gp_pll_user_handle_s *user, - int event) -{ - debug_print("gp_pll_user_cb_vdec call\n"); - if (event == GP_PLL_USER_EVENT_GRANT) { - struct clk *clk = clk_get(NULL, "gp0_pll"); - if (!IS_ERR(clk)) { - if (is_gp0_div2) - clk_set_rate(clk, 1296000000UL); - else - clk_set_rate(clk, 648000000UL); - VDEC1_SAFE_CLOCK(); - VDEC1_CLOCK_OFF(); - if (is_gp0_div2) - VDEC1_648M_DIV(); - else - VDEC1_648M(); - - VDEC1_CLOCK_ON(); - debug_print("gp_pll_user_cb_vdec call set\n"); - } - } - return 0; -} - -static int gp_pll_user_cb_hevc(struct gp_pll_user_handle_s *user, - int event) -{ - debug_print("gp_pll_user_cb_hevc callback\n"); - if (event == GP_PLL_USER_EVENT_GRANT) { - struct clk *clk = clk_get(NULL, "gp0_pll"); - if (!IS_ERR(clk)) { - if (is_gp0_div2) - clk_set_rate(clk, 1296000000UL); - else - clk_set_rate(clk, 648000000UL); -// HEVC_SAFE_CLOCK(); - HEVC_CLOCK_OFF(); - if (is_gp0_div2) - HEVC_648M_DIV(); - else - HEVC_648M(); - HEVC_CLOCK_ON(); - debug_print("gp_pll_user_cb_hevc callback2\n"); - } - } - - return 0; -} - - -#endif - -struct clk_mux_s { - struct gate_switch_node *vdec_mux_node; - struct gate_switch_node *hcodec_mux_node; - struct gate_switch_node *hevc_mux_node; - struct gate_switch_node *hevc_back_mux_node; -}; - -struct clk_mux_s gclk; - -void vdec1_set_clk(int source, int div) -{ - pr_debug("vdec1_set_clk %d, %d\n", source, div); - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16); -} -EXPORT_SYMBOL(vdec1_set_clk); - -void hcodec_set_clk(int source, int div) -{ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, - (source << 9) | (div - 1), 16, 16); -} -EXPORT_SYMBOL(hcodec_set_clk); - -void vdec2_set_clk(int source, int div) -{ - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, - (source << 9) | (div - 1), 0, 16); -} -EXPORT_SYMBOL(vdec2_set_clk); - -//extern uint force_hevc_clock_cntl; -uint force_hevc_clock_cntl = 0; -void hevc_set_clk(int source, int div) -{ - if (force_hevc_clock_cntl) { - pr_info("%s, write force clock cntl %x\n", __func__, force_hevc_clock_cntl); - WRITE_HHI_REG(HHI_VDEC2_CLK_CNTL, force_hevc_clock_cntl); - } else { - pr_debug("hevc_set_clk %d, %d\n", source, div); - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, - (source << 9) | (div - 1), 16, 16); - WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (source << 9) | (div - 1), 0, 16); - } -} -EXPORT_SYMBOL(hevc_set_clk); - -void vdec_get_clk_source(int clk, int *source, int *div, int *rclk) -{ -#define source_div4 (0) -#define source_div3 (1) -#define source_div5 (2) -#define source_div7 (3) - if (clk > 500) { - *source = source_div3; - *div = 1; - *rclk = 667; - } else if (clk >= 500) { - *source = source_div4; - *div = 1; - *rclk = 500; - } else if (clk >= 400) { - *source = source_div5; - *div = 1; - *rclk = 400; - } else if (clk >= 333) { - *source = source_div3; - *div = 2; - *rclk = 333; - } else if (clk >= 200) { - *source = source_div5; - *div = 2; - *rclk = 200; - } else if (clk >= 166) { - *source = source_div4; - *div = 3; - *rclk = 166; - } else if (clk >= 133) { - *source = source_div5; - *div = 3; - *rclk = 133; - } else if (clk >= 100) { - *source = source_div5; - *div = 4; - *rclk = 100; - } else if (clk >= 50) { - *source = source_div5; - *div = 8; - *rclk = 50; - } else { - *source = source_div5; - *div = 20; - *rclk = 10; - } -} -EXPORT_SYMBOL(vdec_get_clk_source); - - -/* - *enum vformat_e { - * VFORMAT_MPEG12 = 0, - * VFORMAT_MPEG4, - * VFORMAT_H264, - * VFORMAT_MJPEG, - * VFORMAT_REAL, - * VFORMAT_JPEG, - * VFORMAT_VC1, - * VFORMAT_AVS, - * VFORMAT_YUV, - * VFORMAT_H264MVC, - * VFORMAT_H264_4K2K, - * VFORMAT_HEVC, - * VFORMAT_H264_ENC, - * VFORMAT_JPEG_ENC, - * VFORMAT_VP9, - * VFORMAT_MAX - *}; - *sample: - *{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333}, - * {4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},} - *mean: - *width * height * fps - *<720p30fps clk=100MHZ - *>=720p30fps & < 1080p30fps clk=166MHZ - *>=1080p 30fps & < 1080p60fps clk=333MHZ - */ -static struct clk_set_setting clks_for_formats[] = { - { /*[VFORMAT_MPEG12] */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, - {1920 * 1080 * 60, 333}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_MPEG4] */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, - {1920 * 1080 * 60, 333}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_H264] */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166}, - {1920 * 1080 * 30, 333}, - {1920 * 1080 * 60, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_MJPEG] */ - {{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200}, - {1920 * 1080 * 60, 333}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_REAL] */ - {{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500}, - {1920 * 1080 * 60, 500}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_JPEG] */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, - {1920 * 1080 * 60, 333}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_VC1] */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, - {1920 * 1080 * 60, 333}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_AVS] */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, - {1920 * 1080 * 60, 333}, - {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, - 600}, {INT_MAX, 600}, - } - }, - { /*[VFORMAT_YUV] */ - {{1280 * 720 * 30, 100}, {INT_MAX, 100}, - {0, 0}, {0, 0}, {0, 0}, {0, 0}, - } - }, - { /*VFORMAT_H264MVC */ - {{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333}, - {4096 * 2048 * 60, 600}, - {INT_MAX, 630}, {0, 0}, {0, 0}, - } - }, - { /*VFORMAT_H264_4K2K */ - {{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630}, - {INT_MAX, 630}, - {0, 0}, {0, 0}, {0, 0}, - } - }, - { /*VFORMAT_HEVC */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600}, - {4096 * 2048 * 25, 630}, - {4096 * 2048 * 30, 630}, {4096 * 2048 * 60, - 630}, {INT_MAX, 630}, - } - }, - { /*VFORMAT_H264_ENC */ - {{1280 * 720 * 30, 0}, {INT_MAX, 0}, - {0, 0}, {0, 0}, {0, 0}, {0, 0}, - } - }, - { /*VFORMAT_JPEG_ENC */ - {{1280 * 720 * 30, 0}, {INT_MAX, 0}, - {0, 0}, {0, 0}, {0, 0}, {0, 0}, - } - }, - { /*VFORMAT_VP9 */ - {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100}, - {1920 * 1080 * 60, 166}, - {4096 * 2048 * 30, 333}, {4096 * 2048 * 60, - 630}, {INT_MAX, 630}, - } - }, - {/*VFORMAT_AVS2*/ - {{1280*720*30, 100}, {1920*1080*30, 100}, - {1920*1080*60, 166}, {4096*2048*30, 333}, - {4096*2048*60, 630}, {INT_MAX, 630},} - }, - -}; - -void set_clock_gate(struct gate_switch_node *nodes, int num) -{ - struct gate_switch_node *node = NULL; - - do { - node = &nodes[num - 1]; - if (IS_ERR_OR_NULL(node)) - pr_info("get mux clk err.\n"); - - if (!strcmp(node->name, "clk_vdec_mux")) - gclk.vdec_mux_node = node; - else if (!strcmp(node->name, "clk_hcodec_mux")) - gclk.hcodec_mux_node = node; - else if (!strcmp(node->name, "clk_hevc_mux")) - gclk.hevc_mux_node = node; - else if (!strcmp(node->name, "clk_hevcb_mux")) - gclk.hevc_back_mux_node = node; - } while(--num); -} -EXPORT_SYMBOL(set_clock_gate); -#ifdef NO_CLKTREE -int vdec_set_clk(int dec, int source, int div) -{ - - if (dec == VDEC_1) - vdec1_set_clk(source, div); - else if (dec == VDEC_2) - vdec2_set_clk(source, div); - else if (dec == VDEC_HEVC) - hevc_set_clk(source, div); - else if (dec == VDEC_HCODEC) - hcodec_set_clk(source, div); - return 0; -} - -#else -static int vdec_set_clk(int dec, int rate) -{ - struct clk *clk = NULL; - - switch (dec) { - case VDEC_1: - clk = gclk.vdec_mux_node->clk; - WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); - break; - - case VDEC_HCODEC: - clk = gclk.hcodec_mux_node->clk; - WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); - break; - - case VDEC_2: - clk = gclk.vdec_mux_node->clk; - WRITE_VREG(DOS_GCLK_EN1, 0x3ff); - break; - - case VDEC_HEVC: - clk = gclk.hevc_mux_node->clk; - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); - break; - - case VDEC_HEVCB: - clk = gclk.hevc_back_mux_node->clk; - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); - break; - - case VDEC_MAX: - break; - - default: - pr_info("invaild vdec type.\n"); - } - - if (IS_ERR_OR_NULL(clk)) { - pr_info("the mux clk err.\n"); - return -1; - } - - clk_set_rate(clk, rate); - - return 0; -} - -static int vdec_clock_init(void) -{ - return 0; -} - -#endif -#ifdef NO_CLKTREE -static int vdec_clock_init(void) -{ - gp_pll_user_vdec = gp_pll_user_register("vdec", 0, - gp_pll_user_cb_vdec); - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) - is_gp0_div2 = false; - else - is_gp0_div2 = true; - - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) { - pr_info("used fix clk for vdec clk source!\n"); - //update_vdec_clk_config_settings(1); - } - return (gp_pll_user_vdec) ? 0 : -ENOMEM; -} - - - -static void update_clk_with_clk_configs( - int clk, int *source, int *div, int *rclk) -{ - unsigned int config = 0;//get_vdec_clk_config_settings(); - - if (!config) - return; - if (config >= 10) { - int wantclk; - wantclk = config; - vdec_get_clk_source(wantclk, source, div, rclk); - } - return; -} -#define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1) -#define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2) - -#define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1) -#define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2) - -static int vdec_clock_set(int clk) -{ - int use_gpll = 0; - int source, div, rclk; - int clk_seted = 0; - int gp_pll_wait = 0; - if (clk == 1) - clk = 200; - else if (clk == 2) { - if (clock_real_clk[VDEC_1] != 648) - clk = 500; - else - clk = 648; - } else if (clk == 0) { - /*used for release gp pull. - if used, release it. - if not used gp pll - do nothing. - */ - if (clock_real_clk[VDEC_1] == 667 || - (clock_real_clk[VDEC_1] == 648) || - clock_real_clk[VDEC_1] <= 0) - clk = 200; - else - clk = clock_real_clk[VDEC_1]; - } - vdec_get_clk_source(clk, &source, &div, &rclk); - update_clk_with_clk_configs(clk, &source, &div, &rclk); - - if (clock_real_clk[VDEC_1] == rclk) - return rclk; - if (NO_GP0_PLL) { - use_gpll = 0; - clk_seted = 0; - } else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) { - if (clock_real_clk[VDEC_1] == 648) - return 648; - use_gpll = 1; - gp_pll_request(gp_pll_user_vdec); - while (!VDEC1_WITH_GP_PLL() && gp_pll_wait++ < 1000000) - udelay(1); - if (VDEC1_WITH_GP_PLL()) { - clk_seted = 1; - rclk = 648; - } else { - use_gpll = 0; - rclk = 667; - /*gp_pull request failed,used default 500Mhz*/ - pr_info("get gp pll failed used fix pull\n"); - } - } - if (!clk_seted) {/*if 648 not set,*/ - VDEC1_SAFE_CLOCK(); - VDEC1_CLOCK_OFF(); - vdec_set_clk(VDEC_1, source, div); - VDEC1_CLOCK_ON(); - } - - if (!use_gpll) - gp_pll_release(gp_pll_user_vdec); - clock_real_clk[VDEC_1] = rclk; - debug_print("vdec_clock_set 2 to %d\n", rclk); - return rclk; -} -static int hevc_clock_init(void) -{ - gp_pll_user_hevc = gp_pll_user_register("hevc", 0, - gp_pll_user_cb_hevc); - - return (gp_pll_user_hevc) ? 0 : -ENOMEM; -} -static int hevc_back_clock_init(void) -{ - return 0; -} - -static int hevc_back_clock_set(int clk) -{ - return 0; -} - -static int hevc_clock_set(int clk) -{ - int use_gpll = 0; - int source, div, rclk; - int gp_pll_wait = 0; - int clk_seted = 0; - - debug_print("hevc_clock_set 1 to clk %d\n", clk); - if (clk == 1) - clk = 200; - else if (clk == 2) { - if (clock_real_clk[VDEC_HEVC] != 648) - clk = 500; - else - clk = 648; - } else if (clk == 0) { - /*used for release gp pull. - if used, release it. - if not used gp pll - do nothing. - */ - if ((clock_real_clk[VDEC_HEVC] == 667) || - (clock_real_clk[VDEC_HEVC] == 648) || - (clock_real_clk[VDEC_HEVC] <= 0)) - clk = 200; - else - clk = clock_real_clk[VDEC_HEVC]; - } - vdec_get_clk_source(clk, &source, &div, &rclk); - update_clk_with_clk_configs(clk, &source, &div, &rclk); - - if (rclk == clock_real_clk[VDEC_HEVC]) - return rclk;/*clk not changed,*/ - if (NO_GP0_PLL) { - use_gpll = 0; - clk_seted = 0; - } else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) { - if (clock_real_clk[VDEC_HEVC] == 648) - return 648; - use_gpll = 1; - gp_pll_request(gp_pll_user_hevc); - while (!HEVC_WITH_GP_PLL() && gp_pll_wait++ < 1000000) - udelay(1); - if (HEVC_WITH_GP_PLL()) { - clk_seted = 1; - rclk = 648; - } else { - rclk = 667; - /*gp_pull request failed,used default 500Mhz*/ - pr_info("get gp pll failed used fix pull\n"); - } - } - if (!clk_seted) {/*if 648 not set,*/ -// HEVC_SAFE_CLOCK(); - HEVC_CLOCK_OFF(); - vdec_set_clk(VDEC_HEVC, source, div); - HEVC_CLOCK_ON(); - } - if (!use_gpll) - gp_pll_release(gp_pll_user_hevc); - clock_real_clk[VDEC_HEVC] = rclk; - /*debug_print("hevc_clock_set 2 to rclk=%d, configs=%d\n", - rclk, - get_vdec_clk_config_settings());*/ //DEBUG_TMP - return rclk; -} - -static int hcodec_clock_set(int clk) -{ - int source, div, rclk; - HCODEC_CLOCK_OFF(); - vdec_get_clk_source(200, &source, &div, &rclk); - vdec_set_clk(VDEC_HCODEC, source, div); - HCODEC_CLOCK_ON(); - clock_real_clk[VDEC_HCODEC] = rclk; - return rclk; -} - - -#else -static int vdec_clock_set(int clk) -{ - if (clk == 1) - clk = 200; - else if (clk == 2) { - if (clock_real_clk[VDEC_1] != 648) - clk = 500; - else - clk = 648; - } else if (clk == 0) { - if (clock_real_clk[VDEC_1] == 667 || - (clock_real_clk[VDEC_1] == 648) || - clock_real_clk[VDEC_1] <= 0) - clk = 200; - else - clk = clock_real_clk[VDEC_1]; - } - - if ((clk > 500 && clk != 667)) { - if (clock_real_clk[VDEC_1] == 648) - return 648; - clk = 667; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1 && - get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1) - clk = 800; - - if (set_frq_enable && vdec_frq) { - pr_info("Set the vdec frq is %u MHz\n", vdec_frq); - clk = vdec_frq; - } - - vdec_set_clk(VDEC_1, clk * MHz); - - clock_real_clk[VDEC_1] = clk; - - pr_debug("vdec mux clock is %lu Hz\n", - clk_get_rate(gclk.vdec_mux_node->clk)); - - return clk; -} - -static int hevc_clock_init(void) -{ - return 0; -} - -static int hevc_back_clock_init(void) -{ - return 0; -} - -static int hevc_back_clock_set(int clk) -{ - if (clk == 1) - clk = 200; - else if (clk == 2) { - if (clock_real_clk[VDEC_HEVCB] != 648) - clk = 500; - else - clk = 648; - } else if (clk == 0) { - if (clock_real_clk[VDEC_HEVCB] == 667 || - (clock_real_clk[VDEC_HEVCB] == 648) || - clock_real_clk[VDEC_HEVCB] <= 0) - clk = 200; - else - clk = clock_real_clk[VDEC_HEVCB]; - } - - if ((clk > 500 && clk != 667)) { - if (clock_real_clk[VDEC_HEVCB] == 648) - return 648; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - clk = TL1_HEVC_MAX_CLK; - else - clk = 667; - } - - if (set_frq_enable && hevcb_frq) { - pr_info("Set the hevcb frq is %u MHz\n", hevcb_frq); - clk = hevcb_frq; - } - - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) { - if ((READ_EFUSE_REG(EFUSE_LIC1) >> 28 & 0x1) && clk > 333) { - pr_info("The hevcb clock limit to 333MHz.\n"); - clk = 333; - } - } - - vdec_set_clk(VDEC_HEVCB, clk * MHz); - - clock_real_clk[VDEC_HEVCB] = clk; - pr_debug("hevc back mux clock is %lu Hz\n", - clk_get_rate(gclk.hevc_back_mux_node->clk)); - - return clk; -} - -static int hevc_clock_set(int clk) -{ - if (clk == 1) - clk = 200; - else if (clk == 2) { - if (clock_real_clk[VDEC_HEVC] != 648) - clk = 500; - else - clk = 648; - } else if (clk == 0) { - if (clock_real_clk[VDEC_HEVC] == 667 || - (clock_real_clk[VDEC_HEVC] == 648) || - clock_real_clk[VDEC_HEVC] <= 0) - clk = 200; - else - clk = clock_real_clk[VDEC_HEVC]; - } - - if ((clk > 500 && clk != 667)) { - if (clock_real_clk[VDEC_HEVC] == 648) - return 648; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - clk = TL1_HEVC_MAX_CLK; - else - clk = 667; - } - - if (set_frq_enable && hevc_frq) { - pr_info("Set the hevc frq is %u MHz\n", hevc_frq); - clk = hevc_frq; - } - - vdec_set_clk(VDEC_HEVC, clk * MHz); - - clock_real_clk[VDEC_HEVC] = clk; - - pr_debug("hevc mux clock is %lu Hz\n", - clk_get_rate(gclk.hevc_mux_node->clk)); - - return clk; -} - -static int hcodec_clock_set(int clk) -{ - if (clk == 1) - clk = 200; - else if (clk == 2) { - if (clock_real_clk[VDEC_HCODEC] != 648) - clk = 500; - else - clk = 648; - } else if (clk == 0) { - if (clock_real_clk[VDEC_HCODEC] == 667 || - (clock_real_clk[VDEC_HCODEC] == 648) || - clock_real_clk[VDEC_HCODEC] <= 0) - clk = 200; - else - clk = clock_real_clk[VDEC_HCODEC]; - } - - if ((clk > 500 && clk != 667)) { - if (clock_real_clk[VDEC_HCODEC] == 648) - return 648; - clk = 667; - } - - vdec_set_clk(VDEC_HCODEC, clk * MHz); - - clock_real_clk[VDEC_HCODEC] = clk; - - pr_debug("hcodec mux clock is %lu Hz\n", - clk_get_rate(gclk.hcodec_mux_node->clk)); - - return clk; -} -#endif - -static void vdec_clock_on(void) -{ - mutex_lock(&gclk.vdec_mux_node->mutex); - if (!gclk.vdec_mux_node->ref_count) - clk_prepare_enable(gclk.vdec_mux_node->clk); - - gclk.vdec_mux_node->ref_count++; - mutex_unlock(&gclk.vdec_mux_node->mutex); - - pr_debug("the %-15s clock on, ref cnt: %d\n", - gclk.vdec_mux_node->name, - gclk.vdec_mux_node->ref_count); -} - -static void vdec_clock_off(void) -{ - mutex_lock(&gclk.vdec_mux_node->mutex); - gclk.vdec_mux_node->ref_count--; - if (!gclk.vdec_mux_node->ref_count) - clk_disable_unprepare(gclk.vdec_mux_node->clk); - - clock_real_clk[VDEC_1] = 0; - mutex_unlock(&gclk.vdec_mux_node->mutex); - - pr_debug("the %-15s clock off, ref cnt: %d\n", - gclk.vdec_mux_node->name, - gclk.vdec_mux_node->ref_count); -} - -static void hcodec_clock_on(void) -{ - mutex_lock(&gclk.hcodec_mux_node->mutex); - if (!gclk.hcodec_mux_node->ref_count) - clk_prepare_enable(gclk.hcodec_mux_node->clk); - - gclk.hcodec_mux_node->ref_count++; - mutex_unlock(&gclk.hcodec_mux_node->mutex); - - pr_debug("the %-15s clock on, ref cnt: %d\n", - gclk.hcodec_mux_node->name, - gclk.hcodec_mux_node->ref_count); -} - -static void hcodec_clock_off(void) -{ - mutex_lock(&gclk.hcodec_mux_node->mutex); - gclk.hcodec_mux_node->ref_count--; - if (!gclk.hcodec_mux_node->ref_count) - clk_disable_unprepare(gclk.hcodec_mux_node->clk); - - mutex_unlock(&gclk.hcodec_mux_node->mutex); - - pr_debug("the %-15s clock off, ref cnt: %d\n", - gclk.hcodec_mux_node->name, - gclk.hcodec_mux_node->ref_count); -} - -static void hevc_clock_on(void) -{ - mutex_lock(&gclk.hevc_mux_node->mutex); - if (!gclk.hevc_mux_node->ref_count) - clk_prepare_enable(gclk.hevc_mux_node->clk); - - gclk.hevc_mux_node->ref_count++; - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); - mutex_unlock(&gclk.hevc_mux_node->mutex); - - pr_debug("the %-15s clock on, ref cnt: %d\n", - gclk.hevc_mux_node->name, - gclk.hevc_mux_node->ref_count); -} - -static void hevc_clock_off(void) -{ - mutex_lock(&gclk.hevc_mux_node->mutex); - gclk.hevc_mux_node->ref_count--; - if (!gclk.hevc_mux_node->ref_count) - clk_disable_unprepare(gclk.hevc_mux_node->clk); - - clock_real_clk[VDEC_HEVC] = 0; - mutex_unlock(&gclk.hevc_mux_node->mutex); - - pr_debug("the %-15s clock off, ref cnt: %d\n", - gclk.hevc_mux_node->name, - gclk.hevc_mux_node->ref_count); -} - -static void hevc_back_clock_on(void) -{ - mutex_lock(&gclk.hevc_back_mux_node->mutex); - if (!gclk.hevc_back_mux_node->ref_count) - clk_prepare_enable(gclk.hevc_back_mux_node->clk); - - gclk.hevc_back_mux_node->ref_count++; - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); - mutex_unlock(&gclk.hevc_back_mux_node->mutex); - - pr_debug("the %-15s clock on, ref cnt: %d\n", - gclk.hevc_back_mux_node->name, - gclk.hevc_back_mux_node->ref_count); -} - -static void hevc_back_clock_off(void) -{ - mutex_lock(&gclk.hevc_back_mux_node->mutex); - gclk.hevc_back_mux_node->ref_count--; - if (!gclk.hevc_back_mux_node->ref_count) - clk_disable_unprepare(gclk.hevc_back_mux_node->clk); - - clock_real_clk[VDEC_HEVC] = 0; - mutex_unlock(&gclk.hevc_back_mux_node->mutex); - - pr_debug("the %-15s clock off, ref cnt: %d\n", - gclk.hevc_back_mux_node->name, - gclk.hevc_back_mux_node->ref_count); -} - -static int vdec_clock_get(enum vdec_type_e core) -{ - if (core >= VDEC_MAX) - return 0; - - return clock_real_clk[core]; -} - -#define INCLUDE_FROM_ARCH_CLK_MGR - -/*#define VDEC_HAS_VDEC2*/ -#define VDEC_HAS_HEVC -#define VDEC_HAS_VDEC_HCODEC -#define VDEC_HAS_CLK_SETTINGS -#define CLK_FOR_CPU {\ - AM_MESON_CPU_MAJOR_ID_GXBB,\ - AM_MESON_CPU_MAJOR_ID_GXTVBB,\ - AM_MESON_CPU_MAJOR_ID_GXL,\ - AM_MESON_CPU_MAJOR_ID_GXM,\ - AM_MESON_CPU_MAJOR_ID_TXL,\ - AM_MESON_CPU_MAJOR_ID_TXLX,\ - AM_MESON_CPU_MAJOR_ID_G12A,\ - AM_MESON_CPU_MAJOR_ID_G12B,\ - AM_MESON_CPU_MAJOR_ID_SM1,\ - AM_MESON_CPU_MAJOR_ID_TL1,\ - AM_MESON_CPU_MAJOR_ID_TM2,\ - 0} -#include "clk.h" - -module_param(set_frq_enable, uint, 0664); -MODULE_PARM_DESC(set_frq_enable, "\n set frequency enable\n"); - -module_param(vdec_frq, uint, 0664); -MODULE_PARM_DESC(vdec_frq, "\n set vdec frequency\n"); - -module_param(hevc_frq, uint, 0664); -MODULE_PARM_DESC(hevc_frq, "\n set hevc frequency\n"); - -module_param(hevcb_frq, uint, 0664); -MODULE_PARM_DESC(hevcb_frq, "\n set hevcb frequency\n"); - -ARCH_VDEC_CLK_INIT(); -ARCH_VDEC_CLK_EXIT(); - -MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c deleted file mode 100644 index beaea5388c05..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/switch/amports_gate.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include "amports_gate.h" -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../../../frame_provider/decoder/utils/vdec.h" -#include "../clk/clk.h" - - -#define DEBUG_REF 1 -#define GATE_RESET_OK - -#ifdef GATE_RESET_OK - -struct gate_switch_node gates[] = { - { - .name = "demux", - }, - { - .name = "parser_top", - }, - { - .name = "vdec", - }, - { - .name = "clk_81", - }, - { - .name = "clk_vdec_mux", - }, - { - .name = "clk_hcodec_mux", - }, - { - .name = "clk_hevc_mux", - }, - { - .name = "clk_hevcb_mux", - }, - { - .name = "ahbarb0", - }, - { - .name = "asyncfifo", - }, -}; - -/* - *mesonstream { - * compatible = "amlogic, codec, streambuf"; - * dev_name = "mesonstream"; - * status = "okay"; - * clocks = <&clkc CLKID_DOS_PARSER - * &clkc CLKID_DEMUX - * &clkc CLKID_DOS - * &clkc CLKID_VDEC_MUX - * &clkc CLKID_HCODEC_MUX - * &clkc CLKID_HEVCF_MUX - * &clkc CLKID_HEVC_MUX>; - * clock-names = "parser_top", - * "demux", - * "vdec", - * "clk_vdec_mux", - * "clk_hcodec_mux", - * "clk_hevc_mux", - * "clk_hevcb_mux"; - *}; - */ - -int amports_clock_gate_init(struct device *dev) -{ - int i; - - for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) { - gates[i].clk = devm_clk_get(dev, gates[i].name); - if (IS_ERR_OR_NULL(gates[i].clk)) { - gates[i].clk = NULL; - pr_info("get gate %s control failed %p\n", - gates[i].name, - gates[i].clk); - } else { - pr_info("get gate %s control ok %p\n", - gates[i].name, - gates[i].clk); - } - gates[i].ref_count = 0; - mutex_init(&gates[i].mutex); - } - - set_clock_gate(gates, ARRAY_SIZE(gates)); - - return 0; -} -EXPORT_SYMBOL(amports_clock_gate_init); - -static int amports_gate_clk(struct gate_switch_node *gate_node, int enable) -{ - mutex_lock(&gate_node->mutex); - if (enable) { - if (gate_node->ref_count == 0) - clk_prepare_enable(gate_node->clk); - - gate_node->ref_count++; - - if (DEBUG_REF) - pr_debug("the %-15s clock on, ref cnt: %d\n", - gate_node->name, gate_node->ref_count); - } else { - gate_node->ref_count--; - if (gate_node->ref_count == 0) - clk_disable_unprepare(gate_node->clk); - - if (DEBUG_REF) - pr_debug("the %-15s clock off, ref cnt: %d\n", - gate_node->name, gate_node->ref_count); - } - mutex_unlock(&gate_node->mutex); - - return 0; -} - -int amports_switch_gate(const char *name, int enable) -{ - int i; - - for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) { - if (!strcmp(name, gates[i].name)) { - - /*pr_info("openclose:%d gate %s control\n", enable, - * gates[i].name); - */ - - if (gates[i].clk) - amports_gate_clk(&gates[i], enable); - } - } - return 0; -} -EXPORT_SYMBOL(amports_switch_gate); - -#else -/* - *can used for debug. - *on chip bringup. - */ -int amports_clock_gate_init(struct device *dev) -{ - static int gate_inited; - - if (gate_inited) - return 0; -/* - *#define HHI_GCLK_MPEG0 0x1050 - *#define HHI_GCLK_MPEG1 0x1051 - *#define HHI_GCLK_MPEG2 0x1052 - *#define HHI_GCLK_OTHER 0x1054 - *#define HHI_GCLK_AO 0x1055 - */ - WRITE_HHI_REG_BITS(HHI_GCLK_MPEG0, 1, 1, 1);/*dos*/ - WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 25, 1);/*U_parser_top()*/ - WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 0xff, 6, 8);/*aiu()*/ - WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 4, 1);/*demux()*/ - WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 2, 1);/*audio in()*/ - WRITE_HHI_REG_BITS(HHI_GCLK_MPEG2, 1, 25, 1);/*VPU Interrupt*/ - gate_inited++; - - - - return 0; -} -EXPORT_SYMBOL(amports_clock_gate_init); - - -int amports_switch_gate(const char *name, int enable) -{ - return 0; -} -EXPORT_SYMBOL(amports_switch_gate); - -#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h deleted file mode 100644 index 58abc9274d9d..000000000000 --- a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * drivers/amlogic/media/common/arch/switch/amports_gate.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef AMPORT_GATE_H -#define AMPORT_GATE_H -#include - -struct gate_switch_node { - struct clk *clk; - const char *name; - struct mutex mutex; - int ref_count; -}; - -extern int amports_clock_gate_init(struct device *dev); -extern int amports_switch_gate(const char *name, int enable); - -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/Makefile b/drivers/amlogic/media_modules/frame_provider/Makefile deleted file mode 100644 index 371e088259c5..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += decoder/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/Makefile deleted file mode 100644 index 12121b43f36d..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -obj-y += utils/ -obj-y += mpeg12/ -obj-y += mpeg4/ -obj-y += vc1/ -obj-y += h264/ -obj-y += h264_multi/ -obj-y += h265/ -obj-y += vp9/ -obj-y += mjpeg/ -obj-y += real/ -obj-y += avs/ -obj-y += avs2/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile deleted file mode 100644 index 1d56236f9ef2..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS) += amvdec_avs.o -amvdec_avs-objs += avs.o avsp_trans.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c deleted file mode 100644 index ae50ec2989f8..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c +++ /dev/null @@ -1,1944 +0,0 @@ -/* - * drivers/amlogic/amports/vavs.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/parser/streambuf_reg.h" -#include "../utils/amvdec.h" -#include -#include "../../../stream_input/amports/amports_priv.h" -#include -#include -#include -#include "avs.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include "../utils/firmware.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" -#include - - -#include - -#define DRIVER_NAME "amvdec_avs" -#define MODULE_NAME "amvdec_avs" - - -#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -#endif - -#define USE_AVS_SEQ_INFO -#define HANDLE_AVS_IRQ -#define DEBUG_PTS - -#define I_PICTURE 0 -#define P_PICTURE 1 -#define B_PICTURE 2 - -/* #define ORI_BUFFER_START_ADDR 0x81000000 */ -#define ORI_BUFFER_START_ADDR 0x80000000 - -#define INTERLACE_FLAG 0x80 -#define TOP_FIELD_FIRST_FLAG 0x40 - -/* protocol registers */ -#define AVS_PIC_RATIO AV_SCRATCH_0 -#define AVS_PIC_WIDTH AV_SCRATCH_1 -#define AVS_PIC_HEIGHT AV_SCRATCH_2 -#define AVS_FRAME_RATE AV_SCRATCH_3 - -#define AVS_ERROR_COUNT AV_SCRATCH_6 -#define AVS_SOS_COUNT AV_SCRATCH_7 -#define AVS_BUFFERIN AV_SCRATCH_8 -#define AVS_BUFFEROUT AV_SCRATCH_9 -#define AVS_REPEAT_COUNT AV_SCRATCH_A -#define AVS_TIME_STAMP AV_SCRATCH_B -#define AVS_OFFSET_REG AV_SCRATCH_C -#define MEM_OFFSET_REG AV_SCRATCH_F -#define AVS_ERROR_RECOVERY_MODE AV_SCRATCH_G - -#define VF_POOL_SIZE 32 -#define PUT_INTERVAL (HZ/100) - -#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ -#define INT_AMVENCODER INT_DOS_MAILBOX_1 -#else -/* #define AMVENC_DEV_VERSION "AML-MT" */ -#define INT_AMVENCODER INT_MAILBOX_1A -#endif - - -#define DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE 0x0001 -static u32 dec_control = DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE; - - -#define VPP_VD1_POSTBLEND (1 << 10) - -static int debug_flag; - -/******************************** -firmware_sel - 0: use avsp_trans long cabac ucode; - 1: not use avsp_trans long cabac ucode -********************************/ -static int firmware_sel; -static int disable_longcabac_trans = 1; - -static int support_user_data = 1; - -int avs_get_debug_flag(void) -{ - return debug_flag; -} - -static struct vframe_s *vavs_vf_peek(void *); -static struct vframe_s *vavs_vf_get(void *); -static void vavs_vf_put(struct vframe_s *, void *); -static int vavs_vf_states(struct vframe_states *states, void *); - -static const char vavs_dec_id[] = "vavs-dev"; - -#define PROVIDER_NAME "decoder.avs" -static DEFINE_SPINLOCK(lock); -static DEFINE_MUTEX(vavs_mutex); - -static const struct vframe_operations_s vavs_vf_provider = { - .peek = vavs_vf_peek, - .get = vavs_vf_get, - .put = vavs_vf_put, - .vf_states = vavs_vf_states, -}; -static void *mm_blk_handle; -static struct vframe_provider_s vavs_vf_prov; - -#define VF_BUF_NUM_MAX 16 -#define WORKSPACE_SIZE (4 * SZ_1M) - -#ifdef AVSP_LONG_CABAC -#define MAX_BMMU_BUFFER_NUM (VF_BUF_NUM_MAX + 2) -#define WORKSPACE_SIZE_A (MAX_CODED_FRAME_SIZE + LOCAL_HEAP_SIZE) -#else -#define MAX_BMMU_BUFFER_NUM (VF_BUF_NUM_MAX + 1) -#endif - -#define RV_AI_BUFF_START_ADDR 0x01a00000 -#define LONG_CABAC_RV_AI_BUFF_START_ADDR 0x00000000 - -static u32 vf_buf_num = 4; -static u32 vf_buf_num_used; -static u32 canvas_base = 128; -#ifdef NV21 - int canvas_num = 2; /*NV21*/ -#else - int canvas_num = 3; -#endif - - -static struct vframe_s vfpool[VF_POOL_SIZE]; -/*static struct vframe_s vfpool2[VF_POOL_SIZE];*/ -static struct vframe_s *cur_vfpool; -static unsigned char recover_flag; -static s32 vfbuf_use[VF_BUF_NUM_MAX]; -static u32 saved_resolution; -static u32 frame_width, frame_height, frame_dur, frame_prog; -static struct timer_list recycle_timer; -static u32 stat; -static u32 buf_size = 32 * 1024 * 1024; -static u32 buf_offset; -static u32 avi_flag; -static u32 vavs_ratio; -static u32 pic_type; -static u32 pts_by_offset = 1; -static u32 total_frame; -static u32 next_pts; -static unsigned char throw_pb_flag; -#ifdef DEBUG_PTS -static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; -#endif - -static u32 radr, rval; -static struct dec_sysinfo vavs_amstream_dec_info; -static struct vdec_info *gvs; -static u32 fr_hint_status; -static struct work_struct notify_work; -static struct work_struct set_clk_work; -static bool is_reset; - -static struct vdec_s *vdec; - -#ifdef AVSP_LONG_CABAC -static struct work_struct long_cabac_wd_work; -void *es_write_addr_virt; -dma_addr_t es_write_addr_phy; - -void *bitstream_read_tmp; -dma_addr_t bitstream_read_tmp_phy; -void *avsp_heap_adr; -static uint long_cabac_busy; -#endif - - -static void *user_data_buffer; -static dma_addr_t user_data_buffer_phys; - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static inline u32 index2canvas(u32 index) -{ - const u32 canvas_tab[VF_BUF_NUM_MAX] = { - 0x010100, 0x030302, 0x050504, 0x070706, - 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e, - 0x111110, 0x131312, 0x151514, 0x171716, - 0x191918, 0x1b1b1a, 0x1d1d1c, 0x1f1f1e, - }; - const u32 canvas_tab_3[4] = { - 0x010100, 0x040403, 0x070706, 0x0a0a09 - }; - - if (canvas_num == 2) - return canvas_tab[index] + (canvas_base << 16) - + (canvas_base << 8) + canvas_base; - - return canvas_tab_3[index] + (canvas_base << 16) - + (canvas_base << 8) + canvas_base; -} - -static const u32 frame_rate_tab[16] = { - 96000 / 30, /* forbidden */ - 96000000 / 23976, /* 24000/1001 (23.967) */ - 96000 / 24, - 96000 / 25, - 9600000 / 2997, /* 30000/1001 (29.97) */ - 96000 / 30, - 96000 / 50, - 9600000 / 5994, /* 60000/1001 (59.94) */ - 96000 / 60, - /* > 8 reserved, use 24 */ - 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, - 96000 / 24, 96000 / 24, 96000 / 24 -}; - -static void set_frame_info(struct vframe_s *vf, unsigned int *duration) -{ - int ar = 0; - - unsigned int pixel_ratio = READ_VREG(AVS_PIC_RATIO); -#ifndef USE_AVS_SEQ_INFO - if (vavs_amstream_dec_info.width > 0 - && vavs_amstream_dec_info.height > 0) { - vf->width = vavs_amstream_dec_info.width; - vf->height = vavs_amstream_dec_info.height; - } else -#endif - { - vf->width = READ_VREG(AVS_PIC_WIDTH); - vf->height = READ_VREG(AVS_PIC_HEIGHT); - frame_width = vf->width; - frame_height = vf->height; - /* pr_info("%s: (%d,%d)\n", __func__,vf->width, vf->height);*/ - } - -#ifndef USE_AVS_SEQ_INFO - if (vavs_amstream_dec_info.rate > 0) - *duration = vavs_amstream_dec_info.rate; - else -#endif - { - *duration = frame_rate_tab[READ_VREG(AVS_FRAME_RATE) & 0xf]; - /* pr_info("%s: duration = %d\n", __func__, *duration); */ - frame_dur = *duration; - schedule_work(¬ify_work); - } - - if (vavs_ratio == 0) { - /* always stretch to 16:9 */ - vf->ratio_control |= (0x90 << - DISP_RATIO_ASPECT_RATIO_BIT); - } else { - switch (pixel_ratio) { - case 1: - ar = (vf->height * vavs_ratio) / vf->width; - break; - case 2: - ar = (vf->height * 3 * vavs_ratio) / (vf->width * 4); - break; - case 3: - ar = (vf->height * 9 * vavs_ratio) / (vf->width * 16); - break; - case 4: - ar = (vf->height * 100 * vavs_ratio) / (vf->width * - 221); - break; - default: - ar = (vf->height * vavs_ratio) / vf->width; - break; - } - } - - ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); - - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - /*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO; */ - - vf->flag = 0; -} - - -static struct work_struct userdata_push_work; -/* -#define DUMP_LAST_REPORTED_USER_DATA -*/ -static void userdata_push_do_work(struct work_struct *work) -{ - unsigned int user_data_flags; - unsigned int user_data_wp; - unsigned int user_data_length; - struct userdata_poc_info_t user_data_poc; -#ifdef DUMP_LAST_REPORTED_USER_DATA - int user_data_len; - int wp_start; - unsigned char *pdata; - int nLeft; -#endif - - user_data_flags = READ_VREG(AV_SCRATCH_N); - user_data_wp = (user_data_flags >> 16) & 0xffff; - user_data_length = user_data_flags & 0x7fff; - -#ifdef DUMP_LAST_REPORTED_USER_DATA - dma_sync_single_for_cpu(amports_get_dma_device(), - user_data_buffer_phys, USER_DATA_SIZE, - DMA_FROM_DEVICE); - - if (user_data_length & 0x07) - user_data_len = (user_data_length + 8) & 0xFFFFFFF8; - else - user_data_len = user_data_length; - - if (user_data_wp >= user_data_len) { - wp_start = user_data_wp - user_data_len; - - pdata = (unsigned char *)user_data_buffer; - pdata += wp_start; - nLeft = user_data_len; - while (nLeft >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } - } else { - wp_start = user_data_wp + - USER_DATA_SIZE - user_data_len; - - pdata = (unsigned char *)user_data_buffer; - pdata += wp_start; - nLeft = USER_DATA_SIZE - wp_start; - - while (nLeft >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } - - pdata = (unsigned char *)user_data_buffer; - nLeft = user_data_wp; - while (nLeft >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } - } -#endif - -/* - pr_info("pocinfo 0x%x, poc %d, wp 0x%x, len %d\n", - READ_VREG(AV_SCRATCH_L), READ_VREG(AV_SCRATCH_M), - user_data_wp, user_data_length); -*/ - user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L); - user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M); - - WRITE_VREG(AV_SCRATCH_N, 0); -/* - wakeup_userdata_poll(user_data_poc, user_data_wp, - (unsigned long)user_data_buffer, - USER_DATA_SIZE, user_data_length); -*/ -} - -static void UserDataHandler(void) -{ - unsigned int user_data_flags; - - user_data_flags = READ_VREG(AV_SCRATCH_N); - if (user_data_flags & (1 << 15)) { /* data ready */ - schedule_work(&userdata_push_work); - } -} - - -#ifdef HANDLE_AVS_IRQ -static irqreturn_t vavs_isr(int irq, void *dev_id) -#else -static void vavs_isr(void) -#endif -{ - u32 reg; - struct vframe_s *vf; - u32 dur; - u32 repeat_count; - u32 picture_type; - u32 buffer_index; - u32 frame_size; - bool force_interlaced_frame = false; - unsigned int pts, pts_valid = 0, offset = 0; - u64 pts_us64; - if (debug_flag & AVS_DEBUG_UCODE) { - if (READ_VREG(AV_SCRATCH_E) != 0) { - pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_E), - READ_VREG(AV_SCRATCH_D)); - WRITE_VREG(AV_SCRATCH_E, 0); - } - } -#ifdef AVSP_LONG_CABAC - if (firmware_sel == 0 && READ_VREG(LONG_CABAC_REQ)) { -#ifdef PERFORMANCE_DEBUG - pr_info("%s:schedule long_cabac_wd_work\r\n", __func__); -#endif - pr_info("schedule long_cabac_wd_work and requested from %d\n", - (READ_VREG(LONG_CABAC_REQ) >> 8)&0xFF); - schedule_work(&long_cabac_wd_work); - } -#endif - - - UserDataHandler(); - - reg = READ_VREG(AVS_BUFFEROUT); - - if (reg) { - if (debug_flag & AVS_DEBUG_PRINT) - pr_info("AVS_BUFFEROUT=%x\n", reg); - if (pts_by_offset) { - offset = READ_VREG(AVS_OFFSET_REG); - if (debug_flag & AVS_DEBUG_PRINT) - pr_info("AVS OFFSET=%x\n", offset); - if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, &pts, - &frame_size, - 0, &pts_us64) == 0) { - pts_valid = 1; -#ifdef DEBUG_PTS - pts_hit++; -#endif - } else { -#ifdef DEBUG_PTS - pts_missed++; -#endif - } - } - - repeat_count = READ_VREG(AVS_REPEAT_COUNT); - if (firmware_sel == 0) - buffer_index = - ((reg & 0x7) + - (((reg >> 8) & 0x3) << 3) - 1) & 0x1f; - else - buffer_index = - ((reg & 0x7) - 1) & 3; - - picture_type = (reg >> 3) & 7; -#ifdef DEBUG_PTS - if (picture_type == I_PICTURE) { - /* pr_info("I offset 0x%x, pts_valid %d\n", - * offset, pts_valid); - */ - if (!pts_valid) - pts_i_missed++; - else - pts_i_hit++; - } -#endif - - if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE) - && frame_width == 1920 && frame_height == 1080) { - force_interlaced_frame = true; - } - - if (throw_pb_flag && picture_type != I_PICTURE) { - - if (debug_flag & AVS_DEBUG_PRINT) { - pr_info("picture type %d throwed\n", - picture_type); - } - WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index)); - } else if (reg & INTERLACE_FLAG || force_interlaced_frame) { /* interlace */ - throw_pb_flag = 0; - - if (debug_flag & AVS_DEBUG_PRINT) { - pr_info("interlace, picture type %d\n", - picture_type); - } - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - set_frame_info(vf, &dur); - vf->bufWidth = 1920; - pic_type = 2; - if ((picture_type == I_PICTURE) && pts_valid) { - vf->pts = pts; - if ((repeat_count > 1) && avi_flag) { - /* next_pts = pts + - * (vavs_amstream_dec_info.rate * - * repeat_count >> 1)*15/16; - */ - next_pts = - pts + - (dur * repeat_count >> 1) * - 15 / 16; - } else - next_pts = 0; - } else { - vf->pts = next_pts; - if ((repeat_count > 1) && avi_flag) { - /* vf->duration = - * vavs_amstream_dec_info.rate * - * repeat_count >> 1; - */ - vf->duration = dur * repeat_count >> 1; - if (next_pts != 0) { - next_pts += - ((vf->duration) - - ((vf->duration) >> 4)); - } - } else { - /* vf->duration = - * vavs_amstream_dec_info.rate >> 1; - */ - vf->duration = dur >> 1; - next_pts = 0; - } - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->duration_pulldown = 0; - if (force_interlaced_frame) { - vf->type = VIDTYPE_INTERLACE_TOP; - }else{ - vf->type = - (reg & TOP_FIELD_FIRST_FLAG) - ? VIDTYPE_INTERLACE_TOP - : VIDTYPE_INTERLACE_BOTTOM; - } -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->type_original = vf->type; - - if (debug_flag & AVS_DEBUG_PRINT) { - pr_info("buffer_index %d, canvas addr %x\n", - buffer_index, vf->canvas0Addr); - } - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - decoder_do_frame_check(NULL, vf); - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - set_frame_info(vf, &dur); - vf->bufWidth = 1920; - if (force_interlaced_frame) - vf->pts = 0; - else - vf->pts = next_pts; - - if ((repeat_count > 1) && avi_flag) { - /* vf->duration = vavs_amstream_dec_info.rate * - * repeat_count >> 1; - */ - vf->duration = dur * repeat_count >> 1; - if (next_pts != 0) { - next_pts += - ((vf->duration) - - ((vf->duration) >> 4)); - } - } else { - /* vf->duration = vavs_amstream_dec_info.rate - * >> 1; - */ - vf->duration = dur >> 1; - next_pts = 0; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->duration_pulldown = 0; - if (force_interlaced_frame) { - vf->type = VIDTYPE_INTERLACE_BOTTOM; - } else { - vf->type = - (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP; - } -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->type_original = vf->type; - vf->pts_us64 = 0; - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - total_frame++; - } else { /* progressive */ - throw_pb_flag = 0; - - if (debug_flag & AVS_DEBUG_PRINT) { - pr_info("progressive picture type %d\n", - picture_type); - } - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - set_frame_info(vf, &dur); - vf->bufWidth = 1920; - pic_type = 1; - - if ((picture_type == I_PICTURE) && pts_valid) { - vf->pts = pts; - if ((repeat_count > 1) && avi_flag) { - /* next_pts = pts + - * (vavs_amstream_dec_info.rate * - * repeat_count)*15/16; - */ - next_pts = - pts + - (dur * repeat_count) * 15 / 16; - } else - next_pts = 0; - } else { - vf->pts = next_pts; - if ((repeat_count > 1) && avi_flag) { - /* vf->duration = - * vavs_amstream_dec_info.rate * - * repeat_count; - */ - vf->duration = dur * repeat_count; - if (next_pts != 0) { - next_pts += - ((vf->duration) - - ((vf->duration) >> 4)); - } - } else { - /* vf->duration = - * vavs_amstream_dec_info.rate; - */ - vf->duration = dur; - next_pts = 0; - } - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->duration_pulldown = 0; - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->type_original = vf->type; - - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - if (debug_flag & AVS_DEBUG_PRINT) { - pr_info("buffer_index %d, canvas addr %x\n", - buffer_index, vf->canvas0Addr); - } - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - decoder_do_frame_check(NULL, vf); - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - total_frame++; - } - - /*count info*/ - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, 0, offset); - - /* pr_info("PicType = %d, PTS = 0x%x\n", - * picture_type, vf->pts); - */ - WRITE_VREG(AVS_BUFFEROUT, 0); - } - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - -#ifdef HANDLE_AVS_IRQ - return IRQ_HANDLED; -#else - return; -#endif -} -/* - *static int run_flag = 1; - *static int step_flag; - */ -static int error_recovery_mode; /*0: blocky 1: mosaic*/ -/* - *static uint error_watchdog_threshold=10; - *static uint error_watchdog_count; - *static uint error_watchdog_buf_threshold = 0x4000000; - */ - -static struct vframe_s *vavs_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (recover_flag) - return NULL; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; - -} - -static struct vframe_s *vavs_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (recover_flag) - return NULL; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; - -} - -static void vavs_vf_put(struct vframe_s *vf, void *op_arg) -{ - int i; - - if (recover_flag) - return; - - for (i = 0; i < VF_POOL_SIZE; i++) { - if (vf == &cur_vfpool[i]) - break; - } - if (i < VF_POOL_SIZE) - kfifo_put(&recycle_q, (const struct vframe_s *)vf); - -} - -int vavs_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (frame_dur != 0) - vstatus->frame_rate = 96000 / frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(AV_SCRATCH_C); - vstatus->status = stat; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -int vavs_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -static int vavs_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} -/****************************************/ -static int vavs_canvas_init(void) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 decbuf_size, decbuf_y_size, decbuf_uv_size; - unsigned long buf_start; - int need_alloc_buf_num; - u32 endian; - - vf_buf_num_used = vf_buf_num; - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - /* HD & SD */ - canvas_width = 1920; - canvas_height = 1088; - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - -#ifdef AVSP_LONG_CABAC - need_alloc_buf_num = vf_buf_num_used + 2; -#else - need_alloc_buf_num = vf_buf_num_used + 1; -#endif - for (i = 0; i < need_alloc_buf_num; i++) { - - if (i == (need_alloc_buf_num - 1)) - decbuf_size = WORKSPACE_SIZE; -#ifdef AVSP_LONG_CABAC - else if (i == (need_alloc_buf_num - 2)) - decbuf_size = WORKSPACE_SIZE_A; -#endif - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; - if (i == (need_alloc_buf_num - 1)) { - if (firmware_sel == 1) - buf_offset = buf_start - - RV_AI_BUFF_START_ADDR; - else - buf_offset = buf_start - - LONG_CABAC_RV_AI_BUFF_START_ADDR; - continue; - } -#ifdef AVSP_LONG_CABAC - else if (i == (need_alloc_buf_num - 2)) { - avsp_heap_adr = codec_mm_phys_to_virt(buf_start); - continue; - } -#endif - if (vdec->canvas_mode == CANVAS_BLKMODE_LINEAR) - endian = 7; - else - endian = 0; -#ifdef NV21 - canvas_config_ex(canvas_base + canvas_num * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, - vdec->canvas_mode, endian); - canvas_config_ex(canvas_base + canvas_num * i + 1, - buf_start + - decbuf_y_size, canvas_width, - canvas_height / 2, - CANVAS_ADDR_NOWRAP, - vdec->canvas_mode, endian); -#else - canvas_config_ex(canvas_num * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, - vdec->canvas_mode, endian); - canvas_config_ex(canvas_num * i + 1, - buf_start + - decbuf_y_size, canvas_width / 2, - canvas_height / 2, - CANVAS_ADDR_NOWRAP, - vdec->canvas_mode, endian); - canvas_config_ex(canvas_num * i + 2, - buf_start + - decbuf_y_size + decbuf_uv_size, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - vdec->canvas_mode, endian); -#endif - if (debug_flag & AVS_DEBUG_PRINT) { - pr_info("canvas config %d, addr %p\n", i, - (void *)buf_start); - } - - } - return 0; -} - -void vavs_recover(void) -{ - vavs_canvas_init(); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); - - if (firmware_sel == 1) { - WRITE_VREG(POWER_CTL_VLD, 0x10); - WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, - MEM_FIFO_CNT_BIT, 2); - WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, - MEM_LEVEL_CNT_BIT, 6); - } - - - if (firmware_sel == 0) { - /* fixed canvas index */ - WRITE_VREG(AV_SCRATCH_0, canvas_base); - WRITE_VREG(AV_SCRATCH_1, vf_buf_num_used); - } else { - int ii; - - for (ii = 0; ii < 4; ii++) { - WRITE_VREG(AV_SCRATCH_0 + ii, - (canvas_base + canvas_num * ii) | - ((canvas_base + canvas_num * ii + 1) - << 8) | - ((canvas_base + canvas_num * ii + 1) - << 16) - ); - } - } - - /* notify ucode the buffer offset */ - WRITE_VREG(AV_SCRATCH_F, buf_offset); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - WRITE_VREG(AVS_SOS_COUNT, 0); - WRITE_VREG(AVS_BUFFERIN, 0); - WRITE_VREG(AVS_BUFFEROUT, 0); - if (error_recovery_mode) - WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); - else - WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); -#if 1 /* def DEBUG_UCODE */ - WRITE_VREG(AV_SCRATCH_D, 0); -#endif - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - -#ifdef PIC_DC_NEED_CLEAR - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); -#endif - -#ifdef AVSP_LONG_CABAC - if (firmware_sel == 0) { - WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy); - WRITE_VREG(LONG_CABAC_REQ, 0); - WRITE_VREG(LONG_CABAC_PIC_SIZE, 0); - WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); - } -#endif - WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset)); - pr_info("support_user_data = %d\n", support_user_data); - if (support_user_data) - WRITE_VREG(AV_SCRATCH_M, 1); - else - WRITE_VREG(AV_SCRATCH_M, 0); - - WRITE_VREG(AV_SCRATCH_5, 0); - -} - -static int vavs_prot_init(void) -{ - int r; -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); - -#else - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - READ_RESET_REG(RESET0_REGISTER); - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - - WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); -#endif - - /***************** reset vld **********************************/ - WRITE_VREG(POWER_CTL_VLD, 0x10); - WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2); - WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, MEM_LEVEL_CNT_BIT, 6); - /*************************************************************/ - - r = vavs_canvas_init(); -#ifdef NV21 - if (firmware_sel == 0) { - /* fixed canvas index */ - WRITE_VREG(AV_SCRATCH_0, canvas_base); - WRITE_VREG(AV_SCRATCH_1, vf_buf_num_used); - } else { - int ii; - - for (ii = 0; ii < 4; ii++) { - WRITE_VREG(AV_SCRATCH_0 + ii, - (canvas_base + canvas_num * ii) | - ((canvas_base + canvas_num * ii + 1) - << 8) | - ((canvas_base + canvas_num * ii + 1) - << 16) - ); - } - /* - *WRITE_VREG(AV_SCRATCH_0, 0x010100); - *WRITE_VREG(AV_SCRATCH_1, 0x040403); - *WRITE_VREG(AV_SCRATCH_2, 0x070706); - *WRITE_VREG(AV_SCRATCH_3, 0x0a0a09); - */ - } -#else - /* index v << 16 | u << 8 | y */ - WRITE_VREG(AV_SCRATCH_0, 0x020100); - WRITE_VREG(AV_SCRATCH_1, 0x050403); - WRITE_VREG(AV_SCRATCH_2, 0x080706); - WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); -#endif - /* notify ucode the buffer offset */ - WRITE_VREG(AV_SCRATCH_F, buf_offset); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - WRITE_VREG(AVS_SOS_COUNT, 0); - WRITE_VREG(AVS_BUFFERIN, 0); - WRITE_VREG(AVS_BUFFEROUT, 0); - if (error_recovery_mode) - WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); - else - WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); -#if 1 /* def DEBUG_UCODE */ - WRITE_VREG(AV_SCRATCH_D, 0); -#endif - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - -#ifdef PIC_DC_NEED_CLEAR - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); -#endif - -#ifdef AVSP_LONG_CABAC - if (firmware_sel == 0) { - WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy); - WRITE_VREG(LONG_CABAC_REQ, 0); - WRITE_VREG(LONG_CABAC_PIC_SIZE, 0); - WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); - } -#endif - - WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset)); - pr_info("support_user_data = %d\n", support_user_data); - if (support_user_data) - WRITE_VREG(AV_SCRATCH_M, 1); - else - WRITE_VREG(AV_SCRATCH_M, 0); - - return r; -} - -#ifdef AVSP_LONG_CABAC -static unsigned char es_write_addr[MAX_CODED_FRAME_SIZE] __aligned(64); -#endif -static void vavs_local_init(void) -{ - int i; - - vavs_ratio = vavs_amstream_dec_info.ratio; - - avi_flag = (unsigned long) vavs_amstream_dec_info.param; - - frame_width = frame_height = frame_dur = frame_prog = 0; - - throw_pb_flag = 1; - - total_frame = 0; - saved_resolution = 0; - next_pts = 0; - -#ifdef DEBUG_PTS - pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0; -#endif - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &vfpool[i]; - - vfpool[i].index = vf_buf_num; - vfpool[i].bufWidth = 1920; - kfifo_put(&newframe_q, vf); - } - for (i = 0; i < vf_buf_num; i++) - vfbuf_use[i] = 0; - - cur_vfpool = vfpool; - - if (recover_flag == 1) - return; - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - -} - -static int vavs_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - spin_unlock_irqrestore(&lock, flags); - return 0; -} - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER -static void vavs_ppmgr_reset(void) -{ - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); - - vavs_local_init(); - - pr_info("vavs: vf_ppmgr_reset\n"); -} -#endif - -static void vavs_local_reset(void) -{ - mutex_lock(&vavs_mutex); - recover_flag = 1; - pr_info("error, local reset\n"); - amvdec_stop(); - msleep(100); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); - vavs_local_init(); - vavs_recover(); - - - reset_userdata_fifo(1); - - - amvdec_start(); - recover_flag = 0; -#if 0 - error_watchdog_count = 0; - - pr_info("pc %x stream buf wp %x rp %x level %x\n", - READ_VREG(MPC_E), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); -#endif - - - - mutex_unlock(&vavs_mutex); -} - -static struct work_struct fatal_error_wd_work; -static struct work_struct notify_work; -static atomic_t error_handler_run = ATOMIC_INIT(0); -static void vavs_fatal_error_handler(struct work_struct *work) -{ - if (debug_flag & AVS_DEBUG_OLD_ERROR_HANDLE) { - mutex_lock(&vavs_mutex); - pr_info("vavs fatal error reset !\n"); - amvdec_stop(); -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vavs_ppmgr_reset(); -#else - vf_light_unreg_provider(&vavs_vf_prov); - vavs_local_init(); - vf_reg_provider(&vavs_vf_prov); -#endif - vavs_recover(); - amvdec_start(); - mutex_unlock(&vavs_mutex); - } else { - pr_info("avs fatal_error_handler\n"); - vavs_local_reset(); - } - atomic_set(&error_handler_run, 0); -} - -static void vavs_notify_work(struct work_struct *work) -{ - if (fr_hint_status == VDEC_NEED_HINT) { - vf_notify_receiver(PROVIDER_NAME , - VFRAME_EVENT_PROVIDER_FR_HINT , - (void *)((unsigned long)frame_dur)); - fr_hint_status = VDEC_HINTED; - } - return; -} - -static void avs_set_clk(struct work_struct *work) -{ - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - if (firmware_sel == 0 && - (debug_flag & AVS_DEBUG_USE_FULL_SPEED)) { - vdec_source_changed(VFORMAT_AVS, - 4096, 2048, 60); - } else { - vdec_source_changed(VFORMAT_AVS, - frame_width, frame_height, fps); - } -} - -static void vavs_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - -#ifndef HANDLE_AVS_IRQ - vavs_isr(); -#endif - - if (READ_VREG(AVS_SOS_COUNT)) { - if (!error_recovery_mode) { -#if 0 - if (debug_flag & AVS_DEBUG_OLD_ERROR_HANDLE) { - mutex_lock(&vavs_mutex); - pr_info("vavs fatal error reset !\n"); - amvdec_stop(); -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vavs_ppmgr_reset(); -#else - vf_light_unreg_provider(&vavs_vf_prov); - vavs_local_init(); - vf_reg_provider(&vavs_vf_prov); -#endif - vavs_recover(); - amvdec_start(); - mutex_unlock(&vavs_mutex); - } else { - vavs_local_reset(); - } -#else - if (!atomic_read(&error_handler_run)) { - atomic_set(&error_handler_run, 1); - pr_info("AVS_SOS_COUNT = %d\n", - READ_VREG(AVS_SOS_COUNT)); - pr_info("WP = 0x%x, RP = 0x%x, LEVEL = 0x%x, AVAIL = 0x%x, CUR_PTR = 0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL), - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR)); - schedule_work(&fatal_error_wd_work); - } -#endif - } - } -#if 0 - if (long_cabac_busy == 0 && - error_watchdog_threshold > 0 && - kfifo_len(&display_q) == 0 && - READ_VREG(VLD_MEM_VIFIFO_LEVEL) > - error_watchdog_buf_threshold) { - pr_info("newq %d dispq %d recyq %d\r\n", - kfifo_len(&newframe_q), - kfifo_len(&display_q), - kfifo_len(&recycle_q)); - pr_info("pc %x stream buf wp %x rp %x level %x\n", - READ_VREG(MPC_E), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - error_watchdog_count++; - if (error_watchdog_count >= error_watchdog_threshold) - vavs_local_reset(); - } else - error_watchdog_count = 0; -#endif - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - - if (!kfifo_is_empty(&recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < vf_buf_num) && - (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index)); - vf->index = vf_buf_num; - } - kfifo_put(&newframe_q, - (const struct vframe_s *)vf); - } - - } - - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) - schedule_work(&set_clk_work); - - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -#ifdef AVSP_LONG_CABAC - -static void long_cabac_do_work(struct work_struct *work) -{ - int status = 0; -#ifdef PERFORMANCE_DEBUG - pr_info("enter %s buf level (new %d, display %d, recycle %d)\r\n", - __func__, - kfifo_len(&newframe_q), - kfifo_len(&display_q), - kfifo_len(&recycle_q) - ); -#endif - mutex_lock(&vavs_mutex); - long_cabac_busy = 1; - while (READ_VREG(LONG_CABAC_REQ)) { - if (process_long_cabac() < 0) { - status = -1; - break; - } - } - long_cabac_busy = 0; - mutex_unlock(&vavs_mutex); -#ifdef PERFORMANCE_DEBUG - pr_info("exit %s buf level (new %d, display %d, recycle %d)\r\n", - __func__, - kfifo_len(&newframe_q), - kfifo_len(&display_q), - kfifo_len(&recycle_q) - ); -#endif - if (status < 0) { - pr_info("transcoding error, local reset\r\n"); - vavs_local_reset(); - } - -} -#endif - -#ifdef AVSP_LONG_CABAC -static void init_avsp_long_cabac_buf(void) -{ -#if 0 - es_write_addr_phy = (unsigned long)codec_mm_alloc_for_dma( - "vavs", - PAGE_ALIGN(MAX_CODED_FRAME_SIZE)/PAGE_SIZE, - 0, CODEC_MM_FLAGS_DMA_CPU); - es_write_addr_virt = codec_mm_phys_to_virt(es_write_addr_phy); - -#elif 0 - es_write_addr_virt = - (void *)dma_alloc_coherent(amports_get_dma_device(), - MAX_CODED_FRAME_SIZE, &es_write_addr_phy, - GFP_KERNEL); -#else - /*es_write_addr_virt = kmalloc(MAX_CODED_FRAME_SIZE, GFP_KERNEL); - * es_write_addr_virt = (void *)__get_free_pages(GFP_KERNEL, - * get_order(MAX_CODED_FRAME_SIZE)); - */ - es_write_addr_virt = &es_write_addr[0]; - if (es_write_addr_virt == NULL) { - pr_err("%s: failed to alloc es_write_addr_virt buffer\n", - __func__); - return; - } - - es_write_addr_phy = dma_map_single(amports_get_dma_device(), - es_write_addr_virt, - MAX_CODED_FRAME_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - es_write_addr_phy)) { - pr_err("%s: failed to map es_write_addr_virt buffer\n", - __func__); - /*kfree(es_write_addr_virt);*/ - es_write_addr_virt = NULL; - return; - } -#endif - - -#ifdef BITSTREAM_READ_TMP_NO_CACHE - bitstream_read_tmp = - (void *)dma_alloc_coherent(amports_get_dma_device(), - SVA_STREAM_BUF_SIZE, &bitstream_read_tmp_phy, - GFP_KERNEL); - -#else - - bitstream_read_tmp = kmalloc(SVA_STREAM_BUF_SIZE, GFP_KERNEL); - /*bitstream_read_tmp = (void *)__get_free_pages(GFP_KERNEL, - *get_order(MAX_CODED_FRAME_SIZE)); - */ - if (bitstream_read_tmp == NULL) { - pr_err("%s: failed to alloc bitstream_read_tmp buffer\n", - __func__); - return; - } - - bitstream_read_tmp_phy = dma_map_single(amports_get_dma_device(), - bitstream_read_tmp, - SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - bitstream_read_tmp_phy)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(bitstream_read_tmp); - bitstream_read_tmp = NULL; - return; - } -#endif -} -#endif - - -static s32 vavs_init(void) -{ - int ret, size = -1; - char *buf = vmalloc(0x1000 * 16); - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - pr_info("vavs_init\n"); - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - amvdec_enable(); - - vdec_enable_DMC(NULL); - - vavs_local_init(); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) - size = get_firmware_data(VIDEO_DEC_AVS, buf); - else { - if (firmware_sel == 1) - size = get_firmware_data(VIDEO_DEC_AVS_NOCABAC, buf); -#ifdef AVSP_LONG_CABAC - else { - init_avsp_long_cabac_buf(); - size = get_firmware_data(VIDEO_DEC_AVS, buf); - } -#endif - } - - if (size < 0) { - amvdec_disable(); - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) - ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); - else if (firmware_sel == 1) - ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", buf); - else - ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); - - if (ret < 0) { - amvdec_disable(); - vfree(buf); - pr_err("AVS: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(buf); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - ret = vavs_prot_init(); - if (ret < 0) - return ret; - -#ifdef HANDLE_AVS_IRQ - if (vdec_request_irq(VDEC_IRQ_1, vavs_isr, - "vavs-irq", (void *)vavs_dec_id)) { - amvdec_disable(); - pr_info("vavs irq register error.\n"); - return -ENOENT; - } -#endif - - stat |= STAT_ISR_REG; - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, NULL); - vf_reg_provider(&vavs_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, NULL); - vf_reg_provider(&vavs_vf_prov); -#endif - - if (vavs_amstream_dec_info.rate != 0) { - if (!is_reset) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long) - vavs_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; - } - } else - fr_hint_status = VDEC_NEED_HINT; - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong)(&recycle_timer); - recycle_timer.function = vavs_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - -#ifdef AVSP_LONG_CABAC - if (firmware_sel == 0) - INIT_WORK(&long_cabac_wd_work, long_cabac_do_work); -#endif - vdec_source_changed(VFORMAT_AVS, - 1920, 1080, 30); - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - return 0; -} - -static int amvdec_avs_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - if (pdata == NULL) { - pr_info("amvdec_avs memory resource undefined.\n"); - return -EFAULT; - } - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) - firmware_sel = 1; - - if (firmware_sel == 1) { - vf_buf_num = 4; - canvas_base = 0; - canvas_num = 3; - } else { - - canvas_base = 128; - canvas_num = 2; /*NV21*/ - } - - - if (pdata->sys_info) - vavs_amstream_dec_info = *pdata->sys_info; - - pr_info("%s (%d,%d) %d\n", __func__, vavs_amstream_dec_info.width, - vavs_amstream_dec_info.height, vavs_amstream_dec_info.rate); - - pdata->dec_status = vavs_dec_status; - pdata->set_isreset = vavs_set_isreset; - is_reset = 0; - - pdata->user_data_read = NULL; - pdata->reset_userdata_fifo = NULL; - - vavs_vdec_info_init(); - - - if (NULL == user_data_buffer) { - user_data_buffer = - dma_alloc_coherent(amports_get_dma_device(), - USER_DATA_SIZE, - &user_data_buffer_phys, GFP_KERNEL); - if (!user_data_buffer) { - pr_info("%s: Can not allocate user_data_buffer\n", - __func__); - return -ENOMEM; - } - pr_debug("user_data_buffer = 0x%p, user_data_buffer_phys = 0x%x\n", - user_data_buffer, (u32)user_data_buffer_phys); - } - - INIT_WORK(&set_clk_work, avs_set_clk); - vdec = pdata; - if (vavs_init() < 0) { - pr_info("amvdec_avs init failed.\n"); - kfree(gvs); - gvs = NULL; - pdata->dec_status = NULL; - return -ENODEV; - } - - INIT_WORK(&fatal_error_wd_work, vavs_fatal_error_handler); - atomic_set(&error_handler_run, 0); - - INIT_WORK(&userdata_push_work, userdata_push_do_work); - - INIT_WORK(¬ify_work, vavs_notify_work); - - return 0; -} - -static int amvdec_avs_remove(struct platform_device *pdev) -{ - cancel_work_sync(&fatal_error_wd_work); - atomic_set(&error_handler_run, 0); - - cancel_work_sync(&userdata_push_work); - - cancel_work_sync(¬ify_work); - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id); - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } -#ifdef AVSP_LONG_CABAC - if (firmware_sel == 0) { - mutex_lock(&vavs_mutex); - cancel_work_sync(&long_cabac_wd_work); - mutex_unlock(&vavs_mutex); - - if (es_write_addr_virt) { -#if 0 - codec_mm_free_for_dma("vavs", es_write_addr_phy); -#else - dma_unmap_single(amports_get_dma_device(), - es_write_addr_phy, - MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE); - /*kfree(es_write_addr_virt);*/ - es_write_addr_virt = NULL; -#endif - } - -#ifdef BITSTREAM_READ_TMP_NO_CACHE - if (bitstream_read_tmp) { - dma_free_coherent(amports_get_dma_device(), - SVA_STREAM_BUF_SIZE, bitstream_read_tmp, - bitstream_read_tmp_phy); - bitstream_read_tmp = NULL; - } -#else - if (bitstream_read_tmp) { - dma_unmap_single(amports_get_dma_device(), - bitstream_read_tmp_phy, - SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); - kfree(bitstream_read_tmp); - bitstream_read_tmp = NULL; - } -#endif - } -#endif - if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); - fr_hint_status = VDEC_NO_NEED_HINT; - vf_unreg_provider(&vavs_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - - if (user_data_buffer != NULL) { - dma_free_coherent( - amports_get_dma_device(), - USER_DATA_SIZE, - user_data_buffer, - user_data_buffer_phys); - user_data_buffer = NULL; - user_data_buffer_phys = 0; - } - - - amvdec_disable(); - vdec_disable_DMC(NULL); - - pic_type = 0; - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } -#ifdef DEBUG_PTS - pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit, - pts_missed, pts_i_hit, pts_i_missed); - pr_debug("total frame %d, avi_flag %d, rate %d\n", total_frame, avi_flag, - vavs_amstream_dec_info.rate); -#endif - kfree(gvs); - gvs = NULL; - - cancel_work_sync(&set_clk_work); - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_avs_driver = { - .probe = amvdec_avs_probe, - .remove = amvdec_avs_remove, - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_avs_profile = { - .name = "avs", - .profile = "" -}; - -static struct mconfig avs_configs[] = { - MC_PU32("stat", &stat), - MC_PU32("debug_flag", &debug_flag), - MC_PU32("error_recovery_mode", &error_recovery_mode), - MC_PU32("pic_type", &pic_type), - MC_PU32("radr", &radr), - MC_PU32("vf_buf_num", &vf_buf_num), - MC_PU32("vf_buf_num_used", &vf_buf_num_used), - MC_PU32("canvas_base", &canvas_base), - MC_PU32("firmware_sel", &firmware_sel), -}; -static struct mconfig_node avs_node; - - -static int __init amvdec_avs_driver_init_module(void) -{ - pr_debug("amvdec_avs module init\n"); - - if (platform_driver_register(&amvdec_avs_driver)) { - pr_info("failed to register amvdec_avs driver\n"); - return -ENODEV; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) - amvdec_avs_profile.profile = "avs+"; - - vcodec_profile_register(&amvdec_avs_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &avs_node, - "avs", avs_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_avs_driver_remove_module(void) -{ - pr_debug("amvdec_avs module remove.\n"); - - platform_driver_unregister(&amvdec_avs_driver); -} - -/****************************************/ - -module_param(stat, uint, 0664); -MODULE_PARM_DESC(stat, "\n amvdec_avs stat\n"); - -/****************************************** - *module_param(run_flag, uint, 0664); - *MODULE_PARM_DESC(run_flag, "\n run_flag\n"); - * - *module_param(step_flag, uint, 0664); - *MODULE_PARM_DESC(step_flag, "\n step_flag\n"); - ******************************************* - */ - -module_param(debug_flag, uint, 0664); -MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); - -module_param(error_recovery_mode, uint, 0664); -MODULE_PARM_DESC(error_recovery_mode, "\n error_recovery_mode\n"); - -/****************************************** - *module_param(error_watchdog_threshold, uint, 0664); - *MODULE_PARM_DESC(error_watchdog_threshold, "\n error_watchdog_threshold\n"); - * - *module_param(error_watchdog_buf_threshold, uint, 0664); - *MODULE_PARM_DESC(error_watchdog_buf_threshold, - * "\n error_watchdog_buf_threshold\n"); - ******************************************* - */ - -module_param(pic_type, uint, 0444); -MODULE_PARM_DESC(pic_type, "\n amdec_vas picture type\n"); - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\nradr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\nrval\n"); - -module_param(vf_buf_num, uint, 0664); -MODULE_PARM_DESC(vf_buf_num, "\nvf_buf_num\n"); - -module_param(vf_buf_num_used, uint, 0664); -MODULE_PARM_DESC(vf_buf_num_used, "\nvf_buf_num_used\n"); - -module_param(canvas_base, uint, 0664); -MODULE_PARM_DESC(canvas_base, "\ncanvas_base\n"); - - -module_param(firmware_sel, uint, 0664); -MODULE_PARM_DESC(firmware_sel, "\n firmware_sel\n"); - -module_param(disable_longcabac_trans, uint, 0664); -MODULE_PARM_DESC(disable_longcabac_trans, "\n disable_longcabac_trans\n"); - -module_param(dec_control, uint, 0664); -MODULE_PARM_DESC(dec_control, "\n amvdec_vavs decoder control\n"); - -module_param(support_user_data, uint, 0664); -MODULE_PARM_DESC(support_user_data, "\n support_user_data\n"); - -module_init(amvdec_avs_driver_init_module); -module_exit(amvdec_avs_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC AVS Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Qi Wang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h deleted file mode 100644 index 8277d202d3cd..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef AVS_H_ -#define AVS_H_ - -#ifdef CONFIG_AMLOGIC_AVSP_LONG_CABAC -#define AVSP_LONG_CABAC -#endif -/*#define BITSTREAM_READ_TMP_NO_CACHE*/ - -#ifdef AVSP_LONG_CABAC -#define MAX_CODED_FRAME_SIZE 1500000 /*!< bytes for one frame*/ -#define LOCAL_HEAP_SIZE (1024*1024*10) -/* - *#define MAX_CODED_FRAME_SIZE 240000 - *#define MAX_CODED_FRAME_SIZE 700000 - */ -#define SVA_STREAM_BUF_SIZE 1024 - -extern void *es_write_addr_virt; -extern dma_addr_t es_write_addr_phy; - -extern void *bitstream_read_tmp; -extern dma_addr_t bitstream_read_tmp_phy; -extern void *avsp_heap_adr; - -int avs_get_debug_flag(void); - -int process_long_cabac(void); - -/* bit [6] - skip_mode_flag - * bit [5:4] - picture_type - * bit [3] - picture_structure (0-Field, 1-Frame) - * bit [2] - fixed_picture_qp - * bit [1] - progressive_sequence - * bit [0] - active - */ -#define LONG_CABAC_REQ AV_SCRATCH_K -#define LONG_CABAC_SRC_ADDR AV_SCRATCH_H -#define LONG_CABAC_DES_ADDR AV_SCRATCH_I -/* bit[31:16] - vertical_size - * bit[15:0] - horizontal_size - */ -#define LONG_CABAC_PIC_SIZE AV_SCRATCH_J - -#endif - -/* - *#define PERFORMANCE_DEBUG - *#define DUMP_DEBUG - */ -#define AVS_DEBUG_PRINT 0x01 -#define AVS_DEBUG_UCODE 0x02 -#define AVS_DEBUG_OLD_ERROR_HANDLE 0x10 -#define AVS_DEBUG_USE_FULL_SPEED 0x80 -#define AEC_DUMP 0x100 -#define STREAM_INFO_DUMP 0x200 -#define SLICE_INFO_DUMP 0x400 -#define MB_INFO_DUMP 0x800 -#define MB_NUM_DUMP 0x1000 -#define BLOCK_NUM_DUMP 0x2000 -#define COEFF_DUMP 0x4000 -#define ES_DUMP 0x8000 -#define DQUANT_DUMP 0x10000 -#define STREAM_INFO_DUMP_MORE 0x20000 -#define STREAM_INFO_DUMP_MORE2 0x40000 - -extern void *es_write_addr_virt; -extern void *bitstream_read_tmp; -extern dma_addr_t bitstream_read_tmp_phy; -int read_bitstream(unsigned char *Buf, int size); -int u_v(int LenInBits, char *tracestring); - -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c deleted file mode 100644 index b5dc44468278..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c +++ /dev/null @@ -1,5065 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* #include */ -#include -#include -#include "../../../stream_input/parser/streambuf_reg.h" -#include "../utils/amvdec.h" -#include -#include "../../../stream_input/amports/amports_priv.h" - -#include "avs.h" -#ifdef AVSP_LONG_CABAC - -#define DECODING_SANITY_CHECK - -#define TRACE 0 -#define LIWR_FIX 0 -#define pow2(a, b) (1< 0) { - if (num >= 8) - push_num = 8; - else - push_num = num; - - num = num - push_num; - push_value = (value >> num); - - es_res = (es_res << push_num) | push_value; - es_res_ptr = es_res_ptr + push_num; - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & ES_DUMP) - io_printf(" #### es_res : 0x%X, es_res_ptr : %d\n", - es_res, es_res_ptr); -#endif - - while (es_res_ptr >= 8) { - es_res_ptr = es_res_ptr & 7; - wr_es_data = (es_res >> es_res_ptr) & 0xff; - if ((previous_es == 0) & (wr_es_data < 4)) { - io_printf( - " Insert 2'b10 for emu at position : %d\n", - es_ptr); - - es_res_ptr = es_res_ptr + 2; - wr_es_data = 2; - } -#ifdef AVSP_LONG_CABAC -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & ES_DUMP) - pr_info("es_buf[%d] = 0x%02x\r\n", - es_buf_ptr, wr_es_data); -#endif - if (!es_buf_is_overflow) { - es_buf[es_buf_ptr++] = wr_es_data; - if (es_buf_ptr >= MAX_CODED_FRAME_SIZE) - es_buf_is_overflow = 1; - } -#else - putc(wr_es_data, f_es); -#endif - es_ptr++; - previous_es = ((previous_es << 8) | wr_es_data) - & 0xffff; - } - - } -} - -#ifdef BLOCK_SIZE -#undef BLOCK_SIZE -#endif - -#define MIN_QP 0 -#define MAX_QP 63 - -#define BLOCK_SIZE 4 -#define B8_SIZE 8 -#define MB_BLOCK_SIZE 16 - -#define BLOCK_MULTIPLE (MB_BLOCK_SIZE/(BLOCK_SIZE*2)) - -#define DECODE_COPY_MB 0 -#define DECODE_MB 1 - -#define NO_INTRA_PMODE 5 -#define INTRA_PMODE_4x4 10 -#define NO_INTRA_PMODE_4x4 19 -/* 8x8 intra prediction modes */ -#define VERT_PRED 0 -#define HOR_PRED 1 -#define DC_PRED 2 -#define DOWN_LEFT_PRED 3 -#define DOWN_RIGHT_PRED 4 - -#define VERT_PRED_4x4 0 -#define HOR_PRED_4x4 1 -#define DC_PRED_4x4 2 -#define DOWN_LEFT_PRED_4x4 3 -#define DOWN_RIGHT_PRED_4x4 4 - -#define HOR_DOWN_PRED_4x4 5 -#define VERT_LEFT_PRED_4x4 6 -#define HOR_UP_PRED_4x4 7 -#define VERT_RIGHT_PRED_4x4 8 - -#define DC_PRED_8 0 -#define HOR_PRED_8 1 -#define VERT_PRED_8 2 -#define PLANE_8 3 - -#define LUMA_16DC 0 -#define LUMA_16AC 1 -#define LUMA_8x8 2 -#define LUMA_8x4 3 -#define LUMA_4x8 4 -#define LUMA_4x4 5 -#define CHROMA_DC 6 -#define CHROMA_AC 7 -#define NUM_BLOCK_TYPES 8 - -#define I_PICTURE_START_CODE 0xB3 -#define PB_PICTURE_START_CODE 0xB6 -#define SLICE_START_CODE_MIN 0x00 -#define SLICE_START_CODE_MAX 0xAF -#define USER_DATA_START_CODE 0xB2 -#define SEQUENCE_HEADER_CODE 0xB0 -#define EXTENSION_START_CODE 0xB5 -#define SEQUENCE_END_CODE 0xB1 -#define VIDEO_EDIT_CODE 0xB7 - -#define EOS 1 -#define SOP 2 -#define SOS 3 -#define P8x8 8 -#define I8MB 9 -#define I4MB 10 -#define IBLOCK 11 -#define SI4MB 12 -#define MAXMODE 13 - -#define IS_INTRA(MB) ((MB)->mb_type == I8MB || (MB)->mb_type == I4MB) -#define IS_NEWINTRA(MB) ((MB)->mb_type == I4MB) -#define IS_OLDINTRA(MB) ((MB)->mb_type == I8MB) -#define IS_INTER(MB) ((MB)->mb_type != I8MB && (MB)->mb_type != I4MB) -#define IS_INTERMV(MB) ((MB)->mb_type != I8MB && (MB)->mb_type != I4MB\ - && (MB)->mb_type != 0) - -#define IS_DIRECT(MB) ((MB)->mb_type == 0 && (img->type == B_IMG)) -#define IS_COPY(MB) ((MB)->mb_type == 0 && (img->type == P_IMG)) -#define IS_P8x8(MB) ((MB)->mb_type == P8x8) - -#define P_IMG 0 -#define B_IMG 1 -#define I_IMG 2 - -#define FIELD 0 -#define FRAME 1 - -#define SE_CABP 21 -struct decoding_environment_s { - unsigned int dbuffer; - int dbits_to_go; - unsigned char *dcodestrm; - int *dcodestrm_len; -}; - -struct bi_context_type_s { - unsigned char MPS; - unsigned int LG_PMPS; - unsigned char cycno; -}; - - -/********************************************************************** - * C O N T E X T S F O R R M S Y N T A X E L E M E N T S - ********************************************************************** - */ - -#define NUM_MB_TYPE_CTX 11 -#define NUM_B8_TYPE_CTX 9 -#define NUM_MV_RES_CTX 10 -#define NUM_REF_NO_CTX 6 -#define NUM_DELTA_QP_CTX 4 -#define NUM_MB_AFF_CTX 4 - -struct motion_info_contexts_s { - struct bi_context_type_s mb_type_contexts[4][NUM_MB_TYPE_CTX]; - struct bi_context_type_s b8_type_contexts[2][NUM_B8_TYPE_CTX]; - struct bi_context_type_s mv_res_contexts[2][NUM_MV_RES_CTX]; - struct bi_context_type_s ref_no_contexts[2][NUM_REF_NO_CTX]; - struct bi_context_type_s delta_qp_contexts[NUM_DELTA_QP_CTX]; - struct bi_context_type_s mb_aff_contexts[NUM_MB_AFF_CTX]; -#ifdef TEST_WEIGHTING_AEC -struct bi_context_type_s mb_weighting_pred; -#endif -}; - -#define NUM_IPR_CTX 2 -#define NUM_CIPR_CTX 4 -#define NUM_CBP_CTX 4 -#define NUM_BCBP_CTX 4 -#define NUM_MAP_CTX 16 -#define NUM_LAST_CTX 16 - -#define NUM_ONE_CTX 5 -#define NUM_ABS_CTX 5 - -struct texture_info_contexts { - struct bi_context_type_s ipr_contexts[NUM_IPR_CTX]; - struct bi_context_type_s cipr_contexts[NUM_CIPR_CTX]; - struct bi_context_type_s cbp_contexts[3][NUM_CBP_CTX]; - struct bi_context_type_s bcbp_contexts[NUM_BLOCK_TYPES][NUM_BCBP_CTX]; - struct bi_context_type_s one_contexts[NUM_BLOCK_TYPES][NUM_ONE_CTX]; - struct bi_context_type_s abs_contexts[NUM_BLOCK_TYPES][NUM_ABS_CTX]; - struct bi_context_type_s fld_map_contexts[NUM_BLOCK_TYPES][NUM_MAP_CTX]; - struct bi_context_type_s fld_last_contexts - [NUM_BLOCK_TYPES][NUM_LAST_CTX]; - struct bi_context_type_s map_contexts[NUM_BLOCK_TYPES][NUM_MAP_CTX]; - struct bi_context_type_s last_contexts[NUM_BLOCK_TYPES][NUM_LAST_CTX]; -}; -struct img_par; - -struct syntaxelement { - int type; - int value1; - int value2; - int len; - int inf; - unsigned int bitpattern; - int context; - int k; - int golomb_grad; - int golomb_maxlevels; -#if TRACE -#define TRACESTRING_SIZE 100 - char tracestring[TRACESTRING_SIZE]; -#endif - - void (*mapping)(int len, int info, int *value1, int *value2); - - void (*reading)(struct syntaxelement *, struct img_par *, - struct decoding_environment_s *); - -}; - -struct bitstream_s { - - int read_len; - int code_len; - - int frame_bitoffset; - int bitstream_length; - - unsigned char *stream_buffer; -}; - -struct datapartition { - - struct bitstream_s *bitstream; - struct decoding_environment_s de_aec; - - int (*read_syntax_element)(struct syntaxelement *, struct img_par *, - struct datapartition *); -/*!< virtual function; - * actual method depends on chosen data partition and - * entropy coding method - */ -}; - -struct slice_s { - int picture_id; - int qp; - int picture_type; - int start_mb_nr; - int max_part_nr; - int num_mb; - - struct datapartition *part_arr; - struct motion_info_contexts_s *mot_ctx; - struct texture_info_contexts *tex_ctx; - int field_ctx[3][2]; -}; - -struct img_par { - int number; - int current_mb_nr; - int max_mb_nr; - int current_slice_nr; - int tr; - int qp; - int type; - - int typeb; - - int width; - int height; - int width_cr; - int height_cr; - int source_bitdepth; - int mb_y; - int mb_x; - int block_y; - int pix_y; - int pix_x; - int pix_c_y; - int block_x; - int pix_c_x; - - int ***mv; - int mpr[16][16]; - - int m7[16][16]; - int m8[/*2*/4][8][8]; - int cof[4][/*6*/8][4][4]; - int cofu[4]; - int **ipredmode; - int quad[256]; - int cod_counter; - - int ***dfmv; - int ***dbmv; - int **fw_reffrarr; - int **bw_reffrarr; - - int ***mv_frm; - int **fw_reffrarr_frm; - int **bw_reffrarr_frm; - int imgtr_next_p; - int imgtr_last_p; - int tr_frm; - int tr_fld; - int imgtr_last_prev_p; - - int no_forward_reference; - int seq_header_indicate; - int b_discard_flag; - - int ***fw_mv; - int ***bw_mv; - int subblock_x; - int subblock_y; - - int buf_cycle; - - int direct_type; - - int ***mv_top; - int ***mv_bot; - int **fw_reffrarr_top; - int **bw_reffrarr_top; - int **fw_reffrarr_bot; - int **bw_reffrarr_bot; - - int **ipredmode_top; - int **ipredmode_bot; - int ***fw_mv_top; - int ***fw_mv_bot; - int ***bw_mv_top; - int ***bw_mv_bot; - int ***dfmv_top; - int ***dbmv_top; - int ***dfmv_bot; - int ***dbm_bot; - - int toppoc; - int bottompoc; - int framepoc; - unsigned int frame_num; - - unsigned int pic_distance; - int delta_pic_order_cnt_bottom; - - signed int pic_distance_msb; - unsigned int prev_pic_distance_lsb; - signed int curr_pic_distance_msb; - unsigned int this_poc; - - int pic_width_inmbs; - int pic_height_inmbs; - int pic_size_inmbs; - - int block8_x, block8_y; - int structure; - int pn; - int buf_used; - int buf_size; - int picture_structure; - int advanced_pred_mode_disable; - int types; - int current_mb_nr_fld; - - int p_field_enhanced; - int b_field_enhanced; - - int slice_weighting_flag; - int lum_scale[4]; - int lum_shift[4]; - int chroma_scale[4]; - int chroma_shift[4]; - int mb_weighting_flag; - int weighting_prediction; - int mpr_weight[16][16]; - int top_bot; - int bframe_number; - - int auto_crop_right; - int auto_crop_bottom; - - struct slice_s *current_slice; - int is_v_block; - int is_intra_block; - - int new_seq_header_flag; - int new_sequence_flag; - int last_pic_bbv_delay; - - int sequence_end_flag; - int is_top_field; - - int abt_flag; - int qp_shift; - -#ifdef EIGHTH -int eighth_subpixel_flag; -int subpixel_precision; -int unit_length; -int subpixel_mask; - -int max_mvd; -int min_mvd; -#endif - -}; - -struct macroblock { - int qp; - int slice_nr; - int delta_quant; - struct macroblock *mb_available[3][3]; - /*!< pointer to neighboring MBs in a 3x3 window of current MB, - *which is located at [1][1] - * NULL pointer identifies neighboring MBs which are unavailable - */ - - int mb_type; - int mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][2]; - int cbp, cbp_blk, cbp01; - unsigned long cbp_bits; - - int b8mode[4]; - int b8pdir[4]; - int mb_type_2; - int c_ipred_mode_2; - int dct_mode; - - int c_ipred_mode; - int lf_disable; - int lf_alpha_c0_offset; - int lf_beta_offset; - - int CABT[4]; - int CABP[4]; - int cbp_4x4[4]; - - int skip_flag; - - struct macroblock *mb_available_up; - struct macroblock *mb_available_left; - unsigned int mbaddr_a, mbaddr_b, mbaddr_c, mbaddr_d; - unsigned int mbavail_a, mbavail_b, mbavail_c, mbavail_d; - -}; - -struct macroblock *mb_data; - -struct img_par *img; - -struct bitstream_s *curr_stream; - -struct datapartition *alloc_partition(int n); - -unsigned int vld_mem_start_addr; -unsigned int vld_mem_end_addr; - -int marker_bit; - -int progressive_sequence; -int horizontal_size; -int vertical_size; - -int second_ifield; -int pre_img_type; - -/* slice_header() */ -int slice_vertical_position; -int slice_vertical_position_extension; -int fixed_picture_qp; -int fixed_slice_qp; -int slice_qp; - -/* - ************************************************************************* - * Function:ue_v, reads an u(v) syntax element, the length in bits is stored in - the global UsedBits variable - * Input: - tracestring - the string for the trace file - bitstream - the stream to be read from - * Output: - * Return: the value of the coded syntax element - * Attention: - ************************************************************************* - */ -/*! - * definition of AVS syntaxelements - * order of elements follow dependencies for picture reconstruction - */ -/*! - * \brief Assignment of old TYPE partition elements to new - * elements - * - * old element | new elements - * TYPE_HEADER | SE_HEADER, SE_PTYPE - * TYPE_MBHEADER | SE_MBTYPE, SE_REFFRAME, SE_INTRAPREDMODE - * TYPE_MVD | SE_MVD - * TYPE_CBP | SE_CBP_INTRA, SE_CBP_INTER * SE_DELTA_QUANT_INTER - * SE_DELTA_QUANT_INTRA - * TYPE_COEFF_Y | SE_LUM_DC_INTRA, SE_LUM_AC_INTRA, - SE_LUM_DC_INTER, SE_LUM_AC_INTER - * TYPE_2x2DC | SE_CHR_DC_INTRA, SE_CHR_DC_INTER - * TYPE_COEFF_C | SE_CHR_AC_INTRA, SE_CHR_AC_INTER - * TYPE_EOS | SE_EOS - */ - -#define SE_HEADER 0 -#define SE_PTYPE 1 -#define SE_MBTYPE 2 -#define SE_REFFRAME 3 -#define SE_INTRAPREDMODE 4 -#define SE_MVD 5 -#define SE_CBP_INTRA 6 -#define SE_LUM_DC_INTRA 7 -#define SE_CHR_DC_INTRA 8 -#define SE_LUM_AC_INTRA 9 -#define SE_CHR_AC_INTRA 10 -#define SE_CBP_INTER 11 -#define SE_LUM_DC_INTER 12 -#define SE_CHR_DC_INTER 13 -#define SE_LUM_AC_INTER 14 -#define SE_CHR_AC_INTER 15 -#define SE_DELTA_QUANT_INTER 16 -#define SE_DELTA_QUANT_INTRA 17 -#define SE_BFRAME 18 -#define SE_EOS 19 -#define SE_MAX_ELEMENTS 20 -#define SE_CBP01 21 -int chroma_format; -/* - ************************************************************************* - * Function:Reads bits from the bitstream buffer - * Input: - byte buffer[] - containing VLC-coded data bits - int totbitoffset - bit offset from start of partition - int bytecount - total bytes in bitstream - int numbits - number of bits to read - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -int get_bits(unsigned char buffer[], int totbitoffset, int *info, int bytecount, - int numbits) -{ - register int inf; - long byteoffset; - int bitoffset; - - int bitcounter = numbits; - - byteoffset = totbitoffset / 8; - bitoffset = 7 - (totbitoffset % 8); - - inf = 0; - while (numbits) { - inf <<= 1; - inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset; - numbits--; - bitoffset--; - if (bitoffset < 0) { - byteoffset++; - bitoffset += 8; - if (byteoffset > bytecount) - return -1; - } - } - - *info = inf; - - - return bitcounter; -} - -/* - ************************************************************************* - * Function:read FLC codeword from UVLC-partition - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -int read_syntaxelement_flc(struct syntaxelement *sym) -{ - int frame_bitoffset = curr_stream->frame_bitoffset; - unsigned char *buf = curr_stream->stream_buffer; - int bitstreamlengthinbytes = curr_stream->bitstream_length; - - if ((get_bits(buf, frame_bitoffset, &(sym->inf), bitstreamlengthinbytes, - sym->len)) < 0) - return -1; - - curr_stream->frame_bitoffset += sym->len; - sym->value1 = sym->inf; - -#if TRACE - tracebits2(sym->tracestring, sym->len, sym->inf); -#endif - - return 1; -} - -/* - ************************************************************************* - * Function:ue_v, reads an u(1) syntax element, the length in bits is stored in - the global UsedBits variable - * Input: - tracestring - the string for the trace file - bitstream - the stream to be read from - * Output: - * Return: the value of the coded syntax element - * Attention: - ************************************************************************* - */ -int u_1(char *tracestring) -{ - return u_v(1, tracestring); -} - -/* - ************************************************************************* - * Function:mapping rule for ue(v) syntax elements - * Input:length and info - * Output:number in the code table - * Return: - * Attention: - ************************************************************************* - */ -void linfo_ue(int len, int info, int *value1, int *dummy) -{ - *value1 = (int)pow2(2, (len / 2)) + info - 1; -} - -int u_v(int leninbits, char *tracestring) -{ - struct syntaxelement symbol, *sym = &symbol; - -#ifdef AVSP_LONG_CABAC -#else - assert(curr_stream->stream_buffer != NULL); -#endif - sym->type = SE_HEADER; - sym->mapping = linfo_ue; - sym->len = leninbits; - read_syntaxelement_flc(sym); - - return sym->inf; -} - -/* - ************************************************************************* - * Function:mapping rule for se(v) syntax elements - * Input:length and info - * Output:signed mvd - * Return: - * Attention: - ************************************************************************* - */ - -void linfo_se(int len, int info, int *value1, int *dummy) -{ - int n; - - n = (int)pow2(2, (len / 2)) + info - 1; - *value1 = (n + 1) / 2; - if ((n & 0x01) == 0) - *value1 = -*value1; - -} - -/* - ************************************************************************* - * Function:length and info - * Input: - * Output:cbp (intra) - * Return: - * Attention: - ************************************************************************* - */ - -void linfo_cbp_intra(int len, int info, int *cbp, int *dummy) -{ -} - -const int NCBP[64][2] = {{4, 0}, {16, 19}, {17, 16}, {19, 15}, {14, 18}, - {9, 11}, {22, 31}, {8, 13}, {11, 17}, {21, 30}, {10, 12}, - {7, 9}, {12, 10}, {6, 7}, {5, 8}, {1, 1}, {35, 4}, {47, 42}, { - 48, 38}, {38, 27}, {46, 39}, {36, 33}, {50, 59}, - {26, 26}, {45, 40}, {52, 58}, {41, 35}, {28, 25}, {37, 29}, {23, - 24}, {31, 28}, {2, 3}, {43, 5}, {51, 51}, {56, - 52}, {39, 37}, {55, 50}, {33, 43}, {62, 63}, { - 27, 44}, {54, 53}, {60, 62}, {40, 48}, {32, 47}, - {42, 34}, {24, 45}, {29, 49}, {3, 6}, {49, 14}, {53, 55}, {57, - 56}, {25, 36}, {58, 54}, {30, 41}, {59, 60}, { - 15, 21}, {61, 57}, {63, 61}, {44, 46}, {18, 22}, - {34, 32}, {13, 20}, {20, 23}, {0, 2} }; - -unsigned int s1, t1, value_s, value_t; -unsigned char dec_bypass, dec_final; - -#define get_byte() { \ - dbuffer = dcodestrm[(*dcodestrm_len)++];\ - dbits_to_go = 7; \ -} - -#define dbuffer (dep->dbuffer) -#define dbits_to_go (dep->dbits_to_go) -#define dcodestrm (dep->dcodestrm) -#define dcodestrm_len (dep->dcodestrm_len) - -#define B_BITS 10 - -#define LG_PMPS_SHIFTNO 2 - -#define HALF (1 << (B_BITS-1)) -#define QUARTER (1 << (B_BITS-2)) - -unsigned int biari_decode_symbol(struct decoding_environment_s *dep, - struct bi_context_type_s *bi_ct) -{ - register unsigned char bit; - register unsigned char s_flag; - register unsigned char is_lps = 0; - register unsigned char cwr; - register unsigned char cycno = bi_ct->cycno; - register unsigned int lg_pmps = bi_ct->LG_PMPS; - register unsigned int t_rlps; - register unsigned int s2, t2; - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & AEC_DUMP) - io_printf("LG_PMPS : %03X, MPS : %d, cycno : %d -- %p\n", - bi_ct->LG_PMPS, bi_ct->MPS, bi_ct->cycno, bi_ct); -#endif - - bit = bi_ct->MPS; - - cwr = (cycno <= 1) ? 3 : (cycno == 2) ? 4 : 5; - - if (t1 >= (lg_pmps >> LG_PMPS_SHIFTNO)) { - s2 = s1; - t2 = t1 - (lg_pmps >> LG_PMPS_SHIFTNO); - s_flag = 0; - } else { - s2 = s1 + 1; - t2 = 256 + t1 - (lg_pmps >> LG_PMPS_SHIFTNO); - s_flag = 1; - } - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & AEC_DUMP) - io_printf(" s2 : %d, t2 : %03X\n", s2, t2); -#endif - - if (s2 > value_s || (s2 == value_s && value_t >= t2)) { - is_lps = 1; - bit = !bit; - - t_rlps = (s_flag == 0) ? - (lg_pmps >> LG_PMPS_SHIFTNO) : - (t1 + (lg_pmps >> LG_PMPS_SHIFTNO)); - - if (s2 == value_s) - value_t = (value_t - t2); - else { - if (--dbits_to_go < 0) - get_byte(); - - value_t = (value_t << 1) - | ((dbuffer >> dbits_to_go) & 0x01); - value_t = 256 + value_t - t2; - - } - - while (t_rlps < QUARTER) { - t_rlps = t_rlps << 1; - if (--dbits_to_go < 0) - get_byte(); - - value_t = (value_t << 1) - | ((dbuffer >> dbits_to_go) & 0x01); - } - - s1 = 0; - t1 = t_rlps & 0xff; - - value_s = 0; - while (value_t < QUARTER) { - int j; - - if (--dbits_to_go < 0) - get_byte(); - j = (dbuffer >> dbits_to_go) & 0x01; - - value_t = (value_t << 1) | j; - value_s++; - } - value_t = value_t & 0xff; - } else { - - s1 = s2; - t1 = t2; - } - - if (dec_bypass) - return bit; - - if (is_lps) - cycno = (cycno <= 2) ? (cycno + 1) : 3; - else if (cycno == 0) - cycno = 1; - bi_ct->cycno = cycno; - - if (is_lps) { - switch (cwr) { - case 3: - lg_pmps = lg_pmps + 197; - break; - case 4: - lg_pmps = lg_pmps + 95; - break; - default: - lg_pmps = lg_pmps + 46; - } - - if (lg_pmps >= (256 << LG_PMPS_SHIFTNO)) { - lg_pmps = (512 << LG_PMPS_SHIFTNO) - 1 - lg_pmps; - bi_ct->MPS = !(bi_ct->MPS); - } - } else { -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & AEC_DUMP) - io_printf(" - lg_pmps_MPS : %X (%X - %X - %X)\n", - lg_pmps - (unsigned int)(lg_pmps>>cwr) - - (unsigned int)(lg_pmps>>(cwr+2)), - lg_pmps, - (unsigned int)(lg_pmps>>cwr), - (unsigned int)(lg_pmps>>(cwr+2)) - ); -#endif - lg_pmps = lg_pmps - (unsigned int)(lg_pmps >> cwr) - - (unsigned int)(lg_pmps >> (cwr + 2)); - } - - bi_ct->LG_PMPS = lg_pmps; - - return bit; -} - -unsigned int biari_decode_symbolw(struct decoding_environment_s *dep, - struct bi_context_type_s *bi_ct1, - struct bi_context_type_s *bi_ct2) -{ - register unsigned char bit1, bit2; - register unsigned char pred_mps, bit; - register unsigned int lg_pmps; - register unsigned char cwr1, cycno1 = bi_ct1->cycno; - register unsigned char cwr2, cycno2 = bi_ct2->cycno; - register unsigned int lg_pmps1 = bi_ct1->LG_PMPS; - register unsigned int lg_pmps2 = - bi_ct2->LG_PMPS; - register unsigned int t_rlps; - register unsigned char s_flag, is_lps = 0; - register unsigned int s2, t2; - - - bit1 = bi_ct1->MPS; - bit2 = bi_ct2->MPS; - - cwr1 = (cycno1 <= 1) ? 3 : (cycno1 == 2) ? 4 : 5; - cwr2 = (cycno2 <= 1) ? 3 : (cycno2 == 2) ? 4 : 5; - - if (bit1 == bit2) { - pred_mps = bit1; - lg_pmps = (lg_pmps1 + lg_pmps2) / 2; - } else { - if (lg_pmps1 < lg_pmps2) { - pred_mps = bit1; - lg_pmps = (256 << LG_PMPS_SHIFTNO) - 1 - - ((lg_pmps2 - lg_pmps1) >> 1); - } else { - pred_mps = bit2; - lg_pmps = (256 << LG_PMPS_SHIFTNO) - 1 - - ((lg_pmps1 - lg_pmps2) >> 1); - } - } - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & AEC_DUMP) - io_printf(" - Begin - LG_PMPS : %03X, MPS : %d\n", - lg_pmps, pred_mps); -#endif - if (t1 >= (lg_pmps >> LG_PMPS_SHIFTNO)) { - s2 = s1; - t2 = t1 - (lg_pmps >> LG_PMPS_SHIFTNO); - s_flag = 0; - } else { - s2 = s1 + 1; - t2 = 256 + t1 - (lg_pmps >> LG_PMPS_SHIFTNO); - s_flag = 1; - } - - bit = pred_mps; - if (s2 > value_s || (s2 == value_s && value_t >= t2)) { - is_lps = 1; - bit = !bit; - t_rlps = (s_flag == 0) ? - (lg_pmps >> LG_PMPS_SHIFTNO) : - (t1 + (lg_pmps >> LG_PMPS_SHIFTNO)); - - if (s2 == value_s) - value_t = (value_t - t2); - else { - if (--dbits_to_go < 0) - get_byte(); - - value_t = (value_t << 1) - | ((dbuffer >> dbits_to_go) & 0x01); - value_t = 256 + value_t - t2; - } - - while (t_rlps < QUARTER) { - t_rlps = t_rlps << 1; - if (--dbits_to_go < 0) - get_byte(); - - value_t = (value_t << 1) - | ((dbuffer >> dbits_to_go) & 0x01); - } - s1 = 0; - t1 = t_rlps & 0xff; - - value_s = 0; - while (value_t < QUARTER) { - int j; - - if (--dbits_to_go < 0) - get_byte(); - j = (dbuffer >> dbits_to_go) & 0x01; - - value_t = (value_t << 1) | j; - value_s++; - } - value_t = value_t & 0xff; - } else { - s1 = s2; - t1 = t2; - } - - if (bit != bit1) { - cycno1 = (cycno1 <= 2) ? (cycno1 + 1) : 3; - } else { - if (cycno1 == 0) - cycno1 = 1; - } - - if (bit != bit2) { - cycno2 = (cycno2 <= 2) ? (cycno2 + 1) : 3; - } else { - if (cycno2 == 0) - cycno2 = 1; - } - bi_ct1->cycno = cycno1; - bi_ct2->cycno = cycno2; - - { - - if (bit == bit1) { - lg_pmps1 = - lg_pmps1 - - (unsigned int)(lg_pmps1 - >> cwr1) - - (unsigned int)(lg_pmps1 - >> (cwr1 - + 2)); - } else { - switch (cwr1) { - case 3: - lg_pmps1 = lg_pmps1 + 197; - break; - case 4: - lg_pmps1 = lg_pmps1 + 95; - break; - default: - lg_pmps1 = lg_pmps1 + 46; - } - - if (lg_pmps1 >= (256 << LG_PMPS_SHIFTNO)) { - lg_pmps1 = (512 << LG_PMPS_SHIFTNO) - 1 - - lg_pmps1; - bi_ct1->MPS = !(bi_ct1->MPS); - } - } - bi_ct1->LG_PMPS = lg_pmps1; - - if (bit == bit2) { - lg_pmps2 = - lg_pmps2 - - (unsigned int)(lg_pmps2 - >> cwr2) - - (unsigned int)(lg_pmps2 - >> (cwr2 - + 2)); - } else { - switch (cwr2) { - case 3: - lg_pmps2 = lg_pmps2 + 197; - break; - case 4: - lg_pmps2 = lg_pmps2 + 95; - break; - default: - lg_pmps2 = lg_pmps2 + 46; - } - - if (lg_pmps2 >= (256 << LG_PMPS_SHIFTNO)) { - lg_pmps2 = (512 << LG_PMPS_SHIFTNO) - 1 - - lg_pmps2; - bi_ct2->MPS = !(bi_ct2->MPS); - } - } - bi_ct2->LG_PMPS = lg_pmps2; - } - - - return bit; -} - -/*! - ************************************************************************ - * \brief - * biari_decode_symbol_eq_prob(): - * \return - * the decoded symbol - ************************************************************************ - */ -unsigned int biari_decode_symbol_eq_prob(struct decoding_environment_s *dep) -{ - unsigned char bit; - struct bi_context_type_s octx; - struct bi_context_type_s *ctx = &octx; - - ctx->LG_PMPS = (QUARTER << LG_PMPS_SHIFTNO) - 1; - ctx->MPS = 0; - ctx->cycno = 0xfe; - dec_bypass = 1; - bit = biari_decode_symbol(dep, ctx); - dec_bypass = 0; - return bit; -} - -unsigned int biari_decode_final(struct decoding_environment_s *dep) -{ - unsigned char bit; - struct bi_context_type_s octx; - struct bi_context_type_s *ctx = &octx; - - ctx->LG_PMPS = 1 << LG_PMPS_SHIFTNO; - ctx->MPS = 0; - ctx->cycno = 0xff; - dec_final = 1; - bit = biari_decode_symbol(dep, ctx); - dec_final = 0; - return bit; -} - -int i_8(char *tracestring) -{ - int frame_bitoffset = curr_stream->frame_bitoffset; - unsigned char *buf = curr_stream->stream_buffer; - int bitstreamlengthinbytes = curr_stream->bitstream_length; - struct syntaxelement symbol, *sym = &symbol; -#ifdef AVSP_LONG_CABAC -#else - assert(curr_stream->stream_buffer != NULL); -#endif - - sym->len = 8; - sym->type = SE_HEADER; - sym->mapping = linfo_ue; - - if ((get_bits(buf, frame_bitoffset, &(sym->inf), bitstreamlengthinbytes, - sym->len)) < 0) - return -1; - curr_stream->frame_bitoffset += sym->len; - sym->value1 = sym->inf; - if (sym->inf & 0x80) - sym->inf = -(~((int)0xffffff00 | sym->inf) + 1); -#if TRACE - tracebits2(sym->tracestring, sym->len, sym->inf); -#endif - return sym->inf; -} - -/*! - ************************************************************************ - * \brief - * arideco_bits_read - ************************************************************************ - */ -int arideco_bits_read(struct decoding_environment_s *dep) -{ - - return 8 * ((*dcodestrm_len) - 1) + (8 - dbits_to_go); -} - -/*! - ************************************************************************ - * \brief - * arithmetic decoding - ************************************************************************ - */ -int read_syntaxelement_aec(struct syntaxelement *se, struct img_par *img, - struct datapartition *this_data_part) -{ - int curr_len; - struct decoding_environment_s *dep_dp = &(this_data_part->de_aec); - - curr_len = arideco_bits_read(dep_dp); - - se->reading(se, img, dep_dp); - - se->len = (arideco_bits_read(dep_dp) - curr_len); - return se->len; -} - -/*! - ************************************************************************ - * \brief - * This function is used to arithmetically decode the - * run length info of the skip mb - ************************************************************************ - */ -void readrunlenghtfrombuffer_aec(struct syntaxelement *se, struct img_par *img, - struct decoding_environment_s *dep_dp) -{ - struct bi_context_type_s *pctx; - int ctx, symbol; - - pctx = img->current_slice->tex_ctx->one_contexts[0]; - symbol = 0; - ctx = 0; - while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) { - symbol += 1; - ctx++; - if (ctx >= 3) - ctx = 3; - } - se->value1 = symbol; -#if TRACE - fprintf(p_trace, "@%d%s\t\t\t%d\n", - symbol_count++, se->tracestring, se->value1); - fflush(p_trace); -#endif -} - -/*! - ************************************************************************ - * \brief - * This function is used to arithmetically decode a pair of - * intra prediction modes of a given MB. - ************************************************************************ - */ -int mapd_intrap[5] = {0, 2, 3, 4, 1}; -void read_intrapredmode_aec(struct syntaxelement *se, struct img_par *img, - struct decoding_environment_s *dep_dp) -{ - struct bi_context_type_s *pctx; - int ctx, symbol; - - pctx = img->current_slice->tex_ctx->one_contexts[1]; - symbol = 0; - ctx = 0; -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & AEC_DUMP) - io_printf(" -- read_intrapredmode_aec ctx : %d\n", ctx); -#endif - while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) { - symbol += 1; - ctx++; - if (ctx >= 3) - ctx = 3; -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & AEC_DUMP) - io_printf(" -- read_intrapredmode_aec ctx : %d\n", ctx); -#endif - if (symbol == 4) - break; - } - se->value1 = mapd_intrap[symbol] - 1; - -#if TRACE - fprintf(p_trace, "@%d %s\t\t\t%d\n", - symbol_count++, se->tracestring, se->value1); - fflush(p_trace); -#endif -} - -/*! - ************************************************************************ - * \brief - * decoding of unary binarization using one or 2 distinct - * models for the first and all remaining bins; no terminating - * "0" for max_symbol - *********************************************************************** - */ -unsigned int unary_bin_max_decode(struct decoding_environment_s *dep_dp, - struct bi_context_type_s *ctx, - int ctx_offset, unsigned int max_symbol) -{ - unsigned int l; - unsigned int symbol; - struct bi_context_type_s *ictx; - - symbol = biari_decode_symbol(dep_dp, ctx); - - if (symbol == 0) - return 0; - - if (max_symbol == 1) - return symbol; - symbol = 0; - ictx = ctx + ctx_offset; - do { - l = biari_decode_symbol(dep_dp, ictx); - symbol++; - } while ((l != 0) && (symbol < max_symbol - 1)); - if ((l != 0) && (symbol == max_symbol - 1)) - symbol++; - return symbol; -} - -/*! - ************************************************************************ - * \brief - * decoding of unary binarization using one or 2 distinct - * models for the first and all remaining bins - *********************************************************************** - */ -unsigned int unary_bin_decode(struct decoding_environment_s *dep_dp, - struct bi_context_type_s *ctx, int ctx_offset) -{ - unsigned int l; - unsigned int symbol; - struct bi_context_type_s *ictx; - - symbol = 1 - biari_decode_symbol(dep_dp, ctx); - - if (symbol == 0) - return 0; - symbol = 0; - ictx = ctx + ctx_offset; - do { - l = 1 - biari_decode_symbol(dep_dp, ictx); - symbol++; - } while (l != 0); - return symbol; -} - -/*! - ************************************************************************ - * \brief - * This function is used to arithmetically decode the chroma - * intra prediction mode of a given MB. - ************************************************************************ - */ -void read_cipredmode_aec(struct syntaxelement *se, - struct img_par *img, - struct decoding_environment_s *dep_dp) -{ - struct texture_info_contexts *ctx = img->current_slice->tex_ctx; - struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; - int act_ctx, a, b; - int act_sym = se->value1; - - if (curr_mb->mb_available_up == NULL) - b = 0; - else { - /*if ( (curr_mb->mb_available_up)->mb_type==IPCM) - * b=0; - * else - */ - b = (((curr_mb->mb_available_up)->c_ipred_mode != 0) ? 1 : 0); - } - - if (curr_mb->mb_available_left == NULL) - a = 0; - else { - /* if ( (curr_mb->mb_available_left)->mb_type==IPCM) - * a=0; - * else - */ - a = (((curr_mb->mb_available_left)->c_ipred_mode != 0) ? 1 : 0); - } - - act_ctx = a + b; - - - act_sym = biari_decode_symbol(dep_dp, ctx->cipr_contexts + act_ctx); - - if (act_sym != 0) - act_sym = unary_bin_max_decode(dep_dp, ctx->cipr_contexts + 3, - 0, 2) + 1; - - se->value1 = act_sym; - -#if TRACE - fprintf(p_trace, "@%d %s\t\t%d\n", - symbol_count++, se->tracestring, se->value1); - fflush(p_trace); -#endif - -} - -int slice_header(char *buf, int startcodepos, int length) -{ - int i; - - int weight_para_num = 0; - int mb_row; - int mb_column; - int mb_index; - int mb_width, mb_height; - - mb_column = 0; - - memcpy(curr_stream->stream_buffer, buf, length); - curr_stream->code_len = curr_stream->bitstream_length = length; - - curr_stream->read_len = - curr_stream->frame_bitoffset = (startcodepos) * 8; - slice_vertical_position = u_v(8, "slice vertical position"); - - push_es(slice_vertical_position, 8); - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & SLICE_INFO_DUMP) - io_printf(" * 8-bits slice_vertical_position : %d\n", - slice_vertical_position); -#endif - - if (vertical_size > 2800) { - slice_vertical_position_extension = u_v(3, - "slice vertical position extension"); - push_es(slice_vertical_position_extension, 3); - - } - - if (vertical_size > 2800) - mb_row = (slice_vertical_position_extension << 7) - + slice_vertical_position; - else - mb_row = slice_vertical_position; - - mb_width = (horizontal_size + 15) / 16; - if (!progressive_sequence) - mb_height = 2 * ((vertical_size + 31) / 32); - else - mb_height = (vertical_size + 15) / 16; - - - mb_index = mb_row * mb_width + mb_column; - - if (!img->picture_structure && img->type == I_IMG - && (mb_index >= mb_width * mb_height / 2)) { - second_ifield = 1; - img->type = P_IMG; - pre_img_type = P_IMG; - } - - { - if (!fixed_picture_qp) { - fixed_slice_qp = u_v(1, "fixed_slice_qp"); - push_es(fixed_slice_qp, 1); -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & SLICE_INFO_DUMP) - io_printf(" * 1-bit fixed_slice_qp : %d\n", - fixed_slice_qp); -#endif - slice_qp = u_v(6, "slice_qp"); - push_es(slice_qp, 6); -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & SLICE_INFO_DUMP) - io_printf(" * 6-bits slice_qp : %d\n", - slice_qp); -#endif - - img->qp = slice_qp; - } - - if (img->type != I_IMG) { - img->slice_weighting_flag = u_v(1, - "slice weighting flag"); - - if (img->slice_weighting_flag) { - - if (second_ifield && !img->picture_structure) - weight_para_num = 1; - else if (img->type == P_IMG - && img->picture_structure) - weight_para_num = 2; - else if (img->type == P_IMG - && !img->picture_structure) - weight_para_num = 4; - else if (img->type == B_IMG - && img->picture_structure) - weight_para_num = 2; - else if (img->type == B_IMG - && !img->picture_structure) - weight_para_num = 4; - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & SLICE_INFO_DUMP) - io_printf(" - weight_para_num : %d\n", - weight_para_num); -#endif - for (i = 0; i < weight_para_num; i++) { - img->lum_scale[i] = u_v(8, - "luma scale"); - - img->lum_shift[i] = i_8("luma shift"); - - marker_bit = u_1("insert bit"); - - - { - img->chroma_scale[i] = u_v(8, - "chroma scale"); - - img->chroma_shift[i] = i_8( - "chroma shift"); - - marker_bit = u_1("insert bit"); - - } - } - img->mb_weighting_flag = u_v(1, - "MB weighting flag"); - - } - } - } - - -#if 1 - return mb_index; -#endif -} - -void no_mem_exit(char *where) -{ - io_printf("%s\r\n", where); -} - -unsigned char bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; - -struct inputstream_s { - /*FILE *f;*/ - unsigned char buf[SVA_STREAM_BUF_SIZE]; - unsigned int uclear_bits; - unsigned int upre_3bytes; - int ibyte_position; - int ibuf_bytesnum; - int iclear_bitsnum; - int istuff_bitsnum; - int ibits_count; -}; - -struct inputstream_s IRABS; -struct inputstream_s *p_irabs = &IRABS; - -struct stat_bits { - int curr_frame_bits; - int prev_frame_bits; - int emulate_bits; - int prev_emulate_bits; - int last_unit_bits; - int bitrate; - int total_bitrate[1000]; - int coded_pic_num; - int time_s; -}; - -struct stat_bits *stat_bits_ptr; - -unsigned char *temp_slice_buf; -int start_codeposition; -int first_slice_length; -int first_slice_startpos; - -int bitstream_buf_used; -int startcode_offset; - -int bitstream_read_ptr; - -int demulate_enable; - -int last_dquant; - -int total_mb_count; - -int current_mb_skip; - -int skip_mode_flag; - -int current_mb_intra; - -/* - ************************************************************************* - * Function: Check start code's type - * Input: - * Output: - * Return: - * Author: XZHENG, 20080515 - ************************************************************************* - */ -void check_type(int startcode) -{ - startcode = startcode & 0x000000ff; - switch (startcode) { - case 0xb0: - case 0xb2: - case 0xb5: - demulate_enable = 0; - break; - default: - demulate_enable = 1; - break; - } - -} -/* - ************************************************************************* - * Function: - * Input: - * Output: - * Return: 0 : OK - -1 : arrive at stream end - -2 : meet another start code - * Attention: - ************************************************************************* - */ -int clear_nextbyte(struct inputstream_s *p) -{ - int i, k, j; - unsigned char temp[3]; - - i = p->ibyte_position; - k = p->ibuf_bytesnum - i; - if (k < 3) { - for (j = 0; j < k; j++) - temp[j] = p->buf[i + j]; - - p->ibuf_bytesnum = read_bitstream(p->buf + k, - SVA_STREAM_BUF_SIZE - k); - bitstream_buf_used++; - if (p->ibuf_bytesnum == 0) { - if (k > 0) { - while (k > 0) { - p->upre_3bytes = ((p->upre_3bytes << 8) - | p->buf[i]) - & 0x00ffffff; - if (p->upre_3bytes < 4 - && demulate_enable) { - p->uclear_bits = - (p->uclear_bits - << 6) - | (p->buf[i] - >> 2); - p->iclear_bitsnum += 6; - stat_bits_ptr->emulate_bits - += 2; - } else { - p->uclear_bits = (p->uclear_bits - << 8) - | p->buf[i]; - p->iclear_bitsnum += 8; - } - p->ibyte_position++; - k--; - i++; - } - return 0; - } else { - return -1; - } - } else { - for (j = 0; j < k; j++) - p->buf[j] = temp[j]; - p->ibuf_bytesnum += k; - i = p->ibyte_position = 0; - } - } - if (p->buf[i] == 0 && p->buf[i + 1] == 0 && p->buf[i + 2] == 1) - return -2; - p->upre_3bytes = ((p->upre_3bytes << 8) | p->buf[i]) & 0x00ffffff; - if (p->upre_3bytes < 4 && demulate_enable) { - p->uclear_bits = (p->uclear_bits << 6) | (p->buf[i] >> 2); - p->iclear_bitsnum += 6; - stat_bits_ptr->emulate_bits += 2; - } else { - p->uclear_bits = (p->uclear_bits << 8) | p->buf[i]; - p->iclear_bitsnum += 8; - } - p->ibyte_position++; - return 0; -} - -/* - ************************************************************************* - * Function: - * Input: - * Output: - * Return: 0 : OK - -1 : arrive at stream end - -2 : meet another start code - * Attention: - ************************************************************************* - */ -int read_n_bit(struct inputstream_s *p, int n, int *v) -{ - int r; - unsigned int t; - - while (n > p->iclear_bitsnum) { - r = clear_nextbyte(p); - if (r) { - if (r == -1) { - if (p->ibuf_bytesnum - p->ibyte_position > 0) - break; - } - return r; - } - } - t = p->uclear_bits; - r = 32 - p->iclear_bitsnum; - *v = (t << r) >> (32 - n); - p->iclear_bitsnum -= n; - return 0; -} - -#ifdef AVSP_LONG_CABAC -unsigned char TMP_BUF[2 * SVA_STREAM_BUF_SIZE]; -int tmp_buf_wr_ptr; -int tmp_buf_rd_ptr; -int tmp_buf_count; -#endif -void open_irabs(struct inputstream_s *p) -{ - p->uclear_bits = 0xffffffff; - p->ibyte_position = 0; - p->ibuf_bytesnum = 0; - p->iclear_bitsnum = 0; - p->istuff_bitsnum = 0; - p->ibits_count = 0; - p->upre_3bytes = 0; - - bitstream_buf_used = 0; - bitstream_read_ptr = (src_start - 16) & 0xfffffff0; - -#ifdef AVSP_LONG_CABAC - tmp_buf_count = 0; - tmp_buf_wr_ptr = 0; - tmp_buf_rd_ptr = 0; -#endif - -} - -void move_bitstream(unsigned int move_from_addr, unsigned int move_to_addr, - int move_size) -{ - int move_bytes_left = move_size; - unsigned int move_read_addr; - unsigned int move_write_addr = move_to_addr; - - int move_byte; - unsigned int data32; - - while (move_from_addr > vld_mem_end_addr) { - move_from_addr = move_from_addr + vld_mem_start_addr - - vld_mem_end_addr - 8; - } - move_read_addr = move_from_addr; - while (move_bytes_left > 0) { - move_byte = move_bytes_left; - if (move_byte > 512) - move_byte = 512; - if ((move_read_addr + move_byte) > vld_mem_end_addr) - move_byte = (vld_mem_end_addr + 8) - move_read_addr; - - WRITE_VREG(LMEM_DMA_ADR, move_read_addr); - WRITE_VREG(LMEM_DMA_COUNT, move_byte / 2); - WRITE_VREG(LMEM_DMA_CTRL, 0xc200); - - data32 = 0x8000; - while (data32 & 0x8000) - data32 = READ_VREG(LMEM_DMA_CTRL); - - WRITE_VREG(LMEM_DMA_ADR, move_write_addr); - WRITE_VREG(LMEM_DMA_COUNT, move_byte / 2); - WRITE_VREG(LMEM_DMA_CTRL, 0x8200); - - data32 = 0x8000; - while (data32 & 0x8000) - data32 = READ_VREG(LMEM_DMA_CTRL); - - data32 = 0x0fff; - while (data32 & 0x0fff) - data32 = READ_VREG(WRRSP_LMEM); - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & STREAM_INFO_DUMP) - io_printf(" 2 MOVE %d Bytes from 0x%x to 0x%x\n", - move_byte, move_read_addr, move_write_addr); -#endif - - move_read_addr = move_read_addr + move_byte; - if (move_read_addr > vld_mem_end_addr) - move_read_addr = vld_mem_start_addr; - move_write_addr = move_write_addr + move_byte; - move_bytes_left = move_bytes_left - move_byte; - } - -} - -int read_bitstream(unsigned char *buf, int size) -{ - int i; - -#ifdef AVSP_LONG_CABAC - - unsigned int *TMP_BUF_32 = (unsigned int *)bitstream_read_tmp; - - if (tmp_buf_count < size) { - dma_sync_single_for_cpu(amports_get_dma_device(), - bitstream_read_tmp_phy, SVA_STREAM_BUF_SIZE, - DMA_FROM_DEVICE); - - move_bitstream(bitstream_read_ptr, bitstream_read_tmp_phy, - SVA_STREAM_BUF_SIZE); - - for (i = 0; i < SVA_STREAM_BUF_SIZE / 8; i++) { - TMP_BUF[tmp_buf_wr_ptr++] = - (TMP_BUF_32[2 * i + 1] >> 24) & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = - (TMP_BUF_32[2 * i + 1] >> 16) & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 1] >> 8) - & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 1] >> 0) - & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = - (TMP_BUF_32[2 * i + 0] >> 24) & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = - (TMP_BUF_32[2 * i + 0] >> 16) & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 0] >> 8) - & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 0] >> 0) - & 0xff; - if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_wr_ptr = 0; - } - tmp_buf_count = tmp_buf_count + SVA_STREAM_BUF_SIZE; - bitstream_read_ptr = bitstream_read_ptr + SVA_STREAM_BUF_SIZE; - } - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & STREAM_INFO_DUMP) - io_printf(" Read %d bytes from %d, size left : %d\n", - size, tmp_buf_rd_ptr, tmp_buf_count); -#endif - for (i = 0; i < size; i++) { - buf[i] = TMP_BUF[tmp_buf_rd_ptr++]; - if (tmp_buf_rd_ptr >= (2 * SVA_STREAM_BUF_SIZE)) - tmp_buf_rd_ptr = 0; - } - tmp_buf_count = tmp_buf_count - size; - -#else - for (i = 0; i < size; i++) - buf[i] = tmp_stream[bitstream_read_ptr + i]; - bitstream_read_ptr = bitstream_read_ptr + size; -#endif - - return size; -} - -int next_startcode(struct inputstream_s *p) -{ - int i, m; - unsigned char a = 0, b = 0; - - m = 0; - - while (1) { - if (p->ibyte_position >= p->ibuf_bytesnum - 2) { - m = p->ibuf_bytesnum - p->ibyte_position; - if (m < 0) - return -2; - if (m == 1) - b = p->buf[p->ibyte_position + 1]; - if (m == 2) { - b = p->buf[p->ibyte_position + 1]; - a = p->buf[p->ibyte_position]; - } - p->ibuf_bytesnum = read_bitstream(p->buf, - SVA_STREAM_BUF_SIZE); - p->ibyte_position = 0; - bitstream_buf_used++; - } - - if (p->ibuf_bytesnum + m < 3) - return -1; - - if (m == 1 && b == 0 && p->buf[0] == 0 && p->buf[1] == 1) { - p->ibyte_position = 2; - p->iclear_bitsnum = 0; - p->istuff_bitsnum = 0; - p->ibits_count += 24; - p->upre_3bytes = 1; - return 0; - } - - if (m == 2 && b == 0 && a == 0 && p->buf[0] == 1) { - p->ibyte_position = 1; - p->iclear_bitsnum = 0; - p->istuff_bitsnum = 0; - p->ibits_count += 24; - p->upre_3bytes = 1; - return 0; - } - - if (m == 2 && b == 0 && p->buf[0] == 0 && p->buf[1] == 1) { - p->ibyte_position = 2; - p->iclear_bitsnum = 0; - p->istuff_bitsnum = 0; - p->ibits_count += 24; - p->upre_3bytes = 1; - return 0; - } - - for (i = p->ibyte_position; i < p->ibuf_bytesnum - 2; i++) { - if (p->buf[i] == 0 && p->buf[i + 1] == 0 - && p->buf[i + 2] == 1) { - p->ibyte_position = i + 3; - p->iclear_bitsnum = 0; - p->istuff_bitsnum = 0; - p->ibits_count += 24; - p->upre_3bytes = 1; - return 0; - } - p->ibits_count += 8; - } - p->ibyte_position = i; - } -} - -int get_oneunit(char *buf, int *startcodepos, int *length) -{ - int i, j, k; - - i = next_startcode(p_irabs); - - if (i != 0) { - if (i == -1) - io_printf( - "\narrive at stream end and start code is not found!"); - if (i == -2) - io_printf("\np->ibyte_position error!"); - - } - startcode_offset = - p_irabs->ibyte_position - - 3 + (bitstream_buf_used-1) - * SVA_STREAM_BUF_SIZE; - buf[0] = 0; - buf[1] = 0; - buf[2] = 1; - *startcodepos = 3; - i = read_n_bit(p_irabs, 8, &j); - buf[3] = (char)j; - - check_type(buf[3]); - if (buf[3] == SEQUENCE_END_CODE) { - *length = 4; - return -1; - } - k = 4; - while (1) { - i = read_n_bit(p_irabs, 8, &j); - if (i < 0) - break; - buf[k++] = (char)j; - if (k >= (MAX_CODED_FRAME_SIZE - 1)) - break; - } - if (p_irabs->iclear_bitsnum > 0) { - int shift; - - shift = 8 - p_irabs->iclear_bitsnum; - i = read_n_bit(p_irabs, p_irabs->iclear_bitsnum, &j); - - if (j != 0) - buf[k++] = (char)(j << shift); - stat_bits_ptr->last_unit_bits += shift; - } - *length = k; - return k; -} - -/*unsigned char tmp_buf[MAX_CODED_FRAME_SIZE] __attribute__ ((aligned(64)));*/ -/*unsigned char tmp_buf[MAX_CODED_FRAME_SIZE] __aligned(64);*/ -int header(void) -{ - unsigned char *buf; - int startcodepos, length; - - unsigned char *tmp_buf; - - tmp_buf = (unsigned char *)avsp_heap_adr; - - buf = &tmp_buf[0]; - while (1) { - start_codeposition = get_oneunit(buf, &startcodepos, &length); - - switch (buf[startcodepos]) { - case SEQUENCE_HEADER_CODE: - io_printf( - "# SEQUENCE_HEADER_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - case EXTENSION_START_CODE: - io_printf( - "# EXTENSION_START_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - case USER_DATA_START_CODE: - io_printf( - "# USER_DATA_START_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - case VIDEO_EDIT_CODE: - io_printf( - "# VIDEO_EDIT_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - case I_PICTURE_START_CODE: - io_printf( - "# I_PICTURE_START_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - case PB_PICTURE_START_CODE: - io_printf( - "# PB_PICTURE_START_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - case SEQUENCE_END_CODE: - io_printf( - "# SEQUENCE_END_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); - break; - default: - io_printf( - "# SLICE_START_CODE (0x%02x) found at offset %d (0x%x)\n", - buf[startcodepos], startcode_offset, - startcode_offset); -#if 0 - io_printf("VLD_MEM_VIFIFO_START_PTR %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_START_PTR)); - io_printf("VLD_MEM_VIFIFO_CURR_PTR %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR)); - io_printf("VLD_MEM_VIFIFO_END_PTR %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_END_PTR)); - io_printf("VLD_MEM_VIFIFO_WP %x\r\n" - READ_VREG(VLD_MEM_VIFIFO_WP)); - io_printf("VLD_MEM_VIFIFO_RP %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_RP)); - io_printf("VLD_MEM_VBUF_RD_PTR %x\r\n" - READ_VREG(VLD_MEM_VBUF_RD_PTR)); - io_printf("VLD_MEM_VIFIFO_BUF_CNTL %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL)); - io_printf("PARSER_VIDEO_HOLE %x\r\n", - READ_MPEG_REG(PARSER_VIDEO_HOLE)); -#endif - if ((buf[startcodepos] >= SLICE_START_CODE_MIN - && buf[startcodepos] - <= SLICE_START_CODE_MAX) - && ((!img->seq_header_indicate) - || (img->type == B_IMG - && img->b_discard_flag - == 1 - && !img->no_forward_reference))) { - break; - } else if (buf[startcodepos] >= SLICE_START_CODE_MIN) { - - first_slice_length = length; - first_slice_startpos = startcodepos; - - temp_slice_buf = &tmp_buf[0]; - return SOP; - } else { - io_printf("Can't find start code"); - return -EOS; - } - } - } - -} - -/* - ************************************************************************* - * Function:Allocates a Bitstream - * Input: - * Output:allocated Bitstream point - * Return: - * Attention: - ************************************************************************* - */ -struct bitstream_s *alloc_bitstream(void) -{ - struct bitstream_s *bitstream; - - bitstream = (struct bitstream_s *)local_alloc(1, - sizeof(struct bitstream_s)); - if (bitstream == NULL) { - io_printf( - "AllocBitstream: Memory allocation for Bitstream failed"); - return NULL; - } - bitstream->stream_buffer = (unsigned char *)local_alloc( - MAX_CODED_FRAME_SIZE, - sizeof(unsigned char)); - if (bitstream->stream_buffer == NULL) { - io_printf( - "AllocBitstream: Memory allocation for streamBuffer failed"); - return NULL; - } - - return bitstream; -} - -void biari_init_context_logac(struct bi_context_type_s *ctx) -{ - ctx->LG_PMPS = (QUARTER << LG_PMPS_SHIFTNO) - 1; - ctx->MPS = 0; - ctx->cycno = 0; -} - -#define BIARI_CTX_INIT1_LOG(jj, ctx)\ -{\ - for (j = 0; j < jj; j++)\ - biari_init_context_logac(&(ctx[j]));\ -} - -#define BIARI_CTX_INIT2_LOG(ii, jj, ctx)\ -{\ - for (i = 0; i < ii; i++)\ - for (j = 0; j < jj; j++)\ - biari_init_context_logac(&(ctx[i][j]));\ -} - -#define BIARI_CTX_INIT3_LOG(ii, jj, kk, ctx)\ -{\ - for (i = 0; i < ii; i++)\ - for (j = 0; j < jj; j++)\ - for (k = 0; k < kk; k++)\ - biari_init_context_logac(&(ctx[i][j][k]));\ -} - -#define BIARI_CTX_INIT4_LOG(ii, jj, kk, ll, ctx)\ -{\ - for (i = 0; i < ii; i++)\ - for (j = 0; j < jj; j++)\ - for (k = 0; k < kk; k++)\ - for (l = 0; l < ll; l++)\ - biari_init_context_logac\ - (&(ctx[i][j][k][l]));\ -} - -void init_contexts(struct img_par *img) -{ - struct motion_info_contexts_s *mc = img->current_slice->mot_ctx; - struct texture_info_contexts *tc = img->current_slice->tex_ctx; - int i, j; - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & SLICE_INFO_DUMP) - io_printf(" ---- init_contexts ----\n"); -#endif - - BIARI_CTX_INIT2_LOG(3, NUM_MB_TYPE_CTX, mc->mb_type_contexts); - BIARI_CTX_INIT2_LOG(2, NUM_B8_TYPE_CTX, mc->b8_type_contexts); - BIARI_CTX_INIT2_LOG(2, NUM_MV_RES_CTX, mc->mv_res_contexts); - BIARI_CTX_INIT2_LOG(2, NUM_REF_NO_CTX, mc->ref_no_contexts); - BIARI_CTX_INIT1_LOG(NUM_DELTA_QP_CTX, mc->delta_qp_contexts); - BIARI_CTX_INIT1_LOG(NUM_MB_AFF_CTX, mc->mb_aff_contexts); - - BIARI_CTX_INIT1_LOG(NUM_IPR_CTX, tc->ipr_contexts); - BIARI_CTX_INIT1_LOG(NUM_CIPR_CTX, tc->cipr_contexts); - BIARI_CTX_INIT2_LOG(3, NUM_CBP_CTX, tc->cbp_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_BCBP_CTX, tc->bcbp_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_ONE_CTX, tc->one_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_ABS_CTX, tc->abs_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_MAP_CTX, tc->fld_map_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_LAST_CTX, - tc->fld_last_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_MAP_CTX, tc->map_contexts); - BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_LAST_CTX, tc->last_contexts); -#ifdef TEST_WEIGHTING_AEC - biari_init_context_logac(&mc->mb_weighting_pred); -#endif -} - -/*! - ************************************************************************ - * \brief - * Allocation of contexts models for the motion info - * used for arithmetic decoding - * - ************************************************************************ - */ -struct motion_info_contexts_s *create_contexts_motioninfo(void) -{ - struct motion_info_contexts_s *deco_ctx; - - deco_ctx = (struct motion_info_contexts_s *)local_alloc(1, - sizeof(struct motion_info_contexts_s)); - if (deco_ctx == NULL) - no_mem_exit("create_contexts_motioninfo: deco_ctx"); - - return deco_ctx; -} - -/*! - ************************************************************************ - * \brief - * Allocates of contexts models for the texture info - * used for arithmetic decoding - ************************************************************************ - */ -struct texture_info_contexts *create_contexts_textureinfo(void) -{ - struct texture_info_contexts *deco_ctx; - - deco_ctx = (struct texture_info_contexts *)local_alloc(1, - sizeof(struct texture_info_contexts)); - if (deco_ctx == NULL) - no_mem_exit("create_contexts_textureinfo: deco_ctx"); - - return deco_ctx; -} - -struct datapartition *alloc_partition(int n) -{ - struct datapartition *part_arr, *datapart; - int i; - - part_arr = - (struct datapartition *)local_alloc(n, sizeof(struct datapartition)); - if (part_arr == NULL) { - no_mem_exit( - "alloc_partition: Memory allocation for Data Partition failed"); - return NULL; - } - -#if LIWR_FIX - part_arr[0].bitstream = NULL; -#else - for (i = 0; i < n; i++) { - datapart = &(part_arr[i]); - datapart->bitstream = (struct bitstream_s *)local_alloc(1, - sizeof(struct bitstream_s)); - if (datapart->bitstream == NULL) { - no_mem_exit( - "alloc_partition: Memory allocation for Bitstream failed"); - return NULL; - } - } -#endif - return part_arr; -} - -int malloc_slice(struct img_par *img) -{ - struct slice_s *currslice; - - img->current_slice = - (struct slice_s *)local_alloc(1, sizeof(struct slice_s)); - currslice = img->current_slice; - if (currslice == NULL) { - no_mem_exit( - "Memory allocation for struct slice_s datastruct Failed" - ); - return 0; - } - if (1) { - - currslice->mot_ctx = create_contexts_motioninfo(); - if (currslice->mot_ctx == NULL) - return 0; - - currslice->tex_ctx = create_contexts_textureinfo(); - if (currslice->tex_ctx == NULL) - return 0; - } -#if LIWR_FIX - currslice->max_part_nr = 1; -#else - currslice->max_part_nr = 3; -#endif - currslice->part_arr = alloc_partition(currslice->max_part_nr); - if (currslice->part_arr == NULL) - return 0; - return 1; -} - -void init(struct img_par *img) -{ - int i; - - for (i = 0; i < 256; i++) - img->quad[i] = i * i; -} - -/* - ************************************************************************* - * Function:Allocate 2D memory array -> int array2D[rows][columns] - * Input: - * Output: memory size in bytes - * Return: - * Attention: - ************************************************************************* - */ - -int get_mem2Dint(int ***array2D, int rows, int columns) -{ - int i; - - *array2D = (int **)local_alloc(rows, sizeof(int *)); - if (*array2D == NULL) { - no_mem_exit("get_mem2Dint: array2D"); - return -1; - } - (*array2D)[0] = (int *)local_alloc(rows * columns, sizeof(int)); - if ((*array2D)[0] == NULL) { - no_mem_exit("get_mem2Dint: array2D"); - return -1; - } - - for (i = 1; i < rows; i++) - (*array2D)[i] = (*array2D)[i - 1] + columns; - - return rows * columns * sizeof(int); -} - -int initial_decode(void) -{ - int i, j; - int ret; - int img_height = (vertical_size + img->auto_crop_bottom); - int memory_size = 0; - - ret = malloc_slice(img); - if (ret == 0) - return 0; - - mb_data = (struct macroblock *)local_alloc( - (img->width / MB_BLOCK_SIZE) - * (img_height /*vertical_size*/ - / MB_BLOCK_SIZE), sizeof(struct macroblock)); - if (mb_data == NULL) { - no_mem_exit("init_global_buffers: mb_data"); - return 0; - } - - if (progressive_sequence) { - int size; - size = get_mem2Dint(&(img->ipredmode), - img->width / B8_SIZE * 2 + 4, - vertical_size / B8_SIZE * 2 + 4); - if (size == -1) - return 0; - - memory_size += size; - } else { - int size; - size = get_mem2Dint(&(img->ipredmode), - img->width / B8_SIZE * 2 + 4, - (vertical_size + 32) / (2 * B8_SIZE) * 4 + 4); - if (size == -1) - return 0; - - memory_size += size; - } - - for (i = 0; i < img->width / (B8_SIZE) * 2 + 4; i++) { - for (j = 0; j < img->height / (B8_SIZE) * 2 + 4; j++) - img->ipredmode[i][j] = -1; - } - - init(img); - img->number = 0; - img->type = I_IMG; - img->imgtr_last_p = 0; - img->imgtr_next_p = 0; - - img->new_seq_header_flag = 1; - img->new_sequence_flag = 1; - - return 1; -} - -void aec_new_slice(void) -{ - last_dquant = 0; -} - -/*! - ************************************************************************ - * \brief - * Initializes the DecodingEnvironment for the arithmetic coder - ************************************************************************ - */ - -void arideco_start_decoding(struct decoding_environment_s *dep, - unsigned char *cpixcode, - int firstbyte, int *cpixcode_len, int slice_type) -{ - - dcodestrm = cpixcode; - dcodestrm_len = cpixcode_len; - *dcodestrm_len = firstbyte; - - s1 = 0; - t1 = QUARTER - 1; - value_s = 0; - - value_t = 0; - - { - int i; - - dbits_to_go = 0; - for (i = 0; i < B_BITS - 1; i++) { - if (--dbits_to_go < 0) - get_byte(); - - value_t = (value_t << 1) - | ((dbuffer >> dbits_to_go) & 0x01); - } - } - - while (value_t < QUARTER) { - if (--dbits_to_go < 0) - get_byte(); - - value_t = (value_t << 1) | ((dbuffer >> dbits_to_go) & 0x01); - value_s++; - } - value_t = value_t & 0xff; - - dec_final = dec_bypass = 0; - - - -} - -/* - ************************************************************************* - * Function:Checks the availability of neighboring macroblocks of - the current macroblock for prediction and context determination; - marks the unavailable MBs for intra prediction in the - ipredmode-array by -1. Only neighboring MBs in the causal - past of the current MB are checked. - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void checkavailabilityofneighbors(struct img_par *img) -{ - int i, j; - const int mb_width = img->width / MB_BLOCK_SIZE; - const int mb_nr = img->current_mb_nr; - struct macroblock *curr_mb = &mb_data[mb_nr]; - int check_value; - int remove_prediction; - - curr_mb->mb_available_up = NULL; - curr_mb->mb_available_left = NULL; - - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - mb_data[mb_nr].mb_available[i][j] = NULL; - - mb_data[mb_nr].mb_available[1][1] = curr_mb; - - if (img->pix_x >= MB_BLOCK_SIZE) { - remove_prediction = curr_mb->slice_nr - != mb_data[mb_nr - 1].slice_nr; - - if (remove_prediction) - - { - - img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y - + 1) * 2] = -1; - img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y - + 1) * 2 + 1] = -1; - img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y - + 2) * 2] = -1; - img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y - + 2) * 2 + 1] = -1; - } - if (!remove_prediction) - curr_mb->mb_available[1][0] = &(mb_data[mb_nr - 1]); - - } - - check_value = (img->pix_y >= MB_BLOCK_SIZE); - if (check_value) { - remove_prediction = curr_mb->slice_nr - != mb_data[mb_nr - mb_width].slice_nr; - - if (remove_prediction) { - img->ipredmode - [(img->block_x + 1) * 2][(img->block_y + 1) - * 2 - 1] = -1; - img->ipredmode[(img->block_x + 1) * 2 + 1][(img->block_y - + 1) * 2 - 1] = -1; - img->ipredmode[(img->block_x + 1) * 2 + 2][(img->block_y - + 1) * 2 - 1] = -1; - img->ipredmode[(img->block_x + 1) * 2 + 3][(img->block_y - + 1) * 2 - 1] = -1; - } - - if (!remove_prediction) { - curr_mb->mb_available[0][1] = - &(mb_data[mb_nr - mb_width]); - } - } - - if (img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) { - remove_prediction = curr_mb->slice_nr - != mb_data[mb_nr - mb_width - 1].slice_nr; - - if (remove_prediction) { - img->ipredmode[img->block_x * 2 + 1][img->block_y * 2 - + 1] = -1; - } - if (!remove_prediction) { - curr_mb->mb_available[0][0] = &(mb_data[mb_nr - mb_width - - 1]); - } - } - - if (img->pix_y >= MB_BLOCK_SIZE - && img->pix_x < (img->width - MB_BLOCK_SIZE)) { - if (curr_mb->slice_nr == mb_data[mb_nr - mb_width + 1].slice_nr) - curr_mb->mb_available[0][2] = &(mb_data[mb_nr - mb_width - + 1]); - } - - if (1) { - curr_mb->mbaddr_a = mb_nr - 1; - curr_mb->mbaddr_b = mb_nr - img->pic_width_inmbs; - curr_mb->mbaddr_c = mb_nr - img->pic_width_inmbs + 1; - curr_mb->mbaddr_d = mb_nr - img->pic_width_inmbs - 1; - - curr_mb->mbavail_a = - (curr_mb->mb_available[1][0] != NULL) ? 1 : 0; - curr_mb->mbavail_b = - (curr_mb->mb_available[0][1] != NULL) ? 1 : 0; - curr_mb->mbavail_c = - (curr_mb->mb_available[0][2] != NULL) ? 1 : 0; - curr_mb->mbavail_d = - (curr_mb->mb_available[0][0] != NULL) ? 1 : 0; - - } - -} - -void checkavailabilityofneighborsaec(void) -{ - - int i, j; - const int mb_width = img->width / MB_BLOCK_SIZE; - const int mb_nr = img->current_mb_nr; - struct macroblock *curr_mb = &(mb_data[mb_nr]); - int check_value; - - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - mb_data[mb_nr].mb_available[i][j] = NULL; - mb_data[mb_nr].mb_available[1][1] = &(mb_data[mb_nr]); - - if (img->pix_x >= MB_BLOCK_SIZE) { - int remove_prediction = curr_mb->slice_nr - != mb_data[mb_nr - 1].slice_nr; - if (!remove_prediction) - curr_mb->mb_available[1][0] = &(mb_data[mb_nr - 1]); - } - - check_value = (img->pix_y >= MB_BLOCK_SIZE); - if (check_value) { - int remove_prediction = curr_mb->slice_nr - != mb_data[mb_nr - mb_width].slice_nr; - - if (!remove_prediction) { - curr_mb->mb_available[0][1] = - &(mb_data[mb_nr - mb_width]); - } - } - - if (img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) { - int remove_prediction = curr_mb->slice_nr - != mb_data[mb_nr - mb_width - 1].slice_nr; - if (!remove_prediction) { - curr_mb->mb_available[0][0] = &(mb_data[mb_nr - mb_width - - 1]); - } - } - - if (img->pix_y >= MB_BLOCK_SIZE - && img->pix_x < (img->width - MB_BLOCK_SIZE)) { - if (curr_mb->slice_nr == mb_data[mb_nr - mb_width + 1].slice_nr) - curr_mb->mb_available[0][2] = &(mb_data[mb_nr - mb_width - + 1]); - } - curr_mb->mb_available_left = curr_mb->mb_available[1][0]; - curr_mb->mb_available_up = curr_mb->mb_available[0][1]; - curr_mb->mbaddr_a = mb_nr - 1; - curr_mb->mbaddr_b = mb_nr - img->pic_width_inmbs; - curr_mb->mbaddr_c = mb_nr - img->pic_width_inmbs + 1; - curr_mb->mbaddr_d = mb_nr - img->pic_width_inmbs - 1; - - curr_mb->mbavail_a = (curr_mb->mb_available[1][0] != NULL) ? 1 : 0; - curr_mb->mbavail_b = (curr_mb->mb_available[0][1] != NULL) ? 1 : 0; - curr_mb->mbavail_c = (curr_mb->mb_available[0][2] != NULL) ? 1 : 0; - curr_mb->mbavail_d = (curr_mb->mb_available[0][0] != NULL) ? 1 : 0; -} - -/* - ************************************************************************* - * Function:initializes the current macroblock - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void start_macroblock(struct img_par *img) -{ - int i, j, k, l; - struct macroblock *curr_mb; - -#ifdef AVSP_LONG_CABAC -#else - -#endif - - curr_mb = &mb_data[img->current_mb_nr]; - - /* Update coordinates of the current macroblock */ - img->mb_x = (img->current_mb_nr) % (img->width / MB_BLOCK_SIZE); - img->mb_y = (img->current_mb_nr) / (img->width / MB_BLOCK_SIZE); - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & MB_NUM_DUMP) - io_printf(" #Begin MB : %d, (%x, %x) es_ptr %d\n", - img->current_mb_nr, img->mb_x, img->mb_y, es_ptr); -#endif - - - total_mb_count = total_mb_count + 1; - - /* Define vertical positions */ - img->block_y = img->mb_y * BLOCK_SIZE / 2; /* luma block position */ - img->block8_y = img->mb_y * BLOCK_SIZE / 2; - img->pix_y = img->mb_y * MB_BLOCK_SIZE; /* luma macroblock position */ - if (chroma_format == 2) - img->pix_c_y = img->mb_y * - MB_BLOCK_SIZE; /* chroma macroblock position */ - else - img->pix_c_y = img->mb_y * - MB_BLOCK_SIZE / 2; /* chroma macroblock position */ - - /* Define horizontal positions */ - img->block_x = img->mb_x * BLOCK_SIZE / 2; /* luma block position */ - img->block8_x = img->mb_x * BLOCK_SIZE / 2; - img->pix_x = img->mb_x * MB_BLOCK_SIZE; /* luma pixel position */ - img->pix_c_x = img->mb_x * - MB_BLOCK_SIZE / 2; /* chroma pixel position */ - - checkavailabilityofneighbors(img); - - /*qp = img->qp; - curr_mb->mb_type = 0; - curr_mb->delta_quant = 0; - curr_mb->cbp = 0; - curr_mb->cbp_blk = 0; - curr_mb->c_ipred_mode = DC_PRED_8; - curr_mb->c_ipred_mode_2 = DC_PRED_8; - - for (l = 0; l < 2; l++) - for (j = 0; j < BLOCK_MULTIPLE; j++) - for (i = 0; i < BLOCK_MULTIPLE; i++) - for (k = 0; k < 2; k++) - curr_mb->mvd[l][j][i][k] = 0; - - curr_mb->cbp_bits = 0; - - for (j = 0; j < MB_BLOCK_SIZE; j++) - for (i = 0; i < MB_BLOCK_SIZE; i++) - img->m7[i][j] = 0; - - for (j = 0; j < 2 * BLOCK_SIZE; j++) - for (i = 0; i < 2 * BLOCK_SIZE; i++) { - img->m8[0][i][j] = 0; - img->m8[1][i][j] = 0; - img->m8[2][i][j] = 0; - img->m8[3][i][j] = 0; - } - - curr_mb->lf_disable = 1; - - img->weighting_prediction = 0; -} - -/* - ************************************************************************* - * Function:init macroblock I and P frames - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void init_macroblock(struct img_par *img) -{ - int i, j; - - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - img->ipredmode[img->block_x * 2 + i + 2][img->block_y - * 2 + j + 2] = -1; - } - } - -} - -/* - ************************************************************************* - * Function:Interpret the mb mode for I-Frames - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void interpret_mb_mode_i(struct img_par *img) -{ - int i; - - struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; - int num = 4; - - curr_mb->mb_type = I8MB; - - - current_mb_intra = 1; - - for (i = 0; i < 4; i++) { - curr_mb->b8mode[i] = IBLOCK; - curr_mb->b8pdir[i] = -1; - } - - for (i = num; i < 4; i++) { - curr_mb->b8mode[i] = - curr_mb->mb_type_2 == P8x8 ? - 4 : curr_mb->mb_type_2; - curr_mb->b8pdir[i] = 0; - } -} - -const int pred_4x4[9][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, - 1, 1}, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {0, 0, 0, 3, 3, 3, 3, 3, 3}, - {0, 1, 4, 4, 4, 4, 4, 4, 4}, {0, 1, 5, 5, 5, 5, 5, 5, 5}, {0, 0, - 0, 0, 0, 0, 6, 0, 0}, - {0, 1, 7, 7, 7, 7, 7, 7, 7}, {0, 0, 0, 0, 4, 5, 6, 7, 8} - -}; - -const int pred_4x4to8x8[9] = {0, 1, 2, 3, 4, 1, 0, 1, 0 - -}; - -const int pred_8x8to4x4[5] = {0, 1, 2, 3, 4}; - -void read_ipred_block_modes(struct img_par *img, int b8) -{ - int bi, bj, dec; - struct syntaxelement curr_se; - struct macroblock *curr_mb; - int j2; - int mostprobableintrapredmode; - int upintrapredmode; - int uprightintrapredmode; - int leftintrapredmode; - int leftdownintrapredmode; - int intrachromapredmodeflag; - - struct slice_s *currslice = img->current_slice; - struct datapartition *dp; - - curr_mb = mb_data + img->current_mb_nr; - intrachromapredmodeflag = IS_INTRA(curr_mb); - - curr_se.type = SE_INTRAPREDMODE; -#if TRACE - strncpy(curr_se.tracestring, "Ipred Mode", TRACESTRING_SIZE); -#endif - - if (b8 < 4) { - if (curr_mb->b8mode[b8] == IBLOCK) { - intrachromapredmodeflag = 1; - - if (1) { - dp = &(currslice->part_arr[0]); - curr_se.reading = read_intrapredmode_aec; - dp->read_syntax_element(&curr_se, img, dp); - - if (curr_se.value1 == -1) - push_es(1, 1); - else - push_es(curr_se.value1, 3); - - - } - bi = img->block_x + (b8 & 1); - bj = img->block_y + (b8 / 2); - - upintrapredmode = img->ipredmode[(bi + 1) * 2][(bj) * 2 - + 1]; - uprightintrapredmode = - img->ipredmode[(bi + 1) * 2 + 1][(bj) - * 2 + 1]; - leftintrapredmode = - img->ipredmode[(bi) * 2 + 1][(bj + 1) - * 2]; - leftdownintrapredmode = img->ipredmode[(bi) * 2 + 1][(bj - + 1) * 2 + 1]; - - if ((upintrapredmode < 0) || (leftintrapredmode < 0)) { - mostprobableintrapredmode = DC_PRED; - } else if ((upintrapredmode < NO_INTRA_PMODE) - && (leftintrapredmode < - NO_INTRA_PMODE)) { - mostprobableintrapredmode = - upintrapredmode - < leftintrapredmode ? - upintrapredmode : - leftintrapredmode; - } else if (upintrapredmode < NO_INTRA_PMODE) { - mostprobableintrapredmode = upintrapredmode; - } else if (leftintrapredmode < NO_INTRA_PMODE) { - mostprobableintrapredmode = leftintrapredmode; - } else { - mostprobableintrapredmode = - pred_4x4[leftintrapredmode - - INTRA_PMODE_4x4][upintrapredmode - - INTRA_PMODE_4x4]; - mostprobableintrapredmode = - pred_4x4to8x8[mostprobableintrapredmode]; - } - - - - dec = - (curr_se.value1 == -1) ? - mostprobableintrapredmode : - curr_se.value1 - + (curr_se.value1 - >= mostprobableintrapredmode); - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & MB_INFO_DUMP) - io_printf(" - ipredmode[%d] : %d\n", b8, dec); -#endif - - img->ipredmode[(1 + bi) * 2][(1 + bj) * 2] = dec; - img->ipredmode[(1 + bi) * 2 + 1][(1 + bj) * 2] = dec; - img->ipredmode[(1 + bi) * 2][(1 + bj) * 2 + 1] = dec; - img->ipredmode[(1 + bi) * 2 + 1][(1 + bj) * 2 + 1] = - dec; - - j2 = bj; - } - } else if (b8 == 4 && curr_mb->b8mode[b8 - 3] == IBLOCK) { - - curr_se.type = SE_INTRAPREDMODE; -#if TRACE - strncpy(curr_se.tracestring, - "Chroma intra pred mode", TRACESTRING_SIZE); -#endif - - if (1) { - dp = &(currslice->part_arr[0]); - curr_se.reading = read_cipredmode_aec; - dp->read_syntax_element(&curr_se, img, dp); - } else - - { - } - curr_mb->c_ipred_mode = curr_se.value1; - - push_es(UE[curr_se.value1][0], UE[curr_se.value1][1]); - -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & MB_INFO_DUMP) - io_printf(" * UE c_ipred_mode read : %d\n", - curr_mb->c_ipred_mode); -#endif - - if (curr_se.value1 < DC_PRED_8 || curr_se.value1 > PLANE_8) { -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & MB_INFO_DUMP) - io_printf("%d\n", img->current_mb_nr); -#endif - pr_info("illegal chroma intra pred mode!\n"); - } - } -} - -/*! - ************************************************************************ - * \brief - * This function is used to arithmetically decode the coded - * block pattern of a given MB. - ************************************************************************ - */ -void readcp_aec(struct syntaxelement *se, struct img_par *img, - struct decoding_environment_s *dep_dp) -{ - struct texture_info_contexts *ctx = img->current_slice->tex_ctx; - struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; - - int mb_x, mb_y; - int a, b; - int curr_cbp_ctx, curr_cbp_idx; - int cbp = 0; - int cbp_bit; - int mask; - - for (mb_y = 0; mb_y < 4; mb_y += 2) { - for (mb_x = 0; mb_x < 4; mb_x += 2) { - if (curr_mb->b8mode[mb_y + (mb_x / 2)] == IBLOCK) - curr_cbp_idx = 0; - else - curr_cbp_idx = 1; - - if (mb_y == 0) { - if (curr_mb->mb_available_up == NULL) - b = 0; - else { - b = ((((curr_mb->mb_available_up)->cbp - & (1 << (2 + mb_x / 2))) - == 0) ? 1 : 0); - } - - } else - b = (((cbp & (1 << (mb_x / 2))) == 0) ? 1 : 0); - - if (mb_x == 0) { - if (curr_mb->mb_available_left == NULL) - a = 0; - else { - a = - ((((curr_mb->mb_available_left)->cbp - & (1 - << (2 - * (mb_y - / 2) - + 1))) - == 0) ? - 1 : 0); - } - } else - a = (((cbp & (1 << mb_y)) == 0) ? 1 : 0); - curr_cbp_ctx = a + 2 * b; - mask = (1 << (mb_y + mb_x / 2)); - cbp_bit = biari_decode_symbol(dep_dp, - ctx->cbp_contexts[0] + curr_cbp_ctx); - - if (cbp_bit) - cbp += mask; - } - } - curr_cbp_ctx = 0; - cbp_bit = biari_decode_symbol(dep_dp, - ctx->cbp_contexts[1] + curr_cbp_ctx); - - if (cbp_bit) { - curr_cbp_ctx = 1; - cbp_bit = biari_decode_symbol(dep_dp, - ctx->cbp_contexts[1] + curr_cbp_ctx); - if (cbp_bit) { - cbp += 48; - - } else { - curr_cbp_ctx = 1; - cbp_bit = biari_decode_symbol(dep_dp, - ctx->cbp_contexts[1] + curr_cbp_ctx); - cbp += (cbp_bit == 1) ? 32 : 16; - - } - } - - se->value1 = cbp; - if (!cbp) - last_dquant = 0; - - - -} - -/*! - ************************************************************************ - * \brief - * This function is used to arithmetically decode the delta qp - * of a given MB. - ************************************************************************ - */ -void readdquant_aec(struct syntaxelement *se, struct img_par *img, - struct decoding_environment_s *dep_dp) -{ - struct motion_info_contexts_s *ctx = img->current_slice->mot_ctx; - - int act_ctx; - int act_sym; - int dquant; - - - act_ctx = ((last_dquant != 0) ? 1 : 0); - - act_sym = 1 - - biari_decode_symbol(dep_dp, - ctx->delta_qp_contexts + act_ctx); - if (act_sym != 0) { - act_ctx = 2; - act_sym = unary_bin_decode(dep_dp, - ctx->delta_qp_contexts + act_ctx, 1); - act_sym++; - } - act_sym &= 0x3f; - push_es(UE[act_sym][0], UE[act_sym][1]); - - dquant = (act_sym + 1) / 2; - if ((act_sym & 0x01) == 0) - dquant = -dquant; - se->value1 = dquant; - - last_dquant = dquant; - -} - -int csyntax; - -#define CHECKDELTAQP {\ - if (img->qp+curr_mb->delta_quant > 63\ - || img->qp+curr_mb->delta_quant < 0) {\ - csyntax = 0;\ - transcoding_error_flag = 1;\ - io_printf("error(0) (%3d|%3d) @ MB%d\n",\ - curr_mb->delta_quant,\ - img->qp+curr_mb->delta_quant,\ - img->picture_structure == 0 \ - ? img->current_mb_nr_fld : img->current_mb_nr);\ - } } - -int dct_level[65]; -int dct_run[65]; -int pair_pos; -int dct_pairs = -1; -const int t_chr[5] = {0, 1, 2, 4, 3000}; - -void readrunlevel_aec_ref(struct syntaxelement *se, struct img_par *img, - struct decoding_environment_s *dep_dp) -{ - int pairs, rank, pos; - int run, level, abslevel, symbol; - int sign; - - if (dct_pairs < 0) { - struct bi_context_type_s (*primary)[NUM_MAP_CTX]; - struct bi_context_type_s *pctx; - struct bi_context_type_s *pCTX2; - int ctx, ctx2, offset; - - if (se->context == LUMA_8x8) { - if (img->picture_structure == 0) { - primary = - img->current_slice->tex_ctx->fld_map_contexts; - } else { - primary = - img->current_slice->tex_ctx->map_contexts; - } - } else { - if (img->picture_structure == 0) { - primary = - img->current_slice->tex_ctx->fld_last_contexts; - } else { - primary = - img->current_slice->tex_ctx->last_contexts; - } - } - - rank = 0; - pos = 0; - for (pairs = 0; pairs < 65; pairs++) { -#ifdef DECODING_SANITY_CHECK - /*max index is NUM_BLOCK_TYPES - 1*/ - pctx = primary[rank & 0x7]; -#else - pctx = primary[rank]; -#endif - if (rank > 0) { -#ifdef DECODING_SANITY_CHECK - /*max index is NUM_BLOCK_TYPES - 1*/ - pCTX2 = primary[(5 + (pos >> 5)) & 0x7]; -#else - pCTX2 = primary[5 + (pos >> 5)]; -#endif - ctx2 = (pos >> 1) & 0x0f; - ctx = 0; - - - if (biari_decode_symbolw(dep_dp, pctx + ctx, - pCTX2 + ctx2)) { - break; - } - } - - ctx = 1; - symbol = 0; - while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) { - symbol += 1; - ctx++; - if (ctx >= 2) - ctx = 2; - } - abslevel = symbol + 1; - - if (biari_decode_symbol_eq_prob(dep_dp)) { - level = -abslevel; - sign = 1; - } else { - level = abslevel; - sign = 0; - } -#if TRACE - tracebits2("level", 1, level); -#endif - - if (abslevel == 1) - offset = 4; - else - offset = 6; - symbol = 0; - ctx = 0; - while (biari_decode_symbol(dep_dp, pctx + ctx + offset) - == 0) { - symbol += 1; - ctx++; - if (ctx >= 1) - ctx = 1; - } - run = symbol; - -#if TRACE - tracebits2("run", 1, run); -#endif - dct_level[pairs] = level; - dct_run[pairs] = run; - if (abslevel > t_chr[rank]) { - if (abslevel <= 2) - rank = abslevel; - else if (abslevel <= 4) - rank = 3; - else - rank = 4; - } - pos += (run + 1); - if (pos >= 64) - pos = 63; - } - dct_pairs = pairs; - pair_pos = dct_pairs; - } - - if (dct_pairs > 0) { - se->value1 = dct_level[pair_pos - 1]; - se->value2 = dct_run[pair_pos - 1]; - pair_pos--; - } else { - - se->value1 = se->value2 = 0; - } - - if ((dct_pairs--) == 0) - pair_pos = 0; -} - -int b8_ctr; -#if 0 -int curr_residual_chroma[4][16][16]; -int curr_residual_luma[16][16]; -#endif - -const int SCAN[2][64][2] = {{{0, 0}, {0, 1}, {0, 2}, {1, 0}, {0, 3}, {0, 4}, {1, - 1}, {1, 2}, {0, 5}, {0, 6}, {1, 3}, {2, 0}, {2, 1}, {0, 7}, {1, - 4}, {2, 2}, {3, 0}, {1, 5}, {1, 6}, {2, 3}, {3, 1}, {3, 2}, {4, - 0}, {1, 7}, {2, 4}, {4, 1}, {2, 5}, {3, 3}, {4, 2}, {2, 6}, {3, - 4}, {4, 3}, {5, 0}, {5, 1}, {2, 7}, {3, 5}, {4, 4}, {5, 2}, {6, - 0}, {5, 3}, {3, 6}, {4, 5}, {6, 1}, {6, 2}, {5, 4}, {3, 7}, {4, - 6}, {6, 3}, {5, 5}, {4, 7}, {6, 4}, {5, 6}, {6, 5}, {5, 7}, {6, - 6}, {7, 0}, {6, 7}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, - 6}, {7, 7} }, {{0, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, { - 3, 0}, {2, 1}, {1, 2}, {0, 3}, {0, 4}, {1, 3}, {2, 2}, {3, 1}, { - 4, 0}, {5, 0}, {4, 1}, {3, 2}, {2, 3}, {1, 4}, {0, 5}, {0, 6}, { - 1, 5}, {2, 4}, {3, 3}, {4, 2}, {5, 1}, {6, 0}, {7, 0}, {6, 1}, { - 5, 2}, {4, 3}, {3, 4}, {2, 5}, {1, 6}, {0, 7}, {1, 7}, {2, 6}, { - 3, 5}, {4, 4}, {5, 3}, {6, 2}, {7, 1}, {7, 2}, {6, 3}, {5, 4}, { - 4, 5}, {3, 6}, {2, 7}, {3, 7}, {4, 6}, {5, 5}, {6, 4}, {7, 3}, { - 7, 4}, {6, 5}, {5, 6}, {4, 7}, {5, 7}, {6, 6}, {7, 5}, {7, 6}, { - 6, 7}, {7, 7} } }; - -const int SCAN_4x4[16][2] = {{0, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, {3, - 0}, {2, 1}, {1, 2}, {0, 3}, {1, 3}, {2, 2}, {3, 1}, {3, 2}, {2, - 3}, {3, 3} }; - -/* - ************************************************************************* - * Function: - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void encode_golomb_word(unsigned int symbol, unsigned int grad0, - unsigned int max_levels, unsigned int *res_bits, - unsigned int *res_len) -{ - unsigned int level, res, numbits; - - res = 1UL << grad0; - level = 1UL; - numbits = 1UL + grad0; - - while (symbol >= res && level < max_levels) { - symbol -= res; - res = res << 1; - level++; - numbits += 2UL; - } - - if (level >= max_levels) { - if (symbol >= res) - symbol = res - 1UL; - } - - *res_bits = res | symbol; - *res_len = numbits; -} - -/* - ************************************************************************* - * Function: - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void encode_multilayer_golomb_word(unsigned int symbol, - const unsigned int *grad, const unsigned int *max_levels, - unsigned int *res_bits, unsigned int *res_len) -{ - unsigned int accbits, acclen, bits, len, tmp; - - accbits = acclen = 0UL; - - while (1) { - encode_golomb_word(symbol, *grad, *max_levels, &bits, &len); - accbits = (accbits << len) | bits; - acclen += len; -#ifdef AVSP_LONG_CABAC -#else - assert(acclen <= 32UL); -#endif - tmp = *max_levels - 1UL; - - if (!((len == (tmp << 1) + (*grad)) - && (bits == (1UL << (tmp + *grad)) - 1UL))) - break; - - tmp = *max_levels; - symbol -= (((1UL << tmp) - 1UL) << (*grad)) - 1UL; - grad++; - max_levels++; - } - *res_bits = accbits; - *res_len = acclen; -} - -/* - ************************************************************************* - * Function: - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -int writesyntaxelement_golomb(struct syntaxelement *se, int write_to_stream) -{ - unsigned int bits, len, i; - unsigned int grad[4], max_lev[4]; - - if (!(se->golomb_maxlevels & ~0xFF)) - encode_golomb_word(se->value1, se->golomb_grad, - se->golomb_maxlevels, &bits, &len); - else { - for (i = 0UL; i < 4UL; i++) { - grad[i] = (se->golomb_grad >> (i << 3)) & 0xFFUL; - max_lev[i] = (se->golomb_maxlevels >> (i << 3)) - & 0xFFUL; - } - encode_multilayer_golomb_word(se->value1, grad, max_lev, &bits, - &len); - } - - se->len = len; - se->bitpattern = bits; - - if (write_to_stream) - push_es(bits, len); - return se->len; -} - -/* - ************************************************************************* - * Function:Get coded block pattern and coefficients (run/level) - from the bitstream - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -void read_cbpandcoeffsfrom_nal(struct img_par *img) -{ - - int tablenum; - int inumblk; - int inumcoeff; - int symbol2D; - int escape_level_diff; - const int (*AVS_2DVLC_table_intra)[26][27]; - const int (*AVS_2DVLC_table_chroma)[26][27]; - int write_to_stream; - struct syntaxelement currse_enc; - struct syntaxelement *e_currse = &currse_enc; - - int coeff_save[65][2]; - int coeff_ptr; - - int ii, jj; - int mb_nr = img->current_mb_nr; - - int m2, jg2; - struct macroblock *curr_mb = &mb_data[mb_nr]; - - int block8x8; - - int block_x, block_y; - - struct slice_s *currslice = img->current_slice; - int level, run, coef_ctr, len, k, i0, j0, uv, qp; - - int boff_x, boff_y, start_scan; - struct syntaxelement curr_se; - struct datapartition *dp; - - AVS_2DVLC_table_intra = AVS_2DVLC_INTRA; - AVS_2DVLC_table_chroma = AVS_2DVLC_CHROMA; - write_to_stream = 1; - - dct_pairs = -1; - - curr_mb->qp = img->qp; - qp = curr_mb->qp; - - - for (block_y = 0; block_y < 4; block_y += 2) {/* all modes */ - for (block_x = 0; block_x < 4; block_x += 2) { - block8x8 = 2 * (block_y / 2) + block_x / 2; - if (curr_mb->cbp & (1 << block8x8)) { - tablenum = 0; - inumblk = 1; - inumcoeff = 65; - coeff_save[0][0] = 0; - coeff_save[0][1] = 0; - coeff_ptr = 1; - - b8_ctr = block8x8; - - boff_x = (block8x8 % 2) << 3; - boff_y = (block8x8 / 2) << 3; - - img->subblock_x = boff_x >> 2; - img->subblock_y = boff_y >> 2; - - start_scan = 0; - coef_ctr = start_scan - 1; - level = 1; - img->is_v_block = 0; - img->is_intra_block = IS_INTRA(curr_mb); - for (k = start_scan; - (k < 65) && (level != 0); - k++) { - - curr_se.context = LUMA_8x8; - curr_se.type = - (IS_INTRA(curr_mb)) ? - SE_LUM_AC_INTRA : - SE_LUM_AC_INTER; - - dp = &(currslice->part_arr[0]); - curr_se.reading = - readrunlevel_aec_ref; - dp-> - read_syntax_element(&curr_se, - img, dp); - level = curr_se.value1; - run = curr_se.value2; - len = curr_se.len; - - if (level != 0) { - coeff_save[coeff_ptr][0] = - run; - coeff_save[coeff_ptr][1] = - level; - coeff_ptr++; - } - - - - if (level != 0) {/* leave if len = 1 */ - coef_ctr += run + 1; - if ((img->picture_structure - == FRAME)) { - ii = - SCAN[img->picture_structure] - [coef_ctr][0]; - jj = - SCAN[img->picture_structure] - [coef_ctr][1]; - } else { - ii = - SCAN[img->picture_structure] - [coef_ctr][0]; - jj = - SCAN[img->picture_structure] - [coef_ctr][1]; - } - - } - } - - while (coeff_ptr > 0) { - run = - coeff_save[coeff_ptr - - 1][0]; - level = - coeff_save[coeff_ptr - - 1][1]; - - coeff_ptr--; - - symbol2D = CODE2D_ESCAPE_SYMBOL; - if (level > -27 && level < 27 - && run < 26) { - if (tablenum == 0) - - symbol2D = - AVS_2DVLC_table_intra - [tablenum] - [run][abs( - level) - - 1]; - else - - symbol2D = - AVS_2DVLC_table_intra - [tablenum] - [run][abs( - level)]; - if (symbol2D >= 0 - && level - < 0) - symbol2D++; - if (symbol2D < 0) - - symbol2D = - (CODE2D_ESCAPE_SYMBOL - + (run - << 1) - + ((level - > 0) ? - 1 : - 0)); - } - - else { - - symbol2D = - (CODE2D_ESCAPE_SYMBOL - + (run - << 1) - + ((level - > 0) ? - 1 : - 0)); - } - - - - e_currse->type = SE_LUM_AC_INTER; - e_currse->value1 = symbol2D; - e_currse->value2 = 0; - - e_currse->golomb_grad = - vlc_golomb_order - [0][tablenum][0]; - e_currse->golomb_maxlevels = - vlc_golomb_order - [0][tablenum][1]; - - writesyntaxelement_golomb( - e_currse, - write_to_stream); - - if (symbol2D - >= CODE2D_ESCAPE_SYMBOL) { - - e_currse->type = - SE_LUM_AC_INTER; - e_currse->golomb_grad = - 1; - e_currse->golomb_maxlevels = - 11; - escape_level_diff = - abs( - level) - - ((run - > MaxRun[0][tablenum]) ? - 1 : - refabslevel[tablenum][run]); - e_currse->value1 = - escape_level_diff; - - writesyntaxelement_golomb( - e_currse, - write_to_stream); - - } - - if (abs(level) - > incvlc_intra[tablenum]) { - if (abs(level) <= 2) - tablenum = - abs( - level); - else if (abs(level) <= 4) - tablenum = 3; - else if (abs(level) <= 7) - tablenum = 4; - else if (abs(level) - <= 10) - tablenum = 5; - else - tablenum = 6; - } - } - - - } - } - } - - - - m2 = img->mb_x * 2; - jg2 = img->mb_y * 2; - - - uv = -1; - block_y = 4; -#if 0 - qp = QP_SCALE_CR[curr_mb->qp]; -#endif - for (block_x = 0; block_x < 4; block_x += 2) { - - uv++; - - - b8_ctr = (uv + 4); - if ((curr_mb->cbp >> (uv + 4)) & 0x1) { - - tablenum = 0; - inumblk = 1; - inumcoeff = 65; - coeff_save[0][0] = 0; - coeff_save[0][1] = 0; - coeff_ptr = 1; - - coef_ctr = -1; - level = 1; - img->subblock_x = 0; - img->subblock_y = 0; - curr_se.context = CHROMA_AC; - curr_se.type = (IS_INTRA(curr_mb) ? - SE_CHR_AC_INTRA : - SE_CHR_AC_INTER); - dp = &(currslice->part_arr[0]); - curr_se.reading = readrunlevel_aec_ref; - img->is_v_block = uv; - img->is_intra_block = IS_INTRA(curr_mb); - for (k = 0; (k < 65) && (level != 0); k++) { - - dp->read_syntax_element - (&curr_se, img, dp); - level = curr_se.value1; - run = curr_se.value2; - len = curr_se.len; - - if (level != 0) { - coeff_save[coeff_ptr][0] = run; - coeff_save[coeff_ptr][1] = - level; - coeff_ptr++; - } - - - if (level != 0) { - coef_ctr = coef_ctr + run + 1; - if ((img->picture_structure - == FRAME) - /*&& (!curr_mb->mb_field)*/) { - i0 = - SCAN[img->picture_structure] - [coef_ctr][0]; - j0 = - SCAN[img->picture_structure] - [coef_ctr][1]; - } else { - i0 = - SCAN[img->picture_structure] - [coef_ctr][0]; - j0 = - SCAN[img->picture_structure] - [coef_ctr][1]; - } - - } - } - - while (coeff_ptr > 0) { - - run = coeff_save[coeff_ptr - 1][0]; - level = coeff_save[coeff_ptr - 1][1]; - - coeff_ptr--; - - symbol2D = CODE2D_ESCAPE_SYMBOL; - if (level > -27 && level < 27 - && run < 26) { - if (tablenum == 0) - - symbol2D = - AVS_2DVLC_table_chroma - [tablenum][run][abs( - level) - - 1]; - else - symbol2D = - AVS_2DVLC_table_chroma - [tablenum][run][abs( - level)]; - if (symbol2D >= 0 - && level < 0) - symbol2D++; - if (symbol2D < 0) - symbol2D = - (CODE2D_ESCAPE_SYMBOL - + (run - << 1) - + ((level - > 0) ? - 1 : - 0)); - } - - else { - symbol2D = - (CODE2D_ESCAPE_SYMBOL - + (run - << 1) - + ((level - > 0) ? - 1 : - 0)); - } - - e_currse->type = SE_LUM_AC_INTER; - e_currse->value1 = symbol2D; - e_currse->value2 = 0; - e_currse->golomb_grad = - vlc_golomb_order[2] - [tablenum][0]; - e_currse->golomb_maxlevels = - vlc_golomb_order[2] - [tablenum][1]; - - writesyntaxelement_golomb(e_currse, - write_to_stream); - - /* - * if (write_to_stream) - * { - * bitCount[BITS_COEFF_UV_MB]+=e_currse->len; - * e_currse++; - * curr_mb->currSEnr++; - * } - * no_bits+=e_currse->len; - - - * if (icoef == 0) break; - */ - - if (symbol2D >= CODE2D_ESCAPE_SYMBOL) { - - e_currse->type = SE_LUM_AC_INTER; - e_currse->golomb_grad = 0; - e_currse->golomb_maxlevels = 11; - escape_level_diff = - abs(level) - - ((run - > MaxRun[2][tablenum]) ? - 1 : - refabslevel[tablenum - + 14][run]); - e_currse->value1 = - escape_level_diff; - - writesyntaxelement_golomb( - e_currse, - write_to_stream); - - } - - if (abs(level) - > incvlc_chroma[tablenum]) { - if (abs(level) <= 2) - tablenum = abs(level); - else if (abs(level) <= 4) - tablenum = 3; - else - tablenum = 4; - } - } - - } - } -} - -/* - ************************************************************************* - * Function:Get the syntax elements from the NAL - * Input: - * Output: - * Return: - * Attention: - ************************************************************************* - */ - -int read_one_macroblock(struct img_par *img) -{ - int i, j; - - struct syntaxelement curr_se; - struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; - - int cabp_flag; - - int tempcbp; - int fixqp; - - struct slice_s *currslice = img->current_slice; - struct datapartition *dp; - - fixqp = (fixed_picture_qp || fixed_slice_qp); - - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) { - img->m8[0][i][j] = 0; - img->m8[1][i][j] = 0; - img->m8[2][i][j] = 0; - img->m8[3][i][j] = 0; - } - - current_mb_skip = 0; - - curr_mb->qp = img->qp; - curr_se.type = SE_MBTYPE; - curr_se.mapping = linfo_ue; - - curr_mb->mb_type_2 = 0; - - if (img->type == I_IMG) - curr_mb->mb_type = 0; - - interpret_mb_mode_i(img); - - init_macroblock(img); - - if ((IS_INTRA(curr_mb)) && (img->abt_flag)) { - -#if TRACE - strncpy(curr_se.tracestring, "cabp_flag", TRACESTRING_SIZE); -#endif - - curr_se.len = 1; - curr_se.type = SE_CABP; - read_syntaxelement_flc(&curr_se); - cabp_flag = curr_se.value1; - if (cabp_flag == 0) { - curr_mb->CABP[0] = 0; - curr_mb->CABP[1] = 0; - curr_mb->CABP[2] = 0; - curr_mb->CABP[3] = 0; - } else { - for (i = 0; i < 4; i++) { - curr_se.len = 1; - curr_se.type = SE_CABP; - read_syntaxelement_flc(&curr_se); - curr_mb->CABP[i] = curr_se.value1; - } - } - - } else { - curr_mb->CABP[0] = 0; - curr_mb->CABP[1] = 0; - curr_mb->CABP[2] = 0; - curr_mb->CABP[3] = 0; - - } - - if (IS_INTRA(curr_mb)) { - for (i = 0; i < /*5*/(chroma_format + 4); i++) - - read_ipred_block_modes(img, i); - } - - curr_se.type = SE_CBP_INTRA; - curr_se.mapping = linfo_cbp_intra; - -#if TRACE - snprintf(curr_se.tracestring, TRACESTRING_SIZE, "CBP"); -#endif - - if (img->type == I_IMG || IS_INTER(curr_mb)) { - curr_se.golomb_maxlevels = 0; - - if (1) { - dp = &(currslice->part_arr[0]); - curr_se.reading = readcp_aec; - dp->read_syntax_element(&curr_se, img, dp); - } - - - curr_mb->cbp = curr_se.value1; - push_es(UE[NCBP[curr_se.value1][0]][0], - UE[NCBP[curr_se.value1][0]][1]); - - } - -# if 1 - if (curr_mb->cbp != 0) - tempcbp = 1; - else - tempcbp = 0; -#else - - if (chroma_format == 2) { -#if TRACE - snprintf(curr_se.tracestring, TRACESTRING_SIZE, "CBP422"); -#endif - curr_se.mapping = /*linfo_se*/linfo_ue; - curr_se.type = SE_CBP_INTRA; - readsyntaxelement_uvlc(&curr_se, inp); - curr_mb->cbp01 = curr_se.value1; - io_printf(" * UE cbp01 read : 0x%02X\n", curr_mb->cbp01); - } - - if (chroma_format == 2) { - if (curr_mb->cbp != 0 || curr_mb->cbp01 != 0) - tempcbp = 1; - else - tempcbp = 0; - - } else { - if (curr_mb->cbp != 0) - tempcbp = 1; - else - tempcbp = 0; - } - -#endif - - if (IS_INTRA(curr_mb) && (img->abt_flag) && (curr_mb->cbp & (0xF))) { - curr_mb->CABT[0] = curr_mb->CABP[0]; - curr_mb->CABT[1] = curr_mb->CABP[1]; - curr_mb->CABT[2] = curr_mb->CABP[2]; - curr_mb->CABT[3] = curr_mb->CABP[3]; - } else { - - curr_mb->CABT[0] = 0; - curr_mb->CABT[1] = 0; - curr_mb->CABT[2] = 0; - curr_mb->CABT[3] = 0; - - if (!fixqp && (tempcbp)) { - if (IS_INTER(curr_mb)) - curr_se.type = SE_DELTA_QUANT_INTER; - else - curr_se.type = SE_DELTA_QUANT_INTRA; - -#if TRACE - snprintf(curr_se.tracestring, - TRACESTRING_SIZE, "Delta quant "); -#endif - - if (1) { - dp = &(currslice->part_arr[0]); - curr_se.reading = readdquant_aec; - dp->read_syntax_element(&curr_se, img, dp); - } - - curr_mb->delta_quant = curr_se.value1; -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & MB_INFO_DUMP) { - io_printf(" * SE delta_quant read : %d\n", - curr_mb->delta_quant); - } -#endif - CHECKDELTAQP - - if (transcoding_error_flag) - return -1; - - img->qp = (img->qp - MIN_QP + curr_mb->delta_quant - + (MAX_QP - MIN_QP + 1)) - % (MAX_QP - MIN_QP + 1) + MIN_QP; - } - - if (fixqp) { - curr_mb->delta_quant = 0; - img->qp = (img->qp - MIN_QP + curr_mb->delta_quant - + (MAX_QP - MIN_QP + 1)) - % (MAX_QP - MIN_QP + 1) + MIN_QP; - - } -#ifdef DUMP_DEBUG - if (avs_get_debug_flag() & MB_INFO_DUMP) - io_printf(" - img->qp : %d\n", img->qp); -#endif - } - - read_cbpandcoeffsfrom_nal(img); - return DECODE_MB; -} - -/*! - ************************************************************************ - * \brief - * finding end of a slice in case this is not the end of a frame - * - * Unsure whether the "correction" below actually solves an off-by-one - * problem or whether it introduces one in some cases :-( Anyway, - * with this change the bit stream format works with AEC again. - * StW, 8.7.02 - ************************************************************************ - */ -int aec_startcode_follows(struct img_par *img, int eos_bit) -{ - struct slice_s *currslice = img->current_slice; - struct datapartition *dp; - unsigned int bit; - struct decoding_environment_s *dep_dp; - - dp = &(currslice->part_arr[0]); - dep_dp = &(dp->de_aec); - - if (eos_bit) - bit = biari_decode_final(dep_dp); - else - bit = 0; - - return bit == 1 ? 1 : 0; -} - -#ifdef AVSP_LONG_CABAC -int process_long_cabac(void) -#else -void main(void) -#endif -{ - int data32; - int current_header; - int i; - int tmp; - int ret; - - int byte_startposition; - int aec_mb_stuffing_bit; - struct slice_s *currslice; -#ifdef PERFORMANCE_DEBUG - pr_info("enter %s\r\n", __func__); -#endif - transcoding_error_flag = 0; - ret = 0; - es_buf = es_write_addr_virt; - - if (local_heap_init(MAX_CODED_FRAME_SIZE * 4) < 0) { - ret = -1; - goto End; - } - - img = (struct img_par *)local_alloc(1, sizeof(struct img_par)); - if (img == NULL) { - no_mem_exit("main: img"); - ret = -1; - goto End; - } - stat_bits_ptr = (struct stat_bits *)local_alloc(1, - sizeof(struct stat_bits)); - if (stat_bits_ptr == NULL) { - no_mem_exit("main: stat_bits"); - ret = -1; - goto End; - } - - curr_stream = alloc_bitstream(); - if (curr_stream == NULL) { - io_printf("alloc bitstream failed\n"); - ret = -1; - goto End; - } - - chroma_format = 1; - demulate_enable = 0; - img->seq_header_indicate = 1; - -#ifdef AVSP_LONG_CABAC - data32 = READ_VREG(LONG_CABAC_REQ); - progressive_sequence = (data32 >> 1) & 1; - fixed_picture_qp = (data32 >> 2) & 1; - img->picture_structure = (data32 >> 3) & 1; - img->type = (data32 >> 4) & 3; - skip_mode_flag = (data32 >> 6) & 1; - - src_start = READ_VREG(LONG_CABAC_SRC_ADDR); - des_start = READ_VREG(LONG_CABAC_DES_ADDR); - - data32 = READ_VREG(LONG_CABAC_PIC_SIZE); - horizontal_size = (data32 >> 0) & 0xffff; - vertical_size = (data32 >> 16) & 0xffff; - if (horizontal_size * vertical_size > 1920 * 1080) { - io_printf("pic size check failed: width = %d, height = %d\n", - horizontal_size, vertical_size); - ret = -1; - goto End; - } - - vld_mem_start_addr = READ_VREG(VLD_MEM_VIFIFO_START_PTR); - vld_mem_end_addr = READ_VREG(VLD_MEM_VIFIFO_END_PTR); - -#else - progressive_sequence = 0; - fixed_picture_qp = 0; - img->picture_structure = 0; - img->type = I_IMG; - skip_mode_flag = 1; - horizontal_size = 1920; - vertical_size = 1080; - - src_start = 0; -#endif - - if (horizontal_size % 16 != 0) - img->auto_crop_right = 16 - (horizontal_size % 16); - else - img->auto_crop_right = 0; - - if (!progressive_sequence) { - if (vertical_size % 32 != 0) - img->auto_crop_bottom = 32 - (vertical_size % 32); - else - img->auto_crop_bottom = 0; - } else { - if (vertical_size % 16 != 0) - img->auto_crop_bottom = 16 - (vertical_size % 16); - else - img->auto_crop_bottom = 0; - } - - img->width = (horizontal_size + img->auto_crop_right); - if (img->picture_structure) - img->height = (vertical_size + img->auto_crop_bottom); - else - img->height = (vertical_size + img->auto_crop_bottom) / 2; - img->width_cr = (img->width >> 1); - - img->pic_width_inmbs = img->width / MB_BLOCK_SIZE; - img->pic_height_inmbs = img->height / MB_BLOCK_SIZE; - img->pic_size_inmbs = img->pic_width_inmbs * img->pic_height_inmbs; - - io_printf( - "[LONG CABAC] Start Transcoding from 0x%x to 0x%x Size : %d x %d\r\n", - src_start, des_start, horizontal_size, vertical_size); -#if 0 - io_printf("VLD_MEM_VIFIFO_START_PTR %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_START_PTR)); - io_printf("VLD_MEM_VIFIFO_CURR_PTR %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR)); - io_printf("VLD_MEM_VIFIFO_END_PTR %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_END_PTR)); - io_printf("VLD_MEM_VIFIFO_WP %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_WP)); - io_printf("VLD_MEM_VIFIFO_RP %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_RP)); - io_printf("VLD_MEM_VBUF_RD_PTR %x\r\n", - READ_VREG(VLD_MEM_VBUF_RD_PTR)); - io_printf("VLD_MEM_VIFIFO_BUF_CNTL %x\r\n", - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL)); -#endif - io_printf( - "[LONG CABAC] progressive_sequence : %d, fixed_picture_qp : %d, skip_mode_flag : %d\r\n", - progressive_sequence, fixed_picture_qp, skip_mode_flag); - io_printf("[LONG CABAC] picture_structure : %d, picture_type : %d\r\n", - img->picture_structure, img->type); - - open_irabs(p_irabs); - - - if (initial_decode() == 0) { - io_printf("initial_decode failed\n"); - ret = -1; - goto End; - } - - init_es(); - - current_header = header(); - io_printf("[LONG CABAC] header Return : %d\n", current_header); - - tmp = slice_header(temp_slice_buf, first_slice_startpos, - first_slice_length); - - init_contexts(img); - aec_new_slice(); - byte_startposition = (curr_stream->frame_bitoffset) / 8; - - currslice = img->current_slice; - - if (1) { - for (i = 0; i < 1; i++) { - img->current_slice->part_arr[i].read_syntax_element = - read_syntaxelement_aec; - img->current_slice->part_arr[i].bitstream = curr_stream; - } - curr_stream = currslice->part_arr[0].bitstream; - } - if ((curr_stream->frame_bitoffset) % 8 != 0) - byte_startposition++; - - arideco_start_decoding(&img->current_slice->part_arr[0].de_aec, - curr_stream->stream_buffer, (byte_startposition), - &(curr_stream->read_len), img->type); - - img->current_mb_nr = 0; - total_mb_count = 0; - while (img->current_mb_nr < img->pic_size_inmbs) - - { - start_macroblock(img); - if (-1 == read_one_macroblock(img)) { - ret = -1; - pr_info("macroblock trans failed, exit\n"); - goto End; - } - if (img->cod_counter <= 0) - aec_mb_stuffing_bit = aec_startcode_follows(img, 1); - img->current_mb_nr++; - } - - push_es(0xff, 8); - io_printf(" Total ES_LENGTH : %d\n", es_ptr); - -#ifdef AVSP_LONG_CABAC - push_es(0xff, 64); - if (es_buf_is_overflow) { - io_printf("fatal error: es_buf_is_overflow\n"); - ret = -1; - goto End; - } - - if (transcoding_error_flag == 0) { -#if 1 - dma_sync_single_for_device(amports_get_dma_device(), - es_write_addr_phy, - es_ptr, DMA_TO_DEVICE); - - wmb(); /**/ -#endif - } -#else - fclose(f_es); -#endif - -End: -#ifdef AVSP_LONG_CABAC - WRITE_VREG(LONG_CABAC_REQ, 0); -#endif - local_heap_uninit(); -#ifdef PERFORMANCE_DEBUG - pr_info("exit %s\r\n", __func__); -#endif - return ret; -} -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/Makefile deleted file mode 100644 index 5fe856648dd2..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS2) += amvdec_avs2.o -amvdec_avs2-objs += vavs2.o avs2_bufmgr.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c deleted file mode 100644 index 6862180a4f47..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c +++ /dev/null @@ -1,2203 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include "avs2_global.h" - -#include -#include "../utils/vdec.h" -#include "../utils/amvdec.h" - -#undef pr_info -#define pr_info printk - -#define assert(chk_cond) {\ - if (!(chk_cond))\ - pr_info("error line %d\n", __LINE__);\ - while (!(chk_cond))\ - ;\ -} - -int16_t get_param(uint16_t value, int8_t *print_info) -{ - if (is_avs2_print_param()) - pr_info("%s = %x\n", print_info, value); - return (int16_t)value; -} - -void readAlfCoeff(struct avs2_decoder *avs2_dec, struct ALFParam_s *Alfp) -{ - int32_t pos; - union param_u *rpm_param = &avs2_dec->param; - - int32_t f = 0, symbol, pre_symbole; - const int32_t numCoeff = (int32_t)ALF_MAX_NUM_COEF; - - switch (Alfp->componentID) { - case ALF_Cb: - case ALF_Cr: { - for (pos = 0; pos < numCoeff; pos++) { - if (Alfp->componentID == ALF_Cb) - Alfp->coeffmulti[0][pos] = - get_param( - rpm_param->alf.alf_cb_coeffmulti[pos], - "Chroma ALF coefficients"); - else - Alfp->coeffmulti[0][pos] = - get_param( - rpm_param->alf.alf_cr_coeffmulti[pos], - "Chroma ALF coefficients"); -#if Check_Bitstream - if (pos <= 7) - assert(Alfp->coeffmulti[0][pos] >= -64 - && Alfp->coeffmulti[0][pos] <= 63); - if (pos == 8) - assert(Alfp->coeffmulti[0][pos] >= -1088 - && Alfp->coeffmulti[0][pos] <= 1071); -#endif - } - } - break; - case ALF_Y: { - int32_t region_distance_idx = 0; - Alfp->filters_per_group = - get_param(rpm_param->alf.alf_filters_num_m_1, - "ALF_filter_number_minus_1"); -#if Check_Bitstream - assert(Alfp->filters_per_group >= 0 - && Alfp->filters_per_group <= 15); -#endif - Alfp->filters_per_group = Alfp->filters_per_group + 1; - - memset(Alfp->filterPattern, 0, NO_VAR_BINS * sizeof(int32_t)); - pre_symbole = 0; - symbol = 0; - for (f = 0; f < Alfp->filters_per_group; f++) { - if (f > 0) { - if (Alfp->filters_per_group != 16) { - symbol = - get_param(rpm_param->alf.region_distance - [region_distance_idx++], - "Region distance"); - } else { - symbol = 1; - } - Alfp->filterPattern[symbol + pre_symbole] = 1; - pre_symbole = symbol + pre_symbole; - } - - for (pos = 0; pos < numCoeff; pos++) { - Alfp->coeffmulti[f][pos] = - get_param( - rpm_param->alf.alf_y_coeffmulti[f][pos], - "Luma ALF coefficients"); -#if Check_Bitstream - if (pos <= 7) - assert( - Alfp->coeffmulti[f][pos] - >= -64 && - Alfp->coeffmulti[f][pos] - <= 63); - if (pos == 8) - assert( - Alfp->coeffmulti[f][pos] - >= -1088 && - Alfp->coeffmulti[f][pos] - <= 1071); -#endif - - } - } - -#if Check_Bitstream - assert(pre_symbole >= 0 && pre_symbole <= 15); - -#endif - } - break; - default: { - pr_info("Not a legal component ID\n"); - assert(0); - return; /* exit(-1);*/ - } - } -} - -void Read_ALF_param(struct avs2_decoder *avs2_dec) -{ - struct inp_par *input = &avs2_dec->input; - struct ImageParameters_s *img = &avs2_dec->img; - union param_u *rpm_param = &avs2_dec->param; - int32_t compIdx; - if (input->alf_enable) { - img->pic_alf_on[0] = - get_param( - rpm_param->alf.picture_alf_enable_Y, - "alf_pic_flag_Y"); - img->pic_alf_on[1] = - get_param( - rpm_param->alf.picture_alf_enable_Cb, - "alf_pic_flag_Cb"); - img->pic_alf_on[2] = - get_param( - rpm_param->alf.picture_alf_enable_Cr, - "alf_pic_flag_Cr"); - - avs2_dec->m_alfPictureParam[ALF_Y].alf_flag - = img->pic_alf_on[ALF_Y]; - avs2_dec->m_alfPictureParam[ALF_Cb].alf_flag - = img->pic_alf_on[ALF_Cb]; - avs2_dec->m_alfPictureParam[ALF_Cr].alf_flag - = img->pic_alf_on[ALF_Cr]; - if (img->pic_alf_on[0] - || img->pic_alf_on[1] - || img->pic_alf_on[2]) { - for (compIdx = 0; - compIdx < NUM_ALF_COMPONENT; - compIdx++) { - if (img->pic_alf_on[compIdx]) { - readAlfCoeff( - avs2_dec, - &avs2_dec->m_alfPictureParam[compIdx]); - } - } - } - } - -} - -void Get_SequenceHeader(struct avs2_decoder *avs2_dec) -{ - struct inp_par *input = &avs2_dec->input; - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - union param_u *rpm_param = &avs2_dec->param; - /*int32_t i, j;*/ - - /*fpr_info(stdout, "Sequence Header\n");*/ - /*memcpy(currStream->streamBuffer, buf, length);*/ - /*currStream->code_len = currStream->bitstream_length = length;*/ - /*currStream->read_len = currStream->frame_bitoffset = (startcodepos + - 1) * 8;*/ - - input->profile_id = - get_param(rpm_param->p.profile_id, "profile_id"); - input->level_id = - get_param(rpm_param->p.level_id, "level_id"); - hd->progressive_sequence = - get_param( - rpm_param->p.progressive_sequence, - "progressive_sequence"); -#if INTERLACE_CODING - hd->is_field_sequence = - get_param( - rpm_param->p.is_field_sequence, - "field_coded_sequence"); -#endif -#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA - img->is_field_sequence = hd->is_field_sequence; -#endif - hd->horizontal_size = - get_param(rpm_param->p.horizontal_size, "horizontal_size"); - hd->vertical_size = - get_param(rpm_param->p.vertical_size, "vertical_size"); - input->chroma_format = - get_param(rpm_param->p.chroma_format, "chroma_format"); - input->output_bit_depth = 8; - input->sample_bit_depth = 8; - hd->sample_precision = 1; - if (input->profile_id == BASELINE10_PROFILE) { /* 10bit profile (0x52)*/ - input->output_bit_depth = - get_param(rpm_param->p.sample_precision, - "sample_precision"); - input->output_bit_depth = - 6 + (input->output_bit_depth) * 2; - input->sample_bit_depth = - get_param(rpm_param->p.encoding_precision, - "encoding_precision"); - input->sample_bit_depth = - 6 + (input->sample_bit_depth) * 2; - } else { /* other profile*/ - hd->sample_precision = - get_param(rpm_param->p.sample_precision, - "sample_precision"); - } - hd->aspect_ratio_information = - get_param(rpm_param->p.aspect_ratio_information, - "aspect_ratio_information"); - hd->frame_rate_code = - get_param(rpm_param->p.frame_rate_code, "frame_rate_code"); - - hd->bit_rate_lower = - get_param(rpm_param->p.bit_rate_lower, "bit_rate_lower"); - /*hd->marker_bit = get_param(rpm_param->p.marker_bit, - * "marker bit");*/ - /*CHECKMARKERBIT*/ - hd->bit_rate_upper = - get_param(rpm_param->p.bit_rate_upper, "bit_rate_upper"); - hd->low_delay = - get_param(rpm_param->p.low_delay, "low_delay"); - /*hd->marker_bit = - get_param(rpm_param->p.marker_bit2, - "marker bit");*/ - /*CHECKMARKERBIT*/ -#if M3480_TEMPORAL_SCALABLE - hd->temporal_id_exist_flag = - get_param(rpm_param->p.temporal_id_exist_flag, - "temporal_id exist flag"); /*get - Extention Flag*/ -#endif - /*u_v(18, "bbv buffer size");*/ - input->g_uiMaxSizeInBit = - get_param(rpm_param->p.g_uiMaxSizeInBit, - "Largest Coding Block Size"); - - - /*hd->background_picture_enable = 0x01 ^ - (get_param(rpm_param->p.avs2_seq_flags, - "background_picture_disable") - >> BACKGROUND_PICTURE_DISABLE_BIT) & 0x1;*/ - /*rain???*/ - hd->background_picture_enable = 0x01 ^ - ((get_param(rpm_param->p.avs2_seq_flags, - "background_picture_disable") - >> BACKGROUND_PICTURE_DISABLE_BIT) & 0x1); - - - hd->b_dmh_enabled = 1; - - hd->b_mhpskip_enabled = - get_param(rpm_param->p.avs2_seq_flags >> B_MHPSKIP_ENABLED_BIT, - "mhpskip enabled") & 0x1; - hd->dhp_enabled = - get_param(rpm_param->p.avs2_seq_flags >> DHP_ENABLED_BIT, - "dhp enabled") & 0x1; - hd->wsm_enabled = - get_param(rpm_param->p.avs2_seq_flags >> WSM_ENABLED_BIT, - "wsm enabled") & 0x1; - - img->inter_amp_enable = - get_param(rpm_param->p.avs2_seq_flags >> INTER_AMP_ENABLE_BIT, - "Asymmetric Motion Partitions") & 0x1; - input->useNSQT = - get_param(rpm_param->p.avs2_seq_flags >> USENSQT_BIT, - "useNSQT") & 0x1; - input->useSDIP = - get_param(rpm_param->p.avs2_seq_flags >> USESDIP_BIT, - "useNSIP") & 0x1; - - hd->b_secT_enabled = - get_param(rpm_param->p.avs2_seq_flags >> B_SECT_ENABLED_BIT, - "secT enabled") & 0x1; - - input->sao_enable = - get_param(rpm_param->p.avs2_seq_flags >> SAO_ENABLE_BIT, - "SAO Enable Flag") & 0x1; - input->alf_enable = - get_param(rpm_param->p.avs2_seq_flags >> ALF_ENABLE_BIT, - "ALF Enable Flag") & 0x1; - hd->b_pmvr_enabled = - get_param(rpm_param->p.avs2_seq_flags >> B_PMVR_ENABLED_BIT, - "pmvr enabled") & 0x1; - - - hd->gop_size = get_param(rpm_param->p.num_of_RPS, - "num_of_RPS"); -#if Check_Bitstream - /*assert(hd->gop_size<=32);*/ -#endif - - if (hd->low_delay == 0) { - hd->picture_reorder_delay = - get_param(rpm_param->p.picture_reorder_delay, - "picture_reorder_delay"); - } - - input->crossSliceLoopFilter = - get_param(rpm_param->p.avs2_seq_flags - >> CROSSSLICELOOPFILTER_BIT, - "Cross Loop Filter Flag") & 0x1; - -#if BCBR - if ((input->profile_id == SCENE_PROFILE || - input->profile_id == SCENE10_PROFILE) && - hd->background_picture_enable) { - hd->bcbr_enable = u_v(1, - "block_composed_background_picture_enable"); - u_v(1, "reserved bits"); - } else { - hd->bcbr_enable = 0; - u_v(2, "reserved bits"); - } -#else - /*u_v(2, "reserved bits");*/ -#endif - - img->width = hd->horizontal_size; - img->height = hd->vertical_size; - img->width_cr = (img->width >> 1); - - if (input->chroma_format == 1) { - img->height_cr - = (img->height >> 1); - } - - img->PicWidthInMbs = img->width / MIN_CU_SIZE; - img->PicHeightInMbs = img->height / MIN_CU_SIZE; - img->PicSizeInMbs = img->PicWidthInMbs * img->PicHeightInMbs; - img->buf_cycle = input->buf_cycle + 1; - img->max_mb_nr = (img->width * img->height) - / (MIN_CU_SIZE * MIN_CU_SIZE); - -#ifdef AML -avs2_dec->lcu_size = - get_param(rpm_param->p.lcu_size, "lcu_size"); -avs2_dec->lcu_size = 1<<(avs2_dec->lcu_size); -#endif -hc->seq_header++; -} - - -void Get_I_Picture_Header(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - union param_u *rpm_param = &avs2_dec->param; - -#if RD1501_FIX_BG /*//Longfei.Wang@mediatek.com*/ - hd->background_picture_flag = 0; - hd->background_picture_output_flag = 0; - img->typeb = 0; -#endif - - hd->time_code_flag = - get_param(rpm_param->p.time_code_flag, - "time_code_flag"); - - if (hd->time_code_flag) { - hd->time_code = - get_param(rpm_param->p.time_code, - "time_code"); - } - if (hd->background_picture_enable) { - hd->background_picture_flag = - get_param(rpm_param->p.background_picture_flag, - "background_picture_flag"); - - if (hd->background_picture_flag) { - img->typeb = - BACKGROUND_IMG; - } else { - img->typeb = 0; - } - - if (img->typeb == BACKGROUND_IMG) { - hd->background_picture_output_flag = - get_param( - rpm_param->p.background_picture_output_flag, - "background_picture_output_flag"); - } - } - - - { - img->coding_order = - get_param(rpm_param->p.coding_order, - "coding_order"); - - - -#if M3480_TEMPORAL_SCALABLE - if (hd->temporal_id_exist_flag == 1) { - hd->cur_layer = - get_param(rpm_param->p.cur_layer, - "temporal_id"); - } -#endif -#if RD1501_FIX_BG /*Longfei.Wang@mediatek.com*/ - if (hd->low_delay == 0 - && !(hd->background_picture_flag && - !hd->background_picture_output_flag)) { /*cdp*/ -#else - if (hd->low_delay == 0 && - !(hd->background_picture_enable && - !hd->background_picture_output_flag)) { /*cdp*/ -#endif - hd->displaydelay = - get_param(rpm_param->p.displaydelay, - "picture_output_delay"); - } - - } - { - int32_t RPS_idx;/* = (img->coding_order-1) % gop_size;*/ - int32_t predict; - int32_t j; - predict = - get_param(rpm_param->p.predict, - "use RCS in SPS"); - /*if (predict) {*/ - RPS_idx = - get_param(rpm_param->p.RPS_idx, - "predict for RCS"); - /* hd->curr_RPS = hd->decod_RPS[RPS_idx];*/ - /*} else {*/ - /*gop size16*/ - hd->curr_RPS.referd_by_others = - get_param(rpm_param->p.referd_by_others_cur, - "refered by others"); - hd->curr_RPS.num_of_ref = - get_param(rpm_param->p.num_of_ref_cur, - "num of reference picture"); - for (j = 0; j < hd->curr_RPS.num_of_ref; j++) { - hd->curr_RPS.ref_pic[j] = - get_param(rpm_param->p.ref_pic_cur[j], - "delta COI of ref pic"); - } - hd->curr_RPS.num_to_remove = - get_param(rpm_param->p.num_to_remove_cur, - "num of removed picture"); -#ifdef SANITY_CHECK - if (hd->curr_RPS.num_to_remove > 8) { - hd->curr_RPS.num_to_remove = 8; - pr_info("Warning, %s: num_to_remove %d beyond range, force to 8\n", - __func__, hd->curr_RPS.num_to_remove); - } -#endif - - for (j = 0; j < hd->curr_RPS.num_to_remove; j++) { - hd->curr_RPS.remove_pic[j] = - get_param( - rpm_param->p.remove_pic_cur[j], - "delta COI of removed pic"); - } - /*u_v(1, "marker bit");*/ - - /*}*/ - } - /*xyji 12.23*/ - if (hd->low_delay) { - /*ue_v( - "bbv check times");*/ - } - - hd->progressive_frame = - get_param(rpm_param->p.progressive_frame, - "progressive_frame"); - - if (!hd->progressive_frame) { - img->picture_structure = - get_param(rpm_param->p.picture_structure, - "picture_structure"); - } else { - img->picture_structure - = 1; - } - - hd->top_field_first = - get_param(rpm_param->p.top_field_first, - "top_field_first"); - hd->repeat_first_field = - get_param(rpm_param->p.repeat_first_field, - "repeat_first_field"); -#if INTERLACE_CODING - if (hd->is_field_sequence) { - hd->is_top_field = - get_param(rpm_param->p.is_top_field, - "is_top_field"); -#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA - img->is_top_field = hd->is_top_field; -#endif - } -#endif - - - img->qp = hd->picture_qp; - - img->type = I_IMG; - -} - -/* - * Function:pb picture header - * Input: - * Output: - * Return: - * Attention: - */ - -void Get_PB_Picture_Header(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - union param_u *rpm_param = &avs2_dec->param; - - - /*u_v(32, "bbv delay");*/ - - hd->picture_coding_type = - get_param(rpm_param->p.picture_coding_type, - "picture_coding_type"); - - if (hd->background_picture_enable && - (hd->picture_coding_type == 1 || - hd->picture_coding_type == 3)) { - if (hd->picture_coding_type == 1) { - hd->background_pred_flag = - get_param( - rpm_param->p.background_pred_flag, - "background_pred_flag"); - } else { - hd->background_pred_flag = 0; - } - if (hd->background_pred_flag == 0) { - - hd->background_reference_enable = - get_param( - rpm_param-> - p.background_reference_enable, - "background_reference_enable"); - - } else { -#if RD170_FIX_BG - hd->background_reference_enable = 1; -#else - hd->background_reference_enable = 0; -#endif - } - - } else { - hd->background_pred_flag = 0; - hd->background_reference_enable = 0; - } - - - - if (hd->picture_coding_type == 1) { - img->type = - P_IMG; - } else if (hd->picture_coding_type == 3) { - img->type = - F_IMG; - } else { - img->type = - B_IMG; - } - - - if (hd->picture_coding_type == 1 && - hd->background_pred_flag) { - img->typeb = BP_IMG; - } else { - img->typeb = 0; - } - - - { - img->coding_order = - get_param( - rpm_param->p.coding_order, - "coding_order"); - - -#if M3480_TEMPORAL_SCALABLE - if (hd->temporal_id_exist_flag == 1) { - hd->cur_layer = - get_param(rpm_param->p.cur_layer, - "temporal_id"); - } -#endif - - if (hd->low_delay == 0) { - hd->displaydelay = - get_param(rpm_param->p.displaydelay, - "displaydelay"); - } - } - { - int32_t RPS_idx;/* = (img->coding_order-1) % gop_size;*/ - int32_t predict; - predict = - get_param(rpm_param->p.predict, - "use RPS in SPS"); - if (predict) { - RPS_idx = - get_param(rpm_param->p.RPS_idx, - "predict for RPS"); - hd->curr_RPS = hd->decod_RPS[RPS_idx]; - } /*else*/ - { - /*gop size16*/ - int32_t j; - hd->curr_RPS.referd_by_others = - get_param( - rpm_param->p.referd_by_others_cur, - "refered by others"); - hd->curr_RPS.num_of_ref = - get_param( - rpm_param->p.num_of_ref_cur, - "num of reference picture"); - for (j = 0; j < hd->curr_RPS.num_of_ref; j++) { - hd->curr_RPS.ref_pic[j] = - get_param( - rpm_param->p.ref_pic_cur[j], - "delta COI of ref pic"); - } - hd->curr_RPS.num_to_remove = - get_param( - rpm_param->p.num_to_remove_cur, - "num of removed picture"); -#ifdef SANITY_CHECK - if (hd->curr_RPS.num_to_remove > 8) { - hd->curr_RPS.num_to_remove = 8; - pr_info("Warning, %s: num_to_remove %d beyond range, force to 8\n", - __func__, hd->curr_RPS.num_to_remove); - } -#endif - for (j = 0; - j < hd->curr_RPS.num_to_remove; j++) { - hd->curr_RPS.remove_pic[j] = - get_param( - rpm_param->p.remove_pic_cur[j], - "delta COI of removed pic"); - } - /*u_v(1, "marker bit");*/ - - } - } - /*xyji 12.23*/ - if (hd->low_delay) { - /*ue_v( - "bbv check times");*/ - } - - hd->progressive_frame = - get_param(rpm_param->p.progressive_frame, - "progressive_frame"); - - if (!hd->progressive_frame) { - img->picture_structure = - get_param(rpm_param->p.picture_structure, - "picture_structure"); - } else { - img->picture_structure = 1; - } - - hd->top_field_first = - get_param(rpm_param->p.top_field_first, - "top_field_first"); - hd->repeat_first_field = - get_param(rpm_param->p.repeat_first_field, - "repeat_first_field"); -#if INTERLACE_CODING - if (hd->is_field_sequence) { - hd->is_top_field = - get_param(rpm_param->p.is_top_field, - "is_top_field"); -#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA - img->is_top_field = hd->is_top_field; -#endif - /*u_v(1, "reserved bit for interlace coding");*/ - } -#endif - -#if Check_Bitstream - /*assert(hd->picture_qp>=0&&hd->picture_qp<=(63 + 8 * - (input->sample_bit_depth - 8)));*/ -#endif - - img->random_access_decodable_flag = - get_param(rpm_param->p.random_access_decodable_flag, - "random_access_decodable_flag"); - - img->qp = hd->picture_qp; -} - - - - -void calc_picture_distance(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - /* - union param_u *rpm_param = &avs2_dec->param; - - for POC mode 0: - uint32_t MaxPicDistanceLsb = (1 << 8); - */ - if (img->coding_order < img->PrevPicDistanceLsb) - - { - int32_t i, j; - - hc->total_frames++; - for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { - if ( - avs2_dec->fref[i]->imgtr_fwRefDistance - >= 0) { - avs2_dec->fref[i]-> - imgtr_fwRefDistance -= 256; - avs2_dec->fref[i]-> - imgcoi_ref -= 256; - } -#if RD170_FIX_BG - for (j = 0; j < MAXREF; j++) { -#else - for (j = 0; j < 4; j++) { -#endif - avs2_dec->fref[i]->ref_poc[j] -= 256; - } - } - for (i = 0; i < avs2_dec->outprint.buffer_num; i++) { - avs2_dec->outprint.stdoutdata[i].framenum -= 256; - avs2_dec->outprint.stdoutdata[i].tr -= 256; - } - - hd->last_output -= 256; - hd->curr_IDRtr -= 256; - hd->curr_IDRcoi -= 256; - hd->next_IDRtr -= 256; - hd->next_IDRcoi -= 256; - } - if (hd->low_delay == 0) { - img->tr = img->coding_order + - hd->displaydelay - hd->picture_reorder_delay; - } else { - img->tr = - img->coding_order; - } - -#if REMOVE_UNUSED - img->pic_distance = img->tr; -#else - img->pic_distance = img->tr % 256; -#endif - hc->picture_distance = img->pic_distance; - -} - -int32_t avs2_init_global_buffers(struct avs2_decoder *avs2_dec) -{ - struct inp_par *input = &avs2_dec->input; - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - - int32_t refnum; - - int32_t memory_size = 0; - /* -int32_t img_height = (hd->vertical_size + img->auto_crop_bottom); - */ - img->buf_cycle = input->buf_cycle + 1; - - img->buf_cycle *= 2; - - hc->background_ref = hc->backgroundReferenceFrame; - - for (refnum = 0; refnum < REF_MAXBUFFER; refnum++) { - avs2_dec->fref[refnum] = &avs2_dec->frm_pool[refnum]; - - /*//avs2_dec->fref[i] memory allocation*/ - if (is_avs2_print_bufmgr_detail()) - pr_info("[t] avs2_dec->fref[%d]@0x%p\n", - refnum, avs2_dec->fref[refnum]); - avs2_dec->fref[refnum]->imgcoi_ref = -257; - avs2_dec->fref[refnum]->is_output = -1; - avs2_dec->fref[refnum]->refered_by_others = -1; - avs2_dec->fref[refnum]-> - imgtr_fwRefDistance = -256; - init_frame_t(avs2_dec->fref[refnum]); -#ifdef AML - avs2_dec->fref[refnum]->index = refnum; -#endif - } -#ifdef AML - avs2_dec->f_bg = NULL; - - avs2_dec->m_bg = &avs2_dec->frm_pool[REF_MAXBUFFER]; - /*///avs2_dec->fref[i] memory allocation*/ - if (is_avs2_print_bufmgr_detail()) - pr_info("[t] avs2_dec->m_bg@0x%p\n", - avs2_dec->m_bg); - avs2_dec->m_bg->imgcoi_ref = -257; - avs2_dec->m_bg->is_output = -1; - avs2_dec->m_bg->refered_by_others = -1; - avs2_dec->m_bg->imgtr_fwRefDistance = -256; - init_frame_t(avs2_dec->m_bg); - avs2_dec->m_bg->index = refnum; -#endif - -#if BCBR - /*init BCBR related*/ - img->iNumCUsInFrame = - ((img->width + MAX_CU_SIZE - 1) / MAX_CU_SIZE) - * ((img->height + MAX_CU_SIZE - 1) - / MAX_CU_SIZE); - /*img->BLCUidx = (int32_t*) calloc( - img->iNumCUsInFrame, sizeof(int32_t));*/ - /*memset( img->BLCUidx, 0, img->iNumCUsInFrame);*/ -#endif - return memory_size; -} - -#ifdef AML -static void free_unused_buffers(struct avs2_decoder *avs2_dec) -{ - struct inp_par *input = &avs2_dec->input; - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - - int32_t refnum; - - img->buf_cycle = input->buf_cycle + 1; - - img->buf_cycle *= 2; - - hc->background_ref = hc->backgroundReferenceFrame; - - for (refnum = 0; refnum < REF_MAXBUFFER; refnum++) { -#ifndef NO_DISPLAY - if (avs2_dec->fref[refnum]->vf_ref > 0 || - avs2_dec->fref[refnum]->to_prepare_disp) - continue; -#endif - if (is_avs2_print_bufmgr_detail()) - pr_info("%s[t] avs2_dec->fref[%d]@0x%p\n", - __func__, refnum, avs2_dec->fref[refnum]); - avs2_dec->fref[refnum]->imgcoi_ref = -257; - avs2_dec->fref[refnum]->is_output = -1; - avs2_dec->fref[refnum]->refered_by_others = -1; - avs2_dec->fref[refnum]-> - imgtr_fwRefDistance = -256; - memset(avs2_dec->fref[refnum]->ref_poc, 0, - sizeof(avs2_dec->fref[refnum]->ref_poc)); - } - avs2_dec->f_bg = NULL; - - if (is_avs2_print_bufmgr_detail()) - pr_info("%s[t] avs2_dec->m_bg@0x%p\n", - __func__, avs2_dec->m_bg); - avs2_dec->m_bg->imgcoi_ref = -257; - avs2_dec->m_bg->is_output = -1; - avs2_dec->m_bg->refered_by_others = -1; - avs2_dec->m_bg->imgtr_fwRefDistance = -256; - memset(avs2_dec->m_bg->ref_poc, 0, - sizeof(avs2_dec->m_bg->ref_poc)); - -#if BCBR - /*init BCBR related*/ - img->iNumCUsInFrame = - ((img->width + MAX_CU_SIZE - 1) / MAX_CU_SIZE) - * ((img->height + MAX_CU_SIZE - 1) - / MAX_CU_SIZE); - /*img->BLCUidx = (int32_t*) calloc( - img->iNumCUsInFrame, sizeof(int32_t));*/ - /*memset( img->BLCUidx, 0, img->iNumCUsInFrame);*/ -#endif -} -#endif - -void init_frame_t(struct avs2_frame_s *currfref) -{ - memset(currfref, 0, sizeof(struct avs2_frame_s)); - currfref->imgcoi_ref = -257; - currfref->is_output = -1; - currfref->refered_by_others = -1; - currfref->imgtr_fwRefDistance = -256; - memset(currfref->ref_poc, 0, sizeof(currfref->ref_poc)); -} - -void get_reference_list_info(struct avs2_decoder *avs2_dec, int8_t *str) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - - int8_t str_tmp[16]; - int32_t i; - /* int32_t poc = hc->f_rec->imgtr_fwRefDistance; - fred.chiu@mediatek.com*/ - - if (img->num_of_references > 0) { - strcpy(str, "["); - for (i = 0; i < img->num_of_references; i++) { -#if RD1510_FIX_BG - if (img->type == B_IMG) { - sprintf(str_tmp, "%4d ", - hc->f_rec-> - ref_poc[ - img->num_of_references - 1 - i]); - } else { - sprintf(str_tmp, "%4d ", - hc->f_rec->ref_poc[i]); - } -#else - sprintf(str_tmp, "%4d ", - avs2_dec->fref[i]->imgtr_fwRefDistance); -#endif - - str_tmp[5] = '\0'; - strcat(str, str_tmp); - } - strcat(str, "]"); - } else { - str[0] = '\0'; - } -} - -void prepare_RefInfo(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - - int32_t i, j; - int32_t ii; - struct avs2_frame_s *tmp_fref; - - /*update IDR frame*/ - if (img->tr > hd->next_IDRtr && hd->curr_IDRtr != hd->next_IDRtr) { - hd->curr_IDRtr = hd->next_IDRtr; - hd->curr_IDRcoi = hd->next_IDRcoi; - } - /* re-order the ref buffer according to RPS*/ - img->num_of_references = hd->curr_RPS.num_of_ref; - -#if 1 - /*rain*/ - if (is_avs2_print_bufmgr_detail()) { - pr_info("%s: coding_order is %d, curr_IDRcoi is %d\n", - __func__, img->coding_order, hd->curr_IDRcoi); - for (ii = 0; ii < MAXREF; ii++) { - pr_info("ref_pic(%d)=%d\n", - ii, hd->curr_RPS.ref_pic[ii]); - } - for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { - pr_info( - "fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d\n", - ii, avs2_dec->fref[ii]->index, - avs2_dec->fref[ii]->imgcoi_ref, - avs2_dec->fref[ii]->imgtr_fwRefDistance); - } - } -#endif - - for (i = 0; i < hd->curr_RPS.num_of_ref; i++) { - /*int32_t accumulate = 0;*/ - /* copy tmp_fref from avs2_dec->fref[i] */ - tmp_fref = avs2_dec->fref[i]; - -#if REMOVE_UNUSED - for (j = i; j < avs2_dec->ref_maxbuffer; j++) { - /*/////////////to be modified IDR*/ - if (avs2_dec->fref[j]->imgcoi_ref == - img->coding_order - - hd->curr_RPS.ref_pic[i]) { - break; - } - } -#else - - for (j = i; j < avs2_dec->ref_maxbuffer; j++) { - /*/////////////to be modified IDR*/ - int32_t k , tmp_tr; - for (k = 0; k < avs2_dec->ref_maxbuffer; k++) { - if (((int32_t)img->coding_order - - (int32_t)hd->curr_RPS.ref_pic[i]) == - avs2_dec->fref[k]->imgcoi_ref && - avs2_dec->fref[k]->imgcoi_ref >= -256) { - break; - } - } - if (k == avs2_dec->ref_maxbuffer) { - tmp_tr = - -1-1; - } else { - tmp_tr = - avs2_dec->fref[k]->imgtr_fwRefDistance; - } - if (tmp_tr < hd->curr_IDRtr) { - hd->curr_RPS.ref_pic[i] = - img->coding_order - hd->curr_IDRcoi; - - for (k = 0; k < i; k++) { - if (hd->curr_RPS.ref_pic[k] == - hd->curr_RPS.ref_pic[i]) { - accumulate++; - break; - } - } - } - if (avs2_dec->fref[j]->imgcoi_ref == - img->coding_order - hd->curr_RPS.ref_pic[i]) { - break; - } - } - if (j == avs2_dec->ref_maxbuffer || accumulate) - img->num_of_references--; -#endif - if (j != avs2_dec->ref_maxbuffer) { - /* copy avs2_dec->fref[i] from avs2_dec->fref[j] */ - avs2_dec->fref[i] = avs2_dec->fref[j]; - /* copy avs2_dec->fref[j] from ferf[tmp] */ - avs2_dec->fref[j] = tmp_fref; - if (is_avs2_print_bufmgr_detail()) { - pr_info("%s, switch %d %d: ", __func__, i, j); - for (ii = 0; ii < hd->curr_RPS.num_of_ref - || ii <= j; ii++) - pr_info("%d ", - avs2_dec->fref[ii]->index); - pr_info("\n"); - } - } - } - if (img->type == B_IMG && - (avs2_dec->fref[0]->imgtr_fwRefDistance <= img->tr - || avs2_dec->fref[1]->imgtr_fwRefDistance >= img->tr)) { - - pr_info("wrong reference configuration for B frame\n"); - pr_info( - "fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, img->tr %d\n", - avs2_dec->fref[0]->imgtr_fwRefDistance, - avs2_dec->fref[1]->imgtr_fwRefDistance, - img->tr); - hc->f_rec->error_mark = 1; - avs2_dec->bufmgr_error_flag = 1; - return; /* exit(-1);*/ - /*******************************************/ - } - -#if !FIX_PROFILE_LEVEL_DPB_RPS_1 - /* delete the frame that will never be used*/ - for (i = 0; i < hd->curr_RPS.num_to_remove; i++) { - for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { - if (avs2_dec->fref[j]->imgcoi_ref >= -256 - && avs2_dec->fref[j]->imgcoi_ref - == img->coding_order - - hd->curr_RPS.remove_pic[i]) { - break; - } - } - if (j < avs2_dec->ref_maxbuffer && - j >= img->num_of_references) { - avs2_dec->fref[j]->imgcoi_ref = -257; -#if M3480_TEMPORAL_SCALABLE - avs2_dec->fref[j]->temporal_id = -1; -#endif - if (avs2_dec->fref[j]->is_output == -1) { - avs2_dec->fref[j]-> - imgtr_fwRefDistance = -256; - } - } - } -#endif - - /* add inter-view reference picture*/ - - /* add current frame to ref buffer*/ - for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { - if ((avs2_dec->fref[i]->imgcoi_ref < -256 - || abs(avs2_dec->fref[i]-> - imgtr_fwRefDistance - img->tr) >= 128) - && avs2_dec->fref[i]->is_output == -1 - && avs2_dec->fref[i]->bg_flag == 0 -#ifndef NO_DISPLAY - && avs2_dec->fref[i]->vf_ref == 0 - && avs2_dec->fref[i]->to_prepare_disp == 0 -#endif - ) { - break; - } - } - if (i == avs2_dec->ref_maxbuffer) { - pr_info( - "%s, warning, no enough buf\n", - __func__); - i--; - } - - hc->f_rec = avs2_dec->fref[i]; - hc->currentFrame = hc->f_rec->ref; - hc->f_rec->imgtr_fwRefDistance = img->tr; - hc->f_rec->imgcoi_ref = img->coding_order; -#if M3480_TEMPORAL_SCALABLE - hc->f_rec->temporal_id = hd->cur_layer; -#endif - hc->f_rec->is_output = 1; -#ifdef AML - hc->f_rec->error_mark = 0; - hc->f_rec->decoded_lcu = 0; - hc->f_rec->slice_type = img->type; -#endif - hc->f_rec->refered_by_others = hd->curr_RPS.referd_by_others; - if (is_avs2_print_bufmgr_detail()) - pr_info( - "%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d img_type %d\n", - __func__, i, img->tr, img->coding_order, - img->type); - - if (img->type != B_IMG) { - for (j = 0; - j < img->num_of_references; j++) { - hc->f_rec->ref_poc[j] = - avs2_dec->fref[j]->imgtr_fwRefDistance; - } - } else { - hc->f_rec->ref_poc[0] = - avs2_dec->fref[1]->imgtr_fwRefDistance; - hc->f_rec->ref_poc[1] = - avs2_dec->fref[0]->imgtr_fwRefDistance; - } - -#if M3480_TEMPORAL_SCALABLE - - for (j = img->num_of_references; - j < 4; j++) { - /**/ - hc->f_rec->ref_poc[j] = 0; - } - - if (img->type == INTRA_IMG) { - int32_t l; - for (l = 0; l < 4; l++) { - hc->f_rec->ref_poc[l] - = img->tr; - } - } - -#endif - -/*////////////////////////////////////////////////////////////////////////*/ - /* updata ref pointer*/ - - if (img->type != I_IMG) { - - img->imgtr_next_P = img->type == B_IMG ? - avs2_dec->fref[0]->imgtr_fwRefDistance : img->tr; - if (img->type == B_IMG) { - hd->trtmp = avs2_dec->fref[0]->imgtr_fwRefDistance; - avs2_dec->fref[0]->imgtr_fwRefDistance = - avs2_dec->fref[1]->imgtr_fwRefDistance; - } - } -#if 1 - /*rain*/ - if (is_avs2_print_bufmgr_detail()) { - for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { - pr_info( - "fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, is_out %d, bg %d, vf_ref %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", - ii, avs2_dec->fref[ii]->index, - avs2_dec->fref[ii]->imgcoi_ref, - avs2_dec->fref[ii]->imgtr_fwRefDistance, - avs2_dec->fref[ii]->refered_by_others, - avs2_dec->fref[ii]->is_output, - avs2_dec->fref[ii]->bg_flag, - avs2_dec->fref[ii]->vf_ref, - avs2_dec->fref[ii]->ref_poc[0], - avs2_dec->fref[ii]->ref_poc[1], - avs2_dec->fref[ii]->ref_poc[2], - avs2_dec->fref[ii]->ref_poc[3], - avs2_dec->fref[ii]->ref_poc[4], - avs2_dec->fref[ii]->ref_poc[5], - avs2_dec->fref[ii]->ref_poc[6] - ); - } - } -#endif -} - -int32_t init_frame(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - - -#if RD1510_FIX_BG - if (img->type == I_IMG && - img->typeb == BACKGROUND_IMG) { /*G/GB frame*/ - img->num_of_references = 0; - } else if (img->type == P_IMG && img->typeb == BP_IMG) { - /* only one reference frame(G\GB) for S frame*/ - img->num_of_references = 1; - } -#endif - - if (img->typeb == BACKGROUND_IMG && - hd->background_picture_output_flag == 0) { - hc->currentFrame = hc->background_ref; -#ifdef AML - hc->cur_pic = avs2_dec->m_bg; -#endif - } else { - prepare_RefInfo(avs2_dec); -#ifdef AML - hc->cur_pic = hc->f_rec; -#endif - } - - -#ifdef FIX_CHROMA_FIELD_MV_BK_DIST - if (img->typeb == BACKGROUND_IMG - && img->is_field_sequence) { - avs2_dec->bk_img_is_top_field - = img->is_top_field; - } -#endif - return 0; -} - -void delete_trbuffer(struct outdata_s *data, int32_t pos) -{ - int32_t i; - for (i = pos; - i < data->buffer_num - 1; i++) { - data->stdoutdata[i] = - data->stdoutdata[i + 1]; - } - data->buffer_num--; -} - -#if RD170_FIX_BG -void flushDPB(struct avs2_decoder *avs2_dec) -{ - struct Video_Dec_data_s *hd = &avs2_dec->hd; - int j, tmp_min, i, pos = -1; - int search_times = avs2_dec->outprint.buffer_num; - - tmp_min = 1 << 20; - i = 0, j = 0; - pos = -1; - - for (j = 0; j < search_times; j++) { - pos = -1; - tmp_min = (1 << 20); - /*search for min poi picture to display*/ - for (i = 0; i < avs2_dec->outprint.buffer_num; i++) { - if (avs2_dec->outprint.stdoutdata[i].tr < tmp_min) { - pos = i; - tmp_min = avs2_dec->outprint.stdoutdata[i].tr; - } - } - - if (pos != -1) { - hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr; - report_frame(avs2_dec, &avs2_dec->outprint, pos); - if (avs2_dec->outprint.stdoutdata[pos].typeb - == BACKGROUND_IMG && - avs2_dec->outprint.stdoutdata[pos]. - background_picture_output_flag - == 0) { - /*write_GB_frame(hd->p_out_background);*/ - } else { - write_frame(avs2_dec, - avs2_dec->outprint.stdoutdata[pos].tr); - } - - delete_trbuffer(&avs2_dec->outprint, pos); - } - } - - /*clear dpb info*/ - for (j = 0; j < REF_MAXBUFFER; j++) { - avs2_dec->fref[j]->imgtr_fwRefDistance = -256; - avs2_dec->fref[j]->imgcoi_ref = -257; - avs2_dec->fref[j]->temporal_id = -1; - avs2_dec->fref[j]->refered_by_others = 0; - } -} -#endif - - - -#if M3480_TEMPORAL_SCALABLE -void cleanRefMVBufRef(int pos) -{ -#if 0 - int k, x, y; - /*re-init mvbuf*/ - for (k = 0; k < 2; k++) { - for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) { - for (x = 0; x < img->width / MIN_BLOCK_SIZE; x++) - fref[pos]->mvbuf[y][x][k] = 0; - - } - } - /*re-init refbuf*/ - for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) { - for (x = 0; x < img->width / MIN_BLOCK_SIZE ; x++) - fref[pos]->refbuf[y][x] = -1; - - } -#endif -} -#endif - -static int frame_postprocessing(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - - int32_t pointer_tmp = avs2_dec->outprint.buffer_num; - int32_t i; - struct STDOUT_DATA_s *p_outdata; -#if RD160_FIX_BG - int32_t j, tmp_min, output_cur_dec_pic, pos = -1; - int32_t search_times = avs2_dec->outprint.buffer_num; -#endif - /*pic dist by Grandview Semi. @ [06-07-20 15:25]*/ - img->PrevPicDistanceLsb = (img->coding_order % 256); - - pointer_tmp = avs2_dec->outprint.buffer_num; - p_outdata = &avs2_dec->outprint.stdoutdata[pointer_tmp]; - - p_outdata->type = img->type; - p_outdata->typeb = img->typeb; - p_outdata->framenum = img->tr; - p_outdata->tr = img->tr; -#if 0 /*def ORI*/ - p_outdata->qp = img->qp; -#else - p_outdata->qp = 0; -#endif - /*p_outdata->snr_y = snr->snr_y;*/ - /*p_outdata->snr_u = snr->snr_u;*/ - /*p_outdata->snr_v = snr->snr_v;*/ - p_outdata->tmp_time = hd->tmp_time; - p_outdata->picture_structure = img->picture_structure; - /*p_outdata->curr_frame_bits = - StatBitsPtr->curr_frame_bits;*/ - /*p_outdata->emulate_bits = StatBitsPtr->emulate_bits;*/ -#if RD1501_FIX_BG - p_outdata->background_picture_output_flag - = hd->background_picture_output_flag; - /*Longfei.Wang@mediatek.com*/ -#endif - -#if RD160_FIX_BG - p_outdata->picture_reorder_delay = hd->picture_reorder_delay; -#endif - avs2_dec->outprint.buffer_num++; - -#if RD170_FIX_BG - search_times = avs2_dec->outprint.buffer_num; -#endif - /* record the reference list*/ - strcpy(p_outdata->str_reference_list, hc->str_list_reference); - -#if !REF_OUTPUT - #error "!!!REF_OUTPUT should be 1" - for (i = 0; i < avs2_dec->outprint.buffer_num; i++) { - min_tr(avs2_dec->outprint, &pos); - if (avs2_dec->outprint.stdoutdata[pos].tr < img->tr - || avs2_dec->outprint.stdoutdata[pos].tr - == (hd->last_output + 1)) { - hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr; - report_frame(avs2_dec, &avs2_dec->outprint, pos); -#if 0 /*def ORI*/ - write_frame(hd->p_out, - avs2_dec->outprint.stdoutdata[pos].tr); -#endif - delete_trbuffer(&avs2_dec->outprint, pos); - i--; - } else { - break; - } - } -#else -#if RD160_FIX_BG /*Longfei.Wang@mediatek.com*/ - tmp_min = 1 << 20; - i = 0, j = 0; - output_cur_dec_pic = 0; - pos = -1; - for (j = 0; j < search_times; j++) { - pos = -1; - tmp_min = (1 << 20); - /*search for min poi picture to display*/ - for (i = 0; i < avs2_dec->outprint.buffer_num; i++) { - if ((avs2_dec->outprint.stdoutdata[i].tr < tmp_min) && - ((avs2_dec->outprint.stdoutdata[i].tr - + avs2_dec->outprint.stdoutdata[i]. - picture_reorder_delay) - <= (int32_t)img->coding_order)) { - pos = i; - tmp_min = avs2_dec->outprint.stdoutdata[i].tr; - } - } - - if ((0 == hd->displaydelay) && (0 == output_cur_dec_pic)) { - if (img->tr <= tmp_min) {/*fred.chiu@mediatek.com*/ - /*output current decode picture - right now*/ - pos = avs2_dec->outprint.buffer_num - 1; - output_cur_dec_pic = 1; - } - } - if (pos != -1) { - hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr; - report_frame(avs2_dec, &avs2_dec->outprint, pos); -#if 1 /*def ORI*/ - if (avs2_dec->outprint.stdoutdata[pos].typeb - == BACKGROUND_IMG && - avs2_dec->outprint.stdoutdata[pos]. - background_picture_output_flag == 0) { - /**/ - /**/ - } else { - write_frame(avs2_dec, - avs2_dec->outprint.stdoutdata[pos].tr); - } -#endif - delete_trbuffer(&avs2_dec->outprint, pos); - } - - } - -#else - #error "!!!RD160_FIX_BG should be defined" - if (img->coding_order + - (uint32_t)hc->total_frames * 256 >= - (uint32_t)hd->picture_reorder_delay) { - int32_t tmp_min, pos = -1; - tmp_min = 1 << 20; - - for (i = 0; i < - avs2_dec->outprint.buffer_num; i++) { - if (avs2_dec->outprint.stdoutdata[i].tr - < tmp_min && - avs2_dec->outprint.stdoutdata[i].tr - >= hd->last_output) { - /*GB has the same "tr" with "last_output"*/ - pos = i; - tmp_min = - avs2_dec->outprint.stdoutdata[i].tr; - } - } - - if (pos != -1) { - hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr; - report_frame(avs2_dec, &avs2_dec->outprint, pos); -#if RD1501_FIX_BG - if (avs2_dec->outprint.stdoutdata[pos].typeb - == BACKGROUND_IMG && avs2_dec-> - outprint.stdoutdata[pos]. - background_picture_output_flag == 0) { -#else - if (avs2_dec->outprint.stdoutdata[pos].typeb - == BACKGROUND_IMG && - hd->background_picture_output_flag - == 0) { -#endif - write_GB_frame( - hd->p_out_background); - } else { - write_frame(avs2_dec, - avs2_dec->outprint.stdoutdata[pos].tr); - } - delete_trbuffer(&avs2_dec->outprint, pos); - - } - - } -#endif -#endif - return pos; - - } - -void write_frame(struct avs2_decoder *avs2_dec, int32_t pos) -{ - int32_t j; - - if (is_avs2_print_bufmgr_detail()) - pr_info("%s(pos = %d)\n", __func__, pos); - - for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { - if (avs2_dec->fref[j]->imgtr_fwRefDistance == pos) { - avs2_dec->fref[j]->imgtr_fwRefDistance_bak = pos; - avs2_dec->fref[j]->is_output = -1; - avs2_dec->fref[j]->to_prepare_disp = - avs2_dec->to_prepare_disp_count++; - if (avs2_dec->fref[j]->refered_by_others == 0 - || avs2_dec->fref[j]->imgcoi_ref - == -257) { - avs2_dec->fref[j]->imgtr_fwRefDistance - = -256; - avs2_dec->fref[j]->imgcoi_ref = -257; -#if M3480_TEMPORAL_SCALABLE - avs2_dec->fref[j]->temporal_id = -1; -#endif - if (is_avs2_print_bufmgr_detail()) - pr_info("%s, fref index %d\n", - __func__, j); - } - break; - } - } -} - -/*rain???, outdata *data*/ -void report_frame(struct avs2_decoder *avs2_dec, - struct outdata_s *data, int32_t pos) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - - int8_t *Frmfld; - int8_t Frm[] = "FRM"; - int8_t Fld[] = "FLD"; - struct STDOUT_DATA_s *p_stdoutdata - = &data->stdoutdata[pos]; - const int8_t *typ; - -#if 0 - if (input->MD5Enable & 0x02) { - sprintf(MD5str, "%08X%08X%08X%08X\0", - p_stdoutdata->DecMD5Value[0], - p_stdoutdata->DecMD5Value[1], - p_stdoutdata->DecMD5Value[2], - p_stdoutdata->DecMD5Value[3]); - } else { - memset(MD5val, 0, 16); - memset(MD5str, 0, 33); - } -#endif - - if (p_stdoutdata-> - picture_structure) { - Frmfld = Frm; - } else { - Frmfld = Fld; - } -#if INTERLACE_CODING - if (img->is_field_sequence) { /*rcs??*/ - Frmfld = Fld; - } -#endif - if ((p_stdoutdata->tr + hc->total_frames * 256) - == hd->end_SeqTr) { /* I picture*/ - /*if ( img->new_sequence_flag == 1 )*/ - { - img->sequence_end_flag = 0; - /*fprintf(stdout, "Sequence - End\n\n");*/ - } - } - if ((p_stdoutdata->tr + hc->total_frames * 256) - == hd->next_IDRtr) { -#if !RD170_FIX_BG - if (hd->vec_flag) /**/ -#endif - { - hd->vec_flag = 0; - /*fprintf(stdout, "Video Edit - Code\n");*/ - } - } - - if (p_stdoutdata->typeb == BACKGROUND_IMG) { - typ = (hd->background_picture_output_flag != 0) ? "G" : "GB"; - } else { -#if REMOVE_UNUSED - typ = (p_stdoutdata->type == INTRA_IMG) - ? "I" : (p_stdoutdata->type == INTER_IMG) ? - ((p_stdoutdata->typeb == BP_IMG) ? "S" : "P") - : (p_stdoutdata->type == F_IMG ? "F" : "B"); -#else - typ = (p_stdoutdata->type == INTRA_IMG) ? "I" : - (p_stdoutdata->type == INTER_IMG) ? - ((p_stdoutdata->type == BP_IMG) ? "S" : "P") - : (p_stdoutdata->type == F_IMG ? "F" : "B"); -#endif - } - -#if 0 - /*rain???*/ - pr_info("%3d(%s) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\t%s", - p_stdoutdata->framenum + hc->total_frames * 256, - typ, p_stdoutdata->tr + hc->total_frames * 256, - p_stdoutdata->qp, p_stdoutdata->snr_y, - p_stdoutdata->snr_u, p_stdoutdata->snr_v, - p_stdoutdata->tmp_time, Frmfld, - p_stdoutdata->curr_frame_bits, - p_stdoutdata->emulate_bits, - ""); -#endif - if (is_avs2_print_bufmgr_detail()) - pr_info(" %s\n", p_stdoutdata->str_reference_list); - - /*fflush(stdout);*/ - hd->FrameNum++; -} - -void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - - switch (start_code) { - case SEQUENCE_HEADER_CODE: - img->new_sequence_flag = 1; - if (is_avs2_print_bufmgr_detail()) - pr_info("SEQUENCE\n"); -#ifdef TO_CHECK -#if SEQ_CHANGE_CHECKER - if (seq_checker_buf == NULL) { - seq_checker_buf = malloc(length); - seq_checker_length = length; - memcpy(seq_checker_buf, Buf, length); - } else { - if ((seq_checker_length != length) || - (memcmp(seq_checker_buf, Buf, length) != 0)) { - free(seq_checker_buf); - /*fprintf(stdout, - "Non-conformance - stream: sequence - header cannot change - !!\n");*/ -#if RD170_FIX_BG - seq_checker_buf = NULL; - seq_checker_length = 0; - seq_checker_buf = malloc(length); - seq_checker_length = length; - memcpy(seq_checker_buf, Buf, length); -#endif - } - - - } -#endif -#if RD170_FIX_BG - if (input->alf_enable - && alfParAllcoated == 1) { - ReleaseAlfGlobalBuffer(); - alfParAllcoated = 0; - } -#endif -/*TO_CHECK*/ -#endif -#if FIX_FLUSH_DPB_BY_LF - if (hd->vec_flag) { - int32_t k; - if (is_avs2_print_bufmgr_detail()) - pr_info("vec_flag is 1, flushDPB and reinit bugmgr\n"); - - flushDPB(avs2_dec); - for (k = 0; k < avs2_dec->ref_maxbuffer; k++) - cleanRefMVBufRef(k); - - hd->vec_flag = 0; -#ifdef AML - free_unused_buffers(avs2_dec); -#else - free_global_buffers(avs2_dec); -#endif - img->number = 0; - img->PrevPicDistanceLsb = 0; - avs2_dec->init_hw_flag = 0; - } -#endif - -#if FIX_SEQ_END_FLUSH_DPB_BY_LF - if (img->new_sequence_flag - && img->sequence_end_flag) { - int32_t k; - if (is_avs2_print_bufmgr_detail()) - pr_info( - "new_sequence_flag after sequence_end_flag, flushDPB and reinit bugmgr\n"); - flushDPB(avs2_dec); - for (k = 0; k < avs2_dec->ref_maxbuffer; k++) - cleanRefMVBufRef(k); - -#ifdef AML - free_unused_buffers(avs2_dec); -#else - free_global_buffers(avs2_dec); -#endif - img->number = 0; - img->PrevPicDistanceLsb = 0; - avs2_dec->init_hw_flag = 0; - } -#endif - img->seq_header_indicate = 1; - break; - case I_PICTURE_START_CODE: - if (is_avs2_print_bufmgr_detail()) - pr_info("PIC-I\n"); - Get_SequenceHeader(avs2_dec); - Get_I_Picture_Header(avs2_dec); - calc_picture_distance(avs2_dec); - Read_ALF_param(avs2_dec); - if (!img->seq_header_indicate) { - img->B_discard_flag = 1; - /*fprintf(stdout, " I - %3d\t\tDIDSCARD!!\n", - img->tr);*/ - break; - } - break; - case PB_PICTURE_START_CODE: - if (is_avs2_print_bufmgr_detail()) - pr_info("PIC-PB\n"); - Get_SequenceHeader(avs2_dec); - Get_PB_Picture_Header(avs2_dec); - calc_picture_distance(avs2_dec); - Read_ALF_param(avs2_dec); - /* xiaozhen zheng, 20071009*/ - if (!img->seq_header_indicate) { - img->B_discard_flag = 1; - - if (img->type == P_IMG) { - /*fprintf(stdout, " P - %3d\t\tDIDSCARD!!\n", - img->tr);*/ - } - if (img->type == F_IMG) { - /*fprintf(stdout, " F - %3d\t\tDIDSCARD!!\n", - img->tr);*/ - } else { - /*fprintf(stdout, " B - %3d\t\tDIDSCARD!!\n", - img->tr);*/ - } - - break; - } - - if (img->seq_header_indicate == 1 - && img->type != B_IMG) { - img->B_discard_flag = 0; - } - if (img->type == B_IMG && img->B_discard_flag == 1 - && !img->random_access_decodable_flag) { - /*fprintf(stdout, " B - %3d\t\tDIDSCARD!!\n", - img->tr);*/ - break; - } - - break; - case SEQUENCE_END_CODE: - if (is_avs2_print_bufmgr_detail()) - pr_info("SEQUENCE_END_CODE\n"); -#ifdef TO_CHECK -#if SEQ_CHANGE_CHECKER - if (seq_checker_buf != NULL) { - free(seq_checker_buf); - seq_checker_buf = NULL; - seq_checker_length = 0; - } -#endif -#endif -img->new_sequence_flag = 1; -img->sequence_end_flag = 1; -break; - case VIDEO_EDIT_CODE: - if (is_avs2_print_bufmgr_detail()) - pr_info("VIDEO_EDIT_CODE\n"); - /*video_edit_code_data(Buf, startcodepos, length);*/ - hd->vec_flag = 1; -#ifdef TO_CHECK -#if SEQ_CHANGE_CHECKER - if (seq_checker_buf != NULL) { - free(seq_checker_buf); - seq_checker_buf = NULL; - seq_checker_length = 0; - } -#endif -#endif - -break; - } -} - -#ifdef AML -static uint32_t log2i(uint32_t val) -{ - uint32_t ret = -1; - while (val != 0) { - val >>= 1; - ret++; - } - return ret; -} -#endif - -int32_t avs2_process_header(struct avs2_decoder *avs2_dec) -{ - struct inp_par *input = &avs2_dec->input; - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - int32_t lcu_x_num_div; - int32_t lcu_y_num_div; - - int32_t N8_SizeScale; - /*pr_info("%s\n", __func__);*/ - { - N8_SizeScale = 1; - - if (hd->horizontal_size % - (MIN_CU_SIZE * N8_SizeScale) != 0) { - img->auto_crop_right = - (MIN_CU_SIZE * N8_SizeScale) - - (hd->horizontal_size % - (MIN_CU_SIZE * N8_SizeScale)); - } else - img->auto_crop_right = 0; - -#if !INTERLACE_CODING - if (hd->progressive_sequence) /**/ -#endif - { - if (hd->vertical_size % - (MIN_CU_SIZE * N8_SizeScale) != 0) { - img->auto_crop_bottom = - (MIN_CU_SIZE * N8_SizeScale) - - (hd->vertical_size % - (MIN_CU_SIZE * N8_SizeScale)); - } else - img->auto_crop_bottom = 0; - } - - /* Reinit parameters (NOTE: need to do - before init_frame //*/ - img->width = - (hd->horizontal_size + img->auto_crop_right); - img->height = - (hd->vertical_size + img->auto_crop_bottom); - img->width_cr = (img->width >> 1); - - if (input->chroma_format == 1) - img->height_cr = (img->height >> 1); - - img->PicWidthInMbs = img->width / MIN_CU_SIZE; - img->PicHeightInMbs = img->height / MIN_CU_SIZE; - img->PicSizeInMbs = img->PicWidthInMbs * img->PicHeightInMbs; - img->max_mb_nr = (img->width * img->height) / - (MIN_CU_SIZE * MIN_CU_SIZE); - } - - if (img->new_sequence_flag && img->sequence_end_flag) { -#if 0/*RD170_FIX_BG //*/ - int32_t k; - flushDPB(); - for (k = 0; k < avs2_dec->ref_maxbuffer; k++) - cleanRefMVBufRef(k); - - free_global_buffers(); - img->number = 0; -#endif - hd->end_SeqTr = img->tr; - img->sequence_end_flag = 0; - } - if (img->new_sequence_flag) { - hd->next_IDRtr = img->tr; - hd->next_IDRcoi = img->coding_order; - img->new_sequence_flag = 0; - } -#if 0/*RD170_FIX_BG*/ - if (hd->vec_flag) { - int32_t k; - flushDPB(); - for (k = 0; k < avs2_dec->ref_maxbuffer; k++) - cleanRefMVBufRef(k); - - hd->vec_flag = 0; - free_global_buffers(); - img->number = 0; - } -#endif -/* allocate memory for frame buffers*/ -#if 0 -/* called in vavs2.c*/ - if (img->number == 0) - avs2_init_global_buffers(avs2_dec); -#endif - img->current_mb_nr = 0; - - init_frame(avs2_dec); - - img->types = img->type; /* jlzheng 7.15*/ - - if (img->type != B_IMG) { - hd->pre_img_type = img->type; - hd->pre_img_types = img->types; - } - -#ifdef AML - avs2_dec->lcu_size_log2 = log2i(avs2_dec->lcu_size); - lcu_x_num_div = (img->width/avs2_dec->lcu_size); - lcu_y_num_div = (img->height/avs2_dec->lcu_size); - avs2_dec->lcu_x_num = ((img->width % avs2_dec->lcu_size) == 0) ? - lcu_x_num_div : lcu_x_num_div+1; - avs2_dec->lcu_y_num = ((img->height % avs2_dec->lcu_size) == 0) ? - lcu_y_num_div : lcu_y_num_div+1; - avs2_dec->lcu_total = avs2_dec->lcu_x_num*avs2_dec->lcu_y_num; -#endif - return SOP; -} - -int avs2_post_process(struct avs2_decoder *avs2_dec) -{ - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - int32_t i; - int ret; - if (img->typeb == BACKGROUND_IMG && hd->background_picture_enable) { -#ifdef AML - for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { - if (avs2_dec->fref[i]->bg_flag != 0) { - avs2_dec->fref[i]->bg_flag = 0; - if (is_avs2_print_bufmgr_detail()) - pr_info( - "clear old BACKGROUND_IMG for index %d\r\n", - avs2_dec->fref[i]->index); - } - } - if (is_avs2_print_bufmgr_detail()) - pr_info( - "post_process: set BACKGROUND_IMG flag for %d\r\n", - hc->cur_pic->index); - avs2_dec->f_bg = hc->cur_pic; - hc->cur_pic->bg_flag = 1; -#endif - } - -#if BCBR - if (hd->background_picture_enable - && hd->bcbr_enable && img->number > 0) - updateBgReference(); -#endif - - if (img->typeb == BACKGROUND_IMG && - hd->background_picture_output_flag == 0) - hd->background_number++; - - if (img->type == B_IMG) { - avs2_dec->fref[0]->imgtr_fwRefDistance - = hd->trtmp; - } - - /* record the reference list information*/ - get_reference_list_info(avs2_dec, avs2_dec->hc.str_list_reference); - - /*pr_info("%s\n", __func__);*/ - ret = frame_postprocessing(avs2_dec); - -#if FIX_PROFILE_LEVEL_DPB_RPS_1 - /* delete the frame that will never be used*/ - { - int32_t i, j; - if (is_avs2_print_bufmgr_detail()) { - pr_info( - "%s, coding_order %d to remove %d buf: ", - __func__, - img->coding_order, - hd->curr_RPS.num_to_remove); - for (i = 0; i < hd->curr_RPS.num_to_remove; i++) - pr_info("%d ", hd->curr_RPS.remove_pic[i]); - pr_info("\n"); - } - for (i = 0; i < hd->curr_RPS.num_to_remove; i++) { - for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { - - if (avs2_dec->fref[j]->imgcoi_ref >= -256 - && avs2_dec->fref[j]->imgcoi_ref == - img->coding_order - - hd->curr_RPS.remove_pic[i]) - break; - } - if (j < avs2_dec->ref_maxbuffer) { /**/ -#if FIX_RPS_PICTURE_REMOVE -/* Label new frames as "un-referenced" */ - avs2_dec->fref[j]->refered_by_others = 0; - - /* remove frames which have been outputted */ - if (avs2_dec->fref[j]->is_output == -1) { - avs2_dec->fref[j]-> - imgtr_fwRefDistance = -256; - avs2_dec->fref[j]->imgcoi_ref = -257; - avs2_dec->fref[j]->temporal_id = -1; - - } -#else - avs2_dec->fref[j]->imgcoi_ref = -257; -#if M3480_TEMPORAL_SCALABLE - avs2_dec->fref[j]->temporal_id = -1; -#endif - if (avs2_dec->fref[j]->is_output == -1) { - avs2_dec->fref[j]->imgtr_fwRefDistance - = -256; - } -#endif - } - } - } -#endif - - - /*! TO 19.11.2001 Known Problem: for init_frame - * we have to know the picture type of the - * actual frame*/ - /*! in case the first slice of the P-Frame - * following the I-Frame was lost we decode this - * P-Frame but! do not write it because it - * was - * assumed to be an I-Frame in init_frame.So we - * force the decoder to*/ - /*! guess the right picture type. This is a hack - * a should be removed by the time there is a - * clean*/ - /*! solution where we do not have to know the - * picture type for the function init_frame.*/ - /*! End TO 19.11.2001//Lou*/ - - { - if (img->type == I_IMG || - img->type == P_IMG || - img->type == F_IMG) - img->number++; - else { - hc->Bframe_ctr++; /* B - pictures*/ - } - } - return ret; -} - -void init_avs2_decoder(struct avs2_decoder *avs2_dec) -{ - int32_t i, j, k; - - struct inp_par *input = &avs2_dec->input; - struct ImageParameters_s *img = &avs2_dec->img; - struct Video_Com_data_s *hc = &avs2_dec->hc; - struct Video_Dec_data_s *hd = &avs2_dec->hd; - if (is_avs2_print_bufmgr_detail()) - pr_info("[t] struct avs2_dec @0x%p\n", avs2_dec); - memset(avs2_dec, 0, sizeof(struct avs2_decoder)); -#ifdef AML - avs2_dec->to_prepare_disp_count = 1; -#endif - /* - * ALFParam init - */ - for (i = 0; i < 3; i++) { - avs2_dec->m_alfPictureParam[i].alf_flag = 0; /*1*/ - avs2_dec->m_alfPictureParam[i].num_coeff = 9; /*1*/ - avs2_dec->m_alfPictureParam[i].filters_per_group = 3; /*1*/ - avs2_dec->m_alfPictureParam[i].componentID = i; /*1*/ - for (j = 0; j < 16; j++) { - avs2_dec->m_alfPictureParam[i].filterPattern[j] = 0; - /*16*/ - } - for (j = 0; j < 16; j++) { - for (k = 0; k < 9; k++) { - avs2_dec-> - m_alfPictureParam[i].coeffmulti[j][k] = 0; - /*16*9*/ - } - } - } - - img->seq_header_indicate = 0; - img->B_discard_flag = 0; - - hd->eos = 0; - - if (input->ref_pic_order) { /*ref order*/ - hd->dec_ref_num = 0; - } - - /* - memset(g_log2size, -1, MAX_CU_SIZE + 1); - c = 2; - for (k = 4; k <= MAX_CU_SIZE; k *= 2) { - g_log2size[k] = c; - c++; - } - */ - - avs2_dec->outprint.buffer_num = 0; - - hd->last_output = -1; - hd->end_SeqTr = -1; - hd->curr_IDRtr = 0; - hd->curr_IDRcoi = 0; - hd->next_IDRtr = 0; - hd->next_IDRcoi = 0; - /* Allocate Slice data struct*/ - img->number = 0; - img->type = I_IMG; - - img->imgtr_next_P = 0; - - img->imgcoi_next_ref = 0; - - - img->num_of_references = 0; - hc->seq_header = 0; - - img->new_sequence_flag = 1; - - hd->vec_flag = 0; - - hd->FrameNum = 0; - - /* B pictures*/ - hc->Bframe_ctr = 0; - hc->total_frames = 0; - - /* time for total decoding session*/ - hc->tot_time = 0; - -} - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h deleted file mode 100644 index e6c28cfddb6b..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h +++ /dev/null @@ -1,1681 +0,0 @@ -/* The copyright in this software is being made available under the BSD - * License, included below. This software may be subject to other third party - * and contributor rights, including patent rights, and no such rights are - * granted under this license. - * - * Copyright (c) 2002-2016, Audio Video coding Standard Workgroup of China - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of Audio Video coding Standard Workgroup of China - * nor the names of its contributors maybe - * used to endorse or promote products - * derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - - - -/* - * File name: global.h - * Function: global definitions for for AVS decoder. - * - */ - -#ifndef _GLOBAL_H_ -#define _GLOBAL_H_ - -/* #include //!< for FILE */ -/* #include */ - -#define AML -#define SANITY_CHECK -#undef NO_DISPLAY - -/* #include "define.h" */ -#define RD "19.2" -#define VERSION "19.2" - -#define RESERVED_PROFILE_ID 0x24 -#define BASELINE_PICTURE_PROFILE 18 -#define BASELINE_PROFILE 32 /* 0x20 */ -#define BASELINE10_PROFILE 34 /* 0x22 */ - - -#define SCENE_PROFILE 48 /* 0x21 */ -#define SCENE10_PROFILE 50 /* 0x23 */ - -#define TRACE 0 /* !< 0:Trace off 1:Trace on */ - - -/* Type definitions and file operation for Windows/Linux - * All file operations for windows are replaced with native (FILE *) operations - * Falei LUO (falei.luo@vipl.ict.ac.cn) - * */ - -#define _FILE_OFFSET_BITS 64 /* for 64 bit fseeko */ -#define fseek fseeko - -#define int16 int16_t -#define int64 int64_t - -/* ////////////////// bug fix ///////////////////////////// */ -#define ALFSliceFix 1 -#define WRITENBIT_FIX 1 -#define FIX_PROFILE_LEVEL_DPB_RPS_1 1 -#define FIX_PROFILE_LEVEL_DPB_RPS_2 1 -#define FIX_RPS_PICTURE_REMOVE 1 /* flluo@pku.edu.cn */ -#define Mv_Clip 1 /* yuquanhe@hisilicon.com */ -#define REMOVE_UNUSED 1 /* yuquanhe@hisilicon.com */ -#define SAO_Height_Fix 1 /* yuquanhe@hisilicon.com */ -#define B_BACKGROUND_Fix 1 /* yuquanhe@hisilicon.com */ -#define Check_Bitstream 1 /* yuquanhe@hisilicon.com */ -#define Wq_param_Clip 1 /* yuquanhe@hisilicon.com */ - /* luofalei flluo@pku.edu.cn , wlq15@mails.tsinghua.edu.cn , - Longfei.Wang@mediatek.com */ -#define RD1501_FIX_BG 1 - /* yuquanhe@hisilicon.com ; he-yuan.lin@mstarsemi.com */ -#define Mv_Rang 1 - /* Longfei.Wang@mediatek.com ;fred.chiu@mediatek.com - jie1222.chen@samsung.com */ -#define RD160_FIX_BG 1 - /* Y_K_Tu@novatek.com.tw, he-yuan.lin@mstarsemi.com, - victor.huang@montage-tech.com M4041 */ -#define RD1601_FIX_BG 1 -#define SEQ_CHANGE_CHECKER 1 /* he-yuan.lin@mstarsemi.com */ -#define M4140_END_OF_SLICE_CHECKER 1 /* he-yuan.lin@mstarsemi.com */ - /* wlq15@mails.tsinghua.edu.cn */ -#define Mv_check_bug 1 -#define SAO_ASSERTION_FIX 1 /* fred.chiu@mediatek.com */ -#define FIELD_HORI_MV_NO_SCALE_FIX 1 /* fred.chiu@mediatek.com */ -#define RD170_FIX_BG 1 -#define FIX_CHROMA_FIELD_MV_BK_DIST 1 -#define FIX_LUMA_FIELD_MV_BK_DIST 1 -#define FIX_CHROMA_FIELD_MV_CLIP 1 -#if 1 -#define FIX_FLUSH_DPB_BY_LF 1 /* fred.chiu@mediatek.com */ -#define FIX_SEQ_END_FLUSH_DPB_BY_LF 1 /* fred.chiu@mediatek.com */ -#else -#define FIX_FLUSH_DPB_BY_LF 0 /* fred.chiu@mediatek.com */ -#define FIX_SEQ_END_FLUSH_DPB_BY_LF 0 /* fred.chiu@mediatek.com */ -#endif -#define RD191_FIX_BUG 1 /* yuquanhe@hsilicon.com */ -#define SYM_MV_SCALE_FIX 1/* peisong.chen@broadcom.com */ -#define BUG_10BIT_REFINEQP 0 /* wangzhenyu */ - - - -#if RD191_FIX_BUG -#endif - -/************************ - * AVS2 macros start - **************************/ - -#define INTERLACE_CODING 1 -#if INTERLACE_CODING /* M3531: MV scaling compensation */ -/* Luma component */ -#define HALF_PIXEL_COMPENSATION 1 /* common functions definition */ -#define HALF_PIXEL_COMPENSATION_PMV 1 /* spacial MV prediction */ -#define HALF_PIXEL_COMPENSATION_DIRECT 1 /* B direct mode */ - /* MV derivation method 1, weighted P_skip mode */ -#define HALF_PIXEL_COMPENSATION_M1 1 - /* M1 related with mv-scaling function */ -#define HALF_PIXEL_COMPENSATION_M1_FUCTION 1 -#define HALF_PIXEL_COMPENSATION_MVD 1 /* MV scaling from FW->BW */ -/* Chroma components */ - /* chroma MV is scaled with luma MV for 4:2:0 format */ -#define HALF_PIXEL_CHROMA 1 - /* half pixel compensation for p skip/direct */ -#define HALF_PIXEL_PSKIP 1 -#define INTERLACE_CODING_FIX 1 /* HLS fix */ -#define OUTPUT_INTERLACE_MERGED_PIC 1 - -#endif -/* - ******************************* -AVS2 10bit/12bit profile - ******************************** - */ - -#define DBFIX_10bit 1 - -#define BUG_10bit 1 - -/* - *************************************** -AVS2 HIGH LEVEL SYNTAX - *************************************** - */ -#define AVS2_HDR_HLS 1 - /* AVS2 HDR technology //yuquanhe@hisilicon.com */ -#define AVS2_HDR_Tec 1 -#if AVS2_HDR_Tec -#define HDR_CHROMA_DELTA_QP 1 /* M3905 */ -#define HDR_ADPTIVE_UV_DELTA 1 -#endif -/* - ************************************* -AVS2 S2 - ************************************* - */ -#define AVS2_S2_FASTMODEDECISION 1 -#define RD1510_FIX_BG 1 /* 20160714, flluo@pku.edu.cn */ - - -/* ////////////////// prediction techniques ///////////////////////////// */ -#define LAM_2Level_TU 0.8 - - -#define DIRECTION 4 -#define DS_FORWARD 4 -#define DS_BACKWARD 2 -#define DS_SYM 3 -#define DS_BID 1 - -#define MH_PSKIP_NUM 4 -#define NUM_OFFSET 0 -#define BID_P_FST 1 -#define BID_P_SND 2 -#define FW_P_FST 3 -#define FW_P_SND 4 -#define WPM_NUM 3 - /* M3330 changes it to 2, the original value is 3 */ -#define MAX_MVP_CAND_NUM 2 - -#define DMH_MODE_NUM 5 /* Number of DMH mode */ -#define TH_ME 0 /* Threshold of ME */ - -#define MV_SCALE 1 - -/* ///// reference picture management // */ -#define FIX_MAX_REF 1 /* Falei LUO, flluo@pku.edu.cn */ -#if FIX_MAX_REF - /* maximum number of reference frame for each frame */ -#define MAXREF 7 -#define MAXGOP 32 -#endif - -/* #define REF_MAXBUFFER 7 */ -/* more bufferes for displaying and background */ -/* #define REF_MAXBUFFER 15 */ -#if 1 -#define REF_MAXBUFFER 23 -#define REF_BUFFER 16 -#else -#if RD170_FIX_BG -#define REF_MAXBUFFER 16 -#else -#define REF_MAXBUFFER 7 -#endif -#endif - -#ifdef TO_PORTING - /* block-composed background reference, fangdong@mail.ustc.edu.cn */ -#define BCBR 1 -#else -#define BCBR 0 -#endif -/* one more buffer for background when background_picture_output_flag is 0*/ -#define AVS2_MAX_BUFFER_NUM (REF_MAXBUFFER + 1) - -/* /////////////////Adaptive Loop Filter////////////////////////// */ -#define NUM_ALF_COEFF_CTX 1 -#define NUM_ALF_LCU_CTX 4 - -#define LAMBDA_SCALE_LUMA (1.0) -#define LAMBDA_SCALE_CHROMA (1.0) - - - -/* ////////////////// entropy coding ///////////////////////////// */ - /* M3090: Make sure rs1 will not overflow for 8-bit unsign char */ -#define NUN_VALUE_BOUND 254 -#define Encoder_BYPASS_Final 1 /* M3484 */ -#define Decoder_Bypass_Annex 0 /* M3484 */ -#define Decoder_Final_Annex 0 /* M3540 */ - - -/* ////////////////// coefficient coding ///// */ - /* M3035 size of an coefficient group, 4x4 */ -#define CG_SIZE 16 - -#define SWAP(x, y) {\ - (y) = (y) ^ (x);\ - (x) = (y) ^ (x);\ - (y) = (x) ^ (y);\ -} - -/* ////////////////// encoder optimization /////// */ -#define TH 2 - -#define M3624MDLOG /* reserved */ - -#define TDRDO 1 /* M3528 */ -/* #define FIX_TDRDO_BG 1 // flluo@pku.edu.cn, 20160318// */ -#define RATECONTROL 1 /* M3580 M3627 M3689 */ -#define AQPO 1 /* M3623 */ -#define AQPOM3694 0 -#define AQPOM4063 1 -#define AQPOM3762 1 -#define BGQPO 1 /* M4061 */ -#if BGQPO -#define LONGREFERENCE 32 -#endif - -/* #define REPORT */ -/* ////////////////// Quantization /////////////////////////////////////// */ - /* Adaptive frequency weighting quantization */ -#define FREQUENCY_WEIGHTING_QUANTIZATION 1 -#if FREQUENCY_WEIGHTING_QUANTIZATION -#define CHROMA_DELTA_QP 1 -#define AWQ_WEIGHTING 1 -#define AWQ_LARGE_BLOCK_ENABLE 1 -#define COUNT_BIT_OVERHEAD 0 -#define AWQ_LARGE_BLOCK_EXT_MAPPING 1 -#endif - -#define QuantClip 1 -#define QuantMatrixClipFix 1 /* 20160418, fllu@pku.edu.cn */ - -#define WQ_MATRIX_FCD 1 -#if !WQ_MATRIX_FCD -#define WQ_FLATBASE_INBIT 7 -#else -#define WQ_FLATBASE_INBIT 6 -#endif - - -#define REFINED_QP 1 - - -/* ////////////////// delta QP ///// */ - /* M3122: the minimum dQP unit is Macro block */ -#define MB_DQP 1 - /* M3122: 1 represents left prediction - and 0 represents previous prediction */ -#define LEFT_PREDICTION 1 - - -/* //////////////////////SAO///////// */ -#define NUM_BO_OFFSET 32 -#define MAX_NUM_SAO_CLASSES 32 -#define NUM_SAO_BO_CLASSES_LOG2 5 -#define NUM_SAO_BO_CLASSES_IN_BIT 5 -#define MAX_DOUBLE (1.7e + 308) -#define NUM_SAO_EO_TYPES_LOG2 2 -#define NUM_SAO_BO_CLASSES (1< (c) ? (c) : (a))) -#endif - - /* POC200301 moved from defines.h */ -#define LOG2_MAX_FRAME_NUM_MINUS4 4 - /* !< bytes for one frame */ -#define MAX_CODED_FRAME_SIZE 15000000 - -/* ----------------------- */ -/* FLAGS and DEFINES for new chroma intra prediction, Dzung Hoang */ -/* Threshold values to zero out quantized transform coefficients. */ -/* Recommend that _CHROMA_COEFF_COST_ be low to improve chroma quality */ -#define _LUMA_COEFF_COST_ 4 /* !< threshold for luma coeffs */ - /* !< Number of pixels padded around the reference frame (>=4) */ -#define IMG_PAD_SIZE 64 - -#define OUTSTRING_SIZE 255 - - /* !< abs macro, faster than procedure */ -#define absm(A) ((A) < (0) ? (-(A)) : (A)) - /* !< used for start value for some variables */ -#define MAX_VALUE 999999 - -#define Clip1(a) ((a) > 255 ? 255:((a) < 0 ? 0 : (a))) -#define Clip3(min, max, val) (((val) < (min)) ?\ - (min) : (((val) > (max)) ? (max) : (val))) - -/* --------------------------------------------- */ - -/* block size of block transformed by AVS */ -#define PSKIPDIRECT 0 -#define P2NX2N 1 -#define P2NXN 2 -#define PNX2N 3 -#define PHOR_UP 4 -#define PHOR_DOWN 5 -#define PVER_LEFT 6 -#define PVER_RIGHT 7 -#define PNXN 8 -#define I8MB 9 -#define I16MB 10 -#define IBLOCK 11 -#define InNxNMB 12 -#define INxnNMB 13 -#define MAXMODE 14 /* add yuqh 20130824 */ -#define LAMBDA_ACCURACY_BITS 16 -#define LAMBDA_FACTOR(lambda) ((int)((double)(1 << LAMBDA_ACCURACY_BITS)\ - * lambda + 0.5)) -#define WEIGHTED_COST(factor, bits) (((factor) * (bits))\ - >> LAMBDA_ACCURACY_BITS) -#define MV_COST(f, s, cx, cy, px, py) (WEIGHTED_COST(f, mvbits[((cx) << (s))\ - - px] + mvbits[((cy) << (s)) - py])) -#define REF_COST(f, ref) (WEIGHTED_COST(f, refbits[(ref)])) - -#define BWD_IDX(ref) (((ref) < 2) ? 1 - (ref) : (ref)) -#define REF_COST_FWD(f, ref) (WEIGHTED_COST(f,\ - ((img->num_ref_pic_active_fwd_minus1 == 0) ?\ - 0 : refbits[(ref)]))) -#define REF_COST_BWD(f, ef) (WEIGHTED_COST(f,\ - ((img->num_ref_pic_active_bwd_minus1 == 0) ?\ - 0 : BWD_IDX(refbits[ref])))) - -#define IS_INTRA(MB) ((MB)->cuType == I8MB ||\ - (MB)->cuType == I16MB ||\ - (MB)->cuType == InNxNMB || (MB)->cuType == INxnNMB) -#define IS_INTER(MB) ((MB)->cuType != I8MB &&\ - (MB)->cuType != I16MB && (MB)->cuType != InNxNMB\ - && (MB)->cuType != INxnNMB) -#define IS_INTERMV(MB) ((MB)->cuType != I8MB &&\ - (MB)->cuType != I16MB && (MB)->cuType != InNxNMB &&\ - (MB)->cuType != INxnNMB && (MB)->cuType != 0) - - -#define IS_DIRECT(MB) ((MB)->cuType == PSKIPDIRECT && (img->type == B_IMG)) -#define IS_P_SKIP(MB) ((MB)->cuType == PSKIPDIRECT &&\ - (((img->type == F_IMG)) || ((img->type == P_IMG)))) -#define IS_P8x8(MB) ((MB)->cuType == PNXN) - -/* Quantization parameter range */ -#define MIN_QP 0 -#define MAX_QP 63 -#define SHIFT_QP 11 - -/* Picture types */ -#define INTRA_IMG 0 /* !< I frame */ -#define INTER_IMG 1 /* !< P frame */ -#define B_IMG 2 /* !< B frame */ -#define I_IMG 0 /* !< I frame */ -#define P_IMG 1 /* !< P frame */ -#define F_IMG 4 /* !< F frame */ - -#define BACKGROUND_IMG 3 - -#define BP_IMG 5 - - -/* Direct Mode types */ -#define MIN_CU_SIZE 8 -#define MIN_BLOCK_SIZE 4 -#define MIN_CU_SIZE_IN_BIT 3 -#define MIN_BLOCK_SIZE_IN_BIT 2 -#define BLOCK_MULTIPLE (MIN_CU_SIZE/(MIN_BLOCK_SIZE)) -#define MAX_CU_SIZE 64 -#define MAX_CU_SIZE_IN_BIT 6 -#define B4X4_IN_BIT 2 -#define B8X8_IN_BIT 3 -#define B16X16_IN_BIT 4 -#define B32X32_IN_BIT 5 -#define B64X64_IN_BIT 6 - /* !< # luma intra prediction modes */ -#define NUM_INTRA_PMODE 33 - /* number of luma modes for full RD search */ -#define NUM_MODE_FULL_RD 9 - /* !< #chroma intra prediction modes */ -#define NUM_INTRA_PMODE_CHROMA 5 - -/* luma intra prediction modes */ - -#define DC_PRED 0 -#define PLANE_PRED 1 -#define BI_PRED 2 -#define VERT_PRED 12 -#define HOR_PRED 24 - - -/* chroma intra prediction modes */ -#define DM_PRED_C 0 -#define DC_PRED_C 1 -#define HOR_PRED_C 2 -#define VERT_PRED_C 3 -#define BI_PRED_C 4 - -#define EOS 1 /* !< End Of Sequence */ - /* !< Start Of Picture */ -#define SOP 2 - -#define DECODING_OK 0 -#define SEARCH_SYNC 1 -#define DECODE_MB 1 - -#ifndef max - /* !< Macro returning max value */ -#define max(a, b) ((a) > (b) ? (a) : (b)) - /* !< Macro returning min value */ -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - - -#define XY_MIN_PMV 1 -#if XY_MIN_PMV -#define MVPRED_xy_MIN 0 -#else -#define MVPRED_MEDIAN 0 -#endif -#define MVPRED_L 1 -#define MVPRED_U 2 -#define MVPRED_UR 3 - -#define DUAL 4 -#define FORWARD 0 -#define BACKWARD 1 -#define SYM 2 -#define BID 3 -#define INTRA -1 - -#define BUF_CYCLE 5 - -#define ROI_M3264 1 /* ROI Information Encoding */ - -#define PicExtensionData 1 - - -#define REF_OUTPUT 1 /* M3337 */ - - -/* MV scaling 14 bit */ -#define MULTI 16384 -#define HALF_MULTI 8192 -#define OFFSET 14 -/* end of MV scaling */ - /* store the middle pixel's mv in a motion information unit */ -#define MV_DECIMATION_FACTOR 4 - -/* BUGFIX_AVAILABILITY_INTRA */ -#define NEIGHBOR_INTRA_LEFT 0 -#define NEIGHBOR_INTRA_UP 1 -#define NEIGHBOR_INTRA_UP_RIGHT 2 -#define NEIGHBOR_INTRA_UP_LEFT 3 -#define NEIGHBOR_INTRA_LEFT_DOWN 4 -/* end of BUGFIX_AVAILABILITY_INTRA */ - -/* end #include "define.h" */ - -/*#include "commonStructures.h"*/ - -/*typedef uint16_t byte;*/ /* !< byte type definition */ -#define byte uint16_t -#define pel_t byte - -enum BitCountType_e { - BITS_HEADER, - BITS_TOTAL_MB, - BITS_MB_MODE, - BITS_INTER_MB, - BITS_CBP_MB, - BITS_CBP01_MB, - BITS_COEFF_Y_MB, - BITS_COEFF_UV_MB, - BITS_DELTA_QUANT_MB, - BITS_SAO_MB, - MAX_BITCOUNTER_MB -}; - - -enum SAOEOClasses { -/* EO Groups, the assignments depended on -how you implement the edgeType calculation */ - SAO_CLASS_EO_FULL_VALLEY = 0, - SAO_CLASS_EO_HALF_VALLEY = 1, - SAO_CLASS_EO_PLAIN = 2, - SAO_CLASS_EO_HALF_PEAK = 3, - SAO_CLASS_EO_FULL_PEAK = 4, - SAO_CLASS_BO = 5, - NUM_SAO_EO_CLASSES = SAO_CLASS_BO, - NUM_SAO_OFFSET -}; - -struct SAOstatdata { - int32_t diff[MAX_NUM_SAO_CLASSES]; - int32_t count[MAX_NUM_SAO_CLASSES]; -}; - -struct CopyRight_s { - int32_t extension_id; - int32_t copyright_flag; - int32_t copyright_id; - int32_t original_or_copy; - int32_t reserved; - int32_t copyright_number; -}; - -struct CameraParamters_s { - int32_t reserved; - int32_t camera_id; - int32_t height_of_image_device; - int32_t focal_length; - int32_t f_number; - int32_t vertical_angle_of_view; - int32_t camera_position_x; - int32_t camera_position_y; - int32_t camera_position_z; - int32_t camera_direction_x; - int32_t camera_direction_y; - int32_t camera_direction_z; - int32_t image_plane_vertical_x; - int32_t image_plane_vertical_y; - int32_t image_plane_vertical_z; -}; - -/* ! SNRParameters */ -struct SNRParameters_s { - double snr_y; /* !< current Y SNR */ - double snr_u; /* !< current U SNR */ - double snr_v; /* !< current V SNR */ - double snr_y1; /* !< SNR Y(dB) first frame */ - double snr_u1; /* !< SNR U(dB) first frame */ - double snr_v1; /* !< SNR V(dB) first frame */ - double snr_ya; /* !< Average SNR Y(dB) remaining frames */ - double snr_ua; /* !< Average SNR U(dB) remaining frames */ - double snr_va; /* !< Average SNR V(dB) remaining frames */ -#if INTERLACE_CODING - double i_snr_ya; /* !< current Y SNR */ - double i_snr_ua; /* !< current U SNR */ - double i_snr_va; /* !< current V SNR */ -#endif -}; - -/* signal to noise ratio parameters */ - -/* ! codingUnit */ -struct codingUnit { - uint32_t ui_MbBitSize; - int32_t uiBitSize; /* size of MB */ - /* !< number of current syntax element */ - int32_t currSEnr; - int32_t slice_nr; - int32_t delta_quant; /* !< for rate control */ - int32_t delta_qp; - int32_t qp; - int32_t bitcounter[MAX_BITCOUNTER_MB]; - struct codingUnit - *mb_available[3][3]; /*!< pointer to neighboring MBs - in a 3x3 window of current MB, which is located at [1][1] \n - NULL pointer identifies neighboring MBs which are unavailable */ - /* some storage of codingUnit syntax elements for global access */ - int32_t cuType; - int32_t weighted_skipmode; - - int32_t md_directskip_mode; - - int32_t trans_size; - int - /* !< indices correspond to [forw,backw][block_y][block_x][x,y, dmh] */ - mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][3]; - - int32_t intra_pred_modes[BLOCK_MULTIPLE * BLOCK_MULTIPLE]; - int32_t real_intra_pred_modes[BLOCK_MULTIPLE * BLOCK_MULTIPLE]; - int32_t l_ipred_mode; - int32_t cbp, cbp_blk; - uint32_t cbp_bits; - - int32_t b8mode[4]; - int32_t b8pdir[4]; - /* !< chroma intra prediction mode */ - int32_t c_ipred_mode; - - /* !< pointer to neighboring MB (AEC) */ - struct codingUnit *mb_available_up; - /* !< pointer to neighboring MB (AEC) */ - struct codingUnit *mb_available_left; - int32_t mbAddrA, mbAddrB, mbAddrC, mbAddrD; - /* ! -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include "avs2_global.h" - -#define MEM_NAME "codec_avs2" -/* #include */ -#include -#include "../utils/vdec.h" -#include "../utils/amvdec.h" - -#include -#include -#include "../utils/config_parser.h" -#include "../utils/firmware.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" -#include -#include - -#define I_ONLY_SUPPORT -#define MIX_STREAM_SUPPORT -#define G12A_BRINGUP_DEBUG -#define CONSTRAIN_MAX_BUF_NUM - -#include "vavs2.h" -#define HEVC_SHIFT_LENGTH_PROTECT 0x313a -#define HEVC_MPRED_CTRL9 0x325b -#define HEVC_DBLK_CFGD 0x350d - - -#define HEVC_CM_HEADER_START_ADDR 0x3628 -#define HEVC_DBLK_CFGB 0x350b -#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 -#define HEVC_SAO_MMU_VH1_ADDR 0x363b -#define HEVC_SAO_MMU_VH0_ADDR 0x363a -#define HEVC_SAO_MMU_STATUS 0x3639 - - -/* - * AVS2_DEC_STATUS define -*/ -/*internal*/ -#define AVS2_DEC_IDLE 0 -#define AVS2_SEQUENCE 1 -#define AVS2_I_PICTURE 2 -#define AVS2_PB_PICTURE 3 -#define AVS2_DISCARD_STARTCODE 4 -#define AVS2_DISCARD_NAL 4 - -#define AVS2_SLICE_DECODING 6 - -#define SWAP_IN_CMD 0x10 -#define SWAP_OUT_CMD 0x11 -#define SWAP_OUTIN_CMD 0x12 -#define SWAP_DONE 0x13 -#define SWAP_POST_INIT 0x14 - -/*head*/ -#define AVS2_HEAD_SEQ_READY 0x21 -#define AVS2_HEAD_PIC_I_READY 0x22 -#define AVS2_HEAD_PIC_PB_READY 0x23 -#define AVS2_HEAD_SEQ_END_READY 0x24 -#define AVS2_STARTCODE_SEARCH_DONE 0x25 - -/*pic done*/ -#define HEVC_DECPIC_DATA_DONE 0x30 -#define HEVC_DECPIC_DATA_ERROR 0x31 -#define HEVC_NAL_DECODE_DONE 0x32 -#define AVS2_DECODE_BUFEMPTY 0x33 -#define AVS2_DECODE_TIMEOUT 0x34 -#define AVS2_DECODE_OVER_SIZE 0x35 -#define AVS2_EOS 0x36 - -/*cmd*/ -#define AVS2_10B_DISCARD_NAL 0xf0 -#define AVS2_SEARCH_NEW_PIC 0xf1 -#define AVS2_ACTION_ERROR 0xfe -#define HEVC_ACTION_ERROR 0xfe -#define AVS2_ACTION_DONE 0xff -/*AVS2_DEC_STATUS end*/ - - -#define VF_POOL_SIZE 32 - -#undef pr_info -#define pr_info printk - -#define DECODE_MODE_SINGLE (0 | (0x80 << 24)) -#define DECODE_MODE_MULTI_STREAMBASE (1 | (0x80 << 24)) -#define DECODE_MODE_MULTI_FRAMEBASE (2 | (0x80 << 24)) - - -#define VP9_TRIGGER_FRAME_DONE 0x100 -#define VP9_TRIGGER_FRAME_ENABLE 0x200 - -/*#define MV_MEM_UNIT 0x240*/ -#define MV_MEM_UNIT 0x200 -/*--------------------------------------------------- - Include "parser_cmd.h" ----------------------------------------------------*/ -#define PARSER_CMD_SKIP_CFG_0 0x0000090b - -#define PARSER_CMD_SKIP_CFG_1 0x1b14140f - -#define PARSER_CMD_SKIP_CFG_2 0x001b1910 - - -#define PARSER_CMD_NUMBER 37 - -static unsigned short parser_cmd[PARSER_CMD_NUMBER] = { -0x0401, -0x8401, -0x0800, -0x0402, -0x9002, -0x1423, -0x8CC3, -0x1423, -0x8804, -0x9825, -0x0800, -0x04FE, -0x8406, -0x8411, -0x1800, -0x8408, -0x8409, -0x8C2A, -0x9C2B, -0x1C00, -0x840F, -0x8407, -0x8000, -0x8408, -0x2000, -0xA800, -0x8410, -0x04DE, -0x840C, -0x840D, -0xAC00, -0xA000, -0x08C0, -0x08E0, -0xA40E, -0xFC00, -0x7C00 -}; - -static int32_t g_WqMDefault4x4[16] = { - 64, 64, 64, 68, - 64, 64, 68, 72, - 64, 68, 76, 80, - 72, 76, 84, 96 -}; - - -static int32_t g_WqMDefault8x8[64] = { - 64, 64, 64, 64, 68, 68, 72, 76, - 64, 64, 64, 68, 72, 76, 84, 92, - 64, 64, 68, 72, 76, 80, 88, 100, - 64, 68, 72, 80, 84, 92, 100, 112, - 68, 72, 80, 84, 92, 104, 112, 128, - 76, 80, 84, 92, 104, 116, 132, 152, - 96, 100, 104, 116, 124, 140, 164, 188, - 104, 108, 116, 128, 152, 172, 192, 216 -}; -/*#define HEVC_PIC_STRUCT_SUPPORT*/ -/* to remove, fix build error */ - -/*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/ - -#define MULTI_INSTANCE_SUPPORT -/* #define ERROR_HANDLE_DEBUG */ - -#ifndef STAT_KTHREAD -#define STAT_KTHREAD 0x40 -#endif - -#ifdef MULTI_INSTANCE_SUPPORT -#define MAX_DECODE_INSTANCE_NUM 12 -#define MULTI_DRIVER_NAME "ammvdec_avs2" - -#define lock_buffer(dec, flags) \ - spin_lock_irqsave(&dec->buffer_lock, flags) - -#define unlock_buffer(dec, flags) \ - spin_unlock_irqrestore(&dec->buffer_lock, flags) - -static unsigned int max_decode_instance_num - = MAX_DECODE_INSTANCE_NUM; -static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM]; -static unsigned int run_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; -static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; - -#ifdef G12A_BRINGUP_DEBUG -static u32 decode_timeout_val = 200; -#else -static u32 decode_timeout_val = 200; -#endif -static int start_decode_buf_level = 0x8000; -#ifdef AVS2_10B_MMU -static u32 work_buf_size; /* = 24 * 1024 * 1024*/; -#else -static u32 work_buf_size = 32 * 1024 * 1024; -#endif - -static u32 mv_buf_margin; -static int pre_decode_buf_level = 0x1000; -static u32 again_threshold = 0x40; - - -/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ -/* double_write_mode: 0, no double write - 1, 1:1 ratio - 2, (1/4):(1/4) ratio - 4, (1/2):(1/2) ratio - 0x10, double write only -*/ -static u32 double_write_mode; - -#define DRIVER_NAME "amvdec_avs2" -#define MODULE_NAME "amvdec_avs2" -#define DRIVER_HEADER_NAME "amvdec_avs2_header" - - -#define PUT_INTERVAL (HZ/100) -#define ERROR_SYSTEM_RESET_COUNT 200 - -#define PTS_NORMAL 0 -#define PTS_NONE_REF_USE_DURATION 1 - -#define PTS_MODE_SWITCHING_THRESHOLD 3 -#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 - -#define DUR2PTS(x) ((x)*90/96) - -struct AVS2Decoder_s; -static int vavs2_vf_states(struct vframe_states *states, void *); -static struct vframe_s *vavs2_vf_peek(void *); -static struct vframe_s *vavs2_vf_get(void *); -static void vavs2_vf_put(struct vframe_s *, void *); -static int vavs2_event_cb(int type, void *data, void *private_data); -static void set_vframe(struct AVS2Decoder_s *dec, - struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy); - -static int vavs2_stop(struct AVS2Decoder_s *dec); -static s32 vavs2_init(struct vdec_s *vdec); -static void vavs2_prot_init(struct AVS2Decoder_s *dec); -static int vavs2_local_init(struct AVS2Decoder_s *dec); -static void vavs2_put_timer_func(unsigned long arg); -static void dump_data(struct AVS2Decoder_s *dec, int size); -static unsigned char get_data_check_sum - (struct AVS2Decoder_s *dec, int size); -static void dump_pic_list(struct AVS2Decoder_s *dec); - -static const char vavs2_dec_id[] = "vavs2-dev"; - -#define PROVIDER_NAME "decoder.avs2" -#define MULTI_INSTANCE_PROVIDER_NAME "vdec.avs2" - -static const struct vframe_operations_s vavs2_vf_provider = { - .peek = vavs2_vf_peek, - .get = vavs2_vf_get, - .put = vavs2_vf_put, - .event_cb = vavs2_event_cb, - .vf_states = vavs2_vf_states, -}; - -static struct vframe_provider_s vavs2_vf_prov; - -static u32 bit_depth_luma; -static u32 bit_depth_chroma; -static u32 frame_width; -static u32 frame_height; -static u32 video_signal_type; -static u32 pts_unstable; -static u32 on_no_keyframe_skiped; - -static u32 force_video_signal_type; -static u32 enable_force_video_signal_type; -#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 - -static const char * const video_format_names[] = { - "component", "PAL", "NTSC", "SECAM", - "MAC", "unspecified", "Reserved", "Reserved" -}; - -static inline int div_r32(int64_t m, int n) -{ -/* -return (int)(m/n) -*/ -#ifndef CONFIG_ARM64 - int64_t qu = 0; - qu = div_s64(m, n); - return (int)qu; -#else - return (int)(m/n); -#endif -} - -enum vpx_bit_depth_t { - AVS2_BITS_8 = 8, /**< 8 bits */ - AVS2_BITS_10 = 10, /**< 10 bits */ - AVS2_BITS_12 = 12, /**< 12 bits */ -}; - -/*USE_BUF_BLOCK*/ -struct BUF_s { - int index; - unsigned int alloc_flag; - /*buffer */ - unsigned int cma_page_count; - unsigned long alloc_addr; - unsigned long start_adr; - unsigned int size; - - unsigned int free_start_adr; -} /*BUF_t */; - -struct MVBUF_s { - unsigned long start_adr; - unsigned int size; - int used_flag; -} /*MVBUF_t */; - - /* #undef BUFMGR_ONLY to enable hardware configuration */ - -/*#define TEST_WR_PTR_INC*/ -#define WR_PTR_INC_NUM 128 - -#define SIMULATION -#define DOS_PROJECT -#undef MEMORY_MAP_IN_REAL_CHIP - -/*#undef DOS_PROJECT*/ -/*#define MEMORY_MAP_IN_REAL_CHIP*/ - -/*#define BUFFER_MGR_ONLY*/ -/*#define CONFIG_HEVC_CLK_FORCED_ON*/ -/*#define ENABLE_SWAP_TEST*/ - -#ifdef AVS2_10B_NV21 -#define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/ -#else -#define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/ -#endif - -#ifdef AVS2_10B_NV21 -#else -#define LOSLESS_COMPRESS_MODE -#endif - -#define DOUBLE_WRITE_YSTART_TEMP 0x02000000 -#define DOUBLE_WRITE_CSTART_TEMP 0x02900000 - - - -typedef unsigned int u32; -typedef unsigned short u16; - -#define AVS2_DBG_BUFMGR 0x01 -#define AVS2_DBG_BUFMGR_MORE 0x02 -#define AVS2_DBG_BUFMGR_DETAIL 0x04 -#define AVS2_DBG_IRQ_EVENT 0x08 -#define AVS2_DBG_OUT_PTS 0x10 -#define AVS2_DBG_PRINT_SOURCE_LINE 0x20 -#define AVS2_DBG_PRINT_PARAM 0x40 -#define AVS2_DBG_PRINT_PIC_LIST 0x80 -#define AVS2_DBG_SEND_PARAM_WITH_REG 0x100 -#define AVS2_DBG_MERGE 0x200 -#define AVS2_DBG_DBG_LF_PRINT 0x400 -#define AVS2_DBG_REG 0x800 -#define AVS2_DBG_PIC_LEAK 0x1000 -#define AVS2_DBG_PIC_LEAK_WAIT 0x2000 -#define AVS2_DBG_HDR_INFO 0x4000 -#define AVS2_DBG_DIS_LOC_ERROR_PROC 0x10000 -#define AVS2_DBG_DIS_SYS_ERROR_PROC 0x20000 -#define AVS2_DBG_DUMP_PIC_LIST 0x40000 -#define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000 -#define AVS2_DBG_FORCE_UNCOMPRESS 0x100000 -#define AVS2_DBG_LOAD_UCODE_FROM_FILE 0x200000 -#define AVS2_DBG_FORCE_SEND_AGAIN 0x400000 -#define AVS2_DBG_DUMP_DATA 0x800000 -#define AVS2_DBG_DUMP_LMEM_BUF 0x1000000 -#define AVS2_DBG_DUMP_RPM_BUF 0x2000000 -#define AVS2_DBG_CACHE 0x4000000 -#define IGNORE_PARAM_FROM_CONFIG 0x8000000 -/*MULTI_INSTANCE_SUPPORT*/ -#define PRINT_FLAG_ERROR 0 -#define PRINT_FLAG_VDEC_STATUS 0x20000000 -#define PRINT_FLAG_VDEC_DETAIL 0x40000000 -#define PRINT_FLAG_VDEC_DATA 0x80000000 - -#define PRINT_LINE() \ - do { \ - if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\ - pr_info("%s line %d\n", __func__, __LINE__);\ - } while (0) - -static u32 debug; - -static u32 debug_again; - -bool is_avs2_print_param(void) -{ - bool ret = false; - if (debug & AVS2_DBG_PRINT_PARAM) - ret = true; - return ret; -} - -bool is_avs2_print_bufmgr_detail(void) -{ - bool ret = false; - if (debug & AVS2_DBG_BUFMGR_DETAIL) - ret = true; - return ret; -} -static bool is_reset; -/*for debug*/ -/* - udebug_flag: - bit 0, enable ucode print - bit 1, enable ucode detail print - bit [31:16] not 0, pos to dump lmem - bit 2, pop bits to lmem - bit [11:8], pre-pop bits for alignment (when bit 2 is 1) -*/ -static u32 udebug_flag; -/* - when udebug_flag[1:0] is not 0 - udebug_pause_pos not 0, - pause position -*/ -static u32 udebug_pause_pos; -/* - when udebug_flag[1:0] is not 0 - and udebug_pause_pos is not 0, - pause only when DEBUG_REG2 is equal to this val -*/ -static u32 udebug_pause_val; - -static u32 udebug_pause_decode_idx; - -static u32 force_disp_pic_index; - -#define DEBUG_REG -#ifdef DEBUG_REG -static void WRITE_VREG_DBG2(unsigned adr, unsigned val) -{ - if (debug & AVS2_DBG_REG) - pr_info("%s(%x, %x)\n", __func__, adr, val); - if (adr != 0) - WRITE_VREG(adr, val); -} - -#undef WRITE_VREG -#define WRITE_VREG WRITE_VREG_DBG2 -#endif - - -#ifdef AVS2_10B_MMU -#define MMU_COMPRESS_HEADER_SIZE 0x48000 -#define MMU_COMPRESS_8K_HEADER_SIZE 0x48000*4 -#endif - -#define INVALID_IDX -1 /* Invalid buffer index.*/ - - -#define FRAME_BUFFERS (AVS2_MAX_BUFFER_NUM) -#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS) -#define MAX_BUF_NUM (FRAME_BUFFERS) - -#define FRAME_CONTEXTS_LOG2 2 -#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) -/*buffer + header buffer + workspace*/ -#ifdef MV_USE_FIXED_BUF -#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1) -#define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) -#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1) -#else -#define MAX_BMMU_BUFFER_NUM (((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1) -#define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) -#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n+1) -#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1) -#endif -/* -static void set_canvas(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic); -int avs2_prepare_display_buf(struct AVS2Decoder_s *dec, - int pos); -*/ - - -struct buff_s { - u32 buf_start; - u32 buf_size; - u32 buf_end; -}; - -struct BuffInfo_s { - u32 max_width; - u32 max_height; - u32 start_adr; - u32 end_adr; - struct buff_s ipp; - struct buff_s sao_abv; - struct buff_s sao_vb; - struct buff_s short_term_rps; - struct buff_s rcs; - struct buff_s sps; - struct buff_s pps; - struct buff_s sao_up; - struct buff_s swap_buf; - struct buff_s swap_buf2; - struct buff_s scalelut; - struct buff_s dblk_para; - struct buff_s dblk_data; - struct buff_s dblk_data2; -#ifdef AVS2_10B_MMU - struct buff_s mmu_vbh; - struct buff_s cm_header; -#endif - struct buff_s mpred_above; -#ifdef MV_USE_FIXED_BUF - struct buff_s mpred_mv; -#endif - struct buff_s rpm; - struct buff_s lmem; -}; - -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_CONFIG_PARAM 3 -#define DEC_RESULT_ERROR 4 -#define DEC_INIT_PICLIST 5 -#define DEC_UNINIT_PICLIST 6 -#define DEC_RESULT_GET_DATA 7 -#define DEC_RESULT_GET_DATA_RETRY 8 -#define DEC_RESULT_EOS 9 -#define DEC_RESULT_FORCE_EXIT 10 - -static void avs2_work(struct work_struct *work); -struct loop_filter_info_n; -struct loopfilter; -struct segmentation; - -struct AVS2Decoder_s { - int pic_list_init_flag; - unsigned char index; - spinlock_t buffer_lock; - struct device *cma_dev; - struct platform_device *platform_dev; - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - struct vframe_chunk_s *chunk; - int dec_result; - struct work_struct work; - u32 start_shift_bytes; - - struct BuffInfo_s work_space_buf_store; - unsigned long buf_start; - u32 buf_size; - u32 cma_alloc_count; - unsigned long cma_alloc_addr; - uint8_t eos; - unsigned long int start_process_time; - unsigned last_lcu_idx; - int decode_timeout_count; - unsigned timeout_num; - - int double_write_mode; - - unsigned char m_ins_flag; - char *provider_name; - int frame_count; - u32 stat; - struct timer_list timer; - u32 frame_dur; - u32 frame_ar; - int fatal_error; - uint8_t init_flag; - uint8_t first_sc_checked; - uint8_t process_busy; -#define PROC_STATE_INIT 0 -#define PROC_STATE_HEAD_DONE 1 -#define PROC_STATE_DECODING 2 -#define PROC_STATE_HEAD_AGAIN 3 -#define PROC_STATE_DECODE_AGAIN 4 -#define PROC_STATE_TEST1 5 - uint8_t process_state; - u32 ucode_pause_pos; - - int show_frame_num; -#ifndef AVS2_10B_MMU - struct buff_s mc_buf_spec; -#endif - struct dec_sysinfo vavs2_amstream_dec_info; - void *rpm_addr; - void *lmem_addr; - dma_addr_t rpm_phy_addr; - dma_addr_t lmem_phy_addr; - unsigned short *lmem_ptr; - unsigned short *debug_ptr; - -#if 1 - /*AVS2_10B_MMU*/ - void *frame_mmu_map_addr; - dma_addr_t frame_mmu_map_phy_addr; -#endif - unsigned int use_cma_flag; - - struct BUF_s m_BUF[MAX_BUF_NUM]; - struct MVBUF_s m_mv_BUF[MAX_BUF_NUM]; - u32 used_buf_num; - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE); - struct vframe_s vfpool[VF_POOL_SIZE]; - u32 vf_pre_count; - u32 vf_get_count; - u32 vf_put_count; - int buf_num; - unsigned int losless_comp_body_size; - - u32 video_signal_type; - u32 video_ori_signal_type; - - int pts_mode; - int last_lookup_pts; - int last_pts; - u64 last_lookup_pts_us64; - u64 last_pts_us64; - u64 shift_byte_count; - u32 shift_byte_count_lo; - u32 shift_byte_count_hi; - int pts_mode_switching_count; - int pts_mode_recovery_count; - - bool get_frame_dur; - u32 saved_resolution; - - /**/ - int refresh_frame_flags; - uint8_t hold_ref_buf; - struct BuffInfo_s *work_space_buf; -#ifndef AVS2_10B_MMU - struct buff_s *mc_buf; -#endif - unsigned int frame_width; - unsigned int frame_height; - - unsigned short *rpm_ptr; - int init_pic_w; - int init_pic_h; - - int slice_type; - - int decode_idx; - int slice_idx; - uint8_t wait_buf; - uint8_t error_flag; - unsigned int bufmgr_error_count; - - /* bit 0, for decoding; bit 1, for displaying */ - uint8_t ignore_bufmgr_error; - uint8_t skip_PB_before_I; - int PB_skip_mode; - int PB_skip_count_after_decoding; - /*hw*/ - - /**/ - struct vdec_info *gvs; - - - unsigned int dec_status; - u32 last_put_idx; - int new_frame_displayed; - void *mmu_box; - void *bmmu_box; - struct vframe_master_display_colour_s vf_dp; - struct firmware_s *fw; -#ifdef AVS2_10B_MMU - int cur_fb_idx_mmu; - long used_4k_num; -#endif - struct avs2_decoder avs2_dec; -#define ALF_NUM_BIT_SHIFT 6 -#define NO_VAR_BINS 16 - int32_t m_filterCoeffSym[16][9]; - int32_t m_varIndTab[NO_VAR_BINS]; - - struct vframe_s vframe_dummy; - /* start_decoding_flag, - bit 0, SEQ ready - bit 1, I ready - */ - unsigned char start_decoding_flag; - uint32_t mpred_abv_start_addr; - uint32_t mpred_abv_start_addr_bak; - u8 next_again_flag; - u32 pre_parser_wr_ptr; - int need_cache_size; - u64 sc_start_time; -#ifdef I_ONLY_SUPPORT - u32 i_only; -#endif - int frameinfo_enable; - struct vframe_qos_s vframe_qos; -}; - -static int compute_losless_comp_body_size( - struct AVS2Decoder_s *dec, int width, int height, - uint8_t is_bit_depth_10); - -static int avs2_print(struct AVS2Decoder_s *dec, - int flag, const char *fmt, ...) -{ -#define HEVC_PRINT_BUF 256 - unsigned char buf[HEVC_PRINT_BUF]; - int len = 0; - if (dec == NULL || - (flag == 0) || - (debug & flag)) { - va_list args; - va_start(args, fmt); - if (dec) - len = sprintf(buf, "[%d]", dec->index); - vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); - pr_info("%s", buf); - va_end(args); - } - return 0; -} - -static int avs2_print_cont(struct AVS2Decoder_s *dec, - int flag, const char *fmt, ...) -{ - unsigned char buf[HEVC_PRINT_BUF]; - int len = 0; - if (dec == NULL || - (flag == 0) || - (debug & flag)) { - va_list args; - va_start(args, fmt); - vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); - pr_info("%s", buf); - va_end(args); - } - return 0; -} - -#define PROB_SIZE (496 * 2 * 4) -#define PROB_BUF_SIZE (0x5000) -#define COUNT_BUF_SIZE (0x300 * 4 * 4) -/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ -#define MAX_FRAME_4K_NUM 0x1200 -#define MAX_FRAME_8K_NUM 0x4800 -#define MAX_SIZE_4K (4096 * 2304) -#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) - -static int get_frame_mmu_map_size(struct AVS2Decoder_s *dec) -{ - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) - return (MAX_FRAME_8K_NUM * 4); - return (MAX_FRAME_4K_NUM * 4); -} - -static int get_compress_header_size(struct AVS2Decoder_s *dec) -{ - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) - return MMU_COMPRESS_8K_HEADER_SIZE; - return MMU_COMPRESS_HEADER_SIZE; -} - -static void reset_process_time(struct AVS2Decoder_s *dec) -{ - if (dec->start_process_time) { - unsigned process_time = - 1000 * (jiffies - dec->start_process_time) / HZ; - dec->start_process_time = 0; - if (process_time > max_process_time[dec->index]) - max_process_time[dec->index] = process_time; - } -} - -static void start_process_time(struct AVS2Decoder_s *dec) -{ - dec->start_process_time = jiffies; - dec->decode_timeout_count = 0; - dec->last_lcu_idx = 0; -} - -static void update_decoded_pic(struct AVS2Decoder_s *dec); - -static void timeout_process(struct AVS2Decoder_s *dec) -{ - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; - dec->timeout_num++; - amhevc_stop(); - avs2_print(dec, - 0, "%s decoder timeout\n", __func__); - if (cur_pic) - cur_pic->error_mark = 1; - dec->dec_result = DEC_RESULT_DONE; - update_decoded_pic(dec); - reset_process_time(dec); - vdec_schedule_work(&dec->work); -} - -static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec) -{ - return (dec->m_ins_flag && - ((double_write_mode & 0x80000000) == 0)) ? - dec->double_write_mode : - (double_write_mode & 0x7fffffff); -} - -static int get_double_write_mode(struct AVS2Decoder_s *dec) -{ - u32 valid_dw_mode = get_valid_double_write_mode(dec); - u32 dw; - if (valid_dw_mode == 0x100) { - int w = dec->avs2_dec.img.width; - int h = dec->avs2_dec.img.height; - if (w > 1920 && h > 1088) - dw = 0x4; /*1:2*/ - else - dw = 0x1; /*1:1*/ - - return dw; - } - - return valid_dw_mode; -} - -/* for double write buf alloc */ -static int get_double_write_mode_init(struct AVS2Decoder_s *dec) -{ - u32 valid_dw_mode = get_valid_double_write_mode(dec); - if (valid_dw_mode == 0x100) { - u32 dw; - int w = dec->init_pic_w; - int h = dec->init_pic_h; - if (w > 1920 && h > 1088) - dw = 0x4; /*1:2*/ - else - dw = 0x1; /*1:1*/ - - return dw; - } - return valid_dw_mode; -} - -static int get_double_write_ratio(struct AVS2Decoder_s *dec, - int dw_mode) -{ - int ratio = 1; - if ((dw_mode == 2) || - (dw_mode == 3)) - ratio = 4; - else if (dw_mode == 4) - ratio = 2; - return ratio; -} - -//#define MAX_4K_NUM 0x1200 -#ifdef AVS2_10B_MMU -int avs2_alloc_mmu( - struct AVS2Decoder_s *dec, - int cur_buf_idx, - int pic_width, - int pic_height, - unsigned short bit_depth, - unsigned int *mmu_index_adr) -{ - int bit_depth_10 = (bit_depth == AVS2_BITS_10); - int picture_size; - int cur_mmu_4k_number, max_frame_num; -#ifdef DYNAMIC_ALLOC_HEAD - unsigned long buf_addr; - struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; - if (pic->header_adr == 0) { - if (decoder_bmmu_box_alloc_buf_phy - (dec->bmmu_box, - HEADER_BUFFER_IDX(cur_buf_idx), - MMU_COMPRESS_HEADER_SIZE, - DRIVER_HEADER_NAME, - &buf_addr) < 0){ - avs2_print(dec, 0, - "%s malloc compress header failed %d\n", - DRIVER_HEADER_NAME, cur_buf_idx); - dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; - return -1; - } else - pic->header_adr = buf_addr; - } -#endif - - picture_size = compute_losless_comp_body_size( - dec, pic_width, pic_height, - bit_depth_10); - cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - max_frame_num = MAX_FRAME_8K_NUM; - else - max_frame_num = MAX_FRAME_4K_NUM; - if (cur_mmu_4k_number > max_frame_num) { - pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", - cur_mmu_4k_number, pic_width, pic_height); - return -1; - } - return decoder_mmu_box_alloc_idx( - dec->mmu_box, - cur_buf_idx, - cur_mmu_4k_number, - mmu_index_adr); -} -#endif - -#if 0 -/*ndef MV_USE_FIXED_BUF*/ -static void dealloc_mv_bufs(struct AVS2Decoder_s *dec) -{ - int i; - for (i = 0; i < FRAME_BUFFERS; i++) { - if (dec->m_mv_BUF[i].start_adr) { - if (debug) - pr_info( - "dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n", - i, dec->m_mv_BUF[i].start_adr, - dec->m_mv_BUF[i].size, - dec->m_mv_BUF[i].used_flag); - decoder_bmmu_box_free_idx( - dec->bmmu_box, - MV_BUFFER_IDX(i)); - dec->m_mv_BUF[i].start_adr = 0; - dec->m_mv_BUF[i].size = 0; - dec->m_mv_BUF[i].used_flag = 0; - } - } -} - -static int alloc_mv_buf(struct AVS2Decoder_s *dec, - int i, int size) -{ - int ret = 0; - if (decoder_bmmu_box_alloc_buf_phy - (dec->bmmu_box, - MV_BUFFER_IDX(i), size, - DRIVER_NAME, - &dec->m_mv_BUF[i].start_adr) < 0) { - dec->m_mv_BUF[i].start_adr = 0; - ret = -1; - } else { - dec->m_mv_BUF[i].size = size; - dec->m_mv_BUF[i].used_flag = 0; - ret = 0; - if (debug) { - pr_info( - "MV Buffer %d: start_adr %p size %x\n", - i, - (void *)dec->m_mv_BUF[i].start_adr, - dec->m_mv_BUF[i].size); - } - } - return ret; -} - -static int init_mv_buf_list(struct AVS2Decoder_s *dec) -{ - int i; - int ret = 0; - int count = FRAME_BUFFERS; - int pic_width = dec->init_pic_w; - int pic_height = dec->init_pic_h; - int lcu_size = 64; /*fixed 64*/ - int pic_width_64 = (pic_width + 63) & (~0x3f); - int pic_height_32 = (pic_height + 31) & (~0x1f); - int pic_width_lcu = (pic_width_64 % lcu_size) ? - pic_width_64 / lcu_size + 1 - : pic_width_64 / lcu_size; - int pic_height_lcu = (pic_height_32 % lcu_size) ? - pic_height_32 / lcu_size + 1 - : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; - int size = ((lcu_total * MV_MEM_UNIT) + 0xffff) & - (~0xffff); - if (mv_buf_margin > 0) - count = dec->avs2_dec.ref_maxbuffer + mv_buf_margin; - for (i = 0; i < count; i++) { - if (alloc_mv_buf(dec, i, size) < 0) { - ret = -1; - break; - } - } - return ret; -} -#if 0 - -static int get_mv_buf(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic) -{ - int i; - int ret = -1; - for (i = 0; i < FRAME_BUFFERS; i++) { - if (dec->m_mv_BUF[i].start_adr && - dec->m_mv_BUF[i].used_flag == 0) { - dec->m_mv_BUF[i].used_flag = 1; - ret = i; - break; - } - } - - if (ret >= 0) { - pic->mv_buf_index = ret; - pic->mpred_mv_wr_start_addr = - (dec->m_mv_BUF[ret].start_adr + 0xffff) & - (~0xffff); - if (debug & AVS2_DBG_BUFMGR_MORE) - pr_info( - "%s => %d (%d) size 0x%x\n", - __func__, ret, - pic->mpred_mv_wr_start_addr, - dec->m_mv_BUF[ret].size); - } else { - pr_info( - "%s: Error, mv buf is not enough\n", - __func__); - } - return ret; -} - -static void put_mv_buf(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic) -{ - int i = pic->mv_buf_index; - if (i >= FRAME_BUFFERS) { - if (debug & AVS2_DBG_BUFMGR_MORE) - pr_info( - "%s: index %d beyond range\n", - __func__, i); - return; - } - if (debug & AVS2_DBG_BUFMGR_MORE) - pr_info( - "%s(%d): used_flag(%d)\n", - __func__, i, - dec->m_mv_BUF[i].used_flag); - - pic->mv_buf_index = -1; - if (dec->m_mv_BUF[i].start_adr && - dec->m_mv_BUF[i].used_flag) - dec->m_mv_BUF[i].used_flag = 0; -} - -static void put_un_used_mv_bufs(struct AVS2Decoder_s *dec) -{ - struct VP9_Common_s *const cm = &dec->common; - struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; - int i; - for (i = 0; i < dec->used_buf_num; ++i) { - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.index != -1) && - (frame_bufs[i].buf.mv_buf_index >= 0) - ) - put_mv_buf(dec, &frame_bufs[i].buf); - } -} -#endif - -#endif - -static int get_free_buf_count(struct AVS2Decoder_s *dec) -{ - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - int i; - int count = 0; - for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { - if ((avs2_dec->fref[i]->imgcoi_ref < -256 -#if 0 - || abs(avs2_dec->fref[i]-> - imgtr_fwRefDistance - img->tr) >= 128 -#endif - ) && avs2_dec->fref[i]->is_output == -1 - && avs2_dec->fref[i]->bg_flag == 0 -#ifndef NO_DISPLAY - && avs2_dec->fref[i]->vf_ref == 0 - && avs2_dec->fref[i]->to_prepare_disp == 0 -#endif - ) { - count++; - } - } - - return count; -} - -#ifdef CONSTRAIN_MAX_BUF_NUM -static int get_vf_ref_only_buf_count(struct AVS2Decoder_s *dec) -{ - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - int i; - int count = 0; - for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { - if ((avs2_dec->fref[i]->imgcoi_ref < -256 -#if 0 - || abs(avs2_dec->fref[i]-> - imgtr_fwRefDistance - img->tr) >= 128 -#endif - ) && avs2_dec->fref[i]->is_output == -1 - && avs2_dec->fref[i]->bg_flag == 0 -#ifndef NO_DISPLAY - && avs2_dec->fref[i]->vf_ref > 0 - && avs2_dec->fref[i]->to_prepare_disp == 0 -#endif - ) { - count++; - } - } - - return count; -} - -static int get_used_buf_count(struct AVS2Decoder_s *dec) -{ - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - int i; - int count = 0; - for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { - if ((avs2_dec->fref[i]->imgcoi_ref >= -256 -#if 0 - || abs(avs2_dec->fref[i]-> - imgtr_fwRefDistance - img->tr) >= 128 -#endif - ) || avs2_dec->fref[i]->is_output != -1 - || avs2_dec->fref[i]->bg_flag != 0 -#ifndef NO_DISPLAY - || avs2_dec->fref[i]->vf_ref != 0 - || avs2_dec->fref[i]->to_prepare_disp != 0 -#endif - ) { - count++; - } - } - - return count; -} -#endif - -int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, - struct buff_s *mc_buf_i) { - - dec->frame_count = 0; -#ifdef AVS2_10B_MMU - dec->used_4k_num = -1; - dec->cur_fb_idx_mmu = INVALID_IDX; -#endif - - - /* private init */ - dec->work_space_buf = buf_spec_i; -#ifndef AVS2_10B_MMU - dec->mc_buf = mc_buf_i; -#endif - dec->rpm_addr = NULL; - dec->lmem_addr = NULL; - - dec->use_cma_flag = 0; - dec->decode_idx = 0; - dec->slice_idx = 0; - /*int m_uiMaxCUWidth = 1<<7;*/ - /*int m_uiMaxCUHeight = 1<<7;*/ - dec->wait_buf = 0; - dec->error_flag = 0; - dec->skip_PB_before_I = 0; - - dec->pts_mode = PTS_NORMAL; - dec->last_pts = 0; - dec->last_lookup_pts = 0; - dec->last_pts_us64 = 0; - dec->last_lookup_pts_us64 = 0; - dec->shift_byte_count = 0; - dec->shift_byte_count_lo = 0; - dec->shift_byte_count_hi = 0; - dec->pts_mode_switching_count = 0; - dec->pts_mode_recovery_count = 0; - - dec->buf_num = 0; - - dec->bufmgr_error_count = 0; - return 0; -} - - - -#define HEVC_CM_BODY_START_ADDR 0x3626 -#define HEVC_CM_BODY_LENGTH 0x3627 -#define HEVC_CM_HEADER_LENGTH 0x3629 -#define HEVC_CM_HEADER_OFFSET 0x362b - -#define LOSLESS_COMPRESS_MODE - -/*#define DECOMP_HEADR_SURGENT*/ - -static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ -static u32 enable_mem_saving = 1; -static u32 force_w_h; - -static u32 force_fps; - - -const u32 avs2_version = 201602101; -static u32 debug; -static u32 radr; -static u32 rval; -static u32 pop_shorts; -static u32 dbg_cmd; -static u32 dbg_skip_decode_index; -static u32 endian = 0xff0; -#ifdef ERROR_HANDLE_DEBUG -static u32 dbg_nal_skip_flag; - /* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */ -static u32 dbg_nal_skip_count; -#endif -/*for debug*/ -static u32 decode_pic_begin; -static uint slice_parse_begin; -static u32 step; -#ifdef MIX_STREAM_SUPPORT -static u32 buf_alloc_width = 4096; -static u32 buf_alloc_height = 2304; - -static u32 dynamic_buf_num_margin; -#else -static u32 buf_alloc_width; -static u32 buf_alloc_height; -static u32 dynamic_buf_num_margin = 7; -#endif -#ifdef CONSTRAIN_MAX_BUF_NUM -static u32 run_ready_max_vf_only_num; -static u32 run_ready_display_q_num; - /*0: not check - 0xff: avs2_dec.ref_maxbuffer - */ -static u32 run_ready_max_buf_num = 0xff; -#endif -static u32 buf_alloc_depth = 10; -static u32 buf_alloc_size; -/* -bit[0]: 0, - bit[1]: 0, always release cma buffer when stop - bit[1]: 1, never release cma buffer when stop -bit[0]: 1, when stop, release cma buffer if blackout is 1; -do not release cma buffer is blackout is not 1 - -bit[2]: 0, when start decoding, check current displayed buffer - (only for buffer decoded by vp9) if blackout is 0 - 1, do not check current displayed buffer - -bit[3]: 1, if blackout is not 1, do not release current - displayed cma buffer always. -*/ -/* set to 1 for fast play; - set to 8 for other case of "keep last frame" -*/ -static u32 buffer_mode = 1; -/* buffer_mode_dbg: debug only*/ -static u32 buffer_mode_dbg = 0xffff0000; -/**/ - -/* -bit 0, 1: only display I picture; -bit 1, 1: only decode I picture; -*/ -static u32 i_only_flag; - - -static u32 max_decoding_time; -/* -error handling -*/ -/*error_handle_policy: -bit 0: search seq again if buffer mgr error occur - (buffer mgr error count need big than - re_search_seq_threshold) -bit 1: 1, display from I picture; - 0, display from any correct pic -*/ - -static u32 error_handle_policy = 1; -/* -re_search_seq_threshold: - bit 7~0: buffer mgr error research seq count - bit 15~8: frame count threshold -*/ -static u32 re_search_seq_threshold = 0x800; /*0x8;*/ -/*static u32 parser_sei_enable = 1;*/ - -static u32 max_buf_num = (REF_BUFFER + 1); - -static u32 run_ready_min_buf_num = 2; - -static DEFINE_MUTEX(vavs2_mutex); - -#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 -#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 -#define AVS2_ALF_SWAP_BUFFER HEVC_ASSIST_SCRATCH_2 -#define HEVC_RCS_BUFFER HEVC_ASSIST_SCRATCH_3 -#define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 -#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 -#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 -#ifdef AVS2_10B_MMU -#define AVS2_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7 -#else -#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 -#endif -#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 -/* -#define VP9_PROB_SWAP_BUFFER HEVC_ASSIST_SCRATCH_9 -#define VP9_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A -#define VP9_SEG_MAP_BUFFER HEVC_ASSIST_SCRATCH_B -*/ -#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D -#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E -#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F -#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_9 -#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L -/*!!!*/ -#define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M -#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N -#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G -#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H - - -/* -ucode parser/search control -bit 0: 0, header auto parse; 1, header manual parse -bit 1: 0, auto skip for noneseamless stream; 1, no skip -bit [3:2]: valid when bit1==0; -0, auto skip nal before first vps/sps/pps/idr; -1, auto skip nal before first vps/sps/pps -2, auto skip nal before first vps/sps/pps, - and not decode until the first I slice (with slice address of 0) - -3, auto skip before first I slice (nal_type >=16 && nal_type<=21) -bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) ) -bit [16]: for NAL_UNIT_EOS when bit0 is 0: - 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm -bit [17]: for NAL_SEI when bit0 is 0: - 0, do not parse SEI in ucode; 1, parse SEI in ucode -bit [31:20]: used by ucode for debug purpose -*/ -#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I - /*DECODE_MODE: set before start decoder - bit 7~0: decode mode - bit 23~16: start_decoding_flag - bit [0] - SEQ_ready - bit [2:1] - I Picture Count - bit 31~24: chip feature - */ -#define DECODE_MODE HEVC_ASSIST_SCRATCH_J -#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K - /*read only*/ -#define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J - -#define RPM_BUF_SIZE (0x600 * 2) -#define LMEM_BUF_SIZE (0x600 * 2) - -#define WORK_BUF_SPEC_NUM 3 -static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = { - { - /* 8M bytes */ - .max_width = 1920, - .max_height = 1088, - .ipp = { - /* IPP work space calculation : - 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ - .buf_size = 0x4000, - }, - .sao_abv = { - .buf_size = 0x30000, - }, - .sao_vb = { - .buf_size = 0x30000, - }, - .short_term_rps = { - /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, - total 64x16x2 = 2048 bytes (0x800) */ - .buf_size = 0x800, - }, - .rcs = { - /* RCS STORE AREA - Max 32 RCS, each has 32 bytes, - total 0x0400 bytes */ - .buf_size = 0x400, - }, - .sps = { - /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - total 0x0800 bytes*/ - .buf_size = 0x800, - }, - .pps = { - /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, - total 0x2000 bytes*/ - .buf_size = 0x2000, - }, - .sao_up = { - /* SAO UP STORE AREA - Max 640(10240/16) LCU, - each has 16 bytes total 0x2800 bytes */ - .buf_size = 0x2800, - }, - .swap_buf = { - /* 256cyclex64bit = 2K bytes 0x800 - (only 144 cycles valid) */ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /* support up to 32 SCALELUT 1024x32 = - 32Kbytes (0x8000) */ - .buf_size = 0x8000, - }, - .dblk_para = { - /* DBLK -> Max 256(4096/16) LCU, - each para 1024bytes(total:0x40000), - data 1024bytes(total:0x40000)*/ - .buf_size = 0x40000, - }, - .dblk_data = { - .buf_size = 0x40000, - }, - .dblk_data2 = { - .buf_size = 0x40000, - }, -#ifdef AVS2_10B_MMU - .mmu_vbh = { - .buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/ - }, -#if 0 - .cm_header = { - /*add one for keeper.*/ - .buf_size = MMU_COMPRESS_HEADER_SIZE * - (FRAME_BUFFERS + 1), - /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ - }, -#endif -#endif - .mpred_above = { - .buf_size = 0x8000, /* 2 * size of hevc*/ - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = {/* 1080p, 0x40000 per buffer */ - .buf_size = 0x40000 * FRAME_BUFFERS, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x400 * 2, - } - }, - { - .max_width = 4096, - .max_height = 2304, - .ipp = { - /* IPP work space calculation : - 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ - .buf_size = 0x4000, - }, - .sao_abv = { - .buf_size = 0x30000, - }, - .sao_vb = { - .buf_size = 0x30000, - }, - .short_term_rps = { - /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, - total 64x16x2 = 2048 bytes (0x800) */ - .buf_size = 0x800, - }, - .rcs = { - /* RCS STORE AREA - Max 16 RCS, each has 32 bytes, - total 0x0400 bytes */ - .buf_size = 0x400, - }, - .sps = { - /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - total 0x0800 bytes */ - .buf_size = 0x800, - }, - .pps = { - /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, - total 0x2000 bytes */ - .buf_size = 0x2000, - }, - .sao_up = { - /* SAO UP STORE AREA - Max 640(10240/16) LCU, - each has 16 bytes total 0x2800 bytes */ - .buf_size = 0x2800, - }, - .swap_buf = { - /* 256cyclex64bit = 2K bytes 0x800 - (only 144 cycles valid) */ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /* support up to 32 SCALELUT 1024x32 = 32Kbytes - (0x8000) */ - .buf_size = 0x8000, - }, - .dblk_para = { - /* DBLK -> Max 256(4096/16) LCU, - each para 1024bytes(total:0x40000), - data 1024bytes(total:0x40000)*/ - .buf_size = 0x80000, - }, - .dblk_data = { - /*DBLK -> Max 256(4096/16) LCU, - each para 1024bytes(total:0x40000), - data 1024bytes(total:0x40000)*/ - .buf_size = 0x80000, - }, - .dblk_data2 = { - .buf_size = 0x80000, - }, -#ifdef AVS2_10B_MMU - .mmu_vbh = { - .buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/ - }, -#if 0 - .cm_header = { - /*add one for keeper.*/ - .buf_size = MMU_COMPRESS_HEADER_SIZE * - (FRAME_BUFFERS + 1), - /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ - }, -#endif -#endif - .mpred_above = { - .buf_size = 0x10000, /* 2 * size of hevc*/ - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = { - /* .buf_size = 0x100000*16, - //4k2k , 0x100000 per buffer */ - /* 4096x2304 , 0x120000 per buffer */ - .buf_size = 0x120000 * FRAME_BUFFERS, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x400 * 2, - } - }, - { - .max_width = 4096 * 2, - .max_height = 2304 * 2, - .ipp = { - /*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, - round to 16k*/ - .buf_size = 0x4000 * 2, - }, - .sao_abv = { - .buf_size = 0x30000 * 2, - }, - .sao_vb = { - .buf_size = 0x30000 * 2, - }, - .short_term_rps = { - /*SHORT_TERM_RPS - Max 64 set, 16 entry every set, - total 64x16x2 = 2048 bytes (0x800)*/ - .buf_size = 0x800, - }, - .rcs = { - /*RCS STORE AREA - Max 16 RCS, each has 32 bytes, - total 0x0400 bytes*/ - .buf_size = 0x400, - }, - .sps = { - /*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - total 0x0800 bytes*/ - .buf_size = 0x800, - }, - .pps = { - /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total - 0x2000 bytes*/ - .buf_size = 0x2000, - }, - .sao_up = { - /*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i - total 0x2800 bytes*/ - .buf_size = 0x2800 * 2, - }, - .swap_buf = { - /*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/ - .buf_size = 0x8000 * 2, - }, - .dblk_para = { - .buf_size = 0x40000 * 2, - }, - .dblk_data = { - .buf_size = 0x80000 * 2, - }, - .dblk_data2 = { - .buf_size = 0x80000 * 2, - }, -#ifdef AVS2_10B_MMU - .mmu_vbh = { - .buf_size = 0x5000 * 2, /*2*16*2304/4, 4K*/ - }, -#if 0 - .cm_header = { - /*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ - .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17, - }, -#endif -#endif - .mpred_above = { - .buf_size = 0x8000 * 2, - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = { - /*4k2k , 0x100000 per buffer*/ - .buf_size = 0x120000 * FRAME_BUFFERS * 4, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x400 * 2, - } - } -}; - - -/*Losless compression body buffer size 4K per 64x32 (jt)*/ -static int compute_losless_comp_body_size(struct AVS2Decoder_s *dec, - int width, int height, - uint8_t is_bit_depth_10) -{ - int width_x64; - int height_x32; - int bsize; - width_x64 = width + 63; - width_x64 >>= 6; - height_x32 = height + 31; - height_x32 >>= 5; -#ifdef AVS2_10B_MMU - bsize = (is_bit_depth_10 ? 4096 : 3200) - * width_x64 * height_x32; -#else - bsize = (is_bit_depth_10 ? 4096 : 3072) - * width_x64 * height_x32; -#endif - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s(%d,%d,%d)=>%d\n", - __func__, width, height, - is_bit_depth_10, bsize); - - return bsize; -} - -/* Losless compression header buffer size 32bytes per 128x64 (jt)*/ -static int compute_losless_comp_header_size(struct AVS2Decoder_s *dec, - int width, int height) -{ - int width_x128; - int height_x64; - int hsize; - width_x128 = width + 127; - width_x128 >>= 7; - height_x64 = height + 63; - height_x64 >>= 6; - - hsize = 32 * width_x128 * height_x64; - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s(%d,%d)=>%d\n", - __func__, width, height, - hsize); - - return hsize; -} - -static void init_buff_spec(struct AVS2Decoder_s *dec, - struct BuffInfo_s *buf_spec) -{ - void *mem_start_virt; - buf_spec->ipp.buf_start = buf_spec->start_adr; - buf_spec->sao_abv.buf_start = - buf_spec->ipp.buf_start + buf_spec->ipp.buf_size; - - buf_spec->sao_vb.buf_start = - buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size; - buf_spec->short_term_rps.buf_start = - buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size; - buf_spec->rcs.buf_start = - buf_spec->short_term_rps.buf_start + - buf_spec->short_term_rps.buf_size; - buf_spec->sps.buf_start = - buf_spec->rcs.buf_start + buf_spec->rcs.buf_size; - buf_spec->pps.buf_start = - buf_spec->sps.buf_start + buf_spec->sps.buf_size; - buf_spec->sao_up.buf_start = - buf_spec->pps.buf_start + buf_spec->pps.buf_size; - buf_spec->swap_buf.buf_start = - buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size; - buf_spec->swap_buf2.buf_start = - buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size; - buf_spec->scalelut.buf_start = - buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size; - buf_spec->dblk_para.buf_start = - buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size; - buf_spec->dblk_data.buf_start = - buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; - buf_spec->dblk_data2.buf_start = - buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; -#ifdef AVS2_10B_MMU - buf_spec->mmu_vbh.buf_start = - buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size; - buf_spec->mpred_above.buf_start = - buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; -#else - buf_spec->mpred_above.buf_start = - buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size; -#endif -#ifdef MV_USE_FIXED_BUF - buf_spec->mpred_mv.buf_start = - buf_spec->mpred_above.buf_start + - buf_spec->mpred_above.buf_size; - - buf_spec->rpm.buf_start = - buf_spec->mpred_mv.buf_start + - buf_spec->mpred_mv.buf_size; -#else - buf_spec->rpm.buf_start = - buf_spec->mpred_above.buf_start + - buf_spec->mpred_above.buf_size; - -#endif - buf_spec->lmem.buf_start = - buf_spec->rpm.buf_start + - buf_spec->rpm.buf_size; - buf_spec->end_adr = - buf_spec->lmem.buf_start + - buf_spec->lmem.buf_size; - - if (dec) { - mem_start_virt = - codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start); - if (mem_start_virt) { - memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size); - codec_mm_dma_flush(mem_start_virt, - buf_spec->dblk_para.buf_size, - DMA_TO_DEVICE); - } else { - /*not virt for tvp playing, - may need clear on ucode.*/ - pr_err("mem_start_virt failed\n"); - } - if (debug) { - pr_info("%s workspace (%x %x) size = %x\n", __func__, - buf_spec->start_adr, buf_spec->end_adr, - buf_spec->end_adr - buf_spec->start_adr); - } - if (debug) { - pr_info("ipp.buf_start :%x\n", - buf_spec->ipp.buf_start); - pr_info("sao_abv.buf_start :%x\n", - buf_spec->sao_abv.buf_start); - pr_info("sao_vb.buf_start :%x\n", - buf_spec->sao_vb.buf_start); - pr_info("short_term_rps.buf_start :%x\n", - buf_spec->short_term_rps.buf_start); - pr_info("rcs.buf_start :%x\n", - buf_spec->rcs.buf_start); - pr_info("sps.buf_start :%x\n", - buf_spec->sps.buf_start); - pr_info("pps.buf_start :%x\n", - buf_spec->pps.buf_start); - pr_info("sao_up.buf_start :%x\n", - buf_spec->sao_up.buf_start); - pr_info("swap_buf.buf_start :%x\n", - buf_spec->swap_buf.buf_start); - pr_info("swap_buf2.buf_start :%x\n", - buf_spec->swap_buf2.buf_start); - pr_info("scalelut.buf_start :%x\n", - buf_spec->scalelut.buf_start); - pr_info("dblk_para.buf_start :%x\n", - buf_spec->dblk_para.buf_start); - pr_info("dblk_data.buf_start :%x\n", - buf_spec->dblk_data.buf_start); - pr_info("dblk_data2.buf_start :%x\n", - buf_spec->dblk_data2.buf_start); - #ifdef AVS2_10B_MMU - pr_info("mmu_vbh.buf_start :%x\n", - buf_spec->mmu_vbh.buf_start); - #endif - pr_info("mpred_above.buf_start :%x\n", - buf_spec->mpred_above.buf_start); -#ifdef MV_USE_FIXED_BUF - pr_info("mpred_mv.buf_start :%x\n", - buf_spec->mpred_mv.buf_start); -#endif - if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) { - pr_info("rpm.buf_start :%x\n", - buf_spec->rpm.buf_start); - } - } - } - -} - -static void uninit_mmu_buffers(struct AVS2Decoder_s *dec) -{ -#if 0 -/*ndef MV_USE_FIXED_BUF*/ - dealloc_mv_bufs(dec); -#endif - decoder_mmu_box_free(dec->mmu_box); - dec->mmu_box = NULL; - - if (dec->bmmu_box) - decoder_bmmu_box_free(dec->bmmu_box); - dec->bmmu_box = NULL; -} - -#ifndef AVS2_10B_MMU -static void init_buf_list(struct AVS2Decoder_s *dec) -{ - int i; - int buf_size; - int mc_buffer_end = dec->mc_buf->buf_start + dec->mc_buf->buf_size; - dec->used_buf_num = max_buf_num; - - if (dec->used_buf_num > MAX_BUF_NUM) - dec->used_buf_num = MAX_BUF_NUM; - if (buf_alloc_size > 0) { - buf_size = buf_alloc_size; - avs2_print(dec, AVS2_DBG_BUFMGR, - "[Buffer Management] init_buf_list:\n"); - } else { - int pic_width = dec->init_pic_w; - int pic_height = dec->init_pic_h; - - /*SUPPORT_10BIT*/ - int losless_comp_header_size = compute_losless_comp_header_size - (dec, pic_width, pic_height); - int losless_comp_body_size = compute_losless_comp_body_size - (dec, pic_width, pic_height, buf_alloc_depth == 10); - int mc_buffer_size = losless_comp_header_size - + losless_comp_body_size; - int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; - - int dw_mode = get_double_write_mode_init(dec); - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(dec, dw_mode); - int pic_height_dw = pic_height / - get_double_write_ratio(dec, dw_mode); - int lcu_size = 64; /*fixed 64*/ - int pic_width_64 = (pic_width_dw + 63) & (~0x3f); - int pic_height_32 = (pic_height_dw + 31) & (~0x1f); - int pic_width_lcu = - (pic_width_64 % lcu_size) ? pic_width_64 / lcu_size - + 1 : pic_width_64 / lcu_size; - int pic_height_lcu = - (pic_height_32 % lcu_size) ? pic_height_32 / lcu_size - + 1 : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; - int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; - int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - buf_size = ((mc_buffer_size_u_v_h << 16) * 3); - } else - buf_size = 0; - - if (mc_buffer_size & 0xffff) { /*64k alignment*/ - mc_buffer_size_h += 1; - } - if ((dw_mode & 0x10) == 0) - buf_size += (mc_buffer_size_h << 16); - avs2_print(dec, AVS2_DBG_BUFMGR, - "init_buf_list num %d (width %d height %d):\n", - dec->used_buf_num, pic_width, pic_height); - } - - for (i = 0; i < dec->used_buf_num; i++) { - if (((i + 1) * buf_size) > dec->mc_buf->buf_size) - dec->use_cma_flag = 1; -#ifndef AVS2_10B_MMU - dec->m_BUF[i].alloc_flag = 0; - dec->m_BUF[i].index = i; - - dec->use_cma_flag = 1; - if (dec->use_cma_flag) { - dec->m_BUF[i].cma_page_count = - PAGE_ALIGN(buf_size) / PAGE_SIZE; - if (decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, - VF_BUFFER_IDX(i), buf_size, DRIVER_NAME, - &dec->m_BUF[i].alloc_addr) < 0) { - dec->m_BUF[i].cma_page_count = 0; - if (i <= 5) { - dec->fatal_error |= - DECODER_FATAL_ERROR_NO_MEM; - } - break; - } - dec->m_BUF[i].start_adr = dec->m_BUF[i].alloc_addr; - } else { - dec->m_BUF[i].cma_page_count = 0; - dec->m_BUF[i].alloc_addr = 0; - dec->m_BUF[i].start_adr = - dec->mc_buf->buf_start + i * buf_size; - } - dec->m_BUF[i].size = buf_size; - dec->m_BUF[i].free_start_adr = dec->m_BUF[i].start_adr; - - if (((dec->m_BUF[i].start_adr + buf_size) > mc_buffer_end) - && (dec->m_BUF[i].alloc_addr == 0)) { - if (debug) { - avs2_print(dec, 0, - "Max mc buffer or mpred_mv buffer is used\n"); - } - break; - } - - avs2_print(dec, AVS2_DBG_BUFMGR, - "Buffer %d: start_adr %p size %x\n", i, - (void *)dec->m_BUF[i].start_adr, - dec->m_BUF[i].size); -#endif - } - dec->buf_num = i; -} -#endif - -static int config_pic(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic, int32_t lcu_size_log2) -{ - int ret = -1; - int i; - int pic_width = dec->init_pic_w; - int pic_height = dec->init_pic_h; - /*struct avs2_decoder *avs2_dec = &dec->avs2_dec; - int32_t lcu_size_log2 = avs2_dec->lcu_size_log2;*/ - int32_t lcu_size = 1 << lcu_size_log2; - int pic_width_64 = (pic_width + 63) & (~0x3f); - int pic_height_32 = (pic_height + 31) & (~0x1f); - int pic_width_lcu = (pic_width_64 % lcu_size) ? - pic_width_64 / lcu_size + 1 - : pic_width_64 / lcu_size; - int pic_height_lcu = (pic_height_32 % lcu_size) ? - pic_height_32 / lcu_size + 1 - : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; -#if 0 - int32_t MV_MEM_UNIT = - (lcu_size_log2 == 6) ? 0x200 : - ((lcu_size_log2 == 5) ? 0x80 : 0x20); -#endif -#ifdef MV_USE_FIXED_BUF - u32 mpred_mv_end = dec->work_space_buf->mpred_mv.buf_start + - dec->work_space_buf->mpred_mv.buf_size; -#endif - u32 y_adr = 0; - int buf_size = 0; - - int losless_comp_header_size = - compute_losless_comp_header_size( - dec, pic_width, pic_height); - int losless_comp_body_size = compute_losless_comp_body_size( - dec, pic_width, - pic_height, buf_alloc_depth == 10); - int mc_buffer_size = losless_comp_header_size + losless_comp_body_size; - int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16; - int mc_buffer_size_u_v = 0; - int mc_buffer_size_u_v_h = 0; - int dw_mode = get_double_write_mode_init(dec); - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(dec, dw_mode); - int pic_height_dw = pic_height / - get_double_write_ratio(dec, dw_mode); - int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f); - int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f); - int pic_width_lcu_dw = (pic_width_64_dw % lcu_size) ? - pic_width_64_dw / lcu_size + 1 - : pic_width_64_dw / lcu_size; - int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ? - pic_height_32_dw / lcu_size + 1 - : pic_height_32_dw / lcu_size; - int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; - - mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; - mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - buf_size = ((mc_buffer_size_u_v_h << 16) * 3); - buf_size = ((buf_size + 0xffff) >> 16) << 16; - } - if (mc_buffer_size & 0xffff) /*64k alignment*/ - mc_buffer_size_h += 1; -#ifndef AVS2_10B_MMU - if ((dw_mode & 0x10) == 0) - buf_size += (mc_buffer_size_h << 16); -#endif - -#ifdef AVS2_10B_MMU -#ifndef DYNAMIC_ALLOC_HEAD - pic->header_adr = decoder_bmmu_box_get_phy_addr( - dec->bmmu_box, HEADER_BUFFER_IDX(pic->index)); - - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "buf_size %d, MMU header_adr %d: %ld\n", - buf_size, pic->index, pic->header_adr); -#endif -#endif - - i = pic->index; -#ifdef MV_USE_FIXED_BUF -#ifdef G12A_BRINGUP_DEBUG - if (1) { -#else - if ((dec->work_space_buf->mpred_mv.buf_start + - (((i + 1) * lcu_total) * MV_MEM_UNIT)) - <= mpred_mv_end - ) { -#endif -#endif -#ifndef AVS2_10B_MMU - if (debug) { - pr_err("start %x .size=%d\n", - dec->mc_buf_spec.buf_start + i * buf_size, - buf_size); - } -#endif -#ifndef AVS2_10B_MMU - for (i = 0; i < dec->buf_num; i++) { - y_adr = ((dec->m_BUF[i].free_start_adr - + 0xffff) >> 16) << 16; - /*64k alignment*/ - if ((y_adr+buf_size) <= (dec->m_BUF[i].start_adr+ - dec->m_BUF[i].size)) { - dec->m_BUF[i].free_start_adr = - y_adr + buf_size; - break; - } - } - if (i < dec->buf_num) -#else - /*if ((dec->mc_buf->buf_start + (i + 1) * buf_size) < - dec->mc_buf->buf_end) - y_adr = dec->mc_buf->buf_start + i * buf_size; - else {*/ - if (buf_size > 0 && pic->cma_alloc_addr == 0) { - ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, - VF_BUFFER_IDX(i), - buf_size, DRIVER_NAME, - &pic->cma_alloc_addr); - if (ret < 0) { - avs2_print(dec, 0, - "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", - VF_BUFFER_IDX(i), - buf_size - ); - return ret; - } - - if (pic->cma_alloc_addr) - y_adr = pic->cma_alloc_addr; - else { - avs2_print(dec, 0, - "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n", - VF_BUFFER_IDX(i), - buf_size - ); - return -1; - } - } -#endif - { - /*ensure get_pic_by_POC() - not get the buffer not decoded*/ - pic->BUF_index = i; - pic->lcu_total = lcu_total; - - pic->comp_body_size = losless_comp_body_size; - pic->buf_size = buf_size; -#ifndef AVS2_10B_MMU - pic->mc_y_adr = y_adr; -#endif - pic->mc_canvas_y = pic->index; - pic->mc_canvas_u_v = pic->index; -#ifndef AVS2_10B_MMU - if (dw_mode & 0x10) { - pic->mc_u_v_adr = y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); - - pic->mc_canvas_y = - (pic->index << 1); - pic->mc_canvas_u_v = - (pic->index << 1) + 1; - - pic->dw_y_adr = y_adr; - pic->dw_u_v_adr = pic->mc_u_v_adr; - } else -#endif - if (dw_mode) { - pic->dw_y_adr = y_adr -#ifndef AVS2_10B_MMU - + (mc_buffer_size_h << 16) -#endif - ; - pic->dw_u_v_adr = pic->dw_y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); -#ifdef AVS2_10B_MMU - pic->mc_y_adr = pic->dw_y_adr; - pic->mc_u_v_adr = pic->dw_u_v_adr; -#endif - } -#ifdef MV_USE_FIXED_BUF -#ifdef G12A_BRINGUP_DEBUG - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - pic->mpred_mv_wr_start_addr = - dec->work_space_buf->mpred_mv.buf_start + - (pic->index * 0x120000 * 4); - } else { - pic->mpred_mv_wr_start_addr = - dec->work_space_buf->mpred_mv.buf_start + - (pic->index * 0x120000); - } -#else - pic->mpred_mv_wr_start_addr = - dec->work_space_buf->mpred_mv.buf_start + - ((pic->index * lcu_total) - * MV_MEM_UNIT); -#endif -#endif - if (debug) { - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s index %d BUF_index %d mc_y_adr %x ", - __func__, pic->index, - pic->BUF_index, - pic->mc_y_adr); - avs2_print_cont(dec, AVS2_DBG_BUFMGR, - "comp_body_size %x comp_buf_size %x ", - pic->comp_body_size, - pic->buf_size); - avs2_print_cont(dec, AVS2_DBG_BUFMGR, - "mpred_mv_wr_start_adr %d\n", - pic->mpred_mv_wr_start_addr); - avs2_print_cont(dec, AVS2_DBG_BUFMGR, - "dw_y_adr %d, pic->dw_u_v_adr =%d\n", - pic->dw_y_adr, - pic->dw_u_v_adr); - } - ret = 0; - } -#ifdef MV_USE_FIXED_BUF - } else { - avs2_print(dec, 0, - "mv buffer alloc fail %x > %x\n", - dec->work_space_buf->mpred_mv.buf_start + - (((i + 1) * lcu_total) * MV_MEM_UNIT), - mpred_mv_end); - } -#endif - return ret; -} - -static void init_pic_list(struct AVS2Decoder_s *dec, - int32_t lcu_size_log2) -{ - int i; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *pic; -#ifdef AVS2_10B_MMU - unsigned long buf_addr1; - /*alloc AVS2 compress header first*/ - if (decoder_bmmu_box_alloc_buf_phy - (dec->bmmu_box, - HEADER_BUFFER_IDX(-1), get_compress_header_size(dec), - DRIVER_HEADER_NAME, - &buf_addr1) < 0){ - avs2_print(dec, 0, - "%s malloc compress header failed %d\n", - DRIVER_HEADER_NAME, -1); - dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; - return; - } -#ifndef DYNAMIC_ALLOC_HEAD - for (i = 0; i < dec->used_buf_num; i++) { - unsigned long buf_addr; - if (decoder_bmmu_box_alloc_buf_phy - (dec->bmmu_box, - HEADER_BUFFER_IDX(i), get_compress_header_size(dec), - DRIVER_HEADER_NAME, - &buf_addr) < 0){ - avs2_print(dec, 0, - "%s malloc compress header failed %d\n", - DRIVER_HEADER_NAME, i); - dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; - return; - } - } -#endif -#endif - dec->frame_height = avs2_dec->img.height; - dec->frame_width = avs2_dec->img.width; - - for (i = 0; i < dec->used_buf_num; i++) { - if (i == (dec->used_buf_num - 1)) - pic = avs2_dec->m_bg; - else - pic = avs2_dec->fref[i]; - pic->index = i; - pic->BUF_index = -1; - pic->mv_buf_index = -1; - if (config_pic(dec, pic, lcu_size_log2) < 0) { - if (debug) - avs2_print(dec, 0, - "Config_pic %d fail\n", - pic->index); - pic->index = -1; - break; - } - pic->pic_w = avs2_dec->img.width; - pic->pic_h = avs2_dec->img.height; - } - for (; i < dec->used_buf_num; i++) { - if (i == (dec->used_buf_num - 1)) - pic = avs2_dec->m_bg; - else - pic = avs2_dec->fref[i]; - pic->index = -1; - pic->BUF_index = -1; - pic->mv_buf_index = -1; - } - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s ok, used_buf_num = %d\n", - __func__, dec->used_buf_num); - dec->pic_list_init_flag = 1; -} - - -static void init_pic_list_hw(struct AVS2Decoder_s *dec) -{ - int i; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *pic; - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ -#if 0 - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (0x1 << 2)); - -#ifdef DUAL_CORE_64 - WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (0x1 << 2)); -#endif -#endif - for (i = 0; i < dec->used_buf_num; i++) { - if (i == (dec->used_buf_num - 1)) - pic = avs2_dec->m_bg; - else - pic = avs2_dec->fref[i]; - if (pic->index < 0) - break; -#ifdef AVS2_10B_MMU - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic->header_adr - | (pic->mc_canvas_y << 8)|0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (pic->index << 8)); - -#ifdef DUAL_CORE_64 - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXLX2) - WRITE_VREG(HEVC2_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (pic->index << 8)); - else - WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (pic->index << 8)); -#endif - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5); -#else - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic->mc_y_adr - | (pic->mc_canvas_y << 8) | 0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_y_adr >> 5); -#endif -#ifndef LOSLESS_COMPRESS_MODE - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic->mc_u_v_adr - | (pic->mc_canvas_u_v << 8)| 0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_u_v_adr >> 5); -#endif -#ifdef DUAL_CORE_64 -#ifdef AVS2_10B_MMU - WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA, - pic->header_adr >> 5); -#else - WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA, - pic->mc_y_adr >> 5); -#endif -#ifndef LOSLESS_COMPRESS_MODE - WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA, - pic->mc_u_v_adr >> 5); -#endif -/*DUAL_CORE_64*/ -#endif - } - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); -#ifdef DUAL_CORE_64 - WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - 0x1); -#endif - /*Zero out canvas registers in IPP -- avoid simulation X*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 1); - for (i = 0; i < 32; i++) { - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); -#ifdef DUAL_CORE_64 - WRITE_VREG(HEVC2_HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); -#endif - } -} - - -static void dump_pic_list(struct AVS2Decoder_s *dec) -{ - int ii; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { - avs2_print(dec, 0, - "fref[%d]: index %d decode_id %d mvbuf %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, pre %d is_out %d, bg %d, vf_ref %d error %d lcu %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", - ii, avs2_dec->fref[ii]->index, - avs2_dec->fref[ii]->decode_idx, - avs2_dec->fref[ii]->mv_buf_index, - avs2_dec->fref[ii]->imgcoi_ref, - avs2_dec->fref[ii]->imgtr_fwRefDistance, - avs2_dec->fref[ii]->refered_by_others, - avs2_dec->fref[ii]->to_prepare_disp, - avs2_dec->fref[ii]->is_output, - avs2_dec->fref[ii]->bg_flag, - avs2_dec->fref[ii]->vf_ref, - avs2_dec->fref[ii]->error_mark, - avs2_dec->fref[ii]->decoded_lcu, - avs2_dec->fref[ii]->ref_poc[0], - avs2_dec->fref[ii]->ref_poc[1], - avs2_dec->fref[ii]->ref_poc[2], - avs2_dec->fref[ii]->ref_poc[3], - avs2_dec->fref[ii]->ref_poc[4], - avs2_dec->fref[ii]->ref_poc[5], - avs2_dec->fref[ii]->ref_poc[6] - ); - } - return; -} - -static int config_mc_buffer(struct AVS2Decoder_s *dec) -{ - int32_t i; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *pic; - struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; - - /*if (avs2_dec->img.type == I_IMG) - return 0; - */ - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "Entered config_mc_buffer....\n"); - if (avs2_dec->f_bg != NULL) { - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "config_mc_buffer for background (canvas_y %d, canvas_u_v %d)\n", - avs2_dec->f_bg->mc_canvas_y, avs2_dec->f_bg->mc_canvas_u_v); - /*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (7 << 8) | (0<<1) | 1); L0:BG */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (15 << 8) | (0<<1) | 1); /* L0:BG*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (avs2_dec->f_bg->mc_canvas_u_v << 16) | - (avs2_dec->f_bg->mc_canvas_u_v << 8) | - avs2_dec->f_bg->mc_canvas_y); - /*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (23 << 8) | (0<<1) | 1); L1:BG*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (31 << 8) | (0<<1) | 1); /* L1:BG*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (avs2_dec->f_bg->mc_canvas_u_v << 16) | - (avs2_dec->f_bg->mc_canvas_u_v << 8) | - avs2_dec->f_bg->mc_canvas_y); - } - - if (avs2_dec->img.type == I_IMG) - return 0; - - if (avs2_dec->img.type == P_IMG) { - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "config_mc_buffer for P_IMG, img type %d\n", - avs2_dec->img.type); - /*refer to prepare_RefInfo()*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0<<1) | 1); - for (i = 0; i < avs2_dec->img.num_of_references; i++) { - pic = avs2_dec->fref[i]; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v << 16) | - (pic->mc_canvas_u_v << 8) | - pic->mc_canvas_y); - - if (pic->error_mark) - cur_pic->error_mark = 1; - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y, - pic->error_mark); - } - } else if (avs2_dec->img.type == F_IMG) { - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "config_mc_buffer for F_IMG, img type %d\n", - avs2_dec->img.type); - /*refer to prepare_RefInfo()*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0<<1) | 1); - for (i = 0; i < avs2_dec->img.num_of_references; i++) { - pic = avs2_dec->fref[i]; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v << 16) | - (pic->mc_canvas_u_v << 8) | - pic->mc_canvas_y); - - if (pic->error_mark) - cur_pic->error_mark = 1; - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y, - pic->error_mark); - } - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (16 << 8) | (0<<1) | 1); - for (i = 0; i < avs2_dec->img.num_of_references; i++) { - pic = avs2_dec->fref[i]; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v << 16) | - (pic->mc_canvas_u_v << 8) | - pic->mc_canvas_y); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y); - } - } else { - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "config_mc_buffer for B_IMG\n"); - /*refer to prepare_RefInfo()*/ - pic = avs2_dec->fref[1]; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0<<1) | 1); - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v << 16) | - (pic->mc_canvas_u_v << 8) | - pic->mc_canvas_y); - - if (pic->error_mark) - cur_pic->error_mark = 1; - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", - 1, pic->mc_canvas_u_v, pic->mc_canvas_y, - pic->error_mark); - - pic = avs2_dec->fref[0]; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (16 << 8) | (0<<1) | 1); - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v<<16) | - (pic->mc_canvas_u_v<<8) | - pic->mc_canvas_y); - - if (pic->error_mark) - cur_pic->error_mark = 1; - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", - 0, pic->mc_canvas_u_v, pic->mc_canvas_y, - pic->error_mark); - } - return 0; -} -#if 0 -static void mcrcc_get_hitrate(void) -{ - u32 tmp; - u32 raw_mcr_cnt; - u32 hit_mcr_cnt; - u32 byp_mcr_cnt_nchoutwin; - u32 byp_mcr_cnt_nchcanv; - int hitrate; - - if (debug & AVS2_DBG_CACHE) - pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n"); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1)); - raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1)); - hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1)); - byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1)); - byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - - if (debug & AVS2_DBG_CACHE) { - pr_info("raw_mcr_cnt_total: %d\n",raw_mcr_cnt); - pr_info("hit_mcr_cnt_total: %d\n",hit_mcr_cnt); - pr_info("byp_mcr_cnt_nchoutwin_total: %d\n",byp_mcr_cnt_nchoutwin); - pr_info("byp_mcr_cnt_nchcanv_total: %d\n",byp_mcr_cnt_nchcanv); - } - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & AVS2_DBG_CACHE) - pr_info("miss_mcr_0_cnt_total: %d\n", tmp); - - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & AVS2_DBG_CACHE) - pr_info("miss_mcr_1_cnt_total: %d\n", tmp); - - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & AVS2_DBG_CACHE) - pr_info("hit_mcr_0_cnt_total: %d\n",tmp); - - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1)); - tmp= READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & AVS2_DBG_CACHE) - pr_info("hit_mcr_1_cnt_total: %d\n",tmp); - - if (raw_mcr_cnt != 0) { - hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; - if (debug & AVS2_DBG_CACHE) - pr_info("MCRCC_HIT_RATE : %d\n", hitrate); - hitrate = ((byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv) - /raw_mcr_cnt) * 100; - if (debug & AVS2_DBG_CACHE) - pr_info("MCRCC_BYP_RATE : %d\n", hitrate); - } else if (debug & AVS2_DBG_CACHE) { - pr_info("MCRCC_HIT_RATE : na\n"); - pr_info("MCRCC_BYP_RATE : na\n"); - } - return; -} - - -static void decomp_get_hitrate(void) -{ - u32 raw_mcr_cnt; - u32 hit_mcr_cnt; - int hitrate; - - if (debug & AVS2_DBG_CACHE) - pr_info("[cache_util.c] Entered decomp_get_hitrate...\n"); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1)); - raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1)); - hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - - if (debug & AVS2_DBG_CACHE) { - pr_info("hcache_raw_cnt_total: %d\n",raw_mcr_cnt); - pr_info("hcache_hit_cnt_total: %d\n",hit_mcr_cnt); - } - if (raw_mcr_cnt != 0) { - hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; - if (debug & AVS2_DBG_CACHE) - pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate); - } else { - if (debug & AVS2_DBG_CACHE) - pr_info("DECOMP_HCACHE_HIT_RATE : na\n"); - } - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1)); - raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1)); - hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - - if (debug & AVS2_DBG_CACHE) { - pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt); - pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt); - } - if (raw_mcr_cnt != 0) { - hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; - if (debug & AVS2_DBG_CACHE) - pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate); - } else if (debug & AVS2_DBG_CACHE) { - pr_info("DECOMP_DCACHE_HIT_RATE : na\n"); - } -return; -} - -static void decomp_get_comprate(void) -{ - u32 raw_ucomp_cnt; - u32 fast_comp_cnt; - u32 slow_comp_cnt; - int comprate; - - if (debug & AVS2_DBG_CACHE) - pr_info("[cache_util.c] Entered decomp_get_comprate...\n"); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1)); - fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1)); - slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1)); - raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - if (debug & AVS2_DBG_CACHE) { - pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt); - pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt); - pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt); - } - - if (raw_ucomp_cnt != 0) { - comprate = ((fast_comp_cnt + slow_comp_cnt) - / raw_ucomp_cnt) * 100; - if (debug & AVS2_DBG_CACHE) - pr_info("DECOMP_COMP_RATIO : %d\n", comprate); - } else if (debug & AVS2_DBG_CACHE) { - pr_info("DECOMP_COMP_RATIO : na\n"); - } - return; -} -#endif - -static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec) -{ - uint32_t rdata32; - uint32_t rdata32_2; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc*/ - - if (avs2_dec->img.type == I_IMG) { /* I-PIC*/ - /* remove reset -- disables clock */ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); - return; - } -/* - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - mcrcc_get_hitrate(); - decomp_get_hitrate(); - decomp_get_comprate(); - } -*/ - if ((avs2_dec->img.type == B_IMG) || - (avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/ - /*Programme canvas0 */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 0); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - /*Programme canvas1 */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (16 << 8) | (1 << 1) | 0); - rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32_2 = rdata32_2 & 0xffff; - rdata32_2 = rdata32_2 | (rdata32_2 << 16); - if (rdata32 == rdata32_2) { - rdata32_2 = - READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32_2 = rdata32_2 & 0xffff; - rdata32_2 = rdata32_2 | (rdata32_2 << 16); - } - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); - } else { /* P-PIC */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (1 << 1) | 0); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - /*Programme canvas1*/ - rdata32 = - READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - } - /*enable mcrcc progressive-mode */ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); - return; -} - -static void config_mpred_hw(struct AVS2Decoder_s *dec) -{ - uint32_t data32; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; - struct avs2_frame_s *col_pic = avs2_dec->fref[0]; - int32_t mpred_mv_rd_start_addr; - int32_t mpred_curr_lcu_x; - int32_t mpred_curr_lcu_y; - int32_t mpred_mv_rd_end_addr; - int32_t above_en; - int32_t mv_wr_en; - int32_t mv_rd_en; - int32_t col_isIntra; - int mv_mem_unit; - if (avs2_dec->img.type != I_IMG) { - above_en = 1; - mv_wr_en = 1; - mv_rd_en = 1; - col_isIntra = 0; - } else { - above_en = 1; - mv_wr_en = 1; - mv_rd_en = 0; - col_isIntra = 0; - } - - mpred_mv_rd_start_addr = - col_pic->mpred_mv_wr_start_addr; - data32 = READ_VREG(HEVC_MPRED_CURR_LCU); - mpred_curr_lcu_x = data32 & 0xffff; - mpred_curr_lcu_y = (data32 >> 16) & 0xffff; - - mv_mem_unit = avs2_dec->lcu_size_log2 == 6 ? - 0x200 : (avs2_dec->lcu_size_log2 == 5 ? - 0x80 : 0x20); - - mpred_mv_rd_end_addr = - mpred_mv_rd_start_addr + - ((avs2_dec->lcu_x_num * - avs2_dec->lcu_y_num) * mv_mem_unit); - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "cur pic index %d col pic index %d\n", - cur_pic->index, col_pic->index); - - - WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, - cur_pic->mpred_mv_wr_start_addr); - WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, - col_pic->mpred_mv_wr_start_addr); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[MPRED CO_MV] write 0x%x read 0x%x\n", - cur_pic->mpred_mv_wr_start_addr, - col_pic->mpred_mv_wr_start_addr); - - data32 = - ((avs2_dec->bk_img_is_top_field) << 13) | - ((avs2_dec->hd.background_picture_enable & 1) << 12) | - ((avs2_dec->hd.curr_RPS.num_of_ref & 7) << 8) | - ((avs2_dec->hd.b_pmvr_enabled & 1) << 6) | - ((avs2_dec->img.is_top_field & 1) << 5) | - ((avs2_dec->img.is_field_sequence & 1) << 4) | - ((avs2_dec->img.typeb & 7) << 1) | - (avs2_dec->hd.background_reference_enable & 0x1); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "HEVC_MPRED_CTRL9 <= 0x%x(num of ref %d)\n", - data32, avs2_dec->hd.curr_RPS.num_of_ref); - WRITE_VREG(HEVC_MPRED_CTRL9, data32); - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "%s: dis %d %d %d %d %d %d %d fref0_ref_poc %d %d %d %d %d %d %d\n", - __func__, - avs2_dec->fref[0]->imgtr_fwRefDistance, - avs2_dec->fref[1]->imgtr_fwRefDistance, - avs2_dec->fref[2]->imgtr_fwRefDistance, - avs2_dec->fref[3]->imgtr_fwRefDistance, - avs2_dec->fref[4]->imgtr_fwRefDistance, - avs2_dec->fref[5]->imgtr_fwRefDistance, - avs2_dec->fref[6]->imgtr_fwRefDistance, - avs2_dec->fref[0]->ref_poc[0], - avs2_dec->fref[0]->ref_poc[1], - avs2_dec->fref[0]->ref_poc[2], - avs2_dec->fref[0]->ref_poc[3], - avs2_dec->fref[0]->ref_poc[4], - avs2_dec->fref[0]->ref_poc[5], - avs2_dec->fref[0]->ref_poc[6] - ); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "pic_distance %d, imgtr_next_P %d\n", - avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P); - - - WRITE_VREG(HEVC_MPRED_CUR_POC, avs2_dec->img.pic_distance); - WRITE_VREG(HEVC_MPRED_COL_POC, avs2_dec->img.imgtr_next_P); - - /*below MPRED Ref_POC_xx_Lx registers - must follow Ref_POC_xx_L0 -> - Ref_POC_xx_L1 in pair write order!!!*/ - WRITE_VREG(HEVC_MPRED_L0_REF00_POC, - avs2_dec->fref[0]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF00_POC, - avs2_dec->fref[0]->ref_poc[0]); - - WRITE_VREG(HEVC_MPRED_L0_REF01_POC, - avs2_dec->fref[1]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF01_POC, - avs2_dec->fref[0]->ref_poc[1]); - - WRITE_VREG(HEVC_MPRED_L0_REF02_POC, - avs2_dec->fref[2]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF02_POC, - avs2_dec->fref[0]->ref_poc[2]); - - WRITE_VREG(HEVC_MPRED_L0_REF03_POC, - avs2_dec->fref[3]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF03_POC, - avs2_dec->fref[0]->ref_poc[3]); - - WRITE_VREG(HEVC_MPRED_L0_REF04_POC, - avs2_dec->fref[4]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF04_POC, - avs2_dec->fref[0]->ref_poc[4]); - - WRITE_VREG(HEVC_MPRED_L0_REF05_POC, - avs2_dec->fref[5]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF05_POC, - avs2_dec->fref[0]->ref_poc[5]); - - WRITE_VREG(HEVC_MPRED_L0_REF06_POC, - avs2_dec->fref[6]->imgtr_fwRefDistance); - WRITE_VREG(HEVC_MPRED_L1_REF06_POC, - avs2_dec->fref[0]->ref_poc[6]); - - - WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, - mpred_mv_rd_end_addr); -} - -static void config_dblk_hw(struct AVS2Decoder_s *dec) -{ - /* - * Picture level de-block parameter configuration here - */ - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - union param_u *rpm_param = &avs2_dec->param; - uint32_t data32; - - data32 = READ_VREG(HEVC_DBLK_CFG1); - data32 = (((data32 >> 20) & 0xfff) << 20) | - (((avs2_dec->input.sample_bit_depth == 10) - ? 0xa : 0x0) << 16) | /*[16 +: 4]: {luma_bd[1:0], - chroma_bd[1:0]}*/ - (((data32 >> 2) & 0x3fff) << 2) | - (((rpm_param->p.lcu_size == 6) - ? 0 : (rpm_param->p.lcu_size == 5) - ? 1 : 2) << 0);/*[ 0 +: 2]: lcu_size*/ - WRITE_VREG(HEVC_DBLK_CFG1, data32); - - data32 = (avs2_dec->img.height << 16) | - avs2_dec->img.width; - WRITE_VREG(HEVC_DBLK_CFG2, data32); - /* - [27 +: 1]: cross_slice_loopfilter_enable_flag - [26 +: 1]: loop_filter_disable - [25 +: 1]: useNSQT - [22 +: 3]: imgtype - [17 +: 5]: alpha_c_offset (-8~8) - [12 +: 5]: beta_offset (-8~8) - [ 6 +: 6]: chroma_quant_param_delta_u (-16~16) - [ 0 +: 6]: chroma_quant_param_delta_v (-16~16) - */ - data32 = ((avs2_dec->input.crossSliceLoopFilter - & 0x1) << 27) | - ((rpm_param->p.loop_filter_disable & 0x1) << 26) | - ((avs2_dec->input.useNSQT & 0x1) << 25) | - ((avs2_dec->img.type & 0x7) << 22) | - ((rpm_param->p.alpha_c_offset & 0x1f) << 17) | - ((rpm_param->p.beta_offset & 0x1f) << 12) | - ((rpm_param->p.chroma_quant_param_delta_cb & 0x3f) << 6) | - ((rpm_param->p.chroma_quant_param_delta_cr & 0x3f) << 0); - - WRITE_VREG(HEVC_DBLK_CFG9, data32); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] cfgDBLK: crossslice(%d),lfdisable(%d),bitDepth(%d),lcuSize(%d),NSQT(%d)\n", - avs2_dec->input.crossSliceLoopFilter, - rpm_param->p.loop_filter_disable, - avs2_dec->input.sample_bit_depth, - avs2_dec->lcu_size, - avs2_dec->input.useNSQT); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] cfgDBLK: alphaCOffset(%d),betaOffset(%d),quantDeltaCb(%d),quantDeltaCr(%d)\n", - rpm_param->p.alpha_c_offset, - rpm_param->p.beta_offset, - rpm_param->p.chroma_quant_param_delta_cb, - rpm_param->p.chroma_quant_param_delta_cr); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] cfgDBLK: .done.\n"); -} - -static void config_sao_hw(struct AVS2Decoder_s *dec) -{ - uint32_t data32; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; - - int lcu_size = 64; - int mc_buffer_size_u_v = - cur_pic->lcu_total * lcu_size*lcu_size/2; - int mc_buffer_size_u_v_h = - (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ - - data32 = READ_VREG(HEVC_SAO_CTRL0); - data32 &= (~0xf); - data32 |= avs2_dec->lcu_size_log2; - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "%s, lcu_size_log2 = %d, config HEVC_SAO_CTRL0 0x%x\n", - __func__, - avs2_dec->lcu_size_log2, - data32); - - WRITE_VREG(HEVC_SAO_CTRL0, data32); - -#ifndef AVS2_10B_MMU - if ((get_double_write_mode(dec) & 0x10) == 0) - WRITE_VREG(HEVC_CM_BODY_START_ADDR, cur_pic->mc_y_adr); -#endif - if (get_double_write_mode(dec)) { - WRITE_VREG(HEVC_SAO_Y_START_ADDR, cur_pic->dw_y_adr); - WRITE_VREG(HEVC_SAO_C_START_ADDR, cur_pic->dw_u_v_adr); - WRITE_VREG(HEVC_SAO_Y_WPTR, cur_pic->dw_y_adr); - WRITE_VREG(HEVC_SAO_C_WPTR, cur_pic->dw_u_v_adr); - } else { - WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); - WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); - } -#ifdef AVS2_10B_MMU - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, cur_pic->header_adr); -#endif - data32 = (mc_buffer_size_u_v_h << 16) << 1; - /*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n", - data32, mc_buffer_size_u_v_h, cur_pic->lcu_total);*/ - WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); - - data32 = (mc_buffer_size_u_v_h << 16); - WRITE_VREG(HEVC_SAO_C_LENGTH, data32); - -#ifdef AVS2_10B_NV21 -#ifdef DOS_PROJECT - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (MEM_MAP_MODE << 12); - data32 &= (~0x3); - data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/ - WRITE_VREG(HEVC_SAO_CTRL1, data32); - /*[23:22] dw_v1_ctrl [21:20] dw_v0_ctrl [19:18] dw_h1_ctrl - [17:16] dw_h0_ctrl*/ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /*set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - ata32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (MEM_MAP_MODE << 4); - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#else - /*m8baby test1902*/ - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (MEM_MAP_MODE << 12); - data32 &= (~0xff0); - /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/ - data32 |= 0x880; /*.Big-Endian per 64-bit */ - data32 &= (~0x3); - data32 |= 0x1; /*[1]:dw_disable [0]:cm_disable*/ - WRITE_VREG(HEVC_SAO_CTRL1, data32); - /* [23:22] dw_v1_ctrl [21:20] dw_v0_ctrl - [19:18] dw_h1_ctrl [17:16] dw_h0_ctrl*/ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /* set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (MEM_MAP_MODE << 4); - data32 &= (~0xF); - data32 |= 0x8; /*Big-Endian per 64-bit*/ - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#endif -#else - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - data32 |= (MEM_MAP_MODE << - 12); /* [13:12] axi_aformat, 0-Linear, - 1-32x32, 2-64x32 */ - data32 &= (~0xff0); - /* data32 |= 0x670; // Big-Endian per 64-bit */ - data32 |= endian; /* Big-Endian per 64-bit */ - data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ -#if 0 - if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { - if (get_double_write_mode(dec) == 0) - data32 |= 0x2; /*disable double write*/ -#ifndef AVS2_10B_MMU - else - if (get_double_write_mode(dec) & 0x10) - data32 |= 0x1; /*disable cm*/ -#endif - } -#endif - WRITE_VREG(HEVC_SAO_CTRL1, data32); - - if (get_double_write_mode(dec) & 0x10) { - /* [23:22] dw_v1_ctrl - [21:20] dw_v0_ctrl - [19:18] dw_h1_ctrl - [17:16] dw_h0_ctrl - */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /*set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } else { - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 &= (~(0xff << 16)); - if (get_double_write_mode(dec) == 2 || - get_double_write_mode(dec) == 3) - data32 |= (0xff<<16); - else if (get_double_write_mode(dec) == 4) - data32 |= (0x33<<16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ - data32 |= (mem_map_mode << - 4); - data32 &= (~0xF); - data32 |= 0xf; /* valid only when double write only */ - /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#endif -} - -static void reconstructCoefficients(struct AVS2Decoder_s *dec, - struct ALFParam_s *alfParam) -{ - int32_t g, sum, i, coeffPred; - for (g = 0; g < alfParam->filters_per_group; g++) { - sum = 0; - for (i = 0; i < alfParam->num_coeff - 1; i++) { - sum += (2 * alfParam->coeffmulti[g][i]); - dec->m_filterCoeffSym[g][i] = - alfParam->coeffmulti[g][i]; - /*pr_info("[t] dec->m_filterCoeffSym[%d][%d]=0x%x\n", - g, i, dec->m_filterCoeffSym[g][i]);*/ - } - coeffPred = (1 << ALF_NUM_BIT_SHIFT) - sum; - dec->m_filterCoeffSym[g][alfParam->num_coeff - 1] - = coeffPred + - alfParam->coeffmulti[g][alfParam->num_coeff - 1]; - /*pr_info("[t] dec->m_filterCoeffSym[%d][%d]=0x%x\n", - g, (alfParam->num_coeff - 1), - dec->m_filterCoeffSym[g][alfParam->num_coeff - 1]);*/ - } -} - -static void reconstructCoefInfo(struct AVS2Decoder_s *dec, - int32_t compIdx, struct ALFParam_s *alfParam) -{ - int32_t i; - if (compIdx == ALF_Y) { - if (alfParam->filters_per_group > 1) { - for (i = 1; i < NO_VAR_BINS; ++i) { - if (alfParam->filterPattern[i]) - dec->m_varIndTab[i] = - dec->m_varIndTab[i - 1] + 1; - else - dec->m_varIndTab[i] = - dec->m_varIndTab[i - 1]; - } - } - } - reconstructCoefficients(dec, alfParam); -} - -static void config_alf_hw(struct AVS2Decoder_s *dec) -{ - /* - * Picture level ALF parameter configuration here - */ - uint32_t data32; - int32_t i, j; - int32_t m_filters_per_group; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct ALFParam_s *m_alfPictureParam_y = - &avs2_dec->m_alfPictureParam[0]; - struct ALFParam_s *m_alfPictureParam_cb = - &avs2_dec->m_alfPictureParam[1]; - struct ALFParam_s *m_alfPictureParam_cr = - &avs2_dec->m_alfPictureParam[2]; - - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[t]alfy,cidx(%d),flag(%d),filters_per_group(%d),filterPattern[0]=0x%x,[15]=0x%x\n", - m_alfPictureParam_y->componentID, - m_alfPictureParam_y->alf_flag, - m_alfPictureParam_y->filters_per_group, - m_alfPictureParam_y->filterPattern[0], - m_alfPictureParam_y->filterPattern[15]); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[t]alfy,num_coeff(%d),coeffmulti[0][0]=0x%x,[0][1]=0x%x,[1][0]=0x%x,[1][1]=0x%x\n", - m_alfPictureParam_y->num_coeff, - m_alfPictureParam_y->coeffmulti[0][0], - m_alfPictureParam_y->coeffmulti[0][1], - m_alfPictureParam_y->coeffmulti[1][0], - m_alfPictureParam_y->coeffmulti[1][1]); - - /*Cr*/ - for (i = 0; i < 16; i++) - dec->m_varIndTab[i] = 0; - for (j = 0; j < 16; j++) - for (i = 0; i < 9; i++) - dec->m_filterCoeffSym[j][i] = 0; - reconstructCoefInfo(dec, 2, m_alfPictureParam_cr); - data32 = - ((dec->m_filterCoeffSym[0][4] & 0xf) << 28) | - ((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) | - ((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) | - ((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) | - ((dec->m_filterCoeffSym[0][0] & 0x7f) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - data32 = - ((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) | - ((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) | - ((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) | - ((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) | - (((dec->m_filterCoeffSym[0][4] >> 4) & 0x7) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] pic_alf_on_cr(%d), alf_cr_coef(%d %d %d %d %d %d %d %d %d)\n", - m_alfPictureParam_cr->alf_flag, - dec->m_filterCoeffSym[0][0], - dec->m_filterCoeffSym[0][1], - dec->m_filterCoeffSym[0][2], - dec->m_filterCoeffSym[0][3], - dec->m_filterCoeffSym[0][4], - dec->m_filterCoeffSym[0][5], - dec->m_filterCoeffSym[0][6], - dec->m_filterCoeffSym[0][7], - dec->m_filterCoeffSym[0][8]); - - /* Cb*/ - for (j = 0; j < 16; j++) - for (i = 0; i < 9; i++) - dec->m_filterCoeffSym[j][i] = 0; - reconstructCoefInfo(dec, 1, m_alfPictureParam_cb); - data32 = - ((dec->m_filterCoeffSym[0][4] & 0xf) << 28) | - ((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) | - ((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) | - ((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) | - ((dec->m_filterCoeffSym[0][0] & 0x7f) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - data32 = - ((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) | - ((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) | - ((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) | - ((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) | - (((dec->m_filterCoeffSym[0][4] >> 4) & 0x7) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] pic_alf_on_cb(%d), alf_cb_coef(%d %d %d %d %d %d %d %d %d)\n", - m_alfPictureParam_cb->alf_flag, - dec->m_filterCoeffSym[0][0], - dec->m_filterCoeffSym[0][1], - dec->m_filterCoeffSym[0][2], - dec->m_filterCoeffSym[0][3], - dec->m_filterCoeffSym[0][4], - dec->m_filterCoeffSym[0][5], - dec->m_filterCoeffSym[0][6], - dec->m_filterCoeffSym[0][7], - dec->m_filterCoeffSym[0][8]); - - /* Y*/ - for (j = 0; j < 16; j++) - for (i = 0; i < 9; i++) - dec->m_filterCoeffSym[j][i] = 0; - reconstructCoefInfo(dec, 0, m_alfPictureParam_y); - data32 = - ((dec->m_varIndTab[7] & 0xf) << 28) | - ((dec->m_varIndTab[6] & 0xf) << 24) | - ((dec->m_varIndTab[5] & 0xf) << 20) | - ((dec->m_varIndTab[4] & 0xf) << 16) | - ((dec->m_varIndTab[3] & 0xf) << 12) | - ((dec->m_varIndTab[2] & 0xf) << 8) | - ((dec->m_varIndTab[1] & 0xf) << 4) | - ((dec->m_varIndTab[0] & 0xf) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - data32 = ((dec->m_varIndTab[15] & 0xf) << 28) | - ((dec->m_varIndTab[14] & 0xf) << 24) | - ((dec->m_varIndTab[13] & 0xf) << 20) | - ((dec->m_varIndTab[12] & 0xf) << 16) | - ((dec->m_varIndTab[11] & 0xf) << 12) | - ((dec->m_varIndTab[10] & 0xf) << 8) | - ((dec->m_varIndTab[9] & 0xf) << 4) | - ((dec->m_varIndTab[8] & 0xf) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] pic_alf_on_y(%d), alf_y_tab(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)\n", - m_alfPictureParam_y->alf_flag, - dec->m_varIndTab[0], - dec->m_varIndTab[1], - dec->m_varIndTab[2], - dec->m_varIndTab[3], - dec->m_varIndTab[4], - dec->m_varIndTab[5], - dec->m_varIndTab[6], - dec->m_varIndTab[7], - dec->m_varIndTab[8], - dec->m_varIndTab[9], - dec->m_varIndTab[10], - dec->m_varIndTab[11], - dec->m_varIndTab[12], - dec->m_varIndTab[13], - dec->m_varIndTab[14], - dec->m_varIndTab[15]); - - m_filters_per_group = - (m_alfPictureParam_y->alf_flag == 0) ? - 1 : m_alfPictureParam_y->filters_per_group; - for (i = 0; i < m_filters_per_group; i++) { - data32 = - ((dec->m_filterCoeffSym[i][4] & 0xf) << 28) | - ((dec->m_filterCoeffSym[i][3] & 0x7f) << 21) | - ((dec->m_filterCoeffSym[i][2] & 0x7f) << 14) | - ((dec->m_filterCoeffSym[i][1] & 0x7f) << 7) | - ((dec->m_filterCoeffSym[i][0] & 0x7f) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - data32 = - /*[31] last indication*/ - ((i == m_filters_per_group-1) << 31) | - ((dec->m_filterCoeffSym[i][8] & 0x7f) << 24) | - ((dec->m_filterCoeffSym[i][7] & 0x7f) << 17) | - ((dec->m_filterCoeffSym[i][6] & 0x7f) << 10) | - ((dec->m_filterCoeffSym[i][5] & 0x7f) << 3) | - (((dec->m_filterCoeffSym[i][4] >> 4) & 0x7) << 0); - WRITE_VREG(HEVC_DBLK_CFGD, data32); - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] alf_y_coef[%d](%d %d %d %d %d %d %d %d %d)\n", - i, dec->m_filterCoeffSym[i][0], - dec->m_filterCoeffSym[i][1], - dec->m_filterCoeffSym[i][2], - dec->m_filterCoeffSym[i][3], - dec->m_filterCoeffSym[i][4], - dec->m_filterCoeffSym[i][5], - dec->m_filterCoeffSym[i][6], - dec->m_filterCoeffSym[i][7], - dec->m_filterCoeffSym[i][8]); - } - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "[c] cfgALF .done.\n"); -} - -static void config_other_hw(struct AVS2Decoder_s *dec) -{ - uint32_t data32; - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; - int bit_depth = cur_pic->bit_depth; - int losless_comp_header_size = - compute_losless_comp_header_size( - dec, cur_pic->pic_w, - cur_pic->pic_h); - int losless_comp_body_size = - compute_losless_comp_body_size( - dec, cur_pic->pic_w, - cur_pic->pic_h, (bit_depth == AVS2_BITS_10)); - cur_pic->comp_body_size = losless_comp_body_size; - -#ifdef LOSLESS_COMPRESS_MODE - data32 = READ_VREG(HEVC_SAO_CTRL5); - if (bit_depth == AVS2_BITS_10) - data32 &= ~(1 << 9); - else - data32 |= (1 << 9); - - WRITE_VREG(HEVC_SAO_CTRL5, data32); - -#ifdef AVS2_10B_MMU - /*bit[4] : paged_mem_mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); -#else - /*bit[3] smem mdoe*/ - if (bit_depth == AVS2_BITS_10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); - else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); -#endif - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); -#else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif -} - -static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec) -{ - struct BuffInfo_s *buf_spec = dec->work_space_buf; -#ifdef LOSLESS_COMPRESS_MODE - int losless_comp_header_size = - compute_losless_comp_header_size( - dec, dec->init_pic_w, - dec->init_pic_h); - int losless_comp_body_size = - compute_losless_comp_body_size(dec, - dec->init_pic_w, - dec->init_pic_h, buf_alloc_depth == 10); -#endif -#ifdef AVS2_10B_MMU - unsigned int data32; -#endif - if (debug && dec->init_flag == 0) - avs2_print(dec, 0, - "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n", - __func__, - buf_spec->ipp.buf_start, - buf_spec->start_adr, - buf_spec->short_term_rps.buf_start, - buf_spec->rcs.buf_start, - buf_spec->sps.buf_start, - buf_spec->pps.buf_start, - buf_spec->sao_up.buf_start, - buf_spec->swap_buf.buf_start, - buf_spec->swap_buf2.buf_start, - buf_spec->scalelut.buf_start, - buf_spec->dblk_para.buf_start, - buf_spec->dblk_data.buf_start, - buf_spec->dblk_data2.buf_start); - WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); - if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) - WRITE_VREG(HEVC_RPM_BUFFER, (u32)dec->rpm_phy_addr); - WRITE_VREG(AVS2_ALF_SWAP_BUFFER, buf_spec->short_term_rps.buf_start); - WRITE_VREG(HEVC_RCS_BUFFER, buf_spec->rcs.buf_start); - WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start); - WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); - WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); -#ifdef AVS2_10B_MMU - WRITE_VREG(AVS2_MMU_MAP_BUFFER, dec->frame_mmu_map_phy_addr); -#else - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, buf_spec->swap_buf.buf_start); -#endif - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start); - WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); - - /* cfg_p_addr */ - WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); - /* cfg_d_addr */ - WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); - - WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_data2.buf_start); - -#ifdef LOSLESS_COMPRESS_MODE - data32 = READ_VREG(HEVC_SAO_CTRL5); -#if 1 - data32 &= ~(1<<9); -#else - if (params->p.bit_depth != 0x00) - data32 &= ~(1<<9); - else - data32 |= (1<<9); -#endif - WRITE_VREG(HEVC_SAO_CTRL5, data32); -#ifdef AVS2_10B_MMU - /*bit[4] : paged_mem_mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); -#else - /* bit[3] smem mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0<<3)); - - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); -#endif - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2,(losless_comp_body_size >> 5));*/ - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ -/*8-bit mode */ - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); -#else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif - -#ifdef AVS2_10B_MMU - WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); - WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start - + buf_spec->mmu_vbh.buf_size/2); - /*data32 = READ_VREG(HEVC_SAO_CTRL9);*/ - /*data32 |= 0x1;*/ - /*WRITE_VREG(HEVC_SAO_CTRL9, data32);*/ - - /* use HEVC_CM_HEADER_START_ADDR */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 |= (1<<10); -#if 1 - if (debug & AVS2_DBG_FORCE_UNCOMPRESS) - data32 |= 0x80; -#endif - WRITE_VREG(HEVC_SAO_CTRL5, data32); - -#endif - - WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr); -#if 1 -/*MULTI_INSTANCE_SUPPORT*/ - /*new added in simulation???*/ - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, buf_spec->mpred_above.buf_start); -#endif -} - -static void decomp_perfcount_reset(void) -{ - if (debug & AVS2_DBG_CACHE) - pr_info("[cache_util.c] Entered decomp_perfcount_reset...\n"); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x1); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x0); - return; -} - -static void mcrcc_perfcount_reset(void) -{ - if (debug & AVS2_DBG_CACHE) - pr_info("[cache_util.c] Entered mcrcc_perfcount_reset...\n"); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x1); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x0); - return; -} - -static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) -{ - unsigned int data32; - unsigned int decode_mode; - int i; - - /*if (debug & AVS2_DBG_BUFMGR_MORE) - pr_info("%s\n", __func__);*/ - data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); -#if 1 - /* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */ - data32 &= ~(7 << 29); - data32 |= (3 << 29); -#endif - data32 = data32 | - (1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/ - (1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/ - (1 << 7) |/*dec_done_int_cpu_enable*/ - (1 << 4) |/*startcode_found_int_cpu_enable*/ - (0 << 3) |/*startcode_found_int_amrisc_enable*/ - (1 << 0) /*parser_int_enable*/ - ; - WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); - - data32 = READ_VREG(HEVC_SHIFT_STATUS); - data32 = data32 | - (0 << 1) |/*emulation_check_off VP9 - do not have emulation*/ - (1 << 0)/*startcode_check_on*/ - ; - WRITE_VREG(HEVC_SHIFT_STATUS, data32); - WRITE_VREG(HEVC_SHIFT_CONTROL, - (6 << 20) | /* emu_push_bits (6-bits for AVS2)*/ - (0 << 19) | /* emu_3_enable, maybe turned on in microcode*/ - (0 << 18) | /* emu_2_enable, maybe turned on in microcode*/ - (0 << 17) | /* emu_1_enable, maybe turned on in microcode*/ - (0 << 16) | /* emu_0_enable, maybe turned on in microcode*/ - (0 << 14) | /*disable_start_code_protect*/ - (3 << 6) | /* sft_valid_wr_position*/ - (2 << 4) | /* emulate_code_length_sub_1*/ - (2 << 1) | /* start_code_length_sub_1*/ - (1 << 0) /* stream_shift_enable*/ - ); - - WRITE_VREG(HEVC_SHIFT_LENGTH_PROTECT, - (0 << 30) | /*data_protect_fill_00_enable*/ - (1 << 29) /*data_protect_fill_ff_enable*/ - ); - WRITE_VREG(HEVC_CABAC_CONTROL, - (1 << 0)/*cabac_enable*/ - ); - - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, - (1 << 0)/* hevc_parser_core_clk_en*/ - ); - - - WRITE_VREG(HEVC_DEC_STATUS_REG, 0); - - /*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/ - - WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/ - for (i = 0; i < 1024; i++) - WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); - - -#ifdef ENABLE_SWAP_TEST - WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); -#else - WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); -#endif - if (!dec->m_ins_flag) - decode_mode = DECODE_MODE_SINGLE; - else if (vdec_frame_based(hw_to_vdec(dec))) - decode_mode = DECODE_MODE_MULTI_FRAMEBASE; - else - decode_mode = DECODE_MODE_MULTI_STREAMBASE; - if (dec->avs2_dec.bufmgr_error_flag && - (error_handle_policy & 0x1)) { - dec->bufmgr_error_count++; - dec->avs2_dec.bufmgr_error_flag = 0; - if (dec->bufmgr_error_count > - (re_search_seq_threshold & 0xff) - && dec->frame_count > - ((re_search_seq_threshold >> 8) & 0xff)) { - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - dec->start_decoding_flag = 0; - avs2_dec->hd.vec_flag = 1; - dec->skip_PB_before_I = 1; - avs2_print(dec, 0, - "!!Bufmgr error, search seq again (0x%x %d %d)\n", - error_handle_policy, - dec->frame_count, - dec->bufmgr_error_count); - dec->bufmgr_error_count = 0; - } - } - decode_mode |= (dec->start_decoding_flag << 16); - - WRITE_VREG(DECODE_MODE, decode_mode); - WRITE_VREG(HEVC_DECODE_SIZE, 0); - WRITE_VREG(HEVC_DECODE_COUNT, 0); - - /*Send parser_cmd*/ - WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); - for (i = 0; i < PARSER_CMD_NUMBER; i++) - WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); - - - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - (1 << 9) | /* parser_alf_if_en*/ - /* (1 << 8) |*/ /*sao_sw_pred_enable*/ - (1 << 5) | /*parser_sao_if_en*/ - (1 << 2) | /*parser_mpred_if_en*/ - (1 << 0) /*parser_scaler_if_en*/ - ); - -#ifdef MULTI_INSTANCE_SUPPORT - WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); - - WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); - - for (i = 0; i < 8; i++) - data32 = READ_VREG(HEVC_MPRED_ABV_START_ADDR); - - WRITE_VREG(DOS_SW_RESET3, (1<<18)); /* reset mpred */ - WRITE_VREG(DOS_SW_RESET3, 0); - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); -#endif - /*End of Multi-instance*/ - /*Changed to Start MPRED in microcode*/ - /* - pr_info("[test.c] Start MPRED\n"); - WRITE_VREG(HEVC_MPRED_INT_STATUS, - (1<<31) - ); - */ - - /*AVS2 default seq_wq_matrix config*/ - - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "Config AVS2 default seq_wq_matrix ...\n"); - /*4x4*/ - /* default seq_wq_matrix_4x4 begin address*/ - WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 64); - for (i = 0; i < 16; i++) - WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault4x4[i]); - - /*8x8*/ - /*default seq_wq_matrix_8x8 begin address*/ - WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0); - for (i = 0; i < 64; i++) - WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault8x8[i]); - - - WRITE_VREG(HEVCD_IPP_TOP_CNTL, - (0 << 1) | /*enable ipp*/ - (1 << 0) /*software reset ipp and mpp*/ - ); - WRITE_VREG(HEVCD_IPP_TOP_CNTL, - (1 << 1) | /*enable ipp*/ - (0 << 0) /*software reset ipp and mpp*/ - ); -#if 0 -/*AVS2_10B_NV21*/ - /*Enable NV21 reference read mode for MC*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif - /* Init dblk*/ - data32 = READ_VREG(HEVC_DBLK_CFGB); - data32 |= (2 << 0); - /* [3:0] cfg_video_type -> AVS2*/ - - data32 &= (~0x300); /*[8]:first write enable (compress) - [9]:double write enable (uncompress)*/ - if (get_double_write_mode(dec) == 0) - data32 |= (0x1 << 8); /*enable first write*/ - else if (get_double_write_mode(dec) == 0x10) - data32 |= (0x1 << 9); /*double write only*/ - else - data32 |= ((0x1 << 8) | (0x1 << 9)); - WRITE_VREG(HEVC_DBLK_CFGB, data32); - - WRITE_VREG(HEVC_DBLK_CFG0, (1 << 0)); /* [0] rst_sync*/ - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "Bitstream level Init for DBLK .Done.\n"); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - mcrcc_perfcount_reset(); - decomp_perfcount_reset(); - } - - return; -} - - -#ifdef CONFIG_HEVC_CLK_FORCED_ON -static void config_avs2_clk_forced_on(void) -{ - unsigned int rdata32; - /*IQIT*/ - rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL); - WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2)); - - /* DBLK*/ - rdata32 = READ_VREG(HEVC_DBLK_CFG0); - WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2)); - - /* SAO*/ - rdata32 = READ_VREG(HEVC_SAO_CTRL1); - WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2)); - - /*MPRED*/ - rdata32 = READ_VREG(HEVC_MPRED_CTRL1); - WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24)); - - /* PARSER*/ - rdata32 = READ_VREG(HEVC_STREAM_CONTROL); - WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_SHIFT_CONTROL); - WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_CABAC_CONTROL); - WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13)); - rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL); - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL); - WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL); - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - rdata32 | (0x1 << 6) | (0x1 << 3) | (0x1 << 1)); - - /*IPP*/ - rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG); - WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff); - - /* MCRCC*/ - rdata32 = READ_VREG(HEVCD_MCRCC_CTL1); - WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3)); -} -#endif - - - - - -static struct AVS2Decoder_s gAVS2Decoder; - -static void avs2_local_uninit(struct AVS2Decoder_s *dec) -{ - dec->rpm_ptr = NULL; - dec->lmem_ptr = NULL; - if (dec->rpm_addr) { - dma_unmap_single(amports_get_dma_device(), - dec->rpm_phy_addr, RPM_BUF_SIZE, - DMA_FROM_DEVICE); - kfree(dec->rpm_addr); - dec->rpm_addr = NULL; - } - if (dec->lmem_addr) { - if (dec->lmem_phy_addr) - dma_free_coherent(amports_get_dma_device(), - LMEM_BUF_SIZE, dec->lmem_addr, - dec->lmem_phy_addr); - dec->lmem_addr = NULL; - } - -#ifdef AVS2_10B_MMU - if (dec->frame_mmu_map_addr) { - if (dec->frame_mmu_map_phy_addr) - dma_free_coherent(amports_get_dma_device(), - get_frame_mmu_map_size(dec), dec->frame_mmu_map_addr, - dec->frame_mmu_map_phy_addr); - dec->frame_mmu_map_addr = NULL; - } -#endif - if (dec->gvs) - vfree(dec->gvs); - dec->gvs = NULL; -} - -static int avs2_local_init(struct AVS2Decoder_s *dec) -{ - int ret = -1; - /*int losless_comp_header_size, losless_comp_body_size;*/ - - struct BuffInfo_s *cur_buf_info = NULL; - - cur_buf_info = &dec->work_space_buf_store; - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - memcpy(cur_buf_info, &amvavs2_workbuff_spec[2], /* 8k */ - sizeof(struct BuffInfo_s)); - else - memcpy(cur_buf_info, &amvavs2_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - } else - memcpy(cur_buf_info, &amvavs2_workbuff_spec[0],/* 1080p */ - sizeof(struct BuffInfo_s)); - - cur_buf_info->start_adr = dec->buf_start; -#ifndef AVS2_10B_MMU - dec->mc_buf_spec.buf_end = dec->buf_start + dec->buf_size; -#endif - - init_buff_spec(dec, cur_buf_info); - - init_avs2_decoder(&dec->avs2_dec); - -#ifdef AVS2_10B_MMU - avs2_bufmgr_init(dec, cur_buf_info, NULL); -#else - dec->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff) - & (~0xffff); - dec->mc_buf_spec.buf_size = (dec->mc_buf_spec.buf_end - - dec->mc_buf_spec.buf_start); - if (debug) { - pr_err("dec->mc_buf_spec.buf_start %x-%x\n", - dec->mc_buf_spec.buf_start, - dec->mc_buf_spec.buf_start + - dec->mc_buf_spec.buf_size); - } - avs2_bufmgr_init(dec, cur_buf_info, &dec->mc_buf_spec); -#endif - - if (!vdec_is_support_4k() - && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { - buf_alloc_width = 1920; - buf_alloc_height = 1088; - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - buf_alloc_width = 8192; - buf_alloc_height = 4608; - } - dec->init_pic_w = buf_alloc_width ? buf_alloc_width : - (dec->vavs2_amstream_dec_info.width ? - dec->vavs2_amstream_dec_info.width : - dec->work_space_buf->max_width); - dec->init_pic_h = buf_alloc_height ? buf_alloc_height : - (dec->vavs2_amstream_dec_info.height ? - dec->vavs2_amstream_dec_info.height : - dec->work_space_buf->max_height); -#if 0 -/*ndef MV_USE_FIXED_BUF*/ - if (init_mv_buf_list(dec) < 0) { - pr_err("%s: init_mv_buf_list fail\n", __func__); - return -1; - } -#endif - -#ifndef AVS2_10B_MMU - init_buf_list(dec); -#else - dec->used_buf_num = max_buf_num; - if (dec->used_buf_num > MAX_BUF_NUM) - dec->used_buf_num = MAX_BUF_NUM; - if (dec->used_buf_num > FRAME_BUFFERS) - dec->used_buf_num = FRAME_BUFFERS; -#endif - dec->avs2_dec.ref_maxbuffer = dec->used_buf_num - 1; - /*init_pic_list(dec);*/ - - pts_unstable = ((unsigned long)(dec->vavs2_amstream_dec_info.param) - & 0x40) >> 6; - - if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) { - dec->rpm_addr = kmalloc(RPM_BUF_SIZE, GFP_KERNEL); - if (dec->rpm_addr == NULL) { - pr_err("%s: failed to alloc rpm buffer\n", __func__); - return -1; - } - - dec->rpm_phy_addr = dma_map_single(amports_get_dma_device(), - dec->rpm_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - dec->rpm_phy_addr)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(dec->rpm_addr); - dec->rpm_addr = NULL; - return -1; - } else { - avs2_print(dec, AVS2_DBG_BUFMGR, - "rpm_phy_addr %x\n", (u32) dec->rpm_phy_addr); - } - - dec->rpm_ptr = dec->rpm_addr; - } - - dec->lmem_addr = dma_alloc_coherent(amports_get_dma_device(), - LMEM_BUF_SIZE, - &dec->lmem_phy_addr, GFP_KERNEL); - if (dec->lmem_addr == NULL) { - pr_err("%s: failed to alloc lmem buffer\n", __func__); - return -1; - } else - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s, lmem_phy_addr %x\n", - __func__, (u32)dec->lmem_phy_addr); -/* - dec->lmem_phy_addr = dma_map_single(amports_get_dma_device(), - dec->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - dec->lmem_phy_addr)) { - pr_err("%s: failed to map lmem buffer\n", __func__); - kfree(dec->lmem_addr); - dec->lmem_addr = NULL; - return -1; - } -*/ - dec->lmem_ptr = dec->lmem_addr; - - -#ifdef AVS2_10B_MMU - dec->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - get_frame_mmu_map_size(dec), - &dec->frame_mmu_map_phy_addr, GFP_KERNEL); - if (dec->frame_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; - } - memset(dec->frame_mmu_map_addr, 0, get_frame_mmu_map_size(dec)); -/* dec->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), - dec->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - dec->frame_mmu_map_phy_addr)) { - pr_err("%s: failed to map count_buffer\n", __func__); - kfree(dec->frame_mmu_map_addr); - dec->frame_mmu_map_addr = NULL; - return -1; - }*/ -#endif - - ret = 0; - return ret; -} - -/******************************************** - * Mailbox command - ********************************************/ -#define CMD_FINISHED 0 -#define CMD_ALLOC_VIEW 1 -#define CMD_FRAME_DISPLAY 3 -#define CMD_DEBUG 10 - - -#define DECODE_BUFFER_NUM_MAX 32 -#define DISPLAY_BUFFER_NUM 6 - -#define video_domain_addr(adr) (adr&0x7fffffff) -#define DECODER_WORK_SPACE_SIZE 0x800000 - -#define spec2canvas(x) \ - (((x)->uv_canvas_index << 16) | \ - ((x)->uv_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - - -static void set_canvas(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic) -{ - int canvas_w = ALIGN(pic->pic_w, 64)/4; - int canvas_h = ALIGN(pic->pic_h, 32)/4; - int blkmode = mem_map_mode; - struct vdec_s *vdec = hw_to_vdec(dec); - /*CANVAS_BLKMODE_64X32*/ - if (pic->double_write_mode) { - canvas_w = pic->pic_w / - get_double_write_ratio(dec, - pic->double_write_mode); - canvas_h = pic->pic_h / - get_double_write_ratio(dec, - pic->double_write_mode); - - if (mem_map_mode == 0) - canvas_w = ALIGN(canvas_w, 32); - else - canvas_w = ALIGN(canvas_w, 64); - canvas_h = ALIGN(canvas_h, 32); - - if (vdec->parallel_dec == 1) { - if (pic->y_canvas_index == -1) - pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - if (pic->uv_canvas_index == -1) - pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - } else { - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; - } - - canvas_config_ex(pic->y_canvas_index, - pic->dw_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic->uv_canvas_index, - pic->dw_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); -#ifdef MULTI_INSTANCE_SUPPORT - pic->canvas_config[0].phy_addr = - pic->dw_y_adr; - pic->canvas_config[0].width = - canvas_w; - pic->canvas_config[0].height = - canvas_h; - pic->canvas_config[0].block_mode = - blkmode; - pic->canvas_config[0].endian = 7; - - pic->canvas_config[1].phy_addr = - pic->dw_u_v_adr; - pic->canvas_config[1].width = - canvas_w; - pic->canvas_config[1].height = - canvas_h; - pic->canvas_config[1].block_mode = - blkmode; - pic->canvas_config[1].endian = 7; -#endif - } else { - #ifndef AVS2_10B_MMU - if (vdec->parallel_dec == 1) { - if (pic->y_canvas_index == -1) - pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - if (pic->uv_canvas_index == -1) - pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - } else { - pic->y_canvas_index = 128 + pic->index; - pic->uv_canvas_index = 128 + pic->index; - } - - canvas_config_ex(pic->y_canvas_index, - pic->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic->uv_canvas_index, - pic->mc_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - #endif - } -} - -static void set_frame_info(struct AVS2Decoder_s *dec, struct vframe_s *vf) -{ - unsigned int ar; - - vf->duration = dec->frame_dur; - vf->duration_pulldown = 0; - vf->flag = 0; - vf->prop.master_display_colour = dec->vf_dp; - vf->signal_type = dec->video_signal_type; - - ar = min_t(u32, dec->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - - return; -} - -static int vavs2_vf_states(struct vframe_states *states, void *op_arg) -{ - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg; - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&dec->newframe_q); - states->buf_avail_num = kfifo_len(&dec->display_q); - - if (step == 2) - states->buf_avail_num = 0; - return 0; -} - -static struct vframe_s *vavs2_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg; - if (step == 2) - return NULL; - - if (force_disp_pic_index & 0x100) { - if (force_disp_pic_index & 0x200) - return NULL; - return &dec->vframe_dummy; - } - - if (kfifo_peek(&dec->display_q, &vf)) - return vf; - - return NULL; -} - -static struct avs2_frame_s *get_pic_by_index( - struct AVS2Decoder_s *dec, int index) -{ - int i; - struct avs2_frame_s *pic = NULL; - if (index == (dec->used_buf_num - 1)) - pic = dec->avs2_dec.m_bg; - else if (index >= 0 && index < dec->used_buf_num) { - for (i = 0; i < dec->used_buf_num; i++) { - if (dec->avs2_dec.fref[i]->index == index) - pic = dec->avs2_dec.fref[i]; - } - } - return pic; -} - -static struct vframe_s *vavs2_vf_get(void *op_arg) -{ - struct vframe_s *vf; - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg; - if (step == 2) - return NULL; - else if (step == 1) - step = 2; - - if (force_disp_pic_index & 0x100) { - int idx = force_disp_pic_index & 0xff; - struct avs2_frame_s *pic = NULL; - if (idx >= 0 - && idx < dec->avs2_dec.ref_maxbuffer) - pic = get_pic_by_index(dec, idx); - if (pic == NULL) - return NULL; - if (force_disp_pic_index & 0x200) - return NULL; - - vf = &dec->vframe_dummy; - - set_vframe(dec, vf, pic, 1); - - force_disp_pic_index |= 0x200; - return vf; - } - - if (kfifo_get(&dec->display_q, &vf)) { - uint8_t index = vf->index & 0xff; - if (index >= 0 && index < dec->used_buf_num) { - struct avs2_frame_s *pic = get_pic_by_index(dec, index); - if (pic == NULL && - (debug & AVS2_DBG_PIC_LEAK)) { - int i; - avs2_print(dec, 0, - "%s error index 0x%x pic not exist\n", - __func__, index); - dump_pic_list(dec); - for (i = 0; i < 10; i++) { - pic = get_pic_by_index(dec, index); - pr_info("pic = %p\n", pic); - } - - if (debug & AVS2_DBG_PIC_LEAK) - debug |= AVS2_DBG_PIC_LEAK_WAIT; - return NULL; - } - dec->vf_get_count++; - if (pic) - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s index 0x%x pos %d getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n", - __func__, index, - pic->imgtr_fwRefDistance_bak, - dec->vf_get_count, - vf->type, - vf->width, vf->height, - vf->pts, - vf->pts_us64); - return vf; - } - } - return NULL; -} - -static void vavs2_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg; - uint8_t index = vf->index & 0xff; - - if (vf == (&dec->vframe_dummy)) - return; - - kfifo_put(&dec->newframe_q, (const struct vframe_s *)vf); - dec->vf_put_count++; - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s index putcount 0x%x %d\n", - __func__, vf->index, - dec->vf_put_count); - - if (index >= 0 - && index < dec->used_buf_num) { - unsigned long flags; - struct avs2_frame_s *pic; - - lock_buffer(dec, flags); - pic = get_pic_by_index(dec, index); - if (pic && pic->vf_ref > 0) - pic->vf_ref--; - else { - if (pic) - avs2_print(dec, 0, - "%s, error pic (index %d) vf_ref is %d\n", - __func__, index, pic->vf_ref); - else - avs2_print(dec, 0, - "%s, error pic (index %d) is NULL\n", - __func__, index); - } - if (dec->wait_buf) - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - dec->last_put_idx = index; - dec->new_frame_displayed++; - unlock_buffer(dec, flags); - } - -} - -static int vavs2_event_cb(int type, void *data, void *private_data) -{ - return 0; -} - -static struct avs2_frame_s *get_disp_pic(struct AVS2Decoder_s *dec) -{ - struct avs2_decoder *avs2_dec = &dec->avs2_dec; - struct avs2_frame_s *pic = NULL; - int32_t j; - int32_t pre_disp_count_min = 0x7fffffff; - for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { - if (avs2_dec->fref[j]->to_prepare_disp && - avs2_dec->fref[j]->to_prepare_disp < - pre_disp_count_min) { - pre_disp_count_min = - avs2_dec->fref[j]->to_prepare_disp; - pic = avs2_dec->fref[j]; - } - } - if (pic) - pic->to_prepare_disp = 0; - - return pic; - -} - - - -static void fill_frame_info(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic, unsigned int framesize, unsigned int pts) -{ - struct vframe_qos_s *vframe_qos = &dec->vframe_qos; - - if (pic->slice_type == I_IMG) - vframe_qos->type = 1; - else if (pic->slice_type == P_IMG) - vframe_qos->type = 2; - else if (pic->slice_type == B_IMG) - vframe_qos->type = 3; -/* -#define SHOW_QOS_INFO -*/ - vframe_qos->size = framesize; - vframe_qos->pts = pts; -#ifdef SHOW_QOS_INFO - avs2_print(dec, 0, "slice:%d\n", pic->slice_type); -#endif - - - vframe_qos->max_mv = pic->max_mv; - vframe_qos->avg_mv = pic->avg_mv; - vframe_qos->min_mv = pic->min_mv; -#ifdef SHOW_QOS_INFO - avs2_print(dec, 0, "mv: max:%d, avg:%d, min:%d\n", - vframe_qos->max_mv, - vframe_qos->avg_mv, - vframe_qos->min_mv); -#endif - - vframe_qos->max_qp = pic->max_qp; - vframe_qos->avg_qp = pic->avg_qp; - vframe_qos->min_qp = pic->min_qp; -#ifdef SHOW_QOS_INFO - avs2_print(dec, 0, "qp: max:%d, avg:%d, min:%d\n", - vframe_qos->max_qp, - vframe_qos->avg_qp, - vframe_qos->min_qp); -#endif - - vframe_qos->max_skip = pic->max_skip; - vframe_qos->avg_skip = pic->avg_skip; - vframe_qos->min_skip = pic->min_skip; -#ifdef SHOW_QOS_INFO - avs2_print(dec, 0, "skip: max:%d, avg:%d, min:%d\n", - vframe_qos->max_skip, - vframe_qos->avg_skip, - vframe_qos->min_skip); -#endif - - vframe_qos->num++; - - if (dec->frameinfo_enable) - vdec_fill_frame_info(vframe_qos, 1); -} - -static void set_vframe(struct AVS2Decoder_s *dec, - struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy) -{ - unsigned long flags; - int stream_offset; - unsigned int frame_size; - int pts_discontinue; - stream_offset = pic->stream_offset; - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s index = %d pos = %d\r\n", - __func__, pic->index, - pic->imgtr_fwRefDistance); - - if (pic->double_write_mode) - set_canvas(dec, pic); - - display_frame_count[dec->index]++; - - if (!dummy) { -#ifdef MULTI_INSTANCE_SUPPORT - if (vdec_frame_based(hw_to_vdec(dec))) { - vf->pts = pic->pts; - vf->pts_us64 = pic->pts64; - } else -#endif - /* if (pts_lookup_offset(PTS_TYPE_VIDEO, - stream_offset, &vf->pts, 0) != 0) { */ - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, - &vf->pts, &frame_size, 0, - &vf->pts_us64) != 0) { -#ifdef DEBUG_PTS - dec->pts_missed++; -#endif - vf->pts = 0; - vf->pts_us64 = 0; - } -#ifdef DEBUG_PTS - else - dec->pts_hit++; -#endif - if (pts_unstable) - dec->pts_mode = PTS_NONE_REF_USE_DURATION; - - fill_frame_info(dec, pic, frame_size, vf->pts); - - if ((dec->pts_mode == PTS_NORMAL) && (vf->pts != 0) - && dec->get_frame_dur) { - int pts_diff = (int)vf->pts - dec->last_lookup_pts; - - if (pts_diff < 0) { - dec->pts_mode_switching_count++; - dec->pts_mode_recovery_count = 0; - - if (dec->pts_mode_switching_count >= - PTS_MODE_SWITCHING_THRESHOLD) { - dec->pts_mode = - PTS_NONE_REF_USE_DURATION; - pr_info - ("HEVC: switch to n_d mode.\n"); - } - - } else { - int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD; - dec->pts_mode_recovery_count++; - if (dec->pts_mode_recovery_count > p) { - dec->pts_mode_switching_count = 0; - dec->pts_mode_recovery_count = 0; - } - } - } - - pts_discontinue = - (abs(dec->last_pts - vf->pts) >= - tsync_vpts_discontinuity_margin()); - - if (vf->pts != 0) - dec->last_lookup_pts = vf->pts; -#if 1 - if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) - && ((pic->slice_type != I_IMG) || (!pts_discontinue && - !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) - vf->pts = dec->last_pts + DUR2PTS(dec->frame_dur); -#endif - dec->last_pts = vf->pts; - - if (vf->pts_us64 != 0) - dec->last_lookup_pts_us64 = vf->pts_us64; - -#if 1 - if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) - && ((pic->slice_type != I_IMG) || (!pts_discontinue && - !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) { - vf->pts_us64 = - dec->last_pts_us64 + - (DUR2PTS(dec->frame_dur) * 100 / 9); - } -#endif - dec->last_pts_us64 = vf->pts_us64; - avs2_print(dec, AVS2_DBG_OUT_PTS, - "avs2 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n", - vf->pts, vf->pts_us64); - } - - vf->index = 0xff00 | pic->index; - - if (pic->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { -#ifdef AVS2_10B_MMU - vf->compBodyAddr = 0; - vf->compHeadAddr = pic->header_adr; -#else - vf->compBodyAddr = pic->mc_y_adr; /*body adr*/ - vf->compHeadAddr = pic->mc_y_adr + - pic->comp_body_size; - /*head adr*/ -#endif - } - if (pic->double_write_mode) { - vf->type = VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if (pic->double_write_mode == 3) { - vf->type |= VIDTYPE_COMPRESS; -#ifdef AVS2_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif - } -#ifdef MULTI_INSTANCE_SUPPORT - if (dec->m_ins_flag) { - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - pic->canvas_config[0]; - vf->canvas0_config[1] = - pic->canvas_config[1]; - - vf->canvas1_config[0] = - pic->canvas_config[0]; - vf->canvas1_config[1] = - pic->canvas_config[1]; - - } else -#endif - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(pic); - } else { - vf->canvas0Addr = vf->canvas1Addr = 0; - vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; -#ifdef AVS2_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif - } - - switch (pic->bit_depth) { - case AVS2_BITS_8: - vf->bitdepth = BITDEPTH_Y8 | - BITDEPTH_U8 | BITDEPTH_V8; - break; - case AVS2_BITS_10: - case AVS2_BITS_12: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - default: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - } - if ((vf->type & VIDTYPE_COMPRESS) == 0) - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - if (pic->bit_depth == AVS2_BITS_8) - vf->bitdepth |= BITDEPTH_SAVING_MODE; - - set_frame_info(dec, vf); - /* if((vf->width!=pic->width)| - (vf->height!=pic->height)) */ - /* pr_info("aaa: %d/%d, %d/%d\n", - vf->width,vf->height, pic->width, - pic->height); */ - vf->width = pic->pic_w / - get_double_write_ratio(dec, - pic->double_write_mode); - vf->height = pic->pic_h / - get_double_write_ratio(dec, - pic->double_write_mode); - if (force_w_h != 0) { - vf->width = (force_w_h >> 16) & 0xffff; - vf->height = force_w_h & 0xffff; - } - vf->compWidth = pic->pic_w; - vf->compHeight = pic->pic_h; - if (force_fps & 0x100) { - u32 rate = force_fps & 0xff; - if (rate) - vf->duration = 96000/rate; - else - vf->duration = 0; - } -#ifdef AVS2_10B_MMU - if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = decoder_mmu_box_get_mem_handle( - dec->mmu_box, - pic->index); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - } else { - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - VF_BUFFER_IDX(pic->index)); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - } -#else - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - VF_BUFFER_IDX(pic->index)); -#endif - - if (!dummy) { - lock_buffer(dec, flags); - pic->vf_ref = 1; - unlock_buffer(dec, flags); - } - dec->vf_pre_count++; -} - - -static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) -{ -#ifndef NO_DISPLAY - struct vframe_s *vf = NULL; - /*unsigned short slice_type;*/ - struct avs2_frame_s *pic; - while (1) { - pic = get_disp_pic(dec); - if (pic == NULL) - break; - - if (force_disp_pic_index & 0x100) { - /*recycle directly*/ - continue; - } - - if (pic->error_mark) { - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "!!!error pic, skip\n", - 0); - continue; - } - - if (dec->start_decoding_flag != 0) { - if (dec->skip_PB_before_I && - pic->slice_type != I_IMG) { - avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "!!!slice type %d (not I) skip\n", - 0, pic->slice_type); - continue; - } - dec->skip_PB_before_I = 0; - } - - if (kfifo_get(&dec->newframe_q, &vf) == 0) { - pr_info("fatal error, no available buffer slot."); - return -1; - } - - if (vf) { - set_vframe(dec, vf, pic, 0); - decoder_do_frame_check(hw_to_vdec(dec), vf); - kfifo_put(&dec->display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - /*count info*/ - gvs->frame_dur = dec->frame_dur; - vdec_count_info(gvs, 0, stream_offset); - #endif - hw_to_vdec(dec)->vdec_fps_detec(hw_to_vdec(dec)->id); - vf_notify_receiver(dec->provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - } -/*!NO_DISPLAY*/ -#endif - return 0; -} - -static void get_rpm_param(union param_u *params) -{ - int i; - unsigned int data32; - if (debug & AVS2_DBG_BUFMGR) - pr_info("enter %s\r\n", __func__); - for (i = 0; i < (RPM_END - RPM_BEGIN); i++) { - do { - data32 = READ_VREG(RPM_CMD_REG); - /*pr_info("%x\n", data32);*/ - } while ((data32 & 0x10000) == 0); - params->l.data[i] = data32&0xffff; - /*pr_info("%x\n", data32);*/ - WRITE_VREG(RPM_CMD_REG, 0); - } - if (debug & AVS2_DBG_BUFMGR) - pr_info("leave %s\r\n", __func__); -} -static void debug_buffer_mgr_more(struct AVS2Decoder_s *dec) -{ - int i; - if (!(debug & AVS2_DBG_BUFMGR_MORE)) - return; - pr_info("avs2_param: (%d)\n", dec->avs2_dec.img.number); - for (i = 0; i < (RPM_END-RPM_BEGIN); i++) { - pr_info("%04x ", dec->avs2_dec.param.l.data[i]); - if (((i + 1) & 0xf) == 0) - pr_info("\n"); - } -} - -#ifdef AVS2_10B_MMU -static void avs2_recycle_mmu_buf_tail(struct AVS2Decoder_s *dec) -{ - if (dec->cur_fb_idx_mmu != INVALID_IDX) { - if (dec->used_4k_num == -1) - dec->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - decoder_mmu_box_free_idx_tail(dec->mmu_box, - dec->cur_fb_idx_mmu, dec->used_4k_num); - - dec->cur_fb_idx_mmu = INVALID_IDX; - dec->used_4k_num = -1; - } -} - -static void avs2_recycle_mmu_buf(struct AVS2Decoder_s *dec) -{ - if (dec->cur_fb_idx_mmu != INVALID_IDX) { - decoder_mmu_box_free_idx(dec->mmu_box, - dec->cur_fb_idx_mmu); - - dec->cur_fb_idx_mmu = INVALID_IDX; - dec->used_4k_num = -1; - } -} -#endif - -static void dec_again_process(struct AVS2Decoder_s *dec) -{ - amhevc_stop(); - dec->dec_result = DEC_RESULT_AGAIN; - if (dec->process_state == - PROC_STATE_DECODING) { - dec->process_state = - PROC_STATE_DECODE_AGAIN; - } else if (dec->process_state == - PROC_STATE_HEAD_DONE) { - dec->process_state = - PROC_STATE_HEAD_AGAIN; - } - dec->next_again_flag = 1; - reset_process_time(dec); - vdec_schedule_work(&dec->work); -} - -static uint32_t log2i(uint32_t val) -{ - uint32_t ret = -1; - while (val != 0) { - val >>= 1; - ret++; - } - return ret; -} - -static void check_pic_error(struct AVS2Decoder_s *dec, - struct avs2_frame_s *pic) -{ - if (pic->decoded_lcu == 0) { - pic->decoded_lcu = - (READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff) + 1; - } - if (pic->decoded_lcu != dec->avs2_dec.lcu_total) { - avs2_print(dec, AVS2_DBG_BUFMGR, - "%s error pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", - __func__, pic->index, pic->imgtr_fwRefDistance, - pic->decoded_lcu, dec->avs2_dec.lcu_total); - pic->error_mark = 1; - } else { - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", - __func__, pic->index, pic->imgtr_fwRefDistance, - pic->decoded_lcu, dec->avs2_dec.lcu_total); - - } -} -static void update_decoded_pic(struct AVS2Decoder_s *dec) -{ - struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; - if (pic) { - dec->avs2_dec.hc.cur_pic->decoded_lcu = - (READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff) + 1; - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", - __func__, pic->index, pic->imgtr_fwRefDistance, - pic->decoded_lcu, dec->avs2_dec.lcu_total); - } -} -/* +[SE] [BUG][BUG-171463][chuanqi.wang]: get frame rate by video sequeue*/ -static int get_frame_rate(union param_u *params, struct AVS2Decoder_s *dec) -{ - int tmp = 0; - - switch (params->p.frame_rate_code) { - case 1: - case 2: - tmp = 24; - break; - case 3: - tmp = 25; - break; - case 4: - case 5: - tmp = 30; - break; - case 6: - tmp = 50; - break; - case 7: - case 8: - tmp = 60; - break; - case 9: - tmp = 100; - break; - case 10: - tmp = 120; - break; - default: - tmp = 25; - break; - } - - if (!params->p.progressive_sequence) - tmp = tmp / 2; - dec->frame_dur = div_u64(96000ULL, tmp); - dec->get_frame_dur = true; - /*avs2_print(dec, 0, "avs2 frame_dur:%d,progressive:%d\n", dec->frame_dur, params->p.progressive_sequence);*/ - return 0; -} - - -#define HEVC_MV_INFO 0x310d -#define HEVC_QP_INFO 0x3137 -#define HEVC_SKIP_INFO 0x3136 - -/* only when we decoded one field or one frame, -we can call this function to get qos info*/ -static void get_picture_qos_info(struct AVS2Decoder_s *dec) -{ - struct avs2_frame_s *picture = dec->avs2_dec.hc.cur_pic; - if (!picture) { - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s decode picture is none exist\n"); - - return; - } - -/* -#define DEBUG_QOS -*/ - - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { - unsigned char a[3]; - unsigned char i, j, t; - unsigned long data; - - data = READ_VREG(HEVC_MV_INFO); - if (picture->slice_type == I_IMG) - data = 0; - a[0] = data & 0xff; - a[1] = (data >> 8) & 0xff; - a[2] = (data >> 16) & 0xff; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_mv = a[2]; - picture->avg_mv = a[1]; - picture->min_mv = a[0]; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); -#endif - - data = READ_VREG(HEVC_QP_INFO); - a[0] = data & 0x1f; - a[1] = (data >> 8) & 0x3f; - a[2] = (data >> 16) & 0x7f; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_qp = a[2]; - picture->avg_qp = a[1]; - picture->min_qp = a[0]; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); -#endif - - data = READ_VREG(HEVC_SKIP_INFO); - a[0] = data & 0x1f; - a[1] = (data >> 8) & 0x3f; - a[2] = (data >> 16) & 0x7f; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_skip = a[2]; - picture->avg_skip = a[1]; - picture->min_skip = a[0]; - -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); -#endif - } else { - uint32_t blk88_y_count; - uint32_t blk88_c_count; - uint32_t blk22_mv_count; - uint32_t rdata32; - int32_t mv_hi; - int32_t mv_lo; - uint32_t rdata32_l; - uint32_t mvx_L0_hi; - uint32_t mvy_L0_hi; - uint32_t mvx_L1_hi; - uint32_t mvy_L1_hi; - int64_t value; - uint64_t temp_value; -#ifdef DEBUG_QOS - int pic_number = 0; -#endif - - picture->max_mv = 0; - picture->avg_mv = 0; - picture->min_mv = 0; - - picture->max_skip = 0; - picture->avg_skip = 0; - picture->min_skip = 0; - - picture->max_qp = 0; - picture->avg_qp = 0; - picture->min_qp = 0; - - - -#ifdef DEBUG_QOS - avs2_print(dec, 0, "slice_type:%d, poc:%d\n", - picture->slice_type, - pic_number); -#endif - /* set rd_idx to 0 */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); - - blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); - if (blk88_y_count == 0) { -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* qp_y_sum */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_y_count, - rdata32, blk88_y_count); -#endif - picture->avg_qp = rdata32/blk88_y_count; - /* intra_y_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] Y intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - /* skipped_y_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - picture->avg_skip = rdata32*100/blk88_y_count; - /* coeff_non_zero_y_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_y_count*1)), - '%', rdata32); -#endif - /* blk66_c_count */ - blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); - if (blk88_c_count == 0) { -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* qp_c_sum */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_c_count, - rdata32, blk88_c_count); -#endif - /* intra_c_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] C intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* skipped_cu_c_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] C skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* coeff_non_zero_c_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_c_count*1)), - '%', rdata32); -#endif - - /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], - 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] Y QP min : %d\n", - pic_number, (rdata32>>0)&0xff); -#endif - picture->min_qp = (rdata32>>0)&0xff; - -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] Y QP max : %d\n", - pic_number, (rdata32>>8)&0xff); -#endif - picture->max_qp = (rdata32>>8)&0xff; - -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] C QP min : %d\n", - pic_number, (rdata32>>16)&0xff); - avs2_print(dec, 0, "[Picture %d Quality] C QP max : %d\n", - pic_number, (rdata32>>24)&0xff); -#endif - - /* blk22_mv_count */ - blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); - if (blk22_mv_count == 0) { -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] NO MV Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* mvy_L1_count[39:32], mvx_L1_count[39:32], - mvy_L0_count[39:32], mvx_L0_count[39:32] */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - /* should all be 0x00 or 0xff */ -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] MV AVG High Bits: 0x%X\n", - pic_number, rdata32); -#endif - mvx_L0_hi = ((rdata32>>0)&0xff); - mvy_L0_hi = ((rdata32>>8)&0xff); - mvx_L1_hi = ((rdata32>>16)&0xff); - mvy_L1_hi = ((rdata32>>24)&0xff); - - /* mvx_L0_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvx_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvx_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; - value = div_s64(value, blk22_mv_count); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", - pic_number, (int)value, - value, blk22_mv_count); -#endif - picture->avg_mv = value; - - /* mvy_L0_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvy_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvy_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvx_L1_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvx_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvx_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvy_L1_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvy_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvy_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - picture->max_mv = mv_hi; - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - picture->min_mv = mv_lo; - - /* {mvy_L0_max, mvy_L0_min} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvx_L1_max, mvx_L1_min} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvy_L1_max, mvy_L1_min} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); -#ifdef DEBUG_QOS - avs2_print(dec, 0, - "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", - pic_number, rdata32); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - } -} - -static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) -{ - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data; - unsigned int dec_status = dec->dec_status; - int i, ret; - int32_t start_code = 0; - - /*if (dec->wait_buf) - pr_info("set wait_buf to 0\r\n"); - */ - - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s decode_status 0x%x process_state %d lcu 0x%x\n", - __func__, dec_status, dec->process_state, - READ_VREG(HEVC_PARSER_LCU_START)); - -#ifndef G12A_BRINGUP_DEBUG - if (dec->eos) { - PRINT_LINE(); - goto irq_handled_exit; - } -#endif - dec->wait_buf = 0; - if (dec_status == AVS2_DECODE_BUFEMPTY) { - PRINT_LINE(); - if (dec->m_ins_flag) { - reset_process_time(dec); - if (!vdec_frame_based(hw_to_vdec(dec))) - dec_again_process(dec); - else { - dec->dec_result = DEC_RESULT_DONE; - reset_process_time(dec); - amhevc_stop(); - vdec_schedule_work(&dec->work); - } - } - goto irq_handled_exit; - } else if (dec_status == HEVC_DECPIC_DATA_DONE) { - PRINT_LINE(); - dec->start_decoding_flag |= 0x3; - if (dec->m_ins_flag) { - update_decoded_pic(dec); - get_picture_qos_info(dec); - reset_process_time(dec); - dec->dec_result = DEC_RESULT_DONE; - amhevc_stop(); -#if 0 /*def AVS2_10B_MMU*/ - if (dec->m_ins_flag) { - /*avs2_recycle_mmu_buf_tail(dec);*/ - dec->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - } -#endif - -#if 0 - /*keep hardware state*/ - WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); - WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); - dec->mpred_abv_start_addr = - READ_VREG(HEVC_MPRED_ABV_START_ADDR); - /**/ -#endif - vdec_schedule_work(&dec->work); - } - goto irq_handled_exit; - } - PRINT_LINE(); -#if 0 - if (dec_status == AVS2_EOS) { - if (dec->m_ins_flag) - reset_process_time(dec); - - avs2_print(dec, AVS2_DBG_BUFMGR, - "AVS2_EOS, flush buffer\r\n"); - - avs2_post_process(&dec->avs2_dec); - avs2_prepare_display_buf(dec); - - avs2_print(dec, AVS2_DBG_BUFMGR, - "send AVS2_10B_DISCARD_NAL\r\n"); - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL); - if (dec->m_ins_flag) { - update_decoded_pic(dec); - dec->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - vdec_schedule_work(&dec->work); - } - goto irq_handled_exit; - } else -#endif - if (dec_status == AVS2_DECODE_OVER_SIZE) { - avs2_print(dec, 0, - "avs2 decode oversize !!\n"); - debug |= (AVS2_DBG_DIS_LOC_ERROR_PROC | - AVS2_DBG_DIS_SYS_ERROR_PROC); - dec->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - if (dec->m_ins_flag) - reset_process_time(dec); - goto irq_handled_exit; - } - PRINT_LINE(); - - if (dec->m_ins_flag) - reset_process_time(dec); - - if (dec_status == AVS2_HEAD_SEQ_READY) - start_code = SEQUENCE_HEADER_CODE; - else if (dec_status == AVS2_HEAD_PIC_I_READY) - start_code = I_PICTURE_START_CODE; - else if (dec_status == AVS2_HEAD_PIC_PB_READY) - start_code = PB_PICTURE_START_CODE; - else if (dec_status == AVS2_STARTCODE_SEARCH_DONE) - /*SEQUENCE_END_CODE, VIDEO_EDIT_CODE*/ - start_code = READ_VREG(CUR_NAL_UNIT_TYPE); - - if (dec->process_state == - PROC_STATE_HEAD_AGAIN - ) { - if ((start_code == I_PICTURE_START_CODE) - || (start_code == PB_PICTURE_START_CODE)) { - avs2_print(dec, 0, - "PROC_STATE_HEAD_AGAIN error, start_code 0x%x!!!\r\n", - start_code); - goto irq_handled_exit; - } else { - avs2_print(dec, AVS2_DBG_BUFMGR, - "PROC_STATE_HEAD_AGAIN, start_code 0x%x\r\n", - start_code); - dec->process_state = PROC_STATE_HEAD_DONE; - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - goto irq_handled_exit; - } - } else if (dec->process_state == - PROC_STATE_DECODE_AGAIN) { - if ((start_code == I_PICTURE_START_CODE) - || (start_code == PB_PICTURE_START_CODE)) { - avs2_print(dec, AVS2_DBG_BUFMGR, - "PROC_STATE_DECODE_AGAIN=> decode_slice, start_code 0x%x\r\n", - start_code); - goto decode_slice; - } else { - avs2_print(dec, 0, - "PROC_STATE_DECODE_AGAIN, start_code 0x%x!!!\r\n", - start_code); - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - goto irq_handled_exit; - } - } - - if ((start_code == I_PICTURE_START_CODE) - || (start_code == PB_PICTURE_START_CODE) - || (start_code == SEQUENCE_END_CODE) - || (start_code == VIDEO_EDIT_CODE)) { - PRINT_LINE(); - - if (dec->avs2_dec.hc.cur_pic != NULL) { - int32_t ii; -#ifdef AVS2_10B_MMU - avs2_recycle_mmu_buf_tail(dec); -#endif - check_pic_error(dec, dec->avs2_dec.hc.cur_pic); - avs2_post_process(&dec->avs2_dec); - - if (debug & AVS2_DBG_PRINT_PIC_LIST) - dump_pic_list(dec); - - avs2_prepare_display_buf(dec); - dec->avs2_dec.hc.cur_pic = NULL; - for (ii = 0; ii < dec->avs2_dec.ref_maxbuffer; - ii++) { - if (dec->avs2_dec.fref[ii]-> - bg_flag == 0 && - dec->avs2_dec.fref[ii]-> - is_output == -1 && - dec->avs2_dec.fref[ii]-> - mmu_alloc_flag && - dec->avs2_dec.fref[ii]-> - vf_ref == 0) { - struct avs2_frame_s *pic = - dec->avs2_dec.fref[ii]; - if (dec->avs2_dec.fref[ii]-> - refered_by_others == 0) { -#ifdef AVS2_10B_MMU - dec->avs2_dec.fref[ii]-> - mmu_alloc_flag = 0; - /*release_buffer_4k( - dec->avs2_dec.fref[ii]->index);*/ - decoder_mmu_box_free_idx(dec->mmu_box, - dec->avs2_dec.fref[ii]->index); -#ifdef DYNAMIC_ALLOC_HEAD - decoder_bmmu_box_free_idx( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - pic->header_adr = 0; -#endif -#endif -#ifndef MV_USE_FIXED_BUF - decoder_bmmu_box_free_idx( - dec->bmmu_box, - MV_BUFFER_IDX(pic->index)); - pic->mpred_mv_wr_start_addr = 0; -#endif - } - decoder_bmmu_box_free_idx( - dec->bmmu_box, - VF_BUFFER_IDX(pic->index)); - dec->cma_alloc_addr = 0; - } - } - } - } - - if ((dec_status == AVS2_HEAD_PIC_I_READY) - || (dec_status == AVS2_HEAD_PIC_PB_READY)) { - PRINT_LINE(); - - if (debug & AVS2_DBG_SEND_PARAM_WITH_REG) { - get_rpm_param( - &dec->avs2_dec.param); - } else { - PRINT_LINE(); - dma_sync_single_for_cpu( - amports_get_dma_device(), - dec->rpm_phy_addr, - RPM_BUF_SIZE, - DMA_FROM_DEVICE); - - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) - dec->avs2_dec.param.l.data[i + ii] = - dec->rpm_ptr[i + 3 - ii]; - } - } -#ifdef SANITY_CHECK - if (dec->avs2_dec.param.p.num_of_ref_cur > - dec->avs2_dec.ref_maxbuffer) { - pr_info("Warning: Wrong num_of_ref_cur %d, force to %d\n", - dec->avs2_dec.param.p.num_of_ref_cur, - dec->avs2_dec.ref_maxbuffer); - dec->avs2_dec.param.p.num_of_ref_cur = - dec->avs2_dec.ref_maxbuffer; - } -#endif - PRINT_LINE(); - - debug_buffer_mgr_more(dec); - get_frame_rate(&dec->avs2_dec.param, dec); - - if (dec->avs2_dec.param.p.video_signal_type - & (1<<30)) { - union param_u *pPara; - - avs2_print(dec, 0, - "avs2 HDR meta data present\n"); - pPara = &dec->avs2_dec.param; - - /*clean this flag*/ - pPara->p.video_signal_type - &= ~(1<<30); - - dec->vf_dp.present_flag = 1; - - dec->vf_dp.white_point[0] - = pPara->p.white_point_x; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "white_point[0]:0x%x\n", - dec->vf_dp.white_point[0]); - - dec->vf_dp.white_point[1] - = pPara->p.white_point_y; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "white_point[1]:0x%x\n", - dec->vf_dp.white_point[1]); - - for (i = 0; i < 3; i++) { - dec->vf_dp.primaries[i][0] - = pPara->p.display_primaries_x[i]; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "primaries[%d][0]:0x%x\n", - i, - dec->vf_dp.primaries[i][0]); - } - - for (i = 0; i < 3; i++) { - dec->vf_dp.primaries[i][1] - = pPara->p.display_primaries_y[i]; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "primaries[%d][1]:0x%x\n", - i, - dec->vf_dp.primaries[i][1]); - } - - dec->vf_dp.luminance[0] - = pPara->p.max_display_mastering_luminance; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "luminance[0]:0x%x\n", - dec->vf_dp.luminance[0]); - - dec->vf_dp.luminance[1] - = pPara->p.min_display_mastering_luminance; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "luminance[1]:0x%x\n", - dec->vf_dp.luminance[1]); - - - dec->vf_dp.content_light_level.present_flag - = 1; - dec->vf_dp.content_light_level.max_content - = pPara->p.max_content_light_level; - avs2_print(dec, AVS2_DBG_HDR_INFO, - "max_content:0x%x\n", - dec->vf_dp.content_light_level.max_content); - - dec->vf_dp.content_light_level.max_pic_average - = pPara->p.max_picture_average_light_level; - - avs2_print(dec, AVS2_DBG_HDR_INFO, - "max_pic_average:0x%x\n", - dec->vf_dp.content_light_level.max_pic_average); - } - - - if (dec->video_ori_signal_type != - ((dec->avs2_dec.param.p.video_signal_type << 16) - | dec->avs2_dec.param.p.color_description)) { - u32 v = dec->avs2_dec.param.p.video_signal_type; - u32 c = dec->avs2_dec.param.p.color_description; - u32 convert_c = c; - - if (v & 0x2000) { - avs2_print(dec, 0, - "video_signal_type present:\n"); - avs2_print(dec, 0, - " %s %s\n", - video_format_names[(v >> 10) & 7], - ((v >> 9) & 1) ? - "full_range" : "limited"); - if (v & 0x100) { - u32 transfer; - u32 maxtrix; - - avs2_print(dec, 0, - "color_description present:\n"); - avs2_print(dec, 0, - "color_primarie = %d\n", - v & 0xff); - avs2_print(dec, 0, - "transfer_characteristic = %d\n", - (c >> 8) & 0xff); - avs2_print(dec, 0, - " matrix_coefficient = %d\n", - c & 0xff); - - transfer = (c >> 8) & 0xFF; - if (transfer >= 15) - avs2_print(dec, 0, - "unsupport transfer_characteristic\n"); - else if (transfer == 14) - transfer = 18; /* HLG */ - else if (transfer == 13) - transfer = 32; - else if (transfer == 12) - transfer = 16; - else if (transfer == 11) - transfer = 15; - - maxtrix = c & 0xFF; - if (maxtrix >= 10) - avs2_print(dec, 0, - "unsupport matrix_coefficient\n"); - else if (maxtrix == 9) - maxtrix = 10; - else if (maxtrix == 8) - maxtrix = 9; - - convert_c = (transfer << 8) | (maxtrix); - - avs2_print(dec, 0, - " convered c:0x%x\n", - convert_c); - } - } - - if (enable_force_video_signal_type) - dec->video_signal_type - = force_video_signal_type; - else { - dec->video_signal_type - = (v << 16) | convert_c; - - dec->video_ori_signal_type - = (v << 16) | c; - } - - video_signal_type = dec->video_signal_type; - } - } -#if 0 - if ((debug_again & 0x4) && - dec->process_state == - PROC_STATE_INIT) { - if (start_code == PB_PICTURE_START_CODE) { - dec->process_state = PROC_STATE_TEST1; - dec_again_process(dec); - goto irq_handled_exit; - } - } -#endif - PRINT_LINE(); - avs2_prepare_header(&dec->avs2_dec, start_code); - - if (start_code == SEQUENCE_HEADER_CODE || - start_code == VIDEO_EDIT_CODE || - start_code == SEQUENCE_END_CODE) { - if (dec->m_ins_flag && - vdec_frame_based(hw_to_vdec(dec))) - dec->start_decoding_flag |= 0x1; - dec->process_state = PROC_STATE_HEAD_DONE; - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - } else if (start_code == I_PICTURE_START_CODE || - start_code == PB_PICTURE_START_CODE) { - ret = 0; - if (dec->pic_list_init_flag == 0) { - int32_t lcu_size_log2 = - log2i(dec->avs2_dec.param.p.lcu_size); - - avs2_init_global_buffers(&dec->avs2_dec); - /*avs2_dec->m_bg->index is - set to dec->used_buf_num - 1*/ - init_pic_list(dec, lcu_size_log2); - init_pic_list_hw(dec); - } - ret = avs2_process_header(&dec->avs2_dec); - if (!dec->m_ins_flag) - dec->slice_idx++; - - PRINT_LINE(); -#ifdef I_ONLY_SUPPORT - if ((start_code == PB_PICTURE_START_CODE) && - (dec->i_only & 0x2)) - ret = -2; -#endif -#ifdef AVS2_10B_MMU - if (ret >= 0) { - ret = avs2_alloc_mmu(dec, - dec->avs2_dec.hc.cur_pic->index, - dec->avs2_dec.img.width, - dec->avs2_dec.img.height, - dec->avs2_dec.input.sample_bit_depth, - dec->frame_mmu_map_addr); - if (ret >= 0) { - dec->cur_fb_idx_mmu = - dec->avs2_dec.hc.cur_pic->index; - dec->avs2_dec.hc.cur_pic->mmu_alloc_flag = 1; - } else - pr_err("can't alloc need mmu1,idx %d ret =%d\n", - dec->avs2_dec.hc.cur_pic->index, - ret); - } -#endif - -#ifndef MV_USE_FIXED_BUF - if (ret >= 0 && - dec->avs2_dec.hc.cur_pic-> - mpred_mv_wr_start_addr == 0) { - unsigned long buf_addr; - unsigned mv_buf_size = 0x120000; - int i = dec->avs2_dec.hc.cur_pic->index; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - mv_buf_size = 0x120000 * 4; - if (decoder_bmmu_box_alloc_buf_phy - (dec->bmmu_box, - MV_BUFFER_IDX(i), - mv_buf_size, - DRIVER_NAME, - &buf_addr) < 0) - ret = -1; - else - dec->avs2_dec.hc.cur_pic-> - mpred_mv_wr_start_addr - = buf_addr; - } -#endif - if (ret < 0) { - avs2_print(dec, AVS2_DBG_BUFMGR, - "avs2_bufmgr_process=> %d, AVS2_10B_DISCARD_NAL\r\n", - ret); - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL); - #ifdef AVS2_10B_MMU - avs2_recycle_mmu_buf(dec); - #endif - if (dec->m_ins_flag) { - dec->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - vdec_schedule_work(&dec->work); - } - - goto irq_handled_exit; - } else { - PRINT_LINE(); - dec->avs2_dec.hc.cur_pic->stream_offset = - READ_VREG(HEVC_SHIFT_BYTE_COUNT); - /* - struct PIC_BUFFER_CONFIG_s *cur_pic - = &cm->cur_frame->buf; - cur_pic->decode_idx = dec->frame_count; - */ - if (!dec->m_ins_flag) { - dec->frame_count++; - decode_frame_count[dec->index] - = dec->frame_count; - } - /*MULTI_INSTANCE_SUPPORT*/ - if (dec->chunk) { - dec->avs2_dec.hc.cur_pic->pts = - dec->chunk->pts; - dec->avs2_dec.hc.cur_pic->pts64 = - dec->chunk->pts64; - } - /**/ - dec->avs2_dec.hc.cur_pic->bit_depth - = dec->avs2_dec.input.sample_bit_depth; - dec->avs2_dec.hc.cur_pic->double_write_mode - = get_double_write_mode(dec); -decode_slice: - PRINT_LINE(); - - config_mc_buffer(dec); - config_mcrcc_axi_hw(dec); - config_mpred_hw(dec); - config_dblk_hw(dec); - config_sao_hw(dec); - config_alf_hw(dec); - config_other_hw(dec); - - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "=>fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, dis2/dis3/dis4 %d %d %d img->tr %d\n", - dec->avs2_dec.fref[0]->imgtr_fwRefDistance, - dec->avs2_dec.fref[1]->imgtr_fwRefDistance, - dec->avs2_dec.fref[2]->imgtr_fwRefDistance, - dec->avs2_dec.fref[3]->imgtr_fwRefDistance, - dec->avs2_dec.fref[4]->imgtr_fwRefDistance, - dec->avs2_dec.img.tr); - - if ((debug_again & 0x2) && - dec->process_state == - PROC_STATE_INIT) { - dec->process_state = PROC_STATE_DECODING; - dec_again_process(dec); - goto irq_handled_exit; - } - - dec->process_state = PROC_STATE_DECODING; - - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - - } - - if (dec->m_ins_flag) - start_process_time(dec); - } -irq_handled_exit: - PRINT_LINE(); - dec->process_busy = 0; - return IRQ_HANDLED; -} - -static irqreturn_t vavs2_isr(int irq, void *data) -{ - int i; - unsigned int dec_status; - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data; - uint debug_tag; - - WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); - - dec_status = READ_VREG(HEVC_DEC_STATUS_REG); - - if (!dec) - return IRQ_HANDLED; - if (dec->init_flag == 0) - return IRQ_HANDLED; - if (dec->process_busy)/*on process.*/ - return IRQ_HANDLED; - dec->dec_status = dec_status; - dec->process_busy = 1; - if (debug & AVS2_DBG_IRQ_EVENT) - avs2_print(dec, 0, - "avs2 isr dec status = 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n", - dec_status, READ_VREG(HEVC_PARSER_LCU_START), - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_STREAM_START_ADDR), - READ_VREG(HEVC_STREAM_END_ADDR), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR) - ); - - debug_tag = READ_HREG(DEBUG_REG1); - if (debug_tag & 0x10000) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - dec->lmem_phy_addr, - LMEM_BUF_SIZE, - DMA_FROM_DEVICE); - - pr_info("LMEM:\n", READ_HREG(DEBUG_REG1)); - for (i = 0; i < 0x400; i += 4) { - int ii; - if ((i & 0xf) == 0) - pr_info("%03x: ", i); - for (ii = 0; ii < 4; ii++) { - pr_info("%04x ", - dec->lmem_ptr[i + 3 - ii]); - } - if (((i + ii) & 0xf) == 0) - pr_info("\n"); - } - - if (((udebug_pause_pos & 0xffff) - == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == dec->decode_idx) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_HREG(DEBUG_REG2))) { - udebug_pause_pos &= 0xffff; - dec->ucode_pause_pos = udebug_pause_pos; - } else if (debug_tag & 0x20000) - dec->ucode_pause_pos = 0xffffffff; - if (dec->ucode_pause_pos) - reset_process_time(dec); - else - WRITE_HREG(DEBUG_REG1, 0); - } else if (debug_tag != 0) { - pr_info( - "dbg%x: %x lcu %x\n", READ_HREG(DEBUG_REG1), - READ_HREG(DEBUG_REG2), - READ_VREG(HEVC_PARSER_LCU_START)); - if (((udebug_pause_pos & 0xffff) - == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == dec->decode_idx) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_HREG(DEBUG_REG2))) { - udebug_pause_pos &= 0xffff; - dec->ucode_pause_pos = udebug_pause_pos; - } - if (dec->ucode_pause_pos) - reset_process_time(dec); - else - WRITE_HREG(DEBUG_REG1, 0); - dec->process_busy = 0; - return IRQ_HANDLED; - } - - if (!dec->m_ins_flag) { - if (dec->error_flag == 1) { - dec->error_flag = 2; - dec->process_busy = 0; - return IRQ_HANDLED; - } else if (dec->error_flag == 3) { - dec->process_busy = 0; - return IRQ_HANDLED; - } - - if ((dec->pic_list_init_flag) && - get_free_buf_count(dec) <= 0) { - /* - if (dec->wait_buf == 0) - pr_info("set wait_buf to 1\r\n"); - */ - dec->wait_buf = 1; - dec->process_busy = 0; - if (debug & AVS2_DBG_IRQ_EVENT) - avs2_print(dec, 0, "wait_buf\n"); - return IRQ_HANDLED; - } else if (force_disp_pic_index) { - dec->process_busy = 0; - return IRQ_HANDLED; - } - } - return IRQ_WAKE_THREAD; -} - -static void vavs2_put_timer_func(unsigned long arg) -{ - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)arg; - struct timer_list *timer = &dec->timer; - uint8_t empty_flag; - unsigned int buf_level; - - enum receviver_start_e state = RECEIVER_INACTIVE; - if (dec->m_ins_flag) { - if (hw_to_vdec(dec)->next_status - == VDEC_STATUS_DISCONNECTED) { - dec->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&dec->work); - avs2_print(dec, AVS2_DBG_BUFMGR, - "vdec requested to be disconnected\n"); - return; - } - } - if (dec->init_flag == 0) { - if (dec->stat & STAT_TIMER_ARM) { - timer->expires = jiffies + PUT_INTERVAL; - add_timer(&dec->timer); - } - return; - } - if (dec->m_ins_flag == 0) { - if (vf_get_receiver(dec->provider_name)) { - state = - vf_notify_receiver(dec->provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) - state = RECEIVER_INACTIVE; - } else - state = RECEIVER_INACTIVE; - - empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1; - /* error watchdog */ - if (empty_flag == 0) { - /* decoder has input */ - if ((debug & AVS2_DBG_DIS_LOC_ERROR_PROC) == 0) { - - buf_level = READ_VREG(HEVC_STREAM_LEVEL); - /* receiver has no buffer to recycle */ - if ((state == RECEIVER_INACTIVE) && - (kfifo_is_empty(&dec->display_q) && - buf_level > 0x200) - ) { - WRITE_VREG - (HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - } - } - - if ((debug & AVS2_DBG_DIS_SYS_ERROR_PROC) == 0) { - /* receiver has no buffer to recycle */ - /*if ((state == RECEIVER_INACTIVE) && - (kfifo_is_empty(&dec->display_q))) { - pr_info("avs2 something error,need reset\n"); - }*/ - } - } - } else { - if ( - (decode_timeout_val > 0) && - (dec->start_process_time > 0) && - ((1000 * (jiffies - dec->start_process_time) / HZ) - > decode_timeout_val) - ) { - int current_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff; - if (dec->last_lcu_idx == current_lcu_idx) { - if (dec->decode_timeout_count > 0) - dec->decode_timeout_count--; - if (dec->decode_timeout_count == 0) { - if (input_frame_based( - hw_to_vdec(dec)) || - (READ_VREG(HEVC_STREAM_LEVEL) > 0x200)) - timeout_process(dec); - else { - avs2_print(dec, 0, - "timeout & empty, again\n"); - dec_again_process(dec); - } - } - } else { - start_process_time(dec); - dec->last_lcu_idx = current_lcu_idx; - } - } - } - - if ((dec->ucode_pause_pos != 0) && - (dec->ucode_pause_pos != 0xffffffff) && - udebug_pause_pos != dec->ucode_pause_pos) { - dec->ucode_pause_pos = 0; - WRITE_HREG(DEBUG_REG1, 0); - } - if (debug & AVS2_DBG_DUMP_DATA) { - debug &= ~AVS2_DBG_DUMP_DATA; - avs2_print(dec, 0, - "%s: chunk size 0x%x off 0x%x sum 0x%x\n", - __func__, - dec->chunk->size, - dec->chunk->offset, - get_data_check_sum(dec, dec->chunk->size) - ); - dump_data(dec, dec->chunk->size); - } - if (debug & AVS2_DBG_DUMP_PIC_LIST) { - dump_pic_list(dec); - debug &= ~AVS2_DBG_DUMP_PIC_LIST; - } - if (debug & AVS2_DBG_TRIG_SLICE_SEGMENT_PROC) { - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); - debug &= ~AVS2_DBG_TRIG_SLICE_SEGMENT_PROC; - } - if (debug & AVS2_DBG_DUMP_RPM_BUF) { - int i; - dma_sync_single_for_cpu( - amports_get_dma_device(), - dec->rpm_phy_addr, - RPM_BUF_SIZE, - DMA_FROM_DEVICE); - - pr_info("RPM:\n"); - for (i = 0; i < RPM_BUF_SIZE; i += 4) { - int ii; - if ((i & 0xf) == 0) - pr_info("%03x: ", i); - for (ii = 0; ii < 4; ii++) { - pr_info("%04x ", - dec->lmem_ptr[i + 3 - ii]); - } - if (((i + ii) & 0xf) == 0) - pr_info("\n"); - } - debug &= ~AVS2_DBG_DUMP_RPM_BUF; - } - if (debug & AVS2_DBG_DUMP_LMEM_BUF) { - int i; - dma_sync_single_for_cpu( - amports_get_dma_device(), - dec->lmem_phy_addr, - LMEM_BUF_SIZE, - DMA_FROM_DEVICE); - - pr_info("LMEM:\n"); - for (i = 0; i < LMEM_BUF_SIZE; i += 4) { - int ii; - if ((i & 0xf) == 0) - pr_info("%03x: ", i); - for (ii = 0; ii < 4; ii++) { - pr_info("%04x ", - dec->lmem_ptr[i + 3 - ii]); - } - if (((i + ii) & 0xf) == 0) - pr_info("\n"); - } - debug &= ~AVS2_DBG_DUMP_LMEM_BUF; - } - /*if (debug & AVS2_DBG_HW_RESET) { - }*/ - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - if (pop_shorts != 0) { - int i; - u32 sum = 0; - pr_info("pop stream 0x%x shorts\r\n", pop_shorts); - for (i = 0; i < pop_shorts; i++) { - u32 data = - (READ_HREG(HEVC_SHIFTED_DATA) >> 16); - WRITE_HREG(HEVC_SHIFT_COMMAND, - (1<<7)|16); - if ((i & 0xf) == 0) - pr_info("%04x:", i); - pr_info("%04x ", data); - if (((i + 1) & 0xf) == 0) - pr_info("\r\n"); - sum += data; - } - pr_info("\r\nsum = %x\r\n", sum); - pop_shorts = 0; - } - if (dbg_cmd != 0) { - if (dbg_cmd == 1) { - u32 disp_laddr; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && - get_double_write_mode(dec) == 0) { - disp_laddr = - READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; - } else { - struct canvas_s cur_canvas; - canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) - & 0xff), &cur_canvas); - disp_laddr = cur_canvas.addr; - } - pr_info("current displayed buffer address %x\r\n", - disp_laddr); - } - dbg_cmd = 0; - } - /*don't changed at start.*/ - if (dec->get_frame_dur && dec->show_frame_num > 60 && - dec->frame_dur > 0 && dec->saved_resolution != - frame_width * frame_height * - (96000 / dec->frame_dur)) { - int fps = 96000 / dec->frame_dur; - if (hevc_source_changed(VFORMAT_AVS2, - frame_width, frame_height, fps) > 0) - dec->saved_resolution = frame_width * - frame_height * fps; - } - - timer->expires = jiffies + PUT_INTERVAL; - add_timer(timer); -} - - -int vavs2_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - - if (!dec) - return -1; - - vstatus->frame_width = dec->frame_width; - vstatus->frame_height = dec->frame_height; - - if (dec->frame_dur != 0) - vstatus->frame_rate = 96000 / dec->frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = 0; - vstatus->status = dec->stat | dec->fatal_error; - vstatus->frame_dur = dec->frame_dur; -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); -#endif - return 0; -} - -int vavs2_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -static void vavs2_prot_init(struct AVS2Decoder_s *dec) -{ - unsigned int data32; - - avs2_config_work_space_hw(dec); - if (dec->pic_list_init_flag) - init_pic_list_hw(dec); - - avs2_init_decoder_hw(dec); - -#if 1 - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s\n", __func__); - data32 = READ_VREG(HEVC_STREAM_CONTROL); - data32 = data32 | - (1 << 0)/*stream_fetch_enable*/ - ; - WRITE_VREG(HEVC_STREAM_CONTROL, data32); -#if 0 - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x00000100) { - pr_info("avs2 prot init error %d\n", __LINE__); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x00000300) { - pr_info("avs2 prot init error %d\n", __LINE__); - return; - } - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x12345678) { - pr_info("avs2 prot init error %d\n", __LINE__); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x9abcdef0) { - pr_info("avs2 prot init error %d\n", __LINE__); - return; - } -#endif - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000000); -#endif - - - - WRITE_VREG(HEVC_WAIT_FLAG, 1); - - /* WRITE_VREG(HEVC_MPSR, 1); */ - - /* clear mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(HEVC_PSCALE_CTRL, 0); - - WRITE_VREG(DEBUG_REG1, 0x0); - /*check vps/sps/pps/i-slice in ucode*/ - WRITE_VREG(NAL_SEARCH_CTL, 0x8); - - WRITE_VREG(DECODE_STOP_POS, udebug_flag); - -} - -#ifdef I_ONLY_SUPPORT -static int vavs2_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - if (i_only_flag & 0x100) - return 0; - if (trickmode == TRICKMODE_I) - dec->i_only = 0x3; - else if (trickmode == TRICKMODE_NONE) - dec->i_only = 0x0; - return 0; -} -#endif - -static int vavs2_local_init(struct AVS2Decoder_s *dec) -{ - int i; - int ret; - int width, height; - - dec->gvs = vzalloc(sizeof(struct vdec_info)); - if (NULL == dec->gvs) { - avs2_print(dec, 0, - "the struct of vdec status malloc failed.\n"); - return -1; - } -#ifdef DEBUG_PTS - dec->pts_missed = 0; - dec->pts_hit = 0; -#endif - dec->new_frame_displayed = 0; - dec->last_put_idx = -1; - dec->saved_resolution = 0; - dec->get_frame_dur = false; - on_no_keyframe_skiped = 0; - width = dec->vavs2_amstream_dec_info.width; - height = dec->vavs2_amstream_dec_info.height; - dec->frame_dur = - (dec->vavs2_amstream_dec_info.rate == - 0) ? 3600 : dec->vavs2_amstream_dec_info.rate; - if (width && height) - dec->frame_ar = height * 0x100 / width; -/* -TODO:FOR VERSION -*/ - avs2_print(dec, AVS2_DBG_BUFMGR, - "avs2: ver (%d,%d) decinfo: %dx%d rate=%d\n", avs2_version, - 0, width, height, dec->frame_dur); - - if (dec->frame_dur == 0) - dec->frame_dur = 96000 / 24; -#ifdef I_ONLY_SUPPORT - if (i_only_flag & 0x100) - dec->i_only = i_only_flag & 0xff; - else if ((unsigned long) dec->vavs2_amstream_dec_info.param - & 0x08) - dec->i_only = 0x7; - else - dec->i_only = 0x0; -#endif - INIT_KFIFO(dec->display_q); - INIT_KFIFO(dec->newframe_q); - - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &dec->vfpool[i]; - dec->vfpool[i].index = -1; - kfifo_put(&dec->newframe_q, vf); - } - - - ret = avs2_local_init(dec); - - return ret; -} - - -static s32 vavs2_init(struct vdec_s *vdec) -{ - int ret = -1, size = -1; - int fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; - init_timer(&dec->timer); - - dec->stat |= STAT_TIMER_INIT; - if (vavs2_local_init(dec) < 0) - return -EBUSY; - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_AVS2_MMU, fw->data); - if (size < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = fw_size; - - if (dec->m_ins_flag) { - dec->timer.data = (ulong) dec; - dec->timer.function = vavs2_put_timer_func; - dec->timer.expires = jiffies + PUT_INTERVAL; - - /*add_timer(&dec->timer); - - dec->stat |= STAT_TIMER_ARM; - dec->stat |= STAT_ISR_REG;*/ - - INIT_WORK(&dec->work, avs2_work); - dec->fw = fw; - - return 0; - } - hevc_enable_DMC(hw_to_vdec(dec)); - amhevc_enable(); - - ret = amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data); - if (ret < 0) { - amhevc_disable(); - vfree(fw); - pr_err("AVS2: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(fw); - - dec->stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - vavs2_prot_init(dec); - - if (vdec_request_threaded_irq(VDEC_IRQ_0, - vavs2_isr, - vavs2_isr_thread_fn, - IRQF_ONESHOT,/*run thread on this irq disabled*/ - "vavs2-irq", (void *)dec)) { - pr_info("vavs2 irq register error.\n"); - amhevc_disable(); - return -ENOENT; - } - - dec->stat |= STAT_ISR_REG; - - dec->provider_name = PROVIDER_NAME; - vf_provider_init(&vavs2_vf_prov, PROVIDER_NAME, - &vavs2_vf_provider, dec); - vf_reg_provider(&vavs2_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); - if (dec->frame_dur != 0) { - if (!is_reset) - vf_notify_receiver(dec->provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)dec->frame_dur)); - } - dec->stat |= STAT_VF_HOOK; - - dec->timer.data = (ulong)dec; - dec->timer.function = vavs2_put_timer_func; - dec->timer.expires = jiffies + PUT_INTERVAL; - - - add_timer(&dec->timer); - - dec->stat |= STAT_TIMER_ARM; - - /* dec->stat |= STAT_KTHREAD; */ - dec->process_busy = 0; - avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%d, vavs2_init, RP=0x%x\n", - __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); - return 0; -} - -static int vmavs2_stop(struct AVS2Decoder_s *dec) -{ - dec->init_flag = 0; - dec->first_sc_checked = 0; - if (dec->stat & STAT_TIMER_ARM) { - del_timer_sync(&dec->timer); - dec->stat &= ~STAT_TIMER_ARM; - } - - if (dec->stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(dec->provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - - vf_unreg_provider(&vavs2_vf_prov); - dec->stat &= ~STAT_VF_HOOK; - } - avs2_local_uninit(dec); - reset_process_time(dec); - cancel_work_sync(&dec->work); - uninit_mmu_buffers(dec); - if (dec->fw) { - vfree(dec->fw); - dec->fw = NULL; - } - - return 0; -} - - -static int vavs2_stop(struct AVS2Decoder_s *dec) -{ - - dec->init_flag = 0; - dec->first_sc_checked = 0; - if (dec->stat & STAT_VDEC_RUN) { - amhevc_stop(); - dec->stat &= ~STAT_VDEC_RUN; - } - - if (dec->stat & STAT_ISR_REG) { - if (!dec->m_ins_flag) - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0); - vdec_free_irq(VDEC_IRQ_0, (void *)dec); - dec->stat &= ~STAT_ISR_REG; - } - - if (dec->stat & STAT_TIMER_ARM) { - del_timer_sync(&dec->timer); - dec->stat &= ~STAT_TIMER_ARM; - } - - if (dec->stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(dec->provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - - vf_unreg_provider(&vavs2_vf_prov); - dec->stat &= ~STAT_VF_HOOK; - } - avs2_local_uninit(dec); - - if (dec->m_ins_flag) - cancel_work_sync(&dec->work); - else - amhevc_disable(); - uninit_mmu_buffers(dec); - - return 0; -} - -static int amvdec_avs2_mmu_init(struct AVS2Decoder_s *dec) -{ - int tvp_flag = vdec_secure(hw_to_vdec(dec)) ? - CODEC_MM_FLAGS_TVP : 0; - int buf_size = 48; - -#ifdef AVS2_10B_MMU - dec->need_cache_size = buf_size * SZ_1M; - dec->sc_start_time = get_jiffies_64(); - dec->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, - dec->index, FRAME_BUFFERS, - dec->need_cache_size, - tvp_flag - ); - if (!dec->mmu_box) { - pr_err("avs2 alloc mmu box failed!!\n"); - return -1; - } -#endif - dec->bmmu_box = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - dec->index, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER | - tvp_flag); - if (!dec->bmmu_box) { - pr_err("avs2 alloc bmmu box failed!!\n"); - return -1; - } - return 0; -} - -static int amvdec_avs2_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct BUF_s BUF[MAX_BUF_NUM]; - struct AVS2Decoder_s *dec = &gAVS2Decoder; - int ret; - pr_info("%s\n", __func__); - mutex_lock(&vavs2_mutex); - - memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - memset(dec, 0, sizeof(struct AVS2Decoder_s)); - memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - - dec->init_flag = 0; - dec->first_sc_checked = 0; - dec->eos = 0; - dec->start_process_time = 0; - dec->timeout_num = 0; - dec->fatal_error = 0; - dec->show_frame_num = 0; - if (pdata == NULL) { - avs2_print(dec, 0, - "\namvdec_avs2 memory resource undefined.\n"); - mutex_unlock(&vavs2_mutex); - return -EFAULT; - } - dec->m_ins_flag = 0; - dec->platform_dev = pdev; - platform_set_drvdata(pdev, pdata); - - if (amvdec_avs2_mmu_init(dec) < 0) { - mutex_unlock(&vavs2_mutex); - pr_err("avs2 alloc bmmu box failed!!\n"); - return -1; - } - - ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID, - work_buf_size, DRIVER_NAME, &pdata->mem_start); - if (ret < 0) { - uninit_mmu_buffers(dec); - mutex_unlock(&vavs2_mutex); - return ret; - } - dec->buf_size = work_buf_size; - - dec->buf_start = pdata->mem_start; - - - if (debug) { - avs2_print(dec, 0, - "===AVS2 decoder mem resource 0x%lx size 0x%x\n", - pdata->mem_start, dec->buf_size); - } - - if (pdata->sys_info) { - dec->vavs2_amstream_dec_info = *pdata->sys_info; - dec->frame_width = dec->vavs2_amstream_dec_info.width; - dec->frame_height = dec->vavs2_amstream_dec_info.height; - } else { - dec->vavs2_amstream_dec_info.width = 0; - dec->vavs2_amstream_dec_info.height = 0; - dec->vavs2_amstream_dec_info.rate = 30; - } - dec->cma_dev = pdata->cma_dev; - - pdata->private = dec; - pdata->dec_status = vavs2_dec_status; - /*pdata->set_isreset = vavs2_set_isreset;*/ - is_reset = 0; - if (vavs2_init(pdata) < 0) { - pr_info("\namvdec_avs2 init failed.\n"); - avs2_local_uninit(dec); - uninit_mmu_buffers(dec); - pdata->dec_status = NULL; - mutex_unlock(&vavs2_mutex); - return -ENODEV; - } - /*set the max clk for smooth playing...*/ - hevc_source_changed(VFORMAT_AVS2, - 4096, 2048, 60); - mutex_unlock(&vavs2_mutex); - - return 0; -} - -static int amvdec_avs2_remove(struct platform_device *pdev) -{ - struct AVS2Decoder_s *dec = &gAVS2Decoder; - if (debug) - pr_info("amvdec_avs2_remove\n"); - - mutex_lock(&vavs2_mutex); - - vavs2_stop(dec); - - - hevc_source_changed(VFORMAT_AVS2, 0, 0, 0); - - -#ifdef DEBUG_PTS - pr_info("pts missed %ld, pts hit %ld, duration %d\n", - dec->pts_missed, dec->pts_hit, dec->frame_dur); -#endif - - mutex_unlock(&vavs2_mutex); - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_avs2_driver = { - .probe = amvdec_avs2_probe, - .remove = amvdec_avs2_remove, -#ifdef CONFIG_PM - .suspend = amhevc_suspend, - .resume = amhevc_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_avs2_profile = { - .name = "avs2", - .profile = "" -}; - -static unsigned char get_data_check_sum - (struct AVS2Decoder_s *dec, int size) -{ - int jj; - int sum = 0; - u8 *data = NULL; - - if (!dec->chunk->block->is_mapped) - data = codec_mm_vmap(dec->chunk->block->start + - dec->chunk->offset, size); - else - data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; - - for (jj = 0; jj < size; jj++) - sum += data[jj]; - - if (!dec->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - return sum; -} - -static void dump_data(struct AVS2Decoder_s *dec, int size) -{ - int jj; - u8 *data = NULL; - int padding_size = dec->chunk->offset & - (VDEC_FIFO_ALIGN - 1); - - if (!dec->chunk->block->is_mapped) - data = codec_mm_vmap(dec->chunk->block->start + - dec->chunk->offset, size); - else - data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; - - avs2_print(dec, 0, "padding: "); - for (jj = padding_size; jj > 0; jj--) - avs2_print_cont(dec, - 0, - "%02x ", *(data - jj)); - avs2_print_cont(dec, 0, "data adr %p\n", - data); - - for (jj = 0; jj < size; jj++) { - if ((jj & 0xf) == 0) - avs2_print(dec, - 0, - "%06x:", jj); - avs2_print_cont(dec, - 0, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - avs2_print(dec, - 0, - "\n"); - } - avs2_print(dec, - 0, - "\n"); - - if (!dec->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); -} - -static void avs2_work(struct work_struct *work) -{ - struct AVS2Decoder_s *dec = container_of(work, - struct AVS2Decoder_s, work); - struct vdec_s *vdec = hw_to_vdec(dec); - /* finished decoding one frame or error, - * notify vdec core to switch context - */ - avs2_print(dec, PRINT_FLAG_VDEC_DETAIL, - "%s dec_result %d %x %x %x\n", - __func__, - dec->dec_result, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR)); - - if (((dec->dec_result == DEC_RESULT_GET_DATA) || - (dec->dec_result == DEC_RESULT_GET_DATA_RETRY)) - && (hw_to_vdec(dec)->next_status != - VDEC_STATUS_DISCONNECTED)) { - if (!vdec_has_more_input(vdec)) { - dec->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&dec->work); - return; - } - - if (dec->dec_result == DEC_RESULT_GET_DATA) { - avs2_print(dec, PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_GET_DATA %x %x %x\n", - __func__, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR)); - vdec_vframe_dirty(vdec, dec->chunk); - vdec_clean_input(vdec); - } - - if (get_free_buf_count(dec) >= - run_ready_min_buf_num) { - int r; - int decode_size; - r = vdec_prepare_input(vdec, &dec->chunk); - if (r < 0) { - dec->dec_result = DEC_RESULT_GET_DATA_RETRY; - - avs2_print(dec, - PRINT_FLAG_VDEC_DETAIL, - "amvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&dec->work); - return; - } - dec->dec_result = DEC_RESULT_NONE; - avs2_print(dec, PRINT_FLAG_VDEC_STATUS, - "%s: chunk size 0x%x sum 0x%x\n", - __func__, r, - (debug & PRINT_FLAG_VDEC_STATUS) ? - get_data_check_sum(dec, r) : 0 - ); - if (debug & PRINT_FLAG_VDEC_DATA) - dump_data(dec, dec->chunk->size); - - decode_size = dec->chunk->size + - (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - - WRITE_VREG(HEVC_DECODE_SIZE, - READ_VREG(HEVC_DECODE_SIZE) + decode_size); - - vdec_enable_input(vdec); - - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - - start_process_time(dec); - - } else{ - dec->dec_result = DEC_RESULT_GET_DATA_RETRY; - - avs2_print(dec, PRINT_FLAG_VDEC_DETAIL, - "amvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&dec->work); - } - return; - } else if (dec->dec_result == DEC_RESULT_DONE) { - /* if (!dec->ctx_valid) - dec->ctx_valid = 1; */ - dec->slice_idx++; - dec->frame_count++; - dec->process_state = PROC_STATE_INIT; - decode_frame_count[dec->index] = dec->frame_count; - -#ifdef AVS2_10B_MMU - dec->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); -#endif - avs2_print(dec, PRINT_FLAG_VDEC_STATUS, - "%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n", - __func__, - dec->frame_count, - dec->dec_result, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_SHIFT_BYTE_COUNT) - - dec->start_shift_bytes - ); - vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk); - } else if (dec->dec_result == DEC_RESULT_AGAIN) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(vdec)) { - dec->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&dec->work); - return; - } - } else if (dec->dec_result == DEC_RESULT_EOS) { - avs2_print(dec, PRINT_FLAG_VDEC_STATUS, - "%s: end of stream\n", - __func__); - dec->eos = 1; - check_pic_error(dec, dec->avs2_dec.hc.cur_pic); - avs2_post_process(&dec->avs2_dec); - avs2_prepare_display_buf(dec); - vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk); - } else if (dec->dec_result == DEC_RESULT_FORCE_EXIT) { - avs2_print(dec, PRINT_FLAG_VDEC_STATUS, - "%s: force exit\n", - __func__); - if (dec->stat & STAT_VDEC_RUN) { - amhevc_stop(); - dec->stat &= ~STAT_VDEC_RUN; - } - - if (dec->stat & STAT_ISR_REG) { - if (!dec->m_ins_flag) - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0); - vdec_free_irq(VDEC_IRQ_0, (void *)dec); - dec->stat &= ~STAT_ISR_REG; - } - } - - if (dec->stat & STAT_TIMER_ARM) { - del_timer_sync(&dec->timer); - dec->stat &= ~STAT_TIMER_ARM; - } - /* mark itself has all HW resource released and input released */ - if (vdec->parallel_dec ==1) - vdec_core_finish_run(vdec, CORE_MASK_HEVC); - else - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - if (dec->vdec_cb) - dec->vdec_cb(hw_to_vdec(dec), dec->vdec_cb_arg); -} - -static int avs2_hw_ctx_restore(struct AVS2Decoder_s *dec) -{ - /* new to do ... */ - vavs2_prot_init(dec); - return 0; -} - -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - int tvp = vdec_secure(hw_to_vdec(dec)) ? - CODEC_MM_FLAGS_TVP : 0; - unsigned long ret = 0; - avs2_print(dec, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); - if (debug & AVS2_DBG_PIC_LEAK_WAIT) - return ret; - - if (dec->eos) - return ret; - if (!dec->first_sc_checked) { - int size = decoder_mmu_box_sc_check(dec->mmu_box, tvp); - dec->first_sc_checked = 1; - avs2_print(dec, 0, "vavs2 cached=%d need_size=%d speed= %d ms\n", - size, (dec->need_cache_size >> PAGE_SHIFT), - (int)(get_jiffies_64() - dec->sc_start_time) * 1000/HZ); - } - - if (dec->next_again_flag && - (!vdec_frame_based(vdec))) { - u32 parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - if (parser_wr_ptr >= dec->pre_parser_wr_ptr && - (parser_wr_ptr - dec->pre_parser_wr_ptr) < - again_threshold) { - int r = vdec_sync_input(vdec); - avs2_print(dec, - PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); - return 0; - } - } -/* - if (vdec_stream_based(vdec) && (dec->pic_list_init_flag == 0) - && pre_decode_buf_level != 0) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = vdec->input.size + wp - rp; - else - level = wp - rp; - - if (level < pre_decode_buf_level) - return 0; - } -*/ - - if ((dec->pic_list_init_flag == 0) || - get_free_buf_count(dec) >= - run_ready_min_buf_num) - ret = 1; -#ifdef CONSTRAIN_MAX_BUF_NUM - if (dec->pic_list_init_flag) { - if (run_ready_max_vf_only_num > 0 && - get_vf_ref_only_buf_count(dec) >= - run_ready_max_vf_only_num - ) - ret = 0; - if (run_ready_display_q_num > 0 && - kfifo_len(&dec->display_q) >= - run_ready_display_q_num) - ret = 0; - - if (run_ready_max_buf_num == 0xff && - get_used_buf_count(dec) >= - dec->avs2_dec.ref_maxbuffer) - ret = 0; - else if (run_ready_max_buf_num && - get_used_buf_count(dec) >= - run_ready_max_buf_num) - ret = 0; - } -#endif - if (ret) - not_run_ready[dec->index] = 0; - else - not_run_ready[dec->index]++; - - if (vdec->parallel_dec == 1) - return ret ? CORE_MASK_HEVC : 0; - else - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; -} - -static void run(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *arg) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - int r; - - run_count[dec->index]++; - dec->vdec_cb_arg = arg; - dec->vdec_cb = callback; - /* dec->chunk = vdec_prepare_input(vdec); */ - hevc_reset_core(vdec); - dec->pre_parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - dec->next_again_flag = 0; - - r = vdec_prepare_input(vdec, &dec->chunk); - if (r < 0) { - input_empty[dec->index]++; - - dec->dec_result = DEC_RESULT_AGAIN; - - avs2_print(dec, PRINT_FLAG_VDEC_DETAIL, - "ammvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&dec->work); - return; - } - input_empty[dec->index] = 0; - dec->dec_result = DEC_RESULT_NONE; - dec->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - - if (debug & PRINT_FLAG_VDEC_STATUS) { - int ii; - avs2_print(dec, 0, - "%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x", - __func__, - dec->frame_count, r, - dec->chunk ? dec->chunk->size : 0, - dec->chunk ? dec->chunk->offset : 0, - dec->chunk ? ((vdec_frame_based(vdec) && - (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(dec, r) : 0) : 0, - READ_VREG(HEVC_STREAM_START_ADDR), - READ_VREG(HEVC_STREAM_END_ADDR), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - dec->start_shift_bytes); - if (vdec_frame_based(vdec) && dec->chunk) { - u8 *data = NULL; - if (!dec->chunk->block->is_mapped) - data = codec_mm_vmap(dec->chunk->block->start + - dec->chunk->offset, 8); - else - data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; - - avs2_print_cont(dec, 0, "data adr %p:", - data); - for (ii = 0; ii < 8; ii++) - avs2_print_cont(dec, 0, "%02x ", - data[ii]); - if (!dec->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - avs2_print_cont(dec, 0, "\r\n"); - } - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - } else if (amhevc_loadmc_ex(VFORMAT_AVS2, NULL, dec->fw->data) < 0) { - vdec->mc_loaded = 0; - amhevc_disable(); - avs2_print(dec, 0, - "%s: Error amvdec_loadmc fail\n", __func__); - dec->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&dec->work); - return; - } else { - vdec->mc_loaded = 1; - vdec->mc_type = VFORMAT_AVS2; - } - - - if (avs2_hw_ctx_restore(dec) < 0) { - vdec_schedule_work(&dec->work); - return; - } - - vdec_enable_input(vdec); - - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_SEARCH_NEW_PIC); - - if (vdec_frame_based(vdec) && dec->chunk) { - if (debug & PRINT_FLAG_VDEC_DATA) - dump_data(dec, dec->chunk->size); - - WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); - r = dec->chunk->size + - (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - } - - WRITE_VREG(HEVC_DECODE_SIZE, r); - WRITE_VREG(HEVC_DECODE_COUNT, dec->slice_idx); - dec->init_flag = 1; - - avs2_print(dec, PRINT_FLAG_VDEC_DETAIL, - "%s: start hevc (%x %x %x)\n", - __func__, - READ_VREG(HEVC_DEC_STATUS_REG), - READ_VREG(HEVC_MPC_E), - READ_VREG(HEVC_MPSR)); - - start_process_time(dec); - mod_timer(&dec->timer, jiffies); - dec->stat |= STAT_TIMER_ARM; - dec->stat |= STAT_ISR_REG; - amhevc_start(); - dec->stat |= STAT_VDEC_RUN; -} - -static void reset(struct vdec_s *vdec) -{ - - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - - avs2_print(dec, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); - -} - -static irqreturn_t avs2_irq_cb(struct vdec_s *vdec, int irq) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - return vavs2_isr(0, dec); -} - -static irqreturn_t avs2_threaded_irq_cb(struct vdec_s *vdec, int irq) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - return vavs2_isr_thread_fn(0, dec); -} - -static void avs2_dump_state(struct vdec_s *vdec) -{ - struct AVS2Decoder_s *dec = - (struct AVS2Decoder_s *)vdec->private; - int i; - avs2_print(dec, 0, "====== %s\n", __func__); - - avs2_print(dec, 0, - "width/height (%d/%d), used_buf_num %d\n", - dec->avs2_dec.img.width, - dec->avs2_dec.img.height, - dec->used_buf_num - ); - - avs2_print(dec, 0, - "is_framebase(%d), eos %d, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n", - input_frame_based(vdec), - dec->eos, - dec->dec_result, - decode_frame_count[dec->index], - display_frame_count[dec->index], - run_count[dec->index], - not_run_ready[dec->index], - input_empty[dec->index] - ); - - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - avs2_print(dec, 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - - avs2_print(dec, 0, - "%s, newq(%d/%d), dispq(%d/%d), vf prepare/get/put (%d/%d/%d), free_buf_count %d (min %d for run_ready)\n", - __func__, - kfifo_len(&dec->newframe_q), - VF_POOL_SIZE, - kfifo_len(&dec->display_q), - VF_POOL_SIZE, - dec->vf_pre_count, - dec->vf_get_count, - dec->vf_put_count, - get_free_buf_count(dec), - run_ready_min_buf_num - ); - - dump_pic_list(dec); - - for (i = 0; i < MAX_BUF_NUM; i++) { - avs2_print(dec, 0, - "mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n", - i, - dec->m_mv_BUF[i].start_adr, - dec->m_mv_BUF[i].size, - dec->m_mv_BUF[i].used_flag); - } - - avs2_print(dec, 0, - "HEVC_DEC_STATUS_REG=0x%x\n", - READ_VREG(HEVC_DEC_STATUS_REG)); - avs2_print(dec, 0, - "HEVC_MPC_E=0x%x\n", - READ_VREG(HEVC_MPC_E)); - avs2_print(dec, 0, - "DECODE_MODE=0x%x\n", - READ_VREG(DECODE_MODE)); - avs2_print(dec, 0, - "NAL_SEARCH_CTL=0x%x\n", - READ_VREG(NAL_SEARCH_CTL)); - avs2_print(dec, 0, - "HEVC_PARSER_LCU_START=0x%x\n", - READ_VREG(HEVC_PARSER_LCU_START)); - avs2_print(dec, 0, - "HEVC_DECODE_SIZE=0x%x\n", - READ_VREG(HEVC_DECODE_SIZE)); - avs2_print(dec, 0, - "HEVC_SHIFT_BYTE_COUNT=0x%x\n", - READ_VREG(HEVC_SHIFT_BYTE_COUNT)); - avs2_print(dec, 0, - "HEVC_STREAM_START_ADDR=0x%x\n", - READ_VREG(HEVC_STREAM_START_ADDR)); - avs2_print(dec, 0, - "HEVC_STREAM_END_ADDR=0x%x\n", - READ_VREG(HEVC_STREAM_END_ADDR)); - avs2_print(dec, 0, - "HEVC_STREAM_LEVEL=0x%x\n", - READ_VREG(HEVC_STREAM_LEVEL)); - avs2_print(dec, 0, - "HEVC_STREAM_WR_PTR=0x%x\n", - READ_VREG(HEVC_STREAM_WR_PTR)); - avs2_print(dec, 0, - "HEVC_STREAM_RD_PTR=0x%x\n", - READ_VREG(HEVC_STREAM_RD_PTR)); - avs2_print(dec, 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - avs2_print(dec, 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - - if (input_frame_based(vdec) && - (debug & PRINT_FLAG_VDEC_DATA) - ) { - int jj; - if (dec->chunk && dec->chunk->block && - dec->chunk->size > 0) { - u8 *data = NULL; - if (!dec->chunk->block->is_mapped) - data = codec_mm_vmap(dec->chunk->block->start + - dec->chunk->offset, dec->chunk->size); - else - data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; - avs2_print(dec, 0, - "frame data size 0x%x\n", - dec->chunk->size); - for (jj = 0; jj < dec->chunk->size; jj++) { - if ((jj & 0xf) == 0) - avs2_print(dec, 0, - "%06x:", jj); - avs2_print_cont(dec, 0, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - avs2_print_cont(dec, 0, - "\n"); - } - - if (!dec->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } - -} - -static int ammvdec_avs2_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - int ret; - int config_val; - struct vframe_content_light_level_s content_light_level; - struct vframe_master_display_colour_s vf_dp; - - struct BUF_s BUF[MAX_BUF_NUM]; - struct AVS2Decoder_s *dec = NULL; - pr_info("%s\n", __func__); - if (pdata == NULL) { - pr_info("\nammvdec_avs2 memory resource undefined.\n"); - return -EFAULT; - } - /*dec = (struct AVS2Decoder_s *)devm_kzalloc(&pdev->dev, - sizeof(struct AVS2Decoder_s), GFP_KERNEL);*/ - memset(&vf_dp, 0, sizeof(struct vframe_master_display_colour_s)); - dec = vmalloc(sizeof(struct AVS2Decoder_s)); - memset(dec, 0, sizeof(struct AVS2Decoder_s)); - if (dec == NULL) { - pr_info("\nammvdec_avs2 device data allocation failed\n"); - return -ENOMEM; - } - if (pdata->parallel_dec == 1) { - int i; - for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) { - dec->avs2_dec.frm_pool[i].y_canvas_index = -1; - dec->avs2_dec.frm_pool[i].uv_canvas_index = -1; - } - } - pdata->private = dec; - pdata->dec_status = vavs2_dec_status; -#ifdef I_ONLY_SUPPORT - pdata->set_trickmode = vavs2_set_trickmode; -#endif - pdata->run_ready = run_ready; - pdata->run = run; - pdata->reset = reset; - pdata->irq_handler = avs2_irq_cb; - pdata->threaded_irq_handler = avs2_threaded_irq_cb; - pdata->dump_state = avs2_dump_state; - - memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - memset(dec, 0, sizeof(struct AVS2Decoder_s)); - memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - - dec->index = pdev->id; - dec->m_ins_flag = 1; - - if (pdata->use_vfm_path) { - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - dec->frameinfo_enable = 1; - } else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); - - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vavs2_vf_provider, dec); - - dec->provider_name = pdata->vf_provider_name; - platform_set_drvdata(pdev, pdata); - - dec->platform_dev = pdev; - dec->video_signal_type = 0; - dec->video_ori_signal_type = 0; - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) - dec->stat |= VP9_TRIGGER_FRAME_ENABLE; -#if 1 - if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && - pdata->config && pdata->config_len) { - /*use ptr config for doubel_write_mode, etc*/ - avs2_print(dec, 0, "pdata->config=%s\n", pdata->config); - if (get_config_int(pdata->config, "avs2_double_write_mode", - &config_val) == 0) - dec->double_write_mode = config_val; - else - dec->double_write_mode = double_write_mode; - if (get_config_int(pdata->config, "HDRStaticInfo", - &vf_dp.present_flag) == 0 - && vf_dp.present_flag == 1) { - get_config_int(pdata->config, "mG.x", - &vf_dp.primaries[0][0]); - get_config_int(pdata->config, "mG.y", - &vf_dp.primaries[0][1]); - get_config_int(pdata->config, "mB.x", - &vf_dp.primaries[1][0]); - get_config_int(pdata->config, "mB.y", - &vf_dp.primaries[1][1]); - get_config_int(pdata->config, "mR.x", - &vf_dp.primaries[2][0]); - get_config_int(pdata->config, "mR.y", - &vf_dp.primaries[2][1]); - get_config_int(pdata->config, "mW.x", - &vf_dp.white_point[0]); - get_config_int(pdata->config, "mW.y", - &vf_dp.white_point[1]); - get_config_int(pdata->config, "mMaxDL", - &vf_dp.luminance[0]); - get_config_int(pdata->config, "mMinDL", - &vf_dp.luminance[1]); - vf_dp.content_light_level.present_flag = 1; - get_config_int(pdata->config, "mMaxCLL", - &content_light_level.max_content); - get_config_int(pdata->config, "mMaxFALL", - &content_light_level.max_pic_average); - vf_dp.content_light_level = content_light_level; - dec->video_signal_type = (1 << 29) - | (5 << 26) /* unspecified */ - | (0 << 25) /* limit */ - | (1 << 24) /* color available */ - | (9 << 16) /* 2020 */ - | (16 << 8) /* 2084 */ - | (9 << 0); /* 2020 */ - } - dec->vf_dp = vf_dp; - } else -#endif - { - /*dec->vavs2_amstream_dec_info.width = 0; - dec->vavs2_amstream_dec_info.height = 0; - dec->vavs2_amstream_dec_info.rate = 30;*/ - dec->double_write_mode = double_write_mode; - } - video_signal_type = dec->video_signal_type; - -#if 0 - dec->buf_start = pdata->mem_start; - dec->buf_size = pdata->mem_end - pdata->mem_start + 1; -#else - if (amvdec_avs2_mmu_init(dec) < 0) { - pr_err("avs2 alloc bmmu box failed!!\n"); - /* devm_kfree(&pdev->dev, (void *)dec); */ - vfree((void *)dec); - return -1; - } - dec->cma_alloc_count = PAGE_ALIGN(work_buf_size) / PAGE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID, - dec->cma_alloc_count * PAGE_SIZE, DRIVER_NAME, - &dec->cma_alloc_addr); - if (ret < 0) { - uninit_mmu_buffers(dec); - /* devm_kfree(&pdev->dev, (void *)dec); */ - vfree((void *)dec); - return ret; - } - dec->buf_start = dec->cma_alloc_addr; - dec->buf_size = work_buf_size; -#endif - dec->init_flag = 0; - dec->first_sc_checked = 0; - dec->fatal_error = 0; - dec->show_frame_num = 0; - if (pdata == NULL) { - pr_info("\namvdec_avs2 memory resource undefined.\n"); - uninit_mmu_buffers(dec); - /* devm_kfree(&pdev->dev, (void *)dec); */ - vfree((void *)dec); - return -EFAULT; - } - - if (debug) { - pr_info("===AVS2 decoder mem resource 0x%lx size 0x%x\n", - dec->buf_start, - dec->buf_size); - } - - if (pdata->sys_info) { - dec->vavs2_amstream_dec_info = *pdata->sys_info; - dec->frame_width = dec->vavs2_amstream_dec_info.width; - dec->frame_height = dec->vavs2_amstream_dec_info.height; - } else { - dec->vavs2_amstream_dec_info.width = 0; - dec->vavs2_amstream_dec_info.height = 0; - dec->vavs2_amstream_dec_info.rate = 30; - } - - dec->cma_dev = pdata->cma_dev; - if (vavs2_init(pdata) < 0) { - pr_info("\namvdec_avs2 init failed.\n"); - avs2_local_uninit(dec); - uninit_mmu_buffers(dec); - /* devm_kfree(&pdev->dev, (void *)dec); */ - vfree((void *)dec); - pdata->dec_status = NULL; - return -ENODEV; - } - vdec_set_prepare_level(pdata, start_decode_buf_level); - hevc_source_changed(VFORMAT_AVS2, - 4096, 2048, 60); - if (pdata->parallel_dec == 1) - vdec_core_request(pdata, CORE_MASK_HEVC); - else { - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - } - - return 0; -} - -static int ammvdec_avs2_remove(struct platform_device *pdev) -{ - struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - int i; - - if (debug) - pr_info("amvdec_avs2_remove\n"); - - vmavs2_stop(dec); - - if (pdata->parallel_dec == 1) - vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); - else - vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); - - vdec_set_status(hw_to_vdec(dec), VDEC_STATUS_DISCONNECTED); - if (pdata->parallel_dec == 1) { - for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) { - pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].y_canvas_index, pdata->id); - pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].uv_canvas_index, pdata->id); - } - } - - -#ifdef DEBUG_PTS - pr_info("pts missed %ld, pts hit %ld, duration %d\n", - dec->pts_missed, dec->pts_hit, dec->frame_dur); -#endif - /* devm_kfree(&pdev->dev, (void *)dec); */ - vfree((void *)dec); - return 0; -} - -static struct platform_driver ammvdec_avs2_driver = { - .probe = ammvdec_avs2_probe, - .remove = ammvdec_avs2_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = MULTI_DRIVER_NAME, - } -}; -#endif -static struct mconfig avs2_configs[] = { - MC_PU32("bit_depth_luma", &bit_depth_luma), - MC_PU32("bit_depth_chroma", &bit_depth_chroma), - MC_PU32("frame_width", &frame_width), - MC_PU32("frame_height", &frame_height), - MC_PU32("debug", &debug), - MC_PU32("radr", &radr), - MC_PU32("rval", &rval), - MC_PU32("pop_shorts", &pop_shorts), - MC_PU32("dbg_cmd", &dbg_cmd), - MC_PU32("dbg_skip_decode_index", &dbg_skip_decode_index), - MC_PU32("endian", &endian), - MC_PU32("step", &step), - MC_PU32("udebug_flag", &udebug_flag), - MC_PU32("decode_pic_begin", &decode_pic_begin), - MC_PU32("slice_parse_begin", &slice_parse_begin), - MC_PU32("i_only_flag", &i_only_flag), - MC_PU32("error_handle_policy", &error_handle_policy), - MC_PU32("buf_alloc_width", &buf_alloc_width), - MC_PU32("buf_alloc_height", &buf_alloc_height), - MC_PU32("buf_alloc_depth", &buf_alloc_depth), - MC_PU32("buf_alloc_size", &buf_alloc_size), - MC_PU32("buffer_mode", &buffer_mode), - MC_PU32("buffer_mode_dbg", &buffer_mode_dbg), - MC_PU32("max_buf_num", &max_buf_num), - MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin), - MC_PU32("mem_map_mode", &mem_map_mode), - MC_PU32("double_write_mode", &double_write_mode), - MC_PU32("enable_mem_saving", &enable_mem_saving), - MC_PU32("force_w_h", &force_w_h), - MC_PU32("force_fps", &force_fps), - MC_PU32("max_decoding_time", &max_decoding_time), - MC_PU32("on_no_keyframe_skiped", &on_no_keyframe_skiped), - MC_PU32("start_decode_buf_level", &start_decode_buf_level), - MC_PU32("decode_timeout_val", &decode_timeout_val), -}; -static struct mconfig_node avs2_node; - -static int __init amvdec_avs2_driver_init_module(void) -{ - -#ifdef AVS2_10B_MMU - - struct BuffInfo_s *p_buf_info; - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - p_buf_info = &amvavs2_workbuff_spec[2]; - else - p_buf_info = &amvavs2_workbuff_spec[1]; - } else - p_buf_info = &amvavs2_workbuff_spec[0]; - - init_buff_spec(NULL, p_buf_info); - work_buf_size = - (p_buf_info->end_adr - p_buf_info->start_adr - + 0xffff) & (~0xffff); - -#endif - pr_debug("amvdec_avs2 module init\n"); - -#ifdef ERROR_HANDLE_DEBUG - dbg_nal_skip_flag = 0; - dbg_nal_skip_count = 0; -#endif - udebug_flag = 0; - decode_pic_begin = 0; - slice_parse_begin = 0; - step = 0; - buf_alloc_size = 0; - if (platform_driver_register(&ammvdec_avs2_driver)) - pr_err("failed to register ammvdec_avs2 driver\n"); - - if (platform_driver_register(&amvdec_avs2_driver)) { - pr_err("failed to register amvdec_avs2 driver\n"); - return -ENODEV; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - amvdec_avs2_profile.profile = - "8k, 10bit, dwrite, compressed"; - vcodec_profile_register(&amvdec_avs2_profile); - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - if (vdec_is_support_4k()) - amvdec_avs2_profile.profile = - "4k, 10bit, dwrite, compressed"; - else - amvdec_avs2_profile.profile = - "10bit, dwrite, compressed"; - vcodec_profile_register(&amvdec_avs2_profile); - } else { - amvdec_avs2_profile.name = "avs2_unsupport"; - } - - INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node, - "avs2", avs2_configs, CONFIG_FOR_RW); - - return 0; -} - -static void __exit amvdec_avs2_driver_remove_module(void) -{ - pr_debug("amvdec_avs2 module remove.\n"); - platform_driver_unregister(&ammvdec_avs2_driver); - platform_driver_unregister(&amvdec_avs2_driver); -} - -/****************************************/ - -module_param(bit_depth_luma, uint, 0664); -MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_avs2 bit_depth_luma\n"); - -module_param(bit_depth_chroma, uint, 0664); -MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_avs2 bit_depth_chroma\n"); - -module_param(frame_width, uint, 0664); -MODULE_PARM_DESC(frame_width, "\n amvdec_avs2 frame_width\n"); - -module_param(frame_height, uint, 0664); -MODULE_PARM_DESC(frame_height, "\n amvdec_avs2 frame_height\n"); - -module_param(debug, uint, 0664); -MODULE_PARM_DESC(debug, "\n amvdec_avs2 debug\n"); - -module_param(debug_again, uint, 0664); -MODULE_PARM_DESC(debug_again, "\n amvdec_avs2 debug_again\n"); - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\nradr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\nrval\n"); - -module_param(pop_shorts, uint, 0664); -MODULE_PARM_DESC(pop_shorts, "\nrval\n"); - -module_param(dbg_cmd, uint, 0664); -MODULE_PARM_DESC(dbg_cmd, "\ndbg_cmd\n"); - -module_param(dbg_skip_decode_index, uint, 0664); -MODULE_PARM_DESC(dbg_skip_decode_index, "\ndbg_skip_decode_index\n"); - -module_param(endian, uint, 0664); -MODULE_PARM_DESC(endian, "\nrval\n"); - -module_param(step, uint, 0664); -MODULE_PARM_DESC(step, "\n amvdec_avs2 step\n"); - -module_param(decode_pic_begin, uint, 0664); -MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_avs2 decode_pic_begin\n"); - -module_param(slice_parse_begin, uint, 0664); -MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_avs2 slice_parse_begin\n"); - -module_param(i_only_flag, uint, 0664); -MODULE_PARM_DESC(i_only_flag, "\n amvdec_avs2 i_only_flag\n"); - -module_param(error_handle_policy, uint, 0664); -MODULE_PARM_DESC(error_handle_policy, "\n amvdec_avs2 error_handle_policy\n"); - -module_param(re_search_seq_threshold, uint, 0664); -MODULE_PARM_DESC(re_search_seq_threshold, "\n amvdec_avs2 re_search_seq_threshold\n"); - -module_param(buf_alloc_width, uint, 0664); -MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); - -module_param(buf_alloc_height, uint, 0664); -MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n"); - -module_param(buf_alloc_depth, uint, 0664); -MODULE_PARM_DESC(buf_alloc_depth, "\n buf_alloc_depth\n"); - -module_param(buf_alloc_size, uint, 0664); -MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); - -module_param(buffer_mode, uint, 0664); -MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n"); - -module_param(buffer_mode_dbg, uint, 0664); -MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n"); -/*USE_BUF_BLOCK*/ -module_param(max_buf_num, uint, 0664); -MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); - -module_param(dynamic_buf_num_margin, uint, 0664); -MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); - -#ifdef CONSTRAIN_MAX_BUF_NUM -module_param(run_ready_max_vf_only_num, uint, 0664); -MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); - -module_param(run_ready_display_q_num, uint, 0664); -MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); - -module_param(run_ready_max_buf_num, uint, 0664); -MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); -#endif - -module_param(mv_buf_margin, uint, 0664); -MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n"); - -module_param(run_ready_min_buf_num, uint, 0664); -MODULE_PARM_DESC(run_ready_min_buf_num, "\n run_ready_min_buf_num\n"); - -/**/ - -module_param(mem_map_mode, uint, 0664); -MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); - -module_param(double_write_mode, uint, 0664); -MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); - -module_param(enable_mem_saving, uint, 0664); -MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n"); - -module_param(force_w_h, uint, 0664); -MODULE_PARM_DESC(force_w_h, "\n force_w_h\n"); - -module_param(force_fps, uint, 0664); -MODULE_PARM_DESC(force_fps, "\n force_fps\n"); - -module_param(max_decoding_time, uint, 0664); -MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n"); - -module_param(on_no_keyframe_skiped, uint, 0664); -MODULE_PARM_DESC(on_no_keyframe_skiped, "\n on_no_keyframe_skiped\n"); - - -module_param(start_decode_buf_level, int, 0664); -MODULE_PARM_DESC(start_decode_buf_level, - "\n avs2 start_decode_buf_level\n"); - -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, - "\n avs2 decode_timeout_val\n"); - -module_param_array(decode_frame_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(display_frame_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(max_process_time, uint, - &max_decode_instance_num, 0664); - -module_param_array(run_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(input_empty, uint, - &max_decode_instance_num, 0664); - -module_param_array(not_run_ready, uint, - &max_decode_instance_num, 0664); - -module_param(video_signal_type, uint, 0664); -MODULE_PARM_DESC(video_signal_type, "\n amvdec_avs2 video_signal_type\n"); - -module_param(force_video_signal_type, uint, 0664); -MODULE_PARM_DESC(force_video_signal_type, "\n amvdec_avs2 force_video_signal_type\n"); - -module_param(enable_force_video_signal_type, uint, 0664); -MODULE_PARM_DESC(enable_force_video_signal_type, "\n amvdec_avs2 enable_force_video_signal_type\n"); - - -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); - -module_param(udebug_pause_pos, uint, 0664); -MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); - -module_param(udebug_pause_val, uint, 0664); -MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); - -module_param(udebug_pause_decode_idx, uint, 0664); -MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); - -module_param(pre_decode_buf_level, int, 0664); -MODULE_PARM_DESC(pre_decode_buf_level, - "\n amvdec_avs2 pre_decode_buf_level\n"); - -module_param(again_threshold, uint, 0664); -MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); - - -module_param(force_disp_pic_index, int, 0664); -MODULE_PARM_DESC(force_disp_pic_index, - "\n amvdec_h265 force_disp_pic_index\n"); - -module_init(amvdec_avs2_driver_init_module); -module_exit(amvdec_avs2_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC avs2 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.h deleted file mode 100644 index 6b51f612e10b..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * drivers/amlogic/amports/vavs2.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#ifndef VAVS2_H -#define VAVS2_H - -#define AVS2_10B_MMU -#define MV_USE_FIXED_BUF - -void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, -unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count); -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/h264/Makefile deleted file mode 100644 index b7c85ee130d7..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264) += amvdec_h264.o -amvdec_h264-objs += vh264.o - -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC) += amvdec_h264mvc.o -amvdec_h264mvc-objs += vh264_mvc.o - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c deleted file mode 100644 index 3e95690e73db..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c +++ /dev/null @@ -1,4461 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/h264/vh264.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#define DEBUG -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include - -#include "../utils/vdec.h" -#include -#include "../utils/amvdec.h" -#include "vh264.h" -#include "../../../stream_input/parser/streambuf.h" -#include -#include -#include -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include "../utils/firmware.h" -#include -#include "../../../common/chips/decoder_cpu_ver_info.h" -#include - - -#include - - -#define DRIVER_NAME "amvdec_h264" -#define MODULE_NAME "amvdec_h264" -#define MEM_NAME "codec_264" -#define HANDLE_H264_IRQ - -#if 0 -/* currently, only iptv supports this function*/ -#define SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY -#endif - -/* #define DEBUG_PTS */ -#if 0 /* MESON_CPU_TYPE <= MESON_CPU_TYPE_MESON6TV */ -#define DROP_B_FRAME_FOR_1080P_50_60FPS -#endif -#define RATE_MEASURE_NUM 8 -#define RATE_CORRECTION_THRESHOLD 5 -#define RATE_24_FPS 4004 /* 23.97 */ -#define RATE_25_FPS 3840 /* 25 */ -#define DUR2PTS(x) ((x)*90/96) -#define PTS2DUR(x) ((x)*96/90) -#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) -#define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2 -#define VDEC_CLOCK_ADJUST_FRAME 30 - -static inline bool close_to(int a, int b, int m) -{ - return (abs(a - b) < m) ? true : false; -} - -static DEFINE_MUTEX(vh264_mutex); -#define DEF_BUF_START_ADDR 0x1000000 -#define V_BUF_ADDR_OFFSET_NEW (0x1ee000) -#define V_BUF_ADDR_OFFSET (0x13e000) - -#define PIC_SINGLE_FRAME 0 -#define PIC_TOP_BOT_TOP 1 -#define PIC_BOT_TOP_BOT 2 -#define PIC_DOUBLE_FRAME 3 -#define PIC_TRIPLE_FRAME 4 -#define PIC_TOP_BOT 5 -#define PIC_BOT_TOP 6 -#define PIC_INVALID 7 - -#define EXTEND_SAR 0xff - -#define VF_POOL_SIZE 64 -#define VF_BUF_NUM 24 -#define WORKSPACE_BUF_NUM 2 -#define PUT_INTERVAL (HZ/100) -#define NO_DISP_WD_COUNT (3 * HZ / PUT_INTERVAL) - -#define SWITCHING_STATE_OFF 0 -#define SWITCHING_STATE_ON_CMD3 1 -#define SWITCHING_STATE_ON_CMD1 2 -#define SWITCHING_STATE_ON_CMD1_PENDING 3 - - -#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001 -#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE 0x0002 -#define DEC_CONTROL_FLAG_DISABLE_FAST_POC 0x0004 - -#define INCPTR(p) ptr_atomic_wrap_inc(&p) - -#define SLICE_TYPE_I 2 -#define SLICE_TYPE_P 5 -#define SLICE_TYPE_B 6 - -struct buffer_spec_s { - unsigned int y_addr; - unsigned int u_addr; - unsigned int v_addr; - - int y_canvas_index; - int u_canvas_index; - int v_canvas_index; - - unsigned int y_canvas_width; - unsigned int u_canvas_width; - unsigned int v_canvas_width; - - unsigned int y_canvas_height; - unsigned int u_canvas_height; - unsigned int v_canvas_height; - - unsigned long phy_addr; - int alloc_count; -}; - -#define spec2canvas(x) \ - (((x)->v_canvas_index << 16) | \ - ((x)->u_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - -static struct vframe_s *vh264_vf_peek(void *); -static struct vframe_s *vh264_vf_get(void *); -static void vh264_vf_put(struct vframe_s *, void *); -static int vh264_vf_states(struct vframe_states *states, void *); -static int vh264_event_cb(int type, void *data, void *private_data); - -static void vh264_prot_init(void); -static int vh264_local_init(void); -static void vh264_put_timer_func(unsigned long arg); -static void stream_switching_done(void); - -static const char vh264_dec_id[] = "vh264-dev"; - -#define PROVIDER_NAME "decoder.h264" - -static const struct vframe_operations_s vh264_vf_provider_ops = { - .peek = vh264_vf_peek, - .get = vh264_vf_get, - .put = vh264_vf_put, - .event_cb = vh264_event_cb, - .vf_states = vh264_vf_states, -}; - -static struct vframe_provider_s vh264_vf_prov; -/*TODO irq*/ -#if 1 -static u32 frame_width, frame_height, frame_dur, frame_prog, frame_packing_type, - last_duration; -static u32 saved_resolution; -static u32 last_mb_width, last_mb_height; -#else -static u32 frame_buffer_size; -static u32 frame_width, frame_height, frame_dur, frame_prog, last_duration; -static u32 last_mb_width, last_mb_height; -static u32 frame_packing_type; -#endif -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(delay_display_q, struct vframe_s *, VF_POOL_SIZE); - -static struct vframe_s vfpool[VF_POOL_SIZE]; -static s32 vfbuf_use[VF_BUF_NUM]; -static struct buffer_spec_s buffer_spec[VF_BUF_NUM]; -static struct buffer_spec_s fense_buffer_spec[2]; -/* disp buf + keep buf+ fense buf + workspace */ - -#define MAX_BLK_BUFFERS (VF_BUF_NUM + 2 + WORKSPACE_BUF_NUM) -#define VF_BUFFER_IDX(n) (WORKSPACE_BUF_NUM + n) -#define FENSE_BUFFER_IDX(n) (WORKSPACE_BUF_NUM + VF_BUF_NUM + n) - -#define USER_DATA_RUND_SIZE (USER_DATA_SIZE + 4096) -static struct vframe_s fense_vf[2]; - -static struct timer_list recycle_timer; -static u32 stat; -static s32 buf_offset; -static u32 pts_outside; -static u32 sync_outside; -static u32 dec_control; -static u32 vh264_ratio; -static u32 vh264_rotation; -static u32 use_idr_framerate; -static u32 high_bandwidth; - -static u32 seq_info; -static u32 timing_info_present_flag; -static u32 fixed_frame_rate_flag; -static u32 fixed_frame_rate_check_count; -static u32 aspect_ratio_info; -static u32 num_units_in_tick; -static u32 time_scale; -static u32 h264_ar; -static u32 decoder_debug_flag; -static u32 dpb_size_adj = 6; -static u32 fr_hint_status; - -#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS -static u32 last_interlaced; -#endif -static bool is_4k; -static unsigned char h264_first_pts_ready; -static bool h264_first_valid_pts_ready; -static u32 h264pts1, h264pts2; -static u32 h264_pts_count, duration_from_pts_done, duration_on_correcting; -static u32 vh264_error_count; -static u32 vh264_no_disp_count; -static u32 fatal_error_flag; -static u32 fatal_error_reset; -static u32 max_refer_buf = 1; -static u32 decoder_force_reset; -static unsigned int no_idr_error_count; -static unsigned int no_idr_error_max = 60; -static unsigned int canvas_mode; - -#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY -/* 0~128*/ -static u32 bad_block_scale; -#endif -static u32 enable_userdata_debug; - -static unsigned int enable_switch_fense = 1; -#define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k) -static struct vframe_qos_s s_vframe_qos; -static int frame_count; - -#if 0 -static u32 vh264_no_disp_wd_count; -#endif -static u32 vh264_running; -static s32 vh264_stream_switching_state; -static s32 vh264_eos; -static struct vframe_s *p_last_vf; -static s32 iponly_early_mode; -static void *mm_blk_handle; -static int tvp_flag; -static bool is_reset; - -/*TODO irq*/ -#if 1 -static u32 last_pts, last_pts_remainder; -#else -static u32 last_pts; -#endif -static bool check_pts_discontinue; -static u32 wait_buffer_counter; -static u32 video_signal_from_vui; - -static uint error_recovery_mode; -static uint error_recovery_mode_in = 3; -static uint error_recovery_mode_use = 3; - -static uint mb_total = 0, mb_width = 0, mb_height; -static uint saved_idc_level; -#define UCODE_IP_ONLY 2 -#define UCODE_IP_ONLY_PARAM 1 -static uint ucode_type; - -#ifdef DEBUG_PTS -static unsigned long pts_missed, pts_hit; -#endif -static uint debugfirmware; - -static atomic_t vh264_active = ATOMIC_INIT(0); -static int vh264_reset; -static struct work_struct error_wd_work; -static struct work_struct stream_switching_work; -static struct work_struct set_parameter_work; -static struct work_struct notify_work; -static struct work_struct set_clk_work; -static struct work_struct userdata_push_work; - -struct h264_qos_data_node_t { - struct list_head list; - - uint32_t b_offset; - int poc; - /* picture qos infomation*/ - int max_qp; - int avg_qp; - int min_qp; - int max_skip; - int avg_skip; - int min_skip; - int max_mv; - int min_mv; - int avg_mv; -}; - -/*qos data records list waiting for match with picture that be display*/ -static struct list_head picture_qos_list; -/*free qos data records list*/ -static struct list_head free_qos_nodes_list; -#define MAX_FREE_QOS_NODES 64 -static struct h264_qos_data_node_t free_nodes[MAX_FREE_QOS_NODES]; -static struct work_struct qos_work; -static struct dec_sysinfo vh264_amstream_dec_info; -static dma_addr_t mc_dma_handle; -static void *mc_cpu_addr; -static u32 first_offset; -static u32 first_pts; -static u32 first_frame_size; -static u64 first_pts64; -static bool first_pts_cached; -static void *sei_data_buffer; -static dma_addr_t sei_data_buffer_phys; -static int clk_adj_frame_count; - -#define MC_OFFSET_HEADER 0x0000 -#define MC_OFFSET_DATA 0x1000 -#define MC_OFFSET_MMCO 0x2000 -#define MC_OFFSET_LIST 0x3000 -#define MC_OFFSET_SLICE 0x4000 - -#define MC_TOTAL_SIZE (20*SZ_1K) -#define MC_SWAP_SIZE (4*SZ_1K) - -#define MODE_ERROR 0 -#define MODE_FULL 1 - -static DEFINE_SPINLOCK(lock); -static DEFINE_SPINLOCK(prepare_lock); -static DEFINE_SPINLOCK(recycle_lock); - -static bool block_display_q; -static int vh264_stop(int mode); -static s32 vh264_init(void); - - -#define DFS_HIGH_THEASHOLD 3 - -static bool pts_discontinue; - -static struct ge2d_context_s *ge2d_videoh264_context; - -static struct vdec_info *gvs; - -static struct vdec_s *vdec_h264; - -static int ge2d_videoh264task_init(void) -{ - if (ge2d_videoh264_context == NULL) - ge2d_videoh264_context = create_ge2d_work_queue(); - - if (ge2d_videoh264_context == NULL) { - pr_info("create_ge2d_work_queue video task failed\n"); - return -1; - } - return 0; -} - -static int ge2d_videoh264task_release(void) -{ - if (ge2d_videoh264_context) { - destroy_ge2d_work_queue(ge2d_videoh264_context); - ge2d_videoh264_context = NULL; - } - return 0; -} - -static int ge2d_canvas_dup(struct canvas_s *srcy, struct canvas_s *srcu, - struct canvas_s *des, int format, u32 srcindex, - u32 desindex) -{ - - struct config_para_ex_s ge2d_config; - /* pr_info("[%s]h264 ADDR srcy[0x%lx] srcu[0x%lx] des[0x%lx]\n", - * __func__, srcy->addr, srcu->addr, des->addr); - */ - memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); - - ge2d_config.alu_const_color = 0; - ge2d_config.bitmask_en = 0; - ge2d_config.src1_gb_alpha = 0; - - ge2d_config.src_planes[0].addr = srcy->addr; - ge2d_config.src_planes[0].w = srcy->width; - ge2d_config.src_planes[0].h = srcy->height; - - ge2d_config.src_planes[1].addr = srcu->addr; - ge2d_config.src_planes[1].w = srcu->width; - ge2d_config.src_planes[1].h = srcu->height; - - ge2d_config.dst_planes[0].addr = des->addr; - ge2d_config.dst_planes[0].w = des->width; - ge2d_config.dst_planes[0].h = des->height; - - ge2d_config.src_para.canvas_index = srcindex; - ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config.src_para.format = format; - ge2d_config.src_para.fill_color_en = 0; - ge2d_config.src_para.fill_mode = 0; - ge2d_config.src_para.color = 0; - ge2d_config.src_para.top = 0; - ge2d_config.src_para.left = 0; - ge2d_config.src_para.width = srcy->width; - ge2d_config.src_para.height = srcy->height; - - ge2d_config.dst_para.canvas_index = desindex; - ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config.dst_para.format = format; - ge2d_config.dst_para.fill_color_en = 0; - ge2d_config.dst_para.fill_mode = 0; - ge2d_config.dst_para.color = 0; - ge2d_config.dst_para.top = 0; - ge2d_config.dst_para.left = 0; - ge2d_config.dst_para.width = srcy->width; - ge2d_config.dst_para.height = srcy->height; - - if (ge2d_context_config_ex(ge2d_videoh264_context, &ge2d_config) < 0) { - pr_info("ge2d_context_config_ex failed\n"); - return -1; - } - - stretchblt_noalpha(ge2d_videoh264_context, 0, 0, srcy->width, - srcy->height, 0, 0, srcy->width, srcy->height); - - return 0; -} - -static inline int fifo_level(void) -{ - return VF_POOL_SIZE - kfifo_len(&newframe_q); -} - - -void spec_set_canvas(struct buffer_spec_s *spec, - unsigned int width, unsigned int height) -{ - int endian; - - endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; - canvas_config_ex(spec->y_canvas_index, - spec->y_addr, - width, height, - CANVAS_ADDR_NOWRAP, canvas_mode, endian); - - canvas_config_ex(spec->u_canvas_index, - spec->u_addr, - width, height / 2, - CANVAS_ADDR_NOWRAP, canvas_mode, endian); - -} - -static void vh264_notify_work(struct work_struct *work) -{ - pr_info("frame duration changed %d\n", frame_dur); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)frame_dur)); - - return; -} - -static void prepare_display_q(void) -{ - unsigned long flags; - int count; - - spin_lock_irqsave(&prepare_lock, flags); - - if (block_display_q) { - spin_unlock_irqrestore(&prepare_lock, flags); - return; - } - - spin_unlock_irqrestore(&prepare_lock, flags); - - count = (int)VF_POOL_SIZE - - kfifo_len(&delay_display_q) - - kfifo_len(&display_q) - - kfifo_len(&recycle_q) - - kfifo_len(&newframe_q); - - if ((vh264_stream_switching_state != SWITCHING_STATE_OFF) - || !EN_SWITCH_FENCE()) - count = 0; - else - count = (count < 2) ? 0 : 2; - - while (kfifo_len(&delay_display_q) > count) { - struct vframe_s *vf; - - if (kfifo_get(&delay_display_q, &vf)) { - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - } -} - -static struct vframe_s *vh264_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vh264_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vh264_vf_put(struct vframe_s *vf, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&recycle_lock, flags); - - if ((vf != &fense_vf[0]) && (vf != &fense_vf[1])) - kfifo_put(&recycle_q, (const struct vframe_s *)vf); - - spin_unlock_irqrestore(&recycle_lock, flags); -} - -static int vh264_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vh264_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vh264_local_init(); - vh264_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vh264_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -static int vh264_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q) + - kfifo_len(&delay_display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - - return 0; -} - -#if 0 -static tvin_trans_fmt_t convert_3d_format(u32 type) -{ - const tvin_trans_fmt_t conv_tab[] = { - 0, /* checkerboard */ - 0, /* column alternation */ - TVIN_TFMT_3D_LA, /* row alternation */ - TVIN_TFMT_3D_LRH_OLER, /* side by side */ - TVIN_TFMT_3D_FA /* top bottom */ - }; - - return (type <= 4) ? conv_tab[type] : 0; -} -#endif - - - -#define DUMP_CC_AS_ASCII - -#ifdef DUMP_CC_AS_ASCII -static int vbi_to_ascii(int c) -{ - if (c < 0) - return '?'; - - c &= 0x7F; - - if (c < 0x20 || c >= 0x7F) - return '.'; - - return c; -} - -static void dump_cc_ascii(const uint8_t *buf, unsigned int vpts, int poc) -{ - int cc_flag; - int cc_count; - int i; - int szAscii[32]; - int index = 0; - - cc_flag = buf[1] & 0x40; - if (!cc_flag) { - pr_info("### cc_flag is invalid\n"); - return; - } - cc_count = buf[1] & 0x1f; - - for (i = 0; i < cc_count; ++i) { - unsigned int b0; - unsigned int cc_valid; - unsigned int cc_type; - unsigned char cc_data1; - unsigned char cc_data2; - - b0 = buf[3 + i * 3]; - cc_valid = b0 & 4; - cc_type = b0 & 3; - cc_data1 = buf[4 + i * 3]; - cc_data2 = buf[5 + i * 3]; - - - if (cc_type == 0) { - /* NTSC pair, Line 21 */ - szAscii[index++] = vbi_to_ascii(cc_data1); - szAscii[index++] = vbi_to_ascii(cc_data2); - if ((!cc_valid) || (i >= 3)) - break; - } - } - - if (index > 0 && index <= 8) { - char pr_buf[128]; - int len; - - sprintf(pr_buf, "push vpts:0x%x, poc:%d :", vpts, poc); - len = strlen(pr_buf); - for (i=0;i= 16) { - int i; - - for (i=0;i<16;i++) - sprintf(buf+i*3, "%02x ", pdata[i]); - - pr_info("%s\n", buf); - nLeft -= 16; - pdata += 16; - } - - while (nLeft >= 8) { - int i; - for (i=0;i= user_data_len) { - wp_start = user_data_wp - user_data_len; - - pdata = (unsigned char *)sei_data_buffer; - pdata += wp_start; - nLeft = user_data_len; - - memset(szBuf, 0, 256); - memcpy(szBuf, pdata, user_data_len); - } else { - wp_start = user_data_wp + - USER_DATA_SIZE - user_data_len; - - pdata = (unsigned char *)sei_data_buffer; - pdata += wp_start; - nLeft = USER_DATA_SIZE - wp_start; - - memset(szBuf, 0, 256); - memcpy(szBuf, pdata, nLeft); - nOffset = nLeft; - - pdata = (unsigned char *)sei_data_buffer; - nLeft = user_data_wp; - memcpy(szBuf+nOffset, pdata, nLeft); - } - - aml_swap_data(szBuf, user_data_len); - -#ifdef DUMP_USER_DATA_HEX - print_data(szBuf, user_data_len); -#endif - -#ifdef DUMP_CC_AS_ASCII - dump_cc_ascii(szBuf+7, pts, poc); -#endif -} - - -struct vh264_userdata_recored_t { - struct userdata_meta_info_t meta_info; - u32 rec_start; - u32 rec_len; -}; - -#define USERDATA_FIFO_NUM 256 - -struct vh264_userdata_info_t { - struct vh264_userdata_recored_t records[USERDATA_FIFO_NUM]; - u8 *data_buf; - u8 *data_buf_end; - u32 buf_len; - u32 read_index; - u32 write_index; - u32 last_wp; -}; - -static struct vh264_userdata_info_t *p_userdata_mgr; - -static DEFINE_MUTEX(userdata_mutex); - - -void vh264_crate_userdata_manager(u8 *userdata_buf, int buf_len) -{ - p_userdata_mgr = (struct vh264_userdata_info_t *) - vmalloc(sizeof(struct vh264_userdata_info_t)); - if (p_userdata_mgr) { - memset(p_userdata_mgr, 0, - sizeof(struct vh264_userdata_info_t)); - p_userdata_mgr->data_buf = userdata_buf; - p_userdata_mgr->buf_len = buf_len; - p_userdata_mgr->data_buf_end = userdata_buf + buf_len; - } -} - -void vh264_destroy_userdata_manager(void) -{ - if (p_userdata_mgr) { - vfree(p_userdata_mgr); - p_userdata_mgr = NULL; - } -} - -/* -#define DUMP_USER_DATA -*/ -#ifdef DUMP_USER_DATA - -#define MAX_USER_DATA_SIZE 3145728 -static void *user_data_buf; -static unsigned char *pbuf_start; -static int total_len; -static int bskip; -static int n_userdata_id; - - -static void print_mem_data(unsigned char *pdata, - int len, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id) -{ - int nLeft; - - nLeft = len; -#if 0 - pr_info("%d len = %d, flag = %d, duration = %d, vpts = 0x%x, vpts_valid = %d\n", - rec_id, len, flag, - duration, vpts, vpts_valid); -#endif - pr_info("%d len = %d, flag = %d, vpts = 0x%x\n", - rec_id, len, flag, vpts); - - - while (nLeft >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7], - pdata[8], pdata[9], pdata[10], pdata[11], - pdata[12], pdata[13], pdata[14], pdata[15]); - nLeft -= 16; - pdata += 16; - } - - - while (nLeft > 0) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } -} - - -static void dump_data(u8 *pdata, - unsigned int user_data_length, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id) -{ - unsigned char szBuf[256]; - - - memset(szBuf, 0, 256); - memcpy(szBuf, pdata, user_data_length); -/* - aml_swap_data(szBuf, user_data_length); -*/ - - print_mem_data(szBuf, user_data_length, - flag, duration, vpts, - vpts_valid, rec_id); - -#ifdef DEBUG_CC_DUMP_ASCII - dump_cc_ascii(szBuf+7); -#endif -} - -static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta) -{ - u32 *pLen; - int info_cnt; - u8 *pbuf_end; - - if (!user_data_buf) - return; - - if (bskip) { - pr_info("over size, skip\n"); - return; - } - info_cnt = 0; - pLen = (u32 *)pbuf_start; - - *pLen = len; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->duration; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->flags; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts_valid; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - - *pLen = n_userdata_id; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - - - pbuf_end = (u8 *)sei_data_buffer + USER_DATA_SIZE; - if (pdata + len > pbuf_end) { - int first_section_len; - - first_section_len = pbuf_end - pdata; - memcpy(pbuf_start, pdata, first_section_len); - pdata = (u8 *)sei_data_buffer; - pbuf_start += first_section_len; - memcpy(pbuf_start, pdata, len - first_section_len); - pbuf_start += len - first_section_len; - } else { - memcpy(pbuf_start, pdata, len); - pbuf_start += len; - } - - total_len += len + info_cnt * sizeof(u32); - if (total_len >= MAX_USER_DATA_SIZE-4096) - bskip = 1; -} - - -static void dump_userdata_info( - void *puser_data, - int len, - struct userdata_meta_info_t *pmeta) -{ - u8 *pstart; - - pstart = (u8 *)puser_data; - - - push_to_buf(pstart, len, pmeta); -} - -static void show_user_data_buf(void) -{ - u8 *pbuf; - int len; - unsigned int flag; - unsigned int duration; - unsigned int vpts; - unsigned int vpts_valid; - int rec_id; - - pr_info("show user data buf\n"); - pbuf = user_data_buf; - - while (pbuf < pbuf_start) { - u32 *pLen; - - pLen = (u32 *)pbuf; - - len = *pLen; - pLen++; - pbuf += sizeof(u32); - - duration = *pLen; - pLen++; - pbuf += sizeof(u32); - - flag = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts_valid = *pLen; - pLen++; - pbuf += sizeof(u32); - - rec_id = *pLen; - pLen++; - pbuf += sizeof(u32); - - dump_data(pbuf, len, flag, duration, vpts, vpts_valid, rec_id); - pbuf += len; - msleep(30); - } -} - -static int vh264_init_userdata_dump(void) -{ - user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); - if (user_data_buf) - return 1; - else - return 0; -} - -static void vh264_dump_userdata(void) -{ - if (user_data_buf) { - show_user_data_buf(); - kfree(user_data_buf); - user_data_buf = NULL; - } -} - -static void vh264_reset_user_data_buf(void) -{ - total_len = 0; - pbuf_start = user_data_buf; - bskip = 0; - n_userdata_id = 0; -} -#endif - -static void vh264_add_userdata(struct userdata_meta_info_t meta_info, int wp) -{ - struct vh264_userdata_recored_t *p_userdata_rec; - int data_length; - - mutex_lock(&userdata_mutex); - - if (p_userdata_mgr) { - if (wp > p_userdata_mgr->last_wp) - data_length = wp - p_userdata_mgr->last_wp; - else - data_length = wp + p_userdata_mgr->buf_len - - p_userdata_mgr->last_wp; - - if (data_length & 0x7) - data_length = (((data_length + 8) >> 3) << 3); -#if 0 - pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", - p_userdata_mgr->read_index, - p_userdata_mgr->write_index, - data_length, - p_userdata_mgr->last_wp, - wp, - n_userdata_id); -#endif - p_userdata_rec = p_userdata_mgr->records + - p_userdata_mgr->write_index; - p_userdata_rec->meta_info = meta_info; - p_userdata_rec->rec_start = p_userdata_mgr->last_wp; - p_userdata_rec->rec_len = data_length; - p_userdata_mgr->last_wp = wp; - -#ifdef DUMP_USER_DATA - dump_userdata_info(p_userdata_mgr->data_buf + - p_userdata_rec->rec_start, - data_length, - &meta_info); - n_userdata_id++; -#endif - - p_userdata_mgr->write_index++; - if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM) - p_userdata_mgr->write_index = 0; - } - mutex_unlock(&userdata_mutex); - - vdec_wakeup_userdata_poll(vdec_h264); -} - -static int vh264_user_data_read(struct vdec_s *vdec, - struct userdata_param_t *puserdata_para) -{ - int rec_ri, rec_wi; - int rec_len; - u8 *rec_data_start; - u8 *pdest_buf; - struct vh264_userdata_recored_t *p_userdata_rec; - u32 data_size; - u32 res; - int copy_ok = 1; - - - pdest_buf = puserdata_para->pbuf_addr; - - - mutex_lock(&userdata_mutex); - - if (!p_userdata_mgr) { - mutex_unlock(&userdata_mutex); - return 0; - } -/* - pr_info("ri = %d, wi = %d\n", - p_userdata_mgr->read_index, - p_userdata_mgr->write_index); -*/ - rec_ri = p_userdata_mgr->read_index; - rec_wi = p_userdata_mgr->write_index; - - if (rec_ri == rec_wi) { - mutex_unlock(&userdata_mutex); - return 0; - } - - p_userdata_rec = p_userdata_mgr->records + rec_ri; - - rec_len = p_userdata_rec->rec_len; - rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf; -/* - pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n", - p_userdata_rec->rec_len, - p_userdata_rec->rec_start, - puserdata_para->buf_len); -*/ - if (rec_len <= puserdata_para->buf_len) { - /* dvb user data buffer is enought to copy the whole recored. */ - data_size = rec_len; - if (rec_data_start + data_size - > p_userdata_mgr->data_buf_end) { - int first_section_len; - - first_section_len = p_userdata_mgr->buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p1 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)p_userdata_mgr->data_buf, - data_size - first_section_len); - if (res) { - pr_info("p2 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= - data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = - data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p3 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - p_userdata_mgr->read_index++; - if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM) - p_userdata_mgr->read_index = 0; - } - } else { - /* dvb user data buffer is not enought - to copy the whole recored. */ - data_size = puserdata_para->buf_len; - if (rec_data_start + data_size - > p_userdata_mgr->data_buf_end) { - int first_section_len; - - first_section_len = p_userdata_mgr->buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p4 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - /* first secton copy is ok*/ - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)p_userdata_mgr->data_buf, - data_size - first_section_len); - if (res) { - pr_info("p5 read not end res=%d, request=%d\n", - res, - data_size - first_section_len); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p6 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - p_userdata_mgr->read_index++; - if (p_userdata_mgr->read_index - >= USERDATA_FIFO_NUM) - p_userdata_mgr->read_index = 0; - } - - } - puserdata_para->meta_info = p_userdata_rec->meta_info; - - if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) - puserdata_para->meta_info.records_in_que = - p_userdata_mgr->write_index - - p_userdata_mgr->read_index; - else - puserdata_para->meta_info.records_in_que = - p_userdata_mgr->write_index + - USERDATA_FIFO_NUM - - p_userdata_mgr->read_index; - - puserdata_para->version = (0<<24|0<<16|0<<8|1); - - mutex_unlock(&userdata_mutex); - - return 1; -} - -static void vh264_wakeup_userdata_poll(struct vdec_s *vdec) -{ - amstream_wakeup_userdata_poll(vdec); -} - -static void vh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) -{ - mutex_lock(&userdata_mutex); - - if (p_userdata_mgr) { - pr_info("h264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", - bInit, p_userdata_mgr->read_index, - p_userdata_mgr->write_index); - p_userdata_mgr->read_index = 0; - p_userdata_mgr->write_index = 0; - - if (bInit) - p_userdata_mgr->last_wp = 0; - } - - mutex_unlock(&userdata_mutex); -} - -static void h264_reset_qos_mgr(void) -{ - int i; - - pr_info("h264_reset_qos_mgr\n"); - - INIT_LIST_HEAD(&free_qos_nodes_list); - INIT_LIST_HEAD(&picture_qos_list); - - for (i = 0; i < MAX_FREE_QOS_NODES; i++) { - free_nodes[i].b_offset = 0xFFFFFFFF; - - list_add_tail(&free_nodes[i].list, - &free_qos_nodes_list); - } -} - - -static void load_qos_data(int pic_number, uint32_t b_offset) -{ - uint32_t blk88_y_count; - uint32_t blk88_c_count; - uint32_t blk22_mv_count; - uint32_t rdata32; - int32_t mv_hi; - int32_t mv_lo; - uint32_t rdata32_l; - uint32_t mvx_L0_hi; - uint32_t mvy_L0_hi; - uint32_t mvx_L1_hi; - uint32_t mvy_L1_hi; - int64_t value; - uint64_t temp_value; -/* -#define DEBUG_QOS -*/ -#define SUPPORT_NODE - -#ifdef SUPPORT_NODE - struct h264_qos_data_node_t *node; - struct h264_qos_data_node_t *tmp; - int bFoundNode = 0; - - node = NULL; - if (!list_empty(&picture_qos_list)) { - list_for_each_entry_safe(node, tmp, &picture_qos_list, list) { - if (node->b_offset == b_offset) { - bFoundNode = 1; - break; - } - } - } - /* - pr_info("bFoundNode = %d, node:0x%p\n", bFoundNode, node); - */ - if (!bFoundNode) { - if (!list_empty(&free_qos_nodes_list)) { - node = list_entry( - free_qos_nodes_list.next, - struct h264_qos_data_node_t, - list); - /* - pr_info("get a node:0x%p\n", node); - */ - } else { - pr_info("there is no qos data node avaible\n"); - - return; - } - } - - node->b_offset = b_offset; - node->poc = pic_number; - - node->max_mv = 0; - node->avg_mv = 0; - node->min_mv = 0; - - node->max_skip = 0; - node->avg_skip = 0; - node->min_skip = 0; - - node->max_qp = 0; - node->avg_qp = 0; - node->min_qp = 0; -#endif - - - - - - - /* set rd_idx to 0 */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0); - blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA); - if (blk88_y_count == 0) { -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); - -#ifdef SUPPORT_NODE - list_move(&node->list, &picture_qos_list); -#endif - return; - } - /* qp_y_sum */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_y_count, - rdata32, blk88_y_count); -#endif -#ifdef SUPPORT_NODE - node->avg_qp = rdata32/blk88_y_count; -#endif - - /* intra_y_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - /* skipped_y_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif -#ifdef SUPPORT_NODE - node->avg_skip = rdata32*100/blk88_y_count; -#endif - /* coeff_non_zero_y_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_y_count*1)), - '%', rdata32); -#endif - /* blk66_c_count */ - blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA); - if (blk88_c_count == 0) { -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); - -#ifdef SUPPORT_NODE - list_move(&node->list, &picture_qos_list); -#endif - return; - } - /* qp_c_sum */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_c_count, - rdata32, blk88_c_count); -#endif - /* intra_c_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* skipped_cu_c_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* coeff_non_zero_c_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_c_count*1)), - '%', rdata32); -#endif - - /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], - 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y QP min : %d\n", - pic_number, (rdata32>>0)&0xff); -#endif -#ifdef SUPPORT_NODE - node->min_qp = (rdata32>>0)&0xff; -#endif - -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y QP max : %d\n", - pic_number, (rdata32>>8)&0xff); -#endif -#ifdef SUPPORT_NODE - node->max_qp = (rdata32>>8)&0xff; -#endif - -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C QP min : %d\n", - pic_number, (rdata32>>16)&0xff); - pr_info(" [Picture %d Quality] C QP max : %d\n", - pic_number, (rdata32>>24)&0xff); -#endif - - /* blk22_mv_count */ - blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA); - if (blk22_mv_count == 0) { -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] NO MV Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); -#ifdef SUPPORT_NODE - list_move(&node->list, &picture_qos_list); -#endif - return; - } - /* mvy_L1_count[39:32], mvx_L1_count[39:32], - mvy_L0_count[39:32], mvx_L0_count[39:32] */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - /* should all be 0x00 or 0xff */ -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n", - pic_number, rdata32); -#endif - mvx_L0_hi = ((rdata32>>0)&0xff); - mvy_L0_hi = ((rdata32>>8)&0xff); - mvx_L1_hi = ((rdata32>>16)&0xff); - mvy_L1_hi = ((rdata32>>24)&0xff); - - /* mvx_L0_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvx_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvx_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; - value = div_s64(value, blk22_mv_count); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", - pic_number, (int)(value), - value, blk22_mv_count); -#endif -#ifdef SUPPORT_NODE - node->avg_mv = value; -#endif - - /* mvy_L0_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvy_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvy_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvx_L1_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvx_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvx_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvy_L1_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvy_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvy_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n", - pic_number, mv_hi); -#endif -#ifdef SUPPORT_NODE - node->max_mv = mv_hi; -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n", - pic_number, mv_lo); -#endif -#ifdef SUPPORT_NODE - node->min_mv = mv_lo; -#endif - - /* {mvy_L0_max, mvy_L0_min} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvx_L1_max, mvx_L1_min} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvy_L1_max, mvy_L1_min} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", - pic_number, rdata32); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); -#ifdef SUPPORT_NODE - list_move(&node->list, &picture_qos_list); -#endif -} - -void search_qos_node(struct vframe_qos_s *picture_qos, uint32_t b_offset) -{ - struct h264_qos_data_node_t *node; - struct h264_qos_data_node_t *tmp; - - if (!list_empty(&picture_qos_list)) { - list_for_each_entry_safe(node, tmp, &picture_qos_list, list) { - if (node->b_offset == b_offset) { - - picture_qos->avg_mv = node->avg_mv; - picture_qos->min_mv = node->min_mv; - picture_qos->max_mv = node->max_mv; - - picture_qos->avg_skip = node->avg_skip; - picture_qos->min_skip = node->min_skip; - picture_qos->max_skip = node->max_skip; - - picture_qos->avg_qp = node->avg_qp; - picture_qos->min_qp = node->min_qp; - picture_qos->max_qp = node->max_qp; - -#if 0 - pr_info("POC:%d, mv: max:%d, avg:%d, min:%d\n" - "qp: max:%d, avg:%d, min:%d\n" - "skip: max:%d, avg:%d, min:%d\n", - node->poc, - picture_qos->max_mv, - picture_qos->avg_mv, - picture_qos->min_mv, - picture_qos->max_qp, - picture_qos->avg_qp, - picture_qos->min_qp, - picture_qos->max_skip, - picture_qos->avg_skip, - picture_qos->min_skip); -#endif - node->b_offset = 0xFFFFFFFF; - list_move(&node->list, &free_qos_nodes_list); - - break; - } - } - } -} - -static void qos_do_work(struct work_struct *work) -{ - uint32_t poc; - uint32_t bOffset; - - - poc = READ_VREG(AV_SCRATCH_M); - bOffset = READ_VREG(AV_SCRATCH_L); -/* - pr_info("poc:%d, bOffset:0x%x\n", poc, bOffset); -*/ - load_qos_data(poc, bOffset); - - - WRITE_VREG(AV_SCRATCH_0, 0); -} - -static void userdata_push_do_work(struct work_struct *work) -{ - unsigned int sei_itu35_flags; - unsigned int sei_itu35_wp; - unsigned int sei_itu35_data_length; - - struct userdata_meta_info_t meta_info; - u32 offset, pts; - u64 pts_us64 = 0; - u32 slice_type; - u32 reg; - u32 poc_number; - u32 picture_struct; - - memset(&meta_info, 0, sizeof(meta_info)); - - meta_info.duration = frame_dur; - - reg = READ_VREG(AV_SCRATCH_M); - poc_number = reg & 0x7FFFFFF; - if ((poc_number >> 16) == 0x7FF) - poc_number = (reg & 0x7FFFFFF) - 0x8000000; - - slice_type = (reg >> 29) & 0x7; - switch (slice_type) { - case SLICE_TYPE_I: - meta_info.flags |= 1<<7; - break; - case SLICE_TYPE_P: - meta_info.flags |= 3<<7; - break; - case SLICE_TYPE_B: - meta_info.flags |= 2<<7; - break; - } - meta_info.poc_number = poc_number; - picture_struct = (reg >> 27) & 0x3; - - meta_info.flags |= (VFORMAT_H264 << 3) | (picture_struct << 12); - - - offset = READ_VREG(AV_SCRATCH_L); - - if (pts_pickout_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) { - pr_info("pts pick outfailed, offset:0x%x\n", offset); - pts = -1; - meta_info.vpts_valid = 0; - } else - meta_info.vpts_valid = 1; - meta_info.vpts = pts; -/* - pr_info("offset:0x%x, vpts:0x%x, slice:%d, poc:%d\n", - offset, pts, slice_type, - poc_number); -*/ - sei_itu35_flags = READ_VREG(AV_SCRATCH_J); - sei_itu35_wp = (sei_itu35_flags >> 16) & 0xffff; - sei_itu35_data_length = sei_itu35_flags & 0x7fff; - - if (enable_userdata_debug) - udr_dump_data(sei_itu35_wp, - sei_itu35_data_length, - pts, poc_number); - - - vh264_add_userdata(meta_info, sei_itu35_wp); - - WRITE_VREG(AV_SCRATCH_J, 0); -} - - -static void set_frame_info(struct vframe_s *vf) -{ - vf->width = frame_width; - vf->height = frame_height; - vf->duration = frame_dur; - vf->ratio_control = - (min(h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) << - DISP_RATIO_ASPECT_RATIO_BIT; - vf->orientation = vh264_rotation; - vf->flag = 0; - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS - vf->trans_fmt = 0; - if ((vf->trans_fmt == TVIN_TFMT_3D_LRF) || - (vf->trans_fmt == TVIN_TFMT_3D_LA)) { - vf->left_eye.start_x = 0; - vf->left_eye.start_y = 0; - vf->left_eye.width = frame_width / 2; - vf->left_eye.height = frame_height; - - vf->right_eye.start_x = 0; - vf->right_eye.start_y = 0; - vf->right_eye.width = frame_width / 2; - vf->right_eye.height = frame_height; - } else if ((vf->trans_fmt == TVIN_TFMT_3D_LRH_OLER) || - (vf->trans_fmt == TVIN_TFMT_3D_TB)) { - vf->left_eye.start_x = 0; - vf->left_eye.start_y = 0; - vf->left_eye.width = frame_width / 2; - vf->left_eye.height = frame_height; - - vf->right_eye.start_x = 0; - vf->right_eye.start_y = 0; - vf->right_eye.width = frame_width / 2; - vf->right_eye.height = frame_height; - } -#endif - -} - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER -static void vh264_ppmgr_reset(void) -{ - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); - - vh264_local_init(); - - pr_info("vh264dec: vf_ppmgr_reset\n"); -} -#endif - -static int get_max_dpb_size(int level_idc, int mb_width, int mb_height) -{ - int size, r; - - switch (level_idc) { - case 10: - r = 1485; - break; - case 11: - r = 3375; - break; - case 12: - case 13: - case 20: - r = 8910; - break; - case 21: - r = 17820; - break; - case 22: - case 30: - r = 30375; - break; - case 31: - r = 67500; - break; - case 32: - r = 76800; - break; - case 40: - case 41: - case 42: - r = 122880; - break; - case 50: - r = 414000; - break; - case 51: - case 52: - r = 691200; - break; - default: - return 0; - } - size = (mb_width * mb_height + - (mb_width * mb_height / 2)) * 256 * 10; - r = (r * 1024 + size-1) / size; - r = min(r, 16); - /*pr_info("max_dpb %d size:%d\n", r, size);*/ - return r; -} -static void vh264_set_params(struct work_struct *work) -{ - int aspect_ratio_info_present_flag, aspect_ratio_idc; - int max_dpb_size, actual_dpb_size, max_reference_size; - int i, mb_mv_byte, ret; - unsigned long addr; - unsigned int post_canvas, buf_size, endian; - unsigned int frame_mbs_only_flag; - unsigned int chroma_format_idc, chroma444, video_signal; - unsigned int crop_infor, crop_bottom, crop_right, level_idc; - if (!atomic_read(&vh264_active)) - return; - mutex_lock(&vh264_mutex); - if (vh264_stream_switching_state == SWITCHING_STATE_ON_CMD1) - vh264_stream_switching_state = SWITCHING_STATE_ON_CMD1_PENDING; - post_canvas = get_post_canvas(); - clk_adj_frame_count = 0; - /* set to max decoder clock rate at the beginning */ - - if (vdec_is_support_4k()) - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); - else - vdec_source_changed(VFORMAT_H264, 1920, 1080, 29); - - timing_info_present_flag = 0; - mb_width = READ_VREG(AV_SCRATCH_1); - seq_info = READ_VREG(AV_SCRATCH_2); - aspect_ratio_info = READ_VREG(AV_SCRATCH_3); - num_units_in_tick = READ_VREG(AV_SCRATCH_4); - time_scale = READ_VREG(AV_SCRATCH_5); - level_idc = READ_VREG(AV_SCRATCH_A); - if (level_idc > 0) - saved_idc_level = level_idc; - else if (saved_idc_level > 0) - level_idc = saved_idc_level; - video_signal = READ_VREG(AV_SCRATCH_H); - video_signal_from_vui = - ((video_signal & 0xffff) << 8) | - ((video_signal & 0xff0000) >> 16) | - ((video_signal & 0x3f000000)); -/* - * pr_info("video_signal_type_present_flag 0x%x\n", - * (video_signal_from_vui >> 29) & 1); - * pr_info("video_format 0x%x\n", - * (video_signal_from_vui >> 26) & 7); - * pr_info("video_full_range_flag 0x%x\n", - * (video_signal_from_vui >> 25) & 1); - * pr_info("color_description_present_flag 0x%x\n", - * (video_signal_from_vui >> 24) & 1); - * pr_info("color_primaries 0x%x\n", - * (video_signal_from_vui >> 16) & 0xff); - * pr_info("transfer_characteristic 0x%x\n", - * (video_signal_from_vui >> 8) & 0xff); - * pr_info("matrix_coefficient 0x%x\n", - * video_signal_from_vui & 0xff); - */ - - mb_total = (mb_width >> 8) & 0xffff; - max_reference_size = (mb_width >> 24) & 0x7f; - mb_mv_byte = (mb_width & 0x80000000) ? 24 : 96; - if (ucode_type == UCODE_IP_ONLY_PARAM) - mb_mv_byte = 96; - mb_width = mb_width & 0xff; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { - if (!mb_width && mb_total) - mb_width = 256; - } - if (mb_width) - mb_height = mb_total / mb_width; - last_duration = 0; - /* AV_SCRATCH_2 - * bit 15: frame_mbs_only_flag - * bit 13-14: chroma_format_idc - */ - frame_mbs_only_flag = (seq_info >> 15) & 0x01; - chroma_format_idc = (seq_info >> 13) & 0x03; - chroma444 = (chroma_format_idc == 3) ? 1 : 0; - - /* @AV_SCRATCH_6.31-16 = (left << 8 | right ) << 1 - * @AV_SCRATCH_6.15-0 = (top << 8 | bottom ) << - * (2 - frame_mbs_only_flag) - */ - crop_infor = READ_VREG(AV_SCRATCH_6); - crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag); - crop_right = ((crop_infor >> 16) & 0xff) >> (2 - frame_mbs_only_flag); - - /* if width or height from outside is not equal to mb, then use mb */ - /* add: for seeking stream with other resolution */ - if ((last_mb_width && (last_mb_width != mb_width)) - || (mb_width != ((frame_width + 15) >> 4))) - frame_width = 0; - if ((last_mb_height && (last_mb_height != mb_height)) - || (mb_height != ((frame_height + 15) >> 4))) - frame_height = 0; - last_mb_width = mb_width; - last_mb_height = mb_height; - - if ((frame_width == 0) || (frame_height == 0) || crop_infor) { - frame_width = mb_width << 4; - frame_height = mb_height << 4; - if (frame_mbs_only_flag) { - frame_height = - frame_height - (2 >> chroma444) * - min(crop_bottom, - (unsigned int)((8 << chroma444) - 1)); - frame_width = - frame_width - (2 >> chroma444) * min(crop_right, - (unsigned - int)((8 << chroma444) - 1)); - } else { - frame_height = - frame_height - (4 >> chroma444) * - min(crop_bottom, - (unsigned int)((8 << chroma444) - - 1)); - frame_width = - frame_width - (4 >> chroma444) * min(crop_right, - (unsigned - int)((8 << - chroma444) - - 1)); - } -#if 0 - pr_info - ("frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ", - frame_mbs_only_flag, crop_bottom, frame_height); - pr_info - ("mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", - mb_height, crop_right, frame_width, mb_width); -#endif - if (frame_height == 1088) - frame_height = 1080; - } - - mb_width = (mb_width + 3) & 0xfffffffc; - mb_height = (mb_height + 3) & 0xfffffffc; - mb_total = mb_width * mb_height; - - /*max_reference_size <= max_dpb_size <= actual_dpb_size*/ - is_4k = (mb_total > 8160) ? true:false; - - - max_dpb_size = get_max_dpb_size(level_idc, mb_width, mb_height); - if (max_dpb_size < max_reference_size) - max_dpb_size = max_reference_size; - if (max_dpb_size > 15 - && get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB - && (codec_mm_get_total_size() < 80 * SZ_1M)) { - actual_dpb_size - = max_reference_size + dpb_size_adj; - if (actual_dpb_size > VF_BUF_NUM) - actual_dpb_size = VF_BUF_NUM; - } else { - actual_dpb_size = max_dpb_size + dpb_size_adj; - actual_dpb_size = min(actual_dpb_size, VF_BUF_NUM); - } - max_reference_size++; - pr_info("actual_dpb_size %d max_dpb_size %d max_ref %d\n", - actual_dpb_size, max_dpb_size, - max_reference_size); - buf_size = mb_total * mb_mv_byte * max_reference_size; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 1, - buf_size, DRIVER_NAME, &addr); - - if (ret < 0) { - fatal_error_flag = - DECODER_FATAL_ERROR_NO_MEM; - vh264_running = 0; - mutex_unlock(&vh264_mutex); - return; - } - - WRITE_VREG(AV_SCRATCH_1, addr); - WRITE_VREG(AV_SCRATCH_3, post_canvas); - WRITE_VREG(AV_SCRATCH_4, addr + buf_size); - - if (!(READ_VREG(AV_SCRATCH_F) & 0x1)) { - for (i = 0; i < actual_dpb_size; i++) { -#ifdef DOUBLE_WRITE - int page_count = - PAGE_ALIGN((mb_total << 8) + (mb_total - << 7) + (mb_total << 6) + - (mb_total << 5)) / PAGE_SIZE; -#else - int page_count = - PAGE_ALIGN((mb_total << 8) + - (mb_total << 7)) / PAGE_SIZE; -#endif - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, - VF_BUFFER_IDX(i), - page_count << PAGE_SHIFT, - DRIVER_NAME, &buffer_spec[i].phy_addr); - - if (ret < 0) { - buffer_spec[i].alloc_count = 0; - fatal_error_flag = - DECODER_FATAL_ERROR_NO_MEM; - vh264_running = 0; - mutex_unlock(&vh264_mutex); - return; - } - - addr = buffer_spec[i].phy_addr; - buffer_spec[i].alloc_count = page_count; - - if (i <= 21) { - buffer_spec[i].y_addr = addr; - addr += mb_total << 8; - buffer_spec[i].u_addr = addr; - buffer_spec[i].v_addr = addr; - addr += mb_total << 7; - vfbuf_use[i] = 0; - - buffer_spec[i].y_canvas_index = 128 + i * 2; - buffer_spec[i].u_canvas_index = 128 + i * 2 + 1; - buffer_spec[i].v_canvas_index = 128 + i * 2 + 1; - - buffer_spec[i].y_canvas_width = mb_width << 4; - buffer_spec[i].y_canvas_height = mb_height << 4; - buffer_spec[i].u_canvas_width = mb_width << 4; - buffer_spec[i].u_canvas_height = mb_height << 4; - buffer_spec[i].v_canvas_width = mb_width << 4; - buffer_spec[i].v_canvas_height = mb_height << 4; - - endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; - canvas_config_ex(128 + i * 2, - buffer_spec[i].y_addr, - mb_width << 4, mb_height << 4, - CANVAS_ADDR_NOWRAP, - canvas_mode, endian); - canvas_config_ex(128 + i * 2 + 1, - buffer_spec[i].u_addr, - mb_width << 4, mb_height << 3, - CANVAS_ADDR_NOWRAP, - canvas_mode, endian); - WRITE_VREG(ANC0_CANVAS_ADDR + i, - spec2canvas(&buffer_spec[i])); - } else { - buffer_spec[i].y_canvas_index = - 2 * (i - 21) + 4; - buffer_spec[i].y_addr = addr; - addr += mb_total << 8; - buffer_spec[i].u_canvas_index = - 2 * (i - 21) + 5; - buffer_spec[i].v_canvas_index = - 2 * (i - 21) + 5; - buffer_spec[i].u_addr = addr; - addr += mb_total << 7; - vfbuf_use[i] = 0; - - buffer_spec[i].y_canvas_width = mb_width << 4; - buffer_spec[i].y_canvas_height = mb_height << 4; - buffer_spec[i].u_canvas_width = mb_width << 4; - buffer_spec[i].u_canvas_height = mb_height << 4; - buffer_spec[i].v_canvas_width = mb_width << 4; - buffer_spec[i].v_canvas_height = mb_height << 4; - - spec_set_canvas(&buffer_spec[i] - , mb_width << 4, mb_height << 4); - WRITE_VREG(ANC0_CANVAS_ADDR + i - , spec2canvas(&buffer_spec[i])); - } - } - } else { - fatal_error_flag = - DECODER_FATAL_ERROR_NO_MEM; - vh264_running = 0; - mutex_unlock(&vh264_mutex); - pr_err("never be here!!\n"); - return; - } - - timing_info_present_flag = seq_info & 0x2; - fixed_frame_rate_flag = 0; - aspect_ratio_info_present_flag = seq_info & 0x1; - aspect_ratio_idc = (seq_info >> 16) & 0xff; - - if (timing_info_present_flag) { - fixed_frame_rate_flag = seq_info & 0x40; - - if (((num_units_in_tick * 120) >= time_scale - && ((!sync_outside) || (!frame_dur))) && - num_units_in_tick - && time_scale) { - if (use_idr_framerate || !frame_dur - || !duration_from_pts_done || vh264_running) { - u32 frame_dur_es = - div_u64(96000ULL * 2 * - num_units_in_tick, - time_scale); - - /* hack to avoid use ES frame duration - * when it's half of the rate from - * system info - */ - /* sometimes the encoder is given a wrong - * frame rate but the system side information - *is more reliable - */ - if ((frame_dur * 2) != frame_dur_es) { - frame_dur = frame_dur_es; - if (fr_hint_status == VDEC_NEED_HINT) { - schedule_work(¬ify_work); - fr_hint_status = VDEC_HINTED; - } - } - } - } - } else - pr_info("H.264: timing_info not present\n"); - - if (aspect_ratio_info_present_flag) { - if (aspect_ratio_idc == EXTEND_SAR) { - h264_ar = - div_u64(256ULL * (aspect_ratio_info >> 16) * - frame_height, - (aspect_ratio_info & 0xffff) * - frame_width); - } else { - /* pr_info("v264dec: aspect_ratio_idc = %d\n", - * aspect_ratio_idc); - */ - - switch (aspect_ratio_idc) { - case 1: - h264_ar = 0x100 * frame_height / frame_width; - break; - case 2: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 12); - break; - case 3: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 10); - break; - case 4: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 16); - break; - case 5: - h264_ar = 0x100 * frame_height * 33 / - (frame_width * 40); - break; - case 6: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 24); - break; - case 7: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 20); - break; - case 8: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 32); - break; - case 9: - h264_ar = 0x100 * frame_height * 33 / - (frame_width * 80); - break; - case 10: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 18); - break; - case 11: - h264_ar = 0x100 * frame_height * 11 / - (frame_width * 15); - break; - case 12: - h264_ar = 0x100 * frame_height * 33 / - (frame_width * 64); - break; - case 13: - h264_ar = 0x100 * frame_height * 99 / - (frame_width * 160); - break; - case 14: - h264_ar = 0x100 * frame_height * 3 / - (frame_width * 4); - break; - case 15: - h264_ar = 0x100 * frame_height * 2 / - (frame_width * 3); - break; - case 16: - h264_ar = 0x100 * frame_height * 1 / - (frame_width * 2); - break; - default: - if (vh264_ratio >> 16) { - h264_ar = (frame_height * - (vh264_ratio & 0xffff) * - 0x100 + - ((vh264_ratio >> 16) * - frame_width / 2)) / - ((vh264_ratio >> 16) * - frame_width); - } else { - h264_ar = frame_height * 0x100 / - frame_width; - } - break; - } - } - } else { - pr_info("v264dec: aspect_ratio not available from source\n"); - if (vh264_ratio >> 16) { - /* high 16 bit is width, low 16 bit is height */ - h264_ar = - ((vh264_ratio & 0xffff) * frame_height * 0x100 + - (vh264_ratio >> 16) * frame_width / 2) / - ((vh264_ratio >> 16) * frame_width); - } else - h264_ar = frame_height * 0x100 / frame_width; - } - - WRITE_VREG(AV_SCRATCH_0, - (max_reference_size << 24) | (actual_dpb_size << 16) | - (max_dpb_size << 8)); - if (vh264_stream_switching_state != SWITCHING_STATE_OFF) { - vh264_stream_switching_state = SWITCHING_STATE_OFF; - pr_info("Leaving switching mode.\n"); - } - mutex_unlock(&vh264_mutex); -} - -static unsigned int pts_inc_by_duration( - unsigned int *new_pts, unsigned int *new_pts_rem) -{ - unsigned int r, rem; - - r = last_pts + DUR2PTS(frame_dur); - rem = last_pts_remainder + DUR2PTS_REM(frame_dur); - - if (rem >= 96) { - r++; - rem -= 96; - } - - if (new_pts) - *new_pts = r; - if (new_pts_rem) - *new_pts_rem = rem; - - return r; -} -static inline bool vh264_isr_parser(struct vframe_s *vf, - unsigned int pts_valid, unsigned int buffer_index, - unsigned int pts) -{ - unsigned int pts_duration = 0; - - if (h264_first_pts_ready == 0) { - if (pts_valid == 0) { - vfbuf_use[buffer_index]++; - vf->index = buffer_index; - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - return false; - } - - h264pts1 = pts; - h264_pts_count = 0; - h264_first_pts_ready = 1; - } else { - if (pts < h264pts1) { - if (h264_pts_count > 24) { - pr_info("invalid h264pts1, reset\n"); - h264pts1 = pts; - h264_pts_count = 0; - } - } - if (pts_valid && (pts > h264pts1) && (h264_pts_count > 24) - && (duration_from_pts_done == 0)) { - unsigned int - old_duration = frame_dur; - h264pts2 = pts; - - pts_duration = (h264pts2 - h264pts1) * 16 / - (h264_pts_count * 15); - - if ((pts_duration != frame_dur) - && (!pts_outside)) { - if (use_idr_framerate) { - bool pts_c_24 = close_to(pts_duration, - RATE_24_FPS, - RATE_CORRECTION_THRESHOLD); - bool frm_c_25 = close_to(frame_dur, - RATE_25_FPS, - RATE_CORRECTION_THRESHOLD); - bool pts_c_25 = close_to(pts_duration, - RATE_25_FPS, - RATE_CORRECTION_THRESHOLD); - bool frm_c_24 = close_to(frame_dur, - RATE_24_FPS, - RATE_CORRECTION_THRESHOLD); - if ((pts_c_24 && frm_c_25) - || (pts_c_25 && frm_c_24)) { - pr_info - ("H.264:Correct frame dur "); - pr_info - (" from %d to duration based ", - frame_dur); - pr_info - ("on PTS %d ---\n", - pts_duration); - frame_dur = pts_duration; - duration_from_pts_done = 1; - } else if (((frame_dur < 96000 / 240) - && (pts_duration > 96000 / 240)) - || (!duration_on_correcting && - !frm_c_25 && !frm_c_24)) { - /* fft: if the frame rate is - * not regular, use the - * calculate rate insteadof. - */ - pr_info - ("H.264:Correct frame dur "); - pr_info - (" from %d to duration based ", - frame_dur); - pr_info - ("on PTS %d ---\n", - pts_duration); - frame_dur = pts_duration; - duration_on_correcting = 1; - } - } else { - if (close_to(pts_duration, - frame_dur, 2000)) { - frame_dur = pts_duration; - pr_info - ("used calculate frame rate,"); - pr_info("on duration =%d\n", - frame_dur); - } else { - pr_info - ("don't use calculate frame "); - pr_info - ("rate pts_duration =%d\n", - pts_duration); - } - } - } - - if (duration_from_pts_done == 0) { - if (close_to - (pts_duration, - old_duration, - RATE_CORRECTION_THRESHOLD)) { - pr_info - ("finished correct frame dur"); - pr_info - (" new=%d,old_duration=%d,cnt=%d\n", - pts_duration, - old_duration, - h264_pts_count); - duration_from_pts_done = 1; - } else { /*not the same,redo it. */ - if (!close_to(pts_duration, - old_duration, 1000) && - !close_to(pts_duration, - frame_dur, 1000) && - close_to(pts_duration, - last_duration, 200)) { - /* yangle: frame_dur must - * wrong,recover it. - */ - frame_dur = pts_duration; - } - - pr_info - ("restart correct frame duration "); - pr_info - ("new=%d,old_duration=%d,cnt=%d\n", - pts_duration, - old_duration, - h264_pts_count); - h264pts1 = h264pts2; - h264_pts_count = 0; - duration_from_pts_done = 0; - } - } - last_duration = pts_duration; - } - } - return true; -} -#ifdef HANDLE_H264_IRQ -static irqreturn_t vh264_isr(int irq, void *dev_id) -#else -static void vh264_isr(void) -#endif -{ - unsigned int buffer_index; - struct vframe_s *vf; - unsigned int cpu_cmd; - unsigned int pts, pts_lookup_save, pts_valid_save, pts_valid = 0; - unsigned int pts_us64_valid = 0; - unsigned int framesize; - u64 pts_us64; - bool force_interlaced_frame = false; -#ifdef ENABLE_SEI_ITU_T35 - unsigned int sei_itu35_flags; -#endif - static const unsigned int idr_num = - FIX_FRAME_RATE_CHECK_IDRFRAME_NUM; - static const unsigned int flg_1080_itl = - DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE; - static const unsigned int flg_576_itl = - DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE; - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - if (0 == (stat & STAT_VDEC_RUN)) { - pr_info("decoder is not running\n"); -#ifdef HANDLE_H264_IRQ - return IRQ_HANDLED; -#else - return; -#endif - } - - cpu_cmd = READ_VREG(AV_SCRATCH_0); - -#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS - if ((frame_dur < 2004) && - (frame_width >= 1400) && - (frame_height >= 1000) && (last_interlaced == 0)) - SET_VREG_MASK(AV_SCRATCH_F, 0x8); -#endif - if ((decoder_force_reset == 1) - || ((error_recovery_mode != 1) - && (no_idr_error_count >= no_idr_error_max) - && (ucode_type != UCODE_IP_ONLY_PARAM))) { - vh264_running = 0; - pr_info("force reset decoder %d!!!\n", no_idr_error_count); - schedule_work(&error_wd_work); - decoder_force_reset = 0; - no_idr_error_count = 0; - } else if ((cpu_cmd & 0xff) == 1) { - if (unlikely - (vh264_running - && (kfifo_len(&newframe_q) != VF_POOL_SIZE))) { - /* a cmd 1 sent during decoding w/o getting a cmd 3. */ - /* should not happen but the original code has such - * case, do the same process - */ - if ((READ_VREG(AV_SCRATCH_1) & 0xff) - == 1) {/*invalid mb_width*/ - vh264_running = 0; - fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN; - /* this is fatal error, need restart */ - pr_info("cmd 1 fatal error happened\n"); - schedule_work(&error_wd_work); - } else { - vh264_stream_switching_state = SWITCHING_STATE_ON_CMD1; - pr_info("Enter switching mode cmd1.\n"); - schedule_work(&stream_switching_work); - } - return IRQ_HANDLED; - } - pr_info("Enter set parameter cmd1.\n"); - schedule_work(&set_parameter_work); - return IRQ_HANDLED; - } else if ((cpu_cmd & 0xff) == 2) { - int frame_mb_only, pic_struct_present, pic_struct, prog_frame, - poc_sel, idr_flag, eos, error; - int i, status, num_frame, b_offset; - int current_error_count, slice_type; - - vh264_running = 1; - vh264_no_disp_count = 0; - num_frame = (cpu_cmd >> 8) & 0xff; - frame_mb_only = seq_info & 0x8000; - pic_struct_present = seq_info & 0x10; - - current_error_count = READ_VREG(AV_SCRATCH_D); - if (vh264_error_count != current_error_count) { - /* pr_info("decoder error happened, count %d\n", - * current_error_count); - */ - vh264_error_count = current_error_count; - } - - for (i = 0; (i < num_frame) && (!vh264_eos); i++) { - status = READ_VREG(AV_SCRATCH_1 + i); - buffer_index = status & 0x1f; - error = status & 0x200; - slice_type = (READ_VREG(AV_SCRATCH_H) >> (i * 4)) & 0xf; - - if ((error_recovery_mode_use & 2) && error) - check_pts_discontinue = true; - if (ucode_type == UCODE_IP_ONLY_PARAM - && iponly_early_mode) - continue; - if ((p_last_vf != NULL) - && (p_last_vf->index == buffer_index)) - continue; - - if (buffer_index >= VF_BUF_NUM) - continue; - - pic_struct = (status >> 5) & 0x7; - prog_frame = status & 0x100; - poc_sel = status & 0x200; - idr_flag = status & 0x400; - frame_packing_type = (status >> 12) & 0x7; - eos = (status >> 15) & 1; - - if (eos) - vh264_eos = 1; - - b_offset = (status >> 16) & 0xffff; - - if (error) - no_idr_error_count++; - if (idr_flag || - (!error && (slice_type != SLICE_TYPE_I))) - no_idr_error_count = 0; - - if (decoder_debug_flag) { - pr_info - ("slice_type %x idr %x error %x count %d", - slice_type, idr_flag, error, - no_idr_error_count); - pr_info(" prog %x pic_struct %x offset %x\n", - prog_frame, pic_struct, b_offset); - } -#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS - last_interlaced = prog_frame ? 0 : 1; -#endif - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - if (clk_adj_frame_count < (VDEC_CLOCK_ADJUST_FRAME + 1)) - clk_adj_frame_count++; - - set_frame_info(vf); - - switch (i) { - case 0: - b_offset |= - (READ_VREG(AV_SCRATCH_A) & 0xffff) - << 16; - break; - case 1: - b_offset |= - READ_VREG(AV_SCRATCH_A) & 0xffff0000; - break; - case 2: - b_offset |= - (READ_VREG(AV_SCRATCH_B) & 0xffff) - << 16; - break; - case 3: - b_offset |= - READ_VREG(AV_SCRATCH_B) & 0xffff0000; - break; - case 4: - b_offset |= - (READ_VREG(AV_SCRATCH_C) & 0xffff) - << 16; - break; - case 5: - b_offset |= - READ_VREG(AV_SCRATCH_C) & 0xffff0000; - break; - default: - break; - } - - if (error) - gvs->drop_frame_count++; - - /* add 64bit pts us ; */ - if (unlikely - ((b_offset == first_offset) - && (first_pts_cached))) { - pts = first_pts; - pts_us64 = first_pts64; - framesize = first_frame_size; - first_pts_cached = false; - pts_valid = 1; - pts_us64_valid = 1; -#ifdef DEBUG_PTS - pts_hit++; -#endif - } else if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, b_offset, &pts, - &framesize, 0, &pts_us64) == 0) { - pts_valid = 1; - pts_us64_valid = 1; -#ifdef DEBUG_PTS - pts_hit++; -#endif - } else { - pts_valid = 0; - pts_us64_valid = 0; - framesize = 0; -#ifdef DEBUG_PTS - pts_missed++; -#endif - } - - if (idr_flag) - s_vframe_qos.type = 4; - else if (slice_type == SLICE_TYPE_I) - s_vframe_qos.type = 1; - else if (slice_type == SLICE_TYPE_P) - s_vframe_qos.type = 2; - else if (slice_type == SLICE_TYPE_B || slice_type == 8) - s_vframe_qos.type = 3; - - s_vframe_qos.size = framesize; - - if (pts_valid) - s_vframe_qos.pts = pts; - else - s_vframe_qos.pts = last_pts + DUR2PTS(frame_dur); -#ifndef ENABLE_SEI_ITU_T35 - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { - u32 reg_data; - if (i) { - reg_data = READ_VREG(AV_SCRATCH_N); - s_vframe_qos.max_mv - = (reg_data >> 16) & 0xffff; - s_vframe_qos.avg_mv - = (reg_data >> 8) & 0xff; - s_vframe_qos.min_mv - = reg_data & 0xff; - reg_data = READ_VREG(AV_SCRATCH_L); - s_vframe_qos.max_qp - = (reg_data >> 16) & 0xff; - s_vframe_qos.avg_qp - = (reg_data >> 8) & 0xff; - s_vframe_qos.min_qp - = reg_data & 0xff; - reg_data = READ_VREG(AV_SCRATCH_M); - s_vframe_qos.max_skip - = (reg_data >> 16) & 0xff; - s_vframe_qos.avg_skip - = (reg_data >> 8) & 0xff; - s_vframe_qos.min_skip - = reg_data & 0xff; - } else { - reg_data = READ_VREG(AV_SCRATCH_J); - s_vframe_qos.max_mv - = (reg_data >> 16) & 0xffff; - s_vframe_qos.avg_mv - = (reg_data >> 8) & 0xff; - s_vframe_qos.min_mv - = reg_data & 0xff; - reg_data = READ_VREG(AV_SCRATCH_I); - s_vframe_qos.max_qp - = (reg_data >> 16) & 0xff; - s_vframe_qos.avg_qp - = (reg_data >> 8) & 0xff; - s_vframe_qos.min_qp - = reg_data & 0xff; - reg_data = READ_VREG(AV_SCRATCH_K); - s_vframe_qos.max_skip - = (reg_data >> 16) & 0xff; - s_vframe_qos.avg_skip - = (reg_data >> 8) & 0xff; - s_vframe_qos.min_skip - = reg_data & 0xff; - } - if (decoder_debug_flag&0x2) { - pr_info("max_mv %d avg_mv %d min_mv %d slice_type %d offset %x i = %d\n", - s_vframe_qos.max_mv, - s_vframe_qos.avg_mv, - s_vframe_qos.min_mv, - slice_type, - b_offset, - i); - pr_info("max_qp %d avg_qp %d min_qp %d\n", - s_vframe_qos.max_qp, - s_vframe_qos.avg_qp, - s_vframe_qos.min_qp); - pr_info("max_skip %d avg_skip %d min_skip %d\n", - s_vframe_qos.max_skip, - s_vframe_qos.avg_skip, - s_vframe_qos.min_skip); - } - } else - search_qos_node(&s_vframe_qos, b_offset); -#endif - frame_count++; - - s_vframe_qos.num = frame_count; - vdec_fill_frame_info(&s_vframe_qos, 1); - - /* on second IDR frame,check the diff between pts - * compute from duration and pts from lookup , - * if large than frame_dur,we think it is uncorrect. - */ - pts_lookup_save = pts; - pts_valid_save = pts_valid; - if (fixed_frame_rate_flag - && (fixed_frame_rate_check_count <= - idr_num)) { - if (idr_flag && pts_valid) { - fixed_frame_rate_check_count++; - /* pr_info("diff:%d\n", - * last_pts - pts_lookup_save); - */ - if ((fixed_frame_rate_check_count == - idr_num) && - (abs(pts - (last_pts + - DUR2PTS(frame_dur))) > - DUR2PTS(frame_dur))) { - fixed_frame_rate_flag = 0; - pr_info("pts sync mode play\n"); - } - - if (fixed_frame_rate_flag - && (fixed_frame_rate_check_count - > idr_num)) { - pr_info - ("fix_frame_rate mode play\n"); - } - } - } - - if (READ_VREG(AV_SCRATCH_F) & 2) { - /* for I only mode, ignore the PTS information - * and only uses frame duration for each I - * frame decoded - */ - if (p_last_vf) - pts_valid = 0; - /* also skip frame duration calculation - * based on PTS - */ - duration_from_pts_done = 1; - /* and add a default duration for 1/30 second - * if there is no valid frame - * duration available - */ - if (frame_dur == 0) - frame_dur = 96000 / 30; - } - - if (sync_outside == 0) { - if (!vh264_isr_parser(vf, - pts_valid, buffer_index, pts)) - continue; - - h264_pts_count++; - } else { - if (!idr_flag) - pts_valid = 0; - } - - if (pts_valid && !pts_discontinue) { - pts_discontinue = - (abs(last_pts - pts) >= - tsync_vpts_discontinuity_margin()); - } - /* if use_idr_framerate or fixed frame rate, only - * use PTS for IDR frames except for pts discontinue - */ - if (timing_info_present_flag && - frame_dur && - (use_idr_framerate || - (fixed_frame_rate_flag != 0)) - && pts_valid && h264_first_valid_pts_ready - && (!pts_discontinue)) { - pts_valid = - (slice_type == SLICE_TYPE_I) ? 1 : 0; - } - - if (!h264_first_valid_pts_ready && pts_valid) { - h264_first_valid_pts_ready = true; - last_pts = pts - DUR2PTS(frame_dur); - last_pts_remainder = 0; - } - /* calculate PTS of next frame and smooth - * PTS for fixed rate source - */ - if (pts_valid) { - if ((fixed_frame_rate_flag) && - (!pts_discontinue) && - (abs(pts_inc_by_duration(NULL, NULL) - - pts) - < DUR2PTS(frame_dur))) { - pts = pts_inc_by_duration(&pts, - &last_pts_remainder); - } else - last_pts_remainder = 0; - - } else { - if (fixed_frame_rate_flag && !pts_discontinue && - (fixed_frame_rate_check_count > idr_num) && - pts_valid_save && (sync_outside == 0) && - (abs(pts_inc_by_duration(NULL, NULL) - pts) - > DUR2PTS(frame_dur))) { - duration_from_pts_done = 0; - pr_info("recalc frame_dur\n"); - } else - pts = pts_inc_by_duration(&pts, - &last_pts_remainder); - pts_valid = 1; - } - - if ((dec_control & - flg_1080_itl) - && (frame_width == 1920) - && (frame_height >= 1080) - && (vf->duration == 3203)) - force_interlaced_frame = true; - else if ((dec_control & - flg_576_itl) - && (frame_width == 720) - && (frame_height == 576) - && (vf->duration == 3840)) - force_interlaced_frame = true; - - /* for frames with PTS, check if there is PTS - * discontinue based on previous frames - * (including error frames), - * force no VPTS discontinue reporting if we saw - *errors earlier but only once. - */ - - /*count info*/ - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, error, b_offset); - - if ((pts_valid) && (check_pts_discontinue) - && (!error)) { - if (pts_discontinue) { - vf->flag = 0; - check_pts_discontinue = false; - } else if ((pts - last_pts) < 90000) { - vf->flag = VFRAME_FLAG_NO_DISCONTINUE; - check_pts_discontinue = false; - } - } - - last_pts = pts; - - if (fixed_frame_rate_flag - && (fixed_frame_rate_check_count <= - idr_num) - && (sync_outside == 0) - && pts_valid_save) - pts = pts_lookup_save; - - if (pic_struct_present) { - if ((pic_struct == PIC_TOP_BOT) - || (pic_struct == PIC_BOT_TOP)) - prog_frame = 0; - } - - if ((!force_interlaced_frame) - && (prog_frame - || (pic_struct_present - && pic_struct - <= PIC_TRIPLE_FRAME))) { - if (pic_struct_present) { - if (pic_struct == PIC_TOP_BOT_TOP - || pic_struct - == PIC_BOT_TOP_BOT) { - vf->duration += - vf->duration >> 1; - } else if (pic_struct == - PIC_DOUBLE_FRAME) - vf->duration += vf->duration; - else if (pic_struct == - PIC_TRIPLE_FRAME) { - vf->duration += - vf->duration << 1; - } - } - - last_pts = - last_pts + DUR2PTS(vf->duration - - frame_dur); - - vf->index = buffer_index; - vf->type = - VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; - vf->duration_pulldown = 0; - vf->signal_type = video_signal_from_vui; - vf->index = buffer_index; - vf->pts = (pts_valid) ? pts : 0; - if (pts_us64_valid == 1) - vf->pts_us64 = pts_us64; - else - vf->pts_us64 = div64_u64(((u64)vf->pts)*100, 9); - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&buffer_spec[buffer_index]); - vf->type_original = vf->type; - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(buffer_index)); - decoder_do_frame_check(NULL, vf); - if ((error_recovery_mode_use & 2) && error) { - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - } else { - p_last_vf = vf; - pts_discontinue = false; - kfifo_put(&delay_display_q, - (const struct vframe_s *)vf); - } - } else { - if (pic_struct_present - && pic_struct == PIC_TOP_BOT) - vf->type = VIDTYPE_INTERLACE_TOP; - else if (pic_struct_present - && pic_struct == PIC_BOT_TOP) - vf->type = VIDTYPE_INTERLACE_BOTTOM; - else { - vf->type = - poc_sel ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP; - } - vf->type |= VIDTYPE_VIU_NV21; - vf->type |= VIDTYPE_INTERLACE_FIRST; - - high_bandwidth |= - ((codec_mm_get_total_size() < 80 * SZ_1M) - & ((READ_VREG(AV_SCRATCH_N) & 0xf) == 3) - & ((frame_width * frame_height) >= 1920*1080)); - if (high_bandwidth) - vf->flag |= VFRAME_FLAG_HIGH_BANDWIDTH; - - vf->duration >>= 1; - vf->duration_pulldown = 0; - vf->signal_type = video_signal_from_vui; - vf->index = buffer_index; - vf->pts = (pts_valid) ? pts : 0; - if (pts_us64_valid == 1) - vf->pts_us64 = pts_us64; - else - vf->pts_us64 = div64_u64(((u64)vf->pts)*100, 9); - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&buffer_spec[buffer_index]); - vf->type_original = vf->type; - vfbuf_use[buffer_index]++; - vf->ready_jiffies64 = jiffies_64; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(buffer_index)); - decoder_do_frame_check(NULL, vf); - if ((error_recovery_mode_use & 2) && error) { - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - continue; - } else { - pts_discontinue = false; - kfifo_put(&delay_display_q, - (const struct vframe_s *)vf); - } - - if (READ_VREG(AV_SCRATCH_F) & 2) - continue; - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no avail buffer slot."); - return IRQ_HANDLED; - } - - set_frame_info(vf); - - if (pic_struct_present - && pic_struct == PIC_TOP_BOT) - vf->type = VIDTYPE_INTERLACE_BOTTOM; - else if (pic_struct_present - && pic_struct == PIC_BOT_TOP) - vf->type = VIDTYPE_INTERLACE_TOP; - else { - vf->type = - poc_sel ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; - } - - vf->type |= VIDTYPE_VIU_NV21; - vf->duration >>= 1; - vf->duration_pulldown = 0; - vf->signal_type = video_signal_from_vui; - vf->index = buffer_index; - vf->pts = 0; - vf->pts_us64 = 0; - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&buffer_spec[buffer_index]); - vf->type_original = vf->type; - vfbuf_use[buffer_index]++; - if (high_bandwidth) - vf->flag |= VFRAME_FLAG_HIGH_BANDWIDTH; - - p_last_vf = vf; - vf->ready_jiffies64 = jiffies_64; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(buffer_index)); - kfifo_put(&delay_display_q, - (const struct vframe_s *)vf); - } - } - - WRITE_VREG(AV_SCRATCH_0, 0); - } else if ((cpu_cmd & 0xff) == 3) { - vh264_running = 1; - vh264_stream_switching_state = SWITCHING_STATE_ON_CMD3; - - pr_info("Enter switching mode cmd3.\n"); - schedule_work(&stream_switching_work); - - } else if ((cpu_cmd & 0xff) == 4) { - vh264_running = 1; - /* reserved for slice group */ - WRITE_VREG(AV_SCRATCH_0, 0); - } else if ((cpu_cmd & 0xff) == 5) { - vh264_running = 1; - /* reserved for slice group */ - WRITE_VREG(AV_SCRATCH_0, 0); - } else if ((cpu_cmd & 0xff) == 6) { - vh264_running = 0; - fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN; - /* this is fatal error, need restart */ - pr_info("fatal error happend\n"); - amvdec_stop(); - if (!fatal_error_reset) - schedule_work(&error_wd_work); - } else if ((cpu_cmd & 0xff) == 7) { - vh264_running = 0; - frame_width = (READ_VREG(AV_SCRATCH_1) + 1) * 16; - pr_info("Over decoder supported size, width = %d\n", - frame_width); - fatal_error_flag = DECODER_FATAL_ERROR_SIZE_OVERFLOW; - } else if ((cpu_cmd & 0xff) == 8) { - vh264_running = 0; - frame_height = (READ_VREG(AV_SCRATCH_1) + 1) * 16; - pr_info("Over decoder supported size, height = %d\n", - frame_height); - fatal_error_flag = DECODER_FATAL_ERROR_SIZE_OVERFLOW; - } else if ((cpu_cmd & 0xff) == 9) { - first_offset = READ_VREG(AV_SCRATCH_1); - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, first_offset, &first_pts, - &first_frame_size, 0, - &first_pts64) == 0) - first_pts_cached = true; - WRITE_VREG(AV_SCRATCH_0, 0); - } else if ((cpu_cmd & 0xff) == 0xa) { - int b_offset; - unsigned int frame_size; - - b_offset = READ_VREG(AV_SCRATCH_2); - buffer_index = READ_VREG(AV_SCRATCH_1); - /*pr_info("iponly output %d b_offset %x\n", - * buffer_index,b_offset); - */ - if (kfifo_get(&newframe_q, &vf) == 0) { - WRITE_VREG(AV_SCRATCH_0, 0); - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, b_offset, - &pts, &frame_size, - 0, &pts_us64) != 0) - vf->pts_us64 = vf->pts = 0; - else { - vf->pts_us64 = pts_us64; - vf->pts = pts; - } - set_frame_info(vf); - vf->type = VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; - vf->duration_pulldown = 0; - vf->signal_type = video_signal_from_vui; - vf->index = buffer_index; - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&buffer_spec[buffer_index]); - vf->type_original = vf->type; - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(buffer_index)); - vfbuf_use[buffer_index]++; - p_last_vf = vf; - pts_discontinue = false; - iponly_early_mode = 1; - decoder_do_frame_check(NULL, vf); - kfifo_put(&delay_display_q, - (const struct vframe_s *)vf); - WRITE_VREG(AV_SCRATCH_0, 0); - } else if ((cpu_cmd & 0xff) == 0xB) { - schedule_work(&qos_work); - } -#ifdef ENABLE_SEI_ITU_T35 - sei_itu35_flags = READ_VREG(AV_SCRATCH_J); - if (sei_itu35_flags & (1 << 15)) { /* data ready */ - schedule_work(&userdata_push_work); - } -#endif -#ifdef HANDLE_H264_IRQ - return IRQ_HANDLED; -#else - return; -#endif -} - -static void vh264_set_clk(struct work_struct *work) -{ - int fps = 96000 / frame_dur; - - if (frame_dur < 10) /*dur is too small ,think it errors fps*/ - fps = 60; - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_H264, - frame_width, frame_height, fps); -} - -static void vh264_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - unsigned int wait_buffer_status; - unsigned int wait_i_pass_frames; - unsigned int reg_val; - - enum receviver_start_e state = RECEIVER_INACTIVE; - - if (vh264_reset) { - pr_info("operation forbidden in timer !\n"); - goto exit; - } - - prepare_display_q(); - - if (vf_get_receiver(PROVIDER_NAME)) { - state = - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) { - /* receiver has no event_cb or receiver's - * event_cb does not process this event - */ - state = RECEIVER_INACTIVE; - } - } else - state = RECEIVER_INACTIVE; -#ifndef HANDLE_H264_IRQ - vh264_isr(); -#endif - - if (vh264_stream_switching_state != SWITCHING_STATE_OFF) - wait_buffer_counter = 0; - else { - reg_val = READ_VREG(AV_SCRATCH_9); - wait_buffer_status = reg_val & (1 << 31); - wait_i_pass_frames = reg_val & 0xff; - if (wait_buffer_status) { - if (kfifo_is_empty(&display_q) && - kfifo_is_empty(&delay_display_q) && - kfifo_is_empty(&recycle_q) && - (state == RECEIVER_INACTIVE)) { - pr_info("$$$$decoder is waiting for buffer\n"); - if (++wait_buffer_counter > 4) { - amvdec_stop(); - schedule_work(&error_wd_work); - } - } else - wait_buffer_counter = 0; - } else if (wait_i_pass_frames > 1000) { - pr_info("i passed frames > 1000\n"); - amvdec_stop(); - schedule_work(&error_wd_work); - } - } - -#if 0 - if (!wait_buffer_status) { - if (vh264_no_disp_count++ > NO_DISP_WD_COUNT) { - pr_info("$$$decoder did not send frame out\n"); - amvdec_stop(); -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vh264_ppmgr_reset(); -#else - vf_light_unreg_provider(PROVIDER_NAME); - vh264_local_init(); - vf_reg_provider(vh264_vf_prov); -#endif - vh264_prot_init(); - amvdec_start(); - - vh264_no_disp_count = 0; - vh264_no_disp_wd_count++; - } - } -#endif - - while (!kfifo_is_empty(&recycle_q) && - ((READ_VREG(AV_SCRATCH_7) == 0) - || (READ_VREG(AV_SCRATCH_8) == 0)) - && (vh264_stream_switching_state == SWITCHING_STATE_OFF)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if (vf->index < VF_BUF_NUM) { - if (--vfbuf_use[vf->index] == 0) { - if (READ_VREG(AV_SCRATCH_7) == 0) { - WRITE_VREG(AV_SCRATCH_7, - vf->index + 1); - } else { - WRITE_VREG(AV_SCRATCH_8, - vf->index + 1); - } - } - - vf->index = VF_BUF_NUM; - kfifo_put(&newframe_q, - (const struct vframe_s *)vf); - } - } - } - - if (vh264_stream_switching_state != SWITCHING_STATE_OFF) { - while (!kfifo_is_empty(&recycle_q)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if (vf->index < VF_BUF_NUM) { - vf->index = VF_BUF_NUM; - kfifo_put(&newframe_q, - (const struct vframe_s *)vf); - } - } - } - - WRITE_VREG(AV_SCRATCH_7, 0); - WRITE_VREG(AV_SCRATCH_8, 0); - - if (kfifo_len(&newframe_q) == VF_POOL_SIZE) - stream_switching_done(); - } - - if (ucode_type != UCODE_IP_ONLY_PARAM && - (clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) && - frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) - schedule_work(&set_clk_work); - -exit: - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vh264_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - u32 ratio_control; - u32 ar; - - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (frame_dur != 0) - vstatus->frame_rate = 96000 / frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(AV_SCRATCH_D); - vstatus->status = stat; - if (fatal_error_reset) - vstatus->status |= fatal_error_flag; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - ar = min_t(u32, - h264_ar, - DISP_RATIO_ASPECT_RATIO_MAX); - ratio_control = - ar << DISP_RATIO_ASPECT_RATIO_BIT; - vstatus->ratio_control = ratio_control; - - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -static int vh264_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -int vh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) -{ - if (trickmode == TRICKMODE_I) { - WRITE_VREG(AV_SCRATCH_F, - (READ_VREG(AV_SCRATCH_F) & 0xfffffffc) | 2); - trickmode_i = 1; - } else if (trickmode == TRICKMODE_NONE) { - WRITE_VREG(AV_SCRATCH_F, READ_VREG(AV_SCRATCH_F) & 0xfffffffc); - trickmode_i = 0; - } - - return 0; -} - -int vh264_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -static void vh264_prot_init(void) -{ - - while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) - ; - while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) - ; /* reg address is 0x350 */ - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - -#else - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - READ_RESET_REG(RESET0_REGISTER); - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - - WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); -#endif - - WRITE_VREG(POWER_CTL_VLD, - READ_VREG(POWER_CTL_VLD) | - (0 << 10) | (1 << 9) | (1 << 6)); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - WRITE_VREG(AV_SCRATCH_0, 0); - WRITE_VREG(AV_SCRATCH_1, buf_offset); - if (!tee_enabled()) - WRITE_VREG(AV_SCRATCH_G, mc_dma_handle); - WRITE_VREG(AV_SCRATCH_7, 0); - WRITE_VREG(AV_SCRATCH_8, 0); - WRITE_VREG(AV_SCRATCH_9, 0); - WRITE_VREG(AV_SCRATCH_N, 0); - -#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY - if (bad_block_scale > 128) - bad_block_scale = 128; - WRITE_VREG(AV_SCRATCH_A, bad_block_scale); -#endif - - error_recovery_mode_use = - (error_recovery_mode != - 0) ? error_recovery_mode : error_recovery_mode_in; - WRITE_VREG(AV_SCRATCH_F, - (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) | - (READ_VREG(AV_SCRATCH_F) & 0xffffff43) | - ((error_recovery_mode_use & 0x1) << 4)); - if (dec_control & DEC_CONTROL_FLAG_DISABLE_FAST_POC) - SET_VREG_MASK(AV_SCRATCH_F, 1 << 7); - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); - if (ucode_type == UCODE_IP_ONLY_PARAM) - SET_VREG_MASK(AV_SCRATCH_F, 1 << 6); - else - CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6); - - WRITE_VREG(AV_SCRATCH_I, (u32)(sei_data_buffer_phys - buf_offset)); - WRITE_VREG(AV_SCRATCH_J, 0); - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { - /* pr_info("vh264 meson8 prot init\n"); */ - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); - } - /* #endif */ -} - -static int vh264_local_init(void) -{ - int i, ret; - u32 size; - unsigned long buf_start; - vh264_ratio = vh264_amstream_dec_info.ratio; - /* vh264_ratio = 0x100; */ - - vh264_rotation = (((unsigned long) vh264_amstream_dec_info.param) - >> 16) & 0xffff; - - frame_prog = 0; - frame_width = vh264_amstream_dec_info.width; - frame_height = vh264_amstream_dec_info.height; - frame_dur = vh264_amstream_dec_info.rate; - pts_outside = ((unsigned long) vh264_amstream_dec_info.param) & 0x01; - sync_outside = ((unsigned long) vh264_amstream_dec_info.param & 0x02) - >> 1; - use_idr_framerate = ((unsigned long) vh264_amstream_dec_info.param - & 0x04) >> 2; - max_refer_buf = !(((unsigned long) vh264_amstream_dec_info.param - & 0x10) >> 4); - if (!vh264_reset) { - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BLK_BUFFERS, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER | - tvp_flag); - } - pr_info - ("H264 sysinfo: %dx%d duration=%d, pts_outside=%d \n", - frame_width, frame_height, frame_dur, pts_outside); - pr_debug("sync_outside=%d, use_idr_framerate=%d\n", - sync_outside, use_idr_framerate); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) - size = V_BUF_ADDR_OFFSET_NEW; - else - size = V_BUF_ADDR_OFFSET; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 0, - size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; - - buf_offset = buf_start - DEF_BUF_START_ADDR; - - if ((unsigned long) vh264_amstream_dec_info.param & 0x08) - ucode_type = UCODE_IP_ONLY_PARAM; - else - ucode_type = 0; - - if ((unsigned long) vh264_amstream_dec_info.param & 0x20) - error_recovery_mode_in = 1; - else - error_recovery_mode_in = 3; - - if (!vh264_running) { - last_mb_width = 0; - last_mb_height = 0; - } - - for (i = 0; i < VF_BUF_NUM; i++) - vfbuf_use[i] = 0; - - INIT_KFIFO(display_q); - INIT_KFIFO(delay_display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &vfpool[i]; - - vfpool[i].index = VF_BUF_NUM; - vfpool[i].bufWidth = 1920; - kfifo_put(&newframe_q, vf); - } - -#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS - last_interlaced = 1; -#endif - h264_first_pts_ready = 0; - h264_first_valid_pts_ready = false; - h264pts1 = 0; - h264pts2 = 0; - h264_pts_count = 0; - duration_from_pts_done = 0; - vh264_error_count = READ_VREG(AV_SCRATCH_D); - - p_last_vf = NULL; - check_pts_discontinue = false; - last_pts = 0; - wait_buffer_counter = 0; - vh264_no_disp_count = 0; - fatal_error_flag = 0; - high_bandwidth = 0; - vh264_stream_switching_state = SWITCHING_STATE_OFF; -#ifdef DEBUG_PTS - pts_missed = 0; - pts_hit = 0; -#endif - pts_discontinue = false; - no_idr_error_count = 0; - - vh264_reset_userdata_fifo(vdec_h264, 1); - h264_reset_qos_mgr(); - - if (enable_switch_fense) { - for (i = 0; i < ARRAY_SIZE(fense_buffer_spec); i++) { - struct buffer_spec_s *s = &fense_buffer_spec[i]; - s->alloc_count = 3 * SZ_1M / PAGE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, - FENSE_BUFFER_IDX(i), - 3 * SZ_1M, DRIVER_NAME, &s->phy_addr); - - if (ret < 0) { - fatal_error_flag = - DECODER_FATAL_ERROR_NO_MEM; - vh264_running = 0; - return ret; - } - s->y_canvas_index = 2 * i; - s->u_canvas_index = 2 * i + 1; - s->v_canvas_index = 2 * i + 1; - } - } - return 0; -} - -static s32 vh264_init(void) -{ - int ret = 0; - int trickmode_fffb = 0; - int firmwareloaded = 0; - - /* pr_info("\nvh264_init\n"); */ - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - vh264_running = 0;/* init here to reset last_mb_width&last_mb_height */ - vh264_eos = 0; - duration_on_correcting = 0; - first_pts = 0; - first_pts64 = 0; - first_offset = 0; - first_pts_cached = false; - fixed_frame_rate_check_count = 0; - fr_hint_status = VDEC_NO_NEED_HINT; - saved_resolution = 0; - iponly_early_mode = 0; - saved_idc_level = 0; - - frame_count = 0; - memset(&s_vframe_qos, 0, sizeof(s_vframe_qos)); - /*init vdec status*/ - ret = vh264_vdec_info_init(); - if (0 != ret) - return -ret; - - ret = vh264_local_init(); - if (ret < 0) - return ret; - query_video_status(0, &trickmode_fffb); - - amvdec_enable(); - if (!firmwareloaded && tee_enabled()) { - ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, NULL); - if (ret < 0) { - amvdec_disable(); - pr_err("H264: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return ret; - } - } else { - /* -- ucode loading (amrisc and swap code) */ - mc_cpu_addr = - dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, - &mc_dma_handle, GFP_KERNEL); - if (!mc_cpu_addr) { - amvdec_disable(); - del_timer_sync(&recycle_timer); - pr_err("vh264_init: Can not allocate mc memory.\n"); - return -ENOMEM; - } - - pr_debug("264 ucode swap area: phyaddr %p, cpu vaddr %p\n", - (void *)mc_dma_handle, mc_cpu_addr); - if (debugfirmware) { - int r0, r1, r2, r3, r4, r5; - char firmwarename[32]; - - pr_debug("start load debug %d firmware ...\n", debugfirmware); - - snprintf(firmwarename, 32, "%s%d", "vh264_mc", debugfirmware); - r0 = amvdec_loadmc_ex(VFORMAT_H264, firmwarename, NULL); - -#define DEBUGGET_FW(t, name, buf, size, ret)\ - do {\ - snprintf(firmwarename, 32, "%s%d", name,\ - debugfirmware);\ - ret = get_decoder_firmware_data(t,\ - firmwarename, buf, size);\ - } while (0) - /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_HEADER, vh264_header_mc, - *MC_SWAP_SIZE); - */ - DEBUGGET_FW(VFORMAT_H264, "vh264_header_mc", - (u8 *) mc_cpu_addr + MC_OFFSET_HEADER, - MC_SWAP_SIZE, r1); - - /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_DATA, vh264_data_mc, - *MC_SWAP_SIZE); - */ - DEBUGGET_FW(VFORMAT_H264, "vh264_data_mc", - (u8 *) mc_cpu_addr + MC_OFFSET_DATA, MC_SWAP_SIZE, r2); - /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_MMCO, vh264_mmco_mc, - *MC_SWAP_SIZE); - */ - DEBUGGET_FW(VFORMAT_H264, "vh264_mmco_mc", - (u8 *) mc_cpu_addr + MC_OFFSET_MMCO, MC_SWAP_SIZE, r3); - /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_LIST, vh264_list_mc, - *MC_SWAP_SIZE); - */ - DEBUGGET_FW(VFORMAT_H264, "vh264_list_mc", - (u8 *) mc_cpu_addr + MC_OFFSET_LIST, MC_SWAP_SIZE, r4); - /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_SLICE, vh264_slice_mc, - *MC_SWAP_SIZE); - */ - DEBUGGET_FW(VFORMAT_H264, "vh264_slice_mc", - (u8 *) mc_cpu_addr + MC_OFFSET_SLICE, MC_SWAP_SIZE, r5); - - if (r0 < 0 || r1 < 0 || r2 < 0 || r3 < 0 || r4 < 0 || r5 < 0) { - pr_err("264 load debugfirmware err %d,%d,%d,%d,%d,%d\n", - r0, r1, r2, r3, r4, r5); - amvdec_disable(); - if (mc_cpu_addr) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, - mc_dma_handle); - mc_cpu_addr = NULL; - } - return -EBUSY; - } - firmwareloaded = 1; - } else { - int ret = -1; - char *buf = vmalloc(0x1000 * 16); - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - if (get_firmware_data(VIDEO_DEC_H264, buf) < 0) { - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf); - memcpy((u8 *) mc_cpu_addr + MC_OFFSET_HEADER, - buf + 0x4000, MC_SWAP_SIZE); - memcpy((u8 *) mc_cpu_addr + MC_OFFSET_DATA, - buf + 0x2000, MC_SWAP_SIZE); - memcpy((u8 *) mc_cpu_addr + MC_OFFSET_MMCO, - buf + 0x6000, MC_SWAP_SIZE); - memcpy((u8 *) mc_cpu_addr + MC_OFFSET_LIST, - buf + 0x3000, MC_SWAP_SIZE); - memcpy((u8 *) mc_cpu_addr + MC_OFFSET_SLICE, - buf + 0x5000, MC_SWAP_SIZE); - - vfree(buf); - - if (ret < 0) { - amvdec_disable(); - if (mc_cpu_addr) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, - mc_dma_handle); - mc_cpu_addr = NULL; - } - pr_err("H264: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - } - } - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - vh264_prot_init(); - -#ifdef HANDLE_H264_IRQ - /*TODO irq */ - - if (vdec_request_irq(VDEC_IRQ_1, vh264_isr, - "vh264-irq", (void *)vh264_dec_id)) { - pr_err("vh264 irq register error.\n"); - amvdec_disable(); - return -ENOENT; - } -#endif - - stat |= STAT_ISR_REG; - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vh264_vf_prov, PROVIDER_NAME, &vh264_vf_provider_ops, - NULL); - vf_reg_provider(&vh264_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vh264_vf_prov, PROVIDER_NAME, &vh264_vf_provider_ops, - NULL); - vf_reg_provider(&vh264_vf_prov); -#endif - - if (frame_dur != 0) { - if (!is_reset) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)frame_dur)); - fr_hint_status = VDEC_HINTED; - } - } else - fr_hint_status = VDEC_NEED_HINT; - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong) &recycle_timer; - recycle_timer.function = vh264_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - vh264_stream_switching_state = SWITCHING_STATE_OFF; - - stat |= STAT_VDEC_RUN; - wmb(); /* Ensure fetchbuf contents visible */ - - /* -- start decoder */ - amvdec_start(); - - init_userdata_fifo(); - - return 0; -} - -static int vh264_stop(int mode) -{ - - - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - WRITE_VREG(ASSIST_MBOX1_MASK, 0); - /*TODO irq */ - - vdec_free_irq(VDEC_IRQ_1, (void *)vh264_dec_id); - - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - if (stat & STAT_VF_HOOK) { - if (mode == MODE_FULL) { - if (fr_hint_status == VDEC_HINTED) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - fr_hint_status = VDEC_NO_NEED_HINT; - } - - vf_unreg_provider(&vh264_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - if (stat & STAT_MC_LOAD) { - if (mc_cpu_addr != NULL) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, - mc_dma_handle); - mc_cpu_addr = NULL; - } - } - if (sei_data_buffer != NULL) { - dma_free_coherent( - amports_get_dma_device(), - USER_DATA_RUND_SIZE, - sei_data_buffer, - sei_data_buffer_phys); - sei_data_buffer = NULL; - sei_data_buffer_phys = 0; - } - amvdec_disable(); - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - memset(&fense_buffer_spec, 0, sizeof(fense_buffer_spec)); - memset(&buffer_spec, 0, sizeof(buffer_spec)); - return 0; -} - -static void wait_vh264_search_done(void) -{ - u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - int count = 0; - do { - usleep_range(100, 500); - if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) - break; - if (count > 2000) { - pr_info("%s, timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", - __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); - break; - } else - vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - count++; - } while (1); -} - - -static void error_do_work(struct work_struct *work) -{ - - /* - * we need to lock vh264_stop/vh264_init. - * because we will call amvdec_h264_remove on this step; - * then we may call more than once on - * free_irq/deltimer/..and some other. - */ - if (atomic_read(&vh264_active)) { - amvdec_stop(); - do { - msleep(50); - } while (vh264_stream_switching_state != SWITCHING_STATE_OFF); - wait_vh264_search_done(); - vh264_reset = 1; -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vh264_ppmgr_reset(); -#else - vf_light_unreg_provider(&vh264_vf_prov); - - vh264_local_init(); - - vf_reg_provider(&vh264_vf_prov); -#endif - vh264_prot_init(); - amvdec_start(); - vh264_reset = 0; - } -} - -static void stream_switching_done(void) -{ - int state = vh264_stream_switching_state; - - WRITE_VREG(AV_SCRATCH_7, 0); - WRITE_VREG(AV_SCRATCH_8, 0); - WRITE_VREG(AV_SCRATCH_9, 0); - - if (state == SWITCHING_STATE_ON_CMD1) { - pr_info("Enter set parameter cmd1 switching_state %x.\n", - vh264_stream_switching_state); - schedule_work(&set_parameter_work); - return; - } else if (state == SWITCHING_STATE_ON_CMD1_PENDING) - return; - - vh264_stream_switching_state = SWITCHING_STATE_OFF; - - wmb(); /* Ensure fetchbuf contents visible */ - - if (state == SWITCHING_STATE_ON_CMD3) - WRITE_VREG(AV_SCRATCH_0, 0); - - pr_info("Leaving switching mode.\n"); -} - -/* construt a new frame as a copy of last frame so frame receiver can - * release all buffer resources to decoder. - */ -static void stream_switching_do(struct work_struct *work) -{ - int mb_total_num, mb_width_num, mb_height_num, i = 0; - struct vframe_s *vf = NULL; - u32 y_index, u_index, src_index, des_index, y_desindex, u_desindex; - struct canvas_s csy, csu, cyd; - unsigned long flags; - bool delay = true; - - if (!atomic_read(&vh264_active)) - return; - - if (vh264_stream_switching_state == SWITCHING_STATE_OFF) - return; - - spin_lock_irqsave(&prepare_lock, flags); - - block_display_q = true; - - spin_unlock_irqrestore(&prepare_lock, flags); - - mb_total_num = mb_total; - mb_width_num = mb_width; - mb_height_num = mb_height; - - while (is_4k || kfifo_len(&delay_display_q) > 2) { - if (kfifo_get(&delay_display_q, &vf)) { - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } else - break; - } - - if (!kfifo_get(&delay_display_q, &vf)) { - vf = p_last_vf; - delay = false; - } - - while (vf) { - int buffer_index; - - buffer_index = vf->index & 0xff; - - /* construct a clone of the frame from last frame */ - -#if 0 - - pr_info("src yaddr[0x%x] index[%d] width[%d] heigth[%d]\n", - buffer_spec[buffer_index].y_addr, - buffer_spec[buffer_index].y_canvas_index, - buffer_spec[buffer_index].y_canvas_width, - buffer_spec[buffer_index].y_canvas_height); - - pr_info("src uaddr[0x%x] index[%d] width[%d] heigth[%d]\n", - buffer_spec[buffer_index].u_addr, - buffer_spec[buffer_index].u_canvas_index, - buffer_spec[buffer_index].u_canvas_width, - buffer_spec[buffer_index].u_canvas_height); -#endif - if (EN_SWITCH_FENCE()) { - y_index = buffer_spec[buffer_index].y_canvas_index; - u_index = buffer_spec[buffer_index].u_canvas_index; - - canvas_read(y_index, &csy); - canvas_read(u_index, &csu); - - canvas_config(fense_buffer_spec[i].y_canvas_index, - fense_buffer_spec[i].phy_addr, - mb_width_num << 4, mb_height_num << 4, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(fense_buffer_spec[i].u_canvas_index, - fense_buffer_spec[i].phy_addr + - (mb_total_num << 8), - mb_width_num << 4, mb_height_num << 3, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - - y_desindex = fense_buffer_spec[i].y_canvas_index; - u_desindex = fense_buffer_spec[i].u_canvas_index; - - canvas_read(y_desindex, &cyd); - - src_index = ((y_index & 0xff) | - ((u_index << 8) & 0x0000ff00)); - des_index = ((y_desindex & 0xff) | - ((u_desindex << 8) & 0x0000ff00)); - - ge2d_canvas_dup(&csy, &csu, &cyd, - GE2D_FORMAT_M24_NV21, - src_index, - des_index); - } - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - FENSE_BUFFER_IDX(i)); - fense_vf[i] = *vf; - fense_vf[i].index = -1; - - if (EN_SWITCH_FENCE()) - fense_vf[i].canvas0Addr = - spec2canvas(&fense_buffer_spec[i]); - else - fense_vf[i].flag |= VFRAME_FLAG_SWITCHING_FENSE; - - /* send clone to receiver */ - kfifo_put(&display_q, - (const struct vframe_s *)&fense_vf[i]); - ATRACE_COUNTER(MODULE_NAME, fense_vf[i].pts); - /* early recycle frames for last session */ - if (delay) - vh264_vf_put(vf, NULL); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - - i++; - - if (!kfifo_get(&delay_display_q, &vf)) - break; - } - - block_display_q = false; - - pr_info("Switching fense frame post\n"); -} - -static int amvdec_h264_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - mutex_lock(&vh264_mutex); - - if (pdata == NULL) { - pr_info("\namvdec_h264 memory resource undefined.\n"); - mutex_unlock(&vh264_mutex); - return -EFAULT; - } - canvas_mode = pdata->canvas_mode; - tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0; - if (pdata->sys_info) - vh264_amstream_dec_info = *pdata->sys_info; - if (sei_data_buffer == NULL) { - sei_data_buffer = - dma_alloc_coherent(amports_get_dma_device(), - USER_DATA_RUND_SIZE, - &sei_data_buffer_phys, GFP_KERNEL); - if (!sei_data_buffer) { - pr_info("%s: Can not allocate sei_data_buffer\n", - __func__); - mutex_unlock(&vh264_mutex); - return -ENOMEM; - } - /* pr_info("buffer 0x%x, phys 0x%x, remap 0x%x\n", - * sei_data_buffer, sei_data_buffer_phys, - * (u32)sei_data_buffer_remap); - */ - } - pdata->dec_status = vh264_dec_status; - pdata->set_trickmode = vh264_set_trickmode; - pdata->set_isreset = vh264_set_isreset; - - pdata->user_data_read = vh264_user_data_read; - pdata->reset_userdata_fifo = vh264_reset_userdata_fifo; - pdata->wakeup_userdata_poll = vh264_wakeup_userdata_poll; - - is_reset = 0; - clk_adj_frame_count = 0; - if (vh264_init() < 0) { - pr_info("\namvdec_h264 init failed.\n"); - kfree(gvs); - gvs = NULL; - pdata->dec_status = NULL; - mutex_unlock(&vh264_mutex); - return -ENODEV; - } - vdec_h264 = pdata; - vh264_crate_userdata_manager(sei_data_buffer, USER_DATA_SIZE); - vh264_reset_userdata_fifo(vdec_h264, 1); - -#ifdef DUMP_USER_DATA - vh264_init_userdata_dump(); - vh264_reset_user_data_buf(); -#endif - - INIT_WORK(&error_wd_work, error_do_work); - INIT_WORK(&stream_switching_work, stream_switching_do); - INIT_WORK(&set_parameter_work, vh264_set_params); - INIT_WORK(¬ify_work, vh264_notify_work); - INIT_WORK(&set_clk_work, vh264_set_clk); - INIT_WORK(&userdata_push_work, userdata_push_do_work); - INIT_WORK(&qos_work, qos_do_work); - - - - atomic_set(&vh264_active, 1); - - mutex_unlock(&vh264_mutex); - - return 0; -} - -static int amvdec_h264_remove(struct platform_device *pdev) -{ - atomic_set(&vh264_active, 0); - cancel_work_sync(&set_parameter_work); - cancel_work_sync(&error_wd_work); - cancel_work_sync(&stream_switching_work); - cancel_work_sync(¬ify_work); - cancel_work_sync(&userdata_push_work); - cancel_work_sync(&qos_work); - - - vh264_stop(MODE_FULL); - wait_vh264_search_done(); - vdec_source_changed(VFORMAT_H264, 0, 0, 0); -#ifdef DUMP_USER_DATA - vh264_dump_userdata(); -#endif - vh264_destroy_userdata_manager(); - atomic_set(&vh264_active, 0); -#ifdef DEBUG_PTS - pr_info - ("pts missed %ld, pts hit %ld, pts_outside %d, duration %d, ", - pts_missed, pts_hit, pts_outside, frame_dur); - pr_info("sync_outside %d, use_idr_framerate %d\n", - sync_outside, use_idr_framerate); -#endif - kfree(gvs); - gvs = NULL; - cancel_work_sync(&set_clk_work); - mutex_unlock(&vh264_mutex); - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_h264_driver = { - .probe = amvdec_h264_probe, - .remove = amvdec_h264_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_h264_profile = { - .name = "h264", - .profile = "" -}; - - -static struct mconfig h264_configs[] = { - MC_PU32("stat", &stat), - MC_PU32("error_recovery_mode", &error_recovery_mode), - MC_PU32("sync_outside", &sync_outside), - MC_PU32("dec_control", &dec_control), - MC_PU32("fatal_error_reset", &fatal_error_reset), - MC_PU32("max_refer_buf", &max_refer_buf), - MC_PU32("ucode_type", &ucode_type), - MC_PU32("debugfirmware", &debugfirmware), - MC_PU32("fixed_frame_rate_flag", &fixed_frame_rate_flag), - MC_PU32("decoder_debug_flag", &decoder_debug_flag), - MC_PU32("dpb_size_adj", &dpb_size_adj), - MC_PU32("decoder_force_reset", &decoder_force_reset), - MC_PU32("no_idr_error_max", &no_idr_error_max), - MC_PU32("enable_switch_fense", &enable_switch_fense), -}; -static struct mconfig_node h264_node; - - -static int __init amvdec_h264_driver_init_module(void) -{ - pr_debug("amvdec_h264 module init\n"); - - ge2d_videoh264task_init(); - - if (platform_driver_register(&amvdec_h264_driver)) { - pr_err("failed to register amvdec_h264 driver\n"); - return -ENODEV; - } - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB - && (codec_mm_get_total_size() > 80 * SZ_1M)) { - amvdec_h264_profile.profile = "4k"; - } - vcodec_profile_register(&amvdec_h264_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &h264_node, - "h264", h264_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_h264_driver_remove_module(void) -{ - pr_debug("amvdec_h264 module remove.\n"); - - platform_driver_unregister(&amvdec_h264_driver); - - ge2d_videoh264task_release(); -} - -/****************************************/ - -module_param(stat, uint, 0664); -MODULE_PARM_DESC(stat, "\n amvdec_h264 stat\n"); -module_param(error_recovery_mode, uint, 0664); -MODULE_PARM_DESC(error_recovery_mode, "\n amvdec_h264 error_recovery_mode\n"); -module_param(sync_outside, uint, 0664); -MODULE_PARM_DESC(sync_outside, "\n amvdec_h264 sync_outside\n"); -module_param(dec_control, uint, 0664); -MODULE_PARM_DESC(dec_control, "\n amvdec_h264 decoder control\n"); -module_param(frame_count, uint, 0664); -MODULE_PARM_DESC(frame_count, - "\n amvdec_h264 decoded total count\n"); -module_param(fatal_error_reset, uint, 0664); -MODULE_PARM_DESC(fatal_error_reset, - "\n amvdec_h264 decoder reset when fatal error happens\n"); -module_param(max_refer_buf, uint, 0664); -MODULE_PARM_DESC(max_refer_buf, - "\n amvdec_h264 dec buffering or not for reference frame\n"); -module_param(ucode_type, uint, 0664); -MODULE_PARM_DESC(ucode_type, - "\n amvdec_h264 dec buffering or not for reference frame\n"); -module_param(debugfirmware, uint, 0664); -MODULE_PARM_DESC(debugfirmware, "\n amvdec_h264 debug load firmware\n"); -module_param(fixed_frame_rate_flag, uint, 0664); -MODULE_PARM_DESC(fixed_frame_rate_flag, - "\n amvdec_h264 fixed_frame_rate_flag\n"); -module_param(decoder_debug_flag, uint, 0664); -MODULE_PARM_DESC(decoder_debug_flag, - "\n amvdec_h264 decoder_debug_flag\n"); - -module_param(dpb_size_adj, uint, 0664); -MODULE_PARM_DESC(dpb_size_adj, - "\n amvdec_h264 dpb_size_adj\n"); - - -module_param(decoder_force_reset, uint, 0664); -MODULE_PARM_DESC(decoder_force_reset, - "\n amvdec_h264 decoder force reset\n"); -module_param(no_idr_error_max, uint, 0664); -MODULE_PARM_DESC(no_idr_error_max, - "\n print no_idr_error_max\n"); -module_param(enable_switch_fense, uint, 0664); -MODULE_PARM_DESC(enable_switch_fense, - "\n enable switch fense\n"); - -#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY -module_param(bad_block_scale, uint, 0664); -MODULE_PARM_DESC(bad_block_scale, - "\n print bad_block_scale\n"); -#endif - -module_param(enable_userdata_debug, uint, 0664); -MODULE_PARM_DESC(enable_userdata_debug, - "\n enable_userdata_debug\n"); - - -module_init(amvdec_h264_driver_init_module); -module_exit(amvdec_h264_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC H264 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Chen Zhang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h deleted file mode 100644 index 6c8e4ad684a6..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/h264/vh264.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VH264_H -#define VH264_H - -extern int query_video_status(int type, int *value); - -/* extern s32 vh264_init(void); */ - -extern s32 vh264_release(void); - -#endif /* VMPEG4_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c deleted file mode 100644 index 8ea595f09cd9..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c +++ /dev/null @@ -1,1809 +0,0 @@ -/* - * drivers/amlogic/amports/vh264_4k2k.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../utils/firmware.h" -#include -#include "../../../common/chips/decoder_cpu_ver_info.h" - - - -#define MEM_NAME "codec_264_4k" - -/* #include */ -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - -#include -#endif - -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../utils/vdec.h" -#include "../utils/amvdec.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include - -#include - - -#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TVD */ -#define DOUBLE_WRITE -#endif - -#define DRIVER_NAME "amvdec_h264_4k2k" -#define MODULE_NAME "amvdec_h264_4k2k" - -#define PUT_INTERVAL (HZ/100) -#define ERROR_RESET_COUNT 500 -#define DECODE_BUFFER_NUM_MAX 32 -#define DISPLAY_BUFFER_NUM 6 -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + DISPLAY_BUFFER_NUM) -#define VF_BUFFER_IDX(n) (2 + n) -#define DECODER_WORK_SPACE_SIZE 0x800000 - -#if 1 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV */ -#define H264_4K2K_SINGLE_CORE 1 -#else -#define H264_4K2K_SINGLE_CORE IS_MESON_M8M2_CPU -#endif - -#define SLICE_TYPE_I 2 - -static int vh264_4k2k_vf_states(struct vframe_states *states, void *); -static struct vframe_s *vh264_4k2k_vf_peek(void *); -static struct vframe_s *vh264_4k2k_vf_get(void *); -static void vh264_4k2k_vf_put(struct vframe_s *, void *); -static int vh264_4k2k_event_cb(int type, void *data, void *private_data); - -static void vh264_4k2k_prot_init(void); -static int vh264_4k2k_local_init(void); -static void vh264_4k2k_put_timer_func(unsigned long arg); - -static const char vh264_4k2k_dec_id[] = "vh264_4k2k-dev"; -static const char vh264_4k2k_dec_id2[] = "vh264_4k2k-vdec2-dev"; - -#define PROVIDER_NAME "decoder.h264_4k2k" - -static const struct vframe_operations_s vh264_4k2k_vf_provider = { - .peek = vh264_4k2k_vf_peek, - .get = vh264_4k2k_vf_get, - .put = vh264_4k2k_vf_put, - .event_cb = vh264_4k2k_event_cb, - .vf_states = vh264_4k2k_vf_states, -}; -static void *mm_blk_handle; -static struct vframe_provider_s vh264_4k2k_vf_prov; - -static u32 mb_width_old, mb_height_old; -static u32 frame_width, frame_height, frame_dur, frame_ar; -static u32 saved_resolution; -static struct timer_list recycle_timer; -static u32 stat; -static u32 error_watchdog_count; -static uint error_recovery_mode; -static u32 sync_outside; -static u32 vh264_4k2k_rotation; -static u32 first_i_received; -static struct vframe_s *p_last_vf; -static struct work_struct set_clk_work; - -#ifdef DEBUG_PTS -static unsigned long pts_missed, pts_hit; -#endif - -static struct dec_sysinfo vh264_4k2k_amstream_dec_info; -static dma_addr_t mc_dma_handle; -static void *mc_cpu_addr; - -#define AMVDEC_H264_4K2K_CANVAS_INDEX 0x80 -#define AMVDEC_H264_4K2K_CANVAS_MAX 0xc6 -static DEFINE_SPINLOCK(lock); -static int fatal_error; - -static atomic_t vh264_4k2k_active = ATOMIC_INIT(0); - -static DEFINE_MUTEX(vh264_4k2k_mutex); - -static void (*probe_callback)(void); -static void (*remove_callback)(void); -static struct device *cma_dev; - -/* bit[3:0] command : */ -/* 0 - command finished */ -/* (DATA0 - {level_idc_mmco, max_reference_frame_num, width, height} */ -/* 1 - alloc view_0 display_buffer and reference_data_area */ -/* 2 - alloc view_1 display_buffer and reference_data_area */ -#define MAILBOX_COMMAND AV_SCRATCH_0 -#define MAILBOX_DATA_0 AV_SCRATCH_1 -#define MAILBOX_DATA_1 AV_SCRATCH_2 -#define MAILBOX_DATA_2 AV_SCRATCH_3 -#define MAILBOX_DATA_3 AV_SCRATCH_4 -#define MAILBOX_DATA_4 AV_SCRATCH_5 -#define CANVAS_START AV_SCRATCH_6 -#define BUFFER_RECYCLE AV_SCRATCH_7 -#define PICTURE_COUNT AV_SCRATCH_9 -#define DECODE_STATUS AV_SCRATCH_A -#define SPS_STATUS AV_SCRATCH_B -#define PPS_STATUS AV_SCRATCH_C -#define MS_ID AV_SCRATCH_D -#define WORKSPACE_START AV_SCRATCH_E -#define DECODED_PIC_NUM AV_SCRATCH_F -#define DECODE_ERROR_CNT AV_SCRATCH_G -#define CURRENT_UCODE AV_SCRATCH_H -/* bit[15:9]-SPS, bit[8:0]-PPS */ -#define CURRENT_SPS_PPS AV_SCRATCH_I -#define DECODE_SKIP_PICTURE AV_SCRATCH_J -#define DECODE_MODE AV_SCRATCH_K -#define RESERVED_REG_L AV_SCRATCH_L -#define REF_START_VIEW_0 AV_SCRATCH_M -#define REF_START_VIEW_1 AV_SCRATCH_N - -#define VDEC2_MAILBOX_COMMAND VDEC2_AV_SCRATCH_0 -#define VDEC2_MAILBOX_DATA_0 VDEC2_AV_SCRATCH_1 -#define VDEC2_MAILBOX_DATA_1 VDEC2_AV_SCRATCH_2 -#define VDEC2_MAILBOX_DATA_2 VDEC2_AV_SCRATCH_3 -#define VDEC2_MAILBOX_DATA_3 VDEC2_AV_SCRATCH_4 -#define VDEC2_MAILBOX_DATA_4 VDEC2_AV_SCRATCH_5 -#define VDEC2_CANVAS_START VDEC2_AV_SCRATCH_6 -#define VDEC2_BUFFER_RECYCLE VDEC2_AV_SCRATCH_7 -#define VDEC2_PICTURE_COUNT VDEC2_AV_SCRATCH_9 -#define VDEC2_DECODE_STATUS VDEC2_AV_SCRATCH_A -#define VDEC2_SPS_STATUS VDEC2_AV_SCRATCH_B -#define VDEC2_PPS_STATUS VDEC2_AV_SCRATCH_C -#define VDEC2_MS_ID VDEC2_AV_SCRATCH_D -#define VDEC2_WORKSPACE_START VDEC2_AV_SCRATCH_E -#define VDEC2_DECODED_PIC_NUM VDEC2_AV_SCRATCH_F -#define VDEC2_DECODE_ERROR_CNT VDEC2_AV_SCRATCH_G -#define VDEC2_CURRENT_UCODE VDEC2_AV_SCRATCH_H -/* bit[15:9]-SPS, bit[8:0]-PPS */ -#define VDEC2_CURRENT_SPS_PPS VDEC2_AV_SCRATCH_I -#define VDEC2_DECODE_SKIP_PICTURE VDEC2_AV_SCRATCH_J -#define VDEC2_RESERVED_REG_K VDEC2_AV_SCRATCH_K -#define VDEC2_RESERVED_REG_L VDEC2_AV_SCRATCH_L -#define VDEC2_REF_START_VIEW_0 VDEC2_AV_SCRATCH_M -#define VDEC2_REF_START_VIEW_1 VDEC2_AV_SCRATCH_N - -/******************************************** - * DECODE_STATUS Define - ******************************************* - */ -#define DECODE_IDLE 0 -#define DECODE_START_HEADER 1 -#define DECODE_HEADER 2 -#define DECODE_START_MMCO 3 -#define DECODE_MMCO 4 -#define DECODE_START_SLICE 5 -#define DECODE_SLICE 6 -#define DECODE_WAIT_BUFFER 7 - -/******************************************** - * Dual Core Communication - ******************************************** - */ -#define FATAL_ERROR DOS_SCRATCH16 -#define PRE_MASTER_UPDATE_TIMES DOS_SCRATCH20 -/* bit[31] - REQUEST */ -/* bit[30:0] - MASTER_UPDATE_TIMES */ -#define SLAVE_WAIT_DPB_UPDATE DOS_SCRATCH21 -/* [15:8] - current_ref, [7:0] current_dpb (0x80 means no buffer found) */ -#define SLAVE_REF_DPB DOS_SCRATCH22 -#define SAVE_MVC_ENTENSION_0 DOS_SCRATCH23 -#define SAVE_I_POC DOS_SCRATCH24 -/* bit[31:30] - core_status 0-idle, 1-mmco, 2-decoding, 3-finished */ -/* bit[29:0] - core_pic_count */ -#define CORE_STATUS_M DOS_SCRATCH25 -#define CORE_STATUS_S DOS_SCRATCH26 -#define SAVE_ref_status_view_0 DOS_SCRATCH27 -#define SAVE_ref_status_view_1 DOS_SCRATCH28 -#define ALLOC_INFO_0 DOS_SCRATCH29 -#define ALLOC_INFO_1 DOS_SCRATCH30 - -/******************************************** - * Mailbox command - ********************************************/ -#define CMD_FINISHED 0 -#define CMD_ALLOC_VIEW 1 -#define CMD_FRAME_DISPLAY 3 -#define CMD_DEBUG 10 - -#define MC_TOTAL_SIZE (28*SZ_1K) -#define MC_SWAP_SIZE (4*SZ_1K) - -static unsigned long work_space_adr, ref_start_addr; -static unsigned long reserved_buffer; - - -#define video_domain_addr(adr) (adr&0x7fffffff) - - -struct buffer_spec_s { - unsigned int y_addr; - unsigned int uv_addr; -#ifdef DOUBLE_WRITE - unsigned int y_dw_addr; - unsigned int uv_dw_addr; -#endif - - int y_canvas_index; - int uv_canvas_index; -#ifdef DOUBLE_WRITE - int y_dw_canvas_index; - int uv_dw_canvas_index; -#endif - - struct page *alloc_pages; - unsigned long phy_addr; - int alloc_count; -}; - -static struct buffer_spec_s buffer_spec[MAX_BMMU_BUFFER_NUM]; - -#ifdef DOUBLE_WRITE -#define spec2canvas(x) \ - (((x)->uv_dw_canvas_index << 16) | \ - ((x)->uv_dw_canvas_index << 8) | \ - ((x)->y_dw_canvas_index << 0)) -#else -#define spec2canvas(x) \ - (((x)->uv_canvas_index << 16) | \ - ((x)->uv_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) -#endif - -#define VF_POOL_SIZE 32 - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; -static struct vframe_s vfpool[VF_POOL_SIZE]; - -static struct work_struct alloc_work; -static struct vdec_info *gvs; - -static void set_frame_info(struct vframe_s *vf) -{ - unsigned int ar; - -#ifdef DOUBLE_WRITE - vf->width = frame_width / 2; - vf->height = frame_height / 2; -#else - vf->width = frame_width; - vf->height = frame_height; -#endif - vf->duration = frame_dur; - vf->duration_pulldown = 0; - vf->flag = 0; - - ar = min_t(u32, frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - vf->orientation = vh264_4k2k_rotation; - -} - -static int vh264_4k2k_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - return 0; -} - -static struct vframe_s *vh264_4k2k_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vh264_4k2k_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vh264_4k2k_vf_put(struct vframe_s *vf, void *op_arg) -{ - kfifo_put(&recycle_q, (const struct vframe_s *)vf); -} - -static int vh264_4k2k_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); - - if (!H264_4K2K_SINGLE_CORE) - amvdec2_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vh264_4k2k_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vh264_4k2k_local_init(); - vh264_4k2k_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vh264_4k2k_vf_prov); -#endif - amvdec_start(); - - if (!H264_4K2K_SINGLE_CORE) - amvdec2_start(); - } - - return 0; -} - -static int init_canvas(int refbuf_size, long dpb_size, int dpb_number, - int mb_width, int mb_height, - struct buffer_spec_s *buffer_spec) -{ - unsigned long addr; - int i, j, ret = -1; - int mb_total; - int canvas_addr = ANC0_CANVAS_ADDR; - int vdec2_canvas_addr = VDEC2_ANC0_CANVAS_ADDR; - int index = AMVDEC_H264_4K2K_CANVAS_INDEX; - - mb_total = mb_width * mb_height; - mutex_lock(&vh264_4k2k_mutex); - - for (j = 0; j < (dpb_number + 1); j++) { - int page_count; - if (j == 0) { - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 1, - refbuf_size, DRIVER_NAME, &ref_start_addr); - if (ret < 0) { - mutex_unlock(&vh264_4k2k_mutex); - return ret; - } - continue; - } - - WRITE_VREG(canvas_addr++, index | ((index + 1) << 8) | - ((index + 1) << 16)); - if (!H264_4K2K_SINGLE_CORE) { - WRITE_VREG(vdec2_canvas_addr++, - index | ((index + 1) << 8) | - ((index + 1) << 16)); - } - - i = j - 1; -#ifdef DOUBLE_WRITE - page_count = - PAGE_ALIGN((mb_total << 8) + (mb_total << 7) + - (mb_total << 6) + (mb_total << 5)) / PAGE_SIZE; -#else - page_count = - PAGE_ALIGN((mb_total << 8) + (mb_total << 7)) / PAGE_SIZE; -#endif - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, - VF_BUFFER_IDX(i), page_count << PAGE_SHIFT, - DRIVER_NAME, &buffer_spec[i].phy_addr); - - if (ret < 0) { - buffer_spec[i].alloc_count = 0; - mutex_unlock(&vh264_4k2k_mutex); - return ret; - } - addr = buffer_spec[i].phy_addr; - buffer_spec[i].alloc_count = page_count; - buffer_spec[i].y_addr = addr; - buffer_spec[i].y_canvas_index = index; - canvas_config(index, - addr, - mb_width << 4, - mb_height << 4, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - addr += mb_total << 8; - index++; - - buffer_spec[i].uv_addr = addr; - buffer_spec[i].uv_canvas_index = index; - canvas_config(index, - addr, - mb_width << 4, - mb_height << 3, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - addr += mb_total << 7; - index++; - -#ifdef DOUBLE_WRITE - buffer_spec[i].y_dw_addr = addr; - buffer_spec[i].y_dw_canvas_index = index; - canvas_config(index, - addr, - mb_width << 3, - mb_height << 3, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - addr += mb_total << 6; - index++; - - buffer_spec[i].uv_dw_addr = addr; - buffer_spec[i].uv_dw_canvas_index = index; - canvas_config(index, - addr, - mb_width << 3, - mb_height << 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - index++; -#endif - } - - mutex_unlock(&vh264_4k2k_mutex); - - pr_info - ("H264 4k2k decoder canvas allocation successful, "); - - return 0; -} - -static int get_max_dec_frame_buf_size(int level_idc, - int max_reference_frame_num, int mb_width, - int mb_height) -{ - int pic_size = mb_width * mb_height * 384; - - int size = 0; - - switch (level_idc) { - case 9: - size = 152064; - break; - case 10: - size = 152064; - break; - case 11: - size = 345600; - break; - case 12: - size = 912384; - break; - case 13: - size = 912384; - break; - case 20: - size = 912384; - break; - case 21: - size = 1824768; - break; - case 22: - size = 3110400; - break; - case 30: - size = 3110400; - break; - case 31: - size = 6912000; - break; - case 32: - size = 7864320; - break; - case 40: - size = 12582912; - break; - case 41: - size = 12582912; - break; - case 42: - size = 13369344; - break; - case 50: - size = 42393600; - break; - case 51: - case 52: - default: - size = 70778880; - break; - } - - size /= pic_size; - size = size + 1; /* need one more buffer */ - - if (max_reference_frame_num > size) - size = max_reference_frame_num; - - if (size > DECODE_BUFFER_NUM_MAX) - size = DECODE_BUFFER_NUM_MAX; - - return size; -} - -static void do_alloc_work(struct work_struct *work) -{ - int level_idc, max_reference_frame_num, mb_width, mb_height, - frame_mbs_only_flag; - int dpb_size, ref_size, refbuf_size; - int max_dec_frame_buffering, - total_dec_frame_buffering; - unsigned int chroma444; - unsigned int crop_infor, crop_bottom, crop_right; - int ret = READ_VREG(MAILBOX_COMMAND); - - - ret = READ_VREG(MAILBOX_DATA_0); - /* MAILBOX_DATA_1 : - * bit15 : frame_mbs_only_flag - * bit 0-7 : chroma_format_idc - * MAILBOX_DATA_2: - * bit31-16: (left << 8 | right ) << 1 - * bit15-0 : (top << 8 | bottom ) << (2 - frame_mbs_only_flag) - */ - frame_mbs_only_flag = READ_VREG(MAILBOX_DATA_1); - crop_infor = READ_VREG(MAILBOX_DATA_2); - level_idc = (ret >> 24) & 0xff; - max_reference_frame_num = (ret >> 16) & 0xff; - mb_width = (ret >> 8) & 0xff; - if (mb_width == 0) - mb_width = 256; - mb_height = (ret >> 0) & 0xff; - max_dec_frame_buffering = - get_max_dec_frame_buf_size(level_idc, max_reference_frame_num, - mb_width, mb_height); - total_dec_frame_buffering = - max_dec_frame_buffering + DISPLAY_BUFFER_NUM; - - chroma444 = ((frame_mbs_only_flag&0xffff) == 3) ? 1 : 0; - frame_mbs_only_flag = (frame_mbs_only_flag >> 16) & 0x01; - crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag); - crop_right = ((crop_infor >> 16) & 0xff) >> 1; - pr_info("crop_right = 0x%x crop_bottom = 0x%x chroma_format_idc = 0x%x\n", - crop_right, crop_bottom, chroma444); - - if ((frame_width == 0) || (frame_height == 0) || crop_infor || - mb_width != mb_width_old || - mb_height != mb_height_old) { - frame_width = mb_width << 4; - frame_height = mb_height << 4; - mb_width_old = mb_width; - mb_height_old = mb_height; - if (frame_mbs_only_flag) { - frame_height -= (2 >> chroma444) * - min(crop_bottom, - (unsigned int)((8 << chroma444) - 1)); - frame_width -= (2 >> chroma444) * - min(crop_right, - (unsigned int)((8 << chroma444) - 1)); - } else { - frame_height -= (4 >> chroma444) * - min(crop_bottom, - (unsigned int)((8 << chroma444) - 1)); - frame_width -= (4 >> chroma444) * - min(crop_right, - (unsigned int)((8 << chroma444) - 1)); - } - pr_info("frame_mbs_only_flag %d, crop_bottom %d frame_height %d, mb_height %d crop_right %d, frame_width %d, mb_width %d\n", - frame_mbs_only_flag, crop_bottom, frame_height, - mb_height, crop_right, frame_width, mb_height); - } - - mb_width = (mb_width + 3) & 0xfffffffc; - mb_height = (mb_height + 3) & 0xfffffffc; - - dpb_size = mb_width * mb_height * 384; - ref_size = mb_width * mb_height * 96; - refbuf_size = ref_size * (max_reference_frame_num + 1) * 2; - - - pr_info("mb_width=%d, mb_height=%d\n", - mb_width, mb_height); - - ret = init_canvas(refbuf_size, dpb_size, - total_dec_frame_buffering, mb_width, mb_height, - buffer_spec); - - if (ret == -1) { - pr_info(" Un-expected memory alloc problem\n"); - return; - } - - if (frame_width == 0) - frame_width = mb_width << 4; - if (frame_height == 0) - frame_height = mb_height << 4; - - WRITE_VREG(REF_START_VIEW_0, video_domain_addr(ref_start_addr)); - if (!H264_4K2K_SINGLE_CORE) { - WRITE_VREG(VDEC2_REF_START_VIEW_0, - video_domain_addr(ref_start_addr)); - } - - WRITE_VREG(MAILBOX_DATA_0, - (max_dec_frame_buffering << 8) | - (total_dec_frame_buffering << 0)); - WRITE_VREG(MAILBOX_DATA_1, ref_size); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - - /* ///////////// FAKE FIRST PIC */ - -} - -static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) -{ - int drop_status, display_buff_id, display_POC, slice_type, error; - unsigned int stream_offset; - struct vframe_s *vf = NULL; - int ret = READ_VREG(MAILBOX_COMMAND); - u32 frame_size; - - switch (ret & 0xff) { - case CMD_ALLOC_VIEW: - schedule_work(&alloc_work); - break; - - case CMD_FRAME_DISPLAY: - ret >>= 8; - display_buff_id = (ret >> 0) & 0x3f; - drop_status = (ret >> 8) & 0x1; - slice_type = (ret >> 9) & 0x7; - error = (ret >> 12) & 0x1; - display_POC = READ_VREG(MAILBOX_DATA_0); - stream_offset = READ_VREG(MAILBOX_DATA_1); - - smp_rmb();/* rmb smp */ - - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - if (vf) { - vfbuf_use[display_buff_id]++; - - vf->pts = 0; - vf->pts_us64 = 0; - - if ((!sync_outside) - || (sync_outside && - (slice_type == SLICE_TYPE_I))) { - ret = pts_lookup_offset_us64(PTS_TYPE_VIDEO, - stream_offset, - &vf->pts, - &frame_size, - 0, - &vf->pts_us64); - if (ret != 0) - pr_debug(" vpts lookup failed\n"); - } -#ifdef H264_4K2K_SINGLE_CORE - if (READ_VREG(DECODE_MODE) & 1) { - /* for I only mode, ignore the PTS information - * and only uses 10fps for each - * I frame decoded - */ - if (p_last_vf) { - vf->pts = 0; - vf->pts_us64 = 0; - } - frame_dur = 96000 / 10; - } -#endif - vf->signal_type = 0; - vf->index = display_buff_id; - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&buffer_spec[display_buff_id]); - set_frame_info(vf); - - if (error) - gvs->drop_frame_count++; - - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, error, stream_offset); - - if (((error_recovery_mode & 2) && error) - || (!first_i_received - && (slice_type != SLICE_TYPE_I))) { - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - } else { - p_last_vf = vf; - first_i_received = 1; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(display_buff_id)); - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - } - break; - - case CMD_DEBUG: - pr_info("M: core_status 0x%08x 0x%08x; ", - READ_VREG(CORE_STATUS_M), READ_VREG(CORE_STATUS_S)); - switch (READ_VREG(MAILBOX_DATA_0)) { - case 1: - pr_info("H264_BUFFER_INFO_INDEX = 0x%x\n", - READ_VREG(MAILBOX_DATA_1)); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 2: - pr_info("H264_BUFFER_INFO_DATA = 0x%x\n", - READ_VREG(MAILBOX_DATA_1)); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 3: - pr_info("REC_CANVAS_ADDR = 0x%x\n", - READ_VREG(MAILBOX_DATA_1)); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 4: - pr_info("after DPB_MMCO\n"); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 5: - pr_info("MBY = 0x%x, S_MBXY = 0x%x\n", - READ_VREG(MAILBOX_DATA_1), - READ_VREG(0x2c07)); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 6: - pr_info("after FIFO_OUT_FRAME\n"); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 7: - pr_info("after RELEASE_EXCEED_REF_BUFF\n"); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - break; - case 0x5a: - pr_info("\n"); - break; - default: - pr_info("\n"); - break; - } - break; - - default: - break; - } - - return IRQ_HANDLED; -} - -#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ -static irqreturn_t vh264_4k2k_vdec2_isr(int irq, void *dev_id) -{ - int ret = READ_VREG(VDEC2_MAILBOX_COMMAND); - - switch (ret & 0xff) { - case CMD_DEBUG: - pr_info("S: core_status 0x%08x 0x%08x; ", - READ_VREG(CORE_STATUS_M), READ_VREG(CORE_STATUS_S)); - switch (READ_VREG(VDEC2_MAILBOX_DATA_0)) { - case 1: - pr_info("H264_BUFFER_INFO_INDEX = 0x%x\n", - READ_VREG(VDEC2_MAILBOX_DATA_1)); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 2: - pr_info("H264_BUFFER_INFO_DATA = 0x%x\n", - READ_VREG(VDEC2_MAILBOX_DATA_1)); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 3: - pr_info("REC_CANVAS_ADDR = 0x%x\n", - READ_VREG(VDEC2_MAILBOX_DATA_1)); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 4: - pr_info("after DPB_MMCO\n"); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 5: - pr_info("MBY = 0x%x, M/S_MBXY = 0x%x-0x%x\n", - READ_VREG(VDEC2_MAILBOX_DATA_1), - READ_VREG(0xc07), READ_VREG(0x2c07)); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 6: - pr_info("after FIFO_OUT_FRAME\n"); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 7: - pr_info("after RELEASE_EXCEED_REF_BUFF\n"); - WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); - break; - case 0x5a: - pr_info("\n"); - break; - default: - pr_info("\n"); - break; - } - break; - - default: - break; - } - - return IRQ_HANDLED; -} -#endif - -static void vh264_4k2k_set_clk(struct work_struct *work) -{ - if (first_i_received &&/*do switch after first i frame ready.*/ - frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { - int fps = 96000 / frame_dur; - - pr_info("H264 4k2k resolution changed!!\n"); - if (vdec_source_changed(VFORMAT_H264_4K2K, - frame_width, frame_height, fps) > 0)/*changed clk ok*/ - saved_resolution = frame_width * frame_height * fps; - } -} - -static void vh264_4k2k_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - enum receviver_start_e state = RECEIVER_INACTIVE; - - if (vf_get_receiver(PROVIDER_NAME)) { - state = vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) - state = RECEIVER_INACTIVE; - } else - state = RECEIVER_INACTIVE; - - /* error watchdog */ - if (((READ_VREG(VLD_MEM_VIFIFO_CONTROL) & 0x100) == 0) &&/* dec has in*/ - (state == RECEIVER_INACTIVE) && /* rec has no buf to recycle */ - (kfifo_is_empty(&display_q)) && /* no buf in display queue */ - (kfifo_is_empty(&recycle_q)) && /* no buf to recycle */ - (READ_VREG(MS_ID) & 0x100) -#ifdef CONFIG_H264_2K4K_SINGLE_CORE - && (READ_VREG(VDEC2_MS_ID) & 0x100) - -/* with both decoder - * have started decoding - */ -#endif - && first_i_received) { - if (++error_watchdog_count == ERROR_RESET_COUNT) { - /* and it lasts for a while */ - pr_info("H264 4k2k decoder fatal error watchdog.\n"); - fatal_error = DECODER_FATAL_ERROR_UNKNOWN; - } - } else - error_watchdog_count = 0; - - if (READ_VREG(FATAL_ERROR) != 0) { - pr_info("H264 4k2k decoder ucode fatal error.\n"); - fatal_error = DECODER_FATAL_ERROR_UNKNOWN; - WRITE_VREG(FATAL_ERROR, 0); - } - - while (!kfifo_is_empty(&recycle_q) && - (READ_VREG(BUFFER_RECYCLE) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < DECODE_BUFFER_NUM_MAX) - && (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(BUFFER_RECYCLE, vf->index + 1); - vf->index = DECODE_BUFFER_NUM_MAX; - } - - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - } - - schedule_work(&set_clk_work); - - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vh264_4k2k_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (frame_dur != 0) - vstatus->frame_rate = 96000 / frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = 0; - vstatus->status = stat | fatal_error; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -static int vh264_4k2k_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -int vh264_4k2k_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) -{ - if (trickmode == TRICKMODE_I) { - WRITE_VREG(DECODE_MODE, 1); - trickmode_i = 1; - } else if (trickmode == TRICKMODE_NONE) { - WRITE_VREG(DECODE_MODE, 0); - trickmode_i = 0; - } - - return 0; -} - -static void H264_DECODE_INIT(void) -{ - int i; - - WRITE_VREG(GCLK_EN, 0x3ff); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - /* fill_weight_pred */ - WRITE_VREG(MC_MPORT_CTRL, 0x0300); - for (i = 0; i < 192; i++) - WRITE_VREG(MC_MPORT_DAT, 0x100); - WRITE_VREG(MC_MPORT_CTRL, 0); - - WRITE_VREG(MB_WIDTH, 0xff); /* invalid mb_width */ - - /* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */ - WRITE_VREG(SLICE_START_BYTE_01, 0x00000000); - WRITE_VREG(SLICE_START_BYTE_23, 0x01010000); - /* set to mpeg2 to enable mismatch logic */ - WRITE_VREG(MPEG1_2_REG, 1); - WRITE_VREG(VLD_ERROR_MASK, - 0x1011); - - /* Config MCPU Amrisc interrupt */ - WRITE_VREG(ASSIST_AMR1_INT0, 0x1); /* viu_vsync_int */ - WRITE_VREG(ASSIST_AMR1_INT1, 0x5); /* mbox_isr */ - WRITE_VREG(ASSIST_AMR1_INT2, 0x8); /* vld_isr */ - /* WRITE_VREG(ASSIST_AMR1_INT3, 0x15); // vififo_empty */ - WRITE_VREG(ASSIST_AMR1_INT4, 0xd); /* rv_ai_mb_finished_int */ - WRITE_VREG(ASSIST_AMR1_INT7, 0x14); /* dcac_dma_done */ - WRITE_VREG(ASSIST_AMR1_INT8, 0x15); /* vififo_empty */ - - /* Config MCPU Amrisc interrupt */ - WRITE_VREG(ASSIST_AMR1_INT5, 0x9); /* MCPU interrupt */ - WRITE_VREG(ASSIST_AMR1_INT6, 0x17); /* CCPU interrupt */ - - WRITE_VREG(CPC_P, 0xc00); /* CCPU Code will start from 0xc00 */ - WRITE_VREG(CINT_VEC_BASE, (0xc20 >> 5)); - WRITE_VREG(POWER_CTL_VLD, (1 << 10) | /* disable cabac_step_2 */ - (1 << 9) | /* viff_drop_flag_en */ - (1 << 6)); /* h264_000003_en */ - WRITE_VREG(M4_CONTROL_REG, (1 << 13)); /* H264_DECODE_INFO - h264_en */ - - WRITE_VREG(CANVAS_START, AMVDEC_H264_4K2K_CANVAS_INDEX); - /* Start Address of Workspace (UCODE, temp_data...) */ - WRITE_VREG(WORKSPACE_START, - video_domain_addr(work_space_adr)); - /* Clear all sequence parameter set available */ - WRITE_VREG(SPS_STATUS, 0); - /* Clear all picture parameter set available */ - WRITE_VREG(PPS_STATUS, 0); - /* Set current microcode to NULL */ - WRITE_VREG(CURRENT_UCODE, 0xff); - /* Set current SPS/PPS to NULL */ - WRITE_VREG(CURRENT_SPS_PPS, 0xffff); - /* Set decode status to DECODE_START_HEADER */ - WRITE_VREG(DECODE_STATUS, 1); -} - -static void H264_DECODE2_INIT(void) -{ - int i; - - WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); - - WRITE_VREG(DOS_SW_RESET2, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET2, 0); - - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - - WRITE_VREG(DOS_SW_RESET2, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET2, 0); - - WRITE_VREG(DOS_SW_RESET2, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET2, 0); - - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - - /* fill_weight_pred */ - WRITE_VREG(VDEC2_MC_MPORT_CTRL, 0x0300); - for (i = 0; i < 192; i++) - WRITE_VREG(VDEC2_MC_MPORT_DAT, 0x100); - WRITE_VREG(VDEC2_MC_MPORT_CTRL, 0); - - WRITE_VREG(VDEC2_MB_WIDTH, 0xff); /* invalid mb_width */ - - /* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */ - WRITE_VREG(VDEC2_SLICE_START_BYTE_01, 0x00000000); - WRITE_VREG(VDEC2_SLICE_START_BYTE_23, 0x01010000); - /* set to mpeg2 to enable mismatch logic */ - WRITE_VREG(VDEC2_MPEG1_2_REG, 1); - /* disable COEF_GT_64 , error_m4_table and voff_rw_err */ - WRITE_VREG(VDEC2_VLD_ERROR_MASK, - 0x1011); - - /* Config MCPU Amrisc interrupt */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT0, 0x1);/* viu_vsync_int */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT1, 0x5);/* mbox_isr */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT2, 0x8);/* vld_isr */ - /* WRITE_VREG(VDEC2_ASSIST_AMR1_INT3, 0x15); // vififo_empty */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT4, 0xd);/* rv_ai_mb_finished_int */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT7, 0x14);/* dcac_dma_done */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT8, 0x15);/* vififo_empty */ - - /* Config MCPU Amrisc interrupt */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT5, 0x9);/* MCPU interrupt */ - WRITE_VREG(VDEC2_ASSIST_AMR1_INT6, 0x17);/* CCPU interrupt */ - - WRITE_VREG(VDEC2_CPC_P, 0xc00); /* CCPU Code will start from 0xc00 */ - WRITE_VREG(VDEC2_CINT_VEC_BASE, (0xc20 >> 5)); - WRITE_VREG(VDEC2_POWER_CTL_VLD, (1 << 10) |/* disable cabac_step_2 */ - (1 << 9) | /* viff_drop_flag_en */ - (1 << 6)); /* h264_000003_en */ - /* H264_DECODE_INFO - h264_en */ - WRITE_VREG(VDEC2_M4_CONTROL_REG, (1 << 13)); - - WRITE_VREG(VDEC2_CANVAS_START, AMVDEC_H264_4K2K_CANVAS_INDEX); - /* Start Address of Workspace (UCODE, temp_data...) */ - WRITE_VREG(VDEC2_WORKSPACE_START, - video_domain_addr(work_space_adr)); - /* Clear all sequence parameter set available */ - WRITE_VREG(VDEC2_SPS_STATUS, 0); - /* Clear all picture parameter set available */ - WRITE_VREG(VDEC2_PPS_STATUS, 0); - /* Set current microcode to NULL */ - WRITE_VREG(VDEC2_CURRENT_UCODE, 0xff); - /* Set current SPS/PPS to NULL */ - WRITE_VREG(VDEC2_CURRENT_SPS_PPS, 0xffff); - /* Set decode status to DECODE_START_HEADER */ - WRITE_VREG(VDEC2_DECODE_STATUS, 1); -} - -static void vh264_4k2k_prot_init(void) -{ - /* clear mailbox interrupt */ -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (!H264_4K2K_SINGLE_CORE) - WRITE_VREG(VDEC2_ASSIST_MBOX0_CLR_REG, 1); -#endif - WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (!H264_4K2K_SINGLE_CORE) - WRITE_VREG(VDEC2_ASSIST_MBOX0_MASK, 1); -#endif - WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 1); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - H264_DECODE_INIT(); - if (!H264_4K2K_SINGLE_CORE) - H264_DECODE2_INIT(); - - WRITE_VREG(DOS_SW_RESET0, (1 << 11)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - if (!H264_4K2K_SINGLE_CORE) { - WRITE_VREG(DOS_SW_RESET2, (1 << 11)); - WRITE_VREG(DOS_SW_RESET2, 0); - - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - } - - WRITE_VREG(MAILBOX_COMMAND, 0); - WRITE_VREG(BUFFER_RECYCLE, 0); - - if (!H264_4K2K_SINGLE_CORE) { - WRITE_VREG(VDEC2_MAILBOX_COMMAND, 0); - WRITE_VREG(VDEC2_BUFFER_RECYCLE, 0); - } - - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); - if (!H264_4K2K_SINGLE_CORE) - CLEAR_VREG_MASK(VDEC2_MDEC_PIC_DC_CTRL, 1 << 17); - - /* set VDEC Master/ID 0 */ - WRITE_VREG(MS_ID, (1 << 7) | (0 << 0)); - if (!H264_4K2K_SINGLE_CORE) { - /* set VDEC2 Slave/ID 0 */ - WRITE_VREG(VDEC2_MS_ID, (0 << 7) | (1 << 0)); - } - WRITE_VREG(DECODE_SKIP_PICTURE, 0); - if (!H264_4K2K_SINGLE_CORE) - WRITE_VREG(VDEC2_DECODE_SKIP_PICTURE, 0); - - WRITE_VREG(PRE_MASTER_UPDATE_TIMES, 0); - WRITE_VREG(SLAVE_WAIT_DPB_UPDATE, 0); - WRITE_VREG(SLAVE_REF_DPB, 0); - WRITE_VREG(SAVE_MVC_ENTENSION_0, 0); - WRITE_VREG(SAVE_I_POC, 0); - WRITE_VREG(CORE_STATUS_M, 0); - WRITE_VREG(CORE_STATUS_S, 0); - WRITE_VREG(SAVE_ref_status_view_0, 0); - WRITE_VREG(SAVE_ref_status_view_1, 0); - WRITE_VREG(ALLOC_INFO_0, 0); - WRITE_VREG(ALLOC_INFO_1, 0); - WRITE_VREG(FATAL_ERROR, 0); - - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); - if (!H264_4K2K_SINGLE_CORE) - SET_VREG_MASK(VDEC2_MDEC_PIC_DC_CTRL, 1 << 17); - - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); - if (!H264_4K2K_SINGLE_CORE) { - WRITE_VREG(VDEC2_MDEC_PIC_DC_THRESH, 0x404038aa); - } -#ifdef DOUBLE_WRITE - WRITE_VREG(MDEC_DOUBLEW_CFG0, (0 << 31) | /* half y address */ - (1 << 30) | /* 0:No Merge 1:Automatic Merge */ - (0 << 28) | - -/* Field Picture, 0x:no skip - * 10:top only - * 11:bottom only - */ - (0 << 27) | /* Source from, 1:MCW 0:DBLK */ - (0 << 24) | /* Endian Control for Chroma */ - (0 << 18) | /* DMA ID */ - (0 << 12) | /* DMA Burst Number */ - (0 << 11) | /* DMA Urgent */ - (0 << 10) | /* 1:Round 0:Truncation */ - (1 << 9) | - -/* Size by vertical, 0:original size - * 1: 1/2 shrunken size - */ - (1 << 8) | - -/* Size by horizontal, 0:original size - * 1: 1/2 shrunken size - */ - (0 << 6) | - -/* Pixel sel by vertical, 0x:1/2 - * 10:up - * 11:down - */ - (0 << 4) | - -/* Pixel sel by horizontal, 0x:1/2 - * 10:left - * 11:right - */ - (0 << 1) | /* Endian Control for Luma */ - (1 << 0)); /* Double Write Enable */ - if (!H264_4K2K_SINGLE_CORE) { - WRITE_VREG(VDEC2_MDEC_DOUBLEW_CFG0, - (0 << 31) | /* half y address */ - (1 << 30) | - -/* 0:No Merge - * 1:Automatic Merge - */ - (0 << 28) | - -/* Field Picture, 0x:no skip - * 10:top only - * 11:bottom only - */ - (0 << 27) | /* Source from, 1:MCW 0:DBLK */ - (0 << 24) | /* Endian Control for Chroma */ - (0 << 18) | /* DMA ID */ - (0 << 12) | /* DMA Burst Number */ - (0 << 11) | /* DMA Urgent */ - (0 << 10) | /* 1:Round 0:Truncation */ - (1 << 9) | - -/* Size by vertical, - * 0:original size - * 1: 1/2 shrunken size - */ - (1 << 8) | - -/* Size by horizontal, - * 0:original size - * 1: 1/2 shrunken size - */ - (0 << 6) | - -/* Pixel sel by vertical, - * 0x:1/2 - * 10:up - * 11:down - */ - (0 << 4) | - -/* Pixel sel by horizontal, - * 0x:1/2 - * 10:left - * 11:right - */ - (0 << 1) | /* Endian Control for Luma */ - (1 << 0)); /* Double Write Enable */ - } -#endif -} - -static int vh264_4k2k_local_init(void) -{ - int i, size, ret; - -#ifdef DEBUG_PTS - pts_missed = 0; - pts_hit = 0; -#endif - mb_width_old = 0; - mb_height_old = 0; - saved_resolution = 0; - vh264_4k2k_rotation = - (((unsigned long) vh264_4k2k_amstream_dec_info.param) >> 16) - & 0xffff; - frame_width = vh264_4k2k_amstream_dec_info.width; - frame_height = vh264_4k2k_amstream_dec_info.height; - frame_dur = - (vh264_4k2k_amstream_dec_info.rate == - 0) ? 3600 : vh264_4k2k_amstream_dec_info.rate; - if (frame_width && frame_height) - frame_ar = frame_height * 0x100 / frame_width; - sync_outside = ((unsigned long) vh264_4k2k_amstream_dec_info.param - & 0x02) >> 1; - error_watchdog_count = 0; - - pr_info("H264_4K2K: decinfo: %dx%d rate=%d\n", - frame_width, frame_height, - frame_dur); - - if (frame_dur == 0) - frame_dur = 96000 / 24; - - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - vfbuf_use[i] = 0; - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &vfpool[i]; - - vfpool[i].index = DECODE_BUFFER_NUM_MAX; - kfifo_put(&newframe_q, vf); - } - - reserved_buffer = 0; - p_last_vf = NULL; - first_i_received = 0; - INIT_WORK(&alloc_work, do_alloc_work); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - - size = DECODER_WORK_SPACE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 0, - size, DRIVER_NAME, &work_space_adr); - return ret; -} - -static s32 vh264_4k2k_init(void) -{ - int ret = -1, size = -1; - char *buf = vmalloc(0x1000 * 16); - - if (buf == NULL) - return -ENOMEM; - - pr_info("\nvh264_4k2k_init\n"); - - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - ret = vh264_4k2k_local_init(); - if (ret < 0) { - vfree(buf); - return ret; - } - amvdec_enable(); - - /* -- ucode loading (amrisc and swap code) */ - mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, &mc_dma_handle, GFP_KERNEL); - if (!mc_cpu_addr) { - amvdec_disable(); - vfree(buf); - pr_err("vh264_4k2k init: Can not allocate mc memory.\n"); - return -ENOMEM; - } - - WRITE_VREG(AV_SCRATCH_L, mc_dma_handle); - if (!H264_4K2K_SINGLE_CORE) - WRITE_VREG(VDEC2_AV_SCRATCH_L, mc_dma_handle); - - if (H264_4K2K_SINGLE_CORE) - size = get_firmware_data(VIDEO_DEC_H264_4k2K_SINGLE, buf); - else - size = get_firmware_data(VIDEO_DEC_H264_4k2K, buf); - - if (size < 0) { - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - if (H264_4K2K_SINGLE_CORE) - ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, "single_core", buf); - else - ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf); - - if (ret < 0) { - amvdec_disable(); - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - pr_err("H264_4K2K: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - if (!H264_4K2K_SINGLE_CORE) { - amvdec2_enable(); - - if (amvdec2_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf) < 0) { - amvdec_disable(); - amvdec2_disable(); - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - return -EBUSY; - } - } - - /*header*/ - memcpy((u8 *) mc_cpu_addr, buf + 0x1000, 0x1000); - - /*mmco*/ - memcpy((u8 *) mc_cpu_addr + 0x1000, buf + 0x2000, 0x2000); - - /*slice*/ - memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - vh264_4k2k_prot_init(); - - if (vdec_request_irq(VDEC_IRQ_1, vh264_4k2k_isr, - "vh264_4k2k-irq", (void *)vh264_4k2k_dec_id)) { - pr_info("vh264_4k2k irq register error.\n"); - amvdec_disable(); - if (!H264_4K2K_SINGLE_CORE) - amvdec2_disable(); - - return -ENOENT; - } -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (!H264_4K2K_SINGLE_CORE) { - if (vdec_request_irq(VDEC_IRQ_0, vh264_4k2k_vdec2_isr, - "vh264_4k2k-vdec2-irq", - (void *)vh264_4k2k_dec_id2)) { - pr_info("vh264_4k2k irq register error.\n"); - vdec_free_irq(VDEC_IRQ_1, (void *)vh264_4k2k_dec_id); - amvdec_disable(); - amvdec2_disable(); - return -ENOENT; - } - } -#endif - - stat |= STAT_ISR_REG; - - vf_provider_init(&vh264_4k2k_vf_prov, PROVIDER_NAME, - &vh264_4k2k_vf_provider, NULL); - vf_reg_provider(&vh264_4k2k_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); - - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long) - vh264_4k2k_amstream_dec_info.rate)); - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong) (&recycle_timer); - recycle_timer.function = vh264_4k2k_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - if (!H264_4K2K_SINGLE_CORE) - amvdec2_start(); - - stat |= STAT_VDEC_RUN; - - ret = vh264_4k2k_vdec_info_init(); - if (0 != ret) - return -ret; - - return 0; -} - -static int vh264_4k2k_stop(void) -{ - - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - if (!H264_4K2K_SINGLE_CORE) - amvdec2_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 0); - if (!H264_4K2K_SINGLE_CORE) - WRITE_VREG(VDEC2_ASSIST_MBOX0_MASK, 0); - - vdec_free_irq(VDEC_IRQ_1, (void *)vh264_4k2k_dec_id); -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (!H264_4K2K_SINGLE_CORE) - vdec_free_irq(VDEC_IRQ_0, (void *)vh264_4k2k_dec_id2); -#endif - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - if (stat & STAT_VF_HOOK) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); - - vf_unreg_provider(&vh264_4k2k_vf_prov); - stat &= ~STAT_VF_HOOK; - } -#ifdef DOUBLE_WRITE - WRITE_VREG(MDEC_DOUBLEW_CFG0, 0); - if (!H264_4K2K_SINGLE_CORE) - WRITE_VREG(VDEC2_MDEC_DOUBLEW_CFG0, 0); -#endif - - if (stat & STAT_MC_LOAD) { - if (mc_cpu_addr != NULL) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - } - - stat &= ~STAT_MC_LOAD; - } - - amvdec_disable(); - if (!H264_4K2K_SINGLE_CORE) - amvdec2_disable(); -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - msleep(100); -#endif - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - return 0; -} - -void vh264_4k_free_cmabuf(void) -{ - int i; - - if (atomic_read(&vh264_4k2k_active)) - return; - mutex_lock(&vh264_4k2k_mutex); - for (i = 0; i < ARRAY_SIZE(buffer_spec); i++) { - if (buffer_spec[i].phy_addr) { - codec_mm_free_for_dma(MEM_NAME, - buffer_spec[i].phy_addr); - buffer_spec[i].phy_addr = 0; - buffer_spec[i].alloc_pages = NULL; - buffer_spec[i].alloc_count = 0; - pr_info("force free CMA buffer %d\n", i); - } - } - mutex_unlock(&vh264_4k2k_mutex); -} - -static int amvdec_h264_4k2k_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - pr_info("amvdec_h264_4k2k probe start.\n"); - - mutex_lock(&vh264_4k2k_mutex); - - fatal_error = 0; - - if (pdata == NULL) { - pr_info("\namvdec_h264_4k2k memory resource undefined.\n"); - mutex_unlock(&vh264_4k2k_mutex); - return -EFAULT; - } - - if (pdata->sys_info) - vh264_4k2k_amstream_dec_info = *pdata->sys_info; - cma_dev = pdata->cma_dev; - - pr_info(" sysinfo: %dx%d, rate = %d, param = 0x%lx\n", - vh264_4k2k_amstream_dec_info.width, - vh264_4k2k_amstream_dec_info.height, - vh264_4k2k_amstream_dec_info.rate, - (unsigned long) vh264_4k2k_amstream_dec_info.param); - - if (!H264_4K2K_SINGLE_CORE) { - if (vdec_on(VDEC_2)) { /* ++++ */ - vdec_poweroff(VDEC_2); /* ++++ */ - mdelay(10); - } - vdec_poweron(VDEC_2); - } - - - if (!H264_4K2K_SINGLE_CORE) - vdec2_power_mode(1); - - pdata->dec_status = vh264_4k2k_dec_status; - if (H264_4K2K_SINGLE_CORE) - pdata->set_trickmode = vh264_4k2k_set_trickmode; - - if (vh264_4k2k_init() < 0) { - pr_info("\namvdec_h264_4k2k init failed.\n"); - mutex_unlock(&vh264_4k2k_mutex); - kfree(gvs); - gvs = NULL; - - return -ENODEV; - } -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ - request_vpu_clk_vmod(360000000, VPU_VIU_VD1); -#endif - - if (probe_callback) - probe_callback(); - /*set the max clk for smooth playing...*/ - vdec_source_changed(VFORMAT_H264_4K2K, - 4096, 2048, 30); - INIT_WORK(&set_clk_work, vh264_4k2k_set_clk); - - atomic_set(&vh264_4k2k_active, 1); - mutex_unlock(&vh264_4k2k_mutex); - - return 0; -} - -static int amvdec_h264_4k2k_remove(struct platform_device *pdev) -{ - cancel_work_sync(&alloc_work); - cancel_work_sync(&set_clk_work); - mutex_lock(&vh264_4k2k_mutex); - atomic_set(&vh264_4k2k_active, 0); - - vh264_4k2k_stop(); - - vdec_source_changed(VFORMAT_H264_4K2K, 0, 0, 0); - - if (!H264_4K2K_SINGLE_CORE) { - vdec_poweroff(VDEC_2); - } -#ifdef DEBUG_PTS - pr_info("pts missed %ld, pts hit %ld, duration %d\n", - pts_missed, pts_hit, frame_dur); -#endif - - if (remove_callback) - remove_callback(); - - mutex_unlock(&vh264_4k2k_mutex); - - kfree(gvs); - gvs = NULL; - - pr_info("amvdec_h264_4k2k_remove\n"); - return 0; -} - -void vh264_4k2k_register_module_callback(void (*enter_func)(void), - void (*remove_func)(void)) -{ - probe_callback = enter_func; - remove_callback = remove_func; -} -EXPORT_SYMBOL(vh264_4k2k_register_module_callback); - -/****************************************/ - -static struct platform_driver amvdec_h264_4k2k_driver = { - .probe = amvdec_h264_4k2k_probe, - .remove = amvdec_h264_4k2k_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_h264_4k2k_profile = { - .name = "h264_4k2k", - .profile = "" -}; -static struct mconfig h264_4k2k_configs[] = { - MC_PU32("stat", &stat), - MC_PU32("error_recovery_mode", &error_recovery_mode), -}; -static struct mconfig_node h264_4k2k_node; - -static int __init amvdec_h264_4k2k_driver_init_module(void) -{ - pr_debug("amvdec_h264_4k2k module init\n"); - - if (platform_driver_register(&amvdec_h264_4k2k_driver)) { - pr_err("failed to register amvdec_h264_4k2k driver\n"); - return -ENODEV; - } - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXTVBB) - vcodec_profile_register(&amvdec_h264_4k2k_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &h264_4k2k_node, - "h264_4k2k", h264_4k2k_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_h264_4k2k_driver_remove_module(void) -{ - pr_debug("amvdec_h264_4k2k module remove.\n"); - - platform_driver_unregister(&amvdec_h264_4k2k_driver); -} - -/****************************************/ - -module_param(stat, uint, 0664); -MODULE_PARM_DESC(stat, "\n amvdec_h264_4k2k stat\n"); - -module_param(error_recovery_mode, uint, 0664); -MODULE_PARM_DESC(error_recovery_mode, "\n amvdec_h264 error_recovery_mode\n"); - -module_init(amvdec_h264_4k2k_driver_init_module); -module_exit(amvdec_h264_4k2k_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC h264_4k2k Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c deleted file mode 100644 index 5181a459bd2a..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c +++ /dev/null @@ -1,1732 +0,0 @@ -/* - * drivers/amlogic/amports/vh264mvc.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../utils/vdec.h" -#include "../utils/amvdec.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include "../utils/firmware.h" -#include - -#define TIME_TASK_PRINT_ENABLE 0x100 -#define PUT_PRINT_ENABLE 0x200 - -#define DRIVER_NAME "amvdec_h264mvc" -#define MODULE_NAME "amvdec_h264mvc" - -#define HANDLE_h264mvc_IRQ - -#define DEBUG_PTS -#define DEBUG_SKIP - -#define PUT_INTERVAL (HZ/100) - -#define STAT_TIMER_INIT 0x01 -#define STAT_MC_LOAD 0x02 -#define STAT_ISR_REG 0x04 -#define STAT_VF_HOOK 0x08 -#define STAT_TIMER_ARM 0x10 -#define STAT_VDEC_RUN 0x20 - -#define DROPPING_THREAD_HOLD 4 -#define DROPPING_FIRST_WAIT 16 -#define DISPLAY_INVALID_POS -65536 - -#define INIT_DROP_FRAME_CNT 8 - -static int vh264mvc_vf_states(struct vframe_states *states, void *); -static struct vframe_s *vh264mvc_vf_peek(void *); -static struct vframe_s *vh264mvc_vf_get(void *); -static void vh264mvc_vf_put(struct vframe_s *, void *); -static int vh264mvc_event_cb(int type, void *data, void *private_data); - -static void vh264mvc_prot_init(void); -static int vh264mvc_local_init(void); -static void vh264mvc_put_timer_func(unsigned long arg); - -static const char vh264mvc_dec_id[] = "vh264mvc-dev"; - -#define PROVIDER_NAME "decoder.h264mvc" - -static struct vdec_info *gvs; -static struct work_struct alloc_work; -static struct work_struct set_clk_work; - -static DEFINE_MUTEX(vh264_mvc_mutex); - -static const struct vframe_operations_s vh264mvc_vf_provider = { - .peek = vh264mvc_vf_peek, - .get = vh264mvc_vf_get, - .put = vh264mvc_vf_put, - .event_cb = vh264mvc_event_cb, - .vf_states = vh264mvc_vf_states, -}; - -static struct vframe_provider_s vh264mvc_vf_prov; - -static u32 frame_width, frame_height, frame_dur; -static u32 saved_resolution; -static struct timer_list recycle_timer; -static u32 stat; -static u32 pts_outside; -static u32 sync_outside; -static u32 vh264mvc_ratio; -static u32 h264mvc_ar; -static u32 no_dropping_cnt; -static s32 init_drop_cnt; - -#ifdef DEBUG_SKIP -static unsigned long view_total, view_dropped; -#endif - -#ifdef DEBUG_PTS -static unsigned long pts_missed, pts_hit; -#endif - -static atomic_t vh264mvc_active = ATOMIC_INIT(0); -static struct work_struct error_wd_work; - -static struct dec_sysinfo vh264mvc_amstream_dec_info; -static dma_addr_t mc_dma_handle; -static void *mc_cpu_addr; - -static DEFINE_SPINLOCK(lock); - -static int vh264mvc_stop(void); -static s32 vh264mvc_init(void); - -/*************************** - * new - ************************** - */ - -/* bit[3:0] command : */ -/* 0 - command finished */ -/* (DATA0 - {level_idc_mmco, max_reference_frame_num, width, height} */ -/* 1 - alloc view_0 display_buffer and reference_data_area */ -/* 2 - alloc view_1 display_buffer and reference_data_area */ -#define MAILBOX_COMMAND AV_SCRATCH_0 -#define MAILBOX_DATA_0 AV_SCRATCH_1 -#define MAILBOX_DATA_1 AV_SCRATCH_2 -#define MAILBOX_DATA_2 AV_SCRATCH_3 -#define CANVAS_START AV_SCRATCH_6 -#define BUFFER_RECYCLE AV_SCRATCH_7 -#define DROP_CONTROL AV_SCRATCH_8 -#define PICTURE_COUNT AV_SCRATCH_9 -#define DECODE_STATUS AV_SCRATCH_A -#define SPS_STATUS AV_SCRATCH_B -#define PPS_STATUS AV_SCRATCH_C -#define SIM_RESERV_D AV_SCRATCH_D -#define WORKSPACE_START AV_SCRATCH_E -#define SIM_RESERV_F AV_SCRATCH_F -#define DECODE_ERROR_CNT AV_SCRATCH_G -#define CURRENT_UCODE AV_SCRATCH_H -#define CURRENT_SPS_PPS AV_SCRATCH_I/* bit[15:9]-SPS, bit[8:0]-PPS */ -#define DECODE_SKIP_PICTURE AV_SCRATCH_J -#define UCODE_START_ADDR AV_SCRATCH_K -#define SIM_RESERV_L AV_SCRATCH_L -#define REF_START_VIEW_0 AV_SCRATCH_M -#define REF_START_VIEW_1 AV_SCRATCH_N - -/******************************************** - * Mailbox command - ********************************************/ -#define CMD_FINISHED 0 -#define CMD_ALLOC_VIEW_0 1 -#define CMD_ALLOC_VIEW_1 2 -#define CMD_FRAME_DISPLAY 3 -#define CMD_FATAL_ERROR 4 - -#define CANVAS_INDEX_START 0x78 -/* /AMVDEC_H264MVC_CANVAS_INDEX */ - -#define MC_TOTAL_SIZE (28*SZ_1K) -#define MC_SWAP_SIZE (4*SZ_1K) - -unsigned int DECODE_BUFFER_START = 0x00200000; -unsigned int DECODE_BUFFER_END = 0x05000000; - -#define DECODE_BUFFER_NUM_MAX 16 -#define DISPLAY_BUFFER_NUM 4 -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + DISPLAY_BUFFER_NUM) -#define TOTAL_BMMU_BUFF_NUM (MAX_BMMU_BUFFER_NUM * 2 + 3) -#define VF_BUFFER_IDX(n) (2 + n) - -#define DECODER_WORK_SPACE_SIZE 0xa0000 - - -static unsigned int ANC_CANVAS_ADDR; -static unsigned int index; -static unsigned long ref_start_addr[2]; -static unsigned int max_dec_frame_buffering[2]; -static unsigned int total_dec_frame_buffering[2]; - -static unsigned int dpb_size, ref_size; - -static int display_buff_id; -static int display_view_id; -static int display_POC; -static int stream_offset; - -#define video_domain_addr(adr) (adr&0x7fffffff) -static unsigned long work_space_adr; - -struct buffer_spec_s { - unsigned int y_addr; - unsigned int u_addr; - unsigned int v_addr; - - int y_canvas_index; - int u_canvas_index; - int v_canvas_index; - - struct page *alloc_pages; - unsigned long phy_addr; - int alloc_count; -}; -static struct buffer_spec_s buffer_spec0[MAX_BMMU_BUFFER_NUM]; -static struct buffer_spec_s buffer_spec1[MAX_BMMU_BUFFER_NUM]; -static void *mm_blk_handle; - -/* - * dbg_mode: - * bit 0: 1, print debug information - * bit 4: 1, recycle buffer without displaying; - * bit 5: 1, buffer single frame step , set dbg_cmd to 1 to step - * - */ -static int dbg_mode; -static int dbg_cmd; -static int view_mode = - 3; /* 0, left; 1 ,right ; 2, left<->right 3, right<->left */ -static int drop_rate = 2; -static int drop_thread_hold; -/**/ - -struct mvc_buf_s { - struct list_head list; - struct vframe_s vframe; - int display_POC; - int view0_buff_id; - int view1_buff_id; - int view0_drop; - int view1_drop; - int stream_offset; - unsigned int pts; -} /*mvc_buf_t */; - -#define spec2canvas(x) \ - (((x)->v_canvas_index << 16) | \ - ((x)->u_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - -#define to_mvcbuf(vf) \ - container_of(vf, struct mvc_buf_s, vframe) - -static int vf_buf_init_flag; - -static void init_vf_buf(void) -{ - - vf_buf_init_flag = 1; -} - -static void uninit_vf_buf(void) -{ - -} - -/* #define QUEUE_SUPPORT */ - -struct mvc_info_s { - int view0_buf_id; - int view1_buf_id; - int view0_drop; - int view1_drop; - int display_pos; - int used; - int slot; - unsigned int stream_offset; -}; - -#define VF_POOL_SIZE 20 -static struct vframe_s vfpool[VF_POOL_SIZE]; -static struct mvc_info_s vfpool_idx[VF_POOL_SIZE]; -static s32 view0_vfbuf_use[DECODE_BUFFER_NUM_MAX]; -static s32 view1_vfbuf_use[DECODE_BUFFER_NUM_MAX]; - -static s32 fill_ptr, get_ptr, putting_ptr, put_ptr; -static s32 dirty_frame_num; -static s32 enable_recycle; - -static s32 init_drop_frame_id[INIT_DROP_FRAME_CNT]; -#define INCPTR(p) ptr_atomic_wrap_inc(&p) -static inline void ptr_atomic_wrap_inc(u32 *ptr) -{ - u32 i = *ptr; - - i++; - - if (i >= VF_POOL_SIZE) - i = 0; - - *ptr = i; -} - -static void set_frame_info(struct vframe_s *vf) -{ - unsigned int ar = 0; - - vf->width = frame_width; - vf->height = frame_height; - vf->duration = frame_dur; - vf->duration_pulldown = 0; - - if (vh264mvc_ratio == 0) { - /* always stretch to 16:9 */ - vf->ratio_control |= (0x90 << - DISP_RATIO_ASPECT_RATIO_BIT); - } else { - /* h264mvc_ar = ((float)frame_height/frame_width) - *customer_ratio; - */ - ar = min_t(u32, h264mvc_ar, DISP_RATIO_ASPECT_RATIO_MAX); - - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - } -} - -static int vh264mvc_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&lock, flags); - states->vf_pool_size = VF_POOL_SIZE; - - i = put_ptr - fill_ptr; - if (i < 0) - i += VF_POOL_SIZE; - states->buf_free_num = i; - - i = putting_ptr - put_ptr; - if (i < 0) - i += VF_POOL_SIZE; - states->buf_recycle_num = i; - - i = fill_ptr - get_ptr; - if (i < 0) - i += VF_POOL_SIZE; - states->buf_avail_num = i; - - spin_unlock_irqrestore(&lock, flags); - return 0; -} - -void send_drop_cmd(void) -{ - int ready_cnt = 0; - int temp_get_ptr = get_ptr; - int temp_fill_ptr = fill_ptr; - - while (temp_get_ptr != temp_fill_ptr) { - if ((vfpool_idx[temp_get_ptr].view0_buf_id >= 0) - && (vfpool_idx[temp_get_ptr].view1_buf_id >= 0) - && (vfpool_idx[temp_get_ptr].view0_drop == 0) - && (vfpool_idx[temp_get_ptr].view1_drop == 0)) - ready_cnt++; - INCPTR(temp_get_ptr); - } - if (dbg_mode & 0x40) { - pr_info("ready_cnt is %d ; no_dropping_cnt is %d\n", ready_cnt, - no_dropping_cnt); - } - if ((no_dropping_cnt >= DROPPING_FIRST_WAIT) - && (ready_cnt < drop_thread_hold)) - WRITE_VREG(DROP_CONTROL, (1 << 31) | (drop_rate)); - else - WRITE_VREG(DROP_CONTROL, 0); -} - -#if 0 -int get_valid_frame(void) -{ - int ready_cnt = 0; - int temp_get_ptr = get_ptr; - int temp_fill_ptr = fill_ptr; - - while (temp_get_ptr != temp_fill_ptr) { - if ((vfpool_idx[temp_get_ptr].view0_buf_id >= 0) - && (vfpool_idx[temp_get_ptr].view1_buf_id >= 0) - && (vfpool_idx[temp_get_ptr].view0_drop == 0) - && (vfpool_idx[temp_get_ptr].view1_drop == 0)) - ready_cnt++; - INCPTR(temp_get_ptr); - } - return ready_cnt; -} -#endif -static struct vframe_s *vh264mvc_vf_peek(void *op_arg) -{ - - if (get_ptr == fill_ptr) - return NULL; - send_drop_cmd(); - return &vfpool[get_ptr]; - -} - -static struct vframe_s *vh264mvc_vf_get(void *op_arg) -{ - - struct vframe_s *vf; - int view0_buf_id; - int view1_buf_id; - - if (get_ptr == fill_ptr) - return NULL; - - view0_buf_id = vfpool_idx[get_ptr].view0_buf_id; - view1_buf_id = vfpool_idx[get_ptr].view1_buf_id; - vf = &vfpool[get_ptr]; - - if ((view0_buf_id >= 0) && (view1_buf_id >= 0)) { - if (view_mode == 0 || view_mode == 1) { - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - vf->canvas0Addr = vf->canvas1Addr = - (view_mode == - 0) ? spec2canvas(&buffer_spec0[view0_buf_id]) : - spec2canvas(&buffer_spec1[view1_buf_id]); - } else { - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_MVC; - - vf->left_eye.start_x = 0; - vf->left_eye.start_y = 0; - vf->left_eye.width = vf->width; - vf->left_eye.height = vf->height; - vf->right_eye.start_x = 0; - vf->right_eye.start_y = 0; - vf->right_eye.width = vf->width; - vf->right_eye.height = vf->height; - vf->trans_fmt = TVIN_TFMT_3D_TB; - - if (view_mode == 2) { - vf->canvas0Addr = - spec2canvas(&buffer_spec1[ - view1_buf_id]); - vf->canvas1Addr = - spec2canvas(&buffer_spec0[ - view0_buf_id]); - } else { - vf->canvas0Addr = - spec2canvas(&buffer_spec0[ - view0_buf_id]); - vf->canvas1Addr = - spec2canvas(&buffer_spec1[ - view1_buf_id]); - } - } - } - vf->type_original = vf->type; - if (((vfpool_idx[get_ptr].view0_drop != 0) - || (vfpool_idx[get_ptr].view1_drop != 0)) - && ((no_dropping_cnt >= DROPPING_FIRST_WAIT))) - vf->frame_dirty = 1; - else - vf->frame_dirty = 0; - - INCPTR(get_ptr); - - if (frame_width == 0) - frame_width = vh264mvc_amstream_dec_info.width; - if (frame_height == 0) - frame_height = vh264mvc_amstream_dec_info.height; - - vf->width = frame_width; - vf->height = frame_height; - - if ((no_dropping_cnt < DROPPING_FIRST_WAIT) && (vf->frame_dirty == 0)) - no_dropping_cnt++; - return vf; - -} - -static void vh264mvc_vf_put(struct vframe_s *vf, void *op_arg) -{ - - if (vf_buf_init_flag == 0) - return; - if (vf->frame_dirty) { - - vf->frame_dirty = 0; - dirty_frame_num++; - enable_recycle = 0; - if (dbg_mode & PUT_PRINT_ENABLE) { - pr_info("invalid: dirty_frame_num is !!! %d\n", - dirty_frame_num); - } - } else { - INCPTR(putting_ptr); - while (dirty_frame_num > 0) { - INCPTR(putting_ptr); - dirty_frame_num--; - } - enable_recycle = 1; - if (dbg_mode & PUT_PRINT_ENABLE) { - pr_info("valid: dirty_frame_num is @@@ %d\n", - dirty_frame_num); - } - /* send_drop_cmd(); */ - } - -} - -static int vh264mvc_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vh264mvc_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vh264mvc_local_init(); - vh264mvc_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vh264mvc_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -/**/ -static long init_canvas(int view_index, int refbuf_size, long dpb_size, - int dpb_number, int mb_width, int mb_height, - struct buffer_spec_s *buffer_spec) -{ - - unsigned long addr; - int i, j, bmmu_index; - int mb_total, ret = -1; - /* cav_con canvas; */ - mb_total = mb_width * mb_height; - mutex_lock(&vh264_mvc_mutex); - - for (j = 0; j < (dpb_number + 1); j++) { - int page_count; - if (j == 0) { - if (!view_index) - bmmu_index = 1; - else - bmmu_index = dpb_number + 2; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, - bmmu_index, refbuf_size, DRIVER_NAME, - &ref_start_addr[view_index]); - - if (ret < 0) { - mutex_unlock(&vh264_mvc_mutex); - return ret; - } - - continue; - } - /* canvas buf */ - WRITE_VREG(ANC_CANVAS_ADDR, - index | ((index + 1) << 8) | - ((index + 2) << 16)); - ANC_CANVAS_ADDR++; - - i = j - 1; - if (!view_index) - bmmu_index = VF_BUFFER_IDX(i); - else - bmmu_index = VF_BUFFER_IDX(i) + dpb_number + 1; -#ifdef DOUBLE_WRITE - page_count = PAGE_ALIGN((mb_total << 8) + (mb_total << 7) + - (mb_total << 6) + (mb_total << 5)) / PAGE_SIZE; -#else - page_count = PAGE_ALIGN((mb_total << 8) + - (mb_total << 7)) / PAGE_SIZE; -#endif - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, - bmmu_index, page_count << PAGE_SHIFT, - DRIVER_NAME, &buffer_spec[i].phy_addr); - - if (ret < 0) { - buffer_spec[i].alloc_count = 0; - mutex_unlock(&vh264_mvc_mutex); - return ret; - } - - addr = buffer_spec[i].phy_addr; - buffer_spec[i].alloc_count = page_count; - buffer_spec[i].y_addr = addr; - buffer_spec[i].y_canvas_index = index; - canvas_config(index, addr, - mb_width << 4, mb_height << 4, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - addr += mb_total << 8; - index++; - buffer_spec[i].u_addr = addr; - buffer_spec[i].u_canvas_index = index; - canvas_config(index, addr, mb_width << 3, mb_height << 3, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - addr += mb_total << 6; - index++; - buffer_spec[i].v_addr = addr; - buffer_spec[i].v_canvas_index = index; - canvas_config(index, addr, mb_width << 3, mb_height << 3, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - index++; - } - mutex_unlock(&vh264_mvc_mutex); - return 0; -} - -static int get_max_dec_frame_buf_size(int level_idc, - int max_reference_frame_num, int mb_width, - int mb_height) -{ - int pic_size = mb_width * mb_height * 384; - - int size = 0; - - switch (level_idc) { - case 9: - size = 152064; - break; - case 10: - size = 152064; - break; - case 11: - size = 345600; - break; - case 12: - size = 912384; - break; - case 13: - size = 912384; - break; - case 20: - size = 912384; - break; - case 21: - size = 1824768; - break; - case 22: - size = 3110400; - break; - case 30: - size = 3110400; - break; - case 31: - size = 6912000; - break; - case 32: - size = 7864320; - break; - case 40: - size = 12582912; - break; - case 41: - size = 12582912; - break; - case 42: - size = 13369344; - break; - case 50: - size = 42393600; - break; - case 51: - size = 70778880; - break; - default: - break; - } - - size /= pic_size; - size = size + 1; /* For MVC need onr more buffer */ - if (max_reference_frame_num > size) - size = max_reference_frame_num; - if (size > DECODE_BUFFER_NUM_MAX) - size = DECODE_BUFFER_NUM_MAX; - - return size; -} - -int check_in_list(int pos, int *slot) -{ - int i; - int ret = 0; - - for (i = 0; i < VF_POOL_SIZE; i++) { - if ((vfpool_idx[i].display_pos == pos) - && (vfpool_idx[i].used == 0)) { - ret = 1; - *slot = vfpool_idx[i].slot; - break; - } - } - return ret; -} - -static void do_alloc_work(struct work_struct *work) -{ - int level_idc, max_reference_frame_num, mb_width, mb_height; - int refbuf_size; - int ret = READ_VREG(MAILBOX_COMMAND); - - switch (ret & 0xff) { - case CMD_ALLOC_VIEW_0: - if (dbg_mode & 0x1) { - pr_info - ("Start H264 display buffer for view 0\n"); - } - - ret = READ_VREG(MAILBOX_DATA_0); - level_idc = (ret >> 24) & 0xff; - max_reference_frame_num = (ret >> 16) & 0xff; - mb_width = (ret >> 8) & 0xff; - mb_height = (ret >> 0) & 0xff; - max_dec_frame_buffering[0] = - get_max_dec_frame_buf_size(level_idc, - max_reference_frame_num, - mb_width, mb_height); - - total_dec_frame_buffering[0] = - max_dec_frame_buffering[0] + DISPLAY_BUFFER_NUM; - - mb_width = (mb_width + 3) & 0xfffffffc; - mb_height = (mb_height + 3) & 0xfffffffc; - - dpb_size = mb_width * mb_height * 384; - ref_size = mb_width * mb_height * 96; - - if (dbg_mode & 0x1) { - pr_info("dpb_size: 0x%x\n", dpb_size); - pr_info("ref_size: 0x%x\n", ref_size); - pr_info("total_dec_frame_buffering[0] : 0x%x\n", - total_dec_frame_buffering[0]); - pr_info("max_reference_frame_num: 0x%x\n", - max_reference_frame_num); - } - refbuf_size - = ref_size * (max_reference_frame_num + 1) * 2; - - index = CANVAS_INDEX_START; - ANC_CANVAS_ADDR = ANC0_CANVAS_ADDR; - - ret = - init_canvas(0, refbuf_size, dpb_size, - total_dec_frame_buffering[0], mb_width, - mb_height, buffer_spec0); - - if (ret < 0) { - pr_info(" Un-expected memory alloc problem\n"); - return; - } - - WRITE_VREG(REF_START_VIEW_0, - video_domain_addr(ref_start_addr[0])); - WRITE_VREG(MAILBOX_DATA_0, - (max_dec_frame_buffering[0] << 8) | - (total_dec_frame_buffering[0] << 0)); - WRITE_VREG(MAILBOX_DATA_1, ref_size); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - - if (dbg_mode & 0x1) { - pr_info - ("End H264 display buffer for view 0\n"); - } - if (frame_width == 0) { - if (vh264mvc_amstream_dec_info.width) - frame_width = vh264mvc_amstream_dec_info.width; - else - frame_width = mb_width << 4; - } - if (frame_height == 0) { - frame_height = mb_height << 4; - if (frame_height == 1088) - frame_height = 1080; - } - break; - case CMD_ALLOC_VIEW_1: - if (dbg_mode & 0x1) { - pr_info - ("Start H264 display buffer for view 1\n"); - } - - ret = READ_VREG(MAILBOX_DATA_0); - level_idc = (ret >> 24) & 0xff; - max_reference_frame_num = (ret >> 16) & 0xff; - mb_width = (ret >> 8) & 0xff; - mb_height = (ret >> 0) & 0xff; - max_dec_frame_buffering[1] = - get_max_dec_frame_buf_size(level_idc, - max_reference_frame_num, - mb_width, mb_height); - if (max_dec_frame_buffering[1] != max_dec_frame_buffering[0]) { - pr_info - (" Warning: view0/1 max_dec_frame_buffering "); - pr_info("different : 0x%x/0x%x, Use View0\n", - max_dec_frame_buffering[0], - max_dec_frame_buffering[1]); - max_dec_frame_buffering[1] = max_dec_frame_buffering[0]; - } - - total_dec_frame_buffering[1] = - max_dec_frame_buffering[1] + DISPLAY_BUFFER_NUM; - - mb_width = (mb_width + 3) & 0xfffffffc; - mb_height = (mb_height + 3) & 0xfffffffc; - - dpb_size = mb_width * mb_height * 384; - ref_size = mb_width * mb_height * 96; - refbuf_size = ref_size * (max_reference_frame_num + 1) * 2; - if (dbg_mode & 0x1) { - pr_info("dpb_size: 0x%x\n", dpb_size); - pr_info("ref_size: 0x%x\n", ref_size); - pr_info("total_dec_frame_buffering[1] : 0x%x\n", - total_dec_frame_buffering[1]); - pr_info("max_reference_frame_num: 0x%x\n", - max_reference_frame_num); - } - - index = CANVAS_INDEX_START + total_dec_frame_buffering[0] * 3; - ANC_CANVAS_ADDR = - ANC0_CANVAS_ADDR + total_dec_frame_buffering[0]; - - ret = init_canvas(1, refbuf_size, dpb_size, - total_dec_frame_buffering[1], mb_width, - mb_height, buffer_spec1); - - if (ret < 0) { - pr_info(" Un-expected memory alloc problem\n"); - return; - } - - WRITE_VREG(REF_START_VIEW_1, - video_domain_addr(ref_start_addr[1])); - WRITE_VREG(MAILBOX_DATA_0, - (max_dec_frame_buffering[1] << 8) | - (total_dec_frame_buffering[1] << 0)); - WRITE_VREG(MAILBOX_DATA_1, ref_size); - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - - if (dbg_mode & 0x1) { - pr_info - ("End H264 buffer allocation for view 1\n"); - } - if (frame_width == 0) { - if (vh264mvc_amstream_dec_info.width) - frame_width = vh264mvc_amstream_dec_info.width; - else - frame_width = mb_width << 4; - } - if (frame_height == 0) { - frame_height = mb_height << 4; - if (frame_height == 1088) - frame_height = 1080; - } - break; - } - -} - - -#ifdef HANDLE_h264mvc_IRQ -static irqreturn_t vh264mvc_isr(int irq, void *dev_id) -#else -static void vh264mvc_isr(void) -#endif -{ - int drop_status; - struct vframe_s *vf; - unsigned int pts, pts_valid = 0; - u64 pts_us64; - u32 frame_size; - int ret = READ_VREG(MAILBOX_COMMAND); - /* pr_info("vh264mvc_isr, cmd =%x\n", ret); */ - switch (ret & 0xff) { - case CMD_ALLOC_VIEW_0: - case CMD_ALLOC_VIEW_1: - schedule_work(&alloc_work); - break; - case CMD_FRAME_DISPLAY: - ret = READ_VREG(MAILBOX_DATA_0); - display_buff_id = (ret >> 0) & 0x3f; - display_view_id = (ret >> 6) & 0x3; - drop_status = (ret >> 8) & 0x1; - display_POC = READ_VREG(MAILBOX_DATA_1); - stream_offset = READ_VREG(MAILBOX_DATA_2); - /* if (display_view_id == 0) */ - WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); - -#ifdef DEBUG_SKIP - view_total++; - if (drop_status) - view_dropped++; -#endif - if (dbg_mode & 0x1) { - pr_info - (" H264 display frame ready - View : %x, Buffer : %x\n", - display_view_id, display_buff_id); - pr_info - (" H264 display frame POC -- Buffer : %x, POC : %x\n", - display_buff_id, display_POC); - pr_info("H264 display frame ready\n"); - } - if (dbg_mode & 0x10) { - if ((dbg_mode & 0x20) == 0) { - while (READ_VREG(BUFFER_RECYCLE) != 0) - ; - WRITE_VREG(BUFFER_RECYCLE, - (display_view_id << 8) | - (display_buff_id + 1)); - display_buff_id = -1; - display_view_id = -1; - display_POC = -1; - } - } else { - unsigned char in_list_flag = 0; - - int slot = 0; - - in_list_flag = check_in_list(display_POC, &slot); - - if ((dbg_mode & 0x40) && (drop_status)) { - pr_info - ("drop_status:%dview_id=%d,buff_id=%d,", - drop_status, display_view_id, display_buff_id); - pr_info - ("offset=%d, display_POC = %d,fill_ptr=0x%x\n", - stream_offset, display_POC, fill_ptr); - } - - if ((in_list_flag) && (stream_offset != 0)) { - pr_info - ("error case ,display_POC is %d, slot is %d\n", - display_POC, slot); - in_list_flag = 0; - } - if (!in_list_flag) { - if (display_view_id == 0) { - vfpool_idx[fill_ptr].view0_buf_id = - display_buff_id; - view0_vfbuf_use[display_buff_id]++; - vfpool_idx[fill_ptr].stream_offset = - stream_offset; - vfpool_idx[fill_ptr].view0_drop = - drop_status; - } - if (display_view_id == 1) { - vfpool_idx[fill_ptr].view1_buf_id = - display_buff_id; - vfpool_idx[fill_ptr].view1_drop = - drop_status; - view1_vfbuf_use[display_buff_id]++; - } - vfpool_idx[fill_ptr].slot = fill_ptr; - vfpool_idx[fill_ptr].display_pos = display_POC; - - } else { - if (display_view_id == 0) { - vfpool_idx[slot].view0_buf_id = - display_buff_id; - view0_vfbuf_use[display_buff_id]++; - vfpool_idx[slot].stream_offset = - stream_offset; - vfpool_idx[slot].view0_drop = - drop_status; - - } - if (display_view_id == 1) { - vfpool_idx[slot].view1_buf_id = - display_buff_id; - view1_vfbuf_use[display_buff_id]++; - vfpool_idx[slot].view1_drop = - drop_status; - } - vf = &vfpool[slot]; - - if (display_view_id == 0) { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(display_buff_id)); - - } else if (display_view_id == 1) { - vf->mem_head_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(display_buff_id)); - - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - VF_BUFFER_IDX(display_buff_id) - + total_dec_frame_buffering[0] - + 1); - } - - - - if (vfpool_idx[slot].stream_offset == 0) { - pr_info - ("error case, invalid stream offset\n"); - } - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, - vfpool_idx[slot].stream_offset, &pts, - &frame_size, - 0x10000, &pts_us64) == 0) - pts_valid = 1; - else - pts_valid = 0; - vf->pts = (pts_valid) ? pts : 0; - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - /* vf->pts = vf->pts_us64 ? vf->pts_us64 - * : vf->pts ; - */ - /* vf->pts = vf->pts_us64; */ - if (dbg_mode & 0x80) - pr_info("vf->pts:%d\n", vf->pts); - vfpool_idx[slot].used = 1; - INCPTR(fill_ptr); - set_frame_info(vf); - - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, 0, - vfpool_idx[slot].stream_offset); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - } - } - break; - case CMD_FATAL_ERROR: - pr_info("fatal error !!!\n"); - schedule_work(&error_wd_work); - break; - default: - break; - } -#ifdef HANDLE_h264mvc_IRQ - return IRQ_HANDLED; -#else - return; -#endif -} - -static void vh264_mvc_set_clk(struct work_struct *work) -{ - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_H264MVC, - frame_width, frame_height, fps * 2); - } -} - -static void vh264mvc_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - - int valid_frame = 0; - - if (enable_recycle == 0) { - if (dbg_mode & TIME_TASK_PRINT_ENABLE) { - /* valid_frame = get_valid_frame(); */ - pr_info("dirty_frame_num is %d , valid frame is %d\n", - dirty_frame_num, valid_frame); - - } - /* goto RESTART; */ - } - - while ((putting_ptr != put_ptr) && (READ_VREG(BUFFER_RECYCLE) == 0)) { - int view0_buf_id = vfpool_idx[put_ptr].view0_buf_id; - int view1_buf_id = vfpool_idx[put_ptr].view1_buf_id; - - if ((view0_buf_id >= 0) && - (view0_vfbuf_use[view0_buf_id] == 1)) { - if (dbg_mode & 0x100) { - pr_info - ("round 0: put_ptr is %d ;view0_buf_id is %d\n", - put_ptr, view0_buf_id); - } - WRITE_VREG(BUFFER_RECYCLE, - (0 << 8) | (view0_buf_id + 1)); - view0_vfbuf_use[view0_buf_id] = 0; - vfpool_idx[put_ptr].view0_buf_id = -1; - vfpool_idx[put_ptr].view0_drop = 0; - } else if ((view1_buf_id >= 0) - && (view1_vfbuf_use[view1_buf_id] == 1)) { - if (dbg_mode & 0x100) { - pr_info - ("round 1: put_ptr is %d ;view1_buf_id %d==\n", - put_ptr, view1_buf_id); - } - WRITE_VREG(BUFFER_RECYCLE, - (1 << 8) | (view1_buf_id + 1)); - view1_vfbuf_use[view1_buf_id] = 0; - vfpool_idx[put_ptr].display_pos = DISPLAY_INVALID_POS; - vfpool_idx[put_ptr].view1_buf_id = -1; - vfpool_idx[put_ptr].view1_drop = 0; - vfpool_idx[put_ptr].used = 0; - INCPTR(put_ptr); - } - } - - schedule_work(&set_clk_work); - - /* RESTART: */ - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vh264mvc_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (frame_dur != 0) - vstatus->frame_rate = 96000 / frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(AV_SCRATCH_D); - vstatus->status = stat; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -static int vh264mvc_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -int vh264mvc_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) -{ - if (trickmode == TRICKMODE_I) { - WRITE_VREG(AV_SCRATCH_F, - (READ_VREG(AV_SCRATCH_F) & 0xfffffffc) | 2); - trickmode_i = 1; - } else if (trickmode == TRICKMODE_NONE) { - WRITE_VREG(AV_SCRATCH_F, READ_VREG(AV_SCRATCH_F) & 0xfffffffc); - trickmode_i = 0; - } - - return 0; -} - -static void H264_DECODE_INIT(void) -{ - int i; - - i = READ_VREG(DECODE_SKIP_PICTURE); - -#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - -#else - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - READ_RESET_REG(RESET0_REGISTER); - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); -#endif - - /* Wait for some time for RESET */ - READ_VREG(DECODE_SKIP_PICTURE); - READ_VREG(DECODE_SKIP_PICTURE); - - WRITE_VREG(DECODE_SKIP_PICTURE, i); - - /* fill_weight_pred */ - WRITE_VREG(MC_MPORT_CTRL, 0x0300); - for (i = 0; i < 192; i++) - WRITE_VREG(MC_MPORT_DAT, 0x100); - WRITE_VREG(MC_MPORT_CTRL, 0); - - WRITE_VREG(MB_WIDTH, 0xff); /* invalid mb_width */ - - /* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */ - WRITE_VREG(SLICE_START_BYTE_01, 0x00000000); - WRITE_VREG(SLICE_START_BYTE_23, 0x01010000); - /* set to mpeg2 to enable mismatch logic */ - WRITE_VREG(MPEG1_2_REG, 1); - /* disable COEF_GT_64 , error_m4_table and voff_rw_err */ - WRITE_VREG(VLD_ERROR_MASK, 0x1011); - - /* Config MCPU Amrisc interrupt */ - WRITE_VREG(ASSIST_AMR1_INT0, 0x1); /* viu_vsync_int */ - WRITE_VREG(ASSIST_AMR1_INT1, 0x5); /* mbox_isr */ - WRITE_VREG(ASSIST_AMR1_INT2, 0x8); /* vld_isr */ - WRITE_VREG(ASSIST_AMR1_INT3, 0x15); /* vififo_empty */ - WRITE_VREG(ASSIST_AMR1_INT4, 0xd); /* rv_ai_mb_finished_int */ - WRITE_VREG(ASSIST_AMR1_INT7, 0x14); /* dcac_dma_done */ - - /* Config MCPU Amrisc interrupt */ - WRITE_VREG(ASSIST_AMR1_INT5, 0x9); /* MCPU interrupt */ - WRITE_VREG(ASSIST_AMR1_INT6, 0x17); /* CCPU interrupt */ - - WRITE_VREG(CPC_P, 0xc00); /* CCPU Code will start from 0xc00 */ - WRITE_VREG(CINT_VEC_BASE, (0xc20 >> 5)); -#if 0 - WRITE_VREG(POWER_CTL_VLD, - READ_VREG(POWER_CTL_VLD) | (0 << 10) | - (1 << 9) | (1 << 6)); -#else - WRITE_VREG(POWER_CTL_VLD, ((1 << 10) | /* disable cabac_step_2 */ - (1 << 9) | /* viff_drop_flag_en */ - (1 << 6) /* h264_000003_en */ - ) - ); -#endif - WRITE_VREG(M4_CONTROL_REG, (1 << 13)); /* H264_DECODE_INFO - h264_en */ - - WRITE_VREG(CANVAS_START, CANVAS_INDEX_START); -#if 1 - /* Start Address of Workspace (UCODE, temp_data...) */ - WRITE_VREG(WORKSPACE_START, - video_domain_addr(work_space_adr)); -#else - /* Start Address of Workspace (UCODE, temp_data...) */ - WRITE_VREG(WORKSPACE_START, - 0x05000000); -#endif - /* Clear all sequence parameter set available */ - WRITE_VREG(SPS_STATUS, 0); - /* Clear all picture parameter set available */ - WRITE_VREG(PPS_STATUS, 0); - /* Set current microcode to NULL */ - WRITE_VREG(CURRENT_UCODE, 0xff); - /* Set current SPS/PPS to NULL */ - WRITE_VREG(CURRENT_SPS_PPS, 0xffff); - /* Set decode status to DECODE_START_HEADER */ - WRITE_VREG(DECODE_STATUS, 1); -} - -static void vh264mvc_prot_init(void) -{ - while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) - ; - while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) - ; /* reg address is 0x350 */ - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - H264_DECODE_INIT(); - -#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 11)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - -#else - WRITE_RESET_REG(RESET0_REGISTER, 0x80); /* RESET MCPU */ -#endif - - WRITE_VREG(MAILBOX_COMMAND, 0); - WRITE_VREG(BUFFER_RECYCLE, 0); - WRITE_VREG(DROP_CONTROL, 0); - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); -#endif -} - -static int vh264mvc_local_init(void) -{ - int i, size, ret; - display_buff_id = -1; - display_view_id = -1; - display_POC = -1; - no_dropping_cnt = 0; - init_drop_cnt = INIT_DROP_FRAME_CNT; - - for (i = 0; i < INIT_DROP_FRAME_CNT; i++) - init_drop_frame_id[i] = 0; - -#ifdef DEBUG_PTS - pts_missed = 0; - pts_hit = 0; -#endif - -#ifdef DEBUG_SKIP - view_total = 0; - view_dropped = 0; -#endif - - /* vh264mvc_ratio = vh264mvc_amstream_dec_info.ratio; */ - vh264mvc_ratio = 0x100; - - /* frame_width = vh264mvc_amstream_dec_info.width; */ - /* frame_height = vh264mvc_amstream_dec_info.height; */ - frame_dur = vh264mvc_amstream_dec_info.rate; - if (frame_dur == 0) - frame_dur = 96000 / 24; - - pts_outside = ((unsigned long) vh264mvc_amstream_dec_info.param) & 0x01; - sync_outside = ((unsigned long) vh264mvc_amstream_dec_info.param & 0x02) - >> 1; - INIT_WORK(&alloc_work, do_alloc_work); - - max_dec_frame_buffering[0] = -1; - max_dec_frame_buffering[1] = -1; - fill_ptr = get_ptr = put_ptr = putting_ptr = 0; - dirty_frame_num = 0; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - view0_vfbuf_use[i] = 0; - view1_vfbuf_use[i] = 0; - } - - for (i = 0; i < VF_POOL_SIZE; i++) { - vfpool_idx[i].display_pos = -1; - vfpool_idx[i].view0_buf_id = DISPLAY_INVALID_POS; - vfpool_idx[i].view1_buf_id = -1; - vfpool_idx[i].view0_drop = 0; - vfpool_idx[i].view1_drop = 0; - vfpool_idx[i].used = 0; - } - for (i = 0; i < VF_POOL_SIZE; i++) { - memset(&vfpool[i], 0, sizeof(struct vframe_s)); - vfpool[i].index = i; - } - init_vf_buf(); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - TOTAL_BMMU_BUFF_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - - size = DECODER_WORK_SPACE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 0, - size, DRIVER_NAME, &work_space_adr); - - return ret; -} - -static s32 vh264mvc_init(void) -{ - int ret = -1; - char *buf = vmalloc(0x1000 * 16); - - if (buf == NULL) - return -ENOMEM; - - pr_info("\nvh264mvc_init\n"); - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - ret = vh264mvc_vdec_info_init(); - if (0 != ret) { - vfree(buf); - return -ret; - } - - ret = vh264mvc_local_init(); - if (ret < 0) { - vfree(buf); - return ret; - } - - amvdec_enable(); - - if (tee_enabled()) { - ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf); - if (ret != 0) { - amvdec_disable(); - vfree(buf); - pr_err("H264_MVC: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -1; - } - } else { - /* -- ucode loading (amrisc and swap code) */ - mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, &mc_dma_handle, GFP_KERNEL); - if (!mc_cpu_addr) { - amvdec_disable(); - vfree(buf); - pr_err("vh264_mvc init: Can not allocate mc memory.\n"); - return -ENOMEM; - } - - WRITE_VREG(UCODE_START_ADDR, mc_dma_handle); - - if (get_firmware_data(VIDEO_DEC_H264_MVC, buf) < 0) { - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf); - - /*header*/ - memcpy((u8 *) mc_cpu_addr, buf + 0x1000, 0x1000); - /*mmco*/ - memcpy((u8 *) mc_cpu_addr + 0x1000, buf + 0x2000, 0x2000); - /*slice*/ - memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); - - if (ret < 0) { - amvdec_disable(); - - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, - mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - return -EBUSY; - } - } - vfree(buf); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - vh264mvc_prot_init(); - -#ifdef HANDLE_h264mvc_IRQ - if (vdec_request_irq(VDEC_IRQ_1, vh264mvc_isr, - "vh264mvc-irq", (void *)vh264mvc_dec_id)) { - pr_info("vh264mvc irq register error.\n"); - amvdec_disable(); - return -ENOENT; - } -#endif - - stat |= STAT_ISR_REG; - - vf_provider_init(&vh264mvc_vf_prov, PROVIDER_NAME, - &vh264mvc_vf_provider, NULL); - vf_reg_provider(&vh264mvc_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong) (&recycle_timer); - recycle_timer.function = vh264mvc_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - return 0; -} - -static int vh264mvc_stop(void) -{ - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - WRITE_VREG(ASSIST_MBOX1_MASK, 0); -#ifdef HANDLE_h264mvc_IRQ - vdec_free_irq(VDEC_IRQ_1, (void *)vh264mvc_dec_id); -#endif - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - if (stat & STAT_VF_HOOK) { - ulong flags; - - spin_lock_irqsave(&lock, flags); - spin_unlock_irqrestore(&lock, flags); - vf_unreg_provider(&vh264mvc_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - if (stat & STAT_MC_LOAD) { - if (mc_cpu_addr != NULL) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - } - - stat &= ~STAT_MC_LOAD; - } - - amvdec_disable(); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - uninit_vf_buf(); - return 0; -} - -static void error_do_work(struct work_struct *work) -{ - if (atomic_read(&vh264mvc_active)) { - vh264mvc_stop(); - vh264mvc_init(); - } -} - -static int amvdec_h264mvc_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - pr_info("amvdec_h264mvc probe start.\n"); - mutex_lock(&vh264_mvc_mutex); - -#if 0 - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - pr_info("\namvdec_h264mvc memory resource undefined.\n"); - return -EFAULT; - } -#endif - - if (pdata == NULL) { - mutex_unlock(&vh264_mvc_mutex); - pr_info("\namvdec_h264mvc memory resource undefined.\n"); - return -EFAULT; - } - - if (pdata->sys_info) - vh264mvc_amstream_dec_info = *pdata->sys_info; - - pdata->dec_status = vh264mvc_dec_status; - /* pdata->set_trickmode = vh264mvc_set_trickmode; */ - - if (vh264mvc_init() < 0) { - pr_info("\namvdec_h264mvc init failed.\n"); - kfree(gvs); - gvs = NULL; - mutex_unlock(&vh264_mvc_mutex); - return -ENODEV; - } - - INIT_WORK(&error_wd_work, error_do_work); - INIT_WORK(&set_clk_work, vh264_mvc_set_clk); - - atomic_set(&vh264mvc_active, 1); - - mutex_unlock(&vh264_mvc_mutex); - - pr_info("amvdec_h264mvc probe end.\n"); - - return 0; -} - -static int amvdec_h264mvc_remove(struct platform_device *pdev) -{ - pr_info("amvdec_h264mvc_remove\n"); - cancel_work_sync(&alloc_work); - cancel_work_sync(&error_wd_work); - cancel_work_sync(&set_clk_work); - vh264mvc_stop(); - frame_width = 0; - frame_height = 0; - vdec_source_changed(VFORMAT_H264MVC, 0, 0, 0); - atomic_set(&vh264mvc_active, 0); - -#ifdef DEBUG_PTS - pr_info - ("pts missed %ld, pts hit %ld, pts_outside %d, ", - pts_missed, pts_hit, pts_outside); - pr_info("duration %d, sync_outside %d\n", - frame_dur, sync_outside); -#endif - -#ifdef DEBUG_SKIP - pr_info("view_total = %ld, dropped %ld\n", view_total, view_dropped); -#endif - kfree(gvs); - gvs = NULL; - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_h264mvc_driver = { - .probe = amvdec_h264mvc_probe, - .remove = amvdec_h264mvc_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_hmvc_profile = { - .name = "hmvc", - .profile = "" -}; -static struct mconfig h264mvc_configs[] = { - MC_PU32("stat", &stat), - MC_PU32("dbg_mode", &dbg_mode), - MC_PU32("view_mode", &view_mode), - MC_PU32("dbg_cmd", &dbg_cmd), - MC_PU32("drop_rate", &drop_rate), - MC_PU32("drop_thread_hold", &drop_thread_hold), -}; -static struct mconfig_node h264mvc_node; - -static int __init amvdec_h264mvc_driver_init_module(void) -{ - pr_debug("amvdec_h264mvc module init\n"); - - if (platform_driver_register(&amvdec_h264mvc_driver)) { - pr_err("failed to register amvdec_h264mvc driver\n"); - return -ENODEV; - } - - vcodec_profile_register(&amvdec_hmvc_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &h264mvc_node, - "h264mvc", h264mvc_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_h264mvc_driver_remove_module(void) -{ - pr_debug("amvdec_h264mvc module remove.\n"); - - platform_driver_unregister(&amvdec_h264mvc_driver); -} - -/****************************************/ - -module_param(stat, uint, 0664); -MODULE_PARM_DESC(stat, "\n amvdec_h264mvc stat\n"); - -module_param(dbg_mode, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc dbg mode\n"); - -module_param(view_mode, uint, 0664); -MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n"); - -module_param(dbg_cmd, uint, 0664); -MODULE_PARM_DESC(dbg_cmd, "\n amvdec_h264mvc cmd mode\n"); - -module_param(drop_rate, uint, 0664); -MODULE_PARM_DESC(drop_rate, "\n amvdec_h264mvc drop rate\n"); - -module_param(drop_thread_hold, uint, 0664); -MODULE_PARM_DESC(drop_thread_hold, "\n amvdec_h264mvc drop thread hold\n"); -module_init(amvdec_h264mvc_driver_init_module); -module_exit(amvdec_h264mvc_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC h264mvc Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Chen Zhang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile deleted file mode 100644 index 21dfb6abb5b9..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI) += amvdec_mh264.o -amvdec_mh264-objs += vmh264.o h264_dpb.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c deleted file mode 100644 index 8008310f56e2..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c +++ /dev/null @@ -1,5907 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#define DEBUG -#include -#include -#include - -#include -#include "../utils/vdec.h" -#include "../utils/amvdec.h" - -#include "h264_dpb.h" - -#define FRAME_NUM_MAX_SIZE 0x10000 - -#undef pr_info -#define pr_info printk -int dpb_print(int index, int debug_flag, const char *fmt, ...) -{ - if (((h264_debug_flag & debug_flag) && - ((1 << index) & h264_debug_mask)) - || (debug_flag == PRINT_FLAG_ERROR)) { - unsigned char buf[512]; - int len = 0; - va_list args; - - va_start(args, fmt); - len = sprintf(buf, "%d: ", index); - vsnprintf(buf + len, 512-len, fmt, args); - pr_debug("%s", buf); - va_end(args); - } - return 0; -} - -int dpb_print_cont(int index, int debug_flag, const char *fmt, ...) -{ - if (((h264_debug_flag & debug_flag) && - ((1 << index) & h264_debug_mask)) - || (debug_flag == PRINT_FLAG_ERROR)) { - unsigned char buf[512]; - int len = 0; - va_list args; - va_start(args, fmt); - vsnprintf(buf + len, 512-len, fmt, args); - pr_info("%s", buf); - va_end(args); - } - return 0; -} - -unsigned char dpb_is_debug(int index, int debug_flag) -{ - if (((h264_debug_flag & debug_flag) && - ((1 << index) & h264_debug_mask)) - || (debug_flag == PRINT_FLAG_ERROR)) - return 1; - return 0; -} - -#define CHECK_VALID(list_size, mark) {\ - if (list_size > MAX_LIST_SIZE || list_size < 0) { \ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR, \ - "%s(%d): listXsize[%d] %d is larger than max size\r\n",\ - __func__, __LINE__, mark, list_size);\ - list_size = 0; \ - p_H264_Dpb->dpb_error_flag = __LINE__;\ - } \ - } - -static struct DecRefPicMarking_s - dummy_dec_ref_pic_marking_buffer - [DEC_REF_PIC_MARKING_BUFFER_NUM_MAX]; -static struct StorablePicture dummy_pic; -static struct FrameStore dummy_fs; -static struct StorablePicture *get_new_pic( - struct h264_dpb_stru *p_H264_Dpb, - enum PictureStructure structure, unsigned char is_output); - -static void init_dummy_fs(void) -{ - dummy_fs.frame = &dummy_pic; - dummy_fs.top_field = &dummy_pic; - dummy_fs.bottom_field = &dummy_pic; - - dummy_pic.top_field = &dummy_pic; - dummy_pic.bottom_field = &dummy_pic; - dummy_pic.frame = &dummy_pic; - - dummy_pic.dec_ref_pic_marking_buffer = - &dummy_dec_ref_pic_marking_buffer[0]; -} - -enum { - LIST_0 = 0, - LIST_1 = 1, - BI_PRED = 2, - BI_PRED_L0 = 3, - BI_PRED_L1 = 4 -}; - -void ref_pic_list_reordering(struct h264_dpb_stru *p_H264_Dpb, - struct Slice *currSlice) -{ - /* struct VideoParameters *p_Vid = currSlice->p_Vid; - * byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER]; - * DataPartition *partition = &(currSlice->partArr[dP_nr]); - * Bitstream *currStream = partition->bitstream; - */ - int i, j, val; - unsigned short *reorder_cmd = - &p_H264_Dpb->dpb_param.mmco.l0_reorder_cmd[0]; - /* alloc_ref_pic_list_reordering_buffer(currSlice); */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - if (currSlice->slice_type != I_SLICE && - currSlice->slice_type != SI_SLICE) { - /* val = currSlice->ref_pic_list_reordering_flag[LIST_0] = - * read_u_1 ("SH: ref_pic_list_reordering_flag_l0", - * currStream, &p_Dec->UsedBits); - */ - if (reorder_cmd[0] != 3) { - val = currSlice-> - ref_pic_list_reordering_flag[LIST_0] = 1; - } else { - val = currSlice-> - ref_pic_list_reordering_flag[LIST_0] = 0; - } - if (val) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "%s, ref_pic_list_reordering_flag[LIST_0] is 1\n", - __func__); - - j = 0; - i = 0; - do { - val = currSlice-> - modification_of_pic_nums_idc[LIST_0][i] = - reorder_cmd[j++]; - /* read_ue_v( - * "SH: modification_of_pic_nums_idc_l0", - * currStream, &p_Dec->UsedBits); - */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "%d(%d):val %x\n", i, j, val); - if (j >= 66) { - currSlice-> - ref_pic_list_reordering_flag[LIST_0] = - 0; /* by rain */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s error\n", __func__); - break; - } - if (val == 0 || val == 1) { - currSlice-> - abs_diff_pic_num_minus1[LIST_0][i] = - reorder_cmd[j++]; - /* read_ue_v("SH: " - *"abs_diff_pic_num_minus1_l0", - *currStream, &p_Dec->UsedBits); - */ - } else { - if (val == 2) { - currSlice-> - long_term_pic_idx[LIST_0][i] = - reorder_cmd[j++]; - /* read_ue_v( - *"SH: long_term_pic_idx_l0", - *currStream, - *&p_Dec->UsedBits); - */ - } - } - i++; - /* assert (i>currSlice-> - * num_ref_idx_active[LIST_0]); - */ - if ( - -/* - * i>currSlice->num_ref_idx_active[LIST_0] || - */ - i >= REORDERING_COMMAND_MAX_SIZE) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s error %d %d\n", - __func__, i, - currSlice-> - num_ref_idx_active[LIST_0]); - currSlice-> - ref_pic_list_reordering_flag[LIST_0] = - 0; /* by rain */ - break; - } - if (j >= 66) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, "%s error\n", - __func__); - currSlice-> - ref_pic_list_reordering_flag[LIST_0] = - 0; /* by rain */ - break; - } - - } while (val != 3); - } - } - - if (currSlice->slice_type == B_SLICE) { - reorder_cmd = &p_H264_Dpb->dpb_param.mmco.l1_reorder_cmd[0]; - /* val = currSlice->ref_pic_list_reordering_flag[LIST_1] - *= read_u_1 ("SH: ref_pic_list_reordering_flag_l1", - *currStream, - *&p_Dec->UsedBits); - */ - - if (reorder_cmd[0] != 3) { - val = - currSlice->ref_pic_list_reordering_flag[LIST_1] = 1; - } else { - val = - currSlice->ref_pic_list_reordering_flag[LIST_1] = 0; - } - - if (val) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "%s, ref_pic_list_reordering_flag[LIST_1] is 1\n", - __func__); - - j = 0; - i = 0; - do { - val = currSlice-> - modification_of_pic_nums_idc[LIST_1][i] = - reorder_cmd[j++]; - /* read_ue_v( - *"SH: modification_of_pic_nums_idc_l1", - *currStream, - *&p_Dec->UsedBits); - */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "%d(%d):val %x\n", - i, j, val); - if (j >= 66) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, "%s error\n", - __func__); - currSlice-> - ref_pic_list_reordering_flag[LIST_1] = - 0; /* by rain */ - break; - } - if (val == 0 || val == 1) { - currSlice-> - abs_diff_pic_num_minus1[LIST_1][i] = - reorder_cmd[j++]; - /* read_ue_v( - *"SH: abs_diff_pic_num_minus1_l1", - *currStream, &p_Dec->UsedBits); - */ - } else { - if (val == 2) { - currSlice-> - long_term_pic_idx[LIST_1][i] = - reorder_cmd[j++]; - /* read_ue_v( - *"SH: long_term_pic_idx_l1", - *currStream, - *&p_Dec->UsedBits); - */ - } - } - i++; - /* assert(i>currSlice-> - * num_ref_idx_active[LIST_1]); - */ - if ( - /*i>currSlice->num_ref_idx_active[LIST_1] || */ - i >= REORDERING_COMMAND_MAX_SIZE) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s error %d %d\n", - __func__, i, - currSlice-> - num_ref_idx_active[LIST_0]); - currSlice-> - ref_pic_list_reordering_flag[LIST_1] = - 0; /* by rain */ - break; - } - if (j >= 66) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s error\n", __func__); - break; - } - } while (val != 3); - } - } - - /* set reference index of redundant slices. */ - /* - *if (currSlice->redundant_pic_cnt && - *(currSlice->slice_type != I_SLICE)) - *{ - * currSlice->redundant_slice_ref_idx = - * currSlice->abs_diff_pic_num_minus1[LIST_0][0] + 1; - *} - */ -} - -void slice_prepare(struct h264_dpb_stru *p_H264_Dpb, - struct DecodedPictureBuffer *p_Dpb, - struct VideoParameters *p_Vid, - struct SPSParameters *sps, struct Slice *pSlice) -{ - int i, j; - /* p_Vid->active_sps = sps; */ - unsigned short *mmco_cmd = &p_H264_Dpb->dpb_param.mmco.mmco_cmd[0]; - /* for decode_poc */ - sps->pic_order_cnt_type = - p_H264_Dpb->dpb_param.l.data[PIC_ORDER_CNT_TYPE]; - sps->log2_max_pic_order_cnt_lsb_minus4 = - p_H264_Dpb->dpb_param.l.data[LOG2_MAX_PIC_ORDER_CNT_LSB] - 4; - sps->num_ref_frames_in_pic_order_cnt_cycle = - p_H264_Dpb-> - dpb_param.l.data[NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE]; - for (i = 0; i < 128; i++) - sps->offset_for_ref_frame[i] = - (short) p_H264_Dpb-> - dpb_param.mmco.offset_for_ref_frame_base[i]; - sps->offset_for_non_ref_pic = - (short) p_H264_Dpb->dpb_param.l.data[OFFSET_FOR_NON_REF_PIC]; - sps->offset_for_top_to_bottom_field = - (short) p_H264_Dpb->dpb_param.l.data - [OFFSET_FOR_TOP_TO_BOTTOM_FIELD]; - - pSlice->frame_num = p_H264_Dpb->dpb_param.dpb.frame_num; - pSlice->idr_flag = - (p_H264_Dpb->dpb_param.dpb.NAL_info_mmco & 0x1f) - == 5 ? 1 : 0; - pSlice->nal_reference_idc = - (p_H264_Dpb->dpb_param.dpb.NAL_info_mmco >> 5) - & 0x3; - pSlice->pic_order_cnt_lsb = - p_H264_Dpb->dpb_param.dpb.pic_order_cnt_lsb; - pSlice->field_pic_flag = 0; - pSlice->bottom_field_flag = 0; - pSlice->delta_pic_order_cnt_bottom = val( - p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_bottom); - pSlice->delta_pic_order_cnt[0] = val( - p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_0); - pSlice->delta_pic_order_cnt[1] = val( - p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_1); - - p_Vid->last_has_mmco_5 = 0; - /* last memory_management_control_operation is 5 */ - p_Vid->last_pic_bottom_field = 0; - p_Vid->max_frame_num = 1 << - (p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM]); - - /**/ - pSlice->structure = (p_H264_Dpb-> - dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ? - FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE]; - if (pSlice->structure == FRAME) { - pSlice->field_pic_flag = 0; - pSlice->bottom_field_flag = 0; - } else { - pSlice->field_pic_flag = 1; - if (pSlice->structure == TOP_FIELD) - pSlice->bottom_field_flag = 0; - else - pSlice->bottom_field_flag = 1; - } - pSlice->pic_struct = p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT]; - - sps->num_ref_frames = p_H264_Dpb-> - dpb_param.l.data[MAX_REFERENCE_FRAME_NUM]; - sps->profile_idc = - (p_H264_Dpb->dpb_param.l.data[PROFILE_IDC_MMCO] >> 8) & 0xff; - /*sps->max_dpb_size = p_H264_Dpb->dpb_param.l.data[MAX_DPB_SIZE];*/ - if (pSlice->idr_flag) { - pSlice->long_term_reference_flag = mmco_cmd[0] & 1; - pSlice->no_output_of_prior_pics_flag = (mmco_cmd[0] >> 1) & 1; - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "IDR: long_term_reference_flag %d no_output_of_prior_pics_flag %d\r\n", - pSlice->long_term_reference_flag, - pSlice->no_output_of_prior_pics_flag); - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "idr set pre_frame_num(%d) to frame_num (%d)\n", - p_Vid->pre_frame_num, pSlice->frame_num); - - p_Vid->pre_frame_num = pSlice->frame_num; - } else if (p_H264_Dpb->mDPB.first_pic_done == 0) { - /* by rain - handle the case when first slice is I instead of IDR - */ - p_Vid->pre_frame_num = pSlice->frame_num; - } - /* pSlice->adaptive_ref_pic_buffering_flag; */ - sps->log2_max_frame_num_minus4 = - p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM] - 4; - - p_Vid->non_conforming_stream = - p_H264_Dpb->dpb_param.l.data[NON_CONFORMING_STREAM]; - p_Vid->recovery_point = - p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT]; - switch (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE]) { - case I_Slice: - pSlice->slice_type = I_SLICE; - break; - case P_Slice: - pSlice->slice_type = P_SLICE; - break; - case B_Slice: - pSlice->slice_type = B_SLICE; - break; - default: - pSlice->slice_type = NUM_SLICE_TYPES; - break; - } - - pSlice->num_ref_idx_active[LIST_0] = - p_H264_Dpb->dpb_param.dpb.num_ref_idx_l0_active_minus1 + - 1; - /* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1]; */ - pSlice->num_ref_idx_active[LIST_1] = - p_H264_Dpb->dpb_param.dpb.num_ref_idx_l1_active_minus1 + - 1; - /* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1]; */ - - pSlice->p_Vid = p_Vid; - pSlice->p_Dpb = p_Dpb; - /* - p_H264_Dpb->colocated_buf_size = - p_H264_Dpb->dpb_param.l.data[FRAME_SIZE_IN_MB] * 96;*/ - pSlice->first_mb_in_slice = - p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]; - pSlice->mode_8x8_flags = p_H264_Dpb->dpb_param.l.data[MODE_8X8_FLAGS]; - pSlice->picture_structure_mmco = - p_H264_Dpb->dpb_param.dpb.picture_structure_mmco; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s slice_type is %d, num_ref_idx_active[0,1]=%d,%d nal_reference_idc %d pic struct 0x%x(mmco stru 0x%x)\n", - __func__, pSlice->slice_type, - pSlice->num_ref_idx_active[LIST_0], - pSlice->num_ref_idx_active[LIST_1], - pSlice->nal_reference_idc, - pSlice->structure, - pSlice->picture_structure_mmco); -#ifdef ERROR_CHECK - if (pSlice->num_ref_idx_active[LIST_0] >= MAX_LIST_SIZE) { - pSlice->num_ref_idx_active[LIST_0] = MAX_LIST_SIZE - 1; - p_H264_Dpb->dpb_error_flag = __LINE__; - } - if (pSlice->num_ref_idx_active[LIST_1] >= MAX_LIST_SIZE) { - pSlice->num_ref_idx_active[LIST_1] = MAX_LIST_SIZE - 1; - p_H264_Dpb->dpb_error_flag = __LINE__; - } -#endif - -#if 1 - /* dec_ref_pic_marking_buffer */ - pSlice->adaptive_ref_pic_buffering_flag = 0; - if (pSlice->nal_reference_idc) { - for (i = 0, j = 0; i < 44; j++) { - unsigned short val; - struct DecRefPicMarking_s *tmp_drpm = - &pSlice->dec_ref_pic_marking_buffer[j]; - memset(tmp_drpm, 0, sizeof(struct DecRefPicMarking_s)); - val = tmp_drpm-> - memory_management_control_operation = - mmco_cmd[i++]; - tmp_drpm->Next = NULL; - if (j > 0) { - pSlice-> - dec_ref_pic_marking_buffer[j - 1].Next = - tmp_drpm; - } - if (val == 0 || i >= 44) - break; - pSlice->adaptive_ref_pic_buffering_flag = 1; - if ((val == 1) || (val == 3)) { - tmp_drpm->difference_of_pic_nums_minus1 = - mmco_cmd[i++]; - } - if (val == 2) - tmp_drpm->long_term_pic_num = mmco_cmd[i++]; - if (i >= 44) - break; - if ((val == 3) || (val == 6)) - tmp_drpm->long_term_frame_idx = mmco_cmd[i++]; - if (val == 4) { - tmp_drpm->max_long_term_frame_idx_plus1 = - mmco_cmd[i++]; - } - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "dec_ref_pic_marking_buffer[%d]:operation %x diff_pic_minus1 %x long_pic_num %x long_frame_idx %x max_long_frame_idx_plus1 %x\n", - j, - tmp_drpm->memory_management_control_operation, - tmp_drpm->difference_of_pic_nums_minus1, - tmp_drpm->long_term_pic_num, - tmp_drpm->long_term_frame_idx, - tmp_drpm->max_long_term_frame_idx_plus1); - } - } - - ref_pic_list_reordering(p_H264_Dpb, pSlice); -#endif - - /*VUI*/ - p_H264_Dpb->vui_status = p_H264_Dpb->dpb_param.l.data[VUI_STATUS]; - p_H264_Dpb->aspect_ratio_idc = - p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_IDC]; - p_H264_Dpb->aspect_ratio_sar_width = - p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_SAR_WIDTH]; - p_H264_Dpb->aspect_ratio_sar_height = - p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_SAR_HEIGHT]; - - p_H264_Dpb->fixed_frame_rate_flag = p_H264_Dpb->dpb_param.l.data[ - FIXED_FRAME_RATE_FLAG]; - p_H264_Dpb->num_units_in_tick = - p_H264_Dpb->dpb_param.l.data[NUM_UNITS_IN_TICK]; - p_H264_Dpb->time_scale = p_H264_Dpb->dpb_param.l.data[TIME_SCALE] | - (p_H264_Dpb->dpb_param.l.data[TIME_SCALE + 1] << 16); - - p_H264_Dpb->bitstream_restriction_flag = - (p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1; - p_H264_Dpb->num_reorder_frames = - p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES]; - p_H264_Dpb->max_dec_frame_buffering = - p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME]; - - /**/ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s return\n", __func__); -} - -static void decode_poc(struct VideoParameters *p_Vid, struct Slice *pSlice) -{ - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid, - struct h264_dpb_stru, mVideo); - struct SPSParameters *active_sps = p_Vid->active_sps; - int i; - /* for POC mode 0: */ - unsigned int MaxPicOrderCntLsb = (1 << - (active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DEBUG_POC, - "%s:pic_order_cnt_type %d, idr_flag %d last_has_mmco_5 %d last_pic_bottom_field %d pic_order_cnt_lsb %d PrevPicOrderCntLsb %d\r\n", - __func__, - active_sps->pic_order_cnt_type, - pSlice->idr_flag, - p_Vid->last_has_mmco_5, - p_Vid->last_pic_bottom_field, - pSlice->pic_order_cnt_lsb, - p_Vid->PrevPicOrderCntLsb - ); - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC, - "%s:field_pic_flag %d, bottom_field_flag %d frame_num %d PreviousFrameNum %d PreviousFrameNumOffset %d ax_frame_num %d num_ref_frames_in_pic_order_cnt_cycle %d offset_for_non_ref_pic %d\r\n", - __func__, - pSlice->field_pic_flag, - pSlice->bottom_field_flag, - pSlice->frame_num, - p_Vid->PreviousFrameNum, - p_Vid->PreviousFrameNumOffset, - p_Vid->max_frame_num, - active_sps->num_ref_frames_in_pic_order_cnt_cycle, - active_sps->offset_for_non_ref_pic - ); - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC, - "%s: delta_pic_order_cnt %d %d nal_reference_idc %d\r\n", - __func__, - pSlice->delta_pic_order_cnt[0], pSlice->delta_pic_order_cnt[1], - pSlice->nal_reference_idc - ); - - - switch (active_sps->pic_order_cnt_type) { - case 0: /* POC MODE 0 */ - /* 1st */ - if (pSlice->idr_flag) { - p_Vid->PrevPicOrderCntMsb = 0; - p_Vid->PrevPicOrderCntLsb = 0; - } else { - if (p_Vid->last_has_mmco_5) { - if (p_Vid->last_pic_bottom_field) { - p_Vid->PrevPicOrderCntMsb = 0; - p_Vid->PrevPicOrderCntLsb = 0; - } else { - p_Vid->PrevPicOrderCntMsb = 0; - p_Vid->PrevPicOrderCntLsb = - pSlice->toppoc; - } - } - } - /* Calculate the MSBs of current picture */ - if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb && - (p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >= - (MaxPicOrderCntLsb / 2)) - pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb + - MaxPicOrderCntLsb; - else if (pSlice->pic_order_cnt_lsb > - p_Vid->PrevPicOrderCntLsb && - (pSlice->pic_order_cnt_lsb - - p_Vid->PrevPicOrderCntLsb) > - (MaxPicOrderCntLsb / 2)) - pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb - - MaxPicOrderCntLsb; - else - pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb; - - /* 2nd */ - if (pSlice->field_pic_flag == 0) { - /* frame pix */ - pSlice->toppoc = pSlice->PicOrderCntMsb + - pSlice->pic_order_cnt_lsb; - pSlice->bottompoc = pSlice->toppoc + - pSlice->delta_pic_order_cnt_bottom; - pSlice->ThisPOC = pSlice->framepoc = - (pSlice->toppoc < pSlice->bottompoc) ? - pSlice->toppoc : pSlice->bottompoc; - /* POC200301 */ - } else if (pSlice->bottom_field_flag == FALSE) { - /* top field */ - pSlice->ThisPOC = pSlice->toppoc = - pSlice->PicOrderCntMsb + - pSlice->pic_order_cnt_lsb; - } else { - /* bottom field */ - pSlice->ThisPOC = pSlice->bottompoc = - pSlice->PicOrderCntMsb + - pSlice->pic_order_cnt_lsb; - } - pSlice->framepoc = pSlice->ThisPOC; - - p_Vid->ThisPOC = pSlice->ThisPOC; - - /* if ( pSlice->frame_num != p_Vid->PreviousFrameNum) - * Seems redundant - */ - p_Vid->PreviousFrameNum = pSlice->frame_num; - - if (pSlice->nal_reference_idc) { - p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb; - p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb; - } - - break; - - case 1: /* POC MODE 1 */ - /* 1st */ - if (pSlice->idr_flag) { - p_Vid->FrameNumOffset = 0; /* first pix of IDRGOP */ - if (pSlice->frame_num) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "frame_num not equal to zero in IDR picture %d", - -1020); - } else { - if (p_Vid->last_has_mmco_5) { - p_Vid->PreviousFrameNumOffset = 0; - p_Vid->PreviousFrameNum = 0; - } - if (pSlice->frame_num < p_Vid->PreviousFrameNum) { - /* not first pix of IDRGOP */ - p_Vid->FrameNumOffset = - p_Vid->PreviousFrameNumOffset + - p_Vid->max_frame_num; - } else { - p_Vid->FrameNumOffset = - p_Vid->PreviousFrameNumOffset; - } - } - - /* 2nd */ - if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) - pSlice->AbsFrameNum = - p_Vid->FrameNumOffset + pSlice->frame_num; - else - pSlice->AbsFrameNum = 0; - if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0) - pSlice->AbsFrameNum--; - - /* 3rd */ - p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0; - - if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) - for (i = 0; i < (int) active_sps-> - num_ref_frames_in_pic_order_cnt_cycle; i++) { - p_Vid->ExpectedDeltaPerPicOrderCntCycle += - active_sps->offset_for_ref_frame[i]; - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DEBUG_POC, - "%s: offset_for_ref_frame %d\r\n", - __func__, - active_sps-> - offset_for_ref_frame[i]); - } - - if (pSlice->AbsFrameNum) { - p_Vid->PicOrderCntCycleCnt = - (pSlice->AbsFrameNum - 1) / - active_sps-> - num_ref_frames_in_pic_order_cnt_cycle; - p_Vid->FrameNumInPicOrderCntCycle = - (pSlice->AbsFrameNum - 1) % - active_sps-> - num_ref_frames_in_pic_order_cnt_cycle; - p_Vid->ExpectedPicOrderCnt = - p_Vid->PicOrderCntCycleCnt * - p_Vid->ExpectedDeltaPerPicOrderCntCycle; - for (i = 0; i <= (int)p_Vid-> - FrameNumInPicOrderCntCycle; i++) { - p_Vid->ExpectedPicOrderCnt += - active_sps->offset_for_ref_frame[i]; - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DEBUG_POC, - "%s: offset_for_ref_frame %d\r\n", - __func__, - active_sps-> - offset_for_ref_frame[i]); - } - } else - p_Vid->ExpectedPicOrderCnt = 0; - - if (!pSlice->nal_reference_idc) - p_Vid->ExpectedPicOrderCnt += - active_sps->offset_for_non_ref_pic; - - if (pSlice->field_pic_flag == 0) { - /* frame pix */ - pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + - pSlice->delta_pic_order_cnt[0]; - pSlice->bottompoc = pSlice->toppoc + - active_sps->offset_for_top_to_bottom_field + - pSlice->delta_pic_order_cnt[1]; - pSlice->ThisPOC = pSlice->framepoc = - (pSlice->toppoc < pSlice->bottompoc) ? - pSlice->toppoc : pSlice->bottompoc; - /* POC200301 */ - } else if (pSlice->bottom_field_flag == FALSE) { - /* top field */ - pSlice->ThisPOC = pSlice->toppoc = - p_Vid->ExpectedPicOrderCnt + - pSlice->delta_pic_order_cnt[0]; - } else { - /* bottom field */ - pSlice->ThisPOC = pSlice->bottompoc = - p_Vid->ExpectedPicOrderCnt + - active_sps->offset_for_top_to_bottom_field + - pSlice->delta_pic_order_cnt[0]; - } - pSlice->framepoc = pSlice->ThisPOC; - - p_Vid->PreviousFrameNum = pSlice->frame_num; - p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; - - break; - - - case 2: /* POC MODE 2 */ - if (pSlice->idr_flag) { /* IDR picture */ - p_Vid->FrameNumOffset = 0; /* first pix of IDRGOP */ - pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc = - pSlice->bottompoc = 0; - if (pSlice->frame_num) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "frame_num not equal to zero in IDR picture %d", - -1020); - } else { - if (p_Vid->last_has_mmco_5) { - p_Vid->PreviousFrameNum = 0; - p_Vid->PreviousFrameNumOffset = 0; - } - if (pSlice->frame_num < p_Vid->PreviousFrameNum) - p_Vid->FrameNumOffset = - p_Vid->PreviousFrameNumOffset + - p_Vid->max_frame_num; - else - p_Vid->FrameNumOffset = - p_Vid->PreviousFrameNumOffset; - - pSlice->AbsFrameNum = p_Vid->FrameNumOffset + - pSlice->frame_num; - if (!pSlice->nal_reference_idc) - pSlice->ThisPOC = - (2 * pSlice->AbsFrameNum - 1); - else - pSlice->ThisPOC = (2 * pSlice->AbsFrameNum); - - if (pSlice->field_pic_flag == 0) - pSlice->toppoc = pSlice->bottompoc = - pSlice->framepoc = pSlice->ThisPOC; - else if (pSlice->bottom_field_flag == FALSE) - pSlice->toppoc = pSlice->framepoc = - pSlice->ThisPOC; - else - pSlice->bottompoc = pSlice->framepoc = - pSlice->ThisPOC; - } - - p_Vid->PreviousFrameNum = pSlice->frame_num; - p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; - break; - - - default: - /* error must occurs */ - /* assert( 1==0 ); */ - break; - } -} - -void fill_frame_num_gap(struct VideoParameters *p_Vid, struct Slice *currSlice) -{ - struct h264_dpb_stru *p_H264_Dpb = - container_of(p_Vid, struct h264_dpb_stru, mVideo); - struct SPSParameters *active_sps = p_Vid->active_sps; - int CurrFrameNum; - int UnusedShortTermFrameNum; - struct StorablePicture *picture = NULL; - int tmp1 = currSlice->delta_pic_order_cnt[0]; - int tmp2 = currSlice->delta_pic_order_cnt[1]; - int ret; - - currSlice->delta_pic_order_cnt[0] = - currSlice->delta_pic_order_cnt[1] = 0; - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "A gap in frame number is found, try to fill it.(pre_frame_num %d, max_frame_num %d\n", - p_Vid->pre_frame_num, p_Vid->max_frame_num - ); - - UnusedShortTermFrameNum = (p_Vid->pre_frame_num + 1) - % p_Vid->max_frame_num; - CurrFrameNum = currSlice->frame_num; /*p_Vid->frame_num;*/ - - while (CurrFrameNum != UnusedShortTermFrameNum) { - /*picture = alloc_storable_picture - *(p_Vid, FRAME, p_Vid->width, - *p_Vid->height, - *p_Vid->width_cr, - *p_Vid->height_cr, 1); - */ - picture = get_new_pic(p_H264_Dpb, - p_H264_Dpb->mSlice.structure, - /*p_Vid->width, p_Vid->height, - *p_Vid->width_cr, - p_Vid->height_cr,*/ 1); - - if (picture == NULL) { - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s Error: get_new_pic return NULL\r\n", - __func__); - /*h264_debug_flag |= PRINT_FLAG_DUMP_DPB;*/ - dump_dpb(p_Dpb, 0); - return; - } - - picture->colocated_buf_index = -1; - picture->buf_spec_num = -1; - picture->buf_spec_is_alloced = 0; - - picture->coded_frame = 1; - picture->pic_num = UnusedShortTermFrameNum; - picture->frame_num = UnusedShortTermFrameNum; - picture->non_existing = 1; - picture->is_output = 1; - picture->used_for_reference = 1; - picture->adaptive_ref_pic_buffering_flag = 0; - #if (MVC_EXTENSION_ENABLE) - picture->view_id = currSlice->view_id; - #endif - - currSlice->frame_num = UnusedShortTermFrameNum; - if (active_sps->pic_order_cnt_type != 0) { - /*decode_poc(p_Vid, p_Vid->ppSliceList[0]);*/ - decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice); - } - picture->top_poc = currSlice->toppoc; - picture->bottom_poc = currSlice->bottompoc; - picture->frame_poc = currSlice->framepoc; - picture->poc = currSlice->framepoc; - - ret = store_picture_in_dpb(p_H264_Dpb, picture, 0); - if (ret == -1) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s Error: store_picture_in_dpb failed, break\n", - __func__); - release_picture(p_H264_Dpb, picture); - bufmgr_force_recover(p_H264_Dpb); - return; - } - - picture = NULL; - p_Vid->pre_frame_num = UnusedShortTermFrameNum; - UnusedShortTermFrameNum = - (UnusedShortTermFrameNum + 1) % - p_Vid->max_frame_num; - } - currSlice->delta_pic_order_cnt[0] = tmp1; - currSlice->delta_pic_order_cnt[1] = tmp2; - currSlice->frame_num = CurrFrameNum; -} - -void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb, - int id, int actual_dpb_size, int max_reference_size) -{ - int i; - - init_dummy_fs(); - - memset(&p_H264_Dpb->mDPB, 0, sizeof(struct DecodedPictureBuffer)); - - memset(&p_H264_Dpb->mSlice, 0, sizeof(struct Slice)); - memset(&p_H264_Dpb->mVideo, 0, sizeof(struct VideoParameters)); - memset(&p_H264_Dpb->mSPS, 0, sizeof(struct SPSParameters)); - - for (i = 0; i < DPB_SIZE_MAX; i++) { - memset(&(p_H264_Dpb->mFrameStore[i]), 0, - sizeof(struct FrameStore)); - } - - for (i = 0; i < MAX_PIC_BUF_NUM; i++) { - memset(&(p_H264_Dpb->m_PIC[i]), 0, - sizeof(struct StorablePicture)); - p_H264_Dpb->m_PIC[i].index = i; - } - p_H264_Dpb->decoder_index = id; - - /* make sure dpb_init_global - *can be called during decoding - *(in DECODE_STATE_IDLE or DECODE_STATE_READY state) - */ - p_H264_Dpb->mDPB.size = actual_dpb_size; - p_H264_Dpb->max_reference_size = max_reference_size; - p_H264_Dpb->poc_even_odd_flag = 0; -} - -static void init_picture(struct h264_dpb_stru *p_H264_Dpb, - struct Slice *currSlice, - struct StorablePicture *dec_picture) -{ - /* struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo); */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s dec_picture %p\n", __func__, dec_picture); - dec_picture->top_poc = currSlice->toppoc; - dec_picture->bottom_poc = currSlice->bottompoc; - dec_picture->frame_poc = currSlice->framepoc; - switch (currSlice->structure) { - case TOP_FIELD: { - dec_picture->poc = currSlice->toppoc; - /* p_Vid->number *= 2; */ - break; - } - case BOTTOM_FIELD: { - dec_picture->poc = currSlice->bottompoc; - /* p_Vid->number = p_Vid->number * 2 + 1; */ - break; - } - case FRAME: { - dec_picture->poc = currSlice->framepoc; - break; - } - default: - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "p_Vid->structure not initialized %d\n", 235); - } - - /* dec_picture->slice_type = p_Vid->type; */ - dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0); - dec_picture->idr_flag = currSlice->idr_flag; - dec_picture->no_output_of_prior_pics_flag = - currSlice->no_output_of_prior_pics_flag; - dec_picture->long_term_reference_flag = - currSlice->long_term_reference_flag; -#if 1 - dec_picture->adaptive_ref_pic_buffering_flag = - currSlice->adaptive_ref_pic_buffering_flag; - dec_picture->dec_ref_pic_marking_buffer = - &currSlice->dec_ref_pic_marking_buffer[0]; -#endif - /* currSlice->dec_ref_pic_marking_buffer = NULL; */ - - /* dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; */ - /* dec_picture->PicWidthInMbs = p_Vid->PicWidthInMbs; */ - - /* p_Vid->get_mb_block_pos = - * dec_picture->mb_aff_frame_flag ? get_mb_block_pos_mbaff : - * get_mb_block_pos_normal; - */ - /* p_Vid->getNeighbour = - * dec_picture->mb_aff_frame_flag ? getAffNeighbour : - * getNonAffNeighbour; - */ - - dec_picture->pic_num = currSlice->frame_num; - dec_picture->frame_num = currSlice->frame_num; - - /* dec_picture->recovery_frame = - * (unsigned int) ((int) currSlice->frame_num == - * p_Vid->recovery_frame_num); - */ - - dec_picture->coded_frame = (currSlice->structure == FRAME); - - /* dec_picture->chroma_format_idc = active_sps->chroma_format_idc; */ - - /* dec_picture->frame_mbs_only_flag = - * active_sps->frame_mbs_only_flag; - */ - /* dec_picture->frame_cropping_flag = - * active_sps->frame_cropping_flag; - */ - - if ((currSlice->picture_structure_mmco & 0x3) == 3) { - dec_picture->mb_aff_frame_flag = 1; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s, picture_structure_mmco is %x, set mb_aff_frame_flag to 1\n", - __func__, - currSlice->picture_structure_mmco); - } - - if (currSlice->pic_struct >= 3) - dec_picture->pic_struct = currSlice->pic_struct + 2; - else if (currSlice->pic_struct == 1) - dec_picture->pic_struct = PIC_TOP_BOT; - else if (currSlice->pic_struct >= 2) - dec_picture->pic_struct = PIC_BOT_TOP; - else - dec_picture->pic_struct = PIC_INVALID; -} - -void dump_pic(struct h264_dpb_stru *p_H264_Dpb) -{ - int ii; - struct StorablePicture *pic; - for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) { - pic = &(p_H264_Dpb->m_PIC[ii]); - if (pic->is_used) { - dpb_print(p_H264_Dpb->decoder_index, 0, - "pic(%d,%d) poc %d is_used %d bufspec %d colbuf %d for_ref %d long_term %d pre_out %d output %d nonexist %d data_flag 0x%x\n", - ii, pic->index, - pic->poc, - pic->is_used, - pic->buf_spec_num, - pic->colocated_buf_index, - pic->used_for_reference, - pic->is_long_term, - pic->pre_output, - pic->is_output, - pic->non_existing, - pic->data_flag); - } - } -} - -/* -static void is_pic_used_by_dpb(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *pic) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - unsigned i; - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->top_field == pic || - p_Dpb->fs[i]->bottom_field == pic || - p_Dpb->fs[i]->frame == pic - ) - break; - } - if (i < p_Dpb->used_size) - return 1; - return 0; -} -*/ - -static struct StorablePicture *get_new_pic(struct h264_dpb_stru *p_H264_Dpb, - enum PictureStructure structure, unsigned char is_output) -{ - struct StorablePicture *s = NULL; - struct StorablePicture *pic; - struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo); - /* recycle un-used pic */ - int ii = 0; - - for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) { - pic = &(p_H264_Dpb->m_PIC[ii]); - if (pic->is_used == 0) { - pic->is_used = 1; - s = pic; - break; - } - } - - if (s) { - s->buf_spec_is_alloced = 0; - s->pic_num = 0; - s->frame_num = 0; - s->long_term_frame_idx = 0; - s->long_term_pic_num = 0; - s->used_for_reference = 0; - s->is_long_term = 0; - s->non_existing = 0; - s->is_output = 0; - s->pre_output = 0; - s->max_slice_id = 0; - s->data_flag &= ~(ERROR_FLAG | NODISP_FLAG | MAYBE_ERROR_FLAG); -#if (MVC_EXTENSION_ENABLE) - s->view_id = -1; -#endif - - s->structure = structure; - -#if 0 - s->size_x = size_x; - s->size_y = size_y; - s->size_x_cr = size_x_cr; - s->size_y_cr = size_y_cr; - s->size_x_m1 = size_x - 1; - s->size_y_m1 = size_y - 1; - s->size_x_cr_m1 = size_x_cr - 1; - s->size_y_cr_m1 = size_y_cr - 1; - - s->top_field = p_Vid->no_reference_picture; - s->bottom_field = p_Vid->no_reference_picture; - s->frame = p_Vid->no_reference_picture; -#endif - /* s->dec_ref_pic_marking_buffer = NULL; */ - - s->coded_frame = 0; - s->mb_aff_frame_flag = 0; - - s->top_poc = s->bottom_poc = s->poc = 0; - s->seiHasTone_mapping = 0; - s->frame_mbs_only_flag = p_Vid->active_sps->frame_mbs_only_flag; - - if (!p_Vid->active_sps->frame_mbs_only_flag && - structure != FRAME) { - int i, j; - - for (j = 0; j < MAX_NUM_SLICES; j++) { - for (i = 0; i < 2; i++) { - /* s->listX[j][i] = - *calloc(MAX_LIST_SIZE, - *sizeof (struct StorablePicture *)); - *+1 for reordering ??? - - *if (NULL == s->listX[j][i]) - *no_mem_exit("alloc_storable_picture: - *s->listX[i]"); - */ - } - } - } - } else - p_H264_Dpb->buf_alloc_fail = 1; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s %p\n", __func__, s); - return s; -} - -static void free_picture(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *pic) -{ - if (pic == NULL || pic->index < 0 || - pic->index >= MAX_PIC_BUF_NUM) - return; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s %p %d\n", __func__, pic, pic->index); - /* assert(pic->indexm_PIC[pic->index].is_used = 0; -} - -static void gen_field_ref_ids(struct VideoParameters *p_Vid, - struct StorablePicture *p) -{ - int i, j; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid, - struct h264_dpb_stru, mVideo); - /* ! Generate Frame parameters from field information. */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - - /* copy the list; */ - for (j = 0; j < p_Vid->iSliceNumOfCurrPic; j++) { - if (p->listX[j][LIST_0]) { - p->listXsize[j][LIST_0] = - p_Vid->ppSliceList[j]->listXsize[LIST_0]; - for (i = 0; i < p->listXsize[j][LIST_0]; i++) - p->listX[j][LIST_0][i] = - p_Vid->ppSliceList[j]->listX[LIST_0][i]; - } - if (p->listX[j][LIST_1]) { - p->listXsize[j][LIST_1] = - p_Vid->ppSliceList[j]->listXsize[LIST_1]; - for (i = 0; i < p->listXsize[j][LIST_1]; i++) - p->listX[j][LIST_1][i] = - p_Vid->ppSliceList[j]->listX[LIST_1][i]; - } - } -} - -static void init_dpb(struct h264_dpb_stru *p_H264_Dpb, int type) -{ - unsigned int i; - struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - struct SPSParameters *active_sps = &p_H264_Dpb->mSPS; - - p_Vid->active_sps = active_sps; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - - p_Dpb->p_Vid = p_Vid; - if (p_Dpb->init_done) { - /* free_dpb(p_Dpb); */ - if (p_Vid->no_reference_picture) { - free_picture(p_H264_Dpb, p_Vid->no_reference_picture); - p_Vid->no_reference_picture = NULL; - } - p_Dpb->init_done = 0; - } - - /* p_Dpb->size = 10; //active_sps->max_dpb_size; //16; - * getDpbSize(p_Vid, active_sps) + - * p_Vid->p_Inp->dpb_plus[type==2? 1: 0]; - * p_Dpb->size = active_sps->max_dpb_size; //16; - * getDpbSize(p_Vid, active_sps) + - * p_Vid->p_Inp->dpb_plus[type==2? 1: 0]; - * p_Dpb->size initialzie in vh264.c - */ - p_Dpb->num_ref_frames = active_sps->num_ref_frames; - /* p_Dpb->num_ref_frames initialzie in vh264.c */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s dpb_size is %d num_ref_frames = %d (%d)\n", - __func__, p_Dpb->size, - p_Dpb->num_ref_frames, - active_sps->num_ref_frames); - if (active_sps->num_ref_frames == 0xffff) { - dpb_print(p_H264_Dpb->decoder_index, 0, - "!!!Warning, num_ref_frames = %d is invalid\n", - active_sps->num_ref_frames); - } - -#if 0 - /* ??? */ -#if (MVC_EXTENSION_ENABLE) - if ((unsigned int)active_sps->max_dec_frame_buffering < - active_sps->num_ref_frames) { -#else - if (p_Dpb->size < active_sps->num_ref_frames) { -#endif - error( - "DPB size at specified level is smaller than the specified number of reference frames. This is not allowed.\n", - 1000); - } -#endif - - p_Dpb->used_size = 0; - p_Dpb->last_picture = NULL; - - p_Dpb->ref_frames_in_buffer = 0; - p_Dpb->ltref_frames_in_buffer = 0; - -#if 0 - p_Dpb->fs = calloc(p_Dpb->size, sizeof(struct FrameStore *)); - if (NULL == p_Dpb->fs) - no_mem_exit("init_dpb: p_Dpb->fs"); - - p_Dpb->fs_ref = calloc(p_Dpb->size, sizeof(struct FrameStore *)); - if (NULL == p_Dpb->fs_ref) - no_mem_exit("init_dpb: p_Dpb->fs_ref"); - - p_Dpb->fs_ltref = calloc(p_Dpb->size, sizeof(struct FrameStore *)); - if (NULL == p_Dpb->fs_ltref) - no_mem_exit("init_dpb: p_Dpb->fs_ltref"); -#endif - -#if (MVC_EXTENSION_ENABLE) - p_Dpb->fs_ilref = calloc(1, sizeof(struct FrameStore *)); - if (NULL == p_Dpb->fs_ilref) - no_mem_exit("init_dpb: p_Dpb->fs_ilref"); -#endif - - for (i = 0; i < p_Dpb->size; i++) { - p_Dpb->fs[i] = &(p_H264_Dpb->mFrameStore[i]); - /* alloc_frame_store(); */ - p_Dpb->fs[i]->index = i; - p_Dpb->fs_ref[i] = NULL; - p_Dpb->fs_ltref[i] = NULL; - p_Dpb->fs[i]->layer_id = 0; /* MVC_INIT_VIEW_ID; */ -#if (MVC_EXTENSION_ENABLE) - p_Dpb->fs[i]->view_id = MVC_INIT_VIEW_ID; - p_Dpb->fs[i]->inter_view_flag[0] = - p_Dpb->fs[i]->inter_view_flag[1] = 0; - p_Dpb->fs[i]->anchor_pic_flag[0] = - p_Dpb->fs[i]->anchor_pic_flag[1] = 0; -#endif - } -#if (MVC_EXTENSION_ENABLE) - if (type == 2) { - p_Dpb->fs_ilref[0] = alloc_frame_store(); - /* These may need some cleanups */ - p_Dpb->fs_ilref[0]->view_id = MVC_INIT_VIEW_ID; - p_Dpb->fs_ilref[0]->inter_view_flag[0] = - p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0; - p_Dpb->fs_ilref[0]->anchor_pic_flag[0] = - p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0; - /* given that this is in a different buffer, - * do we even need proc_flag anymore? - */ - } else - p_Dpb->fs_ilref[0] = NULL; -#endif - - /* - *for (i = 0; i < 6; i++) - *{ - *currSlice->listX[i] = - * calloc(MAX_LIST_SIZE, sizeof (struct StorablePicture *)); - * +1 for reordering - *if (NULL == currSlice->listX[i]) - *no_mem_exit("init_dpb: currSlice->listX[i]"); - *} - */ - /* allocate a dummy storable picture */ - if (!p_Vid->no_reference_picture) { - p_Vid->no_reference_picture = get_new_pic(p_H264_Dpb, - FRAME, - /*p_Vid->width, p_Vid->height, - *p_Vid->width_cr, p_Vid->height_cr, - */ - 1); - p_Vid->no_reference_picture->top_field = - p_Vid->no_reference_picture; - p_Vid->no_reference_picture->bottom_field = - p_Vid->no_reference_picture; - p_Vid->no_reference_picture->frame = - p_Vid->no_reference_picture; - } - p_Dpb->last_output_poc = INT_MIN; - -#if (MVC_EXTENSION_ENABLE) - p_Dpb->last_output_view_id = -1; -#endif - - p_Vid->last_has_mmco_5 = 0; - - init_colocate_buf(p_H264_Dpb, p_H264_Dpb->max_reference_size); - - p_Dpb->init_done = 1; - -#if 0 -/* ??? */ - /* picture error concealment */ - if (p_Vid->conceal_mode != 0 && !p_Vid->last_out_fs) - p_Vid->last_out_fs = alloc_frame_store(); -#endif -} - -static void dpb_split_field(struct h264_dpb_stru *p_H264_Dpb, - struct FrameStore *fs) -{ - struct StorablePicture *fs_top = NULL, *fs_btm = NULL; - struct StorablePicture *frame = fs->frame; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s %p %p\n", __func__, fs, frame); - - fs->poc = frame->poc; - - if (!frame->frame_mbs_only_flag) { - fs_top = fs->top_field = get_new_pic(p_H264_Dpb, - TOP_FIELD, - /* frame->size_x, frame->size_y, - *frame->size_x_cr, frame->size_y_cr, - */ - 1); - fs_btm = fs->bottom_field = get_new_pic(p_H264_Dpb, - BOTTOM_FIELD, - /*frame->size_x, frame->size_y, - *frame->size_x_cr, frame->size_y_cr, - */ - 1); - if (fs_top == NULL || fs_btm == NULL) - return; -#if 1 -/* rain */ - fs_top->buf_spec_num = frame->buf_spec_num; - fs_btm->buf_spec_num = frame->buf_spec_num; - - fs_top->colocated_buf_index = frame->colocated_buf_index; - fs_btm->colocated_buf_index = frame->colocated_buf_index; - - fs_top->data_flag = frame->data_flag; - fs_btm->data_flag = frame->data_flag; -#endif - fs_top->poc = frame->top_poc; - fs_btm->poc = frame->bottom_poc; - -#if (MVC_EXTENSION_ENABLE) - fs_top->view_id = frame->view_id; - fs_btm->view_id = frame->view_id; -#endif - - fs_top->frame_poc = frame->frame_poc; - - fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc; - fs_top->top_poc = fs_btm->top_poc = frame->top_poc; - fs_btm->frame_poc = frame->frame_poc; - - fs_top->used_for_reference = fs_btm->used_for_reference - = frame->used_for_reference; - fs_top->is_long_term = fs_btm->is_long_term - = frame->is_long_term; - fs->long_term_frame_idx = fs_top->long_term_frame_idx - = fs_btm->long_term_frame_idx - = frame->long_term_frame_idx; - - fs_top->coded_frame = fs_btm->coded_frame = 1; - fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag - = frame->mb_aff_frame_flag; - - frame->top_field = fs_top; - frame->bottom_field = fs_btm; - frame->frame = frame; - fs_top->bottom_field = fs_btm; - fs_top->frame = frame; - fs_top->top_field = fs_top; - fs_btm->top_field = fs_top; - fs_btm->frame = frame; - fs_btm->bottom_field = fs_btm; - -#if (MVC_EXTENSION_ENABLE) - fs_top->view_id = fs_btm->view_id = fs->view_id; - fs_top->inter_view_flag = fs->inter_view_flag[0]; - fs_btm->inter_view_flag = fs->inter_view_flag[1]; -#endif - - fs_top->chroma_format_idc = fs_btm->chroma_format_idc = - frame->chroma_format_idc; - fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType; - } else { - fs->top_field = NULL; - fs->bottom_field = NULL; - frame->top_field = NULL; - frame->bottom_field = NULL; - frame->frame = frame; - } - -} - - -static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb, - struct FrameStore *fs) -{ - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - - if (!fs->frame) { - fs->frame = get_new_pic(p_H264_Dpb, - FRAME, - /* fs->top_field->size_x, fs->top_field->size_y*2, - *fs->top_field->size_x_cr, fs->top_field->size_y_cr*2, - */ - 1); - } - if (!fs->frame) - return; -#if 1 -/* rain */ - fs->frame->buf_spec_num = fs->top_field->buf_spec_num; - fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index; - fs->frame->data_flag = fs->top_field->data_flag; - fs->frame->slice_type = fs->top_field->slice_type; - if (fs->bottom_field) - fs->frame->data_flag |= (fs->bottom_field->data_flag & 0xf0); -#endif - - if (fs->bottom_field) { - fs->poc = fs->frame->poc = fs->frame->frame_poc = imin( - fs->top_field->poc, fs->bottom_field->poc); - - fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; - - fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; - fs->top_field->bottom_poc = fs->frame->bottom_poc = - fs->bottom_field->poc; - - fs->frame->used_for_reference = (fs->top_field->used_for_reference && - fs->bottom_field->used_for_reference); - fs->frame->is_long_term = (fs->top_field->is_long_term && - fs->bottom_field->is_long_term); - } - - if (fs->frame->is_long_term) - fs->frame->long_term_frame_idx = fs->long_term_frame_idx; - - fs->frame->top_field = fs->top_field; - if (fs->bottom_field) - fs->frame->bottom_field = fs->bottom_field; - fs->frame->frame = fs->frame; - - fs->frame->coded_frame = 0; - - fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc; - fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag; - if (fs->frame->frame_cropping_flag) { - fs->frame->frame_crop_top_offset = - fs->top_field->frame_crop_top_offset; - fs->frame->frame_crop_bottom_offset = - fs->top_field->frame_crop_bottom_offset; - fs->frame->frame_crop_left_offset = - fs->top_field->frame_crop_left_offset; - fs->frame->frame_crop_right_offset = - fs->top_field->frame_crop_right_offset; - } - if (fs->bottom_field) { - fs->top_field->frame = fs->bottom_field->frame = fs->frame; - fs->top_field->top_field = fs->top_field; - fs->top_field->bottom_field = fs->bottom_field; - fs->bottom_field->top_field = fs->top_field; - fs->bottom_field->bottom_field = fs->bottom_field; - } - - /**/ -#if (MVC_EXTENSION_ENABLE) - fs->frame->view_id = fs->view_id; -#endif - fs->frame->iCodingType = fs->top_field->iCodingType; - /* FIELD_CODING ;*/ -} - -static void calculate_frame_no(struct VideoParameters *p_Vid, - struct StorablePicture *p) -{ -#if 0 -/* ??? */ - InputParameters *p_Inp = p_Vid->p_Inp; - /* calculate frame number */ - int psnrPOC = p_Vid->active_sps->mb_adaptive_frame_field_flag ? - p->poc / (p_Inp->poc_scale) : p->poc / (p_Inp->poc_scale); - - if (psnrPOC == 0) { /* && p_Vid->psnr_number) */ - p_Vid->idr_psnr_number = - p_Vid->g_nFrame * p_Vid->ref_poc_gap / (p_Inp->poc_scale); - } - p_Vid->psnr_number = imax(p_Vid->psnr_number, - p_Vid->idr_psnr_number + psnrPOC); - - p_Vid->frame_no = p_Vid->idr_psnr_number + psnrPOC; -#endif -} - -static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, - struct FrameStore *fs, - struct StorablePicture *p, - unsigned char data_flag) -{ - struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; - /* InputParameters *p_Inp = p_Vid->p_Inp; - * dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - * "insert (%s) pic with frame_num #%d, poc %d\n", - * (p->structure == FRAME)?"FRAME": - * (p->structure == TOP_FIELD)?"TOP_FIELD": - * "BOTTOM_FIELD", p->pic_num, p->poc); - * assert (p!=NULL); - * assert (fs!=NULL); - */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s %p %p\n", __func__, fs, p); -#if 1 -/* rain */ -/* p->buf_spec_num = fs->index; */ - p->data_flag = data_flag; - fs->data_flag |= data_flag; - fs->buf_spec_num = p->buf_spec_num; - fs->colocated_buf_index = p->colocated_buf_index; -#endif - p->slice_type = p_H264_Dpb->mSlice.slice_type; - switch (p->structure) { - case FRAME: - fs->frame = p; - fs->is_used = 3; - fs->slice_type = p->slice_type; - fs->frame_size = p->frame_size; - if (p->used_for_reference) { - fs->is_reference = 3; - fs->is_orig_reference = 3; - if (p->is_long_term) { - fs->is_long_term = 3; - fs->long_term_frame_idx = - p->long_term_frame_idx; - } - } - fs->layer_id = p->layer_id; -#if (MVC_EXTENSION_ENABLE) - fs->view_id = p->view_id; - fs->inter_view_flag[0] = fs->inter_view_flag[1] = - p->inter_view_flag; - fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] = - p->anchor_pic_flag; -#endif - /* generate field views */ - /* return; */ - dpb_split_field(p_H264_Dpb, fs); - /* return; */ - break; - case TOP_FIELD: - fs->top_field = p; - fs->is_used |= 1; - fs->layer_id = p->layer_id; - if (fs->frame_size == 0) { - fs->slice_type = p->slice_type; -// fs->pts = p->pts; -// fs->pts64 = p->pts64; - } - fs->frame_size += p->frame_size; -#if (MVC_EXTENSION_ENABLE) - fs->view_id = p->view_id; - fs->inter_view_flag[0] = p->inter_view_flag; - fs->anchor_pic_flag[0] = p->anchor_pic_flag; -#endif - if (p->used_for_reference) { - fs->is_reference |= 1; - fs->is_orig_reference |= 1; - if (p->is_long_term) { - fs->is_long_term |= 1; - fs->long_term_frame_idx = - p->long_term_frame_idx; - } - } - if (fs->is_used == 3) { - /* generate frame view */ - dpb_combine_field(p_H264_Dpb, fs); - } else { - fs->poc = p->poc; - } - gen_field_ref_ids(p_Vid, p); - break; - case BOTTOM_FIELD: - fs->bottom_field = p; - fs->is_used |= 2; - fs->layer_id = p->layer_id; - if (fs->frame_size == 0) { - fs->slice_type = p->slice_type; -// fs->pts = p->pts; -// fs->pts64 = p->pts64; - } - fs->frame_size += p->frame_size; -#if (MVC_EXTENSION_ENABLE) - fs->view_id = p->view_id; - fs->inter_view_flag[1] = p->inter_view_flag; - fs->anchor_pic_flag[1] = p->anchor_pic_flag; -#endif - if (p->used_for_reference) { - fs->is_reference |= 2; - fs->is_orig_reference |= 2; - if (p->is_long_term) { - fs->is_long_term |= 2; - fs->long_term_frame_idx = - p->long_term_frame_idx; - } - } - if (fs->is_used == 3) { - /* generate frame view */ - dpb_combine_field(p_H264_Dpb, fs); - } else { - fs->poc = p->poc; - } - gen_field_ref_ids(p_Vid, p); - break; - } - fs->frame_num = p->pic_num; - fs->recovery_frame = p->recovery_frame; - - fs->is_output = p->is_output; - fs->pre_output = p->pre_output; - - /* picture qos infomation*/ - fs->max_mv = p->max_mv; - fs->avg_mv = p->avg_mv; - fs->min_mv = p->min_mv; - - fs->max_qp = p->max_qp; - fs->avg_qp = p->avg_qp; - fs->min_qp = p->min_qp; - - fs->max_skip = p->max_skip; - fs->avg_skip = p->avg_skip; - fs->min_skip = p->min_skip; - - if (fs->is_used == 3) { - calculate_frame_no(p_Vid, p); -#if 0 -/* ??? */ - if (-1 != p_Vid->p_ref && !p_Inp->silent) - find_snr(p_Vid, fs->frame, &p_Vid->p_ref); -#endif - } - - fs->pts = p->pts; - fs->pts64 = p->pts64; - fs->timestamp = p->timestamp; -} - -void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb, - struct FrameStore *f) -{ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - - if (f) { - if (f->frame) { - free_picture(p_H264_Dpb, f->frame); - f->frame = NULL; - } - if (f->top_field) { - free_picture(p_H264_Dpb, f->top_field); - f->top_field = NULL; - } - if (f->bottom_field) { - free_picture(p_H264_Dpb, f->bottom_field); - f->bottom_field = NULL; - } - - /**/ - f->is_used = 0; - f->is_reference = 0; - f->is_long_term = 0; - f->is_orig_reference = 0; - - f->is_output = 0; - f->pre_output = 0; - - f->frame = NULL; - f->top_field = NULL; - f->bottom_field = NULL; - - /* free(f); */ - } -} - -static void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb, - struct FrameStore *fs) -{ - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s %p %p %p %p\n", __func__, - fs, fs->frame, fs->top_field, fs->bottom_field); - /* return; */ - if (fs->is_used & 1) { - if (fs->top_field) - fs->top_field->used_for_reference = 0; - } - if (fs->is_used & 2) { - if (fs->bottom_field) - fs->bottom_field->used_for_reference = 0; - } - if (fs->is_used == 3) { - if (fs->top_field && fs->bottom_field) { - fs->top_field->used_for_reference = 0; - fs->bottom_field->used_for_reference = 0; - } - fs->frame->used_for_reference = 0; - } - - fs->is_reference = 0; - -} - -int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb, - int buf_spec_num) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - unsigned int i; - - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->buf_spec_num == buf_spec_num) - return p_Dpb->fs[i]->is_long_term; - } - return -1; -} - -static void update_pic_num(struct h264_dpb_stru *p_H264_Dpb) -{ - unsigned int i; - struct Slice *currSlice = &p_H264_Dpb->mSlice; - struct VideoParameters *p_Vid = currSlice->p_Vid; - struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb; - struct SPSParameters *active_sps = p_Vid->active_sps; - int add_top = 0, add_bottom = 0; - int max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4); - - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL || - p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_used == 3) { - if ((p_Dpb->fs_ref[i]->frame-> - used_for_reference) && - (!p_Dpb->fs_ref[i]->frame-> - is_long_term)) { - if (p_Dpb->fs_ref[i]->frame_num > - currSlice->frame_num) { - p_Dpb->fs_ref[i]-> - frame_num_wrap = - p_Dpb->fs_ref[i]->frame_num - - max_frame_num; - } else { - p_Dpb->fs_ref[i]-> - frame_num_wrap = - p_Dpb->fs_ref[i]->frame_num; - } - p_Dpb->fs_ref[i]->frame->pic_num = - p_Dpb->fs_ref[i]->frame_num_wrap; - } - } - } - /* update long_term_pic_num */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ltref[i] == NULL || - p_Dpb->fs_ltref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ltref[i]->is_used == 3) { - if (p_Dpb->fs_ltref[i]->frame->is_long_term) { - p_Dpb->fs_ltref[i]->frame-> - long_term_pic_num = - p_Dpb->fs_ltref[i]->frame-> - long_term_frame_idx; - } - } - } - } else { - if (currSlice->structure == TOP_FIELD) { - add_top = 1; - add_bottom = 0; - } else { - add_top = 0; - add_bottom = 1; - } - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference) { - if (p_Dpb->fs_ref[i]->frame_num > currSlice-> - frame_num) { - p_Dpb->fs_ref[i]->frame_num_wrap = - p_Dpb->fs_ref[i]->frame_num - - max_frame_num; - } else { - p_Dpb->fs_ref[i]->frame_num_wrap = - p_Dpb->fs_ref[i]->frame_num; - } - if (p_Dpb->fs_ref[i]->is_reference & 1) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->top_field - == NULL) { - p_H264_Dpb->dpb_error_flag = - __LINE__; - continue; - } -#endif - p_Dpb->fs_ref[i]->top_field-> - pic_num = (2 * p_Dpb->fs_ref[i]-> - frame_num_wrap) + add_top; - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->bottom_field - == NULL) { - p_H264_Dpb->dpb_error_flag = - __LINE__; - continue; - } -#endif - p_Dpb->fs_ref[i]->bottom_field-> - pic_num = (2 * p_Dpb->fs_ref[i]-> - frame_num_wrap) + add_bottom; - } - } - } - /* update long_term_pic_num */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ltref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ltref[i]->is_long_term & 1) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ltref[i]->top_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - p_Dpb->fs_ltref[i]->top_field-> - long_term_pic_num = 2 * - p_Dpb->fs_ltref[i]->top_field-> - long_term_frame_idx + add_top; - } - if (p_Dpb->fs_ltref[i]->is_long_term & 2) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ltref[i]->bottom_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - p_Dpb->fs_ltref[i]->bottom_field-> - long_term_pic_num = 2 * - p_Dpb->fs_ltref[i]->bottom_field-> - long_term_frame_idx + add_bottom; - } - } - } -} - -static void remove_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb, int pos) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - struct FrameStore *fs = p_Dpb->fs[pos]; - struct FrameStore *tmp; - unsigned int i; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s pos %d %p\n", __func__, pos, fs); - - /* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - * "remove frame with frame_num #%d\n", fs->frame_num); - */ - switch (fs->is_used) { - case 3: - free_picture(p_H264_Dpb, fs->frame); - free_picture(p_H264_Dpb, fs->top_field); - free_picture(p_H264_Dpb, fs->bottom_field); - fs->frame = NULL; - fs->top_field = NULL; - fs->bottom_field = NULL; - break; - case 2: - free_picture(p_H264_Dpb, fs->bottom_field); - fs->bottom_field = NULL; - break; - case 1: - free_picture(p_H264_Dpb, fs->top_field); - fs->top_field = NULL; - break; - case 0: - break; - default: - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "invalid frame store type %x", 500); - } - fs->data_flag = 0; - fs->is_used = 0; - fs->is_long_term = 0; - fs->is_reference = 0; - fs->is_orig_reference = 0; - fs->frame_size = 0; - /* move empty framestore to end of buffer */ - tmp = p_Dpb->fs[pos]; - - for (i = pos; i < p_Dpb->used_size - 1; i++) - p_Dpb->fs[i] = p_Dpb->fs[i + 1]; - p_Dpb->fs[p_Dpb->used_size - 1] = tmp; - p_Dpb->used_size--; -} - -static int is_used_for_reference(struct FrameStore *fs) -{ - if (fs->is_reference) - return 1; - - if (fs->is_used == 3) { /* frame */ - if (fs->frame->used_for_reference) - return 1; - } - - if (fs->is_used & 1) { /* top field */ - if (fs->top_field) { - if (fs->top_field->used_for_reference) - return 1; - } - } - - if (fs->is_used & 2) { /* bottom field */ - if (fs->bottom_field) { - if (fs->bottom_field->used_for_reference) - return 1; - } - } - return 0; -} - -static int remove_unused_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb) -{ - unsigned int i; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - /* check for frames that were already output and no longer - * used for reference - */ - for (i = 0; i < p_Dpb->used_size; i++) { - if ((!is_used_for_reference(p_Dpb->fs[i])) && - (p_Dpb->fs[i]->colocated_buf_index >= 0)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "release_colocate_buf[%d] for fs[%d]\n", - p_Dpb->fs[i]->colocated_buf_index, i); - - release_colocate_buf(p_H264_Dpb, - p_Dpb->fs[i]->colocated_buf_index); /* rain */ - p_Dpb->fs[i]->colocated_buf_index = -1; - } - } - - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_output && - (!is_used_for_reference(p_Dpb->fs[i]))) { - release_buf_spec_num(p_H264_Dpb->vdec, - p_Dpb->fs[i]->buf_spec_num); - p_Dpb->fs[i]->buf_spec_num = -1; - remove_frame_from_dpb(p_H264_Dpb, i); - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%s[%d]\n", - __func__, i); - - return 1; - } - } - return 0; -} - -static int unmark_one_error_out_frame(struct h264_dpb_stru *p_H264_Dpb) -{ - int ret = 0; - unsigned i; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_output && - ((p_Dpb->fs[i]->data_flag & ERROR_FLAG) || - (p_Dpb->fs[i]->data_flag & NULL_FLAG)) - ) { - unmark_for_reference(p_Dpb, p_Dpb->fs[i]); - - ret = 1; - } - } - return ret; -} - -static int unmark_one_out_frame(struct h264_dpb_stru *p_H264_Dpb) -{ - int ret = 0; - unsigned i; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_output) { - unmark_for_reference(p_Dpb, p_Dpb->fs[i]); - - ret = 1; - } - } - return ret; -} -/* - force_flag, - 1, remove one error buf (is_out is 1) if there is no un-used buf - 2, remove one buf (is_out is 1) if there is no un-used buf -*/ -void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb, - u8 force_flag) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - int ret = 0; - unsigned char removed_flag = 0; - do { - ret = remove_unused_frame_from_dpb(p_H264_Dpb); - if (ret != 0) - removed_flag = 1; - } while (ret != 0); - if (removed_flag) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%s\r\n", __func__); - dump_dpb(p_Dpb, 0); - } else if (force_flag == 2) { - if (unmark_one_out_frame(p_H264_Dpb)) { - dpb_print(p_H264_Dpb->decoder_index, - 0, "%s, Warnning, force unmark one frame\r\n", - __func__); - remove_unused_frame_from_dpb(p_H264_Dpb); - dump_dpb(p_Dpb, 0); - } - } else if (force_flag == 1) { - if (unmark_one_error_out_frame(p_H264_Dpb)) { - dpb_print(p_H264_Dpb->decoder_index, - 0, "%s, unmark error frame\r\n", - __func__); - remove_unused_frame_from_dpb(p_H264_Dpb); - dump_dpb(p_Dpb, 0); - } - } -} - -#ifdef OUTPUT_BUFFER_IN_C -int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb) -{ - unsigned int i; - - /* check for frames that were already output and no longer - * used for reference - */ - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_output && - (!is_used_for_reference(p_Dpb->fs[i]))) { - return 1; - } - } - return 0; -} -#endif - -static void get_smallest_poc(struct DecodedPictureBuffer *p_Dpb, int *poc, - int *pos) -{ - unsigned int i; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%s\n", __func__); - if (p_Dpb->used_size < 1) { - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "Cannot determine smallest POC, DPB empty. %d\n", - 150); - } - - *pos = -1; - *poc = INT_MAX; - for (i = 0; i < p_Dpb->used_size; i++) { -#ifdef OUTPUT_BUFFER_IN_C - /* rain */ - if ((*poc > p_Dpb->fs[i]->poc) && - (!p_Dpb->fs[i]->is_output) && - (!p_Dpb->fs[i]->pre_output) && - (p_Dpb->fs[i]->is_used == 3)) { -#else - if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) { -#endif - *poc = p_Dpb->fs[i]->poc; - *pos = i; - } - } -} - -int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) -{ - int poc, pos; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - int i; - int none_displayed_num = 0; - unsigned char fast_output_flag = 0; - if (!flush_flag) { - for (i = 0; i < p_Dpb->used_size; i++) { - if ((!p_Dpb->fs[i]->is_output) && - (!p_Dpb->fs[i]->pre_output) && (p_Dpb->fs[i]->is_used == 3)) { - none_displayed_num++; - if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE) - && (p_Dpb->fs[i]->is_used == 3) - && (p_Dpb->last_output_poc == INT_MIN)) { - p_H264_Dpb->first_insert_frame = FirstInsertFrm_OUT; - p_H264_Dpb->first_output_poc = p_Dpb->fs[i]->poc; - fast_output_flag = 1; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s first insert frame i %d poc %d frame_num %x\n", - __func__, i, p_Dpb->fs[i]->poc, p_Dpb->fs[i]->frame_num); - } - /*check poc even/odd*/ - if (p_H264_Dpb->poc_even_odd_flag == 0 && - p_H264_Dpb->decode_pic_count >= 3) - p_H264_Dpb->poc_even_odd_flag = 2; - if (p_Dpb->fs[i]->poc & 0x1) - p_H264_Dpb->poc_even_odd_flag = 1; - /**/ - - if ((p_H264_Dpb->fast_output_enable & 0x1) && - (p_Dpb->fs[i]->data_flag & IDR_FLAG)) - fast_output_flag = 1; - if ((p_H264_Dpb->fast_output_enable & 0x2) && - ((p_Dpb->fs[i]->poc - - p_Dpb->last_output_poc) - == 1)) - fast_output_flag = 1; - if ((p_H264_Dpb->fast_output_enable & 0x4) && - (p_H264_Dpb->poc_even_odd_flag == 2) && - (p_Dpb->fs[i]->is_used == 3) && - ((p_Dpb->fs[i]->poc - - p_Dpb->last_output_poc) - == 2)) - fast_output_flag = 1; - } - } - if (fast_output_flag) - ; - else if (none_displayed_num < - p_H264_Dpb->reorder_pic_num) - return 0; - } - - get_smallest_poc(p_Dpb, &poc, &pos); - - if (pos == -1) - return 0; -#if 0 - if (is_used_for_reference(p_Dpb->fs[pos])) - return 0; -#endif - if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) { - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s pos %d pos->poc %d first_output_poc %d \n", - __func__, pos, p_Dpb->fs[pos]->poc, p_H264_Dpb->first_output_poc); - - if (p_Dpb->fs[pos]->poc < p_H264_Dpb->first_output_poc) - p_Dpb->fs[pos]->data_flag |= NODISP_FLAG; - else if (p_Dpb->last_output_poc != INT_MIN) - p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s first_insert_frame %d \n", __func__, p_H264_Dpb->first_insert_frame); - } - if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) - p_Dpb->fs[pos]->pre_output = 1; - else { - if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { - dpb_print(p_H264_Dpb->decoder_index, 0, - "%s[%d] poc:%d last_output_poc:%d poc_even_odd_flag:%d\n", - __func__, pos, poc, - p_Dpb->last_output_poc, - p_H264_Dpb->poc_even_odd_flag); - dump_dpb(p_Dpb, 1); - } - return 0; - } - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s[%d] poc %d last_output_poc %d poc_even_odd_flag %d\n", - __func__, pos, poc, - p_Dpb->last_output_poc, - p_H264_Dpb->poc_even_odd_flag); - - p_Dpb->last_output_poc = poc; - return 1; - -} - - -void flush_dpb(struct h264_dpb_stru *p_H264_Dpb) -{ - /* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - unsigned int i; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - - /* diagnostics */ - /* dpb_print(p_H264_Dpb->decoder_index, - *PRINT_FLAG_DPB_DETAIL, - *"Flush remaining frames from the dpb." - *"p_Dpb->size = %d, p_Dpb->used_size = %d\n", - *p_Dpb->size, p_Dpb->used_size); - */ - - if (!p_Dpb->init_done) - return; -/* if(p_Vid->conceal_mode == 0) */ -#if 0 -/* ??? */ - if (p_Vid->conceal_mode != 0) - conceal_non_ref_pics(p_Dpb, 0); -#endif - /* mark all frames unused */ - for (i = 0; i < p_Dpb->used_size; i++) { -#if MVC_EXTENSION_ENABLE - assert(p_Dpb->fs[i]->view_id == p_Dpb->layer_id); -#endif - unmark_for_reference(p_Dpb, p_Dpb->fs[i]); - - } - - while (remove_unused_frame_from_dpb(p_H264_Dpb)) - ; - - /* output frames in POC order */ - while (output_frames(p_H264_Dpb, 1)) - ; - - - p_Dpb->last_output_poc = INT_MIN; -} - -static int is_short_term_reference(struct DecodedPictureBuffer *p_Dpb, - struct FrameStore *fs) -{ - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - if (fs->is_used == 3) { /* frame */ - if ((fs->frame->used_for_reference) && - (!fs->frame->is_long_term)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "[[%s 1]]", - __func__); - return 1; - } - } - - if (fs->is_used & 1) { /* top field */ - if (fs->top_field) { - if ((fs->top_field->used_for_reference) && - (!fs->top_field->is_long_term)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "[[%s 2]]", - __func__); - return 1; - } - } - } - - if (fs->is_used & 2) { /* bottom field */ - if (fs->bottom_field) { - if ((fs->bottom_field->used_for_reference) && - (!fs->bottom_field->is_long_term)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "[[%s 3]]", - __func__); - return 1; - } - } - } - return 0; -} - -static int is_long_term_reference(struct FrameStore *fs) -{ - - if (fs->is_used == 3) { /* frame */ - if ((fs->frame->used_for_reference) && - (fs->frame->is_long_term)) { - return 1; - } - } - - if (fs->is_used & 1) { /* top field */ - if (fs->top_field) { - if ((fs->top_field->used_for_reference) && - (fs->top_field->is_long_term)) { - return 1; - } - } - } - - if (fs->is_used & 2) { /* bottom field */ - if (fs->bottom_field) { - if ((fs->bottom_field->used_for_reference) && - (fs->bottom_field->is_long_term)) { - return 1; - } - } - } - return 0; -} - -static void update_ref_list(struct DecodedPictureBuffer *p_Dpb) -{ - unsigned int i, j; - - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s (%d, %d)\n", __func__, p_Dpb->size, p_Dpb->used_size); - for (i = 0, j = 0; i < p_Dpb->used_size; i++) { -#if 1 - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "fs[%d]: fs %p frame %p is_reference %d %d %d\n", - i, p_Dpb->fs[i], p_Dpb->fs[i]->frame, - p_Dpb->fs[i]->frame != NULL ? - p_Dpb->fs[i]->frame->used_for_reference : 0, - p_Dpb->fs[i]->top_field != NULL ? - p_Dpb->fs[i]->top_field->used_for_reference : - 0, - p_Dpb->fs[i]->bottom_field != NULL ? - p_Dpb->fs[i]->bottom_field->used_for_reference : 0); -#endif - if (is_short_term_reference(p_Dpb, p_Dpb->fs[i])) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "fs_ref[%d]=fs[%d]: fs %p\n", j, i, p_Dpb->fs[i]); - p_Dpb->fs_ref[j++] = p_Dpb->fs[i]; - } - } - - p_Dpb->ref_frames_in_buffer = j; - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s dpb size is %d, %d\n", __func__, p_Dpb->size, j); - while (j < p_Dpb->size) { - /* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - *"fs_ref[%d]=null\n", j); - */ - p_Dpb->fs_ref[j++] = NULL; - } -#ifdef ERROR_CHECK - for (i = 0; i < DPB_SIZE_MAX; i++) { - if (p_Dpb->fs_ref[i] == NULL) - p_Dpb->fs_ref[i] = &dummy_fs; - } -#endif -} - -static void update_ltref_list(struct DecodedPictureBuffer *p_Dpb) -{ - unsigned int i, j; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - for (i = 0, j = 0; i < p_Dpb->used_size; i++) { - if (is_long_term_reference(p_Dpb->fs[i])) - p_Dpb->fs_ltref[j++] = p_Dpb->fs[i]; - } - - p_Dpb->ltref_frames_in_buffer = j; - - while (j < p_Dpb->size) - p_Dpb->fs_ltref[j++] = NULL; -#ifdef ERROR_CHECK - for (i = 0; i < DPB_SIZE_MAX; i++) { - if (p_Dpb->fs_ltref[i] == NULL) - p_Dpb->fs_ltref[i] = &dummy_fs; - } -#endif -} - -static void idr_memory_management(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *p) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s ref_frames_in_buffer %d ltref_frames_in_buffer %d\n", - __func__, p_Dpb->ref_frames_in_buffer, - p_Dpb->ltref_frames_in_buffer); - - - if (p->no_output_of_prior_pics_flag) { -#if 0 - /*???*/ - /* free all stored pictures */ - int i; - - for (i = 0; i < p_Dpb->used_size; i++) { - /* reset all reference settings - * free_frame_store(p_Dpb->fs[i]); - * p_Dpb->fs[i] = alloc_frame_store(); - */ - reset_frame_store(p_H264_Dpb, p_Dpb->fs[i]); /* ??? */ - } - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) - p_Dpb->fs_ref[i] = NULL; - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) - p_Dpb->fs_ltref[i] = NULL; - p_Dpb->used_size = 0; -#endif - } else { - flush_dpb(p_H264_Dpb); - } - p_Dpb->last_picture = NULL; - - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - p_Dpb->last_output_poc = INT_MIN; - - if (p->long_term_reference_flag) { - p_Dpb->max_long_term_pic_idx = 0; - p->is_long_term = 1; - p->long_term_frame_idx = 0; - } else { - p_Dpb->max_long_term_pic_idx = -1; - p->is_long_term = 0; - } - -#if (MVC_EXTENSION_ENABLE) - p_Dpb->last_output_view_id = -1; -#endif - -} - -static void sliding_window_memory_management( - struct DecodedPictureBuffer *p_Dpb, - struct StorablePicture *p) -{ - unsigned int i; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - unsigned char slide_flag = 0; - unsigned int sliding_margin = imax( - 1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer; - /* assert (!p->idr_flag); */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s ref_frames_in_buffer %d ltref_frames_in_buffer %d\n", - __func__, p_Dpb->ref_frames_in_buffer, - p_Dpb->ltref_frames_in_buffer); - /* if this is a reference pic with sliding window, - unmark first ref frame */ - if (p_Dpb->ref_frames_in_buffer == sliding_margin) - slide_flag = 1; - /*else if ((h264_error_proc_policy & 0x8) && - (p_Dpb->ref_frames_in_buffer > sliding_margin)) - slide_flag = 1;*/ - - if (slide_flag) { - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_reference && - (!(p_Dpb->fs[i]->is_long_term))) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "unmark %d\n", i); - unmark_for_reference(p_Dpb, p_Dpb->fs[i]); - update_ref_list(p_Dpb); - break; - } - } - } - - p->is_long_term = 0; -} - -static void check_num_ref(struct DecodedPictureBuffer *p_Dpb) -{ - if ((int)(p_Dpb->ltref_frames_in_buffer + - p_Dpb->ref_frames_in_buffer) > - imax(1, p_Dpb->num_ref_frames)) { - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "Max. number of reference frames exceeded. Invalid stream. lt %d ref %d mum_ref %d\n", - p_Dpb->ltref_frames_in_buffer, - p_Dpb->ref_frames_in_buffer, - p_Dpb->num_ref_frames); - } -} - -void dump_dpb(struct DecodedPictureBuffer *p_Dpb, u8 force) -{ - unsigned i; - struct h264_dpb_stru *p_H264_Dpb = - container_of(p_Dpb, struct h264_dpb_stru, mDPB); - if ((h264_debug_flag & PRINT_FLAG_DUMP_DPB) == 0 && - force == 0) - return; - for (i = 0; i < p_Dpb->used_size; i++) { - dpb_print(p_H264_Dpb->decoder_index, - 0, - "("); - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "fn=%d is_used %d ", - p_Dpb->fs[i]->frame_num, - p_Dpb->fs[i]->is_used); - if (p_Dpb->fs[i]->is_used & 1) { - if (p_Dpb->fs[i]->top_field) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "T: poc=%d pic_num=%d ", - p_Dpb->fs[i]->top_field->poc, - p_Dpb->fs[i]->top_field->pic_num); - else - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "T: poc=%d ", - p_Dpb->fs[i]->frame->top_poc); - } - if (p_Dpb->fs[i]->is_used & 2) { - if (p_Dpb->fs[i]->bottom_field) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "B: poc=%d pic_num=%d ", - p_Dpb->fs[i]->bottom_field->poc, - p_Dpb->fs[i]->bottom_field->pic_num); - else - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "B: poc=%d ", - p_Dpb->fs[i]->frame->bottom_poc); - } - if (p_Dpb->fs[i]->is_used == 3) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "F: poc=%d pic_num=%d ", - p_Dpb->fs[i]->frame->poc, - p_Dpb->fs[i]->frame->pic_num); - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "G: poc=%d) ", p_Dpb->fs[i]->poc); - if (p_Dpb->fs[i]->is_reference) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "ref (%d) ", p_Dpb->fs[i]->is_reference); - if (p_Dpb->fs[i]->is_long_term) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "lt_ref (%d) ", p_Dpb->fs[i]->is_reference); - if (p_Dpb->fs[i]->is_output) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "out(displayed) "); - if (p_Dpb->fs[i]->pre_output) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "pre_output(in dispq or displaying) "); - if (p_Dpb->fs[i]->is_used == 3) { - if (p_Dpb->fs[i]->frame->non_existing) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "non_existing "); - } -#if (MVC_EXTENSION_ENABLE) - if (p_Dpb->fs[i]->is_reference) - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "view_id (%d) ", p_Dpb->fs[i]->view_id); -#endif - if (p_Dpb->fs[i]->data_flag) { - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - "data_flag(0x%x)", - p_Dpb->fs[i]->data_flag); - } - dpb_print_cont(p_H264_Dpb->decoder_index, - 0, - " bufspec %d\n", - p_Dpb->fs[i]->buf_spec_num); - } -} - -/*! - ************************************************************************ - * \brief - * adaptive memory management - * - ************************************************************************ - */ - -static int get_pic_num_x(struct StorablePicture *p, - int difference_of_pic_nums_minus1) -{ - int currPicNum; - - if (p->structure == FRAME) - currPicNum = p->frame_num; - else - currPicNum = 2 * p->frame_num + 1; - - return currPicNum - (difference_of_pic_nums_minus1 + 1); -} - -/*! - ************************************************************************ - * \brief - * Adaptive Memory Management: Mark short term picture unused - ************************************************************************ - */ -static void mm_unmark_short_term_for_reference(struct DecodedPictureBuffer - *p_Dpb, struct StorablePicture *p, - int difference_of_pic_nums_minus1) -{ - struct h264_dpb_stru *p_H264_Dpb = - container_of(p_Dpb, struct h264_dpb_stru, mDPB); - int picNumX; - - unsigned int i; - - picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p->structure == FRAME) { - if ((p_Dpb->fs_ref[i]->is_reference == 3) && - (p_Dpb->fs_ref[i]->is_long_term == 0)) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->frame->pic_num == - picNumX) { - unmark_for_reference(p_Dpb, - p_Dpb->fs_ref[i]); - return; - } - } - } else { - if ((p_Dpb->fs_ref[i]->is_reference & 1) && - (!(p_Dpb->fs_ref[i]->is_long_term & 1))) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->top_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->top_field->pic_num == - picNumX) { - p_Dpb->fs_ref[i]-> - top_field->used_for_reference = 0; - p_Dpb->fs_ref[i]->is_reference &= 2; - if ((p_Dpb->fs_ref[i]->is_used == 3) -#ifdef ERROR_CHECK - && p_Dpb->fs_ref[i]->frame -#endif - ) { - p_Dpb->fs_ref[i]->frame-> - used_for_reference = 0; - } - return; - } - } - if ((p_Dpb->fs_ref[i]->is_reference & 2) && - (!(p_Dpb->fs_ref[i]->is_long_term & 2))) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->bottom_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->bottom_field->pic_num == - picNumX) { - p_Dpb->fs_ref[i]->bottom_field-> - used_for_reference = 0; - p_Dpb->fs_ref[i]->is_reference &= 1; - if ((p_Dpb->fs_ref[i]->is_used == 3) -#ifdef ERROR_CHECK - && p_Dpb->fs_ref[i]->frame -#endif - ) { - p_Dpb->fs_ref[i]->frame-> - used_for_reference = 0; - } - return; - } - } - } - } -} - -static void unmark_for_long_term_reference(struct FrameStore *fs) -{ - if (fs->is_used & 1) { - if (fs->top_field) { - fs->top_field->used_for_reference = 0; - fs->top_field->is_long_term = 0; - } - } - if (fs->is_used & 2) { - if (fs->bottom_field) { - fs->bottom_field->used_for_reference = 0; - fs->bottom_field->is_long_term = 0; - } - } - if (fs->is_used == 3) { - if (fs->top_field && fs->bottom_field) { - fs->top_field->used_for_reference = 0; - fs->top_field->is_long_term = 0; - fs->bottom_field->used_for_reference = 0; - fs->bottom_field->is_long_term = 0; - } - fs->frame->used_for_reference = 0; - fs->frame->is_long_term = 0; - } - - fs->is_reference = 0; - fs->is_long_term = 0; -} - -/*! - ************************************************************************ - * \brief - * Adaptive Memory Management: Mark long term picture unused - ************************************************************************ - */ -static void mm_unmark_long_term_for_reference(struct DecodedPictureBuffer - *p_Dpb, struct StorablePicture *p, int long_term_pic_num) -{ - unsigned int i; - - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p->structure == FRAME) { - if ((p_Dpb->fs_ltref[i]->is_reference == 3) && - (p_Dpb->fs_ltref[i]->is_long_term == 3)) { - if (p_Dpb->fs_ltref[i]->frame-> - long_term_pic_num == - long_term_pic_num) { - unmark_for_long_term_reference( - p_Dpb->fs_ltref[i]); - } - } - } else { - if ((p_Dpb->fs_ltref[i]->is_reference & 1) && - ((p_Dpb->fs_ltref[i]->is_long_term & 1))) { - if (p_Dpb->fs_ltref[i]->top_field-> - long_term_pic_num == - long_term_pic_num) { - p_Dpb->fs_ltref[i]->top_field-> - used_for_reference = 0; - p_Dpb->fs_ltref[i]->top_field-> - is_long_term = 0; - p_Dpb->fs_ltref[i]->is_reference &= 2; - p_Dpb->fs_ltref[i]->is_long_term &= 2; - if (p_Dpb->fs_ltref[i]->is_used == 3) { - p_Dpb->fs_ltref[i]->frame-> - used_for_reference = 0; - p_Dpb->fs_ltref[i]->frame-> - is_long_term = 0; - } - return; - } - } - if ((p_Dpb->fs_ltref[i]->is_reference & 2) && - ((p_Dpb->fs_ltref[i]->is_long_term & 2))) { - if (p_Dpb->fs_ltref[i]->bottom_field-> - long_term_pic_num == - long_term_pic_num) { - p_Dpb->fs_ltref[i]->bottom_field-> - used_for_reference = 0; - p_Dpb->fs_ltref[i]->bottom_field-> - is_long_term = 0; - p_Dpb->fs_ltref[i]->is_reference &= 1; - p_Dpb->fs_ltref[i]->is_long_term &= 1; - if (p_Dpb->fs_ltref[i]->is_used == 3) { - p_Dpb->fs_ltref[i]->frame-> - used_for_reference = 0; - p_Dpb->fs_ltref[i]->frame-> - is_long_term = 0; - } - return; - } - } - } - } -} - - -/*! - ************************************************************************ - * \brief - * Mark a long-term reference frame or complementary - * field pair unused for referemce - ************************************************************************ - */ -static void unmark_long_term_frame_for_reference_by_frame_idx( - struct DecodedPictureBuffer *p_Dpb, int long_term_frame_idx) -{ - unsigned int i; - - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->long_term_frame_idx == - long_term_frame_idx) - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } -} - - -static void unmark1(struct DecodedPictureBuffer *p_Dpb, - unsigned int curr_frame_num, int i) -{ - if (p_Dpb->last_picture) { - /*if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || - p_Dpb->last_picture->frame_num != curr_frame_num) {*/ - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - /*} else { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - }*/ - } -} - -static void unmark2(struct DecodedPictureBuffer *p_Dpb, - int curr_pic_num, int i) -{ - if ((p_Dpb->fs_ltref[i]->frame_num) != - (unsigned int)(curr_pic_num >> 1)) - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); -} - -static void unmark3_top(struct DecodedPictureBuffer *p_Dpb, - unsigned int curr_frame_num, int curr_pic_num, int mark_current, int i) -{ - if (p_Dpb->fs_ltref[i]->is_long_term == 3) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (p_Dpb->fs_ltref[i]->is_long_term == 1) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (mark_current) - unmark1(p_Dpb, curr_frame_num, i); - else - unmark2(p_Dpb, curr_pic_num, i); - } - } -} - -static void unmark3_bottom(struct DecodedPictureBuffer *p_Dpb, - unsigned int curr_frame_num, int curr_pic_num, int mark_current, int i) -{ - if (p_Dpb->fs_ltref[i]->is_long_term == 2) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (mark_current) - unmark1(p_Dpb, curr_frame_num, i); - else - unmark2(p_Dpb, curr_pic_num, i); - } -} - -static void unmark_long_term_field_for_reference_by_frame_idx( - struct DecodedPictureBuffer *p_Dpb, enum PictureStructure structure, - int long_term_frame_idx, int mark_current, unsigned int curr_frame_num, - int curr_pic_num) -{ - struct VideoParameters *p_Vid = p_Dpb->p_Vid; - unsigned int i; - - /* assert(structure!=FRAME); */ - if (curr_pic_num < 0) - curr_pic_num += (2 * p_Vid->max_frame_num); - - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->long_term_frame_idx == - long_term_frame_idx) { - if (structure == TOP_FIELD) - unmark3_top(p_Dpb, curr_frame_num, - curr_pic_num, mark_current, i); - - if (structure == BOTTOM_FIELD) - unmark3_bottom(p_Dpb, curr_frame_num, - curr_pic_num, mark_current, i); - } - } -} - -/*! - ************************************************************************ - * \brief - * mark a picture as long-term reference - ************************************************************************ - */ -static void mark_pic_long_term(struct DecodedPictureBuffer *p_Dpb, - struct StorablePicture *p, - int long_term_frame_idx, int picNumX) -{ - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - unsigned int i; - int add_top, add_bottom; - - if (p->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference == 3) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((!p_Dpb->fs_ref[i]->frame-> - is_long_term) && - (p_Dpb->fs_ref[i]->frame->pic_num == - picNumX)) { - p_Dpb->fs_ref[i]-> - long_term_frame_idx = - p_Dpb->fs_ref[i]->frame-> - long_term_frame_idx = - long_term_frame_idx; - p_Dpb->fs_ref[i]->frame-> - long_term_pic_num = - long_term_frame_idx; - p_Dpb->fs_ref[i]->frame-> - is_long_term = 1; - - if (p_Dpb->fs_ref[i]->top_field && - p_Dpb->fs_ref[i]->bottom_field) { - p_Dpb->fs_ref[i]->top_field-> - long_term_frame_idx = - p_Dpb->fs_ref[i]-> - bottom_field-> - long_term_frame_idx = - long_term_frame_idx; - p_Dpb->fs_ref[i]->top_field-> - long_term_pic_num = - long_term_frame_idx; - p_Dpb->fs_ref[i]-> - bottom_field-> - long_term_pic_num = - long_term_frame_idx; - - p_Dpb->fs_ref[i]->top_field-> - is_long_term = - p_Dpb->fs_ref[i]-> - bottom_field-> - is_long_term - = 1; - - } - p_Dpb->fs_ref[i]->is_long_term = 3; - return; - } - } - } - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "Warning: reference frame for long term marking not found\n"); - } else { - if (p->structure == TOP_FIELD) { - add_top = 1; - add_bottom = 0; - } else { - add_top = 0; - add_bottom = 1; - } - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference & 1) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->top_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((!p_Dpb->fs_ref[i]->top_field-> - is_long_term) && - (p_Dpb->fs_ref[i]->top_field->pic_num == - picNumX)) { - if ((p_Dpb->fs_ref[i]-> - is_long_term) && - (p_Dpb->fs_ref[i]-> - long_term_frame_idx != - long_term_frame_idx)) { - dpb_print(p_H264_Dpb-> - decoder_index, - PRINT_FLAG_DPB_DETAIL, - "Warning: assigning long_term_frame_idx different from other field\n"); - } - - p_Dpb->fs_ref[i]-> - long_term_frame_idx = - p_Dpb->fs_ref[i]->top_field-> - long_term_frame_idx - = long_term_frame_idx; - p_Dpb->fs_ref[i]->top_field-> - long_term_pic_num = - 2 * long_term_frame_idx + - add_top; - p_Dpb->fs_ref[i]->top_field-> - is_long_term = 1; - p_Dpb->fs_ref[i]->is_long_term |= 1; - if ((p_Dpb->fs_ref[i]->is_long_term - == 3) -#ifdef ERROR_CHECK - && p_Dpb->fs_ref[i]->frame -#endif - ) { - p_Dpb->fs_ref[i]->frame-> - is_long_term = 1; - p_Dpb->fs_ref[i]->frame-> - long_term_frame_idx = - p_Dpb->fs_ref[i]-> - frame-> - long_term_pic_num = - long_term_frame_idx; - } - return; - } - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->bottom_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((!p_Dpb->fs_ref[i]->bottom_field-> - is_long_term) && - (p_Dpb->fs_ref[i]->bottom_field->pic_num - == picNumX)) { - if ((p_Dpb->fs_ref[i]-> - is_long_term) && - (p_Dpb->fs_ref[i]-> - long_term_frame_idx != - long_term_frame_idx)) { - dpb_print(p_H264_Dpb-> - decoder_index, - PRINT_FLAG_DPB_DETAIL, - "Warning: assigning long_term_frame_idx different from other field\n"); - } - - p_Dpb->fs_ref[i]-> - long_term_frame_idx = - p_Dpb->fs_ref[i]->bottom_field - ->long_term_frame_idx - = long_term_frame_idx; - p_Dpb->fs_ref[i]->bottom_field-> - long_term_pic_num = 2 * - long_term_frame_idx + - add_bottom; - p_Dpb->fs_ref[i]->bottom_field-> - is_long_term = 1; - p_Dpb->fs_ref[i]->is_long_term |= 2; - if ((p_Dpb->fs_ref[i]-> - is_long_term == 3) -#ifdef ERROR_CHECK - && p_Dpb->fs_ref[i]->frame -#endif - ) { - p_Dpb->fs_ref[i]->frame-> - is_long_term = 1; - p_Dpb->fs_ref[i]->frame-> - long_term_frame_idx = - p_Dpb->fs_ref[i]-> - frame-> - long_term_pic_num = - long_term_frame_idx; - } - return; - } - } - } - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "Warning: reference field for long term marking not found\n"); - } -} - - -/*! - ************************************************************************ - * \brief - * Assign a long term frame index to a short term picture - ************************************************************************ - */ -static void mm_assign_long_term_frame_idx(struct DecodedPictureBuffer *p_Dpb, - struct StorablePicture *p, int difference_of_pic_nums_minus1, - int long_term_frame_idx) -{ - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - int picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); - - /* remove frames/fields with same long_term_frame_idx */ - if (p->structure == FRAME) { - unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, - long_term_frame_idx); - } else { - unsigned int i; - enum PictureStructure structure = FRAME; - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference & 1) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->top_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->top_field-> - pic_num == picNumX) { - structure = TOP_FIELD; - break; - } - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->bottom_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->bottom_field-> - pic_num == picNumX) { - structure = BOTTOM_FIELD; - break; - } - } - } - if (structure == FRAME) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "field for long term marking not found %d", - 200); - } - - unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, - structure, - long_term_frame_idx, 0, 0, picNumX); - } - - mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX); -} - -/*! - ************************************************************************ - * \brief - * Set new max long_term_frame_idx - ************************************************************************ - */ -static void mm_update_max_long_term_frame_idx(struct DecodedPictureBuffer - *p_Dpb, int max_long_term_frame_idx_plus1) -{ - unsigned int i; - - p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1; - - /* check for invalid frames */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->long_term_frame_idx > - p_Dpb->max_long_term_pic_idx) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } -} - - -/*! - ************************************************************************ - * \brief - * Mark all long term reference pictures unused for reference - ************************************************************************ - */ -static void mm_unmark_all_long_term_for_reference(struct DecodedPictureBuffer - *p_Dpb) -{ - mm_update_max_long_term_frame_idx(p_Dpb, 0); -} - -/*! - ************************************************************************ - * \brief - * Mark all short term reference pictures unused for reference - ************************************************************************ - */ -static void mm_unmark_all_short_term_for_reference(struct DecodedPictureBuffer - *p_Dpb) -{ - unsigned int i; - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) - unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]); - update_ref_list(p_Dpb); -} - - -/*! - ************************************************************************ - * \brief - * Mark the current picture used for long term reference - ************************************************************************ - */ -static void mm_mark_current_picture_long_term(struct DecodedPictureBuffer - *p_Dpb, struct StorablePicture *p, int long_term_frame_idx) -{ - /* remove long term pictures with same long_term_frame_idx */ - if (p->structure == FRAME) { - unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, - long_term_frame_idx); - } else { - unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, - p->structure, long_term_frame_idx, - 1, p->pic_num, 0); - } - - p->is_long_term = 1; - p->long_term_frame_idx = long_term_frame_idx; -} - -static void adaptive_memory_management(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *p) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - struct DecRefPicMarking_s *tmp_drpm; - struct VideoParameters *p_Vid = p_Dpb->p_Vid; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - p_Vid->last_has_mmco_5 = 0; - - /* assert (!p->idr_flag); */ - /* assert (p->adaptive_ref_pic_buffering_flag); */ - - while (p->dec_ref_pic_marking_buffer) { - tmp_drpm = p->dec_ref_pic_marking_buffer; - switch (tmp_drpm->memory_management_control_operation) { - case 0: - if (tmp_drpm->Next != NULL) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "error, memory_management_control_operation = 0 not last operation in buffer\n"); - break; - case 1: - mm_unmark_short_term_for_reference(p_Dpb, p, - tmp_drpm->difference_of_pic_nums_minus1); - update_ref_list(p_Dpb); - break; - case 2: - mm_unmark_long_term_for_reference(p_Dpb, p, - tmp_drpm->long_term_pic_num); - update_ltref_list(p_Dpb); - break; - case 3: - mm_assign_long_term_frame_idx(p_Dpb, p, - tmp_drpm->difference_of_pic_nums_minus1, - tmp_drpm->long_term_frame_idx); - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - break; - case 4: - mm_update_max_long_term_frame_idx(p_Dpb, - tmp_drpm->max_long_term_frame_idx_plus1); - update_ltref_list(p_Dpb); - break; - case 5: - mm_unmark_all_short_term_for_reference(p_Dpb); - mm_unmark_all_long_term_for_reference(p_Dpb); - p_Vid->last_has_mmco_5 = 1; - break; - case 6: - mm_mark_current_picture_long_term(p_Dpb, p, - tmp_drpm->long_term_frame_idx); - check_num_ref(p_Dpb); - break; - default: - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "error, invalid memory_management_control_operation in buffer\n"); - } - p->dec_ref_pic_marking_buffer = tmp_drpm->Next; - /* free (tmp_drpm); */ - } - if (p_Vid->last_has_mmco_5) { - p->pic_num = p->frame_num = 0; - - switch (p->structure) { - case TOP_FIELD: { - /* p->poc = p->top_poc = p_Vid->toppoc =0; */ - p->poc = p->top_poc = 0; - break; - } - case BOTTOM_FIELD: { - /* p->poc = p->bottom_poc = p_Vid->bottompoc = 0; */ - p->poc = p->bottom_poc = 0; - break; - } - case FRAME: { - p->top_poc -= p->poc; - p->bottom_poc -= p->poc; - - /* p_Vid->toppoc = p->top_poc; */ - /* p_Vid->bottompoc = p->bottom_poc; */ - - p->poc = imin(p->top_poc, p->bottom_poc); - /* p_Vid->framepoc = p->poc; */ - break; - } - } - /* currSlice->ThisPOC = p->poc; */ -#if (MVC_EXTENSION_ENABLE) - if (p->view_id == 0) { - flush_dpb(p_Vid->p_Dpb_layer[0]); - flush_dpb(p_Vid->p_Dpb_layer[1]); - } else { - flush_dpb(p_Dpb); - } -#else - flush_dpb(p_H264_Dpb); -#endif - } -} - - -int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *p, - unsigned char data_flag) -{ - /* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */ - struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - unsigned int i; -#if 0 - int poc, pos; -#endif - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s p_Vid %p\n", __func__, p_Vid); - - /* picture error concealment */ - - /* diagnostics */ - /* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - * "Storing (%s) non-ref pic with frame_num #%d\n", - * (p->type == FRAME)?"FRAME":(p->type == TOP_FIELD)? - * "TOP_FIELD":"BOTTOM_FIELD", p->pic_num); - */ - /* if frame, check for new store, */ - /* assert (p!=NULL); */ - - p_Vid->last_has_mmco_5 = 0; - p_Vid->last_pic_bottom_field = (p->structure == BOTTOM_FIELD); - if (p->idr_flag) { - idr_memory_management(p_H264_Dpb, p); -#if 0 -/* ??? */ - /* picture error concealment */ - memset(p_Vid->pocs_in_dpb, 0, sizeof(int) * 100); -#endif - } else { -#if 1 -/* ??? */ - /* adaptive memory management */ - if (p->used_for_reference && - (p->adaptive_ref_pic_buffering_flag)) - adaptive_memory_management(p_H264_Dpb, p); -#endif - } - - if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) { - /* check for frame store with same pic_number */ - if (p_Dpb->last_picture) { - if ((int)p_Dpb->last_picture->frame_num == - p->pic_num) { - if (((p->structure == TOP_FIELD) && - (p_Dpb->last_picture->is_used == 2)) || - ((p->structure == BOTTOM_FIELD) && - (p_Dpb->last_picture->is_used == 1))) { - if ((p->used_for_reference && - (p_Dpb->last_picture-> - is_orig_reference != 0)) || - (!p->used_for_reference && - (p_Dpb->last_picture-> - is_orig_reference == 0))) { - insert_picture_in_dpb( - p_H264_Dpb, - p_Dpb->last_picture, - p, data_flag); - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - dump_dpb(p_Dpb, 0); - p_Dpb->last_picture = NULL; - return 0; - } - } - } - } - } - /* this is a frame or a field which has no stored - * complementary field - */ - - /* sliding window, if necessary */ - if ((!p->idr_flag) && (p->used_for_reference && - (!p->adaptive_ref_pic_buffering_flag))) { - sliding_window_memory_management(p_Dpb, p); - } - - /* picture error concealment */ - if (p_Vid->conceal_mode != 0) { - for (i = 0; i < p_Dpb->size; i++) - if (p_Dpb->fs[i]->is_reference) - p_Dpb->fs[i]->concealment_reference = 1; - } - - while (remove_unused_frame_from_dpb(p_H264_Dpb)) - ; - - while (output_frames(p_H264_Dpb, 0)) - ; - - /* check for duplicate frame number in short term reference buffer */ - if ((p->used_for_reference) && (!p->is_long_term)) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) - continue; -#endif - if (p_Dpb->fs_ref[i]->frame_num == p->frame_num) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "duplicate frame_num in short-term reference picture buffer %d\n", - 500); - } - } - } - /* store at end of buffer */ - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s p_Dpb->used_size %d\n", __func__, p_Dpb->used_size); - if (p_Dpb->used_size >= p_Dpb->size) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s Error: used_sizd %d is large than dpb size\r\n", - __func__, p_Dpb->used_size); - /*h264_debug_flag |= PRINT_FLAG_DUMP_DPB;*/ - dump_dpb(p_Dpb, 0); - return -1; - } - - insert_picture_in_dpb(p_H264_Dpb, p_Dpb->fs[p_Dpb->used_size], - p, data_flag); - - /* picture error concealment */ - if (p->idr_flag) - p_Vid->earlier_missing_poc = 0; - - if (p->structure != FRAME) - p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size]; - else - p_Dpb->last_picture = NULL; - - p_Dpb->used_size++; -#if 0 -/* ??? */ - if (p_Vid->conceal_mode != 0) - p_Vid->pocs_in_dpb[p_Dpb->used_size - 1] = p->poc; -#endif - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - - check_num_ref(p_Dpb); - if (p_H264_Dpb->fast_output_enable == H264_OUTPUT_MODE_FAST) - i = 1; - else - i = 0; - if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)) { - while (output_frames(p_H264_Dpb, i)) - ; - } - - dump_dpb(p_Dpb, 0); - p_Dpb->first_pic_done = 1; /*by rain*/ - - return 0; -} - -void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb) -{ - /*VideoParameters *p_Vid = p_Dpb->p_Vid;*/ - struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; - - if (p_Vid->last_has_mmco_5) - p_Vid->pre_frame_num = 0; -} -/********************************** - * - * Initialize reference lists - ********************************** - */ -#define __COMPARE(context, p1, p2) comp(p1, p2) -#define __SHORTSORT(lo, hi, width, comp, context) \ - shortsort(lo, hi, width, comp) -#define CUTOFF 8 /* testing shows that this is good value */ -#define STKSIZ (8*sizeof(void *) - 2) - -#undef swap -static void swap( - char *a, - char *b, - size_t width -) -{ - char tmp; - - if (a != b) - /* Do the swap one character at a time to avoid potential - * alignment problems. - */ - while (width--) { - tmp = *a; - *a++ = *b; - *b++ = tmp; - } -} - -static void shortsort( - char *lo, - char *hi, - size_t width, - int (*comp)(const void *, const void *) -) -{ - char *p, *max; - - /* Note: in assertions below, i and j are alway inside original - * bound of array to sort. - */ - - while (hi > lo) { - /* A[i] <= A[j] for i <= j, j > hi */ - max = lo; - for (p = lo + width; p <= hi; p += width) { - /* A[i] <= A[max] for lo <= i < p */ - if (__COMPARE(context, p, max) > 0) - max = p; - /* A[i] <= A[max] for lo <= i <= p */ - } - - /* A[i] <= A[max] for lo <= i <= hi */ - - swap(max, hi, width); - - /* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, - * j >= hi - */ - - hi -= width; - - /* A[i] <= A[j] for i <= j, j > hi, loop top condition - * established - */ - } - /* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] - * for i < j, so array is sorted - */ -} - -static void qsort( - void *base, - size_t num, - size_t width, - int (*comp)(const void *, const void *) -) -{ - char *lo, *hi; /* ends of sub-array currently sorting */ - char *mid; /* points to middle of subarray */ - char *loguy, *higuy; /* traveling pointers for partition step */ - size_t size; /* size of the sub-array */ - char *lostk[STKSIZ], *histk[STKSIZ]; - int stkptr; - -/* stack for saving sub-array to be - * processed - */ -#if 0 - /* validation section */ - _VALIDATE_RETURN_VOID(base != NULL || num == 0, EINVAL); - _VALIDATE_RETURN_VOID(width > 0, EINVAL); - _VALIDATE_RETURN_VOID(comp != NULL, EINVAL); -#endif - if (num < 2) - return; /* nothing to do */ - - stkptr = 0; /* initialize stack */ - - lo = (char *)base; - hi = (char *)base + width * (num - 1); /* initialize limits */ - - /* this entry point is for pseudo-recursion calling: setting - * lo and hi and jumping to here is like recursion, but stkptr is - * preserved, locals aren't, so we preserve stuff on the stack - */ -recurse: - - size = (hi - lo) / width + 1; /* number of el's to sort */ - - /* below a certain size, it is faster to use a O(n^2) sorting method */ - if (size <= CUTOFF) { - __SHORTSORT(lo, hi, width, comp, context); - } else { - /* First we pick a partitioning element. The efficiency of - * the algorithm demands that we find one that is approximately - * the median of the values, but also that we select one fast. - * We choose the median of the first, middle, and last - * elements, to avoid bad performance in the face of already - * sorted data, or data that is made up of multiple sorted - * runs appended together. Testing shows that a - * median-of-three algorithm provides better performance than - * simply picking the middle element for the latter case. - */ - - mid = lo + (size / 2) * width; /* find middle element */ - - /* Sort the first, middle, last elements into order */ - if (__COMPARE(context, lo, mid) > 0) - swap(lo, mid, width); - if (__COMPARE(context, lo, hi) > 0) - swap(lo, hi, width); - if (__COMPARE(context, mid, hi) > 0) - swap(mid, hi, width); - - /* We now wish to partition the array into three pieces, one - * consisting of elements <= partition element, one of elements - * equal to the partition element, and one of elements > than - * it. This is done below; comments indicate conditions - * established at every step. - */ - - loguy = lo; - higuy = hi; - - /* Note that higuy decreases and loguy increases on every - * iteration, so loop must terminate. - */ - for (;;) { - /* lo <= loguy < hi, lo < higuy <= hi, - * A[i] <= A[mid] for lo <= i <= loguy, - * A[i] > A[mid] for higuy <= i < hi, - * A[hi] >= A[mid] - */ - - /* The doubled loop is to avoid calling comp(mid,mid), - * since some existing comparison funcs don't work - * when passed the same value for both pointers. - */ - - if (mid > loguy) { - do { - loguy += width; - } while (loguy < mid && - __COMPARE(context, loguy, mid) <= 0); - } - if (mid <= loguy) { - do { - loguy += width; - } while (loguy <= hi && - __COMPARE(context, loguy, mid) <= 0); - } - - /* lo < loguy <= hi+1, A[i] <= A[mid] for - * lo <= i < loguy, - * either loguy > hi or A[loguy] > A[mid] - */ - - do { - higuy -= width; - } while (higuy > mid && - __COMPARE(context, higuy, mid) > 0); - - /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi, - * either higuy == lo or A[higuy] <= A[mid] - */ - - if (higuy < loguy) - break; - - /* if loguy > hi or higuy == lo, then we would have - * exited, so A[loguy] > A[mid], A[higuy] <= A[mid], - * loguy <= hi, higuy > lo - */ - - swap(loguy, higuy, width); - - /* If the partition element was moved, follow it. - * Only need to check for mid == higuy, since before - * the swap, A[loguy] > A[mid] implies loguy != mid. - */ - - if (mid == higuy) - mid = loguy; - - /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition - * at top of loop is re-established - */ - } - - /* A[i] <= A[mid] for lo <= i < loguy, - * A[i] > A[mid] for higuy < i < hi, - * A[hi] >= A[mid] - * higuy < loguy - * implying: - * higuy == loguy-1 - * or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] - */ - - /* Find adjacent elements equal to the partition element. The - * doubled loop is to avoid calling comp(mid,mid), since some - * existing comparison funcs don't work when passed the same - * value for both pointers. - */ - - higuy += width; - if (mid < higuy) { - do { - higuy -= width; - } while (higuy > mid && - __COMPARE(context, higuy, mid) == 0); - } - if (mid >= higuy) { - do { - higuy -= width; - } while (higuy > lo && - __COMPARE(context, higuy, mid) == 0); - } - - /* OK, now we have the following: - * higuy < loguy - * lo <= higuy <= hi - * A[i] <= A[mid] for lo <= i <= higuy - * A[i] == A[mid] for higuy < i < loguy - * A[i] > A[mid] for loguy <= i < hi - * A[hi] >= A[mid] - */ - - /* We've finished the partition, now we want to sort the - * subarrays [lo, higuy] and [loguy, hi]. - * We do the smaller one first to minimize stack usage. - * We only sort arrays of length 2 or more. - */ - - if (higuy - lo >= hi - loguy) { - if (lo < higuy) { - lostk[stkptr] = lo; - histk[stkptr] = higuy; - ++stkptr; - } /* save big recursion for later */ - - if (loguy < hi) { - lo = loguy; - goto recurse; /* do small recursion */ - } - } else { - if (loguy < hi) { - lostk[stkptr] = loguy; - histk[stkptr] = hi; - ++stkptr; /* save big recursion for later */ - } - - if (lo < higuy) { - hi = higuy; - goto recurse; /* do small recursion */ - } - } - } - - /* We have sorted the array, except for any pending sorts on the stack. - * Check if there are any, and do them. - */ - - --stkptr; - if (stkptr >= 0) { - lo = lostk[stkptr]; - hi = histk[stkptr]; - goto recurse; /* pop subarray from stack */ - } else - return; /* all subarrays done */ -} - -/*! - ************************************************************************ - * \brief - * compares two stored pictures by picture number for qsort in - * descending order - * - ************************************************************************ - */ -static inline int compare_pic_by_pic_num_desc(const void *arg1, - const void *arg2) -{ - int pic_num1 = (*(struct StorablePicture **)arg1)->pic_num; - int pic_num2 = (*(struct StorablePicture **)arg2)->pic_num; - - if (pic_num1 < pic_num2) - return 1; - if (pic_num1 > pic_num2) - return -1; - else - return 0; -} - -/*! - ************************************************************************ - * \brief - * compares two stored pictures by picture number for qsort in - * descending order - * - ************************************************************************ - */ -static inline int compare_pic_by_lt_pic_num_asc(const void *arg1, - const void *arg2) -{ - int long_term_pic_num1 = - (*(struct StorablePicture **)arg1)->long_term_pic_num; - int long_term_pic_num2 = - (*(struct StorablePicture **)arg2)->long_term_pic_num; - - if (long_term_pic_num1 < long_term_pic_num2) - return -1; - if (long_term_pic_num1 > long_term_pic_num2) - return 1; - else - return 0; -} - -/*! - ************************************************************************ - * \brief - * compares two frame stores by pic_num for qsort in descending order - * - ************************************************************************ - */ -static inline int compare_fs_by_frame_num_desc(const void *arg1, - const void *arg2) -{ - int frame_num_wrap1 = (*(struct FrameStore **)arg1)->frame_num_wrap; - int frame_num_wrap2 = (*(struct FrameStore **)arg2)->frame_num_wrap; - - if (frame_num_wrap1 < frame_num_wrap2) - return 1; - if (frame_num_wrap1 > frame_num_wrap2) - return -1; - else - return 0; -} - - -/*! - ************************************************************************ - * \brief - * compares two frame stores by lt_pic_num for qsort in descending order - * - ************************************************************************ - */ -static inline int compare_fs_by_lt_pic_idx_asc(const void *arg1, - const void *arg2) -{ - int long_term_frame_idx1 = - (*(struct FrameStore **)arg1)->long_term_frame_idx; - int long_term_frame_idx2 = - (*(struct FrameStore **)arg2)->long_term_frame_idx; - - if (long_term_frame_idx1 < long_term_frame_idx2) - return -1; - else if (long_term_frame_idx1 > long_term_frame_idx2) - return 1; - else - return 0; -} - - -/*! - ************************************************************************ - * \brief - * compares two stored pictures by poc for qsort in ascending order - * - ************************************************************************ - */ -static inline int compare_pic_by_poc_asc(const void *arg1, const void *arg2) -{ - int poc1 = (*(struct StorablePicture **)arg1)->poc; - int poc2 = (*(struct StorablePicture **)arg2)->poc; - - if (poc1 < poc2) - return -1; - else if (poc1 > poc2) - return 1; - else - return 0; -} - - -/*! - ************************************************************************ - * \brief - * compares two stored pictures by poc for qsort in descending order - * - ************************************************************************ - */ -static inline int compare_pic_by_poc_desc(const void *arg1, const void *arg2) -{ - int poc1 = (*(struct StorablePicture **)arg1)->poc; - int poc2 = (*(struct StorablePicture **)arg2)->poc; - - if (poc1 < poc2) - return 1; - else if (poc1 > poc2) - return -1; - else - return 0; -} - - -/*! - ************************************************************************ - * \brief - * compares two frame stores by poc for qsort in ascending order - * - ************************************************************************ - */ -static inline int compare_fs_by_poc_asc(const void *arg1, const void *arg2) -{ - int poc1 = (*(struct FrameStore **)arg1)->poc; - int poc2 = (*(struct FrameStore **)arg2)->poc; - - if (poc1 < poc2) - return -1; - else if (poc1 > poc2) - return 1; - else - return 0; -} - - -/*! - ************************************************************************ - * \brief - * compares two frame stores by poc for qsort in descending order - * - ************************************************************************ - */ -static inline int compare_fs_by_poc_desc(const void *arg1, const void *arg2) -{ - int poc1 = (*(struct FrameStore **)arg1)->poc; - int poc2 = (*(struct FrameStore **)arg2)->poc; - - if (poc1 < poc2) - return 1; - else if (poc1 > poc2) - return -1; - else - return 0; -} - -/*! - ************************************************************************ - * \brief - * returns true, if picture is short term reference picture - * - ************************************************************************ - */ -static inline int is_short_ref(struct StorablePicture *s) -{ -#ifdef ERROR_CHECK - return (s && - (s->used_for_reference) && (!(s->is_long_term))); -#else - return (s->used_for_reference) && (!(s->is_long_term)); -#endif -} - - -/*! - ************************************************************************ - * \brief - * returns true, if picture is long term reference picture - * - ************************************************************************ - */ -static inline int is_long_ref(struct StorablePicture *s) -{ -#ifdef ERROR_CHECK - return (s && - s->used_for_reference) && (s->is_long_term); -#else - return (s->used_for_reference) && (s->is_long_term); -#endif -} - -/*! - ************************************************************************ - * \brief - * Initialize reference lists for a P Slice - * - ************************************************************************ - */ -/*! - ************************************************************************ - * \brief - * Generates a alternating field list from a given FrameStore list - * - ************************************************************************ - */ -static void gen_pic_list_from_frame_list(enum PictureStructure currStructure, - struct FrameStore **fs_list, int list_idx, - struct StorablePicture **list, - char *list_size, int long_term) -{ - int top_idx = 0; - int bot_idx = 0; - - int (*is_ref)(struct StorablePicture *s) = (long_term) ? is_long_ref : - is_short_ref; - - - if (currStructure == TOP_FIELD) { - while ((top_idx < list_idx) || (bot_idx < list_idx)) { - for (; top_idx < list_idx; top_idx++) { - if (fs_list[top_idx]->is_used & 1) { - if (is_ref(fs_list[top_idx]-> - top_field)) { - /* short term ref pic */ - list[(short) *list_size] = - fs_list[top_idx]->top_field; - (*list_size)++; - top_idx++; - break; - } - } - } - for (; bot_idx < list_idx; bot_idx++) { - if (fs_list[bot_idx]->is_used & 2) { - if (is_ref(fs_list[bot_idx]-> - bottom_field)) { - /* short term ref pic */ - list[(short) *list_size] = - fs_list[bot_idx]->bottom_field; - (*list_size)++; - bot_idx++; - break; - } - } - } - } - } - if (currStructure == BOTTOM_FIELD) { - while ((top_idx < list_idx) || (bot_idx < list_idx)) { - for (; bot_idx < list_idx; bot_idx++) { - if (fs_list[bot_idx]->is_used & 2) { - if (is_ref(fs_list[bot_idx]-> - bottom_field)) { - /* short term ref pic */ - list[(short) *list_size] = - fs_list[bot_idx]->bottom_field; - (*list_size)++; - bot_idx++; - break; - } - } - } - for (; top_idx < list_idx; top_idx++) { - if (fs_list[top_idx]->is_used & 1) { - if (is_ref(fs_list[top_idx]-> - top_field)) { - /* short term ref pic */ - list[(short) *list_size] = - fs_list[top_idx]->top_field; - (*list_size)++; - top_idx++; - break; - } - } - } - } - } -} - -static void init_lists_p_slice(struct Slice *currSlice) -{ - struct VideoParameters *p_Vid = currSlice->p_Vid; - struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - - unsigned int i; - - int list0idx = 0; - int listltidx = 0; - - struct FrameStore **fs_list0; - struct FrameStore **fs_listlt; - -#if (MVC_EXTENSION_ENABLE) - currSlice->listinterviewidx0 = 0; - currSlice->listinterviewidx1 = 0; -#endif - - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL || - p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_used == 3) { - if ((p_Dpb->fs_ref[i]->frame-> - used_for_reference) && - (!p_Dpb->fs_ref[i]->frame-> - is_long_term)) { - currSlice->listX[0][list0idx++] = - p_Dpb->fs_ref[i]->frame; - } - } - } - /* order list 0 by PicNum */ - qsort((void *)currSlice->listX[0], list0idx, - sizeof(struct StorablePicture *), - compare_pic_by_pic_num_desc); - currSlice->listXsize[0] = (char) list0idx; - CHECK_VALID(currSlice->listXsize[0], 0); - if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "listX[0] (PicNum): "); - for (i = 0; i < list0idx; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - currSlice->listX[0][i]->pic_num); - } - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - } - /* long term handling */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->is_used == 3) { - if (p_Dpb->fs_ltref[i]->frame->is_long_term) { - currSlice->listX[0][list0idx++] = - p_Dpb->fs_ltref[i]->frame; - } - } - } - qsort((void *)&currSlice->listX[0][ - (short) currSlice->listXsize[0]], - list0idx - currSlice->listXsize[0], - sizeof(struct StorablePicture *), - compare_pic_by_lt_pic_num_asc); - currSlice->listXsize[0] = (char) list0idx; - CHECK_VALID(currSlice->listXsize[0], 0); - } else { -#if 0 - fs_list0 = calloc(p_Dpb->size, sizeof(struct FrameStore *)); - if (fs_list0 == NULL) - no_mem_exit("init_lists: fs_list0"); - fs_listlt = calloc(p_Dpb->size, sizeof(struct FrameStore *)); - if (fs_listlt == NULL) - no_mem_exit("init_lists: fs_listlt"); -#else - fs_list0 = &(p_Dpb->fs_list0[0]); - fs_listlt = &(p_Dpb->fs_listlt[0]); -#endif - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference) - fs_list0[list0idx++] = p_Dpb->fs_ref[i]; - } - - qsort((void *)fs_list0, list0idx, sizeof(struct FrameStore *), - compare_fs_by_frame_num_desc); - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "fs_list0 (FrameNum): "); - for (i = 0; i < list0idx; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - fs_list0[i]->frame_num_wrap); - } - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "\n"); - - currSlice->listXsize[0] = 0; - gen_pic_list_from_frame_list(currSlice->structure, fs_list0, - list0idx, currSlice->listX[0], - &currSlice->listXsize[0], 0); - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "listX[0] (PicNum): "); - for (i = 0; i < currSlice->listXsize[0]; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - currSlice->listX[0][i]->pic_num); - } - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "\n"); - - /* long term handling */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) - fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; - - qsort((void *)fs_listlt, listltidx, sizeof(struct FrameStore *), - compare_fs_by_lt_pic_idx_asc); - - gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, - listltidx, currSlice->listX[0], - &currSlice->listXsize[0], 1); - - /* free(fs_list0); */ - /* free(fs_listlt); */ - } - currSlice->listXsize[1] = 0; - - - /* set max size */ - currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0], - currSlice->num_ref_idx_active[LIST_0]); - currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1], - currSlice->num_ref_idx_active[LIST_1]); - CHECK_VALID(currSlice->listXsize[0], 0); - CHECK_VALID(currSlice->listXsize[1], 1); - - /* set the unused list entries to NULL */ - for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++) - currSlice->listX[0][i] = p_Vid->no_reference_picture; - for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++) - currSlice->listX[1][i] = p_Vid->no_reference_picture; - -#if PRINTREFLIST -#if (MVC_EXTENSION_ENABLE) - /* print out for h264_debug_flag purpose */ - if ((p_Vid->profile_idc == MVC_HIGH || - p_Vid->profile_idc == STEREO_HIGH) && - currSlice->current_slice_nr == 0) { - if (currSlice->listXsize[0] > 0) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n", - currSlice->view_id, - currSlice->ThisPOC, - currSlice->structure == FRAME ? "FRM" : - (currSlice->structure == TOP_FIELD ? - "TOP" : "BOT")); - for (i = 0; i < (unsigned int)(currSlice-> - listXsize[0]); i++) { /* ref list 0 */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", - i, - currSlice->listX[0][i]->poc, - currSlice->listX[0][i]->pic_num, - currSlice->listX[0][i]->view_id); - } - } - } -#endif -#endif -} - - -/*! - ************************************************************************ - * \brief - * Initialize reference lists - * - ************************************************************************ - */ -static void init_mbaff_lists(struct h264_dpb_stru *p_H264_Dpb, - struct Slice *currSlice) -{ - unsigned int j; - int i; - struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; - for (i = 2; i < 6; i++) { - for (j = 0; j < MAX_LIST_SIZE; j++) - currSlice->listX[i][j] = p_Vid->no_reference_picture; - currSlice->listXsize[i] = 0; - } - - for (i = 0; i < currSlice->listXsize[0]; i++) { -#ifdef ERROR_CHECK - if (currSlice->listX[0][i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - pr_info( - "error currSlice->listX[0][%d] is NULL\r\n", i); - break; - } -#endif - currSlice->listX[2][2 * i] = - currSlice->listX[0][i]->top_field; - currSlice->listX[2][2 * i + 1] = - currSlice->listX[0][i]->bottom_field; - currSlice->listX[4][2 * i] = - currSlice->listX[0][i]->bottom_field; - currSlice->listX[4][2 * i + 1] = - currSlice->listX[0][i]->top_field; - } - currSlice->listXsize[2] = currSlice->listXsize[4] = - currSlice->listXsize[0] * 2; - - for (i = 0; i < currSlice->listXsize[1]; i++) { -#ifdef ERROR_CHECK - if (currSlice->listX[1][i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - pr_info( - "error currSlice->listX[1][%d] is NULL\r\n", i); - break; - } -#endif - currSlice->listX[3][2 * i] = - currSlice->listX[1][i]->top_field; - currSlice->listX[3][2 * i + 1] = - currSlice->listX[1][i]->bottom_field; - currSlice->listX[5][2 * i] = - currSlice->listX[1][i]->bottom_field; - currSlice->listX[5][2 * i + 1] = - currSlice->listX[1][i]->top_field; - } - currSlice->listXsize[3] = currSlice->listXsize[5] = - currSlice->listXsize[1] * 2; -} - - - -static void init_lists_i_slice(struct Slice *currSlice) -{ - -#if (MVC_EXTENSION_ENABLE) - currSlice->listinterviewidx0 = 0; - currSlice->listinterviewidx1 = 0; -#endif - - currSlice->listXsize[0] = 0; - currSlice->listXsize[1] = 0; -} - -static void init_lists_b_slice(struct Slice *currSlice) -{ - struct VideoParameters *p_Vid = currSlice->p_Vid; - struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - - unsigned int i; - int j; - - int list0idx = 0; - int list0idx_1 = 0; - int listltidx = 0; - - struct FrameStore **fs_list0; - struct FrameStore **fs_list1; - struct FrameStore **fs_listlt; - -#if (MVC_EXTENSION_ENABLE) - currSlice->listinterviewidx0 = 0; - currSlice->listinterviewidx1 = 0; -#endif - - { - /* B-Slice */ - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL || - p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((p_Dpb->fs_ref[i]->is_used == 3) && - ((p_Dpb->fs_ref[i]->frame-> - used_for_reference) && - (!p_Dpb->fs_ref[i]->frame-> - is_long_term)) && - (currSlice->framepoc >= - p_Dpb->fs_ref[i]->frame->poc)) { - /* !KS use >= for error - * concealment - */ - currSlice->listX[0][list0idx++] = - p_Dpb->fs_ref[i]->frame; - } - } - qsort((void *)currSlice->listX[0], list0idx, - sizeof(struct StorablePicture *), - compare_pic_by_poc_desc); - - /* get the backward reference picture - * (POC>current POC) in list0; - */ - list0idx_1 = list0idx; - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL || - p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((p_Dpb->fs_ref[i]->is_used == 3) && - ((p_Dpb->fs_ref[i]->frame-> - used_for_reference) && - (!p_Dpb->fs_ref[i]->frame-> - is_long_term)) && - (currSlice->framepoc < - p_Dpb->fs_ref[i]->frame->poc)) { - currSlice-> - listX[0][list0idx++] = - p_Dpb->fs_ref[i]->frame; - } - } - qsort((void *)&currSlice->listX[0][list0idx_1], - list0idx - list0idx_1, - sizeof(struct StorablePicture *), - compare_pic_by_poc_asc); - - for (j = 0; j < list0idx_1; j++) { - currSlice-> - listX[1][list0idx - list0idx_1 + j] = - currSlice->listX[0][j]; - } - for (j = list0idx_1; j < list0idx; j++) { - currSlice->listX[1][j - list0idx_1] = - currSlice->listX[0][j]; - } - - currSlice->listXsize[0] = currSlice->listXsize[1] = - (char) list0idx; - CHECK_VALID(currSlice->listXsize[0], 0); - CHECK_VALID(currSlice->listXsize[1], 1); - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "listX[0] (PicNum): "); - for (i = 0; i < currSlice->listXsize[0]; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - currSlice->listX[0][i]->pic_num); - } - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "listX[1] (PicNum): "); - for (i = 0; i < currSlice->listXsize[1]; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - currSlice->listX[1][i]->pic_num); - } - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - /* dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "currSlice->listX[0] currPoc=%d (Poc): ", - * p_Vid->framepoc); - * for (i=0; ilistXsize[0]; i++) { - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "%d ", currSlice->listX[0][i]->poc); - * } - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, "\n"); - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "currSlice->listX[1] currPoc=%d (Poc): ", - * p_Vid->framepoc); - * for (i=0; ilistXsize[1]; i++) { - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "%d ", - * currSlice->listX[1][i]->poc); - * } - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, "\n"); - */ - - /* long term handling */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->is_used == 3) { - if (p_Dpb->fs_ltref[i]->frame-> - is_long_term) { - currSlice-> - listX[0][list0idx] = - p_Dpb->fs_ltref[i]->frame; - currSlice-> - listX[1][list0idx++] = - p_Dpb->fs_ltref[i]->frame; - } - } - } - qsort((void *)&currSlice-> - listX[0][(short) currSlice->listXsize[0]], - list0idx - currSlice->listXsize[0], - sizeof(struct StorablePicture *), - compare_pic_by_lt_pic_num_asc); - qsort((void *)&currSlice-> - listX[1][(short) currSlice->listXsize[0]], - list0idx - currSlice->listXsize[0], - sizeof(struct StorablePicture *), - compare_pic_by_lt_pic_num_asc); - currSlice->listXsize[0] = currSlice->listXsize[1] = - (char) list0idx; - CHECK_VALID(currSlice->listXsize[0], 0); - CHECK_VALID(currSlice->listXsize[1], 1); - } else { -#if 0 - fs_list0 = calloc(p_Dpb->size, - sizeof(struct FrameStore *)); - if (fs_list0 == NULL) - no_mem_exit("init_lists: fs_list0"); - fs_list1 = calloc(p_Dpb->size, - sizeof(struct FrameStore *)); - if (fs_list1 == NULL) - no_mem_exit("init_lists: fs_list1"); - fs_listlt = calloc(p_Dpb->size, - sizeof(struct FrameStore *)); - if (fs_listlt == NULL) - no_mem_exit("init_lists: fs_listlt"); -#else - fs_list0 = &(p_Dpb->fs_list0[0]); - fs_list1 = &(p_Dpb->fs_list1[0]); - fs_listlt = &(p_Dpb->fs_listlt[0]); - -#endif - currSlice->listXsize[0] = 0; - currSlice->listXsize[1] = 1; - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_used) { - if (currSlice->ThisPOC >= - p_Dpb->fs_ref[i]->poc) { - fs_list0[list0idx++] = - p_Dpb->fs_ref[i]; - } - } - } - qsort((void *)fs_list0, list0idx, - sizeof(struct FrameStore *), - compare_fs_by_poc_desc); - list0idx_1 = list0idx; - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_used) { - if (currSlice->ThisPOC < - p_Dpb->fs_ref[i]->poc) { - fs_list0[list0idx++] = - p_Dpb->fs_ref[i]; - } - } - } - qsort((void *)&fs_list0[list0idx_1], - list0idx - list0idx_1, - sizeof(struct FrameStore *), - compare_fs_by_poc_asc); - - for (j = 0; j < list0idx_1; j++) { - fs_list1[list0idx - list0idx_1 + j] = - fs_list0[j]; - } - for (j = list0idx_1; j < list0idx; j++) - fs_list1[j - list0idx_1] = fs_list0[j]; - - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "fs_list0 currPoc=%d (Poc): ", - currSlice->ThisPOC); - for (i = 0; i < list0idx; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - fs_list0[i]->poc); - } - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "fs_list1 currPoc=%d (Poc): ", - currSlice->ThisPOC); - for (i = 0; i < list0idx; i++) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - fs_list1[i]->poc); - } - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - - currSlice->listXsize[0] = 0; - currSlice->listXsize[1] = 0; - gen_pic_list_from_frame_list(currSlice->structure, - fs_list0, list0idx, - currSlice->listX[0], - &currSlice->listXsize[0], 0); - gen_pic_list_from_frame_list(currSlice->structure, - fs_list1, list0idx, - currSlice->listX[1], - &currSlice->listXsize[1], 0); - - /* dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "currSlice->listX[0] currPoc=%d (Poc): ", - * p_Vid->framepoc); - * for (i=0; ilistXsize[0]; i++) { - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, "%d ", - * currSlice->listX[0][i]->poc); - * } - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, "\n"); - */ - /* dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "currSlice->listX[1] currPoc=%d (Poc): ", - * p_Vid->framepoc); - * for (i=0; ilistXsize[1]; i++) { - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, "%d ", - * currSlice->listX[1][i]->poc); - * } - * dpb_print(p_H264_Dpb->decoder_index, - * PRINT_FLAG_DPB_DETAIL, - * "\n"); - */ - - /* long term handling */ - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) - fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; - - qsort((void *)fs_listlt, listltidx, - sizeof(struct FrameStore *), - compare_fs_by_lt_pic_idx_asc); - - gen_pic_list_from_frame_list(currSlice->structure, - fs_listlt, listltidx, - currSlice->listX[0], - &currSlice->listXsize[0], 1); - gen_pic_list_from_frame_list(currSlice->structure, - fs_listlt, listltidx, - currSlice->listX[1], - &currSlice->listXsize[1], 1); - - /* free(fs_list0); */ - /* free(fs_list1); */ - /* free(fs_listlt); */ - } - } - - if ((currSlice->listXsize[0] == currSlice->listXsize[1]) && - (currSlice->listXsize[0] > 1)) { - /* check if lists are identical, - *if yes swap first two elements of currSlice->listX[1] - */ - int diff = 0; - - for (j = 0; j < currSlice->listXsize[0]; j++) { - if (currSlice->listX[0][j] != - currSlice->listX[1][j]) { - diff = 1; - break; - } - } - if (!diff) { - struct StorablePicture *tmp_s = - currSlice->listX[1][0]; - currSlice->listX[1][0] = currSlice->listX[1][1]; - currSlice->listX[1][1] = tmp_s; - } - } - - /* set max size */ - currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0], - currSlice->num_ref_idx_active[LIST_0]); - currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1], - currSlice->num_ref_idx_active[LIST_1]); - CHECK_VALID(currSlice->listXsize[0], 0); - CHECK_VALID(currSlice->listXsize[1], 1); - - /* set the unused list entries to NULL */ - for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++) - currSlice->listX[0][i] = p_Vid->no_reference_picture; - for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++) - currSlice->listX[1][i] = p_Vid->no_reference_picture; - -#if PRINTREFLIST -#if (MVC_EXTENSION_ENABLE) - /* print out for h264_debug_flag purpose */ - if ((p_Vid->profile_idc == MVC_HIGH || - p_Vid->profile_idc == STEREO_HIGH) && - currSlice->current_slice_nr == 0) { - if ((currSlice->listXsize[0] > 0) || - (currSlice->listXsize[1] > 0)) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - if (currSlice->listXsize[0] > 0) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n", - currSlice->view_id, - currSlice->ThisPOC, - currSlice->structure == FRAME ? "FRM" : - (currSlice->structure == TOP_FIELD ? - "TOP" : "BOT")); - for (i = 0; i < (unsigned int)(currSlice-> - listXsize[0]); i++) { /* ref list 0 */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", - i, - currSlice->listX[0][i]->poc, - currSlice->listX[0][i]->pic_num, - currSlice->listX[0][i]->view_id); - } - } - if (currSlice->listXsize[1] > 0) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " ** (CurViewID:%d %d) %s Ref Pic List 1 ****\n", - currSlice->view_id, - currSlice->ThisPOC, - currSlice->structure == FRAME ? "FRM" : - (currSlice->structure == TOP_FIELD ? "TOP" : - "BOT")); - for (i = 0; i < (unsigned int)(currSlice-> - listXsize[1]); i++) { /* ref list 1 */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", - i, - currSlice->listX[1][i]->poc, - currSlice->listX[1][i]->pic_num, - currSlice->listX[1][i]->view_id); - } - } - } -#endif -#endif -} - -static struct StorablePicture *get_short_term_pic(struct Slice *currSlice, - struct DecodedPictureBuffer *p_Dpb, int picNum) -{ - unsigned int i; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, - struct h264_dpb_stru, mDPB); - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (currSlice->structure == FRAME) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference == 3) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->frame == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((!p_Dpb->fs_ref[i]->frame-> - is_long_term) && - (p_Dpb->fs_ref[i]->frame-> - pic_num == picNum)) - return p_Dpb->fs_ref[i]->frame; - } - } else { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i] == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if (p_Dpb->fs_ref[i]->is_reference & 1) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->top_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((!p_Dpb->fs_ref[i]->top_field-> - is_long_term) && - (p_Dpb->fs_ref[i]->top_field-> - pic_num == picNum)) - return p_Dpb->fs_ref[i]->top_field; - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { -#ifdef ERROR_CHECK - if (p_Dpb->fs_ref[i]->bottom_field == NULL) { - p_H264_Dpb->dpb_error_flag = __LINE__; - continue; - } -#endif - if ((!p_Dpb->fs_ref[i]->bottom_field-> - is_long_term) && - (p_Dpb->fs_ref[i]->bottom_field-> - pic_num == picNum)) - return p_Dpb->fs_ref[i]->bottom_field; - } - } - } - - return currSlice->p_Vid->no_reference_picture; -} - - -static void reorder_short_term(struct Slice *currSlice, int cur_list, - int num_ref_idx_lX_active_minus1, - int picNumLX, int *refIdxLX) -{ - struct h264_dpb_stru *p_H264_Dpb = container_of(currSlice->p_Vid, - struct h264_dpb_stru, mVideo); - - struct StorablePicture **RefPicListX = currSlice->listX[cur_list]; - int cIdx, nIdx; - - struct StorablePicture *picLX; - - picLX = get_short_term_pic(currSlice, currSlice->p_Dpb, picNumLX); - - for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; - cIdx--) { - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n", - __func__, cIdx, cIdx - 1); - RefPicListX[cIdx] = RefPicListX[cIdx - 1]; - } - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s: RefPicListX[ %d ] = pic %x (%d)\n", __func__, - *refIdxLX, picLX, picNumLX); - - RefPicListX[(*refIdxLX)++] = picLX; - - nIdx = *refIdxLX; - - for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; - cIdx++) { - if (RefPicListX[cIdx]) - if ((RefPicListX[cIdx]->is_long_term) || - (RefPicListX[cIdx]->pic_num != picNumLX)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n", - __func__, nIdx, cIdx); - RefPicListX[nIdx++] = RefPicListX[cIdx]; - } - } -} - - -static struct StorablePicture *get_long_term_pic(struct Slice *currSlice, - struct DecodedPictureBuffer *p_Dpb, int LongtermPicNum) -{ - unsigned int i; - - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (currSlice->structure == FRAME) { - if (p_Dpb->fs_ltref[i]->is_reference == 3) - if ((p_Dpb->fs_ltref[i]->frame) && - (p_Dpb->fs_ltref[i]->frame-> - is_long_term) && - (p_Dpb->fs_ltref[i]->frame-> - long_term_pic_num == - LongtermPicNum)) - return p_Dpb->fs_ltref[i]->frame; - } else { - if (p_Dpb->fs_ltref[i]->is_reference & 1) - if ((p_Dpb->fs_ltref[i]->top_field) && - (p_Dpb->fs_ltref[i]->top_field-> - is_long_term) && - (p_Dpb->fs_ltref[i]->top_field-> - long_term_pic_num == LongtermPicNum)) - return p_Dpb->fs_ltref[i]->top_field; - - if (p_Dpb->fs_ltref[i]->is_reference & 2) - if ((p_Dpb->fs_ltref[i]->bottom_field) && - (p_Dpb->fs_ltref[i]->bottom_field-> - is_long_term) && - (p_Dpb->fs_ltref[i]->bottom_field-> - long_term_pic_num == - LongtermPicNum)) - return p_Dpb->fs_ltref[i]-> - bottom_field; - } - } - return NULL; -} - -/*! - ************************************************************************ - * \brief - * Reordering process for long-term reference pictures - * - ************************************************************************ - */ -static void reorder_long_term(struct Slice *currSlice, - struct StorablePicture **RefPicListX, - int num_ref_idx_lX_active_minus1, - int LongTermPicNum, int *refIdxLX) -{ - int cIdx, nIdx; - - struct StorablePicture *picLX; - - picLX = get_long_term_pic(currSlice, currSlice->p_Dpb, LongTermPicNum); - - for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--) - RefPicListX[cIdx] = RefPicListX[cIdx - 1]; - - RefPicListX[(*refIdxLX)++] = picLX; - - nIdx = *refIdxLX; - - for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; - cIdx++) { - if (RefPicListX[cIdx]) { - if ((!RefPicListX[cIdx]->is_long_term) || - (RefPicListX[cIdx]->long_term_pic_num != - LongTermPicNum)) - RefPicListX[nIdx++] = RefPicListX[cIdx]; - } - } -} - -static void reorder_ref_pic_list(struct Slice *currSlice, int cur_list) -{ - int *modification_of_pic_nums_idc = - currSlice->modification_of_pic_nums_idc[cur_list]; - int *abs_diff_pic_num_minus1 = - currSlice->abs_diff_pic_num_minus1[cur_list]; - int *long_term_pic_idx = currSlice->long_term_pic_idx[cur_list]; - int num_ref_idx_lX_active_minus1 = - currSlice->num_ref_idx_active[cur_list] - 1; - - struct VideoParameters *p_Vid = currSlice->p_Vid; - int i; - - int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX; - int refIdxLX = 0; - - if (currSlice->structure == FRAME) { - maxPicNum = p_Vid->max_frame_num; - currPicNum = currSlice->frame_num; - } else { - maxPicNum = 2 * p_Vid->max_frame_num; - currPicNum = 2 * currSlice->frame_num + 1; - } - - picNumLXPred = currPicNum; - - for (i = 0; i < REORDERING_COMMAND_MAX_SIZE && - modification_of_pic_nums_idc[i] != 3; i++) { - if (modification_of_pic_nums_idc[i] > 3) { - struct h264_dpb_stru *p_H264_Dpb = - container_of(p_Vid, struct h264_dpb_stru, mVideo); - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "error, Invalid modification_of_pic_nums_idc command\n"); - /*h264_debug_flag = 0x1f;*/ - break; - } - if (modification_of_pic_nums_idc[i] < 2) { - if (modification_of_pic_nums_idc[i] == 0) { - if (picNumLXPred - (abs_diff_pic_num_minus1[i] - + 1) < 0) - picNumLXNoWrap = picNumLXPred - - (abs_diff_pic_num_minus1[i] + 1) + - maxPicNum; - else - picNumLXNoWrap = picNumLXPred - - (abs_diff_pic_num_minus1[i] + 1); - } else { /* (modification_of_pic_nums_idc[i] == 1) */ - if (picNumLXPred + (abs_diff_pic_num_minus1[i] - + 1) >= maxPicNum) - picNumLXNoWrap = picNumLXPred + - (abs_diff_pic_num_minus1[i] + 1) - - maxPicNum; - else - picNumLXNoWrap = picNumLXPred + - (abs_diff_pic_num_minus1[i] + 1); - } - picNumLXPred = picNumLXNoWrap; - - if (picNumLXNoWrap > currPicNum) - picNumLX = picNumLXNoWrap - maxPicNum; - else - picNumLX = picNumLXNoWrap; - -#if (MVC_EXTENSION_ENABLE) - reorder_short_term(currSlice, cur_list, - num_ref_idx_lX_active_minus1, picNumLX, - &refIdxLX, -1); -#else - reorder_short_term(currSlice, cur_list, - num_ref_idx_lX_active_minus1, picNumLX, - &refIdxLX); -#endif - } else { /* (modification_of_pic_nums_idc[i] == 2) */ -#if (MVC_EXTENSION_ENABLE) - reorder_long_term(currSlice, currSlice->listX[cur_list], - num_ref_idx_lX_active_minus1, - long_term_pic_idx[i], &refIdxLX, -1); -#else - reorder_long_term(currSlice, currSlice->listX[cur_list], - num_ref_idx_lX_active_minus1, - long_term_pic_idx[i], &refIdxLX); -#endif - } - - } - /* that's a definition */ - currSlice->listXsize[cur_list] = - (char)(num_ref_idx_lX_active_minus1 + 1); -} - -static void reorder_lists(struct Slice *currSlice) -{ - struct VideoParameters *p_Vid = currSlice->p_Vid; - struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid, - struct h264_dpb_stru, mVideo); - int i; - - if ((currSlice->slice_type != I_SLICE) && - (currSlice->slice_type != SI_SLICE)) { - if (currSlice->ref_pic_list_reordering_flag[LIST_0]) - reorder_ref_pic_list(currSlice, LIST_0); - if (p_Vid->no_reference_picture == - currSlice-> - listX[0][currSlice->num_ref_idx_active[LIST_0] - 1]) { - if (p_Vid->non_conforming_stream) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "RefPicList0[ %d ] is equal to 'no reference picture'\n", - currSlice-> - num_ref_idx_active[LIST_0] - 1); - else - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "RefPicList0 [ num_ref_idx_l0_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n", - 500); - } - /* that's a definition */ - currSlice->listXsize[0] = - (char)currSlice->num_ref_idx_active[LIST_0]; - CHECK_VALID(currSlice->listXsize[0], 0); - if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "listX[0] reorder (PicNum): "); - for (i = 0; i < currSlice->listXsize[0]; i++) { - dpb_print_cont(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - currSlice->listX[0][i]->pic_num); - } - dpb_print_cont(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - } - } - - if (currSlice->slice_type == B_SLICE) { - if (currSlice->ref_pic_list_reordering_flag[LIST_1]) - reorder_ref_pic_list(currSlice, LIST_1); - if (p_Vid->no_reference_picture == - currSlice->listX[1][currSlice-> - num_ref_idx_active[LIST_1] - 1]) { - if (p_Vid->non_conforming_stream) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "RefPicList1[ %d ] is equal to 'no reference picture'\n", - currSlice-> - num_ref_idx_active[LIST_1] - 1); - else - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "RefPicList1 [ num_ref_idx_l1_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n", - 500); - } - /* that's a definition */ - currSlice->listXsize[1] = - (char)currSlice->num_ref_idx_active[LIST_1]; - if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "listX[1] reorder (PicNum): "); - for (i = 0; i < currSlice->listXsize[1]; i++) { - dpb_print_cont(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "%d ", - currSlice->listX[1][i]->pic_num); - } - dpb_print_cont(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - } - } - - /* free_ref_pic_list_reordering_buffer(currSlice); */ - - if (currSlice->slice_type == P_SLICE) { -#if PRINTREFLIST - unsigned int i; -#if (MVC_EXTENSION_ENABLE) - /* print out for h264_debug_flag purpose */ - if ((p_Vid->profile_idc == MVC_HIGH || - p_Vid->profile_idc == STEREO_HIGH) && - currSlice->current_slice_nr == 0) { - if (currSlice->listXsize[0] > 0 - && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " ** (FinalViewID:%d) %s Ref Pic List 0 ****\n", - currSlice->view_id, - currSlice->structure == FRAME ? - "FRM" : - (currSlice->structure == TOP_FIELD ? - "TOP" : "BOT")); - for (i = 0; i < (unsigned int)(currSlice-> - listXsize[0]); i++) { /* ref list 0 */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", - i, - currSlice->listX[0][i]->poc, - currSlice->listX[0][i]-> - pic_num, - currSlice->listX[0][i]-> - view_id); - } - } - } -#endif -#endif - } else if (currSlice->slice_type == B_SLICE) { -#if PRINTREFLIST - unsigned int i; -#if (MVC_EXTENSION_ENABLE) - /* print out for h264_debug_flag purpose */ - if ((p_Vid->profile_idc == MVC_HIGH || - p_Vid->profile_idc == STEREO_HIGH) && - currSlice->current_slice_nr == 0) { - if ((currSlice->listXsize[0] > 0) || - (currSlice->listXsize[1] > 0)) - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, "\n"); - if (currSlice->listXsize[0] > 0 - && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " ** (FinalViewID:%d) %s Ref Pic List 0 ****\n", - currSlice->view_id, - currSlice->structure == FRAME ? - "FRM" : - (currSlice->structure == TOP_FIELD ? - "TOP" : "BOT")); - for (i = 0; i < (unsigned int)(currSlice-> - listXsize[0]); i++) { /* ref list 0 */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", - i, - currSlice->listX[0][i]->poc, - currSlice->listX[0][i]-> - pic_num, - currSlice->listX[0][i]-> - view_id); - } - } - if (currSlice->listXsize[1] > 0 - && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " ** (FinalViewID:%d) %s Ref Pic List 1 ****\n", - currSlice->view_id, - currSlice->structure == FRAME ? - "FRM" : - (currSlice->structure == TOP_FIELD ? - "TOP" : "BOT")); - for (i = 0; i < (unsigned int)(currSlice-> - listXsize[1]); i++) { /* ref list 1 */ - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", - i, - currSlice->listX[1][i]->poc, - currSlice->listX[1][i]-> - pic_num, - currSlice->listX[1][i]-> - view_id); - } - } - } -#endif - -#endif - } -} - -void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count) -{ - p_H264_Dpb->colocated_buf_map = 0; - p_H264_Dpb->colocated_buf_count = count; -} - -int allocate_colocate_buf(struct h264_dpb_stru *p_H264_Dpb) -{ - int i; - - for (i = 0; i < p_H264_Dpb->colocated_buf_count; i++) { - if (((p_H264_Dpb->colocated_buf_map >> i) & 0x1) == 0) { - p_H264_Dpb->colocated_buf_map |= (1 << i); - break; - } - } - if (i == p_H264_Dpb->colocated_buf_count) { - i = -1; - p_H264_Dpb->buf_alloc_fail = 1; - } - return i; -} - -int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index) -{ - if (index >= 0) { - if (index >= p_H264_Dpb->colocated_buf_count) { - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR, - "%s error, index %d is bigger than buf count %d\n", - __func__, index, - p_H264_Dpb->colocated_buf_count); - } else { - if (((p_H264_Dpb->colocated_buf_map >> - index) & 0x1) == 0x1) { - p_H264_Dpb->colocated_buf_map &= - (~(1 << index)); - } else { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, - "%s error, index %d is not allocated\n", - __func__, index); - } - } - } - return 0; -} - -void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - - p_H264_Dpb->mFrameStore[index].is_output = 1; - p_H264_Dpb->mFrameStore[index].pre_output = 0; - dump_dpb(p_Dpb, 0); -} - -#if 0 -void init_old_slice(OldSliceParams *p_old_slice) -{ - p_old_slice->field_pic_flag = 0; - p_old_slice->pps_id = INT_MAX; - p_old_slice->frame_num = INT_MAX; - p_old_slice->nal_ref_idc = INT_MAX; - p_old_slice->idr_flag = FALSE; - - p_old_slice->pic_oder_cnt_lsb = UINT_MAX; - p_old_slice->delta_pic_oder_cnt_bottom = INT_MAX; - - p_old_slice->delta_pic_order_cnt[0] = INT_MAX; - p_old_slice->delta_pic_order_cnt[1] = INT_MAX; -} - - -void copy_slice_info(struct Slice *currSlice, OldSliceParams *p_old_slice) -{ - struct VideoParameters *p_Vid = currSlice->p_Vid; - - p_old_slice->pps_id = currSlice->pic_parameter_set_id; - p_old_slice->frame_num = currSlice->frame_num; - /* p_Vid->frame_num; */ - p_old_slice->field_pic_flag = - currSlice->field_pic_flag; - /* p_Vid->field_pic_flag; */ - - if (currSlice->field_pic_flag) - p_old_slice->bottom_field_flag = currSlice->bottom_field_flag; - - p_old_slice->nal_ref_idc = currSlice->nal_reference_idc; - p_old_slice->idr_flag = (byte) currSlice->idr_flag; - - if (currSlice->idr_flag) - p_old_slice->idr_pic_id = currSlice->idr_pic_id; - - if (p_Vid->active_sps->pic_order_cnt_type == 0) { - p_old_slice->pic_oder_cnt_lsb = - currSlice->pic_order_cnt_lsb; - p_old_slice->delta_pic_oder_cnt_bottom = - currSlice->delta_pic_order_cnt_bottom; - } - - if (p_Vid->active_sps->pic_order_cnt_type == 1) { - p_old_slice->delta_pic_order_cnt[0] = - currSlice->delta_pic_order_cnt[0]; - p_old_slice->delta_pic_order_cnt[1] = - currSlice->delta_pic_order_cnt[1]; - } -#if (MVC_EXTENSION_ENABLE) - p_old_slice->view_id = currSlice->view_id; - p_old_slice->inter_view_flag = currSlice->inter_view_flag; - p_old_slice->anchor_pic_flag = currSlice->anchor_pic_flag; -#endif - p_old_slice->layer_id = currSlice->layer_id; -} - -int is_new_picture(StorablePicture *dec_picture, struct Slice *currSlice, - OldSliceParams *p_old_slice) -{ - struct VideoParameters *p_Vid = currSlice->p_Vid; - - int result = 0; - - result |= (dec_picture == NULL); - - result |= (p_old_slice->pps_id != currSlice->pic_parameter_set_id); - - result |= (p_old_slice->frame_num != currSlice->frame_num); - - result |= (p_old_slice->field_pic_flag != currSlice->field_pic_flag); - - if (currSlice->field_pic_flag && p_old_slice->field_pic_flag) { - result |= (p_old_slice->bottom_field_flag != - currSlice->bottom_field_flag); - } - - result |= (p_old_slice->nal_ref_idc != - currSlice->nal_reference_idc) && - ((p_old_slice->nal_ref_idc == 0) || - (currSlice->nal_reference_idc == 0)); - result |= (p_old_slice->idr_flag != currSlice->idr_flag); - - if (currSlice->idr_flag && p_old_slice->idr_flag) - result |= (p_old_slice->idr_pic_id != currSlice->idr_pic_id); - - if (p_Vid->active_sps->pic_order_cnt_type == 0) { - result |= (p_old_slice->pic_oder_cnt_lsb != - currSlice->pic_order_cnt_lsb); - if (p_Vid->active_pps-> - bottom_field_pic_order_in_frame_present_flag == 1 && - !currSlice->field_pic_flag) { - result |= (p_old_slice->delta_pic_oder_cnt_bottom != - currSlice->delta_pic_order_cnt_bottom); - } - } - - if (p_Vid->active_sps->pic_order_cnt_type == 1) { - if (!p_Vid->active_sps->delta_pic_order_always_zero_flag) { - result |= (p_old_slice->delta_pic_order_cnt[0] != - currSlice->delta_pic_order_cnt[0]); - if (p_Vid->active_pps-> - bottom_field_pic_order_in_frame_present_flag == 1 && - !currSlice->field_pic_flag) { - result |= (p_old_slice-> - delta_pic_order_cnt[1] != - currSlice->delta_pic_order_cnt[1]); - } - } - } - -#if (MVC_EXTENSION_ENABLE) - result |= (currSlice->view_id != p_old_slice->view_id); - result |= (currSlice->inter_view_flag != p_old_slice->inter_view_flag); - result |= (currSlice->anchor_pic_flag != p_old_slice->anchor_pic_flag); -#endif - result |= (currSlice->layer_id != p_old_slice->layer_id); - return result; -} -#else -int is_new_picture(struct StorablePicture *dec_picture, - struct h264_dpb_stru *p_H264_Dpb, - struct OldSliceParams *p_old_slice) -{ - int ret = 0; - - if (p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] == 0) - ret = 1; - return ret; -} - -#endif - -/* -* release bufspec and pic for picture not in dpb buf -*/ -int release_picture(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *pic) -{ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - - if (p_Dpb->last_picture == NULL) { - if (pic->colocated_buf_index >= 0) { - release_colocate_buf(p_H264_Dpb, - pic->colocated_buf_index); - pic->colocated_buf_index = -1; - } - release_buf_spec_num(p_H264_Dpb->vdec, pic->buf_spec_num); - } else { - if (pic->buf_spec_is_alloced == 1) - release_buf_spec_num(p_H264_Dpb->vdec, - pic->buf_spec_num); - } - - free_picture(p_H264_Dpb, pic); - return 0; -} - -#ifdef ERROR_HANDLE_TEST -/* -* remove all pictures in dpb and release bufspec/pic of them -*/ -void remove_dpb_pictures(struct h264_dpb_stru *p_H264_Dpb) -{ - /* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */ - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - struct Slice *currSlice = &p_H264_Dpb->mSlice; - unsigned i, j; - - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "%s\n", __func__); - - if (!p_Dpb->init_done) - return; - - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->colocated_buf_index >= 0) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "release_colocate_buf[%d] for fs[%d]\n", - p_Dpb->fs[i]->colocated_buf_index, i); - - release_colocate_buf(p_H264_Dpb, - p_Dpb->fs[i]->colocated_buf_index); /* rain */ - p_Dpb->fs[i]->colocated_buf_index = -1; - } - if (!p_Dpb->fs[i]->pre_output) { - release_buf_spec_num(p_H264_Dpb->vdec, - p_Dpb->fs[i]->buf_spec_num); - p_Dpb->fs[i]->buf_spec_num = -1; - } - remove_frame_from_dpb(p_H264_Dpb, i); - } - - for (i = 0; i < p_Dpb->used_size; i++) { - p_Dpb->fs_ref[i] = NULL; - p_Dpb->fs_ltref[i] = NULL; - p_Dpb->fs_list0[i] = NULL; - p_Dpb->fs_list1[i] = NULL; - p_Dpb->fs_listlt[i] = NULL; - } - for (i = 0; i < 2; i++) { - currSlice->listXsize[i] = 0; - for (j = 0; j < (MAX_LIST_SIZE * 2); j++) - currSlice->listX[i][j] = NULL; - } - p_Dpb->ref_frames_in_buffer = 0; - p_Dpb->ltref_frames_in_buffer = 0; - p_Dpb->last_output_poc = INT_MIN; -} -#endif - -static void check_frame_store_same_pic_num(struct DecodedPictureBuffer *p_Dpb, - struct StorablePicture *p, struct Slice *currSlice) -{ - if (p_Dpb->last_picture) { - if ((int)p_Dpb->last_picture->frame_num == p->pic_num) { - if (((p->structure == TOP_FIELD) && - (p_Dpb->last_picture->is_used == 2)) || - ((p->structure == BOTTOM_FIELD) && - (p_Dpb->last_picture->is_used == 1))) { - if ((p->used_for_reference && - (p_Dpb->last_picture-> - is_orig_reference != 0)) || - (!p->used_for_reference && - (p_Dpb->last_picture-> - is_orig_reference == 0))) { - p->buf_spec_num = - p_Dpb->last_picture-> - buf_spec_num; - p->buf_spec_is_alloced = 0; - p->colocated_buf_index = p_Dpb-> - last_picture-> - colocated_buf_index; - if (currSlice->structure == - TOP_FIELD) { - p->bottom_poc = - p_Dpb->last_picture-> - bottom_field->poc; - } else { - p->top_poc = - p_Dpb->last_picture-> - top_field->poc; - } - p->frame_poc = imin(p->bottom_poc, - p->top_poc); - } - } - } - } -} - -int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb) -{ - - int new_pic_flag = 0; - struct Slice *currSlice = &p_H264_Dpb->mSlice; - struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; - struct DecodedPictureBuffer *p_Dpb = - &p_H264_Dpb->mDPB; -#if 0 - new_pic_flag = is_new_picture(p_H264_Dpb->mVideo.dec_picture, - p_H264_Dpb, - &p_H264_Dpb->mVideo.old_slice); - - if (new_pic_flag) { /* new picture */ - if (p_H264_Dpb->mVideo.dec_picture) { - store_picture_in_dpb(p_H264_Dpb, - p_H264_Dpb->mVideo.dec_picture); - /* dump_dpb(&p_H264_Dpb->mDPB); */ - } - } -#else - new_pic_flag = (p_H264_Dpb->mVideo.dec_picture == NULL); -#endif - p_H264_Dpb->buf_alloc_fail = 0; - p_H264_Dpb->dpb_error_flag = 0; - slice_prepare(p_H264_Dpb, &p_H264_Dpb->mDPB, &p_H264_Dpb->mVideo, - &p_H264_Dpb->mSPS, &p_H264_Dpb->mSlice); - - if (p_Dpb->num_ref_frames != p_H264_Dpb->mSPS.num_ref_frames) { - dpb_print(p_H264_Dpb->decoder_index, 0, - "num_ref_frames change from %d to %d\r\n", - p_Dpb->num_ref_frames, p_H264_Dpb->mSPS.num_ref_frames); - p_Dpb->num_ref_frames = p_H264_Dpb->mSPS.num_ref_frames; - } - /* if (p_Vid->active_sps != sps) { */ - if (p_H264_Dpb->mDPB.init_done == 0) { - /*init_global_buffers(p_Vid, 0); - * ** * *if (!p_Vid->no_output_of_prior_pics_flag) - ** * *{ - ** * * flush_dpb(p_Vid->p_Dpb_layer[0]); - ** * *} - ** * *init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 0); - */ - init_dpb(p_H264_Dpb, 0); - } - - - if (new_pic_flag) { /* new picture */ - dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, - "check frame_num gap: cur frame_num %d pre_frame_num %d max_frmae_num %d\r\n", - currSlice->frame_num, - p_Vid->pre_frame_num, - p_Vid->max_frame_num); - if (p_Vid->recovery_point == 0 && - p_Vid->max_frame_num <= FRAME_NUM_MAX_SIZE && - currSlice->frame_num != p_Vid->pre_frame_num && - currSlice->frame_num != - (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num) { - /*if (active_sps-> - *gaps_in_frame_num_value_allowed_flag - *== 0) { - * error("An unintentional - * loss of pictures occurs! Exit\n", - * 100); - *} - *if (p_Vid->conceal_mode == 0) - */ - fill_frame_num_gap(p_Vid, currSlice); - } - - if (currSlice->nal_reference_idc) { - dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_DPB_DETAIL, - "nal_reference_idc not 0, set pre_frame_num(%d) to frame_num (%d)\n", - p_Vid->pre_frame_num, currSlice->frame_num); - p_Vid->pre_frame_num = currSlice->frame_num; - } - - decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice); - p_H264_Dpb->mVideo.dec_picture = get_new_pic(p_H264_Dpb, - p_H264_Dpb->mSlice.structure, - /*p_Vid->width, p_Vid->height, - * p_Vid->width_cr, - * p_Vid->height_cr, - */ - 1); - if (p_H264_Dpb->mVideo.dec_picture) { - struct DecodedPictureBuffer *p_Dpb = - &p_H264_Dpb->mDPB; - struct StorablePicture *p = - p_H264_Dpb->mVideo.dec_picture; - init_picture(p_H264_Dpb, &p_H264_Dpb->mSlice, - p_H264_Dpb->mVideo.dec_picture); -#if 1 - /* rain */ - p_H264_Dpb->mVideo.dec_picture->offset_delimiter_lo = - p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_LO]; - p_H264_Dpb->mVideo.dec_picture->offset_delimiter_hi = - p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_HI]; - - p_H264_Dpb->mVideo.dec_picture->buf_spec_num = -1; - p_H264_Dpb->mVideo.dec_picture-> - colocated_buf_index = -1; - update_pic_num(p_H264_Dpb); - - if ((currSlice->structure == TOP_FIELD) || - (currSlice->structure == BOTTOM_FIELD)) { - /* check for frame store with same - * pic_number - */ - check_frame_store_same_pic_num(p_Dpb, p, - currSlice); - } - - if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num == - -1) { - p_H264_Dpb->mVideo.dec_picture->buf_spec_num = - get_free_buf_idx(p_H264_Dpb->vdec); - if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num - < 0) { - p_H264_Dpb->buf_alloc_fail = 1; - p_H264_Dpb->mVideo.dec_picture-> - buf_spec_is_alloced = 0; - } else - p_H264_Dpb->mVideo.dec_picture-> - buf_spec_is_alloced = 1; - - if (p_H264_Dpb->mVideo.dec_picture-> - used_for_reference) { - p_H264_Dpb->mVideo.dec_picture-> - colocated_buf_index = - allocate_colocate_buf( - p_H264_Dpb); - } - } -#endif - } - } - - if (p_H264_Dpb->mSlice.slice_type == P_SLICE) - init_lists_p_slice(&p_H264_Dpb->mSlice); - else if (p_H264_Dpb->mSlice.slice_type == B_SLICE) - init_lists_b_slice(&p_H264_Dpb->mSlice); - else - init_lists_i_slice(&p_H264_Dpb->mSlice); - - reorder_lists(&p_H264_Dpb->mSlice); - - if (p_H264_Dpb->mSlice.structure == FRAME) - init_mbaff_lists(p_H264_Dpb, &p_H264_Dpb->mSlice); - - if (new_pic_flag) - return 1; - - return 0; -} - -enum PictureStructure get_cur_slice_picture_struct( - struct h264_dpb_stru *p_H264_Dpb) -{ - struct Slice *currSlice = &p_H264_Dpb->mSlice; - return currSlice->structure; -} - -static unsigned char is_pic_in_dpb(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *pic) -{ - unsigned char ret = 0; - int i; - struct DecodedPictureBuffer *p_Dpb = - &p_H264_Dpb->mDPB; - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->top_field == pic || - p_Dpb->fs[i]->bottom_field == pic || - p_Dpb->fs[i]->frame == pic) { - ret = 1; - break; - } - } - return ret; -} - -int dpb_check_ref_list_error( - struct h264_dpb_stru *p_H264_Dpb) -{ - int i; - /*int j;*/ - struct Slice *currSlice = &p_H264_Dpb->mSlice; - /* in first output, ignore ref check */ - if (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE) - return 0; - if ((currSlice->slice_type != I_SLICE) && - (currSlice->slice_type != SI_SLICE)) { - for (i = 0; i < currSlice->listXsize[0]; i++) { - /*for (j = i + 1; j < currSlice->listXsize[0]; j++) { - if(currSlice->listX[0][i]->pic_num == - currSlice->listX[0][j]->pic_num) - return 1; - }*/ - if (currSlice->listX[0][i] == NULL) - return 5; - if (!is_pic_in_dpb(p_H264_Dpb, - currSlice->listX[0][i])) - return 1; - if (currSlice->listX[0][i]->frame && - currSlice->listX[0][i]->frame->non_existing) - return 3; - } - } - - if (currSlice->slice_type == B_SLICE) { - for (i = 0; i < currSlice->listXsize[1]; i++) { - /*for (j = i + 1; j < currSlice->listXsize[1]; j++) { - if(currSlice->listX[1][i]->pic_num == - currSlice->listX[1][j]->pic_num) - return 2; - } - for (j = 0; j < currSlice->listXsize[0]; j++) { - if(currSlice->listX[1][i]->pic_num == - currSlice->listX[0][j]->pic_num) - return 3; - }*/ - if (currSlice->listX[1][i] == NULL) - return 6; - if (!is_pic_in_dpb(p_H264_Dpb, - currSlice->listX[1][i])) - return 2; - if (currSlice->listX[1][i]->frame && - currSlice->listX[1][i]->frame->non_existing) - return 4; -#if 0 - if (currSlice->listXsize[0] == 1 && - currSlice->listXsize[1] == 1 && - currSlice->listX[1][0] == - currSlice->listX[0][0]) - return 3; -#endif - } - } - return 0; -} - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h deleted file mode 100644 index 222113f7eb1b..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h +++ /dev/null @@ -1,952 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef H264_DPB_H_ -#define H264_DPB_H_ - -#define ERROR_CHECK - -#define OUTPUT_BUFFER_IN_C - -#define PRINT_FLAG_ERROR 0x0 -#define PRINT_FLAG_VDEC_STATUS 0X0001 -#define PRINT_FLAG_UCODE_EVT 0x0002 -#define PRINT_FLAG_MMU_DETAIL 0x0004 -#define PRINT_FLAG_ERRORFLAG_DBG 0x0008 -#define PRINT_FLAG_DPB_DETAIL 0x0010 -#define PRINT_FLAG_DEC_DETAIL 0x0020 -#define PRINT_FLAG_VDEC_DETAIL 0x0040 -#define PRINT_FLAG_DUMP_DPB 0x0080 -#define PRINT_FRAMEBASE_DATA 0x0100 -#define PRINT_FLAG_DEBUG_POC 0x0200 -#define RRINT_FLAG_RPM 0x0400 -#define DEBUG_DISABLE_RUNREADY_RMBUF 0x0800 -#define PRINT_FLAG_DUMP_BUFSPEC 0x1000 -#define PRINT_FLAG_V4L_DETAIL 0x8000 -#define DISABLE_ERROR_HANDLE 0x10000 -#define DEBUG_DUMP_STAT 0x80000 - -#define PIC_SINGLE_FRAME 0 -#define PIC_TOP_BOT_TOP 1 -#define PIC_BOT_TOP_BOT 2 -#define PIC_DOUBLE_FRAME 3 -#define PIC_TRIPLE_FRAME 4 -#define PIC_TOP_BOT 5 -#define PIC_BOT_TOP 6 -#define PIC_INVALID 7 - -#define MVC_EXTENSION_ENABLE 0 -#define PRINTREFLIST 0 - -#define MAX_LIST_SIZE 33 - -#define H264_OUTPUT_MODE_NORMAL 0x4 -#define H264_OUTPUT_MODE_FAST 0x8 - -#define FALSE 0 - -#define H264_SLICE_HEAD_DONE 0x01 -#define H264_PIC_DATA_DONE 0x02 -/*#define H264_SPS_DONE 0x03*/ -/*#define H264_PPS_DONE 0x04*/ -/*#define H264_SLICE_DATA_DONE 0x05*/ -/*#define H264_DATA_END 0x06*/ - -#define H264_CONFIG_REQUEST 0x11 -#define H264_DATA_REQUEST 0x12 -#define H264_WRRSP_REQUEST 0x13 -#define H264_WRRSP_DONE 0x14 - -#define H264_DECODE_BUFEMPTY 0x20 -#define H264_DECODE_TIMEOUT 0x21 -#define H264_SEARCH_BUFEMPTY 0x22 -#define H264_DECODE_OVER_SIZE 0x23 - -#define VIDEO_SIGNAL_LOW 0x26 -#define VIDEO_SIGNAL_HIGHT 0x27 - - -#define H264_FIND_NEXT_PIC_NAL 0x50 -#define H264_FIND_NEXT_DVEL_NAL 0x51 -#define H264_AUX_DATA_READY 0x52 - -#define H264_SEI_DATA_READY 0x53 -#define H264_SEI_DATA_DONE 0x54 - - /* 0x8x, search state*/ -#define H264_STATE_SEARCH_AFTER_SPS 0x80 -#define H264_STATE_SEARCH_AFTER_PPS 0x81 -#define H264_STATE_PARSE_SLICE_HEAD 0x82 -#define H264_STATE_SEARCH_HEAD 0x83 - /**/ -#define H264_ACTION_SEARCH_HEAD 0xf0 -#define H264_ACTION_DECODE_SLICE 0xf1 -#define H264_ACTION_CONFIG_DONE 0xf2 -#define H264_ACTION_DECODE_NEWPIC 0xf3 -#define H264_ACTION_DECODE_START 0xff - -#define RPM_BEGIN 0x0 -#define RPM_END 0x400 - -#define val(s) (s[0]|(s[1]<<16)) - -#define FRAME_IN_DPB 24 -#define DPB_OFFSET 0x100 -#define MMCO_OFFSET 0x200 -union param { -#if 0 -#define H_TIME_STAMP_START 0X00 -#define H_TIME_STAMP_END 0X17 -#define PTS_ZERO_0 0X18 -#define PTS_ZERO_1 0X19 -#endif -#define FIXED_FRAME_RATE_FLAG 0X21 - -#define OFFSET_DELIMITER_LO 0x2f -#define OFFSET_DELIMITER_HI 0x30 - - -#define SLICE_IPONLY_BREAK 0X5C -#define PREV_MAX_REFERENCE_FRAME_NUM 0X5D -#define EOS 0X5E -#define FRAME_PACKING_TYPE 0X5F -#define OLD_POC_PAR_1 0X60 -#define OLD_POC_PAR_2 0X61 -#define PREV_MBX 0X62 -#define PREV_MBY 0X63 -#define ERROR_SKIP_MB_NUM 0X64 -#define ERROR_MB_STATUS 0X65 -#define L0_PIC0_STATUS 0X66 -#define TIMEOUT_COUNTER 0X67 -#define BUFFER_SIZE 0X68 -#define BUFFER_SIZE_HI 0X69 -#define CROPPING_LEFT_RIGHT 0X6A -#define CROPPING_TOP_BOTTOM 0X6B -#if 1 - /* sps_flags2: - *bit 3, bitstream_restriction_flag - *bit 2, pic_struct_present_flag - *bit 1, vcl_hrd_parameters_present_flag - *bit 0, nal_hrd_parameters_present_flag - */ -#define SPS_FLAGS2 0x6c -#define NUM_REORDER_FRAMES 0x6d -#else -#define POC_SELECT_NEED_SWAP 0X6C -#define POC_SELECT_SWAP 0X6D -#endif -#define MAX_BUFFER_FRAME 0X6E - -#define NON_CONFORMING_STREAM 0X70 -#define RECOVERY_POINT 0X71 -#define POST_CANVAS 0X72 -#define POST_CANVAS_H 0X73 -#define SKIP_PIC_COUNT 0X74 -#define TARGET_NUM_SCALING_LIST 0X75 -#define FF_POST_ONE_FRAME 0X76 -#define PREVIOUS_BIT_CNT 0X77 -#define MB_NOT_SHIFT_COUNT 0X78 -#define PIC_STATUS 0X79 -#define FRAME_COUNTER 0X7A -#define NEW_SLICE_TYPE 0X7B -#define NEW_PICTURE_STRUCTURE 0X7C -#define NEW_FRAME_NUM 0X7D -#define NEW_IDR_PIC_ID 0X7E -#define IDR_PIC_ID 0X7F - -/* h264 LOCAL */ -#define NAL_UNIT_TYPE 0X80 -#define NAL_REF_IDC 0X81 -#define SLICE_TYPE 0X82 -#define LOG2_MAX_FRAME_NUM 0X83 -#define FRAME_MBS_ONLY_FLAG 0X84 -#define PIC_ORDER_CNT_TYPE 0X85 -#define LOG2_MAX_PIC_ORDER_CNT_LSB 0X86 -#define PIC_ORDER_PRESENT_FLAG 0X87 -#define REDUNDANT_PIC_CNT_PRESENT_FLAG 0X88 -#define PIC_INIT_QP_MINUS26 0X89 -#define DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG 0X8A -#define NUM_SLICE_GROUPS_MINUS1 0X8B -#define MODE_8X8_FLAGS 0X8C -#define ENTROPY_CODING_MODE_FLAG 0X8D -#define SLICE_QUANT 0X8E -#define TOTAL_MB_HEIGHT 0X8F -#define PICTURE_STRUCTURE 0X90 -#define TOP_INTRA_TYPE 0X91 -#define RV_AI_STATUS 0X92 -#define AI_READ_START 0X93 -#define AI_WRITE_START 0X94 -#define AI_CUR_BUFFER 0X95 -#define AI_DMA_BUFFER 0X96 -#define AI_READ_OFFSET 0X97 -#define AI_WRITE_OFFSET 0X98 -#define AI_WRITE_OFFSET_SAVE 0X99 -#define RV_AI_BUFF_START 0X9A -#define I_PIC_MB_COUNT 0X9B -#define AI_WR_DCAC_DMA_CTRL 0X9C -#define SLICE_MB_COUNT 0X9D -#define PICTYPE 0X9E -#define SLICE_GROUP_MAP_TYPE 0X9F -#define MB_TYPE 0XA0 -#define MB_AFF_ADDED_DMA 0XA1 -#define PREVIOUS_MB_TYPE 0XA2 -#define WEIGHTED_PRED_FLAG 0XA3 -#define WEIGHTED_BIPRED_IDC 0XA4 -/* bit 3:2 - PICTURE_STRUCTURE - * bit 1 - MB_ADAPTIVE_FRAME_FIELD_FLAG - * bit 0 - FRAME_MBS_ONLY_FLAG - */ -#define MBFF_INFO 0XA5 -#define TOP_INTRA_TYPE_TOP 0XA6 - -#define RV_AI_BUFF_INC 0xa7 - -#define DEFAULT_MB_INFO_LO 0xa8 - -/* 0 -- no need to read - * 1 -- need to wait Left - * 2 -- need to read Intra - * 3 -- need to read back MV - */ -#define NEED_READ_TOP_INFO 0xa9 -/* 0 -- idle - * 1 -- wait Left - * 2 -- reading top Intra - * 3 -- reading back MV - */ -#define READ_TOP_INFO_STATE 0xaa -#define DCAC_MBX 0xab -#define TOP_MB_INFO_OFFSET 0xac -#define TOP_MB_INFO_RD_IDX 0xad -#define TOP_MB_INFO_WR_IDX 0xae - -#define VLD_NO_WAIT 0 -#define VLD_WAIT_BUFFER 1 -#define VLD_WAIT_HOST 2 -#define VLD_WAIT_GAP 3 - -#define VLD_WAITING 0xaf - -#define MB_X_NUM 0xb0 -/* #define MB_WIDTH 0xb1 */ -#define MB_HEIGHT 0xb2 -#define MBX 0xb3 -#define TOTAL_MBY 0xb4 -#define INTR_MSK_SAVE 0xb5 - -/* #define has_time_stamp 0xb6 */ -#define NEED_DISABLE_PPE 0xb6 -#define IS_NEW_PICTURE 0XB7 -#define PREV_NAL_REF_IDC 0XB8 -#define PREV_NAL_UNIT_TYPE 0XB9 -#define FRAME_MB_COUNT 0XBA -#define SLICE_GROUP_UCODE 0XBB -#define SLICE_GROUP_CHANGE_RATE 0XBC -#define SLICE_GROUP_CHANGE_CYCLE_LEN 0XBD -#define DELAY_LENGTH 0XBE -#define PICTURE_STRUCT 0XBF -/* #define pre_picture_struct 0xc0 */ -#define DCAC_PREVIOUS_MB_TYPE 0xc1 - -#define TIME_STAMP 0XC2 -#define H_TIME_STAMP 0XC3 -#define VPTS_MAP_ADDR 0XC4 -#define H_VPTS_MAP_ADDR 0XC5 - -/*#define MAX_DPB_SIZE 0XC6*/ -#define PIC_INSERT_FLAG 0XC7 - -#define TIME_STAMP_START 0XC8 -#define TIME_STAMP_END 0XDF - -#define OFFSET_FOR_NON_REF_PIC 0XE0 -#define OFFSET_FOR_TOP_TO_BOTTOM_FIELD 0XE2 -#define MAX_REFERENCE_FRAME_NUM 0XE4 -#define FRAME_NUM_GAP_ALLOWED 0XE5 -#define NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE 0XE6 -#define PROFILE_IDC_MMCO 0XE7 -#define LEVEL_IDC_MMCO 0XE8 -#define FRAME_SIZE_IN_MB 0XE9 -#define DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG 0XEA -#define PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1 0XEB -#define PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1 0XEC -#define CURRENT_SPS_ID 0XED -#define CURRENT_PPS_ID 0XEE -/* bit 0 - sequence parameter set may change - * bit 1 - picture parameter set may change - * bit 2 - new dpb just inited - * bit 3 - IDR picture not decoded yet - * bit 5:4 - 0: mb level code loaded 1: picture - * level code loaded 2: slice level code loaded - */ -#define DECODE_STATUS 0XEF -#define FIRST_MB_IN_SLICE 0XF0 -#define PREV_MB_WIDTH 0XF1 -#define PREV_FRAME_SIZE_IN_MB 0XF2 -/*#define MAX_REFERENCE_FRAME_NUM_IN_MEM 0XF3*/ -/* bit 0 - aspect_ratio_info_present_flag - * bit 1 - timing_info_present_flag - * bit 2 - nal_hrd_parameters_present_flag - * bit 3 - vcl_hrd_parameters_present_flag - * bit 4 - pic_struct_present_flag - * bit 5 - bitstream_restriction_flag - */ -#define VUI_STATUS 0XF4 -#define ASPECT_RATIO_IDC 0XF5 -#define ASPECT_RATIO_SAR_WIDTH 0XF6 -#define ASPECT_RATIO_SAR_HEIGHT 0XF7 -#define NUM_UNITS_IN_TICK 0XF8 -#define TIME_SCALE 0XFA -#define CURRENT_PIC_INFO 0XFC -#define DPB_BUFFER_INFO 0XFD -#define REFERENCE_POOL_INFO 0XFE -#define REFERENCE_LIST_INFO 0XFF - struct{ - unsigned short data[RPM_END-RPM_BEGIN]; - } l; - struct{ - unsigned short dump[DPB_OFFSET]; - unsigned short dpb_base[FRAME_IN_DPB<<3]; - - unsigned short dpb_max_buffer_frame; - unsigned short actual_dpb_size; - - unsigned short colocated_buf_status; - - unsigned short num_forward_short_term_reference_pic; - unsigned short num_short_term_reference_pic; - unsigned short num_reference_pic; - - unsigned short current_dpb_index; - unsigned short current_decoded_frame_num; - unsigned short current_reference_frame_num; - - unsigned short l0_size; - unsigned short l1_size; - - /* [6:5] : nal_ref_idc */ - /* [4:0] : nal_unit_type */ - unsigned short NAL_info_mmco; - - /* [1:0] : 00 - top field, 01 - bottom field, - * 10 - frame, 11 - mbaff frame - */ - unsigned short picture_structure_mmco; - - unsigned short frame_num; - unsigned short pic_order_cnt_lsb; - - unsigned short num_ref_idx_l0_active_minus1; - unsigned short num_ref_idx_l1_active_minus1; - - unsigned short PrevPicOrderCntLsb; - unsigned short PreviousFrameNum; - - /* 32 bits variables */ - unsigned short delta_pic_order_cnt_bottom[2]; - unsigned short delta_pic_order_cnt_0[2]; - unsigned short delta_pic_order_cnt_1[2]; - - unsigned short PrevPicOrderCntMsb[2]; - unsigned short PrevFrameNumOffset[2]; - - unsigned short frame_pic_order_cnt[2]; - unsigned short top_field_pic_order_cnt[2]; - unsigned short bottom_field_pic_order_cnt[2]; - - unsigned short colocated_mv_addr_start[2]; - unsigned short colocated_mv_addr_end[2]; - unsigned short colocated_mv_wr_addr[2]; - } dpb; - struct { - unsigned short dump[MMCO_OFFSET]; - - /* array base address for offset_for_ref_frame */ - unsigned short offset_for_ref_frame_base[128]; - - /* 0 - Index in DPB - * 1 - Picture Flag - * [ 2] : 0 - short term reference, - * 1 - long term reference - * [ 1] : bottom field - * [ 0] : top field - * 2 - Picture Number (short term or long term) low 16 bits - * 3 - Picture Number (short term or long term) high 16 bits - */ - unsigned short reference_base[128]; - - /* command and parameter, until command is 3 */ - unsigned short l0_reorder_cmd[66]; - unsigned short l1_reorder_cmd[66]; - - /* command and parameter, until command is 0 */ - unsigned short mmco_cmd[44]; - - unsigned short l0_base[40]; - unsigned short l1_base[40]; - } mmco; - struct { - /* from ucode lmem, do not change this struct */ - } p; -}; - - -struct StorablePicture; -struct VideoParameters; -struct DecodedPictureBuffer; - -/* New enum for field processing */ -enum PictureStructure { - FRAME, - TOP_FIELD, - BOTTOM_FIELD -}; - -#define I_Slice 2 -#define P_Slice 5 -#define B_Slice 6 -#define P_Slice_0 0 -#define B_Slice_1 1 -#define I_Slice_7 7 - -enum SliceType { - P_SLICE = 0, - B_SLICE = 1, - I_SLICE = 2, - SP_SLICE = 3, - SI_SLICE = 4, - NUM_SLICE_TYPES = 5 -}; - -enum ProfileIDC { - FREXT_CAVLC444 = 44, /*!< YUV 4:4:4/14 "CAVLC 4:4:4"*/ - BASELINE = 66, /*!< YUV 4:2:0/8 "Baseline"*/ - MAIN = 77, /*!< YUV 4:2:0/8 "Main"*/ - EXTENDED = 88, /*!< YUV 4:2:0/8 "Extended"*/ - FREXT_HP = 100, /*!< YUV 4:2:0/8 "High"*/ - FREXT_Hi10P = 110, /*!< YUV 4:2:0/10 "High 10"*/ - FREXT_Hi422 = 122, /*!< YUV 4:2:2/10 "High 4:2:2"*/ - FREXT_Hi444 = 244, /*!< YUV 4:4:4/14 "High 4:4:4"*/ - MVC_HIGH = 118, /*!< YUV 4:2:0/8 "Multiview High"*/ - STEREO_HIGH = 128 /*!< YUV 4:2:0/8 "Stereo High"*/ -}; - -enum FirstInsertFrm_State { - FirstInsertFrm_IDLE = 0, - FirstInsertFrm_OUT = 1, - FirstInsertFrm_SKIPDONE = 2, -}; - - -struct SPSParameters { - unsigned int profile_idc; - int pic_order_cnt_type; - int log2_max_pic_order_cnt_lsb_minus4; - int num_ref_frames_in_pic_order_cnt_cycle; - short offset_for_ref_frame[128]; - short offset_for_non_ref_pic; - short offset_for_top_to_bottom_field; - - /**/ - int frame_mbs_only_flag; - int num_ref_frames; - int max_dpb_size; - - int log2_max_frame_num_minus4; -}; - -#define DEC_REF_PIC_MARKING_BUFFER_NUM_MAX 45 -struct DecRefPicMarking_s { - int memory_management_control_operation; - int difference_of_pic_nums_minus1; - int long_term_pic_num; - int long_term_frame_idx; - int max_long_term_frame_idx_plus1; - struct DecRefPicMarking_s *Next; -}; - -#define REORDERING_COMMAND_MAX_SIZE 33 -struct Slice { - int first_mb_in_slice; - int mode_8x8_flags; - int picture_structure_mmco; - - int frame_num; - int idr_flag; - int toppoc; - int bottompoc; - int framepoc; - int pic_order_cnt_lsb; - int PicOrderCntMsb; - unsigned char field_pic_flag; - unsigned char bottom_field_flag; - int ThisPOC; - int nal_reference_idc; - int AbsFrameNum; - int delta_pic_order_cnt_bottom; - int delta_pic_order_cnt[2]; - - /**/ - char listXsize[6]; - struct StorablePicture *listX[6][MAX_LIST_SIZE * 2]; - - /**/ - enum PictureStructure structure; - int long_term_reference_flag; - int no_output_of_prior_pics_flag; - int adaptive_ref_pic_buffering_flag; - - struct VideoParameters *p_Vid; - struct DecodedPictureBuffer *p_Dpb; - int num_ref_idx_active[2]; /* number of available list references */ - - /*modification*/ - int slice_type; /* slice type */ - int ref_pic_list_reordering_flag[2]; - int modification_of_pic_nums_idc[2][REORDERING_COMMAND_MAX_SIZE]; - int abs_diff_pic_num_minus1[2][REORDERING_COMMAND_MAX_SIZE]; - int long_term_pic_idx[2][REORDERING_COMMAND_MAX_SIZE]; - /**/ - unsigned char dec_ref_pic_marking_buffer_valid; - struct DecRefPicMarking_s - dec_ref_pic_marking_buffer[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX]; - int pic_struct; -}; - -struct OldSliceParams { - unsigned int field_pic_flag; - unsigned int frame_num; - int nal_ref_idc; - unsigned int pic_oder_cnt_lsb; - int delta_pic_oder_cnt_bottom; - int delta_pic_order_cnt[2]; - unsigned char bottom_field_flag; - unsigned char idr_flag; - int idr_pic_id; - int pps_id; -#if (MVC_EXTENSION_ENABLE) - int view_id; - int inter_view_flag; - int anchor_pic_flag; -#endif - int layer_id; -}; - -struct VideoParameters { - int PrevPicOrderCntMsb; - int PrevPicOrderCntLsb; - unsigned char last_has_mmco_5; - unsigned char last_pic_bottom_field; - int ThisPOC; - int PreviousFrameNum; - int FrameNumOffset; - int PreviousFrameNumOffset; - int max_frame_num; - unsigned int pre_frame_num; - int ExpectedDeltaPerPicOrderCntCycle; - int PicOrderCntCycleCnt; - int FrameNumInPicOrderCntCycle; - int ExpectedPicOrderCnt; - - /**/ - struct SPSParameters *active_sps; - struct Slice **ppSliceList; - int iSliceNumOfCurrPic; - int conceal_mode; - int earlier_missing_poc; - int pocs_in_dpb[100]; - - struct OldSliceParams old_slice; - /**/ - struct StorablePicture *dec_picture; - struct StorablePicture *no_reference_picture; - - /*modification*/ - int non_conforming_stream; - int recovery_point; -}; - -static inline int imin(int a, int b) -{ - return ((a) < (b)) ? (a) : (b); -} - -static inline int imax(int a, int b) -{ - return ((a) > (b)) ? (a) : (b); -} - -#define MAX_PIC_BUF_NUM 128 -#define MAX_NUM_SLICES 50 - -struct StorablePicture { -/**/ - int width; - int height; - - int y_canvas_index; - int u_canvas_index; - int v_canvas_index; -/**/ - int index; - unsigned char is_used; - - enum PictureStructure structure; - - int poc; - int top_poc; - int bottom_poc; - int frame_poc; - unsigned int frame_num; - unsigned int recovery_frame; - - int pic_num; - int buf_spec_num; - int buf_spec_is_alloced; - int colocated_buf_index; - int long_term_pic_num; - int long_term_frame_idx; - - unsigned char is_long_term; - int used_for_reference; - int is_output; -#if 1 - /* rain */ - int pre_output; -#endif - int non_existing; - int separate_colour_plane_flag; - - short max_slice_id; - - int size_x, size_y, size_x_cr, size_y_cr; - int size_x_m1, size_y_m1, size_x_cr_m1, size_y_cr_m1; - int coded_frame; - int mb_aff_frame_flag; - unsigned int PicWidthInMbs; - unsigned int PicSizeInMbs; - int iLumaPadY, iLumaPadX; - int iChromaPadY, iChromaPadX; - - /* for mb aff, if frame for referencing the top field */ - struct StorablePicture *top_field; - /* for mb aff, if frame for referencing the bottom field */ - struct StorablePicture *bottom_field; - /* for mb aff, if field for referencing the combined frame */ - struct StorablePicture *frame; - - int slice_type; - int idr_flag; - int no_output_of_prior_pics_flag; - int long_term_reference_flag; - int adaptive_ref_pic_buffering_flag; - - int chroma_format_idc; - int frame_mbs_only_flag; - int frame_cropping_flag; - int frame_crop_left_offset; - int frame_crop_right_offset; - int frame_crop_top_offset; - int frame_crop_bottom_offset; - int qp; - int chroma_qp_offset[2]; - int slice_qp_delta; - /* stores the memory management control operations */ - struct DecRefPicMarking_s *dec_ref_pic_marking_buffer; - - /* picture error concealment */ - /*indicates if this is a concealed picture */ - int concealed_pic; - - /* variables for tone mapping */ - int seiHasTone_mapping; - int tone_mapping_model_id; - int tonemapped_bit_depth; - /* imgpel* tone_mapping_lut; tone mapping look up table */ - - int proc_flag; -#if (MVC_EXTENSION_ENABLE) - int view_id; - int inter_view_flag; - int anchor_pic_flag; -#endif - int iLumaStride; - int iChromaStride; - int iLumaExpandedHeight; - int iChromaExpandedHeight; - /* imgpel **cur_imgY; for more efficient get_block_luma */ - int no_ref; - int iCodingType; - - char listXsize[MAX_NUM_SLICES][2]; - struct StorablePicture **listX[MAX_NUM_SLICES][2]; - int layer_id; - - int offset_delimiter_lo; - int offset_delimiter_hi; - - u32 pts; - u64 pts64; - u64 timestamp; - unsigned char data_flag; - int pic_struct; - - /* picture qos infomation*/ - int frame_size; - int max_qp; - int avg_qp; - int min_qp; - int max_skip; - int avg_skip; - int min_skip; - int max_mv; - int min_mv; - int avg_mv; -}; - -struct FrameStore { - /* rain */ - int buf_spec_num; - /* rain */ - int colocated_buf_index; - - /* 0=empty; 1=top; 2=bottom; 3=both fields (or frame) */ - int is_used; - /* 0=not used for ref; 1=top used; 2=bottom used; - * 3=both fields (or frame) used - */ - int is_reference; - /* 0=not used for ref; 1=top used; 2=bottom used; - * 3=both fields (or frame) used - */ - int is_long_term; - /* original marking by nal_ref_idc: 0=not used for ref; 1=top used; - * 2=bottom used; 3=both fields (or frame) used - */ - int is_orig_reference; - - int is_non_existent; - - unsigned int frame_num; - unsigned int recovery_frame; - - int frame_num_wrap; - int long_term_frame_idx; - int is_output; -#if 1 - /* rain */ - int pre_output; - /* index in gFrameStore */ - int index; -#define I_FLAG 0x01 -#define IDR_FLAG 0x02 -#define ERROR_FLAG 0x10 -#define NULL_FLAG 0x20 -#define MAYBE_ERROR_FLAG 0x40 -#define NODISP_FLAG 0x80 - unsigned char data_flag; -#endif - int poc; - - /* picture error concealment */ - int concealment_reference; - - struct StorablePicture *frame; - struct StorablePicture *top_field; - struct StorablePicture *bottom_field; - -#if (MVC_EXTENSION_ENABLE) - int view_id; - int inter_view_flag[2]; - int anchor_pic_flag[2]; -#endif - int layer_id; - - u32 pts; - u64 pts64; - u64 timestamp; - - - /* picture qos infomation*/ - int slice_type; - int frame_size; - - int max_qp; - int avg_qp; - int min_qp; - int max_skip; - int avg_skip; - int min_skip; - int max_mv; - int min_mv; - int avg_mv; -}; - - -/* #define DPB_SIZE_MAX 16 */ -#define DPB_SIZE_MAX 32 -struct DecodedPictureBuffer { - struct VideoParameters *p_Vid; - /* InputParameters *p_Inp; ??? */ - struct FrameStore *fs[DPB_SIZE_MAX]; - struct FrameStore *fs_ref[DPB_SIZE_MAX]; - struct FrameStore *fs_ltref[DPB_SIZE_MAX]; - /* inter-layer reference (for multi-layered codecs) */ - struct FrameStore *fs_ilref[DPB_SIZE_MAX]; - /**/ - struct FrameStore *fs_list0[DPB_SIZE_MAX]; - struct FrameStore *fs_list1[DPB_SIZE_MAX]; - struct FrameStore *fs_listlt[DPB_SIZE_MAX]; - - /**/ - unsigned int size; - unsigned int used_size; - unsigned int ref_frames_in_buffer; - unsigned int ltref_frames_in_buffer; - int last_output_poc; -#if (MVC_EXTENSION_ENABLE) - int last_output_view_id; -#endif - int max_long_term_pic_idx; - - - int init_done; - int first_pic_done; /*by rain*/ - int num_ref_frames; - - struct FrameStore *last_picture; - unsigned int used_size_il; - int layer_id; - - /* DPB related function; */ -}; - -struct h264_dpb_stru { - struct vdec_s *vdec; - int decoder_index; - - union param dpb_param; - - int decode_idx; - int buf_num; - int curr_POC; - int reorder_pic_num; - u8 fast_output_enable; - /*poc_even_flag: - 0, init; 1, odd; 2, even*/ - u8 poc_even_odd_flag; - u32 decode_pic_count; - /**/ - unsigned int max_reference_size; - - unsigned int colocated_buf_map; - unsigned int colocated_buf_count; - unsigned int colocated_mv_addr_start; - unsigned int colocated_mv_addr_end; - unsigned int colocated_buf_size; - - struct DecodedPictureBuffer mDPB; - struct Slice mSlice; - struct VideoParameters mVideo; - struct SPSParameters mSPS; - - struct StorablePicture m_PIC[MAX_PIC_BUF_NUM]; - struct FrameStore mFrameStore[DPB_SIZE_MAX]; - - /*vui*/ - unsigned int vui_status; - unsigned int num_units_in_tick; - unsigned int time_scale; - unsigned int fixed_frame_rate_flag; - unsigned int aspect_ratio_idc; - unsigned int aspect_ratio_sar_width; - unsigned int aspect_ratio_sar_height; - u8 bitstream_restriction_flag; - u16 num_reorder_frames; - u16 max_dec_frame_buffering; - - unsigned int dec_dpb_status; - unsigned char buf_alloc_fail; - unsigned int dpb_error_flag; - unsigned int first_insert_frame; - int first_output_poc; -}; - - -extern unsigned int h264_debug_flag; -extern unsigned int h264_debug_mask; - -int dpb_print(int indext, int debug_flag, const char *fmt, ...); - -int dpb_print_cont(int index, int debug_flag, const char *fmt, ...); - -unsigned char dpb_is_debug(int index, int debug_flag); - -int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame); - -int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num); - -void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index); - -int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb); - -int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb); - -void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb, - int id, int actual_dpb_size, int max_reference_size); - -void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count); - -int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index); - -int get_free_buf_idx(struct vdec_s *vdec); - -int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *p, unsigned char data_flag); - -int release_picture(struct h264_dpb_stru *p_H264_Dpb, - struct StorablePicture *pic); - -void remove_dpb_pictures(struct h264_dpb_stru *p_H264_Dpb); - -void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb); - -void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb); - -int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb, - int buf_spec_num); - -void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb, - u8 force_flag); - -void flush_dpb(struct h264_dpb_stru *p_H264_Dpb); - -void print_pic_info(int decindex, const char *info, - struct StorablePicture *pic, - int slice_type); -void dump_dpb(struct DecodedPictureBuffer *p_Dpb, u8 force); - -void dump_pic(struct h264_dpb_stru *p_H264_Dpb); - -enum PictureStructure get_cur_slice_picture_struct( - struct h264_dpb_stru *p_H264_Dpb); - -int dpb_check_ref_list_error( - struct h264_dpb_stru *p_H264_Dpb); -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c deleted file mode 100644 index 08d5421564ed..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c +++ /dev/null @@ -1,9030 +0,0 @@ -/* - * drivers/amlogic/amports/vh264.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include - -#include "../utils/vdec_input.h" -#include - -#include -#include "../utils/vdec.h" -#include "../utils/amvdec.h" -#include "../h264/vh264.h" -#include "../../../stream_input/parser/streambuf.h" -#include -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include "../utils/firmware.h" -#include -#include -#include "../utils/config_parser.h" -#include "../../../amvdec_ports/vdec_drv_base.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" -#include - -#include - - -#undef pr_info -#define pr_info printk -#define VDEC_DW -#define DEBUG_UCODE -#define MEM_NAME "codec_m264" -#define MULTI_INSTANCE_FRAMEWORK -/* #define ONE_COLOCATE_BUF_PER_DECODE_BUF */ -#include "h264_dpb.h" -/* #define SEND_PARAM_WITH_REG */ - -#define DRIVER_NAME "ammvdec_h264" -#define MODULE_NAME "ammvdec_h264" -#define DRIVER_HEADER_NAME "ammvdec_h264_header" - -#define CHECK_INTERVAL (HZ/100) - -#define SEI_DATA_SIZE (8*1024) -#define SEI_ITU_DATA_SIZE (4*1024) - -#define RATE_MEASURE_NUM 8 -#define RATE_CORRECTION_THRESHOLD 5 -#define RATE_2397_FPS 4004 /* 23.97 */ -#define RATE_25_FPS 3840 /* 25 */ -#define RATE_2997_FPS 3203 /* 29.97 */ -#define DUR2PTS(x) ((x)*90/96) -#define PTS2DUR(x) ((x)*96/90) -#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) -#define FIX_FRAME_RATE_CHECK_IFRAME_NUM 2 - -#define FIX_FRAME_RATE_OFF 0 -#define FIX_FRAME_RATE_ON 1 -#define FIX_FRAME_RATE_SMOOTH_CHECKING 2 - -#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001 -#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE 0x0002 -#define DEC_CONTROL_FLAG_FORCE_RATE_2397_FPS_FIX_FRAME_RATE 0x0010 -#define DEC_CONTROL_FLAG_FORCE_RATE_2997_FPS_FIX_FRAME_RATE 0x0020 - -#define DECODE_ID(hw) (hw_to_vdec(hw)->id) - -#define RATE_MEASURE_NUM 8 -#define RATE_CORRECTION_THRESHOLD 5 -#define RATE_24_FPS 4004 /* 23.97 */ -#define RATE_25_FPS 3840 /* 25 */ -#define DUR2PTS(x) ((x)*90/96) -#define PTS2DUR(x) ((x)*96/90) -#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) -#define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2 - -#define H264_DEV_NUM 9 - -#define CONSTRAIN_MAX_BUF_NUM - -#define H264_MMU -#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 -static int mmu_enable; -static int force_enable_mmu = 1; -unsigned int h264_debug_flag; /* 0xa0000000; */ -unsigned int h264_debug_mask = 0xff; - /* - *h264_debug_cmd: - * 0x1xx, force decoder id of xx to be disconnected - */ -unsigned int h264_debug_cmd; -static unsigned int dec_control; -static unsigned int force_rate_streambase; -static unsigned int force_rate_framebase; -static unsigned int force_disp_bufspec_num; -static unsigned int fixed_frame_rate_mode; -static unsigned int error_recovery_mode_in; -static int start_decode_buf_level = 0x8000; -static int pre_decode_buf_level = 0x1000; -static int stream_mode_start_num = 4; - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -/*to make reorder size difference of bl and el not too big*/ -static unsigned int reorder_dpb_size_margin_dv = 16; -#endif -static unsigned int reorder_dpb_size_margin = 6; -static unsigned int reference_buf_margin = 4; - -#ifdef CONSTRAIN_MAX_BUF_NUM -static u32 run_ready_max_vf_only_num; -static u32 run_ready_display_q_num; - /*0: not check - 0xff: mDPB.size - */ -static u32 run_ready_max_buf_num = 0xff; -#endif - -#define VDEC_ASSIST_CANVAS_BLK32 0x5 - - -static unsigned int max_alloc_buf_count; -static unsigned int decode_timeout_val = 100; -static unsigned int errordata_timeout_val = 50; -static unsigned int get_data_timeout_val = 2000; -#if 1 -/* H264_DATA_REQUEST does not work, disable it, -decode has error for data in none continuous address -*/ -static unsigned int frame_max_data_packet; -#else -static unsigned int frame_max_data_packet = 8; -#endif -static unsigned int radr; -static unsigned int rval; -static u32 endian = 0xff0; - -/* - udebug_flag: - bit 0, enable ucode print - bit 1, enable ucode detail print - bit 3, disable ucode watchdog - bit [31:16] not 0, pos to dump lmem - bit 2, pop bits to lmem - bit [11:8], pre-pop bits for alignment (when bit 2 is 1) -*/ -static u32 udebug_flag; -/* - when udebug_flag[1:0] is not 0 - udebug_pause_pos not 0, - pause position -*/ -static u32 udebug_pause_pos; -/* - when udebug_flag[1:0] is not 0 - and udebug_pause_pos is not 0, - pause only when DEBUG_REG2 is equal to this val -*/ -static u32 udebug_pause_val; - -static u32 udebug_pause_decode_idx; - -static unsigned int disp_vframe_valve_level; - -static unsigned int max_decode_instance_num = H264_DEV_NUM; -static unsigned int decode_frame_count[H264_DEV_NUM]; -static unsigned int display_frame_count[H264_DEV_NUM]; -static unsigned int max_process_time[H264_DEV_NUM]; -static unsigned int max_get_frame_interval[H264_DEV_NUM]; -static unsigned int run_count[H264_DEV_NUM]; -static unsigned int input_empty[H264_DEV_NUM]; -static unsigned int not_run_ready[H264_DEV_NUM]; -static unsigned int ref_frame_mark_flag[H264_DEV_NUM] = -{1, 1, 1, 1, 1, 1, 1, 1, 1}; - -#define VDEC_CLOCK_ADJUST_FRAME 30 -static unsigned int clk_adj_frame_count; - -/* - *bit[3:0]: 0, run ; 1, pause; 3, step - *bit[4]: 1, schedule run - */ -static unsigned int step[H264_DEV_NUM]; - -#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf)) -static u32 prefix_aux_buf_size = (16 * 1024); -static u32 suffix_aux_buf_size; - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -static u32 dv_toggle_prov_name; - -static u32 dolby_meta_with_el; -#endif - -/* - bit[8] - 0: use sys_info[bit 3] - not 0:use i_only_flag[7:0] - bit[7:0]: - bit 0, 1: only display I picture; - bit 1, 1: only decode I picture; -*/ -static unsigned int i_only_flag; - -/* - error_proc_policy: - bit[0] send_error_frame_flag; - (valid when bit[31] is 1, otherwise use sysinfo) - bit[1] do not decode if config_decode_buf() fail - bit[2] force release buf if in deadlock - bit[3] force sliding window ref_frames_in_buffer > num_ref_frames - bit[4] check inactive of receiver - bit[5] reset buffmgr if in deadlock - bit[6] reset buffmgr if bufspec, collocate buf, pic alloc fail - bit[7] reset buffmgr if dpb error - - bit[8] check total mbx/mby of decoded frame - bit[9] check ERROR_STATUS_REG - bit[10] check reference list - bit[11] mark error if dpb error - - bit[12] i_only when error happen -*/ -static unsigned int error_proc_policy = 0xf36; /*0x1f14*/ - - -/* - error_skip_count: - bit[11:0] error skip frame count - bit[15:12] error skip i picture count -*/ -static unsigned int error_skip_count = (0x2 << 12) | 0x40; - -static unsigned int force_sliding_margin; -/* - bit[1:0]: - 0, start playing from any frame - 1, start playing from I frame - bit[15:8]: the count of skip frames after first I - 2, start playing from second I frame (decode from the first I) - bit[15:8]: the max count of skip frames after first I - 3, start playing from IDR -*/ -static unsigned int first_i_policy = 1; - -/* - fast_output_enable: - bit [0], output frame if there is IDR in list - bit [1], output frame if the current poc is 1 big than the previous poc - bit [2], if even poc only, output frame ifthe cuurent poc - is 2 big than the previous poc - bit [3], ip only -*/ -static unsigned int fast_output_enable = H264_OUTPUT_MODE_NORMAL; - -static unsigned int enable_itu_t35 = 1; - -static unsigned int frmbase_cont_bitlevel = 0x40; - -static unsigned int frmbase_cont_bitlevel2 = 0x1; - - -#define MH264_USERDATA_ENABLE - -/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ -/* hevc->double_write_mode: - 0, no double write - 1, 1:1 ratio - 2, (1/4):(1/4) ratio - 3, (1/4):(1/4) ratio, with both compressed frame included - 4, (1/2):(1/2) ratio - 0x10, double write only - 0x10000: vdec dw horizotal 1/2 - 0x20000: vdec dw horizotal/vertical 1/2 -*/ -static u32 double_write_mode; - -#define IS_VDEC_DW(hw) (hw->double_write_mode >> 16 & 0xf) - -static void vmh264_dump_state(struct vdec_s *vdec); - -#define is_in_parsing_state(status) \ - ((status == H264_ACTION_SEARCH_HEAD) || \ - ((status & 0xf0) == 0x80)) - -#define is_interlace(frame) \ - (frame->frame &&\ - frame->top_field &&\ - frame->bottom_field &&\ - (!frame->frame->coded_frame)) -static inline bool close_to(int a, int b, int m) -{ - return (abs(a - b) < m) ? true : false; -} - -#if 0 -#define h264_alloc_hw_stru(dev, size, opt) devm_kzalloc(dev, size, opt) -#define h264_free_hw_stru(dev, hw) devm_kfree(dev, hw) -#else -#define h264_alloc_hw_stru(dev, size, opt) vzalloc(size) -#define h264_free_hw_stru(dev, hw) vfree(hw) -#endif - -/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -/* #endif */ - -/* 12M for L41 */ -#define MAX_DPB_BUFF_SIZE (12*1024*1024) -#define DEFAULT_MEM_SIZE (32*1024*1024) -#define AVIL_DPB_BUFF_SIZE 0x01ec2000 - -#define DEF_BUF_START_ADDR 0x01000000 -#define mem_sps_base 0x011c3c00 -#define mem_pps_base 0x011cbc00 -/*#define V_BUF_ADDR_OFFSET (0x13e000)*/ -u32 V_BUF_ADDR_OFFSET = 0x200000; -#define DCAC_READ_MARGIN (64 * 1024) - - -#define EXTEND_SAR 0xff -#define BUFSPEC_POOL_SIZE 64 -#define VF_POOL_SIZE 64 -#define VF_POOL_NUM 2 -#define MAX_VF_BUF_NUM 27 -#define BMMU_MAX_BUFFERS (BUFSPEC_POOL_SIZE + 3) -#define BMMU_REF_IDX (BUFSPEC_POOL_SIZE) -#define BMMU_DPB_IDX (BUFSPEC_POOL_SIZE + 1) -#define BMMU_EXTIF_IDX (BUFSPEC_POOL_SIZE + 2) -#define EXTIF_BUF_SIZE (0x10000 * 2) - -#define HEADER_BUFFER_IDX(n) (n) -#define VF_BUFFER_IDX(n) (n) - - -#define PUT_INTERVAL (HZ/100) -#define NO_DISP_WD_COUNT (3 * HZ / PUT_INTERVAL) - -#define MMU_MAX_BUFFERS BUFSPEC_POOL_SIZE -#define SWITCHING_STATE_OFF 0 -#define SWITCHING_STATE_ON_CMD3 1 -#define SWITCHING_STATE_ON_CMD1 2 - - - -#define INCPTR(p) ptr_atomic_wrap_inc(&p) - -#define SLICE_TYPE_I 2 -#define SLICE_TYPE_P 5 -#define SLICE_TYPE_B 6 - -struct buffer_spec_s { - /* - used: - -1, none allocated - 0, allocated, free - 1, used by dpb - 2, in disp queue; - 3, in disp queue, isolated, - do not use for dpb when vf_put; - 4, to release - 5, in disp queue, isolated (but not to release) - do not use for dpb when vf_put; - */ - unsigned int used; - unsigned int info0; - unsigned int info1; - unsigned int info2; - unsigned int y_addr; - unsigned int u_addr; - unsigned int v_addr; - - int y_canvas_index; - int u_canvas_index; - int v_canvas_index; - -#ifdef VDEC_DW - unsigned int vdec_dw_y_addr; - unsigned int vdec_dw_u_addr; - unsigned int vdec_dw_v_addr; - - int vdec_dw_y_canvas_index; - int vdec_dw_u_canvas_index; - int vdec_dw_v_canvas_index; -#ifdef NV21 - struct canvas_config_s vdec_dw_canvas_config[2]; -#else - struct canvas_config_s vdec_dw_canvas_config[3]; -#endif -#endif - -#ifdef NV21 - struct canvas_config_s canvas_config[2]; -#else - struct canvas_config_s canvas_config[3]; -#endif - unsigned long cma_alloc_addr; - unsigned int buf_adr; -#ifdef H264_MMU - unsigned long alloc_header_addr; -#endif - char *aux_data_buf; - int aux_data_size; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - unsigned char dv_enhance_exist; -#endif - int canvas_pos; - int vf_ref; - /*unsigned int comp_body_size;*/ - unsigned int dw_y_adr; - unsigned int dw_u_v_adr; -}; - -#define AUX_DATA_SIZE(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_size) -#define AUX_DATA_BUF(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_buf) -#define DEL_EXIST(h, p) (h->buffer_spec[p->buf_spec_num].dv_enhance_exist) - - -#define vdec_dw_spec2canvas(x) \ - (((x)->vdec_dw_v_canvas_index << 16) | \ - ((x)->vdec_dw_u_canvas_index << 8) | \ - ((x)->vdec_dw_y_canvas_index << 0)) - - -#define spec2canvas(x) \ - (((x)->v_canvas_index << 16) | \ - ((x)->u_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - -#define FRAME_INDEX(vf_index) (vf_index & 0xff) -#define BUFSPEC_INDEX(vf_index) ((vf_index >> 8) & 0xff) -#define VF_INDEX(frm_idx, bufspec_idx) (frm_idx | (bufspec_idx << 8)) - -static struct vframe_s *vh264_vf_peek(void *); -static struct vframe_s *vh264_vf_get(void *); -static void vh264_vf_put(struct vframe_s *, void *); -static int vh264_vf_states(struct vframe_states *states, void *); -static int vh264_event_cb(int type, void *data, void *private_data); -static void vh264_work(struct work_struct *work); -static void vh264_notify_work(struct work_struct *work); -#ifdef MH264_USERDATA_ENABLE -static void user_data_ready_notify_work(struct work_struct *work); -static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec); -#endif - -static const char vh264_dec_id[] = "vh264-dev"; - -#define PROVIDER_NAME "vdec.h264" - -static const struct vframe_operations_s vf_provider_ops = { - .peek = vh264_vf_peek, - .get = vh264_vf_get, - .put = vh264_vf_put, - .event_cb = vh264_event_cb, - .vf_states = vh264_vf_states, -}; - -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_CONFIG_PARAM 3 -#define DEC_RESULT_GET_DATA 4 -#define DEC_RESULT_GET_DATA_RETRY 5 -#define DEC_RESULT_ERROR 6 -#define DEC_RESULT_EOS 7 -#define DEC_RESULT_FORCE_EXIT 8 - -/* - *static const char *dec_result_str[] = { - * "DEC_RESULT_NONE ", - * "DEC_RESULT_DONE ", - * "DEC_RESULT_AGAIN ", - * "DEC_RESULT_CONFIG_PARAM", - * "DEC_RESULT_GET_DATA ", - * "DEC_RESULT_GET_DA_RETRY", - * "DEC_RESULT_ERROR ", - *}; - */ - -#define UCODE_IP_ONLY 2 -#define UCODE_IP_ONLY_PARAM 1 - -#define MC_OFFSET_HEADER 0x0000 -#define MC_OFFSET_DATA 0x1000 -#define MC_OFFSET_MMCO 0x2000 -#define MC_OFFSET_LIST 0x3000 -#define MC_OFFSET_SLICE 0x4000 -#define MC_OFFSET_MAIN 0x5000 - -#define MC_TOTAL_SIZE ((20+16)*SZ_1K) -#define MC_SWAP_SIZE (4*SZ_1K) -#define MODE_ERROR 0 -#define MODE_FULL 1 - -#define DFS_HIGH_THEASHOLD 3 - -#define INIT_FLAG_REG AV_SCRATCH_2 -#define HEAD_PADING_REG AV_SCRATCH_3 -#define UCODE_WATCHDOG_REG AV_SCRATCH_7 -#define LMEM_DUMP_ADR AV_SCRATCH_L -#define DEBUG_REG1 AV_SCRATCH_M -#define DEBUG_REG2 AV_SCRATCH_N -#define FRAME_COUNTER_REG AV_SCRATCH_I -#define RPM_CMD_REG AV_SCRATCH_A -#define H264_DECODE_SIZE AV_SCRATCH_E -#define H264_DECODE_MODE AV_SCRATCH_4 -#define H264_DECODE_SEQINFO AV_SCRATCH_5 -#define H264_AUX_ADR AV_SCRATCH_C -#define H264_AUX_DATA_SIZE AV_SCRATCH_H - -#define H264_DECODE_INFO M4_CONTROL_REG /* 0xc29 */ -#define DPB_STATUS_REG AV_SCRATCH_J -#define ERROR_STATUS_REG AV_SCRATCH_9 - /* - NAL_SEARCH_CTL: bit 0, enable itu_t35 - NAL_SEARCH_CTL: bit 1, enable mmu - */ -#define NAL_SEARCH_CTL AV_SCRATCH_9 -#define MBY_MBX MB_MOTION_MODE /*0xc07*/ - -#define DECODE_MODE_SINGLE 0x0 -#define DECODE_MODE_MULTI_FRAMEBASE 0x1 -#define DECODE_MODE_MULTI_STREAMBASE 0x2 -#define DECODE_MODE_MULTI_DVBAL 0x3 -#define DECODE_MODE_MULTI_DVENL 0x4 -static DEFINE_MUTEX(vmh264_mutex); - - - -#ifdef MH264_USERDATA_ENABLE - -struct mh264_userdata_record_t { - struct userdata_meta_info_t meta_info; - u32 rec_start; - u32 rec_len; -}; - -struct mh264_ud_record_wait_node_t { - struct list_head list; - struct mh264_userdata_record_t ud_record; -}; -#define USERDATA_FIFO_NUM 256 -#define MAX_FREE_USERDATA_NODES 5 - -struct mh264_userdata_info_t { - struct mh264_userdata_record_t records[USERDATA_FIFO_NUM]; - u8 *data_buf; - u8 *data_buf_end; - u32 buf_len; - u32 read_index; - u32 write_index; - u32 last_wp; -}; - - -#endif - -struct vdec_h264_hw_s { - spinlock_t lock; - spinlock_t bufspec_lock; - int id; - struct platform_device *platform_dev; - unsigned long cma_alloc_addr; - /* struct page *collocate_cma_alloc_pages; */ - unsigned long collocate_cma_alloc_addr; - - u32 prefix_aux_size; - u32 suffix_aux_size; - void *aux_addr; - dma_addr_t aux_phy_addr; - - /* buffer for store all sei data */ - void *sei_data_buf; - u32 sei_data_len; - - /* buffer for storing one itu35 recored */ - void *sei_itu_data_buf; - u32 sei_itu_data_len; - - /* recycle buffer for user data storing all itu35 records */ - void *sei_user_data_buffer; - u32 sei_user_data_wp; -#ifdef MH264_USERDATA_ENABLE - struct work_struct user_data_ready_work; -#endif - struct StorablePicture *last_dec_picture; - - ulong lmem_addr; - dma_addr_t lmem_addr_remap; - - void *bmmu_box; -#ifdef H264_MMU - void *mmu_box; - void *frame_mmu_map_addr; - dma_addr_t frame_mmu_map_phy_addr; - u32 hevc_cur_buf_idx; - u32 losless_comp_body_size; - u32 losless_comp_body_size_sao; - u32 losless_comp_header_size; - u32 mc_buffer_size_u_v; - u32 mc_buffer_size_u_v_h; - u32 is_idr_frame; - u32 is_new_pic; - u32 frame_done; - u32 frame_busy; - unsigned long extif_addr; - int double_write_mode; - int mmu_enable; -#endif - - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - - int cur_pool; - struct vframe_s vfpool[VF_POOL_NUM][VF_POOL_SIZE]; - struct buffer_spec_s buffer_spec[BUFSPEC_POOL_SIZE]; - struct vframe_s switching_fense_vf; - struct h264_dpb_stru dpb; - u8 init_flag; - u8 first_sc_checked; - u8 has_i_frame; - u8 config_bufmgr_done; - u32 max_reference_size; - u32 decode_pic_count; - int start_search_pos; - u32 reg_iqidct_control; - u32 reg_vcop_ctrl_reg; - u32 reg_rv_ai_mb_count; - u32 vld_dec_control; - struct vframe_s vframe_dummy; - - unsigned char buffer_empty_flag; - - u32 frame_width; - u32 frame_height; - u32 frame_dur; - u32 frame_prog; - u32 frame_packing_type; - - struct vframe_chunk_s *chunk; - - u32 stat; - unsigned long buf_start; - u32 buf_offset; - u32 buf_size; - /* u32 ucode_map_start; */ - u32 pts_outside; - u32 sync_outside; - u32 vh264_ratio; - u32 vh264_rotation; - u32 use_idr_framerate; - - u32 seq_info; - u32 seq_info2; - u32 video_signal_from_vui; /*to do .. */ - u32 timing_info_present_flag; - u32 fixed_frame_rate_flag; - u32 bitstream_restriction_flag; - u32 num_reorder_frames; - u32 max_dec_frame_buffering; - u32 iframe_count; - u32 aspect_ratio_info; - u32 num_units_in_tick; - u32 time_scale; - u32 h264_ar; - bool h264_first_valid_pts_ready; - u32 h264pts1; - u32 h264pts2; - u32 pts_duration; - u32 h264_pts_count; - u32 duration_from_pts_done; - u32 pts_unstable; - u32 unstable_pts; - u32 last_checkout_pts; - u32 max_refer_buf; - - s32 vh264_stream_switching_state; - struct vframe_s *p_last_vf; - u32 last_pts; - u32 last_pts_remainder; - u32 last_duration; - u32 last_mb_width, last_mb_height; - bool check_pts_discontinue; - bool pts_discontinue; - u32 wait_buffer_counter; - u32 first_offset; - u32 first_pts; - u64 first_pts64; - bool first_pts_cached; - -#if 0 - void *sei_data_buffer; - dma_addr_t sei_data_buffer_phys; -#endif - - uint error_recovery_mode; - uint mb_total; - uint mb_width; - uint mb_height; - - uint i_only; - int skip_frame_count; - bool no_poc_reorder_flag; - bool send_error_frame_flag; - dma_addr_t mc_dma_handle; - void *mc_cpu_addr; - int vh264_reset; - - atomic_t vh264_active; - - struct dec_sysinfo vh264_amstream_dec_info; - - int dec_result; - struct work_struct work; - struct work_struct notify_work; - - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - - struct timer_list check_timer; - - /**/ - unsigned int last_frame_time; - u32 vf_pre_count; - u32 vf_get_count; - u32 vf_put_count; - - /* timeout handle */ - unsigned long int start_process_time; - unsigned int last_mby_mbx; - unsigned int last_vld_level; - unsigned int decode_timeout_count; - unsigned int timeout_num; - unsigned int search_dataempty_num; - unsigned int decode_timeout_num; - unsigned int decode_dataempty_num; - unsigned int buffer_empty_recover_num; - - unsigned get_data_count; - unsigned get_data_start_time; - /**/ - - /*log*/ - unsigned int packet_write_success_count; - unsigned int packet_write_EAGAIN_count; - unsigned int packet_write_ENOMEM_count; - unsigned int packet_write_EFAULT_count; - unsigned int total_read_size_pre; - unsigned int total_read_size; - unsigned int frame_count_pre; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - u8 switch_dvlayer_flag; - u8 got_valid_nal; -#endif - u8 eos; - u8 data_flag; - u32 no_error_count; - u32 no_error_i_count; - /* - NODISP_FLAG - */ - u8 dec_flag; - - u32 ucode_pause_pos; - - u8 reset_bufmgr_flag; - u32 reset_bufmgr_count; - u32 cfg_param1; - u32 cfg_param2; - u32 cfg_param3; - u32 cfg_param4; - int valve_count; - u8 next_again_flag; - u32 pre_parser_wr_ptr; - struct firmware_s *fw; - struct firmware_s *fw_mmu; -#ifdef MH264_USERDATA_ENABLE - /*user data*/ - struct mutex userdata_mutex; - struct mh264_userdata_info_t userdata_info; - struct mh264_userdata_record_t ud_record; - int wait_for_udr_send; -#endif - u32 no_mem_count; - u32 canvas_mode; - bool is_used_v4l; - void *v4l2_ctx; - wait_queue_head_t wait_q; - u32 reg_g_status; - struct mutex chunks_mutex; - int need_cache_size; - u64 sc_start_time; - u8 frmbase_cont_flag; - struct vframe_qos_s vframe_qos; - int frameinfo_enable; -}; - -static u32 again_threshold = 0x40; - -static void dump_bufspec(struct vdec_h264_hw_s *hw, - const char *caller); -static void h264_reconfig(struct vdec_h264_hw_s *hw); -static void h264_reset_bufmgr(struct vdec_s *vdec); -static void vh264_local_init(struct vdec_h264_hw_s *hw); -static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw); -static int vh264_stop(struct vdec_h264_hw_s *hw); -static s32 vh264_init(struct vdec_h264_hw_s *hw); -static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, - u32 index); -static void release_aux_data(struct vdec_h264_hw_s *hw, - int buf_spec_num); -#ifdef ERROR_HANDLE_TEST -static void h264_clear_dpb(struct vdec_h264_hw_s *hw); -#endif - -#define H265_PUT_SAO_4K_SET 0x03 -#define H265_ABORT_SAO_4K_SET 0x04 -#define H265_ABORT_SAO_4K_SET_DONE 0x05 - -#define SYS_COMMAND HEVC_ASSIST_SCRATCH_0 -#define H265_CHECK_AXI_INFO_BASE HEVC_ASSIST_SCRATCH_8 -#define H265_SAO_4K_SET_BASE HEVC_ASSIST_SCRATCH_9 -#define H265_SAO_4K_SET_COUNT HEVC_ASSIST_SCRATCH_A -#define HEVC_SAO_MMU_STATUS 0x3639 -#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 - - -#define HEVC_CM_HEADER_START_ADDR 0x3628 -#define HEVC_CM_BODY_START_ADDR 0x3626 -#define HEVC_CM_BODY_LENGTH 0x3627 -#define HEVC_CM_HEADER_LENGTH 0x3629 -#define HEVC_CM_HEADER_OFFSET 0x362b -#define HEVC_SAO_CTRL9 0x362d -#define HEVCD_MPP_DECOMP_CTL3 0x34c4 -#define HEVCD_MPP_VDEC_MCR_CTL 0x34c8 -#define HEVC_DBLK_CFGB 0x350b -#define HEVC_CM_CORE_STATUS 0x3640 -#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 - -#define H265_DW_NO_SCALE -#define H265_MEM_MAP_MODE 0 /*0:linear 1:32x32 2:64x32*/ -#define H265_LOSLESS_COMPRESS_MODE -#define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) - -/* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ -static u32 mem_map_mode = H265_MEM_MAP_MODE; - -#define MAX_SIZE_8K (8192 * 4608) -#define MAX_SIZE_4K (4096 * 2304) - -static int is_oversize(int w, int h) -{ - int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? - MAX_SIZE_8K : MAX_SIZE_4K; - - if (w < 0 || h < 0) - return true; - - if (h != 0 && (w > max / h)) - return true; - - return false; -} - -static int compute_losless_comp_body_size(int width, - int height, int bit_depth_10); -static int compute_losless_comp_header_size(int width, int height); - -static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx, - int pic_width, int pic_height, u16 bit_depth, - unsigned int *mmu_index_adr) { - int cur_buf_idx; - int bit_depth_10 = (bit_depth != 0x00); - int picture_size; - u32 cur_mmu_4k_number; - - WRITE_VREG(CURR_CANVAS_CTRL, pic_idx<<24); - cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL)&0xff; - picture_size = compute_losless_comp_body_size(pic_width, - pic_height, bit_depth_10); - cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "alloc_mmu new_fb_idx %d picture_size %d cur_mmu_4k_number %d\n", - cur_buf_idx, picture_size, cur_mmu_4k_number); - - if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) { - pr_err("hevc_alloc_mmu cur_mmu_4k_number %d unsupport\n", - cur_mmu_4k_number); - return -1; - } - - return decoder_mmu_box_alloc_idx( - hw->mmu_box, - cur_buf_idx, - cur_mmu_4k_number, - mmu_index_adr); - -} - -static int compute_losless_comp_body_size(int width, - int height, int bit_depth_10) -{ - int width_x64; - int height_x32; - int bsize; - - width_x64 = width + 63; - width_x64 >>= 6; - - height_x32 = height + 31; - height_x32 >>= 5; - -#ifdef H264_MMU - bsize = (bit_depth_10 ? 4096 : 3264) * width_x64*height_x32; -#else - bsize = (bit_depth_10 ? 4096 : 3072) * width_x64*height_x32; -#endif - return bsize; -} - -static int compute_losless_comp_header_size(int width, int height) -{ - int width_x64; - int width_x128; - int height_x64; - int hsize; - - width_x64 = width + 63; - width_x64 >>= 6; - - width_x128 = width + 127; - width_x128 >>= 7; - - height_x64 = height + 63; - height_x64 >>= 6; - -#ifdef H264_MMU - hsize = 128*width_x64*height_x64; -#else - hsize = 32*width_x128*height_x64; -#endif - return hsize; -} - -static int get_double_write_ratio(struct vdec_h264_hw_s *hw) -{ - int ratio = 1; - int dw_mode = hw->double_write_mode; - if ((dw_mode == 2) || - (dw_mode == 3)) - ratio = 4; - else if (dw_mode == 4) - ratio = 2; - return ratio; -} - - -static int get_dw_size(struct vdec_h264_hw_s *hw, u32 *pdw_buffer_size_u_v_h) -{ - int pic_width, pic_height; - int lcu_size = 16; - int dw_buf_size; - u32 dw_buffer_size_u_v; - u32 dw_buffer_size_u_v_h; - int dw_mode = hw->double_write_mode; - - pic_width = hw->frame_width; - pic_height = hw->frame_height; - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(hw); - int pic_height_dw = pic_height / - get_double_write_ratio(hw); - - int pic_width_lcu_dw = (pic_width_dw % lcu_size) ? - pic_width_dw / lcu_size + 1 : - pic_width_dw / lcu_size; - int pic_height_lcu_dw = (pic_height_dw % lcu_size) ? - pic_height_dw / lcu_size + 1 : - pic_height_dw / lcu_size; - int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; - - - dw_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; - dw_buffer_size_u_v_h = (dw_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - dw_buf_size = ((dw_buffer_size_u_v_h << 16) * 3); - *pdw_buffer_size_u_v_h = dw_buffer_size_u_v_h; - } else { - *pdw_buffer_size_u_v_h = 0; - dw_buf_size = 0; - } - - return dw_buf_size; -} - - -static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) -{ - int i, size; - u32 canvas_addr; - unsigned long maddr; - int num_buff = hw->dpb.mDPB.size; - int dw_size = 0; - u32 dw_buffer_size_u_v_h; - u32 blkmode = mem_map_mode; - int dw_mode = hw->double_write_mode; - - canvas_addr = ANC0_CANVAS_ADDR; - for (i = 0; i < num_buff; i++) - WRITE_VREG((canvas_addr + i), i | (i << 8) | (i << 16)); - - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); - size = hw->losless_comp_body_size + hw->losless_comp_header_size; - - - dw_size = get_dw_size(hw, &dw_buffer_size_u_v_h); - size += dw_size; - if (size > 0) - size += 0x10000; - - dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, - "dw_buffer_size_u_v_h = %d, dw_size = 0x%x, size = 0x%x\n", - dw_buffer_size_u_v_h, dw_size, size); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, - "body_size = %d, header_size = %d, body_size_sao = %d\n", - hw->losless_comp_body_size, - hw->losless_comp_header_size, - hw->losless_comp_body_size_sao); - - for (i = 0; i < num_buff; i++) { - if (!restore) { - if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, - HEADER_BUFFER_IDX(i), size, - DRIVER_HEADER_NAME, &maddr) < 0) { - dpb_print(DECODE_ID(hw), 0, - "%s malloc compress header failed %d\n", - DRIVER_HEADER_NAME, i); - return; - } - } else - maddr = hw->buffer_spec[i].alloc_header_addr; - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, maddr >> 5); - hw->buffer_spec[i].alloc_header_addr = maddr; - dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, - "%s : canvas: %d axiaddr:%x size 0x%x\n", - __func__, i, (u32)maddr, size); - - if (dw_mode) { - u32 addr; - int canvas_w; - int canvas_h; - - canvas_w = hw->frame_width / - get_double_write_ratio(hw); - canvas_h = hw->frame_height / - get_double_write_ratio(hw); - - if (mem_map_mode == 0) - canvas_w = ALIGN(canvas_w, 32); - else - canvas_w = ALIGN(canvas_w, 64); - canvas_h = ALIGN(canvas_h, 32); - - hw->buffer_spec[i].dw_y_adr = - maddr + hw->losless_comp_header_size; - - hw->buffer_spec[i].dw_y_adr = - ((hw->buffer_spec[i].dw_y_adr + 0xffff) >> 16) - << 16; - hw->buffer_spec[i].dw_u_v_adr = - hw->buffer_spec[i].dw_y_adr - + (dw_buffer_size_u_v_h << 16) * 2; - - - hw->buffer_spec[i].buf_adr - = hw->buffer_spec[i].dw_y_adr; - addr = hw->buffer_spec[i].buf_adr; - - - dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, - "dw_y_adr = 0x%x, dw_u_v_adr = 0x%x, y_addr = 0x%x, u_addr = 0x%x, v_addr = 0x%x, width = %d, height = %d\n", - hw->buffer_spec[i].dw_y_adr, - hw->buffer_spec[i].dw_u_v_adr, - hw->buffer_spec[i].y_addr, - hw->buffer_spec[i].u_addr, - hw->buffer_spec[i].v_addr, - canvas_w, - canvas_h); - - hw->buffer_spec[i].canvas_config[0].phy_addr = - hw->buffer_spec[i].dw_y_adr; - hw->buffer_spec[i].canvas_config[0].width = canvas_w; - hw->buffer_spec[i].canvas_config[0].height = canvas_h; - hw->buffer_spec[i].canvas_config[0].block_mode = - blkmode; - hw->buffer_spec[i].canvas_config[0].endian = 7; - - hw->buffer_spec[i].canvas_config[1].phy_addr = - hw->buffer_spec[i].dw_u_v_adr; - hw->buffer_spec[i].canvas_config[1].width = canvas_w; - hw->buffer_spec[i].canvas_config[1].height = canvas_h; - hw->buffer_spec[i].canvas_config[1].block_mode = - blkmode; - hw->buffer_spec[i].canvas_config[1].endian = 7; - } - } - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); - - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1); - for (i = 0; i < 32; i++) - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); - return; -} -static void hevc_mcr_config_mc_ref(struct vdec_h264_hw_s *hw) -{ - u32 i; - u32 ref_canv; - struct Slice *pSlice = &(hw->dpb.mSlice); - /*REFLIST[0]*/ - for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) { - struct StorablePicture *ref = pSlice->listX[0][i]; - if (ref == NULL) - return; - WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24); - ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (ref->buf_spec_num & 0x3f) << 8); - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, ref_canv); - } - /*REFLIST[1]*/ - for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) { - struct StorablePicture *ref = pSlice->listX[1][i]; - if (ref == NULL) - return; - WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24); - ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (ref->buf_spec_num & 0x3f) << 8); - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, ref_canv); - } - return; -} - -static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) -{ - u32 rdata32; - u32 rdata32_2; - u32 slice_type; - struct StorablePicture *ref; - struct Slice *pSlice; - slice_type = hw->dpb.mSlice.slice_type; - pSlice = &(hw->dpb.mSlice); - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); - if (slice_type == I_SLICE) { - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); - return; - } - if (slice_type == B_SLICE) { - ref = pSlice->listX[0][0]; - if (ref == NULL) - return; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - ((ref->buf_spec_num & 0x3f) << 8)); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - ref = pSlice->listX[1][0]; - if (ref == NULL) - return; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - ((ref->buf_spec_num & 0x3f) << 8)); - rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32_2 = rdata32_2 & 0xffff; - rdata32_2 = rdata32_2 | (rdata32_2 << 16); - if (rdata32 == rdata32_2) { - ref = pSlice->listX[1][1]; - if (ref == NULL) - return; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - ((ref->buf_spec_num & 0x3f) << 8)); - rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32_2 = rdata32_2 & 0xffff; - rdata32_2 = rdata32_2 | (rdata32_2 << 16); - } - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); - } else { /*P-PIC*/ - ref = pSlice->listX[0][0]; - if (ref == NULL) - return; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - ((ref->buf_spec_num & 0x3f) << 8)); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - ref = pSlice->listX[0][1]; - if (ref == NULL) - return; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - ((ref->buf_spec_num & 0x3f) << 8)); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - } - WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); - return; -} - - -static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, - u32 width, u32 height) { - u32 data32; - u32 lcu_x_num, lcu_y_num; - u32 lcu_total; - u32 mc_buffer_size_u_v; - u32 mc_buffer_size_u_v_h; - int dw_mode = hw->double_write_mode; - - lcu_x_num = (width + 15) >> 4; - lcu_y_num = (height + 15) >> 4; - lcu_total = lcu_x_num * lcu_y_num; - - hw->mc_buffer_size_u_v = mc_buffer_size_u_v = lcu_total*16*16/2; - hw->mc_buffer_size_u_v_h = - mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff)>>16; - - hw->losless_comp_body_size = 0; - - hw->losless_comp_body_size_sao = - compute_losless_comp_body_size(width, height, 0); - hw->losless_comp_header_size = - compute_losless_comp_header_size(width, height); - - WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1); /*sw reset ipp10b_top*/ - WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x0); /*sw reset ipp10b_top*/ - - /* setup lcu_size = 16*/ - WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 16); /*set lcu size = 16*/ - /*pic_width/pic_height*/ - WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG, - (height & 0xffff) << 16 | (width & 0xffff)); - /* bitdepth_luma = 8*/ - /* bitdepth_chroma = 8*/ - WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x0);/*set bit-depth 8 */ - -#ifdef H265_LOSLESS_COMPRESS_MODE - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0); -#else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - data32 |= (mem_map_mode << 4); - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); - - WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, - (0x80 << 20) | (0x80 << 10) | (0xff)); - - WRITE_VREG(HEVCD_MPP_VDEC_MCR_CTL, 0x1 | (0x1 << 4)); - - /*comfig vdec:h264:mdec to use hevc mcr/mcrcc/decomp*/ - WRITE_VREG(MDEC_PIC_DC_MUX_CTRL, - READ_VREG(MDEC_PIC_DC_MUX_CTRL) | 0x1 << 31); - /* ipp_enable*/ - WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1 << 1); - - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(HEVC_DBLK_CFG1, 0x2); // set ctusize==16 - WRITE_VREG(HEVC_DBLK_CFG2, ((height & 0xffff)<<16) | (width & 0xffff)); - if (dw_mode) - WRITE_VREG(HEVC_DBLK_CFGB, 0x40405703); - else - WRITE_VREG(HEVC_DBLK_CFGB, 0x40405503); - } - - data32 = READ_VREG(HEVC_SAO_CTRL0); - data32 &= (~0xf); - data32 |= 0x4; - WRITE_VREG(HEVC_SAO_CTRL0, data32); - WRITE_VREG(HEVC_SAO_PIC_SIZE, (height & 0xffff) << 16 | - (width & 0xffff)); - data32 = ((lcu_x_num-1) | (lcu_y_num-1) << 16); - - WRITE_VREG(HEVC_SAO_PIC_SIZE_LCU, data32); - data32 = (lcu_x_num | lcu_y_num << 16); - WRITE_VREG(HEVC_SAO_TILE_SIZE_LCU, data32); - data32 = (mc_buffer_size_u_v_h << 16) << 1; - WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); - data32 = (mc_buffer_size_u_v_h << 16); - WRITE_VREG(HEVC_SAO_C_LENGTH, data32); - - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - data32 &= (~0xff0); - data32 |= endian; /* Big-Endian per 64-bit */ - - if (hw->mmu_enable && dw_mode) - data32 |= ((mem_map_mode << 12)); - else - data32 |= ((mem_map_mode << 12)|2); - - WRITE_VREG(HEVC_SAO_CTRL1, data32); - -#ifdef H265_DW_NO_SCALE - WRITE_VREG(HEVC_SAO_CTRL5, READ_VREG(HEVC_SAO_CTRL5) & ~(0xff << 16)); - if (hw->mmu_enable && dw_mode) { - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 &= (~(0xff << 16)); - if (dw_mode == 2 || - dw_mode == 3) - data32 |= (0xff<<16); - else if (dw_mode == 4) - data32 |= (0x33<<16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - - -#endif - - -#ifdef H265_LOSLESS_COMPRESS_MODE - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 |= (1<<9); /*8-bit smem-mode*/ - WRITE_VREG(HEVC_SAO_CTRL5, data32); - - WRITE_VREG(HEVC_CM_BODY_LENGTH, hw->losless_comp_body_size_sao); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, hw->losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, hw->losless_comp_header_size); -#endif - -#ifdef H265_LOSLESS_COMPRESS_MODE - WRITE_VREG(HEVC_SAO_CTRL9, READ_VREG(HEVC_SAO_CTRL9) | (0x1 << 1)); - WRITE_VREG(HEVC_SAO_CTRL5, READ_VREG(HEVC_SAO_CTRL5) | (0x1 << 10)); -#endif - - WRITE_VREG(HEVC_SAO_CTRL9, READ_VREG(HEVC_SAO_CTRL9) | 0x1 << 7); - - memset(hw->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); - - WRITE_VREG(MDEC_EXTIF_CFG0, hw->extif_addr); - WRITE_VREG(MDEC_EXTIF_CFG1, 0x80000000); - return; -} - -static void hevc_sao_set_slice_type(struct vdec_h264_hw_s *hw, - u32 is_new_pic, u32 is_idr) -{ - hw->is_new_pic = is_new_pic; - hw->is_idr_frame = is_idr; - return; -} - -static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, - struct StorablePicture *pic) { - u32 mc_y_adr; - u32 mc_u_v_adr; - u32 dw_y_adr; - u32 dw_u_v_adr; - u32 canvas_addr; - int ret; - int dw_mode = hw->double_write_mode; - if (hw->is_new_pic != 1) - return; - - if (hw->is_idr_frame) { - /* William TBD */ - memset(hw->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); - } - - WRITE_VREG(CURR_CANVAS_CTRL, pic->buf_spec_num << 24); - canvas_addr = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x0 << 1) | - (0x0 << 2) | ((canvas_addr & 0xff) << 8)); - mc_y_adr = READ_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA) << 5; - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x0 << 1) | - (0x0 << 2) | (((canvas_addr >> 8) & 0xff) << 8)); - mc_u_v_adr = READ_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA) << 5; - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); - - - if (dw_mode) { - dw_y_adr = hw->buffer_spec[pic->buf_spec_num].dw_y_adr; - dw_u_v_adr = hw->buffer_spec[pic->buf_spec_num].dw_u_v_adr; - } else { - dw_y_adr = 0; - dw_u_v_adr = 0; - } -#ifdef H265_LOSLESS_COMPRESS_MODE - if (dw_mode) - WRITE_VREG(HEVC_SAO_Y_START_ADDR, dw_y_adr); - WRITE_VREG(HEVC_CM_BODY_START_ADDR, mc_y_adr); -#ifdef H264_MMU - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, mc_y_adr); -#else - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, - (mc_y_adr + hw->losless_comp_body_size)); -#endif -#else - WRITE_VREG(HEVC_SAO_Y_START_ADDR, mc_y_adr); -#endif - -#ifndef H265_LOSLESS_COMPRESS_MODE - WRITE_VREG(HEVC_SAO_C_START_ADDR, mc_u_v_adr); -#else - if (dw_mode) - WRITE_VREG(HEVC_SAO_C_START_ADDR, dw_u_v_adr); -#endif - -#ifndef LOSLESS_COMPRESS_MODE - if (dw_mode) { - WRITE_VREG(HEVC_SAO_Y_WPTR, mc_y_adr); - WRITE_VREG(HEVC_SAO_C_WPTR, mc_u_v_adr); - } -#else - WRITE_VREG(HEVC_SAO_Y_WPTR, dw_y_adr); - WRITE_VREG(HEVC_SAO_C_WPTR, dw_u_v_adr); -#endif - - ret = hevc_alloc_mmu(hw, pic->buf_spec_num, - (hw->mb_width << 4), (hw->mb_height << 4), 0x0, - hw->frame_mmu_map_addr); - if (ret != 0) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, "can't alloc need mmu1,idx %d ret =%d\n", - pic->buf_spec_num, - ret); - return; - } - - /*Reset SAO + Enable SAO slice_start*/ - if (hw->mmu_enable && get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) - WRITE_VREG(HEVC_DBLK_CFG0, 0x1); // reset buffer32x4 in lpf for every picture - WRITE_VREG(HEVC_SAO_INT_STATUS, - READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 28); - WRITE_VREG(HEVC_SAO_INT_STATUS, - READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 31); - /*pr_info("hevc_sao_set_pic_buffer:mc_y_adr: %x\n", mc_y_adr);*/ - /*Send coommand to hevc-code to supply 4k buffers to sao*/ - - if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(H265_SAO_4K_SET_BASE, (u32)hw->frame_mmu_map_phy_addr); - WRITE_VREG(H265_SAO_4K_SET_COUNT, MAX_FRAME_4K_NUM); - } else - WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, (u32)hw->frame_mmu_map_phy_addr); - WRITE_VREG(SYS_COMMAND, H265_PUT_SAO_4K_SET); - hw->frame_busy = 1; - return; -} - - -static void hevc_set_unused_4k_buff_idx(struct vdec_h264_hw_s *hw, - u32 buf_spec_num) { - WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24); - hw->hevc_cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL)&0xff; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, " %s cur_buf_idx %d buf_spec_num %d\n", - __func__, hw->hevc_cur_buf_idx, buf_spec_num); - return; -} - - -static void hevc_set_frame_done(struct vdec_h264_hw_s *hw) -{ - ulong timeout = jiffies + HZ; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, "hevc_frame_done...set\n"); - while ((READ_VREG(HEVC_SAO_INT_STATUS) & 0x1) == 0) { - if (time_after(jiffies, timeout)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, " %s..timeout!\n", __func__); - break; - } - } - timeout = jiffies + HZ; - while (READ_VREG(HEVC_CM_CORE_STATUS) & 0x1) { - if (time_after(jiffies, timeout)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, " %s cm_core..timeout!\n", __func__); - break; - } - } - WRITE_VREG(HEVC_SAO_INT_STATUS, 0x1); - hw->frame_done = 1; - return; -} - -static void release_cur_decoding_buf(struct vdec_h264_hw_s *hw) -{ - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - if (p_H264_Dpb->mVideo.dec_picture) { - release_picture(p_H264_Dpb, - p_H264_Dpb->mVideo.dec_picture); - p_H264_Dpb->mVideo.dec_picture->data_flag &= ~ERROR_FLAG; - p_H264_Dpb->mVideo.dec_picture = NULL; - if (hw->mmu_enable) - hevc_set_frame_done(hw); - } -} - -static void hevc_sao_wait_done(struct vdec_h264_hw_s *hw) -{ - ulong timeout = jiffies + HZ; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, "hevc_sao_wait_done...start\n"); - while ((READ_VREG(HEVC_SAO_INT_STATUS) >> 31)) { - if (time_after(jiffies, timeout)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "hevc_sao_wait_done...wait timeout!\n"); - break; - } - } - timeout = jiffies + HZ; - if ((hw->frame_busy == 1) && (hw->frame_done == 1) ) { - if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(SYS_COMMAND, H265_ABORT_SAO_4K_SET); - while ((READ_VREG(SYS_COMMAND) & 0xff) != - H265_ABORT_SAO_4K_SET_DONE) { - if (time_after(jiffies, timeout)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "wait h265_abort_sao_4k_set_done timeout!\n"); - break; - } - } - } - amhevc_stop(); - hw->frame_busy = 0; - hw->frame_done = 0; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "sao wait done ,hevc stop!\n"); - } - return; -} -static void buf_spec_init(struct vdec_h264_hw_s *hw) -{ - int i; - unsigned long flags; - spin_lock_irqsave(&hw->bufspec_lock, flags); - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - hw->buffer_spec[i].used = -1; - hw->buffer_spec[i].canvas_pos = -1; - } - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - spin_unlock_irqrestore(&hw->bufspec_lock, flags); -} - -/*is active in buf management */ -static unsigned char is_buf_spec_in_use(struct vdec_h264_hw_s *hw, - int buf_spec_num) -{ - unsigned char ret = 0; - if (hw->buffer_spec[buf_spec_num].used == 1 || - hw->buffer_spec[buf_spec_num].used == 2 || - hw->buffer_spec[buf_spec_num].used == 3 || - hw->buffer_spec[buf_spec_num].used == 5) - ret = 1; - return ret; -} - -static unsigned char is_buf_spec_in_disp_q(struct vdec_h264_hw_s *hw, - int buf_spec_num) -{ - unsigned char ret = 0; - if (hw->buffer_spec[buf_spec_num].used == 2 || - hw->buffer_spec[buf_spec_num].used == 3 || - hw->buffer_spec[buf_spec_num].used == 5) - ret = 1; - return ret; -} - -static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) -{ - if (hw->mmu_enable) { - if (hw->buffer_spec[i].alloc_header_addr) - return 0; - else - return -1; - } else { - - int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); - int addr; -#ifdef VDEC_DW - int orig_buf_size; - orig_buf_size = buf_size; - if (IS_VDEC_DW(hw) == 1) - buf_size += (hw->mb_total << 7) + (hw->mb_total << 6); - else if (IS_VDEC_DW(hw) == 2) - buf_size += (hw->mb_total << 6) + (hw->mb_total << 6); -#endif - if (hw->buffer_spec[i].cma_alloc_addr) - return 0; - - if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, i, - PAGE_ALIGN(buf_size), DRIVER_NAME, - &hw->buffer_spec[i].cma_alloc_addr) < 0) { - hw->buffer_spec[i].cma_alloc_addr = 0; - if (hw->no_mem_count++ > 3) { - hw->stat |= DECODER_FATAL_ERROR_NO_MEM; - hw->reset_bufmgr_flag = 1; - } - dpb_print(DECODE_ID(hw), 0, - "%s, fail to alloc buf for bufspec%d, try later\n", - __func__, i - ); - return -1; - } else { - hw->no_mem_count = 0; - hw->stat &= ~DECODER_FATAL_ERROR_NO_MEM; - } - - hw->buffer_spec[i].buf_adr = - hw->buffer_spec[i].cma_alloc_addr; - addr = hw->buffer_spec[i].buf_adr; - - - hw->buffer_spec[i].y_addr = addr; - addr += hw->mb_total << 8; - hw->buffer_spec[i].u_addr = addr; - hw->buffer_spec[i].v_addr = addr; - addr += hw->mb_total << 7; - - hw->buffer_spec[i].canvas_config[0].phy_addr = - hw->buffer_spec[i].y_addr; - hw->buffer_spec[i].canvas_config[0].width = - hw->mb_width << 4; - hw->buffer_spec[i].canvas_config[0].height = - hw->mb_height << 4; - hw->buffer_spec[i].canvas_config[0].block_mode = - hw->canvas_mode; - - hw->buffer_spec[i].canvas_config[1].phy_addr = - hw->buffer_spec[i].u_addr; - hw->buffer_spec[i].canvas_config[1].width = - hw->mb_width << 4; - hw->buffer_spec[i].canvas_config[1].height = - hw->mb_height << 3; - hw->buffer_spec[i].canvas_config[1].block_mode = - hw->canvas_mode; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s, alloc buf for bufspec%d\n", - __func__, i - ); -#ifdef VDEC_DW - - if (!IS_VDEC_DW(hw)) - return 0; - else if (IS_VDEC_DW(hw) == 1) { - addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size; - hw->buffer_spec[i].vdec_dw_y_addr = addr; - addr += hw->mb_total << 7; - hw->buffer_spec[i].vdec_dw_u_addr = addr; - hw->buffer_spec[i].vdec_dw_v_addr = addr; - addr += hw->mb_total << 6; - - hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr = - hw->buffer_spec[i].vdec_dw_y_addr; - hw->buffer_spec[i].vdec_dw_canvas_config[0].width = - hw->mb_width << 3; - hw->buffer_spec[i].vdec_dw_canvas_config[0].height = - hw->mb_height << 4; - hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode = - CANVAS_BLKMODE_32X32; - - hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr = - hw->buffer_spec[i].vdec_dw_u_addr; - hw->buffer_spec[i].vdec_dw_canvas_config[1].width = - hw->mb_width << 3; - hw->buffer_spec[i].vdec_dw_canvas_config[1].height = - hw->mb_height << 3; - hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode = - CANVAS_BLKMODE_32X32; - }else { - addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size; - hw->buffer_spec[i].vdec_dw_y_addr = addr; - addr += hw->mb_total << 6; - hw->buffer_spec[i].vdec_dw_u_addr = addr; - hw->buffer_spec[i].vdec_dw_v_addr = addr; - addr += hw->mb_total << 5; - - hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr = - hw->buffer_spec[i].vdec_dw_y_addr; - hw->buffer_spec[i].vdec_dw_canvas_config[0].width = - hw->mb_width << 3; - hw->buffer_spec[i].vdec_dw_canvas_config[0].height = - hw->mb_height << 3; - hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode = - CANVAS_BLKMODE_32X32; - - hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr = - hw->buffer_spec[i].vdec_dw_u_addr; - hw->buffer_spec[i].vdec_dw_canvas_config[1].width = - hw->mb_width << 3; - hw->buffer_spec[i].vdec_dw_canvas_config[1].height = - hw->mb_height << 2; - hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode = - CANVAS_BLKMODE_32X32; - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s, vdec_dw: alloc buf for bufspec%d\n", - __func__, i - ); -#endif - } - return 0; -} - -static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) -{ - int ret = 0; - - ret = ctx->dec_if->get_param(ctx->drv_handle, - GET_PARAM_FREE_FRAME_BUFFER, out); - if (ret) - pr_err("get frame buffer failed.\n"); - - return ret; -} - -static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) -{ - int ret = 0; - struct aml_vcodec_ctx *ctx = NULL; - struct buffer_spec_s *bs = &hw->buffer_spec[idx]; - struct canvas_config_s *y_canvas_cfg = NULL; - struct canvas_config_s *c_canvas_cfg = NULL; - struct vdec_fb *fb = NULL; - unsigned int y_addr, c_addr; - - if (IS_ERR_OR_NULL(hw->v4l2_ctx)) { - pr_err("the v4l context has err.\n"); - return -1; - } - - if (bs->cma_alloc_addr) - return 0; - - ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), buf size: %d\n", ctx->id, __func__, - (hw->mb_total << 8) + (hw->mb_total << 7)); - - ret = v4l_get_fb(hw->v4l2_ctx, &fb); - if (ret) { - pr_err("[%d] get fb fail.\n", ctx->id); - return ret; - } - - bs->cma_alloc_addr = (unsigned long)fb; - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), cma alloc addr: 0x%x\n", - ctx->id, __func__, bs->cma_alloc_addr); - - y_addr = virt_to_phys(fb->base_y.va); - c_addr = virt_to_phys(fb->base_c.va); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), y_addr: %x, va: %p\n", - ctx->id, __func__, y_addr, fb->base_y.va); - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), c_addr: %x, va: %p\n", - ctx->id, __func__, c_addr, fb->base_c.va); - - bs->y_addr = y_addr; - bs->u_addr = c_addr; - bs->v_addr = c_addr; - - y_canvas_cfg = &bs->canvas_config[0]; - c_canvas_cfg = &bs->canvas_config[1]; - - y_canvas_cfg->phy_addr = y_addr; - y_canvas_cfg->width = hw->mb_width << 4; - y_canvas_cfg->height = hw->mb_height << 4; - y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; - fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, - y_canvas_cfg->width,y_canvas_cfg->height); - - c_canvas_cfg->phy_addr = c_addr; - c_canvas_cfg->width = hw->mb_width << 4; - c_canvas_cfg->height = hw->mb_height << 3; - c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; - fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, - c_canvas_cfg->width, c_canvas_cfg->height); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx); - - return ret; -} - -static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i) -{ - int endian = 0; - int blkmode = ((hw->canvas_mode == CANVAS_BLKMODE_LINEAR) || - hw->is_used_v4l) ? CANVAS_BLKMODE_LINEAR : - CANVAS_BLKMODE_32X32; - if (blkmode == CANVAS_BLKMODE_LINEAR) - endian = 7; - - canvas_config_ex(hw->buffer_spec[i]. - y_canvas_index, - hw->buffer_spec[i].y_addr, - hw->mb_width << 4, - hw->mb_height << 4, - CANVAS_ADDR_NOWRAP, - blkmode, - endian); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, - (1 << 11) | /* canvas_blk32_wr */ - (blkmode << 10) | /* canvas_blk32*/ - (1 << 8) | /* canvas_index_wr*/ - (hw->buffer_spec[i].y_canvas_index << 0) /* canvas index*/ - ); - } - - canvas_config_ex(hw->buffer_spec[i]. - u_canvas_index, - hw->buffer_spec[i].u_addr, - hw->mb_width << 4, - hw->mb_height << 3, - CANVAS_ADDR_NOWRAP, - blkmode, - endian); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, - (1 << 11) | - (blkmode << 10) | - (1 << 8) | - (hw->buffer_spec[i].u_canvas_index << 0)); - } - WRITE_VREG(ANC0_CANVAS_ADDR + hw->buffer_spec[i].canvas_pos, - spec2canvas(&hw->buffer_spec[i])); - - -#ifdef VDEC_DW - if (!IS_VDEC_DW(hw)) - return; - else if (IS_VDEC_DW(hw) == 1) { - canvas_config_ex(hw->buffer_spec[i]. - vdec_dw_y_canvas_index, - hw->buffer_spec[i].vdec_dw_y_addr, - hw->mb_width << 3, - hw->mb_height << 4, - CANVAS_ADDR_NOWRAP, - blkmode, - hw->is_used_v4l ? 7 : 0); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, - (1 << 11) | - (blkmode << 10) | - (1 << 8) | - (hw->buffer_spec[i].vdec_dw_y_canvas_index << 0)); - } - canvas_config_ex(hw->buffer_spec[i]. - vdec_dw_u_canvas_index, - hw->buffer_spec[i].vdec_dw_u_addr, - hw->mb_width << 3, - hw->mb_height << 3, - CANVAS_ADDR_NOWRAP, - blkmode, - hw->is_used_v4l ? 7 : 0); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, - (1 << 11) | - (blkmode << 10) | - (1 << 8) | - (hw->buffer_spec[i].vdec_dw_u_canvas_index << 0)); - } - } else { - canvas_config_ex(hw->buffer_spec[i]. - vdec_dw_y_canvas_index, - hw->buffer_spec[i].vdec_dw_y_addr, - hw->mb_width << 3, - hw->mb_height << 3, - CANVAS_ADDR_NOWRAP, - blkmode, - hw->is_used_v4l ? 7 : 0); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, - (1 << 11) | - (blkmode << 10) | - (1 << 8) | - (hw->buffer_spec[i].vdec_dw_y_canvas_index << 0)); - } - - canvas_config_ex(hw->buffer_spec[i]. - vdec_dw_u_canvas_index, - hw->buffer_spec[i].vdec_dw_u_addr, - hw->mb_width << 3, - hw->mb_height << 2, - CANVAS_ADDR_NOWRAP, - blkmode, - hw->is_used_v4l ? 7 : 0); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, - (1 << 11) | - (blkmode << 10) | - (1 << 8) | - (hw->buffer_spec[i].vdec_dw_u_canvas_index << 0)); - } - } -#endif -} - -static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) -{ - u32 blkmode = mem_map_mode; - int canvas_w; - int canvas_h; - - canvas_w = hw->frame_width / - get_double_write_ratio(hw); - canvas_h = hw->frame_height / - get_double_write_ratio(hw); - - if (mem_map_mode == 0) - canvas_w = ALIGN(canvas_w, 32); - else - canvas_w = ALIGN(canvas_w, 64); - canvas_h = ALIGN(canvas_h, 32); - - canvas_config_ex(hw->buffer_spec[i]. - y_canvas_index, - hw->buffer_spec[i].dw_y_adr, - canvas_w, - canvas_h, - CANVAS_ADDR_NOWRAP, - blkmode, - 7); - - canvas_config_ex(hw->buffer_spec[i]. - u_canvas_index, - hw->buffer_spec[i].dw_u_v_adr, - canvas_w, - canvas_h, - CANVAS_ADDR_NOWRAP, - blkmode, - 7); -} - - -int get_free_buf_idx(struct vdec_s *vdec) -{ - int i; - unsigned long addr, flags; - int index = -1; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - int buf_total = BUFSPEC_POOL_SIZE; - spin_lock_irqsave(&hw->bufspec_lock, flags); - /*hw->start_search_pos = 0;*/ - for (i = hw->start_search_pos; i < buf_total; i++) { - if (hw->mmu_enable) - addr = hw->buffer_spec[i].alloc_header_addr; - else - addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->buffer_spec[i].used == 0 && addr) { - hw->buffer_spec[i].used = 1; - hw->start_search_pos = i+1; - index = i; - break; - } - } - if (index < 0) { - for (i = 0; i < hw->start_search_pos; i++) { - if (hw->mmu_enable) - addr = hw->buffer_spec[i].alloc_header_addr; - else - addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->buffer_spec[i].used == 0 && addr) { - hw->buffer_spec[i].used = 1; - hw->start_search_pos = i+1; - index = i; - break; - } - } - } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); - if (hw->start_search_pos >= buf_total) - hw->start_search_pos = 0; - dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, - "%s, buf_spec_num %d\n", __func__, index); - - if (index < 0) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s fail\n", __func__); - vmh264_dump_state(vdec); - } - - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - return index; -} - -int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num) -{ - /*u32 cur_buf_idx;*/ - unsigned long flags; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, - "%s buf_spec_num %d used %d\n", - __func__, buf_spec_num, - buf_spec_num > 0 ? hw->buffer_spec[buf_spec_num].used : 0); - if (buf_spec_num >= 0 && - buf_spec_num < BUFSPEC_POOL_SIZE - ) { - spin_lock_irqsave(&hw->bufspec_lock, flags); - hw->buffer_spec[buf_spec_num].used = 0; - spin_unlock_irqrestore(&hw->bufspec_lock, flags); - if (hw->mmu_enable) { - /*WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24); - cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL); - cur_buf_idx = cur_buf_idx&0xff;*/ - decoder_mmu_box_free_idx(hw->mmu_box, buf_spec_num); - } - release_aux_data(hw, buf_spec_num); - } - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - return 0; -} - -static void config_buf_specs(struct vdec_s *vdec) -{ - int i, j; - unsigned long flags; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - int mode = IS_VDEC_DW(hw) ? 2 : 1; - - spin_lock_irqsave(&hw->bufspec_lock, flags); - for (i = 0, j = 0; - j < hw->dpb.mDPB.size - && i < BUFSPEC_POOL_SIZE; - i++) { - int canvas; - if (hw->buffer_spec[i].used != -1) - continue; - if (vdec->parallel_dec == 1) { - if (hw->buffer_spec[i].y_canvas_index == -1) - hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - if (hw->buffer_spec[i].u_canvas_index == -1) { - hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index; - } -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) { - if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1) - hw->buffer_spec[i].vdec_dw_y_canvas_index = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) { - hw->buffer_spec[i].vdec_dw_u_canvas_index = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->buffer_spec[i].vdec_dw_v_canvas_index = - hw->buffer_spec[i].vdec_dw_u_canvas_index; - } - } -#endif - } else { - canvas = vdec->get_canvas(j * mode, 2); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL, - "config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i); -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) { - canvas = vdec->get_canvas(j * mode + 1, 2); - hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL, - "vdec_dw: config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i); - } -#endif - } - - hw->buffer_spec[i].used = 0; - hw->buffer_spec[i].canvas_pos = j; - - - j++; - } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); -} - -static void config_buf_specs_ex(struct vdec_s *vdec) -{ - int i, j; - unsigned long flags; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - int mode = IS_VDEC_DW(hw) ? 2 : 1; - - spin_lock_irqsave(&hw->bufspec_lock, flags); - for (i = 0, j = 0; - j < hw->dpb.mDPB.size - && i < BUFSPEC_POOL_SIZE; - i++) { - int canvas = 0; - if (hw->buffer_spec[i].used != -1) - continue; - if (vdec->parallel_dec == 1) { - if (hw->buffer_spec[i].y_canvas_index == -1) - hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - if (hw->buffer_spec[i].u_canvas_index == -1) { - hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index; - } -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) { - if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1) - hw->buffer_spec[i].vdec_dw_y_canvas_index = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) { - hw->buffer_spec[i].vdec_dw_u_canvas_index = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->buffer_spec[i].vdec_dw_v_canvas_index = - hw->buffer_spec[i].vdec_dw_u_canvas_index; - } - } -#endif - } else { - canvas = vdec->get_canvas(j* mode, 2); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); - - dpb_print(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL, - "config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i); -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) { - canvas = vdec->get_canvas(j*mode + 1, 2); - hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL, - "vdec_dw: config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i); - } -#endif - } - - hw->buffer_spec[i].used = 0; - hw->buffer_spec[i].alloc_header_addr = 0; - hw->buffer_spec[i].canvas_pos = j; - - j++; - } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); -} - - -static void dealloc_buf_specs(struct vdec_h264_hw_s *hw, - unsigned char release_all) -{ - int i; - unsigned long flags; - unsigned char dealloc_flag = 0; - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - if (hw->buffer_spec[i].used == 4 || - release_all) { - dealloc_flag = 1; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL, - "%s buf_spec_num %d\n", - __func__, i - ); - spin_lock_irqsave - (&hw->bufspec_lock, flags); - hw->buffer_spec[i].used = -1; - spin_unlock_irqrestore - (&hw->bufspec_lock, flags); - release_aux_data(hw, i); - - if (!hw->mmu_enable) { - if (hw->buffer_spec[i].cma_alloc_addr) { - if (!hw->is_used_v4l) { - decoder_bmmu_box_free_idx( - hw->bmmu_box, - i); - } - spin_lock_irqsave - (&hw->bufspec_lock, flags); - hw->buffer_spec[i].cma_alloc_addr = 0; - hw->buffer_spec[i].buf_adr = 0; - spin_unlock_irqrestore - (&hw->bufspec_lock, flags); - } - } else { - if (hw->buffer_spec[i].alloc_header_addr) { - decoder_mmu_box_free_idx( - hw->mmu_box, - i); - spin_lock_irqsave - (&hw->bufspec_lock, flags); - hw->buffer_spec[i]. - alloc_header_addr = 0; - hw->buffer_spec[i].buf_adr = 0; - spin_unlock_irqrestore - (&hw->bufspec_lock, flags); - } - } - } - } - if (dealloc_flag && - dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - return; -} - -unsigned char have_free_buf_spec(struct vdec_s *vdec) -{ - int i; - unsigned long addr; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - int canvas_pos_min = BUFSPEC_POOL_SIZE; - int index = -1; - int ret = 0; - int allocated_count = 0; - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - if (hw->mmu_enable) - addr = hw->buffer_spec[i].alloc_header_addr; - else - addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->buffer_spec[i].used == 0) { - - if (addr) - return 1; - if (hw->buffer_spec[i].canvas_pos < canvas_pos_min) { - canvas_pos_min = hw->buffer_spec[i].canvas_pos; - index = i; - } - } - if (addr) - allocated_count++; - } - if (index >= 0) { - mutex_lock(&vmh264_mutex); - dealloc_buf_specs(hw, 0); - if (max_alloc_buf_count == 0 || - allocated_count < max_alloc_buf_count) { - if (hw->is_used_v4l) { - if (alloc_one_buf_spec_from_queue(hw, index) >= 0) - ret = 1; - } else if (alloc_one_buf_spec(hw, index) >= 0) - ret = 1; - } - mutex_unlock(&vmh264_mutex); - } - return ret; -} - -static int get_buf_spec_by_canvas_pos(struct vdec_h264_hw_s *hw, - int canvas_pos) -{ - int i; - int j = 0; - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - if (hw->buffer_spec[i].canvas_pos >= 0) { - if (j == canvas_pos) - return i; - j++; - } - } - return -1; -} -static void update_vf_memhandle(struct vdec_h264_hw_s *hw, - struct vframe_s *vf, int index) -{ - if (index < 0) { - vf->mem_handle = NULL; - vf->mem_head_handle = NULL; - } else if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = - decoder_mmu_box_get_mem_handle( - hw->mmu_box, index); - vf->mem_head_handle = - decoder_bmmu_box_get_mem_handle( - hw->bmmu_box, HEADER_BUFFER_IDX(index)); - } else { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - hw->bmmu_box, VF_BUFFER_IDX(index)); - /* vf->mem_head_handle = - decoder_bmmu_box_get_mem_handle( - hw->bmmu_box, HEADER_BUFFER_IDX(index));*/ - } - return; -} -static int check_force_interlace(struct vdec_h264_hw_s *hw, - struct FrameStore *frame) -{ - int bForceInterlace = 0; - - if (frame->frame) { - if (frame->frame->coded_frame - && !frame->frame->frame_mbs_only_flag) { - if (frame->frame->structure == FRAME) - return 1; - } - } - - if ((dec_control & DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE) - && (hw->frame_width == 1920) - && (hw->frame_height >= 1080) - && (hw->frame_dur == 3203)) { - bForceInterlace = 1; - } else if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE) - && (hw->frame_width == 720) - && (hw->frame_height == 576) - && (hw->frame_dur == 3840)) { - bForceInterlace = 1; - } - - return bForceInterlace; -} - -static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame) -{ - struct vframe_qos_s *vframe_qos = &hw->vframe_qos; - if (frame->slice_type == I_SLICE) - vframe_qos->type = 1; - else if (frame->slice_type == P_SLICE) - vframe_qos->type = 2; - else if (frame->slice_type == B_SLICE) - vframe_qos->type = 3; - - vframe_qos->size = frame->frame_size; - vframe_qos->pts = frame->pts64; - - vframe_qos->max_mv = frame->max_mv; - vframe_qos->avg_mv = frame->avg_mv; - vframe_qos->min_mv = frame->min_mv; -/* - pr_info("mv: max:%d, avg:%d, min:%d\n", - vframe_qos->max_mv, - vframe_qos->avg_mv, - vframe_qos->min_mv); -*/ - - vframe_qos->max_qp = frame->max_qp; - vframe_qos->avg_qp = frame->avg_qp; - vframe_qos->min_qp = frame->min_qp; -/* - pr_info("qp: max:%d, avg:%d, min:%d\n", - vframe_qos->max_qp, - vframe_qos->avg_qp, - vframe_qos->min_qp); -*/ - - vframe_qos->max_skip = frame->max_skip; - vframe_qos->avg_skip = frame->avg_skip; - vframe_qos->min_skip = frame->min_skip; -/* - pr_info("skip: max:%d, avg:%d, min:%d\n", - vframe_qos->max_skip, - vframe_qos->avg_skip, - vframe_qos->min_skip); -*/ - vframe_qos->num++; - if (hw->frameinfo_enable) - vdec_fill_frame_info(vframe_qos, 1); -} - -static int is_iframe(struct FrameStore *frame) { - - if (frame->frame && frame->frame->slice_type == I_SLICE) { - return 1; - } - return 0; -} - - - -int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) -{ - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - struct vframe_s *vf = NULL; - int buffer_index = frame->buf_spec_num; - int vf_count = 1; - int i; - int bForceInterlace = 0; - - if (buffer_index < 0 || buffer_index >= BUFSPEC_POOL_SIZE) { - dpb_print(DECODE_ID(hw), 0, - "%s, buffer_index 0x%x is beyond range\n", - __func__, buffer_index); - return -1; - } - if (force_disp_bufspec_num & 0x100) { - /*recycle directly*/ - if (hw->buffer_spec[frame->buf_spec_num].used != 3 && - hw->buffer_spec[frame->buf_spec_num].used != 5) - set_frame_output_flag(&hw->dpb, frame->index); - - /*make pre_output not set*/ - return -1; - } - if (error_proc_policy & 0x1000) { - int error_skip_i_count = (error_skip_count >> 12) & 0xf; - int error_skip_frame_count = error_skip_count & 0xfff; - if (((hw->no_error_count < error_skip_frame_count) - && (error_skip_i_count == 0 || - hw->no_error_i_count < error_skip_i_count)) - && (!(frame->data_flag & I_FLAG))) - frame->data_flag |= ERROR_FLAG; - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, - "%s, buffer_index 0x%x frame_error %x poc %d hw error %x error_proc_policy %x\n", - __func__, buffer_index, frame->data_flag & ERROR_FLAG, - frame->poc, hw->data_flag & ERROR_FLAG, - error_proc_policy); - if (frame->frame == NULL && - ((frame->is_used == 1 && frame->top_field) - || (frame->is_used == 2 && frame->bottom_field))) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, - "%s Error frame_num %d used %d\n", - frame->frame_num, frame->is_used); - frame->data_flag |= ERROR_FLAG; - } - - if ((frame->data_flag & NODISP_FLAG) || - (frame->data_flag & NULL_FLAG) || - ((!hw->send_error_frame_flag) && - (frame->data_flag & ERROR_FLAG)) || - ((hw->i_only & 0x1) && - (!(frame->data_flag & I_FLAG))) - ) { - set_frame_output_flag(&hw->dpb, frame->index); - return 0; /*do not return -1, - otherwise flush_dpb() will not flush all dbp frames*/ - } - - display_frame_count[DECODE_ID(hw)]++; - - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL)) { - dpb_print(DECODE_ID(hw), 0, - "%s, fs[%d] poc %d, buf_spec_num %d\n", - __func__, frame->index, frame->poc, - frame->buf_spec_num); - print_pic_info(DECODE_ID(hw), "predis_frm", - frame->frame, -1); - print_pic_info(DECODE_ID(hw), "predis_top", - frame->top_field, -1); - print_pic_info(DECODE_ID(hw), "predis_bot", - frame->bottom_field, -1); - } - - if (!is_interlace(frame)) - vf_count = 1; - else - vf_count = 2; - bForceInterlace = check_force_interlace(hw, frame); - if (bForceInterlace) - vf_count = 2; - hw->buffer_spec[buffer_index].vf_ref = 0; - fill_frame_info(hw, frame); - for (i = 0; i < vf_count; i++) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || - vf == NULL) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; - } - vf->duration_pulldown = 0; - if (!(is_iframe(frame)) && hw->unstable_pts) { - vf->pts = 0; - vf->pts_us64 = 0; - vf->timestamp = 0; - vf->index = VF_INDEX(frame->index, buffer_index); - } else { - vf->pts = frame->pts; - vf->pts_us64 = frame->pts64; - vf->timestamp = frame->timestamp; - vf->index = VF_INDEX(frame->index, buffer_index); - } - - if (hw->is_used_v4l) { - vf->v4l_mem_handle - = hw->buffer_spec[buffer_index].cma_alloc_addr; - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l mem handle: 0x%x\n", - ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, - __func__, vf->v4l_mem_handle); - } - - if (hw->mmu_enable) { - if (hw->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { - /*head adr*/ - vf->compHeadAddr = - hw->buffer_spec[buffer_index].alloc_header_addr; - /*body adr*/ - vf->compBodyAddr = 0; - vf->canvas0Addr = vf->canvas1Addr = 0; - } - - vf->type = VIDTYPE_SCATTER; - - if (hw->double_write_mode) { - vf->type |= VIDTYPE_PROGRESSIVE - | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if (hw->double_write_mode == 3) - vf->type |= VIDTYPE_COMPRESS; - - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - hw->buffer_spec[buffer_index]. - canvas_config[0]; - vf->canvas0_config[1] = - hw->buffer_spec[buffer_index]. - canvas_config[1]; - - vf->canvas1_config[0] = - hw->buffer_spec[buffer_index]. - canvas_config[0]; - vf->canvas1_config[1] = - hw->buffer_spec[buffer_index]. - canvas_config[1]; - - } else { - vf->type |= - VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; - vf->canvas0Addr = vf->canvas1Addr = 0; - } - - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - - vf->compWidth = hw->frame_width; - vf->compHeight = hw->frame_height; - } else { - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; - - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&hw->buffer_spec[buffer_index]); -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) - vf->canvas0Addr = vf->canvas1Addr = - vdec_dw_spec2canvas(&hw->buffer_spec[buffer_index]); -#endif - - } - set_frame_info(hw, vf, buffer_index); - - if (hw->mmu_enable && hw->double_write_mode) { - vf->width = hw->frame_width / - get_double_write_ratio(hw); - vf->height = hw->frame_height / - get_double_write_ratio(hw); - } - - vf->flag = 0; - if (frame->data_flag & I_FLAG) - vf->flag |= VFRAME_FLAG_SYNCFRAME; - if (frame->data_flag & ERROR_FLAG) - vf->flag |= VFRAME_FLAG_ERROR_RECOVERY; - update_vf_memhandle(hw, vf, buffer_index); - hw->buffer_spec[buffer_index].used = 2; - hw->buffer_spec[buffer_index].vf_ref++; - - if (bForceInterlace || is_interlace(frame)) { - vf->type = - VIDTYPE_INTERLACE_FIRST | - VIDTYPE_VIU_NV21; - - if (bForceInterlace) { - vf->type |= (i == 0 ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM); - if (i == 1) { - vf->pts = 0; - vf->pts_us64 = 0; - } - } else if (frame->top_field->poc <= - frame->bottom_field->poc) /*top first*/ - vf->type |= (i == 0 ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM); - else - vf->type |= (i == 0 ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP); - vf->duration = vf->duration/2; - } - - if (i == 0) { - if (hw->mmu_enable) - decoder_do_frame_check(hw_to_vdec(hw), vf); - else - decoder_do_frame_check(hw_to_vdec(hw), vf); - } - - vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT); - vf->sar_width = vf->width; - vf->sar_height = vf->height; - - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->vf_pre_count++; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - - return 0; -} - -int notify_v4l_eos(struct vdec_s *vdec) -{ - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; - - if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; - } - - if (v4l_get_fb(hw->v4l2_ctx, &fb)) { - pr_err("[%d] get fb fail.\n", ctx->id); - return -1; - } - - vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = (unsigned long)fb; - vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; - - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - - pr_info("[%d] H264 EOS notify.\n", ctx->id); - } - - return 0; -} - -/****************** - * Hardware config - */ -char *slice_type_name[] = { - "P_SLICE ", - "B_SLICE ", - "I_SLICE ", - "SP_SLICE", - "SI_SLICE", -}; - -char *picture_structure_name[] = { - "FRAME", - "TOP_FIELD", - "BOTTOM_FIELD" -}; - -void print_pic_info(int decindex, const char *info, - struct StorablePicture *pic, - int slice_type) -{ - if (pic) - dpb_print(decindex, PRINT_FLAG_DEC_DETAIL, - "%s: %s (original %s), %s, mb_aff_frame_flag %d poc %d, pic_num %d, buf_spec_num %d data_flag 0x%x\n", - info, - picture_structure_name[pic->structure], - pic->coded_frame ? "Frame" : "Field", - (slice_type < 0) ? "" : slice_type_name[slice_type], - pic->mb_aff_frame_flag, - pic->poc, - pic->pic_num, - pic->buf_spec_num, - pic->data_flag); -} - -static void reset_process_time(struct vdec_h264_hw_s *hw) -{ - if (hw->start_process_time) { - unsigned process_time = - 1000 * (jiffies - hw->start_process_time) / HZ; - hw->start_process_time = 0; - if (process_time > max_process_time[DECODE_ID(hw)]) - max_process_time[DECODE_ID(hw)] = process_time; - } -} - -static void start_process_time(struct vdec_h264_hw_s *hw) -{ - hw->decode_timeout_count = 2; - hw->start_process_time = jiffies; -} - -static void config_aux_buf(struct vdec_h264_hw_s *hw) -{ - WRITE_VREG(H264_AUX_ADR, hw->aux_phy_addr); - WRITE_VREG(H264_AUX_DATA_SIZE, - ((hw->prefix_aux_size >> 4) << 16) | - (hw->suffix_aux_size >> 4) - ); -} - -/* -* dv_meta_flag: 1, dolby meta only; 2, not include dolby meta -*/ -static void set_aux_data(struct vdec_h264_hw_s *hw, - struct StorablePicture *pic, unsigned char suffix_flag, - unsigned char dv_meta_flag, struct vdec_h264_hw_s *hw_b) -{ - int i; - unsigned short *aux_adr; - unsigned size_reg_val = - READ_VREG(H264_AUX_DATA_SIZE); - unsigned aux_count = 0; - int aux_size = 0; - struct vdec_h264_hw_s *hw_buf = hw_b ? hw_b : hw; - if (pic == NULL || pic->buf_spec_num < 0 || pic->buf_spec_num >= BUFSPEC_POOL_SIZE - || (!is_buf_spec_in_use(hw, pic->buf_spec_num))) - return; - - if (suffix_flag) { - aux_adr = (unsigned short *) - (hw_buf->aux_addr + - hw_buf->prefix_aux_size); - aux_count = - ((size_reg_val & 0xffff) << 4) - >> 1; - aux_size = - hw_buf->suffix_aux_size; - } else { - aux_adr = - (unsigned short *)hw_buf->aux_addr; - aux_count = - ((size_reg_val >> 16) << 4) - >> 1; - aux_size = - hw_buf->prefix_aux_size; - } - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL)) { - dpb_print(DECODE_ID(hw), 0, - "%s:old size %d count %d,suf %d dv_flag %d\r\n", - __func__, AUX_DATA_SIZE(pic), - aux_count, suffix_flag, dv_meta_flag); - } - if (aux_size > 0 && aux_count > 0) { - int heads_size = 0; - int new_size; - char *new_buf; - for (i = 0; i < aux_count; i++) { - unsigned char tag = aux_adr[i] >> 8; - if (tag != 0 && tag != 0xff) { - if (dv_meta_flag == 0) - heads_size += 8; - else if (dv_meta_flag == 1 && tag == 0x1) - heads_size += 8; - else if (dv_meta_flag == 2 && tag != 0x1) - heads_size += 8; - } - } - new_size = AUX_DATA_SIZE(pic) + aux_count + heads_size; - new_buf = krealloc(AUX_DATA_BUF(pic), - new_size, - GFP_KERNEL); - if (new_buf) { - unsigned char valid_tag = 0; - unsigned char *h = - new_buf + - AUX_DATA_SIZE(pic); - unsigned char *p = h + 8; - int len = 0; - int padding_len = 0; - AUX_DATA_BUF(pic) = new_buf; - for (i = 0; i < aux_count; i += 4) { - int ii; - unsigned char tag = aux_adr[i + 3] >> 8; - if (tag != 0 && tag != 0xff) { - if (dv_meta_flag == 0) - valid_tag = 1; - else if (dv_meta_flag == 1 - && tag == 0x1) - valid_tag = 1; - else if (dv_meta_flag == 2 - && tag != 0x1) - valid_tag = 1; - else - valid_tag = 0; - if (valid_tag && len > 0) { - AUX_DATA_SIZE(pic) += - (len + 8); - h[0] = - (len >> 24) & 0xff; - h[1] = - (len >> 16) & 0xff; - h[2] = - (len >> 8) & 0xff; - h[3] = - (len >> 0) & 0xff; - h[6] = - (padding_len >> 8) - & 0xff; - h[7] = - (padding_len) & 0xff; - h += (len + 8); - p += 8; - len = 0; - padding_len = 0; - } - if (valid_tag) { - h[4] = tag; - h[5] = 0; - h[6] = 0; - h[7] = 0; - } - } - if (valid_tag) { - for (ii = 0; ii < 4; ii++) { - unsigned short aa = - aux_adr[i + 3 - - ii]; - *p = aa & 0xff; - p++; - len++; - /*if ((aa >> 8) == 0xff) - padding_len++;*/ - } - } - } - if (len > 0) { - AUX_DATA_SIZE(pic) += (len + 8); - h[0] = (len >> 24) & 0xff; - h[1] = (len >> 16) & 0xff; - h[2] = (len >> 8) & 0xff; - h[3] = (len >> 0) & 0xff; - h[6] = (padding_len >> 8) & 0xff; - h[7] = (padding_len) & 0xff; - } - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL)) { - dpb_print(DECODE_ID(hw), 0, - "aux: (size %d) suffix_flag %d\n", - AUX_DATA_SIZE(pic), suffix_flag); - for (i = 0; i < AUX_DATA_SIZE(pic); i++) { - dpb_print_cont(DECODE_ID(hw), 0, - "%02x ", AUX_DATA_BUF(pic)[i]); - if (((i + 1) & 0xf) == 0) - dpb_print_cont( - DECODE_ID(hw), - 0, "\n"); - } - dpb_print_cont(DECODE_ID(hw), - 0, "\n"); - } - - } - } - -} - -static void release_aux_data(struct vdec_h264_hw_s *hw, - int buf_spec_num) -{ - kfree(hw->buffer_spec[buf_spec_num].aux_data_buf); - hw->buffer_spec[buf_spec_num].aux_data_buf = NULL; - hw->buffer_spec[buf_spec_num].aux_data_size = 0; -} - -static void dump_aux_buf(struct vdec_h264_hw_s *hw) -{ - int i; - unsigned short *aux_adr = - (unsigned short *) - hw->aux_addr; - unsigned aux_size = - (READ_VREG(H264_AUX_DATA_SIZE) - >> 16) << 4; - - if (hw->prefix_aux_size > 0) { - dpb_print(DECODE_ID(hw), - 0, - "prefix aux: (size %d)\n", - aux_size); - for (i = 0; i < - (aux_size >> 1); i++) { - dpb_print_cont(DECODE_ID(hw), - 0, - "%04x ", - *(aux_adr + i)); - if (((i + 1) & 0xf) - == 0) - dpb_print_cont( - DECODE_ID(hw), - 0, "\n"); - } - } - if (hw->suffix_aux_size > 0) { - aux_adr = (unsigned short *) - (hw->aux_addr + - hw->prefix_aux_size); - aux_size = - (READ_VREG(H264_AUX_DATA_SIZE) & 0xffff) - << 4; - dpb_print(DECODE_ID(hw), - 0, - "suffix aux: (size %d)\n", - aux_size); - for (i = 0; i < - (aux_size >> 1); i++) { - dpb_print_cont(DECODE_ID(hw), - 0, - "%04x ", *(aux_adr + i)); - if (((i + 1) & 0xf) == 0) - dpb_print_cont(DECODE_ID(hw), - 0, "\n"); - } - } -} - -static void config_decode_mode(struct vdec_h264_hw_s *hw) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - struct vdec_s *vdec = hw_to_vdec(hw); -#endif - if (input_frame_based(hw_to_vdec(hw))) - WRITE_VREG(H264_DECODE_MODE, - DECODE_MODE_MULTI_FRAMEBASE); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec->slave) - WRITE_VREG(H264_DECODE_MODE, - (hw->got_valid_nal << 8) | - DECODE_MODE_MULTI_DVBAL); - else if (vdec->master) - WRITE_VREG(H264_DECODE_MODE, - (hw->got_valid_nal << 8) | - DECODE_MODE_MULTI_DVENL); -#endif - else - WRITE_VREG(H264_DECODE_MODE, - DECODE_MODE_MULTI_STREAMBASE); - WRITE_VREG(H264_DECODE_SEQINFO, - hw->seq_info2); - WRITE_VREG(HEAD_PADING_REG, 0); - - if (hw->init_flag == 0) - WRITE_VREG(INIT_FLAG_REG, 0); - else - WRITE_VREG(INIT_FLAG_REG, 1); -} -int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) -{ - /* static int count = 0; */ - int ret = 0; - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - struct Slice *pSlice = &(p_H264_Dpb->mSlice); - unsigned int colocate_adr_offset; - unsigned int val; - -#ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF - int colocate_buf_index; -#endif -#define H264_BUFFER_INFO_INDEX PMV3_X /* 0xc24 */ -#define H264_BUFFER_INFO_DATA PMV2_X /* 0xc22 */ -#define H264_CURRENT_POC_IDX_RESET LAST_SLICE_MV_ADDR /* 0xc30 */ -#define H264_CURRENT_POC LAST_MVY /* 0xc32 shared with conceal MV */ - -#define H264_CO_MB_WR_ADDR VLD_C38 /* 0xc38 */ -/* bit 31:30 -- L1[0] picture coding structure, - * 00 - top field, 01 - bottom field, - * 10 - frame, 11 - mbaff frame - * bit 29 - L1[0] top/bot for B field pciture , 0 - top, 1 - bot - * bit 28:0 h264_co_mb_mem_rd_addr[31:3] - * -- only used for B Picture Direct mode [2:0] will set to 3'b000 - */ -#define H264_CO_MB_RD_ADDR VLD_C39 /* 0xc39 */ - -/* bit 15 -- flush co_mb_data to DDR -- W-Only - * bit 14 -- h264_co_mb_mem_wr_addr write Enable -- W-Only - * bit 13 -- h264_co_mb_info_wr_ptr write Enable -- W-Only - * bit 9 -- soft_reset -- W-Only - * bit 8 -- upgent - * bit 7:2 -- h264_co_mb_mem_wr_addr - * bit 1:0 -- h264_co_mb_info_wr_ptr - */ -#define H264_CO_MB_RW_CTL VLD_C3D /* 0xc3d */ - - unsigned long canvas_adr; - unsigned int ref_reg_val; - unsigned int one_ref_cfg = 0; - int h264_buffer_info_data_write_count; - int i, j; - unsigned int colocate_wr_adr; - unsigned int colocate_rd_adr; - unsigned char use_direct_8x8; - int canvas_pos; - canvas_pos = hw->buffer_spec[pic->buf_spec_num].canvas_pos; - WRITE_VREG(H264_CURRENT_POC_IDX_RESET, 0); - WRITE_VREG(H264_CURRENT_POC, pic->frame_poc); - WRITE_VREG(H264_CURRENT_POC, pic->top_poc); - WRITE_VREG(H264_CURRENT_POC, pic->bottom_poc); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "%s: pic_num is %d, poc is %d (%d, %d, %d), buf_spec_num %d canvas_pos %d\n", - __func__, pic->pic_num, pic->poc, pic->frame_poc, - pic->top_poc, pic->bottom_poc, pic->buf_spec_num, - canvas_pos); - print_pic_info(DECODE_ID(hw), "cur", pic, pSlice->slice_type); - -#ifdef VDEC_DW - if (IS_VDEC_DW(hw) && pic->mb_aff_frame_flag) - WRITE_VREG(MDEC_DOUBLEW_CFG0, - ( READ_VREG(MDEC_DOUBLEW_CFG0) & (~(1 << 30)))); -#endif - WRITE_VREG(CURR_CANVAS_CTRL, canvas_pos << 24); - canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff; - - if (!hw->mmu_enable) { - WRITE_VREG(REC_CANVAS_ADDR, canvas_adr); - WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr); - WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr); -#ifdef VDEC_DW - WRITE_VREG(MDEC_DOUBLEW_CFG1, - (hw->buffer_spec[canvas_pos].vdec_dw_y_canvas_index - | (hw->buffer_spec[canvas_pos].vdec_dw_u_canvas_index << 8))); -#endif - } else - hevc_sao_set_pic_buffer(hw, pic); - - if (pic->mb_aff_frame_flag) - hw->buffer_spec[pic->buf_spec_num].info0 = 0xf4c0; - else if (pic->structure == TOP_FIELD) - hw->buffer_spec[pic->buf_spec_num].info0 = 0xf400; - else if (pic->structure == BOTTOM_FIELD) - hw->buffer_spec[pic->buf_spec_num].info0 = 0xf440; - else - hw->buffer_spec[pic->buf_spec_num].info0 = 0xf480; - - if (pic->bottom_poc < pic->top_poc) - hw->buffer_spec[pic->buf_spec_num].info0 |= 0x100; - - hw->buffer_spec[pic->buf_spec_num].info1 = pic->top_poc; - hw->buffer_spec[pic->buf_spec_num].info2 = pic->bottom_poc; - WRITE_VREG(H264_BUFFER_INFO_INDEX, 16); - - for (j = 0; j < hw->dpb.mDPB.size; j++) { - int long_term_flag; - i = get_buf_spec_by_canvas_pos(hw, j); - if (i < 0) - break; - long_term_flag = - get_long_term_flag_by_buf_spec_num(p_H264_Dpb, i); - if (long_term_flag > 0) { - if (long_term_flag & 0x1) - hw->buffer_spec[i].info0 |= (1 << 4); - else - hw->buffer_spec[i].info0 &= ~(1 << 4); - - if (long_term_flag & 0x2) - hw->buffer_spec[i].info0 |= (1 << 5); - else - hw->buffer_spec[i].info0 &= ~(1 << 5); - } - - if (i == pic->buf_spec_num) - WRITE_VREG(H264_BUFFER_INFO_DATA, - hw->buffer_spec[i].info0 | 0xf); - else - WRITE_VREG(H264_BUFFER_INFO_DATA, - hw->buffer_spec[i].info0); - WRITE_VREG(H264_BUFFER_INFO_DATA, hw->buffer_spec[i].info1); - WRITE_VREG(H264_BUFFER_INFO_DATA, hw->buffer_spec[i].info2); - } - - /* config reference buffer */ - if (hw->mmu_enable) { - hevc_mcr_config_mc_ref(hw); - hevc_mcr_config_mcrcc(hw); - } - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "list0 size %d\n", pSlice->listXsize[0]); - WRITE_VREG(H264_BUFFER_INFO_INDEX, 0); - ref_reg_val = 0; - j = 0; - h264_buffer_info_data_write_count = 0; - - for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) { - /*ref list 0 */ - struct StorablePicture *ref = pSlice->listX[0][i]; - unsigned int cfg; - /* bit[6:5] - frame/field info, - * 01 - top, 10 - bottom, 11 - frame - */ - #ifdef ERROR_CHECK - if (ref == NULL) { - hw->data_flag |= ERROR_FLAG; - pic->data_flag |= ERROR_FLAG; - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref list0 NULL\n"); - return -1; - } - if ((ref->data_flag & ERROR_FLAG) && ref_frame_mark_flag[DECODE_ID(hw)]) { - hw->data_flag |= ERROR_FLAG; - pic->data_flag |= ERROR_FLAG; - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark1 \n"); - } - if (ref->data_flag & NULL_FLAG) - hw->data_flag |= NULL_FLAG; -#endif - canvas_pos = hw->buffer_spec[ref->buf_spec_num].canvas_pos; - - if (ref->structure == TOP_FIELD) - cfg = 0x1; - else if (ref->structure == BOTTOM_FIELD) - cfg = 0x2; - else /* FRAME */ - cfg = 0x3; - - one_ref_cfg = (canvas_pos & 0x1f) | (cfg << 5); - ref_reg_val <<= 8; - ref_reg_val |= one_ref_cfg; - j++; - - if (j == 4) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "H264_BUFFER_INFO_DATA: %x\n", ref_reg_val); - WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); - h264_buffer_info_data_write_count++; - j = 0; - } - print_pic_info(DECODE_ID(hw), "list0", - pSlice->listX[0][i], -1); - } - if (j != 0) { - while (j != 4) { - ref_reg_val <<= 8; - ref_reg_val |= one_ref_cfg; - j++; - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "H264_BUFFER_INFO_DATA: %x\n", - ref_reg_val); - WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); - h264_buffer_info_data_write_count++; - } - ref_reg_val = (one_ref_cfg << 24) | (one_ref_cfg<<16) | - (one_ref_cfg << 8) | one_ref_cfg; - for (i = h264_buffer_info_data_write_count; i < 8; i++) - WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "list1 size %d\n", pSlice->listXsize[1]); - WRITE_VREG(H264_BUFFER_INFO_INDEX, 8); - ref_reg_val = 0; - j = 0; - - for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) { - /* ref list 0 */ - struct StorablePicture *ref = pSlice->listX[1][i]; - unsigned int cfg; - /* bit[6:5] - frame/field info, - * 01 - top, 10 - bottom, 11 - frame - */ - - #ifdef ERROR_CHECK - if (ref == NULL) { - hw->data_flag |= ERROR_FLAG; - pic->data_flag |= ERROR_FLAG; - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error list1 NULL\n"); - return -2; - } - if ((ref->data_flag & ERROR_FLAG) && (ref_frame_mark_flag[DECODE_ID(hw)])) { - pic->data_flag |= ERROR_FLAG; - hw->data_flag |= ERROR_FLAG; - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark2\n"); - } - if (ref->data_flag & NULL_FLAG) - hw->data_flag |= NULL_FLAG; -#endif - canvas_pos = hw->buffer_spec[ref->buf_spec_num].canvas_pos; - if (ref->structure == TOP_FIELD) - cfg = 0x1; - else if (ref->structure == BOTTOM_FIELD) - cfg = 0x2; - else /* FRAME */ - cfg = 0x3; - one_ref_cfg = (canvas_pos & 0x1f) | (cfg << 5); - ref_reg_val <<= 8; - ref_reg_val |= one_ref_cfg; - j++; - - if (j == 4) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "H264_BUFFER_INFO_DATA: %x\n", - ref_reg_val); - WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); - j = 0; - } - print_pic_info(DECODE_ID(hw), "list1", - pSlice->listX[1][i], -1); - } - if (j != 0) { - while (j != 4) { - ref_reg_val <<= 8; - ref_reg_val |= one_ref_cfg; - j++; - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "H264_BUFFER_INFO_DATA: %x\n", ref_reg_val); - WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); - } - - /* configure co-locate buffer */ - while ((READ_VREG(H264_CO_MB_RW_CTL) >> 11) & 0x1) - ; - if ((pSlice->mode_8x8_flags & 0x4) && - (pSlice->mode_8x8_flags & 0x2)) - use_direct_8x8 = 1; - else - use_direct_8x8 = 0; - -#ifndef ONE_COLOCATE_BUF_PER_DECODE_BUF - colocate_adr_offset = - ((pic->structure == FRAME && pic->mb_aff_frame_flag == 0) - ? 1 : 2) * 96; - if (use_direct_8x8) - colocate_adr_offset >>= 2; - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "colocate buf size of each mb 0x%x first_mb_in_slice 0x%x colocate_adr_offset 0x%x\r\n", - colocate_adr_offset, pSlice->first_mb_in_slice, - colocate_adr_offset * pSlice->first_mb_in_slice); - - colocate_adr_offset *= pSlice->first_mb_in_slice; - - if ((pic->colocated_buf_index >= 0) && - (pic->colocated_buf_index < p_H264_Dpb->colocated_buf_count)) { - colocate_wr_adr = p_H264_Dpb->colocated_mv_addr_start + - ((p_H264_Dpb->colocated_buf_size * - pic->colocated_buf_index) - >> (use_direct_8x8 ? 2 : 0)); - if ((colocate_wr_adr + p_H264_Dpb->colocated_buf_size) > - p_H264_Dpb->colocated_mv_addr_end) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "Error, colocate buf is not enough, index is %d\n", - pic->colocated_buf_index); - ret = -3; - } - val = colocate_wr_adr + colocate_adr_offset; - WRITE_VREG(H264_CO_MB_WR_ADDR, val); - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "WRITE_VREG(H264_CO_MB_WR_ADDR) = %x, first_mb_in_slice %x pic_structure %x colocate_adr_offset %x mode_8x8_flags %x colocated_buf_size %x\n", - val, pSlice->first_mb_in_slice, pic->structure, - colocate_adr_offset, pSlice->mode_8x8_flags, - p_H264_Dpb->colocated_buf_size); - } else { - WRITE_VREG(H264_CO_MB_WR_ADDR, 0xffffffff); - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "WRITE_VREG(H264_CO_MB_WR_ADDR) = 0xffffffff\n"); - } -#else - colocate_buf_index = hw->buffer_spec[pic->buf_spec_num].canvas_pos; - colocate_adr_offset = - ((pic->structure == FRAME && pic->mb_aff_frame_flag == 0) ? 1 : 2) * 96; - if (use_direct_8x8) - colocate_adr_offset >>= 2; - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "colocate buf size of each mb 0x%x first_mb_in_slice 0x%x colocate_adr_offset 0x%x\r\n", - colocate_adr_offset, pSlice->first_mb_in_slice, - colocate_adr_offset * pSlice->first_mb_in_slice); - - colocate_adr_offset *= pSlice->first_mb_in_slice; - - colocate_wr_adr = p_H264_Dpb->colocated_mv_addr_start + - ((p_H264_Dpb->colocated_buf_size * colocate_buf_index) >> - (use_direct_8x8 ? 2 : 0)); - - if ((colocate_wr_adr + p_H264_Dpb->colocated_buf_size) > - p_H264_Dpb->colocated_mv_addr_end) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "Error, colocate buf is not enough, col buf index is %d\n", - colocate_buf_index); - ret = -4; - } - val = colocate_wr_adr + colocate_adr_offset; - WRITE_VREG(H264_CO_MB_WR_ADDR, val); - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "WRITE_VREG(H264_CO_MB_WR_ADDR) = %x, first_mb_in_slice %x pic_structure %x colocate_adr_offset %x mode_8x8_flags %x colocated_buf_size %x\n", - val, pSlice->first_mb_in_slice, pic->structure, - colocate_adr_offset, pSlice->mode_8x8_flags, - p_H264_Dpb->colocated_buf_size); -#endif - if (pSlice->listXsize[1] > 0) { - struct StorablePicture *colocate_pic = pSlice->listX[1][0]; - /* H264_CO_MB_RD_ADDR[bit 31:30], - * original picture structure of L1[0], - * 00 - top field, 01 - bottom field, - * 10 - frame, 11 - mbaff frame - */ - int l10_structure; - int cur_colocate_ref_type; - /* H264_CO_MB_RD_ADDR[bit 29], top/bot for B field pciture, - * 0 - top, 1 - bot - */ - unsigned int val; -#ifdef ERROR_CHECK - if (colocate_pic == NULL) { - hw->data_flag |= ERROR_FLAG; - pic->data_flag |= ERROR_FLAG; - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " colocate error pic NULL\n"); - return -5; - } - if (colocate_pic->data_flag & ERROR_FLAG) { - pic->data_flag |= ERROR_FLAG; - hw->data_flag |= ERROR_FLAG; - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " colocare ref error mark\n"); - } - if (colocate_pic->data_flag & NULL_FLAG) - hw->data_flag |= NULL_FLAG; -#endif - - if (colocate_pic->mb_aff_frame_flag) - l10_structure = 3; - else { - if (colocate_pic->coded_frame) - l10_structure = 2; - else - l10_structure = (colocate_pic->structure == - BOTTOM_FIELD) ? 1 : 0; - } -#if 0 - /*case0016, p16, - *cur_colocate_ref_type should be configured base on current pic - */ - if (pic->structure == FRAME && - pic->mb_aff_frame_flag) - cur_colocate_ref_type = 0; - else if (pic->structure == BOTTOM_FIELD) - cur_colocate_ref_type = 1; - else - cur_colocate_ref_type = 0; -#else - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - " CUR TMP DEBUG : mb_aff_frame_flag : %d, structure : %d coded_frame %d\n", - pic->mb_aff_frame_flag, - pic->structure, - pic->coded_frame); - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - " COL TMP DEBUG : mb_aff_frame_flag : %d, structure : %d coded_frame %d\n", - colocate_pic->mb_aff_frame_flag, - colocate_pic->structure, - colocate_pic->coded_frame); - if (pic->structure == FRAME || pic->mb_aff_frame_flag) { - cur_colocate_ref_type = - (abs(pic->poc - colocate_pic->top_poc) - < abs(pic->poc - - colocate_pic->bottom_poc)) ? 0 : 1; - } else - cur_colocate_ref_type = - (colocate_pic->structure - == BOTTOM_FIELD) ? 1 : 0; -#endif - -#ifndef ONE_COLOCATE_BUF_PER_DECODE_BUF - if ((colocate_pic->colocated_buf_index >= 0) && - (colocate_pic->colocated_buf_index < - p_H264_Dpb->colocated_buf_count)) { - colocate_rd_adr = p_H264_Dpb->colocated_mv_addr_start + - ((p_H264_Dpb->colocated_buf_size * - colocate_pic->colocated_buf_index) - >> (use_direct_8x8 ? 2 : 0)); - if ((colocate_rd_adr + p_H264_Dpb->colocated_buf_size) > - p_H264_Dpb->colocated_mv_addr_end) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_ERROR, - "Error, colocate buf is not enough, index is %d\n", - colocate_pic->colocated_buf_index); - ret = -6; - } - /* bit 31:30 -- L1[0] picture coding structure, - * 00 - top field, 01 - bottom field, - * 10 - frame, 11 - mbaff frame - * bit 29 - L1[0] top/bot for B field pciture, - * 0 - top, 1 - bot - * bit 28:0 h264_co_mb_mem_rd_addr[31:3] - * -- only used for B Picture Direct mode - * [2:0] will set to 3'b000 - */ - /* #define H264_CO_MB_RD_ADDR VLD_C39 0xc39 */ - val = ((colocate_rd_adr+colocate_adr_offset) >> 3) | - (l10_structure << 30) | - (cur_colocate_ref_type << 29); - WRITE_VREG(H264_CO_MB_RD_ADDR, val); - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "co idx %d, WRITE_VREG(H264_CO_MB_RD_ADDR) = %x, addr %x L1(0) pic_structure %d mbaff %d\n", - colocate_pic->colocated_buf_index, - val, colocate_rd_adr + colocate_adr_offset, - colocate_pic->structure, - colocate_pic->mb_aff_frame_flag); - } else { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "Error, reference pic has no colocated buf\n"); - ret = -7; - } -#else - colocate_buf_index = - hw->buffer_spec[colocate_pic->buf_spec_num].canvas_pos; - colocate_rd_adr = p_H264_Dpb->colocated_mv_addr_start + - ((p_H264_Dpb->colocated_buf_size * - colocate_buf_index) - >> (use_direct_8x8 ? 2 : 0)); - if ((colocate_rd_adr + p_H264_Dpb->colocated_buf_size) > - p_H264_Dpb->colocated_mv_addr_end) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "Error, colocate buf is not enough, col buf index is %d\n", - colocate_buf_index); - ret = -8; - } - /* bit 31:30 -- L1[0] picture coding structure, - * 00 - top field, 01 - bottom field, - * 10 - frame, 11 - mbaff frame - * bit 29 - L1[0] top/bot for B field pciture, - * 0 - top, 1 - bot - * bit 28:0 h264_co_mb_mem_rd_addr[31:3] - * -- only used for B Picture Direct mode - * [2:0] will set to 3'b000 - */ - /* #define H264_CO_MB_RD_ADDR VLD_C39 0xc39 */ - val = ((colocate_rd_adr+colocate_adr_offset)>>3) | - (l10_structure << 30) | (cur_colocate_ref_type << 29); - WRITE_VREG(H264_CO_MB_RD_ADDR, val); - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "WRITE_VREG(H264_CO_MB_RD_ADDR) = %x, L1(0) pic_structure %d mbaff %d\n", - val, colocate_pic->structure, - colocate_pic->mb_aff_frame_flag); -#endif - } - return ret; -} - -static int vh264_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - struct vdec_s *vdec = op_arg; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - - spin_lock_irqsave(&hw->lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&hw->newframe_q); - states->buf_avail_num = kfifo_len(&hw->display_q); - - spin_unlock_irqrestore(&hw->lock, flags); - - return 0; -} - -static struct vframe_s *vh264_vf_peek(void *op_arg) -{ - struct vframe_s *vf[2] = {0, 0}; - struct vdec_s *vdec = op_arg; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - - if (!hw) - return NULL; - - if (force_disp_bufspec_num & 0x100) { - if (force_disp_bufspec_num & 0x200) - return NULL; - return &hw->vframe_dummy; - } - - if (kfifo_out_peek(&hw->display_q, (void *)&vf, 2)) { - if (vf[1]) { - vf[0]->next_vf_pts_valid = true; - vf[0]->next_vf_pts = vf[1]->pts; - } else - vf[0]->next_vf_pts_valid = false; - return vf[0]; - } - - return NULL; -} - -static struct vframe_s *vh264_vf_get(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - - if (!hw) - return NULL; - - if (force_disp_bufspec_num & 0x100) { - int buffer_index = force_disp_bufspec_num & 0xff; - if (force_disp_bufspec_num & 0x200) - return NULL; - - vf = &hw->vframe_dummy; - vf->duration_pulldown = 0; - vf->pts = 0; - vf->pts_us64 = 0; - set_frame_info(hw, vf, buffer_index); - vf->flag = 0; - if (hw->mmu_enable) { - if (hw->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { - /*head adr*/ - vf->compHeadAddr = - hw->buffer_spec[buffer_index].alloc_header_addr; - /*body adr*/ - vf->compBodyAddr = 0; - vf->canvas0Addr = vf->canvas1Addr = 0; - } - - vf->type = VIDTYPE_SCATTER; - - if (hw->double_write_mode) { - vf->type |= VIDTYPE_PROGRESSIVE - | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if (hw->double_write_mode == 3) - vf->type |= VIDTYPE_COMPRESS; - - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - hw->buffer_spec[buffer_index]. - canvas_config[0]; - vf->canvas0_config[1] = - hw->buffer_spec[buffer_index]. - canvas_config[1]; - - vf->canvas1_config[0] = - hw->buffer_spec[buffer_index]. - canvas_config[0]; - vf->canvas1_config[1] = - hw->buffer_spec[buffer_index]. - canvas_config[1]; - } else { - vf->type |= - VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; - vf->canvas0Addr = vf->canvas1Addr = 0; - } - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - - vf->compWidth = hw->frame_width; - vf->compHeight = hw->frame_height; - - if (hw->double_write_mode) { - vf->width = hw->frame_width / - get_double_write_ratio(hw); - vf->height = hw->frame_height / - get_double_write_ratio(hw); - } - } else { - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(&hw->buffer_spec[buffer_index]); - } - - /*vf->mem_handle = decoder_bmmu_box_get_mem_handle( - hw->bmmu_box, buffer_index);*/ - update_vf_memhandle(hw, vf, buffer_index); - force_disp_bufspec_num |= 0x200; - return vf; - } - - if (kfifo_get(&hw->display_q, &vf)) { - int time = jiffies; - unsigned int frame_interval = - 1000*(time - hw->last_frame_time)/HZ; - struct vframe_s *next_vf; - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_VDEC_DETAIL)) { - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - int frame_index = FRAME_INDEX(vf->index); - if (frame_index < 0 || - frame_index >= DPB_SIZE_MAX) { - dpb_print(DECODE_ID(hw), 0, - "%s vf index 0x%x error\r\n", - __func__, vf->index); - } else { - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, - "%s buf_spec_num %d vf %p poc %d dur %d pts %d interval %dms\n", - __func__, BUFSPEC_INDEX(vf->index), vf, - p_H264_Dpb->mFrameStore[frame_index].poc, - vf->duration, vf->pts, frame_interval); - } - } - if (hw->last_frame_time > 0) { - if (frame_interval > - max_get_frame_interval[DECODE_ID(hw)]) - max_get_frame_interval[DECODE_ID(hw)] - = frame_interval; - } - hw->last_frame_time = time; - hw->vf_get_count++; - if (kfifo_peek(&hw->display_q, &next_vf)) { - vf->next_vf_pts_valid = true; - vf->next_vf_pts = next_vf->pts; - } else - vf->next_vf_pts_valid = false; - return vf; - } - - return NULL; -} - -static void vh264_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct vdec_s *vdec = op_arg; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - int buf_spec_num; - int frame_index; - - if (vf == (&hw->vframe_dummy)) - return; - if (vf->index == -1) { - dpb_print(DECODE_ID(hw), 0, - "Warning: %s vf %p invalid index\r\n", - __func__, vf); - return; - } - frame_index = FRAME_INDEX(vf->index); - buf_spec_num = BUFSPEC_INDEX(vf->index); - if (frame_index < 0 || - frame_index >= DPB_SIZE_MAX || - buf_spec_num < 0 || - buf_spec_num >= BUFSPEC_POOL_SIZE) { - dpb_print(DECODE_ID(hw), 0, - "%s vf index 0x%x error\r\n", - __func__, vf->index); - return; - } - /*get_buf_spec_idx_by_canvas_config(hw, - &vf->canvas0_config[0]);*/ - if (hw->buffer_spec[buf_spec_num].used == 2) { - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s %p to fs[%d], poc %d buf_spec_num %d used %d vf_ref %d\n", - __func__, vf, frame_index, - p_H264_Dpb->mFrameStore[frame_index].poc, - buf_spec_num, - hw->buffer_spec[buf_spec_num].used, - hw->buffer_spec[buf_spec_num].vf_ref); - hw->buffer_spec[buf_spec_num].vf_ref--; - if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) - set_frame_output_flag(&hw->dpb, frame_index); - } else { - unsigned long flags; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s %p isolated vf, buf_spec_num %d used %d vf_ref %d\n", - __func__, vf, buf_spec_num, - hw->buffer_spec[buf_spec_num].used, - hw->buffer_spec[buf_spec_num].vf_ref); - spin_lock_irqsave(&hw->bufspec_lock, flags); - hw->buffer_spec[buf_spec_num].vf_ref--; - if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) { - if (hw->buffer_spec[buf_spec_num].used == 3) - hw->buffer_spec[buf_spec_num].used = 4; - else if (hw->buffer_spec[buf_spec_num].used == 5) - hw->buffer_spec[buf_spec_num].used = 0; - } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - - } - - hw->vf_put_count++; - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); - -#define ASSIST_MBOX1_IRQ_REG VDEC_ASSIST_MBOX1_IRQ_REG - if (hw->buffer_empty_flag) - WRITE_VREG(ASSIST_MBOX1_IRQ_REG, 0x1); -} - -static int vh264_event_cb(int type, void *data, void *op_arg) -{ - unsigned long flags; - struct vdec_s *vdec = op_arg; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - - if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) { - struct provider_aux_req_s *req = - (struct provider_aux_req_s *)data; - int buf_spec_num = BUFSPEC_INDEX(req->vf->index); - spin_lock_irqsave(&hw->lock, flags); - req->aux_buf = NULL; - req->aux_size = 0; - if (buf_spec_num >= 0 && - buf_spec_num < BUFSPEC_POOL_SIZE && - is_buf_spec_in_disp_q(hw, buf_spec_num) - ) { - req->aux_buf = - hw->buffer_spec[buf_spec_num].aux_data_buf; - req->aux_size = - hw->buffer_spec[buf_spec_num].aux_data_size; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - req->dv_enhance_exist = - hw->buffer_spec[buf_spec_num].dv_enhance_exist; -#else - req->dv_enhance_exist = 0; -#endif - } - spin_unlock_irqrestore(&hw->lock, flags); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s(type 0x%x vf buf_spec_num 0x%x)=>size 0x%x\n", - __func__, type, buf_spec_num, req->aux_size); - } - - return 0; -} - -static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, - u32 index) -{ - struct canvas_config_s *p_canvas_config; - int force_rate = input_frame_based(hw_to_vdec(hw)) ? - force_rate_framebase : force_rate_streambase; - dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, - "%s (%d,%d) dur %d, vf %p, index %d\n", __func__, - hw->frame_width, hw->frame_height, hw->frame_dur, vf, index); - - vf->width = hw->frame_width; - vf->height = hw->frame_height; - if (force_rate) { - if (force_rate == -1) - vf->duration = 0; - else - vf->duration = 96000/force_rate; - } else - vf->duration = hw->frame_dur; - vf->ratio_control = - (min(hw->h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) << - DISP_RATIO_ASPECT_RATIO_BIT; - vf->orientation = hw->vh264_rotation; - if (hw->mmu_enable) - return; - vf->canvas0Addr = vf->canvas1Addr = -1; -#ifdef NV21 - vf->plane_num = 2; -#else - vf->plane_num = 3; -#endif - - if (IS_VDEC_DW(hw)) { - vf->width = (hw->frame_width /2); - if (IS_VDEC_DW(hw) == 2) - vf->height = (hw->frame_height /2); - p_canvas_config = &hw->buffer_spec[index].vdec_dw_canvas_config[0]; - } else - p_canvas_config = &hw->buffer_spec[index].canvas_config[0]; - - vf->canvas0_config[0] = p_canvas_config[0]; - vf->canvas0_config[1] = p_canvas_config[1]; -#ifndef NV21 - vf->canvas0_config[2] = p_canvas_config[2]; -#endif - vf->canvas1_config[0] = p_canvas_config[0]; - vf->canvas1_config[1] = p_canvas_config[1]; -#ifndef NV21 - vf->canvas1_config[2] = p_canvas_config[2]; -#endif - /* signal_type */ - if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) - vf->signal_type = hw->video_signal_from_vui; - else - vf->signal_type = 0; - -} - -static void get_picture_qos_info(struct StorablePicture *picture) -{ - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { - unsigned char a[3]; - unsigned char i, j, t; - unsigned long data; - - get_random_bytes(&data, sizeof(unsigned long)); - if (picture->slice_type == I_SLICE) - data = 0; - a[0] = data & 0xff; - a[1] = (data >> 8) & 0xff; - a[2] = (data >> 16) & 0xff; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_mv = a[2]; - picture->avg_mv = a[1]; - picture->min_mv = a[0]; - /* - pr_info("mv data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); - */ - - get_random_bytes(&data, sizeof(unsigned long)); - a[0] = data & 0x1f; - a[1] = (data >> 8) & 0x3f; - a[2] = (data >> 16) & 0x7f; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_qp = a[2]; - picture->avg_qp = a[1]; - picture->min_qp = a[0]; - /* - pr_info("qp data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); - */ - - get_random_bytes(&data, sizeof(unsigned long)); - a[0] = data & 0x1f; - a[1] = (data >> 8) & 0x3f; - a[2] = (data >> 16) & 0x7f; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_skip = a[2]; - picture->avg_skip = a[1]; - picture->min_skip = a[0]; - - - /* - pr_info("skip data %x a[0]= %x a[1]= %x a[2]= %x\n", - data,a[0], a[1], a[2]); - */ - } else { - uint32_t blk88_y_count; - uint32_t blk88_c_count; - uint32_t blk22_mv_count; - uint32_t rdata32; - int32_t mv_hi; - int32_t mv_lo; - uint32_t rdata32_l; - uint32_t mvx_L0_hi; - uint32_t mvy_L0_hi; - uint32_t mvx_L1_hi; - uint32_t mvy_L1_hi; - int64_t value; - uint64_t temp_value; -/* -#define DEBUG_QOS -*/ -#ifdef DEBUG_QOS - int pic_number = picture->poc; -#endif - - picture->max_mv = 0; - picture->avg_mv = 0; - picture->min_mv = 0; - - picture->max_skip = 0; - picture->avg_skip = 0; - picture->min_skip = 0; - - picture->max_qp = 0; - picture->avg_qp = 0; - picture->min_qp = 0; - - - - - - /* set rd_idx to 0 */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0); - blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA); - if (blk88_y_count == 0) { -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* qp_y_sum */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_y_count, - rdata32, blk88_y_count); -#endif - picture->avg_qp = rdata32/blk88_y_count; - /* intra_y_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - /* skipped_y_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - picture->avg_skip = rdata32*100/blk88_y_count; - /* coeff_non_zero_y_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_y_count*1)), - '%', rdata32); -#endif - /* blk66_c_count */ - blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA); - if (blk88_c_count == 0) { -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* qp_c_sum */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_c_count, - rdata32, blk88_c_count); -#endif - /* intra_c_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* skipped_cu_c_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* coeff_non_zero_c_count */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_c_count*1)), - '%', rdata32); -#endif - - /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], - 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y QP min : %d\n", - pic_number, (rdata32>>0)&0xff); -#endif - picture->min_qp = (rdata32>>0)&0xff; - -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] Y QP max : %d\n", - pic_number, (rdata32>>8)&0xff); -#endif - picture->max_qp = (rdata32>>8)&0xff; - -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] C QP min : %d\n", - pic_number, (rdata32>>16)&0xff); - pr_info(" [Picture %d Quality] C QP max : %d\n", - pic_number, (rdata32>>24)&0xff); -#endif - - /* blk22_mv_count */ - blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA); - if (blk22_mv_count == 0) { -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] NO MV Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* mvy_L1_count[39:32], mvx_L1_count[39:32], - mvy_L0_count[39:32], mvx_L0_count[39:32] */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - /* should all be 0x00 or 0xff */ -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n", - pic_number, rdata32); -#endif - mvx_L0_hi = ((rdata32>>0)&0xff); - mvy_L0_hi = ((rdata32>>8)&0xff); - mvx_L1_hi = ((rdata32>>16)&0xff); - mvy_L1_hi = ((rdata32>>24)&0xff); - - /* mvx_L0_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvx_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvx_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; - value = div_s64(value, blk22_mv_count); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", - pic_number, (int)(value), - value, blk22_mv_count); -#endif - picture->avg_mv = value; - - /* mvy_L0_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvy_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvy_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvx_L1_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvx_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvx_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvy_L1_count[31:0] */ - rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); - temp_value = mvy_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvy_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - picture->max_mv = mv_hi; - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - picture->min_mv = mv_lo; - - /* {mvy_L0_max, mvy_L0_min} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvx_L1_max, mvx_L1_min} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvy_L1_max, mvy_L1_min} */ - rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL); -#ifdef DEBUG_QOS - pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", - pic_number, rdata32); -#endif - /* reset all counts */ - WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); - } -} - -static int get_max_dec_frame_buf_size(int level_idc, - int max_reference_frame_num, int mb_width, - int mb_height) -{ - int pic_size = mb_width * mb_height * 384; - - int size = 0; - - switch (level_idc) { - case 9: - size = 152064; - break; - case 10: - size = 152064; - break; - case 11: - size = 345600; - break; - case 12: - size = 912384; - break; - case 13: - size = 912384; - break; - case 20: - size = 912384; - break; - case 21: - size = 1824768; - break; - case 22: - size = 3110400; - break; - case 30: - size = 3110400; - break; - case 31: - size = 6912000; - break; - case 32: - size = 7864320; - break; - case 40: - size = 12582912; - break; - case 41: - size = 12582912; - break; - case 42: - size = 13369344; - break; - case 50: - size = 42393600; - break; - case 51: - case 52: - default: - size = 70778880; - break; - } - - size /= pic_size; - size = size + 1; /* need one more buffer */ - - if (max_reference_frame_num > size) - size = max_reference_frame_num; - - return size; -} - -static void vh264_config_canvs_for_mmu(struct vdec_h264_hw_s *hw) -{ - int i, j; - - if (hw->double_write_mode) { - mutex_lock(&vmh264_mutex); - if (hw->decode_pic_count == 0) { - for (j = 0; j < hw->dpb.mDPB.size; j++) { - i = get_buf_spec_by_canvas_pos(hw, j); - if (i >= 0) - config_decode_canvas_ex(hw, i); - } - } - mutex_unlock(&vmh264_mutex); - } -} - -static int vh264_set_params(struct vdec_h264_hw_s *hw, - u32 param1, u32 param2, u32 param3, u32 param4) -{ - int i, j; - int mb_width, mb_total; - int max_reference_size, level_idc; - int mb_height = 0; - unsigned long flags; - /*int mb_mv_byte;*/ - struct vdec_s *vdec = hw_to_vdec(hw); - u32 seq_info2; - int ret = 0; - int active_buffer_spec_num; - unsigned int buf_size; - unsigned int frame_mbs_only_flag; - unsigned int chroma_format_idc, chroma444; - unsigned int crop_infor, crop_bottom, crop_right; - unsigned int used_reorder_dpb_size_margin - = reorder_dpb_size_margin; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->master || vdec->slave) - used_reorder_dpb_size_margin = - reorder_dpb_size_margin_dv; -#endif - seq_info2 = param1; - hw->seq_info = param2; - - mb_width = seq_info2 & 0xff; - mb_total = (seq_info2 >> 8) & 0xffff; - if (!mb_width && mb_total) /*for 4k2k*/ - mb_width = 256; - if (mb_width) - mb_height = mb_total/mb_width; - if (mb_width <= 0 || mb_height <= 0 || - is_oversize(mb_width << 4, mb_height << 4)) { - dpb_print(DECODE_ID(hw), 0, - "!!!wrong seq_info2 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n", - seq_info2, - mb_width, - mb_height); - WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | - (hw->dpb.mDPB.size<<16) | - (hw->dpb.mDPB.size<<8)); - return 0; - } - - if (seq_info2 != 0 && - hw->seq_info2 != (seq_info2 & (~0x80000000)) && - hw->seq_info2 != 0 - ) /*picture size changed*/ - h264_reconfig(hw); - - if (hw->config_bufmgr_done == 0) { - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - u32 reg_val; - hw->cfg_param1 = param1; - hw->cfg_param2 = param2; - hw->cfg_param3 = param3; - hw->cfg_param4 = param4; - - hw->seq_info2 = seq_info2 & (~0x80000000); - dpb_print(DECODE_ID(hw), 0, - "AV_SCRATCH_1 = %x, AV_SCRATCH_2 %x\r\n", - seq_info2, hw->seq_info); - - dpb_init_global(&hw->dpb, - DECODE_ID(hw), 0, 0); - - p_H264_Dpb->fast_output_enable = fast_output_enable; - /*mb_mv_byte = (seq_info2 & 0x80000000) ? 24 : 96;*/ - -#if 1 - /*crop*/ - /* AV_SCRATCH_2 - bit 15: frame_mbs_only_flag - bit 13-14: chroma_format_idc */ - frame_mbs_only_flag = (hw->seq_info >> 15) & 0x01; - chroma_format_idc = (hw->seq_info >> 13) & 0x03; - chroma444 = (chroma_format_idc == 3) ? 1 : 0; - - /* @AV_SCRATCH_6.31-16 = (left << 8 | right ) << 1 - @AV_SCRATCH_6.15-0 = (top << 8 | bottom ) << - (2 - frame_mbs_only_flag) */ - crop_infor = param3; - crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag); - crop_right = ((crop_infor >> 16) & 0xff) - >> (2 - frame_mbs_only_flag); - - p_H264_Dpb->mSPS.frame_mbs_only_flag = frame_mbs_only_flag; - hw->frame_width = mb_width << 4; - hw->frame_height = mb_height << 4; - if (frame_mbs_only_flag) { - hw->frame_height = - hw->frame_height - (2 >> chroma444) * - min(crop_bottom, - (unsigned int)((8 << chroma444) - 1)); - hw->frame_width = - hw->frame_width - - (2 >> chroma444) * min(crop_right, - (unsigned - int)((8 << chroma444) - 1)); - } else { - hw->frame_height = - hw->frame_height - (4 >> chroma444) * - min(crop_bottom, - (unsigned int)((8 << chroma444) - - 1)); - hw->frame_width = - hw->frame_width - - (4 >> chroma444) * min(crop_right, - (unsigned int)((8 << chroma444) - 1)); - } - dpb_print(DECODE_ID(hw), 0, - "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d,\n", - frame_mbs_only_flag, crop_bottom, hw->frame_height); - dpb_print(DECODE_ID(hw), 0, - "mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", - mb_height, crop_right, - hw->frame_width, mb_width); - - if (hw->frame_height == 1088) - hw->frame_height = 1080; -#endif - if (!hw->mmu_enable) { - mb_width = (mb_width+3) & 0xfffffffc; - mb_height = (mb_height+3) & 0xfffffffc; - } - mb_total = mb_width * mb_height; - hw->mb_width = mb_width; - hw->mb_height = mb_height; - hw->mb_total = mb_total; - if (hw->mmu_enable) - hevc_mcr_sao_global_hw_init(hw, - (hw->mb_width << 4), (hw->mb_height << 4)); - - reg_val = param4; - level_idc = reg_val & 0xff; - max_reference_size = (reg_val >> 8) & 0xff; - dpb_print(DECODE_ID(hw), 0, - "mb height/widht/total: %x/%x/%x level_idc %x max_ref_num %x\n", - mb_height, mb_width, mb_total, - level_idc, max_reference_size); - - p_H264_Dpb->colocated_buf_size = mb_total * 96; - hw->dpb.reorder_pic_num = - get_max_dec_frame_buf_size(level_idc, - max_reference_size, mb_width, mb_height); - - dpb_print(DECODE_ID(hw), 0, - "restriction_flag=%d, max_dec_frame_buffering=%d, reorder_pic_num=%d\n", - hw->bitstream_restriction_flag, - hw->max_dec_frame_buffering, - hw->dpb.reorder_pic_num); - - if ((hw->bitstream_restriction_flag) && - (hw->max_dec_frame_buffering < - hw->dpb.reorder_pic_num)) { - hw->dpb.reorder_pic_num = hw->max_dec_frame_buffering; - dpb_print(DECODE_ID(hw), 0, - "set reorder_pic_num to %d\n", - hw->dpb.reorder_pic_num); - } - - active_buffer_spec_num = - hw->dpb.reorder_pic_num - + used_reorder_dpb_size_margin; - hw->max_reference_size = - max_reference_size + reference_buf_margin; - - if (active_buffer_spec_num > MAX_VF_BUF_NUM) { - active_buffer_spec_num = MAX_VF_BUF_NUM; - hw->dpb.reorder_pic_num = active_buffer_spec_num - - used_reorder_dpb_size_margin; - } - hw->dpb.mDPB.size = active_buffer_spec_num; - if (hw->max_reference_size > MAX_VF_BUF_NUM) - hw->max_reference_size = MAX_VF_BUF_NUM; - hw->dpb.max_reference_size = hw->max_reference_size; - - if (hw->no_poc_reorder_flag) - hw->dpb.reorder_pic_num = 1; - dpb_print(DECODE_ID(hw), 0, - "%s active_buf_spec_num %d reorder_pic_num %d collocate_buf_num %d\r\n", - __func__, active_buffer_spec_num, - hw->dpb.reorder_pic_num, - hw->max_reference_size); - - buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); - - mutex_lock(&vmh264_mutex); - if (!hw->mmu_enable) { - config_buf_specs(vdec); - i = get_buf_spec_by_canvas_pos(hw, 0); - - if (hw->is_used_v4l) { - if (i != -1) { - ret = alloc_one_buf_spec_from_queue(hw, i); - if (!ret) - config_decode_canvas(hw, i); - } - } else { - if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0) - config_decode_canvas(hw, i); - else - ret = -1; - } - } else { - if (hw->double_write_mode) { - config_buf_specs_ex(vdec); - } else { - spin_lock_irqsave(&hw->bufspec_lock, flags); - for (i = 0, j = 0; - j < active_buffer_spec_num - && i < BUFSPEC_POOL_SIZE; - i++) { - if (hw->buffer_spec[i].used != -1) - continue; - hw->buffer_spec[i].used = 0; - hw->buffer_spec[i]. - alloc_header_addr = 0; - hw->buffer_spec[i].canvas_pos = j; - j++; - } - spin_unlock_irqrestore(&hw->bufspec_lock, - flags); - } - hevc_mcr_config_canv2axitbl(hw, 0); - } - mutex_unlock(&vmh264_mutex); - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, __func__); - -#ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF - buf_size = PAGE_ALIGN( - p_H264_Dpb->colocated_buf_size * - active_buffer_spec_num); -#else - buf_size = PAGE_ALIGN( - p_H264_Dpb->colocated_buf_size * - hw->max_reference_size); -#endif - - if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_REF_IDX, - buf_size, DRIVER_NAME, - &hw->collocate_cma_alloc_addr) < 0) - return -1; - - hw->dpb.colocated_mv_addr_start = - hw->collocate_cma_alloc_addr; -#ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF - hw->dpb.colocated_mv_addr_end = - hw->dpb.colocated_mv_addr_start + - (p_H264_Dpb->colocated_buf_size * - active_buffer_spec_num); -#else - hw->dpb.colocated_mv_addr_end = - hw->dpb.colocated_mv_addr_start + - (p_H264_Dpb->colocated_buf_size * - hw->max_reference_size); -#endif - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "callocate cma, %lx, %x\n", - hw->collocate_cma_alloc_addr, - hw->dpb.colocated_mv_addr_start); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "colocated_mv_addr_start %x colocated_mv_addr_end %x\n", - hw->dpb.colocated_mv_addr_start, - hw->dpb.colocated_mv_addr_end); - if (!hw->mmu_enable) { - mutex_lock(&vmh264_mutex); - if (ret >= 0 && hw->decode_pic_count == 0) { - int buf_cnt; - /* h264_reconfig: alloc later*/ - buf_cnt = hw->dpb.mDPB.size; - - for (j = 1; j < buf_cnt; j++) { - i = get_buf_spec_by_canvas_pos(hw, j); - - if (hw->is_used_v4l) { - if (alloc_one_buf_spec_from_queue - (hw, i) < 0) { - if (j++ != buf_cnt) - ret = -1; - break; - } - } else if (alloc_one_buf_spec(hw, i) < 0) - break; - - config_decode_canvas(hw, i); - } - } - mutex_unlock(&vmh264_mutex); - } else { - vh264_config_canvs_for_mmu(hw); - } - - hw->config_bufmgr_done = 1; - - /*end of config_bufmgr_done */ - } - - return ret; -} - -static void vui_config(struct vdec_h264_hw_s *hw) -{ - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - int aspect_ratio_info_present_flag, aspect_ratio_idc; - /*time*/ - hw->num_units_in_tick = p_H264_Dpb->num_units_in_tick; - hw->time_scale = p_H264_Dpb->time_scale; - hw->timing_info_present_flag = p_H264_Dpb->vui_status & 0x2; - - hw->bitstream_restriction_flag = - p_H264_Dpb->bitstream_restriction_flag; - hw->num_reorder_frames = - p_H264_Dpb->num_reorder_frames; - hw->max_dec_frame_buffering = - p_H264_Dpb->max_dec_frame_buffering; - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, - "vui_config: pdb %d, %d, %d\n", - p_H264_Dpb->bitstream_restriction_flag, - p_H264_Dpb->num_reorder_frames, - p_H264_Dpb->max_dec_frame_buffering); - - hw->fixed_frame_rate_flag = 0; - if (hw->timing_info_present_flag) { - hw->fixed_frame_rate_flag = - p_H264_Dpb->fixed_frame_rate_flag; - - if (((hw->num_units_in_tick * 120) >= hw->time_scale && - ((!hw->sync_outside) || - (!hw->frame_dur))) - && hw->num_units_in_tick && hw->time_scale) { - if (hw->use_idr_framerate || - hw->fixed_frame_rate_flag || - !hw->frame_dur || - !hw->duration_from_pts_done - /*|| vh264_running*/) { - u32 frame_dur_es = - div_u64(96000ULL * 2 * hw->num_units_in_tick, - hw->time_scale); - if (hw->frame_dur != frame_dur_es) { - hw->h264_first_valid_pts_ready = false; - hw->h264pts1 = 0; - hw->h264pts2 = 0; - hw->h264_pts_count = 0; - hw->duration_from_pts_done = 0; - fixed_frame_rate_mode = - FIX_FRAME_RATE_OFF; - hw->pts_duration = 0; - hw->frame_dur = frame_dur_es; - schedule_work(&hw->notify_work); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_DEC_DETAIL, - "frame_dur %d from timing_info\n", - hw->frame_dur); - } - - /*hack to avoid use ES frame duration when - *it's half of the rate from system info - * sometimes the encoder is given a wrong - * frame rate but the system side information - * is more reliable - *if ((frame_dur * 2) != frame_dur_es) { - * frame_dur = frame_dur_es; - *} - */ - } - } - } else { - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "H.264: timing_info not present\n"); - } - - /*aspect ratio*/ - aspect_ratio_info_present_flag = - p_H264_Dpb->vui_status & 0x1; - aspect_ratio_idc = p_H264_Dpb->aspect_ratio_idc; - - if (aspect_ratio_info_present_flag) { - if (aspect_ratio_idc == EXTEND_SAR) { - hw->h264_ar = - div_u64(256ULL * - p_H264_Dpb->aspect_ratio_sar_height * - hw->frame_height, - p_H264_Dpb->aspect_ratio_sar_width * - hw->frame_width); - } else { - /* pr_info("v264dec: aspect_ratio_idc = %d\n", - aspect_ratio_idc); */ - - switch (aspect_ratio_idc) { - case 1: - hw->h264_ar = 0x100 * hw->frame_height / - hw->frame_width; - break; - case 2: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 12); - break; - case 3: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 10); - break; - case 4: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 16); - break; - case 5: - hw->h264_ar = 0x100 * hw->frame_height * 33 / - (hw->frame_width * 40); - break; - case 6: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 24); - break; - case 7: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 20); - break; - case 8: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 32); - break; - case 9: - hw->h264_ar = 0x100 * hw->frame_height * 33 / - (hw->frame_width * 80); - break; - case 10: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 18); - break; - case 11: - hw->h264_ar = 0x100 * hw->frame_height * 11 / - (hw->frame_width * 15); - break; - case 12: - hw->h264_ar = 0x100 * hw->frame_height * 33 / - (hw->frame_width * 64); - break; - case 13: - hw->h264_ar = 0x100 * hw->frame_height * 99 / - (hw->frame_width * 160); - break; - case 14: - hw->h264_ar = 0x100 * hw->frame_height * 3 / - (hw->frame_width * 4); - break; - case 15: - hw->h264_ar = 0x100 * hw->frame_height * 2 / - (hw->frame_width * 3); - break; - case 16: - hw->h264_ar = 0x100 * hw->frame_height * 1 / - (hw->frame_width * 2); - break; - default: - if (hw->vh264_ratio >> 16) { - hw->h264_ar = (hw->frame_height * - (hw->vh264_ratio & 0xffff) * - 0x100 + - ((hw->vh264_ratio >> 16) * - hw->frame_width / 2)) / - ((hw->vh264_ratio >> 16) * - hw->frame_width); - } else { - hw->h264_ar = hw->frame_height * 0x100 / - hw->frame_width; - } - break; - } - } - } else { - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "v264dec: aspect_ratio not available from source\n"); - if (hw->vh264_ratio >> 16) { - /* high 16 bit is width, low 16 bit is height */ - hw->h264_ar = - ((hw->vh264_ratio & 0xffff) * - hw->frame_height * 0x100 + - (hw->vh264_ratio >> 16) * - hw->frame_width / 2) / - ((hw->vh264_ratio >> 16) * - hw->frame_width); - } else - hw->h264_ar = hw->frame_height * 0x100 / - hw->frame_width; - } - - if (hw->pts_unstable && (hw->fixed_frame_rate_flag == 0)) { - if (((hw->frame_dur == RATE_2397_FPS) - && (dec_control - & DEC_CONTROL_FLAG_FORCE_RATE_2397_FPS_FIX_FRAME_RATE)) - || ((RATE_2997_FPS == - hw->frame_dur) && - (dec_control & - DEC_CONTROL_FLAG_FORCE_RATE_2997_FPS_FIX_FRAME_RATE))) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "force fix frame rate\n"); - hw->fixed_frame_rate_flag = 0x40; - } - } - - /*video_signal_from_vui: to do .. */ -} - -static void bufmgr_recover(struct vdec_h264_hw_s *hw) -{ - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - - bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2); - if (error_proc_policy & 0x20) { - if (!hw->is_used_v4l) - hw->reset_bufmgr_flag = 1; - } -} - -void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) -{ - struct vdec_h264_hw_s *hw = - container_of(p_H264_Dpb, struct vdec_h264_hw_s, dpb); - - dpb_print(DECODE_ID(hw), 0, "call %s\n", __func__); - - bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2); - hw->reset_bufmgr_flag = 1; -} - -#ifdef CONSTRAIN_MAX_BUF_NUM -static int get_vf_ref_only_buf_count(struct vdec_h264_hw_s *hw) -{ - int i; - int count = 0; - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - if (is_buf_spec_in_disp_q(hw, i) && - hw->buffer_spec[i].vf_ref > 0) - count++; - } - return count; -} - -static int get_used_buf_count(struct vdec_h264_hw_s *hw) -{ - int i; - int count = 0; - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - if (is_buf_spec_in_use(hw, i)) - count++; - } - return count; -} -#endif - - -static bool is_buffer_available(struct vdec_s *vdec) -{ - bool buffer_available = 1; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private); - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; - if ((kfifo_len(&hw->newframe_q) <= 0) || - ((hw->config_bufmgr_done) && (!have_free_buf_spec(vdec))) || - ((p_H264_Dpb->mDPB.init_done) && - (p_H264_Dpb->mDPB.used_size >= (p_H264_Dpb->mDPB.size -1)) && - (is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) == 0))) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, - "%s, empty, newq(%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n", - __func__, - kfifo_len(&hw->newframe_q), - have_free_buf_spec(vdec), - p_H264_Dpb->mDPB.init_done, - p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, - is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) - ); - buffer_available = 0; - if (dpb_is_debug(DECODE_ID(hw), - DEBUG_DISABLE_RUNREADY_RMBUF)) - return buffer_available; - - if ((error_proc_policy & 0x4) && - (error_proc_policy & 0x8)) { - if ((kfifo_len(&hw->display_q) <= 0) && - (p_H264_Dpb->mDPB.used_size == - p_H264_Dpb->mDPB.size) && - (p_Dpb->ref_frames_in_buffer > - (imax( - 1, p_Dpb->num_ref_frames) - - p_Dpb->ltref_frames_in_buffer + - force_sliding_margin))) - bufmgr_recover(hw); - else - bufmgr_h264_remove_unused_frame(p_H264_Dpb, 1); - } else if ((error_proc_policy & 0x4) && - (kfifo_len(&hw->display_q) <= 0) && - ((p_H264_Dpb->mDPB.used_size == - p_H264_Dpb->mDPB.size) || - (!have_free_buf_spec(vdec)))) { - enum receviver_start_e state = RECEIVER_INACTIVE; - if ((error_proc_policy & 0x10) && - vf_get_receiver(vdec->vf_provider_name)) { - state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) - state = RECEIVER_INACTIVE; - } - if (state == RECEIVER_INACTIVE) - bufmgr_recover(hw); - else - bufmgr_h264_remove_unused_frame(p_H264_Dpb, 1); - } else if ((error_proc_policy & 0x8) && - (p_Dpb->ref_frames_in_buffer > - (imax( - 1, p_Dpb->num_ref_frames) - - p_Dpb->ltref_frames_in_buffer + - force_sliding_margin))) - bufmgr_recover(hw); - else - bufmgr_h264_remove_unused_frame(p_H264_Dpb, 1); - - if (hw->reset_bufmgr_flag == 1) - buffer_available = 1; - } - - return buffer_available; -} - -#define AUX_TAG_SEI 0x2 - -#define SEI_BUFFERING_PERIOD 0 -#define SEI_PicTiming 1 -#define SEI_USER_DATA 4 -#define SEI_RECOVERY_POINT 6 - -/* - ************************************************************************* - * Function:Reads bits from the bitstream buffer - * Input: - byte buffer[] - containing sei message data bits - int totbitoffset - bit offset from start of partition - int bytecount - total bytes in bitstream - int numbits - number of bits to read - * Output: - int *info - * Return: - -1: failed - > 0: the count of bit read - * Attention: - ************************************************************************* - */ - -static int get_bits(unsigned char buffer[], - int totbitoffset, - int *info, - int bytecount, - int numbits) -{ - register int inf; - long byteoffset; - int bitoffset; - - int bitcounter = numbits; - - byteoffset = totbitoffset / 8; - bitoffset = 7 - (totbitoffset % 8); - - inf = 0; - while (numbits) { - inf <<= 1; - inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset; - numbits--; - bitoffset--; - if (bitoffset < 0) { - byteoffset++; - bitoffset += 8; - if (byteoffset > bytecount) - return -1; - } - } - - *info = inf; - - - return bitcounter; -} - -static int parse_one_sei_record(struct vdec_h264_hw_s *hw, - u8 *sei_data_buf, - u8 *sei_data_buf_end) -{ - int payload_type; - int payload_size; - u8 *p_sei; - int temp; - int bit_offset; - int read_size; - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - - p_sei = sei_data_buf; - read_size = 0; - payload_type = 0; - do { - if (p_sei >= sei_data_buf_end) - return read_size; - - payload_type += *p_sei; - read_size++; - } while (*p_sei++ == 255); - - - payload_size = 0; - do { - if (p_sei >= sei_data_buf_end) - return read_size; - - payload_size += *p_sei; - read_size++; - } while (*p_sei++ == 255); - - - if (p_sei + payload_size > sei_data_buf_end) { - dpb_print(DECODE_ID(hw), 0, - "%s: payload_type = %d, payload_size = %d is over\n", - __func__, payload_type, payload_size); - return read_size; - } - bit_offset = 0; - - if (payload_size <= 0) { - dpb_print(DECODE_ID(hw), 0, - "%s warning: this is a null sei message for payload_type = %d\n", - __func__, payload_type); - return read_size; - } - switch (payload_type) { - case SEI_BUFFERING_PERIOD: - break; - case SEI_PicTiming: - if (p_H264_Dpb->vui_status & 0xc) { - int cpb_removal_delay; - int dpb_output_delay; - u32 delay_len; - - delay_len = p_H264_Dpb->dpb_param.l.data[DELAY_LENGTH]; - cpb_removal_delay - = (delay_len & 0x1F) + 1; - dpb_output_delay - = ((delay_len >> 5) & 0x1F) + 1; - - get_bits(p_sei, bit_offset, - &temp, payload_size, - dpb_output_delay+cpb_removal_delay); - bit_offset += dpb_output_delay+cpb_removal_delay; - } - if (p_H264_Dpb->vui_status & 0x10) { - get_bits(p_sei, bit_offset, &temp, payload_size, 4); - bit_offset += 4; - p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT] = temp; - } - break; - case SEI_USER_DATA: - if (enable_itu_t35) { - int i; - int j; - int data_len; - u8 *user_data_buf; - - user_data_buf - = hw->sei_itu_data_buf + hw->sei_itu_data_len; - /* user data length should be align with 8 bytes, - if not, then padding with zero*/ - for (i = 0; i < payload_size; i += 8) { - for (j = 0; j < 8; j++) { - int index; - - index = i+7-j; - if (index >= payload_size) - user_data_buf[i+j] = 0; - else - user_data_buf[i+j] - = p_sei[i+7-j]; - } - } - - data_len = payload_size; - if (payload_size % 8) - data_len = ((payload_size + 8) >> 3) << 3; - - hw->sei_itu_data_len += data_len; - /* - dpb_print(DECODE_ID(hw), 0, - "%s: user data, and len = %d:\n", - __func__, hw->sei_itu_data_len); - */ - } - break; - case SEI_RECOVERY_POINT: - p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT] = 1; - break; - } - - return read_size + payload_size; -} - -static void parse_sei_data(struct vdec_h264_hw_s *hw, - u8 *sei_data_buf, - int len) -{ - char *p_sei; - char *p_sei_end; - int parsed_size; - int read_size; - - - p_sei = sei_data_buf; - p_sei_end = p_sei + len; - parsed_size = 0; - while (parsed_size < len) { - read_size = parse_one_sei_record(hw, p_sei, p_sei_end); - p_sei += read_size; - parsed_size += read_size; - if (*p_sei == 0x80) { - p_sei++; - parsed_size++; - } - } -} - -static void check_decoded_pic_error(struct vdec_h264_hw_s *hw) -{ - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - struct StorablePicture *p = p_H264_Dpb->mVideo.dec_picture; - unsigned mby_mbx = READ_VREG(MBY_MBX); - unsigned mb_total = (hw->seq_info2 >> 8) & 0xffff; - unsigned decode_mb_count = - (((mby_mbx & 0xff) + 1) * - (((mby_mbx >> 8) & 0xff) + 1)); - if (mby_mbx == 0) - return; - if (get_cur_slice_picture_struct(p_H264_Dpb) != FRAME) - mb_total /= 2; - if (error_proc_policy & 0x100) { - if (decode_mb_count != mb_total) - p->data_flag |= ERROR_FLAG; - else if (p->data_flag & MAYBE_ERROR_FLAG) - p->data_flag &= ~ERROR_FLAG; - p->data_flag &= ~MAYBE_ERROR_FLAG; - } - - if ((error_proc_policy & 0x200) && - READ_VREG(ERROR_STATUS_REG) != 0) { - p->data_flag |= ERROR_FLAG; - } - - if (p->data_flag & ERROR_FLAG) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, - "%s: decode error, seq_info2 0x%x, mby_mbx 0x%x, mb_total %d decoded mb_count %d ERROR_STATUS_REG 0x%x\n", - __func__, - hw->seq_info2, - mby_mbx, - mb_total, - decode_mb_count, - READ_VREG(ERROR_STATUS_REG) - ); - - } -} - -static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw, - int frame_type, - u32 vpts, - u32 vpts_valid); - -static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) -{ - int i; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private); - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - unsigned int dec_dpb_status = p_H264_Dpb->dec_dpb_status; - u32 debug_tag; - int ret; - - if (dec_dpb_status == H264_CONFIG_REQUEST) { -#if 1 - unsigned short *p = (unsigned short *)hw->lmem_addr; - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, - DMA_FROM_DEVICE); - for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) { - p_H264_Dpb->dpb_param.l.data[i+ii] = - p[i+3-ii]; - if (dpb_is_debug(DECODE_ID(hw), - RRINT_FLAG_RPM)) { - if (((i + ii) & 0xf) == 0) - dpb_print(DECODE_ID(hw), - 0, "%04x:", - i); - dpb_print_cont(DECODE_ID(hw), - 0, "%04x ", - p[i+3-ii]); - if (((i + ii + 1) & 0xf) == 0) - dpb_print_cont( - DECODE_ID(hw), - 0, "\r\n"); - } - } - } - - p_H264_Dpb->bitstream_restriction_flag = - (p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1; - p_H264_Dpb->num_reorder_frames = - p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES]; - p_H264_Dpb->max_dec_frame_buffering = - p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME]; - - dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, - "H264_CONFIG_REQUEST: pdb %d, %d, %d\n", - p_H264_Dpb->bitstream_restriction_flag, - p_H264_Dpb->num_reorder_frames, - p_H264_Dpb->max_dec_frame_buffering); - hw->bitstream_restriction_flag = - p_H264_Dpb->bitstream_restriction_flag; - hw->num_reorder_frames = - p_H264_Dpb->num_reorder_frames; - hw->max_dec_frame_buffering = - p_H264_Dpb->max_dec_frame_buffering; -#endif - - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE); - reset_process_time(hw); - hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); - hw->dec_result = DEC_RESULT_CONFIG_PARAM; - vdec_schedule_work(&hw->work); - } else if (dec_dpb_status == H264_SLICE_HEAD_DONE) { - u16 data_hight; - u16 data_low; - u32 video_signal; - - int slice_header_process_status = 0; - int I_flag; - /*unsigned char is_idr;*/ - unsigned short *p = (unsigned short *)hw->lmem_addr; - reset_process_time(hw); - - hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); - hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); - hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); - hw->vld_dec_control = READ_VREG(VLD_DECODE_CONTROL); - if (input_frame_based(vdec) && - frmbase_cont_bitlevel2 != 0 && - READ_VREG(VIFF_BIT_CNT) < - frmbase_cont_bitlevel2 && - hw->get_data_count >= 0x70000000) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s H264_SLICE_HEAD_DONE with small bitcnt %d, goto empty_proc\n", - __func__, - READ_VREG(VIFF_BIT_CNT)); - - goto empty_proc; - } - - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, - DMA_FROM_DEVICE); -#if 0 - if (p_H264_Dpb->mVideo.dec_picture == NULL) { - if (!is_buffer_available(vdec)) { - hw->buffer_empty_flag = 1; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_UCODE_EVT, - "%s, buffer_empty, newframe_q(%d), have_free_buf_spec(%d), init_done(%d), used_size(%d/%d), is_there_unused_frame_from_dpb(%d)\n", - __func__, - kfifo_len(&hw->newframe_q), - have_free_buf_spec(vdec), - p_H264_Dpb->mDPB.init_done, - p_H264_Dpb->mDPB.used_size, - p_H264_Dpb->mDPB.size, - is_there_unused_frame_from_dpb( - &p_H264_Dpb->mDPB)); - return IRQ_HANDLED; - } - } - - hw->buffer_empty_flag = 0; -#endif -#ifdef SEND_PARAM_WITH_REG - for (i = 0; i < (RPM_END-RPM_BEGIN); i++) { - unsigned int data32; - - do { - data32 = READ_VREG(RPM_CMD_REG); - /* printk("%x\n", data32); */ - } while ((data32&0x10000) == 0); - p_H264_Dpb->dpb_param.l.data[i] = data32 & 0xffff; - WRITE_VREG(RPM_CMD_REG, 0); - /* printk("%x:%x\n", i,data32); */ - } -#else - for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) { - int ii; - - for (ii = 0; ii < 4; ii++) { - p_H264_Dpb->dpb_param.l.data[i+ii] = - p[i+3-ii]; - if (dpb_is_debug(DECODE_ID(hw), - RRINT_FLAG_RPM)) { - if (((i + ii) & 0xf) == 0) - dpb_print(DECODE_ID(hw), - 0, "%04x:", - i); - dpb_print_cont(DECODE_ID(hw), - 0, "%04x ", - p[i+3-ii]); - if (((i + ii + 1) & 0xf) == 0) - dpb_print_cont( - DECODE_ID(hw), - 0, "\r\n"); - } - } - } -#endif - data_low = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_LOW]; - data_hight = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_HIGHT]; - - video_signal = (data_hight << 16) | data_low; - hw->video_signal_from_vui = - ((video_signal & 0xffff) << 8) | - ((video_signal & 0xff0000) >> 16) | - ((video_signal & 0x3f000000)); - - - /*dpb_print(DECODE_ID(hw), - 0, - "video_signal_from_vui:0x%x, " - "data_low:0x%x, data_hight:0x%x\n", - hw->video_signal_from_vui, - data_low, - data_hight);*/ - - parse_sei_data(hw, hw->sei_data_buf, hw->sei_data_len); - - if (hw->config_bufmgr_done == 0) { - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_UCODE_EVT, - "config_bufmgr not done, discard frame\n"); - return IRQ_HANDLED; - } else if ((first_i_policy & 0x3) != 0) { - unsigned char is_i_slice = - (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] - == I_Slice) - ? 1 : 0; - unsigned char is_idr = - ((p_H264_Dpb->dpb_param.dpb.NAL_info_mmco & 0x1f) - == 5); - if ((first_i_policy & 0x3) == 0x3) - is_i_slice = is_idr; - if (!is_i_slice) { - if (hw->has_i_frame == 0) { - amvdec_stop(); - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - dpb_print(DECODE_ID(hw), - PRINT_FLAG_UCODE_EVT, - "has_i_frame is 0, discard none I(DR) frame\n"); - return IRQ_HANDLED; - } - } else { - if (hw->skip_frame_count < 0 || is_idr) { - /* second I */ - hw->dec_flag &= (~NODISP_FLAG); - hw->skip_frame_count = 0; - } - if (hw->has_i_frame == 0 && - (!is_idr)) { - int skip_count = - (first_i_policy >> 8) & 0xff; - /* first I (not IDR) */ - if ((first_i_policy & 0x3) == 2) - hw->skip_frame_count = - -1 - skip_count; - else - hw->skip_frame_count = - skip_count; - if (hw->skip_frame_count != 0) - hw->dec_flag |= NODISP_FLAG; - } - } - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT, - "current dpb index %d, poc %d, top/bot poc (%d,%d)\n", - p_H264_Dpb->dpb_param.dpb.current_dpb_index, - val(p_H264_Dpb->dpb_param.dpb.frame_pic_order_cnt), - val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt), - val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt)); - I_flag = (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice) - ? I_FLAG : 0; - if ((hw->i_only & 0x2) && (!(I_flag & I_FLAG)) && - (p_H264_Dpb->mSlice.structure == FRAME)) { - hw->data_flag = NULL_FLAG; - goto pic_done_proc; - } - - slice_header_process_status = - h264_slice_header_process(p_H264_Dpb); - if (hw->mmu_enable) - hevc_sao_set_slice_type(hw, - slice_header_process_status, - hw->dpb.mSlice.idr_flag); - vui_config(hw); - - if (p_H264_Dpb->mVideo.dec_picture) { - int cfg_ret = 0; - if (slice_header_process_status == 1) { - if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || - (((unsigned long)(hw->vh264_amstream_dec_info - .param)) & 0x8)) { - p_H264_Dpb->fast_output_enable = - H264_OUTPUT_MODE_FAST; - } - else - p_H264_Dpb->fast_output_enable - = fast_output_enable; - hw->data_flag = I_flag; - if ((p_H264_Dpb-> - dpb_param.dpb.NAL_info_mmco & 0x1f) - == 5) - hw->data_flag |= IDR_FLAG; - dpb_print(DECODE_ID(hw), - PRINT_FLAG_VDEC_STATUS, - "==================> frame count %d to skip %d\n", - hw->decode_pic_count+1, - hw->skip_frame_count); - } else { - struct StorablePicture *p = - p_H264_Dpb->mVideo.dec_picture; - unsigned mby_mbx = READ_VREG(MBY_MBX); - unsigned decode_mb_count = - (((mby_mbx & 0xff) + 1) * - (((mby_mbx >> 8) & 0xff) + 1)); - if ((error_proc_policy & 0x100) && - p_H264_Dpb->dpb_param.l. - data[FIRST_MB_IN_SLICE] - < decode_mb_count) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_VDEC_STATUS, - "Error detect! first_mb 0x%x mby_mbx 0x%x decode_mb 0x%x\n", - p_H264_Dpb->dpb_param.l. - data[FIRST_MB_IN_SLICE], - READ_VREG(MBY_MBX), - decode_mb_count); - if (!p_H264_Dpb->dpb_param.l. - data[FIRST_MB_IN_SLICE]) { - p->data_flag |= ERROR_FLAG; - goto pic_done_proc; - } else - p->data_flag |= MAYBE_ERROR_FLAG; - } - } - - if (error_proc_policy & 0x400) { - int ret = dpb_check_ref_list_error(p_H264_Dpb); - if (ret != 0) { - dpb_print(DECODE_ID(hw), 0, - "reference list error %d frame count %d to skip %d\n", - ret, - hw->decode_pic_count+1, - hw->skip_frame_count); - flush_dpb(p_H264_Dpb); - hw->data_flag |= ERROR_FLAG; - p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; - if ((error_proc_policy & 0x80) - && ((hw->dec_flag & - NODISP_FLAG) == 0)) { - hw->reset_bufmgr_flag = 1; - amvdec_stop(); - hw->dec_result - = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } - } - } - if ((error_proc_policy & 0x800) - && p_H264_Dpb->dpb_error_flag != 0) { - dpb_print(DECODE_ID(hw), 0, - "dpb error %d\n", - p_H264_Dpb->dpb_error_flag); - hw->data_flag |= ERROR_FLAG; - p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; - if ((error_proc_policy & 0x80) && - ((hw->dec_flag & NODISP_FLAG) == 0)) { - hw->reset_bufmgr_flag = 1; - amvdec_stop(); - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } - } - - cfg_ret = config_decode_buf(hw, - p_H264_Dpb->mVideo.dec_picture); - if (cfg_ret < 0) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "config_decode_buf fail (%d)\n", - cfg_ret); - if (error_proc_policy & 0x2) { - release_cur_decoding_buf(hw); - /*hw->data_flag |= ERROR_FLAG;*/ - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } else - hw->data_flag |= ERROR_FLAG; - p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; - } - } - - if (slice_header_process_status == 1) - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_NEWPIC); - else - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_SLICE); - hw->last_mby_mbx = 0; - hw->last_vld_level = 0; - start_process_time(hw); - } else if (dec_dpb_status == H264_PIC_DATA_DONE) { -pic_done_proc: - reset_process_time(hw); - - if (input_frame_based(vdec) && - frmbase_cont_bitlevel != 0 && - READ_VREG(VIFF_BIT_CNT) > - frmbase_cont_bitlevel) { - /*handle the case: multi pictures in one packet*/ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", - __func__, - hw->decode_pic_count, - READ_VREG(VIFF_BIT_CNT)); - hw->frmbase_cont_flag = 1; - } else - hw->frmbase_cont_flag = 0; - - if (p_H264_Dpb->mVideo.dec_picture) { - get_picture_qos_info(p_H264_Dpb->mVideo.dec_picture); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - DEL_EXIST(hw, - p_H264_Dpb->mVideo.dec_picture) = 0; - if (vdec->master) { - struct vdec_h264_hw_s *hw_ba = - (struct vdec_h264_hw_s *) - vdec->master->private; - if (hw_ba->last_dec_picture) - DEL_EXIST(hw_ba, - hw_ba->last_dec_picture) - = 1; - } -#endif - mutex_lock(&hw->chunks_mutex); - if (hw->chunk) { - p_H264_Dpb->mVideo.dec_picture->pts = - hw->chunk->pts; - p_H264_Dpb->mVideo.dec_picture->pts64 = - hw->chunk->pts64; - p_H264_Dpb->mVideo.dec_picture->timestamp = - hw->chunk->timestamp; -#ifdef MH264_USERDATA_ENABLE - vmh264_udc_fill_vpts(hw, - p_H264_Dpb->mSlice.slice_type, - hw->chunk->pts, 1); -#endif - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - } else if (vdec->master) { - /*dv enhance layer, - do not checkout pts*/ - struct StorablePicture *pic = - p_H264_Dpb->mVideo.dec_picture; - pic->pts = 0; - pic->pts64 = 0; -#endif - } else { - struct StorablePicture *pic = - p_H264_Dpb->mVideo.dec_picture; - u32 offset = pic->offset_delimiter_lo | - (pic->offset_delimiter_hi << 16); - if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, - offset, &pic->pts, &pic->frame_size, - 0, &pic->pts64)) { - pic->pts = 0; - pic->pts64 = 0; -#ifdef MH264_USERDATA_ENABLE - vmh264_udc_fill_vpts(hw, - p_H264_Dpb->mSlice.slice_type, - pic->pts, 0); -#endif - } else { -#ifdef MH264_USERDATA_ENABLE - vmh264_udc_fill_vpts(hw, - p_H264_Dpb->mSlice.slice_type, - pic->pts, 1); -#endif - } - } - mutex_unlock(&hw->chunks_mutex); - check_decoded_pic_error(hw); -#ifdef ERROR_HANDLE_TEST - if ((hw->data_flag & ERROR_FLAG) - && (error_proc_policy & 0x80)) { - release_cur_decoding_buf(hw); - h264_clear_dpb(hw); - hw->dec_flag = 0; - hw->data_flag = 0; - hw->skip_frame_count = 0; - hw->has_i_frame = 0; - hw->no_error_count = 0xfff; - hw->no_error_i_count = 0xf; - } else -#endif - ret = store_picture_in_dpb(p_H264_Dpb, - p_H264_Dpb->mVideo.dec_picture, - hw->data_flag | hw->dec_flag | - p_H264_Dpb->mVideo.dec_picture->data_flag); - - - - if (ret == -1) { - release_cur_decoding_buf(hw); - bufmgr_force_recover(p_H264_Dpb); - } else { - if (hw->data_flag & ERROR_FLAG) { - hw->no_error_count = 0; - hw->no_error_i_count = 0; - } else { - hw->no_error_count++; - if (hw->data_flag & I_FLAG) - hw->no_error_i_count++; - } - if (hw->mmu_enable) - hevc_set_unused_4k_buff_idx(hw, - p_H264_Dpb->mVideo. - dec_picture->buf_spec_num); - bufmgr_post(p_H264_Dpb); - hw->last_dec_picture = - p_H264_Dpb->mVideo.dec_picture; - p_H264_Dpb->mVideo.dec_picture = NULL; - /* dump_dpb(&p_H264_Dpb->mDPB); */ - hw->has_i_frame = 1; - if (hw->mmu_enable) - hevc_set_frame_done(hw); - hw->decode_pic_count++; - p_H264_Dpb->decode_pic_count = hw->decode_pic_count; - if (hw->skip_frame_count > 0) { - /*skip n frame after first I */ - hw->skip_frame_count--; - if (hw->skip_frame_count == 0) - hw->dec_flag &= (~NODISP_FLAG); - } else if (hw->skip_frame_count < -1) { - /*skip n frame after first I until second I */ - hw->skip_frame_count++; - if (hw->skip_frame_count == -1) - hw->dec_flag &= (~NODISP_FLAG); - } - } - } - if (hw->frmbase_cont_flag) { - /*do not DEC_RESULT_GET_DATA*/ - hw->get_data_count = 0x7fffffff; - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); - decode_frame_count[DECODE_ID(hw)]++; - start_process_time(hw); - return IRQ_HANDLED; - } - amvdec_stop(); - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s %s decode slice count %d\n", - __func__, - (dec_dpb_status == H264_PIC_DATA_DONE) ? - "H264_PIC_DATA_DONE" : - (dec_dpb_status == H264_FIND_NEXT_PIC_NAL) ? - "H264_FIND_NEXT_PIC_NAL" : "H264_FIND_NEXT_DVEL_NAL", - hw->decode_pic_count); - /* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); */ - hw->dec_result = DEC_RESULT_DONE; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->slave && - dec_dpb_status == H264_FIND_NEXT_DVEL_NAL) { - struct vdec_h264_hw_s *hw_el = - (struct vdec_h264_hw_s *)(vdec->slave->private); - hw_el->got_valid_nal = 0; - hw->switch_dvlayer_flag = 1; - } else if (vdec->master && - dec_dpb_status == H264_FIND_NEXT_PIC_NAL) { - struct vdec_h264_hw_s *hw_bl = - (struct vdec_h264_hw_s *)(vdec->master->private); - hw_bl->got_valid_nal = 0; - hw->switch_dvlayer_flag = 1; - } else { - hw->switch_dvlayer_flag = 0; - hw->got_valid_nal = 1; - } -#endif - if (!hw->wait_for_udr_send) { - hw->dec_result = DEC_RESULT_DONE; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s wait_for_udr_send\n", __func__); - vdec_schedule_work(&hw->work); - } -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - } else if ( - (dec_dpb_status == H264_FIND_NEXT_PIC_NAL) || - (dec_dpb_status == H264_FIND_NEXT_DVEL_NAL)) { - goto pic_done_proc; -#endif - } else if (dec_dpb_status == H264_AUX_DATA_READY) { - reset_process_time(hw); - if (READ_VREG(H264_AUX_DATA_SIZE) != 0) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL)) - dump_aux_buf(hw); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->dolby_meta_with_el || vdec->slave) { - if (hw->last_dec_picture) - set_aux_data(hw, hw->last_dec_picture, - 0, 0, NULL); - } else { - if (vdec->master) { - struct vdec_h264_hw_s *hw_bl = - (struct vdec_h264_hw_s *) - (vdec->master->private); - if (hw_bl->last_dec_picture != NULL) { - set_aux_data(hw_bl, - hw_bl->last_dec_picture, - 0, 1, hw); - } - set_aux_data(hw, - hw->last_dec_picture, - 0, 2, NULL); - } - } -#else - if (hw->last_dec_picture) - set_aux_data(hw, - hw->last_dec_picture, 0, 0, NULL); -#endif - } -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - hw->switch_dvlayer_flag = 0; - hw->got_valid_nal = 1; -#endif - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s H264_AUX_DATA_READY\n", __func__); - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - } else if (/*(dec_dpb_status == H264_DATA_REQUEST) ||*/ - (dec_dpb_status == H264_SEARCH_BUFEMPTY) || - (dec_dpb_status == H264_DECODE_BUFEMPTY) || - (dec_dpb_status == H264_DECODE_TIMEOUT)) { -empty_proc: - reset_process_time(hw); - if (!hw->frmbase_cont_flag) - release_cur_decoding_buf(hw); - - if (input_frame_based(vdec) || - (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x200)) { - if (h264_debug_flag & - DISABLE_ERROR_HANDLE) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_ERROR, - "%s decoding error, level 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - goto send_again; - } - amvdec_stop(); - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s %s\n", __func__, - (dec_dpb_status == H264_SEARCH_BUFEMPTY) ? - "H264_SEARCH_BUFEMPTY" : - (dec_dpb_status == H264_DECODE_BUFEMPTY) ? - "H264_DECODE_BUFEMPTY" : - (dec_dpb_status == H264_DECODE_TIMEOUT) ? - "H264_DECODE_TIMEOUT" : - "OTHER"); - hw->dec_result = DEC_RESULT_DONE; - - if (dec_dpb_status == H264_SEARCH_BUFEMPTY) - hw->search_dataempty_num++; - else if (dec_dpb_status == H264_DECODE_TIMEOUT) - hw->decode_timeout_num++; - else if (dec_dpb_status == H264_DECODE_BUFEMPTY) - hw->decode_dataempty_num++; - if (!hw->frmbase_cont_flag) - hw->data_flag |= ERROR_FLAG; - - vdec_schedule_work(&hw->work); - } else { - /* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_INIT); */ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_AGAIN\n", __func__); -send_again: - hw->dec_result = DEC_RESULT_AGAIN; - vdec_schedule_work(&hw->work); - } - } else if (dec_dpb_status == H264_DATA_REQUEST) { - reset_process_time(hw); - if (input_frame_based(vdec)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_VDEC_STATUS, - "%s H264_DATA_REQUEST (%d)\n", - __func__, hw->get_data_count); - hw->dec_result = DEC_RESULT_GET_DATA; - hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); - hw->get_data_start_time = jiffies; - hw->get_data_count++; - if (hw->get_data_count >= frame_max_data_packet) - goto empty_proc; - vdec_schedule_work(&hw->work); - } else - goto empty_proc; - } else if (dec_dpb_status == H264_DECODE_OVER_SIZE) { - dpb_print(DECODE_ID(hw), 0, - "vmh264 decode oversize !!\n"); - release_cur_decoding_buf(hw); - hw->data_flag |= ERROR_FLAG; - hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - reset_process_time(hw); - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } else if (dec_dpb_status == H264_SEI_DATA_READY) { - int aux_data_len; - aux_data_len = - (READ_VREG(H264_AUX_DATA_SIZE) >> 16) << 4; - - if (aux_data_len > SEI_DATA_SIZE) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "sei data size more than 4K: %d, discarded it\n", - hw->sei_itu_data_len); - hw->sei_itu_data_len = 0; - } - - if (aux_data_len != 0) { - u8 *trans_data_buf; - u8 *sei_data_buf; - u8 swap_byte; - - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); -#if 0 - dump_aux_buf(hw); -#endif - trans_data_buf = (u8 *)hw->aux_addr; - - if (trans_data_buf[7] == AUX_TAG_SEI) { - int left_len; - - sei_data_buf = (u8 *)hw->sei_data_buf - + hw->sei_data_len; - left_len = SEI_DATA_SIZE - hw->sei_data_len; - if (aux_data_len/2 <= left_len) { - for (i = 0; i < aux_data_len/2; i++) - sei_data_buf[i] - = trans_data_buf[i*2]; - - aux_data_len = aux_data_len / 2; - for (i = 0; i < aux_data_len; i = i+4) { - swap_byte = sei_data_buf[i]; - sei_data_buf[i] - = sei_data_buf[i+3]; - sei_data_buf[i+3] = swap_byte; - - swap_byte = sei_data_buf[i+1]; - sei_data_buf[i+1] - = sei_data_buf[i+2]; - sei_data_buf[i+2] = swap_byte; - } - - for (i = aux_data_len-1; i >= 0; i--) - if (sei_data_buf[i] != 0) - break; - - hw->sei_data_len += i+1; - } else - dpb_print(DECODE_ID(hw), - PRINT_FLAG_ERROR, - "sei data size %d and more than left space: %d, discarded it\n", - hw->sei_itu_data_len, - left_len); - } - } - WRITE_VREG(DPB_STATUS_REG, H264_SEI_DATA_DONE); - - return IRQ_HANDLED; - } - - - /* ucode debug */ - debug_tag = READ_VREG(DEBUG_REG1); - if (debug_tag & 0x10000) { - unsigned short *p = (unsigned short *)hw->lmem_addr; - - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, - DMA_FROM_DEVICE); - - dpb_print(DECODE_ID(hw), 0, - "LMEM:\n", debug_tag); - for (i = 0; i < 0x400; i += 4) { - int ii; - if ((i & 0xf) == 0) - dpb_print_cont(DECODE_ID(hw), 0, - "%03x: ", i); - for (ii = 0; ii < 4; ii++) - dpb_print_cont(DECODE_ID(hw), 0, - "%04x ", p[i+3-ii]); - if (((i+ii) & 0xf) == 0) - dpb_print_cont(DECODE_ID(hw), 0, - "\n"); - } - if (((udebug_pause_pos & 0xffff) - == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == - hw->decode_pic_count) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_VREG(DEBUG_REG2))) { - udebug_pause_pos &= 0xffff; - hw->ucode_pause_pos = udebug_pause_pos; - } - else if (debug_tag & 0x20000) - hw->ucode_pause_pos = 0xffffffff; - if (hw->ucode_pause_pos) - reset_process_time(hw); - else - WRITE_VREG(DEBUG_REG1, 0); - } else if (debug_tag != 0) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT, - "dbg%x: %x\n", debug_tag, - READ_VREG(DEBUG_REG2)); - if (((udebug_pause_pos & 0xffff) - == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == - hw->decode_pic_count) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_VREG(DEBUG_REG2))) { - udebug_pause_pos &= 0xffff; - hw->ucode_pause_pos = udebug_pause_pos; - } - if (hw->ucode_pause_pos) - reset_process_time(hw); - else - WRITE_VREG(DEBUG_REG1, 0); - } - /**/ - return IRQ_HANDLED; -} - -static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq) -{ - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private); - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - if (!hw) - return IRQ_HANDLED; - - if (hw->eos) - return IRQ_HANDLED; - - p_H264_Dpb->vdec = vdec; - p_H264_Dpb->dec_dpb_status = READ_VREG(DPB_STATUS_REG); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT, - "%s DPB_STATUS_REG: 0x%x, ERROR_STATUS_REG 0x%x, sb (0x%x 0x%x 0x%x) bitcnt 0x%x mby_mbx 0x%x\n", - __func__, - p_H264_Dpb->dec_dpb_status, - READ_VREG(ERROR_STATUS_REG), - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VIFF_BIT_CNT), - READ_VREG(MBY_MBX)); - - if (p_H264_Dpb->dec_dpb_status == H264_WRRSP_REQUEST) { - if (hw->mmu_enable) - hevc_sao_wait_done(hw); - WRITE_VREG(DPB_STATUS_REG, H264_WRRSP_DONE); - return IRQ_HANDLED; - } - return IRQ_WAKE_THREAD; - -} - -static void timeout_process(struct vdec_h264_hw_s *hw) -{ - hw->timeout_num++; - amvdec_stop(); - if (hw->mmu_enable) { - hevc_set_frame_done(hw); - hevc_sao_wait_done(hw); - } - dpb_print(DECODE_ID(hw), - PRINT_FLAG_ERROR, "%s decoder timeout\n", __func__); - release_cur_decoding_buf(hw); - hw->dec_result = DEC_RESULT_DONE; - hw->data_flag |= ERROR_FLAG; - reset_process_time(hw); - vdec_schedule_work(&hw->work); -} - -static void dump_bufspec(struct vdec_h264_hw_s *hw, - const char *caller) -{ - int i; - dpb_print(DECODE_ID(hw), 0, - "%s in %s:\n", __func__, caller); - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - if (hw->buffer_spec[i].used == -1) - continue; - dpb_print(DECODE_ID(hw), 0, - "bufspec (%d): used %d adr 0x%x canvas(%d) vf_ref(%d) ", - i, hw->buffer_spec[i].used, - hw->buffer_spec[i].buf_adr, - hw->buffer_spec[i].canvas_pos, - hw->buffer_spec[i].vf_ref - ); -#ifdef CONFIG_AM_VDEC_DV - dpb_print_cont(DECODE_ID(hw), 0, - "dv_el_exist %d", - hw->buffer_spec[i].dv_enhance_exist - ); -#endif - dpb_print_cont(DECODE_ID(hw), 0, "\n"); - } - -} - -static void vmh264_dump_state(struct vdec_s *vdec) -{ - struct vdec_h264_hw_s *hw = - (struct vdec_h264_hw_s *)(vdec->private); - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - dpb_print(DECODE_ID(hw), 0, - "====== %s\n", __func__); - dpb_print(DECODE_ID(hw), 0, - "width/height (%d/%d), reorder_pic_num %d dpb size(bufspec count) %d max_reference_size(collocate count) %d i_only %d send_err %d\n", - hw->frame_width, - hw->frame_height, - hw->dpb.reorder_pic_num, - hw->dpb.mDPB.size, - hw->max_reference_size, - hw->i_only, - hw->send_error_frame_flag - ); - - dpb_print(DECODE_ID(hw), 0, - "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d bufmgr_reset_cnt %d\n", - input_frame_based(vdec), - hw->eos, - hw->stat, - hw->dec_result, - decode_frame_count[DECODE_ID(hw)], - display_frame_count[DECODE_ID(hw)], - run_count[DECODE_ID(hw)], - not_run_ready[DECODE_ID(hw)], - input_empty[DECODE_ID(hw)], - hw->reset_bufmgr_count - ); - - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - dpb_print(DECODE_ID(hw), 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - - dpb_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x\n", - __func__, - kfifo_len(&hw->newframe_q), - VF_POOL_SIZE, - kfifo_len(&hw->display_q), - VF_POOL_SIZE, - hw->vf_pre_count, - hw->vf_get_count, - hw->vf_put_count, - have_free_buf_spec(vdec), - p_H264_Dpb->mDPB.init_done, - p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, - is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB), - p_H264_Dpb->fast_output_enable - ); - - dump_dpb(&p_H264_Dpb->mDPB, 1); - dump_pic(p_H264_Dpb); - dump_bufspec(hw, __func__); - - dpb_print(DECODE_ID(hw), 0, - "DPB_STATUS_REG=0x%x\n", - READ_VREG(DPB_STATUS_REG)); - dpb_print(DECODE_ID(hw), 0, - "MPC_E=0x%x\n", - READ_VREG(MPC_E)); - dpb_print(DECODE_ID(hw), 0, - "H264_DECODE_MODE=0x%x\n", - READ_VREG(H264_DECODE_MODE)); - dpb_print(DECODE_ID(hw), 0, - "MBY_MBX=0x%x\n", - READ_VREG(MBY_MBX)); - dpb_print(DECODE_ID(hw), 0, - "H264_DECODE_SIZE=0x%x\n", - READ_VREG(H264_DECODE_SIZE)); - dpb_print(DECODE_ID(hw), 0, - "VIFF_BIT_CNT=0x%x\n", - READ_VREG(VIFF_BIT_CNT)); - dpb_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_LEVEL=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - dpb_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_WP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_WP)); - dpb_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_RP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_RP)); - dpb_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - dpb_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - - if (input_frame_based(vdec) && - dpb_is_debug(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA) - ) { - int jj; - if (hw->chunk && hw->chunk->block && - hw->chunk->size > 0) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, hw->chunk->size); - else - data = ((u8 *)hw->chunk->block->start_virt) - + hw->chunk->offset; - - dpb_print(DECODE_ID(hw), 0, - "frame data size 0x%x\n", - hw->chunk->size); - for (jj = 0; jj < hw->chunk->size; jj++) { - if ((jj & 0xf) == 0) - dpb_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - dpb_print_cont(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - dpb_print_cont(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } -} - - -static void check_timer_func(unsigned long arg) -{ - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)arg; - struct vdec_s *vdec = hw_to_vdec(hw); - int error_skip_frame_count = error_skip_count & 0xfff; - unsigned int timeout_val = decode_timeout_val; - if (timeout_val != 0 && - hw->no_error_count < error_skip_frame_count) - timeout_val = errordata_timeout_val; - if ((h264_debug_cmd & 0x100) != 0 && - DECODE_ID(hw) == (h264_debug_cmd & 0xff)) { - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - pr_info("vdec %d is forced to be disconnected\n", - h264_debug_cmd & 0xff); - h264_debug_cmd = 0; - return; - } - if ((h264_debug_cmd & 0x200) != 0 && - DECODE_ID(hw) == (h264_debug_cmd & 0xff)) { - pr_debug("vdec %d is forced to reset bufmgr\n", - h264_debug_cmd & 0xff); - hw->reset_bufmgr_flag = 1; - h264_debug_cmd = 0; - return; - } - - if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - pr_debug("vdec requested to be disconnected\n"); - return; - } - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - - if ((input_frame_based(vdec) || - (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0xb0)) && - ((h264_debug_flag & DISABLE_ERROR_HANDLE) == 0) && - (timeout_val > 0) && - (hw->start_process_time > 0) && - ((1000 * (jiffies - hw->start_process_time) / HZ) - > timeout_val) - ) { - u32 dpb_status = READ_VREG(DPB_STATUS_REG); - u32 mby_mbx = READ_VREG(MBY_MBX); - if ((dpb_status == H264_ACTION_DECODE_NEWPIC) || - (dpb_status == H264_ACTION_DECODE_SLICE)) { - if (hw->last_mby_mbx == mby_mbx) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); - } else - start_process_time(hw); - } else if (is_in_parsing_state(dpb_status)) { - if (hw->last_vld_level == - READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); - } - } - hw->last_vld_level = - READ_VREG(VLD_MEM_VIFIFO_LEVEL); - hw->last_mby_mbx = mby_mbx; - } - - if ((hw->ucode_pause_pos != 0) && - (hw->ucode_pause_pos != 0xffffffff) && - udebug_pause_pos != hw->ucode_pause_pos) { - hw->ucode_pause_pos = 0; - WRITE_VREG(DEBUG_REG1, 0); - } - - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -} - -static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - u32 ar; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; - - if (!hw) - return -1; - - vstatus->frame_width = hw->frame_width; - vstatus->frame_height = hw->frame_height; - if (hw->frame_dur != 0) - vstatus->frame_rate = 96000 / hw->frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = 0; - vstatus->status = hw->stat; - ar = min_t(u32, - hw->h264_ar, - DISP_RATIO_ASPECT_RATIO_MAX); - vstatus->ratio_control = - ar << DISP_RATIO_ASPECT_RATIO_BIT; - - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s-%02d", DRIVER_NAME, hw->id); - - return 0; -} - -static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) -{ - int i, j; - - /* if (hw->init_flag == 0) { */ - if (h264_debug_flag & 0x40000000) { - /* if (1) */ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s, reset register\n", __func__); - - while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) - ; - while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) - ; /* reg address is 0x350 */ - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1<<9) | (1<<8)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - -#else - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - READ_RESET_REG(RESET0_REGISTER); - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - - WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); -#endif - WRITE_VREG(POWER_CTL_VLD, - READ_VREG(POWER_CTL_VLD) | (0 << 10) | - (1 << 9) | (1 << 6)); - } else { - /* WRITE_VREG(POWER_CTL_VLD, - * READ_VREG(POWER_CTL_VLD) | (0 << 10) | (1 << 9) ); - */ - WRITE_VREG(POWER_CTL_VLD, - READ_VREG(POWER_CTL_VLD) | - (0 << 10) | (1 << 9) | (1 << 6)); - } - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); -#endif - - /* cbcr_merge_swap_en */ - if (hw->is_used_v4l) - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); - - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); - - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); - if (hw->mmu_enable) { - SET_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1<<31); - /* sw reset to extif hardware */ - SET_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30); - CLEAR_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30); - } else { - CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31); - WRITE_VREG(MDEC_EXTIF_CFG1, 0); - } - - -#if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - /* pr_info("vh264 meson8 prot init\n"); */ - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); -#endif - -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) { - u32 data = ((1 << 30) |(1 << 0) |(1 << 8)); - - if (IS_VDEC_DW(hw) == 2) - data |= (1 << 9); - WRITE_VREG(MDEC_DOUBLEW_CFG0, data); /* Double Write Enable*/ - } -#endif - if (hw->dpb.mDPB.size > 0) { - WRITE_VREG(AV_SCRATCH_7, (hw->max_reference_size << 24) | - (hw->dpb.mDPB.size << 16) | - (hw->dpb.mDPB.size << 8)); - - for (j = 0; j < hw->dpb.mDPB.size; j++) { - i = get_buf_spec_by_canvas_pos(hw, j); - if (i < 0) - break; - - if (!hw->mmu_enable && - hw->buffer_spec[i].cma_alloc_addr) - config_decode_canvas(hw, i); - if (hw->mmu_enable && hw->double_write_mode) - config_decode_canvas_ex(hw, i); - } - } else { - WRITE_VREG(AV_SCRATCH_0, 0); - WRITE_VREG(AV_SCRATCH_9, 0); - } - - if (hw->init_flag == 0) - WRITE_VREG(DPB_STATUS_REG, 0); - else - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_START); - - WRITE_VREG(FRAME_COUNTER_REG, hw->decode_pic_count); - WRITE_VREG(AV_SCRATCH_8, hw->buf_offset); - if (!tee_enabled()) - WRITE_VREG(AV_SCRATCH_G, hw->mc_dma_handle); - - /* hw->error_recovery_mode = (error_recovery_mode != 0) ? - * error_recovery_mode : error_recovery_mode_in; - */ - /* WRITE_VREG(AV_SCRATCH_F, - * (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) ); - */ - WRITE_VREG(AV_SCRATCH_F, (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) | - ((error_recovery_mode_in & 0x1) << 4)); - /*if (hw->ucode_type == UCODE_IP_ONLY_PARAM) - SET_VREG_MASK(AV_SCRATCH_F, 1 << 6); - else*/ - CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6); - - WRITE_VREG(LMEM_DUMP_ADR, (u32)hw->lmem_addr_remap); -#if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); -#endif - - WRITE_VREG(DEBUG_REG1, 0); - WRITE_VREG(DEBUG_REG2, 0); - - if (hw->reg_iqidct_control) - WRITE_VREG(IQIDCT_CONTROL, hw->reg_iqidct_control); - if (hw->reg_vcop_ctrl_reg) - WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg); - if (hw->vld_dec_control) - WRITE_VREG(VLD_DECODE_CONTROL, hw->vld_dec_control); - return 0; -} - -static int vmh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) -{ - struct vdec_h264_hw_s *hw = - (struct vdec_h264_hw_s *)vdec->private; - if (i_only_flag & 0x100) - return 0; - if (trickmode == TRICKMODE_I) - hw->i_only = 0x3; - else if (trickmode == TRICKMODE_NONE) - hw->i_only = 0x0; - return 0; -} - -static unsigned char amvdec_enable_flag; -static void vh264_local_init(struct vdec_h264_hw_s *hw) -{ - int i; - hw->init_flag = 0; - hw->first_sc_checked= 0; - hw->eos = 0; - hw->valve_count = 0; - hw->config_bufmgr_done = 0; - hw->start_process_time = 0; - hw->has_i_frame = 0; - hw->no_error_count = 0xfff; - hw->no_error_i_count = 0xf; - - hw->dec_flag = 0; - hw->data_flag = 0; - hw->skip_frame_count = 0; - hw->reg_iqidct_control = 0; - hw->reg_vcop_ctrl_reg = 0; - hw->reg_rv_ai_mb_count = 0; - hw->vld_dec_control = 0; - hw->decode_timeout_count = 0; - hw->no_mem_count = 0; - hw->vh264_ratio = hw->vh264_amstream_dec_info.ratio; - /* vh264_ratio = 0x100; */ - - hw->vh264_rotation = (((unsigned long) - hw->vh264_amstream_dec_info.param) >> 16) & 0xffff; - - hw->frame_prog = 0; - hw->frame_width = hw->vh264_amstream_dec_info.width; - hw->frame_height = hw->vh264_amstream_dec_info.height; - hw->frame_dur = hw->vh264_amstream_dec_info.rate; - hw->pts_outside = ((unsigned long) - hw->vh264_amstream_dec_info.param) & 0x01; - hw->sync_outside = ((unsigned long) - hw->vh264_amstream_dec_info.param & 0x02) >> 1; - hw->use_idr_framerate = ((unsigned long) - hw->vh264_amstream_dec_info.param & 0x04) >> 2; - hw->max_refer_buf = !(((unsigned long) - hw->vh264_amstream_dec_info.param & 0x10) >> 4); - if (hw->frame_dur < 96000/960) { - /*more than 960fps,it should not be a correct value, - *give default 30fps - */ - hw->frame_dur = 96000/30; - } - - hw->unstable_pts = (((unsigned long) hw->vh264_amstream_dec_info.param & 0x40) >> 6); - - hw->is_used_v4l = (((unsigned long) - hw->vh264_amstream_dec_info.param & 0x80) >> 7); - - if (hw->is_used_v4l) - mem_map_mode = CANVAS_BLKMODE_LINEAR; - - pr_info("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n", - hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); - pr_debug("sync_outside=%d, use_idr_framerate=%d, is_used_v4l: %d\n", - hw->sync_outside, hw->use_idr_framerate, hw->is_used_v4l); - - if (i_only_flag & 0x100) - hw->i_only = i_only_flag & 0xff; - if (hw->i_only) - hw->dpb.first_insert_frame = FirstInsertFrm_SKIPDONE; - - if ((unsigned long) hw->vh264_amstream_dec_info.param - & 0x08) - hw->no_poc_reorder_flag = 1; - - error_recovery_mode_in = 1; /*ucode control?*/ - if (error_proc_policy & 0x80000000) - hw->send_error_frame_flag = error_proc_policy & 0x1; - else if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x20) - hw->send_error_frame_flag = 1; - - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - hw->vfpool[hw->cur_pool][i].bufWidth = 1920; - kfifo_put(&hw->newframe_q, vf); - } - - hw->duration_from_pts_done = 0; - - hw->p_last_vf = NULL; - hw->vh264_stream_switching_state = SWITCHING_STATE_OFF; - hw->hevc_cur_buf_idx = 0xffff; - - init_waitqueue_head(&hw->wait_q); - - return; -} - -static s32 vh264_init(struct vdec_h264_hw_s *hw) -{ - int size = -1; - int fw_size = 0x1000 * 16; - int fw_mmu_size = 0x1000 * 16; - struct firmware_s *fw = NULL, *fw_mmu = NULL; - - /* int trickmode_fffb = 0; */ - - /* pr_info("\nvh264_init\n"); */ - /* init_timer(&hw->recycle_timer); */ - - /* timer init */ - init_timer(&hw->check_timer); - - hw->check_timer.data = (unsigned long)hw; - hw->check_timer.function = check_timer_func; - hw->check_timer.expires = jiffies + CHECK_INTERVAL; - - /* add_timer(&hw->check_timer); */ - hw->stat |= STAT_TIMER_ARM; - hw->stat |= STAT_ISR_REG; - - mutex_init(&hw->chunks_mutex); - vh264_local_init(hw); - INIT_WORK(&hw->work, vh264_work); - INIT_WORK(&hw->notify_work, vh264_notify_work); -#ifdef MH264_USERDATA_ENABLE - INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work); -#endif - - if (!amvdec_enable_flag) { - amvdec_enable_flag = true; - amvdec_enable(); - if (hw->mmu_enable) - amhevc_enable(); - } - if (hw->mmu_enable) { - - hw->frame_mmu_map_addr = - dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, - &hw->frame_mmu_map_phy_addr, GFP_KERNEL); - if (hw->frame_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -ENOMEM; - } - } - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_H264_MULTI, fw->data); - if (size < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = size; - hw->fw = fw; - - if (hw->mmu_enable) { - fw_mmu = vmalloc(sizeof(struct firmware_s) + fw_mmu_size); - if (IS_ERR_OR_NULL(fw_mmu)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_H264_MULTI_MMU, fw_mmu->data); - if (size < 0) { - pr_err("get mmu fw fail.\n"); - vfree(fw_mmu); - return -1; - } - - fw_mmu->len = size; - hw->fw_mmu = fw_mmu; - } - - if (!tee_enabled()) { - /* -- ucode loading (amrisc and swap code) */ - hw->mc_cpu_addr = - dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, - &hw->mc_dma_handle, GFP_KERNEL); - if (!hw->mc_cpu_addr) { - amvdec_enable_flag = false; - amvdec_disable(); - if (hw->mmu_enable) - amhevc_disable(); - pr_info("vh264_init: Can not allocate mc memory.\n"); - return -ENOMEM; - } - - /*pr_info("264 ucode swap area: phyaddr %p, cpu vaddr %p\n", - (void *)hw->mc_dma_handle, hw->mc_cpu_addr); - */ - - /*ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf);*/ - - /*header*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_HEADER, - fw->data + 0x4000, MC_SWAP_SIZE); - /*data*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_DATA, - fw->data + 0x2000, MC_SWAP_SIZE); - /*mmco*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MMCO, - fw->data + 0x6000, MC_SWAP_SIZE); - /*list*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_LIST, - fw->data + 0x3000, MC_SWAP_SIZE); - /*slice*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_SLICE, - fw->data + 0x5000, MC_SWAP_SIZE); - /*main*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN, - fw->data, 0x2000); - /*data*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x2000, - fw->data + 0x2000, 0x1000); - /*slice*/ - memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x3000, - fw->data + 0x5000, 0x1000); - } - -#if 1 /* #ifdef BUFFER_MGR_IN_C */ - hw->lmem_addr = __get_free_page(GFP_KERNEL); - if (!hw->lmem_addr) { - pr_info("%s: failed to alloc lmem_addr\n", __func__); - return -ENOMEM; - } else { - hw->lmem_addr_remap = dma_map_single( - amports_get_dma_device(), - (void *)hw->lmem_addr, - PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hw->lmem_addr_remap)) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s: failed to map lmem_addr\n", __func__); - free_page(hw->lmem_addr); - hw->lmem_addr = 0; - hw->lmem_addr_remap = 0; - return -ENOMEM; - } - - pr_debug("%s, vaddr=%lx phy_addr=%p\n", - __func__, hw->lmem_addr, (void *)hw->lmem_addr_remap); - } - - if (prefix_aux_buf_size > 0 || - suffix_aux_buf_size > 0) { - u32 aux_buf_size; - hw->prefix_aux_size = AUX_BUF_ALIGN(prefix_aux_buf_size); - hw->suffix_aux_size = AUX_BUF_ALIGN(suffix_aux_buf_size); - aux_buf_size = hw->prefix_aux_size + hw->suffix_aux_size; - hw->aux_addr = kmalloc(aux_buf_size, GFP_KERNEL); - if (hw->aux_addr == NULL) { - pr_err("%s: failed to alloc rpm buffer\n", __func__); - return -1; - } - - hw->aux_phy_addr = dma_map_single(amports_get_dma_device(), - hw->aux_addr, aux_buf_size, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hw->aux_phy_addr)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(hw->aux_addr); - hw->aux_addr = NULL; - return -1; - } - hw->sei_data_buf = kmalloc(SEI_DATA_SIZE, GFP_KERNEL); - if (hw->sei_data_buf == NULL) { - pr_err("%s: failed to alloc sei itu data buffer\n", - __func__); - return -1; - } - hw->sei_itu_data_buf = kmalloc(SEI_ITU_DATA_SIZE, GFP_KERNEL); - if (hw->sei_itu_data_buf == NULL) { - pr_err("%s: failed to alloc sei itu data buffer\n", - __func__); - kfree(hw->aux_addr); - hw->aux_addr = NULL; - kfree(hw->sei_data_buf); - hw->sei_data_buf = NULL; - - return -1; - } - - if (NULL == hw->sei_user_data_buffer) { - hw->sei_user_data_buffer = kmalloc(USER_DATA_SIZE, - GFP_KERNEL); - if (!hw->sei_user_data_buffer) { - pr_info("%s: Can not allocate sei_data_buffer\n", - __func__); - kfree(hw->aux_addr); - hw->aux_addr = NULL; - kfree(hw->sei_data_buf); - hw->sei_data_buf = NULL; - kfree(hw->sei_itu_data_buf); - hw->sei_itu_data_buf = NULL; - - return -1; - } - hw->sei_user_data_wp = 0; - } - } -/* BUFFER_MGR_IN_C */ -#endif - hw->stat |= STAT_MC_LOAD; - - /* add memory barrier */ - wmb(); - - return 0; -} - -static int vh264_stop(struct vdec_h264_hw_s *hw) -{ - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } -#ifdef VDEC_DW - WRITE_VREG(MDEC_DOUBLEW_CFG0, 0); -#endif - cancel_work_sync(&hw->work); - cancel_work_sync(&hw->notify_work); -#ifdef MH264_USERDATA_ENABLE - cancel_work_sync(&hw->user_data_ready_work); -#endif - - if (hw->stat & STAT_MC_LOAD) { - if (hw->mc_cpu_addr != NULL) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, hw->mc_cpu_addr, - hw->mc_dma_handle); - hw->mc_cpu_addr = NULL; - } - if (hw->frame_mmu_map_addr != NULL) { - dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, hw->frame_mmu_map_addr, - hw->frame_mmu_map_phy_addr); - hw->frame_mmu_map_addr = NULL; - } - - } - if (hw->stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - if (hw->lmem_addr_remap) { - dma_unmap_single(amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, DMA_FROM_DEVICE); - hw->lmem_addr_remap = 0; - } - if (hw->lmem_addr) { - free_page(hw->lmem_addr); - hw->lmem_addr = 0; - } - if (hw->aux_addr) { - dma_unmap_single(amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); - kfree(hw->aux_addr); - hw->aux_addr = NULL; - } - if (hw->sei_data_buf != NULL) { - kfree(hw->sei_data_buf); - hw->sei_data_buf = NULL; - } - if (hw->sei_itu_data_buf != NULL) { - kfree(hw->sei_itu_data_buf); - hw->sei_itu_data_buf = NULL; - } - if (hw->sei_user_data_buffer != NULL) { - kfree(hw->sei_user_data_buffer); - hw->sei_user_data_buffer = NULL; - } - /* amvdec_disable(); */ - - vfree(hw->fw); - hw->fw = NULL; - - if (hw->mmu_enable) { - vfree(hw->fw_mmu); - hw->fw_mmu = NULL; - } - - dpb_print(DECODE_ID(hw), 0, - "%s\n", - __func__); - return 0; -} - -static void wait_vmh264_search_done(struct vdec_h264_hw_s *hw) -{ - u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - int count = 0; - do { - usleep_range(100, 500); - if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) - break; - if (count > 2000) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_ERROR, "%s timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", - __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); - break; - } else - vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - count++; - } while (1); -} - -static void vh264_notify_work(struct work_struct *work) -{ - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, notify_work); - struct vdec_s *vdec = hw_to_vdec(hw); - if (vdec->fr_hint_state == VDEC_NEED_HINT) { - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)hw->frame_dur)); - vdec->fr_hint_state = VDEC_HINTED; - } - - return; -} - -#ifdef MH264_USERDATA_ENABLE -static void vmh264_reset_udr_mgr(struct vdec_h264_hw_s *hw) -{ - hw->wait_for_udr_send = 0; - hw->sei_itu_data_len = 0; - memset(&hw->ud_record, 0, sizeof(hw->ud_record)); -} - -static void vmh264_crate_userdata_manager( - struct vdec_h264_hw_s *hw, - u8 *userdata_buf, - int buf_len) -{ - if (hw) { - - - mutex_init(&hw->userdata_mutex); - - memset(&hw->userdata_info, 0, - sizeof(struct mh264_userdata_info_t)); - hw->userdata_info.data_buf = userdata_buf; - hw->userdata_info.buf_len = buf_len; - hw->userdata_info.data_buf_end = userdata_buf + buf_len; - - vmh264_reset_udr_mgr(hw); - - } -} - -static void vmh264_destroy_userdata_manager(struct vdec_h264_hw_s *hw) -{ - if (hw) - memset(&hw->userdata_info, - 0, - sizeof(struct mh264_userdata_info_t)); -} - -/* -#define DUMP_USERDATA_RECORD -*/ -#ifdef DUMP_USERDATA_RECORD - -#define MAX_USER_DATA_SIZE 3145728 -static void *user_data_buf; -static unsigned char *pbuf_start; -static int total_len; -static int bskip; -static int n_userdata_id; - -static void print_data(unsigned char *pdata, - int len, - unsigned int poc_number, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id) -{ - int nLeft; - - nLeft = len; -#if 0 - pr_info("%d len:%d, flag:%d, dur:%d, vpts:0x%x, valid:%d, poc:%d\n", - rec_id, len, flag, - duration, vpts, vpts_valid, poc_number); -#endif - pr_info("%d len = %d, flag = %d, vpts = 0x%x\n", - rec_id, len, flag, vpts); - - if (len == 96) { - int i; - nLeft = 72; - while (nLeft >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7], - pdata[8], pdata[9], pdata[10], pdata[11], - pdata[12], pdata[13], pdata[14], pdata[15]); - nLeft -= 16; - pdata += 16; - } - - - while (nLeft > 0) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } - - i = 0; - nLeft = 96-72; - while (i < nLeft) { - if (pdata[0] != 0) { - pr_info("some data error\n"); - break; - } - pdata++; - i++; - } - } else { - while (nLeft >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7], - pdata[8], pdata[9], pdata[10], pdata[11], - pdata[12], pdata[13], pdata[14], pdata[15]); - nLeft -= 16; - pdata += 16; - } - - - while (nLeft > 0) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } - - } -} - -static void push_to_buf(struct vdec_h264_hw_s *hw, - u8 *pdata, - int len, - struct userdata_meta_info_t *pmeta); - -static void dump_userdata_record(struct vdec_h264_hw_s *hw, - struct mh264_userdata_record_t *record) -{ - if (record && hw) { - u8 *pdata; - - pdata = hw->userdata_info.data_buf + record->rec_start; -/* - print_data(pdata, - record->rec_len, - record->meta_info.flags, - record->meta_info.duration, - record->meta_info.vpts, - record->meta_info.vpts_valid, - n_record_id); -*/ - push_to_buf(hw, pdata, record->rec_len, &record->meta_info); - n_userdata_id++; - } -} - - -static void push_to_buf(struct vdec_h264_hw_s *hw, - u8 *pdata, int len, - struct userdata_meta_info_t *pmeta) -{ - u32 *pLen; - int info_cnt; - u8 *pbuf_end; - - if (!user_data_buf) - return; - - if (bskip) { - pr_info("over size, skip\n"); - return; - } - info_cnt = 0; - pLen = (u32 *)pbuf_start; - - *pLen = len; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->poc_number; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->duration; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->flags; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts_valid; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - - *pLen = n_userdata_id; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - - - pbuf_end = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE; - if (pdata + len > pbuf_end) { - int first_section_len; - - first_section_len = pbuf_end - pdata; - memcpy(pbuf_start, pdata, first_section_len); - pdata = (u8 *)hw->sei_user_data_buffer; - pbuf_start += first_section_len; - memcpy(pbuf_start, pdata, len - first_section_len); - pbuf_start += len - first_section_len; - } else { - memcpy(pbuf_start, pdata, len); - pbuf_start += len; - } - - total_len += len + info_cnt * sizeof(u32); - if (total_len >= MAX_USER_DATA_SIZE-4096) - bskip = 1; -} - -static void show_user_data_buf(void) -{ - u8 *pbuf; - int len; - unsigned int flag; - unsigned int duration; - unsigned int vpts; - unsigned int vpts_valid; - unsigned int poc_number; - int rec_id; - - pr_info("show user data buf\n"); - pbuf = user_data_buf; - - while (pbuf < pbuf_start) { - u32 *pLen; - - pLen = (u32 *)pbuf; - - len = *pLen; - pLen++; - pbuf += sizeof(u32); - - poc_number = *pLen; - pLen++; - pbuf += sizeof(u32); - - duration = *pLen; - pLen++; - pbuf += sizeof(u32); - - flag = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts_valid = *pLen; - pLen++; - pbuf += sizeof(u32); - - rec_id = *pLen; - pLen++; - pbuf += sizeof(u32); - - print_data(pbuf, len, poc_number, flag, - duration, vpts, - vpts_valid, rec_id); - pbuf += len; - msleep(30); - } -} - -static int vmh264_init_userdata_dump(void) -{ - user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); - if (user_data_buf) - return 1; - else - return 0; -} - -static void vmh264_dump_userdata(void) -{ - if (user_data_buf) { - show_user_data_buf(); - kfree(user_data_buf); - user_data_buf = NULL; - } -} - -static void vmh264_reset_user_data_buf(void) -{ - total_len = 0; - pbuf_start = user_data_buf; - bskip = 0; - n_userdata_id = 0; -} -#endif - - -static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw, - int frame_type, - u32 vpts, - u32 vpts_valid) -{ - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - - unsigned char *pdata; - u8 *pmax_sei_data_buffer; - u8 *sei_data_buf; - int i; - int wp; - int data_length; - struct mh264_userdata_record_t *p_userdata_rec; - - -#ifdef MH264_USERDATA_ENABLE - struct userdata_meta_info_t meta_info; - memset(&meta_info, 0, sizeof(meta_info)); -#endif - - if (hw->sei_itu_data_len <= 0) - return; - - pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp; - pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE; - sei_data_buf = (u8 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len; i++) { - *pdata++ = sei_data_buf[i]; - if (pdata >= pmax_sei_data_buffer) - pdata = (u8 *)hw->sei_user_data_buffer; - } - - hw->sei_user_data_wp = (hw->sei_user_data_wp - + hw->sei_itu_data_len) % USER_DATA_SIZE; - hw->sei_itu_data_len = 0; - -#ifdef MH264_USERDATA_ENABLE - meta_info.duration = hw->frame_dur; - meta_info.flags |= (VFORMAT_H264 << 3); - - meta_info.vpts = vpts; - meta_info.vpts_valid = vpts_valid; - meta_info.poc_number = - p_H264_Dpb->mVideo.dec_picture->poc; - - - wp = hw->sei_user_data_wp; - - if (hw->sei_user_data_wp > hw->userdata_info.last_wp) - data_length = wp - hw->userdata_info.last_wp; - else - data_length = wp + hw->userdata_info.buf_len - - hw->userdata_info.last_wp; - - if (data_length & 0x7) - data_length = (((data_length + 8) >> 3) << 3); - - p_userdata_rec = &hw->ud_record; - p_userdata_rec->meta_info = meta_info; - p_userdata_rec->rec_start = hw->userdata_info.last_wp; - p_userdata_rec->rec_len = data_length; - hw->userdata_info.last_wp = wp; - - p_userdata_rec->meta_info.flags |= - p_H264_Dpb->mVideo.dec_picture->pic_struct << 12; - - hw->wait_for_udr_send = 1; - schedule_work(&hw->user_data_ready_work); -#endif -} - - -static void user_data_ready_notify_work(struct work_struct *work) -{ - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, user_data_ready_work); - - - mutex_lock(&hw->userdata_mutex); - - hw->userdata_info.records[hw->userdata_info.write_index] - = hw->ud_record; - hw->userdata_info.write_index++; - if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) - hw->userdata_info.write_index = 0; - - mutex_unlock(&hw->userdata_mutex); - -#ifdef DUMP_USERDATA_RECORD - dump_userdata_record(hw, &hw->ud_record); -#endif - vdec_wakeup_userdata_poll(hw_to_vdec(hw)); - - hw->wait_for_udr_send = 0; - if (!hw->frmbase_cont_flag) { - hw->dec_result = DEC_RESULT_DONE; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s\n", __func__); - - vdec_schedule_work(&hw->work); - } -} - -static int vmh264_user_data_read(struct vdec_s *vdec, - struct userdata_param_t *puserdata_para) -{ - struct vdec_h264_hw_s *hw = NULL; - int rec_ri, rec_wi; - int rec_len; - u8 *rec_data_start; - u8 *pdest_buf; - struct mh264_userdata_record_t *p_userdata_rec; - u32 data_size; - u32 res; - int copy_ok = 1; - - hw = (struct vdec_h264_hw_s *)vdec->private; - - pdest_buf = puserdata_para->pbuf_addr; - - mutex_lock(&hw->userdata_mutex); - -/* - pr_info("ri = %d, wi = %d\n", - lg_p_mpeg12_userdata_info->read_index, - lg_p_mpeg12_userdata_info->write_index); -*/ - rec_ri = hw->userdata_info.read_index; - rec_wi = hw->userdata_info.write_index; - - if (rec_ri == rec_wi) { - mutex_unlock(&hw->userdata_mutex); - return 0; - } - - p_userdata_rec = hw->userdata_info.records + rec_ri; - - rec_len = p_userdata_rec->rec_len; - rec_data_start = p_userdata_rec->rec_start + hw->userdata_info.data_buf; -/* - pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n", - p_userdata_rec->rec_len, - p_userdata_rec->rec_start, - puserdata_para->buf_len); -*/ - if (rec_len <= puserdata_para->buf_len) { - /* dvb user data buffer is enought to - copy the whole recored. */ - data_size = rec_len; - if (rec_data_start + data_size - > hw->userdata_info.data_buf_end) { - int first_section_len; - - first_section_len = hw->userdata_info.buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p1 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)hw->userdata_info.data_buf, - data_size - first_section_len); - if (res) { - pr_info("p2 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= - data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = - data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p3 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - hw->userdata_info.read_index++; - if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) - hw->userdata_info.read_index = 0; - } - } else { - /* dvb user data buffer is not enought - to copy the whole recored. */ - data_size = puserdata_para->buf_len; - if (rec_data_start + data_size - > hw->userdata_info.data_buf_end) { - int first_section_len; - - first_section_len = hw->userdata_info.buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p4 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - /* first secton copy is ok*/ - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)hw->userdata_info.data_buf, - data_size - first_section_len); - if (res) { - pr_info("p5 read not end res=%d, request=%d\n", - res, - data_size - first_section_len); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= - data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = - data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p6 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - hw->userdata_info.read_index++; - if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) - hw->userdata_info.read_index = 0; - } - - } - puserdata_para->meta_info = p_userdata_rec->meta_info; - - if (hw->userdata_info.read_index <= hw->userdata_info.write_index) - puserdata_para->meta_info.records_in_que = - hw->userdata_info.write_index - - hw->userdata_info.read_index; - else - puserdata_para->meta_info.records_in_que = - hw->userdata_info.write_index + - USERDATA_FIFO_NUM - - hw->userdata_info.read_index; - - puserdata_para->version = (0<<24|0<<16|0<<8|1); - - mutex_unlock(&hw->userdata_mutex); - - return 1; -} - -static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) -{ - struct vdec_h264_hw_s *hw = NULL; - - hw = (struct vdec_h264_hw_s *)vdec->private; - - if (hw) { - mutex_lock(&hw->userdata_mutex); - pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", - bInit, - hw->userdata_info.read_index, - hw->userdata_info.write_index); - hw->userdata_info.read_index = 0; - hw->userdata_info.write_index = 0; - - if (bInit) - hw->userdata_info.last_wp = 0; - mutex_unlock(&hw->userdata_mutex); - } -} - -static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec) -{ - amstream_wakeup_userdata_poll(vdec); -} - -#endif - - -static void vh264_work(struct work_struct *work) -{ - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, work); - struct vdec_s *vdec = hw_to_vdec(hw); - - /* finished decoding one frame or error, - * notify vdec core to switch context - */ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, - "%s dec_result %d %x %x %x\n", - __func__, - hw->dec_result, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP)); - if (!hw->mmu_enable) { - mutex_lock(&vmh264_mutex); - dealloc_buf_specs(hw, 0); - mutex_unlock(&vmh264_mutex); - } - if (hw->dec_result == DEC_RESULT_CONFIG_PARAM) { - u32 param1 = READ_VREG(AV_SCRATCH_1); - u32 param2 = READ_VREG(AV_SCRATCH_2); - u32 param3 = READ_VREG(AV_SCRATCH_6); - u32 param4 = READ_VREG(AV_SCRATCH_B); - if (vh264_set_params(hw, param1, - param2, param3, param4) < 0) - hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | - (hw->dpb.mDPB.size<<16) | - (hw->dpb.mDPB.size<<8)); - start_process_time(hw); - return; - } else - if (((hw->dec_result == DEC_RESULT_GET_DATA) || - (hw->dec_result == DEC_RESULT_GET_DATA_RETRY)) - && (hw_to_vdec(hw)->next_status != - VDEC_STATUS_DISCONNECTED)) { - if (!vdec_has_more_input(vdec)) { - hw->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hw->work); - return; - } - - if (hw->dec_result == DEC_RESULT_GET_DATA) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_GET_DATA %x %x %x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP)); - mutex_lock(&hw->chunks_mutex); - vdec_vframe_dirty(vdec, hw->chunk); - hw->chunk = NULL; - mutex_unlock(&hw->chunks_mutex); - vdec_clean_input(vdec); - } - if ((hw->dec_result == DEC_RESULT_GET_DATA_RETRY) && - ((1000 * (jiffies - hw->get_data_start_time) / HZ) - > get_data_timeout_val)) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_GET_DATA_RETRY timeout\n", - __func__); - goto result_done; - } - if (is_buffer_available(vdec)) { - int r; - int decode_size; - r = vdec_prepare_input(vdec, &hw->chunk); - if (r < 0) { - hw->dec_result = DEC_RESULT_GET_DATA_RETRY; - - dpb_print(DECODE_ID(hw), - PRINT_FLAG_VDEC_DETAIL, - "vdec_prepare_input: Insufficient data\n"); - - vdec_schedule_work(&hw->work); - return; - } - hw->dec_result = DEC_RESULT_NONE; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: chunk size 0x%x\n", - __func__, hw->chunk->size); - - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA)) { - int jj; - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap( - hw->chunk->block->start + - hw->chunk->offset, r); - else - data = ((u8 *) - hw->chunk->block->start_virt) - + hw->chunk->offset; - - for (jj = 0; jj < r; jj++) { - if ((jj & 0xf) == 0) - dpb_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - dpb_print_cont(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - dpb_print_cont(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - WRITE_VREG(POWER_CTL_VLD, - READ_VREG(POWER_CTL_VLD) | - (0 << 10) | (1 << 9) | (1 << 6)); - WRITE_VREG(H264_DECODE_INFO, (1<<13)); - decode_size = hw->chunk->size + - (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - WRITE_VREG(H264_DECODE_SIZE, decode_size); - WRITE_VREG(VIFF_BIT_CNT, decode_size * 8); - vdec_enable_input(vdec); - - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); - start_process_time(hw); - } else{ - hw->dec_result = DEC_RESULT_GET_DATA_RETRY; - vdec_schedule_work(&hw->work); - } - return; - } else if (hw->dec_result == DEC_RESULT_DONE) { - /* if (!hw->ctx_valid) - hw->ctx_valid = 1; */ -result_done: - if (hw->mmu_enable - && hw->frame_busy && hw->frame_done) { - long used_4k_num; - hevc_sao_wait_done(hw); - if (hw->hevc_cur_buf_idx != 0xffff) { - used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - if (used_4k_num >= 0) - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "release unused buf , used_4k_num %ld index %d\n", - used_4k_num, hw->hevc_cur_buf_idx); - - decoder_mmu_box_free_idx_tail( - hw->mmu_box, - hw->hevc_cur_buf_idx, - used_4k_num); - hw->hevc_cur_buf_idx = 0xffff; - } - } - decode_frame_count[DECODE_ID(hw)]++; - amvdec_stop(); - if (!vdec_is_support_4k()) { - if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) { - clk_adj_frame_count++; - if (clk_adj_frame_count == VDEC_CLOCK_ADJUST_FRAME) - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); - } - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s dec_result %d %x %x %x\n", - __func__, - hw->dec_result, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP)); - mutex_lock(&hw->chunks_mutex); - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - mutex_unlock(&hw->chunks_mutex); - } else if (hw->dec_result == DEC_RESULT_AGAIN) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(vdec)) { - hw->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hw->work); - return; - } - hw->next_again_flag = 1; - } else if (hw->dec_result == DEC_RESULT_EOS) { - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: end of stream\n", - __func__); - amvdec_stop(); - if (hw->mmu_enable) - amhevc_stop(); - hw->eos = 1; - flush_dpb(p_H264_Dpb); - if (hw->is_used_v4l) - notify_v4l_eos(hw_to_vdec(hw)); - mutex_lock(&hw->chunks_mutex); - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - mutex_unlock(&hw->chunks_mutex); - vdec_clean_input(vdec); - } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: force exit\n", - __func__); - amvdec_stop(); - if (hw->mmu_enable) - amhevc_stop(); - if (hw->stat & STAT_ISR_REG) { - WRITE_VREG(ASSIST_MBOX1_MASK, 0); - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - } - - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - - wait_vmh264_search_done(hw); - /* mark itself has all HW resource released and input released */ - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (hw->switch_dvlayer_flag) { - if (vdec->slave) - vdec_set_next_sched(vdec, vdec->slave); - else if (vdec->master) - vdec_set_next_sched(vdec, vdec->master); - } else if (vdec->slave || vdec->master) - vdec_set_next_sched(vdec, vdec); -#endif - - /* mark itself has all HW resource released and input released */ - if (vdec->parallel_dec == 1) { - if (hw->mmu_enable == 0) - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1); - else - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - } else - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - wake_up_interruptible(&hw->wait_q); - if (hw->vdec_cb) - hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); -} - -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) -{ - bool ret = 0; - struct vdec_h264_hw_s *hw = - (struct vdec_h264_hw_s *)vdec->private; - int tvp = vdec_secure(hw_to_vdec(hw)) ? - CODEC_MM_FLAGS_TVP : 0; - - if (!hw->first_sc_checked && hw->mmu_enable) { - int size = decoder_mmu_box_sc_check(hw->mmu_box, tvp); - hw->first_sc_checked =1; - dpb_print(DECODE_ID(hw), 0, - "vmh264 cached=%d need_size=%d speed= %d ms\n", - size, (hw->need_cache_size >> PAGE_SHIFT), - (int)(get_jiffies_64() - hw->sc_start_time) * 1000/HZ); - } - - if (vdec_stream_based(vdec) && (hw->init_flag == 0) - && pre_decode_buf_level != 0) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = vdec->input.size + wp - rp; - else - level = wp - rp; - - if (level < pre_decode_buf_level) - return 0; - } - -#ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->master) - return 0; -#endif - if (hw->eos) - return 0; - - if (hw->stat & DECODER_FATAL_ERROR_NO_MEM) - return 0; - - if (disp_vframe_valve_level && - kfifo_len(&hw->display_q) >= - disp_vframe_valve_level) { - hw->valve_count--; - if (hw->valve_count <= 0) - hw->valve_count = 2; - else - return 0; - } - if (hw->next_again_flag && - (!vdec_frame_based(vdec))) { - u32 parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - if (parser_wr_ptr >= hw->pre_parser_wr_ptr && - (parser_wr_ptr - hw->pre_parser_wr_ptr) < - again_threshold) { - int r = vdec_sync_input(vdec); - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, - "%s buf lelvel:%x\n", __func__, r); - return 0; - } - } - - if (h264_debug_flag & 0x20000000) { - /* pr_info("%s, a\n", __func__); */ - ret = 1; - } else - ret = is_buffer_available(vdec); - -#ifdef CONSTRAIN_MAX_BUF_NUM - if (hw->dpb.mDPB.size > 0) { /*make sure initilized*/ - if (run_ready_max_vf_only_num > 0 && - get_vf_ref_only_buf_count(hw) >= - run_ready_max_vf_only_num - ) - ret = 0; - if (run_ready_display_q_num > 0 && - kfifo_len(&hw->display_q) >= - run_ready_display_q_num) - ret = 0; - /*avoid more buffers consumed when - switching resolution*/ - if (run_ready_max_buf_num == 0xff && - get_used_buf_count(hw) >= - hw->dpb.mDPB.size) - ret = 0; - else if (run_ready_max_buf_num && - get_used_buf_count(hw) >= - run_ready_max_buf_num) - ret = 0; - } -#endif - if (ret) - not_run_ready[DECODE_ID(hw)] = 0; - else - not_run_ready[DECODE_ID(hw)]++; - if (vdec->parallel_dec == 1) { - if (hw->mmu_enable == 0) - return ret ? (CORE_MASK_VDEC_1) : 0; - else - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; - } else - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; -} - -static unsigned char get_data_check_sum - (struct vdec_h264_hw_s *hw, int size) -{ - int jj; - int sum = 0; - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, size); - else - data = ((u8 *)hw->chunk->block->start_virt) - + hw->chunk->offset; - - for (jj = 0; jj < size; jj++) - sum += data[jj]; - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - return sum; -} - -static void run(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *arg) -{ - struct vdec_h264_hw_s *hw = - (struct vdec_h264_hw_s *)vdec->private; - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - int size, ret = -1; - - run_count[DECODE_ID(hw)]++; - vdec_reset_core(vdec); - if (hw->mmu_enable) - hevc_reset_core(vdec); - hw->vdec_cb_arg = arg; - hw->vdec_cb = callback; - - if (kfifo_len(&hw->display_q) > VF_POOL_SIZE) { - hw->reset_bufmgr_flag = 1; - dpb_print(DECODE_ID(hw), 0, - "kfifo len:%d invaild, need bufmgr reset\n", - kfifo_len(&hw->display_q)); - } - - hw->pre_parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - hw->next_again_flag = 0; - - if (hw->reset_bufmgr_flag || - ((error_proc_policy & 0x40) && - p_H264_Dpb->buf_alloc_fail)) { - h264_reset_bufmgr(vdec); - hw->reset_bufmgr_flag = 0; - } - - if (h264_debug_cmd & 0xf000) { - if (((h264_debug_cmd >> 12) & 0xf) - == (DECODE_ID(hw) + 1)) { - h264_reconfig(hw); - h264_debug_cmd &= (~0xf000); - } - } - /* hw->chunk = vdec_prepare_input(vdec); */ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->slave || vdec->master) - vdec_set_flag(vdec, VDEC_FLAG_SELF_INPUT_CONTEXT); -#endif - size = vdec_prepare_input(vdec, &hw->chunk); - if ((size < 0) || - (input_frame_based(vdec) && hw->chunk == NULL)) { - input_empty[DECODE_ID(hw)]++; - hw->dec_result = DEC_RESULT_AGAIN; - - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, - "vdec_prepare_input: Insufficient data\n"); - - vdec_schedule_work(&hw->work); - return; - } - input_empty[DECODE_ID(hw)] = 0; - - hw->dec_result = DEC_RESULT_NONE; - hw->get_data_count = 0; -#if 0 - pr_info("VLD_MEM_VIFIFO_LEVEL = 0x%x, rp = 0x%x, wp = 0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_MEM_VIFIFO_WP)); -#endif - - if (input_frame_based(vdec) && !vdec_secure(vdec)) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, size); - else - data = ((u8 *)hw->chunk->block->start_virt) - + hw->chunk->offset; - - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_VDEC_STATUS) - ) { - dpb_print(DECODE_ID(hw), 0, - "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", - __func__, size, get_data_check_sum(hw, size), - data[0], data[1], data[2], data[3], - data[4], data[5], data[size - 4], - data[size - 3], data[size - 2], - data[size - 1]); - } - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA) - ) { - int jj; - - for (jj = 0; jj < size; jj++) { - if ((jj & 0xf) == 0) - dpb_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - dpb_print_cont(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - dpb_print_cont(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } else - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: %x %x %x %x %x size 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP), - size); - - start_process_time(hw); - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - WRITE_VREG(AV_SCRATCH_G, hw->reg_g_status); - } else { - - ret = amvdec_vdec_loadmc_ex(VFORMAT_H264, "mh264", vdec, hw->fw->data); - if (ret < 0) { - amvdec_enable_flag = false; - amvdec_disable(); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "MH264 the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; - } - vdec->mc_type = VFORMAT_H264; - hw->reg_g_status = READ_VREG(AV_SCRATCH_G); - if (hw->mmu_enable) { - ret = amhevc_loadmc_ex(VFORMAT_H264, "mh264_mmu", - hw->fw_mmu->data); - if (ret < 0) { - amvdec_enable_flag = false; - amhevc_disable(); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "MH264_MMU the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; - } - vdec->mc_type = ((1 << 16) | VFORMAT_H264); - } - vdec->mc_loaded = 1; - } - vmh264_reset_udr_mgr(hw); - - if (vh264_hw_ctx_restore(hw) < 0) { - vdec_schedule_work(&hw->work); - return; - } - if (input_frame_based(vdec)) { - int decode_size = 0; - - decode_size = hw->chunk->size + - (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - WRITE_VREG(H264_DECODE_INFO, (1<<13)); - WRITE_VREG(H264_DECODE_SIZE, decode_size); - WRITE_VREG(VIFF_BIT_CNT, decode_size * 8); - } else { - if (size <= 0) - size = 0x7fffffff; /*error happen*/ - WRITE_VREG(H264_DECODE_INFO, (1<<13)); - WRITE_VREG(H264_DECODE_SIZE, size); - WRITE_VREG(VIFF_BIT_CNT, size * 8); - } - config_aux_buf(hw); - config_decode_mode(hw); - vdec_enable_input(vdec); - WRITE_VREG(NAL_SEARCH_CTL, 0); - hw->sei_data_len = 0; - if (enable_itu_t35) - WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x1); - if (!hw->init_flag) { - if (hw->mmu_enable) - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | 0x2); - else - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) & (~0x2)); - } - if (udebug_flag) - WRITE_VREG(AV_SCRATCH_K, udebug_flag); - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); - - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { - - if (hw->mmu_enable) - SET_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); - else - CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); - } - amvdec_start(); - if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) { - WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0); - amhevc_start(); - if (hw->config_bufmgr_done) { - hevc_mcr_sao_global_hw_init(hw, - (hw->mb_width << 4), (hw->mb_height << 4)); - hevc_mcr_config_canv2axitbl(hw, 1); - } - } - - /* if (hw->init_flag) { */ - WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); - /* } */ - - hw->init_flag = 1; -} - -static void reset(struct vdec_s *vdec) -{ - struct vdec_h264_hw_s *hw = - (struct vdec_h264_hw_s *)vdec->private; - - cancel_work_sync(&hw->work); - cancel_work_sync(&hw->notify_work); - if (hw->stat & STAT_VDEC_RUN) { - amhevc_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - hw->eos = 0; - hw->decode_pic_count = 0; - hw->dec_result = DEC_RESULT_NONE; - reset_process_time(hw); - h264_reset_bufmgr(vdec); - dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); -} - -static void h264_reconfig(struct vdec_h264_hw_s *hw) -{ - int i; - unsigned long flags; - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - dpb_print(DECODE_ID(hw), 0, - "%s\n", __func__); - /* after calling flush_dpb() and bufmgr_h264_remove_unused_frame(), - all buffers are in display queue (used == 2), - or free (used == 0) - */ - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, "pre h264_reconfig"); - - flush_dpb(p_H264_Dpb); - bufmgr_h264_remove_unused_frame(p_H264_Dpb, 0); - - if (hw->collocate_cma_alloc_addr) { - decoder_bmmu_box_free_idx( - hw->bmmu_box, - BMMU_REF_IDX); - hw->collocate_cma_alloc_addr = 0; - hw->dpb.colocated_mv_addr_start = 0; - hw->dpb.colocated_mv_addr_end = 0; - } - spin_lock_irqsave(&hw->bufspec_lock, flags); - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - /*make sure buffers not put back to bufmgr when - vf_put is called*/ - if (hw->buffer_spec[i].used == 2) - hw->buffer_spec[i].used = 3; - - /* ready to release "free buffers" - */ - if (hw->buffer_spec[i].used == 0) - hw->buffer_spec[i].used = 4; - - hw->buffer_spec[i].canvas_pos = -1; - } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); - hw->has_i_frame = 0; - hw->config_bufmgr_done = 0; - - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DUMP_BUFSPEC)) - dump_bufspec(hw, "after h264_reconfig"); - -} - -#ifdef ERROR_HANDLE_TEST -static void h264_clear_dpb(struct vdec_h264_hw_s *hw) -{ - int i; - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s\n", __func__); - remove_dpb_pictures(p_H264_Dpb); - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - /*make sure buffers not put back to bufmgr when - vf_put is called*/ - if (hw->buffer_spec[i].used == 2) - hw->buffer_spec[i].used = 5; - } - -} -#endif - -static void h264_reset_bufmgr(struct vdec_s *vdec) -{ - int i; - ulong timeout; - struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; -#if 0 - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - int actual_dpb_size, max_reference_size; - int reorder_pic_num; - unsigned int colocated_buf_size; - unsigned int colocated_mv_addr_start; - unsigned int colocated_mv_addr_end; - dpb_print(DECODE_ID(hw), 0, - "%s\n", __func__); - - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - actual_dpb_size = p_H264_Dpb->mDPB.size; - max_reference_size = p_H264_Dpb->max_reference_size; - reorder_pic_num = p_H264_Dpb->reorder_pic_num; - - colocated_buf_size = p_H264_Dpb->colocated_buf_size; - colocated_mv_addr_start = p_H264_Dpb->colocated_mv_addr_start; - colocated_mv_addr_end = p_H264_Dpb->colocated_mv_addr_end; - - hw->cur_pool++; - if (hw->cur_pool >= VF_POOL_NUM) - hw->cur_pool = 0; - - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - hw->vfpool[hw->cur_pool][i].bufWidth = 1920; - kfifo_put(&hw->newframe_q, vf); - } - - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) - hw->buffer_spec[i].used = 0; - - dpb_init_global(&hw->dpb, - DECODE_ID(hw), 0, 0); - p_H264_Dpb->mDPB.size = actual_dpb_size; - p_H264_Dpb->max_reference_size = max_reference_size; - p_H264_Dpb->reorder_pic_num = reorder_pic_num; - - p_H264_Dpb->colocated_buf_size = colocated_buf_size; - p_H264_Dpb->colocated_mv_addr_start = colocated_mv_addr_start; - p_H264_Dpb->colocated_mv_addr_end = colocated_mv_addr_end; - - p_H264_Dpb->fast_output_enable = fast_output_enable; - hw->has_i_frame = 0; -#else - dpb_print(DECODE_ID(hw), 0, - "%s frame count %d to skip %d\n\n", - __func__, hw->decode_pic_count+1, - hw->skip_frame_count); - - timeout = jiffies + HZ; - while (kfifo_len(&hw->display_q) > 0) { - if (time_after(jiffies, timeout)) - break; - schedule(); - } - - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - hw->cur_pool++; - if (hw->cur_pool >= VF_POOL_NUM) - hw->cur_pool = 0; - - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - - if (hw->collocate_cma_alloc_addr) { - decoder_bmmu_box_free_idx( - hw->bmmu_box, - BMMU_REF_IDX); - hw->collocate_cma_alloc_addr = 0; - hw->dpb.colocated_mv_addr_start = 0; - hw->dpb.colocated_mv_addr_end = 0; - } - vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_RESET, NULL); - - dealloc_buf_specs(hw, 1); - buf_spec_init(hw); - - vh264_local_init(hw); - /*hw->decode_pic_count = 0; - hw->seq_info2 = 0;*/ - if (vh264_set_params(hw, - hw->cfg_param1, - hw->cfg_param2, - hw->cfg_param3, - hw->cfg_param4) < 0) - hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - hw->init_flag = 1; - hw->reset_bufmgr_count++; -#endif - -} - -int ammvdec_h264_mmu_init(struct vdec_h264_hw_s *hw) -{ - int ret = -1; - int tvp_flag = vdec_secure(hw_to_vdec(hw)) ? - CODEC_MM_FLAGS_TVP : 0; - int buf_size = 64; - - pr_debug("ammvdec_h264_mmu_init tvp = 0x%x mmu_enable %d\n", - tvp_flag, hw->mmu_enable); - hw->need_cache_size = buf_size * SZ_1M; - hw->sc_start_time = get_jiffies_64(); - if (hw->mmu_enable && !hw->mmu_box) { - hw->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, - hw->id, - MMU_MAX_BUFFERS, - hw->need_cache_size, - tvp_flag); - if (!hw->mmu_box) { - pr_err("h264 4k alloc mmu box failed!!\n"); - return -1; - } - ret = 0; - } - if (!hw->bmmu_box) { - hw->bmmu_box = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - hw->id, - BMMU_MAX_BUFFERS, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER | - tvp_flag); - if (hw->bmmu_box) - ret = 0; - } - return ret; -} -int ammvdec_h264_mmu_release(struct vdec_h264_hw_s *hw) -{ - if (hw->mmu_box) { - decoder_mmu_box_free(hw->mmu_box); - hw->mmu_box = NULL; - } - if (hw->bmmu_box) { - decoder_bmmu_box_free(hw->bmmu_box); - hw->bmmu_box = NULL; - } - return 0; -} - -static int ammvdec_h264_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct vdec_h264_hw_s *hw = NULL; - char *tmpbuf; - int config_val; - - if (pdata == NULL) { - pr_info("\nammvdec_h264 memory resource undefined.\n"); - return -EFAULT; - } - - hw = (struct vdec_h264_hw_s *)h264_alloc_hw_stru(&pdev->dev, - sizeof(struct vdec_h264_hw_s), GFP_KERNEL); - if (hw == NULL) { - pr_info("\nammvdec_h264 device data allocation failed\n"); - return -ENOMEM; - } - hw->id = pdev->id; - hw->platform_dev = pdev; - - /* the ctx from v4l2 driver. */ - hw->v4l2_ctx = pdata->private; - - hw->canvas_mode = pdata->canvas_mode; - - platform_set_drvdata(pdev, pdata); - - hw->mmu_enable = 0; - if (force_enable_mmu && pdata->sys_info && - (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) && - (pdata->sys_info->height * pdata->sys_info->width - > 1920 * 1088)) - hw->mmu_enable = 1; - - if (hw->mmu_enable && - (pdata->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO)) { - hw->mmu_enable = 0; - pr_info("ionvideo needs disable mmu, path= %d \n", - pdata->frame_base_video_path); - } - - if (ammvdec_h264_mmu_init(hw)) { - h264_free_hw_stru(&pdev->dev, (void *)hw); - pr_info("\nammvdec_h264 mmu alloc failed!\n"); - return -ENOMEM; - } - - if (pdata->config_len) { - /*use ptr config for doubel_write_mode, etc*/ - if (get_config_int(pdata->config, - "mh264_double_write_mode", &config_val) == 0) - hw->double_write_mode = config_val; - else - hw->double_write_mode = double_write_mode; - } else - hw->double_write_mode = double_write_mode; - - if (hw->mmu_enable) - hw->double_write_mode &= 0xffff; - - if (pdata->parallel_dec == 1) { - int i; - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - hw->buffer_spec[i].y_canvas_index = -1; - hw->buffer_spec[i].u_canvas_index = -1; - hw->buffer_spec[i].v_canvas_index = -1; -#ifdef VDEC_DW - if (IS_VDEC_DW(hw)) { - hw->buffer_spec[i].vdec_dw_y_canvas_index = -1; - hw->buffer_spec[i].vdec_dw_u_canvas_index = -1; - hw->buffer_spec[i].vdec_dw_v_canvas_index = -1; - } -#endif - } - } - - dpb_print(DECODE_ID(hw), 0, - "%s mmu_enable %d double_write_mode 0x%x\n", - __func__, hw->mmu_enable, hw->double_write_mode); - - pdata->private = hw; - pdata->dec_status = dec_status; - pdata->set_trickmode = vmh264_set_trickmode; - pdata->run_ready = run_ready; - pdata->run = run; - pdata->reset = reset; - pdata->irq_handler = vh264_isr; - pdata->threaded_irq_handler = vh264_isr_thread_fn; - pdata->dump_state = vmh264_dump_state; - -#ifdef MH264_USERDATA_ENABLE - pdata->wakeup_userdata_poll = vmh264_wakeup_userdata_poll; - pdata->user_data_read = vmh264_user_data_read; - pdata->reset_userdata_fifo = vmh264_reset_userdata_fifo; -#else - pdata->wakeup_userdata_poll = NULL; - pdata->user_data_read = NULL; - pdata->reset_userdata_fifo = NULL; -#endif - if (pdata->use_vfm_path) { - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - hw->frameinfo_enable = 1; - } -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec_dual(pdata)) { - if (dv_toggle_prov_name) /*debug purpose*/ - snprintf(pdata->vf_provider_name, - VDEC_PROVIDER_NAME_SIZE, - (pdata->master) ? VFM_DEC_DVBL_PROVIDER_NAME : - VFM_DEC_DVEL_PROVIDER_NAME); - else - snprintf(pdata->vf_provider_name, - VDEC_PROVIDER_NAME_SIZE, - (pdata->master) ? VFM_DEC_DVEL_PROVIDER_NAME : - VFM_DEC_DVBL_PROVIDER_NAME); - } -#endif - else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - PROVIDER_NAME ".%02x", pdev->id & 0xff); - - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vf_provider_ops, pdata); - - platform_set_drvdata(pdev, pdata); - - buf_spec_init(hw); - - hw->platform_dev = pdev; - -#ifdef DUMP_USERDATA_RECORD - vmh264_init_userdata_dump(); - vmh264_reset_user_data_buf(); -#endif - if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_DPB_IDX, - V_BUF_ADDR_OFFSET, DRIVER_NAME, &hw->cma_alloc_addr) < 0) { - h264_free_hw_stru(&pdev->dev, (void *)hw); - pdata->dec_status = NULL; - return -ENOMEM; - } - - hw->buf_offset = hw->cma_alloc_addr - DEF_BUF_START_ADDR + - DCAC_READ_MARGIN; - if (hw->mmu_enable) { - u32 extif_size = EXTIF_BUF_SIZE; - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) - extif_size <<= 1; - if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_EXTIF_IDX, - extif_size, DRIVER_NAME, &hw->extif_addr) < 0) { - h264_free_hw_stru(&pdev->dev, (void *)hw); - pdata->dec_status = NULL; - return -ENOMEM; - } - } - if (!vdec_secure(pdata)) { -#if 1 - /*init internal buf*/ - tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr); - if (tmpbuf) { - memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); - codec_mm_dma_flush(tmpbuf, - V_BUF_ADDR_OFFSET, - DMA_TO_DEVICE); - } else { - tmpbuf = codec_mm_vmap(hw->cma_alloc_addr, - V_BUF_ADDR_OFFSET); - if (tmpbuf) { - memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); - codec_mm_dma_flush(tmpbuf, - V_BUF_ADDR_OFFSET, - DMA_TO_DEVICE); - codec_mm_unmap_phyaddr(tmpbuf); - } - } -#else - /*init sps/pps internal buf 64k*/ - tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr - + (mem_sps_base - DEF_BUF_START_ADDR)); - memset(tmpbuf, 0, 0x10000); - dma_sync_single_for_device(amports_get_dma_device(), - hw->cma_alloc_addr + - (mem_sps_base - DEF_BUF_START_ADDR), - 0x10000, DMA_TO_DEVICE); -#endif - } - /**/ - - if (pdata->sys_info) - hw->vh264_amstream_dec_info = *pdata->sys_info; -#if 0 - if (NULL == hw->sei_data_buffer) { - hw->sei_data_buffer = - dma_alloc_coherent(amports_get_dma_device(), - USER_DATA_SIZE, - &hw->sei_data_buffer_phys, GFP_KERNEL); - if (!hw->sei_data_buffer) { - pr_info("%s: Can not allocate sei_data_buffer\n", - __func__); - ammvdec_h264_mmu_release(hw); - h264_free_hw_stru(&pdev->dev, (void *)hw); - return -ENOMEM; - } - /* pr_info("buffer 0x%x, phys 0x%x, remap 0x%x\n", - sei_data_buffer, sei_data_buffer_phys, - (u32)sei_data_buffer_remap); */ - } -#endif - pr_debug("ammvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx\n", - pdata->mem_start, hw->buf_offset, hw->cma_alloc_addr); - - if (vdec_is_support_4k() || - (clk_adj_frame_count > (VDEC_CLOCK_ADJUST_FRAME - 1))) - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); - else - vdec_source_changed(VFORMAT_H264, 1920, 1080, 29); - - if (vh264_init(hw) < 0) { - pr_info("\nammvdec_h264 init failed.\n"); - ammvdec_h264_mmu_release(hw); - h264_free_hw_stru(&pdev->dev, (void *)hw); - pdata->dec_status = NULL; - return -ENODEV; - } -#ifdef MH264_USERDATA_ENABLE - vmh264_crate_userdata_manager(hw, - hw->sei_user_data_buffer, - USER_DATA_SIZE); -#endif - - vdec_set_prepare_level(pdata, start_decode_buf_level); - if (pdata->parallel_dec == 1) { - if (hw->mmu_enable == 0) - vdec_core_request(pdata, CORE_MASK_VDEC_1); - else { - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - } - } else - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - - atomic_set(&hw->vh264_active, 1); - - return 0; -} - -static int ammvdec_h264_remove(struct platform_device *pdev) -{ - struct vdec_h264_hw_s *hw = - (struct vdec_h264_hw_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - int i; - - struct vdec_s *vdec = hw_to_vdec(hw); - - if (vdec->next_status == VDEC_STATUS_DISCONNECTED - && (vdec->status == VDEC_STATUS_ACTIVE)) { - pr_info("%s force exit %d\n", __func__, __LINE__); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - wait_event_interruptible_timeout(hw->wait_q, - (vdec->status == VDEC_STATUS_CONNECTED), - msecs_to_jiffies(50)); /* wait for work done */ - } - - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) - release_aux_data(hw, i); - - atomic_set(&hw->vh264_active, 0); - - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - - vh264_stop(hw); -#ifdef MH264_USERDATA_ENABLE -#ifdef DUMP_USERDATA_RECORD - vmh264_dump_userdata(); -#endif - vmh264_destroy_userdata_manager(hw); -#endif - /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ - - atomic_set(&hw->vh264_active, 0); - if (vdec->parallel_dec == 1) { - if (hw->mmu_enable == 0) - vdec_core_release(vdec, CORE_MASK_VDEC_1); - else - vdec_core_release(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | - CORE_MASK_COMBINE); - } else - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - if (vdec->parallel_dec == 1) { - for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { - vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); - if (IS_VDEC_DW(hw)) { - vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id); - } - } - } - ammvdec_h264_mmu_release(hw); - h264_free_hw_stru(&pdev->dev, (void *)hw); - clk_adj_frame_count = 0; - - return 0; -} - -/****************************************/ - -static struct platform_driver ammvdec_h264_driver = { - .probe = ammvdec_h264_probe, - .remove = ammvdec_h264_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t ammvdec_h264_profile = { - .name = "mh264", - .profile = "" -}; - -static struct mconfig hm264_configs[] = { - MC_PU32("h264_debug_flag", &h264_debug_flag), - MC_PI32("start_decode_buf_level", &start_decode_buf_level), - MC_PU32("fixed_frame_rate_mode", &fixed_frame_rate_mode), - MC_PU32("decode_timeout_val", &decode_timeout_val), - MC_PU32("reorder_dpb_size_margin", &reorder_dpb_size_margin), - MC_PU32("reference_buf_margin", &reference_buf_margin), - MC_PU32("radr", &radr), - MC_PU32("rval", &rval), - MC_PU32("h264_debug_mask", &h264_debug_mask), - MC_PU32("h264_debug_cmd", &h264_debug_cmd), - MC_PI32("force_rate_streambase", &force_rate_streambase), - MC_PI32("dec_control", &dec_control), - MC_PI32("force_rate_framebase", &force_rate_framebase), - MC_PI32("force_disp_bufspec_num", &force_disp_bufspec_num), - MC_PU32("prefix_aux_buf_size", &prefix_aux_buf_size), - MC_PU32("suffix_aux_buf_size", &suffix_aux_buf_size), -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - MC_PU32("reorder_dpb_size_margin_dv", &reorder_dpb_size_margin_dv), - MC_PU32("dv_toggle_prov_name", &dv_toggle_prov_name), - MC_PU32("dolby_meta_with_el", &dolby_meta_with_el), -#endif - MC_PU32("i_only_flag", &i_only_flag), - MC_PU32("force_rate_streambase", &force_rate_streambase), -}; -static struct mconfig_node hm264_node; - - -static int __init ammvdec_h264_driver_init_module(void) -{ - pr_info("ammvdec_h264 module init\n"); - if (platform_driver_register(&ammvdec_h264_driver)) { - pr_info("failed to register ammvdec_h264 driver\n"); - return -ENODEV; - } - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) { - ammvdec_h264_profile.profile = - "4k, dwrite, compressed"; - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { - ammvdec_h264_profile.profile = "4k"; - } - } - - vcodec_profile_register(&ammvdec_h264_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &hm264_node, - "mh264", hm264_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit ammvdec_h264_driver_remove_module(void) -{ - pr_info("ammvdec_h264 module remove.\n"); - - platform_driver_unregister(&ammvdec_h264_driver); -} - -/****************************************/ -module_param(h264_debug_flag, uint, 0664); -MODULE_PARM_DESC(h264_debug_flag, "\n ammvdec_h264 h264_debug_flag\n"); - -module_param(start_decode_buf_level, int, 0664); -MODULE_PARM_DESC(start_decode_buf_level, - "\n ammvdec_h264 start_decode_buf_level\n"); - -module_param(pre_decode_buf_level, int, 0664); -MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n"); - -module_param(fixed_frame_rate_mode, uint, 0664); -MODULE_PARM_DESC(fixed_frame_rate_mode, "\namvdec_h264 fixed_frame_rate_mode\n"); - -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, "\n amvdec_h264 decode_timeout_val\n"); - -module_param(errordata_timeout_val, uint, 0664); -MODULE_PARM_DESC(errordata_timeout_val, "\n amvdec_h264 errordata_timeout_val\n"); - -module_param(get_data_timeout_val, uint, 0664); -MODULE_PARM_DESC(get_data_timeout_val, "\n amvdec_h264 get_data_timeout_val\n"); - -module_param(frame_max_data_packet, uint, 0664); -MODULE_PARM_DESC(frame_max_data_packet, "\n amvdec_h264 frame_max_data_packet\n"); - -module_param(reorder_dpb_size_margin, uint, 0664); -MODULE_PARM_DESC(reorder_dpb_size_margin, "\n ammvdec_h264 reorder_dpb_size_margin\n"); - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -module_param(reorder_dpb_size_margin_dv, uint, 0664); -MODULE_PARM_DESC(reorder_dpb_size_margin_dv, - "\n ammvdec_h264 reorder_dpb_size_margin_dv\n"); -#endif - -module_param(reference_buf_margin, uint, 0664); -MODULE_PARM_DESC(reference_buf_margin, "\n ammvdec_h264 reference_buf_margin\n"); - -#ifdef CONSTRAIN_MAX_BUF_NUM -module_param(run_ready_max_vf_only_num, uint, 0664); -MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); - -module_param(run_ready_display_q_num, uint, 0664); -MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); - -module_param(run_ready_max_buf_num, uint, 0664); -MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); -#endif - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\nradr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\nrval\n"); - -module_param(h264_debug_mask, uint, 0664); -MODULE_PARM_DESC(h264_debug_mask, "\n amvdec_h264 h264_debug_mask\n"); - -module_param(h264_debug_cmd, uint, 0664); -MODULE_PARM_DESC(h264_debug_cmd, "\n amvdec_h264 h264_debug_cmd\n"); - -module_param(force_rate_streambase, int, 0664); -MODULE_PARM_DESC(force_rate_streambase, "\n amvdec_h264 force_rate_streambase\n"); - -module_param(dec_control, int, 0664); -MODULE_PARM_DESC(dec_control, "\n amvdec_h264 dec_control\n"); - -module_param(force_rate_framebase, int, 0664); -MODULE_PARM_DESC(force_rate_framebase, "\n amvdec_h264 force_rate_framebase\n"); - -module_param(force_disp_bufspec_num, int, 0664); -MODULE_PARM_DESC(force_disp_bufspec_num, "\n amvdec_h264 force_disp_bufspec_num\n"); - -module_param(V_BUF_ADDR_OFFSET, int, 0664); -MODULE_PARM_DESC(V_BUF_ADDR_OFFSET, "\n amvdec_h264 V_BUF_ADDR_OFFSET\n"); - -module_param(prefix_aux_buf_size, uint, 0664); -MODULE_PARM_DESC(prefix_aux_buf_size, "\n prefix_aux_buf_size\n"); - -module_param(suffix_aux_buf_size, uint, 0664); -MODULE_PARM_DESC(suffix_aux_buf_size, "\n suffix_aux_buf_size\n"); - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -module_param(dv_toggle_prov_name, uint, 0664); -MODULE_PARM_DESC(dv_toggle_prov_name, "\n dv_toggle_prov_name\n"); - -module_param(dolby_meta_with_el, uint, 0664); -MODULE_PARM_DESC(dolby_meta_with_el, "\n dolby_meta_with_el\n"); - -#endif - -module_param(fast_output_enable, uint, 0664); -MODULE_PARM_DESC(fast_output_enable, "\n amvdec_h264 fast_output_enable\n"); - -module_param(error_proc_policy, uint, 0664); -MODULE_PARM_DESC(error_proc_policy, "\n amvdec_h264 error_proc_policy\n"); - -module_param(error_skip_count, uint, 0664); -MODULE_PARM_DESC(error_skip_count, "\n amvdec_h264 error_skip_count\n"); - -module_param(force_sliding_margin, uint, 0664); -MODULE_PARM_DESC(force_sliding_margin, "\n amvdec_h264 force_sliding_margin\n"); - -module_param(i_only_flag, uint, 0664); -MODULE_PARM_DESC(i_only_flag, "\n amvdec_h264 i_only_flag\n"); - -module_param(first_i_policy, uint, 0664); -MODULE_PARM_DESC(first_i_policy, "\n amvdec_h264 first_i_policy\n"); - -module_param(frmbase_cont_bitlevel, uint, 0664); -MODULE_PARM_DESC(frmbase_cont_bitlevel, - "\n amvdec_h264 frmbase_cont_bitlevel\n"); - -module_param(frmbase_cont_bitlevel2, uint, 0664); -MODULE_PARM_DESC(frmbase_cont_bitlevel2, - "\n amvdec_h264 frmbase_cont_bitlevel\n"); - -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_mh264 udebug_flag\n"); - -module_param(udebug_pause_pos, uint, 0664); -MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); - -module_param(udebug_pause_val, uint, 0664); -MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); - -module_param(udebug_pause_decode_idx, uint, 0664); -MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); - -module_param(max_alloc_buf_count, uint, 0664); -MODULE_PARM_DESC(max_alloc_buf_count, "\n amvdec_h264 max_alloc_buf_count\n"); - -module_param(enable_itu_t35, uint, 0664); -MODULE_PARM_DESC(enable_itu_t35, "\n amvdec_h264 enable_itu_t35\n"); - -module_param(endian, uint, 0664); -MODULE_PARM_DESC(endian, "\nrval\n"); - -module_param(mmu_enable, uint, 0664); -MODULE_PARM_DESC(mmu_enable, "\n mmu_enable\n"); - -module_param(force_enable_mmu, uint, 0664); -MODULE_PARM_DESC(force_enable_mmu, "\n force_enable_mmu\n"); - -module_param(again_threshold, uint, 0664); -MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); - -module_param(stream_mode_start_num, uint, 0664); -MODULE_PARM_DESC(stream_mode_start_num, "\n stream_mode_start_num\n"); - -/* -module_param(trigger_task, uint, 0664); -MODULE_PARM_DESC(trigger_task, "\n amvdec_h264 trigger_task\n"); -*/ -module_param_array(decode_frame_count, uint, &max_decode_instance_num, 0664); - -module_param_array(display_frame_count, uint, &max_decode_instance_num, 0664); - -module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); - -module_param_array(run_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(not_run_ready, uint, - &max_decode_instance_num, 0664); - -module_param_array(input_empty, uint, - &max_decode_instance_num, 0664); - -module_param_array(max_get_frame_interval, uint, - &max_decode_instance_num, 0664); - -module_param_array(step, uint, &max_decode_instance_num, 0664); - -module_param_array(ref_frame_mark_flag, uint, &max_decode_instance_num, 0664); - -module_param(disp_vframe_valve_level, uint, 0664); -MODULE_PARM_DESC(disp_vframe_valve_level, "\n disp_vframe_valve_level\n"); - -module_param(double_write_mode, uint, 0664); -MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); - -module_param(mem_map_mode, uint, 0664); -MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); - -module_init(ammvdec_h264_driver_init_module); -module_exit(ammvdec_h264_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC H264 Video Decoder Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/h265/Makefile deleted file mode 100644 index 86b8b8887f15..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h265/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H265) += amvdec_h265.o -amvdec_h265-objs += vh265.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c deleted file mode 100644 index f0d97b5c080e..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c +++ /dev/null @@ -1,12740 +0,0 @@ -/* - * drivers/amlogic/amports/vh265.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include "../utils/config_parser.h" -#include "../utils/firmware.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" -#include - -#define CONSTRAIN_MAX_BUF_NUM - -#define SWAP_HEVC_UCODE -#define DETREFILL_ENABLE - -#define AGAIN_HAS_THRESHOLD -/*#define TEST_NO_BUF*/ -/*#define HEVC_PIC_STRUCT_SUPPORT*/ -#define MULTI_INSTANCE_SUPPORT -#define USE_UNINIT_SEMA - - /* .buf_size = 0x100000*16, - //4k2k , 0x100000 per buffer */ - /* 4096x2304 , 0x120000 per buffer */ -#define MPRED_8K_MV_BUF_SIZE (0x120000*4) -#define MPRED_4K_MV_BUF_SIZE (0x120000) -#define MPRED_MV_BUF_SIZE (0x40000) - -#define MMU_COMPRESS_HEADER_SIZE 0x48000 -#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) - -#define MAX_FRAME_4K_NUM 0x1200 -#define MAX_FRAME_8K_NUM (0x1200*4) - -//#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) -#define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7 - -#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 - -#define HEVC_CM_HEADER_START_ADDR 0x3628 -#define HEVC_SAO_MMU_VH1_ADDR 0x363b -#define HEVC_SAO_MMU_VH0_ADDR 0x363a -#define HEVC_SAO_MMU_STATUS 0x3639 - -#define HEVC_DBLK_CFGB 0x350b -#define HEVCD_MPP_DECOMP_AXIURG_CTL 0x34c7 -#define SWAP_HEVC_OFFSET (3 * 0x1000) - -#define MEM_NAME "codec_265" -/* #include */ -#include - -#include "../utils/vdec.h" -#include "../utils/amvdec.h" -#include -#include - -#define SEND_LMEM_WITH_RPM -#define SUPPORT_10BIT -/* #define ERROR_HANDLE_DEBUG */ - -#ifndef STAT_KTHREAD -#define STAT_KTHREAD 0x40 -#endif - -#ifdef MULTI_INSTANCE_SUPPORT -#define MAX_DECODE_INSTANCE_NUM 9 -#define MULTI_DRIVER_NAME "ammvdec_h265" -#endif -#define DRIVER_NAME "amvdec_h265" -#define MODULE_NAME "amvdec_h265" -#define DRIVER_HEADER_NAME "amvdec_h265_header" - -#define PUT_INTERVAL (HZ/100) -#define ERROR_SYSTEM_RESET_COUNT 200 - -#define PTS_NORMAL 0 -#define PTS_NONE_REF_USE_DURATION 1 - -#define PTS_MODE_SWITCHING_THRESHOLD 3 -#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 - -#define DUR2PTS(x) ((x)*90/96) - -#define MAX_SIZE_8K (8192 * 4608) -#define MAX_SIZE_4K (4096 * 2304) - -#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) -#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) - -#define SEI_UserDataITU_T_T35 4 - -static struct semaphore h265_sema; - -struct hevc_state_s; -static int hevc_print(struct hevc_state_s *hevc, - int debug_flag, const char *fmt, ...); -static int hevc_print_cont(struct hevc_state_s *hevc, - int debug_flag, const char *fmt, ...); -static int vh265_vf_states(struct vframe_states *states, void *); -static struct vframe_s *vh265_vf_peek(void *); -static struct vframe_s *vh265_vf_get(void *); -static void vh265_vf_put(struct vframe_s *, void *); -static int vh265_event_cb(int type, void *data, void *private_data); - -static int vh265_stop(struct hevc_state_s *hevc); -#ifdef MULTI_INSTANCE_SUPPORT -static int vmh265_stop(struct hevc_state_s *hevc); -static s32 vh265_init(struct vdec_s *vdec); -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask); -static void reset_process_time(struct hevc_state_s *hevc); -static void start_process_time(struct hevc_state_s *hevc); -static void restart_process_time(struct hevc_state_s *hevc); -static void timeout_process(struct hevc_state_s *hevc); -#else -static s32 vh265_init(struct hevc_state_s *hevc); -#endif -static void vh265_prot_init(struct hevc_state_s *hevc); -static int vh265_local_init(struct hevc_state_s *hevc); -static void vh265_check_timer_func(unsigned long arg); -static void config_decode_mode(struct hevc_state_s *hevc); - -static const char vh265_dec_id[] = "vh265-dev"; - -#define PROVIDER_NAME "decoder.h265" -#define MULTI_INSTANCE_PROVIDER_NAME "vdec.h265" - -static const struct vframe_operations_s vh265_vf_provider = { - .peek = vh265_vf_peek, - .get = vh265_vf_get, - .put = vh265_vf_put, - .event_cb = vh265_event_cb, - .vf_states = vh265_vf_states, -}; - -static struct vframe_provider_s vh265_vf_prov; - -static u32 bit_depth_luma; -static u32 bit_depth_chroma; -static u32 video_signal_type; - -static int start_decode_buf_level = 0x8000; - -static unsigned int decode_timeout_val = 200; - -/*data_resend_policy: - bit 0, stream base resend data when decoding buf empty -*/ -static u32 data_resend_policy = 1; - -#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 -/* -static const char * const video_format_names[] = { - "component", "PAL", "NTSC", "SECAM", - "MAC", "unspecified", "unspecified", "unspecified" -}; - -static const char * const color_primaries_names[] = { - "unknown", "bt709", "undef", "unknown", - "bt470m", "bt470bg", "smpte170m", "smpte240m", - "film", "bt2020" -}; - -static const char * const transfer_characteristics_names[] = { - "unknown", "bt709", "undef", "unknown", - "bt470m", "bt470bg", "smpte170m", "smpte240m", - "linear", "log100", "log316", "iec61966-2-4", - "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", - "smpte-st-2084", "smpte-st-428" -}; - -static const char * const matrix_coeffs_names[] = { - "GBR", "bt709", "undef", "unknown", - "fcc", "bt470bg", "smpte170m", "smpte240m", - "YCgCo", "bt2020nc", "bt2020c" -}; -*/ -#ifdef SUPPORT_10BIT -#define HEVC_CM_BODY_START_ADDR 0x3626 -#define HEVC_CM_BODY_LENGTH 0x3627 -#define HEVC_CM_HEADER_LENGTH 0x3629 -#define HEVC_CM_HEADER_OFFSET 0x362b -#define HEVC_SAO_CTRL9 0x362d -#define LOSLESS_COMPRESS_MODE -/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ -/* hevc->double_write_mode: - * 0, no double write; - * 1, 1:1 ratio; - * 2, (1/4):(1/4) ratio; - * 3, (1/4):(1/4) ratio, with both compressed frame included - * 0x10, double write only - */ -static u32 double_write_mode; - -/*#define DECOMP_HEADR_SURGENT*/ - -static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ -static u32 enable_mem_saving = 1; -static u32 workaround_enable; -static u32 force_w_h; -#endif -static u32 force_fps; -static u32 pts_unstable; -#define H265_DEBUG_BUFMGR 0x01 -#define H265_DEBUG_BUFMGR_MORE 0x02 -#define H265_DEBUG_DETAIL 0x04 -#define H265_DEBUG_REG 0x08 -#define H265_DEBUG_MAN_SEARCH_NAL 0x10 -#define H265_DEBUG_MAN_SKIP_NAL 0x20 -#define H265_DEBUG_DISPLAY_CUR_FRAME 0x40 -#define H265_DEBUG_FORCE_CLK 0x80 -#define H265_DEBUG_SEND_PARAM_WITH_REG 0x100 -#define H265_DEBUG_NO_DISPLAY 0x200 -#define H265_DEBUG_DISCARD_NAL 0x400 -#define H265_DEBUG_OUT_PTS 0x800 -#define H265_DEBUG_DUMP_PIC_LIST 0x1000 -#define H265_DEBUG_PRINT_SEI 0x2000 -#define H265_DEBUG_PIC_STRUCT 0x4000 -#define H265_DEBUG_HAS_AUX_IN_SLICE 0x8000 -#define H265_DEBUG_DIS_LOC_ERROR_PROC 0x10000 -#define H265_DEBUG_DIS_SYS_ERROR_PROC 0x20000 -#define H265_NO_CHANG_DEBUG_FLAG_IN_CODE 0x40000 -#define H265_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000 -#define H265_DEBUG_HW_RESET 0x100000 -#define H265_CFG_CANVAS_IN_DECODE 0x200000 -#define H265_DEBUG_DV 0x400000 -#define H265_DEBUG_NO_EOS_SEARCH_DONE 0x800000 -#define H265_DEBUG_NOT_USE_LAST_DISPBUF 0x1000000 -#define H265_DEBUG_IGNORE_CONFORMANCE_WINDOW 0x2000000 -#define H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP 0x4000000 -#ifdef MULTI_INSTANCE_SUPPORT -#define IGNORE_PARAM_FROM_CONFIG 0x08000000 -#define PRINT_FRAMEBASE_DATA 0x10000000 -#define PRINT_FLAG_VDEC_STATUS 0x20000000 -#define PRINT_FLAG_VDEC_DETAIL 0x40000000 -#endif -#define BUF_POOL_SIZE 32 -#define MAX_BUF_NUM 24 -#define MAX_REF_PIC_NUM 24 -#define MAX_REF_ACTIVE 16 - -#ifdef MV_USE_FIXED_BUF -#define BMMU_MAX_BUFFERS (BUF_POOL_SIZE + 1) -#define VF_BUFFER_IDX(n) (n) -#define BMMU_WORKSPACE_ID (BUF_POOL_SIZE) -#else -#define BMMU_MAX_BUFFERS (BUF_POOL_SIZE + 1 + MAX_REF_PIC_NUM) -#define VF_BUFFER_IDX(n) (n) -#define BMMU_WORKSPACE_ID (BUF_POOL_SIZE) -#define MV_BUFFER_IDX(n) (BUF_POOL_SIZE + 1 + n) -#endif - -#define HEVC_MV_INFO 0x310d -#define HEVC_QP_INFO 0x3137 -#define HEVC_SKIP_INFO 0x3136 - -const u32 h265_version = 201602101; -static u32 debug_mask = 0xffffffff; -static u32 log_mask; -static u32 debug; -static u32 radr; -static u32 rval; -static u32 dbg_cmd; -static u32 dump_nal; -static u32 dbg_skip_decode_index; -static u32 endian = 0xff0; -#ifdef ERROR_HANDLE_DEBUG -static u32 dbg_nal_skip_flag; - /* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */ -static u32 dbg_nal_skip_count; -#endif -/*for debug*/ -/* - udebug_flag: - bit 0, enable ucode print - bit 1, enable ucode detail print - bit [31:16] not 0, pos to dump lmem - bit 2, pop bits to lmem - bit [11:8], pre-pop bits for alignment (when bit 2 is 1) -*/ -static u32 udebug_flag; -/* - when udebug_flag[1:0] is not 0 - udebug_pause_pos not 0, - pause position -*/ -static u32 udebug_pause_pos; -/* - when udebug_flag[1:0] is not 0 - and udebug_pause_pos is not 0, - pause only when DEBUG_REG2 is equal to this val -*/ -static u32 udebug_pause_val; - -static u32 udebug_pause_decode_idx; - -static u32 decode_pic_begin; -static uint slice_parse_begin; -static u32 step; -static bool is_reset; - -#ifdef CONSTRAIN_MAX_BUF_NUM -static u32 run_ready_max_vf_only_num; -static u32 run_ready_display_q_num; - /*0: not check - 0xff: work_pic_num - */ -static u32 run_ready_max_buf_num = 0xff; -#endif - -static u32 dynamic_buf_num_margin = 7; -static u32 buf_alloc_width; -static u32 buf_alloc_height; - -static u32 max_buf_num = 16; -static u32 buf_alloc_size; -/*static u32 re_config_pic_flag;*/ -/* - *bit[0]: 0, - *bit[1]: 0, always release cma buffer when stop - *bit[1]: 1, never release cma buffer when stop - *bit[0]: 1, when stop, release cma buffer if blackout is 1; - *do not release cma buffer is blackout is not 1 - * - *bit[2]: 0, when start decoding, check current displayed buffer - * (only for buffer decoded by h265) if blackout is 0 - * 1, do not check current displayed buffer - * - *bit[3]: 1, if blackout is not 1, do not release current - * displayed cma buffer always. - */ -/* set to 1 for fast play; - * set to 8 for other case of "keep last frame" - */ -static u32 buffer_mode = 1; - -/* buffer_mode_dbg: debug only*/ -static u32 buffer_mode_dbg = 0xffff0000; -/**/ -/* - *bit[1:0]PB_skip_mode: 0, start decoding at begin; - *1, start decoding after first I; - *2, only decode and display none error picture; - *3, start decoding and display after IDR,etc - *bit[31:16] PB_skip_count_after_decoding (decoding but not display), - *only for mode 0 and 1. - */ -static u32 nal_skip_policy = 2; - -/* - *bit 0, 1: only display I picture; - *bit 1, 1: only decode I picture; - */ -static u32 i_only_flag; - -/* -bit 0, fast output first I picture -*/ -static u32 fast_output_enable = 1; - -static u32 frmbase_cont_bitlevel = 0x60; - -/* -use_cma: 1, use both reserver memory and cma for buffers -2, only use cma for buffers -*/ -static u32 use_cma = 2; - -#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf)) -static u32 prefix_aux_buf_size = (16 * 1024); -static u32 suffix_aux_buf_size; - -static u32 max_decoding_time; -/* - *error handling - */ -/*error_handle_policy: - *bit 0: 0, auto skip error_skip_nal_count nals before error recovery; - *1, skip error_skip_nal_count nals before error recovery; - *bit 1 (valid only when bit0 == 1): - *1, wait vps/sps/pps after error recovery; - *bit 2 (valid only when bit0 == 0): - *0, auto search after error recovery (hevc_recover() called); - *1, manual search after error recovery - *(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) - * - *bit 4: 0, set error_mark after reset/recover - * 1, do not set error_mark after reset/recover - *bit 5: 0, check total lcu for every picture - * 1, do not check total lcu - *bit 6: 0, do not check head error - * 1, check head error - * - */ - -static u32 error_handle_policy; -static u32 error_skip_nal_count = 6; -static u32 error_handle_threshold = 30; -static u32 error_handle_nal_skip_threshold = 10; -static u32 error_handle_system_threshold = 30; -static u32 interlace_enable = 1; -static u32 fr_hint_status; - - /* - *parser_sei_enable: - * bit 0, sei; - * bit 1, sei_suffix (fill aux buf) - * bit 2, fill sei to aux buf (when bit 0 is 1) - * bit 8, debug flag - */ -static u32 parser_sei_enable; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -static u32 parser_dolby_vision_enable = 1; -static u32 dolby_meta_with_el; -static u32 dolby_el_flush_th = 2; -#endif -/* this is only for h265 mmu enable */ - -static u32 mmu_enable = 1; -static u32 mmu_enable_force; -static u32 work_buf_size; -static unsigned int force_disp_pic_index; -static unsigned int disp_vframe_valve_level; -static int pre_decode_buf_level = 0x1000; - -#ifdef MULTI_INSTANCE_SUPPORT -static unsigned int max_decode_instance_num - = MAX_DECODE_INSTANCE_NUM; -static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM]; -static unsigned int max_get_frame_interval[MAX_DECODE_INSTANCE_NUM]; -static unsigned int run_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; -static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; -static unsigned int ref_frame_mark_flag[MAX_DECODE_INSTANCE_NUM] = -{1, 1, 1, 1, 1, 1, 1, 1, 1}; - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -static unsigned char get_idx(struct hevc_state_s *hevc); -#endif - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -static u32 dv_toggle_prov_name; - -static u32 dv_debug; - -static u32 force_bypass_dvenl; -#endif -#endif - - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -#define get_dbg_flag(hevc) ((debug_mask & (1 << hevc->index)) ? debug : 0) -#define get_dbg_flag2(hevc) ((debug_mask & (1 << get_idx(hevc))) ? debug : 0) -#define is_log_enable(hevc) ((log_mask & (1 << hevc->index)) ? 1 : 0) -#else -#define get_dbg_flag(hevc) debug -#define get_dbg_flag2(hevc) debug -#define is_log_enable(hevc) (log_mask ? 1 : 0) -#define get_valid_double_write_mode(hevc) double_write_mode -#define get_buf_alloc_width(hevc) buf_alloc_width -#define get_buf_alloc_height(hevc) buf_alloc_height -#define get_dynamic_buf_num_margin(hevc) dynamic_buf_num_margin -#endif -#define get_buffer_mode(hevc) buffer_mode - - -DEFINE_SPINLOCK(lock); -struct task_struct *h265_task = NULL; -#undef DEBUG_REG -#ifdef DEBUG_REG -void WRITE_VREG_DBG(unsigned adr, unsigned val) -{ - if (debug & H265_DEBUG_REG) - pr_info("%s(%x, %x)\n", __func__, adr, val); - WRITE_VREG(adr, val); -} - -#undef WRITE_VREG -#define WRITE_VREG WRITE_VREG_DBG -#endif - -static DEFINE_MUTEX(vh265_mutex); - -static DEFINE_MUTEX(vh265_log_mutex); - -static struct vdec_info *gvs; - -/************************************************** - * - *h265 buffer management include - * - *************************************************** - */ -enum NalUnitType { - NAL_UNIT_CODED_SLICE_TRAIL_N = 0, /* 0 */ - NAL_UNIT_CODED_SLICE_TRAIL_R, /* 1 */ - - NAL_UNIT_CODED_SLICE_TSA_N, /* 2 */ - /* Current name in the spec: TSA_R */ - NAL_UNIT_CODED_SLICE_TLA, /* 3 */ - - NAL_UNIT_CODED_SLICE_STSA_N, /* 4 */ - NAL_UNIT_CODED_SLICE_STSA_R, /* 5 */ - - NAL_UNIT_CODED_SLICE_RADL_N, /* 6 */ - /* Current name in the spec: RADL_R */ - NAL_UNIT_CODED_SLICE_DLP, /* 7 */ - - NAL_UNIT_CODED_SLICE_RASL_N, /* 8 */ - /* Current name in the spec: RASL_R */ - NAL_UNIT_CODED_SLICE_TFD, /* 9 */ - - NAL_UNIT_RESERVED_10, - NAL_UNIT_RESERVED_11, - NAL_UNIT_RESERVED_12, - NAL_UNIT_RESERVED_13, - NAL_UNIT_RESERVED_14, - NAL_UNIT_RESERVED_15, - - /* Current name in the spec: BLA_W_LP */ - NAL_UNIT_CODED_SLICE_BLA, /* 16 */ - /* Current name in the spec: BLA_W_DLP */ - NAL_UNIT_CODED_SLICE_BLANT, /* 17 */ - NAL_UNIT_CODED_SLICE_BLA_N_LP, /* 18 */ - /* Current name in the spec: IDR_W_DLP */ - NAL_UNIT_CODED_SLICE_IDR, /* 19 */ - NAL_UNIT_CODED_SLICE_IDR_N_LP, /* 20 */ - NAL_UNIT_CODED_SLICE_CRA, /* 21 */ - NAL_UNIT_RESERVED_22, - NAL_UNIT_RESERVED_23, - - NAL_UNIT_RESERVED_24, - NAL_UNIT_RESERVED_25, - NAL_UNIT_RESERVED_26, - NAL_UNIT_RESERVED_27, - NAL_UNIT_RESERVED_28, - NAL_UNIT_RESERVED_29, - NAL_UNIT_RESERVED_30, - NAL_UNIT_RESERVED_31, - - NAL_UNIT_VPS, /* 32 */ - NAL_UNIT_SPS, /* 33 */ - NAL_UNIT_PPS, /* 34 */ - NAL_UNIT_ACCESS_UNIT_DELIMITER, /* 35 */ - NAL_UNIT_EOS, /* 36 */ - NAL_UNIT_EOB, /* 37 */ - NAL_UNIT_FILLER_DATA, /* 38 */ - NAL_UNIT_SEI, /* 39 Prefix SEI */ - NAL_UNIT_SEI_SUFFIX, /* 40 Suffix SEI */ - NAL_UNIT_RESERVED_41, - NAL_UNIT_RESERVED_42, - NAL_UNIT_RESERVED_43, - NAL_UNIT_RESERVED_44, - NAL_UNIT_RESERVED_45, - NAL_UNIT_RESERVED_46, - NAL_UNIT_RESERVED_47, - NAL_UNIT_UNSPECIFIED_48, - NAL_UNIT_UNSPECIFIED_49, - NAL_UNIT_UNSPECIFIED_50, - NAL_UNIT_UNSPECIFIED_51, - NAL_UNIT_UNSPECIFIED_52, - NAL_UNIT_UNSPECIFIED_53, - NAL_UNIT_UNSPECIFIED_54, - NAL_UNIT_UNSPECIFIED_55, - NAL_UNIT_UNSPECIFIED_56, - NAL_UNIT_UNSPECIFIED_57, - NAL_UNIT_UNSPECIFIED_58, - NAL_UNIT_UNSPECIFIED_59, - NAL_UNIT_UNSPECIFIED_60, - NAL_UNIT_UNSPECIFIED_61, - NAL_UNIT_UNSPECIFIED_62, - NAL_UNIT_UNSPECIFIED_63, - NAL_UNIT_INVALID, -}; - -/* --------------------------------------------------- */ -/* Amrisc Software Interrupt */ -/* --------------------------------------------------- */ -#define AMRISC_STREAM_EMPTY_REQ 0x01 -#define AMRISC_PARSER_REQ 0x02 -#define AMRISC_MAIN_REQ 0x04 - -/* --------------------------------------------------- */ -/* HEVC_DEC_STATUS define */ -/* --------------------------------------------------- */ -#define HEVC_DEC_IDLE 0x0 -#define HEVC_NAL_UNIT_VPS 0x1 -#define HEVC_NAL_UNIT_SPS 0x2 -#define HEVC_NAL_UNIT_PPS 0x3 -#define HEVC_NAL_UNIT_CODED_SLICE_SEGMENT 0x4 -#define HEVC_CODED_SLICE_SEGMENT_DAT 0x5 -#define HEVC_SLICE_DECODING 0x6 -#define HEVC_NAL_UNIT_SEI 0x7 -#define HEVC_SLICE_SEGMENT_DONE 0x8 -#define HEVC_NAL_SEARCH_DONE 0x9 -#define HEVC_DECPIC_DATA_DONE 0xa -#define HEVC_DECPIC_DATA_ERROR 0xb -#define HEVC_SEI_DAT 0xc -#define HEVC_SEI_DAT_DONE 0xd -#define HEVC_NAL_DECODE_DONE 0xe -#define HEVC_OVER_DECODE 0xf - -#define HEVC_DATA_REQUEST 0x12 - -#define HEVC_DECODE_BUFEMPTY 0x20 -#define HEVC_DECODE_TIMEOUT 0x21 -#define HEVC_SEARCH_BUFEMPTY 0x22 -#define HEVC_DECODE_OVER_SIZE 0x23 -#define HEVC_DECODE_BUFEMPTY2 0x24 -#define HEVC_FIND_NEXT_PIC_NAL 0x50 -#define HEVC_FIND_NEXT_DVEL_NAL 0x51 - -#define HEVC_DUMP_LMEM 0x30 - -#define HEVC_4k2k_60HZ_NOT_SUPPORT 0x80 -#define HEVC_DISCARD_NAL 0xf0 -#define HEVC_ACTION_DEC_CONT 0xfd -#define HEVC_ACTION_ERROR 0xfe -#define HEVC_ACTION_DONE 0xff - -/* --------------------------------------------------- */ -/* Include "parser_cmd.h" */ -/* --------------------------------------------------- */ -#define PARSER_CMD_SKIP_CFG_0 0x0000090b - -#define PARSER_CMD_SKIP_CFG_1 0x1b14140f - -#define PARSER_CMD_SKIP_CFG_2 0x001b1910 - -#define PARSER_CMD_NUMBER 37 - -/************************************************** - * - *h265 buffer management - * - *************************************************** - */ -/* #define BUFFER_MGR_ONLY */ -/* #define CONFIG_HEVC_CLK_FORCED_ON */ -/* #define ENABLE_SWAP_TEST */ -#define MCRCC_ENABLE -#define INVALID_POC 0x80000000 - -#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 -#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 -#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 -#define HEVC_VPS_BUFFER HEVC_ASSIST_SCRATCH_3 -#define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 -#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 -#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 -#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 -#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 -#define HEVC_sao_mem_unit HEVC_ASSIST_SCRATCH_9 -#define HEVC_SAO_ABV HEVC_ASSIST_SCRATCH_A -#define HEVC_sao_vb_size HEVC_ASSIST_SCRATCH_B -#define HEVC_SAO_VB HEVC_ASSIST_SCRATCH_C -#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D -#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E -#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F -#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_F -#ifdef ENABLE_SWAP_TEST -#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L -#endif - -/*#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M*/ -/*#define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N*/ -#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N - /*do not define ENABLE_SWAP_TEST*/ -#define HEVC_AUX_ADR HEVC_ASSIST_SCRATCH_L -#define HEVC_AUX_DATA_SIZE HEVC_ASSIST_SCRATCH_M - -#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G -#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H -/* - *ucode parser/search control - *bit 0: 0, header auto parse; 1, header manual parse - *bit 1: 0, auto skip for noneseamless stream; 1, no skip - *bit [3:2]: valid when bit1==0; - *0, auto skip nal before first vps/sps/pps/idr; - *1, auto skip nal before first vps/sps/pps - *2, auto skip nal before first vps/sps/pps, - * and not decode until the first I slice (with slice address of 0) - * - *3, auto skip before first I slice (nal_type >=16 && nal_type<=21) - *bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) ) - *bit [16]: for NAL_UNIT_EOS when bit0 is 0: - * 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm - *bit [17]: for NAL_SEI when bit0 is 0: - * 0, do not parse/fetch SEI in ucode; - * 1, parse/fetch SEI in ucode - *bit [18]: for NAL_SEI_SUFFIX when bit0 is 0: - * 0, do not fetch NAL_SEI_SUFFIX to aux buf; - * 1, fetch NAL_SEL_SUFFIX data to aux buf - *bit [19]: - * 0, parse NAL_SEI in ucode - * 1, fetch NAL_SEI to aux buf - *bit [20]: for DOLBY_VISION_META - * 0, do not fetch DOLBY_VISION_META to aux buf - * 1, fetch DOLBY_VISION_META to aux buf - */ -#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I - /*read only*/ -#define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J - /* - [15 : 8] rps_set_id - [7 : 0] start_decoding_flag - */ -#define HEVC_DECODE_INFO HEVC_ASSIST_SCRATCH_1 - /*set before start decoder*/ -#define HEVC_DECODE_MODE HEVC_ASSIST_SCRATCH_J -#define HEVC_DECODE_MODE2 HEVC_ASSIST_SCRATCH_H -#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K - -#define DECODE_MODE_SINGLE 0x0 -#define DECODE_MODE_MULTI_FRAMEBASE 0x1 -#define DECODE_MODE_MULTI_STREAMBASE 0x2 -#define DECODE_MODE_MULTI_DVBAL 0x3 -#define DECODE_MODE_MULTI_DVENL 0x4 - -#define MAX_INT 0x7FFFFFFF - -#define RPM_BEGIN 0x100 -#define modification_list_cur 0x148 -#define RPM_END 0x180 - -#define RPS_USED_BIT 14 -/* MISC_FLAG0 */ -#define PCM_LOOP_FILTER_DISABLED_FLAG_BIT 0 -#define PCM_ENABLE_FLAG_BIT 1 -#define LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT 2 -#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 3 -#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT 4 -#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 5 -#define DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT 6 -#define SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 7 -#define SLICE_SAO_LUMA_FLAG_BIT 8 -#define SLICE_SAO_CHROMA_FLAG_BIT 9 -#define SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 10 - -union param_u { - struct { - unsigned short data[RPM_END - RPM_BEGIN]; - } l; - struct { - /* from ucode lmem, do not change this struct */ - unsigned short CUR_RPS[0x10]; - unsigned short num_ref_idx_l0_active; - unsigned short num_ref_idx_l1_active; - unsigned short slice_type; - unsigned short slice_temporal_mvp_enable_flag; - unsigned short dependent_slice_segment_flag; - unsigned short slice_segment_address; - unsigned short num_title_rows_minus1; - unsigned short pic_width_in_luma_samples; - unsigned short pic_height_in_luma_samples; - unsigned short log2_min_coding_block_size_minus3; - unsigned short log2_diff_max_min_coding_block_size; - unsigned short log2_max_pic_order_cnt_lsb_minus4; - unsigned short POClsb; - unsigned short collocated_from_l0_flag; - unsigned short collocated_ref_idx; - unsigned short log2_parallel_merge_level; - unsigned short five_minus_max_num_merge_cand; - unsigned short sps_num_reorder_pics_0; - unsigned short modification_flag; - unsigned short tiles_enabled_flag; - unsigned short num_tile_columns_minus1; - unsigned short num_tile_rows_minus1; - unsigned short tile_width[8]; - unsigned short tile_height[8]; - unsigned short misc_flag0; - unsigned short pps_beta_offset_div2; - unsigned short pps_tc_offset_div2; - unsigned short slice_beta_offset_div2; - unsigned short slice_tc_offset_div2; - unsigned short pps_cb_qp_offset; - unsigned short pps_cr_qp_offset; - unsigned short first_slice_segment_in_pic_flag; - unsigned short m_temporalId; - unsigned short m_nalUnitType; - - unsigned short vui_num_units_in_tick_hi; - unsigned short vui_num_units_in_tick_lo; - unsigned short vui_time_scale_hi; - unsigned short vui_time_scale_lo; - unsigned short bit_depth; - unsigned short profile_etc; - unsigned short sei_frame_field_info; - unsigned short video_signal_type; - unsigned short modification_list[0x20]; - unsigned short conformance_window_flag; - unsigned short conf_win_left_offset; - unsigned short conf_win_right_offset; - unsigned short conf_win_top_offset; - unsigned short conf_win_bottom_offset; - unsigned short chroma_format_idc; - unsigned short color_description; - unsigned short aspect_ratio_idc; - unsigned short sar_width; - unsigned short sar_height; - unsigned short sps_max_dec_pic_buffering_minus1_0; - } p; -}; - -#define RPM_BUF_SIZE (0x80*2) -/* non mmu mode lmem size : 0x400, mmu mode : 0x500*/ -#define LMEM_BUF_SIZE (0x500 * 2) - -struct buff_s { - u32 buf_start; - u32 buf_size; - u32 buf_end; -}; - -struct BuffInfo_s { - u32 max_width; - u32 max_height; - unsigned int start_adr; - unsigned int end_adr; - struct buff_s ipp; - struct buff_s sao_abv; - struct buff_s sao_vb; - struct buff_s short_term_rps; - struct buff_s vps; - struct buff_s sps; - struct buff_s pps; - struct buff_s sao_up; - struct buff_s swap_buf; - struct buff_s swap_buf2; - struct buff_s scalelut; - struct buff_s dblk_para; - struct buff_s dblk_data; - struct buff_s dblk_data2; - struct buff_s mmu_vbh; - struct buff_s cm_header; - struct buff_s mpred_above; -#ifdef MV_USE_FIXED_BUF - struct buff_s mpred_mv; -#endif - struct buff_s rpm; - struct buff_s lmem; -}; -#define WORK_BUF_SPEC_NUM 3 -static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { - { - /* 8M bytes */ - .max_width = 1920, - .max_height = 1088, - .ipp = { - /* IPP work space calculation : - * 4096 * (Y+CbCr+Flags) = 12k, round to 16k - */ - .buf_size = 0x4000, - }, - .sao_abv = { - .buf_size = 0x30000, - }, - .sao_vb = { - .buf_size = 0x30000, - }, - .short_term_rps = { - /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, - * total 64x16x2 = 2048 bytes (0x800) - */ - .buf_size = 0x800, - }, - .vps = { - /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .sps = { - /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .pps = { - /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, - * total 0x2000 bytes - */ - .buf_size = 0x2000, - }, - .sao_up = { - /* SAO UP STORE AREA - Max 640(10240/16) LCU, - * each has 16 bytes total 0x2800 bytes - */ - .buf_size = 0x2800, - }, - .swap_buf = { - /* 256cyclex64bit = 2K bytes 0x800 - * (only 144 cycles valid) - */ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /* support up to 32 SCALELUT 1024x32 = - * 32Kbytes (0x8000) - */ - .buf_size = 0x8000, - }, - .dblk_para = { -#ifdef SUPPORT_10BIT - .buf_size = 0x40000, -#else - /* DBLK -> Max 256(4096/16) LCU, each para - *512bytes(total:0x20000), data 1024bytes(total:0x40000) - */ - .buf_size = 0x20000, -#endif - }, - .dblk_data = { - .buf_size = 0x40000, - }, - .dblk_data2 = { - .buf_size = 0x40000, - }, /*dblk data for adapter*/ - .mmu_vbh = { - .buf_size = 0x5000, /*2*16*2304/4, 4K*/ - }, -#if 0 - .cm_header = {/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ - .buf_size = MMU_COMPRESS_HEADER_SIZE * - (MAX_REF_PIC_NUM + 1), - }, -#endif - .mpred_above = { - .buf_size = 0x8000, - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = {/* 1080p, 0x40000 per buffer */ - .buf_size = 0x40000 * MAX_REF_PIC_NUM, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x500 * 2, - } - }, - { - .max_width = 4096, - .max_height = 2048, - .ipp = { - /* IPP work space calculation : - * 4096 * (Y+CbCr+Flags) = 12k, round to 16k - */ - .buf_size = 0x4000, - }, - .sao_abv = { - .buf_size = 0x30000, - }, - .sao_vb = { - .buf_size = 0x30000, - }, - .short_term_rps = { - /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, - * total 64x16x2 = 2048 bytes (0x800) - */ - .buf_size = 0x800, - }, - .vps = { - /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .sps = { - /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .pps = { - /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, - * total 0x2000 bytes - */ - .buf_size = 0x2000, - }, - .sao_up = { - /* SAO UP STORE AREA - Max 640(10240/16) LCU, - * each has 16 bytes total 0x2800 bytes - */ - .buf_size = 0x2800, - }, - .swap_buf = { - /* 256cyclex64bit = 2K bytes 0x800 - * (only 144 cycles valid) - */ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /* support up to 32 SCALELUT 1024x32 = 32Kbytes - * (0x8000) - */ - .buf_size = 0x8000, - }, - .dblk_para = { - /* DBLK -> Max 256(4096/16) LCU, each para - * 512bytes(total:0x20000), - * data 1024bytes(total:0x40000) - */ - .buf_size = 0x20000, - }, - .dblk_data = { - .buf_size = 0x80000, - }, - .dblk_data2 = { - .buf_size = 0x80000, - }, /*dblk data for adapter*/ - .mmu_vbh = { - .buf_size = 0x5000, /*2*16*2304/4, 4K*/ - }, -#if 0 - .cm_header = {/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ - .buf_size = MMU_COMPRESS_HEADER_SIZE * - (MAX_REF_PIC_NUM + 1), - }, -#endif - .mpred_above = { - .buf_size = 0x8000, - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = { - /* .buf_size = 0x100000*16, - //4k2k , 0x100000 per buffer */ - /* 4096x2304 , 0x120000 per buffer */ - .buf_size = MPRED_4K_MV_BUF_SIZE * MAX_REF_PIC_NUM, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x500 * 2, - } - }, - - { - .max_width = 4096*2, - .max_height = 2048*2, - .ipp = { - // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k - .buf_size = 0x4000*2, - }, - .sao_abv = { - .buf_size = 0x30000*2, - }, - .sao_vb = { - .buf_size = 0x30000*2, - }, - .short_term_rps = { - // SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800) - .buf_size = 0x800, - }, - .vps = { - // VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes - .buf_size = 0x800, - }, - .sps = { - // SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes - .buf_size = 0x800, - }, - .pps = { - // PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes - .buf_size = 0x2000, - }, - .sao_up = { - // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes - .buf_size = 0x2800*2, - }, - .swap_buf = { - // 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid) - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) - .buf_size = 0x8000*2, - }, - .dblk_para = {.buf_size = 0x40000*2, }, // dblk parameter - .dblk_data = {.buf_size = 0x80000*2, }, // dblk data for left/top - .dblk_data2 = {.buf_size = 0x80000*2, }, // dblk data for adapter - .mmu_vbh = { - .buf_size = 0x5000*2, //2*16*2304/4, 4K - }, -#if 0 - .cm_header = { - .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * - MAX_REF_PIC_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) - }, -#endif - .mpred_above = { - .buf_size = 0x8000*2, - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = { - .buf_size = MPRED_8K_MV_BUF_SIZE * MAX_REF_PIC_NUM, //4k2k , 0x120000 per buffer - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x500 * 2, - }, - } -}; - -static void init_buff_spec(struct hevc_state_s *hevc, - struct BuffInfo_s *buf_spec) -{ - buf_spec->ipp.buf_start = buf_spec->start_adr; - buf_spec->sao_abv.buf_start = - buf_spec->ipp.buf_start + buf_spec->ipp.buf_size; - - buf_spec->sao_vb.buf_start = - buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size; - buf_spec->short_term_rps.buf_start = - buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size; - buf_spec->vps.buf_start = - buf_spec->short_term_rps.buf_start + - buf_spec->short_term_rps.buf_size; - buf_spec->sps.buf_start = - buf_spec->vps.buf_start + buf_spec->vps.buf_size; - buf_spec->pps.buf_start = - buf_spec->sps.buf_start + buf_spec->sps.buf_size; - buf_spec->sao_up.buf_start = - buf_spec->pps.buf_start + buf_spec->pps.buf_size; - buf_spec->swap_buf.buf_start = - buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size; - buf_spec->swap_buf2.buf_start = - buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size; - buf_spec->scalelut.buf_start = - buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size; - buf_spec->dblk_para.buf_start = - buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size; - buf_spec->dblk_data.buf_start = - buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; - buf_spec->dblk_data2.buf_start = - buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; - buf_spec->mmu_vbh.buf_start = - buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size; - buf_spec->mpred_above.buf_start = - buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; -#ifdef MV_USE_FIXED_BUF - buf_spec->mpred_mv.buf_start = - buf_spec->mpred_above.buf_start + - buf_spec->mpred_above.buf_size; - - buf_spec->rpm.buf_start = - buf_spec->mpred_mv.buf_start + - buf_spec->mpred_mv.buf_size; -#else - buf_spec->rpm.buf_start = - buf_spec->mpred_above.buf_start + - buf_spec->mpred_above.buf_size; -#endif - buf_spec->lmem.buf_start = - buf_spec->rpm.buf_start + - buf_spec->rpm.buf_size; - buf_spec->end_adr = - buf_spec->lmem.buf_start + - buf_spec->lmem.buf_size; - - if (hevc && get_dbg_flag2(hevc)) { - hevc_print(hevc, 0, - "%s workspace (%x %x) size = %x\n", __func__, - buf_spec->start_adr, buf_spec->end_adr, - buf_spec->end_adr - buf_spec->start_adr); - - hevc_print(hevc, 0, - "ipp.buf_start :%x\n", - buf_spec->ipp.buf_start); - hevc_print(hevc, 0, - "sao_abv.buf_start :%x\n", - buf_spec->sao_abv.buf_start); - hevc_print(hevc, 0, - "sao_vb.buf_start :%x\n", - buf_spec->sao_vb.buf_start); - hevc_print(hevc, 0, - "short_term_rps.buf_start :%x\n", - buf_spec->short_term_rps.buf_start); - hevc_print(hevc, 0, - "vps.buf_start :%x\n", - buf_spec->vps.buf_start); - hevc_print(hevc, 0, - "sps.buf_start :%x\n", - buf_spec->sps.buf_start); - hevc_print(hevc, 0, - "pps.buf_start :%x\n", - buf_spec->pps.buf_start); - hevc_print(hevc, 0, - "sao_up.buf_start :%x\n", - buf_spec->sao_up.buf_start); - hevc_print(hevc, 0, - "swap_buf.buf_start :%x\n", - buf_spec->swap_buf.buf_start); - hevc_print(hevc, 0, - "swap_buf2.buf_start :%x\n", - buf_spec->swap_buf2.buf_start); - hevc_print(hevc, 0, - "scalelut.buf_start :%x\n", - buf_spec->scalelut.buf_start); - hevc_print(hevc, 0, - "dblk_para.buf_start :%x\n", - buf_spec->dblk_para.buf_start); - hevc_print(hevc, 0, - "dblk_data.buf_start :%x\n", - buf_spec->dblk_data.buf_start); - hevc_print(hevc, 0, - "dblk_data2.buf_start :%x\n", - buf_spec->dblk_data2.buf_start); - hevc_print(hevc, 0, - "mpred_above.buf_start :%x\n", - buf_spec->mpred_above.buf_start); -#ifdef MV_USE_FIXED_BUF - hevc_print(hevc, 0, - "mpred_mv.buf_start :%x\n", - buf_spec->mpred_mv.buf_start); -#endif - if ((get_dbg_flag2(hevc) - & - H265_DEBUG_SEND_PARAM_WITH_REG) - == 0) { - hevc_print(hevc, 0, - "rpm.buf_start :%x\n", - buf_spec->rpm.buf_start); - } - } - -} - -enum SliceType { - B_SLICE, - P_SLICE, - I_SLICE -}; - -/*USE_BUF_BLOCK*/ -struct BUF_s { - unsigned long start_adr; - unsigned int size; - int used_flag; -} /*BUF_t */; - -/* level 6, 6.1 maximum slice number is 800; other is 200 */ -#define MAX_SLICE_NUM 800 -struct PIC_s { - int index; - int scatter_alloc; - int BUF_index; - int mv_buf_index; - int POC; - int decode_idx; - int slice_type; - int RefNum_L0; - int RefNum_L1; - int num_reorder_pic; - int stream_offset; - unsigned char referenced; - unsigned char output_mark; - unsigned char recon_mark; - unsigned char output_ready; - unsigned char error_mark; - /**/ int slice_idx; - int m_aiRefPOCList0[MAX_SLICE_NUM][16]; - int m_aiRefPOCList1[MAX_SLICE_NUM][16]; - /*buffer */ - unsigned int header_adr; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - unsigned char dv_enhance_exist; -#endif - char *aux_data_buf; - int aux_data_size; - unsigned long cma_alloc_addr; - struct page *alloc_pages; - unsigned int mpred_mv_wr_start_addr; - unsigned int mc_y_adr; - unsigned int mc_u_v_adr; -#ifdef SUPPORT_10BIT - /*unsigned int comp_body_size;*/ - unsigned int dw_y_adr; - unsigned int dw_u_v_adr; -#endif - int mc_canvas_y; - int mc_canvas_u_v; - int width; - int height; - - int y_canvas_index; - int uv_canvas_index; -#ifdef MULTI_INSTANCE_SUPPORT - struct canvas_config_s canvas_config[2]; -#endif -#ifdef SUPPORT_10BIT - int mem_saving_mode; - u32 bit_depth_luma; - u32 bit_depth_chroma; -#endif -#ifdef LOSLESS_COMPRESS_MODE - unsigned int losless_comp_body_size; -#endif - unsigned char pic_struct; - int vf_ref; - - u32 pts; - u64 pts64; - - u32 aspect_ratio_idc; - u32 sar_width; - u32 sar_height; - u32 double_write_mode; - u32 video_signal_type; - unsigned short conformance_window_flag; - unsigned short conf_win_left_offset; - unsigned short conf_win_right_offset; - unsigned short conf_win_top_offset; - unsigned short conf_win_bottom_offset; - unsigned short chroma_format_idc; - - /* picture qos infomation*/ - int max_qp; - int avg_qp; - int min_qp; - int max_skip; - int avg_skip; - int min_skip; - int max_mv; - int min_mv; - int avg_mv; -} /*PIC_t */; - -#define MAX_TILE_COL_NUM 10 -#define MAX_TILE_ROW_NUM 20 -struct tile_s { - int width; - int height; - int start_cu_x; - int start_cu_y; - - unsigned int sao_vb_start_addr; - unsigned int sao_abv_start_addr; -}; - -#define SEI_MASTER_DISPLAY_COLOR_MASK 0x00000001 -#define SEI_CONTENT_LIGHT_LEVEL_MASK 0x00000002 -#define SEI_HDR10PLUS_MASK 0x00000004 - -#define VF_POOL_SIZE 32 - -#ifdef MULTI_INSTANCE_SUPPORT -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_CONFIG_PARAM 3 -#define DEC_RESULT_ERROR 4 -#define DEC_INIT_PICLIST 5 -#define DEC_UNINIT_PICLIST 6 -#define DEC_RESULT_GET_DATA 7 -#define DEC_RESULT_GET_DATA_RETRY 8 -#define DEC_RESULT_EOS 9 -#define DEC_RESULT_FORCE_EXIT 10 - -static void vh265_work(struct work_struct *work); -static void vh265_notify_work(struct work_struct *work); - -#endif - -struct debug_log_s { - struct list_head list; - uint8_t data; /*will alloc more size*/ -}; - -struct hevc_state_s { -#ifdef MULTI_INSTANCE_SUPPORT - struct platform_device *platform_dev; - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - struct vframe_chunk_s *chunk; - int dec_result; - struct work_struct work; - struct work_struct notify_work; - struct work_struct set_clk_work; - /* timeout handle */ - unsigned long int start_process_time; - unsigned int last_lcu_idx; - unsigned int decode_timeout_count; - unsigned int timeout_num; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - unsigned char switch_dvlayer_flag; - unsigned char no_switch_dvlayer_count; - unsigned char bypass_dvenl_enable; - unsigned char bypass_dvenl; -#endif - unsigned char start_parser_type; - /*start_decoding_flag: - vps/pps/sps/idr info from ucode*/ - unsigned char start_decoding_flag; - unsigned char rps_set_id; - unsigned char eos; - int pic_decoded_lcu_idx; - u8 over_decode; - u8 empty_flag; -#endif - struct vframe_s vframe_dummy; - char *provider_name; - int index; - struct device *cma_dev; - unsigned char m_ins_flag; - unsigned char dolby_enhance_flag; - unsigned long buf_start; - u32 buf_size; - u32 mv_buf_size; - - struct BuffInfo_s work_space_buf_store; - struct BuffInfo_s *work_space_buf; - - u8 aux_data_dirty; - u32 prefix_aux_size; - u32 suffix_aux_size; - void *aux_addr; - void *rpm_addr; - void *lmem_addr; - dma_addr_t aux_phy_addr; - dma_addr_t rpm_phy_addr; - dma_addr_t lmem_phy_addr; - - unsigned int pic_list_init_flag; - unsigned int use_cma_flag; - - unsigned short *rpm_ptr; - unsigned short *lmem_ptr; - unsigned short *debug_ptr; - int debug_ptr_size; - int pic_w; - int pic_h; - int lcu_x_num; - int lcu_y_num; - int lcu_total; - int lcu_size; - int lcu_size_log2; - int lcu_x_num_pre; - int lcu_y_num_pre; - int first_pic_after_recover; - - int num_tile_col; - int num_tile_row; - int tile_enabled; - int tile_x; - int tile_y; - int tile_y_x; - int tile_start_lcu_x; - int tile_start_lcu_y; - int tile_width_lcu; - int tile_height_lcu; - - int slice_type; - unsigned int slice_addr; - unsigned int slice_segment_addr; - - unsigned char interlace_flag; - unsigned char curr_pic_struct; - - unsigned short sps_num_reorder_pics_0; - unsigned short misc_flag0; - int m_temporalId; - int m_nalUnitType; - int TMVPFlag; - int isNextSliceSegment; - int LDCFlag; - int m_pocRandomAccess; - int plevel; - int MaxNumMergeCand; - - int new_pic; - int new_tile; - int curr_POC; - int iPrevPOC; -#ifdef MULTI_INSTANCE_SUPPORT - int decoded_poc; - struct PIC_s *decoding_pic; -#endif - int iPrevTid0POC; - int list_no; - int RefNum_L0; - int RefNum_L1; - int ColFromL0Flag; - int LongTerm_Curr; - int LongTerm_Col; - int Col_POC; - int LongTerm_Ref; -#ifdef MULTI_INSTANCE_SUPPORT - int m_pocRandomAccess_bak; - int curr_POC_bak; - int iPrevPOC_bak; - int iPrevTid0POC_bak; - unsigned char start_parser_type_bak; - unsigned char start_decoding_flag_bak; - unsigned char rps_set_id_bak; - int pic_decoded_lcu_idx_bak; - int decode_idx_bak; -#endif - struct PIC_s *cur_pic; - struct PIC_s *col_pic; - int skip_flag; - int decode_idx; - int slice_idx; - unsigned char have_vps; - unsigned char have_sps; - unsigned char have_pps; - unsigned char have_valid_start_slice; - unsigned char wait_buf; - unsigned char error_flag; - unsigned int error_skip_nal_count; - long used_4k_num; - - unsigned char - ignore_bufmgr_error; /* bit 0, for decoding; - bit 1, for displaying - bit 1 must be set if bit 0 is 1*/ - int PB_skip_mode; - int PB_skip_count_after_decoding; -#ifdef SUPPORT_10BIT - int mem_saving_mode; -#endif -#ifdef LOSLESS_COMPRESS_MODE - unsigned int losless_comp_body_size; -#endif - int pts_mode; - int last_lookup_pts; - int last_pts; - u64 last_lookup_pts_us64; - u64 last_pts_us64; - u32 shift_byte_count_lo; - u32 shift_byte_count_hi; - int pts_mode_switching_count; - int pts_mode_recovery_count; - - int pic_num; - - /**/ - union param_u param; - - struct tile_s m_tile[MAX_TILE_ROW_NUM][MAX_TILE_COL_NUM]; - - struct timer_list timer; - struct BUF_s m_BUF[BUF_POOL_SIZE]; - struct BUF_s m_mv_BUF[MAX_REF_PIC_NUM]; - struct PIC_s *m_PIC[MAX_REF_PIC_NUM]; - - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE); - struct vframe_s vfpool[VF_POOL_SIZE]; - - u32 stat; - u32 frame_width; - u32 frame_height; - u32 frame_dur; - u32 frame_ar; - u32 bit_depth_luma; - u32 bit_depth_chroma; - u32 video_signal_type; - u32 video_signal_type_debug; - u32 saved_resolution; - bool get_frame_dur; - u32 error_watchdog_count; - u32 error_skip_nal_wt_cnt; - u32 error_system_watchdog_count; - -#ifdef DEBUG_PTS - unsigned long pts_missed; - unsigned long pts_hit; -#endif - struct dec_sysinfo vh265_amstream_dec_info; - unsigned char init_flag; - unsigned char first_sc_checked; - unsigned char uninit_list; - u32 start_decoding_time; - - int show_frame_num; -#ifdef USE_UNINIT_SEMA - struct semaphore h265_uninit_done_sema; -#endif - int fatal_error; - - - u32 sei_present_flag; - void *frame_mmu_map_addr; - dma_addr_t frame_mmu_map_phy_addr; - unsigned int mmu_mc_buf_start; - unsigned int mmu_mc_buf_end; - unsigned int mmu_mc_start_4k_adr; - void *mmu_box; - void *bmmu_box; - int mmu_enable; - - unsigned int dec_status; - - /* data for SEI_MASTER_DISPLAY_COLOR */ - unsigned int primaries[3][2]; - unsigned int white_point[2]; - unsigned int luminance[2]; - /* data for SEI_CONTENT_LIGHT_LEVEL */ - unsigned int content_light_level[2]; - - struct PIC_s *pre_top_pic; - struct PIC_s *pre_bot_pic; - -#ifdef MULTI_INSTANCE_SUPPORT - int double_write_mode; - int dynamic_buf_num_margin; - int start_action; - int save_buffer_mode; -#endif - u32 i_only; - struct list_head log_list; - u32 ucode_pause_pos; - u32 start_shift_bytes; - - u32 vf_pre_count; - u32 vf_get_count; - u32 vf_put_count; -#ifdef SWAP_HEVC_UCODE - dma_addr_t mc_dma_handle; - void *mc_cpu_addr; - int swap_size; - ulong swap_addr; -#endif -#ifdef DETREFILL_ENABLE - dma_addr_t detbuf_adr; - u16 *detbuf_adr_virt; - u8 delrefill_check; -#endif - u8 head_error_flag; - int valve_count; - struct firmware_s *fw; - int max_pic_w; - int max_pic_h; -#ifdef AGAIN_HAS_THRESHOLD - u8 next_again_flag; - u32 pre_parser_wr_ptr; -#endif - u32 ratio_control; - u32 first_pic_flag; - u32 decode_size; - struct mutex chunks_mutex; - int need_cache_size; - u64 sc_start_time; - u32 skip_first_nal; - bool is_swap; - bool is_4k; - - int frameinfo_enable; - struct vframe_qos_s vframe_qos; -} /*hevc_stru_t */; - -#ifdef AGAIN_HAS_THRESHOLD -u32 again_threshold = 0x40; -#endif -#ifdef SEND_LMEM_WITH_RPM -#define get_lmem_params(hevc, ladr) \ - hevc->lmem_ptr[ladr - (ladr & 0x3) + 3 - (ladr & 0x3)] - - -static int get_frame_mmu_map_size(void) -{ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - return (MAX_FRAME_8K_NUM * 4); - - return (MAX_FRAME_4K_NUM * 4); -} - -static int is_oversize(int w, int h) -{ - int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? - MAX_SIZE_8K : MAX_SIZE_4K; - - if (w < 0 || h < 0) - return true; - - if (h != 0 && (w > max / h)) - return true; - - return false; -} - -void check_head_error(struct hevc_state_s *hevc) -{ -#define pcm_enabled_flag 0x040 -#define pcm_sample_bit_depth_luma 0x041 -#define pcm_sample_bit_depth_chroma 0x042 - hevc->head_error_flag = 0; - if ((error_handle_policy & 0x40) == 0) - return; - if (get_lmem_params(hevc, pcm_enabled_flag)) { - uint16_t pcm_depth_luma = get_lmem_params( - hevc, pcm_sample_bit_depth_luma); - uint16_t pcm_sample_chroma = get_lmem_params( - hevc, pcm_sample_bit_depth_chroma); - if (pcm_depth_luma > - hevc->bit_depth_luma || - pcm_sample_chroma > - hevc->bit_depth_chroma) { - hevc_print(hevc, 0, - "error, pcm bit depth %d, %d is greater than normal bit depth %d, %d\n", - pcm_depth_luma, - pcm_sample_chroma, - hevc->bit_depth_luma, - hevc->bit_depth_chroma); - hevc->head_error_flag = 1; - } - } -} -#endif - -#ifdef SUPPORT_10BIT -/* Losless compression body buffer size 4K per 64x32 (jt) */ -static int compute_losless_comp_body_size(struct hevc_state_s *hevc, - int width, int height, int mem_saving_mode) -{ - int width_x64; - int height_x32; - int bsize; - - width_x64 = width + 63; - width_x64 >>= 6; - - height_x32 = height + 31; - height_x32 >>= 5; - if (mem_saving_mode == 1 && hevc->mmu_enable) - bsize = 3200 * width_x64 * height_x32; - else if (mem_saving_mode == 1) - bsize = 3072 * width_x64 * height_x32; - else - bsize = 4096 * width_x64 * height_x32; - - return bsize; -} - -/* Losless compression header buffer size 32bytes per 128x64 (jt) */ -static int compute_losless_comp_header_size(int width, int height) -{ - int width_x128; - int height_x64; - int hsize; - - width_x128 = width + 127; - width_x128 >>= 7; - - height_x64 = height + 63; - height_x64 >>= 6; - - hsize = 32*width_x128*height_x64; - - return hsize; -} -#endif - -static int add_log(struct hevc_state_s *hevc, - const char *fmt, ...) -{ -#define HEVC_LOG_BUF 196 - struct debug_log_s *log_item; - unsigned char buf[HEVC_LOG_BUF]; - int len = 0; - va_list args; - mutex_lock(&vh265_log_mutex); - va_start(args, fmt); - len = sprintf(buf, "<%ld> <%05d> ", - jiffies, hevc->decode_idx); - len += vsnprintf(buf + len, - HEVC_LOG_BUF - len, fmt, args); - va_end(args); - log_item = kmalloc( - sizeof(struct debug_log_s) + len, - GFP_KERNEL); - if (log_item) { - INIT_LIST_HEAD(&log_item->list); - strcpy(&log_item->data, buf); - list_add_tail(&log_item->list, - &hevc->log_list); - } - mutex_unlock(&vh265_log_mutex); - return 0; -} - -static void dump_log(struct hevc_state_s *hevc) -{ - int i = 0; - struct debug_log_s *log_item, *tmp; - mutex_lock(&vh265_log_mutex); - list_for_each_entry_safe(log_item, tmp, &hevc->log_list, list) { - hevc_print(hevc, 0, - "[LOG%04d]%s\n", - i++, - &log_item->data); - list_del(&log_item->list); - kfree(log_item); - } - mutex_unlock(&vh265_log_mutex); -} - -static unsigned char is_skip_decoding(struct hevc_state_s *hevc, - struct PIC_s *pic) -{ - if (pic->error_mark - && ((hevc->ignore_bufmgr_error & 0x1) == 0)) - return 1; - return 0; -} - -static int get_pic_poc(struct hevc_state_s *hevc, - unsigned int idx) -{ - if (idx != 0xff - && idx < MAX_REF_PIC_NUM - && hevc->m_PIC[idx]) - return hevc->m_PIC[idx]->POC; - return INVALID_POC; -} - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -static int get_valid_double_write_mode(struct hevc_state_s *hevc) -{ - return (hevc->m_ins_flag && - ((double_write_mode & 0x80000000) == 0)) ? - hevc->double_write_mode : - (double_write_mode & 0x7fffffff); -} - -static int get_dynamic_buf_num_margin(struct hevc_state_s *hevc) -{ - return (hevc->m_ins_flag && - ((dynamic_buf_num_margin & 0x80000000) == 0)) ? - hevc->dynamic_buf_num_margin : - (dynamic_buf_num_margin & 0x7fffffff); -} -#endif - -static int get_double_write_mode(struct hevc_state_s *hevc) -{ - u32 valid_dw_mode = get_valid_double_write_mode(hevc); - u32 dw = hevc->double_write_mode; - if (valid_dw_mode == 0x100) { - int w = hevc->pic_w; - int h = hevc->pic_h; - if (w > 1920 && h > 1088) - dw = 0x4; /*1:2*/ - else - dw = 0x1; /*1:1*/ - - } else - dw = valid_dw_mode; - return dw; -} - -static int get_double_write_ratio(struct hevc_state_s *hevc, - int dw_mode) -{ - int ratio = 1; - if ((dw_mode == 2) || - (dw_mode == 3)) - ratio = 4; - else if (dw_mode == 4) - ratio = 2; - return ratio; -} -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -static unsigned char get_idx(struct hevc_state_s *hevc) -{ - return hevc->index; -} -#endif - -#undef pr_info -#define pr_info printk -static int hevc_print(struct hevc_state_s *hevc, - int flag, const char *fmt, ...) -{ -#define HEVC_PRINT_BUF 256 - unsigned char buf[HEVC_PRINT_BUF]; - int len = 0; -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (hevc == NULL || - (flag == 0) || - ((debug_mask & - (1 << hevc->index)) - && (debug & flag))) { -#endif - va_list args; - - va_start(args, fmt); - if (hevc) - len = sprintf(buf, "[%d]", hevc->index); - vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); - pr_debug("%s", buf); - va_end(args); -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - } -#endif - return 0; -} - -static int hevc_print_cont(struct hevc_state_s *hevc, - int flag, const char *fmt, ...) -{ - unsigned char buf[HEVC_PRINT_BUF]; - int len = 0; -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (hevc == NULL || - (flag == 0) || - ((debug_mask & - (1 << hevc->index)) - && (debug & flag))) { -#endif - va_list args; - - va_start(args, fmt); - vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); - pr_info("%s", buf); - va_end(args); -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - } -#endif - return 0; -} - -static void put_mv_buf(struct hevc_state_s *hevc, - struct PIC_s *pic); - -static void update_vf_memhandle(struct hevc_state_s *hevc, - struct vframe_s *vf, struct PIC_s *pic); - -static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic); - -static void release_aux_data(struct hevc_state_s *hevc, - struct PIC_s *pic); -static void release_pic_mmu_buf(struct hevc_state_s *hevc, struct PIC_s *pic); - -#ifdef MULTI_INSTANCE_SUPPORT -static void backup_decode_state(struct hevc_state_s *hevc) -{ - hevc->m_pocRandomAccess_bak = hevc->m_pocRandomAccess; - hevc->curr_POC_bak = hevc->curr_POC; - hevc->iPrevPOC_bak = hevc->iPrevPOC; - hevc->iPrevTid0POC_bak = hevc->iPrevTid0POC; - hevc->start_parser_type_bak = hevc->start_parser_type; - hevc->start_decoding_flag_bak = hevc->start_decoding_flag; - hevc->rps_set_id_bak = hevc->rps_set_id; - hevc->pic_decoded_lcu_idx_bak = hevc->pic_decoded_lcu_idx; - hevc->decode_idx_bak = hevc->decode_idx; - -} - -static void restore_decode_state(struct hevc_state_s *hevc) -{ - struct vdec_s *vdec = hw_to_vdec(hevc); - if (!vdec_has_more_input(vdec)) { - hevc->pic_decoded_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff; - return; - } - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: discard pic index 0x%x\n", - __func__, hevc->decoding_pic ? - hevc->decoding_pic->index : 0xff); - if (hevc->decoding_pic) { - hevc->decoding_pic->error_mark = 0; - hevc->decoding_pic->output_ready = 0; - hevc->decoding_pic->output_mark = 0; - hevc->decoding_pic->referenced = 0; - hevc->decoding_pic->POC = INVALID_POC; - put_mv_buf(hevc, hevc->decoding_pic); - release_pic_mmu_buf(hevc, hevc->decoding_pic); - release_aux_data(hevc, hevc->decoding_pic); - hevc->decoding_pic = NULL; - } - hevc->decode_idx = hevc->decode_idx_bak; - hevc->m_pocRandomAccess = hevc->m_pocRandomAccess_bak; - hevc->curr_POC = hevc->curr_POC_bak; - hevc->iPrevPOC = hevc->iPrevPOC_bak; - hevc->iPrevTid0POC = hevc->iPrevTid0POC_bak; - hevc->start_parser_type = hevc->start_parser_type_bak; - hevc->start_decoding_flag = hevc->start_decoding_flag_bak; - hevc->rps_set_id = hevc->rps_set_id_bak; - hevc->pic_decoded_lcu_idx = hevc->pic_decoded_lcu_idx_bak; - - if (hevc->pic_list_init_flag == 1) - hevc->pic_list_init_flag = 0; - /*if (hevc->decode_idx == 0) - hevc->start_decoding_flag = 0;*/ - - hevc->slice_idx = 0; - hevc->used_4k_num = -1; -} -#endif - -static void hevc_init_stru(struct hevc_state_s *hevc, - struct BuffInfo_s *buf_spec_i) -{ - int i; - INIT_LIST_HEAD(&hevc->log_list); - hevc->work_space_buf = buf_spec_i; - hevc->prefix_aux_size = 0; - hevc->suffix_aux_size = 0; - hevc->aux_addr = NULL; - hevc->rpm_addr = NULL; - hevc->lmem_addr = NULL; - - hevc->curr_POC = INVALID_POC; - - hevc->pic_list_init_flag = 0; - hevc->use_cma_flag = 0; - hevc->decode_idx = 0; - hevc->slice_idx = 0; - hevc->new_pic = 0; - hevc->new_tile = 0; - hevc->iPrevPOC = 0; - hevc->list_no = 0; - /* int m_uiMaxCUWidth = 1<<7; */ - /* int m_uiMaxCUHeight = 1<<7; */ - hevc->m_pocRandomAccess = MAX_INT; - hevc->tile_enabled = 0; - hevc->tile_x = 0; - hevc->tile_y = 0; - hevc->iPrevTid0POC = 0; - hevc->slice_addr = 0; - hevc->slice_segment_addr = 0; - hevc->skip_flag = 0; - hevc->misc_flag0 = 0; - - hevc->cur_pic = NULL; - hevc->col_pic = NULL; - hevc->wait_buf = 0; - hevc->error_flag = 0; - hevc->head_error_flag = 0; - hevc->error_skip_nal_count = 0; - hevc->have_vps = 0; - hevc->have_sps = 0; - hevc->have_pps = 0; - hevc->have_valid_start_slice = 0; - - hevc->pts_mode = PTS_NORMAL; - hevc->last_pts = 0; - hevc->last_lookup_pts = 0; - hevc->last_pts_us64 = 0; - hevc->last_lookup_pts_us64 = 0; - hevc->pts_mode_switching_count = 0; - hevc->pts_mode_recovery_count = 0; - - hevc->PB_skip_mode = nal_skip_policy & 0x3; - hevc->PB_skip_count_after_decoding = (nal_skip_policy >> 16) & 0xffff; - if (hevc->PB_skip_mode == 0) - hevc->ignore_bufmgr_error = 0x1; - else - hevc->ignore_bufmgr_error = 0x0; - - for (i = 0; i < MAX_REF_PIC_NUM; i++) - hevc->m_PIC[i] = NULL; - hevc->pic_num = 0; - hevc->lcu_x_num_pre = 0; - hevc->lcu_y_num_pre = 0; - hevc->first_pic_after_recover = 0; - - hevc->pre_top_pic = NULL; - hevc->pre_bot_pic = NULL; - - hevc->sei_present_flag = 0; - hevc->valve_count = 0; - hevc->first_pic_flag = 0; -#ifdef MULTI_INSTANCE_SUPPORT - hevc->decoded_poc = INVALID_POC; - hevc->start_process_time = 0; - hevc->last_lcu_idx = 0; - hevc->decode_timeout_count = 0; - hevc->timeout_num = 0; - hevc->eos = 0; - hevc->pic_decoded_lcu_idx = -1; - hevc->over_decode = 0; - hevc->used_4k_num = -1; - hevc->start_decoding_flag = 0; - hevc->rps_set_id = 0; - backup_decode_state(hevc); -#endif -#ifdef DETREFILL_ENABLE - hevc->detbuf_adr = 0; - hevc->detbuf_adr_virt = NULL; -#endif -} - -static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic); -static int H265_alloc_mmu(struct hevc_state_s *hevc, - struct PIC_s *new_pic, unsigned short bit_depth, - unsigned int *mmu_index_adr); - -#ifdef DETREFILL_ENABLE -#define DETREFILL_BUF_SIZE (4 * 0x4000) -#define HEVC_SAO_DBG_MODE0 0x361e -#define HEVC_SAO_DBG_MODE1 0x361f -#define HEVC_SAO_CTRL10 0x362e -#define HEVC_SAO_CTRL11 0x362f -static int init_detrefill_buf(struct hevc_state_s *hevc) -{ - if (hevc->detbuf_adr_virt) - return 0; - - hevc->detbuf_adr_virt = - (void *)dma_alloc_coherent(amports_get_dma_device(), - DETREFILL_BUF_SIZE, &hevc->detbuf_adr, - GFP_KERNEL); - - if (hevc->detbuf_adr_virt == NULL) { - pr_err("%s: failed to alloc ETREFILL_BUF\n", __func__); - return -1; - } - return 0; -} - -static void uninit_detrefill_buf(struct hevc_state_s *hevc) -{ - if (hevc->detbuf_adr_virt) { - dma_free_coherent(amports_get_dma_device(), - DETREFILL_BUF_SIZE, hevc->detbuf_adr_virt, - hevc->detbuf_adr); - - hevc->detbuf_adr_virt = NULL; - hevc->detbuf_adr = 0; - } -} - -/* - * convert uncompressed frame buffer data from/to ddr - */ -static void convUnc8x4blk(uint16_t* blk8x4Luma, - uint16_t* blk8x4Cb, uint16_t* blk8x4Cr, uint16_t* cmBodyBuf, int32_t direction) -{ - if (direction == 0) { - blk8x4Luma[3 + 0 * 8] = ((cmBodyBuf[0] >> 0)) & 0x3ff; - blk8x4Luma[3 + 1 * 8] = ((cmBodyBuf[1] << 6) - | (cmBodyBuf[0] >> 10)) & 0x3ff; - blk8x4Luma[3 + 2 * 8] = ((cmBodyBuf[1] >> 4)) & 0x3ff; - blk8x4Luma[3 + 3 * 8] = ((cmBodyBuf[2] << 2) - | (cmBodyBuf[1] >> 14)) & 0x3ff; - blk8x4Luma[7 + 0 * 8] = ((cmBodyBuf[3] << 8) - | (cmBodyBuf[2] >> 8)) & 0x3ff; - blk8x4Luma[7 + 1 * 8] = ((cmBodyBuf[3] >> 2)) & 0x3ff; - blk8x4Luma[7 + 2 * 8] = ((cmBodyBuf[4] << 4) - | (cmBodyBuf[3] >> 12)) & 0x3ff; - blk8x4Luma[7 + 3 * 8] = ((cmBodyBuf[4] >> 6)) & 0x3ff; - blk8x4Cb [0 + 0 * 4] = ((cmBodyBuf[5] >> 0)) & 0x3ff; - blk8x4Cr [0 + 0 * 4] = ((cmBodyBuf[6] << 6) - | (cmBodyBuf[5] >> 10)) & 0x3ff; - blk8x4Cb [0 + 1 * 4] = ((cmBodyBuf[6] >> 4)) & 0x3ff; - blk8x4Cr [0 + 1 * 4] = ((cmBodyBuf[7] << 2) - | (cmBodyBuf[6] >> 14)) & 0x3ff; - - blk8x4Luma[0 + 0 * 8] = ((cmBodyBuf[0 + 8] >> 0)) & 0x3ff; - blk8x4Luma[1 + 0 * 8] = ((cmBodyBuf[1 + 8] << 6) | - (cmBodyBuf[0 + 8] >> 10)) & 0x3ff; - blk8x4Luma[2 + 0 * 8] = ((cmBodyBuf[1 + 8] >> 4)) & 0x3ff; - blk8x4Luma[0 + 1 * 8] = ((cmBodyBuf[2 + 8] << 2) | - (cmBodyBuf[1 + 8] >> 14)) & 0x3ff; - blk8x4Luma[1 + 1 * 8] = ((cmBodyBuf[3 + 8] << 8) | - (cmBodyBuf[2 + 8] >> 8)) & 0x3ff; - blk8x4Luma[2 + 1 * 8] = ((cmBodyBuf[3 + 8] >> 2)) & 0x3ff; - blk8x4Luma[0 + 2 * 8] = ((cmBodyBuf[4 + 8] << 4) | - (cmBodyBuf[3 + 8] >> 12)) & 0x3ff; - blk8x4Luma[1 + 2 * 8] = ((cmBodyBuf[4 + 8] >> 6)) & 0x3ff; - blk8x4Luma[2 + 2 * 8] = ((cmBodyBuf[5 + 8] >> 0)) & 0x3ff; - blk8x4Luma[0 + 3 * 8] = ((cmBodyBuf[6 + 8] << 6) | - (cmBodyBuf[5 + 8] >> 10)) & 0x3ff; - blk8x4Luma[1 + 3 * 8] = ((cmBodyBuf[6 + 8] >> 4)) & 0x3ff; - blk8x4Luma[2 + 3 * 8] = ((cmBodyBuf[7 + 8] << 2) | - (cmBodyBuf[6 + 8] >> 14)) & 0x3ff; - - blk8x4Luma[4 + 0 * 8] = ((cmBodyBuf[0 + 16] >> 0)) & 0x3ff; - blk8x4Luma[5 + 0 * 8] = ((cmBodyBuf[1 + 16] << 6) | - (cmBodyBuf[0 + 16] >> 10)) & 0x3ff; - blk8x4Luma[6 + 0 * 8] = ((cmBodyBuf[1 + 16] >> 4)) & 0x3ff; - blk8x4Luma[4 + 1 * 8] = ((cmBodyBuf[2 + 16] << 2) | - (cmBodyBuf[1 + 16] >> 14)) & 0x3ff; - blk8x4Luma[5 + 1 * 8] = ((cmBodyBuf[3 + 16] << 8) | - (cmBodyBuf[2 + 16] >> 8)) & 0x3ff; - blk8x4Luma[6 + 1 * 8] = ((cmBodyBuf[3 + 16] >> 2)) & 0x3ff; - blk8x4Luma[4 + 2 * 8] = ((cmBodyBuf[4 + 16] << 4) | - (cmBodyBuf[3 + 16] >> 12)) & 0x3ff; - blk8x4Luma[5 + 2 * 8] = ((cmBodyBuf[4 + 16] >> 6)) & 0x3ff; - blk8x4Luma[6 + 2 * 8] = ((cmBodyBuf[5 + 16] >> 0)) & 0x3ff; - blk8x4Luma[4 + 3 * 8] = ((cmBodyBuf[6 + 16] << 6) | - (cmBodyBuf[5 + 16] >> 10)) & 0x3ff; - blk8x4Luma[5 + 3 * 8] = ((cmBodyBuf[6 + 16] >> 4)) & 0x3ff; - blk8x4Luma[6 + 3 * 8] = ((cmBodyBuf[7 + 16] << 2) | - (cmBodyBuf[6 + 16] >> 14)) & 0x3ff; - - blk8x4Cb[1 + 0 * 4] = ((cmBodyBuf[0 + 24] >> 0)) & 0x3ff; - blk8x4Cr[1 + 0 * 4] = ((cmBodyBuf[1 + 24] << 6) | - (cmBodyBuf[0 + 24] >> 10)) & 0x3ff; - blk8x4Cb[2 + 0 * 4] = ((cmBodyBuf[1 + 24] >> 4)) & 0x3ff; - blk8x4Cr[2 + 0 * 4] = ((cmBodyBuf[2 + 24] << 2) | - (cmBodyBuf[1 + 24] >> 14)) & 0x3ff; - blk8x4Cb[3 + 0 * 4] = ((cmBodyBuf[3 + 24] << 8) | - (cmBodyBuf[2 + 24] >> 8)) & 0x3ff; - blk8x4Cr[3 + 0 * 4] = ((cmBodyBuf[3 + 24] >> 2)) & 0x3ff; - blk8x4Cb[1 + 1 * 4] = ((cmBodyBuf[4 + 24] << 4) | - (cmBodyBuf[3 + 24] >> 12)) & 0x3ff; - blk8x4Cr[1 + 1 * 4] = ((cmBodyBuf[4 + 24] >> 6)) & 0x3ff; - blk8x4Cb[2 + 1 * 4] = ((cmBodyBuf[5 + 24] >> 0)) & 0x3ff; - blk8x4Cr[2 + 1 * 4] = ((cmBodyBuf[6 + 24] << 6) | - (cmBodyBuf[5 + 24] >> 10)) & 0x3ff; - blk8x4Cb[3 + 1 * 4] = ((cmBodyBuf[6 + 24] >> 4)) & 0x3ff; - blk8x4Cr[3 + 1 * 4] = ((cmBodyBuf[7 + 24] << 2) | - (cmBodyBuf[6 + 24] >> 14)) & 0x3ff; - } else { - cmBodyBuf[0 + 8 * 0] = (blk8x4Luma[3 + 1 * 8] << 10) | - blk8x4Luma[3 + 0 * 8]; - cmBodyBuf[1 + 8 * 0] = (blk8x4Luma[3 + 3 * 8] << 14) | - (blk8x4Luma[3 + 2 * 8] << 4) | (blk8x4Luma[3 + 1 * 8] >> 6); - cmBodyBuf[2 + 8 * 0] = (blk8x4Luma[7 + 0 * 8] << 8) | - (blk8x4Luma[3 + 3 * 8] >> 2); - cmBodyBuf[3 + 8 * 0] = (blk8x4Luma[7 + 2 * 8] << 12) | - (blk8x4Luma[7 + 1 * 8] << 2) | (blk8x4Luma[7 + 0 * 8] >>8); - cmBodyBuf[4 + 8 * 0] = (blk8x4Luma[7 + 3 * 8] << 6) | - (blk8x4Luma[7 + 2 * 8] >>4); - cmBodyBuf[5 + 8 * 0] = (blk8x4Cr[0 + 0 * 4] << 10) | - blk8x4Cb[0 + 0 * 4]; - cmBodyBuf[6 + 8 * 0] = (blk8x4Cr[0 + 1 * 4] << 14) | - (blk8x4Cb[0 + 1 * 4] << 4) | (blk8x4Cr[0 + 0 * 4] >> 6); - cmBodyBuf[7 + 8 * 0] = (0<< 8) | (blk8x4Cr[0 + 1 * 4] >> 2); - - cmBodyBuf[0 + 8 * 1] = (blk8x4Luma[1 + 0 * 8] << 10) | - blk8x4Luma[0 + 0 * 8]; - cmBodyBuf[1 + 8 * 1] = (blk8x4Luma[0 + 1 * 8] << 14) | - (blk8x4Luma[2 + 0 * 8] << 4) | (blk8x4Luma[1 + 0 * 8] >> 6); - cmBodyBuf[2 + 8 * 1] = (blk8x4Luma[1 + 1 * 8] << 8) | - (blk8x4Luma[0 + 1 * 8] >> 2); - cmBodyBuf[3 + 8 * 1] = (blk8x4Luma[0 + 2 * 8] << 12) | - (blk8x4Luma[2 + 1 * 8] << 2) | (blk8x4Luma[1 + 1 * 8] >>8); - cmBodyBuf[4 + 8 * 1] = (blk8x4Luma[1 + 2 * 8] << 6) | - (blk8x4Luma[0 + 2 * 8] >>4); - cmBodyBuf[5 + 8 * 1] = (blk8x4Luma[0 + 3 * 8] << 10) | - blk8x4Luma[2 + 2 * 8]; - cmBodyBuf[6 + 8 * 1] = (blk8x4Luma[2 + 3 * 8] << 14) | - (blk8x4Luma[1 + 3 * 8] << 4) | (blk8x4Luma[0 + 3 * 8] >> 6); - cmBodyBuf[7 + 8 * 1] = (0<< 8) | (blk8x4Luma[2 + 3 * 8] >> 2); - - cmBodyBuf[0 + 8 * 2] = (blk8x4Luma[5 + 0 * 8] << 10) | - blk8x4Luma[4 + 0 * 8]; - cmBodyBuf[1 + 8 * 2] = (blk8x4Luma[4 + 1 * 8] << 14) | - (blk8x4Luma[6 + 0 * 8] << 4) | (blk8x4Luma[5 + 0 * 8] >> 6); - cmBodyBuf[2 + 8 * 2] = (blk8x4Luma[5 + 1 * 8] << 8) | - (blk8x4Luma[4 + 1 * 8] >> 2); - cmBodyBuf[3 + 8 * 2] = (blk8x4Luma[4 + 2 * 8] << 12) | - (blk8x4Luma[6 + 1 * 8] << 2) | (blk8x4Luma[5 + 1 * 8] >>8); - cmBodyBuf[4 + 8 * 2] = (blk8x4Luma[5 + 2 * 8] << 6) | - (blk8x4Luma[4 + 2 * 8] >>4); - cmBodyBuf[5 + 8 * 2] = (blk8x4Luma[4 + 3 * 8] << 10) | - blk8x4Luma[6 + 2 * 8]; - cmBodyBuf[6 + 8 * 2] = (blk8x4Luma[6 + 3 * 8] << 14) | - (blk8x4Luma[5 + 3 * 8] << 4) | (blk8x4Luma[4 + 3 * 8] >> 6); - cmBodyBuf[7 + 8 * 2] = (0<< 8) | (blk8x4Luma[6 + 3 * 8] >> 2); - - cmBodyBuf[0 + 8 * 3] = (blk8x4Cr[1 + 0 * 4] << 10) | - blk8x4Cb[1 + 0 * 4]; - cmBodyBuf[1 + 8 * 3] = (blk8x4Cr[2 + 0 * 4] << 14) | - (blk8x4Cb[2 + 0 * 4] << 4) | (blk8x4Cr[1 + 0 * 4] >> 6); - cmBodyBuf[2 + 8 * 3] = (blk8x4Cb[3 + 0 * 4] << 8) | - (blk8x4Cr[2 + 0 * 4] >> 2); - cmBodyBuf[3 + 8 * 3] = (blk8x4Cb[1 + 1 * 4] << 12) | - (blk8x4Cr[3 + 0 * 4] << 2) | (blk8x4Cb[3 + 0 * 4] >>8); - cmBodyBuf[4 + 8 * 3] = (blk8x4Cr[1 + 1 * 4] << 6) | - (blk8x4Cb[1 + 1 * 4] >>4); - cmBodyBuf[5 + 8 * 3] = (blk8x4Cr[2 + 1 * 4] << 10) | - blk8x4Cb[2 + 1 * 4]; - cmBodyBuf[6 + 8 * 3] = (blk8x4Cr[3 + 1 * 4] << 14) | - (blk8x4Cb[3 + 1 * 4] << 4) | (blk8x4Cr[2 + 1 * 4] >> 6); - cmBodyBuf[7 + 8 * 3] = (0 << 8) | (blk8x4Cr[3 + 1 * 4] >> 2); - } -} - -static void corrRefillWithAmrisc ( - struct hevc_state_s *hevc, - uint32_t cmHeaderBaseAddr, - uint32_t picWidth, - uint32_t ctuPosition) -{ - int32_t i; - uint16_t ctux = (ctuPosition>>16) & 0xffff; - uint16_t ctuy = (ctuPosition>> 0) & 0xffff; - int32_t aboveCtuAvailable = (ctuy) ? 1 : 0; - - uint16_t cmBodyBuf[32 * 18]; - - uint32_t pic_width_x64_pre = picWidth + 0x3f; - uint32_t pic_width_x64 = pic_width_x64_pre >> 6; - uint32_t stride64x64 = pic_width_x64 * 128; - uint32_t addr_offset64x64_abv = stride64x64 * - (aboveCtuAvailable ? ctuy - 1 : ctuy) + 128 * ctux; - uint32_t addr_offset64x64_cur = stride64x64*ctuy + 128 * ctux; - uint32_t cmHeaderAddrAbv = cmHeaderBaseAddr + addr_offset64x64_abv; - uint32_t cmHeaderAddrCur = cmHeaderBaseAddr + addr_offset64x64_cur; - unsigned int tmpData32; - - uint16_t blkBuf0Y[32]; - uint16_t blkBuf0Cb[8]; - uint16_t blkBuf0Cr[8]; - uint16_t blkBuf1Y[32]; - uint16_t blkBuf1Cb[8]; - uint16_t blkBuf1Cr[8]; - int32_t blkBufCnt = 0; - - int32_t blkIdx; - - WRITE_VREG(HEVC_SAO_CTRL10, cmHeaderAddrAbv); - WRITE_VREG(HEVC_SAO_CTRL11, cmHeaderAddrCur); - WRITE_VREG(HEVC_SAO_DBG_MODE0, hevc->detbuf_adr); - WRITE_VREG(HEVC_SAO_DBG_MODE1, 2); - - for (i = 0; i < 32 * 18; i++) - cmBodyBuf[i] = 0; - - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s, %d\n", __func__, __LINE__); - do { - tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1); - } while (tmpData32); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s, %d\n", __func__, __LINE__); - - hevc_print(hevc, H265_DEBUG_DETAIL, - "cmBodyBuf from detbuf:\n"); - for (i = 0; i < 32 * 18; i++) { - cmBodyBuf[i] = hevc->detbuf_adr_virt[i]; - if (get_dbg_flag(hevc) & - H265_DEBUG_DETAIL) { - if ((i & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]); - } - } - hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n"); - - for (i = 0; i < 32; i++) - blkBuf0Y[i] = 0; - for (i = 0; i < 8; i++) - blkBuf0Cb[i] = 0; - for (i = 0; i < 8; i++) - blkBuf0Cr[i] = 0; - for (i = 0; i < 32; i++) - blkBuf1Y[i] = 0; - for (i = 0; i < 8; i++) - blkBuf1Cb[i] = 0; - for (i = 0; i < 8; i++) - blkBuf1Cr[i] = 0; - - for (blkIdx = 0; blkIdx < 18; blkIdx++) { - int32_t inAboveCtu = (blkIdx<2) ? 1 : 0; - int32_t restoreEnable = (blkIdx>0) ? 1 : 0; - uint16_t* blkY = (blkBufCnt==0) ? blkBuf0Y : blkBuf1Y ; - uint16_t* blkCb = (blkBufCnt==0) ? blkBuf0Cb : blkBuf1Cb; - uint16_t* blkCr = (blkBufCnt==0) ? blkBuf0Cr : blkBuf1Cr; - uint16_t* cmBodyBufNow = cmBodyBuf + (blkIdx * 32); - - if (!aboveCtuAvailable && inAboveCtu) - continue; - - /* detRefillBuf --> 8x4block*/ - convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 0); - - if (restoreEnable) { - blkY[3 + 0 * 8] = blkY[2 + 0 * 8] + 2; - blkY[4 + 0 * 8] = blkY[1 + 0 * 8] + 3; - blkY[5 + 0 * 8] = blkY[0 + 0 * 8] + 1; - blkY[6 + 0 * 8] = blkY[0 + 0 * 8] + 2; - blkY[7 + 0 * 8] = blkY[1 + 0 * 8] + 2; - blkY[3 + 1 * 8] = blkY[2 + 1 * 8] + 1; - blkY[4 + 1 * 8] = blkY[1 + 1 * 8] + 2; - blkY[5 + 1 * 8] = blkY[0 + 1 * 8] + 2; - blkY[6 + 1 * 8] = blkY[0 + 1 * 8] + 2; - blkY[7 + 1 * 8] = blkY[1 + 1 * 8] + 3; - blkY[3 + 2 * 8] = blkY[2 + 2 * 8] + 3; - blkY[4 + 2 * 8] = blkY[1 + 2 * 8] + 1; - blkY[5 + 2 * 8] = blkY[0 + 2 * 8] + 3; - blkY[6 + 2 * 8] = blkY[0 + 2 * 8] + 3; - blkY[7 + 2 * 8] = blkY[1 + 2 * 8] + 3; - blkY[3 + 3 * 8] = blkY[2 + 3 * 8] + 0; - blkY[4 + 3 * 8] = blkY[1 + 3 * 8] + 0; - blkY[5 + 3 * 8] = blkY[0 + 3 * 8] + 1; - blkY[6 + 3 * 8] = blkY[0 + 3 * 8] + 2; - blkY[7 + 3 * 8] = blkY[1 + 3 * 8] + 1; - blkCb[1 + 0 * 4] = blkCb[0 + 0 * 4]; - blkCb[2 + 0 * 4] = blkCb[0 + 0 * 4]; - blkCb[3 + 0 * 4] = blkCb[0 + 0 * 4]; - blkCb[1 + 1 * 4] = blkCb[0 + 1 * 4]; - blkCb[2 + 1 * 4] = blkCb[0 + 1 * 4]; - blkCb[3 + 1 * 4] = blkCb[0 + 1 * 4]; - blkCr[1 + 0 * 4] = blkCr[0 + 0 * 4]; - blkCr[2 + 0 * 4] = blkCr[0 + 0 * 4]; - blkCr[3 + 0 * 4] = blkCr[0 + 0 * 4]; - blkCr[1 + 1 * 4] = blkCr[0 + 1 * 4]; - blkCr[2 + 1 * 4] = blkCr[0 + 1 * 4]; - blkCr[3 + 1 * 4] = blkCr[0 + 1 * 4]; - - /*Store data back to DDR*/ - convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 1); - } - - blkBufCnt = (blkBufCnt==1) ? 0 : blkBufCnt + 1; - } - - hevc_print(hevc, H265_DEBUG_DETAIL, - "cmBodyBuf to detbuf:\n"); - for (i = 0; i < 32 * 18; i++) { - hevc->detbuf_adr_virt[i] = cmBodyBuf[i]; - if (get_dbg_flag(hevc) & - H265_DEBUG_DETAIL) { - if ((i & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]); - } - } - hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n"); - - WRITE_VREG(HEVC_SAO_DBG_MODE1, 3); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s, %d\n", __func__, __LINE__); - do { - tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1); - } while (tmpData32); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s, %d\n", __func__, __LINE__); -} - -static void delrefill(struct hevc_state_s *hevc) -{ - /* - * corrRefill - */ - /*HEVC_SAO_DBG_MODE0: picGlobalVariable - [31:30]error number - [29:20]error2([9:7]tilex[6:0]ctuy) - [19:10]error1 [9:0]error0*/ - uint32_t detResult = READ_VREG(HEVC_ASSIST_SCRATCH_3); - uint32_t errorIdx; - uint32_t errorNum = (detResult>>30); - - if (detResult) { - hevc_print(hevc, H265_DEBUG_BUFMGR, - "[corrRefillWithAmrisc] detResult=%08x\n", detResult); - for (errorIdx = 0; errorIdx < errorNum; errorIdx++) { - uint32_t errorPos = errorIdx * 10; - uint32_t errorResult = (detResult >> errorPos) & 0x3ff; - uint32_t tilex = (errorResult >> 7) - 1; - uint16_t ctux = hevc->m_tile[0][tilex].start_cu_x - + hevc->m_tile[0][tilex].width - 1; - uint16_t ctuy = (uint16_t)(errorResult & 0x7f); - uint32_t ctuPosition = (ctux<< 16) + ctuy; - hevc_print(hevc, H265_DEBUG_BUFMGR, - "Idx:%d tilex:%d ctu(%d(0x%x), %d(0x%x))\n", - errorIdx,tilex,ctux,ctux, ctuy,ctuy); - corrRefillWithAmrisc( - hevc, - (uint32_t)hevc->cur_pic->header_adr, - hevc->pic_w, - ctuPosition); - } - - WRITE_VREG(HEVC_ASSIST_SCRATCH_3, 0); /*clear status*/ - WRITE_VREG(HEVC_SAO_DBG_MODE0, 0); - WRITE_VREG(HEVC_SAO_DBG_MODE1, 1); - } -} -#endif - -static void get_rpm_param(union param_u *params) -{ - int i; - unsigned int data32; - - for (i = 0; i < 128; i++) { - do { - data32 = READ_VREG(RPM_CMD_REG); - /* hevc_print(hevc, 0, "%x\n", data32); */ - } while ((data32 & 0x10000) == 0); - params->l.data[i] = data32 & 0xffff; - /* hevc_print(hevc, 0, "%x\n", data32); */ - WRITE_VREG(RPM_CMD_REG, 0); - } -} - -static struct PIC_s *get_pic_by_POC(struct hevc_state_s *hevc, int POC) -{ - int i; - struct PIC_s *pic; - struct PIC_s *ret_pic = NULL; - if (POC == INVALID_POC) - return NULL; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1 || - pic->BUF_index == -1) - continue; - if (pic->POC == POC) { - if (ret_pic == NULL) - ret_pic = pic; - else { - if (pic->decode_idx > ret_pic->decode_idx) - ret_pic = pic; - } - } - } - return ret_pic; -} - -static struct PIC_s *get_ref_pic_by_POC(struct hevc_state_s *hevc, int POC) -{ - int i; - struct PIC_s *pic; - struct PIC_s *ret_pic = NULL; - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1 || - pic->BUF_index == -1) - continue; - if ((pic->POC == POC) && (pic->referenced)) { - if (ret_pic == NULL) - ret_pic = pic; - else { - if (pic->decode_idx > ret_pic->decode_idx) - ret_pic = pic; - } - } - } - - if (ret_pic == NULL) { - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "Wrong, POC of %d is not in referenced list\n", - POC); - } - ret_pic = get_pic_by_POC(hevc, POC); - } - return ret_pic; -} - -static unsigned int log2i(unsigned int val) -{ - unsigned int ret = -1; - - while (val != 0) { - val >>= 1; - ret++; - } - return ret; -} - -static int init_buf_spec(struct hevc_state_s *hevc); -static void uninit_mmu_buffers(struct hevc_state_s *hevc) -{ - if (hevc->mmu_box) - decoder_mmu_box_free(hevc->mmu_box); - hevc->mmu_box = NULL; - - if (hevc->bmmu_box) - decoder_bmmu_box_free(hevc->bmmu_box); - hevc->bmmu_box = NULL; -} -static int init_mmu_buffers(struct hevc_state_s *hevc) -{ - int tvp_flag = vdec_secure(hw_to_vdec(hevc)) ? - CODEC_MM_FLAGS_TVP : 0; - int buf_size = 64; - if ((hevc->max_pic_w * hevc->max_pic_h) > 0 && - (hevc->max_pic_w * hevc->max_pic_h) <= 1920*1088) { - buf_size = 24; - } - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, "%s max_w %d max_h %d\n", - __func__, hevc->max_pic_w, hevc->max_pic_h); - } - hevc->need_cache_size = buf_size * SZ_1M; - hevc->sc_start_time = get_jiffies_64(); - if (hevc->mmu_enable - && ((get_double_write_mode(hevc) & 0x10) == 0)) { - hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, - hevc->index, - MAX_REF_PIC_NUM, - buf_size * SZ_1M, - tvp_flag - ); - if (!hevc->mmu_box) { - pr_err("h265 alloc mmu box failed!!\n"); - return -1; - } - } - - hevc->bmmu_box = decoder_bmmu_box_alloc_box(DRIVER_NAME, - hevc->index, - BMMU_MAX_BUFFERS, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER | - tvp_flag); - if (!hevc->bmmu_box) { - if (hevc->mmu_box) - decoder_mmu_box_free(hevc->mmu_box); - hevc->mmu_box = NULL; - pr_err("h265 alloc mmu box failed!!\n"); - return -1; - } - return 0; -} - -struct buf_stru_s -{ - int lcu_total; - int mc_buffer_size_h; - int mc_buffer_size_u_v_h; -}; - -#ifndef MV_USE_FIXED_BUF -static void dealloc_mv_bufs(struct hevc_state_s *hevc) -{ - int i; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - if (hevc->m_mv_BUF[i].start_adr) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "dealloc mv buf(%d) adr 0x%p size 0x%x used_flag %d\n", - i, hevc->m_mv_BUF[i].start_adr, - hevc->m_mv_BUF[i].size, - hevc->m_mv_BUF[i].used_flag); - decoder_bmmu_box_free_idx( - hevc->bmmu_box, - MV_BUFFER_IDX(i)); - hevc->m_mv_BUF[i].start_adr = 0; - hevc->m_mv_BUF[i].size = 0; - hevc->m_mv_BUF[i].used_flag = 0; - } - } - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - if (hevc->m_PIC[i] != NULL) - hevc->m_PIC[i]->mv_buf_index = -1; - } - -} - -static int alloc_mv_buf(struct hevc_state_s *hevc, int i) -{ - int ret = 0; - /*get_cma_alloc_ref();*/ /*DEBUG_TMP*/ - if (decoder_bmmu_box_alloc_buf_phy - (hevc->bmmu_box, - MV_BUFFER_IDX(i), hevc->mv_buf_size, - DRIVER_NAME, - &hevc->m_mv_BUF[i].start_adr) < 0) { - hevc->m_mv_BUF[i].start_adr = 0; - ret = -1; - } else { - hevc->m_mv_BUF[i].size = hevc->mv_buf_size; - hevc->m_mv_BUF[i].used_flag = 0; - ret = 0; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "MV Buffer %d: start_adr %p size %x\n", - i, - (void *)hevc->m_mv_BUF[i].start_adr, - hevc->m_mv_BUF[i].size); - } - } - /*put_cma_alloc_ref();*/ /*DEBUG_TMP*/ - return ret; -} -#endif - -static int get_mv_buf(struct hevc_state_s *hevc, struct PIC_s *pic) -{ -#ifdef MV_USE_FIXED_BUF - if (pic && pic->index >= 0) { - if (IS_8K_SIZE(pic->width, pic->height)) { - pic->mpred_mv_wr_start_addr = - hevc->work_space_buf->mpred_mv.buf_start - + (pic->index * MPRED_8K_MV_BUF_SIZE); - } else { - pic->mpred_mv_wr_start_addr = - hevc->work_space_buf->mpred_mv.buf_start - + (pic->index * MPRED_4K_MV_BUF_SIZE); - } - } - return 0; -#else - int i; - int ret = -1; - int new_size; - if (IS_8K_SIZE(pic->width, pic->height)) - new_size = MPRED_8K_MV_BUF_SIZE + 0x10000; - else if (IS_4K_SIZE(pic->width, pic->height)) - new_size = MPRED_4K_MV_BUF_SIZE + 0x10000; /*0x120000*/ - else - new_size = MPRED_MV_BUF_SIZE + 0x10000; - if (new_size != hevc->mv_buf_size) { - dealloc_mv_bufs(hevc); - hevc->mv_buf_size = new_size; - } - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - if (hevc->m_mv_BUF[i].start_adr && - hevc->m_mv_BUF[i].used_flag == 0) { - hevc->m_mv_BUF[i].used_flag = 1; - ret = i; - break; - } - } - if (ret < 0) { - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - if (hevc->m_mv_BUF[i].start_adr == 0) { - if (alloc_mv_buf(hevc, i) >= 0) { - hevc->m_mv_BUF[i].used_flag = 1; - ret = i; - } - break; - } - } - } - - if (ret >= 0) { - pic->mv_buf_index = ret; - pic->mpred_mv_wr_start_addr = - (hevc->m_mv_BUF[ret].start_adr + 0xffff) & - (~0xffff); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s => %d (0x%x) size 0x%x\n", - __func__, ret, - pic->mpred_mv_wr_start_addr, - hevc->m_mv_BUF[ret].size); - - } else { - hevc_print(hevc, 0, - "%s: Error, mv buf is not enough\n", - __func__); - } - return ret; - -#endif -} - -static void put_mv_buf(struct hevc_state_s *hevc, - struct PIC_s *pic) -{ -#ifndef MV_USE_FIXED_BUF - int i = pic->mv_buf_index; - if (i < 0 || i >= MAX_REF_PIC_NUM) { - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s: index %d beyond range\n", - __func__, i); - return; - } - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s(%d): used_flag(%d)\n", - __func__, i, - hevc->m_mv_BUF[i].used_flag); - - if (hevc->m_mv_BUF[i].start_adr && - hevc->m_mv_BUF[i].used_flag) - hevc->m_mv_BUF[i].used_flag = 0; - pic->mv_buf_index = -1; -#endif -} - -static int cal_current_buf_size(struct hevc_state_s *hevc, - struct buf_stru_s *buf_stru) -{ - - int buf_size; - int pic_width = hevc->pic_w; - int pic_height = hevc->pic_h; - int lcu_size = hevc->lcu_size; - int pic_width_lcu = (pic_width % lcu_size) ? pic_width / lcu_size + - 1 : pic_width / lcu_size; - int pic_height_lcu = (pic_height % lcu_size) ? pic_height / lcu_size + - 1 : pic_height / lcu_size; - /*SUPPORT_10BIT*/ - int losless_comp_header_size = compute_losless_comp_header_size - (pic_width, pic_height); - /*always alloc buf for 10bit*/ - int losless_comp_body_size = compute_losless_comp_body_size - (hevc, pic_width, pic_height, 0); - int mc_buffer_size = losless_comp_header_size - + losless_comp_body_size; - int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16; - int mc_buffer_size_u_v_h = 0; - - int dw_mode = get_double_write_mode(hevc); - - if (hevc->mmu_enable) { - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) - buf_size = ((MMU_COMPRESS_8K_HEADER_SIZE + 0xffff) >> 16) - << 16; - else - buf_size = ((MMU_COMPRESS_HEADER_SIZE + 0xffff) >> 16) - << 16; - } else - buf_size = 0; - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(hevc, dw_mode); - int pic_height_dw = pic_height / - get_double_write_ratio(hevc, dw_mode); - - int pic_width_lcu_dw = (pic_width_dw % lcu_size) ? - pic_width_dw / lcu_size + 1 : - pic_width_dw / lcu_size; - int pic_height_lcu_dw = (pic_height_dw % lcu_size) ? - pic_height_dw / lcu_size + 1 : - pic_height_dw / lcu_size; - int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; - - int mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; - mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - buf_size += ((mc_buffer_size_u_v_h << 16) * 3); - } - - if ((!hevc->mmu_enable) && - ((dw_mode & 0x10) == 0)) { - /* use compress mode without mmu, - need buf for compress decoding*/ - buf_size += (mc_buffer_size_h << 16); - } - - /*in case start adr is not 64k alignment*/ - if (buf_size > 0) - buf_size += 0x10000; - - if (buf_stru) { - buf_stru->lcu_total = pic_width_lcu * pic_height_lcu; - buf_stru->mc_buffer_size_h = mc_buffer_size_h; - buf_stru->mc_buffer_size_u_v_h = mc_buffer_size_u_v_h; - } - return buf_size; -} - -static int alloc_buf(struct hevc_state_s *hevc) -{ - int i; - int ret = -1; - int buf_size = cal_current_buf_size(hevc, NULL); - - for (i = 0; i < BUF_POOL_SIZE; i++) { - if (hevc->m_BUF[i].start_adr == 0) - break; - } - if (i < BUF_POOL_SIZE) { - if (buf_size > 0) { - /*get_cma_alloc_ref();*/ /*DEBUG_TMP*/ - /*alloc compress header first*/ - - if (decoder_bmmu_box_alloc_buf_phy - (hevc->bmmu_box, - VF_BUFFER_IDX(i), buf_size, - DRIVER_NAME, - &hevc->m_BUF[i].start_adr) < 0) - hevc->m_BUF[i].start_adr = 0; - else { - hevc->m_BUF[i].size = buf_size; - hevc->m_BUF[i].used_flag = 0; - ret = 0; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "Buffer %d: start_adr %p size %x\n", - i, - (void *)hevc->m_BUF[i].start_adr, - hevc->m_BUF[i].size); - } - } - /*put_cma_alloc_ref();*/ /*DEBUG_TMP*/ - } else - ret = 0; - } - if (ret >= 0) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "alloc buf(%d) for %d/%d size 0x%x) => %p\n", - i, hevc->pic_w, hevc->pic_h, - buf_size, - hevc->m_BUF[i].start_adr); - } - } else { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "alloc buf(%d) for %d/%d size 0x%x) => Fail!!!\n", - i, hevc->pic_w, hevc->pic_h, - buf_size); - } - } - return ret; -} - -static void set_buf_unused(struct hevc_state_s *hevc, int i) -{ - if (i >= 0 && i < BUF_POOL_SIZE) - hevc->m_BUF[i].used_flag = 0; -} - -static void dealloc_unused_buf(struct hevc_state_s *hevc) -{ - int i; - for (i = 0; i < BUF_POOL_SIZE; i++) { - if (hevc->m_BUF[i].start_adr && - hevc->m_BUF[i].used_flag == 0) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "dealloc buf(%d) adr 0x%p size 0x%x\n", - i, hevc->m_BUF[i].start_adr, - hevc->m_BUF[i].size); - } - decoder_bmmu_box_free_idx( - hevc->bmmu_box, - VF_BUFFER_IDX(i)); - hevc->m_BUF[i].start_adr = 0; - hevc->m_BUF[i].size = 0; - } - } - -} - -static void dealloc_pic_buf(struct hevc_state_s *hevc, - struct PIC_s *pic) -{ - int i = pic->BUF_index; - pic->BUF_index = -1; - if (i >= 0 && - i < BUF_POOL_SIZE && - hevc->m_BUF[i].start_adr) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "dealloc buf(%d) adr 0x%p size 0x%x\n", - i, hevc->m_BUF[i].start_adr, - hevc->m_BUF[i].size); - } - decoder_bmmu_box_free_idx( - hevc->bmmu_box, - VF_BUFFER_IDX(i)); - hevc->m_BUF[i].used_flag = 0; - hevc->m_BUF[i].start_adr = 0; - hevc->m_BUF[i].size = 0; - } -} - -static int get_work_pic_num(struct hevc_state_s *hevc) -{ - int used_buf_num = 0; - int sps_pic_buf_diff = 0; - - if (get_dynamic_buf_num_margin(hevc) > 0) { - if ((!hevc->sps_num_reorder_pics_0) && - (hevc->param.p.sps_max_dec_pic_buffering_minus1_0)) { - /* the range of sps_num_reorder_pics_0 is in - [0, sps_max_dec_pic_buffering_minus1_0] */ - used_buf_num = get_dynamic_buf_num_margin(hevc) + - hevc->param.p.sps_max_dec_pic_buffering_minus1_0; - } else - used_buf_num = hevc->sps_num_reorder_pics_0 - + get_dynamic_buf_num_margin(hevc); - - sps_pic_buf_diff = hevc->param.p.sps_max_dec_pic_buffering_minus1_0 - - hevc->sps_num_reorder_pics_0; - -#ifdef MULTI_INSTANCE_SUPPORT - /* - need one more for multi instance, as - apply_ref_pic_set() has no chanch to run to - to clear referenced flag in some case - */ - if (hevc->m_ins_flag) - used_buf_num++; -#endif - } else - used_buf_num = max_buf_num; - - if (hevc->save_buffer_mode) - hevc_print(hevc, 0, - "save buf _mode : dynamic_buf_num_margin %d ----> %d \n", - dynamic_buf_num_margin, hevc->dynamic_buf_num_margin); - - if (sps_pic_buf_diff >= 4) - { - used_buf_num += 1; - } - - if (used_buf_num > MAX_BUF_NUM) - used_buf_num = MAX_BUF_NUM; - return used_buf_num; -} - -static int get_alloc_pic_count(struct hevc_state_s *hevc) -{ - int alloc_pic_count = 0; - int i; - struct PIC_s *pic; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic && pic->index >= 0) - alloc_pic_count++; - } - return alloc_pic_count; -} - -static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) -{ - int ret = -1; - int i; - /*int lcu_size_log2 = hevc->lcu_size_log2; - int MV_MEM_UNIT=lcu_size_log2== - 6 ? 0x100 : lcu_size_log2==5 ? 0x40 : 0x10;*/ - /*int MV_MEM_UNIT = lcu_size_log2 == 6 ? 0x200 : lcu_size_log2 == - 5 ? 0x80 : 0x20; - int mpred_mv_end = hevc->work_space_buf->mpred_mv.buf_start + - hevc->work_space_buf->mpred_mv.buf_size;*/ - unsigned int y_adr = 0; - struct buf_stru_s buf_stru; - int buf_size = cal_current_buf_size(hevc, &buf_stru); - int dw_mode = get_double_write_mode(hevc); - - for (i = 0; i < BUF_POOL_SIZE; i++) { - if (hevc->m_BUF[i].start_adr != 0 && - hevc->m_BUF[i].used_flag == 0 && - buf_size <= hevc->m_BUF[i].size) { - hevc->m_BUF[i].used_flag = 1; - break; - } - } - if (i >= BUF_POOL_SIZE) - return -1; - - if (hevc->mmu_enable) { - pic->header_adr = hevc->m_BUF[i].start_adr; - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) - y_adr = hevc->m_BUF[i].start_adr + - MMU_COMPRESS_8K_HEADER_SIZE; - else - y_adr = hevc->m_BUF[i].start_adr + - MMU_COMPRESS_HEADER_SIZE; - } else - y_adr = hevc->m_BUF[i].start_adr; - - y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/ - pic->POC = INVALID_POC; - /*ensure get_pic_by_POC() - not get the buffer not decoded*/ - pic->BUF_index = i; - - if ((!hevc->mmu_enable) && - ((dw_mode & 0x10) == 0) - ) { - pic->mc_y_adr = y_adr; - y_adr += (buf_stru.mc_buffer_size_h << 16); - } - pic->mc_canvas_y = pic->index; - pic->mc_canvas_u_v = pic->index; - if (dw_mode & 0x10) { - pic->mc_y_adr = y_adr; - pic->mc_u_v_adr = y_adr + - ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); - - pic->mc_canvas_y = (pic->index << 1); - pic->mc_canvas_u_v = (pic->index << 1) + 1; - - pic->dw_y_adr = pic->mc_y_adr; - pic->dw_u_v_adr = pic->mc_u_v_adr; - } else if (dw_mode) { - pic->dw_y_adr = y_adr; - pic->dw_u_v_adr = pic->dw_y_adr + - ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); - } - - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "%s index %d BUF_index %d mc_y_adr %x\n", - __func__, pic->index, - pic->BUF_index, pic->mc_y_adr); - if (hevc->mmu_enable && - dw_mode) - hevc_print(hevc, 0, - "mmu double write adr %ld\n", - pic->cma_alloc_addr); - - - } - ret = 0; - - return ret; -} - -static void init_pic_list(struct hevc_state_s *hevc) -{ - int i; - int init_buf_num = get_work_pic_num(hevc); - int dw_mode = get_double_write_mode(hevc); - struct vdec_s *vdec = hw_to_vdec(hevc); - /*alloc decoder buf*/ - for (i = 0; i < init_buf_num; i++) { - if (alloc_buf(hevc) < 0) { - if (i <= 8) { - /*if alloced (i+1)>=9 - don't send errors.*/ - hevc->fatal_error |= - DECODER_FATAL_ERROR_NO_MEM; - } - break; - } - } - - for (i = 0; i < init_buf_num; i++) { - struct PIC_s *pic = - vmalloc(sizeof(struct PIC_s)); - if (pic == NULL) { - hevc_print(hevc, 0, - "%s: alloc pic %d fail!!!\n", - __func__, i); - break; - } - memset(pic, 0, sizeof(struct PIC_s)); - hevc->m_PIC[i] = pic; - pic->index = i; - pic->BUF_index = -1; - pic->mv_buf_index = -1; - if (vdec->parallel_dec == 1) { - pic->y_canvas_index = -1; - pic->uv_canvas_index = -1; - } - if (config_pic(hevc, pic) < 0) { - if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, - "Config_pic %d fail\n", pic->index); - pic->index = -1; - i++; - break; - } - pic->width = hevc->pic_w; - pic->height = hevc->pic_h; - pic->double_write_mode = dw_mode; - if (pic->double_write_mode) - set_canvas(hevc, pic); - } - - for (; i < MAX_REF_PIC_NUM; i++) { - struct PIC_s *pic = - vmalloc(sizeof(struct PIC_s)); - if (pic == NULL) { - hevc_print(hevc, 0, - "%s: alloc pic %d fail!!!\n", - __func__, i); - break; - } - memset(pic, 0, sizeof(struct PIC_s)); - hevc->m_PIC[i] = pic; - pic->index = -1; - pic->BUF_index = -1; - if (vdec->parallel_dec == 1) { - pic->y_canvas_index = -1; - pic->uv_canvas_index = -1; - } - } - -} - -static void uninit_pic_list(struct hevc_state_s *hevc) -{ - struct vdec_s *vdec = hw_to_vdec(hevc); - int i; -#ifndef MV_USE_FIXED_BUF - dealloc_mv_bufs(hevc); -#endif - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - struct PIC_s *pic = hevc->m_PIC[i]; - - if (pic) { - if (vdec->parallel_dec == 1) { - vdec->free_canvas_ex(pic->y_canvas_index, vdec->id); - vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id); - } - release_aux_data(hevc, pic); - vfree(pic); - hevc->m_PIC[i] = NULL; - } - } -} - -#ifdef LOSLESS_COMPRESS_MODE -static void init_decode_head_hw(struct hevc_state_s *hevc) -{ - - struct BuffInfo_s *buf_spec = hevc->work_space_buf; - unsigned int data32; - - int losless_comp_header_size = - compute_losless_comp_header_size(hevc->pic_w, - hevc->pic_h); - int losless_comp_body_size = compute_losless_comp_body_size(hevc, - hevc->pic_w, hevc->pic_h, hevc->mem_saving_mode); - - hevc->losless_comp_body_size = losless_comp_body_size; - - - if (hevc->mmu_enable) { - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0); - } else { - if (hevc->mem_saving_mode == 1) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, - (1 << 3) | ((workaround_enable & 2) ? 1 : 0)); - else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, - ((workaround_enable & 2) ? 1 : 0)); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); - /* - *WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff); - * //8-bit mode - */ - } - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); - - if (hevc->mmu_enable) { - WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); - WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, - buf_spec->mmu_vbh.buf_start + - buf_spec->mmu_vbh.buf_size/2); - data32 = READ_VREG(HEVC_SAO_CTRL9); - data32 |= 0x1; - WRITE_VREG(HEVC_SAO_CTRL9, data32); - - /* use HEVC_CM_HEADER_START_ADDR */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 |= (1<<10); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - - if (!hevc->m_ins_flag) - hevc_print(hevc, 0, - "%s: (%d, %d) body_size 0x%x header_size 0x%x\n", - __func__, hevc->pic_w, hevc->pic_h, - losless_comp_body_size, losless_comp_header_size); - -} -#endif -#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 - -static void init_pic_list_hw(struct hevc_state_s *hevc) -{ - int i; - int cur_pic_num = MAX_REF_PIC_NUM; - int dw_mode = get_double_write_mode(hevc); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (0x1 << 2)); - else - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0); - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - if (hevc->m_PIC[i] == NULL || - hevc->m_PIC[i]->index == -1) { - cur_pic_num = i; - break; - } - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable && ((dw_mode & 0x10) == 0)) - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[i]->header_adr>>5); - else - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[i]->mc_y_adr >> 5); - } else - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - hevc->m_PIC[i]->mc_y_adr | - (hevc->m_PIC[i]->mc_canvas_y << 8) | 0x1); - if (dw_mode & 0x10) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[i]->mc_u_v_adr >> 5); - } - else - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - hevc->m_PIC[i]->mc_u_v_adr | - (hevc->m_PIC[i]->mc_canvas_u_v << 8) - | 0x1); - } - } - if (cur_pic_num == 0) - return; - for (; i < MAX_REF_PIC_NUM; i++) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable && ((dw_mode & 0x10) == 0)) - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[cur_pic_num-1]->header_adr>>5); - else - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[cur_pic_num-1]->mc_y_adr >> 5); -#ifndef LOSLESS_COMPRESS_MODE - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[cur_pic_num-1]->mc_u_v_adr >> 5); -#endif - } else { - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - hevc->m_PIC[cur_pic_num-1]->mc_y_adr| - (hevc->m_PIC[cur_pic_num-1]->mc_canvas_y<<8) - | 0x1); -#ifndef LOSLESS_COMPRESS_MODE - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - hevc->m_PIC[cur_pic_num-1]->mc_u_v_adr| - (hevc->m_PIC[cur_pic_num-1]->mc_canvas_u_v<<8) - | 0x1); -#endif - } - } - - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); - - /* Zero out canvas registers in IPP -- avoid simulation X */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 1); - for (i = 0; i < 32; i++) - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); - -#ifdef LOSLESS_COMPRESS_MODE - if ((dw_mode & 0x10) == 0) - init_decode_head_hw(hevc); -#endif - -} - - -static void dump_pic_list(struct hevc_state_s *hevc) -{ - int i; - struct PIC_s *pic; - - hevc_print(hevc, 0, - "pic_list_init_flag is %d\r\n", hevc->pic_list_init_flag); - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - hevc_print_cont(hevc, 0, - "index %d buf_idx %d mv_idx %d decode_idx:%d, POC:%d, referenced:%d, ", - pic->index, pic->BUF_index, -#ifndef MV_USE_FIXED_BUF - pic->mv_buf_index, -#else - -1, -#endif - pic->decode_idx, pic->POC, pic->referenced); - hevc_print_cont(hevc, 0, - "num_reorder_pic:%d, output_mark:%d, w/h %d,%d", - pic->num_reorder_pic, pic->output_mark, - pic->width, pic->height); - hevc_print_cont(hevc, 0, - "output_ready:%d, mv_wr_start %x vf_ref %d\n", - pic->output_ready, pic->mpred_mv_wr_start_addr, - pic->vf_ref); - } -} - -static void clear_referenced_flag(struct hevc_state_s *hevc) -{ - int i; - struct PIC_s *pic; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - if (pic->referenced) { - pic->referenced = 0; - put_mv_buf(hevc, pic); - } - } -} - -static void clear_poc_flag(struct hevc_state_s *hevc) -{ - int i; - struct PIC_s *pic; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - pic->POC = INVALID_POC; - } -} - -static struct PIC_s *output_pic(struct hevc_state_s *hevc, - unsigned char flush_flag) -{ - int num_pic_not_yet_display = 0; - int i; - struct PIC_s *pic; - struct PIC_s *pic_display = NULL; - - if (hevc->i_only & 0x4) { - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || - (pic->index == -1) || - (pic->BUF_index == -1) || - (pic->POC == INVALID_POC)) - continue; - if (pic->output_mark) { - if (pic_display) { - if (pic->decode_idx < - pic_display->decode_idx) - pic_display = pic; - - } else - pic_display = pic; - - } - } - if (pic_display) { - pic_display->output_mark = 0; - pic_display->recon_mark = 0; - pic_display->output_ready = 1; - pic_display->referenced = 0; - put_mv_buf(hevc, pic_display); - } - } else { - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || - (pic->index == -1) || - (pic->BUF_index == -1) || - (pic->POC == INVALID_POC)) - continue; - if (pic->output_mark) - num_pic_not_yet_display++; - if (pic->slice_type == 2 && - hevc->vf_pre_count == 0 && - fast_output_enable & 0x1) { - /*fast output for first I picture*/ - pic->num_reorder_pic = 0; - hevc_print(hevc, 0, "VH265: output first frame\n"); - } - } - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || - (pic->index == -1) || - (pic->BUF_index == -1) || - (pic->POC == INVALID_POC)) - continue; - if (pic->output_mark) { - if (pic_display) { - if (pic->POC < pic_display->POC) - pic_display = pic; - else if ((pic->POC == pic_display->POC) - && (pic->decode_idx < - pic_display-> - decode_idx)) - pic_display - = pic; - } else - pic_display = pic; - } - } - if (pic_display) { - if ((num_pic_not_yet_display > - pic_display->num_reorder_pic) - || flush_flag) { - pic_display->output_mark = 0; - pic_display->recon_mark = 0; - pic_display->output_ready = 1; - } else if (num_pic_not_yet_display >= - (MAX_REF_PIC_NUM - 1)) { - pic_display->output_mark = 0; - pic_display->recon_mark = 0; - pic_display->output_ready = 1; - hevc_print(hevc, 0, - "Warning, num_reorder_pic %d is byeond buf num\n", - pic_display->num_reorder_pic); - } else - pic_display = NULL; - } - } - if (pic_display && (hevc->vf_pre_count == 1) && (hevc->first_pic_flag == 1)) { - pic_display = NULL; - hevc->first_pic_flag = 0; - } - return pic_display; -} - -static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) -{ - int i; - struct PIC_s *pic; - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "config_mc_buffer entered .....\n"); - if (cur_pic->slice_type != 2) { /* P and B pic */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 1); - for (i = 0; i < cur_pic->RefNum_L0; i++) { - pic = - get_ref_pic_by_POC(hevc, - cur_pic-> - m_aiRefPOCList0[cur_pic-> - slice_idx][i]); - if (pic) { - if ((pic->width != hevc->pic_w) || - (pic->height != hevc->pic_h)) { - hevc_print(hevc, 0, - "%s: Wrong reference pic (poc %d) width/height %d/%d\n", - __func__, pic->POC, - pic->width, pic->height); - cur_pic->error_mark = 1; - } - if (pic->error_mark && (ref_frame_mark_flag[hevc->index])) - cur_pic->error_mark = 1; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v << 16) - | (pic->mc_canvas_u_v - << 8) | - pic->mc_canvas_y); - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, - "refid %x mc_canvas_u_v %x", - i, pic->mc_canvas_u_v); - hevc_print_cont(hevc, 0, - " mc_canvas_y %x\n", - pic->mc_canvas_y); - } - } else - cur_pic->error_mark = 1; - - if (pic == NULL || pic->error_mark) { - hevc_print(hevc, 0, - "Error %s, %dth poc (%d) %s", - __func__, i, - cur_pic->m_aiRefPOCList0[cur_pic-> - slice_idx][i], - pic ? "has error" : - "not in list0"); - } - } - } - if (cur_pic->slice_type == 0) { /* B pic */ - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "config_mc_buffer RefNum_L1\n"); - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (16 << 8) | (0 << 1) | 1); - - for (i = 0; i < cur_pic->RefNum_L1; i++) { - pic = - get_ref_pic_by_POC(hevc, - cur_pic-> - m_aiRefPOCList1[cur_pic-> - slice_idx][i]); - if (pic) { - if ((pic->width != hevc->pic_w) || - (pic->height != hevc->pic_h)) { - hevc_print(hevc, 0, - "%s: Wrong reference pic (poc %d) width/height %d/%d\n", - __func__, pic->POC, - pic->width, pic->height); - cur_pic->error_mark = 1; - } - - if (pic->error_mark && (ref_frame_mark_flag[hevc->index])) - cur_pic->error_mark = 1; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic->mc_canvas_u_v << 16) - | (pic->mc_canvas_u_v - << 8) | - pic->mc_canvas_y); - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, - "refid %x mc_canvas_u_v %x", - i, pic->mc_canvas_u_v); - hevc_print_cont(hevc, 0, - " mc_canvas_y %x\n", - pic->mc_canvas_y); - } - } else - cur_pic->error_mark = 1; - - if (pic == NULL || pic->error_mark) { - hevc_print(hevc, 0, - "Error %s, %dth poc (%d) %s", - __func__, i, - cur_pic->m_aiRefPOCList1[cur_pic-> - slice_idx][i], - pic ? "has error" : - "not in list1"); - } - } - } - return 0; -} - -static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, - union param_u *params) -{ - int ii, i; - int poc_tmp; - struct PIC_s *pic; - unsigned char is_referenced; - /* hevc_print(hevc, 0, - "%s cur_poc %d\n", __func__, cur_poc); */ - - for (ii = 0; ii < MAX_REF_PIC_NUM; ii++) { - pic = hevc->m_PIC[ii]; - if (pic == NULL || - pic->index == -1 || - pic->BUF_index == -1 - ) - continue; - - if ((pic->referenced == 0 || pic->POC == cur_poc)) - continue; - is_referenced = 0; - for (i = 0; i < 16; i++) { - int delt; - - if (params->p.CUR_RPS[i] & 0x8000) - break; - delt = - params->p.CUR_RPS[i] & - ((1 << (RPS_USED_BIT - 1)) - 1); - if (params->p.CUR_RPS[i] & (1 << (RPS_USED_BIT - 1))) { - poc_tmp = - cur_poc - ((1 << (RPS_USED_BIT - 1)) - - delt); - } else - poc_tmp = cur_poc + delt; - if (poc_tmp == pic->POC) { - is_referenced = 1; - /* hevc_print(hevc, 0, "i is %d\n", i); */ - break; - } - } - if (is_referenced == 0) { - pic->referenced = 0; - put_mv_buf(hevc, pic); - /* hevc_print(hevc, 0, - "set poc %d reference to 0\n", pic->POC); */ - } - } - -} - -static void set_ref_pic_list(struct hevc_state_s *hevc, union param_u *params) -{ - struct PIC_s *pic = hevc->cur_pic; - int i, rIdx; - int num_neg = 0; - int num_pos = 0; - int total_num; - int num_ref_idx_l0_active = - (params->p.num_ref_idx_l0_active > - MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : - params->p.num_ref_idx_l0_active; - int num_ref_idx_l1_active = - (params->p.num_ref_idx_l1_active > - MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : - params->p.num_ref_idx_l1_active; - - int RefPicSetStCurr0[16]; - int RefPicSetStCurr1[16]; - - for (i = 0; i < 16; i++) { - RefPicSetStCurr0[i] = 0; - RefPicSetStCurr1[i] = 0; - pic->m_aiRefPOCList0[pic->slice_idx][i] = 0; - pic->m_aiRefPOCList1[pic->slice_idx][i] = 0; - } - for (i = 0; i < 16; i++) { - if (params->p.CUR_RPS[i] & 0x8000) - break; - if ((params->p.CUR_RPS[i] >> RPS_USED_BIT) & 1) { - int delt = - params->p.CUR_RPS[i] & - ((1 << (RPS_USED_BIT - 1)) - 1); - - if ((params->p.CUR_RPS[i] >> (RPS_USED_BIT - 1)) & 1) { - RefPicSetStCurr0[num_neg] = - pic->POC - ((1 << (RPS_USED_BIT - 1)) - - delt); - /* hevc_print(hevc, 0, - * "RefPicSetStCurr0 %x %x %x\n", - * RefPicSetStCurr0[num_neg], pic->POC, - * (0x800-(params[i]&0x7ff))); - */ - num_neg++; - } else { - RefPicSetStCurr1[num_pos] = pic->POC + delt; - /* hevc_print(hevc, 0, - * "RefPicSetStCurr1 %d\n", - * RefPicSetStCurr1[num_pos]); - */ - num_pos++; - } - } - } - total_num = num_neg + num_pos; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "%s: curpoc %d slice_type %d, total %d ", - __func__, pic->POC, params->p.slice_type, total_num); - hevc_print_cont(hevc, 0, - "num_neg %d num_list0 %d num_list1 %d\n", - num_neg, num_ref_idx_l0_active, num_ref_idx_l1_active); - } - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "HEVC Stream buf start "); - hevc_print_cont(hevc, 0, - "%x end %x wr %x rd %x lev %x ctl %x intctl %x\n", - READ_VREG(HEVC_STREAM_START_ADDR), - READ_VREG(HEVC_STREAM_END_ADDR), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_FIFO_CTL), - READ_VREG(HEVC_PARSER_INT_CONTROL)); - } - - if (total_num > 0) { - if (params->p.modification_flag & 0x1) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, "ref0 POC (modification):"); - for (rIdx = 0; rIdx < num_ref_idx_l0_active; rIdx++) { - int cIdx = params->p.modification_list[rIdx]; - - pic->m_aiRefPOCList0[pic->slice_idx][rIdx] = - cIdx >= - num_neg ? RefPicSetStCurr1[cIdx - - num_neg] : - RefPicSetStCurr0[cIdx]; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, "%d ", - pic->m_aiRefPOCList0[pic-> - slice_idx] - [rIdx]); - } - } - } else { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, "ref0 POC:"); - for (rIdx = 0; rIdx < num_ref_idx_l0_active; rIdx++) { - int cIdx = rIdx % total_num; - - pic->m_aiRefPOCList0[pic->slice_idx][rIdx] = - cIdx >= - num_neg ? RefPicSetStCurr1[cIdx - - num_neg] : - RefPicSetStCurr0[cIdx]; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, "%d ", - pic->m_aiRefPOCList0[pic-> - slice_idx] - [rIdx]); - } - } - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, "\n"); - if (params->p.slice_type == B_SLICE) { - if (params->p.modification_flag & 0x2) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "ref1 POC (modification):"); - for (rIdx = 0; rIdx < num_ref_idx_l1_active; - rIdx++) { - int cIdx; - - if (params->p.modification_flag & 0x1) { - cIdx = - params->p. - modification_list - [num_ref_idx_l0_active + - rIdx]; - } else { - cIdx = - params->p. - modification_list[rIdx]; - } - pic->m_aiRefPOCList1[pic-> - slice_idx][rIdx] = - cIdx >= - num_pos ? - RefPicSetStCurr0[cIdx - num_pos] - : RefPicSetStCurr1[cIdx]; - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, "%d ", - pic-> - m_aiRefPOCList1[pic-> - slice_idx] - [rIdx]); - } - } - } else { - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, "ref1 POC:"); - for (rIdx = 0; rIdx < num_ref_idx_l1_active; - rIdx++) { - int cIdx = rIdx % total_num; - - pic->m_aiRefPOCList1[pic-> - slice_idx][rIdx] = - cIdx >= - num_pos ? - RefPicSetStCurr0[cIdx - - num_pos] - : RefPicSetStCurr1[cIdx]; - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, "%d ", - pic-> - m_aiRefPOCList1[pic-> - slice_idx] - [rIdx]); - } - } - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, "\n"); - } - } - /*set m_PIC */ - pic->slice_type = (params->p.slice_type == I_SLICE) ? 2 : - (params->p.slice_type == P_SLICE) ? 1 : - (params->p.slice_type == B_SLICE) ? 0 : 3; - pic->RefNum_L0 = num_ref_idx_l0_active; - pic->RefNum_L1 = num_ref_idx_l1_active; -} - -static void update_tile_info(struct hevc_state_s *hevc, int pic_width_cu, - int pic_height_cu, int sao_mem_unit, - union param_u *params) -{ - int i, j; - int start_cu_x, start_cu_y; - int sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu; - int sao_abv_size = sao_mem_unit * pic_width_cu; -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - int tmpRefillLcuSize = 1 << - (params->p.log2_min_coding_block_size_minus3 + - 3 + params->p.log2_diff_max_min_coding_block_size); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%x, %x, %x, %x\n", - params->p.slice_segment_address, - params->p.bit_depth, - params->p.tiles_enabled_flag, - tmpRefillLcuSize); - if (params->p.slice_segment_address == 0 && - params->p.bit_depth != 0 && - (params->p.tiles_enabled_flag & 1) && - tmpRefillLcuSize == 64) - hevc->delrefill_check = 1; - else - hevc->delrefill_check = 0; - } -#endif - - hevc->tile_enabled = params->p.tiles_enabled_flag & 1; - if (params->p.tiles_enabled_flag & 1) { - hevc->num_tile_col = params->p.num_tile_columns_minus1 + 1; - hevc->num_tile_row = params->p.num_tile_rows_minus1 + 1; - - if (hevc->num_tile_row > MAX_TILE_ROW_NUM - || hevc->num_tile_row <= 0) { - hevc->num_tile_row = 1; - hevc_print(hevc, 0, - "%s: num_tile_rows_minus1 (%d) error!!\n", - __func__, params->p.num_tile_rows_minus1); - } - if (hevc->num_tile_col > MAX_TILE_COL_NUM - || hevc->num_tile_col <= 0) { - hevc->num_tile_col = 1; - hevc_print(hevc, 0, - "%s: num_tile_columns_minus1 (%d) error!!\n", - __func__, params->p.num_tile_columns_minus1); - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "%s pic_w_cu %d pic_h_cu %d tile_enabled ", - __func__, pic_width_cu, pic_height_cu); - hevc_print_cont(hevc, 0, - "num_tile_col %d num_tile_row %d:\n", - hevc->num_tile_col, hevc->num_tile_row); - } - - if (params->p.tiles_enabled_flag & 2) { /* uniform flag */ - int w = pic_width_cu / hevc->num_tile_col; - int h = pic_height_cu / hevc->num_tile_row; - - start_cu_y = 0; - for (i = 0; i < hevc->num_tile_row; i++) { - start_cu_x = 0; - for (j = 0; j < hevc->num_tile_col; j++) { - if (j == (hevc->num_tile_col - 1)) { - hevc->m_tile[i][j].width = - pic_width_cu - - start_cu_x; - } else - hevc->m_tile[i][j].width = w; - if (i == (hevc->num_tile_row - 1)) { - hevc->m_tile[i][j].height = - pic_height_cu - - start_cu_y; - } else - hevc->m_tile[i][j].height = h; - hevc->m_tile[i][j].start_cu_x - = start_cu_x; - hevc->m_tile[i][j].start_cu_y - = start_cu_y; - hevc->m_tile[i][j].sao_vb_start_addr = - hevc->work_space_buf->sao_vb. - buf_start + j * sao_vb_size; - hevc->m_tile[i][j].sao_abv_start_addr = - hevc->work_space_buf->sao_abv. - buf_start + i * sao_abv_size; - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, - "{y=%d, x=%d w %d h %d ", - i, j, hevc->m_tile[i][j].width, - hevc->m_tile[i][j].height); - hevc_print_cont(hevc, 0, - "start_x %d start_y %d ", - hevc->m_tile[i][j].start_cu_x, - hevc->m_tile[i][j].start_cu_y); - hevc_print_cont(hevc, 0, - "sao_vb_start 0x%x ", - hevc->m_tile[i][j]. - sao_vb_start_addr); - hevc_print_cont(hevc, 0, - "sao_abv_start 0x%x}\n", - hevc->m_tile[i][j]. - sao_abv_start_addr); - } - start_cu_x += hevc->m_tile[i][j].width; - - } - start_cu_y += hevc->m_tile[i][0].height; - } - } else { - start_cu_y = 0; - for (i = 0; i < hevc->num_tile_row; i++) { - start_cu_x = 0; - for (j = 0; j < hevc->num_tile_col; j++) { - if (j == (hevc->num_tile_col - 1)) { - hevc->m_tile[i][j].width = - pic_width_cu - - start_cu_x; - } else { - hevc->m_tile[i][j].width = - params->p.tile_width[j]; - } - if (i == (hevc->num_tile_row - 1)) { - hevc->m_tile[i][j].height = - pic_height_cu - - start_cu_y; - } else { - hevc->m_tile[i][j].height = - params-> - p.tile_height[i]; - } - hevc->m_tile[i][j].start_cu_x - = start_cu_x; - hevc->m_tile[i][j].start_cu_y - = start_cu_y; - hevc->m_tile[i][j].sao_vb_start_addr = - hevc->work_space_buf->sao_vb. - buf_start + j * sao_vb_size; - hevc->m_tile[i][j].sao_abv_start_addr = - hevc->work_space_buf->sao_abv. - buf_start + i * sao_abv_size; - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print_cont(hevc, 0, - "{y=%d, x=%d w %d h %d ", - i, j, hevc->m_tile[i][j].width, - hevc->m_tile[i][j].height); - hevc_print_cont(hevc, 0, - "start_x %d start_y %d ", - hevc->m_tile[i][j].start_cu_x, - hevc->m_tile[i][j].start_cu_y); - hevc_print_cont(hevc, 0, - "sao_vb_start 0x%x ", - hevc->m_tile[i][j]. - sao_vb_start_addr); - hevc_print_cont(hevc, 0, - "sao_abv_start 0x%x}\n", - hevc->m_tile[i][j]. - sao_abv_start_addr); - - } - start_cu_x += hevc->m_tile[i][j].width; - } - start_cu_y += hevc->m_tile[i][0].height; - } - } - } else { - hevc->num_tile_col = 1; - hevc->num_tile_row = 1; - hevc->m_tile[0][0].width = pic_width_cu; - hevc->m_tile[0][0].height = pic_height_cu; - hevc->m_tile[0][0].start_cu_x = 0; - hevc->m_tile[0][0].start_cu_y = 0; - hevc->m_tile[0][0].sao_vb_start_addr = - hevc->work_space_buf->sao_vb.buf_start; - hevc->m_tile[0][0].sao_abv_start_addr = - hevc->work_space_buf->sao_abv.buf_start; - } -} - -static int get_tile_index(struct hevc_state_s *hevc, int cu_adr, - int pic_width_lcu) -{ - int cu_x; - int cu_y; - int tile_x = 0; - int tile_y = 0; - int i; - - if (pic_width_lcu == 0) { - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "%s Error, pic_width_lcu is 0, pic_w %d, pic_h %d\n", - __func__, hevc->pic_w, hevc->pic_h); - } - return -1; - } - cu_x = cu_adr % pic_width_lcu; - cu_y = cu_adr / pic_width_lcu; - if (hevc->tile_enabled) { - for (i = 0; i < hevc->num_tile_col; i++) { - if (cu_x >= hevc->m_tile[0][i].start_cu_x) - tile_x = i; - else - break; - } - for (i = 0; i < hevc->num_tile_row; i++) { - if (cu_y >= hevc->m_tile[i][0].start_cu_y) - tile_y = i; - else - break; - } - } - return (tile_x) | (tile_y << 8); -} - -static void print_scratch_error(int error_num) -{ -#if 0 - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - " ERROR : HEVC_ASSIST_SCRATCH_TEST Error : %d\n", - error_num); - } -#endif -} - -static void hevc_config_work_space_hw(struct hevc_state_s *hevc) -{ - struct BuffInfo_s *buf_spec = hevc->work_space_buf; - - if (get_dbg_flag(hevc)) - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n", - __func__, - buf_spec->ipp.buf_start, - buf_spec->start_adr, - buf_spec->short_term_rps.buf_start, - buf_spec->vps.buf_start, - buf_spec->sps.buf_start, - buf_spec->pps.buf_start, - buf_spec->sao_up.buf_start, - buf_spec->swap_buf.buf_start, - buf_spec->swap_buf2.buf_start, - buf_spec->scalelut.buf_start, - buf_spec->dblk_para.buf_start, - buf_spec->dblk_data.buf_start, - buf_spec->dblk_data2.buf_start); - WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); - if ((get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) == 0) - WRITE_VREG(HEVC_RPM_BUFFER, (u32)hevc->rpm_phy_addr); - WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start); - WRITE_VREG(HEVC_VPS_BUFFER, buf_spec->vps.buf_start); - WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start); - WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); - WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); - if (hevc->mmu_enable) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, hevc->frame_mmu_map_phy_addr); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "write HEVC_ASSIST_MMU_MAP_ADDR\n"); - } else - WRITE_VREG(H265_MMU_MAP_BUFFER, hevc->frame_mmu_map_phy_addr); - } /*else - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, - buf_spec->swap_buf.buf_start); - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start);*/ - WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); - /* cfg_p_addr */ - WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); - /* cfg_d_addr */ - WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); - - WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_data2.buf_start); - - WRITE_VREG(LMEM_DUMP_ADR, (u32)hevc->lmem_phy_addr); -} - -static void parser_cmd_write(void) -{ - u32 i; - const unsigned short parser_cmd[PARSER_CMD_NUMBER] = { - 0x0401, 0x8401, 0x0800, 0x0402, 0x9002, 0x1423, - 0x8CC3, 0x1423, 0x8804, 0x9825, 0x0800, 0x04FE, - 0x8406, 0x8411, 0x1800, 0x8408, 0x8409, 0x8C2A, - 0x9C2B, 0x1C00, 0x840F, 0x8407, 0x8000, 0x8408, - 0x2000, 0xA800, 0x8410, 0x04DE, 0x840C, 0x840D, - 0xAC00, 0xA000, 0x08C0, 0x08E0, 0xA40E, 0xFC00, - 0x7C00 - }; - for (i = 0; i < PARSER_CMD_NUMBER; i++) - WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); -} - -static void hevc_init_decoder_hw(struct hevc_state_s *hevc, - int decode_pic_begin, int decode_pic_num) -{ - unsigned int data32; - int i; -#if 0 - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { - /* Set MCR fetch priorities*/ - data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | - (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); - WRITE_VREG(HEVCD_MPP_DECOMP_AXIURG_CTL, data32); - } -#endif -#if 1 - /* m8baby test1902 */ - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "%s\n", __func__); - data32 = READ_VREG(HEVC_PARSER_VERSION); - if (data32 != 0x00010001) { - print_scratch_error(25); - return; - } - WRITE_VREG(HEVC_PARSER_VERSION, 0x5a5a55aa); - data32 = READ_VREG(HEVC_PARSER_VERSION); - if (data32 != 0x5a5a55aa) { - print_scratch_error(26); - return; - } -#if 0 - /* test Parser Reset */ - /* reset iqit to start mem init again */ - WRITE_VREG(DOS_SW_RESET3, (1 << 14) | - (1 << 3) /* reset_whole parser */ - ); - WRITE_VREG(DOS_SW_RESET3, 0); /* clear reset_whole parser */ - data32 = READ_VREG(HEVC_PARSER_VERSION); - if (data32 != 0x00010001) - hevc_print(hevc, 0, - "Test Parser Fatal Error\n"); -#endif - /* reset iqit to start mem init again */ - WRITE_VREG(DOS_SW_RESET3, (1 << 14) - ); - CLEAR_VREG_MASK(HEVC_CABAC_CONTROL, 1); - CLEAR_VREG_MASK(HEVC_PARSER_CORE_CONTROL, 1); - -#endif - if (!hevc->m_ins_flag) { - data32 = READ_VREG(HEVC_STREAM_CONTROL); - data32 = data32 | (1 << 0); /* stream_fetch_enable */ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - data32 |= (0xf << 25); /*arwlen_axi_max*/ - WRITE_VREG(HEVC_STREAM_CONTROL, data32); - } - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x00000100) { - print_scratch_error(29); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x00000300) { - print_scratch_error(30); - return; - } - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x12345678) { - print_scratch_error(31); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x9abcdef0) { - print_scratch_error(32); - return; - } - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000300); - - data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); - data32 &= 0x03ffffff; - data32 = data32 | (3 << 29) | (2 << 26) | (1 << 24) - | /* stream_buffer_empty_int_amrisc_enable */ - (1 << 22) | /* stream_fifo_empty_int_amrisc_enable*/ - (1 << 7) | /* dec_done_int_cpu_enable */ - (1 << 4) | /* startcode_found_int_cpu_enable */ - (0 << 3) | /* startcode_found_int_amrisc_enable */ - (1 << 0) /* parser_int_enable */ - ; - WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); - - data32 = READ_VREG(HEVC_SHIFT_STATUS); - data32 = data32 | (1 << 1) | /* emulation_check_on */ - (1 << 0) /* startcode_check_on */ - ; - WRITE_VREG(HEVC_SHIFT_STATUS, data32); - - WRITE_VREG(HEVC_SHIFT_CONTROL, (3 << 6) |/* sft_valid_wr_position */ - (2 << 4) | /* emulate_code_length_sub_1 */ - (2 << 1) | /* start_code_length_sub_1 */ - (1 << 0) /* stream_shift_enable */ - ); - - WRITE_VREG(HEVC_CABAC_CONTROL, (1 << 0) /* cabac_enable */ - ); - /* hevc_parser_core_clk_en */ - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, (1 << 0) - ); - - WRITE_VREG(HEVC_DEC_STATUS_REG, 0); - - /* Initial IQIT_SCALELUT memory -- just to avoid X in simulation */ - WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0); /* cfg_p_addr */ - for (i = 0; i < 1024; i++) - WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); - -#ifdef ENABLE_SWAP_TEST - WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); -#endif - - /*WRITE_VREG(HEVC_DECODE_PIC_BEGIN_REG, 0);*/ - /*WRITE_VREG(HEVC_DECODE_PIC_NUM_REG, 0xffffffff);*/ - WRITE_VREG(HEVC_DECODE_SIZE, 0); - /*WRITE_VREG(HEVC_DECODE_COUNT, 0);*/ - /* Send parser_cmd */ - WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); - - parser_cmd_write(); - - WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); - - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - /* (1 << 8) | // sao_sw_pred_enable */ - (1 << 5) | /* parser_sao_if_en */ - (1 << 2) | /* parser_mpred_if_en */ - (1 << 0) /* parser_scaler_if_en */ - ); - - /* Changed to Start MPRED in microcode */ - /* - * hevc_print(hevc, 0, "[test.c] Start MPRED\n"); - * WRITE_VREG(HEVC_MPRED_INT_STATUS, - * (1<<31) - * ); - */ - - WRITE_VREG(HEVCD_IPP_TOP_CNTL, (0 << 1) | /* enable ipp */ - (1 << 0) /* software reset ipp and mpp */ - ); - WRITE_VREG(HEVCD_IPP_TOP_CNTL, (1 << 1) | /* enable ipp */ - (0 << 0) /* software reset ipp and mpp */ - ); - - if (get_double_write_mode(hevc) & 0x10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, - 0x1 << 31 /*/Enable NV21 reference read mode for MC*/ - ); - -} - -static void decoder_hw_reset(void) -{ - int i; - unsigned int data32; - /* reset iqit to start mem init again */ - WRITE_VREG(DOS_SW_RESET3, (1 << 14) - ); - CLEAR_VREG_MASK(HEVC_CABAC_CONTROL, 1); - CLEAR_VREG_MASK(HEVC_PARSER_CORE_CONTROL, 1); - - data32 = READ_VREG(HEVC_STREAM_CONTROL); - data32 = data32 | (1 << 0) /* stream_fetch_enable */ - ; - WRITE_VREG(HEVC_STREAM_CONTROL, data32); - - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x00000100) { - print_scratch_error(29); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x00000300) { - print_scratch_error(30); - return; - } - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x12345678) { - print_scratch_error(31); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x9abcdef0) { - print_scratch_error(32); - return; - } - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000300); - - data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); - data32 &= 0x03ffffff; - data32 = data32 | (3 << 29) | (2 << 26) | (1 << 24) - | /* stream_buffer_empty_int_amrisc_enable */ - (1 << 22) | /*stream_fifo_empty_int_amrisc_enable */ - (1 << 7) | /* dec_done_int_cpu_enable */ - (1 << 4) | /* startcode_found_int_cpu_enable */ - (0 << 3) | /* startcode_found_int_amrisc_enable */ - (1 << 0) /* parser_int_enable */ - ; - WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); - - data32 = READ_VREG(HEVC_SHIFT_STATUS); - data32 = data32 | (1 << 1) | /* emulation_check_on */ - (1 << 0) /* startcode_check_on */ - ; - WRITE_VREG(HEVC_SHIFT_STATUS, data32); - - WRITE_VREG(HEVC_SHIFT_CONTROL, (3 << 6) |/* sft_valid_wr_position */ - (2 << 4) | /* emulate_code_length_sub_1 */ - (2 << 1) | /* start_code_length_sub_1 */ - (1 << 0) /* stream_shift_enable */ - ); - - WRITE_VREG(HEVC_CABAC_CONTROL, (1 << 0) /* cabac_enable */ - ); - /* hevc_parser_core_clk_en */ - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, (1 << 0) - ); - - /* Initial IQIT_SCALELUT memory -- just to avoid X in simulation */ - WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0); /* cfg_p_addr */ - for (i = 0; i < 1024; i++) - WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); - - /* Send parser_cmd */ - WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); - - parser_cmd_write(); - - WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); - - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - /* (1 << 8) | // sao_sw_pred_enable */ - (1 << 5) | /* parser_sao_if_en */ - (1 << 2) | /* parser_mpred_if_en */ - (1 << 0) /* parser_scaler_if_en */ - ); - - WRITE_VREG(HEVCD_IPP_TOP_CNTL, (0 << 1) | /* enable ipp */ - (1 << 0) /* software reset ipp and mpp */ - ); - WRITE_VREG(HEVCD_IPP_TOP_CNTL, (1 << 1) | /* enable ipp */ - (0 << 0) /* software reset ipp and mpp */ - ); -} - -#ifdef CONFIG_HEVC_CLK_FORCED_ON -static void config_hevc_clk_forced_on(void) -{ - unsigned int rdata32; - /* IQIT */ - rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL); - WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2)); - - /* DBLK */ - rdata32 = READ_VREG(HEVC_DBLK_CFG0); - WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2)); - - /* SAO */ - rdata32 = READ_VREG(HEVC_SAO_CTRL1); - WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2)); - - /* MPRED */ - rdata32 = READ_VREG(HEVC_MPRED_CTRL1); - WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24)); - - /* PARSER */ - rdata32 = READ_VREG(HEVC_STREAM_CONTROL); - WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_SHIFT_CONTROL); - WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_CABAC_CONTROL); - WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13)); - rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL); - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL); - WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL); - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - rdata32 | (0x3 << 5) | (0x3 << 2) | (0x3 << 0)); - - /* IPP */ - rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG); - WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff); - - /* MCRCC */ - rdata32 = READ_VREG(HEVCD_MCRCC_CTL1); - WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3)); -} -#endif - -#ifdef MCRCC_ENABLE -static void config_mcrcc_axi_hw(struct hevc_state_s *hevc, int slice_type) -{ - unsigned int rdata32; - unsigned int rdata32_2; - int l0_cnt = 0; - int l1_cnt = 0x7fff; - - if (get_double_write_mode(hevc) & 0x10) { - l0_cnt = hevc->cur_pic->RefNum_L0; - l1_cnt = hevc->cur_pic->RefNum_L1; - } - - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc */ - - if (slice_type == 2) { /* I-PIC */ - /* remove reset -- disables clock */ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); - return; - } - - if (slice_type == 0) { /* B-PIC */ - /* Programme canvas0 */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 0); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - /* Programme canvas1 */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (16 << 8) | (1 << 1) | 0); - rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32_2 = rdata32_2 & 0xffff; - rdata32_2 = rdata32_2 | (rdata32_2 << 16); - if (rdata32 == rdata32_2 && l1_cnt > 1) { - rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32_2 = rdata32_2 & 0xffff; - rdata32_2 = rdata32_2 | (rdata32_2 << 16); - } - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); - } else { /* P-PIC */ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (1 << 1) | 0); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - if (l0_cnt == 1) { - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - } else { - /* Programme canvas1 */ - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - } - } - /* enable mcrcc progressive-mode */ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); -} -#endif - -static void config_title_hw(struct hevc_state_s *hevc, int sao_vb_size, - int sao_mem_unit) -{ - WRITE_VREG(HEVC_sao_mem_unit, sao_mem_unit); - WRITE_VREG(HEVC_SAO_ABV, hevc->work_space_buf->sao_abv.buf_start); - WRITE_VREG(HEVC_sao_vb_size, sao_vb_size); - WRITE_VREG(HEVC_SAO_VB, hevc->work_space_buf->sao_vb.buf_start); -} - -static u32 init_aux_size; -static int aux_data_is_avaible(struct hevc_state_s *hevc) -{ - u32 reg_val; - - reg_val = READ_VREG(HEVC_AUX_DATA_SIZE); - if (reg_val != 0 && reg_val != init_aux_size) - return 1; - else - return 0; -} - -static void config_aux_buf(struct hevc_state_s *hevc) -{ - WRITE_VREG(HEVC_AUX_ADR, hevc->aux_phy_addr); - init_aux_size = ((hevc->prefix_aux_size >> 4) << 16) | - (hevc->suffix_aux_size >> 4); - WRITE_VREG(HEVC_AUX_DATA_SIZE, init_aux_size); -} - -static void config_mpred_hw(struct hevc_state_s *hevc) -{ - int i; - unsigned int data32; - struct PIC_s *cur_pic = hevc->cur_pic; - struct PIC_s *col_pic = hevc->col_pic; - int AMVP_MAX_NUM_CANDS_MEM = 3; - int AMVP_MAX_NUM_CANDS = 2; - int NUM_CHROMA_MODE = 5; - int DM_CHROMA_IDX = 36; - int above_ptr_ctrl = 0; - int buffer_linear = 1; - int cu_size_log2 = 3; - - int mpred_mv_rd_start_addr; - int mpred_curr_lcu_x; - int mpred_curr_lcu_y; - int mpred_above_buf_start; - int mpred_mv_rd_ptr; - int mpred_mv_rd_ptr_p1; - int mpred_mv_rd_end_addr; - int MV_MEM_UNIT; - int mpred_mv_wr_ptr; - int *ref_poc_L0, *ref_poc_L1; - - int above_en; - int mv_wr_en; - int mv_rd_en; - int col_isIntra; - - if (hevc->slice_type != 2) { - above_en = 1; - mv_wr_en = 1; - mv_rd_en = 1; - col_isIntra = 0; - } else { - above_en = 1; - mv_wr_en = 1; - mv_rd_en = 0; - col_isIntra = 0; - } - - mpred_mv_rd_start_addr = col_pic->mpred_mv_wr_start_addr; - data32 = READ_VREG(HEVC_MPRED_CURR_LCU); - mpred_curr_lcu_x = data32 & 0xffff; - mpred_curr_lcu_y = (data32 >> 16) & 0xffff; - - MV_MEM_UNIT = - hevc->lcu_size_log2 == 6 ? 0x200 : hevc->lcu_size_log2 == - 5 ? 0x80 : 0x20; - mpred_mv_rd_ptr = - mpred_mv_rd_start_addr + (hevc->slice_addr * MV_MEM_UNIT); - - mpred_mv_rd_ptr_p1 = mpred_mv_rd_ptr + MV_MEM_UNIT; - mpred_mv_rd_end_addr = - mpred_mv_rd_start_addr + - ((hevc->lcu_x_num * hevc->lcu_y_num) * MV_MEM_UNIT); - - mpred_above_buf_start = hevc->work_space_buf->mpred_above.buf_start; - - mpred_mv_wr_ptr = - cur_pic->mpred_mv_wr_start_addr + - (hevc->slice_addr * MV_MEM_UNIT); - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "cur pic index %d col pic index %d\n", cur_pic->index, - col_pic->index); - } - - WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, - cur_pic->mpred_mv_wr_start_addr); - WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, mpred_mv_rd_start_addr); - - data32 = ((hevc->lcu_x_num - hevc->tile_width_lcu) * MV_MEM_UNIT); - WRITE_VREG(HEVC_MPRED_MV_WR_ROW_JUMP, data32); - WRITE_VREG(HEVC_MPRED_MV_RD_ROW_JUMP, data32); - - data32 = READ_VREG(HEVC_MPRED_CTRL0); - data32 = (hevc->slice_type | - hevc->new_pic << 2 | - hevc->new_tile << 3 | - hevc->isNextSliceSegment << 4 | - hevc->TMVPFlag << 5 | - hevc->LDCFlag << 6 | - hevc->ColFromL0Flag << 7 | - above_ptr_ctrl << 8 | - above_en << 9 | - mv_wr_en << 10 | - mv_rd_en << 11 | - col_isIntra << 12 | - buffer_linear << 13 | - hevc->LongTerm_Curr << 14 | - hevc->LongTerm_Col << 15 | - hevc->lcu_size_log2 << 16 | - cu_size_log2 << 20 | hevc->plevel << 24); - WRITE_VREG(HEVC_MPRED_CTRL0, data32); - - data32 = READ_VREG(HEVC_MPRED_CTRL1); - data32 = ( -#if 0 - /* no set in m8baby test1902 */ - /* Don't override clk_forced_on , */ - (data32 & (0x1 << 24)) | -#endif - hevc->MaxNumMergeCand | - AMVP_MAX_NUM_CANDS << 4 | - AMVP_MAX_NUM_CANDS_MEM << 8 | - NUM_CHROMA_MODE << 12 | DM_CHROMA_IDX << 16); - WRITE_VREG(HEVC_MPRED_CTRL1, data32); - - data32 = (hevc->pic_w | hevc->pic_h << 16); - WRITE_VREG(HEVC_MPRED_PIC_SIZE, data32); - - data32 = ((hevc->lcu_x_num - 1) | (hevc->lcu_y_num - 1) << 16); - WRITE_VREG(HEVC_MPRED_PIC_SIZE_LCU, data32); - - data32 = (hevc->tile_start_lcu_x | hevc->tile_start_lcu_y << 16); - WRITE_VREG(HEVC_MPRED_TILE_START, data32); - - data32 = (hevc->tile_width_lcu | hevc->tile_height_lcu << 16); - WRITE_VREG(HEVC_MPRED_TILE_SIZE_LCU, data32); - - data32 = (hevc->RefNum_L0 | hevc->RefNum_L1 << 8 | 0 - /* col_RefNum_L0<<16| */ - /* col_RefNum_L1<<24 */ - ); - WRITE_VREG(HEVC_MPRED_REF_NUM, data32); - - data32 = (hevc->LongTerm_Ref); - WRITE_VREG(HEVC_MPRED_LT_REF, data32); - - data32 = 0; - for (i = 0; i < hevc->RefNum_L0; i++) - data32 = data32 | (1 << i); - WRITE_VREG(HEVC_MPRED_REF_EN_L0, data32); - - data32 = 0; - for (i = 0; i < hevc->RefNum_L1; i++) - data32 = data32 | (1 << i); - WRITE_VREG(HEVC_MPRED_REF_EN_L1, data32); - - WRITE_VREG(HEVC_MPRED_CUR_POC, hevc->curr_POC); - WRITE_VREG(HEVC_MPRED_COL_POC, hevc->Col_POC); - - /* below MPRED Ref_POC_xx_Lx registers must follow Ref_POC_xx_L0 -> - * Ref_POC_xx_L1 in pair write order!!! - */ - ref_poc_L0 = &(cur_pic->m_aiRefPOCList0[cur_pic->slice_idx][0]); - ref_poc_L1 = &(cur_pic->m_aiRefPOCList1[cur_pic->slice_idx][0]); - - WRITE_VREG(HEVC_MPRED_L0_REF00_POC, ref_poc_L0[0]); - WRITE_VREG(HEVC_MPRED_L1_REF00_POC, ref_poc_L1[0]); - - WRITE_VREG(HEVC_MPRED_L0_REF01_POC, ref_poc_L0[1]); - WRITE_VREG(HEVC_MPRED_L1_REF01_POC, ref_poc_L1[1]); - - WRITE_VREG(HEVC_MPRED_L0_REF02_POC, ref_poc_L0[2]); - WRITE_VREG(HEVC_MPRED_L1_REF02_POC, ref_poc_L1[2]); - - WRITE_VREG(HEVC_MPRED_L0_REF03_POC, ref_poc_L0[3]); - WRITE_VREG(HEVC_MPRED_L1_REF03_POC, ref_poc_L1[3]); - - WRITE_VREG(HEVC_MPRED_L0_REF04_POC, ref_poc_L0[4]); - WRITE_VREG(HEVC_MPRED_L1_REF04_POC, ref_poc_L1[4]); - - WRITE_VREG(HEVC_MPRED_L0_REF05_POC, ref_poc_L0[5]); - WRITE_VREG(HEVC_MPRED_L1_REF05_POC, ref_poc_L1[5]); - - WRITE_VREG(HEVC_MPRED_L0_REF06_POC, ref_poc_L0[6]); - WRITE_VREG(HEVC_MPRED_L1_REF06_POC, ref_poc_L1[6]); - - WRITE_VREG(HEVC_MPRED_L0_REF07_POC, ref_poc_L0[7]); - WRITE_VREG(HEVC_MPRED_L1_REF07_POC, ref_poc_L1[7]); - - WRITE_VREG(HEVC_MPRED_L0_REF08_POC, ref_poc_L0[8]); - WRITE_VREG(HEVC_MPRED_L1_REF08_POC, ref_poc_L1[8]); - - WRITE_VREG(HEVC_MPRED_L0_REF09_POC, ref_poc_L0[9]); - WRITE_VREG(HEVC_MPRED_L1_REF09_POC, ref_poc_L1[9]); - - WRITE_VREG(HEVC_MPRED_L0_REF10_POC, ref_poc_L0[10]); - WRITE_VREG(HEVC_MPRED_L1_REF10_POC, ref_poc_L1[10]); - - WRITE_VREG(HEVC_MPRED_L0_REF11_POC, ref_poc_L0[11]); - WRITE_VREG(HEVC_MPRED_L1_REF11_POC, ref_poc_L1[11]); - - WRITE_VREG(HEVC_MPRED_L0_REF12_POC, ref_poc_L0[12]); - WRITE_VREG(HEVC_MPRED_L1_REF12_POC, ref_poc_L1[12]); - - WRITE_VREG(HEVC_MPRED_L0_REF13_POC, ref_poc_L0[13]); - WRITE_VREG(HEVC_MPRED_L1_REF13_POC, ref_poc_L1[13]); - - WRITE_VREG(HEVC_MPRED_L0_REF14_POC, ref_poc_L0[14]); - WRITE_VREG(HEVC_MPRED_L1_REF14_POC, ref_poc_L1[14]); - - WRITE_VREG(HEVC_MPRED_L0_REF15_POC, ref_poc_L0[15]); - WRITE_VREG(HEVC_MPRED_L1_REF15_POC, ref_poc_L1[15]); - - if (hevc->new_pic) { - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, mpred_above_buf_start); - WRITE_VREG(HEVC_MPRED_MV_WPTR, mpred_mv_wr_ptr); - /* WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr); */ - WRITE_VREG(HEVC_MPRED_MV_RPTR, mpred_mv_rd_start_addr); - } else if (!hevc->isNextSliceSegment) { - /* WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr_p1); */ - WRITE_VREG(HEVC_MPRED_MV_RPTR, mpred_mv_rd_ptr); - } - - WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, mpred_mv_rd_end_addr); -} - -static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) -{ - unsigned int data32, data32_2; - int misc_flag0 = hevc->misc_flag0; - int slice_deblocking_filter_disabled_flag = 0; - - int mc_buffer_size_u_v = - hevc->lcu_total * hevc->lcu_size * hevc->lcu_size / 2; - int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - struct PIC_s *cur_pic = hevc->cur_pic; - - data32 = READ_VREG(HEVC_SAO_CTRL0); - data32 &= (~0xf); - data32 |= hevc->lcu_size_log2; - WRITE_VREG(HEVC_SAO_CTRL0, data32); - - data32 = (hevc->pic_w | hevc->pic_h << 16); - WRITE_VREG(HEVC_SAO_PIC_SIZE, data32); - - data32 = ((hevc->lcu_x_num - 1) | (hevc->lcu_y_num - 1) << 16); - WRITE_VREG(HEVC_SAO_PIC_SIZE_LCU, data32); - - if (hevc->new_pic) - WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); -#ifdef LOSLESS_COMPRESS_MODE -/*SUPPORT_10BIT*/ - if ((get_double_write_mode(hevc) & 0x10) == 0) { - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 &= (~(0xff << 16)); - - if (get_double_write_mode(hevc) == 2 || - get_double_write_mode(hevc) == 3) - data32 |= (0xff<<16); - else if (get_double_write_mode(hevc) == 4) - data32 |= (0x33<<16); - - if (hevc->mem_saving_mode == 1) - data32 |= (1 << 9); - else - data32 &= ~(1 << 9); - if (workaround_enable & 1) - data32 |= (1 << 7); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - data32 = cur_pic->mc_y_adr; - if (get_double_write_mode(hevc)) - WRITE_VREG(HEVC_SAO_Y_START_ADDR, cur_pic->dw_y_adr); - - if ((get_double_write_mode(hevc) & 0x10) == 0) - WRITE_VREG(HEVC_CM_BODY_START_ADDR, data32); - - if (hevc->mmu_enable) - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, cur_pic->header_adr); -#else - data32 = cur_pic->mc_y_adr; - WRITE_VREG(HEVC_SAO_Y_START_ADDR, data32); -#endif - data32 = (mc_buffer_size_u_v_h << 16) << 1; - WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); - -#ifdef LOSLESS_COMPRESS_MODE -/*SUPPORT_10BIT*/ - if (get_double_write_mode(hevc)) - WRITE_VREG(HEVC_SAO_C_START_ADDR, cur_pic->dw_u_v_adr); -#else - data32 = cur_pic->mc_u_v_adr; - WRITE_VREG(HEVC_SAO_C_START_ADDR, data32); -#endif - data32 = (mc_buffer_size_u_v_h << 16); - WRITE_VREG(HEVC_SAO_C_LENGTH, data32); - -#ifdef LOSLESS_COMPRESS_MODE -/*SUPPORT_10BIT*/ - if (get_double_write_mode(hevc)) { - WRITE_VREG(HEVC_SAO_Y_WPTR, cur_pic->dw_y_adr); - WRITE_VREG(HEVC_SAO_C_WPTR, cur_pic->dw_u_v_adr); - } -#else - /* multi tile to do... */ - data32 = cur_pic->mc_y_adr; - WRITE_VREG(HEVC_SAO_Y_WPTR, data32); - - data32 = cur_pic->mc_u_v_adr; - WRITE_VREG(HEVC_SAO_C_WPTR, data32); -#endif - /* DBLK CONFIG HERE */ - if (hevc->new_pic) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - data32 = (0xff << 8) | (0x0 << 0); - else - data32 = (0x57 << 8) | /* 1st/2nd write both enable*/ - (0x0 << 0); /* h265 video format*/ - - if (hevc->pic_w >= 1280) - data32 |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/ - data32 &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ - if (get_double_write_mode(hevc) == 0) - data32 |= (0x1 << 8); /*enable first write*/ - else if (get_double_write_mode(hevc) == 0x10) - data32 |= (0x1 << 9); /*double write only*/ - else - data32 |= ((0x1 << 8) |(0x1 << 9)); - - WRITE_VREG(HEVC_DBLK_CFGB, data32); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data32); - } - data32 = (hevc->pic_w | hevc->pic_h << 16); - WRITE_VREG(HEVC_DBLK_CFG2, data32); - - if ((misc_flag0 >> PCM_ENABLE_FLAG_BIT) & 0x1) { - data32 = - ((misc_flag0 >> - PCM_LOOP_FILTER_DISABLED_FLAG_BIT) & - 0x1) << 3; - } else - data32 = 0; - data32 |= - (((params->p.pps_cb_qp_offset & 0x1f) << 4) | - ((params->p.pps_cr_qp_offset - & 0x1f) << - 9)); - data32 |= - (hevc->lcu_size == - 64) ? 0 : ((hevc->lcu_size == 32) ? 1 : 2); - - WRITE_VREG(HEVC_DBLK_CFG1, data32); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - /*if (debug & 0x80) {*/ - data32 = 1 << 28; /* Debug only: sts1 chooses dblk_main*/ - WRITE_VREG(HEVC_DBLK_STS1 + 4, data32); /* 0x3510 */ - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "[DBLK DEBUG] HEVC1 STS1 : 0x%x\n", - data32); - /*}*/ - } - } -#if 0 - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - data32 |= (mem_map_mode << - 12); - -/* [13:12] axi_aformat, - * 0-Linear, 1-32x32, 2-64x32 - */ - WRITE_VREG(HEVC_SAO_CTRL1, data32); - - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - data32 |= (mem_map_mode << - 4); - -/* [5:4] -- address_format - * 00:linear 01:32x32 10:64x32 - */ - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#else - /* m8baby test1902 */ - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - data32 |= (mem_map_mode << - 12); - -/* [13:12] axi_aformat, 0-Linear, - * 1-32x32, 2-64x32 - */ - data32 &= (~0xff0); - /* data32 |= 0x670; // Big-Endian per 64-bit */ - data32 |= endian; /* Big-Endian per 64-bit */ - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { - data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ - if (get_double_write_mode(hevc) == 0) - data32 |= 0x2; /*disable double write*/ - else if (get_double_write_mode(hevc) & 0x10) - data32 |= 0x1; /*disable cm*/ - } else { - unsigned int data; - data = (0x57 << 8) | /* 1st/2nd write both enable*/ - (0x0 << 0); /* h265 video format*/ - if (hevc->pic_w >= 1280) - data |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/ - data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ - if (get_double_write_mode(hevc) == 0) - data |= (0x1 << 8); /*enable first write*/ - else if (get_double_write_mode(hevc) & 0x10) - data |= (0x1 << 9); /*double write only*/ - else - data |= ((0x1 << 8) |(0x1 << 9)); - - WRITE_VREG(HEVC_DBLK_CFGB, data); - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data); - } - - WRITE_VREG(HEVC_SAO_CTRL1, data32); - if (get_double_write_mode(hevc) & 0x10) { - /* [23:22] dw_v1_ctrl - *[21:20] dw_v0_ctrl - *[19:18] dw_h1_ctrl - *[17:16] dw_h0_ctrl - */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /*set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ - data32 |= (mem_map_mode << - 4); - data32 &= (~0xF); - data32 |= 0xf; /* valid only when double write only */ - /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#endif - data32 = 0; - data32_2 = READ_VREG(HEVC_SAO_CTRL0); - data32_2 &= (~0x300); - /* slice_deblocking_filter_disabled_flag = 0; - * ucode has handle it , so read it from ucode directly - */ - if (hevc->tile_enabled) { - data32 |= - ((misc_flag0 >> - LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT) & - 0x1) << 0; - data32_2 |= - ((misc_flag0 >> - LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT) & - 0x1) << 8; - } - slice_deblocking_filter_disabled_flag = (misc_flag0 >> - SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & - 0x1; /* ucode has handle it,so read it from ucode directly */ - if ((misc_flag0 & (1 << DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT)) - && (misc_flag0 & (1 << DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT))) { - /* slice_deblocking_filter_disabled_flag = - * (misc_flag0>>SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT)&0x1; - * //ucode has handle it , so read it from ucode directly - */ - data32 |= slice_deblocking_filter_disabled_flag << 2; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, - "(1,%x)", data32); - if (!slice_deblocking_filter_disabled_flag) { - data32 |= (params->p.slice_beta_offset_div2 & 0xf) << 3; - data32 |= (params->p.slice_tc_offset_div2 & 0xf) << 7; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, - "(2,%x)", data32); - } - } else { - data32 |= - ((misc_flag0 >> - PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & - 0x1) << 2; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, - "(3,%x)", data32); - if (((misc_flag0 >> PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & - 0x1) == 0) { - data32 |= (params->p.pps_beta_offset_div2 & 0xf) << 3; - data32 |= (params->p.pps_tc_offset_div2 & 0xf) << 7; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, - "(4,%x)", data32); - } - } - if ((misc_flag0 & (1 << PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT)) - && ((misc_flag0 & (1 << SLICE_SAO_LUMA_FLAG_BIT)) - || (misc_flag0 & (1 << SLICE_SAO_CHROMA_FLAG_BIT)) - || (!slice_deblocking_filter_disabled_flag))) { - data32 |= - ((misc_flag0 >> - SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) - & 0x1) << 1; - data32_2 |= - ((misc_flag0 >> - SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) - & 0x1) << 9; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, - "(5,%x)\n", data32); - } else { - data32 |= - ((misc_flag0 >> - PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) - & 0x1) << 1; - data32_2 |= - ((misc_flag0 >> - PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) - & 0x1) << 9; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print_cont(hevc, 0, - "(6,%x)\n", data32); - } - WRITE_VREG(HEVC_DBLK_CFG9, data32); - WRITE_VREG(HEVC_SAO_CTRL0, data32_2); -} - -#ifdef TEST_NO_BUF -static unsigned char test_flag = 1; -#endif - -static void pic_list_process(struct hevc_state_s *hevc) -{ - int work_pic_num = get_work_pic_num(hevc); - int alloc_pic_count = 0; - int i; - struct PIC_s *pic; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - alloc_pic_count++; - if (pic->output_mark == 0 && pic->referenced == 0 - && pic->output_ready == 0 - && (pic->width != hevc->pic_w || - pic->height != hevc->pic_h) - ) { - set_buf_unused(hevc, pic->BUF_index); - pic->BUF_index = -1; - if (alloc_pic_count > work_pic_num) { - pic->width = 0; - pic->height = 0; - pic->index = -1; - } else { - pic->width = hevc->pic_w; - pic->height = hevc->pic_h; - } - } - } - if (alloc_pic_count < work_pic_num) { - int new_count = alloc_pic_count; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic && pic->index == -1) { - pic->index = i; - pic->BUF_index = -1; - pic->width = hevc->pic_w; - pic->height = hevc->pic_h; - new_count++; - if (new_count >= - work_pic_num) - break; - } - } - - } - dealloc_unused_buf(hevc); - if (get_alloc_pic_count(hevc) - != alloc_pic_count) { - hevc_print_cont(hevc, 0, - "%s: work_pic_num is %d, Change alloc_pic_count from %d to %d\n", - __func__, - work_pic_num, - alloc_pic_count, - get_alloc_pic_count(hevc)); - } -} - -static void recycle_mmu_bufs(struct hevc_state_s *hevc) -{ - int i; - struct PIC_s *pic; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - - if (pic->output_mark == 0 && pic->referenced == 0 - && pic->output_ready == 0 - && pic->scatter_alloc - ) - release_pic_mmu_buf(hevc, pic); - } - -} - -static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, - union param_u *rpm_param) -{ - struct PIC_s *new_pic = NULL; - struct PIC_s *pic; - int i; - int ret; - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - - if (pic->output_mark == 0 && pic->referenced == 0 - && pic->output_ready == 0 - && pic->width == hevc->pic_w - && pic->height == hevc->pic_h - ) { - if (new_pic) { - if (new_pic->POC != INVALID_POC) { - if (pic->POC == INVALID_POC || - pic->POC < new_pic->POC) - new_pic = pic; - } - } else - new_pic = pic; - } - } - - if (new_pic == NULL) - return NULL; - - if (new_pic->BUF_index < 0) { - if (alloc_buf(hevc) < 0) - return NULL; - else { - if (config_pic(hevc, new_pic) < 0) { - dealloc_pic_buf(hevc, new_pic); - return NULL; - } - } - new_pic->width = hevc->pic_w; - new_pic->height = hevc->pic_h; - set_canvas(hevc, new_pic); - - init_pic_list_hw(hevc); - } - - if (new_pic) { - new_pic->double_write_mode = - get_double_write_mode(hevc); - if (new_pic->double_write_mode) - set_canvas(hevc, new_pic); - -#ifdef TEST_NO_BUF - if (test_flag) { - test_flag = 0; - return NULL; - } else - test_flag = 1; -#endif - if (get_mv_buf(hevc, new_pic) < 0) - return NULL; - - if (hevc->mmu_enable) { - ret = H265_alloc_mmu(hevc, new_pic, - rpm_param->p.bit_depth, - hevc->frame_mmu_map_addr); - if (ret != 0) { - put_mv_buf(hevc, new_pic); - hevc_print(hevc, 0, - "can't alloc need mmu1,idx %d ret =%d\n", - new_pic->decode_idx, - ret); - return NULL; - } - } - new_pic->referenced = 1; - new_pic->decode_idx = hevc->decode_idx; - new_pic->slice_idx = 0; - new_pic->referenced = 1; - new_pic->output_mark = 0; - new_pic->recon_mark = 0; - new_pic->error_mark = 0; - /* new_pic->output_ready = 0; */ - new_pic->num_reorder_pic = rpm_param->p.sps_num_reorder_pics_0; - new_pic->losless_comp_body_size = hevc->losless_comp_body_size; - new_pic->POC = hevc->curr_POC; - new_pic->pic_struct = hevc->curr_pic_struct; - if (new_pic->aux_data_buf) - release_aux_data(hevc, new_pic); - new_pic->mem_saving_mode = - hevc->mem_saving_mode; - new_pic->bit_depth_luma = - hevc->bit_depth_luma; - new_pic->bit_depth_chroma = - hevc->bit_depth_chroma; - new_pic->video_signal_type = - hevc->video_signal_type; - - new_pic->conformance_window_flag = - hevc->param.p.conformance_window_flag; - new_pic->conf_win_left_offset = - hevc->param.p.conf_win_left_offset; - new_pic->conf_win_right_offset = - hevc->param.p.conf_win_right_offset; - new_pic->conf_win_top_offset = - hevc->param.p.conf_win_top_offset; - new_pic->conf_win_bottom_offset = - hevc->param.p.conf_win_bottom_offset; - new_pic->chroma_format_idc = - hevc->param.p.chroma_format_idc; - - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s: index %d, buf_idx %d, decode_idx %d, POC %d\n", - __func__, new_pic->index, - new_pic->BUF_index, new_pic->decode_idx, - new_pic->POC); - - } - - return new_pic; -} - -static int get_display_pic_num(struct hevc_state_s *hevc) -{ - int i; - struct PIC_s *pic; - int num = 0; - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || - pic->index == -1) - continue; - - if (pic->output_ready == 1) - num++; - } - return num; -} - -static void flush_output(struct hevc_state_s *hevc, struct PIC_s *pic) -{ - struct PIC_s *pic_display; - - if (pic) { - /*PB skip control */ - if (pic->error_mark == 0 && hevc->PB_skip_mode == 1) { - /* start decoding after first I */ - hevc->ignore_bufmgr_error |= 0x1; - } - if (hevc->ignore_bufmgr_error & 1) { - if (hevc->PB_skip_count_after_decoding > 0) - hevc->PB_skip_count_after_decoding--; - else { - /* start displaying */ - hevc->ignore_bufmgr_error |= 0x2; - } - } - /**/ - if (pic->POC != INVALID_POC) { - pic->output_mark = 1; - pic->recon_mark = 1; - } - pic->recon_mark = 1; - } - do { - pic_display = output_pic(hevc, 1); - - if (pic_display) { - pic_display->referenced = 0; - put_mv_buf(hevc, pic_display); - if ((pic_display->error_mark - && ((hevc->ignore_bufmgr_error & 0x2) == 0)) - || (get_dbg_flag(hevc) & - H265_DEBUG_DISPLAY_CUR_FRAME) - || (get_dbg_flag(hevc) & - H265_DEBUG_NO_DISPLAY)) { - pic_display->output_ready = 0; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "[BM] Display: POC %d, ", - pic_display->POC); - hevc_print_cont(hevc, 0, - "decoding index %d ==> ", - pic_display->decode_idx); - hevc_print_cont(hevc, 0, - "Debug mode or error, recycle it\n"); - } - } else { - if (hevc->i_only & 0x1 - && pic_display->slice_type != 2) { - pic_display->output_ready = 0; - } else { - prepare_display_buf(hevc, pic_display); - if (get_dbg_flag(hevc) - & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "[BM] flush Display: POC %d, ", - pic_display->POC); - hevc_print_cont(hevc, 0, - "decoding index %d\n", - pic_display->decode_idx); - } - } - } - } - } while (pic_display); - clear_referenced_flag(hevc); -} - -/* -* dv_meta_flag: 1, dolby meta only; 2, not include dolby meta -*/ -static void set_aux_data(struct hevc_state_s *hevc, - struct PIC_s *pic, unsigned char suffix_flag, - unsigned char dv_meta_flag) -{ - int i; - unsigned short *aux_adr; - unsigned int size_reg_val = - READ_VREG(HEVC_AUX_DATA_SIZE); - unsigned int aux_count = 0; - int aux_size = 0; - if (pic == NULL || 0 == aux_data_is_avaible(hevc)) - return; - - if (hevc->aux_data_dirty || - hevc->m_ins_flag == 0) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->aux_phy_addr, - hevc->prefix_aux_size + hevc->suffix_aux_size, - DMA_FROM_DEVICE); - - hevc->aux_data_dirty = 0; - } - - if (suffix_flag) { - aux_adr = (unsigned short *) - (hevc->aux_addr + - hevc->prefix_aux_size); - aux_count = - ((size_reg_val & 0xffff) << 4) - >> 1; - aux_size = - hevc->suffix_aux_size; - } else { - aux_adr = - (unsigned short *)hevc->aux_addr; - aux_count = - ((size_reg_val >> 16) << 4) - >> 1; - aux_size = - hevc->prefix_aux_size; - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { - hevc_print(hevc, 0, - "%s:pic 0x%p old size %d count %d,suf %d dv_flag %d\r\n", - __func__, pic, pic->aux_data_size, - aux_count, suffix_flag, dv_meta_flag); - } - if (aux_size > 0 && aux_count > 0) { - int heads_size = 0; - int new_size; - char *new_buf; - - for (i = 0; i < aux_count; i++) { - unsigned char tag = aux_adr[i] >> 8; - if (tag != 0 && tag != 0xff) { - if (dv_meta_flag == 0) - heads_size += 8; - else if (dv_meta_flag == 1 && tag == 0x1) - heads_size += 8; - else if (dv_meta_flag == 2 && tag != 0x1) - heads_size += 8; - } - } - new_size = pic->aux_data_size + aux_count + heads_size; - new_buf = vmalloc(new_size); - if (new_buf) { - unsigned char valid_tag = 0; - unsigned char *h = - new_buf + - pic->aux_data_size; - unsigned char *p = h + 8; - int len = 0; - int padding_len = 0; - memcpy(new_buf, pic->aux_data_buf, pic->aux_data_size); - if (pic->aux_data_buf) - vfree(pic->aux_data_buf); - pic->aux_data_buf = new_buf; - for (i = 0; i < aux_count; i += 4) { - int ii; - unsigned char tag = aux_adr[i + 3] >> 8; - if (tag != 0 && tag != 0xff) { - if (dv_meta_flag == 0) - valid_tag = 1; - else if (dv_meta_flag == 1 - && tag == 0x1) - valid_tag = 1; - else if (dv_meta_flag == 2 - && tag != 0x1) - valid_tag = 1; - else - valid_tag = 0; - if (valid_tag && len > 0) { - pic->aux_data_size += - (len + 8); - h[0] = (len >> 24) - & 0xff; - h[1] = (len >> 16) - & 0xff; - h[2] = (len >> 8) - & 0xff; - h[3] = (len >> 0) - & 0xff; - h[6] = - (padding_len >> 8) - & 0xff; - h[7] = (padding_len) - & 0xff; - h += (len + 8); - p += 8; - len = 0; - padding_len = 0; - } - if (valid_tag) { - h[4] = tag; - h[5] = 0; - h[6] = 0; - h[7] = 0; - } - } - if (valid_tag) { - for (ii = 0; ii < 4; ii++) { - unsigned short aa = - aux_adr[i + 3 - - ii]; - *p = aa & 0xff; - p++; - len++; - /*if ((aa >> 8) == 0xff) - padding_len++;*/ - } - } - } - if (len > 0) { - pic->aux_data_size += (len + 8); - h[0] = (len >> 24) & 0xff; - h[1] = (len >> 16) & 0xff; - h[2] = (len >> 8) & 0xff; - h[3] = (len >> 0) & 0xff; - h[6] = (padding_len >> 8) & 0xff; - h[7] = (padding_len) & 0xff; - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { - hevc_print(hevc, 0, - "aux: (size %d) suffix_flag %d\n", - pic->aux_data_size, suffix_flag); - for (i = 0; i < pic->aux_data_size; i++) { - hevc_print_cont(hevc, 0, - "%02x ", pic->aux_data_buf[i]); - if (((i + 1) & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - } - hevc_print_cont(hevc, 0, "\n"); - } - - } else { - hevc_print(hevc, 0, "new buf alloc failed\n"); - if (pic->aux_data_buf) - vfree(pic->aux_data_buf); - pic->aux_data_buf = NULL; - pic->aux_data_size = 0; - } - } - -} - -static void release_aux_data(struct hevc_state_s *hevc, - struct PIC_s *pic) -{ - if (pic->aux_data_buf) - vfree(pic->aux_data_buf); - pic->aux_data_buf = NULL; - pic->aux_data_size = 0; -} - -static inline void hevc_pre_pic(struct hevc_state_s *hevc, - struct PIC_s *pic) -{ - - /* prev pic */ - /*if (hevc->curr_POC != 0) {*/ - int decoded_poc = hevc->iPrevPOC; -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) { - decoded_poc = hevc->decoded_poc; - hevc->decoded_poc = INVALID_POC; - } -#endif - if (hevc->m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR - && hevc->m_nalUnitType != - NAL_UNIT_CODED_SLICE_IDR_N_LP) { - struct PIC_s *pic_display; - - pic = get_pic_by_POC(hevc, decoded_poc); - if (pic && (pic->POC != INVALID_POC)) { - /*PB skip control */ - if (pic->error_mark == 0 - && hevc->PB_skip_mode == 1) { - /* start decoding after - * first I - */ - hevc->ignore_bufmgr_error |= 0x1; - } - if (hevc->ignore_bufmgr_error & 1) { - if (hevc->PB_skip_count_after_decoding > 0) { - hevc->PB_skip_count_after_decoding--; - } else { - /* start displaying */ - hevc->ignore_bufmgr_error |= 0x2; - } - } - if (hevc->mmu_enable - && ((hevc->double_write_mode & 0x10) == 0)) { - if (!hevc->m_ins_flag) { - hevc->used_4k_num = - READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; - - if ((!is_skip_decoding(hevc, pic)) && - (hevc->used_4k_num >= 0) && - (hevc->cur_pic->scatter_alloc - == 1)) { - hevc_print(hevc, - H265_DEBUG_BUFMGR_MORE, - "%s pic index %d scatter_alloc %d page_start %d\n", - "decoder_mmu_box_free_idx_tail", - hevc->cur_pic->index, - hevc->cur_pic->scatter_alloc, - hevc->used_4k_num); - decoder_mmu_box_free_idx_tail( - hevc->mmu_box, - hevc->cur_pic->index, - hevc->used_4k_num); - hevc->cur_pic->scatter_alloc - = 2; - } - hevc->used_4k_num = -1; - } - } - - pic->output_mark = 1; - pic->recon_mark = 1; - } - do { - pic_display = output_pic(hevc, 0); - - if (pic_display) { - if ((pic_display->error_mark && - ((hevc->ignore_bufmgr_error & - 0x2) == 0)) - || (get_dbg_flag(hevc) & - H265_DEBUG_DISPLAY_CUR_FRAME) - || (get_dbg_flag(hevc) & - H265_DEBUG_NO_DISPLAY)) { - pic_display->output_ready = 0; - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "[BM] Display: POC %d, ", - pic_display->POC); - hevc_print_cont(hevc, 0, - "decoding index %d ==> ", - pic_display-> - decode_idx); - hevc_print_cont(hevc, 0, - "Debug or err,recycle it\n"); - } - } else { - if (hevc->i_only & 0x1 - && pic_display-> - slice_type != 2) { - pic_display->output_ready = 0; - } else { - prepare_display_buf - (hevc, - pic_display); - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "[BM] Display: POC %d, ", - pic_display->POC); - hevc_print_cont(hevc, 0, - "decoding index %d\n", - pic_display-> - decode_idx); - } - } - } - } - } while (pic_display); - } else { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "[BM] current pic is IDR, "); - hevc_print(hevc, 0, - "clear referenced flag of all buffers\n"); - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - dump_pic_list(hevc); - pic = get_pic_by_POC(hevc, decoded_poc); - flush_output(hevc, pic); - } - -} - -static void check_pic_decoded_error_pre(struct hevc_state_s *hevc, - int decoded_lcu) -{ - int current_lcu_idx = decoded_lcu; - if (decoded_lcu < 0) - return; - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "cur lcu idx = %d, (total %d)\n", - current_lcu_idx, hevc->lcu_total); - } - if ((error_handle_policy & 0x20) == 0 && hevc->cur_pic != NULL) { - if (hevc->first_pic_after_recover) { - if (current_lcu_idx != - ((hevc->lcu_x_num_pre*hevc->lcu_y_num_pre) - 1)) - hevc->cur_pic->error_mark = 1; - } else { - if (hevc->lcu_x_num_pre != 0 - && hevc->lcu_y_num_pre != 0 - && current_lcu_idx != 0 - && current_lcu_idx < - ((hevc->lcu_x_num_pre*hevc->lcu_y_num_pre) - 1)) - hevc->cur_pic->error_mark = 1; - } - if (hevc->cur_pic->error_mark) { - hevc_print(hevc, 0, - "cur lcu idx = %d, (total %d), set error_mark\n", - current_lcu_idx, - hevc->lcu_x_num_pre*hevc->lcu_y_num_pre); - if (is_log_enable(hevc)) - add_log(hevc, - "cur lcu idx = %d, (total %d), set error_mark", - current_lcu_idx, - hevc->lcu_x_num_pre * - hevc->lcu_y_num_pre); - - } - - } - if (hevc->cur_pic && hevc->head_error_flag) { - hevc->cur_pic->error_mark = 1; - hevc_print(hevc, 0, - "head has error, set error_mark\n"); - } - - if ((error_handle_policy & 0x80) == 0) { - if (hevc->over_decode && hevc->cur_pic) { - hevc_print(hevc, 0, - "over decode, set error_mark\n"); - hevc->cur_pic->error_mark = 1; - } - } - - hevc->lcu_x_num_pre = hevc->lcu_x_num; - hevc->lcu_y_num_pre = hevc->lcu_y_num; -} - -static void check_pic_decoded_error(struct hevc_state_s *hevc, - int decoded_lcu) -{ - int current_lcu_idx = decoded_lcu; - if (decoded_lcu < 0) - return; - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "cur lcu idx = %d, (total %d)\n", - current_lcu_idx, hevc->lcu_total); - } - if ((error_handle_policy & 0x20) == 0 && hevc->cur_pic != NULL) { - if (hevc->lcu_x_num != 0 - && hevc->lcu_y_num != 0 - && current_lcu_idx != 0 - && current_lcu_idx < - ((hevc->lcu_x_num*hevc->lcu_y_num) - 1)) - hevc->cur_pic->error_mark = 1; - if (hevc->cur_pic->error_mark) { - hevc_print(hevc, 0, - "cur lcu idx = %d, (total %d), set error_mark\n", - current_lcu_idx, - hevc->lcu_x_num*hevc->lcu_y_num); - if (is_log_enable(hevc)) - add_log(hevc, - "cur lcu idx = %d, (total %d), set error_mark", - current_lcu_idx, - hevc->lcu_x_num * - hevc->lcu_y_num); - - } - - } - if (hevc->cur_pic && hevc->head_error_flag) { - hevc->cur_pic->error_mark = 1; - hevc_print(hevc, 0, - "head has error, set error_mark\n"); - } - - if ((error_handle_policy & 0x80) == 0) { - if (hevc->over_decode && hevc->cur_pic) { - hevc_print(hevc, 0, - "over decode, set error_mark\n"); - hevc->cur_pic->error_mark = 1; - } - } -} - -/* only when we decoded one field or one frame, -we can call this function to get qos info*/ -static void get_picture_qos_info(struct hevc_state_s *hevc) -{ - struct PIC_s *picture = hevc->cur_pic; - -/* -#define DEBUG_QOS -*/ - - if (!hevc->cur_pic) - return; - - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { - unsigned char a[3]; - unsigned char i, j, t; - unsigned long data; - - data = READ_VREG(HEVC_MV_INFO); - if (picture->slice_type == I_SLICE) - data = 0; - a[0] = data & 0xff; - a[1] = (data >> 8) & 0xff; - a[2] = (data >> 16) & 0xff; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_mv = a[2]; - picture->avg_mv = a[1]; - picture->min_mv = a[0]; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); -#endif - - data = READ_VREG(HEVC_QP_INFO); - a[0] = data & 0x1f; - a[1] = (data >> 8) & 0x3f; - a[2] = (data >> 16) & 0x7f; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_qp = a[2]; - picture->avg_qp = a[1]; - picture->min_qp = a[0]; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); -#endif - - data = READ_VREG(HEVC_SKIP_INFO); - a[0] = data & 0x1f; - a[1] = (data >> 8) & 0x3f; - a[2] = (data >> 16) & 0x7f; - - for (i = 0; i < 3; i++) - for (j = i+1; j < 3; j++) { - if (a[j] < a[i]) { - t = a[j]; - a[j] = a[i]; - a[i] = t; - } else if (a[j] == a[i]) { - a[i]++; - t = a[j]; - a[j] = a[i]; - a[i] = t; - } - } - picture->max_skip = a[2]; - picture->avg_skip = a[1]; - picture->min_skip = a[0]; - -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", - data, a[0], a[1], a[2]); -#endif - } else { - uint32_t blk88_y_count; - uint32_t blk88_c_count; - uint32_t blk22_mv_count; - uint32_t rdata32; - int32_t mv_hi; - int32_t mv_lo; - uint32_t rdata32_l; - uint32_t mvx_L0_hi; - uint32_t mvy_L0_hi; - uint32_t mvx_L1_hi; - uint32_t mvy_L1_hi; - int64_t value; - uint64_t temp_value; -#ifdef DEBUG_QOS - int pic_number = picture->POC; -#endif - - picture->max_mv = 0; - picture->avg_mv = 0; - picture->min_mv = 0; - - picture->max_skip = 0; - picture->avg_skip = 0; - picture->min_skip = 0; - - picture->max_qp = 0; - picture->avg_qp = 0; - picture->min_qp = 0; - - - -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "slice_type:%d, poc:%d\n", - picture->slice_type, - picture->POC); -#endif - /* set rd_idx to 0 */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); - - blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); - if (blk88_y_count == 0) { -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* qp_y_sum */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_y_count, - rdata32, blk88_y_count); -#endif - picture->avg_qp = rdata32/blk88_y_count; - /* intra_y_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] Y intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - /* skipped_y_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_y_count, - '%', rdata32); -#endif - picture->avg_skip = rdata32*100/blk88_y_count; - /* coeff_non_zero_y_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_y_count*1)), - '%', rdata32); -#endif - /* blk66_c_count */ - blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); - if (blk88_c_count == 0) { -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] NO Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* qp_c_sum */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", - pic_number, rdata32/blk88_c_count, - rdata32, blk88_c_count); -#endif - /* intra_c_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] C intra rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* skipped_cu_c_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] C skipped rate : %d%c (%d)\n", - pic_number, rdata32*100/blk88_c_count, - '%', rdata32); -#endif - /* coeff_non_zero_c_count */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", - pic_number, (100 - rdata32*100/(blk88_c_count*1)), - '%', rdata32); -#endif - - /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], - 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] Y QP min : %d\n", - pic_number, (rdata32>>0)&0xff); -#endif - picture->min_qp = (rdata32>>0)&0xff; - -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] Y QP max : %d\n", - pic_number, (rdata32>>8)&0xff); -#endif - picture->max_qp = (rdata32>>8)&0xff; - -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] C QP min : %d\n", - pic_number, (rdata32>>16)&0xff); - hevc_print(hevc, 0, "[Picture %d Quality] C QP max : %d\n", - pic_number, (rdata32>>24)&0xff); -#endif - - /* blk22_mv_count */ - blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); - if (blk22_mv_count == 0) { -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] NO MV Data yet.\n", - pic_number); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - return; - } - /* mvy_L1_count[39:32], mvx_L1_count[39:32], - mvy_L0_count[39:32], mvx_L0_count[39:32] */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - /* should all be 0x00 or 0xff */ -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] MV AVG High Bits: 0x%X\n", - pic_number, rdata32); -#endif - mvx_L0_hi = ((rdata32>>0)&0xff); - mvy_L0_hi = ((rdata32>>8)&0xff); - mvx_L1_hi = ((rdata32>>16)&0xff); - mvy_L1_hi = ((rdata32>>24)&0xff); - - /* mvx_L0_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvx_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvx_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; - value = div_s64(value, blk22_mv_count); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", - pic_number, (int)value, - value, blk22_mv_count); -#endif - picture->avg_mv = value; - - /* mvy_L0_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvy_L0_hi; - temp_value = (temp_value << 32) | rdata32_l; - - if (mvy_L0_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvx_L1_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvx_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvx_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* mvy_L1_count[31:0] */ - rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); - temp_value = mvy_L1_hi; - temp_value = (temp_value << 32) | rdata32_l; - if (mvy_L1_hi & 0x80) - value = 0xFFFFFFF000000000 | temp_value; - else - value = temp_value; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", - pic_number, rdata32_l/blk22_mv_count, - value, blk22_mv_count); -#endif - - /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - picture->max_mv = mv_hi; - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - picture->min_mv = mv_lo; - - /* {mvy_L0_max, mvy_L0_min} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvx_L1_max, mvx_L1_min} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - /* {mvy_L1_max, mvy_L1_min} */ - rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); - mv_hi = (rdata32>>16)&0xffff; - if (mv_hi & 0x8000) - mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", - pic_number, mv_hi); -#endif - mv_lo = (rdata32>>0)&0xffff; - if (mv_lo & 0x8000) - mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS - hevc_print(hevc, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", - pic_number, mv_lo); -#endif - - rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); -#ifdef DEBUG_QOS - hevc_print(hevc, 0, - "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", - pic_number, rdata32); -#endif - /* reset all counts */ - WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); - } -} - -static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, - union param_u *rpm_param, - int decode_pic_begin) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - struct vdec_s *vdec = hw_to_vdec(hevc); -#endif - int i; - int lcu_x_num_div; - int lcu_y_num_div; - int Col_ref; - int dbg_skip_flag = 0; - - if (hevc->wait_buf == 0) { - hevc->sps_num_reorder_pics_0 = - rpm_param->p.sps_num_reorder_pics_0; - hevc->m_temporalId = rpm_param->p.m_temporalId; - hevc->m_nalUnitType = rpm_param->p.m_nalUnitType; - hevc->interlace_flag = - (rpm_param->p.profile_etc >> 2) & 0x1; - hevc->curr_pic_struct = - (rpm_param->p.sei_frame_field_info >> 3) & 0xf; - - if (interlace_enable == 0 || hevc->m_ins_flag) - hevc->interlace_flag = 0; - if (interlace_enable & 0x100) - hevc->interlace_flag = interlace_enable & 0x1; - if (hevc->interlace_flag == 0) - hevc->curr_pic_struct = 0; - /* if(hevc->m_nalUnitType == NAL_UNIT_EOS){ */ - /* - *hevc->m_pocRandomAccess = MAX_INT; - * //add to fix RAP_B_Bossen_1 - */ - /* } */ - hevc->misc_flag0 = rpm_param->p.misc_flag0; - if (rpm_param->p.first_slice_segment_in_pic_flag == 0) { - hevc->slice_segment_addr = - rpm_param->p.slice_segment_address; - if (!rpm_param->p.dependent_slice_segment_flag) - hevc->slice_addr = hevc->slice_segment_addr; - } else { - hevc->slice_segment_addr = 0; - hevc->slice_addr = 0; - } - - hevc->iPrevPOC = hevc->curr_POC; - hevc->slice_type = (rpm_param->p.slice_type == I_SLICE) ? 2 : - (rpm_param->p.slice_type == P_SLICE) ? 1 : - (rpm_param->p.slice_type == B_SLICE) ? 0 : 3; - /* hevc->curr_predFlag_L0=(hevc->slice_type==2) ? 0:1; */ - /* hevc->curr_predFlag_L1=(hevc->slice_type==0) ? 1:0; */ - hevc->TMVPFlag = rpm_param->p.slice_temporal_mvp_enable_flag; - hevc->isNextSliceSegment = - rpm_param->p.dependent_slice_segment_flag ? 1 : 0; - if (hevc->pic_w != rpm_param->p.pic_width_in_luma_samples - || hevc->pic_h != - rpm_param->p.pic_height_in_luma_samples) { - hevc_print(hevc, 0, - "Pic Width/Height Change (%d,%d)=>(%d,%d), interlace %d\n", - hevc->pic_w, hevc->pic_h, - rpm_param->p.pic_width_in_luma_samples, - rpm_param->p.pic_height_in_luma_samples, - hevc->interlace_flag); - - hevc->pic_w = rpm_param->p.pic_width_in_luma_samples; - hevc->pic_h = rpm_param->p.pic_height_in_luma_samples; - hevc->frame_width = hevc->pic_w; - hevc->frame_height = hevc->pic_h; -#ifdef LOSLESS_COMPRESS_MODE - if (/*re_config_pic_flag == 0 &&*/ - (get_double_write_mode(hevc) & 0x10) == 0) - init_decode_head_hw(hevc); -#endif - } - - if (is_oversize(hevc->pic_w, hevc->pic_h)) { - hevc_print(hevc, 0, "over size : %u x %u.\n", - hevc->pic_w, hevc->pic_h); - if ((!hevc->m_ins_flag) && - ((debug & - H265_NO_CHANG_DEBUG_FLAG_IN_CODE) == 0)) - debug |= (H265_DEBUG_DIS_LOC_ERROR_PROC | - H265_DEBUG_DIS_SYS_ERROR_PROC); - hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - return 3; - } - if (hevc->bit_depth_chroma > 10 || - hevc->bit_depth_luma > 10) { - hevc_print(hevc, 0, "unsupport bitdepth : %u,%u\n", - hevc->bit_depth_chroma, - hevc->bit_depth_luma); - if (!hevc->m_ins_flag) - debug |= (H265_DEBUG_DIS_LOC_ERROR_PROC | - H265_DEBUG_DIS_SYS_ERROR_PROC); - hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - return 4; - } - - /* it will cause divide 0 error */ - if (hevc->pic_w == 0 || hevc->pic_h == 0) { - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "Fatal Error, pic_w = %d, pic_h = %d\n", - hevc->pic_w, hevc->pic_h); - } - return 3; - } - pic_list_process(hevc); - - hevc->lcu_size = - 1 << (rpm_param->p.log2_min_coding_block_size_minus3 + - 3 + rpm_param-> - p.log2_diff_max_min_coding_block_size); - if (hevc->lcu_size == 0) { - hevc_print(hevc, 0, - "Error, lcu_size = 0 (%d,%d)\n", - rpm_param->p. - log2_min_coding_block_size_minus3, - rpm_param->p. - log2_diff_max_min_coding_block_size); - return 3; - } - hevc->lcu_size_log2 = log2i(hevc->lcu_size); - lcu_x_num_div = (hevc->pic_w / hevc->lcu_size); - lcu_y_num_div = (hevc->pic_h / hevc->lcu_size); - hevc->lcu_x_num = - ((hevc->pic_w % hevc->lcu_size) == - 0) ? lcu_x_num_div : lcu_x_num_div + 1; - hevc->lcu_y_num = - ((hevc->pic_h % hevc->lcu_size) == - 0) ? lcu_y_num_div : lcu_y_num_div + 1; - hevc->lcu_total = hevc->lcu_x_num * hevc->lcu_y_num; - - if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_IDR_N_LP) { - hevc->curr_POC = 0; - if ((hevc->m_temporalId - 1) == 0) - hevc->iPrevTid0POC = hevc->curr_POC; - } else { - int iMaxPOClsb = - 1 << (rpm_param->p. - log2_max_pic_order_cnt_lsb_minus4 + 4); - int iPrevPOClsb; - int iPrevPOCmsb; - int iPOCmsb; - int iPOClsb = rpm_param->p.POClsb; - - if (iMaxPOClsb == 0) { - hevc_print(hevc, 0, - "error iMaxPOClsb is 0\n"); - return 3; - } - - iPrevPOClsb = hevc->iPrevTid0POC % iMaxPOClsb; - iPrevPOCmsb = hevc->iPrevTid0POC - iPrevPOClsb; - - if ((iPOClsb < iPrevPOClsb) - && ((iPrevPOClsb - iPOClsb) >= - (iMaxPOClsb / 2))) - iPOCmsb = iPrevPOCmsb + iMaxPOClsb; - else if ((iPOClsb > iPrevPOClsb) - && ((iPOClsb - iPrevPOClsb) > - (iMaxPOClsb / 2))) - iPOCmsb = iPrevPOCmsb - iMaxPOClsb; - else - iPOCmsb = iPrevPOCmsb; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "iPrePOC%d iMaxPOClsb%d iPOCmsb%d iPOClsb%d\n", - hevc->iPrevTid0POC, iMaxPOClsb, iPOCmsb, - iPOClsb); - } - if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_BLANT - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_BLA_N_LP) { - /* For BLA picture types, POCmsb is set to 0. */ - iPOCmsb = 0; - } - hevc->curr_POC = (iPOCmsb + iPOClsb); - if ((hevc->m_temporalId - 1) == 0) - hevc->iPrevTid0POC = hevc->curr_POC; - else { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "m_temporalID is %d\n", - hevc->m_temporalId); - } - } - } - hevc->RefNum_L0 = - (rpm_param->p.num_ref_idx_l0_active > - MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : rpm_param->p. - num_ref_idx_l0_active; - hevc->RefNum_L1 = - (rpm_param->p.num_ref_idx_l1_active > - MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : rpm_param->p. - num_ref_idx_l1_active; - - /* if(curr_POC==0x10) dump_lmem(); */ - - /* skip RASL pictures after CRA/BLA pictures */ - if (hevc->m_pocRandomAccess == MAX_INT) {/* first picture */ - if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA || - hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_BLANT - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_BLA_N_LP) - hevc->m_pocRandomAccess = hevc->curr_POC; - else - hevc->m_pocRandomAccess = -MAX_INT; - } else if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_BLANT - || hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_BLA_N_LP) - hevc->m_pocRandomAccess = hevc->curr_POC; - else if ((hevc->curr_POC < hevc->m_pocRandomAccess) && - (nal_skip_policy >= 3) && - (hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_RASL_N || - hevc->m_nalUnitType == - NAL_UNIT_CODED_SLICE_TFD)) { /* skip */ - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "RASL picture with POC %d < %d ", - hevc->curr_POC, hevc->m_pocRandomAccess); - hevc_print(hevc, 0, - "RandomAccess point POC), skip it\n"); - } - return 1; - } - - WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) | 0x2); - hevc->skip_flag = 0; - /**/ - /* if((iPrevPOC != curr_POC)){ */ - if (rpm_param->p.slice_segment_address == 0) { - struct PIC_s *pic; - - hevc->new_pic = 1; -#ifdef MULTI_INSTANCE_SUPPORT - if (!hevc->m_ins_flag) -#endif - check_pic_decoded_error_pre(hevc, - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff); - /**/ if (use_cma == 0) { - if (hevc->pic_list_init_flag == 0) { - init_pic_list(hevc); - init_pic_list_hw(hevc); - init_buf_spec(hevc); - hevc->pic_list_init_flag = 3; - } - } - if (!hevc->m_ins_flag) { - if (hevc->cur_pic) - get_picture_qos_info(hevc); - } - hevc->first_pic_after_recover = 0; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) - dump_pic_list(hevc); - /* prev pic */ - hevc_pre_pic(hevc, pic); - /* - *update referenced of old pictures - *(cur_pic->referenced is 1 and not updated) - */ - apply_ref_pic_set(hevc, hevc->curr_POC, - rpm_param); - - if (hevc->mmu_enable) - recycle_mmu_bufs(hevc); - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->master) { - struct hevc_state_s *hevc_ba = - (struct hevc_state_s *) - vdec->master->private; - if (hevc_ba->cur_pic != NULL) { - hevc_ba->cur_pic->dv_enhance_exist = 1; - hevc_print(hevc, H265_DEBUG_DV, - "To decode el (poc %d) => set bl (poc %d) dv_enhance_exist flag\n", - hevc->curr_POC, hevc_ba->cur_pic->POC); - } - } - if (vdec->master == NULL && - vdec->slave == NULL) - set_aux_data(hevc, - hevc->cur_pic, 1, 0); /*suffix*/ - if (hevc->bypass_dvenl && !dolby_meta_with_el) - set_aux_data(hevc, - hevc->cur_pic, 0, 1); /*dv meta only*/ -#else - set_aux_data(hevc, hevc->cur_pic, 1, 0); -#endif - /* new pic */ - hevc->cur_pic = get_new_pic(hevc, rpm_param); - if (hevc->cur_pic == NULL) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - dump_pic_list(hevc); - hevc->wait_buf = 1; - return -1; - } -#ifdef MULTI_INSTANCE_SUPPORT - hevc->decoding_pic = hevc->cur_pic; - if (!hevc->m_ins_flag) - hevc->over_decode = 0; -#endif -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - hevc->cur_pic->dv_enhance_exist = 0; - if (vdec->slave) - hevc_print(hevc, H265_DEBUG_DV, - "Clear bl (poc %d) dv_enhance_exist flag\n", - hevc->curr_POC); - if (vdec->master == NULL && - vdec->slave == NULL) - set_aux_data(hevc, - hevc->cur_pic, 0, 0); /*prefix*/ - - if (hevc->bypass_dvenl && !dolby_meta_with_el) - set_aux_data(hevc, - hevc->cur_pic, 0, 2); /*pre sei only*/ -#else - set_aux_data(hevc, hevc->cur_pic, 0, 0); -#endif - if (get_dbg_flag(hevc) & H265_DEBUG_DISPLAY_CUR_FRAME) { - hevc->cur_pic->output_ready = 1; - hevc->cur_pic->stream_offset = - READ_VREG(HEVC_SHIFT_BYTE_COUNT); - prepare_display_buf(hevc, hevc->cur_pic); - hevc->wait_buf = 2; - return -1; - } - } else { - if (get_dbg_flag(hevc) & H265_DEBUG_HAS_AUX_IN_SLICE) { -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->master == NULL && - vdec->slave == NULL) { - set_aux_data(hevc, hevc->cur_pic, 1, 0); - set_aux_data(hevc, hevc->cur_pic, 0, 0); - } -#else - set_aux_data(hevc, hevc->cur_pic, 1, 0); - set_aux_data(hevc, hevc->cur_pic, 0, 0); -#endif - } - if (hevc->pic_list_init_flag != 3 - || hevc->cur_pic == NULL) { - /* make it dec from the first slice segment */ - return 3; - } - hevc->cur_pic->slice_idx++; - hevc->new_pic = 0; - } - } else { - if (hevc->wait_buf == 1) { - pic_list_process(hevc); - hevc->cur_pic = get_new_pic(hevc, rpm_param); - if (hevc->cur_pic == NULL) - return -1; - - if (!hevc->m_ins_flag) - hevc->over_decode = 0; - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - hevc->cur_pic->dv_enhance_exist = 0; - if (vdec->master == NULL && - vdec->slave == NULL) - set_aux_data(hevc, hevc->cur_pic, 0, 0); -#else - set_aux_data(hevc, hevc->cur_pic, 0, 0); -#endif - hevc->wait_buf = 0; - } else if (hevc->wait_buf == - 2) { - if (get_display_pic_num(hevc) > - 1) - return -1; - hevc->wait_buf = 0; - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) - dump_pic_list(hevc); - } - - if (hevc->new_pic) { -#if 1 - /*SUPPORT_10BIT*/ - int sao_mem_unit = - (hevc->lcu_size == 16 ? 9 : - hevc->lcu_size == - 32 ? 14 : 24) << 4; -#else - int sao_mem_unit = ((hevc->lcu_size / 8) * 2 + 4) << 4; -#endif - int pic_height_cu = - (hevc->pic_h + hevc->lcu_size - 1) / hevc->lcu_size; - int pic_width_cu = - (hevc->pic_w + hevc->lcu_size - 1) / hevc->lcu_size; - int sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu; - - /* int sao_abv_size = sao_mem_unit*pic_width_cu; */ - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "==>%s dec idx %d, struct %d interlace %d pic idx %d\n", - __func__, - hevc->decode_idx, - hevc->curr_pic_struct, - hevc->interlace_flag, - hevc->cur_pic->index); - } - if (dbg_skip_decode_index != 0 && - hevc->decode_idx == dbg_skip_decode_index) - dbg_skip_flag = 1; - - hevc->decode_idx++; - update_tile_info(hevc, pic_width_cu, pic_height_cu, - sao_mem_unit, rpm_param); - - config_title_hw(hevc, sao_vb_size, sao_mem_unit); - } - - if (hevc->iPrevPOC != hevc->curr_POC) { - hevc->new_tile = 1; - hevc->tile_x = 0; - hevc->tile_y = 0; - hevc->tile_y_x = 0; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "new_tile (new_pic) tile_x=%d, tile_y=%d\n", - hevc->tile_x, hevc->tile_y); - } - } else if (hevc->tile_enabled) { - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "slice_segment_address is %d\n", - rpm_param->p.slice_segment_address); - } - hevc->tile_y_x = - get_tile_index(hevc, rpm_param->p.slice_segment_address, - (hevc->pic_w + - hevc->lcu_size - - 1) / hevc->lcu_size); - if ((hevc->tile_y_x != (hevc->tile_x | (hevc->tile_y << 8))) - && (hevc->tile_y_x != -1)) { - hevc->new_tile = 1; - hevc->tile_x = hevc->tile_y_x & 0xff; - hevc->tile_y = (hevc->tile_y_x >> 8) & 0xff; - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "new_tile seg adr %d tile_x=%d, tile_y=%d\n", - rpm_param->p.slice_segment_address, - hevc->tile_x, hevc->tile_y); - } - } else - hevc->new_tile = 0; - } else - hevc->new_tile = 0; - - if ((hevc->tile_x > (MAX_TILE_COL_NUM - 1)) - || (hevc->tile_y > (MAX_TILE_ROW_NUM - 1))) - hevc->new_tile = 0; - - if (hevc->new_tile) { - hevc->tile_start_lcu_x = - hevc->m_tile[hevc->tile_y][hevc->tile_x].start_cu_x; - hevc->tile_start_lcu_y = - hevc->m_tile[hevc->tile_y][hevc->tile_x].start_cu_y; - hevc->tile_width_lcu = - hevc->m_tile[hevc->tile_y][hevc->tile_x].width; - hevc->tile_height_lcu = - hevc->m_tile[hevc->tile_y][hevc->tile_x].height; - } - - set_ref_pic_list(hevc, rpm_param); - - Col_ref = rpm_param->p.collocated_ref_idx; - - hevc->LDCFlag = 0; - if (rpm_param->p.slice_type != I_SLICE) { - hevc->LDCFlag = 1; - for (i = 0; (i < hevc->RefNum_L0) && hevc->LDCFlag; i++) { - if (hevc->cur_pic-> - m_aiRefPOCList0[hevc->cur_pic->slice_idx][i] > - hevc->curr_POC) - hevc->LDCFlag = 0; - } - if (rpm_param->p.slice_type == B_SLICE) { - for (i = 0; (i < hevc->RefNum_L1) - && hevc->LDCFlag; i++) { - if (hevc->cur_pic-> - m_aiRefPOCList1[hevc->cur_pic-> - slice_idx][i] > - hevc->curr_POC) - hevc->LDCFlag = 0; - } - } - } - - hevc->ColFromL0Flag = rpm_param->p.collocated_from_l0_flag; - - hevc->plevel = - rpm_param->p.log2_parallel_merge_level; - hevc->MaxNumMergeCand = 5 - rpm_param->p.five_minus_max_num_merge_cand; - - hevc->LongTerm_Curr = 0; /* to do ... */ - hevc->LongTerm_Col = 0; /* to do ... */ - - hevc->list_no = 0; - if (rpm_param->p.slice_type == B_SLICE) - hevc->list_no = 1 - hevc->ColFromL0Flag; - if (hevc->list_no == 0) { - if (Col_ref < hevc->RefNum_L0) { - hevc->Col_POC = - hevc->cur_pic->m_aiRefPOCList0[hevc->cur_pic-> - slice_idx][Col_ref]; - } else - hevc->Col_POC = INVALID_POC; - } else { - if (Col_ref < hevc->RefNum_L1) { - hevc->Col_POC = - hevc->cur_pic->m_aiRefPOCList1[hevc->cur_pic-> - slice_idx][Col_ref]; - } else - hevc->Col_POC = INVALID_POC; - } - - hevc->LongTerm_Ref = 0; /* to do ... */ - - if (hevc->slice_type != 2) { - /* if(hevc->i_only==1){ */ - /* return 0xf; */ - /* } */ - - if (hevc->Col_POC != INVALID_POC) { - hevc->col_pic = get_ref_pic_by_POC(hevc, hevc->Col_POC); - if (hevc->col_pic == NULL) { - hevc->cur_pic->error_mark = 1; - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "WRONG,fail to get the pic Col_POC\n"); - } - if (is_log_enable(hevc)) - add_log(hevc, - "WRONG,fail to get the pic Col_POC"); - } else if (hevc->col_pic->error_mark) { - hevc->cur_pic->error_mark = 1; - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "WRONG, Col_POC error_mark is 1\n"); - } - if (is_log_enable(hevc)) - add_log(hevc, - "WRONG, Col_POC error_mark is 1"); - } else { - if ((hevc->col_pic->width - != hevc->pic_w) || - (hevc->col_pic->height - != hevc->pic_h)) { - hevc_print(hevc, 0, - "Wrong reference pic (poc %d) width/height %d/%d\n", - hevc->col_pic->POC, - hevc->col_pic->width, - hevc->col_pic->height); - hevc->cur_pic->error_mark = 1; - } - - } - - if (hevc->cur_pic->error_mark - && ((hevc->ignore_bufmgr_error & 0x1) == 0)) { -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - /*count info*/ - vdec_count_info(gvs, hevc->cur_pic->error_mark, - hevc->cur_pic->stream_offset); -#endif - } - - if (is_skip_decoding(hevc, - hevc->cur_pic)) { - return 2; - } - } else - hevc->col_pic = hevc->cur_pic; - } /* */ - if (hevc->col_pic == NULL) - hevc->col_pic = hevc->cur_pic; -#ifdef BUFFER_MGR_ONLY - return 0xf; -#else - if ((decode_pic_begin > 0 && hevc->decode_idx <= decode_pic_begin) - || (dbg_skip_flag)) - return 0xf; -#endif - - config_mc_buffer(hevc, hevc->cur_pic); - - if (is_skip_decoding(hevc, - hevc->cur_pic)) { - if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, - "Discard this picture index %d\n", - hevc->cur_pic->index); -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - /*count info*/ - vdec_count_info(gvs, hevc->cur_pic->error_mark, - hevc->cur_pic->stream_offset); -#endif - return 2; - } -#ifdef MCRCC_ENABLE - config_mcrcc_axi_hw(hevc, hevc->cur_pic->slice_type); -#endif - config_mpred_hw(hevc); - - config_sao_hw(hevc, rpm_param); - - if ((hevc->slice_type != 2) && (hevc->i_only & 0x2)) - return 0xf; - - return 0; -} - - - -static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, - unsigned short bit_depth, unsigned int *mmu_index_adr) { - int cur_buf_idx = new_pic->index; - int bit_depth_10 = (bit_depth != 0x00); - int picture_size; - int cur_mmu_4k_number; - int ret, max_frame_num; - picture_size = compute_losless_comp_body_size(hevc, new_pic->width, - new_pic->height, !bit_depth_10); - cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12); - if (hevc->double_write_mode & 0x10) - return 0; - /*hevc_print(hevc, 0, - "alloc_mmu cur_idx : %d picture_size : %d mmu_4k_number : %d\r\n", - cur_buf_idx, picture_size, cur_mmu_4k_number);*/ - if (new_pic->scatter_alloc) { - decoder_mmu_box_free_idx(hevc->mmu_box, new_pic->index); - new_pic->scatter_alloc = 0; - } - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - max_frame_num = MAX_FRAME_8K_NUM; - else - max_frame_num = MAX_FRAME_4K_NUM; - if (cur_mmu_4k_number > max_frame_num) { - hevc_print(hevc, 0, "over max !! 0x%x width %d height %d\n", - cur_mmu_4k_number, - new_pic->width, - new_pic->height); - return -1; - } - ret = decoder_mmu_box_alloc_idx( - hevc->mmu_box, - cur_buf_idx, - cur_mmu_4k_number, - mmu_index_adr); - if (ret == 0) - new_pic->scatter_alloc = 1; - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s pic index %d page count(%d) ret =%d\n", - __func__, cur_buf_idx, - cur_mmu_4k_number, - ret); - return ret; -} - - -static void release_pic_mmu_buf(struct hevc_state_s *hevc, - struct PIC_s *pic) -{ - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s pic index %d scatter_alloc %d\n", - __func__, pic->index, - pic->scatter_alloc); - - if (hevc->mmu_enable - && ((hevc->double_write_mode & 0x10) == 0) - && pic->scatter_alloc) - decoder_mmu_box_free_idx(hevc->mmu_box, pic->index); - pic->scatter_alloc = 0; -} - -/* - ************************************************* - * - *h265 buffer management end - * - ************************************************** - */ -static struct hevc_state_s *gHevc; - -static void hevc_local_uninit(struct hevc_state_s *hevc) -{ - hevc->rpm_ptr = NULL; - hevc->lmem_ptr = NULL; - -#ifdef SWAP_HEVC_UCODE - if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - if (hevc->mc_cpu_addr != NULL) { - dma_free_coherent(amports_get_dma_device(), - hevc->swap_size, hevc->mc_cpu_addr, - hevc->mc_dma_handle); - hevc->mc_cpu_addr = NULL; - } - - } -#endif -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) - uninit_detrefill_buf(hevc); -#endif - if (hevc->aux_addr) { - dma_unmap_single(amports_get_dma_device(), - hevc->aux_phy_addr, - hevc->prefix_aux_size + hevc->suffix_aux_size, - DMA_FROM_DEVICE); - kfree(hevc->aux_addr); - hevc->aux_addr = NULL; - } - if (hevc->rpm_addr) { - dma_unmap_single(amports_get_dma_device(), - hevc->rpm_phy_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); - kfree(hevc->rpm_addr); - hevc->rpm_addr = NULL; - } - if (hevc->lmem_addr) { - dma_unmap_single(amports_get_dma_device(), - hevc->lmem_phy_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); - kfree(hevc->lmem_addr); - hevc->lmem_addr = NULL; - } - - if (hevc->mmu_enable && hevc->frame_mmu_map_addr) { - if (hevc->frame_mmu_map_phy_addr) - dma_free_coherent(amports_get_dma_device(), - get_frame_mmu_map_size(), hevc->frame_mmu_map_addr, - hevc->frame_mmu_map_phy_addr); - - hevc->frame_mmu_map_addr = NULL; - } - - kfree(gvs); - gvs = NULL; -} - -static int hevc_local_init(struct hevc_state_s *hevc) -{ - int ret = -1; - struct BuffInfo_s *cur_buf_info = NULL; - - memset(&hevc->param, 0, sizeof(union param_u)); - - cur_buf_info = &hevc->work_space_buf_store; - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - memcpy(cur_buf_info, &amvh265_workbuff_spec[2], /* 4k */ - sizeof(struct BuffInfo_s)); - else - memcpy(cur_buf_info, &amvh265_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - } else - memcpy(cur_buf_info, &amvh265_workbuff_spec[0], /* 1080p */ - sizeof(struct BuffInfo_s)); - - cur_buf_info->start_adr = hevc->buf_start; - init_buff_spec(hevc, cur_buf_info); - - hevc_init_stru(hevc, cur_buf_info); - - hevc->bit_depth_luma = 8; - hevc->bit_depth_chroma = 8; - hevc->video_signal_type = 0; - hevc->video_signal_type_debug = 0; - bit_depth_luma = hevc->bit_depth_luma; - bit_depth_chroma = hevc->bit_depth_chroma; - video_signal_type = hevc->video_signal_type; - - if ((get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) == 0) { - hevc->rpm_addr = kmalloc(RPM_BUF_SIZE, GFP_KERNEL); - if (hevc->rpm_addr == NULL) { - pr_err("%s: failed to alloc rpm buffer\n", __func__); - return -1; - } - - hevc->rpm_phy_addr = dma_map_single(amports_get_dma_device(), - hevc->rpm_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hevc->rpm_phy_addr)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(hevc->rpm_addr); - hevc->rpm_addr = NULL; - return -1; - } - - hevc->rpm_ptr = hevc->rpm_addr; - } - - if (prefix_aux_buf_size > 0 || - suffix_aux_buf_size > 0) { - u32 aux_buf_size; - - hevc->prefix_aux_size = AUX_BUF_ALIGN(prefix_aux_buf_size); - hevc->suffix_aux_size = AUX_BUF_ALIGN(suffix_aux_buf_size); - aux_buf_size = hevc->prefix_aux_size + hevc->suffix_aux_size; - hevc->aux_addr = kmalloc(aux_buf_size, GFP_KERNEL); - if (hevc->aux_addr == NULL) { - pr_err("%s: failed to alloc rpm buffer\n", __func__); - return -1; - } - - hevc->aux_phy_addr = dma_map_single(amports_get_dma_device(), - hevc->aux_addr, aux_buf_size, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hevc->aux_phy_addr)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(hevc->aux_addr); - hevc->aux_addr = NULL; - return -1; - } - } - - hevc->lmem_addr = kmalloc(LMEM_BUF_SIZE, GFP_KERNEL); - if (hevc->lmem_addr == NULL) { - pr_err("%s: failed to alloc lmem buffer\n", __func__); - return -1; - } - hevc->lmem_phy_addr = dma_map_single(amports_get_dma_device(), - hevc->lmem_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hevc->lmem_phy_addr)) { - pr_err("%s: failed to map lmem buffer\n", __func__); - kfree(hevc->lmem_addr); - hevc->lmem_addr = NULL; - return -1; - } - hevc->lmem_ptr = hevc->lmem_addr; - - if (hevc->mmu_enable) { - hevc->frame_mmu_map_addr = - dma_alloc_coherent(amports_get_dma_device(), - get_frame_mmu_map_size(), - &hevc->frame_mmu_map_phy_addr, GFP_KERNEL); - if (hevc->frame_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; - } - memset(hevc->frame_mmu_map_addr, 0, get_frame_mmu_map_size()); - } - ret = 0; - return ret; -} - -/* - ******************************************* - * Mailbox command - ******************************************* - */ -#define CMD_FINISHED 0 -#define CMD_ALLOC_VIEW 1 -#define CMD_FRAME_DISPLAY 3 -#define CMD_DEBUG 10 - - -#define DECODE_BUFFER_NUM_MAX 32 -#define DISPLAY_BUFFER_NUM 6 - -#define video_domain_addr(adr) (adr&0x7fffffff) -#define DECODER_WORK_SPACE_SIZE 0x800000 - -#define spec2canvas(x) \ - (((x)->uv_canvas_index << 16) | \ - ((x)->uv_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - - -static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) -{ - struct vdec_s *vdec = hw_to_vdec(hevc); - int canvas_w = ALIGN(pic->width, 64)/4; - int canvas_h = ALIGN(pic->height, 32)/4; - int blkmode = mem_map_mode; - - /*CANVAS_BLKMODE_64X32*/ -#ifdef SUPPORT_10BIT - if (pic->double_write_mode) { - canvas_w = pic->width / - get_double_write_ratio(hevc, pic->double_write_mode); - canvas_h = pic->height / - get_double_write_ratio(hevc, pic->double_write_mode); - - if (mem_map_mode == 0) - canvas_w = ALIGN(canvas_w, 32); - else - canvas_w = ALIGN(canvas_w, 64); - canvas_h = ALIGN(canvas_h, 32); - - if (vdec->parallel_dec == 1) { - if (pic->y_canvas_index == -1) - pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - if (pic->uv_canvas_index == -1) - pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - } else { - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; - } - - canvas_config_ex(pic->y_canvas_index, - pic->dw_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic->uv_canvas_index, pic->dw_u_v_adr, - canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); -#ifdef MULTI_INSTANCE_SUPPORT - pic->canvas_config[0].phy_addr = - pic->dw_y_adr; - pic->canvas_config[0].width = - canvas_w; - pic->canvas_config[0].height = - canvas_h; - pic->canvas_config[0].block_mode = - blkmode; - pic->canvas_config[0].endian = 7; - - pic->canvas_config[1].phy_addr = - pic->dw_u_v_adr; - pic->canvas_config[1].width = - canvas_w; - pic->canvas_config[1].height = - canvas_h; - pic->canvas_config[1].block_mode = - blkmode; - pic->canvas_config[1].endian = 7; -#endif - } else { - if (!hevc->mmu_enable) { - /* to change after 10bit VPU is ready ... */ - if (vdec->parallel_dec == 1) { - if (pic->y_canvas_index == -1) - pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - pic->uv_canvas_index = pic->y_canvas_index; - } else { - pic->y_canvas_index = 128 + pic->index; - pic->uv_canvas_index = 128 + pic->index; - } - - canvas_config_ex(pic->y_canvas_index, - pic->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr, - canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - } - } -#else - if (vdec->parallel_dec == 1) { - if (pic->y_canvas_index == -1) - pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - if (pic->uv_canvas_index == -1) - pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - } else { - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; - } - - - canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr, - canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); -#endif -} - -static int init_buf_spec(struct hevc_state_s *hevc) -{ - int pic_width = hevc->pic_w; - int pic_height = hevc->pic_h; - - /* hevc_print(hevc, 0, - *"%s1: %d %d\n", __func__, hevc->pic_w, hevc->pic_h); - */ - hevc_print(hevc, 0, - "%s2 %d %d\n", __func__, pic_width, pic_height); - /* pic_width = hevc->pic_w; */ - /* pic_height = hevc->pic_h; */ - - if (hevc->frame_width == 0 || hevc->frame_height == 0) { - hevc->frame_width = pic_width; - hevc->frame_height = pic_height; - - } - - return 0; -} - -static int parse_sei(struct hevc_state_s *hevc, - struct PIC_s *pic, char *sei_buf, uint32_t size) -{ - char *p = sei_buf; - char *p_sei; - uint16_t header; - uint8_t nal_unit_type; - uint8_t payload_type, payload_size; - int i, j; - - if (size < 2) - return 0; - header = *p++; - header <<= 8; - header += *p++; - nal_unit_type = header >> 9; - if ((nal_unit_type != NAL_UNIT_SEI) - && (nal_unit_type != NAL_UNIT_SEI_SUFFIX)) - return 0; - while (p+2 <= sei_buf+size) { - payload_type = *p++; - payload_size = *p++; - if (p+payload_size <= sei_buf+size) { - switch (payload_type) { - case SEI_PicTiming: - p_sei = p; - hevc->curr_pic_struct = (*p_sei >> 4)&0x0f; - pic->pic_struct = hevc->curr_pic_struct; - if (get_dbg_flag(hevc) & - H265_DEBUG_PIC_STRUCT) { - hevc_print(hevc, 0, - "parse result pic_struct = %d\n", - hevc->curr_pic_struct); - } - break; - case SEI_UserDataITU_T_T35: - p_sei = p; - if (p_sei[0] == 0xB5 - && p_sei[1] == 0x00 - && p_sei[2] == 0x3C - && p_sei[3] == 0x00 - && p_sei[4] == 0x01 - && p_sei[5] == 0x04) - hevc->sei_present_flag |= SEI_HDR10PLUS_MASK; - - break; - case SEI_MasteringDisplayColorVolume: - /*hevc_print(hevc, 0, - "sei type: primary display color volume %d, size %d\n", - payload_type, - payload_size);*/ - /* master_display_colour */ - p_sei = p; - for (i = 0; i < 3; i++) { - for (j = 0; j < 2; j++) { - hevc->primaries[i][j] - = (*p_sei<<8) - | *(p_sei+1); - p_sei += 2; - } - } - for (i = 0; i < 2; i++) { - hevc->white_point[i] - = (*p_sei<<8) - | *(p_sei+1); - p_sei += 2; - } - for (i = 0; i < 2; i++) { - hevc->luminance[i] - = (*p_sei<<24) - | (*(p_sei+1)<<16) - | (*(p_sei+2)<<8) - | *(p_sei+3); - p_sei += 4; - } - hevc->sei_present_flag |= - SEI_MASTER_DISPLAY_COLOR_MASK; - /*for (i = 0; i < 3; i++) - for (j = 0; j < 2; j++) - hevc_print(hevc, 0, - "\tprimaries[%1d][%1d] = %04x\n", - i, j, - hevc->primaries[i][j]); - hevc_print(hevc, 0, - "\twhite_point = (%04x, %04x)\n", - hevc->white_point[0], - hevc->white_point[1]); - hevc_print(hevc, 0, - "\tmax,min luminance = %08x, %08x\n", - hevc->luminance[0], - hevc->luminance[1]);*/ - break; - case SEI_ContentLightLevel: - if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "sei type: max content light level %d, size %d\n", - payload_type, payload_size); - /* content_light_level */ - p_sei = p; - hevc->content_light_level[0] - = (*p_sei<<8) | *(p_sei+1); - p_sei += 2; - hevc->content_light_level[1] - = (*p_sei<<8) | *(p_sei+1); - p_sei += 2; - hevc->sei_present_flag |= - SEI_CONTENT_LIGHT_LEVEL_MASK; - if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "\tmax cll = %04x, max_pa_cll = %04x\n", - hevc->content_light_level[0], - hevc->content_light_level[1]); - break; - default: - break; - } - } - p += payload_size; - } - return 0; -} - -static unsigned calc_ar(unsigned idc, unsigned sar_w, unsigned sar_h, - unsigned w, unsigned h) -{ - unsigned ar; - - if (idc == 255) { - ar = div_u64(256ULL * sar_h * h, - sar_w * w); - } else { - switch (idc) { - case 1: - ar = 0x100 * h / w; - break; - case 2: - ar = 0x100 * h * 11 / (w * 12); - break; - case 3: - ar = 0x100 * h * 11 / (w * 10); - break; - case 4: - ar = 0x100 * h * 11 / (w * 16); - break; - case 5: - ar = 0x100 * h * 33 / (w * 40); - break; - case 6: - ar = 0x100 * h * 11 / (w * 24); - break; - case 7: - ar = 0x100 * h * 11 / (w * 20); - break; - case 8: - ar = 0x100 * h * 11 / (w * 32); - break; - case 9: - ar = 0x100 * h * 33 / (w * 80); - break; - case 10: - ar = 0x100 * h * 11 / (w * 18); - break; - case 11: - ar = 0x100 * h * 11 / (w * 15); - break; - case 12: - ar = 0x100 * h * 33 / (w * 64); - break; - case 13: - ar = 0x100 * h * 99 / (w * 160); - break; - case 14: - ar = 0x100 * h * 3 / (w * 4); - break; - case 15: - ar = 0x100 * h * 2 / (w * 3); - break; - case 16: - ar = 0x100 * h * 1 / (w * 2); - break; - default: - ar = h * 0x100 / w; - break; - } - } - - return ar; -} - -static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, - struct PIC_s *pic) -{ - unsigned int ar; - int i, j; - char *p; - unsigned size = 0; - unsigned type = 0; - struct vframe_master_display_colour_s *vf_dp - = &vf->prop.master_display_colour; - - vf->width = pic->width / - get_double_write_ratio(hevc, pic->double_write_mode); - vf->height = pic->height / - get_double_write_ratio(hevc, pic->double_write_mode); - - vf->duration = hevc->frame_dur; - vf->duration_pulldown = 0; - vf->flag = 0; - - ar = min_t(u32, hevc->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - - - if (((pic->aspect_ratio_idc == 255) && - pic->sar_width && - pic->sar_height) || - ((pic->aspect_ratio_idc != 255) && - (pic->width))) { - ar = min_t(u32, - calc_ar(pic->aspect_ratio_idc, - pic->sar_width, - pic->sar_height, - pic->width, - pic->height), - DISP_RATIO_ASPECT_RATIO_MAX); - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - } - hevc->ratio_control = vf->ratio_control; - if (pic->aux_data_buf - && pic->aux_data_size) { - /* parser sei */ - p = pic->aux_data_buf; - while (p < pic->aux_data_buf - + pic->aux_data_size - 8) { - size = *p++; - size = (size << 8) | *p++; - size = (size << 8) | *p++; - size = (size << 8) | *p++; - type = *p++; - type = (type << 8) | *p++; - type = (type << 8) | *p++; - type = (type << 8) | *p++; - if (type == 0x02000000) { - /* hevc_print(hevc, 0, - "sei(%d)\n", size); */ - parse_sei(hevc, pic, p, size); - } - p += size; - } - } - if (hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) { - vf->signal_type = pic->video_signal_type; - if (hevc->sei_present_flag & SEI_HDR10PLUS_MASK) { - u32 data; - data = vf->signal_type; - data = data & 0xFFFF00FF; - data = data | (0x30<<8); - vf->signal_type = data; - } - } - else - vf->signal_type = 0; - hevc->video_signal_type_debug = vf->signal_type; - - /* master_display_colour */ - if (hevc->sei_present_flag & SEI_MASTER_DISPLAY_COLOR_MASK) { - for (i = 0; i < 3; i++) - for (j = 0; j < 2; j++) - vf_dp->primaries[i][j] = hevc->primaries[i][j]; - for (i = 0; i < 2; i++) { - vf_dp->white_point[i] = hevc->white_point[i]; - vf_dp->luminance[i] - = hevc->luminance[i]; - } - vf_dp->present_flag = 1; - } else - vf_dp->present_flag = 0; - - /* content_light_level */ - if (hevc->sei_present_flag & SEI_CONTENT_LIGHT_LEVEL_MASK) { - vf_dp->content_light_level.max_content - = hevc->content_light_level[0]; - vf_dp->content_light_level.max_pic_average - = hevc->content_light_level[1]; - vf_dp->content_light_level.present_flag = 1; - } else - vf_dp->content_light_level.present_flag = 0; -} - -static int vh265_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; -#ifdef MULTI_INSTANCE_SUPPORT - struct vdec_s *vdec = op_arg; - struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; -#else - struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; -#endif - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&hevc->newframe_q); - states->buf_avail_num = kfifo_len(&hevc->display_q); - - if (step == 2) - states->buf_avail_num = 0; - spin_unlock_irqrestore(&lock, flags); - return 0; -} - -static struct vframe_s *vh265_vf_peek(void *op_arg) -{ - struct vframe_s *vf[2] = {0, 0}; -#ifdef MULTI_INSTANCE_SUPPORT - struct vdec_s *vdec = op_arg; - struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; -#else - struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; -#endif - - if (step == 2) - return NULL; - - if (force_disp_pic_index & 0x100) { - if (force_disp_pic_index & 0x200) - return NULL; - return &hevc->vframe_dummy; - } - - - if (kfifo_out_peek(&hevc->display_q, (void *)&vf, 2)) { - if (vf[1]) { - vf[0]->next_vf_pts_valid = true; - vf[0]->next_vf_pts = vf[1]->pts; - } else - vf[0]->next_vf_pts_valid = false; - return vf[0]; - } - - return NULL; -} - -static struct vframe_s *vh265_vf_get(void *op_arg) -{ - struct vframe_s *vf; -#ifdef MULTI_INSTANCE_SUPPORT - struct vdec_s *vdec = op_arg; - struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; -#else - struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; -#endif - - if (step == 2) - return NULL; - else if (step == 1) - step = 2; - -#if 0 - if (force_disp_pic_index & 0x100) { - int buffer_index = force_disp_pic_index & 0xff; - struct PIC_s *pic = NULL; - if (buffer_index >= 0 - && buffer_index < MAX_REF_PIC_NUM) - pic = hevc->m_PIC[buffer_index]; - if (pic == NULL) - return NULL; - if (force_disp_pic_index & 0x200) - return NULL; - - vf = &hevc->vframe_dummy; - if (get_double_write_mode(hevc)) { - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; - if (hevc->m_ins_flag) { - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - pic->canvas_config[0]; - vf->canvas0_config[1] = - pic->canvas_config[1]; - - vf->canvas1_config[0] = - pic->canvas_config[0]; - vf->canvas1_config[1] = - pic->canvas_config[1]; - } else { - vf->canvas0Addr = vf->canvas1Addr - = spec2canvas(pic); - } - } else { - vf->canvas0Addr = vf->canvas1Addr = 0; - vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; - if (hevc->mmu_enable) - vf->type |= VIDTYPE_SCATTER; - } - vf->compWidth = pic->width; - vf->compHeight = pic->height; - update_vf_memhandle(hevc, vf, pic); - switch (hevc->bit_depth_luma) { - case 9: - vf->bitdepth = BITDEPTH_Y9 | BITDEPTH_U9 | BITDEPTH_V9; - break; - case 10: - vf->bitdepth = BITDEPTH_Y10 | BITDEPTH_U10 - | BITDEPTH_V10; - break; - default: - vf->bitdepth = BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - break; - } - if ((vf->type & VIDTYPE_COMPRESS) == 0) - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - if (hevc->mem_saving_mode == 1) - vf->bitdepth |= BITDEPTH_SAVING_MODE; - vf->duration_pulldown = 0; - vf->pts = 0; - vf->pts_us64 = 0; - set_frame_info(hevc, vf); - - vf->width = pic->width / - get_double_write_ratio(hevc, pic->double_write_mode); - vf->height = pic->height / - get_double_write_ratio(hevc, pic->double_write_mode); - - force_disp_pic_index |= 0x200; - return vf; - } -#endif - - if (kfifo_get(&hevc->display_q, &vf)) { - struct vframe_s *next_vf; - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s(vf 0x%p type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n", - __func__, vf, vf->type, vf->index, - get_pic_poc(hevc, vf->index & 0xff), - get_pic_poc(hevc, (vf->index >> 8) & 0xff), - vf->pts, vf->pts_us64, - vf->duration); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (get_dbg_flag(hevc) & H265_DEBUG_DV) { - struct PIC_s *pic = hevc->m_PIC[vf->index & 0xff]; - if (pic->aux_data_buf && pic->aux_data_size > 0) { - int i; - struct PIC_s *pic = - hevc->m_PIC[vf->index & 0xff]; - hevc_print(hevc, 0, - "pic 0x%p aux size %d:\n", - pic, pic->aux_data_size); - for (i = 0; i < pic->aux_data_size; i++) { - hevc_print_cont(hevc, 0, - "%02x ", pic->aux_data_buf[i]); - if (((i + 1) & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - } - hevc_print_cont(hevc, 0, "\n"); - } - } -#endif - hevc->show_frame_num++; - hevc->vf_get_count++; - - if (kfifo_peek(&hevc->display_q, &next_vf)) { - vf->next_vf_pts_valid = true; - vf->next_vf_pts = next_vf->pts; - } else - vf->next_vf_pts_valid = false; - - return vf; - } - - return NULL; -} - -static void vh265_vf_put(struct vframe_s *vf, void *op_arg) -{ - unsigned long flags; -#ifdef MULTI_INSTANCE_SUPPORT - struct vdec_s *vdec = op_arg; - struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; -#else - struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; -#endif - unsigned char index_top = vf->index & 0xff; - unsigned char index_bot = (vf->index >> 8) & 0xff; - if (vf == (&hevc->vframe_dummy)) - return; - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s(type %d index 0x%x)\n", - __func__, vf->type, vf->index); - hevc->vf_put_count++; - kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf); - spin_lock_irqsave(&lock, flags); - - if (index_top != 0xff - && index_top < MAX_REF_PIC_NUM - && hevc->m_PIC[index_top]) { - if (hevc->m_PIC[index_top]->vf_ref > 0) { - hevc->m_PIC[index_top]->vf_ref--; - - if (hevc->m_PIC[index_top]->vf_ref == 0) { - hevc->m_PIC[index_top]->output_ready = 0; - - if (hevc->wait_buf != 0) - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - } - } - } - - if (index_bot != 0xff - && index_bot < MAX_REF_PIC_NUM - && hevc->m_PIC[index_bot]) { - if (hevc->m_PIC[index_bot]->vf_ref > 0) { - hevc->m_PIC[index_bot]->vf_ref--; - - if (hevc->m_PIC[index_bot]->vf_ref == 0) { - hevc->m_PIC[index_bot]->output_ready = 0; - if (hevc->wait_buf != 0) - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - } - } - } - spin_unlock_irqrestore(&lock, flags); -} - -static int vh265_event_cb(int type, void *data, void *op_arg) -{ - unsigned long flags; -#ifdef MULTI_INSTANCE_SUPPORT - struct vdec_s *vdec = op_arg; - struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; -#else - struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; -#endif - if (type & VFRAME_EVENT_RECEIVER_RESET) { -#if 0 - amhevc_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vh265_vf_prov); -#endif - spin_lock_irqsave(&hevc->lock, flags); - vh265_local_init(); - vh265_prot_init(); - spin_unlock_irqrestore(&hevc->lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vh265_vf_prov); -#endif - amhevc_start(); -#endif - } else if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) { - struct provider_aux_req_s *req = - (struct provider_aux_req_s *)data; - unsigned char index; - - spin_lock_irqsave(&lock, flags); - index = req->vf->index & 0xff; - req->aux_buf = NULL; - req->aux_size = 0; - if (req->bot_flag) - index = (req->vf->index >> 8) & 0xff; - if (index != 0xff - && index < MAX_REF_PIC_NUM - && hevc->m_PIC[index]) { - req->aux_buf = hevc->m_PIC[index]->aux_data_buf; - req->aux_size = hevc->m_PIC[index]->aux_data_size; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (hevc->bypass_dvenl && !dolby_meta_with_el) - req->dv_enhance_exist = false; - else - req->dv_enhance_exist = - hevc->m_PIC[index]->dv_enhance_exist; - hevc_print(hevc, H265_DEBUG_DV, - "query dv_enhance_exist for pic (vf 0x%p, poc %d index %d) flag => %d, aux sizd 0x%x\n", - req->vf, - hevc->m_PIC[index]->POC, index, - req->dv_enhance_exist, req->aux_size); -#else - req->dv_enhance_exist = 0; -#endif - } - spin_unlock_irqrestore(&lock, flags); - - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s(type 0x%x vf index 0x%x)=>size 0x%x\n", - __func__, type, index, req->aux_size); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - } else if (type & VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL) { - if ((force_bypass_dvenl & 0x80000000) == 0) { - hevc_print(hevc, 0, - "%s: VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL\n", - __func__); - hevc->bypass_dvenl_enable = 1; - } - -#endif - } - return 0; -} - -#ifdef HEVC_PIC_STRUCT_SUPPORT -static int process_pending_vframe(struct hevc_state_s *hevc, - struct PIC_s *pair_pic, unsigned char pair_frame_top_flag) -{ - struct vframe_s *vf; - - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s: pair_pic index 0x%x %s\n", - __func__, pair_pic->index, - pair_frame_top_flag ? - "top" : "bot"); - - if (kfifo_len(&hevc->pending_q) > 1) { - /* do not pending more than 1 frame */ - if (kfifo_get(&hevc->pending_q, &vf) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s warning(1), vf=>display_q: (index 0x%x)\n", - __func__, vf->index); - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - } - - if (kfifo_peek(&hevc->pending_q, &vf)) { - if (pair_pic == NULL || pair_pic->vf_ref <= 0) { - /* - *if pair_pic is recycled (pair_pic->vf_ref <= 0), - *do not use it - */ - if (kfifo_get(&hevc->pending_q, &vf) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s warning(2), vf=>display_q: (index 0x%x)\n", - __func__, vf->index); - if (vf) { - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - } - } else if ((!pair_frame_top_flag) && - (((vf->index >> 8) & 0xff) == 0xff)) { - if (kfifo_get(&hevc->pending_q, &vf) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - if (vf) { - vf->type = VIDTYPE_PROGRESSIVE - | VIDTYPE_VIU_NV21; - vf->index &= 0xff; - vf->index |= (pair_pic->index << 8); - vf->canvas1Addr = spec2canvas(pair_pic); - pair_pic->vf_ref++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hevc->vf_pre_count++; - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s vf => display_q: (index 0x%x)\n", - __func__, vf->index); - } - } else if (pair_frame_top_flag && - ((vf->index & 0xff) == 0xff)) { - if (kfifo_get(&hevc->pending_q, &vf) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - if (vf) { - vf->type = VIDTYPE_PROGRESSIVE - | VIDTYPE_VIU_NV21; - vf->index &= 0xff00; - vf->index |= pair_pic->index; - vf->canvas0Addr = spec2canvas(pair_pic); - pair_pic->vf_ref++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hevc->vf_pre_count++; - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s vf => display_q: (index 0x%x)\n", - __func__, vf->index); - } - } - } - return 0; -} -#endif -static void update_vf_memhandle(struct hevc_state_s *hevc, - struct vframe_s *vf, struct PIC_s *pic) -{ - if (pic->index < 0) { - vf->mem_handle = NULL; - vf->mem_head_handle = NULL; - } else if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = - decoder_mmu_box_get_mem_handle( - hevc->mmu_box, pic->index); - vf->mem_head_handle = - decoder_bmmu_box_get_mem_handle( - hevc->bmmu_box, VF_BUFFER_IDX(pic->BUF_index)); - } else { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - hevc->bmmu_box, VF_BUFFER_IDX(pic->BUF_index)); - vf->mem_head_handle = NULL; - /*vf->mem_head_handle = - decoder_bmmu_box_get_mem_handle( - hevc->bmmu_box, VF_BUFFER_IDX(BUF_index));*/ - } - return; -} - -static void fill_frame_info(struct hevc_state_s *hevc, - struct PIC_s *pic, unsigned int framesize, unsigned int pts) -{ - struct vframe_qos_s *vframe_qos = &hevc->vframe_qos; - if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR) - vframe_qos->type = 4; - else if (pic->slice_type == I_SLICE) - vframe_qos->type = 1; - else if (pic->slice_type == P_SLICE) - vframe_qos->type = 2; - else if (pic->slice_type == B_SLICE) - vframe_qos->type = 3; -/* -#define SHOW_QOS_INFO -*/ - vframe_qos->size = framesize; - vframe_qos->pts = pts; -#ifdef SHOW_QOS_INFO - hevc_print(hevc, 0, "slice:%d, poc:%d\n", pic->slice_type, pic->POC); -#endif - - - vframe_qos->max_mv = pic->max_mv; - vframe_qos->avg_mv = pic->avg_mv; - vframe_qos->min_mv = pic->min_mv; -#ifdef SHOW_QOS_INFO - hevc_print(hevc, 0, "mv: max:%d, avg:%d, min:%d\n", - vframe_qos->max_mv, - vframe_qos->avg_mv, - vframe_qos->min_mv); -#endif - - vframe_qos->max_qp = pic->max_qp; - vframe_qos->avg_qp = pic->avg_qp; - vframe_qos->min_qp = pic->min_qp; -#ifdef SHOW_QOS_INFO - hevc_print(hevc, 0, "qp: max:%d, avg:%d, min:%d\n", - vframe_qos->max_qp, - vframe_qos->avg_qp, - vframe_qos->min_qp); -#endif - - vframe_qos->max_skip = pic->max_skip; - vframe_qos->avg_skip = pic->avg_skip; - vframe_qos->min_skip = pic->min_skip; -#ifdef SHOW_QOS_INFO - hevc_print(hevc, 0, "skip: max:%d, avg:%d, min:%d\n", - vframe_qos->max_skip, - vframe_qos->avg_skip, - vframe_qos->min_skip); -#endif - - vframe_qos->num++; - - if (hevc->frameinfo_enable) - vdec_fill_frame_info(vframe_qos, 1); -} - -static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - struct vdec_s *vdec = hw_to_vdec(hevc); -#endif - struct vframe_s *vf = NULL; - int stream_offset = pic->stream_offset; - unsigned short slice_type = pic->slice_type; - u32 frame_size; - - if (force_disp_pic_index & 0x100) { - /*recycle directly*/ - pic->output_ready = 0; - return -1; - } - if (kfifo_get(&hevc->newframe_q, &vf) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - display_frame_count[hevc->index]++; - if (vf) { - /*hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: pic index 0x%x\n", - __func__, pic->index);*/ - -#ifdef MULTI_INSTANCE_SUPPORT - if (vdec_frame_based(hw_to_vdec(hevc))) { - vf->pts = pic->pts; - vf->pts_us64 = pic->pts64; - } - /* if (pts_lookup_offset(PTS_TYPE_VIDEO, - stream_offset, &vf->pts, 0) != 0) { */ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec->master == NULL) { -#else - else { -#endif -#endif - hevc_print(hevc, H265_DEBUG_OUT_PTS, - "call pts_lookup_offset_us64(0x%x)\n", - stream_offset); - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, - &frame_size, 0, - &vf->pts_us64) != 0) { -#ifdef DEBUG_PTS - hevc->pts_missed++; -#endif - vf->pts = 0; - vf->pts_us64 = 0; - } -#ifdef DEBUG_PTS - else - hevc->pts_hit++; -#endif -#ifdef MULTI_INSTANCE_SUPPORT -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - } else { - vf->pts = 0; - vf->pts_us64 = 0; - } -#else - } -#endif -#endif - if (pts_unstable && (hevc->frame_dur > 0)) - hevc->pts_mode = PTS_NONE_REF_USE_DURATION; - - fill_frame_info(hevc, pic, frame_size, vf->pts); - - if ((hevc->pts_mode == PTS_NORMAL) && (vf->pts != 0) - && hevc->get_frame_dur) { - int pts_diff = (int)vf->pts - hevc->last_lookup_pts; - - if (pts_diff < 0) { - hevc->pts_mode_switching_count++; - hevc->pts_mode_recovery_count = 0; - - if (hevc->pts_mode_switching_count >= - PTS_MODE_SWITCHING_THRESHOLD) { - hevc->pts_mode = - PTS_NONE_REF_USE_DURATION; - hevc_print(hevc, 0, - "HEVC: switch to n_d mode.\n"); - } - - } else { - int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD; - - hevc->pts_mode_recovery_count++; - if (hevc->pts_mode_recovery_count > p) { - hevc->pts_mode_switching_count = 0; - hevc->pts_mode_recovery_count = 0; - } - } - } - - if (vf->pts != 0) - hevc->last_lookup_pts = vf->pts; - - if ((hevc->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != 2)) - vf->pts = hevc->last_pts + DUR2PTS(hevc->frame_dur); - hevc->last_pts = vf->pts; - - if (vf->pts_us64 != 0) - hevc->last_lookup_pts_us64 = vf->pts_us64; - - if ((hevc->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != 2)) { - vf->pts_us64 = - hevc->last_pts_us64 + - (DUR2PTS(hevc->frame_dur) * 100 / 9); - } - hevc->last_pts_us64 = vf->pts_us64; - if ((get_dbg_flag(hevc) & H265_DEBUG_OUT_PTS) != 0) { - hevc_print(hevc, 0, - "H265 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n", - vf->pts, vf->pts_us64); - } - - /* - *vf->index: - *(1) vf->type is VIDTYPE_PROGRESSIVE - * and vf->canvas0Addr != vf->canvas1Addr, - * vf->index[7:0] is the index of top pic - * vf->index[15:8] is the index of bot pic - *(2) other cases, - * only vf->index[7:0] is used - * vf->index[15:8] == 0xff - */ - vf->index = 0xff00 | pic->index; -#if 1 -/*SUPPORT_10BIT*/ - if (pic->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { - - if (hevc->mmu_enable) { - vf->compBodyAddr = 0; - vf->compHeadAddr = pic->header_adr; - } else { - vf->compBodyAddr = pic->mc_y_adr; /*body adr*/ - vf->compHeadAddr = pic->mc_y_adr + - pic->losless_comp_body_size; - vf->mem_head_handle = NULL; - } - - /*head adr*/ - vf->canvas0Addr = vf->canvas1Addr = 0; - } - if (pic->double_write_mode) { - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if ((pic->double_write_mode == 3) && - (!(IS_8K_SIZE(pic->width, pic->height)))) { - vf->type |= VIDTYPE_COMPRESS; - if (hevc->mmu_enable) - vf->type |= VIDTYPE_SCATTER; - } -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag && - (get_dbg_flag(hevc) - & H265_CFG_CANVAS_IN_DECODE) == 0) { - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - pic->canvas_config[0]; - vf->canvas0_config[1] = - pic->canvas_config[1]; - - vf->canvas1_config[0] = - pic->canvas_config[0]; - vf->canvas1_config[1] = - pic->canvas_config[1]; - - } else -#endif - vf->canvas0Addr = vf->canvas1Addr - = spec2canvas(pic); - } else { - vf->canvas0Addr = vf->canvas1Addr = 0; - vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; - if (hevc->mmu_enable) - vf->type |= VIDTYPE_SCATTER; - } - vf->compWidth = pic->width; - vf->compHeight = pic->height; - update_vf_memhandle(hevc, vf, pic); - switch (pic->bit_depth_luma) { - case 9: - vf->bitdepth = BITDEPTH_Y9; - break; - case 10: - vf->bitdepth = BITDEPTH_Y10; - break; - default: - vf->bitdepth = BITDEPTH_Y8; - break; - } - switch (pic->bit_depth_chroma) { - case 9: - vf->bitdepth |= (BITDEPTH_U9 | BITDEPTH_V9); - break; - case 10: - vf->bitdepth |= (BITDEPTH_U10 | BITDEPTH_V10); - break; - default: - vf->bitdepth |= (BITDEPTH_U8 | BITDEPTH_V8); - break; - } - if ((vf->type & VIDTYPE_COMPRESS) == 0) - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - if (pic->mem_saving_mode == 1) - vf->bitdepth |= BITDEPTH_SAVING_MODE; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - vf->canvas0Addr = vf->canvas1Addr = spec2canvas(pic); -#endif - set_frame_info(hevc, vf, pic); - /* if((vf->width!=pic->width)||(vf->height!=pic->height)) */ - /* hevc_print(hevc, 0, - "aaa: %d/%d, %d/%d\n", - vf->width,vf->height, pic->width, pic->height); */ - vf->width = pic->width; - vf->height = pic->height; - - if (force_w_h != 0) { - vf->width = (force_w_h >> 16) & 0xffff; - vf->height = force_w_h & 0xffff; - } - if (force_fps & 0x100) { - u32 rate = force_fps & 0xff; - - if (rate) - vf->duration = 96000/rate; - else - vf->duration = 0; - } - if (force_fps & 0x200) { - vf->pts = 0; - vf->pts_us64 = 0; - } - /* - * !!! to do ... - * need move below code to get_new_pic(), - * hevc->xxx can only be used by current decoded pic - */ - if (pic->conformance_window_flag && - (get_dbg_flag(hevc) & - H265_DEBUG_IGNORE_CONFORMANCE_WINDOW) == 0) { - unsigned int SubWidthC, SubHeightC; - - switch (pic->chroma_format_idc) { - case 1: - SubWidthC = 2; - SubHeightC = 2; - break; - case 2: - SubWidthC = 2; - SubHeightC = 1; - break; - default: - SubWidthC = 1; - SubHeightC = 1; - break; - } - vf->width -= SubWidthC * - (pic->conf_win_left_offset + - pic->conf_win_right_offset); - vf->height -= SubHeightC * - (pic->conf_win_top_offset + - pic->conf_win_bottom_offset); - - vf->compWidth -= SubWidthC * - (pic->conf_win_left_offset + - pic->conf_win_right_offset); - vf->compHeight -= SubHeightC * - (pic->conf_win_top_offset + - pic->conf_win_bottom_offset); - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "conformance_window %d, %d, %d, %d, %d => cropped width %d, height %d com_w %d com_h %d\n", - pic->chroma_format_idc, - pic->conf_win_left_offset, - pic->conf_win_right_offset, - pic->conf_win_top_offset, - pic->conf_win_bottom_offset, - vf->width, vf->height, vf->compWidth, vf->compHeight); - } - - vf->width = vf->width / - get_double_write_ratio(hevc, pic->double_write_mode); - vf->height = vf->height / - get_double_write_ratio(hevc, pic->double_write_mode); -#ifdef HEVC_PIC_STRUCT_SUPPORT - if (pic->pic_struct == 3 || pic->pic_struct == 4) { - struct vframe_s *vf2; - - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "pic_struct = %d index 0x%x\n", - pic->pic_struct, - pic->index); - - if (kfifo_get(&hevc->newframe_q, &vf2) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - pic->vf_ref = 2; - vf->duration = vf->duration>>1; - memcpy(vf2, vf, sizeof(struct vframe_s)); - - if (pic->pic_struct == 3) { - vf->type = VIDTYPE_INTERLACE_TOP - | VIDTYPE_VIU_NV21; - vf2->type = VIDTYPE_INTERLACE_BOTTOM - | VIDTYPE_VIU_NV21; - } else { - vf->type = VIDTYPE_INTERLACE_BOTTOM - | VIDTYPE_VIU_NV21; - vf2->type = VIDTYPE_INTERLACE_TOP - | VIDTYPE_VIU_NV21; - } - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf2); - ATRACE_COUNTER(MODULE_NAME, vf2->pts); - } else if (pic->pic_struct == 5 - || pic->pic_struct == 6) { - struct vframe_s *vf2, *vf3; - - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "pic_struct = %d index 0x%x\n", - pic->pic_struct, - pic->index); - - if (kfifo_get(&hevc->newframe_q, &vf2) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - if (kfifo_get(&hevc->newframe_q, &vf3) == 0) { - hevc_print(hevc, 0, - "fatal error, no available buffer slot."); - return -1; - } - pic->vf_ref = 3; - vf->duration = vf->duration/3; - memcpy(vf2, vf, sizeof(struct vframe_s)); - memcpy(vf3, vf, sizeof(struct vframe_s)); - - if (pic->pic_struct == 5) { - vf->type = VIDTYPE_INTERLACE_TOP - | VIDTYPE_VIU_NV21; - vf2->type = VIDTYPE_INTERLACE_BOTTOM - | VIDTYPE_VIU_NV21; - vf3->type = VIDTYPE_INTERLACE_TOP - | VIDTYPE_VIU_NV21; - } else { - vf->type = VIDTYPE_INTERLACE_BOTTOM - | VIDTYPE_VIU_NV21; - vf2->type = VIDTYPE_INTERLACE_TOP - | VIDTYPE_VIU_NV21; - vf3->type = VIDTYPE_INTERLACE_BOTTOM - | VIDTYPE_VIU_NV21; - } - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf2); - ATRACE_COUNTER(MODULE_NAME, vf2->pts); - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf3); - ATRACE_COUNTER(MODULE_NAME, vf3->pts); - - } else if (pic->pic_struct == 9 - || pic->pic_struct == 10) { - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "pic_struct = %d index 0x%x\n", - pic->pic_struct, - pic->index); - - pic->vf_ref = 1; - /* process previous pending vf*/ - process_pending_vframe(hevc, - pic, (pic->pic_struct == 9)); - - /* process current vf */ - kfifo_put(&hevc->pending_q, - (const struct vframe_s *)vf); - vf->height <<= 1; - if (pic->pic_struct == 9) { - vf->type = VIDTYPE_INTERLACE_TOP - | VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; - process_pending_vframe(hevc, - hevc->pre_bot_pic, 0); - } else { - vf->type = VIDTYPE_INTERLACE_BOTTOM | - VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; - vf->index = (pic->index << 8) | 0xff; - process_pending_vframe(hevc, - hevc->pre_top_pic, 1); - } - - /**/ - if (pic->pic_struct == 9) - hevc->pre_top_pic = pic; - else - hevc->pre_bot_pic = pic; - - } else if (pic->pic_struct == 11 - || pic->pic_struct == 12) { - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "pic_struct = %d index 0x%x\n", - pic->pic_struct, - pic->index); - pic->vf_ref = 1; - /* process previous pending vf*/ - process_pending_vframe(hevc, pic, - (pic->pic_struct == 11)); - - /* put current into pending q */ - vf->height <<= 1; - if (pic->pic_struct == 11) - vf->type = VIDTYPE_INTERLACE_TOP | - VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; - else { - vf->type = VIDTYPE_INTERLACE_BOTTOM | - VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; - vf->index = (pic->index << 8) | 0xff; - } - kfifo_put(&hevc->pending_q, - (const struct vframe_s *)vf); - - /**/ - if (pic->pic_struct == 11) - hevc->pre_top_pic = pic; - else - hevc->pre_bot_pic = pic; - - } else { - pic->vf_ref = 1; - - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "pic_struct = %d index 0x%x\n", - pic->pic_struct, - pic->index); - - switch (pic->pic_struct) { - case 7: - vf->duration <<= 1; - break; - case 8: - vf->duration = vf->duration * 3; - break; - case 1: - vf->height <<= 1; - vf->type = VIDTYPE_INTERLACE_TOP | - VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; - process_pending_vframe(hevc, pic, 1); - hevc->pre_top_pic = pic; - break; - case 2: - vf->height <<= 1; - vf->type = VIDTYPE_INTERLACE_BOTTOM - | VIDTYPE_VIU_NV21 - | VIDTYPE_VIU_FIELD; - process_pending_vframe(hevc, pic, 0); - hevc->pre_bot_pic = pic; - break; - } - hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - } -#else - vf->type_original = vf->type; - pic->vf_ref = 1; - hevc->vf_pre_count++; - decoder_do_frame_check(hw_to_vdec(hevc), vf); - kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) - hevc_print(hevc, 0, - "%s(type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n", - __func__, vf->type, vf->index, - get_pic_poc(hevc, vf->index & 0xff), - get_pic_poc(hevc, (vf->index >> 8) & 0xff), - vf->pts, vf->pts_us64, - vf->duration); -#endif -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - /*count info*/ - vdec_count_info(gvs, 0, stream_offset); -#endif - hw_to_vdec(hevc)->vdec_fps_detec(hw_to_vdec(hevc)->id); - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - - return 0; -} - -static void process_nal_sei(struct hevc_state_s *hevc, - int payload_type, int payload_size) -{ - unsigned short data; - - if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "\tsei message: payload_type = 0x%02x, payload_size = 0x%02x\n", - payload_type, payload_size); - - if (payload_type == 137) { - int i, j; - /* MASTERING_DISPLAY_COLOUR_VOLUME */ - if (payload_size >= 24) { - if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "\tsei MASTERING_DISPLAY_COLOUR_VOLUME available\n"); - for (i = 0; i < 3; i++) { - for (j = 0; j < 2; j++) { - data = - (READ_HREG(HEVC_SHIFTED_DATA) >> 16); - hevc->primaries[i][j] = data; - WRITE_HREG(HEVC_SHIFT_COMMAND, - (1<<7)|16); - if (get_dbg_flag(hevc) & - H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "\t\tprimaries[%1d][%1d] = %04x\n", - i, j, hevc->primaries[i][j]); - } - } - for (i = 0; i < 2; i++) { - data = (READ_HREG(HEVC_SHIFTED_DATA) >> 16); - hevc->white_point[i] = data; - WRITE_HREG(HEVC_SHIFT_COMMAND, (1<<7)|16); - if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "\t\twhite_point[%1d] = %04x\n", - i, hevc->white_point[i]); - } - for (i = 0; i < 2; i++) { - data = (READ_HREG(HEVC_SHIFTED_DATA) >> 16); - hevc->luminance[i] = data << 16; - WRITE_HREG(HEVC_SHIFT_COMMAND, - (1<<7)|16); - data = - (READ_HREG(HEVC_SHIFTED_DATA) >> 16); - hevc->luminance[i] |= data; - WRITE_HREG(HEVC_SHIFT_COMMAND, - (1<<7)|16); - if (get_dbg_flag(hevc) & - H265_DEBUG_PRINT_SEI) - hevc_print(hevc, 0, - "\t\tluminance[%1d] = %08x\n", - i, hevc->luminance[i]); - } - hevc->sei_present_flag |= SEI_MASTER_DISPLAY_COLOR_MASK; - } - payload_size -= 24; - while (payload_size > 0) { - data = (READ_HREG(HEVC_SHIFTED_DATA) >> 24); - payload_size--; - WRITE_HREG(HEVC_SHIFT_COMMAND, (1<<7)|8); - hevc_print(hevc, 0, "\t\tskip byte %02x\n", data); - } - } -} - -static int hevc_recover(struct hevc_state_s *hevc) -{ - int ret = -1; - u32 rem; - u64 shift_byte_count64; - unsigned int hevc_shift_byte_count; - unsigned int hevc_stream_start_addr; - unsigned int hevc_stream_end_addr; - unsigned int hevc_stream_rd_ptr; - unsigned int hevc_stream_wr_ptr; - unsigned int hevc_stream_control; - unsigned int hevc_stream_fifo_ctl; - unsigned int hevc_stream_buf_size; - - mutex_lock(&vh265_mutex); -#if 0 - for (i = 0; i < (hevc->debug_ptr_size / 2); i += 4) { - int ii; - - for (ii = 0; ii < 4; ii++) - hevc_print(hevc, 0, - "%04x ", hevc->debug_ptr[i + 3 - ii]); - if (((i + ii) & 0xf) == 0) - hevc_print(hevc, 0, "\n"); - } -#endif -#define ES_VID_MAN_RD_PTR (1<<0) - if (!hevc->init_flag) { - hevc_print(hevc, 0, "h265 has stopped, recover return!\n"); - mutex_unlock(&vh265_mutex); - return ret; - } - amhevc_stop(); - msleep(20); - ret = 0; - /* reset */ - WRITE_PARSER_REG(PARSER_VIDEO_RP, READ_VREG(HEVC_STREAM_RD_PTR)); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); - - hevc_stream_start_addr = READ_VREG(HEVC_STREAM_START_ADDR); - hevc_stream_end_addr = READ_VREG(HEVC_STREAM_END_ADDR); - hevc_stream_rd_ptr = READ_VREG(HEVC_STREAM_RD_PTR); - hevc_stream_wr_ptr = READ_VREG(HEVC_STREAM_WR_PTR); - hevc_stream_control = READ_VREG(HEVC_STREAM_CONTROL); - hevc_stream_fifo_ctl = READ_VREG(HEVC_STREAM_FIFO_CTL); - hevc_stream_buf_size = hevc_stream_end_addr - hevc_stream_start_addr; - - /* HEVC streaming buffer will reset and restart - * from current hevc_stream_rd_ptr position - */ - /* calculate HEVC_SHIFT_BYTE_COUNT value with the new position. */ - hevc_shift_byte_count = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - if ((hevc->shift_byte_count_lo & (1 << 31)) - && ((hevc_shift_byte_count & (1 << 31)) == 0)) - hevc->shift_byte_count_hi++; - - hevc->shift_byte_count_lo = hevc_shift_byte_count; - shift_byte_count64 = ((u64)(hevc->shift_byte_count_hi) << 32) | - hevc->shift_byte_count_lo; - div_u64_rem(shift_byte_count64, hevc_stream_buf_size, &rem); - shift_byte_count64 -= rem; - shift_byte_count64 += hevc_stream_rd_ptr - hevc_stream_start_addr; - - if (rem > (hevc_stream_rd_ptr - hevc_stream_start_addr)) - shift_byte_count64 += hevc_stream_buf_size; - - hevc->shift_byte_count_lo = (u32)shift_byte_count64; - hevc->shift_byte_count_hi = (u32)(shift_byte_count64 >> 32); - - WRITE_VREG(DOS_SW_RESET3, - /* (1<<2)| */ - (1 << 3) | (1 << 4) | (1 << 8) | - (1 << 11) | (1 << 12) | (1 << 14) - | (1 << 15) | (1 << 17) | (1 << 18) | (1 << 19)); - WRITE_VREG(DOS_SW_RESET3, 0); - - WRITE_VREG(HEVC_STREAM_START_ADDR, hevc_stream_start_addr); - WRITE_VREG(HEVC_STREAM_END_ADDR, hevc_stream_end_addr); - WRITE_VREG(HEVC_STREAM_RD_PTR, hevc_stream_rd_ptr); - WRITE_VREG(HEVC_STREAM_WR_PTR, hevc_stream_wr_ptr); - WRITE_VREG(HEVC_STREAM_CONTROL, hevc_stream_control); - WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, hevc->shift_byte_count_lo); - WRITE_VREG(HEVC_STREAM_FIFO_CTL, hevc_stream_fifo_ctl); - - hevc_config_work_space_hw(hevc); - decoder_hw_reset(); - - hevc->have_vps = 0; - hevc->have_sps = 0; - hevc->have_pps = 0; - - hevc->have_valid_start_slice = 0; - - if (get_double_write_mode(hevc) & 0x10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, - 0x1 << 31 /*/Enable NV21 reference read mode for MC*/ - ); - - WRITE_VREG(HEVC_WAIT_FLAG, 1); - /* clear mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); - /* enable mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1); - /* disable PSCALE for hardware sharing */ - WRITE_VREG(HEVC_PSCALE_CTRL, 0); - - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); - - WRITE_VREG(DEBUG_REG1, 0x0); - - if ((error_handle_policy & 1) == 0) { - if ((error_handle_policy & 4) == 0) { - /* ucode auto mode, and do not check vps/sps/pps/idr */ - WRITE_VREG(NAL_SEARCH_CTL, - 0xc); - } else { - WRITE_VREG(NAL_SEARCH_CTL, 0x1);/* manual parser NAL */ - } - } else { - WRITE_VREG(NAL_SEARCH_CTL, 0x1);/* manual parser NAL */ - } - - if (get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE) - WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x10000); - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) - | ((parser_sei_enable & 0x7) << 17)); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | - ((parser_dolby_vision_enable & 0x1) << 20)); -#endif - config_decode_mode(hevc); - WRITE_VREG(DECODE_STOP_POS, udebug_flag); - - /* if (amhevc_loadmc(vh265_mc) < 0) { */ - /* amhevc_disable(); */ - /* return -EBUSY; */ - /* } */ -#if 0 - for (i = 0; i < (hevc->debug_ptr_size / 2); i += 4) { - int ii; - - for (ii = 0; ii < 4; ii++) { - /* hevc->debug_ptr[i+3-ii]=ttt++; */ - hevc_print(hevc, 0, - "%04x ", hevc->debug_ptr[i + 3 - ii]); - } - if (((i + ii) & 0xf) == 0) - hevc_print(hevc, 0, "\n"); - } -#endif - init_pic_list_hw(hevc); - - hevc_print(hevc, 0, "%s HEVC_SHIFT_BYTE_COUNT=0x%x\n", __func__, - READ_VREG(HEVC_SHIFT_BYTE_COUNT)); - -#ifdef SWAP_HEVC_UCODE - if (!tee_enabled() && hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); - /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ - } -#endif - amhevc_start(); - - /* skip, search next start code */ - WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2)); - hevc->skip_flag = 1; -#ifdef ERROR_HANDLE_DEBUG - if (dbg_nal_skip_count & 0x20000) { - dbg_nal_skip_count &= ~0x20000; - mutex_unlock(&vh265_mutex); - return ret; - } -#endif - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); -#ifdef MULTI_INSTANCE_SUPPORT - if (!hevc->m_ins_flag) -#endif - hevc->first_pic_after_recover = 1; - mutex_unlock(&vh265_mutex); - return ret; -} - -static void dump_aux_buf(struct hevc_state_s *hevc) -{ - int i; - unsigned short *aux_adr = - (unsigned short *) - hevc->aux_addr; - unsigned int aux_size = - (READ_VREG(HEVC_AUX_DATA_SIZE) - >> 16) << 4; - - if (hevc->prefix_aux_size > 0) { - hevc_print(hevc, 0, - "prefix aux: (size %d)\n", - aux_size); - for (i = 0; i < - (aux_size >> 1); i++) { - hevc_print_cont(hevc, 0, - "%04x ", - *(aux_adr + i)); - if (((i + 1) & 0xf) - == 0) - hevc_print_cont(hevc, - 0, "\n"); - } - } - if (hevc->suffix_aux_size > 0) { - aux_adr = (unsigned short *) - (hevc->aux_addr + - hevc->prefix_aux_size); - aux_size = - (READ_VREG(HEVC_AUX_DATA_SIZE) & 0xffff) - << 4; - hevc_print(hevc, 0, - "suffix aux: (size %d)\n", - aux_size); - for (i = 0; i < - (aux_size >> 1); i++) { - hevc_print_cont(hevc, 0, - "%04x ", *(aux_adr + i)); - if (((i + 1) & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - } - } -} - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -static void dolby_get_meta(struct hevc_state_s *hevc) -{ - struct vdec_s *vdec = hw_to_vdec(hevc); - - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR_MORE) - dump_aux_buf(hevc); - if (vdec->dolby_meta_with_el || vdec->slave) { - set_aux_data(hevc, - hevc->cur_pic, 0, 0); - } else if (vdec->master) { - struct hevc_state_s *hevc_ba = - (struct hevc_state_s *) - vdec->master->private; - /*do not use hevc_ba*/ - set_aux_data(hevc, - hevc_ba->cur_pic, - 0, 1); - set_aux_data(hevc, - hevc->cur_pic, 0, 2); - } -} -#endif - -static void read_decode_info(struct hevc_state_s *hevc) -{ - uint32_t decode_info = - READ_HREG(HEVC_DECODE_INFO); - hevc->start_decoding_flag |= - (decode_info & 0xff); - hevc->rps_set_id = (decode_info >> 8) & 0xff; -} - -static irqreturn_t vh265_isr_thread_fn(int irq, void *data) -{ - struct hevc_state_s *hevc = (struct hevc_state_s *) data; - unsigned int dec_status = hevc->dec_status; - int i, ret; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - struct vdec_s *vdec = hw_to_vdec(hevc); -#endif - if (hevc->eos) - return IRQ_HANDLED; - if ( -#ifdef MULTI_INSTANCE_SUPPORT - (!hevc->m_ins_flag) && -#endif - hevc->error_flag == 1) { - if ((error_handle_policy & 0x10) == 0) { - if (hevc->cur_pic) { - int current_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff; - if (current_lcu_idx < - ((hevc->lcu_x_num*hevc->lcu_y_num)-1)) - hevc->cur_pic->error_mark = 1; - - } - } - if ((error_handle_policy & 1) == 0) { - hevc->error_skip_nal_count = 1; - /* manual search nal, skip error_skip_nal_count - * of nal and trigger the HEVC_NAL_SEARCH_DONE irq - */ - WRITE_VREG(NAL_SEARCH_CTL, - (error_skip_nal_count << 4) | 0x1); - } else { - hevc->error_skip_nal_count = error_skip_nal_count; - WRITE_VREG(NAL_SEARCH_CTL, 0x1);/* manual parser NAL */ - } - if ((get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE) -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - || vdec->master - || vdec->slave -#endif - ) { - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | 0x10000); - } - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) - | ((parser_sei_enable & 0x7) << 17)); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | - ((parser_dolby_vision_enable & 0x1) << 20)); -#endif - config_decode_mode(hevc); - /* search new nal */ - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); - - /* hevc_print(hevc, 0, - *"%s: error handle\n", __func__); - */ - hevc->error_flag = 2; - return IRQ_HANDLED; - } else if ( -#ifdef MULTI_INSTANCE_SUPPORT - (!hevc->m_ins_flag) && -#endif - hevc->error_flag == 3) { - hevc_print(hevc, 0, "error_flag=3, hevc_recover\n"); - hevc_recover(hevc); - hevc->error_flag = 0; - - if ((error_handle_policy & 0x10) == 0) { - if (hevc->cur_pic) { - int current_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff; - if (current_lcu_idx < - ((hevc->lcu_x_num*hevc->lcu_y_num)-1)) - hevc->cur_pic->error_mark = 1; - - } - } - if ((error_handle_policy & 1) == 0) { - /* need skip some data when - * error_flag of 3 is triggered, - */ - /* to avoid hevc_recover() being called - * for many times at the same bitstream position - */ - hevc->error_skip_nal_count = 1; - /* manual search nal, skip error_skip_nal_count - * of nal and trigger the HEVC_NAL_SEARCH_DONE irq - */ - WRITE_VREG(NAL_SEARCH_CTL, - (error_skip_nal_count << 4) | 0x1); - } - - if ((error_handle_policy & 0x2) == 0) { - hevc->have_vps = 1; - hevc->have_sps = 1; - hevc->have_pps = 1; - } - return IRQ_HANDLED; - } - if (!hevc->m_ins_flag) { - i = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - if ((hevc->shift_byte_count_lo & (1 << 31)) - && ((i & (1 << 31)) == 0)) - hevc->shift_byte_count_hi++; - hevc->shift_byte_count_lo = i; - } -#ifdef MULTI_INSTANCE_SUPPORT - mutex_lock(&hevc->chunks_mutex); - if ((dec_status == HEVC_DECPIC_DATA_DONE || - dec_status == HEVC_FIND_NEXT_PIC_NAL || - dec_status == HEVC_FIND_NEXT_DVEL_NAL) - && (hevc->chunk)) { - hevc->cur_pic->pts = hevc->chunk->pts; - hevc->cur_pic->pts64 = hevc->chunk->pts64; - } - mutex_unlock(&hevc->chunks_mutex); - - if (dec_status == HEVC_DECODE_BUFEMPTY || - dec_status == HEVC_DECODE_BUFEMPTY2) { - if (hevc->m_ins_flag) { - read_decode_info(hevc); - if (vdec_frame_based(hw_to_vdec(hevc))) { - hevc->empty_flag = 1; - goto pic_done; - } else { - if ( -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - vdec->master || - vdec->slave || -#endif - (data_resend_policy & 0x1)) { - hevc->dec_result = DEC_RESULT_AGAIN; - amhevc_stop(); - restore_decode_state(hevc); - } else - hevc->dec_result = DEC_RESULT_GET_DATA; - } - reset_process_time(hevc); - vdec_schedule_work(&hevc->work); - } - return IRQ_HANDLED; - } else if ((dec_status == HEVC_SEARCH_BUFEMPTY) || - (dec_status == HEVC_NAL_DECODE_DONE) - ) { - if (hevc->m_ins_flag) { - read_decode_info(hevc); - if (vdec_frame_based(hw_to_vdec(hevc))) { - /*hevc->dec_result = DEC_RESULT_GET_DATA;*/ - hevc->empty_flag = 1; - goto pic_done; - } else { - hevc->dec_result = DEC_RESULT_AGAIN; - amhevc_stop(); - restore_decode_state(hevc); - } - - reset_process_time(hevc); - vdec_schedule_work(&hevc->work); - } - - return IRQ_HANDLED; - } else if (dec_status == HEVC_DECPIC_DATA_DONE) { - if (hevc->m_ins_flag) { - struct PIC_s *pic; - struct PIC_s *pic_display; - int decoded_poc; -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - if (hevc->detbuf_adr_virt && hevc->delrefill_check - && READ_VREG(HEVC_SAO_DBG_MODE0)) - hevc->delrefill_check = 2; - } -#endif - hevc->empty_flag = 0; -pic_done: - if (input_frame_based(hw_to_vdec(hevc)) && - frmbase_cont_bitlevel != 0 && - (hevc->decode_size > READ_VREG(HEVC_SHIFT_BYTE_COUNT)) && - (hevc->decode_size - (READ_VREG(HEVC_SHIFT_BYTE_COUNT)) - > frmbase_cont_bitlevel)) { - /*handle the case: multi pictures in one packet*/ - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s has more data index= %d, size=0x%x shiftcnt=0x%x)\n", - __func__, - hevc->decode_idx, hevc->decode_size, - READ_VREG(HEVC_SHIFT_BYTE_COUNT)); - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - start_process_time(hevc); - return IRQ_HANDLED; - } - - read_decode_info(hevc); - get_picture_qos_info(hevc); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - hevc->start_parser_type = 0; - hevc->switch_dvlayer_flag = 0; -#endif - hevc->decoded_poc = hevc->curr_POC; - hevc->decoding_pic = NULL; - hevc->dec_result = DEC_RESULT_DONE; -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) - if (hevc->delrefill_check != 2) -#endif - - amhevc_stop(); - - reset_process_time(hevc); - - if (hevc->vf_pre_count == 0) { - decoded_poc = hevc->curr_POC; - pic = get_pic_by_POC(hevc, decoded_poc); - if (pic && (pic->POC != INVALID_POC)) { - /*PB skip control */ - if (pic->error_mark == 0 - && hevc->PB_skip_mode == 1) { - /* start decoding after - * first I - */ - hevc->ignore_bufmgr_error |= 0x1; - } - if (hevc->ignore_bufmgr_error & 1) { - if (hevc->PB_skip_count_after_decoding > 0) { - hevc->PB_skip_count_after_decoding--; - } else { - /* start displaying */ - hevc->ignore_bufmgr_error |= 0x2; - } - } - if (hevc->mmu_enable - && ((hevc->double_write_mode & 0x10) == 0)) { - if (!hevc->m_ins_flag) { - hevc->used_4k_num = - READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; - - if ((!is_skip_decoding(hevc, pic)) && - (hevc->used_4k_num >= 0) && - (hevc->cur_pic->scatter_alloc - == 1)) { - hevc_print(hevc, - H265_DEBUG_BUFMGR_MORE, - "%s pic index %d scatter_alloc %d page_start %d\n", - "decoder_mmu_box_free_idx_tail", - hevc->cur_pic->index, - hevc->cur_pic->scatter_alloc, - hevc->used_4k_num); - decoder_mmu_box_free_idx_tail( - hevc->mmu_box, - hevc->cur_pic->index, - hevc->used_4k_num); - hevc->cur_pic->scatter_alloc - = 2; - } - hevc->used_4k_num = -1; - } - } - - pic->output_mark = 1; - pic->recon_mark = 1; - } - - pic_display = output_pic(hevc, 1); - - if (pic_display) { - if ((pic_display->error_mark && - ((hevc->ignore_bufmgr_error & - 0x2) == 0)) - || (get_dbg_flag(hevc) & - H265_DEBUG_DISPLAY_CUR_FRAME) - || (get_dbg_flag(hevc) & - H265_DEBUG_NO_DISPLAY)) { - pic_display->output_ready = 0; - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "[BM] Display: POC %d, ", - pic_display->POC); - hevc_print_cont(hevc, 0, - "decoding index %d ==> ", - pic_display-> - decode_idx); - hevc_print_cont(hevc, 0, - "Debug or err,recycle it\n"); - } - } else { - if (pic_display-> - slice_type != 2) { - pic_display->output_ready = 0; - } else { - prepare_display_buf - (hevc, - pic_display); - hevc->first_pic_flag = 1; - } - } - } - } - - vdec_schedule_work(&hevc->work); - } - - return IRQ_HANDLED; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - } else if (dec_status == HEVC_FIND_NEXT_PIC_NAL || - dec_status == HEVC_FIND_NEXT_DVEL_NAL) { - if (hevc->m_ins_flag) { - unsigned char next_parser_type = - READ_HREG(CUR_NAL_UNIT_TYPE) & 0xff; - read_decode_info(hevc); - - if (vdec->slave && - dec_status == HEVC_FIND_NEXT_DVEL_NAL) { - /*cur is base, found enhance*/ - struct hevc_state_s *hevc_el = - (struct hevc_state_s *) - vdec->slave->private; - hevc->switch_dvlayer_flag = 1; - hevc->no_switch_dvlayer_count = 0; - hevc_el->start_parser_type = - next_parser_type; - hevc_print(hevc, H265_DEBUG_DV, - "switch (poc %d) to el\n", - hevc->cur_pic ? - hevc->cur_pic->POC : - INVALID_POC); - } else if (vdec->master && - dec_status == HEVC_FIND_NEXT_PIC_NAL) { - /*cur is enhance, found base*/ - struct hevc_state_s *hevc_ba = - (struct hevc_state_s *) - vdec->master->private; - hevc->switch_dvlayer_flag = 1; - hevc->no_switch_dvlayer_count = 0; - hevc_ba->start_parser_type = - next_parser_type; - hevc_print(hevc, H265_DEBUG_DV, - "switch (poc %d) to bl\n", - hevc->cur_pic ? - hevc->cur_pic->POC : - INVALID_POC); - } else { - hevc->switch_dvlayer_flag = 0; - hevc->start_parser_type = - next_parser_type; - hevc->no_switch_dvlayer_count++; - hevc_print(hevc, H265_DEBUG_DV, - "%s: no_switch_dvlayer_count = %d\n", - vdec->master ? "el" : "bl", - hevc->no_switch_dvlayer_count); - if (vdec->slave && - dolby_el_flush_th != 0 && - hevc->no_switch_dvlayer_count > - dolby_el_flush_th) { - struct hevc_state_s *hevc_el = - (struct hevc_state_s *) - vdec->slave->private; - struct PIC_s *el_pic; - check_pic_decoded_error(hevc_el, - hevc_el->pic_decoded_lcu_idx); - el_pic = get_pic_by_POC(hevc_el, - hevc_el->curr_POC); - hevc_el->curr_POC = INVALID_POC; - hevc_el->m_pocRandomAccess = MAX_INT; - flush_output(hevc_el, el_pic); - hevc_el->decoded_poc = INVALID_POC; /* - already call flush_output*/ - hevc_el->decoding_pic = NULL; - hevc->no_switch_dvlayer_count = 0; - if (get_dbg_flag(hevc) & H265_DEBUG_DV) - hevc_print(hevc, 0, - "no el anymore, flush_output el\n"); - } - } - hevc->decoded_poc = hevc->curr_POC; - hevc->decoding_pic = NULL; - hevc->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - reset_process_time(hevc); - if (aux_data_is_avaible(hevc)) - dolby_get_meta(hevc); - - vdec_schedule_work(&hevc->work); - } - - return IRQ_HANDLED; -#endif - } - -#endif - - if (dec_status == HEVC_SEI_DAT) { - if (!hevc->m_ins_flag) { - int payload_type = - READ_HREG(CUR_NAL_UNIT_TYPE) & 0xffff; - int payload_size = - (READ_HREG(CUR_NAL_UNIT_TYPE) >> 16) & 0xffff; - process_nal_sei(hevc, - payload_type, payload_size); - } - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_SEI_DAT_DONE); - } else if (dec_status == HEVC_NAL_SEARCH_DONE) { - int naltype = READ_HREG(CUR_NAL_UNIT_TYPE); - int parse_type = HEVC_DISCARD_NAL; - - hevc->error_watchdog_count = 0; - hevc->error_skip_nal_wt_cnt = 0; -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) - reset_process_time(hevc); -#endif - if (slice_parse_begin > 0 && - get_dbg_flag(hevc) & H265_DEBUG_DISCARD_NAL) { - hevc_print(hevc, 0, - "nal type %d, discard %d\n", naltype, - slice_parse_begin); - if (naltype <= NAL_UNIT_CODED_SLICE_CRA) - slice_parse_begin--; - } - if (naltype == NAL_UNIT_EOS) { - struct PIC_s *pic; - - hevc_print(hevc, 0, "get NAL_UNIT_EOS, flush output\n"); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if ((vdec->master || vdec->slave) && - aux_data_is_avaible(hevc)) { - if (hevc->decoding_pic) - dolby_get_meta(hevc); - } -#endif - check_pic_decoded_error(hevc, - hevc->pic_decoded_lcu_idx); - pic = get_pic_by_POC(hevc, hevc->curr_POC); - hevc->curr_POC = INVALID_POC; - /* add to fix RAP_B_Bossen_1 */ - hevc->m_pocRandomAccess = MAX_INT; - flush_output(hevc, pic); - clear_poc_flag(hevc); - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_DISCARD_NAL); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) { - hevc->decoded_poc = INVALID_POC; /* - already call flush_output*/ - hevc->decoding_pic = NULL; - hevc->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - - vdec_schedule_work(&hevc->work); - } -#endif - return IRQ_HANDLED; - } - - if ( -#ifdef MULTI_INSTANCE_SUPPORT - (!hevc->m_ins_flag) && -#endif - hevc->error_skip_nal_count > 0) { - hevc_print(hevc, 0, - "nal type %d, discard %d\n", naltype, - hevc->error_skip_nal_count); - hevc->error_skip_nal_count--; - if (hevc->error_skip_nal_count == 0) { - hevc_recover(hevc); - hevc->error_flag = 0; - if ((error_handle_policy & 0x2) == 0) { - hevc->have_vps = 1; - hevc->have_sps = 1; - hevc->have_pps = 1; - } - return IRQ_HANDLED; - } - } else if (naltype == NAL_UNIT_VPS) { - parse_type = HEVC_NAL_UNIT_VPS; - hevc->have_vps = 1; -#ifdef ERROR_HANDLE_DEBUG - if (dbg_nal_skip_flag & 1) - parse_type = HEVC_DISCARD_NAL; -#endif - } else if (hevc->have_vps) { - if (naltype == NAL_UNIT_SPS) { - parse_type = HEVC_NAL_UNIT_SPS; - hevc->have_sps = 1; -#ifdef ERROR_HANDLE_DEBUG - if (dbg_nal_skip_flag & 2) - parse_type = HEVC_DISCARD_NAL; -#endif - } else if (naltype == NAL_UNIT_PPS) { - parse_type = HEVC_NAL_UNIT_PPS; - hevc->have_pps = 1; -#ifdef ERROR_HANDLE_DEBUG - if (dbg_nal_skip_flag & 4) - parse_type = HEVC_DISCARD_NAL; -#endif - } else if (hevc->have_sps && hevc->have_pps) { - int seg = HEVC_NAL_UNIT_CODED_SLICE_SEGMENT; - - if ((naltype == NAL_UNIT_CODED_SLICE_IDR) || - (naltype == - NAL_UNIT_CODED_SLICE_IDR_N_LP) - || (naltype == - NAL_UNIT_CODED_SLICE_CRA) - || (naltype == - NAL_UNIT_CODED_SLICE_BLA) - || (naltype == - NAL_UNIT_CODED_SLICE_BLANT) - || (naltype == - NAL_UNIT_CODED_SLICE_BLA_N_LP) - ) { - if (slice_parse_begin > 0) { - hevc_print(hevc, 0, - "discard %d, for debugging\n", - slice_parse_begin); - slice_parse_begin--; - } else { - parse_type = seg; - } - hevc->have_valid_start_slice = 1; - } else if (naltype <= - NAL_UNIT_CODED_SLICE_CRA - && (hevc->have_valid_start_slice - || (hevc->PB_skip_mode != 3))) { - if (slice_parse_begin > 0) { - hevc_print(hevc, 0, - "discard %d, dd\n", - slice_parse_begin); - slice_parse_begin--; - } else - parse_type = seg; - - } - } - } - if (hevc->have_vps && hevc->have_sps && hevc->have_pps - && hevc->have_valid_start_slice && - hevc->error_flag == 0) { - if ((get_dbg_flag(hevc) & - H265_DEBUG_MAN_SEARCH_NAL) == 0 - /* && (!hevc->m_ins_flag)*/) { - /* auot parser NAL; do not check - *vps/sps/pps/idr - */ - WRITE_VREG(NAL_SEARCH_CTL, 0x2); - } - - if ((get_dbg_flag(hevc) & - H265_DEBUG_NO_EOS_SEARCH_DONE) -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - || vdec->master - || vdec->slave -#endif - ) { - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | - 0x10000); - } - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) - | ((parser_sei_enable & 0x7) << 17)); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | - ((parser_dolby_vision_enable & 0x1) << 20)); -#endif - config_decode_mode(hevc); - } - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { - hevc_print(hevc, 0, - "naltype = %d parse_type %d\n %d %d %d %d\n", - naltype, parse_type, hevc->have_vps, - hevc->have_sps, hevc->have_pps, - hevc->have_valid_start_slice); - } - - WRITE_VREG(HEVC_DEC_STATUS_REG, parse_type); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) - start_process_time(hevc); -#endif - } else if (dec_status == HEVC_SLICE_SEGMENT_DONE) { -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) { - reset_process_time(hevc); - read_decode_info(hevc); - - } -#endif - if (hevc->start_decoding_time > 0) { - u32 process_time = 1000* - (jiffies - hevc->start_decoding_time)/HZ; - if (process_time > max_decoding_time) - max_decoding_time = process_time; - } - - hevc->error_watchdog_count = 0; - if (hevc->pic_list_init_flag == 2) { - hevc->pic_list_init_flag = 3; - hevc_print(hevc, 0, "set pic_list_init_flag to 3\n"); - } else if (hevc->wait_buf == 0) { - u32 vui_time_scale; - u32 vui_num_units_in_tick; - unsigned char reconfig_flag = 0; - - if (get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) - get_rpm_param(&hevc->param); - else { - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->rpm_phy_addr, - RPM_BUF_SIZE, - DMA_FROM_DEVICE); - - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - - for (ii = 0; ii < 4; ii++) { - hevc->param.l.data[i + ii] = - hevc->rpm_ptr[i + 3 - - ii]; - } - } -#ifdef SEND_LMEM_WITH_RPM - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->lmem_phy_addr, - LMEM_BUF_SIZE, - DMA_FROM_DEVICE); - check_head_error(hevc); -#endif - } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { - hevc_print(hevc, 0, - "rpm_param: (%d)\n", hevc->slice_idx); - hevc->slice_idx++; - for (i = 0; i < (RPM_END - RPM_BEGIN); i++) { - hevc_print_cont(hevc, 0, - "%04x ", hevc->param.l.data[i]); - if (((i + 1) & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - } - - hevc_print(hevc, 0, - "vui_timing_info: %x, %x, %x, %x\n", - hevc->param.p.vui_num_units_in_tick_hi, - hevc->param.p.vui_num_units_in_tick_lo, - hevc->param.p.vui_time_scale_hi, - hevc->param.p.vui_time_scale_lo); - } - if ( -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - vdec->master == NULL && - vdec->slave == NULL && -#endif - aux_data_is_avaible(hevc) - ) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->aux_phy_addr, - hevc->prefix_aux_size + hevc->suffix_aux_size, - DMA_FROM_DEVICE); - if (get_dbg_flag(hevc) & - H265_DEBUG_BUFMGR_MORE) - dump_aux_buf(hevc); - } - - vui_time_scale = - (u32)(hevc->param.p.vui_time_scale_hi << 16) | - hevc->param.p.vui_time_scale_lo; - vui_num_units_in_tick = - (u32)(hevc->param. - p.vui_num_units_in_tick_hi << 16) | - hevc->param. - p.vui_num_units_in_tick_lo; - if (hevc->bit_depth_luma != - ((hevc->param.p.bit_depth & 0xf) + 8)) { - reconfig_flag = 1; - hevc_print(hevc, 0, "Bit depth luma = %d\n", - (hevc->param.p.bit_depth & 0xf) + 8); - } - if (hevc->bit_depth_chroma != - (((hevc->param.p.bit_depth >> 4) & 0xf) + 8)) { - reconfig_flag = 1; - hevc_print(hevc, 0, "Bit depth chroma = %d\n", - ((hevc->param.p.bit_depth >> 4) & - 0xf) + 8); - } - hevc->bit_depth_luma = - (hevc->param.p.bit_depth & 0xf) + 8; - hevc->bit_depth_chroma = - ((hevc->param.p.bit_depth >> 4) & 0xf) + 8; - bit_depth_luma = hevc->bit_depth_luma; - bit_depth_chroma = hevc->bit_depth_chroma; -#ifdef SUPPORT_10BIT - if (hevc->bit_depth_luma == 8 && - hevc->bit_depth_chroma == 8 && - enable_mem_saving) - hevc->mem_saving_mode = 1; - else - hevc->mem_saving_mode = 0; -#endif - if (reconfig_flag && - (get_double_write_mode(hevc) & 0x10) == 0) - init_decode_head_hw(hevc); - - if ((vui_time_scale != 0) - && (vui_num_units_in_tick != 0)) { - hevc->frame_dur = - div_u64(96000ULL * - vui_num_units_in_tick, - vui_time_scale); - if (hevc->get_frame_dur != true) - schedule_work( - &hevc->notify_work); - - hevc->get_frame_dur = true; -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - gvs->frame_dur = hevc->frame_dur; -#endif - } - - if (hevc->video_signal_type != - ((hevc->param.p.video_signal_type << 16) - | hevc->param.p.color_description)) { - u32 v = hevc->param.p.video_signal_type; - u32 c = hevc->param.p.color_description; -#if 0 - if (v & 0x2000) { - hevc_print(hevc, 0, - "video_signal_type present:\n"); - hevc_print(hevc, 0, " %s %s\n", - video_format_names[(v >> 10) & 7], - ((v >> 9) & 1) ? - "full_range" : "limited"); - if (v & 0x100) { - hevc_print(hevc, 0, - " color_description present:\n"); - hevc_print(hevc, 0, - " color_primarie = %s\n", - color_primaries_names - [v & 0xff]); - hevc_print(hevc, 0, - " transfer_characteristic = %s\n", - transfer_characteristics_names - [(c >> 8) & 0xff]); - hevc_print(hevc, 0, - " matrix_coefficient = %s\n", - matrix_coeffs_names[c & 0xff]); - } - } -#endif - hevc->video_signal_type = (v << 16) | c; - video_signal_type = hevc->video_signal_type; - } - - if (use_cma && - (hevc->param.p.slice_segment_address == 0) - && (hevc->pic_list_init_flag == 0)) { - int log = hevc->param.p.log2_min_coding_block_size_minus3; - int log_s = hevc->param.p.log2_diff_max_min_coding_block_size; - - hevc->pic_w = hevc->param.p.pic_width_in_luma_samples; - hevc->pic_h = hevc->param.p.pic_height_in_luma_samples; - hevc->lcu_size = 1 << (log + 3 + log_s); - hevc->lcu_size_log2 = log2i(hevc->lcu_size); - if (hevc->pic_w == 0 || hevc->pic_h == 0 - || hevc->lcu_size == 0 - || is_oversize(hevc->pic_w, hevc->pic_h) - || (!hevc->skip_first_nal && - (hevc->pic_h == 96) && (hevc->pic_w == 160))) { - /* skip search next start code */ - WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) - & (~0x2)); - if ( !hevc->skip_first_nal && - (hevc->pic_h == 96) && (hevc->pic_w == 160)) - hevc->skip_first_nal = 1; - hevc->skip_flag = 1; - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) - start_process_time(hevc); -#endif - } else { - hevc->sps_num_reorder_pics_0 = - hevc->param.p.sps_num_reorder_pics_0; - hevc->pic_list_init_flag = 1; -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) { - vdec_schedule_work(&hevc->work); - } else -#endif - up(&h265_sema); - hevc_print(hevc, 0, "set pic_list_init_flag 1\n"); - } - return IRQ_HANDLED; - } - -} - ret = - hevc_slice_segment_header_process(hevc, - &hevc->param, decode_pic_begin); - if (ret < 0) { -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) { - hevc->wait_buf = 0; - hevc->dec_result = DEC_RESULT_AGAIN; - amhevc_stop(); - restore_decode_state(hevc); - reset_process_time(hevc); - vdec_schedule_work(&hevc->work); - return IRQ_HANDLED; - } -#else - ; -#endif - } else if (ret == 0) { - if ((hevc->new_pic) && (hevc->cur_pic)) { - hevc->cur_pic->stream_offset = - READ_VREG(HEVC_SHIFT_BYTE_COUNT); - hevc_print(hevc, H265_DEBUG_OUT_PTS, - "read stream_offset = 0x%x\n", - hevc->cur_pic->stream_offset); - hevc->cur_pic->aspect_ratio_idc = - hevc->param.p.aspect_ratio_idc; - hevc->cur_pic->sar_width = - hevc->param.p.sar_width; - hevc->cur_pic->sar_height = - hevc->param.p.sar_height; - } - - WRITE_VREG(HEVC_DEC_STATUS_REG, - HEVC_CODED_SLICE_SEGMENT_DAT); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); - - hevc->start_decoding_time = jiffies; -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) - start_process_time(hevc); -#endif -#if 1 - /*to do..., copy aux data to hevc->cur_pic*/ -#endif -#ifdef MULTI_INSTANCE_SUPPORT - } else if (hevc->m_ins_flag) { - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s, bufmgr ret %d skip, DEC_RESULT_DONE\n", - __func__, ret); - hevc->decoded_poc = INVALID_POC; - hevc->decoding_pic = NULL; - hevc->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - reset_process_time(hevc); - vdec_schedule_work(&hevc->work); -#endif - } else { - /* skip, search next start code */ -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - gvs->drop_frame_count++; -#endif - WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2)); - hevc->skip_flag = 1; - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - /* Interrupt Amrisc to excute */ - WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); - } - - } else if (dec_status == HEVC_DECODE_OVER_SIZE) { - hevc_print(hevc, 0 , "hevc decode oversize !!\n"); -#ifdef MULTI_INSTANCE_SUPPORT - if (!hevc->m_ins_flag) - debug |= (H265_DEBUG_DIS_LOC_ERROR_PROC | - H265_DEBUG_DIS_SYS_ERROR_PROC); -#endif - hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - } - return IRQ_HANDLED; -} - -static void wait_hevc_search_done(struct hevc_state_s *hevc) -{ - int count = 0; - WRITE_VREG(HEVC_SHIFT_STATUS, 0); - while (READ_VREG(HEVC_STREAM_CONTROL) & 0x2) { - msleep(20); - count++; - if (count > 100) { - hevc_print(hevc, 0, "%s timeout\n", __func__); - break; - } - } -} -static irqreturn_t vh265_isr(int irq, void *data) -{ - int i, temp; - unsigned int dec_status; - struct hevc_state_s *hevc = (struct hevc_state_s *)data; - u32 debug_tag; - dec_status = READ_VREG(HEVC_DEC_STATUS_REG); - if (hevc->init_flag == 0) - return IRQ_HANDLED; - hevc->dec_status = dec_status; - if (is_log_enable(hevc)) - add_log(hevc, - "isr: status = 0x%x dec info 0x%x lcu 0x%x shiftbyte 0x%x shiftstatus 0x%x", - dec_status, READ_HREG(HEVC_DECODE_INFO), - READ_VREG(HEVC_MPRED_CURR_LCU), - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_SHIFT_STATUS)); - - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) - hevc_print(hevc, 0, - "265 isr dec status = 0x%x dec info 0x%x shiftbyte 0x%x shiftstatus 0x%x\n", - dec_status, READ_HREG(HEVC_DECODE_INFO), - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_SHIFT_STATUS)); - - debug_tag = READ_HREG(DEBUG_REG1); - if (debug_tag & 0x10000) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->lmem_phy_addr, - LMEM_BUF_SIZE, - DMA_FROM_DEVICE); - - hevc_print(hevc, 0, - "LMEM:\n", READ_HREG(DEBUG_REG1)); - - if (hevc->mmu_enable) - temp = 0x500; - else - temp = 0x400; - for (i = 0; i < temp; i += 4) { - int ii; - if ((i & 0xf) == 0) - hevc_print_cont(hevc, 0, "%03x: ", i); - for (ii = 0; ii < 4; ii++) { - hevc_print_cont(hevc, 0, "%04x ", - hevc->lmem_ptr[i + 3 - ii]); - } - if (((i + ii) & 0xf) == 0) - hevc_print_cont(hevc, 0, "\n"); - } - - if (((udebug_pause_pos & 0xffff) - == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == hevc->decode_idx) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_HREG(DEBUG_REG2))) { - udebug_pause_pos &= 0xffff; - hevc->ucode_pause_pos = udebug_pause_pos; - } - else if (debug_tag & 0x20000) - hevc->ucode_pause_pos = 0xffffffff; - if (hevc->ucode_pause_pos) - reset_process_time(hevc); - else - WRITE_HREG(DEBUG_REG1, 0); - } else if (debug_tag != 0) { - hevc_print(hevc, 0, - "dbg%x: %x l/w/r %x %x %x\n", READ_HREG(DEBUG_REG1), - READ_HREG(DEBUG_REG2), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR)); - if (((udebug_pause_pos & 0xffff) - == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == hevc->decode_idx) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_HREG(DEBUG_REG2))) { - udebug_pause_pos &= 0xffff; - hevc->ucode_pause_pos = udebug_pause_pos; - } - if (hevc->ucode_pause_pos) - reset_process_time(hevc); - else - WRITE_HREG(DEBUG_REG1, 0); - return IRQ_HANDLED; - } - - - if (hevc->pic_list_init_flag == 1) - return IRQ_HANDLED; - - if (!hevc->m_ins_flag) { - if (dec_status == HEVC_OVER_DECODE) { - hevc->over_decode = 1; - hevc_print(hevc, 0, - "isr: over decode\n"), - WRITE_VREG(HEVC_DEC_STATUS_REG, 0); - return IRQ_HANDLED; - } - } - - return IRQ_WAKE_THREAD; - -} - -static void vh265_set_clk(struct work_struct *work) -{ - struct hevc_state_s *hevc = container_of(work, - struct hevc_state_s, work); - - int fps = 96000 / hevc->frame_dur; - - if (hevc_source_changed(VFORMAT_HEVC, - hevc->frame_width, hevc->frame_height, fps) > 0) - hevc->saved_resolution = hevc->frame_width * - hevc->frame_height * fps; -} - -static void vh265_check_timer_func(unsigned long arg) -{ - struct hevc_state_s *hevc = (struct hevc_state_s *)arg; - struct timer_list *timer = &hevc->timer; - unsigned char empty_flag; - unsigned int buf_level; - - enum receviver_start_e state = RECEIVER_INACTIVE; - - if (hevc->init_flag == 0) { - if (hevc->stat & STAT_TIMER_ARM) { - mod_timer(&hevc->timer, jiffies + PUT_INTERVAL); - } - return; - } -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag && - (get_dbg_flag(hevc) & - H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP) == 0 && - hw_to_vdec(hevc)->next_status == - VDEC_STATUS_DISCONNECTED) { - hevc->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hevc->work); - hevc_print(hevc, - 0, "vdec requested to be disconnected\n"); - return; - } - - if (hevc->m_ins_flag) { - if ((input_frame_based(hw_to_vdec(hevc)) || - (READ_VREG(HEVC_STREAM_LEVEL) > 0xb0)) && - ((get_dbg_flag(hevc) & - H265_DEBUG_DIS_LOC_ERROR_PROC) == 0) && - (decode_timeout_val > 0) && - (hevc->start_process_time > 0) && - ((1000 * (jiffies - hevc->start_process_time) / HZ) - > decode_timeout_val) - ) { - u32 dec_status = READ_VREG(HEVC_DEC_STATUS_REG); - int current_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START)&0xffffff; - if (dec_status == HEVC_CODED_SLICE_SEGMENT_DAT) { - if (hevc->last_lcu_idx == current_lcu_idx) { - if (hevc->decode_timeout_count > 0) - hevc->decode_timeout_count--; - if (hevc->decode_timeout_count == 0) - timeout_process(hevc); - } else - restart_process_time(hevc); - hevc->last_lcu_idx = current_lcu_idx; - } else { - hevc->pic_decoded_lcu_idx = current_lcu_idx; - timeout_process(hevc); - } - } - } else { -#endif - if (hevc->m_ins_flag == 0 && - vf_get_receiver(hevc->provider_name)) { - state = - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) - state = RECEIVER_INACTIVE; - } else - state = RECEIVER_INACTIVE; - - empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1; - /* error watchdog */ - if (hevc->m_ins_flag == 0 && - (empty_flag == 0) - && (hevc->pic_list_init_flag == 0 - || hevc->pic_list_init_flag - == 3)) { - /* decoder has input */ - if ((get_dbg_flag(hevc) & - H265_DEBUG_DIS_LOC_ERROR_PROC) == 0) { - - buf_level = READ_VREG(HEVC_STREAM_LEVEL); - /* receiver has no buffer to recycle */ - if ((state == RECEIVER_INACTIVE) && - (kfifo_is_empty(&hevc->display_q) && - buf_level > 0x200) - ) { - if (hevc->error_flag == 0) { - hevc->error_watchdog_count++; - if (hevc->error_watchdog_count == - error_handle_threshold) { - hevc_print(hevc, 0, - "H265 dec err local reset.\n"); - hevc->error_flag = 1; - hevc->error_watchdog_count = 0; - hevc->error_skip_nal_wt_cnt = 0; - hevc-> - error_system_watchdog_count++; - WRITE_VREG - (HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - } - } else if (hevc->error_flag == 2) { - int th = - error_handle_nal_skip_threshold; - hevc->error_skip_nal_wt_cnt++; - if (hevc->error_skip_nal_wt_cnt - == th) { - hevc->error_flag = 3; - hevc->error_watchdog_count = 0; - hevc-> - error_skip_nal_wt_cnt = 0; - WRITE_VREG - (HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - } - } - } - } - - if ((get_dbg_flag(hevc) - & H265_DEBUG_DIS_SYS_ERROR_PROC) == 0) - /* receiver has no buffer to recycle */ - if ((state == RECEIVER_INACTIVE) && - (kfifo_is_empty(&hevc->display_q)) - ) { /* no buffer to recycle */ - if ((get_dbg_flag(hevc) & - H265_DEBUG_DIS_LOC_ERROR_PROC) != - 0) - hevc->error_system_watchdog_count++; - if (hevc->error_system_watchdog_count == - error_handle_system_threshold) { - /* and it lasts for a while */ - hevc_print(hevc, 0, - "H265 dec fatal error watchdog.\n"); - hevc-> - error_system_watchdog_count = 0; - hevc->fatal_error |= DECODER_FATAL_ERROR_UNKNOWN; - } - } - } else { - hevc->error_watchdog_count = 0; - hevc->error_system_watchdog_count = 0; - } -#ifdef MULTI_INSTANCE_SUPPORT - } -#endif - if ((hevc->ucode_pause_pos != 0) && - (hevc->ucode_pause_pos != 0xffffffff) && - udebug_pause_pos != hevc->ucode_pause_pos) { - hevc->ucode_pause_pos = 0; - WRITE_HREG(DEBUG_REG1, 0); - } - - if (get_dbg_flag(hevc) & H265_DEBUG_DUMP_PIC_LIST) { - dump_pic_list(hevc); - debug &= ~H265_DEBUG_DUMP_PIC_LIST; - } - if (get_dbg_flag(hevc) & H265_DEBUG_TRIG_SLICE_SEGMENT_PROC) { - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); - debug &= ~H265_DEBUG_TRIG_SLICE_SEGMENT_PROC; - } -#ifdef TEST_NO_BUF - if (hevc->wait_buf) - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); -#endif - if (get_dbg_flag(hevc) & H265_DEBUG_HW_RESET) { - hevc->error_skip_nal_count = error_skip_nal_count; - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - - debug &= ~H265_DEBUG_HW_RESET; - } - -#ifdef ERROR_HANDLE_DEBUG - if ((dbg_nal_skip_count > 0) && ((dbg_nal_skip_count & 0x10000) != 0)) { - hevc->error_skip_nal_count = dbg_nal_skip_count & 0xffff; - dbg_nal_skip_count &= ~0x10000; - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - } -#endif - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - hevc_print(hevc, 0, - "WRITE_VREG(%x,%x)\n", radr, rval); - } else - hevc_print(hevc, 0, - "READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - if (dbg_cmd != 0) { - if (dbg_cmd == 1) { - u32 disp_laddr; - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && - get_double_write_mode(hevc) == 0) { - disp_laddr = - READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; - } else { - struct canvas_s cur_canvas; - - canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) - & 0xff), &cur_canvas); - disp_laddr = cur_canvas.addr; - } - hevc_print(hevc, 0, - "current displayed buffer address %x\r\n", - disp_laddr); - } - dbg_cmd = 0; - } - /*don't changed at start.*/ - if (hevc->m_ins_flag == 0 && - hevc->get_frame_dur && hevc->show_frame_num > 60 && - hevc->frame_dur > 0 && hevc->saved_resolution != - hevc->frame_width * hevc->frame_height * - (96000 / hevc->frame_dur)) - schedule_work(&hevc->set_clk_work); - - mod_timer(timer, jiffies + PUT_INTERVAL); -} - -static int h265_task_handle(void *data) -{ - int ret = 0; - struct hevc_state_s *hevc = (struct hevc_state_s *)data; - - set_user_nice(current, -10); - while (1) { - if (use_cma == 0) { - hevc_print(hevc, 0, - "ERROR: use_cma can not be changed dynamically\n"); - } - ret = down_interruptible(&h265_sema); - if ((hevc->init_flag != 0) && (hevc->pic_list_init_flag == 1)) { - init_pic_list(hevc); - init_pic_list_hw(hevc); - init_buf_spec(hevc); - hevc->pic_list_init_flag = 2; - hevc_print(hevc, 0, "set pic_list_init_flag to 2\n"); - - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); - - } - - if (hevc->uninit_list) { - /*USE_BUF_BLOCK*/ - uninit_pic_list(hevc); - hevc_print(hevc, 0, "uninit list\n"); - hevc->uninit_list = 0; -#ifdef USE_UNINIT_SEMA - if (use_cma) { - up(&hevc->h265_uninit_done_sema); - while (!kthread_should_stop()) - msleep(1); - break; - } -#endif - } - } - - return 0; -} - -void vh265_free_cmabuf(void) -{ - struct hevc_state_s *hevc = gHevc; - - mutex_lock(&vh265_mutex); - - if (hevc->init_flag) { - mutex_unlock(&vh265_mutex); - return; - } - - mutex_unlock(&vh265_mutex); -} - -#ifdef MULTI_INSTANCE_SUPPORT -int vh265_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -#else -int vh265_dec_status(struct vdec_info *vstatus) -#endif -{ -#ifdef MULTI_INSTANCE_SUPPORT - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; -#else - struct hevc_state_s *hevc = gHevc; -#endif - if (!hevc) - return -1; - - vstatus->frame_width = hevc->frame_width; - vstatus->frame_height = hevc->frame_height; - if (hevc->frame_dur != 0) - vstatus->frame_rate = 96000 / hevc->frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = 0; - vstatus->status = hevc->stat | hevc->fatal_error; -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = hevc->frame_dur; - if (gvs) { - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - } - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); -#endif - vstatus->ratio_control = hevc->ratio_control; - return 0; -} - -int vh265_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -static int vh265_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -#if 0 -static void H265_DECODE_INIT(void) -{ - /* enable hevc clocks */ - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); - /* *************************************************************** */ - /* Power ON HEVC */ - /* *************************************************************** */ - /* Powerup HEVC */ - WRITE_VREG(P_AO_RTI_GEN_PWR_SLEEP0, - READ_VREG(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x3 << 6))); - WRITE_VREG(DOS_MEM_PD_HEVC, 0x0); - WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) | (0x3ffff << 2)); - WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) & (~(0x3ffff << 2))); - /* remove isolations */ - WRITE_VREG(AO_RTI_GEN_PWR_ISO0, - READ_VREG(AO_RTI_GEN_PWR_ISO0) & (~(0x3 << 10))); - -} -#endif - -static void config_decode_mode(struct hevc_state_s *hevc) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - struct vdec_s *vdec = hw_to_vdec(hevc); -#endif - unsigned decode_mode; - if (!hevc->m_ins_flag) - decode_mode = DECODE_MODE_SINGLE; - else if (vdec_frame_based(hw_to_vdec(hevc))) - decode_mode = - DECODE_MODE_MULTI_FRAMEBASE; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec->slave) { - if (force_bypass_dvenl & 0x80000000) - hevc->bypass_dvenl = force_bypass_dvenl & 0x1; - else - hevc->bypass_dvenl = hevc->bypass_dvenl_enable; - if (dolby_meta_with_el && hevc->bypass_dvenl) { - hevc->bypass_dvenl = 0; - hevc_print(hevc, 0, - "NOT support bypass_dvenl when meta_with_el\n"); - } - if (hevc->bypass_dvenl) - decode_mode = - (hevc->start_parser_type << 8) - | DECODE_MODE_MULTI_STREAMBASE; - else - decode_mode = - (hevc->start_parser_type << 8) - | DECODE_MODE_MULTI_DVBAL; - } else if (vdec->master) - decode_mode = - (hevc->start_parser_type << 8) - | DECODE_MODE_MULTI_DVENL; -#endif - else - decode_mode = - DECODE_MODE_MULTI_STREAMBASE; - - if (hevc->m_ins_flag) - decode_mode |= - (hevc->start_decoding_flag << 16); - /* set MBX0 interrupt flag */ - decode_mode |= (0x80 << 24); - WRITE_VREG(HEVC_DECODE_MODE, decode_mode); - WRITE_VREG(HEVC_DECODE_MODE2, - hevc->rps_set_id); -} - -static void vh265_prot_init(struct hevc_state_s *hevc) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - struct vdec_s *vdec = hw_to_vdec(hevc); -#endif - /* H265_DECODE_INIT(); */ - - hevc_config_work_space_hw(hevc); - - hevc_init_decoder_hw(hevc, 0, 0xffffffff); - - WRITE_VREG(HEVC_WAIT_FLAG, 1); - - /* WRITE_VREG(P_HEVC_MPSR, 1); */ - - /* clear mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(HEVC_PSCALE_CTRL, 0); - - WRITE_VREG(DEBUG_REG1, 0x0 | (dump_nal << 8)); - - if ((get_dbg_flag(hevc) & - (H265_DEBUG_MAN_SKIP_NAL | - H265_DEBUG_MAN_SEARCH_NAL)) - /*||hevc->m_ins_flag*/ - ) { - WRITE_VREG(NAL_SEARCH_CTL, 0x1); /* manual parser NAL */ - } else { - /* check vps/sps/pps/i-slice in ucode */ - unsigned ctl_val = 0x8; - if (hevc->PB_skip_mode == 0) - ctl_val = 0x4; /* check vps/sps/pps only in ucode */ - else if (hevc->PB_skip_mode == 3) - ctl_val = 0x0; /* check vps/sps/pps/idr in ucode */ - WRITE_VREG(NAL_SEARCH_CTL, ctl_val); - } - if ((get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE) -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - || vdec->master - || vdec->slave -#endif - ) - WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x10000); - - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) - | ((parser_sei_enable & 0x7) << 17)); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - WRITE_VREG(NAL_SEARCH_CTL, - READ_VREG(NAL_SEARCH_CTL) | - ((parser_dolby_vision_enable & 0x1) << 20)); -#endif - WRITE_VREG(DECODE_STOP_POS, udebug_flag); - - config_decode_mode(hevc); - config_aux_buf(hevc); -#ifdef SWAP_HEVC_UCODE - if (!tee_enabled() && hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); - /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ - } -#endif -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - WRITE_VREG(HEVC_SAO_DBG_MODE0, 0); - WRITE_VREG(HEVC_SAO_DBG_MODE1, 0); - } -#endif -} - -static int vh265_local_init(struct hevc_state_s *hevc) -{ - int i; - int ret = -1; - -#ifdef DEBUG_PTS - hevc->pts_missed = 0; - hevc->pts_hit = 0; -#endif - - hevc->saved_resolution = 0; - hevc->get_frame_dur = false; - hevc->frame_width = hevc->vh265_amstream_dec_info.width; - hevc->frame_height = hevc->vh265_amstream_dec_info.height; - if (is_oversize(hevc->frame_width, hevc->frame_height)) { - pr_info("over size : %u x %u.\n", - hevc->frame_width, hevc->frame_height); - hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - return ret; - } - - if (hevc->max_pic_w && hevc->max_pic_h) { - hevc->is_4k = !(hevc->max_pic_w && hevc->max_pic_h) || - ((hevc->max_pic_w * hevc->max_pic_h) > - 1920 * 1088) ? true : false; - } else { - hevc->is_4k = !(hevc->frame_width && hevc->frame_height) || - ((hevc->frame_width * hevc->frame_height) > - 1920 * 1088) ? true : false; - } - - hevc->frame_dur = - (hevc->vh265_amstream_dec_info.rate == - 0) ? 3600 : hevc->vh265_amstream_dec_info.rate; -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - gvs->frame_dur = hevc->frame_dur; -#endif - if (hevc->frame_width && hevc->frame_height) - hevc->frame_ar = hevc->frame_height * 0x100 / hevc->frame_width; - - if (i_only_flag) - hevc->i_only = i_only_flag & 0xff; - else if ((unsigned long) hevc->vh265_amstream_dec_info.param - & 0x08) - hevc->i_only = 0x7; - else - hevc->i_only = 0x0; - hevc->error_watchdog_count = 0; - hevc->sei_present_flag = 0; - pts_unstable = ((unsigned long)hevc->vh265_amstream_dec_info.param - & 0x40) >> 6; - hevc_print(hevc, 0, - "h265:pts_unstable=%d\n", pts_unstable); -/* - *TODO:FOR VERSION - */ - hevc_print(hevc, 0, - "h265: ver (%d,%d) decinfo: %dx%d rate=%d\n", h265_version, - 0, hevc->frame_width, hevc->frame_height, hevc->frame_dur); - - if (hevc->frame_dur == 0) - hevc->frame_dur = 96000 / 24; - - INIT_KFIFO(hevc->display_q); - INIT_KFIFO(hevc->newframe_q); - - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &hevc->vfpool[i]; - - hevc->vfpool[i].index = -1; - kfifo_put(&hevc->newframe_q, vf); - } - - - ret = hevc_local_init(hevc); - - return ret; -} -#ifdef MULTI_INSTANCE_SUPPORT -static s32 vh265_init(struct vdec_s *vdec) -{ - struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; -#else -static s32 vh265_init(struct hevc_state_s *hevc) -{ - -#endif - int ret, size = -1; - int fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; - - init_timer(&hevc->timer); - - hevc->stat |= STAT_TIMER_INIT; - if (vh265_local_init(hevc) < 0) - return -EBUSY; - - mutex_init(&hevc->chunks_mutex); - INIT_WORK(&hevc->notify_work, vh265_notify_work); - INIT_WORK(&hevc->set_clk_work, vh265_set_clk); - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - if (hevc->mmu_enable) - if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) - size = get_firmware_data(VIDEO_DEC_HEVC_MMU, fw->data); - else { - if (!hevc->is_4k) { - /* if an older version of the fw was loaded, */ - /* needs try to load noswap fw because the */ - /* old fw package dose not contain the swap fw.*/ - size = get_firmware_data( - VIDEO_DEC_HEVC_MMU_SWAP, fw->data); - if (size < 0) - size = get_firmware_data( - VIDEO_DEC_HEVC_MMU, fw->data); - else if (size) - hevc->is_swap = true; - } else - size = get_firmware_data(VIDEO_DEC_HEVC_MMU, - fw->data); - } - else - size = get_firmware_data(VIDEO_DEC_HEVC, fw->data); - - if (size < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = size; - -#ifdef SWAP_HEVC_UCODE - if (!tee_enabled() && hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - if (hevc->mmu_enable) { - hevc->swap_size = (4 * (4 * SZ_1K)); /*max 4 swap code, each 0x400*/ - hevc->mc_cpu_addr = - dma_alloc_coherent(amports_get_dma_device(), - hevc->swap_size, - &hevc->mc_dma_handle, GFP_KERNEL); - if (!hevc->mc_cpu_addr) { - amhevc_disable(); - pr_info("vh265 mmu swap ucode loaded fail.\n"); - return -ENOMEM; - } - - memcpy((u8 *) hevc->mc_cpu_addr, fw->data + SWAP_HEVC_OFFSET, - hevc->swap_size); - - hevc_print(hevc, 0, - "vh265 mmu ucode swap loaded %x\n", - hevc->mc_dma_handle); - } - } -#endif - -#ifdef MULTI_INSTANCE_SUPPORT - if (hevc->m_ins_flag) { - hevc->timer.data = (ulong) hevc; - hevc->timer.function = vh265_check_timer_func; - hevc->timer.expires = jiffies + PUT_INTERVAL; - -#ifdef USE_UNINIT_SEMA - sema_init(&hevc->h265_uninit_done_sema, 0); -#endif - - /*add_timer(&hevc->timer); - *hevc->stat |= STAT_TIMER_ARM; - */ - - INIT_WORK(&hevc->work, vh265_work); - - hevc->fw = fw; - - return 0; - } -#endif - hevc_enable_DMC(hw_to_vdec(hevc)); - amhevc_enable(); - - if (hevc->mmu_enable) - if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) - ret = amhevc_loadmc_ex(VFORMAT_HEVC, "h265_mmu", fw->data); - else { - if (!hevc->is_4k) { - /* if an older version of the fw was loaded, */ - /* needs try to load noswap fw because the */ - /* old fw package dose not contain the swap fw. */ - ret = amhevc_loadmc_ex(VFORMAT_HEVC, - "hevc_mmu_swap", fw->data); - if (ret < 0) - ret = amhevc_loadmc_ex(VFORMAT_HEVC, - "h265_mmu", fw->data); - else - hevc->is_swap = true; - } else - ret = amhevc_loadmc_ex(VFORMAT_HEVC, - "h265_mmu", fw->data); - } - else - ret = amhevc_loadmc_ex(VFORMAT_HEVC, NULL, fw->data); - - if (ret < 0) { - amhevc_disable(); - vfree(fw); - pr_err("H265: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(fw); - - hevc->stat |= STAT_MC_LOAD; - -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) - init_detrefill_buf(hevc); -#endif - /* enable AMRISC side protocol */ - vh265_prot_init(hevc); - - if (vdec_request_threaded_irq(VDEC_IRQ_0, vh265_isr, - vh265_isr_thread_fn, - IRQF_ONESHOT,/*run thread on this irq disabled*/ - "vh265-irq", (void *)hevc)) { - hevc_print(hevc, 0, "vh265 irq register error.\n"); - amhevc_disable(); - return -ENOENT; - } - - hevc->stat |= STAT_ISR_REG; - hevc->provider_name = PROVIDER_NAME; - -#ifdef MULTI_INSTANCE_SUPPORT - vf_provider_init(&vh265_vf_prov, hevc->provider_name, - &vh265_vf_provider, vdec); - vf_reg_provider(&vh265_vf_prov); - vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_START, - NULL); - if (hevc->frame_dur != 0) { - if (!is_reset) { - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)hevc->frame_dur)); - fr_hint_status = VDEC_HINTED; - } - } else - fr_hint_status = VDEC_NEED_HINT; -#else - vf_provider_init(&vh265_vf_prov, PROVIDER_NAME, &vh265_vf_provider, - hevc); - vf_reg_provider(&vh265_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); - if (hevc->frame_dur != 0) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)hevc->frame_dur)); - fr_hint_status = VDEC_HINTED; - } else - fr_hint_status = VDEC_NEED_HINT; -#endif - hevc->stat |= STAT_VF_HOOK; - - hevc->timer.data = (ulong) hevc; - hevc->timer.function = vh265_check_timer_func; - hevc->timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&hevc->timer); - - hevc->stat |= STAT_TIMER_ARM; - - if (use_cma) { -#ifdef USE_UNINIT_SEMA - sema_init(&hevc->h265_uninit_done_sema, 0); -#endif - if (h265_task == NULL) { - sema_init(&h265_sema, 1); - h265_task = - kthread_run(h265_task_handle, hevc, - "kthread_h265"); - } - } - /* hevc->stat |= STAT_KTHREAD; */ -#if 0 - if (get_dbg_flag(hevc) & H265_DEBUG_FORCE_CLK) { - hevc_print(hevc, 0, "%s force clk\n", __func__); - WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, - READ_VREG(HEVC_IQIT_CLK_RST_CTRL) | - ((1 << 2) | (1 << 1))); - WRITE_VREG(HEVC_DBLK_CFG0, - READ_VREG(HEVC_DBLK_CFG0) | ((1 << 2) | - (1 << 1) | 0x3fff0000));/* 2,29:16 */ - WRITE_VREG(HEVC_SAO_CTRL1, READ_VREG(HEVC_SAO_CTRL1) | - (1 << 2)); /* 2 */ - WRITE_VREG(HEVC_MPRED_CTRL1, READ_VREG(HEVC_MPRED_CTRL1) | - (1 << 24)); /* 24 */ - WRITE_VREG(HEVC_STREAM_CONTROL, - READ_VREG(HEVC_STREAM_CONTROL) | - (1 << 15)); /* 15 */ - WRITE_VREG(HEVC_CABAC_CONTROL, READ_VREG(HEVC_CABAC_CONTROL) | - (1 << 13)); /* 13 */ - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, - READ_VREG(HEVC_PARSER_CORE_CONTROL) | - (1 << 15)); /* 15 */ - WRITE_VREG(HEVC_PARSER_INT_CONTROL, - READ_VREG(HEVC_PARSER_INT_CONTROL) | - (1 << 15)); /* 15 */ - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - READ_VREG(HEVC_PARSER_IF_CONTROL) | ((1 << 6) | - (1 << 3) | (1 << 1))); /* 6, 3, 1 */ - WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, 0xffffffff); /* 31:0 */ - WRITE_VREG(HEVCD_MCRCC_CTL1, READ_VREG(HEVCD_MCRCC_CTL1) | - (1 << 3)); /* 3 */ - } -#endif -#ifdef SWAP_HEVC_UCODE - if (!tee_enabled() && hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); - /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ - } -#endif - -#ifndef MULTI_INSTANCE_SUPPORT - set_vdec_func(&vh265_dec_status); -#endif - amhevc_start(); - hevc->stat |= STAT_VDEC_RUN; - hevc->init_flag = 1; - error_handle_threshold = 30; - /* pr_info("%d, vh265_init, RP=0x%x\n", - * __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); - */ - - return 0; -} - -static int vh265_stop(struct hevc_state_s *hevc) -{ - if (get_dbg_flag(hevc) & - H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP) { - int wait_timeout_count = 0; - - while (READ_VREG(HEVC_DEC_STATUS_REG) == - HEVC_CODED_SLICE_SEGMENT_DAT && - wait_timeout_count < 10){ - wait_timeout_count++; - msleep(20); - } - } - if (hevc->stat & STAT_VDEC_RUN) { - amhevc_stop(); - hevc->stat &= ~STAT_VDEC_RUN; - } - - if (hevc->stat & STAT_ISR_REG) { -#ifdef MULTI_INSTANCE_SUPPORT - if (!hevc->m_ins_flag) -#endif - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0); - vdec_free_irq(VDEC_IRQ_0, (void *)hevc); - hevc->stat &= ~STAT_ISR_REG; - } - - hevc->stat &= ~STAT_TIMER_INIT; - if (hevc->stat & STAT_TIMER_ARM) { - del_timer_sync(&hevc->timer); - hevc->stat &= ~STAT_TIMER_ARM; - } - - if (hevc->stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED) { - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - } - fr_hint_status = VDEC_NO_NEED_HINT; - vf_unreg_provider(&vh265_vf_prov); - hevc->stat &= ~STAT_VF_HOOK; - } - - hevc_local_uninit(hevc); - - if (use_cma) { - hevc->uninit_list = 1; - up(&h265_sema); -#ifdef USE_UNINIT_SEMA - down(&hevc->h265_uninit_done_sema); - if (!IS_ERR(h265_task)) { - kthread_stop(h265_task); - h265_task = NULL; - } -#else - while (hevc->uninit_list) /* wait uninit complete */ - msleep(20); -#endif - - } - hevc->init_flag = 0; - hevc->first_sc_checked = 0; - cancel_work_sync(&hevc->notify_work); - cancel_work_sync(&hevc->set_clk_work); - uninit_mmu_buffers(hevc); - amhevc_disable(); - - kfree(gvs); - gvs = NULL; - - return 0; -} - -#ifdef MULTI_INSTANCE_SUPPORT -static void reset_process_time(struct hevc_state_s *hevc) -{ - if (hevc->start_process_time) { - unsigned int process_time = - 1000 * (jiffies - hevc->start_process_time) / HZ; - hevc->start_process_time = 0; - if (process_time > max_process_time[hevc->index]) - max_process_time[hevc->index] = process_time; - } -} - -static void start_process_time(struct hevc_state_s *hevc) -{ - hevc->start_process_time = jiffies; - hevc->decode_timeout_count = 2; - hevc->last_lcu_idx = 0; -} - -static void restart_process_time(struct hevc_state_s *hevc) -{ - hevc->start_process_time = jiffies; - hevc->decode_timeout_count = 2; -} - -static void timeout_process(struct hevc_state_s *hevc) -{ - hevc->timeout_num++; - amhevc_stop(); - read_decode_info(hevc); - - hevc_print(hevc, - 0, "%s decoder timeout\n", __func__); - check_pic_decoded_error(hevc, - hevc->pic_decoded_lcu_idx); - hevc->decoded_poc = hevc->curr_POC; - hevc->decoding_pic = NULL; - hevc->dec_result = DEC_RESULT_DONE; - reset_process_time(hevc); - vdec_schedule_work(&hevc->work); -} - -#ifdef CONSTRAIN_MAX_BUF_NUM -static int get_vf_ref_only_buf_count(struct hevc_state_s *hevc) -{ - struct PIC_s *pic; - int i; - int count = 0; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - if (pic->output_mark == 0 && pic->referenced == 0 - && pic->output_ready == 1) - count++; - } - - return count; -} - -static int get_used_buf_count(struct hevc_state_s *hevc) -{ - struct PIC_s *pic; - int i; - int count = 0; - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - if (pic->output_mark != 0 || pic->referenced != 0 - || pic->output_ready != 0) - count++; - } - - return count; -} -#endif - - -static unsigned char is_new_pic_available(struct hevc_state_s *hevc) -{ - struct PIC_s *new_pic = NULL; - struct PIC_s *pic; - /* recycle un-used pic */ - int i; - /*return 1 if pic_list is not initialized yet*/ - if (hevc->pic_list_init_flag != 3) - return 1; - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - pic = hevc->m_PIC[i]; - if (pic == NULL || pic->index == -1) - continue; - if (pic->output_mark == 0 && pic->referenced == 0 - && pic->output_ready == 0 - ) { - if (new_pic) { - if (pic->POC < new_pic->POC) - new_pic = pic; - } else - new_pic = pic; - } - } - return (new_pic != NULL) ? 1 : 0; -} - -static int vmh265_stop(struct hevc_state_s *hevc) -{ - if (hevc->stat & STAT_TIMER_ARM) { - del_timer_sync(&hevc->timer); - hevc->stat &= ~STAT_TIMER_ARM; - } - if (hevc->stat & STAT_VDEC_RUN) { - amhevc_stop(); - hevc->stat &= ~STAT_VDEC_RUN; - } - if (hevc->stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_0, (void *)hevc); - hevc->stat &= ~STAT_ISR_REG; - } - - if (hevc->stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED) - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - fr_hint_status = VDEC_NO_NEED_HINT; - vf_unreg_provider(&vh265_vf_prov); - hevc->stat &= ~STAT_VF_HOOK; - } - - hevc_local_uninit(hevc); - - if (use_cma) { - hevc->uninit_list = 1; - reset_process_time(hevc); - vdec_schedule_work(&hevc->work); -#ifdef USE_UNINIT_SEMA - if (hevc->init_flag) { - down(&hevc->h265_uninit_done_sema); - } -#else - while (hevc->uninit_list) /* wait uninit complete */ - msleep(20); -#endif - } - hevc->init_flag = 0; - hevc->first_sc_checked = 0; - cancel_work_sync(&hevc->work); - cancel_work_sync(&hevc->notify_work); - cancel_work_sync(&hevc->set_clk_work); - uninit_mmu_buffers(hevc); - - vfree(hevc->fw); - hevc->fw = NULL; - - dump_log(hevc); - return 0; -} - -static unsigned char get_data_check_sum - (struct hevc_state_s *hevc, int size) -{ - int jj; - int sum = 0; - u8 *data = NULL; - - if (!hevc->chunk->block->is_mapped) - data = codec_mm_vmap(hevc->chunk->block->start + - hevc->chunk->offset, size); - else - data = ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; - - for (jj = 0; jj < size; jj++) - sum += data[jj]; - - if (!hevc->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - return sum; -} - -static void vh265_notify_work(struct work_struct *work) -{ - struct hevc_state_s *hevc = - container_of(work, - struct hevc_state_s, - notify_work); - struct vdec_s *vdec = hw_to_vdec(hevc); -#ifdef MULTI_INSTANCE_SUPPORT - if (vdec->fr_hint_state == VDEC_NEED_HINT) { - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)hevc->frame_dur)); - vdec->fr_hint_state = VDEC_HINTED; - } else if (fr_hint_status == VDEC_NEED_HINT) { - vf_notify_receiver(hevc->provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)hevc->frame_dur)); - fr_hint_status = VDEC_HINTED; - } -#else - if (fr_hint_status == VDEC_NEED_HINT) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)hevc->frame_dur)); - fr_hint_status = VDEC_HINTED; - } -#endif - - return; -} - -static void vh265_work(struct work_struct *work) -{ - struct hevc_state_s *hevc = container_of(work, - struct hevc_state_s, work); - struct vdec_s *vdec = hw_to_vdec(hevc); - - if (hevc->uninit_list) { - /*USE_BUF_BLOCK*/ - uninit_pic_list(hevc); - hevc_print(hevc, 0, "uninit list\n"); - hevc->uninit_list = 0; -#ifdef USE_UNINIT_SEMA - up(&hevc->h265_uninit_done_sema); -#endif - return; - } - - /* finished decoding one frame or error, - * notify vdec core to switch context - */ - if (hevc->pic_list_init_flag == 1 - && (hevc->dec_result != DEC_RESULT_FORCE_EXIT)) { - hevc->pic_list_init_flag = 2; - init_pic_list(hevc); - init_pic_list_hw(hevc); - init_buf_spec(hevc); - hevc_print(hevc, 0, - "set pic_list_init_flag to 2\n"); - - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); - return; - } - - hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, - "%s dec_result %d %x %x %x\n", - __func__, - hevc->dec_result, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR)); - - if (((hevc->dec_result == DEC_RESULT_GET_DATA) || - (hevc->dec_result == DEC_RESULT_GET_DATA_RETRY)) - && (hw_to_vdec(hevc)->next_status != - VDEC_STATUS_DISCONNECTED)) { - if (!vdec_has_more_input(vdec)) { - hevc->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hevc->work); - return; - } - if (!input_frame_based(vdec)) { - int r = vdec_sync_input(vdec); - if (r >= 0x200) { - WRITE_VREG(HEVC_DECODE_SIZE, - READ_VREG(HEVC_DECODE_SIZE) + r); - - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_GET_DATA %x %x %x mpc %x size 0x%x\n", - __func__, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - READ_VREG(HEVC_MPC_E), r); - - start_process_time(hevc); - if (READ_VREG(HEVC_DEC_STATUS_REG) - == HEVC_DECODE_BUFEMPTY2) - WRITE_VREG(HEVC_DEC_STATUS_REG, - HEVC_ACTION_DONE); - else - WRITE_VREG(HEVC_DEC_STATUS_REG, - HEVC_ACTION_DEC_CONT); - } else { - hevc->dec_result = DEC_RESULT_GET_DATA_RETRY; - vdec_schedule_work(&hevc->work); - } - return; - } - - /*below for frame_base*/ - if (hevc->dec_result == DEC_RESULT_GET_DATA) { - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_GET_DATA %x %x %x mpc %x\n", - __func__, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - READ_VREG(HEVC_MPC_E)); - mutex_lock(&hevc->chunks_mutex); - vdec_vframe_dirty(vdec, hevc->chunk); - hevc->chunk = NULL; - mutex_unlock(&hevc->chunks_mutex); - vdec_clean_input(vdec); - } - - /*if (is_new_pic_available(hevc)) {*/ - if (run_ready(vdec, VDEC_HEVC)) { - int r; - int decode_size; - r = vdec_prepare_input(vdec, &hevc->chunk); - if (r < 0) { - hevc->dec_result = DEC_RESULT_GET_DATA_RETRY; - - hevc_print(hevc, - PRINT_FLAG_VDEC_DETAIL, - "amvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&hevc->work); - return; - } - hevc->dec_result = DEC_RESULT_NONE; - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: chunk size 0x%x sum 0x%x mpc %x\n", - __func__, r, - (get_dbg_flag(hevc) & PRINT_FLAG_VDEC_STATUS) ? - get_data_check_sum(hevc, r) : 0, - READ_VREG(HEVC_MPC_E)); - - if (get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) { - int jj; - u8 *data = NULL; - - if (!hevc->chunk->block->is_mapped) - data = codec_mm_vmap( - hevc->chunk->block->start + - hevc->chunk->offset, r); - else - data = ((u8 *) - hevc->chunk->block->start_virt) - + hevc->chunk->offset; - - for (jj = 0; jj < r; jj++) { - if ((jj & 0xf) == 0) - hevc_print(hevc, - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - hevc_print_cont(hevc, - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - hevc_print_cont(hevc, - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hevc->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - - decode_size = hevc->chunk->size + - (hevc->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - WRITE_VREG(HEVC_DECODE_SIZE, - READ_VREG(HEVC_DECODE_SIZE) + decode_size); - - vdec_enable_input(vdec); - - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: mpc %x\n", - __func__, READ_VREG(HEVC_MPC_E)); - - start_process_time(hevc); - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - } else{ - hevc->dec_result = DEC_RESULT_GET_DATA_RETRY; - - /*hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, - * "amvdec_vh265: Insufficient data\n"); - */ - - vdec_schedule_work(&hevc->work); - } - return; - } else if (hevc->dec_result == DEC_RESULT_DONE) { - /* if (!hevc->ctx_valid) - hevc->ctx_valid = 1; */ - decode_frame_count[hevc->index]++; -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { - if (hevc->delrefill_check == 2) { - delrefill(hevc); - amhevc_stop(); - } - } -#endif - if (hevc->mmu_enable && ((hevc->double_write_mode & 0x10) == 0)) { - hevc->used_4k_num = - READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; - if (hevc->used_4k_num >= 0 && - hevc->cur_pic && - hevc->cur_pic->scatter_alloc - == 1) { - hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s pic index %d scatter_alloc %d page_start %d\n", - "decoder_mmu_box_free_idx_tail", - hevc->cur_pic->index, - hevc->cur_pic->scatter_alloc, - hevc->used_4k_num); - decoder_mmu_box_free_idx_tail( - hevc->mmu_box, - hevc->cur_pic->index, - hevc->used_4k_num); - hevc->cur_pic->scatter_alloc = 2; - } - } - hevc->pic_decoded_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff; - - if (vdec->master == NULL && vdec->slave == NULL && - hevc->empty_flag == 0) { - hevc->over_decode = - (READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1; - if (hevc->over_decode) - hevc_print(hevc, 0, - "!!!Over decode\n"); - } - - if (is_log_enable(hevc)) - add_log(hevc, - "%s dec_result %d lcu %d used_mmu %d shiftbyte 0x%x decbytes 0x%x", - __func__, - hevc->dec_result, - hevc->pic_decoded_lcu_idx, - hevc->used_4k_num, - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_SHIFT_BYTE_COUNT) - - hevc->start_shift_bytes - ); - - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s dec_result %d (%x %x %x) lcu %d used_mmu %d shiftbyte 0x%x decbytes 0x%x\n", - __func__, - hevc->dec_result, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - hevc->pic_decoded_lcu_idx, - hevc->used_4k_num, - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_SHIFT_BYTE_COUNT) - - hevc->start_shift_bytes - ); - - hevc->used_4k_num = -1; - - check_pic_decoded_error(hevc, - hevc->pic_decoded_lcu_idx); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -#if 1 - if (vdec->slave) { - if (dv_debug & 0x1) - vdec_set_flag(vdec->slave, - VDEC_FLAG_SELF_INPUT_CONTEXT); - else - vdec_set_flag(vdec->slave, - VDEC_FLAG_OTHER_INPUT_CONTEXT); - } -#else - if (vdec->slave) { - if (no_interleaved_el_slice) - vdec_set_flag(vdec->slave, - VDEC_FLAG_INPUT_KEEP_CONTEXT); - /* this will move real HW pointer for input */ - else - vdec_set_flag(vdec->slave, 0); - /* this will not move real HW pointer - *and SL layer decoding - *will start from same stream position - *as current BL decoder - */ - } -#endif -#endif -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - hevc->shift_byte_count_lo - = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - if (vdec->slave) { - /*cur is base, found enhance*/ - struct hevc_state_s *hevc_el = - (struct hevc_state_s *) - vdec->slave->private; - if (hevc_el) - hevc_el->shift_byte_count_lo = - hevc->shift_byte_count_lo; - } else if (vdec->master) { - /*cur is enhance, found base*/ - struct hevc_state_s *hevc_ba = - (struct hevc_state_s *) - vdec->master->private; - if (hevc_ba) - hevc_ba->shift_byte_count_lo = - hevc->shift_byte_count_lo; - } -#endif - mutex_lock(&hevc->chunks_mutex); - vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); - hevc->chunk = NULL; - mutex_unlock(&hevc->chunks_mutex); - } else if (hevc->dec_result == DEC_RESULT_AGAIN) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(vdec)) { - hevc->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hevc->work); - return; - } -#ifdef AGAIN_HAS_THRESHOLD - hevc->next_again_flag = 1; -#endif - } else if (hevc->dec_result == DEC_RESULT_EOS) { - struct PIC_s *pic; - hevc->eos = 1; -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if ((vdec->master || vdec->slave) && - aux_data_is_avaible(hevc)) - dolby_get_meta(hevc); -#endif - check_pic_decoded_error(hevc, - hevc->pic_decoded_lcu_idx); - pic = get_pic_by_POC(hevc, hevc->curr_POC); - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: end of stream, last dec poc %d => 0x%pf\n", - __func__, hevc->curr_POC, pic); - flush_output(hevc, pic); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - hevc->shift_byte_count_lo - = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - if (vdec->slave) { - /*cur is base, found enhance*/ - struct hevc_state_s *hevc_el = - (struct hevc_state_s *) - vdec->slave->private; - if (hevc_el) - hevc_el->shift_byte_count_lo = - hevc->shift_byte_count_lo; - } else if (vdec->master) { - /*cur is enhance, found base*/ - struct hevc_state_s *hevc_ba = - (struct hevc_state_s *) - vdec->master->private; - if (hevc_ba) - hevc_ba->shift_byte_count_lo = - hevc->shift_byte_count_lo; - } -#endif - mutex_lock(&hevc->chunks_mutex); - vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); - hevc->chunk = NULL; - mutex_unlock(&hevc->chunks_mutex); - } else if (hevc->dec_result == DEC_RESULT_FORCE_EXIT) { - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: force exit\n", - __func__); - if (hevc->stat & STAT_VDEC_RUN) { - amhevc_stop(); - hevc->stat &= ~STAT_VDEC_RUN; - } - if (hevc->stat & STAT_ISR_REG) { - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0); - vdec_free_irq(VDEC_IRQ_0, (void *)hevc); - hevc->stat &= ~STAT_ISR_REG; - } - hevc_print(hevc, 0, "%s: force exit end\n", - __func__); - } - - if (hevc->stat & STAT_VDEC_RUN) { - amhevc_stop(); - hevc->stat &= ~STAT_VDEC_RUN; - } - - if (hevc->stat & STAT_TIMER_ARM) { - del_timer_sync(&hevc->timer); - hevc->stat &= ~STAT_TIMER_ARM; - } - - wait_hevc_search_done(hevc); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (hevc->switch_dvlayer_flag) { - if (vdec->slave) - vdec_set_next_sched(vdec, vdec->slave); - else if (vdec->master) - vdec_set_next_sched(vdec, vdec->master); - } else if (vdec->slave || vdec->master) - vdec_set_next_sched(vdec, vdec); -#endif - - /* mark itself has all HW resource released and input released */ - if (vdec->parallel_dec == 1) - vdec_core_finish_run(vdec, CORE_MASK_HEVC); - else - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - if (hevc->vdec_cb) - hevc->vdec_cb(hw_to_vdec(hevc), hevc->vdec_cb_arg); -} - -static int vh265_hw_ctx_restore(struct hevc_state_s *hevc) -{ - /* new to do ... */ - vh265_prot_init(hevc); - return 0; -} -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) -{ - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; - int tvp = vdec_secure(hw_to_vdec(hevc)) ? - CODEC_MM_FLAGS_TVP : 0; - bool ret = 0; - if (step == 0x12) - return 0; - else if (step == 0x11) - step = 0x12; - - if (hevc->eos) - return 0; - if (!hevc->first_sc_checked && hevc->mmu_enable) { - int size = decoder_mmu_box_sc_check(hevc->mmu_box, tvp); - hevc->first_sc_checked =1; - hevc_print(hevc, 0, - "vh265 cached=%d need_size=%d speed= %d ms\n", - size, (hevc->need_cache_size >> PAGE_SHIFT), - (int)(get_jiffies_64() - hevc->sc_start_time) * 1000/HZ); - } - if (vdec_stream_based(vdec) && (hevc->init_flag == 0) - && pre_decode_buf_level != 0) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = vdec->input.size + wp - rp; - else - level = wp - rp; - - if (level < pre_decode_buf_level) - return 0; - } - -#ifdef AGAIN_HAS_THRESHOLD - if (hevc->next_again_flag && - (!vdec_frame_based(vdec))) { - u32 parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - if (parser_wr_ptr >= hevc->pre_parser_wr_ptr && - (parser_wr_ptr - hevc->pre_parser_wr_ptr) < - again_threshold) { - int r = vdec_sync_input(vdec); - hevc_print(hevc, - PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); - return 0; - } - } -#endif - - if (disp_vframe_valve_level && - kfifo_len(&hevc->display_q) >= - disp_vframe_valve_level) { - hevc->valve_count--; - if (hevc->valve_count <= 0) - hevc->valve_count = 2; - else - return 0; - } - - ret = is_new_pic_available(hevc); - if (!ret) { - hevc_print(hevc, - PRINT_FLAG_VDEC_DETAIL, "%s=>%d\r\n", - __func__, ret); - } - -#ifdef CONSTRAIN_MAX_BUF_NUM - if (hevc->pic_list_init_flag == 3) { - if (run_ready_max_vf_only_num > 0 && - get_vf_ref_only_buf_count(hevc) >= - run_ready_max_vf_only_num - ) - ret = 0; - if (run_ready_display_q_num > 0 && - kfifo_len(&hevc->display_q) >= - run_ready_display_q_num) - ret = 0; - - /*avoid more buffers consumed when - switching resolution*/ - if (run_ready_max_buf_num == 0xff && - get_used_buf_count(hevc) >= - get_work_pic_num(hevc)) - ret = 0; - else if (run_ready_max_buf_num && - get_used_buf_count(hevc) >= - run_ready_max_buf_num) - ret = 0; - } -#endif - - if (ret) - not_run_ready[hevc->index] = 0; - else - not_run_ready[hevc->index]++; - if (vdec->parallel_dec == 1) - return ret ? (CORE_MASK_HEVC) : 0; - else - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; -} - -static void run(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *arg) -{ - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; - int r, loadr = 0; - unsigned char check_sum = 0; - - run_count[hevc->index]++; - hevc->vdec_cb_arg = arg; - hevc->vdec_cb = callback; - hevc->aux_data_dirty = 1; - hevc_reset_core(vdec); - -#ifdef AGAIN_HAS_THRESHOLD - hevc->pre_parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - hevc->next_again_flag = 0; -#endif - r = vdec_prepare_input(vdec, &hevc->chunk); - if (r < 0) { - input_empty[hevc->index]++; - hevc->dec_result = DEC_RESULT_AGAIN; - hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, - "ammvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&hevc->work); - return; - } - input_empty[hevc->index] = 0; - hevc->dec_result = DEC_RESULT_NONE; - if (vdec_frame_based(vdec) && - ((get_dbg_flag(hevc) & PRINT_FLAG_VDEC_STATUS) - || is_log_enable(hevc))) - check_sum = get_data_check_sum(hevc, r); - - if (is_log_enable(hevc)) - add_log(hevc, - "%s: size 0x%x sum 0x%x shiftbyte 0x%x", - __func__, r, - check_sum, - READ_VREG(HEVC_SHIFT_BYTE_COUNT) - ); - hevc->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, - "%s: size 0x%x sum 0x%x (%x %x %x %x %x) byte count %x\n", - __func__, r, - check_sum, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP), - hevc->start_shift_bytes - ); - if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) && - input_frame_based(vdec)) { - int jj; - u8 *data = NULL; - - if (!hevc->chunk->block->is_mapped) - data = codec_mm_vmap(hevc->chunk->block->start + - hevc->chunk->offset, r); - else - data = ((u8 *)hevc->chunk->block->start_virt) - + hevc->chunk->offset; - - for (jj = 0; jj < r; jj++) { - if ((jj & 0xf) == 0) - hevc_print(hevc, PRINT_FRAMEBASE_DATA, - "%06x:", jj); - hevc_print_cont(hevc, PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - hevc_print_cont(hevc, PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hevc->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - if (tee_enabled() && hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->swap_addr); - } else { - if (hevc->mmu_enable) - if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) - loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, - "h265_mmu", hevc->fw->data); - else { - if (!hevc->is_4k) { - /* if an older version of the fw was loaded, */ - /* needs try to load noswap fw because the */ - /* old fw package dose not contain the swap fw.*/ - loadr = amhevc_vdec_loadmc_ex( - VFORMAT_HEVC, vdec, - "hevc_mmu_swap", - hevc->fw->data); - if (loadr < 0) - loadr = amhevc_vdec_loadmc_ex( - VFORMAT_HEVC, vdec, - "h265_mmu", - hevc->fw->data); - else - hevc->is_swap = true; - } else - loadr = amhevc_vdec_loadmc_ex( - VFORMAT_HEVC, vdec, - "h265_mmu", hevc->fw->data); - } - else - loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, - NULL, hevc->fw->data); - - if (loadr < 0) { - amhevc_disable(); - hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", loadr); - hevc->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hevc->work); - return; - } - - if (tee_enabled() && hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) - hevc->swap_addr = READ_VREG(HEVC_STREAM_SWAP_BUFFER2); -#ifdef DETREFILL_ENABLE - if (hevc->is_swap && - get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) - init_detrefill_buf(hevc); -#endif - vdec->mc_loaded = 1; - vdec->mc_type = VFORMAT_HEVC; - } - if (vh265_hw_ctx_restore(hevc) < 0) { - vdec_schedule_work(&hevc->work); - return; - } - vdec_enable_input(vdec); - - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - - if (vdec_frame_based(vdec)) { - WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); - r = hevc->chunk->size + - (hevc->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - hevc->decode_size = r; - } -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else { - if (vdec->master || vdec->slave) - WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, - hevc->shift_byte_count_lo); - } -#endif - WRITE_VREG(HEVC_DECODE_SIZE, r); - /*WRITE_VREG(HEVC_DECODE_COUNT, hevc->decode_idx);*/ - hevc->init_flag = 1; - - if (hevc->pic_list_init_flag == 3) - init_pic_list_hw(hevc); - - backup_decode_state(hevc); - - start_process_time(hevc); - mod_timer(&hevc->timer, jiffies); - hevc->stat |= STAT_TIMER_ARM; - hevc->stat |= STAT_ISR_REG; - amhevc_start(); - hevc->stat |= STAT_VDEC_RUN; -} - -static void reset(struct vdec_s *vdec) -{ - - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; - - hevc_print(hevc, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); - -} - -static irqreturn_t vh265_irq_cb(struct vdec_s *vdec, int irq) -{ - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; - - return vh265_isr(0, hevc); -} - -static irqreturn_t vh265_threaded_irq_cb(struct vdec_s *vdec, int irq) -{ - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; - - return vh265_isr_thread_fn(0, hevc); -} -#endif - -static int amvdec_h265_probe(struct platform_device *pdev) -{ -#ifdef MULTI_INSTANCE_SUPPORT - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; -#else - struct vdec_dev_reg_s *pdata = - (struct vdec_dev_reg_s *)pdev->dev.platform_data; -#endif - int ret; - struct hevc_state_s *hevc; - - hevc = vmalloc(sizeof(struct hevc_state_s)); - if (hevc == NULL) { - hevc_print(hevc, 0, "%s vmalloc hevc failed\r\n", __func__); - return -ENOMEM; - } - gHevc = hevc; - if ((debug & H265_NO_CHANG_DEBUG_FLAG_IN_CODE) == 0) - debug &= (~(H265_DEBUG_DIS_LOC_ERROR_PROC | - H265_DEBUG_DIS_SYS_ERROR_PROC)); - memset(hevc, 0, sizeof(struct hevc_state_s)); - if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, "%s\r\n", __func__); - mutex_lock(&vh265_mutex); - - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) && - (parser_sei_enable & 0x100) == 0) - parser_sei_enable = 7; /*old 1*/ - hevc->m_ins_flag = 0; - hevc->init_flag = 0; - hevc->first_sc_checked = 0; - hevc->uninit_list = 0; - hevc->fatal_error = 0; - hevc->show_frame_num = 0; - hevc->frameinfo_enable = 1; -#ifdef MULTI_INSTANCE_SUPPORT - hevc->platform_dev = pdev; - platform_set_drvdata(pdev, pdata); -#endif - - if (pdata == NULL) { - hevc_print(hevc, 0, - "\namvdec_h265 memory resource undefined.\n"); - vfree(hevc); - mutex_unlock(&vh265_mutex); - return -EFAULT; - } - if (mmu_enable_force == 0) { - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL - || double_write_mode == 0x10) - hevc->mmu_enable = 0; - else - hevc->mmu_enable = 1; - } - if (init_mmu_buffers(hevc)) { - hevc_print(hevc, 0, - "\n 265 mmu init failed!\n"); - vfree(hevc); - mutex_unlock(&vh265_mutex); - return -EFAULT; - } - - ret = decoder_bmmu_box_alloc_buf_phy(hevc->bmmu_box, BMMU_WORKSPACE_ID, - work_buf_size, DRIVER_NAME, &hevc->buf_start); - if (ret < 0) { - uninit_mmu_buffers(hevc); - vfree(hevc); - mutex_unlock(&vh265_mutex); - return ret; - } - hevc->buf_size = work_buf_size; - - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "===H.265 decoder mem resource 0x%lx size 0x%x\n", - hevc->buf_start, hevc->buf_size); - } - - if (pdata->sys_info) - hevc->vh265_amstream_dec_info = *pdata->sys_info; - else { - hevc->vh265_amstream_dec_info.width = 0; - hevc->vh265_amstream_dec_info.height = 0; - hevc->vh265_amstream_dec_info.rate = 30; - } -#ifndef MULTI_INSTANCE_SUPPORT - if (pdata->flag & DEC_FLAG_HEVC_WORKAROUND) { - workaround_enable |= 3; - hevc_print(hevc, 0, - "amvdec_h265 HEVC_WORKAROUND flag set.\n"); - } else - workaround_enable &= ~3; -#endif - hevc->cma_dev = pdata->cma_dev; - vh265_vdec_info_init(); - -#ifdef MULTI_INSTANCE_SUPPORT - pdata->private = hevc; - pdata->dec_status = vh265_dec_status; - pdata->set_isreset = vh265_set_isreset; - is_reset = 0; - if (vh265_init(pdata) < 0) { -#else - if (vh265_init(hevc) < 0) { -#endif - hevc_print(hevc, 0, - "\namvdec_h265 init failed.\n"); - hevc_local_uninit(hevc); - uninit_mmu_buffers(hevc); - vfree(hevc); - pdata->dec_status = NULL; - mutex_unlock(&vh265_mutex); - return -ENODEV; - } - /*set the max clk for smooth playing...*/ - hevc_source_changed(VFORMAT_HEVC, - 3840, 2160, 60); - mutex_unlock(&vh265_mutex); - - return 0; -} - -static int amvdec_h265_remove(struct platform_device *pdev) -{ - struct hevc_state_s *hevc = gHevc; - - if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, "%s\r\n", __func__); - - mutex_lock(&vh265_mutex); - - vh265_stop(hevc); - - hevc_source_changed(VFORMAT_HEVC, 0, 0, 0); - - -#ifdef DEBUG_PTS - hevc_print(hevc, 0, - "pts missed %ld, pts hit %ld, duration %d\n", - hevc->pts_missed, hevc->pts_hit, hevc->frame_dur); -#endif - - vfree(hevc); - hevc = NULL; - gHevc = NULL; - - mutex_unlock(&vh265_mutex); - - return 0; -} -/****************************************/ - -static struct platform_driver amvdec_h265_driver = { - .probe = amvdec_h265_probe, - .remove = amvdec_h265_remove, -#ifdef CONFIG_PM - .suspend = amhevc_suspend, - .resume = amhevc_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -#ifdef MULTI_INSTANCE_SUPPORT -static void vh265_dump_state(struct vdec_s *vdec) -{ - int i; - struct hevc_state_s *hevc = - (struct hevc_state_s *)vdec->private; - hevc_print(hevc, 0, - "====== %s\n", __func__); - - hevc_print(hevc, 0, - "width/height (%d/%d), reorder_pic_num %d buf count(bufspec size) %d, video_signal_type 0x%x, is_swap %d\n", - hevc->frame_width, - hevc->frame_height, - hevc->sps_num_reorder_pics_0, - get_work_pic_num(hevc), - hevc->video_signal_type_debug, - hevc->is_swap - ); - - hevc_print(hevc, 0, - "is_framebase(%d), eos %d, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n", - input_frame_based(vdec), - hevc->eos, - hevc->dec_result, - decode_frame_count[hevc->index], - display_frame_count[hevc->index], - run_count[hevc->index], - not_run_ready[hevc->index], - input_empty[hevc->index] - ); - - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - hevc_print(hevc, 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - - hevc_print(hevc, 0, - "%s, newq(%d/%d), dispq(%d/%d), vf prepare/get/put (%d/%d/%d), pic_list_init_flag(%d), is_new_pic_available(%d)\n", - __func__, - kfifo_len(&hevc->newframe_q), - VF_POOL_SIZE, - kfifo_len(&hevc->display_q), - VF_POOL_SIZE, - hevc->vf_pre_count, - hevc->vf_get_count, - hevc->vf_put_count, - hevc->pic_list_init_flag, - is_new_pic_available(hevc) - ); - - dump_pic_list(hevc); - - for (i = 0; i < BUF_POOL_SIZE; i++) { - hevc_print(hevc, 0, - "Buf(%d) start_adr 0x%x size 0x%x used %d\n", - i, - hevc->m_BUF[i].start_adr, - hevc->m_BUF[i].size, - hevc->m_BUF[i].used_flag); - } - - for (i = 0; i < MAX_REF_PIC_NUM; i++) { - hevc_print(hevc, 0, - "mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n", - i, - hevc->m_mv_BUF[i].start_adr, - hevc->m_mv_BUF[i].size, - hevc->m_mv_BUF[i].used_flag); - } - - hevc_print(hevc, 0, - "HEVC_DEC_STATUS_REG=0x%x\n", - READ_VREG(HEVC_DEC_STATUS_REG)); - hevc_print(hevc, 0, - "HEVC_MPC_E=0x%x\n", - READ_VREG(HEVC_MPC_E)); - hevc_print(hevc, 0, - "HEVC_DECODE_MODE=0x%x\n", - READ_VREG(HEVC_DECODE_MODE)); - hevc_print(hevc, 0, - "HEVC_DECODE_MODE2=0x%x\n", - READ_VREG(HEVC_DECODE_MODE2)); - hevc_print(hevc, 0, - "NAL_SEARCH_CTL=0x%x\n", - READ_VREG(NAL_SEARCH_CTL)); - hevc_print(hevc, 0, - "HEVC_PARSER_LCU_START=0x%x\n", - READ_VREG(HEVC_PARSER_LCU_START)); - hevc_print(hevc, 0, - "HEVC_DECODE_SIZE=0x%x\n", - READ_VREG(HEVC_DECODE_SIZE)); - hevc_print(hevc, 0, - "HEVC_SHIFT_BYTE_COUNT=0x%x\n", - READ_VREG(HEVC_SHIFT_BYTE_COUNT)); - hevc_print(hevc, 0, - "HEVC_STREAM_START_ADDR=0x%x\n", - READ_VREG(HEVC_STREAM_START_ADDR)); - hevc_print(hevc, 0, - "HEVC_STREAM_END_ADDR=0x%x\n", - READ_VREG(HEVC_STREAM_END_ADDR)); - hevc_print(hevc, 0, - "HEVC_STREAM_LEVEL=0x%x\n", - READ_VREG(HEVC_STREAM_LEVEL)); - hevc_print(hevc, 0, - "HEVC_STREAM_WR_PTR=0x%x\n", - READ_VREG(HEVC_STREAM_WR_PTR)); - hevc_print(hevc, 0, - "HEVC_STREAM_RD_PTR=0x%x\n", - READ_VREG(HEVC_STREAM_RD_PTR)); - hevc_print(hevc, 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - hevc_print(hevc, 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - - if (input_frame_based(vdec) && - (get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) - ) { - int jj; - if (hevc->chunk && hevc->chunk->block && - hevc->chunk->size > 0) { - u8 *data = NULL; - if (!hevc->chunk->block->is_mapped) - data = codec_mm_vmap(hevc->chunk->block->start + - hevc->chunk->offset, hevc->chunk->size); - else - data = ((u8 *)hevc->chunk->block->start_virt) - + hevc->chunk->offset; - hevc_print(hevc, 0, - "frame data size 0x%x\n", - hevc->chunk->size); - for (jj = 0; jj < hevc->chunk->size; jj++) { - if ((jj & 0xf) == 0) - hevc_print(hevc, - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - hevc_print_cont(hevc, - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - hevc_print_cont(hevc, - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hevc->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } - -} - - -static int ammvdec_h265_probe(struct platform_device *pdev) -{ - - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct hevc_state_s *hevc = NULL; - int ret; -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - int config_val; -#endif - if (pdata == NULL) { - pr_info("\nammvdec_h265 memory resource undefined.\n"); - return -EFAULT; - } - - /* hevc = (struct hevc_state_s *)devm_kzalloc(&pdev->dev, - sizeof(struct hevc_state_s), GFP_KERNEL); */ - hevc = vmalloc(sizeof(struct hevc_state_s)); - memset(hevc, 0, sizeof(struct hevc_state_s)); - if (hevc == NULL) { - pr_info("\nammvdec_h265 device data allocation failed\n"); - return -ENOMEM; - } - pdata->private = hevc; - pdata->dec_status = vh265_dec_status; - /* pdata->set_trickmode = set_trickmode; */ - pdata->run_ready = run_ready; - pdata->run = run; - pdata->reset = reset; - pdata->irq_handler = vh265_irq_cb; - pdata->threaded_irq_handler = vh265_threaded_irq_cb; - pdata->dump_state = vh265_dump_state; - - hevc->index = pdev->id; - hevc->m_ins_flag = 1; - - if (pdata->use_vfm_path) { - snprintf(pdata->vf_provider_name, - VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - hevc->frameinfo_enable = 1; - } -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec_dual(pdata)) { - struct hevc_state_s *hevc_pair = NULL; - - if (dv_toggle_prov_name) /*debug purpose*/ - snprintf(pdata->vf_provider_name, - VDEC_PROVIDER_NAME_SIZE, - (pdata->master) ? VFM_DEC_DVBL_PROVIDER_NAME : - VFM_DEC_DVEL_PROVIDER_NAME); - else - snprintf(pdata->vf_provider_name, - VDEC_PROVIDER_NAME_SIZE, - (pdata->master) ? VFM_DEC_DVEL_PROVIDER_NAME : - VFM_DEC_DVBL_PROVIDER_NAME); - hevc->dolby_enhance_flag = pdata->master ? 1 : 0; - if (pdata->master) - hevc_pair = (struct hevc_state_s *) - pdata->master->private; - else if (pdata->slave) - hevc_pair = (struct hevc_state_s *) - pdata->slave->private; - if (hevc_pair) - hevc->shift_byte_count_lo = - hevc_pair->shift_byte_count_lo; - } -#endif - else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); - - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vh265_vf_provider, pdata); - - hevc->provider_name = pdata->vf_provider_name; - platform_set_drvdata(pdev, pdata); - - hevc->platform_dev = pdev; - - if (((get_dbg_flag(hevc) & IGNORE_PARAM_FROM_CONFIG) == 0) && - pdata->config && pdata->config_len) { -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - /*use ptr config for doubel_write_mode, etc*/ - hevc_print(hevc, 0, "pdata->config=%s\n", pdata->config); - - if (get_config_int(pdata->config, "hevc_double_write_mode", - &config_val) == 0) - hevc->double_write_mode = config_val; - else - hevc->double_write_mode = double_write_mode; - - if (get_config_int(pdata->config, "save_buffer_mode", - &config_val) == 0) - hevc->save_buffer_mode = config_val; - else - hevc->save_buffer_mode = 0; - - /*use ptr config for max_pic_w, etc*/ - if (get_config_int(pdata->config, "hevc_buf_width", - &config_val) == 0) { - hevc->max_pic_w = config_val; - } - if (get_config_int(pdata->config, "hevc_buf_height", - &config_val) == 0) { - hevc->max_pic_h = config_val; - } - -#endif - } else { - if (pdata->sys_info) - hevc->vh265_amstream_dec_info = *pdata->sys_info; - else { - hevc->vh265_amstream_dec_info.width = 0; - hevc->vh265_amstream_dec_info.height = 0; - hevc->vh265_amstream_dec_info.rate = 30; - } - hevc->double_write_mode = double_write_mode; - } - if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2) - hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2; - else - hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; - - if (mmu_enable_force == 0) { - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL) - hevc->mmu_enable = 0; - else - hevc->mmu_enable = 1; - } - - if (init_mmu_buffers(hevc) < 0) { - hevc_print(hevc, 0, - "\n 265 mmu init failed!\n"); - mutex_unlock(&vh265_mutex); - /* devm_kfree(&pdev->dev, (void *)hevc);*/ - if (hevc) - vfree((void *)hevc); - pdata->dec_status = NULL; - return -EFAULT; - } -#if 0 - hevc->buf_start = pdata->mem_start; - hevc->buf_size = pdata->mem_end - pdata->mem_start + 1; -#else - - ret = decoder_bmmu_box_alloc_buf_phy(hevc->bmmu_box, - BMMU_WORKSPACE_ID, work_buf_size, - DRIVER_NAME, &hevc->buf_start); - if (ret < 0) { - uninit_mmu_buffers(hevc); - /* devm_kfree(&pdev->dev, (void *)hevc); */ - if (hevc) - vfree((void *)hevc); - pdata->dec_status = NULL; - mutex_unlock(&vh265_mutex); - return ret; - } - hevc->buf_size = work_buf_size; -#endif - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) && - (parser_sei_enable & 0x100) == 0) - parser_sei_enable = 7; - hevc->init_flag = 0; - hevc->first_sc_checked = 0; - hevc->uninit_list = 0; - hevc->fatal_error = 0; - hevc->show_frame_num = 0; - - /* - *hevc->mc_buf_spec.buf_end = pdata->mem_end + 1; - *for (i = 0; i < WORK_BUF_SPEC_NUM; i++) - * amvh265_workbuff_spec[i].start_adr = pdata->mem_start; - */ - if (get_dbg_flag(hevc)) { - hevc_print(hevc, 0, - "===H.265 decoder mem resource 0x%lx size 0x%x\n", - hevc->buf_start, hevc->buf_size); - } - - hevc_print(hevc, 0, - "dynamic_buf_num_margin=%d\n", - hevc->dynamic_buf_num_margin); - hevc_print(hevc, 0, - "double_write_mode=%d\n", - hevc->double_write_mode); - - hevc->cma_dev = pdata->cma_dev; - - if (vh265_init(pdata) < 0) { - hevc_print(hevc, 0, - "\namvdec_h265 init failed.\n"); - hevc_local_uninit(hevc); - uninit_mmu_buffers(hevc); - /* devm_kfree(&pdev->dev, (void *)hevc); */ - if (hevc) - vfree((void *)hevc); - pdata->dec_status = NULL; - return -ENODEV; - } - - vdec_set_prepare_level(pdata, start_decode_buf_level); - - /*set the max clk for smooth playing...*/ - hevc_source_changed(VFORMAT_HEVC, - 3840, 2160, 60); - if (pdata->parallel_dec == 1) - vdec_core_request(pdata, CORE_MASK_HEVC); - else - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - - return 0; -} - -static int ammvdec_h265_remove(struct platform_device *pdev) -{ - struct hevc_state_s *hevc = - (struct hevc_state_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - struct vdec_s *vdec = hw_to_vdec(hevc); - - if (hevc == NULL) - return 0; - - if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, "%s\r\n", __func__); - - vmh265_stop(hevc); - - /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ - if (vdec->parallel_dec == 1) - vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); - else - vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); - - vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_DISCONNECTED); - - vfree((void *)hevc); - return 0; -} - -static struct platform_driver ammvdec_h265_driver = { - .probe = ammvdec_h265_probe, - .remove = ammvdec_h265_remove, -#ifdef CONFIG_PM - .suspend = amhevc_suspend, - .resume = amhevc_resume, -#endif - .driver = { - .name = MULTI_DRIVER_NAME, - } -}; -#endif - -static struct codec_profile_t amvdec_h265_profile = { - .name = "hevc", - .profile = "" -}; -static struct mconfig h265_configs[] = { - MC_PU32("use_cma", &use_cma), - MC_PU32("bit_depth_luma", &bit_depth_luma), - MC_PU32("bit_depth_chroma", &bit_depth_chroma), - MC_PU32("video_signal_type", &video_signal_type), -#ifdef ERROR_HANDLE_DEBUG - MC_PU32("dbg_nal_skip_flag", &dbg_nal_skip_flag), - MC_PU32("dbg_nal_skip_count", &dbg_nal_skip_count), -#endif - MC_PU32("radr", &radr), - MC_PU32("rval", &rval), - MC_PU32("dbg_cmd", &dbg_cmd), - MC_PU32("dbg_skip_decode_index", &dbg_skip_decode_index), - MC_PU32("endian", &endian), - MC_PU32("step", &step), - MC_PU32("udebug_flag", &udebug_flag), - MC_PU32("decode_pic_begin", &decode_pic_begin), - MC_PU32("slice_parse_begin", &slice_parse_begin), - MC_PU32("nal_skip_policy", &nal_skip_policy), - MC_PU32("i_only_flag", &i_only_flag), - MC_PU32("error_handle_policy", &error_handle_policy), - MC_PU32("error_handle_threshold", &error_handle_threshold), - MC_PU32("error_handle_nal_skip_threshold", - &error_handle_nal_skip_threshold), - MC_PU32("error_handle_system_threshold", - &error_handle_system_threshold), - MC_PU32("error_skip_nal_count", &error_skip_nal_count), - MC_PU32("debug", &debug), - MC_PU32("debug_mask", &debug_mask), - MC_PU32("buffer_mode", &buffer_mode), - MC_PU32("double_write_mode", &double_write_mode), - MC_PU32("buf_alloc_width", &buf_alloc_width), - MC_PU32("buf_alloc_height", &buf_alloc_height), - MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin), - MC_PU32("max_buf_num", &max_buf_num), - MC_PU32("buf_alloc_size", &buf_alloc_size), - MC_PU32("buffer_mode_dbg", &buffer_mode_dbg), - MC_PU32("mem_map_mode", &mem_map_mode), - MC_PU32("enable_mem_saving", &enable_mem_saving), - MC_PU32("force_w_h", &force_w_h), - MC_PU32("force_fps", &force_fps), - MC_PU32("max_decoding_time", &max_decoding_time), - MC_PU32("prefix_aux_buf_size", &prefix_aux_buf_size), - MC_PU32("suffix_aux_buf_size", &suffix_aux_buf_size), - MC_PU32("interlace_enable", &interlace_enable), - MC_PU32("pts_unstable", &pts_unstable), - MC_PU32("parser_sei_enable", &parser_sei_enable), - MC_PU32("start_decode_buf_level", &start_decode_buf_level), - MC_PU32("decode_timeout_val", &decode_timeout_val), -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - MC_PU32("parser_dolby_vision_enable", &parser_dolby_vision_enable), - MC_PU32("dv_toggle_prov_name", &dv_toggle_prov_name), - MC_PU32("dv_debug", &dv_debug), -#endif -}; -static struct mconfig_node decoder_265_node; - -static int __init amvdec_h265_driver_init_module(void) -{ - struct BuffInfo_s *p_buf_info; - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - p_buf_info = &amvh265_workbuff_spec[2]; - else - p_buf_info = &amvh265_workbuff_spec[1]; - } else - p_buf_info = &amvh265_workbuff_spec[0]; - - init_buff_spec(NULL, p_buf_info); - work_buf_size = - (p_buf_info->end_adr - p_buf_info->start_adr - + 0xffff) & (~0xffff); - - pr_debug("amvdec_h265 module init\n"); - error_handle_policy = 0; - -#ifdef ERROR_HANDLE_DEBUG - dbg_nal_skip_flag = 0; - dbg_nal_skip_count = 0; -#endif - udebug_flag = 0; - decode_pic_begin = 0; - slice_parse_begin = 0; - step = 0; - buf_alloc_size = 0; - -#ifdef MULTI_INSTANCE_SUPPORT - if (platform_driver_register(&ammvdec_h265_driver)) - pr_err("failed to register ammvdec_h265 driver\n"); - -#endif - if (platform_driver_register(&amvdec_h265_driver)) { - pr_err("failed to register amvdec_h265 driver\n"); - return -ENODEV; - } -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ - if (!has_hevc_vdec()) { - /* not support hevc */ - amvdec_h265_profile.name = "hevc_unsupport"; - } - if (vdec_is_support_4k()) { - if (is_meson_m8m2_cpu()) { - /* m8m2 support 4k */ - amvdec_h265_profile.profile = "4k"; - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - amvdec_h265_profile.profile = - "8k, 8bit, 10bit, dwrite, compressed"; - }else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) { - amvdec_h265_profile.profile = - "4k, 8bit, 10bit, dwrite, compressed"; - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_MG9TV) - amvdec_h265_profile.profile = "4k"; - } -#endif - if (codec_mm_get_total_size() < 80 * SZ_1M) { - pr_info("amvdec_h265 default mmu enabled.\n"); - mmu_enable = 1; - } - - vcodec_profile_register(&amvdec_h265_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &decoder_265_node, - "h265", h265_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_h265_driver_remove_module(void) -{ - pr_debug("amvdec_h265 module remove.\n"); - -#ifdef MULTI_INSTANCE_SUPPORT - platform_driver_unregister(&ammvdec_h265_driver); -#endif - platform_driver_unregister(&amvdec_h265_driver); -} - -/****************************************/ -/* - *module_param(stat, uint, 0664); - *MODULE_PARM_DESC(stat, "\n amvdec_h265 stat\n"); - */ -module_param(use_cma, uint, 0664); -MODULE_PARM_DESC(use_cma, "\n amvdec_h265 use_cma\n"); - -module_param(bit_depth_luma, uint, 0664); -MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_h265 bit_depth_luma\n"); - -module_param(bit_depth_chroma, uint, 0664); -MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_h265 bit_depth_chroma\n"); - -module_param(video_signal_type, uint, 0664); -MODULE_PARM_DESC(video_signal_type, "\n amvdec_h265 video_signal_type\n"); - -#ifdef ERROR_HANDLE_DEBUG -module_param(dbg_nal_skip_flag, uint, 0664); -MODULE_PARM_DESC(dbg_nal_skip_flag, "\n amvdec_h265 dbg_nal_skip_flag\n"); - -module_param(dbg_nal_skip_count, uint, 0664); -MODULE_PARM_DESC(dbg_nal_skip_count, "\n amvdec_h265 dbg_nal_skip_count\n"); -#endif - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\n radr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\n rval\n"); - -module_param(dbg_cmd, uint, 0664); -MODULE_PARM_DESC(dbg_cmd, "\n dbg_cmd\n"); - -module_param(dump_nal, uint, 0664); -MODULE_PARM_DESC(dump_nal, "\n dump_nal\n"); - -module_param(dbg_skip_decode_index, uint, 0664); -MODULE_PARM_DESC(dbg_skip_decode_index, "\n dbg_skip_decode_index\n"); - -module_param(endian, uint, 0664); -MODULE_PARM_DESC(endian, "\n rval\n"); - -module_param(step, uint, 0664); -MODULE_PARM_DESC(step, "\n amvdec_h265 step\n"); - -module_param(decode_pic_begin, uint, 0664); -MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_h265 decode_pic_begin\n"); - -module_param(slice_parse_begin, uint, 0664); -MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_h265 slice_parse_begin\n"); - -module_param(nal_skip_policy, uint, 0664); -MODULE_PARM_DESC(nal_skip_policy, "\n amvdec_h265 nal_skip_policy\n"); - -module_param(i_only_flag, uint, 0664); -MODULE_PARM_DESC(i_only_flag, "\n amvdec_h265 i_only_flag\n"); - -module_param(fast_output_enable, uint, 0664); -MODULE_PARM_DESC(fast_output_enable, "\n amvdec_h265 fast_output_enable\n"); - -module_param(error_handle_policy, uint, 0664); -MODULE_PARM_DESC(error_handle_policy, "\n amvdec_h265 error_handle_policy\n"); - -module_param(error_handle_threshold, uint, 0664); -MODULE_PARM_DESC(error_handle_threshold, - "\n amvdec_h265 error_handle_threshold\n"); - -module_param(error_handle_nal_skip_threshold, uint, 0664); -MODULE_PARM_DESC(error_handle_nal_skip_threshold, - "\n amvdec_h265 error_handle_nal_skip_threshold\n"); - -module_param(error_handle_system_threshold, uint, 0664); -MODULE_PARM_DESC(error_handle_system_threshold, - "\n amvdec_h265 error_handle_system_threshold\n"); - -module_param(error_skip_nal_count, uint, 0664); -MODULE_PARM_DESC(error_skip_nal_count, - "\n amvdec_h265 error_skip_nal_count\n"); - -module_param(debug, uint, 0664); -MODULE_PARM_DESC(debug, "\n amvdec_h265 debug\n"); - -module_param(debug_mask, uint, 0664); -MODULE_PARM_DESC(debug_mask, "\n amvdec_h265 debug mask\n"); - -module_param(log_mask, uint, 0664); -MODULE_PARM_DESC(log_mask, "\n amvdec_h265 log_mask\n"); - -module_param(buffer_mode, uint, 0664); -MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n"); - -module_param(double_write_mode, uint, 0664); -MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); - -module_param(buf_alloc_width, uint, 0664); -MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); - -module_param(buf_alloc_height, uint, 0664); -MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n"); - -module_param(dynamic_buf_num_margin, uint, 0664); -MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); - -module_param(max_buf_num, uint, 0664); -MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); - -module_param(buf_alloc_size, uint, 0664); -MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); - -#ifdef CONSTRAIN_MAX_BUF_NUM -module_param(run_ready_max_vf_only_num, uint, 0664); -MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); - -module_param(run_ready_display_q_num, uint, 0664); -MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); - -module_param(run_ready_max_buf_num, uint, 0664); -MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); -#endif - -#if 0 -module_param(re_config_pic_flag, uint, 0664); -MODULE_PARM_DESC(re_config_pic_flag, "\n re_config_pic_flag\n"); -#endif - -module_param(buffer_mode_dbg, uint, 0664); -MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n"); - -module_param(mem_map_mode, uint, 0664); -MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); - -module_param(enable_mem_saving, uint, 0664); -MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n"); - -module_param(force_w_h, uint, 0664); -MODULE_PARM_DESC(force_w_h, "\n force_w_h\n"); - -module_param(force_fps, uint, 0664); -MODULE_PARM_DESC(force_fps, "\n force_fps\n"); - -module_param(max_decoding_time, uint, 0664); -MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n"); - -module_param(prefix_aux_buf_size, uint, 0664); -MODULE_PARM_DESC(prefix_aux_buf_size, "\n prefix_aux_buf_size\n"); - -module_param(suffix_aux_buf_size, uint, 0664); -MODULE_PARM_DESC(suffix_aux_buf_size, "\n suffix_aux_buf_size\n"); - -module_param(interlace_enable, uint, 0664); -MODULE_PARM_DESC(interlace_enable, "\n interlace_enable\n"); -module_param(pts_unstable, uint, 0664); -MODULE_PARM_DESC(pts_unstable, "\n amvdec_h265 pts_unstable\n"); -module_param(parser_sei_enable, uint, 0664); -MODULE_PARM_DESC(parser_sei_enable, "\n parser_sei_enable\n"); - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -module_param(parser_dolby_vision_enable, uint, 0664); -MODULE_PARM_DESC(parser_dolby_vision_enable, - "\n parser_dolby_vision_enable\n"); - -module_param(dolby_meta_with_el, uint, 0664); -MODULE_PARM_DESC(dolby_meta_with_el, - "\n dolby_meta_with_el\n"); - -module_param(dolby_el_flush_th, uint, 0664); -MODULE_PARM_DESC(dolby_el_flush_th, - "\n dolby_el_flush_th\n"); -#endif -module_param(mmu_enable, uint, 0664); -MODULE_PARM_DESC(mmu_enable, "\n mmu_enable\n"); - -module_param(mmu_enable_force, uint, 0664); -MODULE_PARM_DESC(mmu_enable_force, "\n mmu_enable_force\n"); - -#ifdef MULTI_INSTANCE_SUPPORT -module_param(start_decode_buf_level, int, 0664); -MODULE_PARM_DESC(start_decode_buf_level, - "\n h265 start_decode_buf_level\n"); - -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, - "\n h265 decode_timeout_val\n"); - -module_param(data_resend_policy, uint, 0664); -MODULE_PARM_DESC(data_resend_policy, - "\n h265 data_resend_policy\n"); - -module_param_array(decode_frame_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(display_frame_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(max_process_time, uint, - &max_decode_instance_num, 0664); - -module_param_array(max_get_frame_interval, - uint, &max_decode_instance_num, 0664); - -module_param_array(run_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(input_empty, uint, - &max_decode_instance_num, 0664); - -module_param_array(not_run_ready, uint, - &max_decode_instance_num, 0664); - -module_param_array(ref_frame_mark_flag, uint, - &max_decode_instance_num, 0664); - -#endif -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION -module_param(dv_toggle_prov_name, uint, 0664); -MODULE_PARM_DESC(dv_toggle_prov_name, "\n dv_toggle_prov_name\n"); - -module_param(dv_debug, uint, 0664); -MODULE_PARM_DESC(dv_debug, "\n dv_debug\n"); - -module_param(force_bypass_dvenl, uint, 0664); -MODULE_PARM_DESC(force_bypass_dvenl, "\n force_bypass_dvenl\n"); -#endif - -#ifdef AGAIN_HAS_THRESHOLD -module_param(again_threshold, uint, 0664); -MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); -#endif - -module_param(force_disp_pic_index, int, 0664); -MODULE_PARM_DESC(force_disp_pic_index, - "\n amvdec_h265 force_disp_pic_index\n"); - -module_param(frmbase_cont_bitlevel, uint, 0664); -MODULE_PARM_DESC(frmbase_cont_bitlevel, "\n frmbase_cont_bitlevel\n"); - -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); - -module_param(udebug_pause_pos, uint, 0664); -MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); - -module_param(udebug_pause_val, uint, 0664); -MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); - -module_param(pre_decode_buf_level, int, 0664); -MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n"); - -module_param(udebug_pause_decode_idx, uint, 0664); -MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); - -module_param(disp_vframe_valve_level, uint, 0664); -MODULE_PARM_DESC(disp_vframe_valve_level, "\n disp_vframe_valve_level\n"); - -module_init(amvdec_h265_driver_init_module); -module_exit(amvdec_h265_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC h265 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h deleted file mode 100644 index 11de11a22bcd..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * drivers/amlogic/amports/vh265.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VH265_H -#define VH265_H - -extern u32 get_blackout_policy(void); - -extern s32 vh265_init(void); - -extern s32 vh265_release(void); - -#endif /* VMPEG4_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/Makefile deleted file mode 100644 index ab91854d49d4..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG) += amvdec_mjpeg.o -amvdec_mjpeg-objs += vmjpeg.o - -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI) += amvdec_mmjpeg.o -amvdec_mmjpeg-objs += vmjpeg_multi.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c deleted file mode 100644 index 1c69a5a41fd9..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c +++ /dev/null @@ -1,969 +0,0 @@ -/* - * drivers/amlogic/amports/vmjpeg.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../../../stream_input/amports/amports_priv.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include - -#include - - -#ifdef CONFIG_AM_VDEC_MJPEG_LOG -#define AMLOG -#define LOG_LEVEL_VAR amlog_level_vmjpeg -#define LOG_MASK_VAR amlog_mask_vmjpeg -#define LOG_LEVEL_ERROR 0 -#define LOG_LEVEL_INFO 1 -#define LOG_LEVEL_DESC "0:ERROR, 1:INFO" -#endif -#include -MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); - -#include "../utils/amvdec.h" -#include "../utils/firmware.h" - -#define DRIVER_NAME "amvdec_mjpeg" -#define MODULE_NAME "amvdec_mjpeg" - -/* protocol register usage - * AV_SCRATCH_0 - AV_SCRATCH_1 : initial display buffer fifo - * AV_SCRATCH_2 - AV_SCRATCH_3 : decoder settings - * AV_SCRATCH_4 - AV_SCRATCH_7 : display buffer spec - * AV_SCRATCH_8 - AV_SCRATCH_9 : amrisc/host display buffer management - * AV_SCRATCH_a : time stamp - */ - -#define MREG_DECODE_PARAM AV_SCRATCH_2 /* bit 0-3: pico_addr_mode */ -/* bit 15-4: reference height */ -#define MREG_TO_AMRISC AV_SCRATCH_8 -#define MREG_FROM_AMRISC AV_SCRATCH_9 -#define MREG_FRAME_OFFSET AV_SCRATCH_A - -#define PICINFO_BUF_IDX_MASK 0x0007 -#define PICINFO_AVI1 0x0080 -#define PICINFO_INTERLACE 0x0020 -#define PICINFO_INTERLACE_AVI1_BOT 0x0010 -#define PICINFO_INTERLACE_FIRST 0x0010 - -#define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 4 -#define MAX_BMMU_BUFFER_NUM DECODE_BUFFER_NUM_MAX -#define PUT_INTERVAL (HZ/100) - -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ -/* #define NV21 */ -#endif -static DEFINE_MUTEX(vmjpeg_mutex); - -static struct dec_sysinfo vmjpeg_amstream_dec_info; - -static struct vframe_s *vmjpeg_vf_peek(void *); -static struct vframe_s *vmjpeg_vf_get(void *); -static void vmjpeg_vf_put(struct vframe_s *, void *); -static int vmjpeg_vf_states(struct vframe_states *states, void *); -static int vmjpeg_event_cb(int type, void *data, void *private_data); - -static int vmjpeg_prot_init(void); -static void vmjpeg_local_init(void); - -static const char vmjpeg_dec_id[] = "vmjpeg-dev"; -static struct vdec_info *gvs; -static struct work_struct set_clk_work; - -#define PROVIDER_NAME "decoder.mjpeg" -static const struct vframe_operations_s vmjpeg_vf_provider = { - .peek = vmjpeg_vf_peek, - .get = vmjpeg_vf_get, - .put = vmjpeg_vf_put, - .event_cb = vmjpeg_event_cb, - .vf_states = vmjpeg_vf_states, -}; -static void *mm_blk_handle; -static struct vframe_provider_s vmjpeg_vf_prov; - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static struct vframe_s vfpool[VF_POOL_SIZE]; -static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; - -static u32 frame_width, frame_height, frame_dur; -static u32 saved_resolution; -static struct timer_list recycle_timer; -static u32 stat; -static u32 buf_size = 32 * 1024 * 1024; -static DEFINE_SPINLOCK(lock); -static bool is_reset; - -static inline u32 index2canvas0(u32 index) -{ - const u32 canvas_tab[4] = { -#ifdef NV21 - 0x010100, 0x030302, 0x050504, 0x070706 -#else - 0x020100, 0x050403, 0x080706, 0x0b0a09 -#endif - }; - - return canvas_tab[index]; -} - -static inline u32 index2canvas1(u32 index) -{ - const u32 canvas_tab[4] = { -#ifdef NV21 - 0x0d0d0c, 0x0f0f0e, 0x171716, 0x191918 -#else - 0x0e0d0c, 0x181716, 0x222120, 0x252423 -#endif - }; - - return canvas_tab[index]; -} - -static void set_frame_info(struct vframe_s *vf) -{ - vf->width = frame_width; - vf->height = frame_height; - vf->duration = frame_dur; - vf->ratio_control = 0; - vf->duration_pulldown = 0; - vf->flag = 0; -} - -static irqreturn_t vmjpeg_isr(int irq, void *dev_id) -{ - u32 reg, offset, pts, pts_valid = 0; - struct vframe_s *vf = NULL; - u64 pts_us64; - u32 frame_size; - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - reg = READ_VREG(MREG_FROM_AMRISC); - - if (reg & PICINFO_BUF_IDX_MASK) { - offset = READ_VREG(MREG_FRAME_OFFSET); - - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, - &frame_size, 0, &pts_us64) == 0) - pts_valid = 1; - - if ((reg & PICINFO_INTERLACE) == 0) { - u32 index = ((reg & PICINFO_BUF_IDX_MASK) - 1) & 3; - - if (index >= DECODE_BUFFER_NUM_MAX) { - pr_err("fatal error, invalid buffer index."); - return IRQ_HANDLED; - } - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info( - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - set_frame_info(vf); - vf->signal_type = 0; - vf->index = index; -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas0(index); - vf->pts = (pts_valid) ? pts : 0; - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - vf->orientation = 0; - vf->type_original = vf->type; - vfbuf_use[index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - index); - - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, 0, offset); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - } else { - u32 index = ((reg & PICINFO_BUF_IDX_MASK) - 1) & 3; - - if (index >= DECODE_BUFFER_NUM_MAX) { - pr_info("fatal error, invalid buffer index."); - return IRQ_HANDLED; - } - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - set_frame_info(vf); - vf->signal_type = 0; - vf->index = index; -#if 0 - if (reg & PICINFO_AVI1) { - /* AVI1 format */ - if (reg & PICINFO_INTERLACE_AVI1_BOT) { - vf->type = - VIDTYPE_INTERLACE_BOTTOM | - VIDTYPE_INTERLACE_FIRST; - } else - vf->type = VIDTYPE_INTERLACE_TOP; - } else { - if (reg & PICINFO_INTERLACE_FIRST) { - vf->type = - VIDTYPE_INTERLACE_TOP | - VIDTYPE_INTERLACE_FIRST; - } else - vf->type = VIDTYPE_INTERLACE_BOTTOM; - } - - vf->type |= VIDTYPE_VIU_FIELD; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->duration >>= 1; - vf->canvas0Addr = vf->canvas1Addr = - index2canvas0(index); - vf->orientation = 0; - if ((vf->type & VIDTYPE_INTERLACE_FIRST) && - (pts_valid)) - vf->pts = pts; - else - vf->pts = 0; - - vfbuf_use[index]++; - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); -#else - /* send whole frame by weaving top & bottom field */ -#ifdef NV21 - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE; -#endif - vf->canvas0Addr = index2canvas0(index); - vf->canvas1Addr = index2canvas1(index); - vf->orientation = 0; - if (pts_valid) { - vf->pts = pts; - vf->pts_us64 = pts_us64; - } else { - vf->pts = 0; - vf->pts_us64 = 0; - } - vf->type_original = vf->type; - vfbuf_use[index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - index); - - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, 0, offset); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); -#endif - } - - WRITE_VREG(MREG_FROM_AMRISC, 0); - } - - return IRQ_HANDLED; -} - -static struct vframe_s *vmjpeg_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vmjpeg_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg) -{ - kfifo_put(&recycle_q, (const struct vframe_s *)vf); -} - -static int vmjpeg_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vmjpeg_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vmjpeg_local_init(); - vmjpeg_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vmjpeg_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -static int vmjpeg_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - - return 0; -} -static void mjpeg_set_clk(struct work_struct *work) -{ - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_MJPEG, - frame_width, frame_height, fps); - } -} - -static void vmjpeg_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - - while (!kfifo_is_empty(&recycle_q) && - (READ_VREG(MREG_TO_AMRISC) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < DECODE_BUFFER_NUM_MAX) - && (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(MREG_TO_AMRISC, vf->index + 1); - vf->index = DECODE_BUFFER_NUM_MAX; - } - - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - } - - schedule_work(&set_clk_work); - - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (0 != frame_dur) - vstatus->frame_rate = 96000 / frame_dur; - else - vstatus->frame_rate = 96000; - vstatus->error_count = 0; - vstatus->status = stat; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -int vmjpeg_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -/****************************************/ -static int vmjpeg_canvas_init(void) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 decbuf_size, decbuf_y_size, decbuf_uv_size; - unsigned long buf_start; - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - /* HD & SD */ - canvas_width = 1920; - canvas_height = 1088; - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; -#ifdef NV21 - canvas_config(index2canvas0(i) & 0xff, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config((index2canvas0(i) >> 8) & 0xff, - buf_start + - decbuf_y_size, canvas_width, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(index2canvas1(i) & 0xff, - buf_start + - decbuf_size / 2, canvas_width, - canvas_height, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config((index2canvas1(i) >> 8) & 0xff, - buf_start + - decbuf_y_size + decbuf_uv_size / 2, - canvas_width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); -#else - canvas_config(index2canvas0(i) & 0xff, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config((index2canvas0(i) >> 8) & 0xff, - buf_start + - decbuf_y_size, canvas_width / 2, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config((index2canvas0(i) >> 16) & 0xff, - buf_start + - decbuf_y_size + decbuf_uv_size, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(index2canvas1(i) & 0xff, - buf_start + - decbuf_size / 2, canvas_width, - canvas_height, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config((index2canvas1(i) >> 8) & 0xff, - buf_start + - decbuf_y_size + decbuf_uv_size / 2, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config((index2canvas1(i) >> 16) & 0xff, - buf_start + - decbuf_y_size + decbuf_uv_size + - decbuf_uv_size / 2, canvas_width / 2, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); -#endif - - } - return 0; -} - -static void init_scaler(void) -{ - /* 4 point triangle */ - const unsigned int filt_coef[] = { - 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, - 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, - 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, - 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, - 0x18382808, 0x18382808, 0x17372909, 0x17372909, - 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, - 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, - 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, - 0x10303010 - }; - int i; - - /* pscale enable, PSCALE cbus bmem enable */ - WRITE_VREG(PSCALE_CTRL, 0xc000); - - /* write filter coefs */ - WRITE_VREG(PSCALE_BMEM_ADDR, 0); - for (i = 0; i < 33; i++) { - WRITE_VREG(PSCALE_BMEM_DAT, 0); - WRITE_VREG(PSCALE_BMEM_DAT, filt_coef[i]); - } - - /* Y horizontal initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 37 * 2); - /* [35]: buf repeat pix0, - * [34:29] => buf receive num, - * [28:16] => buf blk x, - * [15:0] => buf phase - */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* C horizontal initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 41 * 2); - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* Y vertical initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 39 * 2); - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* C vertical initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 43 * 2); - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* Y horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 36 * 2 + 1); - /* [19:0] => Y horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - /* C horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 40 * 2 + 1); - /* [19:0] => C horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - - /* Y vertical phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 38 * 2 + 1); - /* [19:0] => Y vertical phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - /* C vertical phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 42 * 2 + 1); - /* [19:0] => C horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - - /* reset pscaler */ -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ - WRITE_VREG(DOS_SW_RESET0, (1 << 10)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET2_REGISTER, RESET_PSCALE); -#endif - READ_RESET_REG(RESET2_REGISTER); - READ_RESET_REG(RESET2_REGISTER); - READ_RESET_REG(RESET2_REGISTER); - - WRITE_VREG(PSCALE_RST, 0x7); - WRITE_VREG(PSCALE_RST, 0x0); -} - -static int vmjpeg_prot_init(void) -{ - int r; -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); -#endif - - r = vmjpeg_canvas_init(); - - WRITE_VREG(AV_SCRATCH_0, 12); - WRITE_VREG(AV_SCRATCH_1, 0x031a); -#ifdef NV21 - WRITE_VREG(AV_SCRATCH_4, 0x010100); - WRITE_VREG(AV_SCRATCH_5, 0x030302); - WRITE_VREG(AV_SCRATCH_6, 0x050504); - WRITE_VREG(AV_SCRATCH_7, 0x070706); -#else - WRITE_VREG(AV_SCRATCH_4, 0x020100); - WRITE_VREG(AV_SCRATCH_5, 0x050403); - WRITE_VREG(AV_SCRATCH_6, 0x080706); - WRITE_VREG(AV_SCRATCH_7, 0x0b0a09); -#endif - init_scaler(); - - /* clear buffer IN/OUT registers */ - WRITE_VREG(MREG_TO_AMRISC, 0); - WRITE_VREG(MREG_FROM_AMRISC, 0); - - WRITE_VREG(MCPU_INTR_MSK, 0xffff); - WRITE_VREG(MREG_DECODE_PARAM, (frame_height << 4) | 0x8000); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - /* set interrupt mapping for vld */ - WRITE_VREG(ASSIST_AMR1_INT8, 8); -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#else - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif -#endif - return r; -} - -static int vmjpeg_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -static void vmjpeg_local_init(void) -{ - int i; - - frame_width = vmjpeg_amstream_dec_info.width; - frame_height = vmjpeg_amstream_dec_info.height; - frame_dur = vmjpeg_amstream_dec_info.rate; - saved_resolution = 0; - amlog_level(LOG_LEVEL_INFO, "mjpegdec: w(%d), h(%d), dur(%d)\n", - frame_width, frame_height, frame_dur); - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - vfbuf_use[i] = 0; - - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &vfpool[i]; - - vfpool[i].index = DECODE_BUFFER_NUM_MAX; - kfifo_put(&newframe_q, vf); - } - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); -} - -static s32 vmjpeg_init(void) -{ - int ret = -1, size = -1; - char *buf = vmalloc(0x1000 * 16); - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - amvdec_enable(); - - vmjpeg_local_init(); - - size = get_firmware_data(VIDEO_DEC_MJPEG, buf); - if (size < 0) { - amvdec_disable(); - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_MJPEG, NULL, buf); - if (ret < 0) { - amvdec_disable(); - vfree(buf); - pr_err("MJPEG: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(buf); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - ret = vmjpeg_prot_init(); - if (ret < 0) - return ret; - - ret = vdec_request_irq(VDEC_IRQ_1, vmjpeg_isr, - "vmjpeg-irq", (void *)vmjpeg_dec_id); - - if (ret) { - amvdec_disable(); - - amlog_level(LOG_LEVEL_ERROR, "vmjpeg irq register error.\n"); - return -ENOENT; - } - - stat |= STAT_ISR_REG; - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vmjpeg_vf_prov, PROVIDER_NAME, &vmjpeg_vf_provider, - NULL); - vf_reg_provider(&vmjpeg_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vmjpeg_vf_prov, PROVIDER_NAME, &vmjpeg_vf_provider, - NULL); - vf_reg_provider(&vmjpeg_vf_prov); -#endif - - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)vmjpeg_amstream_dec_info.rate)); - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong)&recycle_timer; - recycle_timer.function = vmjpeg_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - return 0; -} - -static int amvdec_mjpeg_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - mutex_lock(&vmjpeg_mutex); - - amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg probe start.\n"); - - INIT_WORK(&set_clk_work, mjpeg_set_clk); - - if (pdata == NULL) { - amlog_level(LOG_LEVEL_ERROR, - "amvdec_mjpeg memory resource undefined.\n"); - mutex_unlock(&vmjpeg_mutex); - - return -EFAULT; - } - - if (pdata->sys_info) - vmjpeg_amstream_dec_info = *pdata->sys_info; - - pdata->dec_status = vmjpeg_dec_status; - pdata->set_isreset = vmjpeg_set_isreset; - is_reset = 0; - vmjpeg_vdec_info_init(); - - if (vmjpeg_init() < 0) { - amlog_level(LOG_LEVEL_ERROR, "amvdec_mjpeg init failed.\n"); - mutex_unlock(&vmjpeg_mutex); - kfree(gvs); - gvs = NULL; - pdata->dec_status = NULL; - return -ENODEV; - } - - mutex_unlock(&vmjpeg_mutex); - - amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg probe end.\n"); - - return 0; -} - -static int amvdec_mjpeg_remove(struct platform_device *pdev) -{ - mutex_lock(&vmjpeg_mutex); - - cancel_work_sync(&set_clk_work); - - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)vmjpeg_dec_id); - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - if (stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - - vf_unreg_provider(&vmjpeg_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - amvdec_disable(); - - mutex_unlock(&vmjpeg_mutex); - - kfree(gvs); - gvs = NULL; - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg remove.\n"); - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_mjpeg_driver = { - .probe = amvdec_mjpeg_probe, - .remove = amvdec_mjpeg_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_mjpeg_profile = { - .name = "mjpeg", - .profile = "" -}; -static struct mconfig mjpeg_configs[] = { - MC_PU32("stat", &stat), -}; -static struct mconfig_node mjpeg_node; - -static int __init amvdec_mjpeg_driver_init_module(void) -{ - amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg module init\n"); - - if (platform_driver_register(&amvdec_mjpeg_driver)) { - amlog_level(LOG_LEVEL_ERROR, - "failed to register amvdec_mjpeg driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvdec_mjpeg_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &mjpeg_node, - "mjpeg", mjpeg_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_mjpeg_driver_remove_module(void) -{ - amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg module remove.\n"); - - platform_driver_unregister(&amvdec_mjpeg_driver); -} - -/****************************************/ - -module_param(stat, uint, 0664); -MODULE_PARM_DESC(stat, "\n amvdec_mjpeg stat\n"); - -module_init(amvdec_mjpeg_driver_init_module); -module_exit(amvdec_mjpeg_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c deleted file mode 100644 index 38c08e1e113a..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * drivers/amlogic/amports/vmjpeg.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../../../stream_input/amports/amports_priv.h" - -#include "../utils/vdec_input.h" -#include "../utils/vdec.h" -#include "../utils/amvdec.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include "../utils/firmware.h" - -#include - - -#define MEM_NAME "codec_mmjpeg" - -#define DRIVER_NAME "ammvdec_mjpeg" -#define MODULE_NAME "ammvdec_mjpeg" -#define CHECK_INTERVAL (HZ/100) - -/* protocol register usage - * AV_SCRATCH_4 : decode buffer spec - * AV_SCRATCH_5 : decode buffer index - */ - -#define MREG_DECODE_PARAM AV_SCRATCH_2 /* bit 0-3: pico_addr_mode */ -/* bit 15-4: reference height */ -#define MREG_TO_AMRISC AV_SCRATCH_8 -#define MREG_FROM_AMRISC AV_SCRATCH_9 -#define MREG_FRAME_OFFSET AV_SCRATCH_A -#define DEC_STATUS_REG AV_SCRATCH_F -#define MREG_PIC_WIDTH AV_SCRATCH_B -#define MREG_PIC_HEIGHT AV_SCRATCH_C -#define DECODE_STOP_POS AV_SCRATCH_K - -#define PICINFO_BUF_IDX_MASK 0x0007 -#define PICINFO_AVI1 0x0080 -#define PICINFO_INTERLACE 0x0020 -#define PICINFO_INTERLACE_AVI1_BOT 0x0010 -#define PICINFO_INTERLACE_FIRST 0x0010 - -#define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 4 -#define MAX_BMMU_BUFFER_NUM DECODE_BUFFER_NUM_MAX - -#define DEFAULT_MEM_SIZE (32*SZ_1M) -static int debug_enable; -static u32 udebug_flag; -#define DECODE_ID(hw) (hw_to_vdec(hw)->id) - -static unsigned int radr; -static unsigned int rval; -#define VMJPEG_DEV_NUM 9 -static unsigned int max_decode_instance_num = VMJPEG_DEV_NUM; -static unsigned int max_process_time[VMJPEG_DEV_NUM]; -static unsigned int decode_timeout_val = 200; -static struct vframe_s *vmjpeg_vf_peek(void *); -static struct vframe_s *vmjpeg_vf_get(void *); -static void vmjpeg_vf_put(struct vframe_s *, void *); -static int vmjpeg_vf_states(struct vframe_states *states, void *); -static int vmjpeg_event_cb(int type, void *data, void *private_data); -static void vmjpeg_work(struct work_struct *work); -static int pre_decode_buf_level = 0x800; -#undef pr_info -#define pr_info printk -unsigned int mmjpeg_debug_mask = 0xff; -#define PRINT_FLAG_ERROR 0x0 -#define PRINT_FLAG_RUN_FLOW 0X0001 -#define PRINT_FLAG_TIMEINFO 0x0002 -#define PRINT_FLAG_UCODE_DETAIL 0x0004 -#define PRINT_FLAG_VLD_DETAIL 0x0008 -#define PRINT_FLAG_DEC_DETAIL 0x0010 -#define PRINT_FLAG_BUFFER_DETAIL 0x0020 -#define PRINT_FLAG_RESTORE 0x0040 -#define PRINT_FRAME_NUM 0x0080 -#define PRINT_FLAG_FORCE_DONE 0x0100 -#define PRINT_FRAMEBASE_DATA 0x0400 -int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...) -{ - if (((debug_enable & debug_flag) && - ((1 << index) & mmjpeg_debug_mask)) - || (debug_flag == PRINT_FLAG_ERROR)) { - unsigned char buf[512]; - int len = 0; - va_list args; - va_start(args, fmt); - len = sprintf(buf, "%d: ", index); - vsnprintf(buf + len, 512-len, fmt, args); - pr_info("%s", buf); - va_end(args); - } - return 0; -} - -static const char vmjpeg_dec_id[] = "vmmjpeg-dev"; - -#define PROVIDER_NAME "vdec.mjpeg" -static const struct vframe_operations_s vf_provider_ops = { - .peek = vmjpeg_vf_peek, - .get = vmjpeg_vf_get, - .put = vmjpeg_vf_put, - .event_cb = vmjpeg_event_cb, - .vf_states = vmjpeg_vf_states, -}; - -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_FORCE_EXIT 3 -#define DEC_RESULT_EOS 4 -#define DEC_DECODE_TIMEOUT 0x21 - - -struct buffer_spec_s { - unsigned int y_addr; - unsigned int u_addr; - unsigned int v_addr; - - int y_canvas_index; - int u_canvas_index; - int v_canvas_index; - - struct canvas_config_s canvas_config[3]; - unsigned long cma_alloc_addr; - int cma_alloc_count; - unsigned int buf_adr; -}; - -#define spec2canvas(x) \ - (((x)->v_canvas_index << 16) | \ - ((x)->u_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - -struct vdec_mjpeg_hw_s { - spinlock_t lock; - struct mutex vmjpeg_mutex; - - struct platform_device *platform_dev; - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - - struct vframe_s vfpool[VF_POOL_SIZE]; - struct buffer_spec_s buffer_spec[DECODE_BUFFER_NUM_MAX]; - s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; - - u32 frame_width; - u32 frame_height; - u32 frame_dur; - u32 saved_resolution; - u8 init_flag; - u32 stat; - u32 dec_result; - unsigned long buf_start; - u32 buf_size; - void *mm_blk_handle; - struct dec_sysinfo vmjpeg_amstream_dec_info; - - struct vframe_chunk_s *chunk; - struct work_struct work; - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - struct firmware_s *fw; - struct timer_list check_timer; - u32 decode_timeout_count; - u32 start_process_time; - u32 last_vld_level; - u8 eos; - u32 frame_num; - u32 put_num; - u32 run_count; - u32 not_run_ready; - u32 input_empty; - u32 peek_num; - u32 get_num; -}; - -static void reset_process_time(struct vdec_mjpeg_hw_s *hw); -static void set_frame_info(struct vdec_mjpeg_hw_s *hw, struct vframe_s *vf) -{ - u32 temp; - temp = READ_VREG(MREG_PIC_WIDTH); - if (temp > 1920) - vf->width = hw->frame_width = 1920; - else if (temp > 0) - vf->width = hw->frame_width = temp; - temp = READ_VREG(MREG_PIC_HEIGHT); - if (temp > 1088) - vf->height = hw->frame_height = 1088; - else if (temp > 0) - vf->height = hw->frame_height = temp; - vf->duration = hw->frame_dur; - vf->ratio_control = 0; - vf->duration_pulldown = 0; - vf->flag = 0; - - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 3; - - vf->canvas0_config[0] = hw->buffer_spec[vf->index].canvas_config[0]; - vf->canvas0_config[1] = hw->buffer_spec[vf->index].canvas_config[1]; - vf->canvas0_config[2] = hw->buffer_spec[vf->index].canvas_config[2]; - - vf->canvas1_config[0] = hw->buffer_spec[vf->index].canvas_config[0]; - vf->canvas1_config[1] = hw->buffer_spec[vf->index].canvas_config[1]; - vf->canvas1_config[2] = hw->buffer_spec[vf->index].canvas_config[2]; -} - -static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) -{ - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)(vdec->private); - u32 reg; - struct vframe_s *vf = NULL; - u32 index, offset = 0, pts; - u64 pts_us64; - u32 frame_size; - - if (!hw) - return IRQ_HANDLED; - - if (hw->eos) - return IRQ_HANDLED; - reset_process_time(hw); - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - if (READ_VREG(AV_SCRATCH_D) != 0 && - (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { - pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_D), - READ_VREG(AV_SCRATCH_E)); - WRITE_VREG(AV_SCRATCH_D, 0); - return IRQ_HANDLED; - } - - reg = READ_VREG(MREG_FROM_AMRISC); - index = READ_VREG(AV_SCRATCH_5); - - if (index >= DECODE_BUFFER_NUM_MAX) { - pr_err("fatal error, invalid buffer index."); - return IRQ_HANDLED; - } - - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_info( - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - vf->index = index; - set_frame_info(hw, vf); - - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - /* vf->pts = (pts_valid) ? pts : 0; */ - /* vf->pts_us64 = (pts_valid) ? pts_us64 : 0; */ - - if (hw->chunk) { - vf->pts = hw->chunk->pts; - vf->pts_us64 = hw->chunk->pts64; - } else { - offset = READ_VREG(MREG_FRAME_OFFSET); - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, - &frame_size, 3000, - &pts_us64) == 0) { - vf->pts = pts; - vf->pts_us64 = pts_us64; - } else { - vf->pts = 0; - vf->pts_us64 = 0; - } - } - vf->orientation = 0; - hw->vfbuf_use[index]++; - - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "%s:frame num:%d,pts=%d,pts64=%lld. dur=%d\n", - __func__, hw->frame_num, - vf->pts, vf->pts_us64, vf->duration); - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - hw->dec_result = DEC_RESULT_DONE; - - vdec_schedule_work(&hw->work); - - return IRQ_HANDLED; -} - -static struct vframe_s *vmjpeg_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - - if (!hw) - return NULL; - hw->peek_num++; - if (kfifo_peek(&hw->display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vmjpeg_vf_get(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - - if (!hw) - return NULL; - hw->get_num++; - if (kfifo_get(&hw->display_q, &vf)) - return vf; - - return NULL; -} - -static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct vdec_s *vdec = op_arg; - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "%s:put_num:%d\n", __func__, hw->put_num); - hw->vfbuf_use[vf->index]--; - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); - hw->put_num++; -} - -static int vmjpeg_event_cb(int type, void *data, void *private_data) -{ - return 0; -} - -static int vmjpeg_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - struct vdec_s *vdec = op_arg; - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - - spin_lock_irqsave(&hw->lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&hw->newframe_q); - states->buf_avail_num = kfifo_len(&hw->display_q); - states->buf_recycle_num = 0; - - spin_unlock_irqrestore(&hw->lock, flags); - - return 0; -} - -static int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - - if (!hw) - return -1; - - vstatus->frame_width = hw->frame_width; - vstatus->frame_height = hw->frame_height; - if (0 != hw->frame_dur) - vstatus->frame_rate = 96000 / hw->frame_dur; - else - vstatus->frame_rate = 96000; - vstatus->error_count = 0; - vstatus->status = hw->stat; - - return 0; -} - -/****************************************/ -static void vmjpeg_canvas_init(struct vdec_s *vdec) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 decbuf_size, decbuf_y_size, decbuf_uv_size; - unsigned long buf_start, addr; - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; - - canvas_width = 1920; - canvas_height = 1088; - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - int canvas; - - - - ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &buf_start); - if (ret < 0) { - pr_err("CMA alloc failed! size 0x%d idx %d\n", - decbuf_size, i); - return; - } - - hw->buffer_spec[i].buf_adr = buf_start; - addr = hw->buffer_spec[i].buf_adr; - - hw->buffer_spec[i].y_addr = addr; - addr += decbuf_y_size; - hw->buffer_spec[i].u_addr = addr; - addr += decbuf_uv_size; - hw->buffer_spec[i].v_addr = addr; - - if (vdec->parallel_dec == 1) { - if (hw->buffer_spec[i].y_canvas_index == -1) - hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - if (hw->buffer_spec[i].u_canvas_index == -1) - hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - if (hw->buffer_spec[i].v_canvas_index == -1) - hw->buffer_spec[i].v_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - } else { - canvas = vdec->get_canvas(i, 3); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); - } - - canvas_config(hw->buffer_spec[i].y_canvas_index, - hw->buffer_spec[i].y_addr, - canvas_width, - canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - hw->buffer_spec[i].canvas_config[0].phy_addr = - hw->buffer_spec[i].y_addr; - hw->buffer_spec[i].canvas_config[0].width = - canvas_width; - hw->buffer_spec[i].canvas_config[0].height = - canvas_height; - hw->buffer_spec[i].canvas_config[0].block_mode = - CANVAS_BLKMODE_LINEAR; - - canvas_config(hw->buffer_spec[i].u_canvas_index, - hw->buffer_spec[i].u_addr, - canvas_width / 2, - canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - hw->buffer_spec[i].canvas_config[1].phy_addr = - hw->buffer_spec[i].u_addr; - hw->buffer_spec[i].canvas_config[1].width = - canvas_width / 2; - hw->buffer_spec[i].canvas_config[1].height = - canvas_height / 2; - hw->buffer_spec[i].canvas_config[1].block_mode = - CANVAS_BLKMODE_LINEAR; - - canvas_config(hw->buffer_spec[i].v_canvas_index, - hw->buffer_spec[i].v_addr, - canvas_width / 2, - canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - hw->buffer_spec[i].canvas_config[2].phy_addr = - hw->buffer_spec[i].v_addr; - hw->buffer_spec[i].canvas_config[2].width = - canvas_width / 2; - hw->buffer_spec[i].canvas_config[2].height = - canvas_height / 2; - hw->buffer_spec[i].canvas_config[2].block_mode = - CANVAS_BLKMODE_LINEAR; - } -} - -static void init_scaler(void) -{ - /* 4 point triangle */ - const unsigned int filt_coef[] = { - 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, - 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, - 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, - 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, - 0x18382808, 0x18382808, 0x17372909, 0x17372909, - 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, - 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, - 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, - 0x10303010 - }; - int i; - - /* pscale enable, PSCALE cbus bmem enable */ - WRITE_VREG(PSCALE_CTRL, 0xc000); - - /* write filter coefs */ - WRITE_VREG(PSCALE_BMEM_ADDR, 0); - for (i = 0; i < 33; i++) { - WRITE_VREG(PSCALE_BMEM_DAT, 0); - WRITE_VREG(PSCALE_BMEM_DAT, filt_coef[i]); - } - - /* Y horizontal initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 37 * 2); - /* [35]: buf repeat pix0, - * [34:29] => buf receive num, - * [28:16] => buf blk x, - * [15:0] => buf phase - */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* C horizontal initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 41 * 2); - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* Y vertical initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 39 * 2); - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* C vertical initial info */ - WRITE_VREG(PSCALE_BMEM_ADDR, 43 * 2); - WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); - WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); - - /* Y horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 36 * 2 + 1); - /* [19:0] => Y horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - /* C horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 40 * 2 + 1); - /* [19:0] => C horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - - /* Y vertical phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 38 * 2 + 1); - /* [19:0] => Y vertical phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - /* C vertical phase step */ - WRITE_VREG(PSCALE_BMEM_ADDR, 42 * 2 + 1); - /* [19:0] => C horizontal phase step */ - WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); - - /* reset pscaler */ -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ - WRITE_VREG(DOS_SW_RESET0, (1 << 10)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET2_REGISTER, RESET_PSCALE); -#endif - READ_RESET_REG(RESET2_REGISTER); - READ_RESET_REG(RESET2_REGISTER); - READ_RESET_REG(RESET2_REGISTER); - - WRITE_VREG(PSCALE_RST, 0x7); - WRITE_VREG(PSCALE_RST, 0x0); -} - -static void vmjpeg_dump_state(struct vdec_s *vdec) -{ - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)(vdec->private); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "====== %s\n", __func__); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "width/height (%d/%d)\n", - hw->frame_width, - hw->frame_height - ); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d input_empty %d\n", - input_frame_based(vdec), - hw->eos, - hw->stat, - hw->dec_result, - hw->frame_num, - hw->put_num, - hw->run_count, - hw->not_run_ready, - hw->input_empty - ); - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - mmjpeg_debug_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", - __func__, - kfifo_len(&hw->newframe_q), - VF_POOL_SIZE, - kfifo_len(&hw->display_q), - VF_POOL_SIZE, - hw->peek_num, - hw->get_num, - hw->put_num - ); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "VIFF_BIT_CNT=0x%x\n", - READ_VREG(VIFF_BIT_CNT)); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_LEVEL=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_WP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_WP)); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_RP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_RP)); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - mmjpeg_debug_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - if (input_frame_based(vdec) && - debug_enable & PRINT_FRAMEBASE_DATA - ) { - int jj; - if (hw->chunk && hw->chunk->block && - hw->chunk->size > 0) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, hw->chunk->size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - mmjpeg_debug_print(DECODE_ID(hw), 0, - "frame data size 0x%x\n", - hw->chunk->size); - for (jj = 0; jj < hw->chunk->size; jj++) { - if ((jj & 0xf) == 0) - mmjpeg_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - mmjpeg_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - mmjpeg_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } -} -static void reset_process_time(struct vdec_mjpeg_hw_s *hw) -{ - if (hw->start_process_time) { - unsigned process_time = - 1000 * (jiffies - hw->start_process_time) / HZ; - hw->start_process_time = 0; - if (process_time > max_process_time[DECODE_ID(hw)]) - max_process_time[DECODE_ID(hw)] = process_time; - } -} - -static void start_process_time(struct vdec_mjpeg_hw_s *hw) -{ - hw->decode_timeout_count = 2; - hw->start_process_time = jiffies; -} - -static void timeout_process(struct vdec_mjpeg_hw_s *hw) -{ - amvdec_stop(); - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s decoder timeout\n", __func__); - hw->dec_result = DEC_RESULT_DONE; - reset_process_time(hw); - vdec_schedule_work(&hw->work); -} - -static void check_timer_func(unsigned long arg) -{ - struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)arg; - struct vdec_s *vdec = hw_to_vdec(hw); - int timeout_val = decode_timeout_val; - - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "%s: status:nstatus=%d:%d\n", - __func__, vdec->status, vdec->next_status); - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "%s: %d,buftl=%x:%x:%x:%x\n", - __func__, __LINE__, - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), - READ_PARSER_REG(PARSER_VIDEO_WP), - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP)); - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - - if ((debug_enable == 0) && - (input_frame_based(vdec) || - (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && - (timeout_val > 0) && - (hw->start_process_time > 0) && - ((1000 * (jiffies - hw->start_process_time) / HZ) - > timeout_val)) { - if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); - } - hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); - } - - if (READ_VREG(DEC_STATUS_REG) == DEC_DECODE_TIMEOUT) { - pr_info("ucode DEC_DECODE_TIMEOUT\n"); - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); - WRITE_VREG(DEC_STATUS_REG, 0); - } - - if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - pr_info("vdec requested to be disconnected\n"); - return; - } - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -} - -static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index) -{ - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); - WRITE_VREG(DOS_SW_RESET0, 0); - - vmjpeg_canvas_init(vdec); - - /* find next decode buffer index */ - WRITE_VREG(AV_SCRATCH_4, spec2canvas(&hw->buffer_spec[index])); - WRITE_VREG(AV_SCRATCH_5, index); - - init_scaler(); - - /* clear buffer IN/OUT registers */ - WRITE_VREG(MREG_TO_AMRISC, 0); - WRITE_VREG(MREG_FROM_AMRISC, 0); - - WRITE_VREG(MCPU_INTR_MSK, 0xffff); - WRITE_VREG(MREG_DECODE_PARAM, (hw->frame_height << 4) | 0x8000); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - /* set interrupt mapping for vld */ - WRITE_VREG(ASSIST_AMR1_INT8, 8); -#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif -} - -static s32 vmjpeg_init(struct vdec_s *vdec) -{ - int i; - int size = -1, fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_MJPEG_MULTI, fw->data); - if (size < 0) { - pr_err("get firmware fail."); - vfree(fw); - return -1; - } - - fw->len = size; - hw->fw = fw; - - hw->frame_width = hw->vmjpeg_amstream_dec_info.width; - hw->frame_height = hw->vmjpeg_amstream_dec_info.height; - hw->frame_dur = ((hw->vmjpeg_amstream_dec_info.rate) ? - hw->vmjpeg_amstream_dec_info.rate : 3840); - hw->saved_resolution = 0; - hw->eos = 0; - hw->init_flag = 0; - hw->frame_num = 0; - hw->put_num = 0; - hw->run_count = 0; - hw->not_run_ready = 0; - hw->input_empty = 0; - hw->peek_num = 0; - hw->get_num = 0; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - hw->vfbuf_use[i] = 0; - - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &hw->vfpool[i]; - - hw->vfpool[i].index = -1; - kfifo_put(&hw->newframe_q, vf); - } - - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - - hw->mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - - init_timer(&hw->check_timer); - - hw->check_timer.data = (unsigned long)hw; - hw->check_timer.function = check_timer_func; - hw->check_timer.expires = jiffies + CHECK_INTERVAL; - /*add_timer(&hw->check_timer);*/ - hw->stat |= STAT_TIMER_ARM; - hw->stat |= STAT_ISR_REG; - - WRITE_VREG(DECODE_STOP_POS, udebug_flag); - INIT_WORK(&hw->work, vmjpeg_work); - pr_info("w:h=%d:%d\n", hw->frame_width, hw->frame_height); - return 0; -} - -static unsigned long run_ready(struct vdec_s *vdec, - unsigned long mask) -{ - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; - hw->not_run_ready++; - if (hw->eos) - return 0; - if (vdec_stream_based(vdec) && (hw->init_flag == 0) - && pre_decode_buf_level != 0) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = vdec->input.size + wp - rp; - else - level = wp - rp; - - if (level < pre_decode_buf_level) - return 0; - } - hw->not_run_ready = 0; - if (vdec->parallel_dec == 1) - return CORE_MASK_VDEC_1; - else - return CORE_MASK_VDEC_1 | CORE_MASK_HEVC; -} - -static void run(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *arg) -{ - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; - int i, ret; - - hw->vdec_cb_arg = arg; - hw->vdec_cb = callback; - - hw->run_count++; - vdec_reset_core(vdec); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - if (hw->vfbuf_use[i] == 0) - break; - } - - if (i == DECODE_BUFFER_NUM_MAX) { - hw->dec_result = DEC_RESULT_AGAIN; - vdec_schedule_work(&hw->work); - return; - } - - ret = vdec_prepare_input(vdec, &hw->chunk); - if (ret <= 0) { - hw->input_empty++; - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s: %d,r=%d,buftl=%x:%x:%x\n", - __func__, __LINE__, ret, - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), - READ_PARSER_REG(PARSER_VIDEO_WP), - READ_VREG(VLD_MEM_VIFIFO_WP)); - - hw->dec_result = DEC_RESULT_AGAIN; - vdec_schedule_work(&hw->work); - return; - } - hw->input_empty = 0; - hw->dec_result = DEC_RESULT_NONE; - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - } else { - ret = amvdec_vdec_loadmc_ex(VFORMAT_MJPEG, "mmjpeg", vdec, hw->fw->data); - if (ret < 0) { - pr_err("[%d] MMJPEG: the %s fw loading failed, err: %x\n", - vdec->id, tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; - } - vdec->mc_loaded = 1; - vdec->mc_type = VFORMAT_MJPEG; - } -/* if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) { - pr_err("%s: Error amvdec_loadmc fail\n", __func__); - return; - }*/ - - vmjpeg_hw_ctx_restore(vdec, i); -#if 0 - vdec_enable_input(vdec); - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -#endif - hw->stat |= STAT_MC_LOAD; - start_process_time(hw); - hw->last_vld_level = 0; - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); - amvdec_start(); - vdec_enable_input(vdec); - hw->stat |= STAT_VDEC_RUN; - hw->init_flag = 1; - - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_DECODE_CONTROL), - READ_VREG(VIFF_BIT_CNT), - READ_VREG(POWER_CTL_VLD), - READ_VREG(VLD_MEM_VIFIFO_START_PTR), - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), - READ_VREG(VLD_MEM_VIFIFO_CONTROL), - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), - READ_VREG(VLD_MEM_VIFIFO_END_PTR)); -} -static void wait_vmjpeg_search_done(struct vdec_mjpeg_hw_s *hw) -{ - u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - int count = 0; - - do { - usleep_range(100, 500); - if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) - break; - if (count > 1000) { - mmjpeg_debug_print(DECODE_ID(hw), 0, - "%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", - __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); - break; - } else - vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - count++; - } while (1); -} - -static void vmjpeg_work(struct work_struct *work) -{ - struct vdec_mjpeg_hw_s *hw = container_of(work, - struct vdec_mjpeg_hw_s, work); - struct vdec_s *vdec = hw_to_vdec(hw); - - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, - "%s: result=%d,len=%d:%d\n", - __func__, hw->dec_result, - kfifo_len(&hw->newframe_q), - kfifo_len(&hw->display_q)); - if (hw->dec_result == DEC_RESULT_DONE) { - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - } else if (hw->dec_result == DEC_RESULT_AGAIN) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(hw_to_vdec(hw))) { - hw->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hw->work); - /*pr_info("%s: return\n", - __func__);*/ - return; - } - } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { - pr_info("%s: force exit\n", __func__); - if (hw->stat & STAT_ISR_REG) { - amvdec_stop(); - /*disable mbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 0); - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - } else if (hw->dec_result == DEC_RESULT_EOS) { - pr_info("%s: end of stream\n", __func__); - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - hw->eos = 1; - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - vdec_clean_input(hw_to_vdec(hw)); - } - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - wait_vmjpeg_search_done(hw); - /* mark itself has all HW resource released and input released */ - if (vdec->parallel_dec == 1) - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); - else { - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 - | CORE_MASK_HEVC); - } - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - - if (hw->vdec_cb) - hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); -} - -static int vmjpeg_stop(struct vdec_mjpeg_hw_s *hw) -{ - pr_info("%s ...count = %d\n", __func__, hw->frame_num); - - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - pr_info("%s amvdec_stop\n", __func__); - hw->stat &= ~STAT_VDEC_RUN; - } - - if (hw->stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - cancel_work_sync(&hw->work); - hw->init_flag = 0; - - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - - if (hw->fw) { - vfree(hw->fw); - hw->fw = NULL; - } - - return 0; -} - -static int ammvdec_mjpeg_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct vdec_mjpeg_hw_s *hw = NULL; - - if (pdata == NULL) { - pr_info("ammvdec_mjpeg memory resource undefined.\n"); - return -EFAULT; - } - - hw = (struct vdec_mjpeg_hw_s *)devm_kzalloc(&pdev->dev, - sizeof(struct vdec_mjpeg_hw_s), GFP_KERNEL); - hw = vzalloc(sizeof(struct vdec_mjpeg_hw_s)); - if (hw == NULL) { - pr_info("\nammvdec_mjpeg device data allocation failed\n"); - return -ENOMEM; - } - - pdata->private = hw; - pdata->dec_status = vmjpeg_dec_status; - - pdata->run = run; - pdata->run_ready = run_ready; - pdata->irq_handler = vmjpeg_isr; - pdata->dump_state = vmjpeg_dump_state; - - if (pdata->parallel_dec == 1) { - int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - hw->buffer_spec[i].y_canvas_index = -1; - hw->buffer_spec[i].u_canvas_index = -1; - hw->buffer_spec[i].v_canvas_index = -1; - } - } - - if (pdata->use_vfm_path) - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - PROVIDER_NAME ".%02x", pdev->id & 0xff); - - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vf_provider_ops, pdata); - - platform_set_drvdata(pdev, pdata); - - hw->platform_dev = pdev; - - if (pdata->sys_info) - hw->vmjpeg_amstream_dec_info = *pdata->sys_info; - - vdec_source_changed(VFORMAT_MJPEG, - 1920, 1080, 60); - if (vmjpeg_init(pdata) < 0) { - pr_info("ammvdec_mjpeg init failed.\n"); - if (hw) { - vfree(hw); - hw = NULL; - } - pdata->dec_status = NULL; - return -ENODEV; - } - if (pdata->parallel_dec == 1) - vdec_core_request(pdata, CORE_MASK_VDEC_1); - else { - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - } - - return 0; -} - -static int ammvdec_mjpeg_remove(struct platform_device *pdev) -{ - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - struct vdec_s *vdec = hw_to_vdec(hw); - int i; - - vmjpeg_stop(hw); - - if (vdec->parallel_dec == 1) - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); - else - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - if (vdec->parallel_dec == 1) { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); - } - } - if (hw) { - vfree(hw); - hw = NULL; - } - pr_info("%s\n", __func__); - return 0; -} - -/****************************************/ - -static struct platform_driver ammvdec_mjpeg_driver = { - .probe = ammvdec_mjpeg_probe, - .remove = ammvdec_mjpeg_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t ammvdec_mjpeg_profile = { - .name = "mmjpeg", - .profile = "" -}; - -static int __init ammvdec_mjpeg_driver_init_module(void) -{ - if (platform_driver_register(&ammvdec_mjpeg_driver)) { - pr_err("failed to register ammvdec_mjpeg driver\n"); - return -ENODEV; - } - vcodec_profile_register(&ammvdec_mjpeg_profile); - return 0; -} - -static void __exit ammvdec_mjpeg_driver_remove_module(void) -{ - platform_driver_unregister(&ammvdec_mjpeg_driver); -} - -/****************************************/ -module_param(debug_enable, uint, 0664); -MODULE_PARM_DESC(debug_enable, "\n debug enable\n"); -module_param(pre_decode_buf_level, int, 0664); -MODULE_PARM_DESC(pre_decode_buf_level, - "\n ammvdec_h264 pre_decode_buf_level\n"); -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_mmpeg12 udebug_flag\n"); - - -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mjpeg decode_timeout_val\n"); - -module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\nradr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\nrval\n"); - -module_init(ammvdec_mjpeg_driver_init_module); -module_exit(ammvdec_mjpeg_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile deleted file mode 100644 index 34f78c477e30..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12) += amvdec_mpeg12.o -amvdec_mpeg12-objs += vmpeg12.o - -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI) += amvdec_mmpeg12.o -amvdec_mmpeg12-objs += vmpeg12_multi.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c deleted file mode 100644 index ab54188c87e5..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c +++ /dev/null @@ -1,2223 +0,0 @@ -/* - * drivers/amlogic/amports/vmpeg12.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "vmpeg12.h" -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include - -#include - - -#ifdef CONFIG_AM_VDEC_MPEG12_LOG -#define AMLOG -#define LOG_LEVEL_VAR amlog_level_vmpeg -#define LOG_MASK_VAR amlog_mask_vmpeg -#define LOG_LEVEL_ERROR 0 -#define LOG_LEVEL_INFO 1 -#define LOG_LEVEL_DESC "0:ERROR, 1:INFO" -#endif -#include -MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); - -#include "../utils/amvdec.h" -#include "../utils/vdec.h" -#include "../utils/firmware.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" - -#define DRIVER_NAME "amvdec_mpeg12" -#define MODULE_NAME "amvdec_mpeg12" - -/* protocol registers */ -#define MREG_SEQ_INFO AV_SCRATCH_4 -#define MREG_PIC_INFO AV_SCRATCH_5 -#define MREG_PIC_WIDTH AV_SCRATCH_6 -#define MREG_PIC_HEIGHT AV_SCRATCH_7 -#define MREG_BUFFERIN AV_SCRATCH_8 -#define MREG_BUFFEROUT AV_SCRATCH_9 - -#define MREG_CMD AV_SCRATCH_A -#define MREG_CO_MV_START AV_SCRATCH_B -#define MREG_ERROR_COUNT AV_SCRATCH_C -#define MREG_FRAME_OFFSET AV_SCRATCH_D -#define MREG_WAIT_BUFFER AV_SCRATCH_E -#define MREG_FATAL_ERROR AV_SCRATCH_F -#define MREG_FORCE_I_RDY AV_SCRATCH_G - -#define PICINFO_ERROR 0x80000000 -#define PICINFO_TYPE_MASK 0x00030000 -#define PICINFO_TYPE_I 0x00000000 -#define PICINFO_TYPE_P 0x00010000 -#define PICINFO_TYPE_B 0x00020000 - -#define PICINFO_PROG 0x8000 -#define PICINFO_RPT_FIRST 0x4000 -#define PICINFO_TOP_FIRST 0x2000 -#define PICINFO_FRAME 0x1000 - -#define SEQINFO_EXT_AVAILABLE 0x80000000 -#define SEQINFO_PROG 0x00010000 -#define CCBUF_SIZE (5*1024) - -#define VF_POOL_SIZE 32 -#define DECODE_BUFFER_NUM_MAX 8 -#define PUT_INTERVAL (HZ/100) -#define WORKSPACE_SIZE (2*SZ_64K) -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) - - -#define INCPTR(p) ptr_atomic_wrap_inc(&p) - -#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002 -#define DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE 0x0004 -#define DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE 0x0008 -#define DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE 0x0010 -#define DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE 0x0020 -#define DEC_CONTROL_INTERNAL_MASK 0x0fff -#define DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE 0x1000 - -#define INTERLACE_SEQ_ALWAYS - -#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -#endif - - -enum { - FRAME_REPEAT_TOP, - FRAME_REPEAT_BOT, - FRAME_REPEAT_NONE -}; - -static struct vframe_s *vmpeg_vf_peek(void *); -static struct vframe_s *vmpeg_vf_get(void *); -static void vmpeg_vf_put(struct vframe_s *, void *); -static int vmpeg_vf_states(struct vframe_states *states, void *); -static int vmpeg_event_cb(int type, void *data, void *private_data); - -static int vmpeg12_prot_init(void); -static void vmpeg12_local_init(void); - -static const char vmpeg12_dec_id[] = "vmpeg12-dev"; -#define PROVIDER_NAME "decoder.mpeg12" -static const struct vframe_operations_s vmpeg_vf_provider = { - .peek = vmpeg_vf_peek, - .get = vmpeg_vf_get, - .put = vmpeg_vf_put, - .event_cb = vmpeg_event_cb, - .vf_states = vmpeg_vf_states, -}; -static void *mm_blk_handle; -static struct vframe_provider_s vmpeg_vf_prov; - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static const u32 frame_rate_tab[16] = { - 96000 / 30, 96000000 / 23976, 96000 / 24, 96000 / 25, - 9600000 / 2997, 96000 / 30, 96000 / 50, 9600000 / 5994, - 96000 / 60, - /* > 8 reserved, use 24 */ - 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, - 96000 / 24, 96000 / 24, 96000 / 24 -}; - -static struct vframe_s vfpool[VF_POOL_SIZE]; -static struct vframe_s vfpool2[VF_POOL_SIZE]; -static int cur_pool_idx; -static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; -static u32 dec_control; -static u32 frame_width, frame_height, frame_dur, frame_prog; -static u32 saved_resolution; -static struct timer_list recycle_timer; -static u32 stat; -static u32 buf_size = 32 * 1024 * 1024; -static u32 ccbuf_phyAddress; -static void *ccbuf_phyAddress_virt; -static int ccbuf_phyAddress_is_remaped_nocache; -static u32 lastpts; -static u32 fr_hint_status; -static u32 last_offset; -static u32 ratio_control; - - -static DEFINE_SPINLOCK(lock); - -static u32 frame_rpt_state; - -static struct dec_sysinfo vmpeg12_amstream_dec_info; -static struct vdec_info *gvs; -static struct vdec_s *vdec; - -/* for error handling */ -static s32 frame_force_skip_flag; -static s32 error_frame_skip_level; -static s32 wait_buffer_counter; -static u32 first_i_frame_ready; -static u32 force_first_i_ready; - -static struct work_struct userdata_push_work; -static struct work_struct notify_work; -static struct work_struct reset_work; -static struct work_struct set_clk_work; -static bool is_reset; - -static DEFINE_MUTEX(userdata_mutex); - -static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len); - -struct mpeg12_userdata_recored_t { - struct userdata_meta_info_t meta_info; - u32 rec_start; - u32 rec_len; -}; - -#define USERDATA_FIFO_NUM 256 - -struct mpeg12_userdata_info_t { - struct mpeg12_userdata_recored_t records[USERDATA_FIFO_NUM]; - u8 *data_buf; - u8 *data_buf_end; - u32 buf_len; - u32 read_index; - u32 write_index; - u32 last_wp; -}; - -static struct mpeg12_userdata_info_t *p_userdata_mgr; - - -static inline int pool_index(struct vframe_s *vf) -{ - if ((vf >= &vfpool[0]) && (vf <= &vfpool[VF_POOL_SIZE - 1])) - return 0; - else if ((vf >= &vfpool2[0]) && (vf <= &vfpool2[VF_POOL_SIZE - 1])) - return 1; - else - return -1; -} - -static inline u32 index2canvas(u32 index) -{ - const u32 canvas_tab[8] = { -#ifdef NV21 - 0x010100, 0x030302, 0x050504, 0x070706, - 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e -#else - 0x020100, 0x050403, 0x080706, 0x0b0a09, - 0x0e0d0c, 0x11100f, 0x141312, 0x171615 -#endif - }; - - return canvas_tab[index]; -} - -static void set_frame_info(struct vframe_s *vf) -{ - unsigned int ar_bits; - u32 temp; - -#ifdef CONFIG_AM_VDEC_MPEG12_LOG - bool first = (frame_width == 0) && (frame_height == 0); -#endif - temp = READ_VREG(MREG_PIC_WIDTH); - if (temp > 1920) - vf->width = frame_width = 1920; - else - vf->width = frame_width = temp; - - temp = READ_VREG(MREG_PIC_HEIGHT); - if (temp > 1088) - vf->height = frame_height = 1088; - else - vf->height = frame_height = temp; - - vf->flag = 0; - - if (frame_dur > 0) - vf->duration = frame_dur; - else { - int index = (READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf; - vf->duration = frame_dur = frame_rate_tab[index]; - schedule_work(¬ify_work); - } - - gvs->frame_dur = vf->duration; - - ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf; - - if (ar_bits == 0x2) - vf->ratio_control = 0xc0 << DISP_RATIO_ASPECT_RATIO_BIT; - - else if (ar_bits == 0x3) - vf->ratio_control = 0x90 << DISP_RATIO_ASPECT_RATIO_BIT; - - else if (ar_bits == 0x4) - vf->ratio_control = 0x74 << DISP_RATIO_ASPECT_RATIO_BIT; - - else - vf->ratio_control = 0; - - ratio_control = vf->ratio_control; - - amlog_level_if(first, LOG_LEVEL_INFO, - "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", - frame_width, frame_height, frame_dur, - frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]); -} - -static bool error_skip(u32 info, struct vframe_s *vf) -{ - if (error_frame_skip_level) { - /* skip error frame */ - if ((info & PICINFO_ERROR) || (frame_force_skip_flag)) { - if ((info & PICINFO_ERROR) == 0) { - if ((info & PICINFO_TYPE_MASK) == - PICINFO_TYPE_I) - frame_force_skip_flag = 0; - } else { - if (error_frame_skip_level >= 2) - frame_force_skip_flag = 1; - } - if ((info & PICINFO_ERROR) || (frame_force_skip_flag)) - return true; - } - } - - return false; -} - - -static void aml_swap_data(uint8_t *user_data, int ud_size) -{ - int swap_blocks, i, j, k, m; - unsigned char c_temp; - - /* swap byte order */ - swap_blocks = ud_size / 8; - for (i = 0; i < swap_blocks; i++) { - j = i * 8; - k = j + 7; - for (m = 0; m < 4; m++) { - c_temp = user_data[j]; - user_data[j++] = user_data[k]; - user_data[k--] = c_temp; - } - } -} - -/* -#define DUMP_USER_DATA -*/ -#ifdef DUMP_USER_DATA -static int last_wp; -#define DUMP_USER_DATA_HEX - - -#ifdef DUMP_USER_DATA_HEX -static void print_data(unsigned char *pdata, - int len, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id, - u32 reference) -{ - int nLeft; - - nLeft = len; - - pr_info("%d len:%d, flag:0x%x, dur:%d, vpts:0x%x, valid:%d, refer:%d\n", - rec_id, len, flag, - duration, vpts, vpts_valid, - reference); - while (nLeft >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7], - pdata[8], pdata[9], pdata[10], pdata[11], - pdata[12], pdata[13], pdata[14], pdata[15]); - nLeft -= 16; - pdata += 16; - } - - - while (nLeft > 0) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } -} -#endif - - -#define DEBUG_CC_DUMP_ASCII - -#ifdef DEBUG_CC_DUMP_ASCII -static int vbi_to_ascii(int c) -{ - if (c < 0) - return '?'; - - c &= 0x7F; - - if (c < 0x20 || c >= 0x7F) - return '.'; - - return c; -} - -static void dump_cc_ascii(const uint8_t *buf, int poc) -{ - int cc_flag; - int cc_count; - int i; - int szAscii[32]; - int index = 0; - - cc_flag = buf[1] & 0x40; - if (!cc_flag) { - pr_info("### cc_flag is invalid\n"); - return; - } - cc_count = buf[1] & 0x1f; - - for (i = 0; i < cc_count; ++i) { - unsigned int b0; - unsigned int cc_valid; - unsigned int cc_type; - unsigned char cc_data1; - unsigned char cc_data2; - - b0 = buf[3 + i * 3]; - cc_valid = b0 & 4; - cc_type = b0 & 3; - cc_data1 = buf[4 + i * 3]; - cc_data2 = buf[5 + i * 3]; - - - if (cc_type == 0) { - /* NTSC pair, Line 21 */ - szAscii[index++] = vbi_to_ascii(cc_data1); - szAscii[index++] = vbi_to_ascii(cc_data2); - if ((!cc_valid) || (i >= 3)) - break; - } - } - switch (index) { - case 8: - pr_info("push poc:%d : %c %c %c %c %c %c %c %c\n", - poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5], szAscii[6], szAscii[7]); - break; - case 7: - pr_info("push poc:%d : %c %c %c %c %c %c %c\n", - poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5], szAscii[6]); - break; - case 6: - pr_info("push poc:%d : %c %c %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5]); - break; - case 5: - pr_info("push poc:%d : %c %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4]); - break; - case 4: - pr_info("push poc:%d : %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3]); - break; - case 3: - pr_info("push poc:%d : %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2]); - break; - case 2: - pr_info("push poc:%d : %c %c\n", poc, - szAscii[0], szAscii[1]); - break; - case 1: - pr_info("push poc:%d : %c\n", poc, szAscii[0]); - break; - default: - pr_info("push poc:%d and no CC data: index = %d\n", - poc, index); - break; - } -} -#endif - - -static int is_atsc(u8 *pdata) -{ - if ((pdata[0] == 0x47) && - (pdata[1] == 0x41) && - (pdata[2] == 0x39) && - (pdata[3] == 0x34)) - return 1; - else - return 0; -} -/* -#define DUMP_HEAD_INFO_DATA -*/ -static void dump_data(u8 *pdata, - unsigned int user_data_length, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id, - u32 reference) -{ - unsigned char szBuf[256]; - - - memset(szBuf, 0, 256); - memcpy(szBuf, pdata, user_data_length); - - aml_swap_data(szBuf, user_data_length); -#ifdef DUMP_USER_DATA_HEX - print_data(szBuf, - user_data_length, - flag, - duration, - vpts, - vpts_valid, - rec_id, - reference); -#endif - -#ifdef DEBUG_CC_DUMP_ASCII -#ifdef DUMP_HEAD_INFO_DATA - if (is_atsc(szBuf+8)) - dump_cc_ascii(szBuf+8+4, reference); -#else - if (is_atsc(szBuf)) - dump_cc_ascii(szBuf+4, reference); -#endif -#endif -} - - - - -#define MAX_USER_DATA_SIZE 1572864 -static void *user_data_buf; -static unsigned char *pbuf_start; -static int total_len; -static int bskip; -static int n_userdata_id; - -static void reset_user_data_buf(void) -{ - total_len = 0; - pbuf_start = user_data_buf; - bskip = 0; - n_userdata_id = 0; -} - -static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta, - u32 reference) -{ - u32 *pLen; - int info_cnt; - u8 *pbuf_end; - - if (!user_data_buf) - return; - - if (bskip) { - pr_info("over size, skip\n"); - return; - } - info_cnt = 0; - pLen = (u32 *)pbuf_start; - - *pLen = len; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->duration; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->flags; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts_valid; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - - *pLen = n_userdata_id; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = reference; - pbuf_start += sizeof(u32); - info_cnt++; - pLen++; - - - - pbuf_end = (u8 *)ccbuf_phyAddress_virt + CCBUF_SIZE; - if (pdata + len > pbuf_end) { - int first_section_len; - - first_section_len = pbuf_end - pdata; - memcpy(pbuf_start, pdata, first_section_len); - pdata = (u8 *)ccbuf_phyAddress_virt; - pbuf_start += first_section_len; - memcpy(pbuf_start, pdata, len - first_section_len); - pbuf_start += len - first_section_len; - } else { - memcpy(pbuf_start, pdata, len); - pbuf_start += len; - } - - total_len += len + info_cnt * sizeof(u32); - if (total_len >= MAX_USER_DATA_SIZE-4096) - bskip = 1; -} - -static void dump_userdata_info(void *puser_data, - int len, - struct userdata_meta_info_t *pmeta, - u32 reference) -{ - u8 *pstart; - - pstart = (u8 *)puser_data; - -#ifdef DUMP_HEAD_INFO_DATA - push_to_buf(pstart, len, pmeta, reference); -#else - push_to_buf(pstart+8, len - 8, pmeta, reference); -#endif -} - -static void show_user_data_buf(void) -{ - u8 *pbuf; - int len; - unsigned int flag; - unsigned int duration; - unsigned int vpts; - unsigned int vpts_valid; - int rec_id; - u32 reference; - - pr_info("show user data buf\n"); - pbuf = user_data_buf; - - while (pbuf < pbuf_start) { - u32 *pLen; - - pLen = (u32 *)pbuf; - - len = *pLen; - pLen++; - pbuf += sizeof(u32); - - duration = *pLen; - pLen++; - pbuf += sizeof(u32); - - flag = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts_valid = *pLen; - pLen++; - pbuf += sizeof(u32); - - rec_id = *pLen; - pLen++; - pbuf += sizeof(u32); - - reference = *pLen; - pLen++; - pbuf += sizeof(u32); - - - dump_data(pbuf, len, flag, duration, - vpts, vpts_valid, rec_id, reference); - pbuf += len; - msleep(30); - } -} -#endif - -static void vmpeg12_add_userdata(struct userdata_meta_info_t meta_info, - int wp, - u32 reference); -/* -#define PRINT_HEAD_INFO -*/ -static void userdata_push_do_work(struct work_struct *work) -{ - u32 reg; - u32 offset, pts; - u64 pts_us64 = 0; - u8 *pdata; - u8 head_info[8]; - struct userdata_meta_info_t meta_info; - u32 wp; - u32 index; - u32 picture_struct; - u32 reference; - u32 picture_type; - u32 temp; -#ifdef PRINT_HEAD_INFO - u8 *ptype_str; -#endif - memset(&meta_info, 0, sizeof(meta_info)); - - meta_info.duration = frame_dur; - - reg = READ_VREG(AV_SCRATCH_M); - meta_info.flags = ((reg >> 30) << 1); - meta_info.flags |= (VFORMAT_MPEG12 << 3); - /* check top_field_first flag */ - if ((reg >> 28) & 0x1) { - meta_info.flags |= (1 << 10); - meta_info.flags |= (((reg >> 29) & 0x1) << 11); - } - - offset = READ_VREG(AV_SCRATCH_N); - if (offset != last_offset) { - meta_info.flags |= 1; - last_offset = offset; - } - - if (pts_pickout_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) { - pr_info("pick out pts failed by offset = 0x%x\n", offset); - pts = -1; - meta_info.vpts_valid = 0; - } else - meta_info.vpts_valid = 1; - meta_info.vpts = pts; - - if (!ccbuf_phyAddress_is_remaped_nocache && - ccbuf_phyAddress && - ccbuf_phyAddress_virt) { - codec_mm_dma_flush( - ccbuf_phyAddress_virt, - CCBUF_SIZE, - DMA_FROM_DEVICE); - } - - mutex_lock(&userdata_mutex); - if (p_userdata_mgr && ccbuf_phyAddress_virt) { - int new_wp; - - new_wp = reg & 0xffff; - if (new_wp < p_userdata_mgr->last_wp) - pdata = (u8 *)ccbuf_phyAddress_virt; - else - pdata = (u8 *)ccbuf_phyAddress_virt + - p_userdata_mgr->last_wp; - memcpy(head_info, pdata, 8); - } else - memset(head_info, 0, 8); - mutex_unlock(&userdata_mutex); - aml_swap_data(head_info, 8); - - wp = (head_info[0] << 8 | head_info[1]); - index = (head_info[2] << 8 | head_info[3]); - - picture_struct = (head_info[6] << 8 | head_info[7]); - temp = (head_info[4] << 8 | head_info[5]); - reference = temp & 0x3FF; - picture_type = (temp >> 10) & 0x7; - -#if 0 - pr_info("index = %d, wp = %d, ref = %d, type = %d, struct = 0x%x, vpts:0x%x\n", - index, wp, reference, - picture_type, picture_struct, meta_info.vpts); -#endif - switch (picture_type) { - case 1: - /* pr_info("I type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (1<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " I"; -#endif - break; - case 2: - /* pr_info("P type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (2<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " P"; -#endif - break; - case 3: - /* pr_info("B type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (3<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " B"; -#endif - break; - case 4: - /* pr_info("D type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (4<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " D"; -#endif - break; - default: - /* pr_info("Unknown type:0x%x, pos:%d\n", - pheader->picture_coding_type, - (meta_info.flags>>1)&0x3); */ -#ifdef PRINT_HEAD_INFO - ptype_str = " U"; -#endif - break; - } -#ifdef PRINT_HEAD_INFO - pr_info("ref:%d, type:%s, ext:%d, offset:0x%x, first:%d, id:%d\n", - reference, ptype_str, - (reg >> 30), offset, - (reg >> 28)&0x3, - n_userdata_id); -#endif - vmpeg12_add_userdata(meta_info, reg & 0xffff, reference); - - WRITE_VREG(AV_SCRATCH_M, 0); -} - -static void vmpeg12_notify_work(struct work_struct *work) -{ - pr_info("frame duration changed %d\n", frame_dur); - if (fr_hint_status == VDEC_NEED_HINT) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)frame_dur)); - fr_hint_status = VDEC_HINTED; - } - return; -} -static irqreturn_t vmpeg12_isr(int irq, void *dev_id) -{ - u32 reg, info, seqinfo, offset, pts, pts_valid = 0; - struct vframe_s *vf; - u64 pts_us64 = 0; - u32 frame_size; - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - reg = READ_VREG(MREG_BUFFEROUT); - - if (reg) { - info = READ_VREG(MREG_PIC_INFO); - offset = READ_VREG(MREG_FRAME_OFFSET); - seqinfo = READ_VREG(MREG_SEQ_INFO); - - if ((first_i_frame_ready == 0) && - ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && - ((info & PICINFO_ERROR) == 0)) - first_i_frame_ready = 1; - - if ((pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, - &frame_size, 0, &pts_us64) == 0) - && (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) - || ((info & PICINFO_TYPE_MASK) == - PICINFO_TYPE_P))) - pts_valid = 1; - - if (pts_valid && lastpts == pts) - pts_valid = 0; - if (pts_valid) - lastpts = pts; - /*if (frame_prog == 0) */ - { - frame_prog = info & PICINFO_PROG; - if ((seqinfo & SEQINFO_EXT_AVAILABLE) - && (!(seqinfo & SEQINFO_PROG))) - frame_prog = 0; - } - - if ((dec_control & - DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) - && (frame_width == 720 || frame_width == 480) - && (frame_height == 576) - && (frame_dur == 3840)) - frame_prog = 0; - else if ((dec_control & - DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) - && (frame_width == 704) && (frame_height == 480) - && (frame_dur == 3200)) - frame_prog = 0; - else if ((dec_control & - DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) - && (frame_width == 704) && (frame_height == 576) - && (frame_dur == 3840)) - frame_prog = 0; - else if ((dec_control & - DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) - && (frame_width == 544) && (frame_height == 576) - && (frame_dur == 3840)) - frame_prog = 0; - else if ((dec_control & - DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) - && (frame_width == 480) && (frame_height == 576) - && (frame_dur == 3840)) - frame_prog = 0; - else if (dec_control & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) - frame_prog = 0; - if (frame_prog & PICINFO_PROG) { - u32 index = ((reg & 0xf) - 1) & 7; - - seqinfo = READ_VREG(MREG_SEQ_INFO); - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - set_frame_info(vf); - /*pr_info("video signal type:0x%x\n", - READ_VREG(AV_SCRATCH_H));*/ - vf->signal_type = READ_VREG(AV_SCRATCH_H); - vf->index = index; -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - if ((seqinfo & SEQINFO_EXT_AVAILABLE) - && (seqinfo & SEQINFO_PROG)) { - if (info & PICINFO_RPT_FIRST) { - if (info & PICINFO_TOP_FIRST) { - vf->duration = - vf->duration * 3; - /* repeat three times */ - } else { - vf->duration = - vf->duration * 2; - /* repeat two times */ - } - } - vf->duration_pulldown = 0; - /* no pull down */ - - } else { - vf->duration_pulldown = - (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - } - - /*count info*/ - vdec_count_info(gvs, info & PICINFO_ERROR, offset); - - vf->duration += vf->duration_pulldown; - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(index); - vf->orientation = 0; - vf->pts = (pts_valid) ? pts : 0; - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - vf->type_original = vf->type; - - vfbuf_use[index] = 1; - - if ((error_skip(info, vf)) || - ((first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) != - PICINFO_TYPE_I))) { - gvs->drop_frame_count++; - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - } else { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - index); - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - - } else { - u32 index = ((reg & 0xf) - 1) & 7; - int first_field_type = (info & PICINFO_TOP_FIRST) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; - -#ifdef INTERLACE_SEQ_ALWAYS - /* once an interlaced sequence exist, - *always force interlaced type - */ - /* to make DI easy. */ - dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE; -#endif -#if 0 - if (info & PICINFO_FRAME) { - frame_rpt_state = - (info & PICINFO_TOP_FIRST) ? - FRAME_REPEAT_TOP : FRAME_REPEAT_BOT; - } else { - if (frame_rpt_state == FRAME_REPEAT_TOP) { - first_field_type = - VIDTYPE_INTERLACE_TOP; - } else if (frame_rpt_state == - FRAME_REPEAT_BOT) { - first_field_type = - VIDTYPE_INTERLACE_BOTTOM; - } - frame_rpt_state = FRAME_REPEAT_NONE; - } -#else - frame_rpt_state = FRAME_REPEAT_NONE; -#endif - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - if (info & PICINFO_RPT_FIRST) - vfbuf_use[index] = 3; - else - vfbuf_use[index] = 2; - - set_frame_info(vf); - vf->signal_type = 0; - vf->index = index; - vf->type = - (first_field_type == VIDTYPE_INTERLACE_TOP) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - if (info & PICINFO_RPT_FIRST) - vf->duration /= 3; - else - vf->duration >>= 1; - vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - vf->duration += vf->duration_pulldown; - vf->orientation = 0; - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(index); - vf->pts = (pts_valid) ? pts : 0; - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - vf->type_original = vf->type; - - if ((error_skip(info, vf)) || - ((first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) != - PICINFO_TYPE_I))) { - gvs->drop_frame_count++; - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - } else { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - index); - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - set_frame_info(vf); - vf->signal_type = 0; - vf->index = index; - vf->type = (first_field_type == - VIDTYPE_INTERLACE_TOP) ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - if (info & PICINFO_RPT_FIRST) - vf->duration /= 3; - else - vf->duration >>= 1; - vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - vf->duration += vf->duration_pulldown; - vf->orientation = 0; - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(index); - vf->pts = 0; - vf->pts_us64 = 0; - vf->type_original = vf->type; - - /*count info*/ - vdec_count_info(gvs, info & PICINFO_ERROR, offset); - - if ((error_skip(info, vf)) || - ((first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) != - PICINFO_TYPE_I))) { - gvs->drop_frame_count++; - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - } else { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - index); - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - - if (info & PICINFO_RPT_FIRST) { - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info("error, no available buffer slot."); - return IRQ_HANDLED; - } - - set_frame_info(vf); - - vf->index = index; - vf->type = (first_field_type == - VIDTYPE_INTERLACE_TOP) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->duration /= 3; - vf->duration_pulldown = - (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - vf->duration += vf->duration_pulldown; - vf->orientation = 0; - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(index); - vf->pts = 0; - vf->pts_us64 = 0; - if ((error_skip(info, vf)) || - ((first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) - != PICINFO_TYPE_I))) { - kfifo_put(&recycle_q, - (const struct vframe_s *)vf); - } else { - kfifo_put(&display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - } - } - WRITE_VREG(MREG_BUFFEROUT, 0); - } - - reg = READ_VREG(AV_SCRATCH_M); - if (reg & (1<<16)) - schedule_work(&userdata_push_work); - - return IRQ_HANDLED; -} - -static struct vframe_s *vmpeg_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vmpeg_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) -{ - if (pool_index(vf) == cur_pool_idx) - kfifo_put(&recycle_q, (const struct vframe_s *)vf); -} - -static int vmpeg_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vmpeg_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vmpeg12_local_init(); - vmpeg12_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vmpeg_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - - return 0; -} - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER -static void vmpeg12_ppmgr_reset(void) -{ - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); - - vmpeg12_local_init(); - - pr_info("vmpeg12dec: vf_ppmgr_reset\n"); -} -#endif - -static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit); -static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec); - -static void reset_do_work(struct work_struct *work) -{ - amvdec_stop(); - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vmpeg12_ppmgr_reset(); -#else - vf_light_unreg_provider(&vmpeg_vf_prov); - vmpeg12_local_init(); - vf_reg_provider(&vmpeg_vf_prov); -#endif - vmpeg12_prot_init(); - vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); - vmpeg12_reset_userdata_fifo(vdec, 1); -#ifdef DUMP_USER_DATA - last_wp = 0; -#endif - - amvdec_start(); -} - -static void vmpeg12_set_clk(struct work_struct *work) -{ - { - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_MPEG12, - frame_width, frame_height, fps); - } -} - - -static void vmpeg_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - int fatal_reset = 0; - - enum receviver_start_e state = RECEIVER_INACTIVE; - - if (vf_get_receiver(PROVIDER_NAME)) { - state = vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) { - /* receiver has no event_cb or - *receiver's event_cb does not process this event - */ - state = RECEIVER_INACTIVE; - } - } else - state = RECEIVER_INACTIVE; - - if (READ_VREG(MREG_FATAL_ERROR) == 1) - fatal_reset = 1; - - if ((READ_VREG(MREG_WAIT_BUFFER) != 0) && - (kfifo_is_empty(&recycle_q)) && - (kfifo_is_empty(&display_q)) && (state == RECEIVER_INACTIVE)) { - if (++wait_buffer_counter > 4) - fatal_reset = 1; - - } else - wait_buffer_counter = 0; - - if (fatal_reset && (kfifo_is_empty(&display_q))) { - pr_info("$$$$decoder is waiting for buffer or fatal reset.\n"); - schedule_work(&reset_work); - } - - while (!kfifo_is_empty(&recycle_q) && (READ_VREG(MREG_BUFFERIN) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < DECODE_BUFFER_NUM_MAX) && - (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(MREG_BUFFERIN, vf->index + 1); - vf->index = DECODE_BUFFER_NUM_MAX; - } - - if (pool_index(vf) == cur_pool_idx) { - kfifo_put(&newframe_q, - (const struct vframe_s *)vf); - } - } - } - - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) - schedule_work(&set_clk_work); - - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (frame_dur != 0) - vstatus->frame_rate = 96000 / frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(AV_SCRATCH_C); - vstatus->status = stat; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - vstatus->ratio_control = ratio_control; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -int vmpeg12_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - - - - -static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len) -{ - mutex_lock(&userdata_mutex); - - p_userdata_mgr = (struct mpeg12_userdata_info_t *) - vmalloc(sizeof(struct mpeg12_userdata_info_t)); - if (p_userdata_mgr) { - memset(p_userdata_mgr, 0, - sizeof(struct mpeg12_userdata_info_t)); - p_userdata_mgr->data_buf = userdata_buf; - p_userdata_mgr->buf_len = buf_len; - p_userdata_mgr->data_buf_end = userdata_buf + buf_len; - } - mutex_unlock(&userdata_mutex); -} - -static void vmpeg12_destroy_userdata_manager(void) -{ - mutex_lock(&userdata_mutex); - - if (p_userdata_mgr) { - vfree(p_userdata_mgr); - p_userdata_mgr = NULL; - } - mutex_unlock(&userdata_mutex); -} - -static void vmpeg12_add_userdata(struct userdata_meta_info_t meta_info, - int wp, - u32 reference) -{ - struct mpeg12_userdata_recored_t *p_userdata_rec; - int data_length; - - mutex_lock(&userdata_mutex); - - if (p_userdata_mgr) { - if (wp > p_userdata_mgr->last_wp) - data_length = wp - p_userdata_mgr->last_wp; - else { - p_userdata_mgr->last_wp = 0; - data_length = wp - p_userdata_mgr->last_wp; - } - - if (data_length & 0x7) - data_length = (((data_length + 8) >> 3) << 3); -/* -pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", - p_userdata_mgr->read_index, - p_userdata_mgr->write_index, - data_length, - p_userdata_mgr->last_wp, - wp, - n_userdata_id); -*/ - p_userdata_rec = p_userdata_mgr->records - + p_userdata_mgr->write_index; - p_userdata_rec->meta_info = meta_info; - p_userdata_rec->rec_start = p_userdata_mgr->last_wp; - p_userdata_rec->rec_len = data_length; - p_userdata_mgr->last_wp = wp; - -#ifdef DUMP_USER_DATA - dump_userdata_info(p_userdata_mgr->data_buf - + p_userdata_rec->rec_start, - data_length, - &meta_info, - reference); - n_userdata_id++; -#endif - - p_userdata_mgr->write_index++; - if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM) - p_userdata_mgr->write_index = 0; - } - mutex_unlock(&userdata_mutex); - - vdec_wakeup_userdata_poll(vdec); -} - - -static int vmpeg12_user_data_read(struct vdec_s *vdec, - struct userdata_param_t *puserdata_para) -{ - int rec_ri, rec_wi; - int rec_len; - u8 *rec_data_start; - u8 *pdest_buf; - struct mpeg12_userdata_recored_t *p_userdata_rec; - u32 data_size; - u32 res; - int copy_ok = 1; - - pdest_buf = puserdata_para->pbuf_addr; - - mutex_lock(&userdata_mutex); - - if (!p_userdata_mgr) { - mutex_unlock(&userdata_mutex); - return 0; - } -/* - pr_info("ri = %d, wi = %d\n", - p_userdata_mgr->read_index, - p_userdata_mgr->write_index); -*/ - rec_ri = p_userdata_mgr->read_index; - rec_wi = p_userdata_mgr->write_index; - - if (rec_ri == rec_wi) { - mutex_unlock(&userdata_mutex); - return 0; - } - - p_userdata_rec = p_userdata_mgr->records + rec_ri; - - rec_len = p_userdata_rec->rec_len; - rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf; -/* - pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n", - p_userdata_rec->rec_len, - p_userdata_rec->rec_start, - puserdata_para->buf_len); -*/ - if (rec_len <= puserdata_para->buf_len) { - /* dvb user data buffer is enought to copy the whole recored. */ - data_size = rec_len; - if (rec_data_start + data_size - > p_userdata_mgr->data_buf_end) { - int first_section_len; - - first_section_len = p_userdata_mgr->buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p1 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)p_userdata_mgr->data_buf, - data_size - first_section_len); - if (res) { - pr_info("p2 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p3 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - p_userdata_mgr->read_index++; - if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM) - p_userdata_mgr->read_index = 0; - } - } else { - /* dvb user data buffer is not enought - to copy the whole recored. */ - data_size = puserdata_para->buf_len; - if (rec_data_start + data_size - > p_userdata_mgr->data_buf_end) { - int first_section_len; - - first_section_len = p_userdata_mgr->buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p4 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - /* first secton copy is ok*/ - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)p_userdata_mgr->data_buf, - data_size - first_section_len); - if (res) { - pr_info("p5 read not end res=%d, request=%d\n", - res, - data_size - first_section_len); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p6 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - p_userdata_mgr->read_index++; - if (p_userdata_mgr->read_index - >= USERDATA_FIFO_NUM) - p_userdata_mgr->read_index = 0; - } - - } - - puserdata_para->meta_info = p_userdata_rec->meta_info; - - if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) - puserdata_para->meta_info.records_in_que = - p_userdata_mgr->write_index - - p_userdata_mgr->read_index; - else - puserdata_para->meta_info.records_in_que = - p_userdata_mgr->write_index + - USERDATA_FIFO_NUM - - p_userdata_mgr->read_index; - puserdata_para->version = (0<<24|0<<16|0<<8|1); - - mutex_unlock(&userdata_mutex); - - return 1; -} - -static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit) -{ - mutex_lock(&userdata_mutex); - - if (p_userdata_mgr) { - pr_info("vmpeg12_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", - bInit, p_userdata_mgr->read_index, - p_userdata_mgr->write_index); - p_userdata_mgr->read_index = 0; - p_userdata_mgr->write_index = 0; - - if (bInit) - p_userdata_mgr->last_wp = 0; - } - - mutex_unlock(&userdata_mutex); -} - -static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec) -{ - amstream_wakeup_userdata_poll(vdec); -} - -static int vmpeg12_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -/****************************************/ -static int vmpeg12_canvas_init(void) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 decbuf_size, decbuf_y_size, decbuf_uv_size; - static unsigned long buf_start; - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - /* HD & SD */ - canvas_width = 1920; - canvas_height = 1088; - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - - if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* workspace mem */ - decbuf_size = WORKSPACE_SIZE; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; - - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { - - WRITE_VREG(MREG_CO_MV_START, (buf_start + CCBUF_SIZE)); - if (!ccbuf_phyAddress) { - ccbuf_phyAddress - = (u32)buf_start; - - ccbuf_phyAddress_virt - = codec_mm_phys_to_virt( - ccbuf_phyAddress); - if (!ccbuf_phyAddress_virt) { - ccbuf_phyAddress_virt - = codec_mm_vmap( - ccbuf_phyAddress, - CCBUF_SIZE); - ccbuf_phyAddress_is_remaped_nocache = 1; - } - } - - } else { -#ifdef NV21 - canvas_config(2 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(2 * i + 1, - buf_start + - decbuf_y_size, canvas_width, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); -#else - canvas_config(3 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 1, - buf_start + - decbuf_y_size, canvas_width / 2, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 2, - buf_start + - decbuf_y_size + decbuf_uv_size, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); -#endif - } - } - - return 0; -} - -static int vmpeg12_prot_init(void) -{ - int ret; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - int save_reg = READ_VREG(POWER_CTL_VLD); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1<<9) | (1<<8)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(MDEC_SW_RESET, (1 << 7)); - WRITE_VREG(MDEC_SW_RESET, 0); - } - - WRITE_VREG(POWER_CTL_VLD, save_reg); - - } else - WRITE_RESET_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); - - ret = vmpeg12_canvas_init(); - -#ifdef NV21 - WRITE_VREG(AV_SCRATCH_0, 0x010100); - WRITE_VREG(AV_SCRATCH_1, 0x030302); - WRITE_VREG(AV_SCRATCH_2, 0x050504); - WRITE_VREG(AV_SCRATCH_3, 0x070706); - WRITE_VREG(AV_SCRATCH_4, 0x090908); - WRITE_VREG(AV_SCRATCH_5, 0x0b0b0a); - WRITE_VREG(AV_SCRATCH_6, 0x0d0d0c); - WRITE_VREG(AV_SCRATCH_7, 0x0f0f0e); -#else - WRITE_VREG(AV_SCRATCH_0, 0x020100); - WRITE_VREG(AV_SCRATCH_1, 0x050403); - WRITE_VREG(AV_SCRATCH_2, 0x080706); - WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); - WRITE_VREG(AV_SCRATCH_4, 0x0e0d0c); - WRITE_VREG(AV_SCRATCH_5, 0x11100f); - WRITE_VREG(AV_SCRATCH_6, 0x141312); - WRITE_VREG(AV_SCRATCH_7, 0x171615); -#endif - - /* set to mpeg1 default */ - WRITE_VREG(MPEG1_2_REG, 0); - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - /* for Mpeg1 default value */ - WRITE_VREG(PIC_HEAD_INFO, 0x380); - /* disable mpeg4 */ - WRITE_VREG(M4_CONTROL_REG, 0); - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - /* clear buffer IN/OUT registers */ - WRITE_VREG(MREG_BUFFERIN, 0); - WRITE_VREG(MREG_BUFFEROUT, 0); - /* set reference width and height */ - if ((frame_width != 0) && (frame_height != 0)) - WRITE_VREG(MREG_CMD, (frame_width << 16) | frame_height); - else - WRITE_VREG(MREG_CMD, 0); - WRITE_VREG(MREG_FORCE_I_RDY, (force_first_i_ready & 0x01)); - /* clear error count */ - WRITE_VREG(MREG_ERROR_COUNT, 0); - WRITE_VREG(MREG_FATAL_ERROR, 0); - /* clear wait buffer status */ - WRITE_VREG(MREG_WAIT_BUFFER, 0); -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - return ret; -} - -static void vmpeg12_local_init(void) -{ - int i; - - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - cur_pool_idx ^= 1; - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf; - - if (cur_pool_idx == 0) { - vf = &vfpool[i]; - vfpool[i].index = DECODE_BUFFER_NUM_MAX; - } else { - vf = &vfpool2[i]; - vfpool2[i].index = DECODE_BUFFER_NUM_MAX; - } - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - vfbuf_use[i] = 0; - if (mm_blk_handle) { - mutex_lock(&userdata_mutex); - if (p_userdata_mgr) { - vfree(p_userdata_mgr); - p_userdata_mgr = NULL; - } - if (ccbuf_phyAddress_is_remaped_nocache) - codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); - ccbuf_phyAddress_virt = NULL; - ccbuf_phyAddress = 0; - ccbuf_phyAddress_is_remaped_nocache = 0; - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - mutex_unlock(&userdata_mutex); - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - - - frame_width = frame_height = frame_dur = frame_prog = 0; - frame_force_skip_flag = 0; - wait_buffer_counter = 0; - first_i_frame_ready = force_first_i_ready; - saved_resolution = 0; - dec_control &= DEC_CONTROL_INTERNAL_MASK; -} - -static s32 vmpeg12_init(void) -{ - int ret = -1, size = -1; - char *buf = vmalloc(0x1000 * 16); - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - vmpeg12_local_init(); - - amvdec_enable(); - - size = get_firmware_data(VIDEO_DEC_MPEG12, buf); - if (size < 0) { - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_MPEG12, "mpeg12", buf); - if (ret < 0) { - amvdec_disable(); - vfree(buf); - pr_err("MPEG12: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(buf); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - vmpeg12_prot_init(); - - ret = vdec_request_irq(VDEC_IRQ_1, vmpeg12_isr, - "vmpeg12-irq", (void *)vmpeg12_dec_id); - - if (ret) { - amvdec_disable(); - amlog_level(LOG_LEVEL_ERROR, "vmpeg12 irq register error.\n"); - return -ENOENT; - } - - stat |= STAT_ISR_REG; -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, - NULL); - vf_reg_provider(&vmpeg_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, - NULL); - vf_reg_provider(&vmpeg_vf_prov); -#endif - if (vmpeg12_amstream_dec_info.rate != 0) { - if (!is_reset) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long) - vmpeg12_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; - } - } else - fr_hint_status = VDEC_NEED_HINT; - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong)&recycle_timer; - recycle_timer.function = vmpeg_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - return 0; -} - -#ifdef DUMP_USER_DATA -static int amvdec_mpeg12_init_userdata_dump(void) -{ - user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); - if (user_data_buf) - return 1; - else - return 0; -} -#endif - -static int amvdec_mpeg12_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe start.\n"); - - if (pdata == NULL) { - amlog_level(LOG_LEVEL_ERROR, - "amvdec_mpeg12 platform data undefined.\n"); - return -EFAULT; - } - - if (pdata->sys_info) - vmpeg12_amstream_dec_info = *pdata->sys_info; - - pdata->dec_status = vmpeg12_dec_status; - pdata->set_isreset = vmpeg12_set_isreset; - - pdata->user_data_read = vmpeg12_user_data_read; - pdata->reset_userdata_fifo = vmpeg12_reset_userdata_fifo; - pdata->wakeup_userdata_poll = vmpeg12_wakeup_userdata_poll; - is_reset = 0; - - vmpeg12_vdec_info_init(); - - INIT_WORK(&set_clk_work, vmpeg12_set_clk); - if (vmpeg12_init() < 0) { - amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg12 init failed.\n"); - kfree(gvs); - gvs = NULL; - pdata->dec_status = NULL; - return -ENODEV; - } - vdec = pdata; -#ifdef DUMP_USER_DATA - amvdec_mpeg12_init_userdata_dump(); -#endif - vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); - - INIT_WORK(&userdata_push_work, userdata_push_do_work); - INIT_WORK(¬ify_work, vmpeg12_notify_work); - INIT_WORK(&reset_work, reset_do_work); - - - last_offset = 0xFFFFFFFF; -#ifdef DUMP_USER_DATA - last_wp = 0; - reset_user_data_buf(); -#endif - - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe end.\n"); - - return 0; -} - -static int amvdec_mpeg12_remove(struct platform_device *pdev) -{ - cancel_work_sync(&userdata_push_work); - cancel_work_sync(¬ify_work); - cancel_work_sync(&reset_work); - - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)vmpeg12_dec_id); - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - cancel_work_sync(&set_clk_work); - if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); - fr_hint_status = VDEC_NO_NEED_HINT; - - vf_unreg_provider(&vmpeg_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - amvdec_disable(); - if (ccbuf_phyAddress_is_remaped_nocache) - codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); - - ccbuf_phyAddress_virt = NULL; - ccbuf_phyAddress = 0; - ccbuf_phyAddress_is_remaped_nocache = 0; - vmpeg12_destroy_userdata_manager(); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 remove.\n"); - - kfree(gvs); - gvs = NULL; - vdec = NULL; - -#ifdef DUMP_USER_DATA - if (user_data_buf) { - show_user_data_buf(); - kfree(user_data_buf); - user_data_buf = NULL; - } -#endif - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_mpeg12_driver = { - .probe = amvdec_mpeg12_probe, - .remove = amvdec_mpeg12_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_mpeg12_profile = { - .name = "mpeg12", - .profile = "" -}; - - -static struct mconfig mpeg12_configs[] = { - MC_PU32("stat", &stat), - MC_PU32("dec_control", &dec_control), - MC_PU32("error_frame_skip_level", &error_frame_skip_level), -}; -static struct mconfig_node mpeg12_node; - - -static int __init amvdec_mpeg12_driver_init_module(void) -{ - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 module init\n"); - - if (platform_driver_register(&amvdec_mpeg12_driver)) { - amlog_level(LOG_LEVEL_ERROR, - "failed to register amvdec_mpeg12 driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvdec_mpeg12_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &mpeg12_node, - "mpeg12", mpeg12_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit amvdec_mpeg12_driver_remove_module(void) -{ - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 module remove.\n"); - - platform_driver_unregister(&amvdec_mpeg12_driver); -} - -/****************************************/ -module_param(dec_control, uint, 0664); -MODULE_PARM_DESC(dec_control, "\n amvmpeg12 decoder control\n"); -module_param(error_frame_skip_level, uint, 0664); -MODULE_PARM_DESC(error_frame_skip_level, - "\n amvdec_mpeg12 error_frame_skip_level\n"); -module_param(force_first_i_ready, uint, 0664); -MODULE_PARM_DESC(force_first_i_ready, "\n amvmpeg12 force_first_i_ready\n"); - -module_init(amvdec_mpeg12_driver_init_module); -module_exit(amvdec_mpeg12_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC MPEG1/2 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h deleted file mode 100644 index e26a41437e0f..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * drivers/amlogic/amports/vmpeg12.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VMPEG12_H -#define VMPEG12_H - -/* /#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -/* TODO: move to register headers */ -#define VPP_VD1_POSTBLEND (1 << 10) -/* /#endif */ - -#endif /* VMPEG12_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c deleted file mode 100644 index a8962ddd9f70..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c +++ /dev/null @@ -1,2854 +0,0 @@ -/* - * drivers/amlogic/amports/vmpeg12.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "../../../stream_input/amports/amports_priv.h" - -#include "../utils/vdec_input.h" -#include "../utils/vdec.h" -#include "../utils/amvdec.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include "../utils/firmware.h" - - -#define MEM_NAME "codec_mmpeg12" -#define CHECK_INTERVAL (HZ/100) - -#define DRIVER_NAME "ammvdec_mpeg12" -#define MODULE_NAME "ammvdec_mpeg12" -#define MREG_REF0 AV_SCRATCH_2 -#define MREG_REF1 AV_SCRATCH_3 -/* protocol registers */ -#define MREG_SEQ_INFO AV_SCRATCH_4 -#define MREG_PIC_INFO AV_SCRATCH_5 -#define MREG_PIC_WIDTH AV_SCRATCH_6 -#define MREG_PIC_HEIGHT AV_SCRATCH_7 -#define MREG_INPUT AV_SCRATCH_8 /*input_type*/ -#define MREG_BUFFEROUT AV_SCRATCH_9 /*FROM_AMRISC_REG*/ - -#define MREG_CMD AV_SCRATCH_A -#define MREG_CO_MV_START AV_SCRATCH_B -#define MREG_ERROR_COUNT AV_SCRATCH_C -#define MREG_FRAME_OFFSET AV_SCRATCH_D -#define MREG_WAIT_BUFFER AV_SCRATCH_E -#define MREG_FATAL_ERROR AV_SCRATCH_F - -#define PICINFO_ERROR 0x80000000 -#define PICINFO_TYPE_MASK 0x00030000 -#define PICINFO_TYPE_I 0x00000000 -#define PICINFO_TYPE_P 0x00010000 -#define PICINFO_TYPE_B 0x00020000 - -#define GET_SLICE_TYPE(type) ("IPB###"[(type&PICINFO_TYPE_MASK)>>16]) -#define PICINFO_PROG 0x8000 -#define PICINFO_RPT_FIRST 0x4000 -#define PICINFO_TOP_FIRST 0x2000 -#define PICINFO_FRAME 0x1000 -#define TOP_FIELD 0x1000 -#define BOTTOM_FIELD 0x2000 -#define FRAME_PICTURE 0x3000 -#define FRAME_PICTURE_MASK 0x3000 - -#define SEQINFO_EXT_AVAILABLE 0x80000000 -#define SEQINFO_PROG 0x00010000 -#define CCBUF_SIZE (5*1024) - -#define VF_POOL_SIZE 32 -#define DECODE_BUFFER_NUM_MAX 8 -#define PUT_INTERVAL (HZ/100) -#define WORKSPACE_SIZE (4*SZ_64K) /*swap&ccbuf&matirx&MV*/ -#define CTX_LMEM_SWAP_OFFSET 0 -#define CTX_CCBUF_OFFSET 0x800 -#define CTX_QUANT_MATRIX_OFFSET (CTX_CCBUF_OFFSET + 5*1024) -#define CTX_CO_MV_OFFSET (CTX_QUANT_MATRIX_OFFSET + 1*1024) -#define CTX_DECBUF_OFFSET (CTX_CO_MV_OFFSET + 0x11000) - -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) -#define DEFAULT_MEM_SIZE (32*SZ_1M) -static u32 buf_size = 32 * 1024 * 1024; -static int pre_decode_buf_level = 0x800; -static u32 dec_control; -static u32 error_frame_skip_level; -static u32 stat; -static u32 udebug_flag; -static unsigned int radr; -static unsigned int rval; - -#define VMPEG12_DEV_NUM 9 -static unsigned int max_decode_instance_num = VMPEG12_DEV_NUM; -static unsigned int max_process_time[VMPEG12_DEV_NUM]; -static unsigned int decode_timeout_val = 100; -#define INCPTR(p) ptr_atomic_wrap_inc(&p) - -#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002 -#define DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE 0x0004 -#define DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE 0x0008 -#define DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE 0x0010 -#define DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE 0x0020 -#define DEC_CONTROL_INTERNAL_MASK 0x0fff -#define DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE 0x1000 - -#define INTERLACE_SEQ_ALWAYS - -#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -#endif - -#define AGAIN_HAS_THRESHOLD - -#ifdef AGAIN_HAS_THRESHOLD -u32 again_threshold = 0x40; -#endif - -/* -#define DUMP_USER_DATA -*/ - -enum { - FRAME_REPEAT_TOP, - FRAME_REPEAT_BOT, - FRAME_REPEAT_NONE -}; -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_ERROR 3 -#define DEC_RESULT_FORCE_EXIT 4 -#define DEC_RESULT_EOS 5 -#define DEC_RESULT_GET_DATA 6 -#define DEC_RESULT_GET_DATA_RETRY 7 - -#define DEC_DECODE_TIMEOUT 0x21 -#define DECODE_ID(hw) (hw_to_vdec(hw)->id) -#define DECODE_STOP_POS AV_SCRATCH_K - -static struct vframe_s *vmpeg_vf_peek(void *); -static struct vframe_s *vmpeg_vf_get(void *); -static void vmpeg_vf_put(struct vframe_s *, void *); -static int vmpeg_vf_states(struct vframe_states *states, void *); -static int vmpeg_event_cb(int type, void *data, void *private_data); - -struct mmpeg2_userdata_record_t { - struct userdata_meta_info_t meta_info; - u32 rec_start; - u32 rec_len; -}; - -#define USERDATA_FIFO_NUM 256 -#define MAX_FREE_USERDATA_NODES 5 - -struct mmpeg2_userdata_info_t { - struct mmpeg2_userdata_record_t records[USERDATA_FIFO_NUM]; - u8 *data_buf; - u8 *data_buf_end; - u32 buf_len; - u32 read_index; - u32 write_index; - u32 last_wp; -}; -#define MAX_UD_RECORDS 5 - -struct vdec_mpeg12_hw_s { - spinlock_t lock; - struct platform_device *platform_dev; - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - struct vframe_s vfpool[VF_POOL_SIZE]; - s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; - u32 frame_width; - u32 frame_height; - u32 frame_dur; - u32 frame_prog; - u32 seqinfo; - u32 ctx_valid; - u32 dec_control; - void *mm_blk_handle; - struct vframe_chunk_s *chunk; - u32 stat; - u8 init_flag; - unsigned long buf_start; - u32 buf_size; - u32 reg_pic_width; - u32 reg_pic_height; - u32 reg_mpeg1_2_reg; - u32 reg_pic_head_info; - u32 reg_f_code_reg; - u32 reg_slice_ver_pos_pic_type; - u32 reg_vcop_ctrl_reg; - u32 reg_mb_info; - u32 reg_signal_type; - u32 frame_num; - struct timer_list check_timer; - u32 decode_timeout_count; - u32 start_process_time; - u32 last_vld_level; - u32 eos; - u32 buffer_info[DECODE_BUFFER_NUM_MAX]; - u32 pts[DECODE_BUFFER_NUM_MAX]; - u64 pts64[DECODE_BUFFER_NUM_MAX]; - bool pts_valid[DECODE_BUFFER_NUM_MAX]; - u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; - struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; - struct dec_sysinfo vmpeg12_amstream_dec_info; - - s32 refs[2]; - int dec_result; - struct work_struct work; - struct work_struct notify_work; - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - unsigned long ccbuf_phyAddress; - void *ccbuf_phyAddress_virt; - unsigned long ccbuf_phyAddress_is_remaped_nocache; - u32 frame_rpt_state; -/* for error handling */ - s32 frame_force_skip_flag; - s32 error_frame_skip_level; - s32 wait_buffer_counter; - u32 first_i_frame_ready; - u32 run_count; - u32 not_run_ready; - u32 input_empty; - u32 put_num; - u32 peek_num; - u32 get_num; - u32 drop_frame_count; - u32 buffer_not_ready; - u32 ratio_control; - int frameinfo_enable; - struct firmware_s *fw; - u32 canvas_mode; -#ifdef AGAIN_HAS_THRESHOLD - u32 pre_parser_wr_ptr; - u8 next_again_flag; -#endif - struct work_struct userdata_push_work; - struct mutex userdata_mutex; - struct mmpeg2_userdata_info_t userdata_info; - struct mmpeg2_userdata_record_t ud_record[MAX_UD_RECORDS]; - int cur_ud_idx; - u8 *user_data_buffer; - int wait_for_udr_send; - u32 ucode_cc_last_wp; - u32 notify_ucode_cc_last_wp; - u32 notify_data_cc_last_wp; - -#ifdef DUMP_USER_DATA -#define MAX_USER_DATA_SIZE 1572864 - void *user_data_dump_buf; - unsigned char *pdump_buf_cur_start; - int total_len; - int bskip; - int n_userdata_id; - u32 reference[MAX_UD_RECORDS]; -#endif -}; -static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw); -static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw); -static void reset_process_time(struct vdec_mpeg12_hw_s *hw); -static struct vdec_info gvs; -static int debug_enable; -/*static struct work_struct userdata_push_work;*/ -#undef pr_info -#define pr_info printk -unsigned int mpeg12_debug_mask = 0xff; -/*static int counter_max = 5;*/ - -#define PRINT_FLAG_ERROR 0x0 -#define PRINT_FLAG_RUN_FLOW 0X0001 -#define PRINT_FLAG_TIMEINFO 0x0002 -#define PRINT_FLAG_UCODE_DETAIL 0x0004 -#define PRINT_FLAG_VLD_DETAIL 0x0008 -#define PRINT_FLAG_DEC_DETAIL 0x0010 -#define PRINT_FLAG_BUFFER_DETAIL 0x0020 -#define PRINT_FLAG_RESTORE 0x0040 -#define PRINT_FRAME_NUM 0x0080 -#define PRINT_FLAG_FORCE_DONE 0x0100 -#define PRINT_FLAG_COUNTER 0X0200 -#define PRINT_FRAMEBASE_DATA 0x0400 -#define PRINT_FLAG_VDEC_STATUS 0x0800 -#define PRINT_FLAG_PARA_DATA 0x1000 -#define PRINT_FLAG_USERDATA_DETAIL 0x2000 - - - -int debug_print(int index, int debug_flag, const char *fmt, ...) -{ - if (((debug_enable & debug_flag) && - ((1 << index) & mpeg12_debug_mask)) - || (debug_flag == PRINT_FLAG_ERROR)) { - unsigned char buf[512]; - int len = 0; - va_list args; - va_start(args, fmt); - len = sprintf(buf, "%d: ", index); - vsnprintf(buf + len, 512-len, fmt, args); - pr_info("%s", buf); - va_end(args); - } - return 0; -} - - -/*static bool is_reset;*/ -#define PROVIDER_NAME "vdec.mpeg12" -static const struct vframe_operations_s vf_provider_ops = { - .peek = vmpeg_vf_peek, - .get = vmpeg_vf_get, - .put = vmpeg_vf_put, - .event_cb = vmpeg_event_cb, - .vf_states = vmpeg_vf_states, -}; - - -static const u32 frame_rate_tab[16] = { - 96000 / 30, 96000000 / 23976, 96000 / 24, 96000 / 25, - 9600000 / 2997, 96000 / 30, 96000 / 50, 9600000 / 5994, - 96000 / 60, - /* > 8 reserved, use 24 */ - 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, - 96000 / 24, 96000 / 24, 96000 / 24 -}; - - -static u32 find_buffer(struct vdec_mpeg12_hw_s *hw) -{ - u32 i; - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - if (hw->vfbuf_use[i] == 0) - return i; - } - - return DECODE_BUFFER_NUM_MAX; -} - -static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec) -{ - u32 i; - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - if (hw->canvas_spec[i] == spec) - return i; - } - - return DECODE_BUFFER_NUM_MAX; -} - -static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf) -{ - unsigned ar_bits; - u32 temp; - u32 buffer_index = vf->index; -#ifdef CONFIG_AM_VDEC_MPEG12_LOG - bool first = (hw->frame_width == 0) && (hw->frame_height == 0); -#endif - - temp = READ_VREG(MREG_PIC_WIDTH); - if (temp > 1920 || temp == 0) - vf->width = hw->frame_width = 1920; - else - vf->width = hw->frame_width = temp; - - temp = READ_VREG(MREG_PIC_HEIGHT); - if (temp > 1088 || temp == 0) - vf->height = hw->frame_height = 1088; - else - vf->height = hw->frame_height = temp; - - if (hw->frame_dur > 0) - vf->duration = hw->frame_dur; - else { - vf->duration = hw->frame_dur = - frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]; - schedule_work(&hw->notify_work); - } - - ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf; - - if (ar_bits == 0x2) - vf->ratio_control = 0xc0 << DISP_RATIO_ASPECT_RATIO_BIT; - - else if (ar_bits == 0x3) - vf->ratio_control = 0x90 << DISP_RATIO_ASPECT_RATIO_BIT; - - else if (ar_bits == 0x4) - vf->ratio_control = 0x74 << DISP_RATIO_ASPECT_RATIO_BIT; - else - vf->ratio_control = 0; - - hw->ratio_control = vf->ratio_control; - - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - - vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; - vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; - - vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; - vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; - - - debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, - "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", - hw->frame_width, hw->frame_height, hw->frame_dur, - frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]); -} - -static bool error_skip(struct vdec_mpeg12_hw_s *hw, - u32 info, struct vframe_s *vf) -{ - if (hw->error_frame_skip_level) { - /* skip error frame */ - if ((info & PICINFO_ERROR) || (hw->frame_force_skip_flag)) { - if ((info & PICINFO_ERROR) == 0) { - if ((info & PICINFO_TYPE_MASK) == - PICINFO_TYPE_I) - hw->frame_force_skip_flag = 0; - } else { - if (hw->error_frame_skip_level >= 2) - hw->frame_force_skip_flag = 1; - } - if ((info & PICINFO_ERROR) - || (hw->frame_force_skip_flag)) - return true; - } - } - return false; -} - -static inline void vmpeg12_save_hw_context(struct vdec_mpeg12_hw_s *hw) -{ - hw->seqinfo = READ_VREG(MREG_SEQ_INFO); - hw->reg_pic_width = READ_VREG(MREG_PIC_WIDTH); - hw->reg_pic_height = READ_VREG(MREG_PIC_HEIGHT); - hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG); - hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO); - hw->reg_f_code_reg = READ_VREG(F_CODE_REG); - hw->reg_slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE); - hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); - hw->reg_mb_info = READ_VREG(MB_INFO); - hw->reg_signal_type = READ_VREG(AV_SCRATCH_H); - debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, - "signal_type = %x", hw->reg_signal_type); -} - -static void vmmpeg2_reset_udr_mgr(struct vdec_mpeg12_hw_s *hw) -{ - hw->wait_for_udr_send = 0; - hw->cur_ud_idx = 0; - memset(&hw->ud_record, 0, sizeof(hw->ud_record)); -} - -static void vmmpeg2_crate_userdata_manager( - struct vdec_mpeg12_hw_s *hw, - u8 *userdata_buf, - int buf_len) -{ - if (hw) { - mutex_init(&hw->userdata_mutex); - - memset(&hw->userdata_info, 0, - sizeof(struct mmpeg2_userdata_info_t)); - hw->userdata_info.data_buf = userdata_buf; - hw->userdata_info.buf_len = buf_len; - hw->userdata_info.data_buf_end = userdata_buf + buf_len; - - vmmpeg2_reset_udr_mgr(hw); - } -} - -static void vmmpeg2_destroy_userdata_manager(struct vdec_mpeg12_hw_s *hw) -{ - if (hw) - memset(&hw->userdata_info, - 0, - sizeof(struct mmpeg2_userdata_info_t)); -} - -static void aml_swap_data(uint8_t *user_data, int ud_size) -{ - int swap_blocks, i, j, k, m; - unsigned char c_temp; - - /* swap byte order */ - swap_blocks = ud_size / 8; - for (i = 0; i < swap_blocks; i++) { - j = i * 8; - k = j + 7; - for (m = 0; m < 4; m++) { - c_temp = user_data[j]; - user_data[j++] = user_data[k]; - user_data[k--] = c_temp; - } - } -} - -#ifdef DUMP_USER_DATA -static void push_to_buf(struct vdec_mpeg12_hw_s *hw, - u8 *pdata, - int len, - struct userdata_meta_info_t *pmeta, - u32 reference) -{ - u32 *pLen; - int info_cnt; - u8 *pbuf_end; - - if (!hw->user_data_dump_buf) - return; - - if (hw->bskip) { - pr_info("over size, skip\n"); - return; - } - info_cnt = 0; - pLen = (u32 *)hw->pdump_buf_cur_start; - - *pLen = len; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->duration; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->flags; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = pmeta->vpts_valid; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - - *pLen = hw->n_userdata_id; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - *pLen = reference; - hw->pdump_buf_cur_start += sizeof(u32); - info_cnt++; - pLen++; - - pbuf_end = hw->userdata_info.data_buf_end; - if (pdata + len > pbuf_end) { - int first_section_len; - - first_section_len = pbuf_end - pdata; - memcpy(hw->pdump_buf_cur_start, pdata, first_section_len); - pdata = (u8 *)hw->userdata_info.data_buf; - hw->pdump_buf_cur_start += first_section_len; - memcpy(hw->pdump_buf_cur_start, pdata, len - first_section_len); - hw->pdump_buf_cur_start += len - first_section_len; - } else { - memcpy(hw->pdump_buf_cur_start, pdata, len); - hw->pdump_buf_cur_start += len; - } - - hw->total_len += len + info_cnt * sizeof(u32); - if (hw->total_len >= MAX_USER_DATA_SIZE-4096) - hw->bskip = 1; -} - -static void dump_userdata_info(struct vdec_mpeg12_hw_s *hw, - void *puser_data, - int len, - struct userdata_meta_info_t *pmeta, - u32 reference) -{ - u8 *pstart; - - pstart = (u8 *)puser_data; - -#ifdef DUMP_HEAD_INFO_DATA - push_to_buf(hw, pstart, len, pmeta, reference); -#else - push_to_buf(hw, pstart+8, len - 8, pmeta, reference); -#endif -} - - -static void print_data(unsigned char *pdata, - int len, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id, - u32 reference) -{ - int nLeft; - - nLeft = len; - - pr_info("%d len:%d, flag:0x%x, dur:%d, vpts:0x%x, valid:%d, refer:%d\n", - rec_id, len, flag, - duration, vpts, vpts_valid, - reference); - while (nLeft >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7], - pdata[8], pdata[9], pdata[10], pdata[11], - pdata[12], pdata[13], pdata[14], pdata[15]); - nLeft -= 16; - pdata += 16; - } - - - while (nLeft > 0) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); - nLeft -= 8; - pdata += 8; - } -} - -static void dump_data(u8 *pdata, - unsigned int user_data_length, - unsigned int flag, - unsigned int duration, - unsigned int vpts, - unsigned int vpts_valid, - int rec_id, - u32 reference) -{ - unsigned char szBuf[256]; - - - memset(szBuf, 0, 256); - memcpy(szBuf, pdata, user_data_length); - - aml_swap_data(szBuf, user_data_length); - - print_data(szBuf, - user_data_length, - flag, - duration, - vpts, - vpts_valid, - rec_id, - reference); -} - - -static void show_user_data_buf(struct vdec_mpeg12_hw_s *hw) -{ - u8 *pbuf; - int len; - unsigned int flag; - unsigned int duration; - unsigned int vpts; - unsigned int vpts_valid; - int rec_id; - u32 reference; - - pr_info("show user data buf\n"); - pbuf = hw->user_data_dump_buf; - - while (pbuf < hw->pdump_buf_cur_start) { - u32 *pLen; - - pLen = (u32 *)pbuf; - - len = *pLen; - pLen++; - pbuf += sizeof(u32); - - duration = *pLen; - pLen++; - pbuf += sizeof(u32); - - flag = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts = *pLen; - pLen++; - pbuf += sizeof(u32); - - vpts_valid = *pLen; - pLen++; - pbuf += sizeof(u32); - - rec_id = *pLen; - pLen++; - pbuf += sizeof(u32); - - reference = *pLen; - pLen++; - pbuf += sizeof(u32); - - - dump_data(pbuf, len, flag, duration, - vpts, vpts_valid, rec_id, reference); - pbuf += len; - msleep(30); - } -} - -static int amvdec_mmpeg12_init_userdata_dump(struct vdec_mpeg12_hw_s *hw) -{ - hw->user_data_dump_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); - if (hw->user_data_dump_buf) - return 1; - else - return 0; -} - -static void amvdec_mmpeg12_uninit_userdata_dump(struct vdec_mpeg12_hw_s *hw) -{ - if (hw->user_data_dump_buf) { - show_user_data_buf(hw); - kfree(hw->user_data_dump_buf); - hw->user_data_dump_buf = NULL; - } -} - -static void reset_user_data_buf(struct vdec_mpeg12_hw_s *hw) -{ - hw->total_len = 0; - hw->pdump_buf_cur_start = hw->user_data_dump_buf; - hw->bskip = 0; - hw->n_userdata_id = 0; -} -#endif - -static void user_data_ready_notify(struct vdec_mpeg12_hw_s *hw, - u32 pts, u32 pts_valid) -{ - struct mmpeg2_userdata_record_t *p_userdata_rec; - int i; - - if (hw->wait_for_udr_send) { - for (i = 0; i < hw->cur_ud_idx; i++) { - mutex_lock(&hw->userdata_mutex); - - - p_userdata_rec = hw->userdata_info.records - + hw->userdata_info.write_index; - - hw->ud_record[i].meta_info.vpts_valid = pts_valid; - hw->ud_record[i].meta_info.vpts = pts; - - *p_userdata_rec = hw->ud_record[i]; -#ifdef DUMP_USER_DATA - dump_userdata_info(hw, - hw->userdata_info.data_buf + p_userdata_rec->rec_start, - p_userdata_rec->rec_len, - &p_userdata_rec->meta_info, - hw->reference[i]); - hw->n_userdata_id++; -#endif -/* - pr_info("notify: rec_start:%d, rec_len:%d, wi:%d, reference:%d\n", - p_userdata_rec->rec_start, - p_userdata_rec->rec_len, - hw->userdata_info.write_index, - hw->reference[i]); -*/ - hw->userdata_info.write_index++; - if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) - hw->userdata_info.write_index = 0; - - mutex_unlock(&hw->userdata_mutex); - - - vdec_wakeup_userdata_poll(hw_to_vdec(hw)); - } - hw->wait_for_udr_send = 0; - hw->cur_ud_idx = 0; - } - hw->notify_ucode_cc_last_wp = hw->ucode_cc_last_wp; - hw->notify_data_cc_last_wp = hw->userdata_info.last_wp; -} - -static int vmmpeg2_user_data_read(struct vdec_s *vdec, - struct userdata_param_t *puserdata_para) -{ - struct vdec_mpeg12_hw_s *hw = NULL; - int rec_ri, rec_wi; - int rec_len; - u8 *rec_data_start; - u8 *pdest_buf; - struct mmpeg2_userdata_record_t *p_userdata_rec; - u32 data_size; - u32 res; - int copy_ok = 1; - - hw = (struct vdec_mpeg12_hw_s *)vdec->private; - - pdest_buf = puserdata_para->pbuf_addr; - - mutex_lock(&hw->userdata_mutex); - -/* - pr_info("ri = %d, wi = %d\n", - hw->userdata_info.read_index, - hw->userdata_info.write_index); -*/ - rec_ri = hw->userdata_info.read_index; - rec_wi = hw->userdata_info.write_index; - - if (rec_ri == rec_wi) { - mutex_unlock(&hw->userdata_mutex); - return 0; - } - - p_userdata_rec = hw->userdata_info.records + rec_ri; - - rec_len = p_userdata_rec->rec_len; - rec_data_start = p_userdata_rec->rec_start + hw->userdata_info.data_buf; -/* - pr_info("ri:%d, wi:%d, rec_len:%d, rec_start:%d, buf_len:%d\n", - rec_ri, rec_wi, - p_userdata_rec->rec_len, - p_userdata_rec->rec_start, - puserdata_para->buf_len); -*/ - if (rec_len <= puserdata_para->buf_len) { - /* dvb user data buffer is enought to - copy the whole recored. */ - data_size = rec_len; - if (rec_data_start + data_size - > hw->userdata_info.data_buf_end) { - int first_section_len; - - first_section_len = hw->userdata_info.buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p1 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)hw->userdata_info.data_buf, - data_size - first_section_len); - if (res) { - pr_info("p2 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= - data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = - data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p3 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - hw->userdata_info.read_index++; - if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) - hw->userdata_info.read_index = 0; - } - } else { - /* dvb user data buffer is not enought - to copy the whole recored. */ - data_size = puserdata_para->buf_len; - if (rec_data_start + data_size - > hw->userdata_info.data_buf_end) { - int first_section_len; - - first_section_len = hw->userdata_info.buf_len - - p_userdata_rec->rec_start; - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - first_section_len); - if (res) { - pr_info("p4 read not end res=%d, request=%d\n", - res, first_section_len); - copy_ok = 0; - p_userdata_rec->rec_len -= - first_section_len - res; - p_userdata_rec->rec_start += - first_section_len - res; - puserdata_para->data_size = - first_section_len - res; - } else { - /* first secton copy is ok*/ - res = (u32)copy_to_user( - (void *)(pdest_buf+first_section_len), - (void *)hw->userdata_info.data_buf, - data_size - first_section_len); - if (res) { - pr_info("p5 read not end res=%d, request=%d\n", - res, - data_size - first_section_len); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= - data_size - res; - p_userdata_rec->rec_start = - data_size - first_section_len - res; - puserdata_para->data_size = - data_size - res; - } - } else { - res = (u32)copy_to_user((void *)pdest_buf, - (void *)rec_data_start, - data_size); - if (res) { - pr_info("p6 read not end res=%d, request=%d\n", - res, data_size); - copy_ok = 0; - } - - p_userdata_rec->rec_len -= data_size - res; - p_userdata_rec->rec_start += data_size - res; - puserdata_para->data_size = data_size - res; - } - - if (copy_ok) { - hw->userdata_info.read_index++; - if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) - hw->userdata_info.read_index = 0; - } - - } - puserdata_para->meta_info = p_userdata_rec->meta_info; - - if (hw->userdata_info.read_index <= hw->userdata_info.write_index) - puserdata_para->meta_info.records_in_que = - hw->userdata_info.write_index - - hw->userdata_info.read_index; - else - puserdata_para->meta_info.records_in_que = - hw->userdata_info.write_index + - USERDATA_FIFO_NUM - - hw->userdata_info.read_index; - - puserdata_para->version = (0<<24|0<<16|0<<8|1); - - mutex_unlock(&hw->userdata_mutex); - - - return 1; -} - -static void vmmpeg2_reset_userdata_fifo(struct vdec_s *vdec, int bInit) -{ - struct vdec_mpeg12_hw_s *hw = NULL; - - hw = (struct vdec_mpeg12_hw_s *)vdec->private; - - if (hw) { - mutex_lock(&hw->userdata_mutex); - pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", - bInit, - hw->userdata_info.read_index, - hw->userdata_info.write_index); - hw->userdata_info.read_index = 0; - hw->userdata_info.write_index = 0; - - if (bInit) - hw->userdata_info.last_wp = 0; - mutex_unlock(&hw->userdata_mutex); - } -} - -static void vmmpeg2_wakeup_userdata_poll(struct vdec_s *vdec) -{ - amstream_wakeup_userdata_poll(vdec); -} - -/* -#define PRINT_HEAD_INFO -*/ -static void userdata_push_do_work(struct work_struct *work) -{ - u32 reg; - u8 *pdata; - u8 *psrc_data; - u8 head_info[8]; - struct userdata_meta_info_t meta_info; - u32 wp; - u32 index; - u32 picture_struct; - u32 reference; - u32 picture_type; - u32 temp; - u32 data_length; - u32 data_start; - int i; - u32 offset; - u32 cur_wp; -#ifdef PRINT_HEAD_INFO - u8 *ptype_str; -#endif - struct mmpeg2_userdata_record_t *pcur_ud_rec; - - struct vdec_mpeg12_hw_s *hw = container_of(work, - struct vdec_mpeg12_hw_s, userdata_push_work); - - memset(&meta_info, 0, sizeof(meta_info)); - - meta_info.duration = hw->frame_dur; - - - reg = READ_VREG(AV_SCRATCH_J); - meta_info.flags = ((reg >> 30) << 1); - meta_info.flags |= (VFORMAT_MPEG12 << 3); - /* check top_field_first flag */ - if ((reg >> 28) & 0x1) { - meta_info.flags |= (1 << 10); - meta_info.flags |= (((reg >> 29) & 0x1) << 11); - } - - cur_wp = reg & 0x7fff; - if (cur_wp == hw->ucode_cc_last_wp) { - debug_print(DECODE_ID(hw), 0, - "Null user data package: wp = %d\n", cur_wp); - WRITE_VREG(AV_SCRATCH_J, 0); - return; - } - - if (hw->cur_ud_idx >= MAX_UD_RECORDS) { - debug_print(DECODE_ID(hw), 0, - "UD Records over: %d, skip it\n", MAX_UD_RECORDS); - WRITE_VREG(AV_SCRATCH_J, 0); - return; - } - - if (cur_wp < hw->ucode_cc_last_wp) - hw->ucode_cc_last_wp = 0; - - offset = READ_VREG(AV_SCRATCH_I); - - codec_mm_dma_flush( - hw->ccbuf_phyAddress_virt, - CCBUF_SIZE, - DMA_FROM_DEVICE); - - mutex_lock(&hw->userdata_mutex); - if (hw->ccbuf_phyAddress_virt) { - pdata = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; - memcpy(head_info, pdata, 8); - } else - memset(head_info, 0, 8); - mutex_unlock(&hw->userdata_mutex); - aml_swap_data(head_info, 8); - - wp = (head_info[0] << 8 | head_info[1]); - index = (head_info[2] << 8 | head_info[3]); - - picture_struct = (head_info[6] << 8 | head_info[7]); - temp = (head_info[4] << 8 | head_info[5]); - reference = temp & 0x3FF; - picture_type = (temp >> 10) & 0x7; - - if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) - pr_info("index:%d, wp:%d, ref:%d, type:%d, struct:0x%x, u_last_wp:0x%x\n", - index, wp, reference, - picture_type, picture_struct, - hw->ucode_cc_last_wp); - - switch (picture_type) { - case 1: - /* pr_info("I type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (1<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " I"; -#endif - break; - case 2: - /* pr_info("P type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (2<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " P"; -#endif - break; - case 3: - /* pr_info("B type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (3<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " B"; -#endif - break; - case 4: - /* pr_info("D type, pos:%d\n", - (meta_info.flags>>1)&0x3); */ - meta_info.flags |= (4<<7); -#ifdef PRINT_HEAD_INFO - ptype_str = " D"; -#endif - break; - default: - /* pr_info("Unknown type:0x%x, pos:%d\n", - pheader->picture_coding_type, - (meta_info.flags>>1)&0x3); */ -#ifdef PRINT_HEAD_INFO - ptype_str = " U"; -#endif - break; - } -#ifdef PRINT_HEAD_INFO - pr_info("ref:%d, type:%s, ext:%d, first:%d, data_length:%d\n", - reference, ptype_str, - (reg >> 30), - (reg >> 28)&0x3, - reg & 0xffff); -#endif - data_length = cur_wp - hw->ucode_cc_last_wp; - data_start = reg & 0xffff; - psrc_data = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; - - pdata = hw->userdata_info.data_buf + hw->userdata_info.last_wp; - for (i = 0; i < data_length; i++) { - *pdata++ = *psrc_data++; - if (pdata >= hw->userdata_info.data_buf_end) - pdata = hw->userdata_info.data_buf; - } - pcur_ud_rec = hw->ud_record + hw->cur_ud_idx; - - pcur_ud_rec->meta_info = meta_info; - pcur_ud_rec->rec_start = hw->userdata_info.last_wp; - pcur_ud_rec->rec_len = data_length; - - hw->userdata_info.last_wp += data_length; - if (hw->userdata_info.last_wp >= USER_DATA_SIZE) - hw->userdata_info.last_wp -= USER_DATA_SIZE; - - hw->wait_for_udr_send = 1; - - hw->ucode_cc_last_wp = cur_wp; - - if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) - pr_info("cur_wp:%d, rec_start:%d, rec_len:%d\n", - cur_wp, - pcur_ud_rec->rec_start, - pcur_ud_rec->rec_len); - -#ifdef DUMP_USER_DATA - hw->reference[hw->cur_ud_idx] = reference; -#endif - - hw->cur_ud_idx++; - WRITE_VREG(AV_SCRATCH_J, 0); - -} - - -void userdata_pushed_drop(struct vdec_mpeg12_hw_s *hw) -{ - hw->userdata_info.last_wp = hw->notify_data_cc_last_wp; - hw->ucode_cc_last_wp = hw->notify_ucode_cc_last_wp; - hw->cur_ud_idx = 0; - hw->wait_for_udr_send = 0; - -} - - -static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) -{ - u32 reg, info, seqinfo, offset, pts, pts_valid = 0; - struct vframe_s *vf = NULL; - u32 index; - u64 pts_us64 = 0; - u32 frame_size; - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)(vdec->private); - - if (READ_VREG(AV_SCRATCH_M) != 0 && - (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { - - debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "dbg %x: %x, level %x, wp %x, rp %x, cnt %x\n", - READ_VREG(AV_SCRATCH_M), READ_VREG(AV_SCRATCH_N), - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VIFF_BIT_CNT)); - WRITE_VREG(AV_SCRATCH_M, 0); - return IRQ_HANDLED; - } - - reg = READ_VREG(AV_SCRATCH_J); - if (reg & (1<<16)) { - vdec_schedule_work(&hw->userdata_push_work); - return IRQ_HANDLED; - } - - reg = READ_VREG(MREG_BUFFEROUT); - - if (reg == 2) { - /*timeout when decoding next frame*/ - - debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "ammvdec_mpeg12: Insufficient data\n"); - debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "level=%x, vtl=%x,bcnt=%d\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_CONTROL), - READ_VREG(VIFF_BIT_CNT)); - if (input_frame_based(vdec)) - vmpeg12_save_hw_context(hw); - else { - hw->dec_result = DEC_RESULT_AGAIN; - vdec_schedule_work(&hw->work); - userdata_pushed_drop(hw); - } - return IRQ_HANDLED; - } else { - reset_process_time(hw); - info = READ_VREG(MREG_PIC_INFO); - offset = READ_VREG(MREG_FRAME_OFFSET); - index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); - seqinfo = READ_VREG(MREG_SEQ_INFO); - if ((info & PICINFO_PROG) == 0 && - (info & FRAME_PICTURE_MASK) != FRAME_PICTURE) - hw->first_i_frame_ready = 1; /* for field struct case*/ - debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "struct: %d %x\n", (info & PICINFO_FRAME), info); - if (index >= DECODE_BUFFER_NUM_MAX) { - - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "invalid buffer index,index=%d\n", - index); - hw->dec_result = DEC_RESULT_ERROR; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } - - hw->dec_result = DEC_RESULT_DONE; - - /*debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "ammvdec_mpeg12: error = 0x%x, offset = 0x%x\n", - info & PICINFO_ERROR, offset);*/ - - if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I)) { - if (hw->chunk) { - hw->pts_valid[index] = hw->chunk->pts_valid; - hw->pts[index] = hw->chunk->pts; - hw->pts64[index] = hw->chunk->pts64; - debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "!!!cpts=%d,pts64=%lld,size=%d,offset=%d\n", - hw->pts[index], hw->pts64[index], - hw->chunk->size, hw->chunk->offset); - } else { - if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, - offset, &pts, &frame_size, - 0, &pts_us64) == 0) { - hw->pts_valid[index] = true; - hw->pts[index] = pts; - hw->pts64[index] = pts_us64; - } else { - hw->pts_valid[index] = false; - } - } - } else { - hw->pts_valid[index] = false; - } - /*if (frame_prog == 0) */ - { - hw->frame_prog = info & PICINFO_PROG; - if ((seqinfo & SEQINFO_EXT_AVAILABLE) - && (!(seqinfo & SEQINFO_PROG))) - hw->frame_prog = 0; - } - if ((hw->dec_control & - DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) && - (hw->frame_width == 720) && - (hw->frame_height == 576) && - (hw->frame_dur == 3840)) { - hw->frame_prog = 0; - } else if ((hw->dec_control - & DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) && - (hw->frame_width == 704) && - (hw->frame_height == 480) && - (hw->frame_dur == 3200)) { - hw->frame_prog = 0; - } else if ((hw->dec_control - & DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) && - (hw->frame_width == 704) && - (hw->frame_height == 576) && - (hw->frame_dur == 3840)) { - hw->frame_prog = 0; - } else if ((hw->dec_control - & DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) && - (hw->frame_width == 544) && - (hw->frame_height == 576) && - (hw->frame_dur == 3840)) { - hw->frame_prog = 0; - } else if ((hw->dec_control - & DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) && - (hw->frame_width == 480) && - (hw->frame_height == 576) && - (hw->frame_dur == 3840)) { - hw->frame_prog = 0; - } else if (hw->dec_control - & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) { - hw->frame_prog = 0; - } - - hw->buffer_info[index] = info; - - debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "ammvdec_mpeg12: decoded buffer %d, frame_type %c\n", - index, GET_SLICE_TYPE(info)); - - /* Buffer management - todo: add sequence-end flush */ - if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) || - ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) { - hw->vfbuf_use[index]++; - if (hw->refs[1] == -1) { - hw->refs[1] = index; - index = DECODE_BUFFER_NUM_MAX; - } else if (hw->refs[0] == -1) { - hw->refs[0] = hw->refs[1]; - hw->refs[1] = index; - index = hw->refs[0]; - } else { - hw->vfbuf_use[hw->refs[0]]--; - hw->refs[0] = hw->refs[1]; - hw->refs[1] = index; - index = hw->refs[0]; - } - } else { - /* if this is a B frame, then drop - (depending on if there are two reference frames) - or display immediately*/ - if (hw->refs[0] == -1) - index = DECODE_BUFFER_NUM_MAX; - - } - - vmpeg12_save_hw_context(hw); - - if (index >= DECODE_BUFFER_NUM_MAX) { - debug_print(DECODE_ID(hw), 0, - "invalid buffer index,index=%d\n", index); - hw->dec_result = DEC_RESULT_ERROR; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } - - info = hw->buffer_info[index]; - pts_valid = hw->pts_valid[index]; - pts = hw->pts[index]; - pts_us64 = hw->pts64[index]; - - user_data_ready_notify(hw, pts, pts_valid); - - if ((hw->first_i_frame_ready == 0) && - ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && - ((info & PICINFO_ERROR) == 0)) - hw->first_i_frame_ready = 1; - debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "ammvdec_mpeg12: display buffer %d, frame_type %c\n", - index, GET_SLICE_TYPE(info)); - if (hw->frame_prog & PICINFO_PROG) { - - seqinfo = READ_VREG(MREG_SEQ_INFO); - - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "fatal error, no available buffer slot."); - hw->dec_result = DEC_RESULT_ERROR; - vdec_schedule_work(&hw->work); - - return IRQ_HANDLED; - } - - vf->index = index; - set_frame_info(hw, vf); - vf->signal_type = hw->reg_signal_type; - -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - if ((hw->seqinfo & SEQINFO_EXT_AVAILABLE) - && (hw->seqinfo & SEQINFO_PROG)) { - if (info & PICINFO_RPT_FIRST) { - if (info & PICINFO_TOP_FIRST) { - vf->duration = - vf->duration * 3; - /* repeat three times */ - } else { - vf->duration = - vf->duration * 2; - /* repeat two times */ - } - } - vf->duration_pulldown = 0; - /* no pull down */ - - } else { - vf->duration_pulldown = - (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - } - - vf->duration += vf->duration_pulldown; - - vf->orientation = 0; - vf->pts = (pts_valid) ? pts : 0; - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - vf->type_original = vf->type; - hw->vfbuf_use[index]++; - - if ((error_skip(hw, info, vf)) || - ((hw->first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) != - PICINFO_TYPE_I))) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - - } else { - debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "cpts=%d,pts64=%lld\n", - vf->pts, vf->pts_us64); - decoder_do_frame_check(hw_to_vdec(hw), vf); - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - hw->frame_num++; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - } -/*interlace temp*/ - else { - int first_field_type = (info & PICINFO_TOP_FIRST) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; - -#ifdef INTERLACE_SEQ_ALWAYS - /* once an interlaced sequence exist, - always force interlaced type */ - /* to make DI easy. */ - hw->dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE; -#endif - - hw->frame_rpt_state = FRAME_REPEAT_NONE; - - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "fatal error, no available buffer slot."); - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; - } - - hw->vfbuf_use[index] += 2; - vf->signal_type = hw->reg_signal_type; - vf->index = index; - set_frame_info(hw, vf); - vf->type = - (first_field_type == VIDTYPE_INTERLACE_TOP) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - if (info & PICINFO_RPT_FIRST) - vf->duration /= 3; - else - vf->duration >>= 1; - vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - vf->duration += vf->duration_pulldown; - vf->orientation = 0; - vf->pts = (pts_valid) ? pts : 0; - vf->pts_us64 = (pts_valid) ? pts_us64 : 0; - - if ((error_skip(hw, info, vf)) || - ((hw->first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) != - PICINFO_TYPE_I))) { - hw->vfbuf_use[index]--; - hw->drop_frame_count++; - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "cpts0=%d,pts64=%lld,dur=%d, index %d , use %d\n", - vf->pts, vf->pts_us64, vf->duration, - vf->index, hw->vfbuf_use[index]); - decoder_do_frame_check(hw_to_vdec(hw), vf); - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - hw->frame_num++; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "ammvdec_mpeg12: fatal error, no available buffer slot."); - - hw->vfbuf_use[index]--; - - vdec_schedule_work(&hw->work); - - return IRQ_HANDLED; - } - vf->signal_type = hw->reg_signal_type; - vf->index = index; - set_frame_info(hw, vf); - vf->type = (first_field_type == - VIDTYPE_INTERLACE_TOP) ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - if (info & PICINFO_RPT_FIRST) - vf->duration /= 3; - else - vf->duration >>= 1; - vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - vf->duration += vf->duration_pulldown; - vf->orientation = 0; - vf->pts = 0; - vf->pts_us64 = 0; - vf->type_original = vf->type; - - if ((error_skip(hw, info, vf)) || - ((hw->first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) != - PICINFO_TYPE_I))) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "cpts1=%d,pts64=%lld,dur=%d index %d, used %d\n", - vf->pts, vf->pts_us64, vf->duration, vf->index, - hw->vfbuf_use[index]); - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - hw->frame_num++; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - - if (info & PICINFO_RPT_FIRST) { - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - debug_print(DECODE_ID(hw), - PRINT_FLAG_ERROR, - "error, no available buffer slot."); - return IRQ_HANDLED; - } - hw->vfbuf_use[index]++; - vf->index = index; - set_frame_info(hw, vf); - vf->type = (first_field_type == - VIDTYPE_INTERLACE_TOP) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->duration /= 3; - vf->duration_pulldown = - (info & PICINFO_RPT_FIRST) ? - vf->duration >> 1 : 0; - vf->duration += vf->duration_pulldown; - vf->orientation = 0; - - vf->pts = 0; - vf->pts_us64 = 0; - if ((error_skip(hw, info, vf)) || - ((hw->first_i_frame_ready == 0) - && ((PICINFO_TYPE_MASK & info) - != PICINFO_TYPE_I))) { - hw->vfbuf_use[index]--; - hw->drop_frame_count++; - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - hw->frame_num++; - debug_print(DECODE_ID(hw), - PRINT_FLAG_TIMEINFO, - "cpts2=%d,pts64=%lld,dur=%d index %d, used %d\n", - vf->pts, vf->pts_us64, vf->duration, - vf->index, hw->vfbuf_use[index]); - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver( - vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - } - } - vdec_schedule_work(&hw->work); - - debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "frame_num=%d\n", hw->frame_num); - if (hw->frame_num == 1) - debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "frame_num==1\n"); - if (hw->frame_num == 1000) - debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "frame_num==1000\n"); - } - - return IRQ_HANDLED; -} -static irqreturn_t vmpeg12_isr(struct vdec_s *vdec, int irq) -{ - u32 info, offset; - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)(vdec->private); - if (hw->eos) - return IRQ_HANDLED; - info = READ_VREG(MREG_PIC_INFO); - offset = READ_VREG(MREG_FRAME_OFFSET); - - vdec_count_info(&gvs, info & PICINFO_ERROR, offset); - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - return IRQ_WAKE_THREAD; -} - -static void vmpeg12_notify_work(struct work_struct *work) -{ - struct vdec_mpeg12_hw_s *hw = container_of(work, - struct vdec_mpeg12_hw_s, notify_work); - struct vdec_s *vdec = hw_to_vdec(hw); - - if (vdec->fr_hint_state == VDEC_NEED_HINT) { - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)hw->frame_dur)); - vdec->fr_hint_state = VDEC_HINTED; - } -} - -static void wait_vmmpeg12_search_done(struct vdec_mpeg12_hw_s *hw) -{ - u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - int count = 0; - - do { - usleep_range(100, 500); - if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) - break; - if (count > 1000) { - debug_print(DECODE_ID(hw), 0, - "%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", - __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); - break; - } else - vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); - count++; - } while (1); -} - -static void vmpeg12_work(struct work_struct *work) -{ - struct vdec_mpeg12_hw_s *hw = - container_of(work, struct vdec_mpeg12_hw_s, work); - struct vdec_s *vdec = hw_to_vdec(hw); - if (hw->dec_result != DEC_RESULT_DONE) - debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "ammvdec_mpeg12: vmpeg_work,result=%d,status=%d\n", - hw->dec_result, hw_to_vdec(hw)->next_status); - - if (hw->dec_result == DEC_RESULT_DONE) { - if (!hw->ctx_valid) - hw->ctx_valid = 1; - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - } else if (hw->dec_result == DEC_RESULT_AGAIN - && (hw_to_vdec(hw)->next_status != - VDEC_STATUS_DISCONNECTED)) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(hw_to_vdec(hw))) { - hw->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hw->work); - return; - } -#ifdef AGAIN_HAS_THRESHOLD - hw->next_again_flag = 1; -#endif - } else if (hw->dec_result == DEC_RESULT_GET_DATA - && (hw_to_vdec(hw)->next_status != - VDEC_STATUS_DISCONNECTED)) { - if (!vdec_has_more_input(hw_to_vdec(hw))) { - hw->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hw->work); - return; - } - debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "%s DEC_RESULT_GET_DATA %x %x %x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP)); - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - vdec_clean_input(hw_to_vdec(hw)); - return; - } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s: force exit\n", __func__); - if (hw->stat & STAT_ISR_REG) { - amvdec_stop(); - /*disable mbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 0); - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - } else if (hw->dec_result == DEC_RESULT_EOS) { - pr_info("%s: end of stream\n", __func__); - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - hw->eos = 1; - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - vdec_clean_input(hw_to_vdec(hw)); - } - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - wait_vmmpeg12_search_done(hw); - if (vdec->parallel_dec == 1) - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); - else - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - - if (hw->vdec_cb) { - hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); - debug_print(DECODE_ID(hw), 0x80000, - "%s:\n", __func__); - } -} - -static struct vframe_s *vmpeg_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - hw->peek_num++; - if (kfifo_peek(&hw->display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vmpeg_vf_get(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - - hw->get_num++; - if (kfifo_get(&hw->display_q, &vf)) - return vf; - - return NULL; -} - -static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct vdec_s *vdec = op_arg; - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - - hw->vfbuf_use[vf->index]--; - hw->put_num++; - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); -} - -static int vmpeg_event_cb(int type, void *data, void *private_data) -{ - return 0; -} - -static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - struct vdec_s *vdec = op_arg; - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - - spin_lock_irqsave(&hw->lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&hw->newframe_q); - states->buf_avail_num = kfifo_len(&hw->display_q); - states->buf_recycle_num = 0; - - spin_unlock_irqrestore(&hw->lock, flags); - return 0; -} -static int vmmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - - if (!hw) - return -1; - - vstatus->frame_width = hw->frame_width; - vstatus->frame_height = hw->frame_height; - if (hw->frame_dur != 0) - vstatus->frame_rate = 96000 / hw->frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(AV_SCRATCH_C); - vstatus->status = hw->stat; - vstatus->bit_rate = gvs.bit_rate; - vstatus->frame_dur = hw->frame_dur; - vstatus->frame_data = gvs.frame_data; - vstatus->total_data = gvs.total_data; - vstatus->frame_count = gvs.frame_count; - vstatus->error_frame_count = gvs.error_frame_count; - vstatus->drop_frame_count = hw->drop_frame_count; - vstatus->total_data = gvs.total_data; - vstatus->samp_cnt = gvs.samp_cnt; - vstatus->offset = gvs.offset; - vstatus->ratio_control = hw->ratio_control; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - - - -/****************************************/ -static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 decbuf_size, decbuf_y_size, decbuf_uv_size; - unsigned long decbuf_start; - /*u32 disp_addr = 0xffffffff;*/ - struct vdec_s *vdec = hw_to_vdec(hw); - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - /* HD & SD */ - canvas_width = 1920; - canvas_height = 1088; - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - - unsigned canvas; - if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */ - decbuf_size = WORKSPACE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &decbuf_start); - if (ret < 0) { - pr_err("mmu alloc failed! size 0x%d idx %d\n", - decbuf_size, i); - return; - } - - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { - if (hw->ccbuf_phyAddress_is_remaped_nocache) - codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); - hw->ccbuf_phyAddress_virt = NULL; - hw->ccbuf_phyAddress = 0; - hw->ccbuf_phyAddress_is_remaped_nocache = 0; - - hw->buf_start = decbuf_start; - hw->ccbuf_phyAddress = hw->buf_start + CTX_CCBUF_OFFSET; - hw->ccbuf_phyAddress_virt - = codec_mm_phys_to_virt( - hw->ccbuf_phyAddress); - if (!hw->ccbuf_phyAddress_virt) { - hw->ccbuf_phyAddress_virt - = codec_mm_vmap( - hw->ccbuf_phyAddress, - CCBUF_SIZE); - hw->ccbuf_phyAddress_is_remaped_nocache = 1; - } - - WRITE_VREG(MREG_CO_MV_START, hw->buf_start); - } else { - if (vdec->parallel_dec == 1) { - unsigned tmp; - if (canvas_u(hw->canvas_spec[i]) == 0xff) { - tmp = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->canvas_spec[i] &= ~(0xffff << 8); - hw->canvas_spec[i] |= tmp << 8; - hw->canvas_spec[i] |= tmp << 16; - } - if (canvas_y(hw->canvas_spec[i]) == 0xff) { - tmp = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->canvas_spec[i] &= ~0xff; - hw->canvas_spec[i] |= tmp; - } - canvas = hw->canvas_spec[i]; - } else { - canvas = vdec->get_canvas(i, 2); - hw->canvas_spec[i] = canvas; - } - - hw->canvas_config[i][0].phy_addr = - decbuf_start; - hw->canvas_config[i][0].width = - canvas_width; - hw->canvas_config[i][0].height = - canvas_height; - hw->canvas_config[i][0].block_mode = - hw->canvas_mode; - hw->canvas_config[i][0].endian = - (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; - - canvas_config_config(canvas_y(canvas), - &hw->canvas_config[i][0]); - - hw->canvas_config[i][1].phy_addr = - decbuf_start + decbuf_y_size; - hw->canvas_config[i][1].width = - canvas_width; - hw->canvas_config[i][1].height = - canvas_height / 2; - hw->canvas_config[i][1].block_mode = - hw->canvas_mode; - hw->canvas_config[i][0].endian = - (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; - - canvas_config_config(canvas_u(canvas), - &hw->canvas_config[i][1]); - } - } - return; -} - -static void vmpeg2_dump_state(struct vdec_s *vdec) -{ - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)(vdec->private); - u32 i; - debug_print(DECODE_ID(hw), 0, - "====== %s\n", __func__); - debug_print(DECODE_ID(hw), 0, - "width/height (%d/%d),i_first %d\n", - hw->frame_width, - hw->frame_height, - hw->first_i_frame_ready - ); - debug_print(DECODE_ID(hw), 0, - "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d,input_empty %d\n", - input_frame_based(vdec), - hw->eos, - hw->stat, - hw->dec_result, - hw->frame_num, - hw->put_num, - hw->run_count, - hw->not_run_ready, - hw->input_empty - ); - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - debug_print(DECODE_ID(hw), 0, - "index %d, used %d\n", i, hw->vfbuf_use[i]); - } - - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - debug_print(DECODE_ID(hw), 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - debug_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d),drop=%d, buffer_not_ready %d\n", - __func__, - kfifo_len(&hw->newframe_q), - VF_POOL_SIZE, - kfifo_len(&hw->display_q), - VF_POOL_SIZE, - hw->peek_num, - hw->get_num, - hw->put_num, - hw->drop_frame_count, - hw->buffer_not_ready - ); - debug_print(DECODE_ID(hw), 0, - "VIFF_BIT_CNT=0x%x\n", - READ_VREG(VIFF_BIT_CNT)); - debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_LEVEL=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_WP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_WP)); - debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_RP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_RP)); - debug_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - debug_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - if (input_frame_based(vdec) && - debug_enable & PRINT_FRAMEBASE_DATA - ) { - int jj; - if (hw->chunk && hw->chunk->block && - hw->chunk->size > 0) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, hw->chunk->size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - debug_print(DECODE_ID(hw), 0, - "frame data size 0x%x\n", - hw->chunk->size); - for (jj = 0; jj < hw->chunk->size; jj++) { - if ((jj & 0xf) == 0) - debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } -} - -static void reset_process_time(struct vdec_mpeg12_hw_s *hw) -{ - if (hw->start_process_time) { - unsigned process_time = - 1000 * (jiffies - hw->start_process_time) / HZ; - hw->start_process_time = 0; - if (process_time > max_process_time[DECODE_ID(hw)]) - max_process_time[DECODE_ID(hw)] = process_time; - } -} -static void start_process_time(struct vdec_mpeg12_hw_s *hw) -{ - hw->decode_timeout_count = 10; - hw->start_process_time = jiffies; -} -static void timeout_process(struct vdec_mpeg12_hw_s *hw) -{ - struct vdec_s *vdec = hw_to_vdec(hw); - - reset_process_time(hw); - amvdec_stop(); - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s decoder timeout, status=%d, level=%d\n", - __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - hw->dec_result = DEC_RESULT_DONE; - hw->first_i_frame_ready = 0; - vdec_schedule_work(&hw->work); -} - -static void check_timer_func(unsigned long arg) -{ - struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)arg; - struct vdec_s *vdec = hw_to_vdec(hw); - unsigned int timeout_val = decode_timeout_val; - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - - if (debug_enable == 0 && - (input_frame_based(vdec) || - (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && - (timeout_val > 0) && - (hw->start_process_time > 0) && - ((1000 * (jiffies - hw->start_process_time) / HZ) - > timeout_val)) { - if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); - } - hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); - } - - if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - pr_info("vdec requested to be disconnected\n"); - return; - } - - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -} - -static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw) -{ - u32 index; - index = find_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) - return -1; - vmpeg12_canvas_init(hw); - - /* prepare REF0 & REF1 - points to the past two IP buffers - prepare REC_CANVAS_ADDR and ANC2_CANVAS_ADDR - points to the output buffer*/ - WRITE_VREG(MREG_REF0, - (hw->refs[1] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[0]]); - WRITE_VREG(MREG_REF1, - (hw->refs[0] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[1]]); - WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); - WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); - - debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, - "%s,ref0=0x%x, ref1=0x%x,rec=0x%x, ctx_valid=%d,index=%d\n", - __func__, - READ_VREG(MREG_REF0), - READ_VREG(MREG_REF1), - READ_VREG(REC_CANVAS_ADDR), - hw->ctx_valid, index); - - /* set to mpeg1 default */ - WRITE_VREG(MPEG1_2_REG, - (hw->ctx_valid) ? hw->reg_mpeg1_2_reg : 0); - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - /* for Mpeg1 default value */ - WRITE_VREG(PIC_HEAD_INFO, - (hw->ctx_valid) ? hw->reg_pic_head_info : 0x380); - /* disable mpeg4 */ - WRITE_VREG(M4_CONTROL_REG, 0); - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - /* clear buffer IN/OUT registers */ - WRITE_VREG(MREG_BUFFEROUT, 0); - /* set reference width and height */ - if ((hw->frame_width != 0) && (hw->frame_height != 0)) - WRITE_VREG(MREG_CMD, - (hw->frame_width << 16) | hw->frame_height); - else - WRITE_VREG(MREG_CMD, 0); - - - debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, - "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", - hw->frame_width, hw->frame_height, hw->seqinfo, - hw->reg_f_code_reg, hw->reg_slice_ver_pos_pic_type, - hw->reg_mb_info); - - WRITE_VREG(MREG_PIC_WIDTH, hw->reg_pic_width); - WRITE_VREG(MREG_PIC_HEIGHT, hw->reg_pic_height); - WRITE_VREG(MREG_SEQ_INFO, hw->seqinfo); - WRITE_VREG(F_CODE_REG, hw->reg_f_code_reg); - WRITE_VREG(SLICE_VER_POS_PIC_TYPE, - hw->reg_slice_ver_pos_pic_type); - WRITE_VREG(MB_INFO, hw->reg_mb_info); - WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg); - WRITE_VREG(AV_SCRATCH_H, hw->reg_signal_type); - - /* clear error count */ - WRITE_VREG(MREG_ERROR_COUNT, 0); - WRITE_VREG(MREG_FATAL_ERROR, 0); - /* clear wait buffer status */ - WRITE_VREG(MREG_WAIT_BUFFER, 0); -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); -#endif - if (hw->chunk) { - /*frame based input*/ - WRITE_VREG(MREG_INPUT, - (hw->chunk->offset & 7) | (1<<7) | (hw->ctx_valid<<6)); - } else { - /*stream based input*/ - WRITE_VREG(MREG_INPUT, (hw->ctx_valid<<6)); - } - return 0; -} - -static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw) -{ - int i; - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf; - vf = &hw->vfpool[i]; - hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); - } - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - hw->vfbuf_use[i] = 0; - - - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - - hw->mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - hw->eos = 0; - hw->frame_width = hw->frame_height = 0; - hw->frame_dur = hw->frame_prog = 0; - hw->frame_force_skip_flag = 0; - hw->wait_buffer_counter = 0; - hw->first_i_frame_ready = 0; - hw->dec_control &= DEC_CONTROL_INTERNAL_MASK; - hw->refs[0] = -1; - hw->refs[1] = -1; - hw->frame_num = 0; - hw->put_num = 0; - hw->run_count = 0; - hw->not_run_ready = 0; - hw->input_empty = 0; - hw->peek_num = 0; - hw->get_num = 0; - hw->drop_frame_count = 0; - hw->buffer_not_ready = 0; - hw->start_process_time = 0; - hw->error_frame_skip_level = error_frame_skip_level; - if (dec_control) - hw->dec_control = dec_control; -} - -static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw) -{ - int size; - u32 fw_size = 16*0x1000; - struct firmware_s *fw; - - vmpeg12_local_init(hw); - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - pr_debug("get firmware ...\n"); - size = get_firmware_data(VIDEO_DEC_MPEG12_MULTI, fw->data); - if (size < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = size; - hw->fw = fw; - - INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); - INIT_WORK(&hw->work, vmpeg12_work); - INIT_WORK(&hw->notify_work, vmpeg12_notify_work); - - if (NULL == hw->user_data_buffer) { - hw->user_data_buffer = kmalloc(USER_DATA_SIZE, - GFP_KERNEL); - if (!hw->user_data_buffer) { - pr_info("%s: Can not allocate user_data_buffer\n", - __func__); - return -1; - } - } - - vmmpeg2_crate_userdata_manager(hw, - hw->user_data_buffer, - USER_DATA_SIZE); - - amvdec_enable(); - init_timer(&hw->check_timer); - hw->check_timer.data = (unsigned long)hw; - hw->check_timer.function = check_timer_func; - hw->check_timer.expires = jiffies + CHECK_INTERVAL; - - hw->stat |= STAT_TIMER_ARM; - hw->stat |= STAT_ISR_REG; - - hw->buf_start = 0; - hw->init_flag = 0; - WRITE_VREG(DECODE_STOP_POS, udebug_flag); - - return 0; -} - -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) -{ - int index; - - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - if (hw->eos) - return 0; - if (vdec_stream_based(vdec) && (hw->init_flag == 0) - && pre_decode_buf_level != 0) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = vdec->input.size + wp - rp; - else - level = wp - rp; - - if (level < pre_decode_buf_level) { - hw->not_run_ready++; - return 0; - } - } - -#ifdef AGAIN_HAS_THRESHOLD - if (hw->next_again_flag&& - (!vdec_frame_based(vdec))) { - u32 parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - if (parser_wr_ptr >= hw->pre_parser_wr_ptr && - (parser_wr_ptr - hw->pre_parser_wr_ptr) < - again_threshold) { - int r = vdec_sync_input(vdec); - debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s buf level%x\n", - __func__, r); - return 0; - } - } -#endif - - index = find_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) { - hw->buffer_not_ready++; - return 0; - } - hw->not_run_ready = 0; - hw->buffer_not_ready = 0; - if (vdec->parallel_dec == 1) - return (unsigned long)(CORE_MASK_VDEC_1); - else - return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); -} - -static unsigned char get_data_check_sum - (struct vdec_mpeg12_hw_s *hw, int size) -{ - int jj; - int sum = 0; - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - for (jj = 0; jj < size; jj++) - sum += data[jj]; - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - return sum; -} - -static void run(struct vdec_s *vdec, unsigned long mask, -void (*callback)(struct vdec_s *, void *), - void *arg) -{ - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *)vdec->private; - int save_reg = READ_VREG(POWER_CTL_VLD); - int size, ret; - /* reset everything except DOS_TOP[1] and APB_CBUS[0]*/ - WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); - WRITE_VREG(DOS_SW_RESET0, 0); - WRITE_VREG(POWER_CTL_VLD, save_reg); - hw->run_count++; - vdec_reset_core(vdec); - hw->vdec_cb_arg = arg; - hw->vdec_cb = callback; - -#ifdef AGAIN_HAS_THRESHOLD - hw->pre_parser_wr_ptr = - READ_PARSER_REG(PARSER_VIDEO_WP); - hw->next_again_flag = 0; -#endif - - size = vdec_prepare_input(vdec, &hw->chunk); - if (size < 0) { - hw->input_empty++; - hw->dec_result = DEC_RESULT_AGAIN; - vdec_schedule_work(&hw->work); - return; - } - if (input_frame_based(vdec)) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - if (debug_enable & PRINT_FLAG_VDEC_STATUS - ) { - debug_print(DECODE_ID(hw), 0, - "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", - __func__, size, get_data_check_sum(hw, size), - data[0], data[1], data[2], data[3], - data[4], data[5], data[size - 4], - data[size - 3], data[size - 2], - data[size - 1]); - } - if (debug_enable & PRINT_FRAMEBASE_DATA - ) { - int jj; - - for (jj = 0; jj < size; jj++) { - if ((jj & 0xf) == 0) - debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } else - debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: %x %x %x %x %x size 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP), - size); - - - hw->input_empty = 0; - debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s,%d, size=%d\n", __func__, __LINE__, size); - vdec_enable_input(vdec); - hw->init_flag = 1; - - if (hw->chunk) - debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "input chunk offset %d, size %d\n", - hw->chunk->offset, hw->chunk->size); - - hw->dec_result = DEC_RESULT_NONE; - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - } else { - ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG12, "mmpeg12", vdec, - hw->fw->data, hw->fw->len); - if (ret < 0) { - pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, - hw->fw->name, tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; - } - vdec->mc_loaded = 1; - vdec->mc_type = VFORMAT_MPEG12; - } - if (vmpeg12_hw_ctx_restore(hw) < 0) { - hw->dec_result = DEC_RESULT_ERROR; - debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "ammvdec_mpeg12: error HW context restore\n"); - vdec_schedule_work(&hw->work); - return; - } - /*wmb();*/ - hw->stat |= STAT_MC_LOAD; - hw->last_vld_level = 0; - start_process_time(hw); - amvdec_start(); - hw->stat |= STAT_VDEC_RUN; - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -} - -static void reset(struct vdec_s *vdec) -{ - pr_info("ammvdec_mpeg12: reset.\n"); -} - -static int ammvdec_mpeg12_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct vdec_mpeg12_hw_s *hw = NULL; - - pr_info("ammvdec_mpeg12 probe start.\n"); - - if (pdata == NULL) { - pr_info("ammvdec_mpeg12 platform data undefined.\n"); - return -EFAULT; - } - - hw = vzalloc(sizeof(struct vdec_mpeg12_hw_s)); - if (hw == NULL) { - pr_info("\nammvdec_mpeg12 decoder driver alloc failed\n"); - return -ENOMEM; - } - - pdata->private = hw; - pdata->dec_status = vmmpeg12_dec_status; - pdata->run_ready = run_ready; - pdata->run = run; - pdata->reset = reset; - pdata->irq_handler = vmpeg12_isr; - pdata->threaded_irq_handler = vmpeg12_isr_thread_fn; - pdata->dump_state = vmpeg2_dump_state; - - pdata->user_data_read = vmmpeg2_user_data_read; - pdata->reset_userdata_fifo = vmmpeg2_reset_userdata_fifo; - pdata->wakeup_userdata_poll = vmmpeg2_wakeup_userdata_poll; - - if (pdata->use_vfm_path) { - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - hw->frameinfo_enable = 1; - } - else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - PROVIDER_NAME ".%02x", pdev->id & 0xff); - if (pdata->parallel_dec == 1) { - int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - hw->canvas_spec[i] = 0xffffff; - } - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vf_provider_ops, pdata); - - platform_set_drvdata(pdev, pdata); - hw->canvas_mode = pdata->canvas_mode; - hw->platform_dev = pdev; - - if (pdata->sys_info) - hw->vmpeg12_amstream_dec_info = *pdata->sys_info; - - if (vmpeg12_init(hw) < 0) { - pr_info("ammvdec_mpeg12 init failed.\n"); - if (hw) { - vfree(hw); - hw = NULL; - } - pdata->dec_status = NULL; - return -ENODEV; - } - if (pdata->parallel_dec == 1) - vdec_core_request(pdata, CORE_MASK_VDEC_1); - else { - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - } -#ifdef DUMP_USER_DATA - amvdec_mmpeg12_init_userdata_dump(hw); - reset_user_data_buf(hw); -#endif - - /*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/ - return 0; -} - -static int ammvdec_mpeg12_remove(struct platform_device *pdev) - -{ - struct vdec_mpeg12_hw_s *hw = - (struct vdec_mpeg12_hw_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - struct vdec_s *vdec = hw_to_vdec(hw); - int i; - - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - - if (hw->stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - cancel_work_sync(&hw->userdata_push_work); - cancel_work_sync(&hw->work); - cancel_work_sync(&hw->notify_work); - - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - if (vdec->parallel_dec == 1) - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); - else - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - - if (vdec->parallel_dec == 1) { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); - vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); - } - } - - if (hw->ccbuf_phyAddress_is_remaped_nocache) - codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); - hw->ccbuf_phyAddress_virt = NULL; - hw->ccbuf_phyAddress = 0; - hw->ccbuf_phyAddress_is_remaped_nocache = 0; - - if (hw->user_data_buffer != NULL) { - kfree(hw->user_data_buffer); - hw->user_data_buffer = NULL; - } - vmmpeg2_destroy_userdata_manager(hw); - -#ifdef DUMP_USER_DATA - amvdec_mmpeg12_uninit_userdata_dump(hw); -#endif - - if (hw->fw) { - vfree(hw->fw); - hw->fw = NULL; - } - if (hw) { - vfree(hw); - hw = NULL; - } - pr_info("ammvdec_mpeg12 removed.\n"); - memset(&gvs, 0x0, sizeof(gvs)); - - return 0; -} - -/****************************************/ - -static struct platform_driver ammvdec_mpeg12_driver = { - .probe = ammvdec_mpeg12_probe, - .remove = ammvdec_mpeg12_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t ammvdec_mpeg12_profile = { - .name = "mmpeg12", - .profile = "" -}; - -static struct mconfig mmpeg12_configs[] = { - MC_PU32("stat", &stat), - MC_PU32("radr", &radr), - MC_PU32("rval", &rval), - MC_PU32("dec_control", &dec_control), - MC_PU32("error_frame_skip_level", &error_frame_skip_level), - MC_PU32("decode_timeout_val", &decode_timeout_val), -}; -static struct mconfig_node mmpeg12_node; - -static int __init ammvdec_mpeg12_driver_init_module(void) -{ - pr_info("ammvdec_mpeg12 module init\n"); - - if (platform_driver_register(&ammvdec_mpeg12_driver)) { - pr_info("failed to register ammvdec_mpeg12 driver\n"); - return -ENODEV; - } - vcodec_profile_register(&ammvdec_mpeg12_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &mmpeg12_node, - "mmpeg12", mmpeg12_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit ammvdec_mpeg12_driver_remove_module(void) -{ - pr_info("ammvdec_mpeg12 module exit.\n"); - platform_driver_unregister(&ammvdec_mpeg12_driver); -} - -/****************************************/ -module_param(dec_control, uint, 0664); -MODULE_PARM_DESC(dec_control, "\n ammvdec_mpeg12 decoder control\n"); -module_param(error_frame_skip_level, uint, 0664); -MODULE_PARM_DESC(error_frame_skip_level, - "\n ammvdec_mpeg12 error_frame_skip_level\n"); - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\nradr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\nrval\n"); - -module_param(debug_enable, uint, 0664); -MODULE_PARM_DESC(debug_enable, - "\n ammvdec_mpeg12 debug enable\n"); -module_param(pre_decode_buf_level, int, 0664); -MODULE_PARM_DESC(pre_decode_buf_level, - "\n ammvdec_mpeg12 pre_decode_buf_level\n"); -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg12 decode_timeout_val\n"); - -module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); - -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg12 udebug_flag\n"); - -#ifdef AGAIN_HAS_THRESHOLD -module_param(again_threshold, uint, 0664); -MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); -#endif - -module_init(ammvdec_mpeg12_driver_init_module); -module_exit(ammvdec_mpeg12_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC MULTI MPEG1/2 Video Decoder Driver"); -MODULE_LICENSE("GPL"); - - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/Makefile deleted file mode 100644 index 917cc85e6c7a..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4) += amvdec_mpeg4.o -amvdec_mpeg4-objs += vmpeg4.o - -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI) += amvdec_mmpeg4.o -amvdec_mmpeg4-objs += vmpeg4_multi.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c deleted file mode 100644 index 0d8d4078a1d6..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c +++ /dev/null @@ -1,1270 +0,0 @@ -/* - * drivers/amlogic/amports/vmpeg4.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include "vmpeg4.h" -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include - -#include - - -/* #define CONFIG_AM_VDEC_MPEG4_LOG */ -#ifdef CONFIG_AM_VDEC_MPEG4_LOG -#define AMLOG -#define LOG_LEVEL_VAR amlog_level_vmpeg4 -#define LOG_MASK_VAR amlog_mask_vmpeg4 -#define LOG_LEVEL_ERROR 0 -#define LOG_LEVEL_INFO 1 -#define LOG_LEVEL_DESC "0:ERROR, 1:INFO" -#define LOG_MASK_PTS 0x01 -#define LOG_MASK_DESC "0x01:DEBUG_PTS" -#endif - -#include - -MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); - -#include "../utils/amvdec.h" -#include "../utils/vdec.h" -#include "../utils/firmware.h" - -#define DRIVER_NAME "amvdec_mpeg4" -#define MODULE_NAME "amvdec_mpeg4" - -#define DEBUG_PTS - -/* /#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -/* /#endif */ - -#define I_PICTURE 0 -#define P_PICTURE 1 -#define B_PICTURE 2 - -#define ORI_BUFFER_START_ADDR 0x01000000 - -#define INTERLACE_FLAG 0x80 -#define TOP_FIELD_FIRST_FLAG 0x40 - -/* protocol registers */ -#define MP4_PIC_RATIO AV_SCRATCH_5 -#define MP4_RATE AV_SCRATCH_3 -#define MP4_ERR_COUNT AV_SCRATCH_6 -#define MP4_PIC_WH AV_SCRATCH_7 -#define MREG_BUFFERIN AV_SCRATCH_8 -#define MREG_BUFFEROUT AV_SCRATCH_9 -#define MP4_NOT_CODED_CNT AV_SCRATCH_A -#define MP4_VOP_TIME_INC AV_SCRATCH_B -#define MP4_OFFSET_REG AV_SCRATCH_C -#define MP4_SYS_RATE AV_SCRATCH_E -#define MEM_OFFSET_REG AV_SCRATCH_F - -#define PARC_FORBIDDEN 0 -#define PARC_SQUARE 1 -#define PARC_CIF 2 -#define PARC_10_11 3 -#define PARC_16_11 4 -#define PARC_40_33 5 -#define PARC_RESERVED 6 -/* values between 6 and 14 are reserved */ -#define PARC_EXTENDED 15 - -#define VF_POOL_SIZE 32 -#define DECODE_BUFFER_NUM_MAX 8 -#define PUT_INTERVAL (HZ/100) -#define WORKSPACE_SIZE (1 * SZ_1M) -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) -#define DCAC_BUFF_START_IP 0x02b00000 - - -#define RATE_DETECT_COUNT 5 -#define DURATION_UNIT 96000 -#define PTS_UNIT 90000 - -#define DUR2PTS(x) ((x) - ((x) >> 4)) - -#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) - -static struct vframe_s *vmpeg_vf_peek(void *); -static struct vframe_s *vmpeg_vf_get(void *); -static void vmpeg_vf_put(struct vframe_s *, void *); -static int vmpeg_vf_states(struct vframe_states *states, void *); -static int vmpeg_event_cb(int type, void *data, void *private_data); - -static int vmpeg4_prot_init(void); -static void vmpeg4_local_init(void); - -static const char vmpeg4_dec_id[] = "vmpeg4-dev"; - -#define PROVIDER_NAME "decoder.mpeg4" - -/* - *int query_video_status(int type, int *value); - */ -static const struct vframe_operations_s vmpeg_vf_provider = { - .peek = vmpeg_vf_peek, - .get = vmpeg_vf_get, - .put = vmpeg_vf_put, - .event_cb = vmpeg_event_cb, - .vf_states = vmpeg_vf_states, -}; -static void *mm_blk_handle; -static struct vframe_provider_s vmpeg_vf_prov; - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static struct vframe_s vfpool[VF_POOL_SIZE]; -static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; -static u32 frame_width, frame_height, frame_dur, frame_prog; -static u32 saved_resolution; -static struct timer_list recycle_timer; -static u32 stat; -static u32 buf_size = 32 * 1024 * 1024; -static u32 buf_offset; -static u32 vmpeg4_ratio; -static u64 vmpeg4_ratio64; -static u32 rate_detect; -static u32 vmpeg4_rotation; -static u32 fr_hint_status; - -static u32 total_frame; -static u32 last_vop_time_inc, last_duration; -static u32 last_anch_pts, vop_time_inc_since_last_anch, - frame_num_since_last_anch; -static u64 last_anch_pts_us64; -static struct vdec_info *gvs; - -#ifdef CONFIG_AM_VDEC_MPEG4_LOG -u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; -#endif - -static struct work_struct reset_work; -static struct work_struct notify_work; -static struct work_struct set_clk_work; -static bool is_reset; - -static DEFINE_SPINLOCK(lock); - -static struct dec_sysinfo vmpeg4_amstream_dec_info; - -static unsigned char aspect_ratio_table[16] = { - PARC_FORBIDDEN, - PARC_SQUARE, - PARC_CIF, - PARC_10_11, - PARC_16_11, - PARC_40_33, - PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, - PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, - PARC_RESERVED, PARC_EXTENDED -}; - -static inline u32 index2canvas(u32 index) -{ - const u32 canvas_tab[8] = { -#ifdef NV21 - 0x010100, 0x030302, 0x050504, 0x070706, - 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e -#else - 0x020100, 0x050403, 0x080706, 0x0b0a09, - 0x0e0d0c, 0x11100f, 0x141312, 0x171615 -#endif - }; - - return canvas_tab[index]; -} - -static void set_aspect_ratio(struct vframe_s *vf, unsigned int pixel_ratio) -{ - int ar = 0; - unsigned int num = 0; - unsigned int den = 0; - - if (vmpeg4_ratio64 != 0) { - num = vmpeg4_ratio64 >> 32; - den = vmpeg4_ratio64 & 0xffffffff; - } else { - num = vmpeg4_ratio >> 16; - den = vmpeg4_ratio & 0xffff; - - } - if ((num == 0) || (den == 0)) { - num = 1; - den = 1; - } - - if (vmpeg4_ratio == 0) { - vf->ratio_control |= (0x90 << DISP_RATIO_ASPECT_RATIO_BIT); - /* always stretch to 16:9 */ - } else if (pixel_ratio > 0x0f) { - num = (pixel_ratio >> 8) * - vmpeg4_amstream_dec_info.width * num; - ar = div_u64((pixel_ratio & 0xff) * - vmpeg4_amstream_dec_info.height * den * 0x100ULL + - (num >> 1), num); - } else { - switch (aspect_ratio_table[pixel_ratio]) { - case 0: - num = vmpeg4_amstream_dec_info.width * num; - ar = (vmpeg4_amstream_dec_info.height * den * 0x100 + - (num >> 1)) / num; - break; - case 1: - num = vf->width * num; - ar = (vf->height * den * 0x100 + (num >> 1)) / num; - break; - case 2: - num = (vf->width * 12) * num; - ar = (vf->height * den * 0x100 * 11 + - ((num) >> 1)) / num; - break; - case 3: - num = (vf->width * 10) * num; - ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / - num; - break; - case 4: - num = (vf->width * 16) * num; - ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / - num; - break; - case 5: - num = (vf->width * 40) * num; - ar = (vf->height * den * 0x100 * 33 + (num >> 1)) / - num; - break; - default: - num = vf->width * num; - ar = (vf->height * den * 0x100 + (num >> 1)) / num; - break; - } - } - - ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); - - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); -} - -static irqreturn_t vmpeg4_isr(int irq, void *dev_id) -{ - u32 reg; - struct vframe_s *vf = NULL; - u32 picture_type; - u32 buffer_index; - u32 pts, pts_valid = 0, offset = 0; - u64 pts_us64 = 0; - u32 rate, vop_time_inc, repeat_cnt, duration = 3200; - u32 frame_size; - - reg = READ_VREG(MREG_BUFFEROUT); - - if (reg) { - buffer_index = reg & 0x7; - picture_type = (reg >> 3) & 7; - rate = READ_VREG(MP4_RATE); - repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT); - vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); - - if (buffer_index >= DECODE_BUFFER_NUM_MAX) { - pr_err("fatal error, invalid buffer index."); - return IRQ_HANDLED; - } - - if (vmpeg4_amstream_dec_info.width == 0) { - vmpeg4_amstream_dec_info.width = - READ_VREG(MP4_PIC_WH) >> 16; - } -#if 0 - else { - pr_info("info width = %d, ucode width = %d\n", - vmpeg4_amstream_dec_info.width, - READ_VREG(MP4_PIC_WH) >> 16); - } -#endif - - if (vmpeg4_amstream_dec_info.height == 0) { - vmpeg4_amstream_dec_info.height = - READ_VREG(MP4_PIC_WH) & 0xffff; - } -#if 0 - else { - pr_info("info height = %d, ucode height = %d\n", - vmpeg4_amstream_dec_info.height, - READ_VREG(MP4_PIC_WH) & 0xffff); - } -#endif - if (vmpeg4_amstream_dec_info.rate == 0 - || vmpeg4_amstream_dec_info.rate > 96000) { - /* if ((rate >> 16) != 0) { */ - if ((rate & 0xffff) != 0 && (rate >> 16) != 0) { - vmpeg4_amstream_dec_info.rate = - (rate >> 16) * DURATION_UNIT / - (rate & 0xffff); - duration = vmpeg4_amstream_dec_info.rate; - if (fr_hint_status == VDEC_NEED_HINT) { - schedule_work(¬ify_work); - fr_hint_status = VDEC_HINTED; - } - } else if (rate_detect < RATE_DETECT_COUNT) { - if (vop_time_inc < last_vop_time_inc) { - duration = - vop_time_inc + rate - - last_vop_time_inc; - } else { - duration = - vop_time_inc - last_vop_time_inc; - } - - if (duration == last_duration) { - rate_detect++; - if (rate_detect >= RATE_DETECT_COUNT) { - vmpeg4_amstream_dec_info.rate = - duration * DURATION_UNIT / - rate; - duration = - vmpeg4_amstream_dec_info.rate; - } - } else - rate_detect = 0; - - last_duration = duration; - } - } else { - duration = vmpeg4_amstream_dec_info.rate; -#if 0 - pr_info("info rate = %d, ucode rate = 0x%x:0x%x\n", - vmpeg4_amstream_dec_info.rate, - READ_VREG(MP4_RATE), vop_time_inc); -#endif - } - - if ((picture_type == I_PICTURE) || - (picture_type == P_PICTURE)) { - offset = READ_VREG(MP4_OFFSET_REG); - /*2500-->3000,because some mpeg4 - *video may checkout failed; - *may have av sync problem.can changed small later. - *263 may need small? - */ - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, - &frame_size, 3000, - &pts_us64) == 0) { - pts_valid = 1; - last_anch_pts = pts; - last_anch_pts_us64 = pts_us64; -#ifdef CONFIG_AM_VDEC_MPEG4_LOG - pts_hit++; -#endif - } else { -#ifdef CONFIG_AM_VDEC_MPEG4_LOG - pts_missed++; -#endif - } -#ifdef CONFIG_AM_VDEC_MPEG4_LOG - amlog_mask(LOG_MASK_PTS, - "I offset 0x%x, pts_valid %d pts=0x%x\n", - offset, pts_valid, pts); -#endif - } - - if (pts_valid) { - last_anch_pts = pts; - last_anch_pts_us64 = pts_us64; - frame_num_since_last_anch = 0; - vop_time_inc_since_last_anch = 0; - } else { - pts = last_anch_pts; - pts_us64 = last_anch_pts_us64; - - if ((rate != 0) && ((rate >> 16) == 0) - && vmpeg4_amstream_dec_info.rate == 0) { - /* variable PTS rate */ - /*bug on variable pts calc, - *do as dixed vop first if we - *have rate setting before. - */ - if (vop_time_inc > last_vop_time_inc) { - vop_time_inc_since_last_anch += - vop_time_inc - last_vop_time_inc; - } else { - vop_time_inc_since_last_anch += - vop_time_inc + rate - - last_vop_time_inc; - } - - pts += vop_time_inc_since_last_anch * - PTS_UNIT / rate; - pts_us64 += (vop_time_inc_since_last_anch * - PTS_UNIT / rate) * 100 / 9; - - if (vop_time_inc_since_last_anch > (1 << 14)) { - /* avoid overflow */ - last_anch_pts = pts; - last_anch_pts_us64 = pts_us64; - vop_time_inc_since_last_anch = 0; - } - } else { - /* fixed VOP rate */ - frame_num_since_last_anch++; - pts += DUR2PTS(frame_num_since_last_anch * - vmpeg4_amstream_dec_info.rate); - pts_us64 += DUR2PTS(frame_num_since_last_anch * - vmpeg4_amstream_dec_info.rate) * - 100 / 9; - - if (frame_num_since_last_anch > (1 << 15)) { - /* avoid overflow */ - last_anch_pts = pts; - last_anch_pts_us64 = pts_us64; - frame_num_since_last_anch = 0; - } - } - } - - if (reg & INTERLACE_FLAG) { /* interlace */ - if (kfifo_get(&newframe_q, &vf) == 0) { - printk - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = vmpeg4_amstream_dec_info.width; - vf->height = vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = vmpeg4_rotation; - vf->pts = pts; - vf->pts_us64 = pts_us64; - vf->duration = duration >> 1; - vf->duration_pulldown = 0; - vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->type_original = vf->type; - - set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO)); - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - if (kfifo_get(&newframe_q, &vf) == 0) { - printk( - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = vmpeg4_amstream_dec_info.width; - vf->height = vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = vmpeg4_rotation; - - vf->pts = 0; - vf->pts_us64 = 0; - vf->duration = duration >> 1; - - vf->duration_pulldown = 0; - vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->type_original = vf->type; - - set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO)); - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - amlog_mask(LOG_MASK_PTS, - "[%s:%d] [inte] dur=0x%x rate=%d picture_type=%d\n", - __func__, __LINE__, vf->duration, - vmpeg4_amstream_dec_info.rate, picture_type); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - } else { /* progressive */ - if (kfifo_get(&newframe_q, &vf) == 0) { - printk - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = vmpeg4_amstream_dec_info.width; - vf->height = vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = vmpeg4_rotation; - vf->pts = pts; - vf->pts_us64 = pts_us64; - vf->duration = duration; - vf->duration_pulldown = repeat_cnt * duration; -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->type_original = vf->type; - - set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO)); - - amlog_mask(LOG_MASK_PTS, - "[%s:%d] [prog] dur=0x%x rate=%d picture_type=%d\n", - __func__, __LINE__, vf->duration, - vmpeg4_amstream_dec_info.rate, picture_type); - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - - total_frame += repeat_cnt + 1; - - WRITE_VREG(MREG_BUFFEROUT, 0); - - last_vop_time_inc = vop_time_inc; - - /*count info*/ - gvs->frame_dur = duration; - vdec_count_info(gvs, 0, offset); - } - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - return IRQ_HANDLED; -} - -static struct vframe_s *vmpeg_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vmpeg_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) -{ - kfifo_put(&recycle_q, (const struct vframe_s *)vf); -} - -static int vmpeg_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vmpeg_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vmpeg4_local_init(); - vmpeg4_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vmpeg_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - - return 0; -} - -static void vmpeg4_notify_work(struct work_struct *work) -{ - pr_info("frame duration changed %d\n", vmpeg4_amstream_dec_info.rate); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long) - vmpeg4_amstream_dec_info.rate)); - return; -} - -static void reset_do_work(struct work_struct *work) -{ - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vmpeg_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vmpeg4_local_init(); - vmpeg4_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vmpeg_vf_prov); -#endif - amvdec_start(); -} - -static void vmpeg4_set_clk(struct work_struct *work) -{ - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_MPEG4, - frame_width, frame_height, fps); -} - -static void vmpeg_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - - while (!kfifo_is_empty(&recycle_q) && (READ_VREG(MREG_BUFFERIN) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < DECODE_BUFFER_NUM_MAX) - && (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(MREG_BUFFERIN, ~(1 << vf->index)); - vf->index = DECODE_BUFFER_NUM_MAX; - } - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - } - - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) - schedule_work(&set_clk_work); - - if (READ_VREG(AV_SCRATCH_L)) { - pr_info("mpeg4 fatal error happened,need reset !!\n"); - schedule_work(&reset_work); - } - - - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vmpeg4_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = vmpeg4_amstream_dec_info.width; - vstatus->frame_height = vmpeg4_amstream_dec_info.height; - if (0 != vmpeg4_amstream_dec_info.rate) - vstatus->frame_rate = - DURATION_UNIT / vmpeg4_amstream_dec_info.rate; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(MP4_ERR_COUNT); - vstatus->status = stat; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = frame_dur; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -int vmpeg4_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -static int vmpeg4_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -/****************************************/ -static int vmpeg4_canvas_init(void) -{ - int i, ret; - u32 canvas_width, canvas_height; - unsigned long buf_start; - u32 alloc_size, decbuf_size, decbuf_y_size, decbuf_uv_size; - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - int w = vmpeg4_amstream_dec_info.width; - int h = vmpeg4_amstream_dec_info.height; - int align_w, align_h; - int max, min; - - align_w = ALIGN(w, 64); - align_h = ALIGN(h, 64); - if (align_w > align_h) { - max = align_w; - min = align_h; - } else { - max = align_h; - min = align_w; - } - /* HD & SD */ - if ((max > 1920 || min > 1088) && - ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= - buf_size) { - canvas_width = align_w; - canvas_height = align_h; - decbuf_y_size = ALIGN(align_w * align_h, SZ_64K); - decbuf_uv_size = ALIGN(align_w * align_h/4, SZ_64K); - decbuf_size = ALIGN(align_w * align_h * 3/2, SZ_64K); - } else { /*1080p*/ - if (h > w) { - canvas_width = 1088; - canvas_height = 1920; - } else { - canvas_width = 1920; - canvas_height = 1088; - } - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - } - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - /* workspace mem */ - if (i == (MAX_BMMU_BUFFER_NUM - 1)) - alloc_size = WORKSPACE_SIZE; - else - alloc_size = decbuf_size; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, - alloc_size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { - buf_offset = buf_start - DCAC_BUFF_START_IP; - continue; - } - - -#ifdef NV21 - canvas_config(2 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(2 * i + 1, - buf_start + - decbuf_y_size, canvas_width, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); -#else - canvas_config(3 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 1, - buf_start + - decbuf_y_size, canvas_width / 2, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 2, - buf_start + - decbuf_y_size + decbuf_uv_size, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); -#endif - - } - return 0; -} - -static int vmpeg4_prot_init(void) -{ - int r; -#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); -#endif - - r = vmpeg4_canvas_init(); - - /* index v << 16 | u << 8 | y */ -#ifdef NV21 - WRITE_VREG(AV_SCRATCH_0, 0x010100); - WRITE_VREG(AV_SCRATCH_1, 0x030302); - WRITE_VREG(AV_SCRATCH_2, 0x050504); - WRITE_VREG(AV_SCRATCH_3, 0x070706); - WRITE_VREG(AV_SCRATCH_G, 0x090908); - WRITE_VREG(AV_SCRATCH_H, 0x0b0b0a); - WRITE_VREG(AV_SCRATCH_I, 0x0d0d0c); - WRITE_VREG(AV_SCRATCH_J, 0x0f0f0e); -#else - WRITE_VREG(AV_SCRATCH_0, 0x020100); - WRITE_VREG(AV_SCRATCH_1, 0x050403); - WRITE_VREG(AV_SCRATCH_2, 0x080706); - WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); - WRITE_VREG(AV_SCRATCH_G, 0x0e0d0c); - WRITE_VREG(AV_SCRATCH_H, 0x11100f); - WRITE_VREG(AV_SCRATCH_I, 0x141312); - WRITE_VREG(AV_SCRATCH_J, 0x171615); -#endif - WRITE_VREG(AV_SCRATCH_L, 0);/*clearfatal error flag*/ - - /* notify ucode the buffer offset */ - WRITE_VREG(AV_SCRATCH_F, buf_offset); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - /* clear repeat count */ - WRITE_VREG(MP4_NOT_CODED_CNT, 0); - - WRITE_VREG(MREG_BUFFERIN, 0); - WRITE_VREG(MREG_BUFFEROUT, 0); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - - - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - -#if 1/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - pr_debug("mpeg4 meson8 prot init\n"); - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); -#endif - - WRITE_VREG(MP4_PIC_WH, (vmpeg4_amstream_dec_info. - width << 16) | vmpeg4_amstream_dec_info.height); - WRITE_VREG(MP4_SYS_RATE, vmpeg4_amstream_dec_info.rate); - return r; -} - -static void vmpeg4_local_init(void) -{ - int i; - - vmpeg4_ratio = vmpeg4_amstream_dec_info.ratio; - - vmpeg4_ratio64 = vmpeg4_amstream_dec_info.ratio64; - - vmpeg4_rotation = - (((unsigned long) vmpeg4_amstream_dec_info.param) - >> 16) & 0xffff; - - frame_width = frame_height = frame_dur = frame_prog = 0; - - total_frame = 0; - saved_resolution = 0; - last_anch_pts = 0; - - last_anch_pts_us64 = 0; - - last_vop_time_inc = last_duration = 0; - - vop_time_inc_since_last_anch = 0; - - frame_num_since_last_anch = 0; - -#ifdef CONFIG_AM_VDEC_MPEG4_LOG - pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0; -#endif - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - vfbuf_use[i] = 0; - - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &vfpool[i]; - - vfpool[i].index = DECODE_BUFFER_NUM_MAX; - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); -} - -static s32 vmpeg4_init(void) -{ - int trickmode_fffb = 0; - int size = -1, ret = -1; - char fw_name[32] = {0}; - char *buf = vmalloc(0x1000 * 16); - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - amlog_level(LOG_LEVEL_INFO, "vmpeg4_init\n"); - - if (vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_5) { - size = get_firmware_data(VIDEO_DEC_MPEG4_5, buf); - strncpy(fw_name, "vmpeg4_mc_5", sizeof(fw_name)); - - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_5\n"); - } else if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_H263) { - size = get_firmware_data(VIDEO_DEC_H263, buf); - strncpy(fw_name, "h263_mc", sizeof(fw_name)); - - pr_info("load VIDEO_DEC_FORMAT_H263\n"); - } else - pr_err("unsupport mpeg4 sub format %d\n", - vmpeg4_amstream_dec_info.format); - - if (size < 0) { - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_MPEG4, fw_name, buf); - if (ret < 0) { - amvdec_disable(); - vfree(buf); - pr_err("%s: the %s fw loading failed, err: %x\n", - fw_name, tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(buf); - stat |= STAT_MC_LOAD; - query_video_status(0, &trickmode_fffb); - - init_timer(&recycle_timer); - stat |= STAT_TIMER_INIT; - - if (vdec_request_irq(VDEC_IRQ_1, vmpeg4_isr, - "vmpeg4-irq", (void *)vmpeg4_dec_id)) { - amlog_level(LOG_LEVEL_ERROR, "vmpeg4 irq register error.\n"); - return -ENOENT; - } - stat |= STAT_ISR_REG; - vmpeg4_local_init(); - /* enable AMRISC side protocol */ - ret = vmpeg4_prot_init(); - if (ret < 0) { - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - return ret; - } - amvdec_enable(); - fr_hint_status = VDEC_NO_NEED_HINT; -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, - NULL); - vf_reg_provider(&vmpeg_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, - NULL); - vf_reg_provider(&vmpeg_vf_prov); -#endif - if (vmpeg4_amstream_dec_info.rate != 0) { - if (!is_reset) { - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long) - vmpeg4_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; - } - } else - fr_hint_status = VDEC_NEED_HINT; - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong)&recycle_timer; - recycle_timer.function = vmpeg_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - return 0; -} - -static int amvdec_mpeg4_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - if (pdata == NULL) { - amlog_level(LOG_LEVEL_ERROR, - "amvdec_mpeg4 memory resource undefined.\n"); - return -EFAULT; - } - - if (pdata->sys_info) { - vmpeg4_amstream_dec_info = *pdata->sys_info; - if ((vmpeg4_amstream_dec_info.height != 0) && - (vmpeg4_amstream_dec_info.width > - (MAX_MPEG4_SUPPORT_SIZE/vmpeg4_amstream_dec_info.height))) { - pr_info("amvdec_mpeg4: oversize, unsupport: %d*%d\n", - vmpeg4_amstream_dec_info.width, - vmpeg4_amstream_dec_info.height); - return -EFAULT; - } - } - pdata->dec_status = vmpeg4_dec_status; - pdata->set_isreset = vmpeg4_set_isreset; - is_reset = 0; - - INIT_WORK(&reset_work, reset_do_work); - INIT_WORK(¬ify_work, vmpeg4_notify_work); - INIT_WORK(&set_clk_work, vmpeg4_set_clk); - - vmpeg4_vdec_info_init(); - - if (vmpeg4_init() < 0) { - amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg4 init failed.\n"); - kfree(gvs); - gvs = NULL; - pdata->dec_status = NULL; - return -ENODEV; - } - - return 0; -} - -static int amvdec_mpeg4_remove(struct platform_device *pdev) -{ - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)vmpeg4_dec_id); - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); - fr_hint_status = VDEC_NO_NEED_HINT; - - vf_unreg_provider(&vmpeg_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - cancel_work_sync(&reset_work); - cancel_work_sync(¬ify_work); - cancel_work_sync(&set_clk_work); - - amvdec_disable(); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - amlog_mask(LOG_MASK_PTS, - "pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit, - pts_missed, pts_i_hit, pts_i_missed); - amlog_mask(LOG_MASK_PTS, "total frame %d, rate %d\n", total_frame, - vmpeg4_amstream_dec_info.rate); - kfree(gvs); - gvs = NULL; - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_mpeg4_driver = { - .probe = amvdec_mpeg4_probe, - .remove = amvdec_mpeg4_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_mpeg4_profile = { - .name = "mpeg4", - .profile = "" -}; -static struct mconfig mpeg4_configs[] = { - MC_PU32("stat", &stat), -}; -static struct mconfig_node mpeg4_node; - -static int __init amvdec_mpeg4_driver_init_module(void) -{ - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg4 module init\n"); - - if (platform_driver_register(&amvdec_mpeg4_driver)) { - amlog_level(LOG_LEVEL_ERROR, - "failed to register amvdec_mpeg4 driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvdec_mpeg4_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &mpeg4_node, - "mpeg4", mpeg4_configs, CONFIG_FOR_R); - return 0; -} - -static void __exit amvdec_mpeg4_driver_remove_module(void) -{ - amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg4 module remove.\n"); - - platform_driver_unregister(&amvdec_mpeg4_driver); -} - -/****************************************/ -module_init(amvdec_mpeg4_driver_init_module); -module_exit(amvdec_mpeg4_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC MPEG4 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h deleted file mode 100644 index 7914e6a6ada4..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * drivers/amlogic/amports/vmpeg4.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VMPEG4_H -#define VMPEG4_H - -/* /#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -/* TODO: move to register headers */ -#define VPP_VD1_POSTBLEND (1 << 10) -/* /#endif */ - -#endif /* VMPEG4_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c deleted file mode 100644 index 84a8d38d23be..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ /dev/null @@ -1,2033 +0,0 @@ -/* - * drivers/amlogic/amports/vmpeg4.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" - -#include "../utils/amvdec.h" -#include "../utils/vdec_input.h" -#include "../utils/vdec.h" -#include "../utils/firmware.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include "../utils/firmware.h" - -#include - - -#define DRIVER_NAME "ammvdec_mpeg4" -#define MODULE_NAME "ammvdec_mpeg4" - -#define MEM_NAME "codec_mmpeg4" - -#define DEBUG_PTS - -#define NV21 -#define I_PICTURE 0 -#define P_PICTURE 1 -#define B_PICTURE 2 - -#define ORI_BUFFER_START_ADDR 0x01000000 -#define DEFAULT_MEM_SIZE (32*SZ_1M) - -#define INTERLACE_FLAG 0x80 -#define TOP_FIELD_FIRST_FLAG 0x40 - -/* protocol registers */ -#define MREG_REF0 AV_SCRATCH_1 -#define MREG_REF1 AV_SCRATCH_2 -#define MP4_PIC_RATIO AV_SCRATCH_5 -#define MP4_RATE AV_SCRATCH_3 -#define MP4_ERR_COUNT AV_SCRATCH_6 -#define MP4_PIC_WH AV_SCRATCH_7 -#define MREG_INPUT AV_SCRATCH_8 -#define MREG_BUFFEROUT AV_SCRATCH_9 -#define MP4_NOT_CODED_CNT AV_SCRATCH_A -#define MP4_VOP_TIME_INC AV_SCRATCH_B -#define MP4_OFFSET_REG AV_SCRATCH_C -#define MP4_SYS_RATE AV_SCRATCH_E -#define MEM_OFFSET_REG AV_SCRATCH_F - -#define PARC_FORBIDDEN 0 -#define PARC_SQUARE 1 -#define PARC_CIF 2 -#define PARC_10_11 3 -#define PARC_16_11 4 -#define PARC_40_33 5 -#define PARC_RESERVED 6 -/* values between 6 and 14 are reserved */ -#define PARC_EXTENDED 15 - -#define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 4 -#define PUT_INTERVAL (HZ/100) -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) -#define WORKSPACE_SIZE (12*SZ_64K) -static u32 buf_size = 32 * 1024 * 1024; - -#define CTX_LMEM_SWAP_OFFSET 0 -#define CTX_QUANT_MATRIX_OFFSET 0x800 -/* dcac buffer must align at 4k boundary */ -#define CTX_DCAC_BUF_OFFSET 0x1000 -#define CTX_DECBUF_OFFSET (0x0c0000 + 0x1000) - -#define RATE_DETECT_COUNT 5 -#define DURATION_UNIT 96000 -#define PTS_UNIT 90000 -#define CHECK_INTERVAL (HZ/100) - -#define DUR2PTS(x) ((x) - ((x) >> 4)) - -#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) - -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_ERROR 3 -#define DEC_RESULT_FORCE_EXIT 4 -#define DEC_RESULT_EOS 5 -#define DEC_DECODE_TIMEOUT 0x21 -#define DECODE_ID(hw) (hw_to_vdec(hw)->id) -#define DECODE_STOP_POS AV_SCRATCH_K -static u32 udebug_flag; - -static struct vframe_s *vmpeg_vf_peek(void *); -static struct vframe_s *vmpeg_vf_get(void *); -static void vmpeg_vf_put(struct vframe_s *, void *); -static int vmpeg_vf_states(struct vframe_states *states, void *); -static int vmpeg_event_cb(int type, void *data, void *private_data); -static int pre_decode_buf_level = 0x800; -static int debug_enable; -static unsigned int radr; -static unsigned int rval; - -#define VMPEG4_DEV_NUM 9 -static unsigned int max_decode_instance_num = VMPEG4_DEV_NUM; -static unsigned int max_process_time[VMPEG4_DEV_NUM]; -static unsigned int decode_timeout_val = 100; - - -#undef pr_info -#define pr_info printk -unsigned int mpeg4_debug_mask = 0xff; - -#define PRINT_FLAG_ERROR 0x0 -#define PRINT_FLAG_RUN_FLOW 0X0001 -#define PRINT_FLAG_TIMEINFO 0x0002 -#define PRINT_FLAG_UCODE_DETAIL 0x0004 -#define PRINT_FLAG_VLD_DETAIL 0x0008 -#define PRINT_FLAG_DEC_DETAIL 0x0010 -#define PRINT_FLAG_BUFFER_DETAIL 0x0020 -#define PRINT_FLAG_RESTORE 0x0040 -#define PRINT_FRAME_NUM 0x0080 -#define PRINT_FLAG_FORCE_DONE 0x0100 -#define PRINT_FLAG_COUNTER 0X0200 -#define PRINT_FRAMEBASE_DATA 0x0400 -#define PRINT_FLAG_VDEC_STATUS 0x0800 -#define PRINT_FLAG_TIMEOUT_STATUS 0x1000 - -int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...) -{ - if (((debug_enable & debug_flag) && - ((1 << index) & mpeg4_debug_mask)) - || (debug_flag == PRINT_FLAG_ERROR)) { - unsigned char buf[512]; - int len = 0; - va_list args; - va_start(args, fmt); - len = sprintf(buf, "%d: ", index); - vsnprintf(buf + len, 512-len, fmt, args); - pr_info("%s", buf); - va_end(args); - } - return 0; -} - -struct vdec_mpeg4_hw_s { - spinlock_t lock; - struct platform_device *platform_dev; - /* struct device *cma_dev; */ - - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - struct vframe_s vfpool[VF_POOL_SIZE]; - - s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; - u32 frame_width; - u32 frame_height; - u32 frame_dur; - u32 frame_prog; - - u32 ctx_valid; - u32 reg_vcop_ctrl_reg; - u32 reg_pic_head_info; - u32 reg_mpeg1_2_reg; - u32 reg_slice_qp; - u32 reg_mp4_pic_wh; - u32 reg_mp4_rate; - u32 reg_mb_info; - u32 reg_dc_ac_ctrl; - u32 reg_iqidct_control; - u32 reg_resync_marker_length; - u32 reg_rv_ai_mb_count; - struct timer_list check_timer; - u32 decode_timeout_count; - u32 start_process_time; - u32 last_vld_level; - u8 init_flag; - u32 eos; - void *mm_blk_handle; - - struct vframe_chunk_s *chunk; - u32 stat; - unsigned long buf_start; - u32 buf_size; - /* - unsigned long cma_alloc_addr; - int cma_alloc_count; - */ - u32 vmpeg4_ratio; - u64 vmpeg4_ratio64; - u32 rate_detect; - u32 vmpeg4_rotation; - u32 total_frame; - u32 last_vop_time_inc; - u32 last_duration; - u32 last_anch_pts; - u32 vop_time_inc_since_last_anch; - u32 frame_num_since_last_anch; - u64 last_anch_pts_us64; - - u32 pts_hit; - u32 pts_missed; - u32 pts_i_hit; - u32 pts_i_missed; - u32 decoded_type[DECODE_BUFFER_NUM_MAX]; - u32 buffer_info[DECODE_BUFFER_NUM_MAX]; - u32 pts[DECODE_BUFFER_NUM_MAX]; - u64 pts64[DECODE_BUFFER_NUM_MAX]; - bool pts_valid[DECODE_BUFFER_NUM_MAX]; - u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; -#ifdef NV21 - struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; -#else - struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][3]; -#endif - struct dec_sysinfo vmpeg4_amstream_dec_info; - - s32 refs[2]; - int dec_result; - struct work_struct work; - - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - u32 frame_num; - u32 put_num; - u32 sys_mp4_rate; - u32 run_count; - u32 not_run_ready; - u32 buffer_not_ready; - u32 input_empty; - u32 peek_num; - u32 get_num; - u32 first_i_frame_ready; - u32 drop_frame_count; - u32 timeout_flag; - - struct firmware_s *fw; -}; -static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); -static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw); - -#define PROVIDER_NAME "vdec.mpeg4" - -/* - *int query_video_status(int type, int *value); - */ -static const struct vframe_operations_s vf_provider_ops = { - .peek = vmpeg_vf_peek, - .get = vmpeg_vf_get, - .put = vmpeg_vf_put, - .event_cb = vmpeg_event_cb, - .vf_states = vmpeg_vf_states, -}; - -static unsigned char aspect_ratio_table[16] = { - PARC_FORBIDDEN, - PARC_SQUARE, - PARC_CIF, - PARC_10_11, - PARC_16_11, - PARC_40_33, - PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, - PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, - PARC_RESERVED, PARC_EXTENDED -}; - -static void reset_process_time(struct vdec_mpeg4_hw_s *hw); -static int find_buffer(struct vdec_mpeg4_hw_s *hw) -{ - int i; - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - if (hw->vfbuf_use[i] == 0) - return i; - } - - return DECODE_BUFFER_NUM_MAX; -} - -static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec) -{ - int i; - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - if (hw->canvas_spec[i] == spec) - return i; - } - - return -1; -} - -static void set_frame_info(struct vdec_mpeg4_hw_s *hw, struct vframe_s *vf, - int buffer_index) -{ - int ar = 0; - unsigned int num = 0; - unsigned int den = 0; - unsigned int pixel_ratio = READ_VREG(MP4_PIC_RATIO); - - if (hw->vmpeg4_ratio64 != 0) { - num = hw->vmpeg4_ratio64>>32; - den = hw->vmpeg4_ratio64 & 0xffffffff; - } else { - num = hw->vmpeg4_ratio>>16; - den = hw->vmpeg4_ratio & 0xffff; - - } - if ((num == 0) || (den == 0)) { - num = 1; - den = 1; - } - - if (hw->vmpeg4_ratio == 0) { - vf->ratio_control |= (0x90 << DISP_RATIO_ASPECT_RATIO_BIT); - /* always stretch to 16:9 */ - } else if (pixel_ratio > 0x0f) { - num = (pixel_ratio >> 8) * - hw->vmpeg4_amstream_dec_info.width * num; - ar = div_u64((pixel_ratio & 0xff) * - hw->vmpeg4_amstream_dec_info.height * den * 0x100ULL + - (num >> 1), num); - } else { - switch (aspect_ratio_table[pixel_ratio]) { - case 0: - num = hw->vmpeg4_amstream_dec_info.width * num; - ar = (hw->vmpeg4_amstream_dec_info.height * den * - 0x100 + (num >> 1)) / num; - break; - case 1: - num = vf->width * num; - ar = (vf->height * den * 0x100 + (num >> 1)) / num; - break; - case 2: - num = (vf->width * 12) * num; - ar = (vf->height * den * 0x100 * 11 + - ((num) >> 1)) / num; - break; - case 3: - num = (vf->width * 10) * num; - ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / - num; - break; - case 4: - num = (vf->width * 16) * num; - ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / - num; - break; - case 5: - num = (vf->width * 40) * num; - ar = (vf->height * den * 0x100 * 33 + (num >> 1)) / - num; - break; - default: - num = vf->width * num; - ar = (vf->height * den * 0x100 + (num >> 1)) / num; - break; - } - } - - ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); - - vf->signal_type = 0; - vf->type_original = vf->type; - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - vf->canvas0Addr = vf->canvas1Addr = -1; -#ifdef NV21 - vf->plane_num = 2; -#else - vf->plane_num = 3; -#endif - vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; - vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; -#ifndef NV21 - vf->canvas0_config[2] = hw->canvas_config[buffer_index][2]; -#endif - vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; - vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; -#ifndef NV21 - vf->canvas1_config[2] = hw->canvas_config[buffer_index][2]; -#endif -} - -static inline void vmpeg4_save_hw_context(struct vdec_mpeg4_hw_s *hw) -{ - hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG); - hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); - hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO); - hw->reg_slice_qp = READ_VREG(SLICE_QP); - hw->reg_mp4_pic_wh = READ_VREG(MP4_PIC_WH); - hw->reg_mp4_rate = READ_VREG(MP4_RATE); - hw->reg_mb_info = READ_VREG(MB_INFO); - hw->reg_dc_ac_ctrl = READ_VREG(DC_AC_CTRL); - hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); - hw->reg_resync_marker_length = READ_VREG(RESYNC_MARKER_LENGTH); - hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); -} - -static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) -{ - u32 reg; - struct vframe_s *vf = NULL; - u32 picture_type; - int index; - u32 pts, offset = 0; - bool pts_valid = false; - u64 pts_us64 = 0; - u32 frame_size; - u32 time_increment_resolution, fixed_vop_rate, vop_time_inc; - u32 repeat_cnt, duration = 3200; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); - if (hw->eos) - return IRQ_HANDLED; - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - if (READ_VREG(AV_SCRATCH_M) != 0 && - (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_UCODE_DETAIL, - "dbg %x: %x, level %x, wp %x, rp %x, cnt %x\n", - READ_VREG(AV_SCRATCH_M), READ_VREG(AV_SCRATCH_N), - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VIFF_BIT_CNT)); - WRITE_VREG(AV_SCRATCH_M, 0); - return IRQ_HANDLED; - } - reg = READ_VREG(MREG_BUFFEROUT); - - time_increment_resolution = READ_VREG(MP4_RATE); - fixed_vop_rate = time_increment_resolution >> 16; - time_increment_resolution &= 0xffff; - if (time_increment_resolution > 0 && fixed_vop_rate == 0) - hw->sys_mp4_rate = time_increment_resolution; - if (hw->vmpeg4_amstream_dec_info.rate == 0) { - if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { - /* fixed VOP rate */ - hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * - DURATION_UNIT / time_increment_resolution; - } else if (time_increment_resolution == 0 - && hw->sys_mp4_rate > 0) - time_increment_resolution = hw->sys_mp4_rate; - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "resolution=%d,fvop=%d,rate=%d\n", - time_increment_resolution, fixed_vop_rate, - hw->vmpeg4_amstream_dec_info.rate); - - if (reg == 2) { - /* timeout when decoding next frame */ - - /* for frame based case, insufficient result may happen - * at the beginning when only VOL head is available save - * HW context also, such as for the QTable from VCOP register - */ - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "ammvdec_mpeg4: timeout\n"); - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "level=%x, vtl=%x,bcnt=%d\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_CONTROL), - READ_VREG(VIFF_BIT_CNT)); - if (input_frame_based(vdec)) { - vmpeg4_save_hw_context(hw); - hw->timeout_flag++; - } else { - hw->dec_result = DEC_RESULT_AGAIN; - - schedule_work(&hw->work); - } - return IRQ_HANDLED; - } else { - reset_process_time(hw); - picture_type = (reg >> 3) & 7; - repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT); - vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); - - index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); - - if (index < 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "invalid buffer index."); - hw->dec_result = DEC_RESULT_ERROR; - - schedule_work(&hw->work); - - return IRQ_HANDLED; - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, - "index=%d, used=%d cnt=%d, vopinc=%d\n", - index, hw->vfbuf_use[index], repeat_cnt, vop_time_inc); - - hw->dec_result = DEC_RESULT_DONE; - - if (hw->vmpeg4_amstream_dec_info.width == 0) { - hw->vmpeg4_amstream_dec_info.width = - READ_VREG(MP4_PIC_WH) >> 16; - } - - if (hw->vmpeg4_amstream_dec_info.height == 0) { - hw->vmpeg4_amstream_dec_info.height = - READ_VREG(MP4_PIC_WH) & 0xffff; - } - - if (hw->vmpeg4_amstream_dec_info.rate == 0) { - if (vop_time_inc < hw->last_vop_time_inc) { - duration = vop_time_inc + - time_increment_resolution - - hw->last_vop_time_inc; - } else { - duration = vop_time_inc - - hw->last_vop_time_inc; - } - - if (duration == hw->last_duration) { - hw->rate_detect++; - if ((hw->rate_detect >= RATE_DETECT_COUNT) && - (time_increment_resolution != 0)) { - hw->vmpeg4_amstream_dec_info.rate = - duration * DURATION_UNIT / - time_increment_resolution; - duration = - hw->vmpeg4_amstream_dec_info.rate; - } - } else { - hw->rate_detect = 0; - hw->last_duration = duration; - } - } else { - duration = hw->vmpeg4_amstream_dec_info.rate; -#if 0 - pr_info("info rate = %d, ucode rate = 0x%x:0x%x\n", - hw->vmpeg4_amstream_dec_info.rate, - READ_VREG(MP4_RATE), vop_time_inc); -#endif - } - - if ((I_PICTURE == picture_type) || - (P_PICTURE == picture_type)) { - offset = READ_VREG(MP4_OFFSET_REG); - if (hw->chunk) { - hw->pts_valid[index] = hw->chunk->pts_valid; - hw->pts[index] = hw->chunk->pts; - hw->pts64[index] = hw->chunk->pts64; - } else { - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, - &frame_size, 3000, - &pts_us64) == 0) { - hw->pts_valid[index] = true; - hw->pts[index] = pts; - hw->pts64[index] = pts_us64; - hw->pts_hit++; - } else { - hw->pts_valid[index] = false; - hw->pts_missed++; - } - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "I/P offset 0x%x, pts_valid %d pts=0x%x,index=%d,used=%d\n", - offset, hw->pts_valid[index], - hw->pts[index], index, hw->vfbuf_use[index]); - } else { - hw->pts_valid[index] = false; - hw->pts[index] = 0; - hw->pts64[index] = 0; - } - - hw->buffer_info[index] = reg; - hw->vfbuf_use[index] = 0; - hw->decoded_type[index] = picture_type; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "amvdec_mpeg4: decoded buffer %d, frame_type %s,pts=%x\n", - index, - (picture_type == I_PICTURE) ? "I" : - (picture_type == P_PICTURE) ? "P" : "B", - hw->pts[index]); - - /* Buffer management - * todo: add sequence-end flush - */ - if ((picture_type == I_PICTURE) || - (picture_type == P_PICTURE)) { - hw->vfbuf_use[index]++; - - if (hw->refs[1] == -1) { - hw->refs[1] = index; - index = -1; - } else if (hw->refs[0] == -1) { - hw->refs[0] = hw->refs[1]; - hw->refs[1] = index; - index = hw->refs[0]; - } else { - hw->vfbuf_use[hw->refs[0]]--; - hw->refs[0] = hw->refs[1]; - hw->refs[1] = index; - index = hw->refs[0]; - } - } else { - /* if this is a B frame, then drop (depending on if - * there are two reference frames) or display - * immediately - */ - if (hw->refs[1] == -1) - index = -1; - } - - vmpeg4_save_hw_context(hw); - - if (index < 0) { - schedule_work(&hw->work); - return IRQ_HANDLED; - } - - reg = hw->buffer_info[index]; - pts_valid = hw->pts_valid[index]; - pts = hw->pts[index]; - pts_us64 = hw->pts64[index]; - - if ((hw->first_i_frame_ready == 0) && - (I_PICTURE == hw->decoded_type[index])) - hw->first_i_frame_ready = 1; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "queued %d, pts = 0x%x, pts_valid=%d,index=%d,used=%d,type=%d,decode_type=%d\n", - index, pts, pts_valid, index, hw->vfbuf_use[index], - picture_type, hw->decoded_type[index]); - - if (pts_valid) { - hw->last_anch_pts = pts; - hw->last_anch_pts_us64 = pts_us64; - hw->frame_num_since_last_anch = 0; - hw->vop_time_inc_since_last_anch = 0; - } else if (input_stream_based(vdec)) { - pts = hw->last_anch_pts; - pts_us64 = hw->last_anch_pts_us64; - - if ((time_increment_resolution != 0) && - (fixed_vop_rate == 0) && - (hw->vmpeg4_amstream_dec_info.rate == 0)) { - /* variable PTS rate */ - /*bug on variable pts calc, - *do as dixed vop first if we - *have rate setting before. - */ - if (vop_time_inc > hw->last_vop_time_inc) { - duration = vop_time_inc - - hw->last_vop_time_inc; - } else { - duration = vop_time_inc + - time_increment_resolution - - hw->last_vop_time_inc; - } - - hw->vop_time_inc_since_last_anch += duration; - - pts += hw->vop_time_inc_since_last_anch * - PTS_UNIT / time_increment_resolution; - pts_us64 += (hw->vop_time_inc_since_last_anch * - PTS_UNIT / time_increment_resolution) * - 100 / 9; - - if (hw->vop_time_inc_since_last_anch > - (1 << 14)) { - /* avoid overflow */ - hw->last_anch_pts = pts; - hw->last_anch_pts_us64 = pts_us64; - hw->vop_time_inc_since_last_anch = 0; - } - } else { - /* fixed VOP rate */ - hw->frame_num_since_last_anch++; - pts += DUR2PTS(hw->frame_num_since_last_anch * - hw->vmpeg4_amstream_dec_info.rate); - pts_us64 += DUR2PTS( - hw->frame_num_since_last_anch * - hw->vmpeg4_amstream_dec_info.rate) * - 100 / 9; - - if (hw->frame_num_since_last_anch > (1 << 15)) { - /* avoid overflow */ - hw->last_anch_pts = pts; - hw->last_anch_pts_us64 = pts_us64; - hw->frame_num_since_last_anch = 0; - } - } - } - - if (reg & INTERLACE_FLAG) { /* interlace */ - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - vf->index = index; - vf->width = hw->vmpeg4_amstream_dec_info.width; - vf->height = hw->vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = hw->vmpeg4_rotation; - vf->pts = pts; - vf->pts_us64 = pts_us64; - vf->duration = duration >> 1; - vf->duration_pulldown = 0; - vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - set_frame_info(hw, vf, index); - - hw->vfbuf_use[index]++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "pts0=%d,pts64=%lld,w%d,h%d,dur:%d\n", - vf->pts, vf->pts_us64, - vf->width, vf->height, - vf->duration); - if ((hw->first_i_frame_ready == 0) - && (picture_type != I_PICTURE)) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "fatal error, no available buffer slot."); - hw->dec_result = DEC_RESULT_ERROR; - schedule_work(&hw->work); - return IRQ_HANDLED; - } - - vf->index = index; - vf->width = hw->vmpeg4_amstream_dec_info.width; - vf->height = hw->vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = hw->vmpeg4_rotation; - - vf->pts = 0; - vf->pts_us64 = 0; - vf->duration = duration >> 1; - - vf->duration_pulldown = 0; - vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - set_frame_info(hw, vf, index); - - hw->vfbuf_use[index]++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "pts1=%d,pts64=%lld,w%d,h%d,dur:%d\n", - vf->pts, vf->pts_us64, - vf->width, vf->height, - vf->duration); - if ((hw->first_i_frame_ready == 0) - && (picture_type != I_PICTURE)) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - } else { /* progressive */ - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - vf->index = index; - vf->width = hw->vmpeg4_amstream_dec_info.width; - vf->height = hw->vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = hw->vmpeg4_rotation; - vf->pts = pts; - vf->pts_us64 = pts_us64; - vf->duration = duration; - vf->duration_pulldown = repeat_cnt * duration; -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - set_frame_info(hw, vf, index); - - hw->vfbuf_use[index]++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "pts=%d,pts64=%lld,w%d,h%d,index=%d,used=%d,dur:%d, flag=%d, type=%d\n", - vf->pts, vf->pts_us64, - vf->width, vf->height, - index, hw->vfbuf_use[index], - vf->duration, - hw->timeout_flag, picture_type); - if ((hw->first_i_frame_ready == 0) - && (picture_type != I_PICTURE)) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - hw->timeout_flag++; - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - if (hw->timeout_flag > 2) - hw->timeout_flag = 2; - if (hw->timeout_flag && input_frame_based(vdec)) - vf->duration = duration * (hw->timeout_flag + 1); - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - hw->timeout_flag = 0; - vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } - } - - hw->total_frame += repeat_cnt + 1; - hw->last_vop_time_inc = vop_time_inc; - - schedule_work(&hw->work); - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "%s:frame num:%d\n", __func__, hw->frame_num); - - return IRQ_HANDLED; -} - -static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) -{ - u32 time_increment_resolution, fixed_vop_rate; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); - - if (hw->eos) - return IRQ_HANDLED; - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - time_increment_resolution = READ_VREG(MP4_RATE); - fixed_vop_rate = time_increment_resolution >> 16; - time_increment_resolution &= 0xffff; - if (time_increment_resolution > 0 && fixed_vop_rate == 0) - hw->sys_mp4_rate = time_increment_resolution; - if (hw->vmpeg4_amstream_dec_info.rate == 0) { - if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { - hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * - DURATION_UNIT / - time_increment_resolution; - } else if (time_increment_resolution == 0 - && hw->sys_mp4_rate > 0) - time_increment_resolution = hw->sys_mp4_rate; - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "resolution=%d,fvop=%d,rate=%d\n", - time_increment_resolution, fixed_vop_rate, - hw->vmpeg4_amstream_dec_info.rate); - return IRQ_WAKE_THREAD; -} -static void vmpeg4_work(struct work_struct *work) -{ - struct vdec_mpeg4_hw_s *hw = - container_of(work, struct vdec_mpeg4_hw_s, work); - struct vdec_s *vdec = hw_to_vdec(hw); - - /* finished decoding one frame or error, - * notify vdec core to switch context - */ - if (hw->dec_result != DEC_RESULT_DONE) - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "mmpeg4: vmpeg_work,result=%d,status=%d\n", - hw->dec_result, hw_to_vdec(hw)->next_status); - - if ((hw->dec_result == DEC_RESULT_DONE) || - ((hw->chunk) && - (input_frame_based(&(hw_to_vdec(hw))->input)))) { - if (!hw->ctx_valid) - hw->ctx_valid = 1; - - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - } else if (hw->dec_result == DEC_RESULT_AGAIN - && (hw_to_vdec(hw)->next_status != - VDEC_STATUS_DISCONNECTED)) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(hw_to_vdec(hw))) { - hw->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&hw->work); - /*pr_info("%s: return\n", - __func__);*/ - return; - } - } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s: force exit\n", __func__); - if (hw->stat & STAT_ISR_REG) { - amvdec_stop(); - /*disable mbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 0); - vdec_free_irq(VDEC_IRQ_1, (void *)hw); - hw->stat &= ~STAT_ISR_REG; - } - } else if (hw->dec_result == DEC_RESULT_EOS) { - /*pr_info("%s: end of stream\n", - __func__);*/ - hw->eos = 1; - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - hw->chunk = NULL; - vdec_clean_input(hw_to_vdec(hw)); - } - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - - /* mark itself has all HW resource released and input released */ - if (vdec->parallel_dec == 1) - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); - else - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - if (hw->vdec_cb) - hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); -} - -static struct vframe_s *vmpeg_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - - if (!hw) - return NULL; - hw->peek_num++; - if (kfifo_peek(&hw->display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vmpeg_vf_get(void *op_arg) -{ - struct vframe_s *vf; - struct vdec_s *vdec = op_arg; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - hw->get_num++; - if (kfifo_get(&hw->display_q, &vf)) - return vf; - - return NULL; -} - -static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct vdec_s *vdec = op_arg; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - - hw->vfbuf_use[vf->index]--; - hw->put_num++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "%s:put num:%d\n", - __func__, hw->put_num); - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, - "index=%d, used=%d\n", - vf->index, hw->vfbuf_use[vf->index]); - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); -} - -static int vmpeg_event_cb(int type, void *data, void *private_data) -{ - return 0; -} - -static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - struct vdec_s *vdec = op_arg; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - - spin_lock_irqsave(&hw->lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&hw->newframe_q); - states->buf_avail_num = kfifo_len(&hw->display_q); - states->buf_recycle_num = 0; - - spin_unlock_irqrestore(&hw->lock, flags); - - return 0; -} - - -static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - - if (!hw) - return -1; - - vstatus->frame_width = hw->vmpeg4_amstream_dec_info.width; - vstatus->frame_height = hw->vmpeg4_amstream_dec_info.height; - if (0 != hw->vmpeg4_amstream_dec_info.rate) - vstatus->frame_rate = DURATION_UNIT / - hw->vmpeg4_amstream_dec_info.rate; - else - vstatus->frame_rate = DURATION_UNIT; - vstatus->error_count = READ_VREG(MP4_ERR_COUNT); - vstatus->status = hw->stat; - - return 0; -} - -/****************************************/ -static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 decbuf_size, decbuf_y_size; - struct vdec_s *vdec = hw_to_vdec(hw); - unsigned long decbuf_start; - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_size = 0x100000; - } else { - int w = hw->vmpeg4_amstream_dec_info.width; - int h = hw->vmpeg4_amstream_dec_info.height; - int align_w, align_h; - int max, min; - if (w == 0) - w = 1920; - if (h == 0) - h = 1088; - align_w = ALIGN(w, 64); - align_h = ALIGN(h, 64); - if (align_w > align_h) { - max = align_w; - min = align_h; - } else { - max = align_h; - min = align_w; - } - /* HD & SD */ - if ((max > 1920 || min > 1088) && - ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= - buf_size) { - canvas_width = align_w; - canvas_height = align_h; - decbuf_y_size = - ALIGN(align_w * align_h, SZ_64K); - decbuf_size = - ALIGN(align_w * align_h * 3/2, SZ_64K); - } else { /*1080p*/ - if (h > w) { - canvas_width = 1088; - canvas_height = 1920; - } else { - canvas_width = 1920; - canvas_height = 1088; - } - decbuf_y_size = 0x200000; - decbuf_size = 0x300000; - } - } - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - - unsigned canvas; - if (i == (MAX_BMMU_BUFFER_NUM - 1)) - decbuf_size = WORKSPACE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &decbuf_start); - if (ret < 0) { - pr_err("mmu alloc failed! size 0x%d idx %d\n", - decbuf_size, i); - return ret; - } - - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { - hw->buf_start = decbuf_start; - } else { - if (vdec->parallel_dec == 1) { - unsigned tmp; - if (canvas_u(hw->canvas_spec[i]) == 0xff) { - tmp = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->canvas_spec[i] &= ~(0xffff << 8); - hw->canvas_spec[i] |= tmp << 8; - hw->canvas_spec[i] |= tmp << 16; - } - if (canvas_y(hw->canvas_spec[i]) == 0xff) { - tmp = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->canvas_spec[i] &= ~0xff; - hw->canvas_spec[i] |= tmp; - } - canvas = hw->canvas_spec[i]; - } else { - canvas = vdec->get_canvas(i, 2); - hw->canvas_spec[i] = canvas; - } - - hw->canvas_config[i][0].phy_addr = - decbuf_start; - hw->canvas_config[i][0].width = - canvas_width; - hw->canvas_config[i][0].height = - canvas_height; - hw->canvas_config[i][0].block_mode = - CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_y(canvas), - &hw->canvas_config[i][0]); - - hw->canvas_config[i][1].phy_addr = - decbuf_start + decbuf_y_size; - hw->canvas_config[i][1].width = - canvas_width; - hw->canvas_config[i][1].height = - canvas_height / 2; - hw->canvas_config[i][1].block_mode = - CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_u(canvas), - &hw->canvas_config[i][1]); - } - } - - return 0; -} -static void vmpeg4_dump_state(struct vdec_s *vdec) -{ - struct vdec_mpeg4_hw_s *hw = - (struct vdec_mpeg4_hw_s *)(vdec->private); - u32 i; - mmpeg4_debug_print(DECODE_ID(hw), 0, - "====== %s\n", __func__); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "width/height (%d/%d), i_fram:%d, buffer_not_ready %d\n", - hw->vmpeg4_amstream_dec_info.width, - hw->vmpeg4_amstream_dec_info.height, - hw->first_i_frame_ready, - hw->buffer_not_ready - ); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "index %d, used %d\n", i, hw->vfbuf_use[i]); - } - - mmpeg4_debug_print(DECODE_ID(hw), 0, - "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d\n", - input_frame_based(vdec), - hw->eos, - hw->stat, - hw->dec_result, - hw->frame_num - ); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "is_framebase(%d), put_frm %d run %d not_run_ready %d input_empty %d,drop %d\n", - input_frame_based(vdec), - hw->put_num, - hw->run_count, - hw->not_run_ready, - hw->input_empty, - hw->drop_frame_count - ); - - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - mmpeg4_debug_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", - __func__, - kfifo_len(&hw->newframe_q), - VF_POOL_SIZE, - kfifo_len(&hw->display_q), - VF_POOL_SIZE, - hw->peek_num, - hw->get_num, - hw->put_num - ); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "VIFF_BIT_CNT=0x%x\n", - READ_VREG(VIFF_BIT_CNT)); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_LEVEL=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_LEVEL)); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_WP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_WP)); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "VLD_MEM_VIFIFO_RP=0x%x\n", - READ_VREG(VLD_MEM_VIFIFO_RP)); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - mmpeg4_debug_print(DECODE_ID(hw), 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - if (input_frame_based(vdec) && - debug_enable & PRINT_FRAMEBASE_DATA - ) { - int jj; - if (hw->chunk && hw->chunk->block && - hw->chunk->size > 0) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, hw->chunk->size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - mmpeg4_debug_print(DECODE_ID(hw), 0, - "frame data size 0x%x\n", - hw->chunk->size); - for (jj = 0; jj < hw->chunk->size; jj++) { - if ((jj & 0xf) == 0) - mmpeg4_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - mmpeg4_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - mmpeg4_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } -} - -static void reset_process_time(struct vdec_mpeg4_hw_s *hw) -{ - if (hw->start_process_time) { - unsigned process_time = - 1000 * (jiffies - hw->start_process_time) / HZ; - hw->start_process_time = 0; - if (process_time > max_process_time[DECODE_ID(hw)]) - max_process_time[DECODE_ID(hw)] = process_time; - } -} -static void start_process_time(struct vdec_mpeg4_hw_s *hw) -{ - hw->decode_timeout_count = 2; - hw->start_process_time = jiffies; -} - -static void timeout_process(struct vdec_mpeg4_hw_s *hw) -{ - if (hw->stat & STAT_VDEC_RUN) { - amvdec_stop(); - hw->stat &= ~STAT_VDEC_RUN; - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEOUT_STATUS, - "%s decoder timeout\n", __func__); - reset_process_time(hw); - hw->first_i_frame_ready = 0; - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); -} - - -static void check_timer_func(unsigned long arg) -{ - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)arg; - struct vdec_s *vdec = hw_to_vdec(hw); - unsigned int timeout_val = decode_timeout_val; - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - - if (debug_enable == 0 && - (input_frame_based(vdec) || - (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && - (timeout_val > 0) && - (hw->start_process_time > 0) && - ((1000 * (jiffies - hw->start_process_time) / HZ) - > timeout_val)) { - if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); - } - hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); - } - - if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "vdec requested to be disconnected\n"); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; - } - - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -} - -static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) -{ - int index; - - - index = find_buffer(hw); - if (index < 0) - return -1; - - - if (vmpeg4_canvas_init(hw) < 0) - return -1; - - /* prepare REF0 & REF1 - * points to the past two IP buffers - * prepare REC_CANVAS_ADDR and ANC2_CANVAS_ADDR - * points to the output buffer - */ - if (hw->refs[0] == -1) { - WRITE_VREG(MREG_REF0, (hw->refs[1] == -1) ? 0xffffffff : - hw->canvas_spec[hw->refs[1]]); - } else { - WRITE_VREG(MREG_REF0, (hw->refs[0] == -1) ? 0xffffffff : - hw->canvas_spec[hw->refs[0]]); - } - WRITE_VREG(MREG_REF1, (hw->refs[1] == -1) ? 0xffffffff : - hw->canvas_spec[hw->refs[1]]); - - WRITE_VREG(MREG_REF0, (hw->refs[0] == -1) ? 0xffffffff : - hw->canvas_spec[hw->refs[0]]); - WRITE_VREG(MREG_REF1, (hw->refs[1] == -1) ? 0xffffffff : - hw->canvas_spec[hw->refs[1]]); - WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); - WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); - - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, - "restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d,index=%d\n", - READ_VREG(MREG_REF0), - READ_VREG(MREG_REF1), - READ_VREG(REC_CANVAS_ADDR), - hw->ctx_valid, index); - - /* notify ucode the buffer start address */ - WRITE_VREG(MEM_OFFSET_REG, hw->buf_start); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - WRITE_VREG(MREG_BUFFEROUT, 0); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - - /* clear repeat count */ - WRITE_VREG(MP4_NOT_CODED_CNT, 0); - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - -#if 1/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); -#endif - - WRITE_VREG(MP4_PIC_WH, (hw->ctx_valid) ? - hw->reg_mp4_pic_wh : - ((hw->vmpeg4_amstream_dec_info.width << 16) | - hw->vmpeg4_amstream_dec_info.height)); - WRITE_VREG(MP4_SYS_RATE, hw->vmpeg4_amstream_dec_info.rate); - - if (hw->ctx_valid) { - WRITE_VREG(DC_AC_CTRL, hw->reg_dc_ac_ctrl); - WRITE_VREG(IQIDCT_CONTROL, hw->reg_iqidct_control); - WRITE_VREG(RESYNC_MARKER_LENGTH, hw->reg_resync_marker_length); - WRITE_VREG(RV_AI_MB_COUNT, hw->reg_rv_ai_mb_count); - } - WRITE_VREG(MPEG1_2_REG, (hw->ctx_valid) ? hw->reg_mpeg1_2_reg : 1); - WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg); - WRITE_VREG(PIC_HEAD_INFO, hw->reg_pic_head_info); - WRITE_VREG(SLICE_QP, hw->reg_slice_qp); - WRITE_VREG(MB_INFO, hw->reg_mb_info); - - if (hw->chunk) { - /* frame based input */ - WRITE_VREG(MREG_INPUT, (hw->chunk->offset & 7) | (1<<7) | - (hw->ctx_valid<<6)); - } else { - /* stream based input */ - WRITE_VREG(MREG_INPUT, (hw->ctx_valid<<6)); - } - - return 0; -} - -static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) -{ - int i; - - hw->vmpeg4_ratio = hw->vmpeg4_amstream_dec_info.ratio; - - hw->vmpeg4_ratio64 = hw->vmpeg4_amstream_dec_info.ratio64; - - hw->vmpeg4_rotation = - (((unsigned long) hw->vmpeg4_amstream_dec_info.param) - >> 16) & 0xffff; - hw->sys_mp4_rate = hw->vmpeg4_amstream_dec_info.rate; - hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0; - - hw->total_frame = 0; - - hw->last_anch_pts = 0; - - hw->last_anch_pts_us64 = 0; - - hw->last_vop_time_inc = hw->last_duration = 0; - - hw->vop_time_inc_since_last_anch = 0; - - hw->frame_num_since_last_anch = 0; - hw->frame_num = 0; - hw->put_num = 0; - hw->run_count = 0; - hw->not_run_ready = 0; - hw->input_empty = 0; - hw->peek_num = 0; - hw->get_num = 0; - - hw->pts_hit = hw->pts_missed = hw->pts_i_hit = hw->pts_i_missed = 0; - hw->refs[0] = -1; - hw->refs[1] = -1; - hw->first_i_frame_ready = 0; - hw->drop_frame_count = 0; - hw->buffer_not_ready = 0; - hw->timeout_flag = 0; - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - hw->vfbuf_use[i] = 0; - - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &hw->vfpool[i]; - - hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); - } - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - hw->mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - INIT_WORK(&hw->work, vmpeg4_work); -} - -static s32 vmmpeg4_init(struct vdec_mpeg4_hw_s *hw) -{ - int trickmode_fffb = 0; - int size = -1, fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - if (hw->vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_5) { - size = get_firmware_data(VIDEO_DEC_MPEG4_5_MULTI, fw->data); - strncpy(fw->name, "mmpeg4_mc_5", sizeof(fw->name)); - } else if (hw->vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_H263) { - size = get_firmware_data(VIDEO_DEC_H263_MULTI, fw->data); - strncpy(fw->name, "mh263_mc", sizeof(fw->name)); - } else - pr_err("unsupport mpeg4 sub format %d\n", - hw->vmpeg4_amstream_dec_info.format); - pr_info("mmpeg4 get fw %s, size %x\n", fw->name, size); - if (size < 0) { - pr_err("get firmware failed."); - vfree(fw); - return -1; - } - - fw->len = size; - hw->fw = fw; - - query_video_status(0, &trickmode_fffb); - - pr_info("%s\n", __func__); - - amvdec_enable(); - - init_timer(&hw->check_timer); - hw->check_timer.data = (unsigned long)hw; - hw->check_timer.function = check_timer_func; - hw->check_timer.expires = jiffies + CHECK_INTERVAL; - hw->stat |= STAT_TIMER_ARM; - hw->eos = 0; - WRITE_VREG(DECODE_STOP_POS, udebug_flag); - - vmpeg4_local_init(hw); - wmb(); - - return 0; -} - -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) -{ - int index; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - if (hw->eos) - return 0; - if (vdec_stream_based(vdec) && (hw->init_flag == 0) - && pre_decode_buf_level != 0) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = vdec->input.size + wp - rp; - else - level = wp - rp; - if (level < pre_decode_buf_level) { - hw->not_run_ready++; - return 0; - } - } - - index = find_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) { - hw->buffer_not_ready++; - return 0; - } - hw->not_run_ready = 0; - hw->buffer_not_ready = 0; - if (vdec->parallel_dec == 1) - return (unsigned long)(CORE_MASK_VDEC_1); - else - return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); -} - -static unsigned char get_data_check_sum - (struct vdec_mpeg4_hw_s *hw, int size) -{ - int jj; - int sum = 0; - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - for (jj = 0; jj < size; jj++) - sum += data[jj]; - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - return sum; -} - -static void run(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *arg) -{ - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - int save_reg = READ_VREG(POWER_CTL_VLD); - int size, ret = 0; - - hw->run_count++; - /* reset everything except DOS_TOP[1] and APB_CBUS[0] */ - WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); - WRITE_VREG(DOS_SW_RESET0, 0); - WRITE_VREG(POWER_CTL_VLD, save_reg); - - hw->vdec_cb_arg = arg; - hw->vdec_cb = callback; - vdec_reset_core(vdec); - size = vdec_prepare_input(vdec, &hw->chunk); - if (size < 0) { - hw->input_empty++; - hw->dec_result = DEC_RESULT_AGAIN; - schedule_work(&hw->work); - return; - } - - if (input_frame_based(vdec)) { - u8 *data = NULL; - - if (!hw->chunk->block->is_mapped) - data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, size); - else - data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; - - if (debug_enable & PRINT_FLAG_VDEC_STATUS - ) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", - __func__, size, get_data_check_sum(hw, size), - data[0], data[1], data[2], data[3], - data[4], data[5], data[size - 4], - data[size - 3], data[size - 2], - data[size - 1]); - } - if (debug_enable & PRINT_FRAMEBASE_DATA - ) { - int jj; - - for (jj = 0; jj < size; jj++) { - if ((jj & 0xf) == 0) - mmpeg4_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%06x:", jj); - mmpeg4_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - mmpeg4_debug_print(DECODE_ID(hw), - PRINT_FRAMEBASE_DATA, - "\n"); - } - } - - if (!hw->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } else - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: %x %x %x %x %x size 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP), - size); - - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s,%d, size=%d, %x %x %x %x %x\n", - __func__, __LINE__, size, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP)); - - hw->dec_result = DEC_RESULT_NONE; - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - } else { - ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG4,hw->fw->name, vdec, - hw->fw->data, hw->fw->len); - if (ret < 0) { - pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, - hw->fw->name, tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - schedule_work(&hw->work); - return; - } - vdec->mc_loaded = 1; - vdec->mc_type = VFORMAT_MPEG4; - } - if (vmpeg4_hw_ctx_restore(hw) < 0) { - hw->dec_result = DEC_RESULT_ERROR; - mmpeg4_debug_print(DECODE_ID(hw), 0, - "amvdec_mpeg4: error HW context restore\n"); - schedule_work(&hw->work); - return; - } - hw->input_empty = 0; - hw->last_vld_level = 0; - start_process_time(hw); - vdec_enable_input(vdec); - /* wmb before ISR is handled */ - wmb(); - - amvdec_start(); - hw->stat |= STAT_VDEC_RUN; - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); -} - -static int vmpeg4_stop(struct vdec_mpeg4_hw_s *hw) -{ - cancel_work_sync(&hw->work); - - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - - if (hw->fw) { - vfree(hw->fw); - hw->fw = NULL; - } - return 0; -} -static void reset(struct vdec_s *vdec) -{ - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - - pr_info("amvdec_mmpeg4: reset.\n"); - - vmpeg4_local_init(hw); - - hw->ctx_valid = false; -} - -static int ammvdec_mpeg4_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct vdec_mpeg4_hw_s *hw = NULL; - - pr_info("%s [%d] probe start.\n", __func__, pdev->id); - - if (pdata == NULL) { - pr_err("%s memory resource undefined.\n", __func__); - return -EFAULT; - } - - hw = vmalloc(sizeof(struct vdec_mpeg4_hw_s)); - if (hw == NULL) { - pr_err("\namvdec_mpeg4 decoder driver alloc failed\n"); - return -ENOMEM; - } - memset(hw, 0, sizeof(struct vdec_mpeg4_hw_s)); - - pdata->private = hw; - pdata->dec_status = dec_status; - /* pdata->set_trickmode = set_trickmode; */ - pdata->run_ready = run_ready; - pdata->run = run; - pdata->reset = reset; - pdata->irq_handler = vmpeg4_isr; - pdata->threaded_irq_handler = vmpeg4_isr_thread_fn; - pdata->dump_state = vmpeg4_dump_state; - - if (pdata->use_vfm_path) - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - PROVIDER_NAME ".%02x", pdev->id & 0xff); - - if (pdata->parallel_dec == 1) { - int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - hw->canvas_spec[i] = 0xffffff; - } - - vf_provider_init(&pdata->vframe_provider, - pdata->vf_provider_name, &vf_provider_ops, pdata); - - platform_set_drvdata(pdev, pdata); - hw->platform_dev = pdev; - -/* - hw->cma_dev = pdata->cma_dev; - hw->cma_alloc_count = PAGE_ALIGN(DEFAULT_MEM_SIZE) / PAGE_SIZE; - hw->cma_alloc_addr = codec_mm_alloc_for_dma(MEM_NAME, - hw->cma_alloc_count, - 4, CODEC_MM_FLAGS_FOR_VDECODER); - - if (!hw->cma_alloc_addr) { - pr_err("codec_mm alloc failed, request buf size 0x%lx\n", - hw->cma_alloc_count * PAGE_SIZE); - hw->cma_alloc_count = 0; - if (hw) { - vfree((void *)hw); - hw = NULL; - } - return -ENOMEM; - } - hw->buf_start = hw->cma_alloc_addr; - hw->buf_size = DEFAULT_MEM_SIZE; -*/ - if (pdata->sys_info) { - hw->vmpeg4_amstream_dec_info = *pdata->sys_info; - if ((hw->vmpeg4_amstream_dec_info.height != 0) && - (hw->vmpeg4_amstream_dec_info.width > - (MAX_MPEG4_SUPPORT_SIZE/hw->vmpeg4_amstream_dec_info.height))) { - pr_info("ammvdec_mpeg4: oversize, unsupport: %d*%d\n", - hw->vmpeg4_amstream_dec_info.width, - hw->vmpeg4_amstream_dec_info.height); - pdata->dec_status = NULL; - vfree((void *)hw); - hw = NULL; - return -EFAULT; - } - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "W:%d,H:%d,rate=%d\n", - hw->vmpeg4_amstream_dec_info.width, - hw->vmpeg4_amstream_dec_info.height, - hw->vmpeg4_amstream_dec_info.rate); - hw->vmpeg4_amstream_dec_info.height = 0; - hw->vmpeg4_amstream_dec_info.width = 0; - - if (vmmpeg4_init(hw) < 0) { - pr_err("%s init failed.\n", __func__); -/* - if (hw->cma_alloc_addr) { - codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); - hw->cma_alloc_count = 0; - } -*/ - if (hw) { - vfree((void *)hw); - hw = NULL; - } - pdata->dec_status = NULL; - return -ENODEV; - } - if (pdata->parallel_dec == 1) - vdec_core_request(pdata, CORE_MASK_VDEC_1); - else { - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); - } - - return 0; -} - -static int ammvdec_mpeg4_remove(struct platform_device *pdev) -{ - struct vdec_mpeg4_hw_s *hw = - (struct vdec_mpeg4_hw_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - struct vdec_s *vdec = hw_to_vdec(hw); - int i; - - vmpeg4_stop(hw); - /* - if (hw->cma_alloc_addr) { - pr_info("codec_mm release buffer 0x%lx\n", hw->cma_alloc_addr); - codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); - hw->cma_alloc_count = 0; - } - */ - if (vdec->parallel_dec == 1) - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); - else - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - - if (vdec->parallel_dec == 1) { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); - vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); - } - } - - pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, - hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); - pr_info("total frame %d, rate %d\n", hw->total_frame, - hw->vmpeg4_amstream_dec_info.rate); - vfree((void *)hw); - hw = NULL; - - return 0; -} - -/****************************************/ - -static struct platform_driver ammvdec_mpeg4_driver = { - .probe = ammvdec_mpeg4_probe, - .remove = ammvdec_mpeg4_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_mpeg4_profile = { - .name = "mmpeg4", - .profile = "" -}; - -static int __init ammvdec_mpeg4_driver_init_module(void) -{ - pr_info("%s \n", __func__); - - if (platform_driver_register(&ammvdec_mpeg4_driver)) { - pr_err("failed to register ammvdec_mpeg4 driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvdec_mpeg4_profile); - return 0; -} - -static void __exit ammvdec_mpeg4_driver_remove_module(void) -{ - pr_info("ammvdec_mpeg4 module remove.\n"); - - platform_driver_unregister(&ammvdec_mpeg4_driver); -} - -/****************************************/ -module_param(debug_enable, uint, 0664); -MODULE_PARM_DESC(debug_enable, - "\n ammvdec_mpeg4 debug enable\n"); - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\nradr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\nrval\n"); - -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg4 decode_timeout_val\n"); - -module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); - -module_param(pre_decode_buf_level, int, 0664); -MODULE_PARM_DESC(pre_decode_buf_level, - "\n ammvdec_ mpeg4 pre_decode_buf_level\n"); - -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg4 udebug_flag\n"); -module_init(ammvdec_mpeg4_driver_init_module); -module_exit(ammvdec_mpeg4_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC MPEG4 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/real/Makefile deleted file mode 100644 index ab03ef29f11b..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/real/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_REAL) += amvdec_real.o -amvdec_real-objs += vreal.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c deleted file mode 100644 index afce94eee6bf..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * drivers/amlogic/amports/vreal.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../utils/vdec.h" -#include -#include "../utils/amvdec.h" - -#include "../../../stream_input/parser/streambuf.h" -#include "../../../stream_input/parser/streambuf_reg.h" -#include "../../../stream_input/parser/rmparser.h" - -#include "vreal.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include "../utils/firmware.h" -#include - -#include - - -#define DRIVER_NAME "amvdec_real" -#define MODULE_NAME "amvdec_real" - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -#endif - -#define RM_DEF_BUFFER_ADDR 0x01000000 -/* protocol registers */ -#define STATUS_AMRISC AV_SCRATCH_4 - -#define RV_PIC_INFO AV_SCRATCH_5 -#define VPTS_TR AV_SCRATCH_6 -#define VDTS AV_SCRATCH_7 -#define FROM_AMRISC AV_SCRATCH_8 -#define TO_AMRISC AV_SCRATCH_9 -#define SKIP_B_AMRISC AV_SCRATCH_A -#define INT_REASON AV_SCRATCH_B -#define WAIT_BUFFER AV_SCRATCH_E - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define MDEC_WIDTH AV_SCRATCH_I -#define MDEC_HEIGHT AV_SCRATCH_J -#else -#define MDEC_WIDTH HARM_ASB_MB2 -#define MDEC_HEIGHT HASB_ARM_MB0 -#endif - -#define PARC_FORBIDDEN 0 -#define PARC_SQUARE 1 -#define PARC_CIF 2 -#define PARC_10_11 3 -#define PARC_16_11 4 -#define PARC_40_33 5 -#define PARC_RESERVED 6 -/* values between 6 and 14 are reserved */ -#define PARC_EXTENDED 15 - -#define VF_POOL_SIZE 16 -#define VF_BUF_NUM 4 -#define PUT_INTERVAL (HZ/100) -#define WORKSPACE_SIZE (1 * SZ_1M) -#define MAX_BMMU_BUFFER_NUM (VF_BUF_NUM + 1) -#define RV_AI_BUFF_START_IP 0x01f00000 - -static struct vframe_s *vreal_vf_peek(void *); -static struct vframe_s *vreal_vf_get(void *); -static void vreal_vf_put(struct vframe_s *, void *); -static int vreal_vf_states(struct vframe_states *states, void *); -static int vreal_event_cb(int type, void *data, void *private_data); - -static int vreal_prot_init(void); -static void vreal_local_init(void); - -static const char vreal_dec_id[] = "vreal-dev"; - -#define PROVIDER_NAME "decoder.real" - -/* - *int query_video_status(int type, int *value); - */ -static const struct vframe_operations_s vreal_vf_provider = { - .peek = vreal_vf_peek, - .get = vreal_vf_get, - .put = vreal_vf_put, - .event_cb = vreal_event_cb, - .vf_states = vreal_vf_states, -}; - -static struct vframe_provider_s vreal_vf_prov; -static void *mm_blk_handle; - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static struct vframe_s vfpool[VF_POOL_SIZE]; -static s32 vfbuf_use[VF_BUF_NUM]; - -static u32 frame_width, frame_height, frame_dur, frame_prog; -static u32 saved_resolution; -static struct timer_list recycle_timer; -static u32 stat; -static u32 buf_size = 32 * 1024 * 1024; -static u32 buf_offset; -static u32 vreal_ratio; -u32 vreal_format; -static u32 wait_key_frame; -static u32 last_tr; -static u32 frame_count; -static u32 current_vdts; -static u32 hold; -static u32 decoder_state; -static u32 real_err_count; - -static u32 fatal_flag; -static s32 wait_buffer_counter; -static struct work_struct set_clk_work; -static bool is_reset; - -static DEFINE_SPINLOCK(lock); - -static unsigned short pic_sz_tbl[12] ____cacheline_aligned; -static dma_addr_t pic_sz_tbl_map; -static const unsigned char RPR_size[9] = { 0, 1, 1, 2, 2, 3, 3, 3, 3 }; - -static struct dec_sysinfo vreal_amstream_dec_info; - -static unsigned char aspect_ratio_table[16] = { - PARC_FORBIDDEN, - PARC_SQUARE, - PARC_CIF, - PARC_10_11, - PARC_16_11, - PARC_40_33, - PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, - PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, - PARC_RESERVED, PARC_EXTENDED -}; - -static inline u32 index2canvas(u32 index) -{ - const u32 canvas_tab[4] = { -#ifdef NV21 - 0x010100, 0x030302, 0x050504, 0x070706 -#else - 0x020100, 0x050403, 0x080706, 0x0b0a09 -#endif - }; - - return canvas_tab[index]; -} - -static void set_aspect_ratio(struct vframe_s *vf, unsigned int pixel_ratio) -{ - int ar = 0; - - if (vreal_ratio == 0) { - vf->ratio_control |= (0x90 << - DISP_RATIO_ASPECT_RATIO_BIT); - /* always stretch to 16:9 */ - } else { - switch (aspect_ratio_table[pixel_ratio]) { - case 0: - ar = vreal_amstream_dec_info.height * vreal_ratio / - vreal_amstream_dec_info.width; - break; - case 1: - case 0xff: - ar = vreal_ratio * vf->height / vf->width; - break; - case 2: - ar = (vreal_ratio * vf->height * 12) / (vf->width * 11); - break; - case 3: - ar = (vreal_ratio * vf->height * 11) / (vf->width * 10); - break; - case 4: - ar = (vreal_ratio * vf->height * 11) / (vf->width * 16); - break; - case 5: - ar = (vreal_ratio * vf->height * 33) / (vf->width * 40); - break; - default: - ar = vreal_ratio * vf->height / vf->width; - break; - } - } - - ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); - - vf->ratio_control |= (ar << DISP_RATIO_ASPECT_RATIO_BIT); -} - -static irqreturn_t vreal_isr(int irq, void *dev_id) -{ - u32 from; - struct vframe_s *vf = NULL; - u32 buffer_index; - unsigned int status; - unsigned int vdts; - unsigned int info; - unsigned int tr; - unsigned int pictype; - u32 r = READ_VREG(INT_REASON); - - if (decoder_state == 0) - return IRQ_HANDLED; - - status = READ_VREG(STATUS_AMRISC); - if (status & (PARSER_ERROR_WRONG_PACKAGE_SIZE | - PARSER_ERROR_WRONG_HEAD_VER | - DECODER_ERROR_VLC_DECODE_TBL)) { - /* decoder or parser error */ - real_err_count++; - /* pr_info("real decoder or parser - *error, status 0x%x\n", status); - */ - } - - if (r == 2) { - pr_info("first vpts = 0x%x\n", READ_VREG(VDTS)); - pts_checkin_offset(PTS_TYPE_AUDIO, 0, READ_VREG(VDTS) * 90); - WRITE_VREG(AV_SCRATCH_B, 0); - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - return IRQ_HANDLED; - } else if (r == 3) { - pr_info("first apts = 0x%x\n", READ_VREG(VDTS)); - pts_checkin_offset(PTS_TYPE_VIDEO, 0, READ_VREG(VDTS) * 90); - WRITE_VREG(AV_SCRATCH_B, 0); - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - return IRQ_HANDLED; - } - - from = READ_VREG(FROM_AMRISC); - if ((hold == 0) && from) { - tr = READ_VREG(VPTS_TR); - pictype = (tr >> 13) & 3; - tr = (tr & 0x1fff) * 96; - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - vdts = READ_VREG(VDTS); - if (last_tr == -1) /* ignore tr for first time */ - vf->duration = frame_dur; - else { - if (tr > last_tr) - vf->duration = tr - last_tr; - else - vf->duration = (96 << 13) + tr - last_tr; - - if (vf->duration > 10 * frame_dur) { - /* not a reasonable duration, - *should not happen - */ - vf->duration = frame_dur; - } -#if 0 - else { - if (check_frame_duration == 0) { - frame_dur = vf->duration; - check_frame_duration = 1; - } - } -#endif - } - - last_tr = tr; - buffer_index = from & 0x03; - - if (pictype == 0) { /* I */ - current_vdts = vdts * 90 + 1; - vf->pts = current_vdts; - if (wait_key_frame) - wait_key_frame = 0; - } else { - if (wait_key_frame) { - while (READ_VREG(TO_AMRISC)) - ; - WRITE_VREG(TO_AMRISC, ~(1 << buffer_index)); - WRITE_VREG(FROM_AMRISC, 0); - return IRQ_HANDLED; - } else { - current_vdts += - vf->duration - (vf->duration >> 4); - vf->pts = current_vdts; - } - } - - /* pr_info("pts %d, picture type %d\n", vf->pts, pictype); */ - - info = READ_VREG(RV_PIC_INFO); - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = info >> 16; - vf->height = (info >> 4) & 0xfff; - vf->bufWidth = 1920; - vf->flag = 0; - vf->ratio_control = 0; - set_aspect_ratio(vf, info & 0x0f); - vf->duration_pulldown = 0; -#ifdef NV21 - vf->type = VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - vf->canvas0Addr = vf->canvas1Addr = index2canvas(buffer_index); - vf->orientation = 0; - vf->type_original = vf->type; - - vfbuf_use[buffer_index] = 1; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - frame_count++; - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - WRITE_VREG(FROM_AMRISC, 0); - } - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - return IRQ_HANDLED; -} - -static struct vframe_s *vreal_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vreal_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vreal_vf_put(struct vframe_s *vf, void *op_arg) -{ - kfifo_put(&recycle_q, (const struct vframe_s *)vf); -} - -static int vreal_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vreal_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vreal_local_init(); - vreal_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vreal_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -static int vreal_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - - return 0; -} -#if 0 -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER -static void vreal_ppmgr_reset(void) -{ - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); - - vreal_local_init(); - - pr_info("vrealdec: vf_ppmgr_reset\n"); -} -#endif -#endif - -static void vreal_set_clk(struct work_struct *work) -{ - if (frame_dur > 0 && - saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_REAL, - frame_width, frame_height, fps); - } -} - -static void vreal_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - /* unsigned int status; */ - -#if 0 - enum receviver_start_e state = RECEIVER_INACTIVE; - - if (vf_get_receiver(PROVIDER_NAME)) { - state = - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) { - /* receiver has no event_cb - *or receiver's event_cb does not process this event - */ - state = RECEIVER_INACTIVE; - } - } else - state = RECEIVER_INACTIVE; - - if ((READ_VREG(WAIT_BUFFER) != 0) && - kfifo_is_empty(&display_q) && - kfifo_is_empty(&recycle_q) && (state == RECEIVER_INACTIVE)) { - pr_info("$$$$$$decoder is waiting for buffer\n"); - if (++wait_buffer_counter > 2) { - amvdec_stop(); - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vreal_ppmgr_reset(); -#else - vf_light_unreg_provider(&vreal_vf_prov); - vreal_local_init(); - vf_reg_provider(&vreal_vf_prov); -#endif - vreal_prot_init(); - amvdec_start(); - } - } -#endif - - while (!kfifo_is_empty(&recycle_q) && (READ_VREG(TO_AMRISC) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < VF_BUF_NUM) - && (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(TO_AMRISC, ~(1 << vf->index)); - vf->index = VF_BUF_NUM; - } - - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - } - - schedule_work(&set_clk_work); - - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -int vreal_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = vreal_amstream_dec_info.width; - vstatus->frame_height = vreal_amstream_dec_info.height; - if (0 != vreal_amstream_dec_info.rate) - vstatus->frame_rate = 96000 / vreal_amstream_dec_info.rate; - else - vstatus->frame_rate = 96000; - vstatus->error_count = real_err_count; - vstatus->status = - ((READ_VREG(STATUS_AMRISC) << 16) | fatal_flag) | stat; - /* pr_info("vreal_dec_status 0x%x\n", vstatus->status); */ - return 0; -} - -int vreal_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -/****************************************/ -static int vreal_canvas_init(void) -{ - int i, ret; - unsigned long buf_start; - u32 canvas_width, canvas_height; - u32 alloc_size, decbuf_size, decbuf_y_size, decbuf_uv_size; - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - /* HD & SD */ - #if 1 - int w = vreal_amstream_dec_info.width; - int h = vreal_amstream_dec_info.height; - int align_w, align_h; - int max, min; - - align_w = ALIGN(w, 64); - align_h = ALIGN(h, 64); - if (align_w > align_h) { - max = align_w; - min = align_h; - } else { - canvas_width = 1920; - canvas_height = 1088; - max = align_h; - min = align_w; - } - /* HD & SD */ - if ((max > 1920 || min > 1088) && - ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= - buf_size) { - canvas_width = align_w; - canvas_height = align_h; - decbuf_y_size = ALIGN(align_w * align_h, SZ_64K); - decbuf_uv_size = ALIGN(align_w * align_h/4, SZ_64K); - decbuf_size = ALIGN(align_w * align_h * 3/2, SZ_64K); - } else { /*1080p*/ - if (h > w) { - canvas_width = 1088; - canvas_height = 1920; - } else { - canvas_width = 1920; - canvas_height = 1088; - } - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - #endif - } - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - /* workspace mem */ - if (i == (MAX_BMMU_BUFFER_NUM - 1)) - alloc_size = WORKSPACE_SIZE; - else - alloc_size = decbuf_size; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, - alloc_size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; - - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { - buf_offset = buf_start - RV_AI_BUFF_START_IP; - continue; - } - -#ifdef NV21 - canvas_config(2 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(2 * i + 1, - buf_start + - decbuf_y_size, canvas_width, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); -#else - canvas_config(3 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 1, - buf_start + - decbuf_y_size, canvas_width / 2, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 2, - buf_start + - decbuf_y_size + decbuf_uv_size, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); -#endif - } - - return 0; -} - -static int vreal_prot_init(void) -{ - int r; -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); -#endif - - - - r = vreal_canvas_init(); - - /* index v << 16 | u << 8 | y */ -#ifdef NV21 - WRITE_VREG(AV_SCRATCH_0, 0x010100); - WRITE_VREG(AV_SCRATCH_1, 0x030302); - WRITE_VREG(AV_SCRATCH_2, 0x050504); - WRITE_VREG(AV_SCRATCH_3, 0x070706); -#else - WRITE_VREG(AV_SCRATCH_0, 0x020100); - WRITE_VREG(AV_SCRATCH_1, 0x050403); - WRITE_VREG(AV_SCRATCH_2, 0x080706); - WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); -#endif - - /* notify ucode the buffer offset */ - WRITE_VREG(AV_SCRATCH_F, buf_offset); - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); -#endif - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - WRITE_VREG(FROM_AMRISC, 0); - WRITE_VREG(TO_AMRISC, 0); - WRITE_VREG(STATUS_AMRISC, 0); - - WRITE_VREG(RV_PIC_INFO, 0); - WRITE_VREG(VPTS_TR, 0); - WRITE_VREG(VDTS, 0); - WRITE_VREG(SKIP_B_AMRISC, 0); - - WRITE_VREG(MDEC_WIDTH, (frame_width + 15) & 0xfff0); - WRITE_VREG(MDEC_HEIGHT, (frame_height + 15) & 0xfff0); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - - /* clear wait buffer status */ - WRITE_VREG(WAIT_BUFFER, 0); - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - return r; -} - -static void vreal_local_init(void) -{ - int i; - - /* vreal_ratio = vreal_amstream_dec_info.ratio; */ - vreal_ratio = 0x100; - - frame_prog = 0; - - frame_width = vreal_amstream_dec_info.width; - frame_height = vreal_amstream_dec_info.height; - frame_dur = vreal_amstream_dec_info.rate; - - for (i = 0; i < VF_BUF_NUM; i++) - vfbuf_use[i] = 0; - - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &vfpool[i]; - vfpool[i].index = VF_BUF_NUM; - kfifo_put(&newframe_q, vf); - } - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); - - decoder_state = 1; - hold = 0; - last_tr = -1; - wait_key_frame = 1; - frame_count = 0; - current_vdts = 0; - real_err_count = 0; - - pic_sz_tbl_map = 0; - saved_resolution = 0; - fatal_flag = 0; - wait_buffer_counter = 0; -} - -static void load_block_data(void *dest, unsigned int count) -{ - unsigned short *pdest = (unsigned short *)dest; - unsigned short src_tbl[12]; - unsigned int i; - - src_tbl[0] = RPR_size[vreal_amstream_dec_info.extra + 1]; - memcpy((void *)&src_tbl[1], vreal_amstream_dec_info.param, - 2 << src_tbl[0]); - -#if 0 - for (i = 0; i < 12; i++) - pr_info("src_tbl[%d]: 0x%x\n", i, src_tbl[i]); -#endif - - for (i = 0; i < count / 4; i++) { - pdest[i * 4] = src_tbl[i * 4 + 3]; - pdest[i * 4 + 1] = src_tbl[i * 4 + 2]; - pdest[i * 4 + 2] = src_tbl[i * 4 + 1]; - pdest[i * 4 + 3] = src_tbl[i * 4]; - } - - pic_sz_tbl_map = dma_map_single(amports_get_dma_device(), &pic_sz_tbl, - sizeof(pic_sz_tbl), DMA_TO_DEVICE); - -} - -s32 vreal_init(struct vdec_s *vdec) -{ - int ret = -1, size = -1; - char fw_name[32] = {0}; - char *buf = vmalloc(0x1000 * 16); - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - pr_info("vreal_init\n"); - - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - amvdec_enable(); - - vreal_local_init(); - - ret = rmparser_init(vdec); - if (ret) { - amvdec_disable(); - vfree(buf); - pr_info("rm parser init failed\n"); - return ret; - } - - if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_8) { - if (vreal_amstream_dec_info.param == NULL) { - rmparser_release(); - amvdec_disable(); - vfree(buf); - return -1; - } - load_block_data((void *)pic_sz_tbl, 12); - - /* TODO: need to load the table into lmem */ - WRITE_VREG(LMEM_DMA_ADR, (unsigned int)pic_sz_tbl_map); - WRITE_VREG(LMEM_DMA_COUNT, 10); - WRITE_VREG(LMEM_DMA_CTRL, 0xc178 | (3 << 11)); - while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) - ; - size = get_firmware_data(VIDEO_DEC_REAL_V8, buf); - strncpy(fw_name, "vreal_mc_8", sizeof(fw_name)); - - pr_info("load VIDEO_DEC_FORMAT_REAL_8\n"); - } else if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_9) { - size = get_firmware_data(VIDEO_DEC_REAL_V9, buf); - strncpy(fw_name, "vreal_mc_9", sizeof(fw_name)); - - pr_info("load VIDEO_DEC_FORMAT_REAL_9\n"); - } else - pr_info("unsurpported real format\n"); - - if (size < 0) { - rmparser_release(); - amvdec_disable(); - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_REAL, fw_name, buf); - if (ret < 0) { - rmparser_release(); - amvdec_disable(); - vfree(buf); - pr_err("%s: the %s fw loading failed, err: %x\n", - fw_name, tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(buf); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - ret = vreal_prot_init(); - if (ret < 0) { - rmparser_release(); - amvdec_disable(); - return ret; - } - if (vdec_request_irq(VDEC_IRQ_1, vreal_isr, - "vreal-irq", (void *)vreal_dec_id)) { - rmparser_release(); - amvdec_disable(); - - pr_info("vreal irq register error.\n"); - return -ENOENT; - } - - stat |= STAT_ISR_REG; -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vreal_vf_prov, PROVIDER_NAME, &vreal_vf_provider, - NULL); - vf_reg_provider(&vreal_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vreal_vf_prov, PROVIDER_NAME, &vreal_vf_provider, - NULL); - vf_reg_provider(&vreal_vf_prov); -#endif - - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)vreal_amstream_dec_info.rate)); - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong)&recycle_timer; - recycle_timer.function = vreal_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - pr_info("vreal init finished\n"); - - return 0; -} - -void vreal_set_fatal_flag(int flag) -{ - if (flag) - fatal_flag = PARSER_FATAL_ERROR; -} - -static int amvdec_real_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - if (pdata == NULL) { - pr_info("amvdec_real memory resource undefined.\n"); - return -EFAULT; - } - if (pdata->sys_info) - vreal_amstream_dec_info = *pdata->sys_info; - - pdata->dec_status = vreal_dec_status; - pdata->set_isreset = vreal_set_isreset; - is_reset = 0; - - if (vreal_init(pdata) < 0) { - pr_info("amvdec_real init failed.\n"); - pdata->dec_status = NULL; - return -ENODEV; - } - INIT_WORK(&set_clk_work, vreal_set_clk); - return 0; -} - -static int amvdec_real_remove(struct platform_device *pdev) -{ - cancel_work_sync(&set_clk_work); - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)vreal_dec_id); - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - if (stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); - - vf_unreg_provider(&vreal_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - if (pic_sz_tbl_map != 0) { - dma_unmap_single(NULL, pic_sz_tbl_map, sizeof(pic_sz_tbl), - DMA_TO_DEVICE); - } - - rmparser_release(); - - vdec_source_changed(VFORMAT_REAL, 0, 0, 0); - - amvdec_disable(); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - pr_info("frame duration %d, frames %d\n", frame_dur, frame_count); - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_real_driver = { - .probe = amvdec_real_probe, - .remove = amvdec_real_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_real_profile = { - .name = "real", - .profile = "rmvb,1080p+" -}; -static struct mconfig real_configs[] = { - MC_PU32("stat", &stat), -}; -static struct mconfig_node real_node; - -static int __init amvdec_real_driver_init_module(void) -{ - pr_debug("amvdec_real module init\n"); - - if (platform_driver_register(&amvdec_real_driver)) { - pr_err("failed to register amvdec_real driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvdec_real_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &real_node, - "real", real_configs, CONFIG_FOR_R); - return 0; -} - -static void __exit amvdec_real_driver_remove_module(void) -{ - pr_debug("amvdec_real module remove.\n"); - - platform_driver_unregister(&amvdec_real_driver); -} - -/****************************************/ - -module_init(amvdec_real_driver_init_module); -module_exit(amvdec_real_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC REAL Video Decoder Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h deleted file mode 100644 index 734cc6f09a5a..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * drivers/amlogic/amports/vreal.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VREAL_H -#define VREAL_H - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -/* TODO: move to register headers */ -#define VPP_VD1_POSTBLEND (1 << 10) -#endif - -#endif /* VREAL_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile deleted file mode 100644 index ee7dbf425f11..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m += decoder_common.o -decoder_common-objs += utils.o vdec.o vdec_input.o amvdec.o -decoder_common-objs += decoder_mmu_box.o decoder_bmmu_box.o -decoder_common-objs += config_parser.o secprot.o vdec_profile.o -decoder_common-objs += amstream_profile.o -decoder_common-objs += frame_check.o amlogic_fbc_hook.o - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c deleted file mode 100644 index b6179fb9a629..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#include -#include -#include - -#include "amlogic_fbc_hook.h" -static AMLOGIC_FBC_vframe_decoder_fun_t g_decoder_fun; -static AMLOGIC_FBC_vframe_encoder_fun_t g_encoder_fun; - - -int AMLOGIC_FBC_vframe_decoder( - void *dstyuv[4], - struct vframe_s *vf, - int out_format, - int flags) - -{ - if (g_decoder_fun) { - return g_decoder_fun(dstyuv, - vf, - out_format, - flags); - } - printk("no AMLOGIC_FBC_vframe_decoder ERRR!!\n"); - return -1; -} -EXPORT_SYMBOL(AMLOGIC_FBC_vframe_decoder); - -int AMLOGIC_FBC_vframe_encoder( - void *srcyuv[4], - void *dst_header, - void *dst_body, - int in_format, - int flags) - -{ - if (g_encoder_fun) { - return g_encoder_fun( - srcyuv, - dst_header, - dst_body, - in_format, - flags); - } - printk("no AMLOGIC_FBC_vframe_encoder ERRR!!\n"); - return -1; -} -EXPORT_SYMBOL(AMLOGIC_FBC_vframe_encoder); - -int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn) -{ - if (g_decoder_fun) { - pr_err("error!!,AMLOGIC_FBC dec have register\n"); - return -1; - } - printk("register_amlogic_afbc_dec_fun\n"); - g_decoder_fun = fn; - return 0; -} -EXPORT_SYMBOL(register_amlogic_afbc_dec_fun); - -int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn) -{ - if (g_encoder_fun) { - pr_err("error!!,AMLOGIC_FBC enc have register\n"); - return -1; - } - g_encoder_fun = fn; - return 0; -} -EXPORT_SYMBOL(register_amlogic_afbc_enc_fun); - -int unregister_amlogic_afbc_dec_fun(void) -{ - g_decoder_fun = NULL; - pr_err("unregister_amlogic_afbc_dec_fun\n"); - return 0; -} -EXPORT_SYMBOL(unregister_amlogic_afbc_dec_fun); - -int unregister_amlogic_afbc_enc_fun(void) -{ - g_encoder_fun = NULL; - pr_err("unregister_amlogic_afbc_dec_fun\n"); - return 0; -} -EXPORT_SYMBOL(unregister_amlogic_afbc_enc_fun); - - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h deleted file mode 100644 index 7eec4b719e9f..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef AMLGIC_FBC_HEADER___ -#define AMLGIC_FBC_HEADER___ -#include -/* -unsigned short *planes[4], - unsigned char *buf, - unsigned *v2_head_buf // v2_head_buf_size=(((frame_info->mbw + 1)>>1)*2) * (((frame_info->mbh + 15)>>4)*16) -); -*/ - -int AMLOGIC_FBC_vframe_decoder( - void *dstyuv[4], - struct vframe_s *vf, - int out_format, - int flags); -int AMLOGIC_FBC_vframe_encoder( - void *srcyuv[4], - void *dst_header, - void *dst_body, - int in_format, - int flags); - -typedef int (*AMLOGIC_FBC_vframe_decoder_fun_t)( - void **, - struct vframe_s *, - int, - int); -typedef int (*AMLOGIC_FBC_vframe_encoder_fun_t)( - void **, - void *, - void *, - int, - int); -int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn); -int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn); -int unregister_amlogic_afbc_dec_fun(void); -int unregister_amlogic_afbc_enc_fun(void); -#endif \ No newline at end of file diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c deleted file mode 100644 index 93f50c793068..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/amstream_profile.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include - -static const struct codec_profile_t *vcodec_profile[SUPPORT_VDEC_NUM] = { 0 }; - -static int vcodec_profile_idx; - -ssize_t vcodec_profile_read(char *buf) -{ - char *pbuf = buf; - int i = 0; - - for (i = 0; i < vcodec_profile_idx; i++) { - pbuf += snprintf(pbuf, PAGE_SIZE - (pbuf - buf), "%s:%s;\n", vcodec_profile[i]->name, - vcodec_profile[i]->profile); - } - - return pbuf - buf; -} -EXPORT_SYMBOL(vcodec_profile_read); - -int vcodec_profile_register(const struct codec_profile_t *vdec_profile) -{ - if (vcodec_profile_idx < SUPPORT_VDEC_NUM) { - vcodec_profile[vcodec_profile_idx] = vdec_profile; - vcodec_profile_idx++; - pr_debug("regist %s codec profile\n", vdec_profile->name); - - } - - return 0; -} -EXPORT_SYMBOL(vcodec_profile_register); - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c deleted file mode 100644 index 1d4e6f5a49eb..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c +++ /dev/null @@ -1,1161 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/amvdec.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "vdec.h" - -#ifdef CONFIG_PM -#include -#endif - -#ifdef CONFIG_WAKELOCK -#include -#endif -#include "../../../stream_input/amports/amports_priv.h" - -/* #include */ -/* #include */ -#include -#include "amvdec.h" -#include -#include "firmware.h" -#include -#include "../../../common/chips/decoder_cpu_ver_info.h" - -#define MC_SIZE (4096 * 16) - -#ifdef CONFIG_WAKELOCK -static struct wake_lock amvdec_lock; -struct timer_list amvdevtimer; -#define WAKE_CHECK_INTERVAL (100*HZ/100) -#endif -#define AMVDEC_USE_STATIC_MEMORY -static void *mc_addr; -static dma_addr_t mc_addr_map; - -#ifdef CONFIG_WAKELOCK -static int video_running; -static int video_stated_changed = 1; -#endif - -static void amvdec_pg_enable(bool enable) -{ - ulong timeout; - - if (enable) { - AMVDEC_CLK_GATE_ON(MDEC_CLK_PIC_DC); - AMVDEC_CLK_GATE_ON(MDEC_CLK_DBLK); - AMVDEC_CLK_GATE_ON(MC_CLK); - AMVDEC_CLK_GATE_ON(IQIDCT_CLK); - /* AMVDEC_CLK_GATE_ON(VLD_CLK); */ - AMVDEC_CLK_GATE_ON(AMRISC); - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) - WRITE_VREG(GCLK_EN, 0x3ff); - /* #endif */ - CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); - } else { - - AMVDEC_CLK_GATE_OFF(AMRISC); - timeout = jiffies + HZ / 100; - - while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) { - if (time_after(jiffies, timeout)) { - WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 1, 0, 1); - WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 0, 0, 1); - READ_VREG(MDEC_PIC_DC_STATUS); - READ_VREG(MDEC_PIC_DC_STATUS); - READ_VREG(MDEC_PIC_DC_STATUS); - break; - } - } - - AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC); - timeout = jiffies + HZ / 100; - - while (READ_VREG(DBLK_STATUS) & 1) { - if (time_after(jiffies, timeout)) { - WRITE_VREG(DBLK_CTRL, 3); - WRITE_VREG(DBLK_CTRL, 0); - READ_VREG(DBLK_STATUS); - READ_VREG(DBLK_STATUS); - READ_VREG(DBLK_STATUS); - break; - } - } - AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK); - timeout = jiffies + HZ / 100; - - while (READ_VREG(MC_STATUS0) & 1) { - if (time_after(jiffies, timeout)) { - SET_VREG_MASK(MC_CTRL1, 0x9); - CLEAR_VREG_MASK(MC_CTRL1, 0x9); - READ_VREG(MC_STATUS0); - READ_VREG(MC_STATUS0); - READ_VREG(MC_STATUS0); - break; - } - } - AMVDEC_CLK_GATE_OFF(MC_CLK); - timeout = jiffies + HZ / 100; - while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - AMVDEC_CLK_GATE_OFF(IQIDCT_CLK); - /* AMVDEC_CLK_GATE_OFF(VLD_CLK); */ - } -} - -static void amvdec2_pg_enable(bool enable) -{ - if (has_vdec2()) { - ulong timeout; - - if (!vdec_on(VDEC_2)) - return; - if (enable) { - /* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */ - } else { - timeout = jiffies + HZ / 10; - - while (READ_VREG(VDEC2_MDEC_PIC_DC_STATUS) != 0) { - if (time_after(jiffies, timeout)) { - WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL, - 1, 0, 1); - WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL, - 0, 0, 1); - READ_VREG(VDEC2_MDEC_PIC_DC_STATUS); - READ_VREG(VDEC2_MDEC_PIC_DC_STATUS); - READ_VREG(VDEC2_MDEC_PIC_DC_STATUS); - break; - } - } - - timeout = jiffies + HZ / 10; - - while (READ_VREG(VDEC2_DBLK_STATUS) & 1) { - if (time_after(jiffies, timeout)) { - WRITE_VREG(VDEC2_DBLK_CTRL, 3); - WRITE_VREG(VDEC2_DBLK_CTRL, 0); - READ_VREG(VDEC2_DBLK_STATUS); - READ_VREG(VDEC2_DBLK_STATUS); - READ_VREG(VDEC2_DBLK_STATUS); - break; - } - } - - timeout = jiffies + HZ / 10; - - while (READ_VREG(VDEC2_DCAC_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - } - } -} - -static void amhevc_pg_enable(bool enable) -{ - if (has_hevc_vdec()) { - ulong timeout; - - if (!vdec_on(VDEC_HEVC)) - return; - if (enable) { - /* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */ - } else { - timeout = jiffies + HZ / 10; - - while (READ_VREG(HEVC_MDEC_PIC_DC_STATUS) != 0) { - if (time_after(jiffies, timeout)) { - WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL, - 1, 0, 1); - WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL, - 0, 0, 1); - READ_VREG(HEVC_MDEC_PIC_DC_STATUS); - READ_VREG(HEVC_MDEC_PIC_DC_STATUS); - READ_VREG(HEVC_MDEC_PIC_DC_STATUS); - break; - } - } - - timeout = jiffies + HZ / 10; - - while (READ_VREG(HEVC_DBLK_STATUS) & 1) { - if (time_after(jiffies, timeout)) { - WRITE_VREG(HEVC_DBLK_CTRL, 3); - WRITE_VREG(HEVC_DBLK_CTRL, 0); - READ_VREG(HEVC_DBLK_STATUS); - READ_VREG(HEVC_DBLK_STATUS); - READ_VREG(HEVC_DBLK_STATUS); - break; - } - } - - timeout = jiffies + HZ / 10; - - while (READ_VREG(HEVC_DCAC_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - } - } -} - -#ifdef CONFIG_WAKELOCK -int amvdec_wake_lock(void) -{ - wake_lock(&amvdec_lock); - return 0; -} - -int amvdec_wake_unlock(void) -{ - wake_unlock(&amvdec_lock); - return 0; -} -#else -#define amvdec_wake_lock() -#define amvdec_wake_unlock() -#endif - -static s32 am_vdec_loadmc_ex(struct vdec_s *vdec, - const char *name, char *def, s32(*load)(const u32 *)) -{ - int err; - - if (!vdec->mc_loaded) { - if (!def) { - err = get_decoder_firmware_data(vdec->format, - name, (u8 *)(vdec->mc), - (4096 * 4 * 4)); - if (err <= 0) - return -1; - } else - memcpy((char *)vdec->mc, def, sizeof(vdec->mc)); - - vdec->mc_loaded = true; - } - - err = (*load)(vdec->mc); - if (err < 0) { - pr_err("loading firmware %s to vdec ram failed!\n", name); - return err; - } - - return err; -} - -static s32 am_vdec_loadmc_buf_ex(struct vdec_s *vdec, - char *buf, int size, s32(*load)(const u32 *)) -{ - int err; - - if (!vdec->mc_loaded) { - memcpy((u8 *)(vdec->mc), buf, size); - vdec->mc_loaded = true; - } - - err = (*load)(vdec->mc); - if (err < 0) { - pr_err("loading firmware to vdec ram failed!\n"); - return err; - } - - return err; -} - -static s32 am_loadmc_ex(enum vformat_e type, - const char *name, char *def, s32(*load)(const u32 *)) -{ - char *mc_addr = vmalloc(4096 * 16); - char *pmc_addr = def; - int err; - - if (!def && mc_addr) { - int loaded; - - loaded = get_decoder_firmware_data(type, - name, mc_addr, (4096 * 16)); - if (loaded > 0) - pmc_addr = mc_addr; - } - if (!pmc_addr) { - vfree(mc_addr); - return -1; - } - err = (*load)((u32 *) pmc_addr); - if (err < 0) { - pr_err("loading firmware %s to vdec ram failed!\n", name); - vfree(mc_addr); - return err; - } - vfree(mc_addr); - - return err; -} - -static s32 amvdec_loadmc(const u32 *p) -{ - ulong timeout; - s32 ret = 0; - -#ifdef AMVDEC_USE_STATIC_MEMORY - if (mc_addr == NULL) { -#else - { -#endif - mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); - } - - if (!mc_addr) - return -ENOMEM; - - memcpy(mc_addr, p, MC_SIZE); - - mc_addr_map = dma_map_single(get_vdec_device(), - mc_addr, MC_SIZE, DMA_TO_DEVICE); - - WRITE_VREG(MPSR, 0); - WRITE_VREG(CPSR, 0); - - /* Read CBUS register for timing */ - timeout = READ_VREG(MPSR); - timeout = READ_VREG(MPSR); - - timeout = jiffies + HZ; - - WRITE_VREG(IMEM_DMA_ADR, mc_addr_map); - WRITE_VREG(IMEM_DMA_COUNT, 0x1000); - WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16))); - - while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) { - if (time_before(jiffies, timeout)) - schedule(); - else { - pr_err("vdec load mc error\n"); - ret = -EBUSY; - break; - } - } - - dma_unmap_single(get_vdec_device(), - mc_addr_map, MC_SIZE, DMA_TO_DEVICE); - -#ifndef AMVDEC_USE_STATIC_MEMORY - kfree(mc_addr); - mc_addr = NULL; -#endif - - return ret; -} - -s32 optee_load_fw(enum vformat_e type, const char *fw_name) -{ - s32 ret = -1; - unsigned int format = FIRMWARE_MAX; - unsigned int vdec = OPTEE_VDEC_LEGENCY; - char *name = __getname(); - bool is_swap = false; - - sprintf(name, "%s", fw_name ? fw_name : "null"); - - switch ((u32)type) { - case VFORMAT_VC1: - format = VIDEO_DEC_VC1; - break; - - case VFORMAT_AVS: - if (!strcmp(name, "avs_no_cabac")) - format = VIDEO_DEC_AVS_NOCABAC; - else - format = VIDEO_DEC_AVS; - break; - - case VFORMAT_MPEG12: - if (!strcmp(name, "mpeg12")) - format = VIDEO_DEC_MPEG12; - else if (!strcmp(name, "mmpeg12")) - format = VIDEO_DEC_MPEG12_MULTI; - break; - - case VFORMAT_MJPEG: - if (!strcmp(name, "mmjpeg")) - format = VIDEO_DEC_MJPEG_MULTI; - else - format = VIDEO_DEC_MJPEG; - break; - - case VFORMAT_VP9: - if (!strcmp(name, "vp9_mc")) - format = VIDEO_DEC_VP9; - else - format = VIDEO_DEC_VP9_MMU; - break; - - case VFORMAT_AVS2: - format = VIDEO_DEC_AVS2_MMU; - vdec = OPTEE_VDEC_HEVC; - break; - - case VFORMAT_HEVC: - if (!strcmp(name, "h265_mmu")) - format = VIDEO_DEC_HEVC_MMU; - else if (!strcmp(name, "hevc_mmu_swap")) { - format = VIDEO_DEC_HEVC_MMU_SWAP; - vdec = OPTEE_VDEC_HEVC; - is_swap = true; - } else - format = VIDEO_DEC_HEVC; - break; - - case VFORMAT_REAL: - if (!strcmp(name, "vreal_mc_8")) - format = VIDEO_DEC_REAL_V8; - else if (!strcmp(name, "vreal_mc_9")) - format = VIDEO_DEC_REAL_V9; - break; - - case VFORMAT_MPEG4: - if (!strcmp(name, "mmpeg4_mc_5")) - format = VIDEO_DEC_MPEG4_5_MULTI; - else if ((!strcmp(name, "mh263_mc"))) - format = VIDEO_DEC_H263_MULTI; - else if (!strcmp(name, "vmpeg4_mc_5")) - format = VIDEO_DEC_MPEG4_5; - else if (!strcmp(name, "h263_mc")) - format = VIDEO_DEC_H263; - /*not support now*/ - else if (!strcmp(name, "vmpeg4_mc_311")) - format = VIDEO_DEC_MPEG4_3; - else if (!strcmp(name, "vmpeg4_mc_4")) - format = VIDEO_DEC_MPEG4_4; - break; - - case VFORMAT_H264_4K2K: - if (!strcmp(name, "single_core")) - format = VIDEO_DEC_H264_4k2K_SINGLE; - else - format = VIDEO_DEC_H264_4k2K; - break; - - case VFORMAT_H264MVC: - format = VIDEO_DEC_H264_MVC; - break; - - case VFORMAT_H264: - if (!strcmp(name, "mh264")) - format = VIDEO_DEC_H264_MULTI; - else if (!strcmp(name, "mh264_mmu")) { - format = VIDEO_DEC_H264_MULTI_MMU; - vdec = OPTEE_VDEC_HEVC; - } else - format = VIDEO_DEC_H264; - break; - - default: - pr_info("Unknow vdec format!\n"); - break; - } - - if (format < FIRMWARE_MAX) { - if (is_swap) - ret = tee_load_video_fw_swap(format, vdec, is_swap); - else - ret = tee_load_video_fw(format, vdec); - } - - __putname(name); - - return ret; -} -EXPORT_SYMBOL(optee_load_fw); - -s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def) -{ - if (tee_enabled()) - return optee_load_fw(type, name); - else - return am_loadmc_ex(type, name, def, &amvdec_loadmc); -} -EXPORT_SYMBOL(amvdec_loadmc_ex); - -s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name, - struct vdec_s *vdec, char *def) -{ - if (tee_enabled()) - return optee_load_fw(type, name); - else - return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc); -} -EXPORT_SYMBOL(amvdec_vdec_loadmc_ex); - -s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name, - struct vdec_s *vdec, char *buf, int size) -{ - if (tee_enabled()) - return optee_load_fw(type, name); - else - return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc); -} -EXPORT_SYMBOL(amvdec_vdec_loadmc_buf_ex); - -static s32 amvdec2_loadmc(const u32 *p) -{ - if (has_vdec2()) { - ulong timeout; - s32 ret = 0; - -#ifdef AMVDEC_USE_STATIC_MEMORY - if (mc_addr == NULL) { -#else - { -#endif - mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); - } - - if (!mc_addr) - return -ENOMEM; - - memcpy(mc_addr, p, MC_SIZE); - - mc_addr_map = dma_map_single(get_vdec_device(), - mc_addr, MC_SIZE, DMA_TO_DEVICE); - - WRITE_VREG(VDEC2_MPSR, 0); - WRITE_VREG(VDEC2_CPSR, 0); - - /* Read CBUS register for timing */ - timeout = READ_VREG(VDEC2_MPSR); - timeout = READ_VREG(VDEC2_MPSR); - - timeout = jiffies + HZ; - - WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map); - WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000); - WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); - - while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) { - if (time_before(jiffies, timeout)) - schedule(); - else { - pr_err("vdec2 load mc error\n"); - ret = -EBUSY; - break; - } - } - - dma_unmap_single(get_vdec_device(), - mc_addr_map, MC_SIZE, DMA_TO_DEVICE); - -#ifndef AMVDEC_USE_STATIC_MEMORY - kfree(mc_addr); - mc_addr = NULL; -#endif - - return ret; - } else - return 0; -} - -s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def) -{ - if (has_vdec2()) - return am_loadmc_ex(type, name, def, &amvdec2_loadmc); - else - return 0; -} -EXPORT_SYMBOL(amvdec2_loadmc_ex); - -s32 amhcodec_loadmc(const u32 *p) -{ -#ifdef AMVDEC_USE_STATIC_MEMORY - if (mc_addr == NULL) { -#else - { -#endif - mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); - } - - if (!mc_addr) - return -ENOMEM; - - memcpy(mc_addr, p, MC_SIZE); - - mc_addr_map = dma_map_single(get_vdec_device(), - mc_addr, MC_SIZE, DMA_TO_DEVICE); - - WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map); - WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100); - WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); - - while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) - udelay(1000); - - dma_unmap_single(get_vdec_device(), - mc_addr_map, MC_SIZE, DMA_TO_DEVICE); - -#ifndef AMVDEC_USE_STATIC_MEMORY - kfree(mc_addr); -#endif - - return 0; -} -EXPORT_SYMBOL(amhcodec_loadmc); - -s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def) -{ - return am_loadmc_ex(type, name, def, &amhcodec_loadmc); -} -EXPORT_SYMBOL(amhcodec_loadmc_ex); - -static s32 amhevc_loadmc(const u32 *p) -{ - ulong timeout; - s32 ret = 0; - - if (has_hevc_vdec()) { -#ifdef AMVDEC_USE_STATIC_MEMORY - if (mc_addr == NULL) { -#else - { -#endif - mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); - } - - if (!mc_addr) - return -ENOMEM; - - memcpy(mc_addr, p, MC_SIZE); - - mc_addr_map = - dma_map_single(get_vdec_device(), - mc_addr, MC_SIZE, DMA_TO_DEVICE); - - WRITE_VREG(HEVC_MPSR, 0); - WRITE_VREG(HEVC_CPSR, 0); - - /* Read CBUS register for timing */ - timeout = READ_VREG(HEVC_MPSR); - timeout = READ_VREG(HEVC_MPSR); - - timeout = jiffies + HZ; - - WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map); - WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000); - WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); - - while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) { - if (time_before(jiffies, timeout)) - schedule(); - else { - pr_err("vdec2 load mc error\n"); - ret = -EBUSY; - break; - } - } - - dma_unmap_single(get_vdec_device(), - mc_addr_map, MC_SIZE, DMA_TO_DEVICE); - -#ifndef AMVDEC_USE_STATIC_MEMORY - kfree(mc_addr); - mc_addr = NULL; -#endif - } - - return ret; -} - -s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def) -{ - if (has_hevc_vdec()) - if (tee_enabled()) - return optee_load_fw(type, name); - else - return am_loadmc_ex(type, name, def, &amhevc_loadmc); - else - return -1; -} -EXPORT_SYMBOL(amhevc_loadmc_ex); - -s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec, - const char *name, char *def) -{ - if (has_hevc_vdec()) - if (tee_enabled()) - return optee_load_fw(type, name); - else - return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc); - else - return -1; -} -EXPORT_SYMBOL(amhevc_vdec_loadmc_ex); - -void amvdec_start(void) -{ -#ifdef CONFIG_WAKELOCK - amvdec_wake_lock(); -#endif - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - } else { - /* #else */ - /* additional cbus dummy register reading for timing control */ - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - - WRITE_RESET_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU); - - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - } - /* #endif */ - - WRITE_VREG(MPSR, 0x0001); -} -EXPORT_SYMBOL(amvdec_start); - -void amvdec2_start(void) -{ - if (has_vdec2()) { -#ifdef CONFIG_WAKELOCK - amvdec_wake_lock(); -#endif - - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - - WRITE_VREG(DOS_SW_RESET2, (1 << 12) | (1 << 11)); - WRITE_VREG(DOS_SW_RESET2, 0); - - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - - WRITE_VREG(VDEC2_MPSR, 0x0001); - } -} -EXPORT_SYMBOL(amvdec2_start); - -void amhcodec_start(void) -{ - WRITE_VREG(HCODEC_MPSR, 0x0001); -} -EXPORT_SYMBOL(amhcodec_start); - -void amhevc_start(void) -{ - - if (has_hevc_vdec()) { -#ifdef CONFIG_WAKELOCK - amvdec_wake_lock(); -#endif - - READ_VREG(DOS_SW_RESET3); - READ_VREG(DOS_SW_RESET3); - READ_VREG(DOS_SW_RESET3); - - WRITE_VREG(DOS_SW_RESET3, (1 << 12) | (1 << 11)); - WRITE_VREG(DOS_SW_RESET3, 0); - - READ_VREG(DOS_SW_RESET3); - READ_VREG(DOS_SW_RESET3); - READ_VREG(DOS_SW_RESET3); - - WRITE_VREG(HEVC_MPSR, 0x0001); - } -} -EXPORT_SYMBOL(amhevc_start); - -void amvdec_stop(void) -{ - ulong timeout = jiffies + HZ/10; - - WRITE_VREG(MPSR, 0); - WRITE_VREG(CPSR, 0); - - while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - - timeout = jiffies + HZ/10; - while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - READ_VREG(DOS_SW_RESET0); - } else { - /* #else */ - WRITE_RESET_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU); - - /* additional cbus dummy register reading for timing control */ - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - READ_RESET_REG(RESET0_REGISTER); - } - /* #endif */ - -#ifdef CONFIG_WAKELOCK - amvdec_wake_unlock(); -#endif -} -EXPORT_SYMBOL(amvdec_stop); - -void amvdec2_stop(void) -{ - if (has_vdec2()) { - ulong timeout = jiffies + HZ/10; - - WRITE_VREG(VDEC2_MPSR, 0); - WRITE_VREG(VDEC2_CPSR, 0); - - while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - READ_VREG(DOS_SW_RESET2); - -#ifdef CONFIG_WAKELOCK - amvdec_wake_unlock(); -#endif - } -} -EXPORT_SYMBOL(amvdec2_stop); - -void amhcodec_stop(void) -{ - WRITE_VREG(HCODEC_MPSR, 0); -} -EXPORT_SYMBOL(amhcodec_stop); - -void amhevc_stop(void) -{ - if (has_hevc_vdec()) { - ulong timeout = jiffies + HZ/10; - - WRITE_VREG(HEVC_MPSR, 0); - WRITE_VREG(HEVC_CPSR, 0); - - while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - - timeout = jiffies + HZ/10; - while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - - READ_VREG(DOS_SW_RESET3); - READ_VREG(DOS_SW_RESET3); - READ_VREG(DOS_SW_RESET3); - -#ifdef CONFIG_WAKELOCK - amvdec_wake_unlock(); -#endif - } -} -EXPORT_SYMBOL(amhevc_stop); - -void amvdec_enable(void) -{ - amvdec_pg_enable(true); -} -EXPORT_SYMBOL(amvdec_enable); - -void amvdec_disable(void) -{ - amvdec_pg_enable(false); -} -EXPORT_SYMBOL(amvdec_disable); - -void amvdec2_enable(void) -{ - if (has_vdec2()) - amvdec2_pg_enable(true); -} -EXPORT_SYMBOL(amvdec2_enable); - -void amvdec2_disable(void) -{ - if (has_vdec2()) - amvdec2_pg_enable(false); -} -EXPORT_SYMBOL(amvdec2_disable); - -void amhevc_enable(void) -{ - if (has_hevc_vdec()) - amhevc_pg_enable(true); -} -EXPORT_SYMBOL(amhevc_enable); - -void amhevc_disable(void) -{ - if (has_hevc_vdec()) - amhevc_pg_enable(false); -} -EXPORT_SYMBOL(amhevc_disable); - -#ifdef CONFIG_PM -int amvdec_suspend(struct platform_device *dev, pm_message_t event) -{ - amvdec_pg_enable(false); - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ - if (has_vdec2()) - amvdec2_pg_enable(false); - /* #endif */ - - if (has_hevc_vdec()) - amhevc_pg_enable(false); - /*vdec_set_suspend_clk(1, 0);*//*DEBUG_TMP*/ - return 0; -} -EXPORT_SYMBOL(amvdec_suspend); - -int amvdec_resume(struct platform_device *dev) -{ - amvdec_pg_enable(true); - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ - if (has_vdec2()) - amvdec2_pg_enable(true); - /* #endif */ - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (has_hevc_vdec()) - amhevc_pg_enable(true); - /* #endif */ - /*vdec_set_suspend_clk(0, 0);*//*DEBUG_TMP*/ - return 0; -} -EXPORT_SYMBOL(amvdec_resume); - -int amhevc_suspend(struct platform_device *dev, pm_message_t event) -{ - if (has_hevc_vdec()) { - amhevc_pg_enable(false); - /*vdec_set_suspend_clk(1, 1);*//*DEBUG_TMP*/ - } - return 0; -} -EXPORT_SYMBOL(amhevc_suspend); - -int amhevc_resume(struct platform_device *dev) -{ - if (has_hevc_vdec()) { - amhevc_pg_enable(true); - /*vdec_set_suspend_clk(0, 1);*//*DEBUG_TMP*/ - } - return 0; -} -EXPORT_SYMBOL(amhevc_resume); - - -#endif - -#ifdef CONFIG_WAKELOCK - -static int vdec_is_paused(void) -{ - static unsigned long old_wp = -1, old_rp = -1, old_level = -1; - unsigned long wp, rp, level; - static int paused_time; - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (has_hevc_vdec()) { - if ((vdec_on(VDEC_HEVC)) - && (READ_VREG(HEVC_STREAM_CONTROL) & 1)) { - wp = READ_VREG(HEVC_STREAM_WR_PTR); - rp = READ_VREG(HEVC_STREAM_RD_PTR); - level = READ_VREG(HEVC_STREAM_LEVEL); - } else { - wp = READ_VREG(VLD_MEM_VIFIFO_WP); - rp = READ_VREG(VLD_MEM_VIFIFO_RP); - level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); - } - } else - /* #endif */ - { - wp = READ_VREG(VLD_MEM_VIFIFO_WP); - rp = READ_VREG(VLD_MEM_VIFIFO_RP); - level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); - } - /*have data,but output buffer is full */ - if ((rp == old_rp && level > 1024) || - (rp == old_rp && wp == old_wp && level == old_level)) { - /*no write && not read */ - paused_time++; - } else { - paused_time = 0; - } - old_wp = wp; old_rp = rp; old_level = level; - if (paused_time > 10) - return 1; - return 0; -} - -int amvdev_pause(void) -{ - video_running = 0; - video_stated_changed = 1; - return 0; -} -EXPORT_SYMBOL(amvdev_pause); - -int amvdev_resume(void) -{ - video_running = 1; - video_stated_changed = 1; - return 0; -} -EXPORT_SYMBOL(amvdev_resume); - -static void vdec_paused_check_timer(unsigned long arg) -{ - if (video_stated_changed) { - if (!video_running) { - if (vdec_is_paused()) { - pr_info("vdec paused and release wakelock now\n"); - amvdec_wake_unlock(); - video_stated_changed = 0; - } - } else { - amvdec_wake_lock(); - video_stated_changed = 0; - } - } - mod_timer(&amvdevtimer, jiffies + WAKE_CHECK_INTERVAL); -} -#else -int amvdev_pause(void) -{ - return 0; -} - -int amvdev_resume(void) -{ - return 0; -} -#endif - -int amvdec_init(void) -{ -#ifdef CONFIG_WAKELOCK - /* - *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock"); - *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8 - */ - wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND, - "amvdec_lock"); - - init_timer(&amvdevtimer); - - amvdevtimer.data = (ulong) &amvdevtimer; - amvdevtimer.function = vdec_paused_check_timer; -#endif - return 0; -} -EXPORT_SYMBOL(amvdec_init); - -void amvdec_exit(void) -{ -#ifdef CONFIG_WAKELOCK - del_timer_sync(&amvdevtimer); -#endif -} -EXPORT_SYMBOL(amvdec_exit); - -#if 0 -int __init amvdec_init(void) -{ -#ifdef CONFIG_WAKELOCK - /* - *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock"); - *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8 - */ - wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND, - "amvdec_lock"); - - init_timer(&amvdevtimer); - - amvdevtimer.data = (ulong) &amvdevtimer; - amvdevtimer.function = vdec_paused_check_timer; -#endif - return 0; -} - -static void __exit amvdec_exit(void) -{ -#ifdef CONFIG_WAKELOCK - del_timer_sync(&amvdevtimer); -#endif -} - -module_init(amvdec_init); -module_exit(amvdec_exit); -#endif - -MODULE_DESCRIPTION("Amlogic Video Decoder Utility Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h deleted file mode 100644 index a3deecd916e7..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/amvdec.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef AMVDEC_H -#define AMVDEC_H -#include -#include -#include "vdec.h" - -#define UCODE_ALIGN 8 -#define UCODE_ALIGN_MASK 7UL - -struct amvdec_dec_reg_s { - unsigned long mem_start; - unsigned long mem_end; - struct device *cma_dev; - struct dec_sysinfo *dec_sysinfo; -}; /*amvdec_dec_reg_t */ - -struct vdec_s; - -extern void amvdec_start(void); -extern void amvdec_stop(void); -extern void amvdec_enable(void); -extern void amvdec_disable(void); -s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def); -s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name, - struct vdec_s *vdec, char *def); - -extern void amvdec2_start(void); -extern void amvdec2_stop(void); -extern void amvdec2_enable(void); -extern void amvdec2_disable(void); -s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def); - -extern void amhevc_start(void); -extern void amhevc_stop(void); -extern void amhevc_enable(void); -extern void amhevc_disable(void); -s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def); -s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec, - const char *name, char *def); -s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name, - struct vdec_s *vdec, char *buf, int size); - -extern void amhcodec_start(void); -extern void amhcodec_stop(void); -s32 amhcodec_loadmc(const u32 *p); -s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def); - -extern int amvdev_pause(void); -extern int amvdev_resume(void); - -#ifdef CONFIG_PM -extern int amvdec_suspend(struct platform_device *dev, pm_message_t event); -extern int amvdec_resume(struct platform_device *dec); -extern int amhevc_suspend(struct platform_device *dev, pm_message_t event); -extern int amhevc_resume(struct platform_device *dec); - -#endif - -int amvdec_init(void); -void amvdec_exit(void); - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define AMVDEC_CLK_GATE_ON(a) -#define AMVDEC_CLK_GATE_OFF(a) -#else -#define AMVDEC_CLK_GATE_ON(a) CLK_GATE_ON(a) -#define AMVDEC_CLK_GATE_OFF(a) CLK_GATE_OFF(a) -#endif - -/* TODO: move to register headers */ -#define RESET_VCPU (1<<7) -#define RESET_CCPU (1<<8) - -#endif /* AMVDEC_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c deleted file mode 100644 index 9a65620795aa..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * drivers/amlogic/amports/config_parser.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#include -#include -#include -#include - -#include "config_parser.h" -/* - *sample config: - *configs: width:1920;height:1080; - *need:width - *ok: return 0; - **val = value; - */ -int get_config_int(const char *configs, const char *need, int *val) -{ - const char *str; - int ret; - int lval = 0; - *val = 0; - - if (!configs || !need) - return -1; - str = strstr(configs, need); - if (str != NULL) { - if (str > configs && str[-1] != ';') { - /* - * if not the first config val. - * make sure before is ';' - * to recognize: - * ;crop_width:100 - * ;width:100 - */ - return -2; - } - str += strlen(need); - if (str[0] != ':' || str[1] == '\0') - return -3; - ret = sscanf(str, ":%d", &lval); - if (ret == 1) { - *val = lval; - return 0; - } - } - - return -4; -} -EXPORT_SYMBOL(get_config_int); - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h deleted file mode 100644 index 9746cafdb59e..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * drivers/amlogic/amports/config_parser.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#ifndef CONFIG_PARSER_HHH_ -#define CONFIG_PARSER_HHH_ -int get_config_int(const char *configs, const char *need, int *val); - -#endif/*CONFIG_PARSER_HHH_*/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c deleted file mode 100644 index 590b812d36dc..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * drivers/amlogic/amports/decoder/decoder_bmmu_box.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "decoder_bmmu_box.h" -#include -#include - -struct decoder_bmmu_box { - int max_mm_num; - const char *name; - int channel_id; - struct mutex mutex; - struct list_head list; - int total_size; - int change_size_on_need_smaller; - int align2n; /*can overwite on idx alloc */ - int mem_flags; /*can overwite on idx alloc */ - struct codec_mm_s *mm_list[1]; -}; - -struct decoder_bmmu_box_mgr { - int num; - struct mutex mutex; - struct list_head box_list; -}; -static struct decoder_bmmu_box_mgr global_blk_mgr; -static struct decoder_bmmu_box_mgr *get_decoder_bmmu_box_mgr(void) -{ - return &global_blk_mgr; -} - -static int decoder_bmmu_box_mgr_add_box(struct decoder_bmmu_box *box) -{ - struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); - - mutex_lock(&mgr->mutex); - list_add_tail(&box->list, &mgr->box_list); - mutex_unlock(&mgr->mutex); - return 0; -} - -static int decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box *box) -{ - struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); - - mutex_lock(&mgr->mutex); - list_del(&box->list); - mutex_unlock(&mgr->mutex); - return 0; -} - -void *decoder_bmmu_box_alloc_box(const char *name, - int channel_id, int max_num, - int aligned, int mem_flags) -/*min_size_M:wait alloc this size*/ -{ - struct decoder_bmmu_box *box; - int size; - int tvp_flags; - tvp_flags = (mem_flags & CODEC_MM_FLAGS_TVP) ? - CODEC_MM_FLAGS_TVP : 0; - - pr_debug("decoder_bmmu_box_alloc_box, tvp_flags = %x\n", tvp_flags); - - size = sizeof(struct decoder_bmmu_box) + sizeof(struct codec_mm_s *) * - max_num; - box = kmalloc(size, GFP_KERNEL); - if (!box) { - pr_err("can't alloc decoder buffers box!!!\n"); - return NULL; - } - memset(box, 0, size); - box->max_mm_num = max_num; - box->name = name; - box->channel_id = channel_id; - box->align2n = aligned; - box->mem_flags = mem_flags | tvp_flags; - mutex_init(&box->mutex); - INIT_LIST_HEAD(&box->list); - decoder_bmmu_box_mgr_add_box(box); - return (void *)box; -} -EXPORT_SYMBOL(decoder_bmmu_box_alloc_box); - -int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n, - int mem_flags) -/*align& flags if -1 user box default.*/ -{ - struct decoder_bmmu_box *box = handle; - struct codec_mm_s *mm; - int align = aligned_2n; - int memflags = mem_flags; - - if (!box || idx < 0 || idx >= box->max_mm_num) { - pr_err("can't alloc mmu box(%p),idx:%d\n", - box, idx); - return -1; - } - if (align == -1) - align = box->align2n; - if (memflags == -1) - memflags = box->mem_flags; - - mutex_lock(&box->mutex); - mm = box->mm_list[idx]; - if (mm) { - int invalid = 0; - int keeped = 0; - - keeped = is_codec_mm_keeped(mm); - if (!keeped) { - if (mm->page_count * PAGE_SIZE < size) { - /*size is small. */ - invalid = 1; - } else if (box->change_size_on_need_smaller && - (mm->buffer_size > (size << 1))) { - /*size is too large. */ - invalid = 2; - } else if (mm->phy_addr & ((1 << align) - 1)) { - /*addr is not align */ - invalid = 4; - } - if (invalid) { - box->total_size -= mm->buffer_size; - codec_mm_release(mm, box->name); - box->mm_list[idx] = NULL; - mm = NULL; - } - } else { - box->total_size -= mm->buffer_size; - codec_mm_release(mm, box->name); - box->mm_list[idx] = NULL; - mm = NULL; - } - } - if (!mm) { - mm = codec_mm_alloc(box->name, size, align, memflags); - if (mm) { - box->mm_list[idx] = mm; - box->total_size += mm->buffer_size; - mm->ins_id = box->channel_id; - mm->ins_buffer_id = idx; - } - } - mutex_unlock(&box->mutex); - return mm ? 0 : -ENOMEM; -} - -int decoder_bmmu_box_free_idx(void *handle, int idx) -{ - struct decoder_bmmu_box *box = handle; - struct codec_mm_s *mm; - - if (!box || idx < 0 || idx >= box->max_mm_num) { - pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", - box, idx, 0, - box ? (box->max_mm_num - 1) : 0); - return -1; - } - mutex_lock(&box->mutex); - mm = box->mm_list[idx]; - if (mm) { - box->total_size -= mm->buffer_size; - codec_mm_release(mm, box->name); - box->mm_list[idx] = NULL; - mm = NULL; - } - mutex_unlock(&box->mutex); - return 0; -} -EXPORT_SYMBOL(decoder_bmmu_box_free_idx); - -int decoder_bmmu_box_free(void *handle) -{ - struct decoder_bmmu_box *box = handle; - struct codec_mm_s *mm; - int i; - - if (!box) { - pr_err("can't free box of NULL box!\n"); - return -1; - } - mutex_lock(&box->mutex); - for (i = 0; i < box->max_mm_num; i++) { - mm = box->mm_list[i]; - if (mm) { - codec_mm_release(mm, box->name); - box->mm_list[i] = NULL; - } - } - mutex_unlock(&box->mutex); - decoder_bmmu_box_mgr_del_box(box); - kfree(box); - return 0; -} -EXPORT_SYMBOL(decoder_bmmu_box_free); - -void *decoder_bmmu_box_get_mem_handle(void *box_handle, int idx) -{ - struct decoder_bmmu_box *box = box_handle; - - if (!box || idx < 0 || idx >= box->max_mm_num) - return NULL; - return box->mm_list[idx]; -} -EXPORT_SYMBOL(decoder_bmmu_box_get_mem_handle); - -int decoder_bmmu_box_get_mem_size(void *box_handle, int idx) -{ - struct decoder_bmmu_box *box = box_handle; - int size = 0; - - if (!box || idx < 0 || idx >= box->max_mm_num) - return 0; - mutex_lock(&box->mutex); - if (box->mm_list[idx] != NULL) - size = box->mm_list[idx]->buffer_size; - mutex_unlock(&box->mutex); - return size; -} - - -unsigned long decoder_bmmu_box_get_phy_addr(void *box_handle, int idx) -{ - struct decoder_bmmu_box *box = box_handle; - struct codec_mm_s *mm; - - if (!box || idx < 0 || idx >= box->max_mm_num) - return 0; - mm = box->mm_list[idx]; - if (!mm) - return 0; - return mm->phy_addr; -} -EXPORT_SYMBOL(decoder_bmmu_box_get_phy_addr); - -void *decoder_bmmu_box_get_virt_addr(void *box_handle, int idx) -{ - struct decoder_bmmu_box *box = box_handle; - struct codec_mm_s *mm; - - if (!box || idx < 0 || idx >= box->max_mm_num) - return NULL; - mm = box->mm_list[idx]; - if (!mm) - return 0; - return codec_mm_phys_to_virt(mm->phy_addr); -} - -/*flags: &0x1 for wait,*/ -int decoder_bmmu_box_check_and_wait_size(int size, int flags) -{ - if ((flags & BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER) && - codec_mm_get_free_size() < size) { - pr_err("CMA force free keep,for size = %d\n", size); - /*need free others? - */ - try_free_keep_video(1); - } - - return codec_mm_enough_for_size(size, - flags & BMMU_ALLOC_FLAGS_WAIT); -} - -int decoder_bmmu_box_alloc_idx_wait( - void *handle, int idx, - int size, int aligned_2n, - int mem_flags, - int wait_flags) -{ - int have_space; - int ret = -1; - int keeped = 0; - - if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) { - struct decoder_bmmu_box *box = handle; - struct codec_mm_s *mm; - mutex_lock(&box->mutex); - mm = box->mm_list[idx]; - keeped = is_codec_mm_keeped(mm); - mutex_unlock(&box->mutex); - - if (!keeped) - return 0;/*have alloced memery before.*/ - } - have_space = decoder_bmmu_box_check_and_wait_size( - size, - wait_flags); - if (have_space) { - ret = decoder_bmmu_box_alloc_idx(handle, - idx, size, aligned_2n, mem_flags); - if (ret == -ENOMEM) { - pr_info("bmmu alloc idx fail, try free keep video.\n"); - try_free_keep_video(1); - } - } else { - try_free_keep_video(1); - ret = -ENOMEM; - } - return ret; -} -EXPORT_SYMBOL(decoder_bmmu_box_alloc_idx_wait); - -int decoder_bmmu_box_alloc_buf_phy( - void *handle, int idx, - int size, unsigned char *driver_name, - unsigned long *buf_phy_addr) -{ - if (!decoder_bmmu_box_check_and_wait_size( - size, - 1)) { - pr_info("%s not enough buf for buf_idx = %d\n", - driver_name, idx); - return -ENOMEM; - } - if (!decoder_bmmu_box_alloc_idx_wait( - handle, - idx, - size, - -1, - -1, - BMMU_ALLOC_FLAGS_WAITCLEAR - )) { - *buf_phy_addr = - decoder_bmmu_box_get_phy_addr( - handle, - idx); - /* - *pr_info("%s malloc buf_idx = %d addr = %ld size = %d\n", - * driver_name, idx, *buf_phy_addr, size); - */ - } else { - pr_info("%s malloc failed %d\n", driver_name, idx); - return -ENOMEM; - } - - return 0; -} -EXPORT_SYMBOL(decoder_bmmu_box_alloc_buf_phy); - -static int decoder_bmmu_box_dump(struct decoder_bmmu_box *box, void *buf, - int size) -{ - char *pbuf = buf; - char sbuf[512]; - int tsize = 0; - int s; - int i; - if (!buf) { - pbuf = sbuf; - size = 512; - } -#define BUFPRINT(args...) \ - do {\ - s = snprintf(pbuf, size - tsize, args);\ - tsize += s;\ - pbuf += s; \ - } while (0) - - for (i = 0; i < box->max_mm_num; i++) { - struct codec_mm_s *mm = box->mm_list[i]; - if (buf && (size - tsize) < 256) { - BUFPRINT("\n\t**NOT END**\n"); - break; - } - if (mm) { - BUFPRINT("code mem[%d]:%p, addr=%p, size=%d,from=%d\n", - i, - (void *)mm, - (void *)mm->phy_addr, - mm->buffer_size, - mm->from_flags); - if (!buf) { - pr_info("%s", sbuf); - pbuf = sbuf; - } - } - } -#undef BUFPRINT - - return tsize; -} - -static int decoder_bmmu_box_dump_all(void *buf, int size) -{ - struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); - char *pbuf = buf; - char sbuf[512]; - int tsize = 0; - int s; - int i; - struct list_head *head, *list; - if (!buf) { - pbuf = sbuf; - size = 512; - } -#define BUFPRINT(args...) \ - do {\ - s = snprintf(pbuf, size - tsize, args);\ - tsize += s;\ - pbuf += s; \ - } while (0) - - mutex_lock(&mgr->mutex); - head = &mgr->box_list; - list = head->next; - i = 0; - while (list != head) { - struct decoder_bmmu_box *box; - - box = list_entry(list, struct decoder_bmmu_box, list); - BUFPRINT("box[%d]: %s, %splayer_id:%d, max_num:%d, size:%d\n", - i, box->name, - (box->mem_flags & CODEC_MM_FLAGS_TVP) ? - "TVP mode " : "", - box->channel_id, - box->max_mm_num, - box->total_size); - if (buf) { - s = decoder_bmmu_box_dump(box, pbuf, size - tsize); - if (s > 0) { - tsize += s; - pbuf += s; - } - } else { - pr_info("%s", sbuf); - pbuf = sbuf; - tsize += decoder_bmmu_box_dump(box, NULL, 0); - } - list = list->next; - i++; - } - mutex_unlock(&mgr->mutex); - -#undef BUFPRINT - if (!buf) - pr_info("%s", sbuf); - return tsize; -} - -static ssize_t box_dump_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - ssize_t ret = 0; - - ret = decoder_bmmu_box_dump_all(buf, PAGE_SIZE); - return ret; -} - -static ssize_t box_debug_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - ssize_t size = 0; - size += sprintf(buf, "box debug help:\n"); - size += sprintf(buf + size, "echo n > debug\n"); - size += sprintf(buf + size, "n==0: clear all debugs)\n"); - size += sprintf(buf + size, - "n=1: dump all box\n"); - - return size; -} - - -static ssize_t box_debug_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned val; - ssize_t ret; - val = -1; - ret = sscanf(buf, "%d", &val); - if (ret != 1) - return -EINVAL; - switch (val) { - case 1: - decoder_bmmu_box_dump_all(NULL , 0); - break; - default: - pr_err("unknow cmd! %d\n", val); - } - return size; - -} - - - -static struct class_attribute decoder_bmmu_box_class_attrs[] = { - __ATTR_RO(box_dump), - __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP, - box_debug_show, box_debug_store), - __ATTR_NULL -}; - -static struct class decoder_bmmu_box_class = { - .name = "decoder_bmmu_box", - .class_attrs = decoder_bmmu_box_class_attrs, - }; - -int decoder_bmmu_box_init(void) -{ - int r; - - memset(&global_blk_mgr, 0, sizeof(global_blk_mgr)); - INIT_LIST_HEAD(&global_blk_mgr.box_list); - mutex_init(&global_blk_mgr.mutex); - r = class_register(&decoder_bmmu_box_class); - return r; -} -EXPORT_SYMBOL(decoder_bmmu_box_init); - -void decoder_bmmu_box_exit(void) -{ - class_unregister(&decoder_bmmu_box_class); - pr_info("dec bmmu box exit.\n"); -} - -#if 0 -static int __init decoder_bmmu_box_init(void) -{ - int r; - - memset(&global_blk_mgr, 0, sizeof(global_blk_mgr)); - INIT_LIST_HEAD(&global_blk_mgr.box_list); - mutex_init(&global_blk_mgr.mutex); - r = class_register(&decoder_bmmu_box_class); - return r; -} - -module_init(decoder_bmmu_box_init); -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h deleted file mode 100644 index 8744da147cef..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * drivers/amlogic/amports/decoder/decoder_bmmu_box.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef DECODER_BLOCK_BUFFER_BOX -#define DECODER_BLOCK_BUFFER_BOX - -void *decoder_bmmu_box_alloc_box(const char *name, - int channel_id, - int max_num, - int aligned, - int mem_flags); - -int decoder_bmmu_box_alloc_idx( - void *handle, int idx, int size, - int aligned_2n, int mem_flags); - -int decoder_bmmu_box_free_idx(void *handle, int idx); -int decoder_bmmu_box_free(void *handle); -void *decoder_bmmu_box_get_mem_handle( - void *box_handle, int idx); - -unsigned long decoder_bmmu_box_get_phy_addr( - void *box_handle, int idx); - -void *decoder_bmmu_box_get_virt_addr( - void *box_handle, int idx); - -/*flags: &0x1 for wait,*/ -int decoder_bmmu_box_check_and_wait_size( - int size, int flags); - -int decoder_bmmu_box_alloc_buf_phy( - void *handle, int idx, - int size, unsigned char *driver_name, - unsigned long *buf_phy_addr); - -#define BMMU_ALLOC_FLAGS_WAIT (1 << 0) -#define BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER (1 << 1) -#define BMMU_ALLOC_FLAGS_WAITCLEAR \ - (BMMU_ALLOC_FLAGS_WAIT |\ - BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER) - -int decoder_bmmu_box_alloc_idx_wait( - void *handle, int idx, - int size, int aligned_2n, - int mem_flags, - int wait_flags); - -int decoder_bmmu_box_init(void); -void decoder_bmmu_box_exit(void); - -#endif - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c deleted file mode 100644 index cc9e7a906666..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/decoder_mmu_box.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -struct decoder_mmu_box { - int max_sc_num; - const char *name; - int channel_id; - int tvp_mode; - struct mutex mutex; - struct list_head list; - struct codec_mm_scatter *sc_list[1]; -}; -#define MAX_KEEP_FRAME 4 -#define START_KEEP_ID 0x9 -#define MAX_KEEP_ID (INT_MAX - 1) -struct decoder_mmu_box_mgr { - int num; - struct mutex mutex; - struct codec_mm_scatter *keep_sc[MAX_KEEP_FRAME]; - int keep_id[MAX_KEEP_FRAME]; - int next_id;/*id for keep & free.*/ - struct list_head box_list; -}; -static struct decoder_mmu_box_mgr global_mgr; -static struct decoder_mmu_box_mgr *get_decoder_mmu_box_mgr(void) -{ - return &global_mgr; -} - -static int decoder_mmu_box_mgr_add_box(struct decoder_mmu_box *box) -{ - struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); - - mutex_lock(&mgr->mutex); - list_add_tail(&box->list, &mgr->box_list); - mutex_unlock(&mgr->mutex); - return 0; -} - -static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box) -{ - struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); - - mutex_lock(&mgr->mutex); - list_del(&box->list); - mutex_unlock(&mgr->mutex); - return 0; -} - -int decoder_mmu_box_sc_check(void *handle, int is_tvp) -{ - struct decoder_mmu_box *box = handle; - if (!box) { - pr_err("mmu box NULL !!!\n"); - return 0; - } - return codec_mm_scatter_size(is_tvp); -} -EXPORT_SYMBOL(decoder_mmu_box_sc_check); - - -void *decoder_mmu_box_alloc_box(const char *name, - int channel_id, - int max_num, - int min_size_M, - int mem_flags) -/*min_size_M:wait alloc this size*/ -{ - struct decoder_mmu_box *box; - int size; - - pr_debug("decoder_mmu_box_alloc_box, mem_flags = 0x%x\n", mem_flags); - - size = sizeof(struct decoder_mmu_box) + - sizeof(struct codec_mm_scatter *) * - max_num; - box = kmalloc(size, GFP_KERNEL); - if (!box) { - pr_err("can't alloc decoder buffers box!!!\n"); - return NULL; - } - memset(box, 0, size); - box->max_sc_num = max_num; - box->name = name; - box->channel_id = channel_id; - box->tvp_mode = mem_flags; - - mutex_init(&box->mutex); - INIT_LIST_HEAD(&box->list); - decoder_mmu_box_mgr_add_box(box); - codec_mm_scatter_mgt_delay_free_swith(1, 2000, - min_size_M, box->tvp_mode); - return (void *)box; -} -EXPORT_SYMBOL(decoder_mmu_box_alloc_box); - -int decoder_mmu_box_alloc_idx( - void *handle, int idx, int num_pages, - unsigned int *mmu_index_adr) -{ - struct decoder_mmu_box *box = handle; - struct codec_mm_scatter *sc; - int ret; - int i; - - if (!box || idx < 0 || idx >= box->max_sc_num) { - pr_err("can't alloc mmu box(%p),idx:%d\n", - box, idx); - return -1; - } - mutex_lock(&box->mutex); - sc = box->sc_list[idx]; - if (sc) { - if (sc->page_max_cnt >= num_pages) - ret = codec_mm_scatter_alloc_want_pages(sc, - num_pages); - else { - codec_mm_scatter_dec_owner_user(sc, 0); - box->sc_list[idx] = NULL; - sc = NULL; - } - - } - if (!sc) { - sc = codec_mm_scatter_alloc(num_pages + 64, num_pages, - box->tvp_mode); - if (!sc) { - mutex_unlock(&box->mutex); - pr_err("alloc mmu failed, need pages=%d\n", - num_pages); - return -1; - } - box->sc_list[idx] = sc; - } - - for (i = 0; i < num_pages; i++) - mmu_index_adr[i] = PAGE_INDEX(sc->pages_list[i]); - - mutex_unlock(&box->mutex); - - return 0; -} -EXPORT_SYMBOL(decoder_mmu_box_alloc_idx); - -int decoder_mmu_box_free_idx_tail( - void *handle, int idx, - int start_release_index) -{ - struct decoder_mmu_box *box = handle; - struct codec_mm_scatter *sc; - - if (!box || idx < 0 || idx >= box->max_sc_num) { - pr_err("can't free tail mmu box(%p),idx:%d in (%d-%d)\n", - box, idx, 0, - box ? (box->max_sc_num - 1) : 0); - return -1; - } - mutex_lock(&box->mutex); - sc = box->sc_list[idx]; - if (sc && start_release_index < sc->page_cnt) - codec_mm_scatter_free_tail_pages_fast(sc, - start_release_index); - mutex_unlock(&box->mutex); - return 0; -} -EXPORT_SYMBOL(decoder_mmu_box_free_idx_tail); - -int decoder_mmu_box_free_idx(void *handle, int idx) -{ - struct decoder_mmu_box *box = handle; - struct codec_mm_scatter *sc; - - if (!box || idx < 0 || idx >= box->max_sc_num) { - pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", - box, idx, 0, - box ? (box->max_sc_num - 1) : 0); - return -1; - } - mutex_lock(&box->mutex); - sc = box->sc_list[idx]; - if (sc && sc->page_cnt > 0) { - codec_mm_scatter_dec_owner_user(sc, 0); - box->sc_list[idx] = NULL; - } mutex_unlock(&box->mutex); - return 0; -} -EXPORT_SYMBOL(decoder_mmu_box_free_idx); - -int decoder_mmu_box_free(void *handle) -{ - struct decoder_mmu_box *box = handle; - struct codec_mm_scatter *sc; - int i; - - if (!box) { - pr_err("can't free box of NULL box!\n"); - return -1; - } - mutex_lock(&box->mutex); - for (i = 0; i < box->max_sc_num; i++) { - sc = box->sc_list[i]; - if (sc) { - codec_mm_scatter_dec_owner_user(sc, 200); - box->sc_list[i] = NULL; - } - } - mutex_unlock(&box->mutex); - decoder_mmu_box_mgr_del_box(box); - codec_mm_scatter_mgt_delay_free_swith(0, 2000, 0, box->tvp_mode); - kfree(box); - return 0; -} -EXPORT_SYMBOL(decoder_mmu_box_free); - -void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx) -{ - struct decoder_mmu_box *box = box_handle; - - if (!box || idx < 0 || idx >= box->max_sc_num) - return NULL; - return box->sc_list[idx]; -} -EXPORT_SYMBOL(decoder_mmu_box_get_mem_handle); - -static int decoder_mmu_box_dump(struct decoder_mmu_box *box, - void *buf, int size) -{ - char *pbuf = buf; - char sbuf[512]; - int tsize = 0; - int s; - int i; - - if (!buf) { - pbuf = sbuf; - size = 512; - } - #define BUFPRINT(args...) \ - do {\ - s = snprintf(pbuf, size - tsize, args);\ - tsize += s;\ - pbuf += s; \ - } while (0) - - for (i = 0; i < box->max_sc_num; i++) { - struct codec_mm_scatter *sc = box->sc_list[i]; - - if (sc) { - BUFPRINT("sc mem[%d]:%p, size=%d\n", - i, sc, - sc->page_cnt << PAGE_SHIFT); - } - } -#undef BUFPRINT - if (!buf) - pr_info("%s", sbuf); - - return tsize; -} - -static int decoder_mmu_box_dump_all(void *buf, int size) -{ - struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); - char *pbuf = buf; - char sbuf[512]; - int tsize = 0; - int s; - int i; - struct list_head *head, *list; - - if (!pbuf) { - pbuf = sbuf; - size = 512; - } - - #define BUFPRINT(args...) \ - do {\ - s = snprintf(pbuf, size - tsize, args);\ - tsize += s;\ - pbuf += s; \ - } while (0) - - mutex_lock(&mgr->mutex); - head = &mgr->box_list; - list = head->next; - i = 0; - while (list != head) { - struct decoder_mmu_box *box; - box = list_entry(list, struct decoder_mmu_box, - list); - BUFPRINT("box[%d]: %s, %splayer_id:%d, max_num:%d\n", - i, - box->name, - box->tvp_mode ? "TVP mode " : "", - box->channel_id, - box->max_sc_num); - if (buf) { - s += decoder_mmu_box_dump(box, pbuf, size - tsize); - if (s > 0) { - tsize += s; - pbuf += s; - } - } else { - pr_info("%s", sbuf); - pbuf = sbuf; - tsize += decoder_mmu_box_dump(box, NULL, 0); - } - list = list->next; - i++; - } - mutex_unlock(&mgr->mutex); - - -#undef BUFPRINT - if (!buf) - pr_info("%s", sbuf); - return tsize; -} - - - -static ssize_t -box_dump_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - ssize_t ret = 0; - - ret = decoder_mmu_box_dump_all(buf, PAGE_SIZE); - return ret; -} - - - -static struct class_attribute decoder_mmu_box_class_attrs[] = { - __ATTR_RO(box_dump), - __ATTR_NULL -}; - -static struct class decoder_mmu_box_class = { - .name = "decoder_mmu_box", - .class_attrs = decoder_mmu_box_class_attrs, -}; - -int decoder_mmu_box_init(void) -{ - int r; - - memset(&global_mgr, 0, sizeof(global_mgr)); - INIT_LIST_HEAD(&global_mgr.box_list); - mutex_init(&global_mgr.mutex); - global_mgr.next_id = START_KEEP_ID; - r = class_register(&decoder_mmu_box_class); - return r; -} -EXPORT_SYMBOL(decoder_mmu_box_init); - -void decoder_mmu_box_exit(void) -{ - class_unregister(&decoder_mmu_box_class); - pr_info("dec mmu box exit.\n"); -} - -#if 0 -static int __init decoder_mmu_box_init(void) -{ - int r; - - memset(&global_mgr, 0, sizeof(global_mgr)); - INIT_LIST_HEAD(&global_mgr.box_list); - mutex_init(&global_mgr.mutex); - global_mgr.next_id = START_KEEP_ID; - r = class_register(&decoder_mmu_box_class); - return r; -} - -module_init(decoder_mmu_box_init); -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h deleted file mode 100644 index 9f4e0987567b..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/decoder_mmu_box.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef DECODER_BUFFER_BOX -#define DECODER_BUFFER_BOX - -void *decoder_mmu_box_alloc_box(const char *name, - int channel_id, - int max_num, - int min_size_M, - int mem_flags); - -int decoder_mmu_box_sc_check(void *handle, int is_tvp); - -int decoder_mmu_box_alloc_idx( - void *handle, int idx, int num_pages, - unsigned int *mmu_index_adr); - -int decoder_mmu_box_free_idx_tail(void *handle, int idx, - int start_release_index); - -int decoder_mmu_box_free_idx(void *handle, int idx); - -int decoder_mmu_box_free(void *handle); - -int decoder_mmu_box_move_keep_idx(void *box_handle, - int keep_idx); -int decoder_mmu_box_free_keep(int keep_id); -int decoder_mmu_box_free_all_keep(void); -void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx); -int decoder_mmu_box_init(void); -void decoder_mmu_box_exit(void); - -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h deleted file mode 100644 index c799fd091a3a..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __VIDEO_FIRMWARE_HEADER_ -#define __VIDEO_FIRMWARE_HEADER_ - -#include "../../../common/firmware/firmware_type.h" -#include - -#define FW_LOAD_FORCE (0x1) -#define FW_LOAD_TRY (0X2) - -struct firmware_s { - char name[32]; - unsigned int len; - char data[0]; -}; - -extern int get_decoder_firmware_data(enum vformat_e type, - const char *file_name, char *buf, int size); -extern int get_data_from_name(const char *name, char *buf); -extern int get_firmware_data(unsigned int foramt, char *buf); -extern int video_fw_reload(int mode); - -#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c deleted file mode 100644 index e783dbc41ae0..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c +++ /dev/null @@ -1,1161 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "vdec.h" -#include "frame_check.h" -#include "amlogic_fbc_hook.h" -#include -#include -#include "../../../common/chips/decoder_cpu_ver_info.h" - - -#define FC_ERROR 0x0 - -#define FC_YUV_DEBUG 0x01 -#define FC_CRC_DEBUG 0x02 -#define FC_TST_DEBUG 0x80 -#define FC_ERR_CRC_BLOCK_MODE 0x10 -#define FC_CHECK_CRC_LOOP_MODE 0x20 - -#define YUV_MASK 0x01 -#define CRC_MASK 0x02 - -#define YUV_DEF_SIZE (1920*1088*3/2) -#define YUV_DEF_NUM 1 - -#define MAX_SIZE_AFBC_PLANES (4096 * 2048) - -#define VMAP_STRIDE_SIZE (1024*1024) - -static unsigned int fc_debug; -static unsigned int size_yuv_buf = (YUV_DEF_SIZE * YUV_DEF_NUM); - -#define dbg_print(mask, ...) do { \ - if ((fc_debug & mask) || \ - (mask == FC_ERROR)) \ - printk("[FRMAE_CHECK] "__VA_ARGS__);\ - } while(0) - - -#define CRC_PATH "/data/tmp/" -#define YUV_PATH "/data/tmp/" -static char comp_crc[128] = "name"; - -static struct vdec_s *single_mode_vdec = NULL; - -static unsigned int yuv_enable, check_enable; -static unsigned int yuv_start[MAX_INSTANCE_MUN]; -static unsigned int yuv_num[MAX_INSTANCE_MUN]; - - -static inline void set_enable(struct pic_check_mgr_t *p, int mask) -{ - p->enable |= mask; -} - -static inline void set_disable(struct pic_check_mgr_t *p, int mask) -{ - p->enable &= (~mask); -} - -static inline void check_schedule(struct pic_check_mgr_t *mgr) -{ - if (atomic_read(&mgr->work_inited)) - vdec_schedule_work(&mgr->frame_check_work); -} - -static int get_frame_size(struct pic_check_mgr_t *pic, - struct vframe_s *vf) -{ - if ((vf->width < 1) || (vf->height < 1)) - return -1; - pic->size_y = vf->width* vf->height; - pic->size_uv = pic->size_y >> 1; - pic->size_pic = pic->size_y + pic->size_uv; - - if (!(vf->type & VIDTYPE_VIU_NV21)) - return 0; - - if ((vf->canvas0Addr == vf->canvas1Addr) && - (vf->canvas0Addr != 0) && - (vf->canvas0Addr != -1)) { - pic->canvas_w = - canvas_get_width(canvasY(vf->canvas0Addr)); - pic->canvas_h = - canvas_get_height(canvasY(vf->canvas0Addr)); - } else { - pic->canvas_w = vf->canvas0_config[0].width; - pic->canvas_h = vf->canvas0_config[1].height; - } - - if ((pic->canvas_h < 1) || (pic->canvas_w < 1)) { - dbg_print(FC_ERROR, "(canvas,pic) w(%d,%d), h(%d,%d)\n", - pic->canvas_w, vf->width, pic->canvas_h, vf->height); - return -1; - } -/* - int blkmod; - blkmod = canvas_get_blkmode(canvasY(vf->canvas0Addr)); - if (blkmod != CANVAS_BLKMODE_LINEAR) { - dbg_print(0, "WARN: canvas blkmod %x\n", blkmod); - } -*/ - return 0; -} - -static int canvas_get_virt_addr(struct pic_check_mgr_t *pic, - struct vframe_s *vf) -{ - int phy_y_addr, phy_uv_addr; - void *vaddr_y, *vaddr_uv; - - if ((vf->canvas0Addr == vf->canvas1Addr) && - (vf->canvas0Addr != 0) && - (vf->canvas0Addr != -1)) { - phy_y_addr = canvas_get_addr(canvasY(vf->canvas0Addr)); - phy_uv_addr = canvas_get_addr(canvasUV(vf->canvas0Addr)); - } else { - phy_y_addr = vf->canvas0_config[0].phy_addr; - phy_uv_addr = vf->canvas0_config[1].phy_addr; - } - vaddr_y = codec_mm_phys_to_virt(phy_y_addr); - vaddr_uv = codec_mm_phys_to_virt(phy_uv_addr); - - if (((!vaddr_y) || (!vaddr_uv)) && ((!phy_y_addr) || (!phy_uv_addr))) { - dbg_print(FC_ERROR, "%s, y_addr %p(0x%x), uv_addr %p(0x%x)\n", - __func__, vaddr_y, phy_y_addr, vaddr_uv, phy_uv_addr); - return -1; - } - pic->y_vaddr = vaddr_y; - pic->uv_vaddr = vaddr_uv; - pic->y_phyaddr = phy_y_addr; - pic->uv_phyaddr = phy_uv_addr; - - return 0; -} - -static int str_strip(char *str) -{ - char *s = str; - int i = 0; - - while (s[i]) { - if (s[i] == '\n') - s[i] = 0; - else if (s[i] == ' ') - s[i] = '_'; - i++; - } - - return i; -} - -static char *fget_crc_str(char *buf, - unsigned int size, struct pic_check_t *fc) -{ - unsigned int c = 0, sz, ret, index, crc1, crc2; - mm_segment_t old_fs; - char *cs; - - if (!fc->compare_fp) - return NULL; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - do { - cs = buf; - sz = size; - while (--sz && (c = vfs_read(fc->compare_fp, - cs, 1, &fc->compare_pos) != 0)) { - if (*cs++ == '\n') - break; - } - *cs = '\0'; - if ((c == 0) && (cs == buf)) { - set_fs(old_fs); - return NULL; - } - ret = sscanf(buf, "%08u: %8x %8x", &index, &crc1, &crc2); - dbg_print(FC_CRC_DEBUG, "%s, index = %d, cmp = %d\n", - __func__, index, fc->cmp_crc_cnt); - }while(ret != 3 || index != fc->cmp_crc_cnt); - - set_fs(old_fs); - fc->cmp_crc_cnt++; - - return buf; -} - -static struct file* file_open(int mode, const char *str, ...) -{ - char file[256] = {0}; - struct file* fp = NULL; - va_list args; - - va_start(args, str); - vsnprintf(file, sizeof(file), str, args); - - fp = filp_open(file, mode, (mode&O_CREAT)?0666:0); - if (IS_ERR(fp)) { - fp = NULL; - dbg_print(FC_ERROR, "open %s failed\n", file); - return fp; - } - dbg_print(FC_ERROR, "open %s success\n", file); - va_end(args); - - return fp; -} - -static int write_yuv_work(struct pic_check_mgr_t *mgr) -{ - mm_segment_t old_fs; - unsigned int i, wr_size; - struct pic_dump_t *dump = &mgr->pic_dump; - - if (dump->dump_cnt > 0) { - if (!dump->yuv_fp) { - dump->yuv_fp = file_open(O_CREAT | O_WRONLY | O_TRUNC, - "%s%s-%d-%d.yuv", YUV_PATH, comp_crc, mgr->id, mgr->file_cnt); - dump->yuv_pos = 0; - } - - if ((mgr->enable & YUV_MASK) && - (dump->yuv_fp != NULL) && - (dump->dump_cnt >= dump->num)) { - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - for (i = 0; dump->dump_cnt > 0; i++) { - wr_size = vfs_write(dump->yuv_fp, - (dump->buf_addr + i * mgr->size_pic), - mgr->size_pic, &dump->yuv_pos); - if (mgr->size_pic != wr_size) { - dbg_print(FC_ERROR, "buf failed to write yuv file\n"); - break; - } - dump->dump_cnt--; - } - set_fs(old_fs); - vfs_fsync(dump->yuv_fp, 0); - - filp_close(dump->yuv_fp, current->files); - dump->yuv_pos = 0; - dump->yuv_fp = NULL; - set_disable(mgr, YUV_MASK); - dbg_print(FC_YUV_DEBUG, - "closed yuv file, dump yuv exit\n"); - dump->num = 0; - dump->dump_cnt = 0; - if (dump->buf_addr != NULL) - vfree(dump->buf_addr); - dump->buf_addr = NULL; - dump->buf_size = 0; - } - } - - return 0; -} - -static int write_crc_work(struct pic_check_mgr_t *mgr) -{ - unsigned int wr_size; - char *crc_buf, crc_tmp[64*30]; - mm_segment_t old_fs; - struct pic_check_t *check = &mgr->pic_check; - - if (mgr->enable & CRC_MASK) { - wr_size = 0; - while (kfifo_get(&check->wr_chk_q, &crc_buf) != 0) { - wr_size += sprintf(&crc_tmp[wr_size], "%s", crc_buf); - if (check->compare_fp != NULL) { - if (!fget_crc_str(crc_buf, SIZE_CRC, check)) { - dbg_print(0, "%s, can't get more compare crc\n", __func__); - filp_close(check->compare_fp, current->files); - check->compare_fp = NULL; - } - } - kfifo_put(&check->new_chk_q, crc_buf); - } - if (check->check_fp && (wr_size != 0)) { - old_fs = get_fs(); - set_fs(KERNEL_DS); - if (wr_size != vfs_write(check->check_fp, - crc_tmp, wr_size, &check->check_pos)) { - dbg_print(FC_ERROR, "failed to check_dump_filp\n"); - } - set_fs(old_fs); - } - } - return 0; -} - -static void do_check_work(struct work_struct *work) -{ - struct pic_check_mgr_t *mgr = container_of(work, - struct pic_check_mgr_t, frame_check_work); - - write_yuv_work(mgr); - - write_crc_work(mgr); -} - -static int memcpy_phy_to_virt(char *to_virt, - ulong phy_from, unsigned int size) -{ - void *vaddr = NULL; - unsigned int tmp_size = 0; - - if (single_mode_vdec != NULL) { - unsigned int offset = phy_from & (~PAGE_MASK); - while (size > 0) { - if (offset + size >= PAGE_SIZE) { - vaddr = kmap_atomic(phys_to_page(phy_from)); - tmp_size = (PAGE_SIZE - offset); - phy_from += tmp_size; - size -= tmp_size; - vaddr += offset; - } else { - vaddr = kmap_atomic(phys_to_page(phy_from)); - vaddr += offset; - tmp_size = size; - size = 0; - } - if (vaddr == NULL) { - dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n", - __func__, (unsigned int)phy_from); - return -1; - } - /* - codec_mm_dma_flush(vaddr, - tmp_size, DMA_FROM_DEVICE); - */ - memcpy(to_virt, vaddr, tmp_size); - - kunmap_atomic(vaddr - offset); - offset = 0; - } - } else { - while (size > 0) { - if (size >= VMAP_STRIDE_SIZE) { - vaddr = codec_mm_vmap(phy_from, VMAP_STRIDE_SIZE); - tmp_size = VMAP_STRIDE_SIZE; - phy_from += VMAP_STRIDE_SIZE; - size -= VMAP_STRIDE_SIZE; - } else { - vaddr = codec_mm_vmap(phy_from, size); - tmp_size = size; - size = 0; - } - if (vaddr == NULL) { - dbg_print(FC_YUV_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n", - __func__, (unsigned int)phy_from); - return -1; - } - codec_mm_dma_flush(vaddr, - tmp_size, DMA_FROM_DEVICE); - memcpy(to_virt, vaddr, tmp_size); - to_virt += tmp_size; - - codec_mm_unmap_phyaddr(vaddr); - } - } - return 0; -} - -static int do_yuv_dump(struct pic_check_mgr_t *mgr, struct vframe_s *vf) -{ - int i, ret = 0; - void *tmp_addr, *tmp_yaddr, *tmp_uvaddr; - ulong y_phyaddr, uv_phyaddr; - struct pic_dump_t *dump = &mgr->pic_dump; - /* - if ((vf->type & VIDTYPE_VIU_NV21) == 0) - return 0; - */ - if (dump->start > 0) { - dump->start--; - return 0; - } - - if (dump->dump_cnt >= dump->num) - return 0; - - if (mgr->size_pic > - (dump->buf_size - dump->dump_cnt * mgr->size_pic)) { - if (dump->buf_size) { - dbg_print(FC_ERROR, - "not enough buf, force dump less\n"); - dump->num = dump->dump_cnt; - check_schedule(mgr); - } else - set_disable(mgr, YUV_MASK); - return -1; - } - - tmp_addr = dump->buf_addr + - mgr->size_pic * dump->dump_cnt; - if ((mgr->uv_vaddr == NULL) || (mgr->y_vaddr == NULL)) { - y_phyaddr = mgr->y_phyaddr; - uv_phyaddr = mgr->uv_phyaddr; - if (vf->width == mgr->canvas_w) { - ret |= memcpy_phy_to_virt(tmp_addr, y_phyaddr, mgr->size_y); - ret |= memcpy_phy_to_virt(tmp_addr + mgr->size_y, - uv_phyaddr, mgr->size_uv); - } else { - for (i = 0; i < vf->height; i++) { - ret |= memcpy_phy_to_virt(tmp_addr, y_phyaddr, vf->width); - y_phyaddr += mgr->canvas_w; - tmp_addr += vf->width; - } - for (i = 0; i < vf->height/2; i++) { - ret |= memcpy_phy_to_virt(tmp_addr, uv_phyaddr, vf->width); - uv_phyaddr += mgr->canvas_w; - tmp_addr += vf->width; - } - } - if (ret < 0) { - dbg_print(0, "dump yuv failed, may codec_mm_vmap failed\n"); - return ret; - } - } else { - if (vf->width == mgr->canvas_w) { - memcpy(tmp_addr, mgr->y_vaddr, mgr->size_y); - memcpy(tmp_addr + mgr->size_y, - mgr->uv_vaddr, mgr->size_uv); - } else { - tmp_yaddr = mgr->y_vaddr; - tmp_uvaddr = mgr->uv_vaddr; - for (i = 0; i < vf->height; i++) { - memcpy(tmp_addr, tmp_yaddr, vf->width); - tmp_yaddr += mgr->canvas_w; - tmp_addr += vf->width; - } - for (i = 0; i < vf->height/2; i++) { - memcpy(tmp_addr, tmp_uvaddr, vf->width); - tmp_uvaddr += mgr->canvas_w; - tmp_addr += vf->width; - } - } - } - dump->dump_cnt++; - dbg_print(0, "----->dump frame num: %d, dump %dst, size %x\n", - mgr->frame_cnt, dump->dump_cnt, mgr->size_pic); - - if (dump->dump_cnt >= dump->num) - check_schedule(mgr); - - return 0; -} - -static int crc_store(struct pic_check_mgr_t *mgr, struct vframe_s *vf, - int crc_y, int crc_uv) -{ - int ret = 0; - char *crc_addr = NULL; - int comp_frame = 0, comp_crc_y, comp_crc_uv; - struct pic_check_t *check = &mgr->pic_check; - - if (kfifo_get(&check->new_chk_q, &crc_addr) == 0) { - dbg_print(0, "%08d: %08x %08x\n", - mgr->frame_cnt, crc_y, crc_uv); - if (check->check_fp) { - dbg_print(0, "crc32 dropped\n"); - } else { - dbg_print(0, "no opened file to write crc32\n"); - } - return -1; - } - if (check->cmp_crc_cnt > mgr->frame_cnt) { - sscanf(crc_addr, "%08u: %8x %8x", - &comp_frame, &comp_crc_y, &comp_crc_uv); - - dbg_print(0, "%08d: %08x %08x <--> %08d: %08x %08x\n", - mgr->frame_cnt, crc_y, crc_uv, - comp_frame, comp_crc_y, comp_crc_uv); - - if (comp_frame == mgr->frame_cnt) { - if ((comp_crc_y != crc_y) || (crc_uv != comp_crc_uv)) { - mgr->pic_dump.start = 0; - mgr->pic_dump.num++; - dbg_print(0, "\n\nError: %08d: %08x %08x != %08x %08x\n\n", - mgr->frame_cnt, crc_y, crc_uv, comp_crc_y, comp_crc_uv); - do_yuv_dump(mgr, vf); - if (fc_debug & FC_ERR_CRC_BLOCK_MODE) - mgr->err_crc_block = 1; - } - } else { - dbg_print(0, "frame num error: frame_cnt(%d) frame_comp(%d)\n", - mgr->frame_cnt, comp_frame); - } - } else { - dbg_print(0, "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv); - } - - if ((check->check_fp) && (crc_addr != NULL)) { - ret = snprintf(crc_addr, SIZE_CRC, - "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv); - - kfifo_put(&check->wr_chk_q, crc_addr); - if ((mgr->frame_cnt & 0xf) == 0) - check_schedule(mgr); - } - return ret; -} - - -static int crc32_vmap_le(unsigned int *crc32, - ulong phyaddr, unsigned int size) -{ - void *vaddr = NULL; - unsigned int crc = 0; - unsigned int tmp_size = 0; - - /*single mode cannot use codec_mm_vmap*/ - if (single_mode_vdec != NULL) { - unsigned int offset = phyaddr & (~PAGE_MASK); - while (size > 0) { - if (offset + size >= PAGE_SIZE) { - vaddr = kmap_atomic(phys_to_page(phyaddr)); - tmp_size = (PAGE_SIZE - offset); - phyaddr += tmp_size; - size -= tmp_size; - vaddr += offset; - } else { - vaddr = kmap_atomic(phys_to_page(phyaddr)); - tmp_size = size; - vaddr += offset; - size = 0; - } - if (vaddr == NULL) { - dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n", - __func__, (unsigned int)phyaddr); - return -1; - } - /* - codec_mm_dma_flush(vaddr, - tmp_size, DMA_FROM_DEVICE); - */ - crc = crc32_le(crc, vaddr, tmp_size); - - kunmap_atomic(vaddr - offset); - offset = 0; - } - } else { - while (size > 0) { - if (size >= VMAP_STRIDE_SIZE) { - vaddr = codec_mm_vmap(phyaddr, VMAP_STRIDE_SIZE); - tmp_size = VMAP_STRIDE_SIZE; - phyaddr += VMAP_STRIDE_SIZE; - size -= VMAP_STRIDE_SIZE; - } else { - vaddr = codec_mm_vmap(phyaddr, size); - tmp_size = size; - size = 0; - } - if (vaddr == NULL) { - dbg_print(FC_CRC_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n", - __func__, (unsigned int)phyaddr); - return -1; - } - codec_mm_dma_flush(vaddr, - tmp_size, DMA_FROM_DEVICE); - - crc = crc32_le(crc, vaddr, tmp_size); - - codec_mm_unmap_phyaddr(vaddr); - } - } - *crc32 = crc; - - return 0; -} - -static int do_check_nv21(struct pic_check_mgr_t *mgr, struct vframe_s *vf) -{ - int i; - unsigned int crc_y = 0, crc_uv = 0; - void *p_yaddr, *p_uvaddr; - ulong y_phyaddr, uv_phyaddr; - int ret = 0; - - p_yaddr = mgr->y_vaddr; - p_uvaddr = mgr->uv_vaddr; - y_phyaddr = mgr->y_phyaddr; - uv_phyaddr = mgr->uv_phyaddr; - if ((p_yaddr == NULL) || (p_uvaddr == NULL)) - { - if (vf->width == mgr->canvas_w) { - ret = crc32_vmap_le(&crc_y, y_phyaddr, mgr->size_y); - ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, mgr->size_uv); - } else { - for (i = 0; i < vf->height; i++) { - ret |= crc32_vmap_le(&crc_y, y_phyaddr, vf->width); - y_phyaddr += mgr->canvas_w; - } - for (i = 0; i < vf->height/2; i++) { - ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, vf->width); - uv_phyaddr += mgr->canvas_w; - } - } - if (ret < 0) { - dbg_print(0, "calc crc failed, may codec_mm_vmap failed\n"); - return ret; - } - } else { - if (mgr->frame_cnt == 0) { - unsigned int *p = mgr->y_vaddr; - dbg_print(0, "YUV0000: %08x-%08x-%08x-%08x\n", - p[0], p[1], p[2], p[3]); - } - if (vf->width == mgr->canvas_w) { - crc_y = crc32_le(crc_y, p_yaddr, mgr->size_y); - crc_uv = crc32_le(crc_uv, p_uvaddr, mgr->size_uv); - } else { - for (i = 0; i < vf->height; i++) { - crc_y = crc32_le(crc_y, p_yaddr, vf->width); - p_yaddr += mgr->canvas_w; - } - for (i = 0; i < vf->height/2; i++) { - crc_uv = crc32_le(crc_uv, p_uvaddr, vf->width); - p_uvaddr += mgr->canvas_w; - } - } - } - - crc_store(mgr, vf, crc_y, crc_uv); - - return 0; -} - -static int do_check_yuv16(struct pic_check_mgr_t *mgr, - struct vframe_s *vf, char *ybuf, char *uvbuf, - char *ubuf, char *vbuf) -{ - unsigned int crc1, crc2, crc3, crc4; - int w, h; - - w = vf->width; - h = vf->height; - crc1 = 0; - crc2 = 0; - crc3 = 0; - crc4 = 0; - - crc1 = crc32_le(0, ybuf, w * h *2); - crc2 = crc32_le(0, ubuf, w * h/2); - crc3 = crc32_le(0, vbuf, w * h/2); - crc4 = crc32_le(0, uvbuf, w * h*2/2); - /* - printk("%08d: %08x %08x %08x %08x\n", - mgr->frame_cnt, crc1, crc4, crc2, crc3); - */ - mgr->size_y = w * h * 2; - mgr->size_uv = w * h; - mgr->size_pic = mgr->size_y + mgr->size_uv; - mgr->y_vaddr = ybuf; - mgr->uv_vaddr = uvbuf; - mgr->canvas_w = w; - mgr->canvas_h = h; - crc_store(mgr, vf, crc1, crc4); - - return 0; -} - -static int fbc_check_prepare(struct pic_check_t *check, - int resize, int y_size) -{ - int i = 0; - - if (y_size > MAX_SIZE_AFBC_PLANES) - return -1; - - if (((!check->fbc_planes[0]) || - (!check->fbc_planes[1]) || - (!check->fbc_planes[2]) || - (!check->fbc_planes[3])) && - (!resize)) - return -1; - - if (resize) { - dbg_print(0, "size changed to 0x%x(y_size)\n", y_size); - for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { - if (check->fbc_planes[i]) { - vfree(check->fbc_planes[i]); - check->fbc_planes[i] = NULL; - } - } - } - for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { - if (!check->fbc_planes[i]) - check->fbc_planes[i] = - vmalloc(y_size * sizeof(short)); - } - if ((!check->fbc_planes[0]) || - (!check->fbc_planes[1]) || - (!check->fbc_planes[2]) || - (!check->fbc_planes[3])) { - dbg_print(0, "vmalloc staicplanes failed %lx %lx %lx %lx\n", - (ulong)check->fbc_planes[0], - (ulong)check->fbc_planes[1], - (ulong)check->fbc_planes[2], - (ulong)check->fbc_planes[3]); - for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { - if (check->fbc_planes[i]) { - vfree(check->fbc_planes[i]); - check->fbc_planes[i] = NULL; - } - } - return -1; - } else - dbg_print(FC_CRC_DEBUG, "vmalloc staicplanes sucessed\n"); - - return 0; -} - - - -int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf) -{ - int resize = 0; - void *planes[4]; - struct pic_check_t *check = NULL; - struct pic_check_mgr_t *mgr = NULL; - int ret = 0; - - if (vdec == NULL) { - if (single_mode_vdec == NULL) - return 0; - mgr = &single_mode_vdec->vfc; - } else { - mgr = &vdec->vfc; - single_mode_vdec = NULL; - } - - if ((mgr == NULL) || - (vf == NULL) || - (mgr->enable == 0)) - return 0; - - if (get_frame_size(mgr, vf) < 0) - return -1; - - if (mgr->last_size_pic != mgr->size_pic) { - resize = 1; - dbg_print(0, "size changed, %x-->%x\n", - mgr->last_size_pic, mgr->size_pic); - } else - resize = 0; - mgr->last_size_pic = mgr->size_pic; - - if (vf->type & VIDTYPE_VIU_NV21) { - if (canvas_get_virt_addr(mgr, vf) < 0) - return -2; - if ((mgr->y_vaddr) && (mgr->uv_vaddr)) { - codec_mm_dma_flush(mgr->y_vaddr, - mgr->size_y, DMA_FROM_DEVICE); - codec_mm_dma_flush(mgr->uv_vaddr, - mgr->size_uv, DMA_FROM_DEVICE); - } - if (mgr->enable & CRC_MASK) - ret = do_check_nv21(mgr, vf); - if (mgr->enable & YUV_MASK) - do_yuv_dump(mgr, vf); - - } else if (vf->type & VIDTYPE_SCATTER) { - check = &mgr->pic_check; - - if (mgr->pic_dump.buf_addr != NULL) { - dbg_print(0, "scatter free yuv buf\n"); - vfree(mgr->pic_dump.buf_addr); - mgr->pic_dump.buf_addr = NULL; - } - if (fbc_check_prepare(check, - resize, mgr->size_y) < 0) - return -3; - planes[0] = check->fbc_planes[0]; - planes[1] = check->fbc_planes[1]; - planes[2] = check->fbc_planes[2]; - planes[3] = check->fbc_planes[3]; - ret = AMLOGIC_FBC_vframe_decoder(planes, vf, 0, 0); - if (ret < 0) { - dbg_print(0, "amlogic_fbc_lib.ko error %d\n", ret); - } else { - do_check_yuv16(mgr, vf, - (void *)planes[0], (void *)planes[3],//uv - (void *)planes[1], (void *)planes[2]); - } - } - mgr->frame_cnt++; - - return ret; -} -EXPORT_SYMBOL(decoder_do_frame_check); - -static int dump_buf_alloc(struct pic_dump_t *dump) -{ - if ((dump->buf_addr != NULL) && - (dump->buf_size != 0)) - return 0; - - dump->buf_addr = - (char *)vmalloc(size_yuv_buf); - if (!dump->buf_addr) { - dump->buf_size = 0; - dbg_print(0, "vmalloc yuv buf failed\n"); - return -ENOMEM; - } - dump->buf_size = size_yuv_buf; - - dbg_print(0, "%s: buf for yuv is alloced\n", __func__); - - return 0; -} - -int dump_yuv_trig(struct pic_check_mgr_t *mgr, - int id, int start, int num) -{ - struct pic_dump_t *dump = &mgr->pic_dump; - - if (!dump->num) { - mgr->id = id; - dump->start = start; - dump->num = num; - dump->end = start + num; - dump->dump_cnt = 0; - dump->yuv_fp = NULL; - if (!atomic_read(&mgr->work_inited)) { - INIT_WORK(&mgr->frame_check_work, do_check_work); - atomic_set(&mgr->work_inited, 1); - } - dump_buf_alloc(dump); - str_strip(comp_crc); - set_enable(mgr, YUV_MASK); - } else { - dbg_print(FC_ERROR, "yuv dump now, trig later\n"); - return -EBUSY; - } - dbg_print(0, "dump yuv trigger, from %d to %d frame\n", - dump->start, dump->end); - return 0; -} - -int frame_check_init(struct pic_check_mgr_t *mgr, int id) -{ - int i; - struct pic_dump_t *dump = &mgr->pic_dump; - struct pic_check_t *check = &mgr->pic_check; - - mgr->frame_cnt = 0; - mgr->size_pic = 0; - mgr->last_size_pic = 0; - mgr->id = id; - - dump->num = 0; - dump->dump_cnt = 0; - dump->yuv_fp = NULL; - check->check_pos = 0; - check->compare_pos = 0; - - if (!atomic_read(&mgr->work_inited)) { - INIT_WORK(&mgr->frame_check_work, do_check_work); - atomic_set(&mgr->work_inited, 1); - } - /* for dump error yuv prepare. */ - dump_buf_alloc(dump); - - /* try to open compare crc32 file */ - str_strip(comp_crc); - check->compare_fp = file_open(O_RDONLY, - "%s%s", CRC_PATH, comp_crc); - - /* create crc32 log file */ - check->check_fp = file_open(O_CREAT| O_WRONLY | O_TRUNC, - "%s%s-%d-%d.crc", CRC_PATH, comp_crc, id, mgr->file_cnt); - - INIT_KFIFO(check->new_chk_q); - INIT_KFIFO(check->wr_chk_q); - check->check_addr = vmalloc(SIZE_CRC * SIZE_CHECK_Q); - if (check->check_addr == NULL) { - dbg_print(FC_ERROR, "vmalloc qbuf fail\n"); - } else { - void *qaddr = NULL, *rdret = NULL; - check->cmp_crc_cnt = 0; - for (i = 0; i < SIZE_CHECK_Q; i++) { - qaddr = check->check_addr + i * SIZE_CRC; - rdret = fget_crc_str(qaddr, - SIZE_CRC, check); - if (rdret == NULL) { - if (i < 3) - dbg_print(0, "can't get compare crc string\n"); - if (check->compare_fp) { - filp_close(check->compare_fp, current->files); - check->compare_fp = NULL; - } - } - - kfifo_put(&check->new_chk_q, qaddr); - } - } - set_enable(mgr, CRC_MASK); - dbg_print(0, "%s end\n", __func__); - - return 0; -} - -void frame_check_exit(struct pic_check_mgr_t *mgr) -{ - int i; - struct pic_dump_t *dump = &mgr->pic_dump; - struct pic_check_t *check = &mgr->pic_check; - - if (mgr->enable != 0) { - if (dump->dump_cnt != 0) { - dbg_print(0, "%s, cnt = %d, num = %d\n", - __func__, dump->dump_cnt, dump->num); - set_enable(mgr, YUV_MASK); - } - if (atomic_read(&mgr->work_inited)) { - cancel_work_sync(&mgr->frame_check_work); - atomic_set(&mgr->work_inited, 0); - } - write_yuv_work(mgr); - write_crc_work(mgr); - - for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { - if (check->fbc_planes[i]) { - vfree(check->fbc_planes[i]); - check->fbc_planes[i] = NULL; - } - } - if (check->check_addr) { - vfree(check->check_addr); - check->check_addr = NULL; - } - - if (check->check_fp) { - filp_close(check->check_fp, current->files); - check->check_fp = NULL; - } - if (check->compare_fp) { - filp_close(check->compare_fp, current->files); - check->compare_fp = NULL; - } - if (dump->yuv_fp) { - filp_close(dump->yuv_fp, current->files); - dump->yuv_fp = NULL; - } - if (dump->buf_addr) { - vfree(dump->buf_addr); - dump->buf_addr = NULL; - } - mgr->file_cnt++; - set_disable(mgr, YUV_MASK | CRC_MASK); - dbg_print(0, "%s end\n", __func__); - } -} - - -int vdec_frame_check_init(struct vdec_s *vdec) -{ - int ret = 0, id = 0; - - if (vdec == NULL) - return 0; - - if ((vdec->is_reset) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXL)) - return 0; - - vdec->vfc.err_crc_block = 0; - if (!check_enable && !yuv_enable) - return 0; - - if (vdec_single(vdec)) - single_mode_vdec = vdec; - - vdec->canvas_mode = CANVAS_BLKMODE_LINEAR; - id = vdec->id; - - if (check_enable & (0x01 << id)) { - frame_check_init(&vdec->vfc, id); - /*repeat check one video crc32, not clear enable*/ - if ((fc_debug & FC_CHECK_CRC_LOOP_MODE) == 0) - check_enable &= ~(0x01 << id); - } - - if (yuv_enable & (0x01 << id)) { - ret = dump_yuv_trig(&vdec->vfc, - id, yuv_start[id], yuv_num[id]); - if (ret < 0) - pr_info("dump yuv init failed\n"); - else { - pr_info("dump yuv init ok, total %d\n", - yuv_num[id]); - vdec->canvas_mode = CANVAS_BLKMODE_LINEAR; - } - yuv_num[id] = 0; - yuv_start[id] = 0; - yuv_enable &= ~(0x01 << id); - } - - return ret; -} - -void vdec_frame_check_exit(struct vdec_s *vdec) -{ - if (vdec == NULL) - return; - frame_check_exit(&vdec->vfc); - - single_mode_vdec = NULL; -} - -ssize_t dump_yuv_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - struct vdec_s *vdec = NULL; - unsigned int id = 0, num = 0, start = 0; - int ret = -1; - - ret = sscanf(buf, "%d %d %d", &id, &start, &num); - if (ret < 0) { - pr_info("%s, parse failed\n", buf); - return size; - } - if ((num == 0) || (num > YUV_MAX_DUMP_NUM)) { - pr_info("requred yuv num %d, max %d\n", - num, YUV_MAX_DUMP_NUM); - return size; - } - vdec = vdec_get_with_id(id); - if (vdec == NULL) { - yuv_start[id] = start; - yuv_num[id] = num; - yuv_enable |= (1 << id); - pr_info("no connected vdec.%d now, set dump ok\n", id); - return size; - } - - ret = dump_yuv_trig(&vdec->vfc, id, start, num); - if (ret < 0) - pr_info("trigger dump yuv failed\n"); - else - pr_info("trigger dump yuv init ok, total %d frames\n", num); - - return size; -} - -ssize_t dump_yuv_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int i; - char *pbuf = buf; - - for (i = 0; i < MAX_INSTANCE_MUN; i++) { - pbuf += pr_info("vdec.%d, start: %d, total: %d frames\n", - i, yuv_start[i], yuv_num[i]); - } - pbuf += sprintf(pbuf, - "\nUsage: echo [id] [start] [num] > dump_yuv\n\n"); - return pbuf - buf; -} - - -ssize_t frame_check_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int ret = -1; - int on_off, id; - - ret = sscanf(buf, "%d %d", &id, &on_off); - if (ret < 0) { - pr_info("%s, parse failed\n", buf); - return size; - } - if (id >= MAX_INSTANCE_MUN) { - pr_info("%d out of max vdec id\n", id); - return size; - } - if (on_off) - check_enable |= (1 << id); - else - check_enable &= ~(1 << id); - - return size; -} - -ssize_t frame_check_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int i; - char *pbuf = buf; - - for (i = 0; i < MAX_INSTANCE_MUN; i++) { - pbuf += sprintf(pbuf, - "vdec.%d\tcrc: %s\n", i, - (check_enable & (0x01 << i))?"enabled":"--"); - } - pbuf += sprintf(pbuf, - "\nUsage:\techo [id] [1:on/0:off] > frame_check\n\n"); - - if (fc_debug & FC_ERR_CRC_BLOCK_MODE) { - /* cat frame_check to next frame when block */ - struct vdec_s *vdec = NULL; - vdec = vdec_get_with_id(__ffs(check_enable)); - if (vdec) - vdec->vfc.err_crc_block = 0; - } - - return pbuf - buf; -} - - -module_param_string(comp_crc, comp_crc, 128, 0664); -MODULE_PARM_DESC(comp_crc, "\n crc_filename\n"); - -module_param(fc_debug, uint, 0664); -MODULE_PARM_DESC(fc_debug, "\n frame check debug\n"); - -module_param(size_yuv_buf, uint, 0664); -MODULE_PARM_DESC(size_yuv_buf, "\n size_yuv_buf\n"); - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h deleted file mode 100644 index f1ba6773fe43..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#ifndef __FRAME_CHECK_H__ -#define __FRAME_CHECK_H__ - - -#include -#include -#include -#include - -#define FRAME_CHECK - -#define YUV_MAX_DUMP_NUM 20 - -#define SIZE_CRC 64 -#define SIZE_CHECK_Q 128 - -struct pic_dump_t{ - struct file *yuv_fp; - loff_t yuv_pos; - unsigned int start; - unsigned int num; - unsigned int end; - unsigned int dump_cnt; - - unsigned int buf_size; - char *buf_addr; -}; - -struct pic_check_t{ - struct file *check_fp; - loff_t check_pos; - - struct file *compare_fp; - loff_t compare_pos; - unsigned int cmp_crc_cnt; - void *fbc_planes[4]; - void *check_addr; - DECLARE_KFIFO(new_chk_q, char *, SIZE_CHECK_Q); - DECLARE_KFIFO(wr_chk_q, char *, SIZE_CHECK_Q); -}; - -struct pic_check_mgr_t{ - int id; - int enable; - unsigned int frame_cnt; - /* pic info */ - unsigned int canvas_w; - unsigned int canvas_h; - unsigned int size_y; //real size - unsigned int size_uv; - unsigned int size_pic; - unsigned int last_size_pic; - void *y_vaddr; - void *uv_vaddr; - ulong y_phyaddr; - ulong uv_phyaddr; - int err_crc_block; - - int file_cnt; - atomic_t work_inited; - struct work_struct frame_check_work; - - struct pic_check_t pic_check; - struct pic_dump_t pic_dump; -}; - -int dump_yuv_trig(struct pic_check_mgr_t *mgr, - int id, int start, int num); - -int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf); - -int frame_check_init(struct pic_check_mgr_t *mgr, int id); - -void frame_check_exit(struct pic_check_mgr_t *mgr); - -ssize_t frame_check_show(struct class *class, - struct class_attribute *attr, char *buf); - -ssize_t frame_check_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size); - -ssize_t dump_yuv_show(struct class *class, - struct class_attribute *attr, char *buf); - -ssize_t dump_yuv_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size); - -void vdec_frame_check_exit(struct vdec_s *vdec); -int vdec_frame_check_init(struct vdec_s *vdec); - -#endif /* __FRAME_CHECK_H__ */ - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c deleted file mode 100644 index a1e7fa79008f..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * drivers/amlogic/amports/arch/secprot.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#include -#include -#include "secprot.h" -#ifndef CONFIG_ARM64 -#include -#endif - -#ifdef CONFIG_ARM64 - -int tee_config_device_secure(int dev_id, int secure) -{ - int ret = 0; - register unsigned x0 asm("x0"); - register unsigned x1 asm("x1"); - register unsigned x2 asm("x2"); - - x0 = OPTEE_SMC_CONFIG_DEVICE_SECURE; - x1 = dev_id; - x2 = secure; - - asm volatile( - __asmeq("%0", "x0") - __asmeq("%1", "x0") - __asmeq("%2", "x1") - __asmeq("%3", "x2") - "smc #0\n" - : "=r"(x0) - : "r"(x0), "r"(x1), "r"(x2)); - ret = x0; - - return ret; -} -#else -int tee_config_device_secure(int dev_id, int secure) -{ - int ret = 0; - register unsigned int r0 asm("r0"); - register unsigned int r1 asm("r1"); - register unsigned int r2 asm("r2"); - - r0 = OPTEE_SMC_CONFIG_DEVICE_SECURE; - r1 = dev_id; - r2 = secure; - - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r0") - __asmeq("%2", "r1") - __asmeq("%3", "r2") - __SMC(0) - : "=r"(r0) - : "r"(r0), "r"(r1), "r"(r2)); - ret = r0; - - return ret; -} -#endif - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h deleted file mode 100644 index 28ee47725dbc..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * drivers/amlogic/amports/arch/secprot.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#ifndef __SECPROT_H_ -#define __SECPROT_H_ - -#define DMC_DEV_TYPE_NON_SECURE 0 -#define DMC_DEV_TYPE_SECURE 1 - -#define DMC_DEV_ID_GPU 1 -#define DMC_DEV_ID_HEVC 4 -#define DMC_DEV_ID_PARSER 7 -#define DMC_DEV_ID_VPU 8 -#define DMC_DEV_ID_VDEC 13 -#define DMC_DEV_ID_HCODEC 14 -#define DMC_DEV_ID_GE2D 15 - -#define OPTEE_SMC_CONFIG_DEVICE_SECURE 0xb200000e - -/*#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"*/ - -extern int tee_config_device_secure(int dev_id, int secure); - -#endif /* __SECPROT_H_ */ - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c deleted file mode 100644 index 667b6f14bec7..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/utils.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vdec.h" -#include "vdec_input.h" -#include -#include "amvdec.h" -#include "decoder_mmu_box.h" -#include "decoder_bmmu_box.h" -#include "vdec_profile.h" - -static int __init decoder_common_init(void) -{ - /*vdec init.*/ - vdec_module_init(); - - /*amvdec init.*/ - amvdec_init(); - - /*mmu box init.*/ - decoder_mmu_box_init();/*exit?*/ - decoder_bmmu_box_init(); - - vdec_profile_init_debugfs(); - - return 0; -} - -static void __exit decoder_common_exit(void) -{ - /*vdec exit.*/ - vdec_module_exit(); - - /*amvdec exit.*/ - amvdec_exit(); - - decoder_mmu_box_exit(); - decoder_bmmu_box_exit(); - - vdec_profile_exit_debugfs(); -} - -module_init(decoder_common_init); -module_exit(decoder_common_exit); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c deleted file mode 100644 index 3e7a47f7a287..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c +++ /dev/null @@ -1,4862 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/vdec.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*for VDEC_DEBUG_SUPPORT*/ -#include - -#include -#include "vdec.h" -#include "vdec_trace.h" -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -#include "vdec_profile.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" - -#include -#include "../utils/amvdec.h" -#include "vdec_input.h" - -#include "../../../common/media_clock/clk/clk.h" -#include -#include -#include -#include -#include -#include -#include "secprot.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" -#include "frame_check.h" - -#ifdef CONFIG_AMLOGIC_POWER -#include -#endif - -static DEFINE_MUTEX(vdec_mutex); - -#define MC_SIZE (4096 * 4) -#define CMA_ALLOC_SIZE SZ_64M -#define MEM_NAME "vdec_prealloc" -static int inited_vcodec_num; -#define jiffies_ms div64_u64(get_jiffies_64() * 1000, HZ) -static int poweron_clock_level; -static int keep_vdec_mem; -static unsigned int debug_trace_num = 16 * 20; -static int step_mode; -static unsigned int clk_config; -/* - &1: sched_priority to MAX_RT_PRIO -1. - &2: always reload firmware. - &4: vdec canvas debug enable - */ -static unsigned int debug; - -static int hevc_max_reset_count; - -static int no_powerdown; -static int parallel_decode = 1; -static int fps_detection; -static int fps_clear; - - -static int force_nosecure_even_drm; - -static DEFINE_SPINLOCK(vdec_spin_lock); - -#define HEVC_TEST_LIMIT 100 -#define GXBB_REV_A_MINOR 0xA - -#define PRINT_FRAME_INFO 1 -#define DISABLE_FRAME_INFO 2 - -static int frameinfo_flag = 0; -//static int path_debug = 0; - -static struct vframe_qos_s *frame_info_buf_in = NULL; -static struct vframe_qos_s *frame_info_buf_out = NULL; -static int frame_qos_wr = 0; -static int frame_qos_rd = 0; -int decode_underflow = 0; - -#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1) - -struct am_reg { - char *name; - int offset; -}; - -struct vdec_isr_context_s { - int index; - int irq; - irq_handler_t dev_isr; - irq_handler_t dev_threaded_isr; - void *dev_id; - struct vdec_s *vdec; -}; - -struct decode_fps_s { - u32 frame_count; - u64 start_timestamp; - u64 last_timestamp; - u32 fps; -}; - -struct vdec_core_s { - struct list_head connected_vdec_list; - spinlock_t lock; - spinlock_t canvas_lock; - spinlock_t fps_lock; - struct ida ida; - atomic_t vdec_nr; - struct vdec_s *vfm_vdec; - struct vdec_s *active_vdec; - struct vdec_s *active_hevc; - struct vdec_s *hint_fr_vdec; - struct platform_device *vdec_core_platform_device; - struct device *cma_dev; - struct semaphore sem; - struct task_struct *thread; - struct workqueue_struct *vdec_core_wq; - - unsigned long sched_mask; - struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX]; - int power_ref_count[VDEC_MAX]; - struct vdec_s *last_vdec; - int parallel_dec; - unsigned long power_ref_mask; - int vdec_combine_flag; - struct decode_fps_s decode_fps[MAX_INSTANCE_MUN]; -}; - -struct canvas_status_s { - int type; - int canvas_used_flag; - int id; -}; - - -static struct vdec_core_s *vdec_core; - -static const char * const vdec_status_string[] = { - "VDEC_STATUS_UNINITIALIZED", - "VDEC_STATUS_DISCONNECTED", - "VDEC_STATUS_CONNECTED", - "VDEC_STATUS_ACTIVE" -}; - -static int debugflags; - -static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1]; - - -int vdec_get_debug_flags(void) -{ - return debugflags; -} -EXPORT_SYMBOL(vdec_get_debug_flags); - -unsigned char is_mult_inc(unsigned int type) -{ - unsigned char ret = 0; - if (vdec_get_debug_flags() & 0xf000) - ret = (vdec_get_debug_flags() & 0x1000) - ? 1 : 0; - else if (type & PORT_TYPE_DECODER_SCHED) - ret = 1; - return ret; -} -EXPORT_SYMBOL(is_mult_inc); - -static const bool cores_with_input[VDEC_MAX] = { - true, /* VDEC_1 */ - false, /* VDEC_HCODEC */ - false, /* VDEC_2 */ - true, /* VDEC_HEVC / VDEC_HEVC_FRONT */ - false, /* VDEC_HEVC_BACK */ -}; - -static const int cores_int[VDEC_MAX] = { - VDEC_IRQ_1, - VDEC_IRQ_2, - VDEC_IRQ_0, - VDEC_IRQ_0, - VDEC_IRQ_HEVC_BACK -}; - -unsigned long vdec_canvas_lock(struct vdec_core_s *core) -{ - unsigned long flags; - spin_lock_irqsave(&core->canvas_lock, flags); - - return flags; -} - -void vdec_canvas_unlock(struct vdec_core_s *core, unsigned long flags) -{ - spin_unlock_irqrestore(&core->canvas_lock, flags); -} - -unsigned long vdec_fps_lock(struct vdec_core_s *core) -{ - unsigned long flags; - spin_lock_irqsave(&core->fps_lock, flags); - - return flags; -} - -void vdec_fps_unlock(struct vdec_core_s *core, unsigned long flags) -{ - spin_unlock_irqrestore(&core->fps_lock, flags); -} - -unsigned long vdec_core_lock(struct vdec_core_s *core) -{ - unsigned long flags; - - spin_lock_irqsave(&core->lock, flags); - - return flags; -} - -void vdec_core_unlock(struct vdec_core_s *core, unsigned long flags) -{ - spin_unlock_irqrestore(&core->lock, flags); -} - -static u64 vdec_get_us_time_system(void) -{ - struct timeval tv; - - do_gettimeofday(&tv); - - return div64_u64(timeval_to_ns(&tv), 1000); -} - -static void vdec_fps_clear(int id) -{ - if (id >= MAX_INSTANCE_MUN) - return; - - vdec_core->decode_fps[id].frame_count = 0; - vdec_core->decode_fps[id].start_timestamp = 0; - vdec_core->decode_fps[id].last_timestamp = 0; - vdec_core->decode_fps[id].fps = 0; -} - -static void vdec_fps_clearall(void) -{ - int i; - - for (i = 0; i < MAX_INSTANCE_MUN; i++) { - vdec_core->decode_fps[i].frame_count = 0; - vdec_core->decode_fps[i].start_timestamp = 0; - vdec_core->decode_fps[i].last_timestamp = 0; - vdec_core->decode_fps[i].fps = 0; - } -} - -static void vdec_fps_detec(int id) -{ - unsigned long flags; - - if (fps_detection == 0) - return; - - if (id >= MAX_INSTANCE_MUN) - return; - - flags = vdec_fps_lock(vdec_core); - - if (fps_clear == 1) { - vdec_fps_clearall(); - fps_clear = 0; - } - - vdec_core->decode_fps[id].frame_count++; - if (vdec_core->decode_fps[id].frame_count == 1) { - vdec_core->decode_fps[id].start_timestamp = - vdec_get_us_time_system(); - vdec_core->decode_fps[id].last_timestamp = - vdec_core->decode_fps[id].start_timestamp; - } else { - vdec_core->decode_fps[id].last_timestamp = - vdec_get_us_time_system(); - vdec_core->decode_fps[id].fps = - (u32)div_u64(((u64)(vdec_core->decode_fps[id].frame_count) * - 10000000000), - (vdec_core->decode_fps[id].last_timestamp - - vdec_core->decode_fps[id].start_timestamp)); - } - vdec_fps_unlock(vdec_core, flags); -} - - - -static int get_canvas(unsigned int index, unsigned int base) -{ - int start; - int canvas_index = index * base; - int ret; - - if ((base > 4) || (base == 0)) - return -1; - - if ((AMVDEC_CANVAS_START_INDEX + canvas_index + base - 1) - <= AMVDEC_CANVAS_MAX1) { - start = AMVDEC_CANVAS_START_INDEX + base * index; - } else { - canvas_index -= (AMVDEC_CANVAS_MAX1 - - AMVDEC_CANVAS_START_INDEX + 1) / base * base; - if (canvas_index <= AMVDEC_CANVAS_MAX2) - start = canvas_index / base; - else - return -1; - } - - if (base == 1) { - ret = start; - } else if (base == 2) { - ret = ((start + 1) << 16) | ((start + 1) << 8) | start; - } else if (base == 3) { - ret = ((start + 2) << 16) | ((start + 1) << 8) | start; - } else if (base == 4) { - ret = (((start + 3) << 24) | (start + 2) << 16) | - ((start + 1) << 8) | start; - } - - return ret; -} - -static int get_canvas_ex(int type, int id) -{ - int i; - unsigned long flags; - - flags = vdec_canvas_lock(vdec_core); - - for (i = 0; i < CANVAS_MAX_SIZE; i++) { - /*0x10-0x15 has been used by rdma*/ - if ((i >= 0x10) && (i <= 0x15)) - continue; - if ((canvas_stat[i].type == type) && - (canvas_stat[i].id & (1 << id)) == 0) { - canvas_stat[i].canvas_used_flag++; - canvas_stat[i].id |= (1 << id); - if (debug & 4) - pr_debug("get used canvas %d\n", i); - vdec_canvas_unlock(vdec_core, flags); - if (i < AMVDEC_CANVAS_MAX2 + 1) - return i; - else - return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1); - } - } - - for (i = 0; i < CANVAS_MAX_SIZE; i++) { - /*0x10-0x15 has been used by rdma*/ - if ((i >= 0x10) && (i <= 0x15)) - continue; - if (canvas_stat[i].type == 0) { - canvas_stat[i].type = type; - canvas_stat[i].canvas_used_flag = 1; - canvas_stat[i].id = (1 << id); - if (debug & 4) { - pr_debug("get canvas %d\n", i); - pr_debug("canvas_used_flag %d\n", - canvas_stat[i].canvas_used_flag); - pr_debug("canvas_stat[i].id %d\n", - canvas_stat[i].id); - } - vdec_canvas_unlock(vdec_core, flags); - if (i < AMVDEC_CANVAS_MAX2 + 1) - return i; - else - return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1); - } - } - vdec_canvas_unlock(vdec_core, flags); - - pr_info("cannot get canvas\n"); - - return -1; -} - -static void free_canvas_ex(int index, int id) -{ - unsigned long flags; - int offset; - - flags = vdec_canvas_lock(vdec_core); - if (index >= 0 && - index < AMVDEC_CANVAS_MAX2 + 1) - offset = index; - else if ((index >= AMVDEC_CANVAS_START_INDEX) && - (index <= AMVDEC_CANVAS_MAX1)) - offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX; - else { - vdec_canvas_unlock(vdec_core, flags); - return; - } - - if ((canvas_stat[offset].canvas_used_flag > 0) && - (canvas_stat[offset].id & (1 << id))) { - canvas_stat[offset].canvas_used_flag--; - canvas_stat[offset].id &= ~(1 << id); - if (canvas_stat[offset].canvas_used_flag == 0) { - canvas_stat[offset].type = 0; - canvas_stat[offset].id = 0; - } - if (debug & 4) { - pr_debug("free index %d used_flag %d, type = %d, id = %d\n", - offset, - canvas_stat[offset].canvas_used_flag, - canvas_stat[offset].type, - canvas_stat[offset].id); - } - } - vdec_canvas_unlock(vdec_core, flags); - - return; - -} - - - - -static int vdec_get_hw_type(int value) -{ - int type; - switch (value) { - case VFORMAT_HEVC: - case VFORMAT_VP9: - case VFORMAT_AVS2: - type = CORE_MASK_HEVC; - break; - - case VFORMAT_MPEG12: - case VFORMAT_MPEG4: - case VFORMAT_H264: - case VFORMAT_MJPEG: - case VFORMAT_REAL: - case VFORMAT_JPEG: - case VFORMAT_VC1: - case VFORMAT_AVS: - case VFORMAT_YUV: - case VFORMAT_H264MVC: - case VFORMAT_H264_4K2K: - case VFORMAT_H264_ENC: - case VFORMAT_JPEG_ENC: - type = CORE_MASK_VDEC_1; - break; - - default: - type = -1; - } - - return type; -} - - -static void vdec_save_active_hw(struct vdec_s *vdec) -{ - int type; - - type = vdec_get_hw_type(vdec->port->vformat); - - if (type == CORE_MASK_HEVC) { - vdec_core->active_hevc = vdec; - } else if (type == CORE_MASK_VDEC_1) { - vdec_core->active_vdec = vdec; - } else { - pr_info("save_active_fw wrong\n"); - } -} - - -int vdec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (vdec && vdec->dec_status && - ((vdec->status == VDEC_STATUS_CONNECTED || - vdec->status == VDEC_STATUS_ACTIVE))) - return vdec->dec_status(vdec, vstatus); - - return 0; -} -EXPORT_SYMBOL(vdec_status); - -int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) -{ - int r; - - if (vdec->set_trickmode) { - r = vdec->set_trickmode(vdec, trickmode); - - if ((r == 0) && (vdec->slave) && (vdec->slave->set_trickmode)) - r = vdec->slave->set_trickmode(vdec->slave, - trickmode); - return r; - } - - return -1; -} -EXPORT_SYMBOL(vdec_set_trickmode); - -int vdec_set_isreset(struct vdec_s *vdec, int isreset) -{ - vdec->is_reset = isreset; - pr_info("is_reset=%d\n", isreset); - if (vdec->set_isreset) - return vdec->set_isreset(vdec, isreset); - return 0; -} -EXPORT_SYMBOL(vdec_set_isreset); - -int vdec_set_dv_metawithel(struct vdec_s *vdec, int isdvmetawithel) -{ - vdec->dolby_meta_with_el = isdvmetawithel; - pr_info("isdvmetawithel=%d\n", isdvmetawithel); - return 0; -} -EXPORT_SYMBOL(vdec_set_dv_metawithel); - -void vdec_set_no_powerdown(int flag) -{ - no_powerdown = flag; - pr_info("no_powerdown=%d\n", no_powerdown); - return; -} -EXPORT_SYMBOL(vdec_set_no_powerdown); - -void vdec_count_info(struct vdec_info *vs, unsigned int err, - unsigned int offset) -{ - if (err) - vs->error_frame_count++; - if (offset) { - if (0 == vs->frame_count) { - vs->offset = 0; - vs->samp_cnt = 0; - } - vs->frame_data = offset > vs->total_data ? - offset - vs->total_data : vs->total_data - offset; - vs->total_data = offset; - if (vs->samp_cnt < 96000 * 2) { /* 2s */ - if (0 == vs->samp_cnt) - vs->offset = offset; - vs->samp_cnt += vs->frame_dur; - } else { - vs->bit_rate = (offset - vs->offset) / 2; - /*pr_info("bitrate : %u\n",vs->bit_rate);*/ - vs->samp_cnt = 0; - } - vs->frame_count++; - } - /*pr_info("size : %u, offset : %u, dur : %u, cnt : %u\n", - vs->offset,offset,vs->frame_dur,vs->samp_cnt);*/ - return; -} -EXPORT_SYMBOL(vdec_count_info); -int vdec_is_support_4k(void) -{ - return !is_meson_gxl_package_805X(); -} -EXPORT_SYMBOL(vdec_is_support_4k); - -/* - * clk_config: - *0:default - *1:no gp0_pll; - *2:always used gp0_pll; - *>=10:fixed n M clk; - *== 100 , 100M clks; - */ -unsigned int get_vdec_clk_config_settings(void) -{ - return clk_config; -} -void update_vdec_clk_config_settings(unsigned int config) -{ - clk_config = config; -} -EXPORT_SYMBOL(update_vdec_clk_config_settings); - -static bool hevc_workaround_needed(void) -{ - return (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) && - (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) - == GXBB_REV_A_MINOR); -} - -struct device *get_codec_cma_device(void) -{ - return vdec_core->cma_dev; -} - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -static const char * const vdec_device_name[] = { - "amvdec_mpeg12", "ammvdec_mpeg12", - "amvdec_mpeg4", "ammvdec_mpeg4", - "amvdec_h264", "ammvdec_h264", - "amvdec_mjpeg", "ammvdec_mjpeg", - "amvdec_real", "ammvdec_real", - "amjpegdec", "ammjpegdec", - "amvdec_vc1", "ammvdec_vc1", - "amvdec_avs", "ammvdec_avs", - "amvdec_yuv", "ammvdec_yuv", - "amvdec_h264mvc", "ammvdec_h264mvc", - "amvdec_h264_4k2k", "ammvdec_h264_4k2k", - "amvdec_h265", "ammvdec_h265", - "amvenc_avc", "amvenc_avc", - "jpegenc", "jpegenc", - "amvdec_vp9", "ammvdec_vp9", - "amvdec_avs2", "ammvdec_avs2" -}; - - -#else - -static const char * const vdec_device_name[] = { - "amvdec_mpeg12", - "amvdec_mpeg4", - "amvdec_h264", - "amvdec_mjpeg", - "amvdec_real", - "amjpegdec", - "amvdec_vc1", - "amvdec_avs", - "amvdec_yuv", - "amvdec_h264mvc", - "amvdec_h264_4k2k", - "amvdec_h265", - "amvenc_avc", - "jpegenc", - "amvdec_vp9", - "amvdec_avs2" -}; - -#endif - -#ifdef VDEC_DEBUG_SUPPORT -static u64 get_current_clk(void) -{ - /*struct timespec xtime = current_kernel_time(); - u64 usec = xtime.tv_sec * 1000000; - usec += xtime.tv_nsec / 1000; - */ - u64 usec = sched_clock(); - return usec; -} - -static void inc_profi_count(unsigned long mask, u32 *count) -{ - enum vdec_type_e type; - - for (type = VDEC_1; type < VDEC_MAX; type++) { - if (mask & (1 << type)) - count[type]++; - } -} - -static void update_profi_clk_run(struct vdec_s *vdec, - unsigned long mask, u64 clk) -{ - enum vdec_type_e type; - - for (type = VDEC_1; type < VDEC_MAX; type++) { - if (mask & (1 << type)) { - vdec->start_run_clk[type] = clk; - if (vdec->profile_start_clk[type] == 0) - vdec->profile_start_clk[type] = clk; - vdec->total_clk[type] = clk - - vdec->profile_start_clk[type]; - /*pr_info("set start_run_clk %ld\n", - vdec->start_run_clk);*/ - - } - } -} - -static void update_profi_clk_stop(struct vdec_s *vdec, - unsigned long mask, u64 clk) -{ - enum vdec_type_e type; - - for (type = VDEC_1; type < VDEC_MAX; type++) { - if (mask & (1 << type)) { - if (vdec->start_run_clk[type] == 0) - pr_info("error, start_run_clk[%d] not set\n", type); - - /*pr_info("update run_clk type %d, %ld, %ld, %ld\n", - type, - clk, - vdec->start_run_clk[type], - vdec->run_clk[type]);*/ - vdec->run_clk[type] += - (clk - vdec->start_run_clk[type]); - } - } -} - -#endif - -int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p) -{ - if (copy_from_user((void *)&vdec->sys_info_store, (void *)p, - sizeof(struct dec_sysinfo))) - return -EFAULT; - - return 0; -} -EXPORT_SYMBOL(vdec_set_decinfo); - -/* construct vdec strcture */ -struct vdec_s *vdec_create(struct stream_port_s *port, - struct vdec_s *master) -{ - struct vdec_s *vdec; - int type = VDEC_TYPE_SINGLE; - int id; - if (is_mult_inc(port->type)) - type = (port->type & PORT_TYPE_FRAME) ? - VDEC_TYPE_FRAME_BLOCK : - VDEC_TYPE_STREAM_PARSER; - - id = ida_simple_get(&vdec_core->ida, - 0, MAX_INSTANCE_MUN, GFP_KERNEL); - if (id < 0) { - pr_info("vdec_create request id failed!ret =%d\n", id); - return NULL; - } - vdec = vzalloc(sizeof(struct vdec_s)); - - /* TBD */ - if (vdec) { - vdec->magic = 0x43454456; - vdec->id = -1; - vdec->type = type; - vdec->port = port; - vdec->sys_info = &vdec->sys_info_store; - - INIT_LIST_HEAD(&vdec->list); - - atomic_inc(&vdec_core->vdec_nr); - vdec->id = id; - vdec_input_init(&vdec->input, vdec); - if (master) { - vdec->master = master; - master->slave = vdec; - master->sched = 1; - } - } - - pr_debug("vdec_create instance %p, total %d\n", vdec, - atomic_read(&vdec_core->vdec_nr)); - - //trace_vdec_create(vdec); /*DEBUG_TMP*/ - - return vdec; -} -EXPORT_SYMBOL(vdec_create); - -int vdec_set_format(struct vdec_s *vdec, int format) -{ - vdec->format = format; - vdec->port_flag |= PORT_FLAG_VFORMAT; - - if (vdec->slave) { - vdec->slave->format = format; - vdec->slave->port_flag |= PORT_FLAG_VFORMAT; - } - - //trace_vdec_set_format(vdec, format);/*DEBUG_TMP*/ - - return 0; -} -EXPORT_SYMBOL(vdec_set_format); - -int vdec_set_pts(struct vdec_s *vdec, u32 pts) -{ - vdec->pts = pts; - vdec->pts64 = div64_u64((u64)pts * 100, 9); - vdec->pts_valid = true; - //trace_vdec_set_pts(vdec, (u64)pts);/*DEBUG_TMP*/ - return 0; -} -EXPORT_SYMBOL(vdec_set_pts); - -void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp) -{ - vdec->timestamp = timestamp; - vdec->timestamp_valid = true; -} -EXPORT_SYMBOL(vdec_set_timestamp); - -int vdec_set_pts64(struct vdec_s *vdec, u64 pts64) -{ - vdec->pts64 = pts64; - vdec->pts = (u32)div64_u64(pts64 * 9, 100); - vdec->pts_valid = true; - - //trace_vdec_set_pts64(vdec, pts64);/*DEBUG_TMP*/ - return 0; -} -EXPORT_SYMBOL(vdec_set_pts64); - -int vdec_get_status(struct vdec_s *vdec) -{ - return vdec->status; -} -EXPORT_SYMBOL(vdec_get_status); - -void vdec_set_status(struct vdec_s *vdec, int status) -{ - //trace_vdec_set_status(vdec, status);/*DEBUG_TMP*/ - vdec->status = status; -} -EXPORT_SYMBOL(vdec_set_status); - -void vdec_set_next_status(struct vdec_s *vdec, int status) -{ - //trace_vdec_set_next_status(vdec, status);/*DEBUG_TMP*/ - vdec->next_status = status; -} -EXPORT_SYMBOL(vdec_set_next_status); - -int vdec_set_video_path(struct vdec_s *vdec, int video_path) -{ - vdec->frame_base_video_path = video_path; - return 0; -} -EXPORT_SYMBOL(vdec_set_video_path); - -int vdec_set_receive_id(struct vdec_s *vdec, int receive_id) -{ - vdec->vf_receiver_inst = receive_id; - return 0; -} -EXPORT_SYMBOL(vdec_set_receive_id); - -/* add frame data to input chain */ -int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count) -{ - return vdec_input_add_frame(&vdec->input, buf, count); -} -EXPORT_SYMBOL(vdec_write_vframe); - -/* add a work queue thread for vdec*/ -void vdec_schedule_work(struct work_struct *work) -{ - if (vdec_core->vdec_core_wq) - queue_work(vdec_core->vdec_core_wq, work); - else - schedule_work(work); -} -EXPORT_SYMBOL(vdec_schedule_work); - -static struct vdec_s *vdec_get_associate(struct vdec_s *vdec) -{ - if (vdec->master) - return vdec->master; - else if (vdec->slave) - return vdec->slave; - return NULL; -} - -static void vdec_sync_input_read(struct vdec_s *vdec) -{ - if (!vdec_stream_based(vdec)) - return; - - if (vdec_dual(vdec)) { - u32 me, other; - if (vdec->input.target == VDEC_INPUT_TARGET_VLD) { - me = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT); - other = - vdec_get_associate(vdec)->input.stream_cookie; - if (me > other) - return; - else if (me == other) { - me = READ_VREG(VLD_MEM_VIFIFO_RP); - other = - vdec_get_associate(vdec)->input.swap_rp; - if (me > other) { - WRITE_PARSER_REG(PARSER_VIDEO_RP, - vdec_get_associate(vdec)-> - input.swap_rp); - return; - } - } - WRITE_PARSER_REG(PARSER_VIDEO_RP, - READ_VREG(VLD_MEM_VIFIFO_RP)); - } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) { - me = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - if (((me & 0x80000000) == 0) && - (vdec->input.streaming_rp & 0x80000000)) - me += 1ULL << 32; - other = vdec_get_associate(vdec)->input.streaming_rp; - if (me > other) { - WRITE_PARSER_REG(PARSER_VIDEO_RP, - vdec_get_associate(vdec)-> - input.swap_rp); - return; - } - - WRITE_PARSER_REG(PARSER_VIDEO_RP, - READ_VREG(HEVC_STREAM_RD_PTR)); - } - } else if (vdec->input.target == VDEC_INPUT_TARGET_VLD) { - WRITE_PARSER_REG(PARSER_VIDEO_RP, - READ_VREG(VLD_MEM_VIFIFO_RP)); - } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) { - WRITE_PARSER_REG(PARSER_VIDEO_RP, - READ_VREG(HEVC_STREAM_RD_PTR)); - } -} - -static void vdec_sync_input_write(struct vdec_s *vdec) -{ - if (!vdec_stream_based(vdec)) - return; - - if (vdec->input.target == VDEC_INPUT_TARGET_VLD) { - WRITE_VREG(VLD_MEM_VIFIFO_WP, - READ_PARSER_REG(PARSER_VIDEO_WP)); - } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) { - WRITE_VREG(HEVC_STREAM_WR_PTR, - READ_PARSER_REG(PARSER_VIDEO_WP)); - } -} - -/* - *get next frame from input chain - */ -/* - *THE VLD_FIFO is 512 bytes and Video buffer level - * empty interrupt is set to 0x80 bytes threshold - */ -#define VLD_PADDING_SIZE 1024 -#define HEVC_PADDING_SIZE (1024*16) -int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p) -{ - struct vdec_input_s *input = &vdec->input; - struct vframe_chunk_s *chunk = NULL; - struct vframe_block_list_s *block = NULL; - int dummy; - - /* full reset to HW input */ - if (input->target == VDEC_INPUT_TARGET_VLD) { - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); - - /* reset VLD fifo for all vdec */ - WRITE_VREG(DOS_SW_RESET0, (1<<5) | (1<<4) | (1<<3)); - WRITE_VREG(DOS_SW_RESET0, 0); - - dummy = READ_RESET_REG(RESET0_REGISTER); - WRITE_VREG(POWER_CTL_VLD, 1 << 4); - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { -#if 0 - /*move to driver*/ - if (input_frame_based(input)) - WRITE_VREG(HEVC_STREAM_CONTROL, 0); - - /* - * 2: assist - * 3: parser - * 4: parser_state - * 8: dblk - * 11:mcpu - * 12:ccpu - * 13:ddr - * 14:iqit - * 15:ipp - * 17:qdct - * 18:mpred - * 19:sao - * 24:hevc_afifo - */ - WRITE_VREG(DOS_SW_RESET3, - (1<<3)|(1<<4)|(1<<8)|(1<<11)|(1<<12)|(1<<14)|(1<<15)| - (1<<17)|(1<<18)|(1<<19)); - WRITE_VREG(DOS_SW_RESET3, 0); -#endif - } - - /* - *setup HW decoder input buffer (VLD context) - * based on input->type and input->target - */ - if (input_frame_based(input)) { - chunk = vdec_input_next_chunk(&vdec->input); - - if (chunk == NULL) { - *p = NULL; - return -1; - } - - block = chunk->block; - - if (input->target == VDEC_INPUT_TARGET_VLD) { - WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, block->start); - WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, block->start + - block->size - 8); - WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, - round_down(block->start + chunk->offset, - VDEC_FIFO_ALIGN)); - - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); - - /* set to manual mode */ - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); - WRITE_VREG(VLD_MEM_VIFIFO_RP, - round_down(block->start + chunk->offset, - VDEC_FIFO_ALIGN)); - dummy = chunk->offset + chunk->size + - VLD_PADDING_SIZE; - if (dummy >= block->size) - dummy -= block->size; - WRITE_VREG(VLD_MEM_VIFIFO_WP, - round_down(block->start + dummy, - VDEC_FIFO_ALIGN)); - - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3); - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); - - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, - (0x11 << 16) | (1<<10) | (7<<3)); - - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - WRITE_VREG(HEVC_STREAM_START_ADDR, block->start); - WRITE_VREG(HEVC_STREAM_END_ADDR, block->start + - block->size); - WRITE_VREG(HEVC_STREAM_RD_PTR, block->start + - chunk->offset); - dummy = chunk->offset + chunk->size + - HEVC_PADDING_SIZE; - if (dummy >= block->size) - dummy -= block->size; - WRITE_VREG(HEVC_STREAM_WR_PTR, - round_down(block->start + dummy, - VDEC_FIFO_ALIGN)); - - /* set endian */ - SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4); - } - - *p = chunk; - return chunk->size; - - } else { - /* stream based */ - u32 rp = 0, wp = 0, fifo_len = 0; - int size; - bool swap_valid = input->swap_valid; - unsigned long swap_page_phys = input->swap_page_phys; - - if (vdec_dual(vdec) && - ((vdec->flag & VDEC_FLAG_SELF_INPUT_CONTEXT) == 0)) { - /* keep using previous input context */ - struct vdec_s *master = (vdec->slave) ? - vdec : vdec->master; - if (master->input.last_swap_slave) { - swap_valid = master->slave->input.swap_valid; - swap_page_phys = - master->slave->input.swap_page_phys; - } else { - swap_valid = master->input.swap_valid; - swap_page_phys = master->input.swap_page_phys; - } - } - - if (swap_valid) { - if (input->target == VDEC_INPUT_TARGET_VLD) { - if (vdec->format == VFORMAT_H264) - SET_VREG_MASK(POWER_CTL_VLD, - (1 << 9)); - - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); - - /* restore read side */ - WRITE_VREG(VLD_MEM_SWAP_ADDR, - swap_page_phys); - WRITE_VREG(VLD_MEM_SWAP_CTL, 1); - - while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) - ; - WRITE_VREG(VLD_MEM_SWAP_CTL, 0); - - /* restore wrap count */ - WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, - input->stream_cookie); - - rp = READ_VREG(VLD_MEM_VIFIFO_RP); - fifo_len = READ_VREG(VLD_MEM_VIFIFO_LEVEL); - - /* enable */ - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, - (0x11 << 16) | (1<<10)); - - /* sync with front end */ - vdec_sync_input_read(vdec); - vdec_sync_input_write(vdec); - - wp = READ_VREG(VLD_MEM_VIFIFO_WP); - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); - - /* restore read side */ - WRITE_VREG(HEVC_STREAM_SWAP_ADDR, - swap_page_phys); - WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1); - - while (READ_VREG(HEVC_STREAM_SWAP_CTRL) - & (1<<7)) - ; - WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); - - /* restore stream offset */ - WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, - input->stream_cookie); - - rp = READ_VREG(HEVC_STREAM_RD_PTR); - fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL) - >> 16) & 0x7f; - - - /* enable */ - - /* sync with front end */ - vdec_sync_input_read(vdec); - vdec_sync_input_write(vdec); - - wp = READ_VREG(HEVC_STREAM_WR_PTR); - - /*pr_info("vdec: restore context\r\n");*/ - } - - } else { - if (input->target == VDEC_INPUT_TARGET_VLD) { - WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, - input->start); - WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, - input->start + input->size - 8); - WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, - input->start); - - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); - - /* set to manual mode */ - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); - WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start); - WRITE_VREG(VLD_MEM_VIFIFO_WP, - READ_PARSER_REG(PARSER_VIDEO_WP)); - - rp = READ_VREG(VLD_MEM_VIFIFO_RP); - - /* enable */ - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, - (0x11 << 16) | (1<<10)); - - wp = READ_VREG(VLD_MEM_VIFIFO_WP); - - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - WRITE_VREG(HEVC_STREAM_START_ADDR, - input->start); - WRITE_VREG(HEVC_STREAM_END_ADDR, - input->start + input->size); - WRITE_VREG(HEVC_STREAM_RD_PTR, - input->start); - WRITE_VREG(HEVC_STREAM_WR_PTR, - READ_PARSER_REG(PARSER_VIDEO_WP)); - - rp = READ_VREG(HEVC_STREAM_RD_PTR); - wp = READ_VREG(HEVC_STREAM_WR_PTR); - fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL) - >> 16) & 0x7f; - - /* enable */ - } - } - *p = NULL; - if (wp >= rp) - size = wp - rp + fifo_len; - else - size = wp + input->size - rp + fifo_len; - if (size < 0) { - pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n", - __func__, input->size, wp, rp, fifo_len, size); - size = 0; - } - return size; - } -} -EXPORT_SYMBOL(vdec_prepare_input); - -void vdec_enable_input(struct vdec_s *vdec) -{ - struct vdec_input_s *input = &vdec->input; - - if (vdec->status != VDEC_STATUS_ACTIVE) - return; - - if (input->target == VDEC_INPUT_TARGET_VLD) - SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1<<2) | (1<<1)); - else if (input->target == VDEC_INPUT_TARGET_HEVC) { - SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); - if (vdec_stream_based(vdec)) - CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4); - else - SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4); - SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29)); - } -} -EXPORT_SYMBOL(vdec_enable_input); - -int vdec_set_input_buffer(struct vdec_s *vdec, u32 start, u32 size) -{ - int r = vdec_input_set_buffer(&vdec->input, start, size); - - if (r) - return r; - - if (vdec->slave) - r = vdec_input_set_buffer(&vdec->slave->input, start, size); - - return r; -} -EXPORT_SYMBOL(vdec_set_input_buffer); - -/* - * vdec_eos returns the possibility that there are - * more input can be used by decoder through vdec_prepare_input - * Note: this function should be called prior to vdec_vframe_dirty - * by decoder driver to determine if EOS happens for stream based - * decoding when there is no sufficient data for a frame - */ -bool vdec_has_more_input(struct vdec_s *vdec) -{ - struct vdec_input_s *input = &vdec->input; - - if (!input->eos) - return true; - - if (input_frame_based(input)) - return vdec_input_next_input_chunk(input) != NULL; - else { - if (input->target == VDEC_INPUT_TARGET_VLD) - return READ_VREG(VLD_MEM_VIFIFO_WP) != - READ_PARSER_REG(PARSER_VIDEO_WP); - else { - return (READ_VREG(HEVC_STREAM_WR_PTR) & ~0x3) != - (READ_PARSER_REG(PARSER_VIDEO_WP) & ~0x3); - } - } -} -EXPORT_SYMBOL(vdec_has_more_input); - -void vdec_set_prepare_level(struct vdec_s *vdec, int level) -{ - vdec->input.prepare_level = level; -} -EXPORT_SYMBOL(vdec_set_prepare_level); - -void vdec_set_flag(struct vdec_s *vdec, u32 flag) -{ - vdec->flag = flag; -} -EXPORT_SYMBOL(vdec_set_flag); - -void vdec_set_eos(struct vdec_s *vdec, bool eos) -{ - vdec->input.eos = eos; - - if (vdec->slave) - vdec->slave->input.eos = eos; -} -EXPORT_SYMBOL(vdec_set_eos); - -#ifdef VDEC_DEBUG_SUPPORT -void vdec_set_step_mode(void) -{ - step_mode = 0x1ff; -} -EXPORT_SYMBOL(vdec_set_step_mode); -#endif - -void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec) -{ - if (vdec && next_vdec) { - vdec->sched = 0; - next_vdec->sched = 1; - } -} -EXPORT_SYMBOL(vdec_set_next_sched); - -/* - * Swap Context: S0 S1 S2 S3 S4 - * Sample sequence: M S M M S - * Master Context: S0 S0 S2 S3 S3 - * Slave context: NA S1 S1 S2 S4 - * ^ - * ^ - * ^ - * the tricky part - * If there are back to back decoding of master or slave - * then the context of the counter part should be updated - * with current decoder. In this example, S1 should be - * updated to S2. - * This is done by swap the swap_page and related info - * between two layers. - */ -static void vdec_borrow_input_context(struct vdec_s *vdec) -{ - struct page *swap_page; - unsigned long swap_page_phys; - struct vdec_input_s *me; - struct vdec_input_s *other; - - if (!vdec_dual(vdec)) - return; - - me = &vdec->input; - other = &vdec_get_associate(vdec)->input; - - /* swap the swap_context, borrow counter part's - * swap context storage and update all related info. - * After vdec_vframe_dirty, vdec_save_input_context - * will be called to update current vdec's - * swap context - */ - swap_page = other->swap_page; - other->swap_page = me->swap_page; - me->swap_page = swap_page; - - swap_page_phys = other->swap_page_phys; - other->swap_page_phys = me->swap_page_phys; - me->swap_page_phys = swap_page_phys; - - other->swap_rp = me->swap_rp; - other->streaming_rp = me->streaming_rp; - other->stream_cookie = me->stream_cookie; - other->swap_valid = me->swap_valid; -} - -void vdec_vframe_dirty(struct vdec_s *vdec, struct vframe_chunk_s *chunk) -{ - if (chunk) - chunk->flag |= VFRAME_CHUNK_FLAG_CONSUMED; - - if (vdec_stream_based(vdec)) { - vdec->input.swap_needed = true; - - if (vdec_dual(vdec)) { - vdec_get_associate(vdec)->input.dirty_count = 0; - vdec->input.dirty_count++; - if (vdec->input.dirty_count > 1) { - vdec->input.dirty_count = 1; - vdec_borrow_input_context(vdec); - } - } - - /* for stream based mode, we update read and write pointer - * also in case decoder wants to keep working on decoding - * for more frames while input front end has more data - */ - vdec_sync_input_read(vdec); - vdec_sync_input_write(vdec); - - vdec->need_more_data |= VDEC_NEED_MORE_DATA_DIRTY; - vdec->need_more_data &= ~VDEC_NEED_MORE_DATA; - } -} -EXPORT_SYMBOL(vdec_vframe_dirty); - -bool vdec_need_more_data(struct vdec_s *vdec) -{ - if (vdec_stream_based(vdec)) - return vdec->need_more_data & VDEC_NEED_MORE_DATA; - - return false; -} -EXPORT_SYMBOL(vdec_need_more_data); - - -void hevc_wait_ddr(void) -{ - unsigned long flags; - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4))); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & (1 << 4))) - ; -} - -void vdec_save_input_context(struct vdec_s *vdec) -{ - struct vdec_input_s *input = &vdec->input; - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vdec_profile(vdec, VDEC_PROFILE_EVENT_SAVE_INPUT); -#endif - - if (input->target == VDEC_INPUT_TARGET_VLD) - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1<<15); - - if (input_stream_based(input) && (input->swap_needed)) { - if (input->target == VDEC_INPUT_TARGET_VLD) { - WRITE_VREG(VLD_MEM_SWAP_ADDR, - input->swap_page_phys); - WRITE_VREG(VLD_MEM_SWAP_CTL, 3); - while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) - ; - WRITE_VREG(VLD_MEM_SWAP_CTL, 0); - vdec->input.stream_cookie = - READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT); - vdec->input.swap_rp = - READ_VREG(VLD_MEM_VIFIFO_RP); - vdec->input.total_rd_count = - (u64)vdec->input.stream_cookie * - vdec->input.size + vdec->input.swap_rp - - READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL); - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - WRITE_VREG(HEVC_STREAM_SWAP_ADDR, - input->swap_page_phys); - WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 3); - - while (READ_VREG(HEVC_STREAM_SWAP_CTRL) & (1<<7)) - ; - WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); - - vdec->input.stream_cookie = - READ_VREG(HEVC_SHIFT_BYTE_COUNT); - vdec->input.swap_rp = - READ_VREG(HEVC_STREAM_RD_PTR); - if (((vdec->input.stream_cookie & 0x80000000) == 0) && - (vdec->input.streaming_rp & 0x80000000)) - vdec->input.streaming_rp += 1ULL << 32; - vdec->input.streaming_rp &= 0xffffffffULL << 32; - vdec->input.streaming_rp |= vdec->input.stream_cookie; - vdec->input.total_rd_count = vdec->input.streaming_rp; - } - - input->swap_valid = true; - input->swap_needed = false; - /*pr_info("vdec: save context\r\n");*/ - - vdec_sync_input_read(vdec); - - if (vdec_dual(vdec)) { - struct vdec_s *master = (vdec->slave) ? - vdec : vdec->master; - master->input.last_swap_slave = (master->slave == vdec); - /* pr_info("master->input.last_swap_slave = %d\n", - master->input.last_swap_slave); */ - } - - hevc_wait_ddr(); - } -} -EXPORT_SYMBOL(vdec_save_input_context); - -void vdec_clean_input(struct vdec_s *vdec) -{ - struct vdec_input_s *input = &vdec->input; - - while (!list_empty(&input->vframe_chunk_list)) { - struct vframe_chunk_s *chunk = - vdec_input_next_chunk(input); - if (chunk && (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED)) - vdec_input_release_chunk(input, chunk); - else - break; - } - vdec_save_input_context(vdec); -} -EXPORT_SYMBOL(vdec_clean_input); - - -static int vdec_input_read_restore(struct vdec_s *vdec) -{ - struct vdec_input_s *input = &vdec->input; - - if (!vdec_stream_based(vdec)) - return 0; - - if (!input->swap_valid) { - if (input->target == VDEC_INPUT_TARGET_VLD) { - WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, - input->start); - WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, - input->start + input->size - 8); - WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, - input->start); - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); - WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); - - /* set to manual mode */ - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); - WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start); - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - WRITE_VREG(HEVC_STREAM_START_ADDR, - input->start); - WRITE_VREG(HEVC_STREAM_END_ADDR, - input->start + input->size); - WRITE_VREG(HEVC_STREAM_RD_PTR, - input->start); - } - return 0; - } - if (input->target == VDEC_INPUT_TARGET_VLD) { - /* restore read side */ - WRITE_VREG(VLD_MEM_SWAP_ADDR, - input->swap_page_phys); - - /*swap active*/ - WRITE_VREG(VLD_MEM_SWAP_CTL, 1); - - /*wait swap busy*/ - while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) - ; - - WRITE_VREG(VLD_MEM_SWAP_CTL, 0); - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - /* restore read side */ - WRITE_VREG(HEVC_STREAM_SWAP_ADDR, - input->swap_page_phys); - WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1); - - while (READ_VREG(HEVC_STREAM_SWAP_CTRL) - & (1<<7)) - ; - WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); - } - - return 0; -} - - -int vdec_sync_input(struct vdec_s *vdec) -{ - struct vdec_input_s *input = &vdec->input; - u32 rp = 0, wp = 0, fifo_len = 0; - int size; - - vdec_input_read_restore(vdec); - vdec_sync_input_read(vdec); - vdec_sync_input_write(vdec); - if (input->target == VDEC_INPUT_TARGET_VLD) { - rp = READ_VREG(VLD_MEM_VIFIFO_RP); - wp = READ_VREG(VLD_MEM_VIFIFO_WP); - - } else if (input->target == VDEC_INPUT_TARGET_HEVC) { - rp = READ_VREG(HEVC_STREAM_RD_PTR); - wp = READ_VREG(HEVC_STREAM_WR_PTR); - fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL) - >> 16) & 0x7f; - } - if (wp >= rp) - size = wp - rp + fifo_len; - else - size = wp + input->size - rp + fifo_len; - if (size < 0) { - pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n", - __func__, input->size, wp, rp, fifo_len, size); - size = 0; - } - return size; - -} -EXPORT_SYMBOL(vdec_sync_input); - -const char *vdec_status_str(struct vdec_s *vdec) -{ - return vdec->status < ARRAY_SIZE(vdec_status_string) ? - vdec_status_string[vdec->status] : "INVALID"; -} - -const char *vdec_type_str(struct vdec_s *vdec) -{ - switch (vdec->type) { - case VDEC_TYPE_SINGLE: - return "VDEC_TYPE_SINGLE"; - case VDEC_TYPE_STREAM_PARSER: - return "VDEC_TYPE_STREAM_PARSER"; - case VDEC_TYPE_FRAME_BLOCK: - return "VDEC_TYPE_FRAME_BLOCK"; - case VDEC_TYPE_FRAME_CIRCULAR: - return "VDEC_TYPE_FRAME_CIRCULAR"; - default: - return "VDEC_TYPE_INVALID"; - } -} - -const char *vdec_device_name_str(struct vdec_s *vdec) -{ - return vdec_device_name[vdec->format * 2 + 1]; -} -EXPORT_SYMBOL(vdec_device_name_str); - -void walk_vdec_core_list(char *s) -{ - struct vdec_s *vdec; - struct vdec_core_s *core = vdec_core; - unsigned long flags; - - pr_info("%s --->\n", s); - - flags = vdec_core_lock(vdec_core); - - if (list_empty(&core->connected_vdec_list)) { - pr_info("connected vdec list empty\n"); - } else { - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - pr_info("\tvdec (%p), status = %s\n", vdec, - vdec_status_str(vdec)); - } - } - - vdec_core_unlock(vdec_core, flags); -} -EXPORT_SYMBOL(walk_vdec_core_list); - -/* insert vdec to vdec_core for scheduling, - * for dual running decoders, connect/disconnect always runs in pairs - */ -int vdec_connect(struct vdec_s *vdec) -{ - unsigned long flags; - - //trace_vdec_connect(vdec);/*DEBUG_TMP*/ - - if (vdec->status != VDEC_STATUS_DISCONNECTED) - return 0; - - vdec_set_status(vdec, VDEC_STATUS_CONNECTED); - vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED); - - init_completion(&vdec->inactive_done); - - if (vdec->slave) { - vdec_set_status(vdec->slave, VDEC_STATUS_CONNECTED); - vdec_set_next_status(vdec->slave, VDEC_STATUS_CONNECTED); - - init_completion(&vdec->slave->inactive_done); - } - - flags = vdec_core_lock(vdec_core); - - list_add_tail(&vdec->list, &vdec_core->connected_vdec_list); - - if (vdec->slave) { - list_add_tail(&vdec->slave->list, - &vdec_core->connected_vdec_list); - } - - vdec_core_unlock(vdec_core, flags); - - up(&vdec_core->sem); - - return 0; -} -EXPORT_SYMBOL(vdec_connect); - -/* remove vdec from vdec_core scheduling */ -int vdec_disconnect(struct vdec_s *vdec) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vdec_profile(vdec, VDEC_PROFILE_EVENT_DISCONNECT); -#endif - //trace_vdec_disconnect(vdec);/*DEBUG_TMP*/ - - if ((vdec->status != VDEC_STATUS_CONNECTED) && - (vdec->status != VDEC_STATUS_ACTIVE)) { - return 0; - } - mutex_lock(&vdec_mutex); - /* - *when a vdec is under the management of scheduler - * the status change will only be from vdec_core_thread - */ - vdec_set_next_status(vdec, VDEC_STATUS_DISCONNECTED); - - if (vdec->slave) - vdec_set_next_status(vdec->slave, VDEC_STATUS_DISCONNECTED); - else if (vdec->master) - vdec_set_next_status(vdec->master, VDEC_STATUS_DISCONNECTED); - mutex_unlock(&vdec_mutex); - up(&vdec_core->sem); - - if(!wait_for_completion_timeout(&vdec->inactive_done, - msecs_to_jiffies(2000))) - goto discon_timeout; - - if (vdec->slave) { - if(!wait_for_completion_timeout(&vdec->slave->inactive_done, - msecs_to_jiffies(2000))) - goto discon_timeout; - } else if (vdec->master) { - if(!wait_for_completion_timeout(&vdec->master->inactive_done, - msecs_to_jiffies(2000))) - goto discon_timeout; - } - - return 0; -discon_timeout: - pr_err("%s timeout!!! status: 0x%x\n", __func__, vdec->status); - return 0; -} -EXPORT_SYMBOL(vdec_disconnect); - -/* release vdec structure */ -int vdec_destroy(struct vdec_s *vdec) -{ - //trace_vdec_destroy(vdec);/*DEBUG_TMP*/ - - vdec_input_release(&vdec->input); - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vdec_profile_flush(vdec); -#endif - ida_simple_remove(&vdec_core->ida, vdec->id); - vfree(vdec); - - atomic_dec(&vdec_core->vdec_nr); - - return 0; -} -EXPORT_SYMBOL(vdec_destroy); - -/* - * Only support time sliced decoding for frame based input, - * so legacy decoder can exist with time sliced decoder. - */ -static const char *get_dev_name(bool use_legacy_vdec, int format) -{ -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (use_legacy_vdec) - return vdec_device_name[format * 2]; - else - return vdec_device_name[format * 2 + 1]; -#else - return vdec_device_name[format]; -#endif -} - -struct vdec_s *vdec_get_with_id(unsigned int id) -{ - struct vdec_s *vdec, *ret_vdec = NULL; - struct vdec_core_s *core = vdec_core; - unsigned long flags; - - if (id >= MAX_INSTANCE_MUN) - return NULL; - - flags = vdec_core_lock(vdec_core); - if (!list_empty(&core->connected_vdec_list)) { - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - if (vdec->id == id) { - pr_info("searched avaliable vdec connected, id = %d\n", id); - ret_vdec = vdec; - break; - } - } - } - vdec_core_unlock(vdec_core, flags); - - return ret_vdec; -} - -/* - *register vdec_device - * create output, vfm or create ionvideo output - */ -s32 vdec_init(struct vdec_s *vdec, int is_4k) -{ - int r = 0; - struct vdec_s *p = vdec; - const char *dev_name; - int id = PLATFORM_DEVID_AUTO;/*if have used my self*/ - - dev_name = get_dev_name(vdec_single(vdec), vdec->format); - - if (dev_name == NULL) - return -ENODEV; - - pr_info("vdec_init, dev_name:%s, vdec_type=%s\n", - dev_name, vdec_type_str(vdec)); - - /* - *todo: VFM patch control should be configurable, - * for now all stream based input uses default VFM path. - */ - if (vdec_stream_based(vdec) && !vdec_dual(vdec)) { - if (vdec_core->vfm_vdec == NULL) { - pr_debug("vdec_init set vfm decoder %p\n", vdec); - vdec_core->vfm_vdec = vdec; - } else { - pr_info("vdec_init vfm path busy.\n"); - return -EBUSY; - } - } - - mutex_lock(&vdec_mutex); - inited_vcodec_num++; - mutex_unlock(&vdec_mutex); - - vdec_input_set_type(&vdec->input, vdec->type, - (vdec->format == VFORMAT_HEVC || - vdec->format == VFORMAT_AVS2 || - vdec->format == VFORMAT_VP9) ? - VDEC_INPUT_TARGET_HEVC : - VDEC_INPUT_TARGET_VLD); - - p->cma_dev = vdec_core->cma_dev; - p->get_canvas = get_canvas; - p->get_canvas_ex = get_canvas_ex; - p->free_canvas_ex = free_canvas_ex; - p->vdec_fps_detec = vdec_fps_detec; - atomic_set(&p->inirq_flag, 0); - atomic_set(&p->inirq_thread_flag, 0); - /* todo */ - if (!vdec_dual(vdec)) - p->use_vfm_path = vdec_stream_based(vdec); - /* vdec_dev_reg.flag = 0; */ - if (vdec->id >= 0) - id = vdec->id; - p->parallel_dec = parallel_decode; - vdec_core->parallel_dec = parallel_decode; - vdec->canvas_mode = CANVAS_BLKMODE_32X32; -#ifdef FRAME_CHECK - vdec_frame_check_init(vdec); -#endif - p->dev = platform_device_register_data( - &vdec_core->vdec_core_platform_device->dev, - dev_name, - id, - &p, sizeof(struct vdec_s *)); - - if (IS_ERR(p->dev)) { - r = PTR_ERR(p->dev); - pr_err("vdec: Decoder device %s register failed (%d)\n", - dev_name, r); - - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); - - goto error; - } else if (!p->dev->dev.driver) { - pr_info("vdec: Decoder device %s driver probe failed.\n", - dev_name); - r = -ENODEV; - - goto error; - } - - if ((p->type == VDEC_TYPE_FRAME_BLOCK) && (p->run == NULL)) { - r = -ENODEV; - pr_err("vdec: Decoder device not handled (%s)\n", dev_name); - - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); - - goto error; - } - - if (p->use_vfm_path) { - vdec->vf_receiver_inst = -1; - vdec->vfm_map_id[0] = 0; - } else if (!vdec_dual(vdec)) { - /* create IONVIDEO instance and connect decoder's - * vf_provider interface to it - */ - if (p->type != VDEC_TYPE_FRAME_BLOCK) { - r = -ENODEV; - pr_err("vdec: Incorrect decoder type\n"); - - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); - - goto error; - } - if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) { -#if 1 - r = ionvideo_assign_map(&vdec->vf_receiver_name, - &vdec->vf_receiver_inst); -#else - /* - * temporarily just use decoder instance ID as iondriver ID - * to solve OMX iondriver instance number check time sequence - * only the limitation is we can NOT mix different video - * decoders since same ID will be used for different decoder - * formats. - */ - vdec->vf_receiver_inst = p->dev->id; - r = ionvideo_assign_map(&vdec->vf_receiver_name, - &vdec->vf_receiver_inst); -#endif - if (r < 0) { - pr_err("IonVideo frame receiver allocation failed.\n"); - - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); - - goto error; - } - - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - vdec->vf_receiver_name); - snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, - "vdec-map-%d", vdec->id); - } else if (p->frame_base_video_path == - FRAME_BASE_PATH_AMLVIDEO_AMVIDEO) { - if (vdec_secure(vdec)) { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - "amlvideo amvideo"); - } else { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - "amlvideo deinterlace amvideo"); - } - snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, - "vdec-map-%d", vdec->id); - } else if (p->frame_base_video_path == - FRAME_BASE_PATH_AMLVIDEO1_AMVIDEO2) { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - "aml_video.1 videosync.0 videopip"); - snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, - "vdec-map-%d", vdec->id); - } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - vdec->vf_receiver_name); - snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, - "vdec-map-%d", vdec->id); - } else if (p->frame_base_video_path == FRAME_BASE_PATH_TUNNEL_MODE) { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - "amvideo"); - snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, - "vdec-map-%d", vdec->id); - } - - if (vfm_map_add(vdec->vfm_map_id, - vdec->vfm_map_chain) < 0) { - r = -ENOMEM; - pr_err("Decoder pipeline map creation failed %s.\n", - vdec->vfm_map_id); - vdec->vfm_map_id[0] = 0; - - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); - - goto error; - } - - pr_debug("vfm map %s created\n", vdec->vfm_map_id); - - /* - *assume IONVIDEO driver already have a few vframe_receiver - * registered. - * 1. Call iondriver function to allocate a IONVIDEO path and - * provide receiver's name and receiver op. - * 2. Get decoder driver's provider name from driver instance - * 3. vfm_map_add(name, " - * "), e.g. - * vfm_map_add("vdec_ion_map_0", "mpeg4_0 iondriver_1"); - * 4. vf_reg_provider and vf_reg_receiver - * Note: the decoder provider's op uses vdec as op_arg - * the iondriver receiver's op uses iondev device as - * op_arg - */ - - } - - if (!vdec_single(vdec)) { - vf_reg_provider(&p->vframe_provider); - - vf_notify_receiver(p->vf_provider_name, - VFRAME_EVENT_PROVIDER_START, - vdec); - - if (vdec_core->hint_fr_vdec == NULL) - vdec_core->hint_fr_vdec = vdec; - - if (vdec_core->hint_fr_vdec == vdec) { - if (p->sys_info->rate != 0) { - if (!vdec->is_reset) { - vf_notify_receiver(p->vf_provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long) - p->sys_info->rate)); - vdec->fr_hint_state = VDEC_HINTED; - } - } else { - vdec->fr_hint_state = VDEC_NEED_HINT; - } - } - } - - p->dolby_meta_with_el = 0; - pr_debug("vdec_init, vf_provider_name = %s\n", p->vf_provider_name); - vdec_input_prepare_bufs(/*prepared buffer for fast playing.*/ - &vdec->input, - vdec->sys_info->width, - vdec->sys_info->height); - /* vdec is now ready to be active */ - vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); - if (p->use_vfm_path) { - frame_info_buf_in = (struct vframe_qos_s *) - kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); - if (!frame_info_buf_in) - pr_err("kmalloc: frame_info_buf_in failed\n"); - else - memset(frame_info_buf_in, 0, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); - - frame_info_buf_out = (struct vframe_qos_s *) - kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); - if (!frame_info_buf_out) - pr_err("kmalloc: frame_info_buf_out failed\n"); - else - memset(frame_info_buf_out, 0, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); - frame_qos_wr = 0; - frame_qos_rd = 0; - } - return 0; - -error: - return r; -} -EXPORT_SYMBOL(vdec_init); - -/* vdec_create/init/release/destroy are applied to both dual running decoders - */ -void vdec_release(struct vdec_s *vdec) -{ - //trace_vdec_release(vdec);/*DEBUG_TMP*/ -#ifdef VDEC_DEBUG_SUPPORT - if (step_mode) { - pr_info("VDEC_DEBUG: in step_mode, wait release\n"); - while (step_mode) - udelay(10); - pr_info("VDEC_DEBUG: step_mode is clear\n"); - } -#endif - vdec_disconnect(vdec); - - if (vdec->vframe_provider.name) { - if (!vdec_single(vdec)) { - if (vdec_core->hint_fr_vdec == vdec - && vdec->fr_hint_state == VDEC_HINTED) - vf_notify_receiver( - vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - vdec->fr_hint_state = VDEC_NO_NEED_HINT; - } - vf_unreg_provider(&vdec->vframe_provider); - } - - if (vdec_core->vfm_vdec == vdec) - vdec_core->vfm_vdec = NULL; - - if (vdec_core->hint_fr_vdec == vdec) - vdec_core->hint_fr_vdec = NULL; - - if (vdec->vf_receiver_inst >= 0) { - if (vdec->vfm_map_id[0]) { - vfm_map_remove(vdec->vfm_map_id); - vdec->vfm_map_id[0] = 0; - } - } - - while ((atomic_read(&vdec->inirq_flag) > 0) - || (atomic_read(&vdec->inirq_thread_flag) > 0)) - schedule(); - -#ifdef FRAME_CHECK - vdec_frame_check_exit(vdec); -#endif - vdec_fps_clear(vdec->id); - - platform_device_unregister(vdec->dev); - pr_debug("vdec_release instance %p, total %d\n", vdec, - atomic_read(&vdec_core->vdec_nr)); - if (vdec->use_vfm_path) { - kfree(frame_info_buf_in); - frame_info_buf_in = NULL; - kfree(frame_info_buf_out); - frame_info_buf_out = NULL; - frame_qos_wr = 0; - frame_qos_rd = 0; - } - vdec_destroy(vdec); - - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); - -} -EXPORT_SYMBOL(vdec_release); - -/* For dual running decoders, vdec_reset is only called with master vdec. - */ -int vdec_reset(struct vdec_s *vdec) -{ - //trace_vdec_reset(vdec); /*DEBUG_TMP*/ - - vdec_disconnect(vdec); - - if (vdec->vframe_provider.name) - vf_unreg_provider(&vdec->vframe_provider); - - if ((vdec->slave) && (vdec->slave->vframe_provider.name)) - vf_unreg_provider(&vdec->slave->vframe_provider); - - if (vdec->reset) { - vdec->reset(vdec); - if (vdec->slave) - vdec->slave->reset(vdec->slave); - } - vdec->mc_loaded = 0;/*clear for reload firmware*/ - vdec_input_release(&vdec->input); - - vdec_input_init(&vdec->input, vdec); - - vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width, - vdec->sys_info->height); - - vf_reg_provider(&vdec->vframe_provider); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_START, vdec); - - if (vdec->slave) { - vf_reg_provider(&vdec->slave->vframe_provider); - vf_notify_receiver(vdec->slave->vf_provider_name, - VFRAME_EVENT_PROVIDER_START, vdec->slave); - vdec->slave->mc_loaded = 0;/*clear for reload firmware*/ - } - - vdec_connect(vdec); - - return 0; -} -EXPORT_SYMBOL(vdec_reset); - -void vdec_free_cmabuf(void) -{ - mutex_lock(&vdec_mutex); - - /*if (inited_vcodec_num > 0) { - mutex_unlock(&vdec_mutex); - return; - }*/ - mutex_unlock(&vdec_mutex); -} - -void vdec_core_request(struct vdec_s *vdec, unsigned long mask) -{ - vdec->core_mask |= mask; - - if (vdec->slave) - vdec->slave->core_mask |= mask; - if (vdec_core->parallel_dec == 1) { - if (mask & CORE_MASK_COMBINE) - vdec_core->vdec_combine_flag++; - } - -} -EXPORT_SYMBOL(vdec_core_request); - -int vdec_core_release(struct vdec_s *vdec, unsigned long mask) -{ - vdec->core_mask &= ~mask; - - if (vdec->slave) - vdec->slave->core_mask &= ~mask; - if (vdec_core->parallel_dec == 1) { - if (mask & CORE_MASK_COMBINE) - vdec_core->vdec_combine_flag--; - } - return 0; -} -EXPORT_SYMBOL(vdec_core_release); - -bool vdec_core_with_input(unsigned long mask) -{ - enum vdec_type_e type; - - for (type = VDEC_1; type < VDEC_MAX; type++) { - if ((mask & (1 << type)) && cores_with_input[type]) - return true; - } - - return false; -} - -void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask) -{ - unsigned long i; - unsigned long t = mask; - mutex_lock(&vdec_mutex); - while (t) { - i = __ffs(t); - clear_bit(i, &vdec->active_mask); - t &= ~(1 << i); - } - - if (vdec->active_mask == 0) - vdec_set_status(vdec, VDEC_STATUS_CONNECTED); - - mutex_unlock(&vdec_mutex); -} -EXPORT_SYMBOL(vdec_core_finish_run); -/* - * find what core resources are available for vdec - */ -static unsigned long vdec_schedule_mask(struct vdec_s *vdec, - unsigned long active_mask) -{ - unsigned long mask = vdec->core_mask & - ~CORE_MASK_COMBINE; - - if (vdec->core_mask & CORE_MASK_COMBINE) { - /* combined cores must be granted together */ - if ((mask & ~active_mask) == mask) - return mask; - else - return 0; - } else - return mask & ~vdec->sched_mask & ~active_mask; -} - -/* - *Decoder callback - * Each decoder instance uses this callback to notify status change, e.g. when - * decoder finished using HW resource. - * a sample callback from decoder's driver is following: - * - * if (hw->vdec_cb) { - * vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED); - * hw->vdec_cb(vdec, hw->vdec_cb_arg); - * } - */ -static void vdec_callback(struct vdec_s *vdec, void *data) -{ - struct vdec_core_s *core = (struct vdec_core_s *)data; - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vdec_profile(vdec, VDEC_PROFILE_EVENT_CB); -#endif - - up(&core->sem); -} - -static irqreturn_t vdec_isr(int irq, void *dev_id) -{ - struct vdec_isr_context_s *c = - (struct vdec_isr_context_s *)dev_id; - struct vdec_s *vdec = vdec_core->last_vdec; - irqreturn_t ret = IRQ_HANDLED; - - if (vdec_core->parallel_dec == 1) { - if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq) - vdec = vdec_core->active_hevc; - else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq) - vdec = vdec_core->active_vdec; - else - vdec = NULL; - } - - if (vdec) - atomic_set(&vdec->inirq_flag, 1); - if (c->dev_isr) { - ret = c->dev_isr(irq, c->dev_id); - goto isr_done; - } - - if ((c != &vdec_core->isr_context[VDEC_IRQ_0]) && - (c != &vdec_core->isr_context[VDEC_IRQ_1]) && - (c != &vdec_core->isr_context[VDEC_IRQ_HEVC_BACK])) { -#if 0 - pr_warn("vdec interrupt w/o a valid receiver\n"); -#endif - goto isr_done; - } - - if (!vdec) { -#if 0 - pr_warn("vdec interrupt w/o an active instance running. core = %p\n", - core); -#endif - goto isr_done; - } - - if (!vdec->irq_handler) { -#if 0 - pr_warn("vdec instance has no irq handle.\n"); -#endif - goto isr_done; - } - - ret = vdec->irq_handler(vdec, c->index); -isr_done: - if (vdec) - atomic_set(&vdec->inirq_flag, 0); - return ret; -} - -static irqreturn_t vdec_thread_isr(int irq, void *dev_id) -{ - struct vdec_isr_context_s *c = - (struct vdec_isr_context_s *)dev_id; - struct vdec_s *vdec = vdec_core->last_vdec; - irqreturn_t ret = IRQ_HANDLED; - - if (vdec_core->parallel_dec == 1) { - if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq) - vdec = vdec_core->active_hevc; - else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq) - vdec = vdec_core->active_vdec; - else - vdec = NULL; - } - - if (vdec) - atomic_set(&vdec->inirq_thread_flag, 1); - if (c->dev_threaded_isr) { - ret = c->dev_threaded_isr(irq, c->dev_id); - goto thread_isr_done; - } - if (!vdec) - goto thread_isr_done; - - if (!vdec->threaded_irq_handler) - goto thread_isr_done; - ret = vdec->threaded_irq_handler(vdec, c->index); -thread_isr_done: - if (vdec) - atomic_set(&vdec->inirq_thread_flag, 0); - return ret; -} - -unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask) -{ - unsigned long ready_mask; - struct vdec_input_s *input = &vdec->input; - if ((vdec->status != VDEC_STATUS_CONNECTED) && - (vdec->status != VDEC_STATUS_ACTIVE)) - return false; - - if (!vdec->run_ready) - return false; - - /* when crc32 error, block at error frame */ - if (vdec->vfc.err_crc_block) - return false; - - if ((vdec->slave || vdec->master) && - (vdec->sched == 0)) - return false; -#ifdef VDEC_DEBUG_SUPPORT - inc_profi_count(mask, vdec->check_count); -#endif - if (vdec_core_with_input(mask)) { - /* check frame based input underrun */ - if (input && !input->eos && input_frame_based(input) - && (!vdec_input_next_chunk(input))) { -#ifdef VDEC_DEBUG_SUPPORT - inc_profi_count(mask, vdec->input_underrun_count); -#endif - return false; - } - /* check streaming prepare level threshold if not EOS */ - if (input && input_stream_based(input) && !input->eos) { - u32 rp, wp, level; - - rp = READ_PARSER_REG(PARSER_VIDEO_RP); - wp = READ_PARSER_REG(PARSER_VIDEO_WP); - if (wp < rp) - level = input->size + wp - rp; - else - level = wp - rp; - - if ((level < input->prepare_level) && - (pts_get_rec_num(PTS_TYPE_VIDEO, - vdec->input.total_rd_count) < 2)) { - vdec->need_more_data |= VDEC_NEED_MORE_DATA; -#ifdef VDEC_DEBUG_SUPPORT - inc_profi_count(mask, vdec->input_underrun_count); - if (step_mode & 0x200) { - if ((step_mode & 0xff) == vdec->id) { - step_mode |= 0xff; - return mask; - } - } -#endif - return false; - } else if (level > input->prepare_level) - vdec->need_more_data &= ~VDEC_NEED_MORE_DATA; - } - } - - if (step_mode) { - if ((step_mode & 0xff) != vdec->id) - return 0; - step_mode |= 0xff; /*VDEC_DEBUG_SUPPORT*/ - } - - /*step_mode &= ~0xff; not work for id of 0, removed*/ - -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vdec_profile(vdec, VDEC_PROFILE_EVENT_CHK_RUN_READY); -#endif - - ready_mask = vdec->run_ready(vdec, mask) & mask; -#ifdef VDEC_DEBUG_SUPPORT - if (ready_mask != mask) - inc_profi_count(ready_mask ^ mask, vdec->not_run_ready_count); -#endif -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (ready_mask) - vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN_READY); -#endif - - return ready_mask; -} - -/* bridge on/off vdec's interrupt processing to vdec core */ -static void vdec_route_interrupt(struct vdec_s *vdec, unsigned long mask, - bool enable) -{ - enum vdec_type_e type; - - for (type = VDEC_1; type < VDEC_MAX; type++) { - if (mask & (1 << type)) { - struct vdec_isr_context_s *c = - &vdec_core->isr_context[cores_int[type]]; - if (enable) - c->vdec = vdec; - else if (c->vdec == vdec) - c->vdec = NULL; - } - } -} - -/* - * Set up secure protection for each decoder instance running. - * Note: The operation from REE side only resets memory access - * to a default policy and even a non_secure type will still be - * changed to secure type automatically when secure source is - * detected inside TEE. - * Perform need_more_data checking and set flag is decoder - * is not consuming data. - */ -void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) -{ - struct vdec_input_s *input = &vdec->input; - int secure = (vdec_secure(vdec)) ? DMC_DEV_TYPE_SECURE : - DMC_DEV_TYPE_NON_SECURE; - - vdec_route_interrupt(vdec, mask, true); - - if (!vdec_core_with_input(mask)) - return; - - if (secure && vdec_stream_based(vdec) && force_nosecure_even_drm) - { - /* Verimatrix ultra webclient (HLS) was played in drmmode and used hw demux. In drmmode VDEC only can access secure. - Now HW demux parsed es data to no-secure buffer. So the VDEC input was no-secure, VDEC playback failed. Forcing - use nosecure for verimatrix webclient HLS. If in the future HW demux can parse es data to secure buffer, make - VDEC r/w secure.*/ - secure = 0; - //pr_debug("allow VDEC can access nosecure even in drmmode\n"); - } - if (input->target == VDEC_INPUT_TARGET_VLD) - tee_config_device_secure(DMC_DEV_ID_VDEC, secure); - else if (input->target == VDEC_INPUT_TARGET_HEVC) - tee_config_device_secure(DMC_DEV_ID_HEVC, secure); - - if (vdec_stream_based(vdec) && - ((vdec->need_more_data & VDEC_NEED_MORE_DATA_RUN) && - (vdec->need_more_data & VDEC_NEED_MORE_DATA_DIRTY) == 0)) { - vdec->need_more_data |= VDEC_NEED_MORE_DATA; - } - - vdec->need_more_data |= VDEC_NEED_MORE_DATA_RUN; - vdec->need_more_data &= ~VDEC_NEED_MORE_DATA_DIRTY; -} - -/* struct vdec_core_shread manages all decoder instance in active list. When - * a vdec is added into the active list, it can onlt be in two status: - * VDEC_STATUS_CONNECTED(the decoder does not own HW resource and ready to run) - * VDEC_STATUS_ACTIVE(the decoder owns HW resources and is running). - * Removing a decoder from active list is only performed within core thread. - * Adding a decoder into active list is performed from user thread. - */ -static int vdec_core_thread(void *data) -{ - struct vdec_core_s *core = (struct vdec_core_s *)data; - struct sched_param param = {.sched_priority = MAX_RT_PRIO/2}; - unsigned long flags; - int i; - - sched_setscheduler(current, SCHED_FIFO, ¶m); - - allow_signal(SIGTERM); - - while (down_interruptible(&core->sem) == 0) { - struct vdec_s *vdec, *tmp, *worker; - unsigned long sched_mask = 0; - LIST_HEAD(disconnecting_list); - - if (kthread_should_stop()) - break; - mutex_lock(&vdec_mutex); - - if (core->parallel_dec == 1) { - for (i = VDEC_1; i < VDEC_MAX; i++) { - core->power_ref_mask = - core->power_ref_count[i] > 0 ? - (core->power_ref_mask | (1 << i)) : - (core->power_ref_mask & ~(1 << i)); - } - } - /* clean up previous active vdec's input */ - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - unsigned long mask = vdec->sched_mask & - (vdec->active_mask ^ vdec->sched_mask); - - vdec_route_interrupt(vdec, mask, false); - -#ifdef VDEC_DEBUG_SUPPORT - update_profi_clk_stop(vdec, mask, get_current_clk()); -#endif - /* - * If decoder released some core resources (mask), then - * check if these core resources are associated - * with any input side and do input clean up accordingly - */ - if (vdec_core_with_input(mask)) { - struct vdec_input_s *input = &vdec->input; - while (!list_empty( - &input->vframe_chunk_list)) { - struct vframe_chunk_s *chunk = - vdec_input_next_chunk(input); - if (chunk && (chunk->flag & - VFRAME_CHUNK_FLAG_CONSUMED)) - vdec_input_release_chunk(input, - chunk); - else - break; - } - - vdec_save_input_context(vdec); - } - - vdec->sched_mask &= ~mask; - core->sched_mask &= ~mask; - } - - /* - *todo: - * this is the case when the decoder is in active mode and - * the system side wants to stop it. Currently we rely on - * the decoder instance to go back to VDEC_STATUS_CONNECTED - * from VDEC_STATUS_ACTIVE by its own. However, if for some - * reason the decoder can not exist by itself (dead decoding - * or whatever), then we may have to add another vdec API - * to kill the vdec and release its HW resource and make it - * become inactive again. - * if ((core->active_vdec) && - * (core->active_vdec->status == VDEC_STATUS_DISCONNECTED)) { - * } - */ - - /* check disconnected decoders */ - flags = vdec_core_lock(vdec_core); - list_for_each_entry_safe(vdec, tmp, - &core->connected_vdec_list, list) { - if ((vdec->status == VDEC_STATUS_CONNECTED) && - (vdec->next_status == VDEC_STATUS_DISCONNECTED)) { - if (core->parallel_dec == 1) { - if (vdec_core->active_hevc == vdec) - vdec_core->active_hevc = NULL; - if (vdec_core->active_vdec == vdec) - vdec_core->active_vdec = NULL; - } - if (core->last_vdec == vdec) - core->last_vdec = NULL; - list_move(&vdec->list, &disconnecting_list); - } - } - vdec_core_unlock(vdec_core, flags); - mutex_unlock(&vdec_mutex); - /* elect next vdec to be scheduled */ - vdec = core->last_vdec; - if (vdec) { - vdec = list_entry(vdec->list.next, struct vdec_s, list); - list_for_each_entry_from(vdec, - &core->connected_vdec_list, list) { - sched_mask = vdec_schedule_mask(vdec, - core->sched_mask); - if (!sched_mask) - continue; - sched_mask = vdec_ready_to_run(vdec, - sched_mask); - if (sched_mask) - break; - } - - if (&vdec->list == &core->connected_vdec_list) - vdec = NULL; - } - - if (!vdec) { - /* search from beginning */ - list_for_each_entry(vdec, - &core->connected_vdec_list, list) { - sched_mask = vdec_schedule_mask(vdec, - core->sched_mask); - if (vdec == core->last_vdec) { - if (!sched_mask) { - vdec = NULL; - break; - } - - sched_mask = vdec_ready_to_run(vdec, - sched_mask); - - if (!sched_mask) { - vdec = NULL; - break; - } - break; - } - - if (!sched_mask) - continue; - - sched_mask = vdec_ready_to_run(vdec, - sched_mask); - if (sched_mask) - break; - } - - if (&vdec->list == &core->connected_vdec_list) - vdec = NULL; - } - - worker = vdec; - - if (vdec) { - unsigned long mask = sched_mask; - unsigned long i; - - /* setting active_mask should be atomic. - * it can be modified by decoder driver callbacks. - */ - while (sched_mask) { - i = __ffs(sched_mask); - set_bit(i, &vdec->active_mask); - sched_mask &= ~(1 << i); - } - - /* vdec's sched_mask is only set from core thread */ - vdec->sched_mask |= mask; - if (core->last_vdec) { - if ((core->last_vdec != vdec) && - (core->last_vdec->mc_type != vdec->mc_type)) - vdec->mc_loaded = 0;/*clear for reload firmware*/ - } - core->last_vdec = vdec; - if (debug & 2) - vdec->mc_loaded = 0;/*alway reload firmware*/ - vdec_set_status(vdec, VDEC_STATUS_ACTIVE); - - core->sched_mask |= mask; - if (core->parallel_dec == 1) - vdec_save_active_hw(vdec); -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN); -#endif - vdec_prepare_run(vdec, mask); -#ifdef VDEC_DEBUG_SUPPORT - inc_profi_count(mask, vdec->run_count); - update_profi_clk_run(vdec, mask, get_current_clk()); -#endif - vdec->run(vdec, mask, vdec_callback, core); - - - /* we have some cores scheduled, keep working until - * all vdecs are checked with no cores to schedule - */ - if (core->parallel_dec == 1) { - if (vdec_core->vdec_combine_flag == 0) - up(&core->sem); - } else - up(&core->sem); - } - - /* remove disconnected decoder from active list */ - list_for_each_entry_safe(vdec, tmp, &disconnecting_list, list) { - list_del(&vdec->list); - vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); - /*core->last_vdec = NULL;*/ - complete(&vdec->inactive_done); - } - - /* if there is no new work scheduled and nothing - * is running, sleep 20ms - */ - if (core->parallel_dec == 1) { - if (vdec_core->vdec_combine_flag == 0) { - if ((!worker) && - ((core->sched_mask != core->power_ref_mask)) && - (atomic_read(&vdec_core->vdec_nr) > 0)) { - usleep_range(1000, 2000); - up(&core->sem); - } - } else { - if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) { - usleep_range(1000, 2000); - up(&core->sem); - } - } - } else if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) { - usleep_range(1000, 2000); - up(&core->sem); - } - - } - - return 0; -} - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ -static bool test_hevc(u32 decomp_addr, u32 us_delay) -{ - int i; - - /* SW_RESET IPP */ - WRITE_VREG(HEVCD_IPP_TOP_CNTL, 1); - WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0); - - /* initialize all canvas table */ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0); - for (i = 0; i < 32; i++) - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - 0x1 | (i << 8) | decomp_addr); - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1); - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1); - for (i = 0; i < 32; i++) - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); - - /* Initialize mcrcc */ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); - WRITE_VREG(HEVCD_MCRCC_CTL2, 0x0); - WRITE_VREG(HEVCD_MCRCC_CTL3, 0x0); - WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); - - /* Decomp initialize */ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x0); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0); - - /* Frame level initialization */ - WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG, 0x100 | (0x100 << 16)); - WRITE_VREG(HEVCD_IPP_TOP_TILECONFIG3, 0x0); - WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 0x1 << 5); - WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x2 | (0x2 << 2)); - - WRITE_VREG(HEVCD_IPP_CONFIG, 0x0); - WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, 0x0); - - /* Enable SWIMP mode */ - WRITE_VREG(HEVCD_IPP_SWMPREDIF_CONFIG, 0x1); - - /* Enable frame */ - WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x2); - WRITE_VREG(HEVCD_IPP_TOP_FRMCTL, 0x1); - - /* Send SW-command CTB info */ - WRITE_VREG(HEVCD_IPP_SWMPREDIF_CTBINFO, 0x1 << 31); - - /* Send PU_command */ - WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO0, (0x4 << 9) | (0x4 << 16)); - WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO1, 0x1 << 3); - WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO2, 0x0); - WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO3, 0x0); - - udelay(us_delay); - - WRITE_VREG(HEVCD_IPP_DBG_SEL, 0x2 << 4); - - return (READ_VREG(HEVCD_IPP_DBG_DATA) & 3) == 1; -} - -void vdec_power_reset(void) -{ - /* enable vdec1 isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc0); - /* power off vdec1 memories */ - WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL); - /* vdec1 power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc); - - if (has_vdec2()) { - /* enable vdec2 isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x300); - /* power off vdec2 memories */ - WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL); - /* vdec2 power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0x30); - } - - if (has_hdec()) { - /* enable hcodec isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30); - /* power off hcodec memories */ - WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); - /* hcodec power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 3); - } - - if (has_hevc_vdec()) { - /* enable hevc isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc00); - /* power off hevc memories */ - WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); - /* hevc power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc0); - } -} -EXPORT_SYMBOL(vdec_power_reset); - -void vdec_poweron(enum vdec_type_e core) -{ - void *decomp_addr = NULL; - dma_addr_t decomp_dma_addr; - u32 decomp_addr_aligned = 0; - int hevc_loop = 0; - int sleep_val, iso_val; - bool is_power_ctrl_ver2 = false; - - if (core >= VDEC_MAX) - return; - - mutex_lock(&vdec_mutex); - - vdec_core->power_ref_count[core]++; - if (vdec_core->power_ref_count[core] > 1) { - mutex_unlock(&vdec_mutex); - return; - } - - if (vdec_on(core)) { - mutex_unlock(&vdec_mutex); - return; - } - - is_power_ctrl_ver2 = - ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false; - - if (hevc_workaround_needed() && - (core == VDEC_HEVC)) { - decomp_addr = codec_mm_dma_alloc_coherent(MEM_NAME, - SZ_64K + SZ_4K, &decomp_dma_addr, GFP_KERNEL, 0); - - if (decomp_addr) { - decomp_addr_aligned = ALIGN(decomp_dma_addr, SZ_64K); - memset((u8 *)decomp_addr + - (decomp_addr_aligned - decomp_dma_addr), - 0xff, SZ_4K); - } else - pr_err("vdec: alloc HEVC gxbb decomp buffer failed.\n"); - } - - if (core == VDEC_1) { - sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc; - iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0; - - /* vdec1 power on */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_sleep_mask(true, sleep_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("vdec-1 power on ctrl sleep fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); -#endif - /* wait 10uS */ - udelay(10); - /* vdec1 soft reset */ - WRITE_VREG(DOS_SW_RESET0, 0xfffffffc); - WRITE_VREG(DOS_SW_RESET0, 0); - /* enable vdec1 clock */ - /* - *add power on vdec clock level setting,only for m8 chip, - * m8baby and m8m2 can dynamic adjust vdec clock, - * power on with default clock level - */ - amports_switch_gate("clk_vdec_mux", 1); - vdec_clock_hi_enable(); - /* power up vdec memories */ - WRITE_VREG(DOS_MEM_PD_VDEC, 0); - - /* remove vdec1 isolation */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_iso_mask(true, iso_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("vdec-1 power on ctrl iso fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); -#endif - /* reset DOS top registers */ - WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0); - if (get_cpu_major_id() >= - AM_MESON_CPU_MAJOR_ID_GXBB) { - /* - *enable VDEC_1 DMC request - */ - unsigned long flags; - - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - } - } else if (core == VDEC_2) { - if (has_vdec2()) { - /* vdec2 power on */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - ~0x30); - /* wait 10uS */ - udelay(10); - /* vdec2 soft reset */ - WRITE_VREG(DOS_SW_RESET2, 0xffffffff); - WRITE_VREG(DOS_SW_RESET2, 0); - /* enable vdec1 clock */ - vdec2_clock_hi_enable(); - /* power up vdec memories */ - WRITE_VREG(DOS_MEM_PD_VDEC2, 0); - /* remove vdec2 isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - ~0x300); - /* reset DOS top registers */ - WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0); - } - } else if (core == VDEC_HCODEC) { - if (has_hdec()) { - sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3; - iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30; - - /* hcodec power on */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_sleep_mask(true, sleep_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hcodec power on ctrl sleep fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); -#endif - /* wait 10uS */ - udelay(10); - /* hcodec soft reset */ - WRITE_VREG(DOS_SW_RESET1, 0xffffffff); - WRITE_VREG(DOS_SW_RESET1, 0); - /* enable hcodec clock */ - hcodec_clock_enable(); - /* power up hcodec memories */ - WRITE_VREG(DOS_MEM_PD_HCODEC, 0); - /* remove hcodec isolation */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_iso_mask(true, iso_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hcodec power on ctrl iso fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); -#endif - } - } else if (core == VDEC_HEVC) { - if (has_hevc_vdec()) { - bool hevc_fixed = false; - - sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0; - iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00; - - while (!hevc_fixed) { - /* hevc power on */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_sleep_mask(true, sleep_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hevc power on ctrl sleep fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); -#endif - /* wait 10uS */ - udelay(10); - /* hevc soft reset */ - WRITE_VREG(DOS_SW_RESET3, 0xffffffff); - WRITE_VREG(DOS_SW_RESET3, 0); - /* enable hevc clock */ - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); - hevc_clock_hi_enable(); - hevc_back_clock_hi_enable(); - /* power up hevc memories */ - WRITE_VREG(DOS_MEM_PD_HEVC, 0); - /* remove hevc isolation */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_iso_mask(true, iso_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hevc power on ctrl iso fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); -#endif - if (!hevc_workaround_needed()) - break; - - if (decomp_addr) - hevc_fixed = test_hevc( - decomp_addr_aligned, 20); - - if (!hevc_fixed) { - hevc_loop++; - - mutex_unlock(&vdec_mutex); - - if (hevc_loop >= HEVC_TEST_LIMIT) { - pr_warn("hevc power sequence over limit\n"); - pr_warn("=====================================================\n"); - pr_warn(" This chip is identified to have HW failure.\n"); - pr_warn(" Please contact sqa-platform to replace the platform.\n"); - pr_warn("=====================================================\n"); - - panic("Force panic for chip detection !!!\n"); - - break; - } - - vdec_poweroff(VDEC_HEVC); - - mdelay(10); - - mutex_lock(&vdec_mutex); - } - } - - if (hevc_loop > hevc_max_reset_count) - hevc_max_reset_count = hevc_loop; - - WRITE_VREG(DOS_SW_RESET3, 0xffffffff); - udelay(10); - WRITE_VREG(DOS_SW_RESET3, 0); - } - } - - if (decomp_addr) - codec_mm_dma_free_coherent(MEM_NAME, - SZ_64K + SZ_4K, decomp_addr, decomp_dma_addr, 0); - - mutex_unlock(&vdec_mutex); -} -EXPORT_SYMBOL(vdec_poweron); - -void vdec_poweroff(enum vdec_type_e core) -{ - int sleep_val, iso_val; - bool is_power_ctrl_ver2 = false; - - if (core >= VDEC_MAX) - return; - - mutex_lock(&vdec_mutex); - - vdec_core->power_ref_count[core]--; - if (vdec_core->power_ref_count[core] > 0) { - mutex_unlock(&vdec_mutex); - return; - } - - is_power_ctrl_ver2 = - ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false; - - if (core == VDEC_1) { - sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc; - iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0; - - if (get_cpu_major_id() >= - AM_MESON_CPU_MAJOR_ID_GXBB) { - /* disable VDEC_1 DMC REQ*/ - unsigned long flags; - - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - udelay(10); - } - /* enable vdec1 isolation */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_iso_mask(false, iso_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("vdec-1 power off ctrl iso fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); -#endif - /* power off vdec1 memories */ - WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL); - /* disable vdec1 clock */ - vdec_clock_off(); - /* vdec1 power off */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_sleep_mask(false, sleep_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("vdec-1 power off ctrl sleep fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); -#endif - } else if (core == VDEC_2) { - if (has_vdec2()) { - /* enable vdec2 isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - 0x300); - /* power off vdec2 memories */ - WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL); - /* disable vdec2 clock */ - vdec2_clock_off(); - /* vdec2 power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | - 0x30); - } - } else if (core == VDEC_HCODEC) { - if (has_hdec()) { - sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3; - iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30; - - /* enable hcodec isolation */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_iso_mask(false, iso_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hcodec power off ctrl iso fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); -#endif - /* power off hcodec memories */ - WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); - /* disable hcodec clock */ - hcodec_clock_off(); - /* hcodec power off */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_sleep_mask(false, sleep_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hcodec power off ctrl sleep fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); -#endif - } - } else if (core == VDEC_HEVC) { - if (has_hevc_vdec()) { - sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0; - iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00; - - if (no_powerdown == 0) { - /* enable hevc isolation */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_iso_mask(false, iso_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hevc power off ctrl iso fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); -#endif - /* power off hevc memories */ - WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); - - /* disable hevc clock */ - hevc_clock_off(); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - hevc_back_clock_off(); - - /* hevc power off */ -#ifdef CONFIG_AMLOGIC_POWER - if (is_support_power_ctrl()) { - if (power_ctrl_sleep_mask(false, sleep_val, 0)) { - mutex_unlock(&vdec_mutex); - pr_err("hevc power off ctrl sleep fail.\n"); - return; - } - } else { - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); - } -#else - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); -#endif - } else { - pr_info("!!!!!!!!not power down\n"); - hevc_reset_core(NULL); - no_powerdown = 0; - } - } - } - mutex_unlock(&vdec_mutex); -} -EXPORT_SYMBOL(vdec_poweroff); - -bool vdec_on(enum vdec_type_e core) -{ - bool ret = false; - - if (core == VDEC_1) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) - ? 0x2 : 0xc)) == 0) && - (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100)) - ret = true; - } else if (core == VDEC_2) { - if (has_vdec2()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x30) == 0) && - (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100)) - ret = true; - } - } else if (core == VDEC_HCODEC) { - if (has_hdec()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) - ? 0x1 : 0x3)) == 0) && - (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000)) - ret = true; - } - } else if (core == VDEC_HEVC) { - if (has_hevc_vdec()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) - ? 0x4 : 0xc0)) == 0) && - (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000)) - ret = true; - } - } - - return ret; -} -EXPORT_SYMBOL(vdec_on); - -#elif 0 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ -void vdec_poweron(enum vdec_type_e core) -{ - ulong flags; - - spin_lock_irqsave(&lock, flags); - - if (core == VDEC_1) { - /* vdec1 soft reset */ - WRITE_VREG(DOS_SW_RESET0, 0xfffffffc); - WRITE_VREG(DOS_SW_RESET0, 0); - /* enable vdec1 clock */ - vdec_clock_enable(); - /* reset DOS top registers */ - WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0); - } else if (core == VDEC_2) { - /* vdec2 soft reset */ - WRITE_VREG(DOS_SW_RESET2, 0xffffffff); - WRITE_VREG(DOS_SW_RESET2, 0); - /* enable vdec2 clock */ - vdec2_clock_enable(); - /* reset DOS top registers */ - WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0); - } else if (core == VDEC_HCODEC) { - /* hcodec soft reset */ - WRITE_VREG(DOS_SW_RESET1, 0xffffffff); - WRITE_VREG(DOS_SW_RESET1, 0); - /* enable hcodec clock */ - hcodec_clock_enable(); - } - - spin_unlock_irqrestore(&lock, flags); -} - -void vdec_poweroff(enum vdec_type_e core) -{ - ulong flags; - - spin_lock_irqsave(&lock, flags); - - if (core == VDEC_1) { - /* disable vdec1 clock */ - vdec_clock_off(); - } else if (core == VDEC_2) { - /* disable vdec2 clock */ - vdec2_clock_off(); - } else if (core == VDEC_HCODEC) { - /* disable hcodec clock */ - hcodec_clock_off(); - } - - spin_unlock_irqrestore(&lock, flags); -} - -bool vdec_on(enum vdec_type_e core) -{ - bool ret = false; - - if (core == VDEC_1) { - if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100) - ret = true; - } else if (core == VDEC_2) { - if (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100) - ret = true; - } else if (core == VDEC_HCODEC) { - if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000) - ret = true; - } - - return ret; -} -#endif - -int vdec_source_changed(int format, int width, int height, int fps) -{ - /* todo: add level routines for clock adjustment per chips */ - int ret = -1; - static int on_setting; - - if (on_setting > 0) - return ret;/*on changing clk,ignore this change*/ - - if (vdec_source_get(VDEC_1) == width * height * fps) - return ret; - - - on_setting = 1; - ret = vdec_source_changed_for_clk_set(format, width, height, fps); - pr_debug("vdec1 video changed to %d x %d %d fps clk->%dMHZ\n", - width, height, fps, vdec_clk_get(VDEC_1)); - on_setting = 0; - return ret; - -} -EXPORT_SYMBOL(vdec_source_changed); - -void vdec_disable_DMC(struct vdec_s *vdec) -{ - /*close first,then wait pedding end,timing suggestion from vlsi*/ - unsigned long flags; - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & (1 << 13))) - ; -} -EXPORT_SYMBOL(vdec_disable_DMC); - -void vdec_enable_DMC(struct vdec_s *vdec) -{ - unsigned long flags; - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); - spin_unlock_irqrestore(&vdec_spin_lock, flags); -} - -EXPORT_SYMBOL(vdec_enable_DMC); - -void vdec_reset_core(struct vdec_s *vdec) -{ - unsigned long flags; - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & (1 << 13))) - ; - /* - * 2: assist - * 3: vld_reset - * 4: vld_part_reset - * 5: vfifo reset - * 6: iqidct - * 7: mc - * 8: dblk - * 9: pic_dc - * 10: psc - * 11: mcpu - * 12: ccpu - * 13: ddr - * 14: afifo - */ - - WRITE_VREG(DOS_SW_RESET0, - (1<<3)|(1<<4)|(1<<5)); - - WRITE_VREG(DOS_SW_RESET0, 0); - - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); - spin_unlock_irqrestore(&vdec_spin_lock, flags); -} -EXPORT_SYMBOL(vdec_reset_core); - -void hevc_enable_DMC(struct vdec_s *vdec) -{ - unsigned long flags; - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4)); - spin_unlock_irqrestore(&vdec_spin_lock, flags); -} - -EXPORT_SYMBOL(hevc_enable_DMC); - -void hevc_reset_core(struct vdec_s *vdec) -{ - unsigned long flags; - WRITE_VREG(HEVC_STREAM_CONTROL, 0); - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4))); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & (1 << 4))) - ; - - if (vdec == NULL || input_frame_based(vdec)) - WRITE_VREG(HEVC_STREAM_CONTROL, 0); - - /* - * 2: assist - * 3: parser - * 4: parser_state - * 8: dblk - * 11:mcpu - * 12:ccpu - * 13:ddr - * 14:iqit - * 15:ipp - * 17:qdct - * 18:mpred - * 19:sao - * 24:hevc_afifo - */ - WRITE_VREG(DOS_SW_RESET3, - (1<<3)|(1<<4)|(1<<8)|(1<<11)| - (1<<12)|(1<<13)|(1<<14)|(1<<15)| - (1<<17)|(1<<18)|(1<<19)|(1<<24)); - - WRITE_VREG(DOS_SW_RESET3, 0); - - - spin_lock_irqsave(&vdec_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4)); - spin_unlock_irqrestore(&vdec_spin_lock, flags); - -} -EXPORT_SYMBOL(hevc_reset_core); - -int vdec2_source_changed(int format, int width, int height, int fps) -{ - int ret = -1; - static int on_setting; - - if (has_vdec2()) { - /* todo: add level routines for clock adjustment per chips */ - if (on_setting != 0) - return ret;/*on changing clk,ignore this change*/ - - if (vdec_source_get(VDEC_2) == width * height * fps) - return ret; - - on_setting = 1; - ret = vdec_source_changed_for_clk_set(format, - width, height, fps); - pr_debug("vdec2 video changed to %d x %d %d fps clk->%dMHZ\n", - width, height, fps, vdec_clk_get(VDEC_2)); - on_setting = 0; - return ret; - } - return 0; -} -EXPORT_SYMBOL(vdec2_source_changed); - -int hevc_source_changed(int format, int width, int height, int fps) -{ - /* todo: add level routines for clock adjustment per chips */ - int ret = -1; - static int on_setting; - - if (on_setting != 0) - return ret;/*on changing clk,ignore this change*/ - - if (vdec_source_get(VDEC_HEVC) == width * height * fps) - return ret; - - on_setting = 1; - ret = vdec_source_changed_for_clk_set(format, width, height, fps); - pr_debug("hevc video changed to %d x %d %d fps clk->%dMHZ\n", - width, height, fps, vdec_clk_get(VDEC_HEVC)); - on_setting = 0; - - return ret; -} -EXPORT_SYMBOL(hevc_source_changed); - -static struct am_reg am_risc[] = { - {"MSP", 0x300}, - {"MPSR", 0x301}, - {"MCPU_INT_BASE", 0x302}, - {"MCPU_INTR_GRP", 0x303}, - {"MCPU_INTR_MSK", 0x304}, - {"MCPU_INTR_REQ", 0x305}, - {"MPC-P", 0x306}, - {"MPC-D", 0x307}, - {"MPC_E", 0x308}, - {"MPC_W", 0x309}, - {"CSP", 0x320}, - {"CPSR", 0x321}, - {"CCPU_INT_BASE", 0x322}, - {"CCPU_INTR_GRP", 0x323}, - {"CCPU_INTR_MSK", 0x324}, - {"CCPU_INTR_REQ", 0x325}, - {"CPC-P", 0x326}, - {"CPC-D", 0x327}, - {"CPC_E", 0x328}, - {"CPC_W", 0x329}, - {"AV_SCRATCH_0", 0x09c0}, - {"AV_SCRATCH_1", 0x09c1}, - {"AV_SCRATCH_2", 0x09c2}, - {"AV_SCRATCH_3", 0x09c3}, - {"AV_SCRATCH_4", 0x09c4}, - {"AV_SCRATCH_5", 0x09c5}, - {"AV_SCRATCH_6", 0x09c6}, - {"AV_SCRATCH_7", 0x09c7}, - {"AV_SCRATCH_8", 0x09c8}, - {"AV_SCRATCH_9", 0x09c9}, - {"AV_SCRATCH_A", 0x09ca}, - {"AV_SCRATCH_B", 0x09cb}, - {"AV_SCRATCH_C", 0x09cc}, - {"AV_SCRATCH_D", 0x09cd}, - {"AV_SCRATCH_E", 0x09ce}, - {"AV_SCRATCH_F", 0x09cf}, - {"AV_SCRATCH_G", 0x09d0}, - {"AV_SCRATCH_H", 0x09d1}, - {"AV_SCRATCH_I", 0x09d2}, - {"AV_SCRATCH_J", 0x09d3}, - {"AV_SCRATCH_K", 0x09d4}, - {"AV_SCRATCH_L", 0x09d5}, - {"AV_SCRATCH_M", 0x09d6}, - {"AV_SCRATCH_N", 0x09d7}, -}; - -static ssize_t amrisc_regs_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct am_reg *regs = am_risc; - int rsize = sizeof(am_risc) / sizeof(struct am_reg); - int i; - unsigned int val; - ssize_t ret; - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - mutex_lock(&vdec_mutex); - if (!vdec_on(VDEC_1)) { - mutex_unlock(&vdec_mutex); - pbuf += sprintf(pbuf, "amrisc is power off\n"); - ret = pbuf - buf; - return ret; - } - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /*TODO:M6 define */ - /* - * switch_mod_gate_by_type(MOD_VDEC, 1); - */ - amports_switch_gate("vdec", 1); - } - pbuf += sprintf(pbuf, "amrisc registers show:\n"); - for (i = 0; i < rsize; i++) { - val = READ_VREG(regs[i].offset); - pbuf += sprintf(pbuf, "%s(%#x)\t:%#x(%d)\n", - regs[i].name, regs[i].offset, val, val); - } - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) - mutex_unlock(&vdec_mutex); - else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /*TODO:M6 define */ - /* - * switch_mod_gate_by_type(MOD_VDEC, 0); - */ - amports_switch_gate("vdec", 0); - } - ret = pbuf - buf; - return ret; -} - -static ssize_t dump_trace_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int i; - char *pbuf = buf; - ssize_t ret; - u16 *trace_buf = kmalloc(debug_trace_num * 2, GFP_KERNEL); - - if (!trace_buf) { - pbuf += sprintf(pbuf, "No Memory bug\n"); - ret = pbuf - buf; - return ret; - } - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - mutex_lock(&vdec_mutex); - if (!vdec_on(VDEC_1)) { - mutex_unlock(&vdec_mutex); - kfree(trace_buf); - pbuf += sprintf(pbuf, "amrisc is power off\n"); - ret = pbuf - buf; - return ret; - } - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /*TODO:M6 define */ - /* - * switch_mod_gate_by_type(MOD_VDEC, 1); - */ - amports_switch_gate("vdec", 1); - } - pr_info("dump trace steps:%d start\n", debug_trace_num); - i = 0; - while (i <= debug_trace_num - 16) { - trace_buf[i] = READ_VREG(MPC_E); - trace_buf[i + 1] = READ_VREG(MPC_E); - trace_buf[i + 2] = READ_VREG(MPC_E); - trace_buf[i + 3] = READ_VREG(MPC_E); - trace_buf[i + 4] = READ_VREG(MPC_E); - trace_buf[i + 5] = READ_VREG(MPC_E); - trace_buf[i + 6] = READ_VREG(MPC_E); - trace_buf[i + 7] = READ_VREG(MPC_E); - trace_buf[i + 8] = READ_VREG(MPC_E); - trace_buf[i + 9] = READ_VREG(MPC_E); - trace_buf[i + 10] = READ_VREG(MPC_E); - trace_buf[i + 11] = READ_VREG(MPC_E); - trace_buf[i + 12] = READ_VREG(MPC_E); - trace_buf[i + 13] = READ_VREG(MPC_E); - trace_buf[i + 14] = READ_VREG(MPC_E); - trace_buf[i + 15] = READ_VREG(MPC_E); - i += 16; - }; - pr_info("dump trace steps:%d finished\n", debug_trace_num); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) - mutex_unlock(&vdec_mutex); - else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /*TODO:M6 define */ - /* - * switch_mod_gate_by_type(MOD_VDEC, 0); - */ - amports_switch_gate("vdec", 0); - } - for (i = 0; i < debug_trace_num; i++) { - if (i % 4 == 0) { - if (i % 16 == 0) - pbuf += sprintf(pbuf, "\n"); - else if (i % 8 == 0) - pbuf += sprintf(pbuf, " "); - else /* 4 */ - pbuf += sprintf(pbuf, " "); - } - pbuf += sprintf(pbuf, "%04x:", trace_buf[i]); - } - while (i < debug_trace_num) - ; - kfree(trace_buf); - pbuf += sprintf(pbuf, "\n"); - ret = pbuf - buf; - return ret; -} - -static ssize_t clock_level_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - size_t ret; - - pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_1)); - - if (has_vdec2()) - pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_2)); - - if (has_hevc_vdec()) - pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_HEVC)); - - ret = pbuf - buf; - return ret; -} - -static ssize_t store_poweron_clock_level(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int val; - ssize_t ret; - - /*ret = sscanf(buf, "%d", &val);*/ - ret = kstrtoint(buf, 0, &val); - - if (ret != 0) - return -EINVAL; - poweron_clock_level = val; - return size; -} - -static ssize_t show_poweron_clock_level(struct class *class, - struct class_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", poweron_clock_level); -} - -/* - *if keep_vdec_mem == 1 - *always don't release - *vdec 64 memory for fast play. - */ -static ssize_t store_keep_vdec_mem(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int val; - ssize_t ret; - - /*ret = sscanf(buf, "%d", &val);*/ - ret = kstrtoint(buf, 0, &val); - if (ret != 0) - return -EINVAL; - keep_vdec_mem = val; - return size; -} - -static ssize_t show_keep_vdec_mem(struct class *class, - struct class_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", keep_vdec_mem); -} - -#ifdef VDEC_DEBUG_SUPPORT -static ssize_t store_debug(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - struct vdec_s *vdec; - struct vdec_core_s *core = vdec_core; - unsigned long flags; - - unsigned id; - unsigned val; - ssize_t ret; - char cbuf[32]; - - cbuf[0] = 0; - ret = sscanf(buf, "%s %x %x", cbuf, &id, &val); - /*pr_info( - "%s(%s)=>ret %ld: %s, %x, %x\n", - __func__, buf, ret, cbuf, id, val);*/ - if (strcmp(cbuf, "schedule") == 0) { - pr_info("VDEC_DEBUG: force schedule\n"); - up(&core->sem); - } else if (strcmp(cbuf, "power_off") == 0) { - pr_info("VDEC_DEBUG: power off core %d\n", id); - vdec_poweroff(id); - } else if (strcmp(cbuf, "power_on") == 0) { - pr_info("VDEC_DEBUG: power_on core %d\n", id); - vdec_poweron(id); - } else if (strcmp(cbuf, "wr") == 0) { - pr_info("VDEC_DEBUG: WRITE_VREG(0x%x, 0x%x)\n", - id, val); - WRITE_VREG(id, val); - } else if (strcmp(cbuf, "rd") == 0) { - pr_info("VDEC_DEBUG: READ_VREG(0x%x) = 0x%x\n", - id, READ_VREG(id)); - } else if (strcmp(cbuf, "read_hevc_clk_reg") == 0) { - pr_info( - "VDEC_DEBUG: HHI_VDEC4_CLK_CNTL = 0x%x, HHI_VDEC2_CLK_CNTL = 0x%x\n", - READ_HHI_REG(HHI_VDEC4_CLK_CNTL), - READ_HHI_REG(HHI_VDEC2_CLK_CNTL)); - } - - flags = vdec_core_lock(vdec_core); - - list_for_each_entry(vdec, - &core->connected_vdec_list, list) { - pr_info("vdec: status %d, id %d\n", vdec->status, vdec->id); - if (((vdec->status == VDEC_STATUS_CONNECTED - || vdec->status == VDEC_STATUS_ACTIVE)) && - (vdec->id == id)) { - /*to add*/ - break; - } - } - vdec_core_unlock(vdec_core, flags); - return size; -} - -static ssize_t show_debug(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct vdec_s *vdec; - struct vdec_core_s *core = vdec_core; - unsigned long flags = vdec_core_lock(vdec_core); - u64 tmp; - - pbuf += sprintf(pbuf, - "============== help:\n"); - pbuf += sprintf(pbuf, - "'echo xxx > debug' usuage:\n"); - pbuf += sprintf(pbuf, - "schedule - trigger schedule thread to run\n"); - pbuf += sprintf(pbuf, - "power_off core_num - call vdec_poweroff(core_num)\n"); - pbuf += sprintf(pbuf, - "power_on core_num - call vdec_poweron(core_num)\n"); - pbuf += sprintf(pbuf, - "wr adr val - call WRITE_VREG(adr, val)\n"); - pbuf += sprintf(pbuf, - "rd adr - call READ_VREG(adr)\n"); - pbuf += sprintf(pbuf, - "read_hevc_clk_reg - read HHI register for hevc clk\n"); - pbuf += sprintf(pbuf, - "===================\n"); - - pbuf += sprintf(pbuf, - "name(core)\tschedule_count\trun_count\tinput_underrun\tdecbuf_not_ready\trun_time\n"); - list_for_each_entry(vdec, - &core->connected_vdec_list, list) { - enum vdec_type_e type; - if ((vdec->status == VDEC_STATUS_CONNECTED - || vdec->status == VDEC_STATUS_ACTIVE)) { - for (type = VDEC_1; type < VDEC_MAX; type++) { - if (vdec->core_mask & (1 << type)) { - pbuf += sprintf(pbuf, "%s(%d):", - vdec->vf_provider_name, type); - pbuf += sprintf(pbuf, "\t%d", - vdec->check_count[type]); - pbuf += sprintf(pbuf, "\t%d", - vdec->run_count[type]); - pbuf += sprintf(pbuf, "\t%d", - vdec->input_underrun_count[type]); - pbuf += sprintf(pbuf, "\t%d", - vdec->not_run_ready_count[type]); - tmp = vdec->run_clk[type] * 100; - do_div(tmp, vdec->total_clk[type]); - pbuf += sprintf(pbuf, - "\t%d%%\n", - vdec->total_clk[type] == 0 ? 0 : - (u32)tmp); - } - } - } - } - - vdec_core_unlock(vdec_core, flags); - return pbuf - buf; - -} -#endif - -/*irq num as same as .dts*/ -/* - * interrupts = <0 3 1 - * 0 23 1 - * 0 32 1 - * 0 43 1 - * 0 44 1 - * 0 45 1>; - * interrupt-names = "vsync", - * "demux", - * "parser", - * "mailbox_0", - * "mailbox_1", - * "mailbox_2"; - */ -s32 vdec_request_threaded_irq(enum vdec_irq_num num, - irq_handler_t handler, - irq_handler_t thread_fn, - unsigned long irqflags, - const char *devname, void *dev) -{ - s32 res_irq; - s32 ret = 0; - - if (num >= VDEC_IRQ_MAX) { - pr_err("[%s] request irq error, irq num too big!", __func__); - return -EINVAL; - } - - if (vdec_core->isr_context[num].irq < 0) { - res_irq = platform_get_irq( - vdec_core->vdec_core_platform_device, num); - if (res_irq < 0) { - pr_err("[%s] get irq error!", __func__); - return -EINVAL; - } - - vdec_core->isr_context[num].irq = res_irq; - vdec_core->isr_context[num].dev_isr = handler; - vdec_core->isr_context[num].dev_threaded_isr = thread_fn; - vdec_core->isr_context[num].dev_id = dev; - - ret = request_threaded_irq(res_irq, - vdec_isr, - vdec_thread_isr, - (thread_fn) ? IRQF_ONESHOT : irqflags, - devname, - &vdec_core->isr_context[num]); - - if (ret) { - vdec_core->isr_context[num].irq = -1; - vdec_core->isr_context[num].dev_isr = NULL; - vdec_core->isr_context[num].dev_threaded_isr = NULL; - vdec_core->isr_context[num].dev_id = NULL; - - pr_err("vdec irq register error for %s.\n", devname); - return -EIO; - } - } else { - vdec_core->isr_context[num].dev_isr = handler; - vdec_core->isr_context[num].dev_threaded_isr = thread_fn; - vdec_core->isr_context[num].dev_id = dev; - } - - return ret; -} -EXPORT_SYMBOL(vdec_request_threaded_irq); - -s32 vdec_request_irq(enum vdec_irq_num num, irq_handler_t handler, - const char *devname, void *dev) -{ - pr_debug("vdec_request_irq %p, %s\n", handler, devname); - - return vdec_request_threaded_irq(num, - handler, - NULL,/*no thread_fn*/ - IRQF_SHARED, - devname, - dev); -} -EXPORT_SYMBOL(vdec_request_irq); - -void vdec_free_irq(enum vdec_irq_num num, void *dev) -{ - if (num >= VDEC_IRQ_MAX) { - pr_err("[%s] request irq error, irq num too big!", __func__); - return; - } - /* - *assume amrisc is stopped already and there is no mailbox interrupt - * when we reset pointers here. - */ - vdec_core->isr_context[num].dev_isr = NULL; - vdec_core->isr_context[num].dev_threaded_isr = NULL; - vdec_core->isr_context[num].dev_id = NULL; - synchronize_irq(vdec_core->isr_context[num].irq); -} -EXPORT_SYMBOL(vdec_free_irq); - -struct vdec_s *vdec_get_default_vdec_for_userdata(void) -{ - struct vdec_s *vdec; - struct vdec_s *ret_vdec; - struct vdec_core_s *core = vdec_core; - unsigned long flags; - int id; - - flags = vdec_core_lock(vdec_core); - - id = 0x10000000; - ret_vdec = NULL; - if (!list_empty(&core->connected_vdec_list)) { - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - if (vdec->id < id) { - id = vdec->id; - ret_vdec = vdec; - } - } - } - - vdec_core_unlock(vdec_core, flags); - - return ret_vdec; -} -EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata); - -struct vdec_s *vdec_get_vdec_by_id(int vdec_id) -{ - struct vdec_s *vdec; - struct vdec_s *ret_vdec; - struct vdec_core_s *core = vdec_core; - unsigned long flags; - - flags = vdec_core_lock(vdec_core); - - ret_vdec = NULL; - if (!list_empty(&core->connected_vdec_list)) { - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - if (vdec->id == vdec_id) { - ret_vdec = vdec; - break; - } - } - } - - vdec_core_unlock(vdec_core, flags); - - return ret_vdec; -} -EXPORT_SYMBOL(vdec_get_vdec_by_id); - -int vdec_read_user_data(struct vdec_s *vdec, - struct userdata_param_t *p_userdata_param) -{ - int ret = 0; - - if (!vdec) - vdec = vdec_get_default_vdec_for_userdata(); - - if (vdec) { - if (vdec->user_data_read) - ret = vdec->user_data_read(vdec, p_userdata_param); - } - return ret; -} -EXPORT_SYMBOL(vdec_read_user_data); - -int vdec_wakeup_userdata_poll(struct vdec_s *vdec) -{ - if (vdec) { - if (vdec->wakeup_userdata_poll) - vdec->wakeup_userdata_poll(vdec); - } - - return 0; -} -EXPORT_SYMBOL(vdec_wakeup_userdata_poll); - -void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit) -{ - if (!vdec) - vdec = vdec_get_default_vdec_for_userdata(); - - if (vdec) { - if (vdec->reset_userdata_fifo) - vdec->reset_userdata_fifo(vdec, bInit); - } -} -EXPORT_SYMBOL(vdec_reset_userdata_fifo); - -static int dump_mode; -static ssize_t dump_risc_mem_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size)/*set*/ -{ - unsigned int val; - ssize_t ret; - char dump_mode_str[4] = "PRL"; - - /*ret = sscanf(buf, "%d", &val);*/ - ret = kstrtoint(buf, 0, &val); - - if (ret != 0) - return -EINVAL; - dump_mode = val & 0x3; - pr_info("set dump mode to %d,%c_mem\n", - dump_mode, dump_mode_str[dump_mode]); - return size; -} -static u32 read_amrisc_reg(int reg) -{ - WRITE_VREG(0x31b, reg); - return READ_VREG(0x31c); -} - -static void dump_pmem(void) -{ - int i; - - WRITE_VREG(0x301, 0x8000); - WRITE_VREG(0x31d, 0); - pr_info("start dump amrisc pmem of risc\n"); - for (i = 0; i < 0xfff; i++) { - /*same as .o format*/ - pr_info("%08x // 0x%04x:\n", read_amrisc_reg(i), i); - } -} - -static void dump_lmem(void) -{ - int i; - - WRITE_VREG(0x301, 0x8000); - WRITE_VREG(0x31d, 2); - pr_info("start dump amrisc lmem\n"); - for (i = 0; i < 0x3ff; i++) { - /*same as */ - pr_info("[%04x] = 0x%08x:\n", i, read_amrisc_reg(i)); - } -} - -static ssize_t dump_risc_mem_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - int ret; - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - mutex_lock(&vdec_mutex); - if (!vdec_on(VDEC_1)) { - mutex_unlock(&vdec_mutex); - pbuf += sprintf(pbuf, "amrisc is power off\n"); - ret = pbuf - buf; - return ret; - } - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /*TODO:M6 define */ - /* - * switch_mod_gate_by_type(MOD_VDEC, 1); - */ - amports_switch_gate("vdec", 1); - } - /*start do**/ - switch (dump_mode) { - case 0: - dump_pmem(); - break; - case 2: - dump_lmem(); - break; - default: - break; - } - - /*done*/ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) - mutex_unlock(&vdec_mutex); - else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /*TODO:M6 define */ - /* - * switch_mod_gate_by_type(MOD_VDEC, 0); - */ - amports_switch_gate("vdec", 0); - } - return sprintf(buf, "done\n"); -} - -static ssize_t core_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - struct vdec_core_s *core = vdec_core; - char *pbuf = buf; - - if (list_empty(&core->connected_vdec_list)) - pbuf += sprintf(pbuf, "connected vdec list empty\n"); - else { - struct vdec_s *vdec; - - pbuf += sprintf(pbuf, - " Core: last_sched %p, sched_mask %lx\n", - core->last_vdec, - core->sched_mask); - - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - pbuf += sprintf(pbuf, - "\tvdec.%d (%p (%s)), status = %s,\ttype = %s, \tactive_mask = %lx\n", - vdec->id, - vdec, - vdec_device_name[vdec->format * 2], - vdec_status_str(vdec), - vdec_type_str(vdec), - vdec->active_mask); - } - } - - return pbuf - buf; -} - -static ssize_t vdec_status_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct vdec_s *vdec; - struct vdec_info vs; - unsigned char vdec_num = 0; - struct vdec_core_s *core = vdec_core; - unsigned long flags = vdec_core_lock(vdec_core); - - if (list_empty(&core->connected_vdec_list)) { - pbuf += sprintf(pbuf, "No vdec.\n"); - goto out; - } - - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - if ((vdec->status == VDEC_STATUS_CONNECTED - || vdec->status == VDEC_STATUS_ACTIVE)) { - memset(&vs, 0, sizeof(vs)); - if (vdec_status(vdec, &vs)) { - pbuf += sprintf(pbuf, "err.\n"); - goto out; - } - pbuf += sprintf(pbuf, - "vdec channel %u statistics:\n", - vdec_num); - pbuf += sprintf(pbuf, - "%13s : %s\n", "device name", - vs.vdec_name); - pbuf += sprintf(pbuf, - "%13s : %u\n", "frame width", - vs.frame_width); - pbuf += sprintf(pbuf, - "%13s : %u\n", "frame height", - vs.frame_height); - pbuf += sprintf(pbuf, - "%13s : %u %s\n", "frame rate", - vs.frame_rate, "fps"); - pbuf += sprintf(pbuf, - "%13s : %u %s\n", "bit rate", - vs.bit_rate / 1024 * 8, "kbps"); - pbuf += sprintf(pbuf, - "%13s : %u\n", "status", - vs.status); - pbuf += sprintf(pbuf, - "%13s : %u\n", "frame dur", - vs.frame_dur); - pbuf += sprintf(pbuf, - "%13s : %u %s\n", "frame data", - vs.frame_data / 1024, "KB"); - pbuf += sprintf(pbuf, - "%13s : %u\n", "frame count", - vs.frame_count); - pbuf += sprintf(pbuf, - "%13s : %u\n", "drop count", - vs.drop_frame_count); - pbuf += sprintf(pbuf, - "%13s : %u\n", "fra err count", - vs.error_frame_count); - pbuf += sprintf(pbuf, - "%13s : %u\n", "hw err count", - vs.error_count); - pbuf += sprintf(pbuf, - "%13s : %llu %s\n\n", "total data", - vs.total_data / 1024, "KB"); - pbuf += sprintf(pbuf, - "%13s : %x\n", "ratio_control", - vs.ratio_control); - - vdec_num++; - } - } -out: - vdec_core_unlock(vdec_core, flags); - return pbuf - buf; -} - -static ssize_t dump_vdec_blocks_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct vdec_core_s *core = vdec_core; - char *pbuf = buf; - - if (list_empty(&core->connected_vdec_list)) - pbuf += sprintf(pbuf, "connected vdec list empty\n"); - else { - struct vdec_s *vdec; - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - pbuf += vdec_input_dump_blocks(&vdec->input, - pbuf, PAGE_SIZE - (pbuf - buf)); - } - } - - return pbuf - buf; -} -static ssize_t dump_vdec_chunks_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct vdec_core_s *core = vdec_core; - char *pbuf = buf; - - if (list_empty(&core->connected_vdec_list)) - pbuf += sprintf(pbuf, "connected vdec list empty\n"); - else { - struct vdec_s *vdec; - list_for_each_entry(vdec, &core->connected_vdec_list, list) { - pbuf += vdec_input_dump_chunks(&vdec->input, - pbuf, PAGE_SIZE - (pbuf - buf)); - } - } - - return pbuf - buf; -} - -static ssize_t dump_decoder_state_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct vdec_s *vdec; - struct vdec_core_s *core = vdec_core; - unsigned long flags = vdec_core_lock(vdec_core); - - if (list_empty(&core->connected_vdec_list)) { - pbuf += sprintf(pbuf, "No vdec.\n"); - } else { - list_for_each_entry(vdec, - &core->connected_vdec_list, list) { - if ((vdec->status == VDEC_STATUS_CONNECTED - || vdec->status == VDEC_STATUS_ACTIVE) - && vdec->dump_state) - vdec->dump_state(vdec); - } - } - vdec_core_unlock(vdec_core, flags); - - return pbuf - buf; -} - -static ssize_t dump_fps_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct vdec_core_s *core = vdec_core; - int i; - - unsigned long flags = vdec_fps_lock(vdec_core); - for (i = 0; i < MAX_INSTANCE_MUN; i++) - pbuf += sprintf(pbuf, "%d ", core->decode_fps[i].fps); - - pbuf += sprintf(pbuf, "\n"); - vdec_fps_unlock(vdec_core, flags); - - return pbuf - buf; -} - - - -static struct class_attribute vdec_class_attrs[] = { - __ATTR_RO(amrisc_regs), - __ATTR_RO(dump_trace), - __ATTR_RO(clock_level), - __ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP, - show_poweron_clock_level, store_poweron_clock_level), - __ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP, - dump_risc_mem_show, dump_risc_mem_store), - __ATTR(keep_vdec_mem, S_IRUGO | S_IWUSR | S_IWGRP, - show_keep_vdec_mem, store_keep_vdec_mem), - __ATTR_RO(core), - __ATTR_RO(vdec_status), - __ATTR_RO(dump_vdec_blocks), - __ATTR_RO(dump_vdec_chunks), - __ATTR_RO(dump_decoder_state), -#ifdef VDEC_DEBUG_SUPPORT - __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP, - show_debug, store_debug), -#endif -#ifdef FRAME_CHECK - __ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP, - dump_yuv_show, dump_yuv_store), - __ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP, - frame_check_show, frame_check_store), -#endif - __ATTR_RO(dump_fps), - __ATTR_NULL -}; - -static struct class vdec_class = { - .name = "vdec", - .class_attrs = vdec_class_attrs, - }; - -struct device *get_vdec_device(void) -{ - return &vdec_core->vdec_core_platform_device->dev; -} -EXPORT_SYMBOL(get_vdec_device); - -static int vdec_probe(struct platform_device *pdev) -{ - s32 i, r; - - vdec_core = (struct vdec_core_s *)devm_kzalloc(&pdev->dev, - sizeof(struct vdec_core_s), GFP_KERNEL); - if (vdec_core == NULL) { - pr_err("vdec core allocation failed.\n"); - return -ENOMEM; - } - - atomic_set(&vdec_core->vdec_nr, 0); - sema_init(&vdec_core->sem, 1); - - r = class_register(&vdec_class); - if (r) { - pr_info("vdec class create fail.\n"); - return r; - } - - vdec_core->vdec_core_platform_device = pdev; - - platform_set_drvdata(pdev, vdec_core); - - for (i = 0; i < VDEC_IRQ_MAX; i++) { - vdec_core->isr_context[i].index = i; - vdec_core->isr_context[i].irq = -1; - } - - r = vdec_request_threaded_irq(VDEC_IRQ_0, NULL, NULL, - IRQF_ONESHOT, "vdec-0", NULL); - if (r < 0) { - pr_err("vdec interrupt request failed\n"); - return r; - } - - r = vdec_request_threaded_irq(VDEC_IRQ_1, NULL, NULL, - IRQF_ONESHOT, "vdec-1", NULL); - if (r < 0) { - pr_err("vdec interrupt request failed\n"); - return r; - } -#if 0 - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { - r = vdec_request_threaded_irq(VDEC_IRQ_HEVC_BACK, NULL, NULL, - IRQF_ONESHOT, "vdec-hevc_back", NULL); - if (r < 0) { - pr_err("vdec interrupt request failed\n"); - return r; - } - } -#endif - r = of_reserved_mem_device_init(&pdev->dev); - if (r == 0) - pr_info("vdec_probe done\n"); - - vdec_core->cma_dev = &pdev->dev; - - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_M8) { - /* default to 250MHz */ - vdec_clock_hi_enable(); - } - - if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) { - /* set vdec dmc request to urgent */ - WRITE_DMCREG(DMC_AM5_CHAN_CTRL, 0x3f203cf); - } - INIT_LIST_HEAD(&vdec_core->connected_vdec_list); - spin_lock_init(&vdec_core->lock); - spin_lock_init(&vdec_core->canvas_lock); - spin_lock_init(&vdec_core->fps_lock); - ida_init(&vdec_core->ida); - vdec_core->thread = kthread_run(vdec_core_thread, vdec_core, - "vdec-core"); - - vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",__WQ_LEGACY | - WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work"); - /*work queue priority lower than vdec-core.*/ - return 0; -} - -static int vdec_remove(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < VDEC_IRQ_MAX; i++) { - if (vdec_core->isr_context[i].irq >= 0) { - free_irq(vdec_core->isr_context[i].irq, - &vdec_core->isr_context[i]); - vdec_core->isr_context[i].irq = -1; - vdec_core->isr_context[i].dev_isr = NULL; - vdec_core->isr_context[i].dev_threaded_isr = NULL; - vdec_core->isr_context[i].dev_id = NULL; - } - } - - kthread_stop(vdec_core->thread); - - destroy_workqueue(vdec_core->vdec_core_wq); - class_unregister(&vdec_class); - - return 0; -} - -static const struct of_device_id amlogic_vdec_dt_match[] = { - { - .compatible = "amlogic, vdec", - }, - {}, -}; - -static struct mconfig vdec_configs[] = { - MC_PU32("debug_trace_num", &debug_trace_num), - MC_PI32("hevc_max_reset_count", &hevc_max_reset_count), - MC_PU32("clk_config", &clk_config), - MC_PI32("step_mode", &step_mode), - MC_PI32("poweron_clock_level", &poweron_clock_level), -}; -static struct mconfig_node vdec_node; - -static struct platform_driver vdec_driver = { - .probe = vdec_probe, - .remove = vdec_remove, - .driver = { - .name = "vdec", - .of_match_table = amlogic_vdec_dt_match, - } -}; - -static struct codec_profile_t amvdec_input_profile = { - .name = "vdec_input", - .profile = "drm_framemode" -}; - -int vdec_module_init(void) -{ - if (platform_driver_register(&vdec_driver)) { - pr_info("failed to register vdec module\n"); - return -ENODEV; - } - INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node, - "vdec", vdec_configs, CONFIG_FOR_RW); - vcodec_profile_register(&amvdec_input_profile); - return 0; -} -EXPORT_SYMBOL(vdec_module_init); - -void vdec_module_exit(void) -{ - platform_driver_unregister(&vdec_driver); -} -EXPORT_SYMBOL(vdec_module_exit); - -#if 0 -static int __init vdec_module_init(void) -{ - if (platform_driver_register(&vdec_driver)) { - pr_info("failed to register vdec module\n"); - return -ENODEV; - } - INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node, - "vdec", vdec_configs, CONFIG_FOR_RW); - return 0; -} - -static void __exit vdec_module_exit(void) -{ - platform_driver_unregister(&vdec_driver); -} -#endif - -static int vdec_mem_device_init(struct reserved_mem *rmem, struct device *dev) -{ - vdec_core->cma_dev = dev; - - return 0; -} - -static const struct reserved_mem_ops rmem_vdec_ops = { - .device_init = vdec_mem_device_init, -}; - -static int __init vdec_mem_setup(struct reserved_mem *rmem) -{ - rmem->ops = &rmem_vdec_ops; - pr_info("vdec: reserved mem setup\n"); - - return 0; -} - -void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug) -{ - if (frame_info_buf_in == NULL) { - pr_info("error,frame_info_buf_in is null\n"); - return; - } - if (frame_info_buf_out == NULL) { - pr_info("error,frame_info_buf_out is null\n"); - return; - } - if (frame_qos_wr >= QOS_FRAME_NUM) - frame_qos_wr = 0; - - if (frame_qos_wr >= QOS_FRAME_NUM || - frame_qos_wr < 0) { - pr_info("error,index :%d is error\n", frame_qos_wr); - return; - } - if (frameinfo_flag == DISABLE_FRAME_INFO) - return; - - if (frameinfo_flag == PRINT_FRAME_INFO) { - pr_info("num %d size %d pts %d\n", - vframe_qos->num, - vframe_qos->size, - vframe_qos->pts); - pr_info("mv min_mv %d avg_mv %d max_mv %d\n", - vframe_qos->min_mv, - vframe_qos->avg_mv, - vframe_qos->max_mv); - pr_info("qp min_qp %d avg_qp %d max_qp %d\n", - vframe_qos->min_qp, - vframe_qos->avg_qp, - vframe_qos->max_qp); - pr_info("skip min_skip %d avg_skip %d max_skip %d\n", - vframe_qos->min_skip, - vframe_qos->avg_skip, - vframe_qos->max_skip); - } - memcpy(&frame_info_buf_in[frame_qos_wr++], - vframe_qos, sizeof(struct vframe_qos_s)); - if (frame_qos_wr >= QOS_FRAME_NUM) - frame_qos_wr = 0; - - /*pr_info("frame_qos_wr:%d\n", frame_qos_wr);*/ - -} -EXPORT_SYMBOL(vdec_fill_frame_info); - -struct vframe_qos_s *vdec_get_qos_info(void) -{ - int write_count = 0; - int qos_wr = frame_qos_wr; - - if (frame_info_buf_in == NULL) { - pr_info("error,frame_info_buf_in is null\n"); - return NULL; - } - if (frame_info_buf_out == NULL) { - pr_info("error,frame_info_buf_out is null\n"); - return NULL; - } - - - memset(frame_info_buf_out, 0, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); - if (frame_qos_rd > qos_wr) { - write_count = QOS_FRAME_NUM - frame_qos_rd; - if (write_count > 0 && write_count <= QOS_FRAME_NUM) { - memcpy(frame_info_buf_out, &frame_info_buf_in[0], - write_count*sizeof(struct vframe_qos_s)); - if ((write_count + qos_wr) <= QOS_FRAME_NUM) - memcpy(&frame_info_buf_out[write_count], frame_info_buf_in, - qos_wr*sizeof(struct vframe_qos_s)); - else - pr_info("get_qos_info:%d,out of range\n", __LINE__); - } else - pr_info("get_qos_info:%d,out of range\n", __LINE__); - } else if (frame_qos_rd < qos_wr) { - write_count = qos_wr - frame_qos_rd; - if (write_count > 0 && write_count < QOS_FRAME_NUM) - memcpy(frame_info_buf_out, &frame_info_buf_in[frame_qos_rd], - (write_count)*sizeof(struct vframe_qos_s)); - else - pr_info("get_qos_info:%d, out of range\n", __LINE__); - } - /* - pr_info("cnt:%d,size:%d,num:%d,rd:%d,wr:%d\n", - wirte_count, - frame_info_buf_out[0].size, - frame_info_buf_out[0].num, - frame_qos_rd,qos_wr); - */ - frame_qos_rd = qos_wr; - return frame_info_buf_out; -} -EXPORT_SYMBOL(vdec_get_qos_info); - - -RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup); -/* -uint force_hevc_clock_cntl; -EXPORT_SYMBOL(force_hevc_clock_cntl); - -module_param(force_hevc_clock_cntl, uint, 0664); -*/ -module_param(debug, uint, 0664); -module_param(debug_trace_num, uint, 0664); -module_param(hevc_max_reset_count, int, 0664); -module_param(clk_config, uint, 0664); -module_param(step_mode, int, 0664); -module_param(debugflags, int, 0664); -module_param(parallel_decode, int, 0664); -module_param(fps_detection, int, 0664); -module_param(fps_clear, int, 0664); -module_param(force_nosecure_even_drm, int, 0664); - -module_param(frameinfo_flag, int, 0664); -MODULE_PARM_DESC(frameinfo_flag, - "\n frameinfo_flag\n"); -/* -*module_init(vdec_module_init); -*module_exit(vdec_module_exit); -*/ -#define CREATE_TRACE_POINTS -#include "vdec_trace.h" -MODULE_DESCRIPTION("AMLOGIC vdec driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h deleted file mode 100644 index b7287fb95238..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/vdec.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VDEC_H -#define VDEC_H -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/*#define CONFIG_AM_VDEC_DV*/ - -#include "vdec_input.h" -#include "frame_check.h" - -s32 vdec_dev_register(void); -s32 vdec_dev_unregister(void); - -int vdec_source_changed(int format, int width, int height, int fps); -int vdec2_source_changed(int format, int width, int height, int fps); -int hevc_source_changed(int format, int width, int height, int fps); -struct device *get_vdec_device(void); -int vdec_module_init(void); -void vdec_module_exit(void); - -#define MAX_INSTANCE_MUN 9 - -#define VDEC_DEBUG_SUPPORT - -#define DEC_FLAG_HEVC_WORKAROUND 0x01 - -#define VDEC_FIFO_ALIGN 8 - -enum vdec_type_e { - VDEC_1 = 0, - VDEC_HCODEC, - VDEC_2, - VDEC_HEVC, - VDEC_HEVCB, - VDEC_MAX -}; - -#define CORE_MASK_VDEC_1 (1 << VDEC_1) -#define CORE_MASK_HCODEC (1 << VDEC_HCODEC) -#define CORE_MASK_VDEC_2 (1 << VDEC_2) -#define CORE_MASK_HEVC (1 << VDEC_HEVC) -#define CORE_MASK_HEVC_FRONT (1 << VDEC_HEVC) -#define CORE_MASK_HEVC_BACK (1 << VDEC_HEVCB) -#define CORE_MASK_COMBINE (1UL << 31) - -extern void vdec2_power_mode(int level); -extern void vdec_poweron(enum vdec_type_e core); -extern void vdec_poweroff(enum vdec_type_e core); -extern bool vdec_on(enum vdec_type_e core); -extern void vdec_power_reset(void); - -/*irq num as same as .dts*/ - -/* - * interrupts = <0 3 1 - * 0 23 1 - * 0 32 1 - * 0 43 1 - * 0 44 1 - * 0 45 1>; - * interrupt-names = "vsync", - * "demux", - * "parser", - * "mailbox_0", - * "mailbox_1", - * "mailbox_2"; - */ -enum vdec_irq_num { - VSYNC_IRQ = 0, - DEMUX_IRQ, - PARSER_IRQ, - VDEC_IRQ_0, - VDEC_IRQ_1, - VDEC_IRQ_2, - VDEC_IRQ_HEVC_BACK, - VDEC_IRQ_MAX, -}; - -enum vdec_fr_hint_state { - VDEC_NO_NEED_HINT = 0, - VDEC_NEED_HINT, - VDEC_HINTED, -}; -extern s32 vdec_request_threaded_irq(enum vdec_irq_num num, - irq_handler_t handler, - irq_handler_t thread_fn, - unsigned long irqflags, - const char *devname, void *dev); -extern s32 vdec_request_irq(enum vdec_irq_num num, irq_handler_t handler, - const char *devname, void *dev); -extern void vdec_free_irq(enum vdec_irq_num num, void *dev); - -extern void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size); -unsigned int get_vdec_clk_config_settings(void); -void update_vdec_clk_config_settings(unsigned int config); -//unsigned int get_mmu_mode(void);//DEBUG_TMP -extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug); - -struct vdec_s; -enum vformat_t; - -/* stream based with single instance decoder driver */ -#define VDEC_TYPE_SINGLE 0 - -/* stream based with multi-instance decoder with HW resouce sharing */ -#define VDEC_TYPE_STREAM_PARSER 1 - -/* frame based with multi-instance decoder, input block list based */ -#define VDEC_TYPE_FRAME_BLOCK 2 - -/* frame based with multi-instance decoder, single circular input block */ -#define VDEC_TYPE_FRAME_CIRCULAR 3 - -/* decoder status: uninitialized */ -#define VDEC_STATUS_UNINITIALIZED 0 - -/* decoder status: before the decoder can start consuming data */ -#define VDEC_STATUS_DISCONNECTED 1 - -/* decoder status: decoder should become disconnected once it's not active */ -#define VDEC_STATUS_CONNECTED 2 - -/* decoder status: decoder owns HW resource and is running */ -#define VDEC_STATUS_ACTIVE 3 - -#define VDEC_PROVIDER_NAME_SIZE 16 -#define VDEC_RECEIVER_NAME_SIZE 16 -#define VDEC_MAP_NAME_SIZE 90 - -#define VDEC_FLAG_OTHER_INPUT_CONTEXT 0x0 -#define VDEC_FLAG_SELF_INPUT_CONTEXT 0x01 - -#define VDEC_NEED_MORE_DATA_RUN 0x01 -#define VDEC_NEED_MORE_DATA_DIRTY 0x02 -#define VDEC_NEED_MORE_DATA 0x04 - -struct vdec_s { - u32 magic; - struct list_head list; - unsigned long core_mask; - unsigned long active_mask; - unsigned long sched_mask; - int id; - - struct vdec_s *master; - struct vdec_s *slave; - struct stream_port_s *port; - int status; - int next_status; - int type; - int port_flag; - int format; - u32 pts; - u64 pts64; - bool pts_valid; - u64 timestamp; - bool timestamp_valid; - int flag; - int sched; - int need_more_data; - u32 canvas_mode; - - struct completion inactive_done; - - /* config (temp) */ - unsigned long mem_start; - unsigned long mem_end; - - void *mm_blk_handle; - - struct device *cma_dev; - struct platform_device *dev; - struct dec_sysinfo sys_info_store; - struct dec_sysinfo *sys_info; - - /* input */ - struct vdec_input_s input; - - /*frame check*/ - struct pic_check_mgr_t vfc; - - /* mc cache */ - u32 mc[4096 * 4]; - bool mc_loaded; - u32 mc_type; - /* frame provider/receiver interface */ - char vf_provider_name[VDEC_PROVIDER_NAME_SIZE]; - struct vframe_provider_s vframe_provider; - char *vf_receiver_name; - char vfm_map_id[VDEC_MAP_NAME_SIZE]; - char vfm_map_chain[VDEC_MAP_NAME_SIZE]; - int vf_receiver_inst; - enum FRAME_BASE_VIDEO_PATH frame_base_video_path; - enum vdec_fr_hint_state fr_hint_state; - bool use_vfm_path; - char config[PAGE_SIZE]; - int config_len; - bool is_reset; - bool dolby_meta_with_el; - - /* canvas */ - int (*get_canvas)(unsigned int index, unsigned int base); - int (*get_canvas_ex)(int type, int id); - void (*free_canvas_ex)(int index, int id); - - int (*dec_status)(struct vdec_s *vdec, struct vdec_info *vstatus); - int (*set_trickmode)(struct vdec_s *vdec, unsigned long trickmode); - int (*set_isreset)(struct vdec_s *vdec, int isreset); - void (*vdec_fps_detec)(int id); - - unsigned long (*run_ready)(struct vdec_s *vdec, unsigned long mask); - void (*run)(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *); - void (*reset)(struct vdec_s *vdec); - void (*dump_state)(struct vdec_s *vdec); - irqreturn_t (*irq_handler)(struct vdec_s *vdec, int irq); - irqreturn_t (*threaded_irq_handler)(struct vdec_s *vdec, int irq); - - int (*user_data_read)(struct vdec_s *vdec, - struct userdata_param_t *puserdata_para); - void (*reset_userdata_fifo)(struct vdec_s *vdec, int bInit); - void (*wakeup_userdata_poll)(struct vdec_s *vdec); - /* private */ - void *private; /* decoder per instance specific data */ -#ifdef VDEC_DEBUG_SUPPORT - u64 profile_start_clk[VDEC_MAX]; - u64 total_clk[VDEC_MAX]; - u32 check_count[VDEC_MAX]; - u32 not_run_ready_count[VDEC_MAX]; - u32 input_underrun_count[VDEC_MAX]; - u32 run_count[VDEC_MAX]; - u64 run_clk[VDEC_MAX]; - u64 start_run_clk[VDEC_MAX]; -#endif - atomic_t inirq_thread_flag; - atomic_t inirq_flag; - int parallel_dec; -}; - -/* common decoder vframe provider name to use default vfm path */ -#define VFM_DEC_PROVIDER_NAME "decoder" -#define VFM_DEC_DVBL_PROVIDER_NAME "dvbldec" -#define VFM_DEC_DVEL_PROVIDER_NAME "dveldec" - -#define hw_to_vdec(hw) ((struct vdec_s *) \ - (platform_get_drvdata(hw->platform_dev))) - -#define canvas_y(canvas) ((canvas) & 0xff) -#define canvas_u(canvas) (((canvas) >> 8) & 0xff) -#define canvas_v(canvas) (((canvas) >> 16) & 0xff) -#define canvas_y2(canvas) (((canvas) >> 16) & 0xff) -#define canvas_u2(canvas) (((canvas) >> 24) & 0xff) - -#define vdec_frame_based(vdec) \ - (((vdec)->type == VDEC_TYPE_FRAME_BLOCK) || \ - ((vdec)->type == VDEC_TYPE_FRAME_CIRCULAR)) -#define vdec_stream_based(vdec) \ - (((vdec)->type == VDEC_TYPE_STREAM_PARSER) || \ - ((vdec)->type == VDEC_TYPE_SINGLE)) -#define vdec_single(vdec) \ - ((vdec)->type == VDEC_TYPE_SINGLE) -#define vdec_dual(vdec) \ - (((vdec)->port->type & PORT_TYPE_DUALDEC) ||\ - (vdec_get_debug_flags() & 0x100)) -#define vdec_secure(vdec) \ - (((vdec)->port_flag & PORT_FLAG_DRM)) - -/* construct vdec strcture */ -extern struct vdec_s *vdec_create(struct stream_port_s *port, - struct vdec_s *master); - -/* set video format */ -extern int vdec_set_format(struct vdec_s *vdec, int format); - -/* set PTS */ -extern int vdec_set_pts(struct vdec_s *vdec, u32 pts); - -extern int vdec_set_pts64(struct vdec_s *vdec, u64 pts64); - -/* set vfm map when use frame base decoder */ -extern int vdec_set_video_path(struct vdec_s *vdec, int video_path); - -/* set receive id when receive is ionvideo or amlvideo */ -extern int vdec_set_receive_id(struct vdec_s *vdec, int receive_id); - -/* add frame data to input chain */ -extern int vdec_write_vframe(struct vdec_s *vdec, const char *buf, - size_t count); - -/* mark the vframe_chunk as consumed */ -extern void vdec_vframe_dirty(struct vdec_s *vdec, - struct vframe_chunk_s *chunk); - -/* prepare decoder input */ -extern int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p); - -/* clean decoder input */ -extern void vdec_clean_input(struct vdec_s *vdec); - -/* sync decoder input */ -extern int vdec_sync_input(struct vdec_s *vdec); - -/* enable decoder input */ -extern void vdec_enable_input(struct vdec_s *vdec); - -/* set decoder input prepare level */ -extern void vdec_set_prepare_level(struct vdec_s *vdec, int level); - -/* set vdec input */ -extern int vdec_set_input_buffer(struct vdec_s *vdec, u32 start, u32 size); - -/* check if decoder can get more input */ -extern bool vdec_has_more_input(struct vdec_s *vdec); - -/* allocate input chain - * register vdec_device - * create output, vfm or create ionvideo output - * insert vdec to vdec_manager for scheduling - */ -extern int vdec_connect(struct vdec_s *vdec); - -/* remove vdec from vdec_manager scheduling - * release input chain - * disconnect video output from ionvideo - */ -extern int vdec_disconnect(struct vdec_s *vdec); - -/* release vdec structure */ -extern int vdec_destroy(struct vdec_s *vdec); - -/* reset vdec */ -extern int vdec_reset(struct vdec_s *vdec); - -extern void vdec_set_status(struct vdec_s *vdec, int status); - -extern void vdec_set_next_status(struct vdec_s *vdec, int status); - -extern int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p); - -extern int vdec_init(struct vdec_s *vdec, int is_4k); - -extern void vdec_release(struct vdec_s *vdec); - -extern int vdec_status(struct vdec_s *vdec, struct vdec_info *vstatus); - -extern int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode); - -extern int vdec_set_isreset(struct vdec_s *vdec, int isreset); - -extern int vdec_set_dv_metawithel(struct vdec_s *vdec, int isdvmetawithel); - -extern void vdec_set_no_powerdown(int flag); - -extern int vdec_is_support_4k(void); -extern void vdec_set_flag(struct vdec_s *vdec, u32 flag); - -extern void vdec_set_eos(struct vdec_s *vdec, bool eos); - -extern void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec); - -extern const char *vdec_status_str(struct vdec_s *vdec); - -extern const char *vdec_type_str(struct vdec_s *vdec); - -extern const char *vdec_device_name_str(struct vdec_s *vdec); - -extern void vdec_schedule_work(struct work_struct *work); - -extern void vdec_count_info(struct vdec_info *vs, unsigned int err, - unsigned int offset); - -extern bool vdec_need_more_data(struct vdec_s *vdec); - -extern void vdec_reset_core(struct vdec_s *vdec); - -extern void hevc_reset_core(struct vdec_s *vdec); - -extern void vdec_set_suspend_clk(int mode, int hevc); - -extern unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask); - -extern void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask); - -extern void vdec_core_request(struct vdec_s *vdec, unsigned long mask); - -extern int vdec_core_release(struct vdec_s *vdec, unsigned long mask); - -extern bool vdec_core_with_input(unsigned long mask); - -extern void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask); - -#ifdef VDEC_DEBUG_SUPPORT -extern void vdec_set_step_mode(void); -#endif - -extern void vdec_disable_DMC(struct vdec_s *vdec); -extern void vdec_enable_DMC(struct vdec_s *vdec); -extern void hevc_enable_DMC(struct vdec_s *vdec); - -int vdec_read_user_data(struct vdec_s *vdec, - struct userdata_param_t *p_userdata_param); - -int vdec_wakeup_userdata_poll(struct vdec_s *vdec); - -void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit); - -struct vdec_s *vdec_get_vdec_by_id(int vdec_id); - -#ifdef VDEC_DEBUG_SUPPORT -extern void vdec_set_step_mode(void); -#endif -int vdec_get_debug_flags(void); - -unsigned char is_mult_inc(unsigned int); - -int vdec_get_status(struct vdec_s *vdec); - -void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp); - -struct vdec_s *vdec_get_with_id(unsigned int id); - -extern struct vframe_qos_s *vdec_get_qos_info(void); -#endif /* VDEC_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c deleted file mode 100644 index f571bcf52592..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c +++ /dev/null @@ -1,1106 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/vdec_input.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include - -#include "../../../stream_input/amports/amports_priv.h" -#include "vdec.h" -#include "vdec_input.h" - -#include -#include - -#include - -#define VFRAME_BLOCK_SIZE (512 * SZ_1K)/*512 for 1080p default init.*/ -#define VFRAME_BLOCK_SIZE_4K (2 * SZ_1M) /*2M for 4K default.*/ -#define VFRAME_BLOCK_SIZE_MAX (4 * SZ_1M) - -#define VFRAME_BLOCK_PAGEALIGN 4 -#define VFRAME_BLOCK_MIN_LEVEL (2 * SZ_1M) -#define VFRAME_BLOCK_MAX_LEVEL (8 * SZ_1M) -#define VFRAME_BLOCK_MAX_TOTAL_SIZE (16 * SZ_1M) - -/* -2s for OMX -*/ -#define MAX_FRAME_DURATION_S 2 - - -#define VFRAME_BLOCK_HOLE (SZ_64K) - -#define MIN_FRAME_PADDING_SIZE ((u32)(L1_CACHE_BYTES)) - -#define EXTRA_PADDING_SIZE (16 * SZ_1K) /*HEVC_PADDING_SIZE*/ - -#define MEM_NAME "VFRAME_INPUT" - -//static int vdec_input_get_duration_u64(struct vdec_input_s *input); -static struct vframe_block_list_s * - vdec_input_alloc_new_block(struct vdec_input_s *input, - ulong phy_addr, - int size); - -static int copy_from_user_to_phyaddr(void *virts, const char __user *buf, - u32 size, ulong phys, u32 pading, bool is_mapped) -{ - u32 i, span = SZ_1M; - u32 count = size / PAGE_ALIGN(span); - u32 remain = size % PAGE_ALIGN(span); - ulong addr = phys; - u8 *p = virts; - - if (is_mapped) { - if (copy_from_user(p, buf, size)) - return -EFAULT; - - if (pading) - memset(p + size, 0, pading); - - codec_mm_dma_flush(p, size + pading, DMA_TO_DEVICE); - - return 0; - } - - for (i = 0; i < count; i++) { - addr = phys + i * span; - p = codec_mm_vmap(addr, span); - if (!p) - return -1; - - if (copy_from_user(p, buf + i * span, span)) { - codec_mm_unmap_phyaddr(p); - return -EFAULT; - } - - codec_mm_dma_flush(p, span, DMA_TO_DEVICE); - codec_mm_unmap_phyaddr(p); - } - - if (!remain) - return 0; - - span = size - remain; - addr = phys + span; - p = codec_mm_vmap(addr, remain + pading); - if (!p) - return -1; - - if (copy_from_user(p, buf + span, remain)) { - codec_mm_unmap_phyaddr(p); - return -EFAULT; - } - - if (pading) - memset(p + remain, 0, pading); - - codec_mm_dma_flush(p, remain + pading, DMA_TO_DEVICE); - codec_mm_unmap_phyaddr(p); - - return 0; -} - -static int vframe_chunk_fill(struct vdec_input_s *input, - struct vframe_chunk_s *chunk, const char *buf, - size_t count, struct vframe_block_list_s *block) -{ - u8 *p = (u8 *)block->start_virt + block->wp; - if (block->type == VDEC_TYPE_FRAME_BLOCK) { - copy_from_user_to_phyaddr(p, buf, count, - block->start + block->wp, - chunk->pading_size, - block->is_mapped); - } else if (block->type == VDEC_TYPE_FRAME_CIRCULAR) { - size_t len = min((size_t)(block->size - block->wp), count); - u32 wp; - - copy_from_user_to_phyaddr(p, buf, len, - block->start + block->wp, 0, - block->is_mapped); - p += len; - - if (count > len) { - copy_from_user_to_phyaddr(p, buf + len, - count - len, - block->start, 0, - block->is_mapped); - - p += count - len; - } - - wp = block->wp + count; - if (wp >= block->size) - wp -= block->size; - - len = min(block->size - wp, chunk->pading_size); - - if (!block->is_mapped) { - p = codec_mm_vmap(block->start + wp, len); - memset(p, 0, len); - codec_mm_dma_flush(p, len, DMA_TO_DEVICE); - codec_mm_unmap_phyaddr(p); - } else { - memset(p, 0, len); - codec_mm_dma_flush(p, len, DMA_TO_DEVICE); - } - - if (chunk->pading_size > len) { - p = (u8 *)block->start_virt; - - if (!block->is_mapped) { - p = codec_mm_vmap(block->start, - chunk->pading_size - len); - memset(p, 0, chunk->pading_size - len); - codec_mm_dma_flush(p, - chunk->pading_size - len, - DMA_TO_DEVICE); - codec_mm_unmap_phyaddr(p); - } else { - memset(p, 0, chunk->pading_size - len); - codec_mm_dma_flush(p, - chunk->pading_size - len, - DMA_TO_DEVICE); - } - } - } - - return 0; -} - -static inline u32 vframe_block_space(struct vframe_block_list_s *block) -{ - if (block->type == VDEC_TYPE_FRAME_BLOCK) { - return block->size - block->wp; - } else { - return (block->rp >= block->wp) ? - (block->rp - block->wp) : - (block->rp - block->wp + block->size); - } -} - -static void vframe_block_add_chunk(struct vframe_block_list_s *block, - struct vframe_chunk_s *chunk) -{ - block->wp += chunk->size + chunk->pading_size; - if (block->wp >= block->size) - block->wp -= block->size; - block->data_size += chunk->size; - block->chunk_count++; - chunk->block = block; - block->input->wr_block = block; - chunk->sequence = block->input->sequence; - block->input->sequence++; -} - -static void vframe_block_free_block(struct vframe_block_list_s *block) -{ - if (block->addr) { - codec_mm_free_for_dma(MEM_NAME, block->addr); - } - /* - *pr_err("free block %d, size=%d\n", block->id, block->size); - */ - kfree(block); -} - -static int vframe_block_init_alloc_storage(struct vdec_input_s *input, - struct vframe_block_list_s *block, - ulong phy_addr, - int size) -{ - int alloc_size = input->default_block_size; - block->magic = 0x4b434c42; - block->input = input; - block->type = input->type; - - /* - * todo: for different type use different size - */ - if (phy_addr) { - block->is_out_buf = 1; - block->start_virt = NULL; - block->start = phy_addr; - block->size = size; - } else { - alloc_size = PAGE_ALIGN(alloc_size); - block->addr = codec_mm_alloc_for_dma_ex( - MEM_NAME, - alloc_size/PAGE_SIZE, - VFRAME_BLOCK_PAGEALIGN, - CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER, - input->id, - block->id); - - if (!block->addr) { - pr_err("Input block allocation failed\n"); - return -ENOMEM; - } - - block->start_virt = (void *)codec_mm_phys_to_virt(block->addr); - if (block->start_virt) - block->is_mapped = true; - block->start = block->addr; - block->size = alloc_size; - block->is_out_buf = 0; - } - - return 0; -} - -void vdec_input_init(struct vdec_input_s *input, struct vdec_s *vdec) -{ - INIT_LIST_HEAD(&input->vframe_block_list); - INIT_LIST_HEAD(&input->vframe_block_free_list); - INIT_LIST_HEAD(&input->vframe_chunk_list); - spin_lock_init(&input->lock); - input->id = vdec->id; - input->block_nums = 0; - input->vdec = vdec; - input->block_id_seq = 0; - input->size = 0; - input->default_block_size = VFRAME_BLOCK_SIZE; -} -int vdec_input_prepare_bufs(struct vdec_input_s *input, - int frame_width, int frame_height) -{ - struct vframe_block_list_s *block; - int i; - unsigned long flags; - - if (vdec_secure(input->vdec)) - return 0; - if (input->size > 0) - return 0; - if (frame_width * frame_height >= 1920 * 1088) { - /*have add data before. ignore prepare buffers.*/ - input->default_block_size = VFRAME_BLOCK_SIZE_4K; - } - /*prepared 3 buffers for smooth start.*/ - for (i = 0; i < 3; i++) { - block = vdec_input_alloc_new_block(input, 0, 0); - if (!block) - break; - flags = vdec_input_lock(input); - list_move_tail(&block->list, - &input->vframe_block_free_list); - input->wr_block = NULL; - vdec_input_unlock(input, flags); - } - return 0; -} - -static int vdec_input_dump_block_locked( - struct vframe_block_list_s *block, - char *buf, int size) -{ - char *pbuf = buf; - char sbuf[512]; - int tsize = 0; - int s; - if (!pbuf) { - pbuf = sbuf; - size = 512; - } - #define BUFPRINT(args...) \ - do {\ - s = snprintf(pbuf, size - tsize, args);\ - tsize += s;\ - pbuf += s; \ - } while (0) - - BUFPRINT("\tblock:[%d:%p]-addr=%p,vstart=%p,type=%d\n", - block->id, - block, - (void *)block->addr, - (void *)block->start_virt, - block->type); - BUFPRINT("\t-blocksize=%d,data=%d,wp=%d,rp=%d,chunk_count=%d\n", - block->size, - block->data_size, - block->wp, - block->rp, - block->chunk_count); - /* - BUFPRINT("\tlist=%p,next=%p,prev=%p\n", - &block->list, - block->list.next, - block->list.prev); - */ - #undef BUFPRINT - if (!buf) - pr_info("%s", sbuf); - return tsize; -} - -int vdec_input_dump_blocks(struct vdec_input_s *input, - char *bufs, int size) -{ - struct list_head *p, *tmp; - unsigned long flags; - char *lbuf = bufs; - char sbuf[256]; - int s = 0; - - if (size <= 0) - return 0; - if (!bufs) - lbuf = sbuf; - s += snprintf(lbuf + s, size - s, - "blocks:vdec-%d id:%d,bufsize=%d,dsize=%d,frames:%d,dur:%dms\n", - input->id, - input->block_nums, - input->size, - input->data_size, - input->have_frame_num, - vdec_input_get_duration_u64(input)/1000); - if (bufs) - lbuf += s; - else { - pr_info("%s", sbuf); - lbuf = NULL; - } - - flags = vdec_input_lock(input); - /* dump input blocks */ - list_for_each_safe(p, tmp, &input->vframe_block_list) { - struct vframe_block_list_s *block = list_entry( - p, struct vframe_block_list_s, list); - if (bufs != NULL) { - lbuf = bufs + s; - if (size - s < 128) - break; - } - s += vdec_input_dump_block_locked(block, lbuf, size - s); - } - list_for_each_safe(p, tmp, &input->vframe_block_free_list) { - struct vframe_block_list_s *block = list_entry( - p, struct vframe_block_list_s, list); - if (bufs != NULL) { - lbuf = bufs + s; - if (size - s < 128) - break; - } - s += vdec_input_dump_block_locked(block, lbuf, size - s); - } - vdec_input_unlock(input, flags); - return s; -} - -static int vdec_input_dump_chunk_locked( - struct vframe_chunk_s *chunk, - char *buf, int size) -{ - char *pbuf = buf; - char sbuf[512]; - int tsize = 0; - int s; - if (!pbuf) { - pbuf = sbuf; - size = 512; - } - #define BUFPRINT(args...) \ - do {\ - s = snprintf(pbuf, size - tsize, args);\ - tsize += s;\ - pbuf += s; \ - } while (0) - - BUFPRINT( - "\t[%lld:%p]-off=%d,size:%d,p:%d,\tpts64=%lld,addr=%p\n", - chunk->sequence, - chunk->block, - chunk->offset, - chunk->size, - chunk->pading_size, - chunk->pts64, - (void *)(chunk->block->addr + chunk->offset)); - /* - BUFPRINT("\tlist=%p,next=%p,prev=%p\n", - &chunk->list, - chunk->list.next, - chunk->list.prev); - */ - #undef BUFPRINT - if (!buf) - pr_info("%s", sbuf); - return tsize; -} - -int vdec_input_dump_chunks(struct vdec_input_s *input, - char *bufs, int size) -{ - - struct list_head *p, *tmp; - unsigned long flags; - char *lbuf = bufs; - char sbuf[256]; - int s = 0; - if (size <= 0) - return 0; - if (!bufs) - lbuf = sbuf; - snprintf(lbuf + s, size - s, - "blocks:vdec-%d id:%d,bufsize=%d,dsize=%d,frames:%d,maxframe:%d\n", - input->id, - input->block_nums, - input->size, - input->data_size, - input->have_frame_num, - input->frame_max_size); - if (bufs) - lbuf += s; - if (!bufs) { - pr_info("%s", sbuf); - lbuf = NULL; - } - flags = vdec_input_lock(input); - /*dump chunks list infos.*/ - list_for_each_safe(p, tmp, &input->vframe_chunk_list) { - struct vframe_chunk_s *chunk = list_entry( - p, struct vframe_chunk_s, list); - if (bufs != NULL) - lbuf = bufs + s; - s += vdec_input_dump_chunk_locked(chunk, lbuf, size - s); - } - vdec_input_unlock(input, flags); - return s; -} - - - -int vdec_input_set_buffer(struct vdec_input_s *input, u32 start, u32 size) -{ - if (input_frame_based(input)) - return -EINVAL; - - input->start = start; - input->size = size; - input->swap_rp = start; - - if (vdec_secure(input->vdec)) - input->swap_page_phys = codec_mm_alloc_for_dma("SWAP", - 1, 0, CODEC_MM_FLAGS_TVP); - else { - input->swap_page = alloc_page(GFP_KERNEL); - if (input->swap_page) { - input->swap_page_phys = - page_to_phys(input->swap_page); - } - } - - if (input->swap_page_phys == 0) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL(vdec_input_set_buffer); - -void vdec_input_set_type(struct vdec_input_s *input, int type, int target) -{ - input->type = type; - input->target = target; - if (type == VDEC_TYPE_FRAME_CIRCULAR) { - /*alway used max block.*/ - input->default_block_size = VFRAME_BLOCK_SIZE_MAX; - } -} -EXPORT_SYMBOL(vdec_input_set_type); - -int vdec_input_get_status(struct vdec_input_s *input, - struct vdec_input_status_s *status) -{ - unsigned long flags; - - if (input->vdec == NULL) - return -EINVAL; - - flags = vdec_input_lock(input); - - if (list_empty(&input->vframe_block_list)) { - status->size = VFRAME_BLOCK_SIZE; - status->data_len = 0; - status->free_len = VFRAME_BLOCK_SIZE; - status->read_pointer = 0; - } else { - int r = VFRAME_BLOCK_MAX_LEVEL - vdec_input_level(input) - - VFRAME_BLOCK_HOLE; - status->size = input->size; - status->data_len = vdec_input_level(input); - status->free_len = (r > 0) ? r : 0; - status->read_pointer = input->total_rd_count; - } - - vdec_input_unlock(input, flags); - - return 0; -} -EXPORT_SYMBOL(vdec_input_get_status); - -static void vdec_input_add_block(struct vdec_input_s *input, - struct vframe_block_list_s *block) -{ - unsigned long flags; - - flags = vdec_input_lock(input); - block->wp = 0; - block->id = input->block_id_seq++; - list_add_tail(&block->list, &input->vframe_block_list); - input->size += block->size; - input->block_nums++; - input->wr_block = block; - vdec_input_unlock(input, flags); -} - -static inline void vdec_input_del_block_locked(struct vdec_input_s *input, - struct vframe_block_list_s *block) -{ - list_del(&block->list); - input->size -= block->size; - input->block_nums--; -} - -int vdec_input_level(struct vdec_input_s *input) -{ - return input->total_wr_count - input->total_rd_count; -} -EXPORT_SYMBOL(vdec_input_level); - -static struct vframe_block_list_s * - vdec_input_alloc_new_block(struct vdec_input_s *input, - ulong phy_addr, - int size) -{ - struct vframe_block_list_s *block; - block = kzalloc(sizeof(struct vframe_block_list_s), - GFP_KERNEL); - if (block == NULL) { - input->no_mem_err_cnt++; - pr_err("vframe_block structure allocation failed\n"); - return NULL; - } - - if (vframe_block_init_alloc_storage(input, - block, phy_addr, size) != 0) { - kfree(block); - pr_err("vframe_block storage allocation failed\n"); - return NULL; - } - - INIT_LIST_HEAD(&block->list); - - vdec_input_add_block(input, block); - - /* - *pr_info("vdec-%d:new block id=%d, total_blocks:%d, size=%d\n", - * input->id, - * block->id, - * input->block_nums, - * block->size); - */ - if (0 && input->size > VFRAME_BLOCK_MAX_LEVEL * 2) { - /* - used - */ - pr_info( - "input[%d] reach max: size:%d, blocks:%d", - input->id, - input->size, - input->block_nums); - pr_info("level:%d, wr:%lld,rd:%lld\n", - vdec_input_level(input), - input->total_wr_count, - input->total_rd_count); - vdec_input_dump_blocks(input, NULL, 0); - } - return block; -} -int vdec_input_get_duration_u64(struct vdec_input_s *input) -{ - int duration = (input->last_inpts_u64 - input->last_comsumed_pts_u64); - if (input->last_in_nopts_cnt > 0 && - input->last_comsumed_pts_u64 > 0 && - input->last_duration > 0) { - duration += (input->last_in_nopts_cnt - - input->last_comsumed_no_pts_cnt) * - input->last_duration; - } - if (duration > 1000 * 1000000)/*> 1000S,I think jumped.*/ - duration = 0; - if (duration <= 0 && input->last_duration > 0) { - /*..*/ - duration = input->last_duration * input->have_frame_num; - } - if (duration < 0) - duration = 0; - return duration; -} -EXPORT_SYMBOL(vdec_input_get_duration_u64); - -/* - ret >= 13: have enough buffer, blocked add more buffers -*/ -static int vdec_input_have_blocks_enough(struct vdec_input_s *input) -{ - int ret = 0; - if (vdec_input_level(input) > VFRAME_BLOCK_MIN_LEVEL) - ret += 1; - if (vdec_input_level(input) >= VFRAME_BLOCK_MAX_LEVEL) - ret += 2; - if (vdec_input_get_duration_u64(input) > MAX_FRAME_DURATION_S) - ret += 4; - if (input->have_frame_num > 30) - ret += 8; - else - ret -= 8;/*not enough frames.*/ - if (input->size >= VFRAME_BLOCK_MAX_TOTAL_SIZE) - ret += 100;/*always bloced add more buffers.*/ - - return ret; -} -static int vdec_input_get_free_block( - struct vdec_input_s *input, - int size,/*frame size + pading*/ - struct vframe_block_list_s **block_ret) -{ - struct vframe_block_list_s *to_freeblock = NULL; - struct vframe_block_list_s *block = NULL; - unsigned long flags; - flags = vdec_input_lock(input); - /*get from free list.*/ - if (!list_empty(&input->vframe_block_free_list)) { - block = list_entry(input->vframe_block_free_list.next, - struct vframe_block_list_s, list); - if (block->size < (size)) { - vdec_input_del_block_locked(input, block); - to_freeblock = block; - block = NULL; - } else { - list_move_tail(&block->list, - &input->vframe_block_list); - input->wr_block = block;/*swith to new block*/ - } - } - vdec_input_unlock(input, flags); - if (to_freeblock) { - /*free the small block.*/ - vframe_block_free_block(to_freeblock); - } - if (block) { - *block_ret = block; - return 0; - } - - if (vdec_input_have_blocks_enough(input) > 13) { - /*buf fulled */ - return -EAGAIN; - } - if (input->no_mem_err_cnt > 3) { - /*alloced failed more times. - */ - return -EAGAIN; - } - if (input->default_block_size <= - size * 2) { - int def_size = input->default_block_size; - do { - def_size *= 2; - } while ((def_size <= 2 * size) && - (def_size <= VFRAME_BLOCK_SIZE_MAX)); - if (def_size < size) - def_size = ALIGN(size + 64, (1 << 17)); - /*128k aligned,same as codec_mm*/ - input->default_block_size = def_size; - } - block = vdec_input_alloc_new_block(input, 0, 0); - if (!block) { - input->no_mem_err_cnt++; - return -EAGAIN; - } - input->no_mem_err_cnt = 0; - *block_ret = block; - return 0; -} - -int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf, - size_t count, u32 handle) -{ - unsigned long flags; - struct vframe_chunk_s *chunk; - struct vdec_s *vdec = input->vdec; - struct vframe_block_list_s *block; - - int need_pading_size = MIN_FRAME_PADDING_SIZE; - - if (vdec_secure(vdec)) { - block = vdec_input_alloc_new_block(input, (ulong)buf, - PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1)); /*Add padding large than HEVC_PADDING_SIZE */ - if (!block) - return -ENOMEM; - block->handle = handle; - } else { -#if 0 - if (add_count == 0) { - add_count++; - memcpy(sps, buf, 30); - return 30; - } else if (add_count == 1) { - add_count++; - memcpy(pps, buf, 8); - return 8; - } - add_count++; -#endif - -#if 0 - pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count); - - if (count >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); - } - if (count >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[8], buf[9], buf[10], buf[11], - buf[12], buf[13], buf[14], buf[15]); - } - if (count >= 24) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[16], buf[17], buf[18], buf[19], - buf[20], buf[21], buf[22], buf[23]); - } - if (count >= 32) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[24], buf[25], buf[26], buf[27], - buf[28], buf[29], buf[30], buf[31]); - } -#endif - if (input_stream_based(input)) - return -EINVAL; - - if (count < PAGE_SIZE) { - need_pading_size = PAGE_ALIGN(count + need_pading_size) - - count; - } else { - /*to 64 bytes aligned;*/ - if (count & 0x3f) - need_pading_size += 64 - (count & 0x3f); - } - block = input->wr_block; - if (block && - (vframe_block_space(block) > (count + need_pading_size))) { - /*this block have enough buffers. - do nothings. - */ - } else if (block && (block->type == VDEC_TYPE_FRAME_CIRCULAR)) { - /*in circular module. - only one block,.*/ - return -EAGAIN; - } else if (block != NULL) { - /*have block but not enough space. - recycle the no enough blocks.*/ - flags = vdec_input_lock(input); - if (input->wr_block == block && - block->chunk_count == 0) { - block->rp = 0; - block->wp = 0; - /*block no data move to freelist*/ - list_move_tail(&block->list, - &input->vframe_block_free_list); - input->wr_block = NULL; - } - vdec_input_unlock(input, flags); - block = NULL; - } - if (!block) {/*try new block.*/ - int ret = vdec_input_get_free_block(input, - count + need_pading_size + EXTRA_PADDING_SIZE, - &block); - if (ret < 0)/*no enough block now.*/ - return ret; - } - } - - chunk = kzalloc(sizeof(struct vframe_chunk_s), GFP_KERNEL); - - if (!chunk) { - pr_err("vframe_chunk structure allocation failed\n"); - return -ENOMEM; - } - - chunk->magic = 0x4b554843; - if (vdec->pts_valid) { - chunk->pts = vdec->pts; - chunk->pts64 = vdec->pts64; - } - - if (vdec->timestamp_valid) - chunk->timestamp = vdec->timestamp; - - if (vdec->pts_valid && - input->last_inpts_u64 > 0 && - input->last_in_nopts_cnt == 0) { - int d = (int)(chunk->pts64 - input->last_inpts_u64); - if (d > 0 && (d < input->last_duration)) - input->last_duration = d; - /* alwasy: used the smallest duration; - if 60fps->30 fps. - maybe have warning value. - */ - } - chunk->pts_valid = vdec->pts_valid; - vdec->pts_valid = false; - INIT_LIST_HEAD(&chunk->list); - - if (vdec_secure(vdec)) { - chunk->offset = 0; - chunk->size = count; - chunk->pading_size = PAGE_ALIGN(chunk->size + need_pading_size) - - chunk->size; - } else { - chunk->offset = block->wp; - chunk->size = count; - chunk->pading_size = need_pading_size; - if (vframe_chunk_fill(input, chunk, buf, count, block)) { - pr_err("vframe_chunk_fill failed\n"); - kfree(chunk); - return -EFAULT; - } - - } - - - flags = vdec_input_lock(input); - - vframe_block_add_chunk(block, chunk); - - list_add_tail(&chunk->list, &input->vframe_chunk_list); - input->data_size += chunk->size; - input->have_frame_num++; - ATRACE_COUNTER(MEM_NAME, input->have_frame_num); - if (chunk->pts_valid) { - input->last_inpts_u64 = chunk->pts64; - input->last_in_nopts_cnt = 0; - } else { - /*nopts*/ - input->last_in_nopts_cnt++; - } - if (chunk->size > input->frame_max_size) - input->frame_max_size = chunk->size; - input->total_wr_count += count; - vdec_input_unlock(input, flags); -#if 0 - if (add_count == 2) - input->total_wr_count += 38; -#endif - - return count; -} - -int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, - size_t count) -{ - int ret = 0; - struct drm_info drm; - struct vdec_s *vdec = input->vdec; - unsigned long phy_buf; - - if (vdec_secure(vdec)) { - while (count > 0) { - if (count < sizeof(struct drm_info)) - return -EIO; - if (copy_from_user(&drm, buf + ret, sizeof(struct drm_info))) - return -EAGAIN; - if (!(drm.drm_flag & TYPE_DRMINFO_V2)) - return -EIO; /*must drm info v2 version*/ - phy_buf = (unsigned long) drm.drm_phy; - vdec_input_add_chunk(input, (char *)phy_buf, - (size_t)drm.drm_pktsize, drm.handle); - count -= sizeof(struct drm_info); - ret += sizeof(struct drm_info); - - /* the drm frame data might include head infos and raw */ - /* data thus the next drm unit still need a valid pts.*/ - if (count >= sizeof(struct drm_info)) - vdec->pts_valid = true; - } - } else { - ret = vdec_input_add_chunk(input, buf, count, 0); - } - return ret; -} -EXPORT_SYMBOL(vdec_input_add_frame); - -struct vframe_chunk_s *vdec_input_next_chunk(struct vdec_input_s *input) -{ - struct vframe_chunk_s *chunk = NULL; - unsigned long flags; - flags = vdec_input_lock(input); - if (!list_empty(&input->vframe_chunk_list)) { - chunk = list_first_entry(&input->vframe_chunk_list, - struct vframe_chunk_s, list); - } - vdec_input_unlock(input, flags); - return chunk; -} -EXPORT_SYMBOL(vdec_input_next_chunk); - -struct vframe_chunk_s *vdec_input_next_input_chunk( - struct vdec_input_s *input) -{ - struct vframe_chunk_s *chunk = NULL; - struct list_head *p; - unsigned long flags; - flags = vdec_input_lock(input); - - list_for_each(p, &input->vframe_chunk_list) { - struct vframe_chunk_s *c = list_entry( - p, struct vframe_chunk_s, list); - if ((c->flag & VFRAME_CHUNK_FLAG_CONSUMED) == 0) { - chunk = c; - break; - } - } - vdec_input_unlock(input, flags); - return chunk; -} -EXPORT_SYMBOL(vdec_input_next_input_chunk); - -void vdec_input_release_chunk(struct vdec_input_s *input, - struct vframe_chunk_s *chunk) -{ - unsigned long flags; - struct vframe_block_list_s *block = chunk->block; - struct vframe_block_list_s *tofreeblock = NULL; - flags = vdec_input_lock(input); - - list_del(&chunk->list); - input->have_frame_num--; - ATRACE_COUNTER(MEM_NAME, input->have_frame_num); - if (chunk->pts_valid) { - input->last_comsumed_no_pts_cnt = 0; - input->last_comsumed_pts_u64 = chunk->pts64; - } else - input->last_comsumed_no_pts_cnt++; - block->rp += chunk->size; - if (block->rp >= block->size) - block->rp -= block->size; - block->data_size -= chunk->size; - block->chunk_count--; - input->data_size -= chunk->size; - input->total_rd_count += chunk->size; - if (block->is_out_buf) { - list_move_tail(&block->list, - &input->vframe_block_free_list); - } else if (block->chunk_count == 0 && - input->wr_block != block ) {/*don't free used block*/ - if (block->size < input->default_block_size) { - vdec_input_del_block_locked(input, block); - tofreeblock = block; - } else { - block->rp = 0; - block->wp = 0; - list_move_tail(&block->list, - &input->vframe_block_free_list); - } - } - - vdec_input_unlock(input, flags); - if (tofreeblock) - vframe_block_free_block(tofreeblock); - kfree(chunk); -} -EXPORT_SYMBOL(vdec_input_release_chunk); - -unsigned long vdec_input_lock(struct vdec_input_s *input) -{ - unsigned long flags; - - spin_lock_irqsave(&input->lock, flags); - - return flags; -} -EXPORT_SYMBOL(vdec_input_lock); - -void vdec_input_unlock(struct vdec_input_s *input, unsigned long flags) -{ - spin_unlock_irqrestore(&input->lock, flags); -} -EXPORT_SYMBOL(vdec_input_unlock); - -void vdec_input_release(struct vdec_input_s *input) -{ - struct list_head *p, *tmp; - - /* release chunk data */ - list_for_each_safe(p, tmp, &input->vframe_chunk_list) { - struct vframe_chunk_s *chunk = list_entry( - p, struct vframe_chunk_s, list); - vdec_input_release_chunk(input, chunk); - } - list_for_each_safe(p, tmp, &input->vframe_block_list) { - /*should never here.*/ - list_move_tail(p, &input->vframe_block_free_list); - } - /* release input blocks */ - list_for_each_safe(p, tmp, &input->vframe_block_free_list) { - struct vframe_block_list_s *block = list_entry( - p, struct vframe_block_list_s, list); - vdec_input_del_block_locked(input, block); - vframe_block_free_block(block); - } - - /* release swap pages */ - if (input->swap_page_phys) { - if (vdec_secure(input->vdec)) - codec_mm_free_for_dma("SWAP", input->swap_page_phys); - else - __free_page(input->swap_page); - input->swap_page = NULL; - input->swap_page_phys = 0; - } - input->swap_valid = false; -} -EXPORT_SYMBOL(vdec_input_release); - -u32 vdec_input_get_freed_handle(struct vdec_s *vdec) -{ - struct vframe_block_list_s *block; - struct vdec_input_s *input = &vdec->input; - unsigned long flags; - u32 handle = 0; - - if (!vdec_secure(vdec)) - return 0; - - flags = vdec_input_lock(input); - block = list_first_entry_or_null(&input->vframe_block_free_list, - struct vframe_block_list_s, list); - - if (block) { - handle = block->handle; - vdec_input_del_block_locked(input, block); - kfree(block); - } - vdec_input_unlock(input, flags); - return handle; -} -EXPORT_SYMBOL(vdec_input_get_freed_handle); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h deleted file mode 100644 index d2304f6bcf4d..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * drivers/amlogic/media/frame_provider/decoder/utils/vdec_input.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VDEC_INPUT_H -#define VDEC_INPUT_H - -struct vdec_s; -struct vdec_input_s; - -struct vframe_block_list_s { - u32 magic; - int id; - struct list_head list; - ulong start; - void *start_virt; - ulong addr; - bool is_mapped; - int type; - u32 size; - u32 wp; - u32 rp; - int data_size; - int chunk_count; - int is_out_buf; - u32 handle; - struct vdec_input_s *input; -}; - -#define VFRAME_CHUNK_FLAG_CONSUMED 0x0001 - -struct vframe_chunk_s { - u32 magic; - struct list_head list; - int flag; - u32 offset; - u32 size; - u32 pts; - u32 pading_size; - u64 pts64; - bool pts_valid; - u64 timestamp; - bool timestamp_valid; - u64 sequence; - struct vframe_block_list_s *block; -}; - -#define VDEC_INPUT_TARGET_VLD 0 -#define VDEC_INPUT_TARGET_HEVC 1 -#define VLD_PADDING_SIZE 1024 -#define HEVC_PADDING_SIZE (1024*16) - -struct vdec_input_s { - struct list_head vframe_block_list; - struct list_head vframe_chunk_list; - struct list_head vframe_block_free_list; - struct vframe_block_list_s *wr_block; - int have_free_blocks; - int no_mem_err_cnt;/*when alloc no mem cnt++*/ - int block_nums; - int block_id_seq; - int id; - spinlock_t lock; - int type; - int target; - struct vdec_s *vdec; - bool swap_valid; - bool swap_needed; - bool eos; - struct page *swap_page; - unsigned long swap_page_phys; - u64 total_wr_count; - u64 total_rd_count; - u64 streaming_rp; - u32 swap_rp; - bool last_swap_slave; - int dirty_count; - u64 sequence; - unsigned start; - unsigned size; - int default_block_size; - int data_size; - int frame_max_size; - int prepare_level; -/*for check frame delay.*/ - u64 last_inpts_u64; - u64 last_comsumed_pts_u64; - int last_in_nopts_cnt; - int last_comsumed_no_pts_cnt; - int last_duration; -/*for check frame delay.*/ - int have_frame_num; - int stream_cookie; /* wrap count for vld_mem and - HEVC_SHIFT_BYTE_COUNT for hevc */ -}; - -struct vdec_input_status_s { - int size; - int data_len; - int free_len; - int read_pointer; -}; - -#define input_frame_based(input) \ - (((input)->type == VDEC_TYPE_FRAME_BLOCK) || \ - ((input)->type == VDEC_TYPE_FRAME_CIRCULAR)) -#define input_stream_based(input) \ - (((input)->type == VDEC_TYPE_STREAM_PARSER) || \ - ((input)->type == VDEC_TYPE_SINGLE)) - -/* Initialize vdec_input structure */ -extern void vdec_input_init(struct vdec_input_s *input, struct vdec_s *vdec); -extern int vdec_input_prepare_bufs(struct vdec_input_s *input, - int frame_width, int frame_height); - -/* Get available input data size */ -extern int vdec_input_level(struct vdec_input_s *input); - -/* Set input type and target */ -extern void vdec_input_set_type(struct vdec_input_s *input, int type, - int target); - -/* Set stream buffer information for stream based input */ -extern int vdec_input_set_buffer(struct vdec_input_s *input, u32 start, - u32 size); - -/* Add enqueue video data into decoder's input */ -extern int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, - size_t count); - -/* Peek next frame data from decoder's input */ -extern struct vframe_chunk_s *vdec_input_next_chunk( - struct vdec_input_s *input); - -/* Peek next frame data from decoder's input, not marked as consumed */ -extern struct vframe_chunk_s *vdec_input_next_input_chunk( - struct vdec_input_s *input); - -/* Consume next frame data from decoder's input */ -extern void vdec_input_release_chunk(struct vdec_input_s *input, - struct vframe_chunk_s *chunk); - -/* Get decoder input buffer status */ -extern int vdec_input_get_status(struct vdec_input_s *input, - struct vdec_input_status_s *status); - -extern unsigned long vdec_input_lock(struct vdec_input_s *input); - -extern void vdec_input_unlock(struct vdec_input_s *input, unsigned long lock); - -/* release all resource for decoder's input */ -extern void vdec_input_release(struct vdec_input_s *input); -/* return block handle and free block */ -extern u32 vdec_input_get_freed_handle(struct vdec_s *vdec); -int vdec_input_dump_chunks(struct vdec_input_s *input, - char *bufs, int size); -int vdec_input_dump_blocks(struct vdec_input_s *input, - char *bufs, int size); - -int vdec_input_get_duration_u64(struct vdec_input_s *input); - -#endif /* VDEC_INPUT_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c deleted file mode 100644 index d03335a6297c..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * drivers/amlogic/amports/vdec_profile.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#include -#include -#include -#include -#include - - -#include -#include -#include "vdec_profile.h" -#include "vdec.h" - -#define ISA_TIMERE 0x2662 -#define ISA_TIMERE_HI 0x2663 - -#define PROFILE_REC_SIZE 40 - -static DEFINE_MUTEX(vdec_profile_mutex); -static int rec_wp; -static bool rec_wrapped; -static uint dec_time_stat_flag; -static uint dec_time_stat_reset; - - -struct dentry *root, *event; - -#define MAX_INSTANCE_MUN 9 - -struct vdec_profile_time_stat_s { - int time_6ms_less_cnt; - int time_6_9ms_cnt; - int time_9_12ms_cnt; - int time_12_15ms_cnt; - int time_15_18ms_cnt; - int time_18_21ms_cnt; - int time_21ms_up_cnt; - u64 time_max_us; - u64 time_total_us; -}; - -struct vdec_profile_statistics_s { - bool status; - u64 run_lasttimestamp; - int run_cnt; - u64 cb_lasttimestamp; - int cb_cnt; - u64 decode_first_us; - struct vdec_profile_time_stat_s run2cb_time_stat; - struct vdec_profile_time_stat_s decode_time_stat; -}; - -static struct vdec_profile_statistics_s statistics_s[MAX_INSTANCE_MUN]; - - -struct vdec_profile_rec_s { - struct vdec_s *vdec; - u64 timestamp; - int event; - int para1; - int para2; -}; - -static struct vdec_profile_rec_s recs[PROFILE_REC_SIZE]; -static const char *event_name[VDEC_PROFILE_MAX_EVENT] = { - "run", - "cb", - "save_input", - "check run ready", - "run ready", - "disconnect", - "dec_work", - "info" -}; - -#if 0 /* get time from hardware. */ -static u64 get_us_time_hw(void) -{ - u32 lo, hi1, hi2; - int offset = 0; - - /* txlx, g12a isa register base is 0x3c00 */ - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) - offset = 0x1600; - - do { - hi1 = READ_MPEG_REG(ISA_TIMERE_HI + offset); - lo = READ_MPEG_REG(ISA_TIMERE + offset); - hi2 = READ_MPEG_REG(ISA_TIMERE_HI + offset); - } while (hi1 != hi2); - - return (((u64)hi1) << 32) | lo; -} -#endif - -static u64 get_us_time_system(void) -{ - struct timeval tv; - - do_gettimeofday(&tv); - - return div64_u64(timeval_to_ns(&tv), 1000); -} - -static void vdec_profile_update_alloc_time( - struct vdec_profile_time_stat_s *time_stat, u64 startus, u64 endus) -{ - u64 spend_time_us = endus - startus; - - if (spend_time_us > 0 && spend_time_us < 100000000) { - if (spend_time_us < 6000) - time_stat->time_6ms_less_cnt++; - else if (spend_time_us < 9000) - time_stat->time_6_9ms_cnt++; - else if (spend_time_us < 12000) - time_stat->time_9_12ms_cnt++; - else if (spend_time_us < 15000) - time_stat->time_12_15ms_cnt++; - else if (spend_time_us < 18000) - time_stat->time_15_18ms_cnt++; - else if (spend_time_us < 21000) - time_stat->time_18_21ms_cnt++; - else - time_stat->time_21ms_up_cnt++; - } - - if (spend_time_us > time_stat->time_max_us) - time_stat->time_max_us = spend_time_us; - - time_stat->time_total_us += spend_time_us; -} - - -static void vdec_profile_statistics(struct vdec_s *vdec, int event) -{ - struct vdec_profile_statistics_s *time_stat = NULL; - u64 timestamp; - int i; - - if (vdec->id >= MAX_INSTANCE_MUN) - return; - - if (event != VDEC_PROFILE_EVENT_RUN && - event != VDEC_PROFILE_EVENT_CB) - return; - - mutex_lock(&vdec_profile_mutex); - - if (dec_time_stat_reset == 1) { - if (event != VDEC_PROFILE_EVENT_RUN) { - mutex_unlock(&vdec_profile_mutex); - return; - } - for (i = 0; i < MAX_INSTANCE_MUN; i++) - memset(&statistics_s[i], 0, - sizeof(struct vdec_profile_statistics_s)); - dec_time_stat_reset = 0; - } - - time_stat = &statistics_s[vdec->id]; - timestamp = get_us_time_system(); - - if (time_stat->status == false) { - time_stat->decode_first_us = timestamp; - time_stat->status = true; - } - - if (event == VDEC_PROFILE_EVENT_RUN) { - time_stat->run_lasttimestamp = timestamp; - time_stat->run_cnt++; - } else if (event == VDEC_PROFILE_EVENT_CB) { - /*run2cb statistics*/ - vdec_profile_update_alloc_time(&time_stat->run2cb_time_stat, time_stat->run_lasttimestamp, timestamp); - - /*decode statistics*/ - if (time_stat->cb_cnt == 0) - vdec_profile_update_alloc_time(&time_stat->decode_time_stat, time_stat->decode_first_us, timestamp); - else - vdec_profile_update_alloc_time(&time_stat->decode_time_stat, time_stat->cb_lasttimestamp, timestamp); - - time_stat->cb_lasttimestamp = timestamp; - time_stat->cb_cnt++; - } - - mutex_unlock(&vdec_profile_mutex); -} - - -void vdec_profile_more(struct vdec_s *vdec, int event, int para1, int para2) -{ - mutex_lock(&vdec_profile_mutex); - - recs[rec_wp].vdec = vdec; - recs[rec_wp].timestamp = get_us_time_system(); - recs[rec_wp].event = event; - recs[rec_wp].para1 = para1; - recs[rec_wp].para2 = para2; - - rec_wp++; - if (rec_wp == PROFILE_REC_SIZE) { - rec_wrapped = true; - rec_wp = 0; - } - - mutex_unlock(&vdec_profile_mutex); -} -EXPORT_SYMBOL(vdec_profile_more); - -void vdec_profile(struct vdec_s *vdec, int event) -{ - ATRACE_COUNTER(vdec_device_name_str(vdec), event); - vdec_profile_more(vdec, event, 0 , 0); - if (dec_time_stat_flag == 1) - vdec_profile_statistics(vdec, event); -} -EXPORT_SYMBOL(vdec_profile); - -void vdec_profile_flush(struct vdec_s *vdec) -{ - int i; - - if (vdec->id >= MAX_INSTANCE_MUN) - return; - - mutex_lock(&vdec_profile_mutex); - - for (i = 0; i < PROFILE_REC_SIZE; i++) { - if (recs[i].vdec == vdec) - recs[i].vdec = NULL; - } - - memset(&statistics_s[vdec->id], 0, sizeof(struct vdec_profile_statistics_s)); - - mutex_unlock(&vdec_profile_mutex); -} - -static const char *event_str(int event) -{ - if (event < VDEC_PROFILE_MAX_EVENT) - return event_name[event]; - - return "INVALID"; -} - -static int vdec_profile_dbg_show(struct seq_file *m, void *v) -{ - int i, end; - u64 base_timestamp; - - mutex_lock(&vdec_profile_mutex); - - if (rec_wrapped) { - i = rec_wp; - end = rec_wp; - } else { - i = 0; - end = rec_wp; - } - - base_timestamp = recs[i].timestamp; - while (1) { - if ((!rec_wrapped) && (i == end)) - break; - - if (recs[i].vdec) { - seq_printf(m, "[%s:%d] \t%016llu us : %s (%d,%d)\n", - vdec_device_name_str(recs[i].vdec), - recs[i].vdec->id, - recs[i].timestamp - base_timestamp, - event_str(recs[i].event), - recs[i].para1, - recs[i].para2 - ); - } else { - seq_printf(m, "[%s:%d] \t%016llu us : %s (%d,%d)\n", - "N/A", - 0, - recs[i].timestamp - base_timestamp, - event_str(recs[i].event), - recs[i].para1, - recs[i].para2 - ); - } - if (++i == PROFILE_REC_SIZE) - i = 0; - - if (rec_wrapped && (i == end)) - break; - } - - mutex_unlock(&vdec_profile_mutex); - - return 0; -} - -static int time_stat_profile_dbg_show(struct seq_file *m, void *v) -{ - int i; - - mutex_lock(&vdec_profile_mutex); - - for (i = 0; i < MAX_INSTANCE_MUN; i++) - { - if (statistics_s[i].status == false) - continue; - - seq_printf(m, "[%d]run_cnt:%d, cb_cnt:%d\n\ - \t\t\ttime_total_us:%llu\n\ - \t\t\trun2cb time:\n\ - \t\t\ttime_max_us:%llu\n\ - \t\t\t[%d]run2cb ave_us:%llu\n\ - \t\t\ttime_6ms_less_cnt:%d\n\ - \t\t\ttime_6_9ms_cnt:%d\n\ - \t\t\ttime_9_12ms_cnt:%d\n\ - \t\t\ttime_12_15ms_cnt:%d\n\ - \t\t\ttime_15_18ms_cnt:%d\n\ - \t\t\ttime_18_21ms_cnt:%d\n\ - \t\t\ttime_21ms_up_cnt:%d\n\ - \t\t\tdecode time:\n\ - \t\t\ttime_total_us:%llu\n\ - \t\t\ttime_max_us:%llu\n\ - \t\t\t[%d]cb2cb ave_us:%llu\n\ - \t\t\ttime_6ms_less_cnt:%d\n\ - \t\t\ttime_6_9ms_cnt:%d\n\ - \t\t\ttime_9_12ms_cnt:%d\n\ - \t\t\ttime_12_15ms_cnt:%d\n\ - \t\t\ttime_15_18ms_cnt:%d\n\ - \t\t\ttime_18_21ms_cnt:%d\n\ - \t\t\ttime_21ms_up_cnt:%d\n", - i, - statistics_s[i].run_cnt, - statistics_s[i].cb_cnt, - statistics_s[i].run2cb_time_stat.time_total_us, - statistics_s[i].run2cb_time_stat.time_max_us, - i, - div_u64(statistics_s[i].run2cb_time_stat.time_total_us , statistics_s[i].cb_cnt), - statistics_s[i].run2cb_time_stat.time_6ms_less_cnt, - statistics_s[i].run2cb_time_stat.time_6_9ms_cnt, - statistics_s[i].run2cb_time_stat.time_9_12ms_cnt, - statistics_s[i].run2cb_time_stat.time_12_15ms_cnt, - statistics_s[i].run2cb_time_stat.time_15_18ms_cnt, - statistics_s[i].run2cb_time_stat.time_18_21ms_cnt, - statistics_s[i].run2cb_time_stat.time_21ms_up_cnt, - statistics_s[i].decode_time_stat.time_total_us, - statistics_s[i].decode_time_stat.time_max_us, - i, - div_u64(statistics_s[i].decode_time_stat.time_total_us , statistics_s[i].cb_cnt), - statistics_s[i].decode_time_stat.time_6ms_less_cnt, - statistics_s[i].decode_time_stat.time_6_9ms_cnt, - statistics_s[i].decode_time_stat.time_9_12ms_cnt, - statistics_s[i].decode_time_stat.time_12_15ms_cnt, - statistics_s[i].decode_time_stat.time_15_18ms_cnt, - statistics_s[i].decode_time_stat.time_18_21ms_cnt, - statistics_s[i].decode_time_stat.time_21ms_up_cnt); - } - - mutex_unlock(&vdec_profile_mutex); - - return 0; -} - - -static int vdec_profile_dbg_open(struct inode *inode, struct file *file) -{ - return single_open(file, vdec_profile_dbg_show, NULL); -} - -static int time_stat_profile_dbg_open(struct inode *inode, struct file *file) -{ - return single_open(file, time_stat_profile_dbg_show, NULL); -} - - -static const struct file_operations event_dbg_fops = { - .open = vdec_profile_dbg_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations time_stat_dbg_fops = { - .open = time_stat_profile_dbg_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - - -#if 0 /*DEBUG_TMP*/ -static int __init vdec_profile_init_debugfs(void) -{ - struct dentry *root, *event; - - root = debugfs_create_dir("vdec_profile", NULL); - if (IS_ERR(root) || !root) - goto err; - - event = debugfs_create_file("event", 0400, root, NULL, - &event_dbg_fops); - if (!event) - goto err_1; - - mutex_init(&vdec_profile_mutex); - - return 0; - -err_1: - debugfs_remove(root); -err: - pr_err("Can not create debugfs for vdec_profile\n"); - return 0; -} - -#endif - -int vdec_profile_init_debugfs(void) -{ - struct dentry *root, *event, *time_stat; - - root = debugfs_create_dir("vdec_profile", NULL); - if (IS_ERR(root) || !root) - goto err; - - event = debugfs_create_file("event", 0400, root, NULL, - &event_dbg_fops); - if (!event) - goto err_1; - - time_stat = debugfs_create_file("time_stat", 0400, root, NULL, - &time_stat_dbg_fops); - if (!time_stat) - goto err_2; - - mutex_init(&vdec_profile_mutex); - - return 0; - -err_2: - debugfs_remove(event); -err_1: - debugfs_remove(root); -err: - pr_err("Can not create debugfs for vdec_profile\n"); - return 0; -} -EXPORT_SYMBOL(vdec_profile_init_debugfs); - -void vdec_profile_exit_debugfs(void) -{ - debugfs_remove(event); - debugfs_remove(root); -} -EXPORT_SYMBOL(vdec_profile_exit_debugfs); - -module_param(dec_time_stat_flag, uint, 0664); - -module_param(dec_time_stat_reset, uint, 0664); - - -/*module_init(vdec_profile_init_debugfs);*/ - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.h deleted file mode 100644 index 34f3beed3231..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * drivers/amlogic/amports/vdec_profile.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#ifndef VDEC_PROFILE_H -#define VDEC_PROFILE_H - -struct vdec_s; - -#define VDEC_PROFILE_EVENT_RUN 0 -#define VDEC_PROFILE_EVENT_CB 1 -#define VDEC_PROFILE_EVENT_SAVE_INPUT 2 -#define VDEC_PROFILE_EVENT_CHK_RUN_READY 3 -#define VDEC_PROFILE_EVENT_RUN_READY 4 -#define VDEC_PROFILE_EVENT_DISCONNECT 5 -#define VDEC_PROFILE_EVENT_DEC_WORK 6 -#define VDEC_PROFILE_EVENT_INFO 7 -#define VDEC_PROFILE_MAX_EVENT 8 - -extern void vdec_profile(struct vdec_s *vdec, int event); -extern void vdec_profile_more(struct vdec_s *vdec, int event, int para1, int para2); -extern void vdec_profile_flush(struct vdec_s *vdec); - -int vdec_profile_init_debugfs(void); -void vdec_profile_exit_debugfs(void); - -#endif /* VDEC_PROFILE_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_trace.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_trace.h deleted file mode 100644 index e09518ef7d90..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_trace.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * drivers/amlogic/amports/vdec_trace.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM vdec - -#if !defined(_VDEC_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define _VDEC_TRACE_H - -#include - -struct vdec_s; - -/* single lifecycle events */ -DECLARE_EVENT_CLASS(vdec_event_class, - TP_PROTO(struct vdec_s *vdec), - TP_ARGS(vdec), - TP_STRUCT__entry( - __field(struct vdec_s *, vdec) - ), - TP_fast_assign( - __entry->vdec = vdec; - ), - TP_printk("[%p]", __entry->vdec) -); - -#define DEFINE_VDEC_EVENT(name) \ -DEFINE_EVENT(vdec_event_class, name, \ - TP_PROTO(struct vdec_s *vdec), \ - TP_ARGS(vdec)) - -DEFINE_VDEC_EVENT(vdec_create); -DEFINE_VDEC_EVENT(vdec_connect); -DEFINE_VDEC_EVENT(vdec_disconnect); -DEFINE_VDEC_EVENT(vdec_destroy); -DEFINE_VDEC_EVENT(vdec_reset); -DEFINE_VDEC_EVENT(vdec_release); - -/* set format event */ -#define format_name(format) \ - __print_symbolic(format, \ - {0, "MPEG"}, \ - {1, "MPEG4"}, \ - {2, "H264"}, \ - {3, "MJPEG"}, \ - {4, "REAL"}, \ - {5, "JPEG"}, \ - {6, "VC1"}, \ - {7, "AVS"}, \ - {8, "YUV"}, \ - {9, "H264MVC"}, \ - {10, "H264_4K2K"}, \ - {11, "H265"}, \ - {12, "ENC_AVC"}, \ - {13, "ENC_JPEG"}, \ - {14, "VP9"}) - -TRACE_EVENT(vdec_set_format, - TP_PROTO(struct vdec_s *vdec, int format), - TP_ARGS(vdec, format), - TP_STRUCT__entry( - __field(struct vdec_s *, vdec) - __field(int, format) - ), - TP_fast_assign( - __entry->vdec = vdec; - __entry->format = format; - ), - TP_printk("[%p]:%s", __entry->vdec, - format_name(__entry->format)) -); - -/* status events */ -#define status_name(status) \ - __print_symbolic(status, \ - {0, "UNINITIALIZED"}, \ - {1, "DISCONNECTED"}, \ - {2, "CONNECTED"}, \ - {3, "ACTIVE"}) - -DECLARE_EVENT_CLASS(vdec_status_class, - TP_PROTO(struct vdec_s *vdec, int state), - TP_ARGS(vdec, state), - TP_STRUCT__entry( - __field(struct vdec_s *, vdec) - __field(int, state) - ), - TP_fast_assign( - __entry->vdec = vdec; - __entry->state = state; - ), - TP_printk("[%p]:%s", __entry->vdec, status_name(__entry->state)) -); - -#define DEFINE_STATUS_EVENT(name) \ -DEFINE_EVENT(vdec_status_class, name, \ - TP_PROTO(struct vdec_s *vdec, int status), \ - TP_ARGS(vdec, status)) - -DEFINE_STATUS_EVENT(vdec_set_status); -DEFINE_STATUS_EVENT(vdec_set_next_status); - -/* set pts events */ -DECLARE_EVENT_CLASS(vdec_pts_class, - TP_PROTO(struct vdec_s *vdec, u64 pts), - TP_ARGS(vdec, pts), - TP_STRUCT__entry( - __field(struct vdec_s *, vdec) - __field(u64, pts) - ), - TP_fast_assign( - __entry->vdec = vdec; - __entry->pts = pts; - ), - TP_printk("[%p]%llu", __entry->vdec, __entry->pts) -); - -#define DEFINE_PTS_EVENT(name) \ -DEFINE_EVENT(vdec_pts_class, name, \ - TP_PROTO(struct vdec_s *vdec, u64 pts), \ - TP_ARGS(vdec, pts)) - -DEFINE_PTS_EVENT(vdec_set_pts); -DEFINE_PTS_EVENT(vdec_set_pts64); - -#endif /* _VDEC_TRACE_H */ - -/* -#undef TRACE_INCLUDE_PATH -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE vdec_trace -#include -*/ -/**/ //DEBUG_TMP diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/Makefile deleted file mode 100644 index b43a6002e1b2..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_VC1) += amvdec_vc1.o -amvdec_vc1-objs += vvc1.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c deleted file mode 100644 index d9cb53c0839a..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * drivers/amlogic/amports/vvc1.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../utils/amvdec.h" -#include "../utils/vdec.h" -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" -#include -#include -#include "../utils/firmware.h" -#include -#include -#include - - -#define DRIVER_NAME "amvdec_vc1" -#define MODULE_NAME "amvdec_vc1" - -#define DEBUG_PTS -#if 1 /* //MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NV21 -#endif - -#define VC1_MAX_SUPPORT_SIZE (1920*1088) - -#define I_PICTURE 0 -#define P_PICTURE 1 -#define B_PICTURE 2 - -#define ORI_BUFFER_START_ADDR 0x01000000 - -#define INTERLACE_FLAG 0x80 -#define BOTTOM_FIELD_FIRST_FLAG 0x40 - -/* protocol registers */ -#define VC1_PIC_RATIO AV_SCRATCH_0 -#define VC1_ERROR_COUNT AV_SCRATCH_6 -#define VC1_SOS_COUNT AV_SCRATCH_7 -#define VC1_BUFFERIN AV_SCRATCH_8 -#define VC1_BUFFEROUT AV_SCRATCH_9 -#define VC1_REPEAT_COUNT AV_SCRATCH_A -#define VC1_TIME_STAMP AV_SCRATCH_B -#define VC1_OFFSET_REG AV_SCRATCH_C -#define MEM_OFFSET_REG AV_SCRATCH_F - -#define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 4 -#define WORKSPACE_SIZE (2 * SZ_1M) -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) -#define VF_BUFFER_IDX(n) (1 + n) -#define DCAC_BUFF_START_ADDR 0x01f00000 - - -#define PUT_INTERVAL (HZ/100) - -#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -/* TODO: move to register headers */ -#define VPP_VD1_POSTBLEND (1 << 10) -#define MEM_FIFO_CNT_BIT 16 -#define MEM_LEVEL_CNT_BIT 18 -#endif -static struct vdec_info *gvs; - -static struct vframe_s *vvc1_vf_peek(void *); -static struct vframe_s *vvc1_vf_get(void *); -static void vvc1_vf_put(struct vframe_s *, void *); -static int vvc1_vf_states(struct vframe_states *states, void *); -static int vvc1_event_cb(int type, void *data, void *private_data); - -static int vvc1_prot_init(void); -static void vvc1_local_init(void); - -static const char vvc1_dec_id[] = "vvc1-dev"; - -#define PROVIDER_NAME "decoder.vc1" -static const struct vframe_operations_s vvc1_vf_provider = { - .peek = vvc1_vf_peek, - .get = vvc1_vf_get, - .put = vvc1_vf_put, - .event_cb = vvc1_event_cb, - .vf_states = vvc1_vf_states, -}; -static void *mm_blk_handle; -static struct vframe_provider_s vvc1_vf_prov; - -static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); -static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); - -static struct vframe_s vfpool[VF_POOL_SIZE]; -static struct vframe_s vfpool2[VF_POOL_SIZE]; -static int cur_pool_idx; - -static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; -static struct timer_list recycle_timer; -static u32 stat; -static u32 buf_size = 32 * 1024 * 1024; -static u32 buf_offset; -static u32 avi_flag; -static u32 vvc1_ratio; -static u32 vvc1_format; - -static u32 intra_output; -static u32 frame_width, frame_height, frame_dur; -static u32 saved_resolution; -static u32 pts_by_offset = 1; -static u32 total_frame; -static u32 next_pts; -static u64 next_pts_us64; -static bool is_reset; -static struct work_struct set_clk_work; -static struct work_struct error_wd_work; - -#ifdef DEBUG_PTS -static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; -#endif -static DEFINE_SPINLOCK(lock); - -static struct dec_sysinfo vvc1_amstream_dec_info; - -struct frm_s { - int state; - u32 start_pts; - int num; - u32 end_pts; - u32 rate; - u32 trymax; -}; - -static struct frm_s frm; - -enum { - RATE_MEASURE_START_PTS = 0, - RATE_MEASURE_END_PTS, - RATE_MEASURE_DONE -}; -#define RATE_MEASURE_NUM 8 -#define RATE_CORRECTION_THRESHOLD 5 -#define RATE_24_FPS 3755 /* 23.97 */ -#define RATE_30_FPS 3003 /* 29.97 */ -#define DUR2PTS(x) ((x)*90/96) -#define PTS2DUR(x) ((x)*96/90) - -static inline int pool_index(struct vframe_s *vf) -{ - if ((vf >= &vfpool[0]) && (vf <= &vfpool[VF_POOL_SIZE - 1])) - return 0; - else if ((vf >= &vfpool2[0]) && (vf <= &vfpool2[VF_POOL_SIZE - 1])) - return 1; - else - return -1; -} - -static inline bool close_to(int a, int b, int m) -{ - return abs(a - b) < m; -} - -static inline u32 index2canvas(u32 index) -{ - const u32 canvas_tab[DECODE_BUFFER_NUM_MAX] = { -#if 1 /* ALWASY.MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - 0x010100, 0x030302, 0x050504, 0x070706/*, - 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e*/ -#else - 0x020100, 0x050403, 0x080706, 0x0b0a09 -#endif - }; - - return canvas_tab[index]; -} - -static void set_aspect_ratio(struct vframe_s *vf, unsigned int pixel_ratio) -{ - int ar = 0; - - if (vvc1_ratio == 0) { - /* always stretch to 16:9 */ - vf->ratio_control |= (0x90 << DISP_RATIO_ASPECT_RATIO_BIT); - } else if (pixel_ratio > 0x0f) { - ar = (vvc1_amstream_dec_info.height * (pixel_ratio & 0xff) * - vvc1_ratio) / (vvc1_amstream_dec_info.width * - (pixel_ratio >> 8)); - } else { - switch (pixel_ratio) { - case 0: - ar = (vvc1_amstream_dec_info.height * vvc1_ratio) / - vvc1_amstream_dec_info.width; - break; - case 1: - ar = (vf->height * vvc1_ratio) / vf->width; - break; - case 2: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 12); - break; - case 3: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 10); - break; - case 4: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 16); - break; - case 5: - ar = (vf->height * 33 * vvc1_ratio) / (vf->width * 40); - break; - case 6: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 24); - break; - case 7: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 20); - break; - case 8: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 32); - break; - case 9: - ar = (vf->height * 33 * vvc1_ratio) / (vf->width * 80); - break; - case 10: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 18); - break; - case 11: - ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 15); - break; - case 12: - ar = (vf->height * 33 * vvc1_ratio) / (vf->width * 64); - break; - case 13: - ar = (vf->height * 99 * vvc1_ratio) / - (vf->width * 160); - break; - default: - ar = (vf->height * vvc1_ratio) / vf->width; - break; - } - } - - ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); - - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - /*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO;*/ -} - -static irqreturn_t vvc1_isr(int irq, void *dev_id) -{ - u32 reg; - struct vframe_s *vf = NULL; - u32 repeat_count; - u32 picture_type; - u32 buffer_index; - unsigned int pts, pts_valid = 0, offset = 0; - u32 v_width, v_height; - u64 pts_us64 = 0; - u32 frame_size; - - reg = READ_VREG(VC1_BUFFEROUT); - - if (reg) { - v_width = READ_VREG(AV_SCRATCH_J); - v_height = READ_VREG(AV_SCRATCH_K); - - if (v_width && v_width <= 4096 - && (v_width != vvc1_amstream_dec_info.width)) { - pr_info("frame width changed %d to %d\n", - vvc1_amstream_dec_info.width, v_width); - vvc1_amstream_dec_info.width = v_width; - frame_width = v_width; - } - if (v_height && v_height <= 4096 - && (v_height != vvc1_amstream_dec_info.height)) { - pr_info("frame height changed %d to %d\n", - vvc1_amstream_dec_info.height, v_height); - vvc1_amstream_dec_info.height = v_height; - frame_height = v_height; - } - - if (pts_by_offset) { - offset = READ_VREG(VC1_OFFSET_REG); - if (pts_lookup_offset_us64( - PTS_TYPE_VIDEO, - offset, &pts, &frame_size, - 0, &pts_us64) == 0) { - pts_valid = 1; -#ifdef DEBUG_PTS - pts_hit++; -#endif - } else { -#ifdef DEBUG_PTS - pts_missed++; -#endif - } - } - - repeat_count = READ_VREG(VC1_REPEAT_COUNT); - buffer_index = ((reg & 0x7) - 1) & 3; - picture_type = (reg >> 3) & 7; - - if (buffer_index >= DECODE_BUFFER_NUM_MAX) { - pr_info("fatal error, invalid buffer index."); - return IRQ_HANDLED; - } - - if ((intra_output == 0) && (picture_type != 0)) { - WRITE_VREG(VC1_BUFFERIN, ~(1 << buffer_index)); - WRITE_VREG(VC1_BUFFEROUT, 0); - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - return IRQ_HANDLED; - } - - intra_output = 1; - -#ifdef DEBUG_PTS - if (picture_type == I_PICTURE) { - /* pr_info("I offset 0x%x, - *pts_valid %d\n", offset, pts_valid); - */ - if (!pts_valid) - pts_i_missed++; - else - pts_i_hit++; - } -#endif - - if ((pts_valid) && (frm.state != RATE_MEASURE_DONE)) { - if (frm.state == RATE_MEASURE_START_PTS) { - frm.start_pts = pts; - frm.state = RATE_MEASURE_END_PTS; - frm.trymax = RATE_MEASURE_NUM; - } else if (frm.state == RATE_MEASURE_END_PTS) { - if (frm.num >= frm.trymax) { - frm.end_pts = pts; - frm.rate = (frm.end_pts - - frm.start_pts) / frm.num; - pr_info("frate before=%d,%d,num=%d\n", - frm.rate, - DUR2PTS(vvc1_amstream_dec_info.rate), - frm.num); - /* check if measured rate is same as - * settings from upper layer - * and correct it if necessary - */ - if ((close_to(frm.rate, RATE_30_FPS, - RATE_CORRECTION_THRESHOLD) && - close_to( - DUR2PTS( - vvc1_amstream_dec_info.rate), - RATE_24_FPS, - RATE_CORRECTION_THRESHOLD)) - || - (close_to( - frm.rate, RATE_24_FPS, - RATE_CORRECTION_THRESHOLD) - && - close_to(DUR2PTS( - vvc1_amstream_dec_info.rate), - RATE_30_FPS, - RATE_CORRECTION_THRESHOLD))) { - pr_info( - "vvc1: frate from %d to %d\n", - vvc1_amstream_dec_info.rate, - PTS2DUR(frm.rate)); - - vvc1_amstream_dec_info.rate = - PTS2DUR(frm.rate); - frm.state = RATE_MEASURE_DONE; - } else if (close_to(frm.rate, - DUR2PTS( - vvc1_amstream_dec_info.rate), - RATE_CORRECTION_THRESHOLD)) - frm.state = RATE_MEASURE_DONE; - else { - -/* maybe still have problem, - * try next double frames.... - */ - frm.state = RATE_MEASURE_DONE; - frm.start_pts = pts; - frm.state = - RATE_MEASURE_END_PTS; - /*60 fps*60 S */ - frm.num = 0; - } - } - } - } - - if (frm.state != RATE_MEASURE_DONE) - frm.num += (repeat_count > 1) ? repeat_count : 1; - if (vvc1_amstream_dec_info.rate == 0) - vvc1_amstream_dec_info.rate = PTS2DUR(frm.rate); - - if (reg & INTERLACE_FLAG) { /* interlace */ - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = vvc1_amstream_dec_info.width; - vf->height = vvc1_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - - if (pts_valid) { - vf->pts = pts; - vf->pts_us64 = pts_us64; - if ((repeat_count > 1) && avi_flag) { - vf->duration = - vvc1_amstream_dec_info.rate * - repeat_count >> 1; - next_pts = pts + - (vvc1_amstream_dec_info.rate * - repeat_count >> 1) * 15 / 16; - next_pts_us64 = pts_us64 + - ((vvc1_amstream_dec_info.rate * - repeat_count >> 1) * 15 / 16) * - 100 / 9; - } else { - vf->duration = - vvc1_amstream_dec_info.rate >> 1; - next_pts = 0; - next_pts_us64 = 0; - } - } else { - vf->pts = next_pts; - vf->pts_us64 = next_pts_us64; - if ((repeat_count > 1) && avi_flag) { - vf->duration = - vvc1_amstream_dec_info.rate * - repeat_count >> 1; - if (next_pts != 0) { - next_pts += ((vf->duration) - - ((vf->duration) >> 4)); - } - if (next_pts_us64 != 0) { - next_pts_us64 += - ((vf->duration) - - ((vf->duration) >> 4)) * - 100 / 9; - } - } else { - vf->duration = - vvc1_amstream_dec_info.rate >> 1; - next_pts = 0; - next_pts_us64 = 0; - } - } - - vf->duration_pulldown = 0; - vf->type = (reg & BOTTOM_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->orientation = 0; - vf->type_original = vf->type; - set_aspect_ratio(vf, READ_VREG(VC1_PIC_RATIO)); - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver( - PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = vvc1_amstream_dec_info.width; - vf->height = vvc1_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - - vf->pts = next_pts; - vf->pts_us64 = next_pts_us64; - if ((repeat_count > 1) && avi_flag) { - vf->duration = - vvc1_amstream_dec_info.rate * - repeat_count >> 1; - if (next_pts != 0) { - next_pts += - ((vf->duration) - - ((vf->duration) >> 4)); - } - if (next_pts_us64 != 0) { - next_pts_us64 += ((vf->duration) - - ((vf->duration) >> 4)) * 100 / 9; - } - } else { - vf->duration = - vvc1_amstream_dec_info.rate >> 1; - next_pts = 0; - next_pts_us64 = 0; - } - - vf->duration_pulldown = 0; - vf->type = (reg & BOTTOM_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->orientation = 0; - vf->type_original = vf->type; - set_aspect_ratio(vf, READ_VREG(VC1_PIC_RATIO)); - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver( - PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } else { /* progressive */ - if (kfifo_get(&newframe_q, &vf) == 0) { - pr_info - ("fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - vf->signal_type = 0; - vf->index = buffer_index; - vf->width = vvc1_amstream_dec_info.width; - vf->height = vvc1_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - - if (pts_valid) { - vf->pts = pts; - vf->pts_us64 = pts_us64; - if ((repeat_count > 1) && avi_flag) { - vf->duration = - vvc1_amstream_dec_info.rate * - repeat_count; - next_pts = - pts + - (vvc1_amstream_dec_info.rate * - repeat_count) * 15 / 16; - next_pts_us64 = pts_us64 + - ((vvc1_amstream_dec_info.rate * - repeat_count) * 15 / 16) * - 100 / 9; - } else { - vf->duration = - vvc1_amstream_dec_info.rate; - next_pts = 0; - next_pts_us64 = 0; - } - } else { - vf->pts = next_pts; - vf->pts_us64 = next_pts_us64; - if ((repeat_count > 1) && avi_flag) { - vf->duration = - vvc1_amstream_dec_info.rate * - repeat_count; - if (next_pts != 0) { - next_pts += ((vf->duration) - - ((vf->duration) >> 4)); - } - if (next_pts_us64 != 0) { - next_pts_us64 += - ((vf->duration) - - ((vf->duration) >> 4)) * - 100 / 9; - } - } else { - vf->duration = - vvc1_amstream_dec_info.rate; - next_pts = 0; - next_pts_us64 = 0; - } - } - - vf->duration_pulldown = 0; -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - vf->canvas0Addr = vf->canvas1Addr = - index2canvas(buffer_index); - vf->orientation = 0; - vf->type_original = vf->type; - set_aspect_ratio(vf, READ_VREG(VC1_PIC_RATIO)); - - vfbuf_use[buffer_index]++; - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - mm_blk_handle, - buffer_index); - kfifo_put(&display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - frame_dur = vvc1_amstream_dec_info.rate; - total_frame++; - - /*count info*/ - gvs->frame_dur = frame_dur; - vdec_count_info(gvs, 0, offset); - - /* pr_info("PicType = %d, PTS = 0x%x, repeat - *count %d\n", picture_type, vf->pts, repeat_count); - */ - WRITE_VREG(VC1_BUFFEROUT, 0); - } - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - return IRQ_HANDLED; -} - -static struct vframe_s *vvc1_vf_peek(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_peek(&display_q, &vf)) - return vf; - - return NULL; -} - -static struct vframe_s *vvc1_vf_get(void *op_arg) -{ - struct vframe_s *vf; - - if (kfifo_get(&display_q, &vf)) - return vf; - - return NULL; -} - -static void vvc1_vf_put(struct vframe_s *vf, void *op_arg) -{ - if (pool_index(vf) == cur_pool_idx) - kfifo_put(&recycle_q, (const struct vframe_s *)vf); -} - -static int vvc1_vf_states(struct vframe_states *states, void *op_arg) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&newframe_q); - states->buf_avail_num = kfifo_len(&display_q); - states->buf_recycle_num = kfifo_len(&recycle_q); - - spin_unlock_irqrestore(&lock, flags); - - return 0; -} - -static int vvc1_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { - unsigned long flags; - - amvdec_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vvc1_vf_prov); -#endif - spin_lock_irqsave(&lock, flags); - vvc1_local_init(); - vvc1_prot_init(); - spin_unlock_irqrestore(&lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vvc1_vf_prov); -#endif - amvdec_start(); - } - return 0; -} - -int vvc1_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - if (!(stat & STAT_VDEC_RUN)) - return -1; - - vstatus->frame_width = vvc1_amstream_dec_info.width; - vstatus->frame_height = vvc1_amstream_dec_info.height; - if (vvc1_amstream_dec_info.rate != 0) - vstatus->frame_rate = 96000 / vvc1_amstream_dec_info.rate; - else - vstatus->frame_rate = -1; - vstatus->error_count = READ_VREG(AV_SCRATCH_C); - vstatus->status = stat; - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_dur = vvc1_amstream_dec_info.rate; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); - - return 0; -} - -int vvc1_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -static int vvc1_vdec_info_init(void) -{ - gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); - if (NULL == gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -ENOMEM; - } - return 0; -} - -/****************************************/ -static int vvc1_canvas_init(void) -{ - int i, ret; - u32 canvas_width, canvas_height; - u32 alloc_size, decbuf_size, decbuf_y_size, decbuf_uv_size; - unsigned long buf_start; - - if (buf_size <= 0x00400000) { - /* SD only */ - canvas_width = 768; - canvas_height = 576; - decbuf_y_size = 0x80000; - decbuf_uv_size = 0x20000; - decbuf_size = 0x100000; - } else { - /* HD & SD */ - canvas_width = 1920; - canvas_height = 1088; - decbuf_y_size = 0x200000; - decbuf_uv_size = 0x80000; - decbuf_size = 0x300000; - } - - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - /* workspace mem */ - if (i == (MAX_BMMU_BUFFER_NUM - 1)) - alloc_size = WORKSPACE_SIZE; - else - alloc_size = decbuf_size; - - ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, - alloc_size, DRIVER_NAME, &buf_start); - if (ret < 0) - return ret; - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { - buf_offset = buf_start - DCAC_BUFF_START_ADDR; - continue; - } - -#ifdef NV21 - canvas_config(2 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(2 * i + 1, - buf_start + - decbuf_y_size, canvas_width, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); -#else - canvas_config(3 * i + 0, - buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 1, - buf_start + - decbuf_y_size, canvas_width / 2, - canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(3 * i + 2, - buf_start + - decbuf_y_size + decbuf_uv_size, - canvas_width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); -#endif - - } - return 0; -} - -static int vvc1_prot_init(void) -{ - int r; -#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - READ_VREG(DOS_SW_RESET0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); - - WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); - WRITE_VREG(DOS_SW_RESET0, 0); - -#else - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - READ_RESET_REG(RESET0_REGISTER); - WRITE_RESET_REG(RESET0_REGISTER, - RESET_IQIDCT | RESET_MC | RESET_VLD_PART); - - WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); -#endif - - WRITE_VREG(POWER_CTL_VLD, 0x10); - WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2); - WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, MEM_LEVEL_CNT_BIT, 6); - - r = vvc1_canvas_init(); - - /* index v << 16 | u << 8 | y */ -#ifdef NV21 - WRITE_VREG(AV_SCRATCH_0, 0x010100); - WRITE_VREG(AV_SCRATCH_1, 0x030302); - WRITE_VREG(AV_SCRATCH_2, 0x050504); - WRITE_VREG(AV_SCRATCH_3, 0x070706); -/* WRITE_VREG(AV_SCRATCH_G, 0x090908); - WRITE_VREG(AV_SCRATCH_H, 0x0b0b0a); - WRITE_VREG(AV_SCRATCH_I, 0x0d0d0c); - WRITE_VREG(AV_SCRATCH_J, 0x0f0f0e);*/ -#else - WRITE_VREG(AV_SCRATCH_0, 0x020100); - WRITE_VREG(AV_SCRATCH_1, 0x050403); - WRITE_VREG(AV_SCRATCH_2, 0x080706); - WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); - WRITE_VREG(AV_SCRATCH_G, 0x090908); - WRITE_VREG(AV_SCRATCH_H, 0x0b0b0a); - WRITE_VREG(AV_SCRATCH_I, 0x0d0d0c); - WRITE_VREG(AV_SCRATCH_J, 0x0f0f0e); -#endif - - /* notify ucode the buffer offset */ - WRITE_VREG(AV_SCRATCH_F, buf_offset); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(PSCALE_CTRL, 0); - - WRITE_VREG(VC1_SOS_COUNT, 0); - WRITE_VREG(VC1_BUFFERIN, 0); - WRITE_VREG(VC1_BUFFEROUT, 0); - - /* clear mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(ASSIST_MBOX1_MASK, 1); - -#ifdef NV21 - SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); -#endif - return r; -} - -static void vvc1_local_init(void) -{ - int i; - - /* vvc1_ratio = vvc1_amstream_dec_info.ratio; */ - vvc1_ratio = 0x100; - - avi_flag = (unsigned long) vvc1_amstream_dec_info.param; - - total_frame = 0; - - next_pts = 0; - - next_pts_us64 = 0; - saved_resolution = 0; - frame_width = frame_height = frame_dur = 0; -#ifdef DEBUG_PTS - pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0; -#endif - - memset(&frm, 0, sizeof(frm)); - - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) - vfbuf_use[i] = 0; - - INIT_KFIFO(display_q); - INIT_KFIFO(recycle_q); - INIT_KFIFO(newframe_q); - cur_pool_idx ^= 1; - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf; - - if (cur_pool_idx == 0) { - vf = &vfpool[i]; - vfpool[i].index = DECODE_BUFFER_NUM_MAX; - } else { - vf = &vfpool2[i]; - vfpool2[i].index = DECODE_BUFFER_NUM_MAX; - } - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - - mm_blk_handle = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - 0, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER); -} - -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER -static void vvc1_ppmgr_reset(void) -{ - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); - - vvc1_local_init(); - - /* vf_notify_receiver(PROVIDER_NAME, - * VFRAME_EVENT_PROVIDER_START,NULL); - */ - - pr_info("vvc1dec: vf_ppmgr_reset\n"); -} -#endif - -static void vvc1_set_clk(struct work_struct *work) -{ - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_VC1, - frame_width, frame_height, fps); - -} - -static void error_do_work(struct work_struct *work) -{ - amvdec_stop(); - msleep(20); -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vvc1_ppmgr_reset(); -#else - vf_light_unreg_provider(&vvc1_vf_prov); - vvc1_local_init(); - vf_reg_provider(&vvc1_vf_prov); -#endif - vvc1_prot_init(); - amvdec_start(); -} - - -static void vvc1_put_timer_func(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - - if (READ_VREG(VC1_SOS_COUNT) > 10) - schedule_work(&error_wd_work); - - while (!kfifo_is_empty(&recycle_q) && (READ_VREG(VC1_BUFFERIN) == 0)) { - struct vframe_s *vf; - - if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index < DECODE_BUFFER_NUM_MAX) && - (--vfbuf_use[vf->index] == 0)) { - WRITE_VREG(VC1_BUFFERIN, ~(1 << vf->index)); - vf->index = DECODE_BUFFER_NUM_MAX; - } - if (pool_index(vf) == cur_pool_idx) - kfifo_put(&newframe_q, (const struct vframe_s *)vf); - } - } - - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) - schedule_work(&set_clk_work); - timer->expires = jiffies + PUT_INTERVAL; - - add_timer(timer); -} - -static s32 vvc1_init(void) -{ - int ret = -1; - char *buf = vmalloc(0x1000 * 16); - int fw_type = VIDEO_DEC_VC1; - - if (IS_ERR_OR_NULL(buf)) - return -ENOMEM; - - pr_info("vvc1_init, format %d\n", vvc1_amstream_dec_info.format); - init_timer(&recycle_timer); - - stat |= STAT_TIMER_INIT; - - intra_output = 0; - amvdec_enable(); - - vvc1_local_init(); - - if (vvc1_amstream_dec_info.format == VIDEO_DEC_FORMAT_WMV3) { - pr_info("WMV3 dec format\n"); - vvc1_format = VIDEO_DEC_FORMAT_WMV3; - WRITE_VREG(AV_SCRATCH_4, 0); - } else if (vvc1_amstream_dec_info.format == VIDEO_DEC_FORMAT_WVC1) { - pr_info("WVC1 dec format\n"); - vvc1_format = VIDEO_DEC_FORMAT_WVC1; - WRITE_VREG(AV_SCRATCH_4, 1); - } else - pr_info("not supported VC1 format\n"); - - if (get_firmware_data(fw_type, buf) < 0) { - amvdec_disable(); - pr_err("get firmware fail."); - vfree(buf); - return -1; - } - - ret = amvdec_loadmc_ex(VFORMAT_VC1, NULL, buf); - if (ret < 0) { - amvdec_disable(); - vfree(buf); - pr_err("VC1: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(buf); - - stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - ret = vvc1_prot_init(); - if (ret < 0) - return ret; - - if (vdec_request_irq(VDEC_IRQ_1, vvc1_isr, - "vvc1-irq", (void *)vvc1_dec_id)) { - amvdec_disable(); - - pr_info("vvc1 irq register error.\n"); - return -ENOENT; - } - - stat |= STAT_ISR_REG; -#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_provider_init(&vvc1_vf_prov, - PROVIDER_NAME, &vvc1_vf_provider, NULL); - vf_reg_provider(&vvc1_vf_prov); - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_START, NULL); -#else - vf_provider_init(&vvc1_vf_prov, - PROVIDER_NAME, &vvc1_vf_provider, NULL); - vf_reg_provider(&vvc1_vf_prov); -#endif - - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)vvc1_amstream_dec_info.rate)); - - stat |= STAT_VF_HOOK; - - recycle_timer.data = (ulong)&recycle_timer; - recycle_timer.function = vvc1_put_timer_func; - recycle_timer.expires = jiffies + PUT_INTERVAL; - - add_timer(&recycle_timer); - - stat |= STAT_TIMER_ARM; - - amvdec_start(); - - stat |= STAT_VDEC_RUN; - - return 0; -} - -static int amvdec_vc1_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - - if (pdata == NULL) { - pr_info("amvdec_vc1 memory resource undefined.\n"); - return -EFAULT; - } - - if (pdata->sys_info) { - vvc1_amstream_dec_info = *pdata->sys_info; - - if ((vvc1_amstream_dec_info.height != 0) && - (vvc1_amstream_dec_info.width > - (VC1_MAX_SUPPORT_SIZE/vvc1_amstream_dec_info.height))) { - pr_info("amvdec_vc1: over size, unsupport: %d * %d\n", - vvc1_amstream_dec_info.width, - vvc1_amstream_dec_info.height); - return -EFAULT; - } - } - pdata->dec_status = vvc1_dec_status; - pdata->set_isreset = vvc1_set_isreset; - is_reset = 0; - - vvc1_vdec_info_init(); - - INIT_WORK(&error_wd_work, error_do_work); - INIT_WORK(&set_clk_work, vvc1_set_clk); - if (vvc1_init() < 0) { - pr_info("amvdec_vc1 init failed.\n"); - kfree(gvs); - gvs = NULL; - pdata->dec_status = NULL; - return -ENODEV; - } - - return 0; -} - -static int amvdec_vc1_remove(struct platform_device *pdev) -{ - cancel_work_sync(&error_wd_work); - if (stat & STAT_VDEC_RUN) { - amvdec_stop(); - stat &= ~STAT_VDEC_RUN; - } - - if (stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_1, (void *)vvc1_dec_id); - stat &= ~STAT_ISR_REG; - } - - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } - - cancel_work_sync(&set_clk_work); - if (stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - - vf_unreg_provider(&vvc1_vf_prov); - stat &= ~STAT_VF_HOOK; - } - - amvdec_disable(); - - if (mm_blk_handle) { - decoder_bmmu_box_free(mm_blk_handle); - mm_blk_handle = NULL; - } - -#ifdef DEBUG_PTS - pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit, - pts_missed, pts_i_hit, pts_i_missed); - pr_debug("total frame %d, avi_flag %d, rate %d\n", - total_frame, avi_flag, - vvc1_amstream_dec_info.rate); -#endif - kfree(gvs); - gvs = NULL; - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_vc1_driver = { - .probe = amvdec_vc1_probe, - .remove = amvdec_vc1_remove, -#ifdef CONFIG_PM - .suspend = amvdec_suspend, - .resume = amvdec_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -#if defined(CONFIG_ARCH_MESON) /*meson1 only support progressive */ -static struct codec_profile_t amvdec_vc1_profile = { - .name = "vc1", - .profile = "progressive, wmv3" -}; -#else -static struct codec_profile_t amvdec_vc1_profile = { - .name = "vc1", - .profile = "progressive, interlace, wmv3" -}; -#endif - -static int __init amvdec_vc1_driver_init_module(void) -{ - pr_debug("amvdec_vc1 module init\n"); - - if (platform_driver_register(&amvdec_vc1_driver)) { - pr_err("failed to register amvdec_vc1 driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvdec_vc1_profile); - return 0; -} - -static void __exit amvdec_vc1_driver_remove_module(void) -{ - pr_debug("amvdec_vc1 module remove.\n"); - - platform_driver_unregister(&amvdec_vc1_driver); -} - -/****************************************/ -module_init(amvdec_vc1_driver_init_module); -module_exit(amvdec_vc1_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC VC1 Video Decoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Qi Wang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/Makefile deleted file mode 100644 index 51edefe1e67d..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_VP9) += amvdec_vp9.o -amvdec_vp9-objs += vvp9.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c deleted file mode 100644 index 42ecd4613b83..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c +++ /dev/null @@ -1,9855 +0,0 @@ - /* - * drivers/amlogic/amports/vvp9.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../../stream_input/amports/amports_priv.h" -#include -#include "../utils/decoder_mmu_box.h" -#include "../utils/decoder_bmmu_box.h" - -#define MEM_NAME "codec_vp9" -/* #include */ -#include -#include "../utils/vdec.h" -#include "../utils/amvdec.h" - -#include -#include -#include "../utils/config_parser.h" -#include "../utils/firmware.h" -#include "../../../common/chips/decoder_cpu_ver_info.h" - -#include - - -#define MIX_STREAM_SUPPORT - -#include "vvp9.h" - - -/*#define SUPPORT_FB_DECODING*/ -/*#define FB_DECODING_TEST_SCHEDULE*/ - - -#define HW_MASK_FRONT 0x1 -#define HW_MASK_BACK 0x2 - -#define VP9D_MPP_REFINFO_TBL_ACCCONFIG 0x3442 -#define VP9D_MPP_REFINFO_DATA 0x3443 -#define VP9D_MPP_REF_SCALE_ENBL 0x3441 -#define HEVC_MPRED_CTRL4 0x324c -#define HEVC_CM_HEADER_START_ADDR 0x3628 -#define HEVC_DBLK_CFGB 0x350b -#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 -#define HEVC_SAO_MMU_VH1_ADDR 0x363b -#define HEVC_SAO_MMU_VH0_ADDR 0x363a -#define HEVC_SAO_MMU_STATUS 0x3639 - -#define VP9_10B_DEC_IDLE 0 -#define VP9_10B_DEC_FRAME_HEADER 1 -#define VP9_10B_DEC_SLICE_SEGMENT 2 -#define VP9_10B_DECODE_SLICE 5 -#define VP9_10B_DISCARD_NAL 6 -#define VP9_DUMP_LMEM 7 -#define HEVC_DECPIC_DATA_DONE 0xa -#define HEVC_DECPIC_DATA_ERROR 0xb -#define HEVC_NAL_DECODE_DONE 0xe -#define HEVC_DECODE_BUFEMPTY 0x20 -#define HEVC_DECODE_TIMEOUT 0x21 -#define HEVC_SEARCH_BUFEMPTY 0x22 -#define HEVC_DECODE_OVER_SIZE 0x23 -#define HEVC_S2_DECODING_DONE 0x50 -#define VP9_HEAD_PARSER_DONE 0xf0 -#define VP9_HEAD_SEARCH_DONE 0xf1 -#define VP9_EOS 0xf2 -#define HEVC_ACTION_DONE 0xff - -#define VF_POOL_SIZE 32 - -#undef pr_info -#define pr_info printk - -#define DECODE_MODE_SINGLE ((0x80 << 24) | 0) -#define DECODE_MODE_MULTI_STREAMBASE ((0x80 << 24) | 1) -#define DECODE_MODE_MULTI_FRAMEBASE ((0x80 << 24) | 2) - - -#define VP9_TRIGGER_FRAME_DONE 0x100 -#define VP9_TRIGGER_FRAME_ENABLE 0x200 - -#define MV_MEM_UNIT 0x240 -/*--------------------------------------------------- - * Include "parser_cmd.h" - *--------------------------------------------------- - */ -#define PARSER_CMD_SKIP_CFG_0 0x0000090b - -#define PARSER_CMD_SKIP_CFG_1 0x1b14140f - -#define PARSER_CMD_SKIP_CFG_2 0x001b1910 - -#define PARSER_CMD_NUMBER 37 - -/*#define HEVC_PIC_STRUCT_SUPPORT*/ -/* to remove, fix build error */ - -/*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/ - -#define MULTI_INSTANCE_SUPPORT -#define SUPPORT_10BIT -/* #define ERROR_HANDLE_DEBUG */ - -#ifndef STAT_KTHREAD -#define STAT_KTHREAD 0x40 -#endif - -#ifdef MULTI_INSTANCE_SUPPORT -#define MAX_DECODE_INSTANCE_NUM 9 -#define MULTI_DRIVER_NAME "ammvdec_vp9" - -static unsigned int max_decode_instance_num - = MAX_DECODE_INSTANCE_NUM; -static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM]; -static unsigned int run_count[MAX_DECODE_INSTANCE_NUM]; -static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; -static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; - -static u32 decode_timeout_val = 200; -static int start_decode_buf_level = 0x8000; -static u32 work_buf_size; - -static u32 mv_buf_margin; - -/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ -/* double_write_mode: 0, no double write - 1, 1:1 ratio - 2, (1/4):(1/4) ratio - 4, (1/2):(1/2) ratio - 0x10, double write only -*/ -static u32 double_write_mode; - -#define DRIVER_NAME "amvdec_vp9" -#define MODULE_NAME "amvdec_vp9" -#define DRIVER_HEADER_NAME "amvdec_vp9_header" - - -#define PUT_INTERVAL (HZ/100) -#define ERROR_SYSTEM_RESET_COUNT 200 - -#define PTS_NORMAL 0 -#define PTS_NONE_REF_USE_DURATION 1 - -#define PTS_MODE_SWITCHING_THRESHOLD 3 -#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 - -#define DUR2PTS(x) ((x)*90/96) - -struct VP9Decoder_s; -static int vvp9_vf_states(struct vframe_states *states, void *); -static struct vframe_s *vvp9_vf_peek(void *); -static struct vframe_s *vvp9_vf_get(void *); -static void vvp9_vf_put(struct vframe_s *, void *); -static int vvp9_event_cb(int type, void *data, void *private_data); - -static int vvp9_stop(struct VP9Decoder_s *pbi); -#ifdef MULTI_INSTANCE_SUPPORT -static s32 vvp9_init(struct vdec_s *vdec); -#else -static s32 vvp9_init(struct VP9Decoder_s *pbi); -#endif -static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask); -static int vvp9_local_init(struct VP9Decoder_s *pbi); -static void vvp9_put_timer_func(unsigned long arg); -static void dump_data(struct VP9Decoder_s *pbi, int size); -static unsigned char get_data_check_sum - (struct VP9Decoder_s *pbi, int size); -static void dump_pic_list(struct VP9Decoder_s *pbi); -static int vp9_alloc_mmu( - struct VP9Decoder_s *pbi, - int cur_buf_idx, - int pic_width, - int pic_height, - unsigned short bit_depth, - unsigned int *mmu_index_adr); - - -static const char vvp9_dec_id[] = "vvp9-dev"; - -#define PROVIDER_NAME "decoder.vp9" -#define MULTI_INSTANCE_PROVIDER_NAME "vdec.vp9" - -static const struct vframe_operations_s vvp9_vf_provider = { - .peek = vvp9_vf_peek, - .get = vvp9_vf_get, - .put = vvp9_vf_put, - .event_cb = vvp9_event_cb, - .vf_states = vvp9_vf_states, -}; - -static struct vframe_provider_s vvp9_vf_prov; - -static u32 bit_depth_luma; -static u32 bit_depth_chroma; -static u32 frame_width; -static u32 frame_height; -static u32 video_signal_type; - -static u32 on_no_keyframe_skiped; - -#define PROB_SIZE (496 * 2 * 4) -#define PROB_BUF_SIZE (0x5000) -#define COUNT_BUF_SIZE (0x300 * 4 * 4) -/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ -#define MAX_FRAME_4K_NUM 0x1200 -#define MAX_FRAME_8K_NUM 0x4800 - -#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 - -#ifdef SUPPORT_FB_DECODING -/* register define */ -#define HEVC_ASSIST_HED_FB_W_CTL 0x3006 -#define HEVC_ASSIST_HED_FB_R_CTL 0x3007 -#define HEVC_ASSIST_HED_FB_ADDR 0x3008 -#define HEVC_ASSIST_FB_MMU_MAP_ADDR 0x300a -#define HEVC_ASSIST_FBD_MMU_MAP_ADDR 0x300b - - -#define MAX_STAGE_PAGE_NUM 0x1200 -#define STAGE_MMU_MAP_SIZE (MAX_STAGE_PAGE_NUM * 4) -#endif -static inline int div_r32(int64_t m, int n) -{ -/* - *return (int)(m/n) - */ -#ifndef CONFIG_ARM64 - int64_t qu = 0; - qu = div_s64(m, n); - return (int)qu; -#else - return (int)(m/n); -#endif -} - -/*USE_BUF_BLOCK*/ -struct BUF_s { - int index; - unsigned int alloc_flag; - /*buffer */ - unsigned int cma_page_count; - unsigned long alloc_addr; - unsigned long start_adr; - unsigned int size; - - unsigned int free_start_adr; -} /*BUF_t */; - -struct MVBUF_s { - unsigned long start_adr; - unsigned int size; - int used_flag; -} /*MVBUF_t */; - - /* #undef BUFMGR_ONLY to enable hardware configuration */ - -/*#define TEST_WR_PTR_INC*/ -/*#define WR_PTR_INC_NUM 128*/ -#define WR_PTR_INC_NUM 1 - -#define SIMULATION -#define DOS_PROJECT -#undef MEMORY_MAP_IN_REAL_CHIP - -/*#undef DOS_PROJECT*/ -/*#define MEMORY_MAP_IN_REAL_CHIP*/ - -/*#define BUFFER_MGR_ONLY*/ -/*#define CONFIG_HEVC_CLK_FORCED_ON*/ -/*#define ENABLE_SWAP_TEST*/ -#define MCRCC_ENABLE - -#define VP9_LPF_LVL_UPDATE -/*#define DBG_LF_PRINT*/ - -#ifdef VP9_10B_NV21 -#else -#define LOSLESS_COMPRESS_MODE -#endif - -#define DOUBLE_WRITE_YSTART_TEMP 0x02000000 -#define DOUBLE_WRITE_CSTART_TEMP 0x02900000 - - - -typedef unsigned int u32; -typedef unsigned short u16; - -#define VP9_DEBUG_BUFMGR 0x01 -#define VP9_DEBUG_BUFMGR_MORE 0x02 -#define VP9_DEBUG_BUFMGR_DETAIL 0x04 -#define VP9_DEBUG_OUT_PTS 0x10 -#define VP9_DEBUG_SEND_PARAM_WITH_REG 0x100 -#define VP9_DEBUG_MERGE 0x200 -#define VP9_DEBUG_DBG_LF_PRINT 0x400 -#define VP9_DEBUG_REG 0x800 -#define VP9_DEBUG_2_STAGE 0x1000 -#define VP9_DEBUG_2_STAGE_MORE 0x2000 -#define VP9_DEBUG_DIS_LOC_ERROR_PROC 0x10000 -#define VP9_DEBUG_DIS_SYS_ERROR_PROC 0x20000 -#define VP9_DEBUG_DUMP_PIC_LIST 0x40000 -#define VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000 -#define VP9_DEBUG_NO_TRIGGER_FRAME 0x100000 -#define VP9_DEBUG_LOAD_UCODE_FROM_FILE 0x200000 -#define VP9_DEBUG_FORCE_SEND_AGAIN 0x400000 -#define VP9_DEBUG_DUMP_DATA 0x800000 -#define VP9_DEBUG_CACHE 0x1000000 -#define VP9_DEBUG_CACHE_HIT_RATE 0x2000000 -#define IGNORE_PARAM_FROM_CONFIG 0x8000000 -#ifdef MULTI_INSTANCE_SUPPORT -#define PRINT_FLAG_ERROR 0 -#define PRINT_FLAG_VDEC_STATUS 0x20000000 -#define PRINT_FLAG_VDEC_DETAIL 0x40000000 -#define PRINT_FLAG_VDEC_DATA 0x80000000 -#endif - -static u32 debug; -static bool is_reset; -/*for debug*/ -/* - udebug_flag: - bit 0, enable ucode print - bit 1, enable ucode detail print - bit [31:16] not 0, pos to dump lmem - bit 2, pop bits to lmem - bit [11:8], pre-pop bits for alignment (when bit 2 is 1) -*/ -static u32 udebug_flag; -/* - when udebug_flag[1:0] is not 0 - udebug_pause_pos not 0, - pause position -*/ -static u32 udebug_pause_pos; -/* - when udebug_flag[1:0] is not 0 - and udebug_pause_pos is not 0, - pause only when DEBUG_REG2 is equal to this val -*/ -static u32 udebug_pause_val; - -static u32 udebug_pause_decode_idx; - -#define DEBUG_REG -#ifdef DEBUG_REG -void WRITE_VREG_DBG2(unsigned int adr, unsigned int val) -{ - if (debug & VP9_DEBUG_REG) - pr_info("%s(%x, %x)\n", __func__, adr, val); - if (adr != 0) - WRITE_VREG(adr, val); -} - -#undef WRITE_VREG -#define WRITE_VREG WRITE_VREG_DBG2 -#endif - -#define FRAME_CNT_WINDOW_SIZE 59 -#define RATE_CORRECTION_THRESHOLD 5 -/************************************************** - -VP9 buffer management start - -***************************************************/ - -#define MMU_COMPRESS_HEADER_SIZE 0x48000 -#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) -#define MAX_SIZE_8K (8192 * 4608) -#define MAX_SIZE_4K (4096 * 2304) -#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) - -#define INVALID_IDX -1 /* Invalid buffer index.*/ - -#define RPM_BEGIN 0x200 -#define RPM_END 0x280 - -union param_u { - struct { - unsigned short data[RPM_END - RPM_BEGIN]; - } l; - struct { - /* from ucode lmem, do not change this struct */ - unsigned short profile; - unsigned short show_existing_frame; - unsigned short frame_to_show_idx; - unsigned short frame_type; /*1 bit*/ - unsigned short show_frame; /*1 bit*/ - unsigned short error_resilient_mode; /*1 bit*/ - unsigned short intra_only; /*1 bit*/ - unsigned short display_size_present; /*1 bit*/ - unsigned short reset_frame_context; - unsigned short refresh_frame_flags; - unsigned short width; - unsigned short height; - unsigned short display_width; - unsigned short display_height; - /* - *bit[11:8] - ref_frame_info_0 (ref(3-bits), ref_frame_sign_bias(1-bit)) - *bit[7:4] - ref_frame_info_1 (ref(3-bits), ref_frame_sign_bias(1-bit)) - *bit[3:0] - ref_frame_info_2 (ref(3-bits), ref_frame_sign_bias(1-bit)) - */ - unsigned short ref_info; - /* - *bit[2]: same_frame_size0 - *bit[1]: same_frame_size1 - *bit[0]: same_frame_size2 - */ - unsigned short same_frame_size; - - unsigned short mode_ref_delta_enabled; - unsigned short ref_deltas[4]; - unsigned short mode_deltas[2]; - unsigned short filter_level; - unsigned short sharpness_level; - unsigned short bit_depth; - unsigned short seg_quant_info[8]; - unsigned short seg_enabled; - unsigned short seg_abs_delta; - /* bit 15: feature enabled; bit 8, sign; bit[5:0], data */ - unsigned short seg_lf_info[8]; - } p; -}; - - -struct vpx_codec_frame_buffer_s { - uint8_t *data; /**< Pointer to the data buffer */ - size_t size; /**< Size of data in bytes */ - void *priv; /**< Frame's private data */ -}; - -enum vpx_color_space_t { - VPX_CS_UNKNOWN = 0, /**< Unknown */ - VPX_CS_BT_601 = 1, /**< BT.601 */ - VPX_CS_BT_709 = 2, /**< BT.709 */ - VPX_CS_SMPTE_170 = 3, /**< SMPTE.170 */ - VPX_CS_SMPTE_240 = 4, /**< SMPTE.240 */ - VPX_CS_BT_2020 = 5, /**< BT.2020 */ - VPX_CS_RESERVED = 6, /**< Reserved */ - VPX_CS_SRGB = 7 /**< sRGB */ -}; /**< alias for enum vpx_color_space */ - -enum vpx_bit_depth_t { - VPX_BITS_8 = 8, /**< 8 bits */ - VPX_BITS_10 = 10, /**< 10 bits */ - VPX_BITS_12 = 12, /**< 12 bits */ -}; - -#define MAX_SLICE_NUM 1024 -struct PIC_BUFFER_CONFIG_s { - int index; - int BUF_index; - int mv_buf_index; - int comp_body_size; - int buf_size; - int vf_ref; - int y_canvas_index; - int uv_canvas_index; -#ifdef MULTI_INSTANCE_SUPPORT - struct canvas_config_s canvas_config[2]; -#endif - int decode_idx; - int slice_type; - int stream_offset; - u32 pts; - u64 pts64; - uint8_t error_mark; - /**/ - int slice_idx; - /*buffer*/ - unsigned long header_adr; - unsigned long mpred_mv_wr_start_addr; - /*unsigned long mc_y_adr; - *unsigned long mc_u_v_adr; - */ - unsigned int dw_y_adr; - unsigned int dw_u_v_adr; - int mc_canvas_y; - int mc_canvas_u_v; - - int lcu_total; - /**/ - int y_width; - int y_height; - int y_crop_width; - int y_crop_height; - int y_stride; - - int uv_width; - int uv_height; - int uv_crop_width; - int uv_crop_height; - int uv_stride; - - int alpha_width; - int alpha_height; - int alpha_stride; - - uint8_t *y_buffer; - uint8_t *u_buffer; - uint8_t *v_buffer; - uint8_t *alpha_buffer; - - uint8_t *buffer_alloc; - int buffer_alloc_sz; - int border; - int frame_size; - int subsampling_x; - int subsampling_y; - unsigned int bit_depth; - enum vpx_color_space_t color_space; - - int corrupted; - int flags; - unsigned long cma_alloc_addr; - - int double_write_mode; -} PIC_BUFFER_CONFIG; - -enum BITSTREAM_PROFILE { - PROFILE_0, - PROFILE_1, - PROFILE_2, - PROFILE_3, - MAX_PROFILES -}; - -enum FRAME_TYPE { - KEY_FRAME = 0, - INTER_FRAME = 1, - FRAME_TYPES, -}; - -enum REFERENCE_MODE { - SINGLE_REFERENCE = 0, - COMPOUND_REFERENCE = 1, - REFERENCE_MODE_SELECT = 2, - REFERENCE_MODES = 3, -}; - -#define NONE -1 -#define INTRA_FRAME 0 -#define LAST_FRAME 1 -#define GOLDEN_FRAME 2 -#define ALTREF_FRAME 3 -#define MAX_REF_FRAMES 4 - -#define REFS_PER_FRAME 3 - -#define REF_FRAMES_LOG2 3 -#define REF_FRAMES (1 << REF_FRAMES_LOG2) -#define REF_FRAMES_4K (6) - -/*4 scratch frames for the new frames to support a maximum of 4 cores decoding - *in parallel, 3 for scaled references on the encoder. - *TODO(hkuang): Add ondemand frame buffers instead of hardcoding the number - * // of framebuffers. - *TODO(jkoleszar): These 3 extra references could probably come from the - *normal reference pool. - */ -#define FRAME_BUFFERS (REF_FRAMES + 16) -#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS) -#define MAX_BUF_NUM (FRAME_BUFFERS) -#define MV_BUFFER_NUM FRAME_BUFFERS -#ifdef SUPPORT_FB_DECODING -#define STAGE_MAX_BUFFERS 16 -#else -#define STAGE_MAX_BUFFERS 0 -#endif - -#define FRAME_CONTEXTS_LOG2 2 -#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) -/*buffer + header buffer + workspace*/ -#ifdef MV_USE_FIXED_BUF -#define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1) -#define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) -#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS) -#else -#define MAX_BMMU_BUFFER_NUM \ - (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM + 1) -#define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) -#define MV_BUFFER_IDX(n) (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + n) -#define WORK_SPACE_BUF_ID \ - (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM) -#endif - -struct RefCntBuffer_s { - int ref_count; - /*MV_REF *mvs;*/ - int mi_rows; - int mi_cols; - struct vpx_codec_frame_buffer_s raw_frame_buffer; - struct PIC_BUFFER_CONFIG_s buf; - -/*The Following variables will only be used in frame parallel decode. - * - *frame_worker_owner indicates which FrameWorker owns this buffer. NULL means - *that no FrameWorker owns, or is decoding, this buffer. - *VP9Worker *frame_worker_owner; - * - *row and col indicate which position frame has been decoded to in real - *pixel unit. They are reset to -1 when decoding begins and set to INT_MAX - *when the frame is fully decoded. - */ - int row; - int col; -} RefCntBuffer; - -struct RefBuffer_s { -/*TODO(dkovalev): idx is not really required and should be removed, now it - *is used in vp9_onyxd_if.c - */ - int idx; - struct PIC_BUFFER_CONFIG_s *buf; - /*struct scale_factors sf;*/ -} RefBuffer; - -struct InternalFrameBuffer_s { - uint8_t *data; - size_t size; - int in_use; -} InternalFrameBuffer; - -struct InternalFrameBufferList_s { - int num_internal_frame_buffers; - struct InternalFrameBuffer_s *int_fb; -} InternalFrameBufferList; - -struct BufferPool_s { -/*Protect BufferPool from being accessed by several FrameWorkers at - *the same time during frame parallel decode. - *TODO(hkuang): Try to use atomic variable instead of locking the whole pool. - * - *Private data associated with the frame buffer callbacks. - *void *cb_priv; - * - *vpx_get_frame_buffer_cb_fn_t get_fb_cb; - *vpx_release_frame_buffer_cb_fn_t release_fb_cb; - */ - - struct RefCntBuffer_s frame_bufs[FRAME_BUFFERS]; - -/*Frame buffers allocated internally by the codec.*/ - struct InternalFrameBufferList_s int_frame_buffers; - unsigned long flags; - spinlock_t lock; - -} BufferPool; - -#define lock_buffer_pool(pool, flags) \ - spin_lock_irqsave(&pool->lock, flags) - -#define unlock_buffer_pool(pool, flags) \ - spin_unlock_irqrestore(&pool->lock, flags) - -struct VP9_Common_s { - enum vpx_color_space_t color_space; - int width; - int height; - int display_width; - int display_height; - int last_width; - int last_height; - - int subsampling_x; - int subsampling_y; - - int use_highbitdepth;/*Marks if we need to use 16bit frame buffers.*/ - - struct PIC_BUFFER_CONFIG_s *frame_to_show; - struct RefCntBuffer_s *prev_frame; - - /*TODO(hkuang): Combine this with cur_buf in macroblockd.*/ - struct RefCntBuffer_s *cur_frame; - - int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */ - - /*Prepare ref_frame_map for the next frame. - *Only used in frame parallel decode. - */ - int next_ref_frame_map[REF_FRAMES]; - - /* TODO(jkoleszar): could expand active_ref_idx to 4, - *with 0 as intra, and roll new_fb_idx into it. - */ - - /*Each frame can reference REFS_PER_FRAME buffers*/ - struct RefBuffer_s frame_refs[REFS_PER_FRAME]; - - int prev_fb_idx; - int new_fb_idx; - int cur_fb_idx_mmu; - /*last frame's frame type for motion search*/ - enum FRAME_TYPE last_frame_type; - enum FRAME_TYPE frame_type; - - int show_frame; - int last_show_frame; - int show_existing_frame; - - /*Flag signaling that the frame is encoded using only INTRA modes.*/ - uint8_t intra_only; - uint8_t last_intra_only; - - int allow_high_precision_mv; - - /*Flag signaling that the frame context should be reset to default - *values. 0 or 1 implies don't reset, 2 reset just the context - *specified in the frame header, 3 reset all contexts. - */ - int reset_frame_context; - - /*MBs, mb_rows/cols is in 16-pixel units; mi_rows/cols is in - * MODE_INFO (8-pixel) units. - */ - int MBs; - int mb_rows, mi_rows; - int mb_cols, mi_cols; - int mi_stride; - - /*Whether to use previous frame's motion vectors for prediction.*/ - int use_prev_frame_mvs; - - int refresh_frame_context; /* Two state 0 = NO, 1 = YES */ - - int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */ - - /*struct loopfilter lf;*/ - /*struct segmentation seg;*/ - - /*TODO(hkuang):Remove this as it is the same as frame_parallel_decode*/ - /* in pbi.*/ - int frame_parallel_decode; /* frame-based threading.*/ - - /*Context probabilities for reference frame prediction*/ - /*MV_REFERENCE_FRAME comp_fixed_ref;*/ - /*MV_REFERENCE_FRAME comp_var_ref[2];*/ - enum REFERENCE_MODE reference_mode; - - /*FRAME_CONTEXT *fc; */ /* this frame entropy */ - /*FRAME_CONTEXT *frame_contexts; */ /*FRAME_CONTEXTS*/ - /*unsigned int frame_context_idx; *//* Context to use/update */ - /*FRAME_COUNTS counts;*/ - - unsigned int current_video_frame; - enum BITSTREAM_PROFILE profile; - - enum vpx_bit_depth_t bit_depth; - - int error_resilient_mode; - int frame_parallel_decoding_mode; - - int byte_alignment; - int skip_loop_filter; - - /*External BufferPool passed from outside.*/ - struct BufferPool_s *buffer_pool; - - int above_context_alloc_cols; - -}; - -static void set_canvas(struct VP9Decoder_s *pbi, - struct PIC_BUFFER_CONFIG_s *pic_config); -static int prepare_display_buf(struct VP9Decoder_s *pbi, - struct PIC_BUFFER_CONFIG_s *pic_config); - -static struct PIC_BUFFER_CONFIG_s *get_frame_new_buffer(struct VP9_Common_s *cm) -{ - return &cm->buffer_pool->frame_bufs[cm->new_fb_idx].buf; -} - -static void ref_cnt_fb(struct RefCntBuffer_s *bufs, int *idx, int new_idx) -{ - const int ref_index = *idx; - - if (ref_index >= 0 && bufs[ref_index].ref_count > 0) { - bufs[ref_index].ref_count--; - /*pr_info("[MMU DEBUG 2] dec ref_count[%d] : %d\r\n", - * ref_index, bufs[ref_index].ref_count); - */ - } - - *idx = new_idx; - - bufs[new_idx].ref_count++; - /*pr_info("[MMU DEBUG 3] inc ref_count[%d] : %d\r\n", - * new_idx, bufs[new_idx].ref_count); - */ -} - -int vp9_release_frame_buffer(struct vpx_codec_frame_buffer_s *fb) -{ - struct InternalFrameBuffer_s *const int_fb = - (struct InternalFrameBuffer_s *)fb->priv; - if (int_fb) - int_fb->in_use = 0; - return 0; -} - -static int compute_losless_comp_body_size(int width, int height, - uint8_t is_bit_depth_10); - -static void setup_display_size(struct VP9_Common_s *cm, union param_u *params, - int print_header_info) -{ - cm->display_width = cm->width; - cm->display_height = cm->height; - if (params->p.display_size_present) { - if (print_header_info) - pr_info(" * 1-bit display_size_present read : 1\n"); - cm->display_width = params->p.display_width; - cm->display_height = params->p.display_height; - /*vp9_read_frame_size(rb, &cm->display_width, - * &cm->display_height); - */ - } else { - if (print_header_info) - pr_info(" * 1-bit display_size_present read : 0\n"); - } -} - - -uint8_t print_header_info = 0; - -struct buff_s { - u32 buf_start; - u32 buf_size; - u32 buf_end; -} buff_t; - -struct BuffInfo_s { - u32 max_width; - u32 max_height; - u32 start_adr; - u32 end_adr; - struct buff_s ipp; - struct buff_s sao_abv; - struct buff_s sao_vb; - struct buff_s short_term_rps; - struct buff_s vps; - struct buff_s sps; - struct buff_s pps; - struct buff_s sao_up; - struct buff_s swap_buf; - struct buff_s swap_buf2; - struct buff_s scalelut; - struct buff_s dblk_para; - struct buff_s dblk_data; - struct buff_s seg_map; - struct buff_s mmu_vbh; - struct buff_s cm_header; - struct buff_s mpred_above; -#ifdef MV_USE_FIXED_BUF - struct buff_s mpred_mv; -#endif - struct buff_s rpm; - struct buff_s lmem; -} BuffInfo_t; - -#ifdef MULTI_INSTANCE_SUPPORT -#define DEC_RESULT_NONE 0 -#define DEC_RESULT_DONE 1 -#define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_CONFIG_PARAM 3 -#define DEC_RESULT_ERROR 4 -#define DEC_INIT_PICLIST 5 -#define DEC_UNINIT_PICLIST 6 -#define DEC_RESULT_GET_DATA 7 -#define DEC_RESULT_GET_DATA_RETRY 8 -#define DEC_RESULT_EOS 9 -#define DEC_RESULT_FORCE_EXIT 10 - -#define DEC_S1_RESULT_NONE 0 -#define DEC_S1_RESULT_DONE 1 -#define DEC_S1_RESULT_FORCE_EXIT 2 -#define DEC_S1_RESULT_TEST_TRIGGER_DONE 0xf0 - -#ifdef FB_DECODING_TEST_SCHEDULE -#define TEST_SET_NONE 0 -#define TEST_SET_PIC_DONE 1 -#define TEST_SET_S2_DONE 2 -#endif - -static void vp9_work(struct work_struct *work); -#endif -struct loop_filter_info_n; -struct loopfilter; -struct segmentation; - -#ifdef SUPPORT_FB_DECODING -static void mpred_process(struct VP9Decoder_s *pbi); -static void vp9_s1_work(struct work_struct *work); - -struct stage_buf_s { - int index; - unsigned short rpm[RPM_END - RPM_BEGIN]; -}; - -static unsigned int not_run2_ready[MAX_DECODE_INSTANCE_NUM]; - -static unsigned int run2_count[MAX_DECODE_INSTANCE_NUM]; - -#ifdef FB_DECODING_TEST_SCHEDULE -u32 stage_buf_num; /* = 16;*/ -#else -u32 stage_buf_num; -#endif -#endif - -struct VP9Decoder_s { -#ifdef MULTI_INSTANCE_SUPPORT - unsigned char index; - - struct device *cma_dev; - struct platform_device *platform_dev; - void (*vdec_cb)(struct vdec_s *, void *); - void *vdec_cb_arg; - struct vframe_chunk_s *chunk; - int dec_result; - struct work_struct work; - struct work_struct set_clk_work; - u32 start_shift_bytes; - - struct BuffInfo_s work_space_buf_store; - unsigned long buf_start; - u32 buf_size; - u32 cma_alloc_count; - unsigned long cma_alloc_addr; - uint8_t eos; - unsigned long int start_process_time; - unsigned last_lcu_idx; - int decode_timeout_count; - unsigned timeout_num; - int save_buffer_mode; - - int double_write_mode; -#endif - long used_4k_num; - - unsigned char m_ins_flag; - char *provider_name; - union param_u param; - int frame_count; - int pic_count; - u32 stat; - struct timer_list timer; - u32 frame_dur; - u32 frame_ar; - int fatal_error; - uint8_t init_flag; - uint8_t first_sc_checked; - uint8_t process_busy; -#define PROC_STATE_INIT 0 -#define PROC_STATE_DECODESLICE 1 -#define PROC_STATE_SENDAGAIN 2 - uint8_t process_state; - u32 ucode_pause_pos; - - int show_frame_num; - struct buff_s mc_buf_spec; - struct dec_sysinfo vvp9_amstream_dec_info; - void *rpm_addr; - void *lmem_addr; - dma_addr_t rpm_phy_addr; - dma_addr_t lmem_phy_addr; - unsigned short *lmem_ptr; - unsigned short *debug_ptr; - - void *prob_buffer_addr; - void *count_buffer_addr; - dma_addr_t prob_buffer_phy_addr; - dma_addr_t count_buffer_phy_addr; - - void *frame_mmu_map_addr; - dma_addr_t frame_mmu_map_phy_addr; - - unsigned int use_cma_flag; - - struct BUF_s m_BUF[MAX_BUF_NUM]; - struct MVBUF_s m_mv_BUF[MV_BUFFER_NUM]; - u32 used_buf_num; - DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); - DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE); - struct vframe_s vfpool[VF_POOL_SIZE]; - u32 vf_pre_count; - u32 vf_get_count; - u32 vf_put_count; - int buf_num; - int pic_num; - int lcu_size_log2; - unsigned int losless_comp_body_size; - - u32 video_signal_type; - - int pts_mode; - int last_lookup_pts; - int last_pts; - u64 last_lookup_pts_us64; - u64 last_pts_us64; - u64 shift_byte_count; - - u32 pts_unstable; - u32 frame_cnt_window; - u32 pts1, pts2; - u32 last_duration; - u32 duration_from_pts_done; - bool vp9_first_pts_ready; - - u32 shift_byte_count_lo; - u32 shift_byte_count_hi; - int pts_mode_switching_count; - int pts_mode_recovery_count; - - bool get_frame_dur; - u32 saved_resolution; - - /**/ - struct VP9_Common_s common; - struct RefCntBuffer_s *cur_buf; - int refresh_frame_flags; - uint8_t need_resync; - uint8_t hold_ref_buf; - uint8_t ready_for_new_data; - struct BufferPool_s vp9_buffer_pool; - - struct BuffInfo_s *work_space_buf; - - struct buff_s *mc_buf; - - unsigned int frame_width; - unsigned int frame_height; - - unsigned short *rpm_ptr; - int init_pic_w; - int init_pic_h; - int lcu_total; - int lcu_size; - - int slice_type; - - int skip_flag; - int decode_idx; - int slice_idx; - uint8_t has_keyframe; - uint8_t wait_buf; - uint8_t error_flag; - - /* bit 0, for decoding; bit 1, for displaying */ - uint8_t ignore_bufmgr_error; - int PB_skip_mode; - int PB_skip_count_after_decoding; - /*hw*/ - - /*lf*/ - int default_filt_lvl; - struct loop_filter_info_n *lfi; - struct loopfilter *lf; - struct segmentation *seg_4lf; - /**/ - struct vdec_info *gvs; - - u32 pre_stream_offset; - - unsigned int dec_status; - u32 last_put_idx; - int new_frame_displayed; - void *mmu_box; - void *bmmu_box; - int mmu_enable; - struct vframe_master_display_colour_s vf_dp; - struct firmware_s *fw; - int max_pic_w; - int max_pic_h; -#ifdef SUPPORT_FB_DECODING - int dec_s1_result; - int s1_test_cmd; - struct work_struct s1_work; - int used_stage_buf_num; - int s1_pos; - int s2_pos; - void *stage_mmu_map_addr; - dma_addr_t stage_mmu_map_phy_addr; - struct stage_buf_s *s1_buf; - struct stage_buf_s *s2_buf; - struct stage_buf_s *stage_bufs - [STAGE_MAX_BUFFERS]; - unsigned char run2_busy; - - int s1_mv_buf_index; - int s1_mv_buf_index_pre; - int s1_mv_buf_index_pre_pre; - unsigned long s1_mpred_mv_wr_start_addr; - unsigned long s1_mpred_mv_wr_start_addr_pre; - unsigned short s1_intra_only; - unsigned short s1_frame_type; - unsigned short s1_width; - unsigned short s1_height; - unsigned short s1_last_show_frame; - union param_u s1_param; - u8 back_not_run_ready; -#endif - int need_cache_size; - u64 sc_start_time; -}; - -static void resize_context_buffers(struct VP9Decoder_s *pbi, - struct VP9_Common_s *cm, int width, int height) -{ - if (cm->width != width || cm->height != height) { - /* to do ..*/ - if (pbi != NULL) { - pbi->vp9_first_pts_ready = 0; - pbi->duration_from_pts_done = 0; - } - cm->width = width; - cm->height = height; - pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width, - cm->height, width, height); - } - /* - *if (cm->cur_frame->mvs == NULL || - * cm->mi_rows > cm->cur_frame->mi_rows || - * cm->mi_cols > cm->cur_frame->mi_cols) { - * resize_mv_buffer(cm); - *} - */ -} - -static int valid_ref_frame_size(int ref_width, int ref_height, - int this_width, int this_height) { - return 2 * this_width >= ref_width && - 2 * this_height >= ref_height && - this_width <= 16 * ref_width && - this_height <= 16 * ref_height; -} - -/* - *static int valid_ref_frame_img_fmt(enum vpx_bit_depth_t ref_bit_depth, - * int ref_xss, int ref_yss, - * enum vpx_bit_depth_t this_bit_depth, - * int this_xss, int this_yss) { - * return ref_bit_depth == this_bit_depth && ref_xss == this_xss && - * ref_yss == this_yss; - *} - */ - - -static int setup_frame_size( - struct VP9Decoder_s *pbi, - struct VP9_Common_s *cm, union param_u *params, - unsigned int *mmu_index_adr, - int print_header_info) { - int width, height; - struct BufferPool_s * const pool = cm->buffer_pool; - struct PIC_BUFFER_CONFIG_s *ybf; - int ret = 0; - - width = params->p.width; - height = params->p.height; - /*vp9_read_frame_size(rb, &width, &height);*/ - if (print_header_info) - pr_info(" * 16-bits w read : %d (width : %d)\n", width, height); - if (print_header_info) - pr_info - (" * 16-bits h read : %d (height : %d)\n", width, height); - - WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); -#ifdef VP9_10B_HED_FB - WRITE_VREG(HEVC_ASSIST_PIC_SIZE_FB_READ, (height << 16) | width); -#endif - if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { - ret = vp9_alloc_mmu(pbi, - cm->new_fb_idx, - params->p.width, - params->p.height, - params->p.bit_depth, - mmu_index_adr); - if (ret != 0) { - pr_err("can't alloc need mmu1,idx %d ret =%d\n", - cm->new_fb_idx, - ret); - return ret; - } - cm->cur_fb_idx_mmu = cm->new_fb_idx; - } - - resize_context_buffers(pbi, cm, width, height); - setup_display_size(cm, params, print_header_info); -#if 0 - lock_buffer_pool(pool); - if (vp9_realloc_frame_buffer( - get_frame_new_buffer(cm), cm->width, cm->height, - cm->subsampling_x, cm->subsampling_y, -#if CONFIG_VP9_HIGHBITDEPTH - cm->use_highbitdepth, -#endif - VP9_DEC_BORDER_IN_PIXELS, - cm->byte_alignment, - &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, - pool->get_fb_cb, pool->cb_priv)) { - unlock_buffer_pool(pool); - vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, - "Failed to allocate frame buffer"); - } - unlock_buffer_pool(pool); -#else - /* porting */ - ybf = get_frame_new_buffer(cm); - ybf->y_crop_width = width; - ybf->y_crop_height = height; - ybf->bit_depth = params->p.bit_depth; -#endif - pool->frame_bufs[cm->new_fb_idx].buf.subsampling_x = cm->subsampling_x; - pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; - pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = - (unsigned int)cm->bit_depth; - pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; - return ret; -} - -static int setup_frame_size_with_refs( - struct VP9Decoder_s *pbi, - struct VP9_Common_s *cm, - union param_u *params, - unsigned int *mmu_index_adr, - int print_header_info) { - - int width, height; - int found = 0, i; - int has_valid_ref_frame = 0; - struct PIC_BUFFER_CONFIG_s *ybf; - struct BufferPool_s * const pool = cm->buffer_pool; - int ret = 0; - - for (i = 0; i < REFS_PER_FRAME; ++i) { - if ((params->p.same_frame_size >> - (REFS_PER_FRAME - i - 1)) & 0x1) { - struct PIC_BUFFER_CONFIG_s *const buf = - cm->frame_refs[i].buf; - /*if (print_header_info) - * pr_info - * ("1-bit same_frame_size[%d] read : 1\n", i); - */ - width = buf->y_crop_width; - height = buf->y_crop_height; - /*if (print_header_info) - * pr_info - * (" - same_frame_size width : %d\n", width); - */ - /*if (print_header_info) - * pr_info - * (" - same_frame_size height : %d\n", height); - */ - found = 1; - break; - } else { - /*if (print_header_info) - * pr_info - * ("1-bit same_frame_size[%d] read : 0\n", i); - */ - } - } - - if (!found) { - /*vp9_read_frame_size(rb, &width, &height);*/ - width = params->p.width; - height = params->p.height; - /*if (print_header_info) - * pr_info - * (" * 16-bits w read : %d (width : %d)\n", - * width, height); - *if (print_header_info) - * pr_info - * (" * 16-bits h read : %d (height : %d)\n", - * width, height); - */ - } - - if (width <= 0 || height <= 0) { - pr_err("Error: Invalid frame size\r\n"); - return -1; - } - - params->p.width = width; - params->p.height = height; - - WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); - if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { - /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); - *cm->prev_fb_idx = cm->new_fb_idx; - */ - /* pr_info - * ("[DEBUG DEBUG]Before alloc_mmu, - * prev_fb_idx : %d, new_fb_idx : %d\r\n", - * cm->prev_fb_idx, cm->new_fb_idx); - */ - ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, - params->p.width, params->p.height, - params->p.bit_depth, mmu_index_adr); - if (ret != 0) { - pr_err("can't alloc need mmu,idx %d\r\n", - cm->new_fb_idx); - return ret; - } - cm->cur_fb_idx_mmu = cm->new_fb_idx; - } - - /*Check to make sure at least one of frames that this frame references - *has valid dimensions. - */ - for (i = 0; i < REFS_PER_FRAME; ++i) { - struct RefBuffer_s * const ref_frame = &cm->frame_refs[i]; - - has_valid_ref_frame |= - valid_ref_frame_size(ref_frame->buf->y_crop_width, - ref_frame->buf->y_crop_height, - width, height); - } - if (!has_valid_ref_frame) { - pr_err("Error: Referenced frame has invalid size\r\n"); - return -1; - } -#if 0 - for (i = 0; i < REFS_PER_FRAME; ++i) { - struct RefBuffer_s * const ref_frame = - &cm->frame_refs[i]; - if (!valid_ref_frame_img_fmt( - ref_frame->buf->bit_depth, - ref_frame->buf->subsampling_x, - ref_frame->buf->subsampling_y, - cm->bit_depth, - cm->subsampling_x, - cm->subsampling_y)) - pr_err - ("Referenced frame incompatible color fmt\r\n"); - return -1; - } -#endif - resize_context_buffers(pbi, cm, width, height); - setup_display_size(cm, params, print_header_info); - -#if 0 - lock_buffer_pool(pool); - if (vp9_realloc_frame_buffer( - get_frame_new_buffer(cm), cm->width, cm->height, - cm->subsampling_x, cm->subsampling_y, -#if CONFIG_VP9_HIGHBITDEPTH - cm->use_highbitdepth, -#endif - VP9_DEC_BORDER_IN_PIXELS, - cm->byte_alignment, - &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, - pool->get_fb_cb, - pool->cb_priv)) { - unlock_buffer_pool(pool); - vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, - "Failed to allocate frame buffer"); - } - unlock_buffer_pool(pool); -#else - /* porting */ - ybf = get_frame_new_buffer(cm); - ybf->y_crop_width = width; - ybf->y_crop_height = height; - ybf->bit_depth = params->p.bit_depth; -#endif - pool->frame_bufs[cm->new_fb_idx].buf.subsampling_x = cm->subsampling_x; - pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; - pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = - (unsigned int)cm->bit_depth; - pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; - return ret; -} - - - - - -static int vp9_print(struct VP9Decoder_s *pbi, - int flag, const char *fmt, ...) -{ -#define HEVC_PRINT_BUF 256 - unsigned char buf[HEVC_PRINT_BUF]; - int len = 0; - - if (pbi == NULL || - (flag == 0) || - (debug & flag)) { - va_list args; - - va_start(args, fmt); - if (pbi) - len = sprintf(buf, "[%d]", pbi->index); - vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); - pr_debug("%s", buf); - va_end(args); - } - return 0; -} - -static inline bool close_to(int a, int b, int m) -{ - return (abs(a - b) < m) ? true : false; -} - -#ifdef MULTI_INSTANCE_SUPPORT -static int vp9_print_cont(struct VP9Decoder_s *pbi, - int flag, const char *fmt, ...) -{ - unsigned char buf[HEVC_PRINT_BUF]; - int len = 0; - - if (pbi == NULL || - (flag == 0) || - (debug & flag)) { - va_list args; - - va_start(args, fmt); - vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); - pr_debug("%s", buf); - va_end(args); - } - return 0; -} - -static void trigger_schedule(struct VP9Decoder_s *pbi) -{ - if (pbi->vdec_cb) - pbi->vdec_cb(hw_to_vdec(pbi), pbi->vdec_cb_arg); -} - -static void reset_process_time(struct VP9Decoder_s *pbi) -{ - if (pbi->start_process_time) { - unsigned process_time = - 1000 * (jiffies - pbi->start_process_time) / HZ; - pbi->start_process_time = 0; - if (process_time > max_process_time[pbi->index]) - max_process_time[pbi->index] = process_time; - } -} - -static void start_process_time(struct VP9Decoder_s *pbi) -{ - pbi->start_process_time = jiffies; - pbi->decode_timeout_count = 0; - pbi->last_lcu_idx = 0; -} - -static void timeout_process(struct VP9Decoder_s *pbi) -{ - pbi->timeout_num++; - amhevc_stop(); - vp9_print(pbi, - 0, "%s decoder timeout\n", __func__); - - pbi->dec_result = DEC_RESULT_DONE; - reset_process_time(pbi); - vdec_schedule_work(&pbi->work); -} - -static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi) -{ - return ((double_write_mode & 0x80000000) == 0) ? - pbi->double_write_mode : - (double_write_mode & 0x7fffffff); -} - -static int get_double_write_mode(struct VP9Decoder_s *pbi) -{ - u32 valid_dw_mode = get_valid_double_write_mode(pbi); - u32 dw; - if (valid_dw_mode == 0x100) { - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *cur_pic_config; - int w, h; - - if (!cm->cur_frame) - return 1;/*no valid frame,*/ - cur_pic_config = &cm->cur_frame->buf; - w = cur_pic_config->y_crop_width; - h = cur_pic_config->y_crop_width; - if (w > 1920 && h > 1088) - dw = 0x4; /*1:2*/ - else - dw = 0x1; /*1:1*/ - - return dw; - } - - return valid_dw_mode; -} - -/* for double write buf alloc */ -static int get_double_write_mode_init(struct VP9Decoder_s *pbi) -{ - u32 valid_dw_mode = get_valid_double_write_mode(pbi); - if (valid_dw_mode == 0x100) { - u32 dw; - int w = pbi->init_pic_w; - int h = pbi->init_pic_h; - if (w > 1920 && h > 1088) - dw = 0x4; /*1:2*/ - else - dw = 0x1; /*1:1*/ - - return dw; - } - return valid_dw_mode; -} -#endif - -static int get_double_write_ratio(struct VP9Decoder_s *pbi, - int dw_mode) -{ - int ratio = 1; - if ((dw_mode == 2) || - (dw_mode == 3)) - ratio = 4; - else if (dw_mode == 4) - ratio = 2; - return ratio; -} - -//#define MAX_4K_NUM 0x1200 - -int vp9_alloc_mmu( - struct VP9Decoder_s *pbi, - int cur_buf_idx, - int pic_width, - int pic_height, - unsigned short bit_depth, - unsigned int *mmu_index_adr) -{ - int bit_depth_10 = (bit_depth == VPX_BITS_10); - int picture_size; - int cur_mmu_4k_number, max_frame_num; - if (!pbi->mmu_box) { - pr_err("error no mmu box!\n"); - return -1; - } - if (pbi->double_write_mode & 0x10) - return 0; - if (bit_depth >= VPX_BITS_12) { - pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW; - pr_err("fatal_error, un support bit depth 12!\n\n"); - return -1; - } - picture_size = compute_losless_comp_body_size(pic_width, pic_height, - bit_depth_10); - cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - max_frame_num = MAX_FRAME_8K_NUM; - else - max_frame_num = MAX_FRAME_4K_NUM; - - if (cur_mmu_4k_number > max_frame_num) { - pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", - cur_mmu_4k_number, pic_width, pic_height); - return -1; - } - return decoder_mmu_box_alloc_idx( - pbi->mmu_box, - cur_buf_idx, - cur_mmu_4k_number, - mmu_index_adr); -} - - -#ifndef MV_USE_FIXED_BUF -static void dealloc_mv_bufs(struct VP9Decoder_s *pbi) -{ - int i; - for (i = 0; i < MV_BUFFER_NUM; i++) { - if (pbi->m_mv_BUF[i].start_adr) { - if (debug) - pr_info( - "dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n", - i, pbi->m_mv_BUF[i].start_adr, - pbi->m_mv_BUF[i].size, - pbi->m_mv_BUF[i].used_flag); - decoder_bmmu_box_free_idx( - pbi->bmmu_box, - MV_BUFFER_IDX(i)); - pbi->m_mv_BUF[i].start_adr = 0; - pbi->m_mv_BUF[i].size = 0; - pbi->m_mv_BUF[i].used_flag = 0; - } - } -} - -static int alloc_mv_buf(struct VP9Decoder_s *pbi, - int i, int size) -{ - int ret = 0; - if (decoder_bmmu_box_alloc_buf_phy - (pbi->bmmu_box, - MV_BUFFER_IDX(i), size, - DRIVER_NAME, - &pbi->m_mv_BUF[i].start_adr) < 0) { - pbi->m_mv_BUF[i].start_adr = 0; - ret = -1; - } else { - pbi->m_mv_BUF[i].size = size; - pbi->m_mv_BUF[i].used_flag = 0; - ret = 0; - if (debug) { - pr_info( - "MV Buffer %d: start_adr %p size %x\n", - i, - (void *)pbi->m_mv_BUF[i].start_adr, - pbi->m_mv_BUF[i].size); - } - } - return ret; -} - -static int init_mv_buf_list(struct VP9Decoder_s *pbi) -{ - int i; - int ret = 0; - int count = MV_BUFFER_NUM; - int pic_width = pbi->init_pic_w; - int pic_height = pbi->init_pic_h; - int lcu_size = 64; /*fixed 64*/ - int pic_width_64 = (pic_width + 63) & (~0x3f); - int pic_height_32 = (pic_height + 31) & (~0x1f); - int pic_width_lcu = (pic_width_64 % lcu_size) ? - pic_width_64 / lcu_size + 1 - : pic_width_64 / lcu_size; - int pic_height_lcu = (pic_height_32 % lcu_size) ? - pic_height_32 / lcu_size + 1 - : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; - int size = ((lcu_total * MV_MEM_UNIT) + 0xffff) & - (~0xffff); - if (mv_buf_margin > 0) - count = REF_FRAMES + mv_buf_margin; - - if (pbi->init_pic_w > 2048 && pbi->init_pic_h > 1088) - count = REF_FRAMES_4K + mv_buf_margin; - - if (debug) { - pr_info("%s w:%d, h:%d, count: %d\n", - __func__, pbi->init_pic_w, pbi->init_pic_h, count); - } - - for (i = 0; - i < count && i < MV_BUFFER_NUM; i++) { - if (alloc_mv_buf(pbi, i, size) < 0) { - ret = -1; - break; - } - } - return ret; -} - -static int get_mv_buf(struct VP9Decoder_s *pbi, - int *mv_buf_index, - unsigned long *mpred_mv_wr_start_addr) -{ - int i; - int ret = -1; - for (i = 0; i < MV_BUFFER_NUM; i++) { - if (pbi->m_mv_BUF[i].start_adr && - pbi->m_mv_BUF[i].used_flag == 0) { - pbi->m_mv_BUF[i].used_flag = 1; - ret = i; - break; - } - } - - if (ret >= 0) { - *mv_buf_index = ret; - *mpred_mv_wr_start_addr = - (pbi->m_mv_BUF[ret].start_adr + 0xffff) & - (~0xffff); - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info( - "%s => %d (%ld) size 0x%x\n", - __func__, ret, - *mpred_mv_wr_start_addr, - pbi->m_mv_BUF[ret].size); - } else { - pr_info( - "%s: Error, mv buf is not enough\n", - __func__); - } - return ret; -} - -static void put_mv_buf(struct VP9Decoder_s *pbi, - int *mv_buf_index) -{ - int i = *mv_buf_index; - if (i >= MV_BUFFER_NUM) { - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info( - "%s: index %d beyond range\n", - __func__, i); - return; - } - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info( - "%s(%d): used_flag(%d)\n", - __func__, i, - pbi->m_mv_BUF[i].used_flag); - - *mv_buf_index = -1; - if (pbi->m_mv_BUF[i].start_adr && - pbi->m_mv_BUF[i].used_flag) - pbi->m_mv_BUF[i].used_flag = 0; -} - -static void put_un_used_mv_bufs(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; - int i; - for (i = 0; i < pbi->used_buf_num; ++i) { - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.index != -1) && - (frame_bufs[i].buf.mv_buf_index >= 0) - ) - put_mv_buf(pbi, &frame_bufs[i].buf.mv_buf_index); - } -} - -#ifdef SUPPORT_FB_DECODING -static bool mv_buf_available(struct VP9Decoder_s *pbi) -{ - int i; - bool ret = 0; - for (i = 0; i < MV_BUFFER_NUM; i++) { - if (pbi->m_mv_BUF[i].start_adr && - pbi->m_mv_BUF[i].used_flag == 0) { - ret = 1; - break; - } - } - return ret; -} -#endif -#endif - -#ifdef SUPPORT_FB_DECODING -static void init_stage_buf(struct VP9Decoder_s *pbi) -{ - uint i; - for (i = 0; i < STAGE_MAX_BUFFERS - && i < stage_buf_num; i++) { - pbi->stage_bufs[i] = - vmalloc(sizeof(struct stage_buf_s)); - if (pbi->stage_bufs[i] == NULL) { - vp9_print(pbi, - 0, "%s vmalloc fail\n", __func__); - break; - } - pbi->stage_bufs[i]->index = i; - } - pbi->used_stage_buf_num = i; - pbi->s1_pos = 0; - pbi->s2_pos = 0; - pbi->s1_buf = NULL; - pbi->s2_buf = NULL; - pbi->s1_mv_buf_index = FRAME_BUFFERS; - pbi->s1_mv_buf_index_pre = FRAME_BUFFERS; - pbi->s1_mv_buf_index_pre_pre = FRAME_BUFFERS; - - if (pbi->used_stage_buf_num > 0) - vp9_print(pbi, - 0, "%s 2 stage decoding buf %d\n", - __func__, - pbi->used_stage_buf_num); -} - -static void uninit_stage_buf(struct VP9Decoder_s *pbi) -{ - int i; - for (i = 0; i < pbi->used_stage_buf_num; i++) { - if (pbi->stage_bufs[i]) - vfree(pbi->stage_bufs[i]); - pbi->stage_bufs[i] = NULL; - } - pbi->used_stage_buf_num = 0; - pbi->s1_pos = 0; - pbi->s2_pos = 0; - pbi->s1_buf = NULL; - pbi->s2_buf = NULL; -} - -static int get_s1_buf( - struct VP9Decoder_s *pbi) -{ - struct stage_buf_s *buf = NULL; - int ret = -1; - int buf_page_num = MAX_STAGE_PAGE_NUM; - int next_s1_pos = pbi->s1_pos + 1; - - if (next_s1_pos >= pbi->used_stage_buf_num) - next_s1_pos = 0; - if (next_s1_pos == pbi->s2_pos) { - pbi->s1_buf = NULL; - return ret; - } - - buf = pbi->stage_bufs[pbi->s1_pos]; - ret = decoder_mmu_box_alloc_idx( - pbi->mmu_box, - buf->index, - buf_page_num, - pbi->stage_mmu_map_addr); - if (ret < 0) { - vp9_print(pbi, 0, - "%s decoder_mmu_box_alloc fail for index %d (s1_pos %d s2_pos %d)\n", - __func__, buf->index, - pbi->s1_pos, pbi->s2_pos); - buf = NULL; - } else { - vp9_print(pbi, VP9_DEBUG_2_STAGE, - "%s decoder_mmu_box_alloc %d page for index %d (s1_pos %d s2_pos %d)\n", - __func__, buf_page_num, buf->index, - pbi->s1_pos, pbi->s2_pos); - } - pbi->s1_buf = buf; - return ret; -} - -static void inc_s1_pos(struct VP9Decoder_s *pbi) -{ - struct stage_buf_s *buf = - pbi->stage_bufs[pbi->s1_pos]; - - int used_page_num = -#ifdef FB_DECODING_TEST_SCHEDULE - MAX_STAGE_PAGE_NUM/2; -#else - (READ_VREG(HEVC_ASSIST_HED_FB_W_CTL) >> 16); -#endif - decoder_mmu_box_free_idx_tail(pbi->mmu_box, - FRAME_BUFFERS + buf->index, used_page_num); - - pbi->s1_pos++; - if (pbi->s1_pos >= pbi->used_stage_buf_num) - pbi->s1_pos = 0; - - vp9_print(pbi, VP9_DEBUG_2_STAGE, - "%s (used_page_num %d) for index %d (s1_pos %d s2_pos %d)\n", - __func__, used_page_num, buf->index, - pbi->s1_pos, pbi->s2_pos); -} - -#define s2_buf_available(pbi) (pbi->s1_pos != pbi->s2_pos) - -static int get_s2_buf( - struct VP9Decoder_s *pbi) -{ - int ret = -1; - struct stage_buf_s *buf = NULL; - if (s2_buf_available(pbi)) { - buf = pbi->stage_bufs[pbi->s2_pos]; - vp9_print(pbi, VP9_DEBUG_2_STAGE, - "%s for index %d (s1_pos %d s2_pos %d)\n", - __func__, buf->index, - pbi->s1_pos, pbi->s2_pos); - pbi->s2_buf = buf; - ret = 0; - } - return ret; -} - -static void inc_s2_pos(struct VP9Decoder_s *pbi) -{ - struct stage_buf_s *buf = - pbi->stage_bufs[pbi->s2_pos]; - decoder_mmu_box_free_idx(pbi->mmu_box, - FRAME_BUFFERS + buf->index); - pbi->s2_pos++; - if (pbi->s2_pos >= pbi->used_stage_buf_num) - pbi->s2_pos = 0; - vp9_print(pbi, VP9_DEBUG_2_STAGE, - "%s for index %d (s1_pos %d s2_pos %d)\n", - __func__, buf->index, - pbi->s1_pos, pbi->s2_pos); -} - -static int get_free_stage_buf_num(struct VP9Decoder_s *pbi) -{ - int num; - if (pbi->s1_pos >= pbi->s2_pos) - num = pbi->used_stage_buf_num - - (pbi->s1_pos - pbi->s2_pos) - 1; - else - num = (pbi->s2_pos - pbi->s1_pos) - 1; - return num; -} - -#ifndef FB_DECODING_TEST_SCHEDULE -static DEFINE_SPINLOCK(fb_core_spin_lock); - -static u8 is_s2_decoding_finished(struct VP9Decoder_s *pbi) -{ - /* to do: VLSI review - completion of last LCU decoding in BACK - */ - return 1; -} - -static void start_s1_decoding(struct VP9Decoder_s *pbi) -{ - /* to do: VLSI review - after parser, how to start LCU decoding in BACK - */ -} - -static void fb_reset_core(struct vdec_s *vdec, u32 mask) -{ - /* to do: VLSI review - 1. how to disconnect DMC for FRONT and BACK - 2. reset bit 13, 24, FRONT or BACK ?? - */ - - unsigned long flags; - u32 reset_bits = 0; - if (mask & HW_MASK_FRONT) - WRITE_VREG(HEVC_STREAM_CONTROL, 0); - spin_lock_irqsave(&fb_core_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4))); - spin_unlock_irqrestore(&fb_core_spin_lock, flags); - - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & (1 << 4))) - ; - - if ((mask & HW_MASK_FRONT) && - input_frame_based(vdec)) - WRITE_VREG(HEVC_STREAM_CONTROL, 0); - - /* - * 2: assist - * 3: parser - * 4: parser_state - * 8: dblk - * 11:mcpu - * 12:ccpu - * 13:ddr - * 14:iqit - * 15:ipp - * 17:qdct - * 18:mpred - * 19:sao - * 24:hevc_afifo - */ - if (mask & HW_MASK_FRONT) { - reset_bits = - (1<<3)|(1<<4)|(1<<11)| - (1<<12)|(1<<18); - } - if (mask & HW_MASK_BACK) { - reset_bits = - (1<<8)|(1<<13)|(1<<14)|(1<<15)| - (1<<17)|(1<<19)|(1<<24); - } - WRITE_VREG(DOS_SW_RESET3, reset_bits); -#if 0 - (1<<3)|(1<<4)|(1<<8)|(1<<11)| - (1<<12)|(1<<13)|(1<<14)|(1<<15)| - (1<<17)|(1<<18)|(1<<19)|(1<<24); -#endif - WRITE_VREG(DOS_SW_RESET3, 0); - - - spin_lock_irqsave(&fb_core_spin_lock, flags); - codec_dmcbus_write(DMC_REQ_CTRL, - codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4)); - spin_unlock_irqrestore(&fb_core_spin_lock, flags); - -} -#endif - -#endif - - -static int get_free_fb(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; - int i; - unsigned long flags; - - lock_buffer_pool(cm->buffer_pool, flags); - if (debug & VP9_DEBUG_BUFMGR_MORE) { - for (i = 0; i < pbi->used_buf_num; ++i) { - pr_info("%s:%d, ref_count %d vf_ref %d index %d\r\n", - __func__, i, frame_bufs[i].ref_count, - frame_bufs[i].buf.vf_ref, - frame_bufs[i].buf.index); - } - } - for (i = 0; i < pbi->used_buf_num; ++i) { - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.vf_ref == 0) && - (frame_bufs[i].buf.index != -1) - ) - break; - } - if (i != pbi->used_buf_num) { - frame_bufs[i].ref_count = 1; - /*pr_info("[MMU DEBUG 1] set ref_count[%d] : %d\r\n", - i, frame_bufs[i].ref_count);*/ - } else { - /* Reset i to be INVALID_IDX to indicate - no free buffer found*/ - i = INVALID_IDX; - } - - unlock_buffer_pool(cm->buffer_pool, flags); - return i; -} - -static int get_free_buf_count(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; - int i; - int free_buf_count = 0; - for (i = 0; i < pbi->used_buf_num; ++i) - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.vf_ref == 0) && - (frame_bufs[i].buf.index != -1) - ) - free_buf_count++; - return free_buf_count; -} - -static void decrease_ref_count(int idx, struct RefCntBuffer_s *const frame_bufs, - struct BufferPool_s *const pool) -{ - if (idx >= 0) { - --frame_bufs[idx].ref_count; - /*pr_info("[MMU DEBUG 7] dec ref_count[%d] : %d\r\n", idx, - * frame_bufs[idx].ref_count); - */ - /*A worker may only get a free framebuffer index when - *calling get_free_fb. But the private buffer is not set up - *until finish decoding header. So any error happens during - *decoding header, the frame_bufs will not have valid priv - *buffer. - */ - - if (frame_bufs[idx].ref_count == 0 && - frame_bufs[idx].raw_frame_buffer.priv) - vp9_release_frame_buffer - (&frame_bufs[idx].raw_frame_buffer); - } -} - -static void generate_next_ref_frames(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; - struct BufferPool_s *const pool = cm->buffer_pool; - int mask, ref_index = 0; - unsigned long flags; - - /* Generate next_ref_frame_map.*/ - lock_buffer_pool(pool, flags); - for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { - if (mask & 1) { - cm->next_ref_frame_map[ref_index] = cm->new_fb_idx; - ++frame_bufs[cm->new_fb_idx].ref_count; - /*pr_info("[MMU DEBUG 4] inc ref_count[%d] : %d\r\n", - *cm->new_fb_idx, frame_bufs[cm->new_fb_idx].ref_count); - */ - } else - cm->next_ref_frame_map[ref_index] = - cm->ref_frame_map[ref_index]; - /* Current thread holds the reference frame.*/ - if (cm->ref_frame_map[ref_index] >= 0) { - ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; - /*pr_info - *("[MMU DEBUG 5] inc ref_count[%d] : %d\r\n", - *cm->ref_frame_map[ref_index], - *frame_bufs[cm->ref_frame_map[ref_index]].ref_count); - */ - } - ++ref_index; - } - - for (; ref_index < REF_FRAMES; ++ref_index) { - cm->next_ref_frame_map[ref_index] = - cm->ref_frame_map[ref_index]; - /* Current thread holds the reference frame.*/ - if (cm->ref_frame_map[ref_index] >= 0) { - ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; - /*pr_info("[MMU DEBUG 6] inc ref_count[%d] : %d\r\n", - *cm->ref_frame_map[ref_index], - *frame_bufs[cm->ref_frame_map[ref_index]].ref_count); - */ - } - } - unlock_buffer_pool(pool, flags); - return; -} - -static void refresh_ref_frames(struct VP9Decoder_s *pbi) - -{ - struct VP9_Common_s *const cm = &pbi->common; - struct BufferPool_s *pool = cm->buffer_pool; - struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; - int mask, ref_index = 0; - unsigned long flags; - - lock_buffer_pool(pool, flags); - for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { - const int old_idx = cm->ref_frame_map[ref_index]; - /*Current thread releases the holding of reference frame.*/ - decrease_ref_count(old_idx, frame_bufs, pool); - - /*Release the reference frame in reference map.*/ - if ((mask & 1) && old_idx >= 0) - decrease_ref_count(old_idx, frame_bufs, pool); - cm->ref_frame_map[ref_index] = - cm->next_ref_frame_map[ref_index]; - ++ref_index; - } - - /*Current thread releases the holding of reference frame.*/ - for (; ref_index < REF_FRAMES && !cm->show_existing_frame; - ++ref_index) { - const int old_idx = cm->ref_frame_map[ref_index]; - - decrease_ref_count(old_idx, frame_bufs, pool); - cm->ref_frame_map[ref_index] = - cm->next_ref_frame_map[ref_index]; - } - unlock_buffer_pool(pool, flags); - return; -} - -int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) -{ - struct VP9_Common_s *const cm = &pbi->common; - struct BufferPool_s *pool = cm->buffer_pool; - struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; - int i; - int ret; - - pbi->ready_for_new_data = 0; - - if (pbi->has_keyframe == 0 && - params->p.frame_type != KEY_FRAME){ - on_no_keyframe_skiped++; - return -2; - } - pbi->has_keyframe = 1; - on_no_keyframe_skiped = 0; -#if 0 - if (pbi->mmu_enable) { - if (!pbi->m_ins_flag) - pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - if (cm->prev_fb_idx >= 0) { - decoder_mmu_box_free_idx_tail(pbi->mmu_box, - cm->prev_fb_idx, pbi->used_4k_num); - } - } -#endif - if (cm->new_fb_idx >= 0 - && frame_bufs[cm->new_fb_idx].ref_count == 0){ - vp9_release_frame_buffer - (&frame_bufs[cm->new_fb_idx].raw_frame_buffer); - } - /*pr_info("Before get_free_fb, prev_fb_idx : %d, new_fb_idx : %d\r\n", - cm->prev_fb_idx, cm->new_fb_idx);*/ -#ifndef MV_USE_FIXED_BUF - put_un_used_mv_bufs(pbi); - if (debug & VP9_DEBUG_BUFMGR_DETAIL) - dump_pic_list(pbi); -#endif - cm->new_fb_idx = get_free_fb(pbi); - if (cm->new_fb_idx == INVALID_IDX) { - pr_info("get_free_fb error\r\n"); - return -1; - } -#ifndef MV_USE_FIXED_BUF -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num == 0) { -#endif - if (get_mv_buf(pbi, - &pool->frame_bufs[cm->new_fb_idx]. - buf.mv_buf_index, - &pool->frame_bufs[cm->new_fb_idx]. - buf.mpred_mv_wr_start_addr - ) < 0) { - pr_info("get_mv_buf fail\r\n"); - return -1; - } - if (debug & VP9_DEBUG_BUFMGR_DETAIL) - dump_pic_list(pbi); -#ifdef SUPPORT_FB_DECODING - } -#endif -#endif - cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx]; - /*if (debug & VP9_DEBUG_BUFMGR) - pr_info("[VP9 DEBUG]%s(get_free_fb): %d\r\n", __func__, - cm->new_fb_idx);*/ - - pbi->cur_buf = &frame_bufs[cm->new_fb_idx]; - if (pbi->mmu_enable) { - /* moved to after picture size ready - *alloc_mmu(cm, params->p.width, params->p.height, - *params->p.bit_depth, pbi->frame_mmu_map_addr); - */ - cm->prev_fb_idx = cm->new_fb_idx; - } - /*read_uncompressed_header()*/ - cm->last_frame_type = cm->frame_type; - cm->last_intra_only = cm->intra_only; - cm->profile = params->p.profile; - if (cm->profile >= MAX_PROFILES) { - pr_err("Error: Unsupported profile %d\r\n", cm->profile); - return -1; - } - cm->show_existing_frame = params->p.show_existing_frame; - if (cm->show_existing_frame) { - /* Show an existing frame directly.*/ - int frame_to_show_idx = params->p.frame_to_show_idx; - int frame_to_show; - unsigned long flags; - if (frame_to_show_idx >= REF_FRAMES) { - pr_info("frame_to_show_idx %d exceed max index\r\n", - frame_to_show_idx); - return -1; - } - - frame_to_show = cm->ref_frame_map[frame_to_show_idx]; - /*pr_info("frame_to_show %d\r\n", frame_to_show);*/ - lock_buffer_pool(pool, flags); - if (frame_to_show < 0 || - frame_bufs[frame_to_show].ref_count < 1) { - unlock_buffer_pool(pool, flags); - pr_err - ("Error:Buffer %d does not contain a decoded frame", - frame_to_show); - return -1; - } - - ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show); - unlock_buffer_pool(pool, flags); - pbi->refresh_frame_flags = 0; - /*cm->lf.filter_level = 0;*/ - cm->show_frame = 1; - - /* - *if (pbi->frame_parallel_decode) { - * for (i = 0; i < REF_FRAMES; ++i) - * cm->next_ref_frame_map[i] = - * cm->ref_frame_map[i]; - *} - */ - /* do not decode, search next start code */ - return 1; - } - cm->frame_type = params->p.frame_type; - cm->show_frame = params->p.show_frame; - cm->error_resilient_mode = params->p.error_resilient_mode; - - - if (cm->frame_type == KEY_FRAME) { - pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; - - for (i = 0; i < REFS_PER_FRAME; ++i) { - cm->frame_refs[i].idx = INVALID_IDX; - cm->frame_refs[i].buf = NULL; - } - - ret = setup_frame_size(pbi, - cm, params, pbi->frame_mmu_map_addr, - print_header_info); - if (ret) - return -1; - if (pbi->need_resync) { - memset(&cm->ref_frame_map, -1, - sizeof(cm->ref_frame_map)); - pbi->need_resync = 0; - } - } else { - cm->intra_only = cm->show_frame ? 0 : params->p.intra_only; - /*if (print_header_info) { - * if (cm->show_frame) - * pr_info - * ("intra_only set to 0 because of show_frame\n"); - * else - * pr_info - * ("1-bit intra_only read: %d\n", cm->intra_only); - *} - */ - - - cm->reset_frame_context = cm->error_resilient_mode ? - 0 : params->p.reset_frame_context; - if (print_header_info) { - if (cm->error_resilient_mode) - pr_info - ("reset to 0 error_resilient_mode\n"); - else - pr_info - (" * 2-bits reset_frame_context read : %d\n", - cm->reset_frame_context); - } - - if (cm->intra_only) { - if (cm->profile > PROFILE_0) { - /*read_bitdepth_colorspace_sampling(cm, - * rb, print_header_info); - */ - } else { - /*NOTE: The intra-only frame header - *does not include the specification - *of either the color format or - *color sub-sampling - *in profile 0. VP9 specifies that the default - *color format should be YUV 4:2:0 in this - *case (normative). - */ - cm->color_space = VPX_CS_BT_601; - cm->subsampling_y = cm->subsampling_x = 1; - cm->bit_depth = VPX_BITS_8; - cm->use_highbitdepth = 0; - } - - pbi->refresh_frame_flags = - params->p.refresh_frame_flags; - /*if (print_header_info) - * pr_info("*%d-bits refresh_frame read:0x%x\n", - * REF_FRAMES, pbi->refresh_frame_flags); - */ - ret = setup_frame_size(pbi, - cm, - params, - pbi->frame_mmu_map_addr, - print_header_info); - if (ret) - return -1; - if (pbi->need_resync) { - memset(&cm->ref_frame_map, -1, - sizeof(cm->ref_frame_map)); - pbi->need_resync = 0; - } - } else if (pbi->need_resync != 1) { /* Skip if need resync */ - pbi->refresh_frame_flags = - params->p.refresh_frame_flags; - if (print_header_info) - pr_info - ("*%d-bits refresh_frame read:0x%x\n", - REF_FRAMES, pbi->refresh_frame_flags); - for (i = 0; i < REFS_PER_FRAME; ++i) { - const int ref = - (params->p.ref_info >> - (((REFS_PER_FRAME-i-1)*4)+1)) - & 0x7; - const int idx = - cm->ref_frame_map[ref]; - struct RefBuffer_s * const ref_frame = - &cm->frame_refs[i]; - if (print_header_info) - pr_info("*%d-bits ref[%d]read:%d\n", - REF_FRAMES_LOG2, i, ref); - ref_frame->idx = idx; - ref_frame->buf = &frame_bufs[idx].buf; - cm->ref_frame_sign_bias[LAST_FRAME + i] - = (params->p.ref_info >> - ((REFS_PER_FRAME-i-1)*4)) & 0x1; - if (print_header_info) - pr_info("1bit ref_frame_sign_bias"); - /*pr_info - *("%dread: %d\n", - *LAST_FRAME+i, - *cm->ref_frame_sign_bias - *[LAST_FRAME + i]); - */ - /*pr_info - *("[VP9 DEBUG]%s(get ref):%d\r\n", - *__func__, ref_frame->idx); - */ - - } - - ret = setup_frame_size_with_refs( - pbi, - cm, - params, - pbi->frame_mmu_map_addr, - print_header_info); - if (ret) - return -1; - for (i = 0; i < REFS_PER_FRAME; ++i) { - /*struct RefBuffer_s *const ref_buf = - *&cm->frame_refs[i]; - */ - /* to do: - *vp9_setup_scale_factors_for_frame - */ - } - } - } - - get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; - get_frame_new_buffer(cm)->color_space = cm->color_space; - get_frame_new_buffer(cm)->slice_type = cm->frame_type; - - if (pbi->need_resync) { - pr_err - ("Error: Keyframe/intra-only frame required to reset\r\n"); - return -1; - } - generate_next_ref_frames(pbi); - pbi->hold_ref_buf = 1; - -#if 0 - if (frame_is_intra_only(cm) || cm->error_resilient_mode) - vp9_setup_past_independence(cm); - setup_loopfilter(&cm->lf, rb, print_header_info); - setup_quantization(cm, &pbi->mb, rb, print_header_info); - setup_segmentation(&cm->seg, rb, print_header_info); - setup_segmentation_dequant(cm, print_header_info); - - setup_tile_info(cm, rb, print_header_info); - sz = vp9_rb_read_literal(rb, 16); - if (print_header_info) - pr_info(" * 16-bits size read : %d (0x%x)\n", sz, sz); - - if (sz == 0) - vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, - "Invalid header size"); -#endif - /*end read_uncompressed_header()*/ - cm->use_prev_frame_mvs = !cm->error_resilient_mode && - cm->width == cm->last_width && - cm->height == cm->last_height && - !cm->last_intra_only && - cm->last_show_frame && - (cm->last_frame_type != KEY_FRAME); - - /*pr_info - *("set use_prev_frame_mvs to %d (last_width %d last_height %d", - *cm->use_prev_frame_mvs, cm->last_width, cm->last_height); - *pr_info - *(" last_intra_only %d last_show_frame %d last_frame_type %d)\n", - *cm->last_intra_only, cm->last_show_frame, cm->last_frame_type); - */ - return 0; -} - - -void swap_frame_buffers(struct VP9Decoder_s *pbi) -{ - int ref_index = 0; - struct VP9_Common_s *const cm = &pbi->common; - struct BufferPool_s *const pool = cm->buffer_pool; - struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; - unsigned long flags; - refresh_ref_frames(pbi); - pbi->hold_ref_buf = 0; - cm->frame_to_show = get_frame_new_buffer(cm); - - /*if (!pbi->frame_parallel_decode || !cm->show_frame) {*/ - lock_buffer_pool(pool, flags); - --frame_bufs[cm->new_fb_idx].ref_count; - /*pr_info("[MMU DEBUG 8] dec ref_count[%d] : %d\r\n", cm->new_fb_idx, - * frame_bufs[cm->new_fb_idx].ref_count); - */ - unlock_buffer_pool(pool, flags); - /*}*/ - - /*Invalidate these references until the next frame starts.*/ - for (ref_index = 0; ref_index < 3; ref_index++) - cm->frame_refs[ref_index].idx = -1; -} - -#if 0 -static void check_resync(vpx_codec_alg_priv_t *const ctx, - const struct VP9Decoder_s *const pbi) -{ - /* Clear resync flag if worker got a key frame or intra only frame.*/ - if (ctx->need_resync == 1 && pbi->need_resync == 0 && - (pbi->common.intra_only || pbi->common.frame_type == KEY_FRAME)) - ctx->need_resync = 0; -} -#endif - -int vp9_get_raw_frame(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *sd) -{ - struct VP9_Common_s *const cm = &pbi->common; - int ret = -1; - - if (pbi->ready_for_new_data == 1) - return ret; - - pbi->ready_for_new_data = 1; - - /* no raw frame to show!!! */ - if (!cm->show_frame) - return ret; - - pbi->ready_for_new_data = 1; - - *sd = *cm->frame_to_show; - ret = 0; - - return ret; -} - -int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, - struct buff_s *mc_buf_i) { - struct VP9_Common_s *cm = &pbi->common; - - /*memset(pbi, 0, sizeof(struct VP9Decoder_s));*/ - pbi->frame_count = 0; - pbi->pic_count = 0; - pbi->pre_stream_offset = 0; - cm->buffer_pool = &pbi->vp9_buffer_pool; - spin_lock_init(&cm->buffer_pool->lock); - cm->prev_fb_idx = INVALID_IDX; - cm->new_fb_idx = INVALID_IDX; - pbi->used_4k_num = -1; - cm->cur_fb_idx_mmu = INVALID_IDX; - pr_debug - ("After vp9_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n", - cm->prev_fb_idx, cm->new_fb_idx); - pbi->need_resync = 1; - /* Initialize the references to not point to any frame buffers.*/ - memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map)); - memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map)); - cm->current_video_frame = 0; - pbi->ready_for_new_data = 1; - - /* private init */ - pbi->work_space_buf = buf_spec_i; - if (!pbi->mmu_enable) - pbi->mc_buf = mc_buf_i; - - pbi->rpm_addr = NULL; - pbi->lmem_addr = NULL; - - pbi->use_cma_flag = 0; - pbi->decode_idx = 0; - pbi->slice_idx = 0; - /*int m_uiMaxCUWidth = 1<<7;*/ - /*int m_uiMaxCUHeight = 1<<7;*/ - pbi->has_keyframe = 0; - pbi->skip_flag = 0; - pbi->wait_buf = 0; - pbi->error_flag = 0; - - pbi->pts_mode = PTS_NORMAL; - pbi->last_pts = 0; - pbi->last_lookup_pts = 0; - pbi->last_pts_us64 = 0; - pbi->last_lookup_pts_us64 = 0; - pbi->shift_byte_count = 0; - pbi->shift_byte_count_lo = 0; - pbi->shift_byte_count_hi = 0; - pbi->pts_mode_switching_count = 0; - pbi->pts_mode_recovery_count = 0; - - pbi->buf_num = 0; - pbi->pic_num = 0; - - return 0; -} - - -int vp9_bufmgr_postproc(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s sd; - - swap_frame_buffers(pbi); - if (!cm->show_existing_frame) { - cm->last_show_frame = cm->show_frame; - cm->prev_frame = cm->cur_frame; -#if 0 - if (cm->seg.enabled && !pbi->frame_parallel_decode) - vp9_swap_current_and_last_seg_map(cm); -#endif - } - cm->last_width = cm->width; - cm->last_height = cm->height; - if (cm->show_frame) - cm->current_video_frame++; - - if (vp9_get_raw_frame(pbi, &sd) == 0) { - /*pr_info("Display frame index %d\r\n", sd.index);*/ - sd.stream_offset = pbi->pre_stream_offset; - prepare_display_buf(pbi, &sd); - pbi->pre_stream_offset = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - } - -/* else - * pr_info - * ("Not display this frame,ready_for_new_data%d show_frame%d\r\n", - * pbi->ready_for_new_data, cm->show_frame); - */ - return 0; -} - -struct VP9Decoder_s vp9_decoder; -union param_u vp9_param; - -/************************************************** - * - *VP9 buffer management end - * - *************************************************** - */ - - -#define HEVC_CM_BODY_START_ADDR 0x3626 -#define HEVC_CM_BODY_LENGTH 0x3627 -#define HEVC_CM_HEADER_LENGTH 0x3629 -#define HEVC_CM_HEADER_OFFSET 0x362b - -#define LOSLESS_COMPRESS_MODE - -/*#define DECOMP_HEADR_SURGENT*/ -#ifdef VP9_10B_NV21 -static u32 mem_map_mode = 2 /* 0:linear 1:32x32 2:64x32*/ -#else -static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ -#endif -static u32 enable_mem_saving = 1; -static u32 force_w_h; - -static u32 force_fps; - - -const u32 vp9_version = 201602101; -static u32 debug; -static u32 radr; -static u32 rval; -static u32 pop_shorts; -static u32 dbg_cmd; -static u32 dbg_skip_decode_index; -static u32 endian = 0xff0; -#ifdef ERROR_HANDLE_DEBUG -static u32 dbg_nal_skip_flag; - /* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */ -static u32 dbg_nal_skip_count; -#endif -/*for debug*/ -static u32 decode_pic_begin; -static uint slice_parse_begin; -static u32 step; -#ifdef MIX_STREAM_SUPPORT -static u32 buf_alloc_width = 4096; -static u32 buf_alloc_height = 2304; -static u32 vp9_max_pic_w = 4096; -static u32 vp9_max_pic_h = 2304; - -static u32 dynamic_buf_num_margin; -#else -static u32 buf_alloc_width; -static u32 buf_alloc_height; -static u32 dynamic_buf_num_margin = 7; -#endif -static u32 buf_alloc_depth = 10; -static u32 buf_alloc_size; -/* - *bit[0]: 0, - * bit[1]: 0, always release cma buffer when stop - * bit[1]: 1, never release cma buffer when stop - *bit[0]: 1, when stop, release cma buffer if blackout is 1; - *do not release cma buffer is blackout is not 1 - * - *bit[2]: 0, when start decoding, check current displayed buffer - * (only for buffer decoded by vp9) if blackout is 0 - * 1, do not check current displayed buffer - * - *bit[3]: 1, if blackout is not 1, do not release current - * displayed cma buffer always. - */ -/* set to 1 for fast play; - * set to 8 for other case of "keep last frame" - */ -static u32 buffer_mode = 1; -/* buffer_mode_dbg: debug only*/ -static u32 buffer_mode_dbg = 0xffff0000; -/**/ - -/* - *bit 0, 1: only display I picture; - *bit 1, 1: only decode I picture; - */ -static u32 i_only_flag; - - -static u32 max_decoding_time; -/* - *error handling - */ -/*error_handle_policy: - *bit 0: 0, auto skip error_skip_nal_count nals before error recovery; - *1, skip error_skip_nal_count nals before error recovery; - *bit 1 (valid only when bit0 == 1): - *1, wait vps/sps/pps after error recovery; - *bit 2 (valid only when bit0 == 0): - *0, auto search after error recovery (vp9_recover() called); - *1, manual search after error recovery - *(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) - * - *bit 4: 0, set error_mark after reset/recover - * 1, do not set error_mark after reset/recover - *bit 5: 0, check total lcu for every picture - * 1, do not check total lcu - * - */ - -static u32 error_handle_policy; -/*static u32 parser_sei_enable = 1;*/ -#define MAX_BUF_NUM_NORMAL 12 -#define MAX_BUF_NUM_LESS 10 -static u32 max_buf_num = MAX_BUF_NUM_NORMAL; -#define MAX_BUF_NUM_SAVE_BUF 8 - -static u32 run_ready_min_buf_num = 2; - - -static DEFINE_MUTEX(vvp9_mutex); -#ifndef MULTI_INSTANCE_SUPPORT -static struct device *cma_dev; -#endif - -#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 -#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 -#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 -#define VP9_ADAPT_PROB_REG HEVC_ASSIST_SCRATCH_3 -#define VP9_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_4 -#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 -#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 -#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 -#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 -#define VP9_PROB_SWAP_BUFFER HEVC_ASSIST_SCRATCH_9 -#define VP9_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A -#define VP9_SEG_MAP_BUFFER HEVC_ASSIST_SCRATCH_B -#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D -#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E -#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F -#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_F -#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L -#ifdef MULTI_INSTANCE_SUPPORT -#define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M -#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N -#else -#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M -#define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N -#endif -#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G -#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H - - -/* - *ucode parser/search control - *bit 0: 0, header auto parse; 1, header manual parse - *bit 1: 0, auto skip for noneseamless stream; 1, no skip - *bit [3:2]: valid when bit1==0; - *0, auto skip nal before first vps/sps/pps/idr; - *1, auto skip nal before first vps/sps/pps - *2, auto skip nal before first vps/sps/pps, - * and not decode until the first I slice (with slice address of 0) - * - *3, auto skip before first I slice (nal_type >=16 && nal_type<=21) - *bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) ) - *bit [16]: for NAL_UNIT_EOS when bit0 is 0: - * 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm - *bit [17]: for NAL_SEI when bit0 is 0: - * 0, do not parse SEI in ucode; 1, parse SEI in ucode - *bit [31:20]: used by ucode for debug purpose - */ -#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I - /*[31:24] chip feature - 31: 0, use MBOX1; 1, use MBOX0 - */ -#define DECODE_MODE HEVC_ASSIST_SCRATCH_J -#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K - -#ifdef MULTI_INSTANCE_SUPPORT -#define RPM_BUF_SIZE (0x400 * 2) -#else -#define RPM_BUF_SIZE (0x80*2) -#endif -#define LMEM_BUF_SIZE (0x400 * 2) - -#define WORK_BUF_SPEC_NUM 3 -static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { - { - /* 8M bytes */ - .max_width = 1920, - .max_height = 1088, - .ipp = { - /* IPP work space calculation : - * 4096 * (Y+CbCr+Flags) = 12k, round to 16k - */ - .buf_size = 0x4000, - }, - .sao_abv = { - .buf_size = 0x30000, - }, - .sao_vb = { - .buf_size = 0x30000, - }, - .short_term_rps = { - /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, - * total 64x16x2 = 2048 bytes (0x800) - */ - .buf_size = 0x800, - }, - .vps = { - /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .sps = { - /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .pps = { - /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, - * total 0x2000 bytes - */ - .buf_size = 0x2000, - }, - .sao_up = { - /* SAO UP STORE AREA - Max 640(10240/16) LCU, - * each has 16 bytes total 0x2800 bytes - */ - .buf_size = 0x2800, - }, - .swap_buf = { - /* 256cyclex64bit = 2K bytes 0x800 - * (only 144 cycles valid) - */ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /* support up to 32 SCALELUT 1024x32 = - * 32Kbytes (0x8000) - */ - .buf_size = 0x8000, - }, - .dblk_para = { - /* DBLK -> Max 256(4096/16) LCU, - *each para 1024bytes(total:0x40000), - *data 1024bytes(total:0x40000) - */ - .buf_size = 0x80000, - }, - .dblk_data = { - .buf_size = 0x80000, - }, - .seg_map = { - /*4096x2304/64/64 *24 = 0xd800 Bytes*/ - .buf_size = 0xd800, - }, - .mmu_vbh = { - .buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/ - }, -#if 0 - .cm_header = { - /*add one for keeper.*/ - .buf_size = MMU_COMPRESS_HEADER_SIZE * - (FRAME_BUFFERS + 1), - /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ - }, -#endif - .mpred_above = { - .buf_size = 0x10000, /* 2 * size of hevc*/ - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = {/* 1080p, 0x40000 per buffer */ - .buf_size = 0x40000 * FRAME_BUFFERS, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x400 * 2, - } - }, - { - .max_width = 4096, - .max_height = 2304, - .ipp = { - /* IPP work space calculation : - * 4096 * (Y+CbCr+Flags) = 12k, round to 16k - */ - .buf_size = 0x4000, - }, - .sao_abv = { - .buf_size = 0x30000, - }, - .sao_vb = { - .buf_size = 0x30000, - }, - .short_term_rps = { - /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, - * total 64x16x2 = 2048 bytes (0x800) - */ - .buf_size = 0x800, - }, - .vps = { - /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .sps = { - /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, - * total 0x0800 bytes - */ - .buf_size = 0x800, - }, - .pps = { - /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, - * total 0x2000 bytes - */ - .buf_size = 0x2000, - }, - .sao_up = { - /* SAO UP STORE AREA - Max 640(10240/16) LCU, - * each has 16 bytes total 0x2800 bytes - */ - .buf_size = 0x2800, - }, - .swap_buf = { - /* 256cyclex64bit = 2K bytes 0x800 - * (only 144 cycles valid) - */ - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - /* support up to 32 SCALELUT 1024x32 = 32Kbytes - * (0x8000) - */ - .buf_size = 0x8000, - }, - .dblk_para = { - /* DBLK -> Max 256(4096/16) LCU, - *each para 1024bytes(total:0x40000), - *data 1024bytes(total:0x40000) - */ - .buf_size = 0x80000, - }, - .dblk_data = { - .buf_size = 0x80000, - }, - .seg_map = { - /*4096x2304/64/64 *24 = 0xd800 Bytes*/ - .buf_size = 0xd800, - }, - .mmu_vbh = { - .buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/ - }, -#if 0 - .cm_header = { - /*add one for keeper.*/ - .buf_size = MMU_COMPRESS_HEADER_SIZE * - (FRAME_BUFFERS + 1), - /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ - }, -#endif - .mpred_above = { - .buf_size = 0x10000, /* 2 * size of hevc*/ - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = { - /* .buf_size = 0x100000*16, - * //4k2k , 0x100000 per buffer - */ - /* 4096x2304 , 0x120000 per buffer */ - .buf_size = 0x120000 * FRAME_BUFFERS, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x400 * 2, - } - }, - { - .max_width = 4096*2, - .max_height = 2304*2, - .ipp = { - // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k - .buf_size = 0x4000*2, - }, - .sao_abv = { - .buf_size = 0x30000*2, - }, - .sao_vb = { - .buf_size = 0x30000*2, - }, - .short_term_rps = { - // SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800) - .buf_size = 0x800, - }, - .vps = { - // VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes - .buf_size = 0x800, - }, - .sps = { - // SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes - .buf_size = 0x800, - }, - .pps = { - // PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes - .buf_size = 0x2000, - }, - .sao_up = { - // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes - .buf_size = 0x2800*2, - }, - .swap_buf = { - // 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid) - .buf_size = 0x800, - }, - .swap_buf2 = { - .buf_size = 0x800, - }, - .scalelut = { - // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) - .buf_size = 0x8000*2, - }, - .dblk_para = { - // DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000) - .buf_size = 0x80000*2, - }, - .dblk_data = { - .buf_size = 0x80000*2, - }, - .mmu_vbh = { - .buf_size = 0x5000*2, //2*16*(more than 2304)/4, 4K - }, -#if 0 - .cm_header = { - //.buf_size = MMU_COMPRESS_HEADER_SIZE*8, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) - .buf_size = MMU_COMPRESS_HEADER_SIZE*16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) - }, -#endif - .mpred_above = { - .buf_size = 0x10000*2, /* 2 * size of hevc*/ - }, -#ifdef MV_USE_FIXED_BUF - .mpred_mv = { - //4k2k , 0x100000 per buffer */ - /* 4096x2304 , 0x120000 per buffer */ - .buf_size = 0x120000 * FRAME_BUFFERS * 4, - }, -#endif - .rpm = { - .buf_size = RPM_BUF_SIZE, - }, - .lmem = { - .buf_size = 0x400 * 2, - } - } -}; - - -/*Losless compression body buffer size 4K per 64x32 (jt)*/ -int compute_losless_comp_body_size(int width, int height, - uint8_t is_bit_depth_10) -{ - int width_x64; - int height_x32; - int bsize; - - width_x64 = width + 63; - width_x64 >>= 6; - height_x32 = height + 31; - height_x32 >>= 5; - bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32; - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("%s(%d,%d,%d)=>%d\n", - __func__, width, height, - is_bit_depth_10, bsize); - - return bsize; -} - -/* Losless compression header buffer size 32bytes per 128x64 (jt)*/ -static int compute_losless_comp_header_size(int width, int height) -{ - int width_x128; - int height_x64; - int hsize; - - width_x128 = width + 127; - width_x128 >>= 7; - height_x64 = height + 63; - height_x64 >>= 6; - - hsize = 32 * width_x128 * height_x64; - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("%s(%d,%d)=>%d\n", - __func__, width, height, - hsize); - - return hsize; -} - -static void init_buff_spec(struct VP9Decoder_s *pbi, - struct BuffInfo_s *buf_spec) -{ - void *mem_start_virt; - - buf_spec->ipp.buf_start = buf_spec->start_adr; - buf_spec->sao_abv.buf_start = - buf_spec->ipp.buf_start + buf_spec->ipp.buf_size; - - buf_spec->sao_vb.buf_start = - buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size; - buf_spec->short_term_rps.buf_start = - buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size; - buf_spec->vps.buf_start = - buf_spec->short_term_rps.buf_start + - buf_spec->short_term_rps.buf_size; - buf_spec->sps.buf_start = - buf_spec->vps.buf_start + buf_spec->vps.buf_size; - buf_spec->pps.buf_start = - buf_spec->sps.buf_start + buf_spec->sps.buf_size; - buf_spec->sao_up.buf_start = - buf_spec->pps.buf_start + buf_spec->pps.buf_size; - buf_spec->swap_buf.buf_start = - buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size; - buf_spec->swap_buf2.buf_start = - buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size; - buf_spec->scalelut.buf_start = - buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size; - buf_spec->dblk_para.buf_start = - buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size; - buf_spec->dblk_data.buf_start = - buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; - buf_spec->seg_map.buf_start = - buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; - if (pbi == NULL || pbi->mmu_enable) { - buf_spec->mmu_vbh.buf_start = - buf_spec->seg_map.buf_start + - buf_spec->seg_map.buf_size; - buf_spec->mpred_above.buf_start = - buf_spec->mmu_vbh.buf_start + - buf_spec->mmu_vbh.buf_size; - } else { - buf_spec->mpred_above.buf_start = - buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; - } -#ifdef MV_USE_FIXED_BUF - buf_spec->mpred_mv.buf_start = - buf_spec->mpred_above.buf_start + - buf_spec->mpred_above.buf_size; - - buf_spec->rpm.buf_start = - buf_spec->mpred_mv.buf_start + - buf_spec->mpred_mv.buf_size; -#else - buf_spec->rpm.buf_start = - buf_spec->mpred_above.buf_start + - buf_spec->mpred_above.buf_size; - -#endif - buf_spec->lmem.buf_start = - buf_spec->rpm.buf_start + - buf_spec->rpm.buf_size; - buf_spec->end_adr = - buf_spec->lmem.buf_start + - buf_spec->lmem.buf_size; - - if (!pbi) - return; - - if (!vdec_secure(hw_to_vdec(pbi))) { - mem_start_virt = - codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start); - if (mem_start_virt) { - memset(mem_start_virt, 0, - buf_spec->dblk_para.buf_size); - codec_mm_dma_flush(mem_start_virt, - buf_spec->dblk_para.buf_size, - DMA_TO_DEVICE); - } else { - mem_start_virt = codec_mm_vmap( - buf_spec->dblk_para.buf_start, - buf_spec->dblk_para.buf_size); - if (mem_start_virt) { - memset(mem_start_virt, 0, - buf_spec->dblk_para.buf_size); - codec_mm_dma_flush(mem_start_virt, - buf_spec->dblk_para.buf_size, - DMA_TO_DEVICE); - codec_mm_unmap_phyaddr(mem_start_virt); - } else { - /*not virt for tvp playing, - may need clear on ucode.*/ - pr_err("mem_start_virt failed\n"); - } - } - } - - if (debug) { - pr_info("%s workspace (%x %x) size = %x\n", __func__, - buf_spec->start_adr, buf_spec->end_adr, - buf_spec->end_adr - buf_spec->start_adr); - } - - if (debug) { - pr_info("ipp.buf_start :%x\n", - buf_spec->ipp.buf_start); - pr_info("sao_abv.buf_start :%x\n", - buf_spec->sao_abv.buf_start); - pr_info("sao_vb.buf_start :%x\n", - buf_spec->sao_vb.buf_start); - pr_info("short_term_rps.buf_start :%x\n", - buf_spec->short_term_rps.buf_start); - pr_info("vps.buf_start :%x\n", - buf_spec->vps.buf_start); - pr_info("sps.buf_start :%x\n", - buf_spec->sps.buf_start); - pr_info("pps.buf_start :%x\n", - buf_spec->pps.buf_start); - pr_info("sao_up.buf_start :%x\n", - buf_spec->sao_up.buf_start); - pr_info("swap_buf.buf_start :%x\n", - buf_spec->swap_buf.buf_start); - pr_info("swap_buf2.buf_start :%x\n", - buf_spec->swap_buf2.buf_start); - pr_info("scalelut.buf_start :%x\n", - buf_spec->scalelut.buf_start); - pr_info("dblk_para.buf_start :%x\n", - buf_spec->dblk_para.buf_start); - pr_info("dblk_data.buf_start :%x\n", - buf_spec->dblk_data.buf_start); - pr_info("seg_map.buf_start :%x\n", - buf_spec->seg_map.buf_start); - if (pbi->mmu_enable) { - pr_info("mmu_vbh.buf_start :%x\n", - buf_spec->mmu_vbh.buf_start); - } - pr_info("mpred_above.buf_start :%x\n", - buf_spec->mpred_above.buf_start); -#ifdef MV_USE_FIXED_BUF - pr_info("mpred_mv.buf_start :%x\n", - buf_spec->mpred_mv.buf_start); -#endif - if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { - pr_info("rpm.buf_start :%x\n", - buf_spec->rpm.buf_start); - } - } -} - -/* cache_util.c */ -#define THODIYIL_MCRCC_CANVAS_ALGX 4 - -static u32 mcrcc_cache_alg_flag = THODIYIL_MCRCC_CANVAS_ALGX; - -static void mcrcc_perfcount_reset(void) -{ - if (debug & VP9_DEBUG_CACHE) - pr_info("[cache_util.c] Entered mcrcc_perfcount_reset...\n"); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x1); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x0); - return; -} - -static unsigned raw_mcr_cnt_total_prev; -static unsigned hit_mcr_0_cnt_total_prev; -static unsigned hit_mcr_1_cnt_total_prev; -static unsigned byp_mcr_cnt_nchcanv_total_prev; -static unsigned byp_mcr_cnt_nchoutwin_total_prev; - -static void mcrcc_get_hitrate(unsigned reset_pre) -{ - unsigned delta_hit_mcr_0_cnt; - unsigned delta_hit_mcr_1_cnt; - unsigned delta_raw_mcr_cnt; - unsigned delta_mcr_cnt_nchcanv; - unsigned delta_mcr_cnt_nchoutwin; - - unsigned tmp; - unsigned raw_mcr_cnt; - unsigned hit_mcr_cnt; - unsigned byp_mcr_cnt_nchoutwin; - unsigned byp_mcr_cnt_nchcanv; - int hitrate; - if (reset_pre) { - raw_mcr_cnt_total_prev = 0; - hit_mcr_0_cnt_total_prev = 0; - hit_mcr_1_cnt_total_prev = 0; - byp_mcr_cnt_nchcanv_total_prev = 0; - byp_mcr_cnt_nchoutwin_total_prev = 0; - } - if (debug & VP9_DEBUG_CACHE) - pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n"); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1)); - raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1)); - hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1)); - byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1)); - byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - - if (debug & VP9_DEBUG_CACHE) - pr_info("raw_mcr_cnt_total: %d\n", - raw_mcr_cnt); - if (debug & VP9_DEBUG_CACHE) - pr_info("hit_mcr_cnt_total: %d\n", - hit_mcr_cnt); - if (debug & VP9_DEBUG_CACHE) - pr_info("byp_mcr_cnt_nchoutwin_total: %d\n", - byp_mcr_cnt_nchoutwin); - if (debug & VP9_DEBUG_CACHE) - pr_info("byp_mcr_cnt_nchcanv_total: %d\n", - byp_mcr_cnt_nchcanv); - - delta_raw_mcr_cnt = raw_mcr_cnt - - raw_mcr_cnt_total_prev; - delta_mcr_cnt_nchcanv = byp_mcr_cnt_nchcanv - - byp_mcr_cnt_nchcanv_total_prev; - delta_mcr_cnt_nchoutwin = byp_mcr_cnt_nchoutwin - - byp_mcr_cnt_nchoutwin_total_prev; - raw_mcr_cnt_total_prev = raw_mcr_cnt; - byp_mcr_cnt_nchcanv_total_prev = byp_mcr_cnt_nchcanv; - byp_mcr_cnt_nchoutwin_total_prev = byp_mcr_cnt_nchoutwin; - - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & VP9_DEBUG_CACHE) - pr_info("miss_mcr_0_cnt_total: %d\n", tmp); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & VP9_DEBUG_CACHE) - pr_info("miss_mcr_1_cnt_total: %d\n", tmp); - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & VP9_DEBUG_CACHE) - pr_info("hit_mcr_0_cnt_total: %d\n", tmp); - delta_hit_mcr_0_cnt = tmp - hit_mcr_0_cnt_total_prev; - hit_mcr_0_cnt_total_prev = tmp; - WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1)); - tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); - if (debug & VP9_DEBUG_CACHE) - pr_info("hit_mcr_1_cnt_total: %d\n", tmp); - delta_hit_mcr_1_cnt = tmp - hit_mcr_1_cnt_total_prev; - hit_mcr_1_cnt_total_prev = tmp; - - if (delta_raw_mcr_cnt != 0) { - hitrate = 100 * delta_hit_mcr_0_cnt - / delta_raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("CANV0_HIT_RATE : %d\n", hitrate); - hitrate = 100 * delta_hit_mcr_1_cnt - / delta_raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("CANV1_HIT_RATE : %d\n", hitrate); - hitrate = 100 * delta_mcr_cnt_nchcanv - / delta_raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("NONCACH_CANV_BYP_RATE : %d\n", hitrate); - hitrate = 100 * delta_mcr_cnt_nchoutwin - / delta_raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("CACHE_OUTWIN_BYP_RATE : %d\n", hitrate); - } - - - if (raw_mcr_cnt != 0) { - hitrate = 100 * hit_mcr_cnt / raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("MCRCC_HIT_RATE : %d\n", hitrate); - hitrate = 100 * (byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv) - / raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("MCRCC_BYP_RATE : %d\n", hitrate); - } else { - if (debug & VP9_DEBUG_CACHE) - pr_info("MCRCC_HIT_RATE : na\n"); - if (debug & VP9_DEBUG_CACHE) - pr_info("MCRCC_BYP_RATE : na\n"); - } - return; -} - - -static void decomp_perfcount_reset(void) -{ - if (debug & VP9_DEBUG_CACHE) - pr_info("[cache_util.c] Entered decomp_perfcount_reset...\n"); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x1); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x0); - return; -} - -static void decomp_get_hitrate(void) -{ - unsigned raw_mcr_cnt; - unsigned hit_mcr_cnt; - int hitrate; - if (debug & VP9_DEBUG_CACHE) - pr_info("[cache_util.c] Entered decomp_get_hitrate...\n"); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1)); - raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1)); - hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - - if (debug & VP9_DEBUG_CACHE) - pr_info("hcache_raw_cnt_total: %d\n", raw_mcr_cnt); - if (debug & VP9_DEBUG_CACHE) - pr_info("hcache_hit_cnt_total: %d\n", hit_mcr_cnt); - - if (raw_mcr_cnt != 0) { - hitrate = hit_mcr_cnt * 100 / raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate); - } else { - if (debug & VP9_DEBUG_CACHE) - pr_info("DECOMP_HCACHE_HIT_RATE : na\n"); - } - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1)); - raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1)); - hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - - if (debug & VP9_DEBUG_CACHE) - pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt); - if (debug & VP9_DEBUG_CACHE) - pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt); - - if (raw_mcr_cnt != 0) { - hitrate = hit_mcr_cnt * 100 / raw_mcr_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate); - } else { - if (debug & VP9_DEBUG_CACHE) - pr_info("DECOMP_DCACHE_HIT_RATE : na\n"); - } - return; -} - -static void decomp_get_comprate(void) -{ - unsigned raw_ucomp_cnt; - unsigned fast_comp_cnt; - unsigned slow_comp_cnt; - int comprate; - - if (debug & VP9_DEBUG_CACHE) - pr_info("[cache_util.c] Entered decomp_get_comprate...\n"); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1)); - fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1)); - slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1)); - raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); - - if (debug & VP9_DEBUG_CACHE) - pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt); - if (debug & VP9_DEBUG_CACHE) - pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt); - if (debug & VP9_DEBUG_CACHE) - pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt); - - if (raw_ucomp_cnt != 0) { - comprate = (fast_comp_cnt + slow_comp_cnt) - * 100 / raw_ucomp_cnt; - if (debug & VP9_DEBUG_CACHE) - pr_info("DECOMP_COMP_RATIO : %d\n", comprate); - } else { - if (debug & VP9_DEBUG_CACHE) - pr_info("DECOMP_COMP_RATIO : na\n"); - } - return; -} -/* cache_util.c end */ - -/*==================================================== - *======================================================================== - *vp9_prob define - *======================================================================== - */ -#define VP9_PARTITION_START 0 -#define VP9_PARTITION_SIZE_STEP (3 * 4) -#define VP9_PARTITION_ONE_SIZE (4 * VP9_PARTITION_SIZE_STEP) -#define VP9_PARTITION_KEY_START 0 -#define VP9_PARTITION_P_START VP9_PARTITION_ONE_SIZE -#define VP9_PARTITION_SIZE (2 * VP9_PARTITION_ONE_SIZE) -#define VP9_SKIP_START (VP9_PARTITION_START + VP9_PARTITION_SIZE) -#define VP9_SKIP_SIZE 4 /* only use 3*/ -#define VP9_TX_MODE_START (VP9_SKIP_START+VP9_SKIP_SIZE) -#define VP9_TX_MODE_8_0_OFFSET 0 -#define VP9_TX_MODE_8_1_OFFSET 1 -#define VP9_TX_MODE_16_0_OFFSET 2 -#define VP9_TX_MODE_16_1_OFFSET 4 -#define VP9_TX_MODE_32_0_OFFSET 6 -#define VP9_TX_MODE_32_1_OFFSET 9 -#define VP9_TX_MODE_SIZE 12 -#define VP9_COEF_START (VP9_TX_MODE_START+VP9_TX_MODE_SIZE) -#define VP9_COEF_BAND_0_OFFSET 0 -#define VP9_COEF_BAND_1_OFFSET (VP9_COEF_BAND_0_OFFSET + 3 * 3 + 1) -#define VP9_COEF_BAND_2_OFFSET (VP9_COEF_BAND_1_OFFSET + 6 * 3) -#define VP9_COEF_BAND_3_OFFSET (VP9_COEF_BAND_2_OFFSET + 6 * 3) -#define VP9_COEF_BAND_4_OFFSET (VP9_COEF_BAND_3_OFFSET + 6 * 3) -#define VP9_COEF_BAND_5_OFFSET (VP9_COEF_BAND_4_OFFSET + 6 * 3) -#define VP9_COEF_SIZE_ONE_SET 100 /* ((3 +5*6)*3 + 1 padding)*/ -#define VP9_COEF_4X4_START (VP9_COEF_START + 0 * VP9_COEF_SIZE_ONE_SET) -#define VP9_COEF_8X8_START (VP9_COEF_START + 4 * VP9_COEF_SIZE_ONE_SET) -#define VP9_COEF_16X16_START (VP9_COEF_START + 8 * VP9_COEF_SIZE_ONE_SET) -#define VP9_COEF_32X32_START (VP9_COEF_START + 12 * VP9_COEF_SIZE_ONE_SET) -#define VP9_COEF_SIZE_PLANE (2 * VP9_COEF_SIZE_ONE_SET) -#define VP9_COEF_SIZE (4 * 2 * 2 * VP9_COEF_SIZE_ONE_SET) -#define VP9_INTER_MODE_START (VP9_COEF_START+VP9_COEF_SIZE) -#define VP9_INTER_MODE_SIZE 24 /* only use 21 ( #*7)*/ -#define VP9_INTERP_START (VP9_INTER_MODE_START+VP9_INTER_MODE_SIZE) -#define VP9_INTERP_SIZE 8 -#define VP9_INTRA_INTER_START (VP9_INTERP_START+VP9_INTERP_SIZE) -#define VP9_INTRA_INTER_SIZE 4 -#define VP9_INTERP_INTRA_INTER_START VP9_INTERP_START -#define VP9_INTERP_INTRA_INTER_SIZE (VP9_INTERP_SIZE + VP9_INTRA_INTER_SIZE) -#define VP9_COMP_INTER_START \ - (VP9_INTERP_INTRA_INTER_START+VP9_INTERP_INTRA_INTER_SIZE) -#define VP9_COMP_INTER_SIZE 5 -#define VP9_COMP_REF_START (VP9_COMP_INTER_START+VP9_COMP_INTER_SIZE) -#define VP9_COMP_REF_SIZE 5 -#define VP9_SINGLE_REF_START (VP9_COMP_REF_START+VP9_COMP_REF_SIZE) -#define VP9_SINGLE_REF_SIZE 10 -#define VP9_REF_MODE_START VP9_COMP_INTER_START -#define VP9_REF_MODE_SIZE \ - (VP9_COMP_INTER_SIZE+VP9_COMP_REF_SIZE+VP9_SINGLE_REF_SIZE) -#define VP9_IF_Y_MODE_START (VP9_REF_MODE_START+VP9_REF_MODE_SIZE) -#define VP9_IF_Y_MODE_SIZE 36 -#define VP9_IF_UV_MODE_START (VP9_IF_Y_MODE_START+VP9_IF_Y_MODE_SIZE) -#define VP9_IF_UV_MODE_SIZE 92 /* only use 90*/ -#define VP9_MV_JOINTS_START (VP9_IF_UV_MODE_START+VP9_IF_UV_MODE_SIZE) -#define VP9_MV_JOINTS_SIZE 3 -#define VP9_MV_SIGN_0_START (VP9_MV_JOINTS_START+VP9_MV_JOINTS_SIZE) -#define VP9_MV_SIGN_0_SIZE 1 -#define VP9_MV_CLASSES_0_START (VP9_MV_SIGN_0_START+VP9_MV_SIGN_0_SIZE) -#define VP9_MV_CLASSES_0_SIZE 10 -#define VP9_MV_CLASS0_0_START (VP9_MV_CLASSES_0_START+VP9_MV_CLASSES_0_SIZE) -#define VP9_MV_CLASS0_0_SIZE 1 -#define VP9_MV_BITS_0_START (VP9_MV_CLASS0_0_START+VP9_MV_CLASS0_0_SIZE) -#define VP9_MV_BITS_0_SIZE 10 -#define VP9_MV_SIGN_1_START (VP9_MV_BITS_0_START+VP9_MV_BITS_0_SIZE) -#define VP9_MV_SIGN_1_SIZE 1 -#define VP9_MV_CLASSES_1_START \ - (VP9_MV_SIGN_1_START+VP9_MV_SIGN_1_SIZE) -#define VP9_MV_CLASSES_1_SIZE 10 -#define VP9_MV_CLASS0_1_START \ - (VP9_MV_CLASSES_1_START+VP9_MV_CLASSES_1_SIZE) -#define VP9_MV_CLASS0_1_SIZE 1 -#define VP9_MV_BITS_1_START \ - (VP9_MV_CLASS0_1_START+VP9_MV_CLASS0_1_SIZE) -#define VP9_MV_BITS_1_SIZE 10 -#define VP9_MV_CLASS0_FP_0_START \ - (VP9_MV_BITS_1_START+VP9_MV_BITS_1_SIZE) -#define VP9_MV_CLASS0_FP_0_SIZE 9 -#define VP9_MV_CLASS0_FP_1_START \ - (VP9_MV_CLASS0_FP_0_START+VP9_MV_CLASS0_FP_0_SIZE) -#define VP9_MV_CLASS0_FP_1_SIZE 9 -#define VP9_MV_CLASS0_HP_0_START \ - (VP9_MV_CLASS0_FP_1_START+VP9_MV_CLASS0_FP_1_SIZE) -#define VP9_MV_CLASS0_HP_0_SIZE 2 -#define VP9_MV_CLASS0_HP_1_START \ - (VP9_MV_CLASS0_HP_0_START+VP9_MV_CLASS0_HP_0_SIZE) -#define VP9_MV_CLASS0_HP_1_SIZE 2 -#define VP9_MV_START VP9_MV_JOINTS_START -#define VP9_MV_SIZE 72 /*only use 69*/ - -#define VP9_TOTAL_SIZE (VP9_MV_START + VP9_MV_SIZE) - - -/*======================================================================== - * vp9_count_mem define - *======================================================================== - */ -#define VP9_COEF_COUNT_START 0 -#define VP9_COEF_COUNT_BAND_0_OFFSET 0 -#define VP9_COEF_COUNT_BAND_1_OFFSET \ - (VP9_COEF_COUNT_BAND_0_OFFSET + 3*5) -#define VP9_COEF_COUNT_BAND_2_OFFSET \ - (VP9_COEF_COUNT_BAND_1_OFFSET + 6*5) -#define VP9_COEF_COUNT_BAND_3_OFFSET \ - (VP9_COEF_COUNT_BAND_2_OFFSET + 6*5) -#define VP9_COEF_COUNT_BAND_4_OFFSET \ - (VP9_COEF_COUNT_BAND_3_OFFSET + 6*5) -#define VP9_COEF_COUNT_BAND_5_OFFSET \ - (VP9_COEF_COUNT_BAND_4_OFFSET + 6*5) -#define VP9_COEF_COUNT_SIZE_ONE_SET 165 /* ((3 +5*6)*5 */ -#define VP9_COEF_COUNT_4X4_START \ - (VP9_COEF_COUNT_START + 0*VP9_COEF_COUNT_SIZE_ONE_SET) -#define VP9_COEF_COUNT_8X8_START \ - (VP9_COEF_COUNT_START + 4*VP9_COEF_COUNT_SIZE_ONE_SET) -#define VP9_COEF_COUNT_16X16_START \ - (VP9_COEF_COUNT_START + 8*VP9_COEF_COUNT_SIZE_ONE_SET) -#define VP9_COEF_COUNT_32X32_START \ - (VP9_COEF_COUNT_START + 12*VP9_COEF_COUNT_SIZE_ONE_SET) -#define VP9_COEF_COUNT_SIZE_PLANE (2 * VP9_COEF_COUNT_SIZE_ONE_SET) -#define VP9_COEF_COUNT_SIZE (4 * 2 * 2 * VP9_COEF_COUNT_SIZE_ONE_SET) - -#define VP9_INTRA_INTER_COUNT_START \ - (VP9_COEF_COUNT_START+VP9_COEF_COUNT_SIZE) -#define VP9_INTRA_INTER_COUNT_SIZE (4*2) -#define VP9_COMP_INTER_COUNT_START \ - (VP9_INTRA_INTER_COUNT_START+VP9_INTRA_INTER_COUNT_SIZE) -#define VP9_COMP_INTER_COUNT_SIZE (5*2) -#define VP9_COMP_REF_COUNT_START \ - (VP9_COMP_INTER_COUNT_START+VP9_COMP_INTER_COUNT_SIZE) -#define VP9_COMP_REF_COUNT_SIZE (5*2) -#define VP9_SINGLE_REF_COUNT_START \ - (VP9_COMP_REF_COUNT_START+VP9_COMP_REF_COUNT_SIZE) -#define VP9_SINGLE_REF_COUNT_SIZE (10*2) -#define VP9_TX_MODE_COUNT_START \ - (VP9_SINGLE_REF_COUNT_START+VP9_SINGLE_REF_COUNT_SIZE) -#define VP9_TX_MODE_COUNT_SIZE (12*2) -#define VP9_SKIP_COUNT_START \ - (VP9_TX_MODE_COUNT_START+VP9_TX_MODE_COUNT_SIZE) -#define VP9_SKIP_COUNT_SIZE (3*2) -#define VP9_MV_SIGN_0_COUNT_START \ - (VP9_SKIP_COUNT_START+VP9_SKIP_COUNT_SIZE) -#define VP9_MV_SIGN_0_COUNT_SIZE (1*2) -#define VP9_MV_SIGN_1_COUNT_START \ - (VP9_MV_SIGN_0_COUNT_START+VP9_MV_SIGN_0_COUNT_SIZE) -#define VP9_MV_SIGN_1_COUNT_SIZE (1*2) -#define VP9_MV_BITS_0_COUNT_START \ - (VP9_MV_SIGN_1_COUNT_START+VP9_MV_SIGN_1_COUNT_SIZE) -#define VP9_MV_BITS_0_COUNT_SIZE (10*2) -#define VP9_MV_BITS_1_COUNT_START \ - (VP9_MV_BITS_0_COUNT_START+VP9_MV_BITS_0_COUNT_SIZE) -#define VP9_MV_BITS_1_COUNT_SIZE (10*2) -#define VP9_MV_CLASS0_HP_0_COUNT_START \ - (VP9_MV_BITS_1_COUNT_START+VP9_MV_BITS_1_COUNT_SIZE) -#define VP9_MV_CLASS0_HP_0_COUNT_SIZE (2*2) -#define VP9_MV_CLASS0_HP_1_COUNT_START \ - (VP9_MV_CLASS0_HP_0_COUNT_START+VP9_MV_CLASS0_HP_0_COUNT_SIZE) -#define VP9_MV_CLASS0_HP_1_COUNT_SIZE (2*2) -/* Start merge_tree*/ -#define VP9_INTER_MODE_COUNT_START \ - (VP9_MV_CLASS0_HP_1_COUNT_START+VP9_MV_CLASS0_HP_1_COUNT_SIZE) -#define VP9_INTER_MODE_COUNT_SIZE (7*4) -#define VP9_IF_Y_MODE_COUNT_START \ - (VP9_INTER_MODE_COUNT_START+VP9_INTER_MODE_COUNT_SIZE) -#define VP9_IF_Y_MODE_COUNT_SIZE (10*4) -#define VP9_IF_UV_MODE_COUNT_START \ - (VP9_IF_Y_MODE_COUNT_START+VP9_IF_Y_MODE_COUNT_SIZE) -#define VP9_IF_UV_MODE_COUNT_SIZE (10*10) -#define VP9_PARTITION_P_COUNT_START \ - (VP9_IF_UV_MODE_COUNT_START+VP9_IF_UV_MODE_COUNT_SIZE) -#define VP9_PARTITION_P_COUNT_SIZE (4*4*4) -#define VP9_INTERP_COUNT_START \ - (VP9_PARTITION_P_COUNT_START+VP9_PARTITION_P_COUNT_SIZE) -#define VP9_INTERP_COUNT_SIZE (4*3) -#define VP9_MV_JOINTS_COUNT_START \ - (VP9_INTERP_COUNT_START+VP9_INTERP_COUNT_SIZE) -#define VP9_MV_JOINTS_COUNT_SIZE (1 * 4) -#define VP9_MV_CLASSES_0_COUNT_START \ - (VP9_MV_JOINTS_COUNT_START+VP9_MV_JOINTS_COUNT_SIZE) -#define VP9_MV_CLASSES_0_COUNT_SIZE (1*11) -#define VP9_MV_CLASS0_0_COUNT_START \ - (VP9_MV_CLASSES_0_COUNT_START+VP9_MV_CLASSES_0_COUNT_SIZE) -#define VP9_MV_CLASS0_0_COUNT_SIZE (1*2) -#define VP9_MV_CLASSES_1_COUNT_START \ - (VP9_MV_CLASS0_0_COUNT_START+VP9_MV_CLASS0_0_COUNT_SIZE) -#define VP9_MV_CLASSES_1_COUNT_SIZE (1*11) -#define VP9_MV_CLASS0_1_COUNT_START \ - (VP9_MV_CLASSES_1_COUNT_START+VP9_MV_CLASSES_1_COUNT_SIZE) -#define VP9_MV_CLASS0_1_COUNT_SIZE (1*2) -#define VP9_MV_CLASS0_FP_0_COUNT_START \ - (VP9_MV_CLASS0_1_COUNT_START+VP9_MV_CLASS0_1_COUNT_SIZE) -#define VP9_MV_CLASS0_FP_0_COUNT_SIZE (3*4) -#define VP9_MV_CLASS0_FP_1_COUNT_START \ - (VP9_MV_CLASS0_FP_0_COUNT_START+VP9_MV_CLASS0_FP_0_COUNT_SIZE) -#define VP9_MV_CLASS0_FP_1_COUNT_SIZE (3*4) - - -#define DC_PRED 0 /* Average of above and left pixels*/ -#define V_PRED 1 /* Vertical*/ -#define H_PRED 2 /* Horizontal*/ -#define D45_PRED 3 /*Directional 45 deg = round(arctan(1/1) * 180/pi)*/ -#define D135_PRED 4 /* Directional 135 deg = 180 - 45*/ -#define D117_PRED 5 /* Directional 117 deg = 180 - 63*/ -#define D153_PRED 6 /* Directional 153 deg = 180 - 27*/ -#define D207_PRED 7 /* Directional 207 deg = 180 + 27*/ -#define D63_PRED 8 /*Directional 63 deg = round(arctan(2/1) * 180/pi)*/ -#define TM_PRED 9 /*True-motion*/ - -int clip_prob(int p) -{ - return (p > 255) ? 255 : (p < 1) ? 1 : p; -} - -#define ROUND_POWER_OF_TWO(value, n) \ - (((value) + (1 << ((n) - 1))) >> (n)) - -#define MODE_MV_COUNT_SAT 20 -static const int count_to_update_factor[MODE_MV_COUNT_SAT + 1] = { - 0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, - 70, 76, 83, 89, 96, 102, 108, 115, 121, 128 -}; - -void vp9_tree_merge_probs(unsigned int *prev_prob, unsigned int *cur_prob, - int coef_node_start, int tree_left, int tree_right, int tree_i, - int node) { - - int prob_32, prob_res, prob_shift; - int pre_prob, new_prob; - int den, m_count, get_prob, factor; - - prob_32 = prev_prob[coef_node_start / 4 * 2]; - prob_res = coef_node_start & 3; - prob_shift = prob_res * 8; - pre_prob = (prob_32 >> prob_shift) & 0xff; - - den = tree_left + tree_right; - - if (den == 0) - new_prob = pre_prob; - else { - m_count = (den < MODE_MV_COUNT_SAT) ? - den : MODE_MV_COUNT_SAT; - get_prob = clip_prob( - div_r32(((int64_t)tree_left * 256 + (den >> 1)), - den)); - /*weighted_prob*/ - factor = count_to_update_factor[m_count]; - new_prob = ROUND_POWER_OF_TWO(pre_prob * (256 - factor) - + get_prob * factor, 8); - } - cur_prob[coef_node_start / 4 * 2] = (cur_prob[coef_node_start / 4 * 2] - & (~(0xff << prob_shift))) | (new_prob << prob_shift); - - /*pr_info(" - [%d][%d] 0x%02X --> 0x%02X (0x%X 0x%X) (%X)\n", - *tree_i, node, pre_prob, new_prob, tree_left, tree_right, - *cur_prob[coef_node_start/4*2]); - */ -} - - -/*void adapt_coef_probs(void)*/ -void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, - unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count) -{ - /* 80 * 64bits = 0xF00 ( use 0x1000 4K bytes) - *unsigned int prev_prob[496*2]; - *unsigned int cur_prob[496*2]; - *0x300 * 128bits = 0x3000 (32K Bytes) - *unsigned int count[0x300*4]; - */ - - int tx_size, coef_tx_size_start, coef_count_tx_size_start; - int plane, coef_plane_start, coef_count_plane_start; - int type, coef_type_start, coef_count_type_start; - int band, coef_band_start, coef_count_band_start; - int cxt_num; - int cxt, coef_cxt_start, coef_count_cxt_start; - int node, coef_node_start, coef_count_node_start; - - int tree_i, tree_left, tree_right; - int mvd_i; - - int count_sat = 24; - /*int update_factor = 112;*/ /*If COEF_MAX_UPDATE_FACTOR_AFTER_KEY, - *use 128 - */ - /* If COEF_MAX_UPDATE_FACTOR_AFTER_KEY, use 128*/ - /*int update_factor = (pic_count == 1) ? 128 : 112;*/ - int update_factor = cur_kf ? 112 : - prev_kf ? 128 : 112; - - int prob_32; - int prob_res; - int prob_shift; - int pre_prob; - - int num, den; - int get_prob; - int m_count; - int factor; - - int new_prob; - - if (debug & VP9_DEBUG_MERGE) - pr_info - ("\n ##adapt_coef_probs (pre_fc : %d ,prev_kf : %d,cur_kf : %d)##\n\n", - pre_fc, prev_kf, cur_kf); - - /*adapt_coef_probs*/ - for (tx_size = 0; tx_size < 4; tx_size++) { - coef_tx_size_start = VP9_COEF_START - + tx_size * 4 * VP9_COEF_SIZE_ONE_SET; - coef_count_tx_size_start = VP9_COEF_COUNT_START - + tx_size * 4 * VP9_COEF_COUNT_SIZE_ONE_SET; - coef_plane_start = coef_tx_size_start; - coef_count_plane_start = coef_count_tx_size_start; - for (plane = 0; plane < 2; plane++) { - coef_type_start = coef_plane_start; - coef_count_type_start = coef_count_plane_start; - for (type = 0; type < 2; type++) { - coef_band_start = coef_type_start; - coef_count_band_start = coef_count_type_start; - for (band = 0; band < 6; band++) { - if (band == 0) - cxt_num = 3; - else - cxt_num = 6; - coef_cxt_start = coef_band_start; - coef_count_cxt_start = - coef_count_band_start; - for (cxt = 0; cxt < cxt_num; cxt++) { - const int n0 = - count[coef_count_cxt_start]; - const int n1 = - count[coef_count_cxt_start + 1]; - const int n2 = - count[coef_count_cxt_start + 2]; - const int neob = - count[coef_count_cxt_start + 3]; - const int nneob = - count[coef_count_cxt_start + 4]; - const unsigned int - branch_ct[3][2] = { - { neob, nneob }, - { n0, n1 + n2 }, - { n1, n2 } - }; - coef_node_start = - coef_cxt_start; - for - (node = 0; node < 3; node++) { - prob_32 = - prev_prob[ - coef_node_start - / 4 * 2]; - prob_res = - coef_node_start & 3; - prob_shift = - prob_res * 8; - pre_prob = - (prob_32 >> prob_shift) - & 0xff; - - /*get_binary_prob*/ - num = - branch_ct[node][0]; - den = - branch_ct[node][0] + - branch_ct[node][1]; - m_count = (den < - count_sat) - ? den : count_sat; - - get_prob = - (den == 0) ? 128u : - clip_prob( - div_r32(((int64_t) - num * 256 - + (den >> 1)), - den)); - - factor = - update_factor * m_count - / count_sat; - new_prob = - ROUND_POWER_OF_TWO - (pre_prob * - (256 - factor) + - get_prob * factor, 8); - - cur_prob[coef_node_start - / 4 * 2] = - (cur_prob - [coef_node_start - / 4 * 2] & (~(0xff << - prob_shift))) | - (new_prob << - prob_shift); - - coef_node_start += 1; - } - - coef_cxt_start = - coef_cxt_start + 3; - coef_count_cxt_start = - coef_count_cxt_start - + 5; - } - if (band == 0) { - coef_band_start += 10; - coef_count_band_start += 15; - } else { - coef_band_start += 18; - coef_count_band_start += 30; - } - } - coef_type_start += VP9_COEF_SIZE_ONE_SET; - coef_count_type_start += - VP9_COEF_COUNT_SIZE_ONE_SET; - } - coef_plane_start += 2 * VP9_COEF_SIZE_ONE_SET; - coef_count_plane_start += - 2 * VP9_COEF_COUNT_SIZE_ONE_SET; - } - } - - if (cur_kf == 0) { - /*mode_mv_merge_probs - merge_intra_inter_prob*/ - for (coef_count_node_start = VP9_INTRA_INTER_COUNT_START; - coef_count_node_start < (VP9_MV_CLASS0_HP_1_COUNT_START + - VP9_MV_CLASS0_HP_1_COUNT_SIZE); coef_count_node_start += 2) { - - if (coef_count_node_start == - VP9_INTRA_INTER_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_intra_inter_prob\n"); - coef_node_start = VP9_INTRA_INTER_START; - } else if (coef_count_node_start == - VP9_COMP_INTER_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_comp_inter_prob\n"); - coef_node_start = VP9_COMP_INTER_START; - } - /* - *else if (coef_count_node_start == - * VP9_COMP_REF_COUNT_START) { - * pr_info(" # merge_comp_inter_prob\n"); - * coef_node_start = VP9_COMP_REF_START; - *} - *else if (coef_count_node_start == - * VP9_SINGLE_REF_COUNT_START) { - * pr_info(" # merge_comp_inter_prob\n"); - * coef_node_start = VP9_SINGLE_REF_START; - *} - */ - else if (coef_count_node_start == - VP9_TX_MODE_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_tx_mode_probs\n"); - coef_node_start = VP9_TX_MODE_START; - } else if (coef_count_node_start == - VP9_SKIP_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_skip_probs\n"); - coef_node_start = VP9_SKIP_START; - } else if (coef_count_node_start == - VP9_MV_SIGN_0_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_sign_0\n"); - coef_node_start = VP9_MV_SIGN_0_START; - } else if (coef_count_node_start == - VP9_MV_SIGN_1_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_sign_1\n"); - coef_node_start = VP9_MV_SIGN_1_START; - } else if (coef_count_node_start == - VP9_MV_BITS_0_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_bits_0\n"); - coef_node_start = VP9_MV_BITS_0_START; - } else if (coef_count_node_start == - VP9_MV_BITS_1_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_bits_1\n"); - coef_node_start = VP9_MV_BITS_1_START; - } else if (coef_count_node_start == - VP9_MV_CLASS0_HP_0_COUNT_START) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_class0_hp\n"); - coef_node_start = VP9_MV_CLASS0_HP_0_START; - } - - - den = count[coef_count_node_start] + - count[coef_count_node_start + 1]; - - prob_32 = prev_prob[coef_node_start / 4 * 2]; - prob_res = coef_node_start & 3; - prob_shift = prob_res * 8; - pre_prob = (prob_32 >> prob_shift) & 0xff; - - if (den == 0) - new_prob = pre_prob; - else { - m_count = (den < MODE_MV_COUNT_SAT) ? - den : MODE_MV_COUNT_SAT; - get_prob = - clip_prob( - div_r32(((int64_t)count[coef_count_node_start] - * 256 + (den >> 1)), - den)); - /*weighted_prob*/ - factor = count_to_update_factor[m_count]; - new_prob = - ROUND_POWER_OF_TWO(pre_prob * (256 - factor) - + get_prob * factor, 8); - } - cur_prob[coef_node_start / 4 * 2] = - (cur_prob[coef_node_start / 4 * 2] & - (~(0xff << prob_shift))) - | (new_prob << prob_shift); - - coef_node_start = coef_node_start + 1; - } - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_inter_mode_tree\n"); - coef_node_start = VP9_INTER_MODE_START; - coef_count_node_start = VP9_INTER_MODE_COUNT_START; - for (tree_i = 0; tree_i < 7; tree_i++) { - for (node = 0; node < 3; node++) { - switch (node) { - case 2: - tree_left = - count[coef_count_node_start + 1]; - tree_right = - count[coef_count_node_start + 3]; - break; - case 1: - tree_left = - count[coef_count_node_start + 0]; - tree_right = - count[coef_count_node_start + 1] - + count[coef_count_node_start + 3]; - break; - default: - tree_left = - count[coef_count_node_start + 2]; - tree_right = - count[coef_count_node_start + 0] - + count[coef_count_node_start + 1] - + count[coef_count_node_start + 3]; - break; - - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, tree_left, tree_right, - tree_i, node); - - coef_node_start = coef_node_start + 1; - } - coef_count_node_start = coef_count_node_start + 4; - } - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_intra_mode_tree\n"); - coef_node_start = VP9_IF_Y_MODE_START; - coef_count_node_start = VP9_IF_Y_MODE_COUNT_START; - for (tree_i = 0; tree_i < 14; tree_i++) { - for (node = 0; node < 9; node++) { - switch (node) { - case 8: - tree_left = - count[coef_count_node_start+D153_PRED]; - tree_right = - count[coef_count_node_start+D207_PRED]; - break; - case 7: - tree_left = - count[coef_count_node_start+D63_PRED]; - tree_right = - count[coef_count_node_start+D207_PRED] + - count[coef_count_node_start+D153_PRED]; - break; - case 6: - tree_left = - count[coef_count_node_start + D45_PRED]; - tree_right = - count[coef_count_node_start+D207_PRED] + - count[coef_count_node_start+D153_PRED] + - count[coef_count_node_start+D63_PRED]; - break; - case 5: - tree_left = - count[coef_count_node_start+D135_PRED]; - tree_right = - count[coef_count_node_start+D117_PRED]; - break; - case 4: - tree_left = - count[coef_count_node_start+H_PRED]; - tree_right = - count[coef_count_node_start+D117_PRED] + - count[coef_count_node_start+D135_PRED]; - break; - case 3: - tree_left = - count[coef_count_node_start+H_PRED] + - count[coef_count_node_start+D117_PRED] + - count[coef_count_node_start+D135_PRED]; - tree_right = - count[coef_count_node_start+D45_PRED] + - count[coef_count_node_start+D207_PRED] + - count[coef_count_node_start+D153_PRED] + - count[coef_count_node_start+D63_PRED]; - break; - case 2: - tree_left = - count[coef_count_node_start+V_PRED]; - tree_right = - count[coef_count_node_start+H_PRED] + - count[coef_count_node_start+D117_PRED] + - count[coef_count_node_start+D135_PRED] + - count[coef_count_node_start+D45_PRED] + - count[coef_count_node_start+D207_PRED] + - count[coef_count_node_start+D153_PRED] + - count[coef_count_node_start+D63_PRED]; - break; - case 1: - tree_left = - count[coef_count_node_start+TM_PRED]; - tree_right = - count[coef_count_node_start+V_PRED] + - count[coef_count_node_start+H_PRED] + - count[coef_count_node_start+D117_PRED] + - count[coef_count_node_start+D135_PRED] + - count[coef_count_node_start+D45_PRED] + - count[coef_count_node_start+D207_PRED] + - count[coef_count_node_start+D153_PRED] + - count[coef_count_node_start+D63_PRED]; - break; - default: - tree_left = - count[coef_count_node_start+DC_PRED]; - tree_right = - count[coef_count_node_start+TM_PRED] + - count[coef_count_node_start+V_PRED] + - count[coef_count_node_start+H_PRED] + - count[coef_count_node_start+D117_PRED] + - count[coef_count_node_start+D135_PRED] + - count[coef_count_node_start+D45_PRED] + - count[coef_count_node_start+D207_PRED] + - count[coef_count_node_start+D153_PRED] + - count[coef_count_node_start+D63_PRED]; - break; - - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, tree_left, tree_right, - tree_i, node); - - coef_node_start = coef_node_start + 1; - } - coef_count_node_start = coef_count_node_start + 10; - } - - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_partition_tree\n"); - coef_node_start = VP9_PARTITION_P_START; - coef_count_node_start = VP9_PARTITION_P_COUNT_START; - for (tree_i = 0; tree_i < 16; tree_i++) { - for (node = 0; node < 3; node++) { - switch (node) { - case 2: - tree_left = - count[coef_count_node_start + 2]; - tree_right = - count[coef_count_node_start + 3]; - break; - case 1: - tree_left = - count[coef_count_node_start + 1]; - tree_right = - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3]; - break; - default: - tree_left = - count[coef_count_node_start + 0]; - tree_right = - count[coef_count_node_start + 1] + - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3]; - break; - - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, - tree_left, tree_right, tree_i, node); - - coef_node_start = coef_node_start + 1; - } - coef_count_node_start = coef_count_node_start + 4; - } - - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_switchable_interp_tree\n"); - coef_node_start = VP9_INTERP_START; - coef_count_node_start = VP9_INTERP_COUNT_START; - for (tree_i = 0; tree_i < 4; tree_i++) { - for (node = 0; node < 2; node++) { - switch (node) { - case 1: - tree_left = - count[coef_count_node_start + 1]; - tree_right = - count[coef_count_node_start + 2]; - break; - default: - tree_left = - count[coef_count_node_start + 0]; - tree_right = - count[coef_count_node_start + 1] + - count[coef_count_node_start + 2]; - break; - - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, - tree_left, tree_right, tree_i, node); - - coef_node_start = coef_node_start + 1; - } - coef_count_node_start = coef_count_node_start + 3; - } - - if (debug & VP9_DEBUG_MERGE) - pr_info("# merge_vp9_mv_joint_tree\n"); - coef_node_start = VP9_MV_JOINTS_START; - coef_count_node_start = VP9_MV_JOINTS_COUNT_START; - for (tree_i = 0; tree_i < 1; tree_i++) { - for (node = 0; node < 3; node++) { - switch (node) { - case 2: - tree_left = - count[coef_count_node_start + 2]; - tree_right = - count[coef_count_node_start + 3]; - break; - case 1: - tree_left = - count[coef_count_node_start + 1]; - tree_right = - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3]; - break; - default: - tree_left = - count[coef_count_node_start + 0]; - tree_right = - count[coef_count_node_start + 1] + - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3]; - break; - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, - tree_left, tree_right, tree_i, node); - - coef_node_start = coef_node_start + 1; - } - coef_count_node_start = coef_count_node_start + 4; - } - - for (mvd_i = 0; mvd_i < 2; mvd_i++) { - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_mv_class_tree [%d] -\n", mvd_i); - coef_node_start = - mvd_i ? VP9_MV_CLASSES_1_START : VP9_MV_CLASSES_0_START; - coef_count_node_start = - mvd_i ? VP9_MV_CLASSES_1_COUNT_START - : VP9_MV_CLASSES_0_COUNT_START; - tree_i = 0; - for (node = 0; node < 10; node++) { - switch (node) { - case 9: - tree_left = - count[coef_count_node_start + 9]; - tree_right = - count[coef_count_node_start + 10]; - break; - case 8: - tree_left = - count[coef_count_node_start + 7]; - tree_right = - count[coef_count_node_start + 8]; - break; - case 7: - tree_left = - count[coef_count_node_start + 7] + - count[coef_count_node_start + 8]; - tree_right = - count[coef_count_node_start + 9] + - count[coef_count_node_start + 10]; - break; - case 6: - tree_left = - count[coef_count_node_start + 6]; - tree_right = - count[coef_count_node_start + 7] + - count[coef_count_node_start + 8] + - count[coef_count_node_start + 9] + - count[coef_count_node_start + 10]; - break; - case 5: - tree_left = - count[coef_count_node_start + 4]; - tree_right = - count[coef_count_node_start + 5]; - break; - case 4: - tree_left = - count[coef_count_node_start + 4] + - count[coef_count_node_start + 5]; - tree_right = - count[coef_count_node_start + 6] + - count[coef_count_node_start + 7] + - count[coef_count_node_start + 8] + - count[coef_count_node_start + 9] + - count[coef_count_node_start + 10]; - break; - case 3: - tree_left = - count[coef_count_node_start + 2]; - tree_right = - count[coef_count_node_start + 3]; - break; - case 2: - tree_left = - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3]; - tree_right = - count[coef_count_node_start + 4] + - count[coef_count_node_start + 5] + - count[coef_count_node_start + 6] + - count[coef_count_node_start + 7] + - count[coef_count_node_start + 8] + - count[coef_count_node_start + 9] + - count[coef_count_node_start + 10]; - break; - case 1: - tree_left = - count[coef_count_node_start + 1]; - tree_right = - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3] + - count[coef_count_node_start + 4] + - count[coef_count_node_start + 5] + - count[coef_count_node_start + 6] + - count[coef_count_node_start + 7] + - count[coef_count_node_start + 8] + - count[coef_count_node_start + 9] + - count[coef_count_node_start + 10]; - break; - default: - tree_left = - count[coef_count_node_start + 0]; - tree_right = - count[coef_count_node_start + 1] + - count[coef_count_node_start + 2] + - count[coef_count_node_start + 3] + - count[coef_count_node_start + 4] + - count[coef_count_node_start + 5] + - count[coef_count_node_start + 6] + - count[coef_count_node_start + 7] + - count[coef_count_node_start + 8] + - count[coef_count_node_start + 9] + - count[coef_count_node_start + 10]; - break; - - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, tree_left, tree_right, - tree_i, node); - - coef_node_start = coef_node_start + 1; - } - - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_mv_class0_tree [%d] -\n", mvd_i); - coef_node_start = - mvd_i ? VP9_MV_CLASS0_1_START : VP9_MV_CLASS0_0_START; - coef_count_node_start = - mvd_i ? VP9_MV_CLASS0_1_COUNT_START : - VP9_MV_CLASS0_0_COUNT_START; - tree_i = 0; - node = 0; - tree_left = count[coef_count_node_start + 0]; - tree_right = count[coef_count_node_start + 1]; - - vp9_tree_merge_probs(prev_prob, cur_prob, coef_node_start, - tree_left, tree_right, tree_i, node); - if (debug & VP9_DEBUG_MERGE) - pr_info(" # merge_vp9_mv_fp_tree_class0_fp [%d] -\n", - mvd_i); - coef_node_start = - mvd_i ? VP9_MV_CLASS0_FP_1_START : - VP9_MV_CLASS0_FP_0_START; - coef_count_node_start = - mvd_i ? VP9_MV_CLASS0_FP_1_COUNT_START : - VP9_MV_CLASS0_FP_0_COUNT_START; - for (tree_i = 0; tree_i < 3; tree_i++) { - for (node = 0; node < 3; node++) { - switch (node) { - case 2: - tree_left = - count[coef_count_node_start + 2]; - tree_right = - count[coef_count_node_start + 3]; - break; - case 1: - tree_left = - count[coef_count_node_start + 1]; - tree_right = - count[coef_count_node_start + 2] - + count[coef_count_node_start + 3]; - break; - default: - tree_left = - count[coef_count_node_start + 0]; - tree_right = - count[coef_count_node_start + 1] - + count[coef_count_node_start + 2] - + count[coef_count_node_start + 3]; - break; - - } - - vp9_tree_merge_probs(prev_prob, cur_prob, - coef_node_start, tree_left, tree_right, - tree_i, node); - - coef_node_start = coef_node_start + 1; - } - coef_count_node_start = coef_count_node_start + 4; - } - - } /* for mvd_i (mvd_y or mvd_x)*/ -} - -} - - -static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) -{ -#ifndef MV_USE_FIXED_BUF - dealloc_mv_bufs(pbi); -#endif - if (pbi->mmu_box) - decoder_mmu_box_free(pbi->mmu_box); - pbi->mmu_box = NULL; - - if (pbi->bmmu_box) - decoder_bmmu_box_free(pbi->bmmu_box); - pbi->bmmu_box = NULL; -} - - -static int config_pic(struct VP9Decoder_s *pbi, - struct PIC_BUFFER_CONFIG_s *pic_config) -{ - int ret = -1; - int i; - int pic_width = pbi->init_pic_w; - int pic_height = pbi->init_pic_h; - int lcu_size = 64; /*fixed 64*/ - int pic_width_64 = (pic_width + 63) & (~0x3f); - int pic_height_32 = (pic_height + 31) & (~0x1f); - int pic_width_lcu = (pic_width_64 % lcu_size) ? - pic_width_64 / lcu_size + 1 - : pic_width_64 / lcu_size; - int pic_height_lcu = (pic_height_32 % lcu_size) ? - pic_height_32 / lcu_size + 1 - : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; -#ifdef MV_USE_FIXED_BUF - u32 mpred_mv_end = pbi->work_space_buf->mpred_mv.buf_start + - pbi->work_space_buf->mpred_mv.buf_size; -#endif - u32 y_adr = 0; - int buf_size = 0; - - int losless_comp_header_size = - compute_losless_comp_header_size(pic_width, - pic_height); - int losless_comp_body_size = compute_losless_comp_body_size(pic_width, - pic_height, buf_alloc_depth == 10); - int mc_buffer_size = losless_comp_header_size + losless_comp_body_size; - int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16; - int mc_buffer_size_u_v = 0; - int mc_buffer_size_u_v_h = 0; - int dw_mode = get_double_write_mode_init(pbi); - - pbi->lcu_total = lcu_total; - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(pbi, dw_mode); - int pic_height_dw = pic_height / - get_double_write_ratio(pbi, dw_mode); - - int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f); - int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f); - int pic_width_lcu_dw = (pic_width_64_dw % lcu_size) ? - pic_width_64_dw / lcu_size + 1 - : pic_width_64_dw / lcu_size; - int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ? - pic_height_32_dw / lcu_size + 1 - : pic_height_32_dw / lcu_size; - int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; - mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; - mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - buf_size = ((mc_buffer_size_u_v_h << 16) * 3); - buf_size = ((buf_size + 0xffff) >> 16) << 16; - } - - if (mc_buffer_size & 0xffff) /*64k alignment*/ - mc_buffer_size_h += 1; - if ((!pbi->mmu_enable) && ((dw_mode & 0x10) == 0)) - buf_size += (mc_buffer_size_h << 16); - - - if (pbi->mmu_enable) { - pic_config->header_adr = decoder_bmmu_box_get_phy_addr( - pbi->bmmu_box, HEADER_BUFFER_IDX(pic_config->index)); - - if (debug & VP9_DEBUG_BUFMGR_MORE) { - pr_info("MMU header_adr %d: %ld\n", - pic_config->index, pic_config->header_adr); - } - } - - i = pic_config->index; -#ifdef MV_USE_FIXED_BUF - if ((pbi->work_space_buf->mpred_mv.buf_start + - (((i + 1) * lcu_total) * MV_MEM_UNIT)) - <= mpred_mv_end - ) { -#endif - - if (buf_size > 0) { - ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, - VF_BUFFER_IDX(i), - buf_size, DRIVER_NAME, - &pic_config->cma_alloc_addr); - if (ret < 0) { - pr_info( - "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", - VF_BUFFER_IDX(i), - buf_size - ); - return ret; - } - - if (pic_config->cma_alloc_addr) - y_adr = pic_config->cma_alloc_addr; - else { - pr_info( - "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n", - VF_BUFFER_IDX(i), - buf_size - ); - return -1; - } - } - { - /*ensure get_pic_by_POC() - not get the buffer not decoded*/ - pic_config->BUF_index = i; - pic_config->lcu_total = lcu_total; - - pic_config->comp_body_size = losless_comp_body_size; - pic_config->buf_size = buf_size; - - pic_config->mc_canvas_y = pic_config->index; - pic_config->mc_canvas_u_v = pic_config->index; - if (dw_mode & 0x10) { - pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); - - pic_config->mc_canvas_y = - (pic_config->index << 1); - pic_config->mc_canvas_u_v = - (pic_config->index << 1) + 1; - } else if (dw_mode) { - pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = pic_config->dw_y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); - } -#ifdef MV_USE_FIXED_BUF - pic_config->mpred_mv_wr_start_addr = - pbi->work_space_buf->mpred_mv.buf_start + - ((pic_config->index * lcu_total) - * MV_MEM_UNIT); -#endif - if (debug) { - pr_info - ("%s index %d BUF_index %d ", - __func__, pic_config->index, - pic_config->BUF_index); - pr_info - ("comp_body_size %x comp_buf_size %x ", - pic_config->comp_body_size, - pic_config->buf_size); - pr_info - ("mpred_mv_wr_start_adr %ld\n", - pic_config->mpred_mv_wr_start_addr); - pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n", - pic_config->dw_y_adr, - pic_config->dw_u_v_adr); - } - ret = 0; - } -#ifdef MV_USE_FIXED_BUF - } -#endif - return ret; -} - -static int is_oversize(int w, int h) -{ - int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? - MAX_SIZE_8K : MAX_SIZE_4K; - - if (w < 0 || h < 0) - return true; - - if (h != 0 && (w > max / h)) - return true; - - return false; -} - -static int vvp9_mmu_compress_header_size(struct VP9Decoder_s *pbi) -{ - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h)) - return (MMU_COMPRESS_8K_HEADER_SIZE); - - return (MMU_COMPRESS_HEADER_SIZE); -} - -/*#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)*/ -static int vvp9_frame_mmu_map_size(struct VP9Decoder_s *pbi) -{ - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h)) - return (MAX_FRAME_8K_NUM * 4); - - return (MAX_FRAME_4K_NUM * 4); -} - - -static void init_pic_list(struct VP9Decoder_s *pbi) -{ - int i; - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *pic_config; - u32 header_size; - struct vdec_s *vdec = hw_to_vdec(pbi); - if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { - header_size = vvp9_mmu_compress_header_size(pbi); - /*alloc VP9 compress header first*/ - for (i = 0; i < pbi->used_buf_num; i++) { - unsigned long buf_addr; - if (decoder_bmmu_box_alloc_buf_phy - (pbi->bmmu_box, - HEADER_BUFFER_IDX(i), header_size, - DRIVER_HEADER_NAME, - &buf_addr) < 0) { - pr_info("%s malloc compress header failed %d\n", - DRIVER_HEADER_NAME, i); - pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; - return; - } - } - } - for (i = 0; i < pbi->used_buf_num; i++) { - pic_config = &cm->buffer_pool->frame_bufs[i].buf; - pic_config->index = i; - pic_config->BUF_index = -1; - pic_config->mv_buf_index = -1; - if (vdec->parallel_dec == 1) { - pic_config->y_canvas_index = -1; - pic_config->uv_canvas_index = -1; - } - if (config_pic(pbi, pic_config) < 0) { - if (debug) - pr_info("Config_pic %d fail\n", - pic_config->index); - pic_config->index = -1; - break; - } - pic_config->y_crop_width = pbi->init_pic_w; - pic_config->y_crop_height = pbi->init_pic_h; - pic_config->double_write_mode = get_double_write_mode(pbi); - if (pic_config->double_write_mode) { - set_canvas(pbi, pic_config); - } - } - for (; i < pbi->used_buf_num; i++) { - pic_config = &cm->buffer_pool->frame_bufs[i].buf; - pic_config->index = -1; - pic_config->BUF_index = -1; - pic_config->mv_buf_index = -1; - if (vdec->parallel_dec == 1) { - pic_config->y_canvas_index = -1; - pic_config->uv_canvas_index = -1; - } - } - pr_info("%s ok, used_buf_num = %d\n", - __func__, pbi->used_buf_num); - -} - -static void init_pic_list_hw(struct VP9Decoder_s *pbi) -{ - int i; - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *pic_config; - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, - (0x1 << 1) | (0x1 << 2)); - - - for (i = 0; i < pbi->used_buf_num; i++) { - pic_config = &cm->buffer_pool->frame_bufs[i].buf; - if (pic_config->index < 0) - break; - - if (pbi->mmu_enable && ((pic_config->double_write_mode & 0x10) == 0)) { - - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - pic_config->header_adr >> 5); - } else { - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - * pic_config->mc_y_adr - * | (pic_config->mc_canvas_y << 8) | 0x1); - */ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - pic_config->dw_y_adr >> 5); - } -#ifndef LOSLESS_COMPRESS_MODE - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - * pic_config->mc_u_v_adr - * | (pic_config->mc_canvas_u_v << 8)| 0x1); - */ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - pic_config->header_adr >> 5); -#else - if (pic_config->double_write_mode & 0x10) { - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - pic_config->dw_u_v_adr >> 5); - } -#endif - } - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); - - /*Zero out canvas registers in IPP -- avoid simulation X*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 1); - for (i = 0; i < 32; i++) - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); -} - - -static void dump_pic_list(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *pic_config; - int i; - for (i = 0; i < FRAME_BUFFERS; i++) { - pic_config = &cm->buffer_pool->frame_bufs[i].buf; - vp9_print(pbi, 0, - "Buf(%d) index %d mv_buf_index %d ref_count %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n", - i, - pic_config->index, -#ifndef MV_USE_FIXED_BUF - pic_config->mv_buf_index, -#else - -1, -#endif - cm->buffer_pool-> - frame_bufs[i].ref_count, - pic_config->vf_ref, - pic_config->decode_idx, - pic_config->slice_type, - pic_config->y_crop_width, - pic_config->y_crop_height, - pic_config->cma_alloc_addr - ); - } - return; -} - -static int config_pic_size(struct VP9Decoder_s *pbi, unsigned short bit_depth) -{ -#ifdef LOSLESS_COMPRESS_MODE - unsigned int data32; -#endif - int losless_comp_header_size, losless_comp_body_size; - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; - - frame_width = cur_pic_config->y_crop_width; - frame_height = cur_pic_config->y_crop_height; - cur_pic_config->bit_depth = bit_depth; - cur_pic_config->double_write_mode = get_double_write_mode(pbi); - losless_comp_header_size = - compute_losless_comp_header_size(cur_pic_config->y_crop_width, - cur_pic_config->y_crop_height); - losless_comp_body_size = - compute_losless_comp_body_size(cur_pic_config->y_crop_width, - cur_pic_config->y_crop_height, (bit_depth == VPX_BITS_10)); - cur_pic_config->comp_body_size = losless_comp_body_size; -#ifdef LOSLESS_COMPRESS_MODE - data32 = READ_VREG(HEVC_SAO_CTRL5); - if (bit_depth == VPX_BITS_10) - data32 &= ~(1 << 9); - else - data32 |= (1 << 9); - - WRITE_VREG(HEVC_SAO_CTRL5, data32); - - if (pbi->mmu_enable) { - /*bit[4] : paged_mem_mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - } else { - /*bit[3] smem mdoe*/ - if (bit_depth == VPX_BITS_10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); - else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); - } - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); - if (get_double_write_mode(pbi) & 0x10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif - return 0; -} - -static int config_mc_buffer(struct VP9Decoder_s *pbi, unsigned short bit_depth) -{ - int i; - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; - uint8_t scale_enable = 0; - - if (debug&VP9_DEBUG_BUFMGR_MORE) - pr_info("config_mc_buffer entered .....\n"); - - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (0 << 1) | 1); - for (i = 0; i < REFS_PER_FRAME; ++i) { - struct PIC_BUFFER_CONFIG_s *pic_config = cm->frame_refs[i].buf; - if (!pic_config) - continue; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic_config->mc_canvas_u_v << 16) - | (pic_config->mc_canvas_u_v << 8) - | pic_config->mc_canvas_y); - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - i, pic_config->mc_canvas_u_v, - pic_config->mc_canvas_y); - } - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (16 << 8) | (0 << 1) | 1); - for (i = 0; i < REFS_PER_FRAME; ++i) { - struct PIC_BUFFER_CONFIG_s *pic_config = cm->frame_refs[i].buf; - if (!pic_config) - continue; - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, - (pic_config->mc_canvas_u_v << 16) - | (pic_config->mc_canvas_u_v << 8) - | pic_config->mc_canvas_y); - } - - /*auto_inc start index:0 field:0*/ - WRITE_VREG(VP9D_MPP_REFINFO_TBL_ACCCONFIG, 0x1 << 2); - /*index 0:last 1:golden 2:altref*/ - for (i = 0; i < REFS_PER_FRAME; i++) { - int ref_pic_body_size; - struct PIC_BUFFER_CONFIG_s *pic_config = cm->frame_refs[i].buf; - if (!pic_config) - continue; - WRITE_VREG(VP9D_MPP_REFINFO_DATA, pic_config->y_crop_width); - WRITE_VREG(VP9D_MPP_REFINFO_DATA, pic_config->y_crop_height); - - if (pic_config->y_crop_width != cur_pic_config->y_crop_width || - pic_config->y_crop_height != cur_pic_config->y_crop_height) { - scale_enable |= (1 << i); - } - ref_pic_body_size = - compute_losless_comp_body_size(pic_config->y_crop_width, - pic_config->y_crop_height, (bit_depth == VPX_BITS_10)); - WRITE_VREG(VP9D_MPP_REFINFO_DATA, - (pic_config->y_crop_width << 14) - / cur_pic_config->y_crop_width); - WRITE_VREG(VP9D_MPP_REFINFO_DATA, - (pic_config->y_crop_height << 14) - / cur_pic_config->y_crop_height); - if (pbi->mmu_enable) - WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0); - else - WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5); - } - WRITE_VREG(VP9D_MPP_REF_SCALE_ENBL, scale_enable); - return 0; -} - -static void clear_mpred_hw(struct VP9Decoder_s *pbi) -{ - unsigned int data32; - - data32 = READ_VREG(HEVC_MPRED_CTRL4); - data32 &= (~(1 << 6)); - WRITE_VREG(HEVC_MPRED_CTRL4, data32); -} - -static void config_mpred_hw(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; - struct PIC_BUFFER_CONFIG_s *last_frame_pic_config = - &cm->prev_frame->buf; - - unsigned int data32; - int mpred_curr_lcu_x; - int mpred_curr_lcu_y; - int mpred_mv_rd_end_addr; - - - mpred_mv_rd_end_addr = last_frame_pic_config->mpred_mv_wr_start_addr - + (last_frame_pic_config->lcu_total * MV_MEM_UNIT); - - data32 = READ_VREG(HEVC_MPRED_CURR_LCU); - mpred_curr_lcu_x = data32 & 0xffff; - mpred_curr_lcu_y = (data32 >> 16) & 0xffff; - - if (debug & VP9_DEBUG_BUFMGR) - pr_info("cur pic_config index %d col pic_config index %d\n", - cur_pic_config->index, last_frame_pic_config->index); - WRITE_VREG(HEVC_MPRED_CTRL3, 0x24122412); - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, - pbi->work_space_buf->mpred_above.buf_start); - - data32 = READ_VREG(HEVC_MPRED_CTRL4); - - data32 &= (~(1 << 6)); - data32 |= (cm->use_prev_frame_mvs << 6); - WRITE_VREG(HEVC_MPRED_CTRL4, data32); - - WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, - cur_pic_config->mpred_mv_wr_start_addr); - WRITE_VREG(HEVC_MPRED_MV_WPTR, cur_pic_config->mpred_mv_wr_start_addr); - - WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, - last_frame_pic_config->mpred_mv_wr_start_addr); - WRITE_VREG(HEVC_MPRED_MV_RPTR, - last_frame_pic_config->mpred_mv_wr_start_addr); - /*data32 = ((pbi->lcu_x_num - pbi->tile_width_lcu)*MV_MEM_UNIT);*/ - /*WRITE_VREG(HEVC_MPRED_MV_WR_ROW_JUMP,data32);*/ - /*WRITE_VREG(HEVC_MPRED_MV_RD_ROW_JUMP,data32);*/ - WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, mpred_mv_rd_end_addr); - -} - -static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) -{ - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *pic_config = &cm->cur_frame->buf; - - unsigned int data32; - int lcu_size = 64; - int mc_buffer_size_u_v = - pic_config->lcu_total * lcu_size*lcu_size/2; - int mc_buffer_size_u_v_h = - (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ - - - if (get_double_write_mode(pbi)) { - WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr); - WRITE_VREG(HEVC_SAO_C_START_ADDR, pic_config->dw_u_v_adr); - WRITE_VREG(HEVC_SAO_Y_WPTR, pic_config->dw_y_adr); - WRITE_VREG(HEVC_SAO_C_WPTR, pic_config->dw_u_v_adr); - } else { - WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); - WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); - } - if (pbi->mmu_enable) - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr); - - data32 = (mc_buffer_size_u_v_h << 16) << 1; - /*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n", - * data32, mc_buffer_size_u_v_h, pic_config->lcu_total); - */ - WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); - - data32 = (mc_buffer_size_u_v_h << 16); - WRITE_VREG(HEVC_SAO_C_LENGTH, data32); - -#ifdef VP9_10B_NV21 -#ifdef DOS_PROJECT - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (mem_map_mode << 12); - data32 &= (~0x3); - data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/ - WRITE_VREG(HEVC_SAO_CTRL1, data32); - /*[23:22] dw_v1_ctrl [21:20] dw_v0_ctrl [19:18] dw_h1_ctrl - * [17:16] dw_h0_ctrl - */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /*set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (mem_map_mode << 4); - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#else - /*m8baby test1902*/ - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (mem_map_mode << 12); - data32 &= (~0xff0); - /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/ - data32 |= 0x880; /*.Big-Endian per 64-bit */ - data32 &= (~0x3); - data32 |= 0x1; /*[1]:dw_disable [0]:cm_disable*/ - WRITE_VREG(HEVC_SAO_CTRL1, data32); - /* [23:22] dw_v1_ctrl [21:20] dw_v0_ctrl - *[19:18] dw_h1_ctrl [17:16] dw_h0_ctrl - */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /* set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (mem_map_mode << 4); - data32 &= (~0xF); - data32 |= 0x8; /*Big-Endian per 64-bit*/ - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#endif -#else - data32 = READ_VREG(HEVC_SAO_CTRL1); - data32 &= (~0x3000); - data32 |= (mem_map_mode << - 12); - -/* [13:12] axi_aformat, 0-Linear, - * 1-32x32, 2-64x32 - */ - data32 &= (~0xff0); - /* data32 |= 0x670; // Big-Endian per 64-bit */ - data32 |= endian; /* Big-Endian per 64-bit */ - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { - data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ - if (get_double_write_mode(pbi) == 0) - data32 |= 0x2; /*disable double write*/ - else if (get_double_write_mode(pbi) & 0x10) - data32 |= 0x1; /*disable cm*/ - } else { /* >= G12A dw write control */ - unsigned int data; - data = READ_VREG(HEVC_DBLK_CFGB); - data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ - if (get_double_write_mode(pbi) == 0) - data |= (0x1 << 8); /*enable first write*/ - else if (get_double_write_mode(pbi) & 0x10) - data |= (0x1 << 9); /*double write only*/ - else - data |= ((0x1 << 8) |(0x1 << 9)); - WRITE_VREG(HEVC_DBLK_CFGB, data); - } - WRITE_VREG(HEVC_SAO_CTRL1, data32); - - if (get_double_write_mode(pbi) & 0x10) { - /* [23:22] dw_v1_ctrl - *[21:20] dw_v0_ctrl - *[19:18] dw_h1_ctrl - *[17:16] dw_h0_ctrl - */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - /*set them all 0 for H265_NV21 (no down-scale)*/ - data32 &= ~(0xff << 16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } else { - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 &= (~(0xff << 16)); - if (get_double_write_mode(pbi) == 2 || - get_double_write_mode(pbi) == 3) - data32 |= (0xff<<16); - else if (get_double_write_mode(pbi) == 4) - data32 |= (0x33<<16); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - - data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); - data32 &= (~0x30); - /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ - data32 |= (mem_map_mode << - 4); - data32 &= (~0xF); - data32 |= 0xf; /* valid only when double write only */ - /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ - WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); -#endif -} - -static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) -{ - struct BuffInfo_s *buf_spec = pbi->work_space_buf; - unsigned int data32; - - if (debug && pbi->init_flag == 0) - pr_info("%s %x %x %x %x %x %x %x %x %x %x %x %x\n", - __func__, - buf_spec->ipp.buf_start, - buf_spec->start_adr, - buf_spec->short_term_rps.buf_start, - buf_spec->vps.buf_start, - buf_spec->sps.buf_start, - buf_spec->pps.buf_start, - buf_spec->sao_up.buf_start, - buf_spec->swap_buf.buf_start, - buf_spec->swap_buf2.buf_start, - buf_spec->scalelut.buf_start, - buf_spec->dblk_para.buf_start, - buf_spec->dblk_data.buf_start); - - if (mask & HW_MASK_FRONT) { - if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) - WRITE_VREG(HEVC_RPM_BUFFER, (u32)pbi->rpm_phy_addr); - - WRITE_VREG(HEVC_SHORT_TERM_RPS, - buf_spec->short_term_rps.buf_start); - /*WRITE_VREG(HEVC_VPS_BUFFER, buf_spec->vps.buf_start);*/ - /*WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);*/ - WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, - buf_spec->swap_buf.buf_start); - WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, - buf_spec->swap_buf2.buf_start); - WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr); - - } - - if (mask & HW_MASK_BACK) { -#ifdef LOSLESS_COMPRESS_MODE - int losless_comp_header_size = - compute_losless_comp_header_size(pbi->init_pic_w, - pbi->init_pic_h); - int losless_comp_body_size = - compute_losless_comp_body_size(pbi->init_pic_w, - pbi->init_pic_h, buf_alloc_depth == 10); -#endif - WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, - buf_spec->ipp.buf_start); - WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); - WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - /* cfg_addr_adp*/ - WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_para.buf_start); - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("Write HEVC_DBLK_CFGE\n"); - } - /* cfg_p_addr */ - WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); - /* cfg_d_addr */ - WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - /* - * data32 = (READ_VREG(P_HEVC_DBLK_CFG3)>>8) & 0xff; // xio left offset, default is 0x40 - * data32 = data32 * 2; - * data32 = (READ_VREG(P_HEVC_DBLK_CFG3)>>16) & 0xff; // adp left offset, default is 0x040 - * data32 = data32 * 2; - */ - WRITE_VREG(HEVC_DBLK_CFG3, 0x808010); // make left storage 2 x 4k] - } -#ifdef LOSLESS_COMPRESS_MODE - if (pbi->mmu_enable) { - /*bit[4] : paged_mem_mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); - } else { - /*if(cur_pic_config->bit_depth == VPX_BITS_10) - * WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (0<<3)); - */ - /*bit[3] smem mdoe*/ - /*else WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (1<<3));*/ - /*bit[3] smem mdoe*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, - (losless_comp_body_size >> 5)); - } - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, - (losless_comp_body_size >> 5));*/ - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, - (0xff<<20) | (0xff<<10) | 0xff);*/ - /*8-bit mode */ - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); - if (get_double_write_mode(pbi) & 0x10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif - - if (pbi->mmu_enable) { - WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); - WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start - + buf_spec->mmu_vbh.buf_size/2); - /*data32 = READ_VREG(P_HEVC_SAO_CTRL9);*/ - /*data32 |= 0x1;*/ - /*WRITE_VREG(P_HEVC_SAO_CTRL9, data32);*/ - - /* use HEVC_CM_HEADER_START_ADDR */ - data32 = READ_VREG(HEVC_SAO_CTRL5); - data32 |= (1<<10); - WRITE_VREG(HEVC_SAO_CTRL5, data32); - } - - WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start); - - WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr); - /**/ - WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr); - WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr); - if (pbi->mmu_enable) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr); - else - WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr); - } - } -} - - -#ifdef VP9_LPF_LVL_UPDATE -/* - * Defines, declarations, sub-functions for vp9 de-block loop - filter Thr/Lvl table update - * - struct segmentation is for loop filter only (removed something) - * - function "vp9_loop_filter_init" and "vp9_loop_filter_frame_init" will - be instantiated in C_Entry - * - vp9_loop_filter_init run once before decoding start - * - vp9_loop_filter_frame_init run before every frame decoding start - * - set video format to VP9 is in vp9_loop_filter_init - */ -#define MAX_LOOP_FILTER 63 -#define MAX_REF_LF_DELTAS 4 -#define MAX_MODE_LF_DELTAS 2 -/*#define INTRA_FRAME 0*/ -/*#define LAST_FRAME 1*/ -/*#define MAX_REF_FRAMES 4*/ -#define SEGMENT_DELTADATA 0 -#define SEGMENT_ABSDATA 1 -#define MAX_SEGMENTS 8 -/*.#define SEG_TREE_PROBS (MAX_SEGMENTS-1)*/ -/*no use for loop filter, if this struct for common use, pls add it back*/ -/*#define PREDICTION_PROBS 3*/ -/* no use for loop filter, if this struct for common use, pls add it back*/ - -enum SEG_LVL_FEATURES { - SEG_LVL_ALT_Q = 0, /*Use alternate Quantizer ....*/ - SEG_LVL_ALT_LF = 1, /*Use alternate loop filter value...*/ - SEG_LVL_REF_FRAME = 2, /*Optional Segment reference frame*/ - SEG_LVL_SKIP = 3, /*Optional Segment (0,0) + skip mode*/ - SEG_LVL_MAX = 4 /*Number of features supported*/ -}; - -struct segmentation { - uint8_t enabled; - uint8_t update_map; - uint8_t update_data; - uint8_t abs_delta; - uint8_t temporal_update; - - /*no use for loop filter, if this struct - *for common use, pls add it back - */ - /*vp9_prob tree_probs[SEG_TREE_PROBS]; */ - /* no use for loop filter, if this struct - * for common use, pls add it back - */ - /*vp9_prob pred_probs[PREDICTION_PROBS];*/ - - int16_t feature_data[MAX_SEGMENTS][SEG_LVL_MAX]; - unsigned int feature_mask[MAX_SEGMENTS]; -}; - -struct loop_filter_thresh { - uint8_t mblim; - uint8_t lim; - uint8_t hev_thr; -}; - -struct loop_filter_info_n { - struct loop_filter_thresh lfthr[MAX_LOOP_FILTER + 1]; - uint8_t lvl[MAX_SEGMENTS][MAX_REF_FRAMES][MAX_MODE_LF_DELTAS]; -}; - -struct loopfilter { - int filter_level; - - int sharpness_level; - int last_sharpness_level; - - uint8_t mode_ref_delta_enabled; - uint8_t mode_ref_delta_update; - - /*0 = Intra, Last, GF, ARF*/ - signed char ref_deltas[MAX_REF_LF_DELTAS]; - signed char last_ref_deltas[MAX_REF_LF_DELTAS]; - - /*0 = ZERO_MV, MV*/ - signed char mode_deltas[MAX_MODE_LF_DELTAS]; - signed char last_mode_deltas[MAX_MODE_LF_DELTAS]; -}; - -static int vp9_clamp(int value, int low, int high) -{ - return value < low ? low : (value > high ? high : value); -} - -int segfeature_active(struct segmentation *seg, - int segment_id, - enum SEG_LVL_FEATURES feature_id) { - return seg->enabled && - (seg->feature_mask[segment_id] & (1 << feature_id)); -} - -int get_segdata(struct segmentation *seg, int segment_id, - enum SEG_LVL_FEATURES feature_id) { - return seg->feature_data[segment_id][feature_id]; -} - -static void vp9_update_sharpness(struct loop_filter_info_n *lfi, - int sharpness_lvl) -{ - int lvl; - /*For each possible value for the loop filter fill out limits*/ - for (lvl = 0; lvl <= MAX_LOOP_FILTER; lvl++) { - /*Set loop filter parameters that control sharpness.*/ - int block_inside_limit = lvl >> ((sharpness_lvl > 0) + - (sharpness_lvl > 4)); - - if (sharpness_lvl > 0) { - if (block_inside_limit > (9 - sharpness_lvl)) - block_inside_limit = (9 - sharpness_lvl); - } - - if (block_inside_limit < 1) - block_inside_limit = 1; - - lfi->lfthr[lvl].lim = (uint8_t)block_inside_limit; - lfi->lfthr[lvl].mblim = (uint8_t)(2 * (lvl + 2) + - block_inside_limit); - } -} - -/*instantiate this function once when decode is started*/ -void vp9_loop_filter_init(struct VP9Decoder_s *pbi) -{ - struct loop_filter_info_n *lfi = pbi->lfi; - struct loopfilter *lf = pbi->lf; - struct segmentation *seg_4lf = pbi->seg_4lf; - int i; - unsigned int data32; - - memset(lfi, 0, sizeof(struct loop_filter_info_n)); - memset(lf, 0, sizeof(struct loopfilter)); - memset(seg_4lf, 0, sizeof(struct segmentation)); - lf->sharpness_level = 0; /*init to 0 */ - /*init limits for given sharpness*/ - vp9_update_sharpness(lfi, lf->sharpness_level); - lf->last_sharpness_level = lf->sharpness_level; - /*init hev threshold const vectors (actually no use) - *for (i = 0; i <= MAX_LOOP_FILTER; i++) - * lfi->lfthr[i].hev_thr = (uint8_t)(i >> 4); - */ - - /*Write to register*/ - for (i = 0; i < 32; i++) { - unsigned int thr; - - thr = ((lfi->lfthr[i * 2 + 1].lim & 0x3f)<<8) | - (lfi->lfthr[i * 2 + 1].mblim & 0xff); - thr = (thr<<16) | ((lfi->lfthr[i*2].lim & 0x3f)<<8) | - (lfi->lfthr[i * 2].mblim & 0xff); - WRITE_VREG(HEVC_DBLK_CFG9, thr); - } - - /*video format is VP9*/ - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - data32 = (0x3 << 14) | // (dw fifo thres r and b) - (0x3 << 12) | // (dw fifo thres r or b) - (0x3 << 10) | // (dw fifo thres not r/b) - (0x3 << 8) | // 1st/2nd write both enable - (0x1 << 0); // vp9 video format - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - data32 = (0x57 << 8) | /*1st/2nd write both enable*/ - (0x1 << 0); /*vp9 video format*/ - } else - data32 = 0x40400001; - - WRITE_VREG(HEVC_DBLK_CFGB, data32); - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("[DBLK DEBUG] CFGB : 0x%x\n", data32); -} - /* perform this function per frame*/ -void vp9_loop_filter_frame_init(struct segmentation *seg, - struct loop_filter_info_n *lfi, struct loopfilter *lf, - int default_filt_lvl) { - int i; - int seg_id; - /*n_shift is the multiplier for lf_deltas - *the multiplier is 1 for when filter_lvl is between 0 and 31; - *2 when filter_lvl is between 32 and 63 - */ - const int scale = 1 << (default_filt_lvl >> 5); - - /*update limits if sharpness has changed*/ - if (lf->last_sharpness_level != lf->sharpness_level) { - vp9_update_sharpness(lfi, lf->sharpness_level); - lf->last_sharpness_level = lf->sharpness_level; - - /*Write to register*/ - for (i = 0; i < 32; i++) { - unsigned int thr; - - thr = ((lfi->lfthr[i * 2 + 1].lim & 0x3f) << 8) - | (lfi->lfthr[i * 2 + 1].mblim & 0xff); - thr = (thr << 16) | ((lfi->lfthr[i * 2].lim & 0x3f) << 8) - | (lfi->lfthr[i * 2].mblim & 0xff); - WRITE_VREG(HEVC_DBLK_CFG9, thr); - } - } - - for (seg_id = 0; seg_id < MAX_SEGMENTS; seg_id++) {/*MAX_SEGMENTS = 8*/ - int lvl_seg = default_filt_lvl; - - if (segfeature_active(seg, seg_id, SEG_LVL_ALT_LF)) { - const int data = get_segdata(seg, seg_id, - SEG_LVL_ALT_LF); - lvl_seg = vp9_clamp(seg->abs_delta == SEGMENT_ABSDATA ? - data : default_filt_lvl + data, - 0, MAX_LOOP_FILTER); -#ifdef DBG_LF_PRINT - pr_info("segfeature_active!!!seg_id=%d,lvl_seg=%d\n", seg_id, lvl_seg); -#endif - } - - if (!lf->mode_ref_delta_enabled) { - /*we could get rid of this if we assume that deltas are set to - *zero when not in use; encoder always uses deltas - */ - memset(lfi->lvl[seg_id], lvl_seg, sizeof(lfi->lvl[seg_id])); - } else { - int ref, mode; - const int intra_lvl = lvl_seg + lf->ref_deltas[INTRA_FRAME] - * scale; -#ifdef DBG_LF_PRINT - pr_info("LF_PRINT:vp9_loop_filter_frame_init,seg_id=%d\n", seg_id); - pr_info("ref_deltas[INTRA_FRAME]=%d\n", lf->ref_deltas[INTRA_FRAME]); -#endif - lfi->lvl[seg_id][INTRA_FRAME][0] = - vp9_clamp(intra_lvl, 0, MAX_LOOP_FILTER); - - for (ref = LAST_FRAME; ref < MAX_REF_FRAMES; ++ref) { - /* LAST_FRAME = 1, MAX_REF_FRAMES = 4*/ - for (mode = 0; mode < MAX_MODE_LF_DELTAS; ++mode) { - /*MAX_MODE_LF_DELTAS = 2*/ - const int inter_lvl = - lvl_seg + lf->ref_deltas[ref] * scale - + lf->mode_deltas[mode] * scale; -#ifdef DBG_LF_PRINT -#endif - lfi->lvl[seg_id][ref][mode] = - vp9_clamp(inter_lvl, 0, - MAX_LOOP_FILTER); - } - } - } - } - -#ifdef DBG_LF_PRINT - /*print out thr/lvl table per frame*/ - for (i = 0; i <= MAX_LOOP_FILTER; i++) { - pr_info("LF_PRINT:(%d)thr=%d,blim=%d,lim=%d\n", - i, lfi->lfthr[i].hev_thr, lfi->lfthr[i].mblim, - lfi->lfthr[i].lim); - } - for (seg_id = 0; seg_id < MAX_SEGMENTS; seg_id++) { - pr_info("LF_PRINT:lvl(seg_id=%d)(mode=0,%d,%d,%d,%d)\n", - seg_id, lfi->lvl[seg_id][0][0], - lfi->lvl[seg_id][1][0], lfi->lvl[seg_id][2][0], - lfi->lvl[seg_id][3][0]); - pr_info("i(mode=1,%d,%d,%d,%d)\n", lfi->lvl[seg_id][0][1], - lfi->lvl[seg_id][1][1], lfi->lvl[seg_id][2][1], - lfi->lvl[seg_id][3][1]); - } -#endif - - /*Write to register */ - for (i = 0; i < 16; i++) { - unsigned int level; - - level = ((lfi->lvl[i >> 1][3][i & 1] & 0x3f) << 24) | - ((lfi->lvl[i >> 1][2][i & 1] & 0x3f) << 16) | - ((lfi->lvl[i >> 1][1][i & 1] & 0x3f) << 8) | - (lfi->lvl[i >> 1][0][i & 1] & 0x3f); - if (!default_filt_lvl) - level = 0; - WRITE_VREG(HEVC_DBLK_CFGA, level); - } -} -/* VP9_LPF_LVL_UPDATE */ -#endif - -static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi, u32 mask) -{ - unsigned int data32; - int i; - const unsigned short parser_cmd[PARSER_CMD_NUMBER] = { - 0x0401, 0x8401, 0x0800, 0x0402, 0x9002, 0x1423, - 0x8CC3, 0x1423, 0x8804, 0x9825, 0x0800, 0x04FE, - 0x8406, 0x8411, 0x1800, 0x8408, 0x8409, 0x8C2A, - 0x9C2B, 0x1C00, 0x840F, 0x8407, 0x8000, 0x8408, - 0x2000, 0xA800, 0x8410, 0x04DE, 0x840C, 0x840D, - 0xAC00, 0xA000, 0x08C0, 0x08E0, 0xA40E, 0xFC00, - 0x7C00 - }; -#if 0 - if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { - /* Set MCR fetch priorities*/ - data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | - (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); - WRITE_VREG(HEVCD_MPP_DECOMP_AXIURG_CTL, data32); - } -#endif - /*if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("%s\n", __func__);*/ - if (mask & HW_MASK_FRONT) { - data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); -#if 1 - /* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */ - data32 &= ~(7 << 29); - data32 |= (3 << 29); -#endif - data32 = data32 | - (1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/ - (1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/ - (1 << 7) |/*dec_done_int_cpu_enable*/ - (1 << 4) |/*startcode_found_int_cpu_enable*/ - (0 << 3) |/*startcode_found_int_amrisc_enable*/ - (1 << 0) /*parser_int_enable*/ - ; -#ifdef SUPPORT_FB_DECODING -#ifndef FB_DECODING_TEST_SCHEDULE - /*fed_fb_slice_done_int_cpu_enable*/ - if (pbi->used_stage_buf_num > 0) - data32 |= (1 << 10); -#endif -#endif - WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); - - data32 = READ_VREG(HEVC_SHIFT_STATUS); - data32 = data32 | - (0 << 1) |/*emulation_check_off VP9 - do not have emulation*/ - (1 << 0)/*startcode_check_on*/ - ; - WRITE_VREG(HEVC_SHIFT_STATUS, data32); - WRITE_VREG(HEVC_SHIFT_CONTROL, - (0 << 14) | /*disable_start_code_protect*/ - (1 << 10) | /*length_zero_startcode_en for VP9*/ - (1 << 9) | /*length_valid_startcode_en for VP9*/ - (3 << 6) | /*sft_valid_wr_position*/ - (2 << 4) | /*emulate_code_length_sub_1*/ - (3 << 1) | /*start_code_length_sub_1 - VP9 use 0x00000001 as startcode (4 Bytes)*/ - (1 << 0) /*stream_shift_enable*/ - ); - - WRITE_VREG(HEVC_CABAC_CONTROL, - (1 << 0)/*cabac_enable*/ - ); - - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, - (1 << 0)/* hevc_parser_core_clk_en*/ - ); - - - WRITE_VREG(HEVC_DEC_STATUS_REG, 0); - - } - - if (mask & HW_MASK_BACK) { - /*Initial IQIT_SCALELUT memory - -- just to avoid X in simulation*/ - - WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/ - for (i = 0; i < 1024; i++) - WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); - } - - if (mask & HW_MASK_FRONT) { - u32 decode_mode; -#ifdef ENABLE_SWAP_TEST - WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); -#else - WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); -#endif -#ifdef MULTI_INSTANCE_SUPPORT - if (!pbi->m_ins_flag) - decode_mode = DECODE_MODE_SINGLE; - else if (vdec_frame_based(hw_to_vdec(pbi))) - decode_mode = DECODE_MODE_MULTI_FRAMEBASE; - else - decode_mode = DECODE_MODE_MULTI_STREAMBASE; -#ifdef SUPPORT_FB_DECODING -#ifndef FB_DECODING_TEST_SCHEDULE - if (pbi->used_stage_buf_num > 0) - decode_mode |= (0x01 << 24); -#endif -#endif - WRITE_VREG(DECODE_MODE, decode_mode); - WRITE_VREG(HEVC_DECODE_SIZE, 0); - WRITE_VREG(HEVC_DECODE_COUNT, 0); -#else - WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE); - WRITE_VREG(HEVC_DECODE_PIC_BEGIN_REG, 0); - WRITE_VREG(HEVC_DECODE_PIC_NUM_REG, 0x7fffffff); /*to remove*/ -#endif - /*Send parser_cmd*/ - WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); - for (i = 0; i < PARSER_CMD_NUMBER; i++) - WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); - WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); - - - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - /* (1 << 8) |*/ /*sao_sw_pred_enable*/ - (1 << 5) | /*parser_sao_if_en*/ - (1 << 2) | /*parser_mpred_if_en*/ - (1 << 0) /*parser_scaler_if_en*/ - ); - } - - if (mask & HW_MASK_BACK) { - /*Changed to Start MPRED in microcode*/ - /* - pr_info("[test.c] Start MPRED\n"); - WRITE_VREG(HEVC_MPRED_INT_STATUS, - (1<<31) - ); - */ - WRITE_VREG(HEVCD_IPP_TOP_CNTL, - (0 << 1) | /*enable ipp*/ - (1 << 0) /*software reset ipp and mpp*/ - ); - WRITE_VREG(HEVCD_IPP_TOP_CNTL, - (1 << 1) | /*enable ipp*/ - (0 << 0) /*software reset ipp and mpp*/ - ); - if (get_double_write_mode(pbi) & 0x10) { - /*Enable NV21 reference read mode for MC*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); - } - - /*Initialize mcrcc and decomp perf counters*/ - if (mcrcc_cache_alg_flag && - pbi->init_flag == 0) { - mcrcc_perfcount_reset(); - decomp_perfcount_reset(); - } - } - return; -} - - -#ifdef CONFIG_HEVC_CLK_FORCED_ON -static void config_vp9_clk_forced_on(void) -{ - unsigned int rdata32; - /*IQIT*/ - rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL); - WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2)); - - /* DBLK*/ - rdata32 = READ_VREG(HEVC_DBLK_CFG0); - WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2)); - - /* SAO*/ - rdata32 = READ_VREG(HEVC_SAO_CTRL1); - WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2)); - - /*MPRED*/ - rdata32 = READ_VREG(HEVC_MPRED_CTRL1); - WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24)); - - /* PARSER*/ - rdata32 = READ_VREG(HEVC_STREAM_CONTROL); - WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_SHIFT_CONTROL); - WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_CABAC_CONTROL); - WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13)); - rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL); - WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL); - WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15)); - rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL); - WRITE_VREG(HEVC_PARSER_IF_CONTROL, - rdata32 | (0x1 << 6) | (0x1 << 3) | (0x1 << 1)); - - /*IPP*/ - rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG); - WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff); - - /* MCRCC*/ - rdata32 = READ_VREG(HEVCD_MCRCC_CTL1); - WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3)); -} -#endif - - -#ifdef MCRCC_ENABLE -static void dump_hit_rate(struct VP9Decoder_s *pbi) -{ - if (debug & VP9_DEBUG_CACHE_HIT_RATE) { - mcrcc_get_hitrate(pbi->m_ins_flag); - decomp_get_hitrate(); - decomp_get_comprate(); - } -} - -static void config_mcrcc_axi_hw(struct VP9Decoder_s *pbi) -{ - unsigned int rdata32; - unsigned short is_inter; - /*pr_info("Entered config_mcrcc_axi_hw...\n");*/ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2);/* reset mcrcc*/ - is_inter = ((pbi->common.frame_type != KEY_FRAME) && - (!pbi->common.intra_only)) ? 1 : 0; - if (!is_inter) { /* I-PIC*/ - /*remove reset -- disables clock*/ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); - return; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - mcrcc_get_hitrate(pbi->m_ins_flag); - decomp_get_hitrate(); - decomp_get_comprate(); - } - - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (1 << 1) | 0); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - /*Programme canvas1 */ - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - /*enable mcrcc progressive-mode*/ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); -} - -static void config_mcrcc_axi_hw_new(struct VP9Decoder_s *pbi) -{ - u32 curr_picnum = -1; - u32 lastref_picnum = -1; - u32 goldenref_picnum = -1; - u32 altref_picnum = -1; - - u32 lastref_delta_picnum; - u32 goldenref_delta_picnum; - u32 altref_delta_picnum; - - u32 rdata32; - - u32 lastcanvas; - u32 goldencanvas; - u32 altrefcanvas; - - u16 is_inter; - u16 lastref_inref; - u16 goldenref_inref; - u16 altref_inref; - - u32 refcanvas_array[3], utmp; - int deltapicnum_array[3], tmp; - - struct VP9_Common_s *cm = &pbi->common; - struct PIC_BUFFER_CONFIG_s *cur_pic_config - = &cm->cur_frame->buf; - curr_picnum = cur_pic_config->decode_idx; - if (cm->frame_refs[0].buf) - lastref_picnum = cm->frame_refs[0].buf->decode_idx; - if (cm->frame_refs[1].buf) - goldenref_picnum = cm->frame_refs[1].buf->decode_idx; - if (cm->frame_refs[2].buf) - altref_picnum = cm->frame_refs[2].buf->decode_idx; - - lastref_delta_picnum = (lastref_picnum >= curr_picnum) ? - (lastref_picnum - curr_picnum) : (curr_picnum - lastref_picnum); - goldenref_delta_picnum = (goldenref_picnum >= curr_picnum) ? - (goldenref_picnum - curr_picnum) : - (curr_picnum - goldenref_picnum); - altref_delta_picnum = - (altref_picnum >= curr_picnum) ? - (altref_picnum - curr_picnum) : (curr_picnum - altref_picnum); - - lastref_inref = (cm->frame_refs[0].idx != INVALID_IDX) ? 1 : 0; - goldenref_inref = (cm->frame_refs[1].idx != INVALID_IDX) ? 1 : 0; - altref_inref = (cm->frame_refs[2].idx != INVALID_IDX) ? 1 : 0; - - if (debug & VP9_DEBUG_CACHE) - pr_info("%s--0--lastref_inref:%d goldenref_inref:%d altref_inref:%d\n", - __func__, lastref_inref, goldenref_inref, altref_inref); - - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc */ - - is_inter = ((pbi->common.frame_type != KEY_FRAME) - && (!pbi->common.intra_only)) ? 1 : 0; - - if (!is_inter) { /* I-PIC */ - /* remove reset -- disables clock */ - WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); - return; - } - - if (!pbi->m_ins_flag) - dump_hit_rate(pbi); - - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (1<<1) | 0); - lastcanvas = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - goldencanvas = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - altrefcanvas = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - - if (debug & VP9_DEBUG_CACHE) - pr_info("[test.c] lastref_canv:%x goldenref_canv:%x altref_canv:%x\n", - lastcanvas, goldencanvas, altrefcanvas); - - altref_inref = ((altref_inref == 1) && - (altrefcanvas != (goldenref_inref - ? goldencanvas : 0xffffffff)) && - (altrefcanvas != (lastref_inref ? - lastcanvas : 0xffffffff))) ? 1 : 0; - goldenref_inref = ((goldenref_inref == 1) && - (goldencanvas != (lastref_inref ? - lastcanvas : 0xffffffff))) ? 1 : 0; - if (debug & VP9_DEBUG_CACHE) - pr_info("[test.c]--1--lastref_inref:%d goldenref_inref:%d altref_inref:%d\n", - lastref_inref, goldenref_inref, altref_inref); - - altref_delta_picnum = altref_inref ? altref_delta_picnum : 0x7fffffff; - goldenref_delta_picnum = goldenref_inref ? - goldenref_delta_picnum : 0x7fffffff; - lastref_delta_picnum = lastref_inref ? - lastref_delta_picnum : 0x7fffffff; - if (debug & VP9_DEBUG_CACHE) - pr_info("[test.c]--1--lastref_delta_picnum:%d goldenref_delta_picnum:%d altref_delta_picnum:%d\n", - lastref_delta_picnum, goldenref_delta_picnum, - altref_delta_picnum); - /*ARRAY SORT HERE DELTA/CANVAS ARRAY SORT -- use DELTA*/ - - refcanvas_array[0] = lastcanvas; - refcanvas_array[1] = goldencanvas; - refcanvas_array[2] = altrefcanvas; - - deltapicnum_array[0] = lastref_delta_picnum; - deltapicnum_array[1] = goldenref_delta_picnum; - deltapicnum_array[2] = altref_delta_picnum; - - /* sort0 : 2-to-1 */ - if (deltapicnum_array[2] < deltapicnum_array[1]) { - utmp = refcanvas_array[2]; - refcanvas_array[2] = refcanvas_array[1]; - refcanvas_array[1] = utmp; - tmp = deltapicnum_array[2]; - deltapicnum_array[2] = deltapicnum_array[1]; - deltapicnum_array[1] = tmp; - } - /* sort1 : 1-to-0 */ - if (deltapicnum_array[1] < deltapicnum_array[0]) { - utmp = refcanvas_array[1]; - refcanvas_array[1] = refcanvas_array[0]; - refcanvas_array[0] = utmp; - tmp = deltapicnum_array[1]; - deltapicnum_array[1] = deltapicnum_array[0]; - deltapicnum_array[0] = tmp; - } - /* sort2 : 2-to-1 */ - if (deltapicnum_array[2] < deltapicnum_array[1]) { - utmp = refcanvas_array[2]; refcanvas_array[2] = - refcanvas_array[1]; refcanvas_array[1] = utmp; - tmp = deltapicnum_array[2]; deltapicnum_array[2] = - deltapicnum_array[1]; deltapicnum_array[1] = tmp; - } - if (mcrcc_cache_alg_flag == - THODIYIL_MCRCC_CANVAS_ALGX) { /*09/15/2017*/ - /* lowest delta_picnum */ - rdata32 = refcanvas_array[0]; - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - /* 2nd-lowest delta_picnum */ - rdata32 = refcanvas_array[1]; - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - } else { - /* previous version -- LAST/GOLDEN ALWAYS -- before 09/13/2017*/ - WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, - (0 << 8) | (1<<1) | 0); - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); - - /* Programme canvas1 */ - rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); - rdata32 = rdata32 & 0xffff; - rdata32 = rdata32 | (rdata32 << 16); - WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); - } - - WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); /* enable mcrcc progressive-mode */ - return; -} - -#endif - - -static void free_lf_buf(struct VP9Decoder_s *pbi) -{ - if (pbi->lfi) - vfree(pbi->lfi); - if (pbi->lf) - vfree(pbi->lf); - if (pbi->seg_4lf) - vfree(pbi->seg_4lf); - pbi->lfi = NULL; - pbi->lf = NULL; - pbi->seg_4lf = NULL; -} - -static int alloc_lf_buf(struct VP9Decoder_s *pbi) -{ - pbi->lfi = vmalloc(sizeof(struct loop_filter_info_n)); - pbi->lf = vmalloc(sizeof(struct loopfilter)); - pbi->seg_4lf = vmalloc(sizeof(struct segmentation)); - if (pbi->lfi == NULL || pbi->lf == NULL || pbi->seg_4lf == NULL) { - free_lf_buf(pbi); - pr_err("[test.c] vp9_loop_filter init malloc error!!!\n"); - return -1; - } - return 0; -} - -static void vp9_local_uninit(struct VP9Decoder_s *pbi) -{ - pbi->rpm_ptr = NULL; - pbi->lmem_ptr = NULL; - if (pbi->rpm_addr) { - dma_unmap_single(amports_get_dma_device(), - pbi->rpm_phy_addr, RPM_BUF_SIZE, - DMA_FROM_DEVICE); - kfree(pbi->rpm_addr); - pbi->rpm_addr = NULL; - } - if (pbi->lmem_addr) { - if (pbi->lmem_phy_addr) - dma_free_coherent(amports_get_dma_device(), - LMEM_BUF_SIZE, pbi->lmem_addr, - pbi->lmem_phy_addr); - pbi->lmem_addr = NULL; - } - if (pbi->prob_buffer_addr) { - if (pbi->prob_buffer_phy_addr) - dma_free_coherent(amports_get_dma_device(), - PROB_BUF_SIZE, pbi->prob_buffer_addr, - pbi->prob_buffer_phy_addr); - - pbi->prob_buffer_addr = NULL; - } - if (pbi->count_buffer_addr) { - if (pbi->count_buffer_phy_addr) - dma_free_coherent(amports_get_dma_device(), - COUNT_BUF_SIZE, pbi->count_buffer_addr, - pbi->count_buffer_phy_addr); - - pbi->count_buffer_addr = NULL; - } - if (pbi->mmu_enable) { - u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi); - if (pbi->frame_mmu_map_addr) { - if (pbi->frame_mmu_map_phy_addr) - dma_free_coherent(amports_get_dma_device(), - mmu_map_size, - pbi->frame_mmu_map_addr, - pbi->frame_mmu_map_phy_addr); - pbi->frame_mmu_map_addr = NULL; - } - } -#ifdef SUPPORT_FB_DECODING - if (pbi->stage_mmu_map_addr) { - if (pbi->stage_mmu_map_phy_addr) - dma_free_coherent(amports_get_dma_device(), - STAGE_MMU_MAP_SIZE * STAGE_MAX_BUFFERS, - pbi->stage_mmu_map_addr, - pbi->stage_mmu_map_phy_addr); - pbi->stage_mmu_map_addr = NULL; - } - - uninit_stage_buf(pbi); -#endif - -#ifdef VP9_LPF_LVL_UPDATE - free_lf_buf(pbi); -#endif - if (pbi->gvs) - vfree(pbi->gvs); - pbi->gvs = NULL; -} - -static int vp9_local_init(struct VP9Decoder_s *pbi) -{ - int ret = -1; - /*int losless_comp_header_size, losless_comp_body_size;*/ - - struct BuffInfo_s *cur_buf_info = NULL; - - memset(&pbi->param, 0, sizeof(union param_u)); - memset(&pbi->common, 0, sizeof(struct VP9_Common_s)); -#ifdef MULTI_INSTANCE_SUPPORT - cur_buf_info = &pbi->work_space_buf_store; - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - memcpy(cur_buf_info, &amvvp9_workbuff_spec[2], /* 8k */ - sizeof(struct BuffInfo_s)); - } else - memcpy(cur_buf_info, &amvvp9_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - } else - memcpy(cur_buf_info, &amvvp9_workbuff_spec[0],/* 1080p */ - sizeof(struct BuffInfo_s)); - - cur_buf_info->start_adr = pbi->buf_start; - if (!pbi->mmu_enable) - pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size; - -#else -/*! MULTI_INSTANCE_SUPPORT*/ - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - cur_buf_info = &amvvp9_workbuff_spec[2];/* 8k work space */ - else - cur_buf_info = &amvvp9_workbuff_spec[1];/* 4k2k work space */ - } else - cur_buf_info = &amvvp9_workbuff_spec[0];/* 1080p work space */ - -#endif - - init_buff_spec(pbi, cur_buf_info); - vp9_bufmgr_init(pbi, cur_buf_info, NULL); - - if (!vdec_is_support_4k() - && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { - buf_alloc_width = 1920; - buf_alloc_height = 1088; - if (pbi->max_pic_w > 1920 && pbi->max_pic_h > 1088) { - pbi->max_pic_w = 1920; - pbi->max_pic_h = 1088; - } - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - buf_alloc_width = 8192; - buf_alloc_height = 4608; - } - pbi->init_pic_w = pbi->max_pic_w ? pbi->max_pic_w : - (buf_alloc_width ? buf_alloc_width : - (pbi->vvp9_amstream_dec_info.width ? - pbi->vvp9_amstream_dec_info.width : - pbi->work_space_buf->max_width)); - pbi->init_pic_h = pbi->max_pic_h ? pbi->max_pic_h : - (buf_alloc_height ? buf_alloc_height : - (pbi->vvp9_amstream_dec_info.height ? - pbi->vvp9_amstream_dec_info.height : - pbi->work_space_buf->max_height)); - - if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && - (pbi->double_write_mode != 0) && - (((pbi->max_pic_w % 64) != 0) || - (pbi->vvp9_amstream_dec_info.width % 64) != 0)) - mem_map_mode = 2; - -#ifndef MV_USE_FIXED_BUF - if (init_mv_buf_list(pbi) < 0) { - pr_err("%s: init_mv_buf_list fail\n", __func__); - return -1; - } -#endif - - if (pbi->save_buffer_mode) - pbi->used_buf_num = MAX_BUF_NUM_SAVE_BUF; - else - pbi->used_buf_num = max_buf_num; - - if (pbi->used_buf_num > MAX_BUF_NUM) - pbi->used_buf_num = MAX_BUF_NUM; - if (pbi->used_buf_num > FRAME_BUFFERS) - pbi->used_buf_num = FRAME_BUFFERS; - - init_pic_list(pbi); - - pbi->pts_unstable = ((unsigned long)(pbi->vvp9_amstream_dec_info.param) - & 0x40) >> 6; - - if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { - pbi->rpm_addr = kmalloc(RPM_BUF_SIZE, GFP_KERNEL); - if (pbi->rpm_addr == NULL) { - pr_err("%s: failed to alloc rpm buffer\n", __func__); - return -1; - } - - pbi->rpm_phy_addr = dma_map_single(amports_get_dma_device(), - pbi->rpm_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - pbi->rpm_phy_addr)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(pbi->rpm_addr); - pbi->rpm_addr = NULL; - return -1; - } - - pbi->rpm_ptr = pbi->rpm_addr; - } - - pbi->lmem_addr = dma_alloc_coherent(amports_get_dma_device(), - LMEM_BUF_SIZE, - &pbi->lmem_phy_addr, GFP_KERNEL); - if (pbi->lmem_addr == NULL) { - pr_err("%s: failed to alloc lmem buffer\n", __func__); - return -1; - } -/* - * pbi->lmem_phy_addr = dma_map_single(amports_get_dma_device(), - * pbi->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL); - * if (dma_mapping_error(amports_get_dma_device(), - * pbi->lmem_phy_addr)) { - * pr_err("%s: failed to map lmem buffer\n", __func__); - * kfree(pbi->lmem_addr); - * pbi->lmem_addr = NULL; - * return -1; - * } - */ - pbi->lmem_ptr = pbi->lmem_addr; - - pbi->prob_buffer_addr = dma_alloc_coherent(amports_get_dma_device(), - PROB_BUF_SIZE, - &pbi->prob_buffer_phy_addr, GFP_KERNEL); - if (pbi->prob_buffer_addr == NULL) { - pr_err("%s: failed to alloc prob_buffer\n", __func__); - return -1; - } - memset(pbi->prob_buffer_addr, 0, PROB_BUF_SIZE); -/* pbi->prob_buffer_phy_addr = dma_map_single(amports_get_dma_device(), - * pbi->prob_buffer_addr, PROB_BUF_SIZE, DMA_BIDIRECTIONAL); - * if (dma_mapping_error(amports_get_dma_device(), - * pbi->prob_buffer_phy_addr)) { - * pr_err("%s: failed to map prob_buffer\n", __func__); - * kfree(pbi->prob_buffer_addr); - * pbi->prob_buffer_addr = NULL; - * return -1; - * } - */ - pbi->count_buffer_addr = dma_alloc_coherent(amports_get_dma_device(), - COUNT_BUF_SIZE, - &pbi->count_buffer_phy_addr, GFP_KERNEL); - if (pbi->count_buffer_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; - } - memset(pbi->count_buffer_addr, 0, COUNT_BUF_SIZE); -/* pbi->count_buffer_phy_addr = dma_map_single(amports_get_dma_device(), - pbi->count_buffer_addr, COUNT_BUF_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - pbi->count_buffer_phy_addr)) { - pr_err("%s: failed to map count_buffer\n", __func__); - kfree(pbi->count_buffer_addr); - pbi->count_buffer_addr = NULL; - return -1; - } -*/ - if (pbi->mmu_enable) { - u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi); - pbi->frame_mmu_map_addr = - dma_alloc_coherent(amports_get_dma_device(), - mmu_map_size, - &pbi->frame_mmu_map_phy_addr, GFP_KERNEL); - if (pbi->frame_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; - } - memset(pbi->frame_mmu_map_addr, 0, COUNT_BUF_SIZE); - /* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), - pbi->frame_mmu_map_addr, mmu_map_size, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - pbi->frame_mmu_map_phy_addr)) { - pr_err("%s: failed to map count_buffer\n", __func__); - kfree(pbi->frame_mmu_map_addr); - pbi->frame_mmu_map_addr = NULL; - return -1; - }*/ - } -#ifdef SUPPORT_FB_DECODING - if (pbi->m_ins_flag && stage_buf_num > 0) { - pbi->stage_mmu_map_addr = - dma_alloc_coherent(amports_get_dma_device(), - STAGE_MMU_MAP_SIZE * STAGE_MAX_BUFFERS, - &pbi->stage_mmu_map_phy_addr, GFP_KERNEL); - if (pbi->stage_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; - } - memset(pbi->stage_mmu_map_addr, - 0, STAGE_MMU_MAP_SIZE * STAGE_MAX_BUFFERS); - - init_stage_buf(pbi); - } -#endif - - ret = 0; - return ret; -} - -/******************************************** - * Mailbox command - ********************************************/ -#define CMD_FINISHED 0 -#define CMD_ALLOC_VIEW 1 -#define CMD_FRAME_DISPLAY 3 -#define CMD_DEBUG 10 - - -#define DECODE_BUFFER_NUM_MAX 32 -#define DISPLAY_BUFFER_NUM 6 - -#define video_domain_addr(adr) (adr&0x7fffffff) -#define DECODER_WORK_SPACE_SIZE 0x800000 - -#define spec2canvas(x) \ - (((x)->uv_canvas_index << 16) | \ - ((x)->uv_canvas_index << 8) | \ - ((x)->y_canvas_index << 0)) - - -static void set_canvas(struct VP9Decoder_s *pbi, - struct PIC_BUFFER_CONFIG_s *pic_config) -{ - struct vdec_s *vdec = hw_to_vdec(pbi); - int canvas_w = ALIGN(pic_config->y_crop_width, 64)/4; - int canvas_h = ALIGN(pic_config->y_crop_height, 32)/4; - int blkmode = mem_map_mode; - /*CANVAS_BLKMODE_64X32*/ - if (pic_config->double_write_mode) { - canvas_w = pic_config->y_crop_width / - get_double_write_ratio(pbi, - pic_config->double_write_mode); - canvas_h = pic_config->y_crop_height / - get_double_write_ratio(pbi, - pic_config->double_write_mode); - - if (mem_map_mode == 0) - canvas_w = ALIGN(canvas_w, 32); - else - canvas_w = ALIGN(canvas_w, 64); - canvas_h = ALIGN(canvas_h, 32); - - if (vdec->parallel_dec == 1) { - if (pic_config->y_canvas_index == -1) - pic_config->y_canvas_index = - vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - if (pic_config->uv_canvas_index == -1) - pic_config->uv_canvas_index = - vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); - } else { - pic_config->y_canvas_index = 128 + pic_config->index * 2; - pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1; - } - - canvas_config_ex(pic_config->y_canvas_index, - pic_config->dw_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic_config->uv_canvas_index, - pic_config->dw_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - -#ifdef MULTI_INSTANCE_SUPPORT - pic_config->canvas_config[0].phy_addr = - pic_config->dw_y_adr; - pic_config->canvas_config[0].width = - canvas_w; - pic_config->canvas_config[0].height = - canvas_h; - pic_config->canvas_config[0].block_mode = - blkmode; - pic_config->canvas_config[0].endian = 7; - - pic_config->canvas_config[1].phy_addr = - pic_config->dw_u_v_adr; - pic_config->canvas_config[1].width = - canvas_w; - pic_config->canvas_config[1].height = - canvas_h; - pic_config->canvas_config[1].block_mode = - blkmode; - pic_config->canvas_config[1].endian = 7; -#endif - } -} - - -static void set_frame_info(struct VP9Decoder_s *pbi, struct vframe_s *vf) -{ - unsigned int ar; - - vf->duration = pbi->frame_dur; - vf->duration_pulldown = 0; - vf->flag = 0; - vf->prop.master_display_colour = pbi->vf_dp; - vf->signal_type = pbi->video_signal_type; - - ar = min_t(u32, pbi->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); - vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - -} - -static int vvp9_vf_states(struct vframe_states *states, void *op_arg) -{ - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; - - states->vf_pool_size = VF_POOL_SIZE; - states->buf_free_num = kfifo_len(&pbi->newframe_q); - states->buf_avail_num = kfifo_len(&pbi->display_q); - - if (step == 2) - states->buf_avail_num = 0; - return 0; -} - -static struct vframe_s *vvp9_vf_peek(void *op_arg) -{ - struct vframe_s *vf[2] = {0, 0}; - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; - - if (step == 2) - return NULL; - - if (kfifo_out_peek(&pbi->display_q, (void *)&vf, 2)) { - if (vf[1]) { - vf[0]->next_vf_pts_valid = true; - vf[0]->next_vf_pts = vf[1]->pts; - } else - vf[0]->next_vf_pts_valid = false; - return vf[0]; - } - - return NULL; -} - -static struct vframe_s *vvp9_vf_get(void *op_arg) -{ - struct vframe_s *vf; - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; - - if (step == 2) - return NULL; - else if (step == 1) - step = 2; - - if (kfifo_get(&pbi->display_q, &vf)) { - struct vframe_s *next_vf; - uint8_t index = vf->index & 0xff; - if (index < pbi->used_buf_num) { - pbi->vf_get_count++; - if (debug & VP9_DEBUG_BUFMGR) - pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n", - __func__, vf->type, - vf->width, vf->height, - vf->pts, - vf->pts_us64); - - if (kfifo_peek(&pbi->display_q, &next_vf)) { - vf->next_vf_pts_valid = true; - vf->next_vf_pts = next_vf->pts; - } else - vf->next_vf_pts_valid = false; - - return vf; - } - } - return NULL; -} - -static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) -{ - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; - uint8_t index = vf->index & 0xff; - - kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf); - pbi->vf_put_count++; - if (index < pbi->used_buf_num) { - struct VP9_Common_s *cm = &pbi->common; - struct BufferPool_s *pool = cm->buffer_pool; - unsigned long flags; - - lock_buffer_pool(pool, flags); - if (pool->frame_bufs[index].buf.vf_ref > 0) - pool->frame_bufs[index].buf.vf_ref--; - - if (pbi->wait_buf) - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - pbi->last_put_idx = index; - pbi->new_frame_displayed++; - unlock_buffer_pool(pool, flags); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0 && - pbi->back_not_run_ready) - trigger_schedule(pbi); -#endif - } - -} - -static int vvp9_event_cb(int type, void *data, void *private_data) -{ - if (type & VFRAME_EVENT_RECEIVER_RESET) { -#if 0 - unsigned long flags; - - amhevc_stop(); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_light_unreg_provider(&vvp9_vf_prov); -#endif - spin_lock_irqsave(&pbi->lock, flags); - vvp9_local_init(); - vvp9_prot_init(); - spin_unlock_irqrestore(&pbi->lock, flags); -#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - vf_reg_provider(&vvp9_vf_prov); -#endif - amhevc_start(); -#endif - } - - return 0; -} - -void inc_vf_ref(struct VP9Decoder_s *pbi, int index) -{ - struct VP9_Common_s *cm = &pbi->common; - - cm->buffer_pool->frame_bufs[index].buf.vf_ref++; - - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("%s index = %d new vf_ref = %d\r\n", - __func__, index, - cm->buffer_pool->frame_bufs[index].buf.vf_ref); -} - -static int frame_duration_adapt(struct VP9Decoder_s *pbi, struct vframe_s *vf, u32 valid) -{ - u32 old_duration, pts_duration = 0; - u32 pts = vf->pts; - - if (pbi->get_frame_dur == true) - return true; - - pbi->frame_cnt_window++; - if (!(pbi->vp9_first_pts_ready == 1)) { - if (valid) { - pbi->pts1 = pts; - pbi->frame_cnt_window = 0; - pbi->duration_from_pts_done = 0; - pbi->vp9_first_pts_ready = 1; - } else { - return false; - } - } else { - if (pts < pbi->pts1) { - if (pbi->frame_cnt_window > FRAME_CNT_WINDOW_SIZE) { - pbi->pts1 = pts; - pbi->frame_cnt_window = 0; - } - } - - if (valid && (pbi->frame_cnt_window > FRAME_CNT_WINDOW_SIZE) && - (pts > pbi->pts1) && (pbi->duration_from_pts_done == 0)) { - old_duration = pbi->frame_dur; - pbi->pts2 = pts; - pts_duration = (((pbi->pts2 - pbi->pts1) * 16) / - (pbi->frame_cnt_window * 15)); - - if (close_to(pts_duration, old_duration, 2000)) { - pbi->frame_dur = pts_duration; - if ((debug & VP9_DEBUG_OUT_PTS) != 0) - pr_info("use calc duration %d\n", pts_duration); - } - - if (pbi->duration_from_pts_done == 0) { - if (close_to(pts_duration, old_duration, RATE_CORRECTION_THRESHOLD)) { - pbi->duration_from_pts_done = 1; - } else { - if (!close_to(pts_duration, - old_duration, 1000) && - !close_to(pts_duration, - pbi->frame_dur, 1000) && - close_to(pts_duration, - pbi->last_duration, 200)) { - /* frame_dur must - * wrong,recover it. - */ - pbi->frame_dur = pts_duration; - } - pbi->pts1 = pbi->pts2; - pbi->frame_cnt_window = 0; - pbi->duration_from_pts_done = 0; - } - } - pbi->last_duration = pts_duration; - } - } - return true; -} - -static void update_vf_memhandle(struct VP9Decoder_s *pbi, - struct vframe_s *vf, struct PIC_BUFFER_CONFIG_s *pic) -{ - if (pic->index < 0) { - vf->mem_handle = NULL; - vf->mem_head_handle = NULL; - } else if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = - decoder_mmu_box_get_mem_handle( - pbi->mmu_box, pic->index); - vf->mem_head_handle = - decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - HEADER_BUFFER_IDX(pic->BUF_index)); - } else { - vf->mem_handle = - decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, VF_BUFFER_IDX(pic->BUF_index)); - vf->mem_head_handle = NULL; - /*vf->mem_head_handle = - *decoder_bmmu_box_get_mem_handle( - *hevc->bmmu_box, VF_BUFFER_IDX(BUF_index)); - */ - } -} -static int prepare_display_buf(struct VP9Decoder_s *pbi, - struct PIC_BUFFER_CONFIG_s *pic_config) -{ - struct vframe_s *vf = NULL; - int stream_offset = pic_config->stream_offset; - unsigned short slice_type = pic_config->slice_type; - u32 pts_valid = 0, pts_us64_valid = 0; - u32 pts_save; - u64 pts_us64_save; - u32 frame_size; - - if (debug & VP9_DEBUG_BUFMGR) - pr_info("%s index = %d\r\n", __func__, pic_config->index); - if (kfifo_get(&pbi->newframe_q, &vf) == 0) { - pr_info("fatal error, no available buffer slot."); - return -1; - } - - if (pic_config->double_write_mode) - set_canvas(pbi, pic_config); - - display_frame_count[pbi->index]++; - if (vf) { -#ifdef MULTI_INSTANCE_SUPPORT - if (vdec_frame_based(hw_to_vdec(pbi))) { - vf->pts = pic_config->pts; - vf->pts_us64 = pic_config->pts64; - if (vf->pts != 0 || vf->pts_us64 != 0) { - pts_valid = 1; - pts_us64_valid = 1; - } else { - pts_valid = 0; - pts_us64_valid = 0; - } - } else -#endif - /* if (pts_lookup_offset(PTS_TYPE_VIDEO, - * stream_offset, &vf->pts, 0) != 0) { - */ - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, - &frame_size, 0, - &vf->pts_us64) != 0) { -#ifdef DEBUG_PTS - pbi->pts_missed++; -#endif - vf->pts = 0; - vf->pts_us64 = 0; - pts_valid = 0; - pts_us64_valid = 0; - } else { -#ifdef DEBUG_PTS - pbi->pts_hit++; -#endif - pts_valid = 1; - pts_us64_valid = 1; - } - - pts_save = vf->pts; - pts_us64_save = vf->pts_us64; - if (pbi->pts_unstable) { - frame_duration_adapt(pbi, vf, pts_valid); - if (pbi->duration_from_pts_done) { - pbi->pts_mode = PTS_NONE_REF_USE_DURATION; - } else { - if (pts_valid || pts_us64_valid) - pbi->pts_mode = PTS_NORMAL; - } - } - - if ((pbi->pts_mode == PTS_NORMAL) && (vf->pts != 0) - && pbi->get_frame_dur) { - int pts_diff = (int)vf->pts - pbi->last_lookup_pts; - - if (pts_diff < 0) { - pbi->pts_mode_switching_count++; - pbi->pts_mode_recovery_count = 0; - - if (pbi->pts_mode_switching_count >= - PTS_MODE_SWITCHING_THRESHOLD) { - pbi->pts_mode = - PTS_NONE_REF_USE_DURATION; - pr_info - ("HEVC: switch to n_d mode.\n"); - } - - } else { - int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD; - - pbi->pts_mode_recovery_count++; - if (pbi->pts_mode_recovery_count > p) { - pbi->pts_mode_switching_count = 0; - pbi->pts_mode_recovery_count = 0; - } - } - } - - if (vf->pts != 0) - pbi->last_lookup_pts = vf->pts; - - if ((pbi->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != KEY_FRAME)) - vf->pts = pbi->last_pts + DUR2PTS(pbi->frame_dur); - pbi->last_pts = vf->pts; - - if (vf->pts_us64 != 0) - pbi->last_lookup_pts_us64 = vf->pts_us64; - - if ((pbi->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != KEY_FRAME)) { - vf->pts_us64 = - pbi->last_pts_us64 + - (DUR2PTS(pbi->frame_dur) * 100 / 9); - } - pbi->last_pts_us64 = vf->pts_us64; - if ((debug & VP9_DEBUG_OUT_PTS) != 0) { - pr_info - ("VP9 dec out pts: pts_mode=%d,dur=%d,pts(%d,%lld)(%d,%lld)\n", - pbi->pts_mode, pbi->frame_dur, vf->pts, - vf->pts_us64, pts_save, pts_us64_save); - } - - if (pbi->pts_mode == PTS_NONE_REF_USE_DURATION) { - vf->disp_pts = vf->pts; - vf->disp_pts_us64 = vf->pts_us64; - vf->pts = pts_save; - vf->pts_us64 = pts_us64_save; - } else { - vf->disp_pts = 0; - vf->disp_pts_us64 = 0; - } - - vf->index = 0xff00 | pic_config->index; - - if (pic_config->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { - if (pbi->mmu_enable) { - vf->compBodyAddr = 0; - vf->compHeadAddr = pic_config->header_adr; - } else { - /*vf->compBodyAddr = pic_config->mc_y_adr; - *vf->compHeadAddr = pic_config->mc_y_adr + - *pic_config->comp_body_size; */ - /*head adr*/ - } - vf->canvas0Addr = vf->canvas1Addr = 0; - } - if (pic_config->double_write_mode) { - vf->type = VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if ((pic_config->double_write_mode == 3) && - (!IS_8K_SIZE(pic_config->y_crop_width, - pic_config->y_crop_height))) { - vf->type |= VIDTYPE_COMPRESS; - if (pbi->mmu_enable) - vf->type |= VIDTYPE_SCATTER; - } -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) { - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - pic_config->canvas_config[0]; - vf->canvas0_config[1] = - pic_config->canvas_config[1]; - vf->canvas1_config[0] = - pic_config->canvas_config[0]; - vf->canvas1_config[1] = - pic_config->canvas_config[1]; - - } else -#endif - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(pic_config); - } else { - vf->canvas0Addr = vf->canvas1Addr = 0; - vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; - if (pbi->mmu_enable) - vf->type |= VIDTYPE_SCATTER; - } - - switch (pic_config->bit_depth) { - case VPX_BITS_8: - vf->bitdepth = BITDEPTH_Y8 | - BITDEPTH_U8 | BITDEPTH_V8; - break; - case VPX_BITS_10: - case VPX_BITS_12: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - default: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - } - if ((vf->type & VIDTYPE_COMPRESS) == 0) - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - if (pic_config->bit_depth == VPX_BITS_8) - vf->bitdepth |= BITDEPTH_SAVING_MODE; - - set_frame_info(pbi, vf); - /* if((vf->width!=pic_config->width)| - * (vf->height!=pic_config->height)) - */ - /* pr_info("aaa: %d/%d, %d/%d\n", - vf->width,vf->height, pic_config->width, - pic_config->height); */ - vf->width = pic_config->y_crop_width / - get_double_write_ratio(pbi, - pic_config->double_write_mode); - vf->height = pic_config->y_crop_height / - get_double_write_ratio(pbi, - pic_config->double_write_mode); - if (force_w_h != 0) { - vf->width = (force_w_h >> 16) & 0xffff; - vf->height = force_w_h & 0xffff; - } - vf->compWidth = pic_config->y_crop_width; - vf->compHeight = pic_config->y_crop_height; - if (force_fps & 0x100) { - u32 rate = force_fps & 0xff; - - if (rate) - vf->duration = 96000/rate; - else - vf->duration = 0; - } - update_vf_memhandle(pbi, vf, pic_config); - if (!(pic_config->y_crop_width == 196 - && pic_config->y_crop_height == 196 - && (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0 - )) { - inc_vf_ref(pbi, pic_config->index); - decoder_do_frame_check(hw_to_vdec(pbi), vf); - kfifo_put(&pbi->display_q, (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - pbi->vf_pre_count++; -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - /*count info*/ - gvs->frame_dur = pbi->frame_dur; - vdec_count_info(gvs, 0, stream_offset); -#endif - hw_to_vdec(pbi)->vdec_fps_detec(hw_to_vdec(pbi)->id); - vf_notify_receiver(pbi->provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - } else { - pbi->stat |= VP9_TRIGGER_FRAME_DONE; - hevc_source_changed(VFORMAT_VP9, 196, 196, 30); - pr_debug("[%s %d] drop trigger frame width %d height %d state 0x%x\n", - __func__, __LINE__, vf->width, - vf->height, pbi->stat); - } - } - - return 0; -} - -static void get_rpm_param(union param_u *params) -{ - int i; - unsigned int data32; - - if (debug & VP9_DEBUG_BUFMGR) - pr_info("enter %s\r\n", __func__); - for (i = 0; i < 128; i++) { - do { - data32 = READ_VREG(RPM_CMD_REG); - /*pr_info("%x\n", data32);*/ - } while ((data32 & 0x10000) == 0); - params->l.data[i] = data32&0xffff; - /*pr_info("%x\n", data32);*/ - WRITE_VREG(RPM_CMD_REG, 0); - } - if (debug & VP9_DEBUG_BUFMGR) - pr_info("leave %s\r\n", __func__); -} -static void debug_buffer_mgr_more(struct VP9Decoder_s *pbi) -{ - int i; - - if (!(debug & VP9_DEBUG_BUFMGR_MORE)) - return; - pr_info("vp9_param: (%d)\n", pbi->slice_idx); - for (i = 0; i < (RPM_END-RPM_BEGIN); i++) { - pr_info("%04x ", vp9_param.l.data[i]); - if (((i + 1) & 0xf) == 0) - pr_info("\n"); - } - pr_info("=============param==========\r\n"); - pr_info("profile %x\r\n", vp9_param.p.profile); - pr_info("show_existing_frame %x\r\n", - vp9_param.p.show_existing_frame); - pr_info("frame_to_show_idx %x\r\n", - vp9_param.p.frame_to_show_idx); - pr_info("frame_type %x\r\n", vp9_param.p.frame_type); - pr_info("show_frame %x\r\n", vp9_param.p.show_frame); - pr_info("e.r.r.o.r_resilient_mode %x\r\n", - vp9_param.p.error_resilient_mode); - pr_info("intra_only %x\r\n", vp9_param.p.intra_only); - pr_info("display_size_present %x\r\n", - vp9_param.p.display_size_present); - pr_info("reset_frame_context %x\r\n", - vp9_param.p.reset_frame_context); - pr_info("refresh_frame_flags %x\r\n", - vp9_param.p.refresh_frame_flags); - pr_info("bit_depth %x\r\n", vp9_param.p.bit_depth); - pr_info("width %x\r\n", vp9_param.p.width); - pr_info("height %x\r\n", vp9_param.p.height); - pr_info("display_width %x\r\n", vp9_param.p.display_width); - pr_info("display_height %x\r\n", vp9_param.p.display_height); - pr_info("ref_info %x\r\n", vp9_param.p.ref_info); - pr_info("same_frame_size %x\r\n", vp9_param.p.same_frame_size); - if (!(debug & VP9_DEBUG_DBG_LF_PRINT)) - return; - pr_info("mode_ref_delta_enabled: 0x%x\r\n", - vp9_param.p.mode_ref_delta_enabled); - pr_info("sharpness_level: 0x%x\r\n", - vp9_param.p.sharpness_level); - pr_info("ref_deltas: 0x%x, 0x%x, 0x%x, 0x%x\r\n", - vp9_param.p.ref_deltas[0], vp9_param.p.ref_deltas[1], - vp9_param.p.ref_deltas[2], vp9_param.p.ref_deltas[3]); - pr_info("mode_deltas: 0x%x, 0x%x\r\n", vp9_param.p.mode_deltas[0], - vp9_param.p.mode_deltas[1]); - pr_info("filter_level: 0x%x\r\n", vp9_param.p.filter_level); - pr_info("seg_enabled: 0x%x\r\n", vp9_param.p.seg_enabled); - pr_info("seg_abs_delta: 0x%x\r\n", vp9_param.p.seg_abs_delta); - pr_info("seg_lf_feature_enabled: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\r\n", - (vp9_param.p.seg_lf_info[0]>>15 & 1), - (vp9_param.p.seg_lf_info[1]>>15 & 1), - (vp9_param.p.seg_lf_info[2]>>15 & 1), - (vp9_param.p.seg_lf_info[3]>>15 & 1), - (vp9_param.p.seg_lf_info[4]>>15 & 1), - (vp9_param.p.seg_lf_info[5]>>15 & 1), - (vp9_param.p.seg_lf_info[6]>>15 & 1), - (vp9_param.p.seg_lf_info[7]>>15 & 1)); - pr_info("seg_lf_feature_data: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\r\n", - (vp9_param.p.seg_lf_info[0] & 0x13f), - (vp9_param.p.seg_lf_info[1] & 0x13f), - (vp9_param.p.seg_lf_info[2] & 0x13f), - (vp9_param.p.seg_lf_info[3] & 0x13f), - (vp9_param.p.seg_lf_info[4] & 0x13f), - (vp9_param.p.seg_lf_info[5] & 0x13f), - (vp9_param.p.seg_lf_info[6] & 0x13f), - (vp9_param.p.seg_lf_info[7] & 0x13f)); - -} - - -static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - if (pbi->double_write_mode & 0x10) - return; - if (cm->cur_fb_idx_mmu != INVALID_IDX) { - if (pbi->used_4k_num == -1) - pbi->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - decoder_mmu_box_free_idx_tail(pbi->mmu_box, - cm->cur_fb_idx_mmu, pbi->used_4k_num); - - cm->cur_fb_idx_mmu = INVALID_IDX; - pbi->used_4k_num = -1; - } -} - -#ifdef MULTI_INSTANCE_SUPPORT -static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi) -{ - struct VP9_Common_s *const cm = &pbi->common; - if (pbi->double_write_mode & 0x10) - return; - if (cm->cur_fb_idx_mmu != INVALID_IDX) { - decoder_mmu_box_free_idx(pbi->mmu_box, - cm->cur_fb_idx_mmu); - - cm->cur_fb_idx_mmu = INVALID_IDX; - pbi->used_4k_num = -1; - } -} -#endif - - -static void dec_again_process(struct VP9Decoder_s *pbi) -{ - amhevc_stop(); - pbi->dec_result = DEC_RESULT_AGAIN; - if (pbi->process_state == - PROC_STATE_DECODESLICE) { - pbi->process_state = - PROC_STATE_SENDAGAIN; - if (pbi->mmu_enable) - vp9_recycle_mmu_buf(pbi); - } - reset_process_time(pbi); - vdec_schedule_work(&pbi->work); -} - -int continue_decoding(struct VP9Decoder_s *pbi) -{ - int ret; - int i; - struct VP9_Common_s *const cm = &pbi->common; - debug_buffer_mgr_more(pbi); - - bit_depth_luma = vp9_param.p.bit_depth; - bit_depth_chroma = vp9_param.p.bit_depth; - - if (pbi->process_state != PROC_STATE_SENDAGAIN) { - ret = vp9_bufmgr_process(pbi, &vp9_param); - if (!pbi->m_ins_flag) - pbi->slice_idx++; - } else { - union param_u *params = &vp9_param; - if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { - ret = vp9_alloc_mmu(pbi, - cm->new_fb_idx, - params->p.width, - params->p.height, - params->p.bit_depth, - pbi->frame_mmu_map_addr); - if (ret >= 0) - cm->cur_fb_idx_mmu = cm->new_fb_idx; - else - pr_err("can't alloc need mmu1,idx %d ret =%d\n", - cm->new_fb_idx, - ret); - } else { - ret = 0; - } - WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, - (params->p.height << 16) | params->p.width); - } - if (ret < 0) { - pr_info("vp9_bufmgr_process=> %d, VP9_10B_DISCARD_NAL\r\n", - ret); - WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL); - cm->show_frame = 0; - if (pbi->mmu_enable) - vp9_recycle_mmu_buf(pbi); -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) { - pbi->dec_result = DEC_RESULT_DONE; -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num == 0) -#endif - amhevc_stop(); - vdec_schedule_work(&pbi->work); - } -#endif - return ret; - } else if (ret == 0) { - struct PIC_BUFFER_CONFIG_s *cur_pic_config - = &cm->cur_frame->buf; - cur_pic_config->decode_idx = pbi->frame_count; - - if (pbi->process_state != PROC_STATE_SENDAGAIN) { - if (!pbi->m_ins_flag) { - pbi->frame_count++; - decode_frame_count[pbi->index] - = pbi->frame_count; - } -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->chunk) { - cur_pic_config->pts = pbi->chunk->pts; - cur_pic_config->pts64 = pbi->chunk->pts64; - } -#endif - } - /*pr_info("Decode Frame Data %d\n", pbi->frame_count);*/ - config_pic_size(pbi, vp9_param.p.bit_depth); - - if ((pbi->common.frame_type != KEY_FRAME) - && (!pbi->common.intra_only)) { - config_mc_buffer(pbi, vp9_param.p.bit_depth); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num == 0) -#endif - config_mpred_hw(pbi); - } else { -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num == 0) -#endif - clear_mpred_hw(pbi); - } -#ifdef MCRCC_ENABLE - if (mcrcc_cache_alg_flag) - config_mcrcc_axi_hw_new(pbi); - else - config_mcrcc_axi_hw(pbi); -#endif - config_sao_hw(pbi, &vp9_param); - -#ifdef VP9_LPF_LVL_UPDATE - /* - * Get loop filter related picture level parameters from Parser - */ - pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled; - pbi->lf->sharpness_level = vp9_param.p.sharpness_level; - for (i = 0; i < 4; i++) - pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i]; - for (i = 0; i < 2; i++) - pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i]; - pbi->default_filt_lvl = vp9_param.p.filter_level; - pbi->seg_4lf->enabled = vp9_param.p.seg_enabled; - pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta; - for (i = 0; i < MAX_SEGMENTS; i++) - pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] & - 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0; - for (i = 0; i < MAX_SEGMENTS; i++) - pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF] - = (vp9_param.p.seg_lf_info[i] - & 0x100) ? -(vp9_param.p.seg_lf_info[i] - & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - /*Set pipeline mode*/ - uint32_t lpf_data32 = READ_VREG(HEVC_DBLK_CFGB); - /*dblk pipeline mode=1 for performance*/ - if (vp9_param.p.width >= 1280) - lpf_data32 |= (0x1 << 4); - else - lpf_data32 &= ~(0x3 << 4); - WRITE_VREG(HEVC_DBLK_CFGB, lpf_data32); - } - /* - * Update loop filter Thr/Lvl table for every frame - */ - /*pr_info - ("vp9_loop_filter (run before every frame decoding start)\n");*/ - vp9_loop_filter_frame_init(pbi->seg_4lf, - pbi->lfi, pbi->lf, pbi->default_filt_lvl); -#endif - /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/ - WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); - } else { - pr_info("Skip search next start code\n"); - cm->prev_fb_idx = INVALID_IDX; - /*skip, search next start code*/ - WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); - } - pbi->process_state = PROC_STATE_DECODESLICE; - if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { - if (pbi->last_put_idx < pbi->used_buf_num) { - struct RefCntBuffer_s *frame_bufs = - cm->buffer_pool->frame_bufs; - int i = pbi->last_put_idx; - /*free not used buffers.*/ - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.vf_ref == 0) && - (frame_bufs[i].buf.index != -1)) { - decoder_mmu_box_free_idx(pbi->mmu_box, i); - } - pbi->last_put_idx = -1; - } - } - return ret; -} - -static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) -{ - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data; - unsigned int dec_status = pbi->dec_status; - int i; - - /*if (pbi->wait_buf) - * pr_info("set wait_buf to 0\r\n"); - */ - if (pbi->eos) - return IRQ_HANDLED; - pbi->wait_buf = 0; -#ifdef MULTI_INSTANCE_SUPPORT -#ifdef SUPPORT_FB_DECODING -#ifdef FB_DECODING_TEST_SCHEDULE - if (pbi->s1_test_cmd == TEST_SET_PIC_DONE) - dec_status = HEVC_DECPIC_DATA_DONE; - else if (pbi->s1_test_cmd == TEST_SET_S2_DONE - && dec_status == HEVC_DECPIC_DATA_DONE) - dec_status = HEVC_S2_DECODING_DONE; - pbi->s1_test_cmd = TEST_SET_NONE; -#else - /*if (irq != VDEC_IRQ_0) - dec_status = HEVC_S2_DECODING_DONE;*/ -#endif - if (dec_status == HEVC_S2_DECODING_DONE) { - pbi->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&pbi->work); -#ifdef FB_DECODING_TEST_SCHEDULE - amhevc_stop(); - pbi->dec_s1_result = DEC_S1_RESULT_DONE; - vdec_schedule_work(&pbi->s1_work); -#endif - } else -#endif - if ((dec_status == HEVC_NAL_DECODE_DONE) || - (dec_status == HEVC_SEARCH_BUFEMPTY) || - (dec_status == HEVC_DECODE_BUFEMPTY) - ) { - if (pbi->m_ins_flag) { - reset_process_time(pbi); - if (!vdec_frame_based(hw_to_vdec(pbi))) - dec_again_process(pbi); - else { - pbi->dec_result = DEC_RESULT_GET_DATA; - vdec_schedule_work(&pbi->work); - } - } - pbi->process_busy = 0; - return IRQ_HANDLED; - } else if (dec_status == HEVC_DECPIC_DATA_DONE) { - if (pbi->m_ins_flag) { -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) { - reset_process_time(pbi); - inc_s1_pos(pbi); - trigger_schedule(pbi); -#ifdef FB_DECODING_TEST_SCHEDULE - pbi->s1_test_cmd = TEST_SET_S2_DONE; -#else - amhevc_stop(); - pbi->dec_s1_result = DEC_S1_RESULT_DONE; - vdec_schedule_work(&pbi->s1_work); -#endif - } else -#endif - { - reset_process_time(pbi); - if (pbi->vf_pre_count == 0) - vp9_bufmgr_postproc(pbi); - - pbi->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - if (mcrcc_cache_alg_flag) - dump_hit_rate(pbi); - vdec_schedule_work(&pbi->work); - } - } - - pbi->process_busy = 0; - return IRQ_HANDLED; - } -#endif - - if (dec_status == VP9_EOS) { -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) - reset_process_time(pbi); -#endif - - pr_info("VP9_EOS, flush buffer\r\n"); - - vp9_bufmgr_postproc(pbi); - - pr_info("send VP9_10B_DISCARD_NAL\r\n"); - WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL); - pbi->process_busy = 0; -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) { - pbi->dec_result = DEC_RESULT_DONE; - amhevc_stop(); - vdec_schedule_work(&pbi->work); - } -#endif - return IRQ_HANDLED; - } else if (dec_status == HEVC_DECODE_OVER_SIZE) { - pr_info("vp9 decode oversize !!\n"); - debug |= (VP9_DEBUG_DIS_LOC_ERROR_PROC | - VP9_DEBUG_DIS_SYS_ERROR_PROC); - pbi->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) - reset_process_time(pbi); -#endif - return IRQ_HANDLED; - } - - if (dec_status != VP9_HEAD_PARSER_DONE) { - pbi->process_busy = 0; - return IRQ_HANDLED; - } - -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) - reset_process_time(pbi); -#endif - if (pbi->process_state != PROC_STATE_SENDAGAIN -#ifdef SUPPORT_FB_DECODING - && pbi->used_stage_buf_num == 0 -#endif - ) { - if (pbi->mmu_enable) - vp9_recycle_mmu_buf_tail(pbi); - - - if (pbi->frame_count > 0) - vp9_bufmgr_postproc(pbi); - } - - if (debug & VP9_DEBUG_SEND_PARAM_WITH_REG) { - get_rpm_param(&vp9_param); - } else { - dma_sync_single_for_cpu( - amports_get_dma_device(), - pbi->rpm_phy_addr, - RPM_BUF_SIZE, - DMA_FROM_DEVICE); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) { - reset_process_time(pbi); - get_s1_buf(pbi); - - if (get_mv_buf(pbi, - &pbi->s1_mv_buf_index, - &pbi->s1_mpred_mv_wr_start_addr - ) < 0) { - vp9_print(pbi, 0, - "%s: Error get_mv_buf fail\n", - __func__); - } - - if (pbi->s1_buf == NULL) { - vp9_print(pbi, 0, - "%s: Error get_s1_buf fail\n", - __func__); - pbi->process_busy = 0; - return IRQ_HANDLED; - } - - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) { - pbi->s1_buf->rpm[i + 3 - ii] = - pbi->rpm_ptr[i + 3 - ii]; - pbi->s1_param.l.data[i + ii] = - pbi->rpm_ptr[i + 3 - ii]; - } - } - - mpred_process(pbi); -#ifdef FB_DECODING_TEST_SCHEDULE - pbi->dec_s1_result = - DEC_S1_RESULT_TEST_TRIGGER_DONE; - vdec_schedule_work(&pbi->s1_work); -#else - WRITE_VREG(HEVC_ASSIST_FB_MMU_MAP_ADDR, - pbi->stage_mmu_map_phy_addr + - pbi->s1_buf->index * STAGE_MMU_MAP_SIZE); - - start_s1_decoding(pbi); -#endif - start_process_time(pbi); - pbi->process_busy = 0; - return IRQ_HANDLED; - } else -#endif - { - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) - vp9_param.l.data[i + ii] = - pbi->rpm_ptr[i + 3 - ii]; - } - } - } - - continue_decoding(pbi); - pbi->process_busy = 0; - -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) - start_process_time(pbi); -#endif - - return IRQ_HANDLED; -} - -static irqreturn_t vvp9_isr(int irq, void *data) -{ - int i; - unsigned int dec_status; - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data; - unsigned int adapt_prob_status; - struct VP9_Common_s *const cm = &pbi->common; - uint debug_tag; - - WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); - - dec_status = READ_VREG(HEVC_DEC_STATUS_REG); - adapt_prob_status = READ_VREG(VP9_ADAPT_PROB_REG); - if (!pbi) - return IRQ_HANDLED; - if (pbi->init_flag == 0) - return IRQ_HANDLED; - if (pbi->process_busy)/*on process.*/ - return IRQ_HANDLED; - pbi->dec_status = dec_status; - pbi->process_busy = 1; - if (debug & VP9_DEBUG_BUFMGR) - pr_info("vp9 isr (%d) dec status = 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n", - irq, - dec_status, READ_VREG(HEVC_PARSER_LCU_START), - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_STREAM_START_ADDR), - READ_VREG(HEVC_STREAM_END_ADDR), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR) - ); -#ifdef SUPPORT_FB_DECODING - /*if (irq != VDEC_IRQ_0) - return IRQ_WAKE_THREAD;*/ -#endif - - debug_tag = READ_HREG(DEBUG_REG1); - if (debug_tag & 0x10000) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - pbi->lmem_phy_addr, - LMEM_BUF_SIZE, - DMA_FROM_DEVICE); - - pr_info("LMEM:\n", READ_HREG(DEBUG_REG1)); - for (i = 0; i < 0x400; i += 4) { - int ii; - if ((i & 0xf) == 0) - pr_info("%03x: ", i); - for (ii = 0; ii < 4; ii++) { - pr_info("%04x ", - pbi->lmem_ptr[i + 3 - ii]); - } - if (((i + ii) & 0xf) == 0) - pr_info("\n"); - } - - if ((udebug_pause_pos == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == pbi->slice_idx) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_HREG(DEBUG_REG2))) - pbi->ucode_pause_pos = udebug_pause_pos; - else if (debug_tag & 0x20000) - pbi->ucode_pause_pos = 0xffffffff; - if (pbi->ucode_pause_pos) - reset_process_time(pbi); - else - WRITE_HREG(DEBUG_REG1, 0); - } else if (debug_tag != 0) { - pr_info( - "dbg%x: %x lcu %x\n", READ_HREG(DEBUG_REG1), - READ_HREG(DEBUG_REG2), - READ_VREG(HEVC_PARSER_LCU_START)); - if ((udebug_pause_pos == (debug_tag & 0xffff)) && - (udebug_pause_decode_idx == 0 || - udebug_pause_decode_idx == pbi->slice_idx) && - (udebug_pause_val == 0 || - udebug_pause_val == READ_HREG(DEBUG_REG2))) - pbi->ucode_pause_pos = udebug_pause_pos; - if (pbi->ucode_pause_pos) - reset_process_time(pbi); - else - WRITE_HREG(DEBUG_REG1, 0); - pbi->process_busy = 0; - return IRQ_HANDLED; - } - -#ifdef MULTI_INSTANCE_SUPPORT - if (!pbi->m_ins_flag) { -#endif - if (pbi->error_flag == 1) { - pbi->error_flag = 2; - pbi->process_busy = 0; - return IRQ_HANDLED; - } else if (pbi->error_flag == 3) { - pbi->process_busy = 0; - return IRQ_HANDLED; - } - - if (get_free_buf_count(pbi) <= 0) { - /* - if (pbi->wait_buf == 0) - pr_info("set wait_buf to 1\r\n"); - */ - pbi->wait_buf = 1; - pbi->process_busy = 0; - return IRQ_HANDLED; - } -#ifdef MULTI_INSTANCE_SUPPORT - } -#endif - if ((adapt_prob_status & 0xff) == 0xfd) { - /*VP9_REQ_ADAPT_PROB*/ - int pre_fc = (cm->frame_type == KEY_FRAME) ? 1 : 0; - uint8_t *prev_prob_b = - ((uint8_t *)pbi->prob_buffer_addr) + - ((adapt_prob_status >> 8) * 0x1000); - uint8_t *cur_prob_b = - ((uint8_t *)pbi->prob_buffer_addr) + 0x4000; - uint8_t *count_b = (uint8_t *)pbi->count_buffer_addr; -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) - reset_process_time(pbi); -#endif - adapt_coef_probs(pbi->pic_count, - (cm->last_frame_type == KEY_FRAME), - pre_fc, (adapt_prob_status >> 8), - (unsigned int *)prev_prob_b, - (unsigned int *)cur_prob_b, (unsigned int *)count_b); - - memcpy(prev_prob_b, cur_prob_b, PROB_SIZE); - WRITE_VREG(VP9_ADAPT_PROB_REG, 0); - pbi->pic_count += 1; -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) - start_process_time(pbi); -#endif - - /*return IRQ_HANDLED;*/ - } - return IRQ_WAKE_THREAD; -} - -static void vp9_set_clk(struct work_struct *work) -{ - struct VP9Decoder_s *pbi = container_of(work, - struct VP9Decoder_s, work); - - int fps = 96000 / pbi->frame_dur; - - if (hevc_source_changed(VFORMAT_VP9, - frame_width, frame_height, fps) > 0) - pbi->saved_resolution = frame_width * - frame_height * fps; -} - -static void vvp9_put_timer_func(unsigned long arg) -{ - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)arg; - struct timer_list *timer = &pbi->timer; - uint8_t empty_flag; - unsigned int buf_level; - - enum receviver_start_e state = RECEIVER_INACTIVE; - - if (pbi->m_ins_flag) { - if (hw_to_vdec(pbi)->next_status - == VDEC_STATUS_DISCONNECTED) { -#ifdef SUPPORT_FB_DECODING - if (pbi->run2_busy) - return; - - pbi->dec_s1_result = DEC_S1_RESULT_FORCE_EXIT; - vdec_schedule_work(&pbi->s1_work); -#endif - pbi->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&pbi->work); - pr_debug( - "vdec requested to be disconnected\n"); - return; - } - } - if (pbi->init_flag == 0) { - if (pbi->stat & STAT_TIMER_ARM) { - timer->expires = jiffies + PUT_INTERVAL; - add_timer(&pbi->timer); - } - return; - } - if (pbi->m_ins_flag == 0) { - if (vf_get_receiver(pbi->provider_name)) { - state = - vf_notify_receiver(pbi->provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - if ((state == RECEIVER_STATE_NULL) - || (state == RECEIVER_STATE_NONE)) - state = RECEIVER_INACTIVE; - } else - state = RECEIVER_INACTIVE; - - empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1; - /* error watchdog */ - if (empty_flag == 0) { - /* decoder has input */ - if ((debug & VP9_DEBUG_DIS_LOC_ERROR_PROC) == 0) { - - buf_level = READ_VREG(HEVC_STREAM_LEVEL); - /* receiver has no buffer to recycle */ - if ((state == RECEIVER_INACTIVE) && - (kfifo_is_empty(&pbi->display_q) && - buf_level > 0x200) - ) { - WRITE_VREG - (HEVC_ASSIST_MBOX0_IRQ_REG, - 0x1); - } - } - - if ((debug & VP9_DEBUG_DIS_SYS_ERROR_PROC) == 0) { - /* receiver has no buffer to recycle */ - /*if ((state == RECEIVER_INACTIVE) && - * (kfifo_is_empty(&pbi->display_q))) { - *pr_info("vp9 something error,need reset\n"); - *} - */ - } - } - } -#ifdef MULTI_INSTANCE_SUPPORT - else { - if ( - (decode_timeout_val > 0) && - (pbi->start_process_time > 0) && - ((1000 * (jiffies - pbi->start_process_time) / HZ) - > decode_timeout_val) - ) { - int current_lcu_idx = - READ_VREG(HEVC_PARSER_LCU_START) - & 0xffffff; - if (pbi->last_lcu_idx == current_lcu_idx) { - if (pbi->decode_timeout_count > 0) - pbi->decode_timeout_count--; - if (pbi->decode_timeout_count == 0) { - if (input_frame_based( - hw_to_vdec(pbi)) || - (READ_VREG(HEVC_STREAM_LEVEL) > 0x200)) - timeout_process(pbi); - else { - vp9_print(pbi, 0, - "timeout & empty, again\n"); - dec_again_process(pbi); - } - } - } else { - start_process_time(pbi); - pbi->last_lcu_idx = current_lcu_idx; - } - } - } -#endif - - if ((pbi->ucode_pause_pos != 0) && - (pbi->ucode_pause_pos != 0xffffffff) && - udebug_pause_pos != pbi->ucode_pause_pos) { - pbi->ucode_pause_pos = 0; - WRITE_HREG(DEBUG_REG1, 0); - } -#ifdef MULTI_INSTANCE_SUPPORT - if (debug & VP9_DEBUG_FORCE_SEND_AGAIN) { - pr_info( - "Force Send Again\r\n"); - debug &= ~VP9_DEBUG_FORCE_SEND_AGAIN; - reset_process_time(pbi); - pbi->dec_result = DEC_RESULT_AGAIN; - if (pbi->process_state == - PROC_STATE_DECODESLICE) { - if (pbi->mmu_enable) - vp9_recycle_mmu_buf(pbi); - pbi->process_state = - PROC_STATE_SENDAGAIN; - } - amhevc_stop(); - - vdec_schedule_work(&pbi->work); - } - - if (debug & VP9_DEBUG_DUMP_DATA) { - debug &= ~VP9_DEBUG_DUMP_DATA; - vp9_print(pbi, 0, - "%s: chunk size 0x%x off 0x%x sum 0x%x\n", - __func__, - pbi->chunk->size, - pbi->chunk->offset, - get_data_check_sum(pbi, pbi->chunk->size) - ); - dump_data(pbi, pbi->chunk->size); - } -#endif - if (debug & VP9_DEBUG_DUMP_PIC_LIST) { - dump_pic_list(pbi); - debug &= ~VP9_DEBUG_DUMP_PIC_LIST; - } - if (debug & VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC) { - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); - debug &= ~VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC; - } - /*if (debug & VP9_DEBUG_HW_RESET) { - }*/ - - if (radr != 0) { - if (rval != 0) { - WRITE_VREG(radr, rval); - pr_info("WRITE_VREG(%x,%x)\n", radr, rval); - } else - pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); - rval = 0; - radr = 0; - } - if (pop_shorts != 0) { - int i; - u32 sum = 0; - - pr_info("pop stream 0x%x shorts\r\n", pop_shorts); - for (i = 0; i < pop_shorts; i++) { - u32 data = - (READ_HREG(HEVC_SHIFTED_DATA) >> 16); - WRITE_HREG(HEVC_SHIFT_COMMAND, - (1<<7)|16); - if ((i & 0xf) == 0) - pr_info("%04x:", i); - pr_info("%04x ", data); - if (((i + 1) & 0xf) == 0) - pr_info("\r\n"); - sum += data; - } - pr_info("\r\nsum = %x\r\n", sum); - pop_shorts = 0; - } - if (dbg_cmd != 0) { - if (dbg_cmd == 1) { - u32 disp_laddr; - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && - get_double_write_mode(pbi) == 0) { - disp_laddr = - READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; - } else { - struct canvas_s cur_canvas; - - canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) - & 0xff), &cur_canvas); - disp_laddr = cur_canvas.addr; - } - pr_info("current displayed buffer address %x\r\n", - disp_laddr); - } - dbg_cmd = 0; - } - /*don't changed at start.*/ - if (pbi->get_frame_dur && pbi->show_frame_num > 60 && - pbi->frame_dur > 0 && pbi->saved_resolution != - frame_width * frame_height * - (96000 / pbi->frame_dur)) - schedule_work(&pbi->set_clk_work); - - timer->expires = jiffies + PUT_INTERVAL; - add_timer(timer); -} - - -int vvp9_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) -{ - struct VP9Decoder_s *vp9 = - (struct VP9Decoder_s *)vdec->private; - - if (!vp9) - return -1; - - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; - if (vp9->frame_dur != 0) - vstatus->frame_rate = 96000 / vp9->frame_dur; - else - vstatus->frame_rate = -1; - vstatus->error_count = 0; - vstatus->status = vp9->stat | vp9->fatal_error; - vstatus->frame_dur = vp9->frame_dur; -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - vstatus->bit_rate = gvs->bit_rate; - vstatus->frame_data = gvs->frame_data; - vstatus->total_data = gvs->total_data; - vstatus->frame_count = gvs->frame_count; - vstatus->error_frame_count = gvs->error_frame_count; - vstatus->drop_frame_count = gvs->drop_frame_count; - vstatus->total_data = gvs->total_data; - vstatus->samp_cnt = gvs->samp_cnt; - vstatus->offset = gvs->offset; - snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), - "%s", DRIVER_NAME); -#endif - return 0; -} - -int vvp9_set_isreset(struct vdec_s *vdec, int isreset) -{ - is_reset = isreset; - return 0; -} - -#if 0 -static void VP9_DECODE_INIT(void) -{ - /* enable vp9 clocks */ - WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); - /* *************************************************************** */ - /* Power ON HEVC */ - /* *************************************************************** */ - /* Powerup HEVC */ - WRITE_VREG(AO_RTI_GEN_PWR_SLEEP0, - READ_VREG(AO_RTI_GEN_PWR_SLEEP0) & (~(0x3 << 6))); - WRITE_VREG(DOS_MEM_PD_HEVC, 0x0); - WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) | (0x3ffff << 2)); - WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) & (~(0x3ffff << 2))); - /* remove isolations */ - WRITE_VREG(AO_RTI_GEN_PWR_ISO0, - READ_VREG(AO_RTI_GEN_PWR_ISO0) & (~(0x3 << 10))); - -} -#endif - -static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask) -{ - unsigned int data32; - /* VP9_DECODE_INIT(); */ - vp9_config_work_space_hw(pbi, mask); - if (mask & HW_MASK_BACK) - init_pic_list_hw(pbi); - - vp9_init_decoder_hw(pbi, mask); - -#ifdef VP9_LPF_LVL_UPDATE - if (mask & HW_MASK_BACK) - vp9_loop_filter_init(pbi); -#endif - - if ((mask & HW_MASK_FRONT) == 0) - return; -#if 1 - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("%s\n", __func__); - data32 = READ_VREG(HEVC_STREAM_CONTROL); - data32 = data32 | - (1 << 0)/*stream_fetch_enable*/ - ; - WRITE_VREG(HEVC_STREAM_CONTROL, data32); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - if (debug & VP9_DEBUG_BUFMGR) - pr_info("[test.c] Config STREAM_FIFO_CTL\n"); - data32 = READ_VREG(HEVC_STREAM_FIFO_CTL); - data32 = data32 | - (1 << 29) // stream_fifo_hole - ; - WRITE_VREG(HEVC_STREAM_FIFO_CTL, data32); - } -#if 0 - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x00000100) { - pr_info("vp9 prot init error %d\n", __LINE__); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x00000300) { - pr_info("vp9 prot init error %d\n", __LINE__); - return; - } - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); - data32 = READ_VREG(HEVC_SHIFT_STARTCODE); - if (data32 != 0x12345678) { - pr_info("vp9 prot init error %d\n", __LINE__); - return; - } - data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); - if (data32 != 0x9abcdef0) { - pr_info("vp9 prot init error %d\n", __LINE__); - return; - } -#endif - WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x000000001); - WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000300); -#endif - - - - WRITE_VREG(HEVC_WAIT_FLAG, 1); - - /* WRITE_VREG(HEVC_MPSR, 1); */ - - /* clear mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); - - /* enable mailbox interrupt */ - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1); - - /* disable PSCALE for hardware sharing */ - WRITE_VREG(HEVC_PSCALE_CTRL, 0); - - WRITE_VREG(DEBUG_REG1, 0x0); - /*check vps/sps/pps/i-slice in ucode*/ - WRITE_VREG(NAL_SEARCH_CTL, 0x8); - - WRITE_VREG(DECODE_STOP_POS, udebug_flag); -#ifdef SUPPORT_FB_DECODING -#ifndef FB_DECODING_TEST_SCHEDULE - if (pbi->used_stage_buf_num > 0) { - if (mask & HW_MASK_FRONT) { - data32 = READ_VREG( - HEVC_ASSIST_HED_FB_W_CTL); - data32 = data32 | - (1 << 0) /*hed_fb_wr_en*/ - ; - WRITE_VREG(HEVC_ASSIST_HED_FB_W_CTL, - data32); - } - if (mask & HW_MASK_BACK) { - data32 = READ_VREG( - HEVC_ASSIST_HED_FB_R_CTL); - while (data32 & (1 << 7)) { - /*wait finish*/ - data32 = READ_VREG( - HEVC_ASSIST_HED_FB_R_CTL); - } - data32 &= (~(0x1 << 0)); - /*hed_fb_rd_addr_auto_rd*/ - data32 &= (~(0x1 << 1)); - /*rd_id = 0, hed_rd_map_auto_halt_num, - after wr 2 ready, then start reading*/ - data32 |= (0x2 << 16); - WRITE_VREG(HEVC_ASSIST_HED_FB_R_CTL, - data32); - - data32 |= (0x1 << 11); /*hed_rd_map_auto_halt_en*/ - data32 |= (0x1 << 1); /*hed_fb_rd_addr_auto_rd*/ - data32 |= (0x1 << 0); /*hed_fb_rd_en*/ - WRITE_VREG(HEVC_ASSIST_HED_FB_R_CTL, - data32); - } - - } -#endif -#endif -} - -static int vvp9_local_init(struct VP9Decoder_s *pbi) -{ - int i; - int ret; - int width, height; - if (alloc_lf_buf(pbi) < 0) - return -1; - - pbi->gvs = vzalloc(sizeof(struct vdec_info)); - if (NULL == pbi->gvs) { - pr_info("the struct of vdec status malloc failed.\n"); - return -1; - } -#ifdef DEBUG_PTS - pbi->pts_missed = 0; - pbi->pts_hit = 0; -#endif - pbi->new_frame_displayed = 0; - pbi->last_put_idx = -1; - pbi->saved_resolution = 0; - pbi->get_frame_dur = false; - on_no_keyframe_skiped = 0; - pbi->duration_from_pts_done = 0; - pbi->vp9_first_pts_ready = 0; - pbi->frame_cnt_window = 0; - width = pbi->vvp9_amstream_dec_info.width; - height = pbi->vvp9_amstream_dec_info.height; - pbi->frame_dur = - (pbi->vvp9_amstream_dec_info.rate == - 0) ? 3200 : pbi->vvp9_amstream_dec_info.rate; - if (width && height) - pbi->frame_ar = height * 0x100 / width; -/* - *TODO:FOR VERSION - */ - pr_info("vp9: ver (%d,%d) decinfo: %dx%d rate=%d\n", vp9_version, - 0, width, height, pbi->frame_dur); - - if (pbi->frame_dur == 0) - pbi->frame_dur = 96000 / 24; - - INIT_KFIFO(pbi->display_q); - INIT_KFIFO(pbi->newframe_q); - - - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &pbi->vfpool[i]; - - pbi->vfpool[i].index = -1; - kfifo_put(&pbi->newframe_q, vf); - } - - - ret = vp9_local_init(pbi); - - if (!pbi->pts_unstable) { - pbi->pts_unstable = - (pbi->vvp9_amstream_dec_info.rate == 0)?1:0; - pr_info("set pts unstable\n"); - } - - return ret; -} - - -#ifdef MULTI_INSTANCE_SUPPORT -static s32 vvp9_init(struct vdec_s *vdec) -{ - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)vdec->private; -#else -static s32 vvp9_init(struct VP9Decoder_s *pbi) -{ -#endif - int ret; - int fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; - - pbi->stat |= STAT_TIMER_INIT; - - if (vvp9_local_init(pbi) < 0) - return -EBUSY; - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - if (get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data) < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = fw_size; - - INIT_WORK(&pbi->set_clk_work, vp9_set_clk); - init_timer(&pbi->timer); - -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) { - pbi->timer.data = (ulong) pbi; - pbi->timer.function = vvp9_put_timer_func; - pbi->timer.expires = jiffies + PUT_INTERVAL; - - /*add_timer(&pbi->timer); - - pbi->stat |= STAT_TIMER_ARM; - pbi->stat |= STAT_ISR_REG;*/ - - INIT_WORK(&pbi->work, vp9_work); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) - INIT_WORK(&pbi->s1_work, vp9_s1_work); -#endif - pbi->fw = fw; - - return 0; - } -#endif - hevc_enable_DMC(hw_to_vdec(pbi)); - amhevc_enable(); - - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, fw->data); - if (ret < 0) { - amhevc_disable(); - vfree(fw); - pr_err("VP9: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - return -EBUSY; - } - - vfree(fw); - - pbi->stat |= STAT_MC_LOAD; - - /* enable AMRISC side protocol */ - vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK); - - if (vdec_request_threaded_irq(VDEC_IRQ_0, - vvp9_isr, - vvp9_isr_thread_fn, - IRQF_ONESHOT,/*run thread on this irq disabled*/ - "vvp9-irq", (void *)pbi)) { - pr_info("vvp9 irq register error.\n"); - amhevc_disable(); - return -ENOENT; - } - - pbi->stat |= STAT_ISR_REG; - - pbi->provider_name = PROVIDER_NAME; -#ifdef MULTI_INSTANCE_SUPPORT - vf_provider_init(&vvp9_vf_prov, PROVIDER_NAME, - &vvp9_vf_provider, pbi); - vf_reg_provider(&vvp9_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); - if (pbi->frame_dur != 0) { - if (!is_reset) - vf_notify_receiver(pbi->provider_name, - VFRAME_EVENT_PROVIDER_FR_HINT, - (void *) - ((unsigned long)pbi->frame_dur)); - } -#else - vf_provider_init(&vvp9_vf_prov, PROVIDER_NAME, &vvp9_vf_provider, - pbi); - vf_reg_provider(&vvp9_vf_prov); - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); - if (!is_reset) - vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, - (void *)((unsigned long)pbi->frame_dur)); -#endif - pbi->stat |= STAT_VF_HOOK; - - pbi->timer.data = (ulong)pbi; - pbi->timer.function = vvp9_put_timer_func; - pbi->timer.expires = jiffies + PUT_INTERVAL; - - pbi->stat |= STAT_VDEC_RUN; - - add_timer(&pbi->timer); - - pbi->stat |= STAT_TIMER_ARM; - - amhevc_start(); - - pbi->init_flag = 1; - pbi->process_busy = 0; - pr_info("%d, vvp9_init, RP=0x%x\n", - __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); - return 0; -} - -static int vmvp9_stop(struct VP9Decoder_s *pbi) -{ - pbi->init_flag = 0; - - if (pbi->stat & STAT_VDEC_RUN) { - amhevc_stop(); - pbi->stat &= ~STAT_VDEC_RUN; - } - if (pbi->stat & STAT_ISR_REG) { - vdec_free_irq(VDEC_IRQ_0, (void *)pbi); - pbi->stat &= ~STAT_ISR_REG; - } - if (pbi->stat & STAT_TIMER_ARM) { - del_timer_sync(&pbi->timer); - pbi->stat &= ~STAT_TIMER_ARM; - } - - if (pbi->stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(pbi->provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - - vf_unreg_provider(&vvp9_vf_prov); - pbi->stat &= ~STAT_VF_HOOK; - } - vp9_local_uninit(pbi); - reset_process_time(pbi); - cancel_work_sync(&pbi->work); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) - cancel_work_sync(&pbi->s1_work); -#endif - cancel_work_sync(&pbi->set_clk_work); - uninit_mmu_buffers(pbi); - if (pbi->fw) - vfree(pbi->fw); - pbi->fw = NULL; - return 0; -} - -static int vvp9_stop(struct VP9Decoder_s *pbi) -{ - - pbi->init_flag = 0; - pbi->first_sc_checked = 0; - if (pbi->stat & STAT_VDEC_RUN) { - amhevc_stop(); - pbi->stat &= ~STAT_VDEC_RUN; - } - - if (pbi->stat & STAT_ISR_REG) { -#ifdef MULTI_INSTANCE_SUPPORT - if (!pbi->m_ins_flag) -#endif - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0); - vdec_free_irq(VDEC_IRQ_0, (void *)pbi); - pbi->stat &= ~STAT_ISR_REG; - } - - if (pbi->stat & STAT_TIMER_ARM) { - del_timer_sync(&pbi->timer); - pbi->stat &= ~STAT_TIMER_ARM; - } - - if (pbi->stat & STAT_VF_HOOK) { - if (!is_reset) - vf_notify_receiver(pbi->provider_name, - VFRAME_EVENT_PROVIDER_FR_END_HINT, - NULL); - - vf_unreg_provider(&vvp9_vf_prov); - pbi->stat &= ~STAT_VF_HOOK; - } - vp9_local_uninit(pbi); - -#ifdef MULTI_INSTANCE_SUPPORT - if (pbi->m_ins_flag) { - cancel_work_sync(&pbi->work); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) - cancel_work_sync(&pbi->s1_work); -#endif - } else - amhevc_disable(); -#else - amhevc_disable(); -#endif - cancel_work_sync(&pbi->set_clk_work); - uninit_mmu_buffers(pbi); - - vfree(pbi->fw); - pbi->fw = NULL; - return 0; -} -static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi) -{ - int tvp_flag = vdec_secure(hw_to_vdec(pbi)) ? - CODEC_MM_FLAGS_TVP : 0; - int buf_size = 48; - - if ((pbi->max_pic_w * pbi->max_pic_h > 1280*736) && - (pbi->max_pic_w * pbi->max_pic_h <= 1920*1088)) { - buf_size = 12; - } else if ((pbi->max_pic_w * pbi->max_pic_h > 0) && - (pbi->max_pic_w * pbi->max_pic_h <= 1280*736)) { - buf_size = 4; - } - pbi->need_cache_size = buf_size * SZ_1M; - pbi->sc_start_time = get_jiffies_64(); - if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { - pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, - pbi->index, FRAME_BUFFERS, - pbi->need_cache_size, - tvp_flag - ); - if (!pbi->mmu_box) { - pr_err("vp9 alloc mmu box failed!!\n"); - return -1; - } - } - pbi->bmmu_box = decoder_bmmu_box_alloc_box( - DRIVER_NAME, - pbi->index, - MAX_BMMU_BUFFER_NUM, - 4 + PAGE_SHIFT, - CODEC_MM_FLAGS_CMA_CLEAR | - CODEC_MM_FLAGS_FOR_VDECODER | - tvp_flag); - if (!pbi->bmmu_box) { - pr_err("vp9 alloc bmmu box failed!!\n"); - return -1; - } - return 0; -} - -static struct VP9Decoder_s *gHevc; - -static int amvdec_vp9_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - struct BUF_s BUF[MAX_BUF_NUM]; - struct VP9Decoder_s *pbi; - int ret; -#ifndef MULTI_INSTANCE_SUPPORT - int i; -#endif - pr_debug("%s\n", __func__); - - mutex_lock(&vvp9_mutex); - pbi = vmalloc(sizeof(struct VP9Decoder_s)); - if (pbi == NULL) { - pr_info("\namvdec_vp9 device data allocation failed\n"); - mutex_unlock(&vvp9_mutex); - return -ENOMEM; - } - - gHevc = pbi; - memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - memset(pbi, 0, sizeof(struct VP9Decoder_s)); - memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - - pbi->init_flag = 0; - pbi->first_sc_checked= 0; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - vp9_max_pic_w = 8192; - vp9_max_pic_h = 4608; - } - pbi->max_pic_w = vp9_max_pic_w; - pbi->max_pic_h = vp9_max_pic_h; - -#ifdef MULTI_INSTANCE_SUPPORT - pbi->eos = 0; - pbi->start_process_time = 0; - pbi->timeout_num = 0; -#endif - pbi->fatal_error = 0; - pbi->show_frame_num = 0; - if (pdata == NULL) { - pr_info("\namvdec_vp9 memory resource undefined.\n"); - vfree(pbi); - mutex_unlock(&vvp9_mutex); - return -EFAULT; - } - pbi->m_ins_flag = 0; -#ifdef MULTI_INSTANCE_SUPPORT - pbi->platform_dev = pdev; - platform_set_drvdata(pdev, pdata); -#endif - pbi->double_write_mode = double_write_mode; - pbi->mmu_enable = 1; - if (amvdec_vp9_mmu_init(pbi) < 0) { - vfree(pbi); - mutex_unlock(&vvp9_mutex); - pr_err("vp9 alloc bmmu box failed!!\n"); - return -1; - } - - ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, WORK_SPACE_BUF_ID, - work_buf_size, DRIVER_NAME, &pdata->mem_start); - if (ret < 0) { - uninit_mmu_buffers(pbi); - vfree(pbi); - mutex_unlock(&vvp9_mutex); - return ret; - } - pbi->buf_size = work_buf_size; - -#ifdef MULTI_INSTANCE_SUPPORT - pbi->buf_start = pdata->mem_start; -#else - if (!pbi->mmu_enable) - pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size; - - for (i = 0; i < WORK_BUF_SPEC_NUM; i++) - amvvp9_workbuff_spec[i].start_adr = pdata->mem_start; -#endif - - - if (debug) { - pr_info("===VP9 decoder mem resource 0x%lx size 0x%x\n", - pdata->mem_start, pbi->buf_size); - } - - if (pdata->sys_info) - pbi->vvp9_amstream_dec_info = *pdata->sys_info; - else { - pbi->vvp9_amstream_dec_info.width = 0; - pbi->vvp9_amstream_dec_info.height = 0; - pbi->vvp9_amstream_dec_info.rate = 30; - } -#ifdef MULTI_INSTANCE_SUPPORT - pbi->cma_dev = pdata->cma_dev; -#else - cma_dev = pdata->cma_dev; -#endif - -#ifdef MULTI_INSTANCE_SUPPORT - pdata->private = pbi; - pdata->dec_status = vvp9_dec_status; - pdata->set_isreset = vvp9_set_isreset; - is_reset = 0; - if (vvp9_init(pdata) < 0) { -#else - if (vvp9_init(pbi) < 0) { -#endif - pr_info("\namvdec_vp9 init failed.\n"); - vp9_local_uninit(pbi); - uninit_mmu_buffers(pbi); - vfree(pbi); - pdata->dec_status = NULL; - mutex_unlock(&vvp9_mutex); - return -ENODEV; - } - /*set the max clk for smooth playing...*/ - hevc_source_changed(VFORMAT_VP9, - 4096, 2048, 60); - mutex_unlock(&vvp9_mutex); - - return 0; -} - -static int amvdec_vp9_remove(struct platform_device *pdev) -{ - struct VP9Decoder_s *pbi = gHevc; - - if (debug) - pr_info("amvdec_vp9_remove\n"); - - mutex_lock(&vvp9_mutex); - - vvp9_stop(pbi); - - - hevc_source_changed(VFORMAT_VP9, 0, 0, 0); - - -#ifdef DEBUG_PTS - pr_info("pts missed %ld, pts hit %ld, duration %d\n", - pbi->pts_missed, pbi->pts_hit, pbi->frame_dur); -#endif - vfree(pbi); - mutex_unlock(&vvp9_mutex); - - return 0; -} - -/****************************************/ - -static struct platform_driver amvdec_vp9_driver = { - .probe = amvdec_vp9_probe, - .remove = amvdec_vp9_remove, -#ifdef CONFIG_PM - .suspend = amhevc_suspend, - .resume = amhevc_resume, -#endif - .driver = { - .name = DRIVER_NAME, - } -}; - -static struct codec_profile_t amvdec_vp9_profile = { - .name = "vp9", - .profile = "" -}; - -static unsigned char get_data_check_sum - (struct VP9Decoder_s *pbi, int size) -{ - int jj; - int sum = 0; - u8 *data = NULL; - - if (!pbi->chunk->block->is_mapped) - data = codec_mm_vmap(pbi->chunk->block->start + - pbi->chunk->offset, size); - else - data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; - - for (jj = 0; jj < size; jj++) - sum += data[jj]; - - if (!pbi->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - return sum; -} - -static void dump_data(struct VP9Decoder_s *pbi, int size) -{ - int jj; - u8 *data = NULL; - int padding_size = pbi->chunk->offset & - (VDEC_FIFO_ALIGN - 1); - - if (!pbi->chunk->block->is_mapped) - data = codec_mm_vmap(pbi->chunk->block->start + - pbi->chunk->offset, size); - else - data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; - - vp9_print(pbi, 0, "padding: "); - for (jj = padding_size; jj > 0; jj--) - vp9_print_cont(pbi, - 0, - "%02x ", *(data - jj)); - vp9_print_cont(pbi, 0, "data adr %p\n", - data); - - for (jj = 0; jj < size; jj++) { - if ((jj & 0xf) == 0) - vp9_print(pbi, - 0, - "%06x:", jj); - vp9_print_cont(pbi, - 0, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - vp9_print(pbi, - 0, - "\n"); - } - vp9_print(pbi, - 0, - "\n"); - - if (!pbi->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); -} - -static void vp9_work(struct work_struct *work) -{ - struct VP9Decoder_s *pbi = container_of(work, - struct VP9Decoder_s, work); - struct vdec_s *vdec = hw_to_vdec(pbi); - /* finished decoding one frame or error, - * notify vdec core to switch context - */ - vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, - "%s dec_result %d %x %x %x\n", - __func__, - pbi->dec_result, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR)); - - if (((pbi->dec_result == DEC_RESULT_GET_DATA) || - (pbi->dec_result == DEC_RESULT_GET_DATA_RETRY)) - && (hw_to_vdec(pbi)->next_status != - VDEC_STATUS_DISCONNECTED)) { - if (!vdec_has_more_input(vdec)) { - pbi->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&pbi->work); - return; - } - - if (pbi->dec_result == DEC_RESULT_GET_DATA) { - vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, - "%s DEC_RESULT_GET_DATA %x %x %x\n", - __func__, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR)); - vdec_vframe_dirty(vdec, pbi->chunk); - vdec_clean_input(vdec); - } - - if (get_free_buf_count(pbi) >= - run_ready_min_buf_num) { - int r; - int decode_size; - r = vdec_prepare_input(vdec, &pbi->chunk); - if (r < 0) { - pbi->dec_result = DEC_RESULT_GET_DATA_RETRY; - - vp9_print(pbi, - PRINT_FLAG_VDEC_DETAIL, - "amvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&pbi->work); - return; - } - pbi->dec_result = DEC_RESULT_NONE; - vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, - "%s: chunk size 0x%x sum 0x%x\n", - __func__, r, - (debug & PRINT_FLAG_VDEC_STATUS) ? - get_data_check_sum(pbi, r) : 0 - ); - - if (debug & PRINT_FLAG_VDEC_DATA) - dump_data(pbi, pbi->chunk->size); - - decode_size = pbi->chunk->size + - (pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - - WRITE_VREG(HEVC_DECODE_SIZE, - READ_VREG(HEVC_DECODE_SIZE) + decode_size); - - vdec_enable_input(vdec); - - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - - start_process_time(pbi); - - } else{ - pbi->dec_result = DEC_RESULT_GET_DATA_RETRY; - - vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, - "amvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&pbi->work); - } - return; - } else if (pbi->dec_result == DEC_RESULT_DONE) { -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) { -#ifndef FB_DECODING_TEST_SCHEDULE - if (!is_s2_decoding_finished(pbi)) { - vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, - "s2 decoding not done, check again later\n"); - vdec_schedule_work(&pbi->work); - } -#endif - inc_s2_pos(pbi); - if (mcrcc_cache_alg_flag) - dump_hit_rate(pbi); - } -#endif - /* if (!pbi->ctx_valid) - pbi->ctx_valid = 1; */ - pbi->slice_idx++; - pbi->frame_count++; - pbi->process_state = PROC_STATE_INIT; - decode_frame_count[pbi->index] = pbi->frame_count; - - if (pbi->mmu_enable) - pbi->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, - "%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n", - __func__, - pbi->frame_count, - pbi->dec_result, - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - READ_VREG(HEVC_SHIFT_BYTE_COUNT), - READ_VREG(HEVC_SHIFT_BYTE_COUNT) - - pbi->start_shift_bytes - ); - vdec_vframe_dirty(hw_to_vdec(pbi), pbi->chunk); - } else if (pbi->dec_result == DEC_RESULT_AGAIN) { - /* - stream base: stream buf empty or timeout - frame base: vdec_prepare_input fail - */ - if (!vdec_has_more_input(vdec)) { - pbi->dec_result = DEC_RESULT_EOS; - vdec_schedule_work(&pbi->work); - return; - } - } else if (pbi->dec_result == DEC_RESULT_EOS) { - vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, - "%s: end of stream\n", - __func__); - pbi->eos = 1; - vp9_bufmgr_postproc(pbi); - vdec_vframe_dirty(hw_to_vdec(pbi), pbi->chunk); - } else if (pbi->dec_result == DEC_RESULT_FORCE_EXIT) { - vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, - "%s: force exit\n", - __func__); - if (pbi->stat & STAT_VDEC_RUN) { - amhevc_stop(); - pbi->stat &= ~STAT_VDEC_RUN; - } - - if (pbi->stat & STAT_ISR_REG) { -#ifdef MULTI_INSTANCE_SUPPORT - if (!pbi->m_ins_flag) -#endif - WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0); - vdec_free_irq(VDEC_IRQ_0, (void *)pbi); - pbi->stat &= ~STAT_ISR_REG; - } - } - if (pbi->stat & STAT_VDEC_RUN) { - amhevc_stop(); - pbi->stat &= ~STAT_VDEC_RUN; - } - - if (pbi->stat & STAT_TIMER_ARM) { - del_timer_sync(&pbi->timer); - pbi->stat &= ~STAT_TIMER_ARM; - } - /* mark itself has all HW resource released and input released */ -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) - vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_HEVC_BACK); - else - vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1 - | CORE_MASK_HEVC - | CORE_MASK_HEVC_FRONT - | CORE_MASK_HEVC_BACK - ); -#else - if (vdec->parallel_dec == 1) - vdec_core_finish_run(vdec, CORE_MASK_HEVC); - else - vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1 - | CORE_MASK_HEVC); -#endif - trigger_schedule(pbi); -} - -static int vp9_hw_ctx_restore(struct VP9Decoder_s *pbi) -{ - /* new to do ... */ -#if (!defined SUPPORT_FB_DECODING) - vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK); -#elif (defined FB_DECODING_TEST_SCHEDULE) - vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK); -#else - if (pbi->used_stage_buf_num > 0) - vvp9_prot_init(pbi, HW_MASK_FRONT); - else - vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK); -#endif - return 0; -} -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - int tvp = vdec_secure(hw_to_vdec(pbi)) ? - CODEC_MM_FLAGS_TVP : 0; - unsigned long ret = 0; - - if (pbi->eos) - return ret; - if (!pbi->first_sc_checked && pbi->mmu_enable) { - int size = decoder_mmu_box_sc_check(pbi->mmu_box, tvp); - pbi->first_sc_checked = 1; - vp9_print(pbi, 0, "vp9 cached=%d need_size=%d speed= %d ms\n", - size, (pbi->need_cache_size >> PAGE_SHIFT), - (int)(get_jiffies_64() - pbi->sc_start_time) * 1000/HZ); - } -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) { - if (mask & CORE_MASK_HEVC_FRONT) { - if (get_free_stage_buf_num(pbi) > 0 - && mv_buf_available(pbi)) - ret |= CORE_MASK_HEVC_FRONT; - } - if (mask & CORE_MASK_HEVC_BACK) { - if (s2_buf_available(pbi) && - (get_free_buf_count(pbi) >= - run_ready_min_buf_num)) { - ret |= CORE_MASK_HEVC_BACK; - pbi->back_not_run_ready = 0; - } else - pbi->back_not_run_ready = 1; -#if 0 - if (get_free_buf_count(pbi) < - run_ready_min_buf_num) - dump_pic_list(pbi); -#endif - } - } else if (get_free_buf_count(pbi) >= - run_ready_min_buf_num) - ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_HEVC_FRONT - | CORE_MASK_HEVC_BACK; - - if (ret & CORE_MASK_HEVC_FRONT) - not_run_ready[pbi->index] = 0; - else - not_run_ready[pbi->index]++; - - if (ret & CORE_MASK_HEVC_BACK) - not_run2_ready[pbi->index] = 0; - else - not_run2_ready[pbi->index]++; - - vp9_print(pbi, - PRINT_FLAG_VDEC_DETAIL, "%s mask %lx=>%lx (%d %d %d %d)\r\n", - __func__, mask, ret, - get_free_stage_buf_num(pbi), - mv_buf_available(pbi), - s2_buf_available(pbi), - get_free_buf_count(pbi) - ); - - return ret; - -#else - if (get_free_buf_count(pbi) >= - run_ready_min_buf_num) { - if (vdec->parallel_dec == 1) - ret = CORE_MASK_HEVC; - else - ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; - } - if (ret) - not_run_ready[pbi->index] = 0; - else - not_run_ready[pbi->index]++; - - vp9_print(pbi, - PRINT_FLAG_VDEC_DETAIL, "%s mask %lx=>%lx\r\n", - __func__, mask, ret); - return ret; -#endif -} - -static void run_front(struct vdec_s *vdec) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - int ret, size; - - run_count[pbi->index]++; - /* pbi->chunk = vdec_prepare_input(vdec); */ -#if (!defined SUPPORT_FB_DECODING) - hevc_reset_core(vdec); -#elif (defined FB_DECODING_TEST_SCHEDULE) - hevc_reset_core(vdec); -#else - if (pbi->used_stage_buf_num > 0) - fb_reset_core(vdec, HW_MASK_FRONT); - else - hevc_reset_core(vdec); -#endif - - size = vdec_prepare_input(vdec, &pbi->chunk); - if (size < 0) { - input_empty[pbi->index]++; - - pbi->dec_result = DEC_RESULT_AGAIN; - - vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, - "ammvdec_vh265: Insufficient data\n"); - - vdec_schedule_work(&pbi->work); - return; - } - input_empty[pbi->index] = 0; - pbi->dec_result = DEC_RESULT_NONE; - pbi->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT); - - if (debug & PRINT_FLAG_VDEC_STATUS) { - int ii; - vp9_print(pbi, 0, - "%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x", - __func__, - pbi->frame_count, size, - pbi->chunk ? pbi->chunk->size : 0, - pbi->chunk ? pbi->chunk->offset : 0, - pbi->chunk ? ((vdec_frame_based(vdec) && - (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(pbi, size) : 0) : 0, - READ_VREG(HEVC_STREAM_START_ADDR), - READ_VREG(HEVC_STREAM_END_ADDR), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - pbi->start_shift_bytes); - if (vdec_frame_based(vdec) && pbi->chunk) { - u8 *data = NULL; - - if (!pbi->chunk->block->is_mapped) - data = codec_mm_vmap(pbi->chunk->block->start + - pbi->chunk->offset, 8); - else - data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; - - vp9_print_cont(pbi, 0, "data adr %p:", - data); - for (ii = 0; ii < 8; ii++) - vp9_print_cont(pbi, 0, "%02x ", - data[ii]); - - if (!pbi->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - vp9_print_cont(pbi, 0, "\r\n"); - } - if (vdec->mc_loaded) { - /*firmware have load before, - and not changes to another. - ignore reload. - */ - } else { - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); - if (ret < 0) { - amhevc_disable(); - vp9_print(pbi, PRINT_FLAG_ERROR, - "VP9: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - pbi->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&pbi->work); - return; - } - vdec->mc_loaded = 1; - vdec->mc_type = VFORMAT_VP9; - } - - if (vp9_hw_ctx_restore(pbi) < 0) { - vdec_schedule_work(&pbi->work); - return; - } - - vdec_enable_input(vdec); - - WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); - - if (vdec_frame_based(vdec)) { - if (debug & PRINT_FLAG_VDEC_DATA) - dump_data(pbi, pbi->chunk->size); - - WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); - size = pbi->chunk->size + - (pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1)); - } - WRITE_VREG(HEVC_DECODE_SIZE, size); - WRITE_VREG(HEVC_DECODE_COUNT, pbi->slice_idx); - pbi->init_flag = 1; - - vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, - "%s: start hevc (%x %x %x)\n", - __func__, - READ_VREG(HEVC_DEC_STATUS_REG), - READ_VREG(HEVC_MPC_E), - READ_VREG(HEVC_MPSR)); - - start_process_time(pbi); - mod_timer(&pbi->timer, jiffies); - pbi->stat |= STAT_TIMER_ARM; - pbi->stat |= STAT_ISR_REG; - amhevc_start(); - pbi->stat |= STAT_VDEC_RUN; -} - -#ifdef SUPPORT_FB_DECODING -static void mpred_process(struct VP9Decoder_s *pbi) -{ - union param_u *params = &pbi->s1_param; - unsigned char use_prev_frame_mvs = - !params->p.error_resilient_mode && - params->p.width == pbi->s1_width && - params->p.height == pbi->s1_height && - !pbi->s1_intra_only && - pbi->s1_last_show_frame && - (pbi->s1_frame_type != KEY_FRAME); - pbi->s1_width = params->p.width; - pbi->s1_height = params->p.height; - pbi->s1_frame_type = params->p.frame_type; - pbi->s1_intra_only = - (params->p.show_frame || - params->p.show_existing_frame) - ? 0 : params->p.intra_only; - if ((pbi->s1_frame_type != KEY_FRAME) - && (!pbi->s1_intra_only)) { - unsigned int data32; - int mpred_mv_rd_end_addr; - - mpred_mv_rd_end_addr = - pbi->s1_mpred_mv_wr_start_addr_pre - + (pbi->lcu_total * MV_MEM_UNIT); - - WRITE_VREG(HEVC_MPRED_CTRL3, 0x24122412); - WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, - pbi->work_space_buf-> - mpred_above.buf_start); - - data32 = READ_VREG(HEVC_MPRED_CTRL4); - - data32 &= (~(1 << 6)); - data32 |= (use_prev_frame_mvs << 6); - WRITE_VREG(HEVC_MPRED_CTRL4, data32); - - WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, - pbi->s1_mpred_mv_wr_start_addr); - WRITE_VREG(HEVC_MPRED_MV_WPTR, - pbi->s1_mpred_mv_wr_start_addr); - - WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, - pbi->s1_mpred_mv_wr_start_addr_pre); - WRITE_VREG(HEVC_MPRED_MV_RPTR, - pbi->s1_mpred_mv_wr_start_addr_pre); - - WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, - mpred_mv_rd_end_addr); - - } else - clear_mpred_hw(pbi); - - if (!params->p.show_existing_frame) { - pbi->s1_mpred_mv_wr_start_addr_pre = - pbi->s1_mpred_mv_wr_start_addr; - pbi->s1_last_show_frame = - params->p.show_frame; - if (pbi->s1_mv_buf_index_pre_pre != MV_BUFFER_NUM) - put_mv_buf(pbi, &pbi->s1_mv_buf_index_pre_pre); - pbi->s1_mv_buf_index_pre_pre = - pbi->s1_mv_buf_index_pre; - pbi->s1_mv_buf_index_pre = pbi->s1_mv_buf_index; - } else - put_mv_buf(pbi, &pbi->s1_mv_buf_index); -} - -static void vp9_s1_work(struct work_struct *s1_work) -{ - struct VP9Decoder_s *pbi = container_of(s1_work, - struct VP9Decoder_s, s1_work); - vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, - "%s dec_s1_result %d\n", - __func__, - pbi->dec_s1_result); - -#ifdef FB_DECODING_TEST_SCHEDULE - if (pbi->dec_s1_result == - DEC_S1_RESULT_TEST_TRIGGER_DONE) { - pbi->s1_test_cmd = TEST_SET_PIC_DONE; - WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); - } -#endif - if (pbi->dec_s1_result == DEC_S1_RESULT_DONE || - pbi->dec_s1_result == DEC_S1_RESULT_FORCE_EXIT) { - - vdec_core_finish_run(hw_to_vdec(pbi), - CORE_MASK_HEVC_FRONT); - - trigger_schedule(pbi); - /*pbi->dec_s1_result = DEC_S1_RESULT_NONE;*/ - } - -} - -static void run_back(struct vdec_s *vdec) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - int i; - run2_count[pbi->index]++; - if (debug & PRINT_FLAG_VDEC_STATUS) { - vp9_print(pbi, 0, - "%s", __func__); - } - pbi->run2_busy = 1; -#ifndef FB_DECODING_TEST_SCHEDULE - fb_reset_core(vdec, HW_MASK_BACK); - - vvp9_prot_init(pbi, HW_MASK_BACK); -#endif - vp9_recycle_mmu_buf_tail(pbi); - - if (pbi->frame_count > 0) - vp9_bufmgr_postproc(pbi); - - if (get_s2_buf(pbi) >= 0) { - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) - vp9_param.l.data[i + ii] = - pbi->s2_buf->rpm[i + 3 - ii]; - } -#ifndef FB_DECODING_TEST_SCHEDULE - WRITE_VREG(HEVC_ASSIST_FBD_MMU_MAP_ADDR, - pbi->stage_mmu_map_phy_addr + - pbi->s2_buf->index * STAGE_MMU_MAP_SIZE); -#endif - continue_decoding(pbi); - } - pbi->run2_busy = 0; -} -#endif - -static void run(struct vdec_s *vdec, unsigned long mask, - void (*callback)(struct vdec_s *, void *), void *arg) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - - vp9_print(pbi, - PRINT_FLAG_VDEC_DETAIL, "%s mask %lx\r\n", - __func__, mask); - - run_count[pbi->index]++; - pbi->vdec_cb_arg = arg; - pbi->vdec_cb = callback; -#ifdef SUPPORT_FB_DECODING - if ((mask & CORE_MASK_HEVC) || - (mask & CORE_MASK_HEVC_FRONT)) - run_front(vdec); - - if ((pbi->used_stage_buf_num > 0) - && (mask & CORE_MASK_HEVC_BACK)) - run_back(vdec); -#else - run_front(vdec); -#endif -} - -static void reset(struct vdec_s *vdec) -{ - - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - - vp9_print(pbi, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); - -} - -static irqreturn_t vp9_irq_cb(struct vdec_s *vdec, int irq) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - return vvp9_isr(0, pbi); -} - -static irqreturn_t vp9_threaded_irq_cb(struct vdec_s *vdec, int irq) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - return vvp9_isr_thread_fn(0, pbi); -} - -static void vp9_dump_state(struct vdec_s *vdec) -{ - struct VP9Decoder_s *pbi = - (struct VP9Decoder_s *)vdec->private; - struct VP9_Common_s *const cm = &pbi->common; - int i; - vp9_print(pbi, 0, "====== %s\n", __func__); - - vp9_print(pbi, 0, - "width/height (%d/%d), used_buf_num %d\n", - cm->width, - cm->height, - pbi->used_buf_num - ); - - vp9_print(pbi, 0, - "is_framebase(%d), eos %d, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n", - input_frame_based(vdec), - pbi->eos, - pbi->dec_result, - decode_frame_count[pbi->index], - display_frame_count[pbi->index], - run_count[pbi->index], - not_run_ready[pbi->index], - input_empty[pbi->index] - ); - - if (vf_get_receiver(vdec->vf_provider_name)) { - enum receviver_start_e state = - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL); - vp9_print(pbi, 0, - "\nreceiver(%s) state %d\n", - vdec->vf_provider_name, - state); - } - - vp9_print(pbi, 0, - "%s, newq(%d/%d), dispq(%d/%d), vf prepare/get/put (%d/%d/%d), free_buf_count %d (min %d for run_ready)\n", - __func__, - kfifo_len(&pbi->newframe_q), - VF_POOL_SIZE, - kfifo_len(&pbi->display_q), - VF_POOL_SIZE, - pbi->vf_pre_count, - pbi->vf_get_count, - pbi->vf_put_count, - get_free_buf_count(pbi), - run_ready_min_buf_num - ); - - dump_pic_list(pbi); - - for (i = 0; i < MAX_BUF_NUM; i++) { - vp9_print(pbi, 0, - "mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n", - i, - pbi->m_mv_BUF[i].start_adr, - pbi->m_mv_BUF[i].size, - pbi->m_mv_BUF[i].used_flag); - } - - vp9_print(pbi, 0, - "HEVC_DEC_STATUS_REG=0x%x\n", - READ_VREG(HEVC_DEC_STATUS_REG)); - vp9_print(pbi, 0, - "HEVC_MPC_E=0x%x\n", - READ_VREG(HEVC_MPC_E)); - vp9_print(pbi, 0, - "DECODE_MODE=0x%x\n", - READ_VREG(DECODE_MODE)); - vp9_print(pbi, 0, - "NAL_SEARCH_CTL=0x%x\n", - READ_VREG(NAL_SEARCH_CTL)); - vp9_print(pbi, 0, - "HEVC_PARSER_LCU_START=0x%x\n", - READ_VREG(HEVC_PARSER_LCU_START)); - vp9_print(pbi, 0, - "HEVC_DECODE_SIZE=0x%x\n", - READ_VREG(HEVC_DECODE_SIZE)); - vp9_print(pbi, 0, - "HEVC_SHIFT_BYTE_COUNT=0x%x\n", - READ_VREG(HEVC_SHIFT_BYTE_COUNT)); - vp9_print(pbi, 0, - "HEVC_STREAM_START_ADDR=0x%x\n", - READ_VREG(HEVC_STREAM_START_ADDR)); - vp9_print(pbi, 0, - "HEVC_STREAM_END_ADDR=0x%x\n", - READ_VREG(HEVC_STREAM_END_ADDR)); - vp9_print(pbi, 0, - "HEVC_STREAM_LEVEL=0x%x\n", - READ_VREG(HEVC_STREAM_LEVEL)); - vp9_print(pbi, 0, - "HEVC_STREAM_WR_PTR=0x%x\n", - READ_VREG(HEVC_STREAM_WR_PTR)); - vp9_print(pbi, 0, - "HEVC_STREAM_RD_PTR=0x%x\n", - READ_VREG(HEVC_STREAM_RD_PTR)); - vp9_print(pbi, 0, - "PARSER_VIDEO_RP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_RP)); - vp9_print(pbi, 0, - "PARSER_VIDEO_WP=0x%x\n", - READ_PARSER_REG(PARSER_VIDEO_WP)); - - if (input_frame_based(vdec) && - (debug & PRINT_FLAG_VDEC_DATA) - ) { - int jj; - if (pbi->chunk && pbi->chunk->block && - pbi->chunk->size > 0) { - u8 *data = NULL; - - if (!pbi->chunk->block->is_mapped) - data = codec_mm_vmap( - pbi->chunk->block->start + - pbi->chunk->offset, - pbi->chunk->size); - else - data = ((u8 *)pbi->chunk->block->start_virt) - + pbi->chunk->offset; - vp9_print(pbi, 0, - "frame data size 0x%x\n", - pbi->chunk->size); - for (jj = 0; jj < pbi->chunk->size; jj++) { - if ((jj & 0xf) == 0) - vp9_print(pbi, 0, - "%06x:", jj); - vp9_print_cont(pbi, 0, - "%02x ", data[jj]); - if (((jj + 1) & 0xf) == 0) - vp9_print_cont(pbi, 0, - "\n"); - } - - if (!pbi->chunk->block->is_mapped) - codec_mm_unmap_phyaddr(data); - } - } - -} - -static int ammvdec_vp9_probe(struct platform_device *pdev) -{ - struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; - int ret; - int config_val; - struct vframe_content_light_level_s content_light_level; - struct vframe_master_display_colour_s vf_dp; - - struct BUF_s BUF[MAX_BUF_NUM]; - struct VP9Decoder_s *pbi = NULL; - pr_debug("%s\n", __func__); - - if (pdata == NULL) { - pr_info("\nammvdec_vp9 memory resource undefined.\n"); - return -EFAULT; - } - /*pbi = (struct VP9Decoder_s *)devm_kzalloc(&pdev->dev, - sizeof(struct VP9Decoder_s), GFP_KERNEL);*/ - memset(&vf_dp, 0, sizeof(struct vframe_master_display_colour_s)); - pbi = vmalloc(sizeof(struct VP9Decoder_s)); - if (pbi == NULL) { - pr_info("\nammvdec_vp9 device data allocation failed\n"); - return -ENOMEM; - } - memset(pbi, 0, sizeof(struct VP9Decoder_s)); - pdata->private = pbi; - pdata->dec_status = vvp9_dec_status; - /* pdata->set_trickmode = set_trickmode; */ - pdata->run_ready = run_ready; - pdata->run = run; - pdata->reset = reset; - pdata->irq_handler = vp9_irq_cb; - pdata->threaded_irq_handler = vp9_threaded_irq_cb; - pdata->dump_state = vp9_dump_state; - - memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - memset(pbi, 0, sizeof(struct VP9Decoder_s)); - memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); - - pbi->index = pdev->id; - - if (pdata->use_vfm_path) - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - VFM_DEC_PROVIDER_NAME); - else - snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, - MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); - - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vvp9_vf_provider, pbi); - - pbi->provider_name = pdata->vf_provider_name; - platform_set_drvdata(pdev, pdata); - - pbi->platform_dev = pdev; - pbi->video_signal_type = 0; - pbi->m_ins_flag = 1; - if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) - pbi->stat |= VP9_TRIGGER_FRAME_ENABLE; - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - pbi->max_pic_w = 8192; - pbi->max_pic_h = 4608; - } -#if 1 - if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && - pdata->config_len) { -#ifdef MULTI_INSTANCE_SUPPORT - /*use ptr config for doubel_write_mode, etc*/ - vp9_print(pbi, 0, "pdata->config=%s\n", pdata->config); - if (get_config_int(pdata->config, "vp9_double_write_mode", - &config_val) == 0) - pbi->double_write_mode = config_val; - else - pbi->double_write_mode = double_write_mode; - - if (get_config_int(pdata->config, "save_buffer_mode", - &config_val) == 0) - pbi->save_buffer_mode = config_val; - else - pbi->save_buffer_mode = 0; - - /*use ptr config for max_pic_w, etc*/ - if (get_config_int(pdata->config, "vp9_max_pic_w", - &config_val) == 0) { - pbi->max_pic_w = config_val; - } - if (get_config_int(pdata->config, "vp9_max_pic_h", - &config_val) == 0) { - pbi->max_pic_h = config_val; - } -#endif - if (get_config_int(pdata->config, "HDRStaticInfo", - &vf_dp.present_flag) == 0 - && vf_dp.present_flag == 1) { - get_config_int(pdata->config, "mG.x", - &vf_dp.primaries[0][0]); - get_config_int(pdata->config, "mG.y", - &vf_dp.primaries[0][1]); - get_config_int(pdata->config, "mB.x", - &vf_dp.primaries[1][0]); - get_config_int(pdata->config, "mB.y", - &vf_dp.primaries[1][1]); - get_config_int(pdata->config, "mR.x", - &vf_dp.primaries[2][0]); - get_config_int(pdata->config, "mR.y", - &vf_dp.primaries[2][1]); - get_config_int(pdata->config, "mW.x", - &vf_dp.white_point[0]); - get_config_int(pdata->config, "mW.y", - &vf_dp.white_point[1]); - get_config_int(pdata->config, "mMaxDL", - &vf_dp.luminance[0]); - get_config_int(pdata->config, "mMinDL", - &vf_dp.luminance[1]); - vf_dp.content_light_level.present_flag = 1; - get_config_int(pdata->config, "mMaxCLL", - &content_light_level.max_content); - get_config_int(pdata->config, "mMaxFALL", - &content_light_level.max_pic_average); - vf_dp.content_light_level = content_light_level; - pbi->video_signal_type = (1 << 29) - | (5 << 26) /* unspecified */ - | (0 << 25) /* limit */ - | (1 << 24) /* color available */ - | (9 << 16) /* 2020 */ - | (16 << 8) /* 2084 */ - | (9 << 0); /* 2020 */ - } - pbi->vf_dp = vf_dp; - } else -#endif - { - /*pbi->vvp9_amstream_dec_info.width = 0; - pbi->vvp9_amstream_dec_info.height = 0; - pbi->vvp9_amstream_dec_info.rate = 30;*/ - pbi->double_write_mode = double_write_mode; - } - if (is_oversize(pbi->max_pic_w, pbi->max_pic_h)) { - pr_err("over size: %dx%d, probe failed\n", - pbi->max_pic_w, pbi->max_pic_h); - return -1; - } - pbi->mmu_enable = 1; - video_signal_type = pbi->video_signal_type; -#if 0 - pbi->buf_start = pdata->mem_start; - pbi->buf_size = pdata->mem_end - pdata->mem_start + 1; -#else - if (amvdec_vp9_mmu_init(pbi) < 0) { - pr_err("vp9 alloc bmmu box failed!!\n"); - /* devm_kfree(&pdev->dev, (void *)pbi); */ - vfree((void *)pbi); - pdata->dec_status = NULL; - return -1; - } - - pbi->cma_alloc_count = PAGE_ALIGN(work_buf_size) / PAGE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, WORK_SPACE_BUF_ID, - pbi->cma_alloc_count * PAGE_SIZE, DRIVER_NAME, - &pbi->cma_alloc_addr); - if (ret < 0) { - uninit_mmu_buffers(pbi); - /* devm_kfree(&pdev->dev, (void *)pbi); */ - vfree((void *)pbi); - pdata->dec_status = NULL; - return ret; - } - pbi->buf_start = pbi->cma_alloc_addr; - pbi->buf_size = work_buf_size; -#endif - - pbi->init_flag = 0; - pbi->first_sc_checked = 0; - pbi->fatal_error = 0; - pbi->show_frame_num = 0; - - if (debug) { - pr_info("===VP9 decoder mem resource 0x%lx size 0x%x\n", - pbi->buf_start, - pbi->buf_size); - } - - if (pdata->sys_info) - pbi->vvp9_amstream_dec_info = *pdata->sys_info; - else { - pbi->vvp9_amstream_dec_info.width = 0; - pbi->vvp9_amstream_dec_info.height = 0; - pbi->vvp9_amstream_dec_info.rate = 30; - } - - pbi->cma_dev = pdata->cma_dev; - if (vvp9_init(pdata) < 0) { - pr_info("\namvdec_vp9 init failed.\n"); - vp9_local_uninit(pbi); - uninit_mmu_buffers(pbi); - /* devm_kfree(&pdev->dev, (void *)pbi); */ - vfree((void *)pbi); - pdata->dec_status = NULL; - return -ENODEV; - } - vdec_set_prepare_level(pdata, start_decode_buf_level); - hevc_source_changed(VFORMAT_VP9, - 4096, 2048, 60); -#ifdef SUPPORT_FB_DECODING - if (pbi->used_stage_buf_num > 0) - vdec_core_request(pdata, - CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK); - else - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK - | CORE_MASK_COMBINE); -#else - if (pdata->parallel_dec == 1) - vdec_core_request(pdata, CORE_MASK_HEVC); - else - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); -#endif - return 0; -} - -static int ammvdec_vp9_remove(struct platform_device *pdev) -{ - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *) - (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); - struct vdec_s *vdec = hw_to_vdec(pbi); - int i; - if (debug) - pr_info("amvdec_vp9_remove\n"); - - vmvp9_stop(pbi); - -#ifdef SUPPORT_FB_DECODING - vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK - ); -#else - if (vdec->parallel_dec == 1) - vdec_core_release(hw_to_vdec(pbi), CORE_MASK_HEVC); - else - vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); -#endif - vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_DISCONNECTED); - - if (vdec->parallel_dec == 1) { - for (i = 0; i < FRAME_BUFFERS; i++) { - vdec->free_canvas_ex - (pbi->common.buffer_pool->frame_bufs[i].buf.y_canvas_index, - vdec->id); - vdec->free_canvas_ex - (pbi->common.buffer_pool->frame_bufs[i].buf.uv_canvas_index, - vdec->id); - } - } - - -#ifdef DEBUG_PTS - pr_info("pts missed %ld, pts hit %ld, duration %d\n", - pbi->pts_missed, pbi->pts_hit, pbi->frame_dur); -#endif - /* devm_kfree(&pdev->dev, (void *)pbi); */ - vfree((void *)pbi); - return 0; -} - -static struct platform_driver ammvdec_vp9_driver = { - .probe = ammvdec_vp9_probe, - .remove = ammvdec_vp9_remove, -#ifdef CONFIG_PM - .suspend = amhevc_suspend, - .resume = amhevc_resume, -#endif - .driver = { - .name = MULTI_DRIVER_NAME, - } -}; -#endif -static struct mconfig vp9_configs[] = { - MC_PU32("bit_depth_luma", &bit_depth_luma), - MC_PU32("bit_depth_chroma", &bit_depth_chroma), - MC_PU32("frame_width", &frame_width), - MC_PU32("frame_height", &frame_height), - MC_PU32("debug", &debug), - MC_PU32("radr", &radr), - MC_PU32("rval", &rval), - MC_PU32("pop_shorts", &pop_shorts), - MC_PU32("dbg_cmd", &dbg_cmd), - MC_PU32("dbg_skip_decode_index", &dbg_skip_decode_index), - MC_PU32("endian", &endian), - MC_PU32("step", &step), - MC_PU32("udebug_flag", &udebug_flag), - MC_PU32("decode_pic_begin", &decode_pic_begin), - MC_PU32("slice_parse_begin", &slice_parse_begin), - MC_PU32("i_only_flag", &i_only_flag), - MC_PU32("error_handle_policy", &error_handle_policy), - MC_PU32("buf_alloc_width", &buf_alloc_width), - MC_PU32("buf_alloc_height", &buf_alloc_height), - MC_PU32("buf_alloc_depth", &buf_alloc_depth), - MC_PU32("buf_alloc_size", &buf_alloc_size), - MC_PU32("buffer_mode", &buffer_mode), - MC_PU32("buffer_mode_dbg", &buffer_mode_dbg), - MC_PU32("max_buf_num", &max_buf_num), - MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin), - MC_PU32("mem_map_mode", &mem_map_mode), - MC_PU32("double_write_mode", &double_write_mode), - MC_PU32("enable_mem_saving", &enable_mem_saving), - MC_PU32("force_w_h", &force_w_h), - MC_PU32("force_fps", &force_fps), - MC_PU32("max_decoding_time", &max_decoding_time), - MC_PU32("on_no_keyframe_skiped", &on_no_keyframe_skiped), - MC_PU32("start_decode_buf_level", &start_decode_buf_level), - MC_PU32("decode_timeout_val", &decode_timeout_val), - MC_PU32("vp9_max_pic_w", &vp9_max_pic_w), - MC_PU32("vp9_max_pic_h", &vp9_max_pic_h), -}; -static struct mconfig_node vp9_node; - -static int __init amvdec_vp9_driver_init_module(void) -{ - - struct BuffInfo_s *p_buf_info; - - if (vdec_is_support_4k()) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - p_buf_info = &amvvp9_workbuff_spec[2]; - else - p_buf_info = &amvvp9_workbuff_spec[1]; - } else - p_buf_info = &amvvp9_workbuff_spec[0]; - - init_buff_spec(NULL, p_buf_info); - work_buf_size = - (p_buf_info->end_adr - p_buf_info->start_adr - + 0xffff) & (~0xffff); - - pr_debug("amvdec_vp9 module init\n"); - - error_handle_policy = 0; - -#ifdef ERROR_HANDLE_DEBUG - dbg_nal_skip_flag = 0; - dbg_nal_skip_count = 0; -#endif - udebug_flag = 0; - decode_pic_begin = 0; - slice_parse_begin = 0; - step = 0; - buf_alloc_size = 0; -#ifdef MULTI_INSTANCE_SUPPORT - if (platform_driver_register(&ammvdec_vp9_driver)) - pr_err("failed to register ammvdec_vp9 driver\n"); - -#endif - if (platform_driver_register(&amvdec_vp9_driver)) { - pr_err("failed to register amvdec_vp9 driver\n"); - return -ENODEV; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { - amvdec_vp9_profile.profile = - "8k, 10bit, dwrite, compressed"; - } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL - /*&& get_cpu_major_id() != MESON_CPU_MAJOR_ID_GXLX*/ - && get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TXL) { - if (vdec_is_support_4k()) - amvdec_vp9_profile.profile = - "4k, 10bit, dwrite, compressed"; - else - amvdec_vp9_profile.profile = - "10bit, dwrite, compressed"; - } else { - amvdec_vp9_profile.name = "vp9_unsupport"; - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - max_buf_num = MAX_BUF_NUM_LESS; - - vcodec_profile_register(&amvdec_vp9_profile); - INIT_REG_NODE_CONFIGS("media.decoder", &vp9_node, - "vp9", vp9_configs, CONFIG_FOR_RW); - - return 0; -} - -static void __exit amvdec_vp9_driver_remove_module(void) -{ - pr_debug("amvdec_vp9 module remove.\n"); -#ifdef MULTI_INSTANCE_SUPPORT - platform_driver_unregister(&ammvdec_vp9_driver); -#endif - platform_driver_unregister(&amvdec_vp9_driver); -} - -/****************************************/ - -module_param(bit_depth_luma, uint, 0664); -MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_vp9 bit_depth_luma\n"); - -module_param(bit_depth_chroma, uint, 0664); -MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_vp9 bit_depth_chroma\n"); - -module_param(frame_width, uint, 0664); -MODULE_PARM_DESC(frame_width, "\n amvdec_vp9 frame_width\n"); - -module_param(frame_height, uint, 0664); -MODULE_PARM_DESC(frame_height, "\n amvdec_vp9 frame_height\n"); - -module_param(debug, uint, 0664); -MODULE_PARM_DESC(debug, "\n amvdec_vp9 debug\n"); - -module_param(radr, uint, 0664); -MODULE_PARM_DESC(radr, "\n radr\n"); - -module_param(rval, uint, 0664); -MODULE_PARM_DESC(rval, "\n rval\n"); - -module_param(pop_shorts, uint, 0664); -MODULE_PARM_DESC(pop_shorts, "\n rval\n"); - -module_param(dbg_cmd, uint, 0664); -MODULE_PARM_DESC(dbg_cmd, "\n dbg_cmd\n"); - -module_param(dbg_skip_decode_index, uint, 0664); -MODULE_PARM_DESC(dbg_skip_decode_index, "\n dbg_skip_decode_index\n"); - -module_param(endian, uint, 0664); -MODULE_PARM_DESC(endian, "\n rval\n"); - -module_param(step, uint, 0664); -MODULE_PARM_DESC(step, "\n amvdec_vp9 step\n"); - -module_param(decode_pic_begin, uint, 0664); -MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_vp9 decode_pic_begin\n"); - -module_param(slice_parse_begin, uint, 0664); -MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_vp9 slice_parse_begin\n"); - -module_param(i_only_flag, uint, 0664); -MODULE_PARM_DESC(i_only_flag, "\n amvdec_vp9 i_only_flag\n"); - -module_param(error_handle_policy, uint, 0664); -MODULE_PARM_DESC(error_handle_policy, "\n amvdec_vp9 error_handle_policy\n"); - -module_param(buf_alloc_width, uint, 0664); -MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); - -module_param(buf_alloc_height, uint, 0664); -MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n"); - -module_param(buf_alloc_depth, uint, 0664); -MODULE_PARM_DESC(buf_alloc_depth, "\n buf_alloc_depth\n"); - -module_param(buf_alloc_size, uint, 0664); -MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); - -module_param(buffer_mode, uint, 0664); -MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n"); - -module_param(buffer_mode_dbg, uint, 0664); -MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n"); -/*USE_BUF_BLOCK*/ -module_param(max_buf_num, uint, 0664); -MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); - -module_param(dynamic_buf_num_margin, uint, 0664); -MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); - -module_param(mv_buf_margin, uint, 0664); -MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n"); - -module_param(run_ready_min_buf_num, uint, 0664); -MODULE_PARM_DESC(run_ready_min_buf_num, "\n run_ready_min_buf_num\n"); - -/**/ - -module_param(mem_map_mode, uint, 0664); -MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); - -#ifdef SUPPORT_10BIT -module_param(double_write_mode, uint, 0664); -MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); - -module_param(enable_mem_saving, uint, 0664); -MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n"); - -module_param(force_w_h, uint, 0664); -MODULE_PARM_DESC(force_w_h, "\n force_w_h\n"); -#endif - -module_param(force_fps, uint, 0664); -MODULE_PARM_DESC(force_fps, "\n force_fps\n"); - -module_param(max_decoding_time, uint, 0664); -MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n"); - -module_param(on_no_keyframe_skiped, uint, 0664); -MODULE_PARM_DESC(on_no_keyframe_skiped, "\n on_no_keyframe_skiped\n"); - -module_param(mcrcc_cache_alg_flag, uint, 0664); -MODULE_PARM_DESC(mcrcc_cache_alg_flag, "\n mcrcc_cache_alg_flag\n"); - -#ifdef MULTI_INSTANCE_SUPPORT -module_param(start_decode_buf_level, int, 0664); -MODULE_PARM_DESC(start_decode_buf_level, - "\n vp9 start_decode_buf_level\n"); - -module_param(decode_timeout_val, uint, 0664); -MODULE_PARM_DESC(decode_timeout_val, - "\n vp9 decode_timeout_val\n"); - -module_param(vp9_max_pic_w, uint, 0664); -MODULE_PARM_DESC(vp9_max_pic_w, "\n vp9_max_pic_w\n"); - -module_param(vp9_max_pic_h, uint, 0664); -MODULE_PARM_DESC(vp9_max_pic_h, "\n vp9_max_pic_h\n"); - -module_param_array(decode_frame_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(display_frame_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(max_process_time, uint, - &max_decode_instance_num, 0664); - -module_param_array(run_count, uint, - &max_decode_instance_num, 0664); - -module_param_array(input_empty, uint, - &max_decode_instance_num, 0664); - -module_param_array(not_run_ready, uint, - &max_decode_instance_num, 0664); -#endif - -#ifdef SUPPORT_FB_DECODING -module_param_array(not_run2_ready, uint, - &max_decode_instance_num, 0664); - -module_param_array(run2_count, uint, - &max_decode_instance_num, 0664); - -module_param(stage_buf_num, uint, 0664); -MODULE_PARM_DESC(stage_buf_num, "\n amvdec_h265 stage_buf_num\n"); -#endif - -module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); - -module_param(udebug_pause_pos, uint, 0664); -MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); - -module_param(udebug_pause_val, uint, 0664); -MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); - -module_param(udebug_pause_decode_idx, uint, 0664); -MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); - -module_init(amvdec_vp9_driver_init_module); -module_exit(amvdec_vp9_driver_remove_module); - -MODULE_DESCRIPTION("AMLOGIC vp9 Video Decoder Driver"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h deleted file mode 100644 index 1db9d0998ff2..000000000000 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * drivers/amlogic/amports/vvp9.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef VVP9_H -#define VVP9_H - -void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, -unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count); -#endif diff --git a/drivers/amlogic/media_modules/frame_sink/Makefile b/drivers/amlogic/media_modules/frame_sink/Makefile deleted file mode 100644 index 2b9754a3947e..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += encoder/ diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/Makefile b/drivers/amlogic/media_modules/frame_sink/encoder/Makefile deleted file mode 100644 index 9afecec9265f..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_VENC_H264) += h264/ -obj-$(CONFIG_AMLOGIC_MEDIA_VENC_H265) += h265/ diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile b/drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile deleted file mode 100644 index c12d7c3d86b2..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += encoder.o diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c deleted file mode 100644 index fadff431d0b5..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c +++ /dev/null @@ -1,4310 +0,0 @@ -/* - * drivers/amlogic/amports/encoder.c - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../../../frame_provider/decoder/utils/vdec.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "encoder.h" -#include "../../../frame_provider/decoder/utils/amvdec.h" -#include -#include "../../../stream_input/amports/amports_priv.h" -#include "../../../frame_provider/decoder/utils/firmware.h" -#include -#ifdef CONFIG_AM_JPEG_ENCODER -#include "jpegenc.h" -#endif - -#define ENCODE_NAME "encoder" -#define AMVENC_CANVAS_INDEX 0xE4 -#define AMVENC_CANVAS_MAX_INDEX 0xEF - -#define MIN_SIZE amvenc_buffspec[0].min_buffsize -#define DUMP_INFO_BYTES_PER_MB 80 - -#define ADJUSTED_QP_FLAG 64 - -static s32 avc_device_major; -static struct device *amvenc_avc_dev; -#define DRIVER_NAME "amvenc_avc" -#define CLASS_NAME "amvenc_avc" -#define DEVICE_NAME "amvenc_avc" - -static struct encode_manager_s encode_manager; - -#define MULTI_SLICE_MC -#define H264_ENC_CBR -/* #define MORE_MODULE_PARAM */ - -#define ENC_CANVAS_OFFSET AMVENC_CANVAS_INDEX - -#define UCODE_MODE_FULL 0 - -/* #define ENABLE_IGNORE_FUNCTION */ - -static u32 ie_me_mb_type; -static u32 ie_me_mode; -static u32 ie_pippeline_block = 3; -static u32 ie_cur_ref_sel; -/* static u32 avc_endian = 6; */ -static u32 clock_level = 5; - -static u32 encode_print_level = LOG_DEBUG; -static u32 no_timeout; -static int nr_mode = -1; -static u32 qp_table_debug; - -static u32 me_mv_merge_ctl = - (0x1 << 31) | /* [31] me_merge_mv_en_16 */ - (0x1 << 30) | /* [30] me_merge_small_mv_en_16 */ - (0x1 << 29) | /* [29] me_merge_flex_en_16 */ - (0x1 << 28) | /* [28] me_merge_sad_en_16 */ - (0x1 << 27) | /* [27] me_merge_mv_en_8 */ - (0x1 << 26) | /* [26] me_merge_small_mv_en_8 */ - (0x1 << 25) | /* [25] me_merge_flex_en_8 */ - (0x1 << 24) | /* [24] me_merge_sad_en_8 */ - /* [23:18] me_merge_mv_diff_16 - MV diff <= n pixel can be merged */ - (0x12 << 18) | - /* [17:12] me_merge_mv_diff_8 - MV diff <= n pixel can be merged */ - (0x2b << 12) | - /* [11:0] me_merge_min_sad - SAD >= 0x180 can be merged with other MV */ - (0x80 << 0); - /* ( 0x4 << 18) | - * // [23:18] me_merge_mv_diff_16 - MV diff <= n pixel can be merged - */ - /* ( 0x3f << 12) | - * // [17:12] me_merge_mv_diff_8 - MV diff <= n pixel can be merged - */ - /* ( 0xc0 << 0); - * // [11:0] me_merge_min_sad - SAD >= 0x180 can be merged with other MV - */ - -static u32 me_mv_weight_01 = (0x40 << 24) | (0x30 << 16) | (0x20 << 8) | 0x30; -static u32 me_mv_weight_23 = (0x40 << 8) | 0x30; -static u32 me_sad_range_inc = 0x03030303; -static u32 me_step0_close_mv = 0x003ffc21; -static u32 me_f_skip_sad; -static u32 me_f_skip_weight; -static u32 me_sad_enough_01;/* 0x00018010; */ -static u32 me_sad_enough_23;/* 0x00000020; */ - -/* [31:0] NUM_ROWS_PER_SLICE_P */ -/* [15:0] NUM_ROWS_PER_SLICE_I */ -static u32 fixed_slice_cfg; - -/* y tnr */ -static unsigned int y_tnr_mc_en = 1; -static unsigned int y_tnr_txt_mode; -static unsigned int y_tnr_mot_sad_margin = 1; -static unsigned int y_tnr_mot_cortxt_rate = 1; -static unsigned int y_tnr_mot_distxt_ofst = 5; -static unsigned int y_tnr_mot_distxt_rate = 4; -static unsigned int y_tnr_mot_dismot_ofst = 4; -static unsigned int y_tnr_mot_frcsad_lock = 8; -static unsigned int y_tnr_mot2alp_frc_gain = 10; -static unsigned int y_tnr_mot2alp_nrm_gain = 216; -static unsigned int y_tnr_mot2alp_dis_gain = 128; -static unsigned int y_tnr_mot2alp_dis_ofst = 32; -static unsigned int y_tnr_alpha_min = 32; -static unsigned int y_tnr_alpha_max = 63; -static unsigned int y_tnr_deghost_os; -/* c tnr */ -static unsigned int c_tnr_mc_en = 1; -static unsigned int c_tnr_txt_mode; -static unsigned int c_tnr_mot_sad_margin = 1; -static unsigned int c_tnr_mot_cortxt_rate = 1; -static unsigned int c_tnr_mot_distxt_ofst = 5; -static unsigned int c_tnr_mot_distxt_rate = 4; -static unsigned int c_tnr_mot_dismot_ofst = 4; -static unsigned int c_tnr_mot_frcsad_lock = 8; -static unsigned int c_tnr_mot2alp_frc_gain = 10; -static unsigned int c_tnr_mot2alp_nrm_gain = 216; -static unsigned int c_tnr_mot2alp_dis_gain = 128; -static unsigned int c_tnr_mot2alp_dis_ofst = 32; -static unsigned int c_tnr_alpha_min = 32; -static unsigned int c_tnr_alpha_max = 63; -static unsigned int c_tnr_deghost_os; -/* y snr */ -static unsigned int y_snr_err_norm = 1; -static unsigned int y_snr_gau_bld_core = 1; -static int y_snr_gau_bld_ofst = -1; -static unsigned int y_snr_gau_bld_rate = 48; -static unsigned int y_snr_gau_alp0_min; -static unsigned int y_snr_gau_alp0_max = 63; -static unsigned int y_bld_beta2alp_rate = 16; -static unsigned int y_bld_beta_min; -static unsigned int y_bld_beta_max = 63; -/* c snr */ -static unsigned int c_snr_err_norm = 1; -static unsigned int c_snr_gau_bld_core = 1; -static int c_snr_gau_bld_ofst = -1; -static unsigned int c_snr_gau_bld_rate = 48; -static unsigned int c_snr_gau_alp0_min; -static unsigned int c_snr_gau_alp0_max = 63; -static unsigned int c_bld_beta2alp_rate = 16; -static unsigned int c_bld_beta_min; -static unsigned int c_bld_beta_max = 63; - -static DEFINE_SPINLOCK(lock); - -#define ADV_MV_LARGE_16x8 1 -#define ADV_MV_LARGE_8x16 1 -#define ADV_MV_LARGE_16x16 1 - -/* me weight offset should not very small, it used by v1 me module. */ -/* the min real sad for me is 16 by hardware. */ -#define ME_WEIGHT_OFFSET 0x520 -#define I4MB_WEIGHT_OFFSET 0x655 -#define I16MB_WEIGHT_OFFSET 0x560 - -#define ADV_MV_16x16_WEIGHT 0x080 -#define ADV_MV_16_8_WEIGHT 0x0e0 -#define ADV_MV_8x8_WEIGHT 0x240 -#define ADV_MV_4x4x4_WEIGHT 0x3000 - -#define IE_SAD_SHIFT_I16 0x001 -#define IE_SAD_SHIFT_I4 0x001 -#define ME_SAD_SHIFT_INTER 0x001 - -#define STEP_2_SKIP_SAD 0 -#define STEP_1_SKIP_SAD 0 -#define STEP_0_SKIP_SAD 0 -#define STEP_2_SKIP_WEIGHT 0 -#define STEP_1_SKIP_WEIGHT 0 -#define STEP_0_SKIP_WEIGHT 0 - -#define ME_SAD_RANGE_0 0x1 /* 0x0 */ -#define ME_SAD_RANGE_1 0x0 -#define ME_SAD_RANGE_2 0x0 -#define ME_SAD_RANGE_3 0x0 - -/* use 0 for v3, 0x18 for v2 */ -#define ME_MV_PRE_WEIGHT_0 0x18 -/* use 0 for v3, 0x18 for v2 */ -#define ME_MV_PRE_WEIGHT_1 0x18 -#define ME_MV_PRE_WEIGHT_2 0x0 -#define ME_MV_PRE_WEIGHT_3 0x0 - -/* use 0 for v3, 0x18 for v2 */ -#define ME_MV_STEP_WEIGHT_0 0x18 -/* use 0 for v3, 0x18 for v2 */ -#define ME_MV_STEP_WEIGHT_1 0x18 -#define ME_MV_STEP_WEIGHT_2 0x0 -#define ME_MV_STEP_WEIGHT_3 0x0 - -#define ME_SAD_ENOUGH_0_DATA 0x00 -#define ME_SAD_ENOUGH_1_DATA 0x04 -#define ME_SAD_ENOUGH_2_DATA 0x11 -#define ADV_MV_8x8_ENOUGH_DATA 0x20 - -/* V4_COLOR_BLOCK_FIX */ -#define V3_FORCE_SKIP_SAD_0 0x10 -/* 4 Blocks */ -#define V3_FORCE_SKIP_SAD_1 0x60 -/* 16 Blocks + V3_SKIP_WEIGHT_2 */ -#define V3_FORCE_SKIP_SAD_2 0x250 -/* almost disable it -- use t_lac_coeff_2 output to F_ZERO is better */ -#define V3_ME_F_ZERO_SAD (ME_WEIGHT_OFFSET + 0x10) - -#define V3_IE_F_ZERO_SAD_I16 (I16MB_WEIGHT_OFFSET + 0x10) -#define V3_IE_F_ZERO_SAD_I4 (I4MB_WEIGHT_OFFSET + 0x20) - -#define V3_SKIP_WEIGHT_0 0x10 -/* 4 Blocks 8 separate search sad can be very low */ -#define V3_SKIP_WEIGHT_1 0x8 /* (4 * ME_MV_STEP_WEIGHT_1 + 0x100) */ -#define V3_SKIP_WEIGHT_2 0x3 - -#define V3_LEVEL_1_F_SKIP_MAX_SAD 0x0 -#define V3_LEVEL_1_SKIP_MAX_SAD 0x6 - -#define I4_ipred_weight_most 0x18 -#define I4_ipred_weight_else 0x28 - -#define C_ipred_weight_V 0x04 -#define C_ipred_weight_H 0x08 -#define C_ipred_weight_DC 0x0c - -#define I16_ipred_weight_V 0x04 -#define I16_ipred_weight_H 0x08 -#define I16_ipred_weight_DC 0x0c - -/* 0x00 same as disable */ -#define v3_left_small_max_ie_sad 0x00 -#define v3_left_small_max_me_sad 0x40 - -#define v5_use_small_diff_cnt 0 -#define v5_simple_mb_inter_all_en 1 -#define v5_simple_mb_inter_8x8_en 1 -#define v5_simple_mb_inter_16_8_en 1 -#define v5_simple_mb_inter_16x16_en 1 -#define v5_simple_mb_intra_en 1 -#define v5_simple_mb_C_en 0 -#define v5_simple_mb_Y_en 1 -#define v5_small_diff_Y 0x10 -#define v5_small_diff_C 0x18 -/* shift 8-bits, 2, 1, 0, -1, -2, -3, -4 */ -#define v5_simple_dq_setting 0x43210fed -#define v5_simple_me_weight_setting 0 - -#ifdef H264_ENC_CBR -#define CBR_TABLE_SIZE 0x800 -#define CBR_SHORT_SHIFT 12 /* same as disable */ -#define CBR_LONG_MB_NUM 2 -#define START_TABLE_ID 8 -#define CBR_LONG_THRESH 4 -#endif - -static u32 v3_mv_sad[64] = { - /* For step0 */ - 0x00000004, - 0x00010008, - 0x00020010, - 0x00030018, - 0x00040020, - 0x00050028, - 0x00060038, - 0x00070048, - 0x00080058, - 0x00090068, - 0x000a0080, - 0x000b0098, - 0x000c00b0, - 0x000d00c8, - 0x000e00e8, - 0x000f0110, - /* For step1 */ - 0x00100002, - 0x00110004, - 0x00120008, - 0x0013000c, - 0x00140010, - 0x00150014, - 0x0016001c, - 0x00170024, - 0x0018002c, - 0x00190034, - 0x001a0044, - 0x001b0054, - 0x001c0064, - 0x001d0074, - 0x001e0094, - 0x001f00b4, - /* For step2 */ - 0x00200006, - 0x0021000c, - 0x0022000c, - 0x00230018, - 0x00240018, - 0x00250018, - 0x00260018, - 0x00270030, - 0x00280030, - 0x00290030, - 0x002a0030, - 0x002b0030, - 0x002c0030, - 0x002d0030, - 0x002e0030, - 0x002f0050, - /* For step2 4x4-8x8 */ - 0x00300001, - 0x00310002, - 0x00320002, - 0x00330004, - 0x00340004, - 0x00350004, - 0x00360004, - 0x00370006, - 0x00380006, - 0x00390006, - 0x003a0006, - 0x003b0006, - 0x003c0006, - 0x003d0006, - 0x003e0006, - 0x003f0006 -}; - -static struct BuffInfo_s amvenc_buffspec[] = { - { - .lev_id = 0, - .max_width = 1920, - .max_height = 1088, - .min_buffsize = 0x1400000, - .dct = { - .buf_start = 0, - .buf_size = 0x800000, /* 1920x1088x4 */ - }, - .dec0_y = { - .buf_start = 0x800000, - .buf_size = 0x300000, - }, - .dec1_y = { - .buf_start = 0xb00000, - .buf_size = 0x300000, - }, - .assit = { - .buf_start = 0xe10000, - .buf_size = 0xc0000, - }, - .bitstream = { - .buf_start = 0xf00000, - .buf_size = 0x100000, - }, - .scale_buff = { - .buf_start = 0x1000000, - .buf_size = 0x300000, - }, - .dump_info = { - .buf_start = 0x1300000, - .buf_size = 0xa0000, /* (1920x1088/256)x80 */ - }, - .cbr_info = { - .buf_start = 0x13b0000, - .buf_size = 0x2000, - } - } -}; - -enum ucode_type_e { - UCODE_GXL, - UCODE_TXL, - UCODE_G12A, - UCODE_MAX -}; - -const char *ucode_name[] = { - "gxl_h264_enc", - "txl_h264_enc_cavlc", - "ga_h264_enc_cabac", -}; - -static void dma_flush(u32 buf_start, u32 buf_size); -static void cache_flush(u32 buf_start, u32 buf_size); - -static const char *select_ucode(u32 ucode_index) -{ - enum ucode_type_e ucode = UCODE_GXL; - - switch (ucode_index) { - case UCODE_MODE_FULL: - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ucode = UCODE_G12A; - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) - ucode = UCODE_TXL; - else /* (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) */ - ucode = UCODE_GXL; - break; - break; - default: - break; - } - return (const char *)ucode_name[ucode]; -} - -static void hcodec_prog_qtbl(struct encode_wq_s *wq) -{ - WRITE_HREG(HCODEC_Q_QUANT_CONTROL, - (0 << 23) | /* quant_table_addr */ - (1 << 22)); /* quant_table_addr_update */ - - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[0]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[1]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[2]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[3]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[4]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[5]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[6]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i4[7]); - - WRITE_HREG(HCODEC_Q_QUANT_CONTROL, - (8 << 23) | /* quant_table_addr */ - (1 << 22)); /* quant_table_addr_update */ - - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[0]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[1]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[2]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[3]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[4]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[5]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[6]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_i16[7]); - - WRITE_HREG(HCODEC_Q_QUANT_CONTROL, - (16 << 23) | /* quant_table_addr */ - (1 << 22)); /* quant_table_addr_update */ - - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[0]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[1]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[2]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[3]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[4]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[5]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[6]); - WRITE_HREG(HCODEC_QUANT_TABLE_DATA, - wq->quant_tbl_me[7]); -} - -static void InitEncodeWeight(void) -{ - me_mv_merge_ctl = - (0x1 << 31) | /* [31] me_merge_mv_en_16 */ - (0x1 << 30) | /* [30] me_merge_small_mv_en_16 */ - (0x1 << 29) | /* [29] me_merge_flex_en_16 */ - (0x1 << 28) | /* [28] me_merge_sad_en_16 */ - (0x1 << 27) | /* [27] me_merge_mv_en_8 */ - (0x1 << 26) | /* [26] me_merge_small_mv_en_8 */ - (0x1 << 25) | /* [25] me_merge_flex_en_8 */ - (0x1 << 24) | /* [24] me_merge_sad_en_8 */ - (0x12 << 18) | - /* [23:18] me_merge_mv_diff_16 - MV diff - * <= n pixel can be merged - */ - (0x2b << 12) | - /* [17:12] me_merge_mv_diff_8 - MV diff - * <= n pixel can be merged - */ - (0x80 << 0); - /* [11:0] me_merge_min_sad - SAD - * >= 0x180 can be merged with other MV - */ - - me_mv_weight_01 = (ME_MV_STEP_WEIGHT_1 << 24) | - (ME_MV_PRE_WEIGHT_1 << 16) | - (ME_MV_STEP_WEIGHT_0 << 8) | - (ME_MV_PRE_WEIGHT_0 << 0); - - me_mv_weight_23 = (ME_MV_STEP_WEIGHT_3 << 24) | - (ME_MV_PRE_WEIGHT_3 << 16) | - (ME_MV_STEP_WEIGHT_2 << 8) | - (ME_MV_PRE_WEIGHT_2 << 0); - - me_sad_range_inc = (ME_SAD_RANGE_3 << 24) | - (ME_SAD_RANGE_2 << 16) | - (ME_SAD_RANGE_1 << 8) | - (ME_SAD_RANGE_0 << 0); - - me_step0_close_mv = (0x100 << 10) | - /* me_step0_big_sad -- two MV sad - * diff bigger will use use 1 - */ - (2 << 5) | /* me_step0_close_mv_y */ - (2 << 0); /* me_step0_close_mv_x */ - - me_f_skip_sad = (0x00 << 24) | /* force_skip_sad_3 */ - (STEP_2_SKIP_SAD << 16) | /* force_skip_sad_2 */ - (STEP_1_SKIP_SAD << 8) | /* force_skip_sad_1 */ - (STEP_0_SKIP_SAD << 0); /* force_skip_sad_0 */ - - me_f_skip_weight = (0x00 << 24) | /* force_skip_weight_3 */ - /* force_skip_weight_2 */ - (STEP_2_SKIP_WEIGHT << 16) | - /* force_skip_weight_1 */ - (STEP_1_SKIP_WEIGHT << 8) | - /* force_skip_weight_0 */ - (STEP_0_SKIP_WEIGHT << 0); - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - me_f_skip_sad = 0; - me_f_skip_weight = 0; - me_mv_weight_01 = 0; - me_mv_weight_23 = 0; - } - - me_sad_enough_01 = (ME_SAD_ENOUGH_1_DATA << 12) | - /* me_sad_enough_1 */ - (ME_SAD_ENOUGH_0_DATA << 0) | - /* me_sad_enough_0 */ - (0 << 12) | /* me_sad_enough_1 */ - (0 << 0); /* me_sad_enough_0 */ - - me_sad_enough_23 = (ADV_MV_8x8_ENOUGH_DATA << 12) | - /* adv_mv_8x8_enough */ - (ME_SAD_ENOUGH_2_DATA << 0) | - /* me_sad_enough_2 */ - (0 << 12) | /* me_sad_enough_3 */ - (0 << 0); /* me_sad_enough_2 */ -} - -/*output stream buffer setting*/ -static void avc_init_output_buffer(struct encode_wq_s *wq) -{ - WRITE_HREG(HCODEC_VLC_VB_MEM_CTL, - ((1 << 31) | (0x3f << 24) | - (0x20 << 16) | (2 << 0))); - WRITE_HREG(HCODEC_VLC_VB_START_PTR, - wq->mem.BitstreamStart); - WRITE_HREG(HCODEC_VLC_VB_WR_PTR, - wq->mem.BitstreamStart); - WRITE_HREG(HCODEC_VLC_VB_SW_RD_PTR, - wq->mem.BitstreamStart); - WRITE_HREG(HCODEC_VLC_VB_END_PTR, - wq->mem.BitstreamEnd); - WRITE_HREG(HCODEC_VLC_VB_CONTROL, 1); - WRITE_HREG(HCODEC_VLC_VB_CONTROL, - ((0 << 14) | (7 << 3) | - (1 << 1) | (0 << 0))); -} - -/*input dct buffer setting*/ -static void avc_init_input_buffer(struct encode_wq_s *wq) -{ - WRITE_HREG(HCODEC_QDCT_MB_START_PTR, - wq->mem.dct_buff_start_addr); - WRITE_HREG(HCODEC_QDCT_MB_END_PTR, - wq->mem.dct_buff_end_addr); - WRITE_HREG(HCODEC_QDCT_MB_WR_PTR, - wq->mem.dct_buff_start_addr); - WRITE_HREG(HCODEC_QDCT_MB_RD_PTR, - wq->mem.dct_buff_start_addr); - WRITE_HREG(HCODEC_QDCT_MB_BUFF, 0); -} - -/*input reference buffer setting*/ -static void avc_init_reference_buffer(s32 canvas) -{ - WRITE_HREG(HCODEC_ANC0_CANVAS_ADDR, canvas); - WRITE_HREG(HCODEC_VLC_HCMD_CONFIG, 0); -} - -static void avc_init_assit_buffer(struct encode_wq_s *wq) -{ - WRITE_HREG(MEM_OFFSET_REG, wq->mem.assit_buffer_offset); -} - -/*deblock buffer setting, same as INI_CANVAS*/ -static void avc_init_dblk_buffer(s32 canvas) -{ - WRITE_HREG(HCODEC_REC_CANVAS_ADDR, canvas); - WRITE_HREG(HCODEC_DBKR_CANVAS_ADDR, canvas); - WRITE_HREG(HCODEC_DBKW_CANVAS_ADDR, canvas); -} - -static void avc_init_encoder(struct encode_wq_s *wq, bool idr) -{ - WRITE_HREG(HCODEC_VLC_TOTAL_BYTES, 0); - WRITE_HREG(HCODEC_VLC_CONFIG, 0x07); - WRITE_HREG(HCODEC_VLC_INT_CONTROL, 0); - - WRITE_HREG(HCODEC_ASSIST_AMR1_INT0, 0x15); - WRITE_HREG(HCODEC_ASSIST_AMR1_INT1, 0x8); - WRITE_HREG(HCODEC_ASSIST_AMR1_INT3, 0x14); - - WRITE_HREG(IDR_PIC_ID, wq->pic.idr_pic_id); - WRITE_HREG(FRAME_NUMBER, - (idr == true) ? 0 : wq->pic.frame_number); - WRITE_HREG(PIC_ORDER_CNT_LSB, - (idr == true) ? 0 : wq->pic.pic_order_cnt_lsb); - - WRITE_HREG(LOG2_MAX_PIC_ORDER_CNT_LSB, - wq->pic.log2_max_pic_order_cnt_lsb); - WRITE_HREG(LOG2_MAX_FRAME_NUM, - wq->pic.log2_max_frame_num); - WRITE_HREG(ANC0_BUFFER_ID, 0); - WRITE_HREG(QPPICTURE, wq->pic.init_qppicture); -} - -static void avc_canvas_init(struct encode_wq_s *wq) -{ - u32 canvas_width, canvas_height; - u32 start_addr = wq->mem.buf_start; - - canvas_width = ((wq->pic.encoder_width + 31) >> 5) << 5; - canvas_height = ((wq->pic.encoder_height + 15) >> 4) << 4; - - canvas_config(ENC_CANVAS_OFFSET, - start_addr + wq->mem.bufspec.dec0_y.buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config(1 + ENC_CANVAS_OFFSET, - start_addr + wq->mem.bufspec.dec0_uv.buf_start, - canvas_width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - /*here the third plane use the same address as the second plane*/ - canvas_config(2 + ENC_CANVAS_OFFSET, - start_addr + wq->mem.bufspec.dec0_uv.buf_start, - canvas_width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - - canvas_config(3 + ENC_CANVAS_OFFSET, - start_addr + wq->mem.bufspec.dec1_y.buf_start, - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config(4 + ENC_CANVAS_OFFSET, - start_addr + wq->mem.bufspec.dec1_uv.buf_start, - canvas_width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - /*here the third plane use the same address as the second plane*/ - canvas_config(5 + ENC_CANVAS_OFFSET, - start_addr + wq->mem.bufspec.dec1_uv.buf_start, - canvas_width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); -} - -static void avc_buffspec_init(struct encode_wq_s *wq) -{ - u32 canvas_width, canvas_height; - u32 start_addr = wq->mem.buf_start; - u32 mb_w = (wq->pic.encoder_width + 15) >> 4; - u32 mb_h = (wq->pic.encoder_height + 15) >> 4; - u32 mbs = mb_w * mb_h; - - canvas_width = ((wq->pic.encoder_width + 31) >> 5) << 5; - canvas_height = ((wq->pic.encoder_height + 15) >> 4) << 4; - - wq->mem.dct_buff_start_addr = start_addr + - wq->mem.bufspec.dct.buf_start; - wq->mem.dct_buff_end_addr = - wq->mem.dct_buff_start_addr + - wq->mem.bufspec.dct.buf_size - 1; - enc_pr(LOG_INFO, "dct_buff_start_addr is 0x%x, wq:%p.\n", - wq->mem.dct_buff_start_addr, (void *)wq); - - wq->mem.bufspec.dec0_uv.buf_start = - wq->mem.bufspec.dec0_y.buf_start + - canvas_width * canvas_height; - wq->mem.bufspec.dec0_uv.buf_size = canvas_width * canvas_height / 2; - wq->mem.bufspec.dec1_uv.buf_start = - wq->mem.bufspec.dec1_y.buf_start + - canvas_width * canvas_height; - wq->mem.bufspec.dec1_uv.buf_size = canvas_width * canvas_height / 2; - wq->mem.assit_buffer_offset = start_addr + - wq->mem.bufspec.assit.buf_start; - enc_pr(LOG_INFO, "assit_buffer_offset is 0x%x, wq: %p.\n", - wq->mem.assit_buffer_offset, (void *)wq); - /*output stream buffer config*/ - wq->mem.BitstreamStart = start_addr + - wq->mem.bufspec.bitstream.buf_start; - wq->mem.BitstreamEnd = - wq->mem.BitstreamStart + - wq->mem.bufspec.bitstream.buf_size - 1; - enc_pr(LOG_INFO, "BitstreamStart is 0x%x, wq: %p.\n", - wq->mem.BitstreamStart, (void *)wq); - - wq->mem.scaler_buff_start_addr = - wq->mem.buf_start + wq->mem.bufspec.scale_buff.buf_start; - wq->mem.dump_info_ddr_start_addr = - wq->mem.buf_start + wq->mem.bufspec.dump_info.buf_start; - enc_pr(LOG_INFO, - "CBR: dump_info_ddr_start_addr:%x.\n", - wq->mem.dump_info_ddr_start_addr); - enc_pr(LOG_INFO, "CBR: buf_start :%d.\n", - wq->mem.buf_start); - enc_pr(LOG_INFO, "CBR: dump_info.buf_start :%d.\n", - wq->mem.bufspec.dump_info.buf_start); - wq->mem.dump_info_ddr_size = - DUMP_INFO_BYTES_PER_MB * mbs; - wq->mem.dump_info_ddr_size = - (wq->mem.dump_info_ddr_size + PAGE_SIZE - 1) - & ~(PAGE_SIZE - 1); - wq->mem.cbr_info_ddr_start_addr = - wq->mem.buf_start + wq->mem.bufspec.cbr_info.buf_start; - wq->mem.cbr_info_ddr_size = - wq->mem.bufspec.cbr_info.buf_size; - wq->mem.cbr_info_ddr_virt_addr = - codec_mm_vmap(wq->mem.cbr_info_ddr_start_addr, - wq->mem.bufspec.cbr_info.buf_size); - - wq->mem.dblk_buf_canvas = - ((ENC_CANVAS_OFFSET + 2) << 16) | - ((ENC_CANVAS_OFFSET + 1) << 8) | - (ENC_CANVAS_OFFSET); - wq->mem.ref_buf_canvas = - ((ENC_CANVAS_OFFSET + 5) << 16) | - ((ENC_CANVAS_OFFSET + 4) << 8) | - (ENC_CANVAS_OFFSET + 3); -} - -static void avc_init_ie_me_parameter(struct encode_wq_s *wq, u32 quant) -{ - ie_cur_ref_sel = 0; - ie_pippeline_block = 12; - /* currently disable half and sub pixel */ - ie_me_mode = - (ie_pippeline_block & IE_PIPPELINE_BLOCK_MASK) << - IE_PIPPELINE_BLOCK_SHIFT; - - WRITE_HREG(IE_ME_MODE, ie_me_mode); - WRITE_HREG(IE_REF_SEL, ie_cur_ref_sel); - WRITE_HREG(IE_ME_MB_TYPE, ie_me_mb_type); -#ifdef MULTI_SLICE_MC - if (fixed_slice_cfg) - WRITE_HREG(FIXED_SLICE_CFG, fixed_slice_cfg); - else if (wq->pic.rows_per_slice != - (wq->pic.encoder_height + 15) >> 4) { - u32 mb_per_slice = (wq->pic.encoder_height + 15) >> 4; - - mb_per_slice = mb_per_slice * wq->pic.rows_per_slice; - WRITE_HREG(FIXED_SLICE_CFG, mb_per_slice); - } else - WRITE_HREG(FIXED_SLICE_CFG, 0); -#else - WRITE_HREG(FIXED_SLICE_CFG, 0); -#endif -} - -/* for temp */ -#define HCODEC_MFDIN_REGC_MBLP (HCODEC_MFDIN_REGB_AMPC + 0x1) -#define HCODEC_MFDIN_REG0D (HCODEC_MFDIN_REGB_AMPC + 0x2) -#define HCODEC_MFDIN_REG0E (HCODEC_MFDIN_REGB_AMPC + 0x3) -#define HCODEC_MFDIN_REG0F (HCODEC_MFDIN_REGB_AMPC + 0x4) -#define HCODEC_MFDIN_REG10 (HCODEC_MFDIN_REGB_AMPC + 0x5) -#define HCODEC_MFDIN_REG11 (HCODEC_MFDIN_REGB_AMPC + 0x6) -#define HCODEC_MFDIN_REG12 (HCODEC_MFDIN_REGB_AMPC + 0x7) -#define HCODEC_MFDIN_REG13 (HCODEC_MFDIN_REGB_AMPC + 0x8) -#define HCODEC_MFDIN_REG14 (HCODEC_MFDIN_REGB_AMPC + 0x9) -#define HCODEC_MFDIN_REG15 (HCODEC_MFDIN_REGB_AMPC + 0xa) -#define HCODEC_MFDIN_REG16 (HCODEC_MFDIN_REGB_AMPC + 0xb) - -static void mfdin_basic(u32 input, u8 iformat, - u8 oformat, u32 picsize_x, u32 picsize_y, - u8 r2y_en, u8 nr, u8 ifmt_extra) -{ - u8 dsample_en; /* Downsample Enable */ - u8 interp_en; /* Interpolation Enable */ - u8 y_size; /* 0:16 Pixels for y direction pickup; 1:8 pixels */ - u8 r2y_mode; /* RGB2YUV Mode, range(0~3) */ - /* mfdin_reg3_canv[25:24]; - * // bytes per pixel in x direction for index0, 0:half 1:1 2:2 3:3 - */ - u8 canv_idx0_bppx; - /* mfdin_reg3_canv[27:26]; - * // bytes per pixel in x direction for index1-2, 0:half 1:1 2:2 3:3 - */ - u8 canv_idx1_bppx; - /* mfdin_reg3_canv[29:28]; - * // bytes per pixel in y direction for index0, 0:half 1:1 2:2 3:3 - */ - u8 canv_idx0_bppy; - /* mfdin_reg3_canv[31:30]; - * // bytes per pixel in y direction for index1-2, 0:half 1:1 2:2 3:3 - */ - u8 canv_idx1_bppy; - u8 ifmt444, ifmt422, ifmt420, linear_bytes4p; - u8 nr_enable; - u8 cfg_y_snr_en; - u8 cfg_y_tnr_en; - u8 cfg_c_snr_en; - u8 cfg_c_tnr_en; - u32 linear_bytesperline; - s32 reg_offset; - bool linear_enable = false; - bool format_err = false; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) { - if ((iformat == 7) && (ifmt_extra > 2)) - format_err = true; - } else if (iformat == 7) - format_err = true; - - if (format_err) { - enc_pr(LOG_ERROR, - "mfdin format err, iformat:%d, ifmt_extra:%d\n", - iformat, ifmt_extra); - return; - } - if (iformat != 7) - ifmt_extra = 0; - - ifmt444 = ((iformat == 1) || (iformat == 5) || (iformat == 8) || - (iformat == 9) || (iformat == 12)) ? 1 : 0; - if (iformat == 7 && ifmt_extra == 1) - ifmt444 = 1; - ifmt422 = ((iformat == 0) || (iformat == 10)) ? 1 : 0; - if (iformat == 7 && ifmt_extra != 1) - ifmt422 = 1; - ifmt420 = ((iformat == 2) || (iformat == 3) || (iformat == 4) || - (iformat == 11)) ? 1 : 0; - dsample_en = ((ifmt444 && (oformat != 2)) || - (ifmt422 && (oformat == 0))) ? 1 : 0; - interp_en = ((ifmt422 && (oformat == 2)) || - (ifmt420 && (oformat != 0))) ? 1 : 0; - y_size = (oformat != 0) ? 1 : 0; - if (iformat == 12) - y_size = 0; - r2y_mode = (r2y_en == 1) ? 1 : 0; /* Fixed to 1 (TODO) */ - canv_idx0_bppx = (iformat == 1) ? 3 : (iformat == 0) ? 2 : 1; - canv_idx1_bppx = (iformat == 4) ? 0 : 1; - canv_idx0_bppy = 1; - canv_idx1_bppy = (iformat == 5) ? 1 : 0; - - if ((iformat == 8) || (iformat == 9) || (iformat == 12)) - linear_bytes4p = 3; - else if (iformat == 10) - linear_bytes4p = 2; - else if (iformat == 11) - linear_bytes4p = 1; - else - linear_bytes4p = 0; - if (iformat == 12) - linear_bytesperline = picsize_x * 4; - else - linear_bytesperline = picsize_x * linear_bytes4p; - - if (iformat < 8) - linear_enable = false; - else - linear_enable = true; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { - reg_offset = -8; - /* nr_mode: 0:Disabled 1:SNR Only 2:TNR Only 3:3DNR */ - nr_enable = (nr) ? 1 : 0; - cfg_y_snr_en = ((nr == 1) || (nr == 3)) ? 1 : 0; - cfg_y_tnr_en = ((nr == 2) || (nr == 3)) ? 1 : 0; - cfg_c_snr_en = cfg_y_snr_en; - /* cfg_c_tnr_en = cfg_y_tnr_en; */ - cfg_c_tnr_en = 0; - - /* NR For Y */ - WRITE_HREG((HCODEC_MFDIN_REG0D + reg_offset), - ((cfg_y_snr_en << 0) | - (y_snr_err_norm << 1) | - (y_snr_gau_bld_core << 2) | - (((y_snr_gau_bld_ofst) & 0xff) << 6) | - (y_snr_gau_bld_rate << 14) | - (y_snr_gau_alp0_min << 20) | - (y_snr_gau_alp0_max << 26))); - WRITE_HREG((HCODEC_MFDIN_REG0E + reg_offset), - ((cfg_y_tnr_en << 0) | - (y_tnr_mc_en << 1) | - (y_tnr_txt_mode << 2) | - (y_tnr_mot_sad_margin << 3) | - (y_tnr_alpha_min << 7) | - (y_tnr_alpha_max << 13) | - (y_tnr_deghost_os << 19))); - WRITE_HREG((HCODEC_MFDIN_REG0F + reg_offset), - ((y_tnr_mot_cortxt_rate << 0) | - (y_tnr_mot_distxt_ofst << 8) | - (y_tnr_mot_distxt_rate << 4) | - (y_tnr_mot_dismot_ofst << 16) | - (y_tnr_mot_frcsad_lock << 24))); - WRITE_HREG((HCODEC_MFDIN_REG10 + reg_offset), - ((y_tnr_mot2alp_frc_gain << 0) | - (y_tnr_mot2alp_nrm_gain << 8) | - (y_tnr_mot2alp_dis_gain << 16) | - (y_tnr_mot2alp_dis_ofst << 24))); - WRITE_HREG((HCODEC_MFDIN_REG11 + reg_offset), - ((y_bld_beta2alp_rate << 0) | - (y_bld_beta_min << 8) | - (y_bld_beta_max << 14))); - - /* NR For C */ - WRITE_HREG((HCODEC_MFDIN_REG12 + reg_offset), - ((cfg_y_snr_en << 0) | - (c_snr_err_norm << 1) | - (c_snr_gau_bld_core << 2) | - (((c_snr_gau_bld_ofst) & 0xff) << 6) | - (c_snr_gau_bld_rate << 14) | - (c_snr_gau_alp0_min << 20) | - (c_snr_gau_alp0_max << 26))); - - WRITE_HREG((HCODEC_MFDIN_REG13 + reg_offset), - ((cfg_c_tnr_en << 0) | - (c_tnr_mc_en << 1) | - (c_tnr_txt_mode << 2) | - (c_tnr_mot_sad_margin << 3) | - (c_tnr_alpha_min << 7) | - (c_tnr_alpha_max << 13) | - (c_tnr_deghost_os << 19))); - WRITE_HREG((HCODEC_MFDIN_REG14 + reg_offset), - ((c_tnr_mot_cortxt_rate << 0) | - (c_tnr_mot_distxt_ofst << 8) | - (c_tnr_mot_distxt_rate << 4) | - (c_tnr_mot_dismot_ofst << 16) | - (c_tnr_mot_frcsad_lock << 24))); - WRITE_HREG((HCODEC_MFDIN_REG15 + reg_offset), - ((c_tnr_mot2alp_frc_gain << 0) | - (c_tnr_mot2alp_nrm_gain << 8) | - (c_tnr_mot2alp_dis_gain << 16) | - (c_tnr_mot2alp_dis_ofst << 24))); - - WRITE_HREG((HCODEC_MFDIN_REG16 + reg_offset), - ((c_bld_beta2alp_rate << 0) | - (c_bld_beta_min << 8) | - (c_bld_beta_max << 14))); - - WRITE_HREG((HCODEC_MFDIN_REG1_CTRL + reg_offset), - (iformat << 0) | (oformat << 4) | - (dsample_en << 6) | (y_size << 8) | - (interp_en << 9) | (r2y_en << 12) | - (r2y_mode << 13) | (ifmt_extra << 16) | - (nr_enable << 19)); - WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset), - (picsize_x << 14) | (picsize_y << 0)); - } else { - reg_offset = 0; - WRITE_HREG((HCODEC_MFDIN_REG1_CTRL + reg_offset), - (iformat << 0) | (oformat << 4) | - (dsample_en << 6) | (y_size << 8) | - (interp_en << 9) | (r2y_en << 12) | - (r2y_mode << 13)); - WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset), - (picsize_x << 12) | (picsize_y << 0)); - } - - if (linear_enable == false) { - WRITE_HREG((HCODEC_MFDIN_REG3_CANV + reg_offset), - (input & 0xffffff) | - (canv_idx1_bppy << 30) | - (canv_idx0_bppy << 28) | - (canv_idx1_bppx << 26) | - (canv_idx0_bppx << 24)); - WRITE_HREG((HCODEC_MFDIN_REG4_LNR0 + reg_offset), - (0 << 16) | (0 << 0)); - WRITE_HREG((HCODEC_MFDIN_REG5_LNR1 + reg_offset), 0); - } else { - WRITE_HREG((HCODEC_MFDIN_REG3_CANV + reg_offset), - (canv_idx1_bppy << 30) | - (canv_idx0_bppy << 28) | - (canv_idx1_bppx << 26) | - (canv_idx0_bppx << 24)); - WRITE_HREG((HCODEC_MFDIN_REG4_LNR0 + reg_offset), - (linear_bytes4p << 16) | (linear_bytesperline << 0)); - WRITE_HREG((HCODEC_MFDIN_REG5_LNR1 + reg_offset), input); - } - - if (iformat == 12) - WRITE_HREG((HCODEC_MFDIN_REG9_ENDN + reg_offset), - (2 << 0) | (1 << 3) | (0 << 6) | - (3 << 9) | (6 << 12) | (5 << 15) | - (4 << 18) | (7 << 21)); - else - WRITE_HREG((HCODEC_MFDIN_REG9_ENDN + reg_offset), - (7 << 0) | (6 << 3) | (5 << 6) | - (4 << 9) | (3 << 12) | (2 << 15) | - (1 << 18) | (0 << 21)); -} - -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D -static int scale_frame(struct encode_wq_s *wq, - struct encode_request_s *request, - struct config_para_ex_s *ge2d_config, - u32 src_addr, bool canvas) -{ - struct ge2d_context_s *context = encode_manager.context; - int src_top, src_left, src_width, src_height; - struct canvas_s cs0, cs1, cs2, cd; - u32 src_canvas, dst_canvas; - u32 src_canvas_w, dst_canvas_w; - u32 src_h = request->src_h; - u32 dst_w = ((wq->pic.encoder_width + 15) >> 4) << 4; - u32 dst_h = ((wq->pic.encoder_height + 15) >> 4) << 4; - int input_format = GE2D_FORMAT_M24_NV21; - - src_top = request->crop_top; - src_left = request->crop_left; - src_width = request->src_w - src_left - request->crop_right; - src_height = request->src_h - src_top - request->crop_bottom; - if (canvas) { - if ((request->fmt == FMT_NV21) - || (request->fmt == FMT_NV12)) { - src_canvas = src_addr & 0xffff; - input_format = GE2D_FORMAT_M24_NV21; - } else if (request->fmt == FMT_BGR888) { - src_canvas = src_addr & 0xffffff; - input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d - } else { - src_canvas = src_addr & 0xffffff; - input_format = GE2D_FORMAT_M24_YUV420; - } - } else { - if ((request->fmt == FMT_NV21) - || (request->fmt == FMT_NV12)) { - src_canvas_w = - ((request->src_w + 31) >> 5) << 5; - canvas_config(ENC_CANVAS_OFFSET + 9, - src_addr, - src_canvas_w, src_h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 10, - src_addr + src_canvas_w * src_h, - src_canvas_w, src_h / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - src_canvas = - ((ENC_CANVAS_OFFSET + 10) << 8) - | (ENC_CANVAS_OFFSET + 9); - input_format = GE2D_FORMAT_M24_NV21; - } else if (request->fmt == FMT_BGR888) { - src_canvas_w = - ((request->src_w + 31) >> 5) << 5; - canvas_config(ENC_CANVAS_OFFSET + 9, - src_addr, - src_canvas_w * 3, src_h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - src_canvas = ENC_CANVAS_OFFSET + 9; - input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d - } else { - src_canvas_w = - ((request->src_w + 63) >> 6) << 6; - canvas_config(ENC_CANVAS_OFFSET + 9, - src_addr, - src_canvas_w, src_h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 10, - src_addr + src_canvas_w * src_h, - src_canvas_w / 2, src_h / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 11, - src_addr + src_canvas_w * src_h * 5 / 4, - src_canvas_w / 2, src_h / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - src_canvas = - ((ENC_CANVAS_OFFSET + 11) << 16) | - ((ENC_CANVAS_OFFSET + 10) << 8) | - (ENC_CANVAS_OFFSET + 9); - input_format = GE2D_FORMAT_M24_YUV420; - } - } - dst_canvas_w = ((dst_w + 31) >> 5) << 5; - canvas_config(ENC_CANVAS_OFFSET + 6, - wq->mem.scaler_buff_start_addr, - dst_canvas_w, dst_h, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 7, - wq->mem.scaler_buff_start_addr + dst_canvas_w * dst_h, - dst_canvas_w, dst_h / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - dst_canvas = ((ENC_CANVAS_OFFSET + 7) << 8) | - (ENC_CANVAS_OFFSET + 6); - ge2d_config->alu_const_color = 0; - ge2d_config->bitmask_en = 0; - ge2d_config->src1_gb_alpha = 0; - ge2d_config->dst_xy_swap = 0; - canvas_read(src_canvas & 0xff, &cs0); - canvas_read((src_canvas >> 8) & 0xff, &cs1); - canvas_read((src_canvas >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; - canvas_read(dst_canvas & 0xff, &cd); - ge2d_config->dst_planes[0].addr = cd.addr; - ge2d_config->dst_planes[0].w = cd.width; - ge2d_config->dst_planes[0].h = cd.height; - ge2d_config->src_key.key_enable = 0; - ge2d_config->src_key.key_mask = 0; - ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = src_canvas; - ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config->src_para.format = input_format | GE2D_LITTLE_ENDIAN; - ge2d_config->src_para.fill_color_en = 0; - ge2d_config->src_para.fill_mode = 0; - ge2d_config->src_para.x_rev = 0; - ge2d_config->src_para.y_rev = 0; - ge2d_config->src_para.color = 0xffffffff; - ge2d_config->src_para.top = 0; - ge2d_config->src_para.left = 0; - ge2d_config->src_para.width = request->src_w; - ge2d_config->src_para.height = request->src_h; - ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config->dst_para.canvas_index = dst_canvas; - ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID; - ge2d_config->dst_para.format = - GE2D_FORMAT_M24_NV21 | GE2D_LITTLE_ENDIAN; - ge2d_config->dst_para.fill_color_en = 0; - ge2d_config->dst_para.fill_mode = 0; - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - ge2d_config->dst_para.color = 0; - ge2d_config->dst_para.top = 0; - ge2d_config->dst_para.left = 0; - ge2d_config->dst_para.width = dst_w; - ge2d_config->dst_para.height = dst_h; - ge2d_config->dst_para.x_rev = 0; - ge2d_config->dst_para.y_rev = 0; - - if (ge2d_context_config_ex(context, ge2d_config) < 0) { - pr_err("++ge2d configing error.\n"); - return -1; - } - stretchblt_noalpha(context, src_left, src_top, src_width, src_height, - 0, 0, wq->pic.encoder_width, wq->pic.encoder_height); - return dst_canvas_w*dst_h * 3 / 2; -} -#endif - -static s32 set_input_format(struct encode_wq_s *wq, - struct encode_request_s *request) -{ - s32 ret = 0; - u8 iformat = MAX_FRAME_FMT, oformat = MAX_FRAME_FMT, r2y_en = 0; - u32 picsize_x, picsize_y, src_addr; - u32 canvas_w = 0; - u32 input = request->src; - u8 ifmt_extra = 0; - - if ((request->fmt == FMT_RGB565) || (request->fmt >= MAX_FRAME_FMT)) - return -1; - - picsize_x = ((wq->pic.encoder_width + 15) >> 4) << 4; - picsize_y = ((wq->pic.encoder_height + 15) >> 4) << 4; - oformat = 0; - if ((request->type == LOCAL_BUFF) - || (request->type == PHYSICAL_BUFF)) { - if ((request->type == LOCAL_BUFF) && - (request->flush_flag & AMVENC_FLUSH_FLAG_INPUT)) - dma_flush(wq->mem.dct_buff_start_addr, - request->framesize); - if (request->type == LOCAL_BUFF) { - input = wq->mem.dct_buff_start_addr; - src_addr = - wq->mem.dct_buff_start_addr; - } else { - src_addr = input; - picsize_y = wq->pic.encoder_height; - } - if (request->scale_enable) { -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D - struct config_para_ex_s ge2d_config; - - memset(&ge2d_config, 0, - sizeof(struct config_para_ex_s)); - scale_frame( - wq, request, - &ge2d_config, - src_addr, - false); - iformat = 2; - r2y_en = 0; - input = ((ENC_CANVAS_OFFSET + 7) << 8) | - (ENC_CANVAS_OFFSET + 6); - ret = 0; - goto MFDIN; -#else - enc_pr(LOG_ERROR, - "Warning: need enable ge2d for scale frame!\n"); - return -1; -#endif - } - if ((request->fmt <= FMT_YUV444_PLANE) || - (request->fmt >= FMT_YUV422_12BIT)) - r2y_en = 0; - else - r2y_en = 1; - - if (request->fmt >= FMT_YUV422_12BIT) { - iformat = 7; - ifmt_extra = request->fmt - FMT_YUV422_12BIT; - if (request->fmt == FMT_YUV422_12BIT) - canvas_w = picsize_x * 24 / 8; - else if (request->fmt == FMT_YUV444_10BIT) - canvas_w = picsize_x * 32 / 8; - else - canvas_w = (picsize_x * 20 + 7) / 8; - canvas_w = ((canvas_w + 31) >> 5) << 5; - canvas_config(ENC_CANVAS_OFFSET + 6, - input, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - input = ENC_CANVAS_OFFSET + 6; - input = input & 0xff; - } else if (request->fmt == FMT_YUV422_SINGLE) - iformat = 10; - else if ((request->fmt == FMT_YUV444_SINGLE) - || (request->fmt == FMT_RGB888)) { - iformat = 1; - if (request->fmt == FMT_RGB888) - r2y_en = 1; - canvas_w = picsize_x * 3; - canvas_w = ((canvas_w + 31) >> 5) << 5; - canvas_config(ENC_CANVAS_OFFSET + 6, - input, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - input = ENC_CANVAS_OFFSET + 6; - } else if ((request->fmt == FMT_NV21) - || (request->fmt == FMT_NV12)) { - canvas_w = ((wq->pic.encoder_width + 31) >> 5) << 5; - iformat = (request->fmt == FMT_NV21) ? 2 : 3; - canvas_config(ENC_CANVAS_OFFSET + 6, - input, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 7, - input + canvas_w * picsize_y, - canvas_w, picsize_y / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - input = ((ENC_CANVAS_OFFSET + 7) << 8) | - (ENC_CANVAS_OFFSET + 6); - } else if (request->fmt == FMT_YUV420) { - iformat = 4; - canvas_w = ((wq->pic.encoder_width + 63) >> 6) << 6; - canvas_config(ENC_CANVAS_OFFSET + 6, - input, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 7, - input + canvas_w * picsize_y, - canvas_w / 2, picsize_y / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 8, - input + canvas_w * picsize_y * 5 / 4, - canvas_w / 2, picsize_y / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - input = ((ENC_CANVAS_OFFSET + 8) << 16) | - ((ENC_CANVAS_OFFSET + 7) << 8) | - (ENC_CANVAS_OFFSET + 6); - } else if ((request->fmt == FMT_YUV444_PLANE) - || (request->fmt == FMT_RGB888_PLANE)) { - if (request->fmt == FMT_RGB888_PLANE) - r2y_en = 1; - iformat = 5; - canvas_w = ((wq->pic.encoder_width + 31) >> 5) << 5; - canvas_config(ENC_CANVAS_OFFSET + 6, - input, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 7, - input + canvas_w * picsize_y, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(ENC_CANVAS_OFFSET + 8, - input + canvas_w * picsize_y * 2, - canvas_w, picsize_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - input = ((ENC_CANVAS_OFFSET + 8) << 16) | - ((ENC_CANVAS_OFFSET + 7) << 8) | - (ENC_CANVAS_OFFSET + 6); - } else if (request->fmt == FMT_RGBA8888) { - r2y_en = 1; - iformat = 12; - } - ret = 0; - } else if (request->type == CANVAS_BUFF) { - r2y_en = 0; - if (request->scale_enable) { -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D - struct config_para_ex_s ge2d_config; - memset(&ge2d_config, 0, - sizeof(struct config_para_ex_s)); - scale_frame( - wq, request, - &ge2d_config, - input, true); - iformat = 2; - r2y_en = 0; - input = ((ENC_CANVAS_OFFSET + 7) << 8) | - (ENC_CANVAS_OFFSET + 6); - ret = 0; - goto MFDIN; -#else - enc_pr(LOG_ERROR, - "Warning: need enable ge2d for scale frame!\n"); - return -1; -#endif - } - if (request->fmt == FMT_YUV422_SINGLE) { - iformat = 0; - input = input & 0xff; - } else if (request->fmt == FMT_YUV444_SINGLE) { - iformat = 1; - input = input & 0xff; - } else if ((request->fmt == FMT_NV21) - || (request->fmt == FMT_NV12)) { - iformat = (request->fmt == FMT_NV21) ? 2 : 3; - input = input & 0xffff; - } else if (request->fmt == FMT_YUV420) { - iformat = 4; - input = input & 0xffffff; - } else if ((request->fmt == FMT_YUV444_PLANE) - || (request->fmt == FMT_RGB888_PLANE)) { - if (request->fmt == FMT_RGB888_PLANE) - r2y_en = 1; - iformat = 5; - input = input & 0xffffff; - } else if ((request->fmt == FMT_YUV422_12BIT) - || (request->fmt == FMT_YUV444_10BIT) - || (request->fmt == FMT_YUV422_10BIT)) { - iformat = 7; - ifmt_extra = request->fmt - FMT_YUV422_12BIT; - input = input & 0xff; - } else - ret = -1; - } -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D -MFDIN: -#endif - if (ret == 0) - mfdin_basic(input, iformat, oformat, - picsize_x, picsize_y, r2y_en, - request->nr_mode, ifmt_extra); - return ret; -} - -#ifdef H264_ENC_CBR -static void ConvertTable2Risc(void *table, u32 len) -{ - u32 i, j; - u16 temp; - u16 *tbl = (u16 *)table; - - if ((len < 8) || (len % 8) || (!table)) { - enc_pr(LOG_ERROR, "ConvertTable2Risc tbl %p, len %d error\n", - table, len); - return; - } - for (i = 0; i < len / 8; i++) { - j = i << 2; - temp = tbl[j]; - tbl[j] = tbl[j + 3]; - tbl[j + 3] = temp; - - temp = tbl[j + 1]; - tbl[j + 1] = tbl[j + 2]; - tbl[j + 2] = temp; - } - -} -#endif - -static void avc_prot_init(struct encode_wq_s *wq, - struct encode_request_s *request, u32 quant, bool IDR) -{ - u32 data32; - u32 pic_width, pic_height; - u32 pic_mb_nr; - u32 pic_mbx, pic_mby; - u32 i_pic_qp, p_pic_qp; - u32 i_pic_qp_c, p_pic_qp_c; - u32 pic_width_in_mb; - u32 slice_qp; - - pic_width = wq->pic.encoder_width; - pic_height = wq->pic.encoder_height; - pic_mb_nr = 0; - pic_mbx = 0; - pic_mby = 0; - i_pic_qp = quant; - p_pic_qp = quant; - - pic_width_in_mb = (pic_width + 15) / 16; - WRITE_HREG(HCODEC_HDEC_MC_OMEM_AUTO, - (1 << 31) | /* use_omem_mb_xy */ - ((pic_width_in_mb - 1) << 16)); /* omem_max_mb_x */ - - WRITE_HREG(HCODEC_VLC_ADV_CONFIG, - /* early_mix_mc_hcmd -- will enable in P Picture */ - (0 << 10) | - (1 << 9) | /* update_top_left_mix */ - (1 << 8) | /* p_top_left_mix */ - /* mv_cal_mixed_type -- will enable in P Picture */ - (0 << 7) | - /* mc_hcmd_mixed_type -- will enable in P Picture */ - (0 << 6) | - (1 << 5) | /* use_separate_int_control */ - (1 << 4) | /* hcmd_intra_use_q_info */ - (1 << 3) | /* hcmd_left_use_prev_info */ - (1 << 2) | /* hcmd_use_q_info */ - (1 << 1) | /* use_q_delta_quant */ - /* detect_I16_from_I4 use qdct detected mb_type */ - (0 << 0)); - - WRITE_HREG(HCODEC_QDCT_ADV_CONFIG, - (1 << 29) | /* mb_info_latch_no_I16_pred_mode */ - (1 << 28) | /* ie_dma_mbxy_use_i_pred */ - (1 << 27) | /* ie_dma_read_write_use_ip_idx */ - (1 << 26) | /* ie_start_use_top_dma_count */ - (1 << 25) | /* i_pred_top_dma_rd_mbbot */ - (1 << 24) | /* i_pred_top_dma_wr_disable */ - /* i_pred_mix -- will enable in P Picture */ - (0 << 23) | - (1 << 22) | /* me_ab_rd_when_intra_in_p */ - (1 << 21) | /* force_mb_skip_run_when_intra */ - /* mc_out_mixed_type -- will enable in P Picture */ - (0 << 20) | - (1 << 19) | /* ie_start_when_quant_not_full */ - (1 << 18) | /* mb_info_state_mix */ - /* mb_type_use_mix_result -- will enable in P Picture */ - (0 << 17) | - /* me_cb_ie_read_enable -- will enable in P Picture */ - (0 << 16) | - /* ie_cur_data_from_me -- will enable in P Picture */ - (0 << 15) | - (1 << 14) | /* rem_per_use_table */ - (0 << 13) | /* q_latch_int_enable */ - (1 << 12) | /* q_use_table */ - (0 << 11) | /* q_start_wait */ - (1 << 10) | /* LUMA_16_LEFT_use_cur */ - (1 << 9) | /* DC_16_LEFT_SUM_use_cur */ - (1 << 8) | /* c_ref_ie_sel_cur */ - (0 << 7) | /* c_ipred_perfect_mode */ - (1 << 6) | /* ref_ie_ul_sel */ - (1 << 5) | /* mb_type_use_ie_result */ - (1 << 4) | /* detect_I16_from_I4 */ - (1 << 3) | /* ie_not_wait_ref_busy */ - (1 << 2) | /* ie_I16_enable */ - (3 << 0)); /* ie_done_sel // fastest when waiting */ - - if (request != NULL) { - WRITE_HREG(HCODEC_IE_WEIGHT, - (request->i16_weight << 16) | - (request->i4_weight << 0)); - WRITE_HREG(HCODEC_ME_WEIGHT, - (request->me_weight << 0)); - WRITE_HREG(HCODEC_SAD_CONTROL_0, - /* ie_sad_offset_I16 */ - (request->i16_weight << 16) | - /* ie_sad_offset_I4 */ - (request->i4_weight << 0)); - WRITE_HREG(HCODEC_SAD_CONTROL_1, - /* ie_sad_shift_I16 */ - (IE_SAD_SHIFT_I16 << 24) | - /* ie_sad_shift_I4 */ - (IE_SAD_SHIFT_I4 << 20) | - /* me_sad_shift_INTER */ - (ME_SAD_SHIFT_INTER << 16) | - /* me_sad_offset_INTER */ - (request->me_weight << 0)); - wq->me_weight = request->me_weight; - wq->i4_weight = request->i4_weight; - wq->i16_weight = request->i16_weight; - } else { - WRITE_HREG(HCODEC_IE_WEIGHT, - (I16MB_WEIGHT_OFFSET << 16) | - (I4MB_WEIGHT_OFFSET << 0)); - WRITE_HREG(HCODEC_ME_WEIGHT, - (ME_WEIGHT_OFFSET << 0)); - WRITE_HREG(HCODEC_SAD_CONTROL_0, - /* ie_sad_offset_I16 */ - (I16MB_WEIGHT_OFFSET << 16) | - /* ie_sad_offset_I4 */ - (I4MB_WEIGHT_OFFSET << 0)); - WRITE_HREG(HCODEC_SAD_CONTROL_1, - /* ie_sad_shift_I16 */ - (IE_SAD_SHIFT_I16 << 24) | - /* ie_sad_shift_I4 */ - (IE_SAD_SHIFT_I4 << 20) | - /* me_sad_shift_INTER */ - (ME_SAD_SHIFT_INTER << 16) | - /* me_sad_offset_INTER */ - (ME_WEIGHT_OFFSET << 0)); - } - - WRITE_HREG(HCODEC_ADV_MV_CTL0, - (ADV_MV_LARGE_16x8 << 31) | - (ADV_MV_LARGE_8x16 << 30) | - (ADV_MV_8x8_WEIGHT << 16) | /* adv_mv_8x8_weight */ - /* adv_mv_4x4x4_weight should be set bigger */ - (ADV_MV_4x4x4_WEIGHT << 0)); - WRITE_HREG(HCODEC_ADV_MV_CTL1, - /* adv_mv_16x16_weight */ - (ADV_MV_16x16_WEIGHT << 16) | - (ADV_MV_LARGE_16x16 << 15) | - (ADV_MV_16_8_WEIGHT << 0)); /* adv_mv_16_8_weight */ - - hcodec_prog_qtbl(wq); - if (IDR) { - i_pic_qp = - wq->quant_tbl_i4[0] & 0xff; - i_pic_qp += - wq->quant_tbl_i16[0] & 0xff; - i_pic_qp /= 2; - p_pic_qp = i_pic_qp; - } else { - i_pic_qp = - wq->quant_tbl_i4[0] & 0xff; - i_pic_qp += - wq->quant_tbl_i16[0] & 0xff; - p_pic_qp = wq->quant_tbl_me[0] & 0xff; - slice_qp = (i_pic_qp + p_pic_qp) / 3; - i_pic_qp = slice_qp; - p_pic_qp = i_pic_qp; - } -#ifdef H264_ENC_CBR - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - data32 = READ_HREG(HCODEC_SAD_CONTROL_1); - data32 = data32 & 0xffff; /* remove sad shift */ - WRITE_HREG(HCODEC_SAD_CONTROL_1, data32); - WRITE_HREG(H264_ENC_CBR_TABLE_ADDR, - wq->mem.cbr_info_ddr_start_addr); - WRITE_HREG(H264_ENC_CBR_MB_SIZE_ADDR, - wq->mem.cbr_info_ddr_start_addr - + CBR_TABLE_SIZE); - WRITE_HREG(H264_ENC_CBR_CTL, - (wq->cbr_info.start_tbl_id << 28) | - (wq->cbr_info.short_shift << 24) | - (wq->cbr_info.long_mb_num << 16) | - (wq->cbr_info.long_th << 0)); - WRITE_HREG(H264_ENC_CBR_REGION_SIZE, - (wq->cbr_info.block_w << 16) | - (wq->cbr_info.block_h << 0)); - } -#endif - - WRITE_HREG(HCODEC_QDCT_VLC_QUANT_CTL_0, - (0 << 19) | /* vlc_delta_quant_1 */ - (i_pic_qp << 13) | /* vlc_quant_1 */ - (0 << 6) | /* vlc_delta_quant_0 */ - (i_pic_qp << 0)); /* vlc_quant_0 */ - WRITE_HREG(HCODEC_QDCT_VLC_QUANT_CTL_1, - (14 << 6) | /* vlc_max_delta_q_neg */ - (13 << 0)); /* vlc_max_delta_q_pos */ - WRITE_HREG(HCODEC_VLC_PIC_SIZE, - pic_width | (pic_height << 16)); - WRITE_HREG(HCODEC_VLC_PIC_POSITION, - (pic_mb_nr << 16) | - (pic_mby << 8) | - (pic_mbx << 0)); - - /* synopsys parallel_case full_case */ - switch (i_pic_qp) { - case 0: - i_pic_qp_c = 0; - break; - case 1: - i_pic_qp_c = 1; - break; - case 2: - i_pic_qp_c = 2; - break; - case 3: - i_pic_qp_c = 3; - break; - case 4: - i_pic_qp_c = 4; - break; - case 5: - i_pic_qp_c = 5; - break; - case 6: - i_pic_qp_c = 6; - break; - case 7: - i_pic_qp_c = 7; - break; - case 8: - i_pic_qp_c = 8; - break; - case 9: - i_pic_qp_c = 9; - break; - case 10: - i_pic_qp_c = 10; - break; - case 11: - i_pic_qp_c = 11; - break; - case 12: - i_pic_qp_c = 12; - break; - case 13: - i_pic_qp_c = 13; - break; - case 14: - i_pic_qp_c = 14; - break; - case 15: - i_pic_qp_c = 15; - break; - case 16: - i_pic_qp_c = 16; - break; - case 17: - i_pic_qp_c = 17; - break; - case 18: - i_pic_qp_c = 18; - break; - case 19: - i_pic_qp_c = 19; - break; - case 20: - i_pic_qp_c = 20; - break; - case 21: - i_pic_qp_c = 21; - break; - case 22: - i_pic_qp_c = 22; - break; - case 23: - i_pic_qp_c = 23; - break; - case 24: - i_pic_qp_c = 24; - break; - case 25: - i_pic_qp_c = 25; - break; - case 26: - i_pic_qp_c = 26; - break; - case 27: - i_pic_qp_c = 27; - break; - case 28: - i_pic_qp_c = 28; - break; - case 29: - i_pic_qp_c = 29; - break; - case 30: - i_pic_qp_c = 29; - break; - case 31: - i_pic_qp_c = 30; - break; - case 32: - i_pic_qp_c = 31; - break; - case 33: - i_pic_qp_c = 32; - break; - case 34: - i_pic_qp_c = 32; - break; - case 35: - i_pic_qp_c = 33; - break; - case 36: - i_pic_qp_c = 34; - break; - case 37: - i_pic_qp_c = 34; - break; - case 38: - i_pic_qp_c = 35; - break; - case 39: - i_pic_qp_c = 35; - break; - case 40: - i_pic_qp_c = 36; - break; - case 41: - i_pic_qp_c = 36; - break; - case 42: - i_pic_qp_c = 37; - break; - case 43: - i_pic_qp_c = 37; - break; - case 44: - i_pic_qp_c = 37; - break; - case 45: - i_pic_qp_c = 38; - break; - case 46: - i_pic_qp_c = 38; - break; - case 47: - i_pic_qp_c = 38; - break; - case 48: - i_pic_qp_c = 39; - break; - case 49: - i_pic_qp_c = 39; - break; - case 50: - i_pic_qp_c = 39; - break; - default: - i_pic_qp_c = 39; - break; - } - - /* synopsys parallel_case full_case */ - switch (p_pic_qp) { - case 0: - p_pic_qp_c = 0; - break; - case 1: - p_pic_qp_c = 1; - break; - case 2: - p_pic_qp_c = 2; - break; - case 3: - p_pic_qp_c = 3; - break; - case 4: - p_pic_qp_c = 4; - break; - case 5: - p_pic_qp_c = 5; - break; - case 6: - p_pic_qp_c = 6; - break; - case 7: - p_pic_qp_c = 7; - break; - case 8: - p_pic_qp_c = 8; - break; - case 9: - p_pic_qp_c = 9; - break; - case 10: - p_pic_qp_c = 10; - break; - case 11: - p_pic_qp_c = 11; - break; - case 12: - p_pic_qp_c = 12; - break; - case 13: - p_pic_qp_c = 13; - break; - case 14: - p_pic_qp_c = 14; - break; - case 15: - p_pic_qp_c = 15; - break; - case 16: - p_pic_qp_c = 16; - break; - case 17: - p_pic_qp_c = 17; - break; - case 18: - p_pic_qp_c = 18; - break; - case 19: - p_pic_qp_c = 19; - break; - case 20: - p_pic_qp_c = 20; - break; - case 21: - p_pic_qp_c = 21; - break; - case 22: - p_pic_qp_c = 22; - break; - case 23: - p_pic_qp_c = 23; - break; - case 24: - p_pic_qp_c = 24; - break; - case 25: - p_pic_qp_c = 25; - break; - case 26: - p_pic_qp_c = 26; - break; - case 27: - p_pic_qp_c = 27; - break; - case 28: - p_pic_qp_c = 28; - break; - case 29: - p_pic_qp_c = 29; - break; - case 30: - p_pic_qp_c = 29; - break; - case 31: - p_pic_qp_c = 30; - break; - case 32: - p_pic_qp_c = 31; - break; - case 33: - p_pic_qp_c = 32; - break; - case 34: - p_pic_qp_c = 32; - break; - case 35: - p_pic_qp_c = 33; - break; - case 36: - p_pic_qp_c = 34; - break; - case 37: - p_pic_qp_c = 34; - break; - case 38: - p_pic_qp_c = 35; - break; - case 39: - p_pic_qp_c = 35; - break; - case 40: - p_pic_qp_c = 36; - break; - case 41: - p_pic_qp_c = 36; - break; - case 42: - p_pic_qp_c = 37; - break; - case 43: - p_pic_qp_c = 37; - break; - case 44: - p_pic_qp_c = 37; - break; - case 45: - p_pic_qp_c = 38; - break; - case 46: - p_pic_qp_c = 38; - break; - case 47: - p_pic_qp_c = 38; - break; - case 48: - p_pic_qp_c = 39; - break; - case 49: - p_pic_qp_c = 39; - break; - case 50: - p_pic_qp_c = 39; - break; - default: - p_pic_qp_c = 39; - break; - } - WRITE_HREG(HCODEC_QDCT_Q_QUANT_I, - (i_pic_qp_c << 22) | - (i_pic_qp << 16) | - ((i_pic_qp_c % 6) << 12) | - ((i_pic_qp_c / 6) << 8) | - ((i_pic_qp % 6) << 4) | - ((i_pic_qp / 6) << 0)); - - WRITE_HREG(HCODEC_QDCT_Q_QUANT_P, - (p_pic_qp_c << 22) | - (p_pic_qp << 16) | - ((p_pic_qp_c % 6) << 12) | - ((p_pic_qp_c / 6) << 8) | - ((p_pic_qp % 6) << 4) | - ((p_pic_qp / 6) << 0)); - -#ifdef ENABLE_IGNORE_FUNCTION - WRITE_HREG(HCODEC_IGNORE_CONFIG, - (1 << 31) | /* ignore_lac_coeff_en */ - (1 << 26) | /* ignore_lac_coeff_else (<1) */ - (1 << 21) | /* ignore_lac_coeff_2 (<1) */ - (2 << 16) | /* ignore_lac_coeff_1 (<2) */ - (1 << 15) | /* ignore_cac_coeff_en */ - (1 << 10) | /* ignore_cac_coeff_else (<1) */ - (1 << 5) | /* ignore_cac_coeff_2 (<1) */ - (3 << 0)); /* ignore_cac_coeff_1 (<2) */ - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) - WRITE_HREG(HCODEC_IGNORE_CONFIG_2, - (1 << 31) | /* ignore_t_lac_coeff_en */ - (1 << 26) | /* ignore_t_lac_coeff_else (<1) */ - (2 << 21) | /* ignore_t_lac_coeff_2 (<2) */ - (6 << 16) | /* ignore_t_lac_coeff_1 (<6) */ - (1<<15) | /* ignore_cdc_coeff_en */ - (0<<14) | /* ignore_t_lac_coeff_else_le_3 */ - (1<<13) | /* ignore_t_lac_coeff_else_le_4 */ - (1<<12) | /* ignore_cdc_only_when_empty_cac_inter */ - (1<<11) | /* ignore_cdc_only_when_one_empty_inter */ - /* ignore_cdc_range_max_inter 0-0, 1-1, 2-2, 3-3 */ - (2<<9) | - /* ignore_cdc_abs_max_inter 0-1, 1-2, 2-3, 3-4 */ - (0<<7) | - /* ignore_cdc_only_when_empty_cac_intra */ - (1<<5) | - /* ignore_cdc_only_when_one_empty_intra */ - (1<<4) | - /* ignore_cdc_range_max_intra 0-0, 1-1, 2-2, 3-3 */ - (1<<2) | - /* ignore_cdc_abs_max_intra 0-1, 1-2, 2-3, 3-4 */ - (0<<0)); - else - WRITE_HREG(HCODEC_IGNORE_CONFIG_2, - (1 << 31) | /* ignore_t_lac_coeff_en */ - (1 << 26) | /* ignore_t_lac_coeff_else (<1) */ - (1 << 21) | /* ignore_t_lac_coeff_2 (<1) */ - (5 << 16) | /* ignore_t_lac_coeff_1 (<5) */ - (0 << 0)); -#else - WRITE_HREG(HCODEC_IGNORE_CONFIG, 0); - WRITE_HREG(HCODEC_IGNORE_CONFIG_2, 0); -#endif - - WRITE_HREG(HCODEC_QDCT_MB_CONTROL, - (1 << 9) | /* mb_info_soft_reset */ - (1 << 0)); /* mb read buffer soft reset */ - - WRITE_HREG(HCODEC_QDCT_MB_CONTROL, - (1 << 28) | /* ignore_t_p8x8 */ - (0 << 27) | /* zero_mc_out_null_non_skipped_mb */ - (0 << 26) | /* no_mc_out_null_non_skipped_mb */ - (0 << 25) | /* mc_out_even_skipped_mb */ - (0 << 24) | /* mc_out_wait_cbp_ready */ - (0 << 23) | /* mc_out_wait_mb_type_ready */ - (1 << 29) | /* ie_start_int_enable */ - (1 << 19) | /* i_pred_enable */ - (1 << 20) | /* ie_sub_enable */ - (1 << 18) | /* iq_enable */ - (1 << 17) | /* idct_enable */ - (1 << 14) | /* mb_pause_enable */ - (1 << 13) | /* q_enable */ - (1 << 12) | /* dct_enable */ - (1 << 10) | /* mb_info_en */ - (0 << 3) | /* endian */ - (0 << 1) | /* mb_read_en */ - (0 << 0)); /* soft reset */ - - WRITE_HREG(HCODEC_SAD_CONTROL, - (0 << 3) | /* ie_result_buff_enable */ - (1 << 2) | /* ie_result_buff_soft_reset */ - (0 << 1) | /* sad_enable */ - (1 << 0)); /* sad soft reset */ - WRITE_HREG(HCODEC_IE_RESULT_BUFFER, 0); - - WRITE_HREG(HCODEC_SAD_CONTROL, - (1 << 3) | /* ie_result_buff_enable */ - (0 << 2) | /* ie_result_buff_soft_reset */ - (1 << 1) | /* sad_enable */ - (0 << 0)); /* sad soft reset */ - - WRITE_HREG(HCODEC_IE_CONTROL, - (1 << 30) | /* active_ul_block */ - (0 << 1) | /* ie_enable */ - (1 << 0)); /* ie soft reset */ - - WRITE_HREG(HCODEC_IE_CONTROL, - (1 << 30) | /* active_ul_block */ - (0 << 1) | /* ie_enable */ - (0 << 0)); /* ie soft reset */ - - WRITE_HREG(HCODEC_ME_SKIP_LINE, - (8 << 24) | /* step_3_skip_line */ - (8 << 18) | /* step_2_skip_line */ - (2 << 12) | /* step_1_skip_line */ - (0 << 6) | /* step_0_skip_line */ - (0 << 0)); - - WRITE_HREG(HCODEC_ME_MV_MERGE_CTL, me_mv_merge_ctl); - WRITE_HREG(HCODEC_ME_STEP0_CLOSE_MV, me_step0_close_mv); - WRITE_HREG(HCODEC_ME_SAD_ENOUGH_01, me_sad_enough_01); - WRITE_HREG(HCODEC_ME_SAD_ENOUGH_23, me_sad_enough_23); - WRITE_HREG(HCODEC_ME_F_SKIP_SAD, me_f_skip_sad); - WRITE_HREG(HCODEC_ME_F_SKIP_WEIGHT, me_f_skip_weight); - WRITE_HREG(HCODEC_ME_MV_WEIGHT_01, me_mv_weight_01); - WRITE_HREG(HCODEC_ME_MV_WEIGHT_23, me_mv_weight_23); - WRITE_HREG(HCODEC_ME_SAD_RANGE_INC, me_sad_range_inc); - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) { - WRITE_HREG(HCODEC_V5_SIMPLE_MB_CTL, 0); - WRITE_HREG(HCODEC_V5_SIMPLE_MB_CTL, - (v5_use_small_diff_cnt << 7) | - (v5_simple_mb_inter_all_en << 6) | - (v5_simple_mb_inter_8x8_en << 5) | - (v5_simple_mb_inter_16_8_en << 4) | - (v5_simple_mb_inter_16x16_en << 3) | - (v5_simple_mb_intra_en << 2) | - (v5_simple_mb_C_en << 1) | - (v5_simple_mb_Y_en << 0)); - WRITE_HREG(HCODEC_V5_MB_DIFF_SUM, 0); - WRITE_HREG(HCODEC_V5_SMALL_DIFF_CNT, - (v5_small_diff_C<<16) | - (v5_small_diff_Y<<0)); - WRITE_HREG(HCODEC_V5_SIMPLE_MB_DQUANT, - v5_simple_dq_setting); - WRITE_HREG(HCODEC_V5_SIMPLE_MB_ME_WEIGHT, - v5_simple_me_weight_setting); - /* txlx can remove it */ - WRITE_HREG(HCODEC_QDCT_CONFIG, 1 << 0); - } - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - WRITE_HREG(HCODEC_V4_FORCE_SKIP_CFG, - (i_pic_qp << 26) | /* v4_force_q_r_intra */ - (i_pic_qp << 20) | /* v4_force_q_r_inter */ - (0 << 19) | /* v4_force_q_y_enable */ - (5 << 16) | /* v4_force_qr_y */ - (6 << 12) | /* v4_force_qp_y */ - (0 << 0)); /* v4_force_skip_sad */ - - /* V3 Force skip */ - WRITE_HREG(HCODEC_V3_SKIP_CONTROL, - (1 << 31) | /* v3_skip_enable */ - (0 << 30) | /* v3_step_1_weight_enable */ - (1 << 28) | /* v3_mv_sad_weight_enable */ - (1 << 27) | /* v3_ipred_type_enable */ - (V3_FORCE_SKIP_SAD_1 << 12) | - (V3_FORCE_SKIP_SAD_0 << 0)); - WRITE_HREG(HCODEC_V3_SKIP_WEIGHT, - (V3_SKIP_WEIGHT_1 << 16) | - (V3_SKIP_WEIGHT_0 << 0)); - WRITE_HREG(HCODEC_V3_L1_SKIP_MAX_SAD, - (V3_LEVEL_1_F_SKIP_MAX_SAD << 16) | - (V3_LEVEL_1_SKIP_MAX_SAD << 0)); - WRITE_HREG(HCODEC_V3_L2_SKIP_WEIGHT, - (V3_FORCE_SKIP_SAD_2 << 16) | - (V3_SKIP_WEIGHT_2 << 0)); - if (request != NULL) { - unsigned int off1, off2; - - off1 = V3_IE_F_ZERO_SAD_I4 - I4MB_WEIGHT_OFFSET; - off2 = V3_IE_F_ZERO_SAD_I16 - - I16MB_WEIGHT_OFFSET; - WRITE_HREG(HCODEC_V3_F_ZERO_CTL_0, - ((request->i16_weight + off2) << 16) | - ((request->i4_weight + off1) << 0)); - off1 = V3_ME_F_ZERO_SAD - ME_WEIGHT_OFFSET; - WRITE_HREG(HCODEC_V3_F_ZERO_CTL_1, - (0 << 25) | - /* v3_no_ver_when_top_zero_en */ - (0 << 24) | - /* v3_no_hor_when_left_zero_en */ - (3 << 16) | /* type_hor break */ - ((request->me_weight + off1) << 0)); - } else { - WRITE_HREG(HCODEC_V3_F_ZERO_CTL_0, - (V3_IE_F_ZERO_SAD_I16 << 16) | - (V3_IE_F_ZERO_SAD_I4 << 0)); - WRITE_HREG(HCODEC_V3_F_ZERO_CTL_1, - (0 << 25) | - /* v3_no_ver_when_top_zero_en */ - (0 << 24) | - /* v3_no_hor_when_left_zero_en */ - (3 << 16) | /* type_hor break */ - (V3_ME_F_ZERO_SAD << 0)); - } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - /* V3 Force skip */ - WRITE_HREG(HCODEC_V3_SKIP_CONTROL, - (1 << 31) | /* v3_skip_enable */ - (0 << 30) | /* v3_step_1_weight_enable */ - (1 << 28) | /* v3_mv_sad_weight_enable */ - (1 << 27) | /* v3_ipred_type_enable */ - (0 << 12) | /* V3_FORCE_SKIP_SAD_1 */ - (0 << 0)); /* V3_FORCE_SKIP_SAD_0 */ - WRITE_HREG(HCODEC_V3_SKIP_WEIGHT, - (V3_SKIP_WEIGHT_1 << 16) | - (V3_SKIP_WEIGHT_0 << 0)); - WRITE_HREG(HCODEC_V3_L1_SKIP_MAX_SAD, - (V3_LEVEL_1_F_SKIP_MAX_SAD << 16) | - (V3_LEVEL_1_SKIP_MAX_SAD << 0)); - WRITE_HREG(HCODEC_V3_L2_SKIP_WEIGHT, - (0 << 16) | /* V3_FORCE_SKIP_SAD_2 */ - (V3_SKIP_WEIGHT_2 << 0)); - WRITE_HREG(HCODEC_V3_F_ZERO_CTL_0, - (0 << 16) | /* V3_IE_F_ZERO_SAD_I16 */ - (0 << 0)); /* V3_IE_F_ZERO_SAD_I4 */ - WRITE_HREG(HCODEC_V3_F_ZERO_CTL_1, - (0 << 25) | /* v3_no_ver_when_top_zero_en */ - (0 << 24) | /* v3_no_hor_when_left_zero_en */ - (3 << 16) | /* type_hor break */ - (0 << 0)); /* V3_ME_F_ZERO_SAD */ - } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - int i; - /* MV SAD Table */ - for (i = 0; i < 64; i++) - WRITE_HREG(HCODEC_V3_MV_SAD_TABLE, - v3_mv_sad[i]); - - /* IE PRED SAD Table*/ - WRITE_HREG(HCODEC_V3_IPRED_TYPE_WEIGHT_0, - (C_ipred_weight_H << 24) | - (C_ipred_weight_V << 16) | - (I4_ipred_weight_else << 8) | - (I4_ipred_weight_most << 0)); - WRITE_HREG(HCODEC_V3_IPRED_TYPE_WEIGHT_1, - (I16_ipred_weight_DC << 24) | - (I16_ipred_weight_H << 16) | - (I16_ipred_weight_V << 8) | - (C_ipred_weight_DC << 0)); - WRITE_HREG(HCODEC_V3_LEFT_SMALL_MAX_SAD, - (v3_left_small_max_me_sad << 16) | - (v3_left_small_max_ie_sad << 0)); - } - WRITE_HREG(HCODEC_IE_DATA_FEED_BUFF_INFO, 0); - - WRITE_HREG(HCODEC_CURR_CANVAS_CTRL, 0); - data32 = READ_HREG(HCODEC_VLC_CONFIG); - data32 = data32 | (1 << 0); /* set pop_coeff_even_all_zero */ - WRITE_HREG(HCODEC_VLC_CONFIG, data32); - - WRITE_HREG(INFO_DUMP_START_ADDR, - wq->mem.dump_info_ddr_start_addr); - - /* clear mailbox interrupt */ - WRITE_HREG(HCODEC_IRQ_MBOX_CLR, 1); - - /* enable mailbox interrupt */ - WRITE_HREG(HCODEC_IRQ_MBOX_MASK, 1); -} - -void amvenc_reset(void) -{ - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - WRITE_VREG(DOS_SW_RESET1, - (1 << 2) | (1 << 6) | - (1 << 7) | (1 << 8) | - (1 << 14) | (1 << 16) | - (1 << 17)); - WRITE_VREG(DOS_SW_RESET1, 0); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); -} - -void amvenc_start(void) -{ - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - WRITE_VREG(DOS_SW_RESET1, - (1 << 12) | (1 << 11)); - WRITE_VREG(DOS_SW_RESET1, 0); - - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - - WRITE_HREG(HCODEC_MPSR, 0x0001); -} - -void amvenc_stop(void) -{ - ulong timeout = jiffies + HZ; - - WRITE_HREG(HCODEC_MPSR, 0); - WRITE_HREG(HCODEC_CPSR, 0); - while (READ_HREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) { - if (time_after(jiffies, timeout)) - break; - } - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - - WRITE_VREG(DOS_SW_RESET1, - (1 << 12) | (1 << 11) | - (1 << 2) | (1 << 6) | - (1 << 7) | (1 << 8) | - (1 << 14) | (1 << 16) | - (1 << 17)); - - WRITE_VREG(DOS_SW_RESET1, 0); - - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); - READ_VREG(DOS_SW_RESET1); -} - -static void __iomem *mc_addr; -static u32 mc_addr_map; -#define MC_SIZE (4096 * 8) -s32 amvenc_loadmc(const char *p, struct encode_wq_s *wq) -{ - ulong timeout; - s32 ret = 0; - - /* use static mempry*/ - if (mc_addr == NULL) { - mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); - if (!mc_addr) { - enc_pr(LOG_ERROR, "avc loadmc iomap mc addr error.\n"); - return -ENOMEM; - } - } - - enc_pr(LOG_ALL, "avc encode ucode name is %s\n", p); - ret = get_data_from_name(p, (u8 *)mc_addr); - if (ret < 0) { - enc_pr(LOG_ERROR, - "avc microcode fail ret=%d, name: %s, wq:%p.\n", - ret, p, (void *)wq); - } - - mc_addr_map = dma_map_single( - &encode_manager.this_pdev->dev, - mc_addr, MC_SIZE, DMA_TO_DEVICE); - - /* mc_addr_map = wq->mem.assit_buffer_offset; */ - /* mc_addr = ioremap_wc(mc_addr_map, MC_SIZE); */ - /* memcpy(mc_addr, p, MC_SIZE); */ - enc_pr(LOG_ALL, "address 0 is 0x%x\n", *((u32 *)mc_addr)); - enc_pr(LOG_ALL, "address 1 is 0x%x\n", *((u32 *)mc_addr + 1)); - enc_pr(LOG_ALL, "address 2 is 0x%x\n", *((u32 *)mc_addr + 2)); - enc_pr(LOG_ALL, "address 3 is 0x%x\n", *((u32 *)mc_addr + 3)); - WRITE_HREG(HCODEC_MPSR, 0); - WRITE_HREG(HCODEC_CPSR, 0); - - /* Read CBUS register for timing */ - timeout = READ_HREG(HCODEC_MPSR); - timeout = READ_HREG(HCODEC_MPSR); - - timeout = jiffies + HZ; - - WRITE_HREG(HCODEC_IMEM_DMA_ADR, mc_addr_map); - WRITE_HREG(HCODEC_IMEM_DMA_COUNT, 0x1000); - WRITE_HREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); - - while (READ_HREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) { - if (time_before(jiffies, timeout)) - schedule(); - else { - enc_pr(LOG_ERROR, "hcodec load mc error\n"); - ret = -EBUSY; - break; - } - } - dma_unmap_single( - &encode_manager.this_pdev->dev, - mc_addr_map, MC_SIZE, DMA_TO_DEVICE); - return ret; -} - -const u32 fix_mc[] __aligned(8) = { - 0x0809c05a, 0x06696000, 0x0c780000, 0x00000000 -}; - - -/* - * DOS top level register access fix. - * When hcodec is running, a protocol register HCODEC_CCPU_INTR_MSK - * is set to make hcodec access one CBUS out of DOS domain once - * to work around a HW bug for 4k2k dual decoder implementation. - * If hcodec is not running, then a ucode is loaded and executed - * instead. - */ -void amvenc_dos_top_reg_fix(void) -{ - bool hcodec_on; - ulong flags; - - spin_lock_irqsave(&lock, flags); - - hcodec_on = vdec_on(VDEC_HCODEC); - - if ((hcodec_on) && (READ_VREG(HCODEC_MPSR) & 1)) { - WRITE_HREG(HCODEC_CCPU_INTR_MSK, 1); - spin_unlock_irqrestore(&lock, flags); - return; - } - - if (!hcodec_on) - vdec_poweron(VDEC_HCODEC); - - amhcodec_loadmc(fix_mc); - - amhcodec_start(); - - udelay(1000); - - amhcodec_stop(); - - if (!hcodec_on) - vdec_poweroff(VDEC_HCODEC); - - spin_unlock_irqrestore(&lock, flags); -} - -bool amvenc_avc_on(void) -{ - bool hcodec_on; - ulong flags; - - spin_lock_irqsave(&lock, flags); - - hcodec_on = vdec_on(VDEC_HCODEC); - hcodec_on &= (encode_manager.wq_count > 0); - - spin_unlock_irqrestore(&lock, flags); - return hcodec_on; -} - -static s32 avc_poweron(u32 clock) -{ - ulong flags; - u32 data32; - - data32 = 0; - - amports_switch_gate("vdec", 1); - - spin_lock_irqsave(&lock, flags); - - WRITE_AOREG(AO_RTI_PWR_CNTL_REG0, - (READ_AOREG(AO_RTI_PWR_CNTL_REG0) & (~0x18))); - udelay(10); - /* Powerup HCODEC */ - /* [1:0] HCODEC */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || - get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) - ? ~0x1 : ~0x3)); - - udelay(10); - - WRITE_VREG(DOS_SW_RESET1, 0xffffffff); - WRITE_VREG(DOS_SW_RESET1, 0); - - /* Enable Dos internal clock gating */ - hvdec_clock_enable(clock); - - /* Powerup HCODEC memories */ - WRITE_VREG(DOS_MEM_PD_HCODEC, 0x0); - - /* Remove HCODEC ISO */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || - get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) - ? ~0x1 : ~0x30)); - - udelay(10); - /* Disable auto-clock gate */ - WRITE_VREG(DOS_GEN_CTRL0, - (READ_VREG(DOS_GEN_CTRL0) | 0x1)); - WRITE_VREG(DOS_GEN_CTRL0, - (READ_VREG(DOS_GEN_CTRL0) & 0xFFFFFFFE)); - - spin_unlock_irqrestore(&lock, flags); - - mdelay(10); - return 0; -} - -static s32 avc_poweroff(void) -{ - ulong flags; - - spin_lock_irqsave(&lock, flags); - - /* enable HCODEC isolation */ - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || - get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) - ? 0x1 : 0x30)); - - /* power off HCODEC memories */ - WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); - - /* disable HCODEC clock */ - hvdec_clock_disable(); - - /* HCODEC power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | - ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || - get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) - ? 0x1 : 0x3)); - - spin_unlock_irqrestore(&lock, flags); - - /* release DOS clk81 clock gating */ - amports_switch_gate("vdec", 0); - return 0; -} - -static s32 reload_mc(struct encode_wq_s *wq) -{ - const char *p = select_ucode(encode_manager.ucode_index); - - amvenc_stop(); - - WRITE_VREG(DOS_SW_RESET1, 0xffffffff); - WRITE_VREG(DOS_SW_RESET1, 0); - - udelay(10); - - WRITE_HREG(HCODEC_ASSIST_MMC_CTRL1, 0x32); - enc_pr(LOG_INFO, "reload microcode\n"); - - if (amvenc_loadmc(p, wq) < 0) - return -EBUSY; - return 0; -} - -static void encode_isr_tasklet(ulong data) -{ - struct encode_manager_s *manager = (struct encode_manager_s *)data; - - enc_pr(LOG_INFO, "encoder is done %d\n", manager->encode_hw_status); - if (((manager->encode_hw_status == ENCODER_IDR_DONE) - || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) - || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) - || (manager->encode_hw_status == ENCODER_PICTURE_DONE)) - && (manager->process_irq)) { - wake_up_interruptible(&manager->event.hw_complete); - } -} - -/* irq function */ -static irqreturn_t enc_isr(s32 irq_number, void *para) -{ - struct encode_manager_s *manager = (struct encode_manager_s *)para; - - WRITE_HREG(HCODEC_IRQ_MBOX_CLR, 1); - - manager->encode_hw_status = READ_HREG(ENCODER_STATUS); - if ((manager->encode_hw_status == ENCODER_IDR_DONE) - || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) - || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) - || (manager->encode_hw_status == ENCODER_PICTURE_DONE)) { - enc_pr(LOG_ALL, "encoder stage is %d\n", - manager->encode_hw_status); - } - - if (((manager->encode_hw_status == ENCODER_IDR_DONE) - || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) - || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) - || (manager->encode_hw_status == ENCODER_PICTURE_DONE)) - && (!manager->process_irq)) { - manager->process_irq = true; - if (manager->encode_hw_status != ENCODER_SEQUENCE_DONE) - manager->need_reset = true; - tasklet_schedule(&manager->encode_tasklet); - } - return IRQ_HANDLED; -} - -static s32 convert_request(struct encode_wq_s *wq, u32 *cmd_info) -{ - int i = 0; - u8 *ptr; - u32 data_offset; - u32 cmd = cmd_info[0]; - - if (!wq) - return -1; - memset(&wq->request, 0, sizeof(struct encode_request_s)); - wq->request.me_weight = ME_WEIGHT_OFFSET; - wq->request.i4_weight = I4MB_WEIGHT_OFFSET; - wq->request.i16_weight = I16MB_WEIGHT_OFFSET; - - if (cmd == ENCODER_SEQUENCE) { - wq->request.cmd = cmd; - wq->request.ucode_mode = cmd_info[1]; - wq->request.quant = cmd_info[2]; - wq->request.flush_flag = cmd_info[3]; - wq->request.timeout = cmd_info[4]; - wq->request.timeout = 5000; /* 5000 ms */ - } else if ((cmd == ENCODER_IDR) || (cmd == ENCODER_NON_IDR)) { - wq->request.cmd = cmd; - wq->request.ucode_mode = cmd_info[1]; - wq->request.type = cmd_info[2]; - wq->request.fmt = cmd_info[3]; - wq->request.src = cmd_info[4]; - wq->request.framesize = cmd_info[5]; - wq->request.quant = cmd_info[6]; - wq->request.flush_flag = cmd_info[7]; - wq->request.timeout = cmd_info[8]; - wq->request.crop_top = cmd_info[9]; - wq->request.crop_bottom = cmd_info[10]; - wq->request.crop_left = cmd_info[11]; - wq->request.crop_right = cmd_info[12]; - wq->request.src_w = cmd_info[13]; - wq->request.src_h = cmd_info[14]; - wq->request.scale_enable = cmd_info[15]; - wq->request.nr_mode = - (nr_mode > 0) ? nr_mode : cmd_info[16]; - if (cmd == ENCODER_IDR) - wq->request.nr_mode = 0; - - data_offset = 17 + - (sizeof(wq->quant_tbl_i4) - + sizeof(wq->quant_tbl_i16) - + sizeof(wq->quant_tbl_me)) / 4; - - if (wq->request.quant == ADJUSTED_QP_FLAG) { - ptr = (u8 *) &cmd_info[17]; - memcpy(wq->quant_tbl_i4, ptr, - sizeof(wq->quant_tbl_i4)); - ptr += sizeof(wq->quant_tbl_i4); - memcpy(wq->quant_tbl_i16, ptr, - sizeof(wq->quant_tbl_i16)); - ptr += sizeof(wq->quant_tbl_i16); - memcpy(wq->quant_tbl_me, ptr, - sizeof(wq->quant_tbl_me)); - wq->request.i4_weight -= - cmd_info[data_offset++]; - wq->request.i16_weight -= - cmd_info[data_offset++]; - wq->request.me_weight -= - cmd_info[data_offset++]; - if (qp_table_debug) { - u8 *qp_tb = (u8 *)(&wq->quant_tbl_i4[0]); - - for (i = 0; i < 32; i++) { - enc_pr(LOG_INFO, "%d ", *qp_tb); - qp_tb++; - } - enc_pr(LOG_INFO, "\n"); - - qp_tb = (u8 *)(&wq->quant_tbl_i16[0]); - for (i = 0; i < 32; i++) { - enc_pr(LOG_INFO, "%d ", *qp_tb); - qp_tb++; - } - enc_pr(LOG_INFO, "\n"); - - qp_tb = (u8 *)(&wq->quant_tbl_me[0]); - for (i = 0; i < 32; i++) { - enc_pr(LOG_INFO, "%d ", *qp_tb); - qp_tb++; - } - enc_pr(LOG_INFO, "\n"); - } - } else { - memset(wq->quant_tbl_me, wq->request.quant, - sizeof(wq->quant_tbl_me)); - memset(wq->quant_tbl_i4, wq->request.quant, - sizeof(wq->quant_tbl_i4)); - memset(wq->quant_tbl_i16, wq->request.quant, - sizeof(wq->quant_tbl_i16)); - data_offset += 3; - } -#ifdef H264_ENC_CBR - wq->cbr_info.block_w = cmd_info[data_offset++]; - wq->cbr_info.block_h = cmd_info[data_offset++]; - wq->cbr_info.long_th = cmd_info[data_offset++]; - wq->cbr_info.start_tbl_id = cmd_info[data_offset++]; - wq->cbr_info.short_shift = CBR_SHORT_SHIFT; - wq->cbr_info.long_mb_num = CBR_LONG_MB_NUM; -#endif - } else { - enc_pr(LOG_ERROR, "error cmd = %d, wq: %p.\n", - cmd, (void *)wq); - return -1; - } - wq->request.parent = wq; - return 0; -} - -void amvenc_avc_start_cmd(struct encode_wq_s *wq, - struct encode_request_s *request) -{ - u32 reload_flag = 0; - - if (request->ucode_mode != encode_manager.ucode_index) { - encode_manager.ucode_index = request->ucode_mode; - if (reload_mc(wq)) { - enc_pr(LOG_ERROR, - "reload mc fail, wq:%p\n", (void *)wq); - return; - } - reload_flag = 1; - encode_manager.need_reset = true; - } - - wq->hw_status = 0; - wq->output_size = 0; - wq->ucode_index = encode_manager.ucode_index; - - ie_me_mode = (0 & ME_PIXEL_MODE_MASK) << ME_PIXEL_MODE_SHIFT; - if (encode_manager.need_reset) { - encode_manager.need_reset = false; - encode_manager.encode_hw_status = ENCODER_IDLE; - amvenc_reset(); - avc_canvas_init(wq); - avc_init_encoder(wq, - (request->cmd == ENCODER_IDR) ? true : false); - avc_init_input_buffer(wq); - avc_init_output_buffer(wq); - avc_prot_init(wq, request, request->quant, - (request->cmd == ENCODER_IDR) ? true : false); - avc_init_assit_buffer(wq); - enc_pr(LOG_INFO, - "begin to new frame, request->cmd: %d, ucode mode: %d, wq:%p.\n", - request->cmd, request->ucode_mode, (void *)wq); - } - if ((request->cmd == ENCODER_IDR) || - (request->cmd == ENCODER_NON_IDR)) { - avc_init_dblk_buffer(wq->mem.dblk_buf_canvas); - avc_init_reference_buffer(wq->mem.ref_buf_canvas); - } - if ((request->cmd == ENCODER_IDR) || - (request->cmd == ENCODER_NON_IDR)) - set_input_format(wq, request); - if (request->cmd == ENCODER_IDR) - ie_me_mb_type = HENC_MB_Type_I4MB; - else if (request->cmd == ENCODER_NON_IDR) - ie_me_mb_type = - (HENC_SKIP_RUN_AUTO << 16) | - (HENC_MB_Type_AUTO << 4) | - (HENC_MB_Type_AUTO << 0); - else - ie_me_mb_type = 0; - avc_init_ie_me_parameter(wq, request->quant); - -#ifdef MULTI_SLICE_MC - if (fixed_slice_cfg) - WRITE_HREG(FIXED_SLICE_CFG, fixed_slice_cfg); - else if (wq->pic.rows_per_slice != - (wq->pic.encoder_height + 15) >> 4) { - u32 mb_per_slice = (wq->pic.encoder_height + 15) >> 4; - - mb_per_slice = mb_per_slice * wq->pic.rows_per_slice; - WRITE_HREG(FIXED_SLICE_CFG, mb_per_slice); - } else - WRITE_HREG(FIXED_SLICE_CFG, 0); -#else - WRITE_HREG(FIXED_SLICE_CFG, 0); -#endif - - encode_manager.encode_hw_status = request->cmd; - wq->hw_status = request->cmd; - WRITE_HREG(ENCODER_STATUS, request->cmd); - if ((request->cmd == ENCODER_IDR) - || (request->cmd == ENCODER_NON_IDR) - || (request->cmd == ENCODER_SEQUENCE) - || (request->cmd == ENCODER_PICTURE)) - encode_manager.process_irq = false; - - if (reload_flag) - amvenc_start(); - enc_pr(LOG_ALL, "amvenc_avc_start cmd, wq:%p.\n", (void *)wq); -} - -static void dma_flush(u32 buf_start, u32 buf_size) -{ - if ((buf_start == 0) || (buf_size == 0)) - return; - dma_sync_single_for_device( - &encode_manager.this_pdev->dev, buf_start, - buf_size, DMA_TO_DEVICE); -} - -static void cache_flush(u32 buf_start, u32 buf_size) -{ - if ((buf_start == 0) || (buf_size == 0)) - return; - dma_sync_single_for_cpu( - &encode_manager.this_pdev->dev, buf_start, - buf_size, DMA_FROM_DEVICE); -} - -static u32 getbuffer(struct encode_wq_s *wq, u32 type) -{ - u32 ret = 0; - - switch (type) { - case ENCODER_BUFFER_INPUT: - ret = wq->mem.dct_buff_start_addr; - break; - case ENCODER_BUFFER_REF0: - ret = wq->mem.dct_buff_start_addr + - wq->mem.bufspec.dec0_y.buf_start; - break; - case ENCODER_BUFFER_REF1: - ret = wq->mem.dct_buff_start_addr + - wq->mem.bufspec.dec1_y.buf_start; - break; - case ENCODER_BUFFER_OUTPUT: - ret = wq->mem.BitstreamStart; - break; - case ENCODER_BUFFER_DUMP: - ret = wq->mem.dump_info_ddr_start_addr; - break; - case ENCODER_BUFFER_CBR: - ret = wq->mem.cbr_info_ddr_start_addr; - break; - default: - break; - } - return ret; -} - -s32 amvenc_avc_start(struct encode_wq_s *wq, u32 clock) -{ - const char *p = select_ucode(encode_manager.ucode_index); - - avc_poweron(clock); - avc_canvas_init(wq); - - WRITE_HREG(HCODEC_ASSIST_MMC_CTRL1, 0x32); - - if (amvenc_loadmc(p, wq) < 0) - return -EBUSY; - - encode_manager.need_reset = true; - encode_manager.process_irq = false; - encode_manager.encode_hw_status = ENCODER_IDLE; - amvenc_reset(); - avc_init_encoder(wq, true); - avc_init_input_buffer(wq); /* dct buffer setting */ - avc_init_output_buffer(wq); /* output stream buffer */ - - ie_me_mode = (0 & ME_PIXEL_MODE_MASK) << ME_PIXEL_MODE_SHIFT; - avc_prot_init(wq, NULL, wq->pic.init_qppicture, true); - if (request_irq(encode_manager.irq_num, enc_isr, IRQF_SHARED, - "enc-irq", (void *)&encode_manager) == 0) - encode_manager.irq_requested = true; - else - encode_manager.irq_requested = false; - - /* decoder buffer , need set before each frame start */ - avc_init_dblk_buffer(wq->mem.dblk_buf_canvas); - /* reference buffer , need set before each frame start */ - avc_init_reference_buffer(wq->mem.ref_buf_canvas); - avc_init_assit_buffer(wq); /* assitant buffer for microcode */ - ie_me_mb_type = 0; - avc_init_ie_me_parameter(wq, wq->pic.init_qppicture); - WRITE_HREG(ENCODER_STATUS, ENCODER_IDLE); - -#ifdef MULTI_SLICE_MC - if (fixed_slice_cfg) - WRITE_HREG(FIXED_SLICE_CFG, fixed_slice_cfg); - else if (wq->pic.rows_per_slice != - (wq->pic.encoder_height + 15) >> 4) { - u32 mb_per_slice = (wq->pic.encoder_height + 15) >> 4; - - mb_per_slice = mb_per_slice * wq->pic.rows_per_slice; - WRITE_HREG(FIXED_SLICE_CFG, mb_per_slice); - } else - WRITE_HREG(FIXED_SLICE_CFG, 0); -#else - WRITE_HREG(FIXED_SLICE_CFG, 0); -#endif - amvenc_start(); - return 0; -} - -void amvenc_avc_stop(void) -{ - if ((encode_manager.irq_num >= 0) && - (encode_manager.irq_requested == true)) { - free_irq(encode_manager.irq_num, &encode_manager); - encode_manager.irq_requested = false; - } - amvenc_stop(); - avc_poweroff(); -} - -static s32 avc_init(struct encode_wq_s *wq) -{ - s32 r = 0; - - encode_manager.ucode_index = wq->ucode_index; - r = amvenc_avc_start(wq, clock_level); - - enc_pr(LOG_DEBUG, - "init avc encode. microcode %d, ret=%d, wq:%p.\n", - encode_manager.ucode_index, r, (void *)wq); - return 0; -} - -static s32 amvenc_avc_light_reset(struct encode_wq_s *wq, u32 value) -{ - s32 r = 0; - - amvenc_avc_stop(); - - mdelay(value); - - encode_manager.ucode_index = UCODE_MODE_FULL; - r = amvenc_avc_start(wq, clock_level); - - enc_pr(LOG_DEBUG, - "amvenc_avc_light_reset finish, wq:%p. ret=%d\n", - (void *)wq, r); - return r; -} - -#ifdef CONFIG_CMA -static u32 checkCMA(void) -{ - u32 ret; - - if (encode_manager.cma_pool_size > 0) { - ret = encode_manager.cma_pool_size; - ret = ret / MIN_SIZE; - } else - ret = 0; - return ret; -} -#endif - -/* file operation */ -static s32 amvenc_avc_open(struct inode *inode, struct file *file) -{ - s32 r = 0; - struct encode_wq_s *wq = NULL; - - file->private_data = NULL; - enc_pr(LOG_DEBUG, "avc open\n"); -#ifdef CONFIG_AM_JPEG_ENCODER - if (jpegenc_on() == true) { - enc_pr(LOG_ERROR, - "hcodec in use for JPEG Encode now.\n"); - return -EBUSY; - } -#endif - -#ifdef CONFIG_CMA - if ((encode_manager.use_reserve == false) && - (encode_manager.check_cma == false)) { - encode_manager.max_instance = checkCMA(); - if (encode_manager.max_instance > 0) { - enc_pr(LOG_DEBUG, - "amvenc_avc check CMA pool success, max instance: %d.\n", - encode_manager.max_instance); - } else { - enc_pr(LOG_ERROR, - "amvenc_avc CMA pool too small.\n"); - } - encode_manager.check_cma = true; - } -#endif - - wq = create_encode_work_queue(); - if (wq == NULL) { - enc_pr(LOG_ERROR, "amvenc_avc create instance fail.\n"); - return -EBUSY; - } - -#ifdef CONFIG_CMA - if (encode_manager.use_reserve == false) { - wq->mem.buf_start = codec_mm_alloc_for_dma(ENCODE_NAME, - MIN_SIZE >> PAGE_SHIFT, 0, - CODEC_MM_FLAGS_CPU); - if (wq->mem.buf_start) { - wq->mem.buf_size = MIN_SIZE; - enc_pr(LOG_DEBUG, - "allocating phys 0x%x, size %dk, wq:%p.\n", - wq->mem.buf_start, - wq->mem.buf_size >> 10, (void *)wq); - } else { - enc_pr(LOG_ERROR, - "CMA failed to allocate dma buffer for %s, wq:%p.\n", - encode_manager.this_pdev->name, - (void *)wq); - destroy_encode_work_queue(wq); - return -ENOMEM; - } - } -#endif - - if (wq->mem.buf_start == 0 || - wq->mem.buf_size < MIN_SIZE) { - enc_pr(LOG_ERROR, - "alloc mem failed, start: 0x%x, size:0x%x, wq:%p.\n", - wq->mem.buf_start, - wq->mem.buf_size, (void *)wq); - destroy_encode_work_queue(wq); - return -ENOMEM; - } - - memcpy(&wq->mem.bufspec, &amvenc_buffspec[0], - sizeof(struct BuffInfo_s)); - - enc_pr(LOG_DEBUG, - "amvenc_avc memory config success, buff start:0x%x, size is 0x%x, wq:%p.\n", - wq->mem.buf_start, wq->mem.buf_size, (void *)wq); - - file->private_data = (void *) wq; - return r; -} - -static s32 amvenc_avc_release(struct inode *inode, struct file *file) -{ - struct encode_wq_s *wq = (struct encode_wq_s *)file->private_data; - - if (wq) { - enc_pr(LOG_DEBUG, "avc release, wq:%p\n", (void *)wq); - destroy_encode_work_queue(wq); - } - return 0; -} - -static long amvenc_avc_ioctl(struct file *file, u32 cmd, ulong arg) -{ - long r = 0; - u32 amrisc_cmd = 0; - struct encode_wq_s *wq = (struct encode_wq_s *)file->private_data; -#define MAX_ADDR_INFO_SIZE 50 - u32 addr_info[MAX_ADDR_INFO_SIZE + 4]; - ulong argV; - u32 buf_start; - s32 canvas = -1; - struct canvas_s dst; - - switch (cmd) { - case AMVENC_AVC_IOC_GET_ADDR: - if ((wq->mem.ref_buf_canvas & 0xff) == (ENC_CANVAS_OFFSET)) - put_user(1, (u32 *)arg); - else - put_user(2, (u32 *)arg); - break; - case AMVENC_AVC_IOC_INPUT_UPDATE: - break; - case AMVENC_AVC_IOC_NEW_CMD: - if (copy_from_user(addr_info, (void *)arg, - MAX_ADDR_INFO_SIZE * sizeof(u32))) { - enc_pr(LOG_ERROR, - "avc get new cmd error, wq:%p.\n", (void *)wq); - return -1; - } - r = convert_request(wq, addr_info); - if (r == 0) - r = encode_wq_add_request(wq); - if (r) { - enc_pr(LOG_ERROR, - "avc add new request error, wq:%p.\n", - (void *)wq); - } - break; - case AMVENC_AVC_IOC_GET_STAGE: - put_user(wq->hw_status, (u32 *)arg); - break; - case AMVENC_AVC_IOC_GET_OUTPUT_SIZE: - addr_info[0] = wq->output_size; - addr_info[1] = wq->me_weight; - addr_info[2] = wq->i4_weight; - addr_info[3] = wq->i16_weight; - r = copy_to_user((u32 *)arg, - addr_info, 4 * sizeof(u32)); - break; - case AMVENC_AVC_IOC_CONFIG_INIT: - if (copy_from_user(addr_info, (void *)arg, - MAX_ADDR_INFO_SIZE * sizeof(u32))) { - enc_pr(LOG_ERROR, - "avc config init error, wq:%p.\n", (void *)wq); - return -1; - } - wq->ucode_index = UCODE_MODE_FULL; -#ifdef MULTI_SLICE_MC - wq->pic.rows_per_slice = addr_info[1]; - enc_pr(LOG_DEBUG, - "avc init -- rows_per_slice: %d, wq: %p.\n", - wq->pic.rows_per_slice, (void *)wq); -#endif - enc_pr(LOG_DEBUG, - "avc init as mode %d, wq: %p.\n", - wq->ucode_index, (void *)wq); - - if (addr_info[2] > wq->mem.bufspec.max_width || - addr_info[3] > wq->mem.bufspec.max_height) { - enc_pr(LOG_ERROR, - "avc config init- encode size %dx%d is larger than supported (%dx%d). wq:%p.\n", - addr_info[2], addr_info[3], - wq->mem.bufspec.max_width, - wq->mem.bufspec.max_height, (void *)wq); - return -1; - } - wq->pic.encoder_width = addr_info[2]; - wq->pic.encoder_height = addr_info[3]; - if (wq->pic.encoder_width * - wq->pic.encoder_height >= 1280 * 720) - clock_level = 6; - else - clock_level = 5; - avc_buffspec_init(wq); - complete(&encode_manager.event.request_in_com); - addr_info[1] = wq->mem.bufspec.dct.buf_start; - addr_info[2] = wq->mem.bufspec.dct.buf_size; - addr_info[3] = wq->mem.bufspec.bitstream.buf_start; - addr_info[4] = wq->mem.bufspec.bitstream.buf_size; - addr_info[5] = wq->mem.bufspec.scale_buff.buf_start; - addr_info[6] = wq->mem.bufspec.scale_buff.buf_size; - addr_info[7] = wq->mem.bufspec.dump_info.buf_start; - addr_info[8] = wq->mem.bufspec.dump_info.buf_size; - addr_info[9] = wq->mem.bufspec.cbr_info.buf_start; - addr_info[10] = wq->mem.bufspec.cbr_info.buf_size; - r = copy_to_user((u32 *)arg, addr_info, 11*sizeof(u32)); - break; - case AMVENC_AVC_IOC_FLUSH_CACHE: - if (copy_from_user(addr_info, (void *)arg, - MAX_ADDR_INFO_SIZE * sizeof(u32))) { - enc_pr(LOG_ERROR, - "avc flush cache error, wq: %p.\n", (void *)wq); - return -1; - } - buf_start = getbuffer(wq, addr_info[0]); - dma_flush(buf_start + addr_info[1], - addr_info[2] - addr_info[1]); - break; - case AMVENC_AVC_IOC_FLUSH_DMA: - if (copy_from_user(addr_info, (void *)arg, - MAX_ADDR_INFO_SIZE * sizeof(u32))) { - enc_pr(LOG_ERROR, - "avc flush dma error, wq:%p.\n", (void *)wq); - return -1; - } - buf_start = getbuffer(wq, addr_info[0]); - cache_flush(buf_start + addr_info[1], - addr_info[2] - addr_info[1]); - break; - case AMVENC_AVC_IOC_GET_BUFFINFO: - put_user(wq->mem.buf_size, (u32 *)arg); - break; - case AMVENC_AVC_IOC_GET_DEVINFO: - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - /* send the same id as GXTVBB to upper*/ - r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_GXTVBB, - strlen(AMVENC_DEVINFO_GXTVBB)); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) { - r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_GXTVBB, - strlen(AMVENC_DEVINFO_GXTVBB)); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) { - r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_GXBB, - strlen(AMVENC_DEVINFO_GXBB)); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_MG9TV) { - r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_G9, - strlen(AMVENC_DEVINFO_G9)); - } else { - r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_M8, - strlen(AMVENC_DEVINFO_M8)); - } - break; - case AMVENC_AVC_IOC_SUBMIT: - get_user(amrisc_cmd, ((u32 *)arg)); - if (amrisc_cmd == ENCODER_IDR) { - wq->pic.idr_pic_id++; - if (wq->pic.idr_pic_id > 65535) - wq->pic.idr_pic_id = 0; - wq->pic.pic_order_cnt_lsb = 2; - wq->pic.frame_number = 1; - } else if (amrisc_cmd == ENCODER_NON_IDR) { - wq->pic.frame_number++; - wq->pic.pic_order_cnt_lsb += 2; - if (wq->pic.frame_number > 65535) - wq->pic.frame_number = 0; - } - amrisc_cmd = wq->mem.dblk_buf_canvas; - wq->mem.dblk_buf_canvas = wq->mem.ref_buf_canvas; - /* current dblk buffer as next reference buffer */ - wq->mem.ref_buf_canvas = amrisc_cmd; - break; - case AMVENC_AVC_IOC_READ_CANVAS: - get_user(argV, ((u32 *)arg)); - canvas = argV; - if (canvas & 0xff) { - canvas_read(canvas & 0xff, &dst); - addr_info[0] = dst.addr; - if ((canvas & 0xff00) >> 8) - canvas_read((canvas & 0xff00) >> 8, &dst); - if ((canvas & 0xff0000) >> 16) - canvas_read((canvas & 0xff0000) >> 16, &dst); - addr_info[1] = dst.addr - addr_info[0] + - dst.width * dst.height; - } else { - addr_info[0] = 0; - addr_info[1] = 0; - } - dma_flush(dst.addr, dst.width * dst.height * 3 / 2); - r = copy_to_user((u32 *)arg, addr_info, 2 * sizeof(u32)); - break; - case AMVENC_AVC_IOC_MAX_INSTANCE: - put_user(encode_manager.max_instance, (u32 *)arg); - break; - default: - r = -1; - break; - } - return r; -} - -#ifdef CONFIG_COMPAT -static long amvenc_avc_compat_ioctl(struct file *filp, - unsigned int cmd, unsigned long args) -{ - unsigned long ret; - - args = (unsigned long)compat_ptr(args); - ret = amvenc_avc_ioctl(filp, cmd, args); - return ret; -} -#endif - -static s32 avc_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct encode_wq_s *wq = (struct encode_wq_s *)filp->private_data; - ulong off = vma->vm_pgoff << PAGE_SHIFT; - ulong vma_size = vma->vm_end - vma->vm_start; - - if (vma_size == 0) { - enc_pr(LOG_ERROR, "vma_size is 0, wq:%p.\n", (void *)wq); - return -EAGAIN; - } - if (!off) - off += wq->mem.buf_start; - enc_pr(LOG_ALL, - "vma_size is %ld , off is %ld, wq:%p.\n", - vma_size, off, (void *)wq); - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO; - /* vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); */ - if (remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - enc_pr(LOG_ERROR, - "set_cached: failed remap_pfn_range, wq:%p.\n", - (void *)wq); - return -EAGAIN; - } - return 0; -} - -static u32 amvenc_avc_poll(struct file *file, poll_table *wait_table) -{ - struct encode_wq_s *wq = (struct encode_wq_s *)file->private_data; - - poll_wait(file, &wq->request_complete, wait_table); - - if (atomic_read(&wq->request_ready)) { - atomic_dec(&wq->request_ready); - return POLLIN | POLLRDNORM; - } - return 0; -} - -static const struct file_operations amvenc_avc_fops = { - .owner = THIS_MODULE, - .open = amvenc_avc_open, - .mmap = avc_mmap, - .release = amvenc_avc_release, - .unlocked_ioctl = amvenc_avc_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amvenc_avc_compat_ioctl, -#endif - .poll = amvenc_avc_poll, -}; - -/* work queue function */ -static s32 encode_process_request(struct encode_manager_s *manager, - struct encode_queue_item_s *pitem) -{ - s32 ret = 0; - struct encode_wq_s *wq = pitem->request.parent; - struct encode_request_s *request = &pitem->request; - u32 timeout = (request->timeout == 0) ? - 1 : msecs_to_jiffies(request->timeout); - u32 buf_start = 0; - u32 size = 0; - u32 flush_size = ((wq->pic.encoder_width + 31) >> 5 << 5) * - ((wq->pic.encoder_height + 15) >> 4 << 4) * 3 / 2; - -#ifdef H264_ENC_CBR - if (request->cmd == ENCODER_IDR || request->cmd == ENCODER_NON_IDR) { - if (request->flush_flag & AMVENC_FLUSH_FLAG_CBR - && get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - void *vaddr = wq->mem.cbr_info_ddr_virt_addr; - ConvertTable2Risc(vaddr, 0xa00); - buf_start = getbuffer(wq, ENCODER_BUFFER_CBR); - codec_mm_dma_flush(vaddr, wq->mem.cbr_info_ddr_size, DMA_TO_DEVICE); - } - } -#endif - -Again: - amvenc_avc_start_cmd(wq, request); - - if (no_timeout) { - wait_event_interruptible(manager->event.hw_complete, - (manager->encode_hw_status == ENCODER_IDR_DONE - || manager->encode_hw_status == ENCODER_NON_IDR_DONE - || manager->encode_hw_status == ENCODER_SEQUENCE_DONE - || manager->encode_hw_status == ENCODER_PICTURE_DONE)); - } else { - wait_event_interruptible_timeout(manager->event.hw_complete, - ((manager->encode_hw_status == ENCODER_IDR_DONE) - || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) - || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) - || (manager->encode_hw_status == ENCODER_PICTURE_DONE)), - timeout); - } - - if ((request->cmd == ENCODER_SEQUENCE) && - (manager->encode_hw_status == ENCODER_SEQUENCE_DONE)) { - wq->sps_size = READ_HREG(HCODEC_VLC_TOTAL_BYTES); - wq->hw_status = manager->encode_hw_status; - request->cmd = ENCODER_PICTURE; - goto Again; - } else if ((request->cmd == ENCODER_PICTURE) && - (manager->encode_hw_status == ENCODER_PICTURE_DONE)) { - wq->pps_size = - READ_HREG(HCODEC_VLC_TOTAL_BYTES) - wq->sps_size; - wq->hw_status = manager->encode_hw_status; - if (request->flush_flag & AMVENC_FLUSH_FLAG_OUTPUT) { - buf_start = getbuffer(wq, ENCODER_BUFFER_OUTPUT); - cache_flush(buf_start, - wq->sps_size + wq->pps_size); - } - wq->output_size = (wq->sps_size << 16) | wq->pps_size; - } else { - wq->hw_status = manager->encode_hw_status; - if ((manager->encode_hw_status == ENCODER_IDR_DONE) || - (manager->encode_hw_status == ENCODER_NON_IDR_DONE)) { - wq->output_size = READ_HREG(HCODEC_VLC_TOTAL_BYTES); - if (request->flush_flag & AMVENC_FLUSH_FLAG_OUTPUT) { - buf_start = getbuffer(wq, - ENCODER_BUFFER_OUTPUT); - cache_flush(buf_start, wq->output_size); - } - if (request->flush_flag & - AMVENC_FLUSH_FLAG_DUMP) { - buf_start = getbuffer(wq, - ENCODER_BUFFER_DUMP); - size = wq->mem.dump_info_ddr_size; - cache_flush(buf_start, size); - //enc_pr(LOG_DEBUG, "CBR flush dump_info done"); - } - if (request->flush_flag & - AMVENC_FLUSH_FLAG_REFERENCE) { - u32 ref_id = ENCODER_BUFFER_REF0; - - if ((wq->mem.ref_buf_canvas & 0xff) == - (ENC_CANVAS_OFFSET)) - ref_id = ENCODER_BUFFER_REF0; - else - ref_id = ENCODER_BUFFER_REF1; - buf_start = getbuffer(wq, ref_id); - cache_flush(buf_start, flush_size); - } - } else { - manager->encode_hw_status = ENCODER_ERROR; - enc_pr(LOG_DEBUG, "avc encode light reset --- "); - enc_pr(LOG_DEBUG, - "frame type: %s, size: %dx%d, wq: %p\n", - (request->cmd == ENCODER_IDR) ? "IDR" : "P", - wq->pic.encoder_width, - wq->pic.encoder_height, (void *)wq); - enc_pr(LOG_DEBUG, - "mb info: 0x%x, encode status: 0x%x, dct status: 0x%x ", - READ_HREG(HCODEC_VLC_MB_INFO), - READ_HREG(ENCODER_STATUS), - READ_HREG(HCODEC_QDCT_STATUS_CTRL)); - enc_pr(LOG_DEBUG, - "vlc status: 0x%x, me status: 0x%x, risc pc:0x%x, debug:0x%x\n", - READ_HREG(HCODEC_VLC_STATUS_CTRL), - READ_HREG(HCODEC_ME_STATUS), - READ_HREG(HCODEC_MPC_E), - READ_HREG(DEBUG_REG)); - amvenc_avc_light_reset(wq, 30); - } - } - atomic_inc(&wq->request_ready); - wake_up_interruptible(&wq->request_complete); - return ret; -} - -s32 encode_wq_add_request(struct encode_wq_s *wq) -{ - struct encode_queue_item_s *pitem = NULL; - struct list_head *head = NULL; - struct encode_wq_s *tmp = NULL; - bool find = false; - - spin_lock(&encode_manager.event.sem_lock); - - head = &encode_manager.wq; - list_for_each_entry(tmp, head, list) { - if ((wq == tmp) && (wq != NULL)) { - find = true; - break; - } - } - - if (find == false) { - enc_pr(LOG_ERROR, "current wq (%p) doesn't register.\n", - (void *)wq); - goto error; - } - - if (list_empty(&encode_manager.free_queue)) { - enc_pr(LOG_ERROR, "work queue no space, wq:%p.\n", - (void *)wq); - goto error; - } - - pitem = list_entry(encode_manager.free_queue.next, - struct encode_queue_item_s, list); - if (IS_ERR(pitem)) - goto error; - - memcpy(&pitem->request, &wq->request, sizeof(struct encode_request_s)); - memset(&wq->request, 0, sizeof(struct encode_request_s)); - wq->hw_status = 0; - wq->output_size = 0; - pitem->request.parent = wq; - list_move_tail(&pitem->list, &encode_manager.process_queue); - spin_unlock(&encode_manager.event.sem_lock); - - enc_pr(LOG_INFO, - "add new work ok, cmd:%d, ucode mode: %d, wq:%p.\n", - pitem->request.cmd, pitem->request.ucode_mode, - (void *)wq); - complete(&encode_manager.event.request_in_com);/* new cmd come in */ - return 0; -error: - spin_unlock(&encode_manager.event.sem_lock); - return -1; -} - -struct encode_wq_s *create_encode_work_queue(void) -{ - struct encode_wq_s *encode_work_queue = NULL; - bool done = false; - u32 i, max_instance; - struct Buff_s *reserve_buff; - - encode_work_queue = kzalloc(sizeof(struct encode_wq_s), GFP_KERNEL); - if (IS_ERR(encode_work_queue)) { - enc_pr(LOG_ERROR, "can't create work queue\n"); - return NULL; - } - max_instance = encode_manager.max_instance; - encode_work_queue->pic.init_qppicture = 26; - encode_work_queue->pic.log2_max_frame_num = 4; - encode_work_queue->pic.log2_max_pic_order_cnt_lsb = 4; - encode_work_queue->pic.idr_pic_id = 0; - encode_work_queue->pic.frame_number = 0; - encode_work_queue->pic.pic_order_cnt_lsb = 0; - encode_work_queue->ucode_index = UCODE_MODE_FULL; - -#ifdef H264_ENC_CBR - encode_work_queue->cbr_info.block_w = 16; - encode_work_queue->cbr_info.block_h = 9; - encode_work_queue->cbr_info.long_th = CBR_LONG_THRESH; - encode_work_queue->cbr_info.start_tbl_id = START_TABLE_ID; - encode_work_queue->cbr_info.short_shift = CBR_SHORT_SHIFT; - encode_work_queue->cbr_info.long_mb_num = CBR_LONG_MB_NUM; -#endif - init_waitqueue_head(&encode_work_queue->request_complete); - atomic_set(&encode_work_queue->request_ready, 0); - spin_lock(&encode_manager.event.sem_lock); - if (encode_manager.wq_count < encode_manager.max_instance) { - list_add_tail(&encode_work_queue->list, &encode_manager.wq); - encode_manager.wq_count++; - if (encode_manager.use_reserve == true) { - for (i = 0; i < max_instance; i++) { - reserve_buff = &encode_manager.reserve_buff[i]; - if (reserve_buff->used == false) { - encode_work_queue->mem.buf_start = - reserve_buff->buf_start; - encode_work_queue->mem.buf_size = - reserve_buff->buf_size; - reserve_buff->used = true; - done = true; - break; - } - } - } else - done = true; - } - spin_unlock(&encode_manager.event.sem_lock); - if (done == false) { - kfree(encode_work_queue); - encode_work_queue = NULL; - enc_pr(LOG_ERROR, "too many work queue!\n"); - } - return encode_work_queue; /* find it */ -} - -static void _destroy_encode_work_queue(struct encode_manager_s *manager, - struct encode_wq_s **wq, - struct encode_wq_s *encode_work_queue, - bool *find) -{ - struct list_head *head; - struct encode_wq_s *wp_tmp = NULL; - u32 i, max_instance; - struct Buff_s *reserve_buff; - u32 buf_start = encode_work_queue->mem.buf_start; - - max_instance = manager->max_instance; - head = &manager->wq; - list_for_each_entry_safe((*wq), wp_tmp, head, list) { - if ((*wq) && (*wq == encode_work_queue)) { - list_del(&(*wq)->list); - if (manager->use_reserve == true) { - for (i = 0; i < max_instance; i++) { - reserve_buff = - &manager->reserve_buff[i]; - if (reserve_buff->used == true && - buf_start == - reserve_buff->buf_start) { - reserve_buff->used = false; - break; - } - } - } - *find = true; - manager->wq_count--; - enc_pr(LOG_DEBUG, - "remove encode_work_queue %p success, %s line %d.\n", - (void *)encode_work_queue, - __func__, __LINE__); - break; - } - } -} - -s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue) -{ - struct encode_queue_item_s *pitem, *tmp; - struct encode_wq_s *wq = NULL; - bool find = false; - - struct list_head *head; - - if (encode_work_queue) { - spin_lock(&encode_manager.event.sem_lock); - if (encode_manager.current_wq == encode_work_queue) { - encode_manager.remove_flag = true; - spin_unlock(&encode_manager.event.sem_lock); - enc_pr(LOG_DEBUG, - "warning--Destroy the running queue, should not be here.\n"); - wait_for_completion( - &encode_manager.event.process_complete); - spin_lock(&encode_manager.event.sem_lock); - } /* else we can delete it safely. */ - - head = &encode_manager.process_queue; - list_for_each_entry_safe(pitem, tmp, head, list) { - if (pitem && pitem->request.parent == - encode_work_queue) { - pitem->request.parent = NULL; - enc_pr(LOG_DEBUG, - "warning--remove not process request, should not be here.\n"); - list_move_tail(&pitem->list, - &encode_manager.free_queue); - } - } - - _destroy_encode_work_queue(&encode_manager, &wq, - encode_work_queue, &find); - spin_unlock(&encode_manager.event.sem_lock); -#ifdef CONFIG_CMA - if (encode_work_queue->mem.buf_start) { - if (wq->mem.cbr_info_ddr_virt_addr != NULL) { - codec_mm_unmap_phyaddr(wq->mem.cbr_info_ddr_virt_addr); - wq->mem.cbr_info_ddr_virt_addr = NULL; - } - codec_mm_free_for_dma( - ENCODE_NAME, - encode_work_queue->mem.buf_start); - encode_work_queue->mem.buf_start = 0; - - } -#endif - kfree(encode_work_queue); - complete(&encode_manager.event.request_in_com); - } - return 0; -} - -static s32 encode_monitor_thread(void *data) -{ - struct encode_manager_s *manager = (struct encode_manager_s *)data; - struct encode_queue_item_s *pitem = NULL; - struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; - s32 ret = 0; - - enc_pr(LOG_DEBUG, "encode workqueue monitor start.\n"); - sched_setscheduler(current, SCHED_FIFO, ¶m); - allow_signal(SIGTERM); - /* setup current_wq here. */ - while (manager->process_queue_state != ENCODE_PROCESS_QUEUE_STOP) { - if (kthread_should_stop()) - break; - - ret = wait_for_completion_interruptible( - &manager->event.request_in_com); - - if (ret == -ERESTARTSYS) - break; - - if (kthread_should_stop()) - break; - if (manager->inited == false) { - spin_lock(&manager->event.sem_lock); - if (!list_empty(&manager->wq)) { - struct encode_wq_s *first_wq = - list_entry(manager->wq.next, - struct encode_wq_s, list); - manager->current_wq = first_wq; - spin_unlock(&manager->event.sem_lock); - if (first_wq) { -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D - if (!manager->context) - manager->context = - create_ge2d_work_queue(); -#endif - avc_init(first_wq); - manager->inited = true; - } - spin_lock(&manager->event.sem_lock); - manager->current_wq = NULL; - spin_unlock(&manager->event.sem_lock); - if (manager->remove_flag) { - complete( - &manager - ->event.process_complete); - manager->remove_flag = false; - } - } else - spin_unlock(&manager->event.sem_lock); - continue; - } - - spin_lock(&manager->event.sem_lock); - pitem = NULL; - if (list_empty(&manager->wq)) { - spin_unlock(&manager->event.sem_lock); - manager->inited = false; - amvenc_avc_stop(); -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D - if (manager->context) { - destroy_ge2d_work_queue(manager->context); - manager->context = NULL; - } -#endif - enc_pr(LOG_DEBUG, "power off encode.\n"); - continue; - } else if (!list_empty(&manager->process_queue)) { - pitem = list_entry(manager->process_queue.next, - struct encode_queue_item_s, list); - list_del(&pitem->list); - manager->current_item = pitem; - manager->current_wq = pitem->request.parent; - } - spin_unlock(&manager->event.sem_lock); - - if (pitem) { - encode_process_request(manager, pitem); - spin_lock(&manager->event.sem_lock); - list_add_tail(&pitem->list, &manager->free_queue); - manager->current_item = NULL; - manager->last_wq = manager->current_wq; - manager->current_wq = NULL; - spin_unlock(&manager->event.sem_lock); - } - if (manager->remove_flag) { - complete(&manager->event.process_complete); - manager->remove_flag = false; - } - } - while (!kthread_should_stop()) - msleep(20); - - enc_pr(LOG_DEBUG, "exit encode_monitor_thread.\n"); - return 0; -} - -static s32 encode_start_monitor(void) -{ - s32 ret = 0; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - y_tnr_mot2alp_nrm_gain = 216; - y_tnr_mot2alp_dis_gain = 144; - c_tnr_mot2alp_nrm_gain = 216; - c_tnr_mot2alp_dis_gain = 144; - } else { - /* more tnr */ - y_tnr_mot2alp_nrm_gain = 144; - y_tnr_mot2alp_dis_gain = 96; - c_tnr_mot2alp_nrm_gain = 144; - c_tnr_mot2alp_dis_gain = 96; - } - - enc_pr(LOG_DEBUG, "encode start monitor.\n"); - encode_manager.process_queue_state = ENCODE_PROCESS_QUEUE_START; - encode_manager.encode_thread = kthread_run(encode_monitor_thread, - &encode_manager, "encode_monitor"); - if (IS_ERR(encode_manager.encode_thread)) { - ret = PTR_ERR(encode_manager.encode_thread); - encode_manager.process_queue_state = ENCODE_PROCESS_QUEUE_STOP; - enc_pr(LOG_ERROR, - "encode monitor : failed to start kthread (%d)\n", ret); - } - return ret; -} - -static s32 encode_stop_monitor(void) -{ - enc_pr(LOG_DEBUG, "stop encode monitor thread\n"); - if (encode_manager.encode_thread) { - spin_lock(&encode_manager.event.sem_lock); - if (!list_empty(&encode_manager.wq)) { - u32 count = encode_manager.wq_count; - - spin_unlock(&encode_manager.event.sem_lock); - enc_pr(LOG_ERROR, - "stop encode monitor thread error, active wq (%d) is not 0.\n", - count); - return -1; - } - spin_unlock(&encode_manager.event.sem_lock); - encode_manager.process_queue_state = ENCODE_PROCESS_QUEUE_STOP; - send_sig(SIGTERM, encode_manager.encode_thread, 1); - complete(&encode_manager.event.request_in_com); - kthread_stop(encode_manager.encode_thread); - encode_manager.encode_thread = NULL; - kfree(mc_addr); - mc_addr = NULL; - } - return 0; -} - -static s32 encode_wq_init(void) -{ - u32 i = 0; - struct encode_queue_item_s *pitem = NULL; - - enc_pr(LOG_DEBUG, "encode_wq_init.\n"); - encode_manager.irq_requested = false; - - spin_lock_init(&encode_manager.event.sem_lock); - init_completion(&encode_manager.event.request_in_com); - init_waitqueue_head(&encode_manager.event.hw_complete); - init_completion(&encode_manager.event.process_complete); - INIT_LIST_HEAD(&encode_manager.process_queue); - INIT_LIST_HEAD(&encode_manager.free_queue); - INIT_LIST_HEAD(&encode_manager.wq); - - tasklet_init(&encode_manager.encode_tasklet, - encode_isr_tasklet, - (ulong)&encode_manager); - - for (i = 0; i < MAX_ENCODE_REQUEST; i++) { - pitem = kcalloc(1, - sizeof(struct encode_queue_item_s), - GFP_KERNEL); - if (IS_ERR(pitem)) { - enc_pr(LOG_ERROR, "can't request queue item memory.\n"); - return -1; - } - pitem->request.parent = NULL; - list_add_tail(&pitem->list, &encode_manager.free_queue); - } - encode_manager.current_wq = NULL; - encode_manager.last_wq = NULL; - encode_manager.encode_thread = NULL; - encode_manager.current_item = NULL; - encode_manager.wq_count = 0; - encode_manager.remove_flag = false; - InitEncodeWeight(); - if (encode_start_monitor()) { - enc_pr(LOG_ERROR, "encode create thread error.\n"); - return -1; - } - return 0; -} - -static s32 encode_wq_uninit(void) -{ - struct encode_queue_item_s *pitem, *tmp; - struct list_head *head; - u32 count = 0; - s32 r = -1; - - enc_pr(LOG_DEBUG, "uninit encode wq.\n"); - if (encode_stop_monitor() == 0) { - if ((encode_manager.irq_num >= 0) && - (encode_manager.irq_requested == true)) { - free_irq(encode_manager.irq_num, &encode_manager); - encode_manager.irq_requested = false; - } - spin_lock(&encode_manager.event.sem_lock); - head = &encode_manager.process_queue; - list_for_each_entry_safe(pitem, tmp, head, list) { - if (pitem) { - list_del(&pitem->list); - kfree(pitem); - count++; - } - } - head = &encode_manager.free_queue; - list_for_each_entry_safe(pitem, tmp, head, list) { - if (pitem) { - list_del(&pitem->list); - kfree(pitem); - count++; - } - } - spin_unlock(&encode_manager.event.sem_lock); - if (count == MAX_ENCODE_REQUEST) - r = 0; - else { - enc_pr(LOG_ERROR, "lost some request item %d.\n", - MAX_ENCODE_REQUEST - count); - } - } - return r; -} - -static ssize_t encode_status_show(struct class *cla, - struct class_attribute *attr, char *buf) -{ - u32 process_count = 0; - u32 free_count = 0; - struct encode_queue_item_s *pitem = NULL; - struct encode_wq_s *current_wq = NULL; - struct encode_wq_s *last_wq = NULL; - struct list_head *head = NULL; - s32 irq_num = 0; - u32 hw_status = 0; - u32 process_queue_state = 0; - u32 wq_count = 0; - u32 ucode_index; - bool need_reset; - bool process_irq; - bool inited; - bool use_reserve; - struct Buff_s reserve_mem; - u32 max_instance; -#ifdef CONFIG_CMA - bool check_cma = false; -#endif - - spin_lock(&encode_manager.event.sem_lock); - head = &encode_manager.free_queue; - list_for_each_entry(pitem, head, list) { - free_count++; - if (free_count > MAX_ENCODE_REQUEST) - break; - } - - head = &encode_manager.process_queue; - list_for_each_entry(pitem, head, list) { - process_count++; - if (free_count > MAX_ENCODE_REQUEST) - break; - } - - current_wq = encode_manager.current_wq; - last_wq = encode_manager.last_wq; - pitem = encode_manager.current_item; - irq_num = encode_manager.irq_num; - hw_status = encode_manager.encode_hw_status; - process_queue_state = encode_manager.process_queue_state; - wq_count = encode_manager.wq_count; - ucode_index = encode_manager.ucode_index; - need_reset = encode_manager.need_reset; - process_irq = encode_manager.process_irq; - inited = encode_manager.inited; - use_reserve = encode_manager.use_reserve; - reserve_mem.buf_start = encode_manager.reserve_mem.buf_start; - reserve_mem.buf_size = encode_manager.reserve_mem.buf_size; - - max_instance = encode_manager.max_instance; -#ifdef CONFIG_CMA - check_cma = encode_manager.check_cma; -#endif - - spin_unlock(&encode_manager.event.sem_lock); - - enc_pr(LOG_DEBUG, - "encode process queue count: %d, free queue count: %d.\n", - process_count, free_count); - enc_pr(LOG_DEBUG, - "encode curent wq: %p, last wq: %p, wq count: %d, max_instance: %d.\n", - current_wq, last_wq, wq_count, max_instance); - if (current_wq) - enc_pr(LOG_DEBUG, - "encode curent wq -- encode width: %d, encode height: %d.\n", - current_wq->pic.encoder_width, - current_wq->pic.encoder_height); - enc_pr(LOG_DEBUG, - "encode curent pitem: %p, ucode_index: %d, hw_status: %d, need_reset: %s, process_irq: %s.\n", - pitem, ucode_index, hw_status, need_reset ? "true" : "false", - process_irq ? "true" : "false"); - enc_pr(LOG_DEBUG, - "encode irq num: %d, inited: %s, process_queue_state: %d.\n", - irq_num, inited ? "true" : "false", process_queue_state); - if (use_reserve) { - enc_pr(LOG_DEBUG, - "encode use reserve memory, buffer start: 0x%x, size: %d MB.\n", - reserve_mem.buf_start, - reserve_mem.buf_size / SZ_1M); - } else { -#ifdef CONFIG_CMA - enc_pr(LOG_DEBUG, "encode check cma: %s.\n", - check_cma ? "true" : "false"); -#endif - } - return snprintf(buf, 40, "encode max instance: %d\n", max_instance); -} - -static struct class_attribute amvenc_class_attrs[] = { - __ATTR(encode_status, - S_IRUGO | S_IWUSR, - encode_status_show, - NULL), - __ATTR_NULL -}; - -static struct class amvenc_avc_class = { - .name = CLASS_NAME, - .class_attrs = amvenc_class_attrs, -}; - -s32 init_avc_device(void) -{ - s32 r = 0; - - r = register_chrdev(0, DEVICE_NAME, &amvenc_avc_fops); - if (r <= 0) { - enc_pr(LOG_ERROR, "register amvenc_avc device error.\n"); - return r; - } - avc_device_major = r; - - r = class_register(&amvenc_avc_class); - if (r < 0) { - enc_pr(LOG_ERROR, "error create amvenc_avc class.\n"); - return r; - } - - amvenc_avc_dev = device_create(&amvenc_avc_class, NULL, - MKDEV(avc_device_major, 0), NULL, - DEVICE_NAME); - - if (IS_ERR(amvenc_avc_dev)) { - enc_pr(LOG_ERROR, "create amvenc_avc device error.\n"); - class_unregister(&amvenc_avc_class); - return -1; - } - return r; -} - -s32 uninit_avc_device(void) -{ - if (amvenc_avc_dev) - device_destroy(&amvenc_avc_class, MKDEV(avc_device_major, 0)); - - class_destroy(&amvenc_avc_class); - - unregister_chrdev(avc_device_major, DEVICE_NAME); - return 0; -} - -static s32 avc_mem_device_init(struct reserved_mem *rmem, struct device *dev) -{ - s32 r; - struct resource res; - - if (!rmem) { - enc_pr(LOG_ERROR, - "Can not obtain I/O memory, and will allocate avc buffer!\n"); - r = -EFAULT; - return r; - } - res.start = (phys_addr_t)rmem->base; - res.end = res.start + (phys_addr_t)rmem->size - 1; - encode_manager.reserve_mem.buf_start = res.start; - encode_manager.reserve_mem.buf_size = res.end - res.start + 1; - - if (encode_manager.reserve_mem.buf_size >= - amvenc_buffspec[0].min_buffsize) { - encode_manager.max_instance = - encode_manager.reserve_mem.buf_size / - amvenc_buffspec[0].min_buffsize; - if (encode_manager.max_instance > MAX_ENCODE_INSTANCE) - encode_manager.max_instance = MAX_ENCODE_INSTANCE; - encode_manager.reserve_buff = kzalloc( - encode_manager.max_instance * - sizeof(struct Buff_s), GFP_KERNEL); - if (encode_manager.reserve_buff) { - u32 i; - struct Buff_s *reserve_buff; - u32 max_instance = encode_manager.max_instance; - - for (i = 0; i < max_instance; i++) { - reserve_buff = &encode_manager.reserve_buff[i]; - reserve_buff->buf_start = - i * - amvenc_buffspec[0] - .min_buffsize + - encode_manager.reserve_mem.buf_start; - reserve_buff->buf_size = - encode_manager.reserve_mem.buf_start; - reserve_buff->used = false; - } - encode_manager.use_reserve = true; - r = 0; - enc_pr(LOG_DEBUG, - "amvenc_avc use reserve memory, buff start: 0x%x, size: 0x%x, max instance is %d\n", - encode_manager.reserve_mem.buf_start, - encode_manager.reserve_mem.buf_size, - encode_manager.max_instance); - } else { - enc_pr(LOG_ERROR, - "amvenc_avc alloc reserve buffer pointer fail. max instance is %d.\n", - encode_manager.max_instance); - encode_manager.max_instance = 0; - encode_manager.reserve_mem.buf_start = 0; - encode_manager.reserve_mem.buf_size = 0; - r = -ENOMEM; - } - } else { - enc_pr(LOG_ERROR, - "amvenc_avc memory resource too small, size is 0x%x. Need 0x%x bytes at least.\n", - encode_manager.reserve_mem.buf_size, - amvenc_buffspec[0] - .min_buffsize); - encode_manager.reserve_mem.buf_start = 0; - encode_manager.reserve_mem.buf_size = 0; - r = -ENOMEM; - } - return r; -} - -static s32 amvenc_avc_probe(struct platform_device *pdev) -{ - /* struct resource mem; */ - s32 res_irq; - s32 idx; - s32 r; - - enc_pr(LOG_INFO, "amvenc_avc probe start.\n"); - - encode_manager.this_pdev = pdev; -#ifdef CONFIG_CMA - encode_manager.check_cma = false; -#endif - encode_manager.reserve_mem.buf_start = 0; - encode_manager.reserve_mem.buf_size = 0; - encode_manager.use_reserve = false; - encode_manager.max_instance = 0; - encode_manager.reserve_buff = NULL; - - idx = of_reserved_mem_device_init(&pdev->dev); - if (idx != 0) { - enc_pr(LOG_DEBUG, - "amvenc_avc_probe -- reserved memory config fail.\n"); - } - - if (encode_manager.use_reserve == false) { -#ifndef CONFIG_CMA - enc_pr(LOG_ERROR, - "amvenc_avc memory is invaild, probe fail!\n"); - return -EFAULT; -#else - encode_manager.cma_pool_size = - (codec_mm_get_total_size() > (MIN_SIZE * 3)) ? - (MIN_SIZE * 3) : codec_mm_get_total_size(); - enc_pr(LOG_DEBUG, - "amvenc_avc - cma memory pool size: %d MB\n", - (u32)encode_manager.cma_pool_size / SZ_1M); -#endif - } - - res_irq = platform_get_irq(pdev, 0); - if (res_irq < 0) { - enc_pr(LOG_ERROR, "[%s] get irq error!", __func__); - return -EINVAL; - } - - encode_manager.irq_num = res_irq; - if (encode_wq_init()) { - kfree(encode_manager.reserve_buff); - encode_manager.reserve_buff = NULL; - enc_pr(LOG_ERROR, "encode work queue init error.\n"); - return -EFAULT; - } - - r = init_avc_device(); - enc_pr(LOG_INFO, "amvenc_avc probe end.\n"); - return r; -} - -static s32 amvenc_avc_remove(struct platform_device *pdev) -{ - kfree(encode_manager.reserve_buff); - encode_manager.reserve_buff = NULL; - if (encode_wq_uninit()) - enc_pr(LOG_ERROR, "encode work queue uninit error.\n"); - uninit_avc_device(); - enc_pr(LOG_INFO, "amvenc_avc remove.\n"); - return 0; -} - -static const struct of_device_id amlogic_avcenc_dt_match[] = { - { - .compatible = "amlogic, amvenc_avc", - }, - {}, -}; - -static struct platform_driver amvenc_avc_driver = { - .probe = amvenc_avc_probe, - .remove = amvenc_avc_remove, - .driver = { - .name = DRIVER_NAME, - .of_match_table = amlogic_avcenc_dt_match, - } -}; - -static struct codec_profile_t amvenc_avc_profile = { - .name = "avc", - .profile = "" -}; - -static s32 __init amvenc_avc_driver_init_module(void) -{ - enc_pr(LOG_INFO, "amvenc_avc module init\n"); - - if (platform_driver_register(&amvenc_avc_driver)) { - enc_pr(LOG_ERROR, - "failed to register amvenc_avc driver\n"); - return -ENODEV; - } - vcodec_profile_register(&amvenc_avc_profile); - return 0; -} - -static void __exit amvenc_avc_driver_remove_module(void) -{ - enc_pr(LOG_INFO, "amvenc_avc module remove.\n"); - - platform_driver_unregister(&amvenc_avc_driver); -} - -static const struct reserved_mem_ops rmem_avc_ops = { - .device_init = avc_mem_device_init, -}; - -static s32 __init avc_mem_setup(struct reserved_mem *rmem) -{ - rmem->ops = &rmem_avc_ops; - enc_pr(LOG_DEBUG, "amvenc_avc reserved mem setup.\n"); - return 0; -} - -module_param(fixed_slice_cfg, uint, 0664); -MODULE_PARM_DESC(fixed_slice_cfg, "\n fixed_slice_cfg\n"); - -module_param(clock_level, uint, 0664); -MODULE_PARM_DESC(clock_level, "\n clock_level\n"); - -module_param(encode_print_level, uint, 0664); -MODULE_PARM_DESC(encode_print_level, "\n encode_print_level\n"); - -module_param(no_timeout, uint, 0664); -MODULE_PARM_DESC(no_timeout, "\n no_timeout flag for process request\n"); - -module_param(nr_mode, int, 0664); -MODULE_PARM_DESC(nr_mode, "\n nr_mode option\n"); - -module_param(qp_table_debug, uint, 0664); -MODULE_PARM_DESC(qp_table_debug, "\n print qp table\n"); - -#ifdef MORE_MODULE_PARAM -module_param(me_mv_merge_ctl, uint, 0664); -MODULE_PARM_DESC(me_mv_merge_ctl, "\n me_mv_merge_ctl\n"); - -module_param(me_step0_close_mv, uint, 0664); -MODULE_PARM_DESC(me_step0_close_mv, "\n me_step0_close_mv\n"); - -module_param(me_f_skip_sad, uint, 0664); -MODULE_PARM_DESC(me_f_skip_sad, "\n me_f_skip_sad\n"); - -module_param(me_f_skip_weight, uint, 0664); -MODULE_PARM_DESC(me_f_skip_weight, "\n me_f_skip_weight\n"); - -module_param(me_mv_weight_01, uint, 0664); -MODULE_PARM_DESC(me_mv_weight_01, "\n me_mv_weight_01\n"); - -module_param(me_mv_weight_23, uint, 0664); -MODULE_PARM_DESC(me_mv_weight_23, "\n me_mv_weight_23\n"); - -module_param(me_sad_range_inc, uint, 0664); -MODULE_PARM_DESC(me_sad_range_inc, "\n me_sad_range_inc\n"); - -module_param(me_sad_enough_01, uint, 0664); -MODULE_PARM_DESC(me_sad_enough_01, "\n me_sad_enough_01\n"); - -module_param(me_sad_enough_23, uint, 0664); -MODULE_PARM_DESC(me_sad_enough_23, "\n me_sad_enough_23\n"); - -module_param(y_tnr_mc_en, uint, 0664); -MODULE_PARM_DESC(y_tnr_mc_en, "\n y_tnr_mc_en option\n"); -module_param(y_tnr_txt_mode, uint, 0664); -MODULE_PARM_DESC(y_tnr_txt_mode, "\n y_tnr_txt_mode option\n"); -module_param(y_tnr_mot_sad_margin, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot_sad_margin, "\n y_tnr_mot_sad_margin option\n"); -module_param(y_tnr_mot_cortxt_rate, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot_cortxt_rate, "\n y_tnr_mot_cortxt_rate option\n"); -module_param(y_tnr_mot_distxt_ofst, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot_distxt_ofst, "\n y_tnr_mot_distxt_ofst option\n"); -module_param(y_tnr_mot_distxt_rate, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot_distxt_rate, "\n y_tnr_mot_distxt_rate option\n"); -module_param(y_tnr_mot_dismot_ofst, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot_dismot_ofst, "\n y_tnr_mot_dismot_ofst option\n"); -module_param(y_tnr_mot_frcsad_lock, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot_frcsad_lock, "\n y_tnr_mot_frcsad_lock option\n"); -module_param(y_tnr_mot2alp_frc_gain, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot2alp_frc_gain, "\n y_tnr_mot2alp_frc_gain option\n"); -module_param(y_tnr_mot2alp_nrm_gain, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot2alp_nrm_gain, "\n y_tnr_mot2alp_nrm_gain option\n"); -module_param(y_tnr_mot2alp_dis_gain, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot2alp_dis_gain, "\n y_tnr_mot2alp_dis_gain option\n"); -module_param(y_tnr_mot2alp_dis_ofst, uint, 0664); -MODULE_PARM_DESC(y_tnr_mot2alp_dis_ofst, "\n y_tnr_mot2alp_dis_ofst option\n"); -module_param(y_tnr_alpha_min, uint, 0664); -MODULE_PARM_DESC(y_tnr_alpha_min, "\n y_tnr_alpha_min option\n"); -module_param(y_tnr_alpha_max, uint, 0664); -MODULE_PARM_DESC(y_tnr_alpha_max, "\n y_tnr_alpha_max option\n"); -module_param(y_tnr_deghost_os, uint, 0664); -MODULE_PARM_DESC(y_tnr_deghost_os, "\n y_tnr_deghost_os option\n"); - -module_param(c_tnr_mc_en, uint, 0664); -MODULE_PARM_DESC(c_tnr_mc_en, "\n c_tnr_mc_en option\n"); -module_param(c_tnr_txt_mode, uint, 0664); -MODULE_PARM_DESC(c_tnr_txt_mode, "\n c_tnr_txt_mode option\n"); -module_param(c_tnr_mot_sad_margin, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot_sad_margin, "\n c_tnr_mot_sad_margin option\n"); -module_param(c_tnr_mot_cortxt_rate, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot_cortxt_rate, "\n c_tnr_mot_cortxt_rate option\n"); -module_param(c_tnr_mot_distxt_ofst, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot_distxt_ofst, "\n c_tnr_mot_distxt_ofst option\n"); -module_param(c_tnr_mot_distxt_rate, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot_distxt_rate, "\n c_tnr_mot_distxt_rate option\n"); -module_param(c_tnr_mot_dismot_ofst, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot_dismot_ofst, "\n c_tnr_mot_dismot_ofst option\n"); -module_param(c_tnr_mot_frcsad_lock, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot_frcsad_lock, "\n c_tnr_mot_frcsad_lock option\n"); -module_param(c_tnr_mot2alp_frc_gain, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot2alp_frc_gain, "\n c_tnr_mot2alp_frc_gain option\n"); -module_param(c_tnr_mot2alp_nrm_gain, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot2alp_nrm_gain, "\n c_tnr_mot2alp_nrm_gain option\n"); -module_param(c_tnr_mot2alp_dis_gain, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot2alp_dis_gain, "\n c_tnr_mot2alp_dis_gain option\n"); -module_param(c_tnr_mot2alp_dis_ofst, uint, 0664); -MODULE_PARM_DESC(c_tnr_mot2alp_dis_ofst, "\n c_tnr_mot2alp_dis_ofst option\n"); -module_param(c_tnr_alpha_min, uint, 0664); -MODULE_PARM_DESC(c_tnr_alpha_min, "\n c_tnr_alpha_min option\n"); -module_param(c_tnr_alpha_max, uint, 0664); -MODULE_PARM_DESC(c_tnr_alpha_max, "\n c_tnr_alpha_max option\n"); -module_param(c_tnr_deghost_os, uint, 0664); -MODULE_PARM_DESC(c_tnr_deghost_os, "\n c_tnr_deghost_os option\n"); - -module_param(y_snr_err_norm, uint, 0664); -MODULE_PARM_DESC(y_snr_err_norm, "\n y_snr_err_norm option\n"); -module_param(y_snr_gau_bld_core, uint, 0664); -MODULE_PARM_DESC(y_snr_gau_bld_core, "\n y_snr_gau_bld_core option\n"); -module_param(y_snr_gau_bld_ofst, int, 0664); -MODULE_PARM_DESC(y_snr_gau_bld_ofst, "\n y_snr_gau_bld_ofst option\n"); -module_param(y_snr_gau_bld_rate, uint, 0664); -MODULE_PARM_DESC(y_snr_gau_bld_rate, "\n y_snr_gau_bld_rate option\n"); -module_param(y_snr_gau_alp0_min, uint, 0664); -MODULE_PARM_DESC(y_snr_gau_alp0_min, "\n y_snr_gau_alp0_min option\n"); -module_param(y_snr_gau_alp0_max, uint, 0664); -MODULE_PARM_DESC(y_snr_gau_alp0_max, "\n y_snr_gau_alp0_max option\n"); -module_param(y_bld_beta2alp_rate, uint, 0664); -MODULE_PARM_DESC(y_bld_beta2alp_rate, "\n y_bld_beta2alp_rate option\n"); -module_param(y_bld_beta_min, uint, 0664); -MODULE_PARM_DESC(y_bld_beta_min, "\n y_bld_beta_min option\n"); -module_param(y_bld_beta_max, uint, 0664); -MODULE_PARM_DESC(y_bld_beta_max, "\n y_bld_beta_max option\n"); - -module_param(c_snr_err_norm, uint, 0664); -MODULE_PARM_DESC(c_snr_err_norm, "\n c_snr_err_norm option\n"); -module_param(c_snr_gau_bld_core, uint, 0664); -MODULE_PARM_DESC(c_snr_gau_bld_core, "\n c_snr_gau_bld_core option\n"); -module_param(c_snr_gau_bld_ofst, int, 0664); -MODULE_PARM_DESC(c_snr_gau_bld_ofst, "\n c_snr_gau_bld_ofst option\n"); -module_param(c_snr_gau_bld_rate, uint, 0664); -MODULE_PARM_DESC(c_snr_gau_bld_rate, "\n c_snr_gau_bld_rate option\n"); -module_param(c_snr_gau_alp0_min, uint, 0664); -MODULE_PARM_DESC(c_snr_gau_alp0_min, "\n c_snr_gau_alp0_min option\n"); -module_param(c_snr_gau_alp0_max, uint, 0664); -MODULE_PARM_DESC(c_snr_gau_alp0_max, "\n c_snr_gau_alp0_max option\n"); -module_param(c_bld_beta2alp_rate, uint, 0664); -MODULE_PARM_DESC(c_bld_beta2alp_rate, "\n c_bld_beta2alp_rate option\n"); -module_param(c_bld_beta_min, uint, 0664); -MODULE_PARM_DESC(c_bld_beta_min, "\n c_bld_beta_min option\n"); -module_param(c_bld_beta_max, uint, 0664); -MODULE_PARM_DESC(c_bld_beta_max, "\n c_bld_beta_max option\n"); -#endif - -module_init(amvenc_avc_driver_init_module); -module_exit(amvenc_avc_driver_remove_module); -RESERVEDMEM_OF_DECLARE(amvenc_avc, "amlogic, amvenc-memory", avc_mem_setup); - -MODULE_DESCRIPTION("AMLOGIC AVC Video Encoder Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("simon.zheng "); diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h deleted file mode 100644 index a5e0ceee1c12..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h +++ /dev/null @@ -1,471 +0,0 @@ -/* - * drivers/amlogic/amports/encoder.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef __H264_H__ -#define __H264_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D -#include -#endif - -#define AMVENC_DEVINFO_M8 "AML-M8" -#define AMVENC_DEVINFO_G9 "AML-G9" -#define AMVENC_DEVINFO_GXBB "AML-GXBB" -#define AMVENC_DEVINFO_GXTVBB "AML-GXTVBB" -#define AMVENC_DEVINFO_GXL "AML-GXL" - -#define HCODEC_IRQ_MBOX_CLR HCODEC_ASSIST_MBOX2_CLR_REG -#define HCODEC_IRQ_MBOX_MASK HCODEC_ASSIST_MBOX2_MASK - -/* M8: 2550/10 = 255M GX: 2000/10 = 200M */ -#define HDEC_L0() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (2 << 25) | (1 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) -/* M8: 2550/8 = 319M GX: 2000/8 = 250M */ -#define HDEC_L1() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (0 << 25) | (1 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) -/* M8: 2550/7 = 364M GX: 2000/7 = 285M */ -#define HDEC_L2() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (3 << 25) | (0 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) -/* M8: 2550/6 = 425M GX: 2000/6 = 333M */ -#define HDEC_L3() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (1 << 25) | (1 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) -/* M8: 2550/5 = 510M GX: 2000/5 = 400M */ -#define HDEC_L4() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (2 << 25) | (0 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) -/* M8: 2550/4 = 638M GX: 2000/4 = 500M */ -#define HDEC_L5() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (0 << 25) | (0 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) -/* M8: 2550/3 = 850M GX: 2000/3 = 667M */ -#define HDEC_L6() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ - (1 << 25) | (0 << 16) | (1 << 24) | \ - (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) - -#define hvdec_clock_enable(level) \ - do { \ - if (level == 0) \ - HDEC_L0(); \ - else if (level == 1) \ - HDEC_L1(); \ - else if (level == 2) \ - HDEC_L2(); \ - else if (level == 3) \ - HDEC_L3(); \ - else if (level == 4) \ - HDEC_L4(); \ - else if (level == 5) \ - HDEC_L5(); \ - else if (level == 6) \ - HDEC_L6(); \ - WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); \ - } while (0) - -#define hvdec_clock_disable() \ - do { \ - WRITE_VREG_BITS(DOS_GCLK_EN0, 0, 12, 15); \ - WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1); \ - } while (0) - -#define LOG_ALL 0 -#define LOG_INFO 1 -#define LOG_DEBUG 2 -#define LOG_ERROR 3 - -#define enc_pr(level, x...) \ - do { \ - if (level >= encode_print_level) \ - printk(x); \ - } while (0) - -#define AMVENC_AVC_IOC_MAGIC 'E' - -#define AMVENC_AVC_IOC_GET_DEVINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0xf0, u32) -#define AMVENC_AVC_IOC_MAX_INSTANCE _IOW(AMVENC_AVC_IOC_MAGIC, 0xf1, u32) - -#define AMVENC_AVC_IOC_GET_ADDR _IOW(AMVENC_AVC_IOC_MAGIC, 0x00, u32) -#define AMVENC_AVC_IOC_INPUT_UPDATE _IOW(AMVENC_AVC_IOC_MAGIC, 0x01, u32) -#define AMVENC_AVC_IOC_NEW_CMD _IOW(AMVENC_AVC_IOC_MAGIC, 0x02, u32) -#define AMVENC_AVC_IOC_GET_STAGE _IOW(AMVENC_AVC_IOC_MAGIC, 0x03, u32) -#define AMVENC_AVC_IOC_GET_OUTPUT_SIZE _IOW(AMVENC_AVC_IOC_MAGIC, 0x04, u32) -#define AMVENC_AVC_IOC_CONFIG_INIT _IOW(AMVENC_AVC_IOC_MAGIC, 0x05, u32) -#define AMVENC_AVC_IOC_FLUSH_CACHE _IOW(AMVENC_AVC_IOC_MAGIC, 0x06, u32) -#define AMVENC_AVC_IOC_FLUSH_DMA _IOW(AMVENC_AVC_IOC_MAGIC, 0x07, u32) -#define AMVENC_AVC_IOC_GET_BUFFINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0x08, u32) -#define AMVENC_AVC_IOC_SUBMIT _IOW(AMVENC_AVC_IOC_MAGIC, 0x09, u32) -#define AMVENC_AVC_IOC_READ_CANVAS _IOW(AMVENC_AVC_IOC_MAGIC, 0x0a, u32) - - -#define IE_PIPPELINE_BLOCK_SHIFT 0 -#define IE_PIPPELINE_BLOCK_MASK 0x1f -#define ME_PIXEL_MODE_SHIFT 5 -#define ME_PIXEL_MODE_MASK 0x3 - -enum amvenc_mem_type_e { - LOCAL_BUFF = 0, - CANVAS_BUFF, - PHYSICAL_BUFF, - MAX_BUFF_TYPE -}; - -enum amvenc_frame_fmt_e { - FMT_YUV422_SINGLE = 0, - FMT_YUV444_SINGLE, - FMT_NV21, - FMT_NV12, - FMT_YUV420, - FMT_YUV444_PLANE, - FMT_RGB888, - FMT_RGB888_PLANE, - FMT_RGB565, - FMT_RGBA8888, - FMT_YUV422_12BIT, - FMT_YUV444_10BIT, - FMT_YUV422_10BIT, - FMT_BGR888, - MAX_FRAME_FMT -}; - -#define MAX_ENCODE_REQUEST 8 /* 64 */ - -#define MAX_ENCODE_INSTANCE 8 /* 64 */ - -#define ENCODE_PROCESS_QUEUE_START 0 -#define ENCODE_PROCESS_QUEUE_STOP 1 - -#define AMVENC_FLUSH_FLAG_INPUT 0x1 -#define AMVENC_FLUSH_FLAG_OUTPUT 0x2 -#define AMVENC_FLUSH_FLAG_REFERENCE 0x4 -#define AMVENC_FLUSH_FLAG_INTRA_INFO 0x8 -#define AMVENC_FLUSH_FLAG_INTER_INFO 0x10 -#define AMVENC_FLUSH_FLAG_QP 0x20 -#define AMVENC_FLUSH_FLAG_DUMP 0x40 -#define AMVENC_FLUSH_FLAG_CBR 0x80 - -#define ENCODER_BUFFER_INPUT 0 -#define ENCODER_BUFFER_REF0 1 -#define ENCODER_BUFFER_REF1 2 -#define ENCODER_BUFFER_OUTPUT 3 -#define ENCODER_BUFFER_INTER_INFO 4 -#define ENCODER_BUFFER_INTRA_INFO 5 -#define ENCODER_BUFFER_QP 6 -#define ENCODER_BUFFER_DUMP 7 -#define ENCODER_BUFFER_CBR 8 - -struct encode_wq_s; - -struct encode_request_s { - u32 quant; - u32 cmd; - u32 ucode_mode; - - u32 src; - - u32 framesize; - - u32 me_weight; - u32 i4_weight; - u32 i16_weight; - - u32 crop_top; - u32 crop_bottom; - u32 crop_left; - u32 crop_right; - u32 src_w; - u32 src_h; - u32 scale_enable; - - u32 nr_mode; - u32 flush_flag; - u32 timeout; - enum amvenc_mem_type_e type; - enum amvenc_frame_fmt_e fmt; - struct encode_wq_s *parent; -}; - -struct encode_queue_item_s { - struct list_head list; - struct encode_request_s request; -}; - -struct Buff_s { - u32 buf_start; - u32 buf_size; - bool used; -}; - -struct BuffInfo_s { - u32 lev_id; - u32 min_buffsize; - u32 max_width; - u32 max_height; - struct Buff_s dct; - struct Buff_s dec0_y; - struct Buff_s dec0_uv; - struct Buff_s dec1_y; - struct Buff_s dec1_uv; - struct Buff_s assit; - struct Buff_s bitstream; - struct Buff_s scale_buff; - struct Buff_s dump_info; - struct Buff_s cbr_info; -}; - -struct encode_meminfo_s { - u32 buf_start; - u32 buf_size; - - u32 BitstreamStart; - u32 BitstreamEnd; - - /*input buffer define*/ - u32 dct_buff_start_addr; - u32 dct_buff_end_addr; - - /*microcode assitant buffer*/ - u32 assit_buffer_offset; - - u32 scaler_buff_start_addr; - - u32 dump_info_ddr_start_addr; - u32 dump_info_ddr_size; - - u32 cbr_info_ddr_start_addr; - u32 cbr_info_ddr_size; - - u8 * cbr_info_ddr_virt_addr; - - s32 dblk_buf_canvas; - s32 ref_buf_canvas; - struct BuffInfo_s bufspec; -#ifdef CONFIG_CMA - struct page *venc_pages; -#endif -}; - -struct encode_picinfo_s { - u32 encoder_width; - u32 encoder_height; - - u32 rows_per_slice; - - u32 idr_pic_id; /* need reset as 0 for IDR */ - u32 frame_number; /* need plus each frame */ - /* need reset as 0 for IDR and plus 2 for NON-IDR */ - u32 pic_order_cnt_lsb; - - u32 log2_max_pic_order_cnt_lsb; - u32 log2_max_frame_num; - u32 init_qppicture; -}; - -struct encode_cbr_s { - u16 block_w; - u16 block_h; - u16 long_th; - u8 start_tbl_id; - u8 short_shift; - u8 long_mb_num; -}; - -struct encode_wq_s { - struct list_head list; - - /* dev info */ - u32 ucode_index; - u32 hw_status; - u32 output_size; - - u32 sps_size; - u32 pps_size; - - u32 me_weight; - u32 i4_weight; - u32 i16_weight; - - u32 quant_tbl_i4[8]; - u32 quant_tbl_i16[8]; - u32 quant_tbl_me[8]; - - struct encode_meminfo_s mem; - struct encode_picinfo_s pic; - struct encode_request_s request; - struct encode_cbr_s cbr_info; - atomic_t request_ready; - wait_queue_head_t request_complete; -}; - -struct encode_event_s { - wait_queue_head_t hw_complete; - struct completion process_complete; - spinlock_t sem_lock; /* for queue switch and create destroy queue. */ - struct completion request_in_com; -}; - -struct encode_manager_s { - struct list_head wq; - struct list_head process_queue; - struct list_head free_queue; - - u32 encode_hw_status; - u32 process_queue_state; - s32 irq_num; - u32 wq_count; - u32 ucode_index; - u32 max_instance; -#ifdef CONFIG_AMLOGIC_MEDIA_GE2D - struct ge2d_context_s *context; -#endif - bool irq_requested; - bool need_reset; - bool process_irq; - bool inited; /* power on encode */ - bool remove_flag; /* remove wq; */ - bool uninit_flag; /* power off encode */ - bool use_reserve; - -#ifdef CONFIG_CMA - bool check_cma; - ulong cma_pool_size; -#endif - struct platform_device *this_pdev; - struct Buff_s *reserve_buff; - struct encode_wq_s *current_wq; - struct encode_wq_s *last_wq; - struct encode_queue_item_s *current_item; - struct task_struct *encode_thread; - struct Buff_s reserve_mem; - struct encode_event_s event; - struct tasklet_struct encode_tasklet; -}; - -extern s32 encode_wq_add_request(struct encode_wq_s *wq); -extern struct encode_wq_s *create_encode_work_queue(void); -extern s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue); - -/******************************************** - * AV Scratch Register Re-Define - ****************************************** * - */ -#define ENCODER_STATUS HCODEC_HENC_SCRATCH_0 -#define MEM_OFFSET_REG HCODEC_HENC_SCRATCH_1 -#define DEBUG_REG HCODEC_HENC_SCRATCH_2 -#define IDR_PIC_ID HCODEC_HENC_SCRATCH_5 -#define FRAME_NUMBER HCODEC_HENC_SCRATCH_6 -#define PIC_ORDER_CNT_LSB HCODEC_HENC_SCRATCH_7 -#define LOG2_MAX_PIC_ORDER_CNT_LSB HCODEC_HENC_SCRATCH_8 -#define LOG2_MAX_FRAME_NUM HCODEC_HENC_SCRATCH_9 -#define ANC0_BUFFER_ID HCODEC_HENC_SCRATCH_A -#define QPPICTURE HCODEC_HENC_SCRATCH_B - -#define IE_ME_MB_TYPE HCODEC_HENC_SCRATCH_D - -/* bit 0-4, IE_PIPPELINE_BLOCK - * bit 5 me half pixel in m8 - * disable i4x4 in gxbb - * bit 6 me step2 sub pixel in m8 - * disable i16x16 in gxbb - */ -#define IE_ME_MODE HCODEC_HENC_SCRATCH_E -#define IE_REF_SEL HCODEC_HENC_SCRATCH_F - -/* [31:0] NUM_ROWS_PER_SLICE_P */ -/* [15:0] NUM_ROWS_PER_SLICE_I */ -#define FIXED_SLICE_CFG HCODEC_HENC_SCRATCH_L - -/* For GX */ -#define INFO_DUMP_START_ADDR HCODEC_HENC_SCRATCH_I - -/* For CBR */ -#define H264_ENC_CBR_TABLE_ADDR HCODEC_HENC_SCRATCH_3 -#define H264_ENC_CBR_MB_SIZE_ADDR HCODEC_HENC_SCRATCH_4 -/* Bytes(Float) * 256 */ -#define H264_ENC_CBR_CTL HCODEC_HENC_SCRATCH_G -/* [31:28] : init qp table idx */ -/* [27:24] : short_term adjust shift */ -/* [23:16] : Long_term MB_Number between adjust, */ -/* [15:0] Long_term adjust threshold(Bytes) */ -#define H264_ENC_CBR_TARGET_SIZE HCODEC_HENC_SCRATCH_H -/* Bytes(Float) * 256 */ -#define H264_ENC_CBR_PREV_BYTES HCODEC_HENC_SCRATCH_J -#define H264_ENC_CBR_REGION_SIZE HCODEC_HENC_SCRATCH_J - -/* --------------------------------------------------- */ -/* ENCODER_STATUS define */ -/* --------------------------------------------------- */ -#define ENCODER_IDLE 0 -#define ENCODER_SEQUENCE 1 -#define ENCODER_PICTURE 2 -#define ENCODER_IDR 3 -#define ENCODER_NON_IDR 4 -#define ENCODER_MB_HEADER 5 -#define ENCODER_MB_DATA 6 - -#define ENCODER_SEQUENCE_DONE 7 -#define ENCODER_PICTURE_DONE 8 -#define ENCODER_IDR_DONE 9 -#define ENCODER_NON_IDR_DONE 10 -#define ENCODER_MB_HEADER_DONE 11 -#define ENCODER_MB_DATA_DONE 12 - -#define ENCODER_NON_IDR_INTRA 13 -#define ENCODER_NON_IDR_INTER 14 - -#define ENCODER_ERROR 0xff - -/******************************************** - * defines for H.264 mb_type - ******************************************* - */ -#define HENC_MB_Type_PBSKIP 0x0 -#define HENC_MB_Type_PSKIP 0x0 -#define HENC_MB_Type_BSKIP_DIRECT 0x0 -#define HENC_MB_Type_P16x16 0x1 -#define HENC_MB_Type_P16x8 0x2 -#define HENC_MB_Type_P8x16 0x3 -#define HENC_MB_Type_SMB8x8 0x4 -#define HENC_MB_Type_SMB8x4 0x5 -#define HENC_MB_Type_SMB4x8 0x6 -#define HENC_MB_Type_SMB4x4 0x7 -#define HENC_MB_Type_P8x8 0x8 -#define HENC_MB_Type_I4MB 0x9 -#define HENC_MB_Type_I16MB 0xa -#define HENC_MB_Type_IBLOCK 0xb -#define HENC_MB_Type_SI4MB 0xc -#define HENC_MB_Type_I8MB 0xd -#define HENC_MB_Type_IPCM 0xe -#define HENC_MB_Type_AUTO 0xf - -#define HENC_MB_CBP_AUTO 0xff -#define HENC_SKIP_RUN_AUTO 0xffff - - -extern bool amvenc_avc_on(void); -#endif diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile b/drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile deleted file mode 100644 index e7414bfb8614..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += vpu.o diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h deleted file mode 100644 index a32dd06eb7ab..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h +++ /dev/null @@ -1,665 +0,0 @@ -/* - * vmm.h - * - * memory allocator for VPU - * - * Copyright (C) 2006 - 2013 CHIPS&MEDIA INC. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef __CNM_VIDEO_MEMORY_MANAGEMENT_H__ -#define __CNM_VIDEO_MEMORY_MANAGEMENT_H__ - -#define VMEM_PAGE_SIZE (16 * 1024) -#define MAKE_KEY(_a, _b) (((vmem_key_t)_a) << 32 | _b) -#define KEY_TO_VALUE(_key) (_key >> 32) - -#define VMEM_P_ALLOC(_x) vmalloc(_x) -#define VMEM_P_FREE(_x) vfree(_x) - -#define VMEM_ASSERT \ - pr_info("VMEM_ASSERT at %s:%d\n", __FILE__, __LINE__) - - -#define VMEM_HEIGHT(_tree) (_tree == NULL ? -1 : _tree->height) - -#define MAX(_a, _b) (_a >= _b ? _a : _b) - -struct avl_node_t; -#define vmem_key_t unsigned long long - -struct vmem_info_t { - ulong total_pages; - ulong alloc_pages; - ulong free_pages; - ulong page_size; -}; - -struct page_t { - s32 pageno; - ulong addr; - s32 used; - s32 alloc_pages; - s32 first_pageno; -}; - -struct avl_node_t { - vmem_key_t key; - s32 height; - struct page_t *page; - struct avl_node_t *left; - struct avl_node_t *right; -}; - -struct video_mm_t { - struct avl_node_t *free_tree; - struct avl_node_t *alloc_tree; - struct page_t *page_list; - s32 num_pages; - ulong base_addr; - ulong mem_size; - s32 free_page_count; - s32 alloc_page_count; -}; - -enum rotation_dir_t { - LEFT, - RIGHT -}; - -struct avl_node_data_t { - s32 key; - struct page_t *page; -}; - -static struct avl_node_t *make_avl_node( - vmem_key_t key, - struct page_t *page) -{ - struct avl_node_t *node = - (struct avl_node_t *)VMEM_P_ALLOC(sizeof(struct avl_node_t)); - node->key = key; - node->page = page; - node->height = 0; - node->left = NULL; - node->right = NULL; - return node; -} - -static s32 get_balance_factor(struct avl_node_t *tree) -{ - s32 factor = 0; - - if (tree) - factor = VMEM_HEIGHT(tree->right) - VMEM_HEIGHT(tree->left); - return factor; -} - -/* - * Left Rotation - * - * A B - * \ / \ - * B => A C - * / \ \ - * D C D - * - */ -static struct avl_node_t *rotation_left(struct avl_node_t *tree) -{ - struct avl_node_t *rchild; - struct avl_node_t *lchild; - - if (tree == NULL) - return NULL; - - rchild = tree->right; - if (rchild == NULL) - return tree; - - lchild = rchild->left; - rchild->left = tree; - tree->right = lchild; - - tree->height = - MAX(VMEM_HEIGHT(tree->left), VMEM_HEIGHT(tree->right)) + 1; - rchild->height = - MAX(VMEM_HEIGHT(rchild->left), VMEM_HEIGHT(rchild->right)) + 1; - return rchild; -} - - -/* - * Reft Rotation - * - * A B - * \ / \ - * B => D A - * / \ / - * D C C - * - */ -static struct avl_node_t *rotation_right(struct avl_node_t *tree) -{ - struct avl_node_t *rchild; - struct avl_node_t *lchild; - - if (tree == NULL) - return NULL; - - lchild = tree->left; - if (lchild == NULL) - return NULL; - - rchild = lchild->right; - lchild->right = tree; - tree->left = rchild; - - tree->height = - MAX(VMEM_HEIGHT(tree->left), - VMEM_HEIGHT(tree->right)) + 1; - lchild->height = - MAX(VMEM_HEIGHT(lchild->left), - VMEM_HEIGHT(lchild->right)) + 1; - return lchild; -} - -static struct avl_node_t *do_balance(struct avl_node_t *tree) -{ - s32 bfactor = 0, child_bfactor; - - bfactor = get_balance_factor(tree); - if (bfactor >= 2) { - child_bfactor = get_balance_factor(tree->right); - if (child_bfactor == 1 || child_bfactor == 0) { - tree = rotation_left(tree); - } else if (child_bfactor == -1) { - tree->right = rotation_right(tree->right); - tree = rotation_left(tree); - } else { - pr_info( - "invalid balancing factor: %d\n", - child_bfactor); - VMEM_ASSERT; - return NULL; - } - } else if (bfactor <= -2) { - child_bfactor = get_balance_factor(tree->left); - if (child_bfactor == -1 || child_bfactor == 0) { - tree = rotation_right(tree); - } else if (child_bfactor == 1) { - tree->left = rotation_left(tree->left); - tree = rotation_right(tree); - } else { - pr_info( - "invalid balancing factor: %d\n", - child_bfactor); - VMEM_ASSERT; - return NULL; - } - } - return tree; -} - -static struct avl_node_t *unlink_end_node( - struct avl_node_t *tree, - s32 dir, - struct avl_node_t **found_node) -{ - struct avl_node_t *node; - *found_node = NULL; - - if (tree == NULL) - return NULL; - - if (dir == LEFT) { - if (tree->left == NULL) { - *found_node = tree; - return NULL; - } - } else { - if (tree->right == NULL) { - *found_node = tree; - return NULL; - } - } - - if (dir == LEFT) { - node = tree->left; - tree->left = unlink_end_node(tree->left, LEFT, found_node); - if (tree->left == NULL) { - tree->left = (*found_node)->right; - (*found_node)->left = NULL; - (*found_node)->right = NULL; - } - } else { - node = tree->right; - tree->right = unlink_end_node(tree->right, RIGHT, found_node); - if (tree->right == NULL) { - tree->right = (*found_node)->left; - (*found_node)->left = NULL; - (*found_node)->right = NULL; - } - } - tree->height = - MAX(VMEM_HEIGHT(tree->left), VMEM_HEIGHT(tree->right)) + 1; - return do_balance(tree); -} - - -static struct avl_node_t *avltree_insert( - struct avl_node_t *tree, - vmem_key_t key, - struct page_t *page) -{ - if (tree == NULL) { - tree = make_avl_node(key, page); - } else { - if (key >= tree->key) - tree->right = - avltree_insert(tree->right, key, page); - else - tree->left = - avltree_insert(tree->left, key, page); - } - tree = do_balance(tree); - tree->height = - MAX(VMEM_HEIGHT(tree->left), VMEM_HEIGHT(tree->right)) + 1; - return tree; -} - -static struct avl_node_t *do_unlink(struct avl_node_t *tree) -{ - struct avl_node_t *node; - struct avl_node_t *end_node; - - node = unlink_end_node(tree->right, LEFT, &end_node); - if (node) { - tree->right = node; - } else { - node = - unlink_end_node(tree->left, RIGHT, &end_node); - if (node) - tree->left = node; - } - - if (node == NULL) { - node = tree->right ? tree->right : tree->left; - end_node = node; - } - - if (end_node) { - end_node->left = - (tree->left != end_node) ? - tree->left : end_node->left; - end_node->right = - (tree->right != end_node) ? - tree->right : end_node->right; - end_node->height = - MAX(VMEM_HEIGHT(end_node->left), - VMEM_HEIGHT(end_node->right)) + 1; - } - tree = end_node; - return tree; -} - -static struct avl_node_t *avltree_remove( - struct avl_node_t *tree, - struct avl_node_t **found_node, - vmem_key_t key) -{ - *found_node = NULL; - if (tree == NULL) { - pr_info("failed to find key %d\n", (s32)key); - return NULL; - } - - if (key == tree->key) { - *found_node = tree; - tree = do_unlink(tree); - } else if (key > tree->key) { - tree->right = - avltree_remove(tree->right, found_node, key); - } else { - tree->left = - avltree_remove(tree->left, found_node, key); - } - - if (tree) - tree->height = - MAX(VMEM_HEIGHT(tree->left), - VMEM_HEIGHT(tree->right)) + 1; - - tree = do_balance(tree); - return tree; -} - -void avltree_free(struct avl_node_t *tree) -{ - if (tree == NULL) - return; - if (tree->left == NULL && tree->right == NULL) { - VMEM_P_FREE(tree); - return; - } - - avltree_free(tree->left); - tree->left = NULL; - avltree_free(tree->right); - tree->right = NULL; - VMEM_P_FREE(tree); -} - -static struct avl_node_t *remove_approx_value( - struct avl_node_t *tree, - struct avl_node_t **found, - vmem_key_t key) -{ - *found = NULL; - if (tree == NULL) - return NULL; - - if (key == tree->key) { - *found = tree; - tree = do_unlink(tree); - } else if (key > tree->key) { - tree->right = remove_approx_value(tree->right, found, key); - } else { - tree->left = remove_approx_value(tree->left, found, key); - if (*found == NULL) { - *found = tree; - tree = do_unlink(tree); - } - } - if (tree) - tree->height = - MAX(VMEM_HEIGHT(tree->left), - VMEM_HEIGHT(tree->right)) + 1; - tree = do_balance(tree); - return tree; -} - -static void set_blocks_free( - struct video_mm_t *mm, - s32 pageno, - s32 npages) -{ - s32 last_pageno = pageno + npages - 1; - s32 i; - struct page_t *page; - struct page_t *last_page; - - if (npages == 0) - VMEM_ASSERT; - - if (last_pageno >= mm->num_pages) { - pr_info( - "set_blocks_free: invalid last page number: %d\n", - last_pageno); - VMEM_ASSERT; - return; - } - - for (i = pageno; i <= last_pageno; i++) { - mm->page_list[i].used = 0; - mm->page_list[i].alloc_pages = 0; - mm->page_list[i].first_pageno = -1; - } - - page = &mm->page_list[pageno]; - page->alloc_pages = npages; - last_page = &mm->page_list[last_pageno]; - last_page->first_pageno = pageno; - mm->free_tree = - avltree_insert(mm->free_tree, MAKE_KEY(npages, pageno), page); -} - -static void set_blocks_alloc( - struct video_mm_t *mm, - s32 pageno, - s32 npages) -{ - s32 last_pageno = pageno + npages - 1; - s32 i; - struct page_t *page; - struct page_t *last_page; - - if (last_pageno >= mm->num_pages) { - pr_info( - "set_blocks_free: invalid last page number: %d\n", - last_pageno); - VMEM_ASSERT; - return; - } - - for (i = pageno; i <= last_pageno; i++) { - mm->page_list[i].used = 1; - mm->page_list[i].alloc_pages = 0; - mm->page_list[i].first_pageno = -1; - } - - page = &mm->page_list[pageno]; - page->alloc_pages = npages; - last_page = &mm->page_list[last_pageno]; - last_page->first_pageno = pageno; - mm->alloc_tree = - avltree_insert(mm->alloc_tree, MAKE_KEY(page->addr, 0), page); -} - - -s32 vmem_init(struct video_mm_t *mm, ulong addr, ulong size) -{ - s32 i; - - if (mm == NULL) - return -1; - - mm->base_addr = (addr + (VMEM_PAGE_SIZE - 1)) - & ~(VMEM_PAGE_SIZE - 1); - mm->mem_size = size & ~VMEM_PAGE_SIZE; - mm->num_pages = mm->mem_size / VMEM_PAGE_SIZE; - mm->free_tree = NULL; - mm->alloc_tree = NULL; - mm->free_page_count = mm->num_pages; - mm->alloc_page_count = 0; - mm->page_list = - (struct page_t *)VMEM_P_ALLOC( - mm->num_pages * sizeof(struct page_t)); - if (mm->page_list == NULL) { - pr_err("%s:%d failed to kmalloc(%zu)\n", - __func__, __LINE__, - mm->num_pages * sizeof(struct page_t)); - return -1; - } - - for (i = 0; i < mm->num_pages; i++) { - mm->page_list[i].pageno = i; - mm->page_list[i].addr = - mm->base_addr + i * VMEM_PAGE_SIZE; - mm->page_list[i].alloc_pages = 0; - mm->page_list[i].used = 0; - mm->page_list[i].first_pageno = -1; - } - set_blocks_free(mm, 0, mm->num_pages); - return 0; -} - -s32 vmem_exit(struct video_mm_t *mm) -{ - if (mm == NULL) { - pr_info("vmem_exit: invalid handle\n"); - return -1; - } - - if (mm->free_tree) - avltree_free(mm->free_tree); - if (mm->alloc_tree) - avltree_free(mm->alloc_tree); - - if (mm->page_list) { - VMEM_P_FREE(mm->page_list); - mm->page_list = NULL; - } - - mm->base_addr = 0; - mm->mem_size = 0; - mm->num_pages = 0; - mm->page_list = NULL; - mm->free_tree = NULL; - mm->alloc_tree = NULL; - mm->free_page_count = 0; - mm->alloc_page_count = 0; - return 0; -} - -ulong vmem_alloc(struct video_mm_t *mm, s32 size, ulong pid) -{ - struct avl_node_t *node; - struct page_t *free_page; - s32 npages, free_size; - s32 alloc_pageno; - ulong ptr; - - if (mm == NULL) { - pr_info("vmem_alloc: invalid handle\n"); - return -1; - } - - if (size <= 0) - return -1; - - npages = (size + VMEM_PAGE_SIZE - 1) / VMEM_PAGE_SIZE; - mm->free_tree = remove_approx_value(mm->free_tree, - &node, MAKE_KEY(npages, 0)); - - if (node == NULL) - return -1; - - free_page = node->page; - free_size = KEY_TO_VALUE(node->key); - alloc_pageno = free_page->pageno; - set_blocks_alloc(mm, alloc_pageno, npages); - if (npages != free_size) { - s32 free_pageno = alloc_pageno + npages; - - set_blocks_free(mm, free_pageno, (free_size-npages)); - } - VMEM_P_FREE(node); - - ptr = mm->page_list[alloc_pageno].addr; - mm->alloc_page_count += npages; - mm->free_page_count -= npages; - return ptr; -} - -s32 vmem_free(struct video_mm_t *mm, ulong ptr, ulong pid) -{ - ulong addr; - struct avl_node_t *found; - struct page_t *page; - s32 pageno, prev_free_pageno, next_free_pageno; - s32 prev_size, next_size; - s32 merge_page_no, merge_page_size, free_page_size; - - if (mm == NULL) { - pr_info("vmem_free: invalid handle\n"); - return -1; - } - - addr = ptr; - mm->alloc_tree = avltree_remove(mm->alloc_tree, &found, - MAKE_KEY(addr, 0)); - - if (found == NULL) { - pr_info("vmem_free: 0x%08x not found\n", (s32)addr); - VMEM_ASSERT; - return -1; - } - - /* find previous free block */ - page = found->page; - pageno = page->pageno; - free_page_size = page->alloc_pages; - prev_free_pageno = pageno - 1; - prev_size = -1; - if (prev_free_pageno >= 0) { - if (mm->page_list[prev_free_pageno].used == 0) { - prev_free_pageno = - mm->page_list[prev_free_pageno].first_pageno; - prev_size = - mm->page_list[prev_free_pageno].alloc_pages; - } - } - - /* find next free block */ - next_free_pageno = pageno + page->alloc_pages; - next_free_pageno = - (next_free_pageno == mm->num_pages) ? -1 : next_free_pageno; - next_size = -1; - if (next_free_pageno >= 0) { - if (mm->page_list[next_free_pageno].used == 0) { - next_size = - mm->page_list[next_free_pageno].alloc_pages; - } - } - VMEM_P_FREE(found); - - /* merge */ - merge_page_no = page->pageno; - merge_page_size = page->alloc_pages; - if (prev_size >= 0) { - mm->free_tree = avltree_remove(mm->free_tree, &found, - MAKE_KEY(prev_size, prev_free_pageno)); - if (found == NULL) { - VMEM_ASSERT; - return -1; - } - merge_page_no = found->page->pageno; - merge_page_size += found->page->alloc_pages; - VMEM_P_FREE(found); - } - if (next_size >= 0) { - mm->free_tree = avltree_remove(mm->free_tree, &found, - MAKE_KEY(next_size, next_free_pageno)); - if (found == NULL) { - VMEM_ASSERT; - return -1; - } - merge_page_size += found->page->alloc_pages; - VMEM_P_FREE(found); - } - page->alloc_pages = 0; - page->first_pageno = -1; - set_blocks_free(mm, merge_page_no, merge_page_size); - mm->alloc_page_count -= free_page_size; - mm->free_page_count += free_page_size; - return 0; -} - -s32 vmem_get_info(struct video_mm_t *mm, struct vmem_info_t *info) -{ - if (mm == NULL) { - pr_info("vmem_get_info: invalid handle\n"); - return -1; - } - - if (info == NULL) - return -1; - - info->total_pages = mm->num_pages; - info->alloc_pages = mm->alloc_page_count; - info->free_pages = mm->free_page_count; - info->page_size = VMEM_PAGE_SIZE; - return 0; -} -#endif /* __CNM_VIDEO_MEMORY_MANAGEMENT_H__ */ diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c deleted file mode 100644 index 3180b4968a9e..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c +++ /dev/null @@ -1,2049 +0,0 @@ -/* - * vpu.c - * - * linux device driver for VPU. - * - * Copyright (C) 2006 - 2013 CHIPS&MEDIA INC. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../../../common/media_clock/switch/amports_gate.h" - -#include "vpu.h" -#include "vmm.h" - -/* definitions to be changed as customer configuration */ -/* if you want to have clock gating scheme frame by frame */ -/* #define VPU_SUPPORT_CLOCK_CONTROL */ - -#define VPU_PLATFORM_DEVICE_NAME "HevcEnc" -#define VPU_DEV_NAME "HevcEnc" -#define VPU_CLASS_NAME "HevcEnc" - -#ifndef VM_RESERVED /*for kernel up to 3.7.0 version*/ -#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) -#endif - -#define VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE (64 * SZ_1M) - -#define LOG_ALL 0 -#define LOG_INFO 1 -#define LOG_DEBUG 2 -#define LOG_ERROR 3 - -#define enc_pr(level, x...) \ - do { \ - if (level >= print_level) \ - printk(x); \ - } while (0) - -static s32 print_level = LOG_DEBUG; -static s32 clock_level = 4; - -static struct video_mm_t s_vmem; -static struct vpudrv_buffer_t s_video_memory = {0}; -static bool use_reserve; -static ulong cma_pool_size; - -/* end customer definition */ -static struct vpudrv_buffer_t s_instance_pool = {0}; -static struct vpudrv_buffer_t s_common_memory = {0}; -static struct vpu_drv_context_t s_vpu_drv_context; -static s32 s_vpu_major; -static struct device *hevcenc_dev; - -static s32 s_vpu_open_ref_count; -static s32 s_vpu_irq; -static bool s_vpu_irq_requested; - -static struct vpudrv_buffer_t s_vpu_register = {0}; - -static s32 s_interrupt_flag; -static wait_queue_head_t s_interrupt_wait_q; - -static spinlock_t s_vpu_lock = __SPIN_LOCK_UNLOCKED(s_vpu_lock); -static DEFINE_SEMAPHORE(s_vpu_sem); -static struct list_head s_vbp_head = LIST_HEAD_INIT(s_vbp_head); -static struct list_head s_inst_list_head = LIST_HEAD_INIT(s_inst_list_head); -static struct tasklet_struct hevc_tasklet; -static struct platform_device *hevc_pdev; - -static struct vpu_bit_firmware_info_t s_bit_firmware_info[MAX_NUM_VPU_CORE]; - -static void dma_flush(u32 buf_start, u32 buf_size) -{ - if (hevc_pdev) - dma_sync_single_for_device( - &hevc_pdev->dev, buf_start, - buf_size, DMA_TO_DEVICE); -} - -static void cache_flush(u32 buf_start, u32 buf_size) -{ - if (hevc_pdev) - dma_sync_single_for_cpu( - &hevc_pdev->dev, buf_start, - buf_size, DMA_FROM_DEVICE); -} - -s32 vpu_hw_reset(void) -{ - enc_pr(LOG_DEBUG, "request vpu reset from application.\n"); - return 0; -} - -s32 vpu_clk_config(u32 enable) -{ - if (enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - HevcEnc_MoreClock_enable(); - HevcEnc_clock_enable(clock_level); - } else { - HevcEnc_clock_disable(); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - HevcEnc_MoreClock_disable(); - } - return 0; -} - -static s32 vpu_alloc_dma_buffer(struct vpudrv_buffer_t *vb) -{ - if (!vb) - return -1; - - vb->phys_addr = (ulong)vmem_alloc(&s_vmem, vb->size, 0); - if ((ulong)vb->phys_addr == (ulong)-1) { - enc_pr(LOG_ERROR, - "Physical memory allocation error size=%d\n", vb->size); - return -1; - } - - enc_pr(LOG_INFO, "vpu_alloc_dma_buffer: vb->phys_addr 0x%lx \n",vb->phys_addr); - return 0; -} - -static void vpu_free_dma_buffer(struct vpudrv_buffer_t *vb) -{ - if (!vb) - return; - enc_pr(LOG_INFO, "vpu_free_dma_buffer 0x%lx\n",vb->phys_addr); - - if (vb->phys_addr) - vmem_free(&s_vmem, vb->phys_addr, 0); -} - -static s32 vpu_free_instances(struct file *filp) -{ - struct vpudrv_instanace_list_t *vil, *n; - struct vpudrv_instance_pool_t *vip; - void *vip_base; - - enc_pr(LOG_DEBUG, "vpu_free_instances\n"); - - list_for_each_entry_safe(vil, n, &s_inst_list_head, list) { - if (vil->filp == filp) { - vip_base = (void *)s_instance_pool.base; - enc_pr(LOG_INFO, - "free_instances instIdx=%d, coreIdx=%d, vip_base=%p\n", - (s32)vil->inst_idx, - (s32)vil->core_idx, - vip_base); - vip = (struct vpudrv_instance_pool_t *)vip_base; - if (vip) { - /* only first 4 byte is key point - * (inUse of CodecInst in vpuapi) - * to free the corresponding instance. - */ - memset(&vip->codecInstPool[vil->inst_idx], - 0x00, 4); - } - s_vpu_open_ref_count--; - list_del(&vil->list); - kfree(vil); - } - } - return 1; -} - -static s32 vpu_free_buffers(struct file *filp) -{ - struct vpudrv_buffer_pool_t *pool, *n; - struct vpudrv_buffer_t vb; - - enc_pr(LOG_DEBUG, "vpu_free_buffers\n"); - - list_for_each_entry_safe(pool, n, &s_vbp_head, list) { - if (pool->filp == filp) { - vb = pool->vb; - if (vb.phys_addr) { - vpu_free_dma_buffer(&vb); - list_del(&pool->list); - kfree(pool); - } - } - } - return 0; -} - -static u32 vpu_is_buffer_cached(struct file *filp, ulong vm_pgoff) -{ - struct vpudrv_buffer_pool_t *pool, *n; - struct vpudrv_buffer_t vb; - bool find = false; - u32 cached = 0; - - enc_pr(LOG_ALL, "[+]vpu_is_buffer_cached\n"); - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(pool, n, &s_vbp_head, list) { - if (pool->filp == filp) { - vb = pool->vb; - if (((vb.phys_addr >> PAGE_SHIFT) == vm_pgoff) - && find == false){ - cached = vb.cached; - find = true; - } - } - } - spin_unlock(&s_vpu_lock); - enc_pr(LOG_ALL, "[-]vpu_is_buffer_cached, ret:%d\n", cached); - return cached; -} - -static void hevcenc_isr_tasklet(ulong data) -{ - struct vpu_drv_context_t *dev = (struct vpu_drv_context_t *)data; - - enc_pr(LOG_INFO, "hevcenc_isr_tasklet interruput:0x%08lx\n", - dev->interrupt_reason); - if (dev->interrupt_reason) { - /* notify the interrupt to user space */ - if (dev->async_queue) { - enc_pr(LOG_ALL, "kill_fasync e %s\n", __func__); - kill_fasync(&dev->async_queue, SIGIO, POLL_IN); - } - s_interrupt_flag = 1; - wake_up_interruptible(&s_interrupt_wait_q); - } - enc_pr(LOG_ALL, "[-]%s\n", __func__); -} - -static irqreturn_t vpu_irq_handler(s32 irq, void *dev_id) -{ - struct vpu_drv_context_t *dev = (struct vpu_drv_context_t *)dev_id; - /* this can be removed. - * it also work in VPU_WaitInterrupt of API function - */ - u32 core; - ulong interrupt_reason = 0; - - enc_pr(LOG_ALL, "[+]%s\n", __func__); - - for (core = 0; core < MAX_NUM_VPU_CORE; core++) { - if (s_bit_firmware_info[core].size == 0) { - /* it means that we didn't get an information - * the current core from API layer. - * No core activated. - */ - enc_pr(LOG_ERROR, - "s_bit_firmware_info[core].size is zero\n"); - continue; - } - if (ReadVpuRegister(W4_VPU_VPU_INT_STS)) { - interrupt_reason = ReadVpuRegister(W4_VPU_INT_REASON); - WriteVpuRegister(W4_VPU_INT_REASON_CLEAR, - interrupt_reason); - WriteVpuRegister(W4_VPU_VINT_CLEAR, 0x1); - dev->interrupt_reason |= interrupt_reason; - } - enc_pr(LOG_INFO, - "intr_reason: 0x%08lx\n", dev->interrupt_reason); - } - if (dev->interrupt_reason) - tasklet_schedule(&hevc_tasklet); - enc_pr(LOG_ALL, "[-]%s\n", __func__); - return IRQ_HANDLED; -} - -static s32 vpu_open(struct inode *inode, struct file *filp) -{ - bool alloc_buffer = false; - s32 r = 0; - - enc_pr(LOG_DEBUG, "[+] %s\n", __func__); - spin_lock(&s_vpu_lock); - s_vpu_drv_context.open_count++; - if (s_vpu_drv_context.open_count == 1) { - alloc_buffer = true; - } else { - r = -EBUSY; - s_vpu_drv_context.open_count--; - spin_unlock(&s_vpu_lock); - goto Err; - } - filp->private_data = (void *)(&s_vpu_drv_context); - spin_unlock(&s_vpu_lock); - if (alloc_buffer && !use_reserve) { -#ifdef CONFIG_CMA - s_video_memory.size = VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE; - s_video_memory.phys_addr = - (ulong)codec_mm_alloc_for_dma(VPU_DEV_NAME, - VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE >> PAGE_SHIFT, 0, 0); - if (s_video_memory.phys_addr) { - enc_pr(LOG_DEBUG, - "allocating phys 0x%lx, virt addr 0x%lx, size %dk\n", - s_video_memory.phys_addr, - s_video_memory.base, - s_video_memory.size >> 10); - if (vmem_init(&s_vmem, - s_video_memory.phys_addr, - s_video_memory.size) < 0) { - enc_pr(LOG_ERROR, "fail to init vmem system\n"); - r = -ENOMEM; - codec_mm_free_for_dma( - VPU_DEV_NAME, - (u32)s_video_memory.phys_addr); - vmem_exit(&s_vmem); - memset(&s_video_memory, 0, - sizeof(struct vpudrv_buffer_t)); - memset(&s_vmem, 0, - sizeof(struct video_mm_t)); - } - } else { - enc_pr(LOG_ERROR, - "CMA failed to allocate dma buffer for %s, phys: 0x%lx\n", - VPU_DEV_NAME, s_video_memory.phys_addr); - if (s_video_memory.phys_addr) - codec_mm_free_for_dma( - VPU_DEV_NAME, - (u32)s_video_memory.phys_addr); - s_video_memory.phys_addr = 0; - r = -ENOMEM; - } -#else - enc_pr(LOG_ERROR, - "No CMA and reserved memory for HevcEnc!!!\n"); - r = -ENOMEM; -#endif - } else if (!s_video_memory.phys_addr) { - enc_pr(LOG_ERROR, - "HevcEnc memory is not malloced!!!\n"); - r = -ENOMEM; - } - if (alloc_buffer) { - ulong flags; - u32 data32; - - if ((s_vpu_irq >= 0) && (s_vpu_irq_requested == false)) { - s32 err; - - err = request_irq(s_vpu_irq, vpu_irq_handler, 0, - "HevcEnc-irq", (void *)(&s_vpu_drv_context)); - if (err) { - enc_pr(LOG_ERROR, - "fail to register interrupt handler\n"); - s_vpu_drv_context.open_count--; - return -EFAULT; - } - s_vpu_irq_requested = true; - } - amports_switch_gate("vdec", 1); - spin_lock_irqsave(&s_vpu_lock, flags); - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 - ? ~0x8 : ~(0x3<<24))); - udelay(10); - - if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXLX) { - data32 = 0x700; - data32 |= READ_VREG(DOS_SW_RESET4); - WRITE_VREG(DOS_SW_RESET4, data32); - data32 &= ~0x700; - WRITE_VREG(DOS_SW_RESET4, data32); - } else { - data32 = 0xf00; - data32 |= READ_VREG(DOS_SW_RESET4); - WRITE_VREG(DOS_SW_RESET4, data32); - data32 &= ~0xf00; - WRITE_VREG(DOS_SW_RESET4, data32); - } - - WRITE_MPEG_REG(RESET0_REGISTER, data32 & ~(1<<21)); - WRITE_MPEG_REG(RESET0_REGISTER, data32 | (1<<21)); - READ_MPEG_REG(RESET0_REGISTER); - READ_MPEG_REG(RESET0_REGISTER); - READ_MPEG_REG(RESET0_REGISTER); - READ_MPEG_REG(RESET0_REGISTER); -#ifndef VPU_SUPPORT_CLOCK_CONTROL - vpu_clk_config(1); -#endif - /* Enable wave420l_vpu_idle_rise_irq, - * Disable wave420l_vpu_idle_fall_irq - */ - WRITE_VREG(DOS_WAVE420L_CNTL_STAT, 0x1); - WRITE_VREG(DOS_MEM_PD_WAVE420L, 0x0); - - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 - ? ~0x8 : ~(0x3<<12))); - udelay(10); - - spin_unlock_irqrestore(&s_vpu_lock, flags); - } -Err: - if (r != 0) - s_vpu_drv_context.open_count--; - enc_pr(LOG_DEBUG, "[-] %s, ret: %d\n", __func__, r); - return r; -} - -static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) -{ - s32 ret = 0; - struct vpu_drv_context_t *dev = - (struct vpu_drv_context_t *)filp->private_data; - - switch (cmd) { - case VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY: - { - struct vpudrv_buffer_pool_t *vbp; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret == 0) { - vbp = kzalloc(sizeof(*vbp), GFP_KERNEL); - if (!vbp) { - up(&s_vpu_sem); - return -ENOMEM; - } - - ret = copy_from_user(&(vbp->vb), - (struct vpudrv_buffer_t *)arg, - sizeof(struct vpudrv_buffer_t)); - if (ret) { - kfree(vbp); - up(&s_vpu_sem); - return -EFAULT; - } - - ret = vpu_alloc_dma_buffer(&(vbp->vb)); - if (ret == -1) { - ret = -ENOMEM; - kfree(vbp); - up(&s_vpu_sem); - break; - } - ret = copy_to_user((void __user *)arg, - &(vbp->vb), - sizeof(struct vpudrv_buffer_t)); - if (ret) { - kfree(vbp); - ret = -EFAULT; - up(&s_vpu_sem); - break; - } - - vbp->filp = filp; - spin_lock(&s_vpu_lock); - list_add(&vbp->list, &s_vbp_head); - spin_unlock(&s_vpu_lock); - - up(&s_vpu_sem); - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY\n"); - } - break; -#ifdef CONFIG_COMPAT - case VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32: - { - struct vpudrv_buffer_pool_t *vbp; - struct compat_vpudrv_buffer_t buf32; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret == 0) { - vbp = kzalloc(sizeof(*vbp), GFP_KERNEL); - if (!vbp) { - up(&s_vpu_sem); - return -ENOMEM; - } - - ret = copy_from_user(&buf32, - (struct compat_vpudrv_buffer_t *)arg, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret) { - kfree(vbp); - up(&s_vpu_sem); - return -EFAULT; - } - - vbp->vb.size = buf32.size; - vbp->vb.cached = buf32.cached; - vbp->vb.phys_addr = - (ulong)buf32.phys_addr; - vbp->vb.virt_addr = - (ulong)buf32.virt_addr; - ret = vpu_alloc_dma_buffer(&(vbp->vb)); - if (ret == -1) { - ret = -ENOMEM; - kfree(vbp); - up(&s_vpu_sem); - break; - } - - buf32.size = vbp->vb.size; - buf32.phys_addr = - (compat_ulong_t)vbp->vb.phys_addr; - buf32.virt_addr = - (compat_ulong_t)vbp->vb.virt_addr; - - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret) { - kfree(vbp); - ret = -EFAULT; - up(&s_vpu_sem); - break; - } - - vbp->filp = filp; - spin_lock(&s_vpu_lock); - list_add(&vbp->list, &s_vbp_head); - spin_unlock(&s_vpu_lock); - - up(&s_vpu_sem); - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32\n"); - } - break; -#endif - case VDI_IOCTL_FREE_PHYSICALMEMORY: - { - struct vpudrv_buffer_pool_t *vbp, *n; - struct vpudrv_buffer_t vb; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_FREE_PHYSICALMEMORY\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret == 0) { - ret = copy_from_user(&vb, - (struct vpudrv_buffer_t *)arg, - sizeof(struct vpudrv_buffer_t)); - if (ret) { - up(&s_vpu_sem); - return -EACCES; - } - - if (vb.phys_addr) - vpu_free_dma_buffer(&vb); - - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(vbp, n, - &s_vbp_head, list) { - if (vbp->vb.phys_addr == vb.phys_addr) { - list_del(&vbp->list); - kfree(vbp); - break; - } - } - spin_unlock(&s_vpu_lock); - - up(&s_vpu_sem); - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_FREE_PHYSICALMEMORY\n"); - } - break; -#ifdef CONFIG_COMPAT - case VDI_IOCTL_FREE_PHYSICALMEMORY32: - { - struct vpudrv_buffer_pool_t *vbp, *n; - struct compat_vpudrv_buffer_t buf32; - struct vpudrv_buffer_t vb; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_FREE_PHYSICALMEMORY32\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret == 0) { - ret = copy_from_user(&buf32, - (struct compat_vpudrv_buffer_t *)arg, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret) { - up(&s_vpu_sem); - return -EACCES; - } - - vb.size = buf32.size; - vb.phys_addr = - (ulong)buf32.phys_addr; - vb.virt_addr = - (ulong)buf32.virt_addr; - - if (vb.phys_addr) - vpu_free_dma_buffer(&vb); - - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(vbp, n, - &s_vbp_head, list) { - if ((compat_ulong_t)vbp->vb.base - == buf32.base) { - list_del(&vbp->list); - kfree(vbp); - break; - } - } - spin_unlock(&s_vpu_lock); - up(&s_vpu_sem); - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_FREE_PHYSICALMEMORY32\n"); - } - break; -#endif - case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO: - { - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); - if (s_video_memory.phys_addr != 0) { - ret = copy_to_user((void __user *)arg, - &s_video_memory, - sizeof(struct vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else { - ret = -EFAULT; - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); - } - break; -#ifdef CONFIG_COMPAT - case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32: - { - struct compat_vpudrv_buffer_t buf32; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32\n"); - - buf32.size = s_video_memory.size; - buf32.phys_addr = - (compat_ulong_t)s_video_memory.phys_addr; - buf32.virt_addr = - (compat_ulong_t)s_video_memory.virt_addr; - if (s_video_memory.phys_addr != 0) { - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else { - ret = -EFAULT; - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32\n"); - } - break; -#endif - case VDI_IOCTL_WAIT_INTERRUPT: - { - struct vpudrv_intr_info_t info; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_WAIT_INTERRUPT\n"); - ret = copy_from_user(&info, - (struct vpudrv_intr_info_t *)arg, - sizeof(struct vpudrv_intr_info_t)); - if (ret != 0) - return -EFAULT; - - ret = wait_event_interruptible_timeout( - s_interrupt_wait_q, - s_interrupt_flag != 0, - msecs_to_jiffies(info.timeout)); - if (!ret) { - ret = -ETIME; - break; - } - enc_pr(LOG_INFO, - "s_interrupt_flag(%d), reason(0x%08lx)\n", - s_interrupt_flag, dev->interrupt_reason); - if (dev->interrupt_reason & (1 << W4_INT_ENC_PIC)) { - u32 start, end, size, core = 0; - - start = ReadVpuRegister(W4_BS_RD_PTR); - end = ReadVpuRegister(W4_BS_WR_PTR); - size = ReadVpuRegister(W4_RET_ENC_PIC_BYTE); - enc_pr(LOG_INFO, "flush output buffer, "); - enc_pr(LOG_INFO, - "start:0x%x, end:0x%x, size:0x%x\n", - start, end, size); - if (end - start > size && end > start) - size = end - start; - if (size > 0) - cache_flush(start, size); - } - - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - enc_pr(LOG_INFO, - "s_interrupt_flag(%d), reason(0x%08lx)\n", - s_interrupt_flag, dev->interrupt_reason); - - info.intr_reason = dev->interrupt_reason; - s_interrupt_flag = 0; - dev->interrupt_reason = 0; - ret = copy_to_user((void __user *)arg, - &info, sizeof(struct vpudrv_intr_info_t)); - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_WAIT_INTERRUPT\n"); - if (ret != 0) - return -EFAULT; - } - break; - case VDI_IOCTL_SET_CLOCK_GATE: - { - u32 clkgate; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_SET_CLOCK_GATE\n"); - if (get_user(clkgate, (u32 __user *) arg)) - return -EFAULT; -#ifdef VPU_SUPPORT_CLOCK_CONTROL - vpu_clk_config(clkgate); -#endif - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_SET_CLOCK_GATE\n"); - } - break; - case VDI_IOCTL_GET_INSTANCE_POOL: - { - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_INSTANCE_POOL\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret != 0) - break; - - if (s_instance_pool.base != 0) { - ret = copy_to_user((void __user *)arg, - &s_instance_pool, - sizeof(struct vpudrv_buffer_t)); - ret = (ret != 0) ? -EFAULT : 0; - } else { - ret = copy_from_user(&s_instance_pool, - (struct vpudrv_buffer_t *)arg, - sizeof(struct vpudrv_buffer_t)); - if (ret == 0) { - s_instance_pool.size = - PAGE_ALIGN( - s_instance_pool.size); - s_instance_pool.base = - (ulong)vmalloc( - s_instance_pool.size); - s_instance_pool.phys_addr = - s_instance_pool.base; - if (s_instance_pool.base == 0) { - ret = -EFAULT; - up(&s_vpu_sem); - break; - } - /*clearing memory*/ - memset((void *)s_instance_pool.base, - 0, s_instance_pool.size); - ret = copy_to_user((void __user *)arg, - &s_instance_pool, - sizeof(struct vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else - ret = -EFAULT; - } - up(&s_vpu_sem); - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_INSTANCE_POOL\n"); - } - break; -#ifdef CONFIG_COMPAT - case VDI_IOCTL_GET_INSTANCE_POOL32: - { - struct compat_vpudrv_buffer_t buf32; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_INSTANCE_POOL32\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret != 0) - break; - if (s_instance_pool.base != 0) { - buf32.size = s_instance_pool.size; - buf32.phys_addr = - (compat_ulong_t) - s_instance_pool.phys_addr; - buf32.virt_addr = - (compat_ulong_t) - s_instance_pool.virt_addr; - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof(struct compat_vpudrv_buffer_t)); - ret = (ret != 0) ? -EFAULT : 0; - } else { - ret = copy_from_user(&buf32, - (struct compat_vpudrv_buffer_t *)arg, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret == 0) { - s_instance_pool.size = buf32.size; - s_instance_pool.size = - PAGE_ALIGN( - s_instance_pool.size); - s_instance_pool.base = - (ulong)vmalloc( - s_instance_pool.size); - s_instance_pool.phys_addr = - s_instance_pool.base; - buf32.size = - s_instance_pool.size; - buf32.phys_addr = - (compat_ulong_t) - s_instance_pool.phys_addr; - buf32.base = - (compat_ulong_t) - s_instance_pool.base; - buf32.virt_addr = - (compat_ulong_t) - s_instance_pool.virt_addr; - if (s_instance_pool.base == 0) { - ret = -EFAULT; - up(&s_vpu_sem); - break; - } - /*clearing memory*/ - memset((void *)s_instance_pool.base, - 0x0, s_instance_pool.size); - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof( - struct compat_vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else - ret = -EFAULT; - } - up(&s_vpu_sem); - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_INSTANCE_POOL32\n"); - } - break; -#endif - case VDI_IOCTL_GET_COMMON_MEMORY: - { - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_COMMON_MEMORY\n"); - if (s_common_memory.phys_addr != 0) { - ret = copy_to_user((void __user *)arg, - &s_common_memory, - sizeof(struct vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else { - ret = copy_from_user(&s_common_memory, - (struct vpudrv_buffer_t *)arg, - sizeof(struct vpudrv_buffer_t)); - if (ret != 0) { - ret = -EFAULT; - break; - } - if (vpu_alloc_dma_buffer( - &s_common_memory) != -1) { - ret = copy_to_user((void __user *)arg, - &s_common_memory, - sizeof(struct vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else - ret = -EFAULT; - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_COMMON_MEMORY\n"); - } - break; -#ifdef CONFIG_COMPAT - case VDI_IOCTL_GET_COMMON_MEMORY32: - { - struct compat_vpudrv_buffer_t buf32; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_COMMON_MEMORY32\n"); - - buf32.size = s_common_memory.size; - buf32.phys_addr = - (compat_ulong_t) - s_common_memory.phys_addr; - buf32.virt_addr = - (compat_ulong_t) - s_common_memory.virt_addr; - if (s_common_memory.phys_addr != 0) { - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else { - ret = copy_from_user(&buf32, - (struct compat_vpudrv_buffer_t *)arg, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret != 0) { - ret = -EFAULT; - break; - } - s_common_memory.size = buf32.size; - if (vpu_alloc_dma_buffer( - &s_common_memory) != -1) { - buf32.size = - s_common_memory.size; - buf32.phys_addr = - (compat_ulong_t) - s_common_memory.phys_addr; - buf32.virt_addr = - (compat_ulong_t) - s_common_memory.virt_addr; - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof( - struct compat_vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - } else - ret = -EFAULT; - } - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_COMMON_MEMORY32\n"); - } - break; -#endif - case VDI_IOCTL_OPEN_INSTANCE: - { - struct vpudrv_inst_info_t inst_info; - struct vpudrv_instanace_list_t *vil, *n; - - vil = kzalloc(sizeof(*vil), GFP_KERNEL); - if (!vil) - return -ENOMEM; - - if (copy_from_user(&inst_info, - (struct vpudrv_inst_info_t *)arg, - sizeof(struct vpudrv_inst_info_t))) - return -EFAULT; - - vil->inst_idx = inst_info.inst_idx; - vil->core_idx = inst_info.core_idx; - vil->filp = filp; - - spin_lock(&s_vpu_lock); - list_add(&vil->list, &s_inst_list_head); - - /* counting the current open instance number */ - inst_info.inst_open_count = 0; - list_for_each_entry_safe(vil, n, - &s_inst_list_head, list) { - if (vil->core_idx == inst_info.core_idx) - inst_info.inst_open_count++; - } - - /* flag just for that vpu is in opened or closed */ - s_vpu_open_ref_count++; - spin_unlock(&s_vpu_lock); - - if (copy_to_user((void __user *)arg, - &inst_info, - sizeof(struct vpudrv_inst_info_t))) { - kfree(vil); - return -EFAULT; - } - - enc_pr(LOG_DEBUG, - "VDI_IOCTL_OPEN_INSTANCE "); - enc_pr(LOG_DEBUG, - "core_idx=%d, inst_idx=%d, ", - (u32)inst_info.core_idx, - (u32)inst_info.inst_idx); - enc_pr(LOG_DEBUG, - "s_vpu_open_ref_count=%d, inst_open_count=%d\n", - s_vpu_open_ref_count, - inst_info.inst_open_count); - } - break; - case VDI_IOCTL_CLOSE_INSTANCE: - { - struct vpudrv_inst_info_t inst_info; - struct vpudrv_instanace_list_t *vil, *n; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_CLOSE_INSTANCE\n"); - if (copy_from_user(&inst_info, - (struct vpudrv_inst_info_t *)arg, - sizeof(struct vpudrv_inst_info_t))) - return -EFAULT; - - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(vil, n, - &s_inst_list_head, list) { - if (vil->inst_idx == inst_info.inst_idx && - vil->core_idx == inst_info.core_idx) { - list_del(&vil->list); - kfree(vil); - break; - } - } - - /* counting the current open instance number */ - inst_info.inst_open_count = 0; - list_for_each_entry_safe(vil, n, - &s_inst_list_head, list) { - if (vil->core_idx == inst_info.core_idx) - inst_info.inst_open_count++; - } - - /* flag just for that vpu is in opened or closed */ - s_vpu_open_ref_count--; - spin_unlock(&s_vpu_lock); - - if (copy_to_user((void __user *)arg, - &inst_info, - sizeof(struct vpudrv_inst_info_t))) - return -EFAULT; - - enc_pr(LOG_DEBUG, - "VDI_IOCTL_CLOSE_INSTANCE "); - enc_pr(LOG_DEBUG, - "core_idx=%d, inst_idx=%d, ", - (u32)inst_info.core_idx, - (u32)inst_info.inst_idx); - enc_pr(LOG_DEBUG, - "s_vpu_open_ref_count=%d, inst_open_count=%d\n", - s_vpu_open_ref_count, - inst_info.inst_open_count); - } - break; - case VDI_IOCTL_GET_INSTANCE_NUM: - { - struct vpudrv_inst_info_t inst_info; - struct vpudrv_instanace_list_t *vil, *n; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_INSTANCE_NUM\n"); - - ret = copy_from_user(&inst_info, - (struct vpudrv_inst_info_t *)arg, - sizeof(struct vpudrv_inst_info_t)); - if (ret != 0) - break; - - inst_info.inst_open_count = 0; - - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(vil, n, - &s_inst_list_head, list) { - if (vil->core_idx == inst_info.core_idx) - inst_info.inst_open_count++; - } - spin_unlock(&s_vpu_lock); - - ret = copy_to_user((void __user *)arg, - &inst_info, - sizeof(struct vpudrv_inst_info_t)); - - enc_pr(LOG_DEBUG, - "VDI_IOCTL_GET_INSTANCE_NUM "); - enc_pr(LOG_DEBUG, - "core_idx=%d, inst_idx=%d, open_count=%d\n", - (u32)inst_info.core_idx, - (u32)inst_info.inst_idx, - inst_info.inst_open_count); - } - break; - case VDI_IOCTL_RESET: - { - vpu_hw_reset(); - } - break; - case VDI_IOCTL_GET_REGISTER_INFO: - { - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_REGISTER_INFO\n"); - ret = copy_to_user((void __user *)arg, - &s_vpu_register, - sizeof(struct vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_REGISTER_INFO "); - enc_pr(LOG_ALL, - "s_vpu_register.phys_addr=0x%lx, ", - s_vpu_register.phys_addr); - enc_pr(LOG_ALL, - "s_vpu_register.virt_addr=0x%lx, ", - s_vpu_register.virt_addr); - enc_pr(LOG_ALL, - "s_vpu_register.size=0x%x\n", - s_vpu_register.size); - } - break; -#ifdef CONFIG_COMPAT - case VDI_IOCTL_GET_REGISTER_INFO32: - { - struct compat_vpudrv_buffer_t buf32; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_GET_REGISTER_INFO32\n"); - - buf32.size = s_vpu_register.size; - buf32.phys_addr = - (compat_ulong_t) - s_vpu_register.phys_addr; - buf32.virt_addr = - (compat_ulong_t) - s_vpu_register.virt_addr; - ret = copy_to_user((void __user *)arg, - &buf32, - sizeof( - struct compat_vpudrv_buffer_t)); - if (ret != 0) - ret = -EFAULT; - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_GET_REGISTER_INFO32 "); - enc_pr(LOG_ALL, - "s_vpu_register.phys_addr=0x%lx, ", - s_vpu_register.phys_addr); - enc_pr(LOG_ALL, - "s_vpu_register.virt_addr=0x%lx, ", - s_vpu_register.virt_addr); - enc_pr(LOG_ALL, - "s_vpu_register.size=0x%x\n", - s_vpu_register.size); - } - break; - case VDI_IOCTL_FLUSH_BUFFER32: - { - struct vpudrv_buffer_pool_t *pool, *n; - struct compat_vpudrv_buffer_t buf32; - struct vpudrv_buffer_t vb; - bool find = false; - u32 cached = 0; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_FLUSH_BUFFER32\n"); - - ret = copy_from_user(&buf32, - (struct compat_vpudrv_buffer_t *)arg, - sizeof(struct compat_vpudrv_buffer_t)); - if (ret) - return -EFAULT; - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(pool, n, - &s_vbp_head, list) { - if (pool->filp == filp) { - vb = pool->vb; - if (((compat_ulong_t)vb.phys_addr - == buf32.phys_addr) - && find == false){ - cached = vb.cached; - find = true; - } - } - } - spin_unlock(&s_vpu_lock); - if (find && cached) - dma_flush( - (u32)buf32.phys_addr, - (u32)buf32.size); - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_FLUSH_BUFFER32\n"); - } - break; -#endif - case VDI_IOCTL_FLUSH_BUFFER: - { - struct vpudrv_buffer_pool_t *pool, *n; - struct vpudrv_buffer_t vb, buf; - bool find = false; - u32 cached = 0; - - enc_pr(LOG_ALL, - "[+]VDI_IOCTL_FLUSH_BUFFER\n"); - - ret = copy_from_user(&buf, - (struct vpudrv_buffer_t *)arg, - sizeof(struct vpudrv_buffer_t)); - if (ret) - return -EFAULT; - spin_lock(&s_vpu_lock); - list_for_each_entry_safe(pool, n, - &s_vbp_head, list) { - if (pool->filp == filp) { - vb = pool->vb; - if ((vb.phys_addr - == buf.phys_addr) - && find == false){ - cached = vb.cached; - find = true; - } - } - } - spin_unlock(&s_vpu_lock); - if (find && cached) - dma_flush( - (u32)buf.phys_addr, - (u32)buf.size); - enc_pr(LOG_ALL, - "[-]VDI_IOCTL_FLUSH_BUFFER\n"); - } - break; - default: - { - enc_pr(LOG_ERROR, - "No such IOCTL, cmd is %d\n", cmd); - ret = -EFAULT; - } - break; - } - return ret; -} - -#ifdef CONFIG_COMPAT -static long vpu_compat_ioctl(struct file *filp, u32 cmd, ulong arg) -{ - long ret; - - arg = (ulong)compat_ptr(arg); - ret = vpu_ioctl(filp, cmd, arg); - return ret; -} -#endif - -static ssize_t vpu_write(struct file *filp, - const char *buf, - size_t len, - loff_t *ppos) -{ - enc_pr(LOG_INFO, "vpu_write len=%d\n", (int)len); - - if (!buf) { - enc_pr(LOG_ERROR, "vpu_write buf = NULL error\n"); - return -EFAULT; - } - - if (len == sizeof(struct vpu_bit_firmware_info_t)) { - struct vpu_bit_firmware_info_t *bit_firmware_info; - - bit_firmware_info = - kmalloc(sizeof(struct vpu_bit_firmware_info_t), - GFP_KERNEL); - if (!bit_firmware_info) { - enc_pr(LOG_ERROR, - "vpu_write bit_firmware_info allocation error\n"); - return -EFAULT; - } - - if (copy_from_user(bit_firmware_info, buf, len)) { - enc_pr(LOG_ERROR, - "vpu_write copy_from_user error for bit_firmware_info\n"); - return -EFAULT; - } - - if (bit_firmware_info->size == - sizeof(struct vpu_bit_firmware_info_t)) { - enc_pr(LOG_INFO, - "vpu_write set bit_firmware_info coreIdx=0x%x, ", - bit_firmware_info->core_idx); - enc_pr(LOG_INFO, - "reg_base_offset=0x%x size=0x%x, bit_code[0]=0x%x\n", - bit_firmware_info->reg_base_offset, - bit_firmware_info->size, - bit_firmware_info->bit_code[0]); - - if (bit_firmware_info->core_idx - > MAX_NUM_VPU_CORE) { - enc_pr(LOG_ERROR, - "vpu_write coreIdx[%d] is ", - bit_firmware_info->core_idx); - enc_pr(LOG_ERROR, - "exceeded than MAX_NUM_VPU_CORE[%d]\n", - MAX_NUM_VPU_CORE); - return -ENODEV; - } - - memcpy((void *)&s_bit_firmware_info - [bit_firmware_info->core_idx], - bit_firmware_info, - sizeof(struct vpu_bit_firmware_info_t)); - kfree(bit_firmware_info); - return len; - } - kfree(bit_firmware_info); - } - return -1; -} - -static s32 vpu_release(struct inode *inode, struct file *filp) -{ - s32 ret = 0; - ulong flags; - - enc_pr(LOG_DEBUG, "vpu_release\n"); - ret = down_interruptible(&s_vpu_sem); - if (ret == 0) { - vpu_free_buffers(filp); - vpu_free_instances(filp); - s_vpu_drv_context.open_count--; - if (s_vpu_drv_context.open_count == 0) { - enc_pr(LOG_INFO, - "vpu_release: s_interrupt_flag(%d), reason(0x%08lx)\n", - s_interrupt_flag, s_vpu_drv_context.interrupt_reason); - s_vpu_drv_context.interrupt_reason = 0; - s_interrupt_flag = 0; - if (s_instance_pool.base) { - enc_pr(LOG_DEBUG, "free instance pool\n"); - vfree((const void *)s_instance_pool.base); - s_instance_pool.base = 0; - } - if (s_common_memory.phys_addr) { - enc_pr(LOG_INFO, "vpu_release, s_common_memory 0x%lx\n",s_common_memory.phys_addr); - vpu_free_dma_buffer(&s_common_memory); - s_common_memory.phys_addr = 0; - } - - if (s_video_memory.phys_addr && !use_reserve) { - enc_pr(LOG_DEBUG, "vpu_release, s_video_memory 0x%lx\n",s_video_memory.phys_addr); - codec_mm_free_for_dma( - VPU_DEV_NAME, - (u32)s_video_memory.phys_addr); - vmem_exit(&s_vmem); - memset(&s_video_memory, - 0, sizeof(struct vpudrv_buffer_t)); - memset(&s_vmem, - 0, sizeof(struct video_mm_t)); - } - if ((s_vpu_irq >= 0) && (s_vpu_irq_requested == true)) { - free_irq(s_vpu_irq, &s_vpu_drv_context); - s_vpu_irq_requested = false; - } - spin_lock_irqsave(&s_vpu_lock, flags); - WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 - ? 0x8 : (0x3<<12))); - udelay(10); - - WRITE_VREG(DOS_MEM_PD_WAVE420L, 0xffffffff); -#ifndef VPU_SUPPORT_CLOCK_CONTROL - vpu_clk_config(0); -#endif - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | - (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 - ? 0x8 : (0x3<<24))); - udelay(10); - spin_unlock_irqrestore(&s_vpu_lock, flags); - amports_switch_gate("vdec", 0); - } - } - up(&s_vpu_sem); - return 0; -} - -static s32 vpu_fasync(s32 fd, struct file *filp, s32 mode) -{ - struct vpu_drv_context_t *dev = - (struct vpu_drv_context_t *)filp->private_data; - return fasync_helper(fd, filp, mode, &dev->async_queue); -} - -static s32 vpu_map_to_register(struct file *fp, struct vm_area_struct *vm) -{ - ulong pfn; - - vm->vm_flags |= VM_IO | VM_RESERVED; - vm->vm_page_prot = - pgprot_noncached(vm->vm_page_prot); - pfn = s_vpu_register.phys_addr >> PAGE_SHIFT; - return remap_pfn_range(vm, vm->vm_start, pfn, - vm->vm_end - vm->vm_start, - vm->vm_page_prot) ? -EAGAIN : 0; -} - -static s32 vpu_map_to_physical_memory( - struct file *fp, struct vm_area_struct *vm) -{ - vm->vm_flags |= VM_IO | VM_RESERVED; - if (vm->vm_pgoff == - (s_common_memory.phys_addr >> PAGE_SHIFT)) { - vm->vm_page_prot = - pgprot_noncached(vm->vm_page_prot); - } else { - if (vpu_is_buffer_cached(fp, vm->vm_pgoff) == 0) - vm->vm_page_prot = - pgprot_noncached(vm->vm_page_prot); - } - /* vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot); */ - return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff, - vm->vm_end - vm->vm_start, vm->vm_page_prot) ? -EAGAIN : 0; -} - -static s32 vpu_map_to_instance_pool_memory( - struct file *fp, struct vm_area_struct *vm) -{ - s32 ret; - long length = vm->vm_end - vm->vm_start; - ulong start = vm->vm_start; - s8 *vmalloc_area_ptr = (s8 *)s_instance_pool.base; - ulong pfn; - - vm->vm_flags |= VM_RESERVED; - - /* loop over all pages, map it page individually */ - while (length > 0) { - pfn = vmalloc_to_pfn(vmalloc_area_ptr); - ret = remap_pfn_range(vm, start, pfn, - PAGE_SIZE, PAGE_SHARED); - if (ret < 0) - return ret; - start += PAGE_SIZE; - vmalloc_area_ptr += PAGE_SIZE; - length -= PAGE_SIZE; - } - return 0; -} - -/* - * @brief memory map interface for vpu file operation - * @return 0 on success or negative error code on error - */ -static s32 vpu_mmap(struct file *fp, struct vm_area_struct *vm) -{ - /* if (vm->vm_pgoff == (s_vpu_register.phys_addr >> PAGE_SHIFT)) */ - if ((vm->vm_end - vm->vm_start == s_vpu_register.size + 1) && - (vm->vm_pgoff == 0)) { - vm->vm_pgoff = (s_vpu_register.phys_addr >> PAGE_SHIFT); - return vpu_map_to_register(fp, vm); - } - - if (vm->vm_pgoff == 0) - return vpu_map_to_instance_pool_memory(fp, vm); - - return vpu_map_to_physical_memory(fp, vm); -} - -static const struct file_operations vpu_fops = { - .owner = THIS_MODULE, - .open = vpu_open, - .release = vpu_release, - .write = vpu_write, - .unlocked_ioctl = vpu_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vpu_compat_ioctl, -#endif - .fasync = vpu_fasync, - .mmap = vpu_mmap, -}; - -static ssize_t hevcenc_status_show(struct class *cla, - struct class_attribute *attr, char *buf) -{ - return snprintf(buf, 40, "hevcenc_status_show\n"); -} - -static struct class_attribute hevcenc_class_attrs[] = { - __ATTR(encode_status, - S_IRUGO | S_IWUSR, - hevcenc_status_show, - NULL), - __ATTR_NULL -}; - -static struct class hevcenc_class = { - .name = VPU_CLASS_NAME, - .class_attrs = hevcenc_class_attrs, -}; - -s32 init_HevcEnc_device(void) -{ - s32 r = 0; - - r = register_chrdev(0, VPU_DEV_NAME, &vpu_fops); - if (r <= 0) { - enc_pr(LOG_ERROR, "register hevcenc device error.\n"); - return r; - } - s_vpu_major = r; - - r = class_register(&hevcenc_class); - if (r < 0) { - enc_pr(LOG_ERROR, "error create hevcenc class.\n"); - return r; - } - - hevcenc_dev = device_create(&hevcenc_class, NULL, - MKDEV(s_vpu_major, 0), NULL, - VPU_DEV_NAME); - - if (IS_ERR(hevcenc_dev)) { - enc_pr(LOG_ERROR, "create hevcenc device error.\n"); - class_unregister(&hevcenc_class); - return -1; - } - return r; -} - -s32 uninit_HevcEnc_device(void) -{ - if (hevcenc_dev) - device_destroy(&hevcenc_class, MKDEV(s_vpu_major, 0)); - - class_destroy(&hevcenc_class); - - unregister_chrdev(s_vpu_major, VPU_DEV_NAME); - return 0; -} - -static s32 hevc_mem_device_init( - struct reserved_mem *rmem, struct device *dev) -{ - s32 r; - - if (!rmem) { - enc_pr(LOG_ERROR, - "Can not obtain I/O memory, will allocate hevc buffer!\n"); - r = -EFAULT; - return r; - } - - if ((!rmem->base) || - (rmem->size < VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE)) { - enc_pr(LOG_ERROR, - "memory range error, 0x%lx - 0x%lx\n", - (ulong)rmem->base, (ulong)rmem->size); - r = -EFAULT; - return r; - } - r = 0; - s_video_memory.size = rmem->size; - s_video_memory.phys_addr = (ulong)rmem->base; - enc_pr(LOG_DEBUG, "hevc_mem_device_init %d, 0x%lx\n ",s_video_memory.size,s_video_memory.phys_addr); - - return r; -} - -static s32 vpu_probe(struct platform_device *pdev) -{ - s32 err = 0, irq, reg_count, idx; - struct resource res; - struct device_node *np, *child; - - enc_pr(LOG_DEBUG, "vpu_probe\n"); - - s_vpu_major = 0; - use_reserve = false; - s_vpu_irq = -1; - cma_pool_size = 0; - s_vpu_irq_requested = false; - s_vpu_open_ref_count = 0; - hevcenc_dev = NULL; - hevc_pdev = NULL; - memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); - memset(&s_vpu_register, 0, sizeof(struct vpudrv_buffer_t)); - memset(&s_vmem, 0, sizeof(struct video_mm_t)); - memset(&s_bit_firmware_info[0], 0, sizeof(s_bit_firmware_info)); - memset(&res, 0, sizeof(struct resource)); - - idx = of_reserved_mem_device_init(&pdev->dev); - if (idx != 0) { - enc_pr(LOG_DEBUG, - "HevcEnc reserved memory config fail.\n"); - } else if (s_video_memory.phys_addr) { - use_reserve = true; - } - - if (use_reserve == false) { -#ifndef CONFIG_CMA - enc_pr(LOG_ERROR, - "HevcEnc reserved memory is invaild, probe fail!\n"); - err = -EFAULT; - goto ERROR_PROVE_DEVICE; -#else - cma_pool_size = - (codec_mm_get_total_size() > - (VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE)) ? - (VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE) : - codec_mm_get_total_size(); - enc_pr(LOG_DEBUG, - "HevcEnc - cma memory pool size: %d MB\n", - (u32)cma_pool_size / SZ_1M); -#endif - } - - /* get interrupt resource */ - irq = platform_get_irq_byname(pdev, "wave420l_irq"); - if (irq < 0) { - enc_pr(LOG_ERROR, "get HevcEnc irq resource error\n"); - err = -ENXIO; - goto ERROR_PROVE_DEVICE; - } - s_vpu_irq = irq; - enc_pr(LOG_DEBUG, "HevcEnc - wave420l_irq: %d\n", s_vpu_irq); -#if 0 - rstc = devm_reset_control_get(&pdev->dev, "HevcEnc"); - if (IS_ERR(rstc)) { - enc_pr(LOG_ERROR, - "get HevcEnc rstc error: %lx\n", PTR_ERR(rstc)); - rstc = NULL; - err = -ENOENT; - goto ERROR_PROVE_DEVICE; - } - reset_control_assert(rstc); - s_vpu_rstc = rstc; - - clk = clk_get(&pdev->dev, "clk_HevcEnc"); - if (IS_ERR(clk)) { - enc_pr(LOG_ERROR, "cannot get clock\n"); - clk = NULL; - err = -ENOENT; - goto ERROR_PROVE_DEVICE; - } - s_vpu_clk = clk; -#endif - -#ifdef VPU_SUPPORT_CLOCK_CONTROL -#else - vpu_clk_config(1); -#endif - - np = pdev->dev.of_node; - reg_count = 0; - for_each_child_of_node(np, child) { - if (of_address_to_resource(child, 0, &res) - || (reg_count > 1)) { - enc_pr(LOG_ERROR, - "no reg ranges or more reg ranges %d\n", - reg_count); - err = -ENXIO; - goto ERROR_PROVE_DEVICE; - } - /* if platform driver is implemented */ - if (res.start != 0) { - s_vpu_register.phys_addr = res.start; - s_vpu_register.virt_addr = - (ulong)ioremap_nocache( - res.start, resource_size(&res)); - s_vpu_register.size = res.end - res.start; - enc_pr(LOG_DEBUG, - "vpu base address get from platform driver "); - enc_pr(LOG_DEBUG, - "physical base addr=0x%lx, virtual base=0x%lx\n", - s_vpu_register.phys_addr, - s_vpu_register.virt_addr); - } else { - s_vpu_register.phys_addr = VPU_REG_BASE_ADDR; - s_vpu_register.virt_addr = - (ulong)ioremap_nocache( - s_vpu_register.phys_addr, VPU_REG_SIZE); - s_vpu_register.size = VPU_REG_SIZE; - enc_pr(LOG_DEBUG, - "vpu base address get from defined value "); - enc_pr(LOG_DEBUG, - "physical base addr=0x%lx, virtual base=0x%lx\n", - s_vpu_register.phys_addr, - s_vpu_register.virt_addr); - } - reg_count++; - } - - /* get the major number of the character device */ - if (init_HevcEnc_device()) { - err = -EBUSY; - enc_pr(LOG_ERROR, "could not allocate major number\n"); - goto ERROR_PROVE_DEVICE; - } - enc_pr(LOG_INFO, "SUCCESS alloc_chrdev_region\n"); - - init_waitqueue_head(&s_interrupt_wait_q); - tasklet_init(&hevc_tasklet, - hevcenc_isr_tasklet, - (ulong)&s_vpu_drv_context); - s_common_memory.base = 0; - s_instance_pool.base = 0; - - if (use_reserve == true) { - if (vmem_init(&s_vmem, s_video_memory.phys_addr, - s_video_memory.size) < 0) { - enc_pr(LOG_ERROR, "fail to init vmem system\n"); - goto ERROR_PROVE_DEVICE; - } - enc_pr(LOG_DEBUG, - "success to probe vpu device with video memory "); - enc_pr(LOG_DEBUG, - "phys_addr=0x%lx, base = 0x%lx\n", - (ulong)s_video_memory.phys_addr, - (ulong)s_video_memory.base); - } else - enc_pr(LOG_DEBUG, - "success to probe vpu device with video memory from cma\n"); - hevc_pdev = pdev; - return 0; - -ERROR_PROVE_DEVICE: - if (s_vpu_register.virt_addr) { - iounmap((void *)s_vpu_register.virt_addr); - memset(&s_vpu_register, 0, sizeof(struct vpudrv_buffer_t)); - } - - if (s_video_memory.phys_addr) { - vmem_exit(&s_vmem); - memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); - memset(&s_vmem, 0, sizeof(struct video_mm_t)); - } - - vpu_clk_config(0); - - if (s_vpu_irq_requested == true) { - if (s_vpu_irq >= 0) { - free_irq(s_vpu_irq, &s_vpu_drv_context); - s_vpu_irq = -1; - } - s_vpu_irq_requested = false; - } - uninit_HevcEnc_device(); - return err; -} - -static s32 vpu_remove(struct platform_device *pdev) -{ - enc_pr(LOG_DEBUG, "vpu_remove\n"); - - if (s_instance_pool.base) { - vfree((const void *)s_instance_pool.base); - s_instance_pool.base = 0; - } - - if (s_common_memory.phys_addr) { - vpu_free_dma_buffer(&s_common_memory); - s_common_memory.phys_addr = 0; - } - - if (s_video_memory.phys_addr) { - if (!use_reserve) { - codec_mm_free_for_dma( - VPU_DEV_NAME, - (u32)s_video_memory.phys_addr); - } - vmem_exit(&s_vmem); - memset(&s_video_memory, - 0, sizeof(struct vpudrv_buffer_t)); - memset(&s_vmem, - 0, sizeof(struct video_mm_t)); - } - - if (s_vpu_irq_requested == true) { - if (s_vpu_irq >= 0) { - free_irq(s_vpu_irq, &s_vpu_drv_context); - s_vpu_irq = -1; - } - s_vpu_irq_requested = false; - } - - if (s_vpu_register.virt_addr) { - iounmap((void *)s_vpu_register.virt_addr); - memset(&s_vpu_register, - 0, sizeof(struct vpudrv_buffer_t)); - } - hevc_pdev = NULL; - vpu_clk_config(0); - - uninit_HevcEnc_device(); - return 0; -} - -#ifdef CONFIG_PM -static void Wave4BitIssueCommand(u32 core, u32 cmd) -{ - WriteVpuRegister(W4_VPU_BUSY_STATUS, 1); - WriteVpuRegister(W4_CORE_INDEX, 0); - /* coreIdx = ReadVpuRegister(W4_VPU_BUSY_STATUS); */ - /* coreIdx = 0; */ - /* WriteVpuRegister(W4_INST_INDEX, - * (instanceIndex & 0xffff) | (codecMode << 16)); - */ - WriteVpuRegister(W4_COMMAND, cmd); - WriteVpuRegister(W4_VPU_HOST_INT_REQ, 1); -} - -static s32 vpu_suspend(struct platform_device *pdev, pm_message_t state) -{ - u32 core; - ulong timeout = jiffies + HZ; /* vpu wait timeout to 1sec */ - - enc_pr(LOG_DEBUG, "vpu_suspend\n"); - - vpu_clk_config(1); - - if (s_vpu_open_ref_count > 0) { - for (core = 0; core < MAX_NUM_VPU_CORE; core++) { - if (s_bit_firmware_info[core].size == 0) - continue; - while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { - if (time_after(jiffies, timeout)) { - enc_pr(LOG_ERROR, - "SLEEP_VPU BUSY timeout"); - goto DONE_SUSPEND; - } - } - Wave4BitIssueCommand(core, W4_CMD_SLEEP_VPU); - - while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { - if (time_after(jiffies, timeout)) { - enc_pr(LOG_ERROR, - "SLEEP_VPU BUSY timeout"); - goto DONE_SUSPEND; - } - } - if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { - enc_pr(LOG_ERROR, - "SLEEP_VPU failed [0x%x]", - ReadVpuRegister(W4_RET_FAIL_REASON)); - goto DONE_SUSPEND; - } - } - } - - vpu_clk_config(0); - return 0; - -DONE_SUSPEND: - vpu_clk_config(0); - return -EAGAIN; -} -static s32 vpu_resume(struct platform_device *pdev) -{ - u32 i; - u32 core; - u32 val; - ulong timeout = jiffies + HZ; /* vpu wait timeout to 1sec */ - ulong code_base; - u32 code_size; - u32 remap_size; - u32 regVal; - u32 hwOption = 0; - - enc_pr(LOG_DEBUG, "vpu_resume\n"); - - vpu_clk_config(1); - if (s_vpu_open_ref_count > 0) { - for (core = 0; core < MAX_NUM_VPU_CORE; core++) { - if (s_bit_firmware_info[core].size == 0) - continue; - code_base = s_common_memory.phys_addr; - /* ALIGN TO 4KB */ - code_size = (s_common_memory.size & ~0xfff); - if (code_size < s_bit_firmware_info[core].size * 2) - goto DONE_WAKEUP; - - /*---- LOAD BOOT CODE */ - for (i = 0; i < 512; i += 2) { - val = s_bit_firmware_info[core].bit_code[i]; - val |= (s_bit_firmware_info[core].bit_code[i+1] << 16); - WriteVpu(code_base+(i*2), val); - } - - regVal = 0; - WriteVpuRegister(W4_PO_CONF, regVal); - - /* Reset All blocks */ - regVal = 0x7ffffff; - WriteVpuRegister(W4_VPU_RESET_REQ, regVal); - - /* Waiting reset done */ - while (ReadVpuRegister(W4_VPU_RESET_STATUS)) { - if (time_after(jiffies, timeout)) - goto DONE_WAKEUP; - } - - WriteVpuRegister(W4_VPU_RESET_REQ, 0); - - /* remap page size */ - remap_size = (code_size >> 12) & 0x1ff; - regVal = 0x80000000 | (W4_REMAP_CODE_INDEX<<12) - | (0 << 16) | (1<<11) | remap_size; - WriteVpuRegister(W4_VPU_REMAP_CTRL, regVal); - /* DO NOT CHANGE! */ - WriteVpuRegister(W4_VPU_REMAP_VADDR, 0x00000000); - WriteVpuRegister(W4_VPU_REMAP_PADDR, code_base); - WriteVpuRegister(W4_ADDR_CODE_BASE, code_base); - WriteVpuRegister(W4_CODE_SIZE, code_size); - WriteVpuRegister(W4_CODE_PARAM, 0); - WriteVpuRegister(W4_INIT_VPU_TIME_OUT_CNT, timeout); - WriteVpuRegister(W4_HW_OPTION, hwOption); - - /* Interrupt */ - regVal = (1 << W4_INT_DEC_PIC_HDR); - regVal |= (1 << W4_INT_DEC_PIC); - regVal |= (1 << W4_INT_QUERY_DEC); - regVal |= (1 << W4_INT_SLEEP_VPU); - regVal |= (1 << W4_INT_BSBUF_EMPTY); - regVal = 0xfffffefe; - WriteVpuRegister(W4_VPU_VINT_ENABLE, regVal); - Wave4BitIssueCommand(core, W4_CMD_INIT_VPU); - WriteVpuRegister(W4_VPU_REMAP_CORE_START, 1); - while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { - if (time_after(jiffies, timeout)) - goto DONE_WAKEUP; - } - - if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { - enc_pr(LOG_ERROR, - "WAKEUP_VPU failed [0x%x]", - ReadVpuRegister(W4_RET_FAIL_REASON)); - goto DONE_WAKEUP; - } - } - } - - if (s_vpu_open_ref_count == 0) - vpu_clk_config(0); -DONE_WAKEUP: - if (s_vpu_open_ref_count > 0) - vpu_clk_config(1); - return 0; -} -#else -#define vpu_suspend NULL -#define vpu_resume NULL -#endif /* !CONFIG_PM */ - -static const struct of_device_id cnm_hevcenc_dt_match[] = { - { - .compatible = "cnm, HevcEnc", - }, - {}, -}; - -static struct platform_driver vpu_driver = { - .driver = { - .name = VPU_PLATFORM_DEVICE_NAME, - .of_match_table = cnm_hevcenc_dt_match, - }, - .probe = vpu_probe, - .remove = vpu_remove, - .suspend = vpu_suspend, - .resume = vpu_resume, -}; - -static s32 __init vpu_init(void) -{ - s32 res; - - enc_pr(LOG_DEBUG, "vpu_init\n"); - - if ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) - && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) - && (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) - && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) - && (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) { - enc_pr(LOG_DEBUG, - "The chip is not support hevc encoder\n"); - return -1; - } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) { - if ((READ_EFUSE_REG(EFUSE_LIC2) >> 12) & 1) { - enc_pr(LOG_DEBUG, - "Chip efuse disabled H265\n"); - return -1; - } - } - - res = platform_driver_register(&vpu_driver); - enc_pr(LOG_INFO, - "end vpu_init result=0x%x\n", res); - return res; -} - -static void __exit vpu_exit(void) -{ - enc_pr(LOG_DEBUG, "vpu_exit\n"); - if ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) { - enc_pr(LOG_INFO, - "The chip is not support hevc encoder\n"); - return; - } - platform_driver_unregister(&vpu_driver); -} - -static const struct reserved_mem_ops rmem_hevc_ops = { - .device_init = hevc_mem_device_init, -}; - -static s32 __init hevc_mem_setup(struct reserved_mem *rmem) -{ - rmem->ops = &rmem_hevc_ops; - enc_pr(LOG_DEBUG, "HevcEnc reserved mem setup.\n"); - return 0; -} - -module_param(print_level, uint, 0664); -MODULE_PARM_DESC(print_level, "\n print_level\n"); - -module_param(clock_level, uint, 0664); -MODULE_PARM_DESC(clock_level, "\n clock_level\n"); - -MODULE_AUTHOR("Amlogic using C&M VPU, Inc."); -MODULE_DESCRIPTION("VPU linux driver"); -MODULE_LICENSE("GPL"); - -module_init(vpu_init); -module_exit(vpu_exit); -RESERVEDMEM_OF_DECLARE(cnm_hevc, "cnm, HevcEnc-memory", hevc_mem_setup); diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h deleted file mode 100644 index eaf764c1c4b3..000000000000 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * vpu.h - * - * linux device driver for VPU. - * - * Copyright (C) 2006 - 2013 CHIPS&MEDIA INC. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef __VPU_DRV_H__ -#define __VPU_DRV_H__ - -#include -#include -#include - -#define MAX_INST_HANDLE_SIZE (32*1024) -#define MAX_NUM_INSTANCE 4 -#define MAX_NUM_VPU_CORE 1 - -#define W4_CMD_INIT_VPU (0x0001) -#define W4_CMD_SLEEP_VPU (0x0400) -#define W4_CMD_WAKEUP_VPU (0x0800) - -/* GXM: 2000/10 = 200M */ -#define HevcEnc_L0() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (3 << 25) | (1 << 16) | (3 << 9) | (1 << 0)) -/* GXM: 2000/8 = 250M */ -#define HevcEnc_L1() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (1 << 25) | (1 << 16) | (1 << 9) | (1 << 0)) -/* GXM: 2000/7 = 285M */ -#define HevcEnc_L2() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (4 << 25) | (0 << 16) | (4 << 9) | (0 << 0)) -/*GXM: 2000/6 = 333M */ -#define HevcEnc_L3() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (2 << 25) | (1 << 16) | (2 << 9) | (1 << 0)) -/* GXM: 2000/5 = 400M */ -#define HevcEnc_L4() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (3 << 25) | (0 << 16) | (3 << 9) | (0 << 0)) -/* GXM: 2000/4 = 500M */ -#define HevcEnc_L5() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (1 << 25) | (0 << 16) | (1 << 9) | (0 << 0)) -/* GXM: 2000/3 = 667M */ -#define HevcEnc_L6() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - (2 << 25) | (0 << 16) | (2 << 9) | (0 << 0)) - -#define HevcEnc_clock_enable(level) \ - do { \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - READ_HHI_REG(HHI_WAVE420L_CLK_CNTL) \ - & (~(1 << 8)) & (~(1 << 24))); \ - if (level == 0) \ - HevcEnc_L0(); \ - else if (level == 1) \ - HevcEnc_L1(); \ - else if (level == 2) \ - HevcEnc_L2(); \ - else if (level == 3) \ - HevcEnc_L3(); \ - else if (level == 4) \ - HevcEnc_L4(); \ - else if (level == 5) \ - HevcEnc_L5(); \ - else if (level == 6) \ - HevcEnc_L6(); \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - READ_HHI_REG(HHI_WAVE420L_CLK_CNTL) \ - | (1 << 8) | (1 << 24)); \ - } while (0) - -#define HevcEnc_clock_disable() \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ - READ_HHI_REG(HHI_WAVE420L_CLK_CNTL) \ - & (~(1 << 8)) & (~(1 << 24))) - -/* ACLK 667MHZ */ -#define HevcEnc_MoreClock_enable() \ - do { \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL2, \ - READ_HHI_REG(HHI_WAVE420L_CLK_CNTL2) \ - & (~(1 << 8))); \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL2, \ - (2 << 9) | (0 << 0)); \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL2, \ - READ_HHI_REG(HHI_WAVE420L_CLK_CNTL2) \ - | (1 << 8)); \ - } while (0) - -#define HevcEnc_MoreClock_disable() \ - WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL2, \ - READ_HHI_REG(HHI_WAVE420L_CLK_CNTL2) \ - & (~(1 << 8))) - -#ifdef CONFIG_COMPAT -struct compat_vpudrv_buffer_t { - u32 size; - u32 cached; - compat_ulong_t phys_addr; - compat_ulong_t base; /* kernel logical address in use kernel */ - compat_ulong_t virt_addr; /* virtual user space address */ -}; -#endif - -struct vpudrv_buffer_t { - u32 size; - u32 cached; - ulong phys_addr; - ulong base; /* kernel logical address in use kernel */ - ulong virt_addr; /* virtual user space address */ -}; - -struct vpu_bit_firmware_info_t { - u32 size; /* size of this structure*/ - u32 core_idx; - u32 reg_base_offset; - u16 bit_code[512]; -}; - -struct vpudrv_inst_info_t { - u32 core_idx; - u32 inst_idx; - s32 inst_open_count; /* for output only*/ -}; - -struct vpudrv_intr_info_t { - u32 timeout; - s32 intr_reason; -}; - -struct vpu_drv_context_t { - struct fasync_struct *async_queue; - ulong interrupt_reason; - u32 open_count; /*!<< device reference count. Not instance count */ -}; - -/* To track the allocated memory buffer */ -struct vpudrv_buffer_pool_t { - struct list_head list; - struct vpudrv_buffer_t vb; - struct file *filp; -}; - -/* To track the instance index and buffer in instance pool */ -struct vpudrv_instanace_list_t { - struct list_head list; - ulong inst_idx; - ulong core_idx; - struct file *filp; -}; - -struct vpudrv_instance_pool_t { - u8 codecInstPool[MAX_NUM_INSTANCE][MAX_INST_HANDLE_SIZE]; -}; - -#define VPUDRV_BUF_LEN struct vpudrv_buffer_t -#define VPUDRV_BUF_LEN32 struct compat_vpudrv_buffer_t -#define VPUDRV_INST_LEN struct vpudrv_inst_info_t - -#define VDI_MAGIC 'V' -#define VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY \ - _IOW(VDI_MAGIC, 0, VPUDRV_BUF_LEN) - -#define VDI_IOCTL_FREE_PHYSICALMEMORY \ - _IOW(VDI_MAGIC, 1, VPUDRV_BUF_LEN) - -#define VDI_IOCTL_WAIT_INTERRUPT \ - _IOW(VDI_MAGIC, 2, struct vpudrv_intr_info_t) - -#define VDI_IOCTL_SET_CLOCK_GATE \ - _IOW(VDI_MAGIC, 3, u32) - -#define VDI_IOCTL_RESET \ - _IOW(VDI_MAGIC, 4, u32) - -#define VDI_IOCTL_GET_INSTANCE_POOL \ - _IOW(VDI_MAGIC, 5, VPUDRV_BUF_LEN) - -#define VDI_IOCTL_GET_COMMON_MEMORY \ - _IOW(VDI_MAGIC, 6, VPUDRV_BUF_LEN) - -#define VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO \ - _IOW(VDI_MAGIC, 8, VPUDRV_BUF_LEN) - -#define VDI_IOCTL_OPEN_INSTANCE \ - _IOW(VDI_MAGIC, 9, VPUDRV_INST_LEN) - -#define VDI_IOCTL_CLOSE_INSTANCE \ - _IOW(VDI_MAGIC, 10, VPUDRV_INST_LEN) - -#define VDI_IOCTL_GET_INSTANCE_NUM \ - _IOW(VDI_MAGIC, 11, VPUDRV_INST_LEN) - -#define VDI_IOCTL_GET_REGISTER_INFO \ - _IOW(VDI_MAGIC, 12, VPUDRV_BUF_LEN) - -#define VDI_IOCTL_FLUSH_BUFFER \ - _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN) - -#ifdef CONFIG_COMPAT -#define VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32 \ - _IOW(VDI_MAGIC, 0, VPUDRV_BUF_LEN32) - -#define VDI_IOCTL_FREE_PHYSICALMEMORY32 \ - _IOW(VDI_MAGIC, 1, VPUDRV_BUF_LEN32) - -#define VDI_IOCTL_GET_INSTANCE_POOL32 \ - _IOW(VDI_MAGIC, 5, VPUDRV_BUF_LEN32) - -#define VDI_IOCTL_GET_COMMON_MEMORY32 \ - _IOW(VDI_MAGIC, 6, VPUDRV_BUF_LEN32) - -#define VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32 \ - _IOW(VDI_MAGIC, 8, VPUDRV_BUF_LEN32) - -#define VDI_IOCTL_GET_REGISTER_INFO32 \ - _IOW(VDI_MAGIC, 12, VPUDRV_BUF_LEN32) - -#define VDI_IOCTL_FLUSH_BUFFER32 \ - _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN32) -#endif - -enum { - W4_INT_INIT_VPU = 0, - W4_INT_DEC_PIC_HDR = 1, - W4_INT_SET_PARAM = 1, - W4_INT_ENC_INIT_SEQ = 1, - W4_INT_FINI_SEQ = 2, - W4_INT_DEC_PIC = 3, - W4_INT_ENC_PIC = 3, - W4_INT_SET_FRAMEBUF = 4, - W4_INT_FLUSH_DEC = 5, - W4_INT_ENC_SLICE_INT = 7, - W4_INT_GET_FW_VERSION = 8, - W4_INT_QUERY_DEC = 9, - W4_INT_SLEEP_VPU = 10, - W4_INT_WAKEUP_VPU = 11, - W4_INT_CHANGE_INT = 12, - W4_INT_CREATE_INSTANCE = 14, - W4_INT_BSBUF_EMPTY = 15, - /*!<< Bitstream buffer empty[dec]/full[enc] */ -}; - -/* WAVE4 registers */ -#define VPU_REG_BASE_ADDR 0xc8810000 -#define VPU_REG_SIZE (0x4000 * MAX_NUM_VPU_CORE) - -#define W4_REG_BASE 0x0000 -#define W4_VPU_BUSY_STATUS (W4_REG_BASE + 0x0070) -#define W4_VPU_INT_REASON_CLEAR (W4_REG_BASE + 0x0034) -#define W4_VPU_VINT_CLEAR (W4_REG_BASE + 0x003C) -#define W4_VPU_VPU_INT_STS (W4_REG_BASE + 0x0044) -#define W4_VPU_INT_REASON (W4_REG_BASE + 0x004c) - -#define W4_RET_SUCCESS (W4_REG_BASE + 0x0110) -#define W4_RET_FAIL_REASON (W4_REG_BASE + 0x0114) - -/* WAVE4 INIT, WAKEUP */ -#define W4_PO_CONF (W4_REG_BASE + 0x0000) -#define W4_VCPU_CUR_PC (W4_REG_BASE + 0x0004) - -#define W4_VPU_VINT_ENABLE (W4_REG_BASE + 0x0048) - -#define W4_VPU_RESET_REQ (W4_REG_BASE + 0x0050) -#define W4_VPU_RESET_STATUS (W4_REG_BASE + 0x0054) - -#define W4_VPU_REMAP_CTRL (W4_REG_BASE + 0x0060) -#define W4_VPU_REMAP_VADDR (W4_REG_BASE + 0x0064) -#define W4_VPU_REMAP_PADDR (W4_REG_BASE + 0x0068) -#define W4_VPU_REMAP_CORE_START (W4_REG_BASE + 0x006C) -#define W4_VPU_BUSY_STATUS (W4_REG_BASE + 0x0070) - -#define W4_HW_OPTION (W4_REG_BASE + 0x0124) -#define W4_CODE_SIZE (W4_REG_BASE + 0x011C) -/* Note: W4_INIT_CODE_BASE_ADDR should be aligned to 4KB */ -#define W4_ADDR_CODE_BASE (W4_REG_BASE + 0x0118) -#define W4_CODE_PARAM (W4_REG_BASE + 0x0120) -#define W4_INIT_VPU_TIME_OUT_CNT (W4_REG_BASE + 0x0134) - -/* WAVE4 Wave4BitIssueCommand */ -#define W4_CORE_INDEX (W4_REG_BASE + 0x0104) -#define W4_INST_INDEX (W4_REG_BASE + 0x0108) -#define W4_COMMAND (W4_REG_BASE + 0x0100) -#define W4_VPU_HOST_INT_REQ (W4_REG_BASE + 0x0038) - -#define W4_BS_RD_PTR (W4_REG_BASE + 0x0130) -#define W4_BS_WR_PTR (W4_REG_BASE + 0x0134) -#define W4_RET_ENC_PIC_BYTE (W4_REG_BASE + 0x01C8) - -#define W4_REMAP_CODE_INDEX 0 - -#define ReadVpuRegister(addr) \ - readl((void __iomem *)(s_vpu_register.virt_addr \ - + s_bit_firmware_info[core].reg_base_offset + addr)) - -#define WriteVpuRegister(addr, val) \ - writel((u32)val, (void __iomem *)(s_vpu_register.virt_addr \ - + s_bit_firmware_info[core].reg_base_offset + addr)) - -#define WriteVpu(addr, val) writel((u32)val, (void __iomem *)addr) -#endif diff --git a/drivers/amlogic/media_modules/include/dummy-for-git-empty-dir b/drivers/amlogic/media_modules/include/dummy-for-git-empty-dir deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/amlogic/media_modules/stream_input/Makefile b/drivers/amlogic/media_modules/stream_input/Makefile deleted file mode 100644 index 73dfd13058ab..000000000000 --- a/drivers/amlogic/media_modules/stream_input/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -obj-m += stream_input.o - -stream_input-objs += amports/amstream.o -stream_input-objs += amports/adec.o -stream_input-objs += parser/thread_rw.o -stream_input-objs += parser/streambuf.o -stream_input-objs += parser/esparser.o -stream_input-objs += parser/tsdemux.o -stream_input-objs += parser/psparser.o -stream_input-objs += parser/rmparser.o -stream_input-objs += subtitle/subtitle.o - -obj-$(CONFIG_AMLOGIC_DVB) += parser/hw_demux/ -#obj-y += tv_frontend/ -# obj-y += box-frontend/avl6211/ -# obj-y += box-frontend/atbm8881/ -# obj-y += box-frontend/avl68xx/ diff --git a/drivers/amlogic/media_modules/stream_input/amports/Makefile b/drivers/amlogic/media_modules/stream_input/amports/Makefile deleted file mode 100644 index 82f5934b5f9b..000000000000 --- a/drivers/amlogic/media_modules/stream_input/amports/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += amports.o -amports-objs += amstream.o adec.o diff --git a/drivers/amlogic/media_modules/stream_input/amports/adec.c b/drivers/amlogic/media_modules/stream_input/amports/adec.c deleted file mode 100644 index 5bca205c4262..000000000000 --- a/drivers/amlogic/media_modules/stream_input/amports/adec.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/adec.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../parser/streambuf.h" -#include -#include -#include "amports_priv.h" -#include "../../common/chips/decoder_cpu_ver_info.h" -#define INFO_VALID ((astream_dev) && (astream_dev->format)) - -struct astream_device_s { - char *name; - char *format; - s32 channum; - s32 samplerate; - s32 datawidth; - int offset; - - struct device dev; -}; - -static char *astream_format[] = { - "amadec_mpeg", - "amadec_pcm_s16le", - "amadec_aac", - "amadec_ac3", - "amadec_alaw", - "amadec_mulaw", - "amadec_dts", - "amadec_pcm_s16be", - "amadec_flac", - "amadec_cook", - "amadec_pcm_u8", - "amadec_adpcm", - "amadec_amr", - "amadec_raac", - "amadec_wma", - "amadec_wmapro", - "amadec_pcm_bluray", - "amadec_alac", - "amadec_vorbis", - "amadec_aac_latm", - "amadec_ape", - "amadec_eac3", - "amadec_pcm_widi", - "amadec_dra", - "amadec_sipr", - "amadec_truehd", - "amadec_mpeg1", - "amadec_mpeg2", - "amadec_wmavoi", - "amadec_wmalossless", - "amadec_pcm_s24le", - "adec_max" -}; - -static const char *na_string = "NA"; -static struct astream_device_s *astream_dev; - -static ssize_t format_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - if (INFO_VALID && astream_dev->format) - return sprintf(buf, "%s\n", astream_dev->format); - else - return sprintf(buf, "%s\n", na_string); -} - -static ssize_t channum_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - if (INFO_VALID) - return sprintf(buf, "%u\n", astream_dev->channum); - else - return sprintf(buf, "%s\n", na_string); -} - -static ssize_t samplerate_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - if (INFO_VALID) - return sprintf(buf, "%u\n", astream_dev->samplerate); - else - return sprintf(buf, "%s\n", na_string); -} - -static ssize_t datawidth_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - if (INFO_VALID) - return sprintf(buf, "%u\n", astream_dev->datawidth); - else - return sprintf(buf, "%s\n", na_string); -} - -static ssize_t pts_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - u32 pts, frame_size; - u32 pts_margin = 0; - - if (astream_dev->samplerate <= 12000) - pts_margin = 512; - - if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts, - &frame_size, pts_margin) >= 0)) - return sprintf(buf, "0x%x\n", pts); - else - return sprintf(buf, "%s\n", na_string); -} - -static ssize_t addr_offset_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", astream_dev->offset); -} - -static struct class_attribute astream_class_attrs[] = { - __ATTR_RO(format), - __ATTR_RO(samplerate), - __ATTR_RO(channum), - __ATTR_RO(datawidth), - __ATTR_RO(pts), - __ATTR_RO(addr_offset), - __ATTR_NULL -}; - -static struct class astream_class = { - .name = "astream", - .class_attrs = astream_class_attrs, - }; - -#if 1 -#define IO_CBUS_PHY_BASE 0xc1100000ULL -#define IO_AOBUS_PHY_BASE 0xc8100000ULL -#define CBUS_REG_OFFSET(reg) ((reg) << 2) -#define IO_SECBUS_PHY_BASE 0xda000000ULL - - -#define IO_AOBUS_PHY_BASE_AFTER_G12A 0xff800000ULL - -static struct uio_info astream_uio_info = { - .name = "astream_uio", - .version = "0.1", - .irq = UIO_IRQ_NONE, - - .mem = { - [0] = { - .name = "AIFIFO", - .memtype = UIO_MEM_PHYS, - .addr = - (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL)) - &(PAGE_MASK), - .size = PAGE_SIZE, - }, - [1] = { - .memtype = UIO_MEM_PHYS, - .addr = - (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(VCOP_CTRL_REG)), - .size = PAGE_SIZE, - }, -/* - [2] = { - .name = "SECBUS", - .memtype = UIO_MEM_PHYS, - .addr = (IO_SECBUS_PHY_BASE), - .size = PAGE_SIZE, - }, -*/ - [2] = { - .name = "CBUS", - .memtype = UIO_MEM_PHYS, - .addr = - (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(ASSIST_HW_REV)) - &(PAGE_MASK), - .size = PAGE_SIZE, - }, - [3] = { - .name = "CBUS-START", - .memtype = UIO_MEM_PHYS, - .addr = (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(0x1000)), - .size = PAGE_SIZE, - }, - [4] = { - .name = "AOBUS-START", - .memtype = UIO_MEM_PHYS, - .addr = (IO_AOBUS_PHY_BASE), - .size = PAGE_SIZE, - }, - }, -}; -#endif - -static void astream_release(struct device *dev) -{ - kfree(astream_dev); - - astream_dev = NULL; -} - -s32 adec_init(struct stream_port_s *port) -{ - enum aformat_e af; - - if (!astream_dev) - return -ENODEV; - - af = port->aformat; - - astream_dev->channum = port->achanl; - astream_dev->samplerate = port->asamprate; - astream_dev->datawidth = port->adatawidth; - - /*wmb();don't need it...*/ - if (af < ARRAY_SIZE(astream_format)) - astream_dev->format = astream_format[af]; - else - astream_dev->format = NULL; - return 0; -} -EXPORT_SYMBOL(adec_init); - -s32 adec_release(enum aformat_e vf) -{ - pr_info("adec_release\n"); - - if (!astream_dev) - return -ENODEV; - - astream_dev->format = NULL; - - return 0; -} -EXPORT_SYMBOL(adec_release); - -int amstream_adec_show_fun(const char *trigger, int id, char *sbuf, int size) -{ - int ret = -1; - void *buf, *getbuf = NULL; - if (size < PAGE_SIZE) { - getbuf = (void *)__get_free_page(GFP_KERNEL); - if (!getbuf) - return -ENOMEM; - buf = getbuf; - } else { - buf = sbuf; - } - switch (trigger[0]) { - case 'f': - ret = format_show(NULL, NULL, buf); - break; - case 's': - ret = samplerate_show(NULL, NULL, buf); - break; - case 'c': - ret = channum_show(NULL, NULL, buf); - break; - case 'd': - ret = datawidth_show(NULL, NULL, buf); - break; - case 'p': - ret = pts_show(NULL, NULL, buf); - break; - default: - ret = -1; - } - if (ret > 0 && getbuf != NULL) { - ret = min_t(int, ret, size); - strncpy(sbuf, buf, ret); - } - if (getbuf != NULL) - free_page((unsigned long)getbuf); - return ret; -} - -static struct mconfig adec_configs[] = { - MC_FUN("format", &amstream_adec_show_fun, NULL), - MC_FUN("samplerate", &amstream_adec_show_fun, NULL), - MC_FUN("channum", &amstream_adec_show_fun, NULL), - MC_FUN("datawidth", &amstream_adec_show_fun, NULL), - MC_FUN("pts", &amstream_adec_show_fun, NULL), -}; -static struct mconfig_node adec_node; - - -s32 astream_dev_register(void) -{ - s32 r; - struct device_node *node; - unsigned int cbus_base = 0xffd00000; - - r = class_register(&astream_class); - if (r) { - pr_info("astream class create fail.\n"); - return r; - } - - astream_dev = kzalloc(sizeof(struct astream_device_s), GFP_KERNEL); - - if (!astream_dev) { - pr_info("astream device create fail.\n"); - r = -ENOMEM; - goto err_3; - } - - astream_dev->dev.class = &astream_class; - astream_dev->dev.release = astream_release; - astream_dev->offset = 0; - dev_set_name(&astream_dev->dev, "astream-dev"); - - dev_set_drvdata(&astream_dev->dev, astream_dev); - - r = device_register(&astream_dev->dev); - if (r) { - pr_info("astream device register fail.\n"); - goto err_2; - } - - if (AM_MESON_CPU_MAJOR_ID_TXL < get_cpu_major_id()) { - node = of_find_node_by_path("/codec_io/io_cbus_base"); - if (!node) { - pr_info("No io_cbus_base node found."); - goto err_1; - } - -#ifdef CONFIG_ARM64_A32 - r = of_property_read_u32_index(node, "reg", 0, &cbus_base); -#else - r = of_property_read_u32_index(node, "reg", 1, &cbus_base); -#endif - if (r) { - pr_info("No find node.\n"); - goto err_1; - } - - /*need to offset -0x100 in txlx.*/ - astream_dev->offset = -0x100; - - /*need to offset -0x180 in g12a.*/ - if (AM_MESON_CPU_MAJOR_ID_G12A <= get_cpu_major_id()) { - astream_dev->offset = -0x180; - /* after G12A chip, the aobus base addr changed */ - astream_uio_info.mem[4].addr = IO_AOBUS_PHY_BASE_AFTER_G12A; - } - astream_uio_info.mem[0].addr = - (cbus_base + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL + - astream_dev->offset)) & (PAGE_MASK); - - astream_uio_info.mem[3].addr = - (cbus_base + CBUS_REG_OFFSET(ASSIST_HW_REV + - 0x100)) & (PAGE_MASK); - } - -#if 1 - if (uio_register_device(&astream_dev->dev, &astream_uio_info)) { - pr_info("astream UIO device register fail.\n"); - r = -ENODEV; - goto err_1; - } -#endif - INIT_REG_NODE_CONFIGS("media", &adec_node, - "adec", adec_configs, CONFIG_FOR_R); - return 0; - -err_1: - device_unregister(&astream_dev->dev); - -err_2: - kfree(astream_dev); - astream_dev = NULL; - -err_3: - class_unregister(&astream_class); - - return r; -} - -void astream_dev_unregister(void) -{ - if (astream_dev) { -#if 1 - uio_unregister_device(&astream_uio_info); -#endif - - device_unregister(&astream_dev->dev); - - class_unregister(&astream_class); - } -} diff --git a/drivers/amlogic/media_modules/stream_input/amports/adec.h b/drivers/amlogic/media_modules/stream_input/amports/adec.h deleted file mode 100644 index f06f73ad39b0..000000000000 --- a/drivers/amlogic/media_modules/stream_input/amports/adec.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/adec.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef ADEC_H -#define ADEC_H - -#include "../parser/streambuf.h" -#include - -extern s32 adec_init(struct stream_port_s *port); - -extern s32 adec_release(enum aformat_e af); - -extern s32 astream_dev_register(void); - -extern s32 astream_dev_unregister(void); - -#endif /* ADEC_H */ diff --git a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h deleted file mode 100644 index b09118d19057..000000000000 --- a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/amports_priv.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef AMPORTS_PRIV_HEAD_HH -#define AMPORTS_PRIV_HEAD_HH -#include "../parser/streambuf.h" -#include "../../common/media_clock/switch/amports_gate.h" -#include -#include -#include - -struct port_priv_s { - struct vdec_s *vdec; - struct stream_port_s *port; - struct mutex mutex; -}; - -struct stream_buf_s *get_buf_by_type(u32 type); - -/*video.c provide*/ -extern u32 trickmode_i; -struct amvideocap_req; -extern u32 set_blackout_policy(int policy); -extern u32 get_blackout_policy(void); -int calculation_stream_ext_delayed_ms(u8 type); -int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index); -int ext_put_video_frame(struct vframe_s *vf); -int ext_register_end_frame_callback(struct amvideocap_req *req); -int amstream_request_firmware_from_sys(const char *file_name, - char *buf, int size); -void set_vsync_pts_inc_mode(int inc); - -void set_real_audio_info(void *arg); -void amstream_wakeup_userdata_poll(struct vdec_s *vdec); -#define dbg() pr_info("on %s,line %d\n", __func__, __LINE__); - -struct device *amports_get_dma_device(void); -struct device *get_codec_cma_device(void); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream.c b/drivers/amlogic/media_modules/stream_input/amports/amstream.c deleted file mode 100644 index 2c0ae399013f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream.c +++ /dev/null @@ -1,4134 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/amstream.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ -#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -/* #include */ - -#include -#include -#include -#include -#include -#include -#include -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -/* #include */ -/* #include */ -#endif -#include "../parser/streambuf.h" -#include "../parser/streambuf_reg.h" -#include "../parser/tsdemux.h" -#include "../parser/psparser.h" -#include "../parser/esparser.h" -#include "../../frame_provider/decoder/utils/vdec.h" -#include "adec.h" -#include "../parser/rmparser.h" -#include "amports_priv.h" -#include -#include -#include "../parser/thread_rw.h" -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_COMPAT -#include -#endif -#include -#include -#include "../../frame_provider/decoder/utils/firmware.h" -#include "../../common/chips/chips.h" -#include "../../common/chips/decoder_cpu_ver_info.h" -#include "../subtitle/subtitle.h" - -//#define G12A_BRINGUP_DEBUG - -#define CONFIG_AM_VDEC_REAL //DEBUG_TMP - -#define DEVICE_NAME "amstream-dev" -#define DRIVER_NAME "amstream" -#define MODULE_NAME "amstream" - -#define MAX_AMSTREAM_PORT_NUM ARRAY_SIZE(ports) -u32 amstream_port_num; -u32 amstream_buf_num; - -u32 amstream_audio_reset = 0; - -#if 0 -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV -#define NO_VDEC2_INIT 1 -#elif MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD -#define NO_VDEC2_INIT IS_MESON_M8M2_CPU -#endif -#endif -#define NO_VDEC2_INIT 1 - -#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) -#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) -#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) -#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) - - -#define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2) -#define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256) - -static int def_4k_vstreambuf_sizeM = - (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); -static int def_vstreambuf_sizeM = - (DEFAULT_VIDEO_BUFFER_SIZE >> 20); -static int slow_input; - - - - -/* #define DATA_DEBUG */ -static int use_bufferlevelx10000 = 10000; -static int reset_canuse_buferlevel(int level); -static struct platform_device *amstream_pdev; -struct device *amports_get_dma_device(void) -{ - return &amstream_pdev->dev; -} -EXPORT_SYMBOL(amports_get_dma_device); - -#ifdef DATA_DEBUG -#include - -#define DEBUG_FILE_NAME "/sdcard/debug.tmp" -static struct file *debug_filp; -static loff_t debug_file_pos; - -void debug_file_write(const char __user *buf, size_t count) -{ - mm_segment_t old_fs; - - if (!debug_filp) - return; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (count != vfs_write(debug_filp, buf, count, &debug_file_pos)) - pr_err("Failed to write debug file\n"); - - set_fs(old_fs); -} -#endif - - - -static int amstream_open(struct inode *inode, struct file *file); -static int amstream_release(struct inode *inode, struct file *file); -static long amstream_ioctl(struct file *file, unsigned int cmd, ulong arg); -#ifdef CONFIG_COMPAT -static long amstream_compat_ioctl - (struct file *file, unsigned int cmd, ulong arg); -#endif -static ssize_t amstream_vbuf_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -static ssize_t amstream_vframe_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -static ssize_t amstream_abuf_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -static ssize_t amstream_mpts_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -static ssize_t amstream_mpps_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -static ssize_t amstream_sub_read -(struct file *file, char *buf, size_t count, loff_t *ppos); -static ssize_t amstream_sub_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -static unsigned int amstream_sub_poll -(struct file *file, poll_table *wait_table); -static unsigned int amstream_userdata_poll -(struct file *file, poll_table *wait_table); -static ssize_t amstream_userdata_read -(struct file *file, char *buf, size_t count, loff_t *ppos); -static int (*amstream_adec_status) -(struct adec_status *astatus); -#ifdef CONFIG_AM_VDEC_REAL -static ssize_t amstream_mprm_write -(struct file *file, const char *buf, size_t count, loff_t *ppos); -#endif - -static const struct file_operations vbuf_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .write = amstream_vbuf_write, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations vframe_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .write = amstream_vframe_write, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations abuf_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .write = amstream_abuf_write, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations mpts_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .write = amstream_mpts_write, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations mpps_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .write = amstream_mpps_write, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations mprm_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, -#ifdef CONFIG_AM_VDEC_REAL - .write = amstream_mprm_write, -#endif - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations sub_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .write = amstream_sub_write, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations sub_read_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .read = amstream_sub_read, - .poll = amstream_sub_poll, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations userdata_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .read = amstream_userdata_read, - .poll = amstream_userdata_poll, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -static const struct file_operations amstream_fops = { - .owner = THIS_MODULE, - .open = amstream_open, - .release = amstream_release, - .unlocked_ioctl = amstream_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amstream_compat_ioctl, -#endif -}; - -/**************************************************/ -static struct audio_info audio_dec_info; -static struct class *amstream_dev_class; -static DEFINE_MUTEX(amstream_mutex); - -atomic_t subdata_ready = ATOMIC_INIT(0); -static int sub_type; -static int sub_port_inited; -/* wait queue for poll */ -static wait_queue_head_t amstream_sub_wait; -atomic_t userdata_ready = ATOMIC_INIT(0); -static int userdata_length; -static wait_queue_head_t amstream_userdata_wait; -#define USERDATA_FIFO_NUM 1024 -static struct userdata_poc_info_t userdata_poc_info[USERDATA_FIFO_NUM]; -static int userdata_poc_ri, userdata_poc_wi; -static int last_read_wi; -static u32 ud_ready_vdec_flag; - - - -static DEFINE_MUTEX(userdata_mutex); - -static struct stream_port_s ports[] = { - { - .name = "amstream_vbuf", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO, - .fops = &vbuf_fops, - }, -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - { - .name = "amstream_vbuf_sched", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | - PORT_TYPE_DECODER_SCHED, - .fops = &vbuf_fops, - }, - { - .name = "amstream_vframe", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | - PORT_TYPE_FRAME | PORT_TYPE_DECODER_SCHED, - .fops = &vframe_fops, - }, -#endif - { - .name = "amstream_abuf", - .type = PORT_TYPE_ES | PORT_TYPE_AUDIO, - .fops = &abuf_fops, - }, - { - .name = "amstream_mpts", - .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO | - PORT_TYPE_AUDIO | PORT_TYPE_SUB, - .fops = &mpts_fops, - }, -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - { - .name = "amstream_mpts_sched", - .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO | - PORT_TYPE_AUDIO | PORT_TYPE_SUB | - PORT_TYPE_DECODER_SCHED, - .fops = &mpts_fops, - }, -#endif - { - .name = "amstream_mpps", - .type = PORT_TYPE_MPPS | PORT_TYPE_VIDEO | - PORT_TYPE_AUDIO | PORT_TYPE_SUB, - .fops = &mpps_fops, - }, - { - .name = "amstream_rm", - .type = PORT_TYPE_RM | PORT_TYPE_VIDEO | PORT_TYPE_AUDIO, - .fops = &mprm_fops, - }, - { - .name = "amstream_sub", - .type = PORT_TYPE_SUB, - .fops = &sub_fops, - }, - { - .name = "amstream_sub_read", - .type = PORT_TYPE_SUB_RD, - .fops = &sub_read_fops, - }, - { - .name = "amstream_userdata", - .type = PORT_TYPE_USERDATA, - .fops = &userdata_fops, - }, - { - .name = "amstream_hevc", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC, - .fops = &vbuf_fops, - .vformat = VFORMAT_HEVC, - }, -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - { - .name = "amstream_hevc_frame", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | - PORT_TYPE_FRAME | PORT_TYPE_DECODER_SCHED, - .fops = &vframe_fops, - .vformat = VFORMAT_HEVC, - }, - { - .name = "amstream_hevc_sched", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | - PORT_TYPE_DECODER_SCHED, - .fops = &vbuf_fops, - .vformat = VFORMAT_HEVC, - }, -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - { - .name = "amstream_dves_avc", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | - PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC, - .fops = &vbuf_fops, - }, - { - .name = "amstream_dves_hevc", - .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | - PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC, - .fops = &vbuf_fops, - .vformat = VFORMAT_HEVC, - }, -#endif -#endif -}; - -static struct stream_buf_s bufs[BUF_MAX_NUM] = { - { - .reg_base = VLD_MEM_VIFIFO_REG_BASE, - .type = BUF_TYPE_VIDEO, - .buf_start = 0, - .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, - .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = AIU_MEM_AIFIFO_REG_BASE, - .type = BUF_TYPE_AUDIO, - .buf_start = 0, - .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, - .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = 0, - .type = BUF_TYPE_SUBTITLE, - .buf_start = 0, - .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, - .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = 0, - .type = BUF_TYPE_USERDATA, - .buf_start = 0, - .buf_size = 0, - .first_tstamp = INVALID_PTS - }, - { - .reg_base = HEVC_STREAM_REG_BASE, - .type = BUF_TYPE_HEVC, - .buf_start = 0, - .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, - .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, - .first_tstamp = INVALID_PTS - }, -}; - -struct stream_buf_s *get_buf_by_type(u32 type) -{ - if (PTS_TYPE_VIDEO == type) - return &bufs[BUF_TYPE_VIDEO]; - if (PTS_TYPE_AUDIO == type) - return &bufs[BUF_TYPE_AUDIO]; - if (has_hevc_vdec()) { - if (PTS_TYPE_HEVC == type) - return &bufs[BUF_TYPE_HEVC]; - } - - return NULL; -} - -void set_sample_rate_info(int arg) -{ - audio_dec_info.sample_rate = arg; - audio_dec_info.valid = 1; -} - -void set_ch_num_info(int arg) -{ - audio_dec_info.channels = arg; -} - -struct audio_info *get_audio_info(void) -{ - return &audio_dec_info; -} -EXPORT_SYMBOL(get_audio_info); - -static void amstream_change_vbufsize(struct port_priv_s *priv, - struct stream_buf_s *pvbuf) -{ - if (pvbuf->buf_start != 0) { - pr_info("streambuf is alloced before\n"); - return; - } - if (pvbuf->for_4k) { - pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M; - if (priv->vdec->port_flag & PORT_FLAG_DRM) - pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP; - if ((pvbuf->buf_size > 30 * SZ_1M) && - (codec_mm_get_total_size() < 220 * SZ_1M)) { - /*if less than 250M, used 20M for 4K & 265*/ - pvbuf->buf_size = pvbuf->buf_size >> 1; - } - } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { - if (priv->vdec->port_flag & PORT_FLAG_DRM) - pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; - } else { - pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; - if (priv->vdec->port_flag & PORT_FLAG_DRM) - pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; - } - reset_canuse_buferlevel(10000); -} - -static bool port_get_inited(struct port_priv_s *priv) -{ - struct stream_port_s *port = priv->port; - - if (port->type & PORT_TYPE_VIDEO) { - struct vdec_s *vdec = priv->vdec; - - return vdec->port_flag & PORT_FLAG_INITED; - } - - return port->flag & PORT_FLAG_INITED; -} - -static void port_set_inited(struct port_priv_s *priv) -{ - struct stream_port_s *port = priv->port; - - if (port->type & PORT_TYPE_VIDEO) { - struct vdec_s *vdec = priv->vdec; - - vdec->port_flag |= PORT_FLAG_INITED; - } else - port->flag |= PORT_FLAG_INITED; -} - -static void video_port_release(struct port_priv_s *priv, - struct stream_buf_s *pbuf, int release_num) -{ - struct stream_port_s *port = priv->port; - struct vdec_s *vdec = priv->vdec; - struct vdec_s *slave = NULL; - bool is_multidec = !vdec_single(vdec); - - switch (release_num) { - default: - /*fallthrough*/ - case 0: /*release all */ - /*fallthrough*/ - case 4: - if ((port->type & PORT_TYPE_FRAME) == 0) - esparser_release(pbuf); - /*fallthrough*/ - case 3: - if (vdec->slave) - slave = vdec->slave; - vdec_release(vdec); - if (slave) - vdec_release(slave); - priv->vdec = NULL; - /*fallthrough*/ - case 2: - if ((port->type & PORT_TYPE_FRAME) == 0) - stbuf_release(pbuf, is_multidec); - /*fallthrough*/ - case 1: - ; - } -} - -static int video_port_init(struct port_priv_s *priv, - struct stream_buf_s *pbuf) -{ - int r; - struct stream_port_s *port = priv->port; - struct vdec_s *vdec = priv->vdec; - - if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { - pr_err("vformat not set\n"); - return -EPERM; - } - if (vdec_dual(vdec) && vdec_secure(vdec)) { - /*copy drm flags for slave dec.*/ - vdec->slave->port_flag |= PORT_FLAG_DRM; - } - if (port->vformat == VFORMAT_H264_4K2K || - (priv->vdec->sys_info->height * - priv->vdec->sys_info->width) > 1920*1088) { - pbuf->for_4k = 1; - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX - && port->vformat == VFORMAT_H264) { - vdec_poweron(VDEC_HEVC); - } - } else { - pbuf->for_4k = 0; - } - - if (port->type & PORT_TYPE_FRAME) { - r = vdec_init(vdec, - (priv->vdec->sys_info->height * - priv->vdec->sys_info->width) > 1920*1088); - if (r < 0) { - pr_err("video_port_init %d, vdec_init failed\n", - __LINE__); - video_port_release(priv, pbuf, 2); - return r; - } - - return 0; - } - - amstream_change_vbufsize(priv, pbuf); - - if (has_hevc_vdec()) { - if (port->type & PORT_TYPE_MPTS) { - if (pbuf->type == BUF_TYPE_HEVC) - vdec_poweroff(VDEC_1); - else - vdec_poweroff(VDEC_HEVC); - } - } - - r = stbuf_init(pbuf, vdec, false); - if (r < 0) { - pr_err("video_port_init %d, stbuf_init failed\n", __LINE__); - return r; - } - - /* todo: set path based on port flag */ - r = vdec_init(vdec, - (priv->vdec->sys_info->height * - priv->vdec->sys_info->width) > 1920*1088); - - if (r < 0) { - pr_err("video_port_init %d, vdec_init failed\n", __LINE__); - video_port_release(priv, pbuf, 2); - return r; - } - - if (vdec_dual(vdec)) { - r = vdec_init(vdec->slave, - (priv->vdec->sys_info->height * - priv->vdec->sys_info->width) > 1920*1088); - if (r < 0) { - pr_err("video_port_init %d, vdec_init failed\n", - __LINE__); - video_port_release(priv, pbuf, 2); - return r; - } - } - - if (port->type & PORT_TYPE_ES) { - r = esparser_init(pbuf, vdec); - if (r < 0) { - video_port_release(priv, pbuf, 3); - pr_err("esparser_init() failed\n"); - return r; - } - } - - pbuf->flag |= BUF_FLAG_IN_USE; - - return 0; -} - -static void audio_port_release(struct stream_port_s *port, - struct stream_buf_s *pbuf, int release_num) -{ - switch (release_num) { - default: - /*fallthrough*/ - case 0: /*release all */ - /*fallthrough*/ - case 4: - esparser_release(pbuf); - /*fallthrough*/ - case 3: - adec_release(port->vformat); - /*fallthrough*/ - case 2: - stbuf_release(pbuf, false); - /*fallthrough*/ - case 1: - ; - } - amstream_audio_reset = 0; - return; -} - -static int audio_port_reset(struct stream_port_s *port, - struct stream_buf_s *pbuf) -{ - int r; - - if ((port->flag & PORT_FLAG_AFORMAT) == 0) { - pr_err("aformat not set\n"); - return 0; - } - - pts_stop(PTS_TYPE_AUDIO); - - stbuf_release(pbuf, false); - - r = stbuf_init(pbuf, NULL, false); - if (r < 0) - return r; - - r = adec_init(port); - if (r < 0) { - audio_port_release(port, pbuf, 2); - return r; - } - - if (port->type & PORT_TYPE_ES) - esparser_audio_reset_s(pbuf); - - if (port->type & PORT_TYPE_MPTS) - tsdemux_audio_reset(); - - if (port->type & PORT_TYPE_MPPS) - psparser_audio_reset(); - -#ifdef CONFIG_AM_VDEC_REAL - if (port->type & PORT_TYPE_RM) - rm_audio_reset(); -#endif - - pbuf->flag |= BUF_FLAG_IN_USE; - amstream_audio_reset = 1; - - r = pts_start(PTS_TYPE_AUDIO); - - return r; -} - -static int sub_port_reset(struct stream_port_s *port, - struct stream_buf_s *pbuf) -{ - int r; - - port->flag &= (~PORT_FLAG_INITED); - - stbuf_release(pbuf, false); - - r = stbuf_init(pbuf, NULL, false); - if (r < 0) - return r; - - if (port->type & PORT_TYPE_MPTS) - tsdemux_sub_reset(); - - if (port->type & PORT_TYPE_MPPS) - psparser_sub_reset(); - - if (port->sid == 0xffff) { /* es sub */ - esparser_sub_reset(); - pbuf->flag |= BUF_FLAG_PARSER; - } - - pbuf->flag |= BUF_FLAG_IN_USE; - - port->flag |= PORT_FLAG_INITED; - - return 0; -} - -static int audio_port_init(struct stream_port_s *port, - struct stream_buf_s *pbuf) -{ - int r; - - if ((port->flag & PORT_FLAG_AFORMAT) == 0) { - pr_err("aformat not set\n"); - return 0; - } - - r = stbuf_init(pbuf, NULL, false); - if (r < 0) - return r; - r = adec_init(port); - if (r < 0) { - audio_port_release(port, pbuf, 2); - return r; - } - if (port->type & PORT_TYPE_ES) { - r = esparser_init(pbuf, NULL); - if (r < 0) { - audio_port_release(port, pbuf, 3); - return r; - } - } - pbuf->flag |= BUF_FLAG_IN_USE; - return 0; -} - -static void sub_port_release(struct stream_port_s *port, - struct stream_buf_s *pbuf) -{ - if ((port->sid == 0xffff) && - ((port->type & (PORT_TYPE_MPPS | PORT_TYPE_MPTS)) == 0)) { - /* this is es sub */ - esparser_release(pbuf); - } - stbuf_release(pbuf, false); - sub_port_inited = 0; -} - -static int sub_port_init(struct stream_port_s *port, struct stream_buf_s *pbuf) -{ - int r; - r = stbuf_init(pbuf, NULL, false); - if (r < 0) - return r; - if ((port->flag & PORT_FLAG_SID) == 0) { - pr_err("subtitle id not set\n"); - return 0; - } - - if ((port->sid == 0xffff) && - ((port->type & (PORT_TYPE_MPPS | PORT_TYPE_MPTS)) == 0)) { - /* es sub */ - r = esparser_init(pbuf, NULL); - if (r < 0) { - sub_port_release(port, pbuf); - return r; - } - } - - sub_port_inited = 1; - return 0; -} - -static void amstream_user_buffer_init(void) -{ - struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA]; - - pubuf->buf_size = 0; - pubuf->buf_start = 0; - pubuf->buf_wp = 0; - pubuf->buf_rp = 0; -} - -static int amstream_port_init(struct port_priv_s *priv) -{ - int r = 0; - struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - struct stream_port_s *port = priv->port; - struct vdec_s *vdec = priv->vdec; - - mutex_lock(&amstream_mutex); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { - r = check_efuse_chip(port->vformat); - if (r) { - pr_info("No support video format %d.\n", port->vformat); - mutex_unlock(&amstream_mutex); - return 0; - } - } - - /* try to reload the fw.*/ - r = video_fw_reload(FW_LOAD_TRY); - if (r) - pr_err("the firmware reload fail.\n"); - - stbuf_fetch_init(); - - amstream_user_buffer_init(); - - if (port_get_inited(priv)) { - mutex_unlock(&amstream_mutex); - return 0; - } - - if ((port->type & PORT_TYPE_AUDIO) && - (port->flag & PORT_FLAG_AFORMAT)) { - r = audio_port_init(port, pabuf); - if (r < 0) { - pr_err("audio_port_init failed\n"); - goto error1; - } - } - - if ((port->type & PORT_TYPE_VIDEO) && - (vdec->port_flag & PORT_FLAG_VFORMAT)) { - pvbuf->for_4k = 0; - if (has_hevc_vdec()) { - if (port->vformat == VFORMAT_HEVC || - port->vformat == VFORMAT_AVS2 || - port->vformat == VFORMAT_VP9) - pvbuf = &bufs[BUF_TYPE_HEVC]; - } - mutex_lock(&priv->mutex); - r = video_port_init(priv, pvbuf); - if (r < 0) { - mutex_unlock(&priv->mutex); - pr_err("video_port_init failed\n"); - goto error2; - } - mutex_unlock(&priv->mutex); - } - - if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) { - r = sub_port_init(port, psbuf); - if (r < 0) { - pr_err("sub_port_init failed\n"); - goto error3; - } - } - - if (port->type & PORT_TYPE_MPTS) { - if (has_hevc_vdec()) { - r = tsdemux_init( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, - (port->pcr_inited == 1) ? port->pcrid : 0xffff, - (port->vformat == VFORMAT_HEVC) || - (port->vformat == VFORMAT_AVS2) || - (port->vformat == VFORMAT_VP9), - vdec); - } else { - r = tsdemux_init( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, - (port->pcr_inited == 1) ? port->pcrid : 0xffff, - 0, - vdec); - } - - if (r < 0) { - pr_err("tsdemux_init failed\n"); - goto error4; - } - tsync_pcr_start(); - } - if (port->type & PORT_TYPE_MPPS) { - r = psparser_init( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, - priv->vdec); - if (r < 0) { - pr_err("psparser_init failed\n"); - goto error5; - } - } -#ifdef CONFIG_AM_VDEC_REAL - if (port->type & PORT_TYPE_RM) { - rm_set_vasid( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); - } -#endif -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ - if (!NO_VDEC2_INIT) { - if ((port->type & PORT_TYPE_VIDEO) - && (port->vformat == VFORMAT_H264_4K2K)) - stbuf_vdec2_init(pvbuf); - } -#endif - - if ((port->type & PORT_TYPE_VIDEO) && - (vdec->port_flag & PORT_FLAG_VFORMAT)) - /* connect vdec at the end after all HW initialization */ - vdec_connect(vdec); - - tsync_audio_break(0); /* clear audio break */ - set_vsync_pts_inc_mode(0); /* clear video inc */ - - port_set_inited(priv); - - mutex_unlock(&amstream_mutex); - return 0; - /*errors follow here */ -error5: - tsdemux_release(); -error4: - sub_port_release(port, psbuf); -error3: - video_port_release(priv, pvbuf, 0); -error2: - audio_port_release(port, pabuf, 0); -error1: - mutex_unlock(&amstream_mutex); - return r; -} - -static int amstream_port_release(struct port_priv_s *priv) -{ - struct stream_port_s *port = priv->port; - struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - - if (has_hevc_vdec()) { - if (port->vformat == VFORMAT_HEVC - || port->vformat == VFORMAT_AVS2 - || port->vformat == VFORMAT_VP9) - pvbuf = &bufs[BUF_TYPE_HEVC]; - } - - if (port->type & PORT_TYPE_MPTS) { - vdec_disconnect(priv->vdec); - tsync_pcr_stop(); - tsdemux_release(); - } - - if (port->type & PORT_TYPE_MPPS) - psparser_release(); - - if (port->type & PORT_TYPE_VIDEO) - video_port_release(priv, pvbuf, 0); - - if (port->type & PORT_TYPE_AUDIO) - audio_port_release(port, pabuf, 0); - - if (port->type & PORT_TYPE_SUB) - sub_port_release(port, psbuf); - - port->pcr_inited = 0; - port->flag = 0; - return 0; -} - -static void amstream_change_avid(struct stream_port_s *port) -{ - if (port->type & PORT_TYPE_MPTS) { - tsdemux_change_avid( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); - } - - if (port->type & PORT_TYPE_MPPS) { - psparser_change_avid( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); - } - -#ifdef CONFIG_AM_VDEC_REAL - if (port->type & PORT_TYPE_RM) { - rm_set_vasid( - (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); - } -#endif -} - -static void amstream_change_sid(struct stream_port_s *port) -{ - if (port->type & PORT_TYPE_MPTS) { - tsdemux_change_sid( - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff); - } - - if (port->type & PORT_TYPE_MPPS) { - psparser_change_sid( - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff); - } -} - -/**************************************************/ -static ssize_t amstream_vbuf_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - struct stream_buf_s *pbuf = NULL; - int r; - if (has_hevc_vdec()) { - pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : - &bufs[BUF_TYPE_VIDEO]; - } else - pbuf = &bufs[BUF_TYPE_VIDEO]; - - if (!(port_get_inited(priv))) { - r = amstream_port_init(priv); - if (r < 0) - return r; - } - - if (priv->vdec->port_flag & PORT_FLAG_DRM) - r = drm_write(file, pbuf, buf, count); - else - r = esparser_write(file, pbuf, buf, count); - if (slow_input) { - pr_info("slow_input: es codec write size %x\n", r); - msleep(3000); - } -#ifdef DATA_DEBUG - debug_file_write(buf, r); -#endif - - return r; -} - -static ssize_t amstream_vframe_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - ssize_t ret; - int wait_max_cnt = 5; -#ifdef DATA_DEBUG - debug_file_write(buf, count); -#endif - do { - ret = vdec_write_vframe(priv->vdec, buf, count); - if (file->f_flags & O_NONBLOCK) { - break;/*alway return for no block mode.*/ - } else if (ret == -EAGAIN) { - int level; - level = vdec_input_level(&priv->vdec->input); - if (wait_max_cnt-- < 0) - break; - msleep(20); - } - } while (ret == -EAGAIN); - return ret; -} - -static ssize_t amstream_abuf_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - struct stream_buf_s *pbuf = &bufs[BUF_TYPE_AUDIO]; - int r; - - if (!(port_get_inited(priv))) { - r = amstream_port_init(priv); - if (r < 0) - return r; - } - - if (port->flag & PORT_FLAG_DRM) - r = drm_write(file, pbuf, buf, count); - else - r = esparser_write(file, pbuf, buf, count); - - return r; -} - -static ssize_t amstream_mpts_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - struct stream_buf_s *pvbuf = NULL; - int r = 0; - - if (has_hevc_vdec()) { - pvbuf = (port->vformat == VFORMAT_HEVC || - port->vformat == VFORMAT_AVS2 || - port->vformat == VFORMAT_VP9) ? - &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; - } else - pvbuf = &bufs[BUF_TYPE_VIDEO]; - - if (!(port_get_inited(priv))) { - r = amstream_port_init(priv); - if (r < 0) - return r; - } -#ifdef DATA_DEBUG - debug_file_write(buf, count); -#endif - if (port->flag & PORT_FLAG_DRM) - r = drm_tswrite(file, pvbuf, pabuf, buf, count); - else - r = tsdemux_write(file, pvbuf, pabuf, buf, count); - if (slow_input) { - pr_info("slow_input: ts codec write size %x\n", r); - msleep(3000); - } - return r; -} - -static ssize_t amstream_mpps_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - int r; - - if (!(port_get_inited(priv))) { - r = amstream_port_init(priv); - if (r < 0) - return r; - } - return psparser_write(file, pvbuf, pabuf, buf, count); -} - -#ifdef CONFIG_AM_VDEC_REAL -static ssize_t amstream_mprm_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - int r; - - if (!(port_get_inited(priv))) { - r = amstream_port_init(priv); - if (r < 0) - return r; - } - return rmparser_write(file, pvbuf, pabuf, buf, count); -} -#endif - -static ssize_t amstream_sub_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - u32 sub_rp, sub_wp, sub_start, data_size, res; - struct stream_buf_s *s_buf = &bufs[BUF_TYPE_SUBTITLE]; - - if (sub_port_inited == 0) - return 0; - - sub_rp = stbuf_sub_rp_get(); - sub_wp = stbuf_sub_wp_get(); - sub_start = stbuf_sub_start_get(); - - if (sub_wp == sub_rp || sub_rp == 0) - return 0; - - if (sub_wp > sub_rp) - data_size = sub_wp - sub_rp; - else - data_size = s_buf->buf_size - sub_rp + sub_wp; - - if (data_size > count) - data_size = count; - - if (sub_wp < sub_rp) { - int first_num = s_buf->buf_size - (sub_rp - sub_start); - - if (data_size <= first_num) { - res = copy_to_user((void *)buf, - (void *)(codec_mm_phys_to_virt(sub_rp)), - data_size); - stbuf_sub_rp_set(sub_rp + data_size - res); - - return data_size - res; - } else { - if (first_num > 0) { - res = copy_to_user((void *)buf, - (void *)(codec_mm_phys_to_virt(sub_rp)), - first_num); - stbuf_sub_rp_set(sub_rp + first_num - - res); - - return first_num - res; - } - - res = copy_to_user((void *)buf, - (void *)(codec_mm_phys_to_virt(sub_start)), - data_size - first_num); - - stbuf_sub_rp_set(sub_start + data_size - - first_num - res); - - return data_size - first_num - res; - } - } else { - res = - copy_to_user((void *)buf, - (void *)(codec_mm_phys_to_virt(sub_rp)), - data_size); - - stbuf_sub_rp_set(sub_rp + data_size - res); - - return data_size - res; - } -} - -static ssize_t amstream_sub_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_buf_s *pbuf = &bufs[BUF_TYPE_SUBTITLE]; - int r; - - if (!(port_get_inited(priv))) { - r = amstream_port_init(priv); - if (r < 0) - return r; - } - r = esparser_write(file, pbuf, buf, count); - if (r < 0) - return r; - - wakeup_sub_poll(); - - return r; -} - -static unsigned int amstream_sub_poll(struct file *file, - poll_table *wait_table) -{ - poll_wait(file, &amstream_sub_wait, wait_table); - - if (atomic_read(&subdata_ready)) { - atomic_dec(&subdata_ready); - return POLLOUT | POLLWRNORM; - } - - return 0; -} - -static void set_userdata_poc(struct userdata_poc_info_t poc) -{ - userdata_poc_info[userdata_poc_wi] = poc; - userdata_poc_wi++; - if (userdata_poc_wi == USERDATA_FIFO_NUM) - userdata_poc_wi = 0; -} -EXPORT_SYMBOL(set_userdata_poc); - -void init_userdata_fifo(void) -{ - userdata_poc_ri = 0; - userdata_poc_wi = 0; - userdata_length = 0; -} -EXPORT_SYMBOL(init_userdata_fifo); - -void reset_userdata_fifo(int bInit) -{ - struct stream_buf_s *userdata_buf; - int wi, ri; - u32 rp, wp; - - mutex_lock(&userdata_mutex); - - wi = userdata_poc_wi; - ri = userdata_poc_ri; - - userdata_buf = &bufs[BUF_TYPE_USERDATA]; - rp = userdata_buf->buf_rp; - wp = userdata_buf->buf_wp; - if (bInit) { - /* decoder reset */ - userdata_buf->buf_rp = 0; - userdata_buf->buf_wp = 0; - userdata_poc_ri = 0; - userdata_poc_wi = 0; - } else { - /* just clean fifo buffer */ - userdata_buf->buf_rp = userdata_buf->buf_wp; - userdata_poc_ri = userdata_poc_wi; - } - userdata_length = 0; - last_read_wi = userdata_poc_wi; - - mutex_unlock(&userdata_mutex); - pr_debug("reset_userdata_fifo, bInit=%d, wi=%d, ri=%d, rp=%d, wp=%d\n", - bInit, wi, ri, rp, wp); -} -EXPORT_SYMBOL(reset_userdata_fifo); - -int wakeup_userdata_poll(struct userdata_poc_info_t poc, - int wp, - unsigned long start_phyaddr, - int buf_size, - int data_length) -{ - struct stream_buf_s *userdata_buf = &bufs[BUF_TYPE_USERDATA]; - mutex_lock(&userdata_mutex); - - if (data_length & 0x7) - data_length = (((data_length + 8) >> 3) << 3); - set_userdata_poc(poc); - userdata_buf->buf_start = start_phyaddr; - userdata_buf->buf_wp = wp; - userdata_buf->buf_size = buf_size; - atomic_set(&userdata_ready, 1); - userdata_length += data_length; - mutex_unlock(&userdata_mutex); - - wake_up_interruptible(&amstream_userdata_wait); - return userdata_buf->buf_rp; -} -EXPORT_SYMBOL(wakeup_userdata_poll); - - -void amstream_wakeup_userdata_poll(struct vdec_s *vdec) -{ - int vdec_id; - - vdec_id = vdec->id; - if (vdec_id > 31) { - pr_info("Error, not support so many instances(%d) user data push\n", - vdec_id); - return; - } - - mutex_lock(&userdata_mutex); - ud_ready_vdec_flag |= (1<buf_wp; - buf_rp = userdata_buf->buf_rp; - buf_size = userdata_buf->buf_size; - buf_start = userdata_buf->buf_start; -#ifdef DEBUG_USER_DATA - old_wi = last_read_wi; -#endif - last_read_wi = userdata_poc_wi; - mutex_unlock(&userdata_mutex); - - if (buf_start == 0 || buf_size == 0) - return 0; - if (buf_wp == buf_rp) - return 0; - if (buf_wp > buf_rp) - data_size = buf_wp - buf_rp; - else - data_size = buf_size - buf_rp + buf_wp; - - if (data_size > count) - data_size = count; -#ifdef DEBUG_USER_DATA - pr_info("wi:%d ri:%d wp:%d rp:%d size:%d, last_read_wi=%d\n", - userdata_poc_wi, userdata_poc_ri, - buf_wp, buf_rp, data_size, old_wi); -#endif - if (buf_wp < buf_rp) { - int first_num = buf_size - buf_rp; - if (data_size <= first_num) { - res = copy_to_user((void *)buf, - (void *)((buf_rp + - buf_start)), data_size); - if (res) - pr_info("p1 read not end res=%d, request=%d\n", - res, data_size); - - mutex_lock(&userdata_mutex); - userdata_buf->buf_rp += data_size - res; - mutex_unlock(&userdata_mutex); - retVal = data_size - res; - } else { - if (first_num > 0) { - res = copy_to_user((void *)buf, - (void *)((buf_rp + - buf_start)), first_num); - if (res) - pr_info("p2 read not end res=%d, request=%d\n", - res, first_num); - - res = copy_to_user((void *)buf+first_num, - (void *)(buf_start), - data_size - first_num); - - if (res) - pr_info("p3 read not end res=%d, request=%d\n", - res, data_size - first_num); - - mutex_lock(&userdata_mutex); - userdata_buf->buf_rp += data_size; - if (userdata_buf->buf_rp >= buf_size) - userdata_buf->buf_rp = - userdata_buf->buf_rp - buf_size; - mutex_unlock(&userdata_mutex); - - retVal = data_size; - } else { - /* first_num == 0*/ - res = copy_to_user((void *)buf, - (void *)((buf_start)), - data_size - first_num); - mutex_lock(&userdata_mutex); - userdata_buf->buf_rp = - data_size - first_num - res; - mutex_unlock(&userdata_mutex); - retVal = data_size - first_num - res; - } - } - } else { - res = copy_to_user((void *)buf, - (void *)((buf_rp + buf_start)), - data_size); - if (res) - pr_info("p4 read not end res=%d, request=%d\n", - res, data_size); - - mutex_lock(&userdata_mutex); - userdata_buf->buf_rp += data_size - res; - mutex_unlock(&userdata_mutex); - retVal = data_size - res; - } - return retVal; -} - -static int amstream_open(struct inode *inode, struct file *file) -{ - s32 i; - struct stream_port_s *s; - struct stream_port_s *port = &ports[iminor(inode)]; - struct port_priv_s *priv; -#ifdef G12A_BRINGUP_DEBUG - if (vdec_get_debug_flags() & 0xff0000) { - pr_info("%s force open port %d\n", - __func__, - ((vdec_get_debug_flags() >> 16) & 0xff) - 1); - port = &ports[((vdec_get_debug_flags() >> 16) & 0xff) - 1]; - } - pr_info("%s, port name %s\n", __func__, port->name); -#endif - if (iminor(inode) >= amstream_port_num) - return -ENODEV; - - mutex_lock(&amstream_mutex); - - if (port->type & PORT_TYPE_VIDEO) { - for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) { - if ((!is_mult_inc(s->type)) && - (s->type & PORT_TYPE_VIDEO) && - (s->flag & PORT_FLAG_IN_USE)) { - mutex_unlock(&amstream_mutex); - return -EBUSY; - } - } - } - - if ((port->flag & PORT_FLAG_IN_USE) && - ((port->type & PORT_TYPE_FRAME) == 0)) { - mutex_unlock(&amstream_mutex); - return -EBUSY; - } - - /* check other ports conflicts for audio */ - for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) { - if ((s->flag & PORT_FLAG_IN_USE) && - ((port->type) & (s->type) & PORT_TYPE_AUDIO)) { - mutex_unlock(&amstream_mutex); - return -EBUSY; - } - } - - priv = kzalloc(sizeof(struct port_priv_s), GFP_KERNEL); - if (priv == NULL) { - mutex_unlock(&amstream_mutex); - return -ENOMEM; - } - - mutex_init(&priv->mutex); - - priv->port = port; - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /* TODO: mod gate */ - /* switch_mod_gate_by_name("demux", 1); */ - amports_switch_gate("demux", 1); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - /* TODO: clc gate */ - /* CLK_GATE_ON(HIU_PARSER_TOP); */ - amports_switch_gate("parser_top", 1); - } - - if (port->type & PORT_TYPE_VIDEO) { - /* TODO: mod gate */ - /* switch_mod_gate_by_name("vdec", 1); */ - amports_switch_gate("vdec", 1); - - if (has_hevc_vdec()) { - if (port->type & - (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) - vdec_poweron(VDEC_HEVC); - - if ((port->type & PORT_TYPE_HEVC) == 0) - vdec_poweron(VDEC_1); - } else { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) - vdec_poweron(VDEC_1); - } - } - - if (port->type & PORT_TYPE_AUDIO) { - /* TODO: mod gate */ - /* switch_mod_gate_by_name("audio", 1); */ - amports_switch_gate("audio", 1); - } - } - - port->vid = 0; - port->aid = 0; - port->sid = 0; - port->pcrid = 0xffff; - file->f_op = port->fops; - file->private_data = priv; - - port->flag = PORT_FLAG_IN_USE; - port->pcr_inited = 0; -#ifdef DATA_DEBUG - debug_filp = filp_open(DEBUG_FILE_NAME, O_WRONLY, 0); - if (IS_ERR(debug_filp)) { - pr_err("amstream: open debug file failed\n"); - debug_filp = NULL; - } -#endif - mutex_unlock(&amstream_mutex); - - if (port->type & PORT_TYPE_VIDEO) { - priv->vdec = vdec_create(port, NULL); - - if (priv->vdec == NULL) { - port->flag = 0; - kfree(priv); - pr_err("amstream: vdec creation failed\n"); - return -ENOMEM; - } - - if ((port->type & PORT_TYPE_DUALDEC) || - (vdec_get_debug_flags() & 0x100)) { - priv->vdec->slave = vdec_create(port, priv->vdec); - - if (priv->vdec->slave == NULL) { - vdec_release(priv->vdec); - port->flag = 0; - kfree(priv); - pr_err("amstream: sub vdec creation failed\n"); - return -ENOMEM; - } - } - } - return 0; -} - -static int amstream_release(struct inode *inode, struct file *file) -{ - struct port_priv_s *priv = file->private_data; - struct stream_port_s *port = priv->port; - struct vdec_s *slave = NULL; -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - u32 port_flag = 0; -#endif - - if (iminor(inode) >= amstream_port_num) - return -ENODEV; - - mutex_lock(&amstream_mutex); - - if (port_get_inited(priv)) - amstream_port_release(priv); - - if (priv->vdec) { -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - port_flag = priv->vdec->port_flag; -#endif - if (priv->vdec->slave) - slave = priv->vdec->slave; - vdec_release(priv->vdec); - if (slave) - vdec_release(slave); - priv->vdec = NULL; - } - - if ((port->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == - PORT_TYPE_AUDIO) { - s32 i; - struct stream_port_s *s; - - for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) { - if ((s->flag & PORT_FLAG_IN_USE) - && (s->type & PORT_TYPE_VIDEO)) - break; - } - if (i == amstream_port_num) - timestamp_firstvpts_set(0); - } - port->flag = 0; - - /* timestamp_pcrscr_set(0); */ - -#ifdef DATA_DEBUG - if (debug_filp) { - filp_close(debug_filp, current->files); - debug_filp = NULL; - debug_file_pos = 0; - } -#endif - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - if (port->type & PORT_TYPE_VIDEO) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { -#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (has_hevc_vdec()) - vdec_poweroff(VDEC_HEVC); - - vdec_poweroff(VDEC_1); -#else - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX - && port->vformat == VFORMAT_H264 - && bufs[BUF_TYPE_VIDEO].for_4k) - vdec_poweroff(VDEC_HEVC); - - if ((port->vformat == VFORMAT_HEVC - || port->vformat == VFORMAT_AVS2 - || port->vformat == VFORMAT_VP9)) { - vdec_poweroff(VDEC_HEVC); - } else { - vdec_poweroff(VDEC_1); - } -#endif - } - /* TODO: mod gate */ - /* switch_mod_gate_by_name("vdec", 0); */ - amports_switch_gate("vdec", 0); - } - - if (port->type & PORT_TYPE_AUDIO) { - /* TODO: mod gate */ - /* switch_mod_gate_by_name("audio", 0); */ - /* amports_switch_gate("audio", 0); */ - } - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - /* TODO: clc gate */ - /* CLK_GATE_OFF(HIU_PARSER_TOP); */ - amports_switch_gate("parser_top", 0); - } - /* TODO: mod gate */ - /* switch_mod_gate_by_name("demux", 0); */ - amports_switch_gate("demux", 0); - } - - mutex_destroy(&priv->mutex); - - kfree(priv); - - mutex_unlock(&amstream_mutex); - return 0; -} - -static long amstream_ioctl_get_version(struct port_priv_s *priv, - ulong arg) -{ - int version = (AMSTREAM_IOC_VERSION_FIRST & 0xffff) << 16 - | (AMSTREAM_IOC_VERSION_SECOND & 0xffff); - put_user(version, (u32 __user *)arg); - - return 0; -} -static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg) -{ - struct stream_port_s *this = priv->port; - long r = 0; - - struct am_ioctl_parm parm; - - if (copy_from_user - ((void *)&parm, (void *)arg, - sizeof(parm))) - r = -EFAULT; - - switch (parm.cmd) { - case AMSTREAM_GET_SUB_LENGTH: - if ((this->type & PORT_TYPE_SUB) || - (this->type & PORT_TYPE_SUB_RD)) { - u32 sub_wp, sub_rp; - struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - int val; - - sub_wp = stbuf_sub_wp_get(); - sub_rp = stbuf_sub_rp_get(); - - if (sub_wp == sub_rp) - val = 0; - else if (sub_wp > sub_rp) - val = sub_wp - sub_rp; - else - val = psbuf->buf_size - (sub_rp - sub_wp); - parm.data_32 = val; - } else - r = -EINVAL; - break; - case AMSTREAM_GET_UD_LENGTH: - if (this->type & PORT_TYPE_USERDATA) { - parm.data_32 = userdata_length; - userdata_length = 0; - } else - r = -EINVAL; - break; - case AMSTREAM_GET_APTS_LOOKUP: - if (this->type & PORT_TYPE_AUDIO) { - u32 pts = 0, frame_size, offset; - - offset = parm.data_32; - pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, - &frame_size, 300); - parm.data_32 = pts; - } - break; - case AMSTREAM_GET_FIRST_APTS_FLAG: - if (this->type & PORT_TYPE_AUDIO) { - parm.data_32 = first_pts_checkin_complete( - PTS_TYPE_AUDIO); - } - break; - case AMSTREAM_GET_APTS: - parm.data_32 = timestamp_apts_get(); - break; - case AMSTREAM_GET_VPTS: - parm.data_32 = timestamp_vpts_get(); - break; - case AMSTREAM_GET_PCRSCR: - parm.data_32 = timestamp_pcrscr_get(); - break; - case AMSTREAM_GET_LAST_CHECKIN_APTS: - parm.data_32 = get_last_checkin_pts(PTS_TYPE_AUDIO); - break; - case AMSTREAM_GET_LAST_CHECKIN_VPTS: - parm.data_32 = get_last_checkin_pts(PTS_TYPE_VIDEO); - break; - case AMSTREAM_GET_LAST_CHECKOUT_APTS: - parm.data_32 = get_last_checkout_pts(PTS_TYPE_AUDIO); - break; - case AMSTREAM_GET_LAST_CHECKOUT_VPTS: - parm.data_32 = get_last_checkout_pts(PTS_TYPE_VIDEO); - break; - case AMSTREAM_GET_SUB_NUM: - parm.data_32 = psparser_get_sub_found_num(); - break; - case AMSTREAM_GET_VIDEO_DELAY_LIMIT_MS: - parm.data_32 = bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms; - break; - case AMSTREAM_GET_AUDIO_DELAY_LIMIT_MS: - parm.data_32 = bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms; - break; - case AMSTREAM_GET_VIDEO_CUR_DELAY_MS: { - int delay; - - delay = calculation_stream_delayed_ms( - PTS_TYPE_VIDEO, NULL, NULL); - if (delay >= 0) - parm.data_32 = delay; - else - parm.data_32 = 0; - } - break; - - case AMSTREAM_GET_AUDIO_CUR_DELAY_MS: { - int delay; - - delay = calculation_stream_delayed_ms( - PTS_TYPE_AUDIO, NULL, NULL); - if (delay >= 0) - parm.data_32 = delay; - else - parm.data_32 = 0; - } - break; - case AMSTREAM_GET_AUDIO_AVG_BITRATE_BPS: { - int delay; - u32 avgbps; - - delay = calculation_stream_delayed_ms( - PTS_TYPE_AUDIO, NULL, &avgbps); - if (delay >= 0) - parm.data_32 = avgbps; - else - parm.data_32 = 0; - } - break; - case AMSTREAM_GET_VIDEO_AVG_BITRATE_BPS: { - int delay; - u32 avgbps; - - delay = calculation_stream_delayed_ms( - PTS_TYPE_VIDEO, NULL, &avgbps); - if (delay >= 0) - parm.data_32 = avgbps; - else - parm.data_32 = 0; - } - break; - case AMSTREAM_GET_ION_ID: - parm.data_32 = priv->vdec->vf_receiver_inst; - break; - case AMSTREAM_GET_NEED_MORE_DATA: - parm.data_32 = vdec_need_more_data(priv->vdec); - break; - case AMSTREAM_GET_FREED_HANDLE: - parm.data_32 = vdec_input_get_freed_handle(priv->vdec); - break; - default: - r = -ENOIOCTLCMD; - break; - } - /* pr_info("parm size:%d\n", sizeof(parm)); */ - if (r == 0) { - if (copy_to_user((void *)arg, &parm, sizeof(parm))) - r = -EFAULT; - } - - return r; - -} -static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) -{ - struct stream_port_s *this = priv->port; - struct am_ioctl_parm parm; - long r = 0; - - if (copy_from_user - ((void *)&parm, (void *)arg, - sizeof(parm))) - r = -EFAULT; - - switch (parm.cmd) { - case AMSTREAM_SET_VB_START: - if ((this->type & PORT_TYPE_VIDEO) && - ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { - if (has_hevc_vdec()) - bufs[BUF_TYPE_HEVC].buf_start = parm.data_32; - bufs[BUF_TYPE_VIDEO].buf_start = parm.data_32; - } else - r = -EINVAL; - break; - case AMSTREAM_SET_VB_SIZE: - if ((this->type & PORT_TYPE_VIDEO) && - ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { - if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) { - if (has_hevc_vdec()) { - r = stbuf_change_size( - &bufs[BUF_TYPE_HEVC], - parm.data_32, - false); - } - r += stbuf_change_size( - &bufs[BUF_TYPE_VIDEO], - parm.data_32, - false); - } - } else if (this->type & PORT_TYPE_FRAME) { - /* todo: frame based set max buffer size */ - r = 0; - } else - r = -EINVAL; - break; - case AMSTREAM_SET_AB_START: - if ((this->type & PORT_TYPE_AUDIO) && - ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) - bufs[BUF_TYPE_AUDIO].buf_start = parm.data_32; - else - r = -EINVAL; - break; - case AMSTREAM_SET_AB_SIZE: - if ((this->type & PORT_TYPE_AUDIO) && - ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) { - if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) { - r = stbuf_change_size( - &bufs[BUF_TYPE_AUDIO], - parm.data_32, - false); - } - } else - r = -EINVAL; - break; - case AMSTREAM_SET_VFORMAT: - if ((this->type & PORT_TYPE_VIDEO) && - (parm.data_vformat < VFORMAT_MAX)) { - this->vformat = parm.data_vformat; - this->flag |= PORT_FLAG_VFORMAT; - - vdec_set_format(priv->vdec, this->vformat); - } else - r = -EINVAL; - break; - case AMSTREAM_SET_AFORMAT: - if ((this->type & PORT_TYPE_AUDIO) && - (parm.data_aformat < AFORMAT_MAX)) { - memset(&audio_dec_info, 0, - sizeof(struct audio_info)); - /* for new format,reset the audio info. */ - this->aformat = parm.data_aformat; - this->flag |= PORT_FLAG_AFORMAT; - } else - r = -EINVAL; - break; - case AMSTREAM_SET_VID: - if (this->type & PORT_TYPE_VIDEO) { - this->vid = parm.data_32; - this->flag |= PORT_FLAG_VID; - } else - r = -EINVAL; - - break; - case AMSTREAM_SET_AID: - if (this->type & PORT_TYPE_AUDIO) { - this->aid = parm.data_32; - this->flag |= PORT_FLAG_AID; - - if (port_get_inited(priv)) { - tsync_audio_break(1); - amstream_change_avid(this); - } - } else - r = -EINVAL; - break; - case AMSTREAM_SET_SID: - if (this->type & PORT_TYPE_SUB) { - this->sid = parm.data_32; - this->flag |= PORT_FLAG_SID; - - if (port_get_inited(priv)) - amstream_change_sid(this); - } else - r = -EINVAL; - - break; - case AMSTREAM_IOC_PCRID: - this->pcrid = parm.data_32; - this->pcr_inited = 1; - pr_err("set pcrid = 0x%x\n", this->pcrid); - break; - case AMSTREAM_SET_ACHANNEL: - if (this->type & PORT_TYPE_AUDIO) { - this->achanl = parm.data_32; - set_ch_num_info(parm.data_32); - } else - r = -EINVAL; - break; - case AMSTREAM_SET_SAMPLERATE: - if (this->type & PORT_TYPE_AUDIO) { - this->asamprate = parm.data_32; - set_sample_rate_info(parm.data_32); - } else - r = -EINVAL; - break; - case AMSTREAM_SET_DATAWIDTH: - if (this->type & PORT_TYPE_AUDIO) - this->adatawidth = parm.data_32; - else - r = -EINVAL; - break; - case AMSTREAM_SET_TSTAMP: - if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == - ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) - r = -EINVAL; - else if (this->type & PORT_TYPE_FRAME) - r = vdec_set_pts(priv->vdec, parm.data_32); - else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC) - r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], - parm.data_32); - else if (this->type & PORT_TYPE_VIDEO) - r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], - parm.data_32); - else if (this->type & PORT_TYPE_AUDIO) - r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], - parm.data_32); - break; - case AMSTREAM_SET_TSTAMP_US64: - if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == - ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) - r = -EINVAL; - else { - u64 pts = parm.data_64; - - if (this->type & PORT_TYPE_FRAME) { - /* - *todo: check upper layer for decoder handler - * life sequence or multi-tasking management - */ - r = vdec_set_pts64(priv->vdec, pts); - } else if (has_hevc_vdec()) { - if (this->type & PORT_TYPE_HEVC) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_HEVC], pts); - } else if (this->type & PORT_TYPE_VIDEO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_VIDEO], pts); - } else if (this->type & PORT_TYPE_AUDIO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_AUDIO], pts); - } - } else { - if (this->type & PORT_TYPE_VIDEO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_VIDEO], pts); - } else if (this->type & PORT_TYPE_AUDIO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_AUDIO], pts); - } - } - } - break; - case AMSTREAM_PORT_INIT: - r = amstream_port_init(priv); - break; - case AMSTREAM_SET_TRICKMODE: - if ((this->type & PORT_TYPE_VIDEO) == 0) - return -EINVAL; - r = vdec_set_trickmode(priv->vdec, parm.data_32); - if (r == -1) - return -ENODEV; - break; - - case AMSTREAM_AUDIO_RESET: - if (this->type & PORT_TYPE_AUDIO) { - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - - r = audio_port_reset(this, pabuf); - } else - r = -EINVAL; - - break; - case AMSTREAM_SUB_RESET: - if (this->type & PORT_TYPE_SUB) { - struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - - r = sub_port_reset(this, psbuf); - } else - r = -EINVAL; - break; - case AMSTREAM_DEC_RESET: - tsync_set_dec_reset(); - break; - case AMSTREAM_SET_TS_SKIPBYTE: - tsdemux_set_skipbyte(parm.data_32); - break; - case AMSTREAM_SET_SUB_TYPE: - sub_type = parm.data_32; - break; - case AMSTREAM_SET_PCRSCR: - timestamp_pcrscr_set(parm.data_32); - break; - case AMSTREAM_SET_DEMUX: - tsdemux_set_demux(parm.data_32); - break; - case AMSTREAM_SET_VIDEO_DELAY_LIMIT_MS: - if (has_hevc_vdec()) - bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = parm.data_32; - bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = parm.data_32; - break; - case AMSTREAM_SET_AUDIO_DELAY_LIMIT_MS: - bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = parm.data_32; - break; - case AMSTREAM_SET_DRMMODE: - if (parm.data_32 == 1) { - pr_debug("set drmmode\n"); - this->flag |= PORT_FLAG_DRM; - if ((this->type & PORT_TYPE_VIDEO) && - (priv->vdec)) - priv->vdec->port_flag |= PORT_FLAG_DRM; - } else { - this->flag &= (~PORT_FLAG_DRM); - pr_debug("no drmmode\n"); - } - break; - case AMSTREAM_SET_APTS: { - unsigned int pts; - - pts = parm.data_32; - if (tsync_get_mode() == TSYNC_MODE_PCRMASTER) - tsync_pcr_set_apts(pts); - else - tsync_set_apts(pts); - break; - } - case AMSTREAM_SET_FRAME_BASE_PATH: - if (is_mult_inc(this->type) && - (parm.frame_base_video_path < FRAME_BASE_PATH_MAX)) { - vdec_set_video_path(priv->vdec, parm.data_32); - } else - r = -EINVAL; - break; - case AMSTREAM_SET_EOS: - if (priv->vdec) - vdec_set_eos(priv->vdec, parm.data_32); - break; - case AMSTREAM_SET_RECEIVE_ID: - if (is_mult_inc(this->type)) - vdec_set_receive_id(priv->vdec, parm.data_32); - else - r = -EINVAL; - break; - case AMSTREAM_SET_IS_RESET: - if (priv->vdec) - vdec_set_isreset(priv->vdec, parm.data_32); - break; - case AMSTREAM_SET_DV_META_WITH_EL: - if (priv->vdec) { - vdec_set_dv_metawithel(priv->vdec, parm.data_32); - if (vdec_dual(priv->vdec) && priv->vdec->slave) - vdec_set_dv_metawithel(priv->vdec->slave, - parm.data_32); - } - break; - case AMSTREAM_SET_NO_POWERDOWN: - vdec_set_no_powerdown(parm.data_32); - break; - default: - r = -ENOIOCTLCMD; - break; - } - return r; -} - -static enum E_ASPECT_RATIO get_normalized_aspect_ratio(u32 ratio_control) -{ - enum E_ASPECT_RATIO euAspectRatio; - - ratio_control = ratio_control >> DISP_RATIO_ASPECT_RATIO_BIT; - - switch (ratio_control) { - case 0x8c: - case 0x90: - euAspectRatio = ASPECT_RATIO_16_9; - /*pr_info("ASPECT_RATIO_16_9\n");*/ - break; - case 0xbb: - case 0xc0: - euAspectRatio = ASPECT_RATIO_4_3; - /*pr_info("ASPECT_RATIO_4_3\n");*/ - break; - default: - euAspectRatio = ASPECT_UNDEFINED; - /*pr_info("ASPECT_UNDEFINED and ratio_control = 0x%x\n", - ratio_control);*/ - break; - } - - return euAspectRatio; -} - -static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) -{ - struct stream_port_s *this = priv->port; - long r = 0; - struct am_ioctl_parm_ex parm; - - if (copy_from_user - ((void *)&parm, (void *)arg, - sizeof(parm))) - r = -EFAULT; - - switch (parm.cmd) { - case AMSTREAM_GET_EX_VB_STATUS: - if (this->type & PORT_TYPE_VIDEO) { - struct am_ioctl_parm_ex *p = &parm; - struct stream_buf_s *buf = NULL; - - buf = (this->vformat == VFORMAT_HEVC || - this->vformat == VFORMAT_AVS2 || - this->vformat == VFORMAT_VP9) ? - &bufs[BUF_TYPE_HEVC] : - &bufs[BUF_TYPE_VIDEO]; - - if (this->type & PORT_TYPE_FRAME) { - struct vdec_input_status_s status; - - /* - *todo: check upper layer for decoder - * handler lifecycle - */ - if (priv->vdec == NULL) { - r = -EINVAL; - break; - } - - r = vdec_input_get_status(&priv->vdec->input, - &status); - if (r == 0) { - p->status.size = status.size; - p->status.data_len = status.data_len; - p->status.free_len = status.free_len; - p->status.read_pointer = - status.read_pointer; - } - break; - } - - p->status.size = stbuf_canusesize(buf); - p->status.data_len = stbuf_level(buf); - p->status.free_len = stbuf_space(buf); - p->status.read_pointer = stbuf_rp(buf); - } else - r = -EINVAL; - break; - case AMSTREAM_GET_EX_AB_STATUS: - if (this->type & PORT_TYPE_AUDIO) { - struct am_ioctl_parm_ex *p = &parm; - struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; - - - p->status.size = stbuf_canusesize(buf); - p->status.data_len = stbuf_level(buf); - p->status.free_len = stbuf_space(buf); - p->status.read_pointer = stbuf_rp(buf); - - } else - r = -EINVAL; - break; - case AMSTREAM_GET_EX_VDECSTAT: - if ((this->type & PORT_TYPE_VIDEO) == 0) { - pr_err("no video\n"); - return -EINVAL; - } else { - struct vdec_info vstatus; - struct am_ioctl_parm_ex *p = &parm; - - memset(&vstatus, 0, sizeof(vstatus)); - - mutex_lock(&priv->mutex); - if (vdec_status(priv->vdec, &vstatus) == -1) { - mutex_unlock(&priv->mutex); - return -ENODEV; - } - mutex_unlock(&priv->mutex); - - p->vstatus.width = vstatus.frame_width; - p->vstatus.height = vstatus.frame_height; - p->vstatus.fps = vstatus.frame_rate; - p->vstatus.error_count = vstatus.error_count; - p->vstatus.status = vstatus.status; - p->vstatus.euAspectRatio = - get_normalized_aspect_ratio( - vstatus.ratio_control); - - } - break; - case AMSTREAM_GET_EX_ADECSTAT: - if ((this->type & PORT_TYPE_AUDIO) == 0) { - pr_err("no audio\n"); - return -EINVAL; - } - if (amstream_adec_status == NULL) { - /* - *pr_err("no amstream_adec_status\n"); - *return -ENODEV; - */ - memset(&parm.astatus, 0, sizeof(parm.astatus)); - } else { - struct adec_status astatus; - struct am_ioctl_parm_ex *p = &parm; - - amstream_adec_status(&astatus); - p->astatus.channels = astatus.channels; - p->astatus.sample_rate = astatus.sample_rate; - p->astatus.resolution = astatus.resolution; - p->astatus.error_count = astatus.error_count; - p->astatus.status = astatus.status; - } - break; - - case AMSTREAM_GET_EX_UD_POC: - if (this->type & PORT_TYPE_USERDATA) { - struct userdata_poc_info_t userdata_poc = - userdata_poc_info[userdata_poc_ri]; - memcpy(&parm.data_userdata_info, - &userdata_poc, - sizeof(struct userdata_poc_info_t)); - - userdata_poc_ri++; - if (userdata_poc_ri == USERDATA_FIFO_NUM) - userdata_poc_ri = 0; - } else - r = -EINVAL; - break; - default: - r = -ENOIOCTLCMD; - break; - } - /* pr_info("parm size:%zx\n", sizeof(parm)); */ - if (r == 0) { - if (copy_to_user((void *)arg, &parm, sizeof(parm))) - r = -EFAULT; - } - return r; - -} -static long amstream_ioctl_set_ex(struct port_priv_s *priv, ulong arg) -{ - long r = 0; - return r; -} -static long amstream_ioctl_get_ptr(struct port_priv_s *priv, ulong arg) -{ - long r = 0; - - struct am_ioctl_parm_ptr parm; - - if (copy_from_user - ((void *)&parm, (void *)arg, - sizeof(parm))) - return -EFAULT; - - switch (parm.cmd) { - case AMSTREAM_GET_PTR_SUB_INFO: - { - struct subtitle_info msub_info[MAX_SUB_NUM]; - struct subtitle_info *psub_info[MAX_SUB_NUM]; - int i; - - for (i = 0; i < MAX_SUB_NUM; i++) - psub_info[i] = &msub_info[i]; - - r = psparser_get_sub_info(psub_info); - - if (r == 0) { - memcpy(parm.pdata_sub_info, msub_info, - sizeof(struct subtitle_info) - * MAX_SUB_NUM); - } - } - break; - default: - r = -ENOIOCTLCMD; - break; - } - /* pr_info("parm size:%d\n", sizeof(parm)); */ - if (r == 0) { - if (copy_to_user((void *)arg, &parm, sizeof(parm))) - r = -EFAULT; - } - - return r; - -} -static long amstream_ioctl_set_ptr(struct port_priv_s *priv, ulong arg) -{ - struct stream_port_s *this = priv->port; - struct am_ioctl_parm_ptr parm; - long r = 0; - - if (copy_from_user - ((void *)&parm, (void *)arg, - sizeof(parm))) { - pr_err("[%s]%d, arg err\n", __func__, __LINE__); - r = -EFAULT; - } - switch (parm.cmd) { - case AMSTREAM_SET_PTR_AUDIO_INFO: - if ((this->type & PORT_TYPE_VIDEO) - || (this->type & PORT_TYPE_AUDIO)) { - if (parm.pdata_audio_info != NULL) { - if (copy_from_user - ((void *)&audio_dec_info, (void *)parm.pdata_audio_info, - sizeof(audio_dec_info))) { - pr_err("[%s]%d, arg err\n", __func__, __LINE__); - r = -EFAULT; - } - } - } else - r = -EINVAL; - break; - case AMSTREAM_SET_PTR_CONFIGS: - if (this->type & PORT_TYPE_VIDEO) { - if (!parm.pointer || (parm.len <= 0) || - (parm.len > PAGE_SIZE)) { - r = -EINVAL; - } else { - r = copy_from_user(priv->vdec->config, - parm.pointer, parm.len); - if (r) - r = -EINVAL; - else - priv->vdec->config_len = parm.len; - } - } else - r = -EINVAL; - break; - default: - r = -ENOIOCTLCMD; - break; - } - return r; -} - -static long amstream_do_ioctl_new(struct port_priv_s *priv, - unsigned int cmd, ulong arg) -{ - long r = 0; - struct stream_port_s *this = priv->port; - - switch (cmd) { - case AMSTREAM_IOC_GET_VERSION: - r = amstream_ioctl_get_version(priv, arg); - break; - case AMSTREAM_IOC_GET: - r = amstream_ioctl_get(priv, arg); - break; - case AMSTREAM_IOC_SET: - r = amstream_ioctl_set(priv, arg); - break; - case AMSTREAM_IOC_GET_EX: - r = amstream_ioctl_get_ex(priv, arg); - break; - case AMSTREAM_IOC_SET_EX: - r = amstream_ioctl_set_ex(priv, arg); - break; - case AMSTREAM_IOC_GET_PTR: - r = amstream_ioctl_get_ptr(priv, arg); - break; - case AMSTREAM_IOC_SET_PTR: - r = amstream_ioctl_set_ptr(priv, arg); - break; - case AMSTREAM_IOC_SYSINFO: - if (this->type & PORT_TYPE_VIDEO) - r = vdec_set_decinfo(priv->vdec, (void *)arg); - else - r = -EINVAL; - break; - case AMSTREAM_IOC_GET_QOSINFO: - { - struct av_param_qosinfo_t __user *uarg = (void *)arg; - struct vframe_qos_s *qos_info = vdec_get_qos_info(); - if (this->type & PORT_TYPE_VIDEO) { - if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos, - qos_info, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) { - r = -EFAULT; - break; - } - } - } - break; - default: - r = -ENOIOCTLCMD; - break; - } - - return r; -} - -static long amstream_do_ioctl_old(struct port_priv_s *priv, - unsigned int cmd, ulong arg) -{ - struct stream_port_s *this = priv->port; - long r = 0; - - switch (cmd) { - - case AMSTREAM_IOC_VB_START: - if ((this->type & PORT_TYPE_VIDEO) && - ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { - if (has_hevc_vdec()) - bufs[BUF_TYPE_HEVC].buf_start = arg; - bufs[BUF_TYPE_VIDEO].buf_start = arg; - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_VB_SIZE: - if ((this->type & PORT_TYPE_VIDEO) && - ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { - if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) { - if (has_hevc_vdec()) { - r = stbuf_change_size( - &bufs[BUF_TYPE_HEVC], - arg, false); - } - r += stbuf_change_size( - &bufs[BUF_TYPE_VIDEO], - arg, false); - } - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_AB_START: - if ((this->type & PORT_TYPE_AUDIO) && - ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) - bufs[BUF_TYPE_AUDIO].buf_start = arg; - else - r = -EINVAL; - break; - - case AMSTREAM_IOC_AB_SIZE: - if ((this->type & PORT_TYPE_AUDIO) && - ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) { - if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) { - r = stbuf_change_size( - &bufs[BUF_TYPE_AUDIO], arg, false); - } - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_VFORMAT: - if ((this->type & PORT_TYPE_VIDEO) && (arg < VFORMAT_MAX)) { - this->vformat = (enum vformat_e)arg; - this->flag |= PORT_FLAG_VFORMAT; - - vdec_set_format(priv->vdec, this->vformat); - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_AFORMAT: - if ((this->type & PORT_TYPE_AUDIO) && (arg < AFORMAT_MAX)) { - memset(&audio_dec_info, 0, - sizeof(struct audio_info)); - /* for new format,reset the audio info. */ - this->aformat = (enum aformat_e)arg; - this->flag |= PORT_FLAG_AFORMAT; - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_VID: - if (this->type & PORT_TYPE_VIDEO) { - this->vid = (u32) arg; - this->flag |= PORT_FLAG_VID; - } else - r = -EINVAL; - - break; - - case AMSTREAM_IOC_AID: - if (this->type & PORT_TYPE_AUDIO) { - this->aid = (u32) arg; - this->flag |= PORT_FLAG_AID; - - if (port_get_inited(priv)) { - tsync_audio_break(1); - amstream_change_avid(this); - } - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_SID: - if (this->type & PORT_TYPE_SUB) { - this->sid = (u32) arg; - this->flag |= PORT_FLAG_SID; - - if (port_get_inited(priv)) - amstream_change_sid(this); - } else - r = -EINVAL; - - break; - - case AMSTREAM_IOC_PCRID: - this->pcrid = (u32) arg; - this->pcr_inited = 1; - pr_err("set pcrid = 0x%x\n", this->pcrid); - break; - - case AMSTREAM_IOC_VB_STATUS: - if (this->type & PORT_TYPE_VIDEO) { - struct am_io_param para; - struct am_io_param *p = ¶ - struct stream_buf_s *buf = NULL; - - buf = (this->vformat == VFORMAT_HEVC || - this->vformat == VFORMAT_AVS2 || - this->vformat == VFORMAT_VP9) ? - &bufs[BUF_TYPE_HEVC] : - &bufs[BUF_TYPE_VIDEO]; - - if (this->type & PORT_TYPE_FRAME) { - struct vdec_input_status_s status; - - /* - *todo: check upper layer for decoder - * handler lifecycle - */ - if (priv->vdec == NULL) { - r = -EINVAL; - break; - } - - r = vdec_input_get_status(&priv->vdec->input, - &status); - if (r == 0) { - p->status.size = status.size; - p->status.data_len = status.data_len; - p->status.free_len = status.free_len; - p->status.read_pointer = - status.read_pointer; - if (copy_to_user((void *)arg, p, - sizeof(para))) - r = -EFAULT; - } - break; - } - - p->status.size = stbuf_canusesize(buf); - p->status.data_len = stbuf_level(buf); - p->status.free_len = stbuf_space(buf); - p->status.read_pointer = stbuf_rp(buf); - if (copy_to_user((void *)arg, p, sizeof(para))) - r = -EFAULT; - return r; - } - r = -EINVAL; - break; - - case AMSTREAM_IOC_AB_STATUS: - if (this->type & PORT_TYPE_AUDIO) { - struct am_io_param para; - struct am_io_param *p = ¶ - struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; - - p->status.size = stbuf_canusesize(buf); - p->status.data_len = stbuf_level(buf); - p->status.free_len = stbuf_space(buf); - p->status.read_pointer = stbuf_rp(buf); - if (copy_to_user((void *)arg, p, sizeof(para))) - r = -EFAULT; - return r; - } - r = -EINVAL; - break; - - case AMSTREAM_IOC_SYSINFO: - if (this->type & PORT_TYPE_VIDEO) - r = vdec_set_decinfo(priv->vdec, (void *)arg); - else - r = -EINVAL; - break; - - case AMSTREAM_IOC_ACHANNEL: - if (this->type & PORT_TYPE_AUDIO) { - this->achanl = (u32) arg; - set_ch_num_info((u32) arg); - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_SAMPLERATE: - if (this->type & PORT_TYPE_AUDIO) { - this->asamprate = (u32) arg; - set_sample_rate_info((u32) arg); - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_DATAWIDTH: - if (this->type & PORT_TYPE_AUDIO) - this->adatawidth = (u32) arg; - else - r = -EINVAL; - break; - - case AMSTREAM_IOC_TSTAMP: - if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == - ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) - r = -EINVAL; - else if (this->type & PORT_TYPE_FRAME) - r = vdec_set_pts(priv->vdec, arg); - else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC) - r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], arg); - else if (this->type & PORT_TYPE_VIDEO) - r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], arg); - else if (this->type & PORT_TYPE_AUDIO) - r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], arg); - break; - - case AMSTREAM_IOC_TSTAMP_uS64: - if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == - ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) - r = -EINVAL; - else { - u64 pts; - - if (copy_from_user - ((void *)&pts, (void *)arg, sizeof(u64))) - return -EFAULT; - if (this->type & PORT_TYPE_FRAME) { - /* - *todo: check upper layer for decoder handler - * life sequence or multi-tasking management - */ - if (priv->vdec) - r = vdec_set_pts64(priv->vdec, pts); - } else if (has_hevc_vdec()) { - if (this->type & PORT_TYPE_HEVC) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_HEVC], pts); - } else if (this->type & PORT_TYPE_VIDEO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_VIDEO], pts); - } else if (this->type & PORT_TYPE_AUDIO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_AUDIO], pts); - } - } else { - if (this->type & PORT_TYPE_VIDEO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_VIDEO], pts); - } else if (this->type & PORT_TYPE_AUDIO) { - r = es_vpts_checkin_us64( - &bufs[BUF_TYPE_AUDIO], pts); - } - } - } - break; - - case AMSTREAM_IOC_VDECSTAT: - if ((this->type & PORT_TYPE_VIDEO) == 0) - return -EINVAL; - { - struct vdec_info vstatus; - struct am_io_param para; - struct am_io_param *p = ¶ - - memset(&vstatus, 0, sizeof(vstatus)); - - mutex_lock(&priv->mutex); - if (vdec_status(priv->vdec, &vstatus) == -1) { - mutex_unlock(&priv->mutex); - return -ENODEV; - } - mutex_unlock(&priv->mutex); - - p->vstatus.width = vstatus.frame_width; - p->vstatus.height = vstatus.frame_height; - p->vstatus.fps = vstatus.frame_rate; - p->vstatus.error_count = vstatus.error_count; - p->vstatus.status = vstatus.status; - p->vstatus.euAspectRatio = - get_normalized_aspect_ratio( - vstatus.ratio_control); - - if (copy_to_user((void *)arg, p, sizeof(para))) - r = -EFAULT; - return r; - } - - case AMSTREAM_IOC_VDECINFO: - if ((this->type & PORT_TYPE_VIDEO) == 0) - return -EINVAL; - { - struct vdec_info vinfo; - struct am_io_info para; - - memset(¶, 0x0, sizeof(struct am_io_info)); - - mutex_lock(&priv->mutex); - if (vdec_status(priv->vdec, &vinfo) == -1) { - mutex_unlock(&priv->mutex); - return -ENODEV; - } - mutex_unlock(&priv->mutex); - - memcpy(¶.vinfo, &vinfo, sizeof(struct vdec_info)); - if (copy_to_user((void *)arg, ¶, sizeof(para))) - r = -EFAULT; - return r; - } - - case AMSTREAM_IOC_ADECSTAT: - if ((this->type & PORT_TYPE_AUDIO) == 0) - return -EINVAL; - if (amstream_adec_status == NULL) - return -ENODEV; - else { - struct adec_status astatus; - struct am_io_param para; - struct am_io_param *p = ¶ - - amstream_adec_status(&astatus); - p->astatus.channels = astatus.channels; - p->astatus.sample_rate = astatus.sample_rate; - p->astatus.resolution = astatus.resolution; - p->astatus.error_count = astatus.error_count; - p->astatus.status = astatus.status; - if (copy_to_user((void *)arg, p, sizeof(para))) - r = -EFAULT; - return r; - } - case AMSTREAM_IOC_PORT_INIT: - r = amstream_port_init(priv); - break; - - case AMSTREAM_IOC_VDEC_RESET: - if ((this->type & PORT_TYPE_VIDEO) == 0) - return -EINVAL; - - if (priv->vdec == NULL) - return -ENODEV; - - r = vdec_reset(priv->vdec); - break; - - case AMSTREAM_IOC_TRICKMODE: - if ((this->type & PORT_TYPE_VIDEO) == 0) - return -EINVAL; - r = vdec_set_trickmode(priv->vdec, arg); - if (r == -1) - return -ENODEV; - break; - - case AMSTREAM_IOC_AUDIO_INFO: - if ((this->type & PORT_TYPE_VIDEO) - || (this->type & PORT_TYPE_AUDIO)) { - if (copy_from_user - (&audio_dec_info, (void __user *)arg, - sizeof(audio_dec_info))) - r = -EFAULT; - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_AUDIO_RESET: - if (this->type & PORT_TYPE_AUDIO) { - struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; - - r = audio_port_reset(this, pabuf); - } else - r = -EINVAL; - - break; - - case AMSTREAM_IOC_SUB_RESET: - if (this->type & PORT_TYPE_SUB) { - struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - - r = sub_port_reset(this, psbuf); - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_SUB_LENGTH: - if ((this->type & PORT_TYPE_SUB) || - (this->type & PORT_TYPE_SUB_RD)) { - u32 sub_wp, sub_rp; - struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - int val; - - sub_wp = stbuf_sub_wp_get(); - sub_rp = stbuf_sub_rp_get(); - - if (sub_wp == sub_rp) - val = 0; - else if (sub_wp > sub_rp) - val = sub_wp - sub_rp; - else - val = psbuf->buf_size - (sub_rp - sub_wp); - put_user(val, (int __user *)arg); - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_UD_LENGTH: - if (this->type & PORT_TYPE_USERDATA) { - /* *((u32 *)arg) = userdata_length; */ - put_user(userdata_length, (unsigned long __user *)arg); - userdata_length = 0; - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_UD_POC: - if (this->type & PORT_TYPE_USERDATA) { - /* *((u32 *)arg) = userdata_length; */ - int ri; -#ifdef DEBUG_USER_DATA - int wi; -#endif - int bDataAvail = 0; - - mutex_lock(&userdata_mutex); - if (userdata_poc_wi != userdata_poc_ri) { - bDataAvail = 1; - ri = userdata_poc_ri; -#ifdef DEBUG_USER_DATA - wi = userdata_poc_wi; -#endif - userdata_poc_ri++; - if (userdata_poc_ri >= USERDATA_FIFO_NUM) - userdata_poc_ri = 0; - } - mutex_unlock(&userdata_mutex); - if (bDataAvail) { - int res; - struct userdata_poc_info_t userdata_poc = - userdata_poc_info[ri]; -#ifdef DEBUG_USER_DATA - pr_info("read poc: ri=%d, wi=%d, poc=%d, last_wi=%d\n", - ri, wi, - userdata_poc.poc_number, - last_read_wi); -#endif - res = - copy_to_user((unsigned long __user *)arg, - &userdata_poc, - sizeof(struct userdata_poc_info_t)); - if (res < 0) - r = -EFAULT; - } else { - r = -EFAULT; - } - } else { - r = -EINVAL; - } - break; - - case AMSTREAM_IOC_UD_BUF_READ: - { - if (this->type & PORT_TYPE_USERDATA) { - struct userdata_param_t param; - struct userdata_param_t *p_userdata_param; - struct vdec_s *vdec; - - p_userdata_param = ¶m; - - if (copy_from_user(p_userdata_param, - (void __user *)arg, - sizeof(struct userdata_param_t))) { - r = -EFAULT; - break; - } - - vdec = vdec_get_vdec_by_id(p_userdata_param->instance_id); - if (vdec) { - if (vdec_read_user_data(vdec, - p_userdata_param) == 0) { - r = -EFAULT; - break; - } - - if (copy_to_user((void *)arg, - p_userdata_param, - sizeof(struct userdata_param_t))) - r = -EFAULT; - } else - r = -EINVAL; - } - } - break; - - case AMSTREAM_IOC_UD_AVAILABLE_VDEC: - { - unsigned int ready_vdec; - - mutex_lock(&userdata_mutex); - ready_vdec = ud_ready_vdec_flag; - ud_ready_vdec_flag = 0; - mutex_unlock(&userdata_mutex); - - put_user(ready_vdec, (uint32_t __user *)arg); - } - break; - - case AMSTREAM_IOC_GET_VDEC_ID: - if (this->type & PORT_TYPE_VIDEO && priv->vdec) { - put_user(priv->vdec->id, (int32_t __user *)arg); - } else - r = -EINVAL; - break; - - - case AMSTREAM_IOC_UD_FLUSH_USERDATA: - if (this->type & PORT_TYPE_USERDATA) { - struct vdec_s *vdec; - int vdec_id; - - get_user(vdec_id, (int __user *)arg); - vdec = vdec_get_vdec_by_id(vdec_id); - if (vdec) { - vdec_reset_userdata_fifo(vdec, 0); - pr_info("reset_userdata_fifo for vdec: %d\n", vdec_id); - } - } else - r = -EINVAL; - break; - - case AMSTREAM_IOC_SET_DEC_RESET: - tsync_set_dec_reset(); - break; - - case AMSTREAM_IOC_TS_SKIPBYTE: - if ((int)arg >= 0) - tsdemux_set_skipbyte(arg); - else - r = -EINVAL; - break; - - case AMSTREAM_IOC_SUB_TYPE: - sub_type = (int)arg; - break; - - case AMSTREAM_IOC_APTS_LOOKUP: - if (this->type & PORT_TYPE_AUDIO) { - u32 pts = 0, frame_size, offset; - - get_user(offset, (unsigned long __user *)arg); - pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, - &frame_size, 300); - put_user(pts, (int __user *)arg); - } - return 0; - case GET_FIRST_APTS_FLAG: - if (this->type & PORT_TYPE_AUDIO) { - put_user(first_pts_checkin_complete(PTS_TYPE_AUDIO), - (int __user *)arg); - } - break; - - case AMSTREAM_IOC_APTS: - put_user(timestamp_apts_get(), (int __user *)arg); - break; - - case AMSTREAM_IOC_VPTS: - put_user(timestamp_vpts_get(), (int __user *)arg); - break; - - case AMSTREAM_IOC_PCRSCR: - put_user(timestamp_pcrscr_get(), (int __user *)arg); - break; - - case AMSTREAM_IOC_SET_PCRSCR: - timestamp_pcrscr_set(arg); - break; - case AMSTREAM_IOC_GET_LAST_CHECKIN_APTS: - put_user(get_last_checkin_pts(PTS_TYPE_AUDIO), (int *)arg); - break; - case AMSTREAM_IOC_GET_LAST_CHECKIN_VPTS: - put_user(get_last_checkin_pts(PTS_TYPE_VIDEO), (int *)arg); - break; - case AMSTREAM_IOC_GET_LAST_CHECKOUT_APTS: - put_user(get_last_checkout_pts(PTS_TYPE_AUDIO), (int *)arg); - break; - case AMSTREAM_IOC_GET_LAST_CHECKOUT_VPTS: - put_user(get_last_checkout_pts(PTS_TYPE_VIDEO), (int *)arg); - break; - case AMSTREAM_IOC_SUB_NUM: - put_user(psparser_get_sub_found_num(), (int *)arg); - break; - - case AMSTREAM_IOC_SUB_INFO: - if (arg > 0) { - struct subtitle_info msub_info[MAX_SUB_NUM]; - struct subtitle_info *psub_info[MAX_SUB_NUM]; - int i; - - for (i = 0; i < MAX_SUB_NUM; i++) - psub_info[i] = &msub_info[i]; - - r = psparser_get_sub_info(psub_info); - - if (r == 0) { - if (copy_to_user((void __user *)arg, msub_info, - sizeof(struct subtitle_info) * MAX_SUB_NUM)) - r = -EFAULT; - } - } - break; - case AMSTREAM_IOC_SET_DEMUX: - tsdemux_set_demux((int)arg); - break; - case AMSTREAM_IOC_SET_VIDEO_DELAY_LIMIT_MS: - if (has_hevc_vdec()) - bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = (int)arg; - bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = (int)arg; - break; - case AMSTREAM_IOC_SET_AUDIO_DELAY_LIMIT_MS: - bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = (int)arg; - break; - case AMSTREAM_IOC_GET_VIDEO_DELAY_LIMIT_MS: - put_user(bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms, (int *)arg); - break; - case AMSTREAM_IOC_GET_AUDIO_DELAY_LIMIT_MS: - put_user(bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms, (int *)arg); - break; - case AMSTREAM_IOC_GET_VIDEO_CUR_DELAY_MS: { - int delay; - - delay = calculation_stream_delayed_ms( - PTS_TYPE_VIDEO, NULL, NULL); - if (delay >= 0) - put_user(delay, (int *)arg); - else - put_user(0, (int *)arg); - } - break; - - case AMSTREAM_IOC_GET_AUDIO_CUR_DELAY_MS: { - int delay; - - delay = calculation_stream_delayed_ms(PTS_TYPE_AUDIO, NULL, - NULL); - if (delay >= 0) - put_user(delay, (int *)arg); - else - put_user(0, (int *)arg); - } - break; - case AMSTREAM_IOC_GET_AUDIO_AVG_BITRATE_BPS: { - int delay; - u32 avgbps; - - delay = calculation_stream_delayed_ms(PTS_TYPE_AUDIO, NULL, - &avgbps); - if (delay >= 0) - put_user(avgbps, (int *)arg); - else - put_user(0, (int *)arg); - break; - } - case AMSTREAM_IOC_GET_VIDEO_AVG_BITRATE_BPS: { - int delay; - u32 avgbps; - - delay = calculation_stream_delayed_ms(PTS_TYPE_VIDEO, NULL, - &avgbps); - if (delay >= 0) - put_user(avgbps, (int *)arg); - else - put_user(0, (int *)arg); - break; - } - case AMSTREAM_IOC_SET_DRMMODE: - if ((u32) arg == 1) { - pr_err("set drmmode\n"); - this->flag |= PORT_FLAG_DRM; - if ((this->type & PORT_TYPE_VIDEO) && - (priv->vdec)) - priv->vdec->port_flag |= PORT_FLAG_DRM; - } else { - this->flag &= (~PORT_FLAG_DRM); - pr_err("no drmmode\n"); - } - break; - case AMSTREAM_IOC_SET_APTS: { - unsigned long pts; - - if (get_user(pts, (unsigned long __user *)arg)) { - pr_err - ("Get audio pts from user space fault!\n"); - return -EFAULT; - } - if (tsync_get_mode() == TSYNC_MODE_PCRMASTER) - tsync_pcr_set_apts(pts); - else - tsync_set_apts(pts); - break; - } - default: - r = -ENOIOCTLCMD; - break; - } - - return r; -} - -static long amstream_do_ioctl(struct port_priv_s *priv, - unsigned int cmd, ulong arg) -{ - long r = 0; - - switch (cmd) { - case AMSTREAM_IOC_GET_VERSION: - case AMSTREAM_IOC_GET: - case AMSTREAM_IOC_SET: - case AMSTREAM_IOC_GET_EX: - case AMSTREAM_IOC_SET_EX: - case AMSTREAM_IOC_GET_PTR: - case AMSTREAM_IOC_SET_PTR: - case AMSTREAM_IOC_SYSINFO: - case AMSTREAM_IOC_GET_QOSINFO: - r = amstream_do_ioctl_new(priv, cmd, arg); - break; - default: - r = amstream_do_ioctl_old(priv, cmd, arg); - break; - } - if (r != 0) - pr_err("amstream_do_ioctl error :%lx, %x\n", r, cmd); - - return r; -} -static long amstream_ioctl(struct file *file, unsigned int cmd, ulong arg) -{ - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *this = priv->port; - - if (!this) - return -ENODEV; - - return amstream_do_ioctl(priv, cmd, arg); -} - -#ifdef CONFIG_COMPAT -struct dec_sysinfo32 { - - u32 format; - - u32 width; - - u32 height; - - u32 rate; - - u32 extra; - - u32 status; - - u32 ratio; - - compat_uptr_t param; - - u64 ratio64; -}; - -struct am_ioctl_parm_ptr32 { - union { - compat_uptr_t pdata_audio_info; - compat_uptr_t pdata_sub_info; - compat_uptr_t pointer; - char data[8]; - }; - u32 cmd; - u32 len; -}; - -static long amstream_ioc_setget_ptr(struct port_priv_s *priv, - unsigned int cmd, struct am_ioctl_parm_ptr32 __user *arg) -{ - struct am_ioctl_parm_ptr __user *data; - struct am_ioctl_parm_ptr32 param; - int ret; - - if (copy_from_user(¶m, - (void __user *)arg, - sizeof(struct am_ioctl_parm_ptr32))) - return -EFAULT; - - data = compat_alloc_user_space(sizeof(*data)); - if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) - return -EFAULT; - - if (put_user(param.cmd, &data->cmd) || - put_user(compat_ptr(param.pointer), &data->pointer) || - put_user(param.len, &data->len)) - return -EFAULT; - - ret = amstream_do_ioctl(priv, cmd, (unsigned long)data); - if (ret < 0) - return ret; - return 0; - -} - -static long amstream_set_sysinfo(struct port_priv_s *priv, - struct dec_sysinfo32 __user *arg) -{ - struct dec_sysinfo __user *data; - struct dec_sysinfo32 __user *data32 = arg; - int ret; - struct dec_sysinfo32 param; - - if (copy_from_user(¶m, - (void __user *)arg, - sizeof(struct dec_sysinfo32))) - return -EFAULT; - - data = compat_alloc_user_space(sizeof(*data)); - if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) - return -EFAULT; - if (copy_in_user(data, data32, 7 * sizeof(u32))) - return -EFAULT; - if (put_user(compat_ptr(param.param), &data->param)) - return -EFAULT; - if (copy_in_user(&data->ratio64, &data32->ratio64, - sizeof(data->ratio64))) - return -EFAULT; - - ret = amstream_do_ioctl(priv, AMSTREAM_IOC_SYSINFO, - (unsigned long)data); - if (ret < 0) - return ret; - - if (copy_in_user(&arg->format, &data->format, 7 * sizeof(u32)) || - copy_in_user(&arg->ratio64, &data->ratio64, - sizeof(arg->ratio64))) - return -EFAULT; - - return 0; -} - - -struct userdata_param32_t { - uint32_t version; - uint32_t instance_id; /*input, 0~9*/ - uint32_t buf_len; /*input*/ - uint32_t data_size; /*output*/ - compat_uptr_t pbuf_addr; /*input*/ - struct userdata_meta_info_t meta_info; /*output*/ -}; - - -static long amstream_ioc_get_userdata(struct port_priv_s *priv, - struct userdata_param32_t __user *arg) -{ - struct userdata_param_t __user *data; - struct userdata_param32_t __user *data32 = arg; - int ret; - struct userdata_param32_t param; - - - if (copy_from_user(¶m, - (void __user *)arg, - sizeof(struct userdata_param32_t))) - return -EFAULT; - - data = compat_alloc_user_space(sizeof(*data)); - if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) - return -EFAULT; - - if (copy_in_user(data, data32, 4 * sizeof(u32))) - return -EFAULT; - - if (copy_in_user(&data->meta_info, &data32->meta_info, - sizeof(data->meta_info))) - return -EFAULT; - - if (put_user(compat_ptr(param.pbuf_addr), &data->pbuf_addr)) - return -EFAULT; - - ret = amstream_do_ioctl(priv, AMSTREAM_IOC_UD_BUF_READ, - (unsigned long)data); - if (ret < 0) - return ret; - - if (copy_in_user(&data32->version, &data->version, 4 * sizeof(u32)) || - copy_in_user(&data32->meta_info, &data->meta_info, - sizeof(data32->meta_info))) - return -EFAULT; - - return 0; -} - - -static long amstream_compat_ioctl(struct file *file, - unsigned int cmd, ulong arg) -{ - s32 r = 0; - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - - switch (cmd) { - case AMSTREAM_IOC_GET_VERSION: - case AMSTREAM_IOC_GET: - case AMSTREAM_IOC_SET: - case AMSTREAM_IOC_GET_EX: - case AMSTREAM_IOC_SET_EX: - return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg)); - case AMSTREAM_IOC_GET_PTR: - case AMSTREAM_IOC_SET_PTR: - return amstream_ioc_setget_ptr(priv, cmd, compat_ptr(arg)); - case AMSTREAM_IOC_SYSINFO: - return amstream_set_sysinfo(priv, compat_ptr(arg)); - case AMSTREAM_IOC_UD_BUF_READ: - return amstream_ioc_get_userdata(priv, compat_ptr(arg)); - default: - return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg)); - } - - return r; -} -#endif - -static ssize_t ports_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - int i; - char *pbuf = buf; - struct stream_port_s *p = NULL; - - for (i = 0; i < amstream_port_num; i++) { - p = &ports[i]; - /*name */ - pbuf += sprintf(pbuf, "%s\t:\n", p->name); - /*type */ - pbuf += sprintf(pbuf, "\ttype:%d( ", p->type); - if (p->type & PORT_TYPE_VIDEO) - pbuf += sprintf(pbuf, "%s ", "Video"); - if (p->type & PORT_TYPE_AUDIO) - pbuf += sprintf(pbuf, "%s ", "Audio"); - if (p->type & PORT_TYPE_MPTS) - pbuf += sprintf(pbuf, "%s ", "TS"); - if (p->type & PORT_TYPE_MPPS) - pbuf += sprintf(pbuf, "%s ", "PS"); - if (p->type & PORT_TYPE_ES) - pbuf += sprintf(pbuf, "%s ", "ES"); - if (p->type & PORT_TYPE_RM) - pbuf += sprintf(pbuf, "%s ", "RM"); - if (p->type & PORT_TYPE_SUB) - pbuf += sprintf(pbuf, "%s ", "Subtitle"); - if (p->type & PORT_TYPE_SUB_RD) - pbuf += sprintf(pbuf, "%s ", "Subtitle_Read"); - if (p->type & PORT_TYPE_USERDATA) - pbuf += sprintf(pbuf, "%s ", "userdata"); - pbuf += sprintf(pbuf, ")\n"); - /*flag */ - pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag); - if (p->flag & PORT_FLAG_IN_USE) - pbuf += sprintf(pbuf, "%s ", "Used"); - else - pbuf += sprintf(pbuf, "%s ", "Unused"); - if ((p->type & PORT_TYPE_VIDEO) == 0) { - if (p->flag & PORT_FLAG_INITED) - pbuf += sprintf(pbuf, "%s ", "inited"); - else - pbuf += sprintf(pbuf, "%s ", "uninited"); - } - pbuf += sprintf(pbuf, ")\n"); - /*others */ - pbuf += sprintf(pbuf, "\tVformat:%d\n", - (p->flag & PORT_FLAG_VFORMAT) ? p->vformat : -1); - pbuf += sprintf(pbuf, "\tAformat:%d\n", - (p->flag & PORT_FLAG_AFORMAT) ? p->aformat : -1); - pbuf += sprintf(pbuf, "\tVid:%d\n", - (p->flag & PORT_FLAG_VID) ? p->vid : -1); - pbuf += sprintf(pbuf, "\tAid:%d\n", - (p->flag & PORT_FLAG_AID) ? p->aid : -1); - pbuf += sprintf(pbuf, "\tSid:%d\n", - (p->flag & PORT_FLAG_SID) ? p->sid : -1); - pbuf += sprintf(pbuf, "\tPCRid:%d\n", - (p->pcr_inited == 1) ? p->pcrid : -1); - pbuf += sprintf(pbuf, "\tachannel:%d\n", p->achanl); - pbuf += sprintf(pbuf, "\tasamprate:%d\n", p->asamprate); - pbuf += sprintf(pbuf, "\tadatawidth:%d\n\n", p->adatawidth); - } - return pbuf - buf; -} - -static ssize_t bufs_show(struct class *class, struct class_attribute *attr, - char *buf) -{ - int i; - char *pbuf = buf; - struct stream_buf_s *p = NULL; - char buf_type[][12] = { "Video", "Audio", "Subtitle", - "UserData", "HEVC" }; - - for (i = 0; i < amstream_buf_num; i++) { - p = &bufs[i]; - /*type */ - pbuf += sprintf(pbuf, "%s buffer:", buf_type[p->type]); - /*flag */ - pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag); - if (p->flag & BUF_FLAG_ALLOC) - pbuf += sprintf(pbuf, "%s ", "Alloc"); - else - pbuf += sprintf(pbuf, "%s ", "Unalloc"); - if (p->flag & BUF_FLAG_IN_USE) - pbuf += sprintf(pbuf, "%s ", "Used"); - else - pbuf += sprintf(pbuf, "%s ", "Noused"); - if (p->flag & BUF_FLAG_PARSER) - pbuf += sprintf(pbuf, "%s ", "Parser"); - else - pbuf += sprintf(pbuf, "%s ", "noParser"); - if (p->flag & BUF_FLAG_FIRST_TSTAMP) - pbuf += sprintf(pbuf, "%s ", "firststamp"); - else - pbuf += sprintf(pbuf, "%s ", "nofirststamp"); - pbuf += sprintf(pbuf, ")\n"); - /*buf stats */ - - pbuf += sprintf(pbuf, "\tbuf addr:%p\n", (void *)p->buf_start); - - if (p->type != BUF_TYPE_SUBTITLE) { - pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size); - pbuf += sprintf(pbuf, - "\tbuf canusesize:%#x\n", - p->canusebuf_size); - pbuf += sprintf(pbuf, - "\tbuf regbase:%#lx\n", p->reg_base); - - if (p->reg_base && p->flag & BUF_FLAG_IN_USE) { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /* TODO: mod gate */ - /* switch_mod_gate_by_name("vdec", 1);*/ - amports_switch_gate("vdec", 1); - } - pbuf += sprintf(pbuf, "\tbuf level:%#x\n", - stbuf_level(p)); - pbuf += sprintf(pbuf, "\tbuf space:%#x\n", - stbuf_space(p)); - pbuf += sprintf(pbuf, - "\tbuf read pointer:%#x\n", - stbuf_rp(p)); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { - /* TODO: mod gate */ - /* switch_mod_gate_by_name("vdec", 0);*/ - amports_switch_gate("vdec", 0); - } - } else - pbuf += sprintf(pbuf, "\tbuf no used.\n"); - - if (p->type == BUF_TYPE_USERDATA) { - pbuf += sprintf(pbuf, - "\tbuf write pointer:%#x\n", - p->buf_wp); - pbuf += sprintf(pbuf, - "\tbuf read pointer:%#x\n", - p->buf_rp); - } - } else { - u32 sub_wp, sub_rp, data_size; - - sub_wp = stbuf_sub_wp_get(); - sub_rp = stbuf_sub_rp_get(); - if (sub_wp >= sub_rp) - data_size = sub_wp - sub_rp; - else - data_size = p->buf_size - sub_rp + sub_wp; - pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size); - pbuf += - sprintf(pbuf, "\tbuf canusesize:%#x\n", - p->canusebuf_size); - pbuf += - sprintf(pbuf, "\tbuf start:%#x\n", - stbuf_sub_start_get()); - pbuf += sprintf(pbuf, - "\tbuf write pointer:%#x\n", sub_wp); - pbuf += sprintf(pbuf, - "\tbuf read pointer:%#x\n", sub_rp); - pbuf += sprintf(pbuf, "\tbuf level:%#x\n", data_size); - } - - pbuf += sprintf(pbuf, "\tbuf first_stamp:%#x\n", - p->first_tstamp); - pbuf += sprintf(pbuf, "\tbuf wcnt:%#x\n\n", p->wcnt); - pbuf += sprintf(pbuf, "\tbuf max_buffer_delay_ms:%dms\n", - p->max_buffer_delay_ms); - - if (p->reg_base && p->flag & BUF_FLAG_IN_USE) { - int calc_delayms = 0; - u32 bitrate = 0, avg_bitrate = 0; - - calc_delayms = calculation_stream_delayed_ms( - (p->type == BUF_TYPE_AUDIO) ? PTS_TYPE_AUDIO : - PTS_TYPE_VIDEO, - &bitrate, - &avg_bitrate); - - if (calc_delayms >= 0) { - pbuf += sprintf(pbuf, - "\tbuf current delay:%dms\n", - calc_delayms); - pbuf += sprintf(pbuf, - "\tbuf bitrate latest:%dbps,avg:%dbps\n", - bitrate, avg_bitrate); - pbuf += sprintf(pbuf, - "\tbuf time after last pts:%d ms\n", - calculation_stream_ext_delayed_ms - ((p->type == BUF_TYPE_AUDIO) ? PTS_TYPE_AUDIO : - PTS_TYPE_VIDEO)); - - pbuf += sprintf(pbuf, - "\tbuf time after last write data :%d ms\n", - (int)(jiffies_64 - - p->last_write_jiffies64) * 1000 / HZ); - } - } - if (p->write_thread) { - pbuf += sprintf(pbuf, - "\twrite thread:%d/%d,fifo %d:%d,passed:%d\n", - threadrw_buffer_level(p), - threadrw_buffer_size(p), - threadrw_datafifo_len(p), - threadrw_freefifo_len(p), - threadrw_passed_len(p) - ); - } - } - - return pbuf - buf; -} - -static ssize_t videobufused_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - char *pbuf = buf; - struct stream_buf_s *p = NULL; - struct stream_buf_s *p_hevc = NULL; - - p = &bufs[0]; - if (has_hevc_vdec()) - p_hevc = &bufs[BUF_TYPE_HEVC]; - - if (p->flag & BUF_FLAG_IN_USE) - pbuf += sprintf(pbuf, "%d ", 1); - else if (has_hevc_vdec() && (p_hevc->flag & BUF_FLAG_IN_USE)) - pbuf += sprintf(pbuf, "%d ", 1); - else - pbuf += sprintf(pbuf, "%d ", 0); - return 1; -} - -static ssize_t vcodec_profile_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - return vcodec_profile_read(buf); -} - -static int reset_canuse_buferlevel(int levelx10000) -{ - int i; - struct stream_buf_s *p = NULL; - - if (levelx10000 >= 0 && levelx10000 <= 10000) - use_bufferlevelx10000 = levelx10000; - else - use_bufferlevelx10000 = 10000; - for (i = 0; i < amstream_buf_num; i++) { - p = &bufs[i]; - p->canusebuf_size = ((p->buf_size / 1024) * - use_bufferlevelx10000 / 10000) * 1024; - p->canusebuf_size += 1023; - p->canusebuf_size &= ~1023; - if (p->canusebuf_size > p->buf_size) - p->canusebuf_size = p->buf_size; - } - return 0; -} - -static ssize_t show_canuse_buferlevel(struct class *class, - struct class_attribute *attr, char *buf) -{ - ssize_t size = sprintf(buf, - "use_bufferlevel=%d/10000[=(set range[ 0~10000])=\n", - use_bufferlevelx10000); - return size; -} - -static ssize_t store_canuse_buferlevel(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int val; - ssize_t ret; - - /*ret = sscanf(buf, "%d", &val);*/ - ret = kstrtoint(buf, 0, &val); - - if (ret != 0) - return -EINVAL; - val = val; - reset_canuse_buferlevel(val); - return size; -} - -static ssize_t store_maxdelay(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int val; - ssize_t ret; - int i; - - /*ret = sscanf(buf, "%d", &val);*/ - ret = kstrtoint(buf, 0, &val); - if (ret != 0) - return -EINVAL; - for (i = 0; i < amstream_buf_num; i++) - bufs[i].max_buffer_delay_ms = val; - return size; -} - -static ssize_t show_maxdelay(struct class *class, - struct class_attribute *attr, - char *buf) -{ - ssize_t size = 0; - - size += sprintf(buf, "%dms video max buffered data delay ms\n", - bufs[0].max_buffer_delay_ms); - size += sprintf(buf, "%dms audio max buffered data delay ms\n", - bufs[1].max_buffer_delay_ms); - return size; -} - -static struct class_attribute amstream_class_attrs[] = { - __ATTR_RO(ports), - __ATTR_RO(bufs), - __ATTR_RO(vcodec_profile), - __ATTR_RO(videobufused), - __ATTR(canuse_buferlevel, S_IRUGO | S_IWUSR | S_IWGRP, - show_canuse_buferlevel, store_canuse_buferlevel), - __ATTR(max_buffer_delay_ms, S_IRUGO | S_IWUSR | S_IWGRP, show_maxdelay, - store_maxdelay), - __ATTR_NULL -}; - -static struct class amstream_class = { - .name = "amstream", - .class_attrs = amstream_class_attrs, -}; - -int amstream_request_firmware_from_sys(const char *file_name, - char *buf, int size) -{ - const struct firmware *firmware; - int err = 0; - struct device *micro_dev; - - pr_info("try load %s ...", file_name); - micro_dev = device_create(&amstream_class, - NULL, MKDEV(AMSTREAM_MAJOR, 100), - NULL, "videodec"); - if (micro_dev == NULL) { - pr_err("device_create failed =%d\n", err); - return -1; - } - err = request_firmware(&firmware, file_name, micro_dev); - if (err < 0) { - pr_err("can't load the %s,err=%d\n", file_name, err); - goto error1; - } - if (firmware->size > size) { - pr_err("not enough memory size for audiodsp code\n"); - err = -ENOMEM; - goto release; - } - - memcpy(buf, (char *)firmware->data, firmware->size); - /*mb(); don't need it*/ - pr_err("load mcode size=%zd\n mcode name %s\n", firmware->size, - file_name); - err = firmware->size; -release: - release_firmware(firmware); -error1: - device_destroy(&amstream_class, MKDEV(AMSTREAM_MAJOR, 100)); - return err; -} - -int videobufused_show_fun(const char *trigger, int id, char *sbuf, int size) -{ - int ret = -1; - void *buf, *getbuf = NULL; - if (size < PAGE_SIZE) { - getbuf = (void *)__get_free_page(GFP_KERNEL); - if (!getbuf) - return -ENOMEM; - buf = getbuf; - } else { - buf = sbuf; - } - - switch (id) { - case 0: - ret = videobufused_show(NULL, NULL , buf); - break; - default: - ret = -1; - } - if (ret > 0 && getbuf != NULL) { - ret = min_t(int, ret, size); - strncpy(sbuf, buf, ret); - } - if (getbuf != NULL) - free_page((unsigned long)getbuf); - return ret; -} - -static struct mconfig amports_configs[] = { - MC_PI32("def_4k_vstreambuf_sizeM", &def_4k_vstreambuf_sizeM), - MC_PI32("def_vstreambuf_sizeM", &def_vstreambuf_sizeM), - MC_PI32("slow_input", &slow_input), - MC_FUN_ID("videobufused", videobufused_show_fun, NULL, 0), -}; - - - -/*static struct resource memobj;*/ -static int amstream_probe(struct platform_device *pdev) -{ - int i; - int r; - struct stream_port_s *st; - - pr_err("Amlogic A/V streaming port init\n"); - - amstream_port_num = MAX_AMSTREAM_PORT_NUM; - amstream_buf_num = BUF_MAX_NUM; -/* - * r = of_reserved_mem_device_init(&pdev->dev); - * if (r == 0) - * pr_info("of probe done"); - * else { - * r = -ENOMEM; - * return r; - * } - */ - r = class_register(&amstream_class); - if (r) { - pr_err("amstream class create fail.\n"); - return r; - } - - r = astream_dev_register(); - if (r) - return r; - - r = register_chrdev(AMSTREAM_MAJOR, "amstream", &amstream_fops); - if (r < 0) { - pr_err("Can't allocate major for amstreaming device\n"); - - goto error2; - } - - amstream_dev_class = class_create(THIS_MODULE, DEVICE_NAME); - - for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) { - st->class_dev = device_create(amstream_dev_class, NULL, - MKDEV(AMSTREAM_MAJOR, i), NULL, - ports[i].name); - } - - amstream_adec_status = NULL; - if (tsdemux_class_register() != 0) { - r = (-EIO); - goto error3; - } - tsdemux_tsync_func_init(); - init_waitqueue_head(&amstream_sub_wait); - init_waitqueue_head(&amstream_userdata_wait); - reset_canuse_buferlevel(10000); - amstream_pdev = pdev; - amports_clock_gate_init(&amstream_pdev->dev); - - /*prealloc fetch buf to avoid no continue buffer later...*/ - stbuf_fetch_init(); - REG_PATH_CONFIGS("media.amports", amports_configs); - - /* poweroff the decode core because dos can not be reset when reboot */ - if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_G12A) - vdec_power_reset(); - - return 0; - - /* - * error4: - * tsdemux_class_unregister(); - */ -error3: - for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) - device_destroy(amstream_dev_class, MKDEV(AMSTREAM_MAJOR, i)); - class_destroy(amstream_dev_class); -error2: - unregister_chrdev(AMSTREAM_MAJOR, "amstream"); - /* error1: */ - astream_dev_unregister(); - return r; -} - -static int amstream_remove(struct platform_device *pdev) -{ - int i; - struct stream_port_s *st; - - if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) - stbuf_change_size(&bufs[BUF_TYPE_VIDEO], 0, false); - if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) - stbuf_change_size(&bufs[BUF_TYPE_AUDIO], 0, false); - stbuf_fetch_release(); - tsdemux_class_unregister(); - for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) - device_destroy(amstream_dev_class, MKDEV(AMSTREAM_MAJOR, i)); - - class_destroy(amstream_dev_class); - - unregister_chrdev(AMSTREAM_MAJOR, "amstream"); - - class_unregister(&amstream_class); - - astream_dev_unregister(); - - amstream_adec_status = NULL; - - pr_err("Amlogic A/V streaming port release\n"); - - return 0; -} - -void set_adec_func(int (*adec_func)(struct adec_status *)) -{ - amstream_adec_status = adec_func; -} - -void wakeup_sub_poll(void) -{ - atomic_inc(&subdata_ready); - wake_up_interruptible(&amstream_sub_wait); -} - -int get_sub_type(void) -{ - return sub_type; -} - -u32 get_audio_reset(void) -{ - return amstream_audio_reset; -} - -/*get pes buffers */ - -struct stream_buf_s *get_stream_buffer(int id) -{ - if (id >= BUF_MAX_NUM) - return 0; - return &bufs[id]; -} -EXPORT_SYMBOL(get_stream_buffer); -static const struct of_device_id amlogic_mesonstream_dt_match[] = { - { - .compatible = "amlogic, codec, streambuf", - }, - {}, -}; - -static struct platform_driver amstream_driver = { - .probe = amstream_probe, - .remove = amstream_remove, - .driver = { - .owner = THIS_MODULE, - .name = "mesonstream", - .of_match_table = amlogic_mesonstream_dt_match, - } -}; - -static int __init amstream_module_init(void) -{ - if (platform_driver_register(&amstream_driver)) { - pr_err("failed to register amstream module\n"); - return -ENODEV; - } - - if (subtitle_init()) { - pr_err("failed to init subtitle\n"); - return -ENODEV; - } - - return 0; -} - -static void __exit amstream_module_exit(void) -{ - platform_driver_unregister(&amstream_driver); - subtitle_exit(); -} - -module_init(amstream_module_init); -module_exit(amstream_module_exit); - -module_param(def_4k_vstreambuf_sizeM, uint, 0664); -MODULE_PARM_DESC(def_4k_vstreambuf_sizeM, - "\nDefault video Stream buf size for 4K MByptes\n"); - -module_param(def_vstreambuf_sizeM, uint, 0664); -MODULE_PARM_DESC(def_vstreambuf_sizeM, - "\nDefault video Stream buf size for < 1080p MByptes\n"); - -module_param(slow_input, uint, 0664); -MODULE_PARM_DESC(slow_input, "\n amstream slow_input\n"); - - -MODULE_DESCRIPTION("AMLOGIC streaming port driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c b/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c deleted file mode 100644 index a2bc5564209f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/amstream_profile.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include "amports_priv.h" - -static const struct codec_profile_t *vcodec_profile[SUPPORT_VDEC_NUM] = { 0 }; - -static int vcodec_profile_idx; - -ssize_t vcodec_profile_read(char *buf) -{ - char *pbuf = buf; - int i = 0; - - for (i = 0; i < vcodec_profile_idx; i++) { - pbuf += sprintf(pbuf, "%s:%s;\n", vcodec_profile[i]->name, - vcodec_profile[i]->profile); - } - - return pbuf - buf; -} - -int vcodec_profile_register(const struct codec_profile_t *vdec_profile) -{ - if (vcodec_profile_idx < SUPPORT_VDEC_NUM) { - vcodec_profile[vcodec_profile_idx] = vdec_profile; - vcodec_profile_idx++; - pr_debug("regist %s codec profile\n", vdec_profile->name); - - } - - return 0; -} -EXPORT_SYMBOL(vcodec_profile_register); - diff --git a/drivers/amlogic/media_modules/stream_input/parser/esparser.c b/drivers/amlogic/media_modules/stream_input/parser/esparser.c deleted file mode 100644 index 1cf8f02e056b..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/esparser.c +++ /dev/null @@ -1,970 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/esparser.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* #include */ -#include - -#include "../../frame_provider/decoder/utils/vdec.h" -#include -#include "streambuf_reg.h" -#include "streambuf.h" -#include "esparser.h" -#include "../amports/amports_priv.h" -#include "thread_rw.h" - -#include - - - -#define SAVE_SCR 0 - -#define ES_START_CODE_PATTERN 0x00000100 -#define ES_START_CODE_MASK 0xffffff00 -#define SEARCH_PATTERN_LEN 512 -#define ES_PARSER_POP READ_PARSER_REG(PFIFO_DATA) - -#define PARSER_WRITE (ES_WRITE | ES_PARSER_START) -#define PARSER_VIDEO (ES_TYPE_VIDEO) -#define PARSER_AUDIO (ES_TYPE_AUDIO) -#define PARSER_SUBPIC (ES_TYPE_SUBTITLE) -#define PARSER_PASSTHROUGH (ES_PASSTHROUGH | ES_PARSER_START) -#define PARSER_AUTOSEARCH (ES_SEARCH | ES_PARSER_START) -#define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START) -#define PARSER_BUSY (ES_PARSER_BUSY) - -#define MAX_DRM_PACKAGE_SIZE 0x500000 - - -static unsigned char *search_pattern; -static dma_addr_t search_pattern_map; -static u32 audio_real_wp; -static u32 audio_buf_start; -static u32 audio_buf_end; - -static const char esparser_id[] = "esparser-id"; - -static DECLARE_WAIT_QUEUE_HEAD(wq); - - -static u32 search_done; -static u32 video_data_parsed; -static u32 audio_data_parsed; -static atomic_t esparser_use_count = ATOMIC_INIT(0); -static DEFINE_MUTEX(esparser_mutex); - -static inline u32 get_buf_wp(u32 type) -{ - if (type == BUF_TYPE_AUDIO) - return audio_real_wp; - else - return 0; -} -static inline u32 get_buf_start(u32 type) -{ - if (type == BUF_TYPE_AUDIO) - return audio_buf_start; - else - return 0; -} -static inline u32 get_buf_end(u32 type) -{ - if (type == BUF_TYPE_AUDIO) - return audio_buf_end; - else - return 0; -} -static void set_buf_wp(u32 type, u32 wp) -{ - if (type == BUF_TYPE_AUDIO) { - audio_real_wp = wp; - WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP, wp/* & 0xffffff00*/); - } - return; -} - -static irqreturn_t esparser_isr(int irq, void *dev_id) -{ - u32 int_status = READ_PARSER_REG(PARSER_INT_STATUS); - - WRITE_PARSER_REG(PARSER_INT_STATUS, int_status); - - if (int_status & PARSER_INTSTAT_SC_FOUND) { - WRITE_PARSER_REG(PFIFO_RD_PTR, 0); - WRITE_PARSER_REG(PFIFO_WR_PTR, 0); - search_done = 1; - wake_up_interruptible(&wq); - } - return IRQ_HANDLED; -} - -static inline u32 buf_wp(u32 type) -{ - u32 wp; - - if ((READ_PARSER_REG(PARSER_ES_CONTROL) & ES_VID_MAN_RD_PTR) == 0) { - wp = -#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - (type == BUF_TYPE_HEVC) ? READ_VREG(HEVC_STREAM_WR_PTR) : -#endif - (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) : - (type == BUF_TYPE_AUDIO) ? - READ_AIU_REG(AIU_MEM_AIFIFO_MAN_WP) : - READ_PARSER_REG(PARSER_SUB_START_PTR); - } else { - wp = -#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - (type == BUF_TYPE_HEVC) ? READ_PARSER_REG(PARSER_VIDEO_WP) : -#endif - (type == BUF_TYPE_VIDEO) ? READ_PARSER_REG(PARSER_VIDEO_WP) : - (type == BUF_TYPE_AUDIO) ? - READ_AIU_REG(AIU_MEM_AIFIFO_MAN_WP) : - READ_PARSER_REG(PARSER_SUB_START_PTR); - } - - return wp; -} - -static ssize_t _esparser_write(const char __user *buf, - size_t count, struct stream_buf_s *stbuf, int isphybuf) -{ - size_t r = count; - const char __user *p = buf; - - u32 len = 0; - u32 parser_type; - int ret; - u32 wp; - dma_addr_t dma_addr = 0; - u32 type = stbuf->type; - - if (type == BUF_TYPE_HEVC) - parser_type = PARSER_VIDEO; - else if (type == BUF_TYPE_VIDEO) - parser_type = PARSER_VIDEO; - else if (type == BUF_TYPE_AUDIO) - parser_type = PARSER_AUDIO; - else - parser_type = PARSER_SUBPIC; - - wp = buf_wp(type); - - if (r > 0) { - if (isphybuf) - len = count; - else { - len = min_t(size_t, r, (size_t) FETCHBUF_SIZE); - - if (copy_from_user(fetchbuf, p, len)) - return -EFAULT; - dma_addr = dma_map_single( - amports_get_dma_device(), fetchbuf, - FETCHBUF_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - (dma_addr_t) dma_addr)) - return -EFAULT; - - } - - /* wmb(); don't need */ - /* reset the Write and read pointer to zero again */ - WRITE_PARSER_REG(PFIFO_RD_PTR, 0); - WRITE_PARSER_REG(PFIFO_WR_PTR, 0); - - WRITE_PARSER_REG_BITS(PARSER_CONTROL, len, ES_PACK_SIZE_BIT, - ES_PACK_SIZE_WID); - WRITE_PARSER_REG_BITS(PARSER_CONTROL, - parser_type | PARSER_WRITE | - PARSER_AUTOSEARCH, ES_CTRL_BIT, - ES_CTRL_WID); - - if (isphybuf) { - u32 buf_32 = (unsigned long)buf & 0xffffffff; - WRITE_PARSER_REG(PARSER_FETCH_ADDR, buf_32); - } else { - WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr); - dma_unmap_single(amports_get_dma_device(), dma_addr, - FETCHBUF_SIZE, DMA_TO_DEVICE); - } - - search_done = 0; - if (!(isphybuf & TYPE_PATTERN)) { - WRITE_PARSER_REG(PARSER_FETCH_CMD, - (7 << FETCH_ENDIAN) | len); - WRITE_PARSER_REG(PARSER_FETCH_ADDR, search_pattern_map); - WRITE_PARSER_REG(PARSER_FETCH_CMD, - (7 << FETCH_ENDIAN) | SEARCH_PATTERN_LEN); - } else { - WRITE_PARSER_REG(PARSER_FETCH_CMD, - (7 << FETCH_ENDIAN) | (len + 512)); - } - ret = wait_event_interruptible_timeout(wq, search_done != 0, - HZ / 5); - if (ret == 0) { - WRITE_PARSER_REG(PARSER_FETCH_CMD, 0); - - if (wp == buf_wp(type)) { - /*no data fetched */ - return -EAGAIN; - } else { - pr_info("W Timeout, but fetch ok,"); - pr_info("type %d len=%d,wpdiff=%d, isphy %x\n", - type, len, wp - buf_wp(type), isphybuf); - } - } else if (ret < 0) - return -ERESTARTSYS; - } - - if ((type == BUF_TYPE_VIDEO) - || (has_hevc_vdec() && (type == BUF_TYPE_HEVC))) - video_data_parsed += len; - else if (type == BUF_TYPE_AUDIO) - audio_data_parsed += len; - - threadrw_update_buffer_level(stbuf, len); - return len; -} - -static ssize_t _esparser_write_s(const char __user *buf, - size_t count, struct stream_buf_s *stbuf) -{ - size_t r = count; - const char __user *p = buf; - u32 len = 0; - int ret; - u32 wp, buf_start, buf_end; - dma_addr_t buf_wp_map; - u32 type = stbuf->type; - - if (type != BUF_TYPE_AUDIO) - BUG(); - wp = get_buf_wp(type); - buf_end = get_buf_end(type) + 8; - buf_start = get_buf_start(type); - /*pr_info("write wp 0x%x, count %d, start 0x%x, end 0x%x\n", - * wp, (u32)count, buf_start, buf_end);*/ - if (wp + count > buf_end) { - ret = copy_from_user(codec_mm_phys_to_virt(wp), - p, buf_end - wp); - if (ret > 0) { - len += buf_end - wp - ret; - buf_wp_map = dma_map_single(amports_get_dma_device(), - codec_mm_phys_to_virt(wp), len, DMA_TO_DEVICE); - wp += len; - pr_info("copy from user not finished\n"); - dma_unmap_single(NULL, buf_wp_map, len, DMA_TO_DEVICE); - set_buf_wp(type, wp); - goto end_write; - } else if (ret == 0) { - len += buf_end - wp; - buf_wp_map = dma_map_single(amports_get_dma_device(), - codec_mm_phys_to_virt(wp), len, DMA_TO_DEVICE); - wp = buf_start; - r = count - len; - dma_unmap_single(NULL, buf_wp_map, len, DMA_TO_DEVICE); - set_buf_wp(type, wp); - } else { - pr_info("copy from user failed 1\n"); - pr_info("w wp 0x%x, count %d, start 0x%x end 0x%x\n", - wp, (u32)count, buf_start, buf_end); - return -EAGAIN; - } - } - ret = copy_from_user(codec_mm_phys_to_virt(wp), p + len, r); - if (ret >= 0) { - len += r - ret; - buf_wp_map = dma_map_single(amports_get_dma_device(), - codec_mm_phys_to_virt(wp), r - ret, DMA_TO_DEVICE); - - if (ret > 0) - pr_info("copy from user not finished 2\n"); - wp += r - ret; - dma_unmap_single(NULL, buf_wp_map, r - ret, DMA_TO_DEVICE); - set_buf_wp(type, wp); - } else { - pr_info("copy from user failed 2\n"); - return -EAGAIN; - } - -end_write: - if (type == BUF_TYPE_AUDIO) - { - audio_data_parsed += len; - threadrw_update_buffer_level(stbuf, len); - } - - return len; -} - -s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64) -{ - u32 passed; - - if (buf->write_thread) - passed = threadrw_dataoffset(buf); - else - passed = video_data_parsed; - return pts_checkin_offset_us64(PTS_TYPE_VIDEO, passed, us64); - -} - -s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64) -{ - u32 passed; - - if (buf->write_thread) - passed = threadrw_dataoffset(buf); - else - passed = audio_data_parsed; - return pts_checkin_offset_us64(PTS_TYPE_AUDIO, passed, us64); -} - -s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts) -{ -#if 0 - if (buf->first_tstamp == INVALID_PTS) { - buf->flag |= BUF_FLAG_FIRST_TSTAMP; - buf->first_tstamp = pts; - return 0; - } -#endif - u32 passed = 0; - - mutex_lock(&esparser_mutex); - passed = video_data_parsed + threadrw_buffer_level(buf); - mutex_unlock(&esparser_mutex); - - return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts); - -} - -s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts) -{ -#if 0 - if (buf->first_tstamp == INVALID_PTS) { - buf->flag |= BUF_FLAG_FIRST_TSTAMP; - buf->first_tstamp = pts; - - return 0; - } -#endif - u32 passed = 0; - mutex_lock(&esparser_mutex); - passed = audio_data_parsed + threadrw_buffer_level(buf); - mutex_unlock(&esparser_mutex); - - return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts); -} - -s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec) -{ - s32 r = 0; - u32 pts_type; - u32 parser_sub_start_ptr; - u32 parser_sub_end_ptr; - u32 parser_sub_rp; - bool first_use = false; - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC)) - pts_type = PTS_TYPE_HEVC; - else - /* #endif */ - if (buf->type == BUF_TYPE_VIDEO) - pts_type = PTS_TYPE_VIDEO; - else if (buf->type == BUF_TYPE_AUDIO) - pts_type = PTS_TYPE_AUDIO; - else if (buf->type == BUF_TYPE_SUBTITLE) - pts_type = PTS_TYPE_MAX; - else - return -EINVAL; - mutex_lock(&esparser_mutex); - parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR); - parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR); - parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP); - - buf->flag |= BUF_FLAG_PARSER; - - if (atomic_add_return(1, &esparser_use_count) == 1) { - first_use = true; - - if (fetchbuf == 0) { - pr_info("%s: no fetchbuf\n", __func__); - r = -ENOMEM; - goto Err_1; - } - - if (search_pattern == NULL) { - search_pattern = kcalloc(1, - SEARCH_PATTERN_LEN, - GFP_KERNEL); - - if (search_pattern == NULL) { - pr_err("%s: no search_pattern\n", __func__); - r = -ENOMEM; - goto Err_1; - } - - /* build a fake start code to get parser interrupt */ - search_pattern[0] = 0x00; - search_pattern[1] = 0x00; - search_pattern[2] = 0x01; - search_pattern[3] = 0xff; - - search_pattern_map = dma_map_single( - amports_get_dma_device(), - search_pattern, - SEARCH_PATTERN_LEN, - DMA_TO_DEVICE); - } - - /* reset PARSER with first esparser_init() call */ - WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER); - - /* TS data path */ -#ifndef CONFIG_AM_DVB - WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0); -#else - tsdemux_set_reset_flag(); -#endif - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE); - - CLEAR_DEMUX_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE)); - - WRITE_PARSER_REG(PARSER_CONFIG, - (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | - (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | - (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); - - WRITE_PARSER_REG(PFIFO_RD_PTR, 0); - WRITE_PARSER_REG(PFIFO_WR_PTR, 0); - - WRITE_PARSER_REG(PARSER_SEARCH_PATTERN, ES_START_CODE_PATTERN); - WRITE_PARSER_REG(PARSER_SEARCH_MASK, ES_START_CODE_MASK); - - WRITE_PARSER_REG(PARSER_CONFIG, - (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | - (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | - PS_CFG_STARTCODE_WID_24 | - PS_CFG_PFIFO_ACCESS_WID_8 | - /* single byte pop */ - (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); - - WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH); - - } - - /* hook stream buffer with PARSER */ - if (has_hevc_vdec() && (pts_type == PTS_TYPE_HEVC)) { - WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start - + vdec->input.size - 8); - - if (vdec_single(vdec)) { - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - - /* set vififo_vbuf_rp_sel=>hevc */ - WRITE_VREG(DOS_GEN_CTRL0, 3 << 1); - - /* set use_parser_vbuf_wp */ - SET_VREG_MASK(HEVC_STREAM_CONTROL, - (1 << 3) | (0 << 4)); - /* set stream_fetch_enable */ - SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); - - /* set stream_buffer_hole with 256 bytes */ - SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1 << 29)); - } else { - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start); - } - video_data_parsed = 0; - } else if (pts_type == PTS_TYPE_VIDEO) { - WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, - vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, - vdec->input.start + vdec->input.size - 8); - if (vdec_single(vdec)) { - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, - MEM_BUFCTRL_INIT); - - if (has_hevc_vdec()) { - /* set vififo_vbuf_rp_sel=>vdec */ - WRITE_VREG(DOS_GEN_CTRL0, 0); - } - } else { - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - WRITE_PARSER_REG(PARSER_VIDEO_WP, - vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_RP, - vdec->input.start); - } - video_data_parsed = 0; - } else if (pts_type == PTS_TYPE_AUDIO) { - /* set wp as buffer start */ - SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, - MEM_BUFCTRL_MANUAL); - WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_RP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_AIU_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3); - SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, - MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, - MEM_BUFCTRL_INIT); - WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - audio_data_parsed = 0; - audio_buf_start = - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR); - audio_real_wp = audio_buf_start; - audio_buf_end = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR); - } else if (buf->type == BUF_TYPE_SUBTITLE) { - WRITE_PARSER_REG(PARSER_SUB_START_PTR, - parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, - parser_sub_end_ptr); - WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_rp); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - (7 << ES_SUB_WR_ENDIAN_BIT) | - ES_SUB_MAN_RD_PTR); - } - - if (pts_type < PTS_TYPE_MAX) { - r = pts_start(pts_type); - - if (r < 0) { - pr_info("esparser_init: pts_start failed\n"); - goto Err_1; - } - } -#if 0 - if (buf->flag & BUF_FLAG_FIRST_TSTAMP) { - if (buf->type == BUF_TYPE_VIDEO) - es_vpts_checkin(buf, buf->first_tstamp); - else if (buf->type == BUF_TYPE_AUDIO) - es_apts_checkin(buf, buf->first_tstamp); - - buf->flag &= ~BUF_FLAG_FIRST_TSTAMP; - } -#endif - - if (first_use) { - /*TODO irq */ - r = vdec_request_irq(PARSER_IRQ, esparser_isr, - "parser", (void *)esparser_id); - - if (r) { - pr_info("esparser_init: irq register failed.\n"); - goto Err_2; - } - - WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff); - WRITE_PARSER_REG(PARSER_INT_ENABLE, - PARSER_INTSTAT_SC_FOUND << - PARSER_INT_HOST_EN_BIT); - } - mutex_unlock(&esparser_mutex); - if (!(vdec_get_debug_flags() & 1) && - !codec_mm_video_tvp_enabled()) { - int block_size = (buf->type == BUF_TYPE_AUDIO) ? - PAGE_SIZE : PAGE_SIZE << 4; - int buf_num = (buf->type == BUF_TYPE_AUDIO) ? - 20 : (2 * SZ_1M)/(PAGE_SIZE << 4); - if (!(buf->type == BUF_TYPE_SUBTITLE)) - buf->write_thread = threadrw_alloc(buf_num, - block_size, - esparser_write_ex, - (buf->type == BUF_TYPE_AUDIO) ? 1 : 0); - /*manul mode for audio*/ - } - return 0; - -Err_2: - pts_stop(pts_type); - -Err_1: - atomic_dec(&esparser_use_count); - buf->flag &= ~BUF_FLAG_PARSER; - mutex_unlock(&esparser_mutex); - return r; -} -EXPORT_SYMBOL(esparser_init); - -void esparser_audio_reset_s(struct stream_buf_s *buf) -{ - ulong flags; - DEFINE_SPINLOCK(lock); - - spin_lock_irqsave(&lock, flags); - - SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_MANUAL); - WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_RP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_AIU_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3); - SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - - buf->flag |= BUF_FLAG_PARSER; - - audio_data_parsed = 0; - audio_real_wp = READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR); - audio_buf_start = READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR); - audio_buf_end = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR); - spin_unlock_irqrestore(&lock, flags); - - return; -} - -void esparser_audio_reset(struct stream_buf_s *buf) -{ - ulong flags; - DEFINE_SPINLOCK(lock); - - spin_lock_irqsave(&lock, flags); - - WRITE_PARSER_REG(PARSER_AUDIO_WP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_RP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - buf->flag |= BUF_FLAG_PARSER; - - audio_data_parsed = 0; - audio_real_wp = 0; - audio_buf_start = 0; - audio_buf_end = 0; - spin_unlock_irqrestore(&lock, flags); - -} - -void esparser_release(struct stream_buf_s *buf) -{ - u32 pts_type; - - /* check if esparser_init() is ever called */ - if ((buf->flag & BUF_FLAG_PARSER) == 0) - return; - - if (atomic_read(&esparser_use_count) == 0) { - pr_info - ("[%s:%d]###warning, esparser has been released already\n", - __func__, __LINE__); - return; - } - if (buf->write_thread) - threadrw_release(buf); - if (atomic_dec_and_test(&esparser_use_count)) { - WRITE_PARSER_REG(PARSER_INT_ENABLE, 0); - /*TODO irq */ - - vdec_free_irq(PARSER_IRQ, (void *)esparser_id); - - if (search_pattern) { - dma_unmap_single(amports_get_dma_device(), - search_pattern_map, - SEARCH_PATTERN_LEN, DMA_TO_DEVICE); - kfree(search_pattern); - search_pattern = NULL; - } - } - - if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC)) - pts_type = PTS_TYPE_VIDEO; - else if (buf->type == BUF_TYPE_VIDEO) - pts_type = PTS_TYPE_VIDEO; - else if (buf->type == BUF_TYPE_AUDIO) - pts_type = PTS_TYPE_AUDIO; - else if (buf->type == BUF_TYPE_SUBTITLE) { - buf->flag &= ~BUF_FLAG_PARSER; - return; - } else - return; - - buf->flag &= ~BUF_FLAG_PARSER; - pts_stop(pts_type); -} -EXPORT_SYMBOL(esparser_release); - -ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, - const char __user *buf, size_t count) -{ - s32 r; - u32 len; - u32 realcount, totalcount; - u32 re_count = count; - u32 havewritebytes = 0; - u32 leftcount = 0; - - struct drm_info tmpmm; - struct drm_info *drm = &tmpmm; - u32 res = 0; - int isphybuf = 0; - unsigned long realbuf; - - if (buf == NULL || count == 0) - return -EINVAL; - if (stbuf->write_thread) { - r = threadrw_flush_buffers(stbuf); - if (r < 0) - pr_info("Warning. drm flush threadrw failed[%d]\n", r); - } - res = copy_from_user(drm, buf, sizeof(struct drm_info)); - if (res) { - pr_info("drm kmalloc failed res[%d]\n", res); - return -EFAULT; - } - - if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) { - if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) { - pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); - return -EINVAL; - } - /* buf only has drminfo not have esdata; */ - realbuf = drm->drm_phy; - realcount = drm->drm_pktsize; - isphybuf = drm->drm_flag; - /* DRM_PRNT("drm_get_rawdata - *onlydrminfo drm->drm_hasesdata[0x%x] - * stbuf->type %d buf[0x%x]\n", - *drm->drm_hasesdata,stbuf->type,buf); - */ - } else if (drm->drm_hasesdata == 1) { /* buf is drminfo+es; */ - if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) { - pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); - return -EINVAL; - } - realcount = drm->drm_pktsize; - realbuf = (unsigned long)buf + sizeof(struct drm_info); - isphybuf = 0; - /* DRM_PRNT("drm_get_rawdata - * drminfo+es drm->drm_hasesdata[0x%x] - * stbuf->type %d\n",drm->drm_hasesdata,stbuf->type); - */ - } else { /* buf is hwhead; */ - realcount = count; - isphybuf = 0; - realbuf = (unsigned long)buf; - /* DRM_PRNT("drm_get_rawdata - * drm->drm_hasesdata[0x%x] - * len[%d] count[%d] realcout[%d]\n", - * drm->drm_hasesdata,len,count,realcount); - */ - } - - len = realcount; - count = realcount; - totalcount = realcount; - - while (len > 0) { - if (stbuf->type != BUF_TYPE_SUBTITLE - && stbuf_space(stbuf) < count) { - /*should not write partial data in drm mode*/ - r = stbuf_wait_space(stbuf, count); - if (r < 0) - return r; - if (stbuf_space(stbuf) < count) - return -EAGAIN; - } - len = min_t(u32, len, count); - - mutex_lock(&esparser_mutex); - - if (stbuf->type != BUF_TYPE_AUDIO) - r = _esparser_write((const char __user *)realbuf, len, - stbuf, isphybuf); - else - r = _esparser_write_s((const char __user *)realbuf, len, - stbuf); - if (r < 0) { - pr_info("drm_write _esparser_write failed [%d]\n", r); - mutex_unlock(&esparser_mutex); - return r; - } - havewritebytes += r; - leftcount = totalcount - havewritebytes; - if (havewritebytes == totalcount) { - - mutex_unlock(&esparser_mutex); - break; /* write ok; */ - } else if ((len > 0) && (havewritebytes < totalcount)) { - DRM_PRNT - ("d writebytes[%d] want[%d] total[%d] real[%d]\n", - havewritebytes, len, totalcount, realcount); - len = len - r; /* write again; */ - realbuf = realbuf + r; - } else { - pr_info - ("e writebytes[%d] want[%d] total[%d] real[%d]\n", - havewritebytes, len, totalcount, realcount); - } - mutex_unlock(&esparser_mutex); - } - - return re_count; -} -EXPORT_SYMBOL(drm_write); - -/* - *flags: - *1:phy - *2:noblock - */ -ssize_t esparser_write_ex(struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count, - int flags) -{ - - s32 r; - u32 len = count; - - if (buf == NULL || count == 0) - return -EINVAL; - - /*subtitle have no level to check, */ - if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) { - if ((flags & 2) || ((file != NULL) && - (file->f_flags & O_NONBLOCK))) { - len = stbuf_space(stbuf); - - if (len < 256) /* <1k.do eagain, */ - return -EAGAIN; - } else { - len = min(stbuf_canusesize(stbuf) / 8, len); - - if (stbuf_space(stbuf) < len) { - r = stbuf_wait_space(stbuf, len); - if (r < 0) - return r; - } - } - } - - stbuf->last_write_jiffies64 = jiffies_64; - - len = min_t(u32, len, count); - - mutex_lock(&esparser_mutex); - - if (stbuf->type == BUF_TYPE_AUDIO) - r = _esparser_write_s(buf, len, stbuf); - else - r = _esparser_write(buf, len, stbuf, flags & 1); - - mutex_unlock(&esparser_mutex); - - return r; -} -ssize_t esparser_write(struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count) -{ - if (stbuf->write_thread) { - ssize_t ret; - - ret = threadrw_write(file, stbuf, buf, count); - if (ret == -EAGAIN) { - u32 a, b; - int vdelay, adelay; - - if ((stbuf->type != BUF_TYPE_VIDEO) && - (stbuf->type != BUF_TYPE_HEVC)) - return ret; - if (stbuf->buf_size > (SZ_1M * 30) || - (threadrw_buffer_size(stbuf) > SZ_1M * 10) || - !threadrw_support_more_buffers(stbuf)) - return ret; - /*only chang buffer for video.*/ - vdelay = calculation_stream_delayed_ms( - PTS_TYPE_VIDEO, &a, &b); - adelay = calculation_stream_delayed_ms( - PTS_TYPE_AUDIO, &a, &b); - if ((vdelay > 100 && vdelay < 2000) && /*vdelay valid.*/ - ((vdelay < 500) ||/*video delay is short!*/ - (adelay > 0 && adelay < 1000))/*audio is low.*/ - ) { - /*on buffer fulled. - *if delay is less than 100ms we think errors, - *And we add more buffer on delay < 2s. - */ - int new_size = 2 * 1024 * 1024; - - threadrw_alloc_more_buffer_size( - stbuf, new_size); - } - } - return ret; - } - return esparser_write_ex(file, stbuf, buf, count, 0); -} -EXPORT_SYMBOL(esparser_write); - -void esparser_sub_reset(void) -{ - ulong flags; - DEFINE_SPINLOCK(lock); - u32 parser_sub_start_ptr; - u32 parser_sub_end_ptr; - - spin_lock_irqsave(&lock, flags); - - parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR); - parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR); - - WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); - WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); - - spin_unlock_irqrestore(&lock, flags); -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/esparser.h b/drivers/amlogic/media_modules/stream_input/parser/esparser.h deleted file mode 100644 index 24e6926e91ed..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/esparser.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/esparser.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef ESPARSER_H -#define ESPARSER_H - -#include "../../frame_provider/decoder/utils/vdec.h" - -extern ssize_t drm_write(struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count); - -extern s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec); -extern s32 esparser_init_s(struct stream_buf_s *buf); -extern void esparser_release(struct stream_buf_s *buf); -extern ssize_t esparser_write(struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count); -extern ssize_t esparser_write_ex(struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count, - int is_phy); - -extern s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64); - -extern s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64); - -extern int es_vpts_checkin(struct stream_buf_s *buf, u32 pts); - -extern int es_apts_checkin(struct stream_buf_s *buf, u32 pts); - -extern void esparser_audio_reset(struct stream_buf_s *buf); -extern void esparser_audio_reset_s(struct stream_buf_s *buf); - -extern void esparser_sub_reset(void); - -#ifdef CONFIG_AM_DVB -extern int tsdemux_set_reset_flag(void); -#endif - -/* TODO: move to register headers */ -#define ES_PACK_SIZE_BIT 8 -#define ES_PACK_SIZE_WID 24 - -#define ES_CTRL_WID 8 -#define ES_CTRL_BIT 0 -#define ES_TYPE_MASK (3 << 6) -#define ES_TYPE_VIDEO (0 << 6) -#define ES_TYPE_AUDIO (1 << 6) -#define ES_TYPE_SUBTITLE (2 << 6) - -#define ES_WRITE (1<<5) -#define ES_PASSTHROUGH (1<<4) -#define ES_INSERT_BEFORE_ES_WRITE (1<<3) -#define ES_DISCARD (1<<2) -#define ES_SEARCH (1<<1) -#define ES_PARSER_START (1<<0) -#define ES_PARSER_BUSY (1<<0) - -#define PARSER_INTSTAT_FETCH_CMD (1<<7) -#define PARSER_INTSTAT_PARSE (1<<4) -#define PARSER_INTSTAT_DISCARD (1<<3) -#define PARSER_INTSTAT_INSZERO (1<<2) -#define PARSER_INTSTAT_ACT_NOSSC (1<<1) -#define PARSER_INTSTAT_SC_FOUND (1<<0) - -#define FETCH_CIR_BUF (1<<31) -#define FETCH_CHK_BUF_STOP (1<<30) -#define FETCH_PASSTHROUGH (1<<29) -#define FETCH_ENDIAN 27 -#define FETCH_PASSTHROUGH_TYPE_MASK (0x3<<27) -#define FETCH_ENDIAN_MASK (0x7<<27) -#define FETCH_BUF_SIZE_MASK (0x7ffffff) -#define FETCH_CMD_PTR_MASK 3 -#define FETCH_CMD_RD_PTR_BIT 5 -#define FETCH_CMD_WR_PTR_BIT 3 -#define FETCH_CMD_NUM_MASK 3 -#define FETCH_CMD_NUM_BIT 0 - -#define ES_COUNT_MASK 0xfff -#define ES_COUNT_BIT 20 -#define ES_REQ_PENDING (1<<19) -#define ES_PASSTHROUGH_EN (1<<18) -#define ES_PASSTHROUGH_TYPE_MASK (3<<16) -#define ES_PASSTHROUGH_TYPE_VIDEO (0<<16) -#define ES_PASSTHROUGH_TYPE_AUDIO (1<<16) -#define ES_PASSTHROUGH_TYPE_SUBTITLE (2<<16) -#define ES_WR_ENDIAN_MASK (0x7) -#define ES_SUB_WR_ENDIAN_BIT 9 -#define ES_SUB_MAN_RD_PTR (1<<8) -#define ES_AUD_WR_ENDIAN_BIT 5 -#define ES_AUD_MAN_RD_PTR (1<<4) -#define ES_VID_WR_ENDIAN_BIT 1 -#define ES_VID_MAN_RD_PTR (1<<0) - -#define PS_CFG_FETCH_DMA_URGENT (1<<31) -#define PS_CFG_STREAM_DMA_URGENT (1<<30) -#define PS_CFG_FORCE_PFIFO_REN (1<<29) -#define PS_CFG_PFIFO_PEAK_EN (1<<28) -#define PS_CFG_SRC_SEL_BIT 24 -#define PS_CFG_SRC_SEL_MASK (3< -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../streambuf.h" -#include "c_stb_define.h" -#include "c_stb_regs_define.h" -#include "aml_dvb.h" -#include "aml_dvb_reg.h" - - -#define ENABLE_SEC_BUFF_WATCHDOG -#define USE_AHB_MODE -#define PR_ERROR_SPEED_LIMIT - -#define pr_dbg_flag(_f, _args...)\ - do {\ - if (debug_dmx&(_f))\ - printk(_args);\ - } while (0) -#define pr_dbg_irq_flag(_f, _args...)\ - do {\ - if (debug_irq&(_f))\ - printk(_args);\ - } while (0) -#define pr_dbg(args...) pr_dbg_flag(0x1, args) -#define pr_dbg_irq(args...)pr_dbg_irq_flag(0x1, args) -#define pr_dbg_irq_dvr(args...)pr_dbg_irq_flag(0x2, args) -#define pr_dbg_sf(args...) pr_dbg_flag(0x4, args) -#define pr_dbg_irq_sf(args...) pr_dbg_irq_flag(0x4, args) -#define pr_dbg_ss(args...) pr_dbg_flag(0x8, args) -#define pr_dbg_irq_ss(args...) pr_dbg_irq_flag(0x8, args) -#define pr_dbg_irq_pes(args...) pr_dbg_irq_flag(0x10, args) - -#ifdef PR_ERROR_SPEED_LIMIT -static u32 last_pr_error_time; -#define pr_error(fmt, _args...)\ - do {\ - u32 diff = jiffies_to_msecs(jiffies - last_pr_error_time);\ - if (!last_pr_error_time || diff > 50) {\ - pr_err("DVB:" fmt, ## _args);\ - last_pr_error_time = jiffies;\ - } \ - } while (0) -#else -#define pr_error(fmt, args...) pr_err("DVB: " fmt, ## args) -#endif - -#define pr_inf(fmt, args...) printk("DVB: " fmt, ## args) - -#define dump(b, l) \ - do { \ - int i; \ - printk("dump: "); \ - for (i = 0; i < (l); i++) {\ - if (!(i&0xf)) \ - printk("\n\t"); \ - printk("%02x ", *(((unsigned char *)(b))+i)); \ - } \ - printk("\n"); \ - } while (0) - -MODULE_PARM_DESC(debug_dmx, "\n\t\t Enable demux debug information"); -static int debug_dmx; -module_param(debug_dmx, int, 0644); - -MODULE_PARM_DESC(debug_irq, "\n\t\t Enable demux IRQ debug information"); -static int debug_irq; -module_param(debug_irq, int, 0644); - -MODULE_PARM_DESC(disable_dsc, "\n\t\t Disable discrambler"); -static int disable_dsc; -module_param(disable_dsc, int, 0644); - -/*For old version kernel */ -#ifndef MESON_CPU_MAJOR_ID_GXL -#define MESON_CPU_MAJOR_ID_GXL 0x21 -#endif - -static int npids = CHANNEL_COUNT; -#define MOD_PARAM_DECLARE_CHANPIDS(_dmx) \ -MODULE_PARM_DESC(debug_dmx##_dmx##_chanpids, "\n\t\t pids of dmx channels"); \ -static short debug_dmx##_dmx##_chanpids[CHANNEL_COUNT] = \ - {[0 ... (CHANNEL_COUNT - 1)] = -1}; \ -module_param_array(debug_dmx##_dmx##_chanpids, short, &npids, 0444) - -#define CIPLUS_OUTPUT_AUTO 8 -static int ciplus_out_sel = CIPLUS_OUTPUT_AUTO; -static int ciplus_out_auto_mode = 1; - -MOD_PARAM_DECLARE_CHANPIDS(0); -MOD_PARAM_DECLARE_CHANPIDS(1); -MOD_PARAM_DECLARE_CHANPIDS(2); - -#define set_debug_dmx_chanpids(_dmx, _idx, _pid)\ - do { \ - if ((_dmx) == 0) \ - debug_dmx0_chanpids[(_idx)] = (_pid); \ - else if ((_dmx) == 1) \ - debug_dmx1_chanpids[(_idx)] = (_pid); \ - else if ((_dmx) == 2) \ - debug_dmx2_chanpids[(_idx)] = (_pid); \ - } while (0) - -MODULE_PARM_DESC(debug_sf_user, "\n\t\t only for sf mode check"); -static int debug_sf_user; -module_param(debug_sf_user, int, 0444); - -MODULE_PARM_DESC(force_sec_sf, "\n\t\t force sf mode for sec filter"); -static int force_sec_sf; -module_param(force_sec_sf, int, 0644); - -MODULE_PARM_DESC(force_pes_sf, "\n\t\t force sf mode for pes filter"); -static int force_pes_sf; -module_param(force_pes_sf, int, 0644); - -MODULE_PARM_DESC(use_of_sop, "\n\t\t Enable use of sop input"); -static int use_of_sop; -module_param(use_of_sop, int, 0644); - -/*#define CIPLUS_KEY0 0x16f8 -#define CIPLUS_KEY1 0x16f9 -#define CIPLUS_KEY2 0x16fa -#define CIPLUS_KEY3 0x16fb -#define CIPLUS_KEY_WR 0x16fc -#define CIPLUS_CONFIG 0x16fd -#define CIPLUS_ENDIAN 0x16fe*/ - -static u32 old_stb_top_config; -static u32 old_fec_input_control; -static int have_old_stb_top_config = 1; -static int have_old_fec_input_control = 1; - -static void -dmx_write_reg(int r, u32 v) -{ - u32 oldv, mask; - - if (disable_dsc) { - if (r == STB_TOP_CONFIG) { - if (have_old_stb_top_config) { - oldv = old_stb_top_config; - have_old_stb_top_config = 0; - } else { - oldv = READ_MPEG_REG(STB_TOP_CONFIG); - } - - mask = (1<<7)|(1<<15)|(3<<26)|(7<<28); - v &= ~mask; - v |= (oldv & mask); - } else if (r == FEC_INPUT_CONTROL) { - if (have_old_fec_input_control) { - oldv = old_fec_input_control; - have_old_fec_input_control = 0; - } else { - oldv = READ_MPEG_REG(FEC_INPUT_CONTROL); - } - - mask = (1<<15); - v &= ~mask; - v |= (oldv & mask); - } else if ((r == RESET1_REGISTER) || (r == RESET3_REGISTER)) { - if (!have_old_stb_top_config) { - have_old_stb_top_config = 1; - old_stb_top_config = - READ_MPEG_REG(STB_TOP_CONFIG); - } - if (!have_old_fec_input_control) { - have_old_fec_input_control = 1; - old_fec_input_control = - READ_MPEG_REG(FEC_INPUT_CONTROL); - } - } else if ((r == TS_PL_PID_INDEX) || (r == TS_PL_PID_DATA) - || (r == COMM_DESC_KEY0) - || (r == COMM_DESC_KEY1) - || (r == COMM_DESC_KEY_RW) - || (r == CIPLUS_KEY0) - || (r == CIPLUS_KEY1) - || (r == CIPLUS_KEY2) - || (r == CIPLUS_KEY3) - || (r == CIPLUS_KEY_WR) - || (r == CIPLUS_CONFIG) - || (r == CIPLUS_ENDIAN)) { - return; - } - } - WRITE_MPEG_REG(r, v); -} - -#undef WRITE_MPEG_REG -#define WRITE_MPEG_REG(r, v) dmx_write_reg(r, v) - -#define DMX_READ_REG(i, r)\ - ((i)?((i == 1)?READ_MPEG_REG(r##_2) :\ - READ_MPEG_REG(r##_3)) : READ_MPEG_REG(r)) - -#define DMX_WRITE_REG(i, r, d)\ - do {\ - if (i == 1) {\ - WRITE_MPEG_REG(r##_2, d);\ - } else if (i == 2) {\ - WRITE_MPEG_REG(r##_3, d);\ - } \ - else {\ - WRITE_MPEG_REG(r, d);\ - } \ - } while (0) - -#define READ_PERI_REG READ_CBUS_REG -#define WRITE_PERI_REG WRITE_CBUS_REG - -#define READ_ASYNC_FIFO_REG(i, r)\ - ((i) ? ((i-1)?READ_PERI_REG(ASYNC_FIFO1_##r):\ - READ_PERI_REG(ASYNC_FIFO2_##r)) : READ_PERI_REG(ASYNC_FIFO_##r)) - -#define WRITE_ASYNC_FIFO_REG(i, r, d)\ - do {\ - if (i == 2) {\ - WRITE_PERI_REG(ASYNC_FIFO1_##r, d);\ - } else if (i == 0) {\ - WRITE_PERI_REG(ASYNC_FIFO_##r, d);\ - } else {\ - WRITE_PERI_REG(ASYNC_FIFO2_##r, d);\ - } \ - } while (0) - -#define CLEAR_ASYNC_FIFO_REG_MASK(i, reg, mask) \ - WRITE_ASYNC_FIFO_REG(i, reg, \ - (READ_ASYNC_FIFO_REG(i, reg)&(~(mask)))) - -#define DVR_FEED(f) \ - ((f) && ((f)->type == DMX_TYPE_TS) && \ - (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET)) - -#define MOD_PARAM_DECLARE_CHANREC(_dmx) \ -MODULE_PARM_DESC(dmx##_dmx##_chanrec_enable, \ - "\n\t\t record by channel, one time use in the beginning"); \ -static int dmx##_dmx##_chanrec_enable; \ -module_param(dmx##_dmx##_chanrec_enable, int, 0644); \ -MODULE_PARM_DESC(dmx##_dmx##_chanrec, "\n\t\t record channels bits"); \ -static int dmx##_dmx##_chanrec; \ -module_param(dmx##_dmx##_chanrec, int, 0644) - -MOD_PARAM_DECLARE_CHANREC(0); -MOD_PARAM_DECLARE_CHANREC(1); -MOD_PARAM_DECLARE_CHANREC(2); - -#define MOD_PARAM_DECLARE_CHANPROC(_dmx) \ -MODULE_PARM_DESC(dmx##_dmx##_chanproc_enable, "channel further processing"); \ -static int dmx##_dmx##_chanproc_enable; \ -module_param(dmx##_dmx##_chanproc_enable, int, 0644); \ -MODULE_PARM_DESC(dmx##_dmx##_chanproc, "further process channels bits"); \ -static int dmx##_dmx##_chanproc; \ -module_param(dmx##_dmx##_chanproc, int, 0644) - -MOD_PARAM_DECLARE_CHANPROC(0); -MOD_PARAM_DECLARE_CHANPROC(1); -MOD_PARAM_DECLARE_CHANPROC(2); - -#define DMX_CH_OP_CHANREC 0 -#define DMX_CH_OP_CHANPROC 1 - -static inline int _setbit(int v, int b) { return v|(1<id == SF_DMX_ID) \ - && ((struct aml_dvb *)(_dmx)->demux.priv)->swfilter.user) -#define sf_afifo_sf(_afifo) \ - (((_afifo)->id == SF_AFIFO_ID) && (_afifo)->dvb->swfilter.user) -#define dmx_get_dev(dmx) (((struct aml_dvb *)((dmx)->demux.priv))->dev) -#define asyncfifo_get_dev(afifo) ((afifo)->dvb->dev) - - -/*Section buffer watchdog*/ -static void section_buffer_watchdog_func(unsigned long arg) -{ - struct aml_dvb *dvb = (struct aml_dvb *)arg; - struct aml_dmx *dmx; - u32 section_busy32 = 0, om_cmd_status32 = 0, - demux_channel_activity32 = 0; - u16 demux_int_status1 = 0; - u32 device_no = 0; - u32 filter_number = 0; - u32 i = 0; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - - for (device_no = 0; device_no < DMX_DEV_COUNT; device_no++) { - - dmx = &dvb->dmx[device_no]; - - if (dvb->dmx_watchdog_disable[device_no]) - continue; - - if (!dmx->init) - continue; - - om_cmd_status32 = - DMX_READ_REG(device_no, OM_CMD_STATUS); - demux_channel_activity32 = - DMX_READ_REG(device_no, DEMUX_CHANNEL_ACTIVITY); - section_busy32 = - DMX_READ_REG(device_no, SEC_BUFF_BUSY); -#if 1 - if (om_cmd_status32 & 0x8fc2) { - /* bit 15:12 -- om_cmd_count */ - /* bit 11:9 -- overflow_count */ - /* bit 8:6 -- om_overwrite_count */ - /* bit 1 -- om_cmd_overflow */ - /*BUG: If the recoder is running, return */ - if (dmx->record) - goto end; - /*Reset the demux */ - pr_dbg("reset the demux\n" - "%04x\t%03x\t%03x\t%03x\t%01x\t%01x\t" - "%x\t%x\tdmx%d:status:0x%x\n", - (om_cmd_status32 >> 12) & 0xf, - (om_cmd_status32 >> 9) & 0x7, - (om_cmd_status32 >> 6) & 0x7, - (om_cmd_status32 >> 3) & 0x7, - (om_cmd_status32 >> 2) & 0x1, - (om_cmd_status32 >> 1) & 0x1, - demux_channel_activity32, section_busy32, - dmx->id, om_cmd_status32); - - dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0); - goto end; - } -#else - /* bit 15:12 -- om_cmd_count (read only) */ - /* bit 11:9 -- overflow_count */ - /* bit 11:9 -- om_cmd_wr_ptr(read only) */ - /* bit 8:6 -- om_overwrite_count */ - /* bit 8:6 -- om_cmd_rd_ptr(read only) */ - /* bit 5:3 -- type_stb_om_w_rd(read only) */ - /* bit 2 -- unit_start_stb_om_w_rd(read only) */ - /* bit 1 -- om_cmd_overflow(read only) */ - /* bit 0 -- om_cmd_pending(read) */ - /* bit 0 -- om_cmd_read_finished(write) */ - if (om_cmd_status32 & 0x0002) { - pr_error("reset the demux\n"); - dmx_reset_hw_ex(dvb, 0); - goto end; - } -#endif - section_busy32 = - DMX_READ_REG(device_no, SEC_BUFF_BUSY); - if (LARGE_SEC_BUFF_MASK == - (section_busy32 & LARGE_SEC_BUFF_MASK)) { - /*All the largest section buffers occupied, - * clear buffers - */ - DMX_WRITE_REG(device_no, - SEC_BUFF_READY, section_busy32); - } else { - for (i = 0; i < SEC_BUF_COUNT; i++) { - if (!(section_busy32 & (1 << i))) - continue; - DMX_WRITE_REG(device_no, SEC_BUFF_NUMBER, i); - filter_number = DMX_READ_REG(device_no, - SEC_BUFF_NUMBER); - filter_number >>= 8; - if ((filter_number >= FILTER_COUNT) - /* >=31, do not handle this case */ - || ((filter_number < FILTER_COUNT) - && dmx->filter[filter_number].used)) - section_busy32 &= ~(1 << i); - } - if (section_busy32 & (dmx->smallsec.enable ? - 0x7FFFFFFF : - LARGE_SEC_BUFF_MASK)) { - /*Clear invalid buffers */ - DMX_WRITE_REG(device_no, - SEC_BUFF_READY, - section_busy32); - pr_error("clear invalid buffer 0x%x\n", - section_busy32); - } -#if 0 - section_busy32 = 0x7fffffff; - for (i = 0; i < SEC_BUF_BUSY_SIZE; i++) { - dmx->section_busy[i] = ( - (i == SEC_BUF_BUSY_SIZE - 1) ? - DMX_READ_REG(device_no, SEC_BUFF_BUSY) : - dmx->section_busy[i + 1]); - section_busy32 &= dmx->section_busy[i]; - } - - /*count the number of '1' bits */ - i = section_busy32; - i = (i & 0x55555555) + ((i & 0xaaaaaaaa) >> 1); - i = (i & 0x33333333) + ((i & 0xcccccccc) >> 2); - i = (i & 0x0f0f0f0f) + ((i & 0xf0f0f0f0) >> 4); - i = (i & 0x00ff00ff) + ((i & 0xff00ff00) >> 8); - i = (i & 0x0000ffff) + ((i & 0xffff0000) >> 16); - if (i > LARGE_SEC_BUFF_COUNT) { - /*too long some of the section - * buffers are being processed - */ - DMX_WRITE_REG(device_no, SEC_BUFF_READY, - section_busy32); - } -#endif - } - demux_int_status1 = - DMX_READ_REG(device_no, STB_INT_STATUS) & 0xfff7; - if (demux_int_status1 & (1 << TS_ERROR_PIN)) { - DMX_WRITE_REG(device_no, - STB_INT_STATUS, - (1 << TS_ERROR_PIN)); - } - } - -end: - spin_unlock_irqrestore(&dvb->slock, flags); -#ifdef ENABLE_SEC_BUFF_WATCHDOG - mod_timer(&dvb->watchdog_timer, - jiffies + msecs_to_jiffies(WATCHDOG_TIMER)); -#endif -} - -static inline int sec_filter_match(struct aml_dmx *dmx, struct aml_filter *f, - u8 *p) -{ - int b; - u8 neq = 0; - - if (!f->used || !dmx->channel[f->chan_id].used) - return 0; - - for (b = 0; b < FILTER_LEN; b++) { - u8 xor = p[b] ^ f->value[b]; - - if (xor & f->maskandmode[b]) - return 0; - - if (xor & f->maskandnotmode[b]) - neq = 1; - } - - if (f->neq && !neq) - return 0; - - return 1; -} - -static void trigger_crc_monitor(struct aml_dmx *dmx) -{ - if (!dmx->crc_check_time) { - dmx->crc_check_time = jiffies; - dmx->crc_check_count = 0; - } - - if (dmx->crc_check_count > 100) { - if (jiffies_to_msecs(jiffies - dmx->crc_check_time) <= 1000) { - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - - pr_error("Too many crc fail (%d crc fail in %d ms)!\n", - dmx->crc_check_count, - jiffies_to_msecs(jiffies - dmx->crc_check_time) - ); - dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0); - } - dmx->crc_check_time = 0; - } - - dmx->crc_check_count++; -} -static int section_crc(struct aml_dmx *dmx, struct aml_filter *f, u8 *p) -{ - int sec_len = (((p[1] & 0xF) << 8) | p[2]) + 3; - struct dvb_demux_feed *feed = dmx->channel[f->chan_id].feed; - - if (feed->feed.sec.check_crc) { - struct dvb_demux *demux = feed->demux; - struct dmx_section_feed *sec = &feed->feed.sec; - int section_syntax_indicator; - - section_syntax_indicator = ((p[1] & 0x80) != 0); - sec->seclen = sec_len; - sec->crc_val = ~0; - if (demux->check_crc32(feed, p, sec_len)) { - pr_error("section CRC check failed!\n"); - -#if 0 -{ - int i; - - pr_error("sec:[%#lx:%#lx:%#lx-%#lx:%#lx:%#lx-%#lx:%#lx:%#lx]\n", - dmx->sec_cnt[0], dmx->sec_cnt_match[0], dmx->sec_cnt_crc_fail[0], - dmx->sec_cnt[1], dmx->sec_cnt_match[1], dmx->sec_cnt_crc_fail[1], - dmx->sec_cnt[2], dmx->sec_cnt_match[2], dmx->sec_cnt_crc_fail[2]); - pr_error("bad sec[%d]:\n", sec_len); - /* - * if (sec_len > 256) - * sec_len = 256; - * for (i = 0; i < sec_len; i++) { - * pr_err("%02x ", p[i]); - * if (!((i + 1) % 16)) - * pr_err("\n"); - * } - */ -} -#endif - trigger_crc_monitor(dmx); - return 0; - } -#if 0 - int i; - - for (i = 0; i < sec_len; i++) { - pr_dbg("%02x ", p[i]); - if (!((i + 1) % 16)) - pr_dbg("\n"); - } - pr_dbg("\nsection data\n"); -#endif - } - - return 1; -} - -static void section_notify(struct aml_dmx *dmx, struct aml_filter *f, u8 *p) -{ - int sec_len = (((p[1] & 0xF) << 8) | p[2]) + 3; - struct dvb_demux_feed *feed = dmx->channel[f->chan_id].feed; - - if (feed && feed->cb.sec) - feed->cb.sec(p, sec_len, NULL, 0, f->filter); -} - -static void hardware_match_section(struct aml_dmx *dmx, - u16 sec_num, u16 buf_num) -{ - u8 *p = (u8 *) dmx->sec_buf[buf_num].addr; - struct aml_filter *f; - int chid, i; - int need_crc = 1; - - if (sec_num >= FILTER_COUNT) { - pr_dbg("sec_num invalid: %d\n", sec_num); - return; - } - - dma_sync_single_for_cpu(dmx_get_dev(dmx), - dmx->sec_pages_map + (buf_num << 0x0c), - (1 << 0x0c), DMA_FROM_DEVICE); - - f = &dmx->filter[sec_num]; - chid = f->chan_id; - - dmx->sec_cnt[SEC_CNT_HW]++; - - for (i = 0; i < FILTER_COUNT; i++) { - f = &dmx->filter[i]; - if (f->chan_id != chid) - continue; - if (sec_filter_match(dmx, f, p)) { - if (need_crc) { - dmx->sec_cnt_match[SEC_CNT_HW]++; - if (!section_crc(dmx, f, p)) { - dmx->sec_cnt_crc_fail[SEC_CNT_HW]++; - return; - } - need_crc = 0; - } - section_notify(dmx, f, p); - } - } -} - -static void software_match_section(struct aml_dmx *dmx, u16 buf_num) -{ - u8 *p = (u8 *) dmx->sec_buf[buf_num].addr; - struct aml_filter *f, *fmatch = NULL; - int i, fid = -1; - - dma_sync_single_for_cpu(dmx_get_dev(dmx), - dmx->sec_pages_map + (buf_num << 0x0c), - (1 << 0x0c), DMA_FROM_DEVICE); - - dmx->sec_cnt[SEC_CNT_SW]++; - - for (i = 0; i < FILTER_COUNT; i++) { - f = &dmx->filter[i]; - - if (sec_filter_match(dmx, f, p)) { - pr_dbg("[software match]filter %d match, pid %d\n", - i, dmx->channel[f->chan_id].pid); - if (!fmatch) { - fmatch = f; - fid = i; - } else { - pr_error("[sw match]Muli-filter match this\n" - "section, will skip this section\n"); - return; - } - } - } - - if (fmatch) { - pr_dbg("[software match]dispatch\n" - "section to filter %d pid %d\n", - fid, dmx->channel[fmatch->chan_id].pid); - dmx->sec_cnt_match[SEC_CNT_SW]++; - if (section_crc(dmx, fmatch, p)) - section_notify(dmx, fmatch, p); - else - dmx->sec_cnt_crc_fail[SEC_CNT_SW]++; - } else { - pr_dbg("[software match]this section do not\n" - "match any filter!!!\n"); - } -} - - -static int _rbuf_write(struct dvb_ringbuffer *buf, const u8 *src, size_t len) -{ - ssize_t free; - - if (!len) - return 0; - if (!buf->data) - return 0; - - free = dvb_ringbuffer_free(buf); - if (len > free) { - pr_error("sf: buffer overflow\n"); - return -EOVERFLOW; - } - - return dvb_ringbuffer_write(buf, src, len); -} - -static int _rbuf_filter_pkts(struct dvb_ringbuffer *rb, - u8 *wrapbuf, - void (*swfilter_packets)(struct dvb_demux *demux, - const u8 *buf, - size_t count), - struct dvb_demux *demux) -{ - ssize_t len1 = 0; - ssize_t len2 = 0; - size_t off; - size_t count; - size_t size; - - if (debug_irq & 0x4) - dump(&rb->data[rb->pread], (debug_irq & 0xFFF00) >> 8); - - /* - * rb|====--------===[0x47]====| - * ^ ^ - * wr rd - */ - - len1 = rb->pwrite - rb->pread; - if (len1 < 0) { - len1 = rb->size - rb->pread; - len2 = rb->pwrite; - } - - for (off = 0; off < len1; off++) { - if (rb->data[rb->pread + off] == 0x47) - break; - } - - if (off) - pr_dbg_irq_sf("off ->|%zd\n", off); - - len1 -= off; - rb->pread = (rb->pread + off) % rb->size; - - count = len1 / 188; - if (count) { - pr_dbg_irq_sf("pkt >> 1[%zd<->%zd]\n", rb->pread, rb->pwrite); - swfilter_packets(demux, rb->data + rb->pread, count); - - size = count * 188; - len1 -= size; - rb->pread += size; - } - - if (len2 && len1 && ((len1 + len2) > 188)) { - pr_dbg_irq_sf("pkt >> 2[%zd<->%zd]\n", rb->pread, rb->pwrite); - size = 188 - len1; - memcpy(wrapbuf, rb->data + rb->pread, len1); - memcpy(wrapbuf + len1, rb->data, size); - swfilter_packets(demux, wrapbuf, 1); - rb->pread = size; - len2 -= size; - } - - if (len2) { - pr_dbg_irq_sf("pkt >> 3[%zd<->%zd]\n", rb->pread, rb->pwrite); - count = len2 / 188; - if (count) { - swfilter_packets(demux, rb->data + rb->pread, count); - rb->pread += count * 188; - } - } - return 0; -} - -static void smallsection_match_section(struct aml_dmx *dmx, u8 *p, u16 sec_num) -{ - struct aml_filter *f; - int chid, i; - int need_crc = 1; - - if (sec_num >= FILTER_COUNT) { - pr_dbg("sec_num invalid: %d\n", sec_num); - return; - } - - f = &dmx->filter[sec_num]; - chid = f->chan_id; - - dmx->sec_cnt[SEC_CNT_SS]++; - - for (i = 0; i < FILTER_COUNT; i++) { - f = &dmx->filter[i]; - if (f->chan_id != chid) - continue; - if (sec_filter_match(dmx, f, p)) { - if (need_crc) { - dmx->sec_cnt_match[SEC_CNT_SS]++; - if (!section_crc(dmx, f, p)) { - dmx->sec_cnt_crc_fail[SEC_CNT_SS]++; - return; - } - need_crc = 0; - } - section_notify(dmx, f, p); - } - } - -} -static void process_smallsection(struct aml_dmx *dmx) -{ - - u32 v, wr, rd; - u32 data32; - struct aml_smallsec *ss = &dmx->smallsec; - - v = DMX_READ_REG(dmx->id, DEMUX_SMALL_SEC_CTL); - wr = (v >> 8) & 0xff; - rd = (v >> 16) & 0xff; - - if (rd != wr) { - int n1 = wr - rd, - n2 = 0, - max = (ss->bufsize>>8); - int i; - u8 *p; - int sec_len; - - pr_dbg_irq_ss("secbuf[31] ctrl:0x%x\n", v); - - if (n1 < 0) { - n1 = max - rd; - n2 = wr; - } - if (n1) { - pr_dbg_irq_ss("n1:%d\n", n1); - dma_sync_single_for_cpu(dmx_get_dev(dmx), - ss->buf_map+(rd<<8), - n1<<8, - DMA_FROM_DEVICE); - for (i = 0; i < n1; i++) { - p = (u8 *)ss->buf+((rd+i)<<8); - sec_len = (((p[1] & 0xF) << 8) | p[2]) + 3; - smallsection_match_section(dmx, p, - *(p+sec_len+1)); - } - } - if (n2) { - pr_dbg_irq_ss("n2:%d\n", n2); - dma_sync_single_for_cpu(dmx_get_dev(dmx), - ss->buf_map, - n2<<8, - DMA_FROM_DEVICE); - for (i = 0; i < n2; i++) { - p = (u8 *)ss->buf+(i<<8); - sec_len = (((p[1] & 0xF) << 8) | p[2]) + 3; - smallsection_match_section(dmx, p, - *(p+sec_len+1)); - } - } - - rd = wr; - data32 = (DMX_READ_REG(dmx->id, DEMUX_SMALL_SEC_CTL) - & 0xff00ffff) - | (rd << 16); - DMX_WRITE_REG(dmx->id, DEMUX_SMALL_SEC_CTL, data32); - } -} - - -static void process_section(struct aml_dmx *dmx) -{ - u32 ready, i, sec_busy; - u16 sec_num; - - /*pr_dbg("section\n"); */ - ready = DMX_READ_REG(dmx->id, SEC_BUFF_READY); - if (ready) { -#ifdef USE_AHB_MODE - /* WRITE_ISA_REG(AHB_BRIDGE_CTRL1, - * READ_ISA_REG (AHB_BRIDGE_CTRL1) | (1 << 31)); - */ - /* WRITE_ISA_REG(AHB_BRIDGE_CTRL1, - * READ_ISA_REG (AHB_BRIDGE_CTRL1) & (~ (1 << 31))); - */ -#endif - - if ((ready & (1<<31)) && dmx->smallsec.enable) { - u32 v, wr, rd; - - v = DMX_READ_REG(dmx->id, DEMUX_SMALL_SEC_CTL); - wr = (v >> 8) & 0xff; - rd = (v >> 16) & 0xff; - if ((wr < rd) && (5 > (rd - wr))) - pr_error("warning: small ss buf [w%dr%d]\n", - wr, rd); - pr_dbg_irq_ss("ss>%x\n", - DMX_READ_REG(dmx->id, DEMUX_SMALL_SEC_CTL)); - process_smallsection(dmx); - /*tasklet_hi_schedule(&dmx->dmx_tasklet);*/ - /*tasklet_schedule(&dmx->dmx_tasklet);*/ - DMX_WRITE_REG(dmx->id, SEC_BUFF_READY, (1<<31)); - return; - } - - for (i = 0; i < SEC_BUF_COUNT; i++) { - - if (!(ready & (1 << i))) - continue; - - /* get section busy */ - sec_busy = DMX_READ_REG(dmx->id, SEC_BUFF_BUSY); - /* get filter number */ - DMX_WRITE_REG(dmx->id, SEC_BUFF_NUMBER, i); - sec_num = (DMX_READ_REG(dmx->id, SEC_BUFF_NUMBER) >> 8); - - /* - * sec_buf_watchdog_count dispatch: - * byte0 -- always busy=0 's watchdog count - * byte1 -- always busy=1 & filter_num=31 's - * watchdog count - */ - - /* sec_busy is not set, check busy=0 watchdog count */ - if (!(sec_busy & (1 << i))) { - /* clear other wd count of this buffer */ - dmx->sec_buf_watchdog_count[i] &= 0x000000ff; - dmx->sec_buf_watchdog_count[i] += 0x1; - pr_dbg("bit%d ready=1, busy=0,\n" - "sec_num=%d for %d times\n", - i, sec_num, - dmx->sec_buf_watchdog_count[i]); - if (dmx->sec_buf_watchdog_count[i] >= 5) { - pr_dbg("busy=0 reach the max count,\n" - "try software match.\n"); - software_match_section(dmx, i); - dmx->sec_buf_watchdog_count[i] = 0; - DMX_WRITE_REG(dmx->id, SEC_BUFF_READY, - (1 << i)); - } - continue; - } - - /* filter_num == 31 && busy == 1,check watchdog count */ - if (sec_num >= FILTER_COUNT) { - /* clear other wd count of this buffer */ - dmx->sec_buf_watchdog_count[i] &= 0x0000ff00; - dmx->sec_buf_watchdog_count[i] += 0x100; - pr_dbg("bit%d ready=1,busy=1,\n" - "sec_num=%d for %d times\n", - i, sec_num, - dmx->sec_buf_watchdog_count[i] >> 8); - if (dmx->sec_buf_watchdog_count[i] >= 0x500) { - pr_dbg("busy=1&filter_num=31\n" - " reach the max count, clear\n" - " the buf ready & busy!\n"); - software_match_section(dmx, i); - dmx->sec_buf_watchdog_count[i] = 0; - DMX_WRITE_REG(dmx->id, - SEC_BUFF_READY, - (1 << i)); - DMX_WRITE_REG(dmx->id, - SEC_BUFF_BUSY, - (1 << i)); - } - continue; - } - - /* now, ready & busy are both set and - * filter number is valid - */ - if (dmx->sec_buf_watchdog_count[i] != 0) - dmx->sec_buf_watchdog_count[i] = 0; - - /* process this section */ - hardware_match_section(dmx, sec_num, i); - - /* clear the ready & busy bit */ - DMX_WRITE_REG(dmx->id, SEC_BUFF_READY, (1 << i)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_BUSY, (1 << i)); - } - } -} - -#ifdef NO_SUB -static void process_sub(struct aml_dmx *dmx) -{ - - u32 rd_ptr = 0; - - u32 wr_ptr = READ_MPEG_REG(PARSER_SUB_WP); - u32 start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); - u32 end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); - - u32 buffer1 = 0, buffer2 = 0; - unsigned char *buffer1_virt = 0, *buffer2_virt = 0; - u32 len1 = 0, len2 = 0; - - rd_ptr = READ_MPEG_REG(PARSER_SUB_RP); - if (!rd_ptr) - return; - if (rd_ptr > wr_ptr) { - len1 = end_ptr - rd_ptr + 8; - buffer1 = rd_ptr; - - len2 = wr_ptr - start_ptr; - buffer2 = start_ptr; - - rd_ptr = start_ptr + len2; - } else if (rd_ptr < wr_ptr) { - len1 = wr_ptr - rd_ptr; - buffer1 = rd_ptr; - rd_ptr += len1; - len2 = 0; - } else if (rd_ptr == wr_ptr) { - pr_dbg("sub no data\n"); - } - - if (buffer1 && len1) - buffer1_virt = codec_mm_phys_to_virt(buffer1); - - if (buffer2 && len2) - buffer2_virt = codec_mm_phys_to_virt(buffer2); - -// printk("rd_ptr %p buffer1 %p len1 %d buffer2 %p len2 %d buffer1_virt %p buffer2_virt %p\n", -// (void*)rd_ptr, (void*)buffer1, len1, (void*)buffer2, len2, buffer1_virt, buffer2_virt); - - if (len1) - dma_sync_single_for_cpu(dmx_get_dev(dmx), - (dma_addr_t) buffer1, len1, - DMA_FROM_DEVICE); - if (len2) - dma_sync_single_for_cpu(dmx_get_dev(dmx), - (dma_addr_t) buffer2, len2, - DMA_FROM_DEVICE); - - if (dmx->channel[2].used) { - if (dmx->channel[2].feed && dmx->channel[2].feed->cb.ts && - ((buffer1_virt != NULL && len1 !=0 ) | (buffer2_virt != NULL && len2 != 0))) - { - dmx->channel[2].feed->cb.ts(buffer1_virt, len1, - buffer2_virt, len2, - &dmx->channel[2].feed->feed.ts); - } - } - WRITE_MPEG_REG(PARSER_SUB_RP, rd_ptr); -} -#endif - -static void process_pes(struct aml_dmx *dmx) -{ - static long off, off_pre; - u8 *buffer1 = 0, *buffer2 = 0; - u8 *buffer1_phys = 0, *buffer2_phys = 0; - u32 len1 = 0, len2 = 0; - int i = 1; - - off = (DMX_READ_REG(dmx->id, OB_PES_WR_PTR) << 3); - - pr_dbg_irq_pes("[%d]WR:0x%x PES WR:0x%x\n", dmx->id, - DMX_READ_REG(dmx->id, OTHER_WR_PTR), - DMX_READ_REG(dmx->id, OB_PES_WR_PTR)); - buffer1 = (u8 *)(dmx->pes_pages + off_pre); - pr_dbg_irq_pes("[%d]PES WR[%02x %02x %02x %02x %02x %02x %02x %02x", - dmx->id, - buffer1[0], buffer1[1], buffer1[2], buffer1[3], - buffer1[4], buffer1[5], buffer1[6], buffer1[7]); - pr_dbg_irq_pes(" %02x %02x %02x %02x %02x %02x %02x %02x]\n", - buffer1[8], buffer1[9], buffer1[10], buffer1[11], - buffer1[12], buffer1[13], buffer1[14], buffer1[15]); - - if (off > off_pre) { - len1 = off-off_pre; - buffer1 = (unsigned char *)(dmx->pes_pages + off_pre); - } else if (off < off_pre) { - len1 = dmx->pes_buf_len-off_pre; - buffer1 = (unsigned char *)(dmx->pes_pages + off_pre); - len2 = off; - buffer2 = (unsigned char *)dmx->pes_pages; - } else if (off == off_pre) { - pr_dbg("pes no data\n"); - } - off_pre = off; - if (len1) { - buffer1_phys = (unsigned char *)virt_to_phys(buffer1); - dma_sync_single_for_cpu(dmx_get_dev(dmx), - (dma_addr_t)buffer1_phys, len1, DMA_FROM_DEVICE); - } - if (len2) { - buffer2_phys = (unsigned char *)virt_to_phys(buffer2); - dma_sync_single_for_cpu(dmx_get_dev(dmx), - (dma_addr_t)buffer2_phys, len2, DMA_FROM_DEVICE); - } - if (len1 || len2) { - struct aml_channel *ch; - - for (i = 0; i < CHANNEL_COUNT; i++) { - ch = &dmx->channel[i]; - if (ch->used && ch->feed - && (ch->feed->type == DMX_TYPE_TS)) { - if (ch->feed->ts_type & TS_PAYLOAD_ONLY) { - ch->feed->cb.ts(buffer1, - len1, buffer2, len2, - &ch->feed->feed.ts); - } - } - } - } -} - -static void process_om_read(struct aml_dmx *dmx) -{ - unsigned int i; - unsigned short om_cmd_status_data_0 = 0; - unsigned short om_cmd_status_data_1 = 0; -/* unsigned short om_cmd_status_data_2 = 0;*/ - unsigned short om_cmd_data_out = 0; - - om_cmd_status_data_0 = DMX_READ_REG(dmx->id, OM_CMD_STATUS); - om_cmd_status_data_1 = DMX_READ_REG(dmx->id, OM_CMD_DATA); -/* om_cmd_status_data_2 = DMX_READ_REG(dmx->id, OM_CMD_DATA2);*/ - - if (om_cmd_status_data_0 & 1) { - DMX_WRITE_REG(dmx->id, OM_DATA_RD_ADDR, - (1 << 15) | ((om_cmd_status_data_1 & 0xff) << 2)); - for (i = 0; i < (((om_cmd_status_data_1 >> 7) & 0x1fc) >> 1); - i++) { - om_cmd_data_out = DMX_READ_REG(dmx->id, OM_DATA_RD); - } - - om_cmd_data_out = DMX_READ_REG(dmx->id, OM_DATA_RD_ADDR); - DMX_WRITE_REG(dmx->id, OM_DATA_RD_ADDR, 0); - DMX_WRITE_REG(dmx->id, OM_CMD_STATUS, 1); - } -} - -static void dmx_irq_bh_handler(unsigned long arg) -{ - struct aml_dmx *dmx = (struct aml_dmx *)arg; -#if 0 - u32 status; - - status = DMX_READ_REG(dmx->id, STB_INT_STATUS); - - if (status) - DMX_WRITE_REG(dmx->id, STB_INT_STATUS, status); -#endif - process_smallsection(dmx); -} - -static irqreturn_t dmx_irq_handler(int irq_number, void *para) -{ - struct aml_dmx *dmx = (struct aml_dmx *)para; - struct aml_dvb *dvb = aml_get_dvb_device(); - u32 status; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - status = DMX_READ_REG(dmx->id, STB_INT_STATUS); - if (!status) - goto irq_handled; - - pr_dbg_irq("demux %d irq status: 0x%08x\n", dmx->id, status); - - if (status & (1 << SECTION_BUFFER_READY)) - process_section(dmx); -#ifdef NO_SUB - if (status & (1 << SUB_PES_READY)) { - /*If the subtitle is set by tsdemux, - *do not parser in demux driver. - */ - if (dmx->sub_chan == -1) - process_sub(dmx); - } -#endif - if (status & (1 << OTHER_PES_READY)) - process_pes(dmx); - if (status & (1 << OM_CMD_READ_PENDING)) - process_om_read(dmx); - /* - *if (status & (1 << DUPLICATED_PACKET)) { - *} - *if (status & (1 << DIS_CONTINUITY_PACKET)) { - *} - *if (status & (1 << VIDEO_SPLICING_POINT)) { - *} - *if (status & (1 << AUDIO_SPLICING_POINT)) { - *} - */ - if (status & (1 << TS_ERROR_PIN)) - pr_error("TS_ERROR_PIN\n"); - - if (status & (1 << NEW_PDTS_READY)) { - u32 pdts_status = DMX_READ_REG(dmx->id, STB_PTS_DTS_STATUS); - - if (pdts_status & (1 << VIDEO_PTS_READY)) { - video_pts = DMX_READ_REG(dmx->id, VIDEO_PTS_DEMUX); - video_pts_bit32 = - (status & (1 << VIDEO_PTS_BIT32)) ? 1 : 0; - if (!first_video_pts - || 0 > (int)(video_pts - first_video_pts)) - first_video_pts = video_pts; - } - - if (pdts_status & (1 << AUDIO_PTS_READY)) { - audio_pts = DMX_READ_REG(dmx->id, AUDIO_PTS_DEMUX); - audio_pts_bit32 = - (status & (1 << AUDIO_PTS_BIT32)) ? 1 : 0; - if (!first_audio_pts - || 0 > (int)(audio_pts - first_audio_pts)) - first_audio_pts = audio_pts; - } - } - - if (dmx->irq_handler) - dmx->irq_handler(dmx->dmx_irq, (void *)(long)dmx->id); - - DMX_WRITE_REG(dmx->id, STB_INT_STATUS, status); - - /*tasklet_schedule(&dmx->dmx_tasklet);*/ - - { - if (!dmx->int_check_time) { - dmx->int_check_time = jiffies; - dmx->int_check_count = 0; - } - - if (jiffies_to_msecs(jiffies - dmx->int_check_time) >= 100 - || dmx->int_check_count > 1000) { - if (dmx->int_check_count > 1000) { - struct aml_dvb *dvb = - (struct aml_dvb *)dmx->demux.priv; - pr_error("Too many irq (%d irq in %d ms)!\n", - dmx->int_check_count, - jiffies_to_msecs(jiffies - - dmx->int_check_time)); - if (dmx->fe && !dmx->in_tune) - DMX_WRITE_REG(dmx->id, STB_INT_MASK, 0); - dmx_reset_hw_ex(dvb, 0); - } - dmx->int_check_time = 0; - } - - dmx->int_check_count++; - - if (dmx->in_tune) { - dmx->error_check++; - if (dmx->error_check > 200) - DMX_WRITE_REG(dmx->id, STB_INT_MASK, 0); - } - } - -irq_handled: - spin_unlock_irqrestore(&dvb->slock, flags); - return IRQ_HANDLED; -} - -static inline int dmx_get_order(unsigned long size) -{ - int order; - - order = -1; - do { - size >>= 1; - order++; - } while (size); - - return order; -} - -static void dvr_process_channel(struct aml_asyncfifo *afifo, - struct aml_channel *channel, - u32 total, u32 size, - struct aml_swfilter *sf) -{ - int cnt; - int ret = 0; - struct aml_dvr_block blk; - - if (afifo->buf_read > afifo->buf_toggle) { - cnt = total - afifo->buf_read; - if (!afifo->secure_enable) { - dma_sync_single_for_cpu(asyncfifo_get_dev(afifo), - afifo->pages_map+afifo->buf_read*size, - cnt*size, - DMA_FROM_DEVICE); - if (sf) - ret = _rbuf_write(&sf->rbuf, - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size); - else - channel->dvr_feed->cb.ts( - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size, NULL, 0, - &channel->dvr_feed->feed.ts); - } else { - blk.addr = afifo->blk.addr+afifo->buf_read*size; - blk.len = cnt*size; - if (sf) - ret = _rbuf_write(&sf->rbuf, - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size); - else { - channel->dvr_feed->cb.ts( - (u8 *)&blk, - sizeof(struct aml_dvr_block), - NULL, 0, - &channel->dvr_feed->feed.ts); - } - } - afifo->buf_read = 0; - } - - if (afifo->buf_toggle > afifo->buf_read) { - cnt = afifo->buf_toggle - afifo->buf_read; - if (!afifo->secure_enable) { - dma_sync_single_for_cpu(asyncfifo_get_dev(afifo), - afifo->pages_map+afifo->buf_read*size, - cnt*size, - DMA_FROM_DEVICE); - if (sf) { - if (ret >= 0) - ret = _rbuf_write(&sf->rbuf, - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size); - } else { - channel->dvr_feed->cb.ts( - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size, NULL, 0, - &channel->dvr_feed->feed.ts); - } - } else { - blk.addr = afifo->blk.addr+afifo->buf_read*size; - blk.len = cnt*size; - if (sf) - ret = _rbuf_write(&sf->rbuf, - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size); - else { - channel->dvr_feed->cb.ts( - (u8 *)&blk, - sizeof(struct aml_dvr_block), - NULL, 0, - &channel->dvr_feed->feed.ts); - } - } - afifo->buf_read = afifo->buf_toggle; - } - - if (sf && ret > 0) { - _rbuf_filter_pkts(&sf->rbuf, sf->wrapbuf, - dvb_dmx_swfilter_packets, - channel->dvr_feed->demux); - } else if (sf && ret <= 0) - pr_error("sf rbuf write error[%d]\n", ret); - else - pr_dbg_irq_dvr("write data to dvr\n"); -} - -static void dvr_irq_bh_handler(unsigned long arg) -{ - struct aml_asyncfifo *afifo = (struct aml_asyncfifo *)arg; - struct aml_dvb *dvb = afifo->dvb; - struct aml_dmx *dmx; - u32 size, total; - int i, factor; - unsigned long flags; - - pr_dbg_irq_dvr("async fifo %d irq\n", afifo->id); - - spin_lock_irqsave(&dvb->slock, flags); - - if (dvb && afifo->source >= AM_DMX_0 && afifo->source < AM_DMX_MAX) { - dmx = &dvb->dmx[afifo->source]; - // pr_inf("async fifo %d irq, source:%d\n", afifo->id,afifo->source); - if (dmx->init && dmx->record) { - struct aml_swfilter *sf = &dvb->swfilter; - int issf = 0; - - total = afifo->buf_len / afifo->flush_size; - factor = dmx_get_order(total); - size = afifo->buf_len >> factor; - - if (sf->user && (sf->afifo == afifo)) - issf = 1; - - for (i = 0; i < CHANNEL_COUNT; i++) { - if (dmx->channel[i].used - && dmx->channel[i].dvr_feed) { - dvr_process_channel(afifo, - &dmx->channel[i], - total, - size, - issf?sf:NULL); - break; - } - } - - } - } - spin_unlock_irqrestore(&dvb->slock, flags); -} - -static irqreturn_t dvr_irq_handler(int irq_number, void *para) -{ - struct aml_asyncfifo *afifo = (struct aml_asyncfifo *)para; - int factor = dmx_get_order(afifo->buf_len / afifo->flush_size); - - afifo->buf_toggle++; - afifo->buf_toggle %= (1 << factor); - tasklet_schedule(&afifo->asyncfifo_tasklet); - return IRQ_HANDLED; -} - -/*Enable the STB*/ -static void stb_enable(struct aml_dvb *dvb) -{ - int out_src, des_in, en_des, fec_clk, hiu, dec_clk_en; - int src, tso_src, i; - u32 fec_s0, fec_s1,fec_s2; - u32 invert0, invert1, invert2; - u32 data; - - switch (dvb->stb_source) { - case AM_TS_SRC_DMX0: - src = dvb->dmx[0].source; - break; - case AM_TS_SRC_DMX1: - src = dvb->dmx[1].source; - break; - case AM_TS_SRC_DMX2: - src = dvb->dmx[2].source; - break; - default: - src = dvb->stb_source; - break; - } - - switch (src) { - case AM_TS_SRC_TS0: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_TS1: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_TS2: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_TS3: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_S_TS0: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_S_TS1: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_S_TS2: - fec_clk = tsfile_clkdiv; - hiu = 0; - break; - case AM_TS_SRC_HIU: - fec_clk = tsfile_clkdiv; - hiu = 1; - break; - case AM_TS_SRC_HIU1: - fec_clk = tsfile_clkdiv; - hiu = 1; - break; - default: - fec_clk = 0; - hiu = 0; - break; - } - - switch (dvb->dsc[0].source) { - case AM_TS_SRC_DMX0: - des_in = 0; - en_des = 1; - dec_clk_en = 1; - break; - case AM_TS_SRC_DMX1: - des_in = 1; - en_des = 1; - dec_clk_en = 1; - break; - case AM_TS_SRC_DMX2: - des_in = 2; - en_des = 1; - dec_clk_en = 1; - break; - default: - des_in = 0; - en_des = 0; - dec_clk_en = 0; - break; - } - - switch (dvb->tso_source) { - case AM_TS_SRC_DMX0: - tso_src = dvb->dmx[0].source; - break; - case AM_TS_SRC_DMX1: - tso_src = dvb->dmx[1].source; - break; - case AM_TS_SRC_DMX2: - tso_src = dvb->dmx[2].source; - break; - default: - tso_src = dvb->tso_source; - break; - } - - switch (tso_src) { - case AM_TS_SRC_TS0: - out_src = 0; - break; - case AM_TS_SRC_TS1: - out_src = 1; - break; - case AM_TS_SRC_TS2: - out_src = 2; - break; - case AM_TS_SRC_TS3: - out_src = 3; - break; - case AM_TS_SRC_S_TS0: - out_src = 6; - break; - case AM_TS_SRC_S_TS1: - out_src = 5; - break; - case AM_TS_SRC_S_TS2: - out_src = 4; - break; - case AM_TS_SRC_HIU: - out_src = 7; - break; - default: - out_src = 0; - break; - } - - pr_dbg("[stb]src: %d, dsc1in: %d, tso: %d\n", src, des_in, out_src); - - fec_s0 = 0; - fec_s1 = 0; - fec_s2 = 0; - invert0 = 0; - invert1 = 0; - invert2 = 0; - - for (i = 0; i < dvb->ts_in_total_count; i++) { - if (dvb->ts[i].s2p_id == 0) - fec_s0 = i; - else if (dvb->ts[i].s2p_id == 1) - fec_s1 = i; - else if (dvb->ts[i].s2p_id == 2) - fec_s2 = i; - } - - invert0 = dvb->s2p[0].invert; - invert1 = dvb->s2p[1].invert; - - WRITE_MPEG_REG(STB_TOP_CONFIG, - (invert1 << INVERT_S2P1_FEC_CLK) | - (fec_s1 << S2P1_FEC_SERIAL_SEL) | - (out_src << TS_OUTPUT_SOURCE) | - (des_in << DES_INPUT_SEL) | - (en_des << ENABLE_DES_PL) | - (dec_clk_en << ENABLE_DES_PL_CLK) | - (invert0 << INVERT_S2P0_FEC_CLK) | - (fec_s0 << S2P0_FEC_SERIAL_SEL)); - - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { - invert2 = dvb->s2p[2].invert; - - WRITE_MPEG_REG(STB_S2P2_CONFIG, - (invert2 << INVERT_S2P2_FEC_CLK) | - (fec_s2 << S2P2_FEC_SERIAL_SEL)); - } - - if (dvb->reset_flag) - hiu = 0; - /* invert ts out clk,add ci model need add this*/ - if (dvb->ts_out_invert) { - /*printk("ts out invert ---\r\n");*/ - data = READ_MPEG_REG(TS_TOP_CONFIG); - data |= 1 << TS_OUT_CLK_INVERT; - WRITE_MPEG_REG(TS_TOP_CONFIG, data); - } - - if (src == AM_TS_SRC_HIU1) { - WRITE_MPEG_REG(TS_HIU1_CONFIG, - (demux_skipbyte << FILE_M2TS_SKIP_BYTES_HIU1) | - (hiu << TS_HIU_ENABLE_HIU1) | - (fec_clk << FEC_CLK_DIV_HIU1) | - (0xBB << TS_PACKAGE_LENGTH_SUB_1_HIU1) | - (0x47 << FEC_SYNC_BYTE_HIU1)); - } else { - /* invert ts out clk end */ - WRITE_MPEG_REG(TS_FILE_CONFIG, - (demux_skipbyte << 16) | - (6 << DES_OUT_DLY) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD_2) | - (hiu << TS_HIU_ENABLE) | (fec_clk << FEC_FILE_CLK_DIV)); - } -} - -int dsc_set_pid(struct aml_dsc_channel *ch, int pid) -{ - struct aml_dsc *dsc = ch->dsc; - int is_dsc2 = (dsc->id == 1) ? 1 : 0; - u32 data; - - WRITE_MPEG_REG(TS_PL_PID_INDEX, - ((ch->id & 0x0f) >> 1)+(is_dsc2 ? 4 : 0)); - data = READ_MPEG_REG(TS_PL_PID_DATA); - if (ch->id & 1) { - data &= 0xFFFF0000; - data |= pid & 0x1fff; - if (!ch->used) - data |= 1 << PID_MATCH_DISABLE_LOW; - } else { - data &= 0xFFFF; - data |= (pid & 0x1fff) << 16; - if (!ch->used) - data |= 1 << PID_MATCH_DISABLE_HIGH; - } - WRITE_MPEG_REG(TS_PL_PID_INDEX, - ((ch->id & 0x0f) >> 1)+(is_dsc2 ? 4 : 0)); - WRITE_MPEG_REG(TS_PL_PID_DATA, data); - WRITE_MPEG_REG(TS_PL_PID_INDEX, 0); - - if (ch->used) - pr_dbg("set DSC %d ch %d PID %d\n", dsc->id, ch->id, pid); - else - pr_dbg("disable DSC %d ch %d\n", dsc->id, ch->id); - return 0; -} - -int dsc_set_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, - u8 *key) -{ - /*struct aml_dsc *dsc = ch->dsc;*/ - int ret = -1; - - switch (type) { - case CA_CW_DVB_CSA_EVEN: - case CA_CW_DVB_CSA_ODD: - aml_ci_plus_disable(); - ret = dsc_set_csa_key(ch, flags, type, key); - if (ret != 0) - goto END; - /* Different with old mode, do change */ - if (ch->work_mode == CIPLUS_MODE || ch->work_mode == -1) { - if (ch->work_mode == -1) - pr_inf("dsc[%d:%d] enable\n", - ch->dsc->id, ch->id); - else - pr_inf("dsc[%d:%d] enable (from ciplus)\n", - ch->dsc->id, ch->id); - ch->mode = ECB_MODE; - ch->work_mode = DVBCSA_MODE; - } - break; - case CA_CW_AES_EVEN: - case CA_CW_AES_ODD: - case CA_CW_AES_EVEN_IV: - case CA_CW_AES_ODD_IV: - case CA_CW_DES_EVEN: - case CA_CW_DES_ODD: - case CA_CW_SM4_EVEN: - case CA_CW_SM4_ODD: - case CA_CW_SM4_EVEN_IV: - case CA_CW_SM4_ODD_IV: - am_ci_plus_set_output(ch); - ret = dsc_set_aes_des_sm4_key(ch, flags, type, key); - if (ret != 0) - goto END; - /* Different with old mode, do change */ - if (ch->work_mode == DVBCSA_MODE || ch->work_mode == -1) { - if (ch->work_mode == -1) - pr_inf("dsc[%d:%d] ciplus enable\n", - ch->dsc->id, ch->id); - else - pr_inf("dsc[%d:%d] ciplus enable (from dsc)\n", - ch->dsc->id, ch->id); - ch->work_mode = CIPLUS_MODE; - } - break; - default: - break; - } -END: - return ret; -} - -int dsc_set_keys(struct aml_dsc_channel *ch) -{ - int types = ch->set & 0xFFFFFF; - int flag = (ch->set >> 24) & 0xFF; - int i; - u8 *k; - int ret = 0; - - for (i = 0; i < CA_CW_TYPE_MAX; i++) { - if (types & (1 << i)) { - k = NULL; - switch (i) { - case CA_CW_DVB_CSA_EVEN: - case CA_CW_AES_EVEN: - case CA_CW_DES_EVEN: - case CA_CW_SM4_EVEN: - k = ch->even; - break; - case CA_CW_DVB_CSA_ODD: - case CA_CW_AES_ODD: - case CA_CW_DES_ODD: - case CA_CW_SM4_ODD: - k = ch->odd; - break; - case CA_CW_AES_EVEN_IV: - case CA_CW_SM4_EVEN_IV: - k = ch->even_iv; - break; - case CA_CW_AES_ODD_IV: - case CA_CW_SM4_ODD_IV: - k = ch->odd_iv; - break; - default: - break; - } - /* - if (k) - pr_inf("dsc ch:%d flag:%d type:%d\n", ch->id, flag, i); - */ - if (k) - ret = dsc_set_key(ch, flag, - i, - k); - } - } - return 0; -} - -static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, - enum ca_cw_type type, u8 *key) -{ - struct aml_dsc *dsc = ch->dsc; - int is_dsc2 = (dsc->id == 1) ? 1 : 0; - u16 k0, k1, k2, k3; - u32 key0, key1; - int reg; - - if (flags & DSC_FROM_KL) { - k0 = k1 = k2 = k3 = 0; - /*dummy write to check if kl not working*/ - key0 = key1 = 0; - WRITE_MPEG_REG(COMM_DESC_KEY0, key0); - WRITE_MPEG_REG(COMM_DESC_KEY1, key1); - - /*tdes? :*/ - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) { - WRITE_MPEG_REG(COMM_DESC_KEY_RW, -/* (type ? (1 << 6) : (1 << 5)) | */ - ((1 << 5)) | - ((ch->id + type * DSC_COUNT)+ - (is_dsc2 ? 16 : 0))); - } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL || - get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) { - pr_info("do kl..\n"); - WRITE_MPEG_REG(COMM_DESC_KEY_RW, - (type ? (1 << 6) : (1 << 5)) | (1<<7) | - ((ch->id + type * DSC_COUNT)+ - (is_dsc2 ? 16 : 0))); - } - reg = (type ? (1 << 6) : (1 << 5)) | - ((ch->id + type * DSC_COUNT)+ - (is_dsc2 ? 16 : 0)); - } else { - k0 = (key[0] << 8) | key[1]; - k1 = (key[2] << 8) | key[3]; - k2 = (key[4] << 8) | key[5]; - k3 = (key[6] << 8) | key[7]; - - key0 = (k0 << 16) | k1; - key1 = (k2 << 16) | k3; - WRITE_MPEG_REG(COMM_DESC_KEY0, key0); - WRITE_MPEG_REG(COMM_DESC_KEY1, key1); - - reg = (ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0); - WRITE_MPEG_REG(COMM_DESC_KEY_RW, reg); - } - - return 0; -} - -/************************* AES DESC************************************/ -/*#define STB_TOP_CONFIG 0x16f0 -#define CIPLUS_KEY0 0x16f8 -#define CIPLUS_KEY1 0x16f9 -#define CIPLUS_KEY2 0x16fa -#define CIPLUS_KEY3 0x16fb -#define CIPLUS_KEY_WR 0x16fc -#define CIPLUS_CONFIG 0x16fd -#define CIPLUS_ENDIAN 0x16fe*/ - -#define ENABLE_DEC_PL 7 -#define ENABLE_DES_PL_CLK 15 -#define CIPLUS_OUT_SEL 28 -#define CIPLUS_IN_SEL 26 - -#define KEY_WR_AES_IV_B 5 -#define KEY_WR_AES_IV_A 4 -#define KEY_WR_AES_B 3 -#define KEY_WR_AES_A 2 -#define KEY_WR_DES_B 1 -#define KEY_WR_DES_A 0 - -#define IDSA_MODE_BIT 31 -#define SM4_MODE 30 -#define CNTL_ENABLE 3 -#define AES_CBC_DISABLE 2 -#define AES_EN 1 -#define DES_EN 0 - -#define AES_MSG_OUT_ENDIAN 24 -#define AES_MSG_IN_ENDIAN 20 -#define AES_KEY_ENDIAN 16 -#define DES_MSG_OUT_ENDIAN 8 -#define DES_MSG_IN_ENDIAN 4 -#define DES_KEY_ENDIAN 0 - -#define ALGO_AES 0 -#define ALGO_SM4 1 -#define ALGO_DES 2 - -#if 0 -static void aml_ci_plus_set_stb(void) -{ - unsigned int data; - /* data = READ_MPEG_REG(FEC_INPUT_CONTROL); */ - /* data |= (0<id << 9) | (1<id << 9) | (1<dsc; - u32 data; - u32 in = 0, out = 0; - int set = 0; - - if (dsc->id != 0) { - pr_error("Ciplus set output can only work at dsc0 device\n"); - return; - } - - switch (dsc->source) { - case AM_TS_SRC_DMX0: - in = 0; - break; - case AM_TS_SRC_DMX1: - in = 1; - break; - case AM_TS_SRC_DMX2: - in = 2; - break; - default: - break; - } - - if (ciplus_out_auto_mode == 1) { - switch (dsc->dst) { - case AM_TS_SRC_DMX0: - out = 1; - break; - case AM_TS_SRC_DMX1: - out = 2; - break; - case AM_TS_SRC_DMX2: - out = 4; - break; - default: - break; - } - set = 1; - ciplus_out_sel = out; - } else if (ciplus_out_sel >= 0 && ciplus_out_sel <= 7) { - set = 1; - out = ciplus_out_sel; - } else { - pr_error("dsc ciplus out config is invalid\n"); - } - - if (set) { - /* Set ciplus input source , - * output set 0 means no output. ---> need confirm. - * if output set 0 still affects dsc output, we need to disable - * ciplus module. - */ - data = READ_MPEG_REG(STB_TOP_CONFIG); - data &= ~(3<mode == -1) - ch->mode = ECB_MODE; - aes = 1; - if (type == CA_CW_AES_EVEN) - algo = ALGO_AES; - else - algo = ALGO_SM4; - break; - case CA_CW_AES_ODD: - case CA_CW_SM4_ODD: - ab_aes = (from_kl) ? 0x1 : 0x2; - if (ch->mode == -1) - ch->mode = ECB_MODE; - aes = 1; - if (type == CA_CW_AES_ODD) - algo = ALGO_AES; - else - algo = ALGO_SM4; - break; - case CA_CW_AES_EVEN_IV: - case CA_CW_SM4_EVEN_IV: - ab_iv = 0x1; - if (ch->mode == -1) - ch->mode = CBC_MODE; - iv = 1; - if (type == CA_CW_AES_EVEN_IV) - algo = ALGO_AES; - else - algo = ALGO_SM4; - break; - case CA_CW_AES_ODD_IV: - case CA_CW_SM4_ODD_IV: - ab_iv = 0x2; - if (ch->mode == -1) - ch->mode = CBC_MODE; - iv = 1; - if (type == CA_CW_AES_ODD_IV) - algo = ALGO_AES; - else - algo = ALGO_SM4; - break; - case CA_CW_DES_EVEN: - ab_des = 0x1; - ch->mode = ECB_MODE; - des = 1; - algo = ALGO_DES; - break; - case CA_CW_DES_ODD: - ab_des = 0x2; - ch->mode = ECB_MODE; - algo = ALGO_DES; - des = 1; - break; - default: - break; - } - - /* Set endian and cbc/ecb mode */ - if (from_kl) - aml_ci_plus_config(7, ch->mode, algo); - else - aml_ci_plus_config(0, ch->mode, algo); - - /* Write keys to work */ - if (iv || aes) { - WRITE_MPEG_REG(CIPLUS_KEY0, k0); - WRITE_MPEG_REG(CIPLUS_KEY1, k1); - WRITE_MPEG_REG(CIPLUS_KEY2, k2); - WRITE_MPEG_REG(CIPLUS_KEY3, k3); - } else {/*des*/ - WRITE_MPEG_REG(CIPLUS_KEY0, k2); - WRITE_MPEG_REG(CIPLUS_KEY1, k3); - WRITE_MPEG_REG(CIPLUS_KEY2, 0); - WRITE_MPEG_REG(CIPLUS_KEY3, 0); - } - WRITE_MPEG_REG(CIPLUS_KEY_WR, - (ch->id << 9) | - /* bit[11:9] the key of index, - need match PID index*/ - ((from_kl && des) ? (1 << 8) : 0) | - /* bit[8] des key use cw[127:64]*/ - (0 << 7) | /* bit[7] aes iv use cw*/ - ((from_kl && (aes || des)) ? (1 << 6) : 0) | - /* bit[6] aes/des key use cw*/ - /* bit[5] write AES IV B value*/ - (ab_iv << 4) | /* bit[4] write AES IV A value*/ - /* bit[3] write AES B key*/ - (ab_aes << 2) | /* bit[2] write AES A key*/ - /* bit[1] write DES B key*/ - (ab_des)); /* bit[0] write DES A key*/ - - /* - pr_inf("k:%08x:%08x:%08x:%08x kl:%d aes:%d des:%d ab_iv:%d ab_aes:%d ab_des:%d id:%d mod:%d\n", - k0, k1, k2, k3, - from_kl, aes, des, ab_iv, ab_aes, ab_des, ch->id, ch->aes_mode); - */ - return 0; -} - -void dsc_release(void) -{ - aml_ci_plus_disable(); -} -/************************* AES DESC************************************/ - -int dsc_enable(struct aml_dsc *dsc, int enable) -{ - if (dsc->id == 0) { - WRITE_MPEG_REG(STB_TOP_CONFIG, - READ_MPEG_REG(STB_TOP_CONFIG) & - ~((0x11 << DES_INPUT_SEL)| - (1 << ENABLE_DES_PL)| - (1 << ENABLE_DES_PL_CLK))); - } else if (dsc->id == 1) { - WRITE_MPEG_REG(COMM_DESC_2_CTL, 0); - } - return 0; -} - -/*Set section buffer*/ -static int dmx_alloc_sec_buffer(struct aml_dmx *dmx) -{ - unsigned long base; - unsigned long grp_addr[SEC_BUF_GRP_COUNT]; - int grp_len[SEC_BUF_GRP_COUNT]; - int i; - - if (dmx->sec_pages) - return 0; - - grp_len[0] = (1 << SEC_GRP_LEN_0) * 8; - grp_len[1] = (1 << SEC_GRP_LEN_1) * 8; - grp_len[2] = (1 << SEC_GRP_LEN_2) * 8; - grp_len[3] = (1 << SEC_GRP_LEN_3) * 8; - - dmx->sec_total_len = grp_len[0] + grp_len[1] + grp_len[2] + grp_len[3]; - dmx->sec_pages = - __get_free_pages(GFP_KERNEL, get_order(dmx->sec_total_len)); - if (!dmx->sec_pages) { - pr_error("cannot allocate section buffer %d bytes %d order\n", - dmx->sec_total_len, get_order(dmx->sec_total_len)); - return -1; - } - dmx->sec_pages_map = - dma_map_single(dmx_get_dev(dmx), (void *)dmx->sec_pages, - dmx->sec_total_len, DMA_FROM_DEVICE); - - grp_addr[0] = dmx->sec_pages_map; - - grp_addr[1] = grp_addr[0] + grp_len[0]; - grp_addr[2] = grp_addr[1] + grp_len[1]; - grp_addr[3] = grp_addr[2] + grp_len[2]; - - dmx->sec_buf[0].addr = dmx->sec_pages; - dmx->sec_buf[0].len = grp_len[0] / 8; - - for (i = 1; i < SEC_BUF_COUNT; i++) { - dmx->sec_buf[i].addr = - dmx->sec_buf[i - 1].addr + dmx->sec_buf[i - 1].len; - dmx->sec_buf[i].len = grp_len[i / 8] / 8; - } - - base = grp_addr[0] & 0xFFFF0000; - DMX_WRITE_REG(dmx->id, SEC_BUFF_BASE, base >> 16); - DMX_WRITE_REG(dmx->id, SEC_BUFF_01_START, - (((grp_addr[0] - base) >> 8) << 16) | - ((grp_addr[1] - base) >> 8)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_23_START, - (((grp_addr[2] - base) >> 8) << 16) | - ((grp_addr[3] - base) >> 8)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_SIZE, - SEC_GRP_LEN_0 | - (SEC_GRP_LEN_1 << 4) | - (SEC_GRP_LEN_2 << 8) | - (SEC_GRP_LEN_3 << 12)); - - return 0; -} - -#ifdef NO_SUB -/*Set subtitle buffer*/ -static int dmx_alloc_sub_buffer(struct aml_dmx *dmx) -{ - unsigned long addr; - - if (dmx->sub_pages) - return 0; - - dmx->sub_buf_len = 64 * 1024; - dmx->sub_pages = - __get_free_pages(GFP_KERNEL, get_order(dmx->sub_buf_len)); - if (!dmx->sub_pages) { - pr_error("cannot allocate subtitle buffer\n"); - return -1; - } - dmx->sub_pages_map = - dma_map_single(dmx_get_dev(dmx), (void *)dmx->sub_pages, - dmx->sub_buf_len, DMA_FROM_DEVICE); - - addr = virt_to_phys((void *)dmx->sub_pages); - DMX_WRITE_REG(dmx->id, SB_START, addr >> 12); - DMX_WRITE_REG(dmx->id, SB_LAST_ADDR, (dmx->sub_buf_len >> 3) - 1); - return 0; -} -#endif /*NO_SUB */ - -/*Set PES buffer*/ -static int dmx_alloc_pes_buffer(struct aml_dmx *dmx) -{ - unsigned long addr; - - if (dmx->pes_pages) - return 0; - - dmx->pes_buf_len = 64 * 1024; - dmx->pes_pages = - __get_free_pages(GFP_KERNEL, get_order(dmx->pes_buf_len)); - if (!dmx->pes_pages) { - pr_error("cannot allocate pes buffer\n"); - return -1; - } - dmx->pes_pages_map = - dma_map_single(dmx_get_dev(dmx), (void *)dmx->pes_pages, - dmx->pes_buf_len, DMA_FROM_DEVICE); - - addr = virt_to_phys((void *)dmx->pes_pages); - DMX_WRITE_REG(dmx->id, OB_START, addr >> 12); - DMX_WRITE_REG(dmx->id, OB_LAST_ADDR, (dmx->pes_buf_len >> 3) - 1); - return 0; -} - -/*Allocate ASYNC FIFO Buffer*/ -static unsigned long asyncfifo_alloc_buffer(int len) -{ - unsigned long pages = __get_free_pages(GFP_KERNEL, get_order(len)); - - if (!pages) { - pr_error("cannot allocate async fifo buffer\n"); - return 0; - } - return pages; -} -static void asyncfifo_free_buffer(unsigned long buf, int len) -{ - free_pages(buf, get_order(len)); -} - -static int asyncfifo_set_buffer(struct aml_asyncfifo *afifo, - int len, unsigned long buf) -{ - if (afifo->pages) - return -1; - - afifo->buf_toggle = 0; - afifo->buf_read = 0; - afifo->buf_len = len; - pr_error("++++async fifo %d buf size %d, flush size %d\n", - afifo->id, afifo->buf_len, afifo->flush_size); - - if ((afifo->flush_size <= 0) - || (afifo->flush_size > (afifo->buf_len>>1))) { - afifo->flush_size = afifo->buf_len>>1; - } else if (afifo->flush_size < 128) { - afifo->flush_size = 128; - } else { - int fsize; - - for (fsize = 128; fsize < (afifo->buf_len>>1); fsize <<= 1) { - if (fsize >= afifo->flush_size) - break; - } - - afifo->flush_size = fsize; - } - - afifo->pages = buf; - if (!afifo->pages) - return -1; - - afifo->pages_map = dma_map_single(asyncfifo_get_dev(afifo), - (void *)afifo->pages, afifo->buf_len, DMA_FROM_DEVICE); - - return 0; -} -static void asyncfifo_put_buffer(struct aml_asyncfifo *afifo) -{ - if (afifo->pages) { - dma_unmap_single(asyncfifo_get_dev(afifo), - afifo->pages_map, afifo->buf_len, DMA_FROM_DEVICE); - asyncfifo_free_buffer(afifo->pages, afifo->buf_len); - afifo->pages_map = 0; - afifo->pages = 0; - } -} - -int async_fifo_init(struct aml_asyncfifo *afifo, int initirq, - int buf_len, unsigned long buf) -{ - int ret = 0; - int irq; - - if (afifo->init) - return -1; - - afifo->source = AM_DMX_MAX; - afifo->pages = 0; - afifo->buf_toggle = 0; - afifo->buf_read = 0; - afifo->buf_len = 0; - - if (afifo->asyncfifo_irq == -1) { - pr_error("no irq for ASYNC_FIFO%d\n", afifo->id); - /*Do not return error*/ - return -1; - } - - tasklet_init(&afifo->asyncfifo_tasklet, - dvr_irq_bh_handler, (unsigned long)afifo); - if (initirq) - irq = request_irq(afifo->asyncfifo_irq, dvr_irq_handler, - IRQF_SHARED|IRQF_TRIGGER_RISING, - "dvr irq", afifo); - else - enable_irq(afifo->asyncfifo_irq); - - /*alloc buffer*/ - ret = asyncfifo_set_buffer(afifo, buf_len, buf); - - afifo->init = 1; - - return ret; -} - -int async_fifo_deinit(struct aml_asyncfifo *afifo, int freeirq) -{ - struct aml_dvb *dvb = afifo->dvb; - unsigned long flags; - - if (!afifo->init) - return 0; - - spin_lock_irqsave(&dvb->slock, flags); - CLEAR_ASYNC_FIFO_REG_MASK(afifo->id, REG1, 1 << ASYNC_FIFO_FLUSH_EN); - CLEAR_ASYNC_FIFO_REG_MASK(afifo->id, REG2, 1 << ASYNC_FIFO_FILL_EN); - spin_unlock_irqrestore(&dvb->slock, flags); - - asyncfifo_put_buffer(afifo); - - afifo->source = AM_DMX_MAX; - afifo->buf_toggle = 0; - afifo->buf_read = 0; - afifo->buf_len = 0; - - if (afifo->asyncfifo_irq != -1) { - if (freeirq) - free_irq(afifo->asyncfifo_irq, afifo); - else - disable_irq(afifo->asyncfifo_irq); - } - tasklet_kill(&afifo->asyncfifo_tasklet); - - afifo->init = 0; - - return 0; -} - -static int _dmx_smallsec_enable(struct aml_smallsec *ss, int bufsize) -{ - if (!ss->buf) { - - ss->buf = __get_free_pages(GFP_KERNEL, - get_order(bufsize)); - if (!ss->buf) { - pr_error("cannot allocate smallsec buffer\n" - "%d bytes %d order\n", - bufsize, get_order(bufsize)); - return -1; - } - ss->buf_map = dma_map_single(dmx_get_dev(ss->dmx), - (void *)ss->buf, - bufsize, DMA_FROM_DEVICE); - } - - DMX_WRITE_REG(ss->dmx->id, DEMUX_SMALL_SEC_ADDR, - ss->buf_map); - DMX_WRITE_REG(ss->dmx->id, DEMUX_SMALL_SEC_CTL, - ((((bufsize>>8)-1)&0xff)<<24) | - (1<<1) |/*enable reset the wr ptr*/ - (1<<0)); - - ss->bufsize = bufsize; - ss->enable = 1; - - pr_inf("demux%d smallsec buf start: %lx, size: %d\n", - ss->dmx->id, ss->buf, ss->bufsize); - return 0; -} - -static int _dmx_smallsec_disable(struct aml_smallsec *ss) -{ - DMX_WRITE_REG(ss->dmx->id, DEMUX_SMALL_SEC_CTL, 0); - if (ss->buf) { - dma_unmap_single(dmx_get_dev(ss->dmx), ss->buf_map, - ss->bufsize, DMA_FROM_DEVICE); - free_pages(ss->buf, get_order(ss->bufsize)); - ss->buf = 0; - ss->buf_map = 0; - } - ss->enable = 0; - pr_inf("demux%d smallsec buf disable\n", ss->dmx->id); - return 0; -} - -static int dmx_smallsec_set(struct aml_smallsec *ss, int enable, int bufsize, - int force) -{ - if (!enable) {/*disable*/ - - if (ss->enable || force) - _dmx_smallsec_disable(ss); - - } else {/*enable*/ - - if (bufsize < 0) - bufsize = SS_BUFSIZE_DEF; - else if (!bufsize) - bufsize = ss->bufsize; - else { - /*unit:FF max:FF00*/ - bufsize &= ~0xFF; - bufsize &= 0x1FF00; - } - - if ((ss->enable && (bufsize != ss->bufsize)) || force) - _dmx_smallsec_disable(ss); - - if (!ss->enable) - _dmx_smallsec_enable(ss, bufsize); - } - - return 0; -} - -static int _dmx_timeout_enable(struct aml_dmxtimeout *dto, int timeout, - int ch_dis, int match) -{ - - DMX_WRITE_REG(dto->dmx->id, DEMUX_INPUT_TIMEOUT_C, ch_dis); - DMX_WRITE_REG(dto->dmx->id, DEMUX_INPUT_TIMEOUT, - ((!!match)<<31) | - (timeout&0x7fffffff)); - - dto->ch_disable = ch_dis; - dto->match = match; - dto->timeout = timeout; - dto->trigger = 0; - dto->enable = 1; - - pr_inf("demux%d timeout enable:timeout(%d),ch(0x%x),match(%d)\n", - dto->dmx->id, dto->timeout, dto->ch_disable, dto->match); - - return 0; -} -static int _dmx_timeout_disable(struct aml_dmxtimeout *dto) -{ - - DMX_WRITE_REG(dto->dmx->id, DEMUX_INPUT_TIMEOUT, 0); - dto->enable = 0; - dto->trigger = 0; - pr_inf("demux%d timeout disable\n", dto->dmx->id); - - return 0; -} - -static int dmx_timeout_set(struct aml_dmxtimeout *dto, int enable, - int timeout, int ch_dis, int match, - int force) -{ - - if (!enable) {/*disable*/ - - if (dto->enable || force) - _dmx_timeout_disable(dto); - - } else {/*enable*/ - - if (timeout < 0) { - timeout = DTO_TIMEOUT_DEF; - ch_dis = DTO_CHDIS_VAS; - match = dto->match; - } else if (!timeout) { - timeout = dto->timeout; - ch_dis = dto->ch_disable; - match = dto->match; - } - - if ((dto->enable && (timeout != dto->timeout)) - || force) - _dmx_timeout_disable(dto); - - if (!dto->enable) - _dmx_timeout_enable(dto, timeout, ch_dis, match); - } - - return 0; -} - -/*Initialize the registers*/ -static int dmx_init(struct aml_dmx *dmx) -{ - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - int irq; - int ret = 0; - char buf[32]; - u32 value = 0; - - if (dmx->init) - return 0; - - pr_inf("demux init\n"); - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "asyncfifo_buf_len"); - ret = of_property_read_u32(dvb->pdev->dev.of_node, buf, &value); - if (!ret) { - pr_inf("%s: 0x%x\n", buf, value); - asyncfifo_buf_len = value; - } - /*Register irq handlers */ - if (dmx->dmx_irq != -1) { - pr_dbg("request irq\n"); - tasklet_init(&dmx->dmx_tasklet, - dmx_irq_bh_handler, - (unsigned long)dmx); - irq = request_irq(dmx->dmx_irq, dmx_irq_handler, - IRQF_SHARED|IRQF_TRIGGER_RISING, - "dmx irq", dmx); - } - - /*Allocate buffer */ - if (dmx_alloc_sec_buffer(dmx) < 0) - return -1; -#ifdef NO_SUB - if (dmx_alloc_sub_buffer(dmx) < 0) - return -1; -#endif - if (dmx_alloc_pes_buffer(dmx) < 0) - return -1; - - /*Reset the hardware */ - if (!dvb->dmx_init) { - init_timer(&dvb->watchdog_timer); - dvb->watchdog_timer.function = section_buffer_watchdog_func; - dvb->watchdog_timer.expires = - jiffies + msecs_to_jiffies(WATCHDOG_TIMER); - dvb->watchdog_timer.data = (unsigned long)dvb; -#ifdef ENABLE_SEC_BUFF_WATCHDOG - add_timer(&dvb->watchdog_timer); -#endif - dmx_reset_hw(dvb); - } - - dvb->dmx_init++; - - memset(dmx->sec_buf_watchdog_count, 0, - sizeof(dmx->sec_buf_watchdog_count)); - - dmx->init = 1; - - return 0; -} - -/*Release the resource*/ -static int dmx_deinit(struct aml_dmx *dmx) -{ - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - - if (!dmx->init) - return 0; - - DMX_WRITE_REG(dmx->id, DEMUX_CONTROL, 0); - - dvb->dmx_init--; - - /*Reset the hardware */ - if (!dvb->dmx_init) { - dmx_reset_hw(dvb); -#ifdef ENABLE_SEC_BUFF_WATCHDOG - del_timer_sync(&dvb->watchdog_timer); -#endif - } - - if (dmx->sec_pages) { - dma_unmap_single(dmx_get_dev(dmx), dmx->sec_pages_map, - dmx->sec_total_len, DMA_FROM_DEVICE); - free_pages(dmx->sec_pages, get_order(dmx->sec_total_len)); - dmx->sec_pages = 0; - dmx->sec_pages_map = 0; - } -#ifdef NO_SUB - if (dmx->sub_pages) { - dma_unmap_single(dmx_get_dev(dmx), dmx->sub_pages_map, - dmx->sub_buf_len, DMA_FROM_DEVICE); - free_pages(dmx->sub_pages, get_order(dmx->sub_buf_len)); - dmx->sub_pages = 0; - } -#endif - if (dmx->pes_pages) { - dma_unmap_single(dmx_get_dev(dmx), dmx->pes_pages_map, - dmx->pes_buf_len, DMA_FROM_DEVICE); - free_pages(dmx->pes_pages, get_order(dmx->pes_buf_len)); - dmx->pes_pages = 0; - } - - if (dmx->dmx_irq != -1) { - free_irq(dmx->dmx_irq, dmx); - tasklet_kill(&dmx->dmx_tasklet); - } - - dmx->init = 0; - - return 0; -} - -/*Check the record flag*/ -static int dmx_get_record_flag(struct aml_dmx *dmx) -{ - int i, linked = 0, record_flag = 0; - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - - /*Check whether a async fifo connected to this dmx */ - for (i = 0; i < dvb->async_fifo_total_count; i++) { - if (!dvb->asyncfifo[i].init) - continue; - if ((dvb->asyncfifo[i].source == dmx->id) - /*&& !(dvb->swfilter.user && (i==SF_AFIFO_ID)) */ - /*sf mode reserved */ - ) { - linked = 1; - break; - } - } - - for (i = 0; i < CHANNEL_COUNT; i++) { - if (dmx->channel[i].used && dmx->channel[i].dvr_feed) { - if (!dmx->record) { - dmx->record = 1; - - if (linked) { - /*A new record will start, - * must reset the async fifos for - * linking the right demux - */ - reset_async_fifos(dvb); - } - } - if (linked) - record_flag = 1; - goto find_done; - } - } - - if (dmx->record) { - dmx->record = 0; - if (linked) { - /*A record will stop, reset the async fifos - *for linking the right demux - */ - reset_async_fifos(dvb); - } - } - -find_done: - return record_flag; -} - -static void dmx_cascade_set(int cur_dmx, int source) { - int fec_sel_demux = 0; - int data; - - switch (source) { - case AM_TS_SRC_DMX0: - case AM_TS_SRC_DMX1: - case AM_TS_SRC_DMX2: - fec_sel_demux = source -AM_TS_SRC_DMX0; - break; - default: - fec_sel_demux = cur_dmx; - break; - } - - data = READ_MPEG_REG(TS_TOP_CONFIG1); - data &= ~(0x3 << (cur_dmx*2)); - data |= (fec_sel_demux << (cur_dmx*2)); - WRITE_MPEG_REG(TS_TOP_CONFIG1,data); - - pr_dbg("%s id:%d, source:%d data:0x%0x\n",__FUNCTION__,cur_dmx,fec_sel_demux,data); -} - -/*Enable the demux device*/ -static int dmx_enable(struct aml_dmx *dmx) -{ - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - int fec_sel, hi_bsf, fec_ctrl, record; - int fec_core_sel = 0; - int set_stb = 0, fec_s = 0; - int s2p_id; - u32 invert0 = 0, invert1 = 0, invert2 = 0, fec_s0 = 0, fec_s1 = 0, fec_s2 = 0; - u32 use_sop = 0; - - record = dmx_get_record_flag(dmx); - if (use_of_sop == 1) { - use_sop = 1; - pr_inf("dmx use of sop input\r\n"); - } - switch (dmx->source) { - case AM_TS_SRC_TS0: - fec_sel = 0; - fec_ctrl = dvb->ts[0].control; - record = record ? 1 : 0; - break; - case AM_TS_SRC_TS1: - fec_sel = 1; - fec_ctrl = dvb->ts[1].control; - record = record ? 1 : 0; - break; - case AM_TS_SRC_TS2: - fec_sel = 2; - fec_ctrl = dvb->ts[2].control; - record = record ? 1 : 0; - break; - case AM_TS_SRC_S_TS0: - case AM_TS_SRC_S_TS1: - case AM_TS_SRC_S_TS2: - s2p_id = 0; - fec_ctrl = 0; - if (dmx->source == AM_TS_SRC_S_TS0) { - s2p_id = dvb->ts[0].s2p_id; - fec_ctrl = dvb->ts[0].control; - } else if (dmx->source == AM_TS_SRC_S_TS1) { - s2p_id = dvb->ts[1].s2p_id; - fec_ctrl = dvb->ts[1].control; - } else if (dmx->source == AM_TS_SRC_S_TS2) { - s2p_id = dvb->ts[2].s2p_id; - fec_ctrl = dvb->ts[2].control; - } - //fec_sel = (s2p_id == 1) ? 5 : 6; - fec_sel = 6 - s2p_id; - record = record ? 1 : 0; - set_stb = 1; - fec_s = dmx->source - AM_TS_SRC_S_TS0; - break; - case AM_TS_SRC_HIU: - fec_sel = 7; - fec_ctrl = 0; - /* - support record in HIU mode - record = 0; - */ - break; - case AM_TS_SRC_HIU1: - fec_sel = 8; - fec_ctrl = 0; - /* - support record in HIU mode - record = 0; - */ - break; - case AM_TS_SRC_DMX0: - case AM_TS_SRC_DMX1: - case AM_TS_SRC_DMX2: - fec_sel = -1; - fec_ctrl = 0; - record = record ? 1 : 0; - break; - default: - fec_sel = 0; - fec_ctrl = 0; - record = 0; - break; - } - - if (dmx->channel[0].used || dmx->channel[1].used) { - hi_bsf = 1; - if (fec_sel == 8) { - hi_bsf = 2; /*hi_bsf select hiu1*/ - } - }else { - hi_bsf = 0; - } - if ((dvb->dsc[0].dst != -1) - && ((dvb->dsc[0].dst - AM_TS_SRC_DMX0) == dmx->id)) - fec_core_sel = 1; - - if ((dvb->dsc[1].dst != -1) - && ((dvb->dsc[1].dst - AM_TS_SRC_DMX0) == dmx->id)) { - int des_in, des_out, en_des = 0; - - switch (dvb->dsc[1].source) { - case AM_TS_SRC_DMX0: - des_in = 0; - en_des = 1; - break; - case AM_TS_SRC_DMX1: - des_in = 1; - en_des = 1; - break; - case AM_TS_SRC_DMX2: - des_in = 2; - en_des = 1; - break; - default: - des_in = 0; - en_des = 0; - break; - } - - switch (dvb->dsc[1].dst) { - case AM_TS_SRC_DMX0: - des_out = 1; - break; - case AM_TS_SRC_DMX1: - des_out = 2; - break; - case AM_TS_SRC_DMX2: - des_out = 4; - break; - default: - des_out = 0; - break; - } - - if (!des_out) - en_des = 0; - - WRITE_MPEG_REG(COMM_DESC_2_CTL, - (6 << 8) |/*des_out_dly_2*/ - ((!!en_des) << 6) |/* des_pl_clk_2*/ - ((!!en_des) << 5) |/* des_pl_2*/ - (des_out << 2) |/*use_des_2*/ - (des_in)/*des_i_sel_2*/ - ); - fec_core_sel = 1; - pr_dbg("dsc2 ctrl: 0x%x\n", READ_MPEG_REG(COMM_DESC_2_CTL)); - } - - pr_dbg("[dmx-%d]src: %d, rec: %d, hi_bsf: %d, dsc: %d\n", - dmx->id, dmx->source, record, hi_bsf, fec_core_sel); - - if (dmx->chan_count) { - if (set_stb) { - u32 v = READ_MPEG_REG(STB_TOP_CONFIG); - int i; - - for (i = 0; i < dvb->ts_in_total_count; i++) { - if (dvb->ts[i].s2p_id == 0) - fec_s0 = i; - else if (dvb->ts[i].s2p_id == 1) - fec_s1 = i; - else if (dvb->ts[i].s2p_id == 2) - fec_s2 = i; - } - - invert0 = dvb->s2p[0].invert; - invert1 = dvb->s2p[1].invert; - - v &= ~((0x3 << S2P0_FEC_SERIAL_SEL) | - (0x1f << INVERT_S2P0_FEC_CLK) | - (0x3 << S2P1_FEC_SERIAL_SEL) | - (0x1f << INVERT_S2P1_FEC_CLK)); - - v |= (fec_s0 << S2P0_FEC_SERIAL_SEL) | - (invert0 << INVERT_S2P0_FEC_CLK) | - (fec_s1 << S2P1_FEC_SERIAL_SEL) | - (invert1 << INVERT_S2P1_FEC_CLK); - WRITE_MPEG_REG(STB_TOP_CONFIG, v); - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { - invert2 = dvb->s2p[2].invert; - - //add s2p2 config - v = READ_MPEG_REG(STB_S2P2_CONFIG); - v &= ~((0x3 << S2P2_FEC_SERIAL_SEL) | - (0x1f << INVERT_S2P2_FEC_CLK)); - v |= (fec_s2 << S2P2_FEC_SERIAL_SEL) | - (invert2 << INVERT_S2P2_FEC_CLK); - WRITE_MPEG_REG(STB_S2P2_CONFIG, v); - } - } - - /*Initialize the registers */ - DMX_WRITE_REG(dmx->id, STB_INT_MASK, DEMUX_INT_MASK); - DMX_WRITE_REG(dmx->id, DEMUX_MEM_REQ_EN, -#ifdef USE_AHB_MODE - (1 << SECTION_AHB_DMA_EN) | - (0 << SUB_AHB_DMA_EN) | - (1 << OTHER_PES_AHB_DMA_EN) | -#endif - (1 << SECTION_PACKET) | - (1 << VIDEO_PACKET) | - (1 << AUDIO_PACKET) | - (1 << SUB_PACKET) | - (1 << SCR_ONLY_PACKET) | - (1 << OTHER_PES_PACKET)); - DMX_WRITE_REG(dmx->id, PES_STRONG_SYNC, 0x1234); - DMX_WRITE_REG(dmx->id, DEMUX_ENDIAN, - (1<id, TS_HIU_CTL, -// (0 << LAST_BURST_THRESHOLD) | - (hi_bsf << USE_HI_BSF_INTERFACE)); - } else { - DMX_WRITE_REG(dmx->id, TS_HIU_CTL, - (1 << PDTS_WR_SEL) | - (hi_bsf << USE_HI_BSF_INTERFACE)); - } - - if (fec_sel == -1) { - dmx_cascade_set(dmx->id,dmx->source); - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, - (fec_core_sel << FEC_CORE_SEL) | - (0 << FEC_SEL) | (fec_ctrl << 0)); - } else { - dmx_cascade_set(dmx->id,dmx->source); - if (fec_sel != 8) { - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, - (fec_core_sel << FEC_CORE_SEL) | - (fec_sel << FEC_SEL) | (fec_ctrl << 0)); - } else { - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, - (fec_core_sel << FEC_CORE_SEL) | - (1 << FEC_SEL_3BIT) | (fec_ctrl << 0)); - } - } - DMX_WRITE_REG(dmx->id, STB_OM_CTL, - (0x40 << MAX_OM_DMA_COUNT) | - (0x7f << LAST_OM_ADDR)); - DMX_WRITE_REG(dmx->id, DEMUX_CONTROL, - (0 << BYPASS_USE_RECODER_PATH) | - (0 << INSERT_AUDIO_PES_STRONG_SYNC) | - (0 << INSERT_VIDEO_PES_STRONG_SYNC) | - (0 << OTHER_INT_AT_PES_BEGINING) | - (0 << DISCARD_AV_PACKAGE) | - ((!!dmx->dump_ts_select) << TS_RECORDER_SELECT) | - (record << TS_RECORDER_ENABLE) | - (1 << KEEP_DUPLICATE_PACKAGE) | - (1 << SECTION_END_WITH_TABLE_ID) | - (1 << ENABLE_FREE_CLK_FEC_DATA_VALID) | - (1 << ENABLE_FREE_CLK_STB_REG) | - (1 << STB_DEMUX_ENABLE) | - (use_sop << NOT_USE_OF_SOP_INPUT)); - } else { - DMX_WRITE_REG(dmx->id, STB_INT_MASK, 0); - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, 0); - DMX_WRITE_REG(dmx->id, DEMUX_CONTROL, 0); - //dmx not used, but it can cascade for other dmx - if ((dmx->source == AM_TS_SRC_DMX0 || - dmx->source == AM_TS_SRC_DMX1 || - dmx->source == AM_TS_SRC_DMX2 ) && - (dmx->id != dmx->source-AM_TS_SRC_DMX0)) - dmx_cascade_set(dmx->id,dmx->source); - } - return 0; -} - -static int dmx_set_misc(struct aml_dmx *dmx, int hi_bsf, int en_dsc) -{ - if (hi_bsf >= 0) { - DMX_WRITE_REG(dmx->id, TS_HIU_CTL, - hi_bsf ? - (DMX_READ_REG(dmx->id, TS_HIU_CTL) | - (1 << USE_HI_BSF_INTERFACE)) - : - (DMX_READ_REG(dmx->id, TS_HIU_CTL) & - (~(1 << USE_HI_BSF_INTERFACE)))); - } - - if (en_dsc >= 0) { - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, - en_dsc ? - (DMX_READ_REG(dmx->id, FEC_INPUT_CONTROL) | - (1 << FEC_CORE_SEL)) - : - (DMX_READ_REG(dmx->id, FEC_INPUT_CONTROL) & - (~(1 << FEC_CORE_SEL)))); - } - - return 0; -} - -static int dmx_set_misc_id(struct aml_dvb *dvb, int id, int hi_bsf, int en_dsc) -{ - return dmx_set_misc(&dvb->dmx[id], hi_bsf, en_dsc); -} - -/*Get the channel's ID by its PID*/ -static int dmx_get_chan(struct aml_dmx *dmx, int pid) -{ - int id; - - for (id = 0; id < CHANNEL_COUNT; id++) { - if (dmx->channel[id].used && dmx->channel[id].pid == pid) - return id; - } - - return -1; -} - -/*Get the channel's target*/ -static u32 dmx_get_chan_target(struct aml_dmx *dmx, int cid) -{ - u32 type; - - if (!dmx->channel[cid].used) - return 0xFFFF; - - if (dmx->channel[cid].type == DMX_TYPE_SEC) { - type = SECTION_PACKET; - } else { - switch (dmx->channel[cid].pes_type) { - case DMX_PES_AUDIO: - type = AUDIO_PACKET; - break; - case DMX_PES_VIDEO: - type = VIDEO_PACKET; - break; - case DMX_PES_SUBTITLE: - case DMX_PES_TELETEXT: - type = SUB_PACKET; - break; - case DMX_PES_PCR: - type = SCR_ONLY_PACKET; - break; - default: - type = OTHER_PES_PACKET; - break; - } - } - - pr_dbg("chan target: %x %x\n", type, dmx->channel[cid].pid); - return (type << PID_TYPE) | dmx->channel[cid].pid; -} - -/*Get the advance value of the channel*/ -static inline u32 dmx_get_chan_advance(struct aml_dmx *dmx, int cid) -{ - return 0; -} - -/*Set the channel registers*/ -static int dmx_set_chan_regs(struct aml_dmx *dmx, int cid) -{ - u32 data, addr, advance, max; - - pr_dbg("set channel (id:%d PID:0x%x) registers\n", cid, - dmx->channel[cid].pid); - - while (DMX_READ_REG(dmx->id, FM_WR_ADDR) & 0x8000) - udelay(1); - - if (cid & 1) { - data = - (dmx_get_chan_target(dmx, cid - 1) << 16) | - dmx_get_chan_target(dmx, cid); - advance = - (dmx_get_chan_advance(dmx, cid) << 8) | - dmx_get_chan_advance(dmx, cid - 1); - } else { - data = - (dmx_get_chan_target(dmx, cid) << 16) | - dmx_get_chan_target(dmx, cid + 1); - advance = - (dmx_get_chan_advance(dmx, cid + 1) << 8) | - dmx_get_chan_advance(dmx, cid); - } - addr = cid >> 1; - DMX_WRITE_REG(dmx->id, FM_WR_DATA, data); - DMX_WRITE_REG(dmx->id, FM_WR_ADDR, (advance << 16) | 0x8000 | addr); - - pr_dbg("write fm %x:%x\n", (advance << 16) | 0x8000 | addr, data); - - for (max = CHANNEL_COUNT - 1; max > 0; max--) { - if (dmx->channel[max].used) - break; - } - - data = DMX_READ_REG(dmx->id, MAX_FM_COMP_ADDR) & 0xF0; - DMX_WRITE_REG(dmx->id, MAX_FM_COMP_ADDR, data | (max >> 1)); - - pr_dbg("write fm comp %x\n", data | (max >> 1)); - - if (DMX_READ_REG(dmx->id, OM_CMD_STATUS) & 0x8e00) { - pr_error("error send cmd %x\n", - DMX_READ_REG(dmx->id, OM_CMD_STATUS)); - } - - if (cid == 0) - first_video_pts = 0; - else if (cid == 1) - first_audio_pts = 0; - - return 0; -} - -/*Get the filter target*/ -static int dmx_get_filter_target(struct aml_dmx *dmx, int fid, u32 *target, - u8 *advance) -{ - struct dmx_section_filter *filter; - struct aml_filter *f; - int i, cid, neq_bytes; - - fid = fid & 0xFFFF; - f = &dmx->filter[fid]; - - if (!f->used) { - target[0] = 0x1fff; - advance[0] = 0; - for (i = 1; i < FILTER_LEN; i++) { - target[i] = 0x9fff; - advance[i] = 0; - } - return 0; - } - - cid = f->chan_id; - filter = f->filter; - - neq_bytes = 0; - if (filter->filter_mode[0] != 0xFF) { - neq_bytes = 2; - } else { - for (i = 3; i < FILTER_LEN; i++) { - if (filter->filter_mode[i] != 0xFF) - neq_bytes++; - } - } - - f->neq = 0; - - for (i = 0; i < FILTER_LEN; i++) { - u8 value = filter->filter_value[i]; - u8 mask = filter->filter_mask[i]; - u8 mode = filter->filter_mode[i]; - u8 mb, mb1, nb, v, t, adv = 0; - - if (!i) { - mb = 1; - mb1 = 1; - v = 0; - if ((mode == 0xFF) && mask) { - t = mask & 0xF0; - if (t) { - mb1 = 0; - adv |= t^0xF0; - } - v |= (value & 0xF0) | adv; - - t = mask & 0x0F; - if (t) { - mb = 0; - adv |= t^0x0F; - } - v |= (value & 0x0F) | adv; - } - - target[i] = (mb << SECTION_FIRSTBYTE_MASKLOW) | - (mb1 << SECTION_FIRSTBYTE_MASKHIGH) | - (0 << SECTION_FIRSTBYTE_DISABLE_PID_CHECK) | - (cid << SECTION_FIRSTBYTE_PID_INDEX) | v; - advance[i] = adv; - } else { - if (i < 3) { - value = 0; - mask = 0; - mode = 0xff; - } - mb = 1; - nb = 0; - v = 0; - - if ((i >= 3) && mask) { - if (mode == 0xFF) { - mb = 0; - nb = 0; - adv = mask ^ 0xFF; - v = value | adv; - } else { - if (neq_bytes == 1) { - mb = 0; - nb = 1; - adv = mask ^ 0xFF; - v = value & ~adv; - } - } - } - target[i] = (mb << SECTION_RESTBYTE_MASK) | - (nb << SECTION_RESTBYTE_MASK_EQ) | - (0 << SECTION_RESTBYTE_DISABLE_PID_CHECK) | - (cid << SECTION_RESTBYTE_PID_INDEX) | v; - advance[i] = adv; - } - - f->value[i] = value; - f->maskandmode[i] = mask & mode; - f->maskandnotmode[i] = mask & ~mode; - - if (f->maskandnotmode[i]) - f->neq = 1; - } - - return 0; -} - -/*Set the filter registers*/ -static int dmx_set_filter_regs(struct aml_dmx *dmx, int fid) -{ - u32 t1[FILTER_LEN], t2[FILTER_LEN]; - u8 advance1[FILTER_LEN], advance2[FILTER_LEN]; - u32 addr, data, max, adv; - int i; - - pr_dbg("set filter (id:%d) registers\n", fid); - - if (fid & 1) { - dmx_get_filter_target(dmx, fid - 1, t1, advance1); - dmx_get_filter_target(dmx, fid, t2, advance2); - } else { - dmx_get_filter_target(dmx, fid, t1, advance1); - dmx_get_filter_target(dmx, fid + 1, t2, advance2); - } - - for (i = 0; i < FILTER_LEN; i++) { - while (DMX_READ_REG(dmx->id, FM_WR_ADDR) & 0x8000) - udelay(1); - - data = (t1[i] << 16) | t2[i]; - addr = (fid >> 1) | ((i + 1) << 4); - adv = (advance1[i] << 8) | advance2[i]; - - DMX_WRITE_REG(dmx->id, FM_WR_DATA, data); - DMX_WRITE_REG(dmx->id, FM_WR_ADDR, (adv << 16) | 0x8000 | addr); - - pr_dbg("write fm %x:%x\n", (adv << 16) | 0x8000 | addr, data); - } - - for (max = FILTER_COUNT - 1; max > 0; max--) { - if (dmx->filter[max].used) - break; - } - - data = DMX_READ_REG(dmx->id, MAX_FM_COMP_ADDR) & 0xF; - DMX_WRITE_REG(dmx->id, MAX_FM_COMP_ADDR, data | ((max >> 1) << 4)); - - pr_dbg("write fm comp %x\n", data | ((max >> 1) << 4)); - - if (DMX_READ_REG(dmx->id, OM_CMD_STATUS) & 0x8e00) { - pr_error("error send cmd %x\n", - DMX_READ_REG(dmx->id, OM_CMD_STATUS)); - } - - return 0; -} - -/*Clear the filter's buffer*/ -static void dmx_clear_filter_buffer(struct aml_dmx *dmx, int fid) -{ - u32 section_busy32 = DMX_READ_REG(dmx->id, SEC_BUFF_READY); - u32 filter_number; - int i; - - if (!section_busy32) - return; - - for (i = 0; i < SEC_BUF_COUNT; i++) { - if (section_busy32 & (1 << i)) { - DMX_WRITE_REG(dmx->id, SEC_BUFF_NUMBER, i); - filter_number = - (DMX_READ_REG(dmx->id, SEC_BUFF_NUMBER) >> 8); - if (filter_number != fid) - section_busy32 &= ~(1 << i); - } - } - - if (section_busy32) - DMX_WRITE_REG(dmx->id, SEC_BUFF_READY, section_busy32); -} - -static void async_fifo_set_regs(struct aml_asyncfifo *afifo, int source_val) -{ - u32 start_addr = afifo->secure_enable ? afifo->blk.addr : - virt_to_phys((void *)afifo->pages); - u32 size = afifo->buf_len; - u32 flush_size = afifo->flush_size; - int factor = dmx_get_order(size / flush_size); - pr_error("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d," - "source value 0x%x, factor %d\n", - afifo->id, afifo->source, start_addr, size, source_val, factor); - /* Destination address */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG0, start_addr); - - /* Setup flush parameters */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG1, - (0 << ASYNC_FIFO_TO_HIU) | - (0 << ASYNC_FIFO_FLUSH) | - /* don't flush the path */ - (1 << ASYNC_FIFO_RESET) | - /* reset the path */ - (1 << ASYNC_FIFO_WRAP_EN) | - /* wrap enable */ - (0 << ASYNC_FIFO_FLUSH_EN) | - /* disable the flush path */ - /*(0x3 << ASYNC_FIFO_FLUSH_CNT_LSB); - * flush 3 x 32 32-bit words - */ - /*(0x7fff << ASYNC_FIFO_FLUSH_CNT_LSB); - * flush 4MBytes of data - */ - (((size >> 7) & 0x7fff) << ASYNC_FIFO_FLUSH_CNT_LSB)); - /* number of 128-byte blocks to flush */ - - /* clear the reset signal */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG1, - READ_ASYNC_FIFO_REG(afifo->id, - REG1) & ~(1 << ASYNC_FIFO_RESET)); - /* Enable flush */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG1, - READ_ASYNC_FIFO_REG(afifo->id, - REG1) | (1 << ASYNC_FIFO_FLUSH_EN)); - - /*Setup Fill parameters */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG2, - (1 << ASYNC_FIFO_ENDIAN_LSB) | - (0 << ASYNC_FIFO_FILL_EN) | - /* disable fill path to reset fill path */ - /*(96 << ASYNC_FIFO_FILL_CNT_LSB); - *3 x 32 32-bit words - */ - (0 << ASYNC_FIFO_FILL_CNT_LSB)); - /* forever FILL; */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG2, - READ_ASYNC_FIFO_REG(afifo->id, REG2) | - (1 << ASYNC_FIFO_FILL_EN));/*Enable fill path*/ - - /* generate flush interrupt */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG3, - (READ_ASYNC_FIFO_REG(afifo->id, REG3) & 0xffff0000) | - ((((size >> (factor + 7)) - 1) & 0x7fff) << - ASYNC_FLUSH_SIZE_IRQ_LSB)); - - /* Connect the STB DEMUX to ASYNC_FIFO */ - WRITE_ASYNC_FIFO_REG(afifo->id, REG2, - READ_ASYNC_FIFO_REG(afifo->id, REG2) | - (source_val << ASYNC_FIFO_SOURCE_LSB)); -} - -/*Reset the ASYNC FIFOS when a ASYNC FIFO connect to a different DMX*/ -static void reset_async_fifos(struct aml_dvb *dvb) -{ - struct aml_asyncfifo *low_dmx_fifo = NULL; - struct aml_asyncfifo *high_dmx_fifo = NULL; - struct aml_asyncfifo *highest_dmx_fifo = NULL; - int i, j; - int record_enable; - - pr_dbg("reset ASYNC FIFOs\n"); - for (i = 0; i < dvb->async_fifo_total_count; i++) { - if (!dvb->asyncfifo[i].init) - continue; - pr_dbg("Disable ASYNC FIFO id=%d\n", dvb->asyncfifo[i].id); - CLEAR_ASYNC_FIFO_REG_MASK(dvb->asyncfifo[i].id, REG1, - 1 << ASYNC_FIFO_FLUSH_EN); - CLEAR_ASYNC_FIFO_REG_MASK(dvb->asyncfifo[i].id, REG2, - 1 << ASYNC_FIFO_FILL_EN); - if (READ_ASYNC_FIFO_REG(dvb->asyncfifo[i].id, REG2) & - (1 << ASYNC_FIFO_FILL_EN) || - READ_ASYNC_FIFO_REG(dvb->asyncfifo[i].id, REG1) & - (1 << ASYNC_FIFO_FLUSH_EN)) { - pr_dbg("Set reg failed\n"); - } else - pr_dbg("Set reg ok\n"); - dvb->asyncfifo[i].buf_toggle = 0; - dvb->asyncfifo[i].buf_read = 0; - } - - for (j = 0; j < DMX_DEV_COUNT; j++) { - if (!dvb->dmx[j].init) - continue; - record_enable = 0; - for (i = 0; i < dvb->async_fifo_total_count; i++) { - if (!dvb->asyncfifo[i].init) - continue; - - if (dvb->dmx[j].record - && dvb->dmx[j].id == dvb->asyncfifo[i].source) { - /*This dmx is linked to the async fifo, - *Enable the TS_RECORDER_ENABLE - */ - record_enable = 1; - if (!low_dmx_fifo) { - low_dmx_fifo = &dvb->asyncfifo[i]; - } else if (low_dmx_fifo->source > - dvb->asyncfifo[i].source) { - if (!high_dmx_fifo) - high_dmx_fifo = low_dmx_fifo; - else { - highest_dmx_fifo = high_dmx_fifo; - high_dmx_fifo = low_dmx_fifo; - } - low_dmx_fifo = &dvb->asyncfifo[i]; - } else if (low_dmx_fifo->source < - dvb->asyncfifo[i].source) { - if (!high_dmx_fifo) - high_dmx_fifo = &dvb->asyncfifo[i]; - else { - if (high_dmx_fifo->source > dvb->asyncfifo[i].source) { - highest_dmx_fifo = high_dmx_fifo; - high_dmx_fifo = &dvb->asyncfifo[i]; - } else { - highest_dmx_fifo = &dvb->asyncfifo[i]; - } - } - } - - break; - } - } - pr_dbg("Set DMX%d TS_RECORDER_ENABLE to %d\n", dvb->dmx[j].id, - record_enable ? 1 : 0); - if (record_enable) { - /*DMX_SET_REG_MASK(dvb->dmx[j].id, - *DEMUX_CONTROL, 1<dmx[j].id, DEMUX_CONTROL, - DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL) | - (1 << TS_RECORDER_ENABLE)); - } else { - /*DMX_CLEAR_REG_MASK(dvb->dmx[j].id, - *DEMUX_CONTROL, 1<dmx[j].id, DEMUX_CONTROL, - DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL) & - (~(1 << TS_RECORDER_ENABLE))); - } - } - - /*Set the async fifo regs */ - if (low_dmx_fifo) { - async_fifo_set_regs(low_dmx_fifo, 0x3); - - if (high_dmx_fifo) { - async_fifo_set_regs(high_dmx_fifo, 0x2); - - if (highest_dmx_fifo) - async_fifo_set_regs(highest_dmx_fifo, 0x0); - } - } -} - -/*Reset the demux device*/ -void dmx_reset_hw(struct aml_dvb *dvb) -{ - dmx_reset_hw_ex(dvb, 1); -} - -/*Reset the demux device*/ -void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) -{ - int id, times; - - pr_dbg("demux reset begin\n"); - - for (id = 0; id < DMX_DEV_COUNT; id++) { - if (!dvb->dmx[id].init) - continue; - if (reset_irq) { - if (dvb->dmx[id].dmx_irq != -1) - disable_irq(dvb->dmx[id].dmx_irq); - if (dvb->dmx[id].dvr_irq != -1) - disable_irq(dvb->dmx[id].dvr_irq); - } - } -#ifdef ENABLE_SEC_BUFF_WATCHDOG - if (reset_irq) - del_timer_sync(&dvb->watchdog_timer); -#endif - - WRITE_MPEG_REG(RESET1_REGISTER, RESET_DEMUXSTB); - - for (id = 0; id < DMX_DEV_COUNT; id++) { - times = 0; - while (times++ < 1000000) { - if (!(DMX_READ_REG(id, OM_CMD_STATUS) & 0x01)) - break; - } - } - - WRITE_MPEG_REG(STB_TOP_CONFIG, 0); - WRITE_MPEG_REG(STB_S2P2_CONFIG, 0); - - for (id = 0; id < DMX_DEV_COUNT; id++) { - u32 version, data; - - if (!dvb->dmx[id].init) - continue; - - if (reset_irq) { - if (dvb->dmx[id].dmx_irq != -1) - enable_irq(dvb->dmx[id].dmx_irq); - if (dvb->dmx[id].dvr_irq != -1) - enable_irq(dvb->dmx[id].dvr_irq); - } - DMX_WRITE_REG(id, DEMUX_CONTROL, 0x0000); - version = DMX_READ_REG(id, STB_VERSION); - DMX_WRITE_REG(id, STB_TEST_REG, version); - pr_dbg("STB %d hardware version : %d\n", id, version); - DMX_WRITE_REG(id, STB_TEST_REG, 0x5550); - data = DMX_READ_REG(id, STB_TEST_REG); - if (data != 0x5550) - pr_error("STB %d register access failed\n", id); - DMX_WRITE_REG(id, STB_TEST_REG, 0xaaa0); - data = DMX_READ_REG(id, STB_TEST_REG); - if (data != 0xaaa0) - pr_error("STB %d register access failed\n", id); - DMX_WRITE_REG(id, MAX_FM_COMP_ADDR, 0x0000); - DMX_WRITE_REG(id, STB_INT_MASK, 0); - DMX_WRITE_REG(id, STB_INT_STATUS, 0xffff); - DMX_WRITE_REG(id, FEC_INPUT_CONTROL, 0); - } - - stb_enable(dvb); - - for (id = 0; id < DMX_DEV_COUNT; id++) { - struct aml_dmx *dmx = &dvb->dmx[id]; - int n; - unsigned long addr; - unsigned long base; - unsigned long grp_addr[SEC_BUF_GRP_COUNT]; - int grp_len[SEC_BUF_GRP_COUNT]; - - if (!dvb->dmx[id].init) - continue; - - if (dmx->sec_pages) { - grp_len[0] = (1 << SEC_GRP_LEN_0) * 8; - grp_len[1] = (1 << SEC_GRP_LEN_1) * 8; - grp_len[2] = (1 << SEC_GRP_LEN_2) * 8; - grp_len[3] = (1 << SEC_GRP_LEN_3) * 8; - - grp_addr[0] = virt_to_phys((void *)dmx->sec_pages); - grp_addr[1] = grp_addr[0] + grp_len[0]; - grp_addr[2] = grp_addr[1] + grp_len[1]; - grp_addr[3] = grp_addr[2] + grp_len[2]; - - base = grp_addr[0] & 0xFFFF0000; - DMX_WRITE_REG(dmx->id, SEC_BUFF_BASE, base >> 16); - DMX_WRITE_REG(dmx->id, SEC_BUFF_01_START, - (((grp_addr[0] - base) >> 8) << 16) | - ((grp_addr[1] - base) >> 8)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_23_START, - (((grp_addr[2] - base) >> 8) << 16) | - ((grp_addr[3] - base) >> 8)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_SIZE, - SEC_GRP_LEN_0 | - (SEC_GRP_LEN_1 << 4) | - (SEC_GRP_LEN_2 << 8) | - (SEC_GRP_LEN_3 << 12)); - } - - if (dmx->sub_pages) { - addr = virt_to_phys((void *)dmx->sub_pages); - DMX_WRITE_REG(dmx->id, SB_START, addr >> 12); - DMX_WRITE_REG(dmx->id, SB_LAST_ADDR, - (dmx->sub_buf_len >> 3) - 1); - } - - if (dmx->pes_pages) { - addr = virt_to_phys((void *)dmx->pes_pages); - DMX_WRITE_REG(dmx->id, OB_START, addr >> 12); - DMX_WRITE_REG(dmx->id, OB_LAST_ADDR, - (dmx->pes_buf_len >> 3) - 1); - } - - for (n = 0; n < CHANNEL_COUNT; n++) { - /*struct aml_channel *chan = &dmx->channel[n];*/ - - /*if (chan->used)*/ - { - dmx_set_chan_regs(dmx, n); - } - } - - for (n = 0; n < FILTER_COUNT; n++) { - struct aml_filter *filter = &dmx->filter[n]; - - if (filter->used) - dmx_set_filter_regs(dmx, n); - } - - dmx_enable(&dvb->dmx[id]); - - dmx_smallsec_set(&dmx->smallsec, - dmx->smallsec.enable, - dmx->smallsec.bufsize, - 1); - - dmx_timeout_set(&dmx->timeout, - dmx->timeout.enable, - dmx->timeout.timeout, - dmx->timeout.ch_disable, - dmx->timeout.match, - 1); - } - - for (id = 0; id < DSC_DEV_COUNT; id++) { - struct aml_dsc *dsc = &dvb->dsc[id]; - int n; - - for (n = 0; n < DSC_COUNT; n++) { - struct aml_dsc_channel *ch = &dsc->channel[n]; - /*if(ch->used) */ - { - ch->id = n; - ch->work_mode = -1; - dsc_set_pid(ch, ch->pid); - dsc_set_keys(ch); - } - } - } -#ifdef ENABLE_SEC_BUFF_WATCHDOG - if (reset_irq) { - mod_timer(&dvb->watchdog_timer, - jiffies + msecs_to_jiffies(WATCHDOG_TIMER)); - } -#endif - - pr_dbg("demux reset end\n"); -} - -/*Reset the individual demux*/ -void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx, - int reset_irq) -{ - { - if (!dmx->init) - return; - if (reset_irq) { - if (dmx->dmx_irq != -1) - disable_irq(dmx->dmx_irq); - if (dmx->dvr_irq != -1) - disable_irq(dmx->dvr_irq); - } - } -#ifdef ENABLE_SEC_BUFF_WATCHDOG - if (reset_irq) { - /*del_timer_sync(&dvb->watchdog_timer); */ - dvb->dmx_watchdog_disable[dmx->id] = 1; - } -#endif - - WRITE_MPEG_REG(RESET3_REGISTER, - (dmx->id) ? ((dmx->id == - 1) ? RESET_DEMUX1 : RESET_DEMUX2) : - RESET_DEMUX0); - WRITE_MPEG_REG(RESET3_REGISTER, RESET_DES); - - { - int times; - - times = 0; - while (times++ < 1000000) { - if (!(DMX_READ_REG(dmx->id, OM_CMD_STATUS) & 0x01)) - break; - } - } - - /*WRITE_MPEG_REG(STB_TOP_CONFIG, 0); */ - - { - u32 version, data; - - if (!dmx->init) - return; - - if (reset_irq) { - if (dmx->dmx_irq != -1) - enable_irq(dmx->dmx_irq); - if (dmx->dvr_irq != -1) - enable_irq(dmx->dvr_irq); - } - DMX_WRITE_REG(dmx->id, DEMUX_CONTROL, 0x0000); - version = DMX_READ_REG(dmx->id, STB_VERSION); - DMX_WRITE_REG(dmx->id, STB_TEST_REG, version); - pr_dbg("STB %d hardware version : %d\n", dmx->id, version); - DMX_WRITE_REG(dmx->id, STB_TEST_REG, 0x5550); - data = DMX_READ_REG(dmx->id, STB_TEST_REG); - if (data != 0x5550) - pr_error("STB %d register access failed\n", dmx->id); - DMX_WRITE_REG(dmx->id, STB_TEST_REG, 0xaaa0); - data = DMX_READ_REG(dmx->id, STB_TEST_REG); - if (data != 0xaaa0) - pr_error("STB %d register access failed\n", dmx->id); - DMX_WRITE_REG(dmx->id, MAX_FM_COMP_ADDR, 0x0000); - DMX_WRITE_REG(dmx->id, STB_INT_MASK, 0); - DMX_WRITE_REG(dmx->id, STB_INT_STATUS, 0xffff); - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, 0); - } - - stb_enable(dvb); - - { - int n; - unsigned long addr; - unsigned long base; - unsigned long grp_addr[SEC_BUF_GRP_COUNT]; - int grp_len[SEC_BUF_GRP_COUNT]; - - if (!dmx->init) - return; - - if (dmx->sec_pages) { - grp_len[0] = (1 << SEC_GRP_LEN_0) * 8; - grp_len[1] = (1 << SEC_GRP_LEN_1) * 8; - grp_len[2] = (1 << SEC_GRP_LEN_2) * 8; - grp_len[3] = (1 << SEC_GRP_LEN_3) * 8; - - grp_addr[0] = virt_to_phys((void *)dmx->sec_pages); - grp_addr[1] = grp_addr[0] + grp_len[0]; - grp_addr[2] = grp_addr[1] + grp_len[1]; - grp_addr[3] = grp_addr[2] + grp_len[2]; - - base = grp_addr[0] & 0xFFFF0000; - DMX_WRITE_REG(dmx->id, SEC_BUFF_BASE, base >> 16); - DMX_WRITE_REG(dmx->id, SEC_BUFF_01_START, - (((grp_addr[0] - base) >> 8) << 16) | - ((grp_addr[1] - base) >> 8)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_23_START, - (((grp_addr[2] - base) >> 8) << 16) | - ((grp_addr[3] - base) >> 8)); - DMX_WRITE_REG(dmx->id, SEC_BUFF_SIZE, - SEC_GRP_LEN_0 | - (SEC_GRP_LEN_1 << 4) | - (SEC_GRP_LEN_2 << 8) | - (SEC_GRP_LEN_3 << 12)); - } - - if (dmx->sub_pages) { - addr = virt_to_phys((void *)dmx->sub_pages); - DMX_WRITE_REG(dmx->id, SB_START, addr >> 12); - DMX_WRITE_REG(dmx->id, SB_LAST_ADDR, - (dmx->sub_buf_len >> 3) - 1); - } - - if (dmx->pes_pages) { - addr = virt_to_phys((void *)dmx->pes_pages); - DMX_WRITE_REG(dmx->id, OB_START, addr >> 12); - DMX_WRITE_REG(dmx->id, OB_LAST_ADDR, - (dmx->pes_buf_len >> 3) - 1); - } - - for (n = 0; n < CHANNEL_COUNT; n++) { - /*struct aml_channel *chan = &dmx->channel[n];*/ - - /*if (chan->used)*/ - { - dmx_set_chan_regs(dmx, n); - } - } - - for (n = 0; n < FILTER_COUNT; n++) { - struct aml_filter *filter = &dmx->filter[n]; - - if (filter->used) - dmx_set_filter_regs(dmx, n); - } - - for (n = 0; n < SEC_CNT_MAX; n++) { - dmx->sec_cnt[n] = 0; - dmx->sec_cnt_match[n] = 0; - dmx->sec_cnt_crc_fail[n] = 0; - } - - dmx_enable(dmx); - - dmx_smallsec_set(&dmx->smallsec, - dmx->smallsec.enable, - dmx->smallsec.bufsize, - 1); - - dmx_timeout_set(&dmx->timeout, - dmx->timeout.enable, - dmx->timeout.timeout, - dmx->timeout.ch_disable, - dmx->timeout.match, - 1); - } - - { - int id; - - for (id = 0; id < DSC_DEV_COUNT; id++) { - struct aml_dsc *dsc = &dvb->dsc[id]; - int n; - - for (n = 0; n < DSC_COUNT; n++) { - struct aml_dsc_channel *ch = &dsc->channel[n]; - /*if(ch->used) */ - ch->work_mode = -1; - dsc_set_pid(ch, ch->pid); - dsc_set_keys(ch); - } - } - } -#ifdef ENABLE_SEC_BUFF_WATCHDOG - if (reset_irq) { - /*mod_timer(&dvb->watchdog_timer, - *jiffies+msecs_to_jiffies(WATCHDOG_TIMER)); - */ - dvb->dmx_watchdog_disable[dmx->id] = 0; - } -#endif -} - -void dmx_reset_dmx_id_hw_ex_unlock(struct aml_dvb *dvb, int id, int reset_irq) -{ - dmx_reset_dmx_hw_ex_unlock(dvb, &dvb->dmx[id], reset_irq); -} - -void dmx_reset_dmx_hw_ex(struct aml_dvb *dvb, struct aml_dmx *dmx, - int reset_irq) -{ - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - dmx_reset_dmx_hw_ex_unlock(dvb, dmx, reset_irq); - spin_unlock_irqrestore(&dvb->slock, flags); -} - -void dmx_reset_dmx_id_hw_ex(struct aml_dvb *dvb, int id, int reset_irq) -{ - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - dmx_reset_dmx_id_hw_ex_unlock(dvb, id, reset_irq); - spin_unlock_irqrestore(&dvb->slock, flags); -} - -void dmx_reset_dmx_hw(struct aml_dvb *dvb, int id) -{ - dmx_reset_dmx_id_hw_ex(dvb, id, 1); -} - -/*Allocate subtitle pes buffer*/ -#if 0 -static int alloc_subtitle_pes_buffer(struct aml_dmx *dmx) -{ - int start_ptr = 0; - struct stream_buf_s *sbuff = 0; - u32 phy_addr; - - start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); - if (start_ptr) { - WRITE_MPEG_REG(PARSER_SUB_RP, start_ptr); - goto exit; - } - sbuff = get_stream_buffer(BUF_TYPE_SUBTITLE); - if (sbuff) { - if (sbuff->flag & BUF_FLAG_IOMEM) - phy_addr = sbuff->buf_start; - else - phy_addr = virt_to_phys((void *)sbuff->buf_start); - - WRITE_MPEG_REG(PARSER_SUB_RP, phy_addr); - WRITE_MPEG_REG(PARSER_SUB_START_PTR, phy_addr); - WRITE_MPEG_REG(PARSER_SUB_END_PTR, - phy_addr + sbuff->buf_size - 8); - - pr_dbg("pes buff=:%x %x\n", phy_addr, sbuff->buf_size); - } else - pr_dbg("Error stream buffer\n"); -exit: - return 0; -} -#endif - -/*Allocate a new channel*/ -int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid) -{ - int id = -1; - int ret; - - if (type == DMX_TYPE_TS) { - switch (pes_type) { - case DMX_PES_VIDEO: - if (!dmx->channel[0].used) - id = 0; - break; - case DMX_PES_AUDIO: - if (!dmx->channel[1].used) - id = 1; - break; - case DMX_PES_SUBTITLE: - case DMX_PES_TELETEXT: - if (!dmx->channel[2].used) - id = 2; - //alloc_subtitle_pes_buffer(dmx); - break; - case DMX_PES_PCR: - if (!dmx->channel[3].used) - id = 3; - break; - case DMX_PES_OTHER: - { - int i; - - for (i = SYS_CHAN_COUNT; - i < CHANNEL_COUNT; i++) { - if (!dmx->channel[i].used) { - id = i; - break; - } - } - } - break; - default: - break; - } - } else { - int i; - - for (i = SYS_CHAN_COUNT; i < CHANNEL_COUNT; i++) { - if (!dmx->channel[i].used) { - id = i; - break; - } - } - } - - if (id == -1) { - pr_error("too many channels\n"); - return -1; - } - - pr_dbg("allocate channel(id:%d PID:0x%x)\n", id, pid); - - if (id <= 3) { - ret = dmx_get_chan(dmx, pid); - if (ret >= 0 && DVR_FEED(dmx->channel[ret].feed)) { - dmx_remove_feed(dmx, dmx->channel[ret].feed); - dmx->channel[id].dvr_feed = dmx->channel[ret].feed; - dmx->channel[id].dvr_feed->priv = (void *)(long)id; - } else { - dmx->channel[id].dvr_feed = NULL; - } - } - - dmx->channel[id].type = type; - dmx->channel[id].pes_type = pes_type; - dmx->channel[id].pid = pid; - dmx->channel[id].used = 1; - dmx->channel[id].filter_count = 0; - - dmx_set_chan_regs(dmx, id); - - set_debug_dmx_chanpids(dmx->id, id, pid); - - dmx->chan_count++; - - dmx_enable(dmx); - - return id; -} - -/*Free a channel*/ -void dmx_free_chan(struct aml_dmx *dmx, int cid) -{ - pr_dbg("free channel(id:%d PID:0x%x)\n", cid, dmx->channel[cid].pid); - - dmx->channel[cid].used = 0; - dmx->channel[cid].pid = 0x1fff; - dmx_set_chan_regs(dmx, cid); - - if (cid == 2) { - u32 parser_sub_start_ptr; - - parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); - WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_start_ptr); - WRITE_MPEG_REG(PARSER_SUB_WP, parser_sub_start_ptr); - } - - set_debug_dmx_chanpids(dmx->id, cid, -1); - dmx->chan_count--; - - dmx_enable(dmx); - - /*Special pes type channel, check its dvr feed */ - if (cid <= 3 && dmx->channel[cid].dvr_feed) { - /*start the dvr feed */ - dmx_add_feed(dmx, dmx->channel[cid].dvr_feed); - } -} - -/*Add a section*/ -static int dmx_chan_add_filter(struct aml_dmx *dmx, int cid, - struct dvb_demux_filter *filter) -{ - int id = -1; - int i; - - for (i = 0; i < FILTER_COUNT; i++) { - if (!dmx->filter[i].used) { - id = i; - break; - } - } - - if (id == -1) { - pr_error("too many filters\n"); - return -1; - } - - pr_dbg("channel(id:%d PID:0x%x) add filter(id:%d)\n", cid, - filter->feed->pid, id); - - dmx->filter[id].chan_id = cid; - dmx->filter[id].used = 1; - dmx->filter[id].filter = (struct dmx_section_filter *)filter; - dmx->channel[cid].filter_count++; - - dmx_set_filter_regs(dmx, id); - - return id; -} - -static void dmx_remove_filter(struct aml_dmx *dmx, int cid, int fid) -{ - pr_dbg("channel(id:%d PID:0x%x) remove filter(id:%d)\n", cid, - dmx->channel[cid].pid, fid); - - dmx->filter[fid].used = 0; - dmx->channel[cid].filter_count--; - - dmx_set_filter_regs(dmx, fid); - dmx_clear_filter_buffer(dmx, fid); -} - -static int sf_add_feed(struct aml_dmx *src_dmx, struct dvb_demux_feed *feed) -{ - int ret = 0; - - struct aml_dvb *dvb = (struct aml_dvb *)src_dmx->demux.priv; - struct aml_swfilter *sf = &dvb->swfilter; - - pr_dbg_sf("sf add pid[%d]\n", feed->pid); - - /*init sf */ - if (!sf->user) { - void *mem; - - mem = vmalloc(SF_BUFFER_SIZE); - if (!mem) { - ret = -ENOMEM; - goto fail; - } - dvb_ringbuffer_init(&sf->rbuf, mem, SF_BUFFER_SIZE); - - sf->dmx = &dvb->dmx[SF_DMX_ID]; - sf->afifo = &dvb->asyncfifo[SF_AFIFO_ID]; - - sf->dmx->source = src_dmx->source; - sf->afifo->source = sf->dmx->id; - sf->track_dmx = src_dmx->id; - /*sf->afifo->flush_size = 188*10; */ - - pr_dbg_sf("init sf mode.\n"); - - } else if (sf->dmx->source != src_dmx->source) { - pr_error(" pid=%d[src:%d] already used with sfdmx%d[src:%d]\n", - feed->pid, src_dmx->source, sf->dmx->id, - sf->dmx->source); - ret = -EBUSY; - goto fail; - } - - /*setup feed */ - ret = dmx_get_chan(sf->dmx, feed->pid); - if (ret >= 0) { - pr_error(" pid=%d[dmx:%d] already used [dmx:%d].\n", - feed->pid, src_dmx->id, - ((struct aml_dmx *)sf->dmx->channel[ret].feed-> - demux)->id); - ret = -EBUSY; - goto fail; - } - ret = - dmx_alloc_chan(sf->dmx, DMX_TYPE_TS, DMX_PES_OTHER, - feed->pid); - if (ret < 0) { - pr_error(" %s: alloc chan error, ret=%d\n", __func__, ret); - ret = -EBUSY; - goto fail; - } - sf->dmx->channel[ret].feed = feed; - feed->priv = (void *)(long)ret; - - sf->dmx->channel[ret].dvr_feed = feed; - - sf->user++; - debug_sf_user = sf->user; - - dmx_enable(sf->dmx); - - return 0; - -fail: - feed->priv = (void *)-1; - return ret; -} - -static int sf_remove_feed(struct aml_dmx *src_dmx, struct dvb_demux_feed *feed) -{ - int ret; - - struct aml_dvb *dvb = (struct aml_dvb *)src_dmx->demux.priv; - struct aml_swfilter *sf = &dvb->swfilter; - - if (!sf->user || (sf->dmx->source != src_dmx->source)) - return 0; - - /*add fail, no need to remove*/ - if (((long)feed->priv) < 0) - return 0; - - ret = dmx_get_chan(sf->dmx, feed->pid); - if (ret < 0) - return 0; - - pr_dbg_sf("sf remove pid[%d]\n", feed->pid); - - dmx_free_chan(sf->dmx, (long)feed->priv); - - sf->dmx->channel[ret].feed = NULL; - sf->dmx->channel[ret].dvr_feed = NULL; - - sf->user--; - debug_sf_user = sf->user; - - if (!sf->user) { - sf->dmx->source = -1; - sf->afifo->source = AM_DMX_MAX; - sf->track_dmx = -1; - /*sf->afifo->flush_size = sf->afifo->buf_len>>1; */ - - if (sf->rbuf.data) { - void *mem = sf->rbuf.data; - - sf->rbuf.data = NULL; - vfree(mem); - } - pr_dbg_sf("exit sf mode.\n"); - } - - return 0; -} - -static int sf_feed_sf(struct aml_dmx *dmx, struct dvb_demux_feed *feed, - int add_not_remove) -{ - int sf = 0; - - if (sf_dmx_sf(dmx)) { - pr_error("%s: demux %d is in sf mode\n", __func__, dmx->id); - return -EINVAL; - } - - switch (feed->type) { - case DMX_TYPE_TS:{ - struct dmxdev_filter *dmxdevfilter = - feed->feed.ts.priv; - if (!DVR_FEED(feed)) { - if (dmxdevfilter->params.pes. - flags & DMX_USE_SWFILTER) - sf = 1; - if (force_pes_sf) - sf = 1; - } - } - break; - - case DMX_TYPE_SEC:{ - struct dvb_demux_filter *filter; - - for (filter = feed->filter; filter; - filter = filter->next) { - struct dmxdev_filter *dmxdevfilter = - filter->filter.priv; - if (dmxdevfilter->params.sec. - flags & DMX_USE_SWFILTER) - sf = 1; - if (add_not_remove) - filter->hw_handle = (u16)-1; - } - if (force_sec_sf) - sf = 1; - } - break; - } - - return sf ? 0 : 1; -} - -static int sf_check_feed(struct aml_dmx *dmx, struct dvb_demux_feed *feed, - int add_not_remove) -{ - int ret = 0; - - ret = sf_feed_sf(dmx, feed, add_not_remove); - if (ret) - return ret; - - pr_dbg_sf("%s [pid:%d] %s\n", - (feed->type == DMX_TYPE_TS) ? "DMX_TYPE_TS" : "DMX_TYPE_SEC", - feed->pid, add_not_remove ? "-> sf mode" : "sf mode ->"); - - if (add_not_remove) - ret = sf_add_feed(dmx, feed); - else - ret = sf_remove_feed(dmx, feed); - - if (ret < 0) { - pr_error("sf %s feed fail[%d]\n", - add_not_remove ? "add" : "remove", ret); - } - return ret; -} - -static int dmx_add_feed(struct aml_dmx *dmx, struct dvb_demux_feed *feed) -{ - int id, ret = 0; - struct dvb_demux_filter *filter; - struct dvb_demux_feed *dfeed = NULL; - int sf_ret = 0; /*<0:error, =0:sf_on, >0:sf_off */ - - sf_ret = sf_check_feed(dmx, feed, 1/*SF_FEED_OP_ADD */); - if (sf_ret < 0) - return sf_ret; - - switch (feed->type) { - case DMX_TYPE_TS: - pr_dbg("%s: DMX_TYPE_TS\n", __func__); - ret = dmx_get_chan(dmx, feed->pid); - if (ret >= 0) { - if (DVR_FEED(dmx->channel[ret].feed)) { - if (DVR_FEED(feed)) { - /*dvr feed already work */ - pr_error("PID %d already used(DVR)\n", - feed->pid); - ret = -EBUSY; - goto fail; - } - if (sf_ret) { - /*if sf_on, we do not reset the - *previous dvr feed, just load the pes - *feed on the sf, a diffrent data path. - */ - dfeed = dmx->channel[ret].feed; - dmx_remove_feed(dmx, dfeed); - } - } else { - if (DVR_FEED(feed) - && (!dmx->channel[ret].dvr_feed)) { - /*just store the dvr_feed */ - dmx->channel[ret].dvr_feed = feed; - feed->priv = (void *)(long)ret; - if (!dmx->record) - dmx_enable(dmx); - dmx_add_recchan(dmx->id, ret); - return 0; - } - { - pr_error("PID %d already used\n", - feed->pid); - ret = -EBUSY; - goto fail; - } - } - } - - if (sf_ret) { /*not sf feed. */ - ret = - dmx_alloc_chan(dmx, feed->type, - feed->pes_type, feed->pid); - if (ret < 0) { - pr_dbg("%s: alloc chan error, ret=%d\n", - __func__, ret); - ret = -EBUSY; - goto fail; - } - dmx->channel[ret].feed = feed; - feed->priv = (void *)(long)ret; - dmx->channel[ret].dvr_feed = NULL; - } - /*dvr */ - if (DVR_FEED(feed)) { - dmx->channel[ret].dvr_feed = feed; - feed->priv = (void *)(long)ret; - if (!dmx->record) - dmx_enable(dmx); - dmx_add_recchan(dmx->id, ret); - } else if (dfeed && sf_ret) { - dmx->channel[ret].dvr_feed = dfeed; - dfeed->priv = (void *)(long)ret; - if (!dmx->record) - dmx_enable(dmx); - dmx_add_recchan(dmx->id, ret); - } - - break; - case DMX_TYPE_SEC: - pr_dbg("%s: DMX_TYPE_SEC\n", __func__); - ret = dmx_get_chan(dmx, feed->pid); - if (ret >= 0) { - if (DVR_FEED(dmx->channel[ret].feed)) { - if (sf_ret) { - /*if sf_on, we do not reset the - *previous dvr feed, just load the pes - *feed on the sf,a diffrent data path. - */ - dfeed = dmx->channel[ret].feed; - dmx_remove_feed(dmx, dfeed); - } - } else { - pr_error("PID %d already used\n", feed->pid); - ret = -EBUSY; - goto fail; - } - } - if (sf_ret) { /*not sf feed. */ - id = dmx_alloc_chan(dmx, feed->type, - feed->pes_type, feed->pid); - if (id < 0) { - pr_dbg("%s: alloc chan error, ret=%d\n", - __func__, id); - ret = -EBUSY; - goto fail; - } - for (filter = feed->filter; filter; - filter = filter->next) { - ret = dmx_chan_add_filter(dmx, id, filter); - if (ret >= 0) - filter->hw_handle = ret; - else - filter->hw_handle = (u16)-1; - } - dmx->channel[id].feed = feed; - feed->priv = (void *)(long)id; - dmx->channel[id].dvr_feed = NULL; - - if (dfeed) { - dmx->channel[id].dvr_feed = dfeed; - dfeed->priv = (void *)(long)id; - if (!dmx->record) - dmx_enable(dmx); - dmx_add_recchan(dmx->id, id); - } - } - break; - default: - return -EINVAL; - } - - dmx->feed_count++; - - return 0; - -fail: - feed->priv = (void *)-1; - return ret; -} - -static int dmx_remove_feed(struct aml_dmx *dmx, struct dvb_demux_feed *feed) -{ - struct dvb_demux_filter *filter; - struct dvb_demux_feed *dfeed = NULL; - - int sf_ret = 0; /*<0:error, =0:sf_on, >0:sf_off */ - - /*add fail, no need to remove*/ - if (((long)feed->priv) < 0) - return 0; - - sf_ret = sf_check_feed(dmx, feed, 0/*SF_FEED_OP_RM */); - if (sf_ret <= 0) - return sf_ret; - - switch (feed->type) { - case DMX_TYPE_TS: - if (dmx->channel[(long)feed->priv].feed == - dmx->channel[(long)feed->priv].dvr_feed) { - dmx_rm_recchan(dmx->id, (long)feed->priv); - dmx_free_chan(dmx, (long)feed->priv); - } else { - if (feed == dmx->channel[(long)feed->priv].feed) { - dfeed = dmx->channel[(long)feed->priv].dvr_feed; - dmx_rm_recchan(dmx->id, (long)feed->priv); - dmx_free_chan(dmx, (long)feed->priv); - if (dfeed) { - /*start the dvr feed */ - dmx_add_feed(dmx, dfeed); - } - } else if (feed == - dmx->channel[(long)feed->priv].dvr_feed) { - /*just remove the dvr_feed */ - dmx->channel[(long)feed->priv].dvr_feed = NULL; - dmx_rm_recchan(dmx->id, (long)feed->priv); - if (dmx->record) - dmx_enable(dmx); - } else { - /*This must never happen */ - pr_error("%s: unknown feed\n", __func__); - return -EINVAL; - } - } - - break; - case DMX_TYPE_SEC: - for (filter = feed->filter; filter; filter = filter->next) { - if (filter->hw_handle != (u16)-1) - dmx_remove_filter(dmx, (long)feed->priv, - (int)filter->hw_handle); - } - - dfeed = dmx->channel[(long)feed->priv].dvr_feed; - dmx_rm_recchan(dmx->id, (long)feed->priv); - dmx_free_chan(dmx, (long)feed->priv); - if (dfeed) { - /*start the dvr feed */ - dmx_add_feed(dmx, dfeed); - } - break; - default: - return -EINVAL; - } - - dmx->feed_count--; - return 0; -} - -int aml_dmx_hw_init(struct aml_dmx *dmx) -{ - /* - *struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - *unsigned long flags; - */ - int ret; - - /*Demux initialize */ - /*spin_lock_irqsave(&dvb->slock, flags);*/ - ret = dmx_init(dmx); - /*spin_unlock_irqrestore(&dvb->slock, flags);*/ - - return ret; -} - -int aml_dmx_hw_deinit(struct aml_dmx *dmx) -{ - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - unsigned long flags; - int ret; - - spin_lock_irqsave(&dvb->slock, flags); - ret = dmx_deinit(dmx); - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -/*extern void afifo_reset(int v);*/ - -int aml_asyncfifo_hw_init(struct aml_asyncfifo *afifo) -{ - -/* - * struct aml_dvb *dvb = afifo->dvb; - * unsigned long flags; - */ - int ret; - - int len = asyncfifo_buf_len; - unsigned long buf = asyncfifo_alloc_buffer(len); - - if (!buf) - return -1; - - /*Async FIFO initialize*/ -/* - * spin_lock_irqsave(&dvb->slock, flags); - */ -/* - *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 - * CLK_GATE_ON(ASYNC_FIFO); - *#endif - */ - /*afifo_reset(0);*/ - - WRITE_MPEG_REG(RESET6_REGISTER, (1<<11)|(1<<12)); - - ret = async_fifo_init(afifo, 1, len, buf); -/* - * spin_unlock_irqrestore(&dvb->slock, flags); - */ - if (ret < 0) - asyncfifo_free_buffer(buf, len); - - return ret; -} - -int aml_asyncfifo_hw_deinit(struct aml_asyncfifo *afifo) -{ - int ret; - - ret = async_fifo_deinit(afifo, 1); -/* - *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 - * CLK_GATE_OFF(ASYNC_FIFO); - *#endif - */ - /*afifo_reset(1);*/ - - return ret; -} - -int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo) -{ - struct aml_dvb *dvb = afifo->dvb; - unsigned long flags; - int ret, src = -1; - - unsigned long buf = 0; - int len = asyncfifo_buf_len; - buf = asyncfifo_alloc_buffer(len); - if (!buf) - return -1; - - if (afifo->init) { - src = afifo->source; - async_fifo_deinit(afifo, 0); - } - - spin_lock_irqsave(&dvb->slock, flags); - ret = async_fifo_init(afifo, 0, len, buf); - /* restore the source */ - if (src != -1) - afifo->source = src; - - if ((ret == 0) && afifo->dvb) - reset_async_fifos(afifo->dvb); - - spin_unlock_irqrestore(&dvb->slock, flags); - - if (ret < 0) - asyncfifo_free_buffer(buf, len); - - return ret; -} - -int aml_dmx_hw_start_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - struct aml_dmx *dmx = (struct aml_dmx *)dvbdmxfeed->demux; - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dvb->slock, flags); - ret = dmx_add_feed(dmx, dvbdmxfeed); - spin_unlock_irqrestore(&dvb->slock, flags); - - /*handle errors silently*/ - if (ret != 0) - ret = 0; - - return ret; -} - -int aml_dmx_hw_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - struct aml_dmx *dmx = (struct aml_dmx *)dvbdmxfeed->demux; - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - dmx_remove_feed(dmx, dvbdmxfeed); - spin_unlock_irqrestore(&dvb->slock, flags); - - return 0; -} - -int sf_dmx_track_source(struct aml_dmx *dmx) -{ - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - struct aml_swfilter *sf = &dvb->swfilter; - - if (sf->user && (dmx->id == sf->track_dmx)) { - pr_dbg_sf("tracking dmx src [%d -> %d]\n", - sf->dmx->source, dmx->source); - sf->dmx->source = dmx->source; - dmx_reset_dmx_hw_ex_unlock(dvb, sf->dmx, 0); - } - return 0; -} - -int aml_dmx_hw_set_source(struct dmx_demux *demux, dmx_source_t src) -{ - struct aml_dmx *dmx = (struct aml_dmx *)demux; - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - int ret = 0; - int hw_src; - unsigned long flags; - - if (sf_dmx_sf(dmx)) { - pr_error("%s: demux %d is in sf mode\n", __func__, dmx->id); - return -EINVAL; - } - - spin_lock_irqsave(&dvb->slock, flags); - - hw_src = dmx->source; - - switch (src) { - case DMX_SOURCE_FRONT0: - hw_src = - (dvb->ts[0].mode == - AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; - break; - case DMX_SOURCE_FRONT1: - hw_src = - (dvb->ts[1].mode == - AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; - break; - case DMX_SOURCE_FRONT2: - hw_src = - (dvb->ts[2].mode == - AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; - break; - case DMX_SOURCE_FRONT3: - hw_src = - (dvb->ts[3].mode == - AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; - break; - case DMX_SOURCE_DVR0: - hw_src = AM_TS_SRC_HIU; - break; - case DMX_SOURCE_DVR1: - hw_src = AM_TS_SRC_HIU1; - break; - case DMX_SOURCE_FRONT0_OFFSET: - hw_src = AM_TS_SRC_DMX0; - break; - case DMX_SOURCE_FRONT1_OFFSET: - hw_src = AM_TS_SRC_DMX1; - break; - case DMX_SOURCE_FRONT2_OFFSET: - hw_src = AM_TS_SRC_DMX2; - break; - default: - pr_error("illegal demux source %d\n", src); - ret = -EINVAL; - break; - } - - if (hw_src != dmx->source) { - dmx->source = hw_src; - dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0); - sf_dmx_track_source(dmx); - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -#define IS_SRC_DMX(_src) ((_src) >= AM_TS_SRC_DMX0 && (_src) <= AM_TS_SRC_DMX2) - -int aml_stb_hw_set_source(struct aml_dvb *dvb, dmx_source_t src) -{ - unsigned long flags; - int hw_src; - int ret; - - ret = 0; - spin_lock_irqsave(&dvb->slock, flags); - - hw_src = dvb->stb_source; - - switch (src) { - case DMX_SOURCE_FRONT0: - hw_src = - (dvb->ts[0].mode == - AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; - break; - case DMX_SOURCE_FRONT1: - hw_src = - (dvb->ts[1].mode == - AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; - break; - case DMX_SOURCE_FRONT2: - hw_src = - (dvb->ts[2].mode == - AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; - break; - case DMX_SOURCE_FRONT3: - hw_src = - (dvb->ts[3].mode == - AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; - break; - case DMX_SOURCE_DVR0: - hw_src = AM_TS_SRC_HIU; - break; - case DMX_SOURCE_DVR1: - hw_src = AM_TS_SRC_HIU1; - break; - case DMX_SOURCE_FRONT0_OFFSET: - hw_src = AM_TS_SRC_DMX0; - break; - case DMX_SOURCE_FRONT1_OFFSET: - hw_src = AM_TS_SRC_DMX1; - break; - case DMX_SOURCE_FRONT2_OFFSET: - hw_src = AM_TS_SRC_DMX2; - break; - default: - pr_error("illegal demux source %d\n", src); - ret = -EINVAL; - break; - } - - if (dvb->stb_source != hw_src) { - int old_source = dvb->stb_source; - - dvb->stb_source = hw_src; - - if (IS_SRC_DMX(old_source)) { - dmx_set_misc_id(dvb, - (old_source - AM_TS_SRC_DMX0), 0, -1); - } else { - /*which dmx for av-play is unknown, - *can't avoid reset-all - */ - dmx_reset_hw_ex(dvb, 0); - } - - if (IS_SRC_DMX(dvb->stb_source)) { - dmx_set_misc_id(dvb, - (dvb->stb_source - AM_TS_SRC_DMX0), 1, -1); - /*dmx_reset_dmx_id_hw_ex_unlock - * (dvb, (dvb->stb_source-AM_TS_SRC_DMX0), 0); - */ - } else { - /*which dmx for av-play is unknown, - *can't avoid reset-all - */ - dmx_reset_hw_ex(dvb, 0); - } - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - - - -int aml_dsc_hw_set_source(struct aml_dsc *dsc, - dmx_source_t src, dmx_source_t dst) -{ - struct aml_dvb *dvb = dsc->dvb; - int ret = 0; - unsigned long flags; - int hw_src = -1, hw_dst = -1, org_src = -1, org_dst = -1; - int src_reset = 0, dst_reset = 0; - - spin_lock_irqsave(&dvb->slock, flags); - - hw_src = dsc->source; - hw_dst = dsc->dst; - - switch (src) { - case DMX_SOURCE_FRONT0_OFFSET: - hw_src = AM_TS_SRC_DMX0; - break; - case DMX_SOURCE_FRONT1_OFFSET: - hw_src = AM_TS_SRC_DMX1; - break; - case DMX_SOURCE_FRONT2_OFFSET: - hw_src = AM_TS_SRC_DMX2; - break; - default: - hw_src = -1; - break; - } - switch (dst) { - case DMX_SOURCE_FRONT0_OFFSET: - hw_dst = AM_TS_SRC_DMX0; - break; - case DMX_SOURCE_FRONT1_OFFSET: - hw_dst = AM_TS_SRC_DMX1; - break; - case DMX_SOURCE_FRONT2_OFFSET: - hw_dst = AM_TS_SRC_DMX2; - break; - default: - hw_dst = -1; - break; - } - - if (hw_src != dsc->source) { - org_src = dsc->source; - dsc->source = hw_src; - src_reset = 1; - } - if (hw_dst != dsc->dst) { - org_dst = dsc->dst; - dsc->dst = hw_dst; - dst_reset = 1; - } - - if (src_reset) { - pr_inf("dsc%d source changed: %d -> %d\n", - dsc->id, org_src, hw_src); - if (org_src != -1) { - pr_inf("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0)); - dmx_reset_dmx_id_hw_ex_unlock(dvb, - (org_src - AM_TS_SRC_DMX0), 0); - } - if (hw_src != -1) { - pr_inf("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0)); - dmx_reset_dmx_id_hw_ex_unlock(dvb, - (hw_src - AM_TS_SRC_DMX0), 0); - } else - dsc_enable(dsc, 0); - } - if (dst_reset) { - pr_inf("dsc%d dest changed: %d -> %d\n", - dsc->id, org_dst, hw_dst); - if (((!src_reset) && (org_dst != -1)) || - (src_reset && (org_dst != -1) && - (org_dst != org_src) && (org_dst != hw_src))) { - pr_inf("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0)); - dmx_reset_dmx_id_hw_ex_unlock(dvb, - (org_dst - AM_TS_SRC_DMX0), 0); - } - if (((!src_reset) && (hw_dst != -1)) || - (src_reset && (hw_dst != -1) - && (hw_dst != org_src) && (hw_dst != hw_src))) { - pr_inf("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0)); - dmx_reset_dmx_id_hw_ex_unlock(dvb, - (hw_dst - AM_TS_SRC_DMX0), 0); - } - if (hw_dst == -1) - dsc_enable(dsc, 0); - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -int aml_tso_hw_set_source(struct aml_dvb *dvb, dmx_source_t src) -{ - int ret = 0; - unsigned long flags; - int hw_src; - - spin_lock_irqsave(&dvb->slock, flags); - - hw_src = dvb->tso_source; - - switch (src) { - case DMX_SOURCE_FRONT0: - hw_src = (dvb->ts[0].mode == AM_TS_SERIAL) - ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; - break; - case DMX_SOURCE_FRONT1: - hw_src = (dvb->ts[1].mode == AM_TS_SERIAL) - ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; - break; - case DMX_SOURCE_FRONT2: - hw_src = (dvb->ts[2].mode == AM_TS_SERIAL) - ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; - break; - case DMX_SOURCE_FRONT3: - hw_src = (dvb->ts[3].mode == AM_TS_SERIAL) - ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; - break; - case DMX_SOURCE_DVR0: - hw_src = AM_TS_SRC_HIU; - break; - case DMX_SOURCE_FRONT0 + 100: - hw_src = AM_TS_SRC_DMX0; - break; - case DMX_SOURCE_FRONT1 + 100: - hw_src = AM_TS_SRC_DMX1; - break; - case DMX_SOURCE_FRONT2 + 100: - hw_src = AM_TS_SRC_DMX2; - break; - default: - hw_src = -1; - ret = -EINVAL; - break; - } - - if (hw_src != dvb->tso_source) { - dvb->tso_source = hw_src; - stb_enable(dvb); - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -int aml_asyncfifo_hw_set_source(struct aml_asyncfifo *afifo, - enum aml_dmx_id_t src) -{ - struct aml_dvb *dvb = afifo->dvb; - int ret = -1; - unsigned long flags; - - if (sf_afifo_sf(afifo)) { - pr_error("%s: afifo %d is in sf mode\n", __func__, afifo->id); - return -EINVAL; - } - - spin_lock_irqsave(&dvb->slock, flags); - - pr_dbg("asyncfifo %d set source %d->%d", - afifo->id, afifo->source, src); - switch (src) { - case AM_DMX_0: - case AM_DMX_1: - case AM_DMX_2: - if (afifo->source != src) { - afifo->source = src; - ret = 0; - } - break; - default: - pr_error("illegal async fifo source %d\n", src); - ret = -EINVAL; - break; - } - - if (ret == 0 && afifo->dvb) - reset_async_fifos(afifo->dvb); - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -int aml_dmx_hw_set_dump_ts_select(struct dmx_demux *demux, int dump_ts_select) -{ - struct aml_dmx *dmx = (struct aml_dmx *)demux; - struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - dump_ts_select = !!dump_ts_select; - if (dmx->dump_ts_select != dump_ts_select) { - dmx->dump_ts_select = dump_ts_select; - dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0); - } - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -u32 aml_dmx_get_video_pts(struct aml_dvb *dvb) -{ - unsigned long flags; - u32 pts; - - spin_lock_irqsave(&dvb->slock, flags); - pts = video_pts; - spin_unlock_irqrestore(&dvb->slock, flags); - - return pts; -} - -u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb) -{ - unsigned long flags; - u32 pts; - - spin_lock_irqsave(&dvb->slock, flags); - pts = audio_pts; - spin_unlock_irqrestore(&dvb->slock, flags); - - return pts; -} - -u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb) -{ - unsigned long flags; - u32 bit32; - - spin_lock_irqsave(&dvb->slock, flags); - bit32 = video_pts_bit32; - spin_unlock_irqrestore(&dvb->slock, flags); - - return bit32; -} - -u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb) -{ - unsigned long flags; - u32 bit32; - - spin_lock_irqsave(&dvb->slock, flags); - bit32 = audio_pts_bit32; - spin_unlock_irqrestore(&dvb->slock, flags); - - return bit32; -} -u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb) -{ - unsigned long flags; - u32 pts; - - spin_lock_irqsave(&dvb->slock, flags); - pts = first_video_pts; - spin_unlock_irqrestore(&dvb->slock, flags); - - return pts; -} - -u32 aml_dmx_get_first_audio_pts(struct aml_dvb *dvb) -{ - unsigned long flags; - u32 pts; - - spin_lock_irqsave(&dvb->slock, flags); - pts = first_audio_pts; - spin_unlock_irqrestore(&dvb->slock, flags); - - return pts; -} - -int aml_dmx_set_skipbyte(struct aml_dvb *dvb, int skipbyte) -{ - if (demux_skipbyte != skipbyte) { - pr_dbg("set skip byte %d\n", skipbyte); - demux_skipbyte = skipbyte; - dmx_reset_hw_ex(dvb, 0); - } - - return 0; -} - -int aml_dmx_set_demux(struct aml_dvb *dvb, int id) -{ - aml_stb_hw_set_source(dvb, DMX_SOURCE_DVR0); - if (id < DMX_DEV_COUNT) { - struct aml_dmx *dmx = &dvb->dmx[id]; - - aml_dmx_hw_set_source((struct dmx_demux *)dmx, - DMX_SOURCE_DVR0); - } - - return 0; -} - -int _set_tsfile_clkdiv(struct aml_dvb *dvb, int clkdiv) -{ - if (tsfile_clkdiv != clkdiv) { - pr_dbg("set ts file clock div %d\n", clkdiv); - tsfile_clkdiv = clkdiv; - dmx_reset_hw(dvb); - } - - return 0; -} - -static ssize_t stb_set_tsfile_clkdiv(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - /*int div = (int)simple_strtol(buf, NULL, 10);*/ - long div; - - if (kstrtol(buf, 0, &div) == 0) - _set_tsfile_clkdiv(aml_get_dvb_device(), (int)div); - return size; -} - -static ssize_t stb_get_tsfile_clkdiv(struct class *class, - struct class_attribute *attr, char *buf) -{ - ssize_t ret; - - ret = sprintf(buf, "%d\n", tsfile_clkdiv); - return ret; -} - - -static int dmx_id; - -static ssize_t dmx_smallsec_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - ssize_t ret; - struct aml_dvb *dvb = aml_get_dvb_device(); - - ret = sprintf(buf, "%d:%d\n", dvb->dmx[dmx_id].smallsec.enable, - dvb->dmx[dmx_id].smallsec.bufsize); - return ret; -} -static ssize_t dmx_smallsec_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int i, e, s = 0, f = 0; - struct aml_dvb *dvb = aml_get_dvb_device(); - - i = sscanf(buf, "%d:%i:%d", &e, &s, &f); - if (i <= 0) - return size; - - dmx_smallsec_set(&dvb->dmx[dmx_id].smallsec, e, s, f); - return size; -} - -static ssize_t dmx_timeout_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - ssize_t ret; - struct aml_dvb *dvb = aml_get_dvb_device(); - - ret = sprintf(buf, "%d:%d:0x%x:%d:%d\n", - dvb->dmx[dmx_id].timeout.enable, - dvb->dmx[dmx_id].timeout.timeout, - dvb->dmx[dmx_id].timeout.ch_disable, - dvb->dmx[dmx_id].timeout.match, - (DMX_READ_REG(dmx_id, STB_INT_STATUS)&(1<dmx[dmx_id].timeout, e, t, c, m, f); - return size; -} - - -#define DEMUX_SCAMBLE_FUNC_DECL(i) \ -static ssize_t dmx_reg_value_show_demux##i##_scramble(struct class *class, \ -struct class_attribute *attr, char *buf)\ -{\ - int data = 0;\ - int aflag = 0;\ - int vflag = 0;\ - ssize_t ret = 0;\ - data = DMX_READ_REG(i, DEMUX_SCRAMBLING_STATE);\ - if ((data & 0x01) == 0x01) \ - vflag = 1;\ - if ((data & 0x02) == 0x02) \ - aflag = 1;\ - ret = sprintf(buf, "%d %d\n", vflag, aflag);\ - return ret;\ -} - -#if DMX_DEV_COUNT > 0 -DEMUX_SCAMBLE_FUNC_DECL(0) -#endif -#if DMX_DEV_COUNT > 1 -DEMUX_SCAMBLE_FUNC_DECL(1) -#endif -#if DMX_DEV_COUNT > 2 -DEMUX_SCAMBLE_FUNC_DECL(2) -#endif -static ssize_t ciplus_output_ctrl_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - int ret; - char *out = "none"; - - pr_inf("output demux use 3 bit to indicate.\n"); - pr_inf("1bit:demux0 2bit:demux1 3bit:demux2\n"); - - switch (ciplus_out_sel) { - case 1: - out = "dmx0"; - break; - case 2: - out = "dmx1"; - break; - case 4: - out = "dmx2"; - break; - default: - break; - } - - ret = sprintf(buf, "%s 0x%x %s\n", - out, - ciplus_out_sel, - (ciplus_out_auto_mode) ? "" : "(force)"); - return ret; -} - -static ssize_t ciplus_output_ctrl_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int i, tmp; - - i = kstrtoint(buf, -1, &tmp); - if (tmp > 8 || tmp < 0) - pr_error("Invalid output set\n"); - else if (tmp == 8) { - ciplus_out_auto_mode = 1; - ciplus_out_sel = -1; - pr_error("Auto set output mode enable\n"); - } else { - ciplus_out_auto_mode = 0; - ciplus_out_sel = tmp; - pr_error("Auto set output mode disable\n"); - } - return size; -} -static ssize_t reset_fec_input_ctrl_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - return 0; -} - -static ssize_t reset_fec_input_ctrl_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - u32 v; - - v = READ_MPEG_REG(FEC_INPUT_CONTROL); - v &= ~(1<<11); - WRITE_MPEG_REG(FEC_INPUT_CONTROL, v); - - pr_dbg("reset FEC_INPUT_CONTROL to %x\n", v); - - return size; -} -static ssize_t dmx_reg_addr_show_source(struct class *class, - struct class_attribute *attr, - char *buf); -static ssize_t dmx_reg_addr_store_source(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size); -static ssize_t dmx_id_show_source(struct class *class, - struct class_attribute *attr, char *buf); -static ssize_t dmx_id_store_source(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size); -static ssize_t dmx_reg_value_show_source(struct class *class, - struct class_attribute *attr, - char *buf); -static ssize_t dmx_reg_value_store_source(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size); -static ssize_t dmx_sec_statistics_show(struct class *class, - struct class_attribute *attr, - char *buf); -static int reg_addr; - -static struct class_attribute aml_dmx_class_attrs[] = { - __ATTR(dmx_id, 0644, dmx_id_show_source, - dmx_id_store_source), - __ATTR(register_addr, 0644, dmx_reg_addr_show_source, - dmx_reg_addr_store_source), - __ATTR(register_value, 0644, dmx_reg_value_show_source, - dmx_reg_value_store_source), - __ATTR(tsfile_clkdiv, 0644, stb_get_tsfile_clkdiv, - stb_set_tsfile_clkdiv), - -#define DEMUX_SCAMBLE_ATTR_DECL(i)\ - __ATTR(demux##i##_scramble, 0644, \ - dmx_reg_value_show_demux##i##_scramble, NULL) -#if DMX_DEV_COUNT > 0 - DEMUX_SCAMBLE_ATTR_DECL(0), -#endif -#if DMX_DEV_COUNT > 1 - DEMUX_SCAMBLE_ATTR_DECL(1), -#endif -#if DMX_DEV_COUNT > 2 - DEMUX_SCAMBLE_ATTR_DECL(2), -#endif - - __ATTR(dmx_smallsec, 0644, - dmx_smallsec_show, - dmx_smallsec_store), - __ATTR(dmx_timeout, 0644, - dmx_timeout_show, - dmx_timeout_store), - __ATTR(reset_fec_input_ctrl, 0644, - reset_fec_input_ctrl_show, - reset_fec_input_ctrl_store), - __ATTR(ciplus_output_ctrl, 0644, - ciplus_output_ctrl_show, - ciplus_output_ctrl_store), - __ATTR_RO(dmx_sec_statistics), - __ATTR_NULL -}; - -static struct class aml_dmx_class = { - .name = "dmx", - .class_attrs = aml_dmx_class_attrs, -}; - -static ssize_t dmx_id_show_source(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret; - - ret = sprintf(buf, "%d\n", dmx_id); - return ret; -} - -static ssize_t dmx_id_store_source(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int id = 0; - long value = 0; - - if (kstrtol(buf, 0, &value) == 0) - id = (int)value; - /*id = simple_strtol(buf, 0, 16);*/ - - if (id < 0 || id > 2) - pr_dbg("dmx id must 0 ~2\n"); - else - dmx_id = id; - - return size; -} - -static ssize_t dmx_reg_addr_show_source(struct class *class, - struct class_attribute *attr, - char *buf) -{ - int ret; - - ret = sprintf(buf, "%x\n", reg_addr); - return ret; -} - -static ssize_t dmx_reg_addr_store_source(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int addr = 0; - /*addr = simple_strtol(buf, 0, 16);*/ - long value = 0; - - if (kstrtol(buf, 0, &value) == 0) - addr = (int)value; - reg_addr = addr; - return size; -} - -static ssize_t dmx_reg_value_show_source(struct class *class, - struct class_attribute *attr, - char *buf) -{ - int ret, value; - - value = READ_MPEG_REG(reg_addr); - ret = sprintf(buf, "%x\n", value); - return ret; -} - -static ssize_t dmx_reg_value_store_source(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - int value = 0; - /*value = simple_strtol(buf, 0, 16);*/ - long val = 0; - - if (kstrtol(buf, 0, &val) == 0) - value = (int)val; - WRITE_MPEG_REG(reg_addr, value); - return size; -} - -static ssize_t dmx_sec_statistics_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - ssize_t ret; - char tmp[128]; - struct aml_dvb *dvb = aml_get_dvb_device(); - - ret = sprintf(tmp, "[hw]%#lx:%#lx:%#lx\n[sw]%#lx:%#lx:%#lx\n", - dvb->dmx[dmx_id].sec_cnt[SEC_CNT_HW], - dvb->dmx[dmx_id].sec_cnt_match[SEC_CNT_HW], - dvb->dmx[dmx_id].sec_cnt_crc_fail[SEC_CNT_HW], - dvb->dmx[dmx_id].sec_cnt[SEC_CNT_SW], - dvb->dmx[dmx_id].sec_cnt_match[SEC_CNT_SW], - dvb->dmx[dmx_id].sec_cnt_crc_fail[SEC_CNT_SW]); - ret = sprintf(buf, "%s[ss]%#lx:%#lx:%#lx\n", - tmp, - dvb->dmx[dmx_id].sec_cnt[SEC_CNT_SS], - dvb->dmx[dmx_id].sec_cnt_match[SEC_CNT_SS], - dvb->dmx[dmx_id].sec_cnt_crc_fail[SEC_CNT_SS]); - return ret; -} - -int aml_regist_dmx_class(void) -{ - - if (class_register(&aml_dmx_class) < 0) - pr_error("register class error\n"); - - return 0; -} - -int aml_unregist_dmx_class(void) -{ - - class_unregister(&aml_dmx_class); - return 0; -} - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c deleted file mode 100644 index b3ffbb7cefa6..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c +++ /dev/null @@ -1,2902 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - /* - * AMLOGIC DVB driver. - */ - -//move to define in Makefile -//#define ENABLE_DEMUX_DRIVER - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "c_stb_define.h" -#include "c_stb_regs_define.h" -#include "aml_dvb.h" -#include "aml_dvb_reg.h" - -#include "../../tv_frontend/aml_fe.h" -#include "aml_demod_gt.h" -#include "../../../common/media_clock/switch/amports_gate.h" - -typedef enum __demod_type -{ - DEMOD_INVALID, - DEMOD_INTERNAL, - DEMOD_ATBM8881, - DEMOD_SI2168, - DEMOD_MAX_NUM -}demod_type; - -typedef enum __tuner_type -{ - TUNER_INVALID, - TUNER_SI2151, - TUNER_MXL661, - TUNER_SI2159, - TUNER_R842, - TUNER_R840, - TUNER_MAX_NUM -}tuner_type; - -#define pr_dbg(args...)\ - do {\ - if (debug_dvb)\ - printk(args);\ - } while (0) -#define pr_error(fmt, args...) printk("DVB: " fmt, ## args) -#define pr_inf(fmt, args...) printk("DVB: " fmt, ## args) - -MODULE_PARM_DESC(debug_dvb, "\n\t\t Enable dvb debug information"); -static int debug_dvb = 1; -module_param(debug_dvb, int, 0644); - -#define CARD_NAME "amlogic-dvb" - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -MODULE_PARM_DESC(dsc_max, "max number of dsc"); -static int dsc_max = DSC_DEV_COUNT; -module_param(dsc_max, int, 0644); - -static struct aml_dvb aml_dvb_device; -static struct class aml_stb_class; - -static struct dvb_frontend *frontend[FE_DEV_COUNT] = {NULL, NULL}; -static demod_type s_demod_type[FE_DEV_COUNT] = {DEMOD_INVALID, DEMOD_INVALID}; -static tuner_type s_tuner_type[FE_DEV_COUNT] = {TUNER_INVALID, TUNER_INVALID}; - -#if 0 -static struct reset_control *aml_dvb_demux_reset_ctl; -static struct reset_control *aml_dvb_afifo_reset_ctl; -static struct reset_control *aml_dvb_ahbarb0_reset_ctl; -static struct reset_control *aml_dvb_uparsertop_reset_ctl; -#else -/*no used reset ctl,need use clk in 4.9 kernel*/ -static struct clk *aml_dvb_demux_clk; -static struct clk *aml_dvb_afifo_clk; -static struct clk *aml_dvb_ahbarb0_clk; -static struct clk *aml_dvb_uparsertop_clk; -#endif - -static int aml_tsdemux_reset(void); -static int aml_tsdemux_set_reset_flag(void); -static int aml_tsdemux_request_irq(irq_handler_t handler, void *data); -static int aml_tsdemux_free_irq(void); -static int aml_tsdemux_set_vid(int vpid); -static int aml_tsdemux_set_aid(int apid); -static int aml_tsdemux_set_sid(int spid); -static int aml_tsdemux_set_pcrid(int pcrpid); -static int aml_tsdemux_set_skipbyte(int skipbyte); -static int aml_tsdemux_set_demux(int id); - -static struct tsdemux_ops aml_tsdemux_ops = { - .reset = aml_tsdemux_reset, - .set_reset_flag = aml_tsdemux_set_reset_flag, - .request_irq = aml_tsdemux_request_irq, - .free_irq = aml_tsdemux_free_irq, - .set_vid = aml_tsdemux_set_vid, - .set_aid = aml_tsdemux_set_aid, - .set_sid = aml_tsdemux_set_sid, - .set_pcrid = aml_tsdemux_set_pcrid, - .set_skipbyte = aml_tsdemux_set_skipbyte, - .set_demux = aml_tsdemux_set_demux -}; - -static int dvb_attach_tuner(struct dvb_frontend *fe, struct aml_tuner *tuner, tuner_type *type) -{ - struct tuner_config *cfg = &tuner->cfg; - struct i2c_adapter *i2c_adap = tuner->i2c_adp; - - switch (cfg->id) { - case AM_TUNER_R840: - if (!dvb_attach(r840_attach, fe, i2c_adap, cfg)) { - pr_error("dvb attach r840_attach tuner error\n"); - return -1; - } else { - pr_inf("r840_attach attach sucess\n"); - *type = TUNER_R840; - } - break; - case AM_TUNER_R842: - if (!dvb_attach(r842_attach, fe, i2c_adap, cfg)) { - pr_error("dvb attach r842_attach tuner error\n"); - return -1; - } else { - pr_inf("r842_attach attach sucess\n"); - *type = TUNER_R842; - } - break; - case AM_TUNER_SI2151: - if (!dvb_attach(si2151_attach, fe, i2c_adap, cfg)) { - pr_error("dvb attach tuner error\n"); - return -1; - } else { - pr_inf("si2151 attach sucess\n"); - *type = TUNER_SI2151; - } - break; - case AM_TUNER_SI2159: - if (!dvb_attach(si2159_attach, fe, i2c_adap, cfg)) { - pr_error("dvb attach si2159_attach tuner error\n"); - return -1; - } else { - pr_inf("si2159_attach attach sucess\n"); - *type = TUNER_SI2159; - } - break; - case AM_TUNER_MXL661: - if (!dvb_attach(mxl661_attach, fe, i2c_adap, cfg)) { - pr_error("dvb attach mxl661_attach tuner error\n"); - return -1; - } else { - pr_inf("mxl661_attach attach sucess\n"); - *type = TUNER_MXL661; - } - break; - default: - pr_error("can't support tuner type: %d\n", cfg->id); - break; - } - - return 0; -} - -long aml_stb_get_base(int id) -{ - int newbase = 0; - if (MESON_CPU_MAJOR_ID_TXL < get_cpu_type() - && MESON_CPU_MAJOR_ID_GXLX != get_cpu_type()) { - newbase = 1; - } - - switch (id) { - case ID_STB_CBUS_BASE: - return (newbase) ? 0x1800 : 0x1600; - case ID_SMARTCARD_REG_BASE: - return (newbase) ? 0x9400 : 0x2110; - case ID_ASYNC_FIFO_REG_BASE: - return (newbase) ? 0x2800 : 0x2310; - case ID_ASYNC_FIFO1_REG_BASE: - return 0x9800; - case ID_ASYNC_FIFO2_REG_BASE: - return (newbase) ? 0x2400 : 0x2314; - case ID_RESET_BASE: - return (newbase) ? 0x0400 : 0x1100; - case ID_PARSER_SUB_START_PTR_BASE: - return (newbase) ? 0x3800 : 0x2900; - default: - return 0; - } - return 0; -} -static void aml_dvb_dmx_release(struct aml_dvb *advb, struct aml_dmx *dmx) -{ - int i; - - dvb_net_release(&dmx->dvb_net); - aml_dmx_hw_deinit(dmx); - dmx->demux.dmx.close(&dmx->demux.dmx); - dmx->demux.dmx.remove_frontend(&dmx->demux.dmx, &dmx->mem_fe); - - for (i = 0; i < DMX_DEV_COUNT; i++) - dmx->demux.dmx.remove_frontend(&dmx->demux.dmx, &dmx->hw_fe[i]); - - dvb_dmxdev_release(&dmx->dmxdev); - dvb_dmx_release(&dmx->demux); -} - -static int aml_dvb_dmx_init(struct aml_dvb *advb, struct aml_dmx *dmx, int id) -{ - int i, ret; - - struct resource *res; - char buf[32]; - - switch (id) { - case 0: - dmx->dmx_irq = INT_DEMUX; - break; - case 1: - dmx->dmx_irq = INT_DEMUX_1; - break; - case 2: - dmx->dmx_irq = INT_DEMUX_2; - break; - } - - snprintf(buf, sizeof(buf), "demux%d_irq", id); - res = platform_get_resource_byname(advb->pdev, IORESOURCE_IRQ, buf); - if (res) - dmx->dmx_irq = res->start; - - printk("%s irq num:%d \r\n", buf, dmx->dmx_irq); - - dmx->source = -1; - dmx->dump_ts_select = 0; - dmx->dvr_irq = -1; - - dmx->demux.dmx.capabilities = - (DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING); - dmx->demux.filternum = dmx->demux.feednum = FILTER_COUNT; - dmx->demux.priv = advb; - dmx->demux.start_feed = aml_dmx_hw_start_feed; - dmx->demux.stop_feed = aml_dmx_hw_stop_feed; - dmx->demux.write_to_decoder = NULL; - ret = dvb_dmx_init(&dmx->demux); - if (ret < 0) { - pr_error("dvb_dmx failed: error %d\n", ret); - goto error_dmx_init; - } - - dmx->dmxdev.filternum = dmx->demux.feednum; - dmx->dmxdev.demux = &dmx->demux.dmx; - dmx->dmxdev.capabilities = 0; - ret = dvb_dmxdev_init(&dmx->dmxdev, &advb->dvb_adapter); - if (ret < 0) { - pr_error("dvb_dmxdev_init failed: error %d\n", ret); - goto error_dmxdev_init; - } - - for (i = 0; i < DMX_DEV_COUNT; i++) { - int source = i + DMX_FRONTEND_0; - - dmx->hw_fe[i].source = source; - ret = - dmx->demux.dmx.add_frontend(&dmx->demux.dmx, - &dmx->hw_fe[i]); - if (ret < 0) { - pr_error("adding hw_frontend to dmx failed: error %d", - ret); - dmx->hw_fe[i].source = 0; - goto error_add_hw_fe; - } - } - - dmx->mem_fe.source = DMX_MEMORY_FE; - ret = dmx->demux.dmx.add_frontend(&dmx->demux.dmx, &dmx->mem_fe); - if (ret < 0) { - pr_error("adding mem_frontend to dmx failed: error %d", ret); - goto error_add_mem_fe; - } - ret = dmx->demux.dmx.connect_frontend(&dmx->demux.dmx, &dmx->hw_fe[1]); - if (ret < 0) { - pr_error("connect frontend failed: error %d", ret); - goto error_connect_fe; - } - - dmx->id = id; - dmx->aud_chan = -1; - dmx->vid_chan = -1; - dmx->sub_chan = -1; - dmx->pcr_chan = -1; - - /*smallsec*/ - dmx->smallsec.enable = 0; - dmx->smallsec.bufsize = SS_BUFSIZE_DEF; - dmx->smallsec.dmx = dmx; - - /*input timeout*/ - dmx->timeout.enable = 1; - dmx->timeout.timeout = DTO_TIMEOUT_DEF; - dmx->timeout.ch_disable = DTO_CHDIS_VAS; - dmx->timeout.match = 1; - dmx->timeout.trigger = 0; - dmx->timeout.dmx = dmx; - - /*CRC monitor*/ - dmx->crc_check_count = 0; - dmx->crc_check_time = 0; - - ret = aml_dmx_hw_init(dmx); - if (ret < 0) { - pr_error("demux hw init error %d", ret); - dmx->id = -1; - goto error_dmx_hw_init; - } - - dvb_net_init(&advb->dvb_adapter, &dmx->dvb_net, &dmx->demux.dmx); - - return 0; -error_dmx_hw_init: -error_connect_fe: - dmx->demux.dmx.remove_frontend(&dmx->demux.dmx, &dmx->mem_fe); -error_add_mem_fe: -error_add_hw_fe: - for (i = 0; i < DMX_DEV_COUNT; i++) { - if (dmx->hw_fe[i].source) - dmx->demux.dmx.remove_frontend(&dmx->demux.dmx, - &dmx->hw_fe[i]); - } - dvb_dmxdev_release(&dmx->dmxdev); -error_dmxdev_init: - dvb_dmx_release(&dmx->demux); -error_dmx_init: - return ret; -} - -struct aml_dvb *aml_get_dvb_device(void) -{ - return &aml_dvb_device; -} -EXPORT_SYMBOL(aml_get_dvb_device); - -static int dvb_dsc_open(struct inode *inode, struct file *file) -{ - int err; - - err = dvb_generic_open(inode, file); - if (err < 0) - return err; - - return 0; -} - -static void dsc_channel_alloc(struct aml_dsc *dsc, int id, unsigned int pid) -{ - struct aml_dsc_channel *ch = &dsc->channel[id]; - - ch->used = 1; - ch->work_mode = -1; - ch->id = id; - ch->pid = pid; - ch->set = 0; - ch->dsc = dsc; - ch->mode = -1; - - dsc_set_pid(ch, ch->pid); -} - -static void dsc_channel_free(struct aml_dsc_channel *ch) -{ - if (!ch->used) - return; - - ch->used = 0; - dsc_set_pid(ch, 0x1fff); - dsc_release(); - - ch->pid = 0x1fff; - ch->set = 0; - ch->work_mode = -1; - ch->mode = -1; -} - -static void dsc_reset(struct aml_dsc *dsc) -{ - int i; - - for (i = 0; i < DSC_COUNT; i++) - dsc_channel_free(&dsc->channel[i]); -} - -static int get_dsc_key_work_mode(enum ca_cw_type cw_type) -{ - int work_mode = DVBCSA_MODE; - - switch (cw_type) { - case CA_CW_DVB_CSA_EVEN: - case CA_CW_DVB_CSA_ODD: - work_mode = DVBCSA_MODE; - break; - case CA_CW_AES_EVEN: - case CA_CW_AES_ODD: - case CA_CW_AES_ODD_IV: - case CA_CW_AES_EVEN_IV: - case CA_CW_DES_EVEN: - case CA_CW_DES_ODD: - case CA_CW_SM4_EVEN: - case CA_CW_SM4_ODD: - case CA_CW_SM4_ODD_IV: - case CA_CW_SM4_EVEN_IV: - work_mode = CIPLUS_MODE; - default: - break; - } - return work_mode; -} - -/* Check if there are channels run in previous mode(aes/dvbcsa) - * in dsc0/ciplus - */ -static void dsc_ciplus_switch_check(struct aml_dsc_channel *ch, - enum ca_cw_type cw_type) -{ - struct aml_dsc *dsc = ch->dsc; - int work_mode = 0; - struct aml_dsc_channel *pch = NULL; - int i; - - work_mode = get_dsc_key_work_mode(cw_type); - if (dsc->work_mode == work_mode) - return; - - dsc->work_mode = work_mode; - - for (i = 0; i < DSC_COUNT; i++) { - pch = &dsc->channel[i]; - if (pch->work_mode != work_mode && pch->work_mode != -1) { - pr_error("Dsc work mode changed,"); - pr_error("but there are still some channels"); - pr_error("run in different mode\n"); - pr_error("mod_pre[%d] -> mod[%d] ch[%d]\n", - pch->work_mode, work_mode, i); - } - } -} - -static int dsc_set_cw(struct aml_dsc *dsc, struct ca_descr_ex *d) -{ - struct aml_dsc_channel *ch; - - if (d->index >= DSC_COUNT) - return -EINVAL; - - ch = &dsc->channel[d->index]; - - switch (d->type) { - case CA_CW_DVB_CSA_EVEN: - case CA_CW_AES_EVEN: - case CA_CW_DES_EVEN: - case CA_CW_SM4_EVEN: - memcpy(ch->even, d->cw, DSC_KEY_SIZE_MAX); - break; - case CA_CW_DVB_CSA_ODD: - case CA_CW_AES_ODD: - case CA_CW_DES_ODD: - case CA_CW_SM4_ODD: - memcpy(ch->odd, d->cw, DSC_KEY_SIZE_MAX); - break; - case CA_CW_AES_EVEN_IV: - case CA_CW_SM4_EVEN_IV: - memcpy(ch->even_iv, d->cw, DSC_KEY_SIZE_MAX); - break; - case CA_CW_AES_ODD_IV: - case CA_CW_SM4_ODD_IV: - memcpy(ch->odd_iv, d->cw, DSC_KEY_SIZE_MAX); - break; - default: - break; - } - - ch->set |= (1 << d->type) | (d->flags << 24); - - if (d->mode == CA_DSC_IDSA) { - ch->mode = IDSA_MODE; - } - - /*do key set*/ - dsc_set_key(ch, d->flags, d->type, d->cw); - dsc_ciplus_switch_check(ch, d->type); - - return 0; -} - -static int dvb_dsc_do_ioctl(struct file *file, unsigned int cmd, - void *parg) -{ - struct dvb_device *dvbdev = file->private_data; - struct aml_dsc *dsc = dvbdev->priv; - struct aml_dvb *dvb = dsc->dvb; - struct aml_dsc_channel *ch; - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - - switch (cmd) { - case CA_RESET: - dsc_reset(dsc); - break; - case CA_GET_CAP: { - ca_caps_t *cap = parg; - - cap->slot_num = 1; - cap->slot_type = CA_DESCR; - cap->descr_num = DSC_COUNT; - cap->descr_type = 0; - break; - } - case CA_GET_SLOT_INFO: { - ca_slot_info_t *slot = parg; - - slot->num = 1; - slot->type = CA_DESCR; - slot->flags = 0; - break; - } - case CA_GET_DESCR_INFO: { - ca_descr_info_t *descr = parg; - - descr->num = DSC_COUNT; - descr->type = 0; - break; - } - case CA_SET_DESCR: { - ca_descr_t *d = parg; - struct ca_descr_ex dex; - - dex.index = d->index; - dex.type = d->parity ? CA_CW_DVB_CSA_ODD : CA_CW_DVB_CSA_EVEN; - dex.mode = -1; - dex.flags = 0; - memcpy(dex.cw, d->cw, sizeof(d->cw)); - - ret = dsc_set_cw(dsc, &dex); - break; - } - case CA_SET_PID: { - ca_pid_t *pi = parg; - int i; - - if (pi->index == -1) { - for (i = 0; i < DSC_COUNT; i++) { - ch = &dsc->channel[i]; - - if (ch->used && (ch->pid == pi->pid)) { - dsc_channel_free(ch); - break; - } - } - } else if ((pi->index >= 0) && (pi->index < DSC_COUNT)) { - ch = &dsc->channel[pi->index]; - - if (pi->pid < 0x1fff) { - if (!ch->used) { - dsc_channel_alloc(dsc, - pi->index, pi->pid); - } - } else { - if (ch->used) - dsc_channel_free(ch); - } - } else { - ret = -EINVAL; - } - break; - } - case CA_SET_DESCR_EX: { - struct ca_descr_ex *d = parg; - - ret = dsc_set_cw(dsc, d); - break; - } - default: - ret = -EINVAL; - break; - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -static int dvb_dsc_usercopy(struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - /* - * For this command, the pointer is actually an integer - * argument. - */ - parg = (void *) arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (mbuf == NULL) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - err = func(file, cmd, parg); - if (err == -ENOIOCTLCMD) - err = -ENOTTY; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - kfree(mbuf); - return err; -} - -static long dvb_dsc_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return dvb_dsc_usercopy(file, cmd, arg, dvb_dsc_do_ioctl); -} - -static int dvb_dsc_release(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct aml_dsc *dsc = dvbdev->priv; - struct aml_dvb *dvb = dsc->dvb; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - - dsc_reset(dsc); - - spin_unlock_irqrestore(&dvb->slock, flags); - - dvb_generic_release(inode, file); - - return 0; -} - -#ifdef CONFIG_COMPAT -static long dvb_dsc_compat_ioctl(struct file *filp, - unsigned int cmd, unsigned long args) -{ - unsigned long ret; - - args = (unsigned long)compat_ptr(args); - ret = dvb_dsc_ioctl(filp, cmd, args); - return ret; -} -#endif - - -static const struct file_operations dvb_dsc_fops = { - .owner = THIS_MODULE, - .read = NULL, - .write = NULL, - .unlocked_ioctl = dvb_dsc_ioctl, - .open = dvb_dsc_open, - .release = dvb_dsc_release, - .poll = NULL, -#ifdef CONFIG_COMPAT - .compat_ioctl = dvb_dsc_compat_ioctl, -#endif -}; - -static struct dvb_device dvbdev_dsc = { - .priv = NULL, - .users = 1, - .readers = 1, - .writers = 1, - .fops = &dvb_dsc_fops, -}; - -static int aml_dvb_asyncfifo_init(struct aml_dvb *advb, - struct aml_asyncfifo *asyncfifo, int id) -{ - struct resource *res; - char buf[32]; - - if (id == 0) - asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO_FLUSH; - else if(id == 2) - asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO3_FLUSH; - else - asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO2_FLUSH; - - snprintf(buf, sizeof(buf), "dvr%d_irq", id); - res = platform_get_resource_byname(advb->pdev, IORESOURCE_IRQ, buf); - if (res) - asyncfifo->asyncfifo_irq = res->start; - pr_info("%s irq num:%d ", buf, asyncfifo->asyncfifo_irq); - asyncfifo->dvb = advb; - asyncfifo->id = id; - asyncfifo->init = 0; - asyncfifo->flush_size = 256 * 1024; - asyncfifo->secure_enable = 0; - asyncfifo->blk.addr = 0; - asyncfifo->blk.len = 0; - - return aml_asyncfifo_hw_init(asyncfifo); -} -static void aml_dvb_asyncfifo_release(struct aml_dvb *advb, - struct aml_asyncfifo *asyncfifo) -{ - aml_asyncfifo_hw_deinit(asyncfifo); -} - -static int aml_dvb_dsc_init(struct aml_dvb *advb, - struct aml_dsc *dsc, int id) -{ - int i; - - for (i = 0; i < DSC_COUNT; i++) { - dsc->channel[i].id = i; - dsc->channel[i].used = 0; - dsc->channel[i].set = 0; - dsc->channel[i].pid = 0x1fff; - dsc->channel[i].dsc = dsc; - } - dsc->dvb = advb; - dsc->id = id; - dsc->source = -1; - dsc->dst = -1; - - /*Register descrambler device */ - return dvb_register_device(&advb->dvb_adapter, &dsc->dev, - &dvbdev_dsc, dsc, DVB_DEVICE_CA, 0); -} -static void aml_dvb_dsc_release(struct aml_dvb *advb, - struct aml_dsc *dsc) -{ - if (dsc->dev) - dvb_unregister_device(dsc->dev); - dsc->dev = NULL; -} - - -/*Show the STB input source*/ -static ssize_t stb_show_source(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - char *src; - - switch (dvb->stb_source) { - case AM_TS_SRC_TS0: - case AM_TS_SRC_S_TS0: - src = "ts0"; - break; - case AM_TS_SRC_TS1: - case AM_TS_SRC_S_TS1: - src = "ts1"; - break; - case AM_TS_SRC_TS2: - case AM_TS_SRC_S_TS2: - src = "ts2"; - break; - case AM_TS_SRC_TS3: - src = "ts3"; - break; - case AM_TS_SRC_HIU: - src = "hiu"; - break; - case AM_TS_SRC_HIU1: - src = "hiu1"; - break; - case AM_TS_SRC_DMX0: - src = "dmx0"; - break; - case AM_TS_SRC_DMX1: - src = "dmx1"; - break; - case AM_TS_SRC_DMX2: - src = "dmx2"; - break; - default: - src = "disable"; - break; - } - - ret = sprintf(buf, "%s\n", src); - return ret; -} - -static ssize_t stb_clear_av(struct class *class, - struct class_attribute *attr, const char *buf, - size_t size) -{ - if (!strncmp("1", buf, 1)) { - aml_tsdemux_set_vid(0x1fff); - aml_tsdemux_set_aid(0x1fff); - aml_tsdemux_set_sid(0x1fff); - aml_tsdemux_set_pcrid(0x1fff); - } - - return size; -} - -/*Set the STB input source*/ -static ssize_t stb_store_source(struct class *class, - struct class_attribute *attr, const char *buf, - size_t size) -{ - dmx_source_t src = -1; - - if (!strncmp("ts0", buf, 3)) - src = DMX_SOURCE_FRONT0; - else if (!strncmp("ts1", buf, 3)) - src = DMX_SOURCE_FRONT1; - else if (!strncmp("ts2", buf, 3)) - src = DMX_SOURCE_FRONT2; - else if (!strncmp("ts3", buf, 3)) - src = DMX_SOURCE_FRONT3; - else if (!strncmp("hiu1", buf, 4)) - src = DMX_SOURCE_DVR1; - else if (!strncmp("hiu", buf, 3)) - src = DMX_SOURCE_DVR0; - else if (!strncmp("dmx0", buf, 4)) - src = DMX_SOURCE_FRONT0 + 100; - else if (!strncmp("dmx1", buf, 4)) - src = DMX_SOURCE_FRONT1 + 100; - else if (!strncmp("dmx2", buf, 4)) - src = DMX_SOURCE_FRONT2 + 100; - if (src != -1) - aml_stb_hw_set_source(&aml_dvb_device, src); - - return size; -} - -#define CASE_PREFIX - -/*Show the descrambler's input source*/ -#define DSC_SOURCE_FUNC_DECL(i) \ -static ssize_t dsc##i##_show_source(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_dsc *dsc = &dvb->dsc[i];\ - ssize_t ret = 0;\ - char *src, *dst;\ - switch (dsc->source) {\ - CASE_PREFIX case AM_TS_SRC_DMX0:\ - src = "dmx0";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX1:\ - src = "dmx1";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX2:\ - src = "dmx2";\ - break;\ - CASE_PREFIX default :\ - src = "bypass";\ - break;\ - } \ - switch (dsc->dst) {\ - CASE_PREFIX case AM_TS_SRC_DMX0:\ - dst = "dmx0";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX1:\ - dst = "dmx1";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX2:\ - dst = "dmx2";\ - break;\ - CASE_PREFIX default :\ - dst = "bypass";\ - break;\ - } \ - ret = sprintf(buf, "%s-%s\n", src, dst);\ - return ret;\ -} \ -static ssize_t dsc##i##_store_source(struct class *class, \ - struct class_attribute *attr, const char *buf, size_t size)\ -{\ - dmx_source_t src = -1, dst = -1;\ - \ - if (!strncmp("dmx0", buf, 4)) {\ - src = DMX_SOURCE_FRONT0 + 100;\ - } else if (!strncmp("dmx1", buf, 4)) {\ - src = DMX_SOURCE_FRONT1 + 100;\ - } else if (!strncmp("dmx2", buf, 4)) {\ - src = DMX_SOURCE_FRONT2 + 100;\ - } \ - if (buf[4] == '-') {\ - if (!strncmp("dmx0", buf+5, 4)) {\ - dst = DMX_SOURCE_FRONT0 + 100;\ - } else if (!strncmp("dmx1", buf+5, 4)) {\ - dst = DMX_SOURCE_FRONT1 + 100;\ - } else if (!strncmp("dmx2", buf+5, 4)) {\ - dst = DMX_SOURCE_FRONT2 + 100;\ - } \ - } \ - else \ - dst = src; \ - aml_dsc_hw_set_source(&aml_dvb_device.dsc[i], src, dst);\ - return size;\ -} - -/*Show free descramblers count*/ -#define DSC_FREE_FUNC_DECL(i) \ -static ssize_t dsc##i##_show_free_dscs(struct class *class, \ - struct class_attribute *attr, char *buf) \ -{ \ - struct aml_dvb *dvb = &aml_dvb_device; \ - int fid, count; \ - ssize_t ret = 0; \ - unsigned long flags;\ -\ - spin_lock_irqsave(&dvb->slock, flags); \ - count = 0; \ - for (fid = 0; fid < DSC_COUNT; fid++) { \ - if (!dvb->dsc[i].channel[fid].used) \ - count++; \ - } \ - spin_unlock_irqrestore(&dvb->slock, flags); \ -\ - ret = sprintf(buf, "%d\n", count); \ - return ret; \ -} - -#if DSC_DEV_COUNT > 0 - DSC_SOURCE_FUNC_DECL(0) - DSC_FREE_FUNC_DECL(0) -#endif -#if DSC_DEV_COUNT > 1 - DSC_SOURCE_FUNC_DECL(1) - DSC_FREE_FUNC_DECL(1) -#endif - -/*Show the TS output source*/ -static ssize_t tso_show_source(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - char *src; - - switch (dvb->tso_source) { - case AM_TS_SRC_TS0: - case AM_TS_SRC_S_TS0: - src = "ts0"; - break; - case AM_TS_SRC_TS1: - case AM_TS_SRC_S_TS1: - src = "ts1"; - break; - case AM_TS_SRC_TS2: - case AM_TS_SRC_S_TS2: - src = "ts2"; - break; - case AM_TS_SRC_TS3: - src = "ts3"; - break; - case AM_TS_SRC_HIU: - src = "hiu"; - break; - case AM_TS_SRC_DMX0: - src = "dmx0"; - break; - case AM_TS_SRC_DMX1: - src = "dmx1"; - break; - case AM_TS_SRC_DMX2: - src = "dmx2"; - break; - default: - src = "default"; - break; - } - - ret = sprintf(buf, "%s\n", src); - return ret; -} - -/*Set the TS output source*/ -static ssize_t tso_store_source(struct class *class, - struct class_attribute *attr, const char *buf, - size_t size) -{ - dmx_source_t src = -1; - - if (!strncmp("ts0", buf, 3)) - src = DMX_SOURCE_FRONT0; - else if (!strncmp("ts1", buf, 3)) - src = DMX_SOURCE_FRONT1; - else if (!strncmp("ts2", buf, 3)) - src = DMX_SOURCE_FRONT2; - else if (!strncmp("ts3", buf, 3)) - src = DMX_SOURCE_FRONT3; - else if (!strncmp("hiu", buf, 3)) - src = DMX_SOURCE_DVR0; - else if (!strncmp("dmx0", buf, 4)) - src = DMX_SOURCE_FRONT0 + 100; - else if (!strncmp("dmx1", buf, 4)) - src = DMX_SOURCE_FRONT1 + 100; - else if (!strncmp("dmx2", buf, 4)) - src = DMX_SOURCE_FRONT2 + 100; - - aml_tso_hw_set_source(&aml_dvb_device, src); - - return size; -} - -/*Show PCR*/ -#define DEMUX_PCR_FUNC_DECL(i) \ -static ssize_t demux##i##_show_pcr(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - int f = 0;\ - if (i == 0)\ - f = READ_MPEG_REG(PCR_DEMUX);\ - else if (i == 1)\ - f = READ_MPEG_REG(PCR_DEMUX_2);\ - else if (i == 2)\ - f = READ_MPEG_REG(PCR_DEMUX_3);\ - return sprintf(buf, "%08x\n", f);\ -} - -/*Show the STB input source*/ -#define DEMUX_SOURCE_FUNC_DECL(i) \ -static ssize_t demux##i##_show_source(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_dmx *dmx = &dvb->dmx[i];\ - ssize_t ret = 0;\ - char *src;\ - switch (dmx->source) {\ - CASE_PREFIX case AM_TS_SRC_TS0:\ - CASE_PREFIX case AM_TS_SRC_S_TS0:\ - src = "ts0";\ - break;\ - CASE_PREFIX case AM_TS_SRC_TS1:\ - CASE_PREFIX case AM_TS_SRC_S_TS1:\ - src = "ts1";\ - break;\ - CASE_PREFIX case AM_TS_SRC_TS2:\ - CASE_PREFIX case AM_TS_SRC_S_TS2:\ - src = "ts2";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX0:\ - src = "dmx0";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX1:\ - src = "dmx1";\ - break;\ - CASE_PREFIX case AM_TS_SRC_DMX2:\ - src = "dmx2";\ - break;\ - CASE_PREFIX case AM_TS_SRC_HIU:\ - src = "hiu";\ - break;\ - CASE_PREFIX case AM_TS_SRC_HIU1:\ - src = "hiu1";\ - break;\ - CASE_PREFIX default :\ - src = "";\ - break;\ - } \ - ret = sprintf(buf, "%s\n", src);\ - return ret;\ -} \ -static ssize_t demux##i##_store_source(struct class *class, \ - struct class_attribute *attr, const char *buf, size_t size)\ -{\ - dmx_source_t src = -1;\ - \ - if (!strncmp("ts0", buf, 3)) {\ - src = DMX_SOURCE_FRONT0;\ - } else if (!strncmp("ts1", buf, 3)) {\ - src = DMX_SOURCE_FRONT1;\ - } else if (!strncmp("ts2", buf, 3)) {\ - src = DMX_SOURCE_FRONT2;\ - } else if (!strncmp("hiu1", buf, 4)) {\ - src = DMX_SOURCE_DVR1;\ - } else if (!strncmp("hiu", buf, 3)) {\ - src = DMX_SOURCE_DVR0;\ - } else if (!strncmp("dmx0", buf, 4)) {\ - src = DMX_SOURCE_FRONT0_OFFSET;\ - } else if (!strncmp("dmx1", buf, 4)) {\ - src = DMX_SOURCE_FRONT1_OFFSET;\ - } else if (!strncmp("dmx2", buf, 4)) {\ - src = DMX_SOURCE_FRONT2_OFFSET;\ - } \ - if (src != -1) {\ - aml_dmx_hw_set_source(aml_dvb_device.dmx[i].dmxdev.demux, src);\ - } \ - return size;\ -} - -/*Show free filters count*/ -#define DEMUX_FREE_FILTERS_FUNC_DECL(i) \ -static ssize_t demux##i##_show_free_filters(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct dvb_demux *dmx = &dvb->dmx[i].demux;\ - int fid, count;\ - ssize_t ret = 0;\ - if (mutex_lock_interruptible(&dmx->mutex)) \ - return -ERESTARTSYS; \ - count = 0;\ - for (fid = 0; fid < dmx->filternum; fid++) {\ - if (!dmx->filter[fid].state != DMX_STATE_FREE)\ - count++;\ - } \ - mutex_unlock(&dmx->mutex);\ - ret = sprintf(buf, "%d\n", count);\ - return ret;\ -} - -/*Show filter users count*/ -#define DEMUX_FILTER_USERS_FUNC_DECL(i) \ -static ssize_t demux##i##_show_filter_users(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_dmx *dmx = &dvb->dmx[i];\ - int dmxdevfid, count;\ - ssize_t ret = 0;\ - unsigned long flags;\ - spin_lock_irqsave(&dvb->slock, flags);\ - count = 0;\ - for (dmxdevfid = 0; dmxdevfid < dmx->dmxdev.filternum; dmxdevfid++) {\ - if (dmx->dmxdev.filter[dmxdevfid].state >= \ - DMXDEV_STATE_ALLOCATED)\ - count++;\ - } \ - if (count > dmx->demux_filter_user) {\ - count = dmx->demux_filter_user;\ - } else{\ - dmx->demux_filter_user = count;\ - } \ - spin_unlock_irqrestore(&dvb->slock, flags);\ - ret = sprintf(buf, "%d\n", count);\ - return ret;\ -} \ -static ssize_t demux##i##_store_filter_used(struct class *class, \ - struct class_attribute *attr, const char *buf, size_t size)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_dmx *dmx = &dvb->dmx[i];\ - unsigned long filter_used;\ - unsigned long flags;/*char *endp;*/\ - /*filter_used = simple_strtol(buf, &endp, 0);*/\ - int ret = kstrtol(buf, 0, &filter_used);\ - spin_lock_irqsave(&dvb->slock, flags);\ - if (ret == 0 && filter_used) {\ - if (dmx->demux_filter_user < FILTER_COUNT)\ - dmx->demux_filter_user++;\ - } else {\ - if (dmx->demux_filter_user > 0)\ - dmx->demux_filter_user--;\ - } \ - spin_unlock_irqrestore(&dvb->slock, flags);\ - return size;\ -} - -/*Show ts header*/ -#define DEMUX_TS_HEADER_FUNC_DECL(i) \ -static ssize_t demux##i##_show_ts_header(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - int hdr = 0;\ - if (i == 0)\ - hdr = READ_MPEG_REG(TS_HEAD_1);\ - else if (i == 1)\ - hdr = READ_MPEG_REG(TS_HEAD_1_2);\ - else if (i == 2)\ - hdr = READ_MPEG_REG(TS_HEAD_1_3);\ - return sprintf(buf, "%08x\n", hdr);\ -} - -/*Show channel activity*/ -#define DEMUX_CHANNEL_ACTIVITY_FUNC_DECL(i) \ -static ssize_t demux##i##_show_channel_activity(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - int f = 0;\ - if (i == 0)\ - f = READ_MPEG_REG(DEMUX_CHANNEL_ACTIVITY);\ - else if (i == 1)\ - f = READ_MPEG_REG(DEMUX_CHANNEL_ACTIVITY_2);\ - else if (i == 2)\ - f = READ_MPEG_REG(DEMUX_CHANNEL_ACTIVITY_3);\ - return sprintf(buf, "%08x\n", f);\ -} - -#define DEMUX_RESET_FUNC_DECL(i) \ -static ssize_t demux##i##_reset_store(struct class *class, \ - struct class_attribute *attr, \ - const char *buf, size_t size)\ -{\ - if (!strncmp("1", buf, 1)) { \ - struct aml_dvb *dvb = &aml_dvb_device; \ - pr_info("Reset demux["#i"], call dmx_reset_dmx_hw\n"); \ - dmx_reset_dmx_id_hw_ex(dvb, i, 0); \ - } \ - return size; \ -} - -/*DVR record mode*/ -#define DVR_MODE_FUNC_DECL(i) \ -static ssize_t dvr##i##_show_mode(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_dmx *dmx = &dvb->dmx[i];\ - ssize_t ret = 0;\ - char *mode;\ - if (dmx->dump_ts_select) {\ - mode = "ts";\ - } else {\ - mode = "pid";\ - } \ - ret = sprintf(buf, "%s\n", mode);\ - return ret;\ -} \ -static ssize_t dvr##i##_store_mode(struct class *class, \ - struct class_attribute *attr, const char *buf, size_t size)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_dmx *dmx = &dvb->dmx[i];\ - int dump_ts_select = -1;\ - \ - if (!strncmp("pid", buf, 3) && dmx->dump_ts_select) {\ - dump_ts_select = 0;\ - } else if (!strncmp("ts", buf, 2) && !dmx->dump_ts_select) {\ - dump_ts_select = 1;\ - } \ - if (dump_ts_select != -1) {\ - aml_dmx_hw_set_dump_ts_select(\ - aml_dvb_device.dmx[i].dmxdev.demux, dump_ts_select);\ - } \ - return size;\ -} - -#if DMX_DEV_COUNT > 0 - DEMUX_PCR_FUNC_DECL(0) - DEMUX_SOURCE_FUNC_DECL(0) - DEMUX_FREE_FILTERS_FUNC_DECL(0) - DEMUX_FILTER_USERS_FUNC_DECL(0) - DVR_MODE_FUNC_DECL(0) - DEMUX_TS_HEADER_FUNC_DECL(0) - DEMUX_CHANNEL_ACTIVITY_FUNC_DECL(0) - DEMUX_RESET_FUNC_DECL(0) -#endif -#if DMX_DEV_COUNT > 1 - DEMUX_PCR_FUNC_DECL(1) - DEMUX_SOURCE_FUNC_DECL(1) - DEMUX_FREE_FILTERS_FUNC_DECL(1) - DEMUX_FILTER_USERS_FUNC_DECL(1) - DVR_MODE_FUNC_DECL(1) - DEMUX_TS_HEADER_FUNC_DECL(1) - DEMUX_CHANNEL_ACTIVITY_FUNC_DECL(1) - DEMUX_RESET_FUNC_DECL(1) -#endif -#if DMX_DEV_COUNT > 2 - DEMUX_PCR_FUNC_DECL(2) - DEMUX_SOURCE_FUNC_DECL(2) - DEMUX_FREE_FILTERS_FUNC_DECL(2) - DEMUX_FILTER_USERS_FUNC_DECL(2) - DVR_MODE_FUNC_DECL(2) - DEMUX_TS_HEADER_FUNC_DECL(2) - DEMUX_CHANNEL_ACTIVITY_FUNC_DECL(2) - DEMUX_RESET_FUNC_DECL(2) -#endif - -/*Show the async fifo source*/ -#define ASYNCFIFO_SOURCE_FUNC_DECL(i) \ -static ssize_t asyncfifo##i##_show_source(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - ssize_t ret = 0;\ - char *src;\ - if (dvb->async_fifo_total_count <= i)\ - return ret;\ - switch (afifo->source) {\ - CASE_PREFIX case AM_DMX_0:\ - src = "dmx0";\ - break;\ - CASE_PREFIX case AM_DMX_1:\ - src = "dmx1";\ - break; \ - CASE_PREFIX case AM_DMX_2:\ - src = "dmx2";\ - break;\ - CASE_PREFIX default :\ - src = "";\ - break;\ - } \ - ret = sprintf(buf, "%s\n", src);\ - return ret;\ -} \ -static ssize_t asyncfifo##i##_store_source(struct class *class, \ - struct class_attribute *attr, const char *buf, size_t size)\ -{\ - enum aml_dmx_id_t src = -1;\ - \ - if (aml_dvb_device.async_fifo_total_count <= i)\ - return 0;\ - if (!strncmp("dmx0", buf, 4)) {\ - src = AM_DMX_0;\ - } else if (!strncmp("dmx1", buf, 4)) {\ - src = AM_DMX_1;\ - } else if (!strncmp("dmx2", buf, 4)) {\ - src = AM_DMX_2;\ - } \ - if (src != -1) {\ - aml_asyncfifo_hw_set_source(&aml_dvb_device.asyncfifo[i], src);\ - } \ - return size;\ -} - -#if ASYNCFIFO_COUNT > 0 -ASYNCFIFO_SOURCE_FUNC_DECL(0) -#endif -#if ASYNCFIFO_COUNT > 1 - ASYNCFIFO_SOURCE_FUNC_DECL(1) -#endif - -#if ASYNCFIFO_COUNT > 2 - ASYNCFIFO_SOURCE_FUNC_DECL(2) -#endif - -/*Show the async fifo flush size*/ -#define ASYNCFIFO_FLUSHSIZE_FUNC_DECL(i) \ -static ssize_t asyncfifo##i##_show_flush_size(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - ssize_t ret = 0;\ - if (dvb->async_fifo_total_count <= i)\ - return ret;\ - ret = sprintf(buf, "%d\n", afifo->flush_size);\ - return ret;\ -} \ -static ssize_t asyncfifo##i##_store_flush_size(struct class *class, \ - struct class_attribute *attr, \ - const char *buf, size_t size)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - /*int fsize = simple_strtol(buf, NULL, 10);*/\ - int fsize = 0;\ - long value;\ - int ret =0;\ - if (dvb->async_fifo_total_count <= i)\ - return (size_t)0;\ - ret = kstrtol(buf, 0, &value);\ - if (ret == 0)\ - fsize = value;\ - if (fsize != afifo->flush_size) {\ - afifo->flush_size = fsize;\ - aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ - } \ - return size;\ -} - -#if ASYNCFIFO_COUNT > 0 -ASYNCFIFO_FLUSHSIZE_FUNC_DECL(0) -#endif - -#if ASYNCFIFO_COUNT > 1 - ASYNCFIFO_FLUSHSIZE_FUNC_DECL(1) -#endif - -#if ASYNCFIFO_COUNT > 2 - ASYNCFIFO_FLUSHSIZE_FUNC_DECL(2) -#endif - -/*Show the async fifo secure buffer addr*/ -#define ASYNCFIFO_SECUREADDR_FUNC_DECL(i) \ -static ssize_t asyncfifo##i##_show_secure_addr(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - ssize_t ret = 0;\ - if (dvb->async_fifo_total_count <= i)\ - return ret;\ - ret = sprintf(buf, "0x%x\n", afifo->blk.addr);\ - return ret;\ -} \ -static ssize_t asyncfifo##i##_store_secure_addr(struct class *class, \ - struct class_attribute *attr, \ -const char *buf, size_t size)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - unsigned long value;\ - int ret=0;\ - if (dvb->async_fifo_total_count <= i)\ - return (size_t)0;\ - ret = kstrtol(buf, 0, &value);\ - if (ret == 0 && value != afifo->blk.addr) {\ - afifo->blk.addr = value;\ - aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ - } \ - return size;\ -} - -#if ASYNCFIFO_COUNT > 0 - ASYNCFIFO_SECUREADDR_FUNC_DECL(0) -#endif - -#if ASYNCFIFO_COUNT > 1 - ASYNCFIFO_SECUREADDR_FUNC_DECL(1) -#endif - -#if ASYNCFIFO_COUNT > 2 - ASYNCFIFO_SECUREADDR_FUNC_DECL(2) -#endif - - -/*Show the async fifo secure enable*/ -#define ASYNCFIFO_SECURENABLE_FUNC_DECL(i) \ -static ssize_t asyncfifo##i##_show_secure_enable(struct class *class, \ - struct class_attribute *attr, char *buf)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - ssize_t ret = 0;\ - if (dvb->async_fifo_total_count <= i)\ - return ret;\ - ret = sprintf(buf, "%d\n", afifo->secure_enable);\ - return ret;\ -} \ -static ssize_t asyncfifo##i##_store_secure_enable(struct class *class, \ - struct class_attribute *attr, \ - const char *buf, size_t size)\ -{\ - struct aml_dvb *dvb = &aml_dvb_device;\ - struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ - int enable = 0;\ - long value;\ - int ret=0;\ - if (dvb->async_fifo_total_count <= i)\ - return (size_t)0;\ - ret = kstrtol(buf, 0, &value);\ - if (ret == 0)\ - enable = value;\ - if (enable != afifo->secure_enable) {\ - afifo->secure_enable = enable;\ - aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ - } \ - return size;\ -} - -#if ASYNCFIFO_COUNT > 0 -ASYNCFIFO_SECURENABLE_FUNC_DECL(0) -#endif - -#if ASYNCFIFO_COUNT > 1 - ASYNCFIFO_SECURENABLE_FUNC_DECL(1) -#endif - -#if ASYNCFIFO_COUNT > 2 - ASYNCFIFO_SECURENABLE_FUNC_DECL(2) -#endif - -/*Reset the Demux*/ -static ssize_t demux_do_reset(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - if (!strncmp("1", buf, 1)) { - struct aml_dvb *dvb = &aml_dvb_device; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - pr_dbg("Reset demux, call dmx_reset_hw\n"); - dmx_reset_hw_ex(dvb, 0); - spin_unlock_irqrestore(&dvb->slock, flags); - } - - return size; -} - -/*Show the Video PTS value*/ -static ssize_t demux_show_video_pts(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - - ret = sprintf(buf, "%u\n", aml_dmx_get_video_pts(dvb)); - - return ret; -} - -/*Show the Audio PTS value*/ -static ssize_t demux_show_audio_pts(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - - ret = sprintf(buf, "%u\n", aml_dmx_get_audio_pts(dvb)); - - return ret; -} - -/*Show the Video PTS bit32 value*/ -static ssize_t demux_show_video_pts_bit32(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - - ret = sprintf(buf, "%u\n", aml_dmx_get_video_pts_bit32(dvb)); - - return ret; -} - -/*Show the Audio PTS bit32 value*/ -static ssize_t demux_show_audio_pts_bit32(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - - ret = sprintf(buf, "%u\n", aml_dmx_get_audio_pts_bit32(dvb)); - - return ret; -} - - -/*Show the First Video PTS value*/ -static ssize_t demux_show_first_video_pts(struct class *class, - struct class_attribute *attr, - char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - - ret = sprintf(buf, "%u\n", aml_dmx_get_first_video_pts(dvb)); - - return ret; -} - -/*Show the First Audio PTS value*/ -static ssize_t demux_show_first_audio_pts(struct class *class, - struct class_attribute *attr, - char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - ssize_t ret = 0; - - ret = sprintf(buf, "%u\n", aml_dmx_get_first_audio_pts(dvb)); - - return ret; -} - -static ssize_t stb_show_hw_setting(struct class *class, - struct class_attribute *attr, char *buf) -{ - int r, total = 0; - int i; - struct aml_dvb *dvb = &aml_dvb_device; - int invert, ctrl; - - for (i = 0; i < dvb->ts_in_total_count; i++) { - struct aml_ts_input *ts = &dvb->ts[i]; - - if (ts->s2p_id != -1) - invert = dvb->s2p[ts->s2p_id].invert; - else - invert = 0; - - ctrl = ts->control; - - r = sprintf(buf, "ts%d %s control: 0x%x invert: 0x%x\n", i, - ts->mode == AM_TS_DISABLE ? "disable" : - (ts->mode == AM_TS_SERIAL ? "serial" : - "parallel"), ctrl, invert); - buf += r; - total += r; - } - - return total; -} - -static ssize_t stb_store_hw_setting(struct class *class, - struct class_attribute *attr, - const char *buf, size_t count) -{ - int id, ctrl, invert, r, mode; - char mname[32]; - char pname[32]; - unsigned long flags; - struct aml_ts_input *ts; - struct aml_dvb *dvb = &aml_dvb_device; - - r = sscanf(buf, "%d %s %x %x", &id, mname, &ctrl, &invert); - if (r != 4) - return -EINVAL; - - if (id < 0 || id >= dvb->ts_in_total_count) - return -EINVAL; - - if ((mname[0] == 's') || (mname[0] == 'S')) { - sprintf(pname, "s_ts%d", id); - mode = AM_TS_SERIAL; - } else if ((mname[0] == 'p') || (mname[0] == 'P')) { - sprintf(pname, "p_ts%d", id); - mode = AM_TS_PARALLEL; - } else - mode = AM_TS_DISABLE; - - spin_lock_irqsave(&dvb->slock, flags); - - ts = &dvb->ts[id]; - - if ((mode == AM_TS_SERIAL) && (ts->mode != AM_TS_SERIAL)) { - int i; - int scnt = 0; - - for (i = 0; i < dvb->ts_in_total_count; i++) { - if (dvb->ts[i].s2p_id != -1) - scnt++; - } - - if (scnt >= dvb->s2p_total_count) - pr_error("no free s2p\n"); - else - ts->s2p_id = scnt; - } - - if ((mode != AM_TS_SERIAL) || (ts->s2p_id != -1)) { - if (ts->pinctrl) { - devm_pinctrl_put(ts->pinctrl); - ts->pinctrl = NULL; - } - - ts->pinctrl = devm_pinctrl_get_select(&dvb->pdev->dev, pname); -/* if(IS_ERR_VALUE(ts->pinctrl))*/ -/* ts->pinctrl = NULL;*/ - ts->mode = mode; - ts->control = ctrl; - - if (mode == AM_TS_SERIAL) - dvb->s2p[ts->s2p_id].invert = invert; - else - ts->s2p_id = -1; - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return count; -} - -static ssize_t stb_show_tuner_setting(struct class *class, - struct class_attribute *attr, char *buf) -{ - struct aml_dvb *dvb = &aml_dvb_device; - - if (dvb->tuner_cur >= 0) - pr_inf("dvb current attatch tuner %d, id: %d\n", - dvb->tuner_cur, dvb->tuners[dvb->tuner_cur].cfg.id); - else - pr_inf("dvb has no attatch tuner.\n"); - - return 0; -} - -static ssize_t stb_store_tuner_setting(struct class *class, - struct class_attribute *attr, - const char *buf, size_t count) -{ - int n = 0, i = 0, val = 0; - unsigned long tmp = 0; - char *buf_orig = NULL, *ps = NULL, *token = NULL; - char *parm[4] = { NULL }; - struct aml_dvb *dvb = &aml_dvb_device; - int tuner_id = 0; - struct aml_tuner *tuner = NULL; - - buf_orig = kstrdup(buf, GFP_KERNEL); - ps = buf_orig; - - while (1) { - token = strsep(&ps, "\n "); - if (token == NULL) - break; - if (*token == '\0') - continue; - parm[n++] = token; - } - - if (parm[0] && kstrtoul(parm[0], 10, &tmp) == 0) { - val = tmp; - - for (i = 0; i < dvb->tuner_num; ++i) { - if (dvb->tuners[i].cfg.id == val) { - tuner_id = dvb->tuners[i].cfg.id; - break; - } - } - - if (tuner_id == 0 || dvb->tuner_cur == i) { - pr_error("%s: set nonsupport or the same tuner %d.\n", - __func__, val); - goto EXIT; - } - - dvb->tuner_cur = i; - - for (i = 0; i < FE_DEV_COUNT; i++) { - tuner = &dvb->tuners[dvb->tuner_cur]; - - if (frontend[i] == NULL) - continue; - - if (dvb_attach_tuner(frontend[i], tuner, &s_tuner_type[i]) < 0) { - pr_error("attach tuner %d failed\n", dvb->tuner_cur); - goto EXIT; - } - } - - pr_error("%s: attach tuner %d done.\n", __func__, dvb->tuners[dvb->tuner_cur].cfg.id); - } - -EXIT: - - return count; -} - -static struct class_attribute aml_stb_class_attrs[] = { - __ATTR(hw_setting, 0664, stb_show_hw_setting, - stb_store_hw_setting), - __ATTR(source, 0664, stb_show_source, - stb_store_source), - __ATTR(tso_source, 0644, tso_show_source, - tso_store_source), -#define DEMUX_SOURCE_ATTR_PCR(i)\ - __ATTR(demux##i##_pcr, 0644, demux##i##_show_pcr, NULL) -#define DEMUX_SOURCE_ATTR_DECL(i)\ - __ATTR(demux##i##_source, 0664,\ - demux##i##_show_source, demux##i##_store_source) -#define DEMUX_FREE_FILTERS_ATTR_DECL(i)\ - __ATTR(demux##i##_free_filters, 0644, \ - demux##i##_show_free_filters, NULL) -#define DEMUX_FILTER_USERS_ATTR_DECL(i)\ - __ATTR(demux##i##_filter_users, 0644, \ - demux##i##_show_filter_users, demux##i##_store_filter_used) -#define DVR_MODE_ATTR_DECL(i)\ - __ATTR(dvr##i##_mode, 0644, dvr##i##_show_mode, \ - dvr##i##_store_mode) -#define DEMUX_TS_HEADER_ATTR_DECL(i)\ - __ATTR(demux##i##_ts_header, 0644, \ - demux##i##_show_ts_header, NULL) -#define DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(i)\ - __ATTR(demux##i##_channel_activity, 0644, \ - demux##i##_show_channel_activity, NULL) -#define DMX_RESET_ATTR_DECL(i)\ - __ATTR(demux##i##_reset, 0644, NULL, \ - demux##i##_reset_store) - -#if DMX_DEV_COUNT > 0 - DEMUX_SOURCE_ATTR_PCR(0), - DEMUX_SOURCE_ATTR_DECL(0), - DEMUX_FREE_FILTERS_ATTR_DECL(0), - DEMUX_FILTER_USERS_ATTR_DECL(0), - DVR_MODE_ATTR_DECL(0), - DEMUX_TS_HEADER_ATTR_DECL(0), - DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(0), - DMX_RESET_ATTR_DECL(0), -#endif -#if DMX_DEV_COUNT > 1 - DEMUX_SOURCE_ATTR_PCR(1), - DEMUX_SOURCE_ATTR_DECL(1), - DEMUX_FREE_FILTERS_ATTR_DECL(1), - DEMUX_FILTER_USERS_ATTR_DECL(1), - DVR_MODE_ATTR_DECL(1), - DEMUX_TS_HEADER_ATTR_DECL(1), - DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(1), - DMX_RESET_ATTR_DECL(1), -#endif -#if DMX_DEV_COUNT > 2 - DEMUX_SOURCE_ATTR_PCR(2), - DEMUX_SOURCE_ATTR_DECL(2), - DEMUX_FREE_FILTERS_ATTR_DECL(2), - DEMUX_FILTER_USERS_ATTR_DECL(2), - DVR_MODE_ATTR_DECL(2), - DEMUX_TS_HEADER_ATTR_DECL(2), - DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(2), - DMX_RESET_ATTR_DECL(2), -#endif - -#define ASYNCFIFO_SOURCE_ATTR_DECL(i)\ - __ATTR(asyncfifo##i##_source, 0664, \ - asyncfifo##i##_show_source, asyncfifo##i##_store_source) -#define ASYNCFIFO_FLUSHSIZE_ATTR_DECL(i)\ - __ATTR(asyncfifo##i##_flush_size, 0664,\ - asyncfifo##i##_show_flush_size, \ - asyncfifo##i##_store_flush_size) -#define ASYNCFIFO_SECUREADDR_ATTR_DECL(i)\ - __ATTR(asyncfifo##i##_secure_addr, S_IRUGO | S_IWUSR | S_IWGRP,\ - asyncfifo##i##_show_secure_addr, \ - asyncfifo##i##_store_secure_addr) -#define ASYNCFIFO_SECURENABLE_ATTR_DECL(i)\ - __ATTR(asyncfifo##i##_secure_enable, S_IRUGO | S_IWUSR | S_IWGRP,\ - asyncfifo##i##_show_secure_enable, \ - asyncfifo##i##_store_secure_enable) - -#if ASYNCFIFO_COUNT > 0 - ASYNCFIFO_SOURCE_ATTR_DECL(0), - ASYNCFIFO_FLUSHSIZE_ATTR_DECL(0), - ASYNCFIFO_SECUREADDR_ATTR_DECL(0), - ASYNCFIFO_SECURENABLE_ATTR_DECL(0), -#endif -#if ASYNCFIFO_COUNT > 1 - ASYNCFIFO_SOURCE_ATTR_DECL(1), - ASYNCFIFO_FLUSHSIZE_ATTR_DECL(1), - ASYNCFIFO_SECUREADDR_ATTR_DECL(1), - ASYNCFIFO_SECURENABLE_ATTR_DECL(1), -#endif - -#if ASYNCFIFO_COUNT > 2 - ASYNCFIFO_SOURCE_ATTR_DECL(2), - ASYNCFIFO_FLUSHSIZE_ATTR_DECL(2), - ASYNCFIFO_SECUREADDR_ATTR_DECL(2), - ASYNCFIFO_SECURENABLE_ATTR_DECL(2), -#endif - - __ATTR(demux_reset, 0644, NULL, demux_do_reset), - __ATTR(video_pts, 0664, demux_show_video_pts, - NULL), - __ATTR(audio_pts, 0664, demux_show_audio_pts, - NULL), - __ATTR(video_pts_bit32, 0644, demux_show_video_pts_bit32, NULL), - __ATTR(audio_pts_bit32, 0644, demux_show_audio_pts_bit32, NULL), - __ATTR(first_video_pts, 0644, demux_show_first_video_pts, - NULL), - __ATTR(first_audio_pts, 0644, demux_show_first_audio_pts, - NULL), - __ATTR(clear_av, 0644, NULL, stb_clear_av), - -#define DSC_SOURCE_ATTR_DECL(i)\ - __ATTR(dsc##i##_source, 0664,\ - dsc##i##_show_source, dsc##i##_store_source) -#define DSC_FREE_ATTR_DECL(i) \ - __ATTR(dsc##i##_free_dscs, 0644, \ - dsc##i##_show_free_dscs, NULL) - -#if DSC_DEV_COUNT > 0 - DSC_SOURCE_ATTR_DECL(0), - DSC_FREE_ATTR_DECL(0), -#endif -#if DSC_DEV_COUNT > 1 - DSC_SOURCE_ATTR_DECL(1), - DSC_FREE_ATTR_DECL(1), -#endif - - __ATTR(tuner_setting, 0664, stb_show_tuner_setting, stb_store_tuner_setting), - - __ATTR_NULL -}; - -static struct class aml_stb_class = { - .name = "stb", - .class_attrs = aml_stb_class_attrs, -}; - -/* - *extern int aml_regist_dmx_class(void); - *extern int aml_unregist_dmx_class(void); - */ -/* - *void afifo_reset(int v) - *{ - * if (v) - * reset_control_assert(aml_dvb_afifo_reset_ctl); - * else - * reset_control_deassert(aml_dvb_afifo_reset_ctl); - *} - */ - -static int aml_dvb_probe(struct platform_device *pdev) -{ - struct aml_dvb *advb; - int i, ret = 0; - struct devio_aml_platform_data *pd_dvb; - - pr_dbg("probe amlogic dvb driver\n"); - - /*switch_mod_gate_by_name("demux", 1); */ -#if 0 - /*no used reset ctl to set clk*/ - aml_dvb_demux_reset_ctl = - devm_reset_control_get(&pdev->dev, "demux"); - pr_inf("dmx rst ctl = %p\n", aml_dvb_demux_reset_ctl); - reset_control_deassert(aml_dvb_demux_reset_ctl); - - aml_dvb_afifo_reset_ctl = - devm_reset_control_get(&pdev->dev, "asyncfifo"); - pr_inf("asyncfifo rst ctl = %p\n", aml_dvb_afifo_reset_ctl); - reset_control_deassert(aml_dvb_afifo_reset_ctl); - - aml_dvb_ahbarb0_reset_ctl = - devm_reset_control_get(&pdev->dev, "ahbarb0"); - pr_inf("ahbarb0 rst ctl = %p\n", aml_dvb_ahbarb0_reset_ctl); - reset_control_deassert(aml_dvb_ahbarb0_reset_ctl); - - aml_dvb_uparsertop_reset_ctl = - devm_reset_control_get(&pdev->dev, "uparsertop"); - pr_inf("uparsertop rst ctl = %p\n", aml_dvb_uparsertop_reset_ctl); - reset_control_deassert(aml_dvb_uparsertop_reset_ctl); -#else - - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - aml_dvb_demux_clk = - devm_clk_get(&pdev->dev, "demux"); - if (IS_ERR_OR_NULL(aml_dvb_demux_clk)) { - dev_err(&pdev->dev, "get demux clk fail\n"); - return -1; - } - clk_prepare_enable(aml_dvb_demux_clk); - - aml_dvb_afifo_clk = - devm_clk_get(&pdev->dev, "asyncfifo"); - if (IS_ERR_OR_NULL(aml_dvb_afifo_clk)) { - dev_err(&pdev->dev, "get asyncfifo clk fail\n"); - return -1; - } - clk_prepare_enable(aml_dvb_afifo_clk); - - aml_dvb_ahbarb0_clk = - devm_clk_get(&pdev->dev, "ahbarb0"); - if (IS_ERR_OR_NULL(aml_dvb_ahbarb0_clk)) { - dev_err(&pdev->dev, "get ahbarb0 clk fail\n"); - return -1; - } - clk_prepare_enable(aml_dvb_ahbarb0_clk); - - aml_dvb_uparsertop_clk = - devm_clk_get(&pdev->dev, "uparsertop"); - if (IS_ERR_OR_NULL(aml_dvb_uparsertop_clk)) { - dev_err(&pdev->dev, "get uparsertop clk fail\n"); - return -1; - } - clk_prepare_enable(aml_dvb_uparsertop_clk); - } - else - { - amports_switch_gate("demux", 1); - amports_switch_gate("ahbarb0", 1); - amports_switch_gate("parser_top", 1); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) - { - aml_dvb_afifo_clk = - devm_clk_get(&pdev->dev, "asyncfifo"); - if (IS_ERR_OR_NULL(aml_dvb_afifo_clk)) { - dev_err(&pdev->dev, "get asyncfifo clk fail\n"); - return -1; - } - clk_prepare_enable(aml_dvb_afifo_clk); - } - } -#endif - advb = &aml_dvb_device; - memset(advb, 0, sizeof(aml_dvb_device)); - - spin_lock_init(&advb->slock); - - advb->dev = &pdev->dev; - advb->pdev = pdev; - advb->stb_source = -1; - advb->tso_source = -1; - - if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) { - advb->ts_in_total_count = 3; - advb->s2p_total_count = 2; - advb->async_fifo_total_count = 2; - } else { - advb->ts_in_total_count = 4; - advb->s2p_total_count = 3; - advb->async_fifo_total_count = 3; - } - - for (i = 0; i < DMX_DEV_COUNT; i++) { - advb->dmx[i].dmx_irq = -1; - advb->dmx[i].dvr_irq = -1; - } - -#ifdef CONFIG_OF - if (pdev->dev.of_node) { - int s2p_id = 0; - char buf[32]; - const char *str; - u32 value; - - for (i = 0; i < advb->ts_in_total_count; i++) { - - advb->ts[i].mode = AM_TS_DISABLE; - advb->ts[i].s2p_id = -1; - advb->ts[i].pinctrl = NULL; - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "ts%d", i); - ret = - of_property_read_string(pdev->dev.of_node, buf, - &str); - if (!ret) { - if (!strcmp(str, "serial")) { - pr_inf("%s: serial\n", buf); - - if (s2p_id >= advb->s2p_total_count) - pr_error("no free s2p\n"); - else { - snprintf(buf, sizeof(buf), - "s_ts%d", i); - advb->ts[i].mode = AM_TS_SERIAL; - advb->ts[i].pinctrl = - devm_pinctrl_get_select - (&pdev->dev, buf); - advb->ts[i].s2p_id = s2p_id; - - s2p_id++; - } - } else if (!strcmp(str, "parallel")) { - pr_inf("%s: parallel\n", buf); - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "p_ts%d", i); - advb->ts[i].mode = AM_TS_PARALLEL; - advb->ts[i].pinctrl = - devm_pinctrl_get_select(&pdev->dev, - buf); - } else { - advb->ts[i].mode = AM_TS_DISABLE; - advb->ts[i].pinctrl = NULL; - } - - /* if(IS_ERR_VALUE(advb->ts[i].pinctrl)) */ - /* advb->ts[i].pinctrl = NULL; */ - } - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "ts%d_control", i); - ret = - of_property_read_u32(pdev->dev.of_node, buf, - &value); - if (!ret) { - pr_inf("%s: 0x%x\n", buf, value); - advb->ts[i].control = value; - } else { - pr_inf("read error:%s: 0x%x\n", buf, value); - } - - if (advb->ts[i].s2p_id != -1) { - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "ts%d_invert", i); - ret = - of_property_read_u32(pdev->dev.of_node, buf, - &value); - if (!ret) { - pr_inf("%s: 0x%x\n", buf, value); - advb->s2p[advb->ts[i].s2p_id].invert = - value; - } - } - } - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "ts_out_invert"); - ret = - of_property_read_u32(pdev->dev.of_node, buf, - &value); - if (!ret) { - pr_inf("%s: 0x%x\n", buf, value); - advb->ts_out_invert = value; - } - } -#endif - - pd_dvb = (struct devio_aml_platform_data *)advb->dev->platform_data; - - ret = - dvb_register_adapter(&advb->dvb_adapter, CARD_NAME, THIS_MODULE, - advb->dev, adapter_nr); - if (ret < 0) - return ret; - - for (i = 0; i < DMX_DEV_COUNT; i++) - advb->dmx[i].id = -1; - - for (i = 0; idsc[i].id = -1; - - for (i = 0; i < advb->async_fifo_total_count; i++) - advb->asyncfifo[i].id = -1; - - advb->dvb_adapter.priv = advb; - dev_set_drvdata(advb->dev, advb); - - for (i = 0; i < DSC_DEV_COUNT; i++) { - ret = aml_dvb_dsc_init(advb, &advb->dsc[i], i); - if (ret < 0) - goto error; - } - - for (i = 0; i < DMX_DEV_COUNT; i++) { - ret = aml_dvb_dmx_init(advb, &advb->dmx[i], i); - if (ret < 0) - goto error; - } - - /*Init the async fifos */ - for (i = 0; i < advb->async_fifo_total_count; i++) { - ret = aml_dvb_asyncfifo_init(advb, &advb->asyncfifo[i], i); - if (ret < 0) - goto error; - } - - aml_regist_dmx_class(); - - if (class_register(&aml_stb_class) < 0) { - pr_error("register class error\n"); - goto error; - } - -#ifdef ENABLE_DEMUX_DRIVER - tsdemux_set_ops(&aml_tsdemux_ops); -#else - tsdemux_set_ops(NULL); -#endif - - //pengcc add for dvb using linux TV frontend api init - { - struct amlfe_exp_config config; - char buf[32]; - const char *str = NULL; - struct device_node *node_tuner = NULL; - struct device_node *node_i2c = NULL; - u32 i2c_addr = 0xFFFFFFFF; - u32 value = 0; - int j = 0; - - for (i=0; idev.of_node, buf, &str); - if (ret) { - continue; - } - if (!strcmp(str,"internal")) - { - config.set_mode = 0; - frontend[i] = dvb_attach(aml_dtvdm_attach,&config); - if (frontend[i] == NULL) { - pr_error("dvb attach demod error\n"); - goto error_fe; - } else { - pr_inf("dtvdemod attatch sucess\n"); - s_demod_type[i] = DEMOD_INTERNAL; - } - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_tuner",i); - node_tuner = of_parse_phandle(pdev->dev.of_node, buf, 0); - if (!node_tuner) { - pr_err("can't find tuner.\n"); - goto error_fe; - } - - ret = of_property_read_u32(node_tuner, "tuner_num", &value); - if (ret) { - pr_err("can't find tuner_num.\n"); - goto error_fe; - } else - advb->tuner_num = value; - - advb->tuners = kzalloc(sizeof(struct aml_tuner) * advb->tuner_num, GFP_KERNEL); - if (!advb->tuners) { - pr_err("can't kzalloc for tuners.\n"); - goto error_fe; - } - - ret = of_property_read_u32(node_tuner, "tuner_cur", &value); - if (ret) { - pr_err("can't find tuner_cur, use default 0.\n"); - advb->tuner_cur = -1; - } else - advb->tuner_cur = value; - - for (j = 0; j < advb->tuner_num; ++j) { - snprintf(buf, sizeof(buf), "tuner_name_%d", j); - ret = of_property_read_string(node_tuner, buf, &str); - if (ret) { - //pr_error("tuner%d type error\n",i); - ret = 0; - continue; - } else { - if (!strncmp(str, "mxl661_tuner", 12)) - advb->tuners[j].cfg.id = AM_TUNER_MXL661; - else if (!strncmp(str, "si2151_tuner", 12)) - advb->tuners[j].cfg.id = AM_TUNER_SI2151; - else if (!strncmp(str, "si2159_tuner", 12)) - advb->tuners[j].cfg.id = AM_TUNER_SI2159; - else if (!strncmp(str, "r840_tuner", 10)) - advb->tuners[j].cfg.id = AM_TUNER_R840; - else if (!strncmp(str, "r842_tuner", 10)) - advb->tuners[j].cfg.id = AM_TUNER_R842; - else { - pr_err("nonsupport tuner: %s.\n", str); - advb->tuners[j].cfg.id = AM_TUNER_NONE; - } - } - - snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", j); - node_i2c = of_parse_phandle(node_tuner, buf, 0); - if (!node_i2c) { - pr_error("tuner_i2c_adap_id error\n"); - } else { - advb->tuners[j].i2c_adp = of_find_i2c_adapter_by_node(node_i2c); - of_node_put(node_i2c); - if (advb->tuners[j].i2c_adp == NULL) { - pr_error("i2c_get_adapter error\n"); - of_node_put(node_tuner); - goto error_fe; - } - } - - snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", j); - ret = of_property_read_u32(node_tuner, buf, &i2c_addr); - if (ret) { - pr_error("i2c_addr error\n"); - } - else - advb->tuners[j].cfg.i2c_addr = i2c_addr; - - snprintf(buf, sizeof(buf), "tuner_xtal_%d", j); - ret = of_property_read_u32(node_tuner, buf, &value); - if (ret) - pr_err("tuner_xtal error.\n"); - else - advb->tuners[j].cfg.xtal = value; - - snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", j); - ret = of_property_read_u32(node_tuner, buf, &value); - if (ret) - pr_err("tuner_xtal_mode error.\n"); - else - advb->tuners[j].cfg.xtal_mode = value; - - snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", j); - ret = of_property_read_u32(node_tuner, buf, &value); - if (ret) - pr_err("tuner_xtal_cap error.\n"); - else - advb->tuners[j].cfg.xtal_cap = value; - } - - of_node_put(node_tuner); - - /* define general-purpose callback pointer */ - frontend[i]->callback = NULL; - - if (advb->tuner_cur >= 0) { - if (dvb_attach_tuner(frontend[i], &advb->tuners[advb->tuner_cur], &s_tuner_type[i]) < 0) { - pr_error("attach tuner failed\n"); - goto error_fe; - } - } - - ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]); - if (ret) { - pr_error("register dvb frontend failed\n"); - goto error_fe; - } - } else if(!strcmp(str,"external")) { - const char *name = NULL; - struct amlfe_demod_config config; - - config.dev_id = i; - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_demod",i); - ret = of_property_read_string(pdev->dev.of_node, buf, &name); - if (ret) { - ret = 0; - continue; - } - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_i2c_adap_id",i); - node_i2c = of_parse_phandle(pdev->dev.of_node,buf,0); - if (!node_i2c) { - pr_error("demod%d_i2c_adap_id error\n", i); - } else { - config.i2c_adap = of_find_i2c_adapter_by_node(node_i2c); - of_node_put(node_i2c); - if (config.i2c_adap == NULL) { - pr_error("i2c_get_adapter error\n"); - goto error_fe; - } - } - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_demod_i2c_addr",i); - ret = of_property_read_u32(pdev->dev.of_node, buf,&config.i2c_addr); - if (ret) { - pr_error("i2c_addr error\n"); - goto error_fe; - } - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_ts",i); - ret = of_property_read_u32(pdev->dev.of_node, buf,&config.ts); - if (ret) { - pr_error("ts error\n"); - goto error_fe; - } - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_reset_gpio",i); - ret = of_property_read_string(pdev->dev.of_node, buf, &str); - if (!ret) { - config.reset_gpio = - of_get_named_gpio_flags(pdev->dev.of_node, - buf, 0, NULL); - pr_inf("%s: %d\n", buf, config.reset_gpio); - } else { - config.reset_gpio = -1; - pr_error("cannot find resource \"%s\"\n", buf); - goto error_fe; - } - - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_reset_value",i); - ret = of_property_read_u32(pdev->dev.of_node, buf,&config.reset_value); - if (ret) { - pr_error("reset_value error\n"); - goto error_fe; - } - - if (!strcmp(name,"Atbm8881")) { - frontend[i] = dvb_attach(atbm8881_attach,&config); - if (frontend[i] == NULL) { - pr_error("dvb attach demod error\n"); - goto error_fe; - } else { - pr_inf("dtvdemod attatch sucess\n"); - s_demod_type[i] = DEMOD_ATBM8881; - } - } - if (!strcmp(name,"Si2168")) { - frontend[i] = dvb_attach(si2168_attach,&config); - if (frontend[i] == NULL) { - pr_error("dvb attach demod error\n"); - goto error_fe; - } else { - pr_inf("dtvdemod attatch sucess\n"); - s_demod_type[i] = DEMOD_SI2168; - } - } - if (frontend[i]) { - ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]); - if (ret) { - pr_error("register dvb frontend failed\n"); - goto error_fe; - } - } - } - } - return 0; -error_fe: - for (i=0; ituners) - kfree(advb->tuners); - - return 0; -error: - for (i = 0; i < advb->async_fifo_total_count; i++) { - if (advb->asyncfifo[i].id != -1) - aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); - } - - for (i = 0; i < DMX_DEV_COUNT; i++) { - if (advb->dmx[i].id != -1) - aml_dvb_dmx_release(advb, &advb->dmx[i]); - } - - for (i = 0; i < DSC_DEV_COUNT; i++) { - if (advb->dsc[i].id != -1) - aml_dvb_dsc_release(advb, &advb->dsc[i]); - } - - dvb_unregister_adapter(&advb->dvb_adapter); - - return ret; -} -static int aml_dvb_remove(struct platform_device *pdev) -{ - struct aml_dvb *advb = (struct aml_dvb *)dev_get_drvdata(&pdev->dev); - int i; - - for (i=0; iasync_fifo_total_count; i++) { - if (advb->asyncfifo[i].id != -1) - aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); - } - - for (i = 0; i < DMX_DEV_COUNT; i++) { - pr_error("remove demx %d, id is %d\n",i,advb->dmx[i].id); - if (advb->dmx[i].id != -1) - aml_dvb_dmx_release(advb, &advb->dmx[i]); - } - - for (i = 0; i < DSC_DEV_COUNT; i++) { - if (advb->dsc[i].id != -1) - aml_dvb_dsc_release(advb, &advb->dsc[i]); - } - dvb_unregister_adapter(&advb->dvb_adapter); - - for (i = 0; i < advb->ts_in_total_count; i++) { - if (advb->ts[i].pinctrl && !IS_ERR_VALUE(advb->ts[i].pinctrl)) - devm_pinctrl_put(advb->ts[i].pinctrl); - } - - /*switch_mod_gate_by_name("demux", 0); */ -#if 0 - reset_control_assert(aml_dvb_uparsertop_reset_ctl); - reset_control_assert(aml_dvb_ahbarb0_reset_ctl); - reset_control_assert(aml_dvb_afifo_reset_ctl); - reset_control_assert(aml_dvb_demux_reset_ctl); -#else -#if 1 - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - clk_disable_unprepare(aml_dvb_uparsertop_clk); - clk_disable_unprepare(aml_dvb_ahbarb0_clk); - clk_disable_unprepare(aml_dvb_afifo_clk); - clk_disable_unprepare(aml_dvb_demux_clk); - } - else - { - amports_switch_gate("demux", 0); - amports_switch_gate("ahbarb0", 0); - amports_switch_gate("parser_top", 0); - - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { - clk_disable_unprepare(aml_dvb_afifo_clk); - } - } -#endif -#endif - - if (advb->tuners) - kfree(advb->tuners); - - return 0; -} - -static int aml_dvb_suspend(struct platform_device *dev, pm_message_t state) -{ - return 0; -} - -static int aml_dvb_resume(struct platform_device *dev) -{ - struct aml_dvb *dvb = &aml_dvb_device; - int i; - - for (i = 0; i < DMX_DEV_COUNT; i++) - dmx_reset_dmx_id_hw_ex(dvb, i, 0); - - pr_inf("dvb resume\n"); - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id aml_dvb_dt_match[] = { - { - .compatible = "amlogic, dvb", - }, - {}, -}; -#endif /*CONFIG_OF */ - -static struct platform_driver aml_dvb_driver = { - .probe = aml_dvb_probe, - .remove = aml_dvb_remove, - .suspend = aml_dvb_suspend, - .resume = aml_dvb_resume, - .driver = { - .name = "amlogic-dvb", - .owner = THIS_MODULE, -#ifdef CONFIG_OF - .of_match_table = aml_dvb_dt_match, -#endif - } -}; - -static int __init aml_dvb_init(void) -{ - pr_dbg("aml dvb init\n"); - return platform_driver_register(&aml_dvb_driver); -} - -static void __exit aml_dvb_exit(void) -{ - pr_dbg("aml dvb exit\n"); - platform_driver_unregister(&aml_dvb_driver); -} - -/*Get the STB source demux*/ -static struct aml_dmx *get_stb_dmx(void) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx = NULL; - int i; - - switch (dvb->stb_source) { - case AM_TS_SRC_DMX0: - dmx = &dvb->dmx[0]; - break; - case AM_TS_SRC_DMX1: - dmx = &dvb->dmx[1]; - break; - case AM_TS_SRC_DMX2: - dmx = &dvb->dmx[2]; - break; - default: - for (i = 0; i < DMX_DEV_COUNT; i++) { - dmx = &dvb->dmx[i]; - if (dmx->source == dvb->stb_source) - return dmx; - } - break; - } - - return dmx; -} - -static int aml_tsdemux_reset(void) -{ - struct aml_dvb *dvb = &aml_dvb_device; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - if (dvb->reset_flag) { - struct aml_dmx *dmx = get_stb_dmx(); - - dvb->reset_flag = 0; - if (dmx) - dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0); - } - spin_unlock_irqrestore(&dvb->slock, flags); - - return 0; -} - -static int aml_tsdemux_set_reset_flag(void) -{ - struct aml_dvb *dvb = &aml_dvb_device; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - dvb->reset_flag = 1; - spin_unlock_irqrestore(&dvb->slock, flags); - - return 0; - -} - -/*Add the amstream irq handler*/ -static int aml_tsdemux_request_irq(irq_handler_t handler, void *data) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - - dmx = get_stb_dmx(); - if (dmx) { - dmx->irq_handler = handler; - dmx->irq_data = data; - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return 0; -} - -/*Free the amstream irq handler*/ -static int aml_tsdemux_free_irq(void) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - - dmx = get_stb_dmx(); - if (dmx) { - dmx->irq_handler = NULL; - dmx->irq_data = NULL; - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return 0; -} - -/*Reset the video PID*/ -static int aml_tsdemux_set_vid(int vpid) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dvb->slock, flags); - dmx = get_stb_dmx(); - if (dmx) { - if (dmx->vid_chan != -1) { - dmx_free_chan(dmx, dmx->vid_chan); - dmx->vid_chan = -1; - } - - if ((vpid >= 0) && (vpid < 0x1FFF)) { - dmx->vid_chan = - dmx_alloc_chan(dmx, DMX_TYPE_TS, - DMX_PES_VIDEO, vpid); - if (dmx->vid_chan == -1) - ret = -1; - } - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -/*Reset the audio PID*/ -static int aml_tsdemux_set_aid(int apid) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dvb->slock, flags); - dmx = get_stb_dmx(); - if (dmx) { - if (dmx->aud_chan != -1) { - dmx_free_chan(dmx, dmx->aud_chan); - dmx->aud_chan = -1; - } - - if ((apid >= 0) && (apid < 0x1FFF)) { - dmx->aud_chan = - dmx_alloc_chan(dmx, DMX_TYPE_TS, - DMX_PES_AUDIO, apid); - if (dmx->aud_chan == -1) - ret = -1; - } - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -/*Reset the subtitle PID*/ -static int aml_tsdemux_set_sid(int spid) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dvb->slock, flags); - - dmx = get_stb_dmx(); - if (dmx) { - if (dmx->sub_chan != -1) { - dmx_free_chan(dmx, dmx->sub_chan); - dmx->sub_chan = -1; - } - - if ((spid >= 0) && (spid < 0x1FFF)) { - dmx->sub_chan = - dmx_alloc_chan(dmx, DMX_TYPE_TS, - DMX_PES_SUBTITLE, spid); - if (dmx->sub_chan == -1) - ret = -1; - } - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -static int aml_tsdemux_set_pcrid(int pcrpid) -{ - struct aml_dvb *dvb = &aml_dvb_device; - struct aml_dmx *dmx; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dvb->slock, flags); - - dmx = get_stb_dmx(); - if (dmx) { - if (dmx->pcr_chan != -1) { - dmx_free_chan(dmx, dmx->pcr_chan); - dmx->pcr_chan = -1; - } - - if ((pcrpid >= 0) && (pcrpid < 0x1FFF)) { - dmx->pcr_chan = - dmx_alloc_chan(dmx, DMX_TYPE_TS, - DMX_PES_PCR, pcrpid); - if (dmx->pcr_chan == -1) - ret = -1; - } - } - - spin_unlock_irqrestore(&dvb->slock, flags); - - return ret; -} - -static int aml_tsdemux_set_skipbyte(int skipbyte) -{ - struct aml_dvb *dvb = &aml_dvb_device; - unsigned long flags; - - spin_lock_irqsave(&dvb->slock, flags); - aml_dmx_set_skipbyte(dvb, skipbyte); - spin_unlock_irqrestore(&dvb->slock, flags); - - return 0; -} - -static int aml_tsdemux_set_demux(int id) -{ - struct aml_dvb *dvb = &aml_dvb_device; - - aml_dmx_set_demux(dvb, id); - return 0; -} - -module_init(aml_dvb_init); -module_exit(aml_dvb_exit); - -MODULE_DESCRIPTION("driver for the AMLogic DVB card"); -MODULE_AUTHOR("AMLOGIC"); -MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h deleted file mode 100644 index 50ad86215f46..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h +++ /dev/null @@ -1,414 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _AML_DVB_H_ -#define _AML_DVB_H_ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "aml_demod_gt.h" - -#define TS_IN_COUNT 4 -#define S2P_COUNT 3 -#define ASYNCFIFO_COUNT 3 -#if 0 -#define TS_IN_COUNT 3 -#define S2P_COUNT 2 -#define ASYNCFIFO_COUNT 2 -#endif - -#define DMX_DEV_COUNT 3 -#define FE_DEV_COUNT 2 -#define CHANNEL_COUNT 31 -#define FILTER_COUNT 31 -#define FILTER_LEN 15 -#define DSC_DEV_COUNT 2 -#define DSC_COUNT 8 -#define SEC_BUF_GRP_COUNT 4 -#define SEC_BUF_BUSY_SIZE 4 -#define SEC_BUF_COUNT (SEC_BUF_GRP_COUNT*8) - -enum aml_dmx_id_t { - AM_DMX_0 = 0, - AM_DMX_1, - AM_DMX_2, - AM_DMX_MAX, -}; - -enum aml_ts_source_t { - AM_TS_SRC_TS0, - AM_TS_SRC_TS1, - AM_TS_SRC_TS2, - AM_TS_SRC_TS3, - - AM_TS_SRC_S_TS0, - AM_TS_SRC_S_TS1, - AM_TS_SRC_S_TS2, - - AM_TS_SRC_HIU, - AM_TS_SRC_HIU1, - AM_TS_SRC_DMX0, - AM_TS_SRC_DMX1, - AM_TS_SRC_DMX2 -}; - -struct aml_sec_buf { - unsigned long addr; - int len; -}; - -struct aml_channel { - int type; - enum dmx_ts_pes pes_type; - int pid; - int used; - int filter_count; - struct dvb_demux_feed *feed; - struct dvb_demux_feed *dvr_feed; -}; - -struct aml_filter { - int chan_id; - int used; - struct dmx_section_filter *filter; - u8 value[FILTER_LEN]; - u8 maskandmode[FILTER_LEN]; - u8 maskandnotmode[FILTER_LEN]; - u8 neq; -}; - -#define DVBCSA_MODE 0 -#define CIPLUS_MODE 1 -#define CBC_MODE 0 -#define ECB_MODE 1 -#define IDSA_MODE 2 - -#define DSC_SET_EVEN 1 -#define DSC_SET_ODD 2 -#define DSC_SET_AES_EVEN 4 -#define DSC_SET_AES_ODD 8 -#define DSC_FROM_KL 16 -#define DSC_SET_SM4_EVEN 32 -#define DSC_SET_SM4_ODD 64 - -#define DSC_KEY_SIZE_MAX 16 - -struct aml_dsc_channel { - int pid; - u8 even[DSC_KEY_SIZE_MAX]; - u8 odd[DSC_KEY_SIZE_MAX]; - u8 even_iv[DSC_KEY_SIZE_MAX]; - u8 odd_iv[DSC_KEY_SIZE_MAX]; - int used; - int set; - int id; - struct aml_dsc *dsc; - int work_mode; - int mode; -}; - -struct aml_dsc { - struct dvb_device *dev; - struct aml_dsc_channel channel[DSC_COUNT]; - enum aml_ts_source_t source; - enum aml_ts_source_t dst; - struct aml_dvb *dvb; - int id; - int work_mode; -}; - -struct aml_smallsec { - struct aml_dmx *dmx; - - int enable; - int bufsize; -#define SS_BUFSIZE_DEF (16*4*256) /*16KB*/ - long buf; - long buf_map; -}; - -struct aml_dmxtimeout { - struct aml_dmx *dmx; - - int enable; - - int timeout; -#define DTO_TIMEOUT_DEF (9000) /*0.5s*/ - u32 ch_disable; -#define DTO_CHDIS_VAS (0xfffffff8) /*v/a/s only*/ - int match; - - int trigger; -}; - -struct aml_dmx { - struct dvb_demux demux; - struct dmxdev dmxdev; - int id; - int feed_count; - int chan_count; - enum aml_ts_source_t source; - int init; - int record; - struct dmx_frontend hw_fe[DMX_DEV_COUNT]; - struct dmx_frontend mem_fe; - struct dvb_net dvb_net; - int dmx_irq; - int dvr_irq; - struct tasklet_struct dmx_tasklet; - struct tasklet_struct dvr_tasklet; - unsigned long sec_pages; - unsigned long sec_pages_map; - int sec_total_len; - struct aml_sec_buf sec_buf[SEC_BUF_COUNT]; - unsigned long pes_pages; - unsigned long pes_pages_map; - int pes_buf_len; - unsigned long sub_pages; - unsigned long sub_pages_map; - int sub_buf_len; - struct aml_channel channel[CHANNEL_COUNT+1]; - struct aml_filter filter[FILTER_COUNT+1]; - irq_handler_t irq_handler; - void *irq_data; - int aud_chan; - int vid_chan; - int sub_chan; - int pcr_chan; - u32 section_busy[SEC_BUF_BUSY_SIZE]; - struct dvb_frontend *fe; - int int_check_count; - u32 int_check_time; - int in_tune; - int error_check; - int dump_ts_select; - int sec_buf_watchdog_count[SEC_BUF_COUNT]; - - struct aml_smallsec smallsec; - struct aml_dmxtimeout timeout; - - int demux_filter_user; - - unsigned long sec_cnt[3]; - unsigned long sec_cnt_match[3]; - unsigned long sec_cnt_crc_fail[3]; - #define SEC_CNT_HW (0) - #define SEC_CNT_SW (1) - #define SEC_CNT_SS (2) - #define SEC_CNT_MAX (3) - - int crc_check_count; - u32 crc_check_time; -}; - -struct aml_dvr_block { - u32 addr; - u32 len; -}; - -struct aml_asyncfifo { - int id; - int init; - int asyncfifo_irq; - enum aml_dmx_id_t source; - unsigned long pages; - unsigned long pages_map; - int buf_len; - int buf_toggle; - int buf_read; - int flush_size; - int secure_enable; - struct tasklet_struct asyncfifo_tasklet; - struct aml_dvb *dvb; - struct aml_dvr_block blk; -}; - -enum{ - AM_TS_DISABLE, - AM_TS_PARALLEL, - AM_TS_SERIAL -}; - -struct aml_ts_input { - int mode; - struct pinctrl *pinctrl; - int control; - int s2p_id; -}; - -struct aml_s2p { - int invert; -}; - -struct aml_swfilter { - int user; - struct aml_dmx *dmx; - struct aml_asyncfifo *afifo; - - struct dvb_ringbuffer rbuf; -#define SF_BUFFER_SIZE (10*188*1024) - - u8 wrapbuf[188]; - int track_dmx; -}; - -struct aml_tuner { - struct tuner_config cfg; - unsigned int i2c_adapter_id; - struct i2c_adapter *i2c_adp; -}; - -struct aml_dvb { - struct dvb_device dvb_dev; - int ts_in_total_count; - struct aml_ts_input ts[TS_IN_COUNT]; - int s2p_total_count; - struct aml_s2p s2p[S2P_COUNT]; - struct aml_dmx dmx[DMX_DEV_COUNT]; - struct aml_dsc dsc[DSC_DEV_COUNT]; - int async_fifo_total_count; - struct aml_asyncfifo asyncfifo[ASYNCFIFO_COUNT]; - struct dvb_adapter dvb_adapter; - struct device *dev; - struct platform_device *pdev; - enum aml_ts_source_t stb_source; - enum aml_ts_source_t tso_source; - int dmx_init; - int reset_flag; - spinlock_t slock; - struct timer_list watchdog_timer; - int dmx_watchdog_disable[DMX_DEV_COUNT]; - struct aml_swfilter swfilter; - int ts_out_invert; - - unsigned int tuner_num; - unsigned int tuner_cur; - struct aml_tuner *tuners; - bool tuner_attached; -}; - - -/*AMLogic demux interface*/ -extern int aml_dmx_hw_init(struct aml_dmx *dmx); -extern int aml_dmx_hw_deinit(struct aml_dmx *dmx); -extern int aml_dmx_hw_start_feed(struct dvb_demux_feed *dvbdmxfeed); -extern int aml_dmx_hw_stop_feed(struct dvb_demux_feed *dvbdmxfeed); -extern int aml_dmx_hw_set_source(struct dmx_demux *demux, - dmx_source_t src); -extern int aml_stb_hw_set_source(struct aml_dvb *dvb, dmx_source_t src); -extern int aml_dsc_hw_set_source(struct aml_dsc *dsc, - dmx_source_t src, dmx_source_t dst); -extern int aml_tso_hw_set_source(struct aml_dvb *dvb, dmx_source_t src); -extern int aml_dmx_set_skipbyte(struct aml_dvb *dvb, int skipbyte); -extern int aml_dmx_set_demux(struct aml_dvb *dvb, int id); -extern int aml_dmx_hw_set_dump_ts_select - (struct dmx_demux *demux, int dump_ts_select); - -extern int dmx_alloc_chan(struct aml_dmx *dmx, int type, - int pes_type, int pid); -extern void dmx_free_chan(struct aml_dmx *dmx, int cid); - -extern int dmx_get_ts_serial(enum aml_ts_source_t src); - -/*AMLogic dsc interface*/ -extern int dsc_set_pid(struct aml_dsc_channel *ch, int pid); -extern int dsc_set_key(struct aml_dsc_channel *ch, int flags, - enum ca_cw_type type, u8 *key); -extern void dsc_release(void); -extern int aml_ciplus_hw_set_source(int src); - -/*AMLogic ASYNC FIFO interface*/ -extern int aml_asyncfifo_hw_init(struct aml_asyncfifo *afifo); -extern int aml_asyncfifo_hw_deinit(struct aml_asyncfifo *afifo); -extern int aml_asyncfifo_hw_set_source(struct aml_asyncfifo *afifo, - enum aml_dmx_id_t src); -extern int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo); - -/*Get the Audio & Video PTS*/ -extern u32 aml_dmx_get_video_pts(struct aml_dvb *dvb); -extern u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb); -extern u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb); -extern u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb); -extern u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb); -extern u32 aml_dmx_get_first_audio_pts(struct aml_dvb *dvb); - -/*Get the DVB device*/ -extern struct aml_dvb *aml_get_dvb_device(void); - -extern int aml_regist_dmx_class(void); -extern int aml_unregist_dmx_class(void); - -struct devio_aml_platform_data { - int (*io_setup)(void *); - int (*io_cleanup)(void *); - int (*io_power)(void *, int enable); - int (*io_reset)(void *, int enable); -}; - -void get_aml_dvb(struct aml_dvb *dvb_device); - -/*Reset the demux device*/ -void dmx_reset_hw(struct aml_dvb *dvb); -void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq); - -/*Reset the individual demux*/ -void dmx_reset_dmx_hw(struct aml_dvb *dvb, int id); -void dmx_reset_dmx_id_hw_ex(struct aml_dvb *dvb, int id, int reset_irq); -void dmx_reset_dmx_id_hw_ex_unlock(struct aml_dvb *dvb, int id, int reset_irq); -void dmx_reset_dmx_hw_ex(struct aml_dvb *dvb, - struct aml_dmx *dmx, - int reset_irq); -void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, - struct aml_dmx *dmx, - int reset_irq); - -#endif - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h deleted file mode 100644 index dbfa6ba43a6d..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * drivers/amlogic/dvb_tv/dvb_reg.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef _DVB_REG_H_ -#define _DVB_REG_H_ - -#include - -#include - -#define ID_STB_CBUS_BASE 0 -#define ID_SMARTCARD_REG_BASE 1 -#define ID_ASYNC_FIFO_REG_BASE 2 -#define ID_ASYNC_FIFO1_REG_BASE 3 -#define ID_ASYNC_FIFO2_REG_BASE 4 -#define ID_RESET_BASE 5 -#define ID_PARSER_SUB_START_PTR_BASE 6 - -long aml_stb_get_base(int id); -#include "c_stb_define.h" -#include "c_stb_regs_define.h" - -#define WRITE_MPEG_REG(_r, _v) aml_write_cbus(_r, _v) -#define READ_MPEG_REG(_r) aml_read_cbus(_r) - -#define WRITE_CBUS_REG(_r, _v) aml_write_cbus(_r, _v) -#define READ_CBUS_REG(_r) aml_read_cbus(_r) - -#define WRITE_VCBUS_REG(_r, _v) aml_write_vcbus(_r, _v) -#define READ_VCBUS_REG(_r) aml_read_vcbus(_r) - -#define BASE_IRQ 32 -#define AM_IRQ(reg) (reg + BASE_IRQ) -#define INT_DEMUX AM_IRQ(23) -#define INT_DEMUX_1 AM_IRQ(5) -#define INT_DEMUX_2 AM_IRQ(21) //AM_IRQ(53) -#define INT_ASYNC_FIFO_FILL AM_IRQ(18) -#define INT_ASYNC_FIFO_FLUSH AM_IRQ(19) -#define INT_ASYNC_FIFO2_FILL AM_IRQ(24) -#define INT_ASYNC_FIFO2_FLUSH AM_IRQ(25) - -#define INT_ASYNC_FIFO3_FLUSH AM_IRQ(17) -#endif - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h deleted file mode 100644 index 6b815b67bbd7..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h +++ /dev/null @@ -1,1217 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -/* ----------------------------------------------------------------------*/ -/* This file is automatically generated from the script:*/ -/**/ -/* ./create_stb_define_for_C_code.pl*/ -/**/ -/* and was applied to the file*/ -/**/ -/* ./stb_define.h*/ -/**/ -/* DO NOT EDIT!!!!!*/ -/* ----------------------------------------------------------------------*/ -/**/ -#ifdef C_STB_DEFINE_H -#else -#define C_STB_DEFINE_H - -/*=================================================*/ -/* STB Registers Start*/ -/*=================================================*/ -/* -----------------------------------------------*/ -/*#define STB_CBUS_BASE 0x1600*/ -/* -----------------------------------------------*/ -/* There are two instantiations under one CBUS slave. - * Each CBUS slave can support*/ -/* 256 registers. - * Each demux is allocated 128 registers so set the offset in*/ -/* the middle*/ -/* Copy this define but don't add a base address*/ -/*#define DEMUX_1_OFFSET 0x00*/ -/*#define DEMUX_2_OFFSET 0x50*/ -/*#define DEMUX_3_OFFSET 0xa0*/ -/*======================================================*/ -/* STB TOP Registers (8'hf0 - 8'hf7)*/ -/*======================================================*/ -/* bit 30:28 -- ciplus_o_sel*/ -/* bit 27:26 -- ciplus_i_sel*/ -/* bit 25 -- use FAIL fro TS2*/ -/* bit 24 -- use FAIL fro TS1*/ -/* bit 23 -- use FAIL fro TS0*/ -/* bit 22 -- invert fec_error for S2P1*/ -/* bit 21 -- invert fec_data for S2P1*/ -/* bit 20 -- invert fec_sync for S2P1*/ -/* bit 19 -- invert fec_valid for S2P1*/ -/* bit 18 -- invert fec_clk for S2P1*/ -/* bit 17:16 -- fec_s_sel for S2P1 - * 00 - select TS0, 01 -- select TS1, 10 -- select TS2, 11 - TS3*/ -/* Bit 15 -- enable_des_pl_clk*/ -/* Bit 14 -- reserved*/ -/* Bit 13 -- use FAIL for TS3*/ -/* Bit 12:10 -- ts_out_select, - * 0-TS0, 1-TS1, 2-TS2, 3-TS3,4-S2P2, 5-S2P1, 6-S2P0, 7-File*/ -/* bit 9:8 -- des_i_sel 00 -- select demux0 as des input, -* 01 -- select_demux1, 10 -- select_demux2, 11 - reserved*/ -/* bit 7 -- enable_des_pl*/ -/* bit 6 -- invert fec_error for S2P0*/ -/* bit 5 -- invert fec_data for S2P0*/ -/* bit 4 -- invert fec_sync for S2P0*/ -/* bit 3 -- invert fec_valid for S2P0*/ -/* bit 2 -- invert fec_clk for S2P0*/ -/* bit 1:0 -- fec_s_sel for S2P0 - * 00 - select TS0, 01 -- select TS1, 10 -- select TS2, 11 - reserved*/ -/*#define STB_TOP_CONFIG (STB_CBUS_BASE + 0xf0) // 0x16f0*/ -/*----------- bit define -----------*/ -#define INVERT_S2P1_FEC_ERROR 22 -#define INVERT_S2P1_FEC_DATA 21 -#define INVERT_S2P1_FEC_SYNC 20 -#define INVERT_S2P1_FEC_VALID 19 -#define INVERT_S2P1_FEC_CLK 18 -#define S2P1_FEC_SERIAL_SEL 16 -#define ENABLE_DES_PL_CLK 15 -#define FAIL_TS3 13 -#define TS_OUTPUT_SOURCE 10 -#define DES_INPUT_SEL 8 -#define ENABLE_DES_PL 7 -#define INVERT_S2P0_FEC_ERROR 6 -#define INVERT_S2P0_FEC_DATA 5 -#define INVERT_S2P0_FEC_SYNC 4 -#define INVERT_S2P0_FEC_VALID 3 -#define INVERT_S2P0_FEC_CLK 2 -#define S2P0_FEC_SERIAL_SEL 0 - -//define STB_S2P2_CONFIG -#define S2P2_DISABLE 11 -#define S2P2_CLK_DIV 7 -#define INVERT_S2P2_FEC_ERROR 6 -#define INVERT_S2P2_FEC_DATA 5 -#define INVERT_S2P2_FEC_SYNC 4 -#define INVERT_S2P2_FEC_VALID 3 -#define INVERT_S2P2_FEC_CLK 2 -#define S2P2_FEC_SERIAL_SEL 0 - - -/* 31:24 -- file_m2ts_skip_bytes_hiu1*/ -/* 21 -- ts_hiu_enable_hiu1 */ -/*20:16 -- fec_clk_div_hiu1*/ -/*15:8 -- TS_package_length_sub_1_hiu1 */ -/*7:0 -- fec_sync_byte_hiu1*/ -/*#define TS_HIU1_CONFIG (STB_CBUS_BASE + 0x4e)*/ -#define FILE_M2TS_SKIP_BYTES_HIU1 24 -#define TS_HIU_ENABLE_HIU1 21 -#define FEC_CLK_DIV_HIU1 16 -#define TS_PACKAGE_LENGTH_SUB_1_HIU1 8 -#define FEC_SYNC_BYTE_HIU1 0 - -/*5:4 -- fec_sel_demux_2, default:2*/ -/*3:2 -- fec_sel_demux_1, default:1*/ -/*1:0 -- fec_sel_demux_0, default:0*/ -/*#define TS_TOP_CONFIG1 (STB_CBUS_BASE + 0x4f)*/ -#define FEC_SEL_DEMUX_2 4 -#define FEC_SEL_DEMUX_1 2 -#define FEC_SEL_DEMUX_0 0 - -/* 31:28 - s2p1_clk_div*/ -/* 27:24 - s2p0_clk_div*/ -/* 23 - s2p1_disable*/ -/* 22 - s2p0_disable*/ -/* 21 - Reserved*/ -/* 20 -- TS_OUT_error_INVERT*/ -/* 19 -- TS_OUT_data_INVERT*/ -/* 18 -- TS_OUT_sync_INVERT*/ -/* 17 -- TS_OUT_valid_INVERT*/ -/* 16 -- TS_OUT_clk_INVERT*/ -/* 15:8 -- TS_package_length_sub_1 (default : 187)*/ -/* 7:0 -- fec_sync_byte (default : 0x47)*/ -/*#define TS_TOP_CONFIG (STB_CBUS_BASE + 0xf1) // 0x16f1*/ -/*----------- bit define -----------*/ -#define TS_OUT_CLK_INVERT 16 -#define TS_PACKAGE_LENGTH_SUB_1 8 -#define FEC_DEFAULT_SYNC_BYTE 0 - -/* Bit 25:24 -- transport_scrambling_control_odd_2 // should be 3*/ -/* Bit 23:16 -- file_m2ts_skip_bytes*/ -/* Bit 15:8 -- des_out_dly*/ -/* Bit 7:6 -- transport_scrambling_control_odd // should be 3*/ -/* Bit 5 -- ts_hiu_enable*/ -/* Bit 4:0 -- fec_clk_div*/ -/*#define TS_FILE_CONFIG (STB_CBUS_BASE + 0xf2) // 0x16f2*/ -/*----------- bit define -----------*/ -#define TRANSPORT_SCRAMBLING_CONTROL_ODD_2 24 -#define FILE_M2TS_SKIP_BYTES 16 -#define DES_OUT_DLY 8 -#define TRANSPORT_SCRAMBLING_CONTROL_ODD 6 -#define TS_HIU_ENABLE 5 -#define FEC_FILE_CLK_DIV 0 - -/* Bit 19:14 -- des_2 ts pl state -- Read Only*/ -/* Bit 13:8 -- des ts pl state -- Read Only*/ -/* Bit 3:0 PID index to 8 PID to get key-set*/ -/* auto increse after TS_PL_PID_DATA read/write*/ -/*#define TS_PL_PID_INDEX (STB_CBUS_BASE + 0xf3) // 0x16f3*/ -/*----------- bit define -----------*/ -#define DES_TS_PL_STATE 8 -#define DES_2_TS_PL_STATE 14 - -/* Bit 13 -- PID match disble*/ -/* Bit 12:0 -- PID*/ -/*#define TS_PL_PID_DATA (STB_CBUS_BASE + 0xf4) // 0x16f4*/ -/*----------- bit define -----------*/ -#define PID_MATCH_DISABLE_HIGH 29 -#define PID_MATCH_HIGH 16 -#define PID_MATCH_DISABLE_LOW 13 -#define PID_MATCH_LOW 0 - -/*#define COMM_DESC_KEY0 - * (STB_CBUS_BASE + 0xf5) // 0x16f5 - Common descrambler key (key bits[63:32])*/ -/*#define COMM_DESC_KEY1 - * (STB_CBUS_BASE + 0xf6) // 0x16f6 - Common descrambler key (key bits[31:0])*/ -/*#define COMM_DESC_KEY_RW - * (STB_CBUS_BASE + 0xf7) // 0x16f7 // bits[3:0] - * point to the address to write the key - * {COMM_DESC_KEY3,...,COMM_DESC_KEY0}*/ -/* Writing this register writes the key to RAM*/ - -/* bit 15:8 - des_out_dly_2*/ -/* bit 7 - reserved*/ -/* Bit 6-- enable_des_pl_clk_2*/ -/* bit 5 - enable_des_pl_2*/ -/* bit 4:2 -- use_des_2 bit[2] -- demux0, bit[3] -- demux1, bit[4] -- demux2*/ -/* bit 1:0 -- des_i_sel_2 00 -- select_fec_0, 01 -- select_fec_1, - * 10 -- select_fec_2, 11 - reserved*/ -/*#define COMM_DESC_2_CTL (STB_CBUS_BASE + 0xff) *//*0x16ff*/ - -/*=======================================================*/ -/* Multiple STB Registers (8'h00 - 8'h45)*/ -/*=======================================================*/ -/* STB registers are 8'h0x*/ -/* Bit 15:0 -- version number : 0x0002 (v0.01)*/ -/*#define STB_VERSION - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x00) // 0x1600 // read only*/ -/*#define STB_VERSION_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x00) // 0x1650 // read only*/ -/*#define STB_VERSION_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x00) // 0x16a0 // read only*/ - -/*#define STB_TEST_REG - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x01) // 0x1601*/ -/*#define STB_TEST_REG_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x01) // 0x1651*/ -/*#define STB_TEST_REG_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x01) // 0x16a1*/ - -/* Bit 15 -- fec_core_select 1 - select descramble output*/ -/* Bit 14:12 - fec_select - * 0-TS0, 1-TS1, 2-TS2, 3,4-Reserved, 5-S2P1, 6-S2P0, 7-File*/ -/* Bit 11 -- FEC_CLK*/ -/* Bit 10 -- SOP*/ -/* Bit 9 -- D_VALID*/ -/* Bit 8 -- D_FAIL*/ -/* Bit 7:0 -- D_DATA 7:0*/ -/*#define FEC_INPUT_CONTROL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x02) // 0x1602*/ -/*#define FEC_INPUT_CONTROL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x02) // 0x1652*/ -/*#define FEC_INPUT_CONTROL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x02) // 0x16a2*/ -/*----------- bit define -----------*/ -#define FEC_SEL_3BIT 16 -#define FEC_CORE_SEL 15 -#define FEC_SEL 12 -#define FEC_INPUT_FEC_CLK 11 -#define FEC_INPUT_SOP 10 -#define FEC_INPUT_D_VALID 9 -#define FEC_INPUT_D_FAIL 8 - -/*#define FEC_INPUT_DATA - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x03) // 0x1603 // read only*/ -/*#define FEC_INPUT_DATA_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x03) // 0x1653 // read only*/ -/*#define FEC_INPUT_DATA_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x03) // 0x16a3 // read only*/ - -/* bit 31 -- enable_free_clk_fec_data_valid*/ -/* bit 30 -- enable_free_clk_stb_reg*/ -/* bit 29 -- always_use_pes_package_length*/ -/* bit 28 -- disable_pre_incomplete_section_fix*/ -/* bit 27 -- pointer_field_multi_pre_en*/ -/* bit 26 -- ignore_pre_incomplete_section*/ -/* bit 25 -- video2_enable*/ -/* bit 24:22 -- video2_type*/ -/* bit 21 -- do_not_trust_pes_package_length*/ -/* bit 20 (bit 4) -- Bypass use recoder path*/ -/* bit 19 (bit 3) -- clear_PID_continuity_counter_valid*/ -/* bit 18 (bit 2) -- Disable Splicing*/ -/* bit 17 (bit 1) -- Insert PES_STRONG_SYNC in Audio PES*/ -/* bit 16 (bit 0) -- Insert PES_STRONG_SYNC in Video PES*/ -/* Bit 15 - do not trust section length*/ -/* Bit 14 - om cmd push even zero*/ -/* Bit 13 - reserved*/ -/* Bit 12 - SUB, OTHER PES interrupt at beginning of PES*/ -/* Bit 11 - discard_av_package -- for ts_recorder use only*/ -/* Bit 10 - ts_recorder_select 0:after PID filter 1:before PID filter*/ -/* Bit 9 - ts_recorder_enable*/ -/* Bit 8 - (table_id == 0xff) means section_end*/ -/* Bit 7 - do not send uncomplete section*/ -/* Bit 6 - do not discard duplicate package*/ -/* Bit 5 - search SOP when trasport_error_indicator*/ -/* Bit 4 - stb demux enable*/ -/* Bit 3 - do not reset state machine on SOP*/ -/* Bit 2 - search SOP when error happened - * ( when ignore_fail_n_sop, will have this case)*/ -/* Bit 1 - do not use SOP input ( check FEC sync byte instead )*/ -/* Bit 0 - ignore fec_error bit when non sop ( check error on SOP only)*/ -/*#define DEMUX_CONTROL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x04) // 0x1604*/ -/*#define DEMUX_CONTROL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x04) // 0x1654*/ -/*#define DEMUX_CONTROL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x04) // 0x16a4*/ -/*----------- bit define -----------*/ -#define ENABLE_FREE_CLK_FEC_DATA_VALID 31 -#define ENABLE_FREE_CLK_STB_REG 30 -#define BYPASS_USE_RECODER_PATH 20 -#define CLEAR_PID_CONTINUITY_COUNTER_VALID 19 -#define DISABLE_SPLICING 18 -#define INSERT_AUDIO_PES_STRONG_SYNC 17 -#define INSERT_VIDEO_PES_STRONG_SYNC 16 -#define SECTION_LENGTH_UNTRUSTY 15 -#define OM_CMD_PUSH_EVEN_ZERO 14 -#define OTHER_INT_AT_PES_BEGINING 12 -#define DISCARD_AV_PACKAGE 11 -#define TS_RECORDER_SELECT 10 -#define TS_RECORDER_ENABLE 9 -#define SECTION_END_WITH_TABLE_ID 8 -#define SEND_COMPLETE_SECTION_ONLY 7 -#define KEEP_DUPLICATE_PACKAGE 6 -#define SEACH_SOP_ON_TRANSPORT_ERROR 5 -#define STB_DEMUX_ENABLE 4 -#define NO_RESET_ON_SOP 3 -#define SEARCH_SOP_ON_ERROR 2 -#define NOT_USE_OF_SOP_INPUT 1 -#define IGNORE_NONSOP_FEC_ERROR 0 - -/* bit 15:8 demux package length - 1 ( default : 187 )*/ -/* bit 7:0 default is 0x47*/ -/*#define FEC_SYNC_BYTE - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x05) // 0x1605*/ -/*#define FEC_SYNC_BYTE_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x05) // 0x1655*/ -/*#define FEC_SYNC_BYTE_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x05) // 0x16a5*/ - -/**************************************** - * FM Memory Usage : - * 0-15 (32 PID filter target) ---- 15:13-PID type 12:0-PID target or force data - * (force data : 1 will mask corespoding bit, - * 0 will disable this PID filter channel) - * advanced setting -- bit 7:0 - * bit 7 -- PID bit 12:11 compare result force - * bit 6 -- PID bit 10:9 compare result force - * bit 5 -- PID bit 8:7 compare result force - * bit 4 -- PID bit 6:5 compare result force - * bit 3 -- PID bit 4:3 compare result force - * bit 2 -- PID bit 2 compare result force - * bit 1 -- PID bit 1 compare result force - * bit 0 -- PID bit 0 compare result force - * 16-255(15x32 Section filter target) - * For first byte : Table_ID - * ---- 15-Mask High 4-bits - * 14-Mask Low 4-bits - * 13-disable_PID_check - * 12:8-PIDindex - * 7:0-section target (always EQ) - * For rest of bytes : - * ---- 15-Mask 14-EQ/NE 13-disable_PID_check - * ----12:8-PIDindex 7:0-section target (or force data) - * advanced setting -- bit 7:0 force compare result - **************************************************/ -/*----------- bit define -----------*/ -#define PID_TYPE 13 -#define PID_TARGET 0 - -#define SECTION_FIRSTBYTE_MASKHIGH 15 -#define SECTION_FIRSTBYTE_MASKLOW 14 -#define SECTION_FIRSTBYTE_DISABLE_PID_CHECK 13 -#define SECTION_FIRSTBYTE_PID_INDEX 8 -#define SECTION_TARGET 0 - -#define SECTION_RESTBYTE_MASK 15 -#define SECTION_RESTBYTE_MASK_EQ 14 -#define SECTION_RESTBYTE_DISABLE_PID_CHECK 13 -#define SECTION_RESTBYTE_PID_INDEX 8 - -/* bit 31:16 -- filter memory write data hi[31:16]*/ -/* bit 15:0 -- filter memory write data low [15:0]*/ -/*#define FM_WR_DATA - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x06) // 0x1606*/ -/*#define FM_WR_DATA_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x06) // 0x1656*/ -/*#define FM_WR_DATA_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x06) // 0x16a6*/ -/*----------- bit define -----------*/ -#define FM_WR_DATA_HI 16 - -/* bit 31:24 -- advanced setting hi*/ -/* bit 23:16 -- advanced setting low*/ -/* bit 15 -- filter memory write data request*/ -/* bit 7:0 -- filter memory write addr*/ -/*#define FM_WR_ADDR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x07) // 0x1607*/ -/*#define FM_WR_ADDR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x07) // 0x1657*/ -/*#define FM_WR_ADDR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x07) // 0x16a7*/ -/*----------- bit define -----------*/ -#define FM_ADVANCED_SETTING_HI 24 -#define FM_ADVANCED_SETTING_LO 16 -#define FM_WR_DATA_REQUEST 15 - -/* bit 13:8 demux state -- read only*/ -/* bit 7:4 -- maxnum section filter compare address*/ -/* bit 3:0 -- maxnum PID filter compare address*/ -/*#define MAX_FM_COMP_ADDR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x08) // 0x1608*/ -/*#define MAX_FM_COMP_ADDR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x08) // 0x1658*/ -/*#define MAX_FM_COMP_ADDR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x08) // 0x16a8*/ -/*----------- bit define -----------*/ -#define DEMUX_STATE 8 -#define MAX_FM_SECTION_FILTER_COMP_ADDR 4 - -/* bit 15 - transport_error_indicator*/ -/* bit 14 - payload_unit_start_indicator*/ -/* bit 13 - transport_priority*/ -/* bit 12:0 - PID*/ -/*#define TS_HEAD_0 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x09) // 0x1609*/ -/*#define TS_HEAD_0_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x09) // 0x1659*/ -/*#define TS_HEAD_0_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x09) // 0x16a9*/ -/*----------- bit define -----------*/ -#define TRANSPORT_ERROR_INDICATOR 15 -#define PAYLOAD_UNIT_START_INDICATOR 14 -#define TRANSPORT_PRIORITY 13 - -/* bit 7:6 transport_scrambling_control*/ -/* bit 5:4 adaptation_field_control*/ -/* bit 3:0 continuity_counter*/ -/*#define TS_HEAD_1 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x0a) // 0x160a*/ -/*#define TS_HEAD_1_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x0a) // 0x165a*/ -/*#define TS_HEAD_1_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x0a) // 0x16aa*/ -/*----------- bit define -----------*/ -#define TRANSPORT_SCRAMBLING_CONTROL 6 -#define ADAPTATION_FIELD_CONTROL 4 - -/* bit 15:12 -- om_cmd_count (read only)*/ -/* bit 11:9 -- overflow_count // bit 11:9 -- om_cmd_wr_ptr (read only)*/ -/* bit 8:6 -- om_overwrite_count // bit 8:6 -- om_cmd_rd_ptr (read only)*/ -/* bit 5:3 -- type_stb_om_w_rd (read only)*/ -/* bit 2 -- unit_start_stb_om_w_rd (read only)*/ -/* bit 1 -- om_cmd_overflow (read only)*/ -/* bit 0 -- om_cmd_pending (read)*/ -/* bit 0 -- om_cmd_read_finished (write)*/ -/*#define OM_CMD_STATUS - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x0b) // 0x160b*/ -/*#define OM_CMD_STATUS_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x0b) // 0x165b*/ -/*#define OM_CMD_STATUS_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x0b) // 0x16ab*/ -/*----------- bit define -----------*/ -#define OM_CMD_COUNT 12 -#define OM_OVERFLOW_COUNT 9 -#define OM_OVERWRITE_COUNT 6 -#define TYPE_STB_OM_W_RD 3 -#define UNIT_START_STB_OM_W_RD 2 -#define OM_CMD_OVERFLOW 1 - -/* bit 15:9 -- count_stb_om_w_rd (read only)*/ -/* bit 8:0 -- start_stb_om_wa_rd (read only)*/ -/*#define OM_CMD_DATA - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x0c) // 0x160c*/ -/*#define OM_CMD_DATA_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x0c) // 0x165c*/ -/*#define OM_CMD_DATA_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x0c) // 0x16ac*/ -/*----------- bit define -----------*/ -#define COUNT_STB_OM_W_RD 9 - -/* bit 11:0 -- offset for section data*/ -/*#define OM_CMD_DATA2 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x0d) // 0x160d*/ -/*#define OM_CMD_DATA2_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x0d) // 0x165d*/ -/*#define OM_CMD_DATA2_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x0d) // 0x16ad*/ - -/* bit 31:16 -- base address for section buffer group 0 - * (*0x400 to get real address)*/ -/* bit 15:0 -- base address for section buffer group 1 - * (*0x400 to get real address)*/ -/*#define SEC_BUFF_01_START - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x0e) // 0x160e*/ -/*#define SEC_BUFF_01_START_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x0e) // 0x165e*/ -/*#define SEC_BUFF_01_START_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x0e) // 0x16ae*/ -/*----------- bit define -----------*/ -#define SEC_BUFF_0_BASE_ADDR 16 - -/* bit 31:16 -- base address for section buffer group 2 - * (*0x400 to get real address)*/ -/* bit 15:0 -- base address for section buffer group 3 - * (*0x400 to get real address)*/ -/*#define SEC_BUFF_23_START - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x0f) // 0x160f*/ -/*#define SEC_BUFF_23_START_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x0f) // 0x165f*/ -/*#define SEC_BUFF_23_START_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x0f) // 0x16af*/ -/*----------- bit define -----------*/ -#define SEC_BUFF_2_BASE_ADDR 16 - -/* bit 15:12 -- section buffer size for group 3*/ -/* bit 11:8 -- section buffer size for group 2*/ -/* bit 7:4 -- section buffer size for group 1*/ -/* bit 3:0 -- section buffer size for group 0 - * (bit used, for example, 10 means 1K)*/ -/*#define SEC_BUFF_SIZE - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x10) // 0x1610*/ -/*#define SEC_BUFF_SIZE_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x10) // 0x1660*/ -/*#define SEC_BUFF_SIZE_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x10) // 0x16b0*/ -/*----------- bit define -----------*/ -#define SEC_BUFF_3_SIZE 12 -#define SEC_BUFF_2_SIZE 8 -#define SEC_BUFF_1_SIZE 4 - -/* section buffer busy status for buff 31:0 ( Read Only )*/ -/*#define SEC_BUFF_BUSY - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x11) // 0x1611*/ -/*#define SEC_BUFF_BUSY_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x11) // 0x1661*/ -/*#define SEC_BUFF_BUSY_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x11) // 0x16b1*/ - -/* section buffer write status for buff 31:0 -- Read*/ -/* clear buffer status ( buff READY and BUSY ) -- write*/ -/*#define SEC_BUFF_READY - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x12) // 0x1612*/ -/*#define SEC_BUFF_READY_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x12) // 0x1662*/ -/*#define SEC_BUFF_READY_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x12) // 0x16b2*/ - -/* bit 15 -- section_reset_busy (Read Only)*/ -/* bit 14 -- output_section_buffer_valid*/ -/* bit 12:8 -- SEC_BUFFER_NUMBER for the INDEX buffer Read_Only*/ -/* bit 4:0 -- SEC_BUFFER_INDEX RW*/ -/*#define SEC_BUFF_NUMBER - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x13) // 0x1613*/ -/*#define SEC_BUFF_NUMBER_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x13) // 0x1663*/ -/*#define SEC_BUFF_NUMBER_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x13) // 0x16b3*/ -/*----------- bit define -----------*/ -#define SECTION_RESET_BUSY 15 -#define OUTPUT_SECTION_BUFFER_VALID 14 -#define INDEXED_SEC_BUFF_NUMBER 8 - -/* bit 9:5 -- BYPASS PID number*/ -/* bit 4:0 -- PCR PID number*/ -/*#define ASSIGN_PID_NUMBER - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x14) // 0x1614*/ -/*#define ASSIGN_PID_NUMBER_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x14) // 0x1664*/ -/*#define ASSIGN_PID_NUMBER_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x14) // 0x16b4*/ -/*----------- bit define -----------*/ -#define BYPASS_PID_NUMBER 5 - -/* bit 15:0 -- stream_id filter bit enable*/ -/* bit 7:0 -- stream_id filter target*/ -/*#define VIDEO_STREAM_ID - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x15) // 0x1615*/ -/*#define VIDEO_STREAM_ID_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x15) // 0x1665*/ -/*#define VIDEO_STREAM_ID_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x15) // 0x16b5*/ - -/*#define AUDIO_STREAM_ID - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x16) // 0x1616*/ -/*#define AUDIO_STREAM_ID_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x16) // 0x1666*/ -/*#define AUDIO_STREAM_ID_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x16) // 0x16b6*/ - -/*#define SUB_STREAM_ID - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x17) // 0x1617*/ -/*#define SUB_STREAM_ID_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x17) // 0x1667*/ -/*#define SUB_STREAM_ID_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x17) // 0x16b7*/ - -/*#define OTHER_STREAM_ID - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x18) // 0x1618*/ -/*#define OTHER_STREAM_ID_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x18) // 0x1668*/ -/*#define OTHER_STREAM_ID_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x18) // 0x16b8*/ - -/* bit 12 -- PCR_EN*/ -/* bit 11:0 -- PCR90K_DIV*/ -/*#define PCR90K_CTL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x19) // 0x1619*/ -/*#define PCR90K_CTL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x19) // 0x1669*/ -/*#define PCR90K_CTL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x19) // 0x16b9*/ -/*----------- bit define -----------*/ -#define PCR_EN 12 - -/* bit 15:0 -- PCR[31:0] R/W*/ -/*#define PCR_DEMUX - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x1a) // 0x161a*/ -/*#define PCR_DEMUX_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x1a) // 0x166a*/ -/*#define PCR_DEMUX_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x1a) // 0x16ba*/ - -/* bit 15:0 -- VPTS[31:0] R/W*/ -/*#define VIDEO_PTS_DEMUX - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x1b) // 0x161b*/ -/*#define VIDEO_PTS_DEMUX_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x1b) // 0x166b*/ -/*#define VIDEO_PTS_DEMUX_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x1b) // 0x16bb*/ - -/* bit 15:0 -- VDTS[31:0] R/W*/ -/*#define VIDEO_DTS_DEMUX - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x1c) // 0x161c*/ -/*#define VIDEO_DTS_DEMUX_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x1c) // 0x166c*/ -/*#define VIDEO_DTS_DEMUX_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x1c) // 0x16bc*/ - -/* bit 15:0 -- APTS[31:0] R/W*/ -/*#define AUDIO_PTS_DEMUX - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x1d) // 0x161d*/ -/*#define AUDIO_PTS_DEMUX_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x1d) // 0x166d*/ -/*#define AUDIO_PTS_DEMUX_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x1d) // 0x16bd*/ - -/* bit 15:0 -- SPTS[31:0] R/W*/ -/*#define SUB_PTS_DEMUX - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x1e) // 0x161e*/ -/*#define SUB_PTS_DEMUX_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x1e) // 0x166e*/ -/*#define SUB_PTS_DEMUX_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x1e) // 0x16be*/ - -/* read -- status, write 1 clear status*/ -/* bit 15 -- SUB_PTS[32]*/ -/* bit 14 -- AUDIO_PTS[32]*/ -/* bit 13 -- VIDEO_DTS[32]*/ -/* bit 12 -- VIDEO_PTS[32]*/ -/* bit 3 -- sub_pts_ready*/ -/* bit 2 -- audio_pts_ready*/ -/* bit 1 -- video_dts_ready*/ -/* bit 0 -- video_pts_ready*/ -/*#define STB_PTS_DTS_STATUS - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x1f) // 0x161f*/ -/*#define STB_PTS_DTS_STATUS_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x1f) // 0x166f*/ -/*#define STB_PTS_DTS_STATUS_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x1f) // 0x16bf*/ -/*----------- bit define -----------*/ -#define SUB_PTS_BIT32 15 -#define AUDIO_PTS_BIT32 14 -#define VIDEO_DTS_BIT32 13 -#define VIDEO_PTS_BIT32 12 -#define SUB_PTS_READY 3 -#define AUDIO_PTS_READY 2 -#define VIDEO_DTS_READY 1 -#define VIDEO_PTS_READY 0 - -/* bit 3:0 --*/ -/* 0 -- adaptation_field_length[7:0], adaption_field_byte_1[7:0]*/ -/* 1 -- stream_id[7:0], pes_header_bytes_left[7:0]*/ -/* 2 -- pes_package_bytes_left[15:0]*/ -/* 3 -- pes_ctr_byte[7:0], pes_flag_byte[7:0]*/ -/*#define STB_DEBUG_INDEX - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x20) // 0x1620*/ -/*#define STB_DEBUG_INDEX_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x20) // 0x1670*/ -/*#define STB_DEBUG_INDEX_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x20) // 0x16c0*/ - -/* read only*/ -/*#define STB_DEBUG_DATA_OUT - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x21) // 0x1621*/ -/*#define STB_DEBUG_DATA_OUT_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x21) // 0x1671*/ -/*#define STB_DEBUG_DATA_OUT_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x21) // 0x16c1*/ - -/* bit[31] -- no_match_record_en*/ -/* bit[30:16] - reserved*/ -/* default : 0x807f*/ -/* bit 15:9 -- MAX OM DMA COUNT (default: 0x40)*/ -/* bit 8:0 -- LAST ADDR OF OM ADDR (default: 127)*/ -/*#define STB_OM_CTL \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x22) // 0x1622*/ -/*#define STB_OM_CTL_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x22) // 0x1672*/ -/*#define STB_OM_CTL_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x22) // 0x16c2*/ -/*----------- bit define -----------*/ -#define MAX_OM_DMA_COUNT 9 -#define LAST_OM_ADDR 0 - -/* 15:0 WRITE 1 CLEAR to clear interrupt source*/ -/*12 -- INPUT_TIME_OUT*/ -/*11 -- PCR_ready*/ -/*10 -- audio_splicing_point*/ -/* 9 -- video_splicing_point*/ -/* 8 -- other_PES_int*/ -/* 7 -- sub_PES_int*/ -/* 6 -- discontinuity*/ -/* 5 -- duplicated_pack_found*/ -/* 4 -- New PDTS ready*/ -/* 3 -- om_cmd_buffer ready for access*/ -/* 2 -- section buffer ready*/ -/* 1 -- transport_error_indicator*/ -/* 0 -- TS ERROR PIN*/ -/*#define STB_INT_STATUS - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x23) // 0x1623*/ -/*#define STB_INT_STATUS_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x23) // 0x1673*/ -/*#define STB_INT_STATUS_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x23) // 0x16c3*/ -/*----------- bit define -----------*/ -#define INPUT_TIME_OUT 12 -#define PCR_READY 11 -#define AUDIO_SPLICING_POINT 10 -#define VIDEO_SPLICING_POINT 9 -#define OTHER_PES_READY 8 -#define SUB_PES_READY 7 -#define DIS_CONTINUITY_PACKET 6 -#define DUPLICATED_PACKET 5 -#define NEW_PDTS_READY 4 -#define OM_CMD_READ_PENDING 3 -#define SECTION_BUFFER_READY 2 -#define TS_ERROR_PACKAGE 1 -#define TS_ERROR_PIN 0 - -/* When Bit 31 - 1 write will indicate all type use sepertate endian - * (Write Only)*/ -/* When Bit 31 - 0 write will indicate all type else use Bit 8:6*/ -/* Bit 23:21 - demux om write endian control for OTHER_PES_PACKET*/ -/* Bit 20:18 - demux om write endian control for SCR_ONLY_PACKET*/ -/* Bit 17:15 - demux om write endian control for SUB_PACKET*/ -/* Bit 14:12 - demux om write endian control for AUDIO_PACKET*/ -/* Bit 11:9 - demux om write endian control for VIDEO_PACKET*/ -/* Bit 8:6 - demux om write endian control for else*/ -/* Bit 5:3 - demux om write endian control for bypass*/ -/* Bit 2:0 - demux om write endian control for section*/ -/*#define DEMUX_ENDIAN - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x24) // 0x1624*/ -/*#define DEMUX_ENDIAN_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x24) // 0x1674*/ -/*#define DEMUX_ENDIAN_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x24) // 0x16c4*/ -/*----------- bit define -----------*/ -#define SEPERATE_ENDIAN 31 -#define OTHER_PES_ENDIAN 21 -#define SCR_ENDIAN 18 -#define SUB_ENDIAN 15 -#define AUDIO_ENDIAN 12 -#define VIDEO_ENDIAN 9 -#define OTHER_ENDIAN 6 -#define BYPASS_ENDIAN 3 -#define SECTION_ENDIAN 0 - -/* Bit 10:9 -- PDTS_wr_sel: 0 select video_PDTS_wr_ptr; 1 select video_PDTS_wr_ptr_parser_B; */ -/* Bit 7:8 -- use hi_bsf interface*/ -/* Bit 6:2 - fec_clk_div*/ -/* Bit 1 ts_source_sel */ -/* Bit 0 - Hiu TS generate enable */ -/*#define TS_HIU_CTL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x25) // 0x1625*/ -/*#define TS_HIU_CTL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x25) // 0x1675*/ -/*#define TS_HIU_CTL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x25) // 0x16c5*/ -/*----------- bit define -----------*/ -//#define LAST_BURST_THRESHOLD 8 -#define PDTS_WR_SEL 9 -#define USE_HI_BSF_INTERFACE 7 - -/* bit 15:0 -- base address for section buffer start - * (*0x10000 to get real base)*/ -/*#define SEC_BUFF_BASE - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x26) // 0x1626*/ -/*#define SEC_BUFF_BASE_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x26) // 0x1676*/ -/*#define SEC_BUFF_BASE_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x26) // 0x16c6*/ - -/* bit 11 -- mask bit for OTHER_PES_AHB_DMA_EN*/ -/* bit 10 -- mask bit for SUB_AHB_DMA_EN*/ -/* bit 9 -- mask bit for BYPASS_AHB_DMA_EN*/ -/* bit 8 -- mask bit for SECTION_AHB_DMA_EN*/ -/* bit 7 -- mask bit for recoder stream*/ -/* bit 6:0 -- mask bit for each type*/ -/*#define DEMUX_MEM_REQ_EN - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x27) // 0x1627*/ -/*#define DEMUX_MEM_REQ_EN_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x27) // 0x1677*/ -/*#define DEMUX_MEM_REQ_EN_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x27) // 0x16c7*/ -/*----------- bit define -----------*/ -#define VIDEO2_DMA_EN_BIT 12 -#define OTHER_PES_AHB_DMA_EN 11 -#define SUB_AHB_DMA_EN 10 -#define BYPASS_AHB_DMA_EN 9 -#define SECTION_AHB_DMA_EN 8 -#define RECORDER_STREAM 7 -#define OTHER_PES_PACKET 6 -#define SCR_ONLY_PACKET 5 /*will never be used*/ -#define BYPASS_PACKET 4 -#define SECTION_PACKET 3 -#define SUB_PACKET 2 -#define AUDIO_PACKET 1 -#define VIDEO_PACKET 0 - -/* bit 31:0 -- vb_wr_ptr for video PDTS*/ -/*#define VIDEO_PDTS_WR_PTR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x28) // 0x1628*/ -/*#define VIDEO_PDTS_WR_PTR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x28) // 0x1678*/ -/*#define VIDEO_PDTS_WR_PTR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x28) // 0x16c8*/ - -/* bit 31:0 -- ab_wr_ptr for audio PDTS*/ -/*#define AUDIO_PDTS_WR_PTR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x29) // 0x1629*/ -/*#define AUDIO_PDTS_WR_PTR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x29) // 0x1679*/ -/*#define AUDIO_PDTS_WR_PTR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x29) // 0x16c9*/ - -/* bit 20:0 -- SB_WRITE_PTR (sb_wr_ptr << 3 == byte write position)*/ -/*#define SUB_WR_PTR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x2a) // 0x162a*/ -/*#define SUB_WR_PTR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x2a) // 0x167a*/ -/*#define SUB_WR_PTR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x2a) // 0x16ca*/ - -/* bit 19:0 -- SB_START (sb_start << 12 == byte address);*/ -/*#define SB_START - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x2b) // 0x162b*/ -/*#define SB_START_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x2b) // 0x167b*/ -/*#define SB_START_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x2b) // 0x16cb*/ - -/* bit 20:0 -- SB_SIZE (sb_size << 3 == byte size, 16M maximun)*/ -/*#define SB_LAST_ADDR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x2c) // 0x162c*/ -/*#define SB_LAST_ADDR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x2c) // 0x167c*/ -/*#define SB_LAST_ADDR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x2c) // 0x16cc*/ - -/* bit 31:0 -- sb_wr_ptr for sub PES*/ -/*#define SB_PES_WRITE_PTR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x2d) // 0x162d*/ -/*#define SB_PES_WRITE_PTR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x2d) // 0x167d*/ -/*#define SB_PES_WRITE_PTR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x2d) // 0x16cd*/ - -/* bit 31:16 -- ob_wr_ptr for other PES*/ -/* bit 20:0 -- OB_WRITE_PTR (ob_wr_ptr << 3 == byte write position)*/ -/*#define OTHER_WR_PTR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x2e) // 0x162e*/ -/*#define OTHER_WR_PTR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x2e) // 0x167e*/ -/*#define OTHER_WR_PTR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x2e) // 0x16ce*/ - -/* bit 19:0 -- OB_START (ob_start << 12 == byte address);*/ -/*#define OB_START - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x2f) // 0x162f*/ -/*#define OB_START_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x2f) // 0x167f*/ -/*#define OB_START_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x2f) // 0x16cf*/ - -/* bit 20:0 -- OB_SIZE (ob_size << 3 == byte size, 16M maximun)*/ -/*#define OB_LAST_ADDR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x30) // 0x1630*/ -/*#define OB_LAST_ADDR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x30) // 0x1680*/ -/*#define OB_LAST_ADDR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x30) // 0x16d0*/ - -/* bit 31:0 -- ob_wr_ptr for sub PES*/ -/*#define OB_PES_WRITE_PTR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x31) // 0x1631*/ -/*#define OB_PES_WRITE_PTR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x31) // 0x1681*/ -/*#define OB_PES_WRITE_PTR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x31) // 0x16d1*/ - -/* 15:0 DEMUX interrupt MASK*/ -/* 11 -- PCR_READY*/ -/* 10 -- audio_splicing_point*/ -/* 9 -- video_splicing_point*/ -/* 8 -- other_PES_int*/ -/* 7 -- sub_PES_int*/ -/* 6 -- discontinuity*/ -/* 5 -- duplicated_pack_found*/ -/* 4 -- New PDTS ready*/ -/* 3 -- om_cmd_buffer ready for access*/ -/* 2 -- section buffer ready*/ -/* 1 -- transport_error_indicator*/ -/* 0 -- TS ERROR PIN*/ -/*#define STB_INT_MASK - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x32) // 0x1632*/ -/*#define STB_INT_MASK_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x32) // 0x1682*/ -/*#define STB_INT_MASK_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x32) // 0x16d2*/ - -/* 31:16 VIDEO PID filter data*/ -/*15 -- splicing VIDEO PID change enable*/ -/*14:10 -- VIDEO PID FILTER ADDRESS*/ -/* 9 -- PES splicing active (Read Only)*/ -/* 8 -- splicing active (Read Only)*/ -/* 7:0 splicing countdown (Read Only)*/ -/*#define VIDEO_SPLICING_CTL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x33) // 0x1633*/ -/*#define VIDEO_SPLICING_CTL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x33) // 0x1683*/ -/*#define VIDEO_SPLICING_CTL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x33) // 0x16d3*/ -/*----------- bit define -----------*/ -#define VIDEO_PID_FILTER_DATA 16 -#define VIDEO_SPLICING_PID_CHANGE_ENABLE 15 -#define VIDEO_PID_FILTER_ADDRESS 10 -#define VIDEO_PES_SPLICING_ACTIVE 9 -#define VIDEO_SPLICING_ACTIVE 8 - - -/* 31:16 AUDIO PID filter data*/ -/*15 -- splicing AUDIO PID change enable*/ -/*14:10 -- AUDIO PID FILTER ADDRESS*/ -/* 9 -- PES splicing active (Read Only)*/ -/* 8 -- splicing active (Read Only)*/ -/* 7:0 splicing countdown (Read Only)*/ -/*#define AUDIO_SPLICING_CTL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x34) // 0x1634*/ -/*#define AUDIO_SPLICING_CTL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x34) // 0x1684*/ -/*#define AUDIO_SPLICING_CTL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x34) // 0x16d4*/ -/*----------- bit define -----------*/ -#define AUDIO_PID_FILTER_DATA 16 -#define AUDIO_SPLICING_PID_CHANGE_ENABLE 15 -#define AUDIO_PID_FILTER_ADDRESS 10 -#define AUDIO_PES_SPLICING_ACTIVE 9 -#define AUDIO_SPLICING_ACTIVE 8 - -/* 23:16 M2TS_SKIP_BYTES*/ -/* 15:8 LAST TS PACKAGE BYTE COUNT (Read Only)*/ -/* 7:0 PACKAGE BYTE COUNT (Read Only)*/ -/*#define TS_PACKAGE_BYTE_COUNT - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x35) // 0x1635*/ -/*#define TS_PACKAGE_BYTE_COUNT_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x35) // 0x1685*/ -/*#define TS_PACKAGE_BYTE_COUNT_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x35) // 0x16d5*/ -/*----------- bit define -----------*/ -#define M2TS_SKIP_BYTES 16 -#define LAST_TS_PACKAGE_BYTE_COUNT 8 - -/* 15:0 2 bytes strong sync add to PES*/ -/*#define PES_STRONG_SYNC - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x36) // 0x1636*/ -/*#define PES_STRONG_SYNC_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x36) // 0x1686*/ -/*#define PES_STRONG_SYNC_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x36) // 0x16d6*/ - -/* bit 15 -- stb_om_ren*/ -/* bit 14:11 -- reserved*/ -/* bit 10:0 -- OM_DATA_RD_ADDR*/ -/*#define OM_DATA_RD_ADDR - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x37) // 0x1637*/ -/*#define OM_DATA_RD_ADDR_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x37) // 0x1687*/ -/*#define OM_DATA_RD_ADDR_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x37) // 0x16d7*/ -/*----------- bit define -----------*/ -#define STB_OM_REN 15 - -/* bit 15:0 -- OM_DATA_RD*/ -/*#define OM_DATA_RD - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x38) // 0x1638*/ -/*#define OM_DATA_RD_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x38) // 0x1688*/ -/*#define OM_DATA_RD_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x38) // 0x16d8*/ - -/* AUTO STOP SETTING for 32 channels*/ -/* 4-bits per channel*/ -/* when write*/ -/* bit 3 -- set section active*/ -/* bit 2:0 -- auto stop after count (0 means never stop)*/ -/* when read*/ -/* bit 3 -- current active status (1 - active, 0 - stopped )*/ -/* bit 2:0 -- count down to auto stop*/ -/* section 31:24*/ -/*#define SECTION_AUTO_STOP_3 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x39) // 0x1639*/ -/*#define SECTION_AUTO_STOP_3_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x39) // 0x1689*/ -/*#define SECTION_AUTO_STOP_3_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x39) // 0x16d9*/ -/* section 23:16*/ -/*#define SECTION_AUTO_STOP_2 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x3a) // 0x163a*/ -/*#define SECTION_AUTO_STOP_2_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x3a) // 0x168a*/ -/*#define SECTION_AUTO_STOP_2_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x3a) // 0x16da*/ -/* section 15:8*/ -/*#define SECTION_AUTO_STOP_1 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x3b) // 0x163b*/ -/*#define SECTION_AUTO_STOP_1_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x3b) // 0x168b*/ -/*#define SECTION_AUTO_STOP_1_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x3b) // 0x16db*/ -/* section 7:0*/ -/*#define SECTION_AUTO_STOP_0 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x3c) // 0x163c*/ -/*#define SECTION_AUTO_STOP_0_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x3c) // 0x168c*/ -/*#define SECTION_AUTO_STOP_0_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x3c) // 0x16dc*/ - -/* bit 31:0 reset channel status - each bit reset each channel*/ -/* read -- 32 channel status*/ -/*#define DEMUX_CHANNEL_RESET - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x3d) // 0x163d*/ -/*#define DEMUX_CHANNEL_RESET_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x3d) // 0x168d*/ -/*#define DEMUX_CHANNEL_RESET_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x3d) // 0x16dd*/ - -/*#define DEMUX_SCRAMBLING_STATE - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x3e) // 0x163e*/ -/*#define DEMUX_SCRAMBLING_STATE_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x3e) // 0x168e*/ -/*#define DEMUX_SCRAMBLING_STATE_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x3e) // 0x16de*/ - -/*#define DEMUX_CHANNEL_ACTIVITY - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x3f) // 0x163f*/ -/*#define DEMUX_CHANNEL_ACTIVITY_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x3f) // 0x168f*/ -/*#define DEMUX_CHANNEL_ACTIVITY_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x3f) // 0x16df*/ - -/* bit 4 -- video_stamp_use_dts*/ -/* bit 3 -- audio_stamp_sync_1_en*/ -/* bit 2 -- audio_stamp_insert_en*/ -/* bit 1 -- video_stamp_sync_1_en*/ -/* bit 0 -- video_stamp_insert_en*/ -/*#define DEMUX_STAMP_CTL - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x40) // 0x1640*/ -/*#define DEMUX_STAMP_CTL_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x40) // 0x1690*/ -/*#define DEMUX_STAMP_CTL_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x40) // 0x16e0*/ - -/*#define DEMUX_VIDEO_STAMP_SYNC_0 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x41) // 0x1641*/ -/*#define DEMUX_VIDEO_STAMP_SYNC_0_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x41) // 0x1691*/ -/*#define DEMUX_VIDEO_STAMP_SYNC_0_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x41) // 0x16e1*/ - -/*#define DEMUX_VIDEO_STAMP_SYNC_1 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x42) // 0x1642*/ -/*#define DEMUX_VIDEO_STAMP_SYNC_1_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x42) // 0x1692*/ -/*#define DEMUX_VIDEO_STAMP_SYNC_1_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x42) // 0x16e2*/ - -/*#define DEMUX_AUDIO_STAMP_SYNC_0 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x43) // 0x1643*/ -/*#define DEMUX_AUDIO_STAMP_SYNC_0_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x43) // 0x1693*/ -/*#define DEMUX_AUDIO_STAMP_SYNC_0_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x43) // 0x16e3*/ - -/*#define DEMUX_AUDIO_STAMP_SYNC_1 - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x44) // 0x1644*/ -/*#define DEMUX_AUDIO_STAMP_SYNC_1_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x44) // 0x1694*/ -/*#define DEMUX_AUDIO_STAMP_SYNC_1_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x44) // 0x16e4*/ - -/* Write : Bit[4:0] secter filter number for reset*/ -/* Read : select according to output_section_buffer_valid :*/ -/* per bit per section buffer valid status*/ -/* or section_buffer_ignore*/ -/*#define DEMUX_SECTION_RESET - * (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x45) // 0x1645*/ -/*#define DEMUX_SECTION_RESET_2 - * (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x45) // 0x1695*/ -/*#define DEMUX_SECTION_RESET_3 - * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x45) // 0x16e5*/ - - -/* bit[31:0] - channel_reset_timeout_disable*/ -/*#define DEMUX_INPUT_TIMEOUT_C \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x46) // 0x1646*/ -/*#define DEMUX_INPUT_TIMEOUT_C_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x46) // 0x1696*/ -/*#define DEMUX_INPUT_TIMEOUT_C_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x46) // 0x16e6*/ -/* bit[31] - no_match_reset_timeout_disable*/ -/* bit[30:0] input_time_out_int_cnt (0 -- means disable) Wr-setting, Rd-count*/ -/*#define DEMUX_INPUT_TIMEOUT \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x47) // 0x1647*/ -/*#define DEMUX_INPUT_TIMEOUT_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x47) // 0x1697*/ -/*#define DEMUX_INPUT_TIMEOUT_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x47) // 0x16e7*/ - -/* bit[31:0] - channel_packet_count_disable*/ -/*#define DEMUX_PACKET_COUNT_C \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x48) // 0x1648*/ -/*#define DEMUX_PACKET_COUNT_C_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x48) // 0x1698*/ -/*#define DEMUX_PACKET_COUNT_C_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x48)*/ /* 0x16e8*/ -/* bit[31] - no_match_packet_count_disable*/ -/* bit[30:0] input_packet_count*/ -/*#define DEMUX_PACKET_COUNT \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x49) // 0x1649*/ -/*#define DEMUX_PACKET_COUNT_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x49) // 0x1699*/ -/*#define DEMUX_PACKET_COUNT_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x49) // 0x16e9*/ - -/* bit[31:0] channel_record_enable*/ -/*#define DEMUX_CHAN_RECORD_EN \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4a) // 0x164a*/ -/*#define DEMUX_CHAN_RECORD_EN_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4a) // 0x169a*/ -/*#define DEMUX_CHAN_RECORD_EN_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4a) // 0x16ea*/ - -/* bit[31:0] channel_process_enable*/ -/*#define DEMUX_CHAN_PROCESS_EN \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4b) // 0x164b*/ -/*#define DEMUX_CHAN_PROCESS_EN_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4b) */ /* 0x169b*/ -/*#define DEMUX_CHAN_PROCESS_EN_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4b) // 0x16eb*/ - -/* bit[31:24] small_sec_size ((n+1) * 256 Bytes)*/ -/* bit[23:16] small_sec_rd_ptr */ -/* bit[15:8] small_sec_wr_ptr */ -/* bit[7:2] reserved*/ -/* bit[1] small_sec_wr_ptr_wr_enable*/ -/* bit[0] small_section_enable*/ -/*#define DEMUX_SMALL_SEC_CTL \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4c)*/ /* 0x164c*/ -/*#define DEMUX_SMALL_SEC_CTL_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4c) // 0x169c*/ -/*#define DEMUX_SMALL_SEC_CTL_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4c) // 0x16ec*/ -/* bit[31:0] small_sec_start_addr*/ -/*#define DEMUX_SMALL_SEC_ADDR \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4d) // 0x164d*/ -/*#define DEMUX_SMALL_SEC_ADDR_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4d) // 0x169d*/ -/*#define DEMUX_SMALL_SEC_ADDR_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4d) // 0x16ed*/ - - -/*======================================================*/ -/* STB Registers End*/ -/*====================================================*/ -/* ----------------------------*/ -/* ASYNC FIFO (4)*/ -/* ----------------------------*/ -/*#define ASYNC_FIFO_REG0 0x2310*/ -/*#define ASYNC_FIFO_REG1 0x2311*/ -#define ASYNC_FIFO_FLUSH_STATUS 31 -#define ASYNC_FIFO_ERR 30 -#define ASYNC_FIFO_FIFO_EMPTY 29 -#define ASYNC_FIFO_TO_HIU 24 -#define ASYNC_FIFO_FLUSH 23 -#define ASYNC_FIFO_RESET 22 -#define ASYNC_FIFO_WRAP_EN 21 -#define ASYNC_FIFO_FLUSH_EN 20 -#define ASYNC_FIFO_RESIDUAL_MSB 19 -#define ASYNC_FIFO_RESIDUAL_LSB 15 -#define ASYNC_FIFO_FLUSH_CNT_MSB 14 -#define ASYNC_FIFO_FLUSH_CNT_LSB 0 -/*#define ASYNC_FIFO_REG2 0x2312*/ -#define ASYNC_FIFO_FIFO_FULL 26 -#define ASYNC_FIFO_FILL_STATUS 25 -#define ASYNC_FIFO_SOURCE_MSB 24 -#define ASYNC_FIFO_SOURCE_LSB 23 -#define ASYNC_FIFO_ENDIAN_MSB 22 -#define ASYNC_FIFO_ENDIAN_LSB 21 -#define ASYNC_FIFO_FILL_EN 20 -#define ASYNC_FIFO_FILL_CNT_MSB 19 -#define ASYNC_FIFO_FILL_CNT_LSB 0 -/*#define ASYNC_FIFO_REG3 0x2313*/ -#define ASYNC_FLUSH_SIZE_IRQ_MSB 15 -#define ASYNC_FLUSH_SIZE_IRQ_LSB 0 -/* ----------------------------*/ -/* ASYNC FIFO (4)*/ -/* ----------------------------*/ -/*#define ASYNC_FIFO2_REG0 0x2314*/ -/*#define ASYNC_FIFO2_REG1 0x2315*/ -/*#define ASYNC_FIFO2_REG2 0x2316*/ -/*#define ASYNC_FIFO2_REG3 0x2317*/ - -#define RESET_DEMUXSTB (1 << 1) -#endif /* C_STB_DEFINE_H*/ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h deleted file mode 100644 index b12db6898f7d..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h +++ /dev/null @@ -1,814 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -/* - * This file is automaticly generated by genregs.awk. Please do not edit it - * Base files are .. - * .. - * .. - * Tue Oct 22 15:28:48 CST 2013 - **/ - -#ifndef __MACH_MESON8_REG_ADDR_H_ -#define __MACH_MESON8_REG_ADDR_H_ -#include -#define CBUS_REG_ADDR(_r) aml_read_cbus(_r) - - -#define STB_CBUS_BASE aml_stb_get_base(ID_STB_CBUS_BASE) -#define SMARTCARD_REG_BASE aml_stb_get_base(ID_SMARTCARD_REG_BASE) -#define ASYNC_FIFO_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO_REG_BASE) -#define ASYNC_FIFO1_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO1_REG_BASE) -#define ASYNC_FIFO2_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO2_REG_BASE) -#define RESET_BASE aml_stb_get_base(ID_RESET_BASE) -#define PARSER_SUB_START_PTR_BASE \ - aml_stb_get_base(ID_PARSER_SUB_START_PTR_BASE) - -#define HHI_CSI_PHY_CNTL_BASE 0x1000 - -#define DEMUX_1_OFFSET 0x00 -#define DEMUX_2_OFFSET 0x50 -#define DEMUX_3_OFFSET 0xa0 - - -#define TS_HIU1_CONFIG (STB_CBUS_BASE + 0x4e) -#define P_TS_HIU1_CONFIG CBUS_REG_ADDR(TS_HIU1_CONFIG) - -#define TS_TOP_CONFIG1 (STB_CBUS_BASE + 0x4f) -#define P_TS_TOP_CONFIG1 CBUS_REG_ADDR(TS_TOP_CONFIG1) - -#define STB_S2P2_CONFIG (STB_CBUS_BASE + 0xef) -#define P_STB_S2P2_CONFIG CBUS_REG_ADDR(STB_S2P2_CONFIG) - -#define STB_RECORDER2_CNTL (STB_CBUS_BASE + 0xee) -#define P_STB_RECORDER2_CNTL CBUS_REG_ADDR(STB_RECORDER2_CNTL) - -#define STB_TOP_CONFIG (STB_CBUS_BASE + 0xf0) -#define P_STB_TOP_CONFIG CBUS_REG_ADDR(STB_TOP_CONFIG) -#define TS_TOP_CONFIG (STB_CBUS_BASE + 0xf1) -#define P_TS_TOP_CONFIG CBUS_REG_ADDR(TS_TOP_CONFIG) -#define TS_FILE_CONFIG (STB_CBUS_BASE + 0xf2) -#define P_TS_FILE_CONFIG CBUS_REG_ADDR(TS_FILE_CONFIG) -#define TS_PL_PID_INDEX (STB_CBUS_BASE + 0xf3) -#define P_TS_PL_PID_INDEX CBUS_REG_ADDR(TS_PL_PID_INDEX) -#define TS_PL_PID_DATA (STB_CBUS_BASE + 0xf4) -#define P_TS_PL_PID_DATA CBUS_REG_ADDR(TS_PL_PID_DATA) -#define COMM_DESC_KEY0 (STB_CBUS_BASE + 0xf5) -#define P_COMM_DESC_KEY0 CBUS_REG_ADDR(COMM_DESC_KEY0) -#define COMM_DESC_KEY1 (STB_CBUS_BASE + 0xf6) -#define P_COMM_DESC_KEY1 CBUS_REG_ADDR(COMM_DESC_KEY1) -#define COMM_DESC_KEY_RW (STB_CBUS_BASE + 0xf7) -#define P_COMM_DESC_KEY_RW CBUS_REG_ADDR(COMM_DESC_KEY_RW) -#define CIPLUS_KEY0 (STB_CBUS_BASE + 0xf8) -#define P_CIPLUS_KEY0 CBUS_REG_ADDR(CIPLUS_KEY0) -#define CIPLUS_KEY1 (STB_CBUS_BASE + 0xf9) -#define P_CIPLUS_KEY1 CBUS_REG_ADDR(CIPLUS_KEY1) -#define CIPLUS_KEY2 (STB_CBUS_BASE + 0xfa) -#define P_CIPLUS_KEY2 CBUS_REG_ADDR(CIPLUS_KEY2) -#define CIPLUS_KEY3 (STB_CBUS_BASE + 0xfb) -#define P_CIPLUS_KEY3 CBUS_REG_ADDR(CIPLUS_KEY3) -#define CIPLUS_KEY_WR (STB_CBUS_BASE + 0xfc) -#define P_CIPLUS_KEY_WR CBUS_REG_ADDR(CIPLUS_KEY_WR) -#define CIPLUS_CONFIG (STB_CBUS_BASE + 0xfd) -#define P_CIPLUS_CONFIG CBUS_REG_ADDR(CIPLUS_CONFIG) -#define CIPLUS_ENDIAN (STB_CBUS_BASE + 0xfe) -#define P_CIPLUS_ENDIAN CBUS_REG_ADDR(CIPLUS_ENDIAN) - -#define SMARTCARD_REG0 (SMARTCARD_REG_BASE + 0x0) -#define P_SMARTCARD_REG0 CBUS_REG_ADDR(SMARTCARD_REG0) -#define SMARTCARD_REG1 (SMARTCARD_REG_BASE + 0x1) -#define P_SMARTCARD_REG1 CBUS_REG_ADDR(SMARTCARD_REG1) -#define SMARTCARD_REG2 (SMARTCARD_REG_BASE + 0x2) -#define P_SMARTCARD_REG2 CBUS_REG_ADDR(SMARTCARD_REG2) -#define SMARTCARD_STATUS (SMARTCARD_REG_BASE + 0x3) -#define P_SMARTCARD_STATUS CBUS_REG_ADDR(SMARTCARD_STATUS) -#define SMARTCARD_INTR (SMARTCARD_REG_BASE + 0x4) -#define P_SMARTCARD_INTR CBUS_REG_ADDR(SMARTCARD_INTR) -#define SMARTCARD_REG5 (SMARTCARD_REG_BASE + 0x5) -#define P_SMARTCARD_REG5 CBUS_REG_ADDR(SMARTCARD_REG5) -#define SMARTCARD_REG6 (SMARTCARD_REG_BASE + 0x6) -#define P_SMARTCARD_REG6 CBUS_REG_ADDR(SMARTCARD_REG6) -#define SMARTCARD_FIFO (SMARTCARD_REG_BASE + 0x7) -#define P_SMARTCARD_FIFO CBUS_REG_ADDR(SMARTCARD_FIFO) -#define SMARTCARD_REG8 (SMARTCARD_REG_BASE + 0x8) -#define P_SMARTCARD_REG8 CBUS_REG_ADDR(SMARTCARD_REG8) - -#define ASYNC_FIFO_REG0 (ASYNC_FIFO_REG_BASE + 0x0) -#define P_ASYNC_FIFO_REG0 CBUS_REG_ADDR(ASYNC_FIFO_REG0) -#define ASYNC_FIFO_REG1 (ASYNC_FIFO_REG_BASE + 0x1) -#define P_ASYNC_FIFO_REG1 CBUS_REG_ADDR(ASYNC_FIFO_REG1) -#define ASYNC_FIFO_REG2 (ASYNC_FIFO_REG_BASE + 0x2) -#define P_ASYNC_FIFO_REG2 CBUS_REG_ADDR(ASYNC_FIFO_REG2) -#define ASYNC_FIFO_REG3 (ASYNC_FIFO_REG_BASE + 0x3) -#define P_ASYNC_FIFO_REG3 CBUS_REG_ADDR(ASYNC_FIFO_REG3) -#define ASYNC_FIFO_REG4 (ASYNC_FIFO_REG_BASE + 0x4) -#define P_ASYNC_FIFO_REG4 CBUS_REG_ADDR(ASYNC_FIFO_REG4) -#define ASYNC_FIFO_REG5 (ASYNC_FIFO_REG_BASE + 0x5) -#define P_ASYNC_FIFO_REG5 CBUS_REG_ADDR(ASYNC_FIFO_REG5) - -#define ASYNC_FIFO1_REG0 (ASYNC_FIFO1_REG_BASE + 0x0) -#define P_ASYNC_FIFO1_REG0 CBUS_REG_ADDR(ASYNC_FIFO1_REG0) -#define ASYNC_FIFO1_REG1 (ASYNC_FIFO1_REG_BASE + 0x1) -#define P_ASYNC_FIFO1_REG1 CBUS_REG_ADDR(ASYNC_FIFO1_REG1) -#define ASYNC_FIFO1_REG2 (ASYNC_FIFO1_REG_BASE + 0x2) -#define P_ASYNC_FIFO1_REG2 CBUS_REG_ADDR(ASYNC_FIFO1_REG2) -#define ASYNC_FIFO1_REG3 (ASYNC_FIFO1_REG_BASE + 0x3) -#define P_ASYNC_FIFO1_REG3 CBUS_REG_ADDR(ASYNC_FIFO1_REG3) -#define ASYNC_FIFO1_REG4 (ASYNC_FIFO1_REG_BASE + 0x4) -#define P_ASYNC_FIFO1_REG4 CBUS_REG_ADDR(ASYNC_FIFO1_REG4) -#define ASYNC_FIFO1_REG5 (ASYNC_FIFO1_REG_BASE + 0x5) -#define P_ASYNC_FIFO1_REG5 CBUS_REG_ADDR(ASYNC_FIFO1_REG5) - - -#define ASYNC_FIFO2_REG0 (ASYNC_FIFO2_REG_BASE + 0x0) -#define P_ASYNC_FIFO2_REG0 CBUS_REG_ADDR(ASYNC_FIFO2_REG0) -#define ASYNC_FIFO2_REG1 (ASYNC_FIFO2_REG_BASE + 0x1) -#define P_ASYNC_FIFO2_REG1 CBUS_REG_ADDR(ASYNC_FIFO2_REG1) -#define ASYNC_FIFO2_REG2 (ASYNC_FIFO2_REG_BASE + 0x2) -#define P_ASYNC_FIFO2_REG2 CBUS_REG_ADDR(ASYNC_FIFO2_REG2) -#define ASYNC_FIFO2_REG3 (ASYNC_FIFO2_REG_BASE + 0x3) -#define P_ASYNC_FIFO2_REG3 CBUS_REG_ADDR(ASYNC_FIFO2_REG3) -#define ASYNC_FIFO2_REG4 (ASYNC_FIFO2_REG_BASE + 0x4) -#define P_ASYNC_FIFO2_REG4 CBUS_REG_ADDR(ASYNC_FIFO2_REG4) -#define ASYNC_FIFO2_REG5 (ASYNC_FIFO2_REG_BASE + 0x5) -#define P_ASYNC_FIFO2_REG5 CBUS_REG_ADDR(ASYNC_FIFO2_REG5) - - -#define RESET0_REGISTER (RESET_BASE + 0x1) -#define P_RESET0_REGISTER CBUS_REG_ADDR(RESET0_REGISTER) -#define RESET1_REGISTER (RESET_BASE + 0x2) -#define P_RESET1_REGISTER CBUS_REG_ADDR(RESET1_REGISTER) -#define RESET2_REGISTER (RESET_BASE + 0x3) -#define P_RESET2_REGISTER CBUS_REG_ADDR(RESET2_REGISTER) -#define RESET3_REGISTER (RESET_BASE + 0x4) -#define P_RESET3_REGISTER CBUS_REG_ADDR(RESET3_REGISTER) -#define RESET4_REGISTER (RESET_BASE + 0x5) -#define P_RESET4_REGISTER CBUS_REG_ADDR(RESET4_REGISTER) -#define RESET5_REGISTER (RESET_BASE + 0x6) -#define P_RESET5_REGISTER CBUS_REG_ADDR(RESET5_REGISTER) -#define RESET6_REGISTER (RESET_BASE + 0x7) -#define P_RESET6_REGISTER CBUS_REG_ADDR(RESET6_REGISTER) -#define RESET7_REGISTER (RESET_BASE + 0x8) -#define P_RESET7_REGISTER CBUS_REG_ADDR(RESET7_REGISTER) -#define RESET0_MASK (RESET_BASE + 0x10) -#define P_RESET0_MASK CBUS_REG_ADDR(RESET0_MASK) -#define RESET1_MASK (RESET_BASE + 0x11) -#define P_RESET1_MASK CBUS_REG_ADDR(RESET1_MASK) -#define RESET2_MASK (RESET_BASE + 0x12) -#define P_RESET2_MASK CBUS_REG_ADDR(RESET2_MASK) -#define RESET3_MASK (RESET_BASE + 0x13) -#define P_RESET3_MASK CBUS_REG_ADDR(RESET3_MASK) -#define RESET4_MASK (RESET_BASE + 0x14) -#define P_RESET4_MASK CBUS_REG_ADDR(RESET4_MASK) -#define RESET5_MASK (RESET_BASE + 0x15) -#define P_RESET5_MASK CBUS_REG_ADDR(RESET5_MASK) -#define RESET6_MASK (RESET_BASE + 0x16) -#define P_RESET6_MASK CBUS_REG_ADDR(RESET6_MASK) -#define CRT_MASK (RESET_BASE + 0x17) -#define P_CRT_MASK CBUS_REG_ADDR(CRT_MASK) -#define RESET7_MASK (RESET_BASE + 0x18) -#define P_RESET7_MASK CBUS_REG_ADDR(RESET7_MASK) -/*add from M8M2*/ -#define P_RESET0_LEVEL CBUS_REG_ADDR(RESET0_LEVEL) -#define RESET1_LEVEL (RESET_BASE + 0x21) -#define P_RESET1_LEVEL CBUS_REG_ADDR(RESET1_LEVEL) -#define RESET2_LEVEL (RESET_BASE + 0x22) -#define P_RESET2_LEVEL CBUS_REG_ADDR(RESET2_LEVEL) -#define RESET3_LEVEL (RESET_BASE + 0x23) -#define P_RESET3_LEVEL CBUS_REG_ADDR(RESET3_LEVEL) -#define RESET4_LEVEL (RESET_BASE + 0x24) -#define P_RESET4_LEVEL CBUS_REG_ADDR(RESET4_LEVEL) -#define RESET5_LEVEL (RESET_BASE + 0x25) -#define P_RESET5_LEVEL CBUS_REG_ADDR(RESET5_LEVEL) -#define RESET6_LEVEL (RESET_BASE + 0x26) -#define P_RESET6_LEVEL CBUS_REG_ADDR(RESET6_LEVEL) -#define RESET7_LEVEL (RESET_BASE + 0x27) -#define P_RESET7_LEVEL CBUS_REG_ADDR(RESET7_LEVEL) - -/*no set*/ -#ifdef MESON_M8_CPU -#define HHI_CSI_PHY_CNTL0 (HHI_CSI_PHY_CNTL_BASE + 0xd3) -#define P_HHI_CSI_PHY_CNTL0 CBUS_REG_ADDR(HHI_CSI_PHY_CNTL0) -#define HHI_CSI_PHY_CNTL1 (HHI_CSI_PHY_CNTL_BASE + 0xd4) -#define P_HHI_CSI_PHY_CNTL1 CBUS_REG_ADDR(HHI_CSI_PHY_CNTL1) -#define HHI_CSI_PHY_CNTL2 (HHI_CSI_PHY_CNTL_BASE + 0xd5) -#define P_HHI_CSI_PHY_CNTL2 CBUS_REG_ADDR(HHI_CSI_PHY_CNTL2) -#define HHI_CSI_PHY_CNTL3 (HHI_CSI_PHY_CNTL_BASE + 0xd6) -#define P_HHI_CSI_PHY_CNTL3 CBUS_REG_ADDR(HHI_CSI_PHY_CNTL3) -#define HHI_CSI_PHY_CNTL4 (HHI_CSI_PHY_CNTL_BASE + 0xd7) -#define P_HHI_CSI_PHY_CNTL4 CBUS_REG_ADDR(HHI_CSI_PHY_CNTL4) -#endif - -#define PARSER_SUB_START_PTR (PARSER_SUB_START_PTR_BASE + 0x8a) -#define P_PARSER_SUB_START_PTR CBUS_REG_ADDR(PARSER_SUB_START_PTR) -#define PARSER_SUB_END_PTR (PARSER_SUB_START_PTR_BASE + 0x8b) -#define P_PARSER_SUB_END_PTR CBUS_REG_ADDR(PARSER_SUB_END_PTR) -#define PARSER_SUB_WP (PARSER_SUB_START_PTR_BASE + 0x8c) -#define P_PARSER_SUB_WP CBUS_REG_ADDR(PARSER_SUB_WP) -#define PARSER_SUB_RP (PARSER_SUB_START_PTR_BASE + 0x8d) -#define P_PARSER_SUB_RP CBUS_REG_ADDR(PARSER_SUB_RP) -#define PARSER_SUB_HOLE (PARSER_SUB_START_PTR_BASE + 0x8e) -#define P_PARSER_SUB_HOLE CBUS_REG_ADDR(PARSER_SUB_HOLE) - -/*no set*/ -#define AO_RTI_GEN_PWR_SLEEP0 ((0x00 << 10) | (0x3a << 2)) -#define P_AO_RTI_GEN_PWR_SLEEP0 \ - AOBUS_REG_ADDR(AO_RTI_GEN_PWR_SLEEP0) -#define AO_RTI_GEN_PWR_ISO0 ((0x00 << 10) | (0x3b << 2)) -#define P_AO_RTI_GEN_PWR_ISO0 AOBUS_REG_ADDR(AO_RTI_GEN_PWR_ISO0) - -/**/ -#define STB_VERSION (STB_CBUS_BASE + 0x00) -#define P_STB_VERSION CBUS_REG_ADDR(STB_VERSION) -#define STB_VERSION_2 (STB_CBUS_BASE + 0x50) -#define P_STB_VERSION_2 CBUS_REG_ADDR(STB_VERSION_2) -#define STB_VERSION_3 (STB_CBUS_BASE + 0xa0) -#define P_STB_VERSION_3 CBUS_REG_ADDR(STB_VERSION_3) -#define STB_TEST_REG (STB_CBUS_BASE + 0x01) -#define P_STB_TEST_REG CBUS_REG_ADDR(STB_TEST_REG) -#define STB_TEST_REG_2 (STB_CBUS_BASE + 0x51) -#define P_STB_TEST_REG_2 CBUS_REG_ADDR(STB_TEST_REG_2) -#define STB_TEST_REG_3 (STB_CBUS_BASE + 0xa1) -#define P_STB_TEST_REG_3 CBUS_REG_ADDR(STB_TEST_REG_3) - -#define FEC_INPUT_CONTROL (STB_CBUS_BASE + 0x2) -#define P_FEC_INPUT_CONTROL CBUS_REG_ADDR(FEC_INPUT_CONTROL) -#define FEC_INPUT_CONTROL_2 (STB_CBUS_BASE + 0x52) -#define P_FEC_INPUT_CONTROL_2 CBUS_REG_ADDR(FEC_INPUT_CONTROL_2) -#define FEC_INPUT_CONTROL_3 (STB_CBUS_BASE + 0xa2) -#define P_FEC_INPUT_CONTROL_3 CBUS_REG_ADDR(FEC_INPUT_CONTROL_3) -/*no used*/ -#define FEC_INPUT_DATA (STB_CBUS_BASE + 0x03) -#define P_FEC_INPUT_DATA CBUS_REG_ADDR(FEC_INPUT_DATA) -#define FEC_INPUT_DATA_2 (STB_CBUS_BASE + 0x53) -#define P_FEC_INPUT_DATA_2 CBUS_REG_ADDR(FEC_INPUT_DATA_2) -#define FEC_INPUT_DATA_3 (STB_CBUS_BASE + 0xa3) -#define P_FEC_INPUT_DATA_3 CBUS_REG_ADDR(FEC_INPUT_DATA_3) -/*no used end*/ -#define DEMUX_CONTROL (STB_CBUS_BASE + 0x04) -#define P_DEMUX_CONTROL CBUS_REG_ADDR(DEMUX_CONTROL) -#define DEMUX_CONTROL_2 (STB_CBUS_BASE + 0x54) -#define P_DEMUX_CONTROL_2 CBUS_REG_ADDR(DEMUX_CONTROL_2) -#define DEMUX_CONTROL_3 (STB_CBUS_BASE + 0xa4) -#define P_DEMUX_CONTROL_3 CBUS_REG_ADDR(DEMUX_CONTROL_3) -/*no used*/ -#define FEC_SYNC_BYTE (STB_CBUS_BASE + 0x05) -#define P_FEC_SYNC_BYTE CBUS_REG_ADDR(FEC_SYNC_BYTE) -#define FEC_SYNC_BYTE_2 (STB_CBUS_BASE + 0x55) -#define P_FEC_SYNC_BYTE_2 CBUS_REG_ADDR(FEC_SYNC_BYTE_2) -#define FEC_SYNC_BYTE_3 (STB_CBUS_BASE + 0xa5) -#define P_FEC_SYNC_BYTE_3 CBUS_REG_ADDR(FEC_SYNC_BYTE_3) -/*no used end*/ - -#define FM_WR_DATA (STB_CBUS_BASE + 0x06) -#define P_FM_WR_DATA CBUS_REG_ADDR(FM_WR_DATA) -#define FM_WR_DATA_2 (STB_CBUS_BASE + 0x56) -#define P_FM_WR_DATA_2 CBUS_REG_ADDR(FM_WR_DATA_2) -#define FM_WR_DATA_3 (STB_CBUS_BASE + 0xa6) -#define P_FM_WR_DATA_3 CBUS_REG_ADDR(FM_WR_DATA_3) -#define FM_WR_ADDR (STB_CBUS_BASE + 0x07) -#define P_FM_WR_ADDR CBUS_REG_ADDR(FM_WR_ADDR) -#define FM_WR_ADDR_2 (STB_CBUS_BASE + 0x57) -#define P_FM_WR_ADDR_2 CBUS_REG_ADDR(FM_WR_ADDR_2) -#define FM_WR_ADDR_3 (STB_CBUS_BASE + 0xa7) -#define P_FM_WR_ADDR_3 CBUS_REG_ADDR(FM_WR_ADDR_3) -#define MAX_FM_COMP_ADDR (STB_CBUS_BASE + 0x08) -#define P_MAX_FM_COMP_ADDR CBUS_REG_ADDR(MAX_FM_COMP_ADDR) -#define MAX_FM_COMP_ADDR_2 (STB_CBUS_BASE + 0x58) -#define P_MAX_FM_COMP_ADDR_2 CBUS_REG_ADDR(MAX_FM_COMP_ADDR_2) -#define MAX_FM_COMP_ADDR_3 (STB_CBUS_BASE + 0xa8) -#define P_MAX_FM_COMP_ADDR_3 CBUS_REG_ADDR(MAX_FM_COMP_ADDR_3) - -#define TS_HEAD_0 (STB_CBUS_BASE + 0x09) -#define P_TS_HEAD_0 CBUS_REG_ADDR(TS_HEAD_0) -#define TS_HEAD_0_2 (STB_CBUS_BASE + 0x59) -#define P_TS_HEAD_0_2 CBUS_REG_ADDR(TS_HEAD_0_2) -#define TS_HEAD_0_3 (STB_CBUS_BASE + 0xa9) -#define P_TS_HEAD_0_3 CBUS_REG_ADDR(TS_HEAD_0_3) -#define TS_HEAD_1 (STB_CBUS_BASE + 0x0a) -#define P_TS_HEAD_1 CBUS_REG_ADDR(TS_HEAD_1) -#define TS_HEAD_1_2 (STB_CBUS_BASE + 0x5a) -#define P_TS_HEAD_1_2 CBUS_REG_ADDR(TS_HEAD_1_2) -#define TS_HEAD_1_3 (STB_CBUS_BASE + 0xaa) -#define P_TS_HEAD_1_3 CBUS_REG_ADDR(TS_HEAD_1_3) - -#define OM_CMD_STATUS (STB_CBUS_BASE + 0x0b) -#define P_OM_CMD_STATUS CBUS_REG_ADDR(OM_CMD_STATUS) -#define OM_CMD_STATUS_2 (STB_CBUS_BASE + 0x5b) -#define P_OM_CMD_STATUS_2 CBUS_REG_ADDR(OM_CMD_STATUS_2) -#define OM_CMD_STATUS_3 (STB_CBUS_BASE + 0xab) -#define P_OM_CMD_STATUS_3 CBUS_REG_ADDR(OM_CMD_STATUS_3) - -#define OM_CMD_DATA (STB_CBUS_BASE + 0x0c) -#define P_OM_CMD_DATA CBUS_REG_ADDR(OM_CMD_DATA) -#define OM_CMD_DATA_2 (STB_CBUS_BASE + 0x5c) -#define P_OM_CMD_DATA_2 CBUS_REG_ADDR(OM_CMD_DATA_2) -#define OM_CMD_DATA_3 (STB_CBUS_BASE + 0xac) -#define P_OM_CMD_DATA_3 CBUS_REG_ADDR(OM_CMD_DATA_3) -#define OM_CMD_DATA2 (STB_CBUS_BASE + 0x0d) -#define P_OM_CMD_DATA2 CBUS_REG_ADDR(OM_CMD_DATA2) -#define OM_CMD_DATA2_2 (STB_CBUS_BASE + 0x5d) -#define P_OM_CMD_DATA2_2 CBUS_REG_ADDR(OM_CMD_DATA2_2) -#define OM_CMD_DATA2_3 (STB_CBUS_BASE + 0xad) -#define P_OM_CMD_DATA2_3 CBUS_REG_ADDR(OM_CMD_DATA2_3) - -#define SEC_BUFF_01_START (STB_CBUS_BASE + 0x0e) -#define P_SEC_BUFF_01_START CBUS_REG_ADDR(SEC_BUFF_01_START) -#define SEC_BUFF_01_START_2 (STB_CBUS_BASE + 0x5e) -#define P_SEC_BUFF_01_START_2 CBUS_REG_ADDR(SEC_BUFF_01_START_2) -#define SEC_BUFF_01_START_3 (STB_CBUS_BASE + 0xae) -#define P_SEC_BUFF_01_START_3 CBUS_REG_ADDR(SEC_BUFF_01_START_3) -#define SEC_BUFF_23_START (STB_CBUS_BASE + 0x0f) -#define P_SEC_BUFF_23_START CBUS_REG_ADDR(SEC_BUFF_23_START) -#define SEC_BUFF_23_START_2 (STB_CBUS_BASE + 0x5f) -#define P_SEC_BUFF_23_START_2 CBUS_REG_ADDR(SEC_BUFF_23_START_2) -#define SEC_BUFF_23_START_3 (STB_CBUS_BASE + 0xaf) -#define P_SEC_BUFF_23_START_3 CBUS_REG_ADDR(SEC_BUFF_23_START_3) -#define SEC_BUFF_SIZE (STB_CBUS_BASE + 0x10) -#define P_SEC_BUFF_SIZE CBUS_REG_ADDR(SEC_BUFF_SIZE) -#define SEC_BUFF_SIZE_2 (STB_CBUS_BASE + 0x60) -#define P_SEC_BUFF_SIZE_2 CBUS_REG_ADDR(SEC_BUFF_SIZE_2) -#define SEC_BUFF_SIZE_3 (STB_CBUS_BASE + 0xb0) -#define P_SEC_BUFF_SIZE_3 CBUS_REG_ADDR(SEC_BUFF_SIZE_3) -#define SEC_BUFF_BUSY (STB_CBUS_BASE + 0x11) -#define P_SEC_BUFF_BUSY CBUS_REG_ADDR(SEC_BUFF_BUSY) -#define SEC_BUFF_BUSY_2 (STB_CBUS_BASE + 0x61) -#define P_SEC_BUFF_BUSY_2 CBUS_REG_ADDR(SEC_BUFF_BUSY_2) -#define SEC_BUFF_BUSY_3 (STB_CBUS_BASE + 0xb1) -#define P_SEC_BUFF_BUSY_3 CBUS_REG_ADDR(SEC_BUFF_BUSY_3) -#define SEC_BUFF_READY (STB_CBUS_BASE + 0x12) -#define P_SEC_BUFF_READY CBUS_REG_ADDR(SEC_BUFF_READY) -#define SEC_BUFF_READY_2 (STB_CBUS_BASE + 0x62) -#define P_SEC_BUFF_READY_2 CBUS_REG_ADDR(SEC_BUFF_READY_2) -#define SEC_BUFF_READY_3 (STB_CBUS_BASE + 0xb2) -#define P_SEC_BUFF_READY_3 CBUS_REG_ADDR(SEC_BUFF_READY_3) -#define SEC_BUFF_NUMBER (STB_CBUS_BASE + 0x13) -#define P_SEC_BUFF_NUMBER CBUS_REG_ADDR(SEC_BUFF_NUMBER) -#define SEC_BUFF_NUMBER_2 (STB_CBUS_BASE + 0x63) -#define P_SEC_BUFF_NUMBER_2 CBUS_REG_ADDR(SEC_BUFF_NUMBER_2) -#define SEC_BUFF_NUMBER_3 (STB_CBUS_BASE + 0xb3) -#define P_SEC_BUFF_NUMBER_3 CBUS_REG_ADDR(SEC_BUFF_NUMBER_3) - - -/**no used*/ -#define ASSIGN_PID_NUMBER (STB_CBUS_BASE + 0x14) -#define P_ASSIGN_PID_NUMBER CBUS_REG_ADDR(ASSIGN_PID_NUMBER) -#define ASSIGN_PID_NUMBER_2 (STB_CBUS_BASE + 0x64) -#define P_ASSIGN_PID_NUMBER_2 CBUS_REG_ADDR(ASSIGN_PID_NUMBER_2) -#define ASSIGN_PID_NUMBER_3 (STB_CBUS_BASE + 0xb4) -#define P_ASSIGN_PID_NUMBER_3 CBUS_REG_ADDR(ASSIGN_PID_NUMBER_3) -#define VIDEO_STREAM_ID (STB_CBUS_BASE + 0x15) -#define P_VIDEO_STREAM_ID CBUS_REG_ADDR(VIDEO_STREAM_ID) -#define VIDEO_STREAM_ID_2 (STB_CBUS_BASE + 0x65) -#define P_VIDEO_STREAM_ID_2 CBUS_REG_ADDR(VIDEO_STREAM_ID_2) -#define VIDEO_STREAM_ID_3 (STB_CBUS_BASE + 0xb5) -#define P_VIDEO_STREAM_ID_3 CBUS_REG_ADDR(VIDEO_STREAM_ID_3) -#define AUDIO_STREAM_ID (STB_CBUS_BASE + 0x16) -#define P_AUDIO_STREAM_ID CBUS_REG_ADDR(AUDIO_STREAM_ID) -#define AUDIO_STREAM_ID_2 (STB_CBUS_BASE + 0x66) -#define P_AUDIO_STREAM_ID_2 CBUS_REG_ADDR(AUDIO_STREAM_ID_2) -#define AUDIO_STREAM_ID_3 (STB_CBUS_BASE + 0xb6) -#define P_AUDIO_STREAM_ID_3 CBUS_REG_ADDR(AUDIO_STREAM_ID_3) -#define SUB_STREAM_ID (STB_CBUS_BASE + 0x17) -#define P_SUB_STREAM_ID CBUS_REG_ADDR(SUB_STREAM_ID) -#define SUB_STREAM_ID_2 (STB_CBUS_BASE + 0x67) -#define P_SUB_STREAM_ID_2 CBUS_REG_ADDR(SUB_STREAM_ID_2) -#define SUB_STREAM_ID_3 (STB_CBUS_BASE + 0xb7) -#define P_SUB_STREAM_ID_3 CBUS_REG_ADDR(SUB_STREAM_ID_3) -#define OTHER_STREAM_ID (STB_CBUS_BASE + 0x18) -#define P_OTHER_STREAM_ID CBUS_REG_ADDR(OTHER_STREAM_ID) -#define OTHER_STREAM_ID_2 (STB_CBUS_BASE + 0x68) -#define P_OTHER_STREAM_ID_2 CBUS_REG_ADDR(OTHER_STREAM_ID_2) -#define OTHER_STREAM_ID_3 (STB_CBUS_BASE + 0xb8) -#define P_OTHER_STREAM_ID_3 CBUS_REG_ADDR(OTHER_STREAM_ID_3) -#define PCR90K_CTL (STB_CBUS_BASE + 0x19) -#define P_PCR90K_CTL CBUS_REG_ADDR(PCR90K_CTL) -#define PCR90K_CTL_2 (STB_CBUS_BASE + 0x69) -#define P_PCR90K_CTL_2 CBUS_REG_ADDR(PCR90K_CTL_2) -#define PCR90K_CTL_3 (STB_CBUS_BASE + 0xb9) -#define P_PCR90K_CTL_3 CBUS_REG_ADDR(PCR90K_CTL_3) -/*no used end*/ -#define PCR_DEMUX (STB_CBUS_BASE + 0x1a) -#define P_PCR_DEMUX CBUS_REG_ADDR(PCR_DEMUX) -#define PCR_DEMUX_2 (STB_CBUS_BASE + 0x6a) -#define P_PCR_DEMUX_2 CBUS_REG_ADDR(PCR_DEMUX_2) -#define PCR_DEMUX_3 (STB_CBUS_BASE + 0xba) -#define P_PCR_DEMUX_3 CBUS_REG_ADDR(PCR_DEMUX_3) - -#define VIDEO_PTS_DEMUX (STB_CBUS_BASE + 0x1b) -#define P_VIDEO_PTS_DEMUX CBUS_REG_ADDR(VIDEO_PTS_DEMUX) -#define VIDEO_PTS_DEMUX_2 (STB_CBUS_BASE + 0x6b) -#define P_VIDEO_PTS_DEMUX_2 CBUS_REG_ADDR(VIDEO_PTS_DEMUX_2) -#define VIDEO_PTS_DEMUX_3 (STB_CBUS_BASE + 0xbb) -#define P_VIDEO_PTS_DEMUX_3 CBUS_REG_ADDR(VIDEO_PTS_DEMUX_3) -/*no used*/ -#define VIDEO_DTS_DEMUX (STB_CBUS_BASE + 0x1c) -#define P_VIDEO_DTS_DEMUX CBUS_REG_ADDR(VIDEO_DTS_DEMUX) -#define VIDEO_DTS_DEMUX_2 (STB_CBUS_BASE + 0x6c) -#define P_VIDEO_DTS_DEMUX_2 CBUS_REG_ADDR(VIDEO_DTS_DEMUX_2) -#define VIDEO_DTS_DEMUX_3 (STB_CBUS_BASE + 0xbc) -#define P_VIDEO_DTS_DEMUX_3 CBUS_REG_ADDR(VIDEO_DTS_DEMUX_3) -/*no used end*/ -#define AUDIO_PTS_DEMUX (STB_CBUS_BASE + 0x1d) -#define P_AUDIO_PTS_DEMUX CBUS_REG_ADDR(AUDIO_PTS_DEMUX) -#define AUDIO_PTS_DEMUX_2 (STB_CBUS_BASE + 0x6d) -#define P_AUDIO_PTS_DEMUX_2 CBUS_REG_ADDR(AUDIO_PTS_DEMUX_2) -#define AUDIO_PTS_DEMUX_3 (STB_CBUS_BASE + 0xbd) -#define P_AUDIO_PTS_DEMUX_3 CBUS_REG_ADDR(AUDIO_PTS_DEMUX_3) -/*no used */ -#define SUB_PTS_DEMUX (STB_CBUS_BASE + 0x1e) -#define P_SUB_PTS_DEMUX CBUS_REG_ADDR(SUB_PTS_DEMUX) -#define SUB_PTS_DEMUX_2 (STB_CBUS_BASE + 0x6e) -#define P_SUB_PTS_DEMUX_2 CBUS_REG_ADDR(SUB_PTS_DEMUX_2) -#define SUB_PTS_DEMUX_3 (STB_CBUS_BASE + 0xbe) -#define P_SUB_PTS_DEMUX_3 CBUS_REG_ADDR(SUB_PTS_DEMUX_3) -/*no used end*/ -#define STB_PTS_DTS_STATUS (STB_CBUS_BASE + 0x1f) -#define P_STB_PTS_DTS_STATUS CBUS_REG_ADDR(STB_PTS_DTS_STATUS) -#define STB_PTS_DTS_STATUS_2 (STB_CBUS_BASE + 0x6f) -#define P_STB_PTS_DTS_STATUS_2 CBUS_REG_ADDR(STB_PTS_DTS_STATUS_2) -#define STB_PTS_DTS_STATUS_3 (STB_CBUS_BASE + 0xbf) -#define P_STB_PTS_DTS_STATUS_3 CBUS_REG_ADDR(STB_PTS_DTS_STATUS_3) - -/*no use*/ -#define STB_DEBUG_INDEX (STB_CBUS_BASE + 0x20) -#define P_STB_DEBUG_INDEX CBUS_REG_ADDR(STB_DEBUG_INDEX) -#define STB_DEBUG_INDEX_2 (STB_CBUS_BASE + 0x70) -#define P_STB_DEBUG_INDEX_2 CBUS_REG_ADDR(STB_DEBUG_INDEX_2) -#define STB_DEBUG_INDEX_3 (STB_CBUS_BASE + 0xc0) -#define P_STB_DEBUG_INDEX_3 CBUS_REG_ADDR(STB_DEBUG_INDEX_3) -#define STB_DEBUG_DATAUT_O (STB_CBUS_BASE + 0x21) -#define P_STB_DEBUG_DATAUT_O CBUS_REG_ADDR(STB_DEBUG_DATAUT_O) -#define STB_DEBUG_DATAUT_O_2 (STB_CBUS_BASE + 0x71) -#define P_STB_DEBUG_DATAUT_O_2 CBUS_REG_ADDR(STB_DEBUG_DATAUT_O_2) -#define STB_DEBUG_DATAUT_O_3 (STB_CBUS_BASE + 0xc1) -#define P_STB_DEBUG_DATAUT_O_3 CBUS_REG_ADDR(STB_DEBUG_DATAUT_O_3) -/*no use end*/ - -#define STBM_CTL_O (STB_CBUS_BASE + 0x22) -#define P_STBM_CTL_O CBUS_REG_ADDR(STBM_CTL_O) -#define STBM_CTL_O_2 (STB_CBUS_BASE + 0x72) -#define P_STBM_CTL_O_2 CBUS_REG_ADDR(STBM_CTL_O_2) -#define STBM_CTL_O_3 (STB_CBUS_BASE + 0xc2) -#define P_STBM_CTL_O_3 CBUS_REG_ADDR(STBM_CTL_O_3) -#define STB_INT_STATUS (STB_CBUS_BASE + 0x23) -#define P_STB_INT_STATUS CBUS_REG_ADDR(STB_INT_STATUS) -#define STB_INT_STATUS_2 (STB_CBUS_BASE + 0x73) -#define P_STB_INT_STATUS_2 CBUS_REG_ADDR(STB_INT_STATUS_2) -#define STB_INT_STATUS_3 (STB_CBUS_BASE + 0xc3) -#define P_STB_INT_STATUS_3 CBUS_REG_ADDR(STB_INT_STATUS_3) -#define DEMUX_ENDIAN (STB_CBUS_BASE + 0x24) -#define P_DEMUX_ENDIAN CBUS_REG_ADDR(DEMUX_ENDIAN) -#define DEMUX_ENDIAN_2 (STB_CBUS_BASE + 0x74) -#define P_DEMUX_ENDIAN_2 CBUS_REG_ADDR(DEMUX_ENDIAN_2) -#define DEMUX_ENDIAN_3 (STB_CBUS_BASE + 0xc4) -#define P_DEMUX_ENDIAN_3 CBUS_REG_ADDR(DEMUX_ENDIAN_3) -#define TS_HIU_CTL (STB_CBUS_BASE + 0x25) -#define P_TS_HIU_CTL CBUS_REG_ADDR(TS_HIU_CTL) -#define TS_HIU_CTL_2 (STB_CBUS_BASE + 0x75) -#define P_TS_HIU_CTL_2 CBUS_REG_ADDR(TS_HIU_CTL_2) -#define TS_HIU_CTL_3 (STB_CBUS_BASE + 0xc5) -#define P_TS_HIU_CTL_3 CBUS_REG_ADDR(TS_HIU_CTL_3) - -#define SEC_BUFF_BASE (STB_CBUS_BASE + 0x26) -#define P_SEC_BUFF_BASE CBUS_REG_ADDR(SEC_BUFF_BASE) -#define SEC_BUFF_BASE_2 (STB_CBUS_BASE + 0x76) -#define P_SEC_BUFF_BASE_2 CBUS_REG_ADDR(SEC_BUFF_BASE_2) -#define SEC_BUFF_BASE_3 (STB_CBUS_BASE + 0xc6) -#define P_SEC_BUFF_BASE_3 CBUS_REG_ADDR(SEC_BUFF_BASE_3) -#define DEMUX_MEM_REQ_EN (STB_CBUS_BASE + 0x27) -#define P_DEMUX_MEM_REQ_EN CBUS_REG_ADDR(DEMUX_MEM_REQ_EN) -#define DEMUX_MEM_REQ_EN_2 (STB_CBUS_BASE + 0x77) -#define P_DEMUX_MEM_REQ_EN_2 CBUS_REG_ADDR(DEMUX_MEM_REQ_EN_2) -#define DEMUX_MEM_REQ_EN_3 (STB_CBUS_BASE + 0xc7) -#define P_DEMUX_MEM_REQ_EN_3 CBUS_REG_ADDR(DEMUX_MEM_REQ_EN_3) - - -/*no use*/ -#define VIDEO_PDTS_WR_PTR (STB_CBUS_BASE + 0x28) -#define P_VIDEO_PDTS_WR_PTR CBUS_REG_ADDR(VIDEO_PDTS_WR_PTR) -#define VIDEO_PDTS_WR_PTR_2 (STB_CBUS_BASE + 0x78) -#define P_VIDEO_PDTS_WR_PTR_2 CBUS_REG_ADDR(VIDEO_PDTS_WR_PTR_2) -#define VIDEO_PDTS_WR_PTR_3 (STB_CBUS_BASE + 0xc8) -#define P_VIDEO_PDTS_WR_PTR_3 CBUS_REG_ADDR(VIDEO_PDTS_WR_PTR_3) -#define AUDIO_PDTS_WR_PTR (STB_CBUS_BASE + 0x29) -#define P_AUDIO_PDTS_WR_PTR CBUS_REG_ADDR(AUDIO_PDTS_WR_PTR) -#define AUDIO_PDTS_WR_PTR_2 (STB_CBUS_BASE + 0x79) -#define P_AUDIO_PDTS_WR_PTR_2 CBUS_REG_ADDR(AUDIO_PDTS_WR_PTR_2) -#define AUDIO_PDTS_WR_PTR_3 (STB_CBUS_BASE + 0xc9) -#define P_AUDIO_PDTS_WR_PTR_3 CBUS_REG_ADDR(AUDIO_PDTS_WR_PTR_3) -#define SUB_WR_PTR (STB_CBUS_BASE + 0x2a) -#define P_SUB_WR_PTR CBUS_REG_ADDR(SUB_WR_PTR) -#define SUB_WR_PTR_2 (STB_CBUS_BASE + 0x7a) -#define P_SUB_WR_PTR_2 CBUS_REG_ADDR(SUB_WR_PTR_2) -#define SUB_WR_PTR_3 (STB_CBUS_BASE + 0xca) -#define P_SUB_WR_PTR_3 CBUS_REG_ADDR(SUB_WR_PTR_3) -/*no use*/ - -#define SB_START (STB_CBUS_BASE + 0x2b) -#define P_SB_START CBUS_REG_ADDR(SB_START) -#define SB_START_2 (STB_CBUS_BASE + 0x7b) -#define P_SB_START_2 CBUS_REG_ADDR(SB_START_2) -#define SB_START_3 (STB_CBUS_BASE + 0xcb) -#define P_SB_START_3 CBUS_REG_ADDR(SB_START_3) -#define SB_LAST_ADDR (STB_CBUS_BASE + 0x2c) -#define P_SB_LAST_ADDR CBUS_REG_ADDR(SB_LAST_ADDR) -#define SB_LAST_ADDR_2 (STB_CBUS_BASE + 0x7c) -#define P_SB_LAST_ADDR_2 CBUS_REG_ADDR(SB_LAST_ADDR_2) -#define SB_LAST_ADDR_3 (STB_CBUS_BASE + 0xcc) -#define P_SB_LAST_ADDR_3 CBUS_REG_ADDR(SB_LAST_ADDR_3) -#define SB_PES_WR_PTR (STB_CBUS_BASE + 0x2d) -#define P_SB_PES_WR_PTR CBUS_REG_ADDR(SB_PES_WR_PTR) -#define SB_PES_WR_PTR_2 (STB_CBUS_BASE + 0x7d) -#define P_SB_PES_WR_PTR_2 CBUS_REG_ADDR(SB_PES_WR_PTR_2) -#define SB_PES_WR_PTR_3 (STB_CBUS_BASE + 0xcd) -#define P_SB_PES_WR_PTR_3 CBUS_REG_ADDR(SB_PES_WR_PTR_3) -#define OTHER_WR_PTR (STB_CBUS_BASE + 0x2e) -#define P_OTHER_WR_PTR CBUS_REG_ADDR(OTHER_WR_PTR) -#define OTHER_WR_PTR_2 (STB_CBUS_BASE + 0x7e) -#define P_OTHER_WR_PTR_2 CBUS_REG_ADDR(OTHER_WR_PTR_2) -#define OTHER_WR_PTR_3 (STB_CBUS_BASE + 0xce) -#define P_OTHER_WR_PTR_3 CBUS_REG_ADDR(OTHER_WR_PTR_3) - -#define OB_START (STB_CBUS_BASE + 0x2f) -#define P_OB_START CBUS_REG_ADDR(OB_START) -#define OB_START_2 (STB_CBUS_BASE + 0x7f) -#define P_OB_START_2 CBUS_REG_ADDR(OB_START_2) -#define OB_START_3 (STB_CBUS_BASE + 0xcf) -#define P_OB_START_3 CBUS_REG_ADDR(OB_START_3) -#define OB_LAST_ADDR (STB_CBUS_BASE + 0x30) -#define P_OB_LAST_ADDR CBUS_REG_ADDR(OB_LAST_ADDR) -#define OB_LAST_ADDR_2 (STB_CBUS_BASE + 0x80) -#define P_OB_LAST_ADDR_2 CBUS_REG_ADDR(OB_LAST_ADDR_2) -#define OB_LAST_ADDR_3 (STB_CBUS_BASE + 0xd0) -#define P_OB_LAST_ADDR_3 CBUS_REG_ADDR(OB_LAST_ADDR_3) -#define OB_PES_WR_PTR (STB_CBUS_BASE + 0x31) -#define P_OB_PES_WR_PTR CBUS_REG_ADDR(OB_PES_WR_PTR) -#define OB_PES_WR_PTR_2 (STB_CBUS_BASE + 0x81) -#define P_OB_PES_WR_PTR_2 CBUS_REG_ADDR(OB_PES_WR_PTR_2) -#define OB_PES_WR_PTR_3 (STB_CBUS_BASE + 0xd1) -#define P_OB_PES_WR_PTR_3 CBUS_REG_ADDR(OB_PES_WR_PTR_3) -#define STB_INT_MASK (STB_CBUS_BASE + 0x32) -#define P_STB_INT_MASK CBUS_REG_ADDR(STB_INT_MASK) -#define STB_INT_MASK_2 (STB_CBUS_BASE + 0x82) -#define P_STB_INT_MASK_2 CBUS_REG_ADDR(STB_INT_MASK_2) -#define STB_INT_MASK_3 (STB_CBUS_BASE + 0xd2) -#define P_STB_INT_MASK_3 CBUS_REG_ADDR(STB_INT_MASK_3) -/*no used */ -#define VIDEO_SPLICING_CTL (STB_CBUS_BASE + 0x33) -#define P_VIDEO_SPLICING_CTL CBUS_REG_ADDR(VIDEO_SPLICING_CTL) -#define VIDEO_SPLICING_CTL_2 (STB_CBUS_BASE + 0x83) -#define P_VIDEO_SPLICING_CTL_2 CBUS_REG_ADDR(VIDEO_SPLICING_CTL_2) -#define VIDEO_SPLICING_CTL_3 (STB_CBUS_BASE + 0xd3) -#define P_VIDEO_SPLICING_CTL_3 CBUS_REG_ADDR(VIDEO_SPLICING_CTL_3) -#define AUDIO_SPLICING_CTL (STB_CBUS_BASE + 0x34) -#define P_AUDIO_SPLICING_CTL CBUS_REG_ADDR(AUDIO_SPLICING_CTL) -#define AUDIO_SPLICING_CTL_2 (STB_CBUS_BASE + 0x84) -#define P_AUDIO_SPLICING_CTL_2 CBUS_REG_ADDR(AUDIO_SPLICING_CTL_2) -#define AUDIO_SPLICING_CTL_3 (STB_CBUS_BASE + 0xd4) -#define P_AUDIO_SPLICING_CTL_3 CBUS_REG_ADDR(AUDIO_SPLICING_CTL_3) -#define TS_PACKAGE_BYTE_COUNT (STB_CBUS_BASE + 0x35) -#define P_TS_PACKAGE_BYTE_COUNT \ - CBUS_REG_ADDR(TS_PACKAGE_BYTE_COUNT) -#define TS_PACKAGE_BYTE_COUNT_2 (STB_CBUS_BASE + 0x85) -#define P_TS_PACKAGE_BYTE_COUNT_2 \ - CBUS_REG_ADDR(TS_PACKAGE_BYTE_COUNT_2) -#define TS_PACKAGE_BYTE_COUNT_3 (STB_CBUS_BASE + 0xd5) -#define P_TS_PACKAGE_BYTE_COUNT_3 \ - CBUS_REG_ADDR(TS_PACKAGE_BYTE_COUNT_3) -/*no used end*/ - -#define PES_STRONG_SYNC (STB_CBUS_BASE + 0x36) -#define P_PES_STRONG_SYNC CBUS_REG_ADDR(PES_STRONG_SYNC) -#define PES_STRONG_SYNC_2 (STB_CBUS_BASE + 0x86) -#define P_PES_STRONG_SYNC_2 CBUS_REG_ADDR(PES_STRONG_SYNC_2) -#define PES_STRONG_SYNC_3 (STB_CBUS_BASE + 0xd6) -#define P_PES_STRONG_SYNC_3 CBUS_REG_ADDR(PES_STRONG_SYNC_3) - -#define OM_DATA_RD_ADDR (STB_CBUS_BASE + 0x37) -#define P_OM_DATA_RD_ADDR CBUS_REG_ADDR(OM_DATA_RD_ADDR) -#define OM_DATA_RD_ADDR_2 (STB_CBUS_BASE + 0x87) -#define P_OM_DATA_RD_ADDR_2 CBUS_REG_ADDR(OM_DATA_RD_ADDR_2) -#define OM_DATA_RD_ADDR_3 (STB_CBUS_BASE + 0xd7) -#define P_OM_DATA_RD_ADDR_3 CBUS_REG_ADDR(OM_DATA_RD_ADDR_3) -#define OM_DATA_RD (STB_CBUS_BASE + 0x38) -#define P_OM_DATA_RD CBUS_REG_ADDR(OM_DATA_RD) -#define OM_DATA_RD_2 (STB_CBUS_BASE + 0x88) -#define P_OM_DATA_RD_2 CBUS_REG_ADDR(OM_DATA_RD_2) -#define OM_DATA_RD_3 (STB_CBUS_BASE + 0xd8) -#define P_OM_DATA_RD_3 CBUS_REG_ADDR(OM_DATA_RD_3) - -/*no used*/ - -#define SECTION_AUTO_STOP_3 (STB_CBUS_BASE + 0x39) -#define P_SECTION_AUTO_STOP_3 CBUS_REG_ADDR(SECTION_AUTO_STOP_3) -#define SECTION_AUTO_STOP_3_2 (STB_CBUS_BASE + 0x89) -#define P_SECTION_AUTO_STOP_3_2 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_3_2) -#define SECTION_AUTO_STOP_3_3 (STB_CBUS_BASE + 0xd9) -#define P_SECTION_AUTO_STOP_3_3 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_3_3) -#define SECTION_AUTO_STOP_2 (STB_CBUS_BASE + 0x3a) -#define P_SECTION_AUTO_STOP_2 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_2) -#define SECTION_AUTO_STOP_2_2 (STB_CBUS_BASE + 0x8a) -#define P_SECTION_AUTO_STOP_2_2 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_2_2) -#define SECTION_AUTO_STOP_2_3 (STB_CBUS_BASE + 0xda) -#define P_SECTION_AUTO_STOP_2_3 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_2_3) -#define SECTION_AUTO_STOP_1 (STB_CBUS_BASE + 0x3b) -#define P_SECTION_AUTO_STOP_1 CBUS_REG_ADDR(SECTION_AUTO_STOP_1) -#define SECTION_AUTO_STOP_1_2 (STB_CBUS_BASE + 0x8b) -#define P_SECTION_AUTO_STOP_1_2 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_1_2) -#define SECTION_AUTO_STOP_1_3 (STB_CBUS_BASE + 0xdb) -#define P_SECTION_AUTO_STOP_1_3 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_1_3) -#define SECTION_AUTO_STOP_0 (STB_CBUS_BASE + 0x3c) -#define P_SECTION_AUTO_STOP_0 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_0) -#define SECTION_AUTO_STOP_0_2 (STB_CBUS_BASE + 0x8c) -#define P_SECTION_AUTO_STOP_0_2 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_0_2) -#define SECTION_AUTO_STOP_0_3 (STB_CBUS_BASE + 0xdc) -#define P_SECTION_AUTO_STOP_0_3 \ - CBUS_REG_ADDR(SECTION_AUTO_STOP_0_3) - -#define DEMUX_CHANNEL_RESET (STB_CBUS_BASE + 0x3d) -#define P_DEMUX_CHANNEL_RESET \ - CBUS_REG_ADDR(DEMUX_CHANNEL_RESET) -#define DEMUX_CHANNEL_RESET_2 (STB_CBUS_BASE + 0x8d) -#define P_DEMUX_CHANNEL_RESET_2 \ - CBUS_REG_ADDR(DEMUX_CHANNEL_RESET_2) -#define DEMUX_CHANNEL_RESET_3 (STB_CBUS_BASE + 0xdd) -#define P_DEMUX_CHANNEL_RESET_3 \ - CBUS_REG_ADDR(DEMUX_CHANNEL_RESET_3) -/*no use end*/ -#define DEMUX_SCRAMBLING_STATE (STB_CBUS_BASE + 0x3e) -#define DEMUX_SCRAMBLING_STATE_2 (STB_CBUS_BASE + 0x8e) -#define P_DEMUX_SCRAMBLING_STATE_2 \ - CBUS_REG_ADDR(DEMUX_SCRAMBLING_STATE_2) -#define DEMUX_SCRAMBLING_STATE_3 (STB_CBUS_BASE + 0xde) -#define P_DEMUX_SCRAMBLING_STATE_3 \ - CBUS_REG_ADDR(DEMUX_SCRAMBLING_STATE_3) -#define DEMUX_CHANNEL_ACTIVITY (STB_CBUS_BASE + 0x3f) -#define P_DEMUX_CHANNEL_ACTIVITY \ - CBUS_REG_ADDR(DEMUX_CHANNEL_ACTIVITY) -#define DEMUX_CHANNEL_ACTIVITY_2 (STB_CBUS_BASE + 0x8f) -#define P_DEMUX_CHANNEL_ACTIVITY_2 \ - CBUS_REG_ADDR(DEMUX_CHANNEL_ACTIVITY_2) -#define DEMUX_CHANNEL_ACTIVITY_3 (STB_CBUS_BASE + 0xdf) -#define P_DEMUX_CHANNEL_ACTIVITY_3 \ - CBUS_REG_ADDR(DEMUX_CHANNEL_ACTIVITY_3) - -/*no use*/ - -#define DEMUX_STAMP_CTL (STB_CBUS_BASE + 0x40) -#define P_DEMUX_STAMP_CTL CBUS_REG_ADDR(DEMUX_STAMP_CTL) -#define DEMUX_STAMP_CTL_2 (STB_CBUS_BASE + 0x90) -#define P_DEMUX_STAMP_CTL_2 \ - CBUS_REG_ADDR(DEMUX_STAMP_CTL_2) -#define DEMUX_STAMP_CTL_3 (STB_CBUS_BASE + 0xe0) -#define P_DEMUX_STAMP_CTL_3 \ - CBUS_REG_ADDR(DEMUX_STAMP_CTL_3) -#define DEMUX_VIDEO_STAMP_SYNC_0 (STB_CBUS_BASE + 0x41) -#define P_DEMUX_VIDEO_STAMP_SYNC_0 \ - CBUS_REG_ADDR(DEMUX_VIDEO_STAMP_SYNC_0) -#define DEMUX_VIDEO_STAMP_SYNC_0_2 (STB_CBUS_BASE + 0x91) -#define P_DEMUX_VIDEO_STAMP_SYNC_0_2 \ - CBUS_REG_ADDR(DEMUX_VIDEO_STAMP_SYNC_0_2) -#define DEMUX_VIDEO_STAMP_SYNC_0_3 (STB_CBUS_BASE + 0xe1) -#define P_DEMUX_VIDEO_STAMP_SYNC_0_3 \ - CBUS_REG_ADDR(DEMUX_VIDEO_STAMP_SYNC_0_3) -#define DEMUX_VIDEO_STAMP_SYNC_1 (STB_CBUS_BASE + 0x42) -#define P_DEMUX_VIDEO_STAMP_SYNC_1 \ - CBUS_REG_ADDR(DEMUX_VIDEO_STAMP_SYNC_1) -#define DEMUX_VIDEO_STAMP_SYNC_1_2 (STB_CBUS_BASE + 0x92) -#define P_DEMUX_VIDEO_STAMP_SYNC_1_2 \ - CBUS_REG_ADDR(DEMUX_VIDEO_STAMP_SYNC_1_2) -#define DEMUX_VIDEO_STAMP_SYNC_1_3 (STB_CBUS_BASE + 0xe2) -#define P_DEMUX_VIDEO_STAMP_SYNC_1_3 \ - CBUS_REG_ADDR(DEMUX_VIDEO_STAMP_SYNC_1_3) -#define DEMUX_AUDIO_STAMP_SYNC_0 (STB_CBUS_BASE + 0x43) -#define P_DEMUX_AUDIO_STAMP_SYNC_0 \ - CBUS_REG_ADDR(DEMUX_AUDIO_STAMP_SYNC_0) -#define DEMUX_AUDIO_STAMP_SYNC_0_2 (STB_CBUS_BASE + 0x93) -#define P_DEMUX_AUDIO_STAMP_SYNC_0_2 \ - CBUS_REG_ADDR(DEMUX_AUDIO_STAMP_SYNC_0_2) -#define DEMUX_AUDIO_STAMP_SYNC_0_3 (STB_CBUS_BASE + 0xe3) -#define P_DEMUX_AUDIO_STAMP_SYNC_0_3 \ - CBUS_REG_ADDR(DEMUX_AUDIO_STAMP_SYNC_0_3) -#define DEMUX_AUDIO_STAMP_SYNC_1 (STB_CBUS_BASE + 0x44) -#define P_DEMUX_AUDIO_STAMP_SYNC_1 \ - CBUS_REG_ADDR(DEMUX_AUDIO_STAMP_SYNC_1) -#define DEMUX_AUDIO_STAMP_SYNC_1_2 (STB_CBUS_BASE + 0x94) -#define P_DEMUX_AUDIO_STAMP_SYNC_1_2 \ - CBUS_REG_ADDR(DEMUX_AUDIO_STAMP_SYNC_1_2) -#define DEMUX_AUDIO_STAMP_SYNC_1_3 (STB_CBUS_BASE + 0xe4) -#define P_DEMUX_AUDIO_STAMP_SYNC_1_3 \ - CBUS_REG_ADDR(DEMUX_AUDIO_STAMP_SYNC_1_3) -#define DEMUX_SECTION_RESET (STB_CBUS_BASE + 0x45) -#define P_DEMUX_SECTION_RESET CBUS_REG_ADDR(DEMUX_SECTION_RESET) -#define DEMUX_SECTION_RESET_2 (STB_CBUS_BASE + 0x95) -#define P_DEMUX_SECTION_RESET_2 \ - CBUS_REG_ADDR(DEMUX_SECTION_RESET_2) -#define DEMUX_SECTION_RESET_3 (STB_CBUS_BASE + 0xe5) -#define P_DEMUX_SECTION_RESET_3 \ - CBUS_REG_ADDR(DEMUX_SECTION_RESET_3) -/*no use end*/ - -/*from c_stb_define.h*/ -#define COMM_DESC_2_CTL (STB_CBUS_BASE + 0xff) /*0x16ff*/ - -#define STB_OM_CTL \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x22) /* 0x1622*/ -#define STB_OM_CTL_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x22) /* 0x1672*/ -#define STB_OM_CTL_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x22) /* 0x16c2*/ - -#define DEMUX_INPUT_TIMEOUT_C \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x46) /* 0x1646*/ -#define DEMUX_INPUT_TIMEOUT_C_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x46) /* 0x1696*/ -#define DEMUX_INPUT_TIMEOUT_C_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x46) /* 0x16e6*/ -/* bit[31] - no_match_reset_timeout_disable*/ -/* bit[30:0] input_time_out_int_cnt (0 -- means disable) Wr-setting, Rd-count*/ -#define DEMUX_INPUT_TIMEOUT \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x47) /* 0x1647*/ -#define DEMUX_INPUT_TIMEOUT_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x47) /* 0x1697*/ -#define DEMUX_INPUT_TIMEOUT_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x47) /* 0x16e7*/ - -/* bit[31:0] - channel_packet_count_disable*/ -#define DEMUX_PACKET_COUNT_C \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x48) /* 0x1648*/ -#define DEMUX_PACKET_COUNT_C_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x48) /* 0x1698*/ -#define DEMUX_PACKET_COUNT_C_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x48) /* 0x16e8*/ -/* bit[31] - no_match_packet_count_disable*/ -/* bit[30:0] input_packet_count*/ -#define DEMUX_PACKET_COUNT \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x49) /* 0x1649*/ -#define DEMUX_PACKET_COUNT_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x49) /* 0x1699*/ -#define DEMUX_PACKET_COUNT_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x49) /* 0x16e9*/ - -/* bit[31:0] channel_record_enable*/ -#define DEMUX_CHAN_RECORD_EN \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4a) /* 0x164a*/ -#define DEMUX_CHAN_RECORD_EN_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4a) /* 0x169a*/ -#define DEMUX_CHAN_RECORD_EN_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4a) /* 0x16ea*/ - -/* bit[31:0] channel_process_enable*/ -#define DEMUX_CHAN_PROCESS_EN \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4b) /* 0x164b*/ -#define DEMUX_CHAN_PROCESS_EN_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4b) /* 0x169b*/ -#define DEMUX_CHAN_PROCESS_EN_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4b) /* 0x16eb*/ - -/* bit[31:24] small_sec_size ((n+1) * 256 Bytes)*/ -/* bit[23:16] small_sec_rd_ptr */ -/* bit[15:8] small_sec_wr_ptr */ -/* bit[7:2] reserved*/ -/* bit[1] small_sec_wr_ptr_wr_enable*/ -/* bit[0] small_section_enable*/ -#define DEMUX_SMALL_SEC_CTL \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4c) /* 0x164c*/ -#define DEMUX_SMALL_SEC_CTL_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4c) /* 0x169c*/ -#define DEMUX_SMALL_SEC_CTL_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4c) /* 0x16ec*/ -/* bit[31:0] small_sec_start_addr*/ -#define DEMUX_SMALL_SEC_ADDR \ - (STB_CBUS_BASE + DEMUX_1_OFFSET + 0x4d) /* 0x164d*/ -#define DEMUX_SMALL_SEC_ADDR_2 \ - (STB_CBUS_BASE + DEMUX_2_OFFSET + 0x4d) /* 0x169d*/ -#define DEMUX_SMALL_SEC_ADDR_3 \ - (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x4d) /* 0x16ed*/ - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile deleted file mode 100644 index bbfbdd48e16a..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -obj-m += ci.o cimax-usb.o - -ci-objs = $(amlci-objs) $(cimax-objs) - -amlci-objs = aml_pcmcia.o aml_ci.o -cimax-objs = cimax/dvb_ca_en50221_cimax.o cimax/aml_cimax.o cimax/dvb_ringbuffer.o -cimax-usb-objs += cimax/usb/SRC/cimax+usb-driver.o cimax/usb/SRC/cimax+usb_fw.o -cimax-usb-objs += cimax/usb/SRC/cimax+usb_config.o -cimax-objs += cimax/aml_cimax_usb.o - -ccflags-y += -I$(srctree)/ -ccflags-y += -I$(srctree)/include -ccflags-y += -I$(srctree)/drivers/gpio -ccflags-y += -I$(srctree)/drivers/media/dvb-core - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c deleted file mode 100644 index c28d2fc3cf83..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c +++ /dev/null @@ -1,754 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "aml_ci.h" -#include "aml_spi.h" -#include "cimax/aml_cimax.h" - -MODULE_PARM_DESC(aml_ci_debug, "\n\t\t dvb ci debug"); -static int aml_ci_debug = 1; -module_param(aml_ci_debug, int, S_IRUGO); - -#define pr_dbg(args...)\ - do {\ - if (aml_ci_debug)\ - printk(args);\ - } while (0) -#define pr_error(fmt, args...) printk("DVBCI: " fmt, ## args) -/**\brief aml_ci_mem_read:mem read from cam - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ -static int aml_ci_mem_read(struct dvb_ca_en50221 *en50221, int slot, int addr) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_mem_read != NULL) - return ci->ci_mem_read(ci, slot, addr); - - pr_error("ci_mem_read is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_mem_write:mem write to cam - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param addr: write addr - * \param addr: write value - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_mem_write(struct dvb_ca_en50221 *en50221, - int slot, int addr, u8 data) -{ - - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot not 0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_mem_write != NULL) - return ci->ci_mem_write(ci, slot, addr, data); - pr_error("ci_mem_write is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_io_read:io read from cam - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ -static int aml_ci_io_read(struct dvb_ca_en50221 *en50221, int slot, u8 addr) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_io_read != NULL) - return ci->ci_io_read(ci, slot, addr); - - pr_error("ci_io_read is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_io_write:io write to cam - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param addr: write addr - * \param addr: write value - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_io_write(struct dvb_ca_en50221 *en50221, - int slot, u8 addr, u8 data) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_mem_write != NULL) - return ci->ci_io_write(ci, slot, addr, data); - - pr_error("ci_io_write is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_slot_reset:reset slot - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) -{ - struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); - if (ci->ci_slot_reset != NULL) { - ci->ci_slot_reset(ci, slot); - } else { - pr_error("ci_slot_reset is null %s\r\n", __func__); - return -EINVAL; - } - return 0; -} -/**\brief aml_ci_slot_shutdown:show slot - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) -{ - struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot shutdown\n", slot); - if (ci->ci_slot_shutdown != NULL) { - ci->ci_slot_shutdown(ci, slot); - } else { - pr_error("aml_ci_slot_shutdown is null %s\r\n", __func__); - return -EINVAL; - } - return 0; -} -/**\brief aml_ci_ts_control:control slot ts - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_ts_control(struct dvb_ca_en50221 *en50221, int slot) -{ - - struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): TS control\n", slot); - if (ci->ci_slot_ts_enable != NULL) { - ci->ci_slot_ts_enable(ci, slot); - } else { - pr_error("aml_ci_ts_control is null %s\r\n", __func__); - return -EINVAL; - } - return 0; -} -/**\brief aml_ci_slot_status:get slot status - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param open: no used - * \return - * - cam status - * - -EINVAL : error - */ -static int aml_ci_slot_status(struct dvb_ca_en50221 *en50221, - int slot, int open) -{ - struct aml_ci *ci = en50221->data; - - pr_dbg("Slot(%d): Poll Slot status\n", slot); - - if (ci->ci_poll_slot_status != NULL) { - return ci->ci_poll_slot_status(ci, slot, open); - } else { - pr_error("ci_poll_slot_status is null %s\r\n", __func__); - return -EINVAL; - } - - return -EINVAL; -} -static int aml_ci_cimax_slot_reset(struct dvb_ca_en50221_cimax *en50221, - int slot) -{ - struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); - if (ci->ci_slot_reset != NULL) { - ci->ci_slot_reset(ci, slot); - } else { - pr_error("ci_slot_reset is null %s\r\n", __func__); - return -EINVAL; - } - return 0; -} -/**\brief aml_ci_slot_shutdown:show slot - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_cimax_slot_shutdown(struct dvb_ca_en50221_cimax *en50221, - int slot) -{ - struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot shutdown\n", slot); - if (ci->ci_slot_shutdown != NULL) { - ci->ci_slot_shutdown(ci, slot); - } else { - pr_error("aml_ci_slot_shutdown is null %s\r\n", __func__); - return -EINVAL; - } - return 0; -} -/**\brief aml_ci_ts_control:control slot ts - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ -static int aml_ci_cimax_ts_control(struct dvb_ca_en50221_cimax *en50221, - int slot) -{ - - struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): TS control\n", slot); - if (ci->ci_slot_ts_enable != NULL) { - ci->ci_slot_ts_enable(ci, slot); - } else { - pr_error("aml_ci_ts_control is null %s\r\n", __func__); - return -EINVAL; - } - return 0; -} -/**\brief aml_ci_slot_status:get slot status - * \param en50221: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param open: no used - * \return - * - cam status - * - -EINVAL : error - */ -static int aml_ci_cimax_slot_status( - struct dvb_ca_en50221_cimax *en50221, int slot, int open) -{ - struct aml_ci *ci = en50221->data; - - /*pr_dbg("Slot(%d): Poll Slot status\n", slot);*/ - - if (ci->ci_poll_slot_status != NULL) { - return ci->ci_poll_slot_status(ci, slot, open); - } else { - pr_error("ci_poll_slot_status is null %s\r\n", __func__); - return -EINVAL; - } - - return -EINVAL; -} - -/**\brief aml_ci_read_cis: read cis - * \param en50221_max: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param buf: buf for cis data - * \param size: buf size - * \return - * --EINVAL : error - * - : actual size read - */ -static int aml_ci_read_cis(struct dvb_ca_en50221_cimax *en50221, - int slot, u8 *buf, int size) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_read_cis != NULL) - return ci->ci_read_cis(ci, slot, buf, size); - - pr_error("ci_read_cis is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_write_cor: write cor - * \param en50221_max: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param addr: - * \param buf: - * \return - * --EINVAL : error - * -0 : ok - */ -static int aml_ci_write_cor(struct dvb_ca_en50221_cimax *en50221, - int slot, int address, u8 *buf) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_write_cor != NULL) - return ci->ci_write_cor(ci, slot, address, buf); - - pr_error("ci_write_cor is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_negociate: negotiate - * \param en50221_max: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param size: suggested size - * \return - * --EINVAL : error - * - : size negotiated - */ -static int aml_ci_negotiate(struct dvb_ca_en50221_cimax *en50221, - int slot, int size) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_negotiate != NULL) - return ci->ci_negotiate(ci, slot, size); - - pr_error("ci_negotiate is null %s\r\n", __func__); - return -EINVAL; -} -/**\brief aml_ci_read_lpdu: read lpdu - * \param en50221_max: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param buf: buf - * \param size: buf size - * \return - * --EINVAL : error - * - : size read - */ -static int aml_ci_read_lpdu(struct dvb_ca_en50221_cimax *en50221, - int slot, u8 *buf, int size) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_read_lpdu != NULL) - return ci->ci_read_lpdu(ci, slot, buf, size); - - pr_error("ci_read_lpdu is null %s\r\n", __func__); - return -EINVAL; -} - -/**\brief aml_ci_write_lpdu: write lpdu - * \param en50221_max: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \param buf: buf - * \param size: write size - * \return - * --EINVAL : error - * - : size written - */ -static int aml_ci_write_lpdu(struct dvb_ca_en50221_cimax *en50221, - int slot, u8 *buf, int size) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_write_lpdu != NULL) - return ci->ci_write_lpdu(ci, slot, buf, size); - - pr_error("ci_write_lpdu is null %s\r\n", __func__); - return -EINVAL; -} - -static int aml_ci_read_cam_status(struct dvb_ca_en50221_cimax *en50221, - int slot) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_read_cam_status != NULL) - return ci->ci_read_cam_status(ci, slot); - - pr_error("ci_read_cam_status is null %s\r\n", __func__); - return -EINVAL; -} - -static int aml_ci_cam_reset(struct dvb_ca_en50221_cimax *en50221, int slot) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_cam_reset != NULL) - return ci->ci_cam_reset(ci, slot); - - pr_error("ci_cam_reset is null %s\r\n", __func__); - return -EINVAL; -} - -/**\brief aml_ci_get_capbility - * \param en50221_max: en50221 obj,used this data to get dvb_ci obj - * \param slot: slot index - * \return - * - : capbilities - */ -static int aml_ci_get_capbility(struct dvb_ca_en50221_cimax *en50221, int slot) -{ - struct aml_ci *ci = en50221->data; - - if (slot != 0) { - pr_error("slot !=0 %s :%d\r\n", __func__, slot); - return -EINVAL; - } - - if (ci->ci_get_capbility != NULL) - return ci->ci_get_capbility(ci, slot); - - pr_error("ci_get_capbility is null %s\r\n", __func__); - return -EINVAL; -} - - -/**\brief get ci config from dts - * \param np: device node - * \return - * - 0 æˆåŠŸ - * - 其他值 : - */ -static int aml_ci_get_config_from_dts(struct platform_device *pdev, - struct aml_ci *ci) -{ - char buf[32]; - int ret = 0; - int value; - - snprintf(buf, sizeof(buf), "%s", "io_type"); - ret = of_property_read_u32(pdev->dev.of_node, buf, &value); - if (!ret) { - pr_dbg("%s: 0x%x\n", buf, value); - ci->io_type = value; - } - return 0; -} - -/**\brief aml_ci_init:ci dev init - * \param pdev: platform_device device node,used to get dts info - * \param dvb: aml_dvb obj,used to get dvb_adapter for en0211 to use - * \param cip: ci_dev pp - * \return - * - 0 æˆåŠŸ - * - 其他值 : - */ -int aml_ci_init(struct platform_device *pdev, - struct aml_dvb *dvb, struct aml_ci **cip) -{ - struct dvb_adapter *dvb_adapter = &dvb->dvb_adapter; - struct aml_ci *ci = NULL; - int ca_flags = 0, result; - - ci = kzalloc(sizeof(struct aml_ci), GFP_KERNEL); - if (!ci) { - pr_error("Out of memory!, exiting ..\n"); - result = -ENOMEM; - goto err; - } - ci->id = 0; - aml_ci_get_config_from_dts(pdev, ci); - - ci->priv = dvb; - /* register CA interface */ - if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) { - ci->en50221_cimax.owner = THIS_MODULE; - ci->en50221_cimax.read_cis = aml_ci_read_cis; - ci->en50221_cimax.write_cor = aml_ci_write_cor; - ci->en50221_cimax.negotiate = aml_ci_negotiate; - ci->en50221_cimax.read_lpdu = aml_ci_read_lpdu; - ci->en50221_cimax.write_lpdu = aml_ci_write_lpdu; - ci->en50221_cimax.read_cam_status = aml_ci_read_cam_status; - ci->en50221_cimax.cam_reset = aml_ci_cam_reset; - ci->en50221_cimax.get_capbility = aml_ci_get_capbility; - ci->en50221_cimax.slot_reset = aml_ci_cimax_slot_reset; - ci->en50221_cimax.slot_shutdown = aml_ci_cimax_slot_shutdown; - ci->en50221_cimax.slot_ts_enable = aml_ci_cimax_ts_control; - ci->en50221_cimax.poll_slot_status = aml_ci_cimax_slot_status; - ci->en50221_cimax.data = ci; - - pr_dbg("Registering EN50221 CIMAX device\n"); - result = dvb_ca_en50221_cimax_init(dvb_adapter, - &ci->en50221_cimax, ca_flags, 1); - if (result != 0) { - pr_error("EN50221 CIMAX: Initialization failed <%d>\n", - result); - goto err; - } - } else { - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; - ci->en50221.read_attribute_mem = aml_ci_mem_read; - ci->en50221.write_attribute_mem = aml_ci_mem_write; - ci->en50221.read_cam_control = aml_ci_io_read; - ci->en50221.write_cam_control = aml_ci_io_write; - ci->en50221.slot_reset = aml_ci_slot_reset; - ci->en50221.slot_shutdown = aml_ci_slot_shutdown; - ci->en50221.slot_ts_enable = aml_ci_ts_control; - ci->en50221.poll_slot_status = aml_ci_slot_status; - ci->en50221.data = ci; - - - pr_dbg("Registering EN50221 device\n"); - result = dvb_ca_en50221_init(dvb_adapter, - &ci->en50221, ca_flags, 1); - if (result != 0) { - pr_error("EN50221: Initialization failed <%d>\n", - result); - goto err; - } - } - *cip = ci; - pr_dbg("Registered EN50221 device\n"); - - if (ci->io_type == AML_DVB_IO_TYPE_SPI) { - /* spi init */ - //ci->ci_init = aml_spi_init; - //ci->ci_exit = aml_spi_exit; - } else if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) { - ci->ci_init = aml_cimax_init; - ci->ci_exit = aml_cimax_exit; - } else { - /* no io dev init,is error */ - pr_dbg("unknown io type, please check io_type in dts file\r\n"); - } - - if (ci->ci_init) - result = ci->ci_init(pdev, ci); - - if (result) - dvb_ca_en50221_cimax_release(&ci->en50221_cimax); - - return result; -err: - kfree(ci); - return result; -} - -void aml_ci_exit(struct aml_ci *ci) -{ - pr_dbg("Unregistering EN50221 device\n"); - if (ci) { - if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) - dvb_ca_en50221_cimax_release(&ci->en50221_cimax); - else - dvb_ca_en50221_release(&ci->en50221); - if (ci->ci_exit) - ci->ci_exit(ci); - kfree(ci); - } -} - -static struct aml_ci *ci_dev; - -static ssize_t aml_ci_ts_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret; - ret = sprintf(buf, "ts%d\n", 1); - return ret; -} - -static struct class_attribute amlci_class_attrs[] = { - __ATTR(ts, S_IRUGO | S_IWUSR, aml_ci_ts_show, NULL), - __ATTR_NULL -}; - -static int aml_ci_register_class(struct aml_ci *ci) -{ - #define CLASS_NAME_LEN 48 - int ret; - struct class *clp; - - clp = &(ci->class); - - clp->name = kzalloc(CLASS_NAME_LEN, GFP_KERNEL); - if (!clp->name) - return -ENOMEM; - - snprintf((char *)clp->name, CLASS_NAME_LEN, "amlci-%d", ci->id); - clp->owner = THIS_MODULE; - clp->class_attrs = amlci_class_attrs; - ret = class_register(clp); - if (ret) - kfree(clp->name); - - return 0; -} - -static int aml_ci_unregister_class(struct aml_ci *ci) -{ - class_unregister(&ci->class); - kzfree(ci->class.name); - return 0; -} - - -static int aml_ci_probe(struct platform_device *pdev) -{ - struct aml_dvb *dvb = aml_get_dvb_device(); - int err = 0; - pr_dbg("---Amlogic CI Init---\n"); - err = aml_ci_init(pdev, dvb, &ci_dev); - if (err < 0) - return err; - platform_set_drvdata(pdev, ci_dev); - aml_ci_register_class(ci_dev); - return 0; -} - -static int aml_ci_remove(struct platform_device *pdev) -{ - aml_ci_unregister_class(ci_dev); - platform_set_drvdata(pdev, NULL); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { - //aml_spi_exit(ci_dev); - } - else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) - aml_cimax_exit(ci_dev); - else - pr_dbg("---Amlogic CI remove unkown io type---\n"); - - aml_ci_exit(ci_dev); - return 0; -} - -static int aml_ci_suspend(struct platform_device *pdev, pm_message_t state) -{ - pr_dbg("Amlogic CI Suspend!\n"); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { - //aml_spi_exit(ci_dev); - } - else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) - aml_cimax_exit(ci_dev); - else - pr_dbg("---Amlogic CI remove unkown io type---\n"); - - return 0; -} - -static int aml_ci_resume(struct platform_device *pdev) -{ - int err = 0; - pr_dbg("Amlogic CI Resume!\n"); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { - //aml_spi_init(pdev, ci_dev); - } - else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) - aml_cimax_init(pdev, ci_dev); - else - pr_dbg("---Amlogic CI remove unkown io type---\n"); - return err; -} - -static const struct of_device_id dvbci_dev_dt_match[] = { - { - .compatible = "amlogic, dvbci", - }, - {}, -}; - - - -static struct platform_driver aml_ci_driver = { - .probe = aml_ci_probe, - .remove = aml_ci_remove, - .suspend = aml_ci_suspend, - .resume = aml_ci_resume, - .driver = { - .name = "dvbci", - .of_match_table = dvbci_dev_dt_match, - .owner = THIS_MODULE, - } -}; - -static int aml_ci_mod_init(void) -{ - pr_dbg("Amlogic CI mode init\n"); - return platform_driver_register(&aml_ci_driver); -} - -static void aml_ci_mod_exit(void) -{ - pr_dbg("Amlogic CI mode Exit\n"); - platform_driver_unregister(&aml_ci_driver); -} - -module_init(aml_ci_mod_init); -module_exit(aml_ci_mod_exit); -MODULE_LICENSE("GPL"); - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h deleted file mode 100644 index 3e34417e0c39..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - -#ifndef __AML_CI_H_ -#define __AML_CI_H_ - -#include "drivers/media/dvb-core/dvb_ca_en50221.h" -#include "cimax/dvb_ca_en50221_cimax.h" -#include "../aml_dvb.h" - -enum aml_dvb_io_type_e { - AML_DVB_IO_TYPE_IOBUS = 0, - AML_DVB_IO_TYPE_SPI, - AML_DVB_IO_TYPE_CIMAX, - AML_DVB_IO_TYPE_MAX, -}; - -struct aml_ci { - struct dvb_ca_en50221 en50221; - struct mutex ci_lock; - int io_type; - void *priv; - int id; - struct class class; - - int (*ci_init)(struct platform_device *pdev, struct aml_ci *ci); - int (*ci_exit)(struct aml_ci *ci); - - /* NOTE: the read_*, write_* and poll_slot_status functions will be - * called for different slots concurrently and need to use locks where - * and if appropriate. There will be no concurrent access to one slot. - */ - - /* functions for accessing attribute memory on the CAM */ - int (*ci_mem_read)(struct aml_ci *ca, int slot, int address); - int (*ci_mem_write)(struct aml_ci *ca, int slot, int address, u8 value); - - /* functions for accessing the control interface on the CAM */ - int (*ci_io_read)(struct aml_ci *ca, int slot, int address); - int (*ci_io_write)(struct aml_ci *ca, int slot, int address, u8 value); - - /* Functions for controlling slots */ - int (*ci_slot_reset)(struct aml_ci *ca, int slot); - int (*ci_slot_shutdown)(struct aml_ci *ca, int slot); - int (*ci_slot_ts_enable)(struct aml_ci *ca, int slot); - - /* - * Poll slot status. - * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set - */ - int (*ci_poll_slot_status)(struct aml_ci *ca, int slot, int open); - - - struct dvb_ca_en50221_cimax en50221_cimax; - - int (*ci_read_cis)(struct aml_ci *ca, int slot, u8 *buf, int size); - int (*ci_write_cor)(struct aml_ci *ca, int slot, int address, u8 *buf); - /*return the final size or -1 for error*/ - int (*ci_negotiate)(struct aml_ci *ca, int slot, int size); - - /* functions for accessing the control interface on the CAM */ - int (*ci_read_lpdu)(struct aml_ci *ca, int slot, u8 *buf, int size); - int (*ci_write_lpdu)(struct aml_ci *ca, int slot, u8 *buf, int size); - - int (*ci_get_capbility)(struct aml_ci *ca, int slot); - - int (*ci_cam_reset)(struct aml_ci *ca, int slot); - int (*ci_read_cam_status)(struct aml_ci *ca, int slot); - - /* private data, used by caller */ - void *data; -}; - -struct ci_dev_config_s { - char name[20]; - unsigned char type; - int cs_hold_delay; - int cs_clk_delay; -}; -extern int aml_ci_init(struct platform_device *pdev, - struct aml_dvb *dvb, struct aml_ci **cip); -extern void aml_ci_exit(struct aml_ci *ci); - -#endif /* __AML_CI_H_ */ - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c deleted file mode 100644 index ac8c87d71128..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c +++ /dev/null @@ -1,199 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -#include "aml_pcmcia.h" - -static int aml_pcmcia_debug = 1; - -module_param_named(pcmcia_debug, aml_pcmcia_debug, int, 0644); -MODULE_PARM_DESC(pcmcia_debug, "enable verbose debug messages"); - -#define pr_dbg(args...)\ - do {\ - if (aml_pcmcia_debug)\ - printk(args);\ - } while (0) -#define pr_error(fmt, args...) printk("PCMCIA: " fmt, ## args) - - -static int pcmcia_plugin(struct aml_pcmcia *pc) -{ - if (pc->slot_state == MODULE_XTRACTED) { - pr_dbg(" CAM Plugged IN: Adapter(%d) Slot(0)\n", 0); - udelay(50); - aml_pcmcia_reset(pc); - /*wait unplug*/ - pc->init_irq(pc, IRQF_TRIGGER_RISING); - udelay(500); - pc->slot_state = MODULE_INSERTED; - } else { - pr_error("repeat into pcmcia insert \r\n"); - aml_pcmcia_reset(pc); - } - udelay(100); - pc->pcmcia_plugin(pc, 1); - - return 0; -} - -static int pcmcia_unplug(struct aml_pcmcia *pc) -{ - if (pc->slot_state == MODULE_INSERTED) { - pr_dbg(" CAM Unplugged: Adapter(%d) Slot(0)\n", 0); - /*udelay(50);*/ - /*aml_pcmcia_reset(pc);*/ - /*wait plugin*/ - pc->init_irq(pc, IRQF_TRIGGER_FALLING); - udelay(500); - pc->slot_state = MODULE_XTRACTED; - } - udelay(100); - pc->pcmcia_plugin(pc, 0); - - return 0; -} - -static irqreturn_t pcmcia_irq_handler(int irq, void *dev_id) -{ - struct aml_pcmcia *pc = (struct aml_pcmcia *)dev_id; - pr_dbg("pcmcia_irq_handler--into--\r\n"); - disable_irq_nosync(pc->irq); - schedule_work(&pc->pcmcia_work); - enable_irq(pc->irq); - return IRQ_HANDLED; -} - -static void aml_pcmcia_work(struct work_struct *work) -{ - int cd1, cd2; - struct aml_pcmcia *pc = container_of( - work, struct aml_pcmcia, pcmcia_work); - - cd1 = pc->get_cd1(pc); - cd2 = pc->get_cd2(pc); - - if (cd1 != cd2) - pr_error("CAM card not inerted.\n"); - else { - if (!cd1) { - pr_error("Adapter(%d) Slot(0): CAM Plugin\n", 0); - pcmcia_plugin(pc); - } else { - pr_error("Adapter(%d) Slot(0): CAM Unplug\n", 0); - pcmcia_unplug(pc); - } - } -} - -static struct aml_pcmcia *pc_cur; - -int aml_pcmcia_init(struct aml_pcmcia *pc) -{ - int err = 0; - pr_dbg("aml_pcmcia_init start pc->irq=%d\r\n", pc->irq); - pc->rst(pc, AML_L); - /*power on*/ - pc->pwr(pc, AML_PWR_OPEN);/*hi is open power*/ - /*assuming cam unpluged, config the INT to waiting-for-plugin mode*/ - pc->init_irq(pc, IRQF_TRIGGER_LOW); - - INIT_WORK(&pc->pcmcia_work, aml_pcmcia_work); - - err = request_irq(pc->irq, - pcmcia_irq_handler, - IRQF_ONESHOT, "aml-pcmcia", pc); - if (err != 0) { - pr_error("ERROR: IRQ registration failed ! <%d>", err); - return -ENODEV; - } - - pc_cur = pc; - pr_dbg("aml_pcmcia_init ok\r\n"); - return 0; -} -EXPORT_SYMBOL(aml_pcmcia_init); - -int aml_pcmcia_exit(struct aml_pcmcia *pc) -{ - free_irq(pc->irq, pc); - return 0; -} -EXPORT_SYMBOL(aml_pcmcia_exit); - -int aml_pcmcia_reset(struct aml_pcmcia *pc) -{ - pr_dbg("CAM RESET-->\n"); - /* viaccess neotion cam need delay 2000 and 3000 */ - /* smit cam need delay 1000 and 1500 */ - /* need change delay according cam vendor */ - pc->rst(pc, AML_H);/*HI is reset*/ - mdelay(1000); - pc->rst(pc, AML_L);/*defaule LOW*/ - pr_dbg("CAM RESET--\n"); - mdelay(1500); - pr_dbg("CAM RESET--end\n"); - return 0; -} -EXPORT_SYMBOL(aml_pcmcia_reset); - - -#if 0 -static ssize_t aml_pcmcia_test_cmd(struct class *class, -struct class_attribute *attr, const char *buf, size_t size) -{ - pr_dbg("pcmcia cmd: %s\n", buf); - if (pc_cur) { - if (memcmp(buf, "reset", 5) == 0) - aml_pcmcia_reset(pc_cur); - else if (memcmp(buf, "on", 2) == 0) - pc_cur->pwr(pc_cur, AML_PWR_OPEN); - else if (memcmp(buf, "off", 3) == 0) - pc_cur->pwr(pc_cur, AML_PWR_CLOSE); - else if (memcmp(buf, "poll", 4) == 0) - schedule_work(&pc_cur->pcmcia_work); - else if (memcmp(buf, "intr", 4) == 0) - pc_cur->init_irq(pc_cur, IRQF_TRIGGER_RISING); - else if (memcmp(buf, "intf", 4) == 0) - pc_cur->init_irq(pc_cur, IRQF_TRIGGER_FALLING); - } - return size; -} - -static struct class_attribute aml_pcmcia_class_attrs[] = { - __ATTR(cmd, S_IRUGO | S_IWUSR, NULL, aml_pcmcia_test_cmd), - __ATTR_NULL -}; - -static struct class aml_pcmcia_class = { - .name = "aml_pcmcia_test", - .class_attrs = aml_pcmcia_class_attrs, -}; - -static int __init aml_pcmcia_mod_init(void) -{ - pr_dbg("Amlogic PCMCIA Init\n"); - - class_register(&aml_pcmcia_class); - - return 0; -} - -static void __exit aml_pcmcia_mod_exit(void) -{ - pr_dbg("Amlogic PCMCIA Exit\n"); - - class_unregister(&aml_pcmcia_class); -} - - - -module_init(aml_pcmcia_mod_init); -module_exit(aml_pcmcia_mod_exit); - -MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h deleted file mode 100644 index 612d5776e081..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - -#ifndef _AML_PCMCIA_ -#define _AML_PCMCIA_ - -enum aml_slot_state { - MODULE_INSERTED = 3, - MODULE_XTRACTED = 4 -}; - -enum aml_pwr_cmd { - AML_PWR_OPEN = 0, - AML_PWR_CLOSE = 1 -}; -enum aml_reset_cmd { - AML_L = 0, - AML_H = 1 -}; -struct aml_pcmcia { - enum aml_slot_state slot_state; - struct work_struct pcmcia_work; - int run_type;/*0:irq;1:poll*/ - int irq; - int (*init_irq)(struct aml_pcmcia *pc, int flag); - int (*get_cd1)(struct aml_pcmcia *pc); - int (*get_cd2)(struct aml_pcmcia *pc); - int (*pwr)(struct aml_pcmcia *pc, int enable); - int (*rst)(struct aml_pcmcia *pc, int enable); - - int (*pcmcia_plugin)(struct aml_pcmcia *pc, int plugin); - - void *priv; -}; - -int aml_pcmcia_init(struct aml_pcmcia *pc); -int aml_pcmcia_exit(struct aml_pcmcia *pc); -int aml_pcmcia_reset(struct aml_pcmcia *pc); - - -#endif /*_AML_PCMCIA_*/ - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c deleted file mode 100644 index 62f4f5315dc6..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c +++ /dev/null @@ -1,1666 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aml_spi.h" -#include "aml_ci.h" - -#define AML_MODE_NAME "aml_dvbci_spi" -static int AML_CI_GPIO_IRQ_BASE = 251; -static struct aml_spi *g_spi_dev; -static int aml_spi_debug = 1; -static int G_rec_flag = AM_SPI_STEP_INIT; - - -module_param_named(spi_debug, aml_spi_debug, int, 0644); -MODULE_PARM_DESC(spi_debug, "enable verbose debug messages"); - - -#define pr_dbg(args...)\ - do {\ - if (aml_spi_debug)\ - printk(args);\ - } while (0) -#define pr_error(fmt, args...) printk("AML_CI_SPI: " fmt, ## args) - -struct spi_board_info aml_ci_spi_bdinfo = { - .modalias = "ci_spi_dev", - .mode = SPI_MODE_0, - .max_speed_hz = 1000000, /* 1MHz */ - .bus_num = 0, /* SPI bus No. */ - .chip_select = 0, /* the device index on the spi bus */ - .controller_data = NULL, -}; - -#define NORMAL_MSG (0<<7) -#define BROADCAST_MSG (1<<7) -#define BLOCK_DATA (0<<6) -#define SINGLE_DATA (1<<6) -#define CISPI_DEV_ADDR 1 - -#define INPUT 0 -#define OUTPUT 1 -#define OUTLEVEL_LOW 0 -#define OUTLEVEL_HIGH 1 -#define PULLLOW 1 -#define PULLHIGH 0 - -/* -sendbuf data struct ----------------------------------------------------- -|start flag| cmd | data | addr |end flag | ----------------------------------------------------- -| 2 byte | 1byte | 1byte | 2 byte| 2 byte | ----------------------------------------------------- -*/ - -#define SENDBUFLEN 8 -static u8 sendbuf[SENDBUFLEN];/* send data */ -static u8 rbuf[SENDBUFLEN];/*save get data */ -/**\brief aml_init_send_buf:init spi send buf -* \param cmd: ci cmd -* \param data: write value -* \param addr: read or write addr -* \return -* - read value:ok -* - -EINVAL : error -*/ -static int aml_init_send_buf(u8 cmd, u8 data, u16 addr) -{ - /* start flag */ - sendbuf[0] = DATASTART; - sendbuf[1] = DATASTART; - /* cmd */ - sendbuf[2] = cmd; - /* data */ - sendbuf[3] = data; - /* addr senf low 8 bit first,and then send hi 8bit */ - sendbuf[4] = addr & 0x00ff; - sendbuf[5] = (addr>>8) & 0xff; - /* end flag */ - sendbuf[6] = DATAEND; - sendbuf[7] = DATAEND; - return 0; -} -/**\brief aml_ci_spi_reciver -* \param[out] None -* \param[in] value,get from spi -* \return -* - 0:reciver end,-1:reciver -* - -*/ -/* -data strouct ----------------------------------------------------- -|start flag| cmd | data | addr |end flag | ----------------------------------------------------- -| 2 byte | 1byte | 1byte | 2 byte| 2 byte | ----------------------------------------------------- -*/ -int aml_ci_spi_paser_bit(uint8_t value) -{ - /* read spi data from slave */ - if (G_rec_flag == AM_SPI_STEP_INIT) { - /* start type first */ - if (value == DATASTART) { - rbuf[0] = value; - G_rec_flag = AM_SPI_STEP_START1; - } - } else if (G_rec_flag == AM_SPI_STEP_START1) { - /* start2 type seccond */ - if (value == DATASTART) { - rbuf[1] = value; - G_rec_flag = AM_SPI_STEP_START2; - } - } else if (G_rec_flag == AM_SPI_STEP_START2) { - /* cmd type */ - /* pr_dbg("spi value=%d\r\n",value); */ - rbuf[2] = value; - G_rec_flag = AM_SPI_STEP_CMD; - } else if (G_rec_flag == AM_SPI_STEP_CMD) { - /* data */ - rbuf[3] = value; - G_rec_flag = AM_SPI_STEP_DATA; - } else if (G_rec_flag == AM_SPI_STEP_DATA) { - /* ADDR1 */ - rbuf[4] = value; - G_rec_flag = AM_SPI_STEP_ADDR1; - } else if (G_rec_flag == AM_SPI_STEP_ADDR1) { - /* ADDR2 type */ - rbuf[5] = value; - G_rec_flag = AM_SPI_STEP_ADDR2; - } else if (G_rec_flag == AM_SPI_STEP_ADDR2) { - /* END1 type */ - if (value == DATAEND) { - rbuf[6] = value; - G_rec_flag = AM_SPI_STEP_END1; - } - } else if (G_rec_flag == AM_SPI_STEP_END1) { - /* END2 type */ - if (value == DATAEND) { - rbuf[7] = value; - G_rec_flag = AM_SPI_STEP_END2; - /* pr_dbg("spi read value ok end\r\n"); */ - return 0; - } - } - return -1; -} - -/**\brief aml_spi_io_api:spi read or write api with mcu -* \param spi_dev: aml_spi obj,used this data to get spi obj -* \param val: write value -* \param len: write value len -* \param mode: read or write -* \return -* - read value:ok -* - -EINVAL : error -*/ -static int aml_spi_io_api(struct aml_spi *spi_dev, u8 *val, int len, int mode) -{ - u8 rb[32] = {0}; - int ret = 0; - int i = 0; - u8 rd = 0; - if (spi_dev->spi == NULL) { - pr_error("%s spi is null\r\n", __func__); - return -EINVAL; - } - spin_lock(&spi_dev->spi_lock); - if (spi_dev->cs_hold_delay) - udelay(spi_dev->cs_hold_delay); - dirspi_start(spi_dev->spi); - if (spi_dev->cs_clk_delay) - udelay(spi_dev->cs_clk_delay); - - dirspi_xfer(spi_dev->spi, val, rb, len); - /* wait mcu io */ - udelay(1000); - /* init rec flag */ - G_rec_flag = AM_SPI_STEP_INIT; - memset(rbuf, 0, 8); - for (i = 0; i < 4*len; i++) { - udelay(50); - ret = dirspi_read(spi_dev->spi, &rd, 1); - if (ret != 0) - pr_dbg("spi read value timeout:%x\r\n", rd); - ret = aml_ci_spi_paser_bit(rd); - if (ret == 0) - break; - } - if (ret == 0) { - rd = rbuf[3];/* data */ - } else { - pr_dbg("spi read value error\r\n"); - rd = 0; - } - - if (spi_dev->cs_clk_delay) - udelay(spi_dev->cs_clk_delay); - - /* pr_error("ci spi is stop in %s rd=%d\r\n",__func__,rd);*/ - dirspi_stop(spi_dev->spi); - - spin_unlock(&spi_dev->spi_lock); - - return rd; -} - -/********************************************************/ -/********************************************************/ -/******* gpio api *************/ -/********************************************************/ -/********************************************************/ -/**\brief aml_set_gpio_out:set gio out and set val value -* \param gpio: gpio_desc obj, -* \param val: set val -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int aml_set_gpio_out(struct gpio_desc *gpio, int val) -{ - int ret = 0; - if (val < 0) { - pr_dbg("gpio out val = -1.\n"); - return -1; - } - if (val != 0) - val = 1; - ret = gpiod_direction_output(gpio, val); - pr_dbg("dvb ci gpio out ret %d set val:%d\n", ret, val); - return ret; -} -#if 0 -/**\brief aml_set_gpio_in:set gio in -* \param gpio: gpio_desc obj, -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int aml_set_gpio_in(struct gpio_desc *gpio) -{ - gpiod_direction_input(gpio); - return 0; -} -#endif - -/**\brief aml_get_gpio_value:get gio value -* \param gpio: gpio_desc obj, -* \return -* - gpio value:ok -* - -EINVAL : error -*/ -static int aml_get_gpio_value(struct gpio_desc *gpio) -{ - int ret = 0; - ret = gpiod_get_value(gpio); - return ret; -} -/**\brief aml_gpio_free:free gio -* \param gpio: gpio_desc obj, -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int aml_gpio_free(struct gpio_desc *gpio) -{ - gpiod_put(gpio); - return 0; -} -/**\brief spi_get_gpio_by_name:get gpio desc from dts file -* \param spi_dev: aml_spi obj -* \param gpiod: gpio_desc * obj -* \param str: gpio name at dts file -* \param input_output: gpio input or output type -* \param output_value: gpio out put value -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int spi_get_gpio_by_name(struct aml_spi *spi_dev, -struct gpio_desc **gpiod, int *pin_value, -char *str, int input_output, int output_level) -{ - int ret = 0; - struct device_node *child = NULL; - struct platform_device *pdev = spi_dev->pdev; - struct device_node *np = pdev->dev.of_node; - - /*get spi and gpio config from dts*/ - /* get device config for dvbci_io*/ - child = of_get_child_by_name(np, "dvbci_io"); - if (IS_ERR(*gpiod)) { - pr_dbg("dvb ci spi %s request failed\n", str); - return -1; - } - - *pin_value = of_get_named_gpio_flags(child, str, 0, NULL); - *gpiod = gpio_to_desc(*pin_value); - if (IS_ERR(*gpiod)) { - pr_dbg("spi %s request failed\n", str); - return -1; - } - pr_dbg("spi get_gpio %s %p %d\n", str, *gpiod, *pin_value); - gpio_request(*pin_value, AML_MODE_NAME); - - if (input_output == OUTPUT) { - ret = gpiod_direction_output(*gpiod, output_level); - } else if (input_output == INPUT) { - ret = gpiod_direction_input(*gpiod); - /*ret |= gpiod_set_pullup(*gpiod, 1);*/ - } else { - pr_error("spi Request gpio direction invalid\n"); - } - return ret; -} -/********************************************************/ -/********************************************************/ -/******* gpio api end *************/ -/********************************************************/ -/********************************************************/ -#if 0 -/**\brief aml_ci_cis_test_by_spi:test cis -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param addr: read addr -* \return -* - test :ok -* - -EINVAL : error -*/ -/**\brief aml_ci_full_test_by_spi:ci full test -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param addr: read addr -* \return -* - read value:ok -* - -EINVAL : error -*/ -static int aml_ci_full_test_by_spi( - struct aml_ci *ci_dev, int slot, int addr) -{ - u8 data = 0; - u16 addres = addr; - int value = 0; - struct aml_spi *spi_dev = ci_dev->data; - aml_init_send_buf(AM_CI_CMD_FULLTEST, data, addres); - value = aml_spi_io_api(spi_dev, - sendbuf, SENDBUFLEN, AM_CI_CMD_FULLTEST); - pr_dbg("FULL : TEST END \r\n"); - return value; -} -#endif -/**\brief aml_ci_mem_read_by_spi:io read from cam -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param addr: read addr -* \return -* - read value:ok -* - -EINVAL : error -*/ -static int aml_ci_mem_read_by_spi( - struct aml_ci *ci_dev, int slot, int addr) -{ - u8 data = 0; - u16 addres = addr; - int value = 0; - struct aml_spi *spi_dev = ci_dev->data; - aml_init_send_buf(AM_CI_CMD_MEMR, data, addres); - value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_MEMR); - /*pr_dbg("Read : mem[%d] = 0x%x\n", addr, value);*/ - return value; -} -/**\brief aml_ci_mem_write_by_spi:io write to cam by spi api -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param addr: write addr -* \param addr: write value -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int aml_ci_mem_write_by_spi( - struct aml_ci *ci_dev, int slot, int addr, u8 val) -{ - u8 data = val; - u16 addres = addr; - int value = 0; - struct aml_spi *spi_dev = ci_dev->data; - aml_init_send_buf(AM_CI_CMD_MEMW, data, addres); - value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_MEMW); - /*pr_dbg("write : mem[%d] = 0x%x\n", addr, data);*/ -return value; -} -/**\brief aml_ci_io_read_by_spi:io read from cam by spi api -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param addr: read addr -* \return -* - read value:ok -* - -EINVAL : error -*/ -static int aml_ci_io_read_by_spi( - struct aml_ci *ci_dev, int slot, int addr) -{ - u8 data = 0; - u16 addres = addr; - int value = 0; - struct aml_spi *spi_dev = ci_dev->data; - aml_init_send_buf(AM_CI_CMD_IOR, data, addres); - value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_IOR); - /*pr_dbg("read : io[%d] = 0x%x\n", addr, value);*/ - return value; -} -/**\brief aml_ci_io_write_by_spi:io write to cam -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param addr: write addr -* \param addr: write value -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int aml_ci_io_write_by_spi( - struct aml_ci *ci_dev, int slot, int addr, u8 val) -{ - u8 data = val; - u16 addres = addr; - int value = 0; - struct aml_spi *spi_dev = ci_dev->data; - /*add by chl,need add time delay*/ - mdelay(10); - aml_init_send_buf(AM_CI_CMD_IOW, data, addres); - value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_IOW); - /*pr_dbg("write : ATTR[%d] = 0x%x\n", addr, data);*/ - return value; -} - - -/**\brief aml_ci_slot_reset:reset slot -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \return -* - 0:ok -* - -EINVAL : error -*/ -static int aml_ci_slot_reset(struct aml_ci *ci_dev, int slot) -{ - struct aml_spi *spi_dev = ci_dev->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); - aml_pcmcia_reset(&spi_dev->pc); - dvb_ca_en50221_camready_irq(&ci_dev->en50221, 0); - return 0; -} -/**\brief aml_ci_slot_shutdown:show slot -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \return -* - 0:ok -* - -EINVAL : error -* readme:no use this api -*/ -static int aml_ci_slot_shutdown(struct aml_ci *ci_dev, int slot) -{ - pr_dbg("Slot(%d): Slot shutdown\n", slot); - return 0; -} -/**\brief aml_ci_ts_control:control slot ts -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \return -* - 0:ok -* - -EINVAL : error -* readme:no use this api -*/ -static int aml_ci_ts_control(struct aml_ci *ci_dev, int slot) -{ - pr_dbg("Slot(%d): TS control\n", slot); - return 0; -} -/**\brief aml_ci_slot_status:get slot status -* \param ci_dev: aml_ci obj,used this data to get spi_dev obj -* \param slot: slot index -* \param open: no used -* \return -* - cam status -* - -EINVAL : error -*/ -static int aml_ci_slot_status(struct aml_ci *ci_dev, int slot, int open) -{ - struct aml_spi *spi_dev = ci_dev->data; - - pr_dbg("Slot(%d): Poll Slot status\n", slot); - - if (spi_dev->pc.slot_state == MODULE_INSERTED) { - pr_dbg("CA Module present and ready\n"); - return DVB_CA_EN50221_POLL_CAM_PRESENT | - DVB_CA_EN50221_POLL_CAM_READY; - } else { - pr_error("CA Module not present or not ready\n"); - } - return -EINVAL; -} -#if 0 -/**\brief aml_ci_gio_get_irq:get gpio cam irq pin value -* \return -* - irq pin value -* - -EINVAL : error -*/ -static int aml_ci_gio_get_irq(void) -{ - int ret = 0; - ret = aml_get_gpio_value(g_spi_dev->irq_cam_pin); - return ret; -} -#endif - -/********************************************************/ -/********************************************************/ -/******* for pcmcid api *************/ -/********************************************************/ -/********************************************************/ -/**\brief aml_gio_power:set power gpio hi or low -* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj -* \param enable: power pin hi or low -* \return -* - 0 -* - -EINVAL : error -*/ -static int aml_gio_power(struct aml_pcmcia *pc, int enable) -{ - int ret = 0; - struct aml_spi *spi_dev = pc->priv; - if (spi_dev == NULL) { - pr_dbg("spi dev is null %s : %d\r\n", __func__, enable); - return -1; - } - pr_dbg("%s : %d\r\n", __func__, enable); - if (enable == AML_PWR_OPEN) { - /*hi level ,open power*/ - ret = aml_set_gpio_out(spi_dev->pwr_pin, AML_GPIO_HIGH); - } else { - /*low level ,close power*/ - ret = aml_set_gpio_out(spi_dev->pwr_pin, AML_GPIO_LOW); - } - return ret; -} -/**\brief aml_gio_reset:set reset gpio hi or low -* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj -* \param enable: reset pin hi or low -* \return -* - 0 -* - -EINVAL : error -*/ -static int aml_gio_reset(struct aml_pcmcia *pc, int enable) -{ - /*need set hi and sleep set low*/ - int ret = 0; - struct aml_spi *spi_dev = pc->priv; - pr_dbg("%s : %d\r\n", __func__, enable); - if (enable == AML_L) - ret = aml_set_gpio_out(spi_dev->reset_pin, AML_GPIO_LOW); - else - ret = aml_set_gpio_out(spi_dev->reset_pin, AML_GPIO_HIGH); - return ret; -} - -/**\brief aml_gio_init_irq:set gpio irq -* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj -* \param flag: rising or falling or hi or low -* \return -* - 0 -* - -EINVAL : error -*/ -/*need change*/ -static int aml_gio_init_irq(struct aml_pcmcia *pc, int flag) - { - struct aml_spi *spi_dev = (struct aml_spi *)pc->priv; - -#if 0 - int cd1_pin = desc_to_gpio(spi_dev->cd_pin1); - - int irq = pc->irq-AML_CI_GPIO_IRQ_BASE; - - printk("----cd1_pin=%d irq=%d\r\n", cd1_pin, irq); - aml_set_gpio_in(spi_dev->cd_pin1); - - if (flag == IRQF_TRIGGER_RISING) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_RISING)); - else if (flag == IRQF_TRIGGER_FALLING) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_FALLING)); - else if (flag == IRQF_TRIGGER_HIGH) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_HIGH)); - else if (flag == IRQF_TRIGGER_LOW) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_LOW)); - else - return -1; -#endif - gpiod_to_irq(spi_dev->cd_pin1); - - return 0; - } - -/**\brief aml_gio_get_cd1:get gpio cd1 pin value -* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj -* \return -* - cd1 pin value -* - -EINVAL : error -*/ -static int aml_gio_get_cd1(struct aml_pcmcia *pc) -{ - int ret = 0; - struct aml_spi *spi_dev = pc->priv; - ret = aml_get_gpio_value(spi_dev->cd_pin1); - return ret; -} -/**\brief aml_gio_get_cd2:get gpio cd2 pin value -* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj -* \return -* - cd2 pin value -* - -EINVAL : error -*/ -static int aml_gio_get_cd2(struct aml_pcmcia *pc) -{ - int ret = 0; - struct aml_spi *spi_dev = pc->priv; - ret = aml_get_gpio_value(spi_dev->cd_pin2); - pr_dbg("%s : %d\r\n", __func__, ret); - return ret; -} -/**\brief aml_cam_plugin:notify en50221 cam card in or out -* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj -* \plugin: 0:remove;1:in -* \return -* - 0 -* - -EINVAL : error -*/ -static int aml_cam_plugin(struct aml_pcmcia *pc, int plugin) -{ - struct aml_ci *ci = (struct aml_ci *) - ((struct aml_spi *)(pc->priv))->priv; - pr_dbg("%s : %d\r\n", __func__, plugin); - if (plugin) { - dvb_ca_en50221_camchange_irq(&ci->en50221, - 0, DVB_CA_EN50221_CAMCHANGE_INSERTED); - } else { - dvb_ca_en50221_camchange_irq(&ci->en50221, - 0, DVB_CA_EN50221_CAMCHANGE_REMOVED); - } - return 0; -} -/**\brief aml_pcmcia_alloc:alloc nad init pcmcia obj -* \param spi_dev: aml_spi obj, -* \param pcmcia: aml_pcmcia * obj, -* \return -* - 0 -* - -EINVAL : error -*/ -static void aml_pcmcia_alloc(struct aml_spi *spi_dev, - struct aml_pcmcia **pcmcia) -{ - pr_dbg("aml_pcmcia_alloc----\n"); - *pcmcia = &spi_dev->pc; - (*pcmcia)->irq = spi_dev->irq; - (*pcmcia)->init_irq = aml_gio_init_irq; - (*pcmcia)->get_cd1 = aml_gio_get_cd1; - (*pcmcia)->get_cd2 = aml_gio_get_cd2; - (*pcmcia)->pwr = aml_gio_power; - (*pcmcia)->rst = aml_gio_reset; - (*pcmcia)->pcmcia_plugin = aml_cam_plugin; - (*pcmcia)->slot_state = MODULE_XTRACTED; - (*pcmcia)->priv = spi_dev; - (*pcmcia)->run_type = 0;/*0:irq;1:poll*/ -} - -/**\brief aml_spi_get_config_from_dts:get spi config and gpio config from dts -* \param spi_dev: aml_spi obj, -* \return -* - 0 -* - -EINVAL : error -*/ -static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) -{ - struct device_node *child = NULL; - struct platform_device *pdev = spi_dev->pdev; - struct device_node *np = pdev->dev.of_node; - unsigned int temp[5], val; - int ret = 0; - pr_dbg("into get spi dts \r\n"); - - /*get spi and gpio config from dts*/ - /* get device config for dvbci_io*/ - child = of_get_child_by_name(np, "dvbci_io"); - if (child == NULL) { - pr_error("failed to get dvbci_io\n"); - return -1; - } - spi_dev->spi_bdinfo = &aml_ci_spi_bdinfo; - /* get spi config */ - ret = of_property_read_u32_array(child, "spi_bus_num", temp, 1); - if (ret) { - pr_error("failed to get spi_bus_num\n"); - } else { - aml_ci_spi_bdinfo.bus_num = temp[0]; - pr_dbg("bus_num: %d\n", aml_ci_spi_bdinfo.bus_num); - } - ret = of_property_read_u32_array(child, "spi_chip_select", - temp, 1); - if (ret) { - pr_error("failed to get spi_chip_select\n"); - } else { - aml_ci_spi_bdinfo.chip_select = temp[0]; - pr_dbg("chip_select: %d\n", aml_ci_spi_bdinfo.chip_select); - } - ret = of_property_read_u32_array(child, "spi_max_frequency", - temp, 1); - if (ret) { - pr_error("failed to get spi_chip_select\n"); - } else { - aml_ci_spi_bdinfo.max_speed_hz = temp[0]; - pr_dbg("max_speed_hz: %d\n", aml_ci_spi_bdinfo.max_speed_hz); - } - ret = of_property_read_u32_array(child, "spi_mode", temp, 1); - if (ret) { - pr_error("failed to get spi_mode\n"); - } else { - aml_ci_spi_bdinfo.mode = temp[0]; - pr_dbg("mode: %d\n", aml_ci_spi_bdinfo.mode); - } - ret = of_property_read_u32_array(child, "spi_cs_delay", - &temp[0], 2); - if (ret) { - spi_dev->cs_hold_delay = 0; - spi_dev->cs_clk_delay = 0; - } else { - spi_dev->cs_hold_delay = temp[0]; - spi_dev->cs_clk_delay = temp[1]; - } - ret = of_property_read_u32(child, "spi_write_check", &val); - if (ret) - spi_dev->write_check = 0; - else - spi_dev->write_check = (unsigned char)val; - /*get cd1 irq num*/ - ret = of_property_read_u32(child, "irq_cd1", &val); - if (ret) { - spi_dev->irq = 5; - } else { - /*set irq value need add - AML_CI_GPIO_IRQ_BASE,but - we need minus - AML_CI_GPIO_IRQ_BASE - when gpio request irq */ - spi_dev->irq = val+AML_CI_GPIO_IRQ_BASE; - } - - spi_dev->irq = irq_of_parse_and_map( - pdev->dev.of_node, 0); - AML_CI_GPIO_IRQ_BASE = spi_dev->irq - val; - pr_dbg("get spi irq : %d 0:%d USEDBASE:%d val:%d\r\n", - spi_dev->irq, INT_GPIO_0, AML_CI_GPIO_IRQ_BASE, val); - /*get reset pwd cd1 cd2 gpio pin*/ - spi_dev->reset_pin = NULL; - ret = spi_get_gpio_by_name(spi_dev, &spi_dev->reset_pin, - &spi_dev->reset_pin_value, "reset_pin", - OUTPUT, OUTLEVEL_HIGH); - if (ret) { - pr_error("dvb ci reset pin request failed\n"); - return -1; - } - spi_dev->cd_pin1 = NULL; - ret = spi_get_gpio_by_name(spi_dev, - &spi_dev->cd_pin1, - &spi_dev->cd_pin1_value, "cd_pin1", - INPUT, OUTLEVEL_HIGH); - if (ret) { - pr_error("dvb ci cd_pin1 pin request failed\n"); - return -1; - } - spi_dev->cd_pin2 = spi_dev->cd_pin1; - spi_dev->cd_pin2_value = spi_dev->cd_pin1_value; - spi_dev->pwr_pin = NULL; - pr_dbg("spi_dev->cd_pin1_value==%d\r\n", spi_dev->cd_pin1_value); - ret = spi_get_gpio_by_name(spi_dev, - &spi_dev->pwr_pin, &spi_dev->pwr_pin_value, - "pwr_pin", OUTPUT, OUTLEVEL_HIGH); - if (ret) { - pr_error("dvb ci pwr_pin pin request failed\n"); - return -1; - } - spi_dev->irq_cam_pin = NULL; - ret = spi_get_gpio_by_name(spi_dev, - &spi_dev->irq_cam_pin, &spi_dev->irq_cam_pin_value, - "irq_cam_pin", INPUT, OUTLEVEL_HIGH); - if (ret) { - pr_error("dvbci irq_cam_pin pin request failed\n"); - return -1; - } - - return 0; -} -/**\brief aml_ci_free_gpio:free ci gpio -* \param spi_dev: aml_spi obj, -* \return -* - 0 -* - -EINVAL : error -*/ -static void aml_ci_free_gpio(struct aml_spi *spi_dev) -{ - if (spi_dev == NULL) { - pr_error("spi_dev is NULL,no need free gpio res\r\n"); - return; - } - - if (spi_dev->pwr_pin) { - aml_gpio_free(spi_dev->pwr_pin); - spi_dev->pwr_pin = NULL; - } - if (spi_dev->cd_pin1) { - aml_gpio_free(spi_dev->cd_pin1); - spi_dev->cd_pin1 = NULL; - spi_dev->cd_pin2 = NULL; - } - if (spi_dev->reset_pin) { - aml_gpio_free(spi_dev->reset_pin); - spi_dev->reset_pin = NULL; - } - if (spi_dev->irq_cam_pin) { - aml_gpio_free(spi_dev->irq_cam_pin); - spi_dev->irq_cam_pin = NULL; - } - return; -} - - -/**\brief ci_spi_dev_remove:spi probe api -* \param spi: spi obj, -* \return -* - 0 -* - -EINVAL : error -*/ -static int ci_spi_dev_probe(struct spi_device *spi) -{ - int ret; - pr_dbg("spi Dev probe--\n"); - if (g_spi_dev) - g_spi_dev->spi = spi; - else - pr_dbg("spi Dev probe-error-\n"); - spi->bits_per_word = 8; - ret = spi_setup(spi); - if (ret) - pr_dbg("spi setup failed\n"); - return ret; -} -/**\brief ci_spi_dev_remove:spi remove api -* \param spi: spi obj, -* \return -* - 0 -* - -EINVAL : error -*/ -static int ci_spi_dev_remove(struct spi_device *spi) -{ - pr_dbg("spi Dev remove--\n"); - if (g_spi_dev) - g_spi_dev->spi = NULL; - - return 0; -} - -static struct spi_driver ci_spi_dev_driver = { - .probe = ci_spi_dev_probe, - .remove = ci_spi_dev_remove, - .driver = { - .name = "ci_spi_dev",/*set same with board info modalias*/ - .owner = THIS_MODULE, - }, -}; -/**\brief aml_spi_init:spi_dev init -* \param ci_dev: aml_ci obj, -* \param pdev: platform_device obj,used to get dts info -* \return -* - 0 -* - -EINVAL : error -*/ -int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) -{ - struct aml_spi *spi_dev = NULL; - struct aml_pcmcia *pc; - int result; - - spi_dev = kmalloc(sizeof(struct aml_spi), GFP_KERNEL); - if (!spi_dev) { - pr_error("Out of memory!, exiting ..\n"); - result = -ENOMEM; - goto err; - } - g_spi_dev = spi_dev; - spi_dev->pdev = pdev; - spi_dev->priv = ci_dev; - /*get config from dts*/ - aml_spi_get_config_from_dts(spi_dev); - /*regist api dev*/ - spi_register_board_info(spi_dev->spi_bdinfo, 1); - result = spi_register_driver(&ci_spi_dev_driver); - if (result) { - pr_error("register amlspi_dev spi driver failed\n"); - goto fail1; - } - aml_pcmcia_alloc(spi_dev, &pc); - result = aml_pcmcia_init(pc); - if (result < 0) { - pr_error("aml_pcmcia_init failed\n"); - goto fail2; - } - - /*init ci_dev used api.*/ - ci_dev->ci_mem_read = aml_ci_mem_read_by_spi; - ci_dev->ci_mem_write = aml_ci_mem_write_by_spi; - ci_dev->ci_io_read = aml_ci_io_read_by_spi; - ci_dev->ci_io_write = aml_ci_io_write_by_spi; - ci_dev->ci_slot_reset = aml_ci_slot_reset; - ci_dev->ci_slot_shutdown = aml_ci_slot_shutdown; - ci_dev->ci_slot_ts_enable = aml_ci_ts_control; - ci_dev->ci_poll_slot_status = aml_ci_slot_status; - ci_dev->data = spi_dev; - /*init spi_lock*/ - spin_lock_init(&(spi_dev->spi_lock)); - return 0; -fail2: - spi_unregister_driver(&ci_spi_dev_driver); -fail1: - kfree(spi_dev); - spi_dev = NULL; -err: - return -1; -} -EXPORT_SYMBOL(aml_spi_init); -/**\brief aml_spi_exit:spi exit -* \return -* - 0 -* - -EINVAL : error -*/ -int aml_spi_exit(struct aml_ci *ci) -{ - /*exit pc card*/ - aml_pcmcia_exit(&g_spi_dev->pc); - /*un regist spi driver*/ - spi_unregister_driver(&ci_spi_dev_driver); - /*free gpio*/ - aml_ci_free_gpio(g_spi_dev); - /*free spi dev*/ - kfree(g_spi_dev); - g_spi_dev = NULL; - - return 0; -} -EXPORT_SYMBOL(aml_spi_exit); - - -#if 0 -/********************************************************/ -/********************************************************/ -/******* for spi test api *************/ -/********************************************************/ -/********************************************************/ - -/*cam difines*/ -#define DA 0x80 -#define FR 0x40 -#define WE 0x02 -#define RE 0x01 - -#define RS 0x08 -#define SR 0x04 -#define SW 0x02 -#define HC 0x01 -#define DATA_REG 0 -#define COM_STA_REG 1 -#define SIZE_REG_L 2 -#define SIZE_REG_M 3 -static void aml_spi_ca_full_test(struct aml_ci *ci_dev) -{ - unsigned int BUF_SIZE = 0; - unsigned int i = 0; - unsigned char cc = 0; - unsigned char reg; - unsigned int bsize = 0; - int cnt = 0; - unsigned char buf[10]; - int count = 1000; - mdelay(1000); - pr_dbg("READ CIS START\r\n"); - for (i = 0; i < 267; i++) { - mdelay(100); - cc = aml_ci_mem_read_by_spi(ci_dev, 0, i); - pr_dbg("0x%x ", cc); - if ((i + 1) % 16 == 0) - pr_dbg(" \r\n"); - } - pr_dbg("READ CIS OVER\r\n"); - mdelay(1000); - pr_dbg("SW rst CAM...\r\n"); - aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, RS); - pr_dbg("SW rst over.\r\n"); - pr_dbg("-----------------------------------\r\n"); - pr_dbg("TO delay 2000ms\r\n"); - mdelay(2000); - pr_dbg("\r\n"); - pr_dbg("--------------clear rs--!!!-YOU MUST CLEAR RS BIT--no sleep--------\r\n"); - aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, 0); - pr_dbg("--------------sleep---------------------\r\n"); - mdelay(2000); - pr_dbg("TO check sw-rst is OK\r\n"); - pr_dbg("start read fr \r\n"); - if (1) { - unsigned char reg; - unsigned char reg1; - int count1 = 4000; - while (1) { - mdelay(20); - count1--; - reg1 = aml_ci_io_read_by_spi( - ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg1)) { - continue; - } else { - pr_dbg("CAM Reset Ok\r\n"); - break; - } - } - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - pr_dbg("STA_REG = 0x%2.2x\r\n", reg); - if (FR & reg) { - pr_dbg("SW-RST is OK!\r\n"); - } else { - pr_dbg("SW-RST is ERR!\r\n"); - goto end; - } - } -end: - pr_dbg("TO check sw-rst over.\r\n"); - pr_dbg("\r\n"); - pr_dbg("-----------------------------------\r\n"); - pr_dbg("TO buffer size negotiation protocol...\r\n"); - pr_dbg("Get which buf size CAM can support\r\n"); - aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, SR); - mdelay(1000); - while (1) { - - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if ((reg & DA) == DA) { - pr_dbg("Buffer negotiate size date avalible.\r\n"); - break; - } else { - /*pr_dbg("Buffer negotiate - size date NOT avalible\r\n");*/ - continue; - } - mdelay(100); - } - cnt = (aml_ci_io_read_by_spi(ci_dev, 0, SIZE_REG_L)) + - ((aml_ci_io_read_by_spi(ci_dev, 0, SIZE_REG_M)) * 256); - pr_dbg("Moudle have <%d> Bytes send to host.\r\n", cnt); - if (cnt != 2) { - pr_dbg("The Bytes will be tx is ERR!\r\n"); - return; - } - for (i = 0; i < cnt; i++) - buf[i] = aml_ci_io_read_by_spi(ci_dev, 0, DATA_REG); - - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (RE == (RE & reg)) { - pr_dbg("(1)Read CAM buf size ERR!\r\n"); - return; - } - aml_ci_io_write_by_spi(ci_dev, 0, (COM_STA_REG), 0); - - mdelay(1000); - - while (count--) { - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg)) { - pr_dbg("CAM is busy 2, waiting...\r\n"); - continue; - } else { - pr_dbg("CAM is OK 2.\r\n"); - break; - } - } - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg)) { - pr_dbg("(2)Read CAM buf size ERR!-\r\n"); - return; - } - bsize = (buf[0] * 256) + buf[1]; - - pr_dbg("CAM can support buf size is: <%d>B\r\n", bsize); - - pr_dbg("Tell CAM which size buf is be used\r\n"); - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg)) - pr_dbg("CAM is busy, waiting free\r\n"); - while (1) { - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg)) { - pr_dbg("CAM is busy 3, waiting\r\n"); - continue; - } else { - pr_dbg("CAM is OK 3\r\n"); - break; - } - } - - bsize = bsize - 0; - BUF_SIZE = bsize; - pr_dbg("We will use this buf size: <%d>B\r\n", bsize); - aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, SW); - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg)) - pr_dbg("CAM is busy, waiting\r\n"); - - while (1) { - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (FR != (FR & reg)) { - pr_dbg("CAM is busy 4, waiting\r\n"); - continue; - } else { - pr_dbg("CAM is OK 4\r\n"); - break; - } - } - /*SHOULD CHECK DA!!!!!*/ - /*PLS ADD THIS CHECK CODE:*/ - pr_dbg("PRIOR to check CAM'S DA\r\n"); - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if ((reg & DA) == DA) { - pr_dbg("CAM have data send to HOST\r\n"); - return; - } - - - buf[0] = (unsigned char)((bsize >> 8) & 0xff); - buf[1] = (unsigned char)(bsize & 0xff); - - while (1) { - mdelay(10); - aml_ci_io_write_by_spi(ci_dev, - 0, COM_STA_REG, HC | SW); - mdelay(100); - reg = aml_ci_io_read_by_spi(ci_dev, - 0, COM_STA_REG); - if (FR != (FR & reg)) { - pr_dbg("CAM is busy 5, waiting\r\n"); - aml_ci_io_write_by_spi(ci_dev, - 0, COM_STA_REG, SW); - continue; - } else { - pr_dbg("CAM is OK 5\r\n"); - break; - } - } - pr_dbg("<2> Bytes send to CAM\r\n"); - aml_ci_io_write_by_spi(ci_dev, 0, SIZE_REG_M, 0); - aml_ci_io_write_by_spi(ci_dev, 0, SIZE_REG_L, 2); - for (i = 0; i < 2; i++) - aml_ci_io_write_by_spi(ci_dev, 0, DATA_REG, buf[i]); - - reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); - if (WE == (WE & reg)) { - pr_dbg("Write CAM ERR!\r\n"); - return; - } else { - aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, SW); - mdelay(100); - aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, 0); - pr_dbg("Buffer size negotiation over!\r\n"); - pr_dbg("NOW, HOST can communicates with CAM\r\n"); - pr_dbg("NOW, TEST END\r\n"); - } -} - -/** -* Read a tuple from attribute memory. -* -* @param ca CA instance. -* @param slot Slot id. -* @param address Address to read from. Updated. -* @param tupleType Tuple id byte. Updated. -* @param tupleLength Tuple length. Updated. -* @param tuple Dest buffer for tuple (must be 256 bytes). Updated. -* -* @return 0 on success, nonzero on error. -*/ -static int dvb_ca_en50221_read_tuple( -int *address, int *tupleType, int *tupleLength, u8 *tuple) -{ - int i; - int _tupleType; - int _tupleLength; - int _address = *address; - - /* grab the next tuple length and type */ - _tupleType = aml_ci_mem_read_by_spi((struct aml_ci *) - g_spi_dev->priv, 0, _address); - if (_tupleType < 0) - return _tupleType; - if (_tupleType == 0xff) { - pr_dbg("END OF CHAIN TUPLE type:0x%x\n", _tupleType); - *address += 2; - *tupleType = _tupleType; - *tupleLength = 0; - return 0; - } - _tupleLength = aml_ci_mem_read_by_spi((struct aml_ci *) - g_spi_dev->priv, 0, _address + 2); - if (_tupleLength < 0) - return _tupleLength; - _address += 4; - - pr_dbg("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); - - /* read in the whole tuple */ - for (i = 0; i < _tupleLength; i++) { - tuple[i] = aml_ci_mem_read_by_spi((struct aml_ci *) - g_spi_dev->priv, 0, _address + (i * 2)); - pr_dbg(" 0x%02x: 0x%02x %c\n", - i, tuple[i] & 0xff, - ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); - } - _address += (_tupleLength * 2); - - /* success */ - *tupleType = _tupleType; - *tupleLength = _tupleLength; - *address = _address; - return 0; -} -static char *findstr(char *haystack, int hlen, char *needle, int nlen) -{ - int i; - - if (hlen < nlen) - return NULL; - - for (i = 0; i <= hlen - nlen; i++) { - if (!strncmp(haystack + i, needle, nlen)) - return haystack + i; - } - - return NULL; -} - -/** -* Parse attribute memory of a CAM module, extracting Config register, and checking -* it is a DVB CAM module. -* -* @param ca CA instance. -* @param slot Slot id. -* -* @return 0 on success, <0 on failure. -*/ -static int dvb_ca_en50221_parse_attributes(void) -{ - int address = 0; - int tupleLength; - int tupleType; - u8 tuple[257]; - char *dvb_str; - int rasz; - int status; - int got_cftableentry = 0; - int end_chain = 0; - int i; - u16 manfid = 0; - u16 devid = 0; - int config_base = 0; - int config_option; - - /* CISTPL_DEVICE_0A */ - status = dvb_ca_en50221_read_tuple(&address, - &tupleType, &tupleLength, tuple); - if (status < 0) { - pr_error("read status error\r\n"); - return status; - } - if (tupleType != 0x1D) { - pr_error("read tupleType error [0x%x]\r\n", tupleType); - return -EINVAL; - } - - - - /* CISTPL_DEVICE_0C */ - status = dvb_ca_en50221_read_tuple(&address, - &tupleType, &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis error\r\n"); - return status; - } - if (tupleType != 0x1C) { - pr_error("read read cis type error\r\n"); - return -EINVAL; - } - - - - /* CISTPL_VERS_1 */ - status = dvb_ca_en50221_read_tuple(&address, - &tupleType, &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis version error\r\n"); - return status; - } - if (tupleType != 0x15) { - pr_error("read read cis version type error\r\n"); - return -EINVAL; - } - - - - /* CISTPL_MANFID */ - status = dvb_ca_en50221_read_tuple(&address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis manfid error\r\n"); - return status; - } - if (tupleType != 0x20) { - pr_error("read read cis manfid type error\r\n"); - return -EINVAL; - } - if (tupleLength != 4) { - pr_error("read read cis manfid len error\r\n"); - return -EINVAL; - } - manfid = (tuple[1] << 8) | tuple[0]; - devid = (tuple[3] << 8) | tuple[2]; - - - - /* CISTPL_CONFIG */ - status = dvb_ca_en50221_read_tuple(&address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis config error\r\n"); - return status; - } - if (tupleType != 0x1A) { - pr_error("read read cis config type error\r\n"); - return -EINVAL; - } - if (tupleLength < 3) { - pr_error("read read cis config len error\r\n"); - return -EINVAL; - } - - /* extract the configbase */ - rasz = tuple[0] & 3; - if (tupleLength < (3 + rasz + 14)) { - pr_error("read extract the configbase error\r\n"); - return -EINVAL; - } - - for (i = 0; i < rasz + 1; i++) - config_base |= (tuple[2 + i] << (8 * i)); - - - /* check it contains the correct DVB string */ - dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8); - if (dvb_str == NULL) { - pr_error("find dvb str DVB_CI_V error\r\n"); - return -EINVAL; - } - if (tupleLength < ((dvb_str - (char *) tuple) + 12)) { - pr_error("find dvb str DVB_CI_V len error\r\n"); - return -EINVAL; - } - - /* is it a version we support? */ - if (strncmp(dvb_str + 8, "1.00", 4)) { - pr_error(" Unsupported DVB CAM module version %c%c%c%c\n", - dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); - return -EINVAL; - } - -/* process the CFTABLE_ENTRY tuples, and any after those */ -while ((!end_chain) && (address < 0x1000)) { - status = dvb_ca_en50221_read_tuple(&address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("process the CFTABLE_ENTRY tuples error\r\n"); - return status; - } - - switch (tupleType) { - case 0x1B: /* CISTPL_CFTABLE_ENTRY */ - if (tupleLength < (2 + 11 + 17)) - break; - - /* if we've already parsed one, just use it */ - if (got_cftableentry) - break; - - /* get the config option */ - config_option = tuple[0] & 0x3f; - - /* OK, check it contains the correct strings */ - if ((findstr((char *)tuple, - tupleLength, "DVB_HOST", 8) == NULL) || - (findstr((char *)tuple, - tupleLength, "DVB_CI_MODULE", 13) == NULL)) - break; - - - got_cftableentry = 1; - break; - - case 0x14: /* CISTPL_NO_LINK*/ - break; - - case 0xFF: /* CISTPL_END */ - end_chain = 1; - break; - - default: - /* Unknown tuple type - just skip - *this tuple and move to the next one - */ -pr_error("Skipping unknown tupletype:0x%x L:0x%x\n", - tupleType, tupleLength); - break; - } - } - - if ((address > 0x1000) || (!got_cftableentry)) { - pr_error("got_cftableentry :%d\r\n", got_cftableentry); - return -EINVAL; - } - - pr_error("----------ci cis ok-----\r\n"); - return 0; -} - -static ssize_t aml_spi_ci_reset_help(struct class *class, -struct class_attribute *attr, char *buf) -{ - int ret; - ret = sprintf(buf, "echo 1 > %s\n\t", attr->attr.name); - return ret; -} - -static ssize_t aml_spi_ci_reset(struct class *class, -struct class_attribute *attr, const char *buf, size_t size) -{ - int ret; - struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - ret = aml_ci_slot_reset(ci, 0); - return size; -} - -static ssize_t aml_spi_ci_pwr_help(struct class *class, -struct class_attribute *attr, char *buf) -{ - int ret; - ret = sprintf(buf, "echo 1|0> %s\n\t", attr->attr.name); - return ret; -} - -static ssize_t aml_spi_ci_pwr(struct class *class, -struct class_attribute *attr, const char *buf, size_t size) -{ - int ret = 0; - int enable = 0; - long value; - if (kstrtol(buf, 0, &value) == 0) - enable = (int)value; - ret = aml_gio_power(&g_spi_dev->pc, enable); - return size; -} -static ssize_t aml_spi_ci_state_show(struct class *class, -struct class_attribute *attr, char *buf) -{ - int ret; - struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - ret = aml_ci_slot_status(ci, 0, 0); - ret = sprintf(buf, "%s: %d;\n\t", attr->attr.name, ret); - return ret; -} - -static ssize_t aml_spi_ci_irq_show(struct class *class, -struct class_attribute *attr, char *buf) -{ - int ret; - ret = aml_ci_gio_get_irq(); - ret = sprintf(buf, "%s irq: %d\n\t", attr->attr.name, ret); - return ret; -} - -static ssize_t aml_spi_io_test_help(struct class *class, -struct class_attribute *attr, char *buf) -{ - int ret; - ret = sprintf(buf, "echo (r|w|f|c)(i|a) addr data > %s\n", - attr->attr.name); - return ret; -} - -static ssize_t aml_spi_io_test(struct class *class, -struct class_attribute *attr, const char *buf, size_t size) -{ - int n = 0; - char *buf_orig, *ps, *token; - char *parm[3]; - unsigned int addr = 0, val = 0, retval = 0; - long value = 0; - struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - buf_orig = kstrdup(buf, GFP_KERNEL); - ps = buf_orig; - while (1) { - /*need set '\n' to ' \n'*/ - token = strsep(&ps, "\n"); - if (token == NULL) - break; - if (*token == '\0') - continue; - parm[n++] = token; - } - - if (!n || ((n > 0) && (strlen(parm[0]) != 2))) { - pr_err("invalid command\n"); - kfree(buf_orig); - return size; - } - - if ((parm[0][0] == 'r')) { - if (n != 2) { - pr_err("read: invalid parameter\n"); - kfree(buf_orig); - return size; - } - if (kstrtol(parm[1], 0, &value) == 0) - addr = (int)value; - pr_err("%s 0x%x\n", parm[0], addr); - /* switch ((char)parm[0][1]) { - case 'i': - retval = aml_ci_io_read_by_spi(ci, 0, addr); - break; - case 'a': - retval = aml_ci_mem_read_by_spi(ci, 0, addr); - break; - default: - break; - }*/ - pr_dbg("%s: 0x%x --> 0x%x\n", parm[0], addr, retval); - } else if ((parm[0][0] == 'w')) { - if (n != 3) { - pr_err("write: invalid parameter\n"); - kfree(buf_orig); - return size; - } - if (kstrtol(parm[1], 0, &value) == 0) - addr = (int)value; - if (kstrtol(parm[2], 0, &value) == 0) - val = (int)value; - - pr_err("%s 0x%x 0x%x", parm[0], addr, val); - /*switch ((char)parm[0][1]) { - case 'i': -retval = aml_ci_io_write_by_spi(ci, 0, addr, val); - break; - case 'a': -retval = aml_ci_mem_write_by_spi(ci, 0, addr, val); - break; - default: - break; - }*/ - pr_dbg("%s: 0x%x <-- 0x%x\n", parm[0], addr, retval); - } else if ((parm[0][0] == 'f')) { - pr_dbg("full test----\r\n"); - aml_spi_ca_full_test(ci); - } else if ((parm[0][0] == 'c')) { - pr_dbg("cis test----\r\n"); - aml_ci_full_test_by_spi(ci, 0, addr); - } else if ((parm[0][0] == 'p')) { - pr_dbg("cis dvb_ca_en50221_parse_attributes----\r\n"); - dvb_ca_en50221_parse_attributes(); - } - - kfree(buf_orig); - return size; -} - -static struct class_attribute aml_spi_class_attrs[] = { - __ATTR(reset, S_IRUGO | S_IWUSR, - aml_spi_ci_reset_help, aml_spi_ci_reset), - __ATTR(pwr, S_IRUGO | S_IWUSR, - aml_spi_ci_pwr_help, aml_spi_ci_pwr), - __ATTR(irq, S_IRUGO | S_IWUSR, - aml_spi_ci_irq_show, NULL), - __ATTR(status, S_IRUGO | S_IWUSR, - aml_spi_ci_state_show, NULL), - __ATTR(iotest, S_IRUGO | S_IWUSR, - aml_spi_io_test_help, aml_spi_io_test), - __ATTR_NULL -}; - -static struct class aml_spi_class = { - .name = "aml_dvb_spi_test", - .class_attrs = aml_spi_class_attrs, -}; - -static int aml_spi_mod_init(void) -{ - int ret; - pr_dbg("Amlogic DVB SPI Init\n"); - ret = class_register(&aml_spi_class); - return 0; -} - -static void aml_spi_mod_exit(void) -{ - pr_dbg("Amlogic DVB SPI Exit\n"); - class_unregister(&aml_spi_class); -} - -module_init(aml_spi_mod_init); -module_exit(aml_spi_mod_exit); - -MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h deleted file mode 100644 index 43d0d162e32e..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef __AML_SPI_H_ -#define __AML_SPI_H_ - -#include -#include -#include "aml_pcmcia.h" -#include "aml_ci.h" -#include "drivers/media/dvb-core/dvb_ca_en50221.h" - -/* -aml spi dev -*/ -struct aml_spi { - spinlock_t spi_lock; - - /* add SPI DEV */ - struct spi_board_info *spi_bdinfo; - struct spi_device *spi; - struct platform_device *pdev; - struct device *dev; - - /* spi otherconfig */ - int cs_hold_delay; - int cs_clk_delay; - int write_check; - - /* add gpio pin */ - struct gpio_desc *reset_pin; - int reset_pin_value; - struct gpio_desc *cd_pin1; - int cd_pin1_value; - struct gpio_desc *cd_pin2; - int cd_pin2_value; - struct gpio_desc *pwr_pin; - int pwr_pin_value; - - /* cam and mcu irq */ - struct gpio_desc *irq_cam_pin; - int irq_cam_pin_value; - int irq; - struct aml_pcmcia pc; - void *priv; -}; -enum aml_gpio_level_e { - AML_GPIO_LOW = 0, - AML_GPIO_HIGH -}; - -/* used to mcu */ -#define DATASTART 0xef -#define DATAEND 0xfe -enum AM_CI_CMD { - AM_CI_CMD_IOR = 0, - AM_CI_CMD_IOW, - AM_CI_CMD_MEMR, - AM_CI_CMD_MEMW, - AM_CI_CMD_FULLTEST, - AM_CI_CMD_CISTEST -}; -enum AM_SPI_RECIVERSTEP { - AM_SPI_STEP_INIT = 0, - AM_SPI_STEP_START1, - AM_SPI_STEP_START2, - AM_SPI_STEP_CMD, - AM_SPI_STEP_DATA, - AM_SPI_STEP_ADDR1, - AM_SPI_STEP_ADDR2, - AM_SPI_STEP_END1, - AM_SPI_STEP_END2 -}; -extern int dirspi_xfer(struct spi_device *spi, u8 *tx_buf, u8 *rx_buf, - int len); -extern int dirspi_write(struct spi_device *spi, u8 *buf, int len); -extern int dirspi_read(struct spi_device *spi, u8 *buf, int len); -extern void dirspi_start(struct spi_device *spi); -extern void dirspi_stop(struct spi_device *spi); -extern void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot); -extern int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev); -extern int aml_spi_exit(struct aml_ci *ci_dev); - -#endif /* __AML_SPI_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c deleted file mode 100644 index 9346b8dd46c5..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c +++ /dev/null @@ -1,279 +0,0 @@ - -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include "../aml_ci.h" -#include "aml_cimax.h" -#include "aml_cimax_spi.h" -#include "aml_cimax_usb.h" - -#define MODUDLE_NAME "aml_cimax" - -MODULE_PARM_DESC(cimax_debug, "enable verbose debug messages"); -static int aml_cimax_debug = 1; -module_param_named(cimax_debug, aml_cimax_debug, int, 0644); - -//static struct switch_dev slot_state = { -// .name = "ci_slot", -//}; - -#define pr_dbg(fmt...)\ - do {\ - if (aml_cimax_debug)\ - pr_info("AML_CIMAX: " fmt);\ - } while (0) -#define pr_error(fmt...) pr_err("AML_CIMAX: " fmt) - -static int aml_cimax_slot_reset(struct aml_ci *ci, int slot) -{ - int ret = 0; - struct aml_cimax *cimax = ci->data; - pr_dbg("cimax: slot(%d) reset\n", slot); - if (cimax->ops.slot_reset) - ret = cimax->ops.slot_reset(cimax, slot); - return ret; -} - -static int aml_cimax_slot_shutdown(struct aml_ci *ci, int slot) -{ - pr_dbg("slot(%d) shutdown\n", slot); - return 0; -} - -static int aml_cimax_slot_ts_enable(struct aml_ci *ci, int slot) -{ - pr_dbg("slot(%d) ts control\n", slot); - return 0; -} - -static int aml_cimax_slot_status(struct aml_ci *ci, int slot, int open) -{ - int ret = 0; - struct aml_cimax *cimax = ci->data; - - /*pr_dbg("cimax: slot(%d) poll\n", slot);*/ - if (cimax->ops.slot_status) - ret = cimax->ops.slot_status(cimax, slot); - return ret; -} - -#define DEF_FUNC_WRAPPER3(_pre, _fn, _S, _P1, _P2, _P3) \ -static int _pre##_fn(_S s, _P1 p1, _P2 p2, _P3 p3)\ -{\ - struct aml_cimax *cimax = s->data;\ - /*pr_dbg("%s\n", #_fn);*/\ - if (cimax->ops._fn)\ - return cimax->ops._fn(cimax, p1, p2, p3);\ - return 0;\ -} - -/*DEF_FUNC_WRAPPER3(aml_cimax_, read_reg, struct aml_ci*, int, u8*, int)*/ -/*DEF_FUNC_WRAPPER3(aml_cimax_, write_reg, struct aml_ci*, int, u8*, int)*/ -DEF_FUNC_WRAPPER3(aml_cimax_, read_cis, struct aml_ci*, int, u8*, int) -DEF_FUNC_WRAPPER3(aml_cimax_, read_lpdu, struct aml_ci*, int, u8*, int) -DEF_FUNC_WRAPPER3(aml_cimax_, write_lpdu, struct aml_ci*, int, u8*, int) - -static int aml_cimax_write_cor(struct aml_ci *ci, int slot, int addr, u8 *buf) -{ - struct aml_cimax *cimax = ci->data; - pr_dbg("write_cor\n"); - if (cimax->ops.write_cor) - return cimax->ops.write_cor(cimax, slot, addr, buf); - return 0; -} - -static int aml_cimax_negotiate(struct aml_ci *ci, int slot, int size) -{ - struct aml_cimax *cimax = ci->data; - pr_dbg("negotiate\n"); - if (cimax->ops.negotiate) - return cimax->ops.negotiate(cimax, slot, size); - return 0; -} - -static int aml_cimax_read_cam_status(struct aml_ci *ci, int slot) -{ - struct aml_cimax *cimax = ci->data; - if (cimax->ops.read_cam_status) - return cimax->ops.read_cam_status(cimax, slot); - return 0; -} - -static int aml_cimax_cam_reset(struct aml_ci *ci, int slot) -{ - struct aml_cimax *cimax = ci->data; - if (cimax->ops.cam_reset) - return cimax->ops.cam_reset(cimax, slot); - return 0; -} - -static int aml_cimax_get_capbility(struct aml_ci *ci, int slot) -{ - return 0; -} - -int aml_cimax_camchanged(struct aml_cimax *cimax, int slot, int plugin) -{ - struct aml_ci *ci = cimax->ci; - if (plugin) { - dvb_ca_en50221_cimax_camchange_irq(&ci->en50221_cimax, - slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); - } else { - dvb_ca_en50221_cimax_camchange_irq(&ci->en50221_cimax, - slot, DVB_CA_EN50221_CAMCHANGE_REMOVED); - } - return 0; -} - -static int aml_cimax_start(struct aml_cimax *cimax) -{ - int ret = 0; - if (cimax->ops.start) - ret = cimax->ops.start(cimax); - return ret; -} - -static int aml_cimax_stop(struct aml_cimax *cimax) -{ - int ret = 0; - if (cimax->ops.stop) - ret = cimax->ops.stop(cimax); - return ret; -} - -static int aml_cimax_get_config_from_dts(struct aml_cimax *cimax) -{ - struct device_node *child = NULL; - struct platform_device *pdev = cimax->pdev; - struct device_node *np = pdev->dev.of_node; - unsigned int val; - int ret = 0; - pr_dbg("get cimax dts\n"); - - child = of_get_child_by_name(np, "cimax"); - if (child == NULL) { - pr_error("failed to get cimax\n"); - return -1; - } - ret = of_property_read_u32(child, "io_type", &val); - if (ret) - cimax->io_type = IO_TYPE_SPI; - else - cimax->io_type = val; - - return 0; -} - -int aml_cimax_init(struct platform_device *pdev, struct aml_ci *ci) -{ - struct aml_cimax *cimax = NULL; - int ret = 0; - - cimax = kzalloc(sizeof(struct aml_cimax), GFP_KERNEL); - if (!cimax) { - pr_error("Out of memory!, exiting ..\n"); - return -ENOMEM; - } - cimax->pdev = pdev; - cimax->ci = ci; - - aml_cimax_get_config_from_dts(cimax); - - if (cimax->io_type == IO_TYPE_SPI) { - //ret = aml_cimax_spi_init(pdev, cimax); - } - else { - ret = aml_cimax_usb_init(pdev, cimax); - } - - if (ret != 0) { - kfree(cimax); - cimax = NULL; - return -EIO; - } - - ret = aml_cimax_start(cimax); - if (ret != 0) - return ret; - - ci->ci_read_cis = aml_cimax_read_cis; - ci->ci_write_cor = aml_cimax_write_cor; - ci->ci_negotiate = aml_cimax_negotiate; - ci->ci_read_lpdu = aml_cimax_read_lpdu; - ci->ci_write_lpdu = aml_cimax_write_lpdu; - ci->ci_read_cam_status = aml_cimax_read_cam_status; - ci->ci_cam_reset = aml_cimax_cam_reset; - ci->ci_get_capbility = aml_cimax_get_capbility; - ci->ci_slot_reset = aml_cimax_slot_reset; - ci->ci_slot_shutdown = aml_cimax_slot_shutdown; - ci->ci_slot_ts_enable = aml_cimax_slot_ts_enable; - ci->ci_poll_slot_status = aml_cimax_slot_status; - - ci->data = cimax; - return 0; -} -EXPORT_SYMBOL(aml_cimax_init); - -int aml_cimax_exit(struct aml_ci *ci) -{ - struct aml_cimax *cimax = ci->data; - - aml_cimax_stop(cimax); - - if (cimax->io_type == IO_TYPE_SPI) { - //aml_cimax_spi_exit(cimax); - } - else { - aml_cimax_usb_exit(cimax); - } - kfree(cimax); - ci->data = NULL; - - return 0; -} -EXPORT_SYMBOL(aml_cimax_exit); - -int aml_cimax_slot_state_changed(struct aml_cimax *cimax, int slot, int state) -{ - //if (slot == 0) - // switch_set_state(&slot_state, state); - return 0; -} -EXPORT_SYMBOL(aml_cimax_slot_state_changed); -#if 0 -static int __init aml_cimax_mod_init(void) -{ - pr_dbg("Amlogic DVB CIMAX Init\n"); - //switch_dev_register(&slot_state); - //switch_set_state(&slot_state, 0); - return 0; -} - -static void __exit aml_cimax_mod_exit(void) -{ - pr_dbg("Amlogic DVB CIMAX Exit\n"); - //switch_dev_unregister(&slot_state); -} - -module_init(aml_cimax_mod_init); -module_exit(aml_cimax_mod_exit); - -MODULE_LICENSE("GPL"); -#endif - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h deleted file mode 100644 index 17c62fad7625..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#ifndef __AML_CIMAX_H_ -#define __AML_CIMAX_H_ - -#include "../aml_ci.h" -#include "dvb_ca_en50221_cimax.h" - -struct aml_cimax; - -struct aml_cimax_ops { - int (*read_cis)(struct aml_cimax *cimax, int slot, u8 *buf, int size); - int (*write_cor)(struct aml_cimax *cimax, - int slot, int address, u8 *buf); - int (*negotiate)(struct aml_cimax *cimax, int slot, int size); - int (*read_lpdu)(struct aml_cimax *cimax, int slot, u8 *buf, int size); - int (*write_lpdu)(struct aml_cimax *cimax, int slot, u8 *buf, int size); - int (*read_cam_status)(struct aml_cimax *cimax, int slot); - int (*cam_reset)(struct aml_cimax *cimax, int slot); - int (*get_capblility)(struct aml_cimax *cimax, int slot); - - int (*slot_reset)(struct aml_cimax *cimax, int slot); - int (*slot_shutdown)(struct aml_cimax *cimax, int slot); - int (*slot_ts_enable)(struct aml_cimax *cimax, int slot); - int (*slot_status)(struct aml_cimax *cimax, int slot); - - /*load fw etc.*/ - int (*start)(struct aml_cimax *cimax); - int (*stop)(struct aml_cimax *cimax); - - /*cimax reg*/ - int (*read_reg)(struct aml_cimax *cimax, int addr, u8 *buf, int size); - int (*write_reg)(struct aml_cimax *cimax, int addr, u8 *buf, int size); -}; - -struct aml_cimax { - struct platform_device *pdev; - struct device *dev; - struct aml_ci *ci; - - int io_type; -#define IO_TYPE_SPI 0 -#define IO_TYPE_USB 1 - struct aml_cimax_ops ops; - void *priv; -}; - -int aml_cimax_init(struct platform_device *pdev, struct aml_ci *ci_dev); -int aml_cimax_exit(struct aml_ci *ci_dev); - -int aml_cimax_camchanged(struct aml_cimax *cimax, int slot, int plugin); -int aml_cimax_slot_state_changed(struct aml_cimax *cimax, int slot, int state); -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c deleted file mode 100644 index a4aaddae0260..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c +++ /dev/null @@ -1,2139 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "aml_cimax.h" - -#define MOD_NAME "aml_cimax_spi" - -#define pr_dbg(fmt...)\ - do {\ - if (cimax_spi_debug)\ - pr_info("cimax_spi: "fmt);\ - } while (0) -#define pr_error(fmt...) pr_err("AML_CIMAX_SPI: " fmt) - -#define BUFFIN_CFG 0x0000 -#define BUFFIN_ADDR_LSB 0x0001 -#define BUFFIN_ADDR_MSB 0x0002 -#define BUFFIN_DATA 0x0003 -#define BUFFOUT_CFG 0x0004 -#define BUFFOUT_ADDR_LSB 0x0005 -#define BUFFOUT_ADDR_MSB 0x0006 -#define BUFFOUT_DATA 0x0007 -#define BOOT_Key 0x0008 -#define BOOT_Status 0x0009 -#define BOOT_Test 0x000A -#define usb2_0_irq_mask 0x0010 -#define usb2_0_status 0x0011 -#define usb2_0_rx 0x0012 -#define usb2_0_tx 0x0013 -#define SPI_Slave_Ctrl 0x0018 -#define SPI_Slave_Status 0x0019 -#define SPI_Slave_Rx 0x001A -#define SPI_Slave_Tx 0x001B -#define SPI_Slave_Mask 0x001C -#define UCSG_Ctrl 0x0020 -#define UCSG_Status 0x0021 -#define UCSG_RxData 0x0022 -#define UCSG_TxData 0x0023 -#define PCtrl_Ctrl 0x0028 -#define PCtrl_Status 0x0029 -#define PCtrl_NbByte_LSB 0x002A -#define PCtrl_NbByte_MSB 0x002B -#define SPI_Master_Ctl 0x0030 -#define SPI_Master_NCS 0x0031 -#define SPI_Master_Status 0x0032 -#define SPI_Master_TxBuf 0x0033 -#define SPI_Master_RxBuf 0x0034 -#define BISTRAM_Ctl 0x0038 -#define BISTRAM_Bank 0x0039 -#define BISTRAM_Pat 0x003A -#define BISTRAM_SM 0x003B -#define BISTRAM_AddrLSB 0x003C -#define BISTROM_Config 0x0040 -#define BISTROM_SignatureLSB 0x0041 -#define BISTROM_SignatureMSB 0x0042 -#define BISTROM_StartAddrLSB 0x0043 -#define BISTROM_StartAddrMSB 0x0043 -#define BISTROM_StopAddrLSB 0x0043 -#define BISTROM_StopAddrMSB 0x0043 -#define CkMan_Config 0x0048 -#define CkMan_Select 0x0049 -#define CkMan_Test 0x004A -#define Revision_Number 0x004B -#define ResMan_Config 0x0050 -#define ResMan_Status 0x0051 -#define ResMan_WD 0x0052 -#define ResMan_WD_MSB 0x0053 -#define CPU_Test 0x0060 -#define IrqMan_Config0 0x0068 -#define IrqMan_Config1 0x0069 -#define IrqMan_Irq0 0x006A -#define IrqMan_NMI 0x006B -#define IrqMan_SleepKey 0x006C -#define Tim_Config 0x0070 -#define Tim_Value_LSB 0x0071 -#define Tim_Value_MSB 0x0072 -#define Tim_Comp_LSB 0x0073 -#define Tim_Comp_MSB 0x0074 -#define TI_Config 0x0076 -#define TI_Data 0x0077 -#define TI_Reg0 0x0078 -#define TI_Reg1 0x0079 -#define TI_Reg2 0x007A -#define TI_Reg3 0x007B -#define TI_Reg4 0x007C -#define TI_ROM1 0x007D -#define TI_ROM2 0x007E -#define TI_ROM3 0x007F -#define DVBCI_START_ADDR 0x0100 -#define DVBCI_END_ADDR 0x017F -#define DATA 0x0180 -/*#define CTRL 0x0181*/ -#define QB_HOST 0x0182 -#define LEN_HOST_LSB 0x0183 -#define LEN_HOST_MSB 0x0184 -#define FIFO_TX_TH_LSB 0x0185 -#define FIFO_TX_TH_MSB 0x0186 -#define FIFO_TX_D_NB_LSB 0x0187 -#define FIFO_TX_D_NB_MSB 0x0188 -#define QB_MOD_CURR 0x0189 -#define LEN_MOD_CURR_LSB 0x018A -#define LEN_MOD_CURR_MSB 0x018B -#define QB_MOD 0x018C -#define LEN_MOD_LSB 0x018D -#define LEN_MOD_MSB 0x018E -#define FIFO_RX_TH_LSB 0x018F -#define FIFO_RX_TH_MSB 0x0190 -#define FIFO_RX_D_NB_LSB 0x0191 -#define FIFO_RX_D_NB_MSB 0x0192 -#define IT_STATUS_0 0x0193 -#define IT_STATUS_1 0x0194 -#define IT_MASK_0 0x0195 -#define IT_MASK_1 0x0196 -#define IT_HOST_PIN_CFG 0x0200 -#define CFG_0 0x0201 -#define CFG_1 0x0202 -#define CFG_2 0x0203 -#define IT_HOST 0x0204 -#define MOD_IT_STATUS 0x0205 -#define MOD_IT_MASK 0x0206 -#define MOD_CTRL_A 0x0207 -#define MOD_CTRL_B 0x0208 -#define DEST_SEL 0x0209 -#define CAM_MSB_ADD 0x020A -#define GPIO0_DIR 0x020B -#define GPIO0_DATA_IN 0x020C -#define GPIO0_DATA_OUT 0x020D -#define GPIO0_STATUS 0x020E -#define GPIO0_IT_MASK 0x020F -#define GPIO0_DFT 0x0210 -#define GPIO0_MASK_DATA 0x0211 -#define GPIO1_DIR 0x0212 -#define GPIO1_DATA_IN 0x0213 -#define GPIO1_DATA_OUT 0x0214 -#define GPIO1_STATUS 0x0215 -#define GPIO1_IT_MASK 0x0216 -#define MEM_ACC_TIME_A 0x0217 -#define MEM_ACC_TIME_B 0x0218 -#define IO_ACC_TIME_A 0x0219 -#define IO_ACC_TIME_B 0x021A -#define EXT_CH_ACC_TIME_A 0x021B -#define EXT_CH_ACC_TIME_B 0x021C -#define PAR_IF_0 0x021D -#define PAR_IF_1 0x021E -#define PAR_IF_CTRL 0x021F -#define PCK_LENGTH 0x0220 -#define USB2TS_CTRL 0x0221 -#define USB2TS0_RDL 0x0222 -#define USB2TS1_RDL 0x0223 -#define TS2USB_CTRL 0x0224 -#define TSOUT_PAR_CTRL 0x0225 -#define TSOUT_PAR_CLK_SEL 0x0226 -#define S2P_CH0_CTRL 0x0227 -#define S2P_CH1_CTRL 0x0228 -#define P2S_CH0_CTRL 0x0229 -#define P2S_CH1_CTRL 0x022A -#define TS_IT_STATUS 0x022B -#define TS_IT_MASK 0x022C -#define IN_SEL 0x022D -#define OUT_SEL 0x022E -#define ROUTER_CAM_CH 0x022F -#define ROUTER_CAM_MOD 0x0230 -#define FIFO_CTRL 0x0231 -#define FIFO1_2_STATUS 0x0232 -#define FIFO3_4_STATUS 0x0233 -#define GAP_REMOVER_CH0_CTRL 0x0234 -#define GAP_REMOVER_CH1_CTRL 0x0235 -#define SYNC_RTV_CTRL 0x0236 -#define SYNC_RTV_CH0_SYNC_NB 0x0237 -#define SYNC_RTV_CH0_PATTERN 0x0238 -#define SYNC_RTV_CH1_SYNC_NB 0x0239 -#define SYNC_RTV_CH1_PATTERN 0x023A -#define SYNC_RTV_OFFSET_PATT 0x023B -#define CTRL_FILTER 0x023D -#define PID_EN_FILTER_CH0 0x023E -#define PID_EN_FILTER_CH1 0x023F -#define PID_LSB_FILTER_CH0_0 0x0240 -#define PID_MSB_FILTER_CH0_0 0x0241 -#define PID_LSB_FILTER_CH0_1 0x0242 -#define PID_MSB_FILTER_CH0_1 0x0243 -#define PID_LSB_FILTER_CH0_2 0x0244 -#define PID_MSB_FILTER_CH0_2 0x0245 -#define PID_LSB_FILTER_CH0_3 0x0246 -#define PID_MSB_FILTER_CH0_3 0x0247 -#define PID_LSB_FILTER_CH0_4 0x0248 -#define PID_MSB_FILTER_CH0_4 0x0249 -#define PID_LSB_FILTER_CH0_5 0x024A -#define PID_MSB_FILTER_CH0_5 0x024B -#define PID_LSB_FILTER_CH0_6 0x024C -#define PID_MSB_FILTER_CH0_6 0x024D -#define PID_LSB_FILTER_CH0_7 0x024E -#define PID_MSB_FILTER_CH0_7 0x024F -#define PID_LSB_FILTER_CH1_0 0x0260 -#define PID_MSB_FILTER_CH1_0 0x0261 -#define PID_LSB_FILTER_CH1_1 0x0262 -#define PID_MSB_FILTER_CH1_1 0x0263 -#define PID_LSB_FILTER_CH1_2 0x0264 -#define PID_MSB_FILTER_CH1_2 0x0265 -#define PID_LSB_FILTER_CH1_3 0x0266 -#define PID_MSB_FILTER_CH1_3 0x0267 -#define PID_LSB_FILTER_CH1_4 0x0268 -#define PID_MSB_FILTER_CH1_4 0x0269 -#define PID_LSB_FILTER_CH1_5 0x026A -#define PID_MSB_FILTER_CH1_5 0x026B -#define PID_LSB_FILTER_CH1_6 0x026C -#define PID_MSB_FILTER_CH1_6 0x026D -#define PID_LSB_FILTER_CH1_7 0x026E -#define PID_MSB_FILTER_CH1_7 0x026F -#define PID_OLD_LSB_REMAPPER_0 0x0280 -#define PID_OLD_MSB_REMAPPER_0 0x0281 -#define PID_OLD_LSB_REMAPPER_1 0x0282 -#define PID_OLD_MSB_REMAPPER_1 0x0283 -#define PID_OLD_LSB_REMAPPER_2 0x0284 -#define PID_OLD_MSB_REMAPPER_2 0x0285 -#define PID_OLD_LSB_REMAPPER_3 0x0286 -#define PID_OLD_MSB_REMAPPER_3 0x0287 -#define PID_OLD_LSB_REMAPPER_4 0x0288 -#define PID_OLD_MSB_REMAPPER_4 0x0289 -#define PID_OLD_LSB_REMAPPER_5 0x028A -#define PID_OLD_MSB_REMAPPER_5 0x028B -#define PID_OLD_LSB_REMAPPER_6 0x028C -#define PID_OLD_MSB_REMAPPER_6 0x028D -#define PID_OLD_LSB_REMAPPER_7 0x028E -#define PID_OLD_MSB_REMAPPER_7 0x028F -#define PID_NEW_LSB_REMAPPER_0 0x02A0 -#define PID_NEW_MSB_REMAPPER_0 0x02A1 -#define PID_NEW_LSB_REMAPPER_1 0x02A2 -#define PID_NEW_MSB_REMAPPER_1 0x02A3 -#define PID_NEW_LSB_REMAPPER_2 0x02A4 -#define PID_NEW_MSB_REMAPPER_2 0x02A5 -#define PID_NEW_LSB_REMAPPER_3 0x02A6 -#define PID_NEW_MSB_REMAPPER_3 0x02A7 -#define PID_NEW_LSB_REMAPPER_4 0x02A8 -#define PID_NEW_MSB_REMAPPER_4 0x02A9 -#define PID_NEW_LSB_REMAPPER_5 0x02AA -#define PID_NEW_MSB_REMAPPER_5 0x02AB -#define PID_NEW_LSB_REMAPPER_6 0x02AC -#define PID_NEW_MSB_REMAPPER_6 0x02AD -#define PID_NEW_LSB_REMAPPER_7 0x02AE -#define PID_NEW_MSB_REMAPPER_7 0x02AF -#define MERGER_DIV_MICLK 0x02C0 -#define PID_AND_SYNC_REMAPPER_CTRL 0x02C1 -#define PID_EN_REMAPPER 0x02C2 -#define SYNC_SYMBOL 0x02C3 -#define PID_AND_SYNC_REMAPPER_INV_CTRL 0x02C4 -#define BITRATE_CH0_LSB 0x02C5 -#define BITRATE_CH0_MSB 0x02C6 -#define BITRATE_CH1_LSB 0x02C7 -#define BITRATE_CH1_MSB 0x02C8 -#define STATUS_CLK_SWITCH_0 0x02C9 -#define STATUS_CLK_SWITCH_1 0x02CA -#define RESET_CLK_SWITCH_0 0x02CB -#define RESET_CLK_SWITCH_1 0x02CC -#define PAD_DRVSTR_CTRL 0x02CD -#define PAD_PUPD_CTRL 0x02CE -#define PRE_HEADER_ADDER_CH0_0 0x02D0 -#define PRE_HEADER_ADDER_CH0_1 0x02D1 -#define PRE_HEADER_ADDER_CH0_2 0x02D2 -#define PRE_HEADER_ADDER_CH0_3 0x02D3 -#define PRE_HEADER_ADDER_CH0_4 0x02D4 -#define PRE_HEADER_ADDER_CH0_5 0x02D5 -#define PRE_HEADER_ADDER_CH0_6 0x02D6 -#define PRE_HEADER_ADDER_CH0_7 0x02D7 -#define PRE_HEADER_ADDER_CH0_8 0x02D8 -#define PRE_HEADER_ADDER_CH0_9 0x02D9 -#define PRE_HEADER_ADDER_CH0_10 0x02DA -#define PRE_HEADER_ADDER_CH0_11 0x02DB -#define PRE_HEADER_ADDER_CH1_0 0x02E0 -#define PRE_HEADER_ADDER_CH1_1 0x02E1 -#define PRE_HEADER_ADDER_CH1_2 0x02E2 -#define PRE_HEADER_ADDER_CH1_3 0x02E3 -#define PRE_HEADER_ADDER_CH1_4 0x02E4 -#define PRE_HEADER_ADDER_CH1_5 0x02E5 -#define PRE_HEADER_ADDER_CH1_6 0x02E6 -#define PRE_HEADER_ADDER_CH1_7 0x02E7 -#define PRE_HEADER_ADDER_CH1_8 0x02E8 -#define PRE_HEADER_ADDER_CH1_9 0x02E9 -#define PRE_HEADER_ADDER_CH1_10 0x02EA -#define PRE_HEADER_ADDER_CH1_11 0x02EB -#define PRE_HEADER_ADDER_CTRL 0x02EC -#define PRE_HEADER_ADDER_LEN 0x02ED -#define PRE_HEADER_REMOVER_CTRL 0x02EE -#define FSM_DVB 0x02F0 -#define TS2USB_FSM_DEBUG 0x02F2 -#define TSOUT_PAR_FSM_DEBUG 0x02F3 -#define GAP_REMOVER_FSM_DEBUG 0x02F4 -#define PID_AND_SYNC_REMAPPER_FSM_DEBUG 0x02F5 -#define PRE_HEADER_ADDER_FSM_DEBUG 0x02F6 -#define SYNC_RTV_FSM_DEBUG 0x02F7 -#define CHECK_PHY_CLK 0x0E00 -#define USB_CTRL1 0x0E01 -#define USB_ISO2_out 0x0800 -#define USB_ISO1_out 0x1000 -#define USB_Interrupt_out 0x1E00 -#define USB_Bulk_in 0x1F00 -#define CC2_Buffer_out 0x2000 -#define USB_EP0 0x30C0 -#define CC2_Buffer_in 0x4000 -#define USB_ISO2_in 0x5800 -#define USB_ISO1_in 0x6000 -#define nmb_vector_address_lsb 0xFFFA -#define nmb_vector_address_msb 0xFFFB -#define reset_vector_address_lsb 0xFFFC -#define reset_vector_address_msb 0xFFFD -#define irb_vector_address_lsb 0xFFFE -#define irb_vector_address_msb 0xFFFF - - -#define CIMAX_REG_HDR_SIZE 4 -#define CIMAX_REG_PLD_SIZE 255 -#define CIMAX_CAM_HDR_SIZE 4 -#define CIMAX_CAM_PLD_SIZE 65535 - -#define DEF_LOCK(_l_) struct mutex _l_ - -struct cimax_spi { - struct platform_device *pdev; - struct spi_device *dev; - - struct aml_cimax *cimax; - - u8 buf[CIMAX_REG_HDR_SIZE + CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE]; - - int cam_inserted[2]; - int cam_data_ready[2]; - - int poll_mode; -#define STOP_MODE 0 -#define POLL_MODE 1 -#define INT_MODE 2 - - int irq; - int irq_io; - int rst_io; - - struct workqueue_struct *workq; - struct delayed_work work; - int work_cnt; - - DEF_LOCK(lock); -#define lock_init(_spi) mutex_init(&(_spi)->lock) -#define lock_lock(_spi) do {\ - int err = mutex_lock_interruptible(&(_spi)->lock);\ - if (err)\ - return err;\ -} while (0) -#define lock_unlock(_spi) mutex_unlock(&(_spi)->lock) - - u8 *cis; -#define CIS_MAX 512 -}; - -static struct cimax_spi *g_spi; - -MODULE_PARM_DESC(debug, "enable verbose debug messages"); -static int cimax_spi_debug = 1; -module_param_named(debug, cimax_spi_debug, int, 0644); - -MODULE_PARM_DESC(poll_interval, "interval for spi poll"); -static int spi_poll_interval = 100; -module_param_named(poll_interval, spi_poll_interval, int, 0644); - -MODULE_PARM_DESC(poll_mode, "set cimax poll mode, need reset"); -static int cimax_poll_mode = 1; -module_param_named(poll_mode, cimax_poll_mode, int, 0644); - -MODULE_PARM_DESC(cam_irq_mode, "set cam irq mode, need reset"); -static int cam_irq_mode; -module_param_named(cam_irq_mode, cam_irq_mode, int, 0644); - -#define CIMAX_REG_READ 0xff -#define CIMAX_REG_READ_OK 0x4c -#define CIMAX_REG_WRITE 0x7f -#define CIMAX_REG_WRITE_OK 0x4d -#define CIMAX_REG_INIT 0x00 -#define CIMAX_REG_INIT_OK 0x4b -#define CIMAX_REG_CMD_ERROR 0x51 - -#define CIMAX_CAM_RESET 0x01 -#define CIMAX_CAM_RESET_OK 0x40 -#define CIMAX_CAM_CIS 0x02 -#define CIMAX_CAM_CIS_OK 0x41 -#define CIMAX_CAM_COR 0x03 -#define CIMAX_CAM_COR_OK 0x42 -#define CIMAX_CAM_NEG 0x04 -#define CIMAX_CAM_NEG_OK 0x43 -#define CIMAX_CAM_WLPDU 0x05 -#define CIMAX_CAM_WLPDU_OK 0x44 -#define CIMAX_CAM_RLPDU 0x06 -#define CIMAX_CAM_RLPDU_OK 0x46 -#define CIMAX_CAM_EVT 0x0d -#define CIMAX_CAM_DET_OK 0x45 -#define CIMAX_CAM_NOCAM 0x49 -#define CIMAX_CAM_ERROR 0x4a -#define CIMAX_CAM_NOEVT 0x55 -#define CIMAX_CAM_DATA_READY 0x4e -#define CIMAX_CAM_WBUSY 0x54 -#define CIMAX_CAM_PENDING 0x56 -#define CIMAX_CAM_REGSTAT 0x0e -#define CIMAX_CAM_REGSTAT_OK 0x57 - - -#define CIMAX_CAM_PKT_CNT_VAL 1 - -#define CIMAX_SLOT_A 0 -#define CIMAX_SLOT_B 1 - -#define CIMAX_CMD_RESP_MASK 0x7f - -#define cimax_to_spi(_c) ((struct cimax_spi *)((_c)->priv)) -#define dev_to_spi(_d) ((struct cimax_spi *)spi_get_drvdata(_d)) - -#define byte_to_u16(_b1, _b2) (((_b1)<<8) | (_b2)) - -#define hdr_cmd_resp(_s) ((_s)->buf[0] & CIMAX_CMD_RESP_MASK) - -#define reg_hdr(_s) ((_s)->buf) -#define reg_addr(_s) byte_to_u16((_s)->buf[1], (_s)->buf[2]) -#define reg_hdr_dat_size(_s) ((_s)->buf[3]) -#define reg_dat(_s) (&((_s)->buf[CIMAX_REG_HDR_SIZE])) - -#define cam_hdr(_s) ((_s)->buf) -#define cam_hdr_slot(_s) (((_s)->buf[0] & 0x80) ? 1 : 0) -#define cam_hdr_pkt_cnt(_s) ((_s)->buf[1]) -#define cam_hdr_dat_size(_s) byte_to_u16((_s)->buf[2], (_s)->buf[3]) -#define cam_dat(_s) (&((_s)->buf[CIMAX_CAM_HDR_SIZE])) - -#define REG_TIMEOUT 500 -#define CAM_TIMEOUT 5000 - -#define USE_INT_PIO - -static int aml_cimax_spi_mod_init(void); -static void aml_cimax_spi_mod_exit(void); - -static void dump(char *title, u8 *buf, int size) -{ - int i; - pr_info("%s\n", title); - for (i = 0; i < size; i++) { - if (!(i & 0xf)) - pr_info("\n\t"); - pr_info("%02x ", *(buf+i)); - } - pr_info("\n"); -} - -static void perr(char *err, struct cimax_spi *spi) -{ - pr_error("error: %s\n", err); - dump("dump:", spi->buf, 16); -} - -static inline unsigned long get_jiffies(void) -{ - return (unsigned long)(sched_clock()/10000000); -} - -static inline void set_spi_cam_ready(struct cimax_spi *spi, int slot) -{ - if (spi->cam_inserted[slot] == 1) { - spi->cam_inserted[slot] = 2; - aml_cimax_slot_state_changed(spi->cimax, - slot, spi->cam_inserted[slot]); - } -} - - -static int cimax_spi_get_resp(struct cimax_spi *spi, int timeout) -{ - struct spi_device *dev = spi->dev; - int ret = 0; - unsigned long start = get_jiffies(); -#ifndef USE_INT_PIO - u8 t = 0; - - while (!t && jiffies_to_msecs(get_jiffies() - start) < timeout) { - ret = spi_read(dev, &t, 1); - if (ret) - return ret; - usleep_range(1000, 2000); - } - if (!t) { - pr_error("resp timeout: %dms\n", timeout); - return -EIO; - } - cam_hdr(spi)[0] = t; - ret = spi_read(dev, cam_hdr(spi)+1, CIMAX_CAM_HDR_SIZE-1); - if (ret) - return ret; -#else - do { - if (jiffies_to_msecs(get_jiffies() - start) >= timeout) { - pr_error("resp timeout: %dms\n", timeout); - return -EIO; - } - usleep_range(1000, 2000); - } while (gpio_get_value(spi->irq_io)); - - ret = spi_read(dev, cam_hdr(spi), CIMAX_CAM_HDR_SIZE); - if (ret) - return ret; -#endif - /*pr_dbg("rp: %02x:%02x:%02x:%02x\n", - cam_hdr(spi)[0], cam_hdr(spi)[1], - cam_hdr(spi)[2], cam_hdr(spi)[3]);*/ - switch (hdr_cmd_resp(spi)) { - case CIMAX_REG_READ_OK: - case CIMAX_REG_WRITE_OK: - case CIMAX_REG_INIT_OK: - case CIMAX_REG_CMD_ERROR: { - int len = reg_hdr_dat_size(spi); - if (len) { - ret = spi_read(dev, reg_dat(spi), len); - if (ret != 0) - return ret; - } - } break; - case CIMAX_CAM_RESET_OK: - case CIMAX_CAM_CIS_OK: - case CIMAX_CAM_COR_OK: - case CIMAX_CAM_NEG_OK: - case CIMAX_CAM_WLPDU_OK: - case CIMAX_CAM_RLPDU_OK: - case CIMAX_CAM_NOCAM: - case CIMAX_CAM_ERROR: - case CIMAX_CAM_WBUSY: - case CIMAX_CAM_DET_OK: - case CIMAX_CAM_DATA_READY: - case CIMAX_CAM_PENDING: - case CIMAX_CAM_REGSTAT_OK: - case CIMAX_CAM_NOEVT: { - int len = cam_hdr_dat_size(spi); - if (len) { - ret = spi_read(dev, cam_dat(spi), len); - if (ret != 0) - return ret; - /*if (len) - dump("dat:", cam_dat(spi), len);*/ - } - } - break; - default: - pr_error("unknown resp:0x%02x\n", hdr_cmd_resp(spi)); - return -EINVAL; - } - return 0; -} - -static int init_reg_hdr(u8 *hdr, u8 tag, int addr, int size) -{ - hdr[0] = tag; - hdr[1] = (addr>>8) & 0xff; - hdr[2] = addr & 0xff; - hdr[3] = size; - return 0; -} - -static int check_reg_hdr(u8 *hdr, u8 tag, int addr, int size) -{ - return hdr[0] != tag - || hdr[1] != ((addr>>8) & 0xff) - || hdr[2] != (addr & 0xff) - || hdr[3] != size; -} - -static int aml_cimax_spi_read_reg(struct aml_cimax *cimax, int addr, - u8 *buf, int size) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - struct spi_device *dev = spi->dev; - int err = 0; - - init_reg_hdr(spi->buf, CIMAX_REG_READ, addr, size); - - lock_lock(spi); - - pr_dbg("rd %02x:%02x:%02x:%02x\n", - reg_hdr(spi)[0], reg_hdr(spi)[1], - reg_hdr(spi)[2], reg_hdr(spi)[3]); - err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); - if (err) - goto end; - err = cimax_spi_get_resp(spi, REG_TIMEOUT); - if (err) - goto end; - if (check_reg_hdr(reg_hdr(spi), CIMAX_REG_READ_OK, addr, size) != 0) { - perr("read reg fail.", spi); - err = -EINVAL; - goto end; - } - memcpy(buf, reg_dat(spi), size); -end: - lock_unlock(spi); - return err; -} - -static int aml_cimax_spi_write_reg(struct aml_cimax *cimax, int addr, - u8 *buf, int size) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - struct spi_device *dev = spi->dev; - int err = 0; - - init_reg_hdr(spi->buf, CIMAX_REG_WRITE, addr, size); - memcpy(&spi->buf[CIMAX_REG_HDR_SIZE], buf, size); - - lock_lock(spi); - - pr_dbg("wr %02x:%02x:%02x:%02x\n", - reg_hdr(spi)[0], reg_hdr(spi)[1], - reg_hdr(spi)[2], reg_hdr(spi)[3]); - err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE + size); - if (err) - goto end; - err = cimax_spi_get_resp(spi, REG_TIMEOUT); - if (err) - goto end; - if (check_reg_hdr(reg_hdr(spi), CIMAX_REG_WRITE_OK, addr, 0) != 0) { - perr("write reg fail.", spi); - err = -EINVAL; - goto end; - } -end: - lock_unlock(spi); - return err; -} - -static inline int init_cam_hdr(u8 *hdr, int cmd, int size) -{ - hdr[0] = cmd; - hdr[1] = CIMAX_CAM_PKT_CNT_VAL; - hdr[2] = (size>>8) & 0xff; - hdr[3] = size & 0xff; - return 0; -} - -static inline int cam_err(struct cimax_spi *spi) -{ - if (hdr_cmd_resp(spi) != CIMAX_CAM_ERROR - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(spi) != 2) - return 0; - return byte_to_u16(cam_dat(spi)[0], cam_dat(spi)[1]); -} - -static inline char *cam_err_str(int err) -{ -#define CAMERROR_RESET 0x0101 -#define CAMERROR_CIS_BUF 0x0201 -#define CAMERROR_CIS_SIZE 0x0202 -#define CAMERROR_CAM_NOT_ACT 0x0203 -#define CAMERROR_COR_NOT_READY 0x0301 -#define CAMERROR_COR_VAL_CHK 0x0302 -#define CAMERROR_NEG_NO_RESP 0x0401 -#define CAMERROR_NEG_BAD_SIZE 0x0402 -#define CAMERROR_NEG_NOT_READY 0x0403 -#define CAMERROR_LPDU_NOT_AVAIL 0x0601 - struct { int err; char *str; } cam_err_strings[] = { - {CAMERROR_RESET, "reset error, not ready."}, - {CAMERROR_CIS_BUF, "cis error, buffer not allocated."}, - {CAMERROR_CIS_SIZE, "cis error, bad cis size."}, - {CAMERROR_CAM_NOT_ACT, "cam not activated."}, - {CAMERROR_COR_NOT_READY, "cam not ready during write COR."}, - {CAMERROR_COR_VAL_CHK, "COR value check failed."}, - {CAMERROR_NEG_NO_RESP, "cam not responding when negotiation."}, - {CAMERROR_NEG_BAD_SIZE, "cam buf size length != 2."}, - {CAMERROR_NEG_NOT_READY, "cam not ready during negotiation."}, - {CAMERROR_LPDU_NOT_AVAIL, "lpdu not available."} - }; - int i; - for (i = 0; - i < sizeof(cam_err_strings)/sizeof(cam_err_strings[0]); i++) { - if (cam_err_strings[i].err == err) - return cam_err_strings[i].str; - } - return "err unknown."; -} - -static int cimax_spi_access_cam(struct cimax_spi *spi, int slot, - int cmd, u8 *buf, int size) -{ - struct spi_device *dev = spi->dev; - int err = 0; - - cmd |= slot ? 0x80 : 0; - init_cam_hdr(cam_hdr(spi), cmd, size); - memcpy(cam_dat(spi), buf, size); - /*dump("access cam:", cam_hdr(spi), CIMAX_CAM_HDR_SIZE+size);*/ - err = spi_write(dev, cam_hdr(spi), CIMAX_CAM_HDR_SIZE + size); - if (err) - return err; - err = cimax_spi_get_resp(spi, CAM_TIMEOUT); - if (err) - return err; - if (cam_hdr_slot(spi) != slot) { - pr_error("expect slot(%d), but slot(%d)\n", - slot, cam_hdr_slot(spi)); - return -EINVAL; - } - switch (hdr_cmd_resp(spi)) { - case CIMAX_CAM_NOCAM: - pr_dbg("no cam\n"); - err = -ENODEV; - break; - case CIMAX_CAM_ERROR: - pr_error("cam error\n"); - pr_error("err code: 0x%04x(%s)\n", cam_err(spi), - cam_err_str(cam_err(spi))); - err = -ENODEV; - break; - case CIMAX_CAM_WBUSY: - pr_dbg("cam busy\n"); - err = -EBUSY; - break; - case CIMAX_CAM_PENDING: - pr_dbg("cam pending\n"); - err = -EAGAIN; - break; - } - return err; -} - -static int aml_cimax_spi_read_cis(struct aml_cimax *cimax, int slot, - u8 *buf, int size) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int err = 0; - int len; - - lock_lock(spi); - - err = cimax_spi_access_cam(spi, slot, CIMAX_CAM_CIS, NULL, 0); - if (err) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_CIS_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL) { - perr("read cis fail.", spi); - err = -EINVAL; - goto end; - } - len = cam_hdr_dat_size(spi); - if (size < len) { - pr_error("cis size too large, expect<%d, but:%d\n", size, len); - perr("cis fail.", spi); - err = -EINVAL; - goto end; - } - memcpy(buf, cam_dat(spi), len); - - if (!spi->cis) - spi->cis = kzalloc((len < 512) ? 512 : len, GFP_KERNEL); - if (spi->cis) - memcpy(spi->cis, cam_dat(spi), len); - -end: - lock_unlock(spi); - return err; -} -#define CIMAX_CAM_COR_PLD_SIZE 5 -static int aml_cimax_spi_write_cor(struct aml_cimax *cimax, int slot, - int addr, u8 *buf) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int err = 0; - u8 out[CIMAX_CAM_COR_PLD_SIZE + 8]; - int sz = CIMAX_CAM_COR_PLD_SIZE; - - out[0] = addr>>8 & 0xff; - out[1] = addr & 0xff; - out[2] = buf[0]; - out[3] = 0; - out[4] = 0; - - if (!cam_irq_mode) { - out[5] = 0x40;/*cam poll mode*/ - sz++; - } - - lock_lock(spi); - - err = cimax_spi_access_cam(spi, slot, CIMAX_CAM_COR, out, sz); - if (err) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_COR_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(spi) != 0) { - perr("write cor fail.", spi); - err = -EINVAL; - goto end; - } -end: - lock_unlock(spi); - return err; -} -#define CIMAX_CAM_NEG_PLD_SIZE 2 -static int aml_cimax_spi_negotiate(struct aml_cimax *cimax, int slot, int size) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int ret = 0; - u8 out[CIMAX_CAM_NEG_PLD_SIZE]; - - out[0] = (size>>8) & 0xff; - out[1] = size & 0xff; - - lock_lock(spi); - - ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_NEG, - out, CIMAX_CAM_NEG_PLD_SIZE); - if (ret) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_NEG_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(spi) != 2) { - perr("negotiate fail.", spi); - ret = -EINVAL; - goto end; - } - ret = byte_to_u16(cam_dat(spi)[0], cam_dat(spi)[1]); - - set_spi_cam_ready(spi, slot); -end: - lock_unlock(spi); - return ret; -} - -static int aml_cimax_spi_write_lpdu(struct aml_cimax *cimax, int slot, - u8 *buf, int size) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int ret = 0; - - lock_lock(spi); - - /*dump("lpdu ->", buf, size);*/ - ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_WLPDU, buf, size); - if (ret) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_WLPDU_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(spi) != 0) { - perr("write lpdu fail.", spi); - ret = -EINVAL; - goto end; - } - ret = size; -end: - lock_unlock(spi); - return ret; -} - -static int aml_cimax_spi_read_lpdu(struct aml_cimax *cimax, int slot, - u8 *buf, int size) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int ret = 0; - - lock_lock(spi); - - ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_RLPDU, NULL, 0); - if (ret) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_RLPDU_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL) { - perr("read lpdu fail.", spi); - ret = -EINVAL; - goto end; - } - ret = cam_hdr_dat_size(spi); - memcpy(buf, cam_dat(spi), ret); - - /*dump("lpdu <-", buf, ret);*/ - - spi->cam_data_ready[slot] = 0; -end: - lock_unlock(spi); - return ret; -} - -static int aml_cimax_spi_read_cam_status(struct aml_cimax *cimax, int slot) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int ret = 0; - - if (cam_irq_mode && spi->cam_data_ready[slot]) - return 0x80; - - lock_lock(spi); - - ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_REGSTAT, NULL, 0); - if (ret) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_REGSTAT_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(spi) != 1) { - perr("read cam status fail.", spi); - ret = -EINVAL; - goto end; - } - - ret = cam_dat(spi)[0]; -end: - lock_unlock(spi); - return ret; -} - -static int aml_cimax_spi_slot_reset(struct aml_cimax *cimax, int slot) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - int ret = 0; - - spi->cam_data_ready[slot] = 0; - - lock_lock(spi); - - ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_RESET, NULL, 0); - if (ret) - goto end; - if (hdr_cmd_resp(spi) != CIMAX_CAM_RESET_OK - || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(spi) != 0) { - perr("slot reset fail.", spi); - ret = -EINVAL; - goto end; - } -end: - lock_unlock(spi); - return ret; -} - -static int aml_cimax_spi_cam_reset(struct aml_cimax *cimax, int slot) -{ - pr_dbg("Slot(%d): camreset\n", slot); - return 0; -} - -static int aml_cimax_spi_slot_shutdown(struct aml_cimax *cimax, int slot) -{ - pr_dbg("Slot(%d): shutdown\n", slot); - return 0; -} -static int aml_cimax_spi_slot_ts_enable(struct aml_cimax *cimax, int slot) -{ - pr_dbg("Slot(%d): ts control\n", slot); - return 0; -} -static int aml_cimax_spi_slot_status(struct aml_cimax *cimax, int slot) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - if (spi->cam_inserted[slot]) { - /*pr_dbg("CA Module present and ready\n");*/ - return DVB_CA_EN50221_POLL_CAM_PRESENT | - DVB_CA_EN50221_POLL_CAM_READY; - } else { - /*pr_error("CA Module not present or not ready\n");*/ - } - return 0; -} - -static int cimax_spi_cam_plugin(struct cimax_spi *spi, int slot, int plugin) -{ - pr_dbg("cam plug: slot(%d) %s\n", - slot, plugin ? "plugged" : "unplugged"); - return aml_cimax_camchanged(spi->cimax, slot, plugin); -} - -static int cimax_spi_poll(struct cimax_spi *spi) -{ - struct spi_device *dev = spi->dev; - int err = 0; - - lock_lock(spi); - -#ifdef USE_INT_PIO - if (gpio_get_value(spi->irq_io)) - goto end; -#endif - - init_reg_hdr(spi->buf, CIMAX_CAM_EVT, 0x100, 0); - err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); - if (err) - goto end; - err = cimax_spi_get_resp(spi, CAM_TIMEOUT); - if (err) - goto end; - switch (hdr_cmd_resp(spi)) { - case CIMAX_CAM_DET_OK: { - int slot = cam_hdr_slot(spi); - int insert = cam_dat(spi)[0]; - if (!!spi->cam_inserted[slot] != insert) { - spi->cam_inserted[slot] = insert; - cimax_spi_cam_plugin(spi, slot, insert); - aml_cimax_slot_state_changed(spi->cimax, slot, - spi->cam_inserted[slot]); - } - } break; - case CIMAX_CAM_DATA_READY: { - int slot = cam_hdr_slot(spi); - spi->cam_data_ready[slot] = 1; - } break; - case CIMAX_CAM_NOEVT: - break; - default: - pr_error("unknown resp:%02x\n", hdr_cmd_resp(spi)); - break; - } -end: - queue_delayed_work(spi->workq, &spi->work, spi_poll_interval); - lock_unlock(spi); - return 0; -} - -static void cimax_spi_poll_work(struct work_struct *work) -{ - struct cimax_spi *spi = - container_of(to_delayed_work(work), struct cimax_spi, work); - spi->work_cnt++; - cimax_spi_poll(spi); -} - -static irqreturn_t cimax_irq_handler(int irq, void *para) -{ - return IRQ_HANDLED; -} - -#define CTRL_DISABLE -1 -#define CTRL_STOP 0 -#define CTRL_START 1 - -static inline int cimax_spi_poll_ctrl(struct cimax_spi *spi, int ctrl) -{ - if (ctrl == CTRL_START) { - spi->workq = create_singlethread_workqueue("cimax_spi"); - INIT_DELAYED_WORK(&spi->work, &cimax_spi_poll_work); - queue_delayed_work(spi->workq, - &spi->work, spi_poll_interval); - pr_dbg("poll started\n"); - } else { - if (!spi->workq) - return 0; - cancel_delayed_work_sync(&spi->work); - destroy_workqueue(spi->workq); - spi->workq = NULL; - pr_dbg("poll stopped\n"); - } - return 0; -} - -static inline int cimax_spi_intr_ctrl(struct cimax_spi *spi, int ctrl) -{ - if (ctrl == CTRL_START) { - int ret; - if (spi->irq == -1) { - pr_error("incorrect irq"); - return -1; - } - ret = request_irq(spi->irq, cimax_irq_handler, - IRQF_SHARED|IRQF_TRIGGER_RISING, - "cimax irq", spi); - enable_irq(spi->irq); - } else { - if (spi->irq == -1) - return 0; - disable_irq(spi->irq); - free_irq(spi->irq, spi); - } - return 0; -} - -static int cimax_spi_setup_poll(struct cimax_spi *spi, int poll_mode) -{ - if (poll_mode == spi->poll_mode) - return 0; - switch (poll_mode) { - case POLL_MODE: - if (spi->poll_mode == INT_MODE) - cimax_spi_intr_ctrl(spi, CTRL_DISABLE); - cimax_spi_poll_ctrl(spi, CTRL_START); - spi->poll_mode = POLL_MODE; - break; - case INT_MODE: - if (spi->poll_mode == POLL_MODE) - cimax_spi_poll_ctrl(spi, CTRL_DISABLE); - cimax_spi_intr_ctrl(spi, CTRL_START); - spi->poll_mode = INT_MODE; - break; - case STOP_MODE: - if (spi->poll_mode == POLL_MODE) - cimax_spi_poll_ctrl(spi, CTRL_DISABLE); - else if (spi->poll_mode == INT_MODE) - cimax_spi_intr_ctrl(spi, CTRL_DISABLE); - spi->poll_mode = STOP_MODE; - break; - default: - break; - } - return 0; -} - -static int cimax_spi_hw_reset(struct cimax_spi *spi, int reset_val) -{ - /*trigger reset io*/ - if (spi->rst_io) { - gpio_direction_output(spi->rst_io, reset_val ? 1 : 0); - msleep(50); - gpio_direction_output(spi->rst_io, reset_val ? 0 : 1); - } - return 0; -} - - -enum regOperation_e { - /** Read register. */ - REG_OP_READ, - /** Write register. */ - REG_OP_WRITE, - /** Read register until some bits are set. */ - REG_OP_WAIT_TO_BE_SET, - /** Read register until some bits are cleared. */ - REG_OP_WAIT_TO_BE_CLEARED, - /** Read register until it's value is not equal to defined. */ - REG_OP_WAIT_EQUAL, - /** Perform logical AND over register. */ - REG_OP_LOGICAL_AND, - /** Perform logical OR over register. */ - REG_OP_LOGICAL_OR, - /** Wait timeout in miliseconds. */ - REG_OP_WAIT -}; - -struct regSettings_s { - /** CIMaX+ register address. */ - u16 reg; - /** CIMaX+ register value. */ - u16 val; - /** CIMaX+ register operation. */ - enum regOperation_e op; -}; - -static struct regSettings_s spiRegSettings[] = { - /** TS interface init. */ - {IN_SEL, 0x00, REG_OP_WRITE}, /** Close TS input. */ - {OUT_SEL, 0x00, REG_OP_WRITE}, /** Close TS output. */ - {FIFO_CTRL, 0x0f, REG_OP_WRITE}, /** Reset TS FIFO. */ - {SYNC_RTV_CTRL, 0x0f, REG_OP_WRITE}, - - /** CAM power. */ - {GPIO0_DATA_OUT, 0x00, REG_OP_WRITE}, - /** Unlock CFG. */ - {CFG_2, 0x00, REG_OP_WRITE}, - /** 1) DVB/CI/CI+/SCARD 2slot. */ - {CFG_1, 0x00, REG_OP_WRITE}, - /** 2) Set the Default "power off" state - such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z'. */ - {GPIO0_DFT, 0x00, REG_OP_WRITE}, - /** 3) Set GPIO3 as external power switch driver. */ - {GPIO0_MASK_DATA, 0x07, REG_OP_WRITE}, - /** 4) Set "power on" state (VCC=VPP1=VPP2= 5V). */ - {GPIO0_DATA_OUT, 0x03, REG_OP_WRITE}, - /** 5) Lock config. */ - {CFG_2, 0x01, REG_OP_WRITE}, - /** 6) Write in the GPIO0_DIR_REG: defines the GPIOs, - which are used to drive the external power switch, in output mode. */ - {GPIO0_DIR, 0x07, REG_OP_WRITE}, - /** 7) Check VCCENable. */ - {CFG_1, 0x20, REG_OP_WAIT_TO_BE_SET}, - /** 8) Set & wait for PcmciaOutputEnable. */ - {CFG_1, 0x08, REG_OP_LOGICAL_OR}, - {CFG_1, 0x08, REG_OP_WAIT_TO_BE_SET}, - - /** Set router CAM. */ - /** CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1. */ - {ROUTER_CAM_MOD, 0x21, REG_OP_WRITE}, - {ROUTER_CAM_CH, 0x00, REG_OP_WRITE}, - /** Wait 200 miliseconds. */ - {0x0000, 200, REG_OP_WAIT}, - - /** Set In/Out. */ - /** Route CAM Channel 0 to Channel 0, Channel 1 null. */ - {ROUTER_CAM_CH, 0x80, REG_OP_WRITE}, - -#ifdef PARALLEL_OUT -#else -#if 1 - /*72M internal clock source*/ - /*CLK Select SER0->72M*/ - {CkMan_Select, 0x20, REG_OP_WRITE}, - /*Enable SER0 clk source, Enable 72M clk source*/ - {CkMan_Config, 0x44, REG_OP_LOGICAL_OR}, -#else - /*108M internal clock source*/ - /*CLK Select SER0->108M*/ - {CkMan_Select, 0x30, REG_OP_WRITE}, - /*Enable SER0 clk source, Enable 108M clk source*/ - {CkMan_Config, 0x48, REG_OP_LOGICAL_OR}, -#endif - {P2S_CH0_CTRL, 0x19, REG_OP_WRITE}, /*Enable p2s*/ - {OUT_SEL, 0x02, REG_OP_WRITE}, /*Out1=p2s0*/ -#endif /*Parallel out*/ - - /** Input Ch0=Parallel, Ch1=null. */ - {IN_SEL, 0x01, REG_OP_WRITE}, -}; - -int downloadCfg(struct cimax_spi *spi) -{ - u32 cnt; - u8 buf[CIMAX_REG_PLD_SIZE]; - struct aml_cimax *cimax = spi->cimax; - - pr_info("Download CIMaX+ configuration(register settings):\n"); - - for (cnt = 0; cnt < sizeof(spiRegSettings)/sizeof(struct regSettings_s); - cnt++) { - pr_dbg("reg:%04x, val:%02x, op:%d\n", - spiRegSettings[cnt].reg, - spiRegSettings[cnt].val, - spiRegSettings[cnt].op); - switch (spiRegSettings[cnt].op) { - case REG_OP_READ: - /* Read register. */ - if (aml_cimax_spi_read_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ read error. */ - pr_error("FAILED at REG_OP_READ operation.\n"); - return -1; - } - break; - case REG_OP_WRITE: - /* Write register. */ - if (aml_cimax_spi_write_reg(cimax, - spiRegSettings[cnt].reg, - (u8 *)&spiRegSettings[cnt].val, - 1) < 0) { - /* CIMaX+ write error. */ - pr_error("FAILED at REG_OP_WRITE operation.\n"); - return -1; - } - break; - case REG_OP_WAIT_TO_BE_SET: - do { - if (aml_cimax_spi_read_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ read error. */ - pr_error("E REG_OP_WAIT_TO_BE_SET\n"); - return -1; - } - } while ((buf[0] & spiRegSettings[cnt].val) - != spiRegSettings[cnt].val); - break; - case REG_OP_WAIT_TO_BE_CLEARED: - do { - if (aml_cimax_spi_read_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ read error. */ - pr_error("REG_OP_WAIT_TO_BE_CLEARED\n"); - return -1; - } - } while ((buf[0] & spiRegSettings[cnt].val) != 0); - break; - case REG_OP_WAIT_EQUAL: - do { - if (aml_cimax_spi_read_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ read error. */ - pr_error("REG_OP_WAIT_EQUAL.\n"); - return -1; - } - } while (buf[0] != spiRegSettings[cnt].val); - break; - case REG_OP_LOGICAL_AND: - if (aml_cimax_spi_read_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ read error. */ - pr_error("FAILED at REG_OP_LOGICAL_AND(r).\n"); - return -1; - } - buf[0] &= spiRegSettings[cnt].val; - if (aml_cimax_spi_write_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ write error. */ - pr_error("FAILED at REG_OP_LOGICAL_AND(w).\n"); - return -1; - } - break; - case REG_OP_LOGICAL_OR: - if (aml_cimax_spi_read_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ read error. */ - pr_error("FAILED at REG_OP_LOGICAL_OR(r).\n"); - return -1; - } - buf[0] |= spiRegSettings[cnt].val; - if (aml_cimax_spi_write_reg(cimax, - spiRegSettings[cnt].reg, buf, 1) < 0) { - /* CIMaX+ write error. */ - pr_error("FAILED at REG_OP_LOGICAL_AND(w).\n"); - return -1; - } - break; - case REG_OP_WAIT: - msleep(spiRegSettings[cnt].val); - break; - default: - pr_error("\nInvalid operation 0x%02x!\n", - spiRegSettings[cnt].op); - } - } - pr_info("config OK.\n"); - return 0; -} - - -#define CIMAX_FW_PKT_SIZE 128 -#define CIMAX_FW_START_ADDR 0x8000 -#define CIMAX_FW_STOP_ADDR 0xcff9 -#define CIMAX_FW_VECT_ADDR 0xfffa -#define CIMAX_FW_VECT_SIZE 6 - -static u32 compute_bistrom(const u8 *ptr, int size, u32 sign) -{ - int k, i; - u16 s; - - for (k = 0; k < size; k++) { - s = ptr[k]&0x01; - for (i = 0; i < 16; i++) - if (0x88B7 & (1<>i) & 0x01; - s |= ((sign<<1) ^ (ptr[k])) & 0x00FE; - s |= (sign<<1) & 0x00FF00; - sign = s; - } - return sign; -} - -static int cimax_spi_upload_firmware(struct cimax_spi *spi, - const u8 *fw_data, u32 *sign) -{ - struct aml_cimax *cimax = spi->cimax; - int err = 0; - int addr; - const u8 *ptr; - int size; - int debug = cimax_spi_debug; - u8 *ptmp = kzalloc(CIMAX_FW_PKT_SIZE + CIMAX_REG_HDR_SIZE, GFP_KERNEL); - - if (!ptmp) - return -ENOMEM; - - cimax_spi_debug = 0; - - addr = CIMAX_FW_START_ADDR; - ptr = fw_data + addr; - while (addr < CIMAX_FW_STOP_ADDR) { - size = (addr <= (CIMAX_FW_STOP_ADDR+1-CIMAX_FW_PKT_SIZE)) ? - CIMAX_FW_PKT_SIZE : (CIMAX_FW_STOP_ADDR+1-addr); - - *sign = compute_bistrom(ptr, size, *sign); - - pr_dbg(">>%x@%x\n", size, addr); - - /*dump("w:", (u8*)ptr, size);*/ - err = aml_cimax_spi_write_reg(cimax, addr, (u8 *)ptr, size); - if (err) - break; - err = aml_cimax_spi_read_reg(cimax, addr, ptmp, size); - if (err) - break; - /*dump("r:", ptmp, size);*/ - if (memcmp(ptr, ptmp, size)) { - pr_error("fw write error.\n"); - err = -ENODEV; - break; - } - - addr += size; - ptr += size; - } - - if (!err) { - addr = CIMAX_FW_VECT_ADDR; - ptr = fw_data + addr; - size = CIMAX_FW_VECT_SIZE; - - *sign = compute_bistrom(ptr, size, *sign); - - err = aml_cimax_spi_write_reg(cimax, addr, (u8 *)ptr, size); - if (err) - goto end; - err = aml_cimax_spi_read_reg(cimax, addr, ptmp, size); - if (err) - goto end; - if (memcmp(ptr, ptmp, size)) { - pr_error("fw vect write error.\n"); - err = -ENODEV; - goto end; - } - } -end: - kfree(ptmp); - - cimax_spi_debug = debug; - return err; -} - -static int cimax_spi_check_bistrom(struct cimax_spi *spi, - int start, int end, u32 sign) -{ - struct aml_cimax *cimax = spi->cimax; - int err = 0; - u8 buf[2]; - - buf[0] = (0xd000-start) & 0xff; - buf[1] = (0xd000-start) >> 8; - err = aml_cimax_spi_write_reg(cimax, 0x8d, buf, 2); - if (err) - return err; - buf[0] = sign & 0xff; - buf[1] = sign >> 8; - err = aml_cimax_spi_write_reg(cimax, 0x80, buf, 2); - if (err) - return err; - buf[0] = 0xf; - err = aml_cimax_spi_write_reg(cimax, 0x82, buf, 1); - if (err) - return err; - err = aml_cimax_spi_read_reg(cimax, 0x41, buf, 2); - if (err) - return err; - pr_dbg("bist checked: 0x%04x\n", byte_to_u16(buf[0], buf[1])); - err = aml_cimax_spi_read_reg(cimax, 0x09, buf, 1); - if (err) - return err; - pr_dbg("rom status: 0x%02x\n", buf[0]); - return buf[0]; -} - -static int cimax_spi_init_firmware(struct cimax_spi *spi) -{ - struct spi_device *dev = spi->dev; - int err = 0; - - init_reg_hdr(spi->buf, CIMAX_REG_INIT, 0, 0); - err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); - if (err) - return err; - err = cimax_spi_get_resp(spi, REG_TIMEOUT); - if (err) - return err; - if (check_reg_hdr(spi->buf, CIMAX_REG_INIT_OK, 0, 0)) { - perr("init fw fail.", spi); - return -EINVAL; - } - return err; -} - -static void request_fw_callback(const struct firmware *fw, void *context) -{ - u32 sign = 0; - int err = 0; - struct cimax_spi *spi = (struct cimax_spi *)context; - - if (!fw) - return; - - pr_dbg("got fw: %zd @ %p\n", fw->size, fw->data); - - /*cimax_spi_hw_reset(spi, 1);*/ - - err = cimax_spi_upload_firmware(spi, fw->data, &sign); - if (err) - goto end; - pr_dbg("upload fw done.\n"); - err = cimax_spi_check_bistrom(spi, - CIMAX_FW_START_ADDR, CIMAX_FW_STOP_ADDR, sign); - if (err != 0x2) - goto end; - pr_dbg("check bistrom done.\n"); - err = cimax_spi_init_firmware(spi); - if (err) - goto end; -end: - if (fw) - release_firmware(fw); - if (err) - return; - - if (downloadCfg(spi)) { - pr_error("download config fail.\n"); - return; - } - - cimax_spi_setup_poll(spi, cimax_poll_mode ? POLL_MODE : INT_MODE); - - return; -} - -static int cimax_spi_load_fw(struct cimax_spi *spi) -{ - char *name = "cimax_spidvb.bin"; - return request_firmware_nowait(THIS_MODULE, 1, name, - &spi->dev->dev, GFP_KERNEL, spi, request_fw_callback); -} - -static int cimax_spi_dev_probe(struct spi_device *spi) -{ - int ret; - struct cimax_spi *cimax_spi; - - pr_dbg("dev probe\n"); - /*setup again?*/ - spi->bits_per_word = 8; - ret = spi_setup(spi); - if (ret) - pr_dbg("spi setup failed\n"); - - cimax_spi = dev_get_platdata(&spi->dev); - cimax_spi->dev = spi; - - spi_set_drvdata(spi, cimax_spi); - - return cimax_spi_load_fw(cimax_spi); -} - -static int cimax_spi_dev_remove(struct spi_device *spi) -{ - struct cimax_spi *cimax_spi = dev_get_drvdata(&spi->dev); - - pr_dbg("dev remove\n"); - cimax_spi_setup_poll(cimax_spi, STOP_MODE); - return 0; -} - -static int cimax_spi_get_config_from_dts(struct cimax_spi *spi, - struct spi_board_info *bdinfo) -{ - struct device_node *child = NULL; - struct platform_device *pdev = spi->pdev; - struct device_node *np = pdev->dev.of_node; - unsigned int val; - int ret = 0; - pr_dbg("fetch cimax spi in dts\n"); - - child = of_get_child_by_name(np, "cimax"); - if (child == NULL) { - pr_error("cimax not found in dts\n"); - return -1; - } - child = of_get_child_by_name(child, "spi"); - if (!child) { - pr_error("spi not found in cimax"); - return -1; - } - - /* get spi config */ - ret = of_property_read_u32(child, "bus_num", &val); - if (ret) - pr_error("bus_num not found, use default.\n"); - else - bdinfo->bus_num = val; - pr_dbg("bus_num: %d\n", bdinfo->bus_num); - ret = of_property_read_u32(child, "chip_select", &val); - if (ret) - pr_error("chip_select not found, use default.\n"); - else - bdinfo->chip_select = val; - pr_dbg("chip_select: %d\n", bdinfo->chip_select); - ret = of_property_read_u32(child, "max_frequency", &val); - if (ret) - pr_error("max_frequency not found, use default.\n"); - else - bdinfo->max_speed_hz = val; - pr_dbg("max_speed_hz: %d\n", bdinfo->max_speed_hz); - ret = of_property_read_u32(child, "mode", &val); - if (ret) - pr_error("mode not found, use default.\n"); - else - bdinfo->mode = val; - pr_dbg("mode: %d\n", bdinfo->mode); -/* -dvbci { - compatible = "amlogic, dvbci"; - dev_name = "dvbci"; - io_type = <2>;//0:iobus,1:spi,2:cimax - cimax { - io_type = <0> //0:spi 1:usb - spi { - spi_bus_num = <0>; - spi_chip_select = <0>; - spi_max_frequency = <3000000>; - - rst_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - - irq_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - irq = <2>; - interrupts = ; - }; - }; - -}; -*/ -#ifdef USE_INT_PIO - { - int ret = 0; - int gpio = -1; - gpio = of_get_named_gpio_flags(child, "irq-gpios", 0, NULL); - ret = gpio_request(gpio, "cimax-irq"); - if (ret < 0) { - pr_error("irq-gpios request fail.\n"); - return ret; - } - - ret = gpio_direction_input(gpio); - - spi->irq_io = gpio; - pr_dbg("irq_io: %d\n", spi->irq_io); - } -#ifdef CIMAX_IRQ - { - int irq; - unsigned int irqflag; - ret = of_property_read_u32(child, "irq", &gpio_irq); - irq = irq_of_parse_and_map(child, 0); - - gpio_for_irq(gpio, - AML_GPIO_IRQ(gpio_irq, FILTER_NUM7, GPIO_IRQ_FALLING)); - spi->irq = irq; - pr_dbg("irq: %d\n", spi->irq); - } -#else - spi->irq = -1; -#endif -#endif/*USE_INT_PIO*/ - { - int ret = 0; - int gpio = -1; - gpio = of_get_named_gpio_flags(child, "rst-gpios", 0, NULL); - if (gpio != -1) { - ret = gpio_request(gpio, "cimax"); - if (ret < 0) { - pr_error("rst-gpios request fail.\n"); - return ret; - } - - cimax_spi_hw_reset(spi, 1); - - spi->rst_io = gpio; - pr_dbg("rst: %d\n", spi->rst_io); - } else { - pr_error("rst io got fail, %d\n", gpio); - } - } - return 0; -} - -static struct spi_board_info cimax_spi_bdinfo = { - .modalias = "cimax_spi", - .mode = SPI_MODE_3, - .max_speed_hz = 1000000, /* 1MHz */ - .bus_num = 0, /* SPI bus No. */ - .chip_select = 0, /* the device index on the spi bus */ - .controller_data = NULL, -}; - -static struct spi_driver cimax_spi_dev_driver = { - .probe = cimax_spi_dev_probe, - .remove = cimax_spi_dev_remove, - .driver = { - .name = "cimax_spi", - .owner = THIS_MODULE, - }, -}; - -int aml_cimax_spi_init(struct platform_device *pdev, struct aml_cimax *cimax) -{ - int ret; - struct cimax_spi *cimax_spi; - - cimax_spi = kzalloc(sizeof(struct cimax_spi), GFP_KERNEL); - if (!cimax_spi) - return -ENOMEM; - - cimax_spi->pdev = pdev; - cimax_spi->cimax = cimax; - cimax_spi_get_config_from_dts(cimax_spi, &cimax_spi_bdinfo); - - /*init spi_lock*/ - lock_init(cimax_spi); - - /*register device*/ - cimax_spi_bdinfo.platform_data = cimax_spi; - spi_register_board_info(&cimax_spi_bdinfo, 1); - - /*register driver*/ - ret = spi_register_driver(&cimax_spi_dev_driver); - if (ret) { - pr_error("register cimax spi driver failed\n"); - return ret; - } - - /*init cimax used api.*/ -#define WI(_f)\ - cimax->ops._f = aml_cimax_spi_##_f - WI(read_cis); - WI(write_cor); - WI(negotiate); - WI(read_lpdu); - WI(write_lpdu); - WI(read_cam_status); - WI(cam_reset); - WI(slot_reset); - WI(slot_shutdown); - WI(slot_ts_enable); - WI(slot_status); - /*WI(start);*/ - /*WI(stop);*/ - WI(read_reg); - WI(write_reg); - - cimax->priv = cimax_spi; - - g_spi = cimax_spi; - - aml_cimax_spi_mod_init(); - - return 0; -} -EXPORT_SYMBOL(aml_cimax_spi_init); - -int aml_cimax_spi_exit(struct aml_cimax *cimax) -{ - struct cimax_spi *spi = cimax_to_spi(cimax); - - if (!spi) - return -ENODEV; - - aml_cimax_spi_mod_exit(); - - /*unregister driver*/ - spi_unregister_driver(&cimax_spi_dev_driver); - /*unregister device*/ - spi_unregister_device(spi->dev); - - if (spi->irq_io) - gpio_free(spi->irq_io); - if (spi->rst_io) - gpio_free(spi->rst_io); - - kfree(spi->cis); - - kfree(spi); - cimax->priv = NULL; - - g_spi = NULL; - return 0; -} -EXPORT_SYMBOL(aml_cimax_spi_exit); - -static int cimax_spi_reset(struct cimax_spi *spi, int reset_val) -{ - pr_dbg("reset spi:%p, rst:%d\n", spi, spi ? spi->rst_io : -1); - if (!spi) - return -ENODEV; - - pr_dbg("cimax spi reset\n"); - - cimax_spi_setup_poll(spi, STOP_MODE); - - cimax_spi_hw_reset(spi, reset_val); - - /*notify unplugged*/ - aml_cimax_camchanged(spi->cimax, 0, 0); - aml_cimax_camchanged(spi->cimax, 1, 0); - - spi->cam_inserted[0] = spi->cam_inserted[1] = 0; - spi->cam_data_ready[0] = spi->cam_data_ready[1] = 0; - - /*async start fw*/ - cimax_spi_load_fw(spi); - - /*cimax_spi_setup_poll(spi, cimax_poll_mode? POLL_MODE : INT_MODE);*/ - return 0; -} - -static ssize_t reset_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret; - ret = sprintf(buf, "echo 1 > %s\n", attr->attr.name); - return ret; -} - -static ssize_t reset_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int ret; - int val = 0; - if (!g_spi) - return size; - ret = sscanf(buf, "%i", &val); - if (ret == 1) - ret = cimax_spi_reset(g_spi, val); - return size; -} - -static ssize_t debug_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - if (!g_spi) - return ret; - - ret = sprintf(buf, "poll mode: %d\n", g_spi->poll_mode); - ret += sprintf(buf+ret, "status slot[0]=[%d] slot[1]=[%d]\n", - g_spi->cam_inserted[0], g_spi->cam_inserted[1]); - ret += sprintf(buf+ret, "data slot[0]=[%d] slot[1]=[%d]\n", - g_spi->cam_data_ready[0], g_spi->cam_data_ready[1]); - ret += sprintf(buf+ret, "work cnt:%d\n", g_spi->work_cnt); - return ret; -} - -static int reg_addr; -static ssize_t addr_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - ret = sprintf(buf, "addr = 0x%04x\n", reg_addr); - return ret; -} - -static ssize_t addr_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - if (!g_spi) - return size; - if (sscanf(buf, "%i", ®_addr) == 1) - return size; - return size; -} - -static ssize_t reg_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - u8 reg_val = 0; - struct aml_cimax *cimax = NULL; - - if (!g_spi) - return ret; - - cimax = g_spi->cimax; - ret = aml_cimax_spi_read_reg(cimax, reg_addr, ®_val, 1); - if (ret) - ret = sprintf(buf, "read fail, err=%d\n", ret); - else - ret = sprintf(buf, "reg[0x%04x] = 0x%02x\n", reg_addr, reg_val); - return ret; -} - -static ssize_t reg_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int ret = 0; - struct aml_cimax *cimax = NULL; - int val = 0; - u8 reg_val = 0; - - if (!g_spi) - return size; - - if (sscanf(buf, "%i", &val) != 1) - return size; - reg_val = val; - cimax = g_spi->cimax; - ret = aml_cimax_spi_write_reg(cimax, reg_addr, ®_val, 1); - if (ret) - return ret; - return size; -} - -static int cis_mode; /*0:hex 1:binary*/ -static ssize_t cis_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - - if (!g_spi || !g_spi->cis) - return ret; - - if (cis_mode == 0) { - int i; - for (i = 0; i < CIS_MAX; i++) { - if (i && !(i & 0xf)) - ret += sprintf(buf+ret, "\n"); - ret += sprintf(buf+ret, "%02X ", g_spi->cis[i]); - } - ret += sprintf(buf+ret, "\n"); - return ret; - } else { - memcpy(buf, g_spi->cis, CIS_MAX); - return CIS_MAX; - } - return ret; -} - -static ssize_t cis_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - if (size >= 3 - && !memcmp(buf, "bin", 3)) - cis_mode = 1; - else - cis_mode = 0; - return size; -} - -static ssize_t ts_rate_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - u8 lsb = 0, msb = 0, plen = 0; - struct aml_cimax *cimax = NULL; - int err = 0; - - if (!g_spi) - return ret; - - cimax = g_spi->cimax; - err = aml_cimax_spi_read_reg(cimax, PCK_LENGTH, &plen, 1); - err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH0_LSB, &lsb, 1); - err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH0_MSB, &msb, 1); - if (err || !byte_to_u16(msb, lsb)) - ret += sprintf(buf+ret, "read fail, err=%d\n", err); - else - ret += sprintf(buf+ret, "rate[0] = %d Kbps\n", - 540*plen*8/byte_to_u16(msb, lsb)); - if (err) - return ret; - - err = aml_cimax_spi_read_reg(cimax, BITRATE_CH1_LSB, &lsb, 1); - err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH1_MSB, &msb, 1); - if (err || !byte_to_u16(msb, lsb)) - ret += sprintf(buf+ret, "read fail, err=%d\n", err); - else - ret += sprintf(buf+ret, "rate[1] = %d Kbps\n", - 540*plen*8/byte_to_u16(msb, lsb)); - return ret; -} - -static ssize_t loop_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - u8 ch = 0, mod = 0; - struct aml_cimax *cimax = NULL; - int err = 0; - - if (!g_spi) - return ret; - - cimax = g_spi->cimax; - err = aml_cimax_spi_read_reg(cimax, ROUTER_CAM_CH, &ch, 1); - err |= aml_cimax_spi_read_reg(cimax, ROUTER_CAM_MOD, &mod, 1); - if (err) { - ret = sprintf(buf, "read fail, err=%d\n", err); - return ret; - } - ret += sprintf(buf + ret, "OUT-0 <= "); - switch (ch & 0x0f) { - case 0x0: - ret += sprintf(buf + ret, "CAM-A"); break; - case 0x1: - ret += sprintf(buf + ret, "CH0-IN"); break; - case 0x2: - ret += sprintf(buf + ret, "CH1-IN"); break; - case 0x3: - ret += sprintf(buf + ret, "REMAPPER"); break; - case 0x4: - ret += sprintf(buf + ret, "PREHEADER"); break; - case 0x5: - ret += sprintf(buf + ret, "CAM-B"); break; - case 0x6: - ret += sprintf(buf + ret, "GAPREMOVER-0"); break; - case 0x7: - ret += sprintf(buf + ret, "GAPREMOVER-1"); break; - case 0x8: - ret += sprintf(buf + ret, "NONE"); break; - default: - ret += sprintf(buf + ret, "UNKNOWN"); break; - } - ret += sprintf(buf + ret, "\nCAM-A <= "); - switch (mod & 0x07) { - case 0x1: - ret += sprintf(buf + ret, "CH0-IN"); break; - case 0x2: - ret += sprintf(buf + ret, "CH1-IN"); break; - case 0x3: - ret += sprintf(buf + ret, "REMAPPER"); break; - case 0x4: - ret += sprintf(buf + ret, "PREHEADER"); break; - case 0x5: - ret += sprintf(buf + ret, "CAM-B"); break; - case 0x6: - ret += sprintf(buf + ret, "GAPREMOVER-0"); break; - case 0x7: - ret += sprintf(buf + ret, "GAPREMOVER-1"); break; - default: - ret += sprintf(buf + ret, "NONE"); break; - } - ret += sprintf(buf + ret, "\n"); - - return ret; -} - - -static ssize_t loop_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int loop = 0; - int err = 0; - struct aml_cimax *cimax = NULL; - - if (!g_spi) - return size; - - if (sscanf(buf, "%i", &loop) == 1) { - int a = g_spi->cam_inserted[0]; - int b = g_spi->cam_inserted[1]; - u8 cm[2]; - cm[0] = loop ? (b ? 0x85 : 0x80) : 0x81;/*CH*/ - cm[1] = loop ? (a ? 0x51 : 0x11) : 0x00;/*MOD*/ - cimax = g_spi->cimax; - err = aml_cimax_spi_write_reg(cimax, ROUTER_CAM_CH, cm, 2); - } - return size; -} - -static ssize_t slot_reset_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int err = 0; - int slot = 0; - struct aml_cimax *cimax = NULL; - - if (!g_spi) - return size; - - if (sscanf(buf, "%i", &slot) == 1) { - if (slot == 0 || slot == 1) { - pr_dbg("reset slot %d\n", slot); - cimax = g_spi->cimax; - err = aml_cimax_spi_slot_reset(cimax, slot); - } - } - return size; -} - -static ssize_t detect_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int err = 0; - int slot = 0; - struct aml_cimax *cimax = NULL; - - if (!g_spi) - return size; - - if (sscanf(buf, "%i", &slot) == 1) { - if (slot == 0 || slot == 1) { - int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; - u8 reg = 0; - cimax = g_spi->cimax; - err = aml_cimax_spi_read_reg(cimax, addr, ®, 1); - g_spi->cam_inserted[slot] = reg & 1; - pr_dbg("detect slot(%d): %d\n", slot, reg & 1); - } - } - return size; -} - -static struct class_attribute cimax_spi_class_attrs[] = { - __ATTR_RW(reset), - __ATTR_RO(debug), - __ATTR_RW(addr), - __ATTR_RW(reg), - __ATTR_RW(cis), - __ATTR_RO(ts_rate), - __ATTR_RW(loop), - __ATTR_WO(slot_reset), - __ATTR_WO(detect), - __ATTR_NULL -}; - -static struct class cimax_spi_class = { - .name = "cimax_spi", - .class_attrs = cimax_spi_class_attrs, -}; - -static int aml_cimax_spi_mod_init(void) -{ - int ret; - pr_dbg("Amlogic CIMAX SPI Init\n"); - ret = class_register(&cimax_spi_class); - return 0; -} - -static void aml_cimax_spi_mod_exit(void) -{ - pr_dbg("Amlogic CIMAX SPI Exit\n"); - class_unregister(&cimax_spi_class); -} - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h deleted file mode 100644 index 3548de0506dd..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h +++ /dev/null @@ -1,20 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#ifndef _AML_CIMAX_SPI_H_ -#define _AML_CIMAX_SPI_H_ - -#include -#include "aml_cimax.h" - -int aml_cimax_spi_init(struct platform_device *pdev, struct aml_cimax *ci); -int aml_cimax_spi_exit(struct aml_cimax *ci); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c deleted file mode 100644 index b74b34a63b51..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c +++ /dev/null @@ -1,1714 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include - -#include "aml_cimax.h" -#include "./usb/SRC/cimax+usb-driver.h" - -#define MOD_NAME "aml_cimax_usb" - -#define pr_dbg(fmt...)\ - do {\ - if (cimax_usb_debug)\ - pr_info("cimax_usb: "fmt);\ - } while (0) -#define pr_inf(fmt...) pr_info("cimax_usb: "fmt) -#define pr_error(fmt...) pr_err("AML_CIMAX_USB: " fmt) - -/* - Uncomment below and enable permanent power in cfg - to disable dynamic power control mechanism -*/ -/*#define DISABLE_POWER_PATCH*/ - -#define BUFFIN_CFG 0x0000 -#define BUFFIN_ADDR_LSB 0x0001 -#define BUFFIN_ADDR_MSB 0x0002 -#define BUFFIN_DATA 0x0003 -#define BUFFOUT_CFG 0x0004 -#define BUFFOUT_ADDR_LSB 0x0005 -#define BUFFOUT_ADDR_MSB 0x0006 -#define BUFFOUT_DATA 0x0007 -#define BOOT_Key 0x0008 -#define BOOT_Status 0x0009 -#define BOOT_Test 0x000A -#define usb2_0_irq_mask 0x0010 -#define usb2_0_status 0x0011 -#define usb2_0_rx 0x0012 -#define usb2_0_tx 0x0013 -#define SPI_Slave_Ctrl 0x0018 -#define SPI_Slave_Status 0x0019 -#define SPI_Slave_Rx 0x001A -#define SPI_Slave_Tx 0x001B -#define SPI_Slave_Mask 0x001C -#define UCSG_Ctrl 0x0020 -#define UCSG_Status 0x0021 -#define UCSG_RxData 0x0022 -#define UCSG_TxData 0x0023 -#define PCtrl_Ctrl 0x0028 -#define PCtrl_Status 0x0029 -#define PCtrl_NbByte_LSB 0x002A -#define PCtrl_NbByte_MSB 0x002B -#define SPI_Master_Ctl 0x0030 -#define SPI_Master_NCS 0x0031 -#define SPI_Master_Status 0x0032 -#define SPI_Master_TxBuf 0x0033 -#define SPI_Master_RxBuf 0x0034 -#define BISTRAM_Ctl 0x0038 -#define BISTRAM_Bank 0x0039 -#define BISTRAM_Pat 0x003A -#define BISTRAM_SM 0x003B -#define BISTRAM_AddrLSB 0x003C -#define BISTROM_Config 0x0040 -#define BISTROM_SignatureLSB 0x0041 -#define BISTROM_SignatureMSB 0x0042 -#define BISTROM_StartAddrLSB 0x0043 -#define BISTROM_StartAddrMSB 0x0043 -#define BISTROM_StopAddrLSB 0x0043 -#define BISTROM_StopAddrMSB 0x0043 -#define CkMan_Config 0x0048 -#define CkMan_Select 0x0049 -#define CkMan_Test 0x004A -#define Revision_Number 0x004B -#define ResMan_Config 0x0050 -#define ResMan_Status 0x0051 -#define ResMan_WD 0x0052 -#define ResMan_WD_MSB 0x0053 -#define CPU_Test 0x0060 -#define IrqMan_Config0 0x0068 -#define IrqMan_Config1 0x0069 -#define IrqMan_Irq0 0x006A -#define IrqMan_NMI 0x006B -#define IrqMan_SleepKey 0x006C -#define Tim_Config 0x0070 -#define Tim_Value_LSB 0x0071 -#define Tim_Value_MSB 0x0072 -#define Tim_Comp_LSB 0x0073 -#define Tim_Comp_MSB 0x0074 -#define TI_Config 0x0076 -#define TI_Data 0x0077 -#define TI_Reg0 0x0078 -#define TI_Reg1 0x0079 -#define TI_Reg2 0x007A -#define TI_Reg3 0x007B -#define TI_Reg4 0x007C -#define TI_ROM1 0x007D -#define TI_ROM2 0x007E -#define TI_ROM3 0x007F -#define DVBCI_START_ADDR 0x0100 -#define DVBCI_END_ADDR 0x017F -#define DATA 0x0180 -/*#define CTRL 0x0181*/ -#define QB_HOST 0x0182 -#define LEN_HOST_LSB 0x0183 -#define LEN_HOST_MSB 0x0184 -#define FIFO_TX_TH_LSB 0x0185 -#define FIFO_TX_TH_MSB 0x0186 -#define FIFO_TX_D_NB_LSB 0x0187 -#define FIFO_TX_D_NB_MSB 0x0188 -#define QB_MOD_CURR 0x0189 -#define LEN_MOD_CURR_LSB 0x018A -#define LEN_MOD_CURR_MSB 0x018B -#define QB_MOD 0x018C -#define LEN_MOD_LSB 0x018D -#define LEN_MOD_MSB 0x018E -#define FIFO_RX_TH_LSB 0x018F -#define FIFO_RX_TH_MSB 0x0190 -#define FIFO_RX_D_NB_LSB 0x0191 -#define FIFO_RX_D_NB_MSB 0x0192 -#define IT_STATUS_0 0x0193 -#define IT_STATUS_1 0x0194 -#define IT_MASK_0 0x0195 -#define IT_MASK_1 0x0196 -#define IT_HOST_PIN_CFG 0x0200 -#define CFG_0 0x0201 -#define CFG_1 0x0202 -#define CFG_2 0x0203 -#define IT_HOST 0x0204 -#define MOD_IT_STATUS 0x0205 -#define MOD_IT_MASK 0x0206 -#define MOD_CTRL_A 0x0207 -#define MOD_CTRL_B 0x0208 -#define DEST_SEL 0x0209 -#define CAM_MSB_ADD 0x020A -#define GPIO0_DIR 0x020B -#define GPIO0_DATA_IN 0x020C -#define GPIO0_DATA_OUT 0x020D -#define GPIO0_STATUS 0x020E -#define GPIO0_IT_MASK 0x020F -#define GPIO0_DFT 0x0210 -#define GPIO0_MASK_DATA 0x0211 -#define GPIO1_DIR 0x0212 -#define GPIO1_DATA_IN 0x0213 -#define GPIO1_DATA_OUT 0x0214 -#define GPIO1_STATUS 0x0215 -#define GPIO1_IT_MASK 0x0216 -#define MEM_ACC_TIME_A 0x0217 -#define MEM_ACC_TIME_B 0x0218 -#define IO_ACC_TIME_A 0x0219 -#define IO_ACC_TIME_B 0x021A -#define EXT_CH_ACC_TIME_A 0x021B -#define EXT_CH_ACC_TIME_B 0x021C -#define PAR_IF_0 0x021D -#define PAR_IF_1 0x021E -#define PAR_IF_CTRL 0x021F -#define PCK_LENGTH 0x0220 -#define USB2TS_CTRL 0x0221 -#define USB2TS0_RDL 0x0222 -#define USB2TS1_RDL 0x0223 -#define TS2USB_CTRL 0x0224 -#define TSOUT_PAR_CTRL 0x0225 -#define TSOUT_PAR_CLK_SEL 0x0226 -#define S2P_CH0_CTRL 0x0227 -#define S2P_CH1_CTRL 0x0228 -#define P2S_CH0_CTRL 0x0229 -#define P2S_CH1_CTRL 0x022A -#define TS_IT_STATUS 0x022B -#define TS_IT_MASK 0x022C -#define IN_SEL 0x022D -#define OUT_SEL 0x022E -#define ROUTER_CAM_CH 0x022F -#define ROUTER_CAM_MOD 0x0230 -#define FIFO_CTRL 0x0231 -#define FIFO1_2_STATUS 0x0232 -#define FIFO3_4_STATUS 0x0233 -#define GAP_REMOVER_CH0_CTRL 0x0234 -#define GAP_REMOVER_CH1_CTRL 0x0235 -#define SYNC_RTV_CTRL 0x0236 -#define SYNC_RTV_CH0_SYNC_NB 0x0237 -#define SYNC_RTV_CH0_PATTERN 0x0238 -#define SYNC_RTV_CH1_SYNC_NB 0x0239 -#define SYNC_RTV_CH1_PATTERN 0x023A -#define SYNC_RTV_OFFSET_PATT 0x023B -#define CTRL_FILTER 0x023D -#define PID_EN_FILTER_CH0 0x023E -#define PID_EN_FILTER_CH1 0x023F -#define PID_LSB_FILTER_CH0_0 0x0240 -#define PID_MSB_FILTER_CH0_0 0x0241 -#define PID_LSB_FILTER_CH0_1 0x0242 -#define PID_MSB_FILTER_CH0_1 0x0243 -#define PID_LSB_FILTER_CH0_2 0x0244 -#define PID_MSB_FILTER_CH0_2 0x0245 -#define PID_LSB_FILTER_CH0_3 0x0246 -#define PID_MSB_FILTER_CH0_3 0x0247 -#define PID_LSB_FILTER_CH0_4 0x0248 -#define PID_MSB_FILTER_CH0_4 0x0249 -#define PID_LSB_FILTER_CH0_5 0x024A -#define PID_MSB_FILTER_CH0_5 0x024B -#define PID_LSB_FILTER_CH0_6 0x024C -#define PID_MSB_FILTER_CH0_6 0x024D -#define PID_LSB_FILTER_CH0_7 0x024E -#define PID_MSB_FILTER_CH0_7 0x024F -#define PID_LSB_FILTER_CH1_0 0x0260 -#define PID_MSB_FILTER_CH1_0 0x0261 -#define PID_LSB_FILTER_CH1_1 0x0262 -#define PID_MSB_FILTER_CH1_1 0x0263 -#define PID_LSB_FILTER_CH1_2 0x0264 -#define PID_MSB_FILTER_CH1_2 0x0265 -#define PID_LSB_FILTER_CH1_3 0x0266 -#define PID_MSB_FILTER_CH1_3 0x0267 -#define PID_LSB_FILTER_CH1_4 0x0268 -#define PID_MSB_FILTER_CH1_4 0x0269 -#define PID_LSB_FILTER_CH1_5 0x026A -#define PID_MSB_FILTER_CH1_5 0x026B -#define PID_LSB_FILTER_CH1_6 0x026C -#define PID_MSB_FILTER_CH1_6 0x026D -#define PID_LSB_FILTER_CH1_7 0x026E -#define PID_MSB_FILTER_CH1_7 0x026F -#define PID_OLD_LSB_REMAPPER_0 0x0280 -#define PID_OLD_MSB_REMAPPER_0 0x0281 -#define PID_OLD_LSB_REMAPPER_1 0x0282 -#define PID_OLD_MSB_REMAPPER_1 0x0283 -#define PID_OLD_LSB_REMAPPER_2 0x0284 -#define PID_OLD_MSB_REMAPPER_2 0x0285 -#define PID_OLD_LSB_REMAPPER_3 0x0286 -#define PID_OLD_MSB_REMAPPER_3 0x0287 -#define PID_OLD_LSB_REMAPPER_4 0x0288 -#define PID_OLD_MSB_REMAPPER_4 0x0289 -#define PID_OLD_LSB_REMAPPER_5 0x028A -#define PID_OLD_MSB_REMAPPER_5 0x028B -#define PID_OLD_LSB_REMAPPER_6 0x028C -#define PID_OLD_MSB_REMAPPER_6 0x028D -#define PID_OLD_LSB_REMAPPER_7 0x028E -#define PID_OLD_MSB_REMAPPER_7 0x028F -#define PID_NEW_LSB_REMAPPER_0 0x02A0 -#define PID_NEW_MSB_REMAPPER_0 0x02A1 -#define PID_NEW_LSB_REMAPPER_1 0x02A2 -#define PID_NEW_MSB_REMAPPER_1 0x02A3 -#define PID_NEW_LSB_REMAPPER_2 0x02A4 -#define PID_NEW_MSB_REMAPPER_2 0x02A5 -#define PID_NEW_LSB_REMAPPER_3 0x02A6 -#define PID_NEW_MSB_REMAPPER_3 0x02A7 -#define PID_NEW_LSB_REMAPPER_4 0x02A8 -#define PID_NEW_MSB_REMAPPER_4 0x02A9 -#define PID_NEW_LSB_REMAPPER_5 0x02AA -#define PID_NEW_MSB_REMAPPER_5 0x02AB -#define PID_NEW_LSB_REMAPPER_6 0x02AC -#define PID_NEW_MSB_REMAPPER_6 0x02AD -#define PID_NEW_LSB_REMAPPER_7 0x02AE -#define PID_NEW_MSB_REMAPPER_7 0x02AF -#define MERGER_DIV_MICLK 0x02C0 -#define PID_AND_SYNC_REMAPPER_CTRL 0x02C1 -#define PID_EN_REMAPPER 0x02C2 -#define SYNC_SYMBOL 0x02C3 -#define PID_AND_SYNC_REMAPPER_INV_CTRL 0x02C4 -#define BITRATE_CH0_LSB 0x02C5 -#define BITRATE_CH0_MSB 0x02C6 -#define BITRATE_CH1_LSB 0x02C7 -#define BITRATE_CH1_MSB 0x02C8 -#define STATUS_CLK_SWITCH_0 0x02C9 -#define STATUS_CLK_SWITCH_1 0x02CA -#define RESET_CLK_SWITCH_0 0x02CB -#define RESET_CLK_SWITCH_1 0x02CC -#define PAD_DRVSTR_CTRL 0x02CD -#define PAD_PUPD_CTRL 0x02CE -#define PRE_HEADER_ADDER_CH0_0 0x02D0 -#define PRE_HEADER_ADDER_CH0_1 0x02D1 -#define PRE_HEADER_ADDER_CH0_2 0x02D2 -#define PRE_HEADER_ADDER_CH0_3 0x02D3 -#define PRE_HEADER_ADDER_CH0_4 0x02D4 -#define PRE_HEADER_ADDER_CH0_5 0x02D5 -#define PRE_HEADER_ADDER_CH0_6 0x02D6 -#define PRE_HEADER_ADDER_CH0_7 0x02D7 -#define PRE_HEADER_ADDER_CH0_8 0x02D8 -#define PRE_HEADER_ADDER_CH0_9 0x02D9 -#define PRE_HEADER_ADDER_CH0_10 0x02DA -#define PRE_HEADER_ADDER_CH0_11 0x02DB -#define PRE_HEADER_ADDER_CH1_0 0x02E0 -#define PRE_HEADER_ADDER_CH1_1 0x02E1 -#define PRE_HEADER_ADDER_CH1_2 0x02E2 -#define PRE_HEADER_ADDER_CH1_3 0x02E3 -#define PRE_HEADER_ADDER_CH1_4 0x02E4 -#define PRE_HEADER_ADDER_CH1_5 0x02E5 -#define PRE_HEADER_ADDER_CH1_6 0x02E6 -#define PRE_HEADER_ADDER_CH1_7 0x02E7 -#define PRE_HEADER_ADDER_CH1_8 0x02E8 -#define PRE_HEADER_ADDER_CH1_9 0x02E9 -#define PRE_HEADER_ADDER_CH1_10 0x02EA -#define PRE_HEADER_ADDER_CH1_11 0x02EB -#define PRE_HEADER_ADDER_CTRL 0x02EC -#define PRE_HEADER_ADDER_LEN 0x02ED -#define PRE_HEADER_REMOVER_CTRL 0x02EE -#define FSM_DVB 0x02F0 -#define TS2USB_FSM_DEBUG 0x02F2 -#define TSOUT_PAR_FSM_DEBUG 0x02F3 -#define GAP_REMOVER_FSM_DEBUG 0x02F4 -#define PID_AND_SYNC_REMAPPER_FSM_DEBUG 0x02F5 -#define PRE_HEADER_ADDER_FSM_DEBUG 0x02F6 -#define SYNC_RTV_FSM_DEBUG 0x02F7 -#define CHECK_PHY_CLK 0x0E00 -#define USB_CTRL1 0x0E01 -#define USB_ISO2_out 0x0800 -#define USB_ISO1_out 0x1000 -#define USB_Interrupt_out 0x1E00 -#define USB_Bulk_in 0x1F00 -#define CC2_Buffer_out 0x2000 -#define USB_EP0 0x30C0 -#define CC2_Buffer_in 0x4000 -#define USB_ISO2_in 0x5800 -#define USB_ISO1_in 0x6000 -#define nmb_vector_address_lsb 0xFFFA -#define nmb_vector_address_msb 0xFFFB -#define reset_vector_address_lsb 0xFFFC -#define reset_vector_address_msb 0xFFFD -#define irb_vector_address_lsb 0xFFFE -#define irb_vector_address_msb 0xFFFF - - -#define CIMAX_REG_HDR_SIZE 4 -#define CIMAX_REG_PLD_SIZE 255 -#define CIMAX_CAM_HDR_SIZE 4 -#define CIMAX_CAM_PLD_SIZE 65535 - -#define DEF_LOCK(_l_) struct mutex _l_ - -struct cimax_usb { - struct platform_device *pdev; - struct device_s *dev; - - struct aml_cimax *cimax; - - u8 buf[CIMAX_REG_HDR_SIZE + CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE]; - int buf_size; - - int cam_inserted[2]; -#define IN_INSERTED 0x01 -#define IN_POWERED 0x02 -#define IN_LINKED 0x04 - int cam_data_ready[2]; - - int poll_mode; -#define STOP_MODE 0 -#define POLL_MODE 1 -#define INT_MODE 2 - - int rst_io; - - struct workqueue_struct *workq; - struct delayed_work work; - int work_auto_restart; - int work_cnt; - - struct delayed_work power_work; - int power_work_cnt; - int cam_det; - - DEF_LOCK(lock); -#define lock_init(_usb) mutex_init(&(_usb)->lock) -#define lock_lock(_usb) do {\ - int err = mutex_lock_interruptible(&(_usb)->lock);\ - if (err)\ - return err;\ -} while (0) -#define lock_unlock(_usb) mutex_unlock(&(_usb)->lock) - - u8 *cis; -#define CIS_MAX 512 -}; - -static struct cimax_usb *g_usb; - -MODULE_PARM_DESC(usbdebug, "enable verbose debug messages"); -static int cimax_usb_debug = 1; -module_param_named(usbdebug, cimax_usb_debug, int, 0644); - -MODULE_PARM_DESC(usbpoll_interval, "interval for usb poll"); -static int usb_poll_interval = 100; -module_param_named(usbpoll_interval, usb_poll_interval, int, 0644); - -MODULE_PARM_DESC(usbpoll_mode, "set cimax poll mode, need reset"); -static int cimax_poll_mode = 1; -module_param_named(usbpoll_mode, cimax_poll_mode, int, 0644); - -MODULE_PARM_DESC(usbcam_irq_mode, "set cam irq mode, need reset"); -static int cam_irq_mode; -module_param_named(usbcam_irq_mode, cam_irq_mode, int, 0644); - - -#define CIMAX_REG_READ 0xff -#define CIMAX_REG_READ_OK 0x4c -#define CIMAX_REG_WRITE 0x7f -#define CIMAX_REG_WRITE_OK 0x4d -#define CIMAX_REG_INIT 0x00 -#define CIMAX_REG_INIT_OK 0x4b -#define CIMAX_REG_CMD_ERROR 0x51 - -#define CIMAX_CAM_RESET 0x01 -#define CIMAX_CAM_RESET_OK 0x40 -#define CIMAX_CAM_CIS 0x02 -#define CIMAX_CAM_CIS_OK 0x41 -#define CIMAX_CAM_COR 0x03 -#define CIMAX_CAM_COR_OK 0x42 -#define CIMAX_CAM_NEG 0x04 -#define CIMAX_CAM_NEG_OK 0x43 -#define CIMAX_CAM_WLPDU 0x05 -#define CIMAX_CAM_WLPDU_OK 0x44 -#define CIMAX_CAM_RLPDU 0x06 -#define CIMAX_CAM_RLPDU_OK 0x46 -#define CIMAX_CAM_EVT 0x0d -#define CIMAX_CAM_DET_OK 0x45 -#define CIMAX_CAM_NOCAM 0x49 -#define CIMAX_CAM_ERROR 0x4a -#define CIMAX_CAM_NOEVT 0x55 -#define CIMAX_CAM_DATA_READY 0x4e -#define CIMAX_CAM_WBUSY 0x54 -#define CIMAX_CAM_PENDING 0x56 -#define CIMAX_CAM_REGSTAT 0x0e -#define CIMAX_CAM_REGSTAT_OK 0x57 - - -#define CIMAX_CAM_PKT_CNT_VAL 1 - -#define CIMAX_SLOT_A 0 -#define CIMAX_SLOT_B 1 - -#define CIMAX_CMD_RESP_MASK 0x7f - -#define cimax_to_usb(_c) ((struct cimax_usb *)((_c)->priv)) -#define dev_to_usb(_d) ((struct cimax_usb *)usb_get_drvdata(_d)) - -#define byte_to_u16(_b1, _b2) (((_b1)<<8) | (_b2)) - -#define hdr_cmd_resp(_s) ((_s)->buf[0] & CIMAX_CMD_RESP_MASK) - -#define reg_hdr(_s) ((_s)->buf) -#define reg_addr(_s) byte_to_u16((_s)->buf[1], (_s)->buf[2]) -#define reg_hdr_dat_size(_s) ((_s)->buf[3]) -#define reg_dat(_s) (&((_s)->buf[CIMAX_REG_HDR_SIZE])) - -#define cam_hdr(_s) ((_s)->buf) -#define cam_hdr_slot(_s) (((_s)->buf[0] & 0x80) ? 1 : 0) -#define cam_hdr_pkt_cnt(_s) ((_s)->buf[1]) -#define cam_hdr_dat_size(_s) byte_to_u16((_s)->buf[2], (_s)->buf[3]) -#define cam_dat(_s) (&((_s)->buf[CIMAX_CAM_HDR_SIZE])) - -#define REG_TIMEOUT 500 -#define CAM_TIMEOUT 5000 - -static int aml_cimax_usb_mod_init(void); -static void aml_cimax_usb_mod_exit(void); - -static int cimax_usb_set_loop(struct cimax_usb *usb, int loop); - -static void dump(char *title, u8 *buf, int size) -{ - int i; - pr_info("%s\n", title); - for (i = 0; i < size; i++) { - if (!(i & 0xf)) - pr_info("\n\t"); - pr_info("%02x ", *(buf+i)); - } - pr_info("\n"); -} - -static void perr(char *err, struct cimax_usb *usb) -{ - pr_error("error: %s\n", err); - dump("dump:", usb->buf, 16); -} - -static inline unsigned long get_jiffies(void) -{ - return (unsigned long)(sched_clock()/10000000); -} - -static int cam_usb_cam_detect(struct cimax_usb *usb, int slot, int flag) -{ - usb->cam_inserted[slot] = flag; - pr_inf("detect slot(%d): 0x%x(%s)\n", - slot, usb->cam_inserted[slot], - (!flag) ? "none" : - (flag & IN_LINKED) ? "linked" : - (flag & IN_POWERED) ? "powered" : - (flag & IN_INSERTED) ? "inserted" : - "unknown"); - aml_cimax_slot_state_changed(usb->cimax, slot, - usb->cam_inserted[slot]); - return 0; -} - -static inline void set_usb_cam_ready(struct cimax_usb *usb, int slot) -{ - if (usb->cam_inserted[slot] & IN_POWERED) { - cam_usb_cam_detect(usb, slot, - usb->cam_inserted[slot] | IN_LINKED); - cimax_usb_set_loop(usb, 1);/*set auto-loop*/ - } -} - -static int init_reg_hdr(u8 *hdr, u8 tag, int addr, int size) -{ - hdr[0] = tag; - hdr[1] = (addr>>8) & 0xff; - hdr[2] = addr & 0xff; - hdr[3] = size; - return 0; -} - -static int check_reg_hdr(u8 *hdr, u8 tag, int addr, int size) -{ - return hdr[0] != tag - || hdr[1] != ((addr>>8) & 0xff) - || hdr[2] != (addr & 0xff) - || hdr[3] != size; -} - -static int aml_cimax_usb_read_reg(struct aml_cimax *cimax, int addr, - u8 *buf, int size) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - struct device_s *dev = usb->dev; - u8 out[CIMAX_REG_HDR_SIZE]; - int err = 0; - - init_reg_hdr(out, CIMAX_REG_READ, addr, size); - - lock_lock(usb); - - /*pr_dbg("rd %02x:%02x:%02x:%02x\n", - out[0], out[1], - out[2], out[3]);*/ - err = cimax_usb_ci_write(dev, - out, CIMAX_REG_HDR_SIZE, usb->buf, sizeof(usb->buf)); - if (err) - goto end; - if (check_reg_hdr(reg_hdr(usb), CIMAX_REG_READ_OK, addr, size) != 0) { - pr_dbg("rd %02x:%02x:%02x:%02x\n", - out[0], out[1], - out[2], out[3]); - perr("read reg fail.", usb); - err = -EINVAL; - goto end; - } - memcpy(buf, reg_dat(usb), size); -end: - lock_unlock(usb); - return err; -} - -static int aml_cimax_usb_write_reg(struct aml_cimax *cimax, int addr, - u8 *buf, int size) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - struct device_s *dev = usb->dev; - u8 out[CIMAX_REG_HDR_SIZE + CIMAX_REG_PLD_SIZE]; - int err = 0; - - init_reg_hdr(out, CIMAX_REG_WRITE, addr, size); - memcpy(&out[CIMAX_REG_HDR_SIZE], buf, size); - - lock_lock(usb); - - pr_dbg("wr %02x:%02x:%02x:%02x\n", - out[0], out[1], - out[2], out[3]); - err = cimax_usb_ci_write(dev, - out, CIMAX_REG_HDR_SIZE + size, usb->buf, sizeof(usb->buf)); - if (err) - goto end; - if (check_reg_hdr(reg_hdr(usb), CIMAX_REG_WRITE_OK, addr, 0) != 0) { - perr("write reg fail.", usb); - err = -EINVAL; - goto end; - } -end: - lock_unlock(usb); - return err; -} - -static inline int init_cam_hdr(u8 *hdr, int cmd, int size) -{ - hdr[0] = cmd; - hdr[1] = CIMAX_CAM_PKT_CNT_VAL; - hdr[2] = (size>>8) & 0xff; - hdr[3] = size & 0xff; - return 0; -} - -static inline int cam_err(struct cimax_usb *usb) -{ - if (hdr_cmd_resp(usb) != CIMAX_CAM_ERROR - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(usb) != 2) - return 0; - return byte_to_u16(cam_dat(usb)[0], cam_dat(usb)[1]); -} - -static inline char *cam_err_str(int err) -{ -#define CAMERROR_RESET 0x0101 -#define CAMERROR_CIS_BUF 0x0201 -#define CAMERROR_CIS_SIZE 0x0202 -#define CAMERROR_CAM_NOT_ACT 0x0203 -#define CAMERROR_COR_NOT_READY 0x0301 -#define CAMERROR_COR_VAL_CHK 0x0302 -#define CAMERROR_NEG_NO_RESP 0x0401 -#define CAMERROR_NEG_BAD_SIZE 0x0402 -#define CAMERROR_NEG_NOT_READY 0x0403 -#define CAMERROR_LPDU_NOT_AVAIL 0x0601 - struct { int err; char *str; } cam_err_strings[] = { - {CAMERROR_RESET, "reset error, not ready."}, - {CAMERROR_CIS_BUF, "cis error, buffer not allocated."}, - {CAMERROR_CIS_SIZE, "cis error, bad cis size."}, - {CAMERROR_CAM_NOT_ACT, "cam not activated."}, - {CAMERROR_COR_NOT_READY, "cam not ready during write COR."}, - {CAMERROR_COR_VAL_CHK, "COR value check failed."}, - {CAMERROR_NEG_NO_RESP, "cam not responding when negotiation."}, - {CAMERROR_NEG_BAD_SIZE, "cam buf size length != 2."}, - {CAMERROR_NEG_NOT_READY, "cam not ready during negotiation."}, - {CAMERROR_LPDU_NOT_AVAIL, "lpdu not available."} - }; - int i; - for (i = 0; - i < sizeof(cam_err_strings)/sizeof(cam_err_strings[0]); i++) { - if (cam_err_strings[i].err == err) - return cam_err_strings[i].str; - } - return "err unknown."; -} - -static int cimax_usb_access_cam(struct cimax_usb *usb, int slot, - int cmd, u8 *tx, int tx_size, u8 *rx, int rx_size) -{ - struct device_s *dev = usb->dev; - u8 *out = NULL; - int err = 0; - - out = kzalloc(CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE, GFP_KERNEL); - if (!out) { - pr_err("no mem for access cam.\n"); - return -ENOMEM; - } - - cmd |= slot ? 0x80 : 0; - init_cam_hdr(out, cmd, tx_size); - memcpy(&out[CIMAX_CAM_HDR_SIZE], tx, tx_size); - /*dump("access cam:", out, CIMAX_CAM_HDR_SIZE+size);*/ - - lock_lock(usb); - - err = cimax_usb_ci_write(dev, - out, CIMAX_CAM_HDR_SIZE + tx_size, rx, rx_size); - if (err) - goto end; - if (cam_hdr_slot(usb) != slot) { - pr_error("expect slot(%d), but slot(%d)\n", - slot, cam_hdr_slot(usb)); - err = -EINVAL; - goto end; - } - switch (hdr_cmd_resp(usb)) { - case CIMAX_CAM_NOCAM: - pr_dbg("no cam\n"); - err = -ENODEV; - break; - case CIMAX_CAM_ERROR: - pr_error("cam error\n"); - pr_error("err code: 0x%04x(%s)\n", cam_err(usb), - cam_err_str(cam_err(usb))); - err = -ENODEV; - break; - case CIMAX_CAM_WBUSY: - pr_dbg("cam busy\n"); - err = -EBUSY; - break; - case CIMAX_CAM_PENDING: - pr_dbg("cam pending\n"); - err = -EAGAIN; - break; - } -end: - kfree(out); - lock_unlock(usb); - return err; -} - -static int aml_cimax_usb_read_cis(struct aml_cimax *cimax, int slot, - u8 *buf, int size) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int err = 0; - int len; - - err = cimax_usb_access_cam(usb, slot, CIMAX_CAM_CIS, - NULL, 0, usb->buf, sizeof(usb->buf)); - if (err) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_CIS_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL) { - perr("read cis fail.", usb); - err = -EINVAL; - goto end; - } - len = cam_hdr_dat_size(usb); - if (size < len) { - pr_error("cis size too large, expect<%d, but:%d\n", size, len); - perr("cis fail.", usb); - err = -EINVAL; - goto end; - } - memcpy(buf, cam_dat(usb), len); - - if (!usb->cis) - usb->cis = kzalloc((len < 512) ? 512 : len, GFP_KERNEL); - if (usb->cis) - memcpy(usb->cis, cam_dat(usb), len); - -end: - return err; -} -#define CIMAX_CAM_COR_PLD_SIZE 5 -static int aml_cimax_usb_write_cor(struct aml_cimax *cimax, int slot, - int addr, u8 *buf) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int err = 0; - u8 out[CIMAX_CAM_COR_PLD_SIZE + 8]; - int sz = CIMAX_CAM_COR_PLD_SIZE; - - out[0] = addr>>8 & 0xff; - out[1] = addr & 0xff; - out[2] = buf[0]; - out[3] = 0; - out[4] = 0; - - if (!cam_irq_mode) { - out[5] = 0x40;/*cam poll mode*/ - sz++; - } - - err = cimax_usb_access_cam(usb, slot, CIMAX_CAM_COR, - out, sz, usb->buf, sizeof(usb->buf)); - if (err) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_COR_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(usb) != 0) { - perr("write cor fail.", usb); - err = -EINVAL; - goto end; - } -end: - return err; -} -#define CIMAX_CAM_NEG_PLD_SIZE 2 -static int aml_cimax_usb_negotiate(struct aml_cimax *cimax, int slot, int size) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int ret = 0; - u8 out[CIMAX_CAM_NEG_PLD_SIZE]; - - out[0] = (size>>8) & 0xff; - out[1] = size & 0xff; - - ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_NEG, - out, CIMAX_CAM_NEG_PLD_SIZE, - usb->buf, sizeof(usb->buf)); - if (ret) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_NEG_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(usb) != 2) { - perr("negotiate fail.", usb); - ret = -EINVAL; - goto end; - } - ret = byte_to_u16(cam_dat(usb)[0], cam_dat(usb)[1]); - - set_usb_cam_ready(usb, slot); -end: - return ret; -} - -static int aml_cimax_usb_write_lpdu(struct aml_cimax *cimax, int slot, - u8 *buf, int size) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int ret = 0; - - /*dump("lpdu ->", buf, size);*/ - ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_WLPDU, - buf, size, usb->buf, sizeof(usb->buf)); - if (ret) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_WLPDU_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(usb) != 0) { - perr("write lpdu fail.", usb); - ret = -EINVAL; - goto end; - } - ret = size; -end: - return ret; -} - -static int aml_cimax_usb_read_lpdu(struct aml_cimax *cimax, int slot, - u8 *buf, int size) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int ret = 0; - - ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_RLPDU, - NULL, 0, usb->buf, sizeof(usb->buf)); - if (ret) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_RLPDU_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL) { - perr("read lpdu fail.", usb); - ret = -EINVAL; - goto end; - } - ret = cam_hdr_dat_size(usb); - memcpy(buf, cam_dat(usb), ret); - - /*dump("lpdu <-", buf, ret);*/ - - usb->cam_data_ready[slot] = 0; -end: - return ret; -} - -static int aml_cimax_usb_read_cam_status(struct aml_cimax *cimax, int slot) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int ret = 0; - - if (cam_irq_mode && usb->cam_data_ready[slot]) - return 0x80; - - ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_REGSTAT, - NULL, 0, usb->buf, sizeof(usb->buf)); - if (ret) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_REGSTAT_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(usb) != 1) { - perr("read cam status fail.", usb); - ret = -EINVAL; - goto end; - } - - ret = cam_dat(usb)[0]; -end: - return ret; -} - -static int aml_cimax_usb_slot_reset(struct aml_cimax *cimax, int slot) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - int ret = 0; - - usb->cam_data_ready[slot] = 0; - - ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_RESET, - NULL, 0, usb->buf, sizeof(usb->buf)); - if (ret) - goto end; - if (hdr_cmd_resp(usb) != CIMAX_CAM_RESET_OK - || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL - || cam_hdr_dat_size(usb) != 0) { - perr("slot reset fail.", usb); - ret = -EINVAL; - goto end; - } -end: - return ret; -} - -static int aml_cimax_usb_cam_reset(struct aml_cimax *cimax, int slot) -{ - pr_dbg("Slot(%d): camreset\n", slot); - return 0; -} - -static int aml_cimax_usb_slot_shutdown(struct aml_cimax *cimax, int slot) -{ - pr_dbg("Slot(%d): shutdown\n", slot); - return 0; -} -static int aml_cimax_usb_slot_ts_enable(struct aml_cimax *cimax, int slot) -{ - pr_dbg("Slot(%d): ts control\n", slot); - return 0; -} -static int aml_cimax_usb_slot_status(struct aml_cimax *cimax, int slot) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - if (usb->cam_inserted[slot] & IN_POWERED) { - /*pr_dbg("CA Module present and ready\n");*/ - return DVB_CA_EN50221_POLL_CAM_PRESENT | - DVB_CA_EN50221_POLL_CAM_READY; - } else { - /*pr_error("CA Module not present or not ready\n");*/ - } - return 0; -} - -static int cimax_usb_cam_plugin(struct cimax_usb *usb, int slot, int plugin) -{ - pr_dbg("cam plug: slot(%d) %s\n", - slot, plugin ? "plugged" : "unplugged"); - return aml_cimax_camchanged(usb->cimax, slot, plugin); -} - -static int cimax_usb_set_power(struct cimax_usb *usb, int on) -{ - u8 reg = 0; - int err = 0; - if (!on) { - reg = 0; - err = aml_cimax_usb_read_reg(usb->cimax, MOD_IT_MASK, ®, 1); - if (err) - return err; - reg |= 0x03; - reg &= 0xf3; - - err = aml_cimax_usb_write_reg(usb->cimax, MOD_IT_MASK, ®, 1); - if (err) - return err; - } - reg = on ? 0x3 : 0x0; - return aml_cimax_usb_write_reg(usb->cimax, GPIO0_DATA_OUT, ®, 1); -} - -static int cimax_usb_check_poe(struct cimax_usb *usb, int *on) -{ - u8 reg = 0; - int err = 0; - - *on = 0; - - err = aml_cimax_usb_read_reg(usb->cimax, CFG_1, ®, 1); - if (err) - return err; - if (reg & 0x20) {/*if VCCEN*/ - reg |= 0x08;/*set POE*/ - err = aml_cimax_usb_write_reg(usb->cimax, CFG_1, ®, 1); - if (err) - return err; - err = aml_cimax_usb_read_reg(usb->cimax, CFG_1, ®, 1); - if (err) - return err; - if (reg & 0x08)/*if POE ok*/ - *on = 1; - } - return err; -} - -static void cimax_usb_power_work(struct work_struct *work) -{ - struct cimax_usb *usb = container_of(to_delayed_work(work), - struct cimax_usb, power_work); - int power = 0; - int err = 0; - - usb->power_work_cnt++; - err = cimax_usb_set_power(usb, 1); - if (err) - return; - - err = cimax_usb_check_poe(usb, &power); - if (err) - return; - - if (power) { - return; - } - - schedule_delayed_work(&usb->power_work, usb_poll_interval); -} - -static int cimax_usb_cam_powerctrl(struct cimax_usb *usb, - int slot, int power) -{ - if (slot != 0) - return 0; - -#ifdef DISABLE_POWER_PATCH - if (power) { - cam_usb_cam_detect(usb, slot, - usb->cam_inserted[slot] | IN_POWERED); - cimax_usb_cam_plugin(usb, slot, 1); - } - return 0; -#else - pr_inf("cancel power ctrl previous\n"); - cancel_delayed_work_sync(&usb->power_work); - - if (!power) { - int err = 0; - err = cimax_usb_set_power(usb, 0); - pr_inf("slot[%d] power off\n", slot); - return 0; - } - - INIT_DELAYED_WORK(&usb->power_work, &cimax_usb_power_work); - schedule_delayed_work(&usb->power_work, usb_poll_interval); - pr_inf("slot[%d] power ctrl started\n", slot); -#endif - return 0; -} - -static int cimax_usb_poll(struct cimax_usb *usb) -{ - struct device_s *dev = usb->dev; - int power = 0; - int err = 0; - int slot = 0; - - if (!usb->cam_det) { - for (slot = 0; slot < 2; slot++) { - int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; - u8 reg = 0; - err = aml_cimax_usb_read_reg(usb->cimax, - addr, ®, 1); - if (reg & 1) { - cam_usb_cam_detect(usb, slot, - (reg & 1) ? IN_INSERTED : 0); - msleep(200); - err = cimax_usb_set_power(usb, (reg & 1)); - err = cimax_usb_check_poe(usb, &power); - pr_inf("slot[%d] power on\n", slot); - msleep(200); - if (power) { - cam_usb_cam_detect(usb, slot, - usb->cam_inserted[slot] | IN_POWERED); - cimax_usb_cam_plugin(usb, slot, 1); - usb->cam_det = 1; - } - } - } - return 0; - } - err = cimax_usb_ci_read_evt(dev, CIMAX_SLOT_A, - usb->buf, sizeof(usb->buf)); - if (err) - goto end; - - switch (hdr_cmd_resp(usb)) { - case CIMAX_CAM_DET_OK: { - int slot = cam_hdr_slot(usb); - int insert = cam_dat(usb)[0]; - if ((!!usb->cam_inserted[slot]) != insert) { - cam_usb_cam_detect(usb, slot, - insert ? IN_INSERTED : 0); - cimax_usb_cam_powerctrl(usb, slot, insert); - } - if (!insert) - usb->cam_det = 0; - } break; - case CIMAX_CAM_DATA_READY: { - int slot = cam_hdr_slot(usb); - usb->cam_data_ready[slot] = 1; - } break; - case CIMAX_CAM_NOEVT: - break; - default: - pr_error("unknown resp:%02x\n", hdr_cmd_resp(usb)); - break; - } -end: - return 0; -} - -static void cimax_usb_poll_work(struct work_struct *work) -{ - struct cimax_usb *usb = - container_of(to_delayed_work(work), struct cimax_usb, work); - usb->work_cnt++; - cimax_usb_poll(usb); - if (usb->work_auto_restart) - queue_delayed_work(usb->workq, &usb->work, usb_poll_interval); -} - -#define CTRL_DISABLE -1 -#define CTRL_STOP 0 -#define CTRL_START 1 - -static inline int cimax_usb_poll_ctrl(struct cimax_usb *usb, int ctrl) -{ - if (ctrl == CTRL_START) { - if (usb->workq) - return 0; - usb->work_auto_restart = 1; - usb->workq = create_singlethread_workqueue("cimax_usb"); - INIT_DELAYED_WORK(&usb->work, &cimax_usb_poll_work); - queue_delayed_work(usb->workq, - &usb->work, usb_poll_interval); - pr_inf("poll started\n"); - } else { - if (!usb->workq) - return 0; - usb->work_auto_restart = 0; - cancel_delayed_work_sync(&usb->work); - destroy_workqueue(usb->workq); - usb->workq = NULL; - pr_inf("poll stopped\n"); - } - return 0; -} - -static int cimax_usb_setup_poll(struct cimax_usb *usb, int poll_mode) -{ - if (poll_mode == usb->poll_mode) - return 0; - switch (poll_mode) { - case POLL_MODE: - cimax_usb_poll_ctrl(usb, CTRL_START); - usb->poll_mode = POLL_MODE; - break; - case STOP_MODE: - if (usb->poll_mode == POLL_MODE) - cimax_usb_poll_ctrl(usb, CTRL_DISABLE); - usb->poll_mode = STOP_MODE; - break; - default: - break; - } - return 0; -} - -static int cimax_usb_hw_reset(struct cimax_usb *usb, int reset_val) -{ - /*trigger reset io*/ - if (usb->rst_io) { - gpio_direction_output(usb->rst_io, reset_val ? 1 : 0); - msleep(50); - gpio_direction_output(usb->rst_io, reset_val ? 0 : 1); - } - return 0; -} - -static int cimax_usb_set_loop(struct cimax_usb *usb, int loop) -{ - int a = usb->cam_inserted[0]; - int b = usb->cam_inserted[1]; - u8 cm[2]; - - pr_inf("set loop: %d\n", loop); - - cm[0] = loop ? (b ? 0x85 : 0x80) : 0x81;/*CH*/ - cm[1] = loop ? (a ? 0x51 : 0x11) : 0x00;/*MOD*/ - - return aml_cimax_usb_write_reg(usb->cimax, ROUTER_CAM_CH, cm, 2); -} - -int cimax_usb_dev_add(struct device_s *dev, int id) -{ - pr_inf("dev add\n"); - if (!g_usb) - return 0; - - id = id; - - cimax_usb_device_open(dev); - cimax_usb_select_interface(dev, 3); - - lock_lock(g_usb); - g_usb->dev = dev; - lock_unlock(g_usb); - - if (0) - { - /* - the cimax's fw do not report cam status - when board power on with cam plugged, - have to check manually here. - */ - int slot = 0; - int err = 0; - for (slot = 0; slot < 2; slot++) { - int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; - u8 reg = 0; - err = aml_cimax_usb_read_reg(g_usb->cimax, - addr, ®, 1); - cam_usb_cam_detect(g_usb, slot, - (reg & 1) ? IN_INSERTED : 0); - cimax_usb_cam_powerctrl(g_usb, slot, (reg & 1)); - } - } - cimax_usb_set_power(g_usb, 0); - cimax_usb_setup_poll(g_usb, cimax_poll_mode ? POLL_MODE : INT_MODE); - return 0; -} -EXPORT_SYMBOL(cimax_usb_dev_add); - -int cimax_usb_dev_remove(struct device_s *dev, int id) -{ - pr_dbg("dev remove\n"); - if (!g_usb) - return 0; - id = id; - pr_dbg("setup poll -> stop\n"); - cimax_usb_setup_poll(g_usb, STOP_MODE); - pr_dbg("setup poll end\n"); - lock_lock(g_usb); - g_usb->dev = NULL; - lock_unlock(g_usb); - return 0; -} -EXPORT_SYMBOL(cimax_usb_dev_remove); - -static int cimax_usb_get_config_from_dts(struct cimax_usb *usb) -{ - struct device_node *child = NULL; - struct platform_device *pdev = usb->pdev; - struct device_node *np = pdev->dev.of_node; - pr_dbg("fetch cimax usb in dts\n"); - - child = of_get_child_by_name(np, "cimax"); - if (child == NULL) { - pr_error("cimax not found in dts\n"); - return -1; - } - child = of_get_child_by_name(child, "usb"); - if (!child) { - pr_error("usb not found in cimax"); - return -1; - } -/* -dvbci { - compatible = "amlogic, dvbci"; - dev_name = "dvbci"; - io_type = <2>;//0:iobus,1:usb,2:cimax - cimax { - io_type = <1> //0:spi 1:usb - usb { - rst_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; - }; - }; - -}; -*/ - { - int ret = 0; - int gpio = -1; - gpio = of_get_named_gpio_flags(child, "rst-gpios", 0, NULL); - if (gpio != -1) { - ret = gpio_request(gpio, "cimax"); - if (ret < 0) { - pr_error("rst-gpios request fail.\n"); - return ret; - } - usb->rst_io = gpio; - cimax_usb_hw_reset(usb, 1); - pr_dbg("rst: %d\n", usb->rst_io); - } else { - pr_error("rst io got fail, %d\n", gpio); - } - } - return 0; -} - -int aml_cimax_usb_init(struct platform_device *pdev, struct aml_cimax *cimax) -{ - struct cimax_usb *cimax_usb; - - cimax_usb = kzalloc(sizeof(struct cimax_usb), GFP_KERNEL); - if (!cimax_usb) - return -ENOMEM; - - cimax_usb->pdev = pdev; - cimax_usb->cimax = cimax; - cimax_usb_get_config_from_dts(cimax_usb); - - /*init usb_lock*/ - lock_init(cimax_usb); - - /*init cimax used api.*/ -#define WI(_f)\ - cimax->ops._f = aml_cimax_usb_##_f - WI(read_cis); - WI(write_cor); - WI(negotiate); - WI(read_lpdu); - WI(write_lpdu); - WI(read_cam_status); - WI(cam_reset); - WI(slot_reset); - WI(slot_shutdown); - WI(slot_ts_enable); - WI(slot_status); - WI(read_reg); - WI(write_reg); - - cimax->priv = cimax_usb; - - g_usb = cimax_usb; - - aml_cimax_usb_mod_init(); - - cimax_usb_set_cb(cimax_usb_dev_add, cimax_usb_dev_remove); - - return 0; -} -EXPORT_SYMBOL(aml_cimax_usb_init); - -int aml_cimax_usb_exit(struct aml_cimax *cimax) -{ - struct cimax_usb *usb = cimax_to_usb(cimax); - - if (!usb) - return -ENODEV; - - aml_cimax_usb_mod_exit(); - - cimax_usb_device_close(usb->dev); - cimax_usb_setup_poll(usb, STOP_MODE); - - if (usb->rst_io) - gpio_free(usb->rst_io); - - kfree(usb->cis); - - kfree(usb); - cimax->priv = NULL; - - g_usb = NULL; - return 0; -} -EXPORT_SYMBOL(aml_cimax_usb_exit); - -static int cimax_usb_reset(struct cimax_usb *usb, int reset_val) -{ - pr_dbg("reset usb:%p, rst:%d\n", usb, usb ? usb->rst_io : -1); - if (!usb) - return -ENODEV; - - pr_inf("cimax usb reset\n"); - - /*notify unplugged*/ - aml_cimax_camchanged(usb->cimax, 0, 0); - aml_cimax_camchanged(usb->cimax, 1, 0); - - if (usb->dev) - cimax_usb_device_close(usb->dev); - - cimax_usb_setup_poll(usb, STOP_MODE); - - usb->cam_inserted[0] = usb->cam_inserted[1] = 0; - usb->cam_data_ready[0] = usb->cam_data_ready[1] = 0; - - cimax_usb_hw_reset(usb, reset_val); - - pr_inf("cimax usb reset end\n"); - return 0; -} - -static ssize_t reset_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret; - ret = sprintf(buf, "echo 1 > %s\n", attr->attr.name); - return ret; -} - -static ssize_t reset_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int ret; - int val = 0; - if (!g_usb) - return size; - ret = sscanf(buf, "%i", &val); - if (ret == 1) - ret = cimax_usb_reset(g_usb, val); - return size; -} - -static ssize_t debug_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - if (!g_usb) - return ret; - - ret = sprintf(buf, "poll mode: %d\n", g_usb->poll_mode); - ret += sprintf(buf+ret, "status slot[0]=[%d] slot[1]=[%d]\n", - g_usb->cam_inserted[0], g_usb->cam_inserted[1]); - { - int power = 0; - int err = cimax_usb_check_poe(g_usb, &power); - ret += sprintf(buf+ret, "power slot[0]=[%d] slot[1]=[%d]\n", - err ? -1 : power, 0); - } - ret += sprintf(buf+ret, "data slot[0]=[%d] slot[1]=[%d]\n", - g_usb->cam_data_ready[0], g_usb->cam_data_ready[1]); - ret += sprintf(buf+ret, "work cnt:%d\n", g_usb->work_cnt); - ret += sprintf(buf+ret, "pwr work cnt:%d\n", g_usb->power_work_cnt); - return ret; -} - -static int reg_addr; -static ssize_t addr_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - ret = sprintf(buf, "addr = 0x%04x\n", reg_addr); - return ret; -} - -static ssize_t addr_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - if (!g_usb) - return size; - if (sscanf(buf, "%i", ®_addr) != 1) - return size; - return size; -} - -static ssize_t reg_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - u8 reg_val = 0; - struct aml_cimax *cimax = NULL; - - if (!g_usb) - return ret; - - cimax = g_usb->cimax; - ret = aml_cimax_usb_read_reg(cimax, reg_addr, ®_val, 1); - if (ret) - ret = sprintf(buf, "read fail, err=%d\n", ret); - else - ret = sprintf(buf, "reg[0x%04x] = 0x%02x\n", reg_addr, reg_val); - return ret; -} - -static ssize_t reg_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int ret = 0; - struct aml_cimax *cimax = NULL; - int val = 0; - u8 reg_val = 0; - - if (!g_usb) - return size; - - if (sscanf(buf, "%i", &val) != 1) - return size; - reg_val = val; - cimax = g_usb->cimax; - ret = aml_cimax_usb_write_reg(cimax, reg_addr, ®_val, 1); - if (ret) - return ret; - return size; -} - -static int cis_mode; /*0:hex 1:binary*/ -static ssize_t cis_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - - if (!g_usb || !g_usb->cis) - return ret; - - if (cis_mode == 0) { - int i; - for (i = 0; i < CIS_MAX; i++) { - if (i && !(i & 0xf)) - ret += sprintf(buf+ret, "\n"); - ret += sprintf(buf+ret, "%02X ", g_usb->cis[i]); - } - ret += sprintf(buf+ret, "\n"); - return ret; - } else { - memcpy(buf, g_usb->cis, CIS_MAX); - return CIS_MAX; - } - return ret; -} - -static ssize_t cis_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - if (size >= 3 - && !memcmp(buf, "bin", 3)) - cis_mode = 1; - else - cis_mode = 0; - return size; -} - -static ssize_t ts_rate_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - u8 lsb = 0, msb = 0, plen = 0; - struct aml_cimax *cimax = NULL; - int err = 0; - - if (!g_usb) - return ret; - - cimax = g_usb->cimax; - err = aml_cimax_usb_read_reg(cimax, PCK_LENGTH, &plen, 1); - err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH0_LSB, &lsb, 1); - err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH0_MSB, &msb, 1); - if (err) - ret += sprintf(buf+ret, "read fail, err=%d\n", err); - else if (!byte_to_u16(msb, lsb)) - ret += sprintf(buf+ret, "rate[0] = 0 Kbps\n"); - else - ret += sprintf(buf+ret, "rate[0] = %d Kbps\n", - 540*plen*8/byte_to_u16(msb, lsb)); - if (err) - return ret; - - err = aml_cimax_usb_read_reg(cimax, BITRATE_CH1_LSB, &lsb, 1); - err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH1_MSB, &msb, 1); - if (err) - ret += sprintf(buf+ret, "read fail, err=%d\n", err); - else if (!byte_to_u16(msb, lsb)) - ret += sprintf(buf+ret, "rate[1] = 0 Kbps\n"); - else - ret += sprintf(buf+ret, "rate[1] = %d Kbps\n", - 540*plen*8/byte_to_u16(msb, lsb)); - return ret; -} - -static ssize_t loop_show(struct class *class, - struct class_attribute *attr, char *buf) -{ - int ret = 0; - u8 ch = 0, mod = 0; - struct aml_cimax *cimax = NULL; - int err = 0; - - if (!g_usb) - return ret; - - cimax = g_usb->cimax; - err = aml_cimax_usb_read_reg(cimax, ROUTER_CAM_CH, &ch, 1); - err |= aml_cimax_usb_read_reg(cimax, ROUTER_CAM_MOD, &mod, 1); - if (err) { - ret = sprintf(buf, "read fail, err=%d\n", err); - return ret; - } - ret += sprintf(buf + ret, "OUT-0 <= "); - switch (ch & 0x0f) { - case 0x0: - ret += sprintf(buf + ret, "CAM-A"); break; - case 0x1: - ret += sprintf(buf + ret, "CH0-IN"); break; - case 0x2: - ret += sprintf(buf + ret, "CH1-IN"); break; - case 0x3: - ret += sprintf(buf + ret, "REMAPPER"); break; - case 0x4: - ret += sprintf(buf + ret, "PREHEADER"); break; - case 0x5: - ret += sprintf(buf + ret, "CAM-B"); break; - case 0x6: - ret += sprintf(buf + ret, "GAPREMOVER-0"); break; - case 0x7: - ret += sprintf(buf + ret, "GAPREMOVER-1"); break; - case 0x8: - ret += sprintf(buf + ret, "NONE"); break; - default: - ret += sprintf(buf + ret, "UNKNOWN"); break; - } - ret += sprintf(buf + ret, "\nCAM-A <= "); - switch (mod & 0x07) { - case 0x1: - ret += sprintf(buf + ret, "CH0-IN"); break; - case 0x2: - ret += sprintf(buf + ret, "CH1-IN"); break; - case 0x3: - ret += sprintf(buf + ret, "REMAPPER"); break; - case 0x4: - ret += sprintf(buf + ret, "PREHEADER"); break; - case 0x5: - ret += sprintf(buf + ret, "CAM-B"); break; - case 0x6: - ret += sprintf(buf + ret, "GAPREMOVER-0"); break; - case 0x7: - ret += sprintf(buf + ret, "GAPREMOVER-1"); break; - default: - ret += sprintf(buf + ret, "NONE"); break; - } - ret += sprintf(buf + ret, "\n"); - - return ret; -} - -static ssize_t loop_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int loop = 0; - - if (!g_usb) - return size; - - if (sscanf(buf, "%i", &loop) == 1) - cimax_usb_set_loop(g_usb, loop); - return size; -} - -static ssize_t slot_reset_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int err = 0; - int slot = 0; - struct aml_cimax *cimax = NULL; - - if (!g_usb) - return size; - - if (sscanf(buf, "%i", &slot) == 1) { - if (slot == 0 || slot == 1) { - pr_dbg("reset slot %d\n", slot); - cimax = g_usb->cimax; - err = aml_cimax_usb_slot_reset(cimax, slot); - } - } - return size; -} - -static ssize_t detect_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) -{ - int err = 0; - int slot = 0; - struct aml_cimax *cimax = NULL; - - if (!g_usb) - return size; - - if (sscanf(buf, "%i", &slot) == 1) { - if (slot == 0 || slot == 1) { - int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; - u8 reg = 0; - cimax = g_usb->cimax; - err = aml_cimax_usb_read_reg(cimax, addr, ®, 1); - cam_usb_cam_detect(g_usb, slot, - (reg & 1) ? IN_INSERTED : 0); - cimax_usb_cam_powerctrl(g_usb, slot, (reg & 1)); - } - } - return size; -} - - -static struct class_attribute cimax_usb_class_attrs[] = { - __ATTR_RW(reset), - __ATTR_RO(debug), - __ATTR_RW(addr), - __ATTR_RW(reg), - __ATTR_RW(cis), - __ATTR_RO(ts_rate), - __ATTR_RW(loop), - __ATTR_WO(slot_reset), - __ATTR_WO(detect), - __ATTR_NULL -}; - -static struct class cimax_usb_class = { - .name = "cimax_usb", - .class_attrs = cimax_usb_class_attrs, -}; - -static int aml_cimax_usb_mod_init(void) -{ - int ret; - pr_dbg("Amlogic CIMAX USB Init\n"); - ret = class_register(&cimax_usb_class); - return 0; -} - -static void aml_cimax_usb_mod_exit(void) -{ - pr_dbg("Amlogic CIMAX USB Exit\n"); - class_unregister(&cimax_usb_class); -} - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h deleted file mode 100644 index 471d2da5af56..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h +++ /dev/null @@ -1,20 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#ifndef _AML_CIMAX_USB_H_ -#define _AML_CIMAX_USB_H_ - -#include -#include "aml_cimax.h" - -int aml_cimax_usb_init(struct platform_device *pdev, struct aml_cimax *ci); -int aml_cimax_usb_exit(struct aml_cimax *ci); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h deleted file mode 100644 index aec694c66a3c..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h +++ /dev/null @@ -1,22 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Amlogic, Inc. All rights reserved. - * - * This source code is subject to the terms and conditions defined in the - * file 'LICENSE' which is part of this source code package. - * - * Description: - * -***************************************************************************/ - -#ifndef _CIMAX_USB_DEV_H_ -#define _CIMAX_USB_DEV_H_ - -#if 0 -__attribute__ ((weak)) -int cimax_usb_dev_add(struct device_s *device, int id); -__attribute__ ((weak)) -int cimax_usb_dev_remove(struct device_s *device, int id); -#endif - -#endif - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c deleted file mode 100644 index e8fb0eec9064..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c +++ /dev/null @@ -1,1910 +0,0 @@ -/* - * dvb_ca.c: generic DVB functions for EN50221 CAM CIMAX interfaces - * - * Parts of this file were based on sources as follows: - * - * based on code: - * - * Copyright (C) 1999-2002 Ralph Metzler - * & Marcus Metzler for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dvb_ca_en50221_cimax.h" -#include "dvb_ringbuffer.h" - -static int dvb_ca_en50221_debug = 1; - -module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); -MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); - -#define HOST_LINK_BUF_SIZE 0x1000 - -static int dvb_ca_en50221_link_size = HOST_LINK_BUF_SIZE; -module_param_named(link_size, dvb_ca_en50221_link_size, int, 0644); -MODULE_PARM_DESC(link_size, "debug only, no more than 0x1000"); - - -#define dprintk(args...)\ - do {\ - if (dvb_ca_en50221_debug)\ - printk(args);\ - } while (0) -#define pr_error(fmt, args...) printk("CA EN50211: " fmt, ## args) - -#define INIT_TIMEOUT_SECS 40 - - -#define RX_BUFFER_SIZE 65535 - -#define MAX_RX_PACKETS_PER_ITERATION 10 - -#define CTRLIF_DATA 0 -#define CTRLIF_COMMAND 1 -#define CTRLIF_STATUS 1 -#define CTRLIF_SIZE_LOW 2 -#define CTRLIF_SIZE_HIGH 3 - -#define CMDREG_HC 1 /* Host control */ -#define CMDREG_SW 2 /* Size write */ -#define CMDREG_SR 4 /* Size read */ -#define CMDREG_RS 8 /* Reset interface */ -#define CMDREG_FRIE 0x40 /* Enable FR interrupt */ -#define CMDREG_DAIE 0x80 /* Enable DA interrupt */ -#define IRQEN (CMDREG_DAIE) - -#define STATUSREG_RE 1 /* read error */ -#define STATUSREG_WE 2 /* write error */ -#define STATUSREG_FR 0x40 /* module free */ -#define STATUSREG_DA 0x80 /* data available */ -#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE)/* general transfer error */ - - -#define DVB_CA_SLOTSTATE_NONE 0 -#define DVB_CA_SLOTSTATE_UNINITIALISED 1 -#define DVB_CA_SLOTSTATE_RUNNING 2 -#define DVB_CA_SLOTSTATE_INVALID 3 -#define DVB_CA_SLOTSTATE_WAITREADY 4 -#define DVB_CA_SLOTSTATE_VALIDATE 5 -#define DVB_CA_SLOTSTATE_WAITFR 6 -#define DVB_CA_SLOTSTATE_LINKINIT 7 -#define DVB_CA_SLOTSTATE_WAITLINKINIT 8 - -#define MAX_CIS_SIZE 512 - -/* Information on a CA slot */ -struct dvb_ca_slot { - - /* current state of the CAM */ - int slot_state; - - /* mutex used for serializing access to one CI slot */ - struct mutex slot_lock; - - /* Number of CAMCHANGES that have occurred since last processing */ - atomic_t camchange_count; - - /* Type of last CAMCHANGE */ - int camchange_type; - - /* base address of CAM config */ - u32 config_base; - - /* value to write into Config Control register */ - u8 config_option; - - /* if 1, the CAM supports DA IRQs */ - u8 da_irq_supported:1; - - /* size of the buffer to use when talking to the CAM */ - int link_buf_size; - - /* buffer for incoming packets */ - struct dvb_ringbuffer rx_buffer; - - /* timer used during various states of the slot */ - unsigned long timeout; -}; - -/* Private CA-interface information */ -struct dvb_ca_private { - - /* pointer back to the public data structure */ - struct dvb_ca_en50221_cimax *pub; - - /* the DVB device */ - struct dvb_device *dvbdev; - - /* Flags describing the interface (DVB_CA_FLAG_*) */ - u32 flags; - - /* number of slots supported by this CA interface */ - unsigned int slot_count; - - /* information on each slot */ - struct dvb_ca_slot *slot_info; - - /* wait queues for read() and write() operations */ - wait_queue_head_t wait_queue; - - /* PID of the monitoring thread */ - struct task_struct *thread; - - /* Flag indicating if the CA device is open */ - unsigned int open:1; - - /* Flag indicating the thread should wake up now */ - unsigned int wakeup:1; - - /* Delay the main thread should use */ - unsigned long delay; - - /* Slot to start looking for data - to read from in the next user-space read operation */ - int next_read_slot; - - /* mutex serializing ioctls */ - struct mutex ioctl_mutex; - - /*two bufs for read/write*/ - u8 *rbuf; - u8 *wbuf; -}; - -static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); -static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, - int slot, u8 *ebuf, int ecount); -static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, - int slot, u8 *ebuf, int ecount); - - -/** - * Safely find needle in haystack. - * - * @param haystack Buffer to look in. - * @param hlen Number of bytes in haystack. - * @param needle Buffer to find. - * @param nlen Number of bytes in needle. - * @return Pointer into haystack needle was found at, or NULL if not found. - */ -static char *findstr(char *haystack, int hlen, char *needle, int nlen) -{ - int i; - - if (hlen < nlen) - return NULL; - - for (i = 0; i <= hlen - nlen; i++) { - if (!strncmp(haystack + i, needle, nlen)) - return haystack + i; - } - - return NULL; -} - - - -/* ************************************************************************** */ -/* EN50221 physical interface functions */ - - -/** - * Check CAM status. - */ -static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) -{ - int slot_status; - int cam_present; - int cam_changed; - - /* IRQ mode */ - if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) - return atomic_read(&ca->slot_info[slot].camchange_count) != 0; - - /* poll mode */ - slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); - - cam_present = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0; - cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0; - if (!cam_changed) { - int cam_present_old = - (ca->slot_info[slot].slot_state - != DVB_CA_SLOTSTATE_NONE); - cam_changed = (cam_present != cam_present_old); - } - - if (cam_changed) { - if (!cam_present) { - ca->slot_info[slot].camchange_type = - DVB_CA_EN50221_CAMCHANGE_REMOVED; - } else { - ca->slot_info[slot].camchange_type = - DVB_CA_EN50221_CAMCHANGE_INSERTED; - } - atomic_set(&ca->slot_info[slot].camchange_count, 1); - } else { - if ((ca->slot_info[slot].slot_state - == DVB_CA_SLOTSTATE_WAITREADY) && - (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) { - /* move to validate state if reset is completed */ - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_VALIDATE; - } - } - return cam_changed; -} - - -/** - * Initialise the link layer connection to a CAM. - * - * @param ca CA instance. - * @param slot Slot id. - * - * @return 0 on success, nonzero on failure. - */ -static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) -{ - int ret; - dprintk("%s\n", __func__); - - /* we'll be determining these during this function */ - ca->slot_info[slot].da_irq_supported = 0; - - /* set the host link buffer size temporarily. - it will be overwritten with the real negotiated size later. */ - ca->slot_info[slot].link_buf_size = dvb_ca_en50221_link_size; - dprintk("negotiate: host(%i)\n", ca->slot_info[slot].link_buf_size); - - ret = ca->pub->negotiate(ca->pub, - slot, ca->slot_info[slot].link_buf_size); - if (ret <= 0) - return ret; - - ca->slot_info[slot].link_buf_size = ret; - dprintk("Chosen link buffer size of %i\n", ret); - - /* success */ - return 0; -} - -/** - * Read a tuple from attribute memory. - * - * @param ca CA instance. - * @param slot Slot id. - * @param cis CIS data - * @param address Address to read from. Updated. - * @param tupleType Tuple id byte. Updated. - * @param tupleLength Tuple length. Updated. - * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. - * - * @return 0 on success, nonzero on error. - */ -static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, - int slot, u8 *cis, - int *address, int *tupleType, int *tupleLength, u8 *tuple) -{ - int i; - int _tupleType; - int _tupleLength; - int _address = *address; - - /* grab the next tuple length and type */ - _tupleType = cis[_address]; - if (_tupleType < 0) - return _tupleType; - if (_tupleType == 0xff) { - dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); - *address += 1; - *tupleType = _tupleType; - *tupleLength = 0; - return 0; - } - _tupleLength = cis[_address + 1]; - if (_tupleLength < 0) - return _tupleLength; - _address += 2; - - dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); - - /* read in the whole tuple */ - for (i = 0; i < _tupleLength; i++) { - tuple[i] = cis[_address + (i)]; - dprintk(" 0x%02x: 0x%02x %c\n", - i, tuple[i] & 0xff, - ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); - } - _address += (_tupleLength); - - /* success */ - *tupleType = _tupleType; - *tupleLength = _tupleLength; - *address = _address; - return 0; -} - - -/** - * Parse attribute memory of a CAM module, extracting Config register, - * and checking it is a DVB CAM module. - * - * @param ca CA instance. - * @param slot Slot id. - * - * @return 0 on success, <0 on failure. - */ -static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) -{ - int address = 0; - int tupleLength; - int tupleType; - u8 tuple[257]; - char *dvb_str; - int rasz; - int status; - int got_cftableentry = 0; - int end_chain = 0; - int i; - u16 manfid = 0; - u16 devid = 0; - u8 cis[MAX_CIS_SIZE]; - - status = ca->pub->read_cis(ca->pub, slot, cis, MAX_CIS_SIZE); - if (status != 0) - return -EINVAL; - - /* CISTPL_DEVICE_0A */ - status = - dvb_ca_en50221_read_tuple(ca, slot, cis, &address, - &tupleType, &tupleLength, tuple); - if (status < 0) { - pr_error("read status error\r\n"); - return status; - } - if (tupleType != 0x1D) { - pr_error("read tupleType error [0x%x]\r\n", tupleType); - return -EINVAL; - } - - - - /* CISTPL_DEVICE_0C */ - status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, - &tupleType, &tupleLength, tuple); - - if (status < 0) { - pr_error("read read cis error\r\n"); - return -EINVAL; - } - if (tupleType != 0x1C) { - pr_error("read read cis type error\r\n"); - return -EINVAL; - } - - - - /* CISTPL_VERS_1 */ - status = - dvb_ca_en50221_read_tuple(ca, slot, cis, - &address, &tupleType, &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis version error\r\n"); - return status; - } - if (tupleType != 0x15) { - pr_error("read read cis version type error\r\n"); - return -EINVAL; - } - - - - /* CISTPL_MANFID */ - status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis manfid error\r\n"); - return status; - } - if (tupleType != 0x20) { - pr_error("read read cis manfid type error\r\n"); - return -EINVAL; - } - if (tupleLength != 4) { - pr_error("read read cis manfid len error\r\n"); - return -EINVAL; - } - manfid = (tuple[1] << 8) | tuple[0]; - devid = (tuple[3] << 8) | tuple[2]; - - - - /* CISTPL_CONFIG */ - status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("read read cis config error\r\n"); - return status; - } - if (tupleType != 0x1A) { - pr_error("read read cis config type error\r\n"); - return -EINVAL; - } - if (tupleLength < 3) { - pr_error("read read cis config len error\r\n"); - return -EINVAL; - } - - /* extract the configbase */ - rasz = tuple[0] & 3; - if (tupleLength < (3 + rasz + 14)) { - pr_error("read extract the configbase error\r\n"); - return -EINVAL; - } - ca->slot_info[slot].config_base = 0; - for (i = 0; i < rasz + 1; i++) - ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i)); - - /* check it contains the correct DVB string */ - dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8); - if (dvb_str == NULL) { - pr_error("find dvb str DVB_CI_V error\r\n"); - return -EINVAL; - } - if (tupleLength < ((dvb_str - (char *) tuple) + 12)) { - pr_error("find dvb str DVB_CI_V len error\r\n"); - return -EINVAL; - } - - /* is it a version we support? */ - if (strncmp(dvb_str + 8, "1.00", 4)) { - pr_info("dvb_ca adapter %d: ", ca->dvbdev->adapter->num); - pr_info("Unsupported DVB CAM module version %c%c%c%c\n", - dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); - return -EINVAL; - } - - /* process the CFTABLE_ENTRY tuples, and any after those */ - while ((!end_chain) && (address < 0x1000)) { - status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, - &tupleType, &tupleLength, tuple); - if (status < 0) { - pr_error("process tuples error\r\n"); - return status; - } - - switch (tupleType) { - case 0x1B: /* CISTPL_CFTABLE_ENTRY */ - if (tupleLength < (2 + 11 + 17)) - break; - - /* if we've already parsed one, just use it */ - if (got_cftableentry) - break; - - /* get the config option */ - ca->slot_info[slot].config_option = tuple[0] & 0x3f; - - /* OK, check it contains the correct strings */ - if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) - == NULL) - || (findstr((char *)tuple, - tupleLength, "DVB_CI_MODULE", 13) - == NULL)) { - break; - } - got_cftableentry = 1; - break; - - case 0x14: /* CISTPL_NO_LINK */ - break; - - case 0xFF: /* CISTPL_END */ - end_chain = 1; - break; - - default: /* Unknown tuple type - -just skip this tuple and move to the next one */ - dprintk("dvb_ca: Skipping unknown tuple type:0x%x", - tupleType); - dprintk(" length:0x%x\n", tupleLength); - break; - } - } - - if ((address > 0x1000) || (!got_cftableentry)) { - pr_error("got_cftableentry :%d\r\n", got_cftableentry); - return -EINVAL; - } - - dprintk("Valid DVB CAM detected MANID:%x DEVID:%x", manfid, devid); - dprintk(" CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", - ca->slot_info[slot].config_base, - ca->slot_info[slot].config_option); - - /* success! */ - return 0; -} - - -/** - * Set CAM's configoption correctly. - * - * @param ca CA instance. - * @param slot Slot containing the CAM. - */ -static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) -{ - int configoption; - - dprintk("%s\n", __func__); - - /* set the config option */ - ca->pub->write_cor(ca->pub, slot, - ca->slot_info[slot].config_base, - &ca->slot_info[slot].config_option); - - configoption = ca->slot_info[slot].config_option; - dprintk("Set configoption 0x%x, base 0x%x\n", - ca->slot_info[slot].config_option, - ca->slot_info[slot].config_base); - - /* fine! */ - return 0; - -} - - -/** - * This function talks to an EN50221 CAM control interface. It reads a buffer of - * data from the CAM. The data can either be stored in a supplied buffer, or - * automatically be added to the slot's rx_buffer. - * - * @param ca CA instance. - * @param slot Slot to read from. - * @param ebuf If non-NULL, the data will be written to this buffer. If NULL, - * the data will be added into the buffering system as a normal fragment. - * @param ecount Size of ebuf. Ignored if ebuf is NULL. - * - * @return Number of bytes read, or < 0 on error - */ -static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, - int slot, u8 *ebuf, int ecount) -{ - int bytes_read; - int status; - u8 *buf = ca->rbuf; - - /* dprintk("%s\n", __func__); */ - - /* check if we have space for a link buf in the rx_buffer */ - if (ebuf == NULL) { - int buf_free; - - if (ca->slot_info[slot].rx_buffer.data == NULL) { - status = -EIO; - goto exit; - } - buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); - - if (buf_free < (ca->slot_info[slot].link_buf_size - + DVB_RINGBUFFER_PKTHDRSIZE)) { - status = -EAGAIN; - goto exit; - } - } - - /* check if there is data available */ - status = ca->pub->read_cam_status(ca->pub, slot); - if (status < 0) - goto exit; - if (!(status & STATUSREG_DA)) { - /* no data */ - status = 0; - goto exit; - } - - /* read the amount of data */ - status = ca->pub->read_lpdu(ca->pub, - slot, buf, dvb_ca_en50221_link_size); - if (status < 0) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exit; - } - - bytes_read = status; - - /* check it will fit */ - if (ebuf == NULL) { - if (bytes_read > ca->slot_info[slot].link_buf_size) { - pr_error("dvb_ca adapter %d:", - ca->dvbdev->adapter->num); - pr_error(" CAM tried to send a buffer larger "); - pr_error("than the link buffer size(%i > %i)!\n", - bytes_read, ca->slot_info[slot].link_buf_size); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exit; - } - if (bytes_read < 2) { - pr_error("dvb_ca adapter %d: ", - ca->dvbdev->adapter->num); - pr_error("CAM sent a buffer"); - pr_error("that was less than 2B!\n"); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exit; - } - } else { - if (bytes_read > ecount) { - pr_error("dvb_ca adapter %d:", - ca->dvbdev->adapter->num); - pr_error(" CAM tried to send a buffer larger"); - pr_error(" than the ecount size!\n"); - status = -EIO; - goto exit; - } - } - - /* OK, add it to the receive buffer, - or copy into external buffer if supplied */ - if (ebuf == NULL) { - if (ca->slot_info[slot].rx_buffer.data == NULL) { - status = -EIO; - goto exit; - } - dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, - buf, bytes_read); - } else { - memcpy(ebuf, buf, bytes_read); - } - - /* wake up readers when a last_fragment is received */ - if ((buf[1] & 0x80) == 0x00) - wake_up_interruptible(&ca->wait_queue); - status = bytes_read; - -exit: - return status; -} - - -/** - * This function talks to an EN50221 CAM control interface. - * It writes a buffer of data - * to a CAM. - * - * @param ca CA instance. - * @param slot Slot to write to. - * @param ebuf The data in this buffer - * is treated as a complete link-level packet to be written. - * @param count Size of ebuf. - * - * @return Number of bytes written, or < 0 on error. - */ -static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, - int slot, u8 *buf, int bytes_write) -{ - int status; - - /* dprintk("%s\n", __func__); */ - - /* sanity check */ - if (bytes_write > ca->slot_info[slot].link_buf_size) - return -EINVAL; - - /* it is possible we are dealing with a single buffer implementation, - thus if there is data available for read or if there is even a read - already in progress, we do nothing but awake the kernel thread to - process the data if necessary. */ - status = ca->pub->read_cam_status(ca->pub, slot); - if (status < 0) - return status; - if (status & (STATUSREG_DA | STATUSREG_RE)) { - if (status & STATUSREG_DA) - dvb_ca_en50221_thread_wakeup(ca); - status = -EAGAIN; - return status; - } - - if (!(status & STATUSREG_FR)) { - status = -EAGAIN; - return status; - } - - status = ca->pub->write_lpdu(ca->pub, slot, buf, bytes_write); - if (status < 0) { - if (status == -EBUSY) { - status = -EAGAIN; - return status; - } else { - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - return status; - } - } - - status = bytes_write; - - return status; -} -EXPORT_SYMBOL(dvb_ca_en50221_cimax_camchange_irq); - - - -/* ************************************************************************** */ -/* EN50221 higher level functions */ - - -/** - * A CAM has been removed => shut it down. - * - * @param ca CA instance. - * @param slot Slot to shut down. - */ -static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) -{ - dprintk("%s\n", __func__); - - ca->pub->slot_shutdown(ca->pub, slot); - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; - - /* need to wake up all processes to check if they're now - trying to write to a defunct CAM */ - wake_up_interruptible(&ca->wait_queue); - - dprintk("Slot %i shutdown\n", slot); - - /* success */ - return 0; -} -EXPORT_SYMBOL(dvb_ca_en50221_cimax_camready_irq); - - -/** - * A CAMCHANGE IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - * @param change_type One of the DVB_CA_CAMCHANGE_* values. - */ -void dvb_ca_en50221_cimax_camchange_irq(struct dvb_ca_en50221_cimax *pubca, - int slot, int change_type) -{ - struct dvb_ca_private *ca = pubca->private; - - dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type); - - switch (change_type) { - case DVB_CA_EN50221_CAMCHANGE_REMOVED: - case DVB_CA_EN50221_CAMCHANGE_INSERTED: - break; - - default: - return; - } - - ca->slot_info[slot].camchange_type = change_type; - atomic_inc(&ca->slot_info[slot].camchange_count); - dvb_ca_en50221_thread_wakeup(ca); -} -EXPORT_SYMBOL(dvb_ca_en50221_cimax_frda_irq); - - -/** - * A CAMREADY IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_cimax_camready_irq(struct dvb_ca_en50221_cimax *pubca, - int slot) -{ - struct dvb_ca_private *ca = pubca->private; - - dprintk("CAMREADY IRQ slot:%i\n", slot); - - if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; - dvb_ca_en50221_thread_wakeup(ca); - } -} - - -/** - * An FR or DA IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_cimax_frda_irq(struct dvb_ca_en50221_cimax *pubca, - int slot) -{ - struct dvb_ca_private *ca = pubca->private; - int flags; - - dprintk("FR/DA IRQ slot:%i\n", slot); - - switch (ca->slot_info[slot].slot_state) { - case DVB_CA_SLOTSTATE_LINKINIT: - flags = ca->pub->get_capbility(pubca, slot); - if (flags & DVB_CA_EN50221_CAP_IRQ) { - dprintk("CAM supports DA IRQ\n"); - ca->slot_info[slot].da_irq_supported = 1; - } - break; - - case DVB_CA_SLOTSTATE_RUNNING: - if (ca->open) - dvb_ca_en50221_thread_wakeup(ca); - break; - } -} - - - -/* ************************************************************************** */ -/* EN50221 thread functions */ - -/** - * Wake up the DVB CA thread - * - * @param ca CA instance. - */ -static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) -{ - - dprintk("%s\n", __func__); - - ca->wakeup = 1; - mb(); /*original*/ - wake_up_process(ca->thread); -} - -/** - * Update the delay used by the thread. - * - * @param ca CA instance. - */ -static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) -{ - int delay; - int curdelay = 100000000; - int slot; - - /* Beware of too high polling frequency, because one polling - * call might take several hundred milliseconds until timeout! - */ - for (slot = 0; slot < ca->slot_count; slot++) { - switch (ca->slot_info[slot].slot_state) { - default: - case DVB_CA_SLOTSTATE_NONE: - delay = HZ * 60; /* 60s */ - if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) - delay = HZ * 5; /* 5s */ - break; - case DVB_CA_SLOTSTATE_INVALID: - delay = HZ * 60; /* 60s */ - if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) - delay = HZ / 10; /* 100ms */ - break; - - case DVB_CA_SLOTSTATE_UNINITIALISED: - case DVB_CA_SLOTSTATE_WAITREADY: - case DVB_CA_SLOTSTATE_VALIDATE: - case DVB_CA_SLOTSTATE_WAITFR: - case DVB_CA_SLOTSTATE_LINKINIT: - delay = HZ / 10; /* 100ms */ - break; - case DVB_CA_SLOTSTATE_WAITLINKINIT: - delay = HZ * 2; - break; - - case DVB_CA_SLOTSTATE_RUNNING: - delay = HZ * 60; /* 60s */ - if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) - delay = HZ / 10; /* 100ms */ - if (ca->open) { - if ((!ca->slot_info[slot].da_irq_supported) || - (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) - delay = HZ / 10; /* 100ms */ - } - break; - } - - if (delay < curdelay) - curdelay = delay; - } - - ca->delay = curdelay; -} - -static int dvb_ca_en50221_slot_process(struct dvb_ca_private *ca, int slot) -{ - int flags; - int status; - int pktcount; - void *rxbuf; - - mutex_lock(&ca->slot_info[slot].slot_lock); - - /*check the cam status + deal with CAMCHANGEs*/ - while (dvb_ca_en50221_check_camstatus(ca, slot)) { - /* clear down an old CI slot if necessary */ - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) - dvb_ca_en50221_slot_shutdown(ca, slot); - - /* if a CAM is NOW present, initialise it */ - if (ca->slot_info[slot].camchange_type - == DVB_CA_EN50221_CAMCHANGE_INSERTED) - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_UNINITIALISED; - - /* we've handled one CAMCHANGE */ - dvb_ca_en50221_thread_update_delay(ca); - atomic_dec(&ca->slot_info[slot].camchange_count); - } - - /* CAM state machine */ - switch (ca->slot_info[slot].slot_state) { - case DVB_CA_SLOTSTATE_NONE: - case DVB_CA_SLOTSTATE_INVALID: - /* no action needed */ - break; - - case DVB_CA_SLOTSTATE_UNINITIALISED: - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY; - ca->pub->slot_reset(ca->pub, slot); - ca->slot_info[slot].timeout = jiffies - + (INIT_TIMEOUT_SECS * HZ); - break; - - case DVB_CA_SLOTSTATE_WAITREADY: - if (time_after(jiffies, ca->slot_info[slot].timeout)) { - dprintk("%d: PC card did not respond\n", - ca->dvbdev->adapter->num); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - /* no other action needed; will automatically - * change state when ready - */ - break; - - case DVB_CA_SLOTSTATE_VALIDATE: - if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { - /* we need this extra check - for annoying interfaces like the budget-av */ - if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) - && (ca->pub->poll_slot_status)) { - status = ca->pub->poll_slot_status(ca->pub, - slot, 0); - if (!(status - & DVB_CA_EN50221_POLL_CAM_PRESENT)) { - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_NONE; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - } - dprintk(" %d: Invalid PC card inserted :(\n", - ca->dvbdev->adapter->num); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { - dprintk("%d: Unable initialise CAM:(\n", - ca->dvbdev->adapter->num); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - - if (ca->pub->cam_reset(ca->pub, slot) != 0) { - dprintk("%d: Unable to reset CAM IF\n", - ca->dvbdev->adapter->num); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - - dprintk("DVB CAM validated successfully\n"); - - ca->slot_info[slot].timeout = - jiffies + (INIT_TIMEOUT_SECS * HZ); - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR; - ca->wakeup = 1; - break; - - case DVB_CA_SLOTSTATE_WAITFR: - if (time_after(jiffies, ca->slot_info[slot].timeout)) { - pr_error("dvb_ca adapter %d: ", - ca->dvbdev->adapter->num); - pr_error("DVB CAM did not respond :(\n"); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - - /*flags = ca->pub->read_cam_status(ca->pub, slot);*/ - flags = STATUSREG_FR; - if (flags & STATUSREG_FR) { - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_LINKINIT; - ca->wakeup = 1; - } - break; - - case DVB_CA_SLOTSTATE_WAITLINKINIT: - if (time_after(jiffies, ca->slot_info[slot].timeout)) { - pr_error("dvb_ca adapter %d: ", - ca->dvbdev->adapter->num); - pr_error("DVB CAM link initialisation failed :(\n"); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - - case DVB_CA_SLOTSTATE_LINKINIT: - if (dvb_ca_en50221_link_init(ca, slot) != 0) { - /* we need this extra check for annoying interfaces - like the budget-av */ - if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) - && (ca->pub->poll_slot_status)) { - status = ca->pub->poll_slot_status(ca->pub, - slot, 0); - if (!(status - & DVB_CA_EN50221_POLL_CAM_PRESENT)) { - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_NONE; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - } - - ca->slot_info[slot].timeout = - jiffies + (INIT_TIMEOUT_SECS * HZ); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_WAITLINKINIT; - ca->wakeup = 1; - break; - } - - if (ca->slot_info[slot].rx_buffer.data == NULL) { - rxbuf = vmalloc(RX_BUFFER_SIZE); - if (rxbuf == NULL) { - pr_error("dvb_ca adapter %d: ", - ca->dvbdev->adapter->num); - pr_error("Unable to allocate CAM rx buffer\n"); - ca->slot_info[slot].slot_state = - DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, - rxbuf, RX_BUFFER_SIZE); - } - - ca->pub->slot_ts_enable(ca->pub, slot); - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; - dvb_ca_en50221_thread_update_delay(ca); - dprintk("%d: DVB CAM Initialised successfully\n", - ca->dvbdev->adapter->num); - break; - - case DVB_CA_SLOTSTATE_RUNNING: - if (!ca->open) - break; - - pktcount = 0; - while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) - > 0) { - if (!ca->open) - break; - - /* if a CAMCHANGE occurred at some point, - do not do any more processing of this slot */ - if (dvb_ca_en50221_check_camstatus(ca, slot)) { - /* we dont want to sleep on the next iteration - so we can handle the cam change*/ - ca->wakeup = 1; - break; - } - - /* check if we've hit our limit this time */ - if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { - /*dont sleep; - there is likely to be more data to read*/ - ca->wakeup = 1; - break; - } - } - break; - } - - mutex_unlock(&ca->slot_info[slot].slot_lock); - return 0; -} - - -/** - * Kernel thread which monitors CA slots for CAM changes, - * and performs data transfers. - */ -static int dvb_ca_en50221_thread(void *data) -{ - struct dvb_ca_private *ca = data; - int slot; - - dprintk(" %s\n", __func__); - /* choose the correct initial delay */ - dvb_ca_en50221_thread_update_delay(ca); - - /* main loop */ - while (!kthread_should_stop()) { - /* sleep for a bit */ - if (!ca->wakeup) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ca->delay); - if (kthread_should_stop()) - return 0; - } - ca->wakeup = 0; - - /* go through all the slots processing them */ - for (slot = 0; slot < ca->slot_count; slot++) - dvb_ca_en50221_slot_process(ca, slot); - } - - return 0; -} - - - -/* ************************************************************************** */ -/* EN50221 IO interface functions */ - -/** - * Real ioctl implementation. - * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. - * - * @param inode Inode concerned. - * @param file File concerned. - * @param cmd IOCTL command. - * @param arg Associated argument. - * - * @return 0 on success, <0 on error. - */ -static int dvb_ca_en50221_io_do_ioctl(struct file *file, - unsigned int cmd, void *parg) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_ca_private *ca = dvbdev->priv; - int err = 0; - int slot; - - if (mutex_lock_interruptible(&ca->ioctl_mutex)) { - pr_error("ci lock interrupt error\r\n"); - return -ERESTARTSYS; - } - - switch (cmd) { - case CA_RESET: - dprintk("ci reset---\r\n"); - for (slot = 0; slot < ca->slot_count; slot++) { - mutex_lock(&ca->slot_info[slot].slot_lock); - if (ca->slot_info[slot].slot_state - == DVB_CA_SLOTSTATE_NONE) - goto next; - dvb_ca_en50221_slot_shutdown(ca, slot); - if (ca->flags - & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) - dvb_ca_en50221_cimax_camchange_irq( - ca->pub, - slot, - DVB_CA_EN50221_CAMCHANGE_INSERTED); -next: - mutex_unlock(&ca->slot_info[slot].slot_lock); - } - ca->next_read_slot = 0; - dvb_ca_en50221_thread_wakeup(ca); - break; - - case CA_GET_CAP: { - struct ca_caps *caps = parg; - - caps->slot_num = ca->slot_count; - caps->slot_type = CA_CI_LINK; - caps->descr_num = 0; - caps->descr_type = 0; - break; - } - - case CA_GET_SLOT_INFO: { - struct ca_slot_info *info = parg; - - if ((info->num > ca->slot_count) || (info->num < 0)) { - err = -EINVAL; - pr_error("info num error :%d\r\n", info->num); - goto out_unlock; - } - - info->type = CA_CI_LINK; - info->flags = 0; - if ((ca->slot_info[info->num].slot_state - != DVB_CA_SLOTSTATE_NONE) - && (ca->slot_info[info->num].slot_state - != DVB_CA_SLOTSTATE_INVALID)) { - info->flags = CA_CI_MODULE_PRESENT; - } - if (ca->slot_info[info->num].slot_state - == DVB_CA_SLOTSTATE_RUNNING) { - info->flags |= CA_CI_MODULE_READY; - } - break; - } - - default: - pr_error("Invalid cmd :%d\r\n", cmd); - err = -EINVAL; - break; - } - -out_unlock: - mutex_unlock(&ca->ioctl_mutex); - return err; -} - - -static int dvb_usercopy__(struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - /* - * For this command, the pointer is actually an integer - * argument. - */ - parg = (void *) arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) - err = -ENOTTY; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - kfree(mbuf); - return err; -} - - - -/** - * Wrapper for ioctl implementation. - * - * @param inode Inode concerned. - * @param file File concerned. - * @param cmd IOCTL command. - * @param arg Associated argument. - * - * @return 0 on success, <0 on error. - */ -static long dvb_ca_en50221_io_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return dvb_usercopy__(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); -} - - -/** - * Implementation of write() syscall. - * - * @param file File structure. - * @param buf Source buffer. - * @param count Size of source buffer. - * @param ppos Position in file (ignored). - * - * @return Number of bytes read, or <0 on error. - */ -static ssize_t dvb_ca_en50221_io_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_ca_private *ca = dvbdev->priv; - u8 slot, connection_id; - int status; - u8 *fragbuf = ca->wbuf; - int fragpos = 0; - int fraglen; - unsigned long timeout; - int written; - - /* dprintk("%s\n", __func__); */ - - /* Incoming packet has a 2 byte header. - hdr[0] = slot_id, hdr[1] = connection_id */ - if (count < 2) - return -EINVAL; - - /* extract slot & connection id */ - if (copy_from_user(&slot, buf, 1)) - return -EFAULT; - if (copy_from_user(&connection_id, buf + 1, 1)) - return -EFAULT; - buf += 2; - count -= 2; - - if (slot >= ca->slot_count) - return -EFAULT; - /* check if the slot is actually running */ - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) - return -EINVAL; - - /* fragment the packets & store in the buffer */ - while (fragpos < count) { - fraglen = ca->slot_info[slot].link_buf_size - 2; - if (fraglen < 0) - break; - if (fraglen > dvb_ca_en50221_link_size - 2) - fraglen = dvb_ca_en50221_link_size - 2; - if ((count - fragpos) < fraglen) - fraglen = count - fragpos; - - fragbuf[0] = connection_id; - fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; - status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen); - if (status) { - status = -EFAULT; - goto exit; - } - - timeout = jiffies + HZ / 2; - written = 0; - while (!time_after(jiffies, timeout)) { - /* check the CAM hasn't been removed/reset - in the meantime */ - if (ca->slot_info[slot].slot_state - != DVB_CA_SLOTSTATE_RUNNING) { - status = -EIO; - goto exit; - } - - mutex_lock(&ca->slot_info[slot].slot_lock); - status = dvb_ca_en50221_write_data(ca, - slot, fragbuf, fraglen + 2); - mutex_unlock(&ca->slot_info[slot].slot_lock); - if (status == (fraglen + 2)) { - written = 1; - break; - } - if (status != -EAGAIN) - goto exit; - - msleep(20); - } - if (!written) { - status = -EIO; - goto exit; - } - - fragpos += fraglen; - } - status = count + 2; - -exit: - return status; -} - - -/** - * Condition for waking up in dvb_ca_en50221_io_read_condition - */ -static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, - int *result, int *_slot) -{ - int slot; - int slot_count = 0; - int idx; - size_t fraglen; - int connection_id = -1; - int found = 0; - u8 hdr[2]; - - slot = ca->next_read_slot; - while ((slot_count < ca->slot_count) && (!found)) { - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) - goto nextslot; - - if (ca->slot_info[slot].rx_buffer.data == NULL) - return 0; - - idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, - -1, &fraglen); - while (idx != -1) { - dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, - idx, 0, hdr, 2); - if (connection_id == -1) - connection_id = hdr[0]; - if ((hdr[0] == connection_id) - && ((hdr[1] & 0x80) == 0)) { - *_slot = slot; - found = 1; - break; - } - - idx = dvb_ringbuffer_pkt_next( - &ca->slot_info[slot].rx_buffer, - idx, - &fraglen); - } - -nextslot: - slot = (slot + 1) % ca->slot_count; - slot_count++; - } - - ca->next_read_slot = slot; - return found; -} - - -/** - * Implementation of read() syscall. - * - * @param file File structure. - * @param buf Destination buffer. - * @param count Size of destination buffer. - * @param ppos Position in file (ignored). - * - * @return Number of bytes read, or <0 on error. - */ -static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_ca_private *ca = dvbdev->priv; - int status; - int result = 0; - u8 hdr[2]; - int slot; - int connection_id = -1; - size_t idx, idx2; - int last_fragment = 0; - size_t fraglen; - int pktlen; - int dispose = 0; - - /* dprintk("%s\n", __func__); */ - - /* Outgoing packet has a 2 byte header. - hdr[0] = slot_id, hdr[1] = connection_id */ - if (count < 2) - return -EINVAL; - - /* wait for some data */ - status = dvb_ca_en50221_io_read_condition(ca, &result, &slot); - if (status == 0) { - /* if we're in nonblocking mode, exit immediately */ - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - - /* wait for some data */ - status = wait_event_interruptible(ca->wait_queue, - dvb_ca_en50221_io_read_condition - (ca, &result, &slot)); - } - if ((status < 0) || (result < 0)) { - if (result) - return result; - return status; - } - - idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, - -1, &fraglen); - pktlen = 2; - do { - if (idx == -1) { - pr_error("dvb_ca adapter %d: ", - ca->dvbdev->adapter->num); - pr_error("BUG: read packet ended"); - pr_error("before last_fragment encountered\n"); - status = -EIO; - goto exit; - } - - dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, - idx, 0, hdr, 2); - if (connection_id == -1) - connection_id = hdr[0]; - if (hdr[0] == connection_id) { - if (pktlen < count) { - if ((pktlen + fraglen - 2) > count) - fraglen = count - pktlen; - else - fraglen -= 2; - - status = dvb_ringbuffer_pkt_read_user( - &ca->slot_info[slot].rx_buffer, - idx, - 2, - buf + pktlen, - fraglen); - if (status < 0) - goto exit; - pktlen += fraglen; - } - - if ((hdr[1] & 0x80) == 0) - last_fragment = 1; - dispose = 1; - } - - idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, - idx, &fraglen); - if (dispose) - dvb_ringbuffer_pkt_dispose( - &ca->slot_info[slot].rx_buffer, idx); - idx = idx2; - dispose = 0; - } while (!last_fragment); - - hdr[0] = slot; - hdr[1] = connection_id; - status = copy_to_user(buf, hdr, 2); - if (status) { - status = -EFAULT; - goto exit; - } - status = pktlen; - -exit: - return status; -} - - -/** - * Implementation of file open syscall. - * - * @param inode Inode concerned. - * @param file File concerned. - * - * @return 0 on success, <0 on failure. - */ -static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_ca_private *ca = dvbdev->priv; - int err; - int i; - - dprintk("%s\n", __func__); - - if (!try_module_get(ca->pub->owner)) - return -EIO; - - err = dvb_generic_open(inode, file); - if (err < 0) { - module_put(ca->pub->owner); - return err; - } - - for (i = 0; i < ca->slot_count; i++) { - - if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { - if (ca->slot_info[i].rx_buffer.data != NULL) { - /* it is safe to call this here without locks - because ca->open == 0. - Data is not read in this case */ - dvb_ringbuffer_flush( - &ca->slot_info[i].rx_buffer); - } - } - } - - ca->open = 1; - dvb_ca_en50221_thread_update_delay(ca); - dvb_ca_en50221_thread_wakeup(ca); - - return 0; -} - - -/** - * Implementation of file close syscall. - * - * @param inode Inode concerned. - * @param file File concerned. - * - * @return 0 on success, <0 on failure. - */ -static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_ca_private *ca = dvbdev->priv; - int err; - - dprintk("%s\n", __func__); - - /* mark the CA device as closed */ - ca->open = 0; - dvb_ca_en50221_thread_update_delay(ca); - - err = dvb_generic_release(inode, file); - - module_put(ca->pub->owner); - - return err; -} - - -/** - * Implementation of poll() syscall. - * - * @param file File concerned. - * @param wait poll wait table. - * - * @return Standard poll mask. - */ -static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) -{ - struct dvb_device *dvbdev = file->private_data; - struct dvb_ca_private *ca = dvbdev->priv; - unsigned int mask = 0; - int slot; - int result = 0; - - /* dprintk("%s\n", __func__); */ - - if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) - mask |= POLLIN; - - /* if there is something, return now */ - if (mask) - return mask; - - /* wait for something to happen */ - poll_wait(file, &ca->wait_queue, wait); - - if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) - mask |= POLLIN; - - return mask; -} -EXPORT_SYMBOL(dvb_ca_en50221_cimax_init); - -#ifdef CONFIG_COMPAT -static long dvb_ca_en50221_compat_ioctl(struct file *filp, - unsigned int cmd, unsigned long args) -{ - unsigned long ret; - - args = (unsigned long)compat_ptr(args); - ret = dvb_ca_en50221_io_ioctl(filp, cmd, args); - return ret; -} -#endif -static const struct file_operations dvb_ca_fops = { - .owner = THIS_MODULE, - .read = dvb_ca_en50221_io_read, - .write = dvb_ca_en50221_io_write, - .unlocked_ioctl = dvb_ca_en50221_io_ioctl, - .open = dvb_ca_en50221_io_open, - .release = dvb_ca_en50221_io_release, - .poll = dvb_ca_en50221_io_poll, - .llseek = noop_llseek, -#ifdef CONFIG_COMPAT - .compat_ioctl = dvb_ca_en50221_compat_ioctl, -#endif -}; - -static struct dvb_device dvbdev_ca = { - .priv = NULL, - .users = 1, - .readers = 1, - .writers = 1, - .fops = &dvb_ca_fops, -}; - - -/* ************************************************************************** */ -/* Initialisation/shutdown functions */ - - -/** - * Initialise a new DVB CA EN50221 CIMAX interface device. - * - * @param dvb_adapter DVB adapter to attach the new CA device to. - * @param ca The dvb_ca instance. - * @param flags Flags describing the CA device (DVB_CA_FLAG_*). - * @param slot_count Number of slots supported. - * - * @return 0 on success, nonzero on failure - */ -int dvb_ca_en50221_cimax_init(struct dvb_adapter *dvb_adapter, - struct dvb_ca_en50221_cimax *pubca, - int flags, int slot_count) -{ - int ret; - struct dvb_ca_private *ca = NULL; - int i; - - dprintk("%s\n", __func__); - - if (slot_count < 1) - return -EINVAL; - - /* initialise the system data */ - ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL); - if (ca == NULL) { - ret = -ENOMEM; - goto error; - } - ca->pub = pubca; - ca->flags = flags; - ca->slot_count = slot_count; - ca->slot_info = - kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL); - if (ca->slot_info == NULL) { - ret = -ENOMEM; - goto error; - } - init_waitqueue_head(&ca->wait_queue); - ca->open = 0; - ca->wakeup = 0; - ca->next_read_slot = 0; - ca->rbuf = kcalloc(HOST_LINK_BUF_SIZE, 1, GFP_KERNEL); - ca->wbuf = kcalloc(HOST_LINK_BUF_SIZE, 1, GFP_KERNEL); - if (ca->rbuf == NULL || ca->wbuf == NULL) { - ret = -ENOMEM; - goto error; - } - pubca->private = ca; - - /* register the DVB device */ - ret = dvb_register_device(dvb_adapter, - &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0); - if (ret) - goto error; - - /* now initialise each slot */ - for (i = 0; i < slot_count; i++) { - memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot)); - ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; - atomic_set(&ca->slot_info[i].camchange_count, 0); - ca->slot_info[i].camchange_type = - DVB_CA_EN50221_CAMCHANGE_REMOVED; - mutex_init(&ca->slot_info[i].slot_lock); - } - - mutex_init(&ca->ioctl_mutex); - - if (signal_pending(current)) { - ret = -EINTR; - goto error; - } - mb();/*original*/ - - /* create a kthread for monitoring this CA device */ - ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", - ca->dvbdev->adapter->num, ca->dvbdev->id); - if (IS_ERR(ca->thread)) { - ret = PTR_ERR(ca->thread); - printk("dvb_ca_init: failed to start kernel_thread (%d)\n", - ret); - goto error; - } - return 0; - -error: - if (ca != NULL) { - if (ca->dvbdev != NULL) - dvb_unregister_device(ca->dvbdev); - kfree(ca->slot_info); - kfree(ca->rbuf); - kfree(ca->wbuf); - kfree(ca); - } - pubca->private = NULL; - return ret; -} -EXPORT_SYMBOL(dvb_ca_en50221_cimax_release); - - - -/** - * Release a DVB CA EN50221 CIMAX interface device. - * - * @param ca_dev The dvb_struct device_s instance for the CA device. - * @param ca The associated dvb_ca instance. - */ -void dvb_ca_en50221_cimax_release(struct dvb_ca_en50221_cimax *pubca) -{ - struct dvb_ca_private *ca = pubca->private; - int i; - - dprintk("%s\n", __func__); - - /* shutdown the thread if there was one */ - kthread_stop(ca->thread); - - for (i = 0; i < ca->slot_count; i++) { - dvb_ca_en50221_slot_shutdown(ca, i); - vfree(ca->slot_info[i].rx_buffer.data); - } - kfree(ca->slot_info); - kfree(ca->rbuf); - kfree(ca->wbuf); - dvb_unregister_device(ca->dvbdev); - kfree(ca); - pubca->private = NULL; -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h deleted file mode 100644 index e2ebde6cbc62..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * dvb_ca_cimax.h: generic DVB functions for EN50221 CA CIMAX interfaces - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * 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. - */ - -#ifndef _DVB_CA_EN50221_CIMAX_H_ -#define _DVB_CA_EN50221_CIMAX_H_ - -#include -#include - -#include "dvbdev.h" - -#define DVB_CA_EN50221_POLL_CAM_PRESENT 1 -#define DVB_CA_EN50221_POLL_CAM_CHANGED 2 -#define DVB_CA_EN50221_POLL_CAM_READY 4 - -#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1 -#define DVB_CA_EN50221_FLAG_IRQ_FR 2 -#define DVB_CA_EN50221_FLAG_IRQ_DA 4 - -#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0 -#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1 - -#define DVB_CA_EN50221_CAP_IRQ 1 - -/* Structure describing a CA interface */ -struct dvb_ca_en50221_cimax { - - /* the module owning this structure */ - struct module *owner; - - /* NOTE: the read_*, write_* and poll_slot_status functions will be - * called for different slots concurrently and need to use locks where - * and if appropriate. There will be no concurrent access to one slot. - */ - - /* functions for accessing attribute memory on the CAM */ - int (*read_cis)(struct dvb_ca_en50221_cimax *ca, - int slot, u8 *buf, int size); - int (*write_cor)(struct dvb_ca_en50221_cimax *ca, - int slot, int address, u8 *buf); - /*return the final size or -1 for error*/ - int (*negotiate)(struct dvb_ca_en50221_cimax *ca, int slot, int size); - - /* functions for accessing the control interface on the CAM */ - int (*read_lpdu)(struct dvb_ca_en50221_cimax *ca, - int slot, u8 *buf, int size); - int (*write_lpdu)(struct dvb_ca_en50221_cimax *ca, - int slot, u8 *buf, int size); - - int (*cam_reset)(struct dvb_ca_en50221_cimax *ca, int slot); - int (*read_cam_status)(struct dvb_ca_en50221_cimax *ca, int slot); - int (*get_capbility)(struct dvb_ca_en50221_cimax *ca, int slot); - - /* Functions for controlling slots */ - int (*slot_reset)(struct dvb_ca_en50221_cimax *ca, int slot); - int (*slot_shutdown)(struct dvb_ca_en50221_cimax *ca, int slot); - int (*slot_ts_enable)(struct dvb_ca_en50221_cimax *ca, int slot); - - /* - * Poll slot status. - * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set - */ - int (*poll_slot_status)(struct dvb_ca_en50221_cimax *ca, - int slot, int open); - - /* private data, used by caller */ - void *data; - - /* Opaque data used by the dvb_ca core. Do not modify! */ - void *private; -}; - - - - -/* ************************************************************************* */ -/* Functions for reporting IRQ events */ - -/** - * A CAMCHANGE IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - * @param change_type One of the DVB_CA_CAMCHANGE_* values - */ -void dvb_ca_en50221_cimax_camchange_irq(struct dvb_ca_en50221_cimax *pubca, - int slot, int change_type); - -/** - * A CAMREADY IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_cimax_camready_irq(struct dvb_ca_en50221_cimax *pubca, - int slot); - -/** - * An FR or a DA IRQ has occurred. - * - * @param ca CA instance. - * @param slot Slot concerned. - */ -void dvb_ca_en50221_cimax_frda_irq(struct dvb_ca_en50221_cimax *ca, int slot); - - - -/* ************************************************************************** */ -/* Initialisation/shutdown functions */ - -/** - * Initialise a new DVB CA device. - * - * @param dvb_adapter DVB adapter to attach the new CA device to. - * @param ca The dvb_ca instance. - * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*). - * @param slot_count Number of slots supported. - * - * @return 0 on success, nonzero on failure - */ -extern int dvb_ca_en50221_cimax_init(struct dvb_adapter *dvb_adapter, - struct dvb_ca_en50221_cimax *ca, int flags, int slot_count); - -/** - * Release a DVB CA device. - * - * @param ca The associated dvb_ca instance. - */ -extern void dvb_ca_en50221_cimax_release(struct dvb_ca_en50221_cimax *ca); - - - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c deleted file mode 100644 index fa5c16335909..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * - * dvb_ringbuffer.c: ring buffer implementation for the dvb driver - * - * Copyright (C) 2003 Oliver Endriss - * Copyright (C) 2004 Andrew de Quincey - * - * based on code originally found in av7110.c & dvb_ci.c: - * Copyright (C) 1999-2003 Ralph Metzler - * & Marcus Metzler for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - - -#include -#include -#include -#include -#include -#include - -#include "dvb_ringbuffer.h" - -#define PKT_READY 0 -#define PKT_DISPOSED 1 - - -void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) -{ - rbuf->pread=rbuf->pwrite=0; - rbuf->data=data; - rbuf->size=len; - rbuf->error=0; - - init_waitqueue_head(&rbuf->queue); - - spin_lock_init(&(rbuf->lock)); -} - - - -int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) -{ - /* smp_load_acquire() to load write pointer on reader side - * this pairs with smp_store_release() in dvb_ringbuffer_write(), - * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() - * - * for memory barriers also see Documentation/circular-buffers.txt - */ - return (rbuf->pread == smp_load_acquire(&rbuf->pwrite)); -} - - - -ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) -{ - ssize_t free; - - /* ACCESS_ONCE() to load read pointer on writer side - * this pairs with smp_store_release() in dvb_ringbuffer_read(), - * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(), - * or dvb_ringbuffer_reset() - */ - free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite; - if (free <= 0) - free += rbuf->size; - return free-1; -} - - - -ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) -{ - ssize_t avail; - - /* smp_load_acquire() to load write pointer on reader side - * this pairs with smp_store_release() in dvb_ringbuffer_write(), - * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() - */ - avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread; - if (avail < 0) - avail += rbuf->size; - return avail; -} - - - -void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) -{ - /* dvb_ringbuffer_flush() counts as read operation - * smp_load_acquire() to load write pointer - * smp_store_release() to update read pointer, this ensures that the - * correct pointer is visible for subsequent dvb_ringbuffer_free() - * calls on other cpu cores - */ - smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite)); - rbuf->error = 0; -} -//EXPORT_SYMBOL(dvb_ringbuffer_flush); - -void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) -{ - /* dvb_ringbuffer_reset() counts as read and write operation - * smp_store_release() to update read pointer - */ - smp_store_release(&rbuf->pread, 0); - /* smp_store_release() to update write pointer */ - smp_store_release(&rbuf->pwrite, 0); - rbuf->error = 0; -} - -void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) -{ - unsigned long flags; - - spin_lock_irqsave(&rbuf->lock, flags); - dvb_ringbuffer_flush(rbuf); - spin_unlock_irqrestore(&rbuf->lock, flags); - - wake_up(&rbuf->queue); -} - -ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len) -{ - size_t todo = len; - size_t split; - - split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; - if (split > 0) { - if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) - return -EFAULT; - buf += split; - todo -= split; - /* smp_store_release() for read pointer update to ensure - * that buf is not overwritten until read is complete, - * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() - */ - smp_store_release(&rbuf->pread, 0); - } - if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) - return -EFAULT; - - /* smp_store_release() to update read pointer, see above */ - smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size); - - return len; -} - -void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len) -{ - size_t todo = len; - size_t split; - - split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; - if (split > 0) { - memcpy(buf, rbuf->data+rbuf->pread, split); - buf += split; - todo -= split; - /* smp_store_release() for read pointer update to ensure - * that buf is not overwritten until read is complete, - * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() - */ - smp_store_release(&rbuf->pread, 0); - } - memcpy(buf, rbuf->data+rbuf->pread, todo); - - /* smp_store_release() to update read pointer, see above */ - smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size); -} - - -ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len) -{ - size_t todo = len; - size_t split; - - split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; - - if (split > 0) { - memcpy(rbuf->data+rbuf->pwrite, buf, split); - buf += split; - todo -= split; - /* smp_store_release() for write pointer update to ensure that - * written data is visible on other cpu cores before the pointer - * update, this pairs with smp_load_acquire() in - * dvb_ringbuffer_empty() or dvb_ringbuffer_avail() - */ - smp_store_release(&rbuf->pwrite, 0); - } - memcpy(rbuf->data+rbuf->pwrite, buf, todo); - /* smp_store_release() for write pointer update, see above */ - smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); - - return len; -} - -ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, - const u8 __user *buf, size_t len) -{ - int status; - size_t todo = len; - size_t split; - - split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; - - if (split > 0) { - status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split); - if (status) - return len - todo; - buf += split; - todo -= split; - /* smp_store_release() for write pointer update to ensure that - * written data is visible on other cpu cores before the pointer - * update, this pairs with smp_load_acquire() in - * dvb_ringbuffer_empty() or dvb_ringbuffer_avail() - */ - smp_store_release(&rbuf->pwrite, 0); - } - status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo); - if (status) - return len - todo; - /* smp_store_release() for write pointer update, see above */ - smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); - - return len; -} - -ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) -{ - int status; - ssize_t oldpwrite = rbuf->pwrite; - - DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8); - DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff); - DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY); - status = dvb_ringbuffer_write(rbuf, buf, len); - - if (status < 0) rbuf->pwrite = oldpwrite; - return status; -} - -ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, - int offset, u8 __user *buf, size_t len) -{ - size_t todo; - size_t split; - size_t pktlen; - - pktlen = rbuf->data[idx] << 8; - pktlen |= rbuf->data[(idx + 1) % rbuf->size]; - if (offset > pktlen) return -EINVAL; - if ((offset + len) > pktlen) len = pktlen - offset; - - idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; - todo = len; - split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; - if (split > 0) { - if (copy_to_user(buf, rbuf->data+idx, split)) - return -EFAULT; - buf += split; - todo -= split; - idx = 0; - } - if (copy_to_user(buf, rbuf->data+idx, todo)) - return -EFAULT; - - return len; -} - -ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, - int offset, u8* buf, size_t len) -{ - size_t todo; - size_t split; - size_t pktlen; - - pktlen = rbuf->data[idx] << 8; - pktlen |= rbuf->data[(idx + 1) % rbuf->size]; - if (offset > pktlen) return -EINVAL; - if ((offset + len) > pktlen) len = pktlen - offset; - - idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; - todo = len; - split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; - if (split > 0) { - memcpy(buf, rbuf->data+idx, split); - buf += split; - todo -= split; - idx = 0; - } - memcpy(buf, rbuf->data+idx, todo); - return len; -} - -void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) -{ - size_t pktlen; - - rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED; - - // clean up disposed packets - while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { - if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { - pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; - pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); - DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); - } else { - // first packet is not disposed, so we stop cleaning now - break; - } - } -} - -ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen) -{ - int consumed; - int curpktlen; - int curpktstatus; - - if (idx == -1) { - idx = rbuf->pread; - } else { - curpktlen = rbuf->data[idx] << 8; - curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; - idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; - } - - consumed = (idx - rbuf->pread) % rbuf->size; - - while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { - - curpktlen = rbuf->data[idx] << 8; - curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; - curpktstatus = rbuf->data[(idx + 2) % rbuf->size]; - - if (curpktstatus == PKT_READY) { - *pktlen = curpktlen; - return idx; - } - - consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE; - idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; - } - - // no packets available - return -1; -} - - -#if 0 -EXPORT_SYMBOL(dvb_ringbuffer_init); -EXPORT_SYMBOL(dvb_ringbuffer_empty); -EXPORT_SYMBOL(dvb_ringbuffer_free); -EXPORT_SYMBOL(dvb_ringbuffer_avail); -EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); -EXPORT_SYMBOL(dvb_ringbuffer_read_user); -EXPORT_SYMBOL(dvb_ringbuffer_read); -EXPORT_SYMBOL(dvb_ringbuffer_write); -EXPORT_SYMBOL(dvb_ringbuffer_write_user); -#endif -EXPORT_SYMBOL(dvb_ringbuffer_pkt_read); -EXPORT_SYMBOL(dvb_ringbuffer_pkt_write); -EXPORT_SYMBOL(dvb_ringbuffer_pkt_next); -EXPORT_SYMBOL(dvb_ringbuffer_pkt_dispose); -EXPORT_SYMBOL(dvb_ringbuffer_pkt_read_user); - - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h deleted file mode 100644 index bbe94873d44d..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * - * dvb_ringbuffer.h: ring buffer implementation for the dvb driver - * - * Copyright (C) 2003 Oliver Endriss - * Copyright (C) 2004 Andrew de Quincey - * - * based on code originally found in av7110.c & dvb_ci.c: - * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler - * for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * 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 Lesser General Public License for more details. - */ - -#ifndef _DVB_RINGBUFFER_H_ -#define _DVB_RINGBUFFER_H_ - -#include -#include - -/** - * struct dvb_ringbuffer - Describes a ring buffer used at DVB framework - * - * @data: Area were the ringbuffer data is written - * @size: size of the ringbuffer - * @pread: next position to read - * @pwrite: next position to write - * @error: used by ringbuffer clients to indicate that an error happened. - * @queue: Wait queue used by ringbuffer clients to indicate when buffer - * was filled - * @lock: Spinlock used to protect the ringbuffer - */ -struct dvb_ringbuffer { - u8 *data; - ssize_t size; - ssize_t pread; - ssize_t pwrite; - int error; - - wait_queue_head_t queue; - spinlock_t lock; -}; - -#define DVB_RINGBUFFER_PKTHDRSIZE 3 - -/** - * dvb_ringbuffer_init - initialize ring buffer, lock and queue - * - * @rbuf: pointer to struct dvb_ringbuffer - * @data: pointer to the buffer where the data will be stored - * @len: bytes from ring buffer into @buf - */ -extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, - size_t len); - -/** - * dvb_ringbuffer_empty - test whether buffer is empty - * - * @rbuf: pointer to struct dvb_ringbuffer - */ -extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); - -/** - * dvb_ringbuffer_free - returns the number of free bytes in the buffer - * - * @rbuf: pointer to struct dvb_ringbuffer - * - * Return: number of free bytes in the buffer - */ -extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); - -/** - * dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer - * - * @rbuf: pointer to struct dvb_ringbuffer - * - * Return: number of bytes waiting in the buffer - */ -extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); - -/** - * dvb_ringbuffer_reset - resets the ringbuffer to initial state - * - * @rbuf: pointer to struct dvb_ringbuffer - * - * Resets the read and write pointers to zero and flush the buffer. - * - * This counts as a read and write operation - */ -extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); - -/* - * read routines & macros - */ - -/** - * dvb_ringbuffer_flush - flush buffer - * - * @rbuf: pointer to struct dvb_ringbuffer - */ -extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); - -/** - * dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock - * and wake-up waiting task(s) - * - * @rbuf: pointer to struct dvb_ringbuffer - */ -extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); - -/** - * DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer - * - * @rbuf: pointer to struct dvb_ringbuffer - * @offs: offset inside the ringbuffer - */ -#define DVB_RINGBUFFER_PEEK(rbuf, offs) \ - ((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size]) - -/** - * DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes - * - * @rbuf: pointer to struct dvb_ringbuffer - * @num: number of bytes to advance - */ -#define DVB_RINGBUFFER_SKIP(rbuf, num) {\ - (rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\ -} - -/** - * dvb_ringbuffer_read_user - Reads a buffer into an user pointer - * - * @rbuf: pointer to struct dvb_ringbuffer - * @buf: pointer to the buffer where the data will be stored - * @len: bytes from ring buffer into @buf - * - * This variant assumes that the buffer is a memory at the userspace. So, - * it will internally call copy_to_user(). - * - * Return: number of bytes transferred or -EFAULT - */ -extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, - u8 __user *buf, size_t len); - -/** - * dvb_ringbuffer_read - Reads a buffer into a pointer - * - * @rbuf: pointer to struct dvb_ringbuffer - * @buf: pointer to the buffer where the data will be stored - * @len: bytes from ring buffer into @buf - * - * This variant assumes that the buffer is a memory at the Kernel space - * - * Return: number of bytes transferred or -EFAULT - */ -extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, - u8 *buf, size_t len); - -/* - * write routines & macros - */ - -/** - * DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer - * - * @rbuf: pointer to struct dvb_ringbuffer - * @byte: byte to write - */ -#define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \ - { (rbuf)->data[(rbuf)->pwrite] = (byte); \ - (rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; } - -/** - * dvb_ringbuffer_write - Writes a buffer into the ringbuffer - * - * @rbuf: pointer to struct dvb_ringbuffer - * @buf: pointer to the buffer where the data will be read - * @len: bytes from ring buffer into @buf - * - * This variant assumes that the buffer is a memory at the Kernel space - * - * return: number of bytes transferred or -EFAULT - */ -extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, - size_t len); - -/** - * dvb_ringbuffer_write_user - Writes a buffer received via an user pointer - * - * @rbuf: pointer to struct dvb_ringbuffer - * @buf: pointer to the buffer where the data will be read - * @len: bytes from ring buffer into @buf - * - * This variant assumes that the buffer is a memory at the userspace. So, - * it will internally call copy_from_user(). - * - * Return: number of bytes transferred or -EFAULT - */ -extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, - const u8 __user *buf, size_t len); - -/** - * dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer. - * - * @rbuf: Ringbuffer to write to. - * @buf: Buffer to write. - * @len: Length of buffer (currently limited to 65535 bytes max). - * - * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. - */ -extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, - size_t len); - -/** - * dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer. - * - * @rbuf: Ringbuffer concerned. - * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). - * @offset: Offset into packet to read from. - * @buf: Destination buffer for data. - * @len: Size of destination buffer. - * - * Return: Number of bytes read, or -EFAULT. - * - * .. note:: - * - * unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer - * in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a - * packet as no longer required. - */ -extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, - size_t idx, - int offset, u8 __user *buf, - size_t len); - -/** - * dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer. - * Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer - * in the ringbuffer. - * - * @rbuf: Ringbuffer concerned. - * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). - * @offset: Offset into packet to read from. - * @buf: Destination buffer for data. - * @len: Size of destination buffer. - * - * Return: Number of bytes read, or -EFAULT. - */ -extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, - int offset, u8 *buf, size_t len); - -/** - * dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer. - * - * @rbuf: Ring buffer concerned. - * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). - */ -extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); - -/** - * dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer. - * - * @rbuf: Ringbuffer concerned. - * @idx: Previous packet index, or -1 to return the first packet index. - * @pktlen: On success, will be updated to contain the length of the packet - * in bytes. - * returns Packet index (if >=0), or -1 if no packets available. - */ -extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, - size_t idx, size_t *pktlen); - -#endif /* _DVB_RINGBUFFER_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c deleted file mode 100644 index 0e9599bcb1b5..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c +++ /dev/null @@ -1,968 +0,0 @@ -/* - * dvbdev.c - * - * Copyright (C) 2000 Ralph Metzler - * & Marcus Metzler - * for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dvbdev.h" - -/* Due to enum tuner_pad_index */ -#include - -static DEFINE_MUTEX(dvbdev_mutex); -static int dvbdev_debug; - -module_param(dvbdev_debug, int, 0644); -MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); - -#define dprintk if (dvbdev_debug) printk - -static LIST_HEAD(dvb_adapter_list); -static DEFINE_MUTEX(dvbdev_register_lock); - -static const char * const dnames[] = { - "video", "audio", "sec", "frontend", "demux", "dvr", "ca", - "net", "osd" -}; - -#ifdef CONFIG_DVB_DYNAMIC_MINORS -#define MAX_DVB_MINORS 256 -#define DVB_MAX_IDS MAX_DVB_MINORS -#else -#define DVB_MAX_IDS 4 -#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) -#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) -#endif - -static struct class *dvb_class; - -static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; -static DECLARE_RWSEM(minor_rwsem); - -static int dvb_device_open(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev; - - mutex_lock(&dvbdev_mutex); - down_read(&minor_rwsem); - dvbdev = dvb_minors[iminor(inode)]; - - if (dvbdev && dvbdev->fops) { - int err = 0; - const struct file_operations *new_fops; - - new_fops = fops_get(dvbdev->fops); - if (!new_fops) - goto fail; - file->private_data = dvbdev; - replace_fops(file, new_fops); - if (file->f_op->open) - err = file->f_op->open(inode, file); - up_read(&minor_rwsem); - mutex_unlock(&dvbdev_mutex); - return err; - } -fail: - up_read(&minor_rwsem); - mutex_unlock(&dvbdev_mutex); - return -ENODEV; -} - - -static const struct file_operations dvb_device_fops = -{ - .owner = THIS_MODULE, - .open = dvb_device_open, - .llseek = noop_llseek, -}; - -static struct cdev dvb_device_cdev; - -int dvb_generic_open(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - - if (!dvbdev) - return -ENODEV; - - if (!dvbdev->users) - return -EBUSY; - - if ((file->f_flags & O_ACCMODE) == O_RDONLY) { - if (!dvbdev->readers) - return -EBUSY; - dvbdev->readers--; - } else { - if (!dvbdev->writers) - return -EBUSY; - dvbdev->writers--; - } - - dvbdev->users--; - return 0; -} -EXPORT_SYMBOL(dvb_generic_open); - - -int dvb_generic_release(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - - if (!dvbdev) - return -ENODEV; - - if ((file->f_flags & O_ACCMODE) == O_RDONLY) { - dvbdev->readers++; - } else { - dvbdev->writers++; - } - - dvbdev->users++; - return 0; -} -EXPORT_SYMBOL(dvb_generic_release); - - -long dvb_generic_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct dvb_device *dvbdev = file->private_data; - - if (!dvbdev) - return -ENODEV; - - if (!dvbdev->kernel_ioctl) - return -EINVAL; - - return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); -} -EXPORT_SYMBOL(dvb_generic_ioctl); - - -static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) -{ - u32 id = 0; - - while (id < DVB_MAX_IDS) { - struct dvb_device *dev; - list_for_each_entry(dev, &adap->device_list, list_head) - if (dev->type == type && dev->id == id) - goto skip; - return id; -skip: - id++; - } - return -ENFILE; -} - -static void dvb_media_device_free(struct dvb_device *dvbdev) -{ -#if defined(CONFIG_MEDIA_CONTROLLER_DVB) - if (dvbdev->entity) { - media_device_unregister_entity(dvbdev->entity); - kfree(dvbdev->entity); - kfree(dvbdev->pads); - dvbdev->entity = NULL; - dvbdev->pads = NULL; - } - - if (dvbdev->tsout_entity) { - int i; - - for (i = 0; i < dvbdev->tsout_num_entities; i++) { - media_device_unregister_entity(&dvbdev->tsout_entity[i]); - kfree(dvbdev->tsout_entity[i].name); - } - kfree(dvbdev->tsout_entity); - kfree(dvbdev->tsout_pads); - dvbdev->tsout_entity = NULL; - dvbdev->tsout_pads = NULL; - - dvbdev->tsout_num_entities = 0; - } - - if (dvbdev->intf_devnode) { - media_devnode_remove(dvbdev->intf_devnode); - dvbdev->intf_devnode = NULL; - } - - if (dvbdev->adapter->conn) { - media_device_unregister_entity(dvbdev->adapter->conn); - dvbdev->adapter->conn = NULL; - kfree(dvbdev->adapter->conn_pads); - dvbdev->adapter->conn_pads = NULL; - } -#endif -} - -#if defined(CONFIG_MEDIA_CONTROLLER_DVB) -static int dvb_create_tsout_entity(struct dvb_device *dvbdev, - const char *name, int npads) -{ - int i, ret = 0; - - dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads), - GFP_KERNEL); - if (!dvbdev->tsout_pads) - return -ENOMEM; - - dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity), - GFP_KERNEL); - if (!dvbdev->tsout_entity) - return -ENOMEM; - - dvbdev->tsout_num_entities = npads; - - for (i = 0; i < npads; i++) { - struct media_pad *pads = &dvbdev->tsout_pads[i]; - struct media_entity *entity = &dvbdev->tsout_entity[i]; - - entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i); - if (!entity->name) - return -ENOMEM; - - entity->function = MEDIA_ENT_F_IO_DTV; - pads->flags = MEDIA_PAD_FL_SINK; - - ret = media_entity_pads_init(entity, 1, pads); - if (ret < 0) - return ret; - - ret = media_device_register_entity(dvbdev->adapter->mdev, - entity); - if (ret < 0) - return ret; - } - return 0; -} - -#define DEMUX_TSOUT "demux-tsout" -#define DVR_TSOUT "dvr-tsout" - -static int dvb_create_media_entity(struct dvb_device *dvbdev, - int type, int demux_sink_pads) -{ - int i, ret, npads; - - switch (type) { - case DVB_DEVICE_FRONTEND: - npads = 2; - break; - case DVB_DEVICE_DVR: - ret = dvb_create_tsout_entity(dvbdev, DVR_TSOUT, - demux_sink_pads); - return ret; - case DVB_DEVICE_DEMUX: - npads = 1 + demux_sink_pads; - ret = dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT, - demux_sink_pads); - if (ret < 0) - return ret; - break; - case DVB_DEVICE_CA: - npads = 2; - break; - case DVB_DEVICE_NET: - /* - * We should be creating entities for the MPE/ULE - * decapsulation hardware (or software implementation). - * - * However, the number of for the MPE/ULE decaps may not be - * fixed. As we don't have yet dynamic support for PADs at - * the Media Controller, let's not create the decap - * entities yet. - */ - return 0; - default: - return 0; - } - - dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL); - if (!dvbdev->entity) - return -ENOMEM; - - dvbdev->entity->name = dvbdev->name; - - if (npads) { - dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), - GFP_KERNEL); - if (!dvbdev->pads) - return -ENOMEM; - } - - switch (type) { - case DVB_DEVICE_FRONTEND: - dvbdev->entity->function = MEDIA_ENT_F_DTV_DEMOD; - dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; - dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; - break; - case DVB_DEVICE_DEMUX: - dvbdev->entity->function = MEDIA_ENT_F_TS_DEMUX; - dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; - for (i = 1; i < npads; i++) - dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE; - break; - case DVB_DEVICE_CA: - dvbdev->entity->function = MEDIA_ENT_F_DTV_CA; - dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; - dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; - break; - default: - /* Should never happen, as the first switch prevents it */ - kfree(dvbdev->entity); - kfree(dvbdev->pads); - dvbdev->entity = NULL; - dvbdev->pads = NULL; - return 0; - } - - if (npads) { - ret = media_entity_pads_init(dvbdev->entity, npads, dvbdev->pads); - if (ret) - return ret; - } - ret = media_device_register_entity(dvbdev->adapter->mdev, - dvbdev->entity); - if (ret) - return ret; - - printk(KERN_DEBUG "%s: media entity '%s' registered.\n", - __func__, dvbdev->entity->name); - - return 0; -} -#endif - -static int dvb_register_media_device(struct dvb_device *dvbdev, - int type, int minor, - unsigned demux_sink_pads) -{ -#if defined(CONFIG_MEDIA_CONTROLLER_DVB) - struct media_link *link; - u32 intf_type; - int ret; - - if (!dvbdev->adapter->mdev) - return 0; - - ret = dvb_create_media_entity(dvbdev, type, demux_sink_pads); - if (ret) - return ret; - - switch (type) { - case DVB_DEVICE_FRONTEND: - intf_type = MEDIA_INTF_T_DVB_FE; - break; - case DVB_DEVICE_DEMUX: - intf_type = MEDIA_INTF_T_DVB_DEMUX; - break; - case DVB_DEVICE_DVR: - intf_type = MEDIA_INTF_T_DVB_DVR; - break; - case DVB_DEVICE_CA: - intf_type = MEDIA_INTF_T_DVB_CA; - break; - case DVB_DEVICE_NET: - intf_type = MEDIA_INTF_T_DVB_NET; - break; - default: - return 0; - } - - dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev, - intf_type, 0, - DVB_MAJOR, minor); - - if (!dvbdev->intf_devnode) - return -ENOMEM; - - /* - * Create the "obvious" link, e. g. the ones that represent - * a direct association between an interface and an entity. - * Other links should be created elsewhere, like: - * DVB FE intf -> tuner - * DVB demux intf -> dvr - */ - - if (!dvbdev->entity) - return 0; - - link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, - MEDIA_LNK_FL_ENABLED); - if (!link) - return -ENOMEM; -#endif - return 0; -} - -int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, - const struct dvb_device *template, void *priv, int type, - int demux_sink_pads) -{ - struct dvb_device *dvbdev; - struct file_operations *dvbdevfops; - struct device *clsdev; - int minor; - int id, ret; - - mutex_lock(&dvbdev_register_lock); - - if ((id = dvbdev_get_free_id (adap, type)) < 0){ - mutex_unlock(&dvbdev_register_lock); - *pdvbdev = NULL; - printk(KERN_ERR "%s: couldn't find free device id\n", __func__); - return -ENFILE; - } - - *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); - - if (!dvbdev){ - mutex_unlock(&dvbdev_register_lock); - return -ENOMEM; - } - - dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); - - if (!dvbdevfops){ - kfree (dvbdev); - mutex_unlock(&dvbdev_register_lock); - return -ENOMEM; - } - - memcpy(dvbdev, template, sizeof(struct dvb_device)); - dvbdev->type = type; - dvbdev->id = id; - dvbdev->adapter = adap; - dvbdev->priv = priv; - dvbdev->fops = dvbdevfops; - init_waitqueue_head (&dvbdev->wait_queue); - - memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); - dvbdevfops->owner = adap->module; - - list_add_tail (&dvbdev->list_head, &adap->device_list); - - down_write(&minor_rwsem); -#ifdef CONFIG_DVB_DYNAMIC_MINORS - for (minor = 0; minor < MAX_DVB_MINORS; minor++) - if (dvb_minors[minor] == NULL) - break; - - if (minor == MAX_DVB_MINORS) { - kfree(dvbdevfops); - kfree(dvbdev); - up_write(&minor_rwsem); - mutex_unlock(&dvbdev_register_lock); - return -EINVAL; - } -#else - minor = nums2minor(adap->num, type, id); -#endif - - dvbdev->minor = minor; - dvb_minors[minor] = dvbdev; - up_write(&minor_rwsem); - - ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); - if (ret) { - printk(KERN_ERR - "%s: dvb_register_media_device failed to create the mediagraph\n", - __func__); - - dvb_media_device_free(dvbdev); - kfree(dvbdevfops); - kfree(dvbdev); - up_write(&minor_rwsem); - mutex_unlock(&dvbdev_register_lock); - return ret; - } - - mutex_unlock(&dvbdev_register_lock); - - clsdev = device_create(dvb_class, adap->device, - MKDEV(DVB_MAJOR, minor), - dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); - if (IS_ERR(clsdev)) { - printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", - __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); - return PTR_ERR(clsdev); - } - dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", - adap->num, dnames[type], id, minor, minor); - - return 0; -} -EXPORT_SYMBOL(dvb_register_device); - - -void dvb_unregister_device(struct dvb_device *dvbdev) -{ - if (!dvbdev) - return; - - down_write(&minor_rwsem); - dvb_minors[dvbdev->minor] = NULL; - up_write(&minor_rwsem); - - dvb_media_device_free(dvbdev); - - device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); - - list_del (&dvbdev->list_head); - kfree (dvbdev->fops); - kfree (dvbdev); -} -EXPORT_SYMBOL(dvb_unregister_device); - - -#ifdef CONFIG_MEDIA_CONTROLLER_DVB - -static int dvb_create_io_intf_links(struct dvb_adapter *adap, - struct media_interface *intf, - char *name) -{ - struct media_device *mdev = adap->mdev; - struct media_entity *entity; - struct media_link *link; - - media_device_for_each_entity(entity, mdev) { - if (entity->function == MEDIA_ENT_F_IO_DTV) { - if (strncmp(entity->name, name, strlen(name))) - continue; - link = media_create_intf_link(entity, intf, - MEDIA_LNK_FL_ENABLED); - if (!link) - return -ENOMEM; - } - } - return 0; -} - -int dvb_create_media_graph(struct dvb_adapter *adap, - bool create_rf_connector) -{ - struct media_device *mdev = adap->mdev; - struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn; - struct media_entity *demux = NULL, *ca = NULL; - struct media_link *link; - struct media_interface *intf; - unsigned demux_pad = 0; - unsigned dvr_pad = 0; - unsigned ntuner = 0, ndemod = 0; - int ret; - static const char *connector_name = "Television"; - - if (!mdev) - return 0; - - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_TUNER: - tuner = entity; - ntuner++; - break; - case MEDIA_ENT_F_DTV_DEMOD: - demod = entity; - ndemod++; - break; - case MEDIA_ENT_F_TS_DEMUX: - demux = entity; - break; - case MEDIA_ENT_F_DTV_CA: - ca = entity; - break; - } - } - - /* - * Prepare to signalize to media_create_pad_links() that multiple - * entities of the same type exists and a 1:n or n:1 links need to be - * created. - * NOTE: if both tuner and demod have multiple instances, it is up - * to the caller driver to create such links. - */ - if (ntuner > 1) - tuner = NULL; - if (ndemod > 1) - demod = NULL; - - if (create_rf_connector) { - conn = kzalloc(sizeof(*conn), GFP_KERNEL); - if (!conn) - return -ENOMEM; - adap->conn = conn; - - adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL); - if (!adap->conn_pads) - return -ENOMEM; - - conn->flags = MEDIA_ENT_FL_CONNECTOR; - conn->function = MEDIA_ENT_F_CONN_RF; - conn->name = connector_name; - adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE; - - ret = media_entity_pads_init(conn, 1, adap->conn_pads); - if (ret) - return ret; - - ret = media_device_register_entity(mdev, conn); - if (ret) - return ret; - - if (!ntuner) - ret = media_create_pad_links(mdev, - MEDIA_ENT_F_CONN_RF, - conn, 0, - MEDIA_ENT_F_DTV_DEMOD, - demod, 0, - MEDIA_LNK_FL_ENABLED, - false); - else - ret = media_create_pad_links(mdev, - MEDIA_ENT_F_CONN_RF, - conn, 0, - MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_RF_INPUT, - MEDIA_LNK_FL_ENABLED, - false); - if (ret) - return ret; - } - - if (ntuner && ndemod) { - ret = media_create_pad_links(mdev, - MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_OUTPUT, - MEDIA_ENT_F_DTV_DEMOD, - demod, 0, MEDIA_LNK_FL_ENABLED, - false); - if (ret) - return ret; - } - - if (ndemod && demux) { - ret = media_create_pad_links(mdev, - MEDIA_ENT_F_DTV_DEMOD, - demod, 1, - MEDIA_ENT_F_TS_DEMUX, - demux, 0, MEDIA_LNK_FL_ENABLED, - false); - if (ret) - return ret; - } - if (demux && ca) { - ret = media_create_pad_link(demux, 1, ca, - 0, MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - - /* Create demux links for each ringbuffer/pad */ - if (demux) { - media_device_for_each_entity(entity, mdev) { - if (entity->function == MEDIA_ENT_F_IO_DTV) { - if (!strncmp(entity->name, DVR_TSOUT, - strlen(DVR_TSOUT))) { - ret = media_create_pad_link(demux, - ++dvr_pad, - entity, 0, 0); - if (ret) - return ret; - } - if (!strncmp(entity->name, DEMUX_TSOUT, - strlen(DEMUX_TSOUT))) { - ret = media_create_pad_link(demux, - ++demux_pad, - entity, 0, 0); - if (ret) - return ret; - } - } - } - } - - /* Create interface links for FE->tuner, DVR->demux and CA->ca */ - media_device_for_each_intf(intf, mdev) { - if (intf->type == MEDIA_INTF_T_DVB_CA && ca) { - link = media_create_intf_link(ca, intf, - MEDIA_LNK_FL_ENABLED); - if (!link) - return -ENOMEM; - } - - if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) { - link = media_create_intf_link(tuner, intf, - MEDIA_LNK_FL_ENABLED); - if (!link) - return -ENOMEM; - } -#if 0 - /* - * Indirect link - let's not create yet, as we don't know how - * to handle indirect links, nor if this will - * actually be needed. - */ - if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) { - link = media_create_intf_link(demux, intf, - MEDIA_LNK_FL_ENABLED); - if (!link) - return -ENOMEM; - } -#endif - if (intf->type == MEDIA_INTF_T_DVB_DVR) { - ret = dvb_create_io_intf_links(adap, intf, DVR_TSOUT); - if (ret) - return ret; - } - if (intf->type == MEDIA_INTF_T_DVB_DEMUX) { - ret = dvb_create_io_intf_links(adap, intf, DEMUX_TSOUT); - if (ret) - return ret; - } - } - return 0; -} -EXPORT_SYMBOL_GPL(dvb_create_media_graph); -#endif - -static int dvbdev_check_free_adapter_num(int num) -{ - struct list_head *entry; - list_for_each(entry, &dvb_adapter_list) { - struct dvb_adapter *adap; - adap = list_entry(entry, struct dvb_adapter, list_head); - if (adap->num == num) - return 0; - } - return 1; -} - -static int dvbdev_get_free_adapter_num (void) -{ - int num = 0; - - while (num < DVB_MAX_ADAPTERS) { - if (dvbdev_check_free_adapter_num(num)) - return num; - num++; - } - - return -ENFILE; -} - - -int dvb_register_adapter(struct dvb_adapter *adap, const char *name, - struct module *module, struct device *device, - short *adapter_nums) -{ - int i, num; - - mutex_lock(&dvbdev_register_lock); - - for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { - num = adapter_nums[i]; - if (num >= 0 && num < DVB_MAX_ADAPTERS) { - /* use the one the driver asked for */ - if (dvbdev_check_free_adapter_num(num)) - break; - } else { - num = dvbdev_get_free_adapter_num(); - break; - } - num = -1; - } - - if (num < 0) { - mutex_unlock(&dvbdev_register_lock); - return -ENFILE; - } - - memset (adap, 0, sizeof(struct dvb_adapter)); - INIT_LIST_HEAD (&adap->device_list); - - printk(KERN_INFO "DVB: registering new adapter (%s)\n", name); - - adap->num = num; - adap->name = name; - adap->module = module; - adap->device = device; - adap->mfe_shared = 0; - adap->mfe_dvbdev = NULL; - mutex_init (&adap->mfe_lock); - - list_add_tail (&adap->list_head, &dvb_adapter_list); - - mutex_unlock(&dvbdev_register_lock); - - return num; -} -EXPORT_SYMBOL(dvb_register_adapter); - - -int dvb_unregister_adapter(struct dvb_adapter *adap) -{ - mutex_lock(&dvbdev_register_lock); - list_del (&adap->list_head); - mutex_unlock(&dvbdev_register_lock); - return 0; -} -EXPORT_SYMBOL(dvb_unregister_adapter); - -/* if the miracle happens and "generic_usercopy()" is included into - the kernel, then this can vanish. please don't make the mistake and - define this as video_usercopy(). this will introduce a dependecy - to the v4l "videodev.o" module, which is unnecessary for some - cards (ie. the budget dvb-cards don't need the v4l module...) */ -int dvb_usercopy(struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - /* - * For this command, the pointer is actually an integer - * argument. - */ - parg = (void *) arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) - err = -ENOTTY; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - kfree(mbuf); - return err; -} -EXPORT_SYMBOL(dvb_usercopy); -static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct dvb_device *dvbdev = dev_get_drvdata(dev); - - add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); - add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); - add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id); - return 0; -} - -static char *dvb_devnode(struct device *dev, umode_t *mode) -{ - struct dvb_device *dvbdev = dev_get_drvdata(dev); - - return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", - dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); -} - - -static int __init init_dvbdev(void) -{ - int retval; - dev_t dev = MKDEV(DVB_MAJOR, 0); - - if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { - printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR); - return retval; - } - - cdev_init(&dvb_device_cdev, &dvb_device_fops); - if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { - printk(KERN_ERR "dvb-core: unable register character device\n"); - goto error; - } - - dvb_class = class_create(THIS_MODULE, "dvb"); - if (IS_ERR(dvb_class)) { - retval = PTR_ERR(dvb_class); - goto error; - } - dvb_class->dev_uevent = dvb_uevent; - dvb_class->devnode = dvb_devnode; - return 0; - -error: - cdev_del(&dvb_device_cdev); - unregister_chrdev_region(dev, MAX_DVB_MINORS); - return retval; -} - - -static void __exit exit_dvbdev(void) -{ - class_destroy(dvb_class); - cdev_del(&dvb_device_cdev); - unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); -} -#if 0 -subsys_initcall(init_dvbdev); -module_exit(exit_dvbdev); - -MODULE_DESCRIPTION("DVB Core Driver"); -MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); -MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h deleted file mode 100644 index 4aff7bd3dea8..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * dvbdev.h - * - * Copyright (C) 2000 Ralph Metzler & Marcus Metzler - * for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Lesser Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _DVBDEV_H_ -#define _DVBDEV_H_ - -#include -#include -#include -#include -#include - -#define DVB_MAJOR 212 - -#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 - #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS -#else - #define DVB_MAX_ADAPTERS 8 -#endif - -#define DVB_UNSET (-1) - -#define DVB_DEVICE_VIDEO 0 -#define DVB_DEVICE_AUDIO 1 -#define DVB_DEVICE_SEC 2 -#define DVB_DEVICE_FRONTEND 3 -#define DVB_DEVICE_DEMUX 4 -#define DVB_DEVICE_DVR 5 -#define DVB_DEVICE_CA 6 -#define DVB_DEVICE_NET 7 -#define DVB_DEVICE_OSD 8 - -#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ - static short adapter_nr[] = \ - {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \ - module_param_array(adapter_nr, short, NULL, 0444); \ - MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") - -struct dvb_frontend; - -/** - * struct dvb_adapter - represents a Digital TV adapter using Linux DVB API - * - * @num: Number of the adapter - * @list_head: List with the DVB adapters - * @device_list: List with the DVB devices - * @name: Name of the adapter - * @proposed_mac: proposed MAC address for the adapter - * @priv: private data - * @device: pointer to struct device - * @module: pointer to struct module - * @mfe_shared: mfe shared: indicates mutually exclusive frontends - * Thie usage of this flag is currently deprecated - * @mfe_dvbdev: Frontend device in use, in the case of MFE - * @mfe_lock: Lock to prevent using the other frontends when MFE is - * used. - * @mdev: pointer to struct media_device, used when the media - * controller is used. - * @conn: RF connector. Used only if the device has no separate - * tuner. - * @conn_pads: pointer to struct media_pad associated with @conn; - */ -struct dvb_adapter { - int num; - struct list_head list_head; - struct list_head device_list; - const char *name; - u8 proposed_mac [6]; - void* priv; - - struct device *device; - - struct module *module; - - int mfe_shared; /* indicates mutually exclusive frontends */ - struct dvb_device *mfe_dvbdev; /* frontend device in use */ - struct mutex mfe_lock; /* access lock for thread creation */ - -#if defined(CONFIG_MEDIA_CONTROLLER_DVB) - struct media_device *mdev; - struct media_entity *conn; - struct media_pad *conn_pads; -#endif -}; - -/** - * struct dvb_device - represents a DVB device node - * - * @list_head: List head with all DVB devices - * @fops: pointer to struct file_operations - * @adapter: pointer to the adapter that holds this device node - * @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, - * DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET - * @minor: devnode minor number. Major number is always DVB_MAJOR. - * @id: device ID number, inside the adapter - * @readers: Initialized by the caller. Each call to open() in Read Only mode - * decreases this counter by one. - * @writers: Initialized by the caller. Each call to open() in Read/Write - * mode decreases this counter by one. - * @users: Initialized by the caller. Each call to open() in any mode - * decreases this counter by one. - * @wait_queue: wait queue, used to wait for certain events inside one of - * the DVB API callers - * @kernel_ioctl: callback function used to handle ioctl calls from userspace. - * @name: Name to be used for the device at the Media Controller - * @entity: pointer to struct media_entity associated with the device node - * @pads: pointer to struct media_pad associated with @entity; - * @priv: private data - * @intf_devnode: Pointer to media_intf_devnode. Used by the dvbdev core to - * store the MC device node interface - * @tsout_num_entities: Number of Transport Stream output entities - * @tsout_entity: array with MC entities associated to each TS output node - * @tsout_pads: array with the source pads for each @tsout_entity - * - * This structure is used by the DVB core (frontend, CA, net, demux) in - * order to create the device nodes. Usually, driver should not initialize - * this struct diretly. - */ -struct dvb_device { - struct list_head list_head; - const struct file_operations *fops; - struct dvb_adapter *adapter; - int type; - int minor; - u32 id; - - /* in theory, 'users' can vanish now, - but I don't want to change too much now... */ - int readers; - int writers; - int users; - - wait_queue_head_t wait_queue; - /* don't really need those !? -- FIXME: use video_usercopy */ - int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg); - - /* Needed for media controller register/unregister */ -#if defined(CONFIG_MEDIA_CONTROLLER_DVB) - const char *name; - - /* Allocated and filled inside dvbdev.c */ - struct media_intf_devnode *intf_devnode; - - unsigned tsout_num_entities; - struct media_entity *entity, *tsout_entity; - struct media_pad *pads, *tsout_pads; -#endif - - void *priv; -}; - -/** - * dvb_register_adapter - Registers a new DVB adapter - * - * @adap: pointer to struct dvb_adapter - * @name: Adapter's name - * @module: initialized with THIS_MODULE at the caller - * @device: pointer to struct device that corresponds to the device driver - * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter; - * to select among them. Typically, initialized with: - * DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums) - */ -int dvb_register_adapter(struct dvb_adapter *adap, const char *name, - struct module *module, struct device *device, - short *adapter_nums); - -/** - * dvb_unregister_adapter - Unregisters a DVB adapter - * - * @adap: pointer to struct dvb_adapter - */ -int dvb_unregister_adapter(struct dvb_adapter *adap); - -/** - * dvb_register_device - Registers a new DVB device - * - * @adap: pointer to struct dvb_adapter - * @pdvbdev: pointer to the place where the new struct dvb_device will be - * stored - * @template: Template used to create &pdvbdev; - * @priv: private data - * @type: type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND, - * %DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA, - * %DVB_DEVICE_NET - * @demux_sink_pads: Number of demux outputs, to be used to create the TS - * outputs via the Media Controller. - */ -int dvb_register_device(struct dvb_adapter *adap, - struct dvb_device **pdvbdev, - const struct dvb_device *template, - void *priv, - int type, - int demux_sink_pads); - -/** - * dvb_unregister_device - Unregisters a DVB device - * - * @dvbdev: pointer to struct dvb_device - */ -void dvb_unregister_device(struct dvb_device *dvbdev); - -#ifdef CONFIG_MEDIA_CONTROLLER_DVB -/** - * dvb_create_media_graph - Creates media graph for the Digital TV part of the - * device. - * - * @adap: pointer to struct dvb_adapter - * @create_rf_connector: if true, it creates the RF connector too - * - * This function checks all DVB-related functions at the media controller - * entities and creates the needed links for the media graph. It is - * capable of working with multiple tuners or multiple frontends, but it - * won't create links if the device has multiple tuners and multiple frontends - * or if the device has multiple muxes. In such case, the caller driver should - * manually create the remaining links. - */ -__must_check int dvb_create_media_graph(struct dvb_adapter *adap, - bool create_rf_connector); - -static inline void dvb_register_media_controller(struct dvb_adapter *adap, - struct media_device *mdev) -{ - adap->mdev = mdev; -} - -static inline struct media_device -*dvb_get_media_controller(struct dvb_adapter *adap) -{ - return adap->mdev; -} -#else -static inline -int dvb_create_media_graph(struct dvb_adapter *adap, - bool create_rf_connector) -{ - return 0; -}; -#define dvb_register_media_controller(a, b) {} -#define dvb_get_media_controller(a) NULL -#endif - -int dvb_generic_open (struct inode *inode, struct file *file); -int dvb_generic_release (struct inode *inode, struct file *file); -long dvb_generic_ioctl (struct file *file, - unsigned int cmd, unsigned long arg); - -/* we don't mess with video_usercopy() any more, -we simply define out own dvb_usercopy(), which will hopefully become -generic_usercopy() someday... */ - -int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, - int (*func)(struct file *file, unsigned int cmd, void *arg)); - -/** generic DVB attach function. */ -#ifdef CONFIG_MEDIA_ATTACH -#define dvb_attach(FUNCTION, ARGS...) ({ \ - void *__r = NULL; \ - typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ - if (__a) { \ - __r = (void *) __a(ARGS); \ - if (__r == NULL) \ - symbol_put(FUNCTION); \ - } else { \ - printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \ - } \ - __r; \ -}) - -#define dvb_detach(FUNC) symbol_put_addr(FUNC) - -#else -#define dvb_attach(FUNCTION, ARGS...) ({ \ - FUNCTION(ARGS); \ -}) - -#define dvb_detach(FUNC) {} - -#endif - -#endif /* #ifndef _DVBDEV_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER deleted file mode 100644 index 8f4a86041ed0..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER +++ /dev/null @@ -1,499 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. -We sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library. - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt deleted file mode 100644 index 1d6a01c7dccd..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt +++ /dev/null @@ -1,61 +0,0 @@ -April 28, 2011 - -Linux CIMaX+ Kernel driver. -Release Code version: - -DISCLAIMER ----------- - -This is a Smardtv' Linux Kernel driver for use with -the CIMaX+ USB reference board hardware. - -IMPORTANT NOTE --------------- - -This packages contains a Linux Kernel driver to be installed in the -/lib/modules target directory in order to be loaded automaticaly. - -1. High level driver: cimax+usb_driver.ko - This driver provide the high level interface to control the CIMaX+ USB interface. - -2. Firmware - To have a functional hardware, the firmware must be uploaded to the device. - - The firmwares is delivered in 2 files for dedicated usage and must be - installed in the Linux firmware directory on the target board: - - - /lib/firmware - - A) CIMaX+ firmware binary file - Copy the following firmware file to the /lib/firmware directory: - - firmware/cimax+_usbdvb.bin - - B) CIMaX+ configuration file - Copy the following firmware file to the /lib/firmware directory: - - firmware/cimax+usb.cfg - - -BUILD AND INSTALLATION INSTRUCTIONS ------------------------------------ - -2. Building LINUX USB DVB driver - On the target machine performs the following commands: - - 1. cd src - 2. make - 3. make install - -3. Installing firmware files - On the target machine performs the following command: - - 1. cp firmware/*.* /lib/firmware/ - -4. Installing rules file - 1. cp src/99-cimax+usb.rules /etc/udev/rules.d/ - 2. udevadm control --reload-rules - -5. Build modules dependencies - On the target machine performs the following command: - - 1. depmod -a - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules deleted file mode 100644 index 82af37083592..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules +++ /dev/null @@ -1,4 +0,0 @@ -BUS=="usb", ACTION=="add", SYSFS{idProduct}=="2F00", SYSFS{idVendor}=="1B0D" -KERNEL=="cimaxusb[0-9]", GROUP="users" - - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt deleted file mode 100644 index 23de038208c9..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt +++ /dev/null @@ -1,85 +0,0 @@ -The following examples shows how to use the cimax+usb driver. -All structures and macro are defined in file cimax+usb-driver.h. - - -1.Open the device cimax+usb -=========================== -/* open device */ -dev = open("/dev/cimaxusb0", O_RDWR); -/* select USB alt_setting */ -ioctl(dev, DEVICE_IOC_SELECT_INTF, alt_setting); - - -2.Close the device cimax+usb -============================ -/* unlock read queue */ -ioctl(dev, DEVICE_IOC_UNLOCK_READ, 0); -/* close device */ -close(dev); - - -3.Send a CI message to a CAM through the device -=============================================== -/* Send CAM A Reset command */ -uint8 command[5] = {0x01, /* Command */ - 0x01, /* Counter */ - 0x00, /* MSB data size */ - 0x01, /* LSB data size */ - 0x00}; /* data */ -uint8 response[4100]; -struct ioctl_data_s stData; -stData.txData = command; -stData.txSize = 5; -stData.rxData = response; -stData.rxSize = 4100; -ioctl(dev, DEVICE_IOC_CI_WRITE, &stData); - -/* Send CAM B Get CIS command */ -uint8 command[5] = {0x82, /* Command */ - 0x01, /* Counter */ - 0x00, /* MSB data size */ - 0x00}; /* LSB data size */ -uint8 response[4100]; -struct ioctl_data_s stData; -stData.txData = command; -stData.txSize = 4; -stData.rxData = response; -stData.rxSize = 4100; -ioctl(dev, DEVICE_IOC_CI_WRITE, &stData); - - -4.Send a Transport Stream to a CAM through the device -===================================================== -/* Send to CAM A */ -struct rw_data_s rwData; -rwData.type = DEVICE_TYPE_TS_WRITE; -rwData.moduleId = 0; /* CAM A */ -rwData.data = stream; -rwData.size = size; -rwData.copiedSize = 0; -write(dev, &rwData, sizeof(struct rw_data_s)); - - -5.Read a Transport Stream from a CAM through the device -======================================================= -/* Read from CAM B */ -struct rw_data_s rwData; -rwData.type = DEVICE_TYPE_TS_READ; -rwData.moduleId = 1; /* CAM B */ -rwData.data = stream; -rwData.size = size; -rwData.copiedSize = 0; -read(dev, &rwData, sizeof(struct rw_data_s)); - - -6.Read a CI message from a CAM through the device -================================================= -/* Read from CAM A */ -uint8 response[4096]; -struct rw_data_s rwData; -rwData.type = DEVICE_TYPE_CI_READ; -rwData.moduleId = 0; /* CAM A */ -rwData.data = response; -rwData.size = 4096; -rwData.copiedSize = 0; -read(dev, &rwData, sizeof(struct rw_data_s)); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile deleted file mode 100644 index bc7994599d3f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -TARGET = cimax+usb_driver -OBJS = cimax+usb_driver.o -MDIR = drivers/misc - -ccflags-y = -DEXPORT_SYMTAB -#ccflags-y = -DEXPORT_SYMTAB -DDEBUG -CURRENT = $(shell uname -r) -KDIR = /lib/modules/$(CURRENT)/build -PWD = $(shell pwd) -DEST = /lib/modules/$(CURRENT)/kernel/$(MDIR) - -obj-m := $(TARGET).o -cimax+usb_driver-y := cimax+usb-driver.o cimax+usb_fw.o -cimax+usb_driver-y += cimax+usb_config.o -cimax+usb_driver-y += cimax+usb_time.o - -default: - make -C /usr/src/linux SUBDIRS=$(PWD) modules -# make -C /lib/modules/`uname -r`/build M=$(PWD) modules - -$(TARGET).o: $(OBJS) - $(LD) $(LD_RFLAG) -r -o $@ $(OBJS) - -ifneq (,$(findstring 2.4.,$(CURRENT))) -install: - su -c "cp -v $(TARGET).o $(DEST) && /sbin/depmod -a" -else -install: - su -c "cp -v $(TARGET).ko $(DEST) && /sbin/depmod -a" -endif - -clean: - -rm -f *.o *.ko .*.cmd .*.flags *.mod.c - --include $(KDIR)/Rules.make diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h deleted file mode 100644 index f93fef5d2274..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h +++ /dev/null @@ -1,424 +0,0 @@ -/**************************************************************************//** - * @file bodydef.h - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - ******************************************************************************/ - -#ifndef __BODYDEF_H -#define __BODYDEF_H - -struct reg_s { - __u8 RegisterName[50]; - __u16 RegAddr; -}; - -/*======================================================================= - Input/Output Ports and Data Direction Registers -=======================================================================*/ -struct reg_s cimax_reg_map[] = { - {"BUFFIN_CFG" , 0x0000}, - {"BUFFIN_ADDR_LSB" , 0x0001}, - {"BUFFIN_ADDR_MSB" , 0x0002}, - {"BUFFIN_DATA" , 0x0003}, - {"BUFFOUT_CFG" , 0x0004}, - {"BUFFOUT_ADDR_LSB" , 0x0005}, - {"BUFFOUT_ADDR_MSB" , 0x0006}, - {"BUFFOUT_DATA" , 0x0007}, - {"BOOT_Key" , 0x0008}, - {"BOOT_Status" , 0x0009}, - {"BOOT_Test " , 0x000A}, - {"RxDMA_Ctrl" , 0x0010}, - {"RxDMA_Status" , 0x0011}, - {"RxDMA_DbgL" , 0x0012}, - {"RxDMA_DbgH" , 0x0013}, - {"SPI_Slave_Ctrl" , 0x0018}, - {"SPI_Slave_Status" , 0x0019}, - {"SPI_Slave_Rx" , 0x001A}, - {"SPI_Slave_Tx" , 0x001B}, - {"SPI_Slave_Mask" , 0x001C}, - {"UCSG_Ctrl" , 0x0020}, - {"UCSG_Status" , 0x0021}, - {"UCSG_RxData" , 0x0022}, - {"UCSG_TxData" , 0x0023}, - {"PCtrl_Ctrl" , 0x0028}, - {"PCtrl_Status" , 0x0029}, - {"PCtrl_NbByte_LSB" , 0x002A}, - {"PCtrl_NbByte_MSB" , 0x002B}, - {"SPI_Master_Ctl" , 0x0030}, - {"SPI_Master_NCS" , 0x0031}, - {"SPI_Master_Status" , 0x0032}, - {"SPI_Master_TxBuf" , 0x0033}, - {"SPI_Master_RxBuf" , 0x0034}, - {"BISTRAM_Ctl" , 0x0038}, - {"BISTRAM_Bank" , 0x0039}, - {"BISTRAM_Pat" , 0x003A}, - {"BISTRAM_SM" , 0x003B}, - {"BISTRAM_AddrLSB" , 0x003C}, - {"BISTROM_Config" , 0x0040}, - {"BISTROM_SignatureLSB" , 0x0041}, - {"BISTROM_SignatureMSB" , 0x0042}, - {"BISTROM_StartAddrLSB" , 0x0043}, - {"BISTROM_StartAddrMSB" , 0x0044}, - {"BISTROM_StopAddrLSB" , 0x0045}, - {"BISTROM_StopAddrMSB" , 0x0046}, - {"CkMan_Config" , 0x0048}, - {"CkMan_Select" , 0x0049}, - {"CkMan_Test" , 0x004A}, - {"Revision_Number" , 0x004B}, - {"CkMan_PD_Key" , 0x004C}, - {"USB_Power_Mode" , 0x004D}, - {"ResMan_Config" , 0x0050}, - {"ResMan_Status" , 0x0051}, - {"ResMan_WD" , 0x0052}, - {"ResMan_WD_MSB" , 0x0053}, - {"TxDMA_Ctrl" , 0x0058}, - {"TxDMA_Status" , 0x0059}, - {"TxDMA_StartAddrL" , 0x005A}, - {"TxDMA_StartAddrH" , 0x005B}, - {"TxDMA_StopAddrL" , 0x005C}, - {"TxDMA_StopAddrH" , 0x005D}, - {"CPU_Test" , 0x0060}, - {"IrqMan_Config0" , 0x0068}, - {"IrqMan_Config1" , 0x0069}, - {"IrqMan_Irq0" , 0x006A}, - {"IrqMan_NMI" , 0x006B}, - {"IrqMan_SleepKey" , 0x006C}, - {"Tim_Config" , 0x0070}, - {"Tim_Value_LSB" , 0x0071}, - {"Tim_Value_MSB" , 0x0072}, - {"Tim_Comp_LSB" , 0x0073}, - {"Tim_Comp_MSB" , 0x0074}, - {"TI_Config" , 0x0076}, - {"TI_Data" , 0x0077}, - {"TI_Reg0" , 0x0078}, - {"TI_Reg1" , 0x0079}, - {"TI_Reg2" , 0x007A}, - {"TI_Reg3" , 0x007B}, - {"TI_Reg4" , 0x007C}, - {"TI_ROM1" , 0x007D}, - {"TI_ROM2" , 0x007E}, - {"TI_ROM3" , 0x007F}, - {"DVBCI_START_ADDR" , 0x0100}, - {"DVBCI_END_ADDR" , 0x017F}, - {"DATA" , 0x0180}, - {"CTRL" , 0x0181}, - {"QB_HOST" , 0x0182}, - {"LEN_HOST_LSB" , 0x0183}, - {"LEN_HOST_MSB" , 0x0184}, - {"FIFO_TX_TH_LSB" , 0x0185}, - {"FIFO_TX_TH_MSB" , 0x0186}, - {"FIFO_TX_D_NB_LSB" , 0x0187}, - {"FIFO_TX_D_NB_MSB" , 0x0188}, - {"QB_MOD_CURR" , 0x0189}, - {"LEN_MOD_CURR_LSB" , 0x018A}, - {"LEN_MOD_CURR_MSB" , 0x018B}, - {"QB_MOD" , 0x018C}, - {"LEN_MOD_LSB" , 0x018D}, - {"LEN_MOD_MSB" , 0x018E}, - {"FIFO_RX_TH_LSB" , 0x018F}, - {"FIFO_RX_TH_MSB" , 0x0190}, - {"FIFO_RX_D_NB_LSB" , 0x0191}, - {"FIFO_RX_D_NB_MSB" , 0x0192}, - {"IT_STATUS_0" , 0x0193}, - {"IT_STATUS_1" , 0x0194}, - {"IT_MASK_0" , 0x0195}, - {"IT_MASK_1" , 0x0196}, - {"IT_HOST_PIN_CFG" , 0x0200}, - {"CFG_0" , 0x0201}, - {"CFG_1" , 0x0202}, - {"CFG_2" , 0x0203}, - {"IT_HOST" , 0x0204}, - {"MOD_IT_STATUS" , 0x0205}, - {"MOD_IT_MASK" , 0x0206}, - {"MOD_CTRL_A" , 0x0207}, - {"MOD_CTRL_B" , 0x0208}, - {"DEST_SEL" , 0x0209}, - {"CAM_MSB_ADD" , 0x020A}, - {"GPIO0_DIR" , 0x020B}, - {"GPIO0_DATA_IN" , 0x020C}, - {"GPIO0_DATA_OUT" , 0x020D}, - {"GPIO0_STATUS" , 0x020E}, - {"GPIO0_IT_MASK" , 0x020F}, - {"GPIO0_DFT" , 0x0210}, - {"GPIO0_MASK_DATA" , 0x0211}, - {"GPIO1_DIR" , 0x0212}, - {"GPIO1_DATA_IN" , 0x0213}, - {"GPIO1_DATA_OUT" , 0x0214}, - {"GPIO1_STATUS" , 0x0215}, - {"GPIO1_IT_MASK" , 0x0216}, - {"MEM_ACC_TIME_A" , 0x0217}, - {"MEM_ACC_TIME_B" , 0x0218}, - {"IO_ACC_TIME_A" , 0x0219}, - {"IO_ACC_TIME_B" , 0x021A}, - {"EXT_CH_ACC_TIME_A" , 0x021B}, - {"EXT_CH_ACC_TIME_B" , 0x021C}, - {"PAR_IF_0" , 0x021D}, - {"PAR_IF_1" , 0x021E}, - {"PAR_IF_CTRL" , 0x021F}, - {"PCK_LENGTH" , 0x0220}, - {"USB2TS_CTRL" , 0x0221}, - {"USB2TS0_RDL" , 0x0222}, - {"USB2TS1_RDL" , 0x0223}, - {"TS2USB_CTRL" , 0x0224}, - {"TSOUT_PAR_CTRL" , 0x0225}, - {"TSOUT_PAR_CLK_SEL" , 0x0226}, - {"S2P_CH0_CTRL" , 0x0227}, - {"S2P_CH1_CTRL" , 0x0228}, - {"P2S_CH0_CTRL" , 0x0229}, - {"P2S_CH1_CTRL" , 0x022A}, - {"TS_IT_STATUS" , 0x022B}, - {"TS_IT_MASK" , 0x022C}, - {"IN_SEL" , 0x022D}, - {"OUT_SEL" , 0x022E}, - {"ROUTER_CAM_CH" , 0x022F}, - {"ROUTER_CAM_MOD" , 0x0230}, - {"FIFO_CTRL" , 0x0231}, - {"FIFO1_2_STATUS" , 0x0232}, - {"FIFO3_4_STATUS" , 0x0233}, - {"GAP_REMOVER_CH0_CTRL" , 0x0234}, - {"GAP_REMOVER_CH1_CTRL" , 0x0235}, - {"SYNC_RTV_CTRL" , 0x0236}, - {"SYNC_RTV_CH0_SYNC_NB" , 0x0237}, - {"SYNC_RTV_CH0_PATTERN" , 0x0238}, - {"SYNC_RTV_CH1_SYNC_NB" , 0x0239}, - {"SYNC_RTV_CH1_PATTERN" , 0x023A}, - {"SYNC_RTV_OFFSET_PATT" , 0x023B}, - {"CTRL_FILTER" , 0x023D}, - {"PID_EN_FILTER_CH0" , 0x023E}, - {"PID_EN_FILTER_CH1" , 0x023F}, - {"PID_LSB_FILTER_CH0_0" , 0x0240}, - {"PID_MSB_FILTER_CH0_0" , 0x0241}, - {"PID_LSB_FILTER_CH0_1" , 0x0242}, - {"PID_MSB_FILTER_CH0_1" , 0x0243}, - {"PID_LSB_FILTER_CH0_2" , 0x0244}, - {"PID_MSB_FILTER_CH0_2" , 0x0245}, - {"PID_LSB_FILTER_CH0_3" , 0x0246}, - {"PID_MSB_FILTER_CH0_3" , 0x0247}, - {"PID_LSB_FILTER_CH0_4" , 0x0248}, - {"PID_MSB_FILTER_CH0_4" , 0x0249}, - {"PID_LSB_FILTER_CH0_5" , 0x024A}, - {"PID_MSB_FILTER_CH0_5" , 0x024B}, - {"PID_LSB_FILTER_CH0_6" , 0x024C}, - {"PID_MSB_FILTER_CH0_6" , 0x024D}, - {"PID_LSB_FILTER_CH0_7" , 0x024E}, - {"PID_MSB_FILTER_CH0_7" , 0x024F}, - {"PID_LSB_FILTER_CH1_0" , 0x0260}, - {"PID_MSB_FILTER_CH1_0" , 0x0261}, - {"PID_LSB_FILTER_CH1_1" , 0x0262}, - {"PID_MSB_FILTER_CH1_1" , 0x0263}, - {"PID_LSB_FILTER_CH1_2" , 0x0264}, - {"PID_MSB_FILTER_CH1_2" , 0x0265}, - {"PID_LSB_FILTER_CH1_3" , 0x0266}, - {"PID_MSB_FILTER_CH1_3" , 0x0267}, - {"PID_LSB_FILTER_CH1_4" , 0x0268}, - {"PID_MSB_FILTER_CH1_4" , 0x0269}, - {"PID_LSB_FILTER_CH1_5" , 0x026A}, - {"PID_MSB_FILTER_CH1_5" , 0x026B}, - {"PID_LSB_FILTER_CH1_6" , 0x026C}, - {"PID_MSB_FILTER_CH1_6" , 0x026D}, - {"PID_LSB_FILTER_CH1_7" , 0x026E}, - {"PID_MSB_FILTER_CH1_7" , 0x026F}, - {"PID_OLD_LSB_REMAPPER_0" , 0x0280}, - {"PID_OLD_MSB_REMAPPER_0" , 0x0281}, - {"PID_OLD_LSB_REMAPPER_1" , 0x0282}, - {"PID_OLD_MSB_REMAPPER_1" , 0x0283}, - {"PID_OLD_LSB_REMAPPER_2" , 0x0284}, - {"PID_OLD_MSB_REMAPPER_2" , 0x0285}, - {"PID_OLD_LSB_REMAPPER_3" , 0x0286}, - {"PID_OLD_MSB_REMAPPER_3" , 0x0287}, - {"PID_OLD_LSB_REMAPPER_4" , 0x0288}, - {"PID_OLD_MSB_REMAPPER_4" , 0x0289}, - {"PID_OLD_LSB_REMAPPER_5" , 0x028A}, - {"PID_OLD_MSB_REMAPPER_5" , 0x028B}, - {"PID_OLD_LSB_REMAPPER_6" , 0x028C}, - {"PID_OLD_MSB_REMAPPER_6" , 0x028D}, - {"PID_OLD_LSB_REMAPPER_7" , 0x028E}, - {"PID_OLD_MSB_REMAPPER_7" , 0x028F}, - {"PID_NEW_LSB_REMAPPER_0" , 0x02A0}, - {"PID_NEW_MSB_REMAPPER_0" , 0x02A1}, - {"PID_NEW_LSB_REMAPPER_1" , 0x02A2}, - {"PID_NEW_MSB_REMAPPER_1" , 0x02A3}, - {"PID_NEW_LSB_REMAPPER_2" , 0x02A4}, - {"PID_NEW_MSB_REMAPPER_2" , 0x02A5}, - {"PID_NEW_LSB_REMAPPER_3" , 0x02A6}, - {"PID_NEW_MSB_REMAPPER_3" , 0x02A7}, - {"PID_NEW_LSB_REMAPPER_4" , 0x02A8}, - {"PID_NEW_MSB_REMAPPER_4" , 0x02A9}, - {"PID_NEW_LSB_REMAPPER_5" , 0x02AA}, - {"PID_NEW_MSB_REMAPPER_5" , 0x02AB}, - {"PID_NEW_LSB_REMAPPER_6" , 0x02AC}, - {"PID_NEW_MSB_REMAPPER_6" , 0x02AD}, - {"PID_NEW_LSB_REMAPPER_7" , 0x02AE}, - {"PID_NEW_MSB_REMAPPER_7" , 0x02AF}, - {"MERGER_DIV_MICLK" , 0x02C0}, - {"PID_AND_SYNC_REMAPPER_CTRL" , 0x02C1}, - {"PID_EN_REMAPPER" , 0x02C2}, - {"SYNC_SYMBOL" , 0x02C3}, - {"PID_AND_SYNC_REMAPPER_INV_CTRL" , 0x02C4}, - {"BITRATE_CH0_LSB" , 0x02C5}, - {"BITRATE_CH0_MSB" , 0x02C6}, - {"BITRATE_CH1_LSB" , 0x02C7}, - {"BITRATE_CH1_MSB" , 0x02C8}, - {"STATUS_CLK_SWITCH_0" , 0x02C9}, - {"STATUS_CLK_SWITCH_1" , 0x02CA}, - {"RESET_CLK_SWITCH_0" , 0x02CB}, - {"RESET_CLK_SWITCH_1" , 0x02CC}, - {"PAD_DRVSTR_CTRL" , 0x02CD}, - {"PAD_PUPD_CTRL" , 0x02CE}, - {"PRE_HEADER_ADDER_CH0_0" , 0x02D0}, - {"PRE_HEADER_ADDER_CH0_1" , 0x02D1}, - {"PRE_HEADER_ADDER_CH0_2" , 0x02D2}, - {"PRE_HEADER_ADDER_CH0_3" , 0x02D3}, - {"PRE_HEADER_ADDER_CH0_4" , 0x02D4}, - {"PRE_HEADER_ADDER_CH0_5" , 0x02D5}, - {"PRE_HEADER_ADDER_CH0_6" , 0x02D6}, - {"PRE_HEADER_ADDER_CH0_7" , 0x02D7}, - {"PRE_HEADER_ADDER_CH0_8" , 0x02D8}, - {"PRE_HEADER_ADDER_CH0_9" , 0x02D9}, - {"PRE_HEADER_ADDER_CH0_10" , 0x02DA}, - {"PRE_HEADER_ADDER_CH0_11" , 0x02DB}, - {"PRE_HEADER_ADDER_CH1_0" , 0x02E0}, - {"PRE_HEADER_ADDER_CH1_1" , 0x02E1}, - {"PRE_HEADER_ADDER_CH1_2" , 0x02E2}, - {"PRE_HEADER_ADDER_CH1_3" , 0x02E3}, - {"PRE_HEADER_ADDER_CH1_4" , 0x02E4}, - {"PRE_HEADER_ADDER_CH1_5" , 0x02E5}, - {"PRE_HEADER_ADDER_CH1_6" , 0x02E6}, - {"PRE_HEADER_ADDER_CH1_7" , 0x02E7}, - {"PRE_HEADER_ADDER_CH1_8" , 0x02E8}, - {"PRE_HEADER_ADDER_CH1_9" , 0x02E9}, - {"PRE_HEADER_ADDER_CH1_10" , 0x02EA}, - {"PRE_HEADER_ADDER_CH1_11" , 0x02EB}, - {"PRE_HEADER_ADDER_CTRL" , 0x02EC}, - {"PRE_HEADER_ADDER_LEN" , 0x02ED}, - {"PRE_HEADER_REMOVER_CTRL" , 0x02EE}, - {"FSM_DVB" , 0x02F0}, - {"TS2USB_FSM_DEBUG" , 0x02F2}, - {"TSOUT_PAR_FSM_DEBUG" , 0x02F3}, - {"GAP_REMOVER_FSM_DEBUG" , 0x02F4}, - {"PID_AND_SYNC_REMAPPER_FSM_DEBUG" , 0x02F5}, - {"PRE_HEADER_ADDER_FSM_DEBUG" , 0x02F6}, - {"SYNC_RTV_FSM_DEBUG" , 0x02F7}, - {"CHECK_PHY_CLK" , 0x0E00}, - {"CONTROL1" , 0x0E01}, - {"WAKE_UP" , 0x0E02}, - {"CONTROL2" , 0x0E03}, - {"PHY_RELATED" , 0x0E04}, - {"EP_CFG" , 0x0E05}, - {"MAX_PKT_EP1L" , 0x0E06}, - {"MAX_PKT_EP1H" , 0x0E07}, - {"MAX_PKT_EP2L" , 0x0E08}, - {"MAX_PKT_EP2H" , 0x0E09}, - {"MAX_PKT_EP3L" , 0x0E0A}, - {"MAX_PKT_EP3H" , 0x0E0B}, - {"MAX_PKT_EP4L" , 0x0E0C}, - {"MAX_PKT_EP4H" , 0x0E0D}, - {"EPS_STALL_SET" , 0x0E10}, - {"EPS_STALL_CLR" , 0x0E11}, - {"EPS_ENABLE" , 0x0E12}, - {"DMA_ACC_EPS" , 0x0E13}, - {"CPU_ACC_EPS_EN" , 0x0E14}, - {"SETUP_BYTE0" , 0x0E15}, - {"SETUP_BYTE1" , 0x0E16}, - {"SETUP_BYTE2" , 0x0E17}, - {"SETUP_BYTE3" , 0x0E18}, - {"SETUP_BYTE4" , 0x0E19}, - {"SETUP_BYTE5" , 0x0E1A}, - {"SETUP_BYTE6" , 0x0E1B}, - {"SETUP_BYTE7" , 0x0E1C}, - {"SETUP_DT_VLD" , 0x0E1D}, - {"CLR_EPS_TOG" , 0x0E1E}, - {"EP0_CTRL" , 0x0E20}, - {"EP0_DATA_CNT" , 0x0E21}, - {"EP0_DATA" , 0x0E22}, - {"EP1_CTRL" , 0x0E30}, - {"EP1_DATA_CNTL" , 0x0E31}, - {"EP1_DATA_CNTH" , 0x0E32}, - {"EP1_DATA" , 0x0E33}, - {"EP1_HEADER" , 0x0E34}, - {"EP2_CTRL" , 0x0E40}, - {"EP2_DATA_CNTL" , 0x0E41}, - {"EP2_DATA_CNTH" , 0x0E42}, - {"EP2_DATA" , 0x0E43}, - {"EP2_HEADER" , 0x0E44}, - {"EP3_DATA_CNTL" , 0x0E50}, - {"EP3_DATA_CNTH" , 0x0E51}, - {"EP3_DATA" , 0x0E52}, - {"EP3_HEADER" , 0x0E53}, - {"EP3_HEADER_CNT" , 0x0E54}, - {"EP3_HEADER_DATA" , 0x0E55}, - {"EP4_DATA_CNTL" , 0x0E60}, - {"EP4_DATA_CNTH" , 0x0E61}, - {"EP4_DATA" , 0x0E62}, - {"EP4_HEADER" , 0x0E63}, - {"EP4_HEADER_CNT" , 0x0E64}, - {"EP4_HEADER_DATA" , 0x0E65}, - {"EP5_CTRL" , 0x0E70}, - {"EP5_DATA_CNTL" , 0x0E71}, - {"EP5_DATA_CNTH" , 0x0E72}, - {"EP5_DATA" , 0x0E73}, - {"MAX_PKT_EP5L" , 0x0E74}, - {"MAX_PKT_EP5H" , 0x0E75}, - {"EP6_DATA_CNTL" , 0x0E80}, - {"EP6_DATA_CNTH" , 0x0E81}, - {"EP6_DATA" , 0x0E82}, - {"MAX_PKT_EP6L" , 0x0E83}, - {"MAX_PKT_EP6H" , 0x0E84}, - {"FRAME_NUML" , 0x0E90}, - {"FRAME_NUMH" , 0x0E91}, - {"FRAME_TIMEL" , 0x0E92}, - {"FRAME_TIMEH" , 0x0E93}, - {"STC_DIVL" , 0x0E94}, - {"STC_DIVM" , 0x0E95}, - {"STC_DIVH" , 0x0E96}, - {"USB_STATUS" , 0x0E97}, - {"DEV_STATE1" , 0x0E98}, - {"DEV_STATE2" , 0x0E99}, - {"DEV_STATE3" , 0x0E9A}, - {"DEV_STATE4" , 0x0E9B}, - {"INTR_EN1" , 0x0EA0}, - {"INTR_EN2" , 0x0EA1}, - {"INTR_EN3" , 0x0EA2}, - {"INTR_EN4" , 0x0EA3}, - {"INTR_SRC1" , 0x0EB0}, - {"INTR_SRC2" , 0x0EB1}, - {"INTR_SRC3" , 0x0EB2}, - {"INTR_SRC4" , 0x0EB3}, - {"INTR_FLAG1" , 0x0EC0}, - {"INTR_FLAG2" , 0x0EC1}, - {"INTR_FLAG3" , 0x0EC2}, - {"INTR_FLAG4" , 0x0EC3}, - {"EP0_INAK_CNT" , 0x0ED0}, - {"EP0_ONAK_CNT" , 0x0ED1}, - {"EP1_NAK_CNT" , 0x0ED2}, - {"EP2_NAK_CNT" , 0x0ED3}, - {"EP3_NAK_CNT" , 0x0ED4}, - {"EP4_NAK_CNT" , 0x0ED5}, - {"EP5_NAK_CNT" , 0x0ED6}, - {"EP6_NAK_CNT" , 0x0ED7}, - {"NAK_CNT_LEVEL" , 0x0ED8}, - {"CC2_Buffer_out" , 0x2000}, - {"CC2_Buffer_in" , 0x4000}, - {"nmb_vector_address_lsb" , 0xFFFA}, - {"nmb_vector_address_msb" , 0xFFFB}, - {"reset_vector_address_lsb" , 0xFFFC}, - {"reset_vector_address_msb" , 0xFFFD}, - {"irb_vector_address_lsb" , 0xFFFE}, - {"irb_vector_address_msb" , 0xFFFF} -}; -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c deleted file mode 100644 index 43cdcde5b8eb..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c +++ /dev/null @@ -1,2535 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb-driver.c - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - ******************************************************************************/ - -#define FRBIT -/*#define DEBUG*/ -/*#define DEBUG_BITRATE*/ -/*#define DEBUG_ISOC_IN*/ -/*#define DEBUG_ISOC_OUT*/ -/*#define DEBUG_CONTINUITY*/ - -/****************************************************************************** - * Include - ******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cimax+usb-driver.h" -#include "cimax+usb_fw.h" -#include "cimax+usb_config.h" -#ifdef TIMESTAMP -#include "cimax+usb_time.h" -#endif -#include "../../aml_cimax_usb_priv.h" - -/****************************************************************************** - * Defines - *****************************************************************************/ -#define DRIVER_VERSION "v1.1.2" -#define DRIVER_AUTHOR "Bruno Tonelli, tonelli@smardtv.com" -#define DRIVER_DESC "CIMaX+ USB Driver for Linux (c)2009-2011" - -#define DRIVER_MAX_NUMBER 1 - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); - -/****************************************************************************** - * Structures - ******************************************************************************/ -/****************************************************************************** - * Globals - ******************************************************************************/ -#ifdef FRBIT -int CimaxCfg = 1; -module_param_named(CimaxCfg, CimaxCfg, int, 0644); -MODULE_PARM_DESC(CimaxCfg, "Turn on/off configuration of CIMaX+ (default: on)"); -int CimaxDwnl = 1; -module_param_named(CimaxDwnl, CimaxDwnl, int, 0644); -MODULE_PARM_DESC(CimaxDwnl, "Enable upload of FW in CIMaX+ chip (default: on)"); -#endif - -static struct device_s *gdevice; -static unsigned int gdeviceNumber; - -static struct usb_driver device_driver; -static struct timespec gStart; - -static __u8 nullHeader[] = { - 0x47, 0x1F, 0xFF, 0x1F, 0xFA, 0xDE, 0xBA, 0xBE -}; - -static struct bulk_timer_s gbulk_timer[DEVICE_NUM_CAM]; -int (*cimax_usb_dev_add)(struct device_s *device, int id); -int (*cimax_usb_dev_remove)(struct device_s *device, int id); - -#ifdef TIMESTAMP -static int bSetTimestamps; -#endif - -/****************************************************************************** - * Functions - ******************************************************************************/ -#ifdef DEBUG_CONTINUITY -#define TS_MAXPIDS 8192 /* max value of a PID */ -unsigned char tab_cc[TS_MAXPIDS]; - -__u16 get_ts_pid(unsigned char *pid) -{ - __u16 pp = 0; - - pp = (pid[0] & 0X1f)<<8; - pp |= pid[1]; - - return pp; -} - -static void init_tab_cc(void) -{ - memset(tab_cc, 0xff, TS_MAXPIDS); -} - -static int dbg_cc(unsigned char *buf) -{ - int pid; - unsigned char cc; - - if (buf[0] != DEVICE_MPEG2_SYNC_BYTE) { - err("Out Of Sync: "); - return -1; - } - - pid = get_ts_pid(buf + 1); - - if (!(buf[3] & 0x10)) /* no payload?*/ - return 0; - - if (buf[1] & 0x80) - err("Error in TS for PID: %d\n", pid); - - /* Check continuity count*/ - cc = tab_cc[pid]; - if (cc == 255) - cc = (buf[3] & 15); - else { - cc = ((cc) + 1) & 15; - if (cc != (buf[3] & 15)) { - /* Otherwise, this is a real corruption */ - err("pid %d cc %d expected cc %d actual\n", - pid, cc, buf[3] & 15); - cc = (buf[3] & 15); - } - } - return 0; -} -#endif - -/*-------------------------------------------------------------------*/ -#ifdef DEBUG -static void dbg_dump(char *hdr, unsigned char *data, int size) -{ - int i; - char line[40]; - char str[9]; - line[0] = 0; - for (i = 0; i < size; i++) { - sprintf(line, "%s%.2x ", line, data[i]); - if ((data[i] >= 32) && (data[i] <= 126)) - str[i%8] = data[i]; - else - str[i%8] = '.'; - if (!((i+1)%8)) { - str[i%8 + 1] = 0; - dbg_s("%s %s %s", hdr, line, str); - line[0] = 0; - } /* if */ - } /* for */ - if (i%8) { - int j; - str[i%8 + 1] = 0; - for (j = (i%8); j < 8; j++) - sprintf(line, "%s ", line); - dbg_s("%s %s %s", hdr, line, str); - line[0] = 0; - } /* if */ -} /* dbg_dump */ -#else -#define dbg_dump(format, arg...) do {} while (0) -#endif /* DEBUG */ - -static unsigned long copyDataFrom(int us, - void *to, const void *from, unsigned long n) -{ - if (us) - return copy_from_user(to, from, n); - memcpy(to, from, n); - return 0; -} - -static unsigned long copyDataTo(int us, - void *to, const void *from, unsigned long n) -{ - if (us) - return copy_to_user(to, from, n); - memcpy(to, from, n); - return 0; -} - -static void vb_init(struct video_buf_s *buf) -{ - buf->readOffset = 0; - buf->writeOffset = 0; - buf->isEmpty = 1; -} /* vb_init */ - -static int vb_get_write_size(struct video_buf_s *buf) -{ - int writeSize = 0; - - if (buf->writeOffset == buf->readOffset) { - if (buf->isEmpty) - writeSize = DEVICE_VB_LENGTH; - } else if (buf->writeOffset > buf->readOffset) - writeSize = - DEVICE_VB_LENGTH - (buf->writeOffset - buf->readOffset); - else - writeSize = buf->readOffset - buf->writeOffset; - return writeSize; -} /* vb_get_write_size */ - -static int vb_write(struct video_buf_s *buf, __u8 *data, int size) -{ - int writeSize = vb_get_write_size(buf); - int firstPart = DEVICE_VB_LENGTH - buf->writeOffset; - if (size > writeSize) - size = writeSize; - - if (size < firstPart) { - memcpy(&buf->data[buf->writeOffset], data, size); - buf->writeOffset += size; - } /* if */ else { - memcpy(&buf->data[buf->writeOffset], data, firstPart); - memcpy(buf->data, &data[firstPart], size - firstPart); - buf->writeOffset = size - firstPart; - } /* else */ - - if (size > 0) - buf->isEmpty = 0; - return size; -} /* vb_write */ - -static int vb_read_next(struct video_buf_s *buf, __u8 *data) -{ - int readSize; - int firstPart; - int nextOffset; - int isStuffing; - int ret; - - readSize = DEVICE_VB_LENGTH - vb_get_write_size(buf); - nextOffset = buf->readOffset + DEVICE_MPEG2_PACKET_SIZE; - if (nextOffset >= DEVICE_VB_LENGTH) - nextOffset -= DEVICE_VB_LENGTH; - while (readSize > DEVICE_MPEG2_PACKET_SIZE) { - if ((buf->data[buf->readOffset] == DEVICE_MPEG2_SYNC_BYTE) && - (buf->data[nextOffset] == DEVICE_MPEG2_SYNC_BYTE)) { - /* packet in sync */ - break; - } /* if */ - buf->readOffset++; - if (buf->readOffset == DEVICE_VB_LENGTH) - buf->readOffset = 0; - nextOffset++; - if (nextOffset == DEVICE_VB_LENGTH) - nextOffset = 0; - readSize--; - } /* while */ - if (readSize <= DEVICE_MPEG2_PACKET_SIZE) { - buf->isEmpty = 1; - return 0; - } /* if */ - - /* packet is in sync, check if it is a stuffing packet */ - isStuffing = 0; - firstPart = DEVICE_VB_LENGTH - buf->readOffset; - if (firstPart < DEVICE_NULL_HEADER_SIZE) { - if ((memcmp(nullHeader, &buf->data[buf->readOffset], firstPart) - == 0) && - (memcmp(&nullHeader[firstPart], buf->data, - DEVICE_NULL_HEADER_SIZE - firstPart) - == 0)) { - isStuffing = 1; - } /* if */ - } /* if */ - else { - if (memcmp(nullHeader, &buf->data[buf->readOffset], - DEVICE_NULL_HEADER_SIZE) == 0) { - isStuffing = 1; - } /* if */ - } /* else */ - readSize -= DEVICE_MPEG2_PACKET_SIZE; - if (readSize <= DEVICE_MPEG2_PACKET_SIZE) - buf->isEmpty = 1; - - /* skip stuffing packet */ - if (isStuffing) { - buf->readOffset = nextOffset; - return 0; - } /* if */ - - /* copy packet to user space */ - if (firstPart >= DEVICE_MPEG2_PACKET_SIZE) { - ret = copy_to_user(data, - &buf->data[buf->readOffset], DEVICE_MPEG2_PACKET_SIZE); - } /* if */ else { - ret = copy_to_user(data, - &buf->data[buf->readOffset], firstPart); - ret = copy_to_user(&data[firstPart], - buf->data, DEVICE_MPEG2_PACKET_SIZE - firstPart); - } /* else */ - buf->readOffset = nextOffset; - return DEVICE_MPEG2_PACKET_SIZE; -} /* vb_read_next */ - -/*-------------------------------------------------------------------*/ -#ifdef DEBUG_BITRATE -static void print_bitrate(struct ts_channel_s *channel, __u8 channel_number) -{ - int readSize; - ktime_t currentTime; - int diffTime_us; - int bitrate; - - currentTime = ktime_get_real(); - if (!(channel->bitrateTime.tv64)) { - channel->bitrateTime = currentTime; - } else { - readSize = DEVICE_VB_LENGTH - vb_get_write_size(&channel->inVb); - dbg("%d bytes received\n", readSize); - diffTime_us = (int)(ktime_us_delta(currentTime, - channel->bitrateTime)); - if (diffTime_us) { - bitrate = (int)((readSize * 8 * USEC_PER_SEC) - / diffTime_us); - } - channel->bitrateTime = currentTime; - dbg("received bitrate for channel[%d] = %dbps\n", - channel_number, bitrate); - } -} -#endif /* DEBUG_BITRATE */ -/*-------------------------------------------------------------------*/ - -static void device_cibulk_complete(struct urb *urb) -{ - dbg("start"); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - dbg("end"); -} /* device_cibulk_complete */ - -static int device_cibulk_send(struct device_s *device, - struct ioctl_data_s *data, - int user_space) -{ - int res; - struct urb *urb; - int size; - int index = -1; - __u8 *ptr; - __u32 todo = data->txSize; - __u8 *userData = data->txData; - - dbg("start"); - - do { - /* get a free bulk message */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - err("alloc urb"); - return -ENOMEM; - } /* if */ - urb->dev = device->usbdev; - - /* allocate bulk data */ - size = device->ciBulk.outMaxPacketSize; - if (todo < size) - size = todo; - urb->transfer_buffer = kmalloc(size, GFP_KERNEL); - if (!urb->transfer_buffer) { - err("alloc transfer buffer"); - usb_free_urb(urb); - return -ENOMEM; - } /* if */ - - /* copy data */ - ptr = urb->transfer_buffer; - res = copyDataFrom(user_space, ptr, userData, size); - -#ifdef TIMESTAMP - if (bSetTimestamps) { - if (index == -1) { - SetTimestamp("urb %x, toSend %d, send %d", - urb, todo, size); - SetTimestamp("cmd 0x%02x", ptr[0]); - } else { - SetTimestamp("urb %x, toSend %d, send %d", - urb, todo, size); - } - } -#endif - - /* first packet, get index */ - if (index == -1) { - if ((ptr[DEVICE_COMMAND_OFFSET] == DEVICE_CMD_INIT) || - (ptr[DEVICE_COMMAND_OFFSET] - == DEVICE_CMD_WRITE_REG) || - (ptr[DEVICE_COMMAND_OFFSET] - == DEVICE_CMD_READ_REG)) { - index = 0; /* register command, no module */ - } else if (ptr[DEVICE_COMMAND_OFFSET] - & DEVICE_SEL_MASK) { - index = 1; /* module B */ - } else { - index = 0; /* module A */ - } /* else */ - device->ciBulk.ciData[index].syncDataSize = 0; - device->ciBulk.ciData[index].syncSignal = 0; - } /* if */ - - /* submit bulk */ - urb->pipe = usb_sndbulkpipe(device->usbdev, - DEVICE_BULK_OUT_PIPE); - urb->transfer_buffer_length = size; - urb->complete = device_cibulk_complete; - urb->context = NULL; - dbg_dump("txBuf", urb->transfer_buffer, - urb->transfer_buffer_length); - res = usb_submit_urb(urb, GFP_KERNEL); - if (res < 0) { - err("submit urb res = %d", res); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return -ENOMEM; - } /* if */ - todo -= size; - userData += size; - } while (todo); - - device->ciBulk.ciData[index].bPendingSend = 1; - dbg("end"); - return index; -} /* device_cibulk_send */ - -static void device_int_complete(struct urb *urb) -{ - unsigned long flags; - struct device_s *device = urb->context; - __u8 *dataToCopy; - int sizeToCopy, SizeReceived; - __u8 isFirstPacket = 0; - __u8 isLastPacket = 0; - __u8 index, i; - __u8 status; - struct message_node_s *message; - - dbg("start"); - - if (urb->status) { - dbg("urb status %d, not submitted again", urb->status); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { - if (device->ciBulk.intUrb[i] == urb) - device->ciBulk.intUrb[i] = NULL; - } - return; - } /* if */ - - spin_lock_irqsave(&device->ciBulk.intUrbLock, flags); - dbg("urb status %d, transfer_buffer_length %d actual_length %d", - urb->status, - urb->transfer_buffer_length, - urb->actual_length); - dataToCopy = urb->transfer_buffer; - SizeReceived = urb->actual_length; - dbg_dump("total rxBuf", dataToCopy, SizeReceived); - - - do { - if (device->ciBulk.intSizeToReceive == 0) { - if (!dataToCopy[DEVICE_STATUS_OFFSET] && - !dataToCopy[DEVICE_LENGTH_MSB_OFFSET] && - !dataToCopy[DEVICE_LENGTH_LSB_OFFSET] && - !dataToCopy[DEVICE_COUNTER_OFFSET]){ - dbg("no data receive"); - memset(urb->transfer_buffer, - 0, urb->transfer_buffer_length); - usb_submit_urb(urb, GFP_ATOMIC); - return; - } - /* first packet, read header */ - isFirstPacket = 1; - device->ciBulk.intCurrStatus = - dataToCopy[DEVICE_STATUS_OFFSET] & - DEVICE_CMD_MASK; - if (dataToCopy[DEVICE_STATUS_OFFSET] - & DEVICE_SEL_MASK) { - device->ciBulk.intCurrIndex = 1; /* module B */ - } else { - device->ciBulk.intCurrIndex = 0; /* module A */ - } - if ((device->ciBulk.intCurrStatus == DEVICE_READ_REGOK) - || (device->ciBulk.intCurrStatus - == DEVICE_WRITE_REGOK)) { - device->ciBulk.intSizeToReceive = - dataToCopy[DEVICE_LENGTH_LSB_OFFSET] + - DEVICE_DATA_OFFSET; - } else { - device->ciBulk.intSizeToReceive = - dataToCopy[DEVICE_LENGTH_MSB_OFFSET] * 256 - + dataToCopy[DEVICE_LENGTH_LSB_OFFSET] - + DEVICE_DATA_OFFSET; - } - } /* if */ - - /* get last packet state */ - status = device->ciBulk.intCurrStatus; - index = device->ciBulk.intCurrIndex; - sizeToCopy = device->ciBulk.intSizeToReceive; - if (sizeToCopy > urb->actual_length) { - /* limit size to received buffer size */ - sizeToCopy = urb->actual_length; - } /* if */ else - isLastPacket = 1; - dbg_dump("rxBuf", dataToCopy, sizeToCopy); - -#ifndef FRBIT - if (status == DEVICE_DATAREADY) { - if (device->ciBulk.ciData[index].bPendingSend) - status = DEVICE_DATAREADY_SYNC; - } -#endif - -#ifdef TIMESTAMP - if (device->ciBulk.intSizeToReceive > 2000) - bSetTimestamps = 1; - if (bSetTimestamps) { - SetTimestamp("urb %x,toReceive %d,received %d,toCopy%d", - urb, - device->ciBulk.intSizeToReceive, - SizeReceived, - sizeToCopy); - SetTimestamp("status 0x%02x, camIndex %d, isLast %d", - status, index, isLastPacket); - } -#endif - - switch (status) { - case DEVICE_INITOK: - case DEVICE_READ_REGOK: - case DEVICE_WRITE_REGOK: - index = 0; - case DEVICE_CAMRESETOK: - /*only for debug*/ - if (!dataToCopy[DEVICE_STATUS_OFFSET] && - !dataToCopy[DEVICE_LENGTH_MSB_OFFSET] && - !dataToCopy[DEVICE_LENGTH_LSB_OFFSET] && - !dataToCopy[DEVICE_COUNTER_OFFSET]){ - break; - } - case DEVICE_CISOK: - case DEVICE_WRITECOROK: - case DEVICE_NEGOTIATEOK: - case DEVICE_WRITELPDUOK: - case DEVICE_WRITELPDUBUSY: - case DEVICE_READLPDUOK: - case DEVICE_WRITEEXTOK: - case DEVICE_READEXTOK: - case DEVICE_NO_CAM: - case DEVICE_NOK: - case DEVICE_MCARD_WRITEOK: - case DEVICE_CAMPARSE_ERROR: - case DEVICE_CMDPENDING: - case DEVICE_REGSTATUSOK: - case DEVICE_DATAREADY_SYNC: - /* copy partial message */ - spin_lock_irqsave(&device->ciBulk.intLock, - flags); - memcpy(&device->ciBulk.ciData[index]. - syncData[device->ciBulk.ciData[index]. - syncDataSize], - dataToCopy, sizeToCopy); - device->ciBulk.intSizeToReceive -= sizeToCopy; - device->ciBulk.ciData[index].syncDataSize += - sizeToCopy; - spin_unlock_irqrestore(&device->ciBulk.intLock, - flags); - dbg("copied %d bytes at offset %d", sizeToCopy, - device->ciBulk.ciData[index]. - syncDataSize - sizeToCopy); - - if (isLastPacket) { - /* last packet received, sync message */ - device->ciBulk.ciData[index].syncSignal = 1; - wake_up_interruptible(&device->ciBulk. - ciData[index].syncWait); - device->ciBulk.ciData[index].bPendingSend = 0; - dbg("sync signal return %d %d ", - device->ciBulk.ciData[index]. - syncDataSize, index); - } /* if */ - break; - case DEVICE_CAMDET: - case DEVICE_DATAREADY: - case DEVICE_MCARD_READ: - case DEVICE_FRBit: - if (isFirstPacket) { - /* create new async message */ - message = kmalloc(sizeof(struct message_node_s), - GFP_ATOMIC); - if (!message) { - err("cannot allocate async message"); - break; - } - memset(message, - 0, sizeof(struct message_node_s)); - list_add_tail(&message->node, - &device->ciBulk.ciData[index]. - asyncDataList); - } /* if */ - else { - /* get tail message */ - message = list_entry((device->ciBulk. - ciData[index].asyncDataList.prev), - struct message_node_s, node); - } /* else */ - - /* copy partial message */ - spin_lock_irqsave(&device->ciBulk.intLock, flags); - memcpy(&message->data[message->size], - dataToCopy, sizeToCopy); - device->ciBulk.intSizeToReceive -= sizeToCopy; - message->size += sizeToCopy; - spin_unlock_irqrestore(&device->ciBulk.intLock, flags); - dbg("async copied %d bytes at offset %d", sizeToCopy, - message->size - sizeToCopy); - - if (isLastPacket) { - /* last packet received, signal async message */ - wake_up_interruptible(&device->ciBulk. - ciData[index].asyncWait); - dbg("async signal %d", index); - } /* if */ - break; - case DEVICE_GPIOCHANGE: - info("GPIO change %x %x %x", - status, dataToCopy[4], dataToCopy[5]); - device->ciBulk.intSizeToReceive -= sizeToCopy; - break; - default: - err("unknown status 0x%2x", status); - break; - } /* switch */ - dataToCopy += sizeToCopy; - SizeReceived -= sizeToCopy; - - } while (SizeReceived > 0); - - memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); - usb_submit_urb(urb, GFP_ATOMIC); - -#ifdef TIMESTAMP - /*if (bSetTimestamps) { - SetTimestamp("urb %x submitted", urb); - }*/ -#endif - - spin_unlock_irqrestore(&device->ciBulk.intUrbLock, flags); - - dbg("end"); -} /* device_int_complete */ - -static int device_wait_sync_data(struct device_s *device, - __u8 index, - struct ioctl_data_s *data, - int user_space) -{ - unsigned long flags; - int ret; - - dbg("start %d", index); - - spin_lock_irqsave(&device->ciBulk.intLock, flags); - while (device->ciBulk.ciData[index].syncSignal == 0) { - /* nothing to copy */ - spin_unlock_irqrestore(&device->ciBulk.intLock, flags); - if (wait_event_interruptible(device->ciBulk. - ciData[index].syncWait, - device->ciBulk.ciData[index].syncSignal)) { - device->ciBulk.ciData[index].bPendingSend = 0; - err("interrupt"); - return -ERESTARTSYS; - /* signal: tell the fs layer to handle it */ - } /* if */ - /* otherwise loop, but first reacquire the lock */ - spin_lock_irqsave(&device->ciBulk.intLock, flags); - } /* while */ - - /* copy packet to user space buffer */ - if (device->ciBulk.ciData[index].syncDataSize < data->rxSize) - /* truncate returned message against user buffer size */ - data->rxSize = device->ciBulk.ciData[index].syncDataSize; - spin_unlock_irqrestore(&device->ciBulk.intLock, flags); - /* release the lock */ - ret = copyDataTo(user_space, - data->rxData, - device->ciBulk.ciData[index].syncData, data->rxSize); - dbg_dump("userMsg", - device->ciBulk.ciData[index].syncData, data->rxSize); - dbg("userRet %d", data->rxSize); - device->ciBulk.ciData[index].syncDataSize = 0; - device->ciBulk.ciData[index].syncSignal = 0; - - dbg("end"); - return 0; -} /* device_wait_sync_data */ - -static int device_wait_async_data(struct device_s *device, - __u8 index, - struct rw_data_s *data, - int user_space) -{ - struct list_head *item; - struct message_node_s *message; - unsigned long flags; - int ret; - - dbg("start %d", index); - - if ((device->askToRelease) || (device->askToSuspend)) { - err("ask to release or ask to suspend"); - return -EINTR; /* device close interrupt */ - } /* if */ - - if (index >= DEVICE_NUM_CAM) { - err("bad index(%d)", index); - return -EINVAL; - } - - spin_lock_irqsave(&device->ciBulk.intLock, flags); - while (list_empty(&device->ciBulk.ciData[index].asyncDataList)) { - /* nothing to copy */ - spin_unlock_irqrestore(&device->ciBulk.intLock, flags); - /* release the lock */ - if (wait_event_interruptible(device->ciBulk. - ciData[index].asyncWait, - device->askToRelease || - device->askToSuspend || - (!list_empty(&device->ciBulk. - ciData[index].asyncDataList)))) { - err("interrupt"); - return -ERESTARTSYS; - /* signal: tell the fs layer to handle it */ - } /* if */ - if ((device->askToRelease) || (device->askToSuspend)) { - err("ask to release or ask to suspend"); - return -EINTR; /* device close interrupt */ - } /* if */ - /* otherwise loop, but first reacquire the lock */ - spin_lock_irqsave(&device->ciBulk.intLock, flags); - } /* while */ - - /* ok, data is there, return first item */ - item = device->ciBulk.ciData[index].asyncDataList.next; - message = list_entry(item, struct message_node_s, node); - if (message->size < data->size) { - /* truncate returned message against user buffer size */ - data->size = message->size; - } /* if */ - spin_unlock_irqrestore(&device->ciBulk.intLock, flags); - /* release the lock */ - ret = copyDataTo(user_space, data->data, message->data, data->size); - dbg_dump("userMsg", message->data, data->size); - dbg("userRet %d", data->size); - list_del(item); - kfree(message); - - dbg("end"); - return 0; -} /* device_wait_async_data */ - -static int device_start_intr(struct device_s *device) -{ - __u8 i, j; - struct urb *urb; - - dbg("start"); - - for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - err("alloc urb"); - return -ENOMEM; - } /* if */ - urb->transfer_buffer = - kmalloc(device->ciBulk.inMaxPacketSize, GFP_KERNEL); - if (!urb->transfer_buffer) { - err("alloc transfer buffer"); - usb_free_urb(urb); - urb = NULL; - return -ENOMEM; - } /* if */ - - urb->dev = device->usbdev; - urb->pipe = usb_rcvintpipe(device->usbdev, DEVICE_INT_IN_PIPE); - urb->transfer_buffer_length = device->ciBulk.inMaxPacketSize; - urb->complete = device_int_complete; - urb->context = device; - urb->interval = 1; - device->ciBulk.intUrb[i] = urb; - for (j = 0; j < DEVICE_NUM_CAM; j++) { - init_waitqueue_head(&device->ciBulk.ciData[j].syncWait); - init_waitqueue_head(&device->ciBulk. - ciData[j].asyncWait); - } /* for */ - usb_submit_urb(device->ciBulk.intUrb[i], GFP_KERNEL); - } - - dbg("end"); - return 0; -} /* device_start_intr */ - -static void device_stop_intr(struct device_s *device) -{ - struct list_head *item; - struct list_head *tmp; - struct message_node_s *message; - int i, j; - - dbg("start"); - - for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { - if (!device->ciBulk.intUrb[i]) - break; - usb_unlink_urb(device->ciBulk.intUrb[i]); - device->ciBulk.intUrb[i] = NULL; - for (j = 0; j < DEVICE_NUM_CAM; j++) { - for (item = device->ciBulk.ciData[j].asyncDataList.next; - item != &device->ciBulk.ciData[j].asyncDataList; - ) { - message = list_entry(item, - struct message_node_s, node); - tmp = item->next; - list_del(item); - kfree(item); - item = tmp; - } /* for */ - } /* for */ - dbg("unlink urb"); - } - - dbg("end"); -} /* device_stop_intr */ - -static void device_iso_in_complete(struct urb *urb) -{ - unsigned long flags; - struct ts_channel_s *channel = urb->context; - __u8 i; - __u8 *data; - - /*dbg("start");*/ - - if (urb->status) { - dbg("urb status %d, not submitted again", urb->status); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return; - } /* if */ - - spin_lock_irqsave(&channel->inLock, flags); - for (i = 0; i < urb->number_of_packets; i++) { - data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (!urb->iso_frame_desc[i].status && - (urb->iso_frame_desc[i].actual_length > 0)) { - if (vb_get_write_size(&channel->inVb) - >= urb->iso_frame_desc[i].actual_length) { - vb_write(&channel->inVb, data, - urb->iso_frame_desc[i].actual_length); - } /* if */ - else { - err("video buffer is full, packet loss %d", - urb->iso_frame_desc[i].actual_length); - } /* else */ - } /* if */ - else { - err("frame rejected, status %x, actual_length %d bytes", - urb->iso_frame_desc[i].status, - urb->iso_frame_desc[i].actual_length); - } - } /* for */ - spin_unlock_irqrestore(&channel->inLock, flags); - - if (!channel->inVb.isEmpty) - wake_up_interruptible(&channel->inWait); - - memset(urb->transfer_buffer, - 0, DEVICE_ISOC_LENGTH(channel->maxPacketSize)); - urb->transfer_buffer_length = - DEVICE_ISOC_LENGTH(channel->maxPacketSize); - urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; - urb->complete = device_iso_in_complete; - urb->context = channel; - urb->transfer_flags = URB_ISO_ASAP; - urb->interval = 1; - for (i = 0; i < DEVICE_NUM_FRAMES_PER_URB; i++) { - urb->iso_frame_desc[i].offset = i * channel->maxPacketSize; - urb->iso_frame_desc[i].length = channel->maxPacketSize; - } /* for */ - usb_submit_urb(urb, GFP_ATOMIC); - - /*dbg("end");*/ -} /* device_iso_in_complete */ - -static void device_tsbulk_in_complete(struct urb *urb) -{ - unsigned long flags; - struct ts_channel_s *channel = urb->context; - __u8 *data; -#ifdef DEBUG_CONTINUITY - unsigned int i; -#endif - - /*dbg("start");*/ - - if (urb->status) { - err("urb status %d(%x), not submitted again", - urb->status, urb->status); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return; - } /* if */ - - spin_lock_irqsave(&channel->inLock, flags); - data = urb->transfer_buffer; - -#ifdef DEBUG_CONTINUITY - i = 0; - /* check synchro byte*/ - while (i < urb->actual_length) { - if (!((data[i] == DEVICE_MPEG2_SYNC_BYTE) && - (data[i+DEVICE_MPEG2_PACKET_SIZE] - == DEVICE_MPEG2_SYNC_BYTE))) { - i++; - } else { - /* Synchro find*/ - break; - } - } - - /* Synchro Ok, check discontinuity*/ - while (i < urb->actual_length) { - if (dbg_cc(&data[i]) < 0) { - dbg("(actual_length= %d i=%d pkt=%d)", - urb->actual_length, - i, - i/DEVICE_MPEG2_PACKET_SIZE); - dbg("%02x %02x %02x %02x %02x %02x %02x %02x\n", - data[i-4], data[i-3], data[i-2], data[i-1], - data[i], data[i+1], data[i+2], data[i+3]); - } - i += DEVICE_MPEG2_PACKET_SIZE; - } -#endif - - if (urb->actual_length) { - channel->nbByteRead += urb->actual_length; - if (vb_get_write_size(&channel->inVb) >= urb->actual_length) - vb_write(&channel->inVb, data, urb->actual_length); - else - err("video buffer is full, packet loss %d", - urb->actual_length); - } else { - /*warn("receive size of 0\n");*/ - } - - spin_unlock_irqrestore(&channel->inLock, flags); - /* dbg("urb->actual_length=%d",urb->actual_length);*/ - /* info("urb->actual_length=%d\n",urb->actual_length);*/ - - if (!channel->inVb.isEmpty) - wake_up_interruptible(&channel->inWait); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - /*dbg("end");*/ -} /* device_tsbulk_in_complete */ - -static int device_fill_ts(struct device_s *device, - __u8 index, - struct rw_data_s *data) -{ - unsigned long flags; - __u32 copiedSize; - struct ts_channel_s *channel = &device->channel[index]; - - /*dbg("start");*/ - - spin_lock_irqsave(&channel->inLock, flags); - do { - while (channel->inVb.isEmpty) { - /* nothing to copy */ - spin_unlock_irqrestore(&channel->inLock, flags); - /* release the lock */ - if (wait_event_interruptible(channel->inWait, - device->askToRelease || - device->askToSuspend || - (!channel->inVb.isEmpty))) { - err("interrupt"); - return -ERESTARTSYS; - /* signal: tell the fs layer to handle it */ - } /* if */ - if ((device->askToRelease) || (device->askToSuspend)) { - err("ask to release or ask to suspend"); - return -EINTR; /* device close interrupt */ - } /* if */ - /* otherwise loop, but first reacquire the lock */ - spin_lock_irqsave(&channel->inLock, flags); - } /* while */ - - spin_unlock_irqrestore(&channel->inLock, flags); - - copiedSize = vb_read_next(&channel->inVb, - &data->data[data->copiedSize]); - if (copiedSize) { - /*dbg("copied %d bytes in buffer 0x%p, offset %d", - copiedSize, data->data, data->copiedSize);*/ - data->copiedSize += copiedSize; - } /* if */ - spin_lock_irqsave(&channel->inLock, flags); - } while ((data->copiedSize+DEVICE_MPEG2_PACKET_SIZE) <= data->size); - /* buffer not full */ - - spin_unlock_irqrestore(&channel->inLock, flags); - -#ifdef DEBUG_BITRATE - print_bitrate(channel, index); -#endif - - /*dbg("end, buffer 0x%p", data->data);*/ - return 0; -} /* device_fill_ts */ - -static int device_start_iso_in(struct device_s *device, __u8 index) -{ - int i, j; - int ret = 0; - struct urb *urb; - - /*dbg("start");*/ - -#ifdef DEBUG_BITRATE - device->channel[index].bitrateTime = ktime_set(0, 0); -#endif - for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { - urb = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); - device->channel[index].isocInUrb[i] = urb; - if (urb) { - /*urb->transfer_buffer = - kmalloc(DEVICE_ISOC_LENGTH, GFP_KERNEL);*/ - urb->transfer_buffer = - kmalloc(DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize), - GFP_KERNEL); - if (!urb->transfer_buffer) { - ret = -ENOMEM; - err("transfer_buffer allocation failed %d", i); - break; - } /* if */ - } /* if */ else { - ret = -ENOMEM; - err("usb_alloc_urb failed %d", i); - break; - } /* if */ - } /* for */ - - if (ret) { - /* Allocation error, must free already allocated data */ - for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { - urb = device->channel[index].isocInUrb[i]; - if (urb) { - kfree(urb->transfer_buffer); - if (urb->transfer_buffer) - urb->transfer_buffer = NULL; - usb_free_urb(urb); - device->channel[index].isocInUrb[i] = NULL; - } /* if */ - } /* for */ - return ret; - } /* if */ - - for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { - urb = device->channel[index].isocInUrb[i]; - memset(urb->transfer_buffer, - 0, - DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize)); - urb->transfer_buffer_length = - DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize); - urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; - urb->complete = device_iso_in_complete; - urb->context = &device->channel[index]; - urb->dev = device->usbdev; - urb->pipe = usb_rcvisocpipe( - device->usbdev, DEVICE_TS_IN_PIPE + index); - urb->transfer_flags = URB_ISO_ASAP; - urb->interval = 1; - for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { - urb->iso_frame_desc[j].offset = - j * device->channel[index].maxPacketSize; - urb->iso_frame_desc[j].length = - device->channel[index].maxPacketSize; - } /* for */ - } /* for */ - for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) - usb_submit_urb(device->channel[index].isocInUrb[i], GFP_KERNEL); - - /*dbg("end");*/ - return 0; -} /* device_start_iso_in */ - -static void device_stop_iso_in(struct device_s *device, __u8 index) -{ - int i; - - /*dbg("start");*/ - - for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { - if (device->channel[index].isocInUrb[i]) { - usb_unlink_urb(device->channel[index].isocInUrb[i]); - device->channel[index].isocInUrb[i] = NULL; - dbg("unlink urb %i", i); - } /* if */ - } /* for */ - - /*dbg("end");*/ -} /* device_stop_iso_in */ - -static int device_start_tsbulk_in(struct device_s *device, __u8 index) -{ - struct urb *urb; - - dbg("start"); - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb) { - urb->transfer_buffer = kmalloc(3072, GFP_KERNEL); - if (!urb->transfer_buffer) { - err("transfer_buffer allocation failed"); - usb_free_urb(urb); - return -ENOMEM; - } /* if */ - } /* if */ else { - err("usb_alloc_urb failed"); - return -ENOMEM; - } /* if */ - device->channel[index].bulkInUrb = urb; - memset(urb->transfer_buffer, 0, 3072); - urb->transfer_buffer_length = 3072; - - urb->complete = device_tsbulk_in_complete; - urb->context = &device->channel[index]; - urb->dev = device->usbdev; - urb->pipe = usb_rcvbulkpipe(device->usbdev, DEVICE_TS_IN_PIPE + index); - usb_submit_urb(device->channel[index].bulkInUrb, GFP_KERNEL); - - dbg("end"); - return 0; -} /* device_start_tsbulk_in */ - -static void device_stop_tsbulk_in(struct device_s *device, __u8 index) -{ - dbg("start"); - - if (device->channel[index].bulkInUrb) { - usb_unlink_urb(device->channel[index].bulkInUrb); - device->channel[index].bulkInUrb = NULL; - dbg("unlink urb"); - } /* if */ - - dbg("end"); -} /* device_stop_tsbulk_in */ - -static void device_iso_out_complete(struct urb *urb) -{ - struct ts_channel_s *channel = urb->context; - struct urb *tmpUrb; - int i; - int ret = 0; - - /*dbg("start");*/ - -/*dbg_dump("txBuf", urb->transfer_buffer, urb->transfer_buffer_length);*/ - - if (urb->status || channel->outStop) { - /* error, free all coming urbs */ - err("free urb"); - channel->outStop = 1; - atomic_dec(&channel->numOutUrbs); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return; - } /* if */ - - for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { - if (urb == channel->isocOutUrb[i]) - break; - } /* for */ - if (i == DEVICE_NUM_ISOC_OUT_URBS) { - /* urb must be deleted */ - kfree(urb->transfer_buffer); - usb_free_urb(urb); - } /* if */ - - if (atomic_dec_and_test(&channel->numOutUrbs)) { - /* get next free urb */ - tmpUrb = channel->isocOutUrb[channel->nextFreeOutUrbIndex++]; - if (channel->nextFreeOutUrbIndex == DEVICE_NUM_ISOC_OUT_URBS) - channel->nextFreeOutUrbIndex = 0; - - /* reinitialize urb with null packets */ - memset(tmpUrb->transfer_buffer, - 0xCD, DEVICE_ISOC_LENGTH(channel->maxPacketSize)); - for (i = 0; - i < DEVICE_ISOC_LENGTH(channel->maxPacketSize); - i += DEVICE_MPEG2_PACKET_SIZE) { - memcpy(tmpUrb->transfer_buffer+i, - nullHeader, sizeof(nullHeader)); - } /* for */ - tmpUrb->transfer_buffer_length = - DEVICE_ISOC_LENGTH(channel->maxPacketSize); - tmpUrb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; - tmpUrb->complete = device_iso_out_complete; - tmpUrb->context = channel; - tmpUrb->transfer_flags = URB_ISO_ASAP; - tmpUrb->interval = 1; - for (i = 0; i < DEVICE_NUM_FRAMES_PER_URB; i++) { - tmpUrb->iso_frame_desc[i].offset = - i * channel->maxPacketSize; - tmpUrb->iso_frame_desc[i].length = - channel->maxPacketSize; - } /* for */ - - /* submit urb */ - ret = usb_submit_urb(tmpUrb, GFP_ATOMIC); - if (ret) - err("usb_submit_urb failed %d", ret); - - atomic_inc(&channel->numOutUrbs); - } /* if */ - - /*dbg("end");*/ -} /* device_iso_out_complete */ - -static int device_tsiso_send(struct device_s *device, - __u8 index, __u8 *data, int size) -{ - int i, j; - struct urb **urb; - __u32 numUrbs; - int ret = 0; - - /* dbg("start");*/ - - numUrbs = - size / DEVICE_ISOC_LENGTH(device->channel[index].maxPacketSize); - urb = kmalloc(numUrbs * sizeof(struct urb *), GFP_KERNEL); - if (!urb) { - err("urb array allocation failed %d", numUrbs); - return -ENOMEM; - - } /* if */ - memset(urb, 0, numUrbs * sizeof(struct urb *)); - - for (i = 0; i < numUrbs; i++) { - urb[i] = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); - if (urb[i]) { - urb[i]->transfer_buffer = - kmalloc(DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize), - GFP_KERNEL); - if (!urb[i]->transfer_buffer) { - ret = -ENOMEM; - err("transfer_buffer allocation failed %d", i); - break; - } /* if */ - } /* if */ - else { - ret = -ENOMEM; - err("usb_alloc_urb failed %d", i); - break; - } /* if */ - } /* for */ - if (ret) { - /* Allocation error, must free already allocated data */ - for (i = 0; i < numUrbs; i++) { - if (urb[i]) { - kfree(urb[i]->transfer_buffer); - urb[i]->transfer_buffer = NULL; - usb_free_urb(urb[i]); - urb[i] = NULL; - } /* if */ - } /* for */ - kfree(urb); - return ret; - } /* if */ - - for (i = 0; i < numUrbs; i++) { - ret = copy_from_user(urb[i]->transfer_buffer, - &data[i*DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize)], - DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize)); - urb[i]->transfer_buffer_length = DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize); - urb[i]->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; - urb[i]->complete = device_iso_out_complete; - urb[i]->context = &device->channel[index]; - urb[i]->dev = device->usbdev; - urb[i]->pipe = usb_sndisocpipe(device->usbdev, - DEVICE_TS_OUT_PIPE + index); - urb[i]->transfer_flags = URB_ISO_ASAP; - urb[i]->interval = 1; - for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { - urb[i]->iso_frame_desc[j].offset = - j * device->channel[index].maxPacketSize; - urb[i]->iso_frame_desc[j].length = - device->channel[index].maxPacketSize; - } /* for */ - } /* for */ - - atomic_add(numUrbs, &device->channel[index].numOutUrbs); - for (i = 0; i < numUrbs; i++) { - ret = usb_submit_urb(urb[i], GFP_ATOMIC); - if (ret) - err("usb_submit_urb failed %d", ret); - } /* for */ - - kfree(urb); - - /* dbg("end");*/ - return size; -} /* device_tsiso_send */ - -static int device_start_iso_out(struct device_s *device, __u8 index) -{ - int i, j; - int ret = 0; - struct urb *urb; - - /*dbg("start");*/ - - device->channel[index].outStop = 0; - for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { - urb = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); - device->channel[index].isocOutUrb[i] = urb; - if (urb) { - urb->transfer_buffer = kmalloc(DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize), - GFP_KERNEL); - if (!urb->transfer_buffer) { - ret = -ENOMEM; - err("transfer_buffer allocation failed %d", i); - break; - } /* if */ - } /* if */ else { - ret = -ENOMEM; - err("usb_alloc_urb failed %d", i); - break; - } /* if */ - } /* for */ - - if (ret) { - /* Allocation error, must free already allocated data */ - for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { - urb = device->channel[index].isocOutUrb[i]; - if (urb) { - kfree(urb->transfer_buffer); - urb->transfer_buffer = NULL; - usb_free_urb(urb); - device->channel[index].isocOutUrb[i] = NULL; - } /* if */ - } /* for */ - return ret; - } /* if */ - - for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { - urb = device->channel[index].isocOutUrb[i]; - memset(urb->transfer_buffer, 0, DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize)); - for (j = 0; - j < DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize); - j += DEVICE_MPEG2_PACKET_SIZE) { - memcpy(urb->transfer_buffer+j, - nullHeader, sizeof(nullHeader)); - } /* for */ - urb->transfer_buffer_length = DEVICE_ISOC_LENGTH( - device->channel[index].maxPacketSize); - urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; - urb->complete = device_iso_out_complete; - urb->context = &device->channel[index]; - urb->dev = device->usbdev; - urb->pipe = usb_sndisocpipe(device->usbdev, - DEVICE_TS_OUT_PIPE + index); - urb->transfer_flags = URB_ISO_ASAP; - urb->interval = 1; - for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { - urb->iso_frame_desc[j].offset = - j * device->channel[index].maxPacketSize; - urb->iso_frame_desc[j].length = - device->channel[index].maxPacketSize; - } /* for */ - } /* for */ - device->channel[index].nextFreeOutUrbIndex = DEVICE_NUM_ISOC_OUT_URBS-1; - atomic_set(&device->channel[index].numOutUrbs, 1); - for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS-1; i++) { - ret = usb_submit_urb( - device->channel[index].isocOutUrb[i], GFP_KERNEL); - if (ret) - err("usb_submit_urb failed %d", ret); - } /* for */ - - /*dbg("end");*/ - return 0; -} /* device_start_iso_out */ - -static void device_stop_iso_out(struct device_s *device, __u8 index) -{ - dbg("start"); - - device->channel[index].outStop = 1; - - dbg("end"); -} /* device_stop_iso_out */ - -static void device_tsbulk_complete(struct urb *urb) -{ - struct device_s *device = urb->context; - __u8 index = 0; - - /*dbg("start");*/ - if (!urb->status) { - if (usb_endpoint_num(&(urb->ep->desc)) != DEVICE_TS_OUT_PIPE) - index = 1; - device->channel[index].nbByteSend += urb->actual_length; - } - kfree(urb->transfer_buffer); - usb_free_urb(urb); - /*dbg("end");*/ -} /* device_tsbulk_complete */ - -static int device_tsbulk_send(struct device_s *device, - __u8 index, __u8 *data, int size) -{ - struct urb *urb; - /* int todo = size;*/ - int ret = 0; - - dbg("start"); - - /* get a free bulk message */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - err("alloc urb"); - return -ENOMEM; - } /* if */ - urb->dev = device->usbdev; - - /* allocate bulk data */ - urb->transfer_buffer = kmalloc(size, GFP_KERNEL); - if (!urb->transfer_buffer) { - err("alloc transfer buffer"); - usb_free_urb(urb); - return -ENOMEM; - } /* if */ - - /* copy data */ - ret = copy_from_user(urb->transfer_buffer, data, size); - - /* submit bulk */ - urb->pipe = usb_sndbulkpipe(device->usbdev, DEVICE_TS_OUT_PIPE + index); - urb->transfer_buffer_length = size; - urb->complete = device_tsbulk_complete; - urb->context = device; - /*dbg("Transmit %d bytes\n",urb->transfer_buffer_length);*/ - /*dbg_dump("txBuf", - urb->transfer_buffer, urb->transfer_buffer_length);*/ - mod_timer(&(device->channel[index].StartBulkReadTimer), - usecs_to_jiffies(50)); - - if (usb_submit_urb(urb, GFP_KERNEL) < 0) { - err("submit urb"); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return -ENOMEM; - } /* if */ - - dbg("end"); - return 0; -} /* device_tsbulk_send */ - -/* ---------------------------------------------------------- */ -static void StartBulkRead_func(unsigned long context) -{ - struct bulk_timer_s *bulk_time = (struct bulk_timer_s *) context; - - device_start_tsbulk_in(bulk_time->device, bulk_time->index); -} - -static int device_drv_open(struct device_s *device) -{ - int index; - mutex_lock(&device->lock); - - if (!device->usbdev) { - err("no dev, can not start dev"); - mutex_unlock(&device->lock); - return -ENODEV; - } - - if (device->opened) { - mutex_unlock(&device->lock); - device->opened++; - info("udev=%p opened=%d", (device->usbdev), device->opened); - return 0; - } /* while */ - - info("set interface 0"); - if (usb_set_interface(device->usbdev, 0, 0) < 0) { - mutex_unlock(&device->lock); - err("set_interface fail"); - return -EINVAL; - } /* if */ - - device->opened++; - device->askToRelease = 0; - mutex_unlock(&device->lock); - - for (index = 0; index < DEVICE_NUM_CAM; index++) { - device->channel[index].nbByteSend = -376; - device->channel[index].nbByteRead = 0; - device->channel[index].FirstTransfer = true; - gbulk_timer[index].device = device; - gbulk_timer[index].index = index; - setup_timer(&device->channel[index].StartBulkReadTimer, - StartBulkRead_func, - (unsigned long)&(gbulk_timer[index])); - } -#ifdef DEBUG_CONTINUITY - init_tab_cc(); -#endif - info("udev=%p opened=%d", (device->usbdev), device->opened); - return 0; -} - -static int device_ci_unlock_read(struct device_s *device) -{ - if (device->opened) { - /* release blocking functions */ - device->askToRelease = 1; - wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); - wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); - wake_up_interruptible(&device->channel[0].inWait); - wake_up_interruptible(&device->channel[1].inWait); - } - return 0; -} - -static int device_drv_close(struct device_s *device) -{ - int i; - mutex_lock(&device->lock); - if (device->opened && ((--device->opened) == 0)) { - device->askToRelease = 1; - device_stop_intr(device); - for (i = 0; i < DEVICE_NUM_CAM; i++) { - if (device->useIsoc) { - device_stop_iso_out(device, i); - device_stop_iso_in(device, i); - } else - device_stop_tsbulk_in(device, i); - } /* for */ - device->opened = 0; - } /* if */ - mutex_unlock(&device->lock); - return 0; -} - -static int device_open(struct inode *inode, struct file *file) -{ - int devnum = iminor(inode); -#ifdef DEBUG - int type = (MINOR(inode->i_rdev) >> 4); - int num = (MINOR(inode->i_rdev) & 0xf); -#endif - int ret = 0; - - struct device_s *device; - - dbg("start, devnum = %d type = %d num = %d", devnum, type, num); - - if (gdeviceNumber >= DRIVER_MAX_NUMBER) { - dbg("only support one device open"); - return -EINVAL; - } - device = &gdevice[gdeviceNumber]; - /*gdeviceNumber++;*/ - - ktime_get_ts(&gStart); - - ret = device_drv_open(device); - if (ret < 0) - return ret; - - file->f_pos = 0; - file->private_data = device; - - dbg("end"); - return nonseekable_open(inode, file); -} /* device_open */ - -static int device_release(struct inode *inode, struct file *file) -{ - struct device_s *device = (struct device_s *)file->private_data; - - dbg("start"); - device_drv_close(device); - dbg("end"); - return 0; -} /* device_release */ - -int cimax_usb_select_interface(struct device_s *device, unsigned long intf) -{ - int max = 0; - int mult = 0; - int ret = 0; - - info("set interface %ld", intf); - if (usb_set_interface(device->usbdev, 0, intf) < 0) { - err("set_interface failed interface 0, altSetting %ld", intf); - return -EINVAL; - } /* if */ - - /* check endpoints */ - /* CI bulk out */ - if (!usb_endpoint_is_bulk_out( - &device->usbdev->ep_out[DEVICE_BULK_OUT_PIPE]->desc)) { - err("unexpected endpoint %d", DEVICE_BULK_OUT_PIPE); - return -EINVAL; - } /* if */ - device->ciBulk.outMaxPacketSize = DEVICE_BULK_OUT_MAXPACKET; - dbg("CI bulk out (endpoint %d), packet size %d", DEVICE_BULK_OUT_PIPE, - device->ciBulk.outMaxPacketSize); - /* CI int in */ - if (!usb_endpoint_is_int_in( - &device->usbdev->ep_in[DEVICE_INT_IN_PIPE]->desc)) { - err("unexpected endpoint %d", DEVICE_INT_IN_PIPE); - return -EINVAL; - } /* if */ - device->ciBulk.inMaxPacketSize = - device->usbdev->ep_in[DEVICE_INT_IN_PIPE]->desc.wMaxPacketSize; - dbg("CI int in (endpoint %d), packet size %d", DEVICE_INT_IN_PIPE, - device->ciBulk.inMaxPacketSize); - /* TS out */ - if (device->usbdev->ep_out[DEVICE_TS_OUT_PIPE] == NULL) - dbg("no TS endpoint"); - else { - if (usb_endpoint_is_bulk_out( - &device->usbdev->ep_out[DEVICE_TS_OUT_PIPE]->desc)) { - device->useIsoc = 0; - dbg("TS is configured as bulk"); - } else if (usb_endpoint_is_isoc_out( - &device->usbdev->ep_out[DEVICE_TS_OUT_PIPE]->desc)) { - device->useIsoc = 1; - dbg("TS is configured as isochronous"); - } else { - err("unexpected endpoint %d", DEVICE_TS_OUT_PIPE); - return -EINVAL; - } /* if */ - max = device->usbdev-> - ep_out[DEVICE_TS_OUT_PIPE]->desc.wMaxPacketSize; - mult = 1 + ((max >> 11) & 0x03); - max &= 0x7ff; - device->channel[0].maxPacketSize = max * mult; - dbg("TS out (endpoint %d), packet size %d", DEVICE_TS_OUT_PIPE, - device->channel[0].maxPacketSize); - - max = device->usbdev-> - ep_out[DEVICE_TS_OUT_PIPE+1]->desc.wMaxPacketSize; - mult = 1 + ((max >> 11) & 0x03); - max &= 0x7ff; - device->channel[1].maxPacketSize = max * mult; - dbg("TS out (endpoint %d), packet size %d", - DEVICE_TS_OUT_PIPE + 1, - device->channel[1].maxPacketSize); - } - - /* start intr urb */ - if (device->ciBulk.intUrb[0] == NULL) { - ret = device_start_intr(device); - if (ret < 0) { - err("cannot start int urb"); - return ret; - } /* if */ - } /* if */ - - return ret; -} -EXPORT_SYMBOL(cimax_usb_select_interface); - -static int device_ci_write(struct device_s *device, - struct ioctl_data_s *data, int isIoctl) -{ - int ret = 0; - if (!device) - return -ENODEV; - ret = device_cibulk_send(device, data, isIoctl); - if (ret < 0) - return ret; - return device_wait_sync_data(device, ret, data, isIoctl); -} - -static int device_ci_write_ioctl(struct device_s *device, - struct ioctl_data_s *data) -{ - return device_ci_write(device, data, 1); -} - -int cimax_usb_ci_write(struct device_s *device, - u8 *txData, int txSize, u8 *rxData, int rxSize) -{ - struct ioctl_data_s data; - if (!device) - return -ENODEV; - memset(&data, 0, sizeof(data)); - data.txData = txData; - data.txSize = txSize; - data.rxData = rxData; - data.rxSize = rxSize; - return device_ci_write(device, &data, 0); -} -EXPORT_SYMBOL(cimax_usb_ci_write); - -int cimax_usb_ci_read_evt(struct device_s *device, - int moduleId, u8 *buf, int size) -{ - int ret = 0; - struct rw_data_s data; - if (!device || !device->opened) - return -ENODEV; - memset(&data, 0, sizeof(data)); - data.moduleId = moduleId; - data.data = buf; - data.size = size; - ret = device_wait_async_data(device, data.moduleId, &data, 0); - if (ret < 0) { - err("wait ci read failed"); - return ret; - } /* if */ - dbg("return CI, moduleId %d, data 0x%p, size %d", - data.moduleId, data.data, data.size); - return ret; -} -EXPORT_SYMBOL(cimax_usb_ci_read_evt); - -int cimax_usb_device_open(struct device_s *device) -{ - return device_drv_open(device); -} -EXPORT_SYMBOL(cimax_usb_device_open); - -int cimax_usb_device_unlock_read(struct device_s *device) -{ - int ret = 0; - if (!device) - return 0; - mutex_lock(&device->lock); - ret = device_ci_unlock_read(device); - mutex_unlock(&device->lock); - return ret; -} -EXPORT_SYMBOL(cimax_usb_device_unlock_read); - -int cimax_usb_device_close(struct device_s *device) -{ - if (!device) - return 0; - cimax_usb_device_unlock_read(device); - if (cimax_usb_dev_remove) - cimax_usb_dev_remove(device, gdeviceNumber); - return device_drv_close(device); -} -EXPORT_SYMBOL(cimax_usb_device_close); - -static long device_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct device_s *device = (struct device_s *)file->private_data; - int err = 0; - int ret = 0; - struct ioctl_data_s data; - void *transfer_buffer = NULL; - - dbg("start"); - - /* Don't decode wrong cmds: return ENOTTY (inappropriate ioctl) */ - if (_IOC_TYPE(cmd) != DEVICE_IOC_MAGIC) - return -ENOTTY; - if (_IOC_NR(cmd) > DEVICE_IOC_MAXNR) - return -ENOTTY; - - /* Verify direction (read/write) */ - if (_IOC_DIR(cmd) & _IOC_READ) - err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); - if (err) - return -EFAULT; - - if (mutex_lock_interruptible(&device->lock)) - return -ERESTARTSYS; - - switch (cmd) { - case DEVICE_IOC_SELECT_INTF: - dbg("DEVICE_IOC_SELECT_INTF start"); - ret = cimax_usb_select_interface(device, arg); - dbg("DEVICE_IOC_SELECT_INTF end"); - break; - - case DEVICE_IOC_CI_WRITE: - dbg("DEVICE_IOC_CI_WRITE start"); - - /* send CI message */ - ret = copy_from_user(&data, - (void __user *)arg, sizeof(struct ioctl_data_s)); - dbg("inMsg, rx 0x%p, rxSize %d, tx 0x%p, txSize %d", - data.rxData, - data.rxSize, - data.txData, - data.txSize); - ret = device_ci_write_ioctl(device, &data); - if (ret < 0) - break; - ret = copy_to_user((void __user *)arg, - &data, sizeof(struct ioctl_data_s)); - - dbg("DEVICE_IOC_CI_WRITE end"); - break; - - case DEVICE_IOC_UNLOCK_READ: - dbg("DEVICE_IOC_UNLOCK_READ start"); - - ret = device_ci_unlock_read(device); - - dbg("DEVICE_IOC_UNLOCK_READ end"); - break; - - case DEVICE_IOC_SET_CONFIG: - dbg("DEVICE_IOC_SET_CONFIG start"); - - /* send CI message */ - ret = copy_from_user(&data, - (void __user *)arg, sizeof(struct ioctl_data_s)); - dbg("inMsg, rx 0x%p, rxSize %d, tx 0x%p, txSize %d", - data.rxData, data.rxSize, - data.txData, data.txSize); - transfer_buffer = kmalloc(data.txSize, GFP_KERNEL); - memcpy(transfer_buffer, data.txData, data.txSize); - dbg_dump("New config", transfer_buffer, data.txSize); - err = usb_control_msg(device->usbdev, - usb_sndctrlpipe(device->usbdev, 0), - USB_REQ_SET_DESCRIPTOR, - USB_TYPE_STANDARD, - (USB_DT_CONFIG << 8), - 0, - transfer_buffer, - data.txSize, - 5000); - if (err < 0) { - err("set_config failed %d", err); - ret = -EINVAL; - } - kfree(transfer_buffer); - dbg("DEVICE_IOC_SET_CONFIG end"); - break; - - default: - ret = -ENOIOCTLCMD; - break; - } /* switch */ - mutex_unlock(&device->lock); - - dbg("end, ret %d", ret); - return ret; -} /* device_ioctl */ - -static ssize_t device_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int ret; - struct rw_data_s data; - struct device_s *device = (struct device_s *)file->private_data; - - dbg("start"); - - /* get transmission buffer */ - ret = copy_from_user(&data, buf, sizeof(struct rw_data_s)); - dbg("txBuffer, moduleId %u, data 0x%p, size %d", - data.moduleId, data.data, data.size); - if (data.moduleId >= DEVICE_NUM_CAM) { - err("bad moduleId"); - return 0; - } - - if (device->useIsoc) { - if (!data.size || (data.size % DEVICE_ISOC_LENGTH( - device->channel[data.moduleId].maxPacketSize))) { - err("transmission buffer size must be a multiple of %d", - DEVICE_ISOC_LENGTH( - device->channel[data.moduleId].maxPacketSize)); - return -EINVAL; - } /* if */ - } - - if (device->useIsoc) { - if (device->channel[data.moduleId].isocInUrb[0] == NULL) { - ret = device_start_iso_in(device, data.moduleId); - if (ret < 0) - return ret; - } /* if */ - - if (device->channel[data.moduleId].isocOutUrb[0] == NULL) { - ret = device_start_iso_out(device, data.moduleId); - if (ret < 0) - return ret; - } /* if */ - - dbg("call device_tsiso_send moduleId %d, data 0x%p, size %d", - data.moduleId, data.data, data.size); - ret = device_tsiso_send(device, - data.moduleId, data.data, data.size); - } /* if */ - else { - ret = device_tsbulk_send(device, - data.moduleId, data.data, data.size); - } /* else */ - - dbg("end, moduleId %d return %d", data.moduleId, ret); - return ret; -} /* device_write */ - -static ssize_t device_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int res; - struct rw_data_s data; - struct device_s *device = (struct device_s *)file->private_data; - - dbg("start"); - - if (count != sizeof(struct rw_data_s)) { - err("try to read uncorrect size %zd", count); - return -EFAULT; - } /* if */ - res = copy_from_user(&data, buf, sizeof(struct rw_data_s)); - data.copiedSize = 0; - if (data.type == DEVICE_TYPE_TS_READ) { - res = device_fill_ts(device, data.moduleId, &data); - if (res < 0) { - err("fill ts buffer failed"); - return res; - } /* if */ - dbg("return TS, moduleId %d, data 0x%p, size %d, copiedSize %d", - data.moduleId, data.data, data.size, data.copiedSize); - /*res = count;*/ - res = data.copiedSize; - } /* if */ - else if (data.type == DEVICE_TYPE_CI_READ) { - res = device_wait_async_data(device, data.moduleId, &data, 1); - if (res < 0) { - err("wait ci read failed"); - return res; - } /* if */ - dbg("return CI, moduleId %d, data 0x%p, size %d", - data.moduleId, data.data, data.size); - res = data.size; - } /* else if */ - else { - err("unknown data type %d", data.type); - res = -EFAULT; - } /* else */ - - dbg("end, return %d", res); - return res; -} /* device_read */ - -/****************************************************************************** - * @brief - * write data on Control endpoint. - * - - * @param dev - * Pointer to usb device. - * - * @param addr - - * register address to write. - * - * @param data - * data to write. - * - - * @param size - * size to write. - * - * @return - - * data writen or ENODEV error - ******************************************************************************/ -int write_ctrl_message(struct usb_device *dev, int addr, void *data, int size) -{ - int ret; - void *ptr = NULL; -#ifdef DEBUG - /* int i;*/ - /* unsigned char dump[500];*/ -#endif - - /* info("%s: . addr = %04x size=%d",DRIVER_NAME,addr,size);*/ - - if (size <= 0) - return 0; - - ptr = kmemdup(data, size, GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - ret = usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xA0, 0x40, addr, 0x0001, - ptr, size, 300); - if (ret != size) { - err("Failed to write CIMaX+ register 0x%04x", addr); - ret = -ENODEV; - } - -#ifdef DEBUG - /* dump[0] =0; - for(i=0;i Init Status = %02X", *bootStatus); - if (bootStatus) - kfree(bootStatus); - return 0; - } - if (bootStatus) - kfree(bootStatus); - - return len; -} - -/****************************************************************************** - * @brief - * Start new Firmware. - * - * @param dev - * Pointer to usb device. - - * - * @return - * None. - ******************************************************************************/ -int write_ep6_message(struct usb_device *dev, void *data, int size) -{ - int ret; - void * ptr = NULL; - ptr = kmemdup(data, size, GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - if (usb_bulk_msg(dev, usb_sndbulkpipe(dev, 6), - ptr, size, &ret, 200) < 0) { - err("Failed to write cmd 0x%02x", ((unsigned char *)data)[0]); - ret = -ENODEV; - } - kfree(ptr); - return ret; -} - -/****************************************************************************** - * @brief - * Start new Firmware. - * - * @param dev - * Pointer to usb device. - * - * @return - * None. - ******************************************************************************/ -int read_ep5_message(struct usb_device *dev, void *data, int size) -{ - int ret; - - if (usb_interrupt_msg(dev, usb_rcvintpipe(dev, 5), - data, size, &ret, 200) < 0) { - err("Failed read interrupt endpoint"); - ret = -ENODEV; - } - return ret; -} - -#ifdef CONFIG_COMPAT -static long device_compat_ioctl(struct file *filp, - unsigned int cmd, unsigned long args) -{ - unsigned long ret; - - args = (unsigned long)compat_ptr(args); - ret = device_ioctl(filp, cmd, args); - return ret; -} -#endif - -static const struct file_operations device_fops = { - .owner = THIS_MODULE, - .open = device_open, - .release = device_release, - .unlocked_ioctl = device_ioctl, - .write = device_write, - .read = device_read, - /* - .poll = device_poll, - */ -#ifdef CONFIG_COMPAT - .compat_ioctl = device_compat_ioctl, -#endif -}; - -struct cimaxusb_priv_ops_t cimaxusb_priv_ops = { - .write_ctrl_message = write_ctrl_message, - .read_ctrl_message = read_ctrl_message, - .init_fw = init_fw, - .write_ep6_message = write_ep6_message, - .read_ep5_message = read_ep5_message -}; - -static struct usb_class_driver device_class = { - .name = "cimaxusb%d", - .fops = &device_fops, - .minor_base = DEVICE_MINOR, -}; - -/* ---------------------------------------------------------- */ - - -void cimax_usb_set_cb(void *cb1, void *cb2) -{ - cimax_usb_dev_add = cb1; - cimax_usb_dev_remove = cb2; -} -EXPORT_SYMBOL(cimax_usb_set_cb); - -static int device_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - struct device_s *device; - char cmd[] = { 0x0C, 0x01, 0x00, 0x00 }; - char *rsp; - - dbg("start vendor id 0x%x, product id 0x%x, Device id 0x%x minor 0x%x", - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct), - le16_to_cpu(usbdev->descriptor.bcdDevice), - intf->minor); - - /* device = &gdevice[intf->minor];*/ - device = &gdevice[gdeviceNumber]; - - mutex_lock(&device->lock); - /* device->usbdev = usbdev;*/ - device->usbdev = usb_get_dev(usbdev); - dbg("device->usbdev 0x%p", (device->usbdev)); - - /* set private callback functions */ - device->ops = &cimaxusb_priv_ops; - - device->askToSuspend = 0; - - usb_set_intfdata(intf, device); - mutex_unlock(&device->lock); - - if (usb_register_dev(intf, &device_class)) { - err("usb_register_dev"); - usb_set_intfdata(intf, NULL); - return -ENOMEM; - } /* if */ - - /* test if firmware loafing is needed */ -#ifdef FRBIT - if ((le16_to_cpu(usbdev->descriptor.bcdDevice) != 0) && - (CimaxDwnl == 1)) { -#else - if (le16_to_cpu(usbdev->descriptor.bcdDevice) != 0) { -#endif - info("start firmware download"); - /* load firmware*/ - cimaxusb_fw_upload(device); - info("end firmware download"); - } else { - info("set alternate setting 1"); - if (usb_set_interface(device->usbdev, 0, 1) < 0) { - err("set_interface failed intf 0, alt 1"); - } else { - info("check FW version"); - /* Get BOOT version */ - if (write_ep6_message(device->usbdev, - cmd, sizeof(cmd)) == sizeof(cmd)) { - rsp = kcalloc(256, - sizeof(unsigned char), - GFP_KERNEL); - if (!rsp) { - err("out of memory"); - return -ENOMEM; - } - if (read_ep5_message(device->usbdev, - rsp, 256) >= 0) { - info("=> ---- F.W. Version -------"); - info("=>= %02X.%02X.%02X.%02X.%02X%c", - rsp[4], rsp[5], rsp[6], - rsp[7], rsp[8], rsp[9]); - info("=> Boot Version = %d.%d", - rsp[10], rsp[11]); - info("=> --------------------"); - } - kfree(rsp); - } - } - info("start cfg download"); - if (cimaxusb_configuration_setting(device) < 0) - err(" Error : set CIMaX+ configuration"); - info("end cfg download"); - - if (cimax_usb_dev_add) - cimax_usb_dev_add(device, gdeviceNumber); - } - - dbg("end"); - return 0; -} /* device_probe */ - -static void device_disconnect(struct usb_interface *intf) -{ - struct device_s *device = usb_get_intfdata(intf); - int i; - - dbg("start"); - - if (!device) - return; - - mutex_lock(&device->lock); - if (device->opened) { - /* release blocking functions */ - device->askToRelease = 1; - wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); - wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); - wake_up_interruptible(&device->channel[0].inWait); - wake_up_interruptible(&device->channel[1].inWait); - device_stop_intr(device); - for (i = 0; i < DEVICE_NUM_CAM; i++) { - if (device->useIsoc) { - device_stop_iso_out(device, i); - device_stop_iso_in(device, i); - } /* if */ - else - device_stop_tsbulk_in(device, i); - } /* for */ - device->opened = 0; - - if (cimax_usb_dev_remove) - cimax_usb_dev_remove(device, gdeviceNumber); - } /* if */ - mutex_unlock(&device->lock); - usb_set_intfdata(intf, NULL); - if (device) { - usb_deregister_dev(intf, &device_class); - device->usbdev = NULL; - } /* if */ - dbg("end"); -} /* device_disconnect */ - -static int cimaxusb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct device_s *device = usb_get_intfdata(intf); - int i; - - dbg("start"); - - if (!device) - return 0; - - mutex_lock(&device->lock); - if (device->opened) { - /* release blocking functions */ - device->askToSuspend = 1; - wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); - wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); - wake_up_interruptible(&device->channel[0].inWait); - wake_up_interruptible(&device->channel[1].inWait); - device_stop_intr(device); - for (i = 0; i < DEVICE_NUM_CAM; i++) { - if (device->useIsoc) { - device_stop_iso_out(device, i); - device_stop_iso_in(device, i); - } /* if */ - else - device_stop_tsbulk_in(device, i); - } /* for */ - device->opened = 0; - } /* if */ - mutex_unlock(&device->lock); - dbg("end"); - - return 0; -} - -static int cimaxusb_resume(struct usb_interface *intf) -{ - struct device_s *device = usb_get_intfdata(intf); - - dbg("start"); - - if (!device) - return 0; - - device->askToSuspend = 0; - dbg("end"); - return 0; -} - -static struct usb_device_id device_ids[] = { - { USB_DEVICE(0x1b0d, 0x2f00) }, - { USB_DEVICE(0x1b0d, 0x2f01) }, - { USB_DEVICE(0x1b0d, 0x2f02) }, - { USB_DEVICE(0x1b0d, 0x2f03) }, - { USB_DEVICE(0x1b0d, 0x2f04) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, device_ids); - - -static struct usb_driver device_driver = { - .name = "cimaxusb", - .probe = device_probe, - .disconnect = device_disconnect, - .suspend = cimaxusb_suspend, - .resume = cimaxusb_resume, - .id_table = device_ids, -}; - -/* ---------------------------------------------------------- */ - -static int device_init_module(void) -{ - int ret = 0; - int i, j; - struct device_s *device; - - info("start"); - - if (!gdevice) - gdevice = kcalloc(DRIVER_MAX_NUMBER, - sizeof(struct device_s), GFP_KERNEL); - if (!gdevice) { - err("not enough memory"); - return -ENOMEM; - } - - for (i = 0; i < DRIVER_MAX_NUMBER; i++) { - device = &gdevice[i]; - /* initialize struct */ - memset(device, 0, sizeof(struct device_s)); - mutex_init(&device->lock); - - /* initialize ci bulk struct */ - device->ciBulk.counter = 1; - spin_lock_init(&device->ciBulk.intLock); - spin_lock_init(&device->ciBulk.intUrbLock); - for (j = 0; j < DEVICE_NUM_CAM; j++) { - init_waitqueue_head(&device->ciBulk.ciData[j].syncWait); - init_waitqueue_head( - &device->ciBulk.ciData[j].asyncWait); - INIT_LIST_HEAD(&device->ciBulk.ciData[j].asyncDataList); - } /* for */ - - /* initialize channels */ - for (j = 0; j < DEVICE_NUM_CAM; j++) { - spin_lock_init(&device->channel[j].inLock); - init_waitqueue_head(&device->channel[j].inWait); - vb_init(&device->channel[j].inVb); - device->channel[j].syncOffset = -1; - spin_lock_init(&device->channel[j].outLock); - } /* for */ - } /* for */ - - /* register misc device */ - ret = usb_register(&device_driver); - -#ifdef TIMESTAMP - InitTimestamp(); -#endif - - if (ret) - info("end driver register failed"); - else - info("end driver registered"); - - info(DRIVER_VERSION ":" DRIVER_DESC); - - return ret; -} /* device_init_module */ - -static void device_exit_module(void) -{ - int i; - struct device_s *device; - - info("start"); - -#ifdef TIMESTAMP - ShowTimestamp(); -#endif - - for (i = 0; i < DRIVER_MAX_NUMBER; i++) { - device = &gdevice[i]; - device->askToRelease = 1; - /* destroy struct */ - mutex_destroy(&device->lock); - } /* for */ - usb_deregister(&device_driver); - gdeviceNumber = 0; - - kfree(gdevice); - gdevice = NULL; - info("end"); -} /* device_exit_module */ - -module_init(device_init_module); -module_exit(device_exit_module); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h deleted file mode 100644 index e4656e0e54f8..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h +++ /dev/null @@ -1,362 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb-driver.h - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - ******************************************************************************/ - -#include - -#ifndef CIMAXPLUS_USB_DRIVER_H -#define CIMAXPLUS_USB_DRIVER_H - -/****************************************************************************** - * Includes - *****************************************************************************/ -/****************************************************************************** - * Defines - *****************************************************************************/ -/** - * @brief - * Driver Name - */ -#define DRIVER_NAME "cimax+usb" -/** - * @brief - * An unassigned USB minor. - */ -#define DEVICE_MINOR 240 - -/** - * @brief - * Driver version. - */ -#define DEVICE_VERSION 0x1000 - -/** - * @brief - * Number of CA module supported by the driver. - */ -#define DEVICE_NUM_CAM 2 - -/** - * @brief - * Buffer length. - */ -#define DEVICE_MESSAGE_LENGTH 4100 - -/* Offset */ -#define DEVICE_COMMAND_OFFSET 0 -#define DEVICE_STATUS_OFFSET 0 -#define DEVICE_COUNTER_OFFSET 1 -#define DEVICE_LENGTH_MSB_OFFSET 2 -#define DEVICE_LENGTH_LSB_OFFSET 3 -#define DEVICE_DATA_OFFSET 4 - -/* Mask */ -#define DEVICE_SEL_MASK 0x80 -#define DEVICE_TYP_MASK 0x40 -#define DEVICE_CMD_MASK 0x3F - -/* Command tag */ -#define DEVICE_CMD_INIT 0x00 -#define DEVICE_CMD_WRITE_REG 0x7F -#define DEVICE_CMD_READ_REG 0xFF -#define DEVICE_CMD_CAMRESET 0x01 -#define DEVICE_CMD_GETCIS 0x02 -#define DEVICE_CMD_WRITECOR 0x03 -#define DEVICE_CMD_NEGOTIATE 0x04 -#define DEVICE_CMD_WRITELPDU 0x05 -#define DEVICE_CMD_READLPDU 0x06 -#define DEVICE_CMD_WRITEEXT 0x07 -#define DEVICE_CMD_READEXT 0x08 -#define DEVICE_CMD_CC1RESET 0x09 -#define DEVICE_CMD_MCARD_WRITE 0x0a - -/* Status field */ -#define DEVICE_CAMRESETOK 0x00 -#define DEVICE_CISOK 0x01 -#define DEVICE_WRITECOROK 0x02 -#define DEVICE_NEGOTIATEOK 0x03 -#define DEVICE_WRITELPDUOK 0x04 -#define DEVICE_CAMDET 0x05 -#define DEVICE_READLPDUOK 0x06 -#define DEVICE_WRITEEXTOK 0x07 -#define DEVICE_READEXTOK 0x08 -#define DEVICE_NO_CAM 0x09 -#define DEVICE_NOK 0x0a -#define DEVICE_INITOK 0x0b -#define DEVICE_READ_REGOK 0x0c -#define DEVICE_WRITE_REGOK 0x0d -#define DEVICE_DATAREADY 0x0e -#define DEVICE_MCARD_WRITEOK 0x0f -#define DEVICE_MCARD_READ 0x10 -#define DEVICE_CAMPARSE_ERROR 0x11 -#define DEVICE_WRITELPDUBUSY 0x14 -#define DEVICE_CMDPENDING 0x16 -#define DEVICE_REGSTATUSOK 0x17 -#define DEVICE_GPIOCHANGE 0x18 -#define DEVICE_FRBit 0x1A - - -#define DEVICE_DATAREADY_SYNC 0x3e - -/** - * @brief - * MPEG2 transport size,.isochronous size and number of frames per URB. - */ -#define DEVICE_MPEG2_PACKET_SIZE 188 -#define DEVICE_MPEG2_SYNC_BYTE 0x47 -#define DEVICE_NULL_HEADER_SIZE 8 -#define DEVICE_NUM_FRAMES_PER_URB 8 -#define DEVICE_ISOC_LENGTH(x) (DEVICE_NUM_FRAMES_PER_URB*x) -#define DEVICE_VB_LENGTH 902400 - -/** - * @brief - * Endpoint address. - */ -#define DEVICE_TS_IN_PIPE 1 /* and 2 */ -#define DEVICE_TS_OUT_PIPE 3 /* and 4 */ -#define DEVICE_INT_IN_PIPE 5 -#define DEVICE_BULK_OUT_PIPE 6 -#define DEVICE_BULK_OUT_MAXPACKET 256 - -/** - * @brief - * Number of isochronous/int URBs in the driver. - */ -#define DEVICE_NUM_ISOC_OUT_URBS 3 -#define DEVICE_NUM_ISOC_IN_URBS 2 -#define DEVICE_NUM_INT_IN_URBS 2 - -/** - * @brief - * ioctl() calls definition. - */ -#define DEVICE_IOC_MAGIC 'a' -#define DEVICE_IOC_SELECT_INTF _IOWR(DEVICE_IOC_MAGIC, 0, signed long) -#define DEVICE_IOC_CI_WRITE _IOWR(DEVICE_IOC_MAGIC, 1, struct ioctl_data_s) -#define DEVICE_IOC_UNLOCK_READ _IOWR(DEVICE_IOC_MAGIC, 2, signed long) -#define DEVICE_IOC_SET_CONFIG _IOWR(DEVICE_IOC_MAGIC, 3, struct ioctl_data_s) -#define DEVICE_IOC_MAXNR 4 - -/****************************************************************************** - * Types - *****************************************************************************/ -#ifdef __KERNEL__ -#include -#include -#include - -#undef dbg -#undef dbg_isoc_in -#undef dbg_isoc_out - -#undef err -#undef info -#undef warn - -#define DEBUG - -#ifdef DEBUG -#define dbg(format, arg...) pr_debug("cimax+usb: %s> " format "\n" , \ - __func__, ## arg) -#define dbg_s(format, arg...)\ - pr_debug("cimax+usb: " format "\n" , ## arg) -#else -#define dbg(format, arg...) do {} while (0) -#define dbg_s(format, arg...) do {} while (0) -#endif - -#ifdef DEBUG_ISOC_IN -#define dbg_isoc_in(format, arg...)\ - pr_debug("cimax+usb: %s> " format "\n" , \ - __func__, ## arg) -#else -#define dbg_isoc_in(format, arg...) do {} while (0) -#endif - -#ifdef DEBUG_ISOC_OUT -#define dbg_isoc_out(format, arg...)\ - pr_debug("cimax+usb: %s> " format "\n" , \ - __func__, ## arg) -#else -#define dbg_isoc_out(format, arg...) do {} while (0) -#endif - -#define err(format, arg...)\ - pr_err("cimax+usb: %s> ERROR " format "\n" , \ - __func__, ## arg) -#define info(format, arg...)\ - pr_info("cimax+usb: %s> " format "\n" , \ - __func__, ## arg) -#define warn(format, arg...)\ - pr_warn("cimax+usb: %s> WARN" format "\n" , \ - __func__, ## arg) - -/** - * @brief - * Video buffer structure. - */ -struct video_buf_s { - __u8 data[DEVICE_VB_LENGTH]; - int readOffset; - int writeOffset; - int isEmpty; -}; -#endif - -/** - * @brief - * Io control data structure exchanged between user and kernel space. - */ -struct ioctl_data_s { - __u8 *txData; - __u32 txSize; - __u8 *rxData; - __u32 rxSize; -}; - -/** - * @brief - * Read/write type exchanged between user and kernel space. - */ -enum rw_type_e { - DEVICE_TYPE_CI_READ, - DEVICE_TYPE_TS_WRITE, - DEVICE_TYPE_TS_READ -}; - -/** - * @brief - * Read/write data structure exchanged between user and kernel space. - */ -struct rw_data_s { - enum rw_type_e type; - __u8 moduleId; - __u8 *data; - __u32 size; - __u32 copiedSize; -}; -#ifdef __KERNEL__ -/** - * @brief - * Message node structure. Can be inserted in a list. - */ -struct message_node_s { - __u8 data[DEVICE_MESSAGE_LENGTH]; - __u32 size; - struct list_head node; -}; - -/** - * @brief - * Received CI data. - */ -struct ci_rx_data_s { - wait_queue_head_t syncWait; - __u8 syncSignal; - __u8 syncData[DEVICE_MESSAGE_LENGTH]; - __u32 syncDataSize; - wait_queue_head_t asyncWait; - struct list_head asyncDataList; - __u8 bPendingSend; -}; - -/** - * @brief - * CI bulk channel. - */ -struct ci_bulk_s { - __u8 counter; - __u16 inMaxPacketSize; - __u16 outMaxPacketSize; - struct urb *intUrb[DEVICE_NUM_INT_IN_URBS]; - spinlock_t intLock; - spinlock_t intUrbLock; - __u8 intCurrStatus; - __u8 intCurrIndex; - __u16 intSizeToReceive; - struct ci_rx_data_s ciData[DEVICE_NUM_CAM]; -}; - -/** - * @brief - * TS channel (can use isoc or bulk interface). - */ -struct ts_channel_s { - spinlock_t inLock; - wait_queue_head_t inWait; - struct video_buf_s inVb; - int syncOffset; - int prevOffset; - __u8 lastPacket[DEVICE_MPEG2_PACKET_SIZE]; - __u8 lastPacketSize; - spinlock_t outLock; - __u8 nextFreeOutUrbIndex; - atomic_t numOutUrbs; - __u8 outStop; - __u16 maxPacketSize; - /* isochronous urbs */ - struct urb *isocInUrb[DEVICE_NUM_ISOC_IN_URBS]; - struct urb *isocOutUrb[DEVICE_NUM_ISOC_OUT_URBS]; - /* bulk urbs */ - struct urb *bulkInUrb; - int nbByteSend; - int nbByteRead; - __u8 FirstTransfer; - struct timer_list StartBulkReadTimer; - -#ifdef DEBUG_BITRATE - ktime_t bitrateTime -#endif -}; - -struct device_s { - struct mutex lock; - struct usb_device *usbdev; - __u8 opened; - __u8 askToRelease; - __u8 askToSuspend; - struct ci_bulk_s ciBulk; - __u8 useIsoc; - struct ts_channel_s channel[DEVICE_NUM_CAM]; - /* bus adapter private ops callback */ - struct cimaxusb_priv_ops_t *ops; - int ref; -}; - -struct bulk_timer_s { - struct device_s *device; - __u8 index; -}; - -int cimax_usb_select_interface(struct device_s *device, unsigned long intf); -int cimax_usb_ci_write(struct device_s *device, - u8 *txData, int txSize, u8 *rxData, int rxSize); -int cimax_usb_ci_read_evt(struct device_s *device, - int moduleId, u8 *buf, int size); - -int cimax_usb_device_unlock_read(struct device_s *device); -int cimax_usb_device_open(struct device_s *device); -int cimax_usb_device_close(struct device_s *device); -void cimax_usb_set_cb(void *cb1, void *cb2); - - -#endif -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c deleted file mode 100644 index 4469b872995b..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c +++ /dev/null @@ -1,684 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_config.c - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - ******************************************************************************/ -/****************************************************************************** - * Include - ******************************************************************************/ - - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "cimax+usb-driver.h" -#include "cimax+usb_config.h" -#include "bodydef.h" - -#include - -#define DEBUG -#include - -/****************************************************************************** - * Structures - ******************************************************************************/ -/****************************************************************************** - * Globals - ******************************************************************************/ -char *cimax_config_file[4] = { - "cimax+usb.cfg", - "cimax+usb_vcc0.cfg", - "cimax+usb_vcc3.cfg", - "cimax+usb_vcc5.cfg" -}; - -/****************************************************************************** - * Functions - ******************************************************************************/ -/****************************************************************************** - * @brief - * set CIMaX+ register value. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * CIMaX+ register value to set. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int usb_setbyte(struct device_s *bus_adap, unsigned int addr, unsigned char val) -{ - unsigned char cmd[5]; - unsigned char *buf; - int len; - struct usb_device *dev = bus_adap->usbdev; - - cmd[0] = 0x7F; - cmd[1] = (unsigned char)((addr>>8)&0xff); - cmd[2] = (unsigned char)(addr&0xff); - cmd[3] = 0x01; - cmd[4] = val; - if (bus_adap->ops->write_ep6_message(dev, cmd, sizeof(cmd)) - == sizeof(cmd)) { - /*pr_debug("%s-%s: cmd=0x%x\n", - DRIVER_NAME, __func__,cmd[0]);*/ - buf = kcalloc(256, sizeof(unsigned char), GFP_KERNEL); - if (!buf) { - pr_err("%s-%s: out of memory.\n", - DRIVER_NAME, __func__); - return -ENOMEM; - } - - while ((len = bus_adap->ops->read_ep5_message(dev, buf, 256)) - >= 0) { - if (len == 0) - continue; - if ((len == 5) && ((buf[0] & 0x7f) == 0x45)) - continue; - if (len < 4) { - pr_err("%s-%s: failed to read addr 0x%x\n", - DRIVER_NAME, __func__, addr); - kfree(buf); - return -1; - } else { - break; - } - } - } else { - pr_err("%s-%s: failed to write addr 0x%x\n", - DRIVER_NAME, __func__, addr); - return -1; - } - kfree(buf); - return 0; -} - -/****************************************************************************** - * @brief - * get CIMaX+ register value. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * pointer to buffer to store CIMaX+ register value. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int usb_getbyte(struct device_s *bus_adap, - unsigned int addr, unsigned char *val) -{ - unsigned char cmd[4]; - unsigned char *buf; - int len; - struct usb_device *dev = bus_adap->usbdev; - - cmd[0] = 0xFF; - cmd[1] = (unsigned char)((addr>>8)&0xff); - cmd[2] = (unsigned char)(addr&0xff); - cmd[3] = 0x01; - if (bus_adap->ops->write_ep6_message(dev, cmd, sizeof(cmd)) - == sizeof(cmd)) { - /*pr_debug("%s-%s: cmd=0x%x\n", - DRIVER_NAME, __func__,cmd[0]);*/ - buf = kcalloc(256, sizeof(unsigned char), GFP_KERNEL); - if (!buf) { - pr_err("%s-%s: out of memory.\n", - DRIVER_NAME, __func__); - return -ENOMEM; - } - - while ((len = bus_adap->ops->read_ep5_message(dev, buf, 256)) - >= 0) { - if (len == 0) - continue; - /*pr_debug("%s-%s: 0x%x\n", - DRIVER_NAME, __func__,buf[0]);*/ - if ((len == 5) && ((buf[0] & 0x7f) == 0x45)) - continue; - if (len >= 5) { - *val = buf[4]; - break; - } else { - pr_err("%s-%s: failed to read addr 0x%x\n", - DRIVER_NAME, __func__, addr); - kfree(buf); - return -1; - } - } - } else { - pr_err("%s-%s: failed to read addr 0x%x\n", - DRIVER_NAME, __func__, addr); - return -1; - } - kfree(buf); - return 0; -} - -/****************************************************************************** - * @brief - * compute a logical Or between CIMaX+ register value and a param value. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * value to compute. - * - * @param pval - * pointer to buffer to store CIMaX+ register value. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int setLogicalOr(struct device_s *bus_adap, - unsigned int addr, unsigned char val, unsigned char *pval) -{ - *pval |= val; - - if (usb_setbyte(bus_adap, addr, *pval) < 0) - return -1; - - if (usb_getbyte(bus_adap, addr, pval) < 0) - return -1; - - dbg("=> Logical OR [%02X] => %02X\n", val, *pval); - - return 0; -} - -/****************************************************************************** - * @brief - * compute a logical And between CIMaX+ register value and a param value. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * value to compute. - * - * @param pval - * pointer to buffer to store CIMaX+ register value. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int setLogicalAnd(struct device_s *bus_adap, - unsigned int addr, unsigned char val, unsigned char *pval) -{ - *pval &= val; - - if (usb_setbyte(bus_adap, addr, *pval) < 0) - return -1; - - if (usb_getbyte(bus_adap, addr, pval) < 0) - return -1; - - dbg("=> Logical AND [%02X] => %02X\n", val, *pval); - - return 0; -} - -/****************************************************************************** - * @brief - * wait CIMaX+ register value match a param value. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * value to match. - * - * @param pval - * pointer to buffer to store CIMaX+ register value. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int waitForValue(struct device_s *bus_adap, - unsigned int addr, unsigned char val, unsigned char *pval) -{ - dbg("=> Wait for Value [%02X]\n", val); - if (*pval == val) - return 0; - - while (1) { - if (usb_getbyte(bus_adap, addr, pval) < 0) - return -1; - - dbg("\r => %02X", *pval); - - if (*pval == val) - break; - } - - dbg("\n"); - - return 0; -} - -/****************************************************************************** - * @brief - * wait CIMaX+ register bits match a param value. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * value to match. - * - * @param pval - * pointer to buffer to store CIMaX+ register value. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int waitForBitsSet(struct device_s *bus_adap, - unsigned int addr, unsigned char val, unsigned char *pval) -{ - dbg("=> Wait for Bits set [%02X]\n", val); - if ((*pval & val) == val) - return 0; - - while (1) { - if (usb_getbyte(bus_adap, addr, pval) < 0) - return -1; - - dbg("\r => %02X", *pval); - - if ((*pval & val) == val) - break; - } - - dbg("\n"); - - return 0; -} - -/****************************************************************************** - * @brief - * wait CIMaX+ register bits cleared. - * - * @param bus_adap - * Pointer to CIMaX+ usb adapter. - * - * @param addr - * Addr of CIMaX+ register. - * - * @param val - * bits to check. - * - * @param pval - * pointer to buffer to store CIMaX+ register value. - * - * @return - * 0 if OK otherwise -1. - ******************************************************************************/ -int waitForBitsCleared(struct device_s *bus_adap, - unsigned int addr, unsigned char val, unsigned char *pval) -{ - dbg("=> Wait for Bits cleared [%02X]\n", val); - if ((*pval & val) == 0x00) - return 0; - - while (1) { - if (usb_getbyte(bus_adap, addr, pval) < 0) - return -1; - - dbg("\r => %02X", *pval); - - if ((*pval & val) == 0x00) - break; - } - - dbg("\n"); - - return 0; -} - -/****************************************************************************** - * @brief - * retreive addr of CIMaX+ register. - * - * @param dev - * Pointer to CIMaX+ register Name. - * - * @return - * Address of CIMaX+ register. - *****************************************************************************/ -int cimaxusb_rtr_reg_addr(char *str_addr) -{ - int i32NbItem = sizeof(cimax_reg_map) / sizeof(struct reg_s); - int i32index; - int i32ValAddr = -1; - - for (i32index = 0; i32index < i32NbItem; i32index++) { - if (strcmp(str_addr, cimax_reg_map[i32index].RegisterName) - == 0) { - i32ValAddr = cimax_reg_map[i32index].RegAddr; - break; - } - } - return i32ValAddr; -} - -static int cimaxusb_parse_cfg_ops(struct device_s *bus_adap, - unsigned char **pptr, size_t *plen) -{ - unsigned char op; - int ret; - char param1[256], param2[256]; - char line[256], *ptr_line; - int val; - unsigned char val2; - unsigned int addr; - unsigned char *ptr = *pptr; - size_t len = *plen; - - ptr_line = line; - op = *ptr; - ret = sscanf(ptr, "%s %s", param1, param2); - ptr++; - len++; - if (sscanf(ptr, "%s %X", param1, &val) != 2) - return -EFAULT; - /*pr_debug("%s: param1=%s,param2=%s, val=%x\n", - DRIVER_NAME, param1, param2, val);*/ - strcpy(ptr_line, param1); - len += strlen(param1); - ptr += strlen(param1); - strncat(ptr_line, ptr, 1); - len++; - ptr++; - strcat(ptr_line, param2); - len += strlen(param2); - ptr += strlen(param2); - /*pr_debug("%s: len = %08d line: %s\n", - DRIVER_NAME, len, line);*/ - addr = cimaxusb_rtr_reg_addr(param1); - if (((signed)addr) < 0) { - pr_err("%s: unknown register name: %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - if (usb_getbyte(bus_adap, addr, &val2) < 0) { - pr_err("%s: CIMaX+ register reading problem: %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - - switch (op) { - case '=': - if (waitForValue(bus_adap, addr, val, &val2) == -1) { - pr_err("%s : waitForValue failed on : %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - pr_info("%s : wait for value ([%x] = %x = %x)\n", - line, addr, val, val2); - break; - case '?': - if (waitForBitsSet(bus_adap, addr, val, &val2) == -1) { - pr_err("%s : waitForBitsSet failed on : %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - pr_info("%s : wait for bitsset ([%x] = %x = %x)\n", - line, addr, val, val2); - break; - case '!': - if (waitForBitsCleared(bus_adap, addr, val, &val2) - == -1) { - pr_err("%s : waitForBitsCleared failed on : %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - pr_info("%s : wait for bits cleared ([%x] = %x = %x)\n", - line, addr, val, val2); - break; - case '|': - if (setLogicalOr(bus_adap, addr, val, &val2) == -1) { - pr_err("%s : setLogicalOr failed on : %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - pr_info("%s : setOr ([%x] = %x = %x)\n", - line, addr, val, val2); - break; - case '&': - if (setLogicalAnd(bus_adap, addr, val, &val2) == -1) { - pr_err("%s : setLogicalAnd failed on : %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - pr_info("%s : setAnd ([%x] = %x = %x)\n", - line, addr, val, val2); - break; - default: - pr_err("Error: Marker Unknown <%c> !!!\n", op); - return -ENODEV; - } - *pptr = ptr; - *plen = len; - return 0; -} - -static int cimaxusb_parse_cfg_default(struct device_s *bus_adap, - unsigned char **pptr, size_t *plen) -{ - unsigned char *ptr = *pptr; - size_t len = *plen; - int ret; - char param1[256], param2[256]; - char line[256], *ptr_line; - int val; - unsigned char val2; - unsigned int addr; - - ptr_line = line; - - ret = sscanf(ptr, "%s %s", param1, param2); - ret = sscanf(param2, "%X", &val); - /*pr_debug("%s: param1=%s,param2=%s,val=%x\n", - DRIVER_NAME,param1,param2,val);*/ - strcpy(ptr_line, param1); - len += strlen(param1); - ptr += strlen(param1); - strncat(ptr_line, ptr, 1); - len++; - ptr++; - strcat(ptr_line, param2); - len += strlen(param2); - ptr += strlen(param2); - /*pr_debug("%s: len = %08d line: %s\n", - DRIVER_NAME, len, line);*/ - addr = cimaxusb_rtr_reg_addr(param1); - if (((signed)addr) < 0) { - pr_err("%s: unknown register name: %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - if (usb_getbyte(bus_adap, addr, &val2) < 0) { - pr_err("%s: CIMaX+ register reading problem: %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - if (usb_setbyte(bus_adap, addr, val) < 0) { - pr_err("%s: CIMaX+ register writing problem: %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - if (usb_getbyte(bus_adap, addr, &val2) < 0) { - pr_err("%s: CIMaX+ register checking problem: %s\n", - DRIVER_NAME, param1); - return -ENODEV; - } - pr_info("set: %s(0x%04x) : 0x%02x\n", param1, addr, val); - - *pptr = ptr; - *plen = len; - return 0; -} - -/****************************************************************************** - * @brief - * parse CIMaX+ config file. - * - * @param dev - * Pointer to usb device. - * - * @param fw_data - * Pointer to buffer with firmware data. - * - * @return - * O if no error otherwise errno. - *****************************************************************************/ -int cimaxusb_parse_cfg(struct device_s *bus_adap, - const unsigned char *cfg_data, size_t size) -{ - char line[256], *ptr_line; - size_t len = 0; - unsigned char *ptr = (unsigned char *)cfg_data; - int ret = -EFAULT; - - dbg("%s: %s size = %zd\n", DRIVER_NAME, __func__, size); - do { - ptr_line = line; - switch (*ptr) { - case ';': - /* continue up to find \r character */ - while (*ptr != 0x0A) { - *ptr_line++ = *ptr; - ptr++; - len++; - } - *ptr_line = 0; - /*pr_debug("%s: len = %08d line: %s\n", - DRIVER_NAME, len, line);*/ - break; - case 0x0A: - case 0x0D: - ptr++; - len++; - break; - case '=': - case '?': - case '!': - case '|': - case '&': - ret = cimaxusb_parse_cfg_ops(bus_adap, &ptr, &len); - if (ret < 0) - return ret; - break; - default: - ret = cimaxusb_parse_cfg_default(bus_adap, &ptr, &len); - if (ret < 0) - return ret; - break; - } - } while (len < size); - - return (ret == -EFAULT) ? 0 : ret; -} - -/****************************************************************************** - * @brief - * read configuration file ( CIMAX_CONFIG_NAME) and set in CIMaX+ chip. - * - * @param bus_adap - * Pointer to usb device. - * - * @return - * None. - ******************************************************************************/ -/* -opt: 0: init, 1: off, 2: Vcc3.3 3: Vcc5 -*/ -int cimaxusb_configuration_setting_opt(struct device_s *bus_adap, int opt) -{ - int errno = -EFAULT; - const struct firmware *config; - char *cfg = cimax_config_file[opt]; - - struct usb_device *dev = bus_adap->usbdev; - - dbg("request configuration file"); - /* request kernel to locate firmware file */ - errno = request_firmware(&config, cfg, &dev->dev); - if (errno < 0) { - pr_err("%s: unable to locate configuration file: %s\n", - DRIVER_NAME, cfg); - goto error; - } - - dbg("parse configuration file"); - errno = cimaxusb_parse_cfg(bus_adap, config->data, config->size); - if (errno < 0) { - pr_err("%s: unable to parse config file: %s\n", - DRIVER_NAME, cfg); - goto error; - } - -error: - /* release firmware if needed */ - if (config != NULL) - release_firmware(config); - return errno; -} - -int cimaxusb_configuration_setting(struct device_s *bus_adap) -{ - return cimaxusb_configuration_setting_opt(bus_adap, 0); -} - -int cimaxusb_configuration_setting_vcc(struct device_s *bus_adap, int vcc) -{ - return cimaxusb_configuration_setting_opt(bus_adap, vcc); -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h deleted file mode 100644 index 5c55204c62cc..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_config.h - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - ******************************************************************************/ - -#ifndef __CIMAXPLUS_USB_CFG_H -#define __CIMAXPLUS_USB_CFG_H - -/****************************************************************************** - * Include - ******************************************************************************/ -#include "cimax+usb_handle.h" - -/****************************************************************************** - * Defines - ******************************************************************************/ -#define CIMAX_CONFIG_NAME "cimax+usb.cfg" - -/****************************************************************************** - * Enums - ******************************************************************************/ -/****************************************************************************** - * Structures - ******************************************************************************/ - -/****************************************************************************** - * Functions - ******************************************************************************/ - -/****************************************************************************** - * @brief - * read configuration file ( CIMAX_CONFIG_NAME) and set in CIMaX+ chip. - * - * @param bus_adap - * Pointer to usb device. - * - * @return - * None. - ******************************************************************************/ -int cimaxusb_configuration_setting(struct device_s *bus_adap); - -#endif - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c deleted file mode 100644 index 6bccf4b8e64b..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c +++ /dev/null @@ -1,325 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_fw.c - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - ******************************************************************************/ -/****************************************************************************** - * Include - ******************************************************************************/ -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include "cimax+usb-driver.h" -#include "cimax+usb_fw.h" - -/****************************************************************************** - * Structures - ******************************************************************************/ -/****************************************************************************** - * Globals - ******************************************************************************/ -char cimax_fw[] = CIMAX_FIRMWARE_NAME; - -/****************************************************************************** - * Functions - ******************************************************************************/ -/****************************************************************************** - * @brief - * Start & check Bistrom. - * - * @param dev - * Pointer to usb device. - * - * @param startAddr - * start address of firmware to compute - * - * @param endAddr - * stop address of firmware to compute - * - * @param FWSign - * Current signature to check - * - * - * @return - * None. - ******************************************************************************/ -int checkBistRom(struct device_s *bus_adap, - int startAddr, int endAddr, int signature) -{ - unsigned char *Val; - int rv; - - struct usb_device *dev = bus_adap->usbdev; - - Val = kcalloc(2, sizeof(unsigned char), GFP_KERNEL); - if (!Val) { - pr_err("%s-%s: out of memory.\n", DRIVER_NAME, __func__); - return -ENOMEM; - } - - /* Write "Flash" Size - (!) BistRom is computed since D000-flashSize to D0000-6 - */ - Val[0] = (0xD000-startAddr)&0x00ff; - Val[1] = (0xD000-startAddr)>>8; - if (bus_adap->ops->write_ctrl_message(dev, 0x008D, Val, 2) != 2) { - kfree(Val); - return -1; - } - - /* Write Signature*/ - Val[0] = signature&0x00ff; - Val[1] = signature>>8; - if (bus_adap->ops->write_ctrl_message(dev, 0x0080, Val, 2) != 2) { - kfree(Val); - return -1; - } - - /* Launch BistRom [(D000-flashSize)..CFF9]+[FFFA..FFFF] computation*/ - Val[0] = 0x0F; - if (bus_adap->ops->write_ctrl_message(dev, 0x0082, Val, 1) != 1) { - kfree(Val); - return -1; - } - - pr_info("\n>>Read Signature\n"); - - /* Read Signature*/ - if (bus_adap->ops->read_ctrl_message(dev, 0x0041, Val, 2) != 2) { - kfree(Val); - return -1; - } - - pr_info("\n>> Bistrom computed = %04X\n", Val[0]|Val[1]<<8); - - /* Read Boot status*/ - if (bus_adap->ops->read_ctrl_message(dev, 0x0009, Val, 1) != 1) { - kfree(Val); - return -1; - } - - pr_info("\n>> BootRom Status = %02X\n", Val[0]); - rv = Val[0]; - kfree(Val); - - return rv; -} - -/****************************************************************************** - * @brief - * Compute BistRom. - * - * @param ptr - * Pointer to buffer with register data - * - * @param size - * Number of register to process - * - * @param FWSign - * Current signature - * - * @return - * None. - ******************************************************************************/ -unsigned int MISR(const unsigned char *ptr, int size, unsigned int FWSign) -{ - int k, i; - - unsigned short mySign; - - for (k = 0; k < size; k++) { - mySign = ptr[k]&0x01; - - for (i = 0; i < 16; i++) { - if (0x88B7 & (1<>i) & 0x01; - } - - mySign |= ((FWSign<<1)^(ptr[k])) & 0x00FE; - mySign |= (FWSign<<1) & 0x00FF00; - - FWSign = mySign; - } - - return FWSign; -} - - -/****************************************************************************** - * @brief - * upload firmware in CIMaX+ chip. - * - * @param dev - * Pointer to usb device. - * - * @param fw_data - * Pointer to buffer with firmware data. - * - * @param FWSign - * Pointer to store computed signature. - * - * @return - * None. - ******************************************************************************/ -int cimaxusb_firmware_upload(struct device_s *bus_adap, - const unsigned char *fw_data, unsigned int *FWSign) -{ - int errno = -EFAULT; - const unsigned char *ptr; - int startAddr = START_FW_ADDR; - unsigned char *recv; - int size; - - struct usb_device *dev = bus_adap->usbdev; - - /* data firmware */ - ptr = fw_data; - ptr += START_FW_ADDR; - - recv = kcalloc(300, sizeof(unsigned char), GFP_KERNEL); - if (!recv) { - pr_err("%s-%s: out of memory.\n", DRIVER_NAME, __func__); - return -ENOMEM; - } - - do { - /* compute the size to send to CIMaX+ */ - size = (startAddr <= (STOP_FW_ADDR + 1 - MAX_FW_PKT_SIZE)) ? - (MAX_FW_PKT_SIZE) : (STOP_FW_ADDR + 1 - startAddr); - /* compute Signature */ - *FWSign = MISR(ptr, size, *FWSign); - - pr_info("%s: firmware start address %08x size %d\n", - DRIVER_NAME, startAddr, size); - - /* upload data firmware */ - if (bus_adap->ops->write_ctrl_message( - dev, startAddr, (void *)ptr, size) != size) { - pr_err("Failed to load CIMaX+ firmware\n"); - errno = -ENODEV; - break; - } - if (bus_adap->ops->read_ctrl_message( - dev, startAddr, (void *)recv, size) != size) { - pr_err("Failed to load CIMaX+ firmware\n"); - errno = -ENODEV; - break; - } - if (memcmp(ptr, recv, size)) { - pr_err("Failed compare at Address 0x%04x\n", - startAddr); - errno = -ENODEV; - break; - } - /* update size sent to CIMaX+ */ - startAddr += size; - ptr += size; - if (startAddr >= STOP_FW_ADDR) - break; - } while (1); - - kfree(recv); - - if (errno == -EFAULT) { - /* upload interrupt vector*/ - ptr = fw_data; - ptr += START_INTVECT_ADDR; - startAddr = START_INTVECT_ADDR; - - /* continue to compute Signature */ - *FWSign = MISR(ptr, 6, *FWSign); - - /* upload interrupt vector data*/ - if (bus_adap->ops->write_ctrl_message( - dev, startAddr, (void *)ptr, 6) != 6) { - pr_err("Failed to load CIMaX firmware(Int vector)\n"); - errno = -ENODEV; - } - } - return (errno == -EFAULT) ? 0 : errno; -} - -/****************************************************************************** - * @brief - * upload and start firmware in CIMaX+ chip. - * - * @param bus_adap - * Pointer to usb device. - * - * @return - * None. - ******************************************************************************/ -int cimaxusb_fw_upload(struct device_s *bus_adap) -{ - int errno = -EFAULT; - const struct firmware *firmware; - char *fw = cimax_fw; - unsigned int FWSign = 0; - int ret; - - struct usb_device *dev = bus_adap->usbdev; - - /* request kernel to locate firmware file */ - errno = request_firmware(&firmware, fw, &dev->dev); - if (errno < 0) { - pr_err("%s: unable to locate firmware file: %s\n", - DRIVER_NAME, fw); - goto error; - } - - errno = cimaxusb_firmware_upload(bus_adap, firmware->data, &FWSign); - if (errno < 0) { - pr_err("%s: unable to upload firmware file: %s\n", - DRIVER_NAME, fw); - goto error; - } - - pr_info("%s: firmware: %s loaded with success. Current Bistrom %04X\n", - DRIVER_NAME, fw, FWSign); - - ret = checkBistRom(bus_adap, START_FW_ADDR, STOP_FW_ADDR, FWSign); - if (ret != 0x02) { - pr_err("\nError: Fail on compare BistRom (%02X) !\n", ret); - errno = -ENODEV; - goto error; - } - - if (bus_adap->ops->init_fw(dev) != 0) { - pr_err("\nError: Fail on INIT command !\n"); - errno = -ENODEV; - goto error; - } - -error: - /* release firmware if needed */ - if (firmware != NULL) - release_firmware(firmware); - return errno; -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h deleted file mode 100644 index bf3f64cab8e3..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_fw.h - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - ******************************************************************************/ - -#ifndef __CIMAXPLUS_USB_FW_H -#define __CIMAXPLUS_USB_FW_H - -/****************************************************************************** - * Include - ******************************************************************************/ -#include "cimax+usb_handle.h" - -/****************************************************************************** - * Defines - ******************************************************************************/ -#define CIMAX_FIRMWARE_NAME "cimax+_usbdvb.bin" -#define START_FW_ADDR 0x8000 -#define STOP_FW_ADDR 0xCFF9 -#define START_INTVECT_ADDR 0xFFFA -#define MAX_FW_PKT_SIZE 256 - -/****************************************************************************** - * Enums - ******************************************************************************/ -/****************************************************************************** - * Structures - ******************************************************************************/ - -/****************************************************************************** - * Functions - ******************************************************************************/ -/****************************************************************************** - * @brief - * upload firmware in CIMaX+ chip. - * - * @param bus_adap - * Pointer to usb device. - * - * @return - * None. - ******************************************************************************/ -int cimaxusb_fw_upload(struct device_s *bus_adap); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h deleted file mode 100644 index 936b9cf56bad..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_handle.h - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - ******************************************************************************/ - -#ifndef __CIMAXPLUS_USB_HDLE_H -#define __CIMAXPLUS_USB_HDLE_H - -#ifdef __KERNEL__ - -struct cimaxusb_priv_ops_t { - int (*write_ctrl_message)( - struct usb_device *dev, int addr, void *data, int size); - - int (*read_ctrl_message)( - struct usb_device *dev, int addr, void *data, int size); - - int (*init_fw)( - struct usb_device *dev); - - int (*write_ep6_message)( - struct usb_device *dev, void *data, int size); - - int (*read_ep5_message)( - struct usb_device *dev, void *data, int size); -}; - -#endif - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c deleted file mode 100644 index ea80b5ef473f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_fw.c - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - ******************************************************************************/ - -/*#define TIMESTAMP*/ - -/****************************************************************************** - * Include - ******************************************************************************/ -#include - -#include "cimax+usb_time.h" - -/****************************************************************************** - * Structures - ******************************************************************************/ -#define err(format, arg...)\ - pr_err("cimax+usb_time: %s> ERROR " format "\n" , \ - __func__, ## arg) -#define info(format, arg...) pr_info("time> " format "\n", ## arg) -/****************************************************************************** - * Globals - ******************************************************************************/ -#ifdef TIMESTAMP -struct item_array_s gstArray; -#endif -/****************************************************************************** - * Functions - ******************************************************************************/ -/****************************************************************************** - * @brief - * Init timestamp. - * - * @param - * None - * - * @return - * None. - ******************************************************************************/ -void InitTimestamp(void) -{ -#ifdef TIMESTAMP - gstArray.count = 0; -#endif - return; -} - -/****************************************************************************** - * @brief - * Set timestamp. - * - * @param pcFormat - * Printf-like format - * - * @return - * None. - ******************************************************************************/ -void SetTimestamp(const char *pcFormat, ...) -{ -#ifdef TIMESTAMP - va_list stArgs; - - if (gstArray.count >= MAX_ITEMS) { - if (gstArray.count++ == MAX_ITEMS) - ShowTimestamp(); - return; - } - ktime_get_ts(&gstArray.stItem[gstArray.count].stTime); - va_start(stArgs, pcFormat); - vsprintf(gstArray.stItem[gstArray.count++].pcLine, pcFormat, stArgs); - va_end(stArgs); -#endif - return; -} - -/****************************************************************************** - * @brief - * Display all timestamps. - * - * @param - * None - * - * @return - * None. - ******************************************************************************/ -void ShowTimestamp(void) -{ -#ifdef TIMESTAMP - int i; - - if (gstArray.count == 0) { - err("No timestamps available"); - return; - } - - info("==============================================================="); - info(" TIMESTAMPS"); - info("==============================================================="); - - for (i = 0; i < gstArray.count; i++) { - info("[%04d] [%03d.%09d] %s", - i, - gstArray.stItem[i].stTime.tv_sec, - gstArray.stItem[i].stTime.tv_nsec, - gstArray.stItem[i].pcLine); - if ((i % 100) == 0) - msleep(20); - } - info("==============================================================="); - gstArray.count = 0; - -#endif - return; -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h deleted file mode 100644 index 0012c64dfba4..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************//** - * @file cimax+usb_time.h - * - * @brief CIMaX+ USB Driver for linux based operating systems. - * - * Copyright (C) 2009-2011 Bruno Tonelli - * & Franck Descours - * for SmarDTV France, La Ciotat - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - ******************************************************************************/ - -#ifndef __CIMAXPLUS_USB_TIME_H -#define __CIMAXPLUS_USB_TIME_H - -/****************************************************************************** - * Include - ******************************************************************************/ -#include - -/****************************************************************************** - * Defines - ******************************************************************************/ -#define MAX_ITEMS 100000 -#define MAX_LINE_SIZE 128 - -/****************************************************************************** - * Enums - ******************************************************************************/ -/****************************************************************************** - * Structures - ******************************************************************************/ -struct item_s { - struct timespec stTime; - char pcLine[MAX_LINE_SIZE]; -}; - -struct item_array_s { - int count; - item_s stItem[MAX_ITEMS]; -}; - -extern struct item_array_s gstArray; - -/****************************************************************************** - * Functions - ******************************************************************************/ -/****************************************************************************** - * @brief - * Init timestamp. - * - * @param - * None - * - * @return - * None. - ******************************************************************************/ -void InitTimestamp(void); - -/****************************************************************************** - * @brief - * Set timestamp. - * - * @param pcFormat - * Printf-like format - * - * @return - * None. - ******************************************************************************/ -void SetTimestamp(const char *pcFormat, ...); - -/****************************************************************************** - * @brief - * Display all timestamps. - * - * @param - * None - * - * @return - * None. - ******************************************************************************/ -void ShowTimestamp(void); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg deleted file mode 100644 index 7e792d80285d..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg +++ /dev/null @@ -1,97 +0,0 @@ -; -; ************************ -; * INIT_TS.TXT SCRIPT * -; ************************ -; -; *** CLOSE INPUT *** -; -IN_SEL 0x00 -; -; *** CLOSE OUPUT *** -; -OUT_SEL 0x00 -; -; *** RESET FIFO *** -; -FIFO_CTRL 0x0f -SYNC_RTV_CTRL 0x0f -; -; -; ************************* -; * INIT_USB.TXT SCRIPT * -; ************************* -; -; *** Endpoint Config *** -; -DMA_ACC_EPS 0x3f -EPS_ENABLE 0x7f -; -; *** FIFO Control *** -; -USB2TS_CTRL 0x0f -TS2USB_CTRL 0x0f -; -; *** FREQ Control *** -; -USB2TS0_RDL 0x80 -USB2TS1_RDL 0x80 -; -;----------------------------------------------------------------------------- -; Set CAM power -;----------------------------------------------------------------------------- -; -GPIO0_DATA_OUT 0x00 -; -; unlock CFG -CFG_2 0x00 -; -; 1) DVB/CI/CI+/SCARD 2slot -CFG_1 0x00 -; -; 2) Set the Default "power off" state such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z' -GPIO0_DFT 0x00 -; -; 3) Set GPIO3 as external power switch driver -GPIO0_MASK_DATA 0x07 -; -; 4) Set "power on" state (VCC=VPP1=VPP2= 5V) -GPIO0_DATA_OUT 0x01 -; -; 5) Lock config -CFG_2 0x01 -; -; 6) Write in the GPIO0_DIR_REG: defines the GPIOs, which -; are used to drive the external power switch, in output mode. -GPIO0_DIR 0x07 -; -; 7) Check VCCENable -?CFG_1 0x20 -; -; 8) Set & wait for PcmciaOutputEnable -|CFG_1 0x08 -?CFG_1 0x08 -; -;--------------------------------------- -; Set Router CAM -;--------------------------------------- -; -; -GAP_REMOVER_CH0_CTRL 0x0C -GAP_REMOVER_CH1_CTRL 0x0C - -; 9) CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1 -; -ROUTER_CAM_MOD 0x21 -ROUTER_CAM_CH 0x00 -; -;_Wait 200 -;--------------------------------------- -; ROUTER CAM -;--------------------------------------- -OUT_SEL 0x03 -; -USB2TS0_RDL 0x80 -USB2TS1_RDL 0x80 -; -IN_SEL 0x22 - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg deleted file mode 100644 index 5c38429e78e5..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg +++ /dev/null @@ -1,136 +0,0 @@ -; -; ************************ -; * INIT_TS.TXT SCRIPT * -; ************************ -; -; *** CLOSE INPUT *** -; -IN_SEL 0x00 -; -; *** CLOSE OUPUT *** -; -OUT_SEL 0x00 -; -; *** RESET FIFO *** -; -FIFO_CTRL 0x0f -SYNC_RTV_CTRL 0x0f -; -; -; ************************* -; * INIT_USB.TXT SCRIPT * -; ************************* -; -; *** Endpoint Config *** -; -DMA_ACC_EPS 0x3f -EPS_ENABLE 0x7f -; -; *** FIFO Control *** -; -USB2TS_CTRL 0x0f -TS2USB_CTRL 0x0f -; -; *** FREQ Control *** -; -USB2TS0_RDL 0x80 -USB2TS1_RDL 0x80 -; -;----------------------------------------------------------------------------- -; Set CAM power -;----------------------------------------------------------------------------- -; -GPIO0_DATA_OUT 0x00 -; -; unlock CFG -CFG_2 0x00 -; -; 1) DVB/CI/CI+/SCARD 2slot -CFG_1 0x00 -; -; 2) Set the Default "power off" state such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z' -GPIO0_DFT 0x00 -; -; 3) Set GPIO3 as external power switch driver -GPIO0_MASK_DATA 0x07 -; -; 4) Set "power on" state (VCC=VPP1=VPP2= 5V) -GPIO0_DATA_OUT 0x01 -; -; 5) Lock config -CFG_2 0x01 -; -; 6) Write in the GPIO0_DIR_REG: defines the GPIOs, which -; are used to drive the external power switch, in output mode. -GPIO0_DIR 0x07 -; -; 7) Check VCCENable -?CFG_1 0x20 -; -; 8) Set & wait for PcmciaOutputEnable -|CFG_1 0x08 -?CFG_1 0x08 -; -;--------------------------------------- -; Set Router CAM -;--------------------------------------- -; -; -GAP_REMOVER_CH0_CTRL 0x0C -GAP_REMOVER_CH1_CTRL 0x0C - -; 9) CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1 -; -ROUTER_CAM_MOD 0x21 -ROUTER_CAM_CH 0x00 -; -;_Wait 200 -;--------------------------------------- -; ROUTER CAM -;--------------------------------------- -OUT_SEL 0x03 -; -USB2TS0_RDL 0x80 -USB2TS1_RDL 0x80 -; -IN_SEL 0x22 - -; *************************** -; * MuliStream.TXT SCRIPT * -; *************************** -; -; *** CLOSE INPUT *** -; -IN_SEL 0x00 -; -; *** CLOSE OUPUT *** -; -OUT_SEL 0x00 -; -; *** RESET FIFO *** -; -FIFO_CTRL 0x0f -SYNC_RTV_CTRL 0x0f -; -; *** *** -; -CkMan_Config 0x1f -CkMan_Select 0x00 -MERGER_DIV_MICLK 0x02 -SYNC_SYMBOL 0x0d -PID_AND_SYNC_REMAPPER_INV_CTRL 0x01 - -FIFO_CTRL 0x0f -ROUTER_CAM_MOD 0x03 -ROUTER_CAM_CH 0x80 - -USB2TS_CTRL 0x0f -TS2USB_CTRL 0x0f -USB2TS0_RDL 0x20 -USB2TS1_RDL 0x20 - -OUT_SEL 0x03 -IN_SEL 0x22 -; -; ************************ -; diff --git a/drivers/amlogic/media_modules/stream_input/parser/psparser.c b/drivers/amlogic/media_modules/stream_input/parser/psparser.c deleted file mode 100644 index 3197976e437e..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/psparser.c +++ /dev/null @@ -1,1152 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/psparser.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -/* #include */ -#include -#include "streambuf_reg.h" -#include "streambuf.h" -#include "psparser.h" -#include "../amports/amports_priv.h" - - -#define TIMESTAMP_IONLY 1 -#define SAVE_SCR 0 - -#define MPEG_START_CODE_PATTERN (0x00000100L) -#define MPEG_START_CODE_MASK (0xffffff00L) -#define MAX_MPG_AUDIOPK_SIZE 0x1000 - -#define SUB_INSERT_START_CODE_HIGH 0x414d4c55 -#define SUB_INSERT_START_CODE_LOW 0xaa000000 - -#define PARSER_WRITE (ES_WRITE | ES_PARSER_START) -#define PARSER_VIDEO (ES_TYPE_VIDEO) -#define PARSER_AUDIO (ES_TYPE_AUDIO) -#define PARSER_SUBPIC (ES_TYPE_SUBTITLE) -#define PARSER_PASSTHROUGH (ES_PASSTHROUGH | ES_PARSER_START) -#define PARSER_AUTOSEARCH (ES_SEARCH | ES_PARSER_START) -#define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START) -#define PARSER_BUSY (ES_PARSER_BUSY) - -#define PARSER_PARAMETER_LENGTH_BIT 16 -#define PARSER_PARAMETER_LOOP_BIT 24 - -#define PARSER_POP READ_PARSER_REG(PFIFO_DATA) -#define SET_BLOCK(size) \ -WRITE_PARSER_REG_BITS(PARSER_CONTROL, size, ES_PACK_SIZE_BIT, ES_PACK_SIZE_WID) -#define SET_DISCARD_SIZE(size) WRITE_PARSER_REG(PARSER_PARAMETER, size) - -#define VIDEO_AUTO_FLUSH -#ifdef VIDEO_AUTO_FLUSH -static u32 video_auto_flush_state; -#define VIDEO_AUTO_FLUSH_IDLE 0 -#define VIDEO_AUTO_FLUSH_MONITOR 1 -#define VIDEO_AUTO_FLUSH_TRIGGER 2 -#define VIDEO_AUTO_FLUSH_DONE 3 -#define VIDEO_AUTO_FLUSH_PTS_THRESHOLD 90000 -#define VIDEO_AUTO_FLUSH_BYTE_COUNT 1024 - -static s32 audio_last_pts; -static s32 audio_monitor_pts; -#endif - -enum { - SEARCH_START_CODE = 0, - SEND_VIDEO_SEARCH, - SEND_AUDIO_SEARCH, - SEND_SUBPIC_SEARCH, - DISCARD_SEARCH, - DISCARD_ONLY -#ifdef VIDEO_AUTO_FLUSH - , - SEARCH_START_CODE_VIDEO_FLUSH -#endif -}; - -enum { - AUDIO_FIRST_ACCESS_ARM = 0, - AUDIO_FIRST_ACCESS_POPING, - AUDIO_FIRST_ACCESS_DONE -}; - -static const char psparser_id[] = "psparser-id"; - -static DECLARE_WAIT_QUEUE_HEAD(wq); - -static struct tasklet_struct psparser_tasklet; -static u32 fetch_done; -static u8 audio_id, video_id, sub_id, sub_id_max; -static u32 audio_first_access; -static u32 packet_remaining; -static u32 video_data_parsed; -static u32 audio_data_parsed; -static u32 pts_equ_dts_flag; - -static unsigned int first_apts, first_vpts; -static unsigned int audio_got_first_pts, video_got_first_dts, sub_got_first_pts; -atomic_t sub_block_found = ATOMIC_INIT(0); - -#define DEBUG_VOB_SUB -#ifdef DEBUG_VOB_SUB -static u8 sub_found_num; -static struct subtitle_info *sub_info[MAX_SUB_NUM]; -#endif - -static bool ptsmgr_first_vpts_ready(void) -{ - return (video_got_first_dts != 0) ? true : false; -} - -static bool ptsmgr_first_apts_ready(void) -{ - return (audio_got_first_pts != 0) ? true : false; -} - -static void ptsmgr_vpts_checkin(u32 pts) -{ - if (video_got_first_dts == 0) { - video_got_first_dts = 1; - first_vpts = pts; - } - - pts_checkin_offset(PTS_TYPE_VIDEO, video_data_parsed, pts); -} - -static void ptsmgr_apts_checkin(u32 pts) -{ - if (audio_got_first_pts == 0) { - audio_got_first_pts = 1; - first_apts = pts; - } - /* apts_checkin(pts); */ - pts_checkin_offset(PTS_TYPE_AUDIO, audio_data_parsed, pts); - -#ifdef VIDEO_AUTO_FLUSH - audio_last_pts = pts; - - if ((video_auto_flush_state == VIDEO_AUTO_FLUSH_IDLE) - && ptsmgr_first_vpts_ready()) { - video_auto_flush_state = VIDEO_AUTO_FLUSH_MONITOR; - audio_monitor_pts = pts; - } - - if (video_auto_flush_state == VIDEO_AUTO_FLUSH_MONITOR) { - if ((audio_last_pts - audio_monitor_pts) > - VIDEO_AUTO_FLUSH_PTS_THRESHOLD) - video_auto_flush_state = VIDEO_AUTO_FLUSH_TRIGGER; - } -#endif -} - -static u32 parser_process(s32 type, s32 packet_len) -{ - s16 temp, header_len, misc_flags, i; - u32 pts = 0, dts = 0; - u32 pts_dts_flag = 0; - u16 invalid_pts = 0; - - temp = PARSER_POP; - packet_len--; - - if ((temp >> 6) == 0x02) { - /* mpeg-2 system */ - misc_flags = PARSER_POP; - header_len = PARSER_POP; - packet_len -= 2; - packet_len -= header_len; - - if ((misc_flags >> 6) > 1) { - /* PTS exist */ - pts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */ - pts |= PARSER_POP << 22; /* bit 29-22 */ - pts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ - pts |= (PARSER_POP << 7); /* bit 14-07 */ - pts |= (PARSER_POP >> 1); /* bit 06-00 */ - header_len -= 5; - pts_dts_flag |= 2; - } - - if ((misc_flags >> 6) > 2) { - /* DTS exist */ - dts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */ - dts |= PARSER_POP << 22; /* bit 29-22 */ - dts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ - dts |= (PARSER_POP << 7); /* bit 14-07 */ - dts |= (PARSER_POP >> 1); /* bit 06-00 */ - header_len -= 5; - pts_dts_flag |= 1; - } - - if (misc_flags & 0x20) { - /* ESCR_flag */ - PARSER_POP; - PARSER_POP; - PARSER_POP; - PARSER_POP; - PARSER_POP; - PARSER_POP; - header_len -= 5; - } - - if (misc_flags & 0x10) { - /* ES_rate_flag */ - PARSER_POP; - PARSER_POP; - PARSER_POP; - header_len -= 3; - } - - if (misc_flags & 0x08) { - /* DSM_trick_mode_flag */ - PARSER_POP; - header_len -= 1; - } - - if (misc_flags & 0x04) { - /* additional_copy_info_flag */ - PARSER_POP; - header_len -= 1; - } - - if (misc_flags & 0x02) { - /* PES_CRC_flag */ - PARSER_POP; - PARSER_POP; - header_len -= 2; - } - - if (misc_flags & 0x01) { - /* PES_extension_flag */ - misc_flags = PARSER_POP; - header_len--; - - if ((misc_flags & 0x80) && (header_len >= 128)) { - /* PES_private_data_flag */ - for (i = 0; i < 128; i++) - PARSER_POP; - - header_len -= 128; - } -#if 0 - if (misc_flags & 0x40) { - /* pack_header_field_flag */ - /* Invalid case */ - } -#endif - if (misc_flags & 0x20) { - /* program_packet_sequence_counter_flag */ - PARSER_POP; - PARSER_POP; - header_len -= 2; - } - - if (misc_flags & 0x10) { - /* PSTD_buffer_flag */ - PARSER_POP; - PARSER_POP; - header_len -= 2; - } - - if (misc_flags & 1) { - /* PES_extension_flag_2 */ - temp = PARSER_POP & 0x7f; - - while (temp) { - PARSER_POP; - temp--; - header_len--; - } - } - - while (header_len) { - PARSER_POP; - header_len--; - } - } - - while (header_len) { - PARSER_POP; - header_len--; - } - - } else { - /* mpeg-1 system */ - while (temp == 0xff) { - temp = PARSER_POP; - packet_len--; - } - - if ((temp >> 6) == 1) { - PARSER_POP; /* STD buffer size */ - temp = PARSER_POP; - packet_len -= 2; - } - - if (((temp >> 4) == 2) || ((temp >> 4) == 3)) { - pts = ((temp >> 1) & 7) << 30; /* bit 32-30 */ - pts |= PARSER_POP << 22; /* bit 29-22 */ - pts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ - pts |= (PARSER_POP << 7); /* bit 14-07 */ - pts |= (PARSER_POP >> 1); /* bit 06-00 */ - packet_len -= 4; - pts_dts_flag |= 2; - } - - if ((temp >> 4) == 3) { - dts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */ - dts |= PARSER_POP << 22; /* bit 29-22 */ - dts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ - dts |= (PARSER_POP << 7); /* bit 14-07 */ - dts |= (PARSER_POP >> 1); /* bit 06-00 */ - packet_len -= 5; - pts_dts_flag |= 1; - } - } - - if ((pts == 0) && (dts == 0xffffffff)) { - invalid_pts = 1; - pr_info("invalid pts\n"); - } - - if (!packet_len) - return SEARCH_START_CODE; - - else if (type == 0) { -#ifdef VIDEO_AUTO_FLUSH - if (video_auto_flush_state == VIDEO_AUTO_FLUSH_MONITOR) - audio_monitor_pts = audio_last_pts; -#endif - - if ((pts_dts_flag) && (!invalid_pts)) { -#if TIMESTAMP_IONLY - if (!ptsmgr_first_vpts_ready()) { - if (pts_dts_flag & 2) - ptsmgr_vpts_checkin(pts); - else - ptsmgr_vpts_checkin(dts); - } else if ((pts_dts_flag & 3) == 3) { - if (pts_equ_dts_flag) { - if (dts == pts) - ptsmgr_vpts_checkin(pts); - } else { - if (dts == pts) - pts_equ_dts_flag = 1; - ptsmgr_vpts_checkin(pts); - } - } -#else - if (!ptsmgr_first_vpts_ready()) { - if (pts_dts_flag & 2) - ptsmgr_vpts_checkin(pts); - else - ptsmgr_vpts_checkin(dts); - } else if (pts_dts_flag & 2) - ptsmgr_vpts_checkin(pts); -#endif - } - - if (ptsmgr_first_vpts_ready() || invalid_pts) { - SET_BLOCK(packet_len); - video_data_parsed += packet_len; - return SEND_VIDEO_SEARCH; - - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - - } else if (type == 1) { - /* mpeg audio */ - if (pts_dts_flag & 2) - ptsmgr_apts_checkin(pts); - - if (ptsmgr_first_apts_ready()) { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - - } else if (type == 2) { - /* Private stream */ - temp = PARSER_POP; /* sub_stream_id */ - packet_len--; - - if (((temp & 0xf8) == 0xa0) && (temp == audio_id)) { - /* DVD_VIDEO Audio LPCM data */ - PARSER_POP; - temp = (PARSER_POP << 8) | PARSER_POP; - if (temp == 0) - temp = 4; - temp--; - packet_len -= 3; - - if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) { - if (temp) { - packet_remaining = packet_len - temp; - SET_DISCARD_SIZE(temp); - audio_first_access = - AUDIO_FIRST_ACCESS_POPING; - return DISCARD_ONLY; - } - - audio_first_access = AUDIO_FIRST_ACCESS_DONE; - - if (packet_len) { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - - } else - return SEARCH_START_CODE; - - } else { - PARSER_POP; - PARSER_POP; - PARSER_POP; - packet_len -= 3; - } - - if (pts_dts_flag & 2) - ptsmgr_apts_checkin(pts); - - if (ptsmgr_first_apts_ready()) { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - - } else if (((temp & 0xf8) == 0x80) && (temp == audio_id)) { - /* Audio AC3 data */ - PARSER_POP; - temp = (PARSER_POP << 8) | PARSER_POP; - packet_len -= 3; - - if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) { - if (pts_dts_flag & 2) - ptsmgr_apts_checkin(pts); - - if ((temp > 2) && (packet_len > (temp - 2))) { - temp -= 2; - packet_remaining = packet_len - temp; - SET_DISCARD_SIZE(temp); - audio_first_access = - AUDIO_FIRST_ACCESS_POPING; - return DISCARD_ONLY; - } - - audio_first_access = AUDIO_FIRST_ACCESS_DONE; - - if (packet_len) { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - - } else - return SEARCH_START_CODE; - } - - if (pts_dts_flag & 2) - ptsmgr_apts_checkin(pts); - - if (ptsmgr_first_apts_ready()) { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - - } else if (((temp & 0xf8) == 0x88) && (temp == audio_id)) { - /* Audio DTS data */ - PARSER_POP; - PARSER_POP; - PARSER_POP; - packet_len -= 3; - - if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) - audio_first_access = AUDIO_FIRST_ACCESS_DONE; - - if (pts_dts_flag & 2) - ptsmgr_apts_checkin(pts); - - if (ptsmgr_first_apts_ready()) { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - } else if ((temp & 0xe0) == 0x20) { - if (temp > sub_id_max) - sub_id_max = temp; -#ifdef DEBUG_VOB_SUB - for (i = 0; i < sub_found_num; i++) { - if (!sub_info[i]) - break; - if (temp == sub_info[i]->id) - break; - } - if (i == sub_found_num && i < MAX_SUB_NUM) { - if (sub_info[sub_found_num]) { - sub_info[sub_found_num]->id = temp; - sub_found_num++; - pr_info - ("[%s]found new sub_id=0x%x (num %d)\n", - __func__, temp, sub_found_num); - } else { - pr_info - ("[%s]sub info NULL!\n", __func__); - } - } -#endif - - if (temp == sub_id) { - /* DVD sub-picture data */ - if (!packet_len) - return SEARCH_START_CODE; - - else { -#if 0 - if (pts_dts_flag & 2) - ptsmgr_spts_checkin(pts); - - if (ptsmgr_first_spts_ready()) { - SET_BLOCK(packet_len); - return SEND_SUBPIC_SEARCH; - - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } -#else - if (pts_dts_flag & 2) - sub_got_first_pts = 1; - - if (sub_got_first_pts) { - pr_info - ("sub pts 0x%x, len %d\n", - pts, packet_len); - SET_BLOCK(packet_len); - WRITE_PARSER_REG - (PARSER_PARAMETER, - 16 << - PARSER_PARAMETER_LENGTH_BIT); - WRITE_PARSER_REG - (PARSER_INSERT_DATA, - SUB_INSERT_START_CODE_HIGH); - WRITE_PARSER_REG - (PARSER_INSERT_DATA, - SUB_INSERT_START_CODE_LOW | - get_sub_type()); - WRITE_PARSER_REG - (PARSER_INSERT_DATA, - packet_len); - WRITE_PARSER_REG - (PARSER_INSERT_DATA, pts); - atomic_set(&sub_block_found, 1); - return SEND_SUBPIC_SEARCH; - } - - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; -#endif - } - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - } else { - SET_DISCARD_SIZE(packet_len); - return DISCARD_SEARCH; - } - } - - return SEARCH_START_CODE; -} - -static void on_start_code_found(int start_code) -{ - unsigned short packet_len; - unsigned short temp; - unsigned int next_action; -#if SAVE_SCR - unsigned int scr; -#endif - - if (atomic_read(&sub_block_found)) { - wakeup_sub_poll(); - atomic_set(&sub_block_found, 0); - } - - if (audio_first_access == AUDIO_FIRST_ACCESS_POPING) { - /* - *we are in the procedure of poping data for audio first - * access, continue with last packet - */ - audio_first_access = AUDIO_FIRST_ACCESS_DONE; - - if (packet_remaining) { - next_action = SEND_AUDIO_SEARCH; - SET_BLOCK(packet_remaining); - - } else - next_action = SEARCH_START_CODE; - - } else if (start_code == 0xba) { /* PACK_START_CODE */ - temp = PARSER_POP; - - if ((temp >> 6) == 0x01) { -#if SAVE_SCR - scr = ((temp >> 3) & 0x3) << 30; /* bit 31-30 */ - scr |= (temp & 0x3) << 28; /* bit 29-28 */ - scr |= (PARSER_POP) << 20; /* bit 27-20 */ - temp = PARSER_POP; - scr |= (temp >> 4) << 16; /* bit 19-16 */ - scr |= (temp & 7) << 13; /* bit 15-13 */ - scr |= (PARSER_POP) << 5; /* bit 12-05 */ - scr |= (PARSER_POP) >> 3; /* bit 04-00 */ -#else - PARSER_POP; - PARSER_POP; - PARSER_POP; - PARSER_POP; -#endif - PARSER_POP; - PARSER_POP; - PARSER_POP; - PARSER_POP; - temp = PARSER_POP & 7; - - while (temp) { /* stuff byte */ - PARSER_POP; - temp--; - } - - } else { - /* mpeg-1 Pack Header */ -#if SAVE_SCR - scr = ((temp >> 1) & 0x3) << 30; /* bit 31-30 */ - scr |= (PARSER_POP) << 22; /* bit 29-22 */ - scr |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ - scr |= (PARSER_POP) << 7; /* bit 14-07 */ - scr |= (PARSER_POP >> 1); /* bit 06-00 */ -#else - PARSER_POP; - PARSER_POP; - PARSER_POP; - PARSER_POP; -#endif - } - -#ifdef VIDEO_AUTO_FLUSH - if (video_auto_flush_state == VIDEO_AUTO_FLUSH_TRIGGER) { - next_action = SEARCH_START_CODE_VIDEO_FLUSH; - video_auto_flush_state = VIDEO_AUTO_FLUSH_DONE; - } else -#endif - - next_action = SEARCH_START_CODE; - - } else { - packet_len = (PARSER_POP << 8) | PARSER_POP; - - if (start_code == video_id) - next_action = parser_process(0, packet_len); - - else if (start_code == audio_id) { - /* add mpeg audio packet length check */ - if (packet_len > MAX_MPG_AUDIOPK_SIZE) - next_action = SEARCH_START_CODE; - - else - next_action = parser_process(1, packet_len); - - } else if (start_code == 0xbb) { - SET_DISCARD_SIZE(packet_len); - next_action = DISCARD_SEARCH; - } else if (start_code == 0xbd) - next_action = parser_process(2, packet_len); - - else if (start_code == 0xbf) { - SET_DISCARD_SIZE(packet_len); - next_action = DISCARD_SEARCH; - } else if ((start_code < 0xc0) || (start_code > 0xc8)) - next_action = SEARCH_START_CODE; - - else if (packet_len) { - SET_DISCARD_SIZE(packet_len); - next_action = DISCARD_SEARCH; - - } else - next_action = SEARCH_START_CODE; - } - - switch (next_action) { - case SEARCH_START_CODE: - WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH); - break; - - case SEND_VIDEO_SEARCH: - WRITE_PARSER_REG_BITS(PARSER_CONTROL, - PARSER_AUTOSEARCH | PARSER_VIDEO | - PARSER_WRITE, ES_CTRL_BIT, ES_CTRL_WID); - break; - - case SEND_AUDIO_SEARCH: - WRITE_PARSER_REG_BITS(PARSER_CONTROL, - PARSER_AUTOSEARCH | PARSER_AUDIO | - PARSER_WRITE, ES_CTRL_BIT, ES_CTRL_WID); - break; - - case SEND_SUBPIC_SEARCH: - WRITE_PARSER_REG_BITS(PARSER_CONTROL, - PARSER_AUTOSEARCH | PARSER_SUBPIC | - PARSER_WRITE | ES_INSERT_BEFORE_ES_WRITE, - ES_CTRL_BIT, ES_CTRL_WID); - break; - - case DISCARD_SEARCH: - WRITE_PARSER_REG_BITS(PARSER_CONTROL, - PARSER_AUTOSEARCH | PARSER_DISCARD, - ES_CTRL_BIT, ES_CTRL_WID); - break; - - case DISCARD_ONLY: - WRITE_PARSER_REG_BITS(PARSER_CONTROL, - PARSER_DISCARD, ES_CTRL_BIT, ES_CTRL_WID); - break; - -#ifdef VIDEO_AUTO_FLUSH - case SEARCH_START_CODE_VIDEO_FLUSH: - WRITE_PARSER_REG(PARSER_INSERT_DATA, 0xffffffff); - WRITE_PARSER_REG(PARSER_INSERT_DATA, 0xffffffff); - WRITE_PARSER_REG(PARSER_PARAMETER, - ((VIDEO_AUTO_FLUSH_BYTE_COUNT / - 8) << PARSER_PARAMETER_LOOP_BIT) | (8 << - PARSER_PARAMETER_LENGTH_BIT)); - WRITE_PARSER_REG(PARSER_CONTROL, - PARSER_AUTOSEARCH | PARSER_VIDEO | PARSER_WRITE | - ES_INSERT_BEFORE_ES_WRITE); - break; -#endif - } -} - -static void parser_tasklet(ulong data) -{ - s32 sc; - u32 int_status = READ_PARSER_REG(PARSER_INT_STATUS); - - WRITE_PARSER_REG(PARSER_INT_STATUS, int_status); - - if (int_status & PARSER_INTSTAT_FETCH_CMD) { - fetch_done = 1; - - wake_up_interruptible(&wq); - } - - if (int_status & PARSER_INTSTAT_SC_FOUND) { - sc = PARSER_POP; - - on_start_code_found(sc); - - } else if (int_status & PARSER_INTSTAT_DISCARD) - on_start_code_found(0); -} - -static irqreturn_t parser_isr(int irq, void *dev_id) -{ - tasklet_schedule(&psparser_tasklet); - - return IRQ_HANDLED; -} - -static ssize_t _psparser_write(const char __user *buf, size_t count) -{ - size_t r = count; - const char __user *p = buf; - u32 len; - int ret; - dma_addr_t dma_addr = 0; - - if (r > 0) { - len = min_t(size_t, r, FETCHBUF_SIZE); - if (copy_from_user(fetchbuf, p, len)) - return -EFAULT; - - dma_addr = - dma_map_single(amports_get_dma_device(), - fetchbuf, FETCHBUF_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), dma_addr)) - return -EFAULT; - - - fetch_done = 0; - - wmb(); /* Ensure fetchbuf contents visible */ - - WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr); - - WRITE_PARSER_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len); - dma_unmap_single(amports_get_dma_device(), dma_addr, - FETCHBUF_SIZE, DMA_TO_DEVICE); - ret = - wait_event_interruptible_timeout(wq, fetch_done != 0, - HZ / 10); - if (ret == 0) { - WRITE_PARSER_REG(PARSER_FETCH_CMD, 0); - pr_info("write timeout, retry\n"); - return -EAGAIN; - } else if (ret < 0) - return -ERESTARTSYS; - - p += len; - r -= len; - } - - return count - r; -} - -s32 psparser_init(u32 vid, u32 aid, u32 sid, struct vdec_s *vdec) -{ - s32 r; - u32 parser_sub_start_ptr; - u32 parser_sub_end_ptr; - u32 parser_sub_rp; - -#ifdef DEBUG_VOB_SUB - u8 i; - - for (i = 0; i < MAX_SUB_NUM; i++) { - sub_info[i] = kzalloc(sizeof(struct subtitle_info), GFP_KERNEL); - if (!sub_info[i]) { - pr_info - ("[psparser_init]alloc for subtitle info failed\n"); - } else - sub_info[i]->id = -1; - } - sub_found_num = 0; -#endif - parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR); - parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR); - parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP); - - video_id = vid; - audio_id = aid; - sub_id = sid; - audio_got_first_pts = 0; - video_got_first_dts = 0; - sub_got_first_pts = 0; - first_apts = 0; - first_vpts = 0; - pts_equ_dts_flag = 0; - -#ifdef VIDEO_AUTO_FLUSH - video_auto_flush_state = VIDEO_AUTO_FLUSH_IDLE; -#endif - - pr_info("video 0x%x, audio 0x%x, sub 0x%x\n", video_id, audio_id, - sub_id); - if (fetchbuf == 0) { - pr_info("%s: no fetchbuf\n", __func__); - return -ENOMEM; - } - - WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER); - - /* TS data path */ -#ifndef CONFIG_AM_DVB - WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0); -#else - tsdemux_set_reset_flag(); -#endif - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE)); - - /* hook stream buffer with PARSER */ - WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, - vdec->input.start + vdec->input.size - 8); - - if (vdec_single(vdec)) { - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - } else { - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); - WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start); - } - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_PARSER_REG(PARSER_CONFIG, - (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | - (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | - (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); - - if (vdec_single(vdec)) { - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - } - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); - WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); - - WRITE_PARSER_REG(PFIFO_RD_PTR, 0); - WRITE_PARSER_REG(PFIFO_WR_PTR, 0); - - WRITE_PARSER_REG(PARSER_SEARCH_PATTERN, MPEG_START_CODE_PATTERN); - WRITE_PARSER_REG(PARSER_SEARCH_MASK, MPEG_START_CODE_MASK); - - WRITE_PARSER_REG(PARSER_CONFIG, - (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | - (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | - PS_CFG_STARTCODE_WID_24 | - PS_CFG_PFIFO_ACCESS_WID_8 | /* single byte pop */ - (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); - WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH); - - tasklet_init(&psparser_tasklet, parser_tasklet, 0); - r = pts_start(PTS_TYPE_VIDEO); - if (r < 0) - goto Err_1; - r = pts_start(PTS_TYPE_AUDIO); - if (r < 0) - goto Err_2; - - video_data_parsed = 0; - audio_data_parsed = 0; - /*TODO irq */ - - r = vdec_request_irq(PARSER_IRQ, parser_isr, - "psparser", (void *)psparser_id); - - if (r) { - pr_info("PS Demux irq register failed.\n"); - - r = -ENOENT; - goto Err_3; - } - - WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff); - WRITE_PARSER_REG(PARSER_INT_ENABLE, - PARSER_INT_ALL << PARSER_INT_HOST_EN_BIT); - - return 0; - -Err_3: - pts_stop(PTS_TYPE_AUDIO); - -Err_2: - pts_stop(PTS_TYPE_VIDEO); - -Err_1: - return r; -} - -void psparser_release(void) -{ - u8 i; - - pr_info("psparser_release\n"); - - WRITE_PARSER_REG(PARSER_INT_ENABLE, 0); - /*TODO irq */ - - vdec_free_irq(PARSER_IRQ, (void *)psparser_id); - - pts_stop(PTS_TYPE_VIDEO); - pts_stop(PTS_TYPE_AUDIO); -#ifdef DEBUG_VOB_SUB - for (i = 0; i < MAX_SUB_NUM; i++) - kfree(sub_info[i]); - pr_info("psparser release subtitle info\n"); -#endif -} -EXPORT_SYMBOL(psparser_release); - -ssize_t psparser_write(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count) -{ - s32 r; - - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - - if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - if ((port->flag & PORT_FLAG_VID) - && (stbuf_space(vbuf) < count)) { - r = stbuf_wait_space(vbuf, count); - if (r < 0) - return r; - } - if ((port->flag & PORT_FLAG_AID) - && (stbuf_space(abuf) < count)) { - r = stbuf_wait_space(abuf, count); - if (r < 0) - return r; - } - } - - return _psparser_write(buf, count); -} - -void psparser_change_avid(unsigned int vid, unsigned int aid) -{ - video_id = vid; - audio_id = aid; -} - -void psparser_change_sid(unsigned int sid) -{ - sub_id = sid; -} - -void psparser_audio_reset(void) -{ - ulong flags; - - DEFINE_SPINLOCK(lock); - - spin_lock_irqsave(&lock, flags); - - WRITE_PARSER_REG(PARSER_AUDIO_WP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_RP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - audio_data_parsed = 0; - - spin_unlock_irqrestore(&lock, flags); - -} - -void psparser_sub_reset(void) -{ - ulong flags; - - DEFINE_SPINLOCK(lock); - u32 parser_sub_start_ptr; - u32 parser_sub_end_ptr; - - spin_lock_irqsave(&lock, flags); - - parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR); - parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR); - - WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); - WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); - - spin_unlock_irqrestore(&lock, flags); - -} - -u8 psparser_get_sub_found_num(void) -{ -#ifdef DEBUG_VOB_SUB - return sub_found_num; -#else - return 0; -#endif -} - -u8 psparser_get_sub_info(struct subtitle_info **sub_infos) -{ -#ifdef DEBUG_VOB_SUB - u8 i = 0; - int ret = 0; - u8 size = sizeof(struct subtitle_info); - - for (i = 0; i < sub_found_num; i++) { - if (!sub_info[i]) { - pr_info - ("[psparser_get_sub_info:%d] sub_info[%d] NULL\n", - __LINE__, i); - ret = -1; - break; - } - if (!sub_infos[i]) { - pr_info - ("[psparser_get_sub_info:%d] sub_infos[%d] NULL\n", - __LINE__, i); - ret = -2; - break; - } - memcpy(sub_infos[i], sub_info[i], size); - } - return ret; -#else - return 0; -#endif -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/psparser.h b/drivers/amlogic/media_modules/stream_input/parser/psparser.h deleted file mode 100644 index b83e342d024c..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/psparser.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/psparser.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef PSPARSER_H -#define PSPARSER_H - -#include "../../frame_provider/decoder/utils/vdec.h" - -extern s32 psparser_init(u32 vid, u32 aid, u32 sid, struct vdec_s *vdec); - -extern void psparser_release(void); - -extern ssize_t psparser_write(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count); - -extern void psparser_change_avid(unsigned int vid, unsigned int aid); - -extern void psparser_change_sid(unsigned int sid); - -extern void psparser_audio_reset(void); - -extern void psparser_sub_reset(void); - -extern u8 psparser_get_sub_found_num(void); - -extern u8 psparser_get_sub_info(struct subtitle_info *sub_infos[]); - -#ifdef CONFIG_AM_DVB -extern int tsdemux_set_reset_flag(void); -#endif - -/* TODO: move to register headers */ -#define ES_PACK_SIZE_BIT 8 -#define ES_PACK_SIZE_WID 24 - -#define ES_CTRL_WID 8 -#define ES_CTRL_BIT 0 -#define ES_TYPE_MASK (3 << 6) -#define ES_TYPE_VIDEO (0 << 6) -#define ES_TYPE_AUDIO (1 << 6) -#define ES_TYPE_SUBTITLE (2 << 6) - -#define ES_WRITE (1<<5) -#define ES_PASSTHROUGH (1<<4) -#define ES_INSERT_BEFORE_ES_WRITE (1<<3) -#define ES_DISCARD (1<<2) -#define ES_SEARCH (1<<1) -#define ES_PARSER_START (1<<0) -#define ES_PARSER_BUSY (1<<0) - -#define PARSER_INTSTAT_FETCH_CMD (1<<7) -#define PARSER_INTSTAT_PARSE (1<<4) -#define PARSER_INTSTAT_DISCARD (1<<3) -#define PARSER_INTSTAT_INSZERO (1<<2) -#define PARSER_INTSTAT_ACT_NOSSC (1<<1) -#define PARSER_INTSTAT_SC_FOUND (1<<0) - -#define FETCH_CIR_BUF (1<<31) -#define FETCH_CHK_BUF_STOP (1<<30) -#define FETCH_PASSTHROUGH (1<<29) -#define FETCH_ENDIAN 27 -#define FETCH_PASSTHROUGH_TYPE_MASK (0x3<<27) -#define FETCH_ENDIAN_MASK (0x7<<27) -#define FETCH_BUF_SIZE_MASK (0x7ffffff) -#define FETCH_CMD_PTR_MASK 3 -#define FETCH_CMD_RD_PTR_BIT 5 -#define FETCH_CMD_WR_PTR_BIT 3 -#define FETCH_CMD_NUM_MASK 3 -#define FETCH_CMD_NUM_BIT 0 - -#define ES_COUNT_MASK 0xfff -#define ES_COUNT_BIT 20 -#define ES_REQ_PENDING (1<<19) -#define ES_PASSTHROUGH_EN (1<<18) -#define ES_PASSTHROUGH_TYPE_MASK (3<<16) -#define ES_PASSTHROUGH_TYPE_VIDEO (0<<16) -#define ES_PASSTHROUGH_TYPE_AUDIO (1<<16) -#define ES_PASSTHROUGH_TYPE_SUBTITLE (2<<16) -#define ES_WR_ENDIAN_MASK (0x7) -#define ES_SUB_WR_ENDIAN_BIT 9 -#define ES_SUB_MAN_RD_PTR (1<<8) -#define ES_AUD_WR_ENDIAN_BIT 5 -#define ES_AUD_MAN_RD_PTR (1<<4) -#define ES_VID_WR_ENDIAN_BIT 1 -#define ES_VID_MAN_RD_PTR (1<<0) - -#define PS_CFG_FETCH_DMA_URGENT (1<<31) -#define PS_CFG_STREAM_DMA_URGENT (1<<30) -#define PS_CFG_FORCE_PFIFO_REN (1<<29) -#define PS_CFG_PFIFO_PEAK_EN (1<<28) -#define PS_CFG_SRC_SEL_BIT 24 -#define PS_CFG_SRC_SEL_MASK (3< -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../amports/amports_priv.h" -#include "streambuf.h" -#include "streambuf_reg.h" -#include -#include "rmparser.h" - -#define MANAGE_PTS - -static u32 fetch_done; -static u32 parse_halt; - -static DECLARE_WAIT_QUEUE_HEAD(rm_wq); -static const char rmparser_id[] = "rmparser-id"; - -static irqreturn_t rm_parser_isr(int irq, void *dev_id) -{ - u32 int_status = READ_PARSER_REG(PARSER_INT_STATUS); - - if (int_status & PARSER_INTSTAT_FETCH_CMD) { - WRITE_PARSER_REG(PARSER_INT_STATUS, PARSER_INTSTAT_FETCH_CMD); - fetch_done = 1; - - wake_up_interruptible(&rm_wq); - } - - return IRQ_HANDLED; -} - -s32 rmparser_init(struct vdec_s *vdec) -{ - s32 r; - - parse_halt = 0; - if (fetchbuf == 0) { - pr_info("%s: no fetchbuf\n", __func__); - return -ENOMEM; - } - - WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER); - - /* TS data path */ -#ifndef CONFIG_AM_DVB - WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0); -#else - tsdemux_set_reset_flag(); -#endif - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE); - CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE); - - CLEAR_DEMUX_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE)); - - /* hook stream buffer with PARSER */ - WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, - vdec->input.start + vdec->input.size - 8); - - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - WRITE_PARSER_REG(PFIFO_RD_PTR, 0); - WRITE_PARSER_REG(PFIFO_WR_PTR, 0); - - WRITE_PARSER_REG(PARSER_SEARCH_MASK, 0); - WRITE_PARSER_REG(PARSER_CONTROL, (ES_SEARCH | ES_PARSER_START)); - -#ifdef MANAGE_PTS - if (pts_start(PTS_TYPE_VIDEO) < 0) - goto Err_1; - - if (pts_start(PTS_TYPE_AUDIO) < 0) - goto Err_2; -#endif - /*TODO irq */ - - /* enable interrupt */ - - r = vdec_request_irq(PARSER_IRQ, rm_parser_isr, - "rmparser", (void *)rmparser_id); - - if (r) { - pr_info("RM parser irq register failed.\n"); - goto Err_3; - } - - WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff); - WRITE_PARSER_REG(PARSER_INT_ENABLE, - ((PARSER_INT_ALL & (~PARSER_INTSTAT_FETCH_CMD)) << - PARSER_INT_AMRISC_EN_BIT) - | (PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT)); - - return 0; - -Err_3: - pts_stop(PTS_TYPE_AUDIO); -Err_2: - pts_stop(PTS_TYPE_VIDEO); -Err_1: - return -ENOENT; -} -EXPORT_SYMBOL(rmparser_init); - -void rmparser_release(void) -{ - WRITE_PARSER_REG(PARSER_INT_ENABLE, 0); - /*TODO irq */ - - vdec_free_irq(PARSER_IRQ, (void *)rmparser_id); - -#ifdef MANAGE_PTS - pts_stop(PTS_TYPE_VIDEO); - pts_stop(PTS_TYPE_AUDIO); -#endif - -} -EXPORT_SYMBOL(rmparser_release); - -static inline u32 buf_wp(u32 type) -{ - return (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) : - (type == BUF_TYPE_AUDIO) ? - READ_AIU_REG(AIU_MEM_AIFIFO_MAN_WP) : - READ_PARSER_REG(PARSER_SUB_START_PTR); -} - -static ssize_t _rmparser_write(const char __user *buf, size_t count) -{ - size_t r = count; - const char __user *p = buf; - u32 len; - int ret; - static int halt_droped_len; - u32 vwp, awp; - dma_addr_t dma_addr = 0; - - if (r > 0) { - len = min_t(size_t, r, FETCHBUF_SIZE); - - if (copy_from_user(fetchbuf, p, len)) - return -EFAULT; - dma_addr = - dma_map_single(amports_get_dma_device(), - fetchbuf, FETCHBUF_SIZE, - DMA_TO_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), dma_addr)) - return -EFAULT; - - fetch_done = 0; - - wmb(); /* Ensure fetchbuf contents visible */ - vwp = buf_wp(BUF_TYPE_VIDEO); - awp = buf_wp(BUF_TYPE_AUDIO); - WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr); - - WRITE_PARSER_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len); - dma_unmap_single(amports_get_dma_device(), dma_addr, - FETCHBUF_SIZE, DMA_TO_DEVICE); - ret = - wait_event_interruptible_timeout(rm_wq, fetch_done != 0, - HZ / 10); - if (ret == 0) { - WRITE_PARSER_REG(PARSER_FETCH_CMD, 0); - parse_halt++; - pr_info - ("write timeout,retry,halt_count=%d parse_control=%x\n", - parse_halt, READ_PARSER_REG(PARSER_CONTROL)); - - //vreal_set_fatal_flag(1);//DEBUG_TMP - - if (parse_halt > 10) { - WRITE_PARSER_REG(PARSER_CONTROL, - (ES_SEARCH | ES_PARSER_START)); - pr_info("reset parse_control=%x\n", - READ_PARSER_REG(PARSER_CONTROL)); - } - return -EAGAIN; - } else if (ret < 0) - return -ERESTARTSYS; - - if (vwp == buf_wp(BUF_TYPE_VIDEO) - && awp == buf_wp(BUF_TYPE_AUDIO)) { - struct stream_buf_s *v_buf_t = - get_buf_by_type(BUF_TYPE_VIDEO); - struct stream_buf_s *a_buf_t = - get_buf_by_type(BUF_TYPE_AUDIO); - int v_st_lv = stbuf_level(v_buf_t); - int a_st_lv = stbuf_level(a_buf_t); - - if ((parse_halt + 1) % 10 == 1) { - pr_info("V&A WP not changed after write"); - pr_info(",video %x->%x", vwp, - buf_wp(BUF_TYPE_VIDEO)); - pr_info(",Audio:%x-->%x,parse_halt=%d\n", - awp, buf_wp(BUF_TYPE_AUDIO), - parse_halt); - } - parse_halt++; - -/* wp not changed , - * we think have bugs on parser now. - */ - if (parse_halt > 10 && - (v_st_lv < 1000 || a_st_lv < 100)) { - /*reset while at least one is underflow. */ - WRITE_PARSER_REG(PARSER_CONTROL, - (ES_SEARCH | ES_PARSER_START)); - pr_info("reset parse_control=%x\n", - READ_PARSER_REG(PARSER_CONTROL)); - } - if (parse_halt <= 10 || - halt_droped_len < 100 * 1024) { - /*drops first 10 pkt , - * some times maybe no av data - */ - pr_info("drop this pkt=%d,len=%d\n", parse_halt, - len); - p += len; - r -= len; - halt_droped_len += len; - } else - return -EAGAIN; - } else { - halt_droped_len = 0; - parse_halt = 0; - p += len; - r -= len; - } - } - return count - r; -} - -ssize_t rmparser_write(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count) -{ - s32 r; - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - size_t towrite = count; - - if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) { - if (file->f_flags & O_NONBLOCK) { - towrite = min(stbuf_space(vbuf), stbuf_space(abuf)); - if (towrite < 1024) /*? can write small? */ - return -EAGAIN; - } else { - if ((port->flag & PORT_FLAG_VID) - && (stbuf_space(vbuf) < count)) { - r = stbuf_wait_space(vbuf, count); - if (r < 0) - return r; - } - if ((port->flag & PORT_FLAG_AID) - && (stbuf_space(abuf) < count)) { - r = stbuf_wait_space(abuf, count); - if (r < 0) - return r; - } - } - } - towrite = min(towrite, count); - return _rmparser_write(buf, towrite); -} - -void rm_set_vasid(u32 vid, u32 aid) -{ - pr_info("rm_set_vasid aid %d, vid %d\n", aid, vid); - WRITE_PARSER_REG(VAS_STREAM_ID, (aid << 8) | vid); -} - -void rm_audio_reset(void) -{ - ulong flags; - DEFINE_SPINLOCK(lock); - - spin_lock_irqsave(&lock, flags); - - WRITE_PARSER_REG(PARSER_AUDIO_WP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_RP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - spin_unlock_irqrestore(&lock, flags); -} -EXPORT_SYMBOL(rm_audio_reset); diff --git a/drivers/amlogic/media_modules/stream_input/parser/rmparser.h b/drivers/amlogic/media_modules/stream_input/parser/rmparser.h deleted file mode 100644 index eb2023a972ba..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/rmparser.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * drivers/amlogic/amports/rmparser.h - * - * Copyright (C) 2015 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef RMPARSER_H -#define RMPARSER_H - -#include "../../frame_provider/decoder/utils/vdec.h" - -extern void rm_set_vasid(u32 vid, u32 aid); - -extern ssize_t rmparser_write(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count); - -s32 rmparser_init(struct vdec_s *vdec); - -extern void rmparser_release(void); - -extern void rm_audio_reset(void); - -extern void vreal_set_fatal_flag(int flag); - -#ifdef CONFIG_AM_DVB -extern int tsdemux_set_reset_flag(void); -#endif - -/* TODO: move to register headers */ -#define ES_PACK_SIZE_BIT 8 -#define ES_PACK_SIZE_WID 24 - -#define ES_CTRL_WID 8 -#define ES_CTRL_BIT 0 -#define ES_TYPE_MASK (3 << 6) -#define ES_TYPE_VIDEO (0 << 6) -#define ES_TYPE_AUDIO (1 << 6) -#define ES_TYPE_SUBTITLE (2 << 6) - -#define ES_WRITE (1<<5) -#define ES_PASSTHROUGH (1<<4) -#define ES_INSERT_BEFORE_ES_WRITE (1<<3) -#define ES_DISCARD (1<<2) -#define ES_SEARCH (1<<1) -#define ES_PARSER_START (1<<0) -#define ES_PARSER_BUSY (1<<0) - -#define PARSER_INTSTAT_FETCH_CMD (1<<7) -#define PARSER_INTSTAT_PARSE (1<<4) -#define PARSER_INTSTAT_DISCARD (1<<3) -#define PARSER_INTSTAT_INSZERO (1<<2) -#define PARSER_INTSTAT_ACT_NOSSC (1<<1) -#define PARSER_INTSTAT_SC_FOUND (1<<0) - -#define FETCH_CIR_BUF (1<<31) -#define FETCH_CHK_BUF_STOP (1<<30) -#define FETCH_PASSTHROUGH (1<<29) -#define FETCH_ENDIAN 27 -#define FETCH_PASSTHROUGH_TYPE_MASK (0x3<<27) -#define FETCH_ENDIAN_MASK (0x7<<27) -#define FETCH_BUF_SIZE_MASK (0x7ffffff) -#define FETCH_CMD_PTR_MASK 3 -#define FETCH_CMD_RD_PTR_BIT 5 -#define FETCH_CMD_WR_PTR_BIT 3 -#define FETCH_CMD_NUM_MASK 3 -#define FETCH_CMD_NUM_BIT 0 - -#define ES_COUNT_MASK 0xfff -#define ES_COUNT_BIT 20 -#define ES_REQ_PENDING (1<<19) -#define ES_PASSTHROUGH_EN (1<<18) -#define ES_PASSTHROUGH_TYPE_MASK (3<<16) -#define ES_PASSTHROUGH_TYPE_VIDEO (0<<16) -#define ES_PASSTHROUGH_TYPE_AUDIO (1<<16) -#define ES_PASSTHROUGH_TYPE_SUBTITLE (2<<16) -#define ES_WR_ENDIAN_MASK (0x7) -#define ES_SUB_WR_ENDIAN_BIT 9 -#define ES_SUB_MAN_RD_PTR (1<<8) -#define ES_AUD_WR_ENDIAN_BIT 5 -#define ES_AUD_MAN_RD_PTR (1<<4) -#define ES_VID_WR_ENDIAN_BIT 1 -#define ES_VID_MAN_RD_PTR (1<<0) - -#define PS_CFG_FETCH_DMA_URGENT (1<<31) -#define PS_CFG_STREAM_DMA_URGENT (1<<30) -#define PS_CFG_FORCE_PFIFO_REN (1<<29) -#define PS_CFG_PFIFO_PEAK_EN (1<<28) -#define PS_CFG_SRC_SEL_BIT 24 -#define PS_CFG_SRC_SEL_MASK (3< -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* #include */ - -#include -#include "../../frame_provider/decoder/utils/vdec.h" -#include "streambuf_reg.h" -#include "streambuf.h" -#include -#include "../amports/amports_priv.h" -#include -#include -#include - -#define STBUF_SIZE (64*1024) -#define STBUF_WAIT_INTERVAL (HZ/100) -#define MEM_NAME "streambuf" - -void *fetchbuf = 0; - -static s32 _stbuf_alloc(struct stream_buf_s *buf, bool is_secure) -{ - if (buf->buf_size == 0) - return -ENOBUFS; - - while (buf->buf_start == 0) { - int flags = CODEC_MM_FLAGS_DMA; - - buf->buf_page_num = PAGE_ALIGN(buf->buf_size) / PAGE_SIZE; - if (buf->type == BUF_TYPE_SUBTITLE) - flags = CODEC_MM_FLAGS_DMA_CPU; - - /* - *if 4k, - *used cma first,for less mem fragments. - */ - if (((buf->type == BUF_TYPE_HEVC) || - (buf->type == BUF_TYPE_VIDEO)) && - buf->for_4k) - flags |= CODEC_MM_FLAGS_CMA_FIRST; - if (buf->buf_size > 20 * 1024 * 1024) - flags |= CODEC_MM_FLAGS_CMA_FIRST; - - if ((buf->type == BUF_TYPE_HEVC) || - (buf->type == BUF_TYPE_VIDEO)) { - flags |= CODEC_MM_FLAGS_FOR_VDECODER; - } else if (buf->type == BUF_TYPE_AUDIO) { - flags |= CODEC_MM_FLAGS_FOR_ADECODER; - flags |= CODEC_MM_FLAGS_DMA_CPU; - } - - if (is_secure) - flags |= CODEC_MM_FLAGS_TVP; - - buf->buf_start = codec_mm_alloc_for_dma(MEM_NAME, - buf->buf_page_num, 4+PAGE_SHIFT, flags); - if (!buf->buf_start) { - int is_video = (buf->type == BUF_TYPE_HEVC) || - (buf->type == BUF_TYPE_VIDEO); - if (is_video && buf->buf_size >= 9 * SZ_1M) {/*min 6M*/ - int old_size = buf->buf_size; - - buf->buf_size = - PAGE_ALIGN(buf->buf_size * 2/3); - pr_info("%s stbuf alloced size = %d failed try small %d size\n", - (buf->type == BUF_TYPE_HEVC) ? "HEVC" : - (buf->type == BUF_TYPE_VIDEO) ? "Video" : - (buf->type == BUF_TYPE_AUDIO) ? "Audio" : - "Subtitle", old_size, buf->buf_size); - continue; - } - pr_info("%s stbuf alloced size = %d failed\n", - (buf->type == BUF_TYPE_HEVC) ? "HEVC" : - (buf->type == BUF_TYPE_VIDEO) ? "Video" : - (buf->type == BUF_TYPE_AUDIO) ? "Audio" : - "Subtitle", buf->buf_size); - return -ENOMEM; - } - - buf->is_secure = is_secure; - - pr_debug("%s stbuf alloced at %p, secure = %d, size = %d\n", - (buf->type == BUF_TYPE_HEVC) ? "HEVC" : - (buf->type == BUF_TYPE_VIDEO) ? "Video" : - (buf->type == BUF_TYPE_AUDIO) ? "Audio" : - "Subtitle", (void *)buf->buf_start, - buf->is_secure, - buf->buf_size); - } - if (buf->buf_size < buf->canusebuf_size) - buf->canusebuf_size = buf->buf_size; - buf->flag |= BUF_FLAG_ALLOC; - - return 0; -} - -int stbuf_change_size(struct stream_buf_s *buf, int size, bool is_secure) -{ - unsigned long old_buf; - int old_size, old_pagenum; - int ret; - - pr_info("buffersize=%d,%d,start=%p, secure=%d\n", size, buf->buf_size, - (void *)buf->buf_start, is_secure); - - if (buf->buf_size == size && buf->buf_start != 0) - return 0; - - old_buf = buf->buf_start; - old_size = buf->buf_size; - old_pagenum = buf->buf_page_num; - buf->buf_start = 0; - buf->buf_size = size; - ret = size; - - if (size == 0 || - _stbuf_alloc(buf, is_secure) == 0) { - /* - * size=0:We only free the old memory; - * alloc ok,changed to new buffer - */ - if (old_buf != 0) { - codec_mm_free_for_dma(MEM_NAME, old_buf); - } - - if (size == 0) - buf->is_secure = false; - - pr_info("changed the (%d) buffer size from %d to %d\n", - buf->type, old_size, size); - return 0; - } else { - /* alloc failed */ - buf->buf_start = old_buf; - buf->buf_size = old_size; - buf->buf_page_num = old_pagenum; - pr_info("changed the (%d) buffer size from %d to %d,failed\n", - buf->type, old_size, size); - } - - return ret; -} - -int stbuf_fetch_init(void) -{ - if (NULL != fetchbuf) - return 0; - - fetchbuf = (void *)__get_free_pages(GFP_KERNEL, - get_order(FETCHBUF_SIZE)); - - if (!fetchbuf) { - pr_info("%s: Can not allocate fetch working buffer\n", - __func__); - return -ENOMEM; - } - return 0; -} -EXPORT_SYMBOL(stbuf_fetch_init); - -void stbuf_fetch_release(void) -{ - if (0 && fetchbuf) { - /* always don't free.for safe alloc/free*/ - free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE)); - fetchbuf = 0; - } -} - -static void _stbuf_timer_func(unsigned long arg) -{ - struct stream_buf_s *p = (struct stream_buf_s *)arg; - - if (stbuf_space(p) < p->wcnt) { - p->timer.expires = jiffies + STBUF_WAIT_INTERVAL; - - add_timer(&p->timer); - } else - wake_up_interruptible(&p->wq); - -} - -u32 stbuf_level(struct stream_buf_s *buf) -{ - if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) { - if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) { - int level = READ_PARSER_REG(PARSER_VIDEO_WP) - - READ_PARSER_REG(PARSER_VIDEO_RP); - if (level < 0) - level += READ_PARSER_REG(PARSER_VIDEO_END_PTR) - - READ_PARSER_REG(PARSER_VIDEO_START_PTR) + 8; - return (u32)level; - } else - return (buf->type == BUF_TYPE_HEVC) ? - READ_VREG(HEVC_STREAM_LEVEL) : - _READ_ST_REG(LEVEL); - } - - return _READ_ST_REG(LEVEL); -} - -u32 stbuf_rp(struct stream_buf_s *buf) -{ - if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) { - if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) - return READ_PARSER_REG(PARSER_VIDEO_RP); - else - return (buf->type == BUF_TYPE_HEVC) ? - READ_VREG(HEVC_STREAM_RD_PTR) : - _READ_ST_REG(RP); - } - - return _READ_ST_REG(RP); -} - -u32 stbuf_space(struct stream_buf_s *buf) -{ - /* reserved space for safe write, - * the parser fifo size is 1024byts, so reserve it - */ - int size; - - size = buf->canusebuf_size - stbuf_level(buf); - - if (buf->canusebuf_size >= buf->buf_size / 2) { - /* old reversed value,tobe full, reversed only... */ - size = size - 6 * 1024; - } - - if ((buf->type == BUF_TYPE_VIDEO) - || (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC)) - size -= READ_PARSER_REG(PARSER_VIDEO_HOLE); - - return size > 0 ? size : 0; -} - -u32 stbuf_size(struct stream_buf_s *buf) -{ - return buf->buf_size; -} - -u32 stbuf_canusesize(struct stream_buf_s *buf) -{ - return buf->canusebuf_size; -} - -s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi) -{ - s32 r; - u32 dummy; - u32 addr32; - - if (!buf->buf_start) { - r = _stbuf_alloc(buf, (vdec) ? - vdec->port_flag & PORT_FLAG_DRM : 0); - if (r < 0) - return r; - } - addr32 = buf->buf_start & 0xffffffff; - init_waitqueue_head(&buf->wq); - - /* - * For multidec, do not touch HW stream buffers during port - * init and release. - */ - if ((buf->type == BUF_TYPE_VIDEO) || (buf->type == BUF_TYPE_HEVC)) { - if (vdec) { - if (vdec_stream_based(vdec)) - vdec_set_input_buffer(vdec, addr32, - buf->buf_size); - else - return vdec_set_input_buffer(vdec, addr32, - buf->buf_size); - } - } - - buf->write_thread = 0; - - if ((vdec && !vdec_single(vdec)) || (is_multi)) - return 0; - - if (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC) { - CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 1); - WRITE_VREG(HEVC_STREAM_START_ADDR, addr32); - WRITE_VREG(HEVC_STREAM_END_ADDR, addr32 + buf->buf_size); - WRITE_VREG(HEVC_STREAM_RD_PTR, addr32); - WRITE_VREG(HEVC_STREAM_WR_PTR, addr32); - - return 0; - } - - if (buf->type == BUF_TYPE_VIDEO) { - _WRITE_ST_REG(CONTROL, 0); - /* reset VLD before setting all pointers */ - WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, 0); - /*TODO: only > m6*/ -#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - WRITE_VREG(DOS_SW_RESET0, (1 << 4)); - WRITE_VREG(DOS_SW_RESET0, 0); -#else - WRITE_RESET_REG(RESET0_REGISTER, RESET_VLD); -#endif - - dummy = READ_RESET_REG(RESET0_REGISTER); - WRITE_VREG(POWER_CTL_VLD, 1 << 4); - } else if (buf->type == BUF_TYPE_AUDIO) { - _WRITE_ST_REG(CONTROL, 0); - - WRITE_AIU_REG(AIU_AIFIFO_GBIT, 0x80); - } - - if (buf->type == BUF_TYPE_SUBTITLE) { - WRITE_PARSER_REG(PARSER_SUB_RP, addr32); - WRITE_PARSER_REG(PARSER_SUB_START_PTR, addr32); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, - addr32 + buf->buf_size - 8); - - return 0; - } - - _WRITE_ST_REG(START_PTR, addr32); - _WRITE_ST_REG(CURR_PTR, addr32); - _WRITE_ST_REG(END_PTR, addr32 + buf->buf_size - 8); - - _SET_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT); - _CLR_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT); - - _WRITE_ST_REG(BUF_CTRL, MEM_BUFCTRL_MANUAL); - _WRITE_ST_REG(WP, addr32); - - _SET_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT); - _CLR_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT); - - _SET_ST_REG_MASK(CONTROL, - (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN | - MEM_CTRL_EMPTY_EN); - return 0; -} -EXPORT_SYMBOL(stbuf_init); - -void stbuf_vdec2_init(struct stream_buf_s *buf) -{ - - _WRITE_VDEC2_ST_REG(CONTROL, 0); - - _WRITE_VDEC2_ST_REG(START_PTR, _READ_ST_REG(START_PTR)); - _WRITE_VDEC2_ST_REG(END_PTR, _READ_ST_REG(END_PTR)); - _WRITE_VDEC2_ST_REG(CURR_PTR, _READ_ST_REG(CURR_PTR)); - - _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL | MEM_BUFCTRL_INIT); - _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL); - - _WRITE_VDEC2_ST_REG(BUF_CTRL, MEM_BUFCTRL_INIT); - _WRITE_VDEC2_ST_REG(BUF_CTRL, 0); - - _WRITE_VDEC2_ST_REG(CONTROL, - (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN - | MEM_CTRL_EMPTY_EN); -} - -s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count) -{ - struct stream_buf_s *p = stream_buf; - long time_out = 200; - - p->wcnt = count; - - setup_timer(&p->timer, _stbuf_timer_func, (ulong) p); - - mod_timer(&p->timer, jiffies + STBUF_WAIT_INTERVAL); - - if (wait_event_interruptible_timeout - (p->wq, stbuf_space(p) >= count, - msecs_to_jiffies(time_out)) == 0) { - del_timer_sync(&p->timer); - - return -EAGAIN; - } - - del_timer_sync(&p->timer); - - return 0; -} - -void stbuf_release(struct stream_buf_s *buf, bool is_multi) -{ - int r; - - buf->first_tstamp = INVALID_PTS; - - r = stbuf_init(buf, NULL, is_multi);/* reinit buffer */ - if (r < 0) - pr_err("stbuf_release %d, stbuf_init failed\n", __LINE__); - - if (buf->flag & BUF_FLAG_ALLOC && buf->buf_start) { - codec_mm_free_for_dma(MEM_NAME, buf->buf_start); - buf->flag &= ~BUF_FLAG_ALLOC; - buf->buf_start = 0; - buf->is_secure = false; - } - buf->flag &= ~BUF_FLAG_IN_USE; -} -EXPORT_SYMBOL(stbuf_release); - -u32 stbuf_sub_rp_get(void) -{ - return READ_PARSER_REG(PARSER_SUB_RP); -} - -void stbuf_sub_rp_set(unsigned int sub_rp) -{ - WRITE_PARSER_REG(PARSER_SUB_RP, sub_rp); - return; -} - -u32 stbuf_sub_wp_get(void) -{ - return READ_PARSER_REG(PARSER_SUB_WP); -} - -u32 stbuf_sub_start_get(void) -{ - return READ_PARSER_REG(PARSER_SUB_START_PTR); -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h deleted file mode 100644 index d73865e010f7..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/streambuf.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef STREAMBUF_H -#define STREAMBUF_H -#include - -#define BUF_FLAG_ALLOC 0x01 -#define BUF_FLAG_IN_USE 0x02 -#define BUF_FLAG_PARSER 0x04 -#define BUF_FLAG_FIRST_TSTAMP 0x08 -#define BUF_FLAG_IOMEM 0x10 - -#define BUF_TYPE_VIDEO 0 -#define BUF_TYPE_AUDIO 1 -#define BUF_TYPE_SUBTITLE 2 -#define BUF_TYPE_USERDATA 3 -#define BUF_TYPE_HEVC 4 -#define BUF_MAX_NUM 5 - -#define INVALID_PTS 0xffffffff - -#define FETCHBUF_SIZE (64*1024) -#define USER_DATA_SIZE (8*1024) - -struct vdec_s; - -struct stream_buf_s { - s32 flag; - u32 type; - unsigned long buf_start; - struct page *buf_pages; - int buf_page_num; - u32 buf_size; - u32 default_buf_size; - u32 canusebuf_size; - u32 first_tstamp; - const ulong reg_base; - wait_queue_head_t wq; - struct timer_list timer; - u32 wcnt; - u32 buf_wp; - u32 buf_rp; - u32 max_buffer_delay_ms; - u64 last_write_jiffies64; - void *write_thread; - int for_4k; - bool is_secure; -} /*stream_buf_t */; - -struct stream_port_s { - /* driver info */ - const char *name; - struct device *class_dev; - const struct file_operations *fops; - - /* ports control */ - s32 type; - s32 flag; - s32 pcr_inited; - - /* decoder info */ - s32 vformat; - s32 aformat; - s32 achanl; - s32 asamprate; - s32 adatawidth; - - /* parser info */ - u32 vid; - u32 aid; - u32 sid; - u32 pcrid; -} /*stream_port_t */; -enum drm_level_e { - DRM_LEVEL1 = 1, - DRM_LEVEL2 = 2, - DRM_LEVEL3 = 3, - DRM_NONE = 4, -}; - -struct drm_info { - enum drm_level_e drm_level; - u32 drm_flag; - u32 drm_hasesdata; - u32 drm_priv; - u32 drm_pktsize; - u32 drm_pktpts; - u32 drm_phy; - u32 drm_vir; - u32 drm_remap; - u32 data_offset; - u32 handle; - u32 extpad[7]; -} /*drminfo_t */; - -#define TYPE_DRMINFO_V2 0x100 -#define TYPE_DRMINFO 0x80 -#define TYPE_PATTERN 0x40 - -struct vdec_s; - -extern void *fetchbuf; - -extern u32 stbuf_level(struct stream_buf_s *buf); -extern u32 stbuf_rp(struct stream_buf_s *buf); -extern u32 stbuf_space(struct stream_buf_s *buf); -extern u32 stbuf_size(struct stream_buf_s *buf); -extern u32 stbuf_canusesize(struct stream_buf_s *buf); -extern s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, - bool is_multi); -extern s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count); -extern void stbuf_release(struct stream_buf_s *buf, bool is_multi); -extern int stbuf_change_size(struct stream_buf_s *buf, int size, - bool is_secure); -extern int stbuf_fetch_init(void); -extern void stbuf_fetch_release(void); -extern u32 stbuf_sub_rp_get(void); -extern void stbuf_sub_rp_set(unsigned int sub_rp); -extern u32 stbuf_sub_wp_get(void); -extern u32 stbuf_sub_start_get(void); -extern u32 stbuf_userdata_start_get(void); -extern struct stream_buf_s *get_stream_buffer(int id); - -extern void stbuf_vdec2_init(struct stream_buf_s *buf); - -#endif /* STREAMBUF_H */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h b/drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h deleted file mode 100644 index 5f0c8ca81dc3..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/streambuf_reg.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef STREAMBUF_REG_H -#define STREAMBUF_REG_H - -#define HEVC_STREAM_REG_BASE HEVC_STREAM_START_ADDR - -#define VLD_MEM_VIFIFO_REG_BASE VLD_MEM_VIFIFO_START_PTR -#define AIU_MEM_AIFIFO_REG_BASE AIU_MEM_AIFIFO_START_PTR - -#define START_PTR 0 -#define CURR_PTR 1 -#define END_PTR 2 -#define BYTES_AVAIL 3 -#define CONTROL 4 -#define WP 5 -#define RP 6 -#define LEVEL 7 -#define BUF_CTRL 8 - -/* - *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 - *#define _WRITE_ST_REG(r, val) \ - * __raw_writel(val, (volatile void __iomem *)(buf->reg_base+(r<<2))) - *#define _WRITE_ST_REG_BITS(r, val, s, e) \ - * __raw_writel((((_READ_ST_REG(r) & \ - * (((1L<<(e)-1)<<(s))-1)<<(s)))|((unsigned)((val)&((1L<<(e))-1))<<(s))), \ - * (volatile void __iomem *)(buf->reg_base+(r<<2))) - *#define _SET_ST_REG_MASK(r, val) \ - * __raw_writel(_READ_ST_REG(r)| (val), \ - * (volatile void __iomem *)(buf->reg_base+(r<<2))) - *#define _CLR_ST_REG_MASK(r, val) \ - * __raw_writel(_READ_ST_REG(r)&~(val), \ - * (volatile void __iomem *)(buf->reg_base+(r<<2))) - *#define _READ_ST_REG(r) \ - * (__raw_readl((volatile void __iomem *)(buf->reg_base+(r<<2)))) - * - *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD - *#define _READ_VDEC2_ST_REG(r) \ - * (__raw_readl((volatile void __iomem *)(buf->reg_base + \ - * DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \ - * DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2)))) - *#define _WRITE_VDEC2_ST_REG(r, val) \ - * __raw_writel(val, (volatile void __iomem *)(buf->reg_base + \ - * DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \ - * DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2))) - *#endif - * - *#define MEM_BUFCTRL_MANUAL (1<<1) - *#define MEM_BUFCTRL_INIT (1<<0) - *#define MEM_LEVEL_CNT_BIT 18 - *#define MEM_FIFO_CNT_BIT 16 - *#define MEM_FILL_ON_LEVEL (1<<10) - *#define MEM_CTRL_EMPTY_EN (1<<2) - *#define MEM_CTRL_FILL_EN (1<<1) - *#define MEM_CTRL_INIT (1<<0) - * - *#else - *#define _WRITE_ST_REG(r, val) \ - *WRITE_MPEG_REG(buf->reg_base + (r), \ - * (val)) - *#define _WRITE_ST_REG_BITS(r, val, s, e)\ - * WRITE_MPEG_REG(buf->reg_base + (r), \ - * (val), (s), (e)) - *#define _SET_ST_REG_MASK(r, val) SET_MPEG_REG_MASK(buf->reg_base + \ - * (r), (val)) - *#define _CLR_ST_REG_MASK(r, val) CLEAR_MPEG_REG_MASK(buf->reg_base + \ - * (r), (val)) - *#define _READ_ST_REG(r) READ_MPEG_REG(buf->reg_base + (r)) - *#endif - */ - - /*TODO*/ -#define _WRITE_ST_REG(r, val) do { \ - if (buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) \ - codec_dosbus_write((buf->reg_base+(r)), (val)); \ - else \ - codec_aiubus_write((buf->reg_base+(r)), (val)); \ - } while (0) -#define _READ_ST_REG(r) \ - ((buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) ? \ - codec_dosbus_read(buf->reg_base+(r)) : \ - codec_aiubus_read(buf->reg_base+(r))) - -#define _SET_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r) | (val)) -#define _CLR_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r)&~(val)) -#define _READ_VDEC2_ST_REG(r) (codec_dosbus_read(\ - (VDEC2_VLD_MEM_VIFIFO_START_PTR+(r)))) -#define _WRITE_VDEC2_ST_REG(r, val) codec_dosbus_write(\ - (VDEC2_VLD_MEM_VIFIFO_START_PTR+r), val) -#define MEM_BUFCTRL_MANUAL (1<<1) -#define MEM_BUFCTRL_INIT (1<<0) -#define MEM_LEVEL_CNT_BIT 18 -#define MEM_FIFO_CNT_BIT 16 -#define MEM_FILL_ON_LEVEL (1<<10) -#define MEM_CTRL_EMPTY_EN (1<<2) -#define MEM_CTRL_FILL_EN (1<<1) -#define MEM_CTRL_INIT (1<<0) -#endif /* STREAMBUF_REG_H */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c deleted file mode 100644 index 6fe6cd871dc0..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/thread_rw.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* #include */ -#include - -#include "../../stream_input/parser/streambuf.h" -#include "../../stream_input/amports/amports_priv.h" -#include "thread_rw.h" - -#define BUF_NAME "fetchbuf" - -#define DEFAULT_BLOCK_SIZE (64*1024) - -struct threadrw_buf { - void *vbuffer; - dma_addr_t dma_handle; - int write_off; - int data_size; - int buffer_size; - int from_cma; -}; - -#define MAX_MM_BUFFER_NUM 16 -struct threadrw_write_task { - struct file *file; - struct delayed_work write_work; - DECLARE_KFIFO_PTR(datafifo, void *); - DECLARE_KFIFO_PTR(freefifo, void *); - int bufs_num; - int max_bufs; - int errors; - spinlock_t lock; - struct mutex mutex; - struct stream_buf_s *sbuf; - int buffered_data_size; - int passed_data_len; - int buffer_size; - int def_block_size; - int data_offset; - int writework_on; - unsigned long codec_mm_buffer[MAX_MM_BUFFER_NUM]; - int manual_write; - int failed_onmore; - wait_queue_head_t wq; - ssize_t (*write)(struct file *, - struct stream_buf_s *, - const char __user *, - size_t, int); - struct threadrw_buf buf[1]; - /*don't add any after buf[] define */ -}; - -static int free_task_buffers(struct threadrw_write_task *task); - -static struct workqueue_struct *threadrw_wq_get(void) -{ - static struct workqueue_struct *threadrw_wq; - - if (!threadrw_wq) - threadrw_wq = create_singlethread_workqueue("threadrw"); - return threadrw_wq; -} - -static int threadrw_schedule_delayed_work( - struct threadrw_write_task *task, - unsigned long delay) -{ - bool ret; - - if (threadrw_wq_get()) { - ret = queue_delayed_work(threadrw_wq_get(), - &task->write_work, delay); - } else - ret = schedule_delayed_work(&task->write_work, delay); - if (!ret) { - cancel_delayed_work(&task->write_work); - if (threadrw_wq_get()) - ret = queue_delayed_work(threadrw_wq_get(), - &task->write_work, 0); - else - ret = schedule_delayed_work(&task->write_work, 0); - } - return 0; -} - -static ssize_t threadrw_write_onece( - struct threadrw_write_task *task, - struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count) -{ - struct threadrw_buf *rwbuf = NULL; - int ret = 0; - int to_write; - - if (!kfifo_get(&task->freefifo, (void *)&rwbuf)) { - if (task->errors) - return task->errors; - return -EAGAIN; - } - - to_write = min_t(u32, rwbuf->buffer_size, count); - if (copy_from_user(rwbuf->vbuffer, buf, to_write)) { - kfifo_put(&task->freefifo, (const void *)buf); - ret = -EFAULT; - goto err; - } - rwbuf->data_size = to_write; - rwbuf->write_off = 0; - kfifo_put(&task->datafifo, (const void *)rwbuf); - threadrw_schedule_delayed_work(task, 0); - return to_write; -err: - return ret; -} - -static ssize_t threadrw_write_in( - struct threadrw_write_task *task, - struct stream_buf_s *stbuf, - const char __user *buf, size_t count) -{ - int ret = 0; - int off = 0; - int left = count; - int wait_num = 0; - unsigned long flags; - - while (left > 0) { - ret = threadrw_write_onece(task, - task->file, - stbuf, buf + off, left); - if (ret >= left) { - off = count; - left = 0; - } else if (ret > 0) { - off += ret; - left -= ret; - - } else if (ret < 0) { - if (off > 0) { - break; /*have write ok some data. */ - } else if (ret == -EAGAIN) { - if (!(task->file->f_flags & O_NONBLOCK) && - (++wait_num < 10)) { - wait_event_interruptible_timeout( - task->wq, - !kfifo_is_empty( - &task->freefifo), - HZ / 100); - continue; /* write again. */ - } - ret = -EAGAIN; - break; - } - break; /*to end */ - } - } - - /*end: */ - spin_lock_irqsave(&task->lock, flags); - if (off > 0) { - task->buffered_data_size += off; - task->data_offset += off; - } - spin_unlock_irqrestore(&task->lock, flags); - if (off > 0) - return off; - else - return ret; -} - -static int do_write_work_in(struct threadrw_write_task *task) -{ - struct threadrw_buf *rwbuf = NULL; - int ret; - int need_re_write = 0; - int write_len = 0; - unsigned long flags; - - if (kfifo_is_empty(&task->datafifo)) - return 0; - if (!kfifo_peek(&task->datafifo, (void *)&rwbuf)) - return 0; - if (!task->manual_write && - rwbuf->from_cma && - !rwbuf->write_off) - codec_mm_dma_flush(rwbuf->vbuffer, - rwbuf->buffer_size, - DMA_TO_DEVICE); - if (task->manual_write) { - ret = task->write(task->file, task->sbuf, - (const char __user *)rwbuf->vbuffer + rwbuf->write_off, - rwbuf->data_size, - 2); /* noblock,virtual addr */ - } else { - ret = task->write(task->file, task->sbuf, - (const char __user *)rwbuf->dma_handle + rwbuf->write_off, - rwbuf->data_size, - 3); /* noblock,phy addr */ - } - if (ret == -EAGAIN) { - need_re_write = 0; - /*do later retry. */ - } else if (ret >= rwbuf->data_size) { - write_len += rwbuf->data_size; - if (kfifo_get(&task->datafifo, (void *)&rwbuf)) { - rwbuf->data_size = 0; - kfifo_put(&task->freefifo, (const void *)rwbuf); - /*wakeup write thread. */ - wake_up_interruptible(&task->wq); - } else - pr_err("write ok,but kfifo_get data failed.!!!\n"); - need_re_write = 1; - } else if (ret > 0) { - rwbuf->data_size -= ret; /* half data write */ - rwbuf->write_off += ret; - write_len += ret; - need_re_write = 1; - } else { /*ret <=0 */ - pr_err("get errors ret=%d size=%d\n", ret, - rwbuf->data_size); - task->errors = ret; - } - if (write_len > 0) { - spin_lock_irqsave(&task->lock, flags); - task->passed_data_len += write_len; - spin_unlock_irqrestore(&task->lock, flags); - } - return need_re_write; - -} - -static void do_write_work(struct work_struct *work) -{ - struct threadrw_write_task *task = container_of(work, - struct threadrw_write_task, - write_work.work); - int need_retry = 1; - - task->writework_on = 1; - while (need_retry) { - mutex_lock(&task->mutex); - need_retry = do_write_work_in(task); - mutex_unlock(&task->mutex); - } - threadrw_schedule_delayed_work(task, HZ / 10); - task->writework_on = 0; -} - -static int alloc_task_buffers_inlock(struct threadrw_write_task *task, - int new_bubffers, - int block_size) -{ - struct threadrw_buf *rwbuf; - int i; - int used_codec_mm = task->manual_write ? 0 : 1; - int new_num = new_bubffers; - int mm_slot = -1; - int start_idx = task->bufs_num; - int total_mm = 0; - unsigned long addr; - - if (codec_mm_get_total_size() < 80 || - codec_mm_get_free_size() < 40) - used_codec_mm = 0; - if (task->bufs_num + new_num > task->max_bufs) - new_num = task->max_bufs - task->bufs_num; - for (i = 0; i < MAX_MM_BUFFER_NUM; i++) { - if (task->codec_mm_buffer[i] == 0) { - mm_slot = i; - break; - } - } - if (mm_slot < 0) - used_codec_mm = 0; - if (block_size <= 0) - block_size = DEFAULT_BLOCK_SIZE; - - if (used_codec_mm && (block_size * new_num) >= 128 * 1024) { - total_mm = ALIGN(block_size * new_num, (1 << 17)); - addr = - codec_mm_alloc_for_dma(BUF_NAME, - total_mm / PAGE_SIZE, 0, - CODEC_MM_FLAGS_DMA_CPU); - if (addr != 0) { - task->codec_mm_buffer[mm_slot] = addr; - task->buffer_size += total_mm; - } else { - used_codec_mm = 0; - } - } - for (i = 0; i < new_num; i++) { - int bufidx = start_idx + i; - - rwbuf = &task->buf[bufidx]; - rwbuf->buffer_size = block_size; - if (used_codec_mm) { - unsigned long start_addr = - task->codec_mm_buffer[mm_slot]; - if (i == new_num - 1) - rwbuf->buffer_size = total_mm - - block_size * i; - rwbuf->dma_handle = (dma_addr_t) start_addr + - block_size * i; - rwbuf->vbuffer = codec_mm_phys_to_virt( - rwbuf->dma_handle); - rwbuf->from_cma = 1; - - } else { - rwbuf->vbuffer = dma_alloc_coherent( - amports_get_dma_device(), - rwbuf->buffer_size, - &rwbuf->dma_handle, GFP_KERNEL); - if (!rwbuf->vbuffer) { - rwbuf->buffer_size = 0; - rwbuf->dma_handle = 0; - task->bufs_num = bufidx; - break; - } - rwbuf->from_cma = 0; - task->buffer_size += rwbuf->buffer_size; - } - - kfifo_put(&task->freefifo, (const void *)rwbuf); - task->bufs_num = bufidx + 1; - } - if (start_idx > 0 ||/*have buffers before*/ - task->bufs_num >= 3 || - task->bufs_num == new_num) { - if (!task->def_block_size) - task->def_block_size = task->buf[0].buffer_size; - return 0; /*must >=3 for swap buffers. */ - } - if (task->bufs_num > 0) - free_task_buffers(task); - return -1; -} - -static int free_task_buffers(struct threadrw_write_task *task) -{ - int i; - - for (i = 0; i < MAX_MM_BUFFER_NUM; i++) { - if (task->codec_mm_buffer[i]) - codec_mm_free_for_dma(BUF_NAME, - task->codec_mm_buffer[i]); - } - for (i = 0; i < task->bufs_num; i++) { - if (task->buf[i].vbuffer && task->buf[i].from_cma == 0) - dma_free_coherent(amports_get_dma_device(), - task->buf[i].buffer_size, - task->buf[i].vbuffer, - task->buf[i].dma_handle); - } - return 0; -} - -static struct threadrw_write_task *threadrw_alloc_in(int num, - int block_size, - ssize_t (*write)(struct file *, - struct stream_buf_s *, - const char __user *, size_t, int), - int flags) -{ - int max_bufs = num; - int task_buffer_size; - struct threadrw_write_task *task; - int ret; - - if (!(flags & 1)) /*not audio*/ - max_bufs = 300; /*can great for video bufs.*/ - task_buffer_size = sizeof(struct threadrw_write_task) + - sizeof(struct threadrw_buf) * max_bufs; - task = vmalloc(task_buffer_size); - - if (!task) - return NULL; - memset(task, 0, task_buffer_size); - - spin_lock_init(&task->lock); - mutex_init(&task->mutex); - INIT_DELAYED_WORK(&task->write_work, do_write_work); - init_waitqueue_head(&task->wq); - ret = kfifo_alloc(&task->datafifo, max_bufs, GFP_KERNEL); - if (ret) - goto err1; - ret = kfifo_alloc(&task->freefifo, max_bufs, GFP_KERNEL); - if (ret) - goto err2; - task->write = write; - task->file = NULL; - task->buffer_size = 0; - task->manual_write = flags & 1; - task->max_bufs = max_bufs; - mutex_lock(&task->mutex); - ret = alloc_task_buffers_inlock(task, num, block_size); - mutex_unlock(&task->mutex); - if (ret < 0) - goto err3; - threadrw_wq_get(); /*start thread. */ - return task; - -err3: - kfifo_free(&task->freefifo); -err2: - kfifo_free(&task->datafifo); -err1: - vfree(task); - pr_err("alloc threadrw failed num:%d,block:%d\n", num, block_size); - return NULL; -} - -/* - *fifo data size; - */ - -void threadrw_update_buffer_level(struct stream_buf_s *stbuf, - int parsed_size) -{ - struct threadrw_write_task *task = stbuf->write_thread; - unsigned long flags; - - if (task) - { - spin_lock_irqsave(&task->lock, flags); - task->buffered_data_size -= parsed_size; - spin_unlock_irqrestore(&task->lock, flags); - } - -} -EXPORT_SYMBOL(threadrw_update_buffer_level); - -int threadrw_buffer_level(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (task) - return task->buffered_data_size; - return 0; -} - -int threadrw_buffer_size(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (task) - return task->buffer_size; - return 0; -} - -int threadrw_datafifo_len(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (task) - return kfifo_len(&task->datafifo); - return 0; -} - -int threadrw_freefifo_len(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (task) - return kfifo_len(&task->freefifo); - return 0; -} -int threadrw_support_more_buffers(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (!task) - return 0; - if (task->failed_onmore) - return 0; - return task->max_bufs - task->bufs_num; -} - -/* - *data len out fifo; - */ -int threadrw_passed_len(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (task) - return task->passed_data_len; - return 0; - -} -/* - *all data writed.; - */ -int threadrw_dataoffset(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - int offset = 0; - - if (task) - return task->data_offset; - return offset; - -} - -ssize_t threadrw_write(struct file *file, struct stream_buf_s *stbuf, - const char __user *buf, size_t count) -{ - struct threadrw_write_task *task = stbuf->write_thread; - ssize_t size; - - if (!task->file) { - task->file = file; - task->sbuf = stbuf; - } - mutex_lock(&task->mutex); - size = threadrw_write_in(task, stbuf, buf, count); - mutex_unlock(&task->mutex); - return size; -} - -int threadrw_flush_buffers(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - int max_retry = 20; - - if (!task) - return 0; - while (!kfifo_is_empty(&task->datafifo) && max_retry-- > 0) { - threadrw_schedule_delayed_work(task, 0); - msleep(20); - } - if (!kfifo_is_empty(&task->datafifo)) - return -1;/*data not flushed*/ - return 0; -} -int threadrw_alloc_more_buffer_size( - struct stream_buf_s *stbuf, - int size) -{ - struct threadrw_write_task *task = stbuf->write_thread; - int block_size; - int new_num; - int ret = -1; - int old_num; - - if (!task) - return -1; - mutex_lock(&task->mutex); - block_size = task->def_block_size; - if (block_size == 0) - block_size = 32 * 1024; - new_num = size / block_size; - old_num = task->bufs_num; - if (new_num == 0) - new_num = 1; - else if (new_num > task->max_bufs - task->bufs_num) - new_num = task->max_bufs - task->bufs_num; - if (new_num != 0) - ret = alloc_task_buffers_inlock(task, new_num, - block_size); - mutex_unlock(&task->mutex); - pr_info("threadrw add more buffer from %d -> %d for size %d\n", - old_num, task->bufs_num, - size); - if (ret < 0 || old_num == task->bufs_num) - task->failed_onmore = 1; - return ret; -} - -void *threadrw_alloc(int num, - int block_size, - ssize_t (*write)(struct file *, - struct stream_buf_s *, - const char __user *, - size_t, int), - int flags) -{ - return threadrw_alloc_in(num, block_size, write, flags); -} - -void threadrw_release(struct stream_buf_s *stbuf) -{ - struct threadrw_write_task *task = stbuf->write_thread; - - if (task) { - wake_up_interruptible(&task->wq); - cancel_delayed_work_sync(&task->write_work); - mutex_lock(&task->mutex); - free_task_buffers(task); - mutex_unlock(&task->mutex); - kfifo_free(&task->freefifo); - kfifo_free(&task->datafifo); - vfree(task); - } - stbuf->write_thread = NULL; -} diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h deleted file mode 100644 index a91b00498efc..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/thread_rw.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef THREAD_RW_H -#define THREAD_RW_H -#include "../../stream_input/parser/streambuf_reg.h" -#include "../../stream_input/parser/streambuf.h" -#include "../../stream_input/parser/esparser.h" -#include "../../stream_input/amports/amports_priv.h" - -ssize_t threadrw_write(struct file *file, - struct stream_buf_s *stbuf, - const char __user *buf, - size_t count); - -void *threadrw_alloc(int num, - int block_size, - ssize_t (*write)(struct file *, - struct stream_buf_s *, - const char __user *, - size_t, int), - int flags);/*flags &1: manual mode*/ - -void threadrw_release(struct stream_buf_s *stbuf); - -int threadrw_buffer_level(struct stream_buf_s *stbuf); -int threadrw_buffer_size(struct stream_buf_s *stbuf); -int threadrw_datafifo_len(struct stream_buf_s *stbuf); -int threadrw_freefifo_len(struct stream_buf_s *stbuf); -int threadrw_passed_len(struct stream_buf_s *stbuf); -int threadrw_flush_buffers(struct stream_buf_s *stbuf); -int threadrw_dataoffset(struct stream_buf_s *stbuf); -int threadrw_alloc_more_buffer_size( - struct stream_buf_s *stbuf, - int size); -int threadrw_support_more_buffers(struct stream_buf_s *stbuf); -void threadrw_update_buffer_level(struct stream_buf_s *stbuf, - int parsed_size); -#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c deleted file mode 100644 index ac34cf74c3d3..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c +++ /dev/null @@ -1,1196 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/tsdemux.c - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -/* #include */ -#include -/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -/* #include */ -/* #endif */ - -#include "../../frame_provider/decoder/utils/vdec.h" -#include -#include "streambuf_reg.h" -#include "streambuf.h" -#include - -#include "tsdemux.h" -#include -#include "../amports/amports_priv.h" - -#define MAX_DRM_PACKAGE_SIZE 0x500000 - - -static const char tsdemux_fetch_id[] = "tsdemux-fetch-id"; -static const char tsdemux_irq_id[] = "tsdemux-irq-id"; - -static u32 curr_pcr_num = 0xffff; -static u32 curr_vid_id = 0xffff; -static u32 curr_aud_id = 0xffff; -static u32 curr_sub_id = 0xffff; -static u32 curr_pcr_id = 0xffff; - -static DECLARE_WAIT_QUEUE_HEAD(wq); -static u32 fetch_done; -static u32 discontinued_counter; -static u32 first_pcr; -static u8 pcrscr_valid; -static u8 pcraudio_valid; -static u8 pcrvideo_valid; -static u8 pcr_init_flag; - -static int demux_skipbyte; - -static struct tsdemux_ops *demux_ops; -static DEFINE_SPINLOCK(demux_ops_lock); - -static int enable_demux_driver(void) -{ - return demux_ops ? 1 : 0; -} - -void tsdemux_set_ops(struct tsdemux_ops *ops) -{ - unsigned long flags; - - spin_lock_irqsave(&demux_ops_lock, flags); - demux_ops = ops; - spin_unlock_irqrestore(&demux_ops_lock, flags); -} -EXPORT_SYMBOL(tsdemux_set_ops); - -int tsdemux_set_reset_flag_ext(void) -{ - int r = 0; - - if (demux_ops && demux_ops->set_reset_flag) - r = demux_ops->set_reset_flag(); - - return r; -} - -int tsdemux_set_reset_flag(void) -{ - unsigned long flags; - int r; - - spin_lock_irqsave(&demux_ops_lock, flags); - r = tsdemux_set_reset_flag_ext(); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_reset(void) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->reset) { - tsdemux_set_reset_flag_ext(); - r = demux_ops->reset(); - } - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_request_irq(irq_handler_t handler, void *data) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->request_irq) - r = demux_ops->request_irq(handler, data); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_free_irq(void) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->free_irq) - r = demux_ops->free_irq(); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_set_vid(int vpid) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->set_vid) - r = demux_ops->set_vid(vpid); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_set_aid(int apid) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->set_aid) - r = demux_ops->set_aid(apid); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_set_sid(int spid) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->set_sid) - r = demux_ops->set_sid(spid); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_set_pcrid(int pcrpid) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->set_pcrid) - r = demux_ops->set_pcrid(pcrpid); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_set_skip_byte(int skipbyte) -{ - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->set_skipbyte) - r = demux_ops->set_skipbyte(skipbyte); - spin_unlock_irqrestore(&demux_ops_lock, flags); - - return r; -} - -static int tsdemux_config(void) -{ - return 0; -} - -static void tsdemux_pcr_set(unsigned int pcr); -/*TODO irq*/ -static irqreturn_t tsdemux_isr(int irq, void *dev_id) -{ - u32 int_status = 0; - int id = (long)dev_id; - - if (!enable_demux_driver()) { - int_status = READ_DEMUX_REG(STB_INT_STATUS); - } else { - if (id == 0) - int_status = READ_DEMUX_REG(STB_INT_STATUS); - else if (id == 1) - int_status = READ_DEMUX_REG(STB_INT_STATUS_2); - else if (id == 2) - int_status = READ_DEMUX_REG(STB_INT_STATUS_3); - } - - if (int_status & (1 << NEW_PDTS_READY)) { - if (!enable_demux_driver()) { - u32 pdts_status = READ_DEMUX_REG(STB_PTS_DTS_STATUS); - - if (pdts_status & (1 << VIDEO_PTS_READY)) - pts_checkin_wrptr(PTS_TYPE_VIDEO, - READ_DEMUX_REG(VIDEO_PDTS_WR_PTR), - READ_DEMUX_REG(VIDEO_PTS_DEMUX)); - - if (pdts_status & (1 << AUDIO_PTS_READY)) - pts_checkin_wrptr(PTS_TYPE_AUDIO, - READ_DEMUX_REG(AUDIO_PDTS_WR_PTR), - READ_DEMUX_REG(AUDIO_PTS_DEMUX)); - - WRITE_DEMUX_REG(STB_PTS_DTS_STATUS, pdts_status); - } else { -#define DMX_READ_REG(i, r)\ - ((i) ? ((i == 1) ? READ_DEMUX_REG(r##_2) : \ - READ_DEMUX_REG(r##_3)) : READ_DEMUX_REG(r)) - - u32 pdts_status = DMX_READ_REG(id, STB_PTS_DTS_STATUS); - - if (pdts_status & (1 << VIDEO_PTS_READY)) - pts_checkin_wrptr(PTS_TYPE_VIDEO, - DMX_READ_REG(id, VIDEO_PDTS_WR_PTR), - DMX_READ_REG(id, VIDEO_PTS_DEMUX)); - - if (pdts_status & (1 << AUDIO_PTS_READY)) - pts_checkin_wrptr(PTS_TYPE_AUDIO, - DMX_READ_REG(id, AUDIO_PDTS_WR_PTR), - DMX_READ_REG(id, AUDIO_PTS_DEMUX)); - - if (id == 1) - WRITE_DEMUX_REG(STB_PTS_DTS_STATUS_2, - pdts_status); - else if (id == 2) - WRITE_DEMUX_REG(STB_PTS_DTS_STATUS_3, - pdts_status); - else - WRITE_DEMUX_REG(STB_PTS_DTS_STATUS, - pdts_status); - } - } - if (int_status & (1 << DIS_CONTINUITY_PACKET)) { - discontinued_counter++; - /* pr_info("discontinued counter=%d\n",discontinued_counter); */ - } - if (int_status & (1 << SUB_PES_READY)) { - /* TODO: put data to somewhere */ - /* pr_info("subtitle pes ready\n"); */ - wakeup_sub_poll(); - } - if (int_status & (1< 0) { - if (isphybuf) - len = count; - else { - len = min_t(size_t, r, FETCHBUF_SIZE); - if (copy_from_user(fetchbuf, p, len)) - return -EFAULT; - - dma_addr = - dma_map_single(amports_get_dma_device(), - fetchbuf, - FETCHBUF_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - dma_addr)) - return -EFAULT; - - - } - - fetch_done = 0; - - wmb(); /* Ensure fetchbuf contents visible */ - - if (isphybuf) { - u32 buf_32 = (unsigned long)buf & 0xffffffff; - WRITE_PARSER_REG(PARSER_FETCH_ADDR, buf_32); - } else { - WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr); - dma_unmap_single(amports_get_dma_device(), dma_addr, - FETCHBUF_SIZE, DMA_TO_DEVICE); - } - - WRITE_PARSER_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len); - - - ret = - wait_event_interruptible_timeout(wq, fetch_done != 0, - HZ / 2); - if (ret == 0) { - WRITE_PARSER_REG(PARSER_FETCH_CMD, 0); - pr_info("write timeout, retry\n"); - return -EAGAIN; - } else if (ret < 0) - return -ERESTARTSYS; - - p += len; - r -= len; - } - - return count - r; -} - -#define PCR_EN 12 - -static int reset_pcr_regs(void) -{ - u32 pcr_num; - u32 pcr_regs = 0; - if (curr_pcr_id >= 0x1FFF) - return 0; - /* set paramater to fetch pcr */ - pcr_num = 0; - if (curr_pcr_id == curr_vid_id) - pcr_num = 0; - else if (curr_pcr_id == curr_aud_id) - pcr_num = 1; - else if (curr_pcr_id == curr_sub_id) - pcr_num = 2; - else - pcr_num = 3; - if (pcr_num != curr_pcr_num) { - u32 clk_unit = 0; - u32 clk_81 = 0; - struct clk *clk; - //clk = clk_get(NULL,"clk81"); - clk= devm_clk_get(amports_get_dma_device(),"clk_81"); - if (IS_ERR(clk) || clk == 0) { - pr_info("[%s:%d] error clock\n", __func__, __LINE__); - return 0; - } - clk_81 = clk_get_rate(clk); - clk_unit = clk_81 / 90000; - pr_info("[%s:%d] clk_81 = %x clk_unit =%x\n", __func__, - __LINE__, clk_81, clk_unit); - pcr_regs = 1 << PCR_EN | clk_unit; - pr_info("[tsdemux_init] the set pcr_regs =%x\n", pcr_regs); - if (READ_DEMUX_REG(TS_HIU_CTL_2) & 0x80) { - WRITE_DEMUX_REG(PCR90K_CTL_2, pcr_regs); - WRITE_DEMUX_REG(ASSIGN_PID_NUMBER_2, pcr_num); - pr_info("[tsdemux_init] To use device 2,pcr_num=%d\n", - pcr_num); - pr_info("tsdemux_init] the read pcr_regs= %x\n", - READ_DEMUX_REG(PCR90K_CTL_2)); - } else if (READ_DEMUX_REG(TS_HIU_CTL_3) & 0x80) { - WRITE_DEMUX_REG(PCR90K_CTL_3, pcr_regs); - WRITE_DEMUX_REG(ASSIGN_PID_NUMBER_3, pcr_num); - pr_info("[tsdemux_init] To use device 3,pcr_num=%d\n", - pcr_num); - pr_info("tsdemux_init] the read pcr_regs= %x\n", - READ_DEMUX_REG(PCR90K_CTL_3)); - } else { - WRITE_DEMUX_REG(PCR90K_CTL, pcr_regs); - WRITE_DEMUX_REG(ASSIGN_PID_NUMBER, pcr_num); - pr_info("[tsdemux_init] To use device 1,pcr_num=%d\n", - pcr_num); - pr_info("tsdemux_init] the read pcr_regs= %x\n", - READ_DEMUX_REG(PCR90K_CTL)); - } - curr_pcr_num = pcr_num; - } - return 1; -} - -s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc, - struct vdec_s *vdec) -{ - s32 r; - u32 parser_sub_start_ptr; - u32 parser_sub_end_ptr; - u32 parser_sub_rp; - pcrvideo_valid = 0; - pcraudio_valid = 0; - pcr_init_flag = 0; - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - /*TODO clk */ - /* - *switch_mod_gate_by_type(MOD_DEMUX, 1); - */ - /* #endif */ - - amports_switch_gate("demux", 1); - - parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR); - parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR); - parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP); - - WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER); - - if (enable_demux_driver()) { - tsdemux_reset(); - } else { - WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER | RESET_DEMUXSTB); - - WRITE_DEMUX_REG(STB_TOP_CONFIG, 0); - WRITE_DEMUX_REG(DEMUX_CONTROL, 0); - } - - /* set PID filter */ - pr_info - ("tsdemux video_pid = 0x%x, audio_pid = 0x%x,", - vid, aid); - pr_info - ("sub_pid = 0x%x, pcrid = 0x%x\n", - sid, pcrid); - - if (!enable_demux_driver()) { - WRITE_DEMUX_REG(FM_WR_DATA, - (((vid < 0x1fff) - ? (vid & 0x1fff) | (VIDEO_PACKET << 13) - : 0xffff) << 16) - | ((aid < 0x1fff) - ? (aid & 0x1fff) | (AUDIO_PACKET << 13) - : 0xffff)); - WRITE_DEMUX_REG(FM_WR_ADDR, 0x8000); - while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000) - ; - - WRITE_DEMUX_REG(FM_WR_DATA, - (((sid < 0x1fff) - ? (sid & 0x1fff) | (SUB_PACKET << 13) - : 0xffff) << 16) - | 0xffff); - WRITE_DEMUX_REG(FM_WR_ADDR, 0x8001); - while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000) - ; - - WRITE_DEMUX_REG(MAX_FM_COMP_ADDR, 1); - - WRITE_DEMUX_REG(STB_INT_MASK, 0); - WRITE_DEMUX_REG(STB_INT_STATUS, 0xffff); - - /* TS data path */ - WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0x7000); - WRITE_DEMUX_REG(DEMUX_MEM_REQ_EN, - (1 << VIDEO_PACKET) | - (1 << AUDIO_PACKET) | (1 << SUB_PACKET)); - WRITE_DEMUX_REG(DEMUX_ENDIAN, - (7 << OTHER_ENDIAN) | - (7 << BYPASS_ENDIAN) | (0 << SECTION_ENDIAN)); - WRITE_DEMUX_REG(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); - WRITE_DEMUX_REG(TS_FILE_CONFIG, - (demux_skipbyte << 16) | - (6 << DES_OUT_DLY) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | - (1 << TS_HIU_ENABLE) | (4 << FEC_FILE_CLK_DIV)); - - /* enable TS demux */ - WRITE_DEMUX_REG(DEMUX_CONTROL, - (1 << STB_DEMUX_ENABLE) | - (1 << KEEP_DUPLICATE_PACKAGE)); - } - - if (fetchbuf == 0) { - pr_info("%s: no fetchbuf\n", __func__); - return -ENOMEM; - } - - /* hook stream buffer with PARSER */ - if (has_hevc_vdec() && is_hevc) { - WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start + - vdec->input.size - 8); - - if (vdec_single(vdec)) { - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - /* set vififo_vbuf_rp_sel=>hevc */ - WRITE_VREG(DOS_GEN_CTRL0, 3 << 1); - /* set use_parser_vbuf_wp */ - SET_VREG_MASK(HEVC_STREAM_CONTROL, - (1 << 3) | (0 << 4)); - /* set stream_fetch_enable */ - SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); - /* set stream_buffer_hole with 256 bytes */ - SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, - (1 << 29)); - } else { - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start); - } - } else { - WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start + - vdec->input.size - 8); - - if (vdec_single(vdec)) { - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - - WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, - MEM_BUFCTRL_INIT); - /* set vififo_vbuf_rp_sel=>vdec */ - if (has_hevc_vdec()) - WRITE_VREG(DOS_GEN_CTRL0, 0); - } else { - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - ES_VID_MAN_RD_PTR); - WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start); - WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start); - } - } - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_PARSER_REG(PARSER_CONFIG, - (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | - (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | - (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); - WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_rp); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (has_hevc_vdec()) - r = pts_start((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO); - else - /* #endif */ - r = pts_start(PTS_TYPE_VIDEO); - - if (r < 0) { - pr_info("Video pts start failed.(%d)\n", r); - goto err1; - } - r = pts_start(PTS_TYPE_AUDIO); - if (r < 0) { - pr_info("Audio pts start failed.(%d)\n", r); - goto err2; - } - /*TODO irq */ - - r = vdec_request_irq(PARSER_IRQ, parser_isr, - "tsdemux-fetch", (void *)tsdemux_fetch_id); - - if (r) - goto err3; - - WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff); - WRITE_PARSER_REG(PARSER_INT_ENABLE, - PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT); - - WRITE_PARSER_REG(PARSER_VIDEO_HOLE, 0x400); - WRITE_PARSER_REG(PARSER_AUDIO_HOLE, 0x400); - - discontinued_counter = 0; - - if (!enable_demux_driver()) { - /*TODO irq */ - - r = vdec_request_irq(DEMUX_IRQ, tsdemux_isr, - "tsdemux-irq", (void *)tsdemux_irq_id); - - WRITE_DEMUX_REG(STB_INT_MASK, (1 << SUB_PES_READY) - | (1 << NEW_PDTS_READY) - | (1 << DIS_CONTINUITY_PACKET)); - if (r) - goto err4; - } else { - tsdemux_config(); - tsdemux_request_irq(tsdemux_isr, (void *)tsdemux_irq_id); - if (vid < 0x1FFF) { - curr_vid_id = vid; - tsdemux_set_vid(vid); - pcrvideo_valid = 1; - } - if (aid < 0x1FFF) { - curr_aud_id = aid; - tsdemux_set_aid(aid); - pcraudio_valid = 1; - } - if (sid < 0x1FFF) { - curr_sub_id = sid; - tsdemux_set_sid(sid); - } - - curr_pcr_id = pcrid; - pcrscr_valid = reset_pcr_regs(); - - if ((pcrid < 0x1FFF) && (pcrid != vid) && (pcrid != aid) - && (pcrid != sid)) - tsdemux_set_pcrid(pcrid); - } - - first_pcr = 0; - - return 0; - -err4: - /*TODO irq */ - - if (!enable_demux_driver()) - vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id); - -err3: - pts_stop(PTS_TYPE_AUDIO); -err2: - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if (has_hevc_vdec()) - pts_stop((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO); - else - /* #endif */ - pts_stop(PTS_TYPE_VIDEO); -err1: - pr_info("TS Demux init failed.\n"); - return -ENOENT; -} - -void tsdemux_release(void) -{ - pcrscr_valid = 0; - first_pcr = 0; - pcr_init_flag = 0; - - WRITE_PARSER_REG(PARSER_INT_ENABLE, 0); - WRITE_PARSER_REG(PARSER_VIDEO_HOLE, 0); - WRITE_PARSER_REG(PARSER_AUDIO_HOLE, 0); - - /*TODO irq */ - - vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id); - - if (!enable_demux_driver()) { - WRITE_DEMUX_REG(STB_INT_MASK, 0); - /*TODO irq */ - - vdec_free_irq(DEMUX_IRQ, (void *)tsdemux_irq_id); - } else { - - tsdemux_set_aid(0xffff); - tsdemux_set_vid(0xffff); - tsdemux_set_sid(0xffff); - tsdemux_set_pcrid(0xffff); - tsdemux_free_irq(); - - curr_vid_id = 0xffff; - curr_aud_id = 0xffff; - curr_sub_id = 0xffff; - curr_pcr_id = 0xffff; - curr_pcr_num = 0xffff; - } - - pts_stop(PTS_TYPE_VIDEO); - pts_stop(PTS_TYPE_AUDIO); - - WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER); -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); - WRITE_PARSER_REG(PARSER_VIDEO_WP, 0); - WRITE_PARSER_REG(PARSER_VIDEO_RP, 0); -#endif - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - /*TODO clk */ - /* - *switch_mod_gate_by_type(MOD_DEMUX, 0); - */ - /* #endif */ - amports_switch_gate("demux", 0); - -} -EXPORT_SYMBOL(tsdemux_release); - -static int limited_delay_check(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count) -{ - int write_size; - - if (vbuf->max_buffer_delay_ms > 0 && abuf->max_buffer_delay_ms > 0 && - stbuf_level(vbuf) > 1024 && stbuf_level(abuf) > 256) { - int vdelay = - calculation_stream_delayed_ms(PTS_TYPE_VIDEO, - NULL, NULL); - int adelay = - calculation_stream_delayed_ms(PTS_TYPE_AUDIO, - NULL, NULL); - /*max wait 100ms,if timeout,try again top level. */ - int maxretry = 10; - /*too big delay,do wait now. */ - /*if noblock mode,don't do wait. */ - if (!(file->f_flags & O_NONBLOCK)) { - while (vdelay > vbuf->max_buffer_delay_ms - && adelay > abuf->max_buffer_delay_ms - && maxretry-- > 0) { - msleep(20); - vdelay = - calculation_stream_delayed_ms - (PTS_TYPE_VIDEO, NULL, NULL); - adelay = - calculation_stream_delayed_ms - (PTS_TYPE_AUDIO, NULL, NULL); - } - } - if (vdelay > vbuf->max_buffer_delay_ms - && adelay > abuf->max_buffer_delay_ms) - return 0; - } - write_size = min(stbuf_space(vbuf), stbuf_space(abuf)); - write_size = min_t(int, count, write_size); - return write_size; -} - -ssize_t drm_tswrite(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count) -{ - s32 r; - u32 realcount = count; - u32 re_count = count; - u32 havewritebytes = 0; - - struct drm_info tmpmm; - struct drm_info *drm = &tmpmm; - u32 res = 0; - int isphybuf = 0; - unsigned long realbuf; - - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - size_t wait_size, write_size; - - if (buf == NULL || count == 0) - return -EINVAL; - - res = copy_from_user(drm, buf, sizeof(struct drm_info)); - if (res) { - pr_info("drm kmalloc failed res[%d]\n", res); - return -EFAULT; - } - - if (drm->drm_flag == TYPE_DRMINFO && drm->drm_level == DRM_LEVEL1) { - /* buf only has drminfo not have esdata; */ - if (drm->drm_pktsize <= MAX_DRM_PACKAGE_SIZE) - realcount = drm->drm_pktsize; - else { - pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); - return -EINVAL; - } - realbuf = drm->drm_phy; - isphybuf = 1; - } else - realbuf = (unsigned long)buf; - /* pr_info("drm->drm_flag = 0x%x,realcount = %d , buf = 0x%x ",*/ - /*drm->drm_flag,realcount, buf); */ - - count = realcount; - - while (count > 0) { - if ((stbuf_space(vbuf) < count) || - (stbuf_space(abuf) < count)) { - if (file->f_flags & O_NONBLOCK) { - int v_stbuf_space = stbuf_space(vbuf); - int a_stbuf_space = stbuf_space(abuf); - - write_size = min(v_stbuf_space, a_stbuf_space); - /*have 188 bytes,write now., */ - if (write_size <= 188) - return -EAGAIN; - } else { - wait_size = - min(stbuf_canusesize(vbuf) / 8, - stbuf_canusesize(abuf) / 4); - if ((port->flag & PORT_FLAG_VID) - && (stbuf_space(vbuf) < wait_size)) { - r = stbuf_wait_space(vbuf, wait_size); - - if (r < 0) { - pr_info - ("write no space--- "); - pr_info - ("no space,%d--%d,r-%d\n", - stbuf_space(vbuf), - stbuf_space(abuf), r); - return r; - } - } - - if ((port->flag & PORT_FLAG_AID) - && (stbuf_space(abuf) < wait_size)) { - r = stbuf_wait_space(abuf, wait_size); - - if (r < 0) { - pr_info - ("write no stbuf_wait_space--"); - pr_info - ("no space,%d--%d,r-%d\n", - stbuf_space(vbuf), - stbuf_space(abuf), r); - return r; - } - } - } - } - - write_size = min(stbuf_space(vbuf), stbuf_space(abuf)); - write_size = min(count, write_size); - /* pr_info("write_size = %d,count = %d,\n",*/ - /*write_size, count); */ - if (write_size > 0) - r = _tsdemux_write((const char __user *)realbuf, - write_size, isphybuf); - else - return -EAGAIN; - - havewritebytes += r; - - /* pr_info("havewritebytes = %d, r = %d,\n",*/ - /*havewritebytes, r); */ - if (havewritebytes == realcount) - break; /* write ok; */ - else if (havewritebytes > realcount) - pr_info(" error ! write too much\n"); - - count -= r; - } - return re_count; -} - -ssize_t tsdemux_write(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count) -{ - s32 r; - struct port_priv_s *priv = (struct port_priv_s *)file->private_data; - struct stream_port_s *port = priv->port; - size_t wait_size, write_size; - - if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) { - if (file->f_flags & O_NONBLOCK) { - write_size = min(stbuf_space(vbuf), stbuf_space(abuf)); - if (write_size <= 188) /*have 188 bytes,write now., */ - return -EAGAIN; - } else { - wait_size = - min(stbuf_canusesize(vbuf) / 8, - stbuf_canusesize(abuf) / 4); - if ((port->flag & PORT_FLAG_VID) - && (stbuf_space(vbuf) < wait_size)) { - r = stbuf_wait_space(vbuf, wait_size); - - if (r < 0) { - /* pr_info("write no space--- "); - * pr_info("no space,%d--%d,r-%d\n", - * stbuf_space(vbuf), - * stbuf_space(abuf),r); - */ - return r; - } - } - - if ((port->flag & PORT_FLAG_AID) - && (stbuf_space(abuf) < wait_size)) { - r = stbuf_wait_space(abuf, wait_size); - - if (r < 0) { - /* pr_info("write no stbuf_wait_space")' - * pr_info{"---no space,%d--%d,r-%d\n", - * stbuf_space(vbuf), - * stbuf_space(abuf),r); - */ - return r; - } - } - } - } - vbuf->last_write_jiffies64 = jiffies_64; - abuf->last_write_jiffies64 = jiffies_64; - write_size = limited_delay_check(file, vbuf, abuf, buf, count); - if (write_size > 0) - return _tsdemux_write(buf, write_size, 0); - else - return -EAGAIN; -} - -static ssize_t show_discontinue_counter(struct class *class, - struct class_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", discontinued_counter); -} - -static struct class_attribute tsdemux_class_attrs[] = { - __ATTR(discontinue_counter, S_IRUGO, show_discontinue_counter, NULL), - __ATTR_NULL -}; - -static struct class tsdemux_class = { - .name = "tsdemux", - .class_attrs = tsdemux_class_attrs, - }; - -int tsdemux_class_register(void) -{ - int r = class_register(&tsdemux_class); - - if (r < 0) - pr_info("register tsdemux class error!\n"); - discontinued_counter = 0; - return r; -} - -void tsdemux_class_unregister(void) -{ - class_unregister(&tsdemux_class); -} - -void tsdemux_change_avid(unsigned int vid, unsigned int aid) -{ - if (!enable_demux_driver()) { - WRITE_DEMUX_REG(FM_WR_DATA, - (((vid & 0x1fff) | (VIDEO_PACKET << 13)) << 16) - | ((aid & 0x1fff) | (AUDIO_PACKET << 13))); - WRITE_DEMUX_REG(FM_WR_ADDR, 0x8000); - while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000) - ; - } else { - curr_vid_id = vid; - curr_aud_id = aid; - - tsdemux_set_vid(vid); - tsdemux_set_aid(aid); - - reset_pcr_regs(); - } - -} - -void tsdemux_change_sid(unsigned int sid) -{ - if (!enable_demux_driver()) { - WRITE_DEMUX_REG(FM_WR_DATA, - (((sid & 0x1fff) | (SUB_PACKET << 13)) << 16) - | 0xffff); - WRITE_DEMUX_REG(FM_WR_ADDR, 0x8001); - while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000) - ; - } else { - curr_sub_id = sid; - - tsdemux_set_sid(sid); - - reset_pcr_regs(); - } - -} - -void tsdemux_audio_reset(void) -{ - ulong flags; - - DEFINE_SPINLOCK(lock); - - spin_lock_irqsave(&lock, flags); - - WRITE_PARSER_REG(PARSER_AUDIO_WP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_RP, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - - WRITE_PARSER_REG(PARSER_AUDIO_START_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR)); - WRITE_PARSER_REG(PARSER_AUDIO_END_PTR, - READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR)); - CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); - - WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); - - spin_unlock_irqrestore(&lock, flags); - -} - -void tsdemux_sub_reset(void) -{ - ulong flags; - DEFINE_SPINLOCK(lock); - u32 parser_sub_start_ptr; - u32 parser_sub_end_ptr; - - spin_lock_irqsave(&lock, flags); - - parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR); - parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR); - - WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); - WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr); - WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr); - SET_PARSER_REG_MASK(PARSER_ES_CONTROL, - (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); - - spin_unlock_irqrestore(&lock, flags); - -} - -void tsdemux_set_skipbyte(int skipbyte) -{ - if (!enable_demux_driver()) - demux_skipbyte = skipbyte; - else - tsdemux_set_skip_byte(skipbyte); - -} - -void tsdemux_set_demux(int dev) -{ - if (enable_demux_driver()) { - unsigned long flags; - int r = 0; - - spin_lock_irqsave(&demux_ops_lock, flags); - if (demux_ops && demux_ops->set_demux) - r = demux_ops->set_demux(dev); - spin_unlock_irqrestore(&demux_ops_lock, flags); - } -} - -u32 tsdemux_pcrscr_get(void) -{ - u32 pcr = 0; - - if (pcrscr_valid == 0) - return 0; - - if (READ_DEMUX_REG(TS_HIU_CTL_2) & 0x80) - pcr = READ_DEMUX_REG(PCR_DEMUX_2); - else if (READ_DEMUX_REG(TS_HIU_CTL_3) & 0x80) - pcr = READ_DEMUX_REG(PCR_DEMUX_3); - else - pcr = READ_DEMUX_REG(PCR_DEMUX); - if (first_pcr == 0) - first_pcr = pcr; - return pcr; -} - -u32 tsdemux_first_pcrscr_get(void) -{ - if (pcrscr_valid == 0) - return 0; - - if (first_pcr == 0) { - u32 pcr; - if (READ_DEMUX_REG(TS_HIU_CTL_2) & 0x80) - pcr = READ_DEMUX_REG(PCR_DEMUX_2); - else if (READ_DEMUX_REG(TS_HIU_CTL_3) & 0x80) - pcr = READ_DEMUX_REG(PCR_DEMUX_3); - else - pcr = READ_DEMUX_REG(PCR_DEMUX); - first_pcr = pcr; - /* pr_info("set first_pcr = 0x%x\n", pcr); */ - } - - return first_pcr; -} - -u8 tsdemux_pcrscr_valid(void) -{ - return pcrscr_valid; -} - -u8 tsdemux_pcraudio_valid(void) -{ - return pcraudio_valid; -} - -u8 tsdemux_pcrvideo_valid(void) -{ - return pcrvideo_valid; -} - -void tsdemux_pcr_set(unsigned int pcr) -{ - if (pcr_init_flag == 0) { - /*timestamp_pcrscr_set(pcr); - timestamp_pcrscr_enable(1);*/ - pcr_init_flag = 1; - } -} - -void tsdemux_tsync_func_init(void) -{ - register_tsync_callbackfunc( - TSYNC_PCRSCR_VALID, (void *)(tsdemux_pcrscr_valid)); - register_tsync_callbackfunc( - TSYNC_PCRSCR_GET, (void *)(tsdemux_pcrscr_get)); - register_tsync_callbackfunc( - TSYNC_FIRST_PCRSCR_GET, (void *)(tsdemux_first_pcrscr_get)); - register_tsync_callbackfunc( - TSYNC_PCRAUDIO_VALID, (void *)(tsdemux_pcraudio_valid)); - register_tsync_callbackfunc( - TSYNC_PCRVIDEO_VALID, (void *)(tsdemux_pcrvideo_valid)); - register_tsync_callbackfunc( - TSYNC_BUF_BY_BYTE, (void *)(get_buf_by_type)); - register_tsync_callbackfunc( - TSYNC_STBUF_LEVEL, (void *)(stbuf_level)); - register_tsync_callbackfunc( - TSYNC_STBUF_SPACE, (void *)(stbuf_space)); - register_tsync_callbackfunc( - TSYNC_STBUF_SIZE, (void *)(stbuf_size)); -} - - diff --git a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.h b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.h deleted file mode 100644 index f63bcdf0b632..000000000000 --- a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/parser/tsdemux.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef TSDEMUX_H -#define TSDEMUX_H -#include - -/* TODO: move to register headers */ -#define NEW_PDTS_READY 4 -#define AUDIO_PTS_READY 2 -#define VIDEO_PTS_READY 0 -#define DIS_CONTINUITY_PACKET 6 -#define SUB_PES_READY 7 -#define PCR_READY 11 - -#define PARSER_INTSTAT_FETCH_CMD (1<<7) - -#define FETCH_ENDIAN 27 -#define FETCH_ENDIAN_MASK (0x7<<27) - -#define RESET_DEMUXSTB (1<<1) -#define RESET_PARSER (1<<8) - -#define VIDEO_PACKET 0 -#define AUDIO_PACKET 1 -#define SUB_PACKET 2 - -#define OTHER_ENDIAN 6 -#define BYPASS_ENDIAN 3 -#define SECTION_ENDIAN 0 - -#define USE_HI_BSF_INTERFACE 7 -#define DES_OUT_DLY 8 -#define TRANSPORT_SCRAMBLING_CONTROL_ODD 6 -#define TS_HIU_ENABLE 5 -#define FEC_FILE_CLK_DIV 0 -#define STB_DEMUX_ENABLE 4 -#define KEEP_DUPLICATE_PACKAGE 6 - -#define ES_VID_MAN_RD_PTR (1<<0) -#define ES_AUD_MAN_RD_PTR (1<<4) - -#define PS_CFG_PFIFO_EMPTY_CNT_BIT 16 -#define PS_CFG_MAX_ES_WR_CYCLE_BIT 12 -#define PS_CFG_MAX_FETCH_CYCLE_BIT 0 - -#define ES_SUB_WR_ENDIAN_BIT 9 -#define ES_SUB_MAN_RD_PTR (1<<8) -#define PARSER_INTSTAT_FETCH_CMD (1<<7) - -#define PARSER_INT_HOST_EN_BIT 8 - -struct stream_buf_s; -struct vdec_s; - -extern s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc, - struct vdec_s *vdec); - -extern void tsdemux_release(void); -extern ssize_t drm_tswrite(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count); - -extern ssize_t tsdemux_write(struct file *file, - struct stream_buf_s *vbuf, - struct stream_buf_s *abuf, - const char __user *buf, size_t count); - -extern u32 tsdemux_pcrscr_get(void); -extern u8 tsdemux_pcrscr_valid(void); -extern u8 tsdemux_pcraudio_valid(void); -extern u8 tsdemux_pcrvideo_valid(void); -extern u32 tsdemux_first_pcrscr_get(void); -extern void timestamp_pcrscr_enable(u32 enable); -extern void timestamp_pcrscr_set(u32 pts); - -int tsdemux_class_register(void); -void tsdemux_class_unregister(void); -void tsdemux_change_avid(unsigned int vid, unsigned int aid); -void tsdemux_change_sid(unsigned int sid); -void tsdemux_audio_reset(void); -void tsdemux_sub_reset(void); -void tsdemux_set_skipbyte(int skipbyte); -void tsdemux_set_demux(int dev); -void tsdemux_tsync_func_init(void); - - -#endif /* TSDEMUX_H */ diff --git a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c deleted file mode 100644 index bfcf6122e7d8..000000000000 --- a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c +++ /dev/null @@ -1,715 +0,0 @@ -/* - * drivers/amlogic/media/subtitle/subtitle.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include "amports_priv.h" - -//#include "amlog.h" -//MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0, LOG_DEFAULT_LEVEL_DESC, - //LOG_DEFAULT_MASK_DESC); -#define DEVICE_NAME "amsubtitle" -/* Dev name as it appears in /proc/devices */ -#define DEVICE_CLASS_NAME "subtitle" - -static int subdevice_open; - -#define MAX_SUBTITLE_PACKET 10 -static DEFINE_MUTEX(amsubtitle_mutex); - -struct subtitle_data_s { - int subtitle_size; - int subtitle_pts; - char *data; -}; -static struct subtitle_data_s subtitle_data[MAX_SUBTITLE_PACKET]; -static int subtitle_enable = 1; -static int subtitle_total; -static int subtitle_width; -static int subtitle_height; -static int subtitle_type = -1; -static int subtitle_current; /* no subtitle */ -/* sub_index node will be modified by libplayer; amlogicplayer will use */ -/* it to detect wheather libplayer switch sub finished or not */ -static int subtitle_index; /* no subtitle */ -/* static int subtitle_size = 0; */ -/* static int subtitle_read_pos = 0; */ -static int subtitle_write_pos; -static int subtitle_start_pts; -static int subtitle_fps; -static int subtitle_subtype; -static int subtitle_reset; -/* static int *subltitle_address[MAX_SUBTITLE_PACKET]; */ - -enum subinfo_para_e { - SUB_NULL = -1, - SUB_ENABLE = 0, - SUB_TOTAL, - SUB_WIDTH, - SUB_HEIGHT, - SUB_TYPE, - SUB_CURRENT, - SUB_INDEX, - SUB_WRITE_POS, - SUB_START_PTS, - SUB_FPS, - SUB_SUBTYPE, - SUB_RESET, - SUB_DATA_T_SIZE, - SUB_DATA_T_DATA -}; - -struct subinfo_para_s { - enum subinfo_para_e subinfo_type; - int subtitle_info; - char *data; -}; - -/* total */ -/* curr */ -/* bimap */ -/* text */ -/* type */ -/* info */ -/* pts */ -/* duration */ -/* color pallete */ -/* width/height */ - -static ssize_t show_curr(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: current\n", subtitle_current); -} - -static ssize_t store_curr(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int curr; - ssize_t r; - - r = kstrtoint(buf, 0, &curr); - if (r < 0) - return -EINVAL; - - - subtitle_current = curr; - - return size; -} - -static ssize_t show_index(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: current\n", subtitle_index); -} - -static ssize_t store_index(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int curr; - ssize_t r; - - r = kstrtoint(buf, 0, &curr); - if (r < 0) - return -EINVAL; - - subtitle_index = curr; - - return size; -} - -static ssize_t show_reset(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: current\n", subtitle_reset); -} - -static ssize_t store_reset(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int reset; - ssize_t r; - - r = kstrtoint(buf, 0, &reset); - - pr_info("reset is %d\n", reset); - if (r < 0) - return -EINVAL; - - - subtitle_reset = reset; - - return size; -} - -static ssize_t show_type(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: type\n", subtitle_type); -} - -static ssize_t store_type(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int type; - ssize_t r; - - r = kstrtoint(buf, 0, &type); - if (r < 0) - return -EINVAL; - - subtitle_type = type; - - return size; -} - -static ssize_t show_width(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: width\n", subtitle_width); -} - -static ssize_t store_width(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int width; - ssize_t r; - - r = kstrtoint(buf, 0, &width); - if (r < 0) - return -EINVAL; - - subtitle_width = width; - - return size; -} - -static ssize_t show_height(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: height\n", subtitle_height); -} - -static ssize_t store_height(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int height; - ssize_t r; - - r = kstrtoint(buf, 0, &height); - if (r < 0) - return -EINVAL; - - subtitle_height = height; - - return size; -} - -static ssize_t show_total(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: num\n", subtitle_total); -} - -static ssize_t store_total(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int total; - ssize_t r; - - r = kstrtoint(buf, 0, &total); - if (r < 0) - return -EINVAL; - pr_info("subtitle num is %d\n", total); - subtitle_total = total; - - return size; -} - -static ssize_t show_enable(struct class *class, struct class_attribute *attr, - char *buf) -{ - if (subtitle_enable) - return sprintf(buf, "1: enabled\n"); - - return sprintf(buf, "0: disabled\n"); -} - -static ssize_t store_enable(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int mode; - ssize_t r; - - r = kstrtoint(buf, 0, &mode); - if (r < 0) - return -EINVAL; - pr_info("subtitle enable is %d\n", mode); - subtitle_enable = mode ? 1 : 0; - - return size; -} - -static ssize_t show_size(struct class *class, struct class_attribute *attr, - char *buf) -{ - if (subtitle_enable) - return sprintf(buf, "1: size\n"); - - return sprintf(buf, "0: size\n"); -} - -static ssize_t store_size(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int ssize; - ssize_t r; - - r = kstrtoint(buf, 0, &ssize); - if (r < 0) - return -EINVAL; - pr_info("subtitle size is %d\n", ssize); - subtitle_data[subtitle_write_pos].subtitle_size = ssize; - - return size; -} - -static ssize_t show_startpts(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: pts\n", subtitle_start_pts); -} - -static ssize_t store_startpts(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int spts; - ssize_t r; - - r = kstrtoint(buf, 0, &spts); - if (r < 0) - return -EINVAL; - pr_info("subtitle start pts is %x\n", spts); - subtitle_start_pts = spts; - - return size; -} - -static ssize_t show_data(struct class *class, struct class_attribute *attr, - char *buf) -{ -#if 0 - if (subtitle_data[subtitle_write_pos].data) - return sprintf(buf, "%lld\n", - (unsigned long)(subtitle_data[subtitle_write_pos].data)); -#endif - return sprintf(buf, "0: disabled\n"); -} - -static ssize_t store_data(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int address; - ssize_t r; - - r = kstrtoint(buf, 0, &address); - if ((r == 0)) - return -EINVAL; -#if 0 - if (subtitle_data[subtitle_write_pos].subtitle_size > 0) { - subtitle_data[subtitle_write_pos].data = vmalloc(( - subtitle_data[subtitle_write_pos].subtitle_size)); - if (subtitle_data[subtitle_write_pos].data) - memcpy(subtitle_data[subtitle_write_pos].data, - (unsigned long *)address, - subtitle_data[subtitle_write_pos].subtitle_size); - } - pr_info("subtitle data address is %x", - (unsigned int)(subtitle_data[subtitle_write_pos].data)); -#endif - subtitle_write_pos++; - if (subtitle_write_pos >= MAX_SUBTITLE_PACKET) - subtitle_write_pos = 0; - return 1; -} - -static ssize_t show_fps(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: fps\n", subtitle_fps); -} - -static ssize_t store_fps(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int ssize; - ssize_t r; - - r = kstrtoint(buf, 0, &ssize); - if (r < 0) - return -EINVAL; - pr_info("subtitle fps is %d\n", ssize); - subtitle_fps = ssize; - - return size; -} - -static ssize_t show_subtype(struct class *class, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d: subtype\n", subtitle_subtype); -} - -static ssize_t store_subtype(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - unsigned int ssize; - ssize_t r; - - r = kstrtoint(buf, 0, &ssize); - if (r < 0) - return -EINVAL; - pr_info("subtitle subtype is %d\n", ssize); - subtitle_subtype = ssize; - - return size; -} - -static struct class_attribute subtitle_class_attrs[] = { - __ATTR(enable, 0664, show_enable, store_enable), - __ATTR(total, 0664, show_total, store_total), - __ATTR(width, 0664, show_width, store_width), - __ATTR(height, 0664, show_height, store_height), - __ATTR(type, 0664, show_type, store_type), - __ATTR(curr, 0664, show_curr, store_curr), - __ATTR(index, 0664, show_index, store_index), - __ATTR(size, 0664, show_size, store_size), - __ATTR(data, 0664, show_data, store_data), - __ATTR(startpts, 0664, show_startpts, - store_startpts), - __ATTR(fps, 0664, show_fps, store_fps), - __ATTR(subtype, 0664, show_subtype, - store_subtype), - __ATTR(reset, 0644, show_reset, store_reset), - __ATTR_NULL -}; - - -/********************************************************* - * /dev/amvideo APIs - *********************************************************/ -static int amsubtitle_open(struct inode *inode, struct file *file) -{ - mutex_lock(&amsubtitle_mutex); - - if (subdevice_open) { - mutex_unlock(&amsubtitle_mutex); - return -EBUSY; - } - - subdevice_open = 1; - - try_module_get(THIS_MODULE); - - mutex_unlock(&amsubtitle_mutex); - - return 0; -} - -static int amsubtitle_release(struct inode *inode, struct file *file) -{ - mutex_lock(&amsubtitle_mutex); - - subdevice_open = 0; - - module_put(THIS_MODULE); - - mutex_unlock(&amsubtitle_mutex); - - return 0; -} - -static long amsubtitle_ioctl(struct file *file, unsigned int cmd, ulong arg) -{ - switch (cmd) { - case AMSTREAM_IOC_GET_SUBTITLE_INFO: { - struct subinfo_para_s Vstates; - struct subinfo_para_s *states = &Vstates; - - if (copy_from_user((void *)states, - (void *)arg, sizeof(Vstates))) - return -EFAULT; - switch (states->subinfo_type) { - case SUB_ENABLE: - states->subtitle_info = subtitle_enable; - break; - case SUB_TOTAL: - states->subtitle_info = subtitle_total; - break; - case SUB_WIDTH: - states->subtitle_info = subtitle_width; - break; - case SUB_HEIGHT: - states->subtitle_info = subtitle_height; - break; - case SUB_TYPE: - states->subtitle_info = subtitle_type; - break; - case SUB_CURRENT: - states->subtitle_info = subtitle_current; - break; - case SUB_INDEX: - states->subtitle_info = subtitle_index; - break; - case SUB_WRITE_POS: - states->subtitle_info = subtitle_write_pos; - break; - case SUB_START_PTS: - states->subtitle_info = subtitle_start_pts; - break; - case SUB_FPS: - states->subtitle_info = subtitle_fps; - break; - case SUB_SUBTYPE: - states->subtitle_info = subtitle_subtype; - break; - case SUB_RESET: - states->subtitle_info = subtitle_reset; - break; - case SUB_DATA_T_SIZE: - states->subtitle_info = - subtitle_data[subtitle_write_pos].subtitle_size; - break; - case SUB_DATA_T_DATA: { - if (states->subtitle_info > 0) - states->subtitle_info = - (long)subtitle_data[subtitle_write_pos].data; - } - break; - default: - break; - } - if (copy_to_user((void *)arg, (void *)states, sizeof(Vstates))) - return -EFAULT; - } - - break; - case AMSTREAM_IOC_SET_SUBTITLE_INFO: { - struct subinfo_para_s Vstates; - struct subinfo_para_s *states = &Vstates; - - if (copy_from_user((void *)states, - (void *)arg, sizeof(Vstates))) - return -EFAULT; - switch (states->subinfo_type) { - case SUB_ENABLE: - subtitle_enable = states->subtitle_info; - break; - case SUB_TOTAL: - subtitle_total = states->subtitle_info; - break; - case SUB_WIDTH: - subtitle_width = states->subtitle_info; - break; - case SUB_HEIGHT: - subtitle_height = states->subtitle_info; - break; - case SUB_TYPE: - subtitle_type = states->subtitle_info; - break; - case SUB_CURRENT: - subtitle_current = states->subtitle_info; - break; - case SUB_INDEX: - subtitle_index = states->subtitle_info; - break; - case SUB_WRITE_POS: - subtitle_write_pos = states->subtitle_info; - break; - case SUB_START_PTS: - subtitle_start_pts = states->subtitle_info; - break; - case SUB_FPS: - subtitle_fps = states->subtitle_info; - break; - case SUB_SUBTYPE: - subtitle_subtype = states->subtitle_info; - break; - case SUB_RESET: - subtitle_reset = states->subtitle_info; - break; - case SUB_DATA_T_SIZE: - subtitle_data[subtitle_write_pos].subtitle_size = - states->subtitle_info; - break; - case SUB_DATA_T_DATA: { - if (states->subtitle_info > 0) { - subtitle_data[subtitle_write_pos].data = - vmalloc((states->subtitle_info)); - if (subtitle_data[subtitle_write_pos].data) - memcpy( - subtitle_data[subtitle_write_pos].data, - (char *)states->data, - states->subtitle_info); - } - - subtitle_write_pos++; - if (subtitle_write_pos >= MAX_SUBTITLE_PACKET) - subtitle_write_pos = 0; - } - break; - default: - break; - } - - } - - break; - default: - break; - } - - return 0; -} - -#ifdef CONFIG_COMPAT -static long amsub_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) -{ - long ret = 0; - - ret = amsubtitle_ioctl(file, cmd, (ulong)compat_ptr(arg)); - return ret; -} -#endif - -static const struct file_operations amsubtitle_fops = { - .owner = THIS_MODULE, - .open = amsubtitle_open, - .release = amsubtitle_release, - .unlocked_ioctl = amsubtitle_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = amsub_compat_ioctl, -#endif -}; - -static struct device *amsubtitle_dev; -static dev_t amsub_devno; -static struct class *amsub_clsp; -static struct cdev *amsub_cdevp; -#define AMSUBTITLE_DEVICE_COUNT 1 - -static void create_amsub_attrs(struct class *class) -{ - int i = 0; - - for (i = 0; subtitle_class_attrs[i].attr.name; i++) { - if (class_create_file(class, &subtitle_class_attrs[i]) < 0) - break; - } -} - -static void remove_amsub_attrs(struct class *class) -{ - int i = 0; - - for (i = 0; subtitle_class_attrs[i].attr.name; i++) - class_remove_file(class, &subtitle_class_attrs[i]); -} - -int subtitle_init(void) -{ - int ret = 0; - - ret = alloc_chrdev_region(&amsub_devno, 0, AMSUBTITLE_DEVICE_COUNT, - DEVICE_NAME); - if (ret < 0) { - pr_info("amsub: failed to alloc major number\n"); - ret = -ENODEV; - return ret; - } - - amsub_clsp = class_create(THIS_MODULE, DEVICE_CLASS_NAME); - if (IS_ERR(amsub_clsp)) { - ret = PTR_ERR(amsub_clsp); - goto err1; - } - - create_amsub_attrs(amsub_clsp); - - amsub_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL); - if (!amsub_cdevp) { - /*pr_info("amsub: failed to allocate memory\n");*/ - ret = -ENOMEM; - goto err2; - } - - cdev_init(amsub_cdevp, &amsubtitle_fops); - amsub_cdevp->owner = THIS_MODULE; - /* connect the major/minor number to cdev */ - ret = cdev_add(amsub_cdevp, amsub_devno, AMSUBTITLE_DEVICE_COUNT); - if (ret) { - pr_info("amsub:failed to add cdev\n"); - goto err3; - } - - amsubtitle_dev = device_create(amsub_clsp, - NULL, MKDEV(MAJOR(amsub_devno), 0), - NULL, DEVICE_NAME); - - if (IS_ERR(amsubtitle_dev)) { - pr_err("## Can't create amsubtitle device\n"); - goto err4; - } - - return 0; - -err4: - cdev_del(amsub_cdevp); -err3: - kfree(amsub_cdevp); -err2: - remove_amsub_attrs(amsub_clsp); - class_destroy(amsub_clsp); -err1: - unregister_chrdev_region(amsub_devno, 1); - - return ret; -} -EXPORT_SYMBOL(subtitle_init); - -void subtitle_exit(void) -{ - unregister_chrdev_region(amsub_devno, 1); - device_destroy(amsub_clsp, MKDEV(MAJOR(amsub_devno), 0)); - cdev_del(amsub_cdevp); - kfree(amsub_cdevp); - remove_amsub_attrs(amsub_clsp); - class_destroy(amsub_clsp); -} -EXPORT_SYMBOL(subtitle_exit); - diff --git a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h deleted file mode 100644 index 375a31a06d25..000000000000 --- a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * drivers/amlogic/media/stream_input/amports/amports_priv.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -#ifndef SUBTITLE_H -#define SUBTITLE_H - -int subtitle_init(void); -void subtitle_exit(void); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/Makefile b/drivers/amlogic/media_modules/stream_input/tv_frontend/Makefile deleted file mode 100644 index 404c513d23f2..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -obj-m += aml_hardware_fe.o - -ccflags-y += -I$(srctree)/drivers/media/dvb-core -I$(srctree)/drivers/gpio -I$(srctree)/include - -aml_hardware_fe-objs += aml_fe.o - -# aml_atvdemod-objs += atv_demod/atvdemod_frontend.o -# aml_atvdemod-objs += atv_demod/atvdemod_func.o - -# aml_dtvdemod-objs += dtv_demod/aml_demod.o -# aml_dtvdemod-objs += dtv_demod/amlfrontend.o -# aml_dtvdemod-objs += dtv_demod/demod_func.o -# aml_dtvdemod-objs += dtv_demod/dvbc_func.o -# aml_dtvdemod-objs += dtv_demod/dvbt_func.o -# aml_dtvdemod-objs += dtv_demod/i2c_func.o -# aml_dtvdemod-objs += dtv_demod/tuner_func.o diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c deleted file mode 100644 index 6253def75c4f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -/* - * AMLOGIC DVB frontend driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*add for gpio api by hualing.chen*/ -#include - -#include "aml_fe.h" - -#ifdef pr_dbg -#undef pr_dbg -#endif - -#define pr_dbg(fmt, args ...) \ - pr_info("FE: " fmt, ## args) -#define pr_error(fmt, args ...) pr_err("FE: " fmt, ## args) -#define pr_inf(fmt, args ...) pr_info("FE: " fmt, ## args) - -static DEFINE_SPINLOCK(lock); -static struct aml_fe_drv *tuner_drv_list; -static struct aml_fe_drv *atv_demod_drv_list; -static struct aml_fe_drv *dtv_demod_drv_list; -static struct aml_fe_man fe_man; -static long aml_fe_suspended; - -static int aml_fe_set_sys(struct dvb_frontend *dev, - enum fe_delivery_system sys); - -static struct aml_fe_drv **aml_get_fe_drv_list(enum aml_fe_dev_type_t type) -{ - switch (type) { - case AM_DEV_TUNER: - return &tuner_drv_list; - case AM_DEV_ATV_DEMOD: - return &atv_demod_drv_list; - case AM_DEV_DTV_DEMOD: - return &dtv_demod_drv_list; - default: - return NULL; - } -} - - - -int amlogic_gpio_direction_output(unsigned int pin, int value, - const char *owner) -{ - gpio_direction_output(pin, value); - return 0; -} -EXPORT_SYMBOL(amlogic_gpio_direction_output); -int amlogic_gpio_request(unsigned int pin, const char *label) -{ - return 0; -} -EXPORT_SYMBOL(amlogic_gpio_request); -int aml_register_fe_drv(enum aml_fe_dev_type_t type, struct aml_fe_drv *drv) -{ - if (drv) { - struct aml_fe_drv **list = aml_get_fe_drv_list(type); - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - drv->next = *list; - *list = drv; - - drv->ref = 0; - - spin_unlock_irqrestore(&lock, flags); - } - - return 0; -} -EXPORT_SYMBOL(aml_register_fe_drv); - -int aml_unregister_fe_drv(enum aml_fe_dev_type_t type, struct aml_fe_drv *drv) -{ - int ret = 0; - - if (drv) { - struct aml_fe_drv *pdrv, *pprev; - struct aml_fe_drv **list = aml_get_fe_drv_list(type); - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - if (!drv->ref) { - for (pprev = NULL, pdrv = *list; - pdrv; pprev = pdrv, pdrv = pdrv->next) { - if (pdrv == drv) { - if (pprev) - pprev->next = pdrv->next; - else - *list = pdrv->next; - break; - } - } - } else { - pr_error("fe driver %d is inused\n", drv->id); - ret = -1; - } - - spin_unlock_irqrestore(&lock, flags); - } - - return ret; -} -EXPORT_SYMBOL(aml_unregister_fe_drv); - -static int aml_fe_support_sys(struct aml_fe *fe, - enum fe_delivery_system sys) -{ - if (fe->dtv_demod - && fe->dtv_demod->drv - && fe->dtv_demod->drv->support) { - if (!fe->dtv_demod->drv->support(fe->dtv_demod, sys)) - return 0; - } - - if (fe->atv_demod - && fe->atv_demod->drv - && fe->atv_demod->drv->support) { - if (!fe->atv_demod->drv->support(fe->atv_demod, sys)) - return 0; - } - - if (fe->tuner - && fe->tuner->drv - && fe->tuner->drv->support) { - if (!fe->tuner->drv->support(fe->tuner, sys)) - return 0; - } - - return 1; -} -/* - *#define DTV_START_BLIND_SCAN 71 - *#define DTV_CANCEL_BLIND_SCAN 72 - *#define DTV_BLIND_SCAN_MIN_FRE 73 - *#define DTV_BLIND_SCAN_MAX_FRE 74 - *#define DTV_BLIND_SCAN_MIN_SRATE 75 - *#define DTV_BLIND_SCAN_MAX_SRATE 76 - *#define DTV_BLIND_SCAN_FRE_RANGE 77 - *#define DTV_BLIND_SCAN_FRE_STEP 78 - *#define DTV_BLIND_SCAN_TIMEOUT 79 - */ -static int aml_fe_blind_cmd(struct dvb_frontend *dev, - struct dtv_property *tvp) -{ - struct aml_fe *fe; - int ret = 0; - - fe = dev->demodulator_priv; - pr_error("fe blind cmd into cmd:[%d]\n", tvp->cmd); - switch (tvp->cmd) { - case DTV_START_BLIND_SCAN: - if (fe->dtv_demod - && fe->dtv_demod->drv - && fe->dtv_demod->drv->start_blind_scan) { - ret = fe->dtv_demod->drv->start_blind_scan( - fe->dtv_demod); - } else { - pr_error("fe dtv_demod not surport blind start\n"); - } - break; - case DTV_CANCEL_BLIND_SCAN: - if (fe->dtv_demod - && fe->dtv_demod->drv - && fe->dtv_demod->drv->stop_blind_scan) { - ret = fe->dtv_demod->drv->stop_blind_scan( - fe->dtv_demod); - } else { - pr_error("fe dtv_demod not surport blind stop\n"); - } - break; - case DTV_BLIND_SCAN_MIN_FRE: - fe->blind_scan_para.minfrequency = tvp->u.data; - break; - case DTV_BLIND_SCAN_MAX_FRE: - fe->blind_scan_para.maxfrequency = tvp->u.data; - break; - case DTV_BLIND_SCAN_MIN_SRATE: - fe->blind_scan_para.minSymbolRate = tvp->u.data; - break; - case DTV_BLIND_SCAN_MAX_SRATE: - fe->blind_scan_para.maxSymbolRate = tvp->u.data; - break; - case DTV_BLIND_SCAN_FRE_RANGE: - fe->blind_scan_para.frequencyRange = tvp->u.data; - break; - case DTV_BLIND_SCAN_FRE_STEP: - fe->blind_scan_para.frequencyStep = tvp->u.data; - break; - case DTV_BLIND_SCAN_TIMEOUT: - fe->blind_scan_para.timeout = tvp->u.data; - break; - default: - ret = 0; - break; - } - return ret; -} - -static int aml_fe_set_property(struct dvb_frontend *dev, - struct dtv_property *tvp) -{ - struct aml_fe *fe; - int r = 0; - - fe = dev->demodulator_priv; - - if (tvp->cmd == DTV_DELIVERY_SYSTEM) { - enum fe_delivery_system sys = tvp->u.data; - - pr_error("fe aml_fe_set_property %d\n", sys); - r = aml_fe_set_sys(dev, sys); - if (r < 0) - return r; - } - - if (tvp->cmd == DTV_DELIVERY_SUB_SYSTEM) { - int sub_sys = tvp->u.data; - - pr_error("fe aml_fe_set_property sub_sys: %d\n", sub_sys); - fe->sub_sys = sub_sys; - r = 0; - } - pr_error("fe aml_fe_set_property -tvp->cmd[%d]\n", tvp->cmd); - switch (tvp->cmd) { - case DTV_START_BLIND_SCAN: - case DTV_CANCEL_BLIND_SCAN: - case DTV_BLIND_SCAN_MIN_FRE: - case DTV_BLIND_SCAN_MAX_FRE: - case DTV_BLIND_SCAN_MIN_SRATE: - case DTV_BLIND_SCAN_MAX_SRATE: - case DTV_BLIND_SCAN_FRE_RANGE: - case DTV_BLIND_SCAN_FRE_STEP: - case DTV_BLIND_SCAN_TIMEOUT: - r = aml_fe_blind_cmd(dev, tvp); - if (r < 0) - return r; - default: - break; - } - - if (fe->set_property) { - pr_error("fe fe->set_property -0\n"); - return fe->set_property(dev, tvp); - } - pr_error("fe aml_fe_set_property -2\n"); - return r; -} - -static int aml_fe_get_property(struct dvb_frontend *dev, - struct dtv_property *tvp) -{ - struct aml_fe *fe; - int r = 0; - - fe = dev->demodulator_priv; - - if (tvp->cmd == DTV_TS_INPUT) - tvp->u.data = fe->ts; - if (tvp->cmd == DTV_DELIVERY_SUB_SYSTEM) { - tvp->u.data = fe->sub_sys; - pr_error("fe aml_fe_get_property sub_sys: %d\n", fe->sub_sys); - r = 0; - } - if (fe->get_property) - return fe->get_property(dev, tvp); - - return r; -} - -static int aml_fe_set_sys(struct dvb_frontend *dev, - enum fe_delivery_system sys) -{ - struct aml_fe *fe = dev->demodulator_priv; - unsigned long flags; - int ret = -1; - - if (fe->sys == sys) { - pr_dbg("[%s]:the mode is not change!!!!\n", __func__); - return 0; - } - /*set dvb-t or dvb-t2 - * if dvb-t or t2 is set - * we only set sys value, not init sys - */ - if (fe->sys != SYS_UNDEFINED) { - pr_dbg("release system %d\n", fe->sys); - - if (fe->dtv_demod - && fe->dtv_demod->drv - && fe->dtv_demod->drv->release_sys) - fe->dtv_demod->drv->release_sys(fe->dtv_demod, fe->sys); - if (fe->atv_demod - && fe->atv_demod->drv - && fe->atv_demod->drv->release_sys) - fe->atv_demod->drv->release_sys(fe->atv_demod, fe->sys); - if (fe->tuner - && fe->tuner->drv - && fe->tuner->drv->release_sys) - fe->tuner->drv->release_sys(fe->tuner, fe->sys); - - fe->set_property = NULL; - fe->get_property = NULL; - - fe->sys = SYS_UNDEFINED; - } - - if (sys == SYS_UNDEFINED) - return 0; - - if (!aml_fe_support_sys(fe, sys)) { - int i; - - spin_lock_irqsave(&lock, flags); - for (i = 0; i < FE_DEV_COUNT; i++) { - if (aml_fe_support_sys(&fe_man.fe[i], sys) - && (fe_man.fe[i].dev_id == fe->dev_id)) - break; - } - spin_unlock_irqrestore(&lock, flags); - - if (i >= FE_DEV_COUNT) { - pr_error("do not support delivery system %d\n", sys); - return -1; - } - - fe = &fe_man.fe[i]; - dev->demodulator_priv = fe; - } - - spin_lock_irqsave(&fe->slock, flags); - - memset(&fe->fe->ops.tuner_ops, 0, sizeof(fe->fe->ops.tuner_ops)); - memset(&fe->fe->ops.analog_ops, 0, sizeof(fe->fe->ops.analog_ops)); - memset(&fe->fe->ops.info, 0, sizeof(fe->fe->ops.info)); - fe->fe->ops.release = NULL; - fe->fe->ops.release_sec = NULL; - fe->fe->ops.init = NULL; - fe->fe->ops.sleep = NULL; - fe->fe->ops.write = NULL; - fe->fe->ops.tune = NULL; - fe->fe->ops.get_frontend_algo = NULL; - fe->fe->ops.set_frontend = NULL; - fe->fe->ops.get_tune_settings = NULL; - fe->fe->ops.get_frontend = NULL; - fe->fe->ops.read_status = NULL; - fe->fe->ops.read_ber = NULL; - fe->fe->ops.read_signal_strength = NULL; - fe->fe->ops.read_snr = NULL; - fe->fe->ops.read_ucblocks = NULL; - fe->fe->ops.diseqc_reset_overload = NULL; - fe->fe->ops.diseqc_send_master_cmd = NULL; - fe->fe->ops.diseqc_recv_slave_reply = NULL; - fe->fe->ops.diseqc_send_burst = NULL; - fe->fe->ops.set_tone = NULL; - fe->fe->ops.set_voltage = NULL; - fe->fe->ops.enable_high_lnb_voltage = NULL; - fe->fe->ops.dishnetwork_send_legacy_command = NULL; - fe->fe->ops.i2c_gate_ctrl = NULL; - fe->fe->ops.ts_bus_ctrl = NULL; - fe->fe->ops.search = NULL; - fe->fe->ops.set_property = NULL; - fe->fe->ops.get_property = NULL; - - if (fe->tuner - && fe->tuner->drv - && fe->tuner->drv->get_ops) - fe->tuner->drv->get_ops(fe->tuner, sys, &fe->fe->ops); - - if (fe->atv_demod - && fe->atv_demod->drv - && fe->atv_demod->drv->get_ops) - fe->atv_demod->drv->get_ops(fe->atv_demod, sys, &fe->fe->ops); - - if (fe->dtv_demod - && fe->dtv_demod->drv - && fe->dtv_demod->drv->get_ops) - fe->dtv_demod->drv->get_ops(fe->dtv_demod, sys, &fe->fe->ops); - - spin_unlock_irqrestore(&fe->slock, flags); - - pr_dbg("init system %d\n", sys); - - if (fe->dtv_demod - && fe->dtv_demod->drv - && fe->dtv_demod->drv->init_sys) - ret = fe->dtv_demod->drv->init_sys(fe->dtv_demod, sys); - if (fe->atv_demod - && fe->atv_demod->drv - && fe->atv_demod->drv->init_sys) - ret = fe->atv_demod->drv->init_sys(fe->atv_demod, sys); - if (fe->tuner - && fe->tuner->drv - && fe->tuner->drv->init_sys) - ret = fe->tuner->drv->init_sys(fe->tuner, sys); - - if (ret != 0) { - pr_error("init system, %d fail, ret %d\n", sys, ret); - goto end; - } - - fe->set_property = fe->fe->ops.set_property; - fe->get_property = fe->fe->ops.get_property; - - strcpy(fe->fe->ops.info.name, "amlogic dvb frontend"); - fe->sys = sys; - pr_dbg("set mode ok\n"); - -end: - fe->fe->ops.set_property = aml_fe_set_property; - fe->fe->ops.get_property = aml_fe_get_property; - - return 0; -} - -static const char *aml_fe_dev_type_str(struct aml_fe_dev *dev) -{ - switch (dev->type) { - case AM_DEV_TUNER: - return "tuner"; - case AM_DEV_ATV_DEMOD: - return "atv_demod"; - case AM_DEV_DTV_DEMOD: - return "dtv_demod"; - } - - return ""; -} - -static void aml_fe_property_name(struct aml_fe_dev *dev, const char *name, - char *buf) -{ - const char *tstr; - - tstr = aml_fe_dev_type_str(dev); - - if (name) - sprintf(buf, "%s%d_%s", tstr, dev->dev_id, name); - else - sprintf(buf, "%s%d", tstr, dev->dev_id); -} - -int aml_fe_of_property_string(struct aml_fe_dev *dev, - const char *name, const char **str) -{ - struct platform_device *pdev = dev->man->pdev; - //char buf[128]; - int r; - - //aml_fe_property_name(dev, name, buf); - pr_error("start find resource: \"%s\" --\n", name); - r = of_property_read_string(pdev->dev.of_node, name, str); - if (r) - pr_error("cannot find resource: \"%s\"\n", name); - - return r; -} -EXPORT_SYMBOL(aml_fe_of_property_string); - -int aml_fe_of_property_u32(struct aml_fe_dev *dev, - const char *name, u32 *v) -{ - struct platform_device *pdev = dev->man->pdev; - //char buf[128]; - int r; - - //aml_fe_property_name(dev, name, buf); - r = of_property_read_u32(pdev->dev.of_node, name, v); - if (r) - pr_error("cannot find resource \"%s\"\n", name); - - return r; -} -EXPORT_SYMBOL(aml_fe_of_property_u32); - -static int aml_fe_dev_init(struct aml_fe_man *man, - enum aml_fe_dev_type_t type, - struct aml_fe_dev *dev, - int id) -{ - struct aml_fe_drv **list = aml_get_fe_drv_list(type); - struct aml_fe_drv *drv; - unsigned long flags; - char buf[128]; - const char *str; - char *name = NULL; - u32 value; - int ret; - struct device_node *node; - - dev->man = man; - dev->dev_id = id; - dev->type = type; - dev->drv = NULL; - dev->fe = NULL; - dev->priv_data = NULL; - - memset(buf, 0, 128); - name = NULL; - aml_fe_property_name(dev, name, buf); - pr_dbg("get string: %s\n", buf); - ret = aml_fe_of_property_string(dev, buf, &str); - if (ret) { - pr_dbg("get string: %s error\n", buf); - return 0; - } - - - spin_lock_irqsave(&lock, flags); - - for (drv = *list; drv; drv = drv->next) - if (!strcmp(drv->name, str)) - break; - - if (dev->drv != drv) { - if (dev->drv) { - dev->drv->ref--; - if (dev->drv->owner) - module_put(dev->drv->owner); - } - if (drv) { - drv->ref++; - if (drv->owner) - try_module_get(drv->owner); - } - dev->drv = drv; - } - - spin_unlock_irqrestore(&lock, flags); - - if (drv) { - pr_inf("found driver: %s\n", str); - } else { - pr_err("cannot find driver: %s\n", str); - return -1; - } - /*get i2c adap and i2c addr*/ - memset(buf, 0, 128); - name = "i2c_adap"; - aml_fe_property_name(dev, name, buf); - pr_dbg("get u32: %s\n", buf); - //ret = aml_fe_of_property_u32(dev, buf, &value); - node = of_parse_phandle(dev->man->pdev->dev.of_node, buf, 0); - if (node) { - dev->i2c_adap = of_find_i2c_adapter_by_node(node); - pr_inf("%s:[%p]\n", buf, dev->i2c_adap); - of_node_put(node); - } else { - dev->i2c_adap_id = -1; - pr_error("cannot find resource \"%s\"\n", buf); - } - memset(buf, 0, 128); - name = "i2c_addr"; - aml_fe_property_name(dev, name, buf); - pr_dbg("get u32: %s\n", buf); - ret = aml_fe_of_property_u32(dev, buf, &value); - if (!ret) { - dev->i2c_addr = value; - pr_inf("%s: %d\n", buf, dev->i2c_addr); - } else { - dev->i2c_addr = -1; - pr_error("cannot find resource \"%s\"\n", buf); - } - /*get i2c reset and reset value*/ - memset(buf, 0, 128); - name = "reset_gpio"; - aml_fe_property_name(dev, name, buf); - pr_dbg("get string: %s\n", buf); - ret = aml_fe_of_property_string(dev, buf, &str); - if (!ret) { - dev->reset_gpio = - of_get_named_gpio_flags(dev->man->pdev->dev.of_node, - buf, 0, NULL); - pr_inf("%s: %s\n", buf, str); - } else { - dev->reset_gpio = -1; - pr_error("cannot find resource \"%s\"\n", buf); - } - memset(buf, 0, 128); - name = "reset_value"; - aml_fe_property_name(dev, name, buf); - pr_dbg("get u32: %s\n", buf); - ret = aml_fe_of_property_u32(dev, buf, &value); - if (!ret) { - dev->reset_value = value; - pr_inf("%s: %d\n", buf, dev->reset_value); - } else { - dev->reset_value = -1; - } - - if (dev->drv && dev->drv->init) { - int ret; - - ret = dev->drv->init(dev); - if (ret != 0) { - dev->drv = NULL; - pr_error("[aml_fe..]%s error.\n", __func__); - return ret; - } - } - - return 0; -} - -static int aml_fe_dev_release(struct aml_fe_dev *dev) -{ - if (dev->drv) { - if (dev->drv->owner) - module_put(dev->drv->owner); - dev->drv->ref--; - if (dev->drv->release) - dev->drv->release(dev); - } - - dev->drv = NULL; - return 0; -} - -static void aml_fe_man_run(struct aml_fe *fe) -{ - if (fe->init) - return; - - if (fe->tuner && fe->tuner->drv) - fe->init = 1; - - if (fe->atv_demod && fe->atv_demod->drv) - fe->init = 1; - - if (fe->dtv_demod && fe->dtv_demod->drv) - fe->init = 1; - - if (fe->init) { - struct aml_dvb *dvb = fe->man->dvb; - int reg = 1; - int ret; - int id; - - spin_lock_init(&fe->slock); - - fe->sys = SYS_UNDEFINED; - - pr_dbg("fe: %p\n", fe); - - for (id = 0; id < FE_DEV_COUNT; id++) { - struct aml_fe *prev_fe = &fe_man.fe[id]; - - if (prev_fe == fe) - continue; - if (prev_fe->init && (prev_fe->dev_id == fe->dev_id)) { - reg = 0; - break; - } - } - - fe->fe = &fe_man.dev[fe->dev_id]; - if (reg) { - fe->fe->demodulator_priv = fe; - fe->fe->ops.set_property = aml_fe_set_property; - fe->fe->ops.get_property = aml_fe_set_property; - } - - if (fe->tuner) - fe->tuner->fe = fe; - if (fe->atv_demod) - fe->atv_demod->fe = fe; - if (fe->dtv_demod) - fe->dtv_demod->fe = fe; - - ret = dvb_register_frontend(&dvb->dvb_adapter, fe->fe); - if (ret) { - pr_error("register fe%d failed\n", fe->dev_id); - return; - } - } -} - -static void fe_property_name(struct aml_fe *fe, const char *name, - char *buf) -{ - if (name) - sprintf(buf, "fe%d_%s", fe->dev_id, name); - else - sprintf(buf, "fe%d", fe->dev_id); -} - -static int fe_of_property_u32(struct aml_fe *fe, - const char *name, u32 *v) -{ - struct platform_device *pdev = fe->man->pdev; - char buf[128]; - int r; - - fe_property_name(fe, name, buf); - r = of_property_read_u32(pdev->dev.of_node, buf, v); - if (r) - pr_error("cannot find resource \"%s\"\n", buf); - - return r; -} - -static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) -{ - u32 value; - int ret; - - fe->sys = SYS_UNDEFINED; - fe->man = man; - fe->dev_id = id; - fe->init = 0; - fe->ts = AM_TS_SRC_TS0; - fe->work_running = 0; - fe->work_q = NULL; - fe->tuner = NULL; - fe->atv_demod = NULL; - fe->dtv_demod = NULL; - fe->do_work = NULL; - fe->get_property = NULL; - fe->set_property = NULL; - - init_waitqueue_head(&fe->wait_q); - spin_lock_init(&fe->slock); - - ret = fe_of_property_u32(fe, "tuner", &value); - if (!ret) { - id = value; - - if ((id < 0) || (id >= FE_DEV_COUNT) || !fe_man.tuner[id].drv) { - pr_error("invalid tuner device id %d\n", id); - return -1; - } - - fe->tuner = &fe_man.tuner[id]; - fe_man.tuner[id].fe = fe; - } - - ret = fe_of_property_u32(fe, "atv_demod", &value); - if (!ret) { - id = value; - - if ((id < 0) || - (id >= FE_DEV_COUNT) || - !fe_man.atv_demod[id].drv) { - pr_error("invalid ATV demod device id %d\n", id); - return -1; - } - - fe->atv_demod = &fe_man.atv_demod[id]; - fe_man.atv_demod[id].fe = fe; - } - - ret = fe_of_property_u32(fe, "dtv_demod", &value); - if (!ret) { - id = value; - - if ((id < 0) || - (id >= FE_DEV_COUNT) || - !fe_man.dtv_demod[id].drv) { - pr_error("invalid DTV demod device id %d\n", id); - return -1; - } - - fe->dtv_demod = &fe_man.dtv_demod[id]; - fe_man.dtv_demod[id].fe = fe; - } - - ret = fe_of_property_u32(fe, "ts", &value); - if (!ret) { - enum aml_ts_source_t ts = AM_TS_SRC_TS0; - - switch (value) { - case 0: - ts = AM_TS_SRC_TS0; - break; - case 1: - ts = AM_TS_SRC_TS1; - break; - case 2: - ts = AM_TS_SRC_TS2; - break; - default: - break; - } - - fe->ts = ts; - } - - ret = fe_of_property_u32(fe, "dev", &value); - if (!ret) { - id = value; - - if ((id >= 0) && (id < FE_DEV_COUNT)) - fe->dev_id = id; - else - fe->dev_id = 0; - } - - aml_fe_man_run(fe); - - return 0; -} - -static int aml_fe_man_release(struct aml_fe *fe) -{ - if (fe->init) { - aml_fe_cancel_work(fe); - - if (fe->work_q) - destroy_workqueue(fe->work_q); - - aml_fe_set_sys(fe->fe, SYS_UNDEFINED); - dvb_unregister_frontend(fe->fe); - dvb_frontend_detach(fe->fe); - - fe->tuner = NULL; - fe->atv_demod = NULL; - fe->dtv_demod = NULL; - fe->init = 0; - } - - return 0; -} - -void aml_fe_set_pdata(struct aml_fe_dev *dev, void *pdata) -{ - dev->priv_data = pdata; -} -EXPORT_SYMBOL(aml_fe_set_pdata); - -void *aml_fe_get_pdata(struct aml_fe_dev *dev) -{ - return dev->priv_data; -} -EXPORT_SYMBOL(aml_fe_get_pdata); - -static void aml_fe_do_work(struct work_struct *work) -{ - struct aml_fe *fe; - - fe = container_of(work, struct aml_fe, work); - - if (fe->do_work) - fe->do_work(fe); - - fe->work_running = 0; -} - -void aml_fe_schedule_work(struct aml_fe *fe, void(*func)(struct aml_fe *fe)) -{ - if (fe->work_running) - cancel_work_sync(&fe->work); - - fe->work_running = 1; - fe->do_work = func; - - if (!fe->work_q) { - fe->work_q = create_singlethread_workqueue("amlfe"); - INIT_WORK(&fe->work, aml_fe_do_work); - } - - queue_work(fe->work_q, &fe->work); -} -EXPORT_SYMBOL(aml_fe_schedule_work); - -void aml_fe_cancel_work(struct aml_fe *fe) -{ - if (fe->work_running) { - fe->work_running = 0; - cancel_work_sync(&fe->work); - } - - fe->do_work = NULL; -} -EXPORT_SYMBOL(aml_fe_cancel_work); - - -int aml_fe_work_cancelled(struct aml_fe *fe) -{ - return fe->work_running ? 0 : 1; -} -EXPORT_SYMBOL(aml_fe_work_cancelled); - -int aml_fe_work_sleep(struct aml_fe *fe, unsigned long delay) -{ - wait_event_interruptible_timeout(fe->wait_q, !fe->work_running, delay); - return aml_fe_work_cancelled(fe); -} -EXPORT_SYMBOL(aml_fe_work_sleep); - -static ssize_t tuner_name_show(struct class *cls, struct class_attribute *attr, - char *buf) -{ - size_t len = 0; - struct aml_fe_drv *drv; - unsigned long flags; - - struct aml_fe_drv **list = aml_get_fe_drv_list(AM_DEV_TUNER); - - spin_lock_irqsave(&lock, flags); - for (drv = *list; drv; drv = drv->next) - len += sprintf(buf + len, "%s\n", drv->name); - spin_unlock_irqrestore(&lock, flags); - return len; -} - -static ssize_t atv_demod_name_show(struct class *cls, - struct class_attribute *attr, char *buf) -{ - size_t len = 0; - struct aml_fe_drv *drv; - unsigned long flags; - - struct aml_fe_drv **list = aml_get_fe_drv_list(AM_DEV_ATV_DEMOD); - - spin_lock_irqsave(&lock, flags); - for (drv = *list; drv; drv = drv->next) - len += sprintf(buf + len, "%s\n", drv->name); - spin_unlock_irqrestore(&lock, flags); - return len; -} - -static ssize_t dtv_demod_name_show(struct class *cls, - struct class_attribute *attr, char *buf) -{ - size_t len = 0; - struct aml_fe_drv *drv; - unsigned long flags; - - struct aml_fe_drv **list = aml_get_fe_drv_list(AM_DEV_DTV_DEMOD); - - spin_lock_irqsave(&lock, flags); - for (drv = *list; drv; drv = drv->next) - len += sprintf(buf + len, "%s\n", drv->name); - spin_unlock_irqrestore(&lock, flags); - return len; -} - -static ssize_t setting_show(struct class *cls, struct class_attribute *attr, - char *buf) -{ - int r, total = 0; - int i; - struct aml_fe_man *fm = &fe_man; - - r = sprintf(buf, "tuner:\n"); - buf += r; - total += r; - for (i = 0; i < FE_DEV_COUNT; i++) { - struct aml_fe_dev *dev = &fm->tuner[i]; - - if (dev->drv) { - r = sprintf(buf, "\t%d: %s\n", i, dev->drv->name); - buf += r; - total += r; - } - } - - r = sprintf(buf, "atv_demod:\n"); - buf += r; - total += r; - for (i = 0; i < FE_DEV_COUNT; i++) { - struct aml_fe_dev *dev = &fm->atv_demod[i]; - - if (dev->drv) { - r = sprintf(buf, "\t%d: %s\n", i, dev->drv->name); - buf += r; - total += r; - } - } - - r = sprintf(buf, "dtv_demod:\n"); - buf += r; - total += r; - for (i = 0; i < FE_DEV_COUNT; i++) { - struct aml_fe_dev *dev = &fm->dtv_demod[i]; - - if (dev->drv) { - r = sprintf(buf, "\t%d: %s\n", i, dev->drv->name); - buf += r; - total += r; - } - } - - r = sprintf(buf, "frontend:\n"); - buf += r; - total += r; - for (i = 0; i < FE_DEV_COUNT; i++) { - struct aml_fe *fe = &fm->fe[i]; - - r = sprintf(buf, - "\t%d: %s device: %d ts: %d tuner: %s atv_demod: %s dtv_demod: %s\n", - i, fe->init ? "enabled" : "disabled", fe->dev_id, - fe->ts, fe->tuner ? fe->tuner->drv->name : "none", - fe->atv_demod ? fe->atv_demod->drv->name : "none", - fe->dtv_demod ? fe->dtv_demod->drv->name : "none"); - buf += r; - total += r; - } - - return total; -} - -static void reset_drv(int id, enum aml_fe_dev_type_t type, const char *name) -{ - struct aml_fe_man *fm = &fe_man; - struct aml_fe_drv **list; - struct aml_fe_drv **pdrv; - struct aml_fe_drv *drv; - struct aml_fe_drv *old; - - if ((id < 0) || (id >= FE_DEV_COUNT)) - return; - - if (fm->fe[id].init) { - pr_error("cannot reset driver when the device is inused\n"); - return; - } - - list = aml_get_fe_drv_list(type); - for (drv = *list; drv; drv = drv->next) - if (!strcmp(drv->name, name)) - break; - - switch (type) { - case AM_DEV_TUNER: - pdrv = &fm->tuner[id].drv; - break; - case AM_DEV_ATV_DEMOD: - pdrv = &fm->atv_demod[id].drv; - break; - case AM_DEV_DTV_DEMOD: - pdrv = &fm->dtv_demod[id].drv; - break; - default: - return; - } - - old = *pdrv; - if (old == drv) - return; - - if (old) { - old->ref--; - if (old->owner) - module_put(old->owner); - } - - if (drv) { - drv->ref++; - if (drv->owner) - try_module_get(drv->owner); - } - - *pdrv = drv; -} - -static ssize_t setting_store(struct class *class, struct class_attribute *attr, - const char *buf, size_t size) -{ - struct aml_fe_man *fm = &fe_man; - int id, val; - char dev_name[32]; - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - if (sscanf(buf, "tuner %i driver %s", &id, dev_name) == 2) { - reset_drv(id, AM_DEV_TUNER, dev_name); - } else if (sscanf(buf, "atv_demod %i driver %s", &id, dev_name) == 2) { - reset_drv(id, AM_DEV_ATV_DEMOD, dev_name); - } else if (sscanf(buf, "dtv_demod %i driver %s", &id, dev_name) == 2) { - reset_drv(id, AM_DEV_DTV_DEMOD, dev_name); - } else if (sscanf(buf, "frontend %i device %i", &id, &val) == 2) { - if ((id >= 0) && (id < FE_DEV_COUNT)) - fm->fe[id].dev_id = val; - } else if (sscanf(buf, "frontend %i ts %i", &id, &val) == 2) { - if ((id >= 0) && (id < FE_DEV_COUNT)) - fm->fe[id].ts = val; - } else if (sscanf(buf, "frontend %i tuner %i", &id, &val) == 2) { - if ((id >= 0) && (id < FE_DEV_COUNT) && (val >= 0) - && (val < FE_DEV_COUNT) && fm->tuner[val].drv) - fm->fe[id].tuner = &fm->tuner[val]; - } else if (sscanf(buf, "frontend %i atv_demod %i", &id, &val) == 2) { - if ((id >= 0) && (id < FE_DEV_COUNT) && (val >= 0) - && (val < FE_DEV_COUNT) && fm->atv_demod[val].drv) - fm->fe[id].atv_demod = &fm->atv_demod[val]; - } else if (sscanf(buf, "frontend %i dtv_demod %i", &id, &val) == 2) { - if ((id >= 0) && (id < FE_DEV_COUNT) && (val >= 0) - && (val < FE_DEV_COUNT) && fm->dtv_demod[val].drv) - fm->fe[id].dtv_demod = &fm->dtv_demod[val]; - } - - spin_unlock_irqrestore(&lock, flags); - - if (sscanf(buf, "enable %i", &id) == 1) { - if ((id >= 0) && (id < FE_DEV_COUNT)) - aml_fe_man_run(&fm->fe[id]); - } else if (sscanf(buf, "disable %i", &id) == 1) { - if ((id >= 0) && (id < FE_DEV_COUNT)) - aml_fe_man_release(&fm->fe[id]); - } else if (strstr(buf, "autoload")) { - for (id = 0; id < FE_DEV_COUNT; id++) { - aml_fe_dev_init(fm, AM_DEV_TUNER, - &fm->tuner[id], id); - aml_fe_dev_init(fm, AM_DEV_ATV_DEMOD, - &fm->atv_demod[id], id); - aml_fe_dev_init(fm, AM_DEV_DTV_DEMOD, - &fm->dtv_demod[id], id); - } - - for (id = 0; id < FE_DEV_COUNT; id++) - aml_fe_man_init(fm, &fm->fe[id], id); - } else if (strstr(buf, "disableall")) { - for (id = 0; id < FE_DEV_COUNT; id++) - aml_fe_man_release(&fm->fe[id]); - - for (id = 0; id < FE_DEV_COUNT; id++) { - aml_fe_dev_release(&fm->dtv_demod[id]); - aml_fe_dev_release(&fm->atv_demod[id]); - aml_fe_dev_release(&fm->tuner[id]); - } - } - - return size; -} - -static ssize_t aml_fe_show_suspended_flag(struct class *class, - struct class_attribute *attr, - char *buf) -{ - ssize_t ret = 0; - - ret = sprintf(buf, "%ld\n", aml_fe_suspended); - - return ret; -} - -static ssize_t aml_fe_store_suspended_flag(struct class *class, - struct class_attribute *attr, - const char *buf, size_t size) -{ - /*aml_fe_suspended = simple_strtol(buf, 0, 0); */ - int ret = kstrtol(buf, 0, &aml_fe_suspended); - - if (ret) - return ret; - return size; -} - -static struct class_attribute aml_fe_cls_attrs[] = { - __ATTR(tuner_name, - 0644, - tuner_name_show, NULL), - __ATTR(atv_demod_name, - 0644, - atv_demod_name_show, NULL), - __ATTR(dtv_demod_name, - 0644, - dtv_demod_name_show, NULL), - __ATTR(setting, - 0644, - setting_show, setting_store), - __ATTR(aml_fe_suspended_flag, - 0644, - aml_fe_show_suspended_flag, - aml_fe_store_suspended_flag), - __ATTR_NULL -}; - -static struct class aml_fe_class = { - .name = "amlfe", - .class_attrs = aml_fe_cls_attrs, -}; - -static int aml_fe_probe(struct platform_device *pdev) -{ - struct aml_dvb *dvb = aml_get_dvb_device(); - int i; - - fe_man.dvb = dvb; - fe_man.pdev = pdev; - - platform_set_drvdata(pdev, &fe_man); - - for (i = 0; i < FE_DEV_COUNT; i++) { - if (aml_fe_dev_init(&fe_man, - AM_DEV_TUNER, - &fe_man.tuner[i], i) < 0) - goto probe_end; - - if (aml_fe_dev_init(&fe_man, - AM_DEV_ATV_DEMOD, - &fe_man.atv_demod[i], i) < 0) - goto probe_end; - - if (aml_fe_dev_init(&fe_man, - AM_DEV_DTV_DEMOD, - &fe_man.dtv_demod[i], i) < 0) - goto probe_end; - } - - for (i = 0; i < FE_DEV_COUNT; i++) { - if (aml_fe_man_init(&fe_man, &fe_man.fe[i], i) < 0) - goto probe_end; - } - - probe_end: - - fe_man.pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - - if (class_register(&aml_fe_class) < 0) - pr_error("[aml_fe..] register class error\n"); - - pr_dbg("[aml_fe..] probe ok.\n"); - - return 0; -} - -static int aml_fe_remove(struct platform_device *pdev) -{ - struct aml_fe_man *fe_man = platform_get_drvdata(pdev); - int i; - - if (fe_man) { - platform_set_drvdata(pdev, NULL); - - for (i = 0; i < FE_DEV_COUNT; i++) - aml_fe_man_release(&fe_man->fe[i]); - for (i = 0; i < FE_DEV_COUNT; i++) { - aml_fe_dev_release(&fe_man->dtv_demod[i]); - aml_fe_dev_release(&fe_man->atv_demod[i]); - aml_fe_dev_release(&fe_man->tuner[i]); - } - - if (fe_man->pinctrl) - devm_pinctrl_put(fe_man->pinctrl); - } - - class_unregister(&aml_fe_class); - - return 0; -} - -static int aml_fe_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - - for (i = 0; i < FE_DEV_COUNT; i++) { - struct aml_fe *fe = &fe_man.fe[i]; - - if (fe->tuner && fe->tuner->drv->suspend) - fe->tuner->drv->suspend(fe->tuner); - - if (fe->atv_demod && fe->atv_demod->drv->suspend) - fe->atv_demod->drv->suspend(fe->atv_demod); - - if (fe->dtv_demod && fe->dtv_demod->drv->suspend) - fe->dtv_demod->drv->suspend(fe->dtv_demod); - } - - aml_fe_suspended = 1; - - return 0; -} - -static int aml_fe_resume(struct platform_device *dev) -{ - int i; - - aml_fe_suspended = 0; - - for (i = 0; i < FE_DEV_COUNT; i++) { - struct aml_fe *fe = &fe_man.fe[i]; - - if (fe->tuner && fe->tuner->drv->resume) - fe->tuner->drv->resume(fe->tuner); - - if (fe->atv_demod && fe->atv_demod->drv->resume) - fe->atv_demod->drv->resume(fe->atv_demod); - - if (fe->dtv_demod && fe->dtv_demod->drv->resume) - fe->dtv_demod->drv->resume(fe->dtv_demod); - } - - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id aml_fe_dt_match[] = { - { - .compatible = "amlogic, dvbfe", - }, - {}, -}; -#endif /*CONFIG_OF */ - -static struct platform_driver aml_fe_driver = { - .probe = aml_fe_probe, - .remove = aml_fe_remove, - .suspend = aml_fe_suspend, - .resume = aml_fe_resume, - .driver = { - .name = "amlogic-dvb-fe", - .owner = THIS_MODULE, -#ifdef CONFIG_OF - .of_match_table = aml_fe_dt_match, -#endif - } -}; - -static int __init aml_fe_init(void) -{ - return platform_driver_register(&aml_fe_driver); -} - -static void __exit aml_fe_exit(void) -{ - platform_driver_unregister(&aml_fe_driver); -} - -module_init(aml_fe_init); -module_exit(aml_fe_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("amlogic frontend driver"); -MODULE_AUTHOR("L+#= +0=1"); - diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h deleted file mode 100644 index c975b4ce8941..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _AML_FE_H_ -#define _AML_FE_H_ - - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "../parser/hw_demux/aml_dvb.h" - -enum aml_tuner_type_t { - AM_TUNER_NONE = 0, - AM_TUNER_SI2176 = 1, - AM_TUNER_SI2196 = 2, - AM_TUNER_FQ1216 = 3, - AM_TUNER_HTM = 4, - AM_TUNER_CTC703 = 5, - AM_TUNER_SI2177 = 6, - AM_TUNER_R840 = 7, - AM_TUNER_SI2157 = 8, - AM_TUNER_SI2151 = 9, - AM_TUNER_MXL661 = 10, - AM_TUNER_MXL608 = 11, - AM_TUNER_SI2159 = 12, - AM_TUNER_R842 = 13, -}; - -enum aml_atv_demod_type_t { - AM_ATV_DEMOD_SI2176 = 1, - AM_ATV_DEMOD_SI2196 = 2, - AM_ATV_DEMOD_FQ1216 = 3, - AM_ATV_DEMOD_HTM = 4, - AM_ATV_DEMOD_CTC703 = 5, - AM_ATV_DEMOD_SI2177 = 6, - AM_ATV_DEMOD_AML = 7, - AM_ATV_DEMOD_R840 = 8 -}; - -enum aml_dtv_demod_type_t { - AM_DTV_DEMOD_M1 = 0, - AM_DTV_DEMOD_SI2176 = 1, - AM_DTV_DEMOD_MXL101 = 2, - AM_DTV_DEMOD_SI2196 = 3, - AM_DTV_DEMOD_AVL6211 = 4, - AM_DTV_DEMOD_SI2168 = 5, - AM_DTV_DEMOD_ITE9133 = 6, - AM_DTV_DEMOD_ITE9173 = 7, - AM_DTV_DEMOD_DIB8096 = 8, - AM_DTV_DEMOD_ATBM8869 = 9, - AM_DTV_DEMOD_MXL241 = 10, - AM_DTV_DEMOD_AVL68xx = 11, - AM_DTV_DEMOD_MXL683 = 12, - AM_DTV_DEMOD_ATBM8881 = 13 -}; - -enum aml_fe_dev_type_t { - AM_DEV_TUNER, - AM_DEV_ATV_DEMOD, - AM_DEV_DTV_DEMOD -}; - -struct aml_fe_dev; -struct aml_fe_man; -struct aml_fe; - -struct aml_fe_drv { - struct module *owner; - struct aml_fe_drv *next; - enum aml_tuner_type_t id; - char *name; - int (*init)(struct aml_fe_dev *dev); - int (*release)(struct aml_fe_dev *dev); - int (*resume)(struct aml_fe_dev *dev); - int (*suspend)(struct aml_fe_dev *dev); - int (*support)(struct aml_fe_dev *dev, enum fe_delivery_system sys); - int (*get_ops)(struct aml_fe_dev *dev, enum fe_delivery_system sys, - struct dvb_frontend_ops *ops); - int (*init_sys)(struct aml_fe_dev *dev, enum fe_delivery_system sys); - int (*release_sys)(struct aml_fe_dev *dev, enum fe_delivery_system sys); - int (*start_blind_scan)(struct aml_fe_dev *dev); - int (*stop_blind_scan)(struct aml_fe_dev *dev); - int ref; -}; - -struct aml_fe_dev { - /*point to parent aml_fe */ - enum aml_fe_dev_type_t type; - int dev_id; - struct aml_fe *fe; - struct aml_fe_man *man; - struct aml_fe_drv *drv; - void *priv_data; - /*i2c and reset gpio for all demod and tune*/ - int i2c_adap_id; - int i2c_addr; - struct i2c_adapter *i2c_adap; - int reset_gpio; - int reset_value; -}; - -struct aml_fe { - struct dvb_frontend *fe; - struct aml_fe_man *man; -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend es; -#endif /*CONFIG_HAS_EARLYSUSPEND */ - spinlock_t slock; - int init; - int dev_id; - enum fe_delivery_system sys; - int sub_sys; -/*used to identify T T2 OR C-A C-B C-C,S S2,ISDBT ISDBS ISDBC*/ - enum aml_ts_source_t ts; - struct aml_fe_dev *tuner; - struct aml_fe_dev *atv_demod; - struct aml_fe_dev *dtv_demod; - struct workqueue_struct *work_q; - wait_queue_head_t wait_q; - struct work_struct work; - int work_running; - struct dvbsx_blindscanpara blind_scan_para; - - /*Driver's work function.*/ - void (*do_work)(struct aml_fe *fe); - /*Driver's property function.*/ - int (*get_property)(struct dvb_frontend *fe, struct dtv_property *tvp); - int (*set_property)(struct dvb_frontend *fe, struct dtv_property *tvp); -}; - -struct aml_fe_man { - struct aml_dvb *dvb; - struct aml_fe fe[FE_DEV_COUNT]; - struct aml_fe_dev tuner[FE_DEV_COUNT]; - struct aml_fe_dev atv_demod[FE_DEV_COUNT]; - struct aml_fe_dev dtv_demod[FE_DEV_COUNT]; - struct dvb_frontend dev[FE_DEV_COUNT]; - struct pinctrl *pinctrl; - struct platform_device *pdev; -}; - -extern int aml_register_fe_drv(enum aml_fe_dev_type_t type, - struct aml_fe_drv *drv); -extern int aml_unregister_fe_drv(enum aml_fe_dev_type_t type, - struct aml_fe_drv *drv); - -extern int aml_fe_of_property_string(struct aml_fe_dev *dev, - const char *name, const char **str); -extern int aml_fe_of_property_u32(struct aml_fe_dev *dev, - const char *name, u32 *v); - -extern void aml_fe_set_pdata(struct aml_fe_dev *dev, void *pdata); -extern void *aml_fe_get_pdata(struct aml_fe_dev *dev); - -extern void aml_fe_schedule_work(struct aml_fe *fe, - void (*func)(struct aml_fe *fe)); -extern void aml_fe_cancel_work(struct aml_fe *fe); -extern int aml_fe_work_cancelled(struct aml_fe *fe); -extern int aml_fe_work_sleep(struct aml_fe *fe, unsigned long delay); - -#endif /*_AML_FE_H_*/ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_frontend.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_frontend.c deleted file mode 100644 index 964bc42c224e..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_frontend.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * Silicon labs atvdemod Device Driver - * - * Author: dezhi.kong - * - * - * Copyright (C) 2014 Amlogic Inc. - * - * 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. - */ - -/* Standard Liniux Headers */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Amlogic Headers */ - -/* Local Headers */ -#include "atvdemod_func.h" -#include "../aml_fe.h" -#include -#include - -#define ATVDEMOD_DEVICE_NAME "amlatvdemod" -#define ATVDEMOD_DRIVER_NAME "amlatvdemod" -#define ATVDEMOD_MODULE_NAME "amlatvdemod" -#define ATVDEMOD_CLASS_NAME "amlatvdemod" - -struct amlatvdemod_device_s *amlatvdemod_devp; -#define AMLATVDEMOD_VER "Ref.2015/09/01a" - -static int afc_wave_cnt; -static int last_frq, last_std; - -unsigned int reg_23cf = 0x88188832; /*IIR filter*/ -module_param(reg_23cf, uint, 0664); -MODULE_PARM_DESC(reg_23cf, "\n reg_23cf\n"); - -unsigned int atvdemod_scan_mode; /*IIR filter*/ -module_param(atvdemod_scan_mode, uint, 0664); -MODULE_PARM_DESC(atvdemod_scan_mode, "\n atvdemod_scan_mode\n"); - -/* used for resume */ -#define ATVDEMOD_STATE_IDEL 0 -#define ATVDEMOD_STATE_WORK 1 -#define ATVDEMOD_STATE_SLEEP 2 -static int atvdemod_state = ATVDEMOD_STATE_IDEL; - -int is_atvdemod_scan_mode(void) -{ - return atvdemod_scan_mode; -} -EXPORT_SYMBOL(is_atvdemod_scan_mode); - -static int aml_atvdemod_enter_mode(struct aml_fe *fe, int mode); -/*static void sound_store(const char *buff, v4l2_std_id *std);*/ -static ssize_t aml_atvdemod_store(struct class *cls, - struct class_attribute *attr, const char *buf, - size_t count) -{ - int n = 0; - unsigned int ret = 0; - char *buf_orig, *ps, *token; - char *parm[4]; - unsigned int data_snr[128]; - unsigned int data_snr_avg; - int data_afc, block_addr, block_reg, block_val = 0; - int i, val = 0; - unsigned long tmp = 0; - struct aml_fe *atvdemod_fe = NULL; - - buf_orig = kstrdup(buf, GFP_KERNEL); - ps = buf_orig; - block_addr = 0; - block_reg = 0; - while (1) { - token = strsep(&ps, "\n"); - if (token == NULL) - break; - if (*token == '\0') - continue; - parm[n++] = token; - } - if (!strncmp(parm[0], "init", strlen("init"))) { - ret = aml_atvdemod_enter_mode(atvdemod_fe, 0); - if (ret) - pr_info("[tuner..] atv_restart error.\n"); - } else if (!strcmp(parm[0], "tune")) { - /* val = simple_strtol(parm[1], NULL, 10); */ - } else if (!strcmp(parm[0], "set")) { - if (!strncmp(parm[1], "avout_gain", strlen("avout_gain"))) { - if (kstrtoul(buf+strlen("avout_offset")+1, 10, - &tmp) == 0) - val = tmp; - atv_dmd_wr_byte(0x0c, 0x01, val&0xff); - } else if (!strncmp(parm[1], "avout_offset", - strlen("avout_offset"))) { - if (kstrtoul(buf+strlen("avout_offset")+1, 10, - &tmp) == 0) - val = tmp; - atv_dmd_wr_byte(0x0c, 0x04, val&0xff); - } else if (!strncmp(parm[1], "atv_gain", strlen("atv_gain"))) { - if (kstrtoul(buf+strlen("atv_gain")+1, 10, &tmp) == 0) - val = tmp; - atv_dmd_wr_byte(0x19, 0x01, val&0xff); - } else if (!strncmp(parm[1], "atv_offset", - strlen("atv_offset"))) { - if (kstrtoul(buf+strlen("atv_offset")+1, 10, - &tmp) == 0) - val = tmp; - atv_dmd_wr_byte(0x19, 0x04, val&0xff); - } - } else if (!strcmp(parm[0], "get")) { - if (!strncmp(parm[1], "avout_gain", strlen("avout_gain"))) { - val = atv_dmd_rd_byte(0x0c, 0x01); - pr_dbg("avout_gain:0x%x\n", val); - } else if (!strncmp(parm[1], "avout_offset", - strlen("avout_offset"))) { - val = atv_dmd_rd_byte(0x0c, 0x04); - pr_dbg("avout_offset:0x%x\n", val); - } else if (!strncmp(parm[1], "atv_gain", strlen("atv_gain"))) { - val = atv_dmd_rd_byte(0x19, 0x01); - pr_dbg("atv_gain:0x%x\n", val); - } else if (!strncmp(parm[1], "atv_offset", - strlen("atv_offset"))) { - val = atv_dmd_rd_byte(0x19, 0x04); - pr_dbg("atv_offset:0x%x\n", val); - } - } else if (!strncmp(parm[0], "snr_hist", strlen("snr_hist"))) { - data_snr_avg = 0; - for (i = 0; i < 128; i++) { - data_snr[i] = - (atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8); - usleep_range(50*1000, 50*1000+100); - data_snr_avg += data_snr[i]; - } - data_snr_avg = data_snr_avg / 128; - pr_dbg("**********snr_hist_128avg:0x%x(%d)*********\n", - data_snr_avg, data_snr_avg); - } else if (!strncmp(parm[0], "afc_info", strlen("afc_info"))) { - data_afc = retrieve_vpll_carrier_afc(); - pr_dbg("[amlatvdemod..]afc %d Khz.\n", data_afc); - } else if (!strncmp(parm[0], "ver_info", strlen("ver_info"))) { - pr_dbg("[amlatvdemod..]aml_atvdemod_ver %s.\n", - AMLATVDEMOD_VER); - } else if (!strncmp(parm[0], "audio_autodet", - strlen("audio_autodet"))) { - aml_audiomode_autodet(NULL); - } else if (!strncmp(parm[0], "overmodule_det", - strlen("overmodule_det"))) { - /* unsigned long over_threshold, */ - /* int det_mode = auto_det_mode; */ - aml_atvdemod_overmodule_det(); - } else if (!strncmp(parm[0], "audio_gain_set", - strlen("audio_gain_set"))) { - if (kstrtoul(buf+strlen("audio_gain_set")+1, 16, &tmp) == 0) - val = tmp; - aml_audio_valume_gain_set(val); - pr_dbg("audio_gain_set : %d\n", val); - } else if (!strncmp(parm[0], "audio_gain_get", - strlen("audio_gain_get"))) { - val = aml_audio_valume_gain_get(); - pr_dbg("audio_gain_get : %d\n", val); - } else if (!strncmp(parm[0], "fix_pwm_adj", strlen("fix_pwm_adj"))) { - if (kstrtoul(parm[1], 10, &tmp) == 0) { - val = tmp; - aml_fix_PWM_adjust(val); - } - } else if (!strncmp(parm[0], "rs", strlen("rs"))) { - if (kstrtoul(parm[1], 16, &tmp) == 0) - block_addr = tmp; - if (kstrtoul(parm[2], 16, &tmp) == 0) - block_reg = tmp; - if (block_addr < APB_BLOCK_ADDR_TOP) - block_val = atv_dmd_rd_long(block_addr, block_reg); - pr_info("rs block_addr:0x%x,block_reg:0x%x,block_val:0x%x\n", - block_addr, block_reg, block_val); - } else if (!strncmp(parm[0], "ws", strlen("ws"))) { - if (kstrtoul(parm[1], 16, &tmp) == 0) - block_addr = tmp; - if (kstrtoul(parm[2], 16, &tmp) == 0) - block_reg = tmp; - if (kstrtoul(parm[3], 16, &tmp) == 0) - block_val = tmp; - if (block_addr < APB_BLOCK_ADDR_TOP) - atv_dmd_wr_long(block_addr, block_reg, block_val); - pr_info("ws block_addr:0x%x,block_reg:0x%x,block_val:0x%x\n", - block_addr, block_reg, block_val); - block_val = atv_dmd_rd_long(block_addr, block_reg); - pr_info("readback_val:0x%x\n", block_val); - } else if (!strncmp(parm[0], "pin_mux", strlen("pin_mux"))) { - amlatvdemod_devp->pin = - devm_pinctrl_get_select(amlatvdemod_devp->dev, - amlatvdemod_devp->pin_name); - pr_dbg("atvdemod agc pinmux name:%s\n", - amlatvdemod_devp->pin_name); - } else if (!strncmp(parm[0], "snr_cur", strlen("snr_cur"))) { - data_snr_avg = aml_atvdemod_get_snr_ex(); - pr_dbg("**********snr_cur:%d*********\n", data_snr_avg); - } else - pr_dbg("invalid command\n"); - kfree(buf_orig); - return count; -} - -static ssize_t aml_atvdemod_show(struct class *cls, - struct class_attribute *attr, char *buff) -{ - pr_dbg("\n usage:\n"); - pr_dbg("[get soft version] echo ver_info > /sys/class/amlatvdemod/atvdemod_debug\n"); - pr_dbg("[get afc value] echo afc_info > /sys/class/amlatvdemod/atvdemod_debug\n"); - pr_dbg("[reinit atvdemod] echo init > /sys/class/amlatvdemod/atvdemod_debug\n"); - pr_dbg("[get av-out-gain/av-out-offset/atv-gain/atv-offset]:\n" - "echo get av_gain/av_offset/atv_gain/atv_offset > /sys/class/amlatvdemod/atvdemod_debug\n"); - pr_dbg("[set av-out-gain/av-out-offset/atv-gain/atv-offset]:\n" - "echo set av_gain/av_offset/atv_gain/atv_offset val(0~255) > /sys/class/amlatvdemod/atvdemod_debug\n"); - return 0; -} -static CLASS_ATTR(atvdemod_debug, 0644, aml_atvdemod_show, aml_atvdemod_store); - -void aml_atvdemod_set_frequency(unsigned int freq) -{ -} - -/*static void aml_atvdemod_set_std(void);*/ - -/*try audmode B,CH,I,DK,return the sound level*/ -/*static unsigned char set_video_audio_mode(unsigned char color, - *unsigned char audmode); - */ -/*static void aml_atvdemod_get_status(struct dvb_frontend *fe, - *void *stat); - */ -/*static void aaaml_atvdemod_get_pll_status(struct dvb_frontend *fe, - *void *stat); - */ - -static int aml_atvdemod_fe_init(struct aml_fe_dev *dev) -{ - - int error_code = 0; - - if (!dev) { - pr_dbg("[amlatvdemod..]%s: null pointer error.\n", __func__); - return -1; - } - return error_code; -} - -static int aml_atvdemod_enter_mode(struct aml_fe *fe, int mode) -{ - int err_code; - - if (amlatvdemod_devp->pin_name != NULL) - amlatvdemod_devp->pin = - devm_pinctrl_get_select(amlatvdemod_devp->dev, - amlatvdemod_devp->pin_name); - /* printk("\n%s: set atvdemod pll...\n",__func__); */ - adc_set_pll_cntl(1, 0x1); - atvdemod_clk_init(); - err_code = atvdemod_init(); - if (err_code) { - pr_dbg("[amlatvdemod..]%s init atvdemod error.\n", __func__); - return err_code; - } - - set_aft_thread_enable(1); - atvdemod_state = ATVDEMOD_STATE_WORK; - return 0; -} - -static int aml_atvdemod_leave_mode(struct aml_fe *fe, int mode) -{ - set_aft_thread_enable(0); - atvdemod_uninit(); - if (amlatvdemod_devp->pin != NULL) { - devm_pinctrl_put(amlatvdemod_devp->pin); - amlatvdemod_devp->pin = NULL; - } - /* reset adc pll flag */ - /* printk("\n%s: init atvdemod flag...\n",__func__); */ - adc_set_pll_cntl(0, 0x1); - atvdemod_state = ATVDEMOD_STATE_IDEL; - return 0; -} - -static int aml_atvdemod_suspend(struct aml_fe_dev *dev) -{ - pr_info("%s\n", __func__); - if (atvdemod_state != ATVDEMOD_STATE_IDEL) { - aml_atvdemod_leave_mode(NULL, 0); - atvdemod_state = ATVDEMOD_STATE_SLEEP; - } - return 0; -} - -static int aml_atvdemod_resume(struct aml_fe_dev *dev) -{ - pr_info("%s\n", __func__); - if (atvdemod_state == ATVDEMOD_STATE_SLEEP) - aml_atvdemod_enter_mode(NULL, 0); - return 0; -} - -/* - *static int aml_atvdemod_get_afc(struct dvb_frontend *fe,int *afc) - *{ - * return 0; - *} - */ - -/*ret:5~100;the val is bigger,the signal is better*/ -int aml_atvdemod_get_snr(struct dvb_frontend *fe) -{ -#if 1 - return get_atvdemod_snr_val(); -#else - unsigned int snr_val; - int ret; - - snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; - /* snr_val:900000~0xffffff,ret:5~15 */ - if (snr_val > 900000) - ret = 15 - (snr_val - 900000)*10/(0xffffff - 900000); - /* snr_val:158000~900000,ret:15~30 */ - else if (snr_val > 158000) - ret = 30 - (snr_val - 158000)*15/(900000 - 158000); - /* snr_val:31600~158000,ret:30~50 */ - else if (snr_val > 31600) - ret = 50 - (snr_val - 31600)*20/(158000 - 31600); - /* snr_val:316~31600,ret:50~80 */ - else if (snr_val > 316) - ret = 80 - (snr_val - 316)*30/(31600 - 316); - /* snr_val:0~316,ret:80~100 */ - else - ret = 100 - (316 - snr_val)*20/316; - return ret; -#endif -} -EXPORT_SYMBOL(aml_atvdemod_get_snr); - -int aml_atvdemod_get_snr_ex(void) -{ -#if 1 - return get_atvdemod_snr_val(); -#else - unsigned int snr_val; - int ret; - - snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; - /* snr_val:900000~0xffffff,ret:5~15 */ - if (snr_val > 900000) - ret = 15 - (snr_val - 900000)*10/(0xffffff - 900000); - /* snr_val:158000~900000,ret:15~30 */ - else if (snr_val > 158000) - ret = 30 - (snr_val - 158000)*15/(900000 - 158000); - /* snr_val:31600~158000,ret:30~50 */ - else if (snr_val > 31600) - ret = 50 - (snr_val - 31600)*20/(158000 - 31600); - /* snr_val:316~31600,ret:50~80 */ - else if (snr_val > 316) - ret = 80 - (snr_val - 316)*30/(31600 - 316); - /* snr_val:0~316,ret:80~100 */ - else - ret = 100 - (316 - snr_val)*20/316; - return ret; -#endif -} -EXPORT_SYMBOL(aml_atvdemod_get_snr_ex); - -/*tuner lock status & demod lock status should be same in silicon tuner*/ -static int aml_atvdemod_get_status(struct dvb_frontend *fe, void *stat) -{ - int video_lock; - fe_status_t *status = (fe_status_t *) stat; - - retrieve_video_lock(&video_lock); - if ((video_lock & 0x1) == 0) { - /* *status = FE_HAS_LOCK;*/ - *status = FE_TIMEDOUT; - pr_info("video lock:locked\n"); - } else { - pr_info("video lock:unlocked\n"); - *status = FE_TIMEDOUT; - /* *status = FE_HAS_LOCK;*/ - } - return 0; -} - -/*tuner lock status & demod lock status should be same in silicon tuner*/ -/* force return lock, for atvdemo status not sure */ -static void aml_atvdemod_get_pll_status(struct dvb_frontend *fe, void *stat) -{ - int vpll_lock; - fe_status_t *status = (fe_status_t *) stat; - - retrieve_vpll_carrier_lock(&vpll_lock); - if ((vpll_lock&0x1) == 0) { - *status = FE_HAS_LOCK; - pr_info("visual carrier lock:locked\n"); - } else { - pr_info("visual carrier lock:unlocked\n"); - *status = FE_TIMEDOUT; - /* *status = FE_HAS_LOCK;*/ - } -} - -static int aml_atvdemod_get_atv_status(struct dvb_frontend *fe, - struct atv_status_s *atv_status) -{ - int vpll_lock = 0, line_lock = 0; - int try_std = 1; - int loop_cnt = 5; - int cnt = 10; - int try_std_cnt = 0; - static int last_report_freq; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - - while (fe && atv_status && loop_cnt--) { - atv_status->afc = retrieve_vpll_carrier_afc(); - retrieve_vpll_carrier_lock(&vpll_lock); - line_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f)&0x10; - if ((vpll_lock&0x1) == 0 || line_lock == 0) { - atv_status->atv_lock = 1; - try_std_cnt = 2; - while (try_std_cnt--) { - atv_status->afc = retrieve_vpll_carrier_afc(); - if (atv_status->afc > 1500 - && atvdemod_scan_mode) { - if ((c->analog.std & 0xff000000) - != V4L2_COLOR_STD_PAL) { - c->analog.std = - V4L2_COLOR_STD_PAL - | V4L2_STD_PAL_BG; - c->frequency += 1; - fe->ops.set_frontend(fe); - msleep(20); - } else { - c->analog.std = - V4L2_COLOR_STD_NTSC - | V4L2_STD_NTSC_M; - c->frequency += 1; - fe->ops.set_frontend(fe); - usleep_range(20*1000, - 20*1000+100); - } - atv_status->afc = - retrieve_vpll_carrier_afc(); - - cnt = 4; - while (cnt--) { - if (atv_status->afc < 1500) - break; - atv_status->afc = - retrieve_vpll_carrier_afc(); - usleep_range(5*1000, 5*1000+100); - } - if (atv_status->afc < 1500) - break; - } - } - - if (atv_status->afc > 4000 && !atvdemod_scan_mode) - atv_status->atv_lock = 0; - - if (last_report_freq != c->frequency) - last_report_freq = c->frequency; - - if (atvdemod_scan_mode) - pr_err("%s,lock freq:%d, afc:%d\n", __func__, - c->frequency, atv_status->afc); - break; - - } else if (try_std%3 == 0 && atvdemod_scan_mode) { - if ((c->analog.std & 0xff000000) - != V4L2_COLOR_STD_PAL) { - c->analog.std = - V4L2_COLOR_STD_PAL | V4L2_STD_PAL_DK; - } - if (abs(c->frequency - last_report_freq) > 1000000) { - c->frequency -= 500000; - pr_err("@@@ %s freq:%d unlock,try back 0.5M\n", - __func__, c->frequency); - } else - c->frequency += 1; - fe->ops.set_frontend(fe); - usleep_range(10*1000, 10*1000+100); - } - if (atvdemod_scan_mode) - pr_err("@@@ %s freq:%d unlock, read lock again\n", - __func__, c->frequency); - if (atvdemod_scan_mode == 0) - usleep_range(10*1000, 10*1000+100); - else - usleep_range(1000, 1200); - - atv_status->atv_lock = 0; - try_std++; - } - if (atvdemod_scan_mode == 0) { - if (abs(atv_status->afc) < 20) - afc_wave_cnt = 0; - if (500*1000 > abs(last_frq - c->frequency) - && 20 < abs(atv_status->afc) - && 200 > abs(atv_status->afc)) { - afc_wave_cnt++; - pr_err("%s play mode,afc_wave_cnt:%d\n", - __func__, afc_wave_cnt); - if (afc_wave_cnt < 20) { - atv_status->afc = 0; - pr_err("%s, afc is wave,ignore\n", __func__); - } - } - } - return 0; -} - -void aml_atvdemod_set_params(struct dvb_frontend *fe, - struct analog_parameters *p) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - - if (fe->ops.info.type == FE_ANALOG) { - if ((p->std != amlatvdemod_devp->parm.std) || - (p->tuner_id == AM_TUNER_R840) || - (p->tuner_id == AM_TUNER_SI2151) || - (p->tuner_id == AM_TUNER_MXL661)) { - amlatvdemod_devp->parm.std = p->std; - amlatvdemod_devp->parm.if_freq = p->if_freq; - amlatvdemod_devp->parm.if_inv = p->if_inv; - amlatvdemod_devp->parm.tuner_id = p->tuner_id; - /* open AGC if needed */ - if (amlatvdemod_devp->pin != NULL) - devm_pinctrl_put(amlatvdemod_devp->pin); - if (amlatvdemod_devp->pin_name) - amlatvdemod_devp->pin = - devm_pinctrl_get_select(amlatvdemod_devp->dev, - amlatvdemod_devp->pin_name); - atv_dmd_set_std(); - last_frq = c->frequency; - last_std = c->analog.std; - pr_info("[amlatvdemod..]%s set std color %s, audio type %s.\n", - __func__, - v4l2_std_to_str(0xff000000&amlatvdemod_devp->parm.std), - v4l2_std_to_str(0xffffff&amlatvdemod_devp->parm.std)); - pr_info("[amlatvdemod..]%s set if_freq 0x%x, if_inv 0x%x.\n", - __func__, amlatvdemod_devp->parm.if_freq, - amlatvdemod_devp->parm.if_inv); - } - } -} -static int aml_atvdemod_get_afc(struct dvb_frontend *fe, s32 *afc) -{ - *afc = retrieve_vpll_carrier_afc(); - pr_info("[amlatvdemod..]%s afc %d.\n", __func__, *afc); - return 0; -} - -static int aml_atvdemod_get_ops(struct aml_fe_dev *dev, int mode, void *ops) -{ - struct analog_demod_ops *aml_analog_ops = - (struct analog_demod_ops *)ops; - if (!ops) { - pr_dbg("[amlatvdemod..]%s null pointer error.\n", __func__); - return -1; - } - aml_analog_ops->get_afc = aml_atvdemod_get_afc; - aml_analog_ops->get_snr = aml_atvdemod_get_snr; - aml_analog_ops->get_status = aml_atvdemod_get_status; - aml_analog_ops->set_params = aml_atvdemod_set_params; - aml_analog_ops->get_pll_status = aml_atvdemod_get_pll_status; - aml_analog_ops->get_atv_status = aml_atvdemod_get_atv_status; - return 0; -} - -static struct aml_fe_drv aml_atvdemod_drv = { - .name = "aml_atv_demod", - .capability = AM_FE_ANALOG, - .id = AM_ATV_DEMOD_AML, - .get_ops = aml_atvdemod_get_ops, - .init = aml_atvdemod_fe_init, - .enter_mode = aml_atvdemod_enter_mode, - .leave_mode = aml_atvdemod_leave_mode, - .suspend = aml_atvdemod_suspend, - .resume = aml_atvdemod_resume, -}; - -struct class *aml_atvdemod_clsp; - -static void aml_atvdemod_dt_parse(struct platform_device *pdev) -{ - struct device_node *node; - unsigned int val; - int ret; - - node = pdev->dev.of_node; - /* get integer value */ - if (node) { - ret = of_property_read_u32(node, "reg_23cf", &val); - if (ret) - pr_dbg("Can't find reg_23cf.\n"); - else - reg_23cf = val; - ret = of_property_read_u32(node, "audio_gain_val", &val); - if (ret) - pr_dbg("Can't find audio_gain_val.\n"); - else - set_audio_gain_val(val); - ret = of_property_read_u32(node, "video_gain_val", &val); - if (ret) - pr_dbg("Can't find video_gain_val.\n"); - else - set_video_gain_val(val); - /* agc pin mux */ - ret = of_property_read_string(node, "pinctrl-names", - &amlatvdemod_devp->pin_name); - if (!ret) { - /* amlatvdemod_devp->pin = */ - /* devm_pinctrl_get_select(&pdev->dev, */ - /* amlatvdemod_devp->pin_name); */ - pr_dbg("atvdemod agc pinmux name:%s\n", - amlatvdemod_devp->pin_name); - } - } -} -static struct resource amlatvdemod_memobj; -void __iomem *amlatvdemod_reg_base; -void __iomem *amlatvdemod_hiu_reg_base; -void __iomem *amlatvdemod_periphs_reg_base; -int amlatvdemod_reg_read(unsigned int reg, unsigned int *val) -{ - *val = readl(amlatvdemod_reg_base + reg); - return 0; -} - -int amlatvdemod_reg_write(unsigned int reg, unsigned int val) -{ - writel(val, (amlatvdemod_reg_base + reg)); - return 0; -} - -int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val) -{ - *val = readl(amlatvdemod_hiu_reg_base + ((reg - 0x1000)<<2)); - return 0; -} - -int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val) -{ - writel(val, (amlatvdemod_hiu_reg_base + ((reg - 0x1000)<<2))); - return 0; -} -int amlatvdemod_periphs_reg_read(unsigned int reg, unsigned int *val) -{ - *val = readl(amlatvdemod_periphs_reg_base + ((reg - 0x1000)<<2)); - return 0; -} - -int amlatvdemod_periphs_reg_write(unsigned int reg, unsigned int val) -{ - writel(val, (amlatvdemod_periphs_reg_base + ((reg - 0x1000)<<2))); - return 0; -} - -static int aml_atvdemod_probe(struct platform_device *pdev) -{ - int ret = 0; - struct resource *res; - int size_io_reg; - - res = &amlatvdemod_memobj; - amlatvdemod_devp = kmalloc(sizeof(struct amlatvdemod_device_s), - GFP_KERNEL); - if (!amlatvdemod_devp) - goto fail_alloc_region; - memset(amlatvdemod_devp, 0, sizeof(struct amlatvdemod_device_s)); - amlatvdemod_devp->clsp = class_create(THIS_MODULE, - ATVDEMOD_DEVICE_NAME); - if (!amlatvdemod_devp->clsp) - goto fail_create_class; - ret = class_create_file(amlatvdemod_devp->clsp, - &class_attr_atvdemod_debug); - if (ret) - goto fail_class_create_file; - amlatvdemod_devp->dev = &pdev->dev; - - /*reg mem*/ - pr_info("%s:amlatvdemod start get ioremap .\n", __func__); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "missing memory resource\n"); - return -ENODEV; - } - size_io_reg = resource_size(res); - pr_info("amlatvdemod_probe reg=%p,size=%x\n", - (void *)res->start, size_io_reg); - amlatvdemod_reg_base = - devm_ioremap_nocache(&pdev->dev, res->start, size_io_reg); - if (!amlatvdemod_reg_base) { - dev_err(&pdev->dev, "amlatvdemod ioremap failed\n"); - return -ENOMEM; - } - pr_info("%s: amlatvdemod maped reg_base =%p, size=%x\n", - __func__, amlatvdemod_reg_base, size_io_reg); - /*remap hiu mem*/ - amlatvdemod_hiu_reg_base = ioremap(0xc883c000, 0x2000); - /*remap periphs mem*/ - amlatvdemod_periphs_reg_base = ioremap(0xc8834000, 0x2000); - - /*initialize the tuner common struct and register*/ - aml_register_fe_drv(AM_DEV_ATV_DEMOD, &aml_atvdemod_drv); - - aml_atvdemod_dt_parse(pdev); - pr_dbg("[amlatvdemod.] : probe ok.\n"); - return 0; - -fail_class_create_file: - pr_dbg("[amlatvdemod.] : atvdemod class file create error.\n"); - class_destroy(amlatvdemod_devp->clsp); -fail_create_class: - pr_dbg("[amlatvdemod.] : atvdemod class create error.\n"); - kfree(amlatvdemod_devp); -fail_alloc_region: - pr_dbg("[amlatvdemod.] : atvdemod alloc error.\n"); - pr_dbg("[amlatvdemod.] : atvdemod_init fail.\n"); - return ret; -} - -static int __exit aml_atvdemod_remove(struct platform_device *pdev) -{ - if (amlatvdemod_devp == NULL) - return -1; - class_destroy(amlatvdemod_devp->clsp); - aml_unregister_fe_drv(AM_DEV_ATV_DEMOD, &aml_atvdemod_drv); - kfree(amlatvdemod_devp); - pr_dbg("[amlatvdemod.] : amvecm_remove.\n"); - return 0; -} - - -static const struct of_device_id aml_atvdemod_dt_match[] = { - { - .compatible = "amlogic, aml_atv_demod", - }, - {}, -}; - -static struct platform_driver aml_atvdemod_driver = { - .driver = { - .name = "aml_atv_demod", - .owner = THIS_MODULE, - .of_match_table = aml_atvdemod_dt_match, - }, - .probe = aml_atvdemod_probe, - .remove = __exit_p(aml_atvdemod_remove), -}; - - -static int __init aml_atvdemod_init(void) -{ - if (platform_driver_register(&aml_atvdemod_driver)) { - pr_err("failed to register amlatvdemod driver module\n"); - return -ENODEV; - } - pr_dbg("[amlatvdemod..]%s.\n", __func__); - return 0; -} - -static void __exit aml_atvdemod_exit(void) -{ - platform_driver_unregister(&aml_atvdemod_driver); - pr_dbg("[amlatvdemod..]%s: driver removed ok.\n", __func__); -} - -MODULE_AUTHOR("dezhi.kong "); -MODULE_DESCRIPTION("aml atv demod device driver"); -MODULE_LICENSE("GPL"); - -fs_initcall(aml_atvdemod_init); -module_exit(aml_atvdemod_exit); diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.c deleted file mode 100644 index f5a086e8e932..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.c +++ /dev/null @@ -1,2163 +0,0 @@ -/* - * Silicon labs amlogic Atvdemod Device Driver - * - * Author: dezhi kong - * - * - * Copyright (C) 2014 Amlogic Inc. - * - * 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. - */ - -/* Standard Liniux Headers */ -#include -#include -#include -#include -#include -#include -#include - -#include "atvdemod_func.h" -#include "../aml_dvb_reg.h" - -static int broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC; -module_param(broad_std, int, 0644); -MODULE_PARM_DESC(broad_std, "\n broad_std\n"); - -static unsigned long over_threshold = 0xffff; -module_param(over_threshold, ulong, 0644); -MODULE_PARM_DESC(over_threshold, "\n over_threshold\n"); - -static unsigned long input_amplitude = 0xffff; -module_param(input_amplitude, ulong, 0644); -MODULE_PARM_DESC(input_amplitude, "\n input_amplitude\n"); - -static bool audio_det_en; -module_param(audio_det_en, bool, 0644); -MODULE_PARM_DESC(audio_det_en, "\n audio_det_en\n"); - -static bool non_std_en; -module_param(non_std_en, bool, 0644); -MODULE_PARM_DESC(non_std__en, "\n non_std_en\n"); - -static int atv_video_gain; -module_param(atv_video_gain, int, 0644); -MODULE_PARM_DESC(atv_video_gain, "\n atv_video_gain\n"); - -static int audio_det_mode = AUDIO_AUTO_DETECT; -module_param(audio_det_mode, int, 0644); -MODULE_PARM_DESC(audio_det_mode, "\n audio_det_mode\n"); - -static int aud_dmd_jilinTV; -module_param(aud_dmd_jilinTV, int, 0644); -MODULE_PARM_DESC(aud_dmd_jilinTV, "\naud dmodulation setting for jilin TV\n"); - -static unsigned int if_freq = 4250000; /*PAL-DK:3250000;NTSC-M:4250000*/ -module_param(if_freq, uint, 0644); -MODULE_PARM_DESC(if_freq, "\n if_freq\n"); - -static int if_inv; -module_param(if_inv, int, 0644); -MODULE_PARM_DESC(if_inv, "\n if_inv\n"); - -static int afc_default = CARR_AFC_DEFAULT_VAL; -module_param(afc_default, int, 0644); -MODULE_PARM_DESC(afc_default, "\n afc_default\n"); - -/*GDE_Curve - * 0: CURVE-M - * 1: CURVE-A - * 2: CURVE-B - * 3: CURVE-CHINA - * 4: BYPASS - *BG --> CURVE-B(BYPASS) - *DK --> CURVE-CHINA - *NM --> CURVE-M - *I --> BYPASS - *SECAM --> BYPASS - */ -static int gde_curve; -module_param(gde_curve, int, 0644); -MODULE_PARM_DESC(gde_curve, "\n gde_curve\n"); - -static int sound_format; -module_param(sound_format, int, 0644); -MODULE_PARM_DESC(sound_format, "\n sound_format\n"); - -static unsigned int freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; -module_param(freq_hz_cvrt, int, 0644); -MODULE_PARM_DESC(freq_hz_cvrt, "\n freq_hz\n"); - -int atvdemod_debug_en; -module_param(atvdemod_debug_en, int, 0644); -MODULE_PARM_DESC(atvdemod_debug_en, "\n atvdemod_debug_en\n"); - -/*1:gpio mode output low;2:pwm mode*/ -static unsigned int atvdemod_agc_pinmux = 2; -module_param(atvdemod_agc_pinmux, int, 0644); -MODULE_PARM_DESC(atvdemod_agc_pinmux, "\n atvdemod_agc_pinmux\n"); - -static unsigned int atvdemod_afc_range = 5; -module_param(atvdemod_afc_range, uint, 0644); -MODULE_PARM_DESC(atvdemod_afc_range, "\n atvdemod_afc_range\n"); - -static unsigned int atvdemod_afc_offset = 500; -module_param(atvdemod_afc_offset, uint, 0644); -MODULE_PARM_DESC(atvdemod_afc_offset, "\n atvdemod_afc_offset\n"); - -static unsigned int atvdemod_timer_en = 1; -module_param(atvdemod_timer_en, uint, 0644); -MODULE_PARM_DESC(atvdemod_timer_en, "\n atvdemod_timer_en\n"); - -static unsigned int atvdemod_afc_en; -module_param(atvdemod_afc_en, uint, 0644); -MODULE_PARM_DESC(atvdemod_afc_en, "\n atvdemod_afc_en\n"); - -static unsigned int atvdemod_monitor_en; -module_param(atvdemod_monitor_en, uint, 0644); -MODULE_PARM_DESC(atvdemod_monitor_en, "\n atvdemod_monitor_en\n"); - -static unsigned int atvdemod_det_snr_en = 1; -module_param(atvdemod_det_snr_en, uint, 0644); -MODULE_PARM_DESC(atvdemod_det_snr_en, "\n atvdemod_det_snr_en\n"); - -static unsigned int pwm_kp = 0x19; -module_param(pwm_kp, uint, 0644); -MODULE_PARM_DESC(pwm_kp, "\n pwm_kp\n"); - -static unsigned int reg_dbg_en; -module_param(reg_dbg_en, uint, 0644); -MODULE_PARM_DESC(reg_dbg_en, "\n reg_dbg_en\n"); - -static unsigned int audio_gain_val = 512; -module_param(audio_gain_val, uint, 0644); -MODULE_PARM_DESC(audio_gain_val, "\n audio_gain_val\n"); - -enum AUDIO_SCAN_ID { - ID_PAL_I = 0, - ID_PAL_M, - ID_PAL_DK, - ID_PAL_BG, - ID_MAX, -}; - -static unsigned int mix1_freq; -static unsigned int timer_init_flag; -struct timer_list atvdemod_timer; -static int snr_val; -int broad_std_except_pal_m; - -int get_atvdemod_snr_val(void) -{ - return snr_val; -} -EXPORT_SYMBOL(get_atvdemod_snr_val); - -void amlatvdemod_set_std(int val) -{ - broad_std = val; -} -EXPORT_SYMBOL(amlatvdemod_set_std); - -void atv_dmd_wr_reg(unsigned char block, unsigned char reg, unsigned long data) -{ - /* unsigned long data_tmp; */ - unsigned long reg_addr = (block<<8) + reg * 4; - - amlatvdemod_reg_write(reg_addr, data); -} - -unsigned long atv_dmd_rd_reg(unsigned char block, unsigned char reg) -{ - unsigned long data = 0; - unsigned long reg_addr = (block<<8) + reg * 4; - - amlatvdemod_reg_read(reg_addr, (unsigned int *)&data); - return data; -} - -unsigned long atv_dmd_rd_byte(unsigned long block_addr, unsigned long reg_addr) -{ - unsigned long data; - - data = atv_dmd_rd_long(block_addr, reg_addr); - /*R_APB_REG((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2); - *((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+ - ((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2))); - */ - if ((reg_addr & 0x3) == 0) - data = data >> 24; - else if ((reg_addr & 0x3) == 1) - data = (data >> 16 & 0xff); - else if ((reg_addr & 0x3) == 2) - data = (data >> 8 & 0xff); - else if ((reg_addr & 0x3) == 3) - data = (data >> 0 & 0xff); - return data; -} - -unsigned long atv_dmd_rd_word(unsigned long block_addr, unsigned long reg_addr) -{ - unsigned long data; - - data = atv_dmd_rd_long(block_addr, reg_addr); - /*R_APB_REG((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2); - *((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+ - ((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2))); - */ - if ((reg_addr & 0x3) == 0) - data = data >> 16; - else if ((reg_addr & 0x3) == 1) - data = (data >> 8 & 0xffff); - else if ((reg_addr & 0x3) == 2) - data = (data >> 0 & 0xffff); - else if ((reg_addr & 0x3) == 3) - data = (((data & 0xff) << 8) | ((data >> 24) & 0xff)); - return data; -} - -unsigned long atv_dmd_rd_long(unsigned long block_addr, unsigned long reg_addr) -{ - unsigned long data; - /*data = *((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+ - *((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2))); - */ - data = - R_ATVDEMOD_REG((((block_addr & 0xff) << 6) + - ((reg_addr & 0xff) >> 2)) << 2); - - return data; -} -EXPORT_SYMBOL(atv_dmd_rd_long); - -void atv_dmd_wr_long(unsigned long block_addr, unsigned long reg_addr, - unsigned long data) -{ - W_ATVDEMOD_REG((((block_addr & 0xff) << 6) + - ((reg_addr & 0xff) >> 2)) << 2, data); - if (reg_dbg_en) - pr_dbg("block_addr:0x%x,reg_addr:0x%x;data:0x%x\n", - (unsigned int)block_addr, (unsigned int)reg_addr, - (unsigned int)data); - /**((volatile unsigned long *) - * (ATV_DMD_APB_BASE_ADDR+((((block_addr & 0xff) << 6) + - * ((reg_addr & 0xff) >> 2)) << 2))) = data; - */ - -} -EXPORT_SYMBOL(atv_dmd_wr_long); - -void atv_dmd_wr_word(unsigned long block_addr, unsigned long reg_addr, - unsigned long data) -{ - unsigned long data_tmp; - - data_tmp = atv_dmd_rd_long(block_addr, reg_addr); - data = data & 0xffff; - if ((reg_addr & 0x3) == 0) - data = (data << 16 | (data_tmp & 0xffff)); - else if ((reg_addr & 0x3) == 1) - data = - ((data_tmp & 0xff000000) | (data << 8) | (data_tmp & 0xff)); - else if ((reg_addr & 0x3) == 2) - data = (data | (data_tmp & 0xffff0000)); - else if ((reg_addr & 0x3) == 3) - data = - (((data & 0xff) << 24) | ((data_tmp & 0xffff0000) >> 8) | - ((data & 0xff00) >> 8)); - - /**((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+ - *((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2))) = data; - */ - atv_dmd_wr_long(block_addr, reg_addr, data); - /*W_ATVDEMOD_REG(((((block_addr & 0xff) <<6) + - *((reg_addr & 0xff) >>2)) << 2), data); - */ - -} - -void atv_dmd_wr_byte(unsigned long block_addr, unsigned long reg_addr, - unsigned long data) -{ - unsigned long data_tmp; - - data_tmp = atv_dmd_rd_long(block_addr, reg_addr); - - /*pr_info("atv demod wr byte, read block addr %lx\n",block_addr);*/ - /*pr_info("atv demod wr byte, read reg addr %lx\n", reg_addr);*/ - /*pr_info("atv demod wr byte, wr data %lx\n",data);*/ - /*pr_info("atv demod wr byte, read data out %lx\n",data_tmp);*/ - - data = data & 0xff; - /*pr_info("atv demod wr byte, data & 0xff %lx\n",data);*/ - if ((reg_addr & 0x3) == 0) { - data = (data << 24 | (data_tmp & 0xffffff)); - /*pr_info("atv demod wr byte, reg_addr & 0x3 == 0, - *wr data %lx\n",data); - */ - } else if ((reg_addr & 0x3) == 1) - data = - ((data_tmp & 0xff000000) | (data << 16) | - (data_tmp & 0xffff)); - else if ((reg_addr & 0x3) == 2) - data = - ((data_tmp & 0xffff0000) | (data << 8) | (data_tmp & 0xff)); - else if ((reg_addr & 0x3) == 3) - data = ((data_tmp & 0xffffff00) | (data & 0xff)); - - /*pr_info("atv demod wr byte, wr data %lx\n",data);*/ - - /**((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+ - *((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2))) = data; - */ - atv_dmd_wr_long(block_addr, reg_addr, data); - /*W_ATVDEMOD_REG(((((block_addr & 0xff) <<6) + - *((reg_addr & 0xff) >>2)) << 2), data); - */ -} - -void set_audio_gain_val(int val) -{ - audio_gain_val = val; -} - -void set_video_gain_val(int val) -{ - atv_video_gain = val; -} - -void atv_dmd_soft_reset(void) -{ - atv_dmd_wr_long(0x1d, 0x0, 0x1035);/* disable dac */ - atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x0); - atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x1); - atv_dmd_wr_long(0x1d, 0x0, 0x1037);/* enable dac */ -} - -void atv_dmd_input_clk_32m(void) -{ - atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_MGR, 0x2, 0x1); -} - -void read_version_register(void) -{ - unsigned long data, Byte1, Byte2, Word; - - pr_info("ATV-DMD read version register\n"); - Byte1 = atv_dmd_rd_byte(APB_BLOCK_ADDR_VERS_REGISTER, 0x0); - Byte2 = atv_dmd_rd_byte(APB_BLOCK_ADDR_VERS_REGISTER, 0x1); - Word = atv_dmd_rd_word(APB_BLOCK_ADDR_VERS_REGISTER, 0x2); - data = atv_dmd_rd_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0); - - pr_info("atv demod read version register data out %lx\n", data); - - if ((data != 0x516EAB13) - || (((Byte1 << 24) | (Byte2 << 16) | Word) != 0x516EAB13)) - pr_info("atv demod read version reg failed\n"); -} - -void check_communication_interface(void) -{ - unsigned long data_tmp; - - pr_info("ATV-DMD check communication intf\n"); - atv_dmd_wr_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0, 0xA1B2C3D4); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VERS_REGISTER, 0x1, 0x34); - atv_dmd_wr_word(APB_BLOCK_ADDR_VERS_REGISTER, 0x2, 0xBCDE); - data_tmp = atv_dmd_rd_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0); - pr_info("atv demod check communication intf data out %lx\n", data_tmp); - - if (data_tmp != 0xa134bcde) - pr_info("atv demod check communication intf failed\n"); - atv_dmd_wr_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0, 0x516EAB13); -} - -void power_on_receiver(void) -{ - atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_MGR, 0x2, 0x11); -} - -void atv_dmd_misc(void) -{ - atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x38); /*zhuangwei*/ - /*cpu.write_byte(8'h1A,8'h0E,8'h06);//zhuangwei*/ - /*cpu.write_byte(8'h19,8'h01,8'h7f);//zhuangwei*/ - atv_dmd_wr_byte(0x0f, 0x45, 0x90); /*zhuangwei*/ - - atv_dmd_wr_long(0x0f, 0x44, 0x5c8808c1);/*zhuangwei*/ - if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_R840) { - atv_dmd_wr_long(0x0f, 0x3c, reg_23cf);/*zhuangwei*/ - /*guanzhong@20150804a*/ - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1); - atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x60180200); - /*dezhi@20150610a 0x1a maybe better?!*/ - /* atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0x19); */ - } else { - atv_dmd_wr_long(0x0f, 0x3c, 0x88188832);/*zhuangwei*/ - atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46170200); - } - - if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_MXL661) { - atv_dmd_wr_long(0x0c, 0x04, 0xbffa0000) ;/*test in sky*/ - atv_dmd_wr_long(0x0c, 0x00, 0x5a4000);/*test in sky*/ - /*guanzhong@20151013 fix nonstd def is:0x0c010301;0x0c020601*/ - atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c030901); - } else { - /*zhuangwei 0xdafa0000*/ - atv_dmd_wr_long(0x0c, 0x04, 0xc8fa0000); - atv_dmd_wr_long(0x0c, 0x00, 0x554000);/*zhuangwei*/ - } - atv_dmd_wr_long(0x19, 0x04, 0xdafa0000);/*zhuangwei*/ - atv_dmd_wr_long(0x19, 0x00, 0x4a4000);/*zhuangwei*/ - /*atv_dmd_wr_byte(0x0c,0x01,0x28);//pwd-out gain*/ - /*atv_dmd_wr_byte(0x0c,0x04,0xc0);//pwd-out offset*/ - - aml_audio_valume_gain_set(audio_gain_val); - /* 20160121 fix audio demodulation over */ - atv_dmd_wr_long(0x09, 0x00, 0x1030501); - atv_dmd_wr_long(0x09, 0x04, 0x1900000); - if (aud_dmd_jilinTV) - atv_dmd_wr_long(0x09, 0x00, 0x2030503); - if (non_std_en == 1) { - atv_dmd_wr_long(0x09, 0x00, 0x2030503); - atv_dmd_wr_long(0x0f, 0x44, 0x7c8808c1); - atv_dmd_wr_long(0x06, 0x24, 0x0c010801); - } else { - atv_dmd_wr_long(0x09, 0x00, 0x1030501); - if (atv_video_gain) - atv_dmd_wr_long(0x0f, 0x44, atv_video_gain); - else - atv_dmd_wr_long(0x0f, 0x44, 0xfc0808c1); - atv_dmd_wr_long(0x06, 0x24, 0xc030901); - } - -} - -/*Broadcast_Standard*/ -/* 0: NTSC*/ -/* 1: NTSC-J*/ -/* 2: PAL-M,*/ -/* 3: PAL-BG*/ -/* 4: DTV*/ -/* 5: SECAM- DK2*/ -/* 6: SECAM -DK3*/ -/* 7: PAL-BG, NICAM*/ -/* 8: PAL-DK-CHINA*/ -/* 9: SECAM-L / SECAM-DK3*/ -/* 10: PAL-I*/ -/* 11: PAL-DK1*/ -/*GDE_Curve*/ -/* 0: CURVE-M*/ -/* 1: CURVE-A*/ -/* 2: CURVE-B*/ -/* 3: CURVE-CHINA*/ -/* 4: BYPASS*/ -/*sound format 0: MONO;1:NICAM*/ -void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, - int Tuner_Input_IF_inverted, int GDE_Curve, - int sound_format) -{ - int tmp_int; - int mixer1 = 0; - int mixer3 = 0; - int mixer3_bypass = 0; - int cv = 0; - /*int if_freq = 0;*/ - - int i = 0; - int super_coef0 = 0; - int super_coef1 = 0; - int super_coef2 = 0; - int gp_coeff_1[37]; - int gp_coeff_2[37]; - int gp_cv_g1 = 0; - int gp_cv_g2 = 0; - int crvy_reg_1 = 0; - int crvy_reg_2 = 0; - int sif_co_mx = 0; - int sif_fi_mx = 0; - int sif_ic_bw = 0; - int sif_bb_bw = 0; - int sif_deemp = 0; - int sif_cfg_demod = 0; - int sif_fm_gain = 0; - int gd_coeff[6]; - int gd_bypass; - - pr_info("ATV-DMD configure receiver register\n"); - - if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I)) { - gp_coeff_1[0] = 0x57777; - gp_coeff_1[1] = 0xdd777; - gp_coeff_1[2] = 0x7d777; - gp_coeff_1[3] = 0x75777; - gp_coeff_1[4] = 0x75777; - gp_coeff_1[5] = 0x7c777; - gp_coeff_1[6] = 0x5c777; - gp_coeff_1[7] = 0x44777; - gp_coeff_1[8] = 0x54777; - gp_coeff_1[9] = 0x47d77; - gp_coeff_1[10] = 0x55d77; - gp_coeff_1[11] = 0x55577; - gp_coeff_1[12] = 0x77577; - gp_coeff_1[13] = 0xc4c77; - gp_coeff_1[14] = 0xd7d77; - gp_coeff_1[15] = 0x75477; - gp_coeff_1[16] = 0xcc477; - gp_coeff_1[17] = 0x575d7; - gp_coeff_1[18] = 0xc4c77; - gp_coeff_1[19] = 0xdd757; - gp_coeff_1[20] = 0xdd477; - gp_coeff_1[21] = 0x77dd7; - gp_coeff_1[22] = 0x5dc77; - gp_coeff_1[23] = 0x47c47; - gp_coeff_1[24] = 0x57477; - gp_coeff_1[25] = 0x5c7c7; - gp_coeff_1[26] = 0xccc77; - gp_coeff_1[27] = 0x5ddd5; - gp_coeff_1[28] = 0x54477; - gp_coeff_1[29] = 0x7757d; - gp_coeff_1[30] = 0x755d7; - gp_coeff_1[31] = 0x47cc4; - gp_coeff_1[32] = 0x57d57; - gp_coeff_1[33] = 0x554cc; - gp_coeff_1[34] = 0x755d7; - gp_coeff_1[35] = 0x7d3b2; - gp_coeff_1[36] = 0x73a91; - gp_coeff_2[0] = 0xd5777; - gp_coeff_2[1] = 0x77777; - gp_coeff_2[2] = 0x7c777; - gp_coeff_2[3] = 0xcc777; - gp_coeff_2[4] = 0xc7777; - gp_coeff_2[5] = 0xdd777; - gp_coeff_2[6] = 0x44c77; - gp_coeff_2[7] = 0x54c77; - gp_coeff_2[8] = 0xdd777; - gp_coeff_2[9] = 0x7c777; - gp_coeff_2[10] = 0xc7c77; - gp_coeff_2[11] = 0x75c77; - gp_coeff_2[12] = 0xdd577; - gp_coeff_2[13] = 0x44777; - gp_coeff_2[14] = 0xd5c77; - gp_coeff_2[15] = 0xdc777; - gp_coeff_2[16] = 0xd7757; - gp_coeff_2[17] = 0x4c757; - gp_coeff_2[18] = 0x7d777; - gp_coeff_2[19] = 0x75477; - gp_coeff_2[20] = 0x57547; - gp_coeff_2[21] = 0xdc747; - gp_coeff_2[22] = 0x74777; - gp_coeff_2[23] = 0x75757; - gp_coeff_2[24] = 0x4cc75; - gp_coeff_2[25] = 0xd4747; - gp_coeff_2[26] = 0x7d7d7; - gp_coeff_2[27] = 0xd5577; - gp_coeff_2[28] = 0xc4c75; - gp_coeff_2[29] = 0xcc477; - gp_coeff_2[30] = 0xdd54c; - gp_coeff_2[31] = 0x7547d; - gp_coeff_2[32] = 0x55547; - gp_coeff_2[33] = 0x5575c; - gp_coeff_2[34] = 0xd543a; - gp_coeff_2[35] = 0x57b3a; - gp_coeff_2[36] = 0x77777; - gp_cv_g1 = 0x2b062d; - gp_cv_g2 = 0x40fa2d; - } else if ((Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG_NICAM)) { - gp_coeff_1[0] = 0x75777; - gp_coeff_1[1] = 0x57777; - gp_coeff_1[2] = 0x7d777; - gp_coeff_1[3] = 0x75777; - gp_coeff_1[4] = 0x75777; - gp_coeff_1[5] = 0x7c777; - gp_coeff_1[6] = 0x47777; - gp_coeff_1[7] = 0x74777; - gp_coeff_1[8] = 0xd5d77; - gp_coeff_1[9] = 0xc7777; - gp_coeff_1[10] = 0x77577; - gp_coeff_1[11] = 0xd7d77; - gp_coeff_1[12] = 0x75d77; - gp_coeff_1[13] = 0xdd477; - gp_coeff_1[14] = 0x77d77; - gp_coeff_1[15] = 0x75c77; - gp_coeff_1[16] = 0xc4477; - gp_coeff_1[17] = 0x4c777; - gp_coeff_1[18] = 0x5d5d7; - gp_coeff_1[19] = 0xd7d57; - gp_coeff_1[20] = 0x47577; - gp_coeff_1[21] = 0xd7dd7; - gp_coeff_1[22] = 0xd7d57; - gp_coeff_1[23] = 0xdd757; - gp_coeff_1[24] = 0xc75c7; - gp_coeff_1[25] = 0x7d477; - gp_coeff_1[26] = 0x5d747; - gp_coeff_1[27] = 0x7ddc7; - gp_coeff_1[28] = 0xc4c77; - gp_coeff_1[29] = 0xd4c75; - gp_coeff_1[30] = 0xc755d; - gp_coeff_1[31] = 0x47cc7; - gp_coeff_1[32] = 0xdd7d4; - gp_coeff_1[33] = 0x4c75d; - gp_coeff_1[34] = 0xc7dcc; - gp_coeff_1[35] = 0xd52a2; - gp_coeff_1[36] = 0x555a1; - gp_coeff_2[0] = 0x5d777; - gp_coeff_2[1] = 0x47777; - gp_coeff_2[2] = 0x7d777; - gp_coeff_2[3] = 0xcc777; - gp_coeff_2[4] = 0xd7777; - gp_coeff_2[5] = 0x7c777; - gp_coeff_2[6] = 0x7dd77; - gp_coeff_2[7] = 0xdd777; - gp_coeff_2[8] = 0x7c777; - gp_coeff_2[9] = 0x57c77; - gp_coeff_2[10] = 0x7c777; - gp_coeff_2[11] = 0xd5777; - gp_coeff_2[12] = 0xd7c77; - gp_coeff_2[13] = 0xdd777; - gp_coeff_2[14] = 0x77477; - gp_coeff_2[15] = 0xc7d77; - gp_coeff_2[16] = 0xc4777; - gp_coeff_2[17] = 0x57557; - gp_coeff_2[18] = 0xd5577; - gp_coeff_2[19] = 0xd5577; - gp_coeff_2[20] = 0x7d547; - gp_coeff_2[21] = 0x74757; - gp_coeff_2[22] = 0xc7577; - gp_coeff_2[23] = 0xcc7d5; - gp_coeff_2[24] = 0x4c747; - gp_coeff_2[25] = 0xddc77; - gp_coeff_2[26] = 0x54447; - gp_coeff_2[27] = 0xcc447; - gp_coeff_2[28] = 0x5755d; - gp_coeff_2[29] = 0x5dd57; - gp_coeff_2[30] = 0x54747; - gp_coeff_2[31] = 0x5747c; - gp_coeff_2[32] = 0xc77dd; - gp_coeff_2[33] = 0x47557; - gp_coeff_2[34] = 0x7a22a; - gp_coeff_2[35] = 0xc73aa; - gp_coeff_2[36] = 0x77777; - gp_cv_g1 = 0x2b2834; - gp_cv_g2 = 0x3f6c2e; - } else if ((Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3)) { - gp_coeff_1[0] = 0x47777; - gp_coeff_1[1] = 0x77777; - gp_coeff_1[2] = 0x5d777; - gp_coeff_1[3] = 0x47777; - gp_coeff_1[4] = 0x75777; - gp_coeff_1[5] = 0x5c777; - gp_coeff_1[6] = 0x57777; - gp_coeff_1[7] = 0x44777; - gp_coeff_1[8] = 0x55d77; - gp_coeff_1[9] = 0x7d777; - gp_coeff_1[10] = 0x55577; - gp_coeff_1[11] = 0xd5d77; - gp_coeff_1[12] = 0xd7d77; - gp_coeff_1[13] = 0x47477; - gp_coeff_1[14] = 0xdc777; - gp_coeff_1[15] = 0x4cc77; - gp_coeff_1[16] = 0x77d57; - gp_coeff_1[17] = 0xc4777; - gp_coeff_1[18] = 0xdd7d7; - gp_coeff_1[19] = 0x7c757; - gp_coeff_1[20] = 0xd4477; - gp_coeff_1[21] = 0x755c7; - gp_coeff_1[22] = 0x47d57; - gp_coeff_1[23] = 0xd7c47; - gp_coeff_1[24] = 0xd4cc7; - gp_coeff_1[25] = 0x47577; - gp_coeff_1[26] = 0x5c7d5; - gp_coeff_1[27] = 0x4c75d; - gp_coeff_1[28] = 0xd57d7; - gp_coeff_1[29] = 0x44755; - gp_coeff_1[30] = 0x7557d; - gp_coeff_1[31] = 0xc477d; - gp_coeff_1[32] = 0xd5d44; - gp_coeff_1[33] = 0xdd77d; - gp_coeff_1[34] = 0x5d75b; - gp_coeff_1[35] = 0x74332; - gp_coeff_1[36] = 0xd4311; - gp_coeff_2[0] = 0xd7777; - gp_coeff_2[1] = 0x77777; - gp_coeff_2[2] = 0xdd777; - gp_coeff_2[3] = 0xdc777; - gp_coeff_2[4] = 0xc7777; - gp_coeff_2[5] = 0xdd777; - gp_coeff_2[6] = 0x77d77; - gp_coeff_2[7] = 0x77777; - gp_coeff_2[8] = 0x55777; - gp_coeff_2[9] = 0xc7d77; - gp_coeff_2[10] = 0xd4777; - gp_coeff_2[11] = 0xc7477; - gp_coeff_2[12] = 0x7c777; - gp_coeff_2[13] = 0xd5577; - gp_coeff_2[14] = 0xdd557; - gp_coeff_2[15] = 0x47577; - gp_coeff_2[16] = 0xd7477; - gp_coeff_2[17] = 0x55747; - gp_coeff_2[18] = 0xdd757; - gp_coeff_2[19] = 0xd7477; - gp_coeff_2[20] = 0x7d7d5; - gp_coeff_2[21] = 0xddd47; - gp_coeff_2[22] = 0xdd777; - gp_coeff_2[23] = 0x575d5; - gp_coeff_2[24] = 0x47547; - gp_coeff_2[25] = 0x555c7; - gp_coeff_2[26] = 0x7d447; - gp_coeff_2[27] = 0xd7447; - gp_coeff_2[28] = 0x757dd; - gp_coeff_2[29] = 0x7dc77; - gp_coeff_2[30] = 0x54747; - gp_coeff_2[31] = 0xc743b; - gp_coeff_2[32] = 0xd7c7c; - gp_coeff_2[33] = 0xd7557; - gp_coeff_2[34] = 0x55c7a; - gp_coeff_2[35] = 0x4cc29; - gp_coeff_2[36] = 0x77777; - gp_cv_g1 = 0x20682b; - gp_cv_g2 = 0x29322f; - } else if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I) { - gp_coeff_1[0] = 0x77777; - gp_coeff_1[1] = 0x75777; - gp_coeff_1[2] = 0x7d777; - gp_coeff_1[3] = 0xd7777; - gp_coeff_1[4] = 0x74777; - gp_coeff_1[5] = 0xcc777; - gp_coeff_1[6] = 0x57777; - gp_coeff_1[7] = 0x5d577; - gp_coeff_1[8] = 0x5dd77; - gp_coeff_1[9] = 0x74777; - gp_coeff_1[10] = 0x77577; - gp_coeff_1[11] = 0x77c77; - gp_coeff_1[12] = 0xdc477; - gp_coeff_1[13] = 0x5d577; - gp_coeff_1[14] = 0x575d7; - gp_coeff_1[15] = 0xc7d57; - gp_coeff_1[16] = 0x77777; - gp_coeff_1[17] = 0x557d7; - gp_coeff_1[18] = 0xc7557; - gp_coeff_1[19] = 0x75c77; - gp_coeff_1[20] = 0x477d7; - gp_coeff_1[21] = 0xcc747; - gp_coeff_1[22] = 0x47dd7; - gp_coeff_1[23] = 0x775d7; - gp_coeff_1[24] = 0x47447; - gp_coeff_1[25] = 0x75cc7; - gp_coeff_1[26] = 0xc7777; - gp_coeff_1[27] = 0xc75d5; - gp_coeff_1[28] = 0x44c7d; - gp_coeff_1[29] = 0x74c47; - gp_coeff_1[30] = 0x47d75; - gp_coeff_1[31] = 0x7d57c; - gp_coeff_1[32] = 0xd5dc4; - gp_coeff_1[33] = 0xdd575; - gp_coeff_1[34] = 0xdb3bb; - gp_coeff_1[35] = 0x5c752; - gp_coeff_1[36] = 0x90880; - gp_coeff_2[0] = 0x5d777; - gp_coeff_2[1] = 0xd7777; - gp_coeff_2[2] = 0x77777; - gp_coeff_2[3] = 0xd5d77; - gp_coeff_2[4] = 0xc7777; - gp_coeff_2[5] = 0xd7777; - gp_coeff_2[6] = 0xddd77; - gp_coeff_2[7] = 0x55777; - gp_coeff_2[8] = 0x57777; - gp_coeff_2[9] = 0x54c77; - gp_coeff_2[10] = 0x4c477; - gp_coeff_2[11] = 0x74777; - gp_coeff_2[12] = 0xd5d77; - gp_coeff_2[13] = 0x47757; - gp_coeff_2[14] = 0x75577; - gp_coeff_2[15] = 0xc7577; - gp_coeff_2[16] = 0x4c747; - gp_coeff_2[17] = 0x7d477; - gp_coeff_2[18] = 0x7c757; - gp_coeff_2[19] = 0x55dd5; - gp_coeff_2[20] = 0x57577; - gp_coeff_2[21] = 0x44c47; - gp_coeff_2[22] = 0x5cc75; - gp_coeff_2[23] = 0x4cc77; - gp_coeff_2[24] = 0x47547; - gp_coeff_2[25] = 0x777d5; - gp_coeff_2[26] = 0xcccc7; - gp_coeff_2[27] = 0x57447; - gp_coeff_2[28] = 0xdc757; - gp_coeff_2[29] = 0x5755c; - gp_coeff_2[30] = 0x44747; - gp_coeff_2[31] = 0x5d5dd; - gp_coeff_2[32] = 0x5747b; - gp_coeff_2[33] = 0x77557; - gp_coeff_2[34] = 0xdcb2a; - gp_coeff_2[35] = 0xd5779; - gp_coeff_2[36] = 0x77777; - gp_cv_g1 = 0x72242f; - gp_cv_g2 = 0x28822a; - } - - if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J)) { - sif_co_mx = 0xb8; - sif_fi_mx = 0x0; - sif_ic_bw = 0x1; - sif_bb_bw = 0x1; - sif_deemp = 0x1; - sif_cfg_demod = (sound_format == 0) ? 0x0:0x2; - sif_fm_gain = 0x4; - } else if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG) - || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG)) { - sif_co_mx = 0xa6; - sif_fi_mx = 0x10; - sif_ic_bw = 0x2; - sif_bb_bw = 0x0; - sif_deemp = 0x2; - sif_cfg_demod = (sound_format == 0) ? 0x0:0x2; - sif_fm_gain = 0x3; - } else if (Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK1) { - sif_co_mx = 154; - sif_fi_mx = 240; - sif_ic_bw = 2; - sif_bb_bw = 0; - sif_deemp = 2; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } else if (Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2) { - sif_co_mx = 150; - sif_fi_mx = 16; - sif_ic_bw = 2; - sif_bb_bw = 0; - sif_deemp = 2; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } else if (Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3) { - sif_co_mx = 158; - sif_fi_mx = 208; - sif_ic_bw = 3; - sif_bb_bw = 0; - sif_deemp = 2; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } else if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I) - || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I)) { - sif_co_mx = 153; - sif_fi_mx = 56; - sif_ic_bw = 3; - sif_bb_bw = 0; - sif_deemp = 2; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } else if (Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG_NICAM) { - sif_co_mx = 163; - sif_fi_mx = 40; - sif_ic_bw = 0; - sif_bb_bw = 0; - sif_deemp = 2; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } else if (Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { - sif_co_mx = 159; - sif_fi_mx = 200; - sif_ic_bw = 3; - sif_bb_bw = 0; - sif_deemp = 0; - sif_cfg_demod = (sound_format == 0) ? 1:2; - sif_fm_gain = 5; - } else if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) - || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK)) { - sif_co_mx = 159; - sif_fi_mx = 200; - sif_ic_bw = 3; - sif_bb_bw = 0; - sif_deemp = 2; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } else if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) { - sif_co_mx = 182; - sif_fi_mx = 16; - sif_ic_bw = 1; - sif_bb_bw = 0; - sif_deemp = 1; - sif_cfg_demod = (sound_format == 0) ? 0:2; - sif_fm_gain = 3; - } - sif_fm_gain -= 2; /*avoid sound overflow@guanzhong*/ - /*FE PATH*/ - pr_info("ATV-DMD configure mixer\n"); - if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { - tmp_int = (Tuner_IF_Frequency/125000); - if (Tuner_Input_IF_inverted == 0x0) - mixer1 = -tmp_int; - else - mixer1 = tmp_int; - - mixer3 = 0; - mixer3_bypass = 0; - } else { - tmp_int = (Tuner_IF_Frequency/125000); - pr_info("ATV-DMD configure mixer 1\n"); - - if (Tuner_Input_IF_inverted == 0x0) - mixer1 = 0xe8 - tmp_int; - else - mixer1 = tmp_int - 0x18; - - pr_info("ATV-DMD configure mixer 2\n"); - mixer3 = 0x30; - mixer3_bypass = 0x1; - } - - pr_info("ATV-DMD configure mixer 3\n"); - atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, mixer1); - atv_dmd_wr_word(APB_BLOCK_ADDR_MIXER_3, 0x0, - (((mixer3 & 0xff) << 8) | (mixer3_bypass & 0xff))); - - if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) - atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03180e0f); - else - atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03150e0f); - if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_R840) { - /*config pwm for tuner r840*/ - atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_SE, 1, 0xf); - } - - /*GP Filter*/ - pr_info("ATV-DMD configure GP_filter\n"); - if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { - cv = gp_cv_g1; - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x0, - (0x08000000 | (cv & 0x7fffff))); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x4, 0x04); - for (i = 0; i < 9; i = i + 1) { - /*super_coef = {gp_coeff_1[i*4],gp_coeff_1[i*4+1], - *gp_coeff_1[i*4+2],gp_coeff_1[i*4+3]}; - */ - super_coef0 = - (((gp_coeff_1[i * 4 + 2] & 0xfff) << 20) | - (gp_coeff_1[i * 4 + 3] & 0xfffff)); - super_coef1 = - (((gp_coeff_1[i * 4] & 0xf) << 28) | - ((gp_coeff_1[i * 4 + 1] & 0xfffff) << 8) | - ((gp_coeff_1[i * 4 + 2] >> 12) & 0xff)); - super_coef2 = ((gp_coeff_1[i * 4] >> 4) & 0xffff); - - /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, - *0x8,super_coef[79:48]); - */ - /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, - *0xC,super_coef[47:16]); - */ - /*atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, - *0x10,super_coef[15:0]); - */ - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, - (((super_coef2 & 0xffff) << 16) | - ((super_coef1 & 0xffff0000) >> 16))); - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0xC, - (((super_coef1 & 0xffff) << 16) | - ((super_coef0 & 0xffff0000) >> 16))); - atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, 0x10, - (super_coef0 & 0xffff)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, i); - } - /*atv_dmd_wr_long - *(APB_BLOCK_ADDR_GP_VD_FLT,0x8,{gp_coeff_1[36],12'd0}); - */ - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, - ((gp_coeff_1[36] & 0xfffff) << 12)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, 0x09); - - } else { - cv = gp_cv_g1 - gp_cv_g2; - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x0, cv & 0x7fffff); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x4, 0x00); - for (i = 0; i < 9; i = i + 1) { - /*super_coef = {gp_coeff_1[i*4],gp_coeff_1[i*4+1], - *gp_coeff_1[i*4+2],gp_coeff_1[i*4+3]}; - */ - super_coef0 = - (((gp_coeff_1[i * 4 + 2] & 0xfff) << 20) | - (gp_coeff_1[i * 4 + 3] & 0xfffff)); - super_coef1 = - (((gp_coeff_1[i * 4] & 0xf) << 28) | - ((gp_coeff_1[i * 4 + 1] & 0xfffff) << 8) | - ((gp_coeff_1[i * 4 + 2] >> 12) & 0xff)); - super_coef2 = ((gp_coeff_1[i * 4] >> 4) & 0xffff); - - /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, - *0x8,super_coef[79:48]); - */ - /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, - *0xC,super_coef[47:16]); - */ - /*atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, - *0x10,super_coef[15:0]); - */ - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, - (((super_coef2 & 0xffff) << 16) | - ((super_coef1 & 0xffff0000) >> 16))); - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0xC, - (((super_coef1 & 0xffff) << 16) | - ((super_coef0 & 0xffff0000) >> 16))); - atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, 0x10, - (super_coef0 & 0xffff)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, i); - - /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, - *0x8,{gp_coeff_1[36],12'd0}); - */ - } - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, - ((gp_coeff_1[36] & 0xfffff) << 12)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, 9); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x4, 0x01); - - for (i = 0; i < 9; i = i + 1) { - /*super_coef = {gp_coeff_2[i*4],gp_coeff_2[i*4+1], - *gp_coeff_2[i*4+2],gp_coeff_2[i*4+3]}; - */ - super_coef0 = - (((gp_coeff_2[i * 4 + 2] & 0xfff) << 20) | - (gp_coeff_2[i * 4 + 3] & 0xfffff)); - super_coef1 = - (((gp_coeff_2[i * 4] & 0xf) << 28) | - ((gp_coeff_2[i * 4 + 1] & 0xfffff) << 8) | - ((gp_coeff_2[i * 4 + 2] >> 12) & 0xff)); - super_coef2 = ((gp_coeff_2[i * 4] >> 4) & 0xffff); - - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, - (((super_coef2 & 0xffff) << 16) | - ((super_coef1 & 0xffff0000) >> 16))); - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0xC, - (((super_coef1 & 0xffff) << 16) | - ((super_coef0 & 0xffff0000) >> 16))); - atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, 0x10, - (super_coef0 & 0xffff)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, i); - } - - atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, - ((gp_coeff_2[36] & 0xfffff) << 12)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, 0x09); - } - - /*CRVY*/ - pr_info("ATV-DMD configure CRVY\n"); - if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { - crvy_reg_1 = 0xFF; - crvy_reg_2 = 0x00; - } else { - crvy_reg_1 = 0x04; - crvy_reg_2 = 0x01; - } - - atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x29, crvy_reg_1); - pr_info("ATV-DMD configure rcvy 2\n"); - pr_info("ATV-DMD configure rcvy, crvy_reg_2 = %x\n", crvy_reg_2); - atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x20, crvy_reg_2); - - /*SOUND SUPPRESS*/ - pr_info("ATV-DMD configure sound suppress\n"); - - if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) || - (sound_format == 0)) - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_VD_IF, 0x02, 0x01); - else - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_VD_IF, 0x02, 0x00); - - /*SIF*/ - pr_info("ATV-DMD configure sif\n"); - if (!(Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV)) { - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x03, sif_ic_bw); - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x01, sif_fi_mx); - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x02, sif_co_mx); - - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, - (((sif_bb_bw & 0xff) << 24) | - ((sif_deemp & 0xff) << 16) | 0x0500 | - sif_fm_gain)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x06, sif_cfg_demod); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x24, - (((sif_bb_bw & 0xff) << 24) | - 0xfffff)); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); - } - - if (Broadcast_Standard != AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { - if (sound_format == 0) { - tmp_int = 0; - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_3, 0x00, - (0x01000000 | (tmp_int & 0xffffff))); - } else { - tmp_int = (256 - sif_co_mx) << 13; - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_3, 0x00, - (tmp_int & 0xffffff)); - } - } - - if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { - atv_dmd_wr_long(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x02040E0A); - atv_dmd_wr_word(APB_BLOCK_ADDR_IC_AGC, 0x04, 0x0F0D); - } else if (sound_format == 0) - atv_dmd_wr_byte(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x04); - else if (Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { - atv_dmd_wr_long(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x0003140A); - atv_dmd_wr_word(APB_BLOCK_ADDR_IC_AGC, 0x04, 0x1244); - } else { - atv_dmd_wr_long(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x00040E0A); - atv_dmd_wr_word(APB_BLOCK_ADDR_IC_AGC, 0x04, 0x0D68); - } - - /*VAGC*/ - pr_info("ATV-DMD configure vagc\n"); - atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x48, 0x9B6F2C00); - /*bw select mode*/ - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x37, 0x1C); - /*disable prefilter*/ - - if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { - atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x44, 0x4450); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x46, 0x44); - atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x4, 0x3E04FC); - atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x3C, 0x4848); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x3E, 0x48); - } else { - atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x44, 0xB800); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x46, 0x08); - atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x4, 0x3C04FC); - atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x3C, 0x1818); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x3E, 0x10); - } - - /*tmp_real = $itor(Hz_Freq)/0.23841858; //TODO*/ - /*tmp_int = $rtoi(tmp_real); //TODO*/ - /*tmp_int = Hz_Freq/0.23841858; //TODO*/ - /*tmp_int_2 = ((unsigned long)15625)*10000/23841858;*/ - /*tmp_int_2 = ((unsigned long)Hz_Freq)*10000/23841858;*/ - atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x10, - (freq_hz_cvrt >> 8) & 0xffff); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x12, (freq_hz_cvrt & 0xff)); - - /*OUTPUT STAGE*/ - pr_info("ATV-DMD configure output stage\n"); - if (Broadcast_Standard != AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { - atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x0, 0x00); - atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x1, 0x40); - atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x2, 0x40); - atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x4, 0xFA); - atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x5, 0xFA); - } - - /*GDE FILTER*/ - pr_info("ATV-DMD configure gde filter\n"); - if (GDE_Curve == 0) { - gd_coeff[0] = 0x020; /*12'sd32;*/ - gd_coeff[1] = 0xf5f; /*-12'sd161;*/ - gd_coeff[2] = 0x1fe; /*12'sd510;*/ - gd_coeff[3] = 0xc0b; /*-12'sd1013;*/ - gd_coeff[4] = 0x536; /*12'sd1334;*/ - gd_coeff[5] = 0xb34; /*-12'sd1228;*/ - gd_bypass = 0x1; - } else if (GDE_Curve == 1) { - gd_coeff[0] = 0x8; /*12'sd8;*/ - gd_coeff[1] = 0xfd5; /*-12'sd43;*/ - gd_coeff[2] = 0x8d; /*12'sd141;*/ - gd_coeff[3] = 0xe69; /*-12'sd407;*/ - gd_coeff[4] = 0x1f1; /*12'sd497;*/ - gd_coeff[5] = 0xe7e; /*-12'sd386;*/ - gd_bypass = 0x1; - } else if (GDE_Curve == 2) { - gd_coeff[0] = 0x35; /*12'sd53;*/ - gd_coeff[1] = 0xf41; /*-12'sd191;*/ - gd_coeff[2] = 0x68; /*12'sd104;*/ - gd_coeff[3] = 0xea5; /*-12'sd347;*/ - gd_coeff[4] = 0x322; /*12'sd802;*/ - gd_coeff[5] = 0x1bb; /*12'sd443;*/ - gd_bypass = 0x1; - } else if (GDE_Curve == 3) { - gd_coeff[0] = 0xf; /*12'sd15;*/ - gd_coeff[1] = 0xfb5; /*-12'sd75;*/ - gd_coeff[2] = 0xcc; /*12'sd204;*/ - gd_coeff[3] = 0xe51; - gd_coeff[4] = 0x226; /*12'sd550;*/ - gd_coeff[5] = 0xd02; - gd_bypass = 0x1; - } else - gd_bypass = 0x0; - - if (gd_bypass == 0x0) - atv_dmd_wr_byte(APB_BLOCK_ADDR_GDE_EQUAL, 0x0D, gd_bypass); - else { - for (i = 0; i < 6; i = i + 1) - atv_dmd_wr_word(APB_BLOCK_ADDR_GDE_EQUAL, i << 1, - gd_coeff[i]); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GDE_EQUAL, 0x0C, 0x01); - atv_dmd_wr_byte(APB_BLOCK_ADDR_GDE_EQUAL, 0x0D, gd_bypass); - } - - /*PWM*/ - pr_info("ATV-DMD configure pwm\n"); - atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x00, 0x1f40); /*4KHz*/ - atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x04, 0xc8); - /*26 dB dynamic range*/ - atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0xa); - if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_R840) { - /*config pwm for tuner r840*/ - atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0, 0xc80); - /* guanzhong for Tuner AGC shock */ - atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46180200); - /* atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_SE,1,0xf);//Kd = 0xf */ - } -} - -void retrieve_adc_power(int *adc_level) -{ - *adc_level = atv_dmd_rd_long(APB_BLOCK_ADDR_ADC_SE, 0x0c); - /*adc_level = adc_level/32768*100;*/ - *adc_level = (*adc_level) * 100 / 32768; -} - -void retrieve_vpll_carrier_lock(int *lock) -{ - unsigned int data; - - data = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x43); - *lock = (data & 0x1); -} -int retrieve_vpll_carrier_afc(void) -{ - int data_ret, pll_lock, field_lock, line_lock, line_lock_strong; - unsigned int data_h, data_l, data_exg = 0; - - pll_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x43)&0x1; - field_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f)&0x4; - line_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f)&0x10; - line_lock_strong = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f)&0x8; - /* if((atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY,0x43)&0x1) == 1){ */ - if ((pll_lock == 1) || (line_lock == 0x10)) { - /*if pll unlock, afc is invalid*/ - data_ret = 0xffff;/* 500; */ - return data_ret; - } - data_h = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x40); - data_l = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x41); - data_exg = ((data_h&0x7) << 8) | data_l; - if (data_h&0x8) { - data_ret = (((~data_exg)&0x7ff) - 1); - data_ret = data_ret*488*(-1)/1000; - } else { - data_ret = data_exg; - data_ret = data_ret*488/1000; - } - if ((abs(data_ret) < 50) && (line_lock_strong == 0x8) && - (field_lock == 0x4)) { - data_ret = 100; - return data_ret; - } - return data_ret; -} -void set_pll_lpf(unsigned int lock) -{ - atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x24, lock); -} - -void retrieve_frequency_offset(int *freq_offset) -{ - /*unsigned int data; - *data = atv_dmd_rd_word(APB_BLOCK_ADDR_CARR_RCVY,0x40); - **freq_offset = (int)data; - */ - unsigned int data_h, data_l, data_exg; - int data_ret; - - data_h = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x40); - data_l = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x41); - data_exg = ((data_h&0x7)<<8) | data_l; - if (data_h&0x8) { - data_ret = (((~data_exg) & 0x7ff) - 1); - data_ret = data_ret*(-1); - /* data_ret = data_ret*488*(-1) /1000; */ - } else - data_ret = data_exg;/* data_ret = data_ret*488/100; */ - *freq_offset = data_ret; -} -EXPORT_SYMBOL(retrieve_frequency_offset); -void retrieve_video_lock(int *lock) -{ - unsigned int data, wlock, slock; - - data = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); - wlock = data & 0x10; - slock = data & 0x80; - *lock = wlock & slock; -} - -void retrieve_fh_frequency(int *fh) -{ - unsigned long data1, data2; - - data1 = atv_dmd_rd_word(APB_BLOCK_ADDR_VDAGC, 0x58); - data2 = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x10); - data1 = data1 >> 11; - data2 = data2 >> 3; - *fh = data1 + data2; -} -/*tune mix to adapt afc*/ -void atvdemod_afc_tune(void) -{ - /* int adc_level,lock,freq_offset,fh; */ - int freq_offset, lock, mix1_freq_cur, delta_mix1_freq; - - /* retrieve_adc_power(&adc_level); */ - /* pr_info("adc_level: 0x%x\n",adc_level); */ - retrieve_vpll_carrier_lock(&lock); - mix1_freq_cur = atv_dmd_rd_byte(APB_BLOCK_ADDR_MIXER_1, 0x0); - delta_mix1_freq = abs(mix1_freq_cur - mix1_freq); - if ((lock&0x1) == 0) - pr_info("%s visual carrier lock:locked\n", __func__); - else - pr_info("%s visual carrier lock:unlocked\n", __func__); - /* set_pll_lpf(lock); */ - retrieve_frequency_offset(&freq_offset); - freq_offset = freq_offset*488/1000; - /* pr_info("visual carrier offset:%d Hz\n", - *freq_offset*48828125/100000); - */ - /* retrieve_video_lock(&lock); */ - if ((lock&0x1) == 1) { - if (delta_mix1_freq == atvdemod_afc_range) - atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, mix1_freq); - else if ((freq_offset >= atvdemod_afc_offset) && - (delta_mix1_freq < atvdemod_afc_range)) - atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, - mix1_freq_cur-1); - else if ((freq_offset <= (-1)*atvdemod_afc_offset) && - (delta_mix1_freq < atvdemod_afc_range-1)) - atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, - mix1_freq_cur+1); - /* pr_info("video lock:locked\n"); */ - } - /* retrieve_fh_frequency(&fh); */ - /* pr_info("horizontal frequency:%d Hz\n",fh*190735/100000); */ -} -static enum amlatvdemod_snr_level_e aml_atvdemod_get_snr_level(void) -{ - unsigned int snr_val, i, snr_d[8]; - enum amlatvdemod_snr_level_e ret; - unsigned long fsnr; - - snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50)>>8; - fsnr = snr_val; - for (i = 1; i < 8; i++) { - snr_d[i] = snr_d[i-1]; - fsnr = fsnr + snr_d[i]; - } - snr_d[0] = snr_val; - fsnr = fsnr >> 3; - if (fsnr < 316) - ret = high; - else if (fsnr < 31600) - ret = ok_plus; - else if (fsnr < 158000) - ret = ok_minus; - else if (fsnr < 700000) - ret = low; - else - ret = very_low; - return ret; -} - -void atvdemod_monitor_serice(void) -{ - enum amlatvdemod_snr_level_e snr_level; - unsigned int vagc_bw_typ, vagc_bw_fast, vpll_kptrack, vpll_kitrack; - unsigned int agc_register, vfmat_reg, agc_pll_kptrack, agc_pll_kitrack; - /*1.get current snr*/ - snr_level = aml_atvdemod_get_snr_level(); - /*2.*/ - if (snr_level > very_low) { - vagc_bw_typ = 0x1818; - vagc_bw_fast = (snr_level == low) ? 0x18:0x10; - vpll_kptrack = 0x05; - vpll_kitrack = 0x0c; - agc_pll_kptrack = 0x6; - agc_pll_kitrack = 0xc; - } else { - vagc_bw_typ = 0x6f6f; - vagc_bw_fast = 0x6f; - vpll_kptrack = 0x06; - vpll_kitrack = 0x0e; - agc_pll_kptrack = 0x8; - agc_pll_kitrack = 0xf; - } - atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x3c, vagc_bw_typ); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x3e, vagc_bw_fast); - atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x23, vpll_kptrack); - atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x24, vpll_kitrack); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x0c, - ((atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x0c) & 0xf0)| - agc_pll_kptrack)); - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x0d, - ((atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x0d) & 0xf0)| - agc_pll_kitrack)); - /*3.*/ - agc_register = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x28); - if (snr_level < low) { - agc_register = ((agc_register&0xff80fe03) | (25 << 16) | - (15 << 2)); - atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x28, agc_register); - } else if (snr_level > low) { - agc_register = ((agc_register&0xff80fe03) | (38 << 16) | - (30 << 2)); - atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x28, agc_register); - } - /*4.*/ - if (snr_level < ok_minus) - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x47, - (atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x47) & 0x7f)); - else - atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x47, - (atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x47) | 0x80)); - /*5.vformat*/ - if (snr_level < ok_minus) { - if (atv_dmd_rd_byte(APB_BLOCK_ADDR_VFORMAT, 0xe) != 0xf) - atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, 0xf); - } else if (snr_level > ok_minus) { - vfmat_reg = atv_dmd_rd_word(APB_BLOCK_ADDR_VFORMAT, 0x16); - if ((vfmat_reg << 4) < 0xf000) { - if (atv_dmd_rd_byte(APB_BLOCK_ADDR_VFORMAT, 0xe) == - 0x0f) - atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, - 0x6); - else - atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, - 0x6); - } - } else { - if (atv_dmd_rd_byte(APB_BLOCK_ADDR_VFORMAT, 0xe) == 0x0f) - atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, 0xe); - else - atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, 0xe); - } -} - -static int atvdemod_get_snr(struct dvb_frontend *fe) -{ - unsigned int snr_val = 0; - int ret = 0; - - snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; - /* snr_val:900000~0xffffff,ret:5~15 */ - if (snr_val > 900000) - ret = 15 - (snr_val - 900000)*10/(0xffffff - 900000); - /* snr_val:158000~900000,ret:15~30 */ - else if (snr_val > 158000) - ret = 30 - (snr_val - 158000)*15/(900000 - 158000); - /* snr_val:31600~158000,ret:30~50 */ - else if (snr_val > 31600) - ret = 50 - (snr_val - 31600)*20/(158000 - 31600); - /* snr_val:316~31600,ret:50~80 */ - else if (snr_val > 316) - ret = 80 - (snr_val - 316)*30/(31600 - 316); - /* snr_val:0~316,ret:80~100 */ - else - ret = 100 - (316 - snr_val)*20/316; - return ret; -} - -void atvdemod_det_snr_serice(void) -{ - snr_val = atvdemod_get_snr(NULL); -} - -void atvdemod_timer_handler(unsigned long arg) -{ - if (atvdemod_timer_en == 0) - return; - atvdemod_timer.expires = jiffies + ATVDEMOD_INTERVAL*10;/*100ms timer*/ - add_timer(&atvdemod_timer); - if (atvdemod_afc_en) - atvdemod_afc_tune(); - if (atvdemod_monitor_en) - atvdemod_monitor_serice(); - if (audio_det_en) - aml_atvdemod_overmodule_det(); - if (atvdemod_det_snr_en) - atvdemod_det_snr_serice(); -} - -int atvdemod_clk_init(void) -{ - /* clocks_set_hdtv (); */ - /* 1.set system clock */ -#if 0 /* now set pll in tvafe_general.c */ - if (is_meson_txl_cpu()) { - amlatvdemod_hiu_reg_write(HHI_VDAC_CNTL0, 0x6e0201); - amlatvdemod_hiu_reg_write(HHI_VDAC_CNTL1, 0x8); - /* for TXL(T962) */ - pr_err("%s in TXL\n", __func__); - - /* W_HIU_REG(HHI_ADC_PLL_CNTL, 0x30c54260); */ - #if 0 - W_HIU_REG(HHI_ADC_PLL_CNTL, 0x30f14250); - W_HIU_REG(HHI_ADC_PLL_CNTL1, 0x22000442); - W_HIU_REG(HHI_ADC_PLL_CNTL2, 0x5ba00380); - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xac6a2114); - W_HIU_REG(HHI_ADC_PLL_CNTL4, 0x02953004); - W_HIU_REG(HHI_ADC_PLL_CNTL5, 0x00030a00); - W_HIU_REG(HHI_ADC_PLL_CNTL6, 0x00005000); - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x2c6a2114); - #else /* get from feijun 2015/07/19 */ - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); - W_HIU_REG(HHI_ADC_PLL_CNTL, 0x30f14250); - W_HIU_REG(HHI_ADC_PLL_CNTL1, 0x22000442); - /*0x5ba00380 from pll;0x5ba00384 clk - *form crystal - */ - W_HIU_REG(HHI_ADC_PLL_CNTL2, 0x5ba00384); - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); - W_HIU_REG(HHI_ADC_PLL_CNTL4, 0x02913004); - W_HIU_REG(HHI_ADC_PLL_CNTL5, 0x00034a00); - W_HIU_REG(HHI_ADC_PLL_CNTL6, 0x00005000); - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xca6a2110); - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); - #endif - W_HIU_REG(HHI_DADC_CNTL, 0x00102038); - W_HIU_REG(HHI_DADC_CNTL2, 0x00000406); - W_HIU_REG(HHI_DADC_CNTL3, 0x00082183); - - } else { - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xca2a2110); - W_HIU_REG(HHI_ADC_PLL_CNTL4, 0x2933800); - W_HIU_REG(HHI_ADC_PLL_CNTL, 0xe0644220); - W_HIU_REG(HHI_ADC_PLL_CNTL2, 0x34e0bf84); - W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a2a2110); - - W_HIU_REG(HHI_ATV_DMD_SYS_CLK_CNTL, 0x80); - /* TVFE reset */ - W_HIU_BIT(RESET1_REGISTER, 1, 7, 1); - } -#endif - W_HIU_REG(HHI_ATV_DMD_SYS_CLK_CNTL, 0x80); - - /* read_version_register(); */ - - /*2.set atv demod top page control register*/ - atv_dmd_input_clk_32m(); - atv_dmd_wr_long(APB_BLOCK_ADDR_TOP, ATV_DMD_TOP_CTRL, 0x1037); - atv_dmd_wr_long(APB_BLOCK_ADDR_TOP, (ATV_DMD_TOP_CTRL1 << 2), 0x1f); - - /*3.configure atv demod*/ - check_communication_interface(); - power_on_receiver(); - pr_err("%s done\n", __func__); - - return 0; -} - -int atvdemod_init(void) -{ - /* unsigned long data32; */ - if (atvdemod_timer_en == 1) { - if (timer_init_flag == 1) { - del_timer_sync(&atvdemod_timer); - timer_init_flag = 0; - } - } - - /* 1.set system clock when atv enter*/ - - configure_receiver(broad_std, if_freq, if_inv, gde_curve, sound_format); - atv_dmd_misc(); - /*4.software reset*/ - atv_dmd_soft_reset(); - atv_dmd_soft_reset(); - atv_dmd_soft_reset(); - atv_dmd_soft_reset(); - - /* ????? - *while (!all_lock) { - * data32 = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC,0x13<<2); - * if ((data32 & 0x1c) == 0x0) { - * all_lock = 1; - * } - * delay_us(400); - *} - */ - #if 1/* temp mark */ - if (atvdemod_timer_en == 1) { - /*atvdemod timer handler*/ - init_timer(&atvdemod_timer); - /* atvdemod_timer.data = (ulong) devp; */ - atvdemod_timer.function = atvdemod_timer_handler; - /* after 3s enable demod auto detect */ - atvdemod_timer.expires = jiffies + ATVDEMOD_INTERVAL*300; - add_timer(&atvdemod_timer); - mix1_freq = atv_dmd_rd_byte(APB_BLOCK_ADDR_MIXER_1, 0x0); - timer_init_flag = 1; - } - #endif - pr_info("%s done\n", __func__); - return 0; -} -void atvdemod_uninit(void) -{ - /* del the timer */ - if (atvdemod_timer_en == 1) { - if (timer_init_flag == 1) { - del_timer_sync(&atvdemod_timer); - timer_init_flag = 0; - } - } -} - -void atv_dmd_set_std(void) -{ - v4l2_std_id ptstd = amlatvdemod_devp->parm.std; - /* set broad standard of tuner*/ - if ((ptstd & V4L2_COLOR_STD_PAL) && ((ptstd & V4L2_STD_B) || - (ptstd & V4L2_STD_G))) { - amlatvdemod_devp->fre_offset = 2250000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; - if_freq = 3250000; - gde_curve = 2; - } else if ((ptstd & V4L2_COLOR_STD_PAL) && (ptstd & V4L2_STD_DK)) { - amlatvdemod_devp->fre_offset = 2250000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; - if_freq = 3250000; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; - gde_curve = 3; - } else if ((ptstd & V4L2_COLOR_STD_PAL) && (ptstd & V4L2_STD_PAL_M)) { - amlatvdemod_devp->fre_offset = 2250000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; - if_freq = 4250000; - gde_curve = 0; - } else if ((ptstd & V4L2_COLOR_STD_NTSC) && (ptstd & V4L2_STD_NTSC_M)) { - amlatvdemod_devp->fre_offset = 1750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; - if_freq = 4250000; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC; - gde_curve = 0; - } else if ((ptstd & V4L2_COLOR_STD_NTSC) && (ptstd & V4L2_STD_DK)) { - amlatvdemod_devp->fre_offset = 1750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; - if_freq = 4250000; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK; - gde_curve = 0; - } else if ((ptstd & V4L2_COLOR_STD_NTSC) && (ptstd & V4L2_STD_BG)) { - amlatvdemod_devp->fre_offset = 1750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; - if_freq = 4250000; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG; - gde_curve = 0; - } else if ((ptstd & V4L2_COLOR_STD_NTSC) && (ptstd & V4L2_STD_PAL_I)) { - amlatvdemod_devp->fre_offset = 1750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; - if_freq = 4250000; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I; - gde_curve = 0; - } else if ((ptstd & V4L2_COLOR_STD_NTSC) && - (ptstd & V4L2_STD_NTSC_M_JP)) { - amlatvdemod_devp->fre_offset = 1750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J; - if_freq = 4250000; - gde_curve = 0; - } else if ((ptstd & V4L2_COLOR_STD_PAL) && (ptstd & V4L2_STD_PAL_I)) { - amlatvdemod_devp->fre_offset = 2750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; - if_freq = 3250000; - gde_curve = 4; - } else if (ptstd & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { - amlatvdemod_devp->fre_offset = 2750000; - freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L; - gde_curve = 4; - } - if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_R840) { - if_freq = amlatvdemod_devp->parm.if_freq; - if_inv = amlatvdemod_devp->parm.if_inv; - } else if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_MXL661) { - if_freq = amlatvdemod_devp->parm.if_freq; - if_inv = amlatvdemod_devp->parm.if_inv; - } else if (amlatvdemod_devp->parm.tuner_id == AM_TUNER_SI2151) { - if_freq = amlatvdemod_devp->parm.if_freq; - if_inv = amlatvdemod_devp->parm.if_inv; - } - pr_info - ("[atvdemod..]%s: broad_std %d,freq_hz_cvrt:0x%x,fre_offset:%d.\n", - __func__, broad_std, freq_hz_cvrt, amlatvdemod_devp->fre_offset); - if (atvdemod_init()) - pr_info("[atvdemod..]%s: atv restart error.\n", __func__); -} - -int aml_audiomode_autodet(struct dvb_frontend *fe) -{ - unsigned long carrier_power = 0; - unsigned long carrier_power_max = 0; - unsigned long carrier_power_average_max = 0; - unsigned long carrier_power_average[4] = {0}; - unsigned long reg_addr = 0x03, temp_data; - int carrier_lock_count = 0; - int lock = 0; - int broad_std_final = 0; - int num = 0, i = 0, final_id = 0; - int delay_ms = 10, delay_ms_default = 10; - int cur_std = ID_PAL_DK; - struct dtv_frontend_properties - *p = fe != NULL ? &fe->dtv_property_cache:NULL; -#if 0 - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80;/* 0x40 */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); -#endif - - switch (broad_std) { - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: - - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M; - atvdemod_init(); - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data & (~0x80); /* 0xbf; */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ - return broad_std; - - case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2: - case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3: - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L; - atvdemod_init(); - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - - temp_data = temp_data & (~0x80); /* 0xbf; */ - - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ - return broad_std; - default: - pr_err("unsupport broadcast_standard!!!\n"); - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data & (~0x80); /* 0xbf; */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - return broad_std; - } - /* ----------------read carrier_power--------------------- */ - /* SIF_STG_2[0x09],address 0x03 */ - while (1) { - if (num >= 4) { - temp_data = - atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data & (~0x80); - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, - temp_data); - carrier_power_max = carrier_power_average[0]; - for (i = 0; i < ID_MAX; i++) { - if (carrier_power_max - < carrier_power_average[i]) { - carrier_power_max = - carrier_power_average[i]; - final_id = i; - } - } - switch (final_id) { - case ID_PAL_I: - broad_std_final = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; - break; - case ID_PAL_BG: - broad_std_final = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; - break; - case ID_PAL_M: - broad_std_final = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; - break; - case ID_PAL_DK: - broad_std_final = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; - break; - } - carrier_power_average_max = carrier_power_max; - broad_std = broad_std_final; - pr_err("%s:broad_std:%d,carrier_power_average_max:%lu\n", - __func__, broad_std, carrier_power_average_max); - if (carrier_power_average_max < 150) - pr_err("%s,carrier too low error\n", __func__); - if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) { - /*the max except palm*/ - carrier_power_average[final_id] = 0; - final_id = 0; - carrier_power_max = carrier_power_average[0]; - for (i = 0; i < ID_MAX; i++) { - if (carrier_power_max - < carrier_power_average[i]) { - carrier_power_max = - carrier_power_average[i]; - final_id = i; - } - } - switch (final_id) { - case ID_PAL_I: - broad_std_except_pal_m = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; - break; - case ID_PAL_BG: - broad_std_except_pal_m = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; - break; - case ID_PAL_DK: - broad_std_except_pal_m = - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; - break; - } - } - if (p != NULL) { - p->analog.std = V4L2_COLOR_STD_PAL; - switch (broad_std) { - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: - p->analog.std |= V4L2_STD_PAL_DK; - p->analog.audmode = V4L2_STD_PAL_DK; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: - p->analog.std |= V4L2_STD_PAL_I; - p->analog.audmode = V4L2_STD_PAL_I; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: - p->analog.std |= V4L2_STD_PAL_BG; - p->analog.audmode = V4L2_STD_PAL_BG; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: - p->analog.std |= V4L2_STD_PAL_M; - p->analog.audmode = V4L2_STD_PAL_M; - break; - default: - p->analog.std |= V4L2_STD_PAL_DK; - p->analog.audmode = V4L2_STD_PAL_DK; - } - p->frequency += 1; - fe->ops.set_frontend(fe); - } - return broad_std; - } - switch (broad_std) { - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; - cur_std = ID_PAL_I; - if (p != NULL) { - p->analog.std = - V4L2_COLOR_STD_PAL | V4L2_STD_PAL_I; - p->frequency += 1; - p->analog.audmode = V4L2_STD_PAL_I; - } - delay_ms = delay_ms_default; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; - cur_std = ID_PAL_BG; - if (p != NULL) { - p->analog.std = - V4L2_COLOR_STD_PAL | V4L2_STD_PAL_BG; - p->frequency += 1; - p->analog.audmode = V4L2_STD_PAL_BG; - } - delay_ms = delay_ms_default; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; - cur_std = ID_PAL_M; - if (p != NULL) { - p->analog.std = - V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M; - p->frequency += 1; - p->analog.audmode = V4L2_STD_PAL_M; - } - delay_ms = delay_ms_default; - break; - case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; - cur_std = ID_PAL_DK; - if (p != NULL) { - p->analog.std = - V4L2_COLOR_STD_PAL | V4L2_STD_PAL_DK; - p->frequency += 1; - p->analog.audmode = V4L2_STD_PAL_DK; - } - delay_ms = delay_ms_default; - break; - - default: - pr_err("unsupport broadcast_standard!!!\n"); - break; - } - if (p != NULL) - fe->ops.set_frontend(fe); - /* atvdemod_init(); //set_frontend has already been called it */ - - /* enable audio detect function */ - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80;/* 0x40 */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - - usleep_range(delay_ms*1000, delay_ms*1000+100); - - carrier_lock_count = 0; - i = 4; - while (i--) { - retrieve_vpll_carrier_lock(&lock); - if (lock == 0) - break; - carrier_lock_count++; - if (carrier_lock_count >= 20) { - pr_err("%s step2, retrieve_vpll_carrier_lock failed\n", - __func__); - /* return broad_std; */ - } - usleep_range(6000, 9000); - } - /* ----------------read carrier_power--------------------- */ - for (i = 0; i < 100; i++) { - carrier_power = - atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, - reg_addr); - carrier_power_max += carrier_power; - } - carrier_power = carrier_power_max/i; - carrier_power_max = 0; - pr_err("[amlatvdemod.. %d,std:%d ]%s: atvdemo audio carrier power report:%lu. @@@@@@@@@@\n", - num, broad_std, __func__, carrier_power); - carrier_power_average[cur_std] += carrier_power; - num++; - } - - return broad_std; -} - -void aml_audio_valume_gain_set(unsigned int audio_gain) -{ - unsigned long audio_gain_data, temp_data; - - if (audio_gain > 0xfff) { - pr_err("Error: atv in gain max 7.998, min 0.002! gain = value/512\n"); - pr_err("value (0~0xfff)\n"); - return; - } - audio_gain_data = audio_gain & 0xfff; - temp_data = atv_dmd_rd_word(APB_BLOCK_ADDR_MONO_PROC, 0x52); - temp_data = (temp_data & 0xf000) | audio_gain_data; - atv_dmd_wr_word(APB_BLOCK_ADDR_MONO_PROC, 0x52, temp_data); -} - -unsigned int aml_audio_valume_gain_get(void) -{ - unsigned long audio_gain_data; - - audio_gain_data = atv_dmd_rd_word(APB_BLOCK_ADDR_MONO_PROC, 0x52); - audio_gain_data = audio_gain_data & 0xfff; - return audio_gain_data; -} - -void aml_atvdemod_overmodule_det(void) -{ - unsigned long temp_data, temp_data2;/* , temp_data3 , temp_data4; */ - unsigned long counter_report; - int carrier_lock_count = 0; - int vlock = 0; - - switch (audio_det_mode) { - case AUDIO_AUTO_DETECT: - aml_audiomode_autodet(NULL); - return; -#if 0 - while (1) { - retrieve_vpll_carrier_lock(&vlock); - if (vlock) - break; - carrier_lock_count++; - if (carrier_lock_count >= 1000) - return; - /* ------------whether need timer delays between the detect lock---- */ - } - /* -----------------enable auto_adjust_en------------- */ - temp_data = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x100; - /* set the bit 9 of the temp_data to 1 */ - atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - /* -----------------enable auto_adjust_en end----------------- */ - /* -----------------begain to set ov_cnt_en enable------------- */ - temp_data2 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data2 = temp_data2 | 0x80; - /* set the bit 8 of the temp_data to 1 */ - atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data2); - /* ------------------set ov_cnt_en enable end---------------- */ - udelay(1000);/* timer delay needed , */ - /* ------------------------------------------------------------ */ - /* -----------------disable auto_adjust_en------------- */ - temp_data3 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data3 = temp_data3 & 0xfeff; - /* set the bit 9 of the temp_data to 0 */ - atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data3); - /* -----------------disable auto_adjust_en end------------ */ - /* -----------------begain to set ov_cnt_en disable------------- */ - temp_data4 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data4 = temp_data4 & 0xff7f; - /* set the bit 8 of the temp_data to 0 */ - atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data4); - break; - /* ------------------set ov_cnt_en disable end------ */ -#endif - case AUDIO_MANUAL_DETECT: - while (1) { - retrieve_vpll_carrier_lock(&vlock); - if (vlock) - break; - carrier_lock_count++; - if (carrier_lock_count >= 1000) - return; - } - - /* -----------------begain to set ov_cnt_en enable---- */ - temp_data = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80; - /* set the bit 8 of the temp_data to 1 */ - atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - /* ------------------set ov_cnt_en enable end--------------- */ - /* -----------------disable auto_adjust_en------------- */ - temp_data2 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data2 = temp_data2 & 0xfeff; - /* set the bit 9 of the temp_data to 0 */ - atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data2); - /* -----------------disable auto_adjust_en end------------ */ - udelay(1000);/* timer delay needed , */ - /* ------------------------------------------------------- */ - counter_report = - atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x04); - - while (counter_report > over_threshold) { - unsigned long shift_gain, shift_gain_report; - - temp_data2 = atv_dmd_rd_byte( - APB_BLOCK_ADDR_SIF_STG_2, 0x00); - shift_gain = temp_data2 & 0x07; - shift_gain--; - temp_data2 = (temp_data2 & 0xf8) | shift_gain; - atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x00, - temp_data2); - shift_gain_report = ( - (atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x04) - & 0x00070000) >> 16); - if (shift_gain_report != shift_gain) - pr_info("[atvdemo...]:set shift_gain error\n"); - /* ------------------timer delay needed- */ - udelay(1000);/* timer delay needed , */ - /* ----------------------- */ - counter_report = - atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x04); - } - break; - default: - pr_info("invalid over_module_det mode!!!\n"); - break; - } -} - -void aml_fix_PWM_adjust(int enable) -{ - unsigned long temp_data; - /* - *temp_data = atv_dmd_rd_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08); - *temp_data = temp_data | 0x01; - *atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08, temp_data); - */ - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - if (enable) - temp_data = temp_data & ~((0x3)<<8); - else - temp_data = temp_data & ~((0x1)<<9); - - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - if (enable) { - temp_data = temp_data | ((0x3)<<8); - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - } -} - -void aml_audio_overmodulation(int enable) -{ - static int ov_flag; - unsigned long tmp_v; - unsigned long tmp_v1; - u32 Broadcast_Standard = broad_std; - - if (enable && Broadcast_Standard == - AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) { - tmp_v = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x28); - tmp_v = tmp_v&0xffff; - if (tmp_v >= 0x10 && ov_flag == 0) { - tmp_v1 = - atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); - tmp_v1 = (tmp_v1&0xffffff)|(1<<24); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x14, 0x8000015); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x1c, 0x0f000); - } else if (tmp_v >= 0x2500 && ov_flag == 0) { - tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); - tmp_v1 = (tmp_v1&0xffffff)|(1<<24); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x14, 0xf400015); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x18, 0xc000); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x1c, 0x0f000); - ov_flag = 1; - } else if (tmp_v <= 0x10 && ov_flag == 1) { - tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); - tmp_v1 = (tmp_v1&0xffffff)|(0<<24); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x14, 0xf400000); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x18, 0xc000); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x1c, 0x1f000); - ov_flag = 0; - } - } -} - diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.h deleted file mode 100644 index 807239206f8f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/atv_demod/atvdemod_func.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * ATVDEMOD Device Driver - * - * Author: dezhi kong - * - * - * Copyright (C) 2014 Amlogic Inc. - * - * 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. - */ - -#ifndef __ATVDEMOD_FUN_H -#define __ATVDEMOD_FUN_H - -/*#include "../aml_fe.h"*/ -#include -#include "../aml_fe.h" -#include - -/*#define TVFE_APB_BASE_ADDR 0xd0046000*/ -#define ATV_DMD_APB_BASE_ADDR 0xc8008000 -#define ATV_DMD_APB_BASE_ADDR_GXTVBB 0xc8840000 - -#define HHI_ATV_DMD_SYS_CLK_CNTL 0x10f3 - -extern int atvdemod_debug_en; -extern struct amlatvdemod_device_s *amlatvdemod_devp; -extern unsigned int reg_23cf; /* IIR filter */ -extern int broad_std_except_pal_m; -#undef pr_info -#define pr_info(args...)\ - do {\ - if (atvdemod_debug_en)\ - printk(args);\ - } while (0) -#undef pr_dbg -#define pr_dbg(a...) \ - do {\ - if (1)\ - printk(a);\ - } while (0) - -#define ATVDEMOD_INTERVAL (HZ/100) /*10ms, #define HZ 100*/ - -extern int amlatvdemod_reg_read(unsigned int reg, unsigned int *val); -extern int amlatvdemod_reg_write(unsigned int reg, unsigned int val); -extern int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val); -extern int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val); - -static inline uint32_t R_ATVDEMOD_REG(uint32_t reg) -{ - unsigned int val; - - amlatvdemod_reg_read(reg, &val); - return val; -} - -static inline void W_ATVDEMOD_REG(uint32_t reg, - const uint32_t val) -{ - amlatvdemod_reg_write(reg, val); -} - -static inline void W_ATVDEMOD_BIT(uint32_t reg, - const uint32_t value, - const uint32_t start, - const uint32_t len) -{ - W_ATVDEMOD_REG(reg, ((R_ATVDEMOD_REG(reg) & - ~(((1L << (len)) - 1) << (start))) | - (((value) & ((1L << (len)) - 1)) << (start)))); -} - -static inline uint32_t R_ATVDEMOD_BIT(uint32_t reg, - const uint32_t start, - const uint32_t len) -{ - uint32_t val; - - val = ((R_ATVDEMOD_REG(reg) >> (start)) & ((1L << (len)) - 1)); - - return val; -} - -static inline uint32_t R_HIU_REG(uint32_t reg) -{ - unsigned int val; - - amlatvdemod_hiu_reg_read(reg, &val); - return val; -} - -static inline void W_HIU_REG(uint32_t reg, - const uint32_t val) -{ - amlatvdemod_hiu_reg_write(reg, val); -} - -static inline void W_HIU_BIT(uint32_t reg, - const uint32_t value, - const uint32_t start, - const uint32_t len) -{ - W_HIU_REG(reg, ((R_HIU_REG(reg) & - ~(((1L << (len)) - 1) << (start))) | - (((value) & ((1L << (len)) - 1)) << (start)))); -} - -static inline uint32_t R_HIU_BIT(uint32_t reg, - const uint32_t start, - const uint32_t len) -{ - uint32_t val; - - val = ((R_HIU_REG(reg) >> (start)) & ((1L << (len)) - 1)); - - return val; -} - -enum broadcast_standard_e { - ATVDEMOD_STD_NTSC = 0, - ATVDEMOD_STD_NTSC_J, - ATVDEMOD_STD_PAL_M, - ATVDEMOD_STD_PAL_BG, - ATVDEMOD_STD_DTV, - ATVDEMOD_STD_SECAM_DK2, - ATVDEMOD_STD_SECAM_DK3, - ATVDEMOD_STD_PAL_BG_NICAM, - ATVDEMOD_STD_PAL_DK_CHINA, - ATVDEMOD_STD_SECAM_L, - ATVDEMOD_STD_PAL_I, - ATVDEMOD_STD_PAL_DK1, - ATVDEMOD_STD_MAX, -}; -enum gde_curve_e { - ATVDEMOD_CURVE_M = 0, - ATVDEMOD_CURVE_A, - ATVDEMOD_CURVE_B, - ATVDEMOD_CURVE_CHINA, - ATVDEMOD_CURVE_MAX, -}; -enum sound_format_e { - ATVDEMOD_SOUND_STD_MONO = 0, - ATVDEMOD_SOUND_STD_NICAM, - ATVDEMOD_SOUND_STD_MAX, -}; -extern void atv_dmd_wr_reg(unsigned char block, unsigned char reg, - unsigned long data); -extern unsigned long atv_dmd_rd_reg(unsigned char block, unsigned char reg); -extern unsigned long atv_dmd_rd_byte(unsigned long block_address, - unsigned long reg_addr); -extern unsigned long atv_dmd_rd_word(unsigned long block_address, - unsigned long reg_addr); -extern unsigned long atv_dmd_rd_long(unsigned long block_address, - unsigned long reg_addr); -extern void atv_dmd_wr_long(unsigned long block_address, - unsigned long reg_addr, - unsigned long data); -extern void atv_dmd_wr_word(unsigned long block_address, - unsigned long reg_addr, - unsigned long data); -extern void atv_dmd_wr_byte(unsigned long block_address, - unsigned long reg_addr, - unsigned long data); -extern void set_audio_gain_val(int val); -extern void set_video_gain_val(int val); -extern void atv_dmd_soft_reset(void); -extern void atv_dmd_input_clk_32m(void); -extern void read_version_register(void); -extern void check_communication_interface(void); -extern void power_on_receiver(void); -extern void atv_dmd_misc(void); -extern void configure_receiver(int Broadcast_Standard, - unsigned int Tuner_IF_Frequency, - int Tuner_Input_IF_inverted, int GDE_Curve, - int sound_format); -extern int atvdemod_clk_init(void); -extern int atvdemod_init(void); -extern void atvdemod_uninit(void); -extern void atv_dmd_set_std(void); -extern void retrieve_vpll_carrier_lock(int *lock); -extern void retrieve_video_lock(int *lock); -extern int retrieve_vpll_carrier_afc(void); - -extern int get_atvdemod_snr_val(void); -extern int aml_atvdemod_get_snr(struct dvb_frontend *fe); - -/*atv demod block address*/ -/*address interval is 4, because it's 32bit interface, - * but the address is in byte - */ -#define ATV_DMD_TOP_CTRL 0x0 -#define ATV_DMD_TOP_CTRL1 0x4 -#define ATV_DMD_RST_CTRL 0x8 - -#define APB_BLOCK_ADDR_SYSTEM_MGT 0x0 -#define APB_BLOCK_ADDR_AA_LP_NOTCH 0x1 -#define APB_BLOCK_ADDR_MIXER_1 0x2 -#define APB_BLOCK_ADDR_MIXER_3 0x3 -#define APB_BLOCK_ADDR_ADC_SE 0x4 -#define APB_BLOCK_ADDR_PWR_ANL 0x5 -#define APB_BLOCK_ADDR_CARR_RCVY 0x6 -#define APB_BLOCK_ADDR_FE_DROOP_MDF 0x7 -#define APB_BLOCK_ADDR_SIF_IC_STD 0x8 -#define APB_BLOCK_ADDR_SIF_STG_2 0x9 -#define APB_BLOCK_ADDR_SIF_STG_3 0xa -#define APB_BLOCK_ADDR_IC_AGC 0xb -#define APB_BLOCK_ADDR_DAC_UPS 0xc -#define APB_BLOCK_ADDR_GDE_EQUAL 0xd -#define APB_BLOCK_ADDR_VFORMAT 0xe -#define APB_BLOCK_ADDR_VDAGC 0xf -#define APB_BLOCK_ADDR_VERS_REGISTER 0x10 -#define APB_BLOCK_ADDR_INTERPT_MGT 0x11 -#define APB_BLOCK_ADDR_ADC_MGR 0x12 -#define APB_BLOCK_ADDR_GP_VD_FLT 0x13 -#define APB_BLOCK_ADDR_CARR_DMD 0x14 -#define APB_BLOCK_ADDR_SIF_VD_IF 0x15 -#define APB_BLOCK_ADDR_VD_PKING 0x16 -#define APB_BLOCK_ADDR_FE_DR_SMOOTH 0x17 -#define APB_BLOCK_ADDR_AGC_PWM 0x18 -#define APB_BLOCK_ADDR_DAC_UPS_24M 0x19 -#define APB_BLOCK_ADDR_VFORMAT_DP 0x1a -#define APB_BLOCK_ADDR_VD_PKING_DAC 0x1b -#define APB_BLOCK_ADDR_MONO_PROC 0x1c -#define APB_BLOCK_ADDR_TOP 0x1d - -#define SLAVE_BLOCKS_NUMBER 0x1d /*indeed totals 0x1e, adding top*/ - -/*Broadcast_Standard*/ -/* 0: NTSC*/ -/* 1: NTSC-J*/ -/* 2: PAL-M,*/ -/* 3: PAL-BG*/ -/* 4: DTV*/ -/* 5: SECAM- DK2*/ -/* 6: SECAM -DK3*/ -/* 7: PAL-BG, NICAM*/ -/* 8: PAL-DK-CHINA*/ -/* 9: SECAM-L / SECAM-DK3*/ -/* 10: PAL-I*/ -/* 11: PAL-DK1*/ -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC 0 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J 1 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M 2 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG 3 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV 4 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2 5 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3 6 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG_NICAM 7 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK 8 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L 9 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I 10 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK1 11 -/* new add @20150813 begin */ -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK 12 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG 13 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I 14 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M 15 -/* new add @20150813 end */ - -/*GDE_Curve*/ -/* 0: CURVE-M*/ -/* 1: CURVE-A*/ -/* 2: CURVE-B*/ -/* 3: CURVE-CHINA*/ -/* 4: BYPASS*/ -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_M 0 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_A 1 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_B 2 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_CHINA 3 -#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_BYPASS 4 - -/*sound format 0: MONO;1:NICAM*/ -#define AML_ATV_DEMOD_SOUND_MODE_PROP_MONO 0 -#define AML_ATV_DEMOD_SOUND_MODE_PROP_NICAM 1 -/** - *freq_hz:hs_freq - *freq_hz_cvrt=hs_freq/0.23841858 - *vs_freq==50,freq_hz=15625;freq_hz_cvrt=0xffff - *vs_freq==60,freq_hz=15734,freq_hz_cvrt=0x101c9 - ** - */ -#define AML_ATV_DEMOD_FREQ_50HZ_VERT 0xffff /*65535*/ -#define AML_ATV_DEMOD_FREQ_60HZ_VERT 0x101c9 /*65993*/ - -#define CARR_AFC_DEFAULT_VAL 0xffff - -enum amlatvdemod_snr_level_e { - very_low = 1, - low, - ok_minus, - ok_plus, - high, -}; - -enum audio_detect_mode { - AUDIO_AUTO_DETECT = 0, - AUDIO_MANUAL_DETECT, -}; - -struct amlatvdemod_device_s { - struct class *clsp; - struct device *dev; - struct analog_parameters parm; - int fre_offset; - struct pinctrl *pin; - const char *pin_name; -}; - -extern void aml_audio_overmodulation(int enable); -extern void amlatvdemod_set_std(int val); -extern struct amlatvdemod_device_s *amlatvdemod_devp; -extern void aml_fix_PWM_adjust(int enable); -extern void aml_audio_valume_gain_set(unsigned int audio_gain); -extern unsigned int aml_audio_valume_gain_get(void); -extern void aml_atvdemod_overmodule_det(void); -extern int aml_audiomode_autodet(struct dvb_frontend *fe); -extern void retrieve_frequency_offset(int *freq_offset); -extern int aml_atvdemod_get_snr_ex(void); - -#endif /* __ATVDEMOD_FUN_H */ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c deleted file mode 100644 index 7ccdfae3e1a9..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c +++ /dev/null @@ -1,725 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* #include */ -#include -#include - -/* #include */ -#include -#include -#include "demod_func.h" - -#include -#ifdef CONFIG_COMPAT -#include -#endif -/*#include "sdio/sdio_init.h"*/ -#define DRIVER_NAME "aml_demod" -#define MODULE_NAME "aml_demod" -#define DEVICE_NAME "aml_demod" -#define DEVICE_UI_NAME "aml_demod_ui" - -#define pr_dbg(a ...) \ - do { \ - if (1) { \ - printk(a); \ - } \ - } while (0) - - -const char aml_demod_dev_id[] = "aml_demod"; - -/*#ifndef CONFIG_AM_DEMOD_DVBAPI - * static struct aml_demod_i2c demod_i2c; - * static struct aml_demod_sta demod_sta; - * #else - * extern struct aml_demod_i2c demod_i2c; - * extern struct aml_demod_sta demod_sta; - #endif -*/ - -static struct aml_demod_i2c demod_i2c; -static struct aml_demod_sta demod_sta; -static int read_start; - -int sdio_read_ddr(unsigned long sdio_addr, unsigned long byte_count, - unsigned char *data_buf) -{ - return 0; -} - -int sdio_write_ddr(unsigned long sdio_addr, unsigned long byte_count, - unsigned char *data_buf) -{ - return 0; -} - -int read_reg(int addr) -{ - addr = addr + DEMOD_BASE; - return apb_read_reg(addr); -} - -void wait_capture(int cap_cur_addr, int depth_MB, int start) -{ - int readfirst; - int tmp; - int time_out; - int last = 0x90000000; - - time_out = readfirst = 0; - tmp = depth_MB << 20; - while (tmp && (time_out < 1000)) { /*10seconds time out */ - time_out = time_out + 1; - msleep(20); - readfirst = app_apb_read_reg(cap_cur_addr); - if ((last - readfirst) > 0) - tmp = 0; - else - last = readfirst; - /* usleep(1000); */ - /* readsecond= app_apb_read_reg(cap_cur_addr); */ - - /* if((readsecond-start)>tmp) */ -/* tmp=0;*/ -/* if((readsecond-readfirst)<0) // turn around*/ -/* tmp=0;*/ - pr_dbg("First %x = [%08x],[%08x]%x\n", cap_cur_addr, readfirst, - last, (last - readfirst)); -/* printf("Second %x = [%08x]\n",cap_cur_addr, readsecond);*/ - msleep(20); - } - read_start = readfirst + 0x40000000; - pr_dbg("read_start is %x\n", read_start); -} - -int cap_adc_data(struct aml_cap_data *cap) -{ - int tmp; - int tb_depth; - - pr_dbg("capture ADC\n "); - /* printf("set mem_start (you can read in kernel start log - * (memstart is ).(hex) : "); - */ - /* scanf("%x",&tmp);*/ - tmp = 0x94400000; - app_apb_write_reg(0x9d, cap->cap_addr); - app_apb_write_reg(0x9e, cap->cap_addr + cap->cap_size * 0x100000); - /*0x8000000-128m, 0x400000-4m */ - read_start = tmp + 0x40000000; - /*printf("set afifo rate. (hex)(adc_clk/demod_clk)*256+2 : "); // - * (adc_clk/demod_clk)*256+2 - */ - /* scanf("%x",&tmp); */ - cap->cap_afifo = 0x60; - app_apb_write_reg(0x15, 0x18715f2); - app_apb_write_reg(0x15, (app_apb_read_reg(0x15) & 0xfff00fff) | - ((cap->cap_afifo & 0xff) << 12)); /* set afifo */ - app_apb_write_reg(0x9b, 0x1c9); /* capture ADC 10bits */ - app_apb_write_reg(0x7f, 0x00008000); /* enable testbus 0x8000 */ - - tb_depth = cap->cap_size; /*127; */ - tmp = 9; - app_apb_write_reg(0x9b, (app_apb_read_reg(0x9b) & ~0x1f) | tmp); - /* set testbus width */ - - tmp = 0x100000; - app_apb_write_reg(0x9c, tmp); /* by ADC data enable */ - /* printf("Set test mode. (0 is normal ,1 is testmode) : "); //0 */ - /* scanf("%d",&tmp); */ - tmp = 0; - if (tmp == 1) - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) | (1 << 10)); - /* set test mode; */ - else - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) & ~(1 << 10)); - /* close test mode; */ - - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) & ~(1 << 9)); - /* close cap; */ - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) | (1 << 9)); - /* open cap; */ - - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) | (1 << 7)); - /* close tb; */ - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) & ~(1 << 7)); - /* open tb; */ - - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) | (1 << 5)); - /* close intlv; */ - - app_apb_write_reg(0x303, 0x8); /* open dc_arbit */ - - tmp = 0; - if (tmp) - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) & ~(1 << 5)); - /* open intlv; */ - - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) & ~(1 << 8)); - /* go tb; */ - - wait_capture(0x9f, tb_depth, app_apb_read_reg(0x9d)); - - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) | (1 << 8)); - /* stop tb; */ - app_apb_write_reg(0x9b, app_apb_read_reg(0x9b) | (1 << 7)); - /* close tb; */ - return 0; -} - -static DECLARE_WAIT_QUEUE_HEAD(lock_wq); - -static ssize_t aml_demod_info(struct class *cla, - struct class_attribute *attr, char *buf) -{ - return 0; -} - -static struct class_attribute aml_demod_class_attrs[] = { - __ATTR(info, - 0644, - aml_demod_info, - NULL), - __ATTR_NULL -}; - -static struct class aml_demod_class = { - .name = "aml_demod", - .class_attrs = aml_demod_class_attrs, -}; - -#if 0 - -static irqreturn_t aml_demod_isr(int irq, void *dev_id) -{ - if (demod_sta.dvb_mode == 0) { - /*dvbc_isr(&demod_sta); */ - if (dvbc_isr_islock()) { - pr_dbg("sync4\n"); - /*if (waitqueue_active(&lock_wq)) - *wake_up_interruptible(&lock_wq); - */ - } - } else { - dvbt_isr(&demod_sta); - } - - return IRQ_HANDLED; -} -#endif - -static int aml_demod_open(struct inode *inode, struct file *file) -{ - pr_dbg("Amlogic Demod DVB-T/C Open\n"); - return 0; -} - -static int aml_demod_release(struct inode *inode, struct file *file) -{ - pr_dbg("Amlogic Demod DVB-T/C Release\n"); - return 0; -} - -#if 0 -static int amdemod_islock(void) -{ - struct aml_demod_sts demod_sts; - - if (demod_sta.dvb_mode == 0) { - dvbc_status(&demod_sta, &demod_i2c, &demod_sts); - return demod_sts.ch_sts & 0x1; - } else if (demod_sta.dvb_mode == 1) { - dvbt_status(&demod_sta, &demod_i2c, &demod_sts); - return demod_sts.ch_sts >> 12 & 0x1; - } - return 0; -} -#endif - -void mem_read(struct aml_demod_mem *arg) -{ - int data; - int addr; - - addr = arg->addr; - data = arg->dat; -/* memcpy(mem_buf[addr],data,1);*/ - pr_dbg("[addr %x] data is %x\n", addr, data); -} -static long aml_demod_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int strength = 0; - struct dvb_frontend *dvbfe; - struct aml_tuner_sys *tuner; - - switch (cmd) { - case AML_DEMOD_GET_RSSI: - pr_dbg("Ioctl Demod GET_RSSI.\n"); - dvbfe = get_si2177_tuner(); - if (dvbfe != NULL) - strength = dvbfe->ops.tuner_ops.get_strength(dvbfe); - pr_dbg("[si2177] strength is %d\n", strength - 256); - if (strength < 0) - strength = 0 - strength; - tuner = (struct aml_tuner_sys *)arg; - tuner->rssi = strength; - break; - - case AML_DEMOD_SET_TUNER: - pr_dbg("Ioctl Demod Set Tuner.\n"); - dvbfe = get_si2177_tuner(); - if (dvbfe != NULL) - dvbfe->ops.tuner_ops.set_tuner(dvbfe, &demod_sta, - &demod_i2c, - (struct aml_tuner_sys *) - arg); - break; - - case AML_DEMOD_SET_SYS: - pr_dbg("Ioctl Demod Set System\n"); - demod_set_sys(&demod_sta, &demod_i2c, - (struct aml_demod_sys *)arg); - break; - - case AML_DEMOD_GET_SYS: - pr_dbg("Ioctl Demod Get System\n"); - - /*demod_get_sys(&demod_i2c, (struct aml_demod_sys *)arg); */ - break; - - case AML_DEMOD_TEST: - pr_dbg("Ioctl Demod Test. It is blank now\n"); - /*demod_msr_clk(13); */ - /*demod_msr_clk(14); */ - /*demod_calc_clk(&demod_sta); */ - break; - - case AML_DEMOD_TURN_ON: - pr_dbg("Ioctl Demod Turn ON.It is blank now\n"); - /*demod_turn_on(&demod_sta, (struct aml_demod_sys *)arg); */ - break; - - case AML_DEMOD_TURN_OFF: - pr_dbg("Ioctl Demod Turn OFF.It is blank now\n"); - /*demod_turn_off(&demod_sta, (struct aml_demod_sys *)arg); */ - break; - - case AML_DEMOD_DVBC_SET_CH: - pr_dbg("Ioctl DVB-C Set Channel.\n"); - dvbc_set_ch(&demod_sta, &demod_i2c, - (struct aml_demod_dvbc *)arg); - break; - - case AML_DEMOD_DVBC_GET_CH: - /* pr_dbg("Ioctl DVB-C Get Channel. It is blank\n"); */ - dvbc_status(&demod_sta, &demod_i2c, - (struct aml_demod_sts *)arg); - break; - case AML_DEMOD_DVBC_TEST: - pr_dbg("Ioctl DVB-C Test. It is blank\n"); - /*dvbc_get_test_out(0xb, 1000, (u32 *)arg); */ - break; - case AML_DEMOD_DVBT_SET_CH: - pr_dbg("Ioctl DVB-T Set Channel\n"); - dvbt_set_ch(&demod_sta, &demod_i2c, - (struct aml_demod_dvbt *)arg); - break; - - case AML_DEMOD_DVBT_GET_CH: - pr_dbg("Ioctl DVB-T Get Channel\n"); - /*dvbt_status(&demod_sta, &demod_i2c, - * (struct aml_demod_sts *)arg); - */ - break; - - case AML_DEMOD_DVBT_TEST: - pr_dbg("Ioctl DVB-T Test. It is blank\n"); - /*dvbt_get_test_out(0x1e, 1000, (u32 *)arg); */ - break; - - case AML_DEMOD_DTMB_SET_CH: - dtmb_set_ch(&demod_sta, &demod_i2c, - (struct aml_demod_dtmb *)arg); - break; - - case AML_DEMOD_DTMB_GET_CH: - break; - - case AML_DEMOD_DTMB_TEST: - break; - - case AML_DEMOD_ATSC_SET_CH: - atsc_set_ch(&demod_sta, &demod_i2c, - (struct aml_demod_atsc *)arg); - break; - - case AML_DEMOD_ATSC_GET_CH: - check_atsc_fsm_status(); - break; - - case AML_DEMOD_ATSC_TEST: - break; - - case AML_DEMOD_SET_REG: - /* pr_dbg("Ioctl Set Register\n"); */ - demod_set_reg((struct aml_demod_reg *)arg); - break; - - case AML_DEMOD_GET_REG: - /* pr_dbg("Ioctl Get Register\n"); */ - demod_get_reg((struct aml_demod_reg *)arg); - break; - -/* case AML_DEMOD_SET_REGS: */ -/* break; */ - -/* case AML_DEMOD_GET_REGS: */ -/* break; */ - - case AML_DEMOD_RESET_MEM: - pr_dbg("set mem ok\n"); - break; - - case AML_DEMOD_READ_MEM: - break; - case AML_DEMOD_SET_MEM: - /*step=(struct aml_demod_mem)arg; - * pr_dbg("[%x]0x%x------------------\n",i,mem_buf[step]); - * for(i=step;i<1024-1;i++){ - * pr_dbg("0x%x,",mem_buf[i]); - * } - */ - mem_read((struct aml_demod_mem *)arg); - break; - - case AML_DEMOD_ATSC_IRQ: - atsc_read_iqr_reg(); - break; - - default: - pr_dbg("Enter Default ! 0x%X\n", cmd); -/* pr_dbg("AML_DEMOD_GET_REGS=0x%08X\n", AML_DEMOD_GET_REGS); */ -/* pr_dbg("AML_DEMOD_SET_REGS=0x%08X\n", AML_DEMOD_SET_REGS); */ - return -EINVAL; - } - - return 0; -} - -#ifdef CONFIG_COMPAT - -static long aml_demod_compat_ioctl(struct file *file, unsigned int cmd, - ulong arg) -{ - return aml_demod_ioctl(file, cmd, (ulong)compat_ptr(arg)); -} - -#endif - - -static const struct file_operations aml_demod_fops = { - .owner = THIS_MODULE, - .open = aml_demod_open, - .release = aml_demod_release, - .unlocked_ioctl = aml_demod_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = aml_demod_compat_ioctl, -#endif -}; - -static int aml_demod_ui_open(struct inode *inode, struct file *file) -{ - pr_dbg("Amlogic aml_demod_ui_open Open\n"); - return 0; -} - -static int aml_demod_ui_release(struct inode *inode, struct file *file) -{ - pr_dbg("Amlogic aml_demod_ui_open Release\n"); - return 0; -} -char buf_all[100]; -static ssize_t aml_demod_ui_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - char *capture_buf = buf_all; - int res = 0; - - if (count >= 4 * 1024 * 1024) - count = 4 * 1024 * 1024; - else if (count == 0) - return 0; - - res = copy_to_user((void *)buf, (char *)capture_buf, count); - if (res < 0) { - pr_dbg("[aml_demod_ui_read]res is %d", res); - return res; - } - - return count; -} - -static ssize_t aml_demod_ui_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - return 0; -} - -static struct device *aml_demod_ui_dev; -static dev_t aml_demod_devno_ui; -static struct cdev *aml_demod_cdevp_ui; -static const struct file_operations aml_demod_ui_fops = { - .owner = THIS_MODULE, - .open = aml_demod_ui_open, - .release = aml_demod_ui_release, - .read = aml_demod_ui_read, - .write = aml_demod_ui_write, - /* .unlocked_ioctl = aml_demod_ui_ioctl, */ -}; - -#if 0 -static ssize_t aml_demod_ui_info(struct class *cla, - struct class_attribute *attr, char *buf) -{ - return 0; -} - -static struct class_attribute aml_demod_ui_class_attrs[] = { - __ATTR(info, - 0644, - aml_demod_ui_info, - NULL), - __ATTR_NULL -}; -#endif - -static struct class aml_demod_ui_class = { - .name = "aml_demod_ui", -/* .class_attrs = aml_demod_ui_class_attrs,*/ -}; - -int aml_demod_ui_init(void) -{ - int r = 0; - - r = class_register(&aml_demod_ui_class); - if (r) { - pr_dbg("create aml_demod class fail\r\n"); - class_unregister(&aml_demod_ui_class); - return r; - } - - r = alloc_chrdev_region(&aml_demod_devno_ui, 0, 1, DEVICE_UI_NAME); - if (r < 0) { - pr_dbg("aml_demod_ui: failed to alloc major number\n"); - r = -ENODEV; - unregister_chrdev_region(aml_demod_devno_ui, 1); - class_unregister(&aml_demod_ui_class); - return r; - } - - aml_demod_cdevp_ui = kmalloc(sizeof(struct cdev), GFP_KERNEL); - if (!aml_demod_cdevp_ui) { - r = -ENOMEM; - unregister_chrdev_region(aml_demod_devno_ui, 1); - kfree(aml_demod_cdevp_ui); - class_unregister(&aml_demod_ui_class); - return r; - } - /* connect the file operation with cdev */ - cdev_init(aml_demod_cdevp_ui, &aml_demod_ui_fops); - aml_demod_cdevp_ui->owner = THIS_MODULE; - /* connect the major/minor number to cdev */ - r = cdev_add(aml_demod_cdevp_ui, aml_demod_devno_ui, 1); - if (r) { - pr_dbg("aml_demod_ui:failed to add cdev\n"); - unregister_chrdev_region(aml_demod_devno_ui, 1); - cdev_del(aml_demod_cdevp_ui); - kfree(aml_demod_cdevp_ui); - class_unregister(&aml_demod_ui_class); - return r; - } - - aml_demod_ui_dev = device_create(&aml_demod_ui_class, NULL, - MKDEV(MAJOR(aml_demod_devno_ui), 0), - NULL, DEVICE_UI_NAME); - - if (IS_ERR(aml_demod_ui_dev)) { - pr_dbg("Can't create aml_demod device\n"); - unregister_chrdev_region(aml_demod_devno_ui, 1); - cdev_del(aml_demod_cdevp_ui); - kfree(aml_demod_cdevp_ui); - class_unregister(&aml_demod_ui_class); - return r; - } - - return r; -} - -void aml_demod_exit_ui(void) -{ - unregister_chrdev_region(aml_demod_devno_ui, 1); - cdev_del(aml_demod_cdevp_ui); - kfree(aml_demod_cdevp_ui); - class_unregister(&aml_demod_ui_class); -} - -static struct device *aml_demod_dev; -static dev_t aml_demod_devno; -static struct cdev *aml_demod_cdevp; - -#ifdef CONFIG_AM_DEMOD_DVBAPI -int aml_demod_init(void) -#else -static int __init aml_demod_init(void) -#endif -{ - int r = 0; - - pr_dbg("Amlogic Demod DVB-T/C DebugIF Init\n"); - - init_waitqueue_head(&lock_wq); - - /* hook demod isr */ - /* r = request_irq(INT_DEMOD, &aml_demod_isr, - * IRQF_SHARED, "aml_demod", - * (void *)aml_demod_dev_id); - * if (r) { - * pr_dbg("aml_demod irq register error.\n"); - * r = -ENOENT; - * goto err0; - * } - */ - - /* sysfs node creation */ - r = class_register(&aml_demod_class); - if (r) { - pr_dbg("create aml_demod class fail\r\n"); - goto err1; - } - - r = alloc_chrdev_region(&aml_demod_devno, 0, 1, DEVICE_NAME); - if (r < 0) { - pr_dbg("aml_demod: failed to alloc major number\n"); - r = -ENODEV; - goto err2; - } - - aml_demod_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL); - if (!aml_demod_cdevp) { - r = -ENOMEM; - goto err3; - } - /* connect the file operation with cdev */ - cdev_init(aml_demod_cdevp, &aml_demod_fops); - aml_demod_cdevp->owner = THIS_MODULE; - /* connect the major/minor number to cdev */ - r = cdev_add(aml_demod_cdevp, aml_demod_devno, 1); - if (r) { - pr_dbg("aml_demod:failed to add cdev\n"); - goto err4; - } - - aml_demod_dev = device_create(&aml_demod_class, NULL, - MKDEV(MAJOR(aml_demod_devno), 0), NULL, - DEVICE_NAME); - - if (IS_ERR(aml_demod_dev)) { - pr_dbg("Can't create aml_demod device\n"); - goto err5; - } - pr_dbg("Amlogic Demod DVB-T/C DebugIF Init ok----------------\n"); -#if defined(CONFIG_AM_AMDEMOD_FPGA_VER) && !defined(CONFIG_AM_DEMOD_DVBAPI) - pr_dbg("sdio_init\n"); - sdio_init(); -#endif - aml_demod_ui_init(); - - return 0; - -err5: - cdev_del(aml_demod_cdevp); -err4: - kfree(aml_demod_cdevp); - -err3: - unregister_chrdev_region(aml_demod_devno, 1); - -err2: -/* free_irq(INT_DEMOD, (void *)aml_demod_dev_id);*/ - -err1: - class_unregister(&aml_demod_class); - -/* err0:*/ - return r; -} - -#ifdef CONFIG_AM_DEMOD_DVBAPI -void aml_demod_exit(void) -#else -static void __exit aml_demod_exit(void) -#endif -{ - pr_dbg("Amlogic Demod DVB-T/C DebugIF Exit\n"); - - unregister_chrdev_region(aml_demod_devno, 1); - device_destroy(&aml_demod_class, MKDEV(MAJOR(aml_demod_devno), 0)); - cdev_del(aml_demod_cdevp); - kfree(aml_demod_cdevp); - - /* free_irq(INT_DEMOD, (void *)aml_demod_dev_id); */ - - class_unregister(&aml_demod_class); - - aml_demod_exit_ui(); -} - -#ifndef CONFIG_AM_DEMOD_DVBAPI -module_init(aml_demod_init); -module_exit(aml_demod_exit); - -MODULE_LICENSE("GPL"); -/*MODULE_AUTHOR(DRV_AUTHOR);*/ -/*MODULE_DESCRIPTION(DRV_DESC);*/ -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/amlfrontend.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/amlfrontend.c deleted file mode 100644 index 357b6db90966..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/amlfrontend.c +++ /dev/null @@ -1,1402 +0,0 @@ -/***************************************************************** - ** - ** Copyright (C) 2009 Amlogic,Inc. - ** All rights reserved - ** Filename : amlfrontend.c - ** - ** comment: - ** Driver for m6_demod demodulator - ** author : - ** Shijie.Rong@amlogic - ** version : - ** v1.0 12/3/13 - ** v2.0 15/10/12 - **************************************************************** - */ - -/* - * Driver for gxtv_demod demodulator - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef ARC_700 -#include -#else -/* #include */ -#endif -#include -#include -#include "../aml_fe.h" - -#include -#include -#include "demod_func.h" -#include "../aml_dvb.h" -#include "amlfrontend.h" - -MODULE_PARM_DESC(debug_aml, "\n\t\t Enable frontend debug information"); -static int debug_aml; -module_param(debug_aml, int, 0644); - -#define pr_dbg(a ...) \ - do { \ - if (debug_aml) { \ - printk(a); \ - } \ - } while (0) -#define pr_error(fmt, args ...) pr_err("GXTV_DEMOD: "fmt, ## args) -#define pr_inf(fmt, args...) pr_err("GXTV_DEMOD: " fmt, ## args) - -static int last_lock = -1; -#define DEMOD_DEVICE_NAME "gxtv_demod" -static int cci_thread; -static int freq_dvbc; -static struct aml_demod_sta demod_status; -static fe_modulation_t atsc_mode = VSB_8; - -long *mem_buf; - -MODULE_PARM_DESC(frontend_mode, "\n\t\t Frontend mode 0-DVBC, 1-DVBT"); -static int frontend_mode = -1; -module_param(frontend_mode, int, 0444); - -MODULE_PARM_DESC(frontend_i2c, "\n\t\t IIc adapter id of frontend"); -static int frontend_i2c = -1; -module_param(frontend_i2c, int, 0444); - -MODULE_PARM_DESC(frontend_tuner, - "\n\t\t Frontend tuner type 0-NULL, 1-DCT7070, 2-Maxliner, 3-FJ2207, 4-TD1316"); -static int frontend_tuner = -1; -module_param(frontend_tuner, int, 0444); - -MODULE_PARM_DESC(frontend_tuner_addr, "\n\t\t Tuner IIC address of frontend"); -static int frontend_tuner_addr = -1; -module_param(frontend_tuner_addr, int, 0444); -static int autoflags, autoFlagsTrig; -static struct mutex aml_lock; - -static int Gxtv_Demod_Dvbc_Init(struct aml_fe_dev *dev, int mode); - -static ssize_t dvbc_auto_sym_show(struct class *cls, - struct class_attribute *attr, char *buf) -{ - return sprintf(buf, "dvbc_autoflags: %s\n", autoflags ? "on" : "off"); -} - -static ssize_t dvbc_auto_sym_store(struct class *cls, - struct class_attribute *attr, - const char *buf, size_t count) -{ - - return 0; -} - -static unsigned int dtmb_mode; - -enum { - DTMB_READ_STRENGTH = 0, - DTMB_READ_SNR = 1, - DTMB_READ_LOCK = 2, - DTMB_READ_BCH = 3, -}; - - - -int convert_snr(int in_snr) -{ - int out_snr; - static int calce_snr[40] = { - 5, 6, 8, 10, 13, - 16, 20, 25, 32, 40, - 50, 63, 80, 100, 126, - 159, 200, 252, 318, 400, - 504, 634, 798, 1005, 1265, - 1592, 2005, 2524, 3177, 4000, - 5036, 6340, 7981, 10048, 12649, - 15924, 20047, 25238, 31773, 40000}; - for (out_snr = 1 ; out_snr <= 40; out_snr++) - if (in_snr <= calce_snr[out_snr]) - break; - - return out_snr; -} - - -static ssize_t dtmb_para_show(struct class *cls, - struct class_attribute *attr, char *buf) -{ - int snr, lock_status, bch, agc_if_gain; - struct dvb_frontend *dvbfe; - int strength = 0; - - if (dtmb_mode == DTMB_READ_STRENGTH) { - dvbfe = get_si2177_tuner(); - if (dvbfe != NULL) - if (dvbfe->ops.tuner_ops.get_strength) { - strength = - dvbfe->ops.tuner_ops.get_strength(dvbfe); - } - if (strength <= -56) { - agc_if_gain = - ((dtmb_read_reg(DTMB_TOP_FRONT_AGC))&0x3ff); - strength = dtmb_get_power_strength(agc_if_gain); - } - return sprintf(buf, "strength is %d\n", strength); - } else if (dtmb_mode == DTMB_READ_SNR) { - snr = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) & 0x3fff; - snr = convert_snr(snr); - return sprintf(buf, "snr is %d\n", snr); - } else if (dtmb_mode == DTMB_READ_LOCK) { - lock_status = - (dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) >> 14) & 0x1; - return sprintf(buf, "lock_status is %d\n", lock_status); - } else if (dtmb_mode == DTMB_READ_BCH) { - bch = dtmb_read_reg(DTMB_TOP_FEC_BCH_ACC); - return sprintf(buf, "bch is %d\n", bch); - } else { - return sprintf(buf, "dtmb_para_show can't match mode\n"); - } -} - - - -static ssize_t dtmb_para_store(struct class *cls, - struct class_attribute *attr, - const char *buf, size_t count) -{ - if (buf[0] == '0') - dtmb_mode = DTMB_READ_STRENGTH; - else if (buf[0] == '1') - dtmb_mode = DTMB_READ_SNR; - else if (buf[0] == '2') - dtmb_mode = DTMB_READ_LOCK; - else if (buf[0] == '3') - dtmb_mode = DTMB_READ_BCH; - - return count; -} - -static int readregdata; - -static ssize_t dvbc_reg_show(struct class *cls, struct class_attribute *attr, - char *buf) -{ -/* int readregaddr=0;*/ - char *pbuf = buf; - - pbuf += sprintf(pbuf, "%x", readregdata); - - pr_dbg("read dvbc_reg\n"); - return pbuf - buf; -} - -static ssize_t dvbc_reg_store(struct class *cls, struct class_attribute *attr, - const char *buf, size_t count) -{ - return 0; -} - -static CLASS_ATTR(auto_sym, 0644, dvbc_auto_sym_show, dvbc_auto_sym_store); -static CLASS_ATTR(dtmb_para, 0644, dtmb_para_show, dtmb_para_store); -static CLASS_ATTR(dvbc_reg, 0644, dvbc_reg_show, dvbc_reg_store); - -#if 0 -static irqreturn_t amdemod_isr(int irq, void *data) -{ -/* struct aml_fe_dev *state = data; - * - * #define dvb_isr_islock() (((frontend_mode==0)&&dvbc_isr_islock()) \ - * ||((frontend_mode==1)&&dvbt_isr_islock())) - * #define dvb_isr_monitor() do {\ - * if(frontend_mode==1) dvbt_isr_monitor(); }while(0) - * #define dvb_isr_cancel() do { if(frontend_mode==1) dvbt_isr_cancel(); \ - * else if(frontend_mode==0) dvbc_isr_cancel();}while(0) - * - * dvb_isr_islock(); - * { - * if(waitqueue_active(&state->lock_wq)) - * wake_up_interruptible(&state->lock_wq); - * } - * - * dvb_isr_monitor(); - * - * dvb_isr_cancel(); - */ - - return IRQ_HANDLED; -} -#endif - -static int install_isr(struct aml_fe_dev *state) -{ - int r = 0; - - /* hook demod isr */ -/* pr_dbg("amdemod irq register[IRQ(%d)].\n", INT_DEMOD); - * r = request_irq(INT_DEMOD, &amdemod_isr, - * IRQF_SHARED, "amldemod", - * (void *)state); - * if (r) { - * pr_error("amdemod irq register error.\n"); - * } - */ - return r; -} - - -static int amdemod_qam(fe_modulation_t qam) -{ - switch (qam) { - case QAM_16: - return 0; - case QAM_32: - return 1; - case QAM_64: - return 2; - case QAM_128: - return 3; - case QAM_256: - return 4; - case VSB_8: - return 5; - case QAM_AUTO: - return 6; - default: - return 2; - } - return 2; -} - -static int amdemod_stat_islock(struct aml_fe_dev *dev, int mode) -{ - struct aml_demod_sts demod_sts; - int lock_status; - int dvbt_status1; - - if (mode == 0) { - /*DVBC*/ - /*dvbc_status(state->sta, state->i2c, &demod_sts);*/ - demod_sts.ch_sts = apb_read_reg(QAM_BASE + 0x18); - return demod_sts.ch_sts & 0x1; - } else if (mode == 1) { - /*DVBT*/ - dvbt_status1 = - ((apb_read_reg(DVBT_BASE + (0x0a << 2)) >> 20) & 0x3ff); - lock_status = (apb_read_reg(DVBT_BASE + (0x2a << 2))) & 0xf; - if ((((lock_status) == 9) || ((lock_status) == 10)) - && ((dvbt_status1) != 0)) - return 1; - else - return 0; - /*((apb_read_reg(DVBT_BASE+0x0)>>12)&0x1);// - * dvbt_get_status_ops()->get_status(&demod_sts, &demod_sta); - */ - } else if (mode == 2) { - /*ISDBT*/ - /*return dvbt_get_status_ops()->get_status - * (demod_sts, demod_sta); - */ - } else if (mode == 3) { - /*ATSC*/ - if ((atsc_mode == QAM_64) || (atsc_mode == QAM_256)) - return (atsc_read_iqr_reg() >> 16) == 0x1f; - else if (atsc_mode == VSB_8) - return atsc_read_reg(0x0980) == 0x79; - else - return (atsc_read_iqr_reg() >> 16) == 0x1f; - } else if (mode == 4) { - /*DTMB*/ - /* pr_dbg("DTMB lock status is %u\n", - * ((dtmb_read_reg(DTMB_BASE + (0x0e3 << 2)) >> 14) & - * 0x1)); - */ - return (dtmb_read_reg(DTMB_BASE + (0x0e3 << 2)) >> 14) & 0x1; - } - return 0; -} - -#define amdemod_dvbc_stat_islock(dev) amdemod_stat_islock((dev), 0) -#define amdemod_dvbt_stat_islock(dev) amdemod_stat_islock((dev), 1) -#define amdemod_isdbt_stat_islock(dev) amdemod_stat_islock((dev), 2) -#define amdemod_atsc_stat_islock(dev) amdemod_stat_islock((dev), 3) -#define amdemod_dtmb_stat_islock(dev) amdemod_stat_islock((dev), 4) - -static int gxtv_demod_dvbc_set_qam_mode(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_dvbc param; /*mode 0:16, 1:32, 2:64, 3:128, 4:256*/ - - memset(¶m, 0, sizeof(param)); - param.mode = amdemod_qam(c->modulation); - dvbc_set_qam_mode(param.mode); - return 0; -} - -static void gxtv_demod_dvbc_release(struct dvb_frontend *fe) -{ -/* - * struct aml_fe_dev *state = fe->demodulator_priv; - * - * uninstall_isr(state); - * - * kfree(state); - */ -} - -static int gxtv_demod_dvbc_read_status - (struct dvb_frontend *fe, fe_status_t *status) -{ -/* struct aml_fe_dev *dev = afe->dtv_demod;*/ - struct aml_demod_sts demod_sts; -/* struct aml_demod_sta demod_sta;*/ -/* struct aml_demod_i2c demod_i2c;*/ - int ilock; - - demod_sts.ch_sts = apb_read_reg(QAM_BASE + 0x18); -/* dvbc_status(&demod_sta, &demod_i2c, &demod_sts);*/ - if (demod_sts.ch_sts & 0x1) { - ilock = 1; - *status = - FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | - FE_HAS_VITERBI | FE_HAS_SYNC; - } else { - ilock = 0; - *status = FE_TIMEDOUT; - } - if (last_lock != ilock) { - pr_error("%s.\n", - ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); - last_lock = ilock; - } - - return 0; -} - -static int gxtv_demod_dvbc_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - /*struct aml_fe_dev *dev = afe->dtv_demod;*/ - struct aml_demod_sts demod_sts; - struct aml_demod_i2c demod_i2c; - struct aml_demod_sta demod_sta; - - dvbc_status(&demod_sta, &demod_i2c, &demod_sts); - *ber = demod_sts.ch_ber; - return 0; -} - -static int gxtv_demod_dvbc_read_signal_strength - (struct dvb_frontend *fe, u16 *strength) -{ - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - *strength = 256 - tuner_get_ch_power(dev); - - return 0; -} - -static int gxtv_demod_dvbc_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - struct aml_demod_sts demod_sts; - struct aml_demod_i2c demod_i2c; - struct aml_demod_sta demod_sta; - - dvbc_status(&demod_sta, &demod_i2c, &demod_sts); - *snr = demod_sts.ch_snr / 100; - return 0; -} - -static int gxtv_demod_dvbc_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - return 0; -} - -/*extern int aml_fe_analog_set_frontend(struct dvb_frontend *fe);*/ - -static int gxtv_demod_dvbc_set_frontend(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_dvbc param; /*mode 0:16, 1:32, 2:64, 3:128, 4:256*/ - struct aml_demod_sts demod_sts; - struct aml_demod_i2c demod_i2c; - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - int error, times; - - demod_i2c.tuner = dev->drv->id; - demod_i2c.addr = dev->i2c_addr; - times = 2; - memset(¶m, 0, sizeof(param)); - param.ch_freq = c->frequency / 1000; - param.mode = amdemod_qam(c->modulation); - param.symb_rate = c->symbol_rate / 1000; - if ((param.mode == 3) && (demod_status.tmp != Adc_mode)) { - Gxtv_Demod_Dvbc_Init(dev, Adc_mode); - pr_dbg("Gxtv_Demod_Dvbc_Init,Adc_mode\n"); - } else { - /*Gxtv_Demod_Dvbc_Init(dev,Cry_mode);*/ - } - if (autoflags == 0) { - /*pr_dbg("QAM_TUNING mode\n");*/ - /*flag=0;*/ - } - if ((autoflags == 1) && (autoFlagsTrig == 0) - && (freq_dvbc == param.ch_freq)) { - pr_dbg("now is auto symbrating\n"); - return 0; - } - autoFlagsTrig = 0; - last_lock = -1; - pr_dbg("[gxtv_demod_dvbc_set_frontend]PARA\t" - "demod_i2c.tuner is %d||||demod_i2c.addr is %d||||\t" - "param.ch_freq is %d||||param.symb_rate is %d,\t" - "param.mode is %d\n", - demod_i2c.tuner, demod_i2c.addr, param.ch_freq, - param.symb_rate, param.mode); -retry: - aml_dmx_before_retune(afe->ts, fe); - aml_fe_analog_set_frontend(fe); - dvbc_set_ch(&demod_status, &demod_i2c, ¶m); - if (autoflags == 1) { - pr_dbg("QAM_PLAYING mode,start auto sym\n"); - dvbc_set_auto_symtrack(); - /* flag=1;*/ - } -/*rsj_debug*/ - - dvbc_status(&demod_status, &demod_i2c, &demod_sts); - freq_dvbc = param.ch_freq; - - times--; - if (amdemod_dvbc_stat_islock(dev) && times) { - int lock; - - aml_dmx_start_error_check(afe->ts, fe); - msleep(20); - error = aml_dmx_stop_error_check(afe->ts, fe); - lock = amdemod_dvbc_stat_islock(dev); - if ((error > 200) || !lock) { - pr_error - ("amlfe too many error, error count:%d\t" - "lock statuc:%d, retry\n", - error, lock); - goto retry; - } - } - - aml_dmx_after_retune(afe->ts, fe); - - afe->params = *c; -/* afe->params.frequency = c->frequency; - * afe->params.u.qam.symbol_rate = c->symbol_rate; - * afe->params.u.qam.modulation = c->modulation; - */ - - pr_dbg("AML amldemod => frequency=%d,symbol_rate=%d\r\n", c->frequency, - c->symbol_rate); - return 0; -} - -static int gxtv_demod_dvbc_get_frontend(struct dvb_frontend *fe) -{ /*these content will be writed into eeprom .*/ - struct aml_fe *afe = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int qam_mode; - - qam_mode = apb_read_reg(QAM_BASE + 0x008); - afe->params.modulation = (qam_mode & 7) + 1; - pr_dbg("[mode] is %d\n", afe->params.modulation); - - *c = afe->params; -/* c->modulation= afe->params.u.qam.modulation; - * c->frequency= afe->params.frequency; - * c->symbol_rate= afe->params.u.qam.symbol_rate; - */ - return 0; -} - -static int Gxtv_Demod_Dvbc_Init(struct aml_fe_dev *dev, int mode) -{ - struct aml_demod_sys sys; - struct aml_demod_i2c i2c; - - pr_dbg("AML Demod DVB-C init\r\n"); - memset(&sys, 0, sizeof(sys)); - memset(&i2c, 0, sizeof(i2c)); - i2c.tuner = dev->drv->id; - i2c.addr = dev->i2c_addr; - /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/ - demod_status.dvb_mode = Gxtv_Dvbc; - - if (mode == Adc_mode) { - sys.adc_clk = Adc_Clk_25M; - sys.demod_clk = Demod_Clk_200M; - demod_status.tmp = Adc_mode; - } else { - sys.adc_clk = Adc_Clk_24M; - sys.demod_clk = Demod_Clk_72M; - demod_status.tmp = Cry_mode; - } - demod_status.ch_if = Si2176_5M_If * 1000; - pr_dbg("[%s]adc_clk is %d,demod_clk is %d\n", __func__, sys.adc_clk, - sys.demod_clk); - autoFlagsTrig = 0; - demod_set_sys(&demod_status, &i2c, &sys); - return 0; -} - -static void gxtv_demod_dvbt_release(struct dvb_frontend *fe) -{ -/* - * struct aml_fe_dev *state = fe->demodulator_priv; - * - * uninstall_isr(state); - * - * kfree(state); - */ -} - -static int gxtv_demod_dvbt_read_status - (struct dvb_frontend *fe, fe_status_t *status) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ - struct aml_demod_i2c demod_i2c; - struct aml_demod_sta demod_sta; - int ilock; - unsigned char s = 0; - - s = dvbt_get_status_ops()->get_status(&demod_sta, &demod_i2c); - if (s == 1) { - ilock = 1; - *status = - FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | - FE_HAS_VITERBI | FE_HAS_SYNC; - } else { - ilock = 0; - *status = FE_TIMEDOUT; - } - if (last_lock != ilock) { - pr_error("%s.\n", - ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); - last_lock = ilock; - } - - return 0; -} - -static int gxtv_demod_dvbt_read_ber(struct dvb_frontend *fe, u32 *ber) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ - struct aml_demod_i2c demod_i2c; - struct aml_demod_sta demod_sta; - - *ber = dvbt_get_status_ops()->get_ber(&demod_sta, &demod_i2c) & 0xffff; - return 0; -} - -static int gxtv_demod_dvbt_read_signal_strength - (struct dvb_frontend *fe, u16 *strength) -{ - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - *strength = 256 - tuner_get_ch_power(dev); - pr_dbg("[RSJ]tuner strength is %d dbm\n", *strength); - return 0; -} - -static int gxtv_demod_dvbt_read_snr(struct dvb_frontend *fe, u16 *snr) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ -/* struct aml_demod_sts demod_sts;*/ - struct aml_demod_i2c demod_i2c; - struct aml_demod_sta demod_sta; - - *snr = dvbt_get_status_ops()->get_snr(&demod_sta, &demod_i2c); - *snr /= 8; - pr_dbg("[RSJ]snr is %d dbm\n", *snr); - return 0; -} - -static int gxtv_demod_dvbt_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - return 0; -} - -static int gxtv_demod_dvbt_set_frontend(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - /*struct aml_demod_sts demod_sts;*/ - struct aml_demod_i2c demod_i2c; - int error, times; - struct aml_demod_dvbt param; - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - demod_i2c.tuner = dev->drv->id; - demod_i2c.addr = dev->i2c_addr; - - times = 2; - - /*////////////////////////////////////*/ - /* bw == 0 : 8M*/ - /* 1 : 7M*/ - /* 2 : 6M*/ - /* 3 : 5M*/ - /* agc_mode == 0: single AGC*/ - /* 1: dual AGC*/ - /*////////////////////////////////////*/ - memset(¶m, 0, sizeof(param)); - param.ch_freq = c->frequency / 1000; - param.bw = c->bandwidth_hz; - param.agc_mode = 1; - /*ISDBT or DVBT : 0 is QAM, 1 is DVBT, 2 is ISDBT, - * 3 is DTMB, 4 is ATSC - */ - param.dat0 = 1; - last_lock = -1; - -retry: - aml_dmx_before_retune(AM_TS_SRC_TS2, fe); - aml_fe_analog_set_frontend(fe); - dvbt_set_ch(&demod_status, &demod_i2c, ¶m); - - /* for(count=0;count<10;count++){ - * if(amdemod_dvbt_stat_islock(dev)){ - * pr_dbg("first lock success\n"); - * break; - * } - * - * msleep(200); - * } - */ -/*rsj_debug*/ - -/**/ - - times--; - if (amdemod_dvbt_stat_islock(dev) && times) { - int lock; - - aml_dmx_start_error_check(AM_TS_SRC_TS2, fe); - msleep(20); - error = aml_dmx_stop_error_check(AM_TS_SRC_TS2, fe); - lock = amdemod_dvbt_stat_islock(dev); - if ((error > 200) || !lock) { - pr_error - ("amlfe too many error,\t" - "error count:%d lock statuc:%d, retry\n", - error, lock); - goto retry; - } - } - - aml_dmx_after_retune(AM_TS_SRC_TS2, fe); - - afe->params = *c; - - /*pr_dbg("AML amldemod => frequency=%d,symbol_rate=%d\r\n", - * p->frequency,p->u.qam.symbol_rate); - */ - return 0; -} - -static int gxtv_demod_dvbt_get_frontend(struct dvb_frontend *fe) -{ /*these content will be writed into eeprom .*/ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_fe *afe = fe->demodulator_priv; - - *c = afe->params; - return 0; -} - -int Gxtv_Demod_Dvbt_Init(struct aml_fe_dev *dev) -{ - struct aml_demod_sys sys; - struct aml_demod_i2c i2c; - - pr_dbg("AML Demod DVB-T init\r\n"); - - memset(&sys, 0, sizeof(sys)); - memset(&i2c, 0, sizeof(i2c)); - memset(&demod_status, 0, sizeof(demod_status)); - i2c.tuner = dev->drv->id; - i2c.addr = dev->i2c_addr; - /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/ - demod_status.dvb_mode = Gxtv_Dvbt_Isdbt; - sys.adc_clk = Adc_Clk_24M; - sys.demod_clk = Demod_Clk_60M; - demod_status.ch_if = Si2176_5M_If * 1000; - demod_set_sys(&demod_status, &i2c, &sys); - return 0; -} - -static void gxtv_demod_atsc_release(struct dvb_frontend *fe) -{ -/* - * struct aml_fe_dev *state = fe->demodulator_priv; - * - * uninstall_isr(state); - * - * kfree(state); - */ -} - -static int gxtv_demod_atsc_set_qam_mode(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_atsc param; /*mode 3:64, 5:256, 7:vsb*/ - fe_modulation_t mode; - - memset(¶m, 0, sizeof(param)); - mode = c->modulation; - pr_dbg("mode is %d\n", mode); - atsc_qam_set(mode); - return 0; -} - -static int gxtv_demod_atsc_read_status - (struct dvb_frontend *fe, fe_status_t *status) -{ - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; -/* struct aml_demod_i2c demod_i2c;*/ -/* struct aml_demod_sta demod_sta;*/ - int ilock; - unsigned char s = 0; - - s = amdemod_atsc_stat_islock(dev); - if (s == 1) { - ilock = 1; - *status = - FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | - FE_HAS_VITERBI | FE_HAS_SYNC; - } else { - ilock = 0; - *status = FE_TIMEDOUT; - } - if (last_lock != ilock) { - pr_error("%s.\n", - ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); - last_lock = ilock; - } - - return 0; -} - -static int gxtv_demod_atsc_read_ber(struct dvb_frontend *fe, u32 *ber) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ -/* struct aml_fe_dev *dev = afe->dtv_demod;*/ -/* struct aml_demod_sts demod_sts;*/ -/* struct aml_demod_i2c demod_i2c;*/ -/* struct aml_demod_sta demod_sta;*/ - -/* check_atsc_fsm_status();*/ - return 0; -} - -static int gxtv_demod_atsc_read_signal_strength - (struct dvb_frontend *fe, u16 *strength) -{ - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - *strength = tuner_get_ch_power(dev); - return 0; -} - -static int gxtv_demod_atsc_read_snr(struct dvb_frontend *fe, u16 *snr) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ -/* struct aml_fe_dev *dev = afe->dtv_demod;*/ - -/* struct aml_demod_sts demod_sts;*/ -/* struct aml_demod_i2c demod_i2c;*/ -/* struct aml_demod_sta demod_sta;*/ - -/* * snr=check_atsc_fsm_status();*/ - return 0; -} - -static int gxtv_demod_atsc_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - return 0; -} - -static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) -{ -/* struct amlfe_state *state = fe->demodulator_priv;*/ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_atsc param; -/* struct aml_demod_sta demod_sta;*/ -/* struct aml_demod_sts demod_sts;*/ - struct aml_demod_i2c demod_i2c; - int error, times; - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - demod_i2c.tuner = dev->drv->id; - demod_i2c.addr = dev->i2c_addr; - times = 2; - - memset(¶m, 0, sizeof(param)); - param.ch_freq = c->frequency / 1000; - - last_lock = -1; - /*p->u.vsb.modulation=QAM_64;*/ - atsc_mode = c->modulation; - /* param.mode = amdemod_qam(p->u.vsb.modulation);*/ - param.mode = c->modulation; - -retry: - aml_dmx_before_retune(AM_TS_SRC_TS2, fe); - aml_fe_analog_set_frontend(fe); - atsc_set_ch(&demod_status, &demod_i2c, ¶m); - - /*{ - * int ret; - * ret = wait_event_interruptible_timeout( - * dev->lock_wq, amdemod_atsc_stat_islock(dev), 4*HZ); - * if(!ret) pr_error("amlfe wait lock timeout.\n"); - * } - */ -/*rsj_debug*/ - /* int count; - * for(count=0;count<10;count++){ - * if(amdemod_atsc_stat_islock(dev)){ - * pr_dbg("first lock success\n"); - * break; - * } - * - * msleep(200); - * } - */ - - times--; - if (amdemod_atsc_stat_islock(dev) && times) { - int lock; - - aml_dmx_start_error_check(AM_TS_SRC_TS2, fe); - msleep(20); - error = aml_dmx_stop_error_check(AM_TS_SRC_TS2, fe); - lock = amdemod_atsc_stat_islock(dev); - if ((error > 200) || !lock) { - pr_error - ("amlfe too many error,\t" - "error count:%d lock statuc:%d, retry\n", - error, lock); - goto retry; - } - } - - aml_dmx_after_retune(AM_TS_SRC_TS2, fe); - - afe->params = *c; - /*pr_dbg("AML amldemod => frequency=%d,symbol_rate=%d\r\n", - * p->frequency,p->u.qam.symbol_rate); - */ - return 0; -} - -static int gxtv_demod_atsc_get_frontend(struct dvb_frontend *fe) -{ /*these content will be writed into eeprom .*/ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_fe *afe = fe->demodulator_priv; - - pr_dbg("c->frequency is %d\n", c->frequency); - *c = afe->params; - return 0; -} - -int Gxtv_Demod_Atsc_Init(struct aml_fe_dev *dev) -{ - struct aml_demod_sys sys; - struct aml_demod_i2c i2c; - - pr_dbg("AML Demod ATSC init\r\n"); - - memset(&sys, 0, sizeof(sys)); - memset(&i2c, 0, sizeof(i2c)); - memset(&demod_status, 0, sizeof(demod_status)); - /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/ - demod_status.dvb_mode = Gxtv_Atsc; - sys.adc_clk = Adc_Clk_25_2M; /*Adc_Clk_26M;*/ - sys.demod_clk = Demod_Clk_75M; /*Demod_Clk_71M;//Demod_Clk_78M;*/ - demod_status.ch_if = 6350; - demod_status.tmp = Adc_mode; - demod_set_sys(&demod_status, &i2c, &sys); - return 0; -} - -static void gxtv_demod_dtmb_release(struct dvb_frontend *fe) -{ -/* - * struct aml_fe_dev *state = fe->demodulator_priv; - * - * uninstall_isr(state); - * - * kfree(state); - */ -} - -static int gxtv_demod_dtmb_read_status - (struct dvb_frontend *fe, fe_status_t *status) -{ - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; -/* struct aml_demod_i2c demod_i2c;*/ -/* struct aml_demod_sta demod_sta;*/ - int ilock; - unsigned char s = 0; - -/* s = amdemod_dtmb_stat_islock(dev);*/ -/* if(s==1)*/ - if (is_meson_txl_cpu()) - s = dtmb_check_status_txl(fe); - else - s = dtmb_check_status_gxtv(fe); - s = amdemod_dtmb_stat_islock(dev); -/* s=1;*/ - if (s == 1) { - ilock = 1; - *status = - FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | - FE_HAS_VITERBI | FE_HAS_SYNC; - } else { - ilock = 0; - *status = FE_TIMEDOUT; - } - if (last_lock != ilock) { - pr_error("%s.\n", - ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); - last_lock = ilock; - } - - return 0; -} - -static int gxtv_demod_dtmb_read_ber(struct dvb_frontend *fe, u32 *ber) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ -/* struct aml_fe_dev *dev = afe->dtv_demod;*/ -/* struct aml_demod_sts demod_sts;*/ -/* struct aml_demod_i2c demod_i2c;*/ -/* struct aml_demod_sta demod_sta;*/ - -/* check_atsc_fsm_status();*/ -/* int fec_bch_add; */ -/* fec_bch_add = dtmb_read_reg(0xdf); */ -/* *ber = fec_bch_add; */ - return 0; -} - -static int gxtv_demod_dtmb_read_signal_strength - (struct dvb_frontend *fe, u16 *strength) -{ - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - *strength = tuner_get_ch_power(dev); - return 0; -} - -static int gxtv_demod_dtmb_read_snr(struct dvb_frontend *fe, u16 *snr) -{ -/* struct aml_fe *afe = fe->demodulator_priv;*/ -/* struct aml_fe_dev *dev = afe->dtv_demod;*/ -#if 1 - int tmp, snr_avg; - - tmp = snr_avg = 0; - tmp = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR); -/* snr_avg = (tmp >> 16) & 0x3fff; - * if (snr_avg >= 2048) - * snr_avg = snr_avg - 4096; - * snr_avg = snr_avg / 32; - */ - *snr = tmp&0xff; -#endif - return 0; -} - -static int gxtv_demod_dtmb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - return 0; -} - -static int gxtv_demod_dtmb_read_fsm(struct dvb_frontend *fe, u32 *fsm_status) -{ - int tmp; - - tmp = dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0); - *fsm_status = tmp&0xffffffff; - pr_dbg("[rsj] fsm_status is %x\n", *fsm_status); - return 0; -} - - -static int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_dtmb param; -/* struct aml_demod_sta demod_sta;*/ -/* struct aml_demod_sts demod_sts;*/ - struct aml_demod_i2c demod_i2c; - int times; - struct aml_fe *afe = fe->demodulator_priv; - struct aml_fe_dev *dev = afe->dtv_demod; - - demod_i2c.tuner = dev->drv->id; - demod_i2c.addr = dev->i2c_addr; - times = 2; - pr_dbg("gxtv_demod_dtmb_set_frontend,freq is %d\n", c->frequency); - memset(¶m, 0, sizeof(param)); - param.ch_freq = c->frequency / 1000; - - last_lock = -1; -/* demod_power_switch(PWR_OFF); */ - aml_fe_analog_set_frontend(fe); - msleep(100); -/* demod_power_switch(PWR_ON); */ - dtmb_set_ch(&demod_status, &demod_i2c, ¶m); - afe->params = *c; - /* pr_dbg("AML amldemod => frequency=%d,symbol_rate=%d\r\n", - * p->frequency,p->u.qam.symbol_rate); - */ - return 0; -} - -static int gxtv_demod_dtmb_get_frontend(struct dvb_frontend *fe) -{ /*these content will be writed into eeprom .*/ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_fe *afe = fe->demodulator_priv; - - *c = afe->params; -/* pr_dbg("[get frontend]c->frequency is %d\n",c->frequency);*/ - return 0; -} - -int Gxtv_Demod_Dtmb_Init(struct aml_fe_dev *dev) -{ - struct aml_demod_sys sys; - struct aml_demod_i2c i2c; - - pr_dbg("AML Demod DTMB init\r\n"); - - memset(&sys, 0, sizeof(sys)); - memset(&i2c, 0, sizeof(i2c)); - memset(&demod_status, 0, sizeof(demod_status)); - /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/ - demod_status.dvb_mode = Gxtv_Dtmb; - if (is_meson_txl_cpu()) { - sys.adc_clk = Adc_Clk_25M; /*Adc_Clk_26M;*/ - sys.demod_clk = Demod_Clk_225M; - } else { - sys.adc_clk = Adc_Clk_25M; /*Adc_Clk_26M;*/ - sys.demod_clk = Demod_Clk_200M; - } - demod_status.ch_if = Si2176_5M_If; - demod_status.tmp = Adc_mode; - demod_status.spectrum = dev->spectrum; - demod_set_sys(&demod_status, &i2c, &sys); - return 0; -} - -static int gxtv_demod_fe_get_ops(struct aml_fe_dev *dev, int mode, void *ops) -{ - struct dvb_frontend_ops *fe_ops = (struct dvb_frontend_ops *)ops; - - if (mode == AM_FE_OFDM) { - fe_ops->info.frequency_min = 51000000; - fe_ops->info.frequency_max = 858000000; - fe_ops->info.frequency_stepsize = 0; - fe_ops->info.frequency_tolerance = 0; - fe_ops->info.caps = - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | - FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | - FE_CAN_RECOVER | FE_CAN_MUTE_TS; - fe_ops->release = gxtv_demod_dvbt_release; - fe_ops->set_frontend = gxtv_demod_dvbt_set_frontend; - fe_ops->get_frontend = gxtv_demod_dvbt_get_frontend; - fe_ops->read_status = gxtv_demod_dvbt_read_status; - fe_ops->read_ber = gxtv_demod_dvbt_read_ber; - fe_ops->read_signal_strength = - gxtv_demod_dvbt_read_signal_strength; - fe_ops->read_snr = gxtv_demod_dvbt_read_snr; - fe_ops->read_ucblocks = gxtv_demod_dvbt_read_ucblocks; - fe_ops->read_dtmb_fsm = NULL; - - pr_dbg("=========================dvbt demod init\r\n"); - Gxtv_Demod_Dvbt_Init(dev); - } else if (mode == AM_FE_QAM) { - fe_ops->info.frequency_min = 51000000; - fe_ops->info.frequency_max = 858000000; - fe_ops->info.frequency_stepsize = 0; - fe_ops->info.frequency_tolerance = 0; - fe_ops->info.caps = - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_64 | - FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | - FE_CAN_RECOVER | FE_CAN_MUTE_TS; - - fe_ops->release = gxtv_demod_dvbc_release; - fe_ops->set_frontend = gxtv_demod_dvbc_set_frontend; - fe_ops->get_frontend = gxtv_demod_dvbc_get_frontend; - fe_ops->read_status = gxtv_demod_dvbc_read_status; - fe_ops->read_ber = gxtv_demod_dvbc_read_ber; - fe_ops->read_signal_strength = - gxtv_demod_dvbc_read_signal_strength; - fe_ops->read_snr = gxtv_demod_dvbc_read_snr; - fe_ops->read_ucblocks = gxtv_demod_dvbc_read_ucblocks; - fe_ops->set_qam_mode = gxtv_demod_dvbc_set_qam_mode; - fe_ops->read_dtmb_fsm = NULL; - install_isr(dev); - pr_dbg("=========================dvbc demod init\r\n"); - Gxtv_Demod_Dvbc_Init(dev, Adc_mode); - } else if (mode == AM_FE_ATSC) { - fe_ops->info.frequency_min = 51000000; - fe_ops->info.frequency_max = 858000000; - fe_ops->info.frequency_stepsize = 0; - fe_ops->info.frequency_tolerance = 0; - fe_ops->info.caps = - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | - FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | - FE_CAN_RECOVER | FE_CAN_MUTE_TS; - - fe_ops->release = gxtv_demod_atsc_release; - fe_ops->set_frontend = gxtv_demod_atsc_set_frontend; - fe_ops->get_frontend = gxtv_demod_atsc_get_frontend; - fe_ops->read_status = gxtv_demod_atsc_read_status; - fe_ops->read_ber = gxtv_demod_atsc_read_ber; - fe_ops->read_signal_strength = - gxtv_demod_atsc_read_signal_strength; - fe_ops->read_snr = gxtv_demod_atsc_read_snr; - fe_ops->read_ucblocks = gxtv_demod_atsc_read_ucblocks; - fe_ops->set_qam_mode = gxtv_demod_atsc_set_qam_mode; - fe_ops->read_dtmb_fsm = NULL; - Gxtv_Demod_Atsc_Init(dev); - } else if (mode == AM_FE_DTMB) { - fe_ops->info.frequency_min = 51000000; - fe_ops->info.frequency_max = 900000000; - fe_ops->info.frequency_stepsize = 0; - fe_ops->info.frequency_tolerance = 0; - fe_ops->info.caps = - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | - FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | - FE_CAN_RECOVER | FE_CAN_MUTE_TS; - - fe_ops->release = gxtv_demod_dtmb_release; - fe_ops->set_frontend = gxtv_demod_dtmb_set_frontend; - fe_ops->get_frontend = gxtv_demod_dtmb_get_frontend; - fe_ops->read_status = gxtv_demod_dtmb_read_status; - fe_ops->read_ber = gxtv_demod_dtmb_read_ber; - fe_ops->read_signal_strength = - gxtv_demod_dtmb_read_signal_strength; - fe_ops->read_snr = gxtv_demod_dtmb_read_snr; - fe_ops->read_ucblocks = gxtv_demod_dtmb_read_ucblocks; - fe_ops->read_dtmb_fsm = gxtv_demod_dtmb_read_fsm; - Gxtv_Demod_Dtmb_Init(dev); - } - return 0; -} - -static int gxtv_demod_fe_resume(struct aml_fe_dev *dev) -{ - int memstart_dtmb; - - pr_inf("gxtv_demod_fe_resume\n"); -/* demod_power_switch(PWR_ON);*/ - Gxtv_Demod_Dtmb_Init(dev); - memstart_dtmb = dev->fe->dtv_demod->mem_start; - pr_dbg("[im]memstart is %x\n", memstart_dtmb); - dtmb_write_reg(DTMB_FRONT_MEM_ADDR, memstart_dtmb); - pr_dbg("[dtmb]mem_buf is 0x%x\n", - dtmb_read_reg(DTMB_FRONT_MEM_ADDR)); - return 0; -} - -static int gxtv_demod_fe_suspend(struct aml_fe_dev *dev) -{ - pr_inf("gxtv_demod_fe_suspend\n"); -/* demod_power_switch(PWR_OFF);*/ - return 0; -} - -#ifdef CONFIG_CMA -void dtmb_cma_alloc(struct aml_fe_dev *devp) -{ - unsigned int mem_size = devp->cma_mem_size; - - devp->venc_pages = - dma_alloc_from_contiguous(&(devp->this_pdev->dev), - mem_size >> PAGE_SHIFT, 0); - pr_dbg("[cma]mem_size is %d,%d\n", - mem_size, mem_size >> PAGE_SHIFT); - if (devp->venc_pages) { - devp->mem_start = page_to_phys(devp->venc_pages); - devp->mem_size = mem_size; - pr_dbg("demod mem_start = 0x%x, mem_size = 0x%x\n", - devp->mem_start, devp->mem_size); - pr_dbg("demod cma alloc ok!\n"); - } else { - pr_dbg("demod cma mem undefined2.\n"); - } -} - -void dtmb_cma_release(struct aml_fe_dev *devp) -{ - dma_release_from_contiguous(&(devp->this_pdev->dev), - devp->venc_pages, - devp->cma_mem_size>>PAGE_SHIFT); - pr_dbg("demod cma release ok!\n"); - devp->mem_start = 0; - devp->mem_size = 0; -} -#endif - - -static int gxtv_demod_fe_enter_mode(struct aml_fe *fe, int mode) -{ - struct aml_fe_dev *dev = fe->dtv_demod; - int memstart_dtmb; - - /* must enable the adc ref signal for demod, */ - vdac_enable(1, 0x2); - - autoFlagsTrig = 1; - if (cci_thread) - if (dvbc_get_cci_task() == 1) - dvbc_create_cci_task(); - /*mem_buf = (long *)phys_to_virt(memstart);*/ - if (mode == AM_FE_DTMB) { - Gxtv_Demod_Dtmb_Init(dev); - if (fe->dtv_demod->cma_flag == 1) { - pr_dbg("CMA MODE, cma flag is %d,mem size is %d", - fe->dtv_demod->cma_flag, fe->dtv_demod->cma_mem_size); - dtmb_cma_alloc(dev); - memstart_dtmb = dev->mem_start; - } else { - memstart_dtmb = fe->dtv_demod->mem_start; - } - pr_dbg("[im]memstart is %x\n", memstart_dtmb); - dtmb_write_reg(DTMB_FRONT_MEM_ADDR, memstart_dtmb); - pr_dbg("[dtmb]mem_buf is 0x%x\n", - dtmb_read_reg(DTMB_FRONT_MEM_ADDR)); - /* open arbit */ - demod_set_demod_reg(0x8, DEMOD_REG4); - } else if (mode == AM_FE_QAM) { - Gxtv_Demod_Dvbc_Init(dev, Adc_mode); - } - - return 0; -} - -static int gxtv_demod_fe_leave_mode(struct aml_fe *fe, int mode) -{ - struct aml_fe_dev *dev = fe->dtv_demod; - - dtvpll_init_flag(0); - /*dvbc_timer_exit();*/ - if (cci_thread) - dvbc_kill_cci_task(); - if (mode == AM_FE_DTMB) { - /* close arbit */ - demod_set_demod_reg(0x0, DEMOD_REG4); - if (fe->dtv_demod->cma_flag == 1) - dtmb_cma_release(dev); - } - - /* should disable the adc ref signal for demod */ - vdac_enable(0, 0x2); - - return 0; -} - -static struct aml_fe_drv gxtv_demod_dtv_demod_drv = { - .id = AM_DTV_DEMOD_M1, - .name = "AMLDEMOD", - .capability = - AM_FE_QPSK | AM_FE_QAM | AM_FE_ATSC | AM_FE_OFDM | AM_FE_DTMB, - .get_ops = gxtv_demod_fe_get_ops, - .suspend = gxtv_demod_fe_suspend, - .resume = gxtv_demod_fe_resume, - .enter_mode = gxtv_demod_fe_enter_mode, - .leave_mode = gxtv_demod_fe_leave_mode -}; - -struct class *gxtv_clsp; -struct class *gxtv_para_clsp; - -static int __init gxtvdemodfrontend_init(void) -{ - int ret; - - pr_dbg("register gxtv_demod demod driver\n"); - ret = 0; - - dtvpll_lock_init(); - mutex_init(&aml_lock); - - gxtv_clsp = class_create(THIS_MODULE, DEMOD_DEVICE_NAME); - if (!gxtv_clsp) { - pr_error("[gxtv demod]%s:create class error.\n", __func__); - return PTR_ERR(gxtv_clsp); - } - ret = class_create_file(gxtv_clsp, &class_attr_auto_sym); - if (ret) - pr_error("[gxtv demod]%s create class error.\n", __func__); - - ret = class_create_file(gxtv_clsp, &class_attr_dtmb_para); - if (ret) - pr_error("[gxtv demod]%s create class error.\n", __func__); - - ret = class_create_file(gxtv_clsp, &class_attr_dvbc_reg); - if (ret) - pr_error("[gxtv demod]%s create class error.\n", __func__); - - return aml_register_fe_drv(AM_DEV_DTV_DEMOD, &gxtv_demod_dtv_demod_drv); -} - -static void __exit gxtvdemodfrontend_exit(void) -{ - pr_dbg("unregister gxtv_demod demod driver\n"); - - mutex_destroy(&aml_lock); - - class_remove_file(gxtv_clsp, &class_attr_auto_sym); - class_remove_file(gxtv_clsp, &class_attr_dtmb_para); - class_remove_file(gxtv_clsp, &class_attr_dvbc_reg); - class_destroy(gxtv_clsp); - aml_unregister_fe_drv(AM_DEV_DTV_DEMOD, &gxtv_demod_dtv_demod_drv); -} - -fs_initcall(gxtvdemodfrontend_init); -module_exit(gxtvdemodfrontend_exit); - -MODULE_DESCRIPTION("gxtv_demod DVB-T/DVB-C/DTMB Demodulator driver"); -MODULE_AUTHOR("RSJ"); -MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c deleted file mode 100644 index a54d82cadddc..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c +++ /dev/null @@ -1,2996 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -/*#include "register.h"*/ -/*#include "c_arc_pointer_reg.h"*/ -/*#include "a9_func.h"*/ -/*#include "clk_util.h"*/ -/*#include "c_stimulus.h"*/ -/*#include "a9_l2_func.h"*/ - -#include "demod_func.h" -#include -#include -#include -#include "acf_filter_coefficient.h" -#include - -#define M6D - -/* static void __iomem * demod_meson_reg_map[4]; */ - -#define pr_dbg(fmt, args ...) \ - do { \ - if (debug_demod) \ - pr_info("FE: " fmt, ## args); \ - } while (0) -#define pr_error(fmt, args ...) pr_info("FE: " fmt, ## args) - -MODULE_PARM_DESC(debug_demod, "\n\t\t Enable frontend debug information"); -static int debug_demod; -module_param(debug_demod, int, 0644); - -MODULE_PARM_DESC(demod_timeout, "\n\t\t timeout debug information"); -static int demod_timeout = 120; -module_param(demod_timeout, int, 0644); - -MODULE_PARM_DESC(demod_sync_count, "\n\t\t timeout debug information"); -static int demod_sync_count = 60; -module_param(demod_sync_count, int, 0644); - -MODULE_PARM_DESC(demod_sync_delay_time, "\n\t\t timeout debug information"); -static int demod_sync_delay_time = 8; -module_param(demod_sync_delay_time, int, 0644); - - - -MODULE_PARM_DESC(demod_mobile_power, "\n\t\t demod_mobile_power debug information"); -static int demod_mobile_power = 100; -module_param(demod_mobile_power, int, 0644); - -MODULE_PARM_DESC(demod_enable_performance, "\n\t\t demod_enable_performance information"); -static int demod_enable_performance = 1; -module_param(demod_enable_performance, int, 0644); - - -static struct mutex mp; -static struct mutex dtvpll_init_lock; -static int dtvpll_init; -static int dtmb_spectrum = 2; - - -/* 8vsb */ -static struct atsc_cfg list_8vsb[22] = { - {0x0733, 0x00, 0}, - {0x0734, 0xff, 0}, - {0x0716, 0x02, 0}, /* F06[7] invert spectrum 0x02 0x06 */ - {0x05e7, 0x00, 0}, - {0x05e8, 0x00, 0}, - {0x0f06, 0x80, 0}, - {0x0f09, 0x04, 0}, - {0x070c, 0x18, 0}, - {0x070d, 0x9d, 0}, - {0x070e, 0x89, 0}, - {0x070f, 0x6a, 0}, - {0x0710, 0x75, 0}, - {0x0711, 0x6f, 0}, - {0x072a, 0x02, 0}, - {0x072c, 0x02, 0}, - {0x090d, 0x03, 0}, - {0x090e, 0x02, 0}, - {0x090f, 0x00, 0}, - {0x0900, 0x01, 0}, - {0x0900, 0x00, 0}, - {0x0f00, 0x01, 0}, - {0x0000, 0x00, 1} -}; - -/* 64qam */ -static struct atsc_cfg list_qam64[111] = { - {0x0900, 0x01, 0}, - {0x0f04, 0x08, 0}, - {0x0f06, 0x80, 0}, - {0x0f07, 0x00, 0}, - {0x0f00, 0xe0, 0}, - {0x0f00, 0xec, 0}, - {0x0001, 0x05, 0}, - {0x0002, 0x61, 0}, /* /0x61 invert spectrum */ - {0x0003, 0x3e, 0}, - {0x0004, 0xed, 0}, /* 0x9d */ - {0x0005, 0x10, 0}, - {0x0006, 0xc0, 0}, - {0x0007, 0x5c, 0}, - {0x0008, 0x0f, 0}, - {0x0009, 0x4f, 0}, - {0x000a, 0xfc, 0}, - {0x000b, 0x0c, 0}, - {0x000c, 0x6c, 0}, - {0x000d, 0x3a, 0}, - {0x000e, 0x10, 0}, - {0x000f, 0x02, 0}, - {0x0011, 0x00, 0}, - {0x0012, 0xf5, 0}, - {0x0013, 0x74, 0}, - {0x0014, 0xb9, 0}, - {0x0015, 0x1f, 0}, - {0x0016, 0x80, 0}, - {0x0017, 0x1f, 0}, - {0x0018, 0x0f, 0}, - {0x001e, 0x00, 0}, - {0x001f, 0x00, 0}, - {0x0023, 0x03, 0}, - {0x0025, 0x20, 0}, - {0x0026, 0xff, 0}, - {0x0027, 0xff, 0}, - {0x0028, 0xf8, 0}, - {0x0200, 0x20, 0}, - {0x0201, 0x62, 0}, - {0x0202, 0x23, 0}, - {0x0204, 0x19, 0}, - {0x0205, 0x74, 0}, - {0x0206, 0xab, 0}, - {0x0207, 0xff, 0}, - {0x0208, 0xc0, 0}, - {0x0209, 0xff, 0}, - {0x0211, 0xc0, 0}, - {0x0212, 0xb0, 0}, - {0x0213, 0x05, 0}, - {0x0215, 0x08, 0}, - {0x0222, 0xe0, 0}, - {0x0223, 0xf0, 0}, - {0x0226, 0x40, 0}, - {0x0229, 0x23, 0}, - {0x022a, 0x02, 0}, - {0x022c, 0x01, 0}, - {0x022e, 0x01, 0}, - {0x022f, 0x25, 0}, - {0x0230, 0x40, 0}, - {0x0231, 0x01, 0}, - {0x0734, 0xff, 0}, - {0x073a, 0xff, 0}, - {0x073b, 0x04, 0}, - {0x073c, 0x08, 0}, - {0x073d, 0x08, 0}, - {0x073e, 0x01, 0}, - {0x073f, 0xf8, 0}, - {0x0740, 0xf1, 0}, - {0x0741, 0xf3, 0}, - {0x0742, 0xff, 0}, - {0x0743, 0x0f, 0}, - {0x0744, 0x1a, 0}, - {0x0745, 0x16, 0}, - {0x0746, 0x00, 0}, - {0x0747, 0xe3, 0}, - {0x0748, 0xce, 0}, - {0x0749, 0xd4, 0}, - {0x074a, 0x00, 0}, - {0x074b, 0x4b, 0}, - {0x074c, 0x00, 0}, - {0x074d, 0xa2, 0}, - {0x074e, 0x00, 0}, - {0x074f, 0xe6, 0}, - {0x0750, 0x00, 0}, - {0x0751, 0x00, 0}, - {0x0752, 0x01, 0}, - {0x0753, 0x03, 0}, - {0x0400, 0x00, 0}, - {0x0408, 0x04, 0}, - {0x040e, 0xe0, 0}, - {0x0500, 0x02, 0}, - {0x05e7, 0x00, 0}, - {0x05e8, 0x00, 0}, - {0x0f09, 0x18, 0}, - {0x070c, 0x20, 0}, - {0x070d, 0x41, 0}, /* 0x49 */ - {0x070e, 0x04, 0}, /* 0x37 */ - {0x070f, 0x00, 0}, - {0x0710, 0x00, 0}, - {0x0711, 0x00, 0}, - {0x0716, 0xf0, 0}, - {0x090f, 0x00, 0}, - {0x0900, 0x01, 1}, - {0x0900, 0x00, 0}, - {0x0001, 0xf5, 0}, - {0x0001, 0xf5, 1}, - {0x0001, 0xf5, 1}, - {0x0001, 0xf5, 1}, - {0x0001, 0xf5, 1}, - {0x0001, 0x05, 0}, - {0x0001, 0x05, 1}, - {0x0000, 0x00, 1} -}; - -/* 256qam */ -static struct atsc_cfg list_qam256[113] = { - {0x0900, 0x01, 0}, - {0x0f04, 0x08, 0}, - {0x0f06, 0x80, 0}, - {0x0f00, 0xe0, 0}, - {0x0f00, 0xec, 0}, - {0x0001, 0x05, 0}, - {0x0002, 0x01, 0}, /* 0x09 */ - {0x0003, 0x2c, 0}, - {0x0004, 0x91, 0}, - {0x0005, 0x10, 0}, - {0x0006, 0xc0, 0}, - {0x0007, 0x5c, 0}, - {0x0008, 0x0f, 0}, - {0x0009, 0x4f, 0}, - {0x000a, 0xfc, 0}, - {0x000b, 0x0c, 0}, - {0x000c, 0x6c, 0}, - {0x000d, 0x3a, 0}, - {0x000e, 0x10, 0}, - {0x000f, 0x02, 0}, - {0x0011, 0x80, 0}, - {0x0012, 0xf5, 0}, /* a5 */ - {0x0013, 0x74, 0}, - {0x0014, 0xb9, 0}, - {0x0015, 0x1f, 0}, - {0x0016, 0x80, 0}, - {0x0017, 0x1f, 0}, - {0x0018, 0x0f, 0}, - {0x001e, 0x00, 0}, - {0x001f, 0x00, 0}, - {0x0023, 0x03, 0}, - {0x0025, 0x20, 0}, - {0x0026, 0xff, 0}, - {0x0027, 0xff, 0}, - {0x0028, 0xf8, 0}, - {0x0200, 0x20, 0}, - {0x0201, 0x62, 0}, - {0x0202, 0x23, 0}, - {0x0204, 0x19, 0}, - {0x0205, 0x76, 0}, - {0x0206, 0xd2, 0}, - {0x0207, 0xff, 0}, - {0x0208, 0xc0, 0}, - {0x0209, 0xff, 0}, - {0x0211, 0xc0, 0}, - {0x0212, 0xb0, 0}, - {0x0213, 0x05, 0}, - {0x0215, 0x08, 0}, - {0x0222, 0xf0, 0}, - {0x0223, 0xff, 0}, - {0x0226, 0x40, 0}, - {0x0229, 0x23, 0}, - {0x022a, 0x02, 0}, - {0x022c, 0x01, 0}, - {0x022e, 0x01, 0}, - {0x022f, 0x05, 0}, - {0x0230, 0x40, 0}, - {0x0231, 0x01, 0}, - {0x0400, 0x02, 0}, - {0x0401, 0x30, 0}, - {0x0402, 0x13, 0}, - {0x0406, 0x06, 0}, - {0x0408, 0x04, 0}, - {0x040e, 0xe0, 0}, - {0x0411, 0x02, 0}, - {0x073a, 0x02, 0}, - {0x073b, 0x09, 0}, - {0x073c, 0x0c, 0}, - {0x073d, 0x08, 0}, - {0x073e, 0xfd, 0}, - {0x073f, 0xf2, 0}, - {0x0740, 0xed, 0}, - {0x0741, 0xf4, 0}, - {0x0742, 0x03, 0}, - {0x0743, 0x15, 0}, - {0x0744, 0x1d, 0}, - {0x0745, 0x15, 0}, - {0x0746, 0xfc, 0}, - {0x0747, 0xde, 0}, - {0x0748, 0xcc, 0}, - {0x0749, 0xd6, 0}, - {0x074a, 0x04, 0}, - {0x074b, 0x4f, 0}, - {0x074c, 0x00, 0}, - {0x074d, 0xa2, 0}, - {0x074e, 0x00, 0}, - {0x074f, 0xe3, 0}, - {0x0750, 0x00, 0}, - {0x0751, 0xfc, 0}, - {0x0752, 0x00, 0}, - {0x0753, 0x03, 0}, - {0x0500, 0x02, 0}, - {0x05e7, 0x00, 0}, - {0x05e8, 0x00, 0}, - {0x0f09, 0x18, 0}, - {0x070c, 0x20, 0}, - {0x070d, 0x49, 0}, - {0x070e, 0x37, 0}, - {0x070f, 0x00, 0}, - {0x0710, 0x00, 0}, - {0x0711, 0x00, 0}, - {0x0716, 0xf0, 0}, - {0x090f, 0x00, 0}, - {0x0900, 0x01, 1}, - {0x0900, 0x00, 0}, - {0x0001, 0xf5, 0}, - {0x0001, 0xf5, 1}, - {0x0001, 0xf5, 1}, - {0x0001, 0xf5, 1}, - {0x0001, 0xf5, 1}, - {0x0001, 0x05, 0}, - {0x0001, 0x05, 1}, - {0x0000, 0x00, 1} -}; - -void dtvpll_lock_init(void) -{ - mutex_init(&dtvpll_init_lock); -} - -void dtvpll_init_flag(int on) -{ - mutex_lock(&dtvpll_init_lock); - dtvpll_init = on; - mutex_unlock(&dtvpll_init_lock); - pr_err("%s %d\n", __func__, on); -} - -int get_dtvpll_init_flag(void) -{ - int val; - - mutex_lock(&dtvpll_init_lock); - val = dtvpll_init; - mutex_unlock(&dtvpll_init_lock); - if (!val) - pr_err("%s: %d\n", __func__, val); - return val; -} - -void adc_dpll_setup(int clk_a, int clk_b, int clk_sys) -{ - int unit, found, ena, enb, div2; - int pll_m, pll_n, pll_od_a, pll_od_b, pll_xd_a, pll_xd_b; - long freq_osc, freq_dco, freq_b, freq_a, freq_sys; - long freq_b_act, freq_a_act, freq_sys_act, err_tmp, best_err; - union adc_pll_cntl adc_pll_cntl; - union adc_pll_cntl2 adc_pll_cntl2; - union adc_pll_cntl3 adc_pll_cntl3; - union adc_pll_cntl4 adc_pll_cntl4; - union demod_dig_clk dig_clk_cfg; - - adc_pll_cntl.d32 = 0; - adc_pll_cntl2.d32 = 0; - adc_pll_cntl3.d32 = 0; - adc_pll_cntl4.d32 = 0; - - pr_dbg("target clk_a %d clk_b %d\n", clk_a, clk_b); - - unit = 10000; /* 10000 as 1 MHz, 0.1 kHz resolution. */ - freq_osc = 24 * unit; - - if (clk_a < 1000) - freq_a = clk_a * unit; - else - freq_a = clk_a * (unit / 1000); - - if (clk_b < 1000) - freq_b = clk_b * unit; - else - freq_b = clk_b * (unit / 1000); - - ena = clk_a > 0 ? 1 : 0; - enb = clk_b > 0 ? 1 : 0; - - if (ena || enb) - adc_pll_cntl3.b.enable = 1; - adc_pll_cntl3.b.reset = 1; - - found = 0; - best_err = 100 * unit; - pll_od_a = 1; - pll_od_b = 1; - pll_n = 1; - for (pll_m = 1; pll_m < 512; pll_m++) { - /* for (pll_n=1; pll_n<=5; pll_n++) { */ - if (is_meson_txl_cpu()) { - freq_dco = freq_osc * pll_m / pll_n / 2;/*txl add div2*/ - if (freq_dco < 700 * unit || freq_dco > 1000 * unit) - continue; - } else { - freq_dco = freq_osc * pll_m / pll_n; - if (freq_dco < 750 * unit || freq_dco > 1550 * unit) - continue; - } - pll_xd_a = freq_dco / (1 << pll_od_a) / freq_a; - pll_xd_b = freq_dco / (1 << pll_od_b) / freq_b; - - freq_a_act = freq_dco / (1 << pll_od_a) / pll_xd_a; - freq_b_act = freq_dco / (1 << pll_od_b) / pll_xd_b; - - err_tmp = (freq_a_act - freq_a) * ena + (freq_b_act - freq_b) * - enb; - - if (err_tmp >= best_err) - continue; - - adc_pll_cntl.b.pll_m = pll_m; - adc_pll_cntl.b.pll_n = pll_n; - adc_pll_cntl.b.pll_od0 = pll_od_b; - adc_pll_cntl.b.pll_od1 = pll_od_a; - adc_pll_cntl.b.pll_xd0 = pll_xd_b; - adc_pll_cntl.b.pll_xd1 = pll_xd_a; - if (is_meson_txl_cpu()) { - adc_pll_cntl4.b.pll_od3 = 0; - adc_pll_cntl.b.pll_od2 = 0; - } else { - adc_pll_cntl2.b.div2_ctrl = - freq_dco > 1000 * unit ? 1 : 0; - } - found = 1; - best_err = err_tmp; - /* } */ - } - - pll_m = adc_pll_cntl.b.pll_m; - pll_n = adc_pll_cntl.b.pll_n; - pll_od_b = adc_pll_cntl.b.pll_od0; - pll_od_a = adc_pll_cntl.b.pll_od1; - pll_xd_b = adc_pll_cntl.b.pll_xd0; - pll_xd_a = adc_pll_cntl.b.pll_xd1; - - if (is_meson_txl_cpu()) - div2 = 1; - else - div2 = adc_pll_cntl2.b.div2_ctrl; - /* - * p_adc_pll_cntl = adc_pll_cntl.d32; - * p_adc_pll_cntl2 = adc_pll_cntl2.d32; - * p_adc_pll_cntl3 = adc_pll_cntl3.d32; - * p_adc_pll_cntl4 = adc_pll_cntl4.d32; - */ - adc_pll_cntl3.b.reset = 0; - /* *p_adc_pll_cntl3 = adc_pll_cntl3.d32; */ - if (!found) { - pr_dbg(" ERROR can't setup %7ld kHz %7ld kHz\n", - freq_b / (unit / 1000), freq_a / (unit / 1000)); - } else { - if (is_meson_txl_cpu()) - freq_dco = freq_osc * pll_m / pll_n / 2; - else - freq_dco = freq_osc * pll_m / pll_n; - pr_dbg(" ADC PLL M %3d N %3d\n", pll_m, pll_n); - pr_dbg(" ADC PLL DCO %ld kHz\n", freq_dco / (unit / 1000)); - - pr_dbg(" ADC PLL XD %3d OD %3d\n", pll_xd_b, pll_od_b); - pr_dbg(" ADC PLL XD %3d OD %3d\n", pll_xd_a, pll_od_a); - - freq_a_act = freq_dco / (1 << pll_od_a) / pll_xd_a; - freq_b_act = freq_dco / (1 << pll_od_b) / pll_xd_b; - - pr_dbg(" B %7ld kHz %7ld kHz\n", - freq_b / (unit / 1000), freq_b_act / (unit / 1000)); - pr_dbg(" A %7ld kHz %7ld kHz\n", - freq_a / (unit / 1000), freq_a_act / (unit / 1000)); - - if (clk_sys > 0) { - dig_clk_cfg.b.demod_clk_en = 1; - dig_clk_cfg.b.demod_clk_sel = 3; - if (clk_sys < 1000) - freq_sys = clk_sys * unit; - else - freq_sys = clk_sys * (unit / 1000); - - dig_clk_cfg.b.demod_clk_div = freq_dco / (1 + div2) / - freq_sys - 1; - freq_sys_act = freq_dco / (1 + div2) / - (dig_clk_cfg.b.demod_clk_div + 1); - pr_dbg(" SYS %7ld kHz div %d+1 %7ld kHz\n", - freq_sys / (unit / 1000), - dig_clk_cfg.b.demod_clk_div, - freq_sys_act / (unit / 1000)); - } else { - dig_clk_cfg.b.demod_clk_en = 0; - } - - /* *p_demod_dig_clk = dig_clk_cfg.d32; */ - } - if (is_meson_txl_cpu()) { - demod_set_demod_reg(TXLTV_ADC_RESET_VALUE, ADC_REG3); - demod_set_demod_reg(adc_pll_cntl.d32, ADC_REG1); - demod_set_demod_reg(dig_clk_cfg.d32, ADC_REG6); - demod_set_demod_reg(TXLTV_ADC_REG3_VALUE, ADC_REG3); - /* debug */ - pr_dbg("[adc][%x]%x\n", ADC_REG1, - demod_read_demod_reg(ADC_REG1)); - pr_dbg("[adc][%x]%x\n", ADC_REG2, - demod_read_demod_reg(ADC_REG2)); - pr_dbg("[adc][%x]%x\n", ADC_REG3, - demod_read_demod_reg(ADC_REG3)); - pr_dbg("[adc][%x]%x\n", ADC_REG4, - demod_read_demod_reg(ADC_REG4)); - pr_dbg("[adc][%x]%x\n", ADC_REG5, - demod_read_demod_reg(ADC_REG5)); - pr_dbg("[adc][%x]%x\n", ADC_REG6, - demod_read_demod_reg(ADC_REG6)); - pr_dbg("[adc][%x]%x\n", ADC_REG7, - demod_read_demod_reg(ADC_REG7)); - pr_dbg("[adc][%x]%x\n", ADC_REG8, - demod_read_demod_reg(ADC_REG8)); - pr_dbg("[adc][%x]%x\n", ADC_REG9, - demod_read_demod_reg(ADC_REG9)); - pr_dbg("[adc][%x]%x\n", ADC_REGB, - demod_read_demod_reg(ADC_REGB)); - pr_dbg("[adc][%x]%x\n", ADC_REGC, - demod_read_demod_reg(ADC_REGC)); - pr_dbg("[adc][%x]%x\n", ADC_REGD, - demod_read_demod_reg(ADC_REGD)); - pr_dbg("[adc][%x]%x\n", ADC_REGE, - demod_read_demod_reg(ADC_REGE)); - pr_dbg("[demod][%x]%x\n", DEMOD_REG1, - demod_read_demod_reg(DEMOD_REG1)); - pr_dbg("[demod][%x]%x\n", DEMOD_REG2, - demod_read_demod_reg(DEMOD_REG2)); - pr_dbg("[demod][%x]%x\n", DEMOD_REG3, - demod_read_demod_reg(DEMOD_REG3)); - } else { - demod_set_demod_reg(ADC_RESET_VALUE, ADC_REG3); /* adc reset */ - demod_set_demod_reg(adc_pll_cntl.d32, ADC_REG1); - demod_set_demod_reg(dig_clk_cfg.d32, ADC_REG6); - demod_set_demod_reg(ADC_REG3_VALUE, ADC_REG3); - /* debug */ - pr_dbg("[adc][%x]%x\n", ADC_REG1, - demod_read_demod_reg(ADC_REG1)); - pr_dbg("[adc][%x]%x\n", ADC_REG2, - demod_read_demod_reg(ADC_REG2)); - pr_dbg("[adc][%x]%x\n", ADC_REG3, - demod_read_demod_reg(ADC_REG3)); - pr_dbg("[adc][%x]%x\n", ADC_REG4, - demod_read_demod_reg(ADC_REG4)); - pr_dbg("[adc][%x]%x\n", ADC_REG6, - demod_read_demod_reg(ADC_REG6)); - pr_dbg("[demod][%x]%x\n", DEMOD_REG1, - demod_read_demod_reg(DEMOD_REG1)); - pr_dbg("[demod][%x]%x\n", DEMOD_REG2, - demod_read_demod_reg(DEMOD_REG2)); - pr_dbg("[demod][%x]%x\n", DEMOD_REG3, - demod_read_demod_reg(DEMOD_REG3)); - } - dtvpll_init_flag(1); -} - -void demod_set_adc_core_clk(int adc_clk, int sys_clk, int dvb_mode) -{ - adc_dpll_setup(25, adc_clk, sys_clk); -} - -void demod_set_cbus_reg(unsigned int data, unsigned int addr) -{ - void __iomem *vaddr; - - pr_dbg("[cbus][write]%x\n", (IO_CBUS_PHY_BASE + (addr << 2))); - vaddr = ioremap((IO_CBUS_PHY_BASE + (addr << 2)), 0x4); - writel(data, vaddr); - iounmap(vaddr); -} - -unsigned int demod_read_cbus_reg(unsigned int addr) -{ -/* return __raw_readl(CBUS_REG_ADDR(addr)); */ - unsigned int tmp; - void __iomem *vaddr; - - vaddr = ioremap((IO_CBUS_PHY_BASE + (addr << 2)), 0x4); - tmp = readl(vaddr); - iounmap(vaddr); -/* tmp = aml_read_cbus(addr); */ - pr_dbg("[cbus][read]%x,data is %x\n", - (IO_CBUS_PHY_BASE + (addr << 2)), tmp); - return tmp; -} - -void demod_set_ao_reg(unsigned int data, unsigned int addr) -{ - void __iomem *vaddr; - -/* pr_dbg("[ao][write]%x,data is %x\n",(IO_AOBUS_BASE+addr),data); */ - vaddr = ioremap((IO_AOBUS_BASE + addr), 0x4); - writel(data, vaddr); - iounmap(vaddr); -} - -unsigned int demod_read_ao_reg(unsigned int addr) -{ - unsigned int tmp; - void __iomem *vaddr; - -/* pr_dbg("[ao][read]%x\n",(IO_AOBUS_BASE+addr)); */ - vaddr = ioremap((IO_AOBUS_BASE + addr), 0x4); - tmp = readl(vaddr); -/* pr_dbg("[ao][read]%x,data is %x\n",(IO_AOBUS_BASE+addr),tmp); */ - iounmap(vaddr); - return tmp; -} - -void demod_set_demod_reg(unsigned int data, unsigned int addr) -{ - void __iomem *vaddr; - - mutex_lock(&mp); -/* printk("[demod][write]%x,data is %x\n",(addr),data); */ - vaddr = ioremap((addr), 0x4); - writel(data, vaddr); - iounmap(vaddr); - mutex_unlock(&mp); -} - -unsigned int demod_read_demod_reg(unsigned int addr) -{ - unsigned int tmp; - void __iomem *vaddr; - - mutex_lock(&mp); - vaddr = ioremap((addr), 0x4); - tmp = readl(vaddr); - iounmap(vaddr); - mutex_unlock(&mp); -/* printk("[demod][read]%x,data is %x\n",(addr),tmp); */ - return tmp; -} - -void demod_power_switch(int pwr_cntl) -{ - int reg_data; -#if 1 - if (pwr_cntl == PWR_ON) { - pr_dbg("[PWR]: Power on demod_comp %x,%x\n", - AO_RTI_GEN_PWR_SLEEP0, AO_RTI_GEN_PWR_ISO0); - /* Powerup demod_comb */ - reg_data = demod_read_ao_reg(AO_RTI_GEN_PWR_SLEEP0); - demod_set_ao_reg((reg_data & (~(0x1 << 10))), - AO_RTI_GEN_PWR_SLEEP0); - /* [10] power on */ - pr_dbg("[PWR]: Power on demod_comp %x,%x\n", - HHI_DEMOD_MEM_PD_REG, RESET0_LEVEL); - /* Power up memory */ - demod_set_demod_reg((demod_read_demod_reg(HHI_DEMOD_MEM_PD_REG) - & (~0x2fff)), HHI_DEMOD_MEM_PD_REG); - /* reset */ - demod_set_demod_reg((demod_read_demod_reg(RESET0_LEVEL) & - (~(0x1 << 8))), RESET0_LEVEL); - /* msleep(20);*/ - - /* remove isolation */ - demod_set_ao_reg( - (demod_read_ao_reg(AO_RTI_GEN_PWR_ISO0) & - (~(0x3 << 14))), AO_RTI_GEN_PWR_ISO0); - /* pull up reset */ - demod_set_demod_reg((demod_read_demod_reg(RESET0_LEVEL) | - (0x1 << 8)), RESET0_LEVEL); -/* *P_RESET0_LEVEL |= (0x1<<8); */ - } else { - pr_dbg("[PWR]: Power off demod_comp\n"); - /* add isolation */ - - demod_set_ao_reg( - (demod_read_ao_reg(AO_RTI_GEN_PWR_ISO0) | - (0x3 << 14)), AO_RTI_GEN_PWR_ISO0); - - /* power down memory */ - demod_set_demod_reg((demod_read_demod_reg(HHI_DEMOD_MEM_PD_REG) - | 0x2fff), HHI_DEMOD_MEM_PD_REG); - /* power down demod_comb */ - reg_data = demod_read_ao_reg(AO_RTI_GEN_PWR_SLEEP0); - demod_set_ao_reg((reg_data | (0x1 << 10)), - AO_RTI_GEN_PWR_SLEEP0); - /* [10] power on */ - } -#endif -} - -static void clocks_set_sys_defaults(unsigned char dvb_mode) -{ - union demod_cfg0 cfg0; - union demod_cfg2 cfg2; - - demod_power_switch(PWR_ON); - - if (is_meson_gxtvbb_cpu()) { - pr_dbg("GX_TV config\n"); - demod_set_demod_reg(ADC_RESET_VALUE, ADC_REG3); - demod_set_demod_reg(ADC_REG1_VALUE, ADC_REG1); - demod_set_demod_reg(ADC_REG2_VALUE, ADC_REG2); - demod_set_demod_reg(ADC_REG4_VALUE, ADC_REG4); - demod_set_demod_reg(ADC_REG3_VALUE, ADC_REG3); - /* dadc */ - demod_set_demod_reg(ADC_REG7_VALUE, ADC_REG7); - demod_set_demod_reg(ADC_REG8_VALUE, ADC_REG8); - demod_set_demod_reg(ADC_REG9_VALUE, ADC_REG9); - demod_set_demod_reg(ADC_REGA_VALUE, ADC_REGA); - } else if (is_meson_txl_cpu()) { - pr_dbg("TXL_TV config\n"); - demod_set_demod_reg(TXLTV_ADC_REG3_VALUE, ADC_REG3); - demod_set_demod_reg(TXLTV_ADC_REG1_VALUE, ADC_REG1); - demod_set_demod_reg(TXLTV_ADC_REGB_VALUE, ADC_REGB); - demod_set_demod_reg(TXLTV_ADC_REG2_VALUE, ADC_REG2); - demod_set_demod_reg(TXLTV_ADC_REG3_VALUE, ADC_REG3); - demod_set_demod_reg(TXLTV_ADC_REG4_VALUE, ADC_REG4); - demod_set_demod_reg(TXLTV_ADC_REGC_VALUE, ADC_REGC); - demod_set_demod_reg(TXLTV_ADC_REGD_VALUE, ADC_REGD); - demod_set_demod_reg(TXLTV_ADC_RESET_VALUE, ADC_REG3); - demod_set_demod_reg(TXLTV_ADC_REG3_VALUE, ADC_REG3); - - /* dadc */ - demod_set_demod_reg(TXLTV_ADC_REG7_VALUE, ADC_REG7); - demod_set_demod_reg(TXLTV_ADC_REG8_VALUE, ADC_REG8); - demod_set_demod_reg(TXLTV_ADC_REG9_VALUE, ADC_REG9); - demod_set_demod_reg(TXLTV_ADC_REGE_VALUE, ADC_REGE); - } - - demod_set_demod_reg(DEMOD_REG1_VALUE, DEMOD_REG1); - demod_set_demod_reg(DEMOD_REG2_VALUE, DEMOD_REG2); - demod_set_demod_reg(DEMOD_REG3_VALUE, DEMOD_REG3); - cfg0.b.mode = 7; - cfg0.b.adc_format = 1; - if (dvb_mode == Gxtv_Dvbc) { /* // 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC */ - cfg0.b.ts_sel = 2; - } else if ((dvb_mode == Gxtv_Dvbt_Isdbt) || (dvb_mode == Gxtv_Dtmb)) { - cfg0.b.ts_sel = 1; - cfg0.b.adc_regout = 1; - } else if (dvb_mode == Gxtv_Atsc) { - cfg0.b.ts_sel = 4; - } - demod_set_demod_reg(cfg0.d32, DEMOD_REG1); - cfg2.b.biasgen_en = 1; - cfg2.b.en_adc = 1; - demod_set_demod_reg(cfg2.d32, DEMOD_REG3); - pr_dbg("0xc8020c00 is %x,dvb_mode is %d\n", - demod_read_demod_reg(DEMOD_REG1), dvb_mode); -} - -void dtmb_write_reg(int reg_addr, int reg_data) -{ - if (!get_dtvpll_init_flag()) - return; - demod_set_demod_reg(reg_data, reg_addr); -/* apb_write_reg(reg_addr,reg_data); */ -} - -int dtmb_read_reg(int reg_addr) -{ - if (!get_dtvpll_init_flag()) - return 0; - return demod_read_demod_reg(reg_addr); /* apb_read_reg(reg_addr); */ -} - -void atsc_write_reg(int reg_addr, int reg_data) -{ - if (!get_dtvpll_init_flag()) - return; - apb_write_reg(ATSC_BASE, (reg_addr & 0xffff) << 8 | (reg_data & 0xff)); -} - -unsigned long atsc_read_reg(int reg_addr) -{ - unsigned long tmp; - - if (!get_dtvpll_init_flag()) - return 0; - apb_write_reg(ATSC_BASE + 4, (reg_addr & 0xffff) << 8); - tmp = apb_read_reg(ATSC_BASE); - - return tmp & 0xff; -} - -unsigned long atsc_read_iqr_reg(void) -{ - unsigned long tmp; - - tmp = apb_read_reg(ATSC_BASE + 8); - pr_dbg("[atsc irq] is %lx\n", tmp); - return tmp & 0xffffffff; -} - -int atsc_qam_set(fe_modulation_t mode) -{ - int i, j; - - if (mode == VSB_8) { /* 5-8vsb, 2-64qam, 4-256qam */ - for (i = 0; list_8vsb[i].adr != 0; i++) { - if (list_8vsb[i].rw) - atsc_read_reg(list_8vsb[i].adr); - /* msleep(20); */ - else - atsc_write_reg(list_8vsb[i].adr, - list_8vsb[i].dat); - /* msleep(20); */ - } - j = 15589; - pr_dbg("8-vsb mode\n"); - } else if (mode == QAM_64) { - for (i = 0; list_qam64[i].adr != 0; i++) { - if (list_qam64[i].rw) { - atsc_read_reg(list_qam64[i].adr); - msleep(20); - } else { - atsc_write_reg(list_qam64[i].adr, - list_qam64[i].dat); - msleep(20); - } - } - j = 16588; /* 33177; */ - pr_dbg("64qam mode\n"); - } else if (mode == QAM_256) { - for (i = 0; list_qam256[i].adr != 0; i++) { - if (list_qam256[i].rw) { - atsc_read_reg(list_qam256[i].adr); - msleep(20); - } else { - atsc_write_reg(list_qam256[i].adr, - list_qam256[i].dat); - msleep(20); - } - } - j = 15649; /* 31298; */ - pr_dbg("256qam mode\n"); - } else { - for (i = 0; list_qam256[i].adr != 0; i++) { - if (list_qam256[i].rw) { - atsc_read_reg(list_qam256[i].adr); - msleep(20); - } else { - atsc_write_reg(list_qam256[i].adr, - list_qam256[i].dat); - msleep(20); - } - } - j = 15649; /* 31298; */ - pr_dbg("256qam mode\n"); - } - return j; -} - -void atsc_initial(struct aml_demod_sta *demod_sta) -{ - int fc, fs, cr, ck, j; - fe_modulation_t mode; - - mode = demod_sta->ch_mode; - - j = atsc_qam_set(mode); /* set mode */ - - fs = demod_sta->adc_freq; /* KHZ 25200 */ - fc = demod_sta->ch_if; /* KHZ 6350 */ - - cr = (fc * (1 << 17) / fs) * (1 << 6); - ck = fs * j / 10 - (1 << 25); - /* ck_rate = (f_samp / f_vsb /2 -1)*(1<<25); - *double f_vsb = 10.76238;// double f_64q = 5.056941; - * // double f_256q = 5.360537; - */ - - atsc_write_reg(0x070e, cr & 0xff); - atsc_write_reg(0x070d, (cr >> 8) & 0xff); - atsc_write_reg(0x070c, (cr >> 16) & 0xff); - - if (demod_sta->ch_mode == VSB_8) { - atsc_write_reg(0x0711, ck & 0xff); - atsc_write_reg(0x0710, (ck >> 8) & 0xff); - atsc_write_reg(0x070f, (ck >> 16) & 0xff); - } - pr_dbg("0x70e is %x, 0x70d is %x, 0x70c is %x\n", cr & 0xff, - (cr >> 8) & 0xff, (cr >> 16) & 0xff); - pr_dbg("fs is %d(SR),fc is %d(IF),cr is %x,ck is %x\n", fs, fc, cr, ck); -} - -int atsc_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_atsc *demod_atsc) -{ - int ret = 0; - u8 demod_mode; - u8 bw, sr, ifreq, agc_mode; - u32 ch_freq; - - bw = demod_atsc->bw; - sr = demod_atsc->sr; - ifreq = demod_atsc->ifreq; - agc_mode = demod_atsc->agc_mode; - ch_freq = demod_atsc->ch_freq; - demod_mode = demod_atsc->dat0; - demod_sta->ch_mode = demod_atsc->mode; /* TODO */ - demod_sta->agc_mode = agc_mode; - demod_sta->ch_freq = ch_freq; - demod_sta->dvb_mode = demod_mode; - demod_sta->ch_bw = (8 - bw) * 1000; - atsc_initial(demod_sta); - pr_dbg("ATSC mode\n"); - return ret; -} - -#if 0 -static dtmb_cfg_t list_dtmb_v1[99] = { - {0x00000000, 0x01, 0}, - {0x00001000, 0x02, 0}, - {0x00000000, 0x03, 0}, - {0x00000000, 0x04, 0}, - {0x00000000, 0x05, 0}, - {0x00000000, 0x06, 0}, - {0x007fffff, 0x07, 0}, - {0x0000000f, 0x08, 0}, - {0x00003000, 0x09, 0}, - {0x00000001, 0x0a, 0}, - {0x0c403006, 0x0b, 0}, - {0x44444400, 0x0c, 0}, - {0x1412c320, 0x0d, 0}, - {0x00000152, 0x10, 0}, - {0x47080137, 0x11, 0}, - {0x02200a16, 0x12, 0}, - {0x42190190, 0x13, 0}, - {0x7f807f80, 0x14, 0}, - {0x0000199a, 0x15, 0}, - {0x000a1466, 0x18, 0}, - {0x00274217, 0x1a, 0}, - {0x00131036, 0x1b, 1}, - {0x00000396, 0x1c, 0}, - {0x0037f3cc, 0x1d, 0}, - {0x00000029, 0x1e, 0}, - {0x0004f031, 0x1f, 0}, - {0x00f3cbd4, 0x20, 0}, - {0x0000007e, 0x21, 0}, - {0x23270b6a, 0x22, 0}, - {0x5f700c1b, 0x23, 0}, - {0x00133c2b, 0x24, 0}, - {0x2d3e0f12, 0x25, 0}, - {0x06363038, 0x26, 0}, - {0x060e0a3e, 0x27, 0}, - {0x0015161f, 0x28, 0}, - {0x0809031b, 0x29, 0}, - {0x181c0307, 0x2a, 0}, - {0x051f1a1b, 0x2b, 0}, - {0x00451dce, 0x2c, 0}, - {0x242fde12, 0x2d, 0}, - {0x0034e8fa, 0x2e, 0}, - {0x00000007, 0x30, 0}, - {0x16000d0c, 0x31, 0}, - {0x0000011f, 0x32, 0}, - {0x01000200, 0x33, 0}, - {0x10bbf376, 0x34, 0}, - {0x00000044, 0x35, 0}, - {0x00000000, 0x36, 0}, - {0x00000000, 0x37, 0}, - {0x00000000, 0x38, 0}, - {0x00000000, 0x39, 0}, - {0x00000031, 0x3a, 0}, - {0x4d6b0a58, 0x3b, 0}, - {0x00000c04, 0x3c, 0}, - {0x0d3b0a50, 0x3d, 0}, - {0x03140480, 0x3e, 0}, - {0x05e60452, 0x3f, 0}, - {0x05780400, 0x40, 0}, - {0x0063c025, 0x41, 0}, - {0x05050202, 0x42, 0}, - {0x5e4a0a14, 0x43, 0}, - {0x00003b42, 0x44, 0}, - {0xa53080ff, 0x45, 0}, - {0x00000000, 0x46, 0}, - {0x00133202, 0x47, 0}, - {0x01f00000, 0x48, 0}, - {0x00000000, 0x49, 0}, - {0x00000000, 0x4a, 0}, - {0x00000000, 0x4b, 0}, - {0x00000000, 0x4c, 0}, - {0x20405dc8, 0x4d, 0}, - {0x00000000, 0x4e, 0}, - {0x1f0205df, 0x4f, 0}, - {0x00001120, 0x50, 0}, - {0x4f190803, 0x51, 0}, - {0x00000000, 0x52, 0}, - {0x00000040, 0x53, 0}, - {0x00100050, 0x54, 0}, - {0x00cd1000, 0x55, 0}, - {0x00010fab, 0x56, 0}, - {0x03f0fc3f, 0x58, 0}, - {0x02005014, 0x59, 0}, - {0x01405014, 0x5a, 0}, - {0x00014284, 0x5b, 0}, - {0x00000320, 0x5c, 0}, - {0x14130e05, 0x5d, 0}, - {0x4321c963, 0x5f, 0}, - {0x624668f8, 0x60, 0}, - {0xccc08888, 0x61, 0}, - {0x13212111, 0x62, 0}, - {0x21100000, 0x63, 0}, - {0x624668f8, 0x64, 0}, - {0xccc08888, 0x65, 0}, - {0x13212111, 0x66, 0}, - {0x21100000, 0x67, 0}, - {0x624668f8, 0x68, 0}, - {0xccc08888, 0x69, 0}, - {0x0, 0x0, 0} -}; -#endif - -void dtmb_all_reset(void) -{ - int temp_data = 0; - - if (is_meson_txl_cpu()) { - dtmb_write_reg(DTMB_FRONT_AFIFO_ADC, 0x1f); - /*modified bu xiaotong*/ - dtmb_write_reg(DTMB_CHE_TPS_CONFIG, 0xc00000); - dtmb_write_reg(DTMB_CHE_EQ_CONFIG, 0x1a027719); - dtmb_write_reg(DTMB_FRONT_AGC_CONFIG1, 0x101a7); - dtmb_write_reg(DTMB_FRONT_47_CONFIG, 0x131a31); - /*detect 64qam 420 595 problems*/ - dtmb_write_reg(DTMB_FRONT_19_CONFIG, 0x300); - dtmb_write_reg(DTMB_FRONT_4d_CONFIG, 0x12ffbe0); - /*fix fsm b bug*/ - dtmb_write_reg(DTMB_FRONT_DEBUG_CFG, 0x5680000); - /*fix agc problem,skip warm_up status*/ - dtmb_write_reg(DTMB_FRONT_46_CONFIG, 0x1a000f0f); - dtmb_write_reg(DTMB_FRONT_ST_FREQ, 0xf2400000); - } else { - dtmb_write_reg(DTMB_FRONT_AGC_CONFIG1, 0x10127); - dtmb_write_reg(DTMB_CHE_IBDFE_CONFIG6, 0x943228cc); - dtmb_write_reg(DTMB_CHE_IBDFE_CONFIG7, 0xc09aa8cd); - dtmb_write_reg(DTMB_CHE_FD_TD_COEFF, 0x0); - dtmb_write_reg(DTMB_CHE_EQ_CONFIG, 0x9dc59); - /*0x2 is auto,0x406 is invert spectrum*/ - if (dtmb_spectrum == 0) - dtmb_write_reg(DTMB_TOP_CTRL_TPS, 0x406); - else if (dtmb_spectrum == 1) - dtmb_write_reg(DTMB_TOP_CTRL_TPS, 0x402); - else - dtmb_write_reg(DTMB_TOP_CTRL_TPS, 0x2); - - pr_dbg("dtmb_spectrum is %d\n", dtmb_spectrum); - dtmb_write_reg(DTMB_TOP_CTRL_FEC, 0x41444400); - dtmb_write_reg(DTMB_TOP_CTRL_INTLV_TIME, 0x180300); - dtmb_write_reg(DTMB_FRONT_DDC_BYPASS, 0x662ca0); - dtmb_write_reg(DTMB_FRONT_AFIFO_ADC, 0x29); - dtmb_write_reg(DTMB_FRONT_DC_HOLD, 0xa1066); - /*cci para*/ - dtmb_write_reg(DTMB_CHE_M_CCI_THR_CONFIG3, 0x80201f6); - dtmb_write_reg(DTMB_CHE_M_CCI_THR_CONFIG2, 0x3f20080); - dtmb_write_reg(DTMB_CHE_TPS_CONFIG, 0xc00000); - dtmb_write_reg(DTMB_TOP_CTRL_AGC, 0x3); - dtmb_write_reg(DTMB_TOP_CTRL_TS_SFO_CFO, 0x20403006); - dtmb_write_reg(DTMB_FRONT_AGC_CONFIG2, 0x7200a16); - dtmb_write_reg(DTMB_FRONT_DEBUG_CFG, 0x1e00000); - dtmb_write_reg(DTMB_TOP_CTRL_ENABLE, 0x7fffff); - /*close ts3 timing loop*/ - dtmb_write_reg(DTMB_TOP_CTRL_DAGC_CCI, 0x305); - /*dektec card issue,close f case snr drop*/ - dtmb_write_reg(DTMB_CHE_MC_SC_TIMING_POWTHR, 0xc06100a); - if (demod_enable_performance) { - dtmb_write_reg(DTMB_CHE_IBDFE_CONFIG1, 0x4040002); - temp_data = dtmb_read_reg(DTMB_CHE_FD_TD_COEFF); - temp_data = (temp_data & ~0x3fff)|(0x241f & 0x3fff); - temp_data = temp_data | (1<<21); - /*Set freeze_mode and reset coeff*/ - dtmb_write_reg(DTMB_CHE_FD_TD_COEFF, temp_data); - temp_data = temp_data & ~(1<<21); - /*Set freeze_mode and reset coeff*/ - dtmb_write_reg(DTMB_CHE_FD_TD_COEFF, temp_data); - } - } -} - -void dtmb_initial(struct aml_demod_sta *demod_sta) -{ -/* dtmb_write_reg(0x049, memstart); //only for init */ - dtmb_spectrum = 1; - dtmb_spectrum = demod_sta->spectrum; - dtmb_register_reset(); - dtmb_all_reset(); -#if 0 - int i; - - for (i = 0; list_dtmb_v1[i].adr != 0; i++) { - if (list_dtmb_v1[i].rw) - apb_read_reg(DTMB_BASE + ((list_dtmb_v1[i].adr) << 2)); - /* msleep(20); */ - else - apb_write_reg(DTMB_BASE + ((list_dtmb_v1[i].adr) << 2), - list_dtmb_v1[i].dat); - /* msleep(20); */ - } -#endif -} - -int check_dtmb_fec_lock(void) -{ - int fec_lock, snr, status; - - fec_lock = (dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) >> 14) & 0x1; - snr = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) & 0x3fff; - if (fec_lock && (snr > 4)) - status = 1; - else - status = 0; - return status; -} - -int check_dtmb_mobile_det(void) -{ - int mobile_det = 0; - - mobile_det = (dtmb_read_reg(DTMB_TOP_CTRL_SYS_OFDM_CNT) >> 8) & 0x7ffff; - return mobile_det; - -} - - -int dtmb_information(void) -{ - int tps, snr, fec_lock, fec_bch_add, fec_ldpc_unc_acc, fec_ldpc_it_avg, - tmp, che_snr; - struct aml_fe_dev *dev; - - dev = NULL; - tps = dtmb_read_reg(DTMB_TOP_CTRL_CHE_WORKCNT); - tmp = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR); - if (is_meson_txl_cpu()) - che_snr = tmp & 0x3fff; - else - che_snr = tmp & 0xfff; - snr = che_snr; - snr = convert_snr(snr); - /* if (che_snr >= 8192) */ - /* che_snr = che_snr - 16384;*/ - /* snr = che_snr / 32;*/ - /* snr = 10*log10(snr)-6; */ - fec_lock = (dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) >> 14) & 0x1; - fec_bch_add = dtmb_read_reg(DTMB_TOP_FEC_BCH_ACC); - fec_ldpc_unc_acc = dtmb_read_reg(DTMB_TOP_FEC_LDPC_UNC_ACC); - fec_ldpc_it_avg = dtmb_read_reg(DTMB_TOP_FEC_LDPC_IT_AVG); - pr_dbg("¡¾FSM ¡¿: %x %x %x %x\n", - dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0), - dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE1), - dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE2), - dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE3)); - pr_dbg - ("¡¾AGC ¡¿: agc_power %d,agc_if_gain %d,agc_rf_gain %d,", - (-(((dtmb_read_reg(DTMB_TOP_FRONT_AGC) >> 22) & 0x3ff) / 16)), - ((dtmb_read_reg(DTMB_TOP_FRONT_AGC)) & 0x3ff), - ((dtmb_read_reg(DTMB_TOP_FRONT_AGC) >> 11) & 0x7ff)); - pr_dbg - ("dagc_power %3d,dagc_gain %3d mobi_det_power %d\n", - ((dtmb_read_reg(DTMB_TOP_FRONT_DAGC) >> 0) & 0xff), - ((dtmb_read_reg(DTMB_TOP_FRONT_DAGC) >> 8) & 0xfff), - (dtmb_read_reg(DTMB_TOP_CTRL_SYS_OFDM_CNT) >> 8) & 0x7ffff); - pr_dbg - ("¡¾TPS ¡¿ SC or MC %2d,f_r %2d qam_nr %2d ", - (dtmb_read_reg(DTMB_TOP_CHE_OBS_STATE1) >> 1) & 0x1, - (tps >> 22) & 0x1, (tps >> 21) & 0x1); - pr_dbg - ("intlv %2d,cr %2d constl %2d\n", - (tps >> 20) & 0x1, - (tps >> 18) & 0x3, (tps >> 16) & 0x3); - - pr_dbg - ("[dtmb] snr is %d,fec_lock is %d,fec_bch_add is %d,", - snr, fec_lock, fec_bch_add); - pr_dbg - ("fec_ldpc_unc_acc is %d ,fec_ldpc_it_avg is %d\n", - fec_ldpc_unc_acc, - fec_ldpc_it_avg / 256); - pr_dbg - ("------------------------------------------------------------\n"); - - tuner_get_ch_power(dev); - - return 0; -} - -int dtmb_check_cci(void) -{ - int cci_det = 0; - - cci_det = - ((dtmb_read_reg(DTMB_TOP_SYNC_CCI_NF2_POSITION) >> 22) - & 0x3); - if (cci_det > 0) { - pr_dbg("find cci\n"); - dtmb_write_reg(DTMB_CHE_CCIDET_CONFIG, 0x20210290); - dtmb_write_reg(DTMB_CHE_M_CCI_THR_CONFIG3, 0x20081f6); - dtmb_write_reg(DTMB_CHE_M_CCI_THR_CONFIG2, 0x3f08020); - } - return cci_det; -} - -int dtmb_bch_check(void) -{ - int fec_bch_add, i; - - fec_bch_add = dtmb_read_reg(DTMB_TOP_FEC_BCH_ACC); - pr_dbg("[debug]fec lock,fec_bch_add is %d\n", fec_bch_add); - msleep(100); - if (((dtmb_read_reg(DTMB_TOP_FEC_BCH_ACC))-fec_bch_add) >= 50) { - pr_dbg("[debug]fec lock,but bch add ,need reset,wait not to reset\n"); - dtmb_reset(); - for (i = 0; i < 30; i++) { - msleep(100); - if (check_dtmb_fec_lock() == 1) { - pr_dbg("[debug]fec lock,but bch add ,need reset,now is lock\n"); - return 0; - } - } - } - return 0; -} - -int dtmb_constell_check(void) -{ - int constell; - - constell = dtmb_read_reg(DTMB_TOP_CTRL_CHE_WORKCNT)>>16 & 0x3; - if (constell == 0)/*4qam*/ - dtmb_write_reg(DTMB_FRONT_47_CONFIG, 0x133221); - else if (constell == 1)/*16qam*/ - dtmb_write_reg(DTMB_FRONT_47_CONFIG, 0x132821); - else if (constell == 2)/*32qam*/ - dtmb_write_reg(DTMB_FRONT_47_CONFIG, 0x131e21); - else if (constell == 3)/*64qam*/ - dtmb_write_reg(DTMB_FRONT_47_CONFIG, 0x131a31); - - return 0; -} - - -int dtmb_check_fsm(void) -{ - int tmp, fsm_status, i, has_singnal; - - tmp = dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0); - fsm_status = tmp&0xffffffff; - has_singnal = 0; - pr_dbg("[rsj1] fsm_status is %x\n", fsm_status); - for (i = 0 ; i < 8 ; i++) { - if (((fsm_status >> (i*4)) & 0xf) > 3) { - /*has signal*/ - /* pr_dbg("has signal\n");*/ - has_singnal = 1; - } - } - return has_singnal; - -} - -int patch_ts3(int delay1_us, int delay2_us) -{ - if (((dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0)&0xf) == 0x7)&1) { - dtmb_write_reg(DTMB_TOP_CTRL_FSM, 0x300f); - dtmb_write_reg(DTMB_TOP_CTRL_FSM, 0x310f); - msleep(delay1_us); - dtmb_write_reg(DTMB_TOP_CTRL_ENABLE, 0xffdfff); - dtmb_write_reg(DTMB_TOP_CTRL_ENABLE, 0xffffff); - dtmb_write_reg(DTMB_TOP_CTRL_FSM, 0x3110); - dtmb_write_reg(DTMB_TOP_CTRL_FSM, 0x3010); - dtmb_write_reg(DTMB_TOP_CTRL_FSM, 0x3000); - return 1; - } else - return 0; -} - - -int read_cfo_all(void) -{ - int icfo_all, fcfo_all; - - icfo_all = dtmb_read_reg(DTMB_TOP_CTRL_ICFO_ALL) & 0xfffff; - fcfo_all = dtmb_read_reg(DTMB_TOP_CTRL_FCFO_ALL) & 0x3fff; - if (icfo_all > (1 << 19)) - icfo_all = icfo_all - (1 << 20); - if (fcfo_all > (1 << 13)) - fcfo_all = fcfo_all - (1 << 14); - - return (int)(icfo_all*4+fcfo_all); - -} - - -int dtmb_v3_soft_sync(int cfo_init) -{ - -/* int cfo_all;*/ -/* int cfo_setting;*/ - - if (cfo_init == 0) { - cfo_init = patch_ts3(11, 0); - #if 0 - if (cfo_init == 1) { - cfo_all = read_cfo_all(); - cfo_setting = dtmb_read_reg(DTMB_FRONT_DDC_BYPASS); - dtmb_write_reg(DTMB_FRONT_DDC_BYPASS, - cfo_setting+cfo_all); - dtmb_write_reg(DTMB_TOP_CTRL_LOOP, 0x3); - dtmb_reset(); - } - #endif - } - return cfo_init; - -} - -int dtmb_check_status_gxtv(struct dvb_frontend *fe) -{ - int local_state; - int time_cnt;/* cci_det, src_config;*/ - int cfo_init, count; - - dtmb_information(); - time_cnt = 0; - local_state = 0; - cfo_init = 0; - if (check_dtmb_fec_lock() != 1) { - dtmb_register_reset(); - dtmb_all_reset(); - count = 15; - while ((count) && - ((dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0)&0xf) < 0x6)) { - msleep(20); - count--; - } - - count = demod_sync_count; - while ((count) && (cfo_init == 0)) { - - cfo_init = dtmb_v3_soft_sync(cfo_init); - - msleep(demod_sync_delay_time); - count--; - } - if ((cfo_init == 0) && - ((dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0)&0xf) <= 7)) { - pr_dbg("over 400ms,status is %x, need reset\n", - (dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0)&0xf)); - return 0; - } - while ((time_cnt < 10) && (check_dtmb_fec_lock() != 1)) { - msleep(demod_timeout); - time_cnt++; - local_state = AMLOGIC_DTMB_STEP3; - dtmb_information(); - dtmb_check_cci(); - if (time_cnt > 8) - pr_dbg - ("* local_state = %d\n", local_state); - } - if (time_cnt >= 10 && (check_dtmb_fec_lock() != 1)) { - local_state = AMLOGIC_DTMB_STEP4; - time_cnt = 0; - pr_dbg - ("*all reset,timeout is %d\n", demod_timeout); - } - } else { - dtmb_check_cci(); - dtmb_bch_check(); - #if 0 - cci_det = dtmb_check_cci(); - if ((check_dtmb_mobile_det() <= demod_mobile_power) - && (cci_det == 0)) { - /* open */ - src_config = (dtmb_read_reg(DTMB_FRONT_SRC_CONFIG1)); - dtmb_write_reg(DTMB_FRONT_SRC_CONFIG1, - src_config & (~(0x1 << 28))); - } else { - /* close */ - src_config = (dtmb_read_reg(DTMB_FRONT_SRC_CONFIG1)); - dtmb_write_reg(DTMB_FRONT_SRC_CONFIG1, - src_config | (0x1 << 28)); - } - #endif - } - if (check_dtmb_fec_lock() == 1) - dtmb_write_reg(DTMB_TOP_CTRL_LOOP, 0xf); - return 0; -} - - -int dtmb_check_status_txl(struct dvb_frontend *fe) -{ - int time_cnt; - - time_cnt = 0; - dtmb_information(); - if (check_dtmb_fec_lock() != 1) { - while ((time_cnt < 10) && (check_dtmb_fec_lock() != 1)) { - msleep(demod_timeout); - time_cnt++; - dtmb_information(); - if (((dtmb_read_reg(DTMB_TOP_CTRL_CHE_WORKCNT) - >> 21) & 0x1) == 0x1) { - pr_dbg("4qam-nr,need set spectrum\n"); - if (dtmb_spectrum == 1) { - dtmb_write_reg - (DTMB_TOP_CTRL_TPS, 0x1010406); - } else if (dtmb_spectrum == 0) { - dtmb_write_reg - (DTMB_TOP_CTRL_TPS, 0x1010402); - } else { - dtmb_write_reg - (DTMB_TOP_CTRL_TPS, 0x1010002); - } - } - if (time_cnt > 8) - pr_dbg - ("* time_cnt = %d\n", time_cnt); - } - if (time_cnt >= 10 && (check_dtmb_fec_lock() != 1)) { - time_cnt = 0; - dtmb_register_reset(); - dtmb_all_reset(); - if (dtmb_spectrum == 0) - dtmb_spectrum = 1; - else - dtmb_spectrum = 0; - pr_dbg - ("*all reset,timeout is %d\n", demod_timeout); - } - } else { - dtmb_bch_check(); - dtmb_constell_check(); - } - return 0; -} - - -void dtmb_reset(void) -{ - union DTMB_TOP_CTRL_SW_RST_BITS sw_rst; - - sw_rst.b.ctrl_sw_rst = 1; - sw_rst.b.ctrl_sw_rst_noreg = 1; - dtmb_write_reg(DTMB_TOP_CTRL_SW_RST, sw_rst.d32); - sw_rst.b.ctrl_sw_rst = 0; - sw_rst.b.ctrl_sw_rst_noreg = 0; - dtmb_write_reg(DTMB_TOP_CTRL_SW_RST, sw_rst.d32); -} - -void dtmb_register_reset(void) -{ - union DTMB_TOP_CTRL_SW_RST_BITS sw_rst; - - sw_rst.b.ctrl_sw_rst = 1; - dtmb_write_reg(DTMB_TOP_CTRL_SW_RST, sw_rst.d32); - sw_rst.b.ctrl_sw_rst = 0; - dtmb_write_reg(DTMB_TOP_CTRL_SW_RST, sw_rst.d32); -} - -int dtmb_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dtmb *demod_dtmb) -{ - int ret = 0; - u8 demod_mode; - u8 bw, sr, ifreq, agc_mode; - u32 ch_freq; - - bw = demod_dtmb->bw; - sr = demod_dtmb->sr; - ifreq = demod_dtmb->ifreq; - agc_mode = demod_dtmb->agc_mode; - ch_freq = demod_dtmb->ch_freq; - demod_mode = demod_dtmb->dat0; - demod_sta->ch_mode = demod_dtmb->mode; /* TODO */ - demod_sta->agc_mode = agc_mode; - demod_sta->ch_freq = ch_freq; - demod_sta->dvb_mode = demod_mode; - demod_sta->ch_bw = (8 - bw) * 1000; - dtmb_initial(demod_sta); - pr_dbg("DTMB mode\n"); - return ret; -} - -int dvbt_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dvbt *demod_dvbt) -{ - int ret = 0; - u8_t demod_mode = 1; - u8_t bw, sr, ifreq, agc_mode; - u32_t ch_freq; - - bw = demod_dvbt->bw; - sr = demod_dvbt->sr; - ifreq = demod_dvbt->ifreq; - agc_mode = demod_dvbt->agc_mode; - ch_freq = demod_dvbt->ch_freq; - demod_mode = demod_dvbt->dat0; - if (ch_freq < 1000 || ch_freq > 900000000) { - /* pr_dbg("Error: Invalid Channel Freq option %d\n", - *ch_freq); - */ - ch_freq = 474000; - ret = -1; - } - - if (demod_mode < 0 || demod_mode > 4) { - /* pr_dbg("Error: Invalid demod mode option %d\n", - *demod_mode); - */ - demod_mode = 1; - ret = -1; - } - - /* demod_sta->dvb_mode = 1; */ - demod_sta->ch_mode = 0; /* TODO */ - demod_sta->agc_mode = agc_mode; - demod_sta->ch_freq = ch_freq; - demod_sta->dvb_mode = demod_mode; - /* if (demod_i2c->tuner == 1) - * demod_sta->ch_if = 36130; - * else if (demod_i2c->tuner == 2) - * demod_sta->ch_if = 4570; - * else if (demod_i2c->tuner == 3) - * demod_sta->ch_if = 4000;// It is nouse.(alan) - * else if (demod_i2c->tuner == 7) - * demod_sta->ch_if = 5000;//silab 5000kHz IF - */ - - demod_sta->ch_bw = (8 - bw) * 1000; - demod_sta->symb_rate = 0; /* TODO */ - -/* bw=0; */ - demod_mode = 1; - /* for si2176 IF:5M sr 28.57 */ - sr = 4; - ifreq = 4; - if (bw == BANDWIDTH_AUTO) - demod_mode = 2; - ofdm_initial(bw, - /* 00:8M 01:7M 10:6M 11:5M */ - sr, - /* 00:45M 01:20.8333M 10:20.7M 11:28.57 100:24m */ - ifreq, - /* 000:36.13M 001:-5.5M 010:4.57M 011:4M 100:5M */ - demod_mode - 1, - /* 00:DVBT,01:ISDBT */ - 1 - /* 0: Unsigned, 1:TC */ - ); - pr_dbg("DVBT/ISDBT mode\n"); - - return ret; -} - -int demod_set_sys(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_sys *demod_sys) -{ -/* int adc_clk; */ -/* demod_sta->tmp=Adc_mode; */ - unsigned char dvb_mode; - int clk_adc, clk_dem; - int gpioDV_2; - int gpiW_2; - - dvb_mode = demod_sta->dvb_mode; - clk_adc = demod_sys->adc_clk; - clk_dem = demod_sys->demod_clk; - pr_dbg - ("demod_set_sys,clk_adc is %d,clk_demod is %d\n", - clk_adc, clk_dem); - mutex_init(&mp); - clocks_set_sys_defaults(dvb_mode); - /* open dtv adc pinmux */ - if (is_meson_txl_cpu()) { - gpioDV_2 = demod_read_demod_reg(0xc8834400 + (0x2e << 2)); - pr_dbg("[R840]set adc pinmux,gpioDV_2 %x\n", gpioDV_2); - gpioDV_2 = gpioDV_2 | (0x1 << 22); - gpioDV_2 = gpioDV_2 & ~(0x3 << 19); - gpioDV_2 = gpioDV_2 & ~(0x1 << 23); - gpioDV_2 = gpioDV_2 & ~(0x1 << 31); - demod_set_demod_reg(gpioDV_2, 0xc8834400 + (0x2e << 2)); - pr_dbg("[R840]set adc pinmux,gpioDV_2 %x\n", gpioDV_2); - } else { - gpiW_2 = demod_read_demod_reg(0xc88344c4); - gpiW_2 = gpiW_2 | (0x1 << 25); - gpiW_2 = gpiW_2 & ~(0xd << 24); - demod_set_demod_reg(gpiW_2, 0xc88344c4); - pr_dbg("[R840]set adc pinmux,gpiW_2 %x\n", gpiW_2); - } - /* set adc clk */ - demod_set_adc_core_clk(clk_adc, clk_dem, dvb_mode); - /* init for dtmb */ - if (dvb_mode == Gxtv_Dtmb) { - /* open arbit */ - /* demod_set_demod_reg(0x8, DEMOD_REG4);*/ - } - demod_sta->adc_freq = clk_adc; - demod_sta->clk_freq = clk_dem; - return 0; -} - -void demod_set_reg(struct aml_demod_reg *demod_reg) -{ - switch (demod_reg->mode) { - case 0: - demod_reg->addr = demod_reg->addr + QAM_BASE; - break; - case 1: - case 2: - demod_reg->addr = DTMB_TOP_ADDR(demod_reg->addr); - break; - case 3: - /* demod_reg->addr=ATSC_BASE; */ - break; - case 4: - demod_reg->addr = demod_reg->addr * 4 + DEMOD_CFG_BASE; - break; - case 5: - demod_reg->addr = demod_reg->addr + DEMOD_BASE; - break; - case 6: - /* demod_reg->addr=demod_reg->addr*4+DEMOD_CFG_BASE; */ - break; - case 11: - demod_reg->addr = demod_reg->addr; - break; - case 10: - /* demod_reg->addr=(u32_t)phys_to_virt(demod_reg->addr); */ - break; - } - - if (demod_reg->mode == 3) - atsc_write_reg(demod_reg->addr, demod_reg->val); - else if (demod_reg->mode == 11) - demod_set_cbus_reg(demod_reg->val, demod_reg->addr); - else if (demod_reg->mode == 10) - apb_write_reg_collect(demod_reg->addr, demod_reg->val); - /* demod_reg->val_high = apb_read_reg_high(demod_reg->addr); */ - else - demod_set_demod_reg(demod_reg->val, demod_reg->addr); -} - -void demod_get_reg(struct aml_demod_reg *demod_reg) -{ - if (demod_reg->mode == 0) { - demod_reg->addr = demod_reg->addr + QAM_BASE; - } else if ((demod_reg->mode == 1) || (demod_reg->mode == 2)) { - demod_reg->addr = DTMB_TOP_ADDR(demod_reg->addr); - } else if (demod_reg->mode == 3) { - /* demod_reg->addr=demod_reg->addr+ATSC_BASE; */ - } else if (demod_reg->mode == 4) { - demod_reg->addr = demod_reg->addr * 4 + DEMOD_CFG_BASE; - } else if (demod_reg->mode == 5) { - demod_reg->addr = demod_reg->addr + DEMOD_BASE; - } else if (demod_reg->mode == 6) { - /* demod_reg->addr=demod_reg->addr*4+DEMOD_CFG_BASE; */ - } else if (demod_reg->mode == 11) { - demod_reg->addr = demod_reg->addr; - } else if (demod_reg->mode == 10) { - /* printk("demod_reg->addr is %x\n",demod_reg->addr); */ - /* test=(unsigned long)phys_to_virt(test); */ -/* demod_reg->addr=(unsigned long)phys_to_virt(demod_reg->addr); */ -/* printk("demod_reg->addr is %lx %x\n",test,demod_reg->addr); */ - } - - if (demod_reg->mode == 3) { - demod_reg->val = atsc_read_reg(demod_reg->addr); - /* apb_write_reg(ATSC_BASE+4, (demod_reg->addr&0xffff)<<8); */ - /* demod_reg->val = apb_read_reg(ATSC_BASE)&0xff; */ - } else if (demod_reg->mode == 6) { - demod_reg->val = atsc_read_iqr_reg(); - /* apb_write_reg(ATSC_BASE+4, (demod_reg->addr&0xffff)<<8); */ - /* demod_reg->val = apb_read_reg(ATSC_BASE)&0xff; */ - } else if (demod_reg->mode == 11) { - demod_reg->val = demod_read_cbus_reg(demod_reg->addr); - } else if (demod_reg->mode == 10) { - demod_reg->val = apb_read_reg_collect(demod_reg->addr); - /* demod_reg->val_high = apb_read_reg_high(demod_reg->addr);*/ - } else { - demod_reg->val = demod_read_demod_reg(demod_reg->addr); - } -} - -void apb_write_reg_collect(unsigned int addr, unsigned int data) -{ - writel(data, ((void __iomem *)(phys_to_virt(addr)))); -/* *(volatile unsigned int*)addr = data; */ -} - -unsigned long apb_read_reg_collect(unsigned long addr) -{ - unsigned long tmp; -/* void __iomem *vaddr; - * vaddr = ioremap(((unsigned long)phys_to_virt(addr)), 0x4); - * tmp = readl(vaddr); - * iounmap(vaddr); - */ - tmp = readl((void __iomem *)(phys_to_virt(addr))); -/*tmp = *(volatile unsigned long *)((unsigned long)phys_to_virt(addr));*/ -/* printk("[all][read]%lx,data is %lx\n",addr,tmp); */ - return tmp & 0xffffffff; -} - - - -void apb_write_reg(unsigned int addr, unsigned int data) -{ - demod_set_demod_reg(data, addr); -} - -unsigned long apb_read_reg_high(unsigned long addr) -{ - unsigned long tmp; - - tmp = 0; - return (tmp >> 32) & 0xffffffff; -} - -unsigned long apb_read_reg(unsigned long addr) -{ - return demod_read_demod_reg(addr); -} - -void apb_write_regb(unsigned long addr, int index, unsigned long data) -{ - /*to achieve write func*/ -} - -void enable_qam_int(int idx) -{ - unsigned long mask; - - mask = apb_read_reg(QAM_BASE + 0xd0); - mask |= (1 << idx); - apb_write_reg(QAM_BASE + 0xd0, mask); -} - -void disable_qam_int(int idx) -{ - unsigned long mask; - - mask = apb_read_reg(QAM_BASE + 0xd0); - mask &= ~(1 << idx); - apb_write_reg(QAM_BASE + 0xd0, mask); -} - -char *qam_int_name[] = { " ADC", - " Symbol", - " RS", - " In_Sync0", - " In_Sync1", - " In_Sync2", - " In_Sync3", - " In_Sync4", - "Out_Sync0", - "Out_Sync1", - "Out_Sync2", - "Out_Sync3", - "Out_Sync4", - "In_SyncCo", - "OutSyncCo", - " In_Dagc", - " Out_Dagc", - " Eq_Mode", - "RS_Uncorr" -}; - -#define OFDM_INT_STS 0 -#define OFDM_INT_EN 0 - -void enable_ofdm_int(int ofdm_irq) -{ - -} - -void disable_ofdm_int(int ofdm_irq) -{ - -} - -char *ofdm_int_name[] = { "PFS_FCFO", - "PFS_ICFO", - " CS_FCFO", - " PFS_SFO", - " PFS_TPS", - " SP", - " CCI", - " Symbol", - " In_Sync", - "Out_Sync", - "FSM Stat" -}; - -unsigned long read_ofdm_int(void) -{ - - return 0; -} - -#define PHS_LOOP_OPEN - -void qam_read_all_regs(void) -{ - -} - -void ini_icfo_pn_index(int mode) -{ /* 00:DVBT,01:ISDBT */ - if (mode == 0) { - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000031); - apb_write_reg(DVBT_BASE + 0x3fc, 0x00030000); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000032); - apb_write_reg(DVBT_BASE + 0x3fc, 0x00057036); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000033); - apb_write_reg(DVBT_BASE + 0x3fc, 0x0009c08d); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000034); - apb_write_reg(DVBT_BASE + 0x3fc, 0x000c90c0); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000035); - apb_write_reg(DVBT_BASE + 0x3fc, 0x001170ff); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000036); - apb_write_reg(DVBT_BASE + 0x3fc, 0x0014d11a); - } else if (mode == 1) { - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000031); - apb_write_reg(DVBT_BASE + 0x3fc, 0x00085046); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000032); - apb_write_reg(DVBT_BASE + 0x3fc, 0x0019a0e9); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000033); - apb_write_reg(DVBT_BASE + 0x3fc, 0x0024b1dc); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000034); - apb_write_reg(DVBT_BASE + 0x3fc, 0x003b3313); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000035); - apb_write_reg(DVBT_BASE + 0x3fc, 0x0048d409); - apb_write_reg(DVBT_BASE + 0x3f8, 0x00000036); - apb_write_reg(DVBT_BASE + 0x3fc, 0x00527509); - } -} - -static int coef[] = { - 0xf900, 0xfe00, 0x0000, 0x0000, 0x0100, 0x0100, 0x0000, 0x0000, - 0xfd00, 0xf700, 0x0000, 0x0000, 0x4c00, 0x0000, 0x0000, 0x0000, - 0x2200, 0x0c00, 0x0000, 0x0000, 0xf700, 0xf700, 0x0000, 0x0000, - 0x0300, 0x0900, 0x0000, 0x0000, 0x0600, 0x0600, 0x0000, 0x0000, - 0xfc00, 0xf300, 0x0000, 0x0000, 0x2e00, 0x0000, 0x0000, 0x0000, - 0x3900, 0x1300, 0x0000, 0x0000, 0xfa00, 0xfa00, 0x0000, 0x0000, - 0x0100, 0x0200, 0x0000, 0x0000, 0xf600, 0x0000, 0x0000, 0x0000, - 0x0700, 0x0700, 0x0000, 0x0000, 0xfe00, 0xfb00, 0x0000, 0x0000, - 0x0900, 0x0000, 0x0000, 0x0000, 0x3200, 0x1100, 0x0000, 0x0000, - 0x0400, 0x0400, 0x0000, 0x0000, 0xfe00, 0xfb00, 0x0000, 0x0000, - 0x0e00, 0x0000, 0x0000, 0x0000, 0xfb00, 0xfb00, 0x0000, 0x0000, - 0x0100, 0x0200, 0x0000, 0x0000, 0xf400, 0x0000, 0x0000, 0x0000, - 0x3900, 0x1300, 0x0000, 0x0000, 0x1700, 0x1700, 0x0000, 0x0000, - 0xfc00, 0xf300, 0x0000, 0x0000, 0x0c00, 0x0000, 0x0000, 0x0000, - 0x0300, 0x0900, 0x0000, 0x0000, 0xee00, 0x0000, 0x0000, 0x0000, - 0x2200, 0x0c00, 0x0000, 0x0000, 0x2600, 0x2600, 0x0000, 0x0000, - 0xfd00, 0xf700, 0x0000, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, - 0xf900, 0xfe00, 0x0000, 0x0000, 0x0400, 0x0b00, 0x0000, 0x0000, - 0xf900, 0x0000, 0x0000, 0x0000, 0x0700, 0x0200, 0x0000, 0x0000, - 0x2100, 0x2100, 0x0000, 0x0000, 0x0200, 0x0700, 0x0000, 0x0000, - 0xf900, 0x0000, 0x0000, 0x0000, 0x0b00, 0x0400, 0x0000, 0x0000, - 0xfe00, 0xf900, 0x0000, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, - 0xf700, 0xfd00, 0x0000, 0x0000, 0x2600, 0x2600, 0x0000, 0x0000, - 0x0c00, 0x2200, 0x0000, 0x0000, 0xee00, 0x0000, 0x0000, 0x0000, - 0x0900, 0x0300, 0x0000, 0x0000, 0x0c00, 0x0000, 0x0000, 0x0000, - 0xf300, 0xfc00, 0x0000, 0x0000, 0x1700, 0x1700, 0x0000, 0x0000, - 0x1300, 0x3900, 0x0000, 0x0000, 0xf400, 0x0000, 0x0000, 0x0000, - 0x0200, 0x0100, 0x0000, 0x0000, 0xfb00, 0xfb00, 0x0000, 0x0000, - 0x0e00, 0x0000, 0x0000, 0x0000, 0xfb00, 0xfe00, 0x0000, 0x0000, - 0x0400, 0x0400, 0x0000, 0x0000, 0x1100, 0x3200, 0x0000, 0x0000, - 0x0900, 0x0000, 0x0000, 0x0000, 0xfb00, 0xfe00, 0x0000, 0x0000, - 0x0700, 0x0700, 0x0000, 0x0000, 0xf600, 0x0000, 0x0000, 0x0000, - 0x0200, 0x0100, 0x0000, 0x0000, 0xfa00, 0xfa00, 0x0000, 0x0000, - 0x1300, 0x3900, 0x0000, 0x0000, 0x2e00, 0x0000, 0x0000, 0x0000, - 0xf300, 0xfc00, 0x0000, 0x0000, 0x0600, 0x0600, 0x0000, 0x0000, - 0x0900, 0x0300, 0x0000, 0x0000, 0xf700, 0xf700, 0x0000, 0x0000, - 0x0c00, 0x2200, 0x0000, 0x0000, 0x4c00, 0x0000, 0x0000, 0x0000, - 0xf700, 0xfd00, 0x0000, 0x0000, 0x0100, 0x0100, 0x0000, 0x0000, - 0xfe00, 0xf900, 0x0000, 0x0000, 0x0b00, 0x0400, 0x0000, 0x0000, - 0xfc00, 0xfc00, 0x0000, 0x0000, 0x0200, 0x0700, 0x0000, 0x0000, - 0x4200, 0x0000, 0x0000, 0x0000, 0x0700, 0x0200, 0x0000, 0x0000, - 0xfc00, 0xfc00, 0x0000, 0x0000, 0x0400, 0x0b00, 0x0000, 0x0000 -}; - -void tfd_filter_coff_ini(void) -{ - int i = 0; - - for (i = 0; i < 336; i++) { - apb_write_reg(DVBT_BASE + 0x99 * 4, (i << 16) | coef[i]); - apb_write_reg(DVBT_BASE + 0x03 * 4, (1 << 12)); - } -} - -void ofdm_initial(int bandwidth, - /* 00:8M 01:7M 10:6M 11:5M */ - int samplerate, - /* 00:45M 01:20.8333M 10:20.7M 11:28.57 100: 24.00 */ - int IF, - /* 000:36.13M 001:-5.5M 010:4.57M 011:4M 100:5M */ - int mode, - /* 00:DVBT,01:ISDBT */ - int tc_mode - /* 0: Unsigned, 1:TC */ - ) -{ -#if 0 - int tmp; - int ch_if; - int adc_freq; - - pr_dbg - ("[ofdm_initial]bandwidth is %d,samplerate is %d", - bandwidth, samplerate); - pr_dbg - ("IF is %d, mode is %d,tc_mode is %d\n", - IF, mode, tc_mode); - switch (IF) { - case 0: - ch_if = 36130; - break; - case 1: - ch_if = -5500; - break; - case 2: - ch_if = 4570; - break; - case 3: - ch_if = 4000; - break; - case 4: - ch_if = 5000; - break; - default: - ch_if = 4000; - break; - } - switch (samplerate) { - case 0: - adc_freq = 45000; - break; - case 1: - adc_freq = 20833; - break; - case 2: - adc_freq = 20700; - break; - case 3: - adc_freq = 28571; - break; - case 4: - adc_freq = 24000; - break; - default: - adc_freq = 28571; - break; - } - - apb_write_reg(DVBT_BASE + (0x02 << 2), 0x00800000); - /* SW reset bit[23] ; write anything to zero */ - apb_write_reg(DVBT_BASE + (0x00 << 2), 0x00000000); - - apb_write_reg(DVBT_BASE + (0xe << 2), 0xffff); - /* enable interrupt */ - - if (mode == 0) { /* DVBT */ - switch (samplerate) { - case 0: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00005a00); - break; /* 45MHz */ - case 1: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x000029aa); - break; /* 20.833 */ - case 2: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00002966); - break; /* 20.7 SAMPLERATE*512 */ - case 3: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00003924); - break; /* 28.571 */ - case 4: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00003000); - break; /* 24 */ - default: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00003924); - break; /* 28.571 */ - } - } else { /* ISDBT */ - switch (samplerate) { - case 0: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x0000580d); - break; /* 45MHz */ - case 1: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x0000290d); - break; /* 20.833 = 56/7 * 20.8333 / (512/63)*512 */ - case 2: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x000028da); - break; /* 20.7 */ - case 3: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x0000383F); - break; /* 28.571 3863 */ - case 4: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00002F40); - break; /* 24 */ - default: - apb_write_reg(DVBT_BASE + (0x08 << 2), 0x00003863); - break; /* 28.571 */ - } - } -/* memstart=0x93900000; */ - pr_dbg("memstart is %x\n", memstart); - apb_write_reg(DVBT_BASE + (0x10 << 2), memstart); - /* 0x8f300000 */ - - apb_write_reg(DVBT_BASE + (0x14 << 2), 0xe81c4ff6); - /* AGC_TARGET 0xf0121385 */ - - switch (samplerate) { - case 0: - apb_write_reg(DVBT_BASE + (0x15 << 2), 0x018c2df2); - break; - case 1: - apb_write_reg(DVBT_BASE + (0x15 << 2), 0x0185bdf2); - break; - case 2: - apb_write_reg(DVBT_BASE + (0x15 << 2), 0x0185bdf2); - break; - case 3: - apb_write_reg(DVBT_BASE + (0x15 << 2), 0x0187bdf2); - break; - case 4: - apb_write_reg(DVBT_BASE + (0x15 << 2), 0x0187bdf2); - break; - default: - apb_write_reg(DVBT_BASE + (0x15 << 2), 0x0187bdf2); - break; - } - if (tc_mode == 1) - apb_write_regb(DVBT_BASE + (0x15 << 2), 11, 0); - /* For TC mode. Notice, For ADC input is Unsigned, - *For Capture Data, It is TC. - */ - apb_write_regb(DVBT_BASE + (0x15 << 2), 26, 1); - /* [19:0] = [I , Q], I is high, Q is low. This bit is swap I/Q. */ - - apb_write_reg(DVBT_BASE + (0x16 << 2), 0x00047f80); - /* AGC_IFGAIN_CTRL */ - apb_write_reg(DVBT_BASE + (0x17 << 2), 0x00027f80); - /* AGC_RFGAIN_CTRL */ - apb_write_reg(DVBT_BASE + (0x18 << 2), 0x00000190); - /* AGC_IFGAIN_ACCUM */ - apb_write_reg(DVBT_BASE + (0x19 << 2), 0x00000190); - /* AGC_RFGAIN_ACCUM */ - if (ch_if < 0) - ch_if += adc_freq; - if (ch_if > adc_freq) - ch_if -= adc_freq; - - tmp = ch_if * (1 << 15) / adc_freq; - apb_write_reg(DVBT_BASE + (0x20 << 2), tmp); - - apb_write_reg(DVBT_BASE + (0x21 << 2), 0x001ff000); - /* DDC CS_FCFO_ADJ_CTRL */ - apb_write_reg(DVBT_BASE + (0x22 << 2), 0x00000000); - /* DDC ICFO_ADJ_CTRL */ - apb_write_reg(DVBT_BASE + (0x23 << 2), 0x00004000); - /* DDC TRACK_FCFO_ADJ_CTRL */ - - apb_write_reg(DVBT_BASE + (0x27 << 2), (1 << 23) - | (3 << 19) | (3 << 15) | (1000 << 4) | 9); - /* {8'd0,1'd1,4'd3,4'd3,11'd50,4'd9});//FSM_1 */ - apb_write_reg(DVBT_BASE + (0x28 << 2), (100 << 13) | 1000); - /* {8'd0,11'd40,13'd50});//FSM_2 */ - apb_write_reg(DVBT_BASE + (0x29 << 2), (31 << 20) | (1 << 16) | - (24 << 9) | (3 << 6) | 20); - /* {5'd0,7'd127,1'd0,3'd0,7'd24,3'd5,6'd20}); */ - - if (mode == 0) { /* DVBT */ - if (bandwidth == 0) { /* 8M */ - switch (samplerate) { - case 0: - ini_acf_iireq_src_45m_8m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x004ebf2e); - break; /* 45M */ - case 1: - ini_acf_iireq_src_207m_8m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00247551); - break; /* 20.833M */ - case 2: - ini_acf_iireq_src_207m_8m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00243999); - break; /* 20.7M */ - case 3: - ini_acf_iireq_src_2857m_8m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0031ffcd); - break; /* 28.57M */ - case 4: - ini_acf_iireq_src_24m_8m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x002A0000); - break; /* 24M */ - default: - ini_acf_iireq_src_2857m_8m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0031ffcd); - break; /* 28.57M */ - } - } else if (bandwidth == 1) { /* 7M */ - switch (samplerate) { - case 0: - ini_acf_iireq_src_45m_7m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0059ff10); - break; /* 45M */ - case 1: - ini_acf_iireq_src_207m_7m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0029aaa6); - break; /* 20.833M */ - case 2: - ini_acf_iireq_src_207m_7m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00296665); - break; /* 20.7M */ - case 3: - ini_acf_iireq_src_2857m_7m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00392491); - break; /* 28.57M */ - case 4: - ini_acf_iireq_src_24m_7m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00300000); - break; /* 24M */ - default: - ini_acf_iireq_src_2857m_7m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00392491); - break; /* 28.57M */ - } - } else if (bandwidth == 2) { /* 6M */ - switch (samplerate) { - case 0: - ini_acf_iireq_src_45m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00690000); - break; /* 45M */ - case 1: - ini_acf_iireq_src_207m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00309c3e); - break; /* 20.833M */ - case 2: - ini_acf_iireq_src_207m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x002eaaaa); - break; /* 20.7M */ - case 3: - ini_acf_iireq_src_2857m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0042AA69); - break; /* 28.57M */ - case 4: - ini_acf_iireq_src_24m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00380000); - break; /* 24M */ - default: - ini_acf_iireq_src_2857m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0042AA69); - break; /* 28.57M */ - } - } else { /* 5M */ - switch (samplerate) { - case 0: - ini_acf_iireq_src_45m_5m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x007dfbe0); - break; /* 45M */ - case 1: - ini_acf_iireq_src_207m_5m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x003a554f); - break; /* 20.833M */ - case 2: - ini_acf_iireq_src_207m_5m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x0039f5c0); - break; /* 20.7M */ - case 3: - ini_acf_iireq_src_2857m_5m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x004FFFFE); - break; /* 28.57M */ - case 4: - ini_acf_iireq_src_24m_5m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x00433333); - break; /* 24M */ - default: - ini_acf_iireq_src_2857m_5m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), - 0x004FFFFE); - break; /* 28.57M */ - } - } - } else { /* ISDBT */ - switch (samplerate) { - case 0: - ini_acf_iireq_src_45m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), 0x00589800); - break; - -/* 45M - * SampleRate/(symbolRate)*2^20, - * symbolRate = 512/63 for isdbt - */ - case 1: - ini_acf_iireq_src_207m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), 0x002903d4); - break; /* 20.833M */ - case 2: - ini_acf_iireq_src_207m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), 0x00280ccc); - break; /* 20.7M */ - case 3: - ini_acf_iireq_src_2857m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), 0x00383fc8); - break; /* 28.57M */ - case 4: - ini_acf_iireq_src_24m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), 0x002F4000); - break; /* 24M */ - default: - ini_acf_iireq_src_2857m_6m(); - apb_write_reg(DVBT_BASE + (0x44 << 2), 0x00383fc8); - break; /* 28.57M */ - } - } - - if (mode == 0) /* DVBT */ - apb_write_reg(DVBT_BASE + (0x02 << 2), - (bandwidth << 20) | 0x10002); - else /* ISDBT */ - apb_write_reg(DVBT_BASE + (0x02 << 2), (1 << 20) | 0x1001a); - /* {0x000,2'h1,20'h1_001a}); // For ISDBT , bandwidth should be 1, */ - - apb_write_reg(DVBT_BASE + (0x45 << 2), 0x00000000); - /* SRC SFO_ADJ_CTRL */ - apb_write_reg(DVBT_BASE + (0x46 << 2), 0x02004000); - /* SRC SFO_ADJ_CTRL */ - apb_write_reg(DVBT_BASE + (0x48 << 2), 0x000c0287); - /* DAGC_CTRL1 */ - apb_write_reg(DVBT_BASE + (0x49 << 2), 0x00000005); - /* DAGC_CTRL2 */ - apb_write_reg(DVBT_BASE + (0x4c << 2), 0x00000bbf); - /* CCI_RP */ - apb_write_reg(DVBT_BASE + (0x4d << 2), 0x00000376); - /* CCI_RPSQ */ - apb_write_reg(DVBT_BASE + (0x4e << 2), 0x0f0f1d09); - /* CCI_CTRL */ - apb_write_reg(DVBT_BASE + (0x4f << 2), 0x00000000); - /* CCI DET_INDX1 */ - apb_write_reg(DVBT_BASE + (0x50 << 2), 0x00000000); - /* CCI DET_INDX2 */ - apb_write_reg(DVBT_BASE + (0x51 << 2), 0x00000000); - /* CCI_NOTCH1_A1 */ - apb_write_reg(DVBT_BASE + (0x52 << 2), 0x00000000); - /* CCI_NOTCH1_A2 */ - apb_write_reg(DVBT_BASE + (0x53 << 2), 0x00000000); - /* CCI_NOTCH1_B1 */ - apb_write_reg(DVBT_BASE + (0x54 << 2), 0x00000000); - /* CCI_NOTCH2_A1 */ - apb_write_reg(DVBT_BASE + (0x55 << 2), 0x00000000); - /* CCI_NOTCH2_A2 */ - apb_write_reg(DVBT_BASE + (0x56 << 2), 0x00000000); - /* CCI_NOTCH2_B1 */ - apb_write_reg(DVBT_BASE + (0x58 << 2), 0x00000885); - /* MODE_DETECT_CTRL // 582 */ - if (mode == 0) /* DVBT */ - apb_write_reg(DVBT_BASE + (0x5c << 2), 0x00001011); /* */ - else - apb_write_reg(DVBT_BASE + (0x5c << 2), 0x00000753); - /* ICFO_EST_CTRL ISDBT ICFO thres = 2 */ - - apb_write_reg(DVBT_BASE + (0x5f << 2), 0x0ffffe10); - /* TPS_FCFO_CTRL */ - apb_write_reg(DVBT_BASE + (0x61 << 2), 0x0000006c); - /* FWDT ctrl */ - apb_write_reg(DVBT_BASE + (0x68 << 2), 0x128c3929); - apb_write_reg(DVBT_BASE + (0x69 << 2), 0x91017f2d); - /* 0x1a8 */ - apb_write_reg(DVBT_BASE + (0x6b << 2), 0x00442211); - /* 0x1a8 */ - apb_write_reg(DVBT_BASE + (0x6c << 2), 0x01fc400a); - /* 0x */ - apb_write_reg(DVBT_BASE + (0x6d << 2), 0x0030303f); - /* 0x */ - apb_write_reg(DVBT_BASE + (0x73 << 2), 0xffffffff); - /* CCI0_PILOT_UPDATE_CTRL */ - apb_write_reg(DVBT_BASE + (0x74 << 2), 0xffffffff); - /* CCI0_DATA_UPDATE_CTRL */ - apb_write_reg(DVBT_BASE + (0x75 << 2), 0xffffffff); - /* CCI1_PILOT_UPDATE_CTRL */ - apb_write_reg(DVBT_BASE + (0x76 << 2), 0xffffffff); - /* CCI1_DATA_UPDATE_CTRL */ - - tmp = mode == 0 ? 0x000001a2 : 0x00000da2; - apb_write_reg(DVBT_BASE + (0x78 << 2), tmp); /* FEC_CTR */ - - apb_write_reg(DVBT_BASE + (0x7d << 2), 0x0000009d); - apb_write_reg(DVBT_BASE + (0x7e << 2), 0x00004000); - apb_write_reg(DVBT_BASE + (0x7f << 2), 0x00008000); - - apb_write_reg(DVBT_BASE + ((0x8b + 0) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 1) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 2) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 3) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 4) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 5) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 6) << 2), 0x20002000); - apb_write_reg(DVBT_BASE + ((0x8b + 7) << 2), 0x20002000); - - apb_write_reg(DVBT_BASE + (0x93 << 2), 0x31); - apb_write_reg(DVBT_BASE + (0x94 << 2), 0x00); - apb_write_reg(DVBT_BASE + (0x95 << 2), 0x7f1); - apb_write_reg(DVBT_BASE + (0x96 << 2), 0x20); - - apb_write_reg(DVBT_BASE + (0x98 << 2), 0x03f9115a); - apb_write_reg(DVBT_BASE + (0x9b << 2), 0x000005df); - - apb_write_reg(DVBT_BASE + (0x9c << 2), 0x00100000); - /* TestBus write valid, 0 is system clk valid */ - apb_write_reg(DVBT_BASE + (0x9d << 2), 0x01000000); - /* DDR Start address */ - apb_write_reg(DVBT_BASE + (0x9e << 2), 0x02000000); - /* DDR End address */ - - apb_write_regb(DVBT_BASE + (0x9b << 2), 7, 0); - /* Enable Testbus dump to DDR */ - apb_write_regb(DVBT_BASE + (0x9b << 2), 8, 0); - /* Run Testbus dump to DDR */ - - apb_write_reg(DVBT_BASE + (0xd6 << 2), 0x00000003); - /* apb_write_reg(DVBT_BASE+(0xd7<<2), 0x00000008); */ - apb_write_reg(DVBT_BASE + (0xd8 << 2), 0x00000120); - apb_write_reg(DVBT_BASE + (0xd9 << 2), 0x01010101); - - ini_icfo_pn_index(mode); - tfd_filter_coff_ini(); - - calculate_cordic_para(); - msleep(20); - /* delay_us(1); */ - - apb_write_reg(DVBT_BASE + (0x02 << 2), - apb_read_reg(DVBT_BASE + (0x02 << 2)) | (1 << 0)); - apb_write_reg(DVBT_BASE + (0x02 << 2), - apb_read_reg(DVBT_BASE + (0x02 << 2)) | (1 << 24)); -#endif -/* dvbt_check_status(); */ -} - -void calculate_cordic_para(void) -{ - apb_write_reg(DVBT_BASE + 0x0c, 0x00000040); -} - -char *ofdm_fsm_name[] = { " IDLE", - " AGC", - " CCI", - " ACQ", - " SYNC", - "TRACKING", - " TIMING", - " SP_SYNC", - " TPS_DEC", - "FEC_LOCK", - "FEC_LOST" -}; - -void check_fsm_state(void) -{ - unsigned long tmp; - - tmp = apb_read_reg(DVBT_BASE + 0xa8); - /* printk(">>>>>>>>>>>>>>>>>>>>>>>>> OFDM FSM From %d - *to %d\n", tmp>>4&0xf, tmp&0xf); - */ - - if ((tmp & 0xf) == 3) { - apb_write_regb(DVBT_BASE + (0x9b << 2), 8, 1); - /* Stop dump testbus; */ - apb_write_regb(DVBT_BASE + (0x0f << 2), 0, 1); - tmp = apb_read_reg(DVBT_BASE + (0x9f << 2)); - /* printk(">>>>>>>>>>>>>>>>>>>>>>>>> STOP DUMP DATA To DDR : - *End Addr %d,Is it overflow?%d\n", tmp>>1, tmp&0x1); - */ - } -} - -void ofdm_read_all_regs(void) -{ - int i; - unsigned long tmp; - - for (i = 0; i < 0xff; i++) - tmp = apb_read_reg(DVBT_BASE + 0x00 + i * 4); - /* printk("OFDM Reg (0x%x) is 0x%x\n", i, tmp); */ - -} - -static int dvbt_get_status(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - return apb_read_reg(DVBT_BASE + 0x0) >> 12 & 1; -} - -static int dvbt_get_ber(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ -/* pr_dbg("[RSJ]per is %u\n",apb_read_reg(DVBT_BASE+(0xbf<<2))); */ - return apb_read_reg(DVBT_BASE + (0xbf << 2)); -} - -static int dvbt_get_snr(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ -/* pr_dbg("2snr is %u\n",((apb_read_reg(DVBT_BASE+(0x0a<<2)))>>20)&0x3ff); */ - return ((apb_read_reg(DVBT_BASE + (0x0a << 2))) >> 20) & 0x3ff; - /*dBm: bit0~bit2=decimal */ -} - -static int dvbt_get_strength(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ -/* int dbm = dvbt_get_ch_power(demod_sta, demod_i2c); */ -/* return dbm; */ - return 0; -} - -static int dvbt_get_ucblocks(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - return 0; -/* return dvbt_get_per(); */ -} - -struct demod_status_ops *dvbt_get_status_ops(void) -{ - static struct demod_status_ops ops = { - .get_status = dvbt_get_status, - .get_ber = dvbt_get_ber, - .get_snr = dvbt_get_snr, - .get_strength = dvbt_get_strength, - .get_ucblocks = dvbt_get_ucblocks, - }; - - return &ops; -} - -int app_apb_read_reg(int addr) -{ - addr = DTMB_TOP_ADDR(addr); - return (int)demod_read_demod_reg(addr); -} - -int app_apb_write_reg(int addr, int data) -{ - addr = DTMB_TOP_ADDR(addr); - demod_set_demod_reg(data, addr); - return 0; -} - -void monitor_isdbt(void) -{ - int SNR; - int SNR_SP = 500; - int SNR_TPS = 0; - int SNR_CP = 0; - int timeStamp = 0; - int SFO_residual = 0; - int SFO_esti = 0; - int FCFO_esti = 0; - int FCFO_residual = 0; - int AGC_Gain = 0; - int RF_AGC = 0; - int Signal_power = 0; - int FECFlag = 0; - int EQ_seg_ratio = 0; - int tps_0 = 0; - int tps_1 = 0; - int tps_2 = 0; - - int time_stamp; - int SFO; - int FCFO; - int timing_adj; - int RS_CorrectNum; - - int cnt; - int tmpAGCGain; - - tmpAGCGain = 0; - cnt = 0; - -/* app_apb_write_reg(0x8, app_apb_read_reg(0x8) & ~(1 << 17)); - * // TPS symbol index update : active high - */ - time_stamp = app_apb_read_reg(0x07) & 0xffff; - SNR = app_apb_read_reg(0x0a); - FECFlag = (app_apb_read_reg(0x00) >> 11) & 0x3; - SFO = app_apb_read_reg(0x47) & 0xfff; - SFO_esti = app_apb_read_reg(0x60) & 0xfff; - FCFO_esti = (app_apb_read_reg(0x60) >> 11) & 0xfff; - FCFO = (app_apb_read_reg(0x26)) & 0xffffff; - RF_AGC = app_apb_read_reg(0x0c) & 0x1fff; - timing_adj = app_apb_read_reg(0x6f) & 0x1fff; - RS_CorrectNum = app_apb_read_reg(0xc1) & 0xfffff; - Signal_power = (app_apb_read_reg(0x1b)) & 0x1ff; - EQ_seg_ratio = app_apb_read_reg(0x6e) & 0x3ffff; - tps_0 = app_apb_read_reg(0x64); - tps_1 = app_apb_read_reg(0x65); - tps_2 = app_apb_read_reg(0x66) & 0xf; - - timeStamp = (time_stamp >> 8) * 68 + (time_stamp & 0x7f); - SFO_residual = (SFO > 0x7ff) ? (SFO - 0x1000) : SFO; - FCFO_residual = (FCFO > 0x7fffff) ? (FCFO - 0x1000000) : FCFO; - /* RF_AGC = (RF_AGC>0x3ff)? (RF_AGC - 0x800): RF_AGC; */ - FCFO_esti = (FCFO_esti > 0x7ff) ? (FCFO_esti - 0x1000) : FCFO_esti; - SNR_CP = (SNR) & 0x3ff; - SNR_TPS = (SNR >> 10) & 0x3ff; - SNR_SP = (SNR >> 20) & 0x3ff; - SNR_SP = (SNR_SP > 0x1ff) ? SNR_SP - 0x400 : SNR_SP; - SNR_TPS = (SNR_TPS > 0x1ff) ? SNR_TPS - 0x400 : SNR_TPS; - SNR_CP = (SNR_CP > 0x1ff) ? SNR_CP - 0x400 : SNR_CP; - AGC_Gain = tmpAGCGain >> 4; - tmpAGCGain = (AGC_Gain > 0x3ff) ? AGC_Gain - 0x800 : AGC_Gain; - timing_adj = (timing_adj > 0xfff) ? timing_adj - 0x2000 : timing_adj; - EQ_seg_ratio = - (EQ_seg_ratio > 0x1ffff) ? EQ_seg_ratio - 0x40000 : EQ_seg_ratio; - - pr_dbg - ("T %4x SP %3d TPS %3d CP %3d EQS %8x RSC %4d", - app_apb_read_reg(0xbf) - , SNR_SP, SNR_TPS, SNR_CP -/* ,EQ_seg_ratio */ - , app_apb_read_reg(0x62) - , RS_CorrectNum); - pr_dbg - ("SFO %4d FCFO %4d Vit %4x Timing %3d SigP %3x", - SFO_residual, FCFO_residual, RF_AGC, timing_adj, - Signal_power); - pr_dbg - ("FEC %x RSErr %8x ReSyn %x tps %03x%08x", - FECFlag, app_apb_read_reg(0x0b) - , (app_apb_read_reg(0xc0) >> 20) & 0xff, - app_apb_read_reg(0x05) & 0xfff, app_apb_read_reg(0x04) - ); - pr_dbg("\n"); -} - -int find_2(int data, int *table, int len) -{ - int end; - int index; - int start; - int cnt = 0; - - start = 0; - end = len; - /* printf("data is %d\n",data); */ - while ((len > 1) && (cnt < 10)) { - cnt++; - index = (len / 2); - if (data > table[start + index]) { - start = start + index; - len = len - index - 1; - } - if (data < table[start + index]) { - len = index + 1; - } else if (data == table[start + index]) { - start = start + index; - break; - } - } - return start; -} - -int read_atsc_all_reg(void) -{ - return 0; -#if 0 - int i, j, k; - - j = 4; - unsigned long data; - - pr_dbg("system agc is:"); /* system agc */ - for (i = 0xc00; i <= 0xc0c; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0xc80; i <= 0xc87; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n vsb control is:"); /*vsb control */ - j = 4; - for (i = 0x900; i <= 0x905; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x908; i <= 0x912; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x917; i <= 0x91b; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x980; i <= 0x992; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n vsb demod is:"); /*vsb demod */ - j = 4; - for (i = 0x700; i <= 0x711; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x716; i <= 0x720; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x722; i <= 0x724; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x726; i <= 0x72c; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x730; i <= 0x732; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x735; i <= 0x751; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x780; i <= 0x795; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x752; i <= 0x755; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n vsb equalizer is:"); /*vsb equalizer */ - j = 4; - for (i = 0x501; i <= 0x5ff; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n vsb fec is:"); /*vsb fec */ - j = 4; - for (i = 0x601; i <= 0x601; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x682; i <= 0x685; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n qam demod is:"); /*qam demod */ - j = 4; - for (i = 0x1; i <= 0x1a; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x25; i <= 0x28; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x101; i <= 0x10b; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x206; i <= 0x207; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n qam equalize is:"); /*qam equalize */ - j = 4; - for (i = 0x200; i <= 0x23d; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - j = 4; - for (i = 0x260; i <= 0x275; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n qam fec is:"); /*qam fec */ - j = 4; - for (i = 0x400; i <= 0x418; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n system mpeg formatter is:"); /*system mpeg formatter */ - j = 4; - for (i = 0xf00; i <= 0xf09; i++) { - data = atsc_read_reg(i); - if (j == 4) { - pr_dbg("\n[addr:0x%x]", i); - j = 0; - } - pr_dbg("%02x ", data); - j++; - } - pr_dbg("\n\n"); - return 0; -#endif -} - -int check_atsc_fsm_status(void) -{ - int SNR; - int atsc_snr = 0; - int SNR_dB; - int SNR_table[56] = { 0, 7, 9, 11, 14, - 17, - 22, - 27, 34, 43, 54, - 68, 86, 108, 136, 171, - 215, - 271, 341, - 429, 540, - 566, 592, 620, 649, 680, - 712, - 746, 781, - 818, 856, - 896, 939, 983, 1029, 1078, - 1182, - 1237, - 1237, 1296, 1357, - 1708, 2150, 2707, 3408, 4291, - 5402, - 6800, - 8561, 10778, 13568, - 16312, 17081, 18081, 19081, 65536 - }; - int SNR_dB_table[56] = { 360, 350, 340, 330, 320, 310, 300, - 290, - 280, - 270, 260, - 250, 240, 230, 220, 210, 200, 190, - 180, - 170, - 160, - 158, 156, 154, 152, 150, 148, 146, - 144, - 142, - 140, - 138, 136, 134, 132, 130, 128, 126, - 124, - 122, - 120, - 110, 100, 90, 80, 70, 60, 50, - 40, - 30, - 20, - 12, 10, 4, 2, 0 - }; - - int tmp[3]; - int cr; - int ck; - int SM; - int tni; - int ber; - int per; - - int cnt; - - cnt = 0; - ber = 0; - per = 0; - -/* g_demod_mode = 2; */ - tni = atsc_read_reg((0x08) >> 16); -/* g_demod_mode = 4; */ - tmp[0] = atsc_read_reg(0x0511); - tmp[1] = atsc_read_reg(0x0512); - SNR = (tmp[0] << 8) + tmp[1]; - SNR_dB = SNR_dB_table[find_2(SNR, SNR_table, 56)]; - - tmp[0] = atsc_read_reg(0x0780); - tmp[1] = atsc_read_reg(0x0781); - tmp[2] = atsc_read_reg(0x0782); - cr = tmp[0] + (tmp[1] << 8) + (tmp[2] << 16); - tmp[0] = atsc_read_reg(0x0786); - tmp[1] = atsc_read_reg(0x0787); - tmp[2] = atsc_read_reg(0x0788); - ck = (tmp[0] << 16) + (tmp[1] << 8) + tmp[2]; - ck = (ck > 8388608) ? ck - 16777216 : ck; - SM = atsc_read_reg(0x0980); -/* ber per */ - atsc_write_reg(0x0601, atsc_read_reg(0x0601) & (~(1 << 3))); - atsc_write_reg(0x0601, atsc_read_reg(0x0601) | (1 << 3)); - ber = atsc_read_reg(0x0683) + (atsc_read_reg(0x0682) << 8); - per = atsc_read_reg(0x0685) + (atsc_read_reg(0x0684) << 8); - -/* read_atsc_all_reg(); */ - - pr_dbg - ("INT %x SNR %x SNRdB %d.%d FSM %x cr %d ck %d", - tni, SNR, (SNR_dB / 10) - , (SNR_dB - (SNR_dB / 10) * 10) - , SM, cr, ck); - pr_dbg - ("ber is %d, per is %d\n", - ber, per); - - atsc_snr = (SNR_dB / 10); - return atsc_snr; - - /* unsigned long sm,snr1,snr2,snr; - * static int fec_lock_cnt = 0; - * - * delay_us(10000); - * sm = atsc_read_reg(0x0980); - * snr1 = atsc_read_reg(0x0511)&0xff; - * snr2 = atsc_read_reg(0x0512)&0xff; - * snr = (snr1 << 8) + snr2; - * - * printk(">>>>>>>>>>>>>>>>>>>>>>>>> - OFDM FSM %x SNR %x\n", sm&0xff, snr); - * - * if (sm == 0x79) stimulus_finish_pass(); - */ -} diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c deleted file mode 100644 index cf2ea8163947..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c +++ /dev/null @@ -1,1331 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include "demod_func.h" -#include - -static int debug_amldvbc = 1; -#define dprintk(a ...) do { if (debug_amldvbc) printk(a); } while (0) - -static struct task_struct *cci_task; -int cciflag; -struct timer_list mytimer; - -static void dvbc_cci_timer(unsigned long data) -{ -#if 0 - int count; - int maxCCI_p, re, im, j, i, times, maxCCI, sum, sum1, reg_0xf0, tmp1, - tmp, tmp2, reg_0xa8, reg_0xac; - int reg_0xa8_t, reg_0xac_t; - - count = 100; - if ((((apb_read_reg(QAM_BASE + 0x18)) & 0x1) == 1)) { - dprintk("[cci]lock "); - if (cciflag == 0) { - apb_write_reg(QAM_BASE + 0xa8, 0); - - cciflag = 0; - } - dprintk("\n"); - mdelay(500); - mod_timer(&mytimer, jiffies + 2 * HZ); - return; - } - if (cciflag == 1) { - dprintk("[cci]cciflag is 1,wait 20\n"); - mdelay(20000); - } - times = 300; - tmp = 0x2be2be3; - /*0x2ae4772; IF = 6M, fs = 35M, dec2hex(round(8*IF/fs*2^25)) */ - tmp2 = 0x2000; - tmp1 = 8; - reg_0xa8 = 0xc0000000; /* bypass CCI */ - reg_0xac = 0xc0000000; /* bypass CCI */ - - maxCCI = 0; - maxCCI_p = 0; - for (i = 0; i < times; i++) { - /*reg_0xa8 = app_apb_read_reg(0xa8); */ - reg_0xa8_t = reg_0xa8 + tmp + i * tmp2; - apb_write_reg(QAM_BASE + 0xa8, reg_0xa8_t); - reg_0xac_t = reg_0xac + tmp - i * tmp2; - apb_write_reg(QAM_BASE + 0xac, reg_0xac_t); - sum = 0; - sum1 = 0; - for (j = 0; j < tmp1; j++) { - /* msleep(20); */ - /* mdelay(20); */ - reg_0xf0 = apb_read_reg(QAM_BASE + 0xf0); - re = (reg_0xf0 >> 24) & 0xff; - im = (reg_0xf0 >> 16) & 0xff; - if (re > 127) - /*re = re - 256; */ - re = 256 - re; - if (im > 127) - /*im = im - 256; */ - im = 256 - im; - - sum += re + im; - re = (reg_0xf0 >> 8) & 0xff; - im = (reg_0xf0 >> 0) & 0xff; - if (re > 127) - /*re = re - 256; */ - re = 256 - re; - if (im > 127) - /*im = im - 256; */ - im = 256 - im; - - sum1 += re + im; - } - sum = sum / tmp1; - sum1 = sum1 / tmp1; - if (sum1 > sum) { - sum = sum1; - reg_0xa8_t = reg_0xac_t; - } - if (sum > maxCCI) { - maxCCI = sum; - if (maxCCI > 24) - maxCCI_p = reg_0xa8_t & 0x7fffffff; - } - if ((sum < 24) && (maxCCI_p > 0)) - break; /* stop CCI detect. */ - } - - if (maxCCI_p > 0) { - apb_write_reg(QAM_BASE + 0xa8, maxCCI_p & 0x7fffffff); - /* enable CCI */ - apb_write_reg(QAM_BASE + 0xac, maxCCI_p & 0x7fffffff); - /* enable CCI */ - /* if(dvbc.mode == 4) // 256QAM */ - apb_write_reg(QAM_BASE + 0x54, 0xa25705fa); - /**/ cciflag = 1; - mdelay(1000); - } else { - dprintk - ("[cci] ------------ find NO CCI -------------------\n"); - cciflag = 0; - } - - dprintk("[cci][%s]--------------------------\n", __func__); - mod_timer(&mytimer, jiffies + 2 * HZ); - return; -/* }*/ -#endif -} - -int dvbc_timer_init(void) -{ - dprintk("%s\n", __func__); - setup_timer(&mytimer, dvbc_cci_timer, (unsigned long)"Hello, world!"); - mytimer.expires = jiffies + 2 * HZ; - add_timer(&mytimer); - return 0; -} - -void dvbc_timer_exit(void) -{ - dprintk("%s\n", __func__); - del_timer(&mytimer); -} - -int dvbc_cci_task(void *data) -{ - int count; - int maxCCI_p, re, im, j, i, times, maxCCI, sum, sum1, reg_0xf0, tmp1, - tmp, tmp2, reg_0xa8, reg_0xac; - int reg_0xa8_t, reg_0xac_t; - - count = 100; - while (1) { - msleep(200); - if ((((apb_read_reg(QAM_BASE + 0x18)) & 0x1) == 1)) { - dprintk("[cci]lock "); - if (cciflag == 0) { - apb_write_reg(QAM_BASE + 0xa8, 0); - apb_write_reg(QAM_BASE + 0xac, 0); - dprintk("no cci "); - cciflag = 0; - } - dprintk("\n"); - msleep(500); - continue; - } - - if (cciflag == 1) { - dprintk("[cci]cciflag is 1,wait 20\n"); - msleep(20000); - } - times = 300; - tmp = 0x2be2be3; - /*0x2ae4772; IF = 6M,fs = 35M, dec2hex(round(8*IF/fs*2^25)) */ - tmp2 = 0x2000; - tmp1 = 8; - reg_0xa8 = 0xc0000000; /* bypass CCI */ - reg_0xac = 0xc0000000; /* bypass CCI */ - - maxCCI = 0; - maxCCI_p = 0; - for (i = 0; i < times; i++) { - /*reg_0xa8 = app_apb_read_reg(0xa8); */ - reg_0xa8_t = reg_0xa8 + tmp + i * tmp2; - apb_write_reg(QAM_BASE + 0xa8, reg_0xa8_t); - reg_0xac_t = reg_0xac + tmp - i * tmp2; - apb_write_reg(QAM_BASE + 0xac, reg_0xac_t); - sum = 0; - sum1 = 0; - for (j = 0; j < tmp1; j++) { - /* msleep(1); */ - reg_0xf0 = apb_read_reg(QAM_BASE + 0xf0); - re = (reg_0xf0 >> 24) & 0xff; - im = (reg_0xf0 >> 16) & 0xff; - if (re > 127) - /*re = re - 256; */ - re = 256 - re; - if (im > 127) - /*im = im - 256; */ - im = 256 - im; - - sum += re + im; - - re = (reg_0xf0 >> 8) & 0xff; - im = (reg_0xf0 >> 0) & 0xff; - if (re > 127) - /*re = re - 256; */ - re = 256 - re; - if (im > 127) - /*im = im - 256; */ - im = 256 - im; - - sum1 += re + im; - } - sum = sum / tmp1; - sum1 = sum1 / tmp1; - if (sum1 > sum) { - sum = sum1; - reg_0xa8_t = reg_0xac_t; - } - if (sum > maxCCI) { - maxCCI = sum; - if (maxCCI > 24) - maxCCI_p = reg_0xa8_t & 0x7fffffff; - } - - if ((sum < 24) && (maxCCI_p > 0)) - break; /* stop CCI detect. */ - } - - if (maxCCI_p > 0) { - apb_write_reg(QAM_BASE + 0xa8, maxCCI_p & 0x7fffffff); - /* enable CCI */ - apb_write_reg(QAM_BASE + 0xac, maxCCI_p & 0x7fffffff); - /* enable CCI */ - /* if(dvbc.mode == 4) // 256QAM */ - apb_write_reg(QAM_BASE + 0x54, 0xa25705fa); - /**/ cciflag = 1; - msleep(1000); - } else { - cciflag = 0; - } - - dprintk("[cci][%s]--------------------------\n", __func__); - } - return 0; -} - -int dvbc_get_cci_task(void) -{ - if (cci_task) - return 0; - else - return 1; -} - -void dvbc_create_cci_task(void) -{ - int ret; - - /*apb_write_reg(QAM_BASE+0xa8, 0x42b2ebe3); // enable CCI */ - /* apb_write_reg(QAM_BASE+0xac, 0x42b2ebe3); // enable CCI */ -/* if(dvbc.mode == 4) // 256QAM*/ - /* apb_write_reg(QAM_BASE+0x54, 0xa25705fa); // */ - ret = 0; - cci_task = kthread_create(dvbc_cci_task, NULL, "cci_task"); - if (ret != 0) { - dprintk("[%s]Create cci kthread error!\n", __func__); - cci_task = NULL; - return; - } - wake_up_process(cci_task); - dprintk("[%s]Create cci kthread and wake up!\n", __func__); -} - -void dvbc_kill_cci_task(void) -{ - if (cci_task) { - kthread_stop(cci_task); - cci_task = NULL; - dprintk("[%s]kill cci kthread !\n", __func__); - } -} - -u32 dvbc_set_qam_mode(unsigned char mode) -{ - dprintk("auto change mode ,now mode is %d\n", mode); - apb_write_reg(QAM_BASE + 0x008, (mode & 7)); - /* qam mode */ - switch (mode) { - case 0: /* 16 QAM */ - apb_write_reg(QAM_BASE + 0x054, 0x23460224); - /* EQ_FIR_CTL, */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - apb_write_reg(QAM_BASE + 0x074, 0x50001a0); - /* EQ_TH_LMS 40db 13db */ - apb_write_reg(QAM_BASE + 0x07c, 0x003001e9); - /* EQ_NORM and EQ_TH_MMA */ - /*apb_write_reg(QAM_BASE+0x080, 0x000be1ff); - * // EQ_TH_SMMA0 - */ - apb_write_reg(QAM_BASE + 0x080, 0x000e01fe); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x00000000); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292b); - * // Pilips Tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292d); - * // Pilips Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092d); - /* Pilips Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66); - /* by raymond 20121213 */ - break; - - case 1: /* 32 QAM */ - apb_write_reg(QAM_BASE + 0x054, 0x24560506); - /* EQ_FIR_CTL, */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x5000260); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x50001f0); - /* EQ_TH_LMS 40db 17.5db */ - apb_write_reg(QAM_BASE + 0x07c, 0x00500102); - /* EQ_TH_MMA 0x000001cc */ - apb_write_reg(QAM_BASE + 0x080, 0x00077140); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x001fb000); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292b); - * // Pilips Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092b); - /* Pilips Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66); - /* by raymond 20121213 */ - break; - - case 2: /* 64 QAM */ - /*apb_write_reg(QAM_BASE+0x054, 0x2256033a); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0x2336043a); - /* EQ_FIR_CTL, by raymond */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x5000260); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000230); - /* EQ_TH_LMS 40db 17.5db */ - apb_write_reg(QAM_BASE + 0x07c, 0x007001bd); - /* EQ_TH_MMA */ - apb_write_reg(QAM_BASE + 0x080, 0x000580ed); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x001771fb); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d); - /* Pilips Tuner & maxlinear Tuner */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a); - * // Pilips Tuner & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66); - /* by raymond 20121213 */ - break; - - case 3: /* 128 QAM */ - /*apb_write_reg(QAM_BASE+0x054, 0x2557046a); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0x2437067a); - /* EQ_FIR_CTL, by raymond 20121213 */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000d0); - /* EQ_CRTH_SNR */ - /* apb_write_reg(QAM_BASE+0x074, 0x02440240); - * // EQ_TH_LMS 18.5db 18db - */ - /* apb_write_reg(QAM_BASE+0x074, 0x04000400); - * // EQ_TH_LMS 22db 22.5db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000260); - /* EQ_TH_LMS 40db 19db */ - /*apb_write_reg(QAM_BASE+0x07c, 0x00b000f2); - * // EQ_TH_MMA0x000000b2 - */ - apb_write_reg(QAM_BASE + 0x07c, 0x00b00132); - /* EQ_TH_MMA0x000000b2 by raymond 20121213 */ - apb_write_reg(QAM_BASE + 0x080, 0x0003a09d); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x000f8150); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x001a51f8); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092c); - /* Pilips Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66); - /* by raymond 20121213 */ - break; - - case 4: /* 256 QAM */ - /*apb_write_reg(QAM_BASE+0x054, 0xa2580588); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0xa25905f9); - /* EQ_FIR_CTL, by raymond 20121213 */ - apb_write_reg(QAM_BASE + 0x068, 0x01e00220); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x50002a0); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000270); - /* EQ_TH_LMS 40db 19db by raymond 201211213 */ - apb_write_reg(QAM_BASE + 0x07c, 0x00f001a5); - /* EQ_TH_MMA */ - apb_write_reg(QAM_BASE + 0x080, 0x0002c077); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x000bc0fe); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x0013f17e); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x01bc01f9); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips Tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292d); - * // Maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092d); - /* Maxlinear Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213, when adc=35M,sys=70M, - * its better than 0x61f2f66 - */ - break; - default: /*64qam */ - /*apb_write_reg(QAM_BASE+0x054, 0x2256033a); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0x2336043a); - /* EQ_FIR_CTL, by raymond */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x5000260); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000230); - /* EQ_TH_LMS 40db 17.5db */ - apb_write_reg(QAM_BASE + 0x07c, 0x007001bd); - /* EQ_TH_MMA */ - apb_write_reg(QAM_BASE + 0x080, 0x000580ed); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x001771fb); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d); - /* Pilips Tuner & maxlinear Tuner */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a); - * // Pilips Tuner & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66); - /* by raymond 20121213 */ - break; - } - return 0; -} - -u32 dvbc_get_status(void) -{ -/* dprintk("c4 is %x\n",apb_read_reg(QAM_BASE+0xc4));*/ - return apb_read_reg(QAM_BASE + 0xc4) & 0xf; -} -EXPORT_SYMBOL(dvbc_get_status); - -static u32 dvbc_get_ch_power(void) -{ - u32 tmp; - u32 ad_power; - u32 agc_gain; - u32 ch_power; - - tmp = apb_read_reg(QAM_BASE + 0x09c); - - ad_power = (tmp >> 22) & 0x1ff; - agc_gain = (tmp >> 0) & 0x7ff; - - ad_power = ad_power >> 4; - /* ch_power = lookuptable(agc_gain) + ad_power; TODO */ - ch_power = (ad_power & 0xffff) + ((agc_gain & 0xffff) << 16); - - return ch_power; -} - -static u32 dvbc_get_snr(void) -{ - u32 tmp, snr; - - tmp = apb_read_reg(QAM_BASE + 0x14) & 0xfff; - snr = tmp * 100 / 32; /* * 1e2 */ - - return snr; -} - -static u32 dvbc_get_ber(void) -{ - u32 rs_ber; - u32 rs_packet_len; - - rs_packet_len = apb_read_reg(QAM_BASE + 0x10) & 0xffff; - rs_ber = apb_read_reg(QAM_BASE + 0x14) >> 12 & 0xfffff; - - /* rs_ber = rs_ber / 204.0 / 8.0 / rs_packet_len; */ - if (rs_packet_len == 0) - rs_ber = 1000000; - else - rs_ber = rs_ber * 613 / rs_packet_len; /* 1e-6 */ - - return rs_ber; -} - -static u32 dvbc_get_per(void) -{ - u32 rs_per; - u32 rs_packet_len; - u32 acc_rs_per_times; - - rs_packet_len = apb_read_reg(QAM_BASE + 0x10) & 0xffff; - rs_per = apb_read_reg(QAM_BASE + 0x18) >> 16 & 0xffff; - - acc_rs_per_times = apb_read_reg(QAM_BASE + 0xcc) & 0xffff; - /*rs_per = rs_per / rs_packet_len; */ - - if (rs_packet_len == 0) - rs_per = 10000; - else - rs_per = 10000 * rs_per / rs_packet_len; /* 1e-4 */ - - /*return rs_per; */ - return acc_rs_per_times; -} - -static u32 dvbc_get_symb_rate(void) -{ - u32 tmp; - u32 adc_freq; - u32 symb_rate; - - adc_freq = apb_read_reg(QAM_BASE + 0x34) >> 16 & 0xffff; - tmp = apb_read_reg(QAM_BASE + 0xb8); - - if ((tmp >> 15) == 0) - symb_rate = 0; - else - symb_rate = 10 * (adc_freq << 12) / (tmp >> 15); - /* 1e4 */ - - return symb_rate; -} - -static int dvbc_get_freq_off(void) -{ - int tmp; - int symb_rate; - int freq_off; - - symb_rate = dvbc_get_symb_rate(); - tmp = apb_read_reg(QAM_BASE + 0xe0) & 0x3fffffff; - if (tmp >> 29 & 1) - tmp -= (1 << 30); - - freq_off = ((tmp >> 16) * 25 * (symb_rate >> 10)) >> 3; - - return freq_off; -} - -static void dvbc_set_test_bus(u8 sel) -{ - u32 tmp; - - tmp = apb_read_reg(QAM_BASE + 0x08); - tmp &= ~(0x1f << 4); - tmp |= ((sel & 0x1f) << 4) | (1 << 3); - apb_write_reg(QAM_BASE + 0x08, tmp); -} - -void dvbc_get_test_out(u8 sel, u32 len, u32 *buf) -{ - int i, cnt; - - dvbc_set_test_bus(sel); - - for (i = 0, cnt = 0; i < len - 4 && cnt < 1000000; i++) { - buf[i] = apb_read_reg(QAM_BASE + 0xb0); - if (buf[i] >> 11 & 1) { - buf[i++] = apb_read_reg(QAM_BASE + 0xb0); - buf[i++] = apb_read_reg(QAM_BASE + 0xb0); - buf[i++] = apb_read_reg(QAM_BASE + 0xb0); - buf[i++] = apb_read_reg(QAM_BASE + 0xb0); - } else { - i--; - } - - cnt++; - } -} - -#if 0 -static void dvbc_sw_reset(int addr, int idx) -{ - u32 tmp; - - tmp = apb_read_reg(QAM_BASE + addr); - - tmp &= ~(1 << idx); - apb_write_reg(QAM_BASE + addr, tmp); - - udelay(1); - - tmp |= (1 << idx); - apb_write_reg(QAM_BASE + addr, tmp); -} - -static void dvbc_reset(void) -{ - dvbc_sw_reset(0x04, 0); -} - -static void dvbc_eq_reset(void) -{ - dvbc_sw_reset(0x50, 3); -} - -static void dvbc_eq_smma_reset(void) -{ - dvbc_sw_reset(0xe8, 0); -} -#endif -static void dvbc_reg_initial(struct aml_demod_sta *demod_sta) -{ - u32 clk_freq; - u32 adc_freq; - u8 tuner; - u8 ch_mode; - u8 agc_mode; - u32 ch_freq; - u16 ch_if; - u16 ch_bw; - u16 symb_rate; - u32 phs_cfg; - int afifo_ctr; - int max_frq_off, tmp; - - clk_freq = demod_sta->clk_freq; /* kHz */ - adc_freq = demod_sta->adc_freq; /* kHz */ -/* adc_freq = 25414;*/ - tuner = demod_sta->tuner; - ch_mode = demod_sta->ch_mode; - agc_mode = demod_sta->agc_mode; - ch_freq = demod_sta->ch_freq; /* kHz */ - ch_if = demod_sta->ch_if; /* kHz */ - ch_bw = demod_sta->ch_bw; /* kHz */ - symb_rate = demod_sta->symb_rate; /* k/sec */ - dprintk("ch_if is %d, %d, %d, %d, %d\n", - ch_if, ch_mode, ch_freq, ch_bw, symb_rate); -/* ch_mode=4;*/ -/* apb_write_reg(DEMOD_CFG_BASE,0x00000007);*/ - /* disable irq */ - apb_write_reg(QAM_BASE + 0xd0, 0); - - /* reset */ - /*dvbc_reset(); */ - apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) & ~(1 << 4)); - /* disable fsm_en */ - apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) & ~(1 << 0)); - /* Sw disable demod */ - apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) | (1 << 0)); - /* Sw enable demod */ - - apb_write_reg(QAM_BASE + 0x000, 0x00000000); - /* QAM_STATUS */ - apb_write_reg(QAM_BASE + 0x004, 0x00000f00); - /* QAM_GCTL0 */ - apb_write_reg(QAM_BASE + 0x008, (ch_mode & 7)); - /* qam mode */ - - switch (ch_mode) { - case 0: /* 16 QAM */ - apb_write_reg(QAM_BASE + 0x054, 0x23460224); - /* EQ_FIR_CTL, */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - apb_write_reg(QAM_BASE + 0x074, 0x50001a0); - /* EQ_TH_LMS 40db 13db */ - apb_write_reg(QAM_BASE + 0x07c, 0x003001e9); - /* EQ_NORM and EQ_TH_MMA */ - /*apb_write_reg(QAM_BASE+0x080, 0x000be1ff); - * // EQ_TH_SMMA0 - */ - apb_write_reg(QAM_BASE + 0x080, 0x000e01fe); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x00000000); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292b); - * // Pilips Tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292d); - * // Pilips Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092d); - /* Pilips Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213 */ - break; - - case 1: /* 32 QAM */ - apb_write_reg(QAM_BASE + 0x054, 0x24560506); - /* EQ_FIR_CTL, */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x5000260); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x50001f0); - /* EQ_TH_LMS 40db 17.5db */ - apb_write_reg(QAM_BASE + 0x07c, 0x00500102); - /* EQ_TH_MMA 0x000001cc */ - apb_write_reg(QAM_BASE + 0x080, 0x00077140); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x001fb000); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292b); - * // Pilips Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092b); - /* Pilips Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213 */ - break; - - case 2: /* 64 QAM */ - /*apb_write_reg(QAM_BASE+0x054, 0x2256033a); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0x2336043a); - /* EQ_FIR_CTL, by raymond */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x5000260); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000230); - /* EQ_TH_LMS 40db 17.5db */ - apb_write_reg(QAM_BASE + 0x07c, 0x007001bd); - /* EQ_TH_MMA */ - apb_write_reg(QAM_BASE + 0x080, 0x000580ed); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x001771fb); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d); - /* Pilips Tuner & maxlinear Tuner */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a); - * // Pilips Tuner & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213 */ - break; - - case 3: /* 128 QAM */ - /*apb_write_reg(QAM_BASE+0x054, 0x2557046a); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0x2437067a); - /* EQ_FIR_CTL, by raymond 20121213 */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000d0); - /* EQ_CRTH_SNR */ - /* apb_write_reg(QAM_BASE+0x074, 0x02440240); - * // EQ_TH_LMS 18.5db 18db - */ - /* apb_write_reg(QAM_BASE+0x074, 0x04000400); - * // EQ_TH_LMS 22db 22.5db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000260); - /* EQ_TH_LMS 40db 19db */ - /*apb_write_reg(QAM_BASE+0x07c, 0x00b000f2); - * // EQ_TH_MMA0x000000b2 - */ - apb_write_reg(QAM_BASE + 0x07c, 0x00b00132); - /* EQ_TH_MMA0x000000b2 by raymond 20121213 */ - apb_write_reg(QAM_BASE + 0x080, 0x0003a09d); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x000f8150); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x001a51f8); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092c); - /* Pilips Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213 */ - break; - - case 4: /* 256 QAM */ - /*apb_write_reg(QAM_BASE+0x054, 0xa2580588); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0xa25905f9); - /* EQ_FIR_CTL, by raymond 20121213 */ - apb_write_reg(QAM_BASE + 0x068, 0x01e00220); - /* EQ_CRTH_SNR */ - /*apb_write_reg(QAM_BASE+0x074, 0x50002a0); - * // EQ_TH_LMS 40db 19db - */ - apb_write_reg(QAM_BASE + 0x074, 0x5000270); - /* EQ_TH_LMS 40db 19db by raymond 201211213 */ - apb_write_reg(QAM_BASE + 0x07c, 0x00f001a5); - /* EQ_TH_MMA */ - apb_write_reg(QAM_BASE + 0x080, 0x0002c077); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x000bc0fe); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x0013f17e); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x01bc01f9); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips Tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292d); - * // Maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f80092d); - /* Maxlinear Tuner */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213, when adc=35M,sys=70M, - * its better than 0x61f2f66 - */ - break; - default: /*64qam */ - /*apb_write_reg(QAM_BASE+0x054, 0x2256033a); - * // EQ_FIR_CTL, - */ - apb_write_reg(QAM_BASE + 0x054, 0x2336043a); - /* EQ_FIR_CTL, by raymond */ - apb_write_reg(QAM_BASE + 0x068, 0x00c000c0); - /* EQ_CRTH_SNR */ - /* EQ_TH_LMS 40db 19db */ - apb_write_reg(QAM_BASE + 0x074, 0x5000230); - /* EQ_TH_LMS 40db 17.5db */ - apb_write_reg(QAM_BASE + 0x07c, 0x007001bd); - /* EQ_TH_MMA */ - apb_write_reg(QAM_BASE + 0x080, 0x000580ed); - /* EQ_TH_SMMA0 */ - apb_write_reg(QAM_BASE + 0x084, 0x001771fb); - /* EQ_TH_SMMA1 */ - apb_write_reg(QAM_BASE + 0x088, 0x00000000); - /* EQ_TH_SMMA2 */ - apb_write_reg(QAM_BASE + 0x08c, 0x00000000); - /* EQ_TH_SMMA3 */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c); - * // AGC_CTRL ALPS tuner - */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292c); - * // Pilips & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d); - /* Pilips Tuner & maxlinear Tuner */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a); - * // Pilips Tuner & maxlinear Tuner - */ - apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67); - /* by raymond 20121213 */ - break; - } - - /*apb_write_reg(QAM_BASE+0x00c, 0xfffffffe); - * // adc_cnt, symb_cnt - */ - apb_write_reg(QAM_BASE + 0x00c, 0xffff8ffe); - /* adc_cnt, symb_cnt by raymond 20121213 */ - if (clk_freq == 0) - afifo_ctr = 0; - else - afifo_ctr = (adc_freq * 256 / clk_freq) + 2; - if (afifo_ctr > 255) - afifo_ctr = 255; - apb_write_reg(QAM_BASE + 0x010, (afifo_ctr << 16) | 8000); - /* afifo, rs_cnt_cfg */ - - /*apb_write_reg(QAM_BASE+0x020, 0x21353e54); - * // PHS_reset & TIM_CTRO_ACCURATE sw_tim_select=0 - */ - /*apb_write_reg(QAM_BASE+0x020, 0x21b53e54); - * //modified by qiancheng - */ - apb_write_reg(QAM_BASE + 0x020, 0x61b53e54); - /*modified by qiancheng by raymond 20121208 0x63b53e54 for cci */ - /* apb_write_reg(QAM_BASE+0x020, 0x6192bfe2); - * //modifed by ligg 20130613 auto symb_rate scan - */ - if (adc_freq == 0) - phs_cfg = 0; - else - phs_cfg = (1 << 31) / adc_freq * ch_if / (1 << 8); - /* 8*fo/fs*2^20 fo=36.125, fs = 28.57114, = 21d775 */ - /* dprintk("phs_cfg = %x\n", phs_cfg); */ - apb_write_reg(QAM_BASE + 0x024, 0x4c000000 | (phs_cfg & 0x7fffff)); - /* PHS_OFFSET, IF offset, */ - - if (adc_freq == 0) { - max_frq_off = 0; - } else { - max_frq_off = (1 << 29) / symb_rate; - /* max_frq_off = (400KHz * 2^29) / - * (AD=28571 * symbol_rate=6875) - */ - tmp = 40000000 / adc_freq; - max_frq_off = tmp * max_frq_off; - } - dprintk("max_frq_off is %x,\n", max_frq_off); - apb_write_reg(QAM_BASE + 0x02c, max_frq_off & 0x3fffffff); - /* max frequency offset, by raymond 20121208 */ - - /*apb_write_reg(QAM_BASE+0x030, 0x011bf400); - * // TIM_CTL0 start speed is 0, when know symbol rate - */ - apb_write_reg(QAM_BASE + 0x030, 0x245cf451); - /*MODIFIED BY QIANCHENG */ -/* apb_write_reg(QAM_BASE+0x030, 0x245bf451); - * //modified by ligg 20130613 --auto symb_rate scan - */ - apb_write_reg(QAM_BASE + 0x034, - ((adc_freq & 0xffff) << 16) | (symb_rate & 0xffff)); - - apb_write_reg(QAM_BASE + 0x038, 0x00400000); - /* TIM_SWEEP_RANGE 16000 */ - -/************* hw state machine config **********/ - apb_write_reg(QAM_BASE + 0x040, 0x003c); -/* configure symbol rate step step 0*/ - - /* modified 0x44 0x48 */ - apb_write_reg(QAM_BASE + 0x044, (symb_rate & 0xffff) * 256); - /* blind search, configure max symbol_rate for 7218 fb=3.6M */ - /*apb_write_reg(QAM_BASE+0x048, 3600*256); - * // configure min symbol_rate fb = 6.95M - */ - apb_write_reg(QAM_BASE + 0x048, 3400 * 256); - /* configure min symbol_rate fb = 6.95M */ - - /*apb_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */ - /*apb_write_reg(QAM_BASE+0x0c0, 0xffffff6f); // threshold */ - /*apb_write_reg(QAM_BASE+0x0c0, 0xfffffd68); // threshold */ - /*apb_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */ - /*apb_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */ - /*apb_write_reg(QAM_BASE+0x0c0, 0xffff2f67); - * // threshold for skyworth - */ - /* apb_write_reg(QAM_BASE+0x0c0, 0x061f2f67); // by raymond 20121208 */ - /* apb_write_reg(QAM_BASE+0x0c0, 0x061f2f66); - * // by raymond 20121213, remove it to every constellation - */ -/************* hw state machine config **********/ - - apb_write_reg(QAM_BASE + 0x04c, 0x00008800); /* reserved */ - - /*apb_write_reg(QAM_BASE+0x050, 0x00000002); // EQ_CTL0 */ - apb_write_reg(QAM_BASE + 0x050, 0x01472002); - /* EQ_CTL0 by raymond 20121208 */ - - /*apb_write_reg(QAM_BASE+0x058, 0xff550e1e); // EQ_FIR_INITPOS */ - apb_write_reg(QAM_BASE + 0x058, 0xff100e1e); - /* EQ_FIR_INITPOS for skyworth */ - - apb_write_reg(QAM_BASE + 0x05c, 0x019a0000); /* EQ_FIR_INITVAL0 */ - apb_write_reg(QAM_BASE + 0x060, 0x019a0000); /* EQ_FIR_INITVAL1 */ - - /*apb_write_reg(QAM_BASE+0x064, 0x01101128); // EQ_CRTH_TIMES */ - apb_write_reg(QAM_BASE + 0x064, 0x010a1128); - /* EQ_CRTH_TIMES for skyworth */ - apb_write_reg(QAM_BASE + 0x06c, 0x00041a05); /* EQ_CRTH_PPM */ - - apb_write_reg(QAM_BASE + 0x070, 0xffb9aa01); /* EQ_CRLP */ - - /*apb_write_reg(QAM_BASE+0x090, 0x00020bd5); // agc control */ - apb_write_reg(QAM_BASE + 0x090, 0x00000bd5); /* agc control */ - - /* agc control */ - /* apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);// AGC_CTRL ALPS tuner */ - /* apb_write_reg(QAM_BASE+0x094, 0x7f80292c); // Pilips Tuner */ - if ((agc_mode & 1) == 0) - /* freeze if agc */ - apb_write_reg(QAM_BASE + 0x094, - apb_read_reg(QAM_BASE + 0x94) | (0x1 << 10)); - if ((agc_mode & 2) == 0) { - /* IF control */ - /*freeze rf agc */ - apb_write_reg(QAM_BASE + 0x094, - apb_read_reg(QAM_BASE + 0x94) | (0x1 << 13)); - } - /*Maxlinear Tuner */ - /*apb_write_reg(QAM_BASE+0x094, 0x7f80292d); */ - apb_write_reg(QAM_BASE + 0x098, 0x9fcc8190); - /* AGC_IFGAIN_CTRL */ - /*apb_write_reg(QAM_BASE+0x0a0, 0x0e028c00); - * // AGC_RFGAIN_CTRL 0x0e020800 - */ - /*apb_write_reg(QAM_BASE+0x0a0, 0x0e03cc00); - * // AGC_RFGAIN_CTRL 0x0e020800 - */ - /*apb_write_reg(QAM_BASE+0x0a0, 0x0e028700); - * // AGC_RFGAIN_CTRL 0x0e020800 now - */ - /*apb_write_reg(QAM_BASE+0x0a0, 0x0e03cd00); - * // AGC_RFGAIN_CTRL 0x0e020800 - */ - /*apb_write_reg(QAM_BASE+0x0a0, 0x0603cd11); - * // AGC_RFGAIN_CTRL 0x0e020800 by raymond, - * if Adjcent channel test, maybe it need change.20121208 ad invert - */ - apb_write_reg(QAM_BASE + 0x0a0, 0x0603cd10); - /* AGC_RFGAIN_CTRL 0x0e020800 by raymond, - * if Adjcent channel test, maybe it need change. - * 20121208 ad invert,20130221, suit for two path channel. - */ - - apb_write_reg(QAM_BASE + 0x004, apb_read_reg(QAM_BASE + 0x004) | 0x33); - /* IMQ, QAM Enable */ - - /* start hardware machine */ - /*dvbc_sw_reset(0x004, 4); */ - apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) | (1 << 4)); - apb_write_reg(QAM_BASE + 0x0e8, - (apb_read_reg(QAM_BASE + 0x0e8) | (1 << 2))); - - /* clear irq status */ - apb_read_reg(QAM_BASE + 0xd4); - - /* enable irq */ - apb_write_reg(QAM_BASE + 0xd0, 0x7fff << 3); - -/*auto track*/ - /* dvbc_set_auto_symtrack(); */ -} - -u32 dvbc_set_auto_symtrack(void) -{ - apb_write_reg(QAM_BASE + 0x030, 0x245bf45c); /*open track */ - apb_write_reg(QAM_BASE + 0x020, 0x61b2bf5c); - apb_write_reg(QAM_BASE + 0x044, (7000 & 0xffff) * 256); - apb_write_reg(QAM_BASE + 0x038, 0x00220000); - apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) & ~(1 << 0)); - /* Sw disable demod */ - apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) | (1 << 0)); - /* Sw enable demod */ - return 0; -} - -int dvbc_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dvbc *demod_dvbc) -{ - int ret = 0; - u16 symb_rate; - u8 mode; - u32 ch_freq; - - dprintk("f=%d, s=%d, q=%d\n", - demod_dvbc->ch_freq, demod_dvbc->symb_rate, demod_dvbc->mode); - demod_i2c->tuner = 7; - mode = demod_dvbc->mode; - symb_rate = demod_dvbc->symb_rate; - ch_freq = demod_dvbc->ch_freq; - if (mode > 4) { - dprintk("Error: Invalid QAM mode option %d\n", mode); - mode = 2; - ret = -1; - } - - if (symb_rate < 1000 || symb_rate > 7000) { - dprintk("Error: Invalid Symbol Rate option %d\n", symb_rate); - symb_rate = 6875; - ret = -1; - } - - if (ch_freq < 1000 || ch_freq > 900000) { - dprintk("Error: Invalid Channel Freq option %d\n", ch_freq); - ch_freq = 474000; - ret = -1; - } - /* if (ret != 0) return ret; */ - demod_sta->dvb_mode = 0; - demod_sta->ch_mode = mode; - /* 0:16, 1:32, 2:64, 3:128, 4:256 */ - demod_sta->agc_mode = 1; - /* 0:NULL, 1:IF, 2:RF, 3:both */ - demod_sta->ch_freq = ch_freq; - demod_sta->tuner = demod_i2c->tuner; - - if (demod_i2c->tuner == 1) - demod_sta->ch_if = 36130; /* TODO DCT tuner */ - else if (demod_i2c->tuner == 2) - demod_sta->ch_if = 4570; /* TODO Maxlinear tuner */ - else if (demod_i2c->tuner == 7) - /* demod_sta->ch_if = 5000; // TODO Si2176 tuner */ - - demod_sta->ch_bw = 8000; /* TODO */ - if (demod_sta->ch_if == 0) - demod_sta->ch_if = 5000; - demod_sta->symb_rate = symb_rate; - dvbc_reg_initial(demod_sta); - - return ret; -} - -int dvbc_status(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_sts *demod_sts) -{ - struct aml_fe_dev *dev; - -/* int ftmp, tmp; */ - dev = NULL; - demod_sts->ch_sts = apb_read_reg(QAM_BASE + 0x18); - demod_sts->ch_pow = dvbc_get_ch_power(); - demod_sts->ch_snr = dvbc_get_snr(); - demod_sts->ch_ber = dvbc_get_ber(); - demod_sts->ch_per = dvbc_get_per(); - demod_sts->symb_rate = dvbc_get_symb_rate(); - demod_sts->freq_off = dvbc_get_freq_off(); - /*demod_sts->dat0 = apb_read_reg(QAM_BASE+0x28); */ -/* demod_sts->dat0 = tuner_get_ch_power(demod_i2c);*/ - demod_sts->dat1 = tuner_get_ch_power(dev); -#if 0 - - ftmp = demod_sts->ch_sts; - dprintk("[dvbc debug] ch_sts is %x\n", ftmp); - ftmp = demod_sts->ch_snr; - ftmp /= 100; - dprintk("snr %d dB ", ftmp); - ftmp = demod_sts->ch_ber; - dprintk("ber %.d ", ftmp); - tmp = demod_sts->ch_per; - dprintk("per %d ", tmp); - ftmp = demod_sts->symb_rate; - dprintk("srate %.d ", ftmp); - ftmp = demod_sts->freq_off; - dprintk("freqoff %.d kHz ", ftmp); - tmp = demod_sts->dat1; - dprintk("strength %ddb 0xe0 status is %lu ,b4 status is %lu", tmp, - (apb_read_reg(QAM_BASE + 0xe0) & 0xffff), - (apb_read_reg(QAM_BASE + 0xb4) & 0xffff)); - dprintk("dagc_gain is %lu ", apb_read_reg(QAM_BASE + 0xa4) & 0x7f); - tmp = demod_sts->ch_pow; - dprintk("power is %ddb\n", (tmp & 0xffff)); - -#endif - - return 0; -} - -void dvbc_enable_irq(int dvbc_irq) -{ - u32 mask; - - /* clear status */ - apb_read_reg(QAM_BASE + 0xd4); - /* enable irq */ - mask = apb_read_reg(QAM_BASE + 0xd0); - mask |= (1 << dvbc_irq); - apb_write_reg(QAM_BASE + 0xd0, mask); -} - -void dvbc_disable_irq(int dvbc_irq) -{ - u32 mask; - - /* disable irq */ - mask = apb_read_reg(QAM_BASE + 0xd0); - mask &= ~(1 << dvbc_irq); - apb_write_reg(QAM_BASE + 0xd0, mask); - /* clear status */ - apb_read_reg(QAM_BASE + 0xd4); -} - -char *dvbc_irq_name[] = { - " ADC", - " Symbol", - " RS", - " In_Sync0", - " In_Sync1", - " In_Sync2", - " In_Sync3", - " In_Sync4", - "Out_Sync0", - "Out_Sync1", - "Out_Sync2", - "Out_Sync3", - "Out_Sync4", - "In_SyncCo", - "OutSyncCo", - " In_Dagc", - " Out_Dagc", - " Eq_Mode", - "RS_Uncorr" -}; - -void dvbc_isr(struct aml_demod_sta *demod_sta) -{ - u32 stat, mask; - int dvbc_irq; - - stat = apb_read_reg(QAM_BASE + 0xd4); - mask = apb_read_reg(QAM_BASE + 0xd0); - stat &= mask; - - for (dvbc_irq = 0; dvbc_irq < 20; dvbc_irq++) { - if (stat >> dvbc_irq & 1) { - if (demod_sta->debug) - dprintk("irq: dvbc %2d %s %8x\n", - dvbc_irq, dvbc_irq_name[dvbc_irq], - stat); - /* dvbc_disable_irq(dvbc_irq); */ - } - } -} - -int dvbc_isr_islock(void) -{ -#define IN_SYNC4_MASK (0x80) - - u32 stat, mask; - - stat = apb_read_reg(QAM_BASE + 0xd4); - apb_write_reg(QAM_BASE + 0xd4, 0); - mask = apb_read_reg(QAM_BASE + 0xd0); - stat &= mask; - - return (stat & IN_SYNC4_MASK) == IN_SYNC4_MASK; -} diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c deleted file mode 100644 index 7654aaef1607..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c +++ /dev/null @@ -1,2188 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include "demod_func.h" - -static int debug_amldvbt; - -module_param(debug_amldvbt, int, 0644); -MODULE_PARM_DESC(debug_amldvbt, "turn on debugging (default: 0)"); -#define dprintk(args ...) do { if (debug_amldvbt) printk(args); } while (0) - -static int tuner_type = 3; - -static void set_ACF_coef(int ADsample, int bandwidth) -{ - if (ADsample == 45) { - /* Set ACF and IIREQ */ - if (bandwidth == 0) { - /*8M Hz */ - apb_write_reg(2, 0x2c, 0x255); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x0B5); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x091); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x02E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x253); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x0CB); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x2CD); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x07C); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x250); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0E4); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x276); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05D); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x24D); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0F3); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x25E); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x24A); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0FD); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x256); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003effff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003cefbe); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003adf7c); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x0038bf39); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x003696f5); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x003466b0); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00322e69); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x002fee21); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x002dadd9); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002b6d91); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x00291d48); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x0026ccfe); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x00245cb2); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0021d463); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x001f2410); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x001c3bb6); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x00192b57); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x0015e2f1); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x00127285); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x000eca14); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x000ac99b); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x00063913); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x0000c073); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x003a3fb4); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00347ecf); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x002ff649); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x002a8dab); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x002444f0); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x001d0c1b); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x000fc300); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x000118ce); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x003c17c3); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x00000751); - } else if (bandwidth == 1) { - /* 7Mhz */ - apb_write_reg(2, 0x2c, 0x24B); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x0BD); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x04B); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x03E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x246); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x0D1); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x2A2); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x07C); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x241); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0E7); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x25B); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05D); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x23D); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0F5); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x248); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x23A); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0FD); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x242); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f07ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003cffbf); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003aef7e); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x0038d73c); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x0036b6f9); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x003486b3); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00324e6d); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x00300e25); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x002dcddd); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002b8594); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x00292d4b); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x0026d500); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x00245cb3); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0021cc62); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x001f0c0d); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x001c1bb3); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x0018fb52); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x0015b2eb); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x00123a7f); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x000e9a0e); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x000a9995); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0006090d); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x0000a06e); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x003a57b3); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x0034ded8); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x00309659); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x002b75c4); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x0025350e); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x001dec37); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x00126b28); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x00031130); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x003cffec); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x00000767); - } else if (bandwidth == 2) { - /* 6MHz */ - apb_write_reg(2, 0x2c, 0x240); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x0C6); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x3F9); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x03E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x23A); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x0D7); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x27B); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x07C); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x233); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0EA); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x244); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05D); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x22F); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0F6); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x235); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x22B); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0FD); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x231); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f07ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003cffbf); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003aef7e); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x0038d73c); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x0036b6f8); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x003486b3); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x0032466c); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x002ffe24); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x002dadda); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002b5d90); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x0028fd45); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002694f9); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x002414ab); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x00217458); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x001ea402); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x001ba3a5); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x00187342); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x00151ad9); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x0011926b); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x000dc9f6); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x0009a178); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0004d8eb); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x003f4045); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x0038e785); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00337eab); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x002f3e2d); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x002a1599); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x0023ace1); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x001b33fb); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x000cd29c); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x0001c0c1); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x003cefde); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x0000076a); - } else { - /* 5MHz */ - apb_write_reg(2, 0x2c, 0x236); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x0CE); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x39A); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x03E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x22F); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x0DE); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x257); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x07C); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x227); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0EE); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x230); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05D); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x222); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0F8); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x225); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x21E); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0FE); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x222); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003effff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003ce7bd); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003ac77a); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x0038a737); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x00367ef2); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x00344eac); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00321e66); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x002fee20); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x002dbdda); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002b8d94); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x00295d4e); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x00272508); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0024dcc0); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x00227475); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x001fe426); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x001d1bd1); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x001a2374); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x0016e311); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x00136aa6); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x000fba33); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x000ba9b8); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0007092e); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x0001988e); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x003b37d0); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x0035aef3); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x00316673); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x002c45de); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x0025e527); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x001da444); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x000deaea); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x000178bf); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x003cb7d6); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x00000765); - } - } else if (ADsample == 28) { - /* 28.5714 MHz Set ACF */ - if (bandwidth == 0) { - /*8M Hz */ - apb_write_reg(2, 0x2c, 0x2DB); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x05B); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x163); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x00E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x2D5); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x08B); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x3BC); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x06D); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x2CF); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0BF); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x321); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x008); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x2C9); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0E3); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x2EE); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x058); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x2C3); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0F8); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x2DD); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04D); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003ef7ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d37c0); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003c3f94); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003b0f78); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x0038c73f); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x00369ef1); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x003576be); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x0033b698); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x0031164d); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002f1dfd); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002de5cf); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002c15a2); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0029f560); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0027bd1b); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x00252ccf); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x0022bc7c); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x00207c34); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001da3e5); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001a9b83); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x0017db27); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x001432c6); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x000fa23e); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000b91af); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x00077136); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x0002c090); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003ec01a); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003a3f92); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x00354efa); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x002fee54); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x002a35a3); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x0023f4e4); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x001cdc12); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x00000316); - } else if (bandwidth == 1) { - apb_write_reg(2, 0x2c, 0x2C2); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x069); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x134); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x00E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x2B7); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x095); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x36F); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x06D); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x2AA); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0C6); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x2E5); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x008); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x2A1); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0E6); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x2BA); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x058); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x299); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0F9); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x2AC); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04D); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003ee7ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d1fbc); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003bf790); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003a876a); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x00388f31); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x0036c6f3); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x003536bf); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x00334689); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x00310644); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002ef5fd); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002d45c2); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002b7d8c); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x00298550); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x00278510); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x00252ccc); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x0022847c); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x00201427); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001e03e0); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001b6b9b); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x0017c336); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x0013e2b8); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0010b246); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000d81e8); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x00084966); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x0003089c); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003f0022); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003aaf9c); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x00360f0c); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x00312e74); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x002c05d3); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x00268d2a); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x0020bc76); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x000003b3); - } else if (bandwidth == 2) { - /* 6MHz */ - apb_write_reg(2, 0x2c, 0x2A9); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x078); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x0F4); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x01E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x299); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x0A1); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x321); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x078); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x288); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0CD); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x2AE); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05F); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x27C); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0E9); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x28B); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x058); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x273); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0FA); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x281); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04D); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f17ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d3fc4); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003b7f8a); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x0039df55); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x00381720); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x00360ee2); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00342ea1); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x0032ee6e); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x0031e64e); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x00300e22); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002daddc); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002b758f); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0029ad51); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0027ad18); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x00250ccd); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x00227476); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x00204c2a); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001de3e6); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001a838a); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x0016ab12); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x00137a9d); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x00113a4a); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000db1f8); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x0007c15f); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00022883); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003df803); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x00398f79); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x0034d6e6); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x002fd64b); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x002a8da7); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x002504fa); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x001f2443); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x00000382); - } else { - apb_write_reg(2, 0x2c, 0x28F); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x088); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x09E); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x01E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x27C); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x0AD); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x2D6); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x078); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x268); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0D4); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x27C); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05F); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x25B); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0ED); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x262); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x058); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x252); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0FB); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x25A); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04D); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f17ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d4fc5); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003baf8e); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003a3f5d); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x0038df32); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x00374703); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00354ec9); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x00333e88); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x00314e47); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002f860c); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002d9dd2); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002b5590); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0028cd42); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x00266cf2); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x00245cab); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x00225c6b); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x00200427); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001d4bd5); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001a9b7d); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x00183b2b); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x0015b2e1); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x00122a83); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000d49fc); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x0007594e); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00024080); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003e980e); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003ab796); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x00368f15); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x00320e8a); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x002d25f4); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x0027ad4f); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x00219496); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x000003c9); - } - } else { - /* 20.7 MHz Set ACF */ - if (bandwidth == 0) { - /*8M Hz */ - apb_write_reg(2, 0x2c, 0x318); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x03E); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x1AE); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x00E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x326); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x074); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x074); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x06F); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x336); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0B1); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x3C9); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x008); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x33F); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0DC); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x384); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x340); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0F6); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x36D); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f37ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d97cc); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003bf798); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003a4f64); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x0038a72f); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x0036f6f9); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x003546c3); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x0033868c); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x0031be54); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002fe61a); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002e05df); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002c15a2); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x002a1562); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0027f520); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x0025c4dc); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x00236c93); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x0020f446); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001e4bf4); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001b739d); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x00185b3d); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x0014ead5); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x00111a62); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000cb9df); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x00079148); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00030093); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003f802a); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003b77b2); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x0036a725); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x0030ae7b); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x00285d9f); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x001abc46); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x000f8a85); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x00000187); - } else if (bandwidth == 1) { - apb_write_reg(2, 0x2c, 0x2F9); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x04C); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x18E); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x00E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x2FD); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x07F); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x01A); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x06D); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x300); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0B8); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x372); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05F); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x301); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0DF); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x335); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x2FE); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0F7); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x320); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f37ff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d8fcc); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003bef97); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003a4762); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x0038972d); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x0036e6f7); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00352ec1); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x00336e89); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x00319e50); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002fce16); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002de5db); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002bf59d); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0029ed5e); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0027d51c); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x00259cd7); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x0023448e); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x0020cc41); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001e23ef); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001b4b98); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x00183339); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x0014cad1); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0010fa5e); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000c99dc); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x00078145); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x0002f892); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003f802a); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003b8fb3); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x0036d729); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x00310682); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x00290dae); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x001c0c67); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x0010a2ad); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x000001a8); - } else if (bandwidth == 2) { - /* 6MHz */ - apb_write_reg(2, 0x2c, 0x2D9); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x05C); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x161); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x00E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x2D4); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x08B); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x3B8); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x06B); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x2CD); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0C0); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x31E); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05F); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x2C7); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0E3); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x2EB); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x2C1); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0F8); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x2DA); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f2fff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d87cb); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003bdf96); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003a2f60); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x00387f2a); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x0036c6f4); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x00350ebd); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x00334684); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x0031764b); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002f9e11); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002db5d4); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002bbd97); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0029b557); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x00279515); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x00255ccf); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x00230c87); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x0020943a); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001debe8); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001b1b91); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x00180b33); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x0014aacc); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0010e25a); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000c91da); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x00078945); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00031895); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003fa82e); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003bbfb8); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x00371730); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x0031668c); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x00299dbc); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x001d1480); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x00119acf); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x000001c4); - } else { - apb_write_reg(2, 0x2c, 0x2B9); /* ACF_STAGE1_A1 */ - apb_write_reg(2, 0x2d, 0x06E); /* ACF_STAGE1_A2 */ - apb_write_reg(2, 0x2e, 0x11E); /* ACF_STAGE1_B1 */ - apb_write_reg(2, 0x2f, 0x01E); /* ACF_STAGE1_GAIN */ - apb_write_reg(2, 0x30, 0x2AB); /* ACF_STAGE2_A1 */ - apb_write_reg(2, 0x31, 0x099); /* ACF_STAGE2_A2 */ - apb_write_reg(2, 0x32, 0x351); /* ACF_STAGE2_B1 */ - apb_write_reg(2, 0x33, 0x06B); /* ACF_STAGE2_GAIN */ - apb_write_reg(2, 0x34, 0x29D); /* ACF_STAGE3_A1 */ - apb_write_reg(2, 0x35, 0x0C8); /* ACF_STAGE3_A2 */ - apb_write_reg(2, 0x36, 0x2D0); /* ACF_STAGE3_B1 */ - apb_write_reg(2, 0x37, 0x05F); /* ACF_STAGE3_GAIN */ - apb_write_reg(2, 0x38, 0x292); /* ACF_STAGE4_A1 */ - apb_write_reg(2, 0x39, 0x0E7); /* ACF_STAGE4_A2 */ - apb_write_reg(2, 0x3a, 0x2A8); /* ACF_STAGE4_B1 */ - apb_write_reg(2, 0x3b, 0x05A); /* ACF_STAGE4_GAIN */ - apb_write_reg(2, 0x3c, 0x28A); /* ACF_STAGE5_A1 */ - apb_write_reg(2, 0x3d, 0x0F9); /* ACF_STAGE5_A2 */ - apb_write_reg(2, 0x3e, 0x29B); /* ACF_STAGE5_B1 */ - apb_write_reg(2, 0x3f, 0x04B); /* ACF_STAGE5_GAIN */ - - apb_write_reg(2, 0xfe, 0x000); - apb_write_reg(2, 0xff, 0x003f2fff); - apb_write_reg(2, 0xfe, 0x001); - apb_write_reg(2, 0xff, 0x003d7fca); - apb_write_reg(2, 0xfe, 0x002); - apb_write_reg(2, 0xff, 0x003bcf94); - apb_write_reg(2, 0xfe, 0x003); - apb_write_reg(2, 0xff, 0x003a1f5e); - apb_write_reg(2, 0xfe, 0x004); - apb_write_reg(2, 0xff, 0x00386727); - apb_write_reg(2, 0xfe, 0x005); - apb_write_reg(2, 0xff, 0x0036a6f0); - apb_write_reg(2, 0xfe, 0x006); - apb_write_reg(2, 0xff, 0x0034e6b8); - apb_write_reg(2, 0xfe, 0x007); - apb_write_reg(2, 0xff, 0x0033167f); - apb_write_reg(2, 0xfe, 0x008); - apb_write_reg(2, 0xff, 0x00314645); - apb_write_reg(2, 0xfe, 0x009); - apb_write_reg(2, 0xff, 0x002f660a); - apb_write_reg(2, 0xfe, 0x00a); - apb_write_reg(2, 0xff, 0x002d75cd); - apb_write_reg(2, 0xfe, 0x00b); - apb_write_reg(2, 0xff, 0x002b758e); - apb_write_reg(2, 0xfe, 0x00c); - apb_write_reg(2, 0xff, 0x0029654e); - apb_write_reg(2, 0xfe, 0x00d); - apb_write_reg(2, 0xff, 0x0027450a); - apb_write_reg(2, 0xfe, 0x00e); - apb_write_reg(2, 0xff, 0x002504c4); - apb_write_reg(2, 0xfe, 0x00f); - apb_write_reg(2, 0xff, 0x0022a47b); - apb_write_reg(2, 0xfe, 0x010); - apb_write_reg(2, 0xff, 0x0020242d); - apb_write_reg(2, 0xfe, 0x011); - apb_write_reg(2, 0xff, 0x001d7bdb); - apb_write_reg(2, 0xfe, 0x012); - apb_write_reg(2, 0xff, 0x001aa383); - apb_write_reg(2, 0xfe, 0x013); - apb_write_reg(2, 0xff, 0x00178b24); - apb_write_reg(2, 0xfe, 0x014); - apb_write_reg(2, 0xff, 0x00142abd); - apb_write_reg(2, 0xfe, 0x015); - apb_write_reg(2, 0xff, 0x0010624a); - apb_write_reg(2, 0xfe, 0x016); - apb_write_reg(2, 0xff, 0x000c11ca); - apb_write_reg(2, 0xfe, 0x017); - apb_write_reg(2, 0xff, 0x00070935); - apb_write_reg(2, 0xfe, 0x018); - apb_write_reg(2, 0xff, 0x00029885); - apb_write_reg(2, 0xfe, 0x019); - apb_write_reg(2, 0xff, 0x003f281e); - apb_write_reg(2, 0xfe, 0x01a); - apb_write_reg(2, 0xff, 0x003b3fa9); - apb_write_reg(2, 0xfe, 0x01b); - apb_write_reg(2, 0xff, 0x00369720); - apb_write_reg(2, 0xfe, 0x01c); - apb_write_reg(2, 0xff, 0x0030ce7b); - apb_write_reg(2, 0xfe, 0x01d); - apb_write_reg(2, 0xff, 0x0028dda7); - apb_write_reg(2, 0xfe, 0x01e); - apb_write_reg(2, 0xff, 0x001c6464); - apb_write_reg(2, 0xfe, 0x01f); - apb_write_reg(2, 0xff, 0x0011b2c7); - apb_write_reg(2, 0xfe, 0x020); - apb_write_reg(2, 0xff, 0x000001cb); - } - } -} - -static void dvbt_reg_initial(struct aml_demod_sta *demod_sta) -{ - u32 clk_freq; - u32 adc_freq; - u8 ch_mode; - u8 agc_mode; - u32 ch_freq; - u16 ch_if; - u16 ch_bw; - u16 symb_rate; - - u8 bw; - u8 sr; - u8 ifreq; - u32 tmp; - - clk_freq = demod_sta->clk_freq; /* kHz */ - adc_freq = demod_sta->adc_freq; /* kHz */ - ch_mode = demod_sta->ch_mode; - agc_mode = demod_sta->agc_mode; - ch_freq = demod_sta->ch_freq; /* kHz */ - ch_if = demod_sta->ch_if; /* kHz */ - ch_bw = demod_sta->ch_bw; /* kHz */ - symb_rate = demod_sta->symb_rate; /* k/sec */ - - bw = 8 - ch_bw / 1000; - sr = adc_freq > 40000 ? 3 : adc_freq > 24000 ? 2 : - adc_freq > 20770 ? 1 : 0; - ifreq = ch_if > 35000 ? 0 : 1; - - /*//////////////////////////////////// */ - /* bw == 0 : 8M */ - /* 1 : 7M */ - /* 2 : 6M */ - /* 3 : 5M */ - /* sr == 0 : 20.7M */ - /* 1 : 20.8333M */ - /* 2 : 28.5714M */ - /* 3 : 45M */ - /* ifreq == 0: 36.13MHz */ - /* 1: 4.57MHz */ - /* agc_mode == 0: single AGC */ - /* 1: dual AGC */ - /*//////////////////////////////////// */ - apb_write_reg(2, 0x02, 0x00800000); - /* SW reset bit[23] ; write anything to zero */ - apb_write_reg(2, 0x00, 0x00000000); - - switch (sr) { - case 0: - apb_write_reg(2, 0x08, 0x00002966); - break; - case 1: - apb_write_reg(2, 0x08, 0x00002999); - break; - case 2: - apb_write_reg(2, 0x08, 0x00003924); - break; - case 3: - apb_write_reg(2, 0x08, 0x00005a00); - break; /*sample_rate /*45M */ - default: - break; - } - - apb_write_reg(2, 0x0d, 0x00000000); - apb_write_reg(2, 0x0e, 0x00000000); - dvbt_enable_irq(8); - - apb_write_reg(2, 0x11, 0x00100002); /* FSM [15:0] TIMER_FEC_LOST */ - apb_write_reg(2, 0x12, 0x02100201); /* FSM */ - apb_write_reg(2, 0x14, 0xe81c4ff6); /* AGC_TARGET 0xf0121385 */ - apb_write_reg(2, 0x15, 0x02050ca6); /* AGC_CTRL */ - - switch (sr) { - case 0: - apb_write_reg(2, 0x15, apb_read_reg(2, 0x15) | (0x5b << 12)); - break; - case 1: - apb_write_reg(2, 0x15, apb_read_reg(2, 0x15) | (0x5b << 12)); - break; - case 2: - apb_write_reg(2, 0x15, apb_read_reg(2, 0x15) | (0x7b << 12)); - break; - case 3: - apb_write_reg(2, 0x15, apb_read_reg(2, 0x15) | (0xc2 << 12)); - break; /* sample_rate /*45M */ - default: - break; - } - - if (agc_mode == 0) - apb_write_reg(2, 0x16, 0x67f80); /* AGC_IFGAIN_CTRL */ - else if (agc_mode == 1) - apb_write_reg(2, 0x16, 0x07f80); /* AGC_IFGAIN_CTRL */ - - apb_write_reg(2, 0x17, 0x07f80); /* AGC_RFGAIN_CTRL */ - apb_write_reg(2, 0x18, 0x00000000); /* AGC_IFGAIN_ACCUM */ - apb_write_reg(2, 0x19, 0x00000000); /* AGC_RFGAIN_ACCUM */ - - if (ifreq == 0) { - switch (sr) { - case 0: - apb_write_reg(2, 0x20, 0x00002096); - break; - /* DDC NORM_PHASE 36.13M IF For 20.7M sample rate */ - case 1: - apb_write_reg(2, 0x20, 0x000021a9); - break; - /* DDC NORM_PHASE 36.13M IF For 20.8333M sample rate*/ - case 2: - apb_write_reg(2, 0x20, 0x000021dc); - break; - /* DDC NORM_PHASE 36.13M IF For 28.57142M sample rate*/ - case 3: - apb_write_reg(2, 0x20, 0x000066e2); - break; - /* DDC NORM_PHASE 36.13M IF For 45M sample rate */ - default: - break; - } - } else if (ifreq == 1) { - switch (sr) { - case 0: - apb_write_reg(2, 0x20, 0x00001c42); - break; - /* DDC NORM_PHASE 4.57M IF For 20.7M sample rate */ - case 1: - apb_write_reg(2, 0x20, 0x00001c1f); - break; - /* DDC NORM_PHASE 4.57M IF For 20.8333M sample rate */ - case 2: - apb_write_reg(2, 0x20, 0x00001479); - break; - /* DDC NORM_PHASE 4.57M IF For 28.57142M sample rate*/ - case 3: - apb_write_reg(2, 0x20, 0x0000d00); - break; - /* DDC NORM_PHASE 4.57M IF For 45M sample rate */ - default: - break; - } - } - */tmp = ch_if * (1 << 15)/adc_freq; - tmp &= 0x3fff; - apb_write_reg(2, 0x20, tmp); - if (demod_sta->debug) - dprintk("IF: %d kHz ADC: %d kHz DDC: %04x\n", ch_if, adc_freq, - tmp); - - apb_write_reg(2, 0x21, 0x001ff000); /* DDC CS_FCFO_ADJ_CTRL */ - apb_write_reg(2, 0x22, 0x00000000); /* DDC ICFO_ADJ_CTRL */ - apb_write_reg(2, 0x23, 0x00004000); /* DDC TRACK_FCFO_ADJ_CTRL */ - apb_write_reg(2, 0x27, 0x00a98200); - /*[23] agc state mode [22:19] icfo_time_limit ;[18:15] tps_time_limit ; - * [14:4] cs_cfo_thres ; [3:0] fsm_state_d; - */ - /* 1 010,1 001,1 - * 000,0010,0000, xxxx - */ - apb_write_reg(2, 0x28, 0x04028032); - /* [31:24] cs_Q_thres; [23:13] sfo_thres; FSM [12:0] fcfo_thres;; */ - /* 0000,0100, 0000,0010,100 0,0000,0011,0010 */ - apb_write_reg(2, 0x29, 0x0051117F); - /*apb_write_reg(2, 0x29, 0x00010f7F); */ - /* [18:16] fec_rs_sh_ctrl ;[15:9] fsm_total_timer; - * [8:6] modeDet_time_limit; FSM [5:0] sfo_time_limit; ; - */ - /* 01, () 0000,111 1,01 11,1111 */ - - /* SRC NORM_INRATE */ - switch (bw) { - case 0: - tmp = (1 << 14) * adc_freq / 125 / 8 * 7; - break; - case 1: - tmp = (1 << 14) * adc_freq / 125; - break; - case 2: - tmp = (1 << 14) * adc_freq / 125 / 6 * 7; - break; - case 3: - tmp = (1 << 14) * adc_freq / 125 / 5 * 7; - break; - default: - tmp = (1 << 14) * adc_freq / 125 / 8 * 7; - break; - } - - apb_write_reg(2, 0x44, tmp & 0x7fffff); - - apb_write_reg(2, 0x45, 0x00000000); /* SRC SRC_PHASE_INI */ - apb_write_reg(2, 0x46, 0x02004000); - /* SRC SFO_ADJ_CTRL SFO limit 0x100!! */ - apb_write_reg(2, 0x48, 0xc0287); /* DAGC_CTRL */ - apb_write_reg(2, 0x49, 0x00000005); /* DAGC_CTRL1 */ - apb_write_reg(2, 0x4c, 0x00000bbf); /* CCI_RP */ - apb_write_reg(2, 0x4d, 0x00000376); /* CCI_RPSQ */ - apb_write_reg(2, 0x4e, 0x00202109); /* CCI_CTRL */ - apb_write_reg(2, 0x52, 0x00000000); /* CCI_NOTCH1_A2 */ - apb_write_reg(2, 0x53, 0x00000000); /* CCI_NOTCH1_B1 */ - apb_write_reg(2, 0x54, 0x00c00000); /* CCI_NOTCH2_A1 */ - apb_write_reg(2, 0x55, 0x00000000); /* CCI_NOTCH2_A2 */ - apb_write_reg(2, 0x56, 0x00000000); /* CCI_NOTCH2_B1 */ - apb_write_reg(2, 0x57, 0x00000000); /* CCI_NOTCH2_B1 */ - apb_write_reg(2, 0x58, 0x00000886); /* MODE_DETECT_CTRL */ - apb_write_reg(2, 0x5c, 0x00001011); /* ICFO_EST_CTRL */ - apb_write_reg(2, 0x5f, 0x00010503); /* TPS_FCFO_CTRL */ - apb_write_reg(2, 0x61, 0x00000003); /* DE_PN_CTRL */ - apb_write_reg(2, 0x61, apb_read_reg(2, 0x61) | (1 << 2)); - /* DE_PN_CTRL SP sync close , Use TPS only ; */ - apb_write_reg(2, 0x68, 0x004060c0); /* CHAN_EST_CTRL0 */ - apb_write_reg(2, 0x68, apb_read_reg(2, 0x68) & ~(1 << 7)); - /* SNR report filter; */ - /*apb_write_reg(2, 0x68, apb_read_reg(2, 0x68) &~(1<<13)); // - * Timing Adjust Shutdown; - */ - apb_write_reg(2, 0x69, 0x148c3812); /* CHAN_EST_CTRL1 */ - /*apb_write_reg(2, 0x69, apb_read_reg(2, 0x69) | (1<<10)); // - * Disable FD data update - */ - /*apb_write_reg(2, 0x69, apb_read_reg(2, 0x69) | (1<<9)); // - * set FD coeff - */ - /*apb_write_reg(2, 0x69, apb_read_reg(2, 0x69) | (1<<8)); // - * set TD coeff - */ - apb_write_reg(2, 0x6a, 0x9101012d); /* CHAN_EST_CTRL2 */ - apb_write_reg(2, 0x6b, 0x00442211); /* CHAN_EST_CTRL2 */ - apb_write_reg(2, 0x6c, 0x01fc040a); /* CHAN_EST_CTRL3 */ - apb_write_reg(2, 0x6d, 0x0030303f); /* SET SNR THRESHOLD */ - apb_write_reg(2, 0x73, 0xffffffff); /* CCI0_PILOT_UPDATE_CTRL */ - apb_write_reg(2, 0x74, 0xffffffff); /* CCI0_DATA_UPDATE_CTRL */ - apb_write_reg(2, 0x75, 0xffffffff); /* CCI1_PILOT_UPDATE_CTRL */ - apb_write_reg(2, 0x76, 0xffffffff); /* CCI1_DATA_UPDATE_CTRL */ - - /* Set ACF and ACFEQ coeffecient */ - switch (sr) { - case 0: - set_ACF_coef(21, bw); - break; - case 1: - set_ACF_coef(21, bw); - break; - case 2: - set_ACF_coef(28, bw); - break; - case 3: - set_ACF_coef(45, bw); - break; - default: - break; - } - - apb_write_reg(2, 0x78, 0x000001a2); - /* FEC_CTRL parallel mode ; [27:24] is TS clk/valid/sync/error */ - apb_write_reg(2, 0x7d, 0x0000009d); - apb_write_reg(2, 0xd6, 0x00000003); - apb_write_reg(2, 0xd7, 0x00000008); - apb_write_reg(2, 0xd8, 0x00000120); - apb_write_reg(2, 0xd9, 0x01010101); - apb_write_reg(2, 0x04, 0x00000000); - /* TPS Current, QPSK, none Hierarchy, HP, LP 1/2 */ - - tmp = (1 << 25) | ((bw & 3) << 20) | (1 << 16) | (1 << 1); - apb_write_reg(2, 0x02, tmp); - apb_write_reg(2, 0x03, (1 << 6)); /* Cordic parameter Calc */ - - udelay(1); - - tmp = apb_read_reg(2, 0x02); - tmp |= (1 << 24) | 1; /* FSM, Demod enable. */ - apb_write_reg(2, 0x02, tmp); -} - -int dvbt_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dvbt *demod_dvbt) -{ - int ret = 0; - u8 bw, sr, ifreq, agc_mode; - u32 ch_freq; - - bw = demod_dvbt->bw; - sr = demod_dvbt->sr; - ifreq = demod_dvbt->ifreq; - agc_mode = demod_dvbt->agc_mode; - ch_freq = demod_dvbt->ch_freq; - - /* Set registers */ - /*//////////////////////////////////// */ - /* bw == 0 : 8M */ - /* 1 : 7M */ - /* 2 : 6M */ - /* 3 : 5M */ - /* sr == 0 : 20.7M */ - /* 1 : 20.8333M */ - /* 2 : 28.5714M */ - /* 3 : 45M */ - /* ifreq == 0: 36.13MHz */ - /* 1: 4.57MHz */ - /* agc_mode == 0: single AGC */ - /* 1: dual AGC */ - /*//////////////////////////////////// */ - if (bw > 3) { - dprintk("Error: Invalid Bandwidth option %d\n", bw); - bw = 0; - ret = -1; - } - - if (sr > 3) { - dprintk("Error: Invalid Sampling Freq option %d\n", sr); - sr = 2; - ret = -1; - } - - if (ifreq > 1) { - dprintk("Error: Invalid IFreq option %d\n", ifreq); - ifreq = 0; - ret = -1; - } - - if (agc_mode > 3) { - dprintk("Error: Invalid AGC mode option %d\n", agc_mode); - agc_mode = 0; - ret = -1; - } - /* if (ret != 0) return ret; */ - - /* Set DVB-T */ - (*DEMOD_REG0) |= 1; - - demod_sta->dvb_mode = 1; - demod_sta->ch_mode = 0; /* TODO */ - demod_sta->agc_mode = agc_mode; - demod_sta->ch_freq = ch_freq; - if (demod_i2c->tuner == 1) - demod_sta->ch_if = 36130; - else if (demod_i2c->tuner == 2) - demod_sta->ch_if = 4570; - - demod_sta->ch_bw = (8 - bw) * 1000; - demod_sta->symb_rate = 0; /* TODO */ - - /* Set Tuner */ - if (ch_freq < 1000 || ch_freq > 900000) { - dprintk - ( - "Error: Invalid Channel Freq option %d, Skip Set tuner\n", - ch_freq); - /*ch_freq = 474000; */ - ret = -1; - } else { - /* tuner_set_ch(demod_sta, demod_i2c); */ - } - - if ((ch_freq % 100) == 2) - dprintk("Input frequency is XXX002, Skip initial demod\n"); - else - dvbt_reg_initial(demod_sta); - - dvbt_enable_irq(7); /* open symbolhead int */ - - tuner_type = demod_i2c->tuner; - - return ret; -} - -static int dvbt_get_ch_power(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - u32 ad_power; - - ad_power = - agc_power_to_dbm((apb_read_reg(2, 0x1c) & 0x7ff), - apb_read_reg(2, 0x1b) & 0x1ff, 0, - demod_i2c->tuner); - return ad_power; -} - -int dvbt_sfo(void) -{ - int sfo; - - sfo = apb_read_reg(2, 0x47) & 0xfff; - sfo = (sfo > 0x7ff) ? (sfo - 0x1000) : sfo; - return sfo; -} - -int dvbt_fcfo(void) -{ - int fcfo; - - fcfo = (apb_read_reg(2, 0x26)) & 0xffffff; - fcfo = (fcfo > 0x7fffff) ? (fcfo - 0x1000000) : fcfo; - return fcfo; -} - -static int dvbt_total_packet_error(void) -{ - return apb_read_reg(2, 0xbf); -} - -static int dvbt_super_frame_counter(void) -{ - return apb_read_reg(2, 0xc0) & 0xfffff; -} - -static int dvbt_packet_correct_in_sframe(void) -{ - return apb_read_reg(2, 0xc1) & 0xfffff; -} - -/*static int dvbt_resync_counter(void) - * {return((apb_read_reg(2, 0xc0)>>20)&0xff);} - */ -static int dvbt_packets_per_sframe(void) -{ - u32 tmp; - int hier_mode; - int constel; - int hp_code_rate; - int lp_code_rate; - int hier_sel; - int code_rate; - int ret; - - tmp = apb_read_reg(2, 0x06); - constel = tmp >> 13 & 3; - hier_mode = tmp >> 10 & 7; - hp_code_rate = tmp >> 7 & 7; - lp_code_rate = tmp >> 4 & 7; - - if (hier_mode == 0) { - code_rate = hp_code_rate; - } else { - tmp = apb_read_reg(2, 0x78); - hier_sel = tmp >> 9 & 1; - if (hier_sel == 0) { - constel = 0; /* QPSK; */ - code_rate = hp_code_rate; - } else { - constel = constel == 2 ? 1 : 0; - code_rate = lp_code_rate; - } - } - - switch (code_rate) { - case 0: - ret = (constel == 0) ? 1008 : (constel == 1) ? 2016 : 3024; - break; - case 1: - ret = (constel == 0) ? 1344 : (constel == 1) ? 2688 : 4032; - break; - case 2: - ret = (constel == 0) ? 1512 : (constel == 1) ? 3024 : 4536; - break; - case 3: - ret = (constel == 0) ? 1680 : (constel == 1) ? 3360 : 5040; - break; - case 4: - ret = (constel == 0) ? 1764 : (constel == 1) ? 3528 : 5292; - break; - default: - ret = (constel == 0) ? 1008 : (constel == 1) ? 2016 : 3024; - break; - } - return ret; -} - -static int dvbt_get_per(void) -{ - int packets_per_sframe; - int error; - int per; - - packets_per_sframe = dvbt_packets_per_sframe(); - error = packets_per_sframe - dvbt_packet_correct_in_sframe(); - per = 1000 * error / packets_per_sframe; - - return per; -} - -static void dvbt_set_test_bus(u8 sel) -{ - u32 tmp; - - tmp = apb_read_reg(2, 0x7f); - tmp &= ~(0x1f); - tmp |= ((1 << 15) | (1 << 5) | (sel & 0x1f)); - apb_write_reg(2, 0x7f, tmp); -} - -/* - * void dvbt_get_test_out(u8 sel, u32 len, u32 *buf) - * { - * int i; - * - * dvbt_set_test_bus(sel); - * - * for (i=0; i> 10) & 0x1) { - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - buf[i++] = apb_read_reg(2, 0x13); - } else { - i--; - } - - cnt++; - } -} - -static int dvbt_get_avg_per(void) -{ - int packets_per_sframe; - static int err_last; - static int err_now; - static int rsnum_now; - static int rsnum_last; - int per; - - packets_per_sframe = dvbt_packets_per_sframe(); - rsnum_last = rsnum_now; - rsnum_now = dvbt_super_frame_counter(); - err_last = err_now; - err_now = dvbt_total_packet_error(); - if (rsnum_now != rsnum_last) - per = 1000 * (err_now - err_last) / - ((rsnum_now - rsnum_last) * packets_per_sframe); - else - per = 123; - - return per; -} - -int dvbt_status(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_sts *demod_sts) -{ - /* if parameters are needed to calc, pass the struct to func. */ - /* all small funcs like read_snr() should be static. */ - - demod_sts->ch_snr = apb_read_reg(2, 0x0a); - demod_sts->ch_per = dvbt_get_per(); - demod_sts->ch_pow = dvbt_get_ch_power(demod_sta, demod_i2c); - demod_sts->ch_ber = apb_read_reg(2, 0x0b); - demod_sts->ch_sts = apb_read_reg(2, 0); - demod_sts->dat0 = dvbt_get_avg_per(); - demod_sts->dat1 = apb_read_reg(2, 0x06); - return 0; -} - -static int dvbt_get_status(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - return apb_read_reg(2, 0x0) >> 12 & 1; -} - -static int dvbt_ber(void); - -static int dvbt_get_ber(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - return dvbt_ber(); /*unit: 1e-7 */ -} - -static int dvbt_get_snr(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - return apb_read_reg(2, 0x0a) & 0x3ff; /*dBm: bit0~bit2=decimal */ -} - -static int dvbt_get_strength(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - int dbm = dvbt_get_ch_power(demod_sta, demod_i2c); - - return dbm; -} - -static int dvbt_get_ucblocks(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c) -{ - return dvbt_get_per(); -} - -struct demod_status_ops *dvbt_get_status_ops(void) -{ - static struct demod_status_ops ops = { - .get_status = dvbt_get_status, - .get_ber = dvbt_get_ber, - .get_snr = dvbt_get_snr, - .get_strength = dvbt_get_strength, - .get_ucblocks = dvbt_get_ucblocks, - }; - - return &ops; -} - -void dvbt_enable_irq(int dvbt_irq) -{ - /* clear status & enable irq */ - (*OFDM_INT_STS) &= ~(1 << dvbt_irq); - (*OFDM_INT_EN) |= (1 << dvbt_irq); -} - -void dvbt_disable_irq(int dvbt_irq) -{ - /* disable irq & clear status */ - (*OFDM_INT_EN) &= ~(1 << dvbt_irq); - (*OFDM_INT_STS) &= ~(1 << dvbt_irq); -} - -char *dvbt_irq_name[] = { - "PFS_FCFO", - "PFS_ICFO", - " CS_FCFO", - " PFS_SFO", - " PFS_TPS", - " SP", - " CCI", - " Symbol", - " In_Sync", - "Out_Sync", - "FSM Stat" -}; - -void dvbt_isr(struct aml_demod_sta *demod_sta) -{ - u32 stat, mask; - int dvbt_irq; - - stat = (*OFDM_INT_STS); - mask = (*OFDM_INT_EN); - stat &= mask; - - for (dvbt_irq = 0; dvbt_irq < 11; dvbt_irq++) { - if (stat >> dvbt_irq & 1) { - if (demod_sta->debug) - dprintk("irq: aml_demod dvbt %2d %s %8x %8x\n", - dvbt_irq, dvbt_irq_name[dvbt_irq], stat, - mask); - /* dvbt_disable_irq(dvbt_irq); */ - } - } - /* clear status */ - (*OFDM_INT_STS) = 0; -} - -static int demod_monitor_ave(void); -int dvbt_isr_islock(void) -{ -#define IN_SYNC_MASK (0x100) - - u32 stat, mask; - - stat = (*OFDM_INT_STS); - *OFDM_INT_STS = stat & (~IN_SYNC_MASK); - - mask = (*OFDM_INT_EN); - stat &= mask; - - return (stat & IN_SYNC_MASK) == IN_SYNC_MASK; -} - -int dvbt_isr_monitor(void) -{ -#define SYM_HEAD_MASK (0x80) - u32 stat, mask; - - stat = (*OFDM_INT_STS); - *OFDM_INT_STS = stat & (~SYM_HEAD_MASK); - - mask = (*OFDM_INT_EN); - stat &= mask; - /* symbol_head int */ - if ((stat & SYM_HEAD_MASK) == SYM_HEAD_MASK) - demod_monitor_ave(); - return 0; -} - -int dvbt_isr_cancel(void) -{ - *OFDM_INT_STS = 0; - *OFDM_INT_EN = 0; - return 0; -} - -static int demod_monitor_instant(void) -{ - int SNR; - int SNR_SP = 500; - int SNR_TPS = 0; - int SNR_CP = 0; - int SFO_residual = 0; - int SFO_esti = 0; - int FCFO_esti = 0; - int FCFO_residual = 0; - int AGC_Gain = 0; - int be_vit_error = 0; - int Signal_power = 0; - int FECFlag = 0; - int EQ_seg_ratio = 0; - int tps_0 = 0; - int tps_1 = 0; - int tps_2 = 0; - int cci_blank = 0; - - int SFO; - int FCFO; - int timing_adj; - int RS_CorrectNum; - int RS_Error_sum; - int resync_times; - int tps_summary; - - int tps_window; - int tps_guard; - int tps_constell; - int tps_Hier_none; - int tps_Hier_alpha; - int tps_HP_cr; - int tps_LP_cr; - - int tmpAGCGain; - - /* Read Registers */ - SNR = apb_read_reg(2, 0x0a); - FECFlag = (apb_read_reg(2, 0x00) >> 11) & 0x3; - SFO = apb_read_reg(2, 0x47) & 0xfff; - SFO_esti = apb_read_reg(2, 0x60) & 0xfff; - FCFO_esti = (apb_read_reg(2, 0x60) >> 11) & 0xfff; - FCFO = (apb_read_reg(2, 0x26)) & 0xffffff; - be_vit_error = apb_read_reg(2, 0x0c) & 0x1fff; - timing_adj = apb_read_reg(2, 0x6f) & 0x1fff; - RS_CorrectNum = apb_read_reg(2, 0xc1) & 0xfffff; - Signal_power = (apb_read_reg(2, 0x1b)) & 0x1ff; - EQ_seg_ratio = apb_read_reg(2, 0x6e) & 0x3ffff; - tps_0 = apb_read_reg(2, 0x64); - tps_1 = apb_read_reg(2, 0x65); - tps_2 = apb_read_reg(2, 0x66) & 0xf; - tps_summary = apb_read_reg(2, 0x04) & 0x7fff; - cci_blank = (apb_read_reg(2, 0x66) >> 16); - RS_Error_sum = apb_read_reg(2, 0xbf) & 0x3ffff; - resync_times = (apb_read_reg(2, 0xc0) >> 20) & 0xff; - AGC_Gain = apb_read_reg(2, 0x1c) & 0x7ff; - - /* Calc */ - SFO_residual = (SFO > 0x7ff) ? (SFO - 0x1000) : SFO; - FCFO_residual = (FCFO > 0x7fffff) ? (FCFO - 0x1000000) : FCFO; - FCFO_esti = (FCFO_esti > 0x7ff) ? (FCFO_esti - 0x1000) : FCFO_esti; - SNR_CP = (SNR) & 0x3ff; - SNR_TPS = (SNR >> 10) & 0x3ff; - SNR_SP = (SNR >> 20) & 0x3ff; - SNR_SP = (SNR_SP > 0x1ff) ? SNR_SP - 0x400 : SNR_SP; - SNR_TPS = (SNR_TPS > 0x1ff) ? SNR_TPS - 0x400 : SNR_TPS; - SNR_CP = (SNR_CP > 0x1ff) ? SNR_CP - 0x400 : SNR_CP; - tmpAGCGain = AGC_Gain; - timing_adj = (timing_adj > 0xfff) ? timing_adj - 0x2000 : timing_adj; - - tps_window = (tps_summary & 0x3); - tps_guard = ((tps_summary >> 2) & 0x3); - tps_constell = ((tps_summary >> 13) & 0x3); - tps_Hier_none = (((tps_summary >> 10) & 0x7) == 0) ? 1 : 0; - tps_Hier_alpha = (tps_summary >> 11) & 0x3; - tps_Hier_alpha = (tps_Hier_alpha == 3) ? 4 : tps_Hier_alpha; - tps_LP_cr = (tps_summary >> 4) & 0x7; - tps_HP_cr = (tps_summary >> 7) & 0x7; - - dprintk("\n\n"); - switch (tps_window) { - case 0: - dprintk("2K "); - break; - case 1: - dprintk("8K "); - break; - case 2: - dprintk("4K "); - break; - default: - dprintk("UnWin "); - break; - } - switch (tps_guard) { - case 0: - dprintk("1/32 "); - break; - case 1: - dprintk("1/16 "); - break; - case 2: - dprintk("1/ 8 "); - break; - case 3: - dprintk("1/ 4 "); - break; - default: - dprintk("UnGuard "); - break; - } - switch (tps_constell) { - case 0: - dprintk(" QPSK "); - break; - case 1: - dprintk("16QAM "); - break; - case 2: - dprintk("64QAM "); - break; - default: - dprintk("UnConstl "); - break; - } - switch (tps_Hier_none) { - case 0: - dprintk("Hiera "); - break; - case 1: - dprintk("non-H "); - break; - default: - dprintk("UnHier "); - break; - } - dprintk("%d ", tps_Hier_alpha); - dprintk("HP "); - switch (tps_HP_cr) { - case 0: - dprintk("1/2 "); - break; - case 1: - dprintk("2/3 "); - break; - case 2: - dprintk("3/4 "); - break; - case 3: - dprintk("5/6 "); - break; - case 4: - dprintk("7/8 "); - break; - default: - dprintk("UnHCr "); - break; - } - dprintk("LP "); - switch (tps_LP_cr) { - case 0: - dprintk("1/2 "); - break; - case 1: - dprintk("2/3 "); - break; - case 2: - dprintk("3/4 "); - break; - case 3: - dprintk("5/6 "); - break; - case 4: - dprintk("7/8 "); - break; - default: - dprintk("UnLCr "); - break; - } - dprintk("\n"); - dprintk("P %4x ", RS_Error_sum); - dprintk("SP %2d ", SNR_SP); - dprintk("TPS %2d ", SNR_TPS); - dprintk("CP %2d ", SNR_CP); - dprintk("EQS %2x ", EQ_seg_ratio); - dprintk("RSC %4d ", RS_CorrectNum); - dprintk("SFO %3d ", SFO_residual); - dprintk("FCFO %4d ", FCFO_residual); - dprintk("Vit %3x ", be_vit_error); - dprintk("Timing %3d ", timing_adj); - dprintk("SigP %3x ", Signal_power); - dprintk("AGC %d ", tmpAGCGain); - dprintk("SigP %d ", - agc_power_to_dbm(tmpAGCGain, Signal_power, 0, tuner_type)); - dprintk("FEC %x ", FECFlag); - dprintk("ReSyn %x ", resync_times); - dprintk("cciB %x", cci_blank); - - dprintk("\n"); - - return 0; -} - -int serial_div(int a, int b) -{ - int c; - int cnt; - int b_buf; - - if (b == 0) - return 0x7fffffff; - if (a == 0) - return 0; - - c = 0; - cnt = 0; - - a = (a < 0) ? -1 * a : a; - b = (b < 0) ? -1 * b : b; - - b_buf = b; - - while (a >= b) { - b = b << 1; - cnt++; - } - while (b > b_buf) { - b = b >> 1; - c = c << 1; - if (a > b) { - c = c + 1; - a = a - b; - } - } - return c; -} - -static int ave0, bit_unit_L; - -static int dvbt_ber(void) -{ - int BER_e_n7 = serial_div(ave0 * 40, bit_unit_L); - - return BER_e_n7; -} - -static int demod_monitor_ave(void) -{ - static int i; - static int ave[3] = { 0, 0, 0 }; - - ave[0] = ave[0] + (apb_read_reg(2, 0x0b) & 0x7ff); - ave[1] = ave[1] + (apb_read_reg(2, 0x0a) & 0x3ff); - ave[2] = ave[2] + (apb_read_reg(2, 0x0c) & 0x1fff); - - i++; - - if (i >= 8192) { - int tps_mode; - int tps_constell; - int r_t; - int mode_L; - int const_L; - int SNR_Int; - int SNR_fra; - - if (debug_amldvbt) - demod_monitor_instant(); - - r_t = apb_read_reg(2, 0x04); - tps_mode = r_t & 0x3; - tps_constell = (r_t >> 13) & 0x3; - mode_L = (tps_mode == 0) ? 1 : (tps_mode == 1) ? 4 : 2; - const_L = (tps_constell == 0) ? 2 : (tps_constell == 1) ? 4 : 6; - bit_unit_L = 189 * mode_L * const_L; - SNR_Int = (ave[1] >> 16); - switch ((ave[1] >> 13) & 0x7) { - case 0: - SNR_fra = 0; - break; - case 1: - SNR_fra = 125; - break; - case 2: - SNR_fra = 250; - break; - case 3: - SNR_fra = 375; - break; - case 4: - SNR_fra = 500; - break; - case 5: - SNR_fra = 625; - break; - case 6: - SNR_fra = 750; - break; - case 7: - SNR_fra = 875; - break; - default: - SNR_fra = 0; - break; - } - - ave0 = ave[0]; - - if (debug_amldvbt) - dprintk("RSBi %d Thresh %d SNR %d.%d Vit %x\n\n", - (ave[0] >> 3) * 5, (bit_unit_L * 8), SNR_Int, - SNR_fra, (ave[2] >> 13)); - i = 0; - ave[0] = ave[1] = ave[2] = 0; - } - - return i; -} - -int dvbt_switch_to_HP(void) -{ - apb_write_reg(2, 0x78, apb_read_reg(2, 0x78) & ~(1 << 9)); - return 0; -} - -int dvbt_switch_to_LP(void) -{ - apb_write_reg(2, 0x78, apb_read_reg(2, 0x78) | (1 << 9)); - return 0; -} - -int dvbt_shutdown(void) -{ - apb_write_reg(2, 0x02, 0x00800000); - /* SW reset bit[23] ; write anything to zero */ - apb_write_reg(2, 0x00, 0x00000000); - return 0; -} - -int dvbt_get_params(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *adap, int *code_rate_HP, - /* high priority stream code rate */ - int *code_rate_LP, /* low priority stream code rate */ - int *constellation, /* modulation type (see above) */ - int *transmission_mode, - int *guard_interval, int *hierarchy_information) -{ - int tps_summary, tps_window, tps_guard, tps_constell, tps_Hier_none; - int tps_Hier_alpha, tps_LP_cr, tps_HP_cr; - - tps_summary = apb_read_reg(2, 0x04) & 0x7fff; - tps_window = (tps_summary & 0x3); - tps_guard = ((tps_summary >> 2) & 0x3); - tps_constell = ((tps_summary >> 13) & 0x3); - tps_Hier_none = (((tps_summary >> 10) & 0x7) == 0) ? 1 : 0; - tps_Hier_alpha = (tps_summary >> 11) & 0x3; - tps_Hier_alpha = (tps_Hier_alpha == 3) ? 4 : tps_Hier_alpha; - tps_LP_cr = (tps_summary >> 4) & 0x7; - tps_HP_cr = (tps_summary >> 7) & 0x7; - if (code_rate_HP) - *code_rate_HP = tps_HP_cr; /*1/2:2/3:3/4:5/6:7/8 */ - if (code_rate_LP) - *code_rate_LP = tps_LP_cr; /*1/2:2/3:3/4:5/6:7/8 */ - if (constellation) - *constellation = tps_constell; /*QPSK/16QAM/64QAM */ - if (transmission_mode) - *transmission_mode = tps_window; /*2K/8K/4K */ - if (guard_interval) - *guard_interval = tps_guard; /*1/32:1/16:1/8:1/4 */ - if (hierarchy_information) - *hierarchy_information = tps_Hier_alpha; /*1/2/4 */ - return 0; -} diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c deleted file mode 100644 index 68b214efc470..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include -#include "demod_func.h" - -int am_demod_i2c_xfer(struct aml_demod_i2c *adap, struct i2c_msg msgs[], - int num) -{ - int ret = 0; - - if (adap->scl_oe) { - /* ret = aml_i2c_sw_bit_xfer(adap, msgs, num);*/ - } else { - if (adap->i2c_priv) - ret = i2c_transfer((struct i2c_adapter *)adap->i2c_priv, - msgs, num); - else - ; - /* printk("i2c error, no valid i2c\n");*/ - } - return ret; -} diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h deleted file mode 100644 index 57448858678d..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h +++ /dev/null @@ -1,414 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -void program_acf(int acf1[20], int acf2[33]) -{ - int i; - - for (i = 0; i < 20; i++) - apb_write_reg(DVBT_BASE + (0x2c + i) * 4, acf1[i]); - for (i = 0; i < 33; i++) { - apb_write_reg(DVBT_BASE + 0xfe * 4, i); - apb_write_reg(DVBT_BASE + 0xff * 4, acf2[i]); - } -} - -void ini_acf_iireq_src_45m_8m(void) -{ - int acf1[] = { 0x294, 0x085, 0x076, 0x01e, - 0x27c, 0x0af, 0x2bf, 0x06d, - 0x265, 0x0d8, 0x270, 0x05e, - 0x257, 0x0ef, 0x25b, 0x04b, - 0x24f, 0x0fc, 0x254, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3da7cd, 0x3c0f9b, 0x3a7768, 0x38df35, - 0x373f01, - 0x3596cd, 0x33ee98, 0x323e62, 0x307e2b, 0x2eb5f3, - 0x2ce5b9, - 0x2b057e, 0x290d41, 0x26fd00, 0x24dcbd, 0x229477, - 0x202c2c, - 0x1d93dc, 0x1ac386, 0x17b328, 0x144ac1, 0x106a4d, - 0x0be1c8, - 0x07e129, 0x04d0cc, 0x015064, 0x3d47ec, 0x38675e, - 0x326eb1, - 0x326e4d, 0x326e4d, 0x00064d - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_45m_7m(void) -{ - int acf1[] = { 0x283, 0x091, 0x02f, 0x01e, - 0x26a, 0x0b8, 0x296, 0x06d, - 0x253, 0x0dc, 0x257, 0x05e, - 0x245, 0x0f1, 0x246, 0x04b, - 0x23d, 0x0fc, 0x241, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3dafce, 0x3c1f9c, 0x3a8769, 0x38ef37, - 0x374f03, - 0x35aecf, 0x34069b, 0x325665, 0x30962e, 0x2ecdf6, - 0x2cfdbc, - 0x2b1581, 0x291d43, 0x271503, 0x24e4bf, 0x229c78, - 0x202c2d, - 0x1d8bdc, 0x1ab384, 0x179325, 0x141abc, 0x102a46, - 0x0b81be, - 0x07711c, 0x0448bd, 0x00b052, 0x3c7fd6, 0x374740, - 0x308684, - 0x308610, 0x308610, 0x000610 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_45m_6m(void) -{ - int acf1[] = { 0x272, 0x09e, 0x3dc, 0x01e, - 0x259, 0x0c0, 0x272, 0x06d, - 0x242, 0x0e1, 0x240, 0x05e, - 0x235, 0x0f3, 0x234, 0x04b, - 0x22e, 0x0fd, 0x230, 0x04d - }; - int acf2[] = { 0x3f47ff, 0x3dbfcf, 0x3c379e, 0x3aa76d, 0x391f3c, - 0x378709, - 0x35e6d6, 0x343ea2, 0x328e6d, 0x30d636, 0x2f0dfe, - 0x2d35c4, - 0x2b4d88, 0x294d49, 0x273d08, 0x2504c4, 0x22b47c, - 0x203c2f, - 0x1d9bde, 0x1ac386, 0x17a327, 0x1432bf, 0x104249, - 0x0ba9c2, - 0x07a922, 0x0490c5, 0x01185c, 0x3d0fe5, 0x383f58, - 0x3286af, - 0x328650, 0x328650, 0x000650 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_45m_5m(void) -{ - int acf1[] = { 0x260, 0x0ab, 0x37e, 0x02e, - 0x249, 0x0ca, 0x251, 0x06d, - 0x233, 0x0e6, 0x22d, 0x05e, - 0x227, 0x0f5, 0x224, 0x04b, - 0x220, 0x0fd, 0x221, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3db7cf, 0x3c279d, 0x3a9f6c, 0x39073a, - 0x377707, - 0x35d6d4, 0x3436a0, 0x328e6b, 0x30d636, 0x2f15ff, - 0x2d4dc6, - 0x2b758c, 0x29854f, 0x278511, 0x256ccf, 0x232c89, - 0x20cc3f, - 0x1e33f0, 0x1b6b9b, 0x185b3d, 0x14e2d5, 0x10f260, - 0x0c51d7, - 0x082934, 0x04f8d4, 0x014066, 0x3ccfe4, 0x372f46, - 0x2f5673, - 0x2f55ea, 0x2f55ea, 0x0005ea - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_2857m_8m(void) -{ - int acf1[] = { 0x2df, 0x059, 0x144, 0x00e, - 0x2d3, 0x08f, 0x38d, 0x06f, - 0x2c6, 0x0c5, 0x302, 0x05e, - 0x2be, 0x0e7, 0x2d6, 0x04b, - 0x2b7, 0x0f9, 0x2c8, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3dbfcf, 0x3c379e, 0x3aaf6d, 0x391f3c, - 0x37870a, - 0x35eed7, 0x344ea3, 0x32a66f, 0x30f639, 0x2f3602, - 0x2d65c9, - 0x2b858e, 0x299552, 0x278d12, 0x2564cf, 0x231c88, - 0x20b43d, - 0x1e13ec, 0x1b3395, 0x181336, 0x1492cc, 0x109254, - 0x0be1cb, - 0x07c127, 0x0498c7, 0x00f85b, 0x3cbfde, 0x377747, - 0x309e88, - 0x309e13, 0x309e13, 0x000613 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_2857m_7m(void) -{ - int acf1[] = { 0x2c6, 0x067, 0x10f, 0x01e, - 0x2b4, 0x099, 0x344, 0x06f, - 0x2a2, 0x0cb, 0x2cb, 0x05e, - 0x297, 0x0ea, 0x2a7, 0x04b, - 0x28f, 0x0fa, 0x29c, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3dbfcf, 0x3c379e, 0x3aa76d, 0x39173b, - 0x378709, - 0x35e6d6, 0x3446a2, 0x329e6d, 0x30e637, 0x2f2600, - 0x2d4dc7, - 0x2b6d8c, 0x297d4e, 0x276d0e, 0x2544cb, 0x22fc84, - 0x208438, - 0x1de3e7, 0x1b0b90, 0x17eb30, 0x146ac7, 0x107250, - 0x0bc9c6, - 0x07b124, 0x0490c5, 0x00f85b, 0x3cc7df, 0x37974a, - 0x30ce8d, - 0x30ce19, 0x30ce19, 0x000619 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_2857m_6m(void) -{ - int acf1[] = { 0x2ac, 0x076, 0x0c9, 0x01e, - 0x297, 0x0a4, 0x2fd, 0x06d, - 0x281, 0x0d2, 0x299, 0x05e, - 0x274, 0x0ed, 0x27d, 0x04b, - 0x26c, 0x0fb, 0x274, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3db7cf, 0x3c279d, 0x3a976b, 0x390739, - 0x376f07, - 0x35ced3, 0x342e9f, 0x327e6a, 0x30c634, 0x2f05fc, - 0x2d35c4, - 0x2b5d89, 0x29654c, 0x275d0c, 0x253cca, 0x22fc83, - 0x209439, - 0x1dfbe9, 0x1b2b93, 0x181b35, 0x14b2ce, 0x10ca5a, - 0x0c41d4, - 0x084935, 0x0538d9, 0x01c071, 0x3db7fa, 0x38bf6b, - 0x327eb9, - 0x327e4f, 0x327e4f, 0x00064f - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_2857m_5m(void) -{ - int acf1[] = { 0x292, 0x087, 0x06e, 0x01e, - 0x27a, 0x0b0, 0x2b9, 0x06d, - 0x262, 0x0d8, 0x26d, 0x05e, - 0x254, 0x0f0, 0x258, 0x04b, - 0x24c, 0x0fc, 0x252, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3db7ce, 0x3c279d, 0x3a976b, 0x38ff38, - 0x376706, - 0x35c6d2, 0x341e9d, 0x326e68, 0x30ae31, 0x2eedf9, - 0x2d15c0, - 0x2b2d84, 0x293546, 0x272506, 0x24fcc2, 0x22ac7b, - 0x203c2f, - 0x1d9bde, 0x1ac386, 0x17a327, 0x1422be, 0x103247, - 0x0b91bf, - 0x07891e, 0x0470c1, 0x00e858, 0x3ccfde, 0x37bf4d, - 0x313e96, - 0x313e27, 0x313e27, 0x000627 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_24m_8m(void) -{ - int acf1[] = { 0x303, 0x048, 0x17e, 0x00e, - 0x302, 0x081, 0x3f8, 0x00a, - 0x300, 0x0bd, 0x35b, 0x05e, - 0x2fe, 0x0e3, 0x325, 0x04b, - 0x2fb, 0x0f8, 0x313, 0x04d - }; - int acf2[] = { 0x3f47ff, 0x3dc7d0, 0x3c3fa0, 0x3abf6f, 0x392f3e, - 0x37a70d, - 0x360eda, 0x346ea7, 0x32c673, 0x31163d, 0x2f5606, - 0x2d8dce, - 0x2bad93, 0x29bd56, 0x27b517, 0x258cd4, 0x23448d, - 0x20cc41, - 0x1e2bf0, 0x1b4b98, 0x182338, 0x149ace, 0x109255, - 0x0bd1ca, - 0x07a123, 0x0468c2, 0x00b054, 0x3c5fd4, 0x37073a, - 0x302e79, - 0x302e05, 0x302e05, 0x000605 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_24m_7m(void) -{ - int acf1[] = { 0x2e7, 0x055, 0x153, 0x00e, - 0x2dd, 0x08b, 0x3a5, 0x06f, - 0x2d2, 0x0c4, 0x315, 0x05e, - 0x2cb, 0x0e6, 0x2e7, 0x04b, - 0x2c5, 0x0f9, 0x2d8, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3dbfcf, 0x3c379e, 0x3aaf6d, 0x391f3c, - 0x37870a, - 0x35eed7, 0x344ea3, 0x32a66f, 0x30ee39, 0x2f2e02, - 0x2d65c9, - 0x2b858e, 0x298d51, 0x278511, 0x255cce, 0x231487, - 0x20a43c, - 0x1e0beb, 0x1b3394, 0x181335, 0x1492cb, 0x109254, - 0x0be1ca, - 0x07b925, 0x0480c5, 0x00d858, 0x3c87d8, 0x373740, - 0x305e80, - 0x305e0b, 0x305e0b, 0x00060b - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_24m_6m(void) -{ - int acf1[] = { 0x2c9, 0x065, 0x118, 0x01e, - 0x2b9, 0x097, 0x34f, 0x06f, - 0x2a7, 0x0ca, 0x2d3, 0x05e, - 0x29c, 0x0e9, 0x2ae, 0x04b, - 0x295, 0x0fa, 0x2a2, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3db7cf, 0x3c2f9d, 0x3a9f6c, 0x390f3a, - 0x377707, - 0x35d6d4, 0x342ea0, 0x32866b, 0x30ce34, 0x2f05fd, - 0x2d35c3, - 0x2b5588, 0x295d4b, 0x27550b, 0x252cc8, 0x22dc80, - 0x206c35, - 0x1dcbe4, 0x1af38c, 0x17cb2d, 0x144ac3, 0x104a4b, - 0x0b99c1, - 0x07791d, 0x0448be, 0x00b052, 0x3c6fd4, 0x37473f, - 0x30c686, - 0x30c618, 0x30c618, 0x000618 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_24m_5m(void) -{ - int acf1[] = { 0x2ab, 0x077, 0x0c6, 0x01e, - 0x295, 0x0a5, 0x2fa, 0x06d, - 0x27f, 0x0d2, 0x297, 0x05e, - 0x272, 0x0ed, 0x27b, 0x04b, - 0x26a, 0x0fb, 0x272, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3db7cf, 0x3c2f9e, 0x3aa76c, 0x39173b, - 0x377f08, - 0x35ded5, 0x343ea1, 0x328e6c, 0x30de36, 0x2f15ff, - 0x2d45c6, - 0x2b658a, 0x29754d, 0x27650d, 0x253cca, 0x22f483, - 0x208438, - 0x1de3e7, 0x1b0b90, 0x17eb30, 0x1472c7, 0x107a51, - 0x0bd9c8, - 0x07c927, 0x04a8c9, 0x01205f, 0x3cf7e4, 0x37e752, - 0x31669a, - 0x31662c, 0x31662c, 0x00062c - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_207m_8m(void) -{ - int acf1[] = { 0x327, 0x039, 0x1a5, 0x07b, - 0x332, 0x076, 0x05c, 0x06e, - 0x33e, 0x0b6, 0x3b8, 0x05e, - 0x344, 0x0e0, 0x37a, 0x04b, - 0x345, 0x0f7, 0x365, 0x04d - }; - int acf2[] = { 0x3f47ff, 0x3dcfd1, 0x3c57a1, 0x3ad772, 0x394f42, - 0x37c711, - 0x3636df, 0x34a6ad, 0x32fe7a, 0x315645, 0x2f9e0f, - 0x2dd5d7, - 0x2bfd9d, 0x2a0d61, 0x280d21, 0x25e4df, 0x239c98, - 0x212c4d, - 0x1e8bfc, 0x1baba4, 0x188344, 0x14fad9, 0x10ea61, - 0x0c29d4, - 0x07e92d, 0x04a8cb, 0x00f05c, 0x3c87da, 0x371f3e, - 0x30267a, - 0x302604, 0x302604, 0x000604 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_207m_7m(void) -{ - int acf1[] = { 0x307, 0x046, 0x182, 0x00e, - 0x306, 0x080, 0x002, 0x00a, - 0x306, 0x0bd, 0x364, 0x05e, - 0x304, 0x0e3, 0x32d, 0x04b, - 0x301, 0x0f8, 0x31b, 0x04d - }; - int acf2[] = { 0x3f47ff, 0x3dc7d0, 0x3c47a0, 0x3abf6f, 0x39373f, - 0x37a70d, - 0x3616db, 0x3476a8, 0x32d674, 0x31263f, 0x2f6608, - 0x2d9dd0, - 0x2bbd96, 0x29d559, 0x27cd19, 0x25a4d7, 0x235c90, - 0x20ec45, - 0x1e53f4, 0x1b739d, 0x18533d, 0x14d2d4, 0x10d25c, - 0x0c19d1, - 0x07e12c, 0x04a8ca, 0x00f05c, 0x3c8fdb, 0x372740, - 0x302e7c, - 0x302e05, 0x302e05, 0x000605 - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_207m_6m(void) -{ - int acf1[] = { 0x2e6, 0x056, 0x151, 0x00e, - 0x2db, 0x08c, 0x3a1, 0x06f, - 0x2d0, 0x0c4, 0x312, 0x05e, - 0x2c9, 0x0e6, 0x2e4, 0x04b, - 0x2c3, 0x0f9, 0x2d6, 0x04d - }; - int acf2[] = { 0x3f47ff, 0x3dbfd0, 0x3c3f9f, 0x3ab76e, 0x39273d, - 0x37970b, - 0x35fed9, 0x345ea5, 0x32b671, 0x31063b, 0x2f4604, - 0x2d75cb, - 0x2b9590, 0x29a553, 0x279513, 0x256cd0, 0x232489, - 0x20b43d, - 0x1e0bec, 0x1b3395, 0x180b35, 0x148acb, 0x108253, - 0x0bd1c8, - 0x07a123, 0x0470c2, 0x00c055, 0x3c77d6, 0x372f3e, - 0x306e80, - 0x306e0d, 0x306e0d, 0x00060d - }; - - program_acf(acf1, acf2); -} - -void ini_acf_iireq_src_207m_5m(void) -{ - int acf1[] = { 0x2c3, 0x068, 0x109, 0x01e, - 0x2b1, 0x09a, 0x33d, 0x06f, - 0x29f, 0x0cc, 0x2c6, 0x05e, - 0x293, 0x0ea, 0x2a3, 0x04b, - 0x28c, 0x0fa, 0x298, 0x04d - }; - int acf2[] = { 0x3f3fff, 0x3db7ce, 0x3c279d, 0x3a976b, 0x38ff38, - 0x376706, - 0x35c6d2, 0x341e9e, 0x327669, 0x30be32, 0x2ef5fb, - 0x2d25c1, - 0x2b4586, 0x295549, 0x274509, 0x251cc6, 0x22dc80, - 0x206c34, - 0x1dcbe4, 0x1afb8d, 0x17db2e, 0x1462c5, 0x106a4f, - 0x0bc9c6, - 0x07b124, 0x0488c5, 0x00e859, 0x3cafdc, 0x377f47, - 0x30ee8c, - 0x30ee1d, 0x30ee1d, 0x00061d - }; - - program_acf(acf1, acf2); -} diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h deleted file mode 100644 index 4b231320adbf..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_CHE_H__ -#define __ADDR_DTMB_CHE_H__ - -#include "addr_dtmb_top.h" - -#define DTMB_CHE_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) - -#define DTMB_CHE_TE_HREB_SNR DTMB_CHE_ADDR(0x8d) -#define DTMB_CHE_MC_SC_TIMING_POWTHR DTMB_CHE_ADDR(0x8e) -#define DTMB_CHE_MC_SC_PROTECT_GD DTMB_CHE_ADDR(0x8f) -#define DTMB_CHE_TIMING_LIMIT DTMB_CHE_ADDR(0x90) -#define DTMB_CHE_TPS_CONFIG DTMB_CHE_ADDR(0x91) -#define DTMB_CHE_FD_TD_STEPSIZE DTMB_CHE_ADDR(0x92) -#define DTMB_CHE_QSTEP_SET DTMB_CHE_ADDR(0x93) -#define DTMB_CHE_SEG_CONFIG DTMB_CHE_ADDR(0x94) -#define DTMB_CHE_FD_TD_LEAKSIZE_CONFIG1 DTMB_CHE_ADDR(0x95) -#define DTMB_CHE_FD_TD_LEAKSIZE_CONFIG2 DTMB_CHE_ADDR(0x96) -#define DTMB_CHE_FD_TD_COEFF DTMB_CHE_ADDR(0x97) -#define DTMB_CHE_M_CCI_THR_CONFIG1 DTMB_CHE_ADDR(0x98) -#define DTMB_CHE_M_CCI_THR_CONFIG2 DTMB_CHE_ADDR(0x99) -#define DTMB_CHE_M_CCI_THR_CONFIG3 DTMB_CHE_ADDR(0x9a) -#define DTMB_CHE_CCIDET_CONFIG DTMB_CHE_ADDR(0x9b) -#define DTMB_CHE_IBDFE_CONFIG1 DTMB_CHE_ADDR(0x9d) -#define DTMB_CHE_IBDFE_CONFIG2 DTMB_CHE_ADDR(0x9e) -#define DTMB_CHE_IBDFE_CONFIG3 DTMB_CHE_ADDR(0x9f) -#define DTMB_CHE_TD_COEFF DTMB_CHE_ADDR(0xa0) -#define DTMB_CHE_FD_TD_STEPSIZE_ADJ DTMB_CHE_ADDR(0xa1) -#define DTMB_CHE_FD_COEFF_FRZ DTMB_CHE_ADDR(0xa2) -#define DTMB_CHE_FD_COEFF DTMB_CHE_ADDR(0xa3) -#define DTMB_CHE_FD_LEAKSIZE DTMB_CHE_ADDR(0xa4) -#define DTMB_CHE_IBDFE_CONFIG4 DTMB_CHE_ADDR(0xa5) -#define DTMB_CHE_IBDFE_CONFIG5 DTMB_CHE_ADDR(0xa6) -#define DTMB_CHE_IBDFE_CONFIG6 DTMB_CHE_ADDR(0xa7) -#define DTMB_CHE_IBDFE_CONFIG7 DTMB_CHE_ADDR(0xa8) -#define DTMB_CHE_DCM_SC_MC_GD_LEN DTMB_CHE_ADDR(0xa9) -#define DTMB_CHE_EQMC_PICK_THR DTMB_CHE_ADDR(0xaa) -#define DTMB_CHE_EQMC_THRESHOLD DTMB_CHE_ADDR(0xab) -#define DTMB_CHE_EQSC_PICK_THR DTMB_CHE_ADDR(0xad) -#define DTMB_CHE_EQSC_THRESHOLD DTMB_CHE_ADDR(0xae) -#define DTMB_CHE_PROTECT_GD_TPS DTMB_CHE_ADDR(0xaf) -#define DTMB_CHE_FD_TD_STEPSIZE_THR1 DTMB_CHE_ADDR(0xb0) -#define DTMB_CHE_TDFD_SWITCH_SYM1 DTMB_CHE_ADDR(0xb1) -#define DTMB_CHE_TDFD_SWITCH_SYM2 DTMB_CHE_ADDR(0xb2) -#define DTMB_CHE_EQ_CONFIG DTMB_CHE_ADDR(0xb3) -#define DTMB_CHE_EQSC_SNR_IMP_THR1 DTMB_CHE_ADDR(0xb4) -#define DTMB_CHE_EQSC_SNR_IMP_THR2 DTMB_CHE_ADDR(0xb5) -#define DTMB_CHE_EQMC_SNR_IMP_THR1 DTMB_CHE_ADDR(0xb6) -#define DTMB_CHE_EQMC_SNR_IMP_THR2 DTMB_CHE_ADDR(0xb7) -#define DTMB_CHE_EQSC_SNR_DROP_THR DTMB_CHE_ADDR(0xb8) -#define DTMB_CHE_EQMC_SNR_DROP_THR DTMB_CHE_ADDR(0xb9) -#define DTMB_CHE_M_CCI_THR DTMB_CHE_ADDR(0xba) -#define DTMB_CHE_TPS_MC DTMB_CHE_ADDR(0xbb) -#define DTMB_CHE_TPS_SC DTMB_CHE_ADDR(0xbc) -#define DTMB_CHE_CHE_SET_FSM DTMB_CHE_ADDR(0xbd) -#define DTMB_CHE_ZERO_NUM_THR DTMB_CHE_ADDR(0xbe) -#define DTMB_CHE_TIMING_READY DTMB_CHE_ADDR(0xbf) - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h deleted file mode 100644 index d81c47795d20..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h +++ /dev/null @@ -1,266 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_CHE_BIT_H__ -#define __ADDR_DTMB_CHE_BIT_H__ - -struct DTMB_CHE_TE_HREB_SNR_BITS { - unsigned int te_hreb_snr:21, reserved0:11; -}; -struct DTMB_CHE_MC_SC_TIMING_POWTHR_BITS { - unsigned int mc_timing_powthr1:5, - reserved1:3, - mc_timing_powthr0:5, - reserved2:2, - sc_timing_powthr1:5, reserved3:4, sc_timing_powthr0:5, reserved4:3; -}; -struct DTMB_CHE_MC_SC_PROTECT_GD_BITS { - unsigned int h_valid:2, - reserved5:2, - dist:3, - reserved6:1, - ma_size:3, - reserved7:1, - mc_protect_gd:5, reserved8:3, sc_protect_gd:5, reserved9:7; -}; -struct DTMB_CHE_TIMING_LIMIT_BITS { - unsigned int ncoh_thd:3, - reserved10:1, - coh_thd:3, - reserved11:1, - strong_loc_thd:8, reserved12:4, timing_limit:5, reserved13:7; -}; -struct DTMB_CHE_TPS_CONFIG_BITS { - unsigned int tps_pst_num:5, - reserved14:3, - tps_pre_num:5, reserved15:3, chi_power_thr:8, reserved16:8; -}; -struct DTMB_CHE_FD_TD_STEPSIZE_BITS { - unsigned int fd_stepsize_thr03:5, - fd_stepsize_thr02:5, - fd_stepsize_thr01:5, - td_stepsize_thr03:5, - td_stepsize_thr02:5, td_stepsize_thr01:5, reserved17:2; -}; -struct DTMB_CHE_QSTEP_SET_BITS { - unsigned int factor_stable_thres:10, - reserved18:2, qstep_set:13, qstep_set_val:1, reserved19:6; -}; -struct DTMB_CHE_SEG_CONFIG_BITS { - unsigned int seg_bypass:1, - seg_num_1seg_log2:3, - seg_alpha:3, - seg_read_val:1, seg_read_addr:12, noise_input_shift:4, reserved20:8; -}; -struct DTMB_CHE_FD_TD_LEAKSIZE_CONFIG1_BITS { - unsigned int fd_leaksize_thr03:5, - fd_leaksize_thr02:5, - fd_leaksize_thr01:5, - td_leaksize_thr03:5, - td_leaksize_thr02:5, td_leaksize_thr01:5, reserved21:2; -}; -struct DTMB_CHE_FD_TD_LEAKSIZE_CONFIG2_BITS { - unsigned int fd_leaksize_thr13:5, - fd_leaksize_thr12:5, - fd_leaksize_thr11:5, - td_leaksize_thr13:5, - td_leaksize_thr12:5, td_leaksize_thr11:5, reserved22:2; -}; -struct DTMB_CHE_FD_TD_COEFF_BITS { - unsigned int td_coeff_frz:14, - reserved23:2, - td_coeff_addr:4, - td_coeff_init:1, - td_coeff_rst:1, - fd_coeff_init:1, - fd_coeff_done:1, - fd_coeff_rst:1, td_coeff_done:1, fd_coeff_addr:5, reserved24:1; -}; -struct DTMB_CHE_M_CCI_THR_CONFIG1_BITS { - unsigned int m_cci_thr_mc1:10, - m_cci_thr_mc2:10, m_cci_thr_mc3:10, reserved25:2; -}; -struct DTMB_CHE_M_CCI_THR_CONFIG2_BITS { - unsigned int m_cci_thr_sc2:10, - m_cci_thr_sc3:10, m_cci_thr_mc0:10, reserved26:2; -}; -struct DTMB_CHE_M_CCI_THR_CONFIG3_BITS { - unsigned int m_cci_thr_ma:10, - m_cci_thr_sc0:10, m_cci_thr_sc1:10, reserved27:2; -}; -struct DTMB_CHE_CCIDET_CONFIG_BITS { - unsigned int ccidet_dly:7, - ccidet_malpha:3, - ccidet_sc_mask_rng:5, - ccidet_mc_mask_rng:5, - ccidet_masize:4, - ccidect_sat_sft:3, - ccicnt_out_sel:2, tune_mask:1, m_cci_bypass:1, reserved28:1; -}; -struct DTMB_CHE_IBDFE_CONFIG1_BITS { - unsigned int ibdfe_cci_just_thr:13, - reserved29:3, - ibdfe_dmsg_point:5, reserved30:3, ibdfe_dmsg_alp:3, reserved31:5; -}; -struct DTMB_CHE_IBDFE_CONFIG2_BITS { - unsigned int ibdfe_rou_rat_1:10, - reserved32:6, ibdfe_rou_rat_0:10, reserved33:6; -}; -struct DTMB_CHE_IBDFE_CONFIG3_BITS { - unsigned int ibdfe_rou_rat_3:10, - reserved34:6, ibdfe_rou_rat_2:10, reserved35:6; -}; -struct DTMB_CHE_TD_COEFF_BITS { - unsigned int td_coeff:24, reserved36:8; -}; -struct DTMB_CHE_FD_TD_STEPSIZE_ADJ_BITS { - unsigned int fd_stepsize_adj:3, td_stepsize_adj:3, reserved37:26; -}; -struct DTMB_CHE_FD_COEFF_BITS { - unsigned int fd_coeff:24, reserved38:8; -}; -struct DTMB_CHE_FD_LEAKSIZE_BITS { - unsigned int fd_leaksize:18, reserved39:14; -}; -struct DTMB_CHE_IBDFE_CONFIG4_BITS { - unsigned int ibdfe_fdbk_iter:4, - ibdfe_eqout_iter:4, - eq_dist_thr_tps:4, - eq_soft_slicer_en:1, - reserved40:3, - gd_len:5, ibdfe_blank_y:1, reserved41:1, ibdfe_dmsg_start_cnt:9; -}; -struct DTMB_CHE_IBDFE_CONFIG5_BITS { - unsigned int ibdfe_init_snr:12, - reserved42:4, eq_init_snr:12, reserved43:4; -}; -struct DTMB_CHE_IBDFE_CONFIG6_BITS { - unsigned int ibdfe_const_thr3:4, - ibdfe_const_thr2:4, - ibdfe_const_thr1:4, - ibdfe_const_thr0:4, - ibdfe_threshold3:4, - ibdfe_threshold2:4, ibdfe_threshold1:4, ibdfe_threshold0:4; -}; -struct DTMB_CHE_IBDFE_CONFIG7_BITS { - unsigned int ibdfe_pick_thr3:8, - ibdfe_pick_thr2:8, ibdfe_pick_thr1:8, ibdfe_pick_thr0:8; -}; -struct DTMB_CHE_DCM_SC_MC_GD_LEN_BITS { - unsigned int dcm_mc_gd_len:6, - reserved44:2, dcm_sc_gd_len:6, reserved45:2, eq_dsnr_slc2drm:16; -}; -struct DTMB_CHE_EQMC_PICK_THR_BITS { - unsigned int eqmc_pick_thr3:8, - eqmc_pick_thr2:8, eqmc_pick_thr1:8, eqmc_pick_thr0:8; -}; -struct DTMB_CHE_EQMC_THRESHOLD_BITS { - unsigned int eqmc_const_thr3:4, - eqmc_const_thr2:4, - eqmc_const_thr1:4, - eqmc_const_thr0:4, - eqmc_threshold3:4, - eqmc_threshold2:4, eqmc_threshold1:4, eqmc_threshold0:4; -}; -struct DTMB_CHE_EQSC_PICK_THR_BITS { - unsigned int eqsc_pick_thr3:8, - eqsc_pick_thr2:8, eqsc_pick_thr1:8, eqsc_pick_thr0:8; -}; -struct DTMB_CHE_EQSC_THRESHOLD_BITS { - unsigned int eqsc_const_thr3:4, - eqsc_const_thr2:4, - eqsc_const_thr1:4, - eqsc_const_thr0:4, - eqsc_threshold3:4, - eqsc_threshold2:4, eqsc_threshold1:4, eqsc_threshold0:4; -}; -struct DTMB_CHE_PROTECT_GD_TPS_BITS { - unsigned int pow_norm:10, - ncoh_thd_tps:3, - coh_thd_tps:3, thr_max:10, protect_gd_tps:5, reserved46:1; -}; -struct DTMB_CHE_FD_TD_STEPSIZE_THR1_BITS { - unsigned int fd_stepsize_thr13:5, - fd_stepsize_thr12:5, - fd_stepsize_thr11:5, - td_stepsize_thr13:5, - td_stepsize_thr12:5, td_stepsize_thr11:5, reserved47:2; -}; -struct DTMB_CHE_TDFD_SWITCH_SYM1_BITS { - unsigned int tdfd_switch_sym00:16, tdfd_switch_sym01:16; -}; -struct DTMB_CHE_TDFD_SWITCH_SYM2_BITS { - unsigned int tdfd_switch_sym10:16, tdfd_switch_sym11:16; -}; -struct DTMB_CHE_EQ_CONFIG_BITS { - unsigned int eq_dsnr_h2drm:6, - eq_cmp_en:1, - eq_imp_setzero_en:1, - dcm_sc_bypass:1, - dcm_mc_bypass:1, - dcm_sc_h_limit:4, - dcm_mc_h_limit:4, - eqsnr_imp_alp:3, eqsnr_avg_alp:3, dcm_alpha:2, reserved48:6; -}; -struct DTMB_CHE_EQSC_SNR_IMP_THR1_BITS { - unsigned int eqsc_snr_imp_thr1:12, eqsc_snr_imp_thr0:12, reserved49:8; -}; -struct DTMB_CHE_EQSC_SNR_IMP_THR2_BITS { - unsigned int eqsc_snr_imp_thr3:12, eqsc_snr_imp_thr2:12, reserved50:8; -}; -struct DTMB_CHE_EQMC_SNR_IMP_THR1_BITS { - unsigned int eqmc_snr_imp_thr1:12, eqmc_snr_imp_thr0:12, reserved51:8; -}; -struct DTMB_CHE_EQMC_SNR_IMP_THR2_BITS { - unsigned int eqmc_snr_imp_thr3:12, eqmc_snr_imp_thr2:12, reserved52:8; -}; -struct DTMB_CHE_EQSC_SNR_DROP_THR_BITS { - unsigned int eqsc_snr_drop_thr3:8, - eqsc_snr_drop_thr2:8, eqsc_snr_drop_thr1:8, eqsc_snr_drop_thr0:8; -}; -struct DTMB_CHE_EQMC_SNR_DROP_THR_BITS { - unsigned int eqmc_snr_drop_thr3:8, - eqmc_snr_drop_thr2:8, eqmc_snr_drop_thr1:8, eqmc_snr_drop_thr0:8; -}; -struct DTMB_CHE_M_CCI_THR_BITS { - unsigned int ccidet_mask_rng_tps:5, - m_cci_thr_tps:10, m_cci_thr_ma_tps:10, reserved53:7; -}; -struct DTMB_CHE_TPS_MC_BITS { - unsigned int tps_mc_run_tim_limit:10, - tps_mc_suc_limit:7, tps_mc_q_thr:7, tps_mc_alpha:3, reserved54:5; -}; -struct DTMB_CHE_TPS_SC_BITS { - unsigned int tps_sc_run_tim_limit:10, - tps_sc_suc_limit:7, tps_sc_q_thr:7, tps_sc_alpha:3, reserved55:5; -}; -struct DTMB_CHE_CHE_SET_FSM_BITS { - unsigned int che_open_loop_len:12, - reserved56:4, - che_set_fsm_st:3, reserved57:1, che_set_fsm_en:1, reserved58:11; -}; -struct DTMB_CHE_ZERO_NUM_THR_BITS { - unsigned int null_frame_thr:16, zero_num_thr:12, reserved59:4; -}; -struct DTMB_CHE_TIMING_READY_BITS { - unsigned int timing_offset:11, - reserved60:5, timing_ready:1, reserved61:15; -}; - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h deleted file mode 100644 index bf2f524e1caf..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_FRONT_H__ -#define __ADDR_DTMB_FRONT_H__ - -#include "addr_dtmb_top.h" - -#define DTMB_FRONT_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) - -#define DTMB_FRONT_AFIFO_ADC DTMB_FRONT_ADDR(0x20) -#define DTMB_FRONT_AGC_CONFIG1 DTMB_FRONT_ADDR(0x21) -#define DTMB_FRONT_AGC_CONFIG2 DTMB_FRONT_ADDR(0x22) -#define DTMB_FRONT_AGC_CONFIG3 DTMB_FRONT_ADDR(0x23) -#define DTMB_FRONT_AGC_CONFIG4 DTMB_FRONT_ADDR(0x24) -#define DTMB_FRONT_DDC_BYPASS DTMB_FRONT_ADDR(0x25) -#define DTMB_FRONT_DC_HOLD DTMB_FRONT_ADDR(0x28) -#define DTMB_FRONT_DAGC_TARGET_POWER DTMB_FRONT_ADDR(0x29) -#define DTMB_FRONT_ACF_BYPASS DTMB_FRONT_ADDR(0x2a) -#define DTMB_FRONT_COEF_SET1 DTMB_FRONT_ADDR(0x2b) -#define DTMB_FRONT_COEF_SET2 DTMB_FRONT_ADDR(0x2c) -#define DTMB_FRONT_COEF_SET3 DTMB_FRONT_ADDR(0x2d) -#define DTMB_FRONT_COEF_SET4 DTMB_FRONT_ADDR(0x2e) -#define DTMB_FRONT_COEF_SET5 DTMB_FRONT_ADDR(0x2f) -#define DTMB_FRONT_COEF_SET6 DTMB_FRONT_ADDR(0x30) -#define DTMB_FRONT_COEF_SET7 DTMB_FRONT_ADDR(0x31) -#define DTMB_FRONT_COEF_SET8 DTMB_FRONT_ADDR(0x32) -#define DTMB_FRONT_COEF_SET9 DTMB_FRONT_ADDR(0x33) -#define DTMB_FRONT_COEF_SET10 DTMB_FRONT_ADDR(0x34) -#define DTMB_FRONT_COEF_SET11 DTMB_FRONT_ADDR(0x35) -#define DTMB_FRONT_COEF_SET12 DTMB_FRONT_ADDR(0x36) -#define DTMB_FRONT_COEF_SET13 DTMB_FRONT_ADDR(0x37) -#define DTMB_FRONT_COEF_SET14 DTMB_FRONT_ADDR(0x38) -#define DTMB_FRONT_COEF_SET15 DTMB_FRONT_ADDR(0x39) -#define DTMB_FRONT_COEF_SET16 DTMB_FRONT_ADDR(0x3a) -#define DTMB_FRONT_COEF_SET17 DTMB_FRONT_ADDR(0x3b) -#define DTMB_FRONT_COEF_SET18 DTMB_FRONT_ADDR(0x3c) -#define DTMB_FRONT_COEF_SET19 DTMB_FRONT_ADDR(0x3d) -#define DTMB_FRONT_SRC_CONFIG1 DTMB_FRONT_ADDR(0x3e) -#define DTMB_FRONT_SRC_CONFIG2 DTMB_FRONT_ADDR(0x3f) -#define DTMB_FRONT_SFIFO_OUT_LEN DTMB_FRONT_ADDR(0x40) -#define DTMB_FRONT_DAGC_GAIN DTMB_FRONT_ADDR(0x41) -#define DTMB_FRONT_IQIB_STEP DTMB_FRONT_ADDR(0x42) -#define DTMB_FRONT_IQIB_CONFIG DTMB_FRONT_ADDR(0x43) -#define DTMB_FRONT_ST_CONFIG DTMB_FRONT_ADDR(0x44) -#define DTMB_FRONT_ST_FREQ DTMB_FRONT_ADDR(0x45) -#define DTMB_FRONT_46_CONFIG DTMB_FRONT_ADDR(0x46) -#define DTMB_FRONT_47_CONFIG DTMB_FRONT_ADDR(0x47) -#define DTMB_FRONT_DEBUG_CFG DTMB_FRONT_ADDR(0x48) -#define DTMB_FRONT_MEM_ADDR DTMB_FRONT_ADDR(0x49) -#define DTMB_FRONT_19_CONFIG DTMB_FRONT_ADDR(0x19) -#define DTMB_FRONT_4d_CONFIG DTMB_FRONT_ADDR(0x4d) - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h deleted file mode 100644 index ec74d2353f27..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h +++ /dev/null @@ -1,331 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_FRONT_BIT_H__ -#define __ADDR_DTMB_FRONT_BIT_H__ - -union DTMB_FRONT_AFIFO_ADC_BITS { - unsigned int d32; - struct { - unsigned int afifo_nco_rate:8, - afifo_data_format:1, - afifo_bypass:1, - adc_sample:6, - adc_IQ:1, - reserved0:15; - } b; -}; -struct DTMB_FRONT_AGC_CONFIG1_BITS { - unsigned int agc_target:4, - agc_cal_intv:2, - reserved1:2, - agc_gain_step2:6, - reserved2:2, - agc_gain_step1:6, - reserved3:2, - agc_a_filter_coef2:3, - reserved4:1, - agc_a_filter_coef1:3, - reserved5:1; -}; -struct DTMB_FRONT_AGC_CONFIG2_BITS { - unsigned int agc_imp_thresh:4, - agc_imp_en:1, - agc_iq_exchange:1, - reserved6:2, - agc_clip_ratio:5, - reserved7:3, - agc_signal_clip_thr:6, - reserved8:2, - agc_sd_rate:7, - reserved9:1; -}; -struct DTMB_FRONT_AGC_CONFIG3_BITS { - unsigned int agc_rffb_value:11, - reserved10:1, - agc_iffb_value:11, - reserved11:1, - agc_gain_step_rf:1, - agc_rfgain_freeze:1, - agc_tuning_slope:1, - agc_rffb_set:1, - agc_gain_step_if:1, - agc_ifgain_freeze:1, - agc_if_only:1, - agc_iffb_set:1; -}; -struct DTMB_FRONT_AGC_CONFIG4_BITS { - unsigned int agc_rffb_gain_sat_i:8, - agc_rffb_gain_sat:8, - agc_iffb_gain_sat_i:8, - agc_iffb_gain_sat:8; -}; -struct DTMB_FRONT_DDC_BYPASS_BITS { - unsigned int ddc_phase:25, - reserved12:3, - ddc_bypass:1, - reserved13:3; -}; -struct DTMB_FRONT_DC_HOLD_BITS { - unsigned int dc_hold:1, - dc_alpha:3, - mobi_det_accu_len:3, - reserved14:1, - mobi_det_observe_len:3, - reserved15:1, - channel_static_th:4, - channel_portable_th:4, - dc_bypass:1, - reserved16:3, - dc_len:3, - reserved17:5; -}; -struct DTMB_FRONT_DAGC_TARGET_POWER_BITS { - unsigned int dagc_target_power_l:8, - dagc_target_power_h:8, - dagc_target_power_ler:8, - dagc_target_power_her:8; -}; -struct DTMB_FRONT_ACF_BYPASS_BITS { - unsigned int coef65:11, - reserved18:1, - coef66:11, - reserved19:1, - acf_bypass:1, - reserved20:7; -}; -struct DTMB_FRONT_COEF_SET1_BITS { - unsigned int coef63:11, - reserved21:1, - coef64:11, - reserved22:9; -}; -struct DTMB_FRONT_COEF_SET2_BITS { - unsigned int coef62:10, - reserved23:22; -}; -struct DTMB_FRONT_COEF_SET3_BITS { - unsigned int coef60:10, - reserved24:2, - coef61:10, - reserved25:10; -}; -struct DTMB_FRONT_COEF_SET4_BITS { - unsigned int coef59:9, - reserved26:23; -}; -struct DTMB_FRONT_COEF_SET5_BITS { - unsigned int coef57:9, - reserved27:3, - coef58:9, - reserved28:11; -}; -struct DTMB_FRONT_COEF_SET6_BITS { - unsigned int coef54:8, - coef55:8, - coef56:8, - reserved29:8; -}; -struct DTMB_FRONT_COEF_SET7_BITS { - unsigned int coef53:7, - reserved30:25; -}; -struct DTMB_FRONT_COEF_SET8_BITS { - unsigned int coef49:7, - reserved31:1, - coef50:7, - reserved32:1, - coef51:7, - reserved33:1, - coef52:7, - reserved34:1; -}; -struct DTMB_FRONT_COEF_SET9_BITS { - unsigned int coef45:7, - reserved35:1, - coef46:7, - reserved36:1, - coef47:7, - reserved37:1, - coef48:7, - reserved38:1; -}; -struct DTMB_FRONT_COEF_SET10_BITS { - unsigned int coef42:6, - reserved39:2, - coef43:6, - reserved40:2, - coef44:6, - reserved41:10; -}; -struct DTMB_FRONT_COEF_SET11_BITS { - unsigned int coef38:6, - reserved42:2, - coef39:6, - reserved43:2, - coef40:6, - reserved44:2, - coef41:6, - reserved45:2; -}; -struct DTMB_FRONT_COEF_SET12_BITS { - unsigned int coef34:6, - reserved46:2, - coef35:6, - reserved47:2, - coef36:6, - reserved48:2, - coef37:6, - reserved49:2; -}; -struct DTMB_FRONT_COEF_SET13_BITS { - unsigned int coef30:6, - reserved50:2, - coef31:6, - reserved51:2, - coef32:6, - reserved52:2, - coef33:6, - reserved53:2; -}; -struct DTMB_FRONT_COEF_SET14_BITS { - unsigned int coef27:5, - reserved54:3, - coef28:5, - reserved55:3, - coef29:5, - reserved56:11; -}; -struct DTMB_FRONT_COEF_SET15_BITS { - unsigned int coef23:5, - reserved57:3, - coef24:5, - reserved58:3, - coef25:5, - reserved59:3, - coef26:5, - reserved60:3; -}; -struct DTMB_FRONT_COEF_SET16_BITS { - unsigned int coef19:5, - reserved61:3, - coef20:5, - reserved62:3, - coef21:5, - reserved63:3, - coef22:5, - reserved64:3; -}; -struct DTMB_FRONT_COEF_SET17_BITS { - unsigned int coef15:5, - reserved65:3, - coef16:5, - reserved66:3, - coef17:5, - reserved67:3, - coef18:5, - reserved68:3; -}; -struct DTMB_FRONT_COEF_SET18_BITS { - unsigned int coef08:4, - coef09:4, - coef10:4, - coef11:4, - coef12:4, - coef13:4, - coef14:4, - reserved69:4; -}; -struct DTMB_FRONT_COEF_SET19_BITS { - unsigned int coef00:4, - coef01:4, - coef02:4, - coef03:4, - coef04:4, - coef05:4, - coef06:4, - coef07:4; -}; -struct DTMB_FRONT_SRC_CONFIG1_BITS { - unsigned int src_norm_inrate:24, - src_tim_shr:4, - src_ted_disable:1, - reserved70:3; -}; -struct DTMB_FRONT_SRC_CONFIG2_BITS { - unsigned int src_stable_timeout:4, - src_seg_len:3, - reserved71:1, - src_ted_beta:3, - reserved72:1, - src_time_err_thr:4, - src_time_mu1:5, - reserved73:3, - src_time_mu2:5, - reserved74:3; -}; -struct DTMB_FRONT_SFIFO_OUT_LEN_BITS { - unsigned int sfifo_out_len:4, - reserved75:28; -}; -struct DTMB_FRONT_DAGC_GAIN_BITS { - unsigned int dagc_bypass:1, - dagc_power_alpha:2, - dagc_bw:3, - dagc_gain_ctrl:12, - dagc_gain_step_er:6, - dagc_gain_step:6, - reserved76:2; -}; -struct DTMB_FRONT_IQIB_STEP_BITS { - unsigned int iqib_step_b:2, - iqib_step_a:2, - iqib_period:3, - reserved77:1, - iqib_bypass:1, - reserved78:23; -}; -struct DTMB_FRONT_IQIB_CONFIG_BITS { - unsigned int iqib_set_b:12, - iqib_set_a:10, - reserved79:2, - iqib_set_val:1, - iqib_hold:1, - reserved80:6; -}; -struct DTMB_FRONT_ST_CONFIG_BITS { - unsigned int st_enable:1, - reserved81:3, - st_dc_len:3, - reserved82:1, - st_alpha:3, - reserved83:1, - st_Q_thrsh:8, - st_dist:3, - reserved84:1, - st_len:5, - reserved85:3; -}; -struct DTMB_FRONT_ST_FREQ_BITS { - unsigned int st_freq_v:1, - st_freq_i:19, - reserved86:12; -}; - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h deleted file mode 100644 index 0607b19b4e23..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_SYNC_H__ -#define __ADDR_DTMB_SYNC_H__ - -#include "addr_dtmb_top.h" -#define DTMB_SYNC_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) - -#define DTMB_SYNC_TS_CFO_PN_VALUE DTMB_SYNC_ADDR(0x57) -#define DTMB_SYNC_TS_CFO_ERR_LIMIT DTMB_SYNC_ADDR(0x58) -#define DTMB_SYNC_TS_CFO_PN_MODIFY DTMB_SYNC_ADDR(0x59) -#define DTMB_SYNC_TS_GAIN DTMB_SYNC_ADDR(0x5a) -#define DTMB_SYNC_FE_CONFIG DTMB_SYNC_ADDR(0x5b) -#define DTMB_SYNC_PNPHASE_OFFSET DTMB_SYNC_ADDR(0x5c) -#define DTMB_SYNC_PNPHASE_CONFIG DTMB_SYNC_ADDR(0x5d) -#define DTMB_SYNC_SFO_SFO_PN0_MODIFY DTMB_SYNC_ADDR(0x5e) -#define DTMB_SYNC_SFO_SFO_PN1_MODIFY DTMB_SYNC_ADDR(0x5f) -#define DTMB_SYNC_SFO_SFO_PN2_MODIFY DTMB_SYNC_ADDR(0x60) -#define DTMB_SYNC_SFO_CONFIG DTMB_SYNC_ADDR(0x61) -#define DTMB_SYNC_FEC_CFG DTMB_SYNC_ADDR(0x67) -#define DTMB_SYNC_FEC_DEBUG_CFG DTMB_SYNC_ADDR(0x68) -#define DTMB_SYNC_DATA_DDR_ADR DTMB_SYNC_ADDR(0x69) -#define DTMB_SYNC_DEBUG_DDR_ADR DTMB_SYNC_ADDR(0x6a) -#define DTMB_SYNC_FEC_SIM_CFG1 DTMB_SYNC_ADDR(0x6b) -#define DTMB_SYNC_FEC_SIM_CFG2 DTMB_SYNC_ADDR(0x6c) -#define DTMB_SYNC_TRACK_CFO_MAX DTMB_SYNC_ADDR(0x6d) -#define DTMB_SYNC_CCI_DAGC_CONFIG1 DTMB_SYNC_ADDR(0x6e) -#define DTMB_SYNC_CCI_DAGC_CONFIG2 DTMB_SYNC_ADDR(0x6f) -#define DTMB_SYNC_CCI_RP DTMB_SYNC_ADDR(0x70) -#define DTMB_SYNC_CCI_DET_THRES DTMB_SYNC_ADDR(0x71) -#define DTMB_SYNC_CCI_NOTCH1_CONFIG1 DTMB_SYNC_ADDR(0x72) -#define DTMB_SYNC_CCI_NOTCH1_CONFIG2 DTMB_SYNC_ADDR(0x73) -#define DTMB_SYNC_CCI_NOTCH2_CONFIG1 DTMB_SYNC_ADDR(0x74) -#define DTMB_SYNC_CCI_NOTCH2_CONFIG2 DTMB_SYNC_ADDR(0x75) - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h deleted file mode 100644 index 0aebdd101af2..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_SYNC_BIT_H__ -#define __ADDR_DTMB_SYNC_BIT_H__ - -struct DTMB_SYNC_TS_CFO_PN_VALUE_BITS { - unsigned int ts_cfo_pn1_value:16, ts_cfo_pn0_value:16; -}; -struct DTMB_SYNC_TS_CFO_ERR_LIMIT_BITS { - unsigned int ts_cfo_err_limit:16, ts_cfo_pn2_value:16; -}; -struct DTMB_SYNC_TS_CFO_PN_MODIFY_BITS { - unsigned int ts_cfo_pn1_modify:16, ts_cfo_pn0_modify:16; -}; -struct DTMB_SYNC_TS_GAIN_BITS { - unsigned int ts_gain:2, - reserved0:2, - ts_sat_shift:3, - reserved1:1, - ts_fixpn_en:1, - ts_fixpn:2, reserved2:1, ts_cfo_cut:4, ts_cfo_pn2_modify:16; -}; -struct DTMB_SYNC_FE_CONFIG_BITS { - unsigned int fe_lock_len:4, - fe_sat_shift:3, reserved3:1, fe_cut:4, reserved4:4, fe_modify:16; -}; -struct DTMB_SYNC_PNPHASE_OFFSET_BITS { - unsigned int pnphase_offset2:4, - pnphase_offset1:4, pnphase_offset0:4, reserved5:20; -}; -struct DTMB_SYNC_PNPHASE_CONFIG_BITS { - unsigned int pnphase_gain:2, - reserved6:2, - pnphase_sat_shift:4, pnphase_cut:4, reserved7:4, pnphase_modify:16; -}; -struct DTMB_SYNC_SFO_SFO_PN0_MODIFY_BITS { - unsigned int sfo_cfo_pn0_modify:16, sfo_sfo_pn0_modify:16; -}; -struct DTMB_SYNC_SFO_SFO_PN1_MODIFY_BITS { - unsigned int sfo_cfo_pn1_modify:16, sfo_sfo_pn1_modify:16; -}; -struct DTMB_SYNC_SFO_SFO_PN2_MODIFY_BITS { - unsigned int sfo_cfo_pn2_modify:16, sfo_sfo_pn2_modify:16; -}; -struct DTMB_SYNC_SFO_CONFIG_BITS { - unsigned int sfo_sat_shift:4, - sfo_gain:2, - reserved8:2, - sfo_dist:2, - reserved9:2, - sfo_cfo_cut:4, sfo_sfo_cut:4, sfo_cci_th:4, reserved10:8; -}; -struct DTMB_SYNC_TRACK_CFO_MAX_BITS { - unsigned int track_cfo_max:8, - track_sfo_max:8, track_max_en:1, ctrl_fe_to_th:4, reserved11:11; -}; -struct DTMB_SYNC_CCI_DAGC_CONFIG1_BITS { - unsigned int cci_dagc_bypass:1, - cci_dagc_power_alpha:2, - cci_dagc_bw:3, - cci_dagc_gain_ctrl:12, - cci_dagc_gain_step_er:6, cci_dagc_gain_step:6, reserved12:2; -}; -struct DTMB_SYNC_CCI_DAGC_CONFIG2_BITS { - unsigned int cci_dagc_target_power_l:8, - cci_dagc_target_power_h:8, - cci_dagc_target_power_ler:8, cci_dagc_target_power_her:8; -}; -struct DTMB_SYNC_CCI_RP_BITS { - unsigned int cci_rpsq_n:10, reserved13:2, cci_rp_n:13, reserved14:7; -}; -struct DTMB_SYNC_CCI_DET_THRES_BITS { - unsigned int cci_avr_times:5, - reserved15:3, cci_det_thres:3, reserved16:21; -}; -struct DTMB_SYNC_CCI_NOTCH1_CONFIG1_BITS { - unsigned int cci_notch1_a1:10, - reserved17:2, cci_notch1_en:1, reserved18:19; -}; -struct DTMB_SYNC_CCI_NOTCH1_CONFIG2_BITS { - unsigned int cci_notch1_b1:10, - reserved19:2, cci_notch1_a2:10, reserved20:10; -}; -struct DTMB_SYNC_CCI_NOTCH2_CONFIG1_BITS { - unsigned int cci_notch2_a1:10, - reserved21:2, cci_notch2_en:1, reserved22:3, cci_mpthres:16; -}; -struct DTMB_SYNC_CCI_NOTCH2_CONFIG2_BITS { - unsigned int cci_notch2_b1:10, - reserved23:2, cci_notch2_a2:10, reserved24:10; -}; - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h deleted file mode 100644 index c12d26f66c0f..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_TOP_H__ -#define __ADDR_DTMB_TOP_H__ - -#include "addr_dtmb_top_bit.h" -#include "addr_dtmb_sync.h" -#include "addr_dtmb_sync_bit.h" -#include "addr_dtmb_che.h" -#include "addr_dtmb_che_bit.h" -#include "addr_dtmb_front.h" -#include "addr_dtmb_front_bit.h" - -#define DTMB_DEMOD_BASE DEMOD_REG_ADDR(0x0) -#define DTMB_TOP_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) - -#define DTMB_TOP_CTRL_SW_RST DTMB_TOP_ADDR(0x1) -#define DTMB_TOP_TESTBUS DTMB_TOP_ADDR(0x2) -#define DTMB_TOP_TB DTMB_TOP_ADDR(0x3) -#define DTMB_TOP_TB_V DTMB_TOP_ADDR(0x4) -#define DTMB_TOP_TB_ADDR_BEGIN DTMB_TOP_ADDR(0x5) -#define DTMB_TOP_TB_ADDR_END DTMB_TOP_ADDR(0x6) -#define DTMB_TOP_CTRL_ENABLE DTMB_TOP_ADDR(0x7) -#define DTMB_TOP_CTRL_LOOP DTMB_TOP_ADDR(0x8) -#define DTMB_TOP_CTRL_FSM DTMB_TOP_ADDR(0x9) -#define DTMB_TOP_CTRL_AGC DTMB_TOP_ADDR(0xa) -#define DTMB_TOP_CTRL_TS_SFO_CFO DTMB_TOP_ADDR(0xb) -#define DTMB_TOP_CTRL_FEC DTMB_TOP_ADDR(0xc) -#define DTMB_TOP_CTRL_INTLV_TIME DTMB_TOP_ADDR(0xd) -#define DTMB_TOP_CTRL_DAGC_CCI DTMB_TOP_ADDR(0xe) -#define DTMB_TOP_CTRL_TPS DTMB_TOP_ADDR(0xf) -#define DTMB_TOP_TPS_BIT DTMB_TOP_ADDR(0x10) -#define DTMB_TOP_CCI_FLG DTMB_TOP_ADDR(0xc7) -#define DTMB_TOP_TESTBUS_OUT DTMB_TOP_ADDR(0xc8) -#define DTMB_TOP_TBUS_DC_ADDR DTMB_TOP_ADDR(0xc9) -#define DTMB_TOP_FRONT_IQIB_CHECK DTMB_TOP_ADDR(0xca) -#define DTMB_TOP_SYNC_TS DTMB_TOP_ADDR(0xcb) -#define DTMB_TOP_SYNC_PNPHASE DTMB_TOP_ADDR(0xcd) -#define DTMB_TOP_CTRL_DDC_ICFO DTMB_TOP_ADDR(0xd2) -#define DTMB_TOP_CTRL_DDC_FCFO DTMB_TOP_ADDR(0xd3) -#define DTMB_TOP_CTRL_FSM_STATE0 DTMB_TOP_ADDR(0xd4) -#define DTMB_TOP_CTRL_FSM_STATE1 DTMB_TOP_ADDR(0xd5) -#define DTMB_TOP_CTRL_FSM_STATE2 DTMB_TOP_ADDR(0xd6) -#define DTMB_TOP_CTRL_FSM_STATE3 DTMB_TOP_ADDR(0xd7) -#define DTMB_TOP_CTRL_TS2 DTMB_TOP_ADDR(0xd8) -#define DTMB_TOP_FRONT_AGC DTMB_TOP_ADDR(0xd9) -#define DTMB_TOP_FRONT_DAGC DTMB_TOP_ADDR(0xda) -#define DTMB_TOP_FEC_TIME_STS DTMB_TOP_ADDR(0xdb) -#define DTMB_TOP_FEC_LDPC_STS DTMB_TOP_ADDR(0xdc) -#define DTMB_TOP_FEC_LDPC_IT_AVG DTMB_TOP_ADDR(0xdd) -#define DTMB_TOP_FEC_LDPC_UNC_ACC DTMB_TOP_ADDR(0xde) -#define DTMB_TOP_FEC_BCH_ACC DTMB_TOP_ADDR(0xdf) -#define DTMB_TOP_CTRL_ICFO_ALL DTMB_TOP_ADDR(0xe0) -#define DTMB_TOP_CTRL_FCFO_ALL DTMB_TOP_ADDR(0xe1) -#define DTMB_TOP_CTRL_SFO_ALL DTMB_TOP_ADDR(0xe2) -#define DTMB_TOP_FEC_LOCK_SNR DTMB_TOP_ADDR(0xe3) -#define DTMB_TOP_CHE_SEG_FACTOR DTMB_TOP_ADDR(0xe4) -#define DTMB_TOP_CTRL_CHE_WORKCNT DTMB_TOP_ADDR(0xe5) -#define DTMB_TOP_CHE_OBS_STATE1 DTMB_TOP_ADDR(0xe6) -#define DTMB_TOP_CHE_OBS_STATE2 DTMB_TOP_ADDR(0xe7) -#define DTMB_TOP_CHE_OBS_STATE3 DTMB_TOP_ADDR(0xe8) -#define DTMB_TOP_CHE_OBS_STATE4 DTMB_TOP_ADDR(0xe9) -#define DTMB_TOP_CHE_OBS_STATE5 DTMB_TOP_ADDR(0xea) -#define DTMB_TOP_SYNC_CCI_NF1 DTMB_TOP_ADDR(0xee) -#define DTMB_TOP_SYNC_CCI_NF2 DTMB_TOP_ADDR(0xef) -#define DTMB_TOP_SYNC_CCI_NF2_POSITION DTMB_TOP_ADDR(0xf0) -#define DTMB_TOP_CTRL_SYS_OFDM_CNT DTMB_TOP_ADDR(0xf1) -#define DTMB_TOP_CTRL_TPS_Q_FINAL DTMB_TOP_ADDR(0xf2) -#define DTMB_TOP_FRONT_DC DTMB_TOP_ADDR(0xf3) -#define DTMB_TOP_CHE_DEBUG DTMB_TOP_ADDR(0xf6) -#define DTMB_TOP_CTRL_TOTPS_READY_CNT DTMB_TOP_ADDR(0xff) - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h deleted file mode 100644 index 63233c4e49d9..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef __ADDR_DTMB_TOP_BIT_H__ -#define __ADDR_DTMB_TOP_BIT_H__ - -union DTMB_TOP_CTRL_SW_RST_BITS { - unsigned int d32; - struct { - unsigned int ctrl_sw_rst:1, ctrl_sw_rst_noreg:1, reserved0:30; - } b; -}; -struct DTMB_TOP_TESTBUS_BITS { - unsigned int testbus_addr:16, testbus_en:1, reserved1:15; -}; -struct DTMB_TOP_TB_BITS { - unsigned int tb_act_width:5, - reserved2:3, - tb_dc_mk:3, - reserved3:1, tb_capture_stop:1, tb_self_test:1, reserved4:18; -}; -struct DTMB_TOP_CTRL_ENABLE_BITS { - unsigned int ctrl_enable:24, reserved5:8; -}; -struct DTMB_TOP_CTRL_LOOP_BITS { - unsigned int ctrl_src_pnphase_loop:1, - ctrl_src_sfo_loop:1, - ctrl_ddc_fcfo_loop:1, ctrl_ddc_icfo_loop:1, reserved6:28; -}; -struct DTMB_TOP_CTRL_FSM_BITS { - unsigned int ctrl_fsm_state:5, - reserved7:3, - ctrl_fsm_v:1, reserved8:3, ctrl_reset_state:4, reserved9:16; -}; -struct DTMB_TOP_CTRL_AGC_BITS { - unsigned int ctrl_fast_agc:1, - ctrl_agc_bypass:1, - ts_cfo_bypass:1, sfo_strong0_bypass:1, reserved10:28; -}; -struct DTMB_TOP_CTRL_TS_SFO_CFO_BITS { - unsigned int ctrl_ts_q:10, - reserved11:2, - ctrl_pnphase_q:7, reserved12:1, ctrl_sfo_q:4, ctrl_cfo_q:8; -}; -struct DTMB_TOP_CTRL_FEC_BITS { - unsigned int reserved13:8, - ctrl_ts_to_th:4, - ctrl_pnphase_to_th:4, - ctrl_sfo_to_th:4, - ctrl_fe_to_th:4, ctrl_che_to_th:4, ctrl_fec_to_th:4; -}; -struct DTMB_TOP_CTRL_INTLV_TIME_BITS { - unsigned int ctrl_intlv720_time:12, ctrl_intlv240_time:12, reserved14:8; -}; -struct DTMB_TOP_CTRL_DAGC_CCI_BITS { - unsigned int dagc_mode:2, - cci_dagc_mode:2, - cci_bypass:1, - fe_bypass:1, - reserved15:1, - new_sync1:1, new_sync2:1, fec_inzero_check:1, reserved16:22; -}; -struct DTMB_TOP_CTRL_TPS_BITS { - unsigned int sfo_gain:2, - freq_reverse:1, - qam4_nr:1, - intlv_mode:1, - code_rate:2, - constell:2, - tps_carrier_mode:1, - freq_reverse_known:1, tps_known:1, ctrl_tps_to_th:4, reserved17:16; -}; -struct DTMB_TOP_CCI_FLG_BITS { - unsigned int cci_flg_cnt:8, m_cci_ready:1, reserved18:23; -}; -struct DTMB_TOP_FRONT_IQIB_CHECK_BITS { - unsigned int front_iqib_check_b:12, - front_iqib_check_a:10, reserved19:10; -}; -struct DTMB_TOP_SYNC_TS_BITS { - unsigned int sync_ts_idx:2, sync_ts_pos:13, sync_ts_q:10, reserved20:7; -}; -struct DTMB_TOP_SYNC_PNPHASE_BITS { - unsigned int sync_pnphase_max_q_idx:2, - sync_pnphase:8, sync_pnphase_max_q:7, reserved21:15; -}; -struct DTMB_TOP_CTRL_DDC_ICFO_BITS { - unsigned int ctrl_ddc_icfo:20, reserved22:12; -}; -struct DTMB_TOP_CTRL_DDC_FCFO_BITS { - unsigned int ctrl_src_sfo:17, ctrl_ddc_fcfo:14, reserved23:1; -}; -struct DTMB_TOP_CTRL_TS2_BITS { - unsigned int ctrl_ts2_workcnt:8, - ctrl_pnphase_workcnt:8, ctrl_sfo_workcnt:8, sync_fe_workcnt:8; -}; -struct DTMB_TOP_FRONT_AGC_BITS { - unsigned int front_agc_if_gain:11, - front_agc_rf_gain:11, front_agc_power:10; -}; -struct DTMB_TOP_FRONT_DAGC_BITS { - unsigned int front_dagc_power:8, front_dagc_gain:12, reserved24:12; -}; -struct DTMB_TOP_FEC_LDPC_IT_AVG_BITS { - unsigned int fec_ldpc_it_avg:16, fec_ldpc_per_rpt:13, reserved25:3; -}; -struct DTMB_TOP_CTRL_ICFO_ALL_BITS { - unsigned int ctrl_icfo_all:20, reserved26:12; -}; -struct DTMB_TOP_CTRL_FCFO_ALL_BITS { - unsigned int ctrl_fcfo_all:20, reserved27:12; -}; -struct DTMB_TOP_CTRL_SFO_ALL_BITS { - unsigned int ctrl_sfo_all:25, reserved28:7; -}; -struct DTMB_TOP_FEC_LOCK_SNR_BITS { - unsigned int che_snr:14, - fec_lock:1, reserved29:1, che_snr_average:14, reserved30:2; -}; -struct DTMB_TOP_CHE_SEG_FACTOR_BITS { - unsigned int che_seg_factor:14, reserved31:18; -}; -struct DTMB_TOP_CTRL_CHE_WORKCNT_BITS { - unsigned int ctrl_che_workcnt:8, - ctrl_fec_workcnt:8, - ctrl_constell:2, - ctrl_code_rate:2, - ctrl_intlv_mode:1, - ctrl_qam4_nr:1, ctrl_freq_reverse:1, reserved32:9; -}; -struct DTMB_TOP_SYNC_CCI_NF1_BITS { - unsigned int sync_cci_nf1_b1:10, - sync_cci_nf1_a2:10, sync_cci_nf1_a1:10, reserved33:2; -}; -struct DTMB_TOP_SYNC_CCI_NF2_BITS { - unsigned int sync_cci_nf2_b1:10, - sync_cci_nf2_a2:10, sync_cci_nf2_a1:10, reserved34:2; -}; -struct DTMB_TOP_SYNC_CCI_NF2_POSITION_BITS { - unsigned int sync_cci_nf2_position:11, - sync_cci_nf1_position:11, - sync_cci_nf2_det:1, sync_cci_nf1_det:1, reserved35:8; -}; -struct DTMB_TOP_CTRL_SYS_OFDM_CNT_BITS { - unsigned int ctrl_sys_ofdm_cnt:8, - mobi_det_power_var:19, - reserved36:1, ctrl_che_working_state:2, reserved37:2; -}; -struct DTMB_TOP_CTRL_TPS_Q_FINAL_BITS { - unsigned int ctrl_tps_q_final:7, ctrl_tps_suc_cnt:7, reserved38:18; -}; -struct DTMB_TOP_FRONT_DC_BITS { - unsigned int front_dc_q:10, front_dc_i:10, reserved39:12; -}; -struct DTMB_TOP_CTRL_TOTPS_READY_CNT_BITS { - unsigned int ctrl_dead_lock_det:1, - ctrl_dead_lock:1, - reserved40:2, - ctrl_dead_cnt:4, reserved41:8, ctrl_totps_ready_cnt:16; -}; - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h deleted file mode 100644 index 4f49fa7c5261..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifndef _DTV_REG_H_ -#define _DTV_REG_H_ - -#include - -#define DTV_WRITE_CBUS_REG(_r, _v) aml_write_cbus(_r, _v) -#define DTV_READ_CBUS_REG(_r) aml_read_cbus(_r) - -#endif /* */ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h deleted file mode 100644 index 5df7b1c48995..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ - -/***************************************************************** - ** - ** Copyright (C) 2010 Amlogic,Inc. - ** All rights reserved - ** Filename : amlfrontend.h - ** - ** comment: - ** Driver for aml demodulator - ** - **************************************************************** - */ - -#ifndef _AMLFRONTEND_H -#define _AMLFRONTEND_H - -struct amlfe_config { - int fe_mode; - int i2c_id; - int tuner_type; - int tuner_addr; -}; -enum Gxtv_Demod_Tuner_If { - Si2176_5M_If = 5, - Si2176_6M_If = 6 -}; -/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC */ -enum Gxtv_Demod_Dvb_Mode { - Gxtv_Dvbc = 0, - Gxtv_Dvbt_Isdbt = 1, - Gxtv_Atsc = 2, - Gxtv_Dtmb = 3, -}; -#define Adc_Clk_35M 35714 /* adc clk dvbc */ -#define Demod_Clk_71M 71428 /* demod clk */ - -#define Adc_Clk_24M 24000 -#define Demod_Clk_72M 72000 -#define Demod_Clk_60M 60000 - -#define Adc_Clk_28M 28571 /* dvbt,isdbt */ -#define Demod_Clk_66M 66666 - -#define Adc_Clk_26M 26000 /* atsc air */ -#define Demod_Clk_78M 78000 /* */ - -#define Adc_Clk_25_2M 25200 /* atsc cable */ -#define Demod_Clk_75M 75600 /* */ - -#define Adc_Clk_25M 25000 /* dtmb */ -#define Demod_Clk_100M 100000 /* */ -#define Demod_Clk_180M 180000 /* */ -#define Demod_Clk_200M 200000 /* */ -#define Demod_Clk_225M 225000 - -#define Adc_Clk_27M 27777 /* atsc */ -#define Demod_Clk_83M 83333 /* */ - -enum M6_Demod_Pll_Mode { - Cry_mode = 0, - Adc_mode = 1 -}; - -int M6_Demod_Dtmb_Init(struct aml_fe_dev *dev); -int convert_snr(int in_snr); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h deleted file mode 100644 index 4c9d28193b18..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h +++ /dev/null @@ -1,626 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#ifdef DEMOD_FUNC_H -#else -#define DEMOD_FUNC_H - -#include -/* #include */ -/*#include - * #include - #include -*/ -#include -#include "aml_fe.h" -#include "amlfrontend.h" -#include "addr_dtmb_top.h" -#include "c_stb_define.h" -#include "c_stb_regs_define.h" -#include - -/* #define G9_TV */ -#define GX_TV -#define safe_addr - -#define PWR_ON 1 -#define PWR_OFF 0 - -#define dtmb_mobile_mode - - -/* void __iomem *meson_reg_demod_map[1024]; */ - -#define IO_CBUS_PHY_BASE (0xc0800000) - -#ifdef safe_addr -#define IO_DEMOD_BASE (0xc8844000) -#define IO_AOBUS_BASE (0xc8100000) -#define IO_HIU_BASE (0xc883c000) -#else -#define IO_DEMOD_BASE (0xda844000) -#define IO_AOBUS_BASE (0xda100000) -#define IO_HIU_BASE (0xda83c000) -#endif - -#define DEMOD_REG_OFFSET(reg) (reg & 0xfffff) -#define DEMOD_REG_ADDR(reg) (IO_DEMOD_BASE + DEMOD_REG_OFFSET(reg)) - -#define DEMOD_CBUS_REG_OFFSET(reg) (reg << 2) -#define DEMOD_CBUS_REG_ADDR(reg) (IO_CBUS_PHY_BASE + \ - DEMOD_CBUS_REG_OFFSET(reg)) - -#define DEMOD_AOBUS_REG_OFFSET(reg) ((reg)) -#define DEMOD_AOBUS_REG_ADDR(reg) (IO_AOBUS_BASE + \ - DEMOD_AOBUS_REG_OFFSET(reg)) - -/* #define DEMOD_BASE APB_REG_ADDR(0x20000) */ -#define DEMOD_BASE DEMOD_REG_ADDR(0x0) /* 0xc8020000 */ - -/* #define DEMOD_BASE 0xc8020000 */ -#define DTMB_BASE (DEMOD_BASE + 0x000) -#define DVBT_BASE (DEMOD_BASE + 0x000) -#define ISDBT_BASE (DEMOD_BASE + 0x000) -#define QAM_BASE (DEMOD_BASE + 0x400) -#define ATSC_BASE (DEMOD_BASE + 0x800) -#define DEMOD_CFG_BASE (DEMOD_BASE + 0xC00) - -/* #ifdef TXL_TV */ -#define TXLTV_ADC_RESET_VALUE 0xca6a2110 /* 0xce7a2110 */ -#define TXLTV_ADC_REG1_VALUE 0x5d414260 -#define TXLTV_ADC_REG2_VALUE 0x5ba00384 /* 0x34e0bf81 */ -#define TXLTV_ADC_REG2_VALUE_CRY 0x34e0bf81 -#define TXLTV_ADC_REG3_VALUE 0x4a6a2110 /* 0x4e7a2110 */ -#define TXLTV_ADC_REG4_VALUE 0x02913004 -#define TXLTV_ADC_REG4_CRY_VALUE 0x301 -#define TXLTV_ADC_REG7_VALUE 0x00102038 -#define TXLTV_ADC_REG8_VALUE 0x00000406 -#define TXLTV_ADC_REG9_VALUE 0x00082183 -#define TXLTV_ADC_REGA_VALUE 0x80480240 -#define TXLTV_ADC_REGB_VALUE 0x22000442 -#define TXLTV_ADC_REGC_VALUE 0x00034a00 -#define TXLTV_ADC_REGD_VALUE 0x00005000 -#define TXLTV_ADC_REGE_VALUE 0x00000200 - - -/* DADC DPLL */ -#define ADC_REG1 (IO_HIU_BASE + (0xaa << 2)) -#define ADC_REG2 (IO_HIU_BASE + (0xab << 2)) -#define ADC_REG3 (IO_HIU_BASE + (0xac << 2)) -#define ADC_REG4 (IO_HIU_BASE + (0xad << 2)) - -#define ADC_REG5 (IO_HIU_BASE + (0x73 << 2)) -#define ADC_REG6 (IO_HIU_BASE + (0x74 << 2)) - -#define ADC_REGB (IO_HIU_BASE + (0xaf << 2)) -#define ADC_REGC (IO_HIU_BASE + (0x9e << 2)) -#define ADC_REGD (IO_HIU_BASE + (0x9f << 2)) - -/* DADC REG */ -#define ADC_REG7 (IO_HIU_BASE + (0x27 << 2)) -#define ADC_REG8 (IO_HIU_BASE + (0x28 << 2)) -#define ADC_REG9 (IO_HIU_BASE + (0x2a << 2)) -#define ADC_REGA (IO_HIU_BASE + (0x2b << 2)) -#define ADC_REGE (IO_HIU_BASE + (0xbd << 2)) - -/* #endif */ - - -/* #ifdef GX_TV */ - -#define ADC_RESET_VALUE 0x8a2a2110 /* 0xce7a2110 */ -#define ADC_REG1_VALUE 0x00100228 -#define ADC_REG2_VALUE 0x34e0bf80 /* 0x34e0bf81 */ -#define ADC_REG2_VALUE_CRY 0x34e0bf81 -#define ADC_REG3_VALUE 0x0a2a2110 /* 0x4e7a2110 */ -#define ADC_REG4_VALUE 0x02933800 -#define ADC_REG4_CRY_VALUE 0x301 -#define ADC_REG7_VALUE 0x01411036 -#define ADC_REG8_VALUE 0x00000000 -#define ADC_REG9_VALUE 0x00430036 -#define ADC_REGA_VALUE 0x80480240 -#if 0 -/* DADC DPLL */ -#define ADC_REG1 (IO_HIU_BASE + (0xaa << 2)) -#define ADC_REG2 (IO_HIU_BASE + (0xab << 2)) -#define ADC_REG3 (IO_HIU_BASE + (0xac << 2)) -#define ADC_REG4 (IO_HIU_BASE + (0xad << 2)) - -#define ADC_REG5 (IO_HIU_BASE + (0x73 << 2)) -#define ADC_REG6 (IO_HIU_BASE + (0x74 << 2)) - -/* DADC REG */ -#define ADC_REG7 (IO_HIU_BASE + (0x27 << 2)) -#define ADC_REG8 (IO_HIU_BASE + (0x28 << 2)) -#define ADC_REG9 (IO_HIU_BASE + (0x2a << 2)) -#define ADC_REGA (IO_HIU_BASE + (0x2b << 2)) -#endif -/* #endif */ - -#ifdef G9_TV - -#define ADC_RESET_VALUE 0x8a2a2110 /* 0xce7a2110 */ -#define ADC_REG1_VALUE 0x00100228 -#define ADC_REG2_VALUE 0x34e0bf80 /* 0x34e0bf81 */ -#define ADC_REG2_VALUE_CRY 0x34e0bf81 -#define ADC_REG3_VALUE 0x0a2a2110 /* 0x4e7a2110 */ -#define ADC_REG4_VALUE 0x02933800 -#define ADC_REG4_CRY_VALUE 0x301 -#define ADC_REG7_VALUE 0x01411036 -#define ADC_REG8_VALUE 0x00000000 -#define ADC_REG9_VALUE 0x00430036 -#define ADC_REGA_VALUE 0x80480240 - -/* DADC DPLL */ -#define ADC_REG1 0x10aa -#define ADC_REG2 0x10ab -#define ADC_REG3 0x10ac -#define ADC_REG4 0x10ad - -#define ADC_REG5 0x1073 -#define ADC_REG6 0x1074 - -/* DADC REG */ -#define ADC_REG7 0x1027 -#define ADC_REG8 0x1028 -#define ADC_REG9 0x102a -#define ADC_REGA 0x102b -#endif - -#ifdef M6_TV -#define ADC_REG1_VALUE 0x003b0232 -#define ADC_REG2_VALUE 0x814d3928 -#define ADC_REG3_VALUE 0x6b425012 -#define ADC_REG4_VALUE 0x101 -#define ADC_REG4_CRY_VALUE 0x301 -#define ADC_REG5_VALUE 0x70b -#define ADC_REG6_VALUE 0x713 - -#define ADC_REG1 0x10aa -#define ADC_REG2 0x10ab -#define ADC_REG3 0x10ac -#define ADC_REG4 0x10ad -#define ADC_REG5 0x1073 -#define ADC_REG6 0x1074 -#endif - -#define DEMOD_REG1_VALUE 0x0000d007 -#define DEMOD_REG2_VALUE 0x2e805400 -#define DEMOD_REG3_VALUE 0x201 - -#define DEMOD_REG1 (DEMOD_BASE + 0xc00) -#define DEMOD_REG2 (DEMOD_BASE + 0xc04) -#define DEMOD_REG3 (DEMOD_BASE + 0xc08) -#define DEMOD_REG4 (DEMOD_BASE + 0xc0c) - -/* #define Wr(addr, data) WRITE_CBUS_REG(addr, data)*/ -/* #define Rd(addr) READ_CBUS_REG(addr) */ - -/*#define Wr(addr, data) *(volatile unsigned long *)(addr) = (data)*/ -/*#define Rd(addr) *(volatile unsigned long *)(addr)*/ - -enum { - enable_mobile, - disable_mobile -}; - -enum { - OPEN_TIME_EQ, - CLOSE_TIME_EQ -}; - -enum { - AMLOGIC_DTMB_STEP0, - AMLOGIC_DTMB_STEP1, - AMLOGIC_DTMB_STEP2, - AMLOGIC_DTMB_STEP3, - AMLOGIC_DTMB_STEP4, - AMLOGIC_DTMB_STEP5, /* time eq */ - AMLOGIC_DTMB_STEP6, /* set normal mode sc */ - AMLOGIC_DTMB_STEP7, - AMLOGIC_DTMB_STEP8, /* set time eq mode */ - AMLOGIC_DTMB_STEP9, /* reset */ - AMLOGIC_DTMB_STEP10, /* set normal mode mc */ - AMLOGIC_DTMB_STEP11, -}; - -enum { - DTMB_IDLE = 0, - DTMB_AGC_READY = 1, - DTMB_TS1_READY = 2, - DTMB_TS2_READY = 3, - DTMB_FE_READY = 4, - DTMB_PNPHASE_READY = 5, - DTMB_SFO_INIT_READY = 6, - DTMB_TS3_READY = 7, - DTMB_PM_INIT_READY = 8, - DTMB_CHE_INIT_READY = 9, - DTMB_FEC_READY = 10 -}; - -/* i2c functions */ -/* int aml_i2c_sw_test_bus(struct aml_demod_i2c *adap, char *name); */ -int am_demod_i2c_xfer(struct aml_demod_i2c *adap, struct i2c_msg *msgs, - int num); -int init_tuner_fj2207(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *adap); -int set_tuner_fj2207(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *adap); - -int get_fj2207_ch_power(void); -int tuner_get_ch_power(struct aml_fe_dev *adap); -int tda18273_tuner_set_frequnecy(unsigned int dwFrequency, - unsigned int dwStandard); -int dtmb_get_power_strength(int agc_gain); - - -int tuner_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c); - -/* dvbt */ -int dvbt_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dvbt *demod_dvbt); - -struct demod_status_ops { - int (*get_status)(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c); - int (*get_ber)(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c); - int (*get_snr)(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c); - int (*get_strength)(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c); - int (*get_ucblocks)(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c); -}; - -struct demod_status_ops *dvbt_get_status_ops(void); - -/* dvbc */ - -int dvbc_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dvbc *demod_dvbc); -int dvbc_status(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_sts *demod_sts); -int dvbc_isr_islock(void); -void dvbc_isr(struct aml_demod_sta *demod_sta); -u32 dvbc_set_qam_mode(unsigned char mode); -u32 dvbc_get_status(void); -u32 dvbc_set_auto_symtrack(void); -int dvbc_timer_init(void); -void dvbc_timer_exit(void); -int dvbc_cci_task(void *data); -int dvbc_get_cci_task(void); -void dvbc_create_cci_task(void); -void dvbc_kill_cci_task(void); - -/* atsc */ - -int atsc_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_atsc *demod_atsc); -int check_atsc_fsm_status(void); - -void atsc_write_reg(int reg_addr, int reg_data); - -unsigned long atsc_read_reg(int reg_addr); - -unsigned long atsc_read_iqr_reg(void); - -int atsc_qam_set(fe_modulation_t mode); - -void qam_initial(int qam_id); - -/* dtmb */ - -int dtmb_set_ch(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_dtmb *demod_atsc); - -void dtmb_reset(void); - -int dtmb_check_status_gxtv(struct dvb_frontend *fe); -int dtmb_check_status_txl(struct dvb_frontend *fe); - - -void dtmb_write_reg(int reg_addr, int reg_data); -int dtmb_read_reg(int reg_addr); -void dtmb_register_reset(void); - -/* demod functions */ -unsigned long apb_read_reg_collect(unsigned long addr); -void apb_write_reg_collect(unsigned int addr, unsigned int data); -void apb_write_reg(unsigned int reg, unsigned int val); -unsigned long apb_read_reg_high(unsigned long addr); -unsigned long apb_read_reg(unsigned long reg); -int app_apb_write_reg(int addr, int data); -int app_apb_read_reg(int addr); - -void demod_set_cbus_reg(unsigned int data, unsigned int addr); -unsigned int demod_read_cbus_reg(unsigned int addr); -void demod_set_demod_reg(unsigned int data, unsigned int addr); -unsigned int demod_read_demod_reg(unsigned int addr); - -/* extern int clk_measure(char index); */ - -void ofdm_initial(int bandwidth, - /* 00:8M 01:7M 10:6M 11:5M */ - int samplerate, - /* 00:45M 01:20.8333M 10:20.7M 11:28.57 */ - int IF, - /* 000:36.13M 001:-5.5M 010:4.57M 011:4M 100:5M */ - int mode, - /* 00:DVBT,01:ISDBT */ - int tc_mode - /* 0: Unsigned, 1:TC */); - -void monitor_isdbt(void); -void demod_set_reg(struct aml_demod_reg *demod_reg); -void demod_get_reg(struct aml_demod_reg *demod_reg); - -/* void demod_calc_clk(struct aml_demod_sta *demod_sta); */ -int demod_set_sys(struct aml_demod_sta *demod_sta, - struct aml_demod_i2c *demod_i2c, - struct aml_demod_sys *demod_sys); -/* int demod_get_sys(struct aml_demod_i2c *demod_i2c, */ -/* struct aml_demod_sys *demod_sys); */ -/* int dvbt_set_ch(struct aml_demod_sta *demod_sta, */ -/* struct aml_demod_i2c *demod_i2c, */ -/* struct aml_demod_dvbt *demod_dvbt); */ -/* int tuner_set_ch (struct aml_demod_sta *demod_sta, */ -/* struct aml_demod_i2c *demod_i2c); */ - -/* typedef char int8_t; */ -/* typedef short int int16_t; */ -/* typedef int int32_t; */ -/* typedef long int64_t; */ -/*typedef unsigned char uint8_t; - * typedef unsigned short int uint16_t; - * typedef unsigned int uint32_t; - * typedef unsigned long uint64_t; - */ - -/*typedef unsigned char u8_t; - * typedef signed char s8_t; - * typedef unsigned short u16_t; - * typedef signed short s16_t; - * typedef unsigned int u32_t; - * typedef signed int s32_t; - * typedef unsigned long u64_t; - * typedef signed long s64_t; - */ - -/* #define extadc */ - -/* for g9tv */ -void adc_dpll_setup(int clk_a, int clk_b, int clk_sys); -void demod_power_switch(int pwr_cntl); - -union adc_pll_cntl { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned pll_m:9; - unsigned pll_n:5; - unsigned pll_od0:2; - unsigned pll_od1:2; - unsigned pll_od2:2; - unsigned pll_xd0:6; - unsigned pll_xd1:6; - } b; -}; - -union adc_pll_cntl2 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned output_mux_ctrl:4; - unsigned div2_ctrl:1; - unsigned b_polar_control:1; - unsigned a_polar_control:1; - unsigned gate_ctrl:6; - unsigned tdc_buf:8; - unsigned lm_s:6; - unsigned lm_w:4; - unsigned reserved:1; - } b; -}; - -union adc_pll_cntl3 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned afc_dsel_in:1; - unsigned afc_dsel_bypass:1; - unsigned dco_sdmck_sel:2; - unsigned dc_vc_in:2; - unsigned dco_m_en:1; - unsigned dpfd_lmode:1; - unsigned filter_acq1:11; - unsigned enable:1; - unsigned filter_acq2:11; - unsigned reset:1; - } b; -}; - -union adc_pll_cntl4 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned reve:12; - unsigned tdc_en:1; - unsigned dco_sdm_en:1; - unsigned dco_iup:2; - unsigned pvt_fix_en:1; - unsigned iir_bypass_n:1; - unsigned pll_od3:2; - unsigned filter_pvt1:4; - unsigned filter_pvt2:4; - unsigned reserved:4; - } b; -}; - -/* ///////////////////////////////////////////////////////////////// */ - -union demod_dig_clk { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned demod_clk_div:7; - unsigned reserved0:1; - unsigned demod_clk_en:1; - unsigned demod_clk_sel:2; - unsigned reserved1:5; - unsigned adc_extclk_div:7; /* 34 */ - unsigned use_adc_extclk:1; /* 1 */ - unsigned adc_extclk_en:1; /* 1 */ - unsigned adc_extclk_sel:3; /* 1 */ - unsigned reserved2:4; - } b; -}; - -union demod_adc_clk { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned pll_m:9; - unsigned pll_n:5; - unsigned pll_od:2; - unsigned pll_xd:5; - unsigned reserved0:3; - unsigned pll_ss_clk:4; - unsigned pll_ss_en:1; - unsigned reset:1; - unsigned pll_pd:1; - unsigned reserved1:1; - } b; -}; - -union demod_cfg0 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned mode:4; - unsigned ts_sel:4; - unsigned test_bus_clk:1; - unsigned adc_ext:1; - unsigned adc_rvs:1; - unsigned adc_swap:1; - unsigned adc_format:1; - unsigned adc_regout:1; - unsigned adc_regsel:1; - unsigned adc_regadj:5; - unsigned adc_value:10; - unsigned adc_test:1; - unsigned ddr_sel:1; - } b; -}; - -union demod_cfg1 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned reserved:8; - unsigned ref_top:2; - unsigned ref_bot:2; - unsigned cml_xs:2; - unsigned cml_1s:2; - unsigned vdda_sel:2; - unsigned bias_sel_sha:2; - unsigned bias_sel_mdac2:2; - unsigned bias_sel_mdac1:2; - unsigned fast_chg:1; - unsigned rin_sel:3; - unsigned en_ext_vbg:1; - unsigned en_cmlgen_res:1; - unsigned en_ext_vdd12:1; - unsigned en_ext_ref:1; - } b; -}; - -union demod_cfg2 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned en_adc:1; - unsigned biasgen_ibipt_sel:2; - unsigned biasgen_ibic_sel:2; - unsigned biasgen_rsv:4; - unsigned biasgen_en:1; - unsigned biasgen_bias_sel_adc:2; - unsigned biasgen_bias_sel_cml1:2; - unsigned biasgen_bias_sel_ref_op:2; - unsigned clk_phase_sel:1; - unsigned reserved:15; - } b; -}; - -union demod_cfg3 { - /** raw register data */ - uint32_t d32; - /** register bits */ - struct { - unsigned dc_arb_mask:3; - unsigned dc_arb_enable:1; - unsigned reserved:28; - } b; -}; - -struct atsc_cfg { - int adr; - int dat; - int rw; -}; - -struct agc_power_tab { - char name[128]; - int level; - int ncalcE; - int *calcE; -}; - -struct dtmb_cfg { - int dat; - int adr; - int rw; -}; - -void dtvpll_lock_init(void); -void dtvpll_init_flag(int on); -void demod_set_irq_mask(void); -void demod_clr_irq_stat(void); -void demod_set_adc_core_clk(int adc_clk, int sys_clk, int dvb_mode); -void demod_set_adc_core_clk_fix(int clk_adc, int clk_dem); -void calculate_cordic_para(void); -void ofdm_read_all_regs(void); -extern int aml_fe_analog_set_frontend(struct dvb_frontend *fe); - -#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c deleted file mode 100644 index f4c1a3808ba6..000000000000 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c +++ /dev/null @@ -1,189 +0,0 @@ -/* -* Copyright (C) 2017 Amlogic, Inc. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Description: -*/ -#include -#include -#include -#include "demod_func.h" -#include "../aml_fe.h" - -int tuner_get_ch_power(struct aml_fe_dev *adap) -{ - int strength = 0; - int agc_if_gain; - - struct dvb_frontend *dvbfe; - - dvbfe = get_si2177_tuner(); - if (dvbfe != NULL) - if (dvbfe->ops.tuner_ops.get_strength) - strength = dvbfe->ops.tuner_ops.get_strength(dvbfe); - if (strength <= -56) { - agc_if_gain = - ((dtmb_read_reg(DTMB_TOP_FRONT_AGC))&0x3ff); - strength = dtmb_get_power_strength(agc_if_gain); - } - - return strength; -} - -struct dvb_tuner_info *tuner_get_info(int type, int mode) -{ - /*type : 0-NULL, 1-DCT7070, 2-Maxliner, 3-FJ2207, 4-TD1316 */ - /*mode: 0-DVBC 1-DVBT */ - static struct dvb_tuner_info tinfo_null = { }; - - static struct dvb_tuner_info tinfo_MXL5003S[2] = { - [1] = { /*DVBT*/ .name = "Maxliner", - .frequency_min = 44000000, - .frequency_max = 885000000, } - }; - static struct dvb_tuner_info tinfo_FJ2207[2] = { - [0] = { /*DVBC*/ .name = "FJ2207", - .frequency_min = 54000000, - .frequency_max = 870000000, }, - [1] = { /*DVBT*/ .name = "FJ2207", - .frequency_min = 174000000, - .frequency_max = 864000000, }, - }; - static struct dvb_tuner_info tinfo_DCT7070[2] = { - [0] = { /*DVBC*/ .name = "DCT7070", - .frequency_min = 51000000, - .frequency_max = 860000000, } - }; - static struct dvb_tuner_info tinfo_TD1316[2] = { - [1] = { /*DVBT*/ .name = "TD1316", - .frequency_min = 51000000, - .frequency_max = 858000000, } - }; - static struct dvb_tuner_info tinfo_SI2176[2] = { - [0] = { /*DVBC*/ - /*#error please add SI2176 code*/ - .name = "SI2176", - .frequency_min = 51000000, - .frequency_max = 860000000, - } - }; - - struct dvb_tuner_info *tinfo[] = { - &tinfo_null, - tinfo_DCT7070, - tinfo_MXL5003S, - tinfo_FJ2207, - tinfo_TD1316, - tinfo_SI2176 - }; - - if ((type < 0) || (type > 4) || (mode < 0) || (mode > 1)) - return tinfo[0]; - - return &tinfo[type][mode]; -} - -struct agc_power_tab *tuner_get_agc_power_table(int type) -{ - /*type : 0-NULL, 1-DCT7070, 2-Maxliner, 3-FJ2207, 4-TD1316 */ - static int calcE_FJ2207[31] = { - 87, 118, 138, 154, 172, 197, 245, - 273, 292, 312, 327, 354, 406, 430, - 448, 464, 481, 505, 558, 583, 599, - 616, 632, 653, 698, 725, 745, 762, - 779, 801, 831 }; - static int calcE_Maxliner[79] = { - 543, 552, 562, 575, 586, 596, 608, - 618, 627, 635, 645, 653, 662, 668, - 678, 689, 696, 705, 715, 725, 733, - 742, 752, 763, 769, 778, 789, 800, - 807, 816, 826, 836, 844, 854, 864, - 874, 884, 894, 904, 913, 923, 932, - 942, 951, 961, 970, 980, 990, 1000, - 1012, 1022, 1031, 1040, 1049, 1059, - 1069, 1079, 1088, 1098, 1107, 1115, - 1123, 1132, 1140, 1148, 1157, 1165, - 1173, 1179, 1186, 1192, 1198, 1203, - 1208, 1208, 1214, 1217, 1218, 1220 }; - - static struct agc_power_tab power_tab[] = { - [0] = { "null", 0, 0, NULL }, - [1] = { - .name = "DCT7070", - .level = 0, - .ncalcE = 0, - .calcE = NULL, - }, - [2] = { - .name = "Maxlear", - .level = -22, - .ncalcE = sizeof(calcE_Maxliner) / sizeof(int), - .calcE = calcE_Maxliner, - }, - [3] = { - .name = "FJ2207", - .level = -62, - .ncalcE = sizeof(calcE_FJ2207) / sizeof(int), - .calcE = calcE_FJ2207, - }, - [4] = { - .name = "TD1316", - .level = 0, - .ncalcE = 0, - .calcE = NULL, - }, - }; - - if (type >= 2 && type <= 3) - return &power_tab[type]; - else - return &power_tab[3]; -}; - -int agc_power_to_dbm(int agc_gain, int ad_power, int offset, int tuner) -{ - struct agc_power_tab *ptab = tuner_get_agc_power_table(tuner); - int est_rf_power; - int j; - - for (j = 0; j < ptab->ncalcE; j++) - if (agc_gain <= ptab->calcE[j]) - break; - - est_rf_power = ptab->level - j - (ad_power >> 4) + 12 + offset; - - return est_rf_power; -} - -int dtmb_get_power_strength(int agc_gain) -{ - int strength; - int j; - static int calcE_R840[13] = { - 1010, 969, 890, 840, 800, - 760, 720, 680, 670, 660, - 510, 440, 368}; - for (j = 0; j < sizeof(calcE_R840)/sizeof(int); j++) - if (agc_gain >= calcE_R840[j]) - break; - if (agc_gain >= 440) - strength = -90+j*3; - else - strength = -56; - return strength; -} - - diff --git a/firmware/h264_enc.bin b/firmware/h264_enc.bin deleted file mode 100644 index 27c54d61c881c87861b14aa5cd903163c1ee7f51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76288 zcmeHQdvIOFdEa|=@7~>W@AVbJ5Nd-hJ0S@Kj4T^t10gFpkaMq5Bup|*$OB2n!E}gW zQXoz`g_X?X%1Ld7SH4?lKp@y?f=2cRldX;c%GR&%@zz z)8a*Ki`x9(G`;?lYx>r#Tf6@1MIT;!%`}(UyVl*<+ST{5*2U+wE?##2(iP{ox3#vn zEnc3KZA%hK+{;*V=kKpbvLQY)1Tt)ZGp2clv9e;Spd~BWn!m}oxY^~^bB~~$DX?4< zVl~mY+5B-=ZbEW&3G=g$x%&URp(NV6xQRBn{6Bg*Gsxq9bIL;CIU7x;P%q;-Ade9* zgiL4zVG0cdDpRMpQR52-mZS$00|XVmHd6f8sI7^R9i@ z6S_ZRnO5AtwTs8**G0NF$?DHP!iC2}7}QtyM0L{}nNwUJ#+r0NBCpP5w!9cY`h)IT zgY`w!20P2;%@2IPpDnnu?E75IFLN=ki#P5tQp`h|`kFIV9;edcOWRXrwJW>S%h<5H zHtb?e?Jp>cIHL=qQ|0vjLP;zrbB37Y!pqrzIk|qOP|85wI=?LB;w~<;87cO&oaoef z(V}t!*r{K+vNF41(zO`Z^nbc*ZKzK{pbdd?aVL|6jcM9YqP9g2ePf2l+f=sNqVrVN zJnf!I`Plr@=MhUhGu5+gdaMd25`+tl3-fi4=f9v1{>0JXIeajlY@fTg{#O^%ed+$1 z+6O+&$NCp8PuCOzo~OXJvy#}+ku(3~u^vVq&uM<{@(MAvL3P->T}47tCr$=_ zBQyr7PlVY%E>6Y!I}LUHUs6WQ#dy6P<6$nwPP$$SC-qr}6TRCZyxUE9x0~>8H{snz zcz;89S7})dGKu@r92leb`>@j!&tFs#qFCkPb|Yg1QIuRr#bb=!I*nh+Fh>>5Rf&m= z7&64_Z(V)8)9agEz=HZ#LD@S{wt}+NZXQ$lY6bm0ig|J8!S7Kl0Vab?4q>jxgUxb` z<~;hyM%}y6BZX1{?_#F0KHV6n_YjjVnOotK=KS7Eq-dx4dZ!)Jas;|zkYzM!pFnSRR(OMSBI&JO=&gMkbQ8+$!864bKBR#;dmMTlSgnpFwNuXy<|4Dh>foVmT8<&ePit947(y6Bkar@F zFofXh+?tEjc3Wo*GWi)?N06$*^O#e*&+D8mZY+zoD(;JWXFH^5!+dxna8Z6NqYj&2 z5q937|8*MQ=qL4`VsScT1Hb~IJ_ys_oiPBZsc;vL(uf$`wS zhFFQd(ilOWaBC1|B)b6k&^)>Th_Y8ifDt$RpHmN4u0BG-v~X+VHx{j$3LMI*XpEPWMKj@^xQd zAf`6!cm`_2zH8KplX@6CV>Es`W9TW0dnD!`mo4v+c3ibw;qt5BFU5N+@MAO|!kj0) zQq55LUSDsWls11o^d8Btm*NUME2Sx*JUW25SIXHGy*YLL6o0+VUw=QYbEIwg zRDD|x^*?}qQ`?jujb$~9_#Wnb#tJvsoY%5>A6T3DUH?FETee^^YRN#s<8P)mK*Z% z7k&H*A9u4~MSD(Exmj#0pN0Ar_#lt{JIhwk&aBItcv)#)UX9oc^KuX3o|U}oS)K3F z&bQptl*?_I*Heo$KdKCz#0sqs0|2)L=5YITpWJ;CA%!E$BXH^GCj zIoSroPeFVN`q)g@fzdzYS?)dDV+DPfVD%SMuu8D|te0=~@#m-H@ACOgKK}BQ{8y&r zho|Jb+0!rZU1SdZF3`sV?;_*hMP}M}adKaopR%URPpg&ryj5jB|5B`@x?G-Q$-6qa zALXus{GBM*jdDFGciDk=D1TbxQ5k;b4wj968u6h)otJa4hJe4h`}wc%@qT0dq$1ws zc)J@XCbx^h{b)klNFa&vxu0`-i&2VJb9}#>!c6T%jYv2mn-txpd zy)CYY@)s;+%c2R9Vr5v3hff)(?#wd_A?GNb`z(6d^^aAEG(wGB1olI6ow?~;}WzmF?N8ku1<8(#V%X6t~dcF6t z&`*i`S8xs9W}&DxAKx|*twQ<}SykBmedJdU6gOdgP{e%Ry=l9kKlv*=4&wzO%% z#P#p`a_6RG4||#DUkZPxM-KUX1J7^QG_-Hiu5)r7Y>eI!6|d^%axMI2vpp*IA^o9l zUS~-6BYkx@FRtmvn$<_h3Mf-8fh;7HF2VqCHZujL> z&aQ!e?AopS=NLjPvwc#)eyQKxQrgtca%$X_A#Ch3(cVi64+%S4?OZOUzRu2NxeVja zthZ^Jb2Q%)oDPW@o_7|;)n?e2clz--)h=xTrhAsCJlUw}>=Qks#c%IznA0rRJlZO& zwD#>(MHmxqPTEkiHoF(|6Fzl}Kx9SZ40CyE-8$CzgjYR-xdn{H zLY5P-%@XU?nf6X&>O1z()YqLZt)qOrzX{`>=BLU}eRs2-f?uIDZ#Fv*@*~QZ!>`!I zWZ7d+@3sOR)I5#Pp?725ZZtm$dVM+cdLxJTs}@e^@FCa|$)4d7HY+x**7uOGU3HWb z*n71)-8h}D?@#G;=-_l+sxzH_KcUveTUK@P6EE%Jv%9(uvXP|c6Z?5U->A&?~}PXb*|_V?gf3UUdKu&U~JzB zdpBG6N8`VLgrAsO$s_-r#LA5uR}AZ-6Ct0i2IQU4wX-q5XT$HGjrmD)qU!bUY^=@F zA-xyK<}#}@ruwrwyP*_4s`;jttnEMPJ!`i+S&@}lspnDn0}ZTg@Vqn*^n0BxOl)(l z^CD)}BHMcT%(nGY(Ce4&Cwxrdgw-#Vem559?O2y>Px&NO;ryk4hWtw@xhy#O=dhOh zTuMHcck(|%`M*rbtKRRrD=qVFd^sf>^0Kd_WMf`7oRUdA7x`?-c!+L=uLiu+3*>B+Y z;oj5_8uNL46S{c8$uf`i7Ome&#?EjyKeMbN3RqK#i{NvceML3PuTSVZ&wTW|Wf|5w z+oO14PMXtQ9VpeP){c2g>$j!&_JBREI`e+-Hf{a3G2~BY-x+Xd*yoS8Up{;f}GH7SqmPI;;btI*6jn)uuo!1}5 zkVlZ)ddW8y+>^?We+~Ql^z8+G6(jqK<`mZ-u?qbp{}=rfwQjCn=j1tH5JOMa@Qg!) z%JpNkSBe_iK%4aJwC7nT{WaUSWpFPgIqhc(MYf-nMF+kK&@(`uyptrx>e;>zx(B^8 zT01A>XbgUQakb>*&{1R96DGjy-TcPE6iCOA}rVLl_c+_@-g(b$OYDkF$|SvdU|0 zK_vZHs>1FZ>N%3O$5FR@GXb-0+RCSZ=y%^ZG5_K zfbbdU{Y4(zT9(Zcw7#Hya9pb*t+T9Rv7j~66599Rr3l}g_49fAeUKqezM~Hv;#-@3 zE^oiDAIUzen1k`xFK7?EV1B^uH#YrSS3l`L?V}zw2Gi|d9|H#F*LjP9LQH$x=2wTu z;7IyyzcZrm@xnz|Yd#ny80h;Q2I}d_7(`3Epc7A(5z4Z-EM8yj;%`7W9pQ}#Z$fx8 z!Wjr>BD@9REQGTW79pI2(1x%Wp&fy+C4c!1DSz)CZ)ZPA?^|GnHBF))1 zr^a?)kU2faQ((^ z-eL17b0hLJp7Ez?eyDrw{OF+h!E_VD?*}rN4}0` z@G;z@>g83WBh($ISZPjssGD$&;wt=k>WhSauzn`mlW2$9+eGcbCzX&5p?nR2bQ;wg zLR(axu2IaeUrP7U_};7W`{*k$S%%;J-DK{K{z~5)E$g@^`fqlRy{@qiP-=lI zi|>IJ6ZnIQ+R*noIoeiuHcfkNxJPCK6ACh$|0deUUoPJy^l!ayPJ-|k5C{ka1Ofs9 zfq+0jARrJB2nYlO0s;YnfIvVXAP^7;2m}NI0s(=5KtLcM5D*9m1Ox&C0fB%(Kp-Fx z5C{ka1Ofs9fq+0jARrJB2nYlO0s;YnfIvVXAP^7;2m}NI0I>Wd zgy&%nEn?17o&%}SB|IM9+h5z}s z|A#pf|AqSV7sh{~9(6ny`kBf67uw6+|Kh4Y82$_MK6j4HRQ?P0Jtt=`7XO8KZS!BS zyFH#S5&uQP4{#*>7wU^R8!W|tp}v4T{?GY%;J?sY9Ztu}f5CP*J#no37v`&8&)ntX zz<+UE@?Y39dDgpg&DDbk&NWYXFW7a?PTZay;6Hlo4~y3#;Vfb|yD|Ej;I+8Q_w`tK zEv|8O&6PgB&7I{iiPI+VT7ZWl@LIfDcr943(|P*JSDx2G{W0bfackh*wVBRdJK}T4 zJfB63^YtciSitX(2US*s_rmg{f#WF6VKKo`aYb6+dJ1F7o=*}OWhvJ3vO#H{8c_!X=7|xH&J-;S?(C&Tj?N-KGCm2l-}!KfAe9$60Fjd^E%fkA(I-66Q&F#_g+$M`Hi2)AC5D7RMt&To9AaS;d@t&GSM0 zwR_L?ta*9(Aoe&u2&a3Gkq6=%DP8;`@<2@RKj5rT;`=!w{)d#_PV+nzz^M>;9vF^O zoSADV@I2sbN`D@2!e^B5Jeb*2cplnswP$ip@OVta-!sAUFsfbI%e%nsZJ!J#z8-?uyuof*sXa2d{yKLLG= z2f?>Ag(J}N`JnC#4Yk|g8{sV2>E7#$&g0Pj%JVqr3*C4=8XgC= z!qxdh;c-xBx&BP$aWH2(`O)w==r{ScjN@wvJPwXeg60%`X@9lwIOr1{j{`$YJny=N zA9gRXfqh2S%#Vr3LGN}P2CU@jCwK|iTjA|3?JttO6|lE)VsBqTo(Gk27#VP05YK}` z{G#o*PQ&w{{>EWs{wMG}1fB zi!0ak-E{4m$t)NN&x5;ma671furMuomGEC24u`4zJRB~8{~|pIj^A|Pzo_wglPQSZ zH6Am>kJY%yn?iCZ^OAy6KI~DUMTM4CgsYUnFoIE45vxJYqpH z+9!DfX?tF*Ju|jf%6S!T9zOiJ=yaBm`i|?XKw9Fwy9jeH!kKqN+f-A$8g0#YbIZ=l zQ@gq7ZZgiv-q}Tx zMK{3?uRjnBxC|&C)0_j2ax|7=RfXr_2WjSc(wJswvk>?%j9sf_p{f|dX>6FE#vbSM z5YIzAAMt#|t%zF@M>sq7=NPAR;JXL@3sabb`AX-32mTAj0{=zCi#W@0_kNvUrQO== zP-mP!i#2g^V~_l#Kj(XC(}IcgcfIV~lPGv+)lG@L>&&$qA$-d=fXQyQM zd)cCt>;W%3CnbB(%i2=1onE#$C40!r+EcP`Lq@;-Apf2{QRAwF-xRO~Qrq|r&VCy4 zQ=fu7cmuf?M^&agHBw*_ZdD=@Va+!ulWBGb&W z!1W-!0{=zezsRsY$P=X`|TZa#3KE@W7TWWC5=(9Lc7f(jq;^2}T5I_lhj>o<1u z4x2~$8Fm+EcgSp%h;r9_tH!-s#$`o~BWMx0(ENgbPTAoDHq`7_)zq6pZ zjq)__lXfypWe?PUz}C;GMX0Z`%v@X4&k=`W;J*m`7sv1KLBo>;1Ofs9fq+0jARrJB z2nYlO0s;YnfIvVXAP^7;2m}NI0s(=5KtLcM5D*9m1Ox&C0fB%(Kp-Fx5C{ka1Ofs9 pfq+0jARrJB2nYlO0s;YnfIvVXAP^7;2m}NI0s(=5!0~~={{wBSrpN#Q diff --git a/firmware/video/h264_enc.bin b/firmware/video/h264_enc.bin deleted file mode 100644 index 27c54d61c881c87861b14aa5cd903163c1ee7f51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76288 zcmeHQdvIOFdEa|=@7~>W@AVbJ5Nd-hJ0S@Kj4T^t10gFpkaMq5Bup|*$OB2n!E}gW zQXoz`g_X?X%1Ld7SH4?lKp@y?f=2cRldX;c%GR&%@zz z)8a*Ki`x9(G`;?lYx>r#Tf6@1MIT;!%`}(UyVl*<+ST{5*2U+wE?##2(iP{ox3#vn zEnc3KZA%hK+{;*V=kKpbvLQY)1Tt)ZGp2clv9e;Spd~BWn!m}oxY^~^bB~~$DX?4< zVl~mY+5B-=ZbEW&3G=g$x%&URp(NV6xQRBn{6Bg*Gsxq9bIL;CIU7x;P%q;-Ade9* zgiL4zVG0cdDpRMpQR52-mZS$00|XVmHd6f8sI7^R9i@ z6S_ZRnO5AtwTs8**G0NF$?DHP!iC2}7}QtyM0L{}nNwUJ#+r0NBCpP5w!9cY`h)IT zgY`w!20P2;%@2IPpDnnu?E75IFLN=ki#P5tQp`h|`kFIV9;edcOWRXrwJW>S%h<5H zHtb?e?Jp>cIHL=qQ|0vjLP;zrbB37Y!pqrzIk|qOP|85wI=?LB;w~<;87cO&oaoef z(V}t!*r{K+vNF41(zO`Z^nbc*ZKzK{pbdd?aVL|6jcM9YqP9g2ePf2l+f=sNqVrVN zJnf!I`Plr@=MhUhGu5+gdaMd25`+tl3-fi4=f9v1{>0JXIeajlY@fTg{#O^%ed+$1 z+6O+&$NCp8PuCOzo~OXJvy#}+ku(3~u^vVq&uM<{@(MAvL3P->T}47tCr$=_ zBQyr7PlVY%E>6Y!I}LUHUs6WQ#dy6P<6$nwPP$$SC-qr}6TRCZyxUE9x0~>8H{snz zcz;89S7})dGKu@r92leb`>@j!&tFs#qFCkPb|Yg1QIuRr#bb=!I*nh+Fh>>5Rf&m= z7&64_Z(V)8)9agEz=HZ#LD@S{wt}+NZXQ$lY6bm0ig|J8!S7Kl0Vab?4q>jxgUxb` z<~;hyM%}y6BZX1{?_#F0KHV6n_YjjVnOotK=KS7Eq-dx4dZ!)Jas;|zkYzM!pFnSRR(OMSBI&JO=&gMkbQ8+$!864bKBR#;dmMTlSgnpFwNuXy<|4Dh>foVmT8<&ePit947(y6Bkar@F zFofXh+?tEjc3Wo*GWi)?N06$*^O#e*&+D8mZY+zoD(;JWXFH^5!+dxna8Z6NqYj&2 z5q937|8*MQ=qL4`VsScT1Hb~IJ_ys_oiPBZsc;vL(uf$`wS zhFFQd(ilOWaBC1|B)b6k&^)>Th_Y8ifDt$RpHmN4u0BG-v~X+VHx{j$3LMI*XpEPWMKj@^xQd zAf`6!cm`_2zH8KplX@6CV>Es`W9TW0dnD!`mo4v+c3ibw;qt5BFU5N+@MAO|!kj0) zQq55LUSDsWls11o^d8Btm*NUME2Sx*JUW25SIXHGy*YLL6o0+VUw=QYbEIwg zRDD|x^*?}qQ`?jujb$~9_#Wnb#tJvsoY%5>A6T3DUH?FETee^^YRN#s<8P)mK*Z% z7k&H*A9u4~MSD(Exmj#0pN0Ar_#lt{JIhwk&aBItcv)#)UX9oc^KuX3o|U}oS)K3F z&bQptl*?_I*Heo$KdKCz#0sqs0|2)L=5YITpWJ;CA%!E$BXH^GCj zIoSroPeFVN`q)g@fzdzYS?)dDV+DPfVD%SMuu8D|te0=~@#m-H@ACOgKK}BQ{8y&r zho|Jb+0!rZU1SdZF3`sV?;_*hMP}M}adKaopR%URPpg&ryj5jB|5B`@x?G-Q$-6qa zALXus{GBM*jdDFGciDk=D1TbxQ5k;b4wj968u6h)otJa4hJe4h`}wc%@qT0dq$1ws zc)J@XCbx^h{b)klNFa&vxu0`-i&2VJb9}#>!c6T%jYv2mn-txpd zy)CYY@)s;+%c2R9Vr5v3hff)(?#wd_A?GNb`z(6d^^aAEG(wGB1olI6ow?~;}WzmF?N8ku1<8(#V%X6t~dcF6t z&`*i`S8xs9W}&DxAKx|*twQ<}SykBmedJdU6gOdgP{e%Ry=l9kKlv*=4&wzO%% z#P#p`a_6RG4||#DUkZPxM-KUX1J7^QG_-Hiu5)r7Y>eI!6|d^%axMI2vpp*IA^o9l zUS~-6BYkx@FRtmvn$<_h3Mf-8fh;7HF2VqCHZujL> z&aQ!e?AopS=NLjPvwc#)eyQKxQrgtca%$X_A#Ch3(cVi64+%S4?OZOUzRu2NxeVja zthZ^Jb2Q%)oDPW@o_7|;)n?e2clz--)h=xTrhAsCJlUw}>=Qks#c%IznA0rRJlZO& zwD#>(MHmxqPTEkiHoF(|6Fzl}Kx9SZ40CyE-8$CzgjYR-xdn{H zLY5P-%@XU?nf6X&>O1z()YqLZt)qOrzX{`>=BLU}eRs2-f?uIDZ#Fv*@*~QZ!>`!I zWZ7d+@3sOR)I5#Pp?725ZZtm$dVM+cdLxJTs}@e^@FCa|$)4d7HY+x**7uOGU3HWb z*n71)-8h}D?@#G;=-_l+sxzH_KcUveTUK@P6EE%Jv%9(uvXP|c6Z?5U->A&?~}PXb*|_V?gf3UUdKu&U~JzB zdpBG6N8`VLgrAsO$s_-r#LA5uR}AZ-6Ct0i2IQU4wX-q5XT$HGjrmD)qU!bUY^=@F zA-xyK<}#}@ruwrwyP*_4s`;jttnEMPJ!`i+S&@}lspnDn0}ZTg@Vqn*^n0BxOl)(l z^CD)}BHMcT%(nGY(Ce4&Cwxrdgw-#Vem559?O2y>Px&NO;ryk4hWtw@xhy#O=dhOh zTuMHcck(|%`M*rbtKRRrD=qVFd^sf>^0Kd_WMf`7oRUdA7x`?-c!+L=uLiu+3*>B+Y z;oj5_8uNL46S{c8$uf`i7Ome&#?EjyKeMbN3RqK#i{NvceML3PuTSVZ&wTW|Wf|5w z+oO14PMXtQ9VpeP){c2g>$j!&_JBREI`e+-Hf{a3G2~BY-x+Xd*yoS8Up{;f}GH7SqmPI;;btI*6jn)uuo!1}5 zkVlZ)ddW8y+>^?We+~Ql^z8+G6(jqK<`mZ-u?qbp{}=rfwQjCn=j1tH5JOMa@Qg!) z%JpNkSBe_iK%4aJwC7nT{WaUSWpFPgIqhc(MYf-nMF+kK&@(`uyptrx>e;>zx(B^8 zT01A>XbgUQakb>*&{1R96DGjy-TcPE6iCOA}rVLl_c+_@-g(b$OYDkF$|SvdU|0 zK_vZHs>1FZ>N%3O$5FR@GXb-0+RCSZ=y%^ZG5_K zfbbdU{Y4(zT9(Zcw7#Hya9pb*t+T9Rv7j~66599Rr3l}g_49fAeUKqezM~Hv;#-@3 zE^oiDAIUzen1k`xFK7?EV1B^uH#YrSS3l`L?V}zw2Gi|d9|H#F*LjP9LQH$x=2wTu z;7IyyzcZrm@xnz|Yd#ny80h;Q2I}d_7(`3Epc7A(5z4Z-EM8yj;%`7W9pQ}#Z$fx8 z!Wjr>BD@9REQGTW79pI2(1x%Wp&fy+C4c!1DSz)CZ)ZPA?^|GnHBF))1 zr^a?)kU2faQ((^ z-eL17b0hLJp7Ez?eyDrw{OF+h!E_VD?*}rN4}0` z@G;z@>g83WBh($ISZPjssGD$&;wt=k>WhSauzn`mlW2$9+eGcbCzX&5p?nR2bQ;wg zLR(axu2IaeUrP7U_};7W`{*k$S%%;J-DK{K{z~5)E$g@^`fqlRy{@qiP-=lI zi|>IJ6ZnIQ+R*noIoeiuHcfkNxJPCK6ACh$|0deUUoPJy^l!ayPJ-|k5C{ka1Ofs9 zfq+0jARrJB2nYlO0s;YnfIvVXAP^7;2m}NI0s(=5KtLcM5D*9m1Ox&C0fB%(Kp-Fx z5C{ka1Ofs9fq+0jARrJB2nYlO0s;YnfIvVXAP^7;2m}NI0I>Wd zgy&%nEn?17o&%}SB|IM9+h5z}s z|A#pf|AqSV7sh{~9(6ny`kBf67uw6+|Kh4Y82$_MK6j4HRQ?P0Jtt=`7XO8KZS!BS zyFH#S5&uQP4{#*>7wU^R8!W|tp}v4T{?GY%;J?sY9Ztu}f5CP*J#no37v`&8&)ntX zz<+UE@?Y39dDgpg&DDbk&NWYXFW7a?PTZay;6Hlo4~y3#;Vfb|yD|Ej;I+8Q_w`tK zEv|8O&6PgB&7I{iiPI+VT7ZWl@LIfDcr943(|P*JSDx2G{W0bfackh*wVBRdJK}T4 zJfB63^YtciSitX(2US*s_rmg{f#WF6VKKo`aYb6+dJ1F7o=*}OWhvJ3vO#H{8c_!X=7|xH&J-;S?(C&Tj?N-KGCm2l-}!KfAe9$60Fjd^E%fkA(I-66Q&F#_g+$M`Hi2)AC5D7RMt&To9AaS;d@t&GSM0 zwR_L?ta*9(Aoe&u2&a3Gkq6=%DP8;`@<2@RKj5rT;`=!w{)d#_PV+nzz^M>;9vF^O zoSADV@I2sbN`D@2!e^B5Jeb*2cplnswP$ip@OVta-!sAUFsfbI%e%nsZJ!J#z8-?uyuof*sXa2d{yKLLG= z2f?>Ag(J}N`JnC#4Yk|g8{sV2>E7#$&g0Pj%JVqr3*C4=8XgC= z!qxdh;c-xBx&BP$aWH2(`O)w==r{ScjN@wvJPwXeg60%`X@9lwIOr1{j{`$YJny=N zA9gRXfqh2S%#Vr3LGN}P2CU@jCwK|iTjA|3?JttO6|lE)VsBqTo(Gk27#VP05YK}` z{G#o*PQ&w{{>EWs{wMG}1fB zi!0ak-E{4m$t)NN&x5;ma671furMuomGEC24u`4zJRB~8{~|pIj^A|Pzo_wglPQSZ zH6Am>kJY%yn?iCZ^OAy6KI~DUMTM4CgsYUnFoIE45vxJYqpH z+9!DfX?tF*Ju|jf%6S!T9zOiJ=yaBm`i|?XKw9Fwy9jeH!kKqN+f-A$8g0#YbIZ=l zQ@gq7ZZgiv-q}Tx zMK{3?uRjnBxC|&C)0_j2ax|7=RfXr_2WjSc(wJswvk>?%j9sf_p{f|dX>6FE#vbSM z5YIzAAMt#|t%zF@M>sq7=NPAR;JXL@3sabb`AX-32mTAj0{=zCi#W@0_kNvUrQO== zP-mP!i#2g^V~_l#Kj(XC(}IcgcfIV~lPGv+)lG@L>&&$qA$-d=fXQyQM zd)cCt>;W%3CnbB(%i2=1onE#$C40!r+EcP`Lq@;-Apf2{QRAwF-xRO~Qrq|r&VCy4 zQ=fu7cmuf?M^&agHBw*_ZdD=@Va+!ulWBGb&W z!1W-!0{=zezsRsY$P=X`|TZa#3KE@W7TWWC5=(9Lc7f(jq;^2}T5I_lhj>o<1u z4x2~$8Fm+EcgSp%h;r9_tH!-s#$`o~BWMx0(ENgbPTAoDHq`7_)zq6pZ zjq)__lXfypWe?PUz}C;GMX0Z`%v@X4&k=`W;J*m`7sv1KLBo>;1Ofs9fq+0jARrJB z2nYlO0s;YnfIvVXAP^7;2m}NI0s(=5KtLcM5D*9m1Ox&C0fB%(Kp-Fx5C{ka1Ofs9 pfq+0jARrJB2nYlO0s;YnfIvVXAP^7;2m}NI0s(=5!0~~={{wBSrpN#Q diff --git a/firmware/video/video_ucode.bin b/firmware/video/video_ucode.bin deleted file mode 100644 index dd56ade8bfbde386a811e935b2ba7e24e9859dc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1671680 zcmeFa3wT_`l_y@^>b`ZW`bxHB2@Dt`$;M!dhi&r0KwOdyw_C`@PngXz6U*R`5W>Se z;$#CZ$(ghyWAli~>?U6(l58itBoH36GkMH^D9cH1w`79>n>=S-LA)}Q>RXyI(4e*p6j06(|+;dXFoUVrcM9!@GVzQI&ckp z*EzrXn`IyS`BhQ&zn^;BuYcNp<6kWLyZ^lANunC6F2_n+V5R+{tf3m(DIKf-!=R8v9=|5@3{VZKl|7F zzkkl+dvCpfeSOkQ6q@^zN_EHMh+D$Pcf1_knqL@Bf>{JAQrXoX@^6 z^yP2de#85(y817l-u~;^r4wKJyVZBy@+Qu)Q{}=22`eUp9 z(|`DfKi%`OFaP+zuFwC|^B?N{^nGJ5er3{^s{Zcwrf1EQROa z)8ADaKJxw#&VScC-v5!Cues?%XRZCvwc}fVC~bUv@(bmY*TaYF4~C5z6w zs_@NY(P3gck42YT=AJe0tas0S_u6;7`<$~1SDZ8N%60SRRW$m8H-G4?kAJZH+N&z! zDqojecWra~_3NAGy|a1V+y(DEcfmR5HqW0s@7yF$3_AJA*!7Hk?&XIsKTK7J@>Jhm zLxB|Q@fgz{#(k|~iZj2MdXjDFyqu&?0hkF($%r2_K3jz51xP?<~rX5+Zum1*>@ z8k776`4nTvZwNR84$S@5e>EXJj%N?Mcy<5y^pnt*^pgcI{kPXig1_lW;a}}*kNvMy z(Dnr4S>Wp*JmRS{4QH7e)T3BBDtNtFsb&A`FowIL8_SD`^?#nk(3ouQsBd0(?Mv(R_Tp3d>!X317;2u@^Qvwg3D zFtu~^)ki%4{5yGHtCD6V^7j5HXFyMNiK|cSEdVadh`quChC$tXx;z1X%!w{fX0#{S zLOd=cc$I$wyqXgM()&C)JMc`_)oJqwf!C>wCu;*Ql?wdM%qKm0R^ZjW2lI|)S@4c$O*g~ zyc_$@mkFQYA=vT`*+dP?a!@?K9R=H#*C3d8*-~HTZox-Y-Yk5_s3Q1pWZ>bj~q+D&@sPWd~*&&hMNh zsXTj@2c6SV2IFF2$Ot*C1<_Bk!1HH!dHGF7_`O>A;EDVuguVEUcL~1g+>U(Un|rB0 zcgFqsV{Y56e(pl%1-|JqlkQDv&kU!62xFm)aaBeiik?9$Bm7ge$5-^ovgww6^gi4! z{S!6!*|1d8HUyoG+7r9hxwH=L(va7jvLVQ$4gQISQym&|gF<$~hCrf>UcdtWe$?B+ zf?8_pyJB92j2u9EQkJ($k#9CUda)}InNB?5%J;?*fj8{6(@Y-0`aP&D}3>h?|%L^5a zDHHH!H=l5niRytn!q7C!s9tAFH#nTA9mScNbK}Mf&o1(K>TEl9Xg&%}{Jx;ei@KQz zzjJ?_Ht6vS0?+(6*Ef3Dg((RceLBf$&15Xot=t7ZR^Hy03g*m2TTTSN`KRMCs+qzZ zF#uWT>O9lcaj?#>*xw0knips;&_hn%%W}c%1TV3&@a4A(-e?aK5oA8eF^TvoXt%@| zHIF#DjlB8=uLHE}#nW*8_carcr|k=#2g5n zA>A%8AGvrwQt-Iyc5RvA=s+|tVti7_A%{cAVGcPg0e5sK#vkCOPGx>}7UaZf%&(oz z{H8OR-*^V|(_briyC-RHlU^p$UxOTsOcamiF^FD?hZ8LibGOKk`? zBfhgvdpW=uOE1p!A>?VreVWrSf9KctSQ+o{DR}*9#>=g{WVu6SOBg3UWO<>3W%?;U z^7@eLJ{$CW$aWvH-G2$=Etc&*WV=7Y0MhX)@iVod4{ag&vA1WLFpys)GiW?S^}gWR z@hi(5q80Icl3)Mq@cB*6`20j$Y8TB(`L){h^}o2Wd`Q;=J@I$gygxmB-Wu>ujUJQ? zI#*3vd%MAt4VVMZK|L?G8Ga7<_(nW0pNx0#lg+Qz$r{i~vO7E(8t`F{S3v%;wn2|= zb@gm|mDdgovUH82d|!3>v_6K&x&wTjj`fQU=oe||7vsiG-BPck72~L`&h{12XQWN@H0F^s=9YA}#ye?b zjg?oFMskDtltC|>26;Rmy4kejCySRBw&bQU^n0wMJ@*eio;o)byfi^aW0xd)w}a7$ zb~QFl7pvF{xdXE`Z~T72Yy377tDb#KZiC$0#&*hWn9tammb#~iHD3+cN%QekcBl8fi;OpQODf%n-`g-xt5Y`wjcCt3b2PsP{i&vG z2%ZA`m!D)zg$o)ubT&J=YR+G-IHb2VQx&ZG0;5GeeD!uALz|1brG)}4Wj#oQm zqZee3gI;hP^a6!>a;lffG_HmxAU^X4q@mHS8VF z5QjGIhrC<0Zkb5h*@*ty-_au)(O*g1s9k3IhF}}?j{|`B6zF(Qmen2Cq_Whu;{kUY z@TNy)*`%h`?dff^(AIlYmfExGoxm4uYeJhGKHFte#}42#3>Cc$|XaMtJp!np}JH<=;1x=Cf4pl=;OztFp$ zv>`Y^>8LYl)9P9H-NZ7D2&pYcZwF|&_CZJ2H4l1C-FTl1{L!xQ?a;ZV(+uB6I6bw| z;?#&b_ETMmZ(`_s@YpKgPirs2xv~9Axz(U;lZMWM_09p{xEf^+piJW~^ds_;o@g=~ zg4NI+soxqG^;kWb`fe4wMp8R%d4W7=?`nN^j@qmK&5iw4;K%*wI}A8Ruq^G6o{Yb# zP18gp(uv=Rw#4%WdKK|~LxlK0mtyM8fw=SxjH7#cbK5SwLlVs@dC0=h!xjdOU4nBU z=Ao(VOOp6V{o0M$WK1PAw|xR$n#eR%SuiM3#f)|mq9UDhIf@RoXYW8i~c2jl0z zLzLTFC9NT-jpcYs0a zX2Dm22K7u>-3YRg)~X6NoXYhtbeBv&^do=pN=plq=Rs;l;M=%;G>0)3rWKFC@3fvb z7acy`fZr*dXg-k6WQr)0;7t0xEn9CUg`mO3)Gr;tt=$)652~86UX`VJAP4=^Ca6EH^4#BV)l*L?gj&`P&RjyxQFNa;jV0~r|J2>tdH#Lw5# zK+aMcpQ$<4u{KU)JxFn3Gvdxd+}*%SW9^0f`Bs#HT}ox+a>$dXJV;}Z!M0paw=4oy zDS-!hXX9HielY()sPO0oBMTV-P44Ed@-;{+p!~2-xz*h{OLP#a?>3!%{cp*hVDE@b|@Pn|HLw_ zD03sqTye)i{-XZxqyA}ClKQ@Qmf;1|-w9mg?lp1%?~v13qE$GobI~W4iEzD2_dRh( zj@B(4{ApBY%XD>f$J)F&>KuX-l>V7#$6uvQf!dW14A;N$tc>CqOXlC)d(?ifpx8G3Kgz^0Rd>?OWW4a@vAQ-g3KVFY~pAcuYM zdhtf^|4k@E{13R%O$cvBoXtNhIq;8wAK}5CaPah#jwX~hO7&zZ{~dt0kKmvj$t>R5 zA;X)2FW^Q96Zj$W770Ecehc0gAWiLb@b|><_d58Lm*Cs{hr_2F=O2yniSrZOOHk)N zJo+BT+qP}sW3oL`Q?91*yo3cmz|29msV5;vrXc;(XW;?PPZHi(XOn!OvLW=-2oIly z2lB$oedy^SwH5kdMDdgdYdMa!0LOZf$9Ci*mB;#&^zLXn_yO~#g^6)b`J=NB$##CS zhMXFd=G(Vf85EuXSZvVR`69?C4p~F^t9#>iAuro~TW~L6YvslS&7B(N|F^6dv_ z!;YI8lGNvYcqqLO>#2UC2YwgPZj$qy`j1^91?nn8HzT<}fccVR?kireMTCcA?&He~ zUUVbgp|g(80M3{z$}NjUI2-tGy3+DKWwB9O6uyqb12S{Z7X-W~z(xp}&^? z_6pk%A@W8fAEAd)zZB8GCFoGlNpi#^G;fd%l6~K$6KpmMbM!|+d)uFG467|Jo%)`A z(e*vy=|kT780Ta=W!E_T<^ZN?ak!99RwOvExrfA;Bds}_&&U?)gHHaZj3Aw<2ps)* zEpU9iC&W&7?YjMLmF*m6=~1j#Xm2N&!ZN|jJ((`>{;~FUXdg&ooJiOVY2Kv$pfc(& zqu=|nb}q~{Tp$$GE~E>ryTqrl#{}KT{jT#kY>d&1Ivc|7)eu5Qqdq~KKtJeAIwPVr zIbXvrY0&P+Vtpju*Gt7~3hI;mD}%BW@4XUi>JR?_XaF4jS5W@9uxlpeFUI;bhw(ZF zy}|N|0^d&_giU@>`pv_h&vtlz%6NXZ&MRX4_hCIRrefZ2T_yy^f8DIWC%IpMOqfU) z8ZT5&pIz^3)`q>*=Q}5hHozv_pNE`o!(LI_!y}>%dqr)qF%oUgSk&d6(b1A)xm}Zf zl2W`4c1Gegf_3$dUU3HCT%%@6>UVnoik>0czAL<+$QJS39O%55%g)%c4K!?nJZeKfx1ryj|35nWVf35L2ix%TqfE3} z-Pr_lfD6SR>92Si_#5(|)Y2t*2DW(YTZA)6PC%zY$YAH-GVsg|W|Ep6_!L*X0pptF z1LC6_jVR(>{WY`s`T&p1E-z}C2AlJBvITw7!i?7nnzbUFfp7-GnFwbhe3tfv^;$_X zMnDc1Hx0=$Fr0lL z_z~9MRwo9}*?B-+Cr3e_5cn0-%LU1jBKFke^cv5~CTc4Wd>^#+K|?={y-wsm)_WPW zo>dcgr{Osr&ulz>M0eWfI1PRO24J2H7}N2bf~OfzC)(N%coOhPSEu#~(4m0+mt)nP zz>oui)yd((VIx%oSwE z@YPQx*-U7R9;v?w{yN}FH0SyX`9^4bH2f2s3170i*#5@cG79_z`knMr>iYuvz8`&0 z@~S`S`_sV(kYUs&jyBQym^VlfwWmd?eucRB1d@|jlOm6rjP+8-7bVqGL>O+`Df0$% zEkX`iYRE2!zbs^W67AX zV+`Y!@+5pRZp=WI9B#}^9H$e<%EU2};7a{(c?^AbIKI-b|Bzg%Z2$N%03D`6&LnM1 zaIdVlvQFY{;$;CoqWVWQ&b+Y0<6!05>6mN2#RKAR;%A?&%~9W#K*y`;d{>Su4*(B| zaWa55Gwi{Y!K-A4EYC9dt=NF-&e6D`eF6qM8R-^e?}jd&k>KNgl2zbQS59TrO+28o z3jM0HH9qMmeSketKOwyZ`mxnliEr7JJO~j-1L#7_|VPrutyLsA#{E9 z0QPU&Xg*t$Ge6lF>|HpNqd7rO-4OU~2Jx`1^P$`l*hUK@?HSVJ`sX{Hvk&{vr>2$N zr+yl;FBiYJ#9?b3{S3}UVGfOk9M zChE@udQky;<^}EaqDmdvo|lUC>)Qdp3*|%LIEE*J?JF|PwvQv=z-L@8NC)qljXGd2 z3xI2vdL~C@_OwnDIjo~dZsm|KXS$`$Yw>#k_`!Yxn>6A09QLX8`+4vr=6yP&K>AK` z(;BJ47bHihPsxr(wmP!A^_>Mf590a!-W>6RwXvaYN-JaD%RkYRBU_u0AkLXx`;WE0LWI;Zfl~q{qXD4bj41p)Gu>+u%$}5%}=)x^RxDS@6!*Tqoi?v8Eb0 z+3?P0ykm__=TGd}tFo}RKC&eW;9Q1XP+)En7>`yaVEz%vuO#gMXk-84lwDgi6xSX+ zbD8i2Y&OfsnO{LyQ2G+xM78Dh+kojy-zo6?LI zFgES^4!l!%GR1M|Q+S^q$5FoiIPR2+xN;oVToGrkyfqL$%7cHCGau@7hjRp6$$o0r z(pX#4*iXY;{V#YF*;Hmi_i2T0uwt$#wk{Ciie?eD&Jkm+DmyxC(&5U<_u|q| zD;a)EF}61TO>6XB(0O7wqw{rU3~O4dXW%8B30KZV{sk4~WB74-+P}7WQ7!}yHZSU? zH4xQLeChYLXZ?p^n|~O4Uw9XI7kFQ?sXbeZ_gcJf#d{sz>+nwP8^athmTu4PLAYnc zq=R1AB?vctrQJJFunm`xK1S!rYLJie^dJw~nbX3{!}dpbmE$}j&O>sDU?pXf_@wMu zhshA`1cPkwwoc%jd&s0^&8AGSs6E@Y+oW@_)9#I7*Cq7>?!_46n;|pk9LwE}I!oYt%**-Lu;aDJhUd7xJHm#dvz$k8M2k^mqT&*`8fQ`I2?|{FT~;YI2??_ z9S9%&HO|5S#>F$C&&@VCqtq=(cgaCl?*=cP483F+;a1Eub>Oq<`27ripMr2Ec(NHG z=`WO@^42kzhtesH_BFO{V~{5gcoFOv{8pCcShI4n;bF~+wF~SFHEth34NJ1^Svj~H za~jGXZeM`LEX{9Q|H?>?@g6Pg&e7gMvTsmnw_veeKR%8zjx}+#i`n()5pjd8CfuHY zoOyJ)u{Nm?a^L(CvJaup9`s6RlfQ+fS2U<>|2CE;x!Z}fQG}IsQhUkXQQ79D^Nl^f zFo66VeMdZ+=Lba=i#E%N#U zauj;}DD-$AdVF86P8ZYlLg2hs=iNqj!tO`wn?Bguh_)r1`|X^s?0JL|;w1RC*gIFy z-YKQ`*>tz}R_f7$%KBIn$`?R4GuUK$QYj3cMXCFo({o{;S*js8_JHti00;Gm0;t$ucIjYf^~2gW_4NgKxgg zu77P>Bg^PsGfCEBPvk@H{8vH@w!Kdyn^L*-Do` zYG;`QmRauNLcnzA4ws3925ecJR>Lyt68B!jyMOjZ+}~}LTRzRw{@L0SYnk2Sm=T}d zN$&P1XBn_hH12M%NwGMN8^{^&_g`9RT%y#o}~m+ z@3b(MH>!+TZYC91DzSBw$}W9I3rZ)LA@*Y|jMy$t>$k2yvvJ&Ul^G+~Oj@n}BgRxbdq6FK_?AYeGYSMQ$;1Ujo z(mI5~8Eb08Qk;WL(u-$f499JJ6nkB^jVMFqic=N~7hZIb4ji`LKJ+QYvss7wm1yLn zAF2G+IA3hO!h?O-9}98jjxScyo+qYri8x=E-0|F3aX#6+kPUKb5Z|c4c5$1NPh{H* z!4s-wL-2Tt@w@OIW|-}d=v>eq@+=?!h7DHm1+eYnj%-OALEi-s-(QoXGv~MzsrBar-|d<)1$bb%W=1< z5W_Dw6HhoC!xp#a%kS=Sa;u|9CTT_Bn!NM(9C{Bc-isCQQN?=^ZD$xiN%v&S+z)tPx6jS$JxISV<|}s-+L$@uXv9t-iwv*7?V_%pJe#*RTv+O zK$G4Ui(^P}Bx{gf#5*KbPzyZgOvZTnXgsf*ig_J*%|B=D9fRnR=A8b;t#;0)xkUZM z#fO-`X{?3~?~B9B56v&nxjZBv&C9o1*!A9&{q8wDN!zmhhXf%`O`i4 z9z_oK(W#vJ`gmSZ-*EL8*Ryo=(jA$c?v{HV!VBlfX7K%E&=tBM zhekIkF$r@>V4kz*+AMzaXfMj)rhe}3NLIE%rg49EJ4<(>oW$HyP7NKlJ$bZMbQn92 zBy*l^m-_M%+J*D$kR#^4tQ|{7YKNNG4(K^aJ0=02KtFHWQU=YEc9^&w?5S+91-!4y zj#eux&W`&B-1$OvzZ*M#2Is4Z&gor~{B*nRFF&m(nW32OIKxAFlo@otRUFnrry#jO zdKuMkUW6RL{&MF6&4Y8nd#Jy7J>)#bw!Qa&u@xdckMvS%x$u#vbi?(+@^nK6a}(|v z?!vu@3&7);gG%*(Ch|UoU7~b8;#%>YsFwGMJkm?4Zox-{7oCW+Pk8L_@8G-x)l2Yc z?jOTlV&K4y@H$cN#faaGvz|HR*}VRGk^6SRdye#_leqo%*5fn!mCH-qo-lv+AP1m58@amE7ckvz>a*jM+Vn{mi9 zPIuJK)I7wx)~>@)hVJ6A_qzKqycPK|mr{M^DyQQ|;A`9uz_~G`;htI%Wr}o93B1im zHc9&Cl+BN^N^>7?xR&k}*g22JFRdFm?z5S-F+74rx=FnDCzuoG#K?}TcnuTd!30avywBCoJMw}Ze8+r=G!D32 z36JV16Yk%Oe>b8|!X0PI#$2!T50-a6Xk|{-C=?R6mPt0fd{1 z*Z#a?JZ=hd!{VlJKWn`agl~wx;O0xPSD^o?KZc!sgyaZ+I;N4?DaF&6`%qs$&P9e2 zXK#>h3Nbwl=8Lq#UB~RP%ZI_PQeDc!4O%Gq6_ zp;RVMJPY0~LJuig{@o!3weP$bU##;&)NK~H-|GC>X4BCn^tmxS$`?R4GuUK$QYj3REdjr9hPeRSHxoP^CbX0#yoB zDNv$`?R4GuUK$QZ&PYT@hk@>%q|4WoVI=XKI|CjIo;D*m0iw+apS@nN;^lpE< zq^9saPli4J)E~S5%P0N_{9k_ijr+eeZ`A+g-=(VlFGmjJ|MI@rU*c2Do_{%-ACjv7 zOZZo*^j8<3?d^ozdCT~}yz_PVzub~~Tl&A;Tkgg8pVl1P|K-o!S-rQM|I1q(-QUXo zFZEZQ98mw&g^7QA%kPt*F- ze7x#Uv+7UtxAUi|YvZ-so9s{19KoL^eS0%s)Q9)0nR0ji{9YqUZzJED^qu?M%7T|` zV7T<_{ADuuwWIG`CwCv|{)~=&U`Dv}9??A+d{3C}$gm5YpGe-@EK0ZoeKF$bZYrfw zXnks~`AUxN1pO{PGWC07f0WAIAtW3Wd|T3;7=tvj*B$g{iMv;?$491uZ%bRg!tW)E zePQYeelPXA;`(DBO}74b#^sS#SwDS~^>_7=$rk)^`^e&s{h8m3H}>#$Bp>lu>Knx9IsgajrH#Rb^C8TVS@k0 zsYmeNc-&$9H^N_Igm01@^xt@EEHgn@^53Yw?r_$RxR9X@G$vlR|3>%+l(@%T0K8-R zZ`>E(H8bdk*XzGA_TzWZf8z}fe~J3kKe%_+J<p=$J=yQGlD;fasC^--opMHzkhW9jR)I>JI(C7vH!+} zZcNzwv5={BKQ=`8TlsIinp^+w_mcm{1+o9e*uM&R?UsBj!u$zi%GFUt^EM?@ja9 zc!6uzM1M1HWq*zAS%uD|_L`rFI7VxU5jwV1~-# zI}K@nlS%J|4p2J-{#=F;zo;^vAs&8RUPAm8E}qsRR3_Neo(i=@0ztZu(|Em5kS=-_LUy^N~d`wpQA0)q-6a8PZ(|-T{FHP0|DCtZ#laE zOPZ0%cWd-J_`o!O;`He^+Xp6t-@`ZJ1Jf-1?R;Re3Llud>H{v+-EI70KpC z-}WOPo-|J;zWlU+&t%w^{25H_VQXap-+5(qJmBz)s`1VC+U+K7{i>o&z60O6rubUS zNh_rw-=UQ5&&Y^9_)cIK%F-HKeA=Y(g+0KKg1#eO`!MD40e^fRSdx*aQIKC~n`co* zB;~0rLwZQ*R1d*e4MU>pnY33g3$=E9dtUJ@O{gxyhsyekSOq>zFytY+ zP##NfeAAcmk^fc+U#z)adM_?W;xD1CbodsdtcdXGMB(nR|@ z_*|v33{MIEG|5+Jlxol7`=)6QcpUJ^CP8)lA^)oWFaMC#uhw0qK$QYj3REdjr9hPe zRSHxoP^CbX0#yoBDNv=r>!ZLN@-y%wx9{0X2XTK|`3i`!F3{99VzGsgM9WVgGt-;4jtzj*umzhoailHazf|I4cX z%h+FLg>TFMr~WV3#`C(NeUR9%b=CjnVf|m~RyS_nZ2y<_Q@gzSh8|HrH9)w_hJPrZ zm@4*x8MZo~n2G<(LdNkW`ORdHz6m}t*)z^3Cj9>LyD!HkR-Na=?=O7U3Lk!dtzW@E zu&+%0$nV!zrvB^kzB2XS{BiioWMBS&=POe^>3n7C?;P1zrvCELePyyQjQ5qv{?h%{ zpLgLOi?2+0#2e=;)4c5NGu2mpWxl?J@W0bs9A_u;c>bvUUrs%W|I6dv9RHW<`0@TP z72v+9{x9Lf()#dx1O6}R%+4RH|4TYQL+5R*|H}?-{a+^Mn=0?xve*wM`D>;7$$DXY z-}5MbFx3P>Id`RsYtChyGns71*#ONQlLtK zDg~+(s8XOxfhq;66sS_5N`Wc`suZYFph|%%1*#ONQlLtKDg~+(s8XOxfj<}puG(-- zh5yUzn7jvw7a!1@Am}!8zwP&!0Q*+$2v7I{C@iWX3-C^23)Orm91Es&7Z9fKi@;e*(&+ zYTUVZTLAGUiI2Y_Yvbd8>Xl@#zv6ow8Rg-YieMRr(AcoCth}aCu}(sjn-I(5yL9nJ|Jly}#4HZE(J zpL{1|Rfc7zG;6N`^-N~BdnW5}&@nDaK8EyNS;nc3@50~CNX2^x>lUf^cpmsI!$v-0 z>-g@!7Bf@5ROT~(j=1=nB=z_<&y*E4sEcJ%`1Vz*(WDhVhr*WC9Qtm_vPB;I7oAo5 zg&eBFpQGRSvV-W8xZDx)+oIKfRSHxoP^CbX0#yoBDNv$`?R4GuUK$QYj3LJ$3 zSIwK>eKZ5uvFtol{wUxXdmGrl248*V|34NTCbsifbgA0Ej>;8p%|zIZ-ZcByjEg*t z57@F9uoazo5#ZweOuUng>%9mUUIZJG&M^H|XS<^K_BfqFp(wAgc`IyK<84D#yV6^e zk*Zi#DNv$`?R4GuUK$QYj3REdjr9hPeRSLY-C@}uq)A+MrgzF(Y&*3qjcrNNS zxz@iX<}DRL=f5UDaMy*$qQk^?9*Zu&cl+1%)$?C(gt1br$J(S)jMXZJ(^h_$$7*1A zqCY?IPS{uQ^v7B7j#2^nUdNyB&SoV!^>321VM)yRP&Fp`>FkqY?D!1lVC?nKUwh7f9uYFZNm4zuJ*O3{%0y^djjzc-@f_5Bc3|baF(I7 zSc;{ig4c`lTO5v~-m45~P!s51!d}2s;oIfN-nzu{!ZyN)uqh_JzyBBLYWg+0; z+!@7vPPgS2p)LbIV>ZvCE^pEKN-hde)4t}M{*}wO`vlDwnL+tEeY!pOwFzbDn?1J7 zlfp~gL}%7CFmZ9zhI^5R{QzwMZKw@|xBi)*`Z`#O@EUf==9LuN|Tzmobh~^eq zzRL)G>&Jt_3BVO_3ukK1{&`~{(Ek3pSF@MPHKjlSBPWAXXAIX~?2%o8d5UA5-; zJ8FcJK)VVJIxD8$XX_00Y{~nYrJ04kTlRF0_clwmVnc8u`V`RCus z`&yMWE0MSNM>zv}s!LoSioFHEWf`$oc)&2Idry}qz>hi6<;jfpBwL8bg&@wjKLK9N zi2&(+o}3*VJlkjU2Z7hAj3;XYFO>@X&deu0c~;=ny$AV@XBJ1tZ;X{+-Q)>9BxP9e z26`up(ixh|kxOKuL1mIW&(Sx-ccp?40~fu|l^3~!C+^guACJfhyc@h5`_7l)6Oeca zw!8!R(DzbbXJN_8ZK%f)3gzxo>CP{rTsz8P+=~vBWy9WB%6K^i z7^)J6adc^^@n2hJ`(exY?3134K7!LW8;Uv1KfaCmKHKE^vueEV)*3$rcnKXlsV{>% zZ*-R7@>Ih|Yw-JYykCy6CGf6q3H$-%>4cwUIvYxTNo5CS8qV*WC8<1nmIs~FQ3m5; zV8{qLtOe0evcU6acX|0uM)%~fdSNf* z9LM+rOeQ~O``lmL<@pVhMIL(-VmZd%MHqt$aUES=saK`_UY7B}v*W&JOiY$$lTt>t$(@6?v2qC{H2vAJQ`BSB}1=oZ)`DC+i1>Q+sqBXoC0BdGt*_U(ESH zucrqb-9wDa5P5iO9{r0xdy)r|8LxDn;kB`>;plU|7&2%^mlrBJS8D>^?B)}WGEqHn zM;MxB8P)4-=>~@rps*~@x;hTl z`4#&+flc#*ozI4xyqD#I*9l%?W%ykDR>2#^_iQ7`e3D}l@l()li7{#(adaDb^$T7H zXxEFU<9vj8I*vDdgdU8=k+b37d^+Zv)3iuW54^O&+^U3EGnYclfzTP!?eNnGxD?Mv z3LaPS`SDgq2cmfq~Y~owfO!c;`=ECfAVy<@E=E82=5AbeKucQ4!km2t8pHEL$Dd~opsvF0mfK*ai$L; zPb==zJcc> zJukNzehzr|Mm#T{jCb&m&9BzU8qi9zJ3JX0@LrEsK>o3|LCGkKA2D4J|SPjQg8R<>0%LRT?1Vs4gQwEO`0oZ8uOXuZ-gW8L0SVH!~O;@cYv4E zu};weogxjLV%&JCTk3VRV(iq_*}fuLj#@vy{e3H)Acqfglu`-I%NLEmvGU#H{ zAcN;aADedkWbx9%mfSRkevkFC=l-F`Q|G3FmoOJq>SgAVMAvpO8qu!Crs-l8dm(oK zK2{sQU+@~g&BUr_ACuc4>$b6-avSC_b|&VXnHz$p(==}aEt}A;%kZ7e%bGqRni}f7 zrZY8P4S7j(@KkoE_q~gZH+4%Y-H6}YFgL4HHw2An&pmTAzX$!PrfdkF0{qXY=Ow{u zh<3>RNNZfDvKCg8&aO5;%GtUA?*QO6{b?$_>O#QGF3vPgsq>CkJ7l95WR8O_a2#|2 z^4&Yt%VZi?$1sjqzQdMp^t{YxPSyN4H6)uxhP_Kc^CmOwHSHSqj%SEN8}~!Tty;HC zB<*ZOf9>z+5sm1tq;1qLGkrs_4LZjGzS@llfi?%hPO%9*!vZ-SS@EHaUJ3NIxZED})9nkCKev~^dSn7Qyn-ber zZ;kmvF^jJOzS$$=OMR2zyb3sL^a0`A1e}}9kX+rQGELC24xnG?T~FE&9H4a6nY3y3 zEd0iOmqvutmZP@=G+g_jqwAUny{2xw&jtQy*Z6kmT+?ZWZzG(Z+GufVL>>F7F2px6 z^gVcN74WC^7UA63{-xY%(6&iKPr(}J0B~H5G6ztmaTod#c}X`k@SVIG`XcpP1#`qi~eg zHmq9?V4b8eFS3R@UqJp88m5ba{%KC&Tlf;+z|Wzt0`RzE3!xh=^vOqcE%XTL2Z8V8 zOMD+chd!i!2!c8flFZIQA_X}g?)C(SPH>d97R^y*^p*HLbkD`KcDnP>?+a;tPqGnz zbq=n-vEW50!&|QxeV@YmV59JStiehe>jbQ`LiBHO7uLl1D`_qIiY~s-@Adq&@yg(9 z%EQ0aoC`C6gS7<5x-CzzmZSb zf!bJ(*OKLU9Z9sN{6}kl(!K)L82zTj^7oW@?Ji)~5ZUcgqh4Bz`rj--r)Y*>bI_ok z39B1HHq!c3!ERHz=7sK(>4$#g4_;|$p$pu8N7%;gqd5%U15PU*f!}EjufxNq8}K`& z6U_(GnM@I75}Zk=r!?!+2{gEv`lSQ7wfkc1K~*!>tFkl?+0D&b8&2#;Vf_-Ut5ogbIK;1Eo9o{Q5+tAwe~jq67`#oPMd6PHI? zW!?d_sq>-RK_ka|WakLcHu7g)z6*Q`dq)IaJcRyJ#1ldfFX9QIhjWaN2yyI!SjRsf z_6Yd0*8$d*fH8U|e(OQI&f|}PR=P!UVy=Am~c@qK_v~Gu-P|UxD@)r)|zg)6f(l{ z?gLt=7hM|h#lRwM$BsmOWB7gXr|-zgO?SW?<7{FYy7L&>o@|Kx6U(%s%#A2>#T^Iv zi~7Hh`lnS%>ignZh8IwOCvcIw*T@09Lr!OjR^hPDMW0+I!u2ZM_rx7JTDNfUr==PA zlG;eTO8i86c0c-x=9lOU^ci53KBL*7@j?VT??Kx&*OXT$RFW12OmZCD#N3} zoPq3#cC}}C8|)QGD^4|>BY%XD>f$J)F&>KuX-;$jn-{6Td@nHH?>4SDY z#uM{k9|a$jq4yTeuw+@tUgG=Iu*^?G9;|bV$fs*IS{qJ&8p`9j7dYyT%-V_OG-;1; z)weM#4~QQ9Cj*x+xc)agp&jnBAVWdr%$$ zTL{@dl66jWm&%R~VeBfbNzDVE{{Q0dvK#cnipgRrwb$l%>!&<^mxkgpYfwf#;Hhu8 zGIOSB@54yf>mB}7Hyd^D?BbMdQ-pNh{!H%Rx8|u{z+ivvU`TVjU4MyY#18_WzjE=q zZesZ@E+3T#-t3_`A9RU>unlPYfEN(_68fT)(vu|mXw*EL8wDP+z9?p8H4pY;#xbnziAJI_UawN~14BTw5gNd4X4;EPVIEl7Urog0Jj6!0fx z7&qOr%s_kikmGE~&Z~A_0enGuP;c1oY#-*ku0M;24{h0XvWPGOzI~9xK6t%&Bl!O& zlp+2H+~_8RHzUsGAC?^WN5GHpFi$vmYQLii<&9E3S;~J0;O!$gC`U4jw|2uZ<(|BIOf*)Y!AbZr4kRwx&{^_&u0OuzOZ>+OPK2X^Z`e}rR&%y(FVdXyb z^pM&L{V<|<%7e8W$6A16y~tzRagoYneM)+FG#&hadDFtgxTpNl*@t91KUqUgVLX55 zHY2!C~N+%DubyKf8b1#GR{n4r0nqaBtP5ZXG)9*e#V(cjdk z9Jtdw8G$zjW`YNev*+mL4ld0l`aBkV8F0;N7gq#af%)&VYkEDJOG&={;B44#Q$v#a zyblkh_hCKNPxQd=BHB%Io>Tv^E2KbOW$0!k_XjXva?E|j>$QmRaLj#tdBKZr#5;7> z(HX!Qb49sju?S}a-%VFq-lsg}b|nPhms>X2yaXq_DTV>Px%g3nX#|JvOn4W~p#1Ez zUhfBuy|B|_%)+Ky#C$+~+tBnWo<5c*ab1aX$3d(%)WT`yoW$ zh~y)5F6x&e`nLof3OY%Sc!cH+vOBWxyL5uhW?_#0C}?l{(~V)Z#idi+~ zTOZ@x+Dor-_{{-K)8cR;ovcW3U}q1BFGpH)G@p_E(+8dWPZ>cvQxQ1&@mk>ccpu1| z?%H+x-74ET%+jM+uh4!@Fok7;mwPf@;QeFm=g{7d#5j?#8A3t?v%2qyGxZ{}y)5r2NHLpXM-L$DlV@UQyut z$%C-N4@$pz*z?&A&rcc8&(?WGjQ>8Y=fzaa`>o4_!1%A575F6g3y=vD=|ba$>gluV zea+gifBJmqWYGrLg!}W5({0!vYI}G@v|)d!4K_xi%^8cjyfZplaxAxN(oa%~x53Ux zyhgCD-q9=00Gw;oOiBGt?_bd~WZQRz_Y>J7o|^-m7jxMeyPBo>rQKk`8wHxeraLGYX$vU5zat31K~`BGZ8*Zd%}9HBzYqslZ%^% zWEnE2A7hO|ec6U!3Wxo#fPLq~q?7HD(#bYM?KSsdd}7b;_0&ta9<6SJeQAQN+Yev2 zKG~(y8i?v{sp;}s@yx(86VIuqb$KgQs|-QkBHHqKdG*?9Vh?zHD|8v6bXz&sf+rsFvUPcxoQw6!1bB;b+WPVEz*Ljij+$ErKYHxXtY zFcTatyy=U)f_VXZe2`VC-5J_53{8#^8!PQr#-3RQLE6AqdtDj1; zpU`+cQhyQrb-3{f&8M6!;1BJL#y@_XYHQKl+|zSAWv? zr-Kh5&!|ltZKAa@Z;&EtPm5Ch3UToXBr~x-MIJR7Yp0GcN~))bFx<3L<_+dugdB2} z{6-NCvXGM=o;03Gcxv$E!B-{V)DJw&oDD%?j^Ufp2RY+(l|KAdvt9hea(&oSAU&DR zP0(7I&V*3;hT@=Hsb0v9q0OaP=ug-H3)qv(cjz49Y+!GqbuP(fDxZTa&$R^J9^?s%a#rk-%$bm+|6qPyj`&#L6bKhbj+%)#psZNsFRwo1vICv%m&y@c04)Dn<9?!rZ z=X#x1FK!HYrp`;ot{t=bwPTj}BI!HTSVo?6b8w>bnx?cr~5R7~s~vqP}@+;Gb_G z7oo49ZI%2NrA!8WDoFnip+9i-TAe|}vV(Mo0`*JHRdS`7CDljVoIC(LB*w`A+RU&Y zR|c<=O|m@8;J0D}syj#HhV~2?Y-XfqknJ0Kbw+}Z`$<-TM_oCU(Ko{P9Lg&6tIpQ= zq_6Y=_C#HUbQtK$R(B=7RafvJL>!F=(o?7`%?G5Xk_;I|pX!_Ll!a!X(*EsV5hNT=(c@AS_;>_wlNR(8+&X~@1@ z{N56Wt#SC{inJMV+%pw%Gvl~_isSN-0ev?aIf}5MxLuB-ZV9{%Y=fI$>JYSFK<%Np zPPC!cH)Vb*u3hSx z9F^JAI!)xTrXsnOL%y8pmNu`&?*ZWVfJe4y!tpumS(`uO!IPNx>AV8zJH<_Fqy}G* z9HBlXn;O~e$OhMU7HmF<=kt55FJWtML*0~C#=Mt*q9;doH?#lNU;yweKd`5BCBUJ1 zmm{r2HaCPvh5wKq4S@QD`<&ZHE94?nL9=ZKmG?`+L=BEA#rtAUdZ?`+09 z*2{GM#Gbt>3v2fyyP^QjW!MM><|cvhXk`NCAA$T@U@rh|>|dO+>x_ot+Jk2<6P|$m z#@cV8A7yEOaI{_tqE(n~mr!`E?JzW_%5n?K7}&%K--c*s%u{W$2zqrsvDDJpwq>rf zqleHrsSK@mLi2RamIwS0<+-`f!Y-p8jxoa@y(UNFh3u9g#thl)^K`Z;&3FN0)1LLf zJB24x9EU!I_vvvQiFL)H$S7t)@X@zdEVy-B*E)e00W)Zc{5o4_?J34IA;mXPQeWDoaaKDQy8GcJK zwl@Av>-AmGd15%D^L1tn>szX4;3b_2SI$NL1r_CE_;GpK%eHw@E(8uXFY2cC5YG!s0{fA+ve;E5rcAJ?J=?Y0q;s&@?u}vBCG`XD#Tet8Av5Sq%iWDSOYLX@f1M2Z zKOG^hiB7>oYoca6v?iLkMvz*2btu0XvXyL^Lvi@|IQ+{v9FD^;#NqZh9E`&q2p|15 z&cy)6#WSJL%{Dl%)GbJN$w61|1}~lry<`~SR?IVX;IrxY{S1Def^a5yvKb-iFO;A1 z)-jid(kYGhIJRzMkS7m#5o{X#R+i>izjCtYVf~7=3v3QGZcjiBOS1D>Ik+2h8p{*5Zkm8lQvAogZY_^Gk~XM6jqCk0caANIr?YR#JNu6=kG}lKdCZ@ov|XV^6dDwjhC1#NLO{+GCf-@Ggtt!7gXd!&9Ajm%rh)_6&TyKg(9S{82m0B(ThK z7Z(DiJA=4PBs5^l;+e-qp27Vs#^_7 zeU58Ci$lU8!IiTeGW21ati<{Cyb}zRqqbQ3U~CnqD8V)}JGMElo%EdzxP*hDv<{(g z-kRF56lY?S^y1kV!*LrQ#a@?fBg#;@;*`b0g%=&91Bb1*4}D7UY}TQEB^vqYM=F0c z&Kk3?@L(VI$3mRH$a@H90zejtfHmk~klw@2yV@ z-f)r4Qwx3~8j>6;;QS3Pcpj2ZA9V7mGL7Tz)84zT6&&}QIPO3_io3cT_nZnb{Bkq# zgu^jxaeKb}?j9$%I(lT1Rs^oeJAcoi_psuFQT4<^%EVCUap@k zLZVTO3l3@EZWDgfK0d-Ee?Q(6+U&)>Av#aO2_D(SA(QOBFP#BeA-sOE8Mb=w$B;WPO}nE!8g;9OqGspf&yGxPz47m*5lj zLjFhw|}?_o(8%Sow}INoDy-hA&@*@v#Ur>20w% zh7?D#2I)n-Lt+KBz;n)IjHi#r^SY^+*OAx!bJpJ7iXLgs>0jJx=WLow)K6S|i20kw zYS{3;IK2GO{PLX3L-NtQe5;iW=6}a=fWeaY6`i&$Z&)Qv3*<@brB)VOS^I2U59LqZ zsSjhBVxBpa?(j(PSrOy2%I3BA+;Pq@BDs&fMS@M|TMxoP8w#X1Oi|ea=Dotn&>x^* z>?K}{>#7B>S$TMh8@KH5C43L-OdyjyB6d z`-B(E^(TrDyiBy?#7D0dJ&toq<$AOM#A zuNFSexRmP~MRYpKw;U(<>_g+TjPa}=cesSDNbi{}^gj3dAbjLekGVJ>yh8O5Odt1G zl6R5^MJiw4Abgx3<_!vAovoKs{DV3h>Zk4b0e^9@O{S_%uE{BI;?7{idJ@__74tLY3 zocj8BUQyq0^%vK(boA04nVjyHdmh7?p!RN*?Uwo%8-uzZX|Wl6{}^b)58n{n1Nhdi6tUoUdsE_lyj%&?QV{r1-8yS3A?WGv5Pn$bBT-{4NfBRC6- z_vi-0`Fb}85Z$VORSF!70=yY~kEhhqDI)L=pNTUTSdZjsp25Dl58aGIo^iUbcBbYb z*0pvWhB9<75B@3aT}0lB{FqCrK691R@gwjx?g!x97}9WOt%x#3y0Zk{<|CV={pJ+q z$5^Ggk2hRP_X_NsM{%@n;JDjn*2eG%7U?GO+Mi%foD(BEuHrRJjE`!>89amWfwbbj z@oBn&2mSj{H`+`0!|2SUzY6y~T9pXZmD2AJo_U|EpLgU1JNSHAn1_2R_qelq z6j%MLQlLtKDh2*8d+!2YS5@bIuXA$F+H37|(l&>y<(8!7B84^yAW|Jz3DE2l3UZMd z#>aPP0s<-&tmxFa(3ODZoKywzGmrD=%tKpb=6OX$Vcxks&NE#tIyomTf;gk2^HE`R zZt4fH-sXMBvG4D{);{S;nlufx^x{9C&(7L=?REX_b>I7}FDt+bumY?AE5Hh{0;~Wl zzzVPetN<&(3a|pK04u->umY?AE5Hh{0<6HRsldDM=)Q3e%W?kvOZeY+a*qK1<&C$k z|M*-wOwZ>Y&1TL%^Dk%C<#4mjU~f->cmA2flz(aeEZuj)e-CINAAJ`HGv#8M&rZEh z--OM?zZBp&9_jo`_obK5zjQB?e`)_F!~Dzbd-E^FXHs6`*M$H6WnWAZ=3j!f(#)<) zzwI4BT|Hd*m*RoB`IqiPnOBv6X;)%T;Tx@VeSv=|UKh$5eK$CUZ@d%eN9@eG_?J)B zN3j3XnmPHG?q{JbJ>2-0=Dk7p!w__qGo z<81zf{<5U&-*~^!*W>!Q_m~24`i^_#{=#p(e-Z3N?lDiiJ zVYVi-HRs3Hw5?%`q7N`z)6K%xq`fzjQ9CnZGZTL6r$(Hv9YLH;+ULG-U0D`N0zdi< z>`Vd19qn@+)@p>H-_O`pfeks1-@K30?_{u_F#SeGTpsMBk#=3fZ=kP$9sM?y?vd&F znrl8?7{@sB74b4JPI;9k^!Jno1I{J=CdT0&7MAAE%S;)VZsndZMasY=K4x>6_H}9e zDX+=Le?b~Q?lrrmJy~BdFLUM5&C87NyHnaLo__O0`=ZnS?EW{d7*E6)KM?y1Oo9W- zc%(g=4=BsAGL_|M@f$ZP2Q#r8>34cmR*B{4+QRw%vK-B8rm`H(i8Het-SIQ99KmiJ z$DSmUEXUtZ+f39)VmX?>3Td`mgGs;Bqjc^s%Ta(87~^-`WrQ~u%h5fP{?^RlIqWCP z(LNRYOtKu`71AFgKJ%?`E(WKw7*l4Wq2IcL2MOLEJ(uY$M>ihqUB`6)Q(2DYOTnGR zZ}^&jn@1eWSBvH7zVPx`j^YR5cYdR%;Wy&=?RVr}8Ou@pO9;>YYtUr;0J9v$b7}a` zhw$fOIf`$k?!TR;X9kv|do+}7TFV#*PhtwoarNQLa&+I=H_LG{U-(V4_zZUW}oi}qhvm3=fhcsJeHy#n}#@3}p*$R%!Q`dCqR`6Dy0>`Cw2{lxGuY3e^aohxd{0w-rJimf~`^nTV*v^C1l^) zGMsO=FT%bEyJjW}xx3Q4r;)(X^EZlhIJK1azj$T*OM95`FU4oke_^MijKmFL(j4KdZq^ z#@dovBJ@r%6qm8jt5^^fBXChI_H1u`*kwIe6@HRF>~l@_t>}}ki#4%B>AqT$(>t+G z;A;4#Ik^6)%VLK;gb{1nN4)h3a-$IbR5w^jhMQwGaiP7NOLMy6pZp5k@2C3|4~225 zYPx@{7J0gVs-}A%LjFE9e2d?E5zONpab4Yi%3>?h)Q|HIebr=J!MmlrC&=ql*n^PH z$2Z%&-&e2C=EtwGdDV%7v@k*wiDw@(Gw16AZh1__(v8OM&BYtZP z7HeSydx1lr2y^XmyeB25;)gGFU`*gWDDAz7cUFH{D zp6ShFf75J)@FIjqYZ4U4q5Nb1<)Kuc<7Nd|0akz&U700GOEKyMc)b z?r-$qTk*TV1yX_g3wEtm;Qo59;2~yZ+O4lHE7Sh@R92?_i=%^;DIPtDtjw>btjxci zot0@H-8U;!JT#S+DgI};wtpPVqlT54o5srgariw`8?!R^ZzB9F>MFvw6A6x^nSUux zoSlDZjz2*B%M+&YFA?s6 zUMu}R*j-(nSUA2#J}90@)Exi zejmd8%NGku+$WW|1PAt1f~n6I>V#!NDRBhwFCWwP9)8xhREWd5Z*Y5SVOo;~d>rVtM8u@NU< zwp#Y|ua+mDut@K^q@!@MxHA^%K78N**03}e&5wV%FXp8Z1 zTGDS?OkeoDH?bw{CBaVg2D=>}xmriPTKfG$%$E2H%u%C0?XrZnU|)CgJ~~J{ZHdy9tgIjdE?Q|wp1Erao2EO zfzM4ktEem!uwyItp&mwB*09b{7+I_1(mmSmC)|cI)NON7=bQCF$>w!}dRxYUXIy*G z>e1JL;dZUjw8t^ZHr)N5Zn&}I;aP?_9OA%+!-%6X4vU^f+z4k}bi~Q2VBe*C4p$JS za+~5vg?iPnC+3^kB#Q5ZAGa-pE&g{fufjgZA8r|puR=RQdr=oYXSMlJxJTt;>{9FN z4zU?`;QES>-d~9Cy}vNIZ}kgNaR+f_y$Scz{dB_5yW!`i`wA(mrt?3i@k9Tg5XN5o&?kbuYn|?Y8b9>&!QEc`(8pdqeyDxqW%5J8 zcctff!1$rhhVblHgC+-@AG$LQKjp^G$qxk^mhxvO()7&054C>~%Jz)>&?^sPe(0C> z%?~x7O7lhh$tP2Os0nqVAHT_smb;h754|RY>-nK?Nco}H2Rr($@1f;~-W=D_b~X5+ z)Q;6V*6W!#qNBfU_4r+&AzIwb*Bi!s|?QEFO^J zy|eH{F9_U$eey(8w)p65Jkf6i4QJztnh!NS&p(-kCwlt<=82va@^vKfMBURVM}v8y zM+8rl#v8N!9Vq^#IZXJM?lWkAnSY77kCQ4}^mCxbd42a*c}7c7o{8fu9IwSu!JI^A z2emr0C^Jz}DKHEh?!$ZBy~Am?KLuf&isLjK?KlROVyyw;#R$*l*B6N=sn1+3%h?V+ zSKJME)5A;u^H>}$ zSuOkfy0k{$qs$AjqWM!gH|l6vEt!8=R1)04=^V=%)_$t!m)+Sj^DoVQ@-N*PuRj0M zGXL`E<6myvH~;dLvM`Qa^%VS@Po5A-w-GL`-Wo0SW3GywfAFS$9|K^z1 zuoTu+64&n6$NJB7k!fOII%Z!UHtb7_HR%TX(t?Bf)mY?C!ZY>EvwPRX7W_9_7o%r7 zeh!}Za`eAg*Q;Ren9zDz&xqeklJ3znr+anud&#rI1$C~A+!4&aG%?oyk;m#~nS!!b zmPUtSqr%)GMqUR{zOlyX*KEhzOrGvdv|$|=TJ>jpW4#Rez+JyPJ+61)Jwp-W0BBnp zem5VsHO*SQ`;|@p)9_RO4L0By{PiOZ-Yw!L)*r=3<3Tmjn^#X@ZT^X} zEaP0`T;u%8dwcV(IB&)IhjG3D=L>L7{J&)Pt zO%3;VWbw|R1@6cV7=aVWX8|0+q%`dFP*2_H)Q!V86ckp&Z^ORfcSoPgQQ9dCT7&m- zBF%-zT{dpHH&?v0H^2Hxmo406+_KQ(E+x+}+w`cz4;r@g; zeXIa0zzVPetN<&(3a|pK04u->umY@r5T1Ye)9~)&NZ?bwu``NByzS2i7INNl=HFX=%2H zJU8+{-}zCVs@padidl=VLQxM+u~EI(7U*|}jqd=jJjUcdjDyAyNy-sVjzM1Sr{fs@ z3OFc?oh?@GT!?G)N&i0C{MA&ZrTO0>{?T~oS2j+agYkn4fBiWpXID3_h9~RjG z_=~f69+}NE<|jd3b)Sprd(9+mdwjmkqqF4eVc+h#&m26arTAK4TAF&$>bmszsOqcu z&EMaL-}{-*?we`pHcw?*x=rEQq~_7Wv~(v;Wm;M=@TmJ_re$Lg!R9MfAZo|AWH^p$ z{^fBgI}+{S=rj0cuFYZWxjD4q_@KP{4Ej8L2S1AWqyM)3&BORTlF|L<=2-RNH{)*! z^X;fF(PHu({Uz>27+XaKzZXUvo-z3k>GiRQ^KSh1HT|BA;#BB=B7?E*yKQ8z4`GhK z8)HiJz4Sd`)cFqI2ahA2k(-)Mr_wx}1$XE_B7B!c@r!gVfYN5JZlrT++6>x_qm_SY zn)#QV#`7GYL6Q}+e?9r8OC1kR%V1~ zHNxQAknp{``Q=vH13nVD7MMotb^`nUXZ`nAdj&Gh!v5F(e*<8DFEH2K#qYznioMdE z5cWR`-~SmQa+gc-jKE>=tq0PA?@h$DFwG_@u7-K_rBb|P^Txi2ZwB#q9j+a1FCM<7 zBYznSMvxF$3dbF5Be6*2+_5eizTRT5`VR+x(17fGT--PnJA*;kERwo&L$ zALpV+KiH+0eI3_sOT6rBFwJMe_cUO&Ar)d-Yp+~Z$mnz6c3GiA-wu<~;*Np&tdSO` z*%iKLGl<*dt+qIX$x!;0qx9t97N+&)2c*OIj-o9ik2@Vq!83$fd?w6oMk?r{a`-+R zx~TR|Qb895UDPg{Pf}eJbWz&{zUd6Q+)3e@Y*7`(@TF!=dGNPD-fo+IJl_| zhy9k!y&-?@)b|ysOeEM>(w&@g^TbwJD?KOGl^Lmuz4E>V8I^RtURUk&u@+!qxUi=p zeX~+V{HpXiJq$PcL42E>!G2#czM;kUK@~C)ZUQ$+!9^4nxl2kH>vFq`G&Co>d&#b6 zrLMxxE(>MTo)b)WY)IdvyV6RnvxuYgMqQ`45LOkYTGT7?Eo{EJ5aE{kv|5C;zo}R1 z(r;;9dathHUR=6Ot2bq^=jNu^{y3CR`cBI3&J-Kzs~{~8;HW;c3E?@ZM%r}JV^Jo8 z`$`6RvRmSWOfeK|d{bLSdPs+AY7%<`MMqS`mIB>xEY8sFfOzsY=2{&8L3 zwq`P}hQBi6D*HY1n$iG$>3)T@8^OMyi$YkG_5^#B(s#l2G<>pCu%kWKR7-Hzcn;cZ z@#USuYW5raWP+b8zQ3jCjPHO4$b{PwiU;|r;5n4@E*irzY2S%wlU|R(-HRENzvDys zONPz|6$8($XSuGDSvp78Vd^wLlj*W+Vz&tUY$2{mJCwaj344Me%vfxWlc65$wQc3V zgC?t^Y5CfR+wwfzR_EciJ`cAj2vh0<)vMX^R!-ekNOL^v>U6&jb**&1et$!kzSm9a zQpImMDhkgJb+ZnC34UXu(f;UFp>9uVyN@vHO<`aI+NtT@hd&+fiMvexG}3|i6U46& ze-+P;(x%K%T){o%2ICr;W-wMUT~l2UqE2Ow>N0&-i26IFOqk7a8Szj(HgC)nYjh5` zW%$>nwYuufyL8=~>$EPA{oOts_r0_Y{O4d&TUp7Z?c-DHeYWW(_>DpQ zxM{hf$9d+EuT$8I7kP>rZuH}}rGW43iAmJBU%`FUod|i32G*HEBM*%>!GTRg9Fz&P zlN3&6#I(>Jzey4KN$Wrb^({tz8`o6-2DXT73^&bwDyg4FeOB$mQY}D#gz{1DG5Pw( ztS;lwD>KM1bfz#-$4T$nLVQEp_x)#4|vilM$Cy)J9PsvnA)l zq;g4l^Z7~p;t=LO(wv_?%`NjtGo{z3rF80KT2ywERK3uum+~z`zDw;eH$hMAE7+)K zWTKu?U8H)J_Rxg@AE1C12(aUp^9)%ec=JCfuV1sy7s75^t5LXEVlEfqMll z++zH$b^*pm`I+6-7Qr2*y@dEPGrLKS$GutNiJ?J)Fp`qMm;-HHNx{4d<|3G@b&U3_ z0=t1egEm{}fu7-bpIW#rbKKwL`{Xe^ySOcV2H;0gJ2{4DmMlhIXUWF^`kbV5D}K*7 zb3S9bf9mZ1lQW=$n%Qr1HtrQ>xwm|)tU@DA?MxfoESlM!T8Vn!gE0ukO!Ry!XulNl zS)=x?6=Uj^sLLngI2Fe!I8MXSk0Zg+hvQNlm*KcPqiRLOhxVI(yZIfAM<~2H`T~L9 zZzdzQB|&)PhT7|fJ9;i-XpfuS)!?q&N^OG4CJQJXXnWFdDNOp)2&WM)vF9rAW3!p! zjW2D}2WeY@S)=o&KEvxm&x+zjnTRh!Jx8BFd8KDUCiP!r zlG`$lq|X+}eU;9i4gK9@e}w*w&MO#`R_XV(7iHu?+AmepeknoT=($(O6gR~_4Wt`| z*QpA=3`~{W?!068)FfnMkTaKgQrl?}*9i zPNOy0ExHrGIVePEx1ePU4q^)AvofK);PBT`R;ox!N@Ep=w^OiFlICwni}BAFzva#O zdoqi7`$At!d1|pz;YfOnu95p5kxTm4=*r~zZAc&dtnQQg0rb^4syHf(d_MCDwJSLH z?MLaY7=xodDZK^eBA7R5y&7rB^`Xzid?W3f>c~%w{0!_`gZWd=k7WiB-@tZUx8$VA z#M@S}#Z6BPRPKBXi2PhkmXU#t=038Q5aA zF6Jb)g<4$Z^QZ;V^nlZ3CWte^v!Hy_b>kVS%;gvZuE8_98RLTd)Mu2%HR`h}=J%v) z%NkurK6D>6p=Z~(UMrcG130H=SE2C&p3xXRTY8o>f2C&ze=3?9j#AU&%g^?#C7$&v zsi_=iq^u)cwGi=bzd_%K`1SGg=)29PSYd2a8MV5GLoLntyea&ir-C#qcayJ!DraN` zTtSr+Fr7D*8I}q42lOmqihMfOE$kW3s$JN_I7ekgf|-$1N?k5}Jjkmu=*PeYRanQM zbN7ZYrmOk!;-DW7HjhKA3!QJz@jKHfrn(oWV`>_=V-DUt|5k8AV-G4<6o#Km(wq@t zRG=00(^jG`;~upy&GXw2()ISUbQ$wq?fX=vD?>J((3pRt>{T#V$Mci}3s7zm_rQ?R z+V_R{y=xj@W6lGPXAA9ttfAwMB@XFsF9<&lH#v&C(O%J9x^bN~ zfbmD|aK*192tjeu-qN(jBZL+12cbadNLb^ORnBR)4R2 zZ6C@7+Mlv}K0f=>UU`cWxj)76Z#Z6yO8*WVOZzhN^h-0cgUt`{fy_HE0~3$j5gYTyEWvM`um6aQTNa$>a3d!?WgyPu@Hqz?Hu{jX?P0tnZ_kk>~~p&*A)Kaw&26UxTfK*jB-Kgp*_n_ z`_VRi+K+}ch4XFlhd3(ZH)wjEl#j$d7mIj(v5tEKNbgvu$W<}F)}3hA(U#X>SM9<0 z1Lt(0&&?-j=V{!dQSND7yR)a+-3q%ir`g>GyR(|? z9s;v?sj%{N93411aR~gLatTb*Vx}|=W`$1&#;Z}H2K{>8%}sVn2fMd5*(IsnP?KFH z^?Os3T@7}PIwEcl<;(m{C|AdyIh+m^4F(*!7CNL{xO5BH8fvL{GHN{UR){rV^!9B`d4Q2)QY8kE@ zYxnJFE9bFx-^e%lCw=@_oZbPX;Ut+&`}Gc>5spAO{@n`v`*$ntpPTvJ3fyH7pP_dt zh)<;MO=cGNjrS-|3q@^?7FJH|MtZX%Qukqu@U-yrDfP6G%H0`LeG9B@jLB2K6T2V6 zxacyhy{`ZZ17oa~Rp_s=o|TSI8}6F>M4BH~W6YhfMl-PCJ{hC@(41_F8?0T`F9~)P z8XI7Jlo;6c5u+#UXZ+egoc4u<wT&_2sf$_@|B0GV$r7+EXb(hI&yCtrdeqB@8 zv_4Mj?A0No>q80F9(pkTx?0yuZ`Q@WI2R*~DQUo5u3lQ@{Z5X>I`IyrX?#-0o+&$f zZr3~h!s?xw!9oG+x9%q!ip66@j?y2aPSCh-BkB;PuY&Zddqq~Ej8sOlNQ1z-AMT^Q z-AL>8W^;k^Sl|6zJb~v|#dxNoABbYyr+X9z-P?hCb=;f4y7A7QAx-hBcy@QSrZ8yi zOJURyhDI0#gi%BozRV(=o!izFY?_Bg`J?{gQ1lZNKlMEc;y)Dq!St~frH95^6|{M@ zK3pRcWw@b}Dq#$;!$|5&r@y1r)P{i{?%P7~dEbV$V=UP0PKjZ;5#zEl%8kaHliCzi z%vOC3#&?L@!abguA5X-oIe_ufj$cMo+)R!Ezyz-$O{AUbG=5z}BMxd)DeeN^qwc_a z)GP2FmEzUcVEjq-0DV0%{pg&+rt2EkKPm{T=Du4{7}FLI&W>zL&TD~smNey^@=Ed6 zXbgn5f5#J67wEk$rKJ%LOd7Y8kAdBYi6_wKYn;h({xRTUKiZNG)GF^ z#W{>)hVJ)n%YAUS{r+5eoy}DdcHJPI2w%eu+T;Z^7NT~>|D|g_$+YzzKL*2^5c#8Z zqS>A^rL8W$hw;2Ywqdq;b*L#tDhLye-32E6JC)Dmz zShODYr10rY?sYz2KK;|bOZcLZ)i#uA^s9|=jJ>u+Df54P{rC5%ykjjwn_*dosg|t5 zdoJj)1Zyeht_tf7=i+=?*pqF}MR0TNB29hs0OG2kU7)pp>_Zh5Xr1o$QquJRg}nyP ze&~MeCuMRb-4|B;B8+hx;rV_S?M{L|c;^L*Otq^>wr^Kz&^T_bNj8 zi<^5A_l0T7tEdKI_}KGU6)3Z@mTnuoh6yl3Vyk8>C=X za8!4-_-Xcp)Ct%Q5eK;ro4A|Lse<57>)H*K&;Q?Mb4z ztT?EDu-N2Y_*9sOewO^wc>j6~SMX;SisAx_1ABqd^)jppKL-Eq1X1jQDK5&WWrbe( z=;uZ>zMqlHFei8?#(w1Xv&Vf@uD$LVxeVhAiqm2au?+D(`kz!;gDMqiQ+D#V>$Bq*7_a>t_esK01^`l6y#lB;7ea`W{ z@|=?{*5{Z_@j1^LdAsfKVTcw{{1N=y?+15xAU$^?PE!!YbCITVosc;&3+=y!`#tTc zKRl1jU8FJ0yM;362VKN3qvA_m`!J``NLP6qzWEpq?;jt-w>UPRY6QQOwl38xKi6`v z?ot`q^>;>gtzM+NkoK1{uv-8-v}07>x}gW@@~&cs?nYVd!u*N)D@wziKN->8@cS;i zG^TkooqygfiMzfc;IBikILF2g-|KW|Li*i*g!Gz}eQog#(~4(=T!C+!R$vTI>7sDy ze;3B}UFhe!eqm)7`nWE!Np_)a>q0$+UH-20+oZ1RaJ^ILu5?Vl0%>Z5L36ap_4FlZ z|F8~Rr~ZoGbITmYco;vTEbnW5x)BzoiT_vuR)7^?1y})AfE8c`SOHdm6<`He0akz& zUWJ)g|K-1lQYQtr-&e`&i90{`-!lz(XsL;mFl1B+o^ z{L2poKg+OB;QsS3|KO1DFU9NT=3lz=rtvS|pK8*vhkt2KJM{cZ(UF$T&S07o4i5iP z{4Cvz8v6>GpECcF_PVCM6_a$|emZZkIGC+#)OtV`^T%dAV!kD&f{3+->HCPizBOlY=9rAl1_?Xnk&Bn(RKNOyiX}%ZY zBTgpsF~Qe(C45YSzT;MEV>U5U zUnU<@tUUVom`5yIaz0$iOYZRNDF=cp=?15ACCyR7m2`7(CEXlcNoSZV$y~`JumY?AE5Hh{0;~WlzzVPetN<&( z3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPe ztN<&(3a|pK04u->umY?AE5Hi;Dk*SlchBIy0GM-e9?Abc^*RFhm%q7m{Tu_3S% zP4D5yzqBudf9YNp{}L?4yww(mFc~SFP)=CsaxM}utv5d)op4gLW#n_U7`@z37=TGHdx|DzEn)sLQFyLR> zlz(Yc{-rxe{7c)!zjVyM6b(+%!Qx+)@Go7;za$P2@h;;!PD$hxxR}4nOicUb zxtW+|=gdq@H^EFy#Y{|@l%!{0!;2@GN_DX8;}$S5cdgMn zoAYCuUlk@Mb1;uy4yJ8k4(7|@V4D5lV7e!ngIOzLeu}wX8D{dJDAbBB0wYvC=8RtSOvtlRvnrjNhOi>R+!b1-N@99LzO` zAqO)})6v4gw7<_B%-PoXC)tm9N1zQ@?js`W-xaincLhmi|K1fe!Vw5Z;9Y}&e}Q)m zqWyDH;9Y~jy9V)+&71UH1G&o}J|jf7*}cik;yz_mil>Dl_O2FIPV7c{vm#RWfv^3v zko4k8J#D0NcgEEoQ!u~WP%NX4H_|q-`yr__m&vkQ5szVAO}DI)Rg7Qbl&{`!#~jRy zu}-o%j-fGWQC+|s%tOw>TyyaI2`c|Haxl}l4|adR98Bh5D&}BH4Hm7R4`e&Ajxw!G zFb7jpJEbxi$s9~0mzhs`PUef~tCtr=&YmQS%Zh{g2a8Sag-_W6jfp;coQ>9EEuT4< z9bPLcKbgCP^5)(6j)pmyf;pH}Q}~Y+Uw zQq0A9g#UeKWJ)d*w!u-p97mLH??tJ){w)?>IFYP^nf9cHO$G;RW zgMVpW7XR`O4hjEK><9nSoi~+#X;S{BY2sg+!+?J&QvRh#`IqJ(@h?Ra|I#r3@}ToC zU4i+R%)dOi{7W-W{-sIzmu3e3rF%N?FHOq7)L?CtX+QoUoBvg2U7DxoW?hP>W@cU5 z9n899)@91E1kZw5m(#RxTLRA_3!X_c^RuB9vo4i56^zSM4sX__W7g%X&bqWeXVxXN zE-}8`vPRdzp{qaH?zsZ>7BFf0ZqOPGHQl#fE18!A#8U$!twJ0rjOoU3UBz|vL6P-i zJcOa5yiCZR{L!__%Np3B8thP=9n`p#3S&a@Uv7*I$zDqEn^sBvF{^b(%6iITOSa#j zZ$$k1_>9zxdS$tEs^>k^`jMKgy*Ha;l}9>9t*+rvOEW%A%H0xIkS=9z@vH!~WRD*N^u{b{$=fp<380ICbz(BP*WgqkIiRG?()B9vT>DR0}+%#A4Yx+7}Yp8Z&+WXJk>IkzQLFnSk0`e>OvQ3w z!;1dQ{#U5C>P@{;mwroEOCleaZqw>b2oG+W!x#bMDd~Kpt|N>JG4SlBSmc;{`Et0I zZa=t}=8Md|e5Kq=dpC10k67-dIruy?VwpYUI^v~hCr`)Gfuj?LQ0t3JU=jl~=`ndQ zSF^-DB>ths`N8I#CB$$-`z&q`?X&xvP>!XwGWxoak$X6fWUn0U76s7~+WZyY9+u`Q zQH;R&83oU$AO6j;!N1rpitUbgHtUPBqgQ^Qt*E7WXDsev?j>_Cg<$UGn%K66del5# z(gla=G<6Kc+{?{{0yL@belFf|3Cyg>O^jTvclHeF!YYg#;|HP`Z6tKs%UwKyECWR-3Gg}Qaj>+QJ6F*nJMmr-5)UbavI~XWTTq-9=P*|ty5GAk_rcxv`*Y=WHdjU1b%S&w ze0qlg7V!d_lhPc`|7FEO8doHJCa-9m;pfCI^6c?rLb?)|K5xvuWbP%_BNCK@gxX!4 z>&~mSdQwQ0!8*XbPE$L@+{?b~GK`U#dkJpk_rtv54)nEmX24P}h~l}JADrui%;j5@ z`?qkvr=7W%U1F2$Lf_B@4t>`zZ2qp4L(kmHMrXw)E5Hh{0;~WlzzVPetN<&(3a|pK z04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&( z3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPe zhmQhx-_i5R_?LI|>^n0@0RQrL&i~23%%ubFPs!)2&c8grtG%bI`=Ul7F6_E+===-M zYg`I(mk@vS<0sx)zUjQ~o8Q(w2b6S=w_o+M`S34Y*Ma9>y5A4{OK}+TFU`hGk;(_{ zAxh@5uVQb)jY5C=I2S$o!7lChDg=9I+1F^#!q0d{giV>5%UXNovO-3m1Gmcx9r|{d z;u#|y_5>Br8fjsgUD%=+e?}Y{{-wDfumx%FNlHg$_g1hfS|p`NIU`r(u%G%g{-wPy zXky#nSKN(#$rEBxoEn~?5?irn>vK|FiM@o2z4AWKop`;j+ULQu*bDjEnr<>DVLF@0p5liJ_5TALr(Moy+YG9E>e7+1*Rw_pH=a*qQcF zHciUGw8w|^O}Z z(W|X_2yl= z?#*>t7s&o@ACCP-+6JZ^Olm7DnL!_?NcorcFM}J}JG#vLOKHD6H~-S?oSA>=CYXQ8 z{7dYUU6P*t#r(@@T3|dBQ(HG14-I1n>VL;@#9)(AI~RAp*|%k57>gu}G49KtZJox> zq&9RwV9e6FRVLY)@5gli)Y<(fXJAaIX7-z$jeCVz?k(RctBcU)f_bLe;AYXx?$pX& zsd_NpKprW*6&kZ3pS2?L*^06DN-!@^#&HDjF9q{2Uv>Va`&r;D5nHhSQLqOw{@0m) zu%f^YL^(=26YvNlsS5oVccU*KF*)67v?hDn!@m$s;~Qr8@DGV=7=iy6Ntu8hL99g2 zKvb{;@K9lFur~)Wi}?F6p1?hn=?cdC3J2IFx<>AML@w!Dqbrl=w;_G-v${{}2dpmR zsN$%g?qJ-WPf8d!;k;53dZ6@HjJp-gx4>Kk6MVM5OTI`X-x`Gp_iuXrXTX_CuHweWJ8 z^odE9qmelkqg@K~qs^XwNb{Y6EmrGdPR8IGYH^v*qZUZh15T5fq|b=*P1lWQq%xOd z+_whL=w_`l(-@RlTw^?^ic?vY#J|)-Zw}1MA&m8yc_~QWqlJ0tn0dKp{)0JFjQMq7 zgJKQAttnK&avDRMF+pnrG)CxI6XrWDfi+R_YYalr9N%JHgVuk9u=ocq&X<^ZS)+E4 zSVJ(uFe>;l20%Y5{AGS3GXAD=g-;;5rw;3)umtQDMY-rmwj;4ey7d7~|QQ?}hl> zcQ^QFc`6vY)491CY+B#8f>TT9552Sv4BwC!g|(UrwWG*$1?zMVnU1)OJ`U?%KE4~_ zwuWoEUnl-nX}C~Z;5>_q%!ghY_F;Lx68K5pFY%se4Tw0k@Tb%8)It}1huk;Y@3IK5 zDg4K6!H2cZdTx_{7U;JqJr3pdv>$ELr~PPHQ#juye+a8GeuI9ff4!!BB=)&j#OsT7 z+#5i8$2vu>y3Q1ICs@ar!`G+}>oEoDvkwK!EXn?AGcO%8FZ0a2WacH!iJ5u1Dc*?p zMjIbAo>xihAH<}b0AG#9F_k7>B{MI@tI9xT<|Q*P72Y$}Cf~(4|9-g&9%o&A5923{ zZ&S{v0<%r+vXlK9aX(cNb51Zn$-M?AR24rjmB2y#&uQ+714>+1)oDC~Q-di=EY9|; zGioE|H)VQngLMj8m%yO3RbP|A`|Xe(uxtGoGfvF`jG=e@GMeJ1hVa$4cC4=s%eaWJ zXNjwTbnQSst^j+E;?>vSy%WZ3ehi9tsB}(Y(=~BR{X1^E24i{fX`A$Da8D~K_jKZ6 ztI17_ystPG??YFLqQba7a3d|&HZW!fLsFHpe*LE6Ig<~^{$2d>&xLpK6PP!gpOGyW zU~TjQT0344*3s$xuLx^C;!0XKeN5K!KMa2AMpkJaB4{n<0ne-~Zx0&J85ZK9@IqQP zGxHMf2Y+zM9e&=n40E-$I9`Yc^>WPDUidyUFGY(e{s{9?W?n|c70(E{0^bR(aB00v z+p4aojqF0(2)?E4Lfgp9OIoSsKURPhUO`(U#?I2 zmv4AqQFZi6cS2wQhCM2c5V^~xz@Bi#juhDcO*rfUiT&S%*(3$_gcR6!QoLmI2K!F> zTwaH3C$QaRx_=z}W$ds-NLdQU9gDsC7m1uZ)_L)cem810JkRF)Un;(!4{5R2-k;k1blsZGG#b?6YhP^Fm z&rq-`Y0psAzG=pNLKSpT+r=c~la64k`=Q@Qa8M!HZRpPYH=C(W!x7B&LtraD4*@(ML{=l|8sQk;<&yRm8o)2xH_@`h_;a^S!E{xk6?h!vo=fIO% z1oqtHrsawr7u($%inI^1XJ`m$o4V1D+m^z%O@-$B72F5AE~?@f0E?rcVS|b5ez~Ct zW=(Da{1FNV`zE*eaEp8Nu7GV7Ppc;bTSPX7n`S?i)K8;6tM*~37N9>u`6y%G=laLM z*TSJ!W&)p!!UQXe*jF{ML~1Y<(x6Z;>AGSA$4X1w%TrmhE#;EU#bAv+hP|BK-_6a$ zw9n4W#1vm)Cg%R`Lml?Yc7CsH;=Gkhr%rOmW@RQ?@OQwBsi6(N|AqJL6JT6Q53FP=%VBp7nNaGM;IFCA$;MvR7s!7EA$1#7*N>9 zKfyt5eg$TY&YSv-8q!8>gikxhRq;h&s-aJycq`~r$fW*@OmbVsk@SIGg}AG9{%q*) zCi|mwtXTn1pbAz&d{IUYr2SGg?Uxd;t2{T7OmS1}(?GgWc%5oSCYksS`r}sQB@TY= zOTwpVCMG7cFfk56SvjCA%vP{4(WdEi&VJaiF#EsA$0f;Hm7>_0xV^$ZU zy+D1BiJuC7pVR617%W9y`YrThA|ID-^ZmRZH#UV4IE-)9b%Zh5=W5hT)Ol(vX#S!X zIX{Q^AYE@iOP6u2egCL*Wyr=88tfyKqe_pB$67IuS%9%O;vN_>TBH9QLwbpYG$qX# zFBcwnS?z9$cPw#8cY8tjF*O)>X?v5Py(yy&X^4`@Tm?)muaOMB%lO62|&$G_otEg-h)49Dde zb;fhg70kj=HYeNgt)UJ74p=nAH`HMK>Xh+Y{+Ppc7FxFu_%Gt&B<;GF9D+hM+Tn%z5KclI>9TVZ$RG`rhicUF_# zL#`uUiZWH{K)DibLp&UzVWdz1*0VsTUMc;#+p>)9ZecXb6-f~h-&O2TUcKl*l?eWQGWc~ zzqwDu`coaeL-JQi#|S${uue5%^o0G4pWnwRv$?Q5BPV)4?ceo~8-JaK+Z=DfZ3Soj zlW`q!&nLdIG`>dI&0#XH5@UO`7e^$oa!qKH4`x3>^@RGK1Y`3<(H~47Yf*Y=tW}}; zFzQ&1Ow`9lecoSwVS`ynEW&1Pp%TM#Uu;4P_nO)lv>~&x3CYbQvsz=F5)47oPIa2S zIEeFR6C$jd`))yjy;wk6cVt^~UJHx$Mciw!8yl>`TFNTi@r2a{Vl+}(uohCGaA-{g zeOCDx*o~NY0)4*5Ikk_~?Iy0m4ZUBcYdZA0;3lTIQR*(vVLfE%e($yno_Tru{kifw zo2w%1xc=8x(@lHwVv6YGo_7rmEslgD($MH zk5}1Tm#LhoFM^fXhBA$QwK0yd*S08S{*NES_7v~vdy^&ZmwOVsc#-YTotqrw0^%4W&vw~>h)66^#Fyv2CUMd`wL}^ zHOx;jVx_-dgfVU-yduUiv~HQ;z1hw!I#)ycyR$D2=1^~b$6r{zGc#By;C&~p2NaJH zIlo>)?`p{(naW|@2ov#Ca7|&?V3si!t>8!~T}!Zr(r5izNf~jK;kVubf7y(#XUQ%6 zW4@qZR&Z2zwdBTzY(CE6Iz6Xw2XMV?#Rj=-+lqMENN4;4#-Ga&$D?1!W|zM-A|L&4 z7^~yY9Vd!QTo{WlBktzz+tF?daUi&x=K7$eT_}nRD2|^8O_yO^_c7$logj)`FvUd~ zwXD!9AN|~jURKD+WtbDZ6JtM0$7hfGs9by9GjbWmY%jvC#T;T8<`j?q=T&j0Bco`2 zgbupD0&{m;3isDu{|9pI^?xrP{eCM$dz>@MbR(zD<{R)7^?1y})A zfE8c`SOHdm6<`He0akz&UbY%zQ z0W#s%b55}Ld8PD5UCz5`49BE>C-^7n^%%l=k@li2GXHW4uaov$g^rV46mX?x<#ncR zEA)Jre>sJFL)_Fd_PD3LMcu`jVvWwho+-yDv!%7V>dm`!-J9#Q2KPXh?)F?7_sz5o z{KsH6^DoUaDgW}X!adqEm-eP+{w4IA#=o>*o|}JZcFxSdbQ8?KWd0@gmM%%pO-oAc zS{vqH5<|{w0S1@ncg)5L#U9JlCy(KXY0q%9eR1cTefu^BW@)k*tj}3Eo&)G}lFqGQ zptu>Cp)uV*b$0*B8Q_4bnf)eb<6dEwd&{@VD)=_U6H#q&vuI{_YGtofJs5)^k2KMu z{*T)ES`qnd#XjXLv3K^#IEbZn3J&6F_2VF>Rv(T_ainZ5Vq`Vg0>sjy@apIbM9Q2@ z5MG0$)o@3;k72L#W_LBXD-+)Wtb}9%rNc($lvzMw(w|0Ljc}C!o0`&^&oKXz#xJx- zd^*;w;QV0nFWt|=zTh+QFKc+VNoS&&gLx1*m;o%@Ihaxt&ov_@@l4c0v>V%R z&^Lm^sgKXd{bpEWzkihnivc`K&$L{ck;K?h?v}v8G`INnaaI-u%DTE3Oo~fZ5z{57 z>|@?NjcKuMzu%YNo7!NG2bKl71>Yi}{se9+FumJ@$k??173yl>M$VtHXJ@0~4Z>^2KQ0Z^2$5Mw$>7|7_%*e03O`E4g-8@u`P4m>u zj7_n9X2z!deP(PX_C?P=QrCeUwOwd6oh!+VP0X&GXZ=iBJ7vbEtfJqpJh)tMJOga- zCq#AvY^A*z;k!&;+bwau^y_{OHcIocq4RZh$mse|qLWe&*ydO3dg;x&2!>dUFsA5i z!6_}R@_r{d=be52x-s^smyF)obGvTlj=7%%?ijJkV$8XTslHKJpS}vxtL_z91^!uO zB#SgKV{>0DW-9*)o(nTJ!Lx%F%-BSIV#cOK$Jwf{31z~s!J$3b7k8E1)W8K*+uE_d z3eI8?^W6i*UB$a5W!GRVkGhIDrgK&+DQ9)!VXMha4A$z3W33b`k3Poc5zD8X51aCm zJMgRz44cvo2Bu+yO=*r2Hl>?`P3h)fQ#uoL5zMC4UFp1F1$dd%e)zVGzR>_jReM%z zMyf3Mtn^-D#Iz`xlXcvWaerXf8m+TA|1Ns~_XoD)x+Nz?F6TL*6c+!n0;~WlzzVPe ztN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~Wl zzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{ z0;~WlzzVPetN<&(3e2s*t?O^UaqzwGUOx2pwKF=#y&3Hrmhj&=o!RW0+4^v?z5KE_ zUHa2w{`Sjr=`cN?bLn!x`IqN+wfA&&U)0d;!mbO4&cE=y#-$KOh(G%A6K^fwbYAz( zZ|m;fbA!+Jr9fsq_D{tAvKj0HX@rUFj==3|_{m~xMbZ9IY4g}~@zkQU-`pzQ3E;Bi zTHwzJ@lR9TlRx*%uxEQCjD4Cbe%J5A7WQL93i9iVkytI=zXztG`*AQE_Zz0!HPxOt zd-c;CST#r+_TR6cU?YQcXr#0HjjhKp6mCA_xv;3YqINo#VSmD())^0ZAt7l zq`?uuQXfYDBBrF;sGg2 zEydBIlhI|XW&d4PN0&jr&%duYj{W2!cV|2f_mR6Pj$XT3Mqm7=LIh?&_RSNx^dZsI%lOO?AyRz_?#8Fg8eTOd!3igIboYI!=2 zv(8*CZv!*NhYuE^IvME{4tw1dr2t;AzI&@|Zz;+S90~6Ez3|Q~%Kj5WI{Py=8a>HH z{Vi7ZXIxad7<&&dF3RZiqRgIAR10ym;0XEolQ_Bz{=n9V&OpA9PoMrJNPlmaj@;UC zy%_hz_x$-NxI&|syU6`}&@}qHviBE>k4RAn8j7=u*y^~b`th92^BaoMWk?UwHJ)*~ zXdSfeKzd$7@otXQqD`_N&rY>(0i)xSf#Z~4Ak|68+lj=lxms(uUw|}M5MKXlTr}!7 z6~@~{4jLgG7m-%|$nz-tjKfS$bdk-ssQy!Iw4#4=Om1t(W1m3R?(@)p3OGo+@0C%S zPbxc+xieNJllu@fed?0U1!97Tw)Mrz$qxIRTG<+HE?k)vx$^ejoN`uHv5)G&7Ll!t zi0oNeEvWH{ClUwfmPQyE9X}e@*Qw+D5hCb;QMrR*XIzPay6I zOS`(hdweK&8|j{mVL|SGk z?EcFT7WO!g@|VhJcsc6iCK>%&QHFB5+1F9`_3U1Cl*(0vdb|Vatt>{FDPASZV0tEf zwtzgw)V}S&bM5a%+TEYTs25QUX^2L83-;1%F=;`0L3$O;#i-ArJ`APxo#I8=?|a_w zS&z7U**DKnnWlKby@Ee#Kg>Udw2434!(62>{e5zaeZ|S0`-e0Sq!H?cc_-R3#G&!r zsGL#R5;qptF ze?(*xluexlCxOZ^w5M}2+hJ-o=((pIshxM1+I2SBRa3hqO?GwIxral)F;{zbM$2k> zCJt)XsGZx>w%s(PZKL|uXy;}-Z*KcK(f%!&)&@4(y3sy7>u!@D&peqMJIzKDZC7h* z{{~RrVzhBoW~hy%`XBXmc?LmLiuHJJR@d6D)f(+Ll_4!QhxX5>4Q&tF)BcuE#uV1* z_J`xd;v9WKqm24G;@isS<9_%N&u%F8Ul!UvCquaqdVSI0Ah&t6X%a_-W3RT^J{*7C zpud^3T@G=X9ed)cp&rzb_A1ig{?~?LeX)zKK;8>!`>v38^QXanuXqLWG*_JN`S>lU ztK$fNl=27DJUKP~3bd)i9?udCr%kch6ylq!o>t(8{1wpl7dnb^db-^wLO9Vg&lOA| z=;%I!aSiqNpHIg(TZ0*+UX5*bI^JS+ya|UuAG)Nd)TygwZP?+tg9C+eQf(Nf#Wl`j zwOS5f&+1qerF%St6P<{1LjBf>=(pB6Z~A8rcA#$u&`&QmY2Tl=5#qz4e#97?5DTC& zHi;2;{3i$>ap?!F1Xw`Y5w|e@^dqs_hH(sZn>c4nJocF_q3ped+Kx@}*zH^5i68t^ zYz4I!&^umV9QAFFm3GOVbMx1!CZ~sShY#DhDE^}M@z|1EI93w*0ob|c-NI3r(KapV ze4Ng=n#?C*egt-OwBgtm%%~UP&~@Wpw_7Mq4RJ4~@e-bY1Z~FA zhWU1Piz$pgXoGGJ_LtKAP|tjM!q~$64%%1bar88#$KZZxFm{=3A>MbT@uqdtrz1^E zKlUU?1&>By_QQ0;$REsc98oXs!H;<=Q_P?Y^doFacZK|v-l{9)u1(}4j2$9yiE45@_ZC|r9LXbJu0Urv%Z+Xjt+85_sJYj&8QF8gKl9z%u&jZKs&5ZCs3{<>iaCl zKd=vd6L?AVhv!ovf4w1}<2aA(&E8!|512{t<6Ovx*_M{kOEKm_xu?7d-1A`}ef_Xk zILbIk((&zJW)FI*?PkBzJ={eaw&#Cb&UhcCRr#N@rpHnC!G_H@_BXQ)@aWWDh zKR4cn{sm_Lsc8RZxi^Y?qqE$jwrd>sC&P7H(r|5Fq0g#yn}RkN|Dq4CeZ*w-bDIiw z_lDwlMoo=#9{#4JXD@#ujn8DG2b<$daz4LE>&H=#Ls?xD(=(;A?6pR@js(WfxbDYu zj;=+2d+i!c<(%$&H&owHKKwbAZ>lG=lx^|RPzEeaD#sDZuKP$@-XGj|+4kk~+O+L# zM_Sq)<_HU9v>3-p3#3?_wvUKkpL~_?wD-e~@+~?;d`TyCX|qvstr}IGJU7xTLftJJhxrEdYen0KcF(s(G%iMaLFePUM`eU@YJ3g)+EuG%MPb~K?ah~A zQXNp8Hebn#1(d$YKX7erHnT7uxl5}~lczMtm%=aD6R`;<*u4m6IIlFc+Zgh9D&jj8 zW%k>cgZxiFN5MP=bCglEX_&X?#(QlZ6A3vAKmC|Hpy$K*`z}4&hdAIy?GicFXY&cJ z%eY^rxZ$?k3k{H0=$C^w`8wvA3GP=%*J!fq$G-LYS}hg)jUk*dgfoV4#-@c!_hZ`Q zUTJCmLKNSEu%mQ7q<(ERv_IaDS*h<(IVV4keocK)AO<|w*B8MPws~Jqsa#_`(ht2! z`%$zj^epN)_s^o|ceJ_);~%UkkU#U9ppQK{HO~%a?GOJ@CMW)bL`Q@uj7;S=5tEua0(TS2F)nF{p(!z3fNN_7~f*EvBey? zWb!n>i;?cir4qs$29Nbz~x9X_H$Ny4?SO zuJlYPJ#}b7>8V4X_;D@c&*Atyo(Jx~1^FZ0K2GJU1?2%{Y8)C=aJ)Ywa+l%I$YUAx z4Rsm3T7&^R2R*2bN#M?p$x&uTGZyPkg9R!(A4l32TUs*;YfGaTQ_+~G29ur#neL7d z#$uG`J5ILpj<;i+{)d5sX}=Ln^Qln3+#jX(?+AVh2&0Ijup09=9QMR;Ke`%a9diYP zgU0pB4#pbgdq9M_hd>%A-KH4KBI2g&9nej!wvmF~0`ms4E8|)}D6(aQpRBVvT4N=9 zHG;Mc?T5k|g8F;3RcOZ)rD1tU1C7UO826ZC!!?DI;CUz1w!wXJ1KKqlzWw@|mi@S2 z!BNW$YSOOO_FFpoI_z;ij&P}btFP1gZCHC0%fq~Bb()?U%BMrVipPjtZNzBG3#~zU zeGrDv7oM}a`jG;qQ(x(#0UR4~?8HIocb!;_qXJG{S6_B1}Fv?A;n_vxJgr7ix&mO^yjkWUYdWBXCoD7>i0db@GBwHV9zd|bT6+l`LA zDMxv%plu$5+scT``goh-q`Y`-5Z@T$EyG=Z8YXGn(6+ITsna#g;?`I*$0Xs8D~ARj#8@fL03EeoT&YYAdL(*Kj}Z zCak5>0c|EWi)`WQP4WtG3eC?WpHDvqScfqR{EzzZHu-#0IT=M+q&O+8E1wlv;^5Ny zCA9&<^O2kn!<-c~TWr(0HR?Xits}Jmv(2liuK6|l`_SiJ2DjqYn96koCRlXeYyEgD zx(?&AWVIZ9m(@{%^InX@zM`kBznb68?6v+nj&_myZ~LzKQ^Q$jj5+QM-f zGyU}l*4l*6FRd-~_gtmREhy7yJ8I}_Xl+0bg|ZQ~q+z}WZ9nEBHRMlUYvVfF=f>EL z)KLd zdL9n_eS|p=js3|KKtR%1)kGm*$(x5UjzjzCP$!MX+#dbI|Igl=fXQ`L2mZIJtKNI} zRduVoC4(#*t2Zr{jU>yS40gbN-ICo^tp!OqiD5`A$uc$!i(@-M0fTPKBwZzWkpzT5 z$XIF#DGV9I0NK9G3{MiIt6Rp{Cd-id5*(XlvSDLLCX0jqzjN<OUC$1LqY{LE=>4 zQB_2_(q@!Bw$j0LjK#mmT5vJ)!@SfDI#LH|zp*=LL+UbiN32JZ-{xb`!6RrtE|i`J;M@t^%k3sg{C$a=F#1+5pW;Jn2u zm~*KL6z!zgd!%!Rw7;Ayjqr`}`JSUm5J7w-n1 zPyCO<%Y2RReE5>{^&0vrya?m#FZhn~d!Qc(|2jbU4!)y&dB)87>}Ag93^32xaGv(a z6E|Njdjssr^6bY_99kMxuZ6Zh3Qu*k%jAzzmTJJ3!Z+oibDqAOFSd9swEr>H9ZEhT z&z3p7g??~slhVf~HidCAMp|gMW9^-~g>#pccMf|;*?;V4SB0ayhf7D12S|Dg3yJ^o z;ZnX3`;vdl3Zw77%;=Woe8_DjZVPhQqnmEfcVB_u+_HD~6|sda;MD?NC-XZ=*QMa_ z;02v}srhuM=DPkD54rxJhljoD;4x48@Zu%*CcBLu=hG$JyJLRG`b|AsoSX9NoR8^` zvmUG>oH=~beJx`;;Q`zp5I!sA3H+)zavNik4<_03H_%5JlM?Q4NYh2Cy>p${KIbC6 zUOD^7?O&^U?O#-S_wZBU`nks69Ulne?rr4`@aUl3Iy&3DN0}ElaGodqY(Drr0DkkI z&E?y1w_m{Ah5Vu&+H_oC{5=L)-|6RCj>_E64|Msm>(dIM96gR|=mu&vz zwTHYqF3jcE7s#)$s?a_gxdD92BYwHietnYWwDAXQ{6~DRuGVq1AVV`>j+_Tt_%r$3*5>*s;%hoYk3v;K;xD7bZilgs}=*fDUB z{71u%=%6REsgC}G-lNE$cayG@Gr_%uoZfx#KGvU@{u-%{*wIjEm*TLVGEJMq;Zf++ z5$_K-%!vw*3QoA?w?b~W2lu1k*fB5moAGiu=kkv-XPk;7G}yA=(O}bluVeFm?=k4# z$+|rS$5p1(3C`xPwwE6xpY}Pbu$yxBAWP^_4(IjYEPMU+;L)BtP>TL>dwD(cx!~9l z9kw`ch!>Uw&qv7X5$MhkRWdh8T_s&ghjzlG?+6{F|H!$5^r2;A_OPtG$b&X-#Tl{WuUg%_;IkE1e1j{QyZIU$hI9j-q0w=@_TMRM{=TqAe!{B; zmvIjRxKqw%^Tr!m;dmUG-^2T=$i?o`;eDjpUiBu#uLoJxcJ0;l4(@cs-n^b$wWOUm z+Etn;5MJina+{qW0_F#~r=WG!t1{o(b2MbY0sG?9%~vvaxwchmoV39ov9~(frNcK= zJ9z-4F&P|oP()gM=sM>jvuEHa0wazQGt@Fx^ok(578hK67O8r`q|43ib zs*P~usf?#G>tXb)TZ2=)>P_=#oq1I7O6jVK37w&b4-fc5t+%9=vIl8Tsb_dU^EY)0 z83$6Q5INb-QB#~q_l-8UBhODtA_?Yr* z;Du=$UtMEmLjr{c&3|%^7qZTlSYOMpVNHE1p$B+s)>xD++VQa?AOM=Yl?%m{bbHo%Aewgn?2mv5jDxno)(ArGZu%ZIJ0?p1LaZn z7&sVYSw1)f>JPmdbDzji-^HGfI~I8>ZzPV4+2(SkUV+rFsc!35#9{os?d6cXeA-3i zf0Bn`J`}o&?1H^#p-lL$&l&v?^}T0rWbY59VGmJOx<}m!E^DHvO0tKYzE5qwn-l-T z_Ojg1k$Vh-vG5J>6kYJ+$RuR`8H6_&>oCQ}FGhI@6B-V(pQ>`U#TY3fKg*|QSt0R7 z?j&D&y?1JdjmRXX!1ho z@G;g%kvYa|gx_{;Id%~;629hk9E5*n;XB2D1b@q$l25&b{WSPWe~`VV`A5H8Es%z} zv9e{W*2_8jz-{BhpSbvrhmgKyo^kOTP4VrXSMY;B5}c&Z2!7^oe39!H1J<=P?@Dv{ zw_SLpDSSHqgGpX;E;^;IdpGK!^<=(jy7*DQT$eI9k4(!HTqM1Mfz?8vrm&Qr_uyY< z4Y>#UhSz;Gfn>cpj0drT#(>7~F#TKW@HH>se0dJN`lDdFWY&7fI7dUP{jK zl6p!0l22NOZ8rnu3A#G_u7raspkuK{hO?$LjD z`8D^=nc_*=#^xCn8mGy#8PDjDlphrWeR4cB=bOfj54iFxr-_&18Qc8muV;xTc&dYv zCwMl+O~>2hoPoSR@DV)Jug^SoD}+TKa$(JMlzt`Y%wFasU~?TMOwz@>U08FyQXK49 zH^`8X_q9UHlrF8k@XC@O?XrgbPC4d`RoXD|dng%?;@8?+&@$i1nwrL~;xG7!Um92Z z%)M?5txe|HFPA=9S_^-W;?sffG%k8Pu9b6D7|z2Y8i_txHC?TNd9yU6e22es#YNPBXQ=zUmoK6W5{ z6Eu}NN&4Vxzu}ERzuFD|+Y25=_O1B6zTs8$9ALw5XKb5#g z#C_WQ_BlTHEIg{*F=)ugd6@rIcMev;P1_-7Mc!)VxT|ypx;0osEI-z9ot_s#59<0R z`kmC-`gd1!&F)Lr=$fP(=HAVpxHIFlKl#Fs{|xecD?^Q~UW3$A{={#rqkWQpZuwc{ zwm&O=ZIgaBAMt-4`Q*-&&wu%_=imE9PtF?#8@s*1ul=>>Uk`q5w96{sW5{(Q;19mQ zoscok3=+S7coOPu&nD8aYb70L7^E9aVCo)A;*Km&(##t6;EinDlr~BkCA>^Zi$Rgm zk(UdP)RHe%y(OHnE#WNW67H3JYT{P?w!e+Sw}q;(WN?jlX=J=5pE9LOe$$lR2L1o* zJXLrbX9`RH*qz6=B>E_l{}S+#urzP+%lC~!Io z-0_afUeNm&q(5EO&VR+3gMZYa^8Uq}k0=W(Xr=Hd4wapn9antcC4{f^UjRKJ%%dp;9M?lzuD-knI@ za_;;?y?=3HTUp+}h`)!tl=m;x7I*h5c!V>4HL+vIDQ`{KHzsn+xaYgizA-VF;|wc$j&DdHS0Cie%jz=U9+jfm zQ{Rv^MG3~Ug*0CQL48)Zw>c;IHO`L#2s#ZnCbn4@WM6T#5LWagbf{z?b`@L zhmD@#lXntC_vSgjkMQ@bjg;5?K0-Xd>3xLXc57xFIDBm0QT+10kC02&Veot@-Z)Ux zbm(g#^V>Q2#(_EH^pe$K*Dw8*=ofv$`Ncr#(~3I}gZKx0RX%BZKgXQA#JzFgbGG(U zyi*W=+~JYFBO!WmLgVb6f}fms3QVFmuin?xKhcrOq5l#C&(uF{zdX}B1#^>m>P2{` zK;7G%H&ykn-{ zZ|~ZkQNMqyo1aC${~vg#<-h$Lee51(=hygQ2cvziuc|%HZ8p0!KhgUAQKsJ?yfM!7 z``^g^H`DJwRllFTs_X@#K6(-K>echmt2fsqbJwtg>J4sAi&r}LxvW?J zg7oP>O8w8IPydl5oIAiTg+9I2uYWi9IgyVHzMFfCKso=2-s5zfr|8Fj-raFL5B>O8 zpg;f0qg8M2v8tzH^c;`y9pyWQT6)x^Gp}9yz8E_5V?V5py!o|EM;`v|<Eb#zw_L6=E3hp)0ro)=cO}0 zC4Qze|AKYq|MEwmGfx}7C_3{=KTLJo&lR2d_=nV)PjyWv_2!eefmSo$i40-7?tH29 zJ$gd?doum`On?6Wr~32E0anlEN2xzQ6AsTsf1Y$dHv046lIhPoz5H`Ye_mv0nf`pH zKQB7_nf|E@p^Us*blIoBH}GQU>Sy}%nf`pHKY#A)&u4niB7x8Te%vUK z*gd`Ro$tEwrp;S6-!$D2EP5W3VKd=A-7e}Wan1q#myh4m(RnsHOt0tJ=<>4Lf6eq? zPU(8j#p4wHmwS@?1xezw>c6D-5t<5nKKd_l<23p&zwPd`s?R2Hy8g>&ruzS|`Y+MH zIsF&)^qKWv)ZalD^k1UyB=kvi3gTZ%?%k&LUlaY8=*}0e|DtYld1v}BDzmlvTx_i( zqe^WQG}~G=|K|EEch>BiRz0y`YrKjatHrF(qGVD zG5eD{?u1!3?MI~Fq8JOJ$B@!E({E8fadtT4ZAt(9m8SlQ?t=6SMcA48=gXa>b7(` z_t|t9AxvEKz2o^0TM0QTb!0!xAMrERk_@nA+gxH1m_L!;Q*9)qhg8;|OTweiUOk?E*lljw!oc!Z9bj!LGZV$V>xFC{iKGaHZC z!NPW#=pv+cNoTSFC^pbC8;{N=VY41bX5*1}Q?Qw5?d5T|PweH%8_3P}Br_eAOh+Zt zQOR^vGTVHP^T__6I~2I{?Jvy!3+c~X*>gbu<->oneaYGAFuk6c{g*R0`?(T2UH?Vx zcIS90{%6yFG08p4G`_&+qyM5FnpyuP`joqC8~v_>shyV;#-E$&|3mA){ClGR^30j_ zU##8>_nOUj9etvLv#Alk+uu#ZU!o|}e>s!ROS4`~rvDQAFPHrntM?*y!tPJj(cg0Lh3db=$-3+}>%X+S^W9OxKzDQQ3cqJ~oxcnSRVqo_>sa zPtreuvX`*^bDGY~>H6o(sUKtBz=H<9Q(~rsYV>11i)#r$QjER!DE3xqsZFK8xyvq6iq}q6ie}np;!NyDc>q+>_ zY~w}Ub*j#c`C)9lWI8k6`SY-w)Ad0wZ|&z`Gp}6s2BO%@x0XG3exp=Nqw2Lp`@^Hy z2|U_m@<-?JzCc3<`SXmQ=blkMN4jE**P_;V$5eMHIxk{NP}ag0?iwH4r1Y_gO<`(_ zxn&i8?VY+MJ`}FJa~S(BiEhm9;gYrWLi(4}=8O5+OlM~AT;uPJ|1MlMb|74Tf$`h7 zM#V>8Vf+nqOmRc}c&URn=}cREmDzZi-`eIa8`~Ft-Om@~i@(3U+}_#d%|!D((`df?Rfg+t zo5M$PN3^7Qgnk`Ay}i7iwre-&mPy_t58Axd54M*j|4e5l)0xS1W;W|gXGZ0BGG9zw z82e(2$zQ+H8~d&)4w|P*{x#Tb61z1U`OH4TTD)~D;xPW+_Hy{D82ieZ&dj8Zh1*R& zgnp?FtVX{n9p|q4>dzS67>@FCZ#_J^w6v4E>&H7yaXhcuU?r2kOlQUsBGZ`}q@Rqj z_sn!=lp6n_(Rz8=E61Bdp^4ZysR(VLQOp~Pq6d=tXF4-cvBsV=h_QLkU#2r-Jh3?> z{U_B8@$XQ1(KECC=Rl@2lhUQNSLu{4Yt(31j`yQyr3&d-dx(9U^eORc?Jej!G^{cP z)3{aqtBGG4SNzPq?#-9ANjrSG^vTlN*{YDrU|IwC4fVGnvke^z7{KM@4~Kw!Pyk8?!-9}#vtX6kY)^6L2hh{Ex{mi4Tf5#Sh~-%psz^k01V0kvdXd7iA<5j5%C9LBjLmVWUs zLdS0Ci0scG7ZrQ!LPMcnl;2kVn5_HHfySBsiz$lysc~6U(hdpfV7J?(>EW#Bp;uy3t&uG4y4d$~JRAa7vQxko8b zpGW`aZsp+ZasI>7K5=g-Jn^sddqnky6@Gt&-+q5jSmXC^$nPE9VT0fKFX>{f z7eYsC&z>T4aw7k5s@$bY?T=Ww#lV>A!3%XZkNO>v*I(V)T2^i;yweF5d;{ ztS}Fowry5N;?cS2x5SzL%ltdbdapMA?kjebc3*#gIDgJO-Ohcm`RGWATv6yZUmXtj zoX=bB&pLhZ2hg1o+eN9Kiqi|~&x?*wvtE$ssH|V5bO&da?E~lp9oZMQNBh0@e!f&k zCDVWLw61zp^bO_gBs#I3JFZbdm#UuLZS**wF0l{a9rHW3zteSW{KVZ}@JH-dj&|wr z4ONeO=302*0NJ^gywLj*c}f~zcV_x8nf^xBvXv=rFyWnf}X5-!?Bt z3Dfmo;yv!2y0q-G*?)U17`-IbfiNAMd`!Dg+ z&_&+$|9%g<-X%KAg?leF{+F-WUlLwMb!;owIBN`y@ml@;rM28=s2=Sv$Qf~cMN}Lb zRe6!oF3v~XAykELK3*A+iX6*~o!# zg0d&5gWO@<^~`_{)#gxid&F;udW~PVIlLDfTE{k(M1B$a#@h+*ji1hyLioEEqW==* zTwmp^)t;^ToMZpiSC44H(cc(3U8EIvmrQwE`7a+G*7i)+#u?UsNxZ*&^oSPv3ysD( zN2u)BQEI$`^I6VqL~lyQfnQw7+4{23SNlBwb?}xs!lKdeYfki9{JyxCip zqSx4D9d3PisqMd*zh`ZPrct=9Jkk>T@;jb?@^|#x?hZ~IIDD*bO%(g#7ulzB&&F_f zhV!uE5PtDrqgw*>k7!SRkIC<&{O(4F;xfK|?)SvF1s((L!B4&pz9SC${p2I=H0(0& z@8pto7~DqS17_6GAdTp<$b4nA(ygiwcL9XJq+HCkuf-;q<_GB z;T~k{`5V`3f8!<{a6ikAQHjHNwBuWT54f>A2K12|37;nM{OCX^JiNIp>7Vaw>YwjT z`X^Aj=jr;V9rGJU9Y4|qF6e#u=zaL;efa2nsJY2JMS1$db>3j-`}H9AEA)kgPm3SV zX3ir`S_i>Rqif=;o5Ctk-R^KQKtYKMEPjkF7_qGs{i5?b7wo^7n-hA!#o>%DhcEgF z75LfljSrSY-=Nlk?gyXVOS_65O{cs+l(?a7jo;&`JE7T_%p1a&L$|RLBc2a08*W(R z`PZ%SY5{9=zQ0%n${pmO#}sQ*-s6Lyc{R)AbF;!7x9OlKDhf^^^2OSYC?7@+HUj1- zxx0*hO7w1r|G8xUMU6W9FTv~9K+{*~z`Sdce{S}ZF%rBz_CChi72E@53XH$kaIbNN zDcUh9eVF@HgNC~%#2t~dJ7_O_knOiC-lKyn%UT^iT1g^s`fa4v)Rq*^6qDuuY~T%YCbd9 zh5PG~10?sog%=IX=1{Yi4YB{0d0W;J0TFv&fn~;xz~i~d57sbGvEC{8Uh%8q*61r# z$-i>DDToY7{DU2;AY(B=rV#uochJ#~3j~Ly4hP|58sELY5Y2IJ$w%%gSJ0Kv#IM|d zz8s&`i~BQlUrFhCwG~~C{J@|wZd8*#NDM5D^`Hp^0NGnIlF{^C~D#lz25lu$OoPi z`&GWQexJAcb1EPGKi`fy_>sck?chcF5u4vWi;M6TBaAUAQ}SB-n983sx-r)zb5~*; zM!mt!Y4J+u|C4GP#(b3ed+5=G$aT9f)PCB}k~!LZBnjuviM+kU+=#9Xia^K~8Xc>& zKez0qvT`50A%pQU+fV(g$ZxaKgMa*>>$f7uhfnt}BF-fkX?``jfz&E4`h^=xr>&FKSm?)dAEGpDX1KJ(zD z`&x9@?0Fcx3H-#k@G6Ph_p9E>ZAOpr`IO^tsG^5vw1oQ`(sYq(=N@|doQw2&<>vT~ zSFQ6ltO|7d*Q#Fo7nRdg{Yl3K#^1wPhMJY>#<+Hh)Q`Px%wJ}$=ar-5`5};Ii_h?Sq}1>y77)H#DFuue4gi`NI3E$ZGD=;eDjt zUiC_y@6i+D--C>0yY^~&2XCsy-n^b$wd65zw5v2xAiT`CmTC2^W3sm{}8%OK&eX(UTGO;(Z`V;^-)e2=j+|T1$;ex3;BBa z7V(9~cx}Yph3t^?p2EQd?n~hQ1b!lcqX|5ezyk?941DJPjT)=vK}mG{Mt3iec*ZK*&v ztH(Wt{|My>9p!Gp!+#WqBh+*3n$0DDY+q^YNPoeGH`!)!^S4sX_F9DaK6|9GBWjX& zJuMFLXRJM!r?@x$@CM4G>@jdK|BU<$90K)+UJcwu-uEu{RGFU4^S9@c>B(#g|J%Bep&Pt0@k(kj(+7L)>x5U0L`~uc%>=aN2V@15UEZ~W+!H=PGzN; zotS-A|3%)d$n<2QLW8s5bX>`}k+Ifn`$g`NWqLAxS!}jcn)HOyIXcsmaeV5e-I~l! zjLP(6rfh98$BRUPJKk~Gjkn(X%QxNlj(7ahOh#bRu+tSs`qKqD|Gj4p{!xdD{>$D+ z-+TSp=rFyWXQRu@ZvSPsQXl``=iXes>GI3A-hA0v8s$e#^&g+|bI~w+Bje?iYK>In ztK^I(`oR}u&*ZB_Z{$R*g7{m>-Gj5BZ~on#$Dbvd3;s8Ew?G}>PEU8g7qusDE60yi z@3F}1)j7TOn%M8v-TEL<9aF(24g8PrHI%20aCQWK=W(tSaIQ3ub0zafU-05DobXi9 z_ms!S%W5%lj!5ota&Ia|Mx`E!yyz<6W04nMiOhjK#olayTq)oTI9i+M@N1vf+uCn& z=zFchVXMHeQg&VGzN`6NZ`WHb?9zSYcVOpo-TP?d-6H$W*W}BK`Tb-~>6>_ywzs}s z_Z?9-Ecz+J$j8ic`UxrjQ{7m0_?Riowb#L%ClHtrk8mJB0+;{nK zah>V5XNS=%^5y%aUc(LtDN}SDM5ZP<)C7ke%eCASX&k*@^gpKfhojD4@?O+VJ`3|@ zltBu&@H<+NFO#6Kc6L-~H6l0M6dLZHRO3Tob<06pzLXQHPukyUd5d_*+8_uENLzVg z*uK#m>@dZEbQNRwmk80dAng58? z=k^u4wjuTp3%(b)a)$AjJfr`Y^!3{uJ!+3YyB0?~eYKoPaVKrq-IIyXnR-}gm!9XM zmm==y?MZt|+9WJKkt?qw%)BiLdzLqpl6OJX4|3&)Isa5&rJw&}uDqVQs9Rl`0d1G& zAHT-6X$8Od^)6iS4!U?NvMtB><_~vmA$xz$&O}DuxHR?~3vioHSa-0DdnJ60Hpa)R z`OR13Yw(FKjL3H@ZNz7v6D%c+PyA})*A0J@^y{2~RVZtmu*wz_E@GdgpvkTH zsW&I|v$(kaF7fp;;>x#Uy{<1OZ+=&~zf|pYWlI%q{O+)xjCb?~edEA3-Ym{}oc7r^ zZBSlq1UtxlL0`_hr4^b(-~Wrhgazs?VbFUWcPk0+^}OKK*LfAg?^p91ngmw^uena{ zH5CH$Y1=m{;@_Wy3)B(sERsgzs$sA4(=quPuV&#sFPH;9?@0Q^QtCims?=rT)yA)X zHVWyTeD&a=y^If!0%PML0F|H(zRCN ztWbr@0B@5|{=SvCd3*PCoO`F5u@Dq-Q{FhAb^CcQ@I9{ve&c-BFTgMGyo%6?{$2-) zEZ>HCdC$_}nf_u>Al|HNd4p8hdz?~t*FU6RJq=AB@q(~OUe|ik7D2%8+_jveP)^S# zUA1tl4syklIE`-7T5ub5AoOPTCchyE@&n7DSDIb zI1q(8X~TMt3FU3pU_A1;!_yW{M0UJI-0Ky+yRgIa!t?m%&|mWTg5+W2JrsH6i2Fdhh$CfBrtc)}D`@)j0SZ z3&}ikFbt?m&@@J)UvuM7xA%Kh?%(U=UW>S`?5sWKxiBe1=Hu9o+v)ME()Z%W!}$Ft z^GnmK3v+?GD96FQlrc4*;Mq+UZ&|C%d2XIr%@~N!Q{}4A>HP)H4zcm_ip0IW;3$NGS{+o1MNd33!w&8*|i*GG;iaD>5 zbx8l?`@%j&aW>FyD!Xn^DEt9 z{3h3b=JziMZ~X2NZPya?=A{4hbbX^V?tjwLmn7?>jQ30WJ(Z+6U7w9w-Q3=@Z&^5F z`dN;5)31>Jc{O9|U>JSZ$$5f{`n{m*$&y_kWp1LMS9(k-h8Ku_%P&7L$a+>7@Twn) zb&UNE&0O1fos883Vesb>b1Q8qbHh`vUIBbZgMJsJe8(NkYq1LAZ#rHjC{Z3`qykT8 z(AAhlnB_BL#|uSIZnym9MXaH+KFWM8bD^xAhgmz#F1L0DYM))#?EJ!-Z<71;4?K;& zEa^nfDSSiY(&RVo`askj)|XPh7#-5_Y3` zt4-yH^2*2<|qe0Dr+pFO4mKP)A28hA*z;7X1{-V<*2$ z;4b+ny{%lrT_K-`q`Y46{wKyIct~DC!x|7Ae91%dmAJb5Bu;{Z3oWXo zk#$jUQSf%-xKmsv_`N#8Wi`JW#Iy8l(s7Y>6-;MI`!(92<+rw%zy9tcg>?Pg*`o?| zbfI-mRFL^4Aiw&Gs3hyXd^&cxZec!oKy`<5CLjNP(!ZBcmn7W$-uCil=<|H?t#O}L zcnP7a=-f*?kM4-{XnunpYA)|HQ_Gv4ZYb!`L+tya2VK19g#$W4DGou8Lf37R<^MU=zxmsF!fzEQ^Su1m66aFp``stw>ZSeO1o8AznWK|<5-#zY z@@$SbeLYFjRp`rNw_O|P$hfI8Z`PyHaGZVPc>iJcZur|b_IXQzeqs0>&S(5U%OTE7 zrH%9xvr2MTV~D=039I98-AOq8wWwF1W5{@uzC1L_m|>4NL|nsNr!sSaj3Ha=S&2K@ z2dWO|u7T(H^To6K40sZDT0GgeO~I46ss%ilA5ywS@CMCpLZ-MYy{6dO5@Dam6srfK ze0etf3GN28D9OA6{Z>N<@s~U$ta7-P6wOOoz=m?fCkBY(h{AQlBYoXeWEQWr2l$9tcM|3$*CLPJ#OI*dYrp8nmdndc!|dz$LtSxGCx$^ z`p^;%AiF`HRJGxE%@BU84G$JjZf?-4Tl^@Oy68^o0e(_`kb_1g`mfC=O7f##JzT6U z5f-fS^lajSv!em}BnS|KGX7K2tl~Q5$^CAP{co@e-VRt1xDdWq;3DHUfL4~kJBJng zE5KTSKd=D|t^=0w2L|9-1KRh3fECgQgSamy9M}NXfWZRN3uI4-;M*6S!U`~0PPn*f zH@Qy${TNemzJZ^;i&7;F{|XQprB|;Suf)DP%q#3bMV7~24KE?QYo(7e){+hwtRvke zqyq+*QUdpCeJVDNgv!KnhQ@t#(&9yhQ843Ht$fE8dv+|aQqw1h_skRvzbEulBz z&l_D8U36)}FTdFj_|@chjo}Ld-s#qL=o)Th-?W^55AEyFUe>(Ywok*;Gv?E?mo7ICn%@=0Bj&=dMD9%H zS?8}lkH6Y?a*bqPTuJntDkCxWZjeJF8x1xg_mH_6c~}~r%Er=pRDDG;O{+lYG;zX+ zoX!tEV07>mMgF9fve^^Y*>^bm1&&vdFj*T)d_m;uqh-xhPn7f%Kxiy=vvV2YVd24& z$SS4W_s|Zdc#Erha~$Ru%~+9km$xgcs+H zGrI@Z-*N7BxJ3?j@8xkgOMM5K*x!1yL=H`w;1@QR(scJio3%o3@!x=dlKwvY*Wo`| z)-?VoKw?(^Y3RBmnq14x#+D#Z|I@DHHjKVd|7mIWVXq1ddQWrKFfH%NGOwf$Z)80b z86joWsFU3wU(~y7yLS_E#NL74@K9jQLd#kFX zR;h9?V_UI*wfN?o>^^$h(M0?XYeQ$Iz5WfSQ zyKglQcnkl=gj*HxjV4?$Oxy4dhrGoh_2{GiebwROR%j3>ds*|!ZRMNc)fXIjhsD$4 z1wHz>YhddR9tW=M(uY_>54?4S{ua=lwL_1R-=F5YU~S`hcBvZn2#|Kr;1=Btcb~$>g`2Ror^+%HFRYA)Hv`|&*dKmE`dJ0s z#r>tO(gN_1GT!o~$HN8xW0UPuhY5?9sqzA7xFA+uq1X~c$6ftpZK>>yS^{tqo+(K1 zt$?qLLyPkq<4v~zC!DeYT*O>NmnTOK6rX5ufb9iX3p2X#9LJX9MEzXAM~27;s1 ztq*wf9QrNz#$R*zM2X&4A8oHVrx1Ki?84MvIB0Q^J~)0q?Fy_qoXnrP@P&<0S2lFA zWkV-hb`>aPLnkR)%8fiXpV{(Q59J)){GrQd$>Uwn5B;Cpz(ke6^E z@XsQ6hHhQwcNPCiKBp^;C0U0gjmEFR+*ieKCs6hZ_RWhwQ}%qMIj=h5l1B2e>nr0~ z)>yeq(Z=30@|brh*U9eZA`kp;wtYo@Bx6a^%KsVD!WYbxmXuS{9)~7!ci zFyLKoSyiY5E3ARSBZs%bL*G7Z*9QHkkvG8_MCT2|l~GZDP~|o9j-3PSk%_NaALK0s zy=kAPku7M}w<>&6HIXf7bcL!%;SKDWAG`tdm3q_@8cVq$e)RzpM*rmIK=-z8Qdj8F z94AiZ?B+NZ|4HP%RrQ4;BbDEujC#Yxk1Frtuv;%$VywS{ww8jA`{hNCC~qcSe)a$MPYKm`7>Lt9DBR{>7TvkSjzh^x_D|z{cAwizzsOVf zRvEX9U$5ZR37g;>dS;W>`GP0%cHymtj^gI5*Vds>2xgKk1e6=l4)Xp|TG!wM_jtj1 zU-SamV{?BhU@tBFuJFB6cu%v>>NBf;&z>(eU1tUHU8We&AevKY8A}vR%KP_3z%5fxdU8 z(#PY?VVLB#Zsl!y-O6n`#-3g)c!s1KLf*5J`E-KyJ3KNP%9^xp<*hohFw%0iwr*ub zM;5MUSrGRP8f6*|OXw*gx0ibqRj=x;7}bw);4*adFEKQll4 z3!lhz^1fF_eo+FK;BjPreVq=v!qTs}gSr{#njX?4BduRFZQ(*?XjI*+$u#cvIVLQy6g; zF7KMH+Y*KA=0t_K&y^R?SLKe*{``jTo5F@wQ86&+u6O40qR-yhlur#_+;qD%A@yj? zQ3WYy{EGg3=NC7XO7!#91?6wRe=pxxsmF279m`MB*H|xP{~~#Wv)`;kwI!V5r#6SB zXiI34F|;PxXS9=#^e6SNZfvzvj_e0zAF|#&j#OZqJzL+z8Ktm!dY$uH_;7DcSd>^_IO{_yqG| z=bLr9uaf$3&+uTy&oC;@|Ph9q09KY*7JIcNYcQ$=otnrI}gAm(r)koYmkBL7A_r&$JY(TTHRq z7TdWkb=Pr69#7^l?z;Yl@iZAfSEz1mj_=$Ozf0nCHolL2TV*o7DpaY%$^4yL;q;q#ASXBy7HWDCF{VVRXaTMF~7W6MeL3Iayqu;eo1ZMHM+8* zN7r*PXCGa994P*k9Q(G7CJb>mPQb^%kB46Fh>9WpL-tGMTacE5K@lBD@C6Ohv;t{^x1JIWlK5#VmcYjUF-$Y+(V~uONI}#YTUtDw{{c{I2r+>=cPVktNgRqvQxTbJQICz^sE82BR zB@h`?Xw!qEw2Rv6+C_c!efAE7v~~Pm+Bz56`BU*v5~%&)%^$tI=hmo-)7J zX4AfWDSf0r40-g06)SXIU?*)Nkn)h9*!~c|d1_yX!6Bq?qbbJor2F+m7z^M}M61&0*?HIpVJI z30|5xO&tPX&fU!?h!1S0iDn$tXSx11Ikp%(@h`Z#1mGcOXk~T3S7t93^BjXzN%FXx z@geKjIO!`gSF{Vfie~u4Bo9)PIE)LaXI;VvmfPRs{5Bs4FYa?IAZI7MISb8LV=5g} z@u}mcPMo)}R(zDUAg=I_Um^ZikVDRbo?qd9n$Yt;*6Fs+*q1Pg^YGB;%E<0@WM3q8G@-IEX3mp*o9R}i3=O{-?S|%^&@`q^ zp-Elp%lNBwF4eL(vF+VVE7Dn7F>eU1>^wsIH)PGFpI78#jt}@`?p4WtMcPK%LguaL zRc;P3BW~VWC+psGT(je=d0fKmn_S!jo4j1zoqyHSrSc#dy({F=;%b`Ol7q)Xl7 ziMzS~NF6QC#GCYw4uq8_`gE1LRq{pN-EjH*s^r`GQ(8x^Eu?Irzny=lq~9M#zvB9M zyv;$u!>*0=Ln%{eS{E92zJ`A2);qb67ziJktm*2P=y%92%$@W*paRy#eFuFDD0xoe zEMpaSup_4fvniDOA>vN!UKhGIxyPruHMlf~R}*)0{_5>+9NV*zX=M-5hh>i`b61ML z-3!@!DsCL^5c>7VTK%BK)zV$=p|U5EvTG7fTgvZU@_XY?L8mKpW#ba-XTyb;VQiL@ z`lkGbq`5y$v++{W^ym~1yIuyYm-%SQdRde8^5>KF@_#$tIR1H8N6w?CtPv5{XVW#J zL4Sz;6K!)od^CN%hTedzCBip_vVQz?(XN$4(88{%$O?p?GEX~y!BuoPWKOD{FMZ&( zx-M|VPw8>%zC!DH;=e*yf#!PJeID)2*sqEE4YYsaZs3jx*B1~znkxhsxOPnEyee*+ zzlB$ER?K)6+DUu8o^!~-t4Ssd;14rR|?7T_12=HsX%J|YJMOGOPlK(}<-QAzhdU+jn!7X=*f^LU<+UKelk)MpU zPrLj~(am?eE`ndkJ#P893HC!~pjaL{%4KipBQhbG&+NW)T09jIZy-1&p42rhQ-iO# zZC|B*>bPy)k)MuB{rZ^W`6BrAIV7ze60SoX!(1y^duh{ z{kd0O+!9TWi^`UT`Y>|%_)qEY@Ut?vn@e1L%VQS1OEvP3mbh`#T&HpTYYV8;7x$Mm zZC|w*&GXA5PY@bK zf8z31Nk0p6(2X+V$DF^k6O*ge6O!?+31`Cg4Q0vPaLRax{}LP;&_w7V{8XL#%Na!# zSRucF{%ymW`k=%SdssqS=9kGc&dKvl!tGrKS$7j1s(7L6Ck@FH|Hd$9qHUb%v@^aI zGQN_sgqF>1rWeJ29sI^WKsyvS+j$}8P5ui05)a2_-L?r-t&%A8K)Dx_0d;e44XF zRj5ebGOutJvXkE-v=o_!$+`a3$g4uE-0zaet7KiIPd)TZ9M*_mQHM$b?HO|yWyu+{ zKsjRu>TZ5R1EIT&cj=2~qe(Mun}1s#>7NUBPbTMO_FTG{w3*anhJG+E^lc{$xl^!M z=tR2!CEs*@(zs>LsREBLH2$s_{^5LwYsj6VDL63au#WikE!XQh@kM4OeUG&SzfC%( zj^p^7e<+mei;+PrrtP6~8h>?+{PFJ!#39XO7>NCEK^l=yW z6x_Hg(Lbj5b-}UT`F3s7bElvRE|PY7yeeSaqrOgEE=CS2a}aA(Ro1EZqF=NkB3{B{HtCN^`|I~2 zx4sKg!ish2edyzSv0(c}^cRJ)UP3uJ>AO+h-sf8JPJ0JS!m5M?7f{BM-FEL#TLPVE zFVQ8bK+8%eGAs)>TK%|6&-GSkuF`XZZm@T&^t_qzEO3*SJ3p1%w`#fbQ@Q>2DY_`4 zhtj}5fJcrWqkfbd0re%|h5m}9omfJjm;FnUM|erP;pgLrc&G!XqPxyvK-m&m|R z=>z0%c?m^)$%FAMbE!E>e(WKxmG*aTc%_l6foSuJ1!f+#QiJW7*yjL63Yj z@2HB5sIq{(6ld!HD@jM)rLAkMp%HsE*&9V4bA4Dp9C>xq69zNf@tM9iZb-gKUiO}k z=&PUycME&;_(s-UWOcz~eEHrmxQe*>CrVZNgzWvLZ`7ra@n=4FmzDcOOPx$rUk%*} z(?_5a&wopt=xX*_vEq8=UDhpr*D3DPgqd-Q1i~<=2G74lA$S9Ce zAfrG=fs6tf1u_a`6v!x$Q6Qs0MuCh183i&5WE99KkWnC`Kt_R#0vQD|3S<<>D3DPg zqd-Q1i~<=2G74lA$S9CeAfrG=fs6tf1u_a`6v!x$QQ&kGxMkbhZ@l&9U%qMSmbboh zrZ^HdlYi<*`t;|_aPQ3CKQ6x4u6q5-`+vdv=-KEny`E>I%P%iqdfC$dxconEx#B-w zzO;JN<(F-}`LfHJDt+rOy>;n(Zr%LOTblfuf3AJkJG=UCyS?kO|Il^W@~i&Cl~-M{ zylchs%dSl0Bw43U9>!Pdf9?mhiT^&X47UY*lh zd6T;rJDdlB>X-^HY2c4Nrrw6~)DaaZ@H=k-HVPN2VBR7Xm_Pc07k}Y|r?6Y5uvwtlM@{JUh8n!D)6h6 zU01sAYJOuwbE}12x{v%0>|CyUAC0_QpliG^UtY}bCu>UI#2etf_4T^%2(~>5Qws7Xlecfb-@c1D|%en8u$`NtQ#Hm!(X)rAY* zVk0@=ZDOgn!tLI7-(=roZ^*mH@|H06YUDliU|Eb!X#9B7K6o|1`D%O(zH#2LmUpi! zycHeH=UYk`pZL|pubVfcaX0v+pMIV9sw=!TJWf~zI~I$0FFF2xu6!$g(a$9GVRx<0d*9-&@^*8TH<|4_=fu15yTf`i-q9QMjRV`XeuccF?&h)v<<)o( zxgl>N_vO4>uv4U<@BbAX)jltn11;X+=%bgCKjl;@$J*rnY!u47{w3TyU(K86w>!56 z2kg&zA@3&(e2CA|arP>$vA@1%#SqZLcK86lSLp`zs`Nzmo$X)+{d9o0wRvmX{l1mB z*lov#gkCe?X>63s`~B8d`R-U(`ShARd12Qb+Kzw3=<$!>NB*?{dh%Jjn8mzT1IKYb z>-NdhCk}NQ=d*qReu3v~V$gr<(4Y#mVO}2FakTj}{Y7g>KD?HBP-(G?DSg4UxAc>z zc`N@BFAzK8xobU)%J`bM!mAc;)j_U!5|2^dY?pr0`F+bE@~c0q@}=3HS9&FR6=*l!;yy`R&$Dlf7YkF{ z20Nuw+OL3H#)G*j3@WtC@`4v!#+&h@*hp0G3M(5gg7oinbCp`<1xES}aZGGs4l^Y- zeS9zssEfRLo{pR7*WB39ymMdeypVj{JSgt*4;t)N@y5OllQK@)MV%hMD*Y#ZJdEFe zGQTvvx)7U17v+MP@(G^ZWbu~u!(fL~_>0x_cT(59?*pNzb~=%O1lhUSGA3`=gW^8-O7AdrVoo>D|7P0VhafS zShHroU*9)7DvBK!yY8_5-TPRSUvtc~l*Hcrv^<_q`Zc5tp^ZvxEVWVoEWWka?-o8w zYzfrvj&y{rXZhXWck7%k-Oju6%1^_c?PD8$V7)fj!FK7ep-@QD9oVYdh6~;-zO~dz zY;wxlq?A#NTR-~GyekhsF_T?E!L5>y{NQo=7c^?NIXD?6xLq3i@}_@{_x#0UuxHWrWXY~sGB?rBD?O$Zvp&ba<(D5AWR2ln{wniuEVf4q zd9U$08LQaW!q!ZnoK1)5DOaz6ck~0KzbYjy)*7C-s$#2^A zfv7vIFQtAfjJ5T4BXMQEs2FU45I>zW1W&uxO5BaZrC^!x0^|dH;OSwTzqGN~tF!s- zi1JdFtlu^tNq4&`Rfs={Ut+WC>!hC&uSfEC>9nMK!jx>@qmthF+cw$aaF)5X@jCc= z>=@0b|ICLckUTGvdhpf8ZqU+ZUFr`ky(NBaVGK`W{Cik;g9H5~Js*ApzEy0%?81K+ zbNH@TW4i==kKB{Zx7!NHe2BwvXuc41PS1P96MIPscsso)k`R7qob7I0DUTjRJ> zTqgLvI>BW%zZ>Lb>DgqDQPx#3oh9wpXoHs6RQ~$Aj}+4Nb0_wn>e#^2JyAjCmw^20 z*j^T!74qrW;kt$SXIpu6 zN2Evd8}v|fd7qhD-t=@sL5Ch7_D9C-Ed);x*;j9B=x1lBTQB zm$BQ%{0|)&H&y1%I(GZU*~^XhA7(#=znwR>m8E^f=5;uq@dGV~IwRXp^b@m6VwY`* zzN!hU<8R$bIQ_M#S11|tzVziGY*8!rZ9~L0t*TsRE|4)~YdtG*Cwnv1;oLRw#Gc&q z!?XJgcoKG6JlRW4!IQX({Y{zqA*EXcZ_w-}WQrR*HpSMK2>U;#SjA3_*zXQ;H=spH z<`w9-8ajx-8JOH+6w579b_4wQ|O-LU4;)y!^fN2WhNY+Q(Ve= zF7Z;jRIZ^v@!37j-OAbPX74F79_y^zlQa&# z$l9LfA$Bn(4{vH7^|@2?Ft41N$6?Y%MPv{nuQ&s47})WG_3&-$SF$HF#fo{VB>geP zc^5dZo&o2y-nURr`~&&`<;;ZlY4cC&ljc9YK572JmzrpSY(!{*UA-yvtS*>Ji`a9t zsLf&x#12yV@~9}b?qpwU*FtR7D|q?xQC6a49%)s^Q!Rc_qMgK^c2F3E$K*pM(4hWe z8-C)%gLb^P!hZ>kg5sc8`vL1J_QM+jy+JQH;oKF0KH-VGA@IwtE^GHjMOpu>P4~#v zN!ov=c32zlqdnYQ7qOPFWqd4x=H}Z8&1ay`>1dwPEv5N%x~Vp0=c4CLw>)O1&seva z`&dfr27OHE8x(wO-M7Q@`polFX zJ+{tB*RfruI|p>t!d2M*6!&$yN}tgyDq35(4jaqje?GX7K2tio39$^CAP{co@e-VRt1xDdWqAolATKr0KlHufv{SAZfr zY5*I+;5uL#e_#NfHDHah8o&zagF)OE6Ao+uYrtRu;R4wc1{M56!hykZ!o^LyRaqaQ zA7d)cH}I?B4yuF!D?sFiUcHKZjeU2R$M#}AvOM-`cnRTMD}9u)mUO^i9qF*yRsjZ= zQU*|L%r$^wpDuVk;owvO*2JdedfdPYFhH(b16F_yaZ|S{pN2;ZknJ|`58j0TD~S)R z0BgV+umNlUga3p-w5kAWbAhC*02{ynSd(ztts&vS;LW51Rs>R34XEjlHTs|MuodZd z$ok|r`vG6%ee%1;?|SmP!SC@j4m8kvT$~DYs3yO~j$J+Z9nkjUX&ip*y-9rNRZV`& z{8;CA9lC}a**7hx-$VO4w3junw(ZmK^o)7VSnNF5<>o>4DP_+?g0Ce0&pLneN&MBm zlWSxP@-Ft%A~&>ivDmL0K_IS?74hdyAv9017mkoG?z1?GzuiM#OxrGk7faTGFGEW?mzcCm zsF43JXDb`R}QinqA>HpgL}(To{se~ByW-$TSr^K2}m@5J3Dk^5M?p#sHjC{Qy$ zHQP&-vL|h~wm3VcYvS*O)&^*TqlWI)gzjk>0cGe%$PXTFEwrwP`#a9P4!6jy?!7z? zXQ}TX!}?oqmdJjI6a2#FQkw2w>abSmBK{ljPtxCq|2q8BvJM2s{|5B!t4GD&D~C%5 z7^6=H{l#wrZ@ThmzK^lkr~8XH1GiR>=6lU(*a!cA;Ehr7TelA67rr&NG&I+%vZ0SC z_CwMq()|0_3-zf(;R5zTz5hx%z^&E(u$MM`a&A=UHOBi!&~JIETV#Lqc4hZRiu@#( zUiL>f9oZBfgh%Yt##8H5xi40p_&=HKnN0m+wy5s$*b@D zsIc%#Q|g0$Tlvy-H(zc11@JuT3Ws~|vhChY@l&PVf!^>C^m&r6FWTYtel!mI)CatU zzXE)Ehj-x0e7?7;O7SXH?oH}`fIc1nt&>|>+;f{9eV#h$cVN5oJN(n|CqJ*s3*iZ$ zJaMay7k|&i>x0gMvsvlrV6Il>Hp)or9si@-BlbQ9ed5PU2gU=vkUAYYUlra$KR?VI z9{-%nySMcJvG+DmauwI1Zgo%h=~JhBM$(8Mfw452=^2ecNMgVkFh4aT0q2a6kc96G zPH-6gi+628WNgbZm@@*~-4a3$eqOoGx><-BA+Fa=Okz7X&P(z*5_qM1gu%wK?@MwW z3kh(X+-GC#csUL+@7q=9jCzLg59_X#b>F)^Yn|Dr{&wx!wX15^uG6)Ly~)-4bYGeM z;I~sc*lTVxZoCittJ_odA+O8KxM$#fA2g|dOlc9@Rcbq&tjEOx_*t#Sp43zAr48vB zTeU0aNxZ;5pE@t4PCo}cZlU1cCHUz>!T-`V@Eu(J@c$**U-s;+^s}Ed%YnpAa>l$p ze#9I2P8@7kz<0$#|M+3+`%~fnQ}|P*{nco^xE&rO=^imYcW-3}I&lB7_gXqFUGSsI zxw@1QIwr5|(MMUEChr*1F9YqlGJG1~OmY`(Q1q$v%h8&fBdX6D??|#VsA8Y2o_DRT z()PaGT6phxn8T(jv$4sB{M^Agb-#Hucxlsd zz4J;Fm)TY~M&$BR2?kHWukKXG#I`WWqbIU?;mN$Uv=d-0c;Z=}v6=H+sA zc|pI3jqo&Mx$i3GPR`@EVUy9EZwrn->KtfH2HTSUU}rdqTu%m*sz2yERt>f@p8NK_ zP(A|QogZCVmi`?0=;7ey!nQ#6u`;&}gcHFI;LgUQ!DAw4A+$^QOFiX&=#V;ge(7Y; z|L0>?ZXYKtS*0rd@UTBoUZL3G$5XETGFOKWn-1}PD!PcD(i=jrj7dxLS+O_W|DQ2| z^iw8V)t0`j(w9d_+d=+;+9YxU9klHT@Mvu!coF!r2128>tqR<67IF){$zMBq3^oRl zi>jPQWB(U=lP6u8O8d;xA~M)KM85(fM^pTDmv5jk;p&D@wr==j>yCg@H++)1rC#H; z)W`a=5!pz-=DQAb?-qhjk$6xsr`B8Q}&Hh)99riSPcFmqWLhp#uJ-fbz z@NtFu?sOsze}$HM%44ZFAg(?V2j)j^4wN&gj9%%7);!4%-u*=vFXeCW@S0;TmD+? zEvH?})gOAxY1eYvb;nQQ;vH$bL{|}f>R+5J4WgF~Qf`oPgOnRohrL0{4N`89a=X)V zgYaW;O6kFrAIt9EXUCzSl6^^&$L=5dkc&KR@04-N`1J~2owO;Q(O1W`&KEqfWAEn~ zJx-W2RNIC^!Jli-?o+Q%KRDggwbg&%LC-(?Y0sCvE8hzF>`_I36g_f=E*G<2&%+1w zI?tZLonS7VI!*s$2ROtW_#BV;ITt%{C-#SRsU5fz+e0Vz200r#ge~j@XG0>R!K)@e zZ+Id&xTZ%xmplqwqz{4f;F|gRX4b!hYkYlhjnXHQEkTgt+OXy>yopezLbOw|g zRTIH}=F=(G@8H-(AZyZwHM_O3&}ccc+OQ_n#=?y(3lhE+JY%}79u3w}r`TBqpUm-{ z@IidncfyMU$wavV{}n!;BjLyWs&D|>{2wzv{4l7zv+i@ zVbfYu^yAoD(4EWA2S;}co*MfZwZfGNXh-8LRgij`mksB;pB^ihk@Iy0RoX=S!#rQ3 z9VfaM>&j_ljrBtI1A-%1c$*IJYd#}RZ3)U|YY?Yn=%!R}pAR09C-oCIw&qih?6X4B zH^wK~ZSS>b)|)!0_eG_D`>gZzLhNVV^v^BTT>h5oaQ-G}tW<}~oeOEB&_}+ncDsCK z$@c}7zvT-i|2*e9lIK7{6{H=vfO8%7+)_Yqf9<}C*nZ_)c|N?$c&*;z_z|D)RqE6u zJd-gaV~2W6<%PrLWRdeD9$;6NeN@)&P7Qf-ZZ{!pDJ}OJ3IE0-!D}bpf7A1iHjlo58XW;L}w=@A6-W5i$1zcgiX*tZm@qL z>&$H;BVz0Hv-)6oO%)78Hhkg;w3fI%{1CpQm>Wf?*lK(-TX3lkrF7VbntwhK6)qU^jgt zkos!-oIIFaGiAa2hF1xYjSPpCiP9{Ym=&(4;o1E)jYDLCJO{jg8(D~_9DnJ!l1A=* zWV{J~&AYvdmbTG;KISN?2KmqvAw$Hi51Bj_w;qkBkG24b6U&lIlmk=s`33 zpYzajuqz!$rp`sb2S&i;7`P=2Y)UvG9UF!LV((;+K{~J%m+)y?etDmk-@gC{dE-9^ z2GA?8d`5oNpAp7p&QppyY2W`zU3`loVV}8A_6Bw0<0qW1YR`4i)8v~vmHuhuNb${q z*w*BmN54BR#+<#0{;ipZXY&ERm42@7hu#HwX;whaDm>opH#Omcne@~N(2X#STV~w$UAlWZT8{@#~{0VcR;BDnwL>(GE)O;GAcf-?!K7}WBX)oh4>|Uv5 zUt{~bl~=SN2+aT-V zFS(YRYf2SAK0LkdwYEto>6s$*+J2)Q5p*{1b9$W2lXh=RoRrJL%{1I9Khj1^Gx?_D z&14Xss_KZgh54e^(oWJpDtNmu*V?$gkh+Ecc3z%Q{?Wkfb26TcJ1FJtnu#1rox;<) z@UZ&|vAC43LE1r(gqG|N~e?C;BIKOPI@dkhI@ zZLbU8Tf)s*VGS*<=}{VP#joD)#<4w%m{s>E@*#UqnY%Lj?H3dW~=A zWsMPiDqvlS`LtEm&{23{*IH}{qG!ebT%2B8<#!A+Cq?Ip3|y`20*5ZwO&h*U>+>ak zNJqf<-SqqU^fzO_CgI!Y|1{hnY)IE{A$=lO@ZaM4F`M%u!WO@US8+DWcop7Bf89zs zbQ=Ex=H7SFZr)?!>JkS(MIW;BCh3Ahzg6H>IeSFKVJo-vRh_Wq z12)#Cw5!T|&tuT#>%i8$lAh(2d}Vb+0nmVW!7O zxOG53j;%ia8nTbhEAxDEsmpKm(Bjf^4gB$t8$+#aY7$@Tr%g{kTGq%xc>N30Yi&lm z9!N^bDmUIVXGDTuUx%C|j|MXS!ae(@bvK3mL*`mpU-fmYLox@lCYj{Pz7p;}a`h|NKG6#qAeTcvX5=inQ4 zs=syd(oamZ_IEQf_BH7kMoXgaiH?eQfXlTF_;fLr}b=q$@!-#+(_~fR|$TNVJo$MqU+E`d${BmaLJ;)HAOpL5=*OI$9QJ&vkpKYj|n7E>O;OfqJRq zmGE80yYTlH@uZcvt?we|Mmf6VOij*$lg_lyq#bj}K~wlUpEPV!{vdLQEinWN-fVu- zgk{c&fF}m{HaS6;;2cb74bDY3An$blFz2wQlk4uFmVq`liBJBi zP^k}Mrx>K~MK@0KuS?K@epnz6Wv0{kZ4qUHb946hhk7+SSrvJwJU_Omi9e_-%sVoGsIJ@*ar60nde2 z+TlgWP^4b4ctwY9lE-|Twk*e1N`a^!F5yGpm8#|VTo9%DT!rph<-=T%Q zx9SG_w6OO!#;d?FE#K3Gd$w!&o+jM0XU6Y5qFWszaT6OW6XERdWEryouebz{_GxWCo&f~8?3&TJ|ayYgQv!gGxHAi zV2Se07w@sMYsq{K$`N7S^4(W zZ{K>^+b>-iZM*c6?K>{Hq@~fj-+#x--`c(9&Rs2Wt*`5U4^0uB!R$ukD zE3dljlAfW}mt2|UNl|A(oB}BIdq4R6ZF5w0CQtkA4IIdE-#8vEyc~WyjWQ*rmA$vr z{Paoj1yNFk4xmxui#T~X_eF*Y$?V=8E_icVDua#D4<*QO*1`Y<)5q)%TR~ z`gBfj=MM5de3Kpls;88H5x$xG@KM#*;4ar=%2&{Lc0Ya_2b6#QGUdmA_9VVuUiTEf z+!TJ?6u#XO?j1MW9ZpM1$s!=W|IAfD?tV?KOiI)Ko(r+{Z)Mi!t-ojMrxY5hS34TE z3;Y^&*Ojhb%R7EWw_DhwtKgg5zgqWw)p)z$tGXgz8RY$RP3djidEQswsH?~DcS@SM zoHX#n=jT(tCKlFSf0FxZ9p8O??)ndIare)D%JJXS_u6}CL+6Cr+&-fByZ-wB>9|+YqZ40)eqZzowU8deYWvJhqnvfJap-JaYO1?)tr;B zJS6QJcQiv_$`Q%qd~Owh~r1@$m{^xIyyQ{U|$6e7E-{6HY?-%n5An^hBPz!uU@CknwuGJbp@;42Q0zG`7kMO=$H%JS6jlJ94A5w*Ig!{}p$#36x zlQ%!Z*Op%-Onprr>ua=xfBKT=)u6A*W8-|{e9!p|LEh`|D+1ayFOUB{`0(m*(fYQZ zcfIG2C@sE4rR`2WM6OP5*n@VO=uAw3cYpa97`MJY~9@-(SB(rzCh%Mr%s+_+)bbSUCz!M zyLeZ;%luQLKSZuXUh3c${G&n({UPyMUGGIh3H~poJw|>C#(@!^Kuv?+ zVAT~&8P-u&Qha@lG6x0=JTEw#=PYC=pDzdwo9`Je5h(KR*XZX}{s4Jq zl<%hOIrRM}O@7_yRKC2>^UCLf3*Yu~-}#w-@jQF4d$BOHU-1(=qwfoZMYiH?fgjSR zs|%ig$yzU*z(=L}jUe2-n6A3hw%=E4ovbVJ#EJHSIb6Wl^2w3Fr!8{dd^SeS$CO=L zG(H5P?hC+^`T!=}{3O0LxL4n$NgZc=@XpR3iR>jOgXAM;@MY!I1^8T9ob%_x6W!B#t*9KGV6Tq)jwOgyX-$wu)bO2bJFmA_#t4ZCwW!b&)xZzdkWqZya{Mi5Ag=S zOH&emFZoj6QKR^^?P5Lp@>gTs*@Z(Q^pG){5o44>I`k{rUC_ZxR8pm3D z@OhKJ>8ZG*td0b;alD!GH&IsrZ!&tisDB>Mdimn8@zX()uZQg zr@ty?>CX4GO`qJTWBic2a`>kxq~#{J>#p&FH;-pMZ4#fTvJNU0qlCq!csqCcqr1%I z*HLH-^QPpVM84ortIx;jG@)%pQWAd(HGCAhgs+lqiLsSgB8FUWaI!lgm-t4@BF4EG1OfBzVMl$c}iXCd;_+w)?% zS^A8pFT#II`ll}%_EcI%DI zWiFJp^KsVB_<&nGeRbHbYj%ENEsjgBjgP!?OiMZO7bAK@V@3K-zdmA?2KAM+Zz#4t z^=>Dx%okydpB3_FbB54q*LBIedA#heO3*vN1AOF_af@I2SbWl2eEUpZ>JnYS;*oND z;&Mp-GxWJW`WEG9>)}xP1`_nAxb)y+@J$Yv^%8U&)+_O^bAb2*%;5(v#xD%?o*=vq zX#MTnAD4aNg&w^!vHC$BA1DcWah-4k&jiPQ-pkM~c*K`(nQ#c6XQaM9=>8Go5;_Ez z@URAihLYeAypmUZ?qoCx4T9?g`C4fS2@5YG%E-DXv?z4DCgF^hDc;wmw5;R3K|agR z7QdIWu0rWN>Ayx7yu_#Vw?25RkgcEl@vT+IznJbd1({!b@YV5sE&f8}(TSsVEAz=C zYH6^Pwk3a(%J(YTlBUQ1<-W=m`15A)*6@uax`gmGOnMkPdn*(BjGoAE(xa{Q{o%~| zW|tfF7wA#;ede<+-`jqRuar4D%_r%SuLWmozS-+ZRxU)A@rlR$4<8vf5%Xr< z;9Hh`V{`a%_HM*mpNe}c(!b(!JXpf`ftRD*#>$C4HLol_??#bTOc^u}2&wZ``RW73KmNL$=lP(r~&DR0~|V2A%lodvkOy{W)}!_A}{Z-!_9z z@~RH#V1CH>X3z~$x?eee z>FjgGU%L3O3KD!?$(+wTqP;EFmzu&4lE{l0U@wv!p60RtG;4c?L;Q~l4sRxo`l6XQ zRPRh2k5eu|_o#?%M`2YGZ)=I6Mx#C4F4P2la6oy zOD(*>4kNt4XWlbhIYCmON#eaK4pm(F^zwW}J zz!K?cxFPV%t}W{yHbq(g{7vY~#lq)* z;JJF0aYx_I#h;(W^Nep9&u8;ZbtyX+y=lJXar6Ci+cvk1WxQ@6W5Qp*Q1Zfk^U--r z%=0sOUHd8XAdeki*mnKb(JgqKJ)#7kNzcOAeCOhu^&cm`?z)Yx<2O!skLbw4wfI<- z@C`abX7o^~wS^n-Wi9b{AJ+TUNZL8Zn|45-)bHouQ5pHQcub0qcJ<;DuS}Z1*3%2g3(bxPBiLrx*H?(2QD!YZ z-p=fIYwUmhwdi)hP~ZT1uRweQHh|U^aD7q=i4TD_pLk#c=-&XW5D)aBvj(hDR|6PQ z-oKIXa?*hfU=8T^lP-`wp&t^@ZX*Qxt4WtI{T8u4!av4Tl5Y@KBkV_{0Ye}*O0OPa zXJg+TChAcYvM0- zBVk|&^syn=fFZCUVcHh)Xmm6mJ92|~|5u4Wm;AsGSOeC84PXQ4{~Gb|Dg@RR0Vx*( z8$cgelXUv6A?ZN>Hp&4*fz(w4YUHto{D}@5irjr7MtAJN)(Ji7dyV&c`rhEZndN~8 z8o#HuEPRO4ckv-uPv3p|zM19WT|b=WhhI_pE^}9%_d0wHHnVS9joicgI=q)PueSFI zbb7`-=Q(yB>~Zs8{Kv|kz4*_i@vpgf^#$V9;WKL_`{FQJ6-Yhd#}j<}VXwqC>W^Xf z;7{yfS$bw0%jQw_oMM_*zVK=4^;qn5CI5j~`_C!xQ&#F`Ph4l;VX)bVjAUhHZ7B1| zye;j~GFPipWqk?=kELyPE+aiCe6}pMN-29{Rbu<437o=)-&iB%g%_p}#NT5NY_KaH zw(XO6yLVhppDsfOOXvSD!$Ub!nf3*#IAd7N9ts`pLHePbY;|pK&BOen87tE7l2>8F zdWO6i&c-TaCRth*dynzms!K1$do#=$?>5EXp-*w>)gvAba@X{ohr@o6#>>s>&VuvP=|La@IS-FGoX1(xR z;x`eWmVb!&4a85^HEUh=vHREG0blo->9suG+~ND`FYG#Q(~yPwJEY&oy$JX-&l+ao zp04vsWOy^{q1Xtit45ndzGVF_bEf5A;dv4s72G}JUa<8LdZj6te{%LE^_tsnW%#P> z->T|p(9iy@?#JO&@!@ZO6uf zBj~kNjo!CjRjP^dB>r@|*PE{E>bSI%XFzY!1D(U(z#SubTR-wB{aiiI6b7!0%T@Yl zJ5N?_$F*^(A3e=n>h?u_tM2o*CEqLejr0Xa{kU|Rr)u_jeV`wect4i z`Fvlb%4)5u^f9&-`&UbE&e`tGD~=};H+i3nd;A@-7r$Fo2GFBUKY53xEB>L&S51A1 z#%o;L<7-u=3%prdV{|cTN8j`CBsp20Z2EeDb{suV6?QT%A7`yee#PPLD-U~ozlUcc$;za*TBEJy>B1mYnd7M%sXiVG$sF-(jqpt)W$hkkBbBFuv(2hsi)dY z8`5*fYFEyac!7N!QcYe;oqi5@+(N;>OYm=S_+PpPUW2P2p1&mf;GVsee)hd)Igq$X z&fT}ik9Y&$iG%G5_^vqUAE$5d53A(iuS)x?(Rgt?JV?^LY>Y4D9q8))$KGq{v~6fE5H>XvfHQteAX;8(ET0QSt zU8U`PxwY`#@i2$&S7;e%js-9Jv#oJ@I79_o@qUk&Hx3152;OlhOs z)#U~KBDT!a%Nq?|2oJ5uSZq$R6Vr5_&lC(0`nJA8A(wO`hj@L|&-K5s>5@>6<4=#_D3X+A6Vru+Xh zCXjy0WUJcJmsR@m2x&XWKTw-QPN0Lf9RVJ#O$09jU)Dfql(toYJI+FGp*Q(!M~}f4 zB63ls?-l11LT{Y7H1#(QT3SQ~n}_IEVB~0uzwXip8WXN=_+;ybPqyv|D0Rapsaxtb zUQ2zfhZ~WN_)i_43s3ei4UFmJ zMc4!Xz|B)B&!nvIZqBmk1#^|9^|nk__5?hUZwDTPmUY))gMsc!$J#<27_tV6{uAs* zhu$-8*9QG{<4v&!A-qAb#uW7@RbI1~-H*@uDe`O92hBcRj~(_jds@x<7NI9a>7G{K zLijkkfj#p>H-NuFOFiYW)Ef|2ABh9=BR2=i*;z)f^h0Z&B%QNc^DO@>4f0*k?y2$O9n39*M)a1%rZ49^p5?S} z`D?MaoOUf&f9NfzUCU|L9Y2YScckqS-AeGOe{r%jh#omexk1VeQf^Qk_68|8NV!4E z?M}-L!jHizr3X`fEW3N39fyKS_D@Y7yU*=IF7mX!Q^qah*DH8+(x!MuUmeprU+~1< zF1pp|al)MS+BOsl{#>>NpL%`zLC)>7w)zh|==o$cH zn#US|`|pUf6U?Pkr|Ey}6^EDupW_i<_hPT^#7?p}yKlP>Cj z&VX{G*n9RfpH8uU2gfD?S(7%b*{zL*M$6gShBcu!7H(u&knpYG8PjF;Xt0ht#U3p9 zWRCBI4~Y+i7YCAwas~d!m%27%qbnSMHvh-W5C6;~Hl2LQt6;wgr3DsLF!w;ryl_ z#)VC5P0^2IZ$Wo1KOY?3EqH3^;_*^fCZHXSvs6LqXx@elKS zjdq;qUaTvpku}x}*}n*mVBu{#P+Nl;acWCYHd})@9YZ&z`;7VE5qVNSabs&f^~ioO zBzQ2QqARWsSf9Fg2qa9xZJsrHVS>@`)aq# zSC)KVQ2ATFVDiuJF*eVEf+|QmZUN^y>ba%BegK_XY}9i8Js;j>ypHEPekfp_dW2^( zW@PM8Z>hX+xNN$d|M&p=x9t0}c89`?Q_P3mw`pmQ^s}^g{?or-Ztc$u--8)Go#9j9 zQ*Rnywx5R|h12;}A)*au@Vl_&pD+2*uTK7mc~ofGL)uVF-ZU(EnP2^$JZD?! zI^=Qe{vX_C}>jHn!yZlG?}>IvncN^<2W)M~`j-B|gltZ`&LP0pZ5$=<)Y@ z75{yv7!W^7oX9{;@@?kZ$-E2Oa_AS)tZ+RIKOp(3ufE9DA^9KVnZ||g&?N5x>L{C| zR$mCHNAi`;W5Fo$#zCJQcT%^MleAVSbx2%>d$jv%E#KW`b?omoMZ*|9F-wl6PR%$K zS;ekdnwm&#{qf%wE1ESy31t3@zX>c7W?dKA{g~80hAefl#?2e{8tnP}eG6Ed+@hXY$48l_*u(*>A>Y_0U%A(QV;iq4S)4Mz*A~*hJQ;sP9!5Q6VQ5I#1$NUX0;!Mh z4Xr#Rx6PD=1R4TlBg0{3qBKh;W`*l%cy@nH;}BUO&jIh>Mix}!_)N!@G;;4F<4yRR zZ1yTz+D7~N=%f_?1^Lhu6_9c0#eZI`G=Xo>cV_f6=dMI z)d%5E>F4Tr=y&mda(s^z`XcqmkJD!Ak#LPi=+ew->L~Pb?jAozeqbw4G~=i~&&k{L z*kbG?zwX-NLx-H9Rn#G`!d@)73BaG=xS#PM>sXWWq0ANY1ztrrJT|R^)Fcn%LfToE z^pVx}y~%t0AEAryxfPJJ6OVWMjZe5>COvh+w2AW;){0Nl7vvTF@j3E8haGYr{Ctk@ z(}bT7v5t0iCnZUfJkMV0Y+GHg#sweUt22(hj+ROM0yH{%2o7nztDub4N4S9Ttu z{~NOABIltz%<(>t{pLB{uSnlWU&y>=-s(NRn-w~3-d*-rJbaI zRPc6RuC;M}A$1G??fg5V{G);SkdyIbuY*$Fu8qi{)G0iz3lF=mKn~q{XV(u-~8##}ju|^m^pUu{Y2J&EjjlMY#JsMfB@w)+8OGIx9Wc~PY(XN%F@WQUC z*a}3SieGW@LaY3SL*}IDJduH`bzR`l<+^FZmuY>z#1H8R7{8N#KcD_)?AIiG3;myl z8-xw%`YohS?iW#rMJL#{RDTnUjU%=eEk#_SQ6IYiwXcWE2 z&YPqQ4*gbvSLw(?bUX{8*}}{CX4TCF$$u`|`6#3gpSZ?bdz+&`;+)1m)O|c(}M~aov<9zH5f5avv z^O@au&dR3@`9}OVPy7tQcKY8WMI+oGcl=?5F@A|>XH;I1#EWQzz zyva`-p2i|KAFHnyt$rV`JflaN|LRo+JIwUB2)7RC$FajFUq{~2XJu}WFLL>v*|^K3tNopjjCV~sM$b}AT{1Vk zVZ5V%2@MT+BK#12s!sdmj3NSt;Pa7ho7N(Ol1Iz=J#ox0o_w1pXWG-}o21tUNQZYS z{S8$z;N+wsIEinJb7tJdna+I1*8t-ytxI^>+Gl!MQmR8=^8xyyxW$)dfLka)?5 zZd!`4oz6)|nrFIi&6c3kAn&KV%Ciet2jsi(Zr6^f(i__$x@8Rr{~3wBQ? z=VkU>x|sHvv||oAXbOMllZM^N9~3^(FF?VY%}<)J%sCP81Tt|TL4P>U(HfkKK0w~- z{$b8x9VylM?NXimVzUz2V=W8${$qhWl$lQB zcTJQD&du51Tk6&5VO8Xv_B2;fKI!2*1vl=>$j5A17aHr`@6onA-xNg9B4uaii%9eN zorCVaRr~xlr@4%L{60c(&X(yqc@Mpdow8M*#p-8=8@rvHuB#-(QZCQ>TROTSo zs7ThS5A*w?Aw#}Y$87oinDoE?Fm~&E3cjqN>Rx`2^K`+=h54I8MPEogIgwqHx8HLO z-D$tUlC+34|1H#U;V10gp>`pBqQB&~Bq6*EyRl(exY_}BS)AG$vxM#bTZ+^l(duIF=MSh3UAl^quPM)WI)N6qHBIx4xD^hmqLS!BrS%xFH zC<{AWjXuiH)dv?bFJTka^lzQ_2-pPHfnv+nE9j#c^0pRLLRtgW~_gV5SkIY|U1Al`IfZys8iu{6u@ho#`d>nZN?|~I!N0ZUQ z&l;~D_XhqP-}ubl8#e@RipzfIBfnSScW}GdqbIks?qaL+pXbT<1^!j!&7Ueq$b{_u zMK)dc+?&$wnVy|C&^O`m5&3V6w53}3(i}><^)hjPq`S#Us-+I~GFI^dJyY!OnJ1)7T zrO~_Jf5*z-+P&q@T`h5~uj_x~&Yt1B_Virxww_B?U-h;tuexk?&(P{iuFUeJsI#C_ zhn4z|KluD@b5wOEPy6i+9LRD1Hn)CyIebzYWlBmr{|@G-Pl`W;k}7lnjS@e>@sD%A z)P0}vzdGMkZ>Vgpi1LRl&g75qA%HJXGvD1O?C#Sys_!Y|_3516&Yj$S_~ASPR8J}Y zBK#%y;g6}Wp*(d=`3m~Z?#D;rfb!2@2CaYgq?bJTx~K44rtn#&@MD&654YhiZEh|t zC5wRgxieP*xfeCLGAT{_U@mZfF20=9ujH){X6us^8md=28nz4k8gdV9YUYhn(m)4NGaJgI8;)6c_{#ZBmt9V z7tUOsxA(*E;yr#_zCwY*dVHL8#)pG|dwJ!q|0p>cL|czoK1n@+`iyU9oX7ATcxLYaW?hUy^S?(pq_l?}G?ypMl zFHIcx!KU;S!Fx2Rh<@XM1Nl`ELLIxSq~; z{8oMY$X>0_$$4OPagdZ#a;Tp<@l~wLL;5DBeRKD>d*4l7{K(_eLf9QbQK zeZph?bQbeo4H}y~He3Q{i9EEa$z$Vu;(X8f=wPhW;XwqnXQ{uJ4fBaB_UrBtn`$cbB4o0{) zK9zxbZyXr$!P7MO<5gY3l(FN{;9F~yxinbddBNE{XL;QJoi7Luo9`LpRZg%5cHo0c zc+jD`MnA9e2goCJPnYke>^aEJCry6c=TyGD(DTaYf~!FPbI16ZKJq+!XL_+Pvybt= zI?Xrn*IpnjV>4##g!J#~g6ChtUHB79YxNsJxOp+GztgtgSB$q<>RhF6#q1Ktz^wU_`J#A^ixx~P91&wBils|BuIwfl`W z^WA%c_s+9=^nAnmJTFVfr*oHkR|QoGySsH`a-&xGa~2;9wfo1k!9TOSD|qA5x9hI) zf;W$6J#9=_SFQihv%0iiJ056!PK4d_t$#+Lt#LcD^_3n=r*FU`aZ6Y?Y#!;Sq~afz zJoq@5v?pC2|D=O52K?#yz9%qOX8Lcen14#izvI4s^t8GBH445kZ%Tqo*2h*~j?-x> z_8KdalK4uf;U_`-Gw20QKI_P;r`(hG9ll92wm&B^bQ;r`(E?;pc&5_1{8EJS{LdtNLzOP}%dMd|uYd-X-=;J@}p znQxW#7(c_po8H5#g1O2k^BtcwKI$X<8foOse81$@&&Bu&={a4t>$l8}jI*#eE+^}NmU7}hMs%IViu9ene#9&d>MLpUP;C9`-A-Pa!@?N9E9B4SF=>j` zMI`U$@v^^4bS3ZrA9-cm;+KAx_08hjXYx{)=rlOU2 zoR)H@;=Q5a=#`1pdFuE) zNznQ0gd=z+IQH{ihIYXtesjx&L-0H!_4PqFHB+Cp^m>X-D?VVjsssEKiA?PL>`?uTDLOCJffBcOKF?=<5a#^(Uvq_ec`^! z7WngK@ZzVaSWo*VOnMkjdn*(BjGoAE(xa{QeRgJjv&)V83-l=a-sC^Kd~b?|-ZM1# zy$aV?V|LFnF>#RPJEAti*#rN&Ii|Fpszs_MCvLBK0y6o@9y?9-&Qeux8ugq0?m{&aJ zl^b4n^NNRk!<+x#%jVUO*!r=lQJV6 zpFzdW4uh|yxESFRNPMLSgd6apEb|KdTL&K`UT{iUc&RHh#a>n7rTlDps13n)d``>w zoWb`LcZ6=1r8ispWiA?isl3$n%jC=W5?+Tq@!0*_{mS`9XKya{H1SszB>2FRIiGn% zdt0n;HHF_Jkr&m&{wO&-&13&**5nL__#hP=-b@_zMKf_EZ<&eXamtzQT%{s*pPxe; z&Wt>NBf8wiHS9OzVizrz)44qWBe*J-b~C)hDbU)yi>JqO={ID)v-I z$uHAS;=9~0+=$-EgUzHt`%lnMQ?Gy4j`z+u^;=fF(X0KGbroOj4T0W`p8vWFhXPBa zr{RXcFT1v^f7lf5{(KXBH?B=W?_B+`J~>Q(xVg@-mak`gEQ9Cq4;gp#?Ogo%Sv=49 zmht=zd}CiCegCHUmdB;{&u!b>GM4eWfs6@%{X)qL_py%w&gOOPr_6&qc6?#m_FqT0 z;Boen5_~2-3uE)1i*MFnocO-$HoA_VINd#>BMaB!XH~*C=m?q7L!s6dZor?l#NUli zSAieU^-lJv7ckb*e{}C&>w8XQD#C}L;1$2sx;NC3g*WNC#Is&EExc7X@k^$+-lf@u zlaGB*{AjSB`5|)aLq{-zZH9e+WYh1NBYn3`_xssfxC(jf9tz4r~BxK);`Kf$S6g zkobUfpud`Q3Da*8>m&SQOeOgSaW%qzL>e#zVpsL*5w=5Y0YM%=mw97#>~-i8qPvDw z>R3-Xpud4~_{R%@{tD^h)M`h$a7lSo_Z@@_H4pQQX3R+cOJ0S2?HTfBI2)^w zon&cQ>`vB4t3dJ53e?O`t-fic?rA@{9nNR$P04oy>u)usQDY;GQod((_|&1l0zP!O z_3$i|@ONE!1L1kpb@0+8n5VvrUF{#ddDyk3jQ{If%2~OCv|+vQMdCLRpO$}!_zlEo zbxrzl=|%Wkt(#)smE+|}#^`B(xcCxq+m*-jRmNgf4;Oa;w@1hGeepz4MgO0Cmnpuy zdn7+_M`C#xZ&8&P8By$qL?$x)v-KtaFO64!2mIYqka~!`1UlVc^QRTtyzX^JL|ATpO4A(c#o(t}psl-REsf zzE|!W=?jk1-=}%1W}nyh=_IJC2fTp~0bkkYO@ zG5(gBanHc}K4?<^n9?G)xb)0*vK|));AgcOds0sonaa*yt6e!y;sy5k)Ojg&`Z?fn z3kCl!!A~Cw{+F(S@8If(|1ZgYxo2;spZ&2}4kT`p?-RDik9Y&$iG%G5_^vqUA3tpU z#wvWr3V*7!zZ#7fx5I-Z-Sfuh?yc-Vr|&=ZUQ4H?3w~7jCPT^y9g|n~=%cK)lXnd1 zmx1=11o$+-S@ka3py*TSm!mZ|=T)CI-jQT!P{jsYJ?~mwrR{yWwea5YFo)e(Xc=gZ z1uy#J#cjyJ_SmfzNw2DC`Y!$(*JnHM7rTRR9Qw_p!AqNt>z!Acz*M05>ew5Y+7fJE zK3?2GdlbI0`-zkD_{V6^%MoekNm@@}ur0jA{3&%FF)x>^%M1ENY@Vl?oBFO|F5p{^ zZTryQ_%=dt^ik(PV=~y5^ane`N#uGmm{k2i-?3`2o%yM6-wWj<;NAJrrDf^QfsY;z zUM_44WM3|G^*}fg>;Ud;JQ_SEau!0ngum2N?uQPkW9OGn2K|37=KxAQPFk``Rr=v! zf1EA12_H5c;x|`xD?g<-gkBkwmgci!Z@T|KV*=@?Otz{meOaY1kC3*5 z`~$T~^En+dmSp{tGMcys^I$~WexU3r zLirBk8_J%owBo9hE@cFdU4I$RvIfidBwg%LjmNx0z0StJ2)p4QxOpk%nUodY%~=+` zVXm^Y-j>PAo`5Ivea3^(vhEseHPBt@SX-zAL)Ko=kAmIk+IzAJ{Uhw9$&d2pY4-Da?69Y?L1@;x2t6uFZ4mkv!p9Zc5vSv6_$##3Qyxpb z0de(_I50nQbD*62W%NovwB||DwXZeL^1m|P9jY%7TdKT&#`Fe*Usc}nV5weqA$W;5 zFO(|FzM{NAzMC4fXC;o8GtT_`=!-n{b;?*_%y~lp26p5qa}^kPfy#D=jhwIz3Azv#qf;bY%8ggxy9=Sw0N!K)@eZ+Id& zxTZ%xmplqwqz{4f;F|gRX4ag8YkYlhjnXHQErEQ8A-vqM<}STq&0d{wX4VOv0p&*3 zM6jPZY>G8A;M_{qfemYRYh$6&au&8>O{k598<~nFd@FdybXh$btfNk`)e1hDS3BWD z!dY1-yf~0dlq>K*zQVN``&r=twD~_~O#U+u`nR7ic@=C6WoYqFVvhr#$cW811`m_i z>tfE5x<*G#v5UEUbgOat9A(#&Hy(2ME7*=IKR8qnd&s4RAw6Yw`;?uf`Y%AP^a zHtaqi87n6*-B*$QKqi}A)UC-kv){%7b2eux?APwcW%7X6U{H7nq zg-vTs(T`(qL3b`c9~|8+cxvni;sIACpdF2~R6*)#UN)TXetN82R)@WH1y$Na{KGt7 zqa7!@7wgJtWQ{pm_7s96Sa_Qb@IyZ%PHhRwW@`}ti<<*)N_GGF;1PLJKXLK%sYmu| zA?X|AlkC{{+Ozmg9n|}x(!YJy`FbHXxNiFAmTE44OLaJZ6Es$;!{yF}v{C3I-&ea` zzOv-|g390W1(ScCvmwcIpr8uUj$6RFj(Tn>p!=iKiv2kG@qLx~@Gj$Ze756<0@kTV zcqU^;#t!wC$_t0fW})-@9$=f6y;#<6*fP+MgM|2Qz$K z89oI*^``M+1be5AD1c%Sfe+M#Kn+3jP4!}qO+5dkNzMwN+10p!mj8aXU!2= zmpyfid@;ZJ@!a;ej6XHztcKba$b1#O+EIwMG6#1hrDjXGPS|(_Uoq}_WIRph&lRH0 zt@&M8^7lx7Z*S%BPh&5f&aVm)Z8(G9g(d%d$&XHR(i^vPXS9d3p_aU9Sn@Kz`aRv_ z(|dzu=>2B0%b)Q<*2nf=n*(hQ z{QsW=%hodf$4Zq!WxV*3QYBl9<@>eT$Q3#q>ecmJ!Z~J-ZUQAf%wcEQ90vj6#_NXz zOdA#deWn-?KT4de88ykbc{Tc;3)^z+0is#qdK!K}@>5@Zk*h=UKgctU3;n)H-UHN8 zHb<>aA5f3vE1SoHQEUI>JD{{~fs)n=r4EV9aF2FhZNC-E%IxnoMZ=nYV%EARb!ygi zS=%_HC{0ZyZclNzSkdT^N+9}D{0Oi}7~Naex{pcyW2`-0=*07ey#_WKf8PRhS!dr_ zb^&EVc+PsJ(D8(hXnheqiav&{92`qaJldnW1Y zc$mJ<8LMvzUZ39!gz|fVhwrt&7cdJ-7N_WgwT1LAPsSgShfxn%7#h-bf!*|pKMi$gQ$7edOq>+0c8E?X0 zb&glj(l*-92V|xAKJu}bQ@}bf{z$RX1h(#vbl)(0y*SX=?d`X5ncZIYO*8tRZ!pe5 z*Z3`D>fG2%J_K%{0oEnF7u*sCvN80M50VZvz&fxMm+)y?etDmk-@CyfHcEj3^u7;R zJ|n;J9>Sc{@sy%Y+V`8(#rJO#_R*DO|6Z5)_qaW0DBqIsaDLF0&72xJQhetm_I&vs z&+q0N63+W&kF3$#X7d5Qm45DCk$s}N!}Uj`IDesjwVO6mkA!PHLYGE2ig!YZL(a)7>X28#juNBCN}B}7{fryYhntiSWe%Ay@G83D zvFW``P4X~aq@8t1A6aeRo4l)cLl?hCiEo20An*1&zHq@zdg_E}6KATNX}pWRAg}C0 zpCkWs{QhMg{Ctk@V1=I#p^tZUCnZUfJkMV0Y}8$^#s!}}TxX1IEH70$pI3Q_Ydq!V zpf2cZtTEP3AvO(ZV;m?86Xrs}+se0yIyC#%WFtK9hNlUA3Qy|NUdCnEy;6%^!S;76 zuPA4E#e5>Xvhxf5-w@p$IS=Jw?)Q1@Z!xgr2rbe#(ibwHsc#kSI-^22pKTER`IprF z%};bt0cl^D9?WXN+;tcg;L(GnaH8kDLkzU54*2G z4&6Fv*BaT6rZ%tmZO9#VM+J<4@nztYFt7;}oYOSRSS9T5%V|Fz3*;Lx31@Au3*TG9 z%~@d$Ev@NM8g9iOuW;koo`24&dlVT~*cxT-%ILQ?75gok8;ARZf4#DXe|CC*?#uV@ z*jA+Onxxa0@_sI#2YO zt94!A(B-;m!dR5T$}FOT4-!a{U4(r`@zZYY5e|Kd?PIFQ8zn0jYV#s zVK{3NdsaMt#%`ikVmIk9(_`#+_ncEAbWTiTg^GXV^EJOC3KpalZ1*b({^M z+ne2`ik!Czk78^(!XK5&nV*AiGVW7*lk^jt2K&2w8T*=a4&qBmr<*5ckNu?RXlTF_ z;fL4>>a^eR%}fLg!RI62Hm#+9C69(i;VpBGC%-F^?=h#p$s@fsKsvlr>(jmMhts|m zoWwWA`PQt9-`j6vd<`(Z(z=9~t$n7KC8av_H6NfKid)^ zrF|ytm_rVl!r%F%aW3l*!Y9trL!jWz<|j>9=9~z40+~3FurKDjE1@+wmwhgIr~8LF zhc%^C-}+8nC%>HOitMqj5I3e1+SnvMX4upR`PN~OzK73Q{&fla^=pwQ(sJV{Sk-QwC=Mm}cCy3knfevh{0`3^RM7AZSBUqqVE@7s0v zt=i|e?#*T7i;o0?bGA&^$$KCM2jf6!r5#>`3`Ob%i&yMHP4cKA+OnMQ1Y{0kt%_v5 z`Y_*Z+*9yny;S$|`}GA(A^e$D%(oYUCnvIL^7gj|LwDNW2S{2(n*SDXT=)rV^Qv74 zALtMH?Q;mP!fwuRE!=GHqX>K7Y44~AdvDbZY>r{?ZH!leV_LpP5BF@>@;!REXU~k^ zPRsA68^rtAc9Lb#PrU}HFM=+9Z!Kk~E<~m|BhGLH7iD3GtIF;mN!d@H@0;jxpaM>lMZ-Hv5i{ zJD%35?*($^5%vpCzT;e&mZR;`r#03{gN;#adhsi+pY^lGtE+0@{||hB-jMoO*QE}7 zmjriU$am>}!Fc{hV_oC%3(8Xk`J-zUz-DM4zxM&zX}H$7o)qs zZ;v+F{Z{;r!ap@!EI(zu1E9hb+!*6*|SKBslNX|VZcDpPg3>h#*rwb%acwV&tQz2q!^ z{{y3Cv**6*!Pk}j=2tD@r+3L?UdBW7t!ayQbP?$k@1L%IJuW^=UYYyW_wTb~dRTPS zFLO6j%zA~j?*Yo#Kk4N1`PR!1nCJM`%Mbq4^ZAz6=UdwSeCsrxeoK2`-n0+Ro7U&s z)BSvV>Zk8$v-5wQmM?4XZe-N(wDpy5%_!e~YZkcQyUhLFN=SW@RjSrpyVb~gY@9V$ zxbJR%|J|eIggb%c-CbS2-(2C+gdIsq4XD~PW4)$xQkh^#)z%l2l3u}mOe;Mv=#w~Q z^a_6KCGn({_}~in{>&`qcV2um`OKJ3)0}1$c_fWWf2*MvU&(K;_^k|SgL5S90`4S9 z`5}|#7o_}_!0&8H!?)Eo4gAPs`SF_%={I_b<0tpTXwuvIP^Q#b%GOhXiF<`!XB4zK zi60r8lh>Il^%5K;O#C(Ej4w)M;0`6JPeOTFywp2>pNr4xkszO~i%`l+&T?f1P|25^ zd8#aB-KWY*Ry$tt8I&b;g|?R^zY&nSW_6VMCGT?e4teh+^>2EyclDNK#_IhTdOuRP zdar5Q869GMEcYV`CJFZ&)uDl<$X5`*eE%zyJ1+S4H_O)){o#9b$)}I>`i6TtLw=L6 z3H^{XqK9?T#PlIab4>Vir)RVO4#Te%T>bgYfM6@>o0GdugLi21jcgtLY4J?c$9>{k zgs+cXxO{smajnVI()isrUiJ@?k8gg7Up5mzPJZD#J;QgI%{NYYdNM9c*%7oGxvxH| zjn7$%^k><_%3ezLAq{l$>M>=;C*uz3E9@saBKmuGI);qzi;K3+(YN|!uMwFW(D-y! zlk%gZahdPvOEvWS9^8xrrP`Ad<$K1qnojb3ov>qsZ6r*7^YV4V8zZVzA4&Y?NKk6g z&eGPMlpTR%#JAkSt42Oryv8?_rEqOv^uE!uyjM@aympi^k+#diYLsKsgS|`7{w7P$ znCsHBS4+b>_c5L@1`5AWzT-&4BgP4d3&(-fuqsb|k~&XvCNasL7Pqux3%AImdQ{EtUtnVH?eP0o8MzOvDt>gmioe1A zEe-BeY(ZO4e@~Cm&mZ#lPsV2dBzNX#(y|5)inOVW3f5#nD|}%fv@8KYGPu3 zvmy0KJV&Ko8yG+JRNOHhJmf!(F4clp?Qb$gc2d^XQ?~y&di6MC>YBK^kv85SZB5ul z?q%u(Q^T`eBXD% zvv(xap8t$r6AT#hgx$d|z9*sIb)wVH@SBvdt?!u=?5}Cp=x9*ZBXL>3{<)IgBJ*5Q zY!+*!s?2rlDeYXhb^f_-S81QOY#YCy`!@SFpWn4kt}SVFPH%@#cCSauBRI}pZ0jF; zb$+AX{rtVvXVeF85;G1po z_S|RX{dqmzu=8tsy3Od$5(8> z<+iy}XK{1GGe7w==lt}6`GfzhgkG`k>a`DiPe-~YZ8vlnB9#gcUot*OEk7i)aUj( zdzN4LEz7%3TDdPx_#}_Hux49WJorf)*Gb)*+z}lwa%sE3=Dsx(_%0P&f_=0VdBYPEKKHnl^gixcBVQO} zD;0edTi)Z`r)XYKUQjI7YUqm(w&PEJ#PUjh=ybMm26wY3{WJW<7K`T2z4|ptd%2)Y6HODxt(z5_Jq5WJMfCNX9T;n9pZxX2Omz`Q}SkQ zbh1#}MB4a2q;YR>Z+CVN-p>oQXT!cXv7w9c5qmEMMtaVYoT7RGR|Gfm>c{=nJ`(A?u0j&X-!C+V$wH))Hr zY_aMxe#&d{*!yoQMNe0_uNL`QJT^=drafne2YqjVm)t>Wr5vCiF`a>ue@DDukvsa7`f*|K}?G`cdIpD+5u(;&@K?i5YFQ?TR4F5C*Y zj6ZeSL-bGdr2%i@KQ6M+9ujWU6<##L9hpk%Q}$-saV+pn+J=q(*bl^JWGnC(kGlNn zfO(Xe6kD)zhqS-Y^Ze6!PD5Xc#gg!_>7EX}+A-#(4s6C!uI^A>{4*G#*3p0$-wF3oP&4*Y@}k8R5me$lOXhp$80bXCdI ztJitqq%uZ*#1FSDrm1eT_19{h({)9fI58Spz^szZpKyORbrBm5Ssx8P>-wR=E=SaJ z4t(60EB@B!W9-Lb6U4?z84{P+emggPB)XRz_mewM@yqh7bFgEyxS;3bquovA2xFRG=#FadWTi@S-t^R!;GfO}XK_wc&- z&5UAc{M2S6xBR+r?ocje;X6&&M9J&s*+`v|pSZbIshCM9uEaaBlfl|WZv|IyXt(<< zvW3N5QV|;^b?lRfT@=|=-y5gt}w%GiTpon*3g(vjoUB%O;(eFdHA zO8+^d-gXppNn_aWJE!0+3H$uySDgMV86EO({J{}ylhFsT5hME3-}`d4Rr#W4&MVmd zDt*qJH|nW0&s*ti(CNnZ{zEJMdGmL>wVOFZ`oQJ%sfYdG2NkR5dNKBQdS9yA`BBCu z^gQg3s|jm?;14Rb2d`p2D~);4?<6J>TS<(y&C8^(V&@jySepBD?bz_DtCz;sM-#o% z*}CJSjBAO~$@kn^MOP`WXR!%c)5X7DsC5%(*O`gym%&SS+4bdO=1`d*WxSTLQ0C4@ znLFbHZtm3Tke%1;_`;kYS6m$*eC>#ld}4!1)(y?`Q#bAUV9@6`R!~3g85WsuB(01W zVT|n}(r06ajgxs@(r%fk>XixW4){PHd~L$=mo^TW11vx8J(jX$tzh{`zCCd@B>gG* zTpPVe{#ohzg}=*Z%R3QQE$>Om@4{`HY7F+Ums3bKgE@M7Q=69v}(BLSJudK-}eE+4={!wxBy#A$a@U`dZ^Sx-yK&q z;UbS&k=XS?1G_>A>*5Cfh%~}uKkh1Z7Cy@CtyS@d@OfIw8$j+K(=U-jcnOAeC^A%p zhwzoOV#g|zNn{XS$4J*MONd{vh{z-JqR1lmGPm$&vP|P%pUScxcawA$&o;a0GOr?O zx3pig3oKu`tM=k=94Te<=YH(fHL%%d`h$|Jvo-u0BSBT>dwERaWZlkq@}TPT`>0#; z=c#_Lq%LWE{MEZ^+ra0Y@U3HSOx6;DYnb%Xb@tXK_XTFMc#RovFYixgmp3=xxL#<+ z+4lusa_QcY4BQi)$)Nj{(X0Vw{XfZCD8w!Mgvl}P#>Z{t8w<_kSTI|@!*k?&6VHeI z@$gI&20|CW>kw3%@sJr~%H@^2wFO%>>HJe|6^!bYD z^7tfuhCSjqY2!}rz-KIwK4fd%o%+*#pxhrX@pa_H{^dK9v+r%>Br^JP8T%Kw6 zeG)GD=jub9yV$|`&A6w$Bi2D#e5YvTyQSv3M zJ!*0`@;0*RY1{emc`M8_+%nAP;-bWHHor3yA(7O>{6FwW1$y8d&#ToFKj#wIwG^F-u)`^Q4R%dUe`q30H<*TmGheqX#r6mG{LJ>-4I5t4vB!xY^7k`7 zL~efQ@W(j2;XEm_@psGuZG1%7e|0+Nu3+o&B#~$J!1W3LR$MD-?U1O{hH!xFV^9 zgon_&CLG#?>MNl&!l4>D>(Dx7HK8H-^;P(n6Ax`d>rg#JyioRpIwYLkMhMlbh!;QY z7BN49pR>_HSRKEPh=Ybu&M3V`6njQI9|*3my%!-k@F z*hmpK`+-W7y6d+OoO|#m=V4iVb~cucqv~13Fs-!UG<`CbbGnNDbZqpq z3jXAkve^?i*mne+*@%v0c{5u;I&k$dugB$3ov4}s(8n+iaiu- zw0mfWYO>wcy*&-%i=nSbyGvS`_nszg#sD!R zDSO7obceIIydn9%wK0_OOHOlhh~Z2);!If15Czk057g)x^&`sMFY9mcwR_2dfjpkO&a}c+p1Z$X5ShbYc)2UBO0G8%&fZ;V-3o zy_vEujVm|v44Z9cnD?l|w~Q5S`RJqYA3Q544PP8r2Wg|7JXyY*E{`ii>_>w&ZeKL8 z@-A;j@@jQpY`{OP`@E@(i^YLRRnx#AzWbc2}D@82dXF^xwz+ z&;)IR&1EGIe}mM2Fq$au1cM~q%f{FjzlpW_(2-lMoK`OI801?6$s=-1UEFI9Glx#y zGGbnV+IQ{XG|YS2UDQF^QQGBj-HmC3&jjAXNuNK+IqKk9mzzQAK2TT(_71}WXTKuL zaBHjovYsgKU@YDlySX62#+{+?Z6d-^9E7q2M9^d)FK_H(wn1K@FKNjlJRN zZT`;X6XlzzkHT*J5MlBz`Vs2$N<`dQ64&booEdzN@lncrIC!NxxV&Uu<}C9i#`b|r z=<|G|uwx(VGT!+Mj{(XYZch0-k|F=*a0*?X@~700KX7Ew-^sbdz`pNRABOMEpXsYg zdk%l*kpD_)hcEkW8HfE3Ozv%>h>`7aDCE$8TyKWBBRu85PH*T=q>Ul|INu0a26tZF-Y4h-cyLY zapL0Cw;i>zhz_<6(yq|R$rOLn#Sb?pUD@Dd%LXS~b_A8O!AZ)Nas#ieJmy1rj~@S} z<8$uuUdDl>R=6EWgno=O@~y0=E@O>k^r$sfCMD#c9l z3U>46WnCcegXZR?_BKzJ_ZXPSw*&Ve%lgYWgF)_E$GTDj8ZrmU`p4hR8hX!!og2(I z18b0DD-SX48d`ns{Sz8G|^{-Bsma&dpM!sd_TSmTR>X5gLe9OqUjC{M(e9ORN z*|ajtQaqM^Y@h9i!bs>3(VEbfA_A{=H9hpZ*`mRr@S_;z1?hDyVoSx+wDY7pM2w- z_v~jpoo4>_k4*Y9Cv9508ymAi18mF+4Y4sRbTiX}(Cgu|)l}6({(8!k^I+j8V|*t# zBpM192a?HZ4gBLZuFjm%l@1`A{t4s5|K?$>uZtD0#`#4RS@dzv{NN}0YSV26!vx!t zjGt20_*hWxVqO{F9=J6mc{h?azQFOXaXwZ1;lYydyZ7;fRXO`P2EGyFSVTH(Q&;8v ziQRKxyHwuu$=)Mt%Pz_`q?_GtTm67{;Vt%uo3;o3rqhB_GU&=nutmJEXS8_DkK)ob z>w>b5V{c(kp|}7ZJ#BpIti|I#mq+a9HcwL}DW`SeXtC$1t<@@ezP_X?*AV^y&kNM! z81EfxFQIG97qWj59{!>mjIXx)v%=IizZz`!I%C|)}_THJt)wZYM9=OXGT@{#TvJuY2U z(tSl0ul-6;e11=0(;O(NlGNi`c&?|MYfJ10SX0XxwY>jc0CpMH@dAg3f;K2eFq1wb zeTQ-@)kUM#pv$v!xzBz|_I+8sL&4$%<6+MYM(QK&EcIRR)E`yb+cV>LPsYz={1p7u zJLZ?|r=`rLr^jCMN0r(_)(h8+#pRGQ4bwB>N2ezh&00pzK{acch_g$5G~k>LU1w|) z9g%&zj^{t)%kZf)W;N9gU&gEG^^Q`sJuXLGi5=TAe*=Hum9(PY_5LIMX(oN46m4lw z@BEU!SJLxt{1E%La3;MfMbzOGf9IF<3nV@3tK&ar92Hsi5I546HuXzd##h~2^)30nq&{|$2}k-(qmc0Kqt~>c5*`-Vw{3}iAAj>C>-bM$ zKlP(Q*(ZFQFwud!q}#%`lSSvZ`B+~>bNr3e|7l52d5tq&8It}Uo*7=O9a^M4KpEBG zuw5_slq2b?!6W`S`o@bs+wY`o$tQ8`RLYRBjQ4oYrAEHH%gWf_ACv?7=&?C^EM*${ zspu-_nw9Cv#Fig_r(8442}&sAU;ICyW&F(RqPw4!^0%T(UCeRaqh6CepWe5SxykJp zm!5-u?gMl5Q}%Wu$ILkhb4ey^MrXw%cl@ogou^bvIb-r|eq@w(Q9E6`s24tEzk!gp zPCiLn7Xmwe3SYf_#Dsifn>_a^`;Be9zG8XG_+DQ``|@P?h(3&a=)%Z|X$bA1O@vY& z-y2$eNN$*|3kfp#=tjoF>O^IZPR#K)Qvclcn&Bb3K$-*I{~29SiNl$Os~GfNqvI{` zO}2P7BXy(xd~{NY|Aus|6BU$x=*53suC<_VTJOwiXWq}A!FktTqC4+m9S@D5$zQ-j z{Lq&8|D1R^pMY}y>Lp(#9@?%Gg2#-W;?DF`eFYw*jUR{l$S1UVN>9~e_&LMpsYIPg zMg1vd@okLwHDjFY0U9>kty}GTX4YezF?Ol+&!8`gZy@B%Pcwh&p12(IE>PClhVgdh z>?~amf=}gb*LbY&;y-k_M~d|#<;RawXUY+Ook!#{jA`mH^77t2euVVUc1#TYsL}28 zZKiM0camRobS4gA!J_btp7ze`(?R@RTtlKxq~AMXaw zXZb!&@Vt+Cw5unnNSvg3W{o@B>cXbGX6@A($6j)4rPlepDoR-MNjKJXAzyQCVD~z* zFOoXO*ti#(Fy;y0cHAP$FswI&`@y^iOcUA^Od3*O`d`?y!pPplws$*LpqPx95Gv1gFrwdKEjwe&DI-|=U|p+%lYK#H<=uEzSPW@#bDNaS(o|p zL+O0^U)|a``H-t4@1tkU5dojiW^+UneF%P)wmFM+G`e2rcLOq)$hygw`Qs;LJ6Dc_ zg`HD5E0Fb6{F)0FS>-nzGA2c5i4I(98bU|jXIj>Op)qGm_=t(1@pZKO*|ax(zb^i3 zY5&yU#2*lE-c9^up`_pK+A$mRBK(%WrI+xonEoo*Nqb#QKGrV!9LCT{HL-Vk3!1Ogf-t2S41b}tTMR@{)<@; zGwOoP1Qx4KIEH1ONHbAH;A`VBJ1^8~EZ8_@Q&5}&1& zbjc-PI>=lPZ9r$06L0tH-PD<}Is5)2o4ev4x%$ffKY8ucJeJAWlJeKkc0=&wn?yY{ z2RHnZHu&9S$LgD9yS|TCoLWZ)|HZ2<>j-B0MYw&~JjywI@=f%e^{kBT@p&%2 zU1OH}s&)7W=emB=UZ)n}^&#r?)I(K6+lNRgWH-a;?^4&t4DWn|zxiOy9P*Ga zeJt_&dj2rFy0d;6|Cr^DbQ4iNV$WPDuK@A)Z6e zN=#WYHoU37v;GnpnqVS$$a<}Z(|P4c)6BGOu+8rb(DxHw?U{wl1M*#XkE_RY<<0ewwPhV1s#vLooM$Xd z*FGkuy;&0qFBzxCi>fl-;m#iH+*A58?-Erh6y7qf@GfLOZXYb=Od~Eh{c09fDN)W{ zmGdf@7tyJwUr+ox=|gq6D%8GX?xn2JzG_3Lykmx%KHOj+xJ!Q*UHnCuv}4=uwrixH zlSxN^q?j9E+CF`C%sH?qFtcEHyfV}ei?Hj=&|9rav)*-aF&zR ze;4Zk($2IGV-E93rLp}w(;&T^S&8m3mk_qqB-F7*c>KRgwZ<~eAePbg;GCsjpK$*8 zPbJcjXC{u{HIc{XTO;9RRbd zg&gNI7FqsNu8pa){I*gskl$y?w>&a_$r<>YbO8Q#Euly+Jm}9dmc~cXSNI+{U(OMx z{P>9LXPUi`j9Wh6`aXTceIrt%FLTDx5%N3o_3Bk$&WOSxc&SNW{pU0vb(glTGlvH3 z)nsoJ{GQWc^Gx71;(lMx^Nr8ky>V0cro8NTKJt4Neh0UUJ$iB@^Dbv~`gxw>fUhqh zZSh1kLMLSJFS^kX9pf*4{0@8W6RdD&s^)TVC(axJr?qYj2`*=^l_);1yu<3F}WmV*4$(%}JO=%?Y0IO8yzoe2xd^3;eeecE!4@*FNx# zPhR(naF|=qUxdpiR;^gQ;{B`Mzx~4ZuUQf8ShITPO{-V8ReSfxZ&~qMySLr8t1YbE zx$z^n^^V@Yr+4*xdsnZzVPa^b4pkyWcN&eEi;GcOn8EA{(7eEf!aiaM1hcfARL z0{3ro>!(-1CS{<4iZaf=L-6w_#2!LLl{%n-5<9`kD}`U`zR&n)&NkJX3Y#zBU)}w| zY6=?y*a8g}q<(9cAW#EO2Ht=vn4R3oJ%Am~hoS08rO(4&@&NXj2AaxKN0e5`clr=E z3Wt?Gd#Td#Up?U^Pn`4=cFPnt%M^CZ67Jy+xJ#RwRFX5H*trWXfpRZua&c0bvB6y8 z{#>52`7V;c??{$`*YlA zKk33n=B3ztQ^Q4j_xmo~!BDYAhSEmvtL}^s`962<%02#3a@dcyKWs6Oa(wkg>(2Nt z#r8?uM_Z9MJTc*i+{LZ;#br&tFvji^`Y3kB#>MvJ3(5jqx2_KaYc*-|MufAHb7Jtc1%mz*rrHjy^|4{6*R+`pT)wfcFX_Ket&dI3HEmx8t1 zsdlG&K-*>flZ#xNhJ+>Q-R&Z`*htpgO)T|R_}%^PTkU=9O}Y12?h?jcjogQ>S0>nm zCX74n^#!O4)J7I#?7z1JakMe8LzD~RKfu)2ixac4CCCXeXpi`-Woa@TN+xDY!Q zOSvyufyr*d)D0Z`xbx1-OUkqGTVF3Nq6H9Cd^E_qt}}o z$Mza?M!}2Iv8+jXb?!rM%ALrA1#cI2iURQc2f`&ztDCV2{}wi>1%t~yPk#`b>OCRU@Xcqdk@DqF%tuqE2?;A$Op&s_h$8fJRP2$4-z~1GpM^q^s z4_Xc=HP#fnJu{8${ zuaB0k-TAir%cbs4KSZxy1E=RaEq2HC6`r((*0>8-co?Lq815O5EZu2zp?pfFNo;qD zY-87($kM$=du2~B5*e+XNn{ZWMcxKuj+Kpkw(Ooejjqh*=ZpUEG)S|QyV{fQ6zsUM z3%9~8<4>LT5d9NA#Wb%*L2e_Rz0kVeX$ z$=^fXGidwI2gUV|sbY1J=T+YYuM&F7z2B$W#q;bv=H=4tcEu*@thO)V7u||?_&TIb zSCu@yn)~S|vB#)B;)h!n(^R+F`fIh$>AE6KoEQx)U=qdVPagI)b&>nkvpyPpR@u45 zaHoFMa}Ipmm@EF)=VNSSai719lQK@(V4a&j65UIV`^lZB_+|OkIoL;9T+s9J(Qj$e*s9-MTwV)(&ZWM(V$dd-v(;Nm14Ib60%rj*>SGHa>OgB|O0P z(6oeqDzz(1yNqMQwTpS~>)(h?Cu6JhX9??M{C`I54q=O{d(oZdzC}SU z=Y!&gC*zK)*tVa;Da|*v({xRgyl$S2)Jg1r$~>r4%pxqV#5=jep0&$- zHVj3!uozVIar6s}+U*<8#EER@Cl#?DP{($F*eoy$oqjaX6-j6HrHm~H)=4H?CmlIn zP13ozgbnmeSNhKx^|qs+OB%y|-#G~$>@-O;}4EtONcQB`wpT%{k<<& zTa_<*=Dc)%l>UC+sHf6AZ>6(AryJY*53Tg)&EM_TZU(#U5w?B|?H&A};?{19v7OQT zQq|6nGB%;-VSijrSPKMyP^mq574sQ30HWVXOd@tpN=2`Enez^(`epFaUAB)bW)7A4QO0W- z3uW$nl({oL;O0)P4%vCljxWslamCf~!Pkx$$tU(xWZlp_KXuct4+edHV+HjaiLG6^ z8%ZnUMHpjug!I{%A#&PzUD9rusOpso>kjxpAAD`X@|QLi`>U4UzMv>&$y&kkk$ijN zYDoH1^0_v8k^HmL^$UNO&q%%#an9E-w#jxUvy83H%h*F;GieF>vxN1B@LVkQ z;Hm%Z^+wvPSN(;>ThiBu6V^|0<(|dxn;NZ}C9G|juf*QW0m2V3h99^9J1NL}4F7tl zwLf!rT-Ah&JZ42=*9Q%3ek81m8~7tI6CV3-0M?W*5huH&f?i- z`%&gqB<+^=Yj%Mp_M2b)jU%OO{@jnPsRs78On*?4@kPV0ft_cuk0FmqoUGd!Paaf# zejjy9{yf$1mDDATkH30XZ5#N!6TWq91<6`Ma1E1Qy3XF(S})^@#~$m-lWtt`*x!2#{<#_yQ#=CN@PdN3AN!kXg|lzC|74|8`o4_w z^500B^BMo|Kb6+381<$}XI97A^-B+D0~%h-rx{0B$+O~km_z(!z; zePe6%QTA?xTf2gLYtp`AU)x_o{{hSKp1|sfIniAe8*t<3sv)jHxb>&;=xf=GDCzSR z(dBXMUMu#9iq^M~t`4+7?sT{Skc$hS`fGhh{L=PcgS=Jj4d4@bG5yXq-8lhw7ir z<5BV@tUYRSHu5&IVa&(Vn_0JQUdw(iE{E}}Rnf;x<^#yQejb^#dheo~z_@bellv|C zr}fGBzo|ZH|JGk?!-8`d!2%n8v+#_DW@8a7bXe58nFF!8R9h32#jYM0yR!{-zqKP; zJIYLymeZ+XPjysum39)_-MVxYYfK)_ADYx(?9fl2{F3eOovgnEBVE4AtN)yN61YcdMc;UVUta&Sp^Ruz8 z|D17<$M!GIcJ)ct7Ci1eq5{suXMWCn=flm~OB35~J%MRpC(ZPXnaI+0*clc7l_o-G z%t&aArJJzlEa4x+rm4_Rm_{f2!E@;Atba^D=MvbYll4`E4L#v2cAHIqXd+8Dn1+Ni zU$-p1-n6jGWwzgL*zl5$Jx=_Pzn}3Ta`QunKgQV&=Sh)`zhj>G-8NniQEuTXuVLk* zT%`MLl`RrJ^L2~vL4s~;P1RpRtI&nzM>GCK^$IGbT#Un6{0o^{y8J+nO3AJYdS0t5?@DN(pghQK9eI>L;I8-BN9a^WXCNw0!z6$?x z;-O7w9jb?j7s{SchlI1+2%&lv@#3f5BIZZ%qfaHpCSi5_IwB4lLOG-K8WHDg?7RIU zb{>m?U1P6jEg@^yaF8-Kk`Jmkkq`TDAyl7F8Bnoj*My2KJbg9s$P_~BVn1^;erO2Q zoFUhtA+#xe>K5@B)@Yh@>7gOC4y{9*&?Z#>D&b%iLhENj$rnPKPz|k1 zJnhz$c&NUCe9%xRW!0eueXOH@vW5*s@9vLTJN9zci9D&hj=Pb%o48w98Za=w?b3(f z5T$Ohnb%0&VneW%rNM0;NYjH?l)7bnY~XHytG|VP(<<~H>>FS&b6$P#ms!)(=XsxF z$H87V4#t0`?7J8JY#RQC3s+wuTpc9PrVX|_@EoWodII5mi z4AV*rPSYo2Ij5`WPqWW`R*{ChQZ{?y2K$bHGaJ#7EU(NBRURF<`WTrr)rqP(0R>~J zn;pxD_e)=@%2}o4J+{)dOA9*98GduEU>HCQ_S ze;o|v-N%frO~pHgRqUZyquoP0RFmzlzU^rkUkrUk+FjBr&aj>)ZN{^?5}irgsf@{KZVs8TQ>fe?Alm~qdPe<-GWW~+ z8+`3v@@U`(tak-_qnexvmU*tgW@pj(oIRS3D{)_L{Nz?!zf5)wAM+e?vL@U}8;0Wl zzVmOwFXv$Qu1WlE^?lC7{-@V1=g_3lzqYNK<+~SbHVWPnehuMi{`&~uMEFcubJj!&{gS<&2QB>eNZ} zOXlw?@3izqo+tis;oUpo`P&b&t_(`Szqs=y^@iJTW&8%&zYVIx{t)}OfuF|SAarLm z>JOlQFP#~b2IAOzS&!QF-!Ara$$wOKPZwP4+Gc<~-Hsz${fAlC4jR^d8&z#EQJ#dq zleUx?{JS!*-UmRBlX``JyS-zVtk1Ip0(}Fc_ zUo^1tE^kNjYIR_2z(1_x%1bVo zuU6iIJG&2FbC^ij)Lky@(GSF4{2^5vW*zm?6Sr8o;vczmgE6)``HR=Oy2qERS{Hn? zy2h-8|v-f^(2;7Pd9 z0bWu~t)Wa^fF89}`0o<_n;ie|T?W?h8Upk0$v(JuZ*7QuZ?GIn*c9*Gcg7ET!~Yoj zI~DZb$Nta+ZG$~jB@cgt)PFFVDDMP=B;Cu#@7i0tiM9IBkz1{tRxa=ufl+In?dS6P*?}{ z4#NUxzaq{WO?E{z4=lMoq$3E6&yz>_x1C%-3obq=hL;lU-6uLa+PpKh);K-oAlXHiGec!D< z4BwkS(^r-D9RAE9|CQ1XU-sKF77vG${!P%En-BSqh@OSWF8;6eR)>&7%DDM!$Nizd zcJDkMB`#U1YC~W+lqj!M?$E(8SAUsX!Uuv5u?H(_CY{O~BCqsAEAwfwH`D%K418&) zOt%Kx+H#P#e3-bKNIzVkLQjx`x;+d%T%Yt`hQ4B;$S8Figx+)-dW*cte{=E#oP~&9 z4ASv*HwfQS_WejZuLkjwNBG$JmHsSqtb9w+#ojaU7a}YbD*q${N1df z_e|Ki!F)6DrkR6KUf*9El+EW=(OlEv?Z<}uH0cfVgJGX;wjS~fXA6e;En=M%rDqG~ zTKq>9+l+K=0KOtiBgI(C^$BZ?#eVQ(HwMbPvrJxThxRl{I%c=0S^jr{cZ(YI<&0F^ zUknEPW#3TVa=*_kJvX-D3Ty?tuSgEhFDD@-0(`yk+EDM!sd_ z+nwfH1|G|%m06bJvGim6Y(ErMvVUsv*nRE*dQqhAozidVzh22}5I4;;{`yv9iX~6Z z+huJveiT3NdTkv_B|YESf~H(eJ7`<3tE>L>J)S=ODNoBDoA0MIdudtk+A|UQ`pnuh zKIE%z=73SpzAHS&SUUX@?az6|LB_ymdBpa+oL6^pPO?5dukPfGq?20!ueDEr|bm_-r**^^m`w zGUYs2_{kXG2@Z*dg2jPkvRVWGc#W$wXLO|l$fke7`0&4Zen@oJo3RFOp==gbd& zqOUgHR{C)gdtHp5Qr7rbQ0`)08Q&hbH6(dAk~Y4;@vm_{Rr}$=lJL9t@q<-4`#A=_ z5#v}yx^dRe^8Uo`Ig+hadCw<%k4$g7DBF;3)}DcRKHyz=i~ZrI?Sa4Pw4js>y7H1G zsecIV(5$Ak8w9mDJh2ph?qs0x#SQ{Lzb}pih zA|L6#(c{upCEZt4@!GEh#pm|~HqC*ODoH)Ah39(8xwgc9fHk$8QOo=91z?w99WQWr zC}@Ln1hZ_fNV%2jqS0#5|~X|44tD zNna>MTiVk*zohS#^t>BC#J(+@Nv}!~bvVV}`6c}VNzeM~_>UP!MV39pjkKjr{gRgP zRreNox0TKVOV{o5;@_*(mZ^ZfQKgpkE&0BrK6a4_NBT{pknrxK*R-G#9v0ZQZHav! zfAb{k_)mE?{n4Q86FyFu=s;c4ZQ%JgL7)+^sB*9>!l63X}&{|{&xKl8fi?q{X^t>{u0b6oeR*JRJ9 z_bp^@a{I-l=b)eaz#RRQy`9K$YA%}cGg&h_D;~MyZ74tNF$@o3urcd?F# zM$qIh;30l!OZM{JB z;qz3Y&ZMILl(P6XM*NyFPWAu|8}8Pv_B}J}G0qsfRQhMo7sWRaa^|O*KXp%Bj(Ha- z>uke#J9BoHt_Q)V^0sR{)_3tAI@}}0dXe(uN2xRAh`-Jwav8=nbr^Yh?;bxwdT2W) zhBaBE+v(d(-=gm%zvk+qkwf00)zm?+#$GJh0O3z~+)e+Gd8|eLP{xV{LNB2i9+_E# z)Flo5Lh9L&__0;i-NGIJK63Frw}SHS#KUdB@d+2smZyQAI`O`Rx#D+e3)0H^@mbP8 z%lG5m;Q1`yrwN|-F^_ijBo&F1G|#MYXIovb$0g0$t22(h9xzR4Q!r^red&K;&k7@Z6WiYHSdq_S z#ke6@*>QySZ_1pDo`>=<#%mt?&2ze6k+zYxkZ~(`j~hec&$)4HlgxX+Ldywj1?`kh67{Td&D@X!pQ`NxsbAO8xEnBXzVglWrzFnDWCDgC?SG zVXXO4`b{Q>oi8=>WigmF zU)E*5{7^by{#Um)PCn%7$ouG7b40-Bv)LTcL?41*rESh)9gVKn`Q3obC9-bvW&Zd{ z+0K>YU}5J}&I)8b6~E@fMOOI@hm1+lS)v1%nugGk_nDUUUuewP5-}RTG~JLH}MC=n|BjGSt#juyLQaRya>PLZ|NnxE2h5+cG6x~laIBFK8LY)Gxf$D z6V{M0WR!J}9XE*=9_BqlFENp&tnn;GW=k*Rn^iX!B>$;w$D@!kG-1v6#1+v=Ijc;r zg8yRH!^}H+3G?NZ)CIqMOQidp?3vC*i{U4I?aPi|Tz2E#fyJyB3dij_Zkqj2JXWra zALV0j@R2hi8PDv#b51%HkZw%BDV@|cE7Ksa_^qzeJ`Mb~?wp^tq<({p@jLq(?3-DaDb6-ze3d!Xd=NdN->GlAI{0U~zLp$ueJUAn>j3F<(${1iChOH2 zd1LDGw5%^)ba-6D{_*J##@+_Tz~JmkP0kYpqu}oxZI`8YA!T31fWm?pQatk z+w8cIoVm9a5-#ajn^q#uPUn>)O*7NB!8X4$K;KVzwPzMG56E}nJ+2hn)q~rGy!ZV`W_Ifr*dmx4f{Xk@;9$thFMe4hj zudJI}q){(Ym*t#;${55P70EpHNq%265|A!kW48T%OxoXkl5^`jN?PVn^(lUj^Hj;| zMeyxX&74a)1<~E0Xuszgxy^oqC2{*|k>8;-3D>NVljo@)nYy*9PY?E^#JmXx|3z2-<=+pmLUN&ZmuL>DxA6 z(goAVLHS7wInHM+vizr98&hZbZKYr!zt56yd1U;OGw?U*0Q~J*LXlp0(4S>2jgO+Q z@I7$8oFh#6@e$Y0G+<9U;FXU$0*E<%}pCf|uf*`hQOI zQFm$UI&)~iUQPB!!S6X8HqQiJBkuS0Jm2`t-5WQBZ_3O522Osj!nZ!V*rO*mGVgL$ zr=RC34*2>K(iTrtBXmOc{-PTV(J}tw$M3M`KEVoirfMz+cjC+ua9Zoekl=FmT8ZNG z$~&w+O1}IrM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7Qa zM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7Qa zM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7Qa zM<7QaM<7QaN8qgx*tPe=H}1aa6FY9a_12HC*nZ1xbJJyUbHg(~`7`JI^nv+<|E+{x zvF_@%os}-VoLu?3O3p7~Z?h|(R=?7}y$-o;h1+$Yoxd*Vr`7l&Hsq}f+OCG=;(?C;s z>IkwS-|0ixC>&P$?4?S_fAxfyJaN)f*ez4oEK}GqOSp$S;4W=$F0CYILa}ofTmt1@ z)a2r%GGl|e#QnM0ati*RqP4+nZE_;R;H6H6okCxr?1nOfm*d8U=1xm{%^>`y_OCJn z-w3>2;HrXRZ5i&D>dNfk4)B4-W;1vM+n&S)mlFq{xWAafYq8*LacR+XXiFt(hoqN^OV+i;K1UkUjpalR?Tn2CmutxpI%K*ld(L zwVOu|+I#awwk+JAbm1cNQf$7d6-9gZ`!3wU1;rW}N*l3X(itD}eeT?qd;Fv1upe!I z*kT~%`09(+o$+0Y?UQ&pZAISj#DpJm7q{LQmo@pq7`spCqu3c67u%CBC@=7fwHo^3 zgYEc}&h}#RL#MM1Y?DVx{|tYzouK!OnEEwII3k z8g3C6V#i`B_a!SZ*-coyEyWMF+|eweNqV!AwDMqgt-*cY;*YqyIpR)cd(S!PZv4T7 znMrr_dUNC0USrNEcyYyzW%}qkPh$@zOa}a>$QA71PUXO>e^%~DR?x&!ttPzi0}1yt zBUimptK*Ijx;`iQ>fEW^lzWv23*Ihl9jT6D?H`1nI^^loz!M!1xy=e>MAisdtzGZO z0$*$cRPpb>fP2&TIKQDD*s$|_?qC-BG>>hIMeB^ghWmz*aj1v=@iE-%OcQLv{=nYV ztw+%HG4AK)zHaBTTu|r`tjClq-=VAlE+B?5LF%gg1P=pt@;c1`N@5H9{JA}c% zu4xk!W2|BAtH) zW2rJ?TT^g#IwQLF8u#r#M?AL33s-m;rl}b28;>mAX>_4{N{&hHeHUHpxzlK`?Cnow zX%OyL%3kwxiSb1*cqD8ocd!TlSg_;4F5K}y6zsTCryZnyqzxO?Pugaj^wJKt-P9Fc zG?HM$5t($^n`yr>?r2ZjuF)U+f!Mog1=zk-UH)`n`%!=$t8vCQf1&63r}LcVao2XS zBs^@orvtBcEZ}Z`>|If=?oeIhkE`MV(n#4e`FqHF25tWNpt$}qRje-Zyz0B)RifRv z&-)a%o@ehTFPCPw4Yp2awOrjgvA?*^!-_ zJ`(*&j{C`HPw~t0t8=h>w78(>J^HY&B#)J6H- zJR7kAt`@p_)$a~Wu)w*SxI0hlH46gf%kC^5`^jC-txBpE_Vk$M)MlfwohUVE7 z0k)9Et-!{`?=)Q#C9j)jBXvxe=d7*H)4GgVH{l!XJA^$8tSv;5t$8E5^<1x&QwQ*o zuqBN5HjT7XQqzYd4fez(?g^JhA9qyR@zgjCpNq1!X3XM_k^DyP#%E15pKV0p7Z!tx z@RE70-EQJcoMK&beo_&;1a)i@h%E%O(CKFbU6piJU(48tVEtvX_1BT()y&3y3ES$K zuJ)fZ>TRc^ENKk;ediRsC1IbR{EE}xC8I_&+G_V>PAZB@SLne)v|Caf`%FH~v|Ud23#ZGnh+AQAg1jMvS}WURnO81`~>YL_B-)zwR53!sVK z>vTPne4KHWbyWPaTRS=1+>1>pYsHThYTd-y^=snB1$E*syKY^~+&p(aeN^Vt`wFw> zQ#-yfSH(qF#|K|KVkDo~Ws&tr^Ze9JyFM87`HdCSZzQ(%>TV>hj8|cdJrmMrW0vTd zT`x%5EfZC}Qr0u@fj;=!gyk=7EOuQjzkNYb%91sRI z*M}3D!ad?l^ew#j4? z8HCp{(zVMH;ukC;^4K*KvMAP!E&Q1*)412CvaHA5gqOv$&8DQx>qy!y?bqxAOYB0w z_!~z`+5Ej98&(bMc$xm7WXCi3HLxEob~ofPiIa6Z`n&+nsd@mEv*UP)cj_~6g( zs%-8TwDj zp!*djrMB9A#pKxaCd4iKkIAvkrjFanHx`=7v0%1*kIa$pO+2yb9iC~zK7kTE(kcilxO>inH7&M zo^oeLfDNO#9ARrmY>@l-n_y9uaRvO=gM)+%Pl*fHxIEMBCna3+&((+e2)JX*S^DQJ z+*95W>#!`o)z&Wa$?!|1rL12jU4~2eLG+2o?y>Gx&gMA#XE~=5J5YXtZ7CV^8Apt_ z&Dtze*b@?cNtUq}N)F9nte;|T&v=M!PvPOs=FvEFHjj94HjhWi7xWZrH92#68`&@t zZDV?l^?Jv+6)~0lwso6d$1<#&=$PQEOBFBN$DRc`7wh`Z83%c6|KiM8pJZ*p zbg~~khrZ7G$Mo;DHr+(0B5d;sU$F;m`a=_0y1_IgocX$C>Gh_Cy)U!pS^d1 zvZJ^Twd&u4EFN>C%J3&tktu-Ub}Yf+O=y}RiE1U;A;ZyUc^<29}yn`W$&s9YyyL;fmPyx z0d&@Zb?RyYBgzNEgqM*HYy#`RppSHctOgp9u#$8M({DBANBGB>N{UV5>V$(D zX}}1`-lx~7vA@TcMZhL70M;d)errlPFt~woz(^o<)q%1HUq}ALhK)q-*lUz`)&sumH_CgR z_eT2O5yh*y&*=g2np+gMM_zNOS< zeeg}NCnkHEvWGg#8rQ~O?M2DOv+uG;m+4b=T%oR2ApDwnF_!&8Ke#>C!Er?%a0(5q zjT@{#40}f+D_L2YBPu+ymm=-bGIy${D*7oP{FOFZokn_CdZ1EA-%HtJ7bmuVrhzk@ z5j59GdEtpEh4J&Og$?_gla@w_w`<5{^zBk?v2-5zJiL^%6*(&qpUhfuhOv^h6t>zO z^hYJx>e}0y2R)-1Gt&Q(SFxA&D0wrS&5Mzpq^lx(OxE|QK=FMF)aa*HpRZE)tpC|I z=ZkfH^3BltF->XI?1$D;zGrm=)S({-A2!@I@GO$>H(huG;f2(7=OszFP<@jZ1Mn)9tA(4p;|9pEX zm@;1D_3(Gx%+Brc=C&YE|I^OvHVv6*yk7c$%&P%|o~y%Rq-0S(zN!Y7y z_xj%l{MNX4@UmjDr=}{&T2<{y`|==TH2E9H3rl-pi|g;_PsSa*)y3WSdhD%VQq_L? zsa*Km6?NjXkNS7n#b=J$u^=p2Q3638?cD>I@3NqZSJOn*=|7DEObf0=|Q*5B@(Z z>*dbf)jrn8W*LyUgPi+sk3a79|9u>8SHNG0!@jXe>yK68lU4ZBOZ$6kW99AeAW7G} z@mag8JFw~dj=a;-Y3YI=y?pB+WrU7{mv!pH%(Vw^Uag-4+OvN6)XzEbO|(JLr_wKn z>rUtOK4!c_Nmtm*erxa9Z`8fCy{E7i-a8%^*drEN`lm<3XM(ZvHsoM??B-4-s?hv~*z2F!5^i5MR^CB-6h5c>h?BGMduh*e zHPX(Ow9e45x9}|bQ|dfqo~!gOE9qz0^L!fJ)N?tyfNvzWvB#wO=0I@tP-lPhV7M*m z3vY}LBG(7QgQ_p=Ino<$M?dw9f34}{ME zpVL5Sl(zK(cbtygLT~byjvm9FiO5ASeXjy&hTh~Mm!{G_v$Ti|PVb{%fi*`{{G`j* z-#p;zhEKL`_+;y@0i|yEBy~%@#%rmM`Enz&k^Hg4v;0IS{7b5ZTcAYXd)P}K#qPQS zeM?)KZvcMDU{iGI2JbcEqhdivj3t@>q>Lu6i5{#Gw+AR|ib%eJ_>!{cD6O~}q)QpW zW9MJSv&_NrEk`?RRO6v{sMqcBFJa&C_nlr!c_w9rcc(0i-EgY1wBDA<${vF!^6kPM z(6a6d_G+NJ+P1dT07lHcVjqP&v9))N*?B@gX}lTcBZM~$*O;>YO;yyJ+PppZke?wx z#+#>E&+E}iPqPQ1nd@rUQMGgrLSIMtsA4(dY&;Erg_cIjW2rYJt}zsc<{zC7lrz4J zUg?L{JV`qDwdPs&7sk6;^@g&SD)0B3o^ap`%3Bt8>7~nK8?WH4@Gd#wSC>AnyaB#T z+Bq{;z8T#zV1%~BrZ3|=qGhyi*$-oH8SPr8KIJW=UCU_K%|D3CH>d3q+e`4Ne|EAo zfSox&xdF-zP;Nj?dIOXjpxglEcBbV9;K#s>(gP_!mcD1)jzd8u>#S)WyB_XAE{e2$ zfs9+muUGOKq|NY*yfCVDvE<3V{2rc>ql7t=wrwbtf>Z551k@YQ56;$hZ4GX}!wb%M z#0z9C&i7jZYi_ZJ#V(#>o5sx73-Qa1PwEAv;?_EHwGe&OjTO}OE7Q!?GIzT|vWUEDEP-1ObJv}vs=2XX8z?kE%&fuo}ZPo1@iI^UHE zX-D&PRg!w9FC8p)JTh9TAm{5!%HKr%Jv?8e9mhJ()77VuHRcOh-w2NIv>SAYulYG~ zYD-u#Tf;aVL+jIZ$RhBFJgFbJv9*YLWZf8%zA-+*?!j*R4Zx;0>U~D(kDPvvK8^jr z4*KW1-a_%Z-ofH}Xsq@QRu-H_8-+gdeWAnUt4O}js^WE@HN_`5r;k#Z~*~?D;>DKBZc$e{7wL5;q3%qKBdW2^(W@PM8uU|QBu#!}qZ}*UWa#{&ZTF>Uh+x5x)^(5 z(@XL8sO7yo2 z+j7_!wRz!28opifQ(t3=t3&eN!83~s+hLl#d#R&h4qJO6q#nsvG53Zec5i`i4br*= zN?I$FIwUT`J<{<8`^`yKW>2>%8^-9dd2%duYR0L^D*K=Q%z?z#ul{$rs+kkwzXqcJ zl)y5Od0k}pH>CbiWT~AwZsDNUWc?S6FJ^9XYsaPMBA?^%9Ql+ryU;PaPr_W1(VD?I z>5Ogl7iBw7#b0zVFq5Gz4~^0<@fO!F@#7z~-%3bdC-0}P3&!eC!5i?6Z^Spg=CKdj zZ+zo*zQrl}y?z?~%aid(i9qUOZ@|ifdFxzRFk8K9h-_pytW5ax zWMW>pk%s5@*DMZ^1@i3m{&i#_{-2J&beyk|`v4iAhQDT`SJl!s+Rw)+zWNjLVJF7_ zqg-VidI~rVY_)fE&meYW9BTFi?Kd{5eH4ftG^hVL-#wFkvOh$o&ceP2)_}=p!7X9n zw1huHI(rxf$o{RDe42D%D=y*Fto-smE5Dxt2YKTMfg$t?teliz^#Ebc0C@b`0^0Zc z)Wx?o5)ROPvNmWCA3x~q*+|Z*dDxq5SLvTdjuhWe$X=m*LmG6%<(RWXvA;EXcs?KC zoBy)5A9i1S$n{4}VMj{+2Wd0)NVv`;bZK;*Ism<#+sFIK4{YU$W_&dkIysyjbBrnT zORg;ebjTT8RqgYttkIGPz@Ol_jd3IM+cf1P(IJZjUQRdMJ8PTNB@g38+S!owp_TT1 zn)mp(p^NX#6_B$Rk9YfxP_%e1Jq^ONiSrufkdM+A$1ZXEU+pi%r2w03L5z&N!>=xQLKP*h`LNSL?a^qis>KthKb0^bZT(j@M{y zTwh4t!hfrm=akX! z_!i_2sDKR#zZ=;C3eH)YWvmho#tS-#S({*sN;qqKL-^hjo}L%h(9)V-OT(@B)lN5# z?b*t_x<`;SC<8;9e#Ijpdo`FXquY^Jwx5ZXQ)% zb~bbJ3$BfvXV0BGenelSb4L?-Fh5WDZ0u`fz0U6$WR4MgDr8=XzgxC*=m@;9b1i!a zVrRwQaPdN`{I*1NQtfP!fj8)ez}2tO(>8pm*5^q4YFz`y8|n9R=x@e;UBcJW|7o~M z*pRMYMf!n4DR`CZ$4uwd2wVIXUd~xF<5hSk{k4vA*fhbp=-&0ToA;QwhQvXm*h5xt zk}f#(s|8-JYZhYrSqRM*UdlJGP8THim91Wis3VZL^Uw#chM)H&MSULhA)m6Jsn$@} zdDzU%LBaXZFhsiu*CpKL+L6g$jdC*X%Y8 zmFyddZnJCCdHKxi$u|_dB%ic9t5ZX}gst4tR}I3J5A3l{OS^i}_dEt$z5#5_E9qHY z$){cee|zEY&(UV!oOO`d zf6=b-S=&vq{~@|o=2v|s^N@_eCtVxDv)#B;*nMKV#$C=PkntzuPW_>auTs{~mPfHQ z%wIWvY+{Z1=#{LG(T8e@UzI%v;Zc0t;Z~`f1qJv(a?k^!Vj^n8noYVhEW4X;0us%o7N(Ol1D?M@D^R;$#;HoK0bR!N_xGY zba7-xU&ocmN6U;T`)v@YRgYoF<*iQj;}>D%dt@)oNjk|n#V z5%H1_JJqkTzj{hK(mb<$Yqo?73_9k7SAA@8?92LCcer-U_%CgT*qL>3Brkf^h&_+R zsU4(a`WyRDaEZ}>UHJP-JZa@^>$}Lg z`HrJY&eY^=J5gz$Njpv<2h+meMWnGe6$~JU>?KA(!JFwPO;~hJ4R{Qh*qdNWa1JK4 zhG$_LkaxC!&^gR0eq-yKbc6h|uO+g_yh7ZlPH5va@yXXp)y4q(6a(}IP)&W+;uRZunmp#O zXv;G8O3A00t7H$y9)2A9sW(0jZ5KcnzjcwaGs}@__Q^6F;RRXP;cE6! z{!~1^AVE)U4K@AO;JpT%1~!1QpRF%+vUgIRwuF)|o`MeQS3rFsy2j!^==zX0%kMjd z2l87o`R+&blk9`Pq>sTbHiO7}BsdtaqAQb!kVo+Dy-@ZN4u;8}xp5S*?h(Bd@?G$w zN6>f3dX=%tK1W-`Z`s$W=R?^iiuwd6>!CkM%h7fjA9dzP!@5k?LGgcbGO8alUW42Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPD4 zb0FtH&Vif*IS2mLIB?Ud)mz@SbH{tPt=M|=yG~K7B%LC9HcHCR22S;IB+{ls0h z_S!W+dbs1CUx^R%+xbd-dGE>rp?|`pLZ9t>Mk8kqD!cTO6X8a@P8|o#M zog%_~&)v;yewVxYy9Pb8$c3q!x{T_1*mymS=Os z=n)kt=sTkiAA$WUIA^H};y-x^--R!F3cq0rpJ56=VhML#8}6y5C4RC5h@UxgIgoos zlgko+)>m>Vw!W0il??6|GL9T-pp4<@^Kf}Y>A5( zzu)FtK--(#of@C!@V3L7yDk|kZ%BQ3nzmx~E}{MXjs~go7<|p{u9Z7v#b=`2SKU0i z&)!Kdv}N((0T(YcFU9AYI<08$RlkXM(^0HapmYs)K`)3W!;t%K<&OMXayYDQJ!E+x z^@Qqvcb9C6cPTzb;&%Fqve8pxVZ=Sx!FXH_C>O=}T|yqk&)10fe*B{H%=3k66?qBa z?a0H<_hIrKC$kOw71xsPS^VOoAlQYUgiVQmpU@k)dgRVu!D&)|u;%TKAN9xKU3xdR zy^A*CF4{47SFQO@q57D}MCP;Pn=TyRnD(cXP1BNZ6sjA@n`}?hen_9DeXah1a`2rM=N!*A_7rMn?alpO6(g%vLyE}c<-gVxTJBRIkz4zL1 zaB+e!XyUjpKDdZ?o;pvHXIk!uMusBpX%5ckSwR|)#MLFPi~E`hH+e)(zrtP75qI}a zlNRAGVkvhOD|oV#IP;d2f4s~6$U>Ur*B6sl9{ip)xJz5YHSSHWaUZhOBl+I;?J+%@ z@96dVZ9}`YKC|E@_}!HBCiT_1bGRw@4)+$koA3u@;P2Onm$bl0+b6x?^nw?^)A32K zpdRY0QQyo(+&BDb6UyEB6~cQ6@7?9X8d~rJ=Y`x$Ebvht%g@u+YK@=t^{YpK9zMQ@ zcweiVv@hy5_O9z-HS#*d{niVh!M^V#Z*h+ArJzih`lflT?@1s3>%QmJp>LYU#s$O$ zp7SArOg3m!4QSK6BL3K7FL+_FY<;&cyvhrPlonr;0r9R6rTyRHZu!T(KzxD+S9!v( zAmF`lm4|Z{Uvm$4&BEwx@O^S9e8C=cqBAhUyRTqJQR8x=mkp~ zH89486WYsFo@{Wl_f7&wbqLc;ImM@JB&7;M_0Yewm(p7 zy&$F!6?x*s!U8TqZ29C+7|<5Ee>@vU<~Q6}(cCFt>o^xYsZUtK)4z$Y1@2jQX;Q~Y zpRDuq*F^S`6Jhe9llZdo>RfzqoL2}=g(vvosHI!xlNi64VsESqxM%$g<$Sw+sAPS0 z#%HGCTe+7$E(J+ZRrhe0di4V(ZwB6kw5gMLgCCw5iT_~gdzF3}!Ov+sbH?Yt5bFi# zzbgEfxCQ9w$HWH@eyJ9o_91=OX{IbbQ|vs%e0b**rnvs$xUC|-;OF7^Y09ssYzS{u z>f5ND`WNzCgFkJtyK21GZ!_B9ds*I_ye~MtQ!nCd^C_1$!F!Ij4uOh8J*cOM^03dbiOR%Cp?pt?sEsdtqAJ*jsCFf z+=6$0)D$o5)>|+6L-I^cpfRzGFp) zI6u?p=?J^aY%f$7l4fne#Enby^sRP`oX0#TbC~GsW;(y!C-d8f-29f!YgWH7Ut;N7 z{2%|;5iRA!e~8TO%?s0a`t{?cD{QQweXC>ZW9@C^6@3xK_}w6XrZa?2JNHW7&103| z;so0OJiw2CYs})8J{BLP7T>rjN?kIaTRc*3S6qq6KTBWgE9)zipOdd!@Vjza$~_fV zEbaqR-o@KK+3IK(-P*hYJ0G7x=OaJoV5--{04dl7y@p!XQzbwKNX<+ivI5HIxT6^WZ$@QIONyEX{d z;F;jq!+QnV1&{bvtq_jD^QhF<1Kt0~xP%VDB|NMHp}`j%f>-j250;E3p+RsRBVQ{m z5n z=N^15HSjm3yG=>-O8~wGzL3R#ggiQNv~ES8d|Y*fU9>IvZ>fA=Ok2|Q_>XR_Zh=2P z4PN}zl*N`1zD7wWLuYsOz_`%|iktLEYki-ZTi^V0Bf(-l!rII{;PU-cG<2V&A?Q}P zJ{q+)`T=aAh1y~LyHjULiU< z%_r%SuLWmozWMV>RxU!8@sWo9hmVY#8hW!~@HNWXZhG)O)>p(^y|KG0{VP7G!}A$G z@N%TXSUJ&8Ev$$Sv=L-glhz>KhSPN9wX9bw8S}o#viO)%tm8(=8!u4RD!M?%kZtwC zG@P#0)M6K|Lnpr5emXk4UWQK6ek`4=t>(~4Ud4K+ihjuWX0Q!f!=%g!<5Q-*pv~Zm zCob3U86*C*L&8mXQ4zfY|JK0=i5Hxb7G2`X%&<0-cqu<$9_p*%JAR2}e9qx}io1p# zl%-F%^vkJe_=)mT*H4l!<4bfU^2B4;N4F{GKby6v_|F!9Mqz>vB+>ck5$$cUzO@v7 zaYSC!*{ns9$ypu;k1)4qIK&^N;PB?+Xe^nFBRPF8j{7JV7ul1L{fn2OEl5u7+dHFq zFEp<^70v1RyNP<#50L@tIThVM7Ju5F4FCN0WPA-i*TM_-N`x2qu$#lrTHjn=sFLGF zeIauoK8dQAn6mhlgU5D#8sIx#Var#Ks$y2p0!2I8{GdWViGS;$G>nbO!yZAC_KUCf znHL|h<9z}4myFqrG3 z{U2<^e%`o-b#+{h;^!+;$2G|$(CIqETrU3Om%{VpnUv?J;LnfadB(Sl=P%(~yRy3I zr{-G`x6d!zwo}Vk#_J|BCj1RbKECG{Ve|Uv`MJEV{|kDM$Br-dUxOF1EqL61gb$xd z&%*4>o{DeQpP2YQ>oB^3A2HoAq-z$g#pkAkuhunWMz4;vwr~T!jV1m)`1cg}Ufo#0 zdhlGvI`)t5W?urIY+_&4@F6F7#fP!(j&#k!^|~SP%-7QvUazO|MWwgiqFL~gk2Oxb zKiq?UsJZ!}EgWL+hBbE0rhniR={s$D&_}(6VXtB7qh8vgJ7@>=N&P_q9#xQEi^rt+ zXjeBr(ki3{Ydw7$d7;_yV2HgL*7a55=agBC&##l~-8$>vU@f*CFcR30-764ZaZRAz z3%DxrBjO`qJs=*~1O`_FtHc8X=&S?l)YSw=ln;gpFC!h;1lEB;AL#;F69y6SA?d(i zCFv5T-)hW{@Q*Q-6r04=2?sUOfDw>=M6Xd}pN(~QSj5j^(O4UM9kztnu2C;_Tthiv zuz_;;Pm6%Th13BQe{W5o_=*dzB^{a~U|sx2ZX^thfC2lwbzlT+N|?6Qcr-Rzz+P{Y z_~5O?pGAIP1grz=z$UN>41SS#cohNbOMsM%fK6ZktV=rm)|7N$a0BIlkwEII12ytk zNB+cyjYRJ5jurY#E}YU#W9lxw8#0ewH6<>6i5 zljetCwe($dSA+Kkd<{3VZd!@l!}|ujmpQM#`$24a#yn>(Ru6VMJ!n3m?DKVr?9-HyVtx@4=t!hh^#6-dLtb)p3QIR)O$o=EYd{ z>HOgKSO>=y_$e!OvnFn^?lA1xh>T=qWp1eO1je;Ti>_8rRrFIpcr0zRx{UO&^gu=S zDy8hPi(S7=183N0Z?2K@!V6OhsA%h_??fJZ&o-t0%i>Be?c2_imD};g*zd!pF_*YCM9;;y zdfSrcD?LL!;o%_mpXTW`<6h5yPQqSwyVw6d;J3!TgO?SHJvCKPYgM&}aiCc1S$Yd@ zpWA%P?N3SE!CPJ2eXqx!{3TWG$Ig5Dp_?sT@poOm-qa6cyvDUXexs_kgEwnyjNKyb z=y?L3Bqu5drvu$jI}V?%N;e|I_o0`QpLe)>Dudp^mE*dn!dc7TrF5`<+-BTZ@Bfio zC-xwVOU;;P-b5Q@-T4nGEwUe#?gt)h#N~c?*xMU>QcrI;ZAj12dfN-0#0%^RsPhu) z3<|)b77G5G1pfwy|Jf_xHMsiV`LnWS?A%@LV~uE*0f{@vIr8@S<6i&Y$KiGb{DnB| z8>4UVt*PYUub1}s*2c=);X#tF`(pga?!d0?JMvCTr=<&i^m2ACWrU7{mv!pH%r^&b zUag-4+OuQ$)X%x&O|(J!QTpX@-Hrd=$BcI<=?Z(6)jk=e%_Y~H`d&k29`=mlk z|MY11OfXj7hThs9JH457tE#5&%wM}c+kv0V9h^n?nf>9jn~v%mFEgR3Lh~D9uYYDs zxP94Jc?a!L_y_JIPR>^Er9IEpNIP57Izz+y`dM^|)OpA}SLt0=($BE(_cVI2=W_HS zXYSkBXVIKt3yvP@>~9_nwf4>Q(pEB9%ZRyKi`tlHI zJILQ(KZu+_2W>k9JX}8zJ_CGC1EEpc)(hNmI&urW$zM8p4EqKm7rpeoVozV_jT4uq z{>nj1i^$;gKKd0{b2P1Ov(!H zPFa>Y^i*YOy)BcKJqAzYEc^~=S$75d70_L6TU%-XBjyjW6~dj^o4dyB`b|G+ycy;u zgf|S=n6my&_AfTId3*5pJwtxY{GeIW>d{G0v;Nbp|7zG2wRHWbuOoc4Wj=+!LQ5m% zvD6z9*BFXJ^N&sk$~jX;uk=G}o+Q=Tt$CLHh4F62AFu2u%KQDMCmi^K@|J~Ndg=1m z#w&O$yh~2_)uoRsZ-DPycFv5IZ$`Ha7}@7bZ2B_3OIb$ymi;jHmeHQmk_+O>>! z-TZ^Nd~@0^u|ou(`e!Fg1K3;xlpCPj0ObbMq&Gmh0m=!)f*n?aYY5M{hw~Sw}f_0N;1azLoOiBSq_1WEyK_yT?_8twv1Cgarnok&xkYbSvs)+a)B&9#W*@Hfv zVg3$}90+Aj+OTG)HWnH!=TIBgMA}%mk!eA~*MnzNSJeJ+9d*jyso)bGzW_dn@An1p zVsCPwQicDR5VpsSR6AxZ!kDQmb8k$@!|fxMQ%m>AP`h(^^vw z;@DfbU)=+oE}>!5$G>n#+o>m4kvhsJ8}U}eE+v{C3I-xoSuzKZ1gtSVmj zSyOysm$7;FmQ+dFaUD3|X}) zsrSP&{?yS~O|>l)eN}s*tyJ3@muu~b)ooe0LD+buKr!w{pJqJG<}Z|Ln_Kg{u;lNQ z{G217_*%?&A{l;Fs?mm%_+41?FOvM&SDoKRj|wfjNL$^KHw{Z(^lLDR?#|k8)^7<$xnTaC9V$1e+SPjE^LQs^6sUMiaBiOl#qHP zU&Y)Tjv#LwirH}|bxS!(YlTvW#AUcgI^Lk=JF={fJ)9*N#^|wmax8Uf#;M3Edw~AT zfyCCI{6o2_nG=ja^k4FIU>V*ruZ!&dhSWcbEVVPoEgbZktoefR#mr4^y}0yT%8bKv z{)6bk`o|*V+3fVa;_ToPW2T%bU68;=GBn)J; z#)}^z9jJf}V5>|BKW62W_e@UB5pa+Vgy#ek;$wUJrb_-2wfVTW+KacY*m+#-Lzu`^SE7CX87oxY~wM{xn&jX>?_8aY} zLFe?X&R!FJXxG5RNx3XMorYWGN7`sYgtN9cgzqik>3LxdEv@ObG~9~cyw8nedyX)# z?h)ievBnhLmCuHx9>zf88=yKVWIKe3x%FSrbX!bxEf$<$bTbZ+;DYx>QG- zm)kg-F18F~vzoRyvp1y7zO2mV3n|mBGdk>i88BZK&7AqNF7xHDr1Rzfa<;Mh71u`2 zZs*Jqar?b zLTo$>q1nPq`MxvN1^>Nl^-)9}0ddV&$G*s<>{Y5aga172VdkCSeCDDz(H6q;-A&Nt zXwPJ>b{_Z`YvxZKzPRl4-QM%C7YZk=9XG>zD7m&=9XZN}(eOw1ghZd&b?3Z%<{I)1 z1uw}bZO!V`&?{jptMpHUux&g0r_<8DUUWQ7jNj>?*)DH_(oXr@>Q6{(_G^8 zv3aU&?fc~QC+$e{Wv@EWW@g7lw6$N~$3A@WB=U|uE4n>-oy%`+%yL(y4*vMHZrrrC zX`1+YA8mSMe?`;x(N$laonJHBbwBcZsT*VZ%f=J@`pTF&WPd1QF4{GI(k^3fL--(b zs=g9AV%(X(b8QIEc4JK)cVjB)adv==IT>qWhl#yfrEE-F9u@oI8%~Zkv3`8?%Gg_v z4m9WZRoPDv9>rgExK%1=K>@x|r#j){rJqo)_IEEb-ZklLdin`Ap4g8s8SmI%LPHat z2tUN0YS4Z;qo@HR@CC@XO>2=s$)n}0n>h4~C*QHj`S0vmAnEqpAKs~J9gozdXT|wWIwc)x zp4q-NTfzkfz4DY-eQa^;%i33WxOU9=FKvg|mUVEbqF;^J&sdz=K02nqu?Yp2=&6yS z@<-a--h-WcN)Ouaxgxqc0?3o&1qH zToGu`V>_v9u&dG#DCe<2-Q{>Ce3$VqviM3oY2|I}yU4jIJG$h&OwMpkN7`r7j#J3N zwD5NkY3w@%1Hvcz1t@qk{iF$t&Zz;9^~e6+1pDD^M{9T%_5gWj`v;xFJmNRDzDYO8 zFMC!Zd(0)o@!JF1I8A)=gHp9Iz#hZ^eJ}QKntxq_-Shntc_=fR#&3Wq6Y^b-;LDZwwB2F0|4PuZ9fO)K@KDv74vKW4=LKmaz{?KFu6elX>d>{1#`m zAzx}^w*1yg`d`1Fed`aD0+~bA2U#LLQL=Io|6Qr7ms3wcWY-k!w@<6zWxrRFv>Isv z-!#>h-)+|p_2ux1{*vEaMDQ}|U=Pc}&GxrsQTLnd@5`d@>vfa0Thx66<5}RSmhWSt zUE8&M9~14`HRpF5@|%q&@qyULCukq_#$SQ93!sbNdPv!s<;XmHWEqa|f-LNCHG3$3 zsy?^?y~LiVrhgl}*MQT&22l30^@a4&9C_OkO1}8Z&_VqQs4qkpS^NiGAJb;}t)TEg ze#<1^y@>vjJ@A*v0Qjvfp~x>d7|)_hljF!Mc=ui?`v?ca zA3|HTy}(|0+!pb>=ymG(Q1*zTK5(f6p*fb8qwUhyb>>jRT20nQ@qKRY(2p6f5qF2d zDZYo9zcy|P-V~SpCPseS!EeTHVvU}>jd@oYFL;8d*b@eqlehR(rG`w%+FxX&Au`5a zl6=7K`xy4Mr)7-25x$eAkHDujZfu!1versep#JOwRvx8X{+Dwg=RnSZoC7%rat`Di z$T^U6Am>2Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPEF z{|yJ;^Ul?8d+)YYE4JSJu2Ui;?UeCZB;~W$Q^TQCNB?_?y=v{XYkqJ2&1+wY5A)mk zN_=_m$`z|tymsYlw_f_%OIFmjU9xKXj#aIk-1%!aulV(yTi$ikk72|$?|xV3;4Qm4 zSN&Y)s+E`j++~+vx~g;a%2k(T*;CY6P${F-?|$bqH=LrXlX>#DmvEq<#_$sndj))W z8fAQSb)nizILlbXm2u%b+)4cHLtb(g_b8XzNHZ#VQ{j|%rN-PJpOyW|U_yRFRtM#t zdS9*g%v;`<(lIxEHs90lOY3pzz4&L9`(}HmH2z3qX_J~hEB3{|i-zXL-#p|Al)8r1 zicszdm%EZ{+=CncGxyO0lW$OW&>fl&x;vnK@FX{>>Qo!;UghfZ@BU_Gsx9{Y0cRZr?3E+qa`Au0J?Rd41i`@EpELGIrzMvbHxl-j+1ziRLJ_REx! zyN++;j@-5cAAjxMWFP(3Uk#d_)XSZ}Mc&(ZN<8ZGg=#y{JmUJW`QmM!-vjM~E42@; zk$HDT?(LPfO)XZy#J~5tqq?rCXS1o;xS{ci+z0;brg1H_x;*3hS@MbR)u#9l=l*Ma z?%)Sxu+qdQMsw=f%9ON^I+8`js`!#}d?38ASQS4QQx($X9^&?5br0c~yOA?~i#++| zHI%s+-cNeL6;&@jEA1EXPBidcPrZ$X(Q=o0?S(OXfSIzi!{>hV8T?dtZ;$YaSLdae>6I}vGe zN3-znZgBbF64?-0h`B3TWJ9I#5+~t+`=EpIqorURnF2?0zmplYKOOgfa6#1@ zRs*4>kNe(*9@_@)V3#&50*}z2eDBt(a;Qw8;3Dd@IQ(WzBbPtxEo%wI4Qu zuM8f`ccGtt@VS4wwar3{jCb`7N6RggsZvJ$!>v`}yR>&$bzAx-Nz3{|=uE!m+A|q% zvFTY^@ns?OOCNMJNdD4Y#w|`eVP1d>X9}JKMX!2r9SEV`1_9EKPxZH z%kg5Y+sbRRMaG493jfQ}FUey+z750bDLWP=zwjz+gZidx!^)O;({%Fc|9Or11pWKx z+B2!2Djlr%Dtf&ame6JDO6!YKpvZgc9~ZWhk8z=uomb93r|QW(uAyC5t6t3{o?bxu zneBm_Q@NkNV}n=2pXaPUU$w!jwBrc2y1_H*O7dM9EWl4H&c3a`Z>`!%Z>R30TCKKw zGPZTRKMaR!-k$MA;`hoAk6s(f*v{%mzVCdE=t|AgcgMQHqbr*Cg!jb0w{e}n;t_n| zKJqc1LdKfl39nf1?Ku#aXHp-#;axQ^oQ&~>hp&Rox9IRLaM4ElKABiQMiS?5?6qSm z`JSsk#KzdOKhfcVSW9`>i@%Wd-pE1T;a!~O6aL6NHG>T>?4id~JsOWE3w?aN4im3` zi+Kv)tHN{t9CWhkvU)7}eJ2l+HyKM7O5Wxe^UmX)p{D<&oRpC?i61TwmgU{wx*Z=R zsyG{ukIs|tM(Y*$KPZfq{fqG;e3?N*$fhD($#;cUAhnrM#`f);Df+ ztrMRWQfK!&=hbQEExtU# zt2QSKBif=;n_9{ZE7vxQ}A2{$7x?2ar_r~n2>&N z35y)~tOvvn7Fo3ALh`)b$&}a=0plawgf6*yz1Q@y#n256U?l!|(SP+8zmw8u3cr(a zv9K^4zeNWJOj*WvxMn@;1yc--gFzs6;aE8W4xi?1`(gb0E&cXG-qLTs==D=?Km2$O zTmA5LV$1Vj%TIJctE`Vk8BgCv#<8C#)|v7HuQH_vEL7PH03jsZ%@-f?g3Hjw_*)5H=j{C8Ly0#HZQ=_@gF~yt`d*%l$zP|B$tUH+rjoMq zSUkihJKUU}EJ)kK9A(>yJedL49zD&x3GNB_qZVR&;;(Dsbm*iX<0^bvY)TX4udxoE zmIq%$!kPp<6Etg{&^;yjcg4jiWKlJlj|*+3se)onI#||2ZKa^7{AOWL`^U65Jy<%K zR>W~>mi8!VU7k(zzsUQR^!+b*A9MJc3+Y?rHJH)fSMW2c?udwQv5BEpBR5IwE6$yeIn_$cI1EI-7j>9b>e?l-iNxv zChsCU=0_j0yz$ROeg>6p{%Raf(Qm`Z&m{hOTzsILn@lMA{avO_VQWr*Bq<`?tZhrk ztnr6=7hhlUF5@NY_U!wVyl-{y!}v*?T4l=q?xYyeM#LlibeMJFJ70sGvsdtcZ=hd^^UeP7oj0HxXxl~aj6I3> z&ts2c?1-J`%_VLOng5;Y0@9@1M2x?%+Y>!3dn(W(^#!-H2F5mszv}WPKXfqLvl*ss z{@q`#`0zKln6?+T=wW=*FTSRrsVVy~yG&8`Sp06}l|Ha@h`KjS{+pxC>I3+5DjQ4P-;yV# zP4r_xKgfPd(pIQS-`v|W2N>3~LPz}Ahb$D^T;x!z2bsg*ow?Yy(Z3uXZ&7;q>IZCC z4Y1Z>4>9?3S57VZv}b7F=}FCd)sdQa?$Mg}>W6FI1t#_`931mZ$@NR2PqEfkL9kQ> zXAG#|^b7INl=^lR9!;sl_mPRI3J|@_!0;t~7+8Fy<_&p?-*dd?6`A|mhSqzxtu)1l zV^zA%PyC0~SovY#`K+VH(XqwCm0odW>=ju@6~Qg=Xd2&1c#?Wf@Eqm+XfF`|heOEu zIL}d@BK$v}Iq-baKTg}e!gIdFW8)V)c~93~7B_3JA=X|+S$n1JX+z((Dd#f{4l5g` zpT+)C>{lLTEFbNRi$}pLdRXF$jL9N>S1eFRxy|c6I*R^IY~KhD`4c`RukzjgW!evJ zZ&dObbM zw`lP<`1M2MHeJe{s?5o_x9G1Qf);2RfX_RjLF@+M-va7;jCOpDw(Ueeb)p+2-uj$g zhAqH+F5wZ%jbek3ED!X^@O21`DGG0;+y?Lq zPwqNrqrUT;&6b9C?41ShExz30mOczj%o|)PaO2}z>YPN!O+ni*_)JHdAAD0| zad|jlUy!+6>bbUOkzRnFJ}JmgJN9_j zxq879Nii!Ew3JCMb!DzGUqwEUHE_i@xVSsBxEOkW(Zxx+=<)c?X_z$8G4Y$yu+aSx zN4Hs)(H%hdA?T={lJ59ISN8L?rw*><+LO2zbQE=S@w>E7zZ%w&LgT{jKnIo&C-Jqm zDPHQzAMXkDweZx3Mxk4!c#kV|JaKfK#W#g)h&^Rk3;Os4jCiW-LnQq!-OeZA$@)Rs zJ5gbdp^q1VcM-UR?uD!4a1(Gb&*KG!)A!ihgq;#!=I}gT!0+w}7iZGG5i_$W! z^`(6_D-Rh>aViffJ;FQLYZ+$TP4yy|^xJwBdw1}NT_F9L&23q{jEP5kB7H4-vQ=iP zsodJ}lkSHd?<&p8R1=)RZKl}lF}7?b6E?q>wn6e3Hx6aYBAP+-Wgi>J^5k0&dC@LY4!^a}8^M=m)9+?4 zs&08Eeqozaot3FV5!-rgDcWkvL2|qIC}X99eH|F>$+=0uMa|ECMe zpJu<)l%1@sXTNTGTxpZa$og@k#hw?x+TrN$+w(KARizo4HBOc$c5m4EAZKrCcE7Z8 zT3imksEX^`lz)tP9({~6tw)c>ZPoAWo6Q%}k9GK5gSLh|L-=~_h)Z?)HKbpKW}#E+ zI41P6UX}i^G)+F>XcBo$+c)yU1Zyzn2SZqM;?FVVPwW{lN}ipYe%sna^YecK z+6P!4OT3ibxu|a6v+*;94I<~Uewp#cI#${!^QK=;?0RU5HHYMl%Wc6K>~X*OjPvxH zV`LJ&{Ul}I98ZP`evm&#`7@IP;m6J}rH@heON8b94BB(XQ76L%*)LzXyZR;4&(yL1 zQS{WCKWxe$eRHAsv8z<+Ozh8(US-N(+F2-`d0M-77C6pgp8nYW{ocNbz>;Bo*7dQ_};?)v(P8|4T9?}r=asK^XNQ-x&O&cN2ovX&H(?Df}im%_|M>7 zpyRhucCCR7T9|ANE#%DGg}2Gsw%gNEoP+Z&Yl;b==yT~8(ci;BU%CB>n6={+;fVtK zyX?2PdXzFh@9a(Uq8nE}{p26n8rHxyL7Rrz>zcA~RO=<}p1)*+H=JOvrt3tpi-yOr z=dg|TlJ8hDSxNXtfbnC`rKi(yjj%RbSaZi-g)*|&S}VS^j&=AE9>#~V)TODbMqL%o zz^0)+qeI#ybhYML7aurfp2ly+bMjdn_{Wto?C^~0tesMKE6#*H+X_)y31())$LXvW$(VUjd?C)KA+mH zioUwthDR79E?l=^`_A~8=FI+7b! z`gp1jSnRHFAW>mIsx)ymP;{o)20(d+`x9UC4B~3VW;Hp1vmI*|2n|NlRa#aMcK!8d+MxZsoU~_GIFLhC44@5;^cV* zeQNt3y=e2n!>KM+njk*@Yp0i8U%NKg^9=e^WWw>*$x6ltkrVsgtxD0d#Gjuj$Uq3Z`99P=jdcbcrx5e|7>-xumgte}3 zCT+TuQ;buCoQu93hQI!8&$)R#-qBJI=h39QzT9r>wC}8W0^(~~8hny^Z5lk9Ed!mB zFXB<2qsa%q#5sDlpDd^5;ujpP_-D(2zdl=j($*Cbt|MF1JUTvX+bjH-V4Y0UUE3A= zyIDDG+q&rKEu7mecW@XOBq^^XzQe^^nD%+w zCgVANhi|`eYf4?n=+p%c`T|#>qtfsc_4rGX^$L5*T{r6bGJ#ul#5q%QG3R79yjC|Q zJji!{>^n3EH|nXvk&?o8@%aWR+3}OrCHwnQpFKmR{$cD$8AlWFXiA`g4<7=D^IdK8)W1P&&fXJrMfX)f%BPZkNqf|y@E}U5E;uH3f*wpmxI9c;_YWMy) znIE;|#MXoE5c!jH$k}@5$gj)Wq)w4vHImAVoC_cqQ$K6JtZ;IY@lg6Dd5$wd`o`%U z=I0mO{=OTJZoJkrdInF*urWVf|C~xjO-tRwCY@g{_p5uPK4ekxF6&j%`Igt?PluxK zMJHzc;-eF1-$n0{KYop)Euz0B2>ZZD%5@L%jbZHTj;nRBs!AQgk6UyTeJA55VytE3 z$I1?KovckV{H-!DKYl8e4Ur2sw;l*(UsC#6Xb+^0#p|`$e}2fGf1i^>pRbX1mdw`iG{>ZRCkpa*K~H$*LaBZ|F| zU_352({o*st!CFQ-5|f_n}Fa5_8a?AF8;l`Nqlqhuj{7prt1S*&h$sYFXxZK!vJ}0 zc9I5P#AXs3Ok~={NnhOV1<)VRpLWiaF)uQ&KI{d2L)ILNb-=e`L9l_nB{{=)-;GHg z4Q;|N$G<}-b#=TIT*O=30GoyPYYqi!NlY zmNdSxWlz=3|6*53n#^r-{%+ezT9dVJT^^BX!Jp3a6UeK4Ycw_P);Lx-4ek%cF0uTQboul+8*o+)7@1l=gpPL^!dvstU`QmZClV@Nfdrt9D-jBL>b%(c; zb?4XWl>MOWNBuU>O}IL&3IA_#g?4GvtA17k9*NZ_MsVT!J?*D52QSJ?rwTfbhkab4+3!AUH2vo<#@02F7!!$ zp(|Kewe4_p9kO&~^$6}^@YTuNicj7%e7631_(BtVdsO08ID6h(NWALMxOWG#kj;xS zeq`ME_td-vd^0t1AP%E7M$7xuE_sjayT3->H`@1T&Go>9pOToee|JrOPY~X@M(L@| z0t4+|B5;wubIlUnj{fmK@=AGzbo&y%;i4|#L;DgrJI?=d4&)rjIgoQ8=RnSZoC7%r zat`Di$T{%Sap0y^tGB$|1sJb%&x4eI*&2slHuc{;QSQI!esI8hB|gk==PU6gzyIRj zyla0V0`mJWM)UhG_zuhG8?XHS3uV8%$nU>+>AeN{{TJ=tM(!xc@4rY&et!SO>>V@t z{TKQD7y11c`TZBk5zd_Lx1*eSb#b1}(;7EScuL~r+lp=nhf_F_!l@M6JU!WYe18AM z1mFJ%PvjZqTLB9%axlODB3uV0oI~f05sRF`(l7{tJFzkl%lSogjAs$ZrbxEzkr|e&Zm&3Ci!k;5RP${TKQD z7cKXK*!wy79Z`P&1$W<|Bkb?>_zl%WUwS?Q%7bCBO(9GIgoQ8=RnSZoC7%rat`Di$T^U6;Qtg3+_d{0 zFL(WgdZl|FDF5$j$@$zEv?-&EQKWJYb6Azk2#3swm%V3*_4?@Q>m< zLFM;f^y9CUC*V%;VEkx_JH&M${sizD+fKaNpZ*5uZ&H7-Kf1L#%DoWkMfY0(xhpp+ zaQAJIdlJTbtB)e4($CHbVR`Od9X$v+|e z+*9>tzOv5?N*nNv9v7nqcQlvUy?(#yEiG2P6>ZKxx6ggYem8yv@V^(dC0u$nU?%@4slh>%!-riwU{w;>gK6F@_0GNgQ`L_}vZ;r*I;LQz^80 z^7}6qPNh7^@4vwI!3RXc$EU)$Dh3DQa=q2pix@@u{THuz|3y+P+O;D1&dEz@y{N@G81U^ylPj$Vjp1`+**-)@Peqt%LC*+*&bV33|=kqdilK_eg zLJ|}+exs@GpyzaWMFfBIIpa(xpw1l!1-#$A^WB*{?j-6toe;<T8uI2B%cwxedHDA${{|wR=IxIFmAKh zhjn&C*hiT~aewsW5M{>iOEUcznf?nu(|_Ul^Ixq0Lj8F{3;5<_rLl7r+#2bM?EexQ znZd2>0p~M+|2j?^{Zs6ptNzfTb1zb@~Gqgg_m>a?keT_S&r$u~Lc zz&2{wI4R*Pu>WNLYuq+R51=JJc6ch(&)(PB6c$@k(I;BcByF3Z4}s+zhVvGya%I`a zf8vTU{dI9`_iFR)WWWFD2V8qH{TG@3i%kDTJU27_7b??#u^8SQSN5UlXU6cq{uz=mt_XX6g#RN=7xh&RUN9LfcS;K^90g!#od zPRjAIYm2RDzlxK3&FS&CyP)Z5dA@DYNAbG&yFWo(THb|moWdrnwDGdmyk;tI)Su*C zKb6;>f1LU<{TG@33vepaf060GSfpNg`Y&wP*76hZz3bq64Ys>K3eSHMHY7jVZ3-Vn zkLFkTE#YqNtGf60I37O7UfXtTEq|5oC&7o`%N~E-2Tk$bb-DaUFI9z;bmZTAsVRQ- zx?KLGIUU}~lyS1z6@GNrF7K_-)}KWG#YtTq-o46tLaU!>qaOA4P}+DBe7>~vEvmO9 z?UHi_q2+Ixp?z&V8yopNuvp z_OGvw{pjkDyWIHQkh(go5SG0}4c}L>t>zQedl9|WckQ=7Ox7I6$KSIt9HK0-lUo_v zq#Mp(uk|S%o`1?}Y=1siQm4fImi#>+}$NvgviK?7K==x_;T!rKxL(x=PXg;Uw@$+fgAb?UMGSX;#|ZGo~5; zh&>{mE92)u?}fmCbFGkfW1_b~Y(mR#vAZ1q#zrf@U6{Es$$k8ESRXN-;IRMaLtbN# z(mv;Dg45bO2tFnCFjwPp<9Z}K%v_kRD?&%)S=;8xeZPNso2SWcHw=DD8|#CnSmT`LSZ$5xB5+v<|HplJ;|%0H;8F$-fs{;DjZ_%i`*=Inb#E zW-*BlOc*ln%;nuY7&c|?PV%LWe{NRMz6`Ejc*}z9g8ETX7WY(JJaQ}0Y@8s2*QWrRS zH2o3{>haHFkIsI*+52`~KU@5by2_nVbM|^&b-$PEru-g2-iR}V=0N-wU%`*adwhG{ ziPiN=&}9+*N(`eqa8ZPZg`N>U5g626-;acW(?_N zNnd%oETWMFXXK0@y(5Ar6?k@8J8QtEAueZ+&`Z(^s~6!3cMO6jDIPU)dkWDvwmCd; z_)EFR(q$1Xo5Ep5_@#``OgL&<>aM^`%QUgS7<`X2-9cNd5+`!5Lw%+=UfQ6W?8U46mi*)6>vco; zXZs0PPmR00YSPBWqKNr&e_X%NLUW({hP-Sjd)+$e>g-`1Kh55xIjZt0Jwyfpxdj|$ zxbn#>{irRXu8959SiHw^v}s^hSe1Ds`O!%ku%@cZqghq*%G|Azr@3}S*CoyDx9Gb3 zX3hof_j=uAFA?m0GOWDY>dLz#E&cLO?(qH&ncsJwY6@pZyTV0(G~_MX-=h~_G35RJ zsY?Iej(mQRxe>Y%xi!}OYrOYgw1#wcOkamvv_=!&OL%V_R=0cCv5)*_oxJbooBB=M zA#c$K2-u&YfN@`Xv4#F9_qyg zBU~pex=kg$jBhZj%>1DKU;a(jz5B!JDSzgr^+?$j%Bz#MwLA%@<+=K&l@}W8?NE_d z8W{C%%SB#!aLl`%@lV%6!SyQ6zkA4QpToS|ZNus^qb1zfBH^kFXSyt8)U&?~0vQA{ z2xJh*Ado>IgFps>3<4Phex4z4^ShS*MEWnte{Ar)3iMz6{>VF*9}f=G`KiZpp*M=f_roGjlNOS}=d#IOtLeT@zh7)}O>R_zPznRxgMoDx-RQVQwheDHfQkG9yq7TC9m*Biya6={W5+}a{?qf6k7n%MGzv~no za86!r#j8yJ#o;-Y>A%SIUu60(GW{3Po+(`yelK_6xYoD|zZ()K@*aJ$UrGF0;x`iC zrCE@qg?AG@VIrFyM%s&>it9P-OL^QI%Gw?c@U3lQSj($|$fSzwYi$g9^(4H1SCn^U zNFK`7QZDzIQhq8I;L6GEnN{KLTV#I2fN$iNvgNKl{1@bcaV|agoG!h5Pn~NIytLd? zQm(r{r!OkusU=@U#eH*SoI4e+AXnz%&c^Sh{Rs?e$P7um%eycRSCV`+@t2ZTeDe6o zcL&S&Y%QnxQoojzSt%stByBlf-4!V}DZjcv?vSVYUX7j$1LPQ_4&NqYu_uOqW40+y z#|6OypZ$QyKnb7k@`aRteZ23GwKm`lbhsA&ZpDb#^rvDEr;u54r>z14=hHqfdbSQU&~(5Ltc~AL!;<6U*~&F>UIfx0NS99OeChJy*U^ zsN{`bAv`ol{e)}aX|>OD;f91a#^K5-)UnhQ{jE{HdUxJ^Z|2$xL$i33lQYN?wG}ks z^_&aH?`oh5(uU?}Tj6i`Jsv1uBa&;etKq8fwsI-^j}2(J#L$$dv<317YbdLLN;6) z)*uNBeN6RVL~WV=i@oR`%I7ZedY};#xyXMKx0mo<_<+5aSZ@%TF^1cV%cFnfbY1pN z=lkz6-~I-7y2KZ(m+v8bYT3)p=Uj#F`EuDCG?ABYM`vdu^VilK^4gFGmT^$ZD)$>2 zApDo&-Qiy5^4=bs-%GiwsRN12cUwQt*yWLX%op3dg?rbR((!@?FKjdZl zFJgWz(|-Z38SB}rl*5lZ%v0bDan^d~KgDtKUG@WZUGkf6!sps6liwxYIeyp{E76lB zb9M~Z%N7K>9ofsrdds@86y9#s6x-R)Xvz|~eS1!v_aO0gen*#0mDS#r*Ui~CYQLmC zvoJ1iR$rh+_OrFTptZcS;{1>u)xS}(@KWeXnS?h=)5@90bUhuS zn?U%rhTZ7&b)@B`d0NXfymJ|%jANzoPh0Itos+#r`=@ny<1Jy?lT?1nIx?hw-BM?! zGb3{2>n{|3HPe|PxbDu}-PuQs`|fue=VyJui1-G+>f-GmXMv*oL*mkW6YNRkeN|25 zd@ox2bvag^J9VZHXzt?bUV%_qX<(o=NJW;!#}#u#?C6CEmo+vyl_Pm}4) zVDCNHf@_>33!bHTFZ<=D;4Hdr40tZ|Qr@`w+rJU(v$EH^^YS?THSWAT#_4O^nYs%n zZ)u0f8~@%omB((F%EP$G{HRKOyt9;c_>?bkY5Dautd18iLo zcZZWWZ9nPy>*gtXBBjo_{Trt0l{s1B-faW-c8g=bg8y>r%rNho(l=mln9?`k?l&Or?bU;xY7w)H!pRt~bQ# zJxJk-FK~S|>C8~W3C_GibY`f5DI7NDrH#*t>dc5Pn$nq}2#ZWY^Gw!bp-E#WrZdC- zLfp1YX9mO$dl=X*D>kDZ$BzhoZ1!%^dF^<1QH;He~exGiNK9Njk zMzWqEyA9mjy1`vqPa0;uku^!yo5?(UT5>;<>C8ap=jU8!hUn1v{ZEbQ#dqq%_jh^B zBQzFrx6eBO;WL&Xt5eO77OP`XJ{Z;BIjz6PwD78h>k6E%)JDV!!d{}!D7X1_wo&cxU;{=!8 z*#h;&dMePhf}V;hZwvzScJx|^pXtxY^k)e6Wq%n2G6-Z4$RLnGAcH^#feZo}1TqM` znjrA*8-6nV7vw*7cL$IC`Dgw0(&d*e>-+2??|5*S-p@?`#m{==UY`0h{TG@3i%kE8 z+?}sSra}24Z&2G}+ZtVO(<1vk`C*k$b(I|X{i?&?8{E;oIRCF|`@go8Z&SQKLiSH| znjB4s$yxcbcV1g;7uugemr17oq8vCm6l8aV>UE;4L-cn<|7TlS^mT}i54D8ff4{A~ zo^KU(o=ewHSaf-q?{6zh`k!{ZwmeVf+KW8NL%DASz#|%+9LW9 z%H&bcqN5+b(K}aHRG(|#1m99!B+}04n{j_8xZ9V0rg`P8TiUNkAL2_M>38(?ZBBQ| zPuef3=cxKsGW{2BEMi?VeW8q>+!>}iW(0QXz_zlCOY~@bC*gF_n9m-87Zvri(?uic zW&C8k-I#ti9`pW|c+-sW)&CN2LU_~be~CMbFqQ$;!H8GVBVNecs!&~mi+#bD);}GT zNyogqyWofnAD|M{)%H`FbQJ0YJ zlAt|ry>_MeC*M2xp6S2H^j~E9FQPqD`VRbF)_h!RT!r5ai4z?OeX(Cj{958S65pj+ zkfi0#Qs#K3|02rtU--y_jj4RF+ZOA2)gd(a@E`InHlLdnVuLc+jqMR^c!bMFygITj zp^5z|A4inGAHuSdg1flSugy^I}GWRd2LSw)dYb#ChGp{v;&nz)TpLM3DDHC}b?M43h_$GbW{)xN~{1xOPzNe09 z14ZngRMAaPLBEB*TzkQwDK>g&Bls_U+(8>M{THA2f?q6q(Y5iKp6S1Um*JgxgZJT? z{)DA8S>`s9r8}wH{>lb);k9qKBf@Uw%i$ty|xO1vsBQ%NCk7xQHS>_az@i&o$_(GM7hP*s$U)$h_x4qxw_gPig?nnMUHCo((f9u|&^B zz8^gj?5CWL3j9p}MW+9v9XxyVZ0mm$dU9Qa{A+S9)8XQg)lclKXZkNxrvHL>7@7VH z)>xbAzYw|jI<6voY2Q5E7%;`j-sM`}8w4u0V_y+nMv2_K7Mt|y54<7X1yBB_%8Sm# zN@54Tx!vlJcg?{xoAqhl+ZTBH&h6~MlCyFD`OkaREv6Vgf0s9Wx5+pCK5V0rx>lnbMtddN9pLmVgg(|nZ3VvEGYW5j z@6LtKjC`N;6?8k)n738tXM;C@f%uYtFYhM_OMIQQ>6~?EwssCkz>6Bpm73e~eCe}XY{xWu?s z40>A6B|o?!Vb(744}MG-Y(lekG^tl?lUMgnlmrhd3mKnG|Am8V6L?fP2U`zr z%RF#)w28~~Unr+%rk3fynAKPUy@Yo9;!{S|c=%^{{qU zyw*hMQS}$GMu<*^WzQsh@6mL=tao!$Xj}yUD`ZXd@VnoX>$6tX<(q_&J**OL;zWN- zrvD<-f6-j}HXSVC&U@*4-E{ujb(6Q}&E6ZdyhU%$-lQkMr+UHq7 z>Az4y=W6H@+Y#+@dMt+FGuAW5Limgx{2^Se%jgJxatFMhn~UfnmozR6?=g{vSz9Gf zJYO^Y7mzat-^KvE9rRG-O+-%h=Ux8=y>_%b(|J+%M3-3*G`&=JN5Hqe8*7$vFfH9dj>Xb=~?>vo~8X4 zz5b0Cy>4mG1^r9km?lq(PJi-PSgDVH|8rN(P}NkLEc7A>yh#5A?`u_?)h;1#XkT+^ z$g^)#<<}vru8^ZsXP1!?F9-H7KJOW9E~`Qt@kW_jlsgxiUV;6$Z7%-x^Ot$=N#qrd zNR!weiO-cNhkJ98r%!*|TjINe^!H&O+s;x>wB^X}7Y^JXUMTmd*j#umXBhL4fxpUp zw=|EpV1M{_Q_D;cu5!;kWjzFGWAtR{qPARKbgMkbAcZK8I}l zh4jz-%eL}`+>y+iL|*@7RhT!4?pJKUO8G;tL7#F@Z-}i`ZENo<54{GMV1IFl``qXs zwv{#c$A9bdp7;VMO*@7-lhwcZStlDcl_dr_fp?bhm3p3xJSjfPWR@TH`K!>@&ntT!yw5Tx$LZp+ zQtqvU=KMIU40$`oI<@Eo5BFZ??AWGhqTh-0XzTzET^jnlTQMcab+3;V+GNJ9rbgKY6zuqN6vQuzJ$B-uT8%Iz(5my!&?Hi3r?|$`Tho zz#GA}$etp9T0*|GjLb;+`?ffelvBQf-}{sO$TCh3I71)LRaAkY;#sdJ z+trxo?_D1%!Ut~|!&VXU71%H`*xWMTj&VA`ZfVffsjJv6)!0Z6v5{Uq)jAvLCH!Xc zMl?8`F}j5L`-gtHdwyFGoW6|Txa5s!opdrEtGp4_yps`MV8Z*+LiEpZADYM&$eYoi zjQj;Kia7JF5^lbUdU^w00k12>`+Zg5WIgjWxx0(d5%7oQ=9_>maPyZle;3Fbq1cwH z-xJd}xnq_4RXJ}(ZZmAmMqm5pxD7J5-Mb>}!MJexuINkgyP{l(cv1Sc=)cD_HUxLf zSL6Ek{^)nTLFymF4PMNfpb#H7CXU~OCu6%-9C)(#e7^HGZ0{LX=Xo0@;rv-iIO1Ip za?x$_KFCmjrn`OQ2c8$*e zA#;*6g4=m;JD=e8Ag~w%etB^F0>UyLLTB6Z*4sy4x|q`!^85ST<6j7^y&3oY(+GpN zZF{k!YpxC30>SUQys$z!%u%`LIF0}Dx>P2s*kO6PgvMvIn7W=+J7YCt>dFZ0Nr`ikbJHfNryvLe7cObv^ zR#ljNYUHmij27489|3ptP7L-j28n(N!GXQ36RkFX|B^LJ;3MB;&2fLb;?}D0ep} zu?BbV-R-@FwWT}S?RD?j?VYTMqmPd>Pp-uFUfR#OjL+kPqk1mmllD#e70usTz6YB6 z1m%4dINn=S9Vd00qV(-#%Dsnni!((vt9#u*{vPfQ=iY0I(w{3|PkZTGH+_oRb6?m! zct7pgO&jj_4EIId1NVDRU_0k=@|}cUl8+X1`kr-nCU{_!Yi~q*i$`y-j7{3+D`~UE z4x+TVn>KexyTWzdrqInA@&w}|VGHejLcUXH+NX7A^1E9V=Hg3Vj@=JnxbdMFuInH2 zx;GH+r~UNn$bQ&T_gRsDkF@El+gzLGQpe*`7xAfV_La0>WbUNRa|b?ES_f>q;h7Zr zkDj27>&Wv2dFJk697!u{U&LFrb*zUnZgZE7IvzmA?n-q-DE)N#v8gBhU1!fPNq^11 z#&hXP@bPiRPUe@C}~SDa_rNfJ@VHXfAW~%1f2* z2CwH1?gF1D!ntObH+KMMnV0Pyo@<|%FPwr?=!u%k98SxXHcFY&4hK_kq7_G_{8NzQ zd3<1xmVA%X<_LX0Zd@q;o@INqtE2LnP|6p+RQ&zI!>JA74tO_tL!-Jnf+^iQ-z|yW zov>{N-8-j@c?;JBpmztB^v6ey>RgIBFeS!=0#4SNis?eM&!pH6G|V$~Z4;8|=> z&J+&EU+_9TInc+w?e0+eHo4O}o_R9iodxdl_G+enyMDo63tt`l(U2GH?a}@f^li4% zBGV8+|Af~z?Bj&jc5R|h|oBeWbK{;@7hh$w6*+b(uz-ifk*qdhl zE_*KdF0kB@FSzn+;ziy>>9V4t#ix_9d;9XIjhaJY1fXC3pJb+iQ~iZ=WjDTphDgD!5Hu+uHfiV z1DhVrsW|mR%5SnaO3V9-%CDMZ3ai?bziNRg4)J?6;f{hTteS&!@k+NZ9M(Ix8{8V) zdfX=6$z1A$zw78L$GAuPWdB$J_Kn;?QFH;yKC%ICS%DX;;VSTweu$5&iQ{(#zS5^G zb>+5lgEZmAmL%}{<*jAeXY4krB(8#*9NvyAd*wr&zynp$RMa{_AWgavAbnV7;HSkAOKDe2=|BvOf&`Ay4LS{Z{5W zbfyVEUK+cR_lqCU(ry{w#!_4G`>xc(at2U^W(?sdvw64Gwbxj`a=FoswYDf}{l4GO zX`1NsevB`!j)*$sjE21m^#}}QZz6ha8qkO;ys&%|{HoLMIOfE4SZO z3U9uvB<>rOdE%;EE@#-_2iSXXxyvQG- z9mBLK+_yg5L74TUD6p&Swx!0cYjkCc$=APp7j~_H9eC?t2)+s|1cwE`WG^tz*vY!r zIEOK$jOMLI2gL1QoDbk0q3m{W)PBn^%bL*Ox4fH>Ip{YgN)cyEjXeVektLRIwNoPB zCw&87>hj4W{jcFG{MI*M>hzc{_{U7SN80$&+Ymp;T^P%g4*E!y&%p(nN6>6lj^R|^8KFlLOPERIhK$Ehj(Wc+> z%j2gZ?>7;TW7HkD;|}VrTx~7-l7gJ zyJI~jQkTEy>8ZMCbM&>ioG?o2@1g#`CT`+E&%UW8->9_lj<}8FGk-}M`r2eXnmIcw zWSn-`ub1{yN0|S53FQg?@aX;Fejj|vkHY(?f`i}PrcKt>@!d8ra#q7{Bt7qe_Rj~u z;gKA@fk)a=ihKzV;}21mtjU$rftL^NL9Z}k8BX$D);C!%=(>C3Q=uMBI-fk1f#faA zKX`7ft`T2xd9Mvc$5n%N*P*!qcwD=gvfoV}!EMTIyc_>L#JTjmTY_dbkiT{HybzaX zzVEp?FKHXO(W0cki}DUhIphrs@++jRN%=Vc7Qz?t4O_Ra{AZK$ zzY~`)X{CIZex~+(Gf5BrNq#BQwTE&qqs~LP=%X?2H<-6hw^t8%4$PaZZQ!YU2PX5j z#(b2y-ITXeeb74aG^G<|`g4$Y8OP{TetC$r!D);QV=r&J+`1?8_O;0KF~$LN&duXf zx0c(Bbd^ct%^p z`E8!iPW|W*^E}1@^=N#StvP=m;v8Jy;nrMqu-0g+qigiLMtWJZqd)tATeIg-&R3w1 zbD#kqIS9CV(ms2OfWD_;^@cc2O=trA#>X~}A!8c9J$qX}=cl>&?U}$-zSqw} zKb?#XziW(vtfRi0LmNX)dnVzHWnJ9?f8xVyH19o8hHM(wPW62%pLR6 zGu4`n-$ln~s>sQX$GC3RZFOg=4o0MLFnWIiBbjFp#N#F91guxGcabwu^}%$m&{i2g z&YmlRvwQnW4e3AYWE_KfxqyKwxAp9OM$gs5J5NoA#SsrS^Jb*+x}SxGa0+uzR!eyVKwx4 zo^D19L;uaNl9zBdgc}-Ey7ACxv0@g4je)$b!&8pu*<0>oTOg}vA z?6vFd@L9w)a~rh(70wVSN8s5YzDb%Ycwre!>3?*SS8fs?JOMp`o>YOs{`bP;gY&~% z;aLQZ@*CPGG?4weuc3jH&|7`M`*iSC@=1J7OIO zm3fS>;*MmHI}*7o`NET>#o&sR@8ZXj_`*{q^N-ug_AmVMV%lqNO!TQ;AFuUGxLbk;v<=nul=1c#=TFZZo;_6+qRr8)XWyp^q6?yNGWh*g z<@SKjZnlLb7eFJyW6ioLdyYx&ZW{1Vi+69#o4xRU2Oec6?uL1zYl)_{sR1k_zUsBF89}VV<e&c-xQedhQg1hG;XGGlX|YD z%>sMhULF28us&8lrng<%EoZQ9{Gs8(|7-9-_J)EBL*T+VxFGz(c!~?G>E;E$T!X(3 zENkc2-e2~+LiBCrb#wORdgW`ZU!ol0zfC9fcJPy-)KkN+Z2v?kZPtRB9-f)t9P1-HzPWG%g zT~}=)yuv(JIzXSBXEMIrWew$Xx;kh}(&mWsW;rvelUMSWPQmq-y+=r2hCeRNUd?$^ zr!D~_x85KAePbB6?Ol$3O503NT&Jwd0tu1-|^ybG*GOB`9GX6NrngyO;c$+zoC(hqXKzAxTH$fz+<M0Z=rivx2Ny@sO!#8@)ryOaTvYJ4ux5cn74EZS z-3~e@zyat%&u(bv{hr$+gA+k6@`hw=+TIaf5uF)EE8;!I4(gWu`40NaN~0#hTe+i{ zJQMs!wrdA%kvSxLT*cXR2Xja6y5ycqc)oF=W8iC?&lIdxWyxz8ThYxG6g#{+WovM~ z+P6k)+A3w#&Y(~5mTr#<4o4UJPA`nijru~?Nb;(|xQ()A$i6_*2Is;Ta#kp9s<7{~ zpYhA>OBgF?h5F96^1(}XIUP2Z^MzoE&=7bOe^+T0eC^QQfr9KI#@SoTey0wfd`8}I zUaAUDK^IF&xHs|p694IzZwr#RXIkPGCUJk8#8sgS^>;_%e*CW5ec^uU4rzD9Im>O| z8`N@7DE*PRVfr$;VncWbZD?no6ViVUPQ8$}*B{T9LcyKJJHlc5C}~S}!h@E0T0Q99 zPTcgpn?~Mi=zF%9+WTnTpE-H3WN&vn<&TiRLK_d@8k{pX(6c6RZO{gP!BtxJf0E`A z_ERPHC_=kR#FseRaNk^e9;7`FdeLj;T=_wFRuk{VKEYYE+rt&)Oj^#p14`I$u zTs@r6YuY}^S-WOka`KMANVE26(%8TIKv~ZB$Cu~a{d-RZ|5GKGpKle?_?*d0*^|`cGdKK4Zz##Ukn{fvb3^XLsKEhl(CVp_@_yn z4{t?yeiA3&#*?_yTjC~@xSp0c9c<9*ZSQw&Y|uA3t8-^2oL5M@^K9Lo#~Ebh)I#>} zee9nu@7J}yi*)7k9^L3$tPk{=;{M%HzH&t;zfaW%2IJqgD-^#&ePCnqTh3zkz~?08 z?7zSk4scE)_3ZebEmW@PC;de&`IGXK{D%4J(vq)28(doImOZr8FSr+s4HSdVvG4pG z_Ys6OVNH0|_JLwM;da7z67C?}L0I~C0J?r4KTv!G|B<~>zC6bHleEoVnWWK48lf*zR+=}BPxBraj0)0rDZ_Aw0umB_2zJ=YecAHCqyY0&ri__7~59Vh#t z9-Qolrtc3zYrPKg-;Ni-J@NQ>E z{sDM&;ZI8N=^Mbk)8IXJhr=Bj4ql+!5Y+ zkAh}A=ruSS^WV?80Owu4oDp;0#lD5JtG4(qjWb3$JC11|YZZBCx?7VuD(lvr|1}EP zM04KETF?EP%sn4^JEM*_X!?}iH>G@JcvIbYM{OH4S=#nx=*pvOBd0^HLiv%mHH@BnnVCgqtI^CrTR2!9~Fz)U>C5c!7SgQlM+3Xh;TLlQng=I6`(XTWQ$bO~H z8Lhyt$r;x01;)t}HHizs&DvPM7MTP2UU%Q)d+O#WXB9$=;PI=2F&#B`b7sJw+}YOm zZVY>n6YfP$czvLz^vMKjRuA&TCdkc_v!Gt&ilxo2ugDe)jHMs540Cn@KI+@nEB}M_ zR&qxXG6otad-R*$YkiB0N*nZz+>J%h-2virhX&gezefq1&h4e)i%s#ed2RX4^HgDZ zSs}S^y~3Kkr9w|Z?~yb;gJGewQ!nLvziP{iJBM`r{H8aY+icLAuTq6yBmC(%DaWh) z+8+((_3nIr@j0g0QEtnJW#dPb73VQ7?-JscU>_ij`}Ti|!d3aU{9@vT*Ok7Pli#wg z34Hfoen*LQEkC(Qa11zXhNlIGW&QMUl1Jbq^LYhsdf$GWeiRDdC>8dc5l-)qq5QP% zOFCJ9aw?zxRxhDng@E$+zPNllt$h1qmha&9^ldMKTPyw?#+}X97u>MXCtrjYg`Pl1 z=9+Nx4e?m(*0JRbE$zGb)5liERVU->+H-d-M>_Np$1knBuzX?ITEA(j|5#(u+Kxi? z$TIA-GL8oC)-qgQw%h^EM`h{DEaqYdb1?*tlgvk%hjO=Y=hN_Q(1>{M@_(B`&c*nT z!S~;Z6a20|9LuB#{vNHI%f6@bLTl1;EagPg%BdfvoFUqD7x|?vLc`KBrng1Zl_-lybpQ{t$W~YtYiG0S2F&mOR8`^PH2LYOBMVy*TDZT3|s5< zDX$Xsg*Ra<>jvsNr=>3UjlGGKc_U^10p)!cU-~LGOH)`#UoB@VNA&gT56;+EDO1J` zVSHcY>JDsH`4zoNe-R#E>XH4z7jnv9J`a9a_71OG(}+F0j{r}!+jk%EBGqo8nG9<>ux1? zY1~1W;v>MmK|Noho?-49SD2?Aekk4)tt5|OEm^^Rq?8x^AHQ4@yr-?hE%nI!4hvjC zwzU7V(tgG>Zht}B9Rp$dTYO7>hI_Z-f`PF54Dy3F$GCpk&CJXDtm7j>`Y2^i?{{@y z+;8c#^gS#HJm`CVs_*AdSnu#!|KwoXyO=NW_{C>N*pe&0%Q;ne;J{%1JKPV*UFBk& z&=a9Y3ckjmpUrZnD))eg<2#}44-V#+ymp|pq)in*{YUw{@G=rUGEF}JYq!}X&0t<& zDQT{!j@y$u%(vrnB-z`Gyr}dCP%FD7j#r7?jD>Hp1D|x`Am>Vw#xTBSOG0l6uadU^ zzwtMrovVpcxLMDue8-a}Fa5KhoBG}n@f#VzHCwFXS*1+L_b4>mm6gaq&VrT;E=9zr zqD9ob(7feZo}1pd7s zFdG{Dr>~9t*@m+gWOOU6U27LY!*Y9ORmM8C{`&gRzBQJ$aNp*tf#|%c`Q58 zsP&Z0I%KbSV^F(%jUJXVNT>gwPn6V}I8AMiDjvL;^VtP!^g-@uEM~Rky$DZzoG&sL zW==F~^_)SyD#_n&cZD6a519(D!g+G^amBg0^`hZ8Ph}APGf8U^C6e;eHr7e!U%uVR z3i(fu#ry(wq~Gm|r2eYs=zkh7a-wP2EKk~Y>Cw}u!8na?xm)ew-f4?12HZoK<;Vjj zZL4vop)G63B}sWEDK8)Isa>6f!+-PJg`bX+{j#|@PTv@SPff~FZ;In8ld;Qw7(GJgCFUjeNQYq6rcTAwVL|c@9!<8X`>52PQoS*~M$g-0^2A0qqVA_B_$(de-@wB~L%YO>5{$auuczhY3#v3DFXjL`&&H1YKFN%E8 zSH%jCV{qocerInK$&t-PMY05B90Y2TifQ_c|R0B7fM1+$i*8S4=-d&w|grZIyntBcCJlS>%Kd z&Mp8e_l~9*AamSAZpTNKxCUJ0w~q{E+Qzg^l`-g>)PL$!`&++h-cL-ne5-)FBC~*f z@1nR>oIRvvR(>h+8$a4`_;-!p>9AxU!6X?d@^( z)WBWYL$y=>?5Jgp6`J+6qFb{XpJ)Aiiu+pDPe<4PDvqzPmO5I{^|r*n>M*Uhe-Wn< zT4et^z9Te$p2RU$_Ro^=<-;zo-*u&S_7D2r;^>~EnO{xnk@Qa_VS#rtug&9A-{W?q z?YTT@&y_B%$Zd+eUjuxRdp;>!WR}x%B=3-{;d4xJh&5>FGj3$T$=P#t zV-fj#Ptra(emF04&+LucQR(CRXs0%N;@_=lR20Vr$U93tQf4rBDlBuiCi!P~=>U0f zzsulvxO#nwf5;XqoRdgjf(6zOpm&0A0ew7N4|91H@Q3~v@AwMuLxI1fb!ADqIeFcV z%z~qR^QLHDH0NkE@2VD>XB^E-=ZgAV(x0Rct}XOwe9uIwoaasi_*QsdF*#sM?mi(o zU*OGZ@lKqq)v_)N4prySSNjKHNWKzI%6J4B&_|F5FQM~+|lUDOir0^JaBS)YY`&o}?LGR1ax121QYu{4q&X1)E zgB~YoYil3EJa5$R<7|k0A?w6sZr6;%7jF}w)Ao0YZXO-2 zA0i8VL_au3P5Uv6_LS|jt}m0oOvXU^A^NDKA3>qlovE4po>@VDz@6~~c{|J8o4``e zFyK?nJ@N18BeCBua@oQMtYw|2%;*L9l#8uj$E`e>Gn&x)cjAV)&mF$V`sFurw*6+_ zTj6HoDx4YC$4pqd*@OqLHett=#*HD5f&I!t6YIJHk89i`HJI!Hr*>aarFE9UADIcI;Ia^xIYfY z0Q2VNP1?}{xAyY(7#`h6_B>v5e^u8#S$juxlW`0B(8tyLHeKbrdv~x`do>BCzxR=s zv8&?T_b>2W!s+iXYOirBIDm8CzeM_WXv==$HSstfo+0?t_&r0~2S=~ylhACz$tp0E z^LGD3pDkg_qag3t0$|bnJTjWl&f3z5HxfO%0&X-%`(4}N7x2LW(l&s*&)J=ip1Q_X z@JHSs{yM+E!22V7`CY?zeIA3if&Mk%{X~|iIcnN`;5NRLaUWC;7dZDW2=63s0iC=Q z;dCAeuKc|G`QUsN*X$kE4T0Z6fs4ULnS~#-*s+B_hL-v_1H*HH4|`jC9(yhFR7P3v zdCORtM_SfXv2iDGaqkP+Cq}36{vNn03my}`o-^-uS^q}f zV_I?COFf6LZn5rud?(|2h;cW_Lq@dC@>|gkCH_;y^RCn4BAnuFr<5)C<%iGNpEqrf zao_O5obCCCuHPPRCa>wGeBo2znIGbvs`@X=wOQ?t&w;;B*>+r&MZc8He|cl*b1!Fe z@qXk&zRS0W^+-We93DVJ4059`%pO@C>In@rz(99gni<|>D#?@30hQ(E=H~^-%}aRe z)bA?c@s{5=)A#7TFNRI@T+C;su#vr*w9O);Cw{dIor!jZ%@So3min}eA!9I9W(*d@ zv`@|q^v}W}C*35jF*;E6kuQ^V0_g;|X86dOHAYRbF=~tc!_cn>aS!3hC-0LQTfl+ee6l1m zha$fnpbPCt`eECAaJdFvxjf`U&ZNzUzWVHq0`^AgP`o#q{B`Sx?_+%g26E0)xm)EM zz&IdY=;!2STdEMQr@xmPclRoAbakWaFz7l7z9^RW)aYB}T{1K@}|e}x)LXQdY}2EP^=~AYOXB!Q#B|4 zEoDyUg&XwSkCHQm6bC-;m30Jt=3DL1k>8@<^2+1fgZR)Ift`$7aOEidF}i|GLold4 zR1doP{lTg>r8Eqm%r~EMeWN`?9h1`bKTCf9Hg(eWD8awOeKhPnNf$Bht$k|c=V$7J z`Eb&QMbrV`DDOw5ev?nzQ`I(?hL3EU{YcU_!#cDj($d}vw9}71#d#t0MaE-yd_F0- z<1>dH{G(5V`YG_1`o@tru7t?G@m>8O=EeL7J`r5641C7v*O7Lae@^%};+xS8E?)i9 zRGdw8?Kt|(xlUSNg|*O+uyaa#YK(hOh6et9QV(Mx^HlaFZvRO8_8)_vYUOWg^JTqQ z9~$0<=m~ft!}xNSCbFvbUa$NJv{k|-`ZdBFJIL6`o#V)b!h3Tr$ys9a%j{RUOIy{V z%ck>IQ{35>%RhP{`@Zk1{9}B7Y)+@1#Ts-OWnDI(a}3If^ToPu4)FUiIUC@wv#-oP zQFtq*cD@E#NcfM^)pwR2;jPvqedzmSOdi>5@`vCPq^?KcdrP+(E%^jSa@NJ13!{0! zg}XeFnYDGVd^>%Ru=J-L{Cg>VX>ISZ`gI_`zF=lo%fcVtN&j~|qw;r2|B>evS~Ck; zW5#1zvjlj4ntq-`dv3r9y_p3~Vofa0`hjh0+^q7mSXRO~5y#y`+>NX|pA|>=yf>NBc|RD;{{iks!Z&gkF8AT*|KGMGYj)+m zRv%yK%j6#|e$=@OjYWJ@FZ|)7`=R2!YvfKs@+# zcwZ4QH-0-gqhxQU0a)qkUV)&&R`|6sb%lC(}{@Bka^N=&f3UkW-N&GwA z|5pY_wE3S&d3+PxtPC#KdTH5Hv*Wei{O5R`oMpI6XYQxdyrZ?O(Xu?hCM@sXke#>5RcNnqOOZzupWeQRsoPajs%JJIlqwjNi`4MHZuVj8& zPtqC2y1qGz+G3pmN;TR~fxY8Q*r4O=)G>ov8CNA`ucYjyl=G0Z@?+PSo6eL;1tDc|-+U#!6xro zB){xIMZaE?vuL4MqHrzqRL&jRhtB&pv{-roh?vU$AT(l*Q6Z~r?acWx} zC+l`F7Rz6%SxH_gv_)=S-dc$K|B1-o%ex7YzgKow_yT8#vghAi&grE|n@xGN_(BM7 zmSQ}Ws=f$~S$&QwT*|tjwi3RWc`jk_Smxpii5pRc6~tKyUp4hz=3=_$ifk}Y@hr4H z+D!RdB4oUjZyq#SWW83yD?YYe(nJn!LgSUSOifc1I^Rj&H9_PbT8bQ;K@Np&xB3Fa2=m5S^^;v@xPxsuLLSwoLlD zO6o&4Z)DC2ZNJImXX;z!>KoQET&d5&RQV!TATW(cH&q{NGde7!PHDT8CvBJV%r}sW zqumPq@zM|TzvcI^mb}MnpR{c?vhM~M$#|~*4OLi+zjDEd?(DQhwbK;a4@G&yUSw3p zsdJ6)pkIKHt?H8{EBr(M<$9EMMduS<_RG4xN9l+)rG4L%F+Z}v==Lv1TE^#tOQTSD zlU3BwF0f<`m9W4rG7Ce=EByb;tBsa;+pEfV087VeuOSD z6R&Thto2P?z@Dd7Hn$x-kn{TX1!E=iPw^R%=;1l=`A>z?mX*`$Q?x;i!23ww1&82= z1c!t#GQd{&6vqp6nl=mnL>zuZ|3tO zE>q`BeRpL(sY0Ox{hhpt>1@l36F5km!8feG2Z6�*73iDpYX}4*Nt-SE*G=9|fLL z|MM4i>0D#T%dsaOkp7{2b)erA_smiG0dPq8zvuJ&9RHU?C+p#K=wm%vy4HTB^`&hb zrGL4eD;=LK{A@wm-BZ>B@PRqbL-ufPKN?+Kl6v}m_zGOEyg`@GF{QG)CVY_m5xDt0 z9BA3+u7tIE0AI#o4{0_Xgz))=iuPSMY!TjC4smHUxb zF3^Teqt}%B2j~}ge=Bm`&)cg@{k;Om`@-dQ8vUTo-iXoU(o};d$iuX5i`O$vL6k1dN|Q+4`IM ze_5ln(J!-JJRe4WKj(;>+IUL^+&6(Q{nBQB%Q%Qmij^kb*A%$h5IE;JlkDG5zZrvm z;)E9D_Hsu<|8hH@iJ8>2|^gB@bn& zLr<34ug0`{9 z9#ts!bd)S~UE1#YMY-*rz2U*lJNK7N)eTwO!NebF^!d3hQgF!|4a1 zClPogbXDqfWnLJ+L25uNCJXNaYj4yLRU{QVgcFK>} zhIZ<4Fkp`)Fj&R!fWFI{s+ZD#(`MW3zJa5{z~8sf^*P$`GW3bIOMhHn9**CrN!x`l zd;MHD$32aT)j#VRL3RIA!3=A6vk0=B@ZLe;>P06(o)O4o#AH z^~Ize$(s$Cv$7A~tj;KHf=_qnJkZnu_;BIHW$n(*Gx-7bo!BdL`_Db36FxruwugPH ze3N}@1WpdHH?80r#QVfma5eF7#+PsGeQUS|&L>R;SHr32X(Mw?+N{tuC+%KC`&J{H zWw31^?U#8yoo|;p6{%j}<(K8oQgAdKAAz&s?j^^VT6EP5JRN=CN%}X(>7(>LiqP^j zjGmXYESD$yFN46#41srSz2PUce|f{PTl6ZhfBCglH+}VZaNzq9{mkrN9s!P5?GM%r z_(=9$9H|)2@zsxM|1x^Fis||^Nc^PsFI8gaQq~hzVM>pEd$X+J#B7fJG(NL`$-e7V zX#djiwn@fwCL2AO{Y!Kcb7vU*oZ7#<|aLTisyQe*}qh+_6?)|9-lw_ zr1mfKXPubM%P6sfn|p=YxwPoV6k2jTJC};1uOrgEitJq4-ErGn@gQ9TTkTxhJ7e5P zzh!nVGdq{vXJGGNr?=1g?qx4 z)aMT(-##$2olAv%OPBv0Q)P;MONldllm4Y;PPc#Q>fe~;Pi$YNX`N1{{~&fQ?Yhj) zWoG9xvvXPDZeH$6YvT9BbV2M~Mv2YK6SZ?`dyceoX|a15a5pyH&ZXGDtU}+a$T6IV zolA3a+@=$?b7`?_C~r!KsN-06E-m&6r`x$Sb6>ihOZC5F8%2tDE2#~m>2@xoznx~s zsKw5uYLD$)Mn8=0T$)>Qj(*Eq+Ua&K&69CCt#&Te-w-!}oy}ir$v4f;W%O61L0@u{ z@o2un?Od9Fir?haPUn6P`4B()$?RN;eM`6g{(UTm-;n!7d1v~b=w-2UX|QkU%KvU$ zeuZ+~yH)XB`;WA{X}*=D2mfT9ZY1e_?ldoZkNvr@b7}rKwcW?~y^MA)&0l18F8$Mh zDY8O#^2F_2MqkS8T>iA|T-qHmu19YBY-Z=OBjR0${fX^ds$c!t+qpEGe>Qe5&DQw6zvw}k zZs*cYvw`{3v~wBV6t~0vTD;aD&(39pK0?uXa@Y>~(>Aof_JOi}$BXmJJL8Jl9nNIu z(*Ck~S?yd#%_HqxMv2|ae=j?i!XM4_S33*2(S`7`nf=Qb+1||TUm{P+{_j}!HB&ox znf*)jma*of@Dg1W(_vF(o;h73*bwr0liO;$Q|$F+_AfL0mnyS=`HHiDX)cZL0d~M! zzY^?Unm4`J{-rf>8!N2mnf*(2R`6b`WGB#bGJ)QLSC;)tb82S)a=QIX_05;p{-x?T zzWvKc$Feaq*}qg_X8$s?f0^08%Wo&(-2h_bS&+K2mbep4@{mab$WoG{p z-36joB(r}xBe$MKW)R3A@bd$K%>HE}Yg&kHE{VKpYLhFof0^086gyl|tG!9F4Z%Ap zp#UO3h{mab$<&=$S=t^e)GP8e~ z+P}!`UuO0%W4oT2{Y%kVD{uC&JL2qQ|3|QYse0ml$YGn77aGm(p$6g-$mtse=)&6Bfxi6>v%jm8j-~Oe#JF|Z| zll@C|&(D|rOI6G4UuO0%e>(Or?W|Z%J^Gb+k0AQ@Gy9h|vww-66N}62UuO0%u{W35 zzkCV%-YjVhftlp@Gy9h|vww*Vsm%W6lg^fx$?RWd_AkYbTW0?|Z*& zmDB7sX7(>L`HG(3C;fhnL*$kOE1`PECZOwv-2qV zkJP*29vr6k^LTK%rT@I8=e?o-4I5wgh6~Rdy86PU*Ic`FX$zpPd(S)1 zd*5{%ZhS{eTx)REO*i%oY}(SZ^z}VU`!9O^8!vj@(w+|dH&V*7>DEBHz6U)oz@-M*>)uETy}7c<&&FW%N6l z{mT*iTq#huqC@kNM3?3zo?fhilb8H_+rMmo`o!#Cns3K*J+ptQek%4a_nwj1znnkf zov1BL>&5dnPo6aYE7dNh+7rwE9nUVN{gY|wUPX2>)vmbh$Fqy6?#S$7&MgiW=FaKx z=6YV?qu7Kz$?OWd_wM%I!u!VVXt&qBXSa7UcHz2Bqu<*78@juTJRPgO z#|KCC+z!IX_T95M^5|)x)2Bz4@l>AcWbo-Zw%iNIEpV+{3^{-Fr$3A9j{r{2dVyY`MyO^0>%*-xk zt6fZ$*uoUMm}Y)VBTm#Vros-U=H6ry-R?DbLa~22lU+U!yRG40o5n?}d7i)o&jX7{MYE~YKTb}`KlV!N2pyIbsA?s>Wts@uJ= z5_uZA^5|=EIjwdv?OzjzT}=C?mVDFfVw%4s&8x&NX7mrSj*^$lE@p(CRA(<5`pS@ko=%$~IUCd~j?aN2@pmX}{5zqfZPpIB=q|MBqrd>>PV_cWI zK3?mOXBX29Oydu+i>a=sjJLlyzdIv1id{_g)|b~Vrb+Bz`j>}Vrm> z+0$o@ctiPKeP&zPI}5i6cQ&pra3^g*+MHhw(sa|yY_%Kd%A3E;8;YJQO}8PbW?@4G zJCe;GZTE6-E(iW4BVJ?no3(E~8~O`Iyvks|*4)7a=DT6g#d`*KXQEVZ+lbePTYy`L zJA?L0J=fCa2D*iOdvzH6|Lna9oLt3yE?V7vy3VQ7N3&^V6PnS2kOWA=CXVA=YDOb< zw-`W@!QtiQhLHe+StXe`!pSu?BcbV*F$g)3d!4*^Bo<>6gK=(rbK|^ANy2ouFb0gV zlf1;1u;X}Vu@gIvZN2YbbUWLRf601m9-aQnE5p@`k8k~#`Xs0SvRVJ7`tGZ%|B^UEe9Su?m3zbR z3~CRH!y&A%SAY3}PcBeMj z)ndCj4R#_}FWB$?H+zPOy!mQ(I0UY`A-Uf0ZKst8Uce(m?DOYgz0-w#*t(@+sOy~~ zziy7GbS)B(cggI5JvyC#cN@$nipP7bdFb5?=1@GoAvROId$G=m<2kTgc~1YO(|_so zU!qSt{g*UMj{7$rf5x~Tk7#MXTT@Q|Wrp-FIsKQJ^peQwznt;|#n0QQ{19spL0lxH zlS|*1Tm3GXz3}8rdeg~H|0V9AXO{v8r~guMY9~8ZYzGY3s%s&%rKhg;q zbTRLYcwNaLWp2GFuNVj~+?P%-hQGxP{uVX(Q{j3s1svR;{-DZfjL)C`U2WE#XXd2; zK#qA=<0&FN`JY%vQ~Q*c=T@_MVPm?ak20^1T^FPLF|EyMZeZ*-)t^%{wnWje;yD?Y z^|D*WEi0u*>usn1^4KwV`Y)aSOQ-+R>AyVUQr$T?1RMfyDFmGU%lMm8r~i`cf5}GE zXJ-Qc)D^gYeh>G1oc>Fv{}SJI;g7zFqGxDouds5JxFGH`KJHVM=A#-o%sXOo+=5G83i?gAe9_DIK)|?x$FWTQu*J{O! zp4CHJYd=xs=W3sH7}IaSmBT~a$M;CJ_LD^gI%-K5(1_o)_>B~8*k89s)YgW=|1Em& zM_Wc-x~>*MXT)pm(?n$c3Q-b{{gL)AA_#FZFDv|FZfnjKPCaRB?~ijN_XiH{;n`GWUH7)E>c*HZtb`hSkB|C01p zmY>2mmRL^@;df?pf8wG6?srL%mzRe@kKin_=LvpKLC9S4zDAInk9EB-1(!&pQU9eR zotrl*UkCC1$E1vMcUZyi)SBCPD(}bmjf8)x7u(-LRw11se23@ZHxYsNRcV>gFY4T;HtB(K+!wzm#YQH5f1^&*zLnLA z9J7aDHNn4t{l-e{JF*{yJ-%h4Z?v*&asGwxlgiJ5v(flP8Q_=PZ^IsDQ>XHmv3^hH z3X#HlH^QV|keS=3s;u6O{H?*cQa647kNXQw|E167gn}`r|I+Edq?MZcJ5~h7`+nc) zzjXR9wbOqYPT7CZ>A!sB6CtfP&uh4Muo3q&X#K(Zu=c?^i_y9S>mi2oS6UZItcz%! zV%9EgGSjRRZ0Sy&v+YZI8fzY-3##oP+1 z$MM?o>F9;CJ4C8dX>N5x<=qrqCRO^IWC-?f6ae z1J*4?JmE0z%`KNB^GMJsvtc(&_b##X0nH0EKcp}(V1~-5{oP?U#r$Owd-SC;yR4t3 zx8u(L5bXT@^UQu*uYVQFguGLEOj$nrk&&{rA@2|4EaPFhA>5RM#P=x=LoUOaHT$w3 z?aX1G#BWq6=9Ve28qbp~@KxP_IzJJjr+kagq1pIp=LDQ}JWtxWd!d#q(m zq`TwgB zpWFC{$U7butry)mn^AaZ?oOR7)7|)87y8Pw3UV*`X>i;7ht`e3O`}bAgM&6tJhZU) zVVB18wOf{7 zy8Z+2Uw-Lz*Zskn8{T*Q=nN$;qiyRZ6TWU7`}QW#fB8=vv%fPD4$bA92p6aSa%@vL z9&J)`0B7$wV`prN#5q0__InWdt4HWe-e(?u3t*DHs9C@sxBTxDl|%i~{$4YYKXTV= zZ?f}2>ZT~@?B+_?->hl=pmc+0Brgok5w*Q@Lit^remSLma1M#mtxH7#c`w`o5}&!C2|=BM57;2(;ukU=GwTrlKHXUIFu(e4EWT?axbR;X5llLDbDl zEvXs_MUiFlWvBWfP`G+U^A1sjT>(6jWymnedn_r=)m{CfMt=5n2{D)QJx7SFjbj_d zfpSoJ%cJbxA8(|VNhm>+wwpfYv4UBy?PIR??So5Ox+x!Ol1zvMRm8SV=CW($s4ft zwJ*SZOKm}?QB4txa%eLO?>dL~Hnbo3zm@#&TPTVG`K5Hhtz5!W#Y67f$$i7yL>caM zZc`S@@7pYMEM(CaJFrGOD+P)5-LGzrBCNLplq~?S6@@kRv+f*Gj4?9xfp$OnfZH-lIyHw!WEy6wUe13x(;QBH6PiNBSsUL-p zH*kSc`nH~c#Z;;j)H&pisn|~dm!xa~%2rBCpY-`q8H$L5+>*9ap051^(zA zx_3BaC&&E=ah2dkeW&n4tQ-H<_MIeu0oq~-dxKJs{YHh&vf+rQfe{}V{>U$3834-y zzH=$Cxg+&G68E4K#g8gcj{B?Wi{L#?`Y-jh0DX<(qPzyE2YMgRzQDT1#NQZBPpRkY z4vGuu1WRpuNzBzIbD_x`U~NrtCjLuJ?uBOeCUdpP94sFlU!lodYBE=0E}ez3Vk^ck zU`G31!deY)i4LQ^RWTN_C@$yMBo9zWdY5gJs@2LMK;3S`n7tiOkTU(LM0lXCOQ>u8 zXSS}XE=+x(yfhXD7+*?hq>tY_3vJX-aaSRhq80Y?p0Eg6L_aBZ%n(9e78cN_$e)Po zuSnx5{D^VvDJ<>jN+^R~(ohE4w`@N`-VwLW6UG4Kh3Y0LOBG{2yS+Z<7rN4-EZ3WP zhJFJVT|H(FXe?*a#;WrW7psp?Nu0HL3UeRsV~{)2O4@5MpZqIcrST|4zXb*XFbKfy zNB&0QC3njL*RW_%&`DPzPuSz_Chc0iz(aQY#jf zLpx3;>6R#5Jbsuy`R;QB`xeGR*wYybwITU87%K5+;zxY)kK-{b&OgnCHRMg8{*(Nh z`7wvM;U}3di!jqXQznUdASrL+UW@%xc}@5T{x&ZaMaUBQSGdndY2=hob35h9l%pXZ zWwe#XJd_cZ+M8)>Q_u$SG`iP}JNm*#-0zv9xP&Z1lK&d~ig@0jbWEPq`mhXpeI1Kx z@2#V*`4B0tD?&<@=2G={GMmn!Dk>bW+&!5sazI4HB#RvVuD z1QD>6d%_~*NO;t58F3eZIn_t)4kc=o7S;n|uvZi*{Vr+N0>Qd&%=H*QufnOvn{aK+e;N4{ZQZ<#v0k)c%t2f=e&3HSu56->4JxJF+P__&KclA z3)YvY8;YaYak3Ec`jE`EI8KU(;w|jEL|odlMTi+GZvD?T{tLjhjE6YCOG8Rj@dWdb z{|0;0R#QE^q_mKHOBAHiJea$Rm#D0BISvA=6e1 zWZxaTldMQi>rLaA4e%<}8Tsiz{gHgBI~#auaFBb!sJv*5vm@?^Cs@f%o`WnewPTEJ zL0LLhi?WdgQ8RKC){)}cm%@BNte%SX*zzqRcsFo8 z8Eb%3@Z|9n@tlWeHl9=Q6!5IZ(}(c~b#8D#otNS|H|>DR20MC}=f&+D-$YS;()g&) zv2zo(hopbiINF1}cVxaEX{T8KmDy#+KDP$<>C!%z*ZO7+n3J&?dKPINn5uE z(yjRIMU)9`C19U`4mX>pD)dV}F14R~ba>=Un9jE&JoMd|JSFy*kv^SIhUte)zMuH4 z%srmjZQ7|k!TO2zvGlEnff@YX2EPpFvgbp#t^_V7-96yg1|GAY%}&nm)ci z^+%)Yd^LVgZ9%<1@w5_CFkVpJ$!?0?9e!!*e-RPBVQZcGA#oe-`f040ap%vQg0=fc zzAV#y`&A}~^XBF_jwO5_(hBv#k-BI>`mK1T;2gXSd7!<05$4iXDP$0r3GY*;%@J)9 zYYm(_TlX~>dt&#y*9etO?E8fV+Z_3+-hH`f8Sr>3p7T*I^|PC!9cCY)u<5{f>OnUj z_RB#(+8?k8TDy4_ItzlqcGG?eXnVoIBfE(##%k=jMY8AKdoU+)eolSb>r4eVDC~89 z&dmOM!O7kHv{SnI!hAPBy@>G`<9bma3KyN%&EFd^?-O{wgXeU?ysPnao}A)cr=na6NXi?F#AanU?WaTxp0 zs$7-kTZTG={P+t40^^5q7npYn2p3?E{YJC>W(wC3PaHq_`+7Xjl`5BrkLS0DYF7EB zcwb(K_vJyuzI+b*8@sM+C`UmZ3?`JlSWes-K*zWQMyFl2mS2WlaV5bk*cHh_z z41WFu_;sjkC>1XQx7CQV0KJ*CKmHWP@K0giyBcK&&RL->wx0wJWVZnAyL5W5SkN;^ zl!^uM$?_UgCc=JPeE$9BIzHp1xnli9!i; z&_XG847Q1|EQS8t@yoBUK00dq!P!w`+gZ?qa-lp6aK=_bnW#LJKD8B+M`|DAm05qg zq0CL`PZi1aoC?ilErhl@v{VL*PUn=v0rg!H$MP>;!KQ_i9d2De`sUl`4d>TV}0TmHuMUC z^SdNmuwU}Nb+&HInJhR5=uEcSF?>vCvPX{RGvmfHlKwtv&w`O}a~3R*G2JoYCrEE5 z_6!{3cNf;XGcgy=#~g+Ao!GEZ1oL4|<;`BEMt(XjGVAAJM<7JU@8dj@?D|EKWY>GJ zmL&PR#@@zR5JAf4K`zg0o-%tU!O-W^h#z|;(N(~MbvK?M2Y;>bHwAHQfE(60Vgu}3 zv6jQwTgGGNn7Nq88qHbkK@ex)L;9T4I8Aeh@f*M{uy!*3-q?Bn{7 zw%3Dw49?`@{a6k0(^>E8m-=yT?wPefh&-*{2Xn^b%<}@mM`S%-gXUd+fanXF+0JUx2wl{vhc*r!XJkLzp28kX6VMWMKj9v3CnjgFR#cvIJRztU^{H zgK2PI2zST=WC^kaS%s`Z2GikwI@}=(kR`|xWEHXs8O(tDBDg~qAWM)X$SPzNGMEYX z#c+o#K$aj&kkt_GkaTVnEP*>@0kQ;Hf~-PT$xL{i0e>`~Llz)QkR`|}B;gdC33v39 z0%QTQ1X+cwl6?!@ft%UGNQ8sA07-j>66DBlP5trsGG}t*i^&(xK1vu5t9Ty5-az&- zbFQ!FVjZbjy-hsH0$OuYTRw0YZ7t3GU>o|;ljMi7;7Q2?eM4AYE_2eH&to5yjN9ll zW%QXaIm2jO$;&;s50seE2dU4Lmk;DbW|j4;uMbVU=1doR1^nrGcKxePvhs!$*5uNz zcQy7_OOZbopARQ#FG2Vv?7r{}%x8;#uJ{tjYtQQr7pv#P@1H2W#Y*uXgxzK>djsY; z^;>q1Ta0<_0qp5hnCmh$-*wpej_kjG?(XoKUkr!xu$?!Pv`m=PdXrc6Guww6{WIV~ z<#-4fvbVEnBjjQnoILP9_ldj==QV%4+xq|JoZP1oj>4XWM=oN~8A#&{vhaxxa!UN>NWbL;Qeh0j+)NVZE#`Moj`4g;Ru#aDg^Fx{^m!a)bd)pLsie;$NrC1vVF)la!WKb+a*iCv~Nc#7orUoFD}Hp=Q;eVWl;me&93!lgJkoqOGH+w85;V=% zHMmc-21w$v@w)#G0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`;1F;K zI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL( zfJ49`;1F;KI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^r zZ4tO~+4A*AQGdxM((_2+kD9|bf&NRjNq%%99Gc5H5iU;u!P!r|uw_)uMi&^%NU-0;j(Tmvwepd*JLq2Il$UpkGTFy^F$L^KalnGFn)G50&#`(j=e%ve z=*1*SPXX8$CaD**2!7e|^kUYK<|w_GqzlsnCok#6gvP&Sy_iDSawK{%i!hTuoT8}f z!Mt_;USGW<72P_2U_=jQ)l*~iV2T)%M6XbQI0W=y28i<^skr`zZFfcwCf96DIyQKC%p8dU$y|lGbRotD(t`=i5@D!=)e@Muty&`nhs3zJDv_q3aeUT9hi$7@{h4x|M@ui zM*5{R(j|#}Bx9l(w@Lryj{4YsO!_Z-5!ZP7FME~Me@X7i9D#Nktb`e59#7|GiN+%6 zYa;*D&q!ZHH6EWz$vhNdoF(3W_@nuq{L*-1bY8B)JYdG94Pj|1>Rhf5NoNA-yd+%- zBo*nZY}R>+aAR~{{s=lRVV~%{RR7y@UYqz458D!tPjOyJ7i1ZEYu0&LgB|5@WG>9n zoB}bfKyTNIXbYmwdw(sd~!q?3fFdWGAObX}Iw&II(Jklt&fFRV$| zrETlu>$()}s0-+&OmtmRIcmr!IQv@!-U&bR*Qo0fYlol(I(ksIN7Hdh;VHhO>9}mv zbygs3sqekUIxS1TY3ry8N$Z_votD8-bXk&KEzyDpx-5%E7Gj;2s|1as%{nY=#?J>t zxM1Kl(P62I@wnTd!&1F{tPaaE`onlSEQOEtX_F31wb63_8~q5x`+vh|-v5boSQZiI zvFNZYk$?30DoOO=Aiy{S9hL=>c+fwL4$CUut9U2>q{EW@livV3EEB(^!;<{%fDTK2 znjIg@X*Qz6@<7$aZ*aaL3cA!_xMnBkQmfm?zD+Y9!X- zkS*(>!}5J76WT!_?+f+GHcwU3VcD;tOslT9a>OljWWAN7E2T(bj- zIb!qHICdXNPbKO3D0t|j=b%mEo#w^y^iZOY`vuJD9dGF!K>~Q_}os z=2l43O-XZ$@sD|<0G*RG_ma-ZQTEVHNpX`u6HkL~%Gs1AodB1rv>xLl>8Zh-|C;EeRA02Zg{Tb> zZlsIxsJJCM665^6nz|U}PpvLSgGEz1gu~0x#i;&|Egy^JM7kK&*Xp_$)k8}u%pETip< z=UR;(=GD;OT7z2|_M}fbaSvb?%UQ05G)O=2>OC?|x_`pO+Lt&(`r;z215$Rqqo-Ii zt;fs9k|)G<#5}?6hBoW1c_?FIpTtvI4$ROtn=un{*dpfQ#J$#l>3C^O$}iHIjK3s*N7AKPn!o#) z&WVp4&%@)!lcZmrk9K$(+F?hJ5JvWj;^|~wC2FTYF2|bO$O}YqHrd}O%EsRZgy2}$ z;k~>|rbp@6H2$P0p9=rb#aJ`4PY9Ad(8+4#C4%;*q>HmQi~K=XDf++;=vgb;_L>Qy zgR+2gX>kI%|M58PR~h$4U7ls+iFA3={vpxjSu=M1R;MR)c@}+&?{|fG-}jV@2@laD)Ho~5Oj8)y%UvIWaA7Xim=HhF*jba_(yFz4T~F3%FJ zEpVQYVEcON@-#X;>30mAxs)L3tfmTCg$(e!LqPj4iPc6bctYqMa3B4#*#5iOeez9@oLmi3U_1<=la%J~+8s(z+5+cAr9qV`WTbyS=D|MwqcEB(M|2~K3G|E> zv33p7zMY;?r)Tta)iX-{oAiuAma!ihrDybVoUb(M8NG2FJ)>LRVtPjVF&2`ZQIfHq zQJOQ0SVNBJ86}(=^^6iuje15CoEr6vCOEx?^o%yHC7hm7^DBb;=MZoRI0PI54grUN zL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`;1F;K zI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL( zfJ49`;1F;KI0PI54grUNL%<>65O4@M1SW;Rm0Pa8^t!7zUUB7_8{T*QI3bMNIQEGZ z!Y8le%bxMAj~CmOy%(>QnM5|&lOKGHbpY&>zAyq2v!pTtBOGKSijN) zkwv=5Z-xG$Xm62&N z9%ATJBtHBAVT~Rm$m-!oIO)Nd2S4n`^>o$Gtd0VGsg0kwpi5hA9?BQ*&wClIFZ>u zHn_zY`)q@8t3a<*r5o76pFlqJESnF)j^Ul^U4PwTSOjLIkB{uguj+wc)R$=^;GU=U zP<*OCCqo;K{K+pPZL~pZPbIiho69rJ{d5a&d_QpR=XePF>eg@O0&qC%FV*v0Nu|Wl zav3V<(4aUAzw)P0_+m$|$56jT#H$}4$Nx_n{AXhS|8D)0o)`63(DgPa;_MuoU&@b! z4lC*twoGS+1#rxg?mRLF-kG64c)J(e2z@bRPM;B~jWI_1ZThC1YH==U%f9|p=r6r5 z%>Twcq5s+IJpKLOiTs{xJ+^dBhukFY9)o$PAJq`ZhN8SxH`VwL7 zPr+CQorOh&A7cH`SppqlY2*XCM*`qhrL>`wBS1d%$Lrzp6b@qSV*fCLm%a&1~ZfbEoi4N2g{0NjqKp!3keA92)jrI7b&Z@H0mI40cL5oF@ z(*7#+3%SYqrT(#Fit-;t{QiInv*@2YT408q->t%xY=Ezn1AIp-bm4VhB5pw*4ffa7 z!&4m>F`rd`ZtF!|1GjiBp|7s{D=wEFl}%j~mkqiO2)iuOLR;{9Aw81qJ)$>-_wF`y zvEk5L2D{E)@#q-4g6Ks*9__DBWS^ecg;9`N5(QNM9@Bm=9``b6N);bMgfRld<9^O66nYk=GN@#!f){dJN&RNGAzs=qeFT*?LA!9$VHHSLmy#ukiduxtk zz0`Y0Y));>pZ6RF*5H>!Vl&+*1EkTEHE?GB&78tMGAmG^|c$G-mo3H`=4nZHA-zhkofuv@NfYx^Y zG{KGR5ZuqgJXP>ue~|}WZNlFSZ5h*HFQF%l?0OjNG}e$h^4kTUf_?S*??*jg{=N-q zf8-gN>D#Z65O4@M1RMem0f&G?z#-re za0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`;1F;KycH18KgBot^D_8;LB_?g-}byd zWutEyDBTGpzKii@uQ=j&{%v0_@-<$kX!BBH#xq6!)oiD@E1ME`O_yHlQ$^m|$wV){ zmwJ@Gm+Gv4FV&{|!;A54#lq!+u*+QPBkX%&W5lQu62GO zrm-XE?~Tn{blm1`=i6mY9lAMc1Da^j2si{B0uBL(z^@+y zBfJlnUiSyr-uS*TEEtC8!McqLPBSmW7*9Q8Y>q1n;=g!c=Yz{8!lAjG6XD|cFOI8f zo-i}b{1@!snLQhb`7fCN^7t?0B>69tcau$TqI0k&_g9tw;%8K5H7WiJ9dlXGy|Yi9 ztGN6R7F9y#RUUcps9YHGz4mNT$2=BvkM`wqVW{Wp_fQiq4B2nvr~Cb-1}+T!gZll| zgg+qR!eHMY#|>N<>bv#$Ukxq{H4dLe!i6y&rvzHZ;lg`vLM;D)=y1>DzrHMlU?iix=}45tO|YMOi5Cf&(#VaV~g zEsny4A*=N=j&Ns8z=gp+XYWR<1}+SJj9eIOlWo^h+w@I2C&7iGVlE6d0T+fo3Ks@j zJemuG{SEQ}tf}wI|5eYALOGK=;{M~fBltzZ6D|v(aEISY0FJ+`n`33Bb*rTiOY70ZJ&-4E_a+5N94pf^Ht=; zSkW0S*fyM#(@?iDH^u_|hWu*tW9UD59r-cjy_4d{Fnd9iSa^j2si{B0uBL(fJ49` z;1F;KI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaAj&B4U|Aphfc;(z2j{l;O zJA$|?b~^qGo^WS4{)^*#4sf}12si{B0uBL(fJ49`;1KxrK;X({%QswV$Q;H{Ul;(4 z(@~(H@JDfG>`lOb!S6ls@riI~F6TtJIR1;HwuS!g=w{vFVI(UK|?VZG`h; z9Bzv|abA3VY`A0MylCLLPz~G`x`Eq*HN4BOHKeyE=C#n5g%#YNSI;)My^5R{s%H|M z7f&GVm&18+pq}Ru4vV94UR1{MKLO{3e8}E?W(}Md@)$WU^mVpf%SUYbljXc%G3SMx zfb&8gh4Vr!YT~>go{NO@;&b)oHsxdQTn0$#7k0;O_6W4`o;<}JcToq0hhUC5(w zUFe(ayxhojAwL>(D4%Hii-?q8-l>EDW<|Ugw>@a|p6eYJ&ql5b9d3z&mz3uL*Py*e zc%2as^l(@JS33Jo+)19LI7@Ab_{oZU^KkEZq2gKG-}Ui?m_OK{Zao$riSU>H6k7Zg z)7@Te@77%H4w?2k`?%K)PIRPA@l_7{Q-TE%SMeC5B3mxXXMlVaz*R!&%NK5re3a3{ zyUF9*6z|15zXW+jT%+>&NAxAoCD->@@xq^T^# zcR^**|9W#IfUEwmF&EIcY@JbE)#ADm9jGh#5h#Ob!xKcD>QCNK&wDf91p|jUVGyLW zzl!FgYpq|J*Iy3bg}SO9zM1dBa9qS|2KL^%zl86Ct+8d3>uei+v+`YhVI>ofPVW(4 z+c+Q|ODR8_RzB~ZB|Oy4iCM)@^c8<>Rh!6m2O^ti!kgJ6{z(srRq%I9gWpr(_f+`h z1?zWZ0Xhg~^@u}lgMuxJ0&2I9=F#rYi1?!`AkT{U6=>i80v!c1pf+#Y{ftEsCr*j! ztOb3rk3YKqdDEZCuF-rF{GAND6Px_afqf_JPi?ZFHl2B2xk%wPLQ7b{LRtj zZOYekjxF8hd^DS1R=(z~LcXpt`O**DeEEy|cyBlJR;8Ffw0AJqyFPwjhWAbJ`@q&5 z>Wude#OCg;IgUA`_m0?{+L}W>@!s9B8S!i<^TSE_!Q5kH-kXFU%<&A&Pbc9AbF0XF zC<#B1+YYnhTcXFver;^OejrEvk!80;+bKVtvHd2M>s=PVKdo|)p$%y0w&3KaJ@F%R z+i4u5a(2tyD!kKp&&jTXdGgidx7a@?R57nb!fDZqHlRNCI`UEIdnUz4F^Y#mTK3W8tBw4zTnQxhPib39Be)uv~d1wLT2aC~`lu z6_4f=E;vK*p+%UJI|XMmM8IZ>pyDatpC-7G9fJE=n5Tl1ZGVvmU2VeOtTO&|*vsA4 zu7|-+r;+Q(Zx?(@waCwZzw)MFuDuOuf8-gN>D#Z65O4@M z1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`Fd6~Jf8qEq9RG#J z_jZ!C>HhFyeDCutp4R!ExM+Ss?3^aEPvdFkx0rg0;L}eM{NgoQ?3%{BW_QPbAsqk3 z=%Ln`90Cpjhk!%CA>a^j2si{B0&ge+b>4?duls{*Z+u@f3x?r&uukLVvzZrSjHjM4 zHpi94%H9iC93Hsq!ijKbF6TtJIR1;{s+uRvOf&xld(qxuO!zNU`sMLo$Vu~G+=TN7 z`m^T{la;S3|HY4~%xY5n7ZQGxyV;*QS8@Fl7F9yr|9<4bqjF)$_u9LK@_8Hnm2hD& z;MM0W`kDHB(8PtozTDvUDso}4 z6%%t|NaD0WTQD3ExDQSD!}CmYKi$F`-w&MoIUd5ky7im6AV9l)te)q|aAD~E9->=n1$m^ijAl*y7P#80xPq*3|FxXY2W4 z@jKc3kK?Z47X^2m7!z<}5T`{vhE0kSgSadb|7hp>V=&|Hu)%za_Va2_SVY?&V*Ozm zvWolY0qzV39V%N*gD0Q^d<5X;Fq{@~xIBf!Jx>Y~Wa|Ed4EQ799~a;KQJfa=KZ?_W z%)1)$(E@WLrv;fCIW5S1dqX+Md|N~KR+v9hH|NQGYu*14nZZdR*zQowiMR&0113() zT(*y-Sro8cljOwMZsYy65kWTA}7Wo7F9FMqj`|CJ>j;sEWNT_dMm-9Q3WqYX+Wm4>r^Jc34BATl(%g?OK*qU zV~~wz!>6*MGhDE3ILF#h=P@_N0?eh2{22OwypH@B^4>}DW0<`g@+)WBvBs+vxu>r; zTtv-08Em@s6RC%cySER1UsT>U0q%uc?cCYa^j2si{B0uBL(fJ49`;1F;KI0PI54grUNL%<>65O4@E$A3}hJD4Wl z8z!6w&3p#!6Y(9~GLXxH51}y}@gj7bEch+!lz8PF6M>kG>N$3tU-G6qX!^ZJnG`8KHaofEUZI{}0>-@;@fi(JQL)+eY zr^->=YqW0;OLZW>H?|JgcgNO&865O4@M1RMemf!79s_g}Z{(yNxA zb9OWDMUoo1CGX=&gdfkkZnwPtdOW@n|Ha>|c*orn;m};piEw${`7f3-_7^|?tKTbL zcJ{K%uUIxgr5ukn@y6sSMfZAeCXixmie%E)=Z)sMFn4K@HTCsJxSol-L0$&_B~y2g z_Lt;d{VLwiCKeM(Z%cFq?!MUjEXV=$CHt(8t54k&%}2fx`(~-q9~|Xw{VGx^5Djq*P~!pWV=A*RDEb$58`bh-n*IHY)L>Muh9J={go!`*&U zR3@3eDe{APq58ayvwCe!qrpUpCAGc90Lxi-Mpl;u5-{Ne;t}pwzHu zU8A4s40~t0hWHADDp#F>d*LUf&DldIXYH{+R*y@k_O|*RCyHwO?+NnXY|gK-X%IgK;WE@V`LKS6 z_1he0v)P|ENq;jY=P%!8^W23*{cS3g|7gv0 z?)cP2%EU$OPXE2N_eGKCwbf;>m~EfK`tmSov(=N(uJvVM6}qeoD=rIt@D-T8l+6S+ z-03W)&^{5L+L(&`Q_Q-pRknaMg3U6EzLhck{5cs?TtfGoGF1k^kpMq_ z#~g%NAJY9qiF=bp#3foHuAaAJW>2aC1DGf7$^N4-bs%)#(!JJT8tkTDVEhHk!Sj%q5oVMbVJjH3W=(4e z{OK+Hq*%_5WhbQiDsY4wyV&A2C+@Sl9sOP18)gG1y%#0lsD>Ire6U&!Xyt~5LL2uc@Slzc3|2H)(Oq^L2b2)yVuS2QjjmdUgQhR)JuYk zEn|PEIdOxaZ!p_tlJZhJD53tyt$=n^#<(IobgMwy73%J=(0zAUP3^JcB-&OU_7rvq zvNW)M#J&>S`?GD^5*=%Vz`8?ptP??J#H+wMSSPaqaHYC3b%Z`k^+ok#>S~-i3NV&e z_dlNlRv7o}JzuI1Gj3ol)7FXphce^`?hY%+`%ngB1!O+0eINIphk$$I7-{E*=W{Bz zC0dHGiJ8XJ6#BbF{nFS`W%q<7+%fmjmnl9U^EJg6z>U@(1(c`S-YcqY=-PEcH>k(SBki8j~XndgYsX^x9b}ad)eqzd<+8ye4+cq`0UepTvp0rJUsU7#5 z`>AYsb^2*zU({RUw9Wkc{K&eF@=92nu_~@ltgg-6ndFoDP;d(B4UgZ^BZiFZ6#?p# z+GqiDashoyufte~wm|DeiuWMZR~N=fJhToZOxgc^vsoXWhk842>)pm*?eNDrjcEe? zoxlxQ?O5FBxkaemVVE!S9fNI{2Ql95yD+4DP@EJ-|J>ex7r7!A zJC!Ko5jk)~?bLYJ=G|X|pm-?0@OJn^zX{b1CZ6!NA`gd^pmDjpZlefqLs;}>^FFMt z`6mM?d%vd-Uue=y()Qcth5FxY`XTG%J9fkW9wjKgkVQNU`uOU*@g88lj{UJ2Edj=D zegO4CYu=$x_lIiPmMH&&{xA>w3g!m(2U{Y2BibS!DkJ^r-MW?540+aR{ONAp%9dje zorU_vLuUUA0&AJ|;SiZ=tqZdmJDIIRnx`t{2APk!0Lb6S^P;xzaHsVE`wcq|QyeC~ z6VS%?W9^>q7Quc2KB%r7Msr+NVVz?5p{CW-@~2^}PpQ^C>;&S-gIhr$ z4iop&x|POE_GK%FUP^g8)~Rg%xr|rbpt5E1TZzL|P{tRTSLs$+Utnwjw?v-WCC9kc zBeOpIRa4!oA7UdIohFZHa~mC&X>-?lt`-S(o}4@8lrn2k?nt zP3I}Rhv-w~!8Ky&SN@a`+;R+K9gRghU{@ZLg62rGenCGW_aMF3OX8;ZCLMQXg1F%x z3~DbxKQuU?@0qrTvQ-`iwi_|eq++bFj-x!}(T?+ID>5E8jh&t|5{}{_Eb@qp@HY9D z*yo|X1MENj6VZP0kbR}S-(%nXorta65=pG*7p(2$r>(-+gtcps?#|XY#<4+`4)$Oz zhQWgJHu9HdtxBX?7YuF`;1JAK%PhTMMISGfWqN_MvXDc)qzAGkNa}maL)*vm4Ax;^ zPOTR{+QzP*FmG3{%66b_?LxbG2IgmAeg^NRy`ZhI68Zze`zN97)P_RLN9jTCV_ik- z)c|{t`RPLjgM!3dNgQHnjJp_rg3lLuu#ffuz=Qf2`UPmpj!-=emsF(*@8l{E9pID@F|onzL668nQ{D=<7D_&30F z7WQC#i`RpdRChL%FcYq6=9|6)j=j~rbw9+rw|aHmPoZa(2rz#aIxY~x>onyQcW6={!WV)(wN%$Jt4xn~7?- z3hjF!s%xbgxBbmBqhGu^s@`m2bo9j7Xtt4`&qhnBI+?E z{XFolER$J(i%wsNx=6y9_J=rYz>VUp0q^j$g7;%jP^PgKdHJwH8v(`@I(xYT?QEyu zMU00fm9x*mrg@Be-RH#(PVjIZ_KB7ZW|ou#toCB|S%3;i|8*OL>ZM{)Yt z-&1>_HIVx1hp?a#rccgKKZo(ho~u#3jpu46{_2NJUTBR)=aW)fv#&AltU|j?4P=KP z{k=tAiOuMIIBSDDq;V%R=C(>~_6smS1$Ri}PUffK9-I9l%wL8(q;V(nGjNa1{%VX< zE0{TxOwDIOb^!~5(^xQlAq%E00W?^<>^n_~G}bI>w4*e*l+xfIT|w`dD>9fXMww~+ zkJn9J!`{{hkE2;z%H82=)|op%V+iJIf7b^4jpNiWC<}5S6VK0+M-#70x{wD8i zH;u`5j*GDfl0EEtto3kifN*|(?>*rV_T9d`$Fy;a;oUSA+4ThKp-}0}1zpUewRIJ1 z(<;se0^+|#+YW%S&Vri^^Ol-!*JwT)#+ivd<2Cyttm7Lc)gzfp*xOgz`ve1T6wOyC zC$G?2NMPLwKY2)+&oEZ{f!t&Ewbi{iw}wBgv$Dm{VtiUIb7ZD5yOx9hfzF&icraAh zyZNg+b9C;3F2)p{FJWG!y&IW*gvS`+Ro0_@;e1QMzB(WU^*?%ijD6&%@-)^vo8S&R za<8N{))1fJ;tZUp(OM8^GXbsTaArAD9x5No(}Fy;>U+Xgc__Rc+-+Yv{0P7On=EtN zROVf<25UPVri=-`RfP_&8x{_kfvdk!R3n_F)d( zH%F!Sp}edrf;8s5G}c&Y^vQHKgE6s>_sB!J`A_Z689S8OLtm#gTN2kk)NdMndLQP^ z{ix@CQkptU;z<0-F0A3v&S)=JQ|ogf(oh&5%3VEz`s@zuNz6GA);M%NNByO|OJ<4~ zYj>no>*^l#A?i=?w|b9EhiTh>D9nkyef(oHI>d=M>y*D^$DW1w&17Nxo5@17#qT12 zSM69M?nk@}ndS@ed&cQ_uEOsh^q%B12}geJ$L}iN!#+OoJNHDHrT4jEr&x&h`*#ec z$$S-lYf;O$MD+fhjPe(v3`v?xkshUc4RBh7HNmG&?Dyn}Yof*Ko^TO507} z$?x|m@9?|m01Fw;D(2z5X(7%n7UF!l@wtl1gS>w?F3&=wzvzQ3q_ZjV-|T+XQ>Br# z*j!s~mSWLokT&bGW7iVohte~7i0fj>YT$?8D(=S~jPkl<(W;TWCi%K5XY=yI#=Lxt zg%tMwfk8pxO`e+k{Xl;*x8x+|QGHU}R34S&zsavD-_O6?O1KaBRXZBSf? zc5%juzi+TGd4vB1dx~pelm8z!`oHAXQRyxWwvRSb{Ug3MU~v}GKMV1l)fC^S8{?z8 zhyOJ(cH^ag#_W22uloDjMx{55a7jBm6YcD*xUJFLL~Sm?cf9^_b=vk1m0J@L-Zb_T z-q#G;we9`Xx6lV{tE${~3vYxB=V7`fjZ2=^YpFi>J>P7ppm; z!uT-#ABz0qFVN5a_H5``)a%7+IF#6%-j!AU49q8YO_$zXS?zxnW_s7twnSfrc?RZ~ zJJC)qzC~v5yf~G<>+Q^&fi>8jD`oaQ*QU}lrnc~z2s0D&*o^+&{I2!8`3z6{UqfH~ z8seFWxT#*I<2?4_YzkZG2g8eDKYd0EpMicnqoal2i8jY(ZHb=EAYR;cp*+k`Hc#)t zdY|$^X9pC|d&bGndz$hy-BbRvYxj!jh<`fbC%vW&?TF%k7UgFCmS~14_i#89ZZq*a z%}o4;c&CqY`tXBukQq3?|0*zh_OE65)s?fvpTeH(lII}mVFuQ#WTx{ldjBfox{Lfl zj<~~~e#=n6nsA?v-{hza)AbJCi0POz0L#WQ+?i5bV?Syz!tXe=b|pM!O+)$^_bDHg zZ_4v~&Y2^gU8zjIzlOY=fahzdlYf}b#GjI!pB6LQwU6IL`E^QfB& z!soYsGV}-V`*uS*N!o;+kFhhrqs=?k)4(x_EAiJDmc~E<3_?6PJQ1F;`Na1tNWa>R z-wlzU>au=8c@}s=JUKiOo+On(t3!}FSFfPA1QN|Oy{2zW{3l; zG}hbrUA?jlzp>-DzY6xL`bC_@wZM+fNnsx1z<})6;yn3m>~m6R-#A~S{7P>3cop=y zWbYuCjNS`XfY}iG1+DXG4~9KRI#2J&8?E&rvm|M+L}f7Pq8=%a)MiXttlylE23V6; zDKAK$&XLWTJ=-1Tkr#S5PaKZIx<7}2L%<>65O4@M1RMem0f)ew4S^f4TYl-554`X4 zBi(-?x1*H_;g9Cb*qcEA>yqWaJ!2vqn#(y6F0cFj7wPW59K9iq@0!vId))f{7kQ!m zRxj~Qzb~gwkAmj=FZ#aG{u2MM^!|&c-{Bbc`ky}f{TKc7(eCzl5jE=mi}{uVdsiin zaPMXB9((UaE;09Bk~=SKy1ny4_hsnLi~JLNzB1W6FZ#cw%$*l~&JpgsbPd+;yr>N$ zcV5Ko6}%YV2N=d#hdJlK@08~L3;Yqrjeh7nr1{&^QFmeX#CKuZN8g2!XIMOvxL($s zgFnZ&^7sze$L~9Ira<3`;N0i9xpTncGADNqH0~cI=T7F#-_^3-#?Jg*z@u6?jNY9kHh;1_#XeQe*Zvy&5oz^y}P{B zzEd41{X6MrrjMnRuYrlVfAASwmv6}ZgOhB%xcdhf2Y*fOAF$uHZIgZjl$Y7}q;2Y< z*YEy;x+hM1688`EveEgZJ~XNO2OpgH{(&5H_YYpL`v;YLSFVzqn;TlPCmioCg8n$} zA>fgClJ)2taTh`TS34$~-%;ppgS(61?jjuNE*m!eb@K# zZ65s|T)}sEdDso%-KXC&JMp_F{l2(Rx6XzAJUqkr-9I?Eg9rGXo7O4x8!CNcR>Pfy zlKEaz+3!$kuNL3ODaH3J1b&kg`n_iF6XMQt4tJJ!;P>YpgEIU0pvr!D5Z{DTTwA|| zZ`WkDAKwZT@eSL7bqmDfFAaFP?Yl#X``rgN%oC4q-s3#(H z74VbCZ>{8~3b#@l<{9KIfTZuoD`bX0`t7_RzZH^w4Q3NYcjodNq*xVxgbr<2o#unVS!f(NHLv9!t%u%>+iG0!CjP3{JQD^#m zJ1&}WiGE{d8^S8S?JWU!bLRs2s$_E7S(??YnR8 zO4#3#^Y}KG;vRymbjmEaBM#T4K^xs+Y8+~s^9_8MQ zSj2*vi!tQ0tvtOT!`F9Zf>dW_)O{L^zGl5U=H3g+8OWD^Pe#85?#Zy5?D*e&PbN7_ zllR4K0^hQmH5lfDJbhn>dCc5bOx|fOjo*EI*OkXO_nP0A`Ci;U*)Y~z2Ms4u<2{+= zo$BA+mvQ%HCVO9oe$R1tW{!_LGwdSU$CGc>X??#C>#Fa*#&>4eX_LP*qg!5uJ2QQw z%XvT6if_c788y?Eo9@djIyJ*_H;8{XTr1d&Ez#oH8Sd_$*n3Cg-F0}a@1C&e_`Q1~ zr`GSDG`AfE{yu6ujdxJ=zuCQL(y#A#cTmh76uPtaX1If*UgJ9`>J7ewLT3iA^bU#y z&scH?g~j{`v+x`BCHRKH-9=&MzRa8TE{gi?iSMGQbKG4NTCcf3hk!%CA>a^j2si{B z0uBL(z?%hu(Yjyj-%Y)K`KRBmB$Aszf>(ilvpJGKe{)(C57>|pb^eGU}u?9CPVNe23M#86)58H8OxPrgwcy$`|n^KwFpF_YQ;1F;KI0PI5 z4grUNL%<>65O4_m`XO-TmTO-T{{_My9ke$A|HaC``{D0RghO*V9skAAtNqR5n$qfJ z@n5jlnE!%Jz<hr6q5llL4aYJ6g>18&9|`{jJ5Kp8<4M)O~&6CMA>kcT^fxWoJF!ha#( zW!on4U#JbEc_m&?{tJC~oc1L6FPP)MFk{P`UH_)zzkvQR(y8QhalU1AaVBG^y>B_k z@I27_%hAQ@_%Ed6zj%}IU&v36&wrsmab*4r2Hp$ezfkv1%zvRbTK)^>_%B|W&REBP z!KLHBIBxaEz7_Z{RL_z1#vY0P!hQ$HnB%+{yZ4@m^MZZi_~pEi-*=oBM&~VYdN>`i zfz?C%%5}s#&WqzmPptkm;k;nyJI)KIZ?(?nLV9ZxeZ+~rRmXWTS|9IQQSYkbys&y# z9p{D9zgpK5d;IBNb(|M(man#4J{Y2yxZG^uh2eUfKDpt1eMQN-Bc;O z`wP*QHQF-Tbg&aTl%KY`ru`l!3ea&``TyB_7dWYkJAbtLboZ%Kr+a!HFax5(%!oLm zBA|&ek4?=0p6+2lAi|p5B+j62NHmJXWLfXcQZs?WJI|GWFY zcXQVQ#qQ>%#(>%E-3Xfh{&ka$8)G)P|4rim`>Q$!dWPWQkrQRloYx`}b(` zL=kocV}sIqJD@-NEZeulr&&HM)BKXG>(t~`ZdB<~0(y(P=86(@NaykGb>3jo>o(|z z)_oZPKhkkM$d+dc7)J^^stf4P>L%uhN~`g!a*Roo9m~H!KS3uT>GCGs>(EbXU=qu} zu(&0f76~x{`q!J52oE~ME6_{sEs<&O;;iejk~;{!>;>q}=4r(%Yn9+l*9tG4b7}sl zWE9UgT_ePF#Dy${%A+r3DoLc*x0-o|GU4Y&SSlef29Y&1pho&crX%ve4b*Bt%Ak)0dd%$S-j~cpB@K31|IoM&#U#pEL69 zGa16og>ELd(9LESx{`g^V=#5lJ6y*Y{uvVt@pCqQHk)&+*qaD7?E68%-2j>Q9_9;w z=hZ&dBjS~d2`;*qJGKIkoberi@ zig(2P47#Jqjc|^6Mt#EeE9GJGJ4D-R53PAY7o+tqt$+_6 z_AlP}qh;~&nD-N^K7gM<9&6dq=&V7APVo5HFY#P4s*@PR|VNCt;mbnmefcXkf$Vs^GD{-{8HQkpY-lt&a#w(EMK@ArKg2dXdQqYTxg>j&Gr z1l`+gz+H-jTi|YxbO+Ly8Qd(Bg(j8W;HdiUE{r1@Q;65SO*+0K%^0LKljiogf8Nq0 zCgDy#mVYrj~7 zoqh-NCDKs*(cvqeEV&PD*y+riG*_qztFx5mTlk(nCF$OTetpqjELh9x>_wB4?vFdS z`O}f#Ut(UIj(O>(&SC#1XV_nf{+*7xk=%w3x8Qc{eF@>(eaKsPB=4vlKf#?}2esq> zvF(_FI?X_tvHT0hI*hZfwYQ$3ckwhYxn zXY9Ub*%i-PtbQa7r=$n6RX5vd^pYMnXjhatH+nW(a@UiQ$WOVi}!%gpYc>7Fq z^nr&y^zfEq?#a=Abl;A*4)>^BiNAC4MvC)8&Ye2SP`(O#gGdiZfIccCeX#axKJUNY zybng@L}e2UIp%T?Mw@T!RRPZ^uP9z^9cc{{fPoK_fyu%gThCbj1)U-6J4>%mwuiS4 z+`H79cN4s&n0FdB><8#0`ZflANa^BV41pK|F$7`=#1M!f5JMn_Kn#Hx0>3*1V)+-b z{EOcmYvL3!1Y!up5QrfVLm-Ag41pK|F$7`=#1M!faHc`vQ>$;jZpG~PUN&R-r*9dn z?i4nbf8>Ys(dXFq?6JL17vFhvub%VVuWtCalfhwhJ5L6eFU*`VYsM8buULNh6_?E@ zTz}cD8*ZFcD=B2f=RZB;jum~keCjxWSa9ntt(_}Zwa$7^>#UjYf6tZgzkGJTk8k0LtY|D|vB!$({_ z0kjFJB;re^w~dS!#aF+zynm7Vq&8@3Z#;{IJesHhXevm)g#OweWslM@N@PRt-bZbn zxMM`PjjLD{e9#(o5U8gFy$O|HO@KF=-q0b>g4~1u{D@28l%D`SrATb|r+{uU&=(mw z7*+LGek2P+Hd9*~g5$9=`dX(8<%0<~|I}bqP0X|&brTsGe*^k#`jX&uAIOzVU?EBWrbnZvm z(f!2dx!m{_6B}I)IzMpiy37UJEljZZ&y1g%VqsNO;8|o3+W1sv7(ZwznQzt@#smFe z6lVBFn=V&({e~R&1PAy*0VCy`(oY8K1 ze%5R7vtHt2^z(Eh`@k*#A^7$|Ctm&>Y|x3<0ggnkZg~PAw<6@F)=0}CH-dvdI?KKT zqg{SJuQ9v-&i+|0fKE7VLGIN z7x=EtkHQv=W2t+H9_p8N>^}kbeU~d={=m8$#-0;hp}z_2&Y7A)uS0G8D7; zIizp!Bb=?A4ZPOZ`xVeB<>!Dt3G`QHEP;lp3VN{uWMk0S(YGeD{9N;GWJKsHaF^sn zfYyuXj^1urEc&N*t~7EKK!c_+4@GS(gSM-vhs+!hpe^Mokf{I~xH4$(IE_c}#dGk* zOX58MUp&!SQJcWe;6hG=>w#{}@QNUwH=B5;LpRcla3gIQG-;qS1CL40Jv+1~hjtrm zeE@Jo7+Y$`RBJe94ULj|z)wQP31I35fIH1kQ!y`*G4mJTPjhf2Z{_@*$I4&Pq5Kv0 zSGNDhlD{Iqej3VO5s7Ry!BTssD4xNXsG<)Bb#F%JnVEZbKYO3M`_I?!m++~_gPU%=U@y?K;fLjO@%9`n^8<`u)w0NfR7 zyPxme4!*~2cAf-`0{BzfBJ5Isxc(CCLVrG48`(aw{FRaW5!$nyjF+tp*cY)cD#8vN z&3Pl-z?<4RKH_(y^&vpt1qt+Lqs2|bW7TE9Biz*2*?E8TIF-3KW}McJMYc99JL1VR zYmJqeGZVaeMpjfPPe-Rm)|1vI?_9J8hBtMIqOs=+5AYxy&0|f@gEm+%!CY9A?;(uG z(X_bie}T*l%)#>k$N6hx`77d;e#oBbP3c#!HgmH*H!#KEp)&03uee$wj)@GoN>WS_@+e*5aI zf+0MmpB~ord4vb7&BS{vWUjC)>^w~KmDx|mGFSW}v*S^3!d#BI+N@3bvxe51L%yNP zuFe(-PUtHWhCL4TU$igf4a$`R;CEy1Fqtdiyh&{ibnB7zj!(q?g78++-ZO-W#5oWA zdmhf8d<>Z@Y~Jdu#D0F-;vV;ct8j+I-W5Et>8gu)Y=Al5HkB?xSQEkZ$j@Q*N+jy1 z4XhO2HkqyrGH2SH9=9|oooUkA`3(BS=}(tn)7Vof$QOcn8vC&CCP8Jvk%V*iy9t}!dM`4-gz&Sb;DJDi_? z`N!t`j52YraL6yy`lS&D8h^q);-#Uy$_`5n;try^qt%>)B+dtwdcbhEaG$N$-0uR9 zWw;-F-LfoFZKj=KlNQyDN{G!cRpBOXXCCc|2Ek)$?n;2~3~(5PUlntlX%~1t)qkwX zQe7!7n22~8Z3$Lsr~4}GtH^+d8Ewrdw1MzwH~hT7`WNBP#Of@~i{0cG`tuzZ_$7)9 zx0knZ`M@-DzUd}+K?Zjw5_{M`VNT#kUWB^<{%-oddM^Aw$DHaU^kYKu0DJB7EScu3 zwR3g%(KH7CkY^QeqdcpCxBswkdvPWp*bCI%QMiRJnJ&Sd?~+2` zZpYt*`w+rY{POU3u;r({Zy@a*3#YwBIG1@Ffx{S&m1KXqvi9_qW1$ZIF*Y~CjLGwz z=P>_R8MD;JS{bvZ-4&}>p7vODKPk0!bB+6itALjzrvf(L0XY+)8-ovbZ3u_`X34Q& zbC|i4Oq|cW^fcyq7cj56gL&gGW}XAwaV~_MP*1sY=o|N~Nhdeboy6HYa-pLZlbCVuE|*R@_>=CE&ZFt=komr~#}YFs2ZWJM-$ z?w7Q$1dkTovsBpqen~#ylMD*ln{(XV(caucIPEj@z_Uu@Tv5T=$Y(DSbT2_NCpBax z(4K$v-Q=m91)_a^8RZqR*P?QRG0p^ft=-2H4;!yJkLs_7_<(iFtZArofVsl1Zx~O} zHyfsT*sk>rvEB^k(|he2PcnF`i&qMMuW(17EodDyVYL1uoaU_JZTMb=y#dY? z9A}Dv?rU+T7+HqSQW;Z_{wtXGpM|0Khbg!(x(;XH>u^47McB>{E4K^&128*jp2yrj z1$&)DBI|Xf*167%tb2j%ai?|lxc~C$F6Y5PmiiZ0^9MzLdK%Y!))NJn?Lu41Xp4T( z=inPHC)z~uP^W>i?SD~`ysnwqk9wP z_nRJl$p7)$hy07W?0o^re)w@e$$-$1_wcPy4up1pJiRxi#G)*vV~a<&liC%@mx${7 zR>-no=h=3%1j~{<3)XJ;K^LPw#CL4!5X!2!xEt`p`@}<7tEjFQPrvGj+>J=a#)^!U ztMPBOay9;(`IPpd{sBShjeLz!@qVJembv(BmZJWoya@&h>*!cGOC~FR$)r!3zFYDAdq?1%d51v16KrST?c!1xlAA*3 zII<)7jx|0$*DHHNgEqv-C&Akd$zmgXk7aH!BNyaMmAN4=!#Rh}OSp@qJ2vUsGhP{Ub95Gx z7mqv(l`&?EI0w@{pUz;AspkarjeRQZ^l9URJxWp2 zuS@UE4DZT@{{`^~#EK<&GN$N#*w@*@)8S=D6iMTbD;iW6wd+ZM2N04 zz}+I8 zC!pU~pmijg_=wJj=!{0t9lZ@SM`hHZn8f`s>|hL9BST{p()QDQL^x;o4?bjZlima6 z_4Yf$&9_qjtGYid`&9T3W{s>Tty8DOe{jdi`48kk%zrSrWF`0rz)vs+jZpOF@J8?- zl!Nw6Idfj7c=0xWEM5ft74RXzNEpId`n?^z2(kWG&>_CGCQJHo1MnAc&>hCS2w6*a z$sRQCZUN@rfZqGUIh6K$ua_4g*8eKgy$ZU`Ku^AV$uzO&<^ELW&S77IzkB!csbbHn zwW-YAfI0ZP`F_xazql4Oywb1E`76VFAV7zRGh=-jd>%vK`zSTwEYk(~1goUuK`)u% zLB==RX=zPLpm)#9!#KYUo45jTh)j zjc&^X%cU_iZ&f!*N0L5h$4jY+#CM_6q^FI-$dA%iZUb+|s+{0Ut^tu_4*XVF)6Wq7 zuk7of51y>t=O=IEV!U#%cNPl)I%@S0E*z!+W>erlQ9(bP^{;q+LO;l|d4x&WCD`Yk zCDT*q?iAvIq}Sz51o&nI_-2TohInW4UGH4J8Tq|a=bO=whI|qs-;Dl_b-&$wGx7v{ zGh#aPCR~ImpRIMBX-T)QJ?SOdlAZ(l{GAsl;b6}l?Xi#Hfk8Vx`PzAA^gDoO=485H z<%1zkoQAwJ>R&_rjCp4aFHjEabiKacug9M2KJdKkfAtafzK{=Q;T$IJkdrr(hb9(54W!Km-9?`AS{yw7Be>3@K z*afG~KcjQ6pMOU7jBMva7@Kbg|4gh4_9$P;H^3hi@s$`J9q6uIgf|D`$9OyVP+0c# zep?K zb;0sOm>W6fMh}K)FNj~=&}cAi^vcqnlkSx`_%pzBaYpl{s1Kc-FGamK=1ZadTKtP4 z5JMn_Kn#Hx0x<+)2*ePGA#kQZAlCmnQWiPsQy@9V8nRKT4@;1l5y{pG{6;Z-${hEM zld&^78OoxPX9`-z^^749Lm-Ag41pK|F$7`=#1M!f5JMn_Kn#I57y`H7JnMDoe?|He z*XRt<|9UbwjBaPF|MkS(ex`&bv>GA*BG&(^+*toBa3a?K>c;wCtxW7#|10?MR)LRb zKqZZg+2^Fs&+TyqbcfJ9U+$M_(gnerTA}m+e0Gg8O}vZ5hbh1}7wdm*5L|uJkM+OC z`d>?sqY>+Wy>?6;yqPy`nUVPi~N#zl>C*( zqw-gDtpC-G^}j-I;aensWh|L1vHsULSC^EL14sJLXnzI0+oaRe%7%kZPUtHQNNxdi zu#sOZa|IkHfJ6D)GHvveCPG+^lDVQ{{jah9*I556kM+NXI$;Nd`|qI+S<(|o`%cm! z%Q0`z_bUh^`91U<>65MhcENoj*_kF?w}G_!vPfUE)sw~86DQF(OL_9MAwS5Ro4Z7; z{}uXRWBsoul*t(De~tCO#xg8o{jZLOE?LNSdK9|7c1mg1Cjh+` z_*h@6sxRXsTtUXoV0)J!oy{AdD@?*IaL=*<_p}AX8{90D1?bw|;HdiUE}1Dnj~Gm< zdz*B8$LbHJG?V7`xPRW#Bqpi9_GA68$LhbFzMJ_B{K2QH1JlS}xP$pJl)bRx7+siF z$13UCjP<|1Wc2ht4vUgD!&2cUkX0)OQE~;(oy2c8ArM0#hCmE~7y>Z_VhF?#cxxbV`)6mrKK_@_o`k{WB*AY@E013a>3{vN zbKbZ8WN<+Eh)iPsml5DNV;!%R|3z)LbcmxH{(AMl(mOlpe^p-}soyoapNMSb+>y09 zU+ulcSo&WjXhx}ikses)9!C#sV!PD?t1t2?pEr{Kh23Fw!7At<>U>qxZQD1a z%%@@MQD%cF7iB|d2oE6Fl=Zv3OZ#Q`$NVoM=6`|i5W>0Bo&QCx9Hoo6dV1+1RxjDP zGSWq?`01&OSRJ&wh*_kIIHZ3v^rq^85xR)YI|Sw@(m`zIFVLpa+{r)K4-LL-E^->Gn(tvVyBYXq&zzfmi zR@OoeAof0>m*GBenP_54pfal*jNMPkcbi?$xQRlkvaEaNeZ2uUF?Vn+JW{-(QoRwz$W=;3}LU zIe0gn&UDoUZTkRoylpC75-dmii6cLU)hm&xpEj^kc-v&UGRT~1b9&s;pme55Yv(h- zU(nN+VC#P9b4~52*Dz0Gz5i~aPjFATn_pq6&2v?{No3v4Li4BLej4tl@on~`;FV$} zj0dFW(B~Qe@41itsxuJtzr_46G5<@%qZ0GKq(vVV4vA=_0wGD!Ap)%?ogU z7vZo?IJuujc$wbtQ8~NF)z$(;)P*fKaKUd zHrqWKkM+66`drzEy&E$Smjn99Uf5HxH~9+o+t0#G!F~J`oJp_4J<4@>7idM;&JQcM z3;qKzJ7Js_iWBp~oKCzj^7lvTIHmn=2ksMIY*GBp)a9yXpSmtrIq411<+^BOJ0Ajm zz8$(;V_uk;7p4~P%$vmcoY7xf%NwC^KCk7Eh{ohh;4O{In{c1~8AtK2PwGv@yf85@ z%+_X^+M3qJ#@y>H7pyWKFdbcry2Yf2Nv%T&B(tQ`NzC4%6*1-U}9bv zHxJyXbV3#zMFa!(CjC-iUEe3U?9rgvNg{?vpP&xz1U6 zajbKe=8*UoLm-Ag41pK|F$7`=#1M!f5JTX#K;ToWZ@%ucD{uVNtl2Y`fBKeVbFg8@ z`bR!UAAOE(w~y_8y7&_R%bX89d&9}#FuI*5gUc6Y&X_ghikVj|zx;~JW)!Z!Y}O4o z&Z^avv*Pogo^i*DzFR(Z96&6%^_JGom8)83y{C27%=f?N%J*MByLI-=Syx8U!>l7G zW37yR`R9N0@iB@z8Ylib1_Fs+;l2fD*aXhBl1Z-4wX}K;(ZOB_^Xo@k+yHTwBH3D! zu@BntV={t={H=Z88!PO1e)=ZMmmx2(wn|z47kO#u|995bQ>{&BYg3P7Y{d#V&oi9C z1?oEZn@3!-DQ+NV_=0G2T9qq6XCs!#4AFt*VbrhJWJ@{C$rwHvIqVlyug?yz&JM!X zPoX~fHlKaa-Z^Q{)}shIpYobpGXdVG0(^THBLDnP!ONm~Cun~Soo`708;n!wx==QB!#$bwY`zPKhAnCH9!)#UahE{pO1LZVK$}T*XP`l=z`xSiEqDqvYZrso zXNj)&K;L6%kQnaTkVZqFvw{6|l)EgEO`%-*IopT&C$_)nPNVR9nlF&sOx`8jxp}Cs zo`!fA0|(Hr3&u&%S}C`L`?s;`M|n{F@@%`$9|gQnwt@^cpY{3ORR4dmZ7!i+W!-A- z0f~;Tim;-?QiDz1pbP`OYI~3H(H3eGg^`*GD z$ITr(kew-9W& z$Cmq~1Ehd&A%_jT=pLwmelPVYuATusA-=r^r28Q3M%0PyCeU?}Jr1kR9CeP}-wjxV%LU1|GLp-)Z!K6!NPsUO-tue`d}&2!+$IK@4s zL}eW48TS@kqnBi_aI0$oGd1k<0CXJv4S0-I;K#b!r}nUfr5PrD;07LSp)2ub%V2m0 zbd@WWD8iIKrv%S{S7@b%Tf?o5yNa^;eFf-983G@~ttL-?uT96lphN&uB>NAM{$87& ze?h|^`H=mG$cOv^|Ke@MX&(0$N26V}SBu zkHHUdig?Se5bT%i^Ld0@UCOVb-vsE?sz_Jr1wLSWSIEY=p}B+Z8yV;($DD6yocx1r z`##WDVtn#y=g2$*R~C-9limKi=E9n=?dLL25gjPsp` z{37l)E1*Rr|H>?xsq~vTE=yW`L_E|PY1D&0-wYnV<$w$P^6=wJ;8wtk*@+BaZE13a zQZC)87GLFcc}Ma9@yf$8#pUvh$p>)BV_cPx2Pe8p(5)jsQwN%Jqw@G>l+&dsEG$cA z6*1xg+pQkop9;3O1aZ(Dy~mmwE^8 zavv8i+ll@t3%C3;-060zGzVQmk?Mpx4`QD2UIv`HRJsB`4*FKz3HsqKq)8yGOQ!iM z?eNDyUktisx*w*wR3LwWF*gYQ5x^KUv+X{B=~5Wx8drc`N;*60$tL<)E?+WpYD8~) z-1wlY8WA5fwCeu=k0r)Tz}C4OFc6Ow-0GKg(MB8k==PQ7J7~XM=%?Vf zDe_+~H14p2C4V5)*40@-?Lj*O{dK?G`BlG2biP@0cUnf z;i2Dx9PsMf>6E-1V=p1Oz6&(QD4P#heJh4`+{wD8Z$UpBv^R(<@)6gguP|3+c){KC zEsRNO%Q%+KqCcqKd%mSb7JarGYtnA43;uSN1P?`ecjH1qIt%iMzagPOCWmo}U*_9N zWH{zvtS2R;=Zo6>LF!wqheY$75A!X-&6|7(%hsIM%L4G0+9R4iDS{>k@cB6G9PE#w zo*3hp7YaygaHt7y8)$O@Z7w{VPML8E^z6<#D?PLn`GB5W7-sA_~1#h3QYkt+1QAPS{|8us_(7#k( zZ60QS5XA-E)u03T!H6Ub;TFE-wITk%JqR2d#9Am&PlkF9a^(N&kk9V1^R5khz^6Td z&`0+hv|sXoEBs-*=b-%x|9jxu4$J|xMxw2>pEo+!z61Zp-xGnl)YO~(q3s`nH?5y# ztfL-i@M)jVyLwz7bo9kl(lKxt#+>Z19OV0g)YSfTg4Hu8QD5m_DX`9@gH>2l<{&Ml zX+nOWf#q0t_3m)(7}oV=;ESGxHJJKw_BEmccc6wc*w1F7y@lx`%|+pv5XCJ~kw0`r`YdQv?q=-U!Q-LM{2 zVHaTMiSGq`2A;%t$6UoR|CJkiQ|gLEX8a1^jzC?DNY6U(_DSsy@s(lUcnrSww`NEe z6}5@>q!ic0VYZ$5{^v6)iFuhF&Xfo)N(+U#A}j-c*!`}J6XCT$nCCFW>9p(ZDUKC_uW&5hSJ6IUWc;{=8Fw*_rdVed43-5?yTZ% zFnnXXkMpFv8{fm^9%}O|a3}T)FF-!B!NPtR{Z+)gQ0`=+(x?0))|(>M7whMV%3|qL zeBgLeVg0Rc(hdvrC?Fl3Et$JIi+zj8UZbUvm#2K7@*t0!~O#ElDgm~K|k{- z>rX%GX`b9saMyWF`zJ_b!Bo?m4iNj~CoISsR{& zoh%pJM??2oa^rmX=oLyNaqdfk7hw+OOTHWH6XrQ;BZmyua-vPpp8I#%Z*#(VtWnXP zM*n{yjeK~Ar2omfr(pj(1^eGAfa_O&wnI#LxnE4dnUiRfrvO*3gLxKnz!dBUuLFF( z0&@uK;}HB0!L$OuhR7g(ud8`4>>=2#uv@WzI|Ta>(zZ&tdym$K{mSlze+XRt@&uOp zA@Z2Kzu-=mH~5n~d)#)cOWVpT#1FqO{U3TPH5sx>CJ$}PwD)eyd=g`j(tHwQYw}}u z9!)$!=U|JAlTjvx*|tm8Q7O0`IFof8YV|e7cL(aTLT~rK_Ua?;^sCgcS?nq1+_T433XC7*&BbPwiN+Q3 zGV5y4sdBnK~1E` zTd8e?Yjl@Fb)@zixWg7Gvx=~M7*?XNDV?};WGQb-!mR*al!p8T;uX*?!Ut*_@t0D& z1okzwUQ!w=^OW7QrHNmr`!&FVyI528k1~Z1ZUpWSzPMsO_5uQJrMw0Fqwm6pqByCM zao|sP+7yrKD_Eaj0lev4!0@}P4{N#8nW-k2$&2bsd7p|~W1m6!7Jy4pJy6Ec@2H-z z39ky6KdBCM&JfS34AL1K^MGSCo{q(_p)qlc>Yc*LJhj)}v80gCJeavSzpg|1DW=`W zQ;Oe-wzzG}M9LLz8fI=o$&K99hbPP@vGKV1Fc+d1P>$R7Nt5^7#eZhvj?UYxbHES6 zIV!IRySCnRUZ=Vf9Oe?AHQaN558v3+akPQ%b6wzoo3LkgI;R)0w{~~7`n1QU?|BH{ zgSPI`pYq+ct^RtF{U)XmUe9s4*XkFsyU-~Pyog?nl5BRAM zV!c9p=fN)H?w0aihwoi5gb%!NqL>HS8FM!)rw1_a!CF@CVkX|>$Tw(e5$l)8QhEy$)s<%$WIMeJwAy`B7d3Ys_cq(fLxI!5k%0T}rI$#2E{1 znJcwONhPSAl(+7-bJ-=h!=rXw@>s#W1almHN3h7F&U6pXHftkqp^7nr}-t*#Ncw7rn#&e_dEIJlf)p#5Un|rs?hB+5~O=Ba#eys@O;ky#nlUk(augU7$bUl5? zzZe4VCJ2z+)7L})GFmR`F|cbt#^<#1Ao`d0?*I80PX>q4?TqPPPOENw&6PQZ{^dOT zetA6lmq_N;SOvZo`WN}R@SS>wwIli${oc_3AFM4ewzge=C5os0WUZ~1K?U2$`apaHrmZ0~XCUv!U+M=&{^=wDRc)>}sPuc3b-+8Cl`VxP2e zSS|g_k1Vdf5%e#*(dI?())BqQYo&kjUMQIN9`6O52mW8YXDxOGSN2RvZyLt`HPFal zJeYTz0Cu_4zHgL?uI5GImWhrA_G_l2`J-_DdBVbh=xEfx+WSiL4*wR@(dfsIrK3?q zTk|H;(Wpmk+uu?;nowpU^=YXW{d+pl(fpge+j>28G1c3gUJYq(=-tD?`v;6j!e9?8 z@U1@@;t$-lbTmX$Fo^deLr1gG&bx+=hJAHxIvU6)KP5UE>@SKT&215T1G7&cI@{6o zHMhMr^fhvCxTc(hzDE6H}ZgmRdjbHzh~Vs-Azn)V`utiDbT={G4QLl)x|^8p=1ir#k#p=^_HLoOVcjv^4ZXR=zqbzpx8FSL_0hlF zTr1UNjCPy>^e-g;Tp<|&r{63c&y<-f%8Ut;+$vHX`<{!1+X zh4|S)`)p*@6dcgO#qwWb`7g2jmstJ_<^&_Fgk+Y)@?T>4FHFbsUmO<8e4FK>w+rC9z8WH#ii-lZ}0 zD8=$$-hFzMV)-wz9wj>Kke;m9qDLu~{}Ri8IVJr{vHX{}Prp(u|0UM1bUgh^vHX|g z>NzEu`?Y$PV)-wz-X#HgjS}R%#Cn&YKZ9tPU}C*XW6OJ)4>}Ig4;1NTisiom7O~!? zSnpD-cj+CecPWxiy#7*gs zIL7+u8q4$a@gx05SN-+=Sto+G4cu8g9GSw~Kz3g^o| z|C^7GQPj~m@zoij)3gHp}W6iS!?-C+{$IQ0LxZ%NVWiDAbn}$&y9=p)OK!s*6B9 zMQRRo(?ibsKR$wQTkk+$;tS|96#w4li{9040ea;{8u1=Gl%Xm&q?4Y2eqzyk*cZ@S zIk-^?^*@kb0=kDcYC$&n3porLnO2|8ARS4tJD?+}((21lSB!>^L(0#4r600GWXjW4 z$4jI?=2IEr^}-0q;1wui@JmWmIL?DhRtf=G?4#3>z9SPxbwD`j{T|$e@6Ad;MJBX^ zLN@WA;M>a{(NPnX!52XnG?~9xou&5iji~2;tjWsFiEJqeowU%!sFtAqJ%{ChJ8N3L}@IK z`?OzL{3kBysNh`-O_~6@rUgtj(Ih}^v7=VWr_N^&*$iOl0VOP3zrpb`$Q`1{_xect`G(2H*WJM zqm2?c_~i*Qb;N)6<)Yfz?oUQuB2#dy=yQ<~u+fLGNuLVEr!a#LVYooJ!8?kJGQ5vK ze~<+3LU$;Y0Uf<5f~SB^Z}OvlP*1GMa^NYxP2Xy?$H>e_y$ZnHDjD^hUmZ@S%Fw|} zy40(iP@f9)6zmaR;&$kRM?QmqfzeTbyvoQcSfw2w`r!k8p3%SMLpOYpfln22edvYf zXdmH>51sIQpv|w~I|04mfU_$fw{48R$oSJmmjmAiHO3L*=P}MI&>I}|0LKLCDNrByd$22= z+OOOu9gmgJX67j9u`R-%AF_EADLvBgE|~#Lj>IdG-)v^)Fb;UJuO_l(q!T_&R=DiJ zM3(X`kh>20Uuit+TTMTb4mA&Yf@RLm^}C^SqU7|6!JT>G?}9quUq9k{FSAssUpb{N zm9GAbrHZ#HC(`fgd4PAPO7Bjv-0uEf!IuDL^~${q^H~P@_%#2e!J~yd3P|7WupHrS z0e(8c>iOO0WuUv=El)fzQ-SS~9+k~3lZWnB@9ut=FJ~FdNv=2ZPM6x4Pb#-W25s>i zRbPQ^biw5TL*O{!qelkttxQ22e3z2=hB3Oe(O#C#dB_uCeFkUE9G%U%dBm@vUX@oL zaVr_5B{^6$#vaC834b$3B2AD~TtT08umCuPuRtI2`GuIfXdQ9wyuc^H-F0h*f1t-L z&uS1H;}i9DsUOM-RnHvEM=+eBT^C~Be#x$-`WMzN`6#=lefn$GKk7T0i@8Rg4IAA+ z!fxH{VqQj{{wdo37j9*(65eFg5ACJ#QXC)FAM=>J%JwxIZ*BP%tOuWTvNUcu@?djp z8wjp>z%38|D6G`41#m&|4B|?w*SUnUG;~D=@GAl~0&ojvW9-6Rp|~^#@iTQw(X^KH7m+?f~U&P6cSir`}O6@|BFQrwZeyb1I2bm)3J2kTUO)}?R4^B{%3 zgkC^3Gm%Z42S3%DQ6vH5%0&enEON7?}cL(~mNu`VMub{p*ZNmxEdINyNnCYR1 z+m!8%nclRoy{3J4*!CU2KKU>|HfDZNTaI5JY0?v%kHSat0@_Nt+~)(X68e-YUDt{N z`c_Dpjb-FP{a!&ob3f}Qpj$DC{v&t> z`ckZ|DoyR>ZGiDqjGIo3n^5nx!9R7sU-Sq^Z}kb!IPfQcJ7DK!XutZyM_My#1>l3V zIFK)8iiG#THQJX%=?D)E{wVY(%ej0q@=3$Sp33O9yCK}mhGT=*FQj=#lxIO#-*>Mz z_{tmM*N$x$?TOl_VRL15V=L0Nc%hS}y8QsAc;_N9X)oqme3#GGJUKb(nRdu+*l(cx zb5OTTA{)S#b#{ESqLw4T#?$FUA3&SzfTH0F61Ft53Tc`X+*Z~VpB3ruI; zgo_~l4RvR1t;?n*-M;pumuMrmHv3$vuNkkv0h$xbn4bf{o&Ay>8J7(82@-7?wb0h9 zyjZ4a4lZfHLO$RVJ_p!;mQcr{#6FbZvtzqiqe%Bip4^CQ;sJgY#4loOd$7wG+j$zF zJ81s1`_??o_x(dYt6QCwzqGJ4I#! zi+M-;H**eP1(*l=u&-XU;RGLQlYC%Jmhjz&ySt_w-;vm79c{bDxr^eJ**4z?JbZ#@ z7v@N3*bjCBZuo6L9{LAI`%uqblkJvmnKJU)gKk{FxCOaa-JEBlL7P3X;C{4*~PZK>Yr@;PIVj-TxcAsODz1#zyX@C^f|Vl zqjAT+XW`BKaJ{DW3~Phm3|KS*zHs|VhBMA~f49R@nF-3h8^*wWC(Z#1`)!m(djvjP zX6{D1Yy-xcpU9@q*~ru9Jjqqn)_ntDMexdwV=3h&vhxr=58*ltr#!jypdSnjAz#d? zz*)B2;sJ#bUdkUOj+s}+!Zls7>Eu>hw#r#J63%2%N3(9TVbjhHXlE8izRI%esm|v< z$drym^ST3uYeT?1JIvpbvq+0qintelFbS!VO#h9Qu>+ z?V}FmWC&Mj;aUWo4GcG{44-Sp z+l6>k&s~T|^(1%(1IvA?FQ@v!4qz9l{;cf&}G(e$}T;guc* zC;6`|I}hOzoCrq#x!4m^A5i)i&<=#J2OJ63>qn>m7t|l&yAW>bj&Sv??MIqt^X)3_ z%~q+xfS1C4n(xMb#?#yVBGzQ3c8sLq)9B z-5AeR^aGuP=EGgZ-k0`pCF&dCZ65ed;=frL%Iy|#JNP!n&4sH z@!F9V=X=WMF61+RiOkR#n2)?X=ZTc}vQAa8&(06zO&WnT?1_S_C&Om_X@HQt#cDI$ltDS7gh`Ig;;Z#`6)(c&=+v_ zT(M!md4cLy#TEefVjZ|!>cHJn2kw?u;BKh{cS{{LcS{`!#XEpcu-%R{-AUQ}^NvDW zb+&>%lJ%3Uu4$pWVBBP}fW4Gi;3|HP8uInT)!F@kXAX1rz2jtRKh7lg!cE`z;+vhn zI=c^fuD61Ygl6!8*y&84R9U5|ThlkvKh`&z{`wL*#XBWEr=1BiOe9P9=*?Qz#-=p{w zD02buO=nkU7vS6EgR~|e z+E1dM_04ase^ll|v@OT9n`_Fs3s7ge<6GdOo%%+fV4nkwB<2g#A86ZXnD0m2HuO;+@O@8-=?){;A|6&`yf2j@M|559vHG6*#@CSHy57z2Bg?rWWs0JS+JOnHZ{?zRpa_cnk5bdi&e-O;>!Q3N%wZ`t`!QSc#w4t8;wSP5Way8EUdc5tU zjnp=SyD~-XUI3g%nW?((T`TGyF1U5KuM!OyW7KasE_ZG-7o z^eN#!^=lpaY{A-AT-oH@sEm{4f6vd?rgGSaqYkM$jJbQm@(6AVlr3`s%G5uyW$qh~ z`qtvn$`EH@8=MK<`$Ko`wlEyF2@l=-Lw9af7!KQnhi>)bHQD|6z9;!LzivmbF9B1U zP8VQ*MtD!{s{_6)x=dyaET^)Q!ZK=G)UJEbF8PdYSJX$U{y2Sf*~mUxu(mG140(@ke;xMmvTW-&7Ce8KGNSsAE@J`8U^{FXHb2Z?s57lm z3+62M@59)*uYcIwMdr|^h0klD_pHh05QpJDli{1jgbh=I{GR~6-~05iTeq%3+=p?N z>pJ8%{Ap(znYL?3J;mmE|}6KrZ(w4&Ap=yr7Gjy9GMm&|MD`T?fYpjZSo|4;6%Aorai3hm44@P25+4%_H+t?%YG?wjNfPHIYw@?>E{tHD^ zZa3ojJGcAY12~`183pBUpfe=aw%ynxZNQz+hE+J9IE;6r&vzq#AGVx;aO6pOZ$Mq? z4Cyy1mz~eDbZ*$&D8&ZYY-;50Iue)878F;uBMj$+y^V9l2H3JKa$hC7(WVV(kI5V7 zA%7ggr$l)z8WFxB3O|=+>CCaWafzU_mpmuR?;2AVc{ajPj=~vuZ{xBf^@-{(&x-Pw zA`7_gZ9KNlY(f-gZWw3mx~lO}ys_)5nxgO}HlH?IN7iWTXzEu3Zv*R(0w(P#vAeBD zYyjN5+dWZj`}mQ*4BBzW+m5%E_6FG3h@h!S3^wIqx4`bk+Z%8OYo$Qj2AdX%0=aR= zY2A5~W&`fCg2jZ#6UA2jIb^q6#(!0gq}`O!Ij?C?X!M;gk#!=ZR$rq1jsk>lrhTR>y2SfLtuy1CbhCji8(l#pPHVpud7>6aS zH+28%t;D!rg?R*HWRT`az@FxZf@;l3oJR!Og}En3bIV%4w*N%Ie-M9o5Hh zMFU(wxfPsOsV*Dpaqj#z-X3A=SGX;I9m>BG=XvBqZ`miTK6bT%jVVY)?G}rU_LeOn^(JQZhoJ45Nml0 z&d(eDS@4FA9+#hcOJTd1Fj?gHWZG2yj5 zcBi}5(QeC)?{k}1tah8zZQ@VsH2+hKM~(faM4SU~Z%HS_)?G4n5cdi#kD?DT7b=8N znk`7P3}u-(up_^Np^ zzg0h%*?PWCEyJD3LCT*@x=*x#?jaez<+tns?DVaEGxBXtqF%^rYn|c;V3r|n^UC+R zrfx_Zxhb#avyQr3koMpt;3VGQzbE?zmA#D0ZXUaAXH?lOfJtp%Y&kzGmH~DxdYivh zZSxP(xwd6>_8{O$Fy4B;Oi>?GxvGKuHDCIRwW$__9c<2t12=YwFCqQbUldaZVMpl> zAZ$V_;JWB=Cd!9wG82&3MA+ZIagiYR#D?cG2i8kLWj&MbOq1V%^)`(BC*aPN{I-7H z;>J?IqZ#j=1V`#;dXu0!HlGbVM7@{YD9u=#09<`0T}dgtc};jsxXV7@={$q@&4_yd zc`Q}i{pMEKXglS#C1Lx7;M&ZF+-3$h`h@y@Db)+#L=$D=hW$rzmm+NxcME7>w*2WH zlkNc0ZH0;YvNj*~Pxj13^?j}I7z?%rPB&UO)xv|?-VAswC3t*qO|}{EAXrG;2NOJq zCZ{}0run3-t7qwYjd$Px|P!{ZqQ0=FlS2@J}kYjQwXB@9%khbL`=W28re+Z?;V5QMcgb`^@`q z0d7h+2)`u?a}mxi=VAZ;{6v;|J}=W#G5srKY;ViRD6GgZTF{sRHp97eDWu_!})KH^?zCo`%^EJss9H5k6^C7 z0dXnqc~^Eh+hLx^ea7>bJI?bHWvco`8E66Q)@v$|#r4F1!hS z4Lg8cBzGg$EONsxo{M^u8#cA2Oy9sYu7-U5GL0eIJ~|&3)i?1TMq$f+I=6W%LI1J} z25|Cj7w%s4!*0-S(b{BaxUiQraj}|W-yI^NwWAB>8p6jE?12E3F=K+fpU~sJvDAW4{z#!fM=q^4_ zes~8UT$xXPSOdIqfDQ8T#$Ag%uooQnG2wNQy-XB=dl8Mt-kn-xAJw7M5hdmGOT`==Pzg@7?1BeHc#(R;82YVjeyI|&p ze!F1T=0|yrnXV>(%6qJQlECrgXWr)~vA(Z$w4219CmI_?+$(axlJgjFh3PB zmKfG{J`Q7u#v<%8jYZge9OA(aU~}YCgdM;x!!AyMyBXoI%dmL^;!i+0>;QHVb`f?N zb{RHrL3jhgVF$2_u#2$Eu*>AX7~zZI4?BQehFydmEQSA4_`?ohmthxS2f#!AQTW3S zV3)~_Hy#@A6`TXPci4Vo-l|}(Dk4sR@yI`cG?*^}*kzhGaDT&bKTkGO3i4RagT(>A;@wPBCkhc~7+yfL-ayfL-S?Q#1iHi$i91Z!JU!7bS{3iH*Ha0{DBpc%2O@-KmHD ze#|X9*jFv?8=57Xuj3Y6XYWh?0LH1~;(WBX;3i>rHI!V1dsOm^;;c(-bW=5P9Gb&G z?nP$a;y-hVCm@Y*hIN$AidP{V#9(eWY`W)3?JKzJ)K~pf=U4s599x$=;Xk+QL0^Cd zBenAZzmUZ}1I~Mou?Kt?d$8RIr@NuY`nUP(I_+C?lrQDEZeW`~H}PqI1HOsY(%D~d z2mW291`?JAGb+3C>Q`KvbECFUUsC*2?-UJ_j&!K4fE$&TPPw;%a{#??_9F~8sM&x1Vx6JT$-3%1k0(a=xLgFOJV z3x@KdvZ)-hDGr5GzUg-5ki9`4$}pUBO!xru#<_4F>;aen{kjXbvle+{EuIH^0A?3V zZ61y+xlX$lquW{lee(JfwD&69e+RRqty|dM4Glvn=`G66SJ(T_I@Cu$;Ln3S0283k zcENVmqduTjn+JOUW)}>d3r!mcKGcQ?KGcQ?KGX)ZKY|a-;*a10IA9l@T~DBj;Lx2UnXo zY`5K?%$LKy6W)IfG_ce_gEnU;s&o8{ArM0#hCmE~7y>Z_VhF?#h#?R|;PipO?Vp_; ziodvWEb$l2%6T{q4?K~M=-gx;Jmz`Ap z#aCka7q1DwM$5lYU$yct&m)g!~H`%Cn%iUgAa6|8C`9uq(%w ze<3fj@-mLzhbaacoVQf|g_>dIU#K%c{)N7Cr2GqY-%7BcFMS0?3-&>3~;eNOaOXMB^v$LBopJtu$=dY z_Lm_O865P)5&cAIt$IsjWSIR!D7!&G zwuJzVQ*bffogs@wT#$7Qjq~}C83kT|LKpZmL;6c`0r&<$r&)0N(*^JzlvAL`NP^~~ z6K~pYlB@>(#n&gRLI073xhmK`J5?TW!b1ffae3Xb{QCjgd^}kVY_gTrpr?eq)vLfm zj`+I8maji$>vJ+$4f2){S3+40GLkt#c=W%rlgeuF*hbfbT$04=kl9cKFB(^UMxK=x zHS$GJmm=2)!#f{%n)GG1ZA3>?Li`fw$BxKOSZaCdi3ek}>;&qQB4AT12cuSYf(nie zAB&%z;2VHui}108a`H*cUm;G?JLhOwF&sQ7DjCYuNZWoQ`m6wNnnlD1?Vrnj-@b9l z|Fq%qI@=!{k2?`Xk?ej8Af&q zpR+9!pnep;R;CI0k^Bq7JCbig{2-=X`mnFhweY3+*}(NXZ>;lGI%5;Xout_ z7XJtjsNdO-5KcDuqzTk=uI*oaot4S33%m+xgiB^&EAY&q;% zizjScnBRv{9`HwhY*c>#5#rHDN97m#YseT0kWT)7!pK>mdaOrzY4Av`htaQu=`o&2 zz5>-}7sBTuY!?g*!_`G$z20D%6%4Xx(o`hGAkfoPjc-VxfLncZ-d+lPWxc2t@%3-`$h)c67U@D zI%MuFJbW|IbX8IW6OH*;#xgB1m&P(J!1I4uFP$!8nHD>TVwo1;GckPqCy<#D%e1g^ z3SyZS$I1waWm?2CE#69*7T%M%zr|f+5qFKTY>P-{LoD0E%J_(7Tg0+0*l8)-g57-_ zc@uAfYzw*mIAy&K*%owR|7OXykavvAyGFK!k(XiQ#6V93?uU(h5y-%+ep~t+@SBL@Ek$@W(K^& zF7Xd1A-4qeraM03xsBZB8*)wZI}@2gJ4@xi8`{q$GCIMs0%29+^Tu}p-*mnwe&nm1 z2FO!qkPTz)JnU1IBSZJK#OFkLk-VGC%8lmUpa-@KQ-pcE4=gevpUIuzMR^=@R<447 zd5kd12aNFP^<&7np)e|s?v2e`2jrE!k#bA)BabSt>>H`Nbua9`?s5{jd*xM$lWJ+}iR6H!~+d8@L+w1IW+e%cWn09dub9Op?Pw za#!+a+q>gI*zZaiEFF-+@;}*o`ye@rGr>E%r@N}Mx@I&QX+|;zSu^5eWCKP5uf_V} zs2MTp?ioo)LegTw*bExA>&cJG%6#&d z)A3g#|7qAOUGEL%itvI?zOz@tOgIb76?N4(bH%@MoVgY(ee#$BA z6nK6o*(rpTHlUH6GATDDJ%O8|X6B~UCSj%sAEk(nizTI_xgGk8vKNjc$HwVdDbsOL z)HO46QR+5^1GF^*SH%pJn0w#IERnJ>G|2pT!2CEzAHT(I6ger&Bw?WZ-ZM~w=E)f- z3I8JDU%XfN7X#R)rOzS*+#I2Ax_#JU8B#s7dMPnRw=7f61Fekzv#CCM@QcV654I~;!G>~W@(Lkbs zL<5Ni5)C98NHp*UH1L@%cf|aQWz+C4mQ5KW*H7sedAtkw7Z(K|>zhdr6Q9%YFQ(SZ z+2>y@osoa>jf8(OeOa8scOw5H{GQ=osDoxb)KvV7;BvEG=WOsV)Dpw9sPiv^=M4WM zxL|Vrg^GC@W?sPO$=)dc;&%4ZK9SS#lXU|>SubZD?4}d0PBA|JK%j;7s#DBIJrHV< z;x7A4v9FA)V*Z7C7w|9C*H7hN_`AmW7s0x-&%aQ+&6+u3%}cR+L)?pjJIuT%?2Pi^ zeUox8)ctTTUTEN6^qv9t;_5fYz3?lib1zicJlDC#y$H@h?uGyKyNr9WeeX%`g>z>E z>!K7|g);1hGJ6-mZ;E^;r_W2bU2)T5~xxfgzmY3t86_u`#kTnKaFZRK1%emdtu z_IHtW;APg)=fjs=d+|z3_5lz!wzPL=&bioOI2W&)cWL-*BTwO6@Oymf zbDnFY|4mpIpKM@VEH}^4$g(i@DC2wW{4UrQ>U`c)ur1UFSsRW`NnX|#vYtM;qJdvf zp{>DPm>2ySY$lm!ux0Oa-r2IYe*_MI&7LT>>=W0-JU5Jtd|KIMxrT6J`zU+3$((l$ zW`}SVY~m62fPMEm?R0bAOhu)i_|&BF)t_bR^sq+{x)42&>&Lf?Jge-DIDlSdAEFw2%@>((61ID_ca0wA zcgVZG+FQ`oUSAKu5E)~iZ_#DQURXuqtP;oD%@hf4duvRQpw8lm>&BTf3#85qvmji2 z`kMFpdiW;xBZ%q|_EB|aLBQI2VHWtT!IwDH&1Q|i|Drh$)|vUPnV2H#RQ>~i|eo%v#~Fe@|?$> ztwMT*sb53dupfl2BOH6-V~BlO6b}8>2ru?!4zfz!E=c{v_FBSA*aCKS6*v*98BWA+ zjV`16O=OtBX0Txjl_ehR%p`xxf!TjSHJ_fBjSLf&JKcXWzJZkcnV2OCwuY1gS%)vh zAm}mWAp9S3x#%0u-$s5&@V|_|JhSja{723%KO}r{JP*UAZ;c<~6IY!dG7~#QU22{; z_*?UQXIc-XEJ{5LE;IUzSRu4m;rSC-Aukwx%YKid@92HTyTQdy-eo`DJht>MHtjZc zREMy2&#|ZOP7aAbe{i2$4faL*Q^`I~Ha1c_xz1~)uDJ~?jWLtsM zY53I9>;>cc%5Dqo#ys|6WlYD?@L^?4$I|fsK4EF74~R`4^-0kta;Ow-oBV#uER7w8 zr9s>(h*=u)+oNCk(ofD3N8@(uHpZ5^8C&XZ7+dOQ?5LYI25EI?WzQwE4n^!N<#&xf zl5tB|8LJXjM)Y1vSQ&e*>!>r$2`j^HO;{OL^B3>dt#eweRgAmbN4vfH3#;|2;3ccM zt;M>RcGdr3!pc}>h4usV8=L8yuDR0BNx5ldf8m6ck+3q}NmfSL;@hRi&pNBw8+A~n z*>~9*OQ~qhvDo!iZ~Abw*Kd)sS`1D^`#;-hvyNKv%|F)T>){^8?WpHt2RFGk`$Eee z(e*IHeDBM5yUjk(W5glza2sTf_t#}(48R3mn-0Lkc zGJ*{gI2KFqkM<^?y*;qncCem~b}Qmpz-7=eM?uEti*OWZms@21LB_(=-n}hBx^-56 z#<$nbRhj->emcBvLfj3Ej5o(oxZT<_s&q%pAMd#1c5CY$i=E?)VRme~-P#x~bp4ml z21jAB)qdOUR(rNnKhzxB4}}YJVU96j_U%2!`R;5=?-}(o#~D}Xcyd!t#sg(fU%6&C z*KC|0he6iej>m2t?+fkqtj|2gTILPye&!f)w6hob?sRCi-x}ZduG_5*LyC9;d-p}# z-1Y1eEaBTFzQ`}g?*54H%KL6T`vK48{q+LztmnP9o;`aFM}fG8*6O*N7RO@-zS_7T zu=j*7=k{C_W;QMe?c)-^9NEpfqso50hqaUXqH;P87p)F>Rqe#v-bA`Szu4N-9N5P= zHWIe|&c#-gHmm8$a*h+T-UjHu2l7-V6SqmV0lMd$&)1@AQOwcc7C!=%gdo z$?l6hy%F7YFrL4MvG(J_M(Nn%9T&Zz_dOT+nGWw2&#%jwIFFZHB@B zwWANwg{eP3y;r93tPcIY(?WH zlQ9+SPX_Scm0e8*vkLsS>BHG2GjHoG^|Qhq$iH@fH2+)VT*l&rL-2da9^jktm8;U} zY54;u!%V{XjUM|8#!APW(?{7^qjq83u%xwy}|6 zAn{GgF=(5>G2k0auFa9g+AqIrHo`hwvQqsgXn?w8I zN%{{4TKEPs-tMgH*Uq~2+WGSIOoIw@e~#Mc-qR9ThdG=!KQkTYAlNiB=ODLUTQYCx zmV8&@a;`60mGIT*{h>E#YhYH)KKPMoud@OB1aM>r&HTU+vXApoj=tD!6#2VhA1t<- zc)xE;hgK8s_j=tZ&!y~OFCu-zaW^x+o)6j6A)rm?-EPAMZW6f zecJhpPPdaj@@D3kI+ann zfAL=7U!>0>`(mVZZ^n1lcmu&LZp6QUg?5sEp&l9MUtp`&$iI;9LTORbLCm{AmN@bu zybEM{5SAtVi9TeBW0V7n9dnJPExsbXA*C|ut{^QO3}I*lq(kD2(jpuUNlTrhA!(^| zG$btz9F3D{DaC0)mN=rcAk*98v>;0yqa1$Icv=Ds2^-TQ@2T?IO=Xd8nNn*QeLG2-lfOg*i3So4BpOIGkZ2&$K%#*}1BnLC9SwZpKP-v)7gtZi zzqoqJ1atkAev!w!fPeA-{K0R2Jd++KKBwVdOs$u*&%d~GM*hV&6aK~YWpN7MiTsP; zF~h&`U!IimoF7lwbKuAZEK;eW{RGGv@s#)V~^7tXpZY0-=o zYsQVW3T^#2Pw?A}9p}T#T+R5gX8c%h+VYn97eUOw2;K$!i*U!O{EOiJasGu`fA;wo z;Z`#aB;5P_vAu5iC+1w{tcPVjo4+xSIe-tcmY6x{3Y-fY=5}QO`3H5kKaRph?EEP> z82(q_V61Q8V04`U2V?!4<6s1LpU%PX?=sJIu5mEbImp2XN8e=}jHmwmBnLyvEjD9r zp?jw#M=s4AW$#Mu91JaCVVsK`4F6jxuc~PST@H`2)rV*1U)=ZjDX3ug>-}p>E)d zke0Gdy}%|@&0^jBmFC$dWhZPfYwBeU#zc04#NjfHDTnGy$?_Z7{gRH%Le=bk@Bz)u^emHU$H{oAMxf7mC zBflZM!05NmZwS73cKHp8wd!>SN4Vmx@f!jd6?J|?`7YWl+9`$Ec*NtuCb;~CP}|uS z%U1MXpIhjL*O+Gx;!;{i>ZhIhmYatGQZ8+BeFwYjkD2-wF&(fS@-H*xFS4D1 zouPh;zsUKft@f`q`5S)9Fd0VIsdN^9Um2bIpEN9n?DZ<$C)cHnyZVT^kNSxzCu&X{ z-!=!R;)~rw7$bSE^ZzIn@e3p!L)`v?*-L}y{d^B>5P8-* z55(hKcpyFuoFVQ%gzm(KZ;1O3u^-V8_ixm32-`x^IZ8OO>yvbj%DzQ}6Mg1OH@lKv zThfQjBg>M0WEC0y%%nH!bI{fa$7F;xXrjZN9O2KWXI2PzW;$j?2-9LZW>h{b}DGBOi*res+NKG4}A3K2=5XhIK3jm@IPN!%e(1_WRK~ z!@|-a$3A(Ho5OWE;^bmde4Zuqj)1XhqzL46@m?den9+bvb^~ zn2=J7$BNcsKV})x<5ACO=Vy!&-8NE6|4fnQG406MQ8!~k-HZu!GbZ##xD~eagVW^g zjuURw4_>D-wb7TN`rzlSdo*EMButBD-C_x&AYob*6Q%_` zkE7W4uUe!s6PX^(j5GRG!}Lg)7Jjz*g&TD9Y#$hH;Yr?i5@9FCgpvQ!5q0ULRh1xj$6>R>ZB?;1}Y@CcYJLMI?MamIdU~J$^1v z*r!t}Gt5z0>*rQ*UR&bl3P|yj>lqnW!fuk^(jMpTWL*ruS0XKrGRM=KRoaTzne1RK z%F}R5R^VQp#80lZ=7iZH!u6>WxfP7h%NotXT0bp*az7b2j^;WTJIZsEIfO687?GtH z3Lk(mrq}Ie(MSE7j$KB9K z-pTablK8%NZJCB!B7SGWEg`OmTe2)3lX@%Ml4TRPCCesoOO{!ua!Zz3XOCNAbTU1+ zgmN(@w`9vS+>$NUsoWA1Pn7rMzu|OjiMb_PCgGNFeZ(yhS?87z$2-C;S!PAtlJ@OZ zd%g;{1UV`6i^7g`OO{RGmYf>T>D-bxt`Ea4IaRl!<2`Sc zTY?RM&3Jpb(C|sZNf;)L%o3T`moRdu|7Ll16X(QHEg-*-8*NiLO*_Q6s@O6}J0^$tSa*q&KlaU1N&X)2K;-Fd+|SjO~hXX z*g^zWWK-7VXRA+q$E}o9+Qj#$s~1Ro$WDpx5m#R*@ga%VKJYD97bHI97Tjn1S)aX0 z@^^>n>XINMe13hIT#vj_uHWbC2WU$t+;4c7O6Pe7JJ{#u;pf;l`)(PT@AaeS6%LDV zR|@ZEj9Q)-`FqJ=>4w2F-_MLKc@Hgxs@fUqb*fJc# z_X=}GctQ2&5__F;@a;tF9VnuJ~7uGgrjDMjvlw+iG3ua&&)JFVaKyYw6=?cn=kHTj(mlOUdX$*9}^8 zPY1?BrR3|w_zf_(HOxGg%q11Xjd?8D2Wre+12FlyaK-qG}43waGat2Dm zzo=Nj|J~{dYaneEt@M#s-R-FdtPJN(M~W6J39K|_Tv^N&bM&qK&z9_onZ;evrU@%? z1^ybYVLwv7;W9^y*7o2rH`DW&`&9a|sQuc3`?bCFEBFr09DKwrdVw_z@9-(UTPwyv@p;k3qPTUujtq1g)8(ut?TuBg?}+X+nGL#42*kPH)WJl@FM<2 zuz#F?LBDQvJN$^Dm>+>Gag1_EIm$M$D^$j?E7CA3Y>5L|;>b%J$TYl)h=~ znYkCi)o+e_;a5)QUZ}Epu5*oh5uAhE3;*eN8TVrQUgi=*%dwf)yR(6HQ3|a>8FoXN zy$j$sNSQttxfj7>r*bcXM^j$yE1H<_O%<;mi4d9ufB%e)?kpXurI{eKdTIDf74F7CtDi~(~hI9YEO_o#Qsr-1~+MY z9XezGf_qq>mLr~bf^i|tg}0M)5j=i6=OUPbbD=ELE}S{%Vn@We2w#oYzQ${YPvKnf zeExqm{`I`Gqda_btc!4k$?IUQk^VQgdf_JX+j6KTuUOUk`Q{T+JRNf)B zg*u=26l{xVy*Xt!pJ9%d_4L6N4g7)%Z4K^u>?Hd$*i16dV9PpEUu3Hu!B)p+e%=;4 z&L-x$VPxdf$}Y<_gcDmo*%M9XylXs{a29Oh5%z$6_d4x#bIzK7yDi9;aj(JRFxR$D zd#zIn^yJrL6A;~-^{|uNJ9@sZhUfdLdA_OBQ;6eJlg3wnmZ{U@N7sv<$MxgeMV?iw z&F%nt_0wChk+?w@nQsc1i>qSSFwF0ecYU=NMoF))2Ur_BrZ(q9mmzy$6?w)gaTL&b zo!^kU)N`69uoC2X?M`$IpQPH;s_mFhV(dM><(3`Oc8MK@9X#yjInS#_Ibm-6_=$zN z;I_BM6bWJ$N4;*GDYHQOIG89q{s&KA^DgVRWj*|4Op$=K^};OhS%WWesGH3i|L{d~ z9;`F-T{AI7)W_p_G4vPp*Xz6q^b&kl&BzotwMUs*t6A;HtYv^M+wKiAm@aQ!uk8% z8sWvh%t2PE+Xbng*j`I`30r6i?F#$0s%97_zcspy?g#Uv!kV%Q>686cgw0^P*c3@T z1ONYx z%SGRK{>qvg(Rn^R;i`Wy{_@Q7O#UNhmmd51EM_qArb}_y04` zcc%4F^dj{zxXkFUN*R#$%D-R&E93>EZ`tor^xeo!kTpViZ0RHB19nu0u&c|lE@>x6 zr1yjS+-d-mK*~He`8GCEJF#mJ-h;3*vTz)PrJ)X)v^R1d6s(;-;Zfl4$Nm!MX)KMH zi6MScF2kRu&Wxo|Gvz1TW9}Wa7(Ggv@knFzoNC`mK7_}!hA=XOQ86P+umZkCc2}|ScV`=O#EDhRA6&x@u4f*ZS zuYBnzzY~r|fp?CKW7X&*iB!s0&26i#RdW{TRqEB;Dl4$>4feVrT%%`bZ(7uT_r5uP z=9z40-^aQ9zK`GPqAlK0;%ea=?!FI%cC*Kt>TQ1Z-se^NzC|k2!gt=i%l+)p1%W;5 z1A%>A(`LQ;6_sw0_19e2tZsGh=U%gTpSHYg7zHga?X_A??6r;({%E+*U4@+Gt+tLX z_uc#X?JwNoVTf+e!e;bY?kS9m(A(mz;&&7e*Iq}TTjG1akL?;zpz@b3SP3B+ghx9 z>BIX!G^~j0_%6IIe8~-97)t-H&KiL?k~vDBYSoo~b`|YrJ>FH@T6Oam@7DFWg+sOZ{kq@1E20SKccLD+>zO`&y9Xb3 z`%8TPv7YWw&pvlVz9n0>c!%gKjW8}XayMfTX=V5Gt$1iQjj$H$Q0GcLg5LXCw>8%J ziIaJm?_#XCYmLr#vF^TWz0S9_>EX5lvIEJwF5;7QN3u?FxNVJ&*6TCYY0eALH6t)+ zWv}3B&wPD|dmMtr+|PLO7~{XfFX``^%RPCfuJe)WqkEgayi$kK``rF;A#3_K&x>=wr9`>OXs5Xz%%TIddF&oHgaLrvF{fQ&4-YcI*$%h^N4N zq#pJ?!Bc>15Kh8Sh!_ZrBL&wP&O#$o!K@n|pPP;t3x}-eJ8Uwxg8fP6dQ!@+rh-`o ze%tinWDg#he|47nS>X@lU%Nk=2QG3h?`z=^{9ZB$7?XSDs&sl<4#CMVYHAiio2A|6 z@IAvM2w#(V6&b5#?ufC^v%w??ZW?D2gr68^5{UcT$s}-^na7&5UKi*`J9BP;YrwbS zoEx=+y^k|zW5g_|?_+Z0V5q$(L%otC@1M>w*oprsECcn*ILmY6)_NgWajW1nFUhzgj>)TBn*UVduZFO%%RSs-A3k-Wn>vyMOKk^2mY=2 zBlE~IvW%=EtK!bLoxK)!WFA>XmXY}lxNpE6nMYQUWn`XmXn!1cWFA?S^QT_QiTy#1 z??Br*VSdBLtiil26DAKM#J-7ZXfN`}sr7M)R9)gcV4^F+C0BacLskM)f=oC zlz-Xe3pARQ8C zlosJ=NLuO~4M|I#qakT&;AosoODRqZvcwUk1)1I!rv+K!80GMr#?umDNZ6Pbc|Voc zZc6(v8Wx8-Wcnoo*bAg%E@!D#WlF7K^vxt`PW}=NBpOIGkZ2&$K%#*}1BnI_4I~;k zcQo+D|FHB^G0Wji@h`Z3`iFU!@GoZ4!^G!I_!rY>`@6|E;a`l88|&rl1Hb8nt5fhA z9tgCsUUe$ucc?{*yXJep7%X%X{>7sEBGXpK>>bdI?@DO1Q0oqc1TpAkRy3(!*T#9iYbl{*P59Czl&3VtVcdHY=db=DM% zp83-?uER~{OcMTuwqy-!9$SWC#XJ&rjY`(fQg>P7ip>M-Vx=BGD7uFA&fIU2y^ss6 z*)B3a?>@+!WWv8l_!sPjBy-c!mL>cP>J4?u#(tnO7;0E3I$B4Y@GlbnMZ&*eV}Q>` zHU>o{0q;j^=@|atQD-%9~CB!aBdVw!oN_NgntopMPyAGHic!@9z_h1T|v%X z8bs~rJ#a=E*&-h2!WQup{)H0GP(kcdmj;<)$;tF%yL||rmlHnhmSIwvbM~$Z_jA5R zYu4U+P0BtZ3^2l07`rILsFL4DSie=~yQe?RKA+@+dtu?VZWavF_tbFJ9xIk2y=p|xfIFNxamtlv`Ol{v4c+S?w*>b@BN-;a+uV2Oc%%2V0!wT(H;jON)M_TwM@_)9~i+Cj1u})-;JVV&2m?N@A{^<8ZEo=9W z%GgcL#GUXjTC6&U1zkk^6c__ma|nlJE_@L3BjO#<9{K;<@Cc?0FAM_V4+zhog>uw* zJVP7Q625NS@PFoY^V?_KSH?4&C13s-)&XnmpQR0)rM~0V*$Uy@DcB0Ey>DbIG;$Rt zG8LNXC#ioj&k!*aCh!tg!AVH?7vr3YMqS=V-X#2sasEd$TtB~R%98LPnrWZbTuOgu(F!7#nqd$3z{k;vVXNxrd35_6uf*Fq&2^zuCPX?#TUv`yxC17VfwDl~9L= zw|XsvQCaE>zndQ~TE;KX;{Ggc{C&^wvzoWJYGGNl^uA=ZKGc)FmuE2i5c2;iU)Q-H zA>+9T|AKxJ^9D6^Bz>+tbwSo%=sfdR2S1#vUGs`7{j`LCp}b*Ow};_VsKs^8MZ&+x zT@YADW*fGI|9-=k2w*`*dY#$i@OT!;~L zAH~HtoI8hi>D+p_gnyCnFI2+6Ncb1lo>8ScV$OBP9b2recPw*`(+}uiZQsUlp&KUr z3pe3kZ1Il6AV~NZfwj8{HU=z|7yLoJfj(ctzrZG|VQxC%U#QGaDHn4X6Mlp-k_-8L zy?WTa@Z)~wTZ}jSslVU-JHF$@{rO;@d*Na~^LMykPh0zG+~nFtSNEnL=6K~K+ro!! zp`!1)TNt-rM3`Gn3zP6K?BHg%#+Z_GCw4@4bD$>&PQwxM;Se@lzTVS_2FS5Nr>TtB5>&cB>V4-=o$@Gqv;%a^aX ze97e>z2c)cU-i)|FE8G5<&sa|x};H4w|(jM%fEWt=Ffd*3hk}>{O1<-+ITNy1mgKnJujSR~i5EuS9VKoZD)p<^STVQ5u3}Uyb7q zkv_2->3_(Cub(UU#_ZQ)OIkGP)bNru>)-X?Ji+fK_T2GRKD^A;aFaFMWQ}b_5pJ@E zo2(nS$!~;z5nR5-8-{}sbd%=VLRW0#iJ3v|t9ZOOVjwZ4xzvkBM999rZjyafC;`Wb$Z-@D)>D9_T)N=umP+VQN3 z_prf=D~@o-7Eid)_5-BzH`sRHpYmi)iygoRSWo(4QCHc2+i=o1Mf-3UWbQ6tk9BNY zWgqs4Q;j|URIKVo{zbSo*2Q2rD}QXS8~%woA7dT$Fmu(SpD~YljSsH0WbcK_;eD=M zQo1sL{DZpNA4lOr;wa-EN&L+@apLZOWs6r{f4f^*`=?fzIxx%bS{+@JZ(&ZHV=T2< z+f{A+TG&UKFv0a{FVAmD3wEPC&*t1PmGuFX8La88Apkf;3Ehl*D9b=ezgzZ={w z`MsI_%Gv*Uwx6*N!E3$CJeSUR)=A!l>U0;#x(Ldma4k-{zk?hM_3T#9PLWqUpX9OF z3`?5HJGTf2VoZ+UWp`{}Q%3f}u%Cvp@gQZWrmfUr?WDe_9O{!bEOiJe?3XHW+XS~RaT2!DJ$;5qGiMRsL1ap`CaOa_Hj==qaE~Yg`*}-vX=faj_TqY zb&dP~&y;WH;ZRh2KzVEqT=6ffn_c7P=-OJ}mFw-h{ig7@TfMOd!?cRy6t^+bC2nJ+ z)qPxB?q6~IwSMayjHmvb`RmYfY;;4KWRI{y_fAWW9QFgb-j&)pi2qt`*;~=cm*E1) zu@xQ0^{!sm?XYawl=tC~`b1m>>RWA)J;_#5#x#1>a5->ykhPxBt=;9P9aZ6(RXV_K zyo|g3l8K`%*K-Z)&2l{d$#4~MTWV|+Y|;0_DX+?P+U4-51N&2+#9Nf}W({AS@Zsm9 ze5_Hg9UGhKZqw!;Vr@<(z4@$hFv66YRh@srb=DRw2Y!O+%!MuCWJA07n#vT}Yl1a- zEy8pu;wItkor`i6>@uqJ7v*Y5=N8JqE|p{72FuwwXxTTb9PO3mT(QHF=PqDlK$~V& zcs?f`%&H-41$0W8kJ>VH;-K#udlNhSt~BwRqr!7LJiqc<9OA=ob5w?fec^a5R)O#} z(j;~bHP!~odd-N7ahNs~_o(gUnmp~PZ_{qDS6ta9PuYLeUQAoY`y~|HfBx+AIPd*@ z&i>d+tGc9B+i+`0t0nm&`_ZWMf#|SR$+8!FR_K`g2wIG+xZFE_w%|$g{;lVuw9j@( ze60^ydD5qH@WsLGyu)t)sRH|YGO8z7!ydN5lg z?rMfQMjSQnXS<#yYq*=bJ;&~r{WL#J`yXVLoOgPbO|^SoM=lfKoDpIDd+zeangX*c{=b7jd7o>|_Z_3Pxh<(ce&a<5t}n|-_OERy%X z{oFz~{7S6zqRBIR)@rE-y1K;D_7AR$^k&b-t&1)KX|ua7K84i~elqPz+Fs-+?^vVH zJ3^bl@9O(QyJ#=Tkoxq`W*b{D3KU!QIM}@P3E6fA|@b9(g|LqZDB^ z$s_1LoK&Zr zhfzJ0`e{?{<((Mnl$Tm0dft=^NK2XaAnF&fr>}pdc{XVmDul04S1WNoh3iwE?V>wr zqtKb?s~qf)o>`G66Lp)F^za@Qov8fj{*$p2M8DFWNO`PqAE{gQGAa2ou^vc11x+TO z{H)0*NmrgaEM<%~#!`QzqBMm6$N2l7GWxfvCpLAW_T(mPxVBlf1FUJj*t0U^lcXc6 zZ`9K$J+!lV^bpkt|MI9l*vt3l@}y6~H`WtzQ`e2>x$OTLJy&?b^)E2`mG&gk>-WsM zLznaZhC1%1efkIE`VaX|kh)T(Epo{dm**&>Uel4u8#-Iz5O|++(sX6C=NN;pZU=rdos*_HI#l0IY}S(fx8tH_Ww z=#t*XG9kJW9q#1tf3Cdj1(fwzU)c$I@@Xgf@UQDhbmX!|>>kMjx&9w`4*Z9>UUWS) z@%o>Ue*8!AkJ65R@Dr1d(ry;If`nNyhc_+jT~myE^vn%(YHp|p=OG!>IB-p1^`t_3 zkmCS{(w?PKaC0`vJG*2l`ojK(-Il-mfTeQyF<#=^p`|>2XOPXF)uXmssmnQ!-|>sb ziq>NKFVa>h#)ssa@n?K1-ZoN7|4ea@F}g#H3w1Ll)XkVsH)BG#F(%Z_m{51am{4~r zu)AqzkXCnA#*#wQ{_yURer{pM2{-C*uTz=Y=u6T49DYl?UnaEqXSNfYjG`xj6cO>AuOj>kdJVb1Vxqhb3Mre$8)wWjM$jex@ zNM%|m-w`vze<@<99F_RLZ{k-lPwqYN9rx(qJ{R7K>&N#A=zGik>P!g3WPm3T=jXlK zuFx%Ri*+yg+LCLr>gjqTyosaO^-KCDK7YcrfZb8gU$`>Dy%2teW7wAFp65E#qRbd$wa3pos~NK#RB8I;)>ul}GIl1qs^0YBNEb!XL2$yY z^4vClk$xEa80+!%a1Y<luQQc!~EM&aS#L;?c9IS2BtY17O4%~_jZo|9- zT;8!c(lA^Ka=GP>-iezRJmMY^$^NHDNT;{FRqrHyM^ZiRJ#D-{Qv2K;@OJKD{LEsE zZ{6M+4`TUpDi@}dr|}zOTv746$ZyF< zO?)fJM+u*gWdZqgkDtpE_UV+$40BZ0`neUH*OvIqUrJchUl3i_+YwLNkvkuV+M1O} zi=)i(^k$W|;JTaPbeH(oV-yJFGqF(CWB#nbm&V7OOqmsUKoLiic=x zL%5JWVUBUWJDbvbM*WPiFgl*3ep0pq{N$S5T(gmTMPZP2x8t!}$NNHiJ$40>h7Ik0 z<`{9bXLeY-xo>;@zISc0HVi4^3GCe$ZFAQ&;wI;}nmW|}e(ELhZ@ksdZTwPCx}CbaAzRA?FKqSN zpVHP3Dce4C0qvB3v7M?e@w4`MUNrY_GbZYH{z+8lL+0o6)Ya(whB>ubns1qP*a9G( zcs^gk$PxTE%d`0=68nKFbG_mB!&%Zcl?fZoIrB{>?V|XLeMEuuiT^M%T!I^RYEC!b zVeEG;ZB{va*meG0U{#r)aMsX%9oX+WH{joc+>8GKY!v>A_ar)uY{$C%Z1sunxRsJh zoA@4e^#X|x*(vco;_3?}J|ywl2fpR%g2ad1g8OVg>tp92wouh2LBD?lrSm+49WY0U-tC)xw~Wm9(w^{FK-a?@1@bO>UgSFL3w>-y7V!>z zWxmS1Qt-1E(obpoFF~%Y*qeU-THNLb*++R7K6zm+yg?Vb<|99WUmJdF;;`$G z=W)J1zGkDYa$mlWVR`VLl{qV9S$N6Ir)t-qoK=#x2Uh zx0$;Zzc2mn?=|y@-zNw_o^l|h@ z*g{tUU1ZR~4O+u>ac;uBPxh_X~Yrp)im3ur$=Sb%m@f;zZBXZAczIXDT`U}{h-K8z>OYDV(j*BIwqd6V= zi@GGw!m&|{U70Q85n`Vv_F<82826X+0%7z9ba8#rs)VmbWwLJL6I}B(W8)Kcy3P~W zzM&g?L(!@ZB1^_br*2y~KwC3#6@9?<+6v>j!)(A@BS&`7v& z4w=`KG9&YoeVmVS^u=zY$j102u1T+Jh+pEKES@Indedi@SxxkxwxvU>iT+c)td<$e zw9%3DGsoRbxz5v8mnqwdeu6!RGA(rjS(Unhv|*c6k$GgoJXvn-`PO1AT;^!e+8#XSW_liTpGrR#<;4!%ukEFO!S`t9;3IC)3#?(jAD-g-)#BUX z5dJcb^wi*fcRT$S$(wq-66f~Pe)rnc?XK7~i5+G7nW9ztMUW|_jD2PO-nG}iX-U1S zKa0d8>EF(`iTp0XcNkgt2|av8zb-Faq3>y3uiq>Divh;{(tgECcZGW5^A>x8?9epN zyaGGGi42T;S~q2sQ}EK;AK;z4-|a(|IP&!GMv>_uzR&5O_906gqa0F>vRy%1uYIH~|U&;-zTJTKEtN|01v*#*r$FnH4w^{snUt3I8JDU!<|qqFyBY ziy&QrRWbI@D#IG!w3F`1)&|40<7gNFLG}>fwQnbW1U(K_CT2MFQW15 zgnz-DXA^aax#NU?k?=1P{sr|RW{*s^Ha<^XN%$AJ3=^An!oN@vZ>BnkZB)X)Ncb1R z3W<3Rku4MUO=9k97WSKUn1!W54twFq&FS^CxnB52y}lM3HAmKF zcJb|xeV+8q?qN;I0PBT>0W*Ltpp$+!8&4REVz8T%(>XTHyk*xf{%?4~Pt` zKw;C&p;FjR%WrIYQ|tvlnD8&GRdW{TRqEB;D%O$SiydGHtLPc@-Ja{Wg27liucM?}ayT-y+s?+o63g>w<+hFbm$mbq%}$xvp8= z>fX=2X8HTvmY4Th*I~2X^3qEKT6nVWt}qXV}*&(!v2x1tP{VkNk#D_ z{0r96U%4rR^=_1}&9Xj>_4U!(`d^kavbJ8<)wjS&Xn{|7U(;ZAH8MIEw~p8iDQ@@0 z=g-9F&&ulRM&wSjRhuG>p!}{ukf6?R!<0JTISO@Uio~3_1OMS;e!AE*wPdzkn_-3+Hn-chTT-|XJc+Qs_^_eFCgExgB9zY^;3 z@K&#dFiNT zKC`ebp1o3KeAWxgHFb_i!oPscdho-!+BL7R?t--*i-f`Y^PDhP9oVZ*TaYc%rs>s*EFsp!|)3qz}sML9XM)!4+#S{>ox*%z=DfkW2p2p2EUZ;7ia?v#mye*tp> z_QVm^ON}7ah4u4ZE$fL!;Cjfnhs!!_zpKutxK@wAsqj1N=PM%C!U$`QB)ki!(Ph21 z|ABg3@E2e))cr^5{t5pAh6UVk)}jf^BF`GM;kH7;zo7n4w&s0Dx|Q{Gt+vy2=4V@a zq;MPh<8$Fq$oZeDZ|9yzO1mQ0&JI|s$=XWcIaGMxI0`O1jDh0atTCgG4DhE{|j&X(yaeqG8=U%wj&-@+k*M|$;Pva)+j73-XrXS{bCE;Hr{ELKt5q%dm z@+#z8N#=PI{sm)D?Tk~k!poS)_!KgaEF;UvDzb{SJMeGCADKs%k!55RSrzxS_%mNp zM&^-KWEq*?fIIUiWn>;%MV66ym?}2&DP?3HS(S766T(%h!OOIr6XrMLLN(YqWy0id zBFs%(!(3V(Sw)tahp`z)D~Ed-!(%*;>urlL$UIW=S@w46Vh_iJe<9-oJ`jg3UJ8bX z886^G8aEi1J*`2uhq=r__$mjKVNRI+kIeOT9z+Qp3tynlw&-n5_!kNPVueol7gVX_ zFVR4vfkXp|1`-V<8b~ydXdux*qJj6c2EKU5k{Exn?DCs$|J-TMYB&$ePIIq2aDDyf z%V~+9j7}VUgqkjik60hdk# zaInx--LQ;naN1`Z+v!mDwcyYB)gZQse#Qx3jo7Qcx`zEmuW>$;)6OOi%|57b;`Q*K z1-iyM@xr=0wPr8WiPy>aYUKAo82QWI>cbE6dsm>fVlR7#{ng=HYll5jC)~pZU#;Z$ z`W8?49`*yI^EX>Pe^-jV${3qvE<0F9`Wct4!qu;(&kp}W?KV0P{i#WW`Gwov3VSKYz65sf z>gbw$3u~)6#!{QLU4^49el4uQL8`0MUY_5QmON#p9B$4H2kdXdIuzM6TE?PffA&1( z#y&L8z3?lN&+x3V!4kVt`;fL&**urdc-D{ED_yg@eNlC~3wTDKGWd;oe&(e6(yQ28 zs>@x#8W)`_T4Ut7&cP&?{6vQEhb6rDMdcy(*Z2>|VaB+J@Wl&0WmoNs?jh`P(WkC) z9d0sy9z4sM>QpqA9_6jr6-$~KYj=w&(F;fLvOBh~DN{`;+kTpKJV<(K+DgTC5MuW> zj1EL<;;N!6+3Ua!i`d;Ra-}@F2Z~l%EpmmC;vOtoHqTd)-%s+p)almvonpUT^lbT0 zn=}c#{xOc~;v031`~T0BZ|9pi@8Jl$GZ@@0EcO@+N&?=Mz?UZ5BuSIX%$KHxgz8q*Ec^P;6 zB@;(kuIC!otmV+j$#4~MTdE@abQ^uC$5LLE>$J<^X-hqt@+97(oHuLcSO|}ui{xXC z`4)$@PJWAN>kqNcssgWK_+UZ1quR1y?mMrsf6?HZ<6gMZ{$)eENE}7D8U1P1BIUM- zTL=@w-nl4OVII6Xe^IW6bZ#NPcPaKr;`h!$%f4CVXp=1GiXE0bV}bR26*+hoCmqbH zAr*UZ)C%a3GA`v&p36bMHP&m%?@ANDIVwD-BlAn_??{~ZZH~%p)JA(PR)O#}(j|K} z*02kced5JWJx*JRd(=j9jjTzRJvL-rdYNDO@Fmw?Oxq>z5zDj-XU@6cxnytaSIxUL z{I!u4cJXL@zVI)Mdp+-D{>)~+$7y|leMgWBcd_rtUh?!Ip8xAsZCjun)+LsCUa2qT zxpDew$NUv0uhm>5{crL<_+;9XdSerZT5g^}^jbh~1>Ea?mBCO`7POrstZ&%k749WW z@;q*3bn|wxE!6qEr@GkR`-7e%j*wm8NVpmS~;E^tfyk^Zo8TT4{2AXSIr@huGp|eS^XK#$?-p-`gN6**Q@O)o2&o^~?3UPdD()jAn zGIe^`H-+?wp2zj$+eMyLQ}zeYtLz0+>%Bo2XeemwibDmd= zawqrOxDEaAF3$U}M*F#zSw|yt$@S~xeHoRXfc#V~md(0RJBy@GWk0vj4L%+BW#hVG z&sr_*j;=1TwEY9KUxz&#w=O~cf8MpbE~az!`Ka%~R((#mIPFOtc#)&dwUG9r`u@;v zTF~S~&w(wFlwX^*B|$Fb<&l1~so&~m!#MC?H0QxOlOB0K>Gu_R|H~ujKjin#iYMLd z{`iT@bL!)9y3uFUU%#&2C#O&FS>=TV?m-+r@1lUi=KU@2b9vv{ya!VkDW~~jRHlDApv;wEczSCfcN$;r%$VUe|hgM~Xg4gR}`!&lQJHT(-2IQis_SjLk`$ zs4gx*=U)hQV?9)tn&%Dv);!;t)d zgUkLLE^C+MUFNdyk$e{%Vl7CH^+!87BE28vJ0PIHEoGiQf(;*FC)atc)HOHdWra&| z{&RLPX42lsqX?Xo*N1-}{$cDdaoXue-8}nOR^@w)GOG@mav*+EF8!aTPHR^tD{EoR zT<7mG_YPW&9;M89q%nF|-Ts=VZU)D$f(?)i-)AqvuG6yMmm(G>F=^d(d;EZavOLx8bi$ zI)~8RPyp+L`wx{)XMXsvnRJd4Zj^A6&QZciIz^xP(#@`<*Ov4l^T;w%(pyD_KQrlV zEEA`&G^nH53&zkQXWB(tN*N1;yPog82wQsU-v&Z58jOW0A2t7v6F!B1oC;j-3 z;vc0Q|KKMkAEn(WbOl*wX^<(FoDBVG`w;yZhwqCr?__hXbb+?A%zIhSQ5mmE*+--g zMA!;#Wtn%h{60c|sLZ>%pZYvTKFD{_0Ow=$eWedqk-VXv7bxFy-}eSfV~3@rzfIeu zf&-Sy(Vvvx9`dE1SgP5xden9+b-B2k_uJyJqP3WJj9*ituROWh4)OWmo!?xu}FTHRS0OEd8oc<0FP8hs?==Bwtm z)d?$uax2_`=bAR_S?%vEL!*Ar)qFFysL*O@V?8+KM8^15S)siuyww#>NelVu(_TdE z5{vce9_zas_$1E|b}BxJtVcikeb$;2_fg^w*ymQ_Za%O#7hGoEO9?B(uvVH6?zNgj zm@RzAHj^KsGuF~u{{J@X_UnunbQiH%8pEGtilE~b%2DI-4Bz@K;p@f?|7Tt|zkT-j zlJACul@aq)?le4=mb+s93Nqra#OKe%=Ph@~{>aEbJ`etJtM?4Q?``@Ex0$`jeE1{M zny#XcF6DkQwnM~5n1(wtk>ilCGN=y;D)9QU2_j8#e;dCqM)_$_^^0%Nz*r;>YAnnK1U&Akh|jC)PogfYgqn|#a4we_%? z^l18TjC)&bifSw74dnWIdL=vq%Lyxk^$LEs@`f4XJ3Jd!+hXMnpr<3VSL*O$743O@ zcy_-IE~&e()^^&D`nvsua}Pf3_LulRk#CfqeeMWtl+Ql(hv=t`Fy=GD8vQc;=YI11 z5b?W6e;)qCS?6EKH>B_{)J1ikMZ(H3%#g{s9zk1OPwTWtIX=?4-mpbxEAJk@osP`j zs2lYi>6-N?BkV}?6s zt+VP}j{aSKI@qi{VRsB?e7m;J&k3hvWENvD|H|AWGW?Yt^;u?bhtB8I)Mu%`X zbhs&+f0K7eu`SGw!GSmJJe{0L*c0K6Q``&oliW-F+}um@OZrKTtPeS#EY4tq@~)55 zFKMqWy+2A*J-xyfdDH2=ZbICz-ACLeZSrm_+vYtd@4GUG?62-zif$J24x?=yd);oX zzxO2h9lN$zdq$P+pgoPw@7Q8(y@M&R*^{^9sZ-bRw`V)`L(K0!#D4W5{Y{@R$2i}e zP3b+Oe&#rg&W+6zG$1fo_&I&G)sJuUy$AX5kH!vUeA8ObJ67s#Iv3; zg7x&1+qtg&^Tai@R?pp3-(%ZX8yPd*6TY0=b5WStxBz`f{BmSB>kjN5nkFy}+KIQl ziF6Uyp60+l#<7vG?RPG-qO@^s{aoT|f8Y4Ia1D;1N10>}{sn(f%e^fle-d_s zF;=+-q_%IW;pmvhI4d@U@C zAIg1kJ2qte#C;xP&{26_b0Q~F!bRu&j?Qm2b*TOQ)Jx*uc&ne=_@$n7J9T$Mww4KA z*y^=ErL7-Qj(o<0MIU05Q(fX`?ejbSxsNWnQ6{Cd}**6zg7Bt@)Fv zEl}&2lg8a){y^+6G=B9tX-DQi4qH(;xvpB^`tOIcq@5~rjs3~Ms-_e+Ai=Bxzis+( zVuK{@lC#v$7D!wEwfm#_-y-L7-7s$Ju<`P-#aKlD{gwGD^Gd9W^9?U zExCnxkVV9KOPy12GK?aOAH8cNjOb0;^ztgk)Y~lW($1E9rL)S>vj$M;w{_%`!l;&-zv-)+vF*bLpxfu5W%YU>F3a0uHic{fEiT&%H< z!tjk!q3pSY4Q{f%3g0RNZN3gaVMpI518pm`xYuxB*|u6&=-c*p^&&lFzt+r6Y5Knv zbX@2vpoD(l7`}#0`1I!H!GY=qK>w>s34?q>~x$t8@0^A)NMSD91OMhWT;ni)W3&^u{qoshI;1#4*Y9RVr#i8NW1%kbXmQE zJ=(sUiR0$z9bY8;O2V%syu{~VTT~A(-{1x6gWZ(EH<*;A9BHim^1D{< z@gSY!8OMn02yq>$-}{>Hos3I=0Xwj}w6#*wMBa#9kSFOs7-;WH+LG~hXI;N`)~(mh zm$ldv*<&1Hmn1epkv$M;k@E`W*-`u4ds+hPFo*aRO3bTlK+o3~txEW6RPImOA8h)X zu|EhqUFV6SC3?3v6s_tYvSjQBa_hO4_}!B4N?eWcNW25=8zf=EADQ+#8!*Skksah6 zOxYVk_HjPS(HFaoBC{nkAC_glC<=${!%gPC`eL_HWMh01*QD1q#4mAA7Ecppyy>&c ztS0(A+tQ)cM4zW#H_CI#OLQrH!*MrLkMgunW$KcGm1NJM4oO`^R;4Z??Ky-)=8-n> zl#zL46&ii(UVPb-R8u=k(5MM9QMiEoYDk|H8dC zb-O!4dn&e;>1T>o=@&t!lrlD${kZ2iYOjCOk~X)_`;fd$bH1H#N%>t`80e9OpU}fs z^y~7%75bjm_4>WSzexKPE8P|9iO*VOU%sJfo_8|##YpSkjPI=R27+7M^!5j^Ief(J zLzX!5>JfJonI3w;7F)GGWQk*xLu}O|od;Zl9a$f;#F1z2U=*1i?;vI4#H$$0*0iw3OnsAWIxk zT9D~&aaxcij!_Q3X*?|fhJ=l2smlDu+D&Qy#p|N_1HH^NU zB+bcRqJcyMi3So4BpOIGkZ2&$K%#*}1LuwgKC|VHn16BgH2jOJr%W){Pw5wVybJgj zsoxY{nn@26pVRO!rq;{Z=U*&cxb%u8CvW)CD?WPjRUf@_T=%|G-}vQsKT*8p$|aw^ zb;%4+lJU!uUrJ5nUj&aC{zZ7gtdE_Ff1y5T*4Ug4{)Hd&Eb9CV{}(a;V%g;U3;#oJ zm49*jTjpN`G5;cX7w|8_9jEdyg8Rq$7i#_4=U;?d%{Y)SEAq$oy5XOgbD6U~V-CjQ zKaR%i4EJK+q#O+YD=-4qH*hezX69f7*S|RqMsWA(91Q<1^IYc|2Sc5M9E@=EUBd%?S4kHeRv9;Lb7P@y@a-3vh9K;_M#<|GB2p>L`gAwje&B(z}-ER*EBZPHPoqxi0 z)-oqN2%7<&y%TJVx08zz96p_k;ZMQE5Sth2Yn(Y3qZDy5LdWDs5c5eIxfsEd=KY&z z-IXu_>`3l=Q%sET)A4;^1Vw$KZ*29#|J1<5h}UC@T~S``k2oXIZ^pjG)!d^{iVKybpzOG z7Sn^-B5Mz-8SF8du(@~}Sqf$u zKM=32zT2!Z_dCq}!_S!X%*1N&KNqJvW;OVA=7f}^|EOkUH8|=4%YjRhdJD`3;nvu& z5UR8NOsE_9BBZ5khxjpHI14-3E6uZs9ZiMsmGn3}AzVKVJApizsM}N63Hj6gCtJ^+ zCx0TQ1m&@UO>Ciw^)YdolzGlPWmW8VoCcOc&=fN@vL>IzJ}Zw6P?_-9{#oje%p6zv ze~iEXDU%;I^+XskwI?@W%eBp_9Vlq~V$aHuPm+%4K5$N=^kCPO$KEhvm-v^X#~^Dj z-=E8qJ_+B*G!Zx9UqtN+evSMF{{o}m0%?nw6yH0${07BZ^*S3TT=CZU4FQabI=`WO zSDD(i8u9SSd>?$uP>ko>~0E*NuC4lVLGruUF|l+yiCOsXk)vqkdw_iJB9~_wTtM<;TBq zLVPi^DZF7qe6hPQM)F)2ZcIg-1xd#c_shZ?7~=4M6{m;#Bzy%)&nW(V_>FP|zcl{A zhvIadZDxfx&a6;BH}`7f83@y&&aCibf61fMm=#BizQj+M74q&b^SiNqoveAG7BRiJBS`R#O`f~qcQE_zx|Gx6~AE)ojje9SpnNZ^8RgOR{VSh zW(DoUw9E>a7Sl2-U|J;13bDHktUyurIaG?eEx)lLPqANw)_yS*2^+8V9O?i%z&#~mUT|+Ei6J3 zNF@1%xY#%j$r3D9R4vKY>DHqq83?mx&CqJwvY8~<19R6TckV1ovawEgOV-0S&k$_v zafZwU2!`C5fr;<$+f}F4-EK=53*uSx;?;C!IGq-vJ7UD_+Zz&p9lA@_JgzTDLp9Vz=>+F5Er?q0nN z_iqk+4ZRPd3uJZjtkngwTI8!2vitleIV(P)^JDfJujQ^>Ck3X}Ns)g)nSZzZzSC)8 z>pVJ7_8oo1oa{er(4S&r=6^D0Nszt8l(JYoUzLQn(#JH@uQkKpeLJt#Ee3roJG*pC z*y4#Uk2dZGH8bX|ek#$;jCock!?jb(c=gUUExH+`oNbvwyHU1{a&2b5>2zAePN&7O zH;47>pXY84cZ24yLRaLs!H(pf66;t&M^diRZ|fa#Q~mc7rr5K_c)TYr2WvQM z-LHy-@wn^l%i5Wok3Ih0H{1J5RoXx`dCuNx^Kr9xpE(;m+7s&mbV|tD#ptn3#^iS`Xz^a;k7qc_6phsg9r z#Fu6IA`<4vR%Zlv;0EDyLmx*xr=e#e&h$)hudt!BW3ZvKOS~C$Xz^3 z3w?x!v?Q|{{+v#WkoyIuaI=v+sw;W#>)B#;1Mi_ekF#F0N6MgZ*!1x&ZE3PDii5>A z|18hJ>*Da><8g5V&x!P#rZJD7*z(Mr_gC3 z3-v!Mofh#&rqQ0H)57Y>ki8P_Dr(k+tF-+A<_V+!J~lpeSa;yo&Xf1;VpqkkI?2xN zwXlw!(idek+NRRrj-%!t;}ja$RVUdEFa{Xr93g2K*pY}E=nFW+$}~)2qx)_ zmbK}rw*XQGvv;&C-;V%&{smbQFc<2ajEfb-_d7M zIaUa(-KtbMo15P(glR!V8n;oo-_3iKcWHle5BWyguJ~V(n-$C_dg5>eexE3)(g06w zeH`A%cm0|e-TvYiI)s;TSH?Gamp&o9i~BIVufp_rcJn;3nX57R{gQhbW1m33%8l3` zpTSMSasj?PQ(qu%cAO_3yT^f^k{@4R$<}H5O17e}WJ#{CWNW6cCF1tu=qrJi)mO44zx(^s=qp(=O<&29Y5Gc*cvJP2 zEb(4HeI*%BKE5#0??TthMd^t7L^5K&C~f+pZIS4?kg^h87#E?>LgG!>mk?bk8-K8~ zbP;Y}oZX_IxwTjS3E@BSgWaVsVm87(gWJVj=+&?~H8MK3>AX^3 z$!q7wOuV&a_S5Ps$@P-N^D@08=?uC{ChIB@-6Y~ip5)KG$Y)P*CLJYKmqdCvJNG4V zD0JIX&!q1fz!W_xK6>(lE7^bK?xE;d+RYdh{L92Uj;@4Y9ew}N5fi){_a4k)+>dfb z;nBqEq_Ahny5sWk&p%>nJ5({Fcf{zqLJxDE(0kD61ws!Ky8h7zjIIbh%x&1W$K@Do z5WxgGeoaymz5M#0OL)xRmhguSI7Z+VB;Mrs1`es>3i9A5hs_G~#Q0lcvm0|oZ*21` z`d38XN`<{6n_tX-lDb!}MEA=1^sZR<^XOdZ{?*X6B6@-*#_Uzh&0hyyE9$y)x>n+A z&*@qb`=6z*71;+}fv&LQn3MIUOwpOboM%F33Vx-3o~$!vMtv#8Y5G#sh4rP>XV8@* zdQqzIxVl4WyQhP^C>S__JnuTcj+FE2L%IIK`cN8Y3s=(Dth_GQeUj_DpRB7y>cTz! z?29Mti}Nh!UF^PqIin7fpSkXnC6jcYG-Ms6obHoY*U{6o`?rv<(M9CHmvuAh)(Xty z(vHzxD`)j~r^Bq_sgkUP`5t~SS71t+itg=hFdPs6@blih9KUfMvdTR4>(AS?)!U4I z{dwrupZEB)R{xG*8_v67mACnl4u-Hlw{1r;c~mXu*L~vjU(~z=J;I`EprJEjSK)wH z;=AcY)oT)a%0&TpB+v5opY#&;3Ch?j^hk-W#2azf=rwHUpeUWJdb^T`OsVG~^LX(g zTNd}?=Z0S73+AJxV-K2Y#GDj;hmSLV^;qv5!+j;s^GDl~DnN$$>a~yCSa2#+Pa2#+Pa2#+P za2#+Pa2$9I91y(^?_2t7*Ztlde{}Oq3NRXOuSRmZUWixtyZaS3zfcy-Z&>u1kX z@P3bq-JHy>(7(wD22~H|ebi;SKkQP@dmP1#--;dY6SQY|Nw1J_@=Gye)ujGn%D3vA zS^q`Sp4rEjP7P05y#i0HV!yxs=CB8Sl!`NaF;5~7_x9L%<0LEpxpR?rVxlvZeK|iV zvi2CS@(R5?ZE>+DQKbU=c0H=U+=H2=k))ofdPyRCbcxshzgQbXXJ#+&#WSpt8SZRw z#!z&IB>#wRUDhs}z%40`=^*}F;YF+py-i->=_+YdMb#s^cMqe}HT6{7A@5jVGe^>D`PklEj$BF137rtd_N^P2UdHvh_z4U+j(GJqoM4FQSou#8h8q{;b zFJdMSs$cT3*DK80;idoJN5}AA690{KxAc1+VbZVXVQ`OyU+CQy-o=;+&qNv;Y01s> z#jNa0tjm_#+jNPuma@+*$t`n+b9t_dy4=M(>%aiAV%KGsbFTBo^>J}3-B^8rJDJNl z*IACcLl2twLeo>=$Gjs7yzBX%r}T|r!U+9F*w+%~oZp3^r`ABf2>nMaJr5lCCk|e& zeRZdK0xbA@uTlDm^=plP$tOLp9lwQw_RwkmL}9JTzUOI=JEu<^&Gd0h&{p$8PglJg z<4kY-6npf^&uBll>UlBwAWJ3H5TQq}t+=x;if7qgYVN@9#+U zQ633bpj{^X9p#CyCbf1vx^>;tpjMKby^X=KwlxW647Cc*{e3|!ZE5q*9`WYmFOq# z9{gqTvS0U@4s4ularxL)iPzhuiv1E_POl$&#m87z2l}A!A;m3}#8^??9 z|0Fy}=%1APISx1uI1V@tI1V@tI1V@tI1aqd92jJ7X!7$lX4xulkh^r|laGMG2ew-B zqLoP%viKl#!pvXFydhTBojY}soZvUOgSUlqV^4g>e#_ifbYfMQE7qAG)|o3-WUk0s zKn*kCyho5CZzBWC8Iqv>oQ)?qjczpVBLt_JI{gpMq(DdQ0PnBcfZ;~C@AY$ELG=A_ zp7jgh#-nRY;+M0i@&wB_n=10Z+y$%>hsJNb1-Fs3wJPc0Zbkj`oK4-5Se;z~_k{I^ z#Om@=oHexJSObtW#!EArqw)@IeNkp|*U+zUKBb~Yz#U}1^yk~6I_GQaJ4w?H);w-R zXVSOP;q$v$+AJTyzw1bl>x)NQ1rJR0{7Am)n8{}|{XF&E;F7XF5NP6OW)OU3b0|82 zDtrr#8m3?n+WbC}g%P*pGugXpn50$li2s1|xNU^3!;1>(->(yY4QXk`F5ayogPHuh zEPT+*-3+1k>HOP}4)Q42X%eTDQ;J?x(Iq5)E4ZgevhN!25@#JVc`&o9{~Pl2b@C(S z$vq48KyH7aD~$gtv#*G~q!lw@?x`hReCv*0UB}M8N0}eVij ze()}|0?x4rZF|;R&CA{iBjsz|?V1ekAIs95+?Sc+CUFFu-F`(pljD4~cfw0KHsYvv z##;4fbNULb(s^Dbef7>>9dFOv)~3&f4fj*5wb-=hd8v2apoLz&^F}?C=U@0f0N=$v zrOrtC55RK?H^HNUjCPm=N=o>100R?Q;qn0ql(!btcS9cx0b#@!{+_pooi%)Qen{cvW#T758- z`|SskJ40FX44UGM<{yxjANkPUj9U!{HAk=yaEDF-kXo2rz1`oKAU2Q7J9z>MFY`Iow#jO2c{W_C4k ze_u{74->Q!wwrc@ncSASsoS$UP{S_1HM2`^$xQi{bk}jKkZvjOpe>I-H*1)|62_74 z%XOW5E0V{$*x_I9lSml(wqdag=$jh-T1$K4@5fHsL;AL?UsLbR;!ZFnZi!d&DetxB z#1Cql!-=}eIY(PpPvmv=P^=T~21;E`a=nhCf2=0-8FMPM2hnp`lXmf3j??|FEWQBD z!63fhtjF)@yu?4l+H!S4Y}CH(QRVK$v|}GU#W+Xb6yP2tn~WOT9_dcbg;U1$4#pQL z>-8DEdjG@p!4EUueA-l?T_fDUY{o6x^(bRmtq67{aa5MZCcQT+yLfdLwkByIpPKwN z>Oit9ucx$0?qg`fSXhz#-j(H7y*n=}cqHw1;O>shkF;OPQ+T5KGC!lVcU??cM@d6v zX<}qNku#um#?Zc5^szRb!zN%&tHPs;%J1vAL2KG?EhO*hW+Uf5ZJDaPAElgYwCi^2 z!05$^-v?bOvx9B@dW`(ku@el=QNmZi8m)E|!8N6QaknWD-t}ka=GEIX9tfQ(catQ2 zLgx&0D&iOEA&74^6*0+!_~Sh4gunLoeqF;~wS_#&I7m7rJ)`)G-?=aIddDt)B)~#sW;{Hh1Q03jGv^V`~5mWX3*$65dRX7gsF7gsU?i~v$W~s z>wKq6rqW2S%)TX^l?|IFXbQb}w-=p3rf8Bqh2PyCEn~fN@aS+T`Z}5=j*Gar+M9&Z zM>qPd{pbxj#S@d3fqZ-!VBFHlpBd379PtPZbcJ{)!9b0;-z3?OyYh79VdPuvZNK`` zP$^0_o0F%8&0x=F!frMRIOVP11s|3>rfs{>IYQqT?uvDrO1hI z-%DF%JiL_0_Qj8PnWQHl4+vj>`7@^ZENxBtY1}6CJLYbejueW`oaf%h-Q(4?6WedY z+zRw+)D@XC1ijCNS@>teOC^57TKi&dzl(8-JgeWx;!U}yp6~?o84vUQqJaIPfO@5+ z?I6R@UdrhHC^qsh)^DYrfuD^r zCH|&w<>Se20eeC%hwh}pw|GI*8n0FE#x(IReHr@N`Y^M8P1?UwgB@{sj5?^XAH{E| zkZbrJMHg?lL3?Apae4IE`*ax4r{-h3q+Qx*jsC&5V{1-rd-YcG(?;HDztR>fjDH%L zr134|VM{WS3vb8#xs%9+RqO|N`WVBxkKvE)=r=1F$48NGN0DC#823hZY|ju0tve!v#WOzhH*E}Wtmj&sjSM}!mb4-Bn?5=^C7ws{E)njLnB0% z>%%l7ag)p`%!q2Llh@jgq*#~v#<%}C@)_%@+({kdvFS>;KuhUL7wIYzCp?qBF0g$a z?UDQi!e88NnnZTEKGSj9zz(tFeuCW1Sg(;^s)Z3VYU^z#56M_5eV6)Dmi{F2Z6B_h zGr6-oQYa13ABYT8LoNuc%<+Jg#ZsO5T~0rDPj{@-Ap4H7m-=*1?<#u1oE~nO-3{7Y z6M4xu{x~X=-%3AmqyKgecaGIQ71haSmUqT5;WM&sUCM|w)@L2?D?FnzCqve)UPija zPqALAz{4u_Lii^#Tpj=MS5(xV&;rS$gioH!zUL&YrC{Gj`1?dI`J9S6gs+lM`cH{d z_p(OxL(lSJd2dCliFf)$+=3MUG5sn!fCr%w#LPiuJix9Fe}g2uCz;7wS>3nkXvkTt zCp6?NNt^n7Uf<}C1Jb9tzm&d|#}99Ds5Vh| zUI+etVH*EV=KMo$dbKhNW*=a#e6EZJW+|DYS{5D z`N`Z>c5mC3CF^4|gi9XF!cF!+hd3sewfcBo*3ch>##3`Bf7VPoiuBe02A)d1)Povr zO;acIP5oX4{#W8#Y@JBHdah2SUunEgtrO|IyiR;Mt0QSwAsUl-Sg(>cknxT_FJ|o9 zgdgHD)O)GJW5_Jrk)4of#jQ>m&otK==%$ZL9x!9nwQ=hFIAhUD>e6V3(xc2-U==mv|=ZEsSfTT6G=^aDHTZNy!$KodOukTB(Oe*E~B>iAZyv4NC ztKO5H@6fIEAy1wK|n~pD5y^b$csW+-MZ7Q^`-F25fIIB=>efui!ROdzHD;w+E ze?9WrFM;NQRr&z&r1xj#aDcip#Ck>RE&XOKZDNS@4?)}VLF`{hOiKR5JjD1Zep7Uc z4e@@;hD*%p&bj1qn6>THJN@#@UI%)^){@6oc+wHDZr7yzR@PQpXKm0MZct%c@u+Sq z_Um@*MqRo(3c8j?UI$M*&uPl0jkc^|_tAi`{ARDtT|)1pgn8!~HkMrM8&&7vkdn`APXSbLN&8RB;{SzW6(U zDdFrpJZY0WG8bOQ(@qM`lDhl%`tlChvtetGZ|DYWe{ab++kfk~{Lk$XyemoFRsS)ogN^)1TOCINIw9>fNxZf6MWfdy6Z7bXd?@*q ze2MHkxRf~^GW_5cRT`8&VW|qM01Mhb@*RH9u@Q4b@Ua|r;fgJ|3o?(X*+Lv2(uSj4gN@9KG;pV;E$x!@`rh+q}8VL z=4t87`Q8Zss{HMoIqfNT!X@qI*Ry=e{M_c_5B8nQ2V=K^&p{XR5Nmj~E$A~NZ7cIU z3yz-Hi@V5vwJqo@dxg6y2|vVL{JokVkrNE=gUDU4=BH5)q}`vUezeS1wCSYWvT45A z|I+SK3-#tS>s77aSH)9Jg;Fb+E78ul-1g2`OZiG$mcFTlHoT@(D4x&n8gxJlPo-~a z>!#0{A8Go&@RUltQ^bEN&SX%rkC6jT;dhoDlaxAjttz+9@3Z~QkkqZ5j@9Q4E%}~q zFL`Ul?F6(>s1d6}^eNi>Q}hKV;ES{&-sQU_GDJI%l?~`Sn#ou5ChTad<4>oib}SCl zzw@IO%3^%J(vsG3`mZ7QVtGP5H1*HY|HWnT&RB>{r)j{^ul_98o5| zQTV5eJ*-VrPu1p7!mcY8iZY&@uT7ib=fcVTjBVF9F`p8eJBOf?+H?$Vh;5rcK|i^d zNBYaXv?bP^vcBM@{!*h4Z^$xzigs~-+;oCI*xawIoHD>Vy3iCkMf%DOw5?8L%LBK> z;jEJKpDx9|)E#M`l6LXaj(Z2s#~E*CQ+CfF=ZS8yjrS;hW>*~EM7W#&%aD=rW!CJt zJZm;4bR_)Q55?ifaGy2&oly2Zt$XfvX4X)6wloy3V_wn7r;MXA_MN3}o)!6oIxKYV zBkoS(?xc=%Qb*EDvoiPs^Pf4KeO})GyeUh$F=h$x73C)7n6&2K)Ys(&+}rbS`rqm0 zn#|7Y0leP`?_|&8Y0~mE@owDE)3lMiwV^AgjdEUBF0fXRyOUOllK#xry*AdG+ZZ#~ zE$=C|)9>54@i*ge3|eE!&Bjo-C(8W+b#8olOJZaUl=@35vwY;`KgK-5p4aI5c2-{| zg|lmqj8o<FyTDJx^ho3DW40|(Txld-)tt*Ka!^(UP$_F zTAqD2Ok~eg(wn!JMmZiN->j*WPT_aY78Qobp)xL=px#N{8mHb4$vgRzdefK(wIYAF zmNu1GX^GbIZufWppr`3iW+&y@=xAOmPkFPx5A$QRwWn{2!_FVX#i2h;*aO}cJ+rY; zeER!*zeR;IXL)90Pw{E$@F`^8*7&e_rl}t~DRff*J|0`Xl;1N83dJA8C z8?H;j4(z189^m^l_NOpA=BEBx@q>Ag=Zx56N}7cCPm}&^jU-!#k+nU|dalgr*=L;S zf6m*75$8l7MqPMKvI%?lB16q27hX_4X==4R71=80ypiNx>Y>ar8ud`-4q=?hbO)x( zoyoIdv~z)((x)Puv3F(V(uh7)!e6LAojhj`=qE>+O9>C_(|L&7DePvF?aT~3T$RkT z{YoZVof``pe7T_9_s&=6?JD(c=I$4euV2dKYvHfl?GpZq+%NoXPguia@2SCOsjsib zYvg{v8Cmq?*+lO>%_0XBZf990qK5db{LgbFU+@A=o z+^*Cf=1P3~;bXDoQ^Xw>k#*u{%C--TSdW%(>7%6WslUqXCC%eL>(Rs|Je0LSIpZaB zgrJxG`d)T;L~cR;i+00JiCgfKgT&K(Uwe;f2^x$(& zPiQGGqnUgr5C6zHn(?1!b}8m$n(3eB@&DO5zsbML!{avDukdNlXZKFDU2$_i#{tIy z#{tIy#{tKIf0`UP!~V2ZyU^8qJ?k;o2l^@%T>M5AXtmSRi<-R6-AzGZUQW&-qsKiA)!Bxo31H88rmjZi5N-Plh3_2;eFY=8j8kEol zn!F@>xnni>mBzh=Sea$h?l+{*+qr^L$t&(RG}Zy)A7pZ3aNs-EZ}K0v*>gb^_QQj- z-wwyQlOCpjZe;Ena7VndRO#AMPxmoT>KloRgF94dEIAyGrGIDdsR!Is4_FVYvzEOe z*LA=edUhrh`LI1|-}3Q(uLcjKe!OrCd%%Lf z!TSJ@CLMCdpwhic>k{X(NXH=OGY2I-xK~I+2%pA}b%o=c>j~M*57u)|Weex9*K2R3 z@Q^1^H=AsIW<<)jJT7aKewBC=&XFZL@HuBdxcW}s2{#UX;lJs=!QNk}?Ib+$i67G& zYbiT(_QTe%(5dXoXxOr%PTz7*zxTqbelL(S2CP%nSW{E1KLmz#$-C3mcnLhjuGUZd z5-0X`&bQTgPamb?^Q{*W)<_+@oF@1|^E+22{$=p)a^k)m^9sx>Fa@K0F6K8_Pt(a3 zW7AEU)wsuEXupH3*NQ1+G~3VCMa>1=ZMi*6JM^O9$BLJWGwmUbrRJZxQzKWNVc1xpB5T(2waCDu9P z6wYn(0@{(32|Fr56}lQ8>LPrHpBH+UJ+Q8($eYL0%`=~86dHZ(%jm_CSNI8NUJQ*( zc;@h2%CiT0V{*O_dUEzx%Fe)tLC#lQDDH;8=`;r>rP0!xyUgoLzY_*mQP+x(m13!* z3nOnP{)_)l5x4L#V4d?P;o14p(@2BFKSnubeF^K4)O}e8AE#UlFgoZhYTdEH?lVdsCRpPYbQen;HO$IR^cSa`yT%OYtL5B= z)cx`z^pNlrd0Kgzcr<<6s5)#0Nk_bdv4g(n1a?v0-&Ofe7iad6Y;| zUYPk?xSO@-_&ebV@;d-66Rn|q3woe831w{~Wo;v3y-NB*2_Kc_2Sdb?7^D45)C#wXQpX)n_D#80D+OsW5z zBbllGPj7S6>;3fl-bkyIe`Bngsb0w)5$Piu?LhKBwf=J#f%G@}iALTUX`dYLa&zxt%#gO9wyhbpqO%Qhp~kEQJYVjh#6DchACgxjgFA1d{w*?lXjdWaU?p|X%21eg{ZZ--vezE=*rZ*^*e~~HT4)a}Z`L+W*XKKVg^yp>`2uJJ8( zsD`{!lYX0aJqj(MBmMZo6(VD*(g1#{`MtM5{E!}L{{ihkplwKc3+NNFa$3hbbP#_A zx#G@HWL-JesD5vIG;kGt#v2Lq#>jiJJMo{q{%|P$zv#*uC4N~KZ}AU@vPL?1tf!x6_nM^~0%I zN&Xh@zTXJe*B;(wfBMAtdhHoA;ept#B>!VKZZ=QCkCx+`LRs?+SwkHs?bT`l(TMf& z-M5&K`XGLzWLVZrkv$J^1|s!BD;OnImuVV@^`w zd}@3{cK5`F<8Fi|tc-g#p-q{IdEU4`n@o+nJCA!qV&j%{DefZIp%eTI%KTWD4#v8| zm0gLql6oMtEBCC^gP48bFd6dG2M?tVEZogmHuj1nxedOv4r})VWxgYBq0Dngb8SbD z8KW-MgkHMX7}6on8OYKN1c)&`wH*GL`tH-l_a7 zT?H9WXlC@E3oU*26)S`d(m%Cvv(Z!vsJFqB?++zxK;5lTZw+NFa(7=*`Gd$&Qg-q# z=5Jz-v7aUH@6PSS&3KvJZ%wl6%k6%9lHDM7gI{gT(NcI7t2%8y$j3)}&s@FP1e`CE zJCyYVxkC+m0q58z+X;_FR+axJD1*I^Z88g~)3?q^%Cgse8TtH8`rb=0MHZgJBeJmE zbrD&3x@;IG>|GH41no@L&cBwMU&_rd=jLDK=2vp_>$&;W-27|IQ$O^Z?LGy(JHZn* zZPqf*MaXDhgLfA*hFuOHS{Je(nH)Bk@cmxC=V1O@%u6w4tP}s@SI)|bA8{AAR`R>{ z(+a*EkTd6=rhUqJiGVg4&?W=gByy`4&@QFEip(;3ZYTZV+P_Rqo%+W;fG{{tze?HH zW$wovh2VQhxdPuC{GDp2RKUH3;Fz-W4dMTJ(~&-E)3K2H-@1XbCGb9&kBmhdt6*w% z(5sS%#$4|~{PlfW75CsT#9hYS$?;46wB&PA9*35uMzDic;y*}mm%0lLxkn`BAm^V} zzm$|#CT+Mjx2` zcVsa5y%*XM{EnnAlC;OK9A7o#s*H7Y;+Sc?lm4%dGOEs_Pozu+7|%xe9>8A8M8>(S zY+|*jV~uxY&Rl()`cAl*`o8EZRqx2C(l37NlzEYMb%b?`^r~&qV!|$tQ*SG@zBT8g zdT~dK_Ym|iqHW#I*}HcYQ*iVi_QYHSFFvugP+UZq+a#_9+oDB<#Je4O4>4B6+z)t| zy8AG9>xACI6%U#t)TJX^5NZwy$KKtUei+dj+{t@DQz>67=7xz5i{Y`p{IRgK#M0UT@6!fC^ zH_rRT%BC+RecX+joIY7AX{7Ns(kSwVr15Xy{o?en`I|X$>2DUM{zH7rd)mA$dWi4a z$-_enQh%njW_c?XZ^wOVy5Z55!x`T;9rhM)KJ5Kh@_uD9GBw?ON%%1I)t9$N?}NsX zIjVF-(!~2>=EhR5ZX?|?UP)RP^*10OC@wrcY(6ny^d~+X=_^Cp%lmhPi+*Fsd}7X}+J=osCc?^^oTU>#WTali`MDaQ zC$y&Xw^45<*NGPi_hMD)#nj71z3`PhFNzO)i+Xqx+FWxB<2`9A7fbSpUXn$^!$q&G zXN|I3JgMx2{zb`V^Wx@XTEe{uUsCjuSl&12@BWOXFXy2o4nv`9EVClRnGQRD9Z?qa*vdX?9AC^dbY!I!<7+Pw+q=2c1d zQ2WrEByw9FJHtF-_l~QzVZJWzvac#(q}=N4xyspb+22ren}T!c5Lfqe9B>?P9B>?P z9B>?P9B>?P9B>?P9B>?P9QeiNz=u9?%}<4YN%-?;@RtDpa^(2c&s~TQ)AQ-@FVA1> zzcjAR*`8%1z3DXkOVuI!$jKD^OJy-96EzwCGMxecQvEt%xg*`6J(HPmzBaSZ*1cXU z{$+-{DHIy(W140nAzQ`DcF|mtvf7CY18scRN_y^%#7`2H|w0YeeqLJ4hu8miTm$3 z;5gto;5gto;5gto;5gto@JbFi{7dk^I3MlsFF6mSxi9+Z3?nHp+#^+BapiXmL?4L5 zzf4;v_ri(*mrs7{Vy)kk4mz3o|NjdyWhkt2hLeAAY{7Z*_Y4@-k{-sh5 z|MI8Dzl_1XEP!F0V#>VpeE64%nTmgzx9F< zboiH(F*+UorNh5;_?Hg<(&1mCmG46MM-Kne;a|qT`uLaWYs9}y9scG2as12VvP|}W zJ@GH&i!z#mXZp*If0^hXBQMkNFJtdq7>9r9@GmP4|I*=KvQQ|x-G7Mo^*U;5m8syAPI z%`LZHa{*A&bHV<}zx{&aUna9YV(;;u!?(5APIa7V; z-tVRV(~owr58iY}2g(2byr)V{UTI7R4*#-Ed+LKmy(0>|>sNXA&QtnE^(L#kcmj(u zUKo06jdyQ*5xj!>itrS}vt10hbUON2CC>VIzZ93IQ&b8f9dcqX&(;%(&1m$9scDxoXF(Q zOju03h-dKVaCovQ@lLk#9Y0{#%j2#Lle;nA$hV9?^&P4hyfjpblFjDisbMqNvzf4) zP4fS3k6OQ*=o9GZZQB)>SEtX0;jUP>snlyu|JJPTj7yb^65lLM!p0hN{14lsL3G4Q z{LQ4JIY_*)xW-%gIaORqxUksbjTH`u;-?X2e`j1i#Z!e=UvFwOZQJ2rK4|ti{7YMJ z9sXtFB@X}6_Eir5(&1kQ;Ksz)7qasVS7oNfy=JdC(c2>3!ThN(Vn*8&bSNFp#y;kp zn!RK7rEJV|_?M~_#P=KB%ND!Czl_?G#8dgYL~>Hu?>Wd#wb|%HO7AzdE=>4Ux8K7i zn0>&n%{t(ZzWjOSZ82eS^n}N$xzkV^g9|<=Tj%E6viKhl`J7H`1 z&2TQ2U*SDVi^IRvMdc54D{Ybo%vf^28Hb~FE-UL{Q;8{)O~|gqy;?mV z?wdbLx1=|luxpV~m#FB(j#%%b9yF7Nlb7P}vc!u^+oF|CvA>r%M7CWeaW!p=q#o=i zy=zF@zGWrdaBqpTeo6c#q*MGMFZ&`>2RjJgxj&qYEjfOv^kvi1st!-2HKY#N^v2I+ z=~Y{dq)FuaMw}AYYfaP2ok}-f8=EA^`pqe6TsAe04*$~OUpo9thkxntFCG5n{?4S_ zvT45A|I+SKOG%YZv%b^%eN{ZwR4BDBh`eZL?C>v{$BfTU%0uwQ@}xWR1Yars-`k@A zb3ExbD{@{vn&l6}#aw?}Q5?X-(_WX}$skHh=f@ctR(yxGWd8}Cv2%&s`RiEualmm#wr|FdSt z{ zMH?jCeZ<{K+?~{sPU?umzf{G+Ev#YFPVCy_h$@=53>o#K?N*+4_?Ie_ImPrmj7+pioT1ZP5ntdr9KA&2jjb4*#;>;a@U0 zclejAKRWzNS*CG6#{tIy#{tIy#{tKIUosB-%HUsKp6&A#R1}oTO+oU~A2a8T)!T$$avWFi@+!O8PwKzvTDh<6o-3+!h(ddQ|#=3C?~y9DjMI7p8x1 z#yi;m;$C=VsnWHjp6**3hkYY)agaT+vE*<#mj0c+XC83RJYYSno_@eAP=8_PvtaewfJji?L$&;-5<^N%<3U~vdf^s z9JZDWo3y$uN)!uCAZ~QspUk1+;cd>vn0`A@m_urPE ziD13wBGNLx7!1NRbBq6F=9czk=Jc?VPpuAkqnyz*PgcEwL#jA%EG@tAiGHsJk2Lgd zxvk%;933`Q-UoQ}!fb!L(!EOSQsnh5O8voNe|Zoyz`e3K^+WhLeyl4TFL4eqqI}j@ zy>QFxjE~uLvl$~kp>29&9jw=0;B!`fSE2)7d$tTI;}`Dj_ikC!?**J04cL#ZvDT(o zmk12&m3ODD@scPIyIOyu>pKaHeSK%DYrLnA(jfTO3khqa?p<#A{ySGD{$=p&a^k-n z^9sx>Fy~^<#ry{AY&zLuq&^wWV>(<+hl_b}Q{-L3Gl%C=9*2v$Evob$F~P#ft6^4l zKIm{UQ-_P`a4}{4K5SMpj$7FZ)1IwoTopNN4|{Ji?%y>p3Q~Vt)UqfFM2->}DrCGH z!@r3?Xa;S#xD?-^qCp8;MwUUg)8!VgDt<0uJnvqo&AiAH8Zx%m=cj%x9S*H*!*`AE z3i48|8+*YsUXuEw&=NWU-wRh9HsaUfC#GFi9tp$`=?UgDUiMzCgLK5&7tj-A<+qM^ zpgid_$P;&lRnjbH>5}(uj|Q$net08c-WYjLb|?Om*B=fwX^7jmMGhCU$&1$g>~JyT zEgXfD-@K-vfNra_cYEY;F{%GDSLjgee2smH zC+y=_sJB7-r)G?LY-FC`9}a^j-ycfY;8;(o#vZ+4e^KP^KG|=)GPP$%wK-^=$L%zuk{DP|$}FMeB9=11Jc zt(E+){j`EF2fRu#^&Bpy!^OPK;bJ;mOoxlvl3j$2C6{{w3khM_#F468y^x@nL#CfByKF*Ip3+@>34~^89siCRc}l z>8CG$%1gQbkrX*&8L#pRy*zDku_sZb0w*+kRDZb#Q_WrFrDgU!=bqD(B3P3NXOlSR z>Gl6F&XqN(sF(L5Sd+>`fx0q6txFUn|Cr%UHmQEE$oahFTcVR9R)yXsukdu$i z9=WG;7(IBYr{X5BSMI^+Y;Si5@2Sb&kBNQ$uHt2$`fgH=IsetzPj&d0Q?V=?d^v|{ z*&TW};HTZ;UrLui&9>(U8hld6tDd5cO?-1dY^oi#m5XK)HuDqX&XM4_O&8d|?}-zy zXH!DG94e_c_VKTd%lIf3l=AyKQhk(1!W9%c6!|;K6JH&li!YVN^ZK|Y>R=r;Q?ht=nH);Fc)}f1S>$D<# z0Y5?u{mrEvn7wMVE*#^`Mb`}Wj}sqp_uwy!cZ*Sv>A=R>7MG7*m3X~fs@N~_<@EZY zSA0x+O{oqFA5wv&UEu~DFTPszvMZHv?@0LM@GpfM?&mn*IN&(oIN&(oIN&(oIPiLK zz~Nsy{L6yFzqELl4*&87E%+7n&KvbmDZ~E^(8)4@?qab|cV{?c4*xRo(jWR!G#m3D zGo8Tdkxa*|UcbsSH=irL!Abr?W)ThyD#2tRZWxBx+o6*l7Hnn2HUHwm?cPTdM zy;&WMS7%{s_z!BELw%wOCT-GG1qU$MmDf`+X$KC0&$5N_?@+9hyHuplvcC21Y+bM3 zj9ww}b9YDPNAPQJ$^G*#&6dUZpGdB8eWg-3J0 zxv%2}i|10~eo~Nbw)%f8W)63Etvo|NQ{zr>dki)Vx{dmvEA|K5`t=z35nLY82{lUi z%AurK1xH47qX(CeSK(bhYj5&`D<_Q z*ERfA(K)2mhzZD-)zgl@_^lc36jNx{g&z8of;k!8ij*mOmTPU$ZshB_yiA~1!=J;y z%*L02&RA=QfBC9do@zRlr+RJz%d-tk&gS^PSv=1%a64tKSn6YvV|nrwiELNvWW9R_ z<9C>S$GO=eIM%c`wSh;%elKlprk=~)|6mC^1Rn1)Nl(^aNcj58pE1p6X=}M#di_+l zOGgUDX65iN1G{&kl*7MF9R6kACLR8z!@qR+m#S0+*Fp%aj8qvHxUO;A=zU+VF+^ja~-TG2Uns`Dc9mFX>R|Mkdg zXFlD&V3j^VJn8+}T=@X)Xo&TS)?50`TE>AP(mzD{Eg!`Gg~X)fPs~HCBZ%L$xGfsu z{ge%tnA4qe$>XqTLr?GNmtXceu8YI9H-zUQJhwVRho1`v(Jv~xzXrFU9}~VuHzh`NiH`0Znpo!>+z?y0 z6KSgV@@DzDx>d*B(W8oWs8a@3K&Q`ulNl=q<|OUtWQXJU8{vg88`?^B~U| z-cMmZP2H8c^)wiub>;(tu_Eg*1MHD$^c+{D&QjMK_3ylW82!jZA4c7^{ZVHdeblhA zy3o5-$uRejIvydf?=7Mixk;5)V|Q{{Pq+rVHPG09ZCrlxo2n@Dl)czRISu*VKVOwv z#1wm>f&SpZrdE4)Uho;?A8wDNKU3TjkU2&p-7x_U=w-jYH_(ybc7uN& zGe3=bw8Os?2D+c)fa8GUfa8GUfaAa~9S0o#r4(7B2LEv?)=IXvvn`5$kjaU`0l8n# z&*5MCm4(a=k&$Z)Q@&?er4)U$2d~6wnejjFhm6d zjkVN(`J%;S1(QuM69hM{UR@n7N+@-_0Or26*x{Cgx_*f|xj8?EAXX3y3{}gcx4+GXeUu*t^XXi^#BMlP2;7i!@ zqZ|$U)3QD;Fr7tqhNBo8J|?YrM*bo6F-eQGNt~5{WeqmpWf!C*Zb-9y^&U_V_E&m`iJTDDh{?q zQnwoIK=MDe{&Pox^f&s6M&24}pB(SxIHg`oT^7ug$^Fyx_-+3*L!FlTEM-?Kvd&8$ zieN~#@-*=T#k3UcNVJUIwfVG(7%b_wVaj*d=&lj^v{-wje-1Avg4A(b#;q|P~ZgBXQebs`+pIo?mi-}E!L%)adZzZ^^tYh1KLfJ1A zx3B|wP-N^KJr;wqhQCU>*kV=6`7h~r7ao7eWZ~av>iFGrc8y8A+)Z#@@gw1&juu8Nc{7WvHk~G zte9FI^s2?wGhm`|Z?X6w{`x+xihJ-E;%?>gN%2emwB&PA9*35uCVpvqv=aZauPJ+) zLL>Rn_DJ@TWbbkHOG#-p?t33gbTi}L$wP73fFIgN+|r*({9-ozHsiOMcnMctZF!+o zGx=Wqn9|L8z9;vA$$#G-2@ddHXh-lnV*Ivwond^HaaFLM>%=h=-m{$L=%b9P^SC=o znGG=Rj`BT#z3gWR&a;@DVo-}Z)_6ze%+(J6(sTHi4*$~OU(!c7{7Z*_iCE-*jsuPZ zjsuPZjsuPZjsvfW0}lW4HL=Tib{udVa2#+Pa2#+Pa2#+Pa2#+Pa2#+Pa2)tQ!hzej z-SJc5UlRWO>Ha0azZ^M!^>Y{E!}NSQ{LAwf`!9{_FF5|C>imekr`$Nl(J+(t-2Src z99hGjyDVOTCswiFUw?CGvF^CfAM+&ga4#eEF?mwX$fTW^qGJo)SqVC}9RB4FFZ~BU zItC9*V0cd8cDD3;9=M(A>%#At>J5*Dce67-#+V6DRt`AZb2pRB7qfdrC2%K8;7*n} z8*#Z?Tm(J@x?1;R*Gic5Z7MRD>b+Uq38us?@y74Z z(+IYs;6hgMrw_$V27JiAk+f(|XiqR7Egs}YGOWksV75jnIt=8VV(O#wf_P)h8m4;A z&(_Y~mBklaOxnQb5uKf*+)F&e+H!RPD{=d{$9Z>RL?@`jzl?o{f61NVIZ}_Q!# zQR#la7F{9|u%81ZM@6Bx&J!T(t@l}37H_ATkGY}hnG)6%PX(HYua zlk5rn?)IqZjp&U9gR!}oc+C>WMTu{ElhEpt&DWLDVOs|4r5ux%fs(_&JcJ(nq%-du zLSYbhywPAL^p(%w!m`!Dq*(e(toC6TuuyB2l7kugKYi$3&K8Sq3KV@mu@-;N`b z-2(Q3S`OVwg>UhKrZrycj&(X{;+?jJc4V&)Gwatj*?k_XgC0HH8v9ZFhAKq|mEa{S^@HSxT{PmIoV z@w+K;_?LOPI{ZtAf9dcqmBYWh41Hr@F$7@E)w(d5E7a{b+-fY6IMMhns zq7yq}y^p%qj4X8WQv6-USkByfCF>h|sb3QE@ zC*{*u$-649W4$i?QQ*fL;k*=_mwx@ zsN0!SA0%A6I&4<%Qo4h7d2m*tcyLx+7PI4ts%O8!)mhKn^Wd&^Ix{!vj?X&$ONW1n zme~v8OLeZDz&~2UIJ2$^oGR*W`oFeE>lhQvuPf^=^YaX&X`emUDRoxYm}@7@%|)gW zy>DBRFoecR!iit?vf#Wij^HlX=d~^I4DQUQp&{<#@74SS5*O}+#Uk;{Os6r&Jx#kh zOObXi^{w4C>0dOx* z3(lp(zf`T%*N{FVq|b2pmudoA)Zt$`{7aF2+|O~qalmoFalmoFao|^*1HUr(mzQO8 zc&3~|soWGKFa0rd`B)8prGaZ1E3*u|H_i%~Pd*X`3T(6V`7kTpK))pUC-I2 zZl&w#2h0NX7o<@sIb&qcgvKMLJvnSD;9|(URXwExSr6^QJ$V#do2Rrrs}yjqG{9dw z^B4(l-9M9^6_j&-wPnzd^MuK;i7VJ|@dko`Y$rKxF<6u z9~%6TQ8}NLW1kEhOUt)>yx*(A15NlBZeb6Y^O9BG2Y56%oOQxgx>spk;#}6Ely%_# z@*t)?Z@CybA3lvA>k7w9%mX9%zrN~)Tkf(Llq(zOxYW&N3_4@%gHpcbaq3RsSBY27 zktI6twGCI_$@_ZkjYD7fZ@O>btYqrfb`qZS2yMZ)lyWv_Km4jVm$%&0@4c|9-wQbN z6|hcKyEO3yQ!y}{-@H3*jhBESie0Ur_$5y4>zr?^@t!_P#phc~*%+x~mvfBlgXVX@ zRl5w{T~6GWV_t!I1?F7LxtQNzJ?-_xnv5T&9ePplW5r8aU(dK3_;L>C(&1b>oXfZ* zeWCO}(Iq^b6FtdT)tru)2puJMpAS7Ea&F_?_nqd%V!>s)!;ULe`bjmH@eWh^O~FbO zoJ5Cn>2NOpsp4F!-`gGyTtz#0BV+6vBk##>hjaP!#JNmw_A=RVUQ3F3~dR{3ngTp$7e58OC$>qcH*l=uT1 zl5hY!aZ_OM)#d$PQ0B+FbTHNxuIvIkiFzQkEBCC^gP48yAmc&P;an=;c$>BG`M22X z6SEJqFSq;cNp^$S4SuyTM@#LTt;-RU9GYY& za|fAE$bW}(>2NL`&gFN)#mxN{eWmIh8CCklZ=EtP(yorMZjoNKEm};!wm43`tzc$; zYtBdY;*J*YA^Nb3Xj`|ddFEZk)VoMM?1{OEdG{x_7K)1qbDPM73${gzxchoL^d6Em zhR$u#!_4I#PXE>jy@e|tG)EX0k8F+04@2|HOOx_q=)RBs`F7|nhOU@bLU-{;ip3YV z7K=yp4W&h$E#4B+ccdJZu6$48U5U(^au)d$cx9rmuJX1#8d`LIF%W*_~X+z*X8gH%OkJYSj{GR7ETH99)0gf)3s?t4z$dk{Iq z{Tv4z2OI|+2OI|+2OI}}6*=JWFMkzF)#b@?z;VEFz;VEFz;VEFz;VEFz;VEFz;WPL zjRUuD`@rvQ`=hP5{N5dZ_<;{?ebbh$cTUaWIk&0yjW5DCUS~FYXSV)Dv0Z+{+GSU5 z`F{^wh!4~Ac_F_1(baFd=1p(C`mI~8d+W7ts@{CAL3X-+0U0e&f39x|Uvj&D$D&a?*`Yx$2;XU;5m8W{B#X zANTeO4kS^wr>JIUX1uC#H{lgtr&x%NgDDn2=?D7PZk;2#4pQjFD!F7^E z7P4>Iuz!X5_tV_#RZpFME-Y-5FoJ=pnq!seQm{!oRn2iRRZ*>P0$ve+8!*+Qo?0g+ zzjezz_1&Z#bH*x*54%?lH+=qZHa*Xtql4~T^>~-np<*Oo$GVK@hv=Kgqf#MpMQVo^ zeohq!x5VYfxx%&$O+gqx>VU4iM7PYLVC!ybx? zY#x2W9{>BKykb(=jL(T0<*tYNZ`&hXYVroY&bR7hsT=|-{9Jb@*rV%>5*En@gJgD^_{_-QC<@x!nX;@&0S@t-npz3+uIl_#<8Mg)-9CBY9+I#6JzuwYzG<;K75$KR z{QH~@sN=T|AA(uf&0b^u1xvYm)%YgNlyAZwr~X_rt0nMfw|JN3=G@$zhpD~>FL8_C zmGMl{?59U;KGXKJ)sK&urYoZW-g+y9|J0Qglj_O>>WDnHZc!$-{{Bn&3^wb+W6v2s zdBphnx1W5*q~D>xgI;_#>-P%0`&Ux8Q|h+jZ03P3lbqfj9S5(~??qD!aUP!+=-rt0 z7@d*$54fYH=49!WG#-C0F8lvH@`{saN%&fUy!76nYn`cI;XUZN#fAr?w{>^AIn>yV z9*m0vYD*~RHRP_GoCO&@sEWGYW$i|N?tu|^dTAjVEvVA?8xlVx9ix=VK)NYZ)vUiC z`^Jzr_VPb^L1~Rw+mRH&?ZfKfOGp?$&=lE>15O(YY$+`jeDPT*%6$ z!J90fn@sA_zmk?fWp$>JXQ>A@%1_+nuHOKCjo=7q>aI@iHi-JtCG2j@ zTL0z=`{TL2KR2sex&s~R^!vJFgAO=vScl)ihPWKSTPZJFPPAbuGpP@@yk;n;U;*{z zvG4r>@8O+f}o^fSqm3cE8b$uEW+R%QL0Gghm|BrC>c$23l4Jk^zGZRAzlr)14$ZCUQ`@lr5N_?s|`IVFoZC5!oiVSSjzydbcS%GSevE4SR2?CgNyGCnu3 z-lH-Ed=q5rZTeiU-srdqH5`Uf!QV8{hWR%7_uAYiI(J5A?pCD3m>?TFqb~=2JJRtZnLD^@tq4i)4&&6^ldc~|vze23M!_vyqYT8)5QjMcMQYVWeAa9MVx*bG@W(i1)M(&=*^o zOL>_5P68k8D)`*%6u~ax7g<}D>V!UmULoq%#b_?eD1(bh>xBbl@hOnoDb)}mP9Tp6 zJ|zV5FnK=&TVcpX_OK0$FQ?L*R;f(%)4Ft_Ph|!vZ8`p?j5fZ+(&bK-;qYNm6q-li z4dld&T{6Rwu9E5$9O;6WQHL&-sUS^&cOmi#;Jd=m1oINcv2WIQb&xG+BZs`^z+;Or z&oRu=rfyhA7gcFRgGN%5C8wd~odcB;P}8$KUc3$lr&8tRq>p3GW66 zq@ZG$UttvesNF;@Z~23S8R%-fV7`6dZ=3;!n#;GZmwKL$SS%;a$& z!0yNJ(*5AM8IX&6po5F@^7xwG<-5)m0p_ZF^Kzl4lT1)d0G}XrJ%gO1{1uzKvfDrH zT*y$Yy92K?GvXsX`OblDPzl11>ahRMV+~5A8s-kbu78`%R0f$hcX7908kF8#X~TS0 zBcJ|E2_dz;3|bjJhK%PlA7`+R#hxg_yCUv6$}6{mM{sZW7=Fc0!Mi#1UITXlwzf2e zX-#E$Qu!l<`HwmN01pp^$(Sz1bQPeZU{{zv39;wNV$ZV)^T4J7;0_F^%+26U%5P-X zGgybp%reaH%g|qBTeW-DT(Rfn{&e;x@B+>ycK6K@d)948XFr8L2gW6bes%Ed2F(33 z9I5-NS-T3zjSMvT)(_Sp_g0#%p zeMAHd4SGj$^ljxj?Df{w3%=?CU@z1gJ~h0``oap<*d_3|;XlxXe9h^3mM3WqRz4B^ zi1$(TS{MDI7lNm$ufcbmRjnT(&nWLA!g8z3aL6>1kGvv`W+E;2TD;E(q%rz(8|ZTb z%T;D7|LK{VjW3={y_Lo{kNPt#0%w6Hvk*_b5yw}8UZLS*E{}H-VF}?WC&|p5B|F6_ z|J^0b`22i4U#x^2U(RwIbD3Jk%s8XE6czTc@%n;S?YZfkfMg%>;ULLg%xeQj0|wal(%vtC96Qx}%J5%aV$DhGGhnFDJ~a3?_-7~WvmqZyj-a1Nu5zpw zjJ(MTpVPHg3kr!(>5L=-P0I^qhWLxG(_R7NJc9hqqkjg$e+kT}u^X?vmi1!rO0%bka+LCW1@DNj=|0J?;Tr}2`*oceYHK7x zYkCKHLURh;e}97VC{KPe#uaErYf1U@8?Z1GrcX}wehPVP&yOgt>hmMYU;U6UZt#aa zm`j9I+X>Pxhx1yW5LvR7EGDX0@1;OY4cD;w!!!2*7?0{u%m@7t@_cu zzJ|PG@tGH+^SixmAzQ1`4E@d;WtwD`R9IJ_t_=N4Wzsq>1zZx7e)C@AFH^?v8F-T3 zvrL_zuG-^s;Ha4OwHyv%dy(A@UMfQt@vX}RrO$&$UXwnKH{+ew1>k`Qb{`SOL@BMX zzgZzT_<7X6h~kgJ-YD6pO}Iz;h#kvxPKG(hoQcuiA~~y(_s0E;d6?QAVN6G$skzr! zJ0X7=Ap2^=}rKwx6 z-|!sA*$CCGOlwB0B`HmWkORM_0y+fJ`V_0|!2E`ESdV53_pmh02lPzxWrXJI{?;rX z*c&SBWBIwQ2J4sMkNkylZ@{O0EIo64kFlRF_kz!G21x6zO1~5|hUntJXreUbhcK^S zhxdr1_hmC@-|dUjapp*CW}H<8wB}t<)gEde+Eb4@HNbYU0rTUnbu9e=kAb*|;>CDTV z2jg6uWN*1CNROnXp`Dnmx!qr3-L79SeVgnJFV8}35aa3M$SJ?cKdU?y8WMB+2!3e$kIRaHNQ*rXXbLv7vfx>-G{nk zA7bWQtcl90R&luZG;9~>wufj3`Gr3Tf42htOZ(0d)te15-W0~=U>jsM#tPYfne!;@ z_350D_;e7yWebpXn>^L9vLql2JdqeI=Es8%08lL>P3QuMmeZqA5+*#*`f7!y)Ga##H?42FT%Pls7 zHzI=SHM2g~j@5R*;J4pz`J)|t^(^vSvuTCcj`G`)U%M~-ci~#oSTgrX+mr7o&Gyu0 z|L5>&o1{HuhRo3YDPgN<$NlzA10FrES@~I?owhzl_y3MHN;~M1lzAq~qjIkXPj_H` z{qhX#De70`=BYcw4q$y<&F&1Z-nBh^Zo~F)UYFf#cRPzj~zGYe1e4%-%$G6_iG+3?JrABv+cec<#x=f^U+TK*>I&`E$eghX4d)7by7Qq z;x^pvU)?zzUhNHsYf)cn2hk^K1GRB`uyKFhNjsiT+VL&hjx$iFGf>|%Q13Nrr)a+! z{jhOBTnqZ1KI3B37Sjf#Puf6vwb!KoMRod%J~gV`_TZ+`&qPP$*9e*{K=})h--4R_ zzE+(d(GclZ#55eM{L`_vPU^eniCadMM{`WlUuU4d7Q}r<@|yZ?KflJjUCn1#d6v&u zZbgphO=Ftqef5A{vu!6H1uw~9g_#o=@}x9LKWqojjm1Z=hldinzm|9Y(d12b^h6Wl z?^@nbI0qr#spb{^>gaL3J^1FRIwm|qbsUdBzJ{~!gx*R0#_AUnchPtD=ieUu{egS% z!9jTdWn6o*$|U6+tpERg!+_z{HBbE0{``l=>G$eBpW3|KUp;lESgjxjPg$Rv3fzO$ z_t8(c_I&A4^zUly)g*i>-;T5V7ObCcpDNS0V;}z*p6OmsS)Y3h&n=L%w}D?)e^O>{ zTb=T5|2>v&!TRL3b7bbiYf@eda0;g3n`zh!we$@8xAzYFEosdk$C!K^`AkFJ#5+@Q zmb*HW!dB?(;cCQBZK(&Q0&o?8wQw7FPvf`#N9&L;`(Q|QXi>IK7h+9J_0Tx?r+h9P zqdphb)Msj1@kdwg5L1!=ROJ6C<&WPSDE~*%ZU%qlEvDT=;WWIPhTn9i;rGYeINHgP z2K&4gobx{hnmzh=GJNcu>Ebhpr?}+Wi+*UqT8^G+FGlx|A+Osh9m4(Z5x*LHzT2o= z{Dw-jpNik`s2!`3u9~i|X$R<8-HzKJJ0;GR44vrr!+8HS9lvK@gtNctQ&1PkaHIIkpK^|vG!1!xfB%Hqo5dTl+SlYsIoo%qcW z^{FiE5maY^E5wz>mBW?PxrqL%;G#7l7D6Y`@2j+aq4EdWFxE55oK4f2DScD)K`T%B z9KX?*7vlGN{AO6jzD~b{v*3FAZ5iupJQwKH&kEg+dWYk<1g7W z(79{%o}mny6){F=JxqHQtku1U?ol_6^)bQ>g|w%jHkfkJk5oq*Po^x^W6nkcoV!)1 zE-0VQ^UQAmY#8T6;5D3?m@EE{zIA_&0*(TX0*(TX0*(TX0*(TX0*(U5F9i-Azv58a zPJ0rGOeP5Fw@>VO$4kf8c_J?_4{P;Vi_rPnRHM&Y9GERa{5~|6KC1*~AnD2JoIQIe z;rwJi_ItFyjKU_IXD;^58ESl%Jbx+9f9K@10_uzYTrdpHkdHtpA{F7Ol&Z8-BI)hT!8;_ONoNZpk!m-}5nRW3wKGE6z zISM!mI0`rlI0`rlI0`rlI0`rlI0`rlyd5cU{k4lOS+nS@-x&}8;=sGHse|vwev!mZ z@H$C$v_ita81A{?!HMWl+s=vTa>Vg3&SVb%;tep7s=>ctORbI2L|Gj!{0p)VC!JIE z`5JtSn)5OJ>zellZ^GeU6ruM}=#z(xe?j_Y!~^5uVCa2SI2h2yG&mS)p25KwkzWl7 z3qyX(=23xO&SbDKbYIG1Vayx{3*%wfCgCiSbmR>dhVI>ug)xM4LDG>Soo@;U@s8@R z5ueyKCt(G8ucXUkFfRsT%!_@N?-M;8J=J1fY=!>FBe)t+Zlft1yh+B(;kQ~NAW%>|8NE=U0*fptK43N$N!3_9x2*DsT+EScU*kR5*wM3)R_`x|dkvj%%3t8VIzM`M9&7?WO}cEqvih6f$Mdbft3vrN_PKEi zOFwvlGUXHB=_hP_VrxqI>gR0!#t!U_V6m(Qeh9D-Kr4&IGIDHTvFIPz@o4Sbh71;q zegQUxu^ye#0Xs&pSk$*I7K>VapidH;F{5h+8?)2p)h975j?ig|YBg z?{FRs3TN-~wf6nqLVSVW7_MZATnQM~qMRQh^Qk=caEdEN#_9OB4QNdq%!uE^9 zUx8hm2RVp-D83EwSJ*F^nU~1!O`m4@HQ`Zp$&tffk!#|zCxO4Be{SoX)RV^2r0`c( zO^m;y|H$F594h|GSePri7xu}xBraO7(4QVY@|Y{~_pO{Y`rU-#LRcaWbH%Q0w;cPJ zE2{a}z+7SB8^l~W)yg^IKZEH&dnGj5$RUL z7h;PRBfx-?FOof}I-(dXv{zPX;3wgF1a{^Rr+Q&)Ec~snu=Lg?D$@*m;;pdjcm&Un z;Q0~UV_xtHpM$=QVAo^z+rYVqC>}QDWD8FABje#*=vRTcKo}Qf;}hG9Ic$s0%$tsF z@!adcw)oL#YzzHp{9G6x+roo=`_9vp@L;#@N#%R*0=8tJ{Ka$+`=vVIJ&k%M?4?7% zy`Zsoq;W3@`y_&mRRo)8#Ab;|SBrbWb{xZa7pL2G1cwbXcX$^L?*hL^ zydJy@hjpQIlfk-Rmrf4rLVa*-tPA-eJ5Ce3eUdW??!@85x=@QIk98quya`wrR~;Kz z7Yw%cq?gTrr8>R?ptxKGa}(9Bzybl|6PbItWvNXhIkr z`XO$3UcYQ*PBk`%{N-pl!bbF_`xoc`_3i2Z zRn8vA=H(dh|EgM?|5w89J(g?^oc~wpIsdQD|Eu%=>ioY>)>pIh|N8dy|El2kRg&*l z=l|9DfAysE|N17_B1p1zt+qvQ{$HK{SMv7?n~P(`|0{F;Uk};;tFwza{61gV>#&QF z|1#PxM*hG)tNi$OG2{7st+tmr6gwE_{}nc7L=u~3*yj}COR9)48q3Dq z`G0l(U!DI~-}!%a{$HK{SLgqg{M8e_z)`?az)`?az)`?az)`?a;JBoK^Z%;E(nTsuomc4x=A-lfdR+3ctF)tl zqkyA;qkyA;qkyA;qkyA;qkyA;qrkx_Kz>gTU^$%8cjcdsPJiIt==kKR)-P%jzdt-q z@GmB!Lv1@JqRSEY|06wB;!*}j07W<~! z=O#PpHhI8gTd*L?ik;8ooI7#nvZ=^Ti22h44d4dd5Zeq2tCEr+)Xb;fqr)e1pC?7r%MF zI34~4{A{*bf19UZ-!TVQQ4fdt>B^^l2>CRpy+#4o2z+stVE;_m5XSeZ9tsuq9Rc!{9aL9gpV{Uif9In0 znvbMZLmB1gkylCfg{4O9H@o_?e4X@ylN6WmXF~Vtn^ta>W+Cr4PtV-U(U<w~KBM!36nGA{_T*Etfc_L} zTS$C3h9^fPL?Heqq&rI=`^5D2IQ+Fy2|COq0x#N;klB zsn4cr?t!)G?9Sm|IQ)yDIl%n@{zvUa{6TRg%oUZUZoz&t+HVqv|7uDTksoXLs;=PN zGmzWN+*#Ry`3<}lVZJNe!_v_rnWbkl4`z|RzctGT_J*ns^VGSmS(UQ>x5y6{`Mj2% zedhQ+@H*4wUYVvdK!x~9zZ9CS&(XyPaF&QP<%d|hd>!5+j^3BeoPD=1PRE&}*DJ*7 zIrzx#6~Th4_E7uaTe}|hYS4Fv4VWKqtz+p2_TB5>`ZTM%x@ED>+~V*r9R3A(;p8RV{^xcq2%o%3W&T7yl|4D?_MdD~nUjZxvbuM2K4InM zWBY{F=Z^NpNc-P*jI(E36hE9kVcBVu_X+FpFC6}b!@oG-Ta|nXcg(8uug1Fm*>I&$ zP3v>>X5zVXIK0}kyrN$nJ+7UPRqJC_!YA|b;A2%EW*@8MtCxI}KB{mIz}M$mGK#n0 z>|q+_n`w2prquhlam5|}g~PuHr{Z@5Tn_)j;a|}D(ET|II0`rlI0`rlI0`rlI0`rl zycH?n@Gl(x#aofDU7H*Q90eQ&90eQ&90eQ&90eQ&90eQ&90f*G;KSE0ykyOyvwr82 zYd><$^;fER^zy^Tg1oX6L;XYFHLdt7Iel_I5oKSwt=23wSYMyO_{&Tk< zsRg0IW_S-U9eSCFZu+{hc_Q6t-IoH^0(5a^emuuFKcC%i+X7uxgN5-hY?F|VGtJ4y zrJ#FZi!|g1Y_CuH=K=K0N#~owLA;~-Ys9m*(N_g}uVi~Q0(=c%MPw^2n#+Bb?~^k1 z)Q_9?Z$+9%a5bRZMpHJ*M_W1ca|71z^DZ5hsqUbgiT4XWzyAeO_N^Oarv4f2>3-;x z=spuyOl|hLFZ_C3%m)kwu4v_FO`Mu#=~aa7PMO_h(^Hvo`lzvF?pfS7MRp)Bo!ZgB zn`ekh(+32luYHbI*fI#;nCMb$ocy=E*`}?{v-X)!nPj?_$)$@LZJle&seP8G=7PpB z7o_H+pF3cO0GgFQrUZw+e)+=)p|5`e;)rjpZ_?Su{*LIN@h#`XQ_y{4-@&DQermVR z_b#yfm@T9@P6e+mFT$ zOkcL&4y!ErPJb*mdS1d22 zaL?NzPc`HzgDl!SJCt9#F;{L<8Q#T29_5r<15rd+A-+WVfOrn`tKlEmoR*)G85$#A zRbKRcDTVrXEfJ*?VJnFHpz|{GJ=wb!b#GQ6Ze)w}23cRW0Gu7NyP>f$vW0n~GTX$B zU`z>=tzTlfkrYesnWcCZ^%#K;>Y(n)vVyf^-2IbV{oVV1>j&xOerZ5?yYYUL9?DJ@ z(}B-MU03x8&=Gtbq{}IW=c_~jo1A>}OffPGwznsu4f9~T!%BW-1LOhK0rp5Vm+|I{ zM6gi_iVrf7%4kO=i?P#ufe;<&pLZaCJsj3SwoqS|-vPT>q=}lB3c_E}pR;_bU<;?G z+k5KYWX`emf_)KBwis~Vd4YBE7M?CSJNLA@J;19>DBg2UcT{u zkx$ruNoZr+*%N9X^E&E6Hon9&Nt=leO6Wg&mj@pWLcYjm*e!#1g}Nimcis_JQroP| z1f3$p)3-&0rT*Ui@#Q$4&$PTHnpX&cb%$tPB?8#XRzUAymCOX7E%le_C+I9wpP9a+ z{u-m70{EP+?0O*!T0#CqHhuU&!h|82;bDy2T}hWVHx!=*6HzmQ^Srn@nfyB z>vLyT`L!n5nwnA{Nc1!Ly{@o3!;<`BNOo@I>zZT!<|sG7J6en6(WXk%5>aWy7>DgG z*;P|pHSE?pk#E8)Nl0rLicfrM*M{U{`}NeH#=B{E3Vr%ZJMN6_+i8|x6CPEU*g2qf ztjhW~XRKC_Nx3F2JMk5cej__(sw>gj$g8+d_0MhjNj+&S1@A;Z;^NI+qG-Y;B0zr< zpXM<~=P}0AD#*jCeD_j+wLwL^XkPl^&`@QRP z3YWx1eM)~v19L_GzLm2ii_E$axFf+XtkJzr5$qDM!)(ivoqT|+fGg@^G=F6he1-rx z2?pmuw}u=T4P{^^M2Hi}BO;qn@G?sWT`E&SngH)YvOf)MnH+Nw z%^PMNR|j538#!b&pN_GCxs737Hg$X9#++%xafrF1nvV_46&Aih%#~BEoTGj)m<}`! zsGrbB#B-5Ce<8Gehdm;AD8Sy86D|iXiZ3_yr1jJ9&#CzsOOM=`D}fIKtQiz+dT3l# z8t}YZ_&;d?|72LU7|A07%y8f79PR#BY1uU_ht+b|Kr=J$>zaj1~ zCiJ86GxiPCkEv5xkeSPZ;4~IYZD+xh`7H2mDfl~2Q^LDN_?}e0_b%*h0_88Jdz=T> zdG({8>#%40(Y?OLnw!OET#U{U_qK&>t-_fk)=Q0YT-*!810fp2d12 z!W>&l)4Fnn;8;tJT8~ovQCO2E>*a~orVggv`GZ>+_-pl9kwhj-!dE_UI} zc$bu!ovc^XVgBk$Z}h!0a{g(U^X7JS`#-y~%e!lkrGMsYewXOa%;lOd#BUVrJ`vFR zkL$Zaj(tcu)hZ76T9WO;IrJV}B(v}*+pw<(mI>i>kEq^kh_R+HCI{QP1dS8mkEPAt zAN#dUI7g>-^WaulSAcxmF7a_Fz~S?9$0$U8oO^ zjddYEWXEYc&f(kRbNF`1n8S^Ap%zUZ>q5?0k(;OP3_Ease>LRv)w{Nb&u!Qq&g;6v z$f*vU7A&+9K`=by~dYw#Nh^P|2; z`V}$l#w!2xnFs2-=80QIl{bX%5jOa4tv|t;PGR2YSu@cAVw3V+_b(MUK{p%v_8m{jeQlWi0+@RduT7d%CaX?S$^N z@oOIZN0T?5BN9z$T&Epv&Ez5sPM6Kri;f> z&Pli)#~JMpr!w&w3QzUKH0<4{1CwMb-Vttzl@*fFKE8}+`V9cTRc3ew=LI;Y4X{3< z-|>T%daRd*@H-gx_xPIez&uK z@yoMtt_pp;vLby#*rh>lnL}@xbj>;Rmg!uY&T=a_Bd^3~4HT#L&ur9dB!)R zp7CuNXZSdmhdz3}e{vkojKfxh&i=*Ozc~9BXaC~tUo`1V@esO*q!(3!P1({#%GhgG z`e9#IWs~OYUnKNv?QeMc*WCP;C$a@!K<|7Im&gj-Yusyd&sRV{4Hx+{4sS&|%w?ha z5d2@tbO^oQa7YQVIUHQIR)o<1B|9~9KcwyREB$_<8G7{l&X0dLv}NtR%P~&JTIvJRjoXdiq)F#|Ec+ML2iq51jIQ|4*}pjZ zmk>JW9n9C}WdWJwBZM%V@i(uK^b*v5QLVa>lYpGI1Au zXTR-Fd+_%M?qUCQP}?VzaqY<}lazBXyQhEO0Q)o8{;YZ8pZ4cJRApOKZSPcV>om1_ zxxadN^`xk4cez@!a<~?_Ex7M+?E7mJqauLjfya2j4zmNu`ifc?HEY#VdOMx z3zOvahHVaRtns<=(y`@pL%w3$ZQ7@XLLH(nPx|^=2wGQPp9`|)KXV9c?TQ`Y~+-L@ZzZ;p!pjg;*d=YIpbd!FVT z{ZIrBGY6&^VSO2F;Mh0BTgm^1oMm~G^ncYk_CDcJRXlS3H&`()dlLRP*p$)rB&_C1 z`QP}&#Qrx}zw^IwsP+fts4ZL0o{}xj-xiK#iy&{t9EnSBvU4S^i;jjZg1*?wT!ZUI z{_31BjIyN0j7BGCzJF0-zIZ4pa+v%!}Et!X&$bV(Px z0K7v1yMe64@9P7=a3(*3(BD?L59PLS5cUSUp_ffI2K=|y#^CkXBItJ?8@@Q?!Z+xP zV{t5dfh%~ZzBm}IJF9IG;5UoL)tlvuLro`}By~i6Z(ts>IGYGb#&epFfzeoof6NGR zMci}v`Y5+r>_+2L2AG|v;N2X0uYspO9lk|yPird6lgb}~FOCxC_yar)tWek%(7vk_ z`#2H6d=%^ovu6w8XE1vfY_WjvxoJRV_6(@Z%>z(X8El;k$Yb}a zxnj@D{psvYzzl{ThTVO0#GZ8<(%DbJh5^1A`2*1Ze|7_WZ^>|^?yJTgPrxo=1Q?TL z^0R`xO0q93H7fYMgOAa5(hJ}p&e%@lUVYQbtrGmFHB<9!ah-L1AT6QpM;spe|qL- zj=uCS^;QZ2zZB}vurQwmOx9V5C*FwTD?zW&pJ2H>-bsWdgr}S&Gjo>g6sP=mmoVe= z^YMJK5yY*>S=j>s|wud2^;e5hO&L@oSot#e?dHL8r zVf49ntR{XUXuZ`Ac|-Ook+3t zWrobq{VDLN(T@A=vEPz4@afJ@o4ijLUH>Ndgjr+dWl~>i*U|6^qo&z*lRub_S#>^q zd-%_WD+Oy=pPM(c&Ue05tY01Cn_Ay4hugOb%N@JERpf~We5=&*j>0(z@lLgm75(by zaqWDpSQ`@wpG?Ptj}?8GeXNkL9`YmdDE6ofzEWF&f!2aO@HEK9X~0062F$bDfSIw^6zH z4fRlctVoke0%FfQUOK+c6M1=gxceu!`n&i2)(_Il{nCK)iUW;e6Lgk^==Ljw$J?dD;=pV% z9!9S`0s7!W59*b`;cxGo%`MG zvlttK0ULt7s4}DczmEIe(80em_1U{0V}dd0%zSrts8cLQzLVI_*&)OIQo4_ED6%Lk z$BKUTZ<)6V7#26*!@O*aVX=qb?Pue9W>L>QFRRS5Dh!K*e>-&0Z^_Q8kcPd_b2sKh zy3QZ`&AmQ_bS~MER=)l$Fe*Zpj@0SKKB)pb@;vNH0;1>6^|?w)^DjfkQQmIT@qBBj z-xHsuK5IkcoAJgEWh2bYuOPnCv{dkP zYslxrSHmjZ5QMOSq58n4iN4V||1{-xpxk+>T$=3aW1qX&DCgnU=4DO z_*0?{=nA|N_$VvjUdUlXFY;LiTTNc-1jk8r{X<@EqG7iG`y$qzhHAVEw1-_;xNXlpgPNX+n4fm`%VL^g6d6w`k!o{8_X8y zvXL!Wpp>YDQ*k17%2DpL3{d=Fo4ocs-aR3jewQ1~%CQ#@#0 zybky4kPg1uIDEB5R3?12CH1*H3wK8N>oK7Qt#P)0zLl-=Z*03eJmsrDj>qnUvqME# zANV8RZdcLxzbJmU=<2kbyCOIEKI+S_hI|0e|MULbmyt$Y7^hivb(+0~2a zHa!1tgzK(O>#J6ne8Crf{siI_dmj9imOfeyuY7K!3@XSZ zgU6IXG_Pd4zQ3VfeR_eOZ$a=$6M=EFlj* zz&y~$VBJt1NKPl^@vSJQOVPWyESZ)6XzQe5Z%VwAr#56jXUM}Kg)xgh5Glx7TvR_A z^He64SD|OfVMcb8_#>O5BIK*yp&R)3V27|1eN`5~ZGzoxC*-@x`9-P^>N^Oz6ub-? zb*W4RaU3?@x>Gl>E_{P|Dd>_J^2x=&i}4Gad;JpZ!ig5hUtru0V!k2TL~Kq7Li+SB zu_NCNe~QxE(LgrkgP<4rv^4&}^nVz6Z2Z%exS7w%R`j5G)QywJfKJPe+^hrSNAcSm z#%IJf`W$o;-!1qfpHYIwp~=6wN0802u{&;CYwn}A>xF&@aa)r3KA~5lE~`E$W#rF>hUtMX(4bi-qhR!DXt>l5Pc1lt5fNyezea{e5nS3C| z0U%riFXx-SC!5>0Mlpi##ii&=$ek=N_E~O8B0yXblIc?|twceh1FS`Ihj^ zn?u+eV}60mD1fJ_9isVS5jA_D%LfqFBm8636Y>EvrGRe@k2POp+G^h8J9&|9bKz2y zhcu;kfbTrXD;SS7$3Ws*{vRp8=QQDyVb1>z*}*eL-%vYg?Z{yt&XrvsaoCBM`&A}l zckb_-ynf1jOY4Mkzsyh>GG)u&-M>Q6GnHrT&)3hhY5O1xnpnEnr+J8VXaFp=a2sR* z`=lRY4I1^4?2ukz5la`^RHo1-GXm>p#PcH3Rlb3DuuCtj!}~>ezXsf)dYyoT80@kvD?hECA*!EJoJd3p+i(n(1-aP_2(hPZnd7+Z(75ri0r>b7cErXc51|j#aLV5aUEH{GnF$aH^Q!=emcAlg4 z1bs*SOX0{q%r_TXIZ11P4t&d=w%-bkx<}~u{zgITBAT1{!1>0%E9JxCo3OkCW0K}Q zyd&R)w65acL44EuM5Gp&{^#J$pQC>2Uzu666NUzj?Q$BvhY-(xWaG;iBUE4G=P<@@ zAR2PCxrjVyJzi<;!5Rp4fh?#r-5~gV!nbQ9ZPrE=(2?Uk_j*O}&%&3d+rCSUh=Ay3 z^(hpi`47HbeE9=gb`k5B+PP3)ZNH^D&|F@|oNnreIZQ$4KUmrAi*v#EUEO{tvF-up zK)E0MJ&gIlWA%eurAIWTKb>L?%u6*?`qv7~Zw3o6Sd4G!n`Y#l>d$bj2lVanoHeW) z%HT=D0;mwLEV@8c@Eob3EY{vxwb#l>lKn+>X*dGg&JptE82fL`58N6CyD(b=e{4TRkP*VO{ZMY|Nz1I|Yw|z&0Ql(veVNI>2|gzus_V=& zr28`suV}9UJ|~;tb8=K%>~qq7cfg*W#k^M!UaVJN8I@n-Hwu1Zx-&!HEQkE2wtOFc zElEDped7e>k-fed#|-lgzM(ybz?!*$IiJ24@4 zG_5tI(ha7JSk@l%giibNz6t+&cd0)EUe$nw`kuitRn!og*=r16Xg2^^yLuldwk7%5Dp=njc_*R zw!H}VqW-fbo_o;eyGb72Vd%oaOXXCncs*;dqz*r>Q~a-{vGk9@e={E__%r3D;mpo% zzYXJYTX~K6@n>cD=RPul%vulaS8ty2+mP8s_pQ%<}OP0r=UqJwDz z=4$L`eX*5!d9M*?AWQ_!Izx1!bpXW?os#89G7{AeyFB9>x}99j&bO_a~%5iS^5&~X$+5?jrkWmo6ws0L8!}U z-Ng&ru-?b|h4wj|l}sqGmKdaWs6VY)gu44RYY)mRK;DI3;ItUr8T&i}nIH8c9^Z1% z(B#{Lb*NN+d6CAN8guX^m^XVspA_TEJZaWZM7PO2%U5p9(Kl1kwkb=x{lD0;Ae{0^ zmAODZm7NlG`%|W>%#@*_top_cxhWXWQ<(NIxcvNZ^;DMjYUWvqLjZ<9%%P?Z5okm- zA>O4uCbg01X8H@EKpjWu{S1~?e{9zw`8Zt(?#b>duyrGr^1zXJMGUX(`Q z`vT}g{6#d%W8cVo&>tQHzK}Fygw~aleqJQ8$HKf$=Nh0X_Z5%yGugs>H-i_6|9r8m zSz_L^c?-lR_k}-9(xgYHK|GxsQaY-yV7*}l{YEyCM6a8B6(8|Bvm+^H@}lyot&@4y z7zdPZ0sWWM17#ezPwI(~__TmIlj=ZgJmK|c@txt>06a_MGXT$0_*$MF8k1+K{%P!5 z()Yh$WOW+(or7x$*7+Mzk2Lt@duhdQLYw^73q=|>*BM+(VB?=WQ(qo5AK3hlmk;wr zfHINS#U}41u=}U9wRxMhCHRDRlFBP0tgd%x>Izy=-LZ!+;(5vYaF6{OM}Bmk=7Sgf zl-=9Vex``CE`R6ju#AxI&%ygWXzLz*Md)vs9ez?-*`ylnxFFqDYA2O-AKrZm{n0J$ zd_!vrem(NQ`i|)KUC?R?g$tJoh2KaphWziw@e$7BFq(1|JSY3+WUg9LE|p5U%d}_Tc&*MKdDaUoezvB)PZ=4;y$Ub3X?j3TTLDKbxN4>>*Dg`z7vbU zbLzkz0{LODZTAmJ|7KDCGSHIdN)8^N|B9{e5I5;BhUxcW4h2olL0HDQ8I`{g_xIr< zp5aZ?#W~G0#geVc>qftHV}31nft2|B9`cQvTf`?<$+{&?J)+Qbu{alb5}&325cx9X zi*O^Z`*4k!AL?H2v-we8)E|(cnc93Q&uFm{=`JNUb}CUqTb4*I(ozX(C*^%Q&OE4I zr+>HLpB}G)6B^`ES2}xSTX9~3vxX6j!)zbgOfswwmj~bJ{o31uaM?ZD%VPgTvLg?S zwZT4V_PtBDNiW|wLkwb^j*iQTLCC*lHEEZPk#<=h(%!?o$|{wu;Or0kHowv;v$S8J zu|oV%iR(mdQ5W2p)7R;S`9CQ5*XUM5_j!*CzvD5xf9-gz;CICP*QBlVo%?eXa1?M9 z7>@#1tiR@v^k4A(cv;){wu8Su+HXn!C3{)-hKcA<+fJwdaN`g0^j{95J9B9IFNt2uMEWoK&r|ly zy-NQ@{+nIPn{%5tS^q^nW%C|Ozl6>*4^{s~wOgGD71=Q{k^T#N1!L$q)_+kaQ9E;i z`u(`Qe_{XE^3g>4FEZu>cAV?K z$n&ghRbR91CjA$d=(vob{~{CJmV@ZOunXd`e;D;&)V9~^zsTXktN$WDXKD0C^k3v0 z%WH4;S-5(@&eajlI7&SVXOBl;|3&|ut&`J#!8sJpE^tn7d@=0Tp_zpKi@N^J)qhbR z!rAOm(tpvhe#?0JFZyyjt|Y>@i~fs>eU%lQ{>yQx|Ds}@Zk*AN(tnZ9*x!gIqyNG_ zVC7_@|DyKVZ{KYF7xtvpVW`!AQ9rctM??QbLvNGx=#Lfs7x@?Qob^`Ff1&g8I{apd zH9^odv5pISo9npfMyunZ;@^zN({XWnE%+_CO1C)qZN=%eC}V?gsJiS7jdM!?`#p$)Ywe(u#YNyvizazLmM*&BHBTs=3U%T*- z^k4A(!7F_n=)VyD%S3djZKuU zZt!IYC&uBwSe-$K|KjjpV58>nU!=o-0hWrxe{uLP4*!KY{1=D+;_zP_{)@wZariIH z>B%@fnLPAc2zSTfzq}S7#^JvJ>!lhW#^Jv>{1=D+V$K&G{)@wZAxs+jEz#k>95279 zx_UYa96uDe{+dJ6f5G<$Z|rfP|3dgL6VaizolgJd;N5<_ysg!LVGjSr>A%$YKXUjl zF&@eU{*N5~3-Dlo*L}47A36M&$@xEW_%GN~!p{Ktk(kK;k;8w1UHK&ZA36M&L)U+C z_%E=0d<*+Oa`-RDxBnxD|8i*lj~xCB5a$n<|09S0^16H+Is6yKoL?i0m*o5!Ilo3n v%de5ce@T26Ilo4UA5e$?;`|yVJmCBqy|w)sIsBL7<(E=dPe*~b9tHkCI3x}n diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin deleted file mode 100755 index dd56ade8bfbde386a811e935b2ba7e24e9859dc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1671680 zcmeFa3wT_`l_y@^>b`ZW`bxHB2@Dt`$;M!dhi&r0KwOdyw_C`@PngXz6U*R`5W>Se z;$#CZ$(ghyWAli~>?U6(l58itBoH36GkMH^D9cH1w`79>n>=S-LA)}Q>RXyI(4e*p6j06(|+;dXFoUVrcM9!@GVzQI&ckp z*EzrXn`IyS`BhQ&zn^;BuYcNp<6kWLyZ^lANunC6F2_n+V5R+{tf3m(DIKf-!=R8v9=|5@3{VZKl|7F zzkkl+dvCpfeSOkQ6q@^zN_EHMh+D$Pcf1_knqL@Bf>{JAQrXoX@^6 z^yP2de#85(y817l-u~;^r4wKJyVZBy@+Qu)Q{}=22`eUp9 z(|`DfKi%`OFaP+zuFwC|^B?N{^nGJ5er3{^s{Zcwrf1EQROa z)8ADaKJxw#&VScC-v5!Cues?%XRZCvwc}fVC~bUv@(bmY*TaYF4~C5z6w zs_@NY(P3gck42YT=AJe0tas0S_u6;7`<$~1SDZ8N%60SRRW$m8H-G4?kAJZH+N&z! zDqojecWra~_3NAGy|a1V+y(DEcfmR5HqW0s@7yF$3_AJA*!7Hk?&XIsKTK7J@>Jhm zLxB|Q@fgz{#(k|~iZj2MdXjDFyqu&?0hkF($%r2_K3jz51xP?<~rX5+Zum1*>@ z8k776`4nTvZwNR84$S@5e>EXJj%N?Mcy<5y^pnt*^pgcI{kPXig1_lW;a}}*kNvMy z(Dnr4S>Wp*JmRS{4QH7e)T3BBDtNtFsb&A`FowIL8_SD`^?#nk(3ouQsBd0(?Mv(R_Tp3d>!X317;2u@^Qvwg3D zFtu~^)ki%4{5yGHtCD6V^7j5HXFyMNiK|cSEdVadh`quChC$tXx;z1X%!w{fX0#{S zLOd=cc$I$wyqXgM()&C)JMc`_)oJqwf!C>wCu;*Ql?wdM%qKm0R^ZjW2lI|)S@4c$O*g~ zyc_$@mkFQYA=vT`*+dP?a!@?K9R=H#*C3d8*-~HTZox-Y-Yk5_s3Q1pWZ>bj~q+D&@sPWd~*&&hMNh zsXTj@2c6SV2IFF2$Ot*C1<_Bk!1HH!dHGF7_`O>A;EDVuguVEUcL~1g+>U(Un|rB0 zcgFqsV{Y56e(pl%1-|JqlkQDv&kU!62xFm)aaBeiik?9$Bm7ge$5-^ovgww6^gi4! z{S!6!*|1d8HUyoG+7r9hxwH=L(va7jvLVQ$4gQISQym&|gF<$~hCrf>UcdtWe$?B+ zf?8_pyJB92j2u9EQkJ($k#9CUda)}InNB?5%J;?*fj8{6(@Y-0`aP&D}3>h?|%L^5a zDHHH!H=l5niRytn!q7C!s9tAFH#nTA9mScNbK}Mf&o1(K>TEl9Xg&%}{Jx;ei@KQz zzjJ?_Ht6vS0?+(6*Ef3Dg((RceLBf$&15Xot=t7ZR^Hy03g*m2TTTSN`KRMCs+qzZ zF#uWT>O9lcaj?#>*xw0knips;&_hn%%W}c%1TV3&@a4A(-e?aK5oA8eF^TvoXt%@| zHIF#DjlB8=uLHE}#nW*8_carcr|k=#2g5n zA>A%8AGvrwQt-Iyc5RvA=s+|tVti7_A%{cAVGcPg0e5sK#vkCOPGx>}7UaZf%&(oz z{H8OR-*^V|(_briyC-RHlU^p$UxOTsOcamiF^FD?hZ8LibGOKk`? zBfhgvdpW=uOE1p!A>?VreVWrSf9KctSQ+o{DR}*9#>=g{WVu6SOBg3UWO<>3W%?;U z^7@eLJ{$CW$aWvH-G2$=Etc&*WV=7Y0MhX)@iVod4{ag&vA1WLFpys)GiW?S^}gWR z@hi(5q80Icl3)Mq@cB*6`20j$Y8TB(`L){h^}o2Wd`Q;=J@I$gygxmB-Wu>ujUJQ? zI#*3vd%MAt4VVMZK|L?G8Ga7<_(nW0pNx0#lg+Qz$r{i~vO7E(8t`F{S3v%;wn2|= zb@gm|mDdgovUH82d|!3>v_6K&x&wTjj`fQU=oe||7vsiG-BPck72~L`&h{12XQWN@H0F^s=9YA}#ye?b zjg?oFMskDtltC|>26;Rmy4kejCySRBw&bQU^n0wMJ@*eio;o)byfi^aW0xd)w}a7$ zb~QFl7pvF{xdXE`Z~T72Yy377tDb#KZiC$0#&*hWn9tammb#~iHD3+cN%QekcBl8fi;OpQODf%n-`g-xt5Y`wjcCt3b2PsP{i&vG z2%ZA`m!D)zg$o)ubT&J=YR+G-IHb2VQx&ZG0;5GeeD!uALz|1brG)}4Wj#oQm zqZee3gI;hP^a6!>a;lffG_HmxAU^X4q@mHS8VF z5QjGIhrC<0Zkb5h*@*ty-_au)(O*g1s9k3IhF}}?j{|`B6zF(Qmen2Cq_Whu;{kUY z@TNy)*`%h`?dff^(AIlYmfExGoxm4uYeJhGKHFte#}42#3>Cc$|XaMtJp!np}JH<=;1x=Cf4pl=;OztFp$ zv>`Y^>8LYl)9P9H-NZ7D2&pYcZwF|&_CZJ2H4l1C-FTl1{L!xQ?a;ZV(+uB6I6bw| z;?#&b_ETMmZ(`_s@YpKgPirs2xv~9Axz(U;lZMWM_09p{xEf^+piJW~^ds_;o@g=~ zg4NI+soxqG^;kWb`fe4wMp8R%d4W7=?`nN^j@qmK&5iw4;K%*wI}A8Ruq^G6o{Yb# zP18gp(uv=Rw#4%WdKK|~LxlK0mtyM8fw=SxjH7#cbK5SwLlVs@dC0=h!xjdOU4nBU z=Ao(VOOp6V{o0M$WK1PAw|xR$n#eR%SuiM3#f)|mq9UDhIf@RoXYW8i~c2jl0z zLzLTFC9NT-jpcYs0a zX2Dm22K7u>-3YRg)~X6NoXYhtbeBv&^do=pN=plq=Rs;l;M=%;G>0)3rWKFC@3fvb z7acy`fZr*dXg-k6WQr)0;7t0xEn9CUg`mO3)Gr;tt=$)652~86UX`VJAP4=^Ca6EH^4#BV)l*L?gj&`P&RjyxQFNa;jV0~r|J2>tdH#Lw5# zK+aMcpQ$<4u{KU)JxFn3Gvdxd+}*%SW9^0f`Bs#HT}ox+a>$dXJV;}Z!M0paw=4oy zDS-!hXX9HielY()sPO0oBMTV-P44Ed@-;{+p!~2-xz*h{OLP#a?>3!%{cp*hVDE@b|@Pn|HLw_ zD03sqTye)i{-XZxqyA}ClKQ@Qmf;1|-w9mg?lp1%?~v13qE$GobI~W4iEzD2_dRh( zj@B(4{ApBY%XD>f$J)F&>KuX-l>V7#$6uvQf!dW14A;N$tc>CqOXlC)d(?ifpx8G3Kgz^0Rd>?OWW4a@vAQ-g3KVFY~pAcuYM zdhtf^|4k@E{13R%O$cvBoXtNhIq;8wAK}5CaPah#jwX~hO7&zZ{~dt0kKmvj$t>R5 zA;X)2FW^Q96Zj$W770Ecehc0gAWiLb@b|><_d58Lm*Cs{hr_2F=O2yniSrZOOHk)N zJo+BT+qP}sW3oL`Q?91*yo3cmz|29msV5;vrXc;(XW;?PPZHi(XOn!OvLW=-2oIly z2lB$oedy^SwH5kdMDdgdYdMa!0LOZf$9Ci*mB;#&^zLXn_yO~#g^6)b`J=NB$##CS zhMXFd=G(Vf85EuXSZvVR`69?C4p~F^t9#>iAuro~TW~L6YvslS&7B(N|F^6dv_ z!;YI8lGNvYcqqLO>#2UC2YwgPZj$qy`j1^91?nn8HzT<}fccVR?kireMTCcA?&He~ zUUVbgp|g(80M3{z$}NjUI2-tGy3+DKWwB9O6uyqb12S{Z7X-W~z(xp}&^? z_6pk%A@W8fAEAd)zZB8GCFoGlNpi#^G;fd%l6~K$6KpmMbM!|+d)uFG467|Jo%)`A z(e*vy=|kT780Ta=W!E_T<^ZN?ak!99RwOvExrfA;Bds}_&&U?)gHHaZj3Aw<2ps)* zEpU9iC&W&7?YjMLmF*m6=~1j#Xm2N&!ZN|jJ((`>{;~FUXdg&ooJiOVY2Kv$pfc(& zqu=|nb}q~{Tp$$GE~E>ryTqrl#{}KT{jT#kY>d&1Ivc|7)eu5Qqdq~KKtJeAIwPVr zIbXvrY0&P+Vtpju*Gt7~3hI;mD}%BW@4XUi>JR?_XaF4jS5W@9uxlpeFUI;bhw(ZF zy}|N|0^d&_giU@>`pv_h&vtlz%6NXZ&MRX4_hCIRrefZ2T_yy^f8DIWC%IpMOqfU) z8ZT5&pIz^3)`q>*=Q}5hHozv_pNE`o!(LI_!y}>%dqr)qF%oUgSk&d6(b1A)xm}Zf zl2W`4c1Gegf_3$dUU3HCT%%@6>UVnoik>0czAL<+$QJS39O%55%g)%c4K!?nJZeKfx1ryj|35nWVf35L2ix%TqfE3} z-Pr_lfD6SR>92Si_#5(|)Y2t*2DW(YTZA)6PC%zY$YAH-GVsg|W|Ep6_!L*X0pptF z1LC6_jVR(>{WY`s`T&p1E-z}C2AlJBvITw7!i?7nnzbUFfp7-GnFwbhe3tfv^;$_X zMnDc1Hx0=$Fr0lL z_z~9MRwo9}*?B-+Cr3e_5cn0-%LU1jBKFke^cv5~CTc4Wd>^#+K|?={y-wsm)_WPW zo>dcgr{Osr&ulz>M0eWfI1PRO24J2H7}N2bf~OfzC)(N%coOhPSEu#~(4m0+mt)nP zz>oui)yd((VIx%oSwE z@YPQx*-U7R9;v?w{yN}FH0SyX`9^4bH2f2s3170i*#5@cG79_z`knMr>iYuvz8`&0 z@~S`S`_sV(kYUs&jyBQym^VlfwWmd?eucRB1d@|jlOm6rjP+8-7bVqGL>O+`Df0$% zEkX`iYRE2!zbs^W67AX zV+`Y!@+5pRZp=WI9B#}^9H$e<%EU2};7a{(c?^AbIKI-b|Bzg%Z2$N%03D`6&LnM1 zaIdVlvQFY{;$;CoqWVWQ&b+Y0<6!05>6mN2#RKAR;%A?&%~9W#K*y`;d{>Su4*(B| zaWa55Gwi{Y!K-A4EYC9dt=NF-&e6D`eF6qM8R-^e?}jd&k>KNgl2zbQS59TrO+28o z3jM0HH9qMmeSketKOwyZ`mxnliEr7JJO~j-1L#7_|VPrutyLsA#{E9 z0QPU&Xg*t$Ge6lF>|HpNqd7rO-4OU~2Jx`1^P$`l*hUK@?HSVJ`sX{Hvk&{vr>2$N zr+yl;FBiYJ#9?b3{S3}UVGfOk9M zChE@udQky;<^}EaqDmdvo|lUC>)Qdp3*|%LIEE*J?JF|PwvQv=z-L@8NC)qljXGd2 z3xI2vdL~C@_OwnDIjo~dZsm|KXS$`$Yw>#k_`!Yxn>6A09QLX8`+4vr=6yP&K>AK` z(;BJ47bHihPsxr(wmP!A^_>Mf590a!-W>6RwXvaYN-JaD%RkYRBU_u0AkLXx`;WE0LWI;Zfl~q{qXD4bj41p)Gu>+u%$}5%}=)x^RxDS@6!*Tqoi?v8Eb0 z+3?P0ykm__=TGd}tFo}RKC&eW;9Q1XP+)En7>`yaVEz%vuO#gMXk-84lwDgi6xSX+ zbD8i2Y&OfsnO{LyQ2G+xM78Dh+kojy-zo6?LI zFgES^4!l!%GR1M|Q+S^q$5FoiIPR2+xN;oVToGrkyfqL$%7cHCGau@7hjRp6$$o0r z(pX#4*iXY;{V#YF*;Hmi_i2T0uwt$#wk{Ciie?eD&Jkm+DmyxC(&5U<_u|q| zD;a)EF}61TO>6XB(0O7wqw{rU3~O4dXW%8B30KZV{sk4~WB74-+P}7WQ7!}yHZSU? zH4xQLeChYLXZ?p^n|~O4Uw9XI7kFQ?sXbeZ_gcJf#d{sz>+nwP8^athmTu4PLAYnc zq=R1AB?vctrQJJFunm`xK1S!rYLJie^dJw~nbX3{!}dpbmE$}j&O>sDU?pXf_@wMu zhshA`1cPkwwoc%jd&s0^&8AGSs6E@Y+oW@_)9#I7*Cq7>?!_46n;|pk9LwE}I!oYt%**-Lu;aDJhUd7xJHm#dvz$k8M2k^mqT&*`8fQ`I2?|{FT~;YI2??_ z9S9%&HO|5S#>F$C&&@VCqtq=(cgaCl?*=cP483F+;a1Eub>Oq<`27ripMr2Ec(NHG z=`WO@^42kzhtesH_BFO{V~{5gcoFOv{8pCcShI4n;bF~+wF~SFHEth34NJ1^Svj~H za~jGXZeM`LEX{9Q|H?>?@g6Pg&e7gMvTsmnw_veeKR%8zjx}+#i`n()5pjd8CfuHY zoOyJ)u{Nm?a^L(CvJaup9`s6RlfQ+fS2U<>|2CE;x!Z}fQG}IsQhUkXQQ79D^Nl^f zFo66VeMdZ+=Lba=i#E%N#U zauj;}DD-$AdVF86P8ZYlLg2hs=iNqj!tO`wn?Bguh_)r1`|X^s?0JL|;w1RC*gIFy z-YKQ`*>tz}R_f7$%KBIn$`?R4GuUK$QYj3cMXCFo({o{;S*js8_JHti00;Gm0;t$ucIjYf^~2gW_4NgKxgg zu77P>Bg^PsGfCEBPvk@H{8vH@w!Kdyn^L*-Do` zYG;`QmRauNLcnzA4ws3925ecJR>Lyt68B!jyMOjZ+}~}LTRzRw{@L0SYnk2Sm=T}d zN$&P1XBn_hH12M%NwGMN8^{^&_g`9RT%y#o}~m+ z@3b(MH>!+TZYC91DzSBw$}W9I3rZ)LA@*Y|jMy$t>$k2yvvJ&Ul^G+~Oj@n}BgRxbdq6FK_?AYeGYSMQ$;1Ujo z(mI5~8Eb08Qk;WL(u-$f499JJ6nkB^jVMFqic=N~7hZIb4ji`LKJ+QYvss7wm1yLn zAF2G+IA3hO!h?O-9}98jjxScyo+qYri8x=E-0|F3aX#6+kPUKb5Z|c4c5$1NPh{H* z!4s-wL-2Tt@w@OIW|-}d=v>eq@+=?!h7DHm1+eYnj%-OALEi-s-(QoXGv~MzsrBar-|d<)1$bb%W=1< z5W_Dw6HhoC!xp#a%kS=Sa;u|9CTT_Bn!NM(9C{Bc-isCQQN?=^ZD$xiN%v&S+z)tPx6jS$JxISV<|}s-+L$@uXv9t-iwv*7?V_%pJe#*RTv+O zK$G4Ui(^P}Bx{gf#5*KbPzyZgOvZTnXgsf*ig_J*%|B=D9fRnR=A8b;t#;0)xkUZM z#fO-`X{?3~?~B9B56v&nxjZBv&C9o1*!A9&{q8wDN!zmhhXf%`O`i4 z9z_oK(W#vJ`gmSZ-*EL8*Ryo=(jA$c?v{HV!VBlfX7K%E&=tBM zhekIkF$r@>V4kz*+AMzaXfMj)rhe}3NLIE%rg49EJ4<(>oW$HyP7NKlJ$bZMbQn92 zBy*l^m-_M%+J*D$kR#^4tQ|{7YKNNG4(K^aJ0=02KtFHWQU=YEc9^&w?5S+91-!4y zj#eux&W`&B-1$OvzZ*M#2Is4Z&gor~{B*nRFF&m(nW32OIKxAFlo@otRUFnrry#jO zdKuMkUW6RL{&MF6&4Y8nd#Jy7J>)#bw!Qa&u@xdckMvS%x$u#vbi?(+@^nK6a}(|v z?!vu@3&7);gG%*(Ch|UoU7~b8;#%>YsFwGMJkm?4Zox-{7oCW+Pk8L_@8G-x)l2Yc z?jOTlV&K4y@H$cN#faaGvz|HR*}VRGk^6SRdye#_leqo%*5fn!mCH-qo-lv+AP1m58@amE7ckvz>a*jM+Vn{mi9 zPIuJK)I7wx)~>@)hVJ6A_qzKqycPK|mr{M^DyQQ|;A`9uz_~G`;htI%Wr}o93B1im zHc9&Cl+BN^N^>7?xR&k}*g22JFRdFm?z5S-F+74rx=FnDCzuoG#K?}TcnuTd!30avywBCoJMw}Ze8+r=G!D32 z36JV16Yk%Oe>b8|!X0PI#$2!T50-a6Xk|{-C=?R6mPt0fd{1 z*Z#a?JZ=hd!{VlJKWn`agl~wx;O0xPSD^o?KZc!sgyaZ+I;N4?DaF&6`%qs$&P9e2 zXK#>h3Nbwl=8Lq#UB~RP%ZI_PQeDc!4O%Gq6_ zp;RVMJPY0~LJuig{@o!3weP$bU##;&)NK~H-|GC>X4BCn^tmxS$`?R4GuUK$QYj3REdjr9hPeRSHxoP^CbX0#yoB zDNv$`?R4GuUK$QZ&PYT@hk@>%q|4WoVI=XKI|CjIo;D*m0iw+apS@nN;^lpE< zq^9saPli4J)E~S5%P0N_{9k_ijr+eeZ`A+g-=(VlFGmjJ|MI@rU*c2Do_{%-ACjv7 zOZZo*^j8<3?d^ozdCT~}yz_PVzub~~Tl&A;Tkgg8pVl1P|K-o!S-rQM|I1q(-QUXo zFZEZQ98mw&g^7QA%kPt*F- ze7x#Uv+7UtxAUi|YvZ-so9s{19KoL^eS0%s)Q9)0nR0ji{9YqUZzJED^qu?M%7T|` zV7T<_{ADuuwWIG`CwCv|{)~=&U`Dv}9??A+d{3C}$gm5YpGe-@EK0ZoeKF$bZYrfw zXnks~`AUxN1pO{PGWC07f0WAIAtW3Wd|T3;7=tvj*B$g{iMv;?$491uZ%bRg!tW)E zePQYeelPXA;`(DBO}74b#^sS#SwDS~^>_7=$rk)^`^e&s{h8m3H}>#$Bp>lu>Knx9IsgajrH#Rb^C8TVS@k0 zsYmeNc-&$9H^N_Igm01@^xt@EEHgn@^53Yw?r_$RxR9X@G$vlR|3>%+l(@%T0K8-R zZ`>E(H8bdk*XzGA_TzWZf8z}fe~J3kKe%_+J<p=$J=yQGlD;fasC^--opMHzkhW9jR)I>JI(C7vH!+} zZcNzwv5={BKQ=`8TlsIinp^+w_mcm{1+o9e*uM&R?UsBj!u$zi%GFUt^EM?@ja9 zc!6uzM1M1HWq*zAS%uD|_L`rFI7VxU5jwV1~-# zI}K@nlS%J|4p2J-{#=F;zo;^vAs&8RUPAm8E}qsRR3_Neo(i=@0ztZu(|Em5kS=-_LUy^N~d`wpQA0)q-6a8PZ(|-T{FHP0|DCtZ#laE zOPZ0%cWd-J_`o!O;`He^+Xp6t-@`ZJ1Jf-1?R;Re3Llud>H{v+-EI70KpC z-}WOPo-|J;zWlU+&t%w^{25H_VQXap-+5(qJmBz)s`1VC+U+K7{i>o&z60O6rubUS zNh_rw-=UQ5&&Y^9_)cIK%F-HKeA=Y(g+0KKg1#eO`!MD40e^fRSdx*aQIKC~n`co* zB;~0rLwZQ*R1d*e4MU>pnY33g3$=E9dtUJ@O{gxyhsyekSOq>zFytY+ zP##NfeAAcmk^fc+U#z)adM_?W;xD1CbodsdtcdXGMB(nR|@ z_*|v33{MIEG|5+Jlxol7`=)6QcpUJ^CP8)lA^)oWFaMC#uhw0qK$QYj3REdjr9hPe zRSHxoP^CbX0#yoBDNv=r>!ZLN@-y%wx9{0X2XTK|`3i`!F3{99VzGsgM9WVgGt-;4jtzj*umzhoailHazf|I4cX z%h+FLg>TFMr~WV3#`C(NeUR9%b=CjnVf|m~RyS_nZ2y<_Q@gzSh8|HrH9)w_hJPrZ zm@4*x8MZo~n2G<(LdNkW`ORdHz6m}t*)z^3Cj9>LyD!HkR-Na=?=O7U3Lk!dtzW@E zu&+%0$nV!zrvB^kzB2XS{BiioWMBS&=POe^>3n7C?;P1zrvCELePyyQjQ5qv{?h%{ zpLgLOi?2+0#2e=;)4c5NGu2mpWxl?J@W0bs9A_u;c>bvUUrs%W|I6dv9RHW<`0@TP z72v+9{x9Lf()#dx1O6}R%+4RH|4TYQL+5R*|H}?-{a+^Mn=0?xve*wM`D>;7$$DXY z-}5MbFx3P>Id`RsYtChyGns71*#ONQlLtK zDg~+(s8XOxfhq;66sS_5N`Wc`suZYFph|%%1*#ONQlLtKDg~+(s8XOxfj<}puG(-- zh5yUzn7jvw7a!1@Am}!8zwP&!0Q*+$2v7I{C@iWX3-C^23)Orm91Es&7Z9fKi@;e*(&+ zYTUVZTLAGUiI2Y_Yvbd8>Xl@#zv6ow8Rg-YieMRr(AcoCth}aCu}(sjn-I(5yL9nJ|Jly}#4HZE(J zpL{1|Rfc7zG;6N`^-N~BdnW5}&@nDaK8EyNS;nc3@50~CNX2^x>lUf^cpmsI!$v-0 z>-g@!7Bf@5ROT~(j=1=nB=z_<&y*E4sEcJ%`1Vz*(WDhVhr*WC9Qtm_vPB;I7oAo5 zg&eBFpQGRSvV-W8xZDx)+oIKfRSHxoP^CbX0#yoBDNv$`?R4GuUK$QYj3LJ$3 zSIwK>eKZ5uvFtol{wUxXdmGrl248*V|34NTCbsifbgA0Ej>;8p%|zIZ-ZcByjEg*t z57@F9uoazo5#ZweOuUng>%9mUUIZJG&M^H|XS<^K_BfqFp(wAgc`IyK<84D#yV6^e zk*Zi#DNv$`?R4GuUK$QYj3REdjr9hPeRSLY-C@}uq)A+MrgzF(Y&*3qjcrNNS zxz@iX<}DRL=f5UDaMy*$qQk^?9*Zu&cl+1%)$?C(gt1br$J(S)jMXZJ(^h_$$7*1A zqCY?IPS{uQ^v7B7j#2^nUdNyB&SoV!^>321VM)yRP&Fp`>FkqY?D!1lVC?nKUwh7f9uYFZNm4zuJ*O3{%0y^djjzc-@f_5Bc3|baF(I7 zSc;{ig4c`lTO5v~-m45~P!s51!d}2s;oIfN-nzu{!ZyN)uqh_JzyBBLYWg+0; z+!@7vPPgS2p)LbIV>ZvCE^pEKN-hde)4t}M{*}wO`vlDwnL+tEeY!pOwFzbDn?1J7 zlfp~gL}%7CFmZ9zhI^5R{QzwMZKw@|xBi)*`Z`#O@EUf==9LuN|Tzmobh~^eq zzRL)G>&Jt_3BVO_3ukK1{&`~{(Ek3pSF@MPHKjlSBPWAXXAIX~?2%o8d5UA5-; zJ8FcJK)VVJIxD8$XX_00Y{~nYrJ04kTlRF0_clwmVnc8u`V`RCus z`&yMWE0MSNM>zv}s!LoSioFHEWf`$oc)&2Idry}qz>hi6<;jfpBwL8bg&@wjKLK9N zi2&(+o}3*VJlkjU2Z7hAj3;XYFO>@X&deu0c~;=ny$AV@XBJ1tZ;X{+-Q)>9BxP9e z26`up(ixh|kxOKuL1mIW&(Sx-ccp?40~fu|l^3~!C+^guACJfhyc@h5`_7l)6Oeca zw!8!R(DzbbXJN_8ZK%f)3gzxo>CP{rTsz8P+=~vBWy9WB%6K^i z7^)J6adc^^@n2hJ`(exY?3134K7!LW8;Uv1KfaCmKHKE^vueEV)*3$rcnKXlsV{>% zZ*-R7@>Ih|Yw-JYykCy6CGf6q3H$-%>4cwUIvYxTNo5CS8qV*WC8<1nmIs~FQ3m5; zV8{qLtOe0evcU6acX|0uM)%~fdSNf* z9LM+rOeQ~O``lmL<@pVhMIL(-VmZd%MHqt$aUES=saK`_UY7B}v*W&JOiY$$lTt>t$(@6?v2qC{H2vAJQ`BSB}1=oZ)`DC+i1>Q+sqBXoC0BdGt*_U(ESH zucrqb-9wDa5P5iO9{r0xdy)r|8LxDn;kB`>;plU|7&2%^mlrBJS8D>^?B)}WGEqHn zM;MxB8P)4-=>~@rps*~@x;hTl z`4#&+flc#*ozI4xyqD#I*9l%?W%ykDR>2#^_iQ7`e3D}l@l()li7{#(adaDb^$T7H zXxEFU<9vj8I*vDdgdU8=k+b37d^+Zv)3iuW54^O&+^U3EGnYclfzTP!?eNnGxD?Mv z3LaPS`SDgq2cmfq~Y~owfO!c;`=ECfAVy<@E=E82=5AbeKucQ4!km2t8pHEL$Dd~opsvF0mfK*ai$L; zPb==zJcc> zJukNzehzr|Mm#T{jCb&m&9BzU8qi9zJ3JX0@LrEsK>o3|LCGkKA2D4J|SPjQg8R<>0%LRT?1Vs4gQwEO`0oZ8uOXuZ-gW8L0SVH!~O;@cYv4E zu};weogxjLV%&JCTk3VRV(iq_*}fuLj#@vy{e3H)Acqfglu`-I%NLEmvGU#H{ zAcN;aADedkWbx9%mfSRkevkFC=l-F`Q|G3FmoOJq>SgAVMAvpO8qu!Crs-l8dm(oK zK2{sQU+@~g&BUr_ACuc4>$b6-avSC_b|&VXnHz$p(==}aEt}A;%kZ7e%bGqRni}f7 zrZY8P4S7j(@KkoE_q~gZH+4%Y-H6}YFgL4HHw2An&pmTAzX$!PrfdkF0{qXY=Ow{u zh<3>RNNZfDvKCg8&aO5;%GtUA?*QO6{b?$_>O#QGF3vPgsq>CkJ7l95WR8O_a2#|2 z^4&Yt%VZi?$1sjqzQdMp^t{YxPSyN4H6)uxhP_Kc^CmOwHSHSqj%SEN8}~!Tty;HC zB<*ZOf9>z+5sm1tq;1qLGkrs_4LZjGzS@llfi?%hPO%9*!vZ-SS@EHaUJ3NIxZED})9nkCKev~^dSn7Qyn-ber zZ;kmvF^jJOzS$$=OMR2zyb3sL^a0`A1e}}9kX+rQGELC24xnG?T~FE&9H4a6nY3y3 zEd0iOmqvutmZP@=G+g_jqwAUny{2xw&jtQy*Z6kmT+?ZWZzG(Z+GufVL>>F7F2px6 z^gVcN74WC^7UA63{-xY%(6&iKPr(}J0B~H5G6ztmaTod#c}X`k@SVIG`XcpP1#`qi~eg zHmq9?V4b8eFS3R@UqJp88m5ba{%KC&Tlf;+z|Wzt0`RzE3!xh=^vOqcE%XTL2Z8V8 zOMD+chd!i!2!c8flFZIQA_X}g?)C(SPH>d97R^y*^p*HLbkD`KcDnP>?+a;tPqGnz zbq=n-vEW50!&|QxeV@YmV59JStiehe>jbQ`LiBHO7uLl1D`_qIiY~s-@Adq&@yg(9 z%EQ0aoC`C6gS7<5x-CzzmZSb zf!bJ(*OKLU9Z9sN{6}kl(!K)L82zTj^7oW@?Ji)~5ZUcgqh4Bz`rj--r)Y*>bI_ok z39B1HHq!c3!ERHz=7sK(>4$#g4_;|$p$pu8N7%;gqd5%U15PU*f!}EjufxNq8}K`& z6U_(GnM@I75}Zk=r!?!+2{gEv`lSQ7wfkc1K~*!>tFkl?+0D&b8&2#;Vf_-Ut5ogbIK;1Eo9o{Q5+tAwe~jq67`#oPMd6PHI? zW!?d_sq>-RK_ka|WakLcHu7g)z6*Q`dq)IaJcRyJ#1ldfFX9QIhjWaN2yyI!SjRsf z_6Yd0*8$d*fH8U|e(OQI&f|}PR=P!UVy=Am~c@qK_v~Gu-P|UxD@)r)|zg)6f(l{ z?gLt=7hM|h#lRwM$BsmOWB7gXr|-zgO?SW?<7{FYy7L&>o@|Kx6U(%s%#A2>#T^Iv zi~7Hh`lnS%>ignZh8IwOCvcIw*T@09Lr!OjR^hPDMW0+I!u2ZM_rx7JTDNfUr==PA zlG;eTO8i86c0c-x=9lOU^ci53KBL*7@j?VT??Kx&*OXT$RFW12OmZCD#N3} zoPq3#cC}}C8|)QGD^4|>BY%XD>f$J)F&>KuX-;$jn-{6Td@nHH?>4SDY z#uM{k9|a$jq4yTeuw+@tUgG=Iu*^?G9;|bV$fs*IS{qJ&8p`9j7dYyT%-V_OG-;1; z)weM#4~QQ9Cj*x+xc)agp&jnBAVWdr%$$ zTL{@dl66jWm&%R~VeBfbNzDVE{{Q0dvK#cnipgRrwb$l%>!&<^mxkgpYfwf#;Hhu8 zGIOSB@54yf>mB}7Hyd^D?BbMdQ-pNh{!H%Rx8|u{z+ivvU`TVjU4MyY#18_WzjE=q zZesZ@E+3T#-t3_`A9RU>unlPYfEN(_68fT)(vu|mXw*EL8wDP+z9?p8H4pY;#xbnziAJI_UawN~14BTw5gNd4X4;EPVIEl7Urog0Jj6!0fx z7&qOr%s_kikmGE~&Z~A_0enGuP;c1oY#-*ku0M;24{h0XvWPGOzI~9xK6t%&Bl!O& zlp+2H+~_8RHzUsGAC?^WN5GHpFi$vmYQLii<&9E3S;~J0;O!$gC`U4jw|2uZ<(|BIOf*)Y!AbZr4kRwx&{^_&u0OuzOZ>+OPK2X^Z`e}rR&%y(FVdXyb z^pM&L{V<|<%7e8W$6A16y~tzRagoYneM)+FG#&hadDFtgxTpNl*@t91KUqUgVLX55 zHY2!C~N+%DubyKf8b1#GR{n4r0nqaBtP5ZXG)9*e#V(cjdk z9Jtdw8G$zjW`YNev*+mL4ld0l`aBkV8F0;N7gq#af%)&VYkEDJOG&={;B44#Q$v#a zyblkh_hCKNPxQd=BHB%Io>Tv^E2KbOW$0!k_XjXva?E|j>$QmRaLj#tdBKZr#5;7> z(HX!Qb49sju?S}a-%VFq-lsg}b|nPhms>X2yaXq_DTV>Px%g3nX#|JvOn4W~p#1Ez zUhfBuy|B|_%)+Ky#C$+~+tBnWo<5c*ab1aX$3d(%)WT`yoW$ zh~y)5F6x&e`nLof3OY%Sc!cH+vOBWxyL5uhW?_#0C}?l{(~V)Z#idi+~ zTOZ@x+Dor-_{{-K)8cR;ovcW3U}q1BFGpH)G@p_E(+8dWPZ>cvQxQ1&@mk>ccpu1| z?%H+x-74ET%+jM+uh4!@Fok7;mwPf@;QeFm=g{7d#5j?#8A3t?v%2qyGxZ{}y)5r2NHLpXM-L$DlV@UQyut z$%C-N4@$pz*z?&A&rcc8&(?WGjQ>8Y=fzaa`>o4_!1%A575F6g3y=vD=|ba$>gluV zea+gifBJmqWYGrLg!}W5({0!vYI}G@v|)d!4K_xi%^8cjyfZplaxAxN(oa%~x53Ux zyhgCD-q9=00Gw;oOiBGt?_bd~WZQRz_Y>J7o|^-m7jxMeyPBo>rQKk`8wHxeraLGYX$vU5zat31K~`BGZ8*Zd%}9HBzYqslZ%^% zWEnE2A7hO|ec6U!3Wxo#fPLq~q?7HD(#bYM?KSsdd}7b;_0&ta9<6SJeQAQN+Yev2 zKG~(y8i?v{sp;}s@yx(86VIuqb$KgQs|-QkBHHqKdG*?9Vh?zHD|8v6bXz&sf+rsFvUPcxoQw6!1bB;b+WPVEz*Ljij+$ErKYHxXtY zFcTatyy=U)f_VXZe2`VC-5J_53{8#^8!PQr#-3RQLE6AqdtDj1; zpU`+cQhyQrb-3{f&8M6!;1BJL#y@_XYHQKl+|zSAWv? zr-Kh5&!|ltZKAa@Z;&EtPm5Ch3UToXBr~x-MIJR7Yp0GcN~))bFx<3L<_+dugdB2} z{6-NCvXGM=o;03Gcxv$E!B-{V)DJw&oDD%?j^Ufp2RY+(l|KAdvt9hea(&oSAU&DR zP0(7I&V*3;hT@=Hsb0v9q0OaP=ug-H3)qv(cjz49Y+!GqbuP(fDxZTa&$R^J9^?s%a#rk-%$bm+|6qPyj`&#L6bKhbj+%)#psZNsFRwo1vICv%m&y@c04)Dn<9?!rZ z=X#x1FK!HYrp`;ot{t=bwPTj}BI!HTSVo?6b8w>bnx?cr~5R7~s~vqP}@+;Gb_G z7oo49ZI%2NrA!8WDoFnip+9i-TAe|}vV(Mo0`*JHRdS`7CDljVoIC(LB*w`A+RU&Y zR|c<=O|m@8;J0D}syj#HhV~2?Y-XfqknJ0Kbw+}Z`$<-TM_oCU(Ko{P9Lg&6tIpQ= zq_6Y=_C#HUbQtK$R(B=7RafvJL>!F=(o?7`%?G5Xk_;I|pX!_Ll!a!X(*EsV5hNT=(c@AS_;>_wlNR(8+&X~@1@ z{N56Wt#SC{inJMV+%pw%Gvl~_isSN-0ev?aIf}5MxLuB-ZV9{%Y=fI$>JYSFK<%Np zPPC!cH)Vb*u3hSx z9F^JAI!)xTrXsnOL%y8pmNu`&?*ZWVfJe4y!tpumS(`uO!IPNx>AV8zJH<_Fqy}G* z9HBlXn;O~e$OhMU7HmF<=kt55FJWtML*0~C#=Mt*q9;doH?#lNU;yweKd`5BCBUJ1 zmm{r2HaCPvh5wKq4S@QD`<&ZHE94?nL9=ZKmG?`+L=BEA#rtAUdZ?`+09 z*2{GM#Gbt>3v2fyyP^QjW!MM><|cvhXk`NCAA$T@U@rh|>|dO+>x_ot+Jk2<6P|$m z#@cV8A7yEOaI{_tqE(n~mr!`E?JzW_%5n?K7}&%K--c*s%u{W$2zqrsvDDJpwq>rf zqleHrsSK@mLi2RamIwS0<+-`f!Y-p8jxoa@y(UNFh3u9g#thl)^K`Z;&3FN0)1LLf zJB24x9EU!I_vvvQiFL)H$S7t)@X@zdEVy-B*E)e00W)Zc{5o4_?J34IA;mXPQeWDoaaKDQy8GcJK zwl@Av>-AmGd15%D^L1tn>szX4;3b_2SI$NL1r_CE_;GpK%eHw@E(8uXFY2cC5YG!s0{fA+ve;E5rcAJ?J=?Y0q;s&@?u}vBCG`XD#Tet8Av5Sq%iWDSOYLX@f1M2Z zKOG^hiB7>oYoca6v?iLkMvz*2btu0XvXyL^Lvi@|IQ+{v9FD^;#NqZh9E`&q2p|15 z&cy)6#WSJL%{Dl%)GbJN$w61|1}~lry<`~SR?IVX;IrxY{S1Def^a5yvKb-iFO;A1 z)-jid(kYGhIJRzMkS7m#5o{X#R+i>izjCtYVf~7=3v3QGZcjiBOS1D>Ik+2h8p{*5Zkm8lQvAogZY_^Gk~XM6jqCk0caANIr?YR#JNu6=kG}lKdCZ@ov|XV^6dDwjhC1#NLO{+GCf-@Ggtt!7gXd!&9Ajm%rh)_6&TyKg(9S{82m0B(ThK z7Z(DiJA=4PBs5^l;+e-qp27Vs#^_7 zeU58Ci$lU8!IiTeGW21ati<{Cyb}zRqqbQ3U~CnqD8V)}JGMElo%EdzxP*hDv<{(g z-kRF56lY?S^y1kV!*LrQ#a@?fBg#;@;*`b0g%=&91Bb1*4}D7UY}TQEB^vqYM=F0c z&Kk3?@L(VI$3mRH$a@H90zejtfHmk~klw@2yV@ z-f)r4Qwx3~8j>6;;QS3Pcpj2ZA9V7mGL7Tz)84zT6&&}QIPO3_io3cT_nZnb{Bkq# zgu^jxaeKb}?j9$%I(lT1Rs^oeJAcoi_psuFQT4<^%EVCUap@k zLZVTO3l3@EZWDgfK0d-Ee?Q(6+U&)>Av#aO2_D(SA(QOBFP#BeA-sOE8Mb=w$B;WPO}nE!8g;9OqGspf&yGxPz47m*5lj zLjFhw|}?_o(8%Sow}INoDy-hA&@*@v#Ur>20w% zh7?D#2I)n-Lt+KBz;n)IjHi#r^SY^+*OAx!bJpJ7iXLgs>0jJx=WLow)K6S|i20kw zYS{3;IK2GO{PLX3L-NtQe5;iW=6}a=fWeaY6`i&$Z&)Qv3*<@brB)VOS^I2U59LqZ zsSjhBVxBpa?(j(PSrOy2%I3BA+;Pq@BDs&fMS@M|TMxoP8w#X1Oi|ea=Dotn&>x^* z>?K}{>#7B>S$TMh8@KH5C43L-OdyjyB6d z`-B(E^(TrDyiBy?#7D0dJ&toq<$AOM#A zuNFSexRmP~MRYpKw;U(<>_g+TjPa}=cesSDNbi{}^gj3dAbjLekGVJ>yh8O5Odt1G zl6R5^MJiw4Abgx3<_!vAovoKs{DV3h>Zk4b0e^9@O{S_%uE{BI;?7{idJ@__74tLY3 zocj8BUQyq0^%vK(boA04nVjyHdmh7?p!RN*?Uwo%8-uzZX|Wl6{}^b)58n{n1Nhdi6tUoUdsE_lyj%&?QV{r1-8yS3A?WGv5Pn$bBT-{4NfBRC6- z_vi-0`Fb}85Z$VORSF!70=yY~kEhhqDI)L=pNTUTSdZjsp25Dl58aGIo^iUbcBbYb z*0pvWhB9<75B@3aT}0lB{FqCrK691R@gwjx?g!x97}9WOt%x#3y0Zk{<|CV={pJ+q z$5^Ggk2hRP_X_NsM{%@n;JDjn*2eG%7U?GO+Mi%foD(BEuHrRJjE`!>89amWfwbbj z@oBn&2mSj{H`+`0!|2SUzY6y~T9pXZmD2AJo_U|EpLgU1JNSHAn1_2R_qelq z6j%MLQlLtKDh2*8d+!2YS5@bIuXA$F+H37|(l&>y<(8!7B84^yAW|Jz3DE2l3UZMd z#>aPP0s<-&tmxFa(3ODZoKywzGmrD=%tKpb=6OX$Vcxks&NE#tIyomTf;gk2^HE`R zZt4fH-sXMBvG4D{);{S;nlufx^x{9C&(7L=?REX_b>I7}FDt+bumY?AE5Hh{0;~Wl zzzVPetN<&(3a|pK04u->umY?AE5Hh{0<6HRsldDM=)Q3e%W?kvOZeY+a*qK1<&C$k z|M*-wOwZ>Y&1TL%^Dk%C<#4mjU~f->cmA2flz(aeEZuj)e-CINAAJ`HGv#8M&rZEh z--OM?zZBp&9_jo`_obK5zjQB?e`)_F!~Dzbd-E^FXHs6`*M$H6WnWAZ=3j!f(#)<) zzwI4BT|Hd*m*RoB`IqiPnOBv6X;)%T;Tx@VeSv=|UKh$5eK$CUZ@d%eN9@eG_?J)B zN3j3XnmPHG?q{JbJ>2-0=Dk7p!w__qGo z<81zf{<5U&-*~^!*W>!Q_m~24`i^_#{=#p(e-Z3N?lDiiJ zVYVi-HRs3Hw5?%`q7N`z)6K%xq`fzjQ9CnZGZTL6r$(Hv9YLH;+ULG-U0D`N0zdi< z>`Vd19qn@+)@p>H-_O`pfeks1-@K30?_{u_F#SeGTpsMBk#=3fZ=kP$9sM?y?vd&F znrl8?7{@sB74b4JPI;9k^!Jno1I{J=CdT0&7MAAE%S;)VZsndZMasY=K4x>6_H}9e zDX+=Le?b~Q?lrrmJy~BdFLUM5&C87NyHnaLo__O0`=ZnS?EW{d7*E6)KM?y1Oo9W- zc%(g=4=BsAGL_|M@f$ZP2Q#r8>34cmR*B{4+QRw%vK-B8rm`H(i8Het-SIQ99KmiJ z$DSmUEXUtZ+f39)VmX?>3Td`mgGs;Bqjc^s%Ta(87~^-`WrQ~u%h5fP{?^RlIqWCP z(LNRYOtKu`71AFgKJ%?`E(WKw7*l4Wq2IcL2MOLEJ(uY$M>ihqUB`6)Q(2DYOTnGR zZ}^&jn@1eWSBvH7zVPx`j^YR5cYdR%;Wy&=?RVr}8Ou@pO9;>YYtUr;0J9v$b7}a` zhw$fOIf`$k?!TR;X9kv|do+}7TFV#*PhtwoarNQLa&+I=H_LG{U-(V4_zZUW}oi}qhvm3=fhcsJeHy#n}#@3}p*$R%!Q`dCqR`6Dy0>`Cw2{lxGuY3e^aohxd{0w-rJimf~`^nTV*v^C1l^) zGMsO=FT%bEyJjW}xx3Q4r;)(X^EZlhIJK1azj$T*OM95`FU4oke_^MijKmFL(j4KdZq^ z#@dovBJ@r%6qm8jt5^^fBXChI_H1u`*kwIe6@HRF>~l@_t>}}ki#4%B>AqT$(>t+G z;A;4#Ik^6)%VLK;gb{1nN4)h3a-$IbR5w^jhMQwGaiP7NOLMy6pZp5k@2C3|4~225 zYPx@{7J0gVs-}A%LjFE9e2d?E5zONpab4Yi%3>?h)Q|HIebr=J!MmlrC&=ql*n^PH z$2Z%&-&e2C=EtwGdDV%7v@k*wiDw@(Gw16AZh1__(v8OM&BYtZP z7HeSydx1lr2y^XmyeB25;)gGFU`*gWDDAz7cUFH{D zp6ShFf75J)@FIjqYZ4U4q5Nb1<)Kuc<7Nd|0akz&U700GOEKyMc)b z?r-$qTk*TV1yX_g3wEtm;Qo59;2~yZ+O4lHE7Sh@R92?_i=%^;DIPtDtjw>btjxci zot0@H-8U;!JT#S+DgI};wtpPVqlT54o5srgariw`8?!R^ZzB9F>MFvw6A6x^nSUux zoSlDZjz2*B%M+&YFA?s6 zUMu}R*j-(nSUA2#J}90@)Exi zejmd8%NGku+$WW|1PAt1f~n6I>V#!NDRBhwFCWwP9)8xhREWd5Z*Y5SVOo;~d>rVtM8u@NU< zwp#Y|ua+mDut@K^q@!@MxHA^%K78N**03}e&5wV%FXp8Z1 zTGDS?OkeoDH?bw{CBaVg2D=>}xmriPTKfG$%$E2H%u%C0?XrZnU|)CgJ~~J{ZHdy9tgIjdE?Q|wp1Erao2EO zfzM4ktEem!uwyItp&mwB*09b{7+I_1(mmSmC)|cI)NON7=bQCF$>w!}dRxYUXIy*G z>e1JL;dZUjw8t^ZHr)N5Zn&}I;aP?_9OA%+!-%6X4vU^f+z4k}bi~Q2VBe*C4p$JS za+~5vg?iPnC+3^kB#Q5ZAGa-pE&g{fufjgZA8r|puR=RQdr=oYXSMlJxJTt;>{9FN z4zU?`;QES>-d~9Cy}vNIZ}kgNaR+f_y$Scz{dB_5yW!`i`wA(mrt?3i@k9Tg5XN5o&?kbuYn|?Y8b9>&!QEc`(8pdqeyDxqW%5J8 zcctff!1$rhhVblHgC+-@AG$LQKjp^G$qxk^mhxvO()7&054C>~%Jz)>&?^sPe(0C> z%?~x7O7lhh$tP2Os0nqVAHT_smb;h754|RY>-nK?Nco}H2Rr($@1f;~-W=D_b~X5+ z)Q;6V*6W!#qNBfU_4r+&AzIwb*Bi!s|?QEFO^J zy|eH{F9_U$eey(8w)p65Jkf6i4QJztnh!NS&p(-kCwlt<=82va@^vKfMBURVM}v8y zM+8rl#v8N!9Vq^#IZXJM?lWkAnSY77kCQ4}^mCxbd42a*c}7c7o{8fu9IwSu!JI^A z2emr0C^Jz}DKHEh?!$ZBy~Am?KLuf&isLjK?KlROVyyw;#R$*l*B6N=sn1+3%h?V+ zSKJME)5A;u^H>}$ zSuOkfy0k{$qs$AjqWM!gH|l6vEt!8=R1)04=^V=%)_$t!m)+Sj^DoVQ@-N*PuRj0M zGXL`E<6myvH~;dLvM`Qa^%VS@Po5A-w-GL`-Wo0SW3GywfAFS$9|K^z1 zuoTu+64&n6$NJB7k!fOII%Z!UHtb7_HR%TX(t?Bf)mY?C!ZY>EvwPRX7W_9_7o%r7 zeh!}Za`eAg*Q;Ren9zDz&xqeklJ3znr+anud&#rI1$C~A+!4&aG%?oyk;m#~nS!!b zmPUtSqr%)GMqUR{zOlyX*KEhzOrGvdv|$|=TJ>jpW4#Rez+JyPJ+61)Jwp-W0BBnp zem5VsHO*SQ`;|@p)9_RO4L0By{PiOZ-Yw!L)*r=3<3Tmjn^#X@ZT^X} zEaP0`T;u%8dwcV(IB&)IhjG3D=L>L7{J&)Pt zO%3;VWbw|R1@6cV7=aVWX8|0+q%`dFP*2_H)Q!V86ckp&Z^ORfcSoPgQQ9dCT7&m- zBF%-zT{dpHH&?v0H^2Hxmo406+_KQ(E+x+}+w`cz4;r@g; zeXIa0zzVPetN<&(3a|pK04u->umY@r5T1Ye)9~)&NZ?bwu``NByzS2i7INNl=HFX=%2H zJU8+{-}zCVs@padidl=VLQxM+u~EI(7U*|}jqd=jJjUcdjDyAyNy-sVjzM1Sr{fs@ z3OFc?oh?@GT!?G)N&i0C{MA&ZrTO0>{?T~oS2j+agYkn4fBiWpXID3_h9~RjG z_=~f69+}NE<|jd3b)Sprd(9+mdwjmkqqF4eVc+h#&m26arTAK4TAF&$>bmszsOqcu z&EMaL-}{-*?we`pHcw?*x=rEQq~_7Wv~(v;Wm;M=@TmJ_re$Lg!R9MfAZo|AWH^p$ z{^fBgI}+{S=rj0cuFYZWxjD4q_@KP{4Ej8L2S1AWqyM)3&BORTlF|L<=2-RNH{)*! z^X;fF(PHu({Uz>27+XaKzZXUvo-z3k>GiRQ^KSh1HT|BA;#BB=B7?E*yKQ8z4`GhK z8)HiJz4Sd`)cFqI2ahA2k(-)Mr_wx}1$XE_B7B!c@r!gVfYN5JZlrT++6>x_qm_SY zn)#QV#`7GYL6Q}+e?9r8OC1kR%V1~ zHNxQAknp{``Q=vH13nVD7MMotb^`nUXZ`nAdj&Gh!v5F(e*<8DFEH2K#qYznioMdE z5cWR`-~SmQa+gc-jKE>=tq0PA?@h$DFwG_@u7-K_rBb|P^Txi2ZwB#q9j+a1FCM<7 zBYznSMvxF$3dbF5Be6*2+_5eizTRT5`VR+x(17fGT--PnJA*;kERwo&L$ zALpV+KiH+0eI3_sOT6rBFwJMe_cUO&Ar)d-Yp+~Z$mnz6c3GiA-wu<~;*Np&tdSO` z*%iKLGl<*dt+qIX$x!;0qx9t97N+&)2c*OIj-o9ik2@Vq!83$fd?w6oMk?r{a`-+R zx~TR|Qb895UDPg{Pf}eJbWz&{zUd6Q+)3e@Y*7`(@TF!=dGNPD-fo+IJl_| zhy9k!y&-?@)b|ysOeEM>(w&@g^TbwJD?KOGl^Lmuz4E>V8I^RtURUk&u@+!qxUi=p zeX~+V{HpXiJq$PcL42E>!G2#czM;kUK@~C)ZUQ$+!9^4nxl2kH>vFq`G&Co>d&#b6 zrLMxxE(>MTo)b)WY)IdvyV6RnvxuYgMqQ`45LOkYTGT7?Eo{EJ5aE{kv|5C;zo}R1 z(r;;9dathHUR=6Ot2bq^=jNu^{y3CR`cBI3&J-Kzs~{~8;HW;c3E?@ZM%r}JV^Jo8 z`$`6RvRmSWOfeK|d{bLSdPs+AY7%<`MMqS`mIB>xEY8sFfOzsY=2{&8L3 zwq`P}hQBi6D*HY1n$iG$>3)T@8^OMyi$YkG_5^#B(s#l2G<>pCu%kWKR7-Hzcn;cZ z@#USuYW5raWP+b8zQ3jCjPHO4$b{PwiU;|r;5n4@E*irzY2S%wlU|R(-HRENzvDys zONPz|6$8($XSuGDSvp78Vd^wLlj*W+Vz&tUY$2{mJCwaj344Me%vfxWlc65$wQc3V zgC?t^Y5CfR+wwfzR_EciJ`cAj2vh0<)vMX^R!-ekNOL^v>U6&jb**&1et$!kzSm9a zQpImMDhkgJb+ZnC34UXu(f;UFp>9uVyN@vHO<`aI+NtT@hd&+fiMvexG}3|i6U46& ze-+P;(x%K%T){o%2ICr;W-wMUT~l2UqE2Ow>N0&-i26IFOqk7a8Szj(HgC)nYjh5` zW%$>nwYuufyL8=~>$EPA{oOts_r0_Y{O4d&TUp7Z?c-DHeYWW(_>DpQ zxM{hf$9d+EuT$8I7kP>rZuH}}rGW43iAmJBU%`FUod|i32G*HEBM*%>!GTRg9Fz&P zlN3&6#I(>Jzey4KN$Wrb^({tz8`o6-2DXT73^&bwDyg4FeOB$mQY}D#gz{1DG5Pw( ztS;lwD>KM1bfz#-$4T$nLVQEp_x)#4|vilM$Cy)J9PsvnA)l zq;g4l^Z7~p;t=LO(wv_?%`NjtGo{z3rF80KT2ywERK3uum+~z`zDw;eH$hMAE7+)K zWTKu?U8H)J_Rxg@AE1C12(aUp^9)%ec=JCfuV1sy7s75^t5LXEVlEfqMll z++zH$b^*pm`I+6-7Qr2*y@dEPGrLKS$GutNiJ?J)Fp`qMm;-HHNx{4d<|3G@b&U3_ z0=t1egEm{}fu7-bpIW#rbKKwL`{Xe^ySOcV2H;0gJ2{4DmMlhIXUWF^`kbV5D}K*7 zb3S9bf9mZ1lQW=$n%Qr1HtrQ>xwm|)tU@DA?MxfoESlM!T8Vn!gE0ukO!Ry!XulNl zS)=x?6=Uj^sLLngI2Fe!I8MXSk0Zg+hvQNlm*KcPqiRLOhxVI(yZIfAM<~2H`T~L9 zZzdzQB|&)PhT7|fJ9;i-XpfuS)!?q&N^OG4CJQJXXnWFdDNOp)2&WM)vF9rAW3!p! zjW2D}2WeY@S)=o&KEvxm&x+zjnTRh!Jx8BFd8KDUCiP!r zlG`$lq|X+}eU;9i4gK9@e}w*w&MO#`R_XV(7iHu?+AmepeknoT=($(O6gR~_4Wt`| z*QpA=3`~{W?!068)FfnMkTaKgQrl?}*9i zPNOy0ExHrGIVePEx1ePU4q^)AvofK);PBT`R;ox!N@Ep=w^OiFlICwni}BAFzva#O zdoqi7`$At!d1|pz;YfOnu95p5kxTm4=*r~zZAc&dtnQQg0rb^4syHf(d_MCDwJSLH z?MLaY7=xodDZK^eBA7R5y&7rB^`Xzid?W3f>c~%w{0!_`gZWd=k7WiB-@tZUx8$VA z#M@S}#Z6BPRPKBXi2PhkmXU#t=038Q5aA zF6Jb)g<4$Z^QZ;V^nlZ3CWte^v!Hy_b>kVS%;gvZuE8_98RLTd)Mu2%HR`h}=J%v) z%NkurK6D>6p=Z~(UMrcG130H=SE2C&p3xXRTY8o>f2C&ze=3?9j#AU&%g^?#C7$&v zsi_=iq^u)cwGi=bzd_%K`1SGg=)29PSYd2a8MV5GLoLntyea&ir-C#qcayJ!DraN` zTtSr+Fr7D*8I}q42lOmqihMfOE$kW3s$JN_I7ekgf|-$1N?k5}Jjkmu=*PeYRanQM zbN7ZYrmOk!;-DW7HjhKA3!QJz@jKHfrn(oWV`>_=V-DUt|5k8AV-G4<6o#Km(wq@t zRG=00(^jG`;~upy&GXw2()ISUbQ$wq?fX=vD?>J((3pRt>{T#V$Mci}3s7zm_rQ?R z+V_R{y=xj@W6lGPXAA9ttfAwMB@XFsF9<&lH#v&C(O%J9x^bN~ zfbmD|aK*192tjeu-qN(jBZL+12cbadNLb^ORnBR)4R2 zZ6C@7+Mlv}K0f=>UU`cWxj)76Z#Z6yO8*WVOZzhN^h-0cgUt`{fy_HE0~3$j5gYTyEWvM`um6aQTNa$>a3d!?WgyPu@Hqz?Hu{jX?P0tnZ_kk>~~p&*A)Kaw&26UxTfK*jB-Kgp*_n_ z`_VRi+K+}ch4XFlhd3(ZH)wjEl#j$d7mIj(v5tEKNbgvu$W<}F)}3hA(U#X>SM9<0 z1Lt(0&&?-j=V{!dQSND7yR)a+-3q%ir`g>GyR(|? z9s;v?sj%{N93411aR~gLatTb*Vx}|=W`$1&#;Z}H2K{>8%}sVn2fMd5*(IsnP?KFH z^?Os3T@7}PIwEcl<;(m{C|AdyIh+m^4F(*!7CNL{xO5BH8fvL{GHN{UR){rV^!9B`d4Q2)QY8kE@ zYxnJFE9bFx-^e%lCw=@_oZbPX;Ut+&`}Gc>5spAO{@n`v`*$ntpPTvJ3fyH7pP_dt zh)<;MO=cGNjrS-|3q@^?7FJH|MtZX%Qukqu@U-yrDfP6G%H0`LeG9B@jLB2K6T2V6 zxacyhy{`ZZ17oa~Rp_s=o|TSI8}6F>M4BH~W6YhfMl-PCJ{hC@(41_F8?0T`F9~)P z8XI7Jlo;6c5u+#UXZ+egoc4u<wT&_2sf$_@|B0GV$r7+EXb(hI&yCtrdeqB@8 zv_4Mj?A0No>q80F9(pkTx?0yuZ`Q@WI2R*~DQUo5u3lQ@{Z5X>I`IyrX?#-0o+&$f zZr3~h!s?xw!9oG+x9%q!ip66@j?y2aPSCh-BkB;PuY&Zddqq~Ej8sOlNQ1z-AMT^Q z-AL>8W^;k^Sl|6zJb~v|#dxNoABbYyr+X9z-P?hCb=;f4y7A7QAx-hBcy@QSrZ8yi zOJURyhDI0#gi%BozRV(=o!izFY?_Bg`J?{gQ1lZNKlMEc;y)Dq!St~frH95^6|{M@ zK3pRcWw@b}Dq#$;!$|5&r@y1r)P{i{?%P7~dEbV$V=UP0PKjZ;5#zEl%8kaHliCzi z%vOC3#&?L@!abguA5X-oIe_ufj$cMo+)R!Ezyz-$O{AUbG=5z}BMxd)DeeN^qwc_a z)GP2FmEzUcVEjq-0DV0%{pg&+rt2EkKPm{T=Du4{7}FLI&W>zL&TD~smNey^@=Ed6 zXbgn5f5#J67wEk$rKJ%LOd7Y8kAdBYi6_wKYn;h({xRTUKiZNG)GF^ z#W{>)hVJ)n%YAUS{r+5eoy}DdcHJPI2w%eu+T;Z^7NT~>|D|g_$+YzzKL*2^5c#8Z zqS>A^rL8W$hw;2Ywqdq;b*L#tDhLye-32E6JC)Dmz zShODYr10rY?sYz2KK;|bOZcLZ)i#uA^s9|=jJ>u+Df54P{rC5%ykjjwn_*dosg|t5 zdoJj)1Zyeht_tf7=i+=?*pqF}MR0TNB29hs0OG2kU7)pp>_Zh5Xr1o$QquJRg}nyP ze&~MeCuMRb-4|B;B8+hx;rV_S?M{L|c;^L*Otq^>wr^Kz&^T_bNj8 zi<^5A_l0T7tEdKI_}KGU6)3Z@mTnuoh6yl3Vyk8>C=X za8!4-_-Xcp)Ct%Q5eK;ro4A|Lse<57>)H*K&;Q?Mb4z ztT?EDu-N2Y_*9sOewO^wc>j6~SMX;SisAx_1ABqd^)jppKL-Eq1X1jQDK5&WWrbe( z=;uZ>zMqlHFei8?#(w1Xv&Vf@uD$LVxeVhAiqm2au?+D(`kz!;gDMqiQ+D#V>$Bq*7_a>t_esK01^`l6y#lB;7ea`W{ z@|=?{*5{Z_@j1^LdAsfKVTcw{{1N=y?+15xAU$^?PE!!YbCITVosc;&3+=y!`#tTc zKRl1jU8FJ0yM;362VKN3qvA_m`!J``NLP6qzWEpq?;jt-w>UPRY6QQOwl38xKi6`v z?ot`q^>;>gtzM+NkoK1{uv-8-v}07>x}gW@@~&cs?nYVd!u*N)D@wziKN->8@cS;i zG^TkooqygfiMzfc;IBikILF2g-|KW|Li*i*g!Gz}eQog#(~4(=T!C+!R$vTI>7sDy ze;3B}UFhe!eqm)7`nWE!Np_)a>q0$+UH-20+oZ1RaJ^ILu5?Vl0%>Z5L36ap_4FlZ z|F8~Rr~ZoGbITmYco;vTEbnW5x)BzoiT_vuR)7^?1y})AfE8c`SOHdm6<`He0akz& zUWJ)g|K-1lQYQtr-&e`&i90{`-!lz(XsL;mFl1B+o^ z{L2poKg+OB;QsS3|KO1DFU9NT=3lz=rtvS|pK8*vhkt2KJM{cZ(UF$T&S07o4i5iP z{4Cvz8v6>GpECcF_PVCM6_a$|emZZkIGC+#)OtV`^T%dAV!kD&f{3+->HCPizBOlY=9rAl1_?Xnk&Bn(RKNOyiX}%ZY zBTgpsF~Qe(C45YSzT;MEV>U5U zUnU<@tUUVom`5yIaz0$iOYZRNDF=cp=?15ACCyR7m2`7(CEXlcNoSZV$y~`JumY?AE5Hh{0;~WlzzVPetN<&( z3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPe ztN<&(3a|pK04u->umY?AE5Hi;Dk*SlchBIy0GM-e9?Abc^*RFhm%q7m{Tu_3S% zP4D5yzqBudf9YNp{}L?4yww(mFc~SFP)=CsaxM}utv5d)op4gLW#n_U7`@z37=TGHdx|DzEn)sLQFyLR> zlz(Yc{-rxe{7c)!zjVyM6b(+%!Qx+)@Go7;za$P2@h;;!PD$hxxR}4nOicUb zxtW+|=gdq@H^EFy#Y{|@l%!{0!;2@GN_DX8;}$S5cdgMn zoAYCuUlk@Mb1;uy4yJ8k4(7|@V4D5lV7e!ngIOzLeu}wX8D{dJDAbBB0wYvC=8RtSOvtlRvnrjNhOi>R+!b1-N@99LzO` zAqO)})6v4gw7<_B%-PoXC)tm9N1zQ@?js`W-xaincLhmi|K1fe!Vw5Z;9Y}&e}Q)m zqWyDH;9Y~jy9V)+&71UH1G&o}J|jf7*}cik;yz_mil>Dl_O2FIPV7c{vm#RWfv^3v zko4k8J#D0NcgEEoQ!u~WP%NX4H_|q-`yr__m&vkQ5szVAO}DI)Rg7Qbl&{`!#~jRy zu}-o%j-fGWQC+|s%tOw>TyyaI2`c|Haxl}l4|adR98Bh5D&}BH4Hm7R4`e&Ajxw!G zFb7jpJEbxi$s9~0mzhs`PUef~tCtr=&YmQS%Zh{g2a8Sag-_W6jfp;coQ>9EEuT4< z9bPLcKbgCP^5)(6j)pmyf;pH}Q}~Y+Uw zQq0A9g#UeKWJ)d*w!u-p97mLH??tJ){w)?>IFYP^nf9cHO$G;RW zgMVpW7XR`O4hjEK><9nSoi~+#X;S{BY2sg+!+?J&QvRh#`IqJ(@h?Ra|I#r3@}ToC zU4i+R%)dOi{7W-W{-sIzmu3e3rF%N?FHOq7)L?CtX+QoUoBvg2U7DxoW?hP>W@cU5 z9n899)@91E1kZw5m(#RxTLRA_3!X_c^RuB9vo4i56^zSM4sX__W7g%X&bqWeXVxXN zE-}8`vPRdzp{qaH?zsZ>7BFf0ZqOPGHQl#fE18!A#8U$!twJ0rjOoU3UBz|vL6P-i zJcOa5yiCZR{L!__%Np3B8thP=9n`p#3S&a@Uv7*I$zDqEn^sBvF{^b(%6iITOSa#j zZ$$k1_>9zxdS$tEs^>k^`jMKgy*Ha;l}9>9t*+rvOEW%A%H0xIkS=9z@vH!~WRD*N^u{b{$=fp<380ICbz(BP*WgqkIiRG?()B9vT>DR0}+%#A4Yx+7}Yp8Z&+WXJk>IkzQLFnSk0`e>OvQ3w z!;1dQ{#U5C>P@{;mwroEOCleaZqw>b2oG+W!x#bMDd~Kpt|N>JG4SlBSmc;{`Et0I zZa=t}=8Md|e5Kq=dpC10k67-dIruy?VwpYUI^v~hCr`)Gfuj?LQ0t3JU=jl~=`ndQ zSF^-DB>ths`N8I#CB$$-`z&q`?X&xvP>!XwGWxoak$X6fWUn0U76s7~+WZyY9+u`Q zQH;R&83oU$AO6j;!N1rpitUbgHtUPBqgQ^Qt*E7WXDsev?j>_Cg<$UGn%K66del5# z(gla=G<6Kc+{?{{0yL@belFf|3Cyg>O^jTvclHeF!YYg#;|HP`Z6tKs%UwKyECWR-3Gg}Qaj>+QJ6F*nJMmr-5)UbavI~XWTTq-9=P*|ty5GAk_rcxv`*Y=WHdjU1b%S&w ze0qlg7V!d_lhPc`|7FEO8doHJCa-9m;pfCI^6c?rLb?)|K5xvuWbP%_BNCK@gxX!4 z>&~mSdQwQ0!8*XbPE$L@+{?b~GK`U#dkJpk_rtv54)nEmX24P}h~l}JADrui%;j5@ z`?qkvr=7W%U1F2$Lf_B@4t>`zZ2qp4L(kmHMrXw)E5Hh{0;~WlzzVPetN<&(3a|pK z04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&( z3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPe zhmQhx-_i5R_?LI|>^n0@0RQrL&i~23%%ubFPs!)2&c8grtG%bI`=Ul7F6_E+===-M zYg`I(mk@vS<0sx)zUjQ~o8Q(w2b6S=w_o+M`S34Y*Ma9>y5A4{OK}+TFU`hGk;(_{ zAxh@5uVQb)jY5C=I2S$o!7lChDg=9I+1F^#!q0d{giV>5%UXNovO-3m1Gmcx9r|{d z;u#|y_5>Br8fjsgUD%=+e?}Y{{-wDfumx%FNlHg$_g1hfS|p`NIU`r(u%G%g{-wPy zXky#nSKN(#$rEBxoEn~?5?irn>vK|FiM@o2z4AWKop`;j+ULQu*bDjEnr<>DVLF@0p5liJ_5TALr(Moy+YG9E>e7+1*Rw_pH=a*qQcF zHciUGw8w|^O}Z z(W|X_2yl= z?#*>t7s&o@ACCP-+6JZ^Olm7DnL!_?NcorcFM}J}JG#vLOKHD6H~-S?oSA>=CYXQ8 z{7dYUU6P*t#r(@@T3|dBQ(HG14-I1n>VL;@#9)(AI~RAp*|%k57>gu}G49KtZJox> zq&9RwV9e6FRVLY)@5gli)Y<(fXJAaIX7-z$jeCVz?k(RctBcU)f_bLe;AYXx?$pX& zsd_NpKprW*6&kZ3pS2?L*^06DN-!@^#&HDjF9q{2Uv>Va`&r;D5nHhSQLqOw{@0m) zu%f^YL^(=26YvNlsS5oVccU*KF*)67v?hDn!@m$s;~Qr8@DGV=7=iy6Ntu8hL99g2 zKvb{;@K9lFur~)Wi}?F6p1?hn=?cdC3J2IFx<>AML@w!Dqbrl=w;_G-v${{}2dpmR zsN$%g?qJ-WPf8d!;k;53dZ6@HjJp-gx4>Kk6MVM5OTI`X-x`Gp_iuXrXTX_CuHweWJ8 z^odE9qmelkqg@K~qs^XwNb{Y6EmrGdPR8IGYH^v*qZUZh15T5fq|b=*P1lWQq%xOd z+_whL=w_`l(-@RlTw^?^ic?vY#J|)-Zw}1MA&m8yc_~QWqlJ0tn0dKp{)0JFjQMq7 zgJKQAttnK&avDRMF+pnrG)CxI6XrWDfi+R_YYalr9N%JHgVuk9u=ocq&X<^ZS)+E4 zSVJ(uFe>;l20%Y5{AGS3GXAD=g-;;5rw;3)umtQDMY-rmwj;4ey7d7~|QQ?}hl> zcQ^QFc`6vY)491CY+B#8f>TT9552Sv4BwC!g|(UrwWG*$1?zMVnU1)OJ`U?%KE4~_ zwuWoEUnl-nX}C~Z;5>_q%!ghY_F;Lx68K5pFY%se4Tw0k@Tb%8)It}1huk;Y@3IK5 zDg4K6!H2cZdTx_{7U;JqJr3pdv>$ELr~PPHQ#juye+a8GeuI9ff4!!BB=)&j#OsT7 z+#5i8$2vu>y3Q1ICs@ar!`G+}>oEoDvkwK!EXn?AGcO%8FZ0a2WacH!iJ5u1Dc*?p zMjIbAo>xihAH<}b0AG#9F_k7>B{MI@tI9xT<|Q*P72Y$}Cf~(4|9-g&9%o&A5923{ zZ&S{v0<%r+vXlK9aX(cNb51Zn$-M?AR24rjmB2y#&uQ+714>+1)oDC~Q-di=EY9|; zGioE|H)VQngLMj8m%yO3RbP|A`|Xe(uxtGoGfvF`jG=e@GMeJ1hVa$4cC4=s%eaWJ zXNjwTbnQSst^j+E;?>vSy%WZ3ehi9tsB}(Y(=~BR{X1^E24i{fX`A$Da8D~K_jKZ6 ztI17_ystPG??YFLqQba7a3d|&HZW!fLsFHpe*LE6Ig<~^{$2d>&xLpK6PP!gpOGyW zU~TjQT0344*3s$xuLx^C;!0XKeN5K!KMa2AMpkJaB4{n<0ne-~Zx0&J85ZK9@IqQP zGxHMf2Y+zM9e&=n40E-$I9`Yc^>WPDUidyUFGY(e{s{9?W?n|c70(E{0^bR(aB00v z+p4aojqF0(2)?E4Lfgp9OIoSsKURPhUO`(U#?I2 zmv4AqQFZi6cS2wQhCM2c5V^~xz@Bi#juhDcO*rfUiT&S%*(3$_gcR6!QoLmI2K!F> zTwaH3C$QaRx_=z}W$ds-NLdQU9gDsC7m1uZ)_L)cem810JkRF)Un;(!4{5R2-k;k1blsZGG#b?6YhP^Fm z&rq-`Y0psAzG=pNLKSpT+r=c~la64k`=Q@Qa8M!HZRpPYH=C(W!x7B&LtraD4*@(ML{=l|8sQk;<&yRm8o)2xH_@`h_;a^S!E{xk6?h!vo=fIO% z1oqtHrsawr7u($%inI^1XJ`m$o4V1D+m^z%O@-$B72F5AE~?@f0E?rcVS|b5ez~Ct zW=(Da{1FNV`zE*eaEp8Nu7GV7Ppc;bTSPX7n`S?i)K8;6tM*~37N9>u`6y%G=laLM z*TSJ!W&)p!!UQXe*jF{ML~1Y<(x6Z;>AGSA$4X1w%TrmhE#;EU#bAv+hP|BK-_6a$ zw9n4W#1vm)Cg%R`Lml?Yc7CsH;=Gkhr%rOmW@RQ?@OQwBsi6(N|AqJL6JT6Q53FP=%VBp7nNaGM;IFCA$;MvR7s!7EA$1#7*N>9 zKfyt5eg$TY&YSv-8q!8>gikxhRq;h&s-aJycq`~r$fW*@OmbVsk@SIGg}AG9{%q*) zCi|mwtXTn1pbAz&d{IUYr2SGg?Uxd;t2{T7OmS1}(?GgWc%5oSCYksS`r}sQB@TY= zOTwpVCMG7cFfk56SvjCA%vP{4(WdEi&VJaiF#EsA$0f;Hm7>_0xV^$ZU zy+D1BiJuC7pVR617%W9y`YrThA|ID-^ZmRZH#UV4IE-)9b%Zh5=W5hT)Ol(vX#S!X zIX{Q^AYE@iOP6u2egCL*Wyr=88tfyKqe_pB$67IuS%9%O;vN_>TBH9QLwbpYG$qX# zFBcwnS?z9$cPw#8cY8tjF*O)>X?v5Py(yy&X^4`@Tm?)muaOMB%lO62|&$G_otEg-h)49Dde zb;fhg70kj=HYeNgt)UJ74p=nAH`HMK>Xh+Y{+Ppc7FxFu_%Gt&B<;GF9D+hM+Tn%z5KclI>9TVZ$RG`rhicUF_# zL#`uUiZWH{K)DibLp&UzVWdz1*0VsTUMc;#+p>)9ZecXb6-f~h-&O2TUcKl*l?eWQGWc~ zzqwDu`coaeL-JQi#|S${uue5%^o0G4pWnwRv$?Q5BPV)4?ceo~8-JaK+Z=DfZ3Soj zlW`q!&nLdIG`>dI&0#XH5@UO`7e^$oa!qKH4`x3>^@RGK1Y`3<(H~47Yf*Y=tW}}; zFzQ&1Ow`9lecoSwVS`ynEW&1Pp%TM#Uu;4P_nO)lv>~&x3CYbQvsz=F5)47oPIa2S zIEeFR6C$jd`))yjy;wk6cVt^~UJHx$Mciw!8yl>`TFNTi@r2a{Vl+}(uohCGaA-{g zeOCDx*o~NY0)4*5Ikk_~?Iy0m4ZUBcYdZA0;3lTIQR*(vVLfE%e($yno_Tru{kifw zo2w%1xc=8x(@lHwVv6YGo_7rmEslgD($MH zk5}1Tm#LhoFM^fXhBA$QwK0yd*S08S{*NES_7v~vdy^&ZmwOVsc#-YTotqrw0^%4W&vw~>h)66^#Fyv2CUMd`wL}^ zHOx;jVx_-dgfVU-yduUiv~HQ;z1hw!I#)ycyR$D2=1^~b$6r{zGc#By;C&~p2NaJH zIlo>)?`p{(naW|@2ov#Ca7|&?V3si!t>8!~T}!Zr(r5izNf~jK;kVubf7y(#XUQ%6 zW4@qZR&Z2zwdBTzY(CE6Iz6Xw2XMV?#Rj=-+lqMENN4;4#-Ga&$D?1!W|zM-A|L&4 z7^~yY9Vd!QTo{WlBktzz+tF?daUi&x=K7$eT_}nRD2|^8O_yO^_c7$logj)`FvUd~ zwXD!9AN|~jURKD+WtbDZ6JtM0$7hfGs9by9GjbWmY%jvC#T;T8<`j?q=T&j0Bco`2 zgbupD0&{m;3isDu{|9pI^?xrP{eCM$dz>@MbR(zD<{R)7^?1y})A zfE8c`SOHdm6<`He0akz&UbY%zQ z0W#s%b55}Ld8PD5UCz5`49BE>C-^7n^%%l=k@li2GXHW4uaov$g^rV46mX?x<#ncR zEA)Jre>sJFL)_Fd_PD3LMcu`jVvWwho+-yDv!%7V>dm`!-J9#Q2KPXh?)F?7_sz5o z{KsH6^DoUaDgW}X!adqEm-eP+{w4IA#=o>*o|}JZcFxSdbQ8?KWd0@gmM%%pO-oAc zS{vqH5<|{w0S1@ncg)5L#U9JlCy(KXY0q%9eR1cTefu^BW@)k*tj}3Eo&)G}lFqGQ zptu>Cp)uV*b$0*B8Q_4bnf)eb<6dEwd&{@VD)=_U6H#q&vuI{_YGtofJs5)^k2KMu z{*T)ES`qnd#XjXLv3K^#IEbZn3J&6F_2VF>Rv(T_ainZ5Vq`Vg0>sjy@apIbM9Q2@ z5MG0$)o@3;k72L#W_LBXD-+)Wtb}9%rNc($lvzMw(w|0Ljc}C!o0`&^&oKXz#xJx- zd^*;w;QV0nFWt|=zTh+QFKc+VNoS&&gLx1*m;o%@Ihaxt&ov_@@l4c0v>V%R z&^Lm^sgKXd{bpEWzkihnivc`K&$L{ck;K?h?v}v8G`INnaaI-u%DTE3Oo~fZ5z{57 z>|@?NjcKuMzu%YNo7!NG2bKl71>Yi}{se9+FumJ@$k??173yl>M$VtHXJ@0~4Z>^2KQ0Z^2$5Mw$>7|7_%*e03O`E4g-8@u`P4m>u zj7_n9X2z!deP(PX_C?P=QrCeUwOwd6oh!+VP0X&GXZ=iBJ7vbEtfJqpJh)tMJOga- zCq#AvY^A*z;k!&;+bwau^y_{OHcIocq4RZh$mse|qLWe&*ydO3dg;x&2!>dUFsA5i z!6_}R@_r{d=be52x-s^smyF)obGvTlj=7%%?ijJkV$8XTslHKJpS}vxtL_z91^!uO zB#SgKV{>0DW-9*)o(nTJ!Lx%F%-BSIV#cOK$Jwf{31z~s!J$3b7k8E1)W8K*+uE_d z3eI8?^W6i*UB$a5W!GRVkGhIDrgK&+DQ9)!VXMha4A$z3W33b`k3Poc5zD8X51aCm zJMgRz44cvo2Bu+yO=*r2Hl>?`P3h)fQ#uoL5zMC4UFp1F1$dd%e)zVGzR>_jReM%z zMyf3Mtn^-D#Iz`xlXcvWaerXf8m+TA|1Ns~_XoD)x+Nz?F6TL*6c+!n0;~WlzzVPe ztN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~Wl zzzVPetN<&(3a|pK04u->umY?AE5Hh{0;~WlzzVPetN<&(3a|pK04u->umY?AE5Hh{ z0;~WlzzVPetN<&(3e2s*t?O^UaqzwGUOx2pwKF=#y&3Hrmhj&=o!RW0+4^v?z5KE_ zUHa2w{`Sjr=`cN?bLn!x`IqN+wfA&&U)0d;!mbO4&cE=y#-$KOh(G%A6K^fwbYAz( zZ|m;fbA!+Jr9fsq_D{tAvKj0HX@rUFj==3|_{m~xMbZ9IY4g}~@zkQU-`pzQ3E;Bi zTHwzJ@lR9TlRx*%uxEQCjD4Cbe%J5A7WQL93i9iVkytI=zXztG`*AQE_Zz0!HPxOt zd-c;CST#r+_TR6cU?YQcXr#0HjjhKp6mCA_xv;3YqINo#VSmD())^0ZAt7l zq`?uuQXfYDBBrF;sGg2 zEydBIlhI|XW&d4PN0&jr&%duYj{W2!cV|2f_mR6Pj$XT3Mqm7=LIh?&_RSNx^dZsI%lOO?AyRz_?#8Fg8eTOd!3igIboYI!=2 zv(8*CZv!*NhYuE^IvME{4tw1dr2t;AzI&@|Zz;+S90~6Ez3|Q~%Kj5WI{Py=8a>HH z{Vi7ZXIxad7<&&dF3RZiqRgIAR10ym;0XEolQ_Bz{=n9V&OpA9PoMrJNPlmaj@;UC zy%_hz_x$-NxI&|syU6`}&@}qHviBE>k4RAn8j7=u*y^~b`th92^BaoMWk?UwHJ)*~ zXdSfeKzd$7@otXQqD`_N&rY>(0i)xSf#Z~4Ak|68+lj=lxms(uUw|}M5MKXlTr}!7 z6~@~{4jLgG7m-%|$nz-tjKfS$bdk-ssQy!Iw4#4=Om1t(W1m3R?(@)p3OGo+@0C%S zPbxc+xieNJllu@fed?0U1!97Tw)Mrz$qxIRTG<+HE?k)vx$^ejoN`uHv5)G&7Ll!t zi0oNeEvWH{ClUwfmPQyE9X}e@*Qw+D5hCb;QMrR*XIzPay6I zOS`(hdweK&8|j{mVL|SGk z?EcFT7WO!g@|VhJcsc6iCK>%&QHFB5+1F9`_3U1Cl*(0vdb|Vatt>{FDPASZV0tEf zwtzgw)V}S&bM5a%+TEYTs25QUX^2L83-;1%F=;`0L3$O;#i-ArJ`APxo#I8=?|a_w zS&z7U**DKnnWlKby@Ee#Kg>Udw2434!(62>{e5zaeZ|S0`-e0Sq!H?cc_-R3#G&!r zsGL#R5;qptF ze?(*xluexlCxOZ^w5M}2+hJ-o=((pIshxM1+I2SBRa3hqO?GwIxral)F;{zbM$2k> zCJt)XsGZx>w%s(PZKL|uXy;}-Z*KcK(f%!&)&@4(y3sy7>u!@D&peqMJIzKDZC7h* z{{~RrVzhBoW~hy%`XBXmc?LmLiuHJJR@d6D)f(+Ll_4!QhxX5>4Q&tF)BcuE#uV1* z_J`xd;v9WKqm24G;@isS<9_%N&u%F8Ul!UvCquaqdVSI0Ah&t6X%a_-W3RT^J{*7C zpud^3T@G=X9ed)cp&rzb_A1ig{?~?LeX)zKK;8>!`>v38^QXanuXqLWG*_JN`S>lU ztK$fNl=27DJUKP~3bd)i9?udCr%kch6ylq!o>t(8{1wpl7dnb^db-^wLO9Vg&lOA| z=;%I!aSiqNpHIg(TZ0*+UX5*bI^JS+ya|UuAG)Nd)TygwZP?+tg9C+eQf(Nf#Wl`j zwOS5f&+1qerF%St6P<{1LjBf>=(pB6Z~A8rcA#$u&`&QmY2Tl=5#qz4e#97?5DTC& zHi;2;{3i$>ap?!F1Xw`Y5w|e@^dqs_hH(sZn>c4nJocF_q3ped+Kx@}*zH^5i68t^ zYz4I!&^umV9QAFFm3GOVbMx1!CZ~sShY#DhDE^}M@z|1EI93w*0ob|c-NI3r(KapV ze4Ng=n#?C*egt-OwBgtm%%~UP&~@Wpw_7Mq4RJ4~@e-bY1Z~FA zhWU1Piz$pgXoGGJ_LtKAP|tjM!q~$64%%1bar88#$KZZxFm{=3A>MbT@uqdtrz1^E zKlUU?1&>By_QQ0;$REsc98oXs!H;<=Q_P?Y^doFacZK|v-l{9)u1(}4j2$9yiE45@_ZC|r9LXbJu0Urv%Z+Xjt+85_sJYj&8QF8gKl9z%u&jZKs&5ZCs3{<>iaCl zKd=vd6L?AVhv!ovf4w1}<2aA(&E8!|512{t<6Ovx*_M{kOEKm_xu?7d-1A`}ef_Xk zILbIk((&zJW)FI*?PkBzJ={eaw&#Cb&UhcCRr#N@rpHnC!G_H@_BXQ)@aWWDh zKR4cn{sm_Lsc8RZxi^Y?qqE$jwrd>sC&P7H(r|5Fq0g#yn}RkN|Dq4CeZ*w-bDIiw z_lDwlMoo=#9{#4JXD@#ujn8DG2b<$daz4LE>&H=#Ls?xD(=(;A?6pR@js(WfxbDYu zj;=+2d+i!c<(%$&H&owHKKwbAZ>lG=lx^|RPzEeaD#sDZuKP$@-XGj|+4kk~+O+L# zM_Sq)<_HU9v>3-p3#3?_wvUKkpL~_?wD-e~@+~?;d`TyCX|qvstr}IGJU7xTLftJJhxrEdYen0KcF(s(G%iMaLFePUM`eU@YJ3g)+EuG%MPb~K?ah~A zQXNp8Hebn#1(d$YKX7erHnT7uxl5}~lczMtm%=aD6R`;<*u4m6IIlFc+Zgh9D&jj8 zW%k>cgZxiFN5MP=bCglEX_&X?#(QlZ6A3vAKmC|Hpy$K*`z}4&hdAIy?GicFXY&cJ z%eY^rxZ$?k3k{H0=$C^w`8wvA3GP=%*J!fq$G-LYS}hg)jUk*dgfoV4#-@c!_hZ`Q zUTJCmLKNSEu%mQ7q<(ERv_IaDS*h<(IVV4keocK)AO<|w*B8MPws~Jqsa#_`(ht2! z`%$zj^epN)_s^o|ceJ_);~%UkkU#U9ppQK{HO~%a?GOJ@CMW)bL`Q@uj7;S=5tEua0(TS2F)nF{p(!z3fNN_7~f*EvBey? zWb!n>i;?cir4qs$29Nbz~x9X_H$Ny4?SO zuJlYPJ#}b7>8V4X_;D@c&*Atyo(Jx~1^FZ0K2GJU1?2%{Y8)C=aJ)Ywa+l%I$YUAx z4Rsm3T7&^R2R*2bN#M?p$x&uTGZyPkg9R!(A4l32TUs*;YfGaTQ_+~G29ur#neL7d z#$uG`J5ILpj<;i+{)d5sX}=Ln^Qln3+#jX(?+AVh2&0Ijup09=9QMR;Ke`%a9diYP zgU0pB4#pbgdq9M_hd>%A-KH4KBI2g&9nej!wvmF~0`ms4E8|)}D6(aQpRBVvT4N=9 zHG;Mc?T5k|g8F;3RcOZ)rD1tU1C7UO826ZC!!?DI;CUz1w!wXJ1KKqlzWw@|mi@S2 z!BNW$YSOOO_FFpoI_z;ij&P}btFP1gZCHC0%fq~Bb()?U%BMrVipPjtZNzBG3#~zU zeGrDv7oM}a`jG;qQ(x(#0UR4~?8HIocb!;_qXJG{S6_B1}Fv?A;n_vxJgr7ix&mO^yjkWUYdWBXCoD7>i0db@GBwHV9zd|bT6+l`LA zDMxv%plu$5+scT``goh-q`Y`-5Z@T$EyG=Z8YXGn(6+ITsna#g;?`I*$0Xs8D~ARj#8@fL03EeoT&YYAdL(*Kj}Z zCak5>0c|EWi)`WQP4WtG3eC?WpHDvqScfqR{EzzZHu-#0IT=M+q&O+8E1wlv;^5Ny zCA9&<^O2kn!<-c~TWr(0HR?Xits}Jmv(2liuK6|l`_SiJ2DjqYn96koCRlXeYyEgD zx(?&AWVIZ9m(@{%^InX@zM`kBznb68?6v+nj&_myZ~LzKQ^Q$jj5+QM-f zGyU}l*4l*6FRd-~_gtmREhy7yJ8I}_Xl+0bg|ZQ~q+z}WZ9nEBHRMlUYvVfF=f>EL z)KLd zdL9n_eS|p=js3|KKtR%1)kGm*$(x5UjzjzCP$!MX+#dbI|Igl=fXQ`L2mZIJtKNI} zRduVoC4(#*t2Zr{jU>yS40gbN-ICo^tp!OqiD5`A$uc$!i(@-M0fTPKBwZzWkpzT5 z$XIF#DGV9I0NK9G3{MiIt6Rp{Cd-id5*(XlvSDLLCX0jqzjN<OUC$1LqY{LE=>4 zQB_2_(q@!Bw$j0LjK#mmT5vJ)!@SfDI#LH|zp*=LL+UbiN32JZ-{xb`!6RrtE|i`J;M@t^%k3sg{C$a=F#1+5pW;Jn2u zm~*KL6z!zgd!%!Rw7;Ayjqr`}`JSUm5J7w-n1 zPyCO<%Y2RReE5>{^&0vrya?m#FZhn~d!Qc(|2jbU4!)y&dB)87>}Ag93^32xaGv(a z6E|Njdjssr^6bY_99kMxuZ6Zh3Qu*k%jAzzmTJJ3!Z+oibDqAOFSd9swEr>H9ZEhT z&z3p7g??~slhVf~HidCAMp|gMW9^-~g>#pccMf|;*?;V4SB0ayhf7D12S|Dg3yJ^o z;ZnX3`;vdl3Zw77%;=Woe8_DjZVPhQqnmEfcVB_u+_HD~6|sda;MD?NC-XZ=*QMa_ z;02v}srhuM=DPkD54rxJhljoD;4x48@Zu%*CcBLu=hG$JyJLRG`b|AsoSX9NoR8^` zvmUG>oH=~beJx`;;Q`zp5I!sA3H+)zavNik4<_03H_%5JlM?Q4NYh2Cy>p${KIbC6 zUOD^7?O&^U?O#-S_wZBU`nks69Ulne?rr4`@aUl3Iy&3DN0}ElaGodqY(Drr0DkkI z&E?y1w_m{Ah5Vu&+H_oC{5=L)-|6RCj>_E64|Msm>(dIM96gR|=mu&vz zwTHYqF3jcE7s#)$s?a_gxdD92BYwHietnYWwDAXQ{6~DRuGVq1AVV`>j+_Tt_%r$3*5>*s;%hoYk3v;K;xD7bZilgs}=*fDUB z{71u%=%6REsgC}G-lNE$cayG@Gr_%uoZfx#KGvU@{u-%{*wIjEm*TLVGEJMq;Zf++ z5$_K-%!vw*3QoA?w?b~W2lu1k*fB5moAGiu=kkv-XPk;7G}yA=(O}bluVeFm?=k4# z$+|rS$5p1(3C`xPwwE6xpY}Pbu$yxBAWP^_4(IjYEPMU+;L)BtP>TL>dwD(cx!~9l z9kw`ch!>Uw&qv7X5$MhkRWdh8T_s&ghjzlG?+6{F|H!$5^r2;A_OPtG$b&X-#Tl{WuUg%_;IkE1e1j{QyZIU$hI9j-q0w=@_TMRM{=TqAe!{B; zmvIjRxKqw%^Tr!m;dmUG-^2T=$i?o`;eDjpUiBu#uLoJxcJ0;l4(@cs-n^b$wWOUm z+Etn;5MJina+{qW0_F#~r=WG!t1{o(b2MbY0sG?9%~vvaxwchmoV39ov9~(frNcK= zJ9z-4F&P|oP()gM=sM>jvuEHa0wazQGt@Fx^ok(578hK67O8r`q|43ib zs*P~usf?#G>tXb)TZ2=)>P_=#oq1I7O6jVK37w&b4-fc5t+%9=vIl8Tsb_dU^EY)0 z83$6Q5INb-QB#~q_l-8UBhODtA_?Yr* z;Du=$UtMEmLjr{c&3|%^7qZTlSYOMpVNHE1p$B+s)>xD++VQa?AOM=Yl?%m{bbHo%Aewgn?2mv5jDxno)(ArGZu%ZIJ0?p1LaZn z7&sVYSw1)f>JPmdbDzji-^HGfI~I8>ZzPV4+2(SkUV+rFsc!35#9{os?d6cXeA-3i zf0Bn`J`}o&?1H^#p-lL$&l&v?^}T0rWbY59VGmJOx<}m!E^DHvO0tKYzE5qwn-l-T z_Ojg1k$Vh-vG5J>6kYJ+$RuR`8H6_&>oCQ}FGhI@6B-V(pQ>`U#TY3fKg*|QSt0R7 z?j&D&y?1JdjmRXX!1ho z@G;g%kvYa|gx_{;Id%~;629hk9E5*n;XB2D1b@q$l25&b{WSPWe~`VV`A5H8Es%z} zv9e{W*2_8jz-{BhpSbvrhmgKyo^kOTP4VrXSMY;B5}c&Z2!7^oe39!H1J<=P?@Dv{ zw_SLpDSSHqgGpX;E;^;IdpGK!^<=(jy7*DQT$eI9k4(!HTqM1Mfz?8vrm&Qr_uyY< z4Y>#UhSz;Gfn>cpj0drT#(>7~F#TKW@HH>se0dJN`lDdFWY&7fI7dUP{jK zl6p!0l22NOZ8rnu3A#G_u7raspkuK{hO?$LjD z`8D^=nc_*=#^xCn8mGy#8PDjDlphrWeR4cB=bOfj54iFxr-_&18Qc8muV;xTc&dYv zCwMl+O~>2hoPoSR@DV)Jug^SoD}+TKa$(JMlzt`Y%wFasU~?TMOwz@>U08FyQXK49 zH^`8X_q9UHlrF8k@XC@O?XrgbPC4d`RoXD|dng%?;@8?+&@$i1nwrL~;xG7!Um92Z z%)M?5txe|HFPA=9S_^-W;?sffG%k8Pu9b6D7|z2Y8i_txHC?TNd9yU6e22es#YNPBXQ=zUmoK6W5{ z6Eu}NN&4Vxzu}ERzuFD|+Y25=_O1B6zTs8$9ALw5XKb5#g z#C_WQ_BlTHEIg{*F=)ugd6@rIcMev;P1_-7Mc!)VxT|ypx;0osEI-z9ot_s#59<0R z`kmC-`gd1!&F)Lr=$fP(=HAVpxHIFlKl#Fs{|xecD?^Q~UW3$A{={#rqkWQpZuwc{ zwm&O=ZIgaBAMt-4`Q*-&&wu%_=imE9PtF?#8@s*1ul=>>Uk`q5w96{sW5{(Q;19mQ zoscok3=+S7coOPu&nD8aYb70L7^E9aVCo)A;*Km&(##t6;EinDlr~BkCA>^Zi$Rgm zk(UdP)RHe%y(OHnE#WNW67H3JYT{P?w!e+Sw}q;(WN?jlX=J=5pE9LOe$$lR2L1o* zJXLrbX9`RH*qz6=B>E_l{}S+#urzP+%lC~!Io z-0_afUeNm&q(5EO&VR+3gMZYa^8Uq}k0=W(Xr=Hd4wapn9antcC4{f^UjRKJ%%dp;9M?lzuD-knI@ za_;;?y?=3HTUp+}h`)!tl=m;x7I*h5c!V>4HL+vIDQ`{KHzsn+xaYgizA-VF;|wc$j&DdHS0Cie%jz=U9+jfm zQ{Rv^MG3~Ug*0CQL48)Zw>c;IHO`L#2s#ZnCbn4@WM6T#5LWagbf{z?b`@L zhmD@#lXntC_vSgjkMQ@bjg;5?K0-Xd>3xLXc57xFIDBm0QT+10kC02&Veot@-Z)Ux zbm(g#^V>Q2#(_EH^pe$K*Dw8*=ofv$`Ncr#(~3I}gZKx0RX%BZKgXQA#JzFgbGG(U zyi*W=+~JYFBO!WmLgVb6f}fms3QVFmuin?xKhcrOq5l#C&(uF{zdX}B1#^>m>P2{` zK;7G%H&ykn-{ zZ|~ZkQNMqyo1aC${~vg#<-h$Lee51(=hygQ2cvziuc|%HZ8p0!KhgUAQKsJ?yfM!7 z``^g^H`DJwRllFTs_X@#K6(-K>echmt2fsqbJwtg>J4sAi&r}LxvW?J zg7oP>O8w8IPydl5oIAiTg+9I2uYWi9IgyVHzMFfCKso=2-s5zfr|8Fj-raFL5B>O8 zpg;f0qg8M2v8tzH^c;`y9pyWQT6)x^Gp}9yz8E_5V?V5py!o|EM;`v|<Eb#zw_L6=E3hp)0ro)=cO}0 zC4Qze|AKYq|MEwmGfx}7C_3{=KTLJo&lR2d_=nV)PjyWv_2!eefmSo$i40-7?tH29 zJ$gd?doum`On?6Wr~32E0anlEN2xzQ6AsTsf1Y$dHv046lIhPoz5H`Ye_mv0nf`pH zKQB7_nf|E@p^Us*blIoBH}GQU>Sy}%nf`pHKY#A)&u4niB7x8Te%vUK z*gd`Ro$tEwrp;S6-!$D2EP5W3VKd=A-7e}Wan1q#myh4m(RnsHOt0tJ=<>4Lf6eq? zPU(8j#p4wHmwS@?1xezw>c6D-5t<5nKKd_l<23p&zwPd`s?R2Hy8g>&ruzS|`Y+MH zIsF&)^qKWv)ZalD^k1UyB=kvi3gTZ%?%k&LUlaY8=*}0e|DtYld1v}BDzmlvTx_i( zqe^WQG}~G=|K|EEch>BiRz0y`YrKjatHrF(qGVD zG5eD{?u1!3?MI~Fq8JOJ$B@!E({E8fadtT4ZAt(9m8SlQ?t=6SMcA48=gXa>b7(` z_t|t9AxvEKz2o^0TM0QTb!0!xAMrERk_@nA+gxH1m_L!;Q*9)qhg8;|OTweiUOk?E*lljw!oc!Z9bj!LGZV$V>xFC{iKGaHZC z!NPW#=pv+cNoTSFC^pbC8;{N=VY41bX5*1}Q?Qw5?d5T|PweH%8_3P}Br_eAOh+Zt zQOR^vGTVHP^T__6I~2I{?Jvy!3+c~X*>gbu<->oneaYGAFuk6c{g*R0`?(T2UH?Vx zcIS90{%6yFG08p4G`_&+qyM5FnpyuP`joqC8~v_>shyV;#-E$&|3mA){ClGR^30j_ zU##8>_nOUj9etvLv#Alk+uu#ZU!o|}e>s!ROS4`~rvDQAFPHrntM?*y!tPJj(cg0Lh3db=$-3+}>%X+S^W9OxKzDQQ3cqJ~oxcnSRVqo_>sa zPtreuvX`*^bDGY~>H6o(sUKtBz=H<9Q(~rsYV>11i)#r$QjER!DE3xqsZFK8xyvq6iq}q6ie}np;!NyDc>q+>_ zY~w}Ub*j#c`C)9lWI8k6`SY-w)Ad0wZ|&z`Gp}6s2BO%@x0XG3exp=Nqw2Lp`@^Hy z2|U_m@<-?JzCc3<`SXmQ=blkMN4jE**P_;V$5eMHIxk{NP}ag0?iwH4r1Y_gO<`(_ zxn&i8?VY+MJ`}FJa~S(BiEhm9;gYrWLi(4}=8O5+OlM~AT;uPJ|1MlMb|74Tf$`h7 zM#V>8Vf+nqOmRc}c&URn=}cREmDzZi-`eIa8`~Ft-Om@~i@(3U+}_#d%|!D((`df?Rfg+t zo5M$PN3^7Qgnk`Ay}i7iwre-&mPy_t58Axd54M*j|4e5l)0xS1W;W|gXGZ0BGG9zw z82e(2$zQ+H8~d&)4w|P*{x#Tb61z1U`OH4TTD)~D;xPW+_Hy{D82ieZ&dj8Zh1*R& zgnp?FtVX{n9p|q4>dzS67>@FCZ#_J^w6v4E>&H7yaXhcuU?r2kOlQUsBGZ`}q@Rqj z_sn!=lp6n_(Rz8=E61Bdp^4ZysR(VLQOp~Pq6d=tXF4-cvBsV=h_QLkU#2r-Jh3?> z{U_B8@$XQ1(KECC=Rl@2lhUQNSLu{4Yt(31j`yQyr3&d-dx(9U^eORc?Jej!G^{cP z)3{aqtBGG4SNzPq?#-9ANjrSG^vTlN*{YDrU|IwC4fVGnvke^z7{KM@4~Kw!Pyk8?!-9}#vtX6kY)^6L2hh{Ex{mi4Tf5#Sh~-%psz^k01V0kvdXd7iA<5j5%C9LBjLmVWUs zLdS0Ci0scG7ZrQ!LPMcnl;2kVn5_HHfySBsiz$lysc~6U(hdpfV7J?(>EW#Bp;uy3t&uG4y4d$~JRAa7vQxko8b zpGW`aZsp+ZasI>7K5=g-Jn^sddqnky6@Gt&-+q5jSmXC^$nPE9VT0fKFX>{f z7eYsC&z>T4aw7k5s@$bY?T=Ww#lV>A!3%XZkNO>v*I(V)T2^i;yweF5d;{ ztS}Fowry5N;?cS2x5SzL%ltdbdapMA?kjebc3*#gIDgJO-Ohcm`RGWATv6yZUmXtj zoX=bB&pLhZ2hg1o+eN9Kiqi|~&x?*wvtE$ssH|V5bO&da?E~lp9oZMQNBh0@e!f&k zCDVWLw61zp^bO_gBs#I3JFZbdm#UuLZS**wF0l{a9rHW3zteSW{KVZ}@JH-dj&|wr z4ONeO=302*0NJ^gywLj*c}f~zcV_x8nf^xBvXv=rFyWnf}X5-!?Bt z3Dfmo;yv!2y0q-G*?)U17`-IbfiNAMd`!Dg+ z&_&+$|9%g<-X%KAg?leF{+F-WUlLwMb!;owIBN`y@ml@;rM28=s2=Sv$Qf~cMN}Lb zRe6!oF3v~XAykELK3*A+iX6*~o!# zg0d&5gWO@<^~`_{)#gxid&F;udW~PVIlLDfTE{k(M1B$a#@h+*ji1hyLioEEqW==* zTwmp^)t;^ToMZpiSC44H(cc(3U8EIvmrQwE`7a+G*7i)+#u?UsNxZ*&^oSPv3ysD( zN2u)BQEI$`^I6VqL~lyQfnQw7+4{23SNlBwb?}xs!lKdeYfki9{JyxCip zqSx4D9d3PisqMd*zh`ZPrct=9Jkk>T@;jb?@^|#x?hZ~IIDD*bO%(g#7ulzB&&F_f zhV!uE5PtDrqgw*>k7!SRkIC<&{O(4F;xfK|?)SvF1s((L!B4&pz9SC${p2I=H0(0& z@8pto7~DqS17_6GAdTp<$b4nA(ygiwcL9XJq+HCkuf-;q<_GB z;T~k{`5V`3f8!<{a6ikAQHjHNwBuWT54f>A2K12|37;nM{OCX^JiNIp>7Vaw>YwjT z`X^Aj=jr;V9rGJU9Y4|qF6e#u=zaL;efa2nsJY2JMS1$db>3j-`}H9AEA)kgPm3SV zX3ir`S_i>Rqif=;o5Ctk-R^KQKtYKMEPjkF7_qGs{i5?b7wo^7n-hA!#o>%DhcEgF z75LfljSrSY-=Nlk?gyXVOS_65O{cs+l(?a7jo;&`JE7T_%p1a&L$|RLBc2a08*W(R z`PZ%SY5{9=zQ0%n${pmO#}sQ*-s6Lyc{R)AbF;!7x9OlKDhf^^^2OSYC?7@+HUj1- zxx0*hO7w1r|G8xUMU6W9FTv~9K+{*~z`Sdce{S}ZF%rBz_CChi72E@53XH$kaIbNN zDcUh9eVF@HgNC~%#2t~dJ7_O_knOiC-lKyn%UT^iT1g^s`fa4v)Rq*^6qDuuY~T%YCbd9 zh5PG~10?sog%=IX=1{Yi4YB{0d0W;J0TFv&fn~;xz~i~d57sbGvEC{8Uh%8q*61r# z$-i>DDToY7{DU2;AY(B=rV#uochJ#~3j~Ly4hP|58sELY5Y2IJ$w%%gSJ0Kv#IM|d zz8s&`i~BQlUrFhCwG~~C{J@|wZd8*#NDM5D^`Hp^0NGnIlF{^C~D#lz25lu$OoPi z`&GWQexJAcb1EPGKi`fy_>sck?chcF5u4vWi;M6TBaAUAQ}SB-n983sx-r)zb5~*; zM!mt!Y4J+u|C4GP#(b3ed+5=G$aT9f)PCB}k~!LZBnjuviM+kU+=#9Xia^K~8Xc>& zKez0qvT`50A%pQU+fV(g$ZxaKgMa*>>$f7uhfnt}BF-fkX?``jfz&E4`h^=xr>&FKSm?)dAEGpDX1KJ(zD z`&x9@?0Fcx3H-#k@G6Ph_p9E>ZAOpr`IO^tsG^5vw1oQ`(sYq(=N@|doQw2&<>vT~ zSFQ6ltO|7d*Q#Fo7nRdg{Yl3K#^1wPhMJY>#<+Hh)Q`Px%wJ}$=ar-5`5};Ii_h?Sq}1>y77)H#DFuue4gi`NI3E$ZGD=;eDjt zUiC_y@6i+D--C>0yY^~&2XCsy-n^b$wd65zw5v2xAiT`CmTC2^W3sm{}8%OK&eX(UTGO;(Z`V;^-)e2=j+|T1$;ex3;BBa z7V(9~cx}Yph3t^?p2EQd?n~hQ1b!lcqX|5ezyk?941DJPjT)=vK}mG{Mt3iec*ZK*&v ztH(Wt{|My>9p!Gp!+#WqBh+*3n$0DDY+q^YNPoeGH`!)!^S4sX_F9DaK6|9GBWjX& zJuMFLXRJM!r?@x$@CM4G>@jdK|BU<$90K)+UJcwu-uEu{RGFU4^S9@c>B(#g|J%Bep&Pt0@k(kj(+7L)>x5U0L`~uc%>=aN2V@15UEZ~W+!H=PGzN; zotS-A|3%)d$n<2QLW8s5bX>`}k+Ifn`$g`NWqLAxS!}jcn)HOyIXcsmaeV5e-I~l! zjLP(6rfh98$BRUPJKk~Gjkn(X%QxNlj(7ahOh#bRu+tSs`qKqD|Gj4p{!xdD{>$D+ z-+TSp=rFyWXQRu@ZvSPsQXl``=iXes>GI3A-hA0v8s$e#^&g+|bI~w+Bje?iYK>In ztK^I(`oR}u&*ZB_Z{$R*g7{m>-Gj5BZ~on#$Dbvd3;s8Ew?G}>PEU8g7qusDE60yi z@3F}1)j7TOn%M8v-TEL<9aF(24g8PrHI%20aCQWK=W(tSaIQ3ub0zafU-05DobXi9 z_ms!S%W5%lj!5ota&Ia|Mx`E!yyz<6W04nMiOhjK#olayTq)oTI9i+M@N1vf+uCn& z=zFchVXMHeQg&VGzN`6NZ`WHb?9zSYcVOpo-TP?d-6H$W*W}BK`Tb-~>6>_ywzs}s z_Z?9-Ecz+J$j8ic`UxrjQ{7m0_?Riowb#L%ClHtrk8mJB0+;{nK zah>V5XNS=%^5y%aUc(LtDN}SDM5ZP<)C7ke%eCASX&k*@^gpKfhojD4@?O+VJ`3|@ zltBu&@H<+NFO#6Kc6L-~H6l0M6dLZHRO3Tob<06pzLXQHPukyUd5d_*+8_uENLzVg z*uK#m>@dZEbQNRwmk80dAng58? z=k^u4wjuTp3%(b)a)$AjJfr`Y^!3{uJ!+3YyB0?~eYKoPaVKrq-IIyXnR-}gm!9XM zmm==y?MZt|+9WJKkt?qw%)BiLdzLqpl6OJX4|3&)Isa5&rJw&}uDqVQs9Rl`0d1G& zAHT-6X$8Od^)6iS4!U?NvMtB><_~vmA$xz$&O}DuxHR?~3vioHSa-0DdnJ60Hpa)R z`OR13Yw(FKjL3H@ZNz7v6D%c+PyA})*A0J@^y{2~RVZtmu*wz_E@GdgpvkTH zsW&I|v$(kaF7fp;;>x#Uy{<1OZ+=&~zf|pYWlI%q{O+)xjCb?~edEA3-Ym{}oc7r^ zZBSlq1UtxlL0`_hr4^b(-~Wrhgazs?VbFUWcPk0+^}OKK*LfAg?^p91ngmw^uena{ zH5CH$Y1=m{;@_Wy3)B(sERsgzs$sA4(=quPuV&#sFPH;9?@0Q^QtCims?=rT)yA)X zHVWyTeD&a=y^If!0%PML0F|H(zRCN ztWbr@0B@5|{=SvCd3*PCoO`F5u@Dq-Q{FhAb^CcQ@I9{ve&c-BFTgMGyo%6?{$2-) zEZ>HCdC$_}nf_u>Al|HNd4p8hdz?~t*FU6RJq=AB@q(~OUe|ik7D2%8+_jveP)^S# zUA1tl4syklIE`-7T5ub5AoOPTCchyE@&n7DSDIb zI1q(8X~TMt3FU3pU_A1;!_yW{M0UJI-0Ky+yRgIa!t?m%&|mWTg5+W2JrsH6i2Fdhh$CfBrtc)}D`@)j0SZ z3&}ikFbt?m&@@J)UvuM7xA%Kh?%(U=UW>S`?5sWKxiBe1=Hu9o+v)ME()Z%W!}$Ft z^GnmK3v+?GD96FQlrc4*;Mq+UZ&|C%d2XIr%@~N!Q{}4A>HP)H4zcm_ip0IW;3$NGS{+o1MNd33!w&8*|i*GG;iaD>5 zbx8l?`@%j&aW>FyD!Xn^DEt9 z{3h3b=JziMZ~X2NZPya?=A{4hbbX^V?tjwLmn7?>jQ30WJ(Z+6U7w9w-Q3=@Z&^5F z`dN;5)31>Jc{O9|U>JSZ$$5f{`n{m*$&y_kWp1LMS9(k-h8Ku_%P&7L$a+>7@Twn) zb&UNE&0O1fos883Vesb>b1Q8qbHh`vUIBbZgMJsJe8(NkYq1LAZ#rHjC{Z3`qykT8 z(AAhlnB_BL#|uSIZnym9MXaH+KFWM8bD^xAhgmz#F1L0DYM))#?EJ!-Z<71;4?K;& zEa^nfDSSiY(&RVo`askj)|XPh7#-5_Y3` zt4-yH^2*2<|qe0Dr+pFO4mKP)A28hA*z;7X1{-V<*2$ z;4b+ny{%lrT_K-`q`Y46{wKyIct~DC!x|7Ae91%dmAJb5Bu;{Z3oWXo zk#$jUQSf%-xKmsv_`N#8Wi`JW#Iy8l(s7Y>6-;MI`!(92<+rw%zy9tcg>?Pg*`o?| zbfI-mRFL^4Aiw&Gs3hyXd^&cxZec!oKy`<5CLjNP(!ZBcmn7W$-uCil=<|H?t#O}L zcnP7a=-f*?kM4-{XnunpYA)|HQ_Gv4ZYb!`L+tya2VK19g#$W4DGou8Lf37R<^MU=zxmsF!fzEQ^Su1m66aFp``stw>ZSeO1o8AznWK|<5-#zY z@@$SbeLYFjRp`rNw_O|P$hfI8Z`PyHaGZVPc>iJcZur|b_IXQzeqs0>&S(5U%OTE7 zrH%9xvr2MTV~D=039I98-AOq8wWwF1W5{@uzC1L_m|>4NL|nsNr!sSaj3Ha=S&2K@ z2dWO|u7T(H^To6K40sZDT0GgeO~I46ss%ilA5ywS@CMCpLZ-MYy{6dO5@Dam6srfK ze0etf3GN28D9OA6{Z>N<@s~U$ta7-P6wOOoz=m?fCkBY(h{AQlBYoXeWEQWr2l$9tcM|3$*CLPJ#OI*dYrp8nmdndc!|dz$LtSxGCx$^ z`p^;%AiF`HRJGxE%@BU84G$JjZf?-4Tl^@Oy68^o0e(_`kb_1g`mfC=O7f##JzT6U z5f-fS^lajSv!em}BnS|KGX7K2tl~Q5$^CAP{co@e-VRt1xDdWq;3DHUfL4~kJBJng zE5KTSKd=D|t^=0w2L|9-1KRh3fECgQgSamy9M}NXfWZRN3uI4-;M*6S!U`~0PPn*f zH@Qy${TNemzJZ^;i&7;F{|XQprB|;Suf)DP%q#3bMV7~24KE?QYo(7e){+hwtRvke zqyq+*QUdpCeJVDNgv!KnhQ@t#(&9yhQ843Ht$fE8dv+|aQqw1h_skRvzbEulBz z&l_D8U36)}FTdFj_|@chjo}Ld-s#qL=o)Th-?W^55AEyFUe>(Ywok*;Gv?E?mo7ICn%@=0Bj&=dMD9%H zS?8}lkH6Y?a*bqPTuJntDkCxWZjeJF8x1xg_mH_6c~}~r%Er=pRDDG;O{+lYG;zX+ zoX!tEV07>mMgF9fve^^Y*>^bm1&&vdFj*T)d_m;uqh-xhPn7f%Kxiy=vvV2YVd24& z$SS4W_s|Zdc#Erha~$Ru%~+9km$xgcs+H zGrI@Z-*N7BxJ3?j@8xkgOMM5K*x!1yL=H`w;1@QR(scJio3%o3@!x=dlKwvY*Wo`| z)-?VoKw?(^Y3RBmnq14x#+D#Z|I@DHHjKVd|7mIWVXq1ddQWrKFfH%NGOwf$Z)80b z86joWsFU3wU(~y7yLS_E#NL74@K9jQLd#kFX zR;h9?V_UI*wfN?o>^^$h(M0?XYeQ$Iz5WfSQ zyKglQcnkl=gj*HxjV4?$Oxy4dhrGoh_2{GiebwROR%j3>ds*|!ZRMNc)fXIjhsD$4 z1wHz>YhddR9tW=M(uY_>54?4S{ua=lwL_1R-=F5YU~S`hcBvZn2#|Kr;1=Btcb~$>g`2Ror^+%HFRYA)Hv`|&*dKmE`dJ0s z#r>tO(gN_1GT!o~$HN8xW0UPuhY5?9sqzA7xFA+uq1X~c$6ftpZK>>yS^{tqo+(K1 zt$?qLLyPkq<4v~zC!DeYT*O>NmnTOK6rX5ufb9iX3p2X#9LJX9MEzXAM~27;s1 ztq*wf9QrNz#$R*zM2X&4A8oHVrx1Ki?84MvIB0Q^J~)0q?Fy_qoXnrP@P&<0S2lFA zWkV-hb`>aPLnkR)%8fiXpV{(Q59J)){GrQd$>Uwn5B;Cpz(ke6^E z@XsQ6hHhQwcNPCiKBp^;C0U0gjmEFR+*ieKCs6hZ_RWhwQ}%qMIj=h5l1B2e>nr0~ z)>yeq(Z=30@|brh*U9eZA`kp;wtYo@Bx6a^%KsVD!WYbxmXuS{9)~7!ci zFyLKoSyiY5E3ARSBZs%bL*G7Z*9QHkkvG8_MCT2|l~GZDP~|o9j-3PSk%_NaALK0s zy=kAPku7M}w<>&6HIXf7bcL!%;SKDWAG`tdm3q_@8cVq$e)RzpM*rmIK=-z8Qdj8F z94AiZ?B+NZ|4HP%RrQ4;BbDEujC#Yxk1Frtuv;%$VywS{ww8jA`{hNCC~qcSe)a$MPYKm`7>Lt9DBR{>7TvkSjzh^x_D|z{cAwizzsOVf zRvEX9U$5ZR37g;>dS;W>`GP0%cHymtj^gI5*Vds>2xgKk1e6=l4)Xp|TG!wM_jtj1 zU-SamV{?BhU@tBFuJFB6cu%v>>NBf;&z>(eU1tUHU8We&AevKY8A}vR%KP_3z%5fxdU8 z(#PY?VVLB#Zsl!y-O6n`#-3g)c!s1KLf*5J`E-KyJ3KNP%9^xp<*hohFw%0iwr*ub zM;5MUSrGRP8f6*|OXw*gx0ibqRj=x;7}bw);4*adFEKQll4 z3!lhz^1fF_eo+FK;BjPreVq=v!qTs}gSr{#njX?4BduRFZQ(*?XjI*+$u#cvIVLQy6g; zF7KMH+Y*KA=0t_K&y^R?SLKe*{``jTo5F@wQ86&+u6O40qR-yhlur#_+;qD%A@yj? zQ3WYy{EGg3=NC7XO7!#91?6wRe=pxxsmF279m`MB*H|xP{~~#Wv)`;kwI!V5r#6SB zXiI34F|;PxXS9=#^e6SNZfvzvj_e0zAF|#&j#OZqJzL+z8Ktm!dY$uH_;7DcSd>^_IO{_yqG| z=bLr9uaf$3&+uTy&oC;@|Ph9q09KY*7JIcNYcQ$=otnrI}gAm(r)koYmkBL7A_r&$JY(TTHRq z7TdWkb=Pr69#7^l?z;Yl@iZAfSEz1mj_=$Ozf0nCHolL2TV*o7DpaY%$^4yL;q;q#ASXBy7HWDCF{VVRXaTMF~7W6MeL3Iayqu;eo1ZMHM+8* zN7r*PXCGa994P*k9Q(G7CJb>mPQb^%kB46Fh>9WpL-tGMTacE5K@lBD@C6Ohv;t{^x1JIWlK5#VmcYjUF-$Y+(V~uONI}#YTUtDw{{c{I2r+>=cPVktNgRqvQxTbJQICz^sE82BR zB@h`?Xw!qEw2Rv6+C_c!efAE7v~~Pm+Bz56`BU*v5~%&)%^$tI=hmo-)7J zX4AfWDSf0r40-g06)SXIU?*)Nkn)h9*!~c|d1_yX!6Bq?qbbJor2F+m7z^M}M61&0*?HIpVJI z30|5xO&tPX&fU!?h!1S0iDn$tXSx11Ikp%(@h`Z#1mGcOXk~T3S7t93^BjXzN%FXx z@geKjIO!`gSF{Vfie~u4Bo9)PIE)LaXI;VvmfPRs{5Bs4FYa?IAZI7MISb8LV=5g} z@u}mcPMo)}R(zDUAg=I_Um^ZikVDRbo?qd9n$Yt;*6Fs+*q1Pg^YGB;%E<0@WM3q8G@-IEX3mp*o9R}i3=O{-?S|%^&@`q^ zp-Elp%lNBwF4eL(vF+VVE7Dn7F>eU1>^wsIH)PGFpI78#jt}@`?p4WtMcPK%LguaL zRc;P3BW~VWC+psGT(je=d0fKmn_S!jo4j1zoqyHSrSc#dy({F=;%b`Ol7q)Xl7 ziMzS~NF6QC#GCYw4uq8_`gE1LRq{pN-EjH*s^r`GQ(8x^Eu?Irzny=lq~9M#zvB9M zyv;$u!>*0=Ln%{eS{E92zJ`A2);qb67ziJktm*2P=y%92%$@W*paRy#eFuFDD0xoe zEMpaSup_4fvniDOA>vN!UKhGIxyPruHMlf~R}*)0{_5>+9NV*zX=M-5hh>i`b61ML z-3!@!DsCL^5c>7VTK%BK)zV$=p|U5EvTG7fTgvZU@_XY?L8mKpW#ba-XTyb;VQiL@ z`lkGbq`5y$v++{W^ym~1yIuyYm-%SQdRde8^5>KF@_#$tIR1H8N6w?CtPv5{XVW#J zL4Sz;6K!)od^CN%hTedzCBip_vVQz?(XN$4(88{%$O?p?GEX~y!BuoPWKOD{FMZ&( zx-M|VPw8>%zC!DH;=e*yf#!PJeID)2*sqEE4YYsaZs3jx*B1~znkxhsxOPnEyee*+ zzlB$ER?K)6+DUu8o^!~-t4Ssd;14rR|?7T_12=HsX%J|YJMOGOPlK(}<-QAzhdU+jn!7X=*f^LU<+UKelk)MpU zPrLj~(am?eE`ndkJ#P893HC!~pjaL{%4KipBQhbG&+NW)T09jIZy-1&p42rhQ-iO# zZC|B*>bPy)k)MuB{rZ^W`6BrAIV7ze60SoX!(1y^duh{ z{kd0O+!9TWi^`UT`Y>|%_)qEY@Ut?vn@e1L%VQS1OEvP3mbh`#T&HpTYYV8;7x$Mm zZC|w*&GXA5PY@bK zf8z31Nk0p6(2X+V$DF^k6O*ge6O!?+31`Cg4Q0vPaLRax{}LP;&_w7V{8XL#%Na!# zSRucF{%ymW`k=%SdssqS=9kGc&dKvl!tGrKS$7j1s(7L6Ck@FH|Hd$9qHUb%v@^aI zGQN_sgqF>1rWeJ29sI^WKsyvS+j$}8P5ui05)a2_-L?r-t&%A8K)Dx_0d;e44XF zRj5ebGOutJvXkE-v=o_!$+`a3$g4uE-0zaet7KiIPd)TZ9M*_mQHM$b?HO|yWyu+{ zKsjRu>TZ5R1EIT&cj=2~qe(Mun}1s#>7NUBPbTMO_FTG{w3*anhJG+E^lc{$xl^!M z=tR2!CEs*@(zs>LsREBLH2$s_{^5LwYsj6VDL63au#WikE!XQh@kM4OeUG&SzfC%( zj^p^7e<+mei;+PrrtP6~8h>?+{PFJ!#39XO7>NCEK^l=yW z6x_Hg(Lbj5b-}UT`F3s7bElvRE|PY7yeeSaqrOgEE=CS2a}aA(Ro1EZqF=NkB3{B{HtCN^`|I~2 zx4sKg!ish2edyzSv0(c}^cRJ)UP3uJ>AO+h-sf8JPJ0JS!m5M?7f{BM-FEL#TLPVE zFVQ8bK+8%eGAs)>TK%|6&-GSkuF`XZZm@T&^t_qzEO3*SJ3p1%w`#fbQ@Q>2DY_`4 zhtj}5fJcrWqkfbd0re%|h5m}9omfJjm;FnUM|erP;pgLrc&G!XqPxyvK-m&m|R z=>z0%c?m^)$%FAMbE!E>e(WKxmG*aTc%_l6foSuJ1!f+#QiJW7*yjL63Yj z@2HB5sIq{(6ld!HD@jM)rLAkMp%HsE*&9V4bA4Dp9C>xq69zNf@tM9iZb-gKUiO}k z=&PUycME&;_(s-UWOcz~eEHrmxQe*>CrVZNgzWvLZ`7ra@n=4FmzDcOOPx$rUk%*} z(?_5a&wopt=xX*_vEq8=UDhpr*D3DPgqd-Q1i~<=2G74lA$S9Ce zAfrG=fs6tf1u_a`6v!x$Q6Qs0MuCh183i&5WE99KkWnC`Kt_R#0vQD|3S<<>D3DPg zqd-Q1i~<=2G74lA$S9CeAfrG=fs6tf1u_a`6v!x$QQ&kGxMkbhZ@l&9U%qMSmbboh zrZ^HdlYi<*`t;|_aPQ3CKQ6x4u6q5-`+vdv=-KEny`E>I%P%iqdfC$dxconEx#B-w zzO;JN<(F-}`LfHJDt+rOy>;n(Zr%LOTblfuf3AJkJG=UCyS?kO|Il^W@~i&Cl~-M{ zylchs%dSl0Bw43U9>!Pdf9?mhiT^&X47UY*lh zd6T;rJDdlB>X-^HY2c4Nrrw6~)DaaZ@H=k-HVPN2VBR7Xm_Pc07k}Y|r?6Y5uvwtlM@{JUh8n!D)6h6 zU01sAYJOuwbE}12x{v%0>|CyUAC0_QpliG^UtY}bCu>UI#2etf_4T^%2(~>5Qws7Xlecfb-@c1D|%en8u$`NtQ#Hm!(X)rAY* zVk0@=ZDOgn!tLI7-(=roZ^*mH@|H06YUDliU|Eb!X#9B7K6o|1`D%O(zH#2LmUpi! zycHeH=UYk`pZL|pubVfcaX0v+pMIV9sw=!TJWf~zI~I$0FFF2xu6!$g(a$9GVRx<0d*9-&@^*8TH<|4_=fu15yTf`i-q9QMjRV`XeuccF?&h)v<<)o( zxgl>N_vO4>uv4U<@BbAX)jltn11;X+=%bgCKjl;@$J*rnY!u47{w3TyU(K86w>!56 z2kg&zA@3&(e2CA|arP>$vA@1%#SqZLcK86lSLp`zs`Nzmo$X)+{d9o0wRvmX{l1mB z*lov#gkCe?X>63s`~B8d`R-U(`ShARd12Qb+Kzw3=<$!>NB*?{dh%Jjn8mzT1IKYb z>-NdhCk}NQ=d*qReu3v~V$gr<(4Y#mVO}2FakTj}{Y7g>KD?HBP-(G?DSg4UxAc>z zc`N@BFAzK8xobU)%J`bM!mAc;)j_U!5|2^dY?pr0`F+bE@~c0q@}=3HS9&FR6=*l!;yy`R&$Dlf7YkF{ z20Nuw+OL3H#)G*j3@WtC@`4v!#+&h@*hp0G3M(5gg7oinbCp`<1xES}aZGGs4l^Y- zeS9zssEfRLo{pR7*WB39ymMdeypVj{JSgt*4;t)N@y5OllQK@)MV%hMD*Y#ZJdEFe zGQTvvx)7U17v+MP@(G^ZWbu~u!(fL~_>0x_cT(59?*pNzb~=%O1lhUSGA3`=gW^8-O7AdrVoo>D|7P0VhafS zShHroU*9)7DvBK!yY8_5-TPRSUvtc~l*Hcrv^<_q`Zc5tp^ZvxEVWVoEWWka?-o8w zYzfrvj&y{rXZhXWck7%k-Oju6%1^_c?PD8$V7)fj!FK7ep-@QD9oVYdh6~;-zO~dz zY;wxlq?A#NTR-~GyekhsF_T?E!L5>y{NQo=7c^?NIXD?6xLq3i@}_@{_x#0UuxHWrWXY~sGB?rBD?O$Zvp&ba<(D5AWR2ln{wniuEVf4q zd9U$08LQaW!q!ZnoK1)5DOaz6ck~0KzbYjy)*7C-s$#2^A zfv7vIFQtAfjJ5T4BXMQEs2FU45I>zW1W&uxO5BaZrC^!x0^|dH;OSwTzqGN~tF!s- zi1JdFtlu^tNq4&`Rfs={Ut+WC>!hC&uSfEC>9nMK!jx>@qmthF+cw$aaF)5X@jCc= z>=@0b|ICLckUTGvdhpf8ZqU+ZUFr`ky(NBaVGK`W{Cik;g9H5~Js*ApzEy0%?81K+ zbNH@TW4i==kKB{Zx7!NHe2BwvXuc41PS1P96MIPscsso)k`R7qob7I0DUTjRJ> zTqgLvI>BW%zZ>Lb>DgqDQPx#3oh9wpXoHs6RQ~$Aj}+4Nb0_wn>e#^2JyAjCmw^20 z*j^T!74qrW;kt$SXIpu6 zN2Evd8}v|fd7qhD-t=@sL5Ch7_D9C-Ed);x*;j9B=x1lBTQB zm$BQ%{0|)&H&y1%I(GZU*~^XhA7(#=znwR>m8E^f=5;uq@dGV~IwRXp^b@m6VwY`* zzN!hU<8R$bIQ_M#S11|tzVziGY*8!rZ9~L0t*TsRE|4)~YdtG*Cwnv1;oLRw#Gc&q z!?XJgcoKG6JlRW4!IQX({Y{zqA*EXcZ_w-}WQrR*HpSMK2>U;#SjA3_*zXQ;H=spH z<`w9-8ajx-8JOH+6w579b_4wQ|O-LU4;)y!^fN2WhNY+Q(Ve= zF7Z;jRIZ^v@!37j-OAbPX74F79_y^zlQa&# z$l9LfA$Bn(4{vH7^|@2?Ft41N$6?Y%MPv{nuQ&s47})WG_3&-$SF$HF#fo{VB>geP zc^5dZo&o2y-nURr`~&&`<;;ZlY4cC&ljc9YK572JmzrpSY(!{*UA-yvtS*>Ji`a9t zsLf&x#12yV@~9}b?qpwU*FtR7D|q?xQC6a49%)s^Q!Rc_qMgK^c2F3E$K*pM(4hWe z8-C)%gLb^P!hZ>kg5sc8`vL1J_QM+jy+JQH;oKF0KH-VGA@IwtE^GHjMOpu>P4~#v zN!ov=c32zlqdnYQ7qOPFWqd4x=H}Z8&1ay`>1dwPEv5N%x~Vp0=c4CLw>)O1&seva z`&dfr27OHE8x(wO-M7Q@`polFX zJ+{tB*RfruI|p>t!d2M*6!&$yN}tgyDq35(4jaqje?GX7K2tio39$^CAP{co@e-VRt1xDdWqAolATKr0KlHufv{SAZfr zY5*I+;5uL#e_#NfHDHah8o&zagF)OE6Ao+uYrtRu;R4wc1{M56!hykZ!o^LyRaqaQ zA7d)cH}I?B4yuF!D?sFiUcHKZjeU2R$M#}AvOM-`cnRTMD}9u)mUO^i9qF*yRsjZ= zQU*|L%r$^wpDuVk;owvO*2JdedfdPYFhH(b16F_yaZ|S{pN2;ZknJ|`58j0TD~S)R z0BgV+umNlUga3p-w5kAWbAhC*02{ynSd(ztts&vS;LW51Rs>R34XEjlHTs|MuodZd z$ok|r`vG6%ee%1;?|SmP!SC@j4m8kvT$~DYs3yO~j$J+Z9nkjUX&ip*y-9rNRZV`& z{8;CA9lC}a**7hx-$VO4w3junw(ZmK^o)7VSnNF5<>o>4DP_+?g0Ce0&pLneN&MBm zlWSxP@-Ft%A~&>ivDmL0K_IS?74hdyAv9017mkoG?z1?GzuiM#OxrGk7faTGFGEW?mzcCm zsF43JXDb`R}QinqA>HpgL}(To{se~ByW-$TSr^K2}m@5J3Dk^5M?p#sHjC{Qy$ zHQP&-vL|h~wm3VcYvS*O)&^*TqlWI)gzjk>0cGe%$PXTFEwrwP`#a9P4!6jy?!7z? zXQ}TX!}?oqmdJjI6a2#FQkw2w>abSmBK{ljPtxCq|2q8BvJM2s{|5B!t4GD&D~C%5 z7^6=H{l#wrZ@ThmzK^lkr~8XH1GiR>=6lU(*a!cA;Ehr7TelA67rr&NG&I+%vZ0SC z_CwMq()|0_3-zf(;R5zTz5hx%z^&E(u$MM`a&A=UHOBi!&~JIETV#Lqc4hZRiu@#( zUiL>f9oZBfgh%Yt##8H5xi40p_&=HKnN0m+wy5s$*b@D zsIc%#Q|g0$Tlvy-H(zc11@JuT3Ws~|vhChY@l&PVf!^>C^m&r6FWTYtel!mI)CatU zzXE)Ehj-x0e7?7;O7SXH?oH}`fIc1nt&>|>+;f{9eV#h$cVN5oJN(n|CqJ*s3*iZ$ zJaMay7k|&i>x0gMvsvlrV6Il>Hp)or9si@-BlbQ9ed5PU2gU=vkUAYYUlra$KR?VI z9{-%nySMcJvG+DmauwI1Zgo%h=~JhBM$(8Mfw452=^2ecNMgVkFh4aT0q2a6kc96G zPH-6gi+628WNgbZm@@*~-4a3$eqOoGx><-BA+Fa=Okz7X&P(z*5_qM1gu%wK?@MwW z3kh(X+-GC#csUL+@7q=9jCzLg59_X#b>F)^Yn|Dr{&wx!wX15^uG6)Ly~)-4bYGeM z;I~sc*lTVxZoCittJ_odA+O8KxM$#fA2g|dOlc9@Rcbq&tjEOx_*t#Sp43zAr48vB zTeU0aNxZ;5pE@t4PCo}cZlU1cCHUz>!T-`V@Eu(J@c$**U-s;+^s}Ed%YnpAa>l$p ze#9I2P8@7kz<0$#|M+3+`%~fnQ}|P*{nco^xE&rO=^imYcW-3}I&lB7_gXqFUGSsI zxw@1QIwr5|(MMUEChr*1F9YqlGJG1~OmY`(Q1q$v%h8&fBdX6D??|#VsA8Y2o_DRT z()PaGT6phxn8T(jv$4sB{M^Agb-#Hucxlsd zz4J;Fm)TY~M&$BR2?kHWukKXG#I`WWqbIU?;mN$Uv=d-0c;Z=}v6=H+sA zc|pI3jqo&Mx$i3GPR`@EVUy9EZwrn->KtfH2HTSUU}rdqTu%m*sz2yERt>f@p8NK_ zP(A|QogZCVmi`?0=;7ey!nQ#6u`;&}gcHFI;LgUQ!DAw4A+$^QOFiX&=#V;ge(7Y; z|L0>?ZXYKtS*0rd@UTBoUZL3G$5XETGFOKWn-1}PD!PcD(i=jrj7dxLS+O_W|DQ2| z^iw8V)t0`j(w9d_+d=+;+9YxU9klHT@Mvu!coF!r2128>tqR<67IF){$zMBq3^oRl zi>jPQWB(U=lP6u8O8d;xA~M)KM85(fM^pTDmv5jk;p&D@wr==j>yCg@H++)1rC#H; z)W`a=5!pz-=DQAb?-qhjk$6xsr`B8Q}&Hh)99riSPcFmqWLhp#uJ-fbz z@NtFu?sOsze}$HM%44ZFAg(?V2j)j^4wN&gj9%%7);!4%-u*=vFXeCW@S0;TmD+? zEvH?})gOAxY1eYvb;nQQ;vH$bL{|}f>R+5J4WgF~Qf`oPgOnRohrL0{4N`89a=X)V zgYaW;O6kFrAIt9EXUCzSl6^^&$L=5dkc&KR@04-N`1J~2owO;Q(O1W`&KEqfWAEn~ zJx-W2RNIC^!Jli-?o+Q%KRDggwbg&%LC-(?Y0sCvE8hzF>`_I36g_f=E*G<2&%+1w zI?tZLonS7VI!*s$2ROtW_#BV;ITt%{C-#SRsU5fz+e0Vz200r#ge~j@XG0>R!K)@e zZ+Id&xTZ%xmplqwqz{4f;F|gRX4b!hYkYlhjnXHQEkTgt+OXy>yopezLbOw|g zRTIH}=F=(G@8H-(AZyZwHM_O3&}ccc+OQ_n#=?y(3lhE+JY%}79u3w}r`TBqpUm-{ z@IidncfyMU$wavV{}n!;BjLyWs&D|>{2wzv{4l7zv+i@ zVbfYu^yAoD(4EWA2S;}co*MfZwZfGNXh-8LRgij`mksB;pB^ihk@Iy0RoX=S!#rQ3 z9VfaM>&j_ljrBtI1A-%1c$*IJYd#}RZ3)U|YY?Yn=%!R}pAR09C-oCIw&qih?6X4B zH^wK~ZSS>b)|)!0_eG_D`>gZzLhNVV^v^BTT>h5oaQ-G}tW<}~oeOEB&_}+ncDsCK z$@c}7zvT-i|2*e9lIK7{6{H=vfO8%7+)_Yqf9<}C*nZ_)c|N?$c&*;z_z|D)RqE6u zJd-gaV~2W6<%PrLWRdeD9$;6NeN@)&P7Qf-ZZ{!pDJ}OJ3IE0-!D}bpf7A1iHjlo58XW;L}w=@A6-W5i$1zcgiX*tZm@qL z>&$H;BVz0Hv-)6oO%)78Hhkg;w3fI%{1CpQm>Wf?*lK(-TX3lkrF7VbntwhK6)qU^jgt zkos!-oIIFaGiAa2hF1xYjSPpCiP9{Ym=&(4;o1E)jYDLCJO{jg8(D~_9DnJ!l1A=* zWV{J~&AYvdmbTG;KISN?2KmqvAw$Hi51Bj_w;qkBkG24b6U&lIlmk=s`33 zpYzajuqz!$rp`sb2S&i;7`P=2Y)UvG9UF!LV((;+K{~J%m+)y?etDmk-@gC{dE-9^ z2GA?8d`5oNpAp7p&QppyY2W`zU3`loVV}8A_6Bw0<0qW1YR`4i)8v~vmHuhuNb${q z*w*BmN54BR#+<#0{;ipZXY&ERm42@7hu#HwX;whaDm>opH#Omcne@~N(2X#STV~w$UAlWZT8{@#~{0VcR;BDnwL>(GE)O;GAcf-?!K7}WBX)oh4>|Uv5 zUt{~bl~=SN2+aT-V zFS(YRYf2SAK0LkdwYEto>6s$*+J2)Q5p*{1b9$W2lXh=RoRrJL%{1I9Khj1^Gx?_D z&14Xss_KZgh54e^(oWJpDtNmu*V?$gkh+Ecc3z%Q{?Wkfb26TcJ1FJtnu#1rox;<) z@UZ&|vAC43LE1r(gqG|N~e?C;BIKOPI@dkhI@ zZLbU8Tf)s*VGS*<=}{VP#joD)#<4w%m{s>E@*#UqnY%Lj?H3dW~=A zWsMPiDqvlS`LtEm&{23{*IH}{qG!ebT%2B8<#!A+Cq?Ip3|y`20*5ZwO&h*U>+>ak zNJqf<-SqqU^fzO_CgI!Y|1{hnY)IE{A$=lO@ZaM4F`M%u!WO@US8+DWcop7Bf89zs zbQ=Ex=H7SFZr)?!>JkS(MIW;BCh3Ahzg6H>IeSFKVJo-vRh_Wq z12)#Cw5!T|&tuT#>%i8$lAh(2d}Vb+0nmVW!7O zxOG53j;%ia8nTbhEAxDEsmpKm(Bjf^4gB$t8$+#aY7$@Tr%g{kTGq%xc>N30Yi&lm z9!N^bDmUIVXGDTuUx%C|j|MXS!ae(@bvK3mL*`mpU-fmYLox@lCYj{Pz7p;}a`h|NKG6#qAeTcvX5=inQ4 zs=syd(oamZ_IEQf_BH7kMoXgaiH?eQfXlTF_;fLr}b=q$@!-#+(_~fR|$TNVJo$MqU+E`d${BmaLJ;)HAOpL5=*OI$9QJ&vkpKYj|n7E>O;OfqJRq zmGE80yYTlH@uZcvt?we|Mmf6VOij*$lg_lyq#bj}K~wlUpEPV!{vdLQEinWN-fVu- zgk{c&fF}m{HaS6;;2cb74bDY3An$blFz2wQlk4uFmVq`liBJBi zP^k}Mrx>K~MK@0KuS?K@epnz6Wv0{kZ4qUHb946hhk7+SSrvJwJU_Omi9e_-%sVoGsIJ@*ar60nde2 z+TlgWP^4b4ctwY9lE-|Twk*e1N`a^!F5yGpm8#|VTo9%DT!rph<-=T%Q zx9SG_w6OO!#;d?FE#K3Gd$w!&o+jM0XU6Y5qFWszaT6OW6XERdWEryouebz{_GxWCo&f~8?3&TJ|ayYgQv!gGxHAi zV2Se07w@sMYsq{K$`N7S^4(W zZ{K>^+b>-iZM*c6?K>{Hq@~fj-+#x--`c(9&Rs2Wt*`5U4^0uB!R$ukD zE3dljlAfW}mt2|UNl|A(oB}BIdq4R6ZF5w0CQtkA4IIdE-#8vEyc~WyjWQ*rmA$vr z{Paoj1yNFk4xmxui#T~X_eF*Y$?V=8E_icVDua#D4<*QO*1`Y<)5q)%TR~ z`gBfj=MM5de3Kpls;88H5x$xG@KM#*;4ar=%2&{Lc0Ya_2b6#QGUdmA_9VVuUiTEf z+!TJ?6u#XO?j1MW9ZpM1$s!=W|IAfD?tV?KOiI)Ko(r+{Z)Mi!t-ojMrxY5hS34TE z3;Y^&*Ojhb%R7EWw_DhwtKgg5zgqWw)p)z$tGXgz8RY$RP3djidEQswsH?~DcS@SM zoHX#n=jT(tCKlFSf0FxZ9p8O??)ndIare)D%JJXS_u6}CL+6Cr+&-fByZ-wB>9|+YqZ40)eqZzowU8deYWvJhqnvfJap-JaYO1?)tr;B zJS6QJcQiv_$`Q%qd~Owh~r1@$m{^xIyyQ{U|$6e7E-{6HY?-%n5An^hBPz!uU@CknwuGJbp@;42Q0zG`7kMO=$H%JS6jlJ94A5w*Ig!{}p$#36x zlQ%!Z*Op%-Onprr>ua=xfBKT=)u6A*W8-|{e9!p|LEh`|D+1ayFOUB{`0(m*(fYQZ zcfIG2C@sE4rR`2WM6OP5*n@VO=uAw3cYpa97`MJY~9@-(SB(rzCh%Mr%s+_+)bbSUCz!M zyLeZ;%luQLKSZuXUh3c${G&n({UPyMUGGIh3H~poJw|>C#(@!^Kuv?+ zVAT~&8P-u&Qha@lG6x0=JTEw#=PYC=pDzdwo9`Je5h(KR*XZX}{s4Jq zl<%hOIrRM}O@7_yRKC2>^UCLf3*Yu~-}#w-@jQF4d$BOHU-1(=qwfoZMYiH?fgjSR zs|%ig$yzU*z(=L}jUe2-n6A3hw%=E4ovbVJ#EJHSIb6Wl^2w3Fr!8{dd^SeS$CO=L zG(H5P?hC+^`T!=}{3O0LxL4n$NgZc=@XpR3iR>jOgXAM;@MY!I1^8T9ob%_x6W!B#t*9KGV6Tq)jwOgyX-$wu)bO2bJFmA_#t4ZCwW!b&)xZzdkWqZya{Mi5Ag=S zOH&emFZoj6QKR^^?P5Lp@>gTs*@Z(Q^pG){5o44>I`k{rUC_ZxR8pm3D z@OhKJ>8ZG*td0b;alD!GH&IsrZ!&tisDB>Mdimn8@zX()uZQg zr@ty?>CX4GO`qJTWBic2a`>kxq~#{J>#p&FH;-pMZ4#fTvJNU0qlCq!csqCcqr1%I z*HLH-^QPpVM84ortIx;jG@)%pQWAd(HGCAhgs+lqiLsSgB8FUWaI!lgm-t4@BF4EG1OfBzVMl$c}iXCd;_+w)?% zS^A8pFT#II`ll}%_EcI%DI zWiFJp^KsVB_<&nGeRbHbYj%ENEsjgBjgP!?OiMZO7bAK@V@3K-zdmA?2KAM+Zz#4t z^=>Dx%okydpB3_FbB54q*LBIedA#heO3*vN1AOF_af@I2SbWl2eEUpZ>JnYS;*oND z;&Mp-GxWJW`WEG9>)}xP1`_nAxb)y+@J$Yv^%8U&)+_O^bAb2*%;5(v#xD%?o*=vq zX#MTnAD4aNg&w^!vHC$BA1DcWah-4k&jiPQ-pkM~c*K`(nQ#c6XQaM9=>8Go5;_Ez z@URAihLYeAypmUZ?qoCx4T9?g`C4fS2@5YG%E-DXv?z4DCgF^hDc;wmw5;R3K|agR z7QdIWu0rWN>Ayx7yu_#Vw?25RkgcEl@vT+IznJbd1({!b@YV5sE&f8}(TSsVEAz=C zYH6^Pwk3a(%J(YTlBUQ1<-W=m`15A)*6@uax`gmGOnMkPdn*(BjGoAE(xa{Q{o%~| zW|tfF7wA#;ede<+-`jqRuar4D%_r%SuLWmozS-+ZRxU)A@rlR$4<8vf5%Xr< z;9Hh`V{`a%_HM*mpNe}c(!b(!JXpf`ftRD*#>$C4HLol_??#bTOc^u}2&wZ``RW73KmNL$=lP(r~&DR0~|V2A%lodvkOy{W)}!_A}{Z-!_9z z@~RH#V1CH>X3z~$x?eee z>FjgGU%L3O3KD!?$(+wTqP;EFmzu&4lE{l0U@wv!p60RtG;4c?L;Q~l4sRxo`l6XQ zRPRh2k5eu|_o#?%M`2YGZ)=I6Mx#C4F4P2la6oy zOD(*>4kNt4XWlbhIYCmON#eaK4pm(F^zwW}J zz!K?cxFPV%t}W{yHbq(g{7vY~#lq)* z;JJF0aYx_I#h;(W^Nep9&u8;ZbtyX+y=lJXar6Ci+cvk1WxQ@6W5Qp*Q1Zfk^U--r z%=0sOUHd8XAdeki*mnKb(JgqKJ)#7kNzcOAeCOhu^&cm`?z)Yx<2O!skLbw4wfI<- z@C`abX7o^~wS^n-Wi9b{AJ+TUNZL8Zn|45-)bHouQ5pHQcub0qcJ<;DuS}Z1*3%2g3(bxPBiLrx*H?(2QD!YZ z-p=fIYwUmhwdi)hP~ZT1uRweQHh|U^aD7q=i4TD_pLk#c=-&XW5D)aBvj(hDR|6PQ z-oKIXa?*hfU=8T^lP-`wp&t^@ZX*Qxt4WtI{T8u4!av4Tl5Y@KBkV_{0Ye}*O0OPa zXJg+TChAcYvM0- zBVk|&^syn=fFZCUVcHh)Xmm6mJ92|~|5u4Wm;AsGSOeC84PXQ4{~Gb|Dg@RR0Vx*( z8$cgelXUv6A?ZN>Hp&4*fz(w4YUHto{D}@5irjr7MtAJN)(Ji7dyV&c`rhEZndN~8 z8o#HuEPRO4ckv-uPv3p|zM19WT|b=WhhI_pE^}9%_d0wHHnVS9joicgI=q)PueSFI zbb7`-=Q(yB>~Zs8{Kv|kz4*_i@vpgf^#$V9;WKL_`{FQJ6-Yhd#}j<}VXwqC>W^Xf z;7{yfS$bw0%jQw_oMM_*zVK=4^;qn5CI5j~`_C!xQ&#F`Ph4l;VX)bVjAUhHZ7B1| zye;j~GFPipWqk?=kELyPE+aiCe6}pMN-29{Rbu<437o=)-&iB%g%_p}#NT5NY_KaH zw(XO6yLVhppDsfOOXvSD!$Ub!nf3*#IAd7N9ts`pLHePbY;|pK&BOen87tE7l2>8F zdWO6i&c-TaCRth*dynzms!K1$do#=$?>5EXp-*w>)gvAba@X{ohr@o6#>>s>&VuvP=|La@IS-FGoX1(xR z;x`eWmVb!&4a85^HEUh=vHREG0blo->9suG+~ND`FYG#Q(~yPwJEY&oy$JX-&l+ao zp04vsWOy^{q1Xtit45ndzGVF_bEf5A;dv4s72G}JUa<8LdZj6te{%LE^_tsnW%#P> z->T|p(9iy@?#JO&@!@ZO6uf zBj~kNjo!CjRjP^dB>r@|*PE{E>bSI%XFzY!1D(U(z#SubTR-wB{aiiI6b7!0%T@Yl zJ5N?_$F*^(A3e=n>h?u_tM2o*CEqLejr0Xa{kU|Rr)u_jeV`wect4i z`Fvlb%4)5u^f9&-`&UbE&e`tGD~=};H+i3nd;A@-7r$Fo2GFBUKY53xEB>L&S51A1 z#%o;L<7-u=3%prdV{|cTN8j`CBsp20Z2EeDb{suV6?QT%A7`yee#PPLD-U~ozlUcc$;za*TBEJy>B1mYnd7M%sXiVG$sF-(jqpt)W$hkkBbBFuv(2hsi)dY z8`5*fYFEyac!7N!QcYe;oqi5@+(N;>OYm=S_+PpPUW2P2p1&mf;GVsee)hd)Igq$X z&fT}ik9Y&$iG%G5_^vqUAE$5d53A(iuS)x?(Rgt?JV?^LY>Y4D9q8))$KGq{v~6fE5H>XvfHQteAX;8(ET0QSt zU8U`PxwY`#@i2$&S7;e%js-9Jv#oJ@I79_o@qUk&Hx3152;OlhOs z)#U~KBDT!a%Nq?|2oJ5uSZq$R6Vr5_&lC(0`nJA8A(wO`hj@L|&-K5s>5@>6<4=#_D3X+A6Vru+Xh zCXjy0WUJcJmsR@m2x&XWKTw-QPN0Lf9RVJ#O$09jU)Dfql(toYJI+FGp*Q(!M~}f4 zB63ls?-l11LT{Y7H1#(QT3SQ~n}_IEVB~0uzwXip8WXN=_+;ybPqyv|D0Rapsaxtb zUQ2zfhZ~WN_)i_43s3ei4UFmJ zMc4!Xz|B)B&!nvIZqBmk1#^|9^|nk__5?hUZwDTPmUY))gMsc!$J#<27_tV6{uAs* zhu$-8*9QG{<4v&!A-qAb#uW7@RbI1~-H*@uDe`O92hBcRj~(_jds@x<7NI9a>7G{K zLijkkfj#p>H-NuFOFiYW)Ef|2ABh9=BR2=i*;z)f^h0Z&B%QNc^DO@>4f0*k?y2$O9n39*M)a1%rZ49^p5?S} z`D?MaoOUf&f9NfzUCU|L9Y2YScckqS-AeGOe{r%jh#omexk1VeQf^Qk_68|8NV!4E z?M}-L!jHizr3X`fEW3N39fyKS_D@Y7yU*=IF7mX!Q^qah*DH8+(x!MuUmeprU+~1< zF1pp|al)MS+BOsl{#>>NpL%`zLC)>7w)zh|==o$cH zn#US|`|pUf6U?Pkr|Ey}6^EDupW_i<_hPT^#7?p}yKlP>Cj z&VX{G*n9RfpH8uU2gfD?S(7%b*{zL*M$6gShBcu!7H(u&knpYG8PjF;Xt0ht#U3p9 zWRCBI4~Y+i7YCAwas~d!m%27%qbnSMHvh-W5C6;~Hl2LQt6;wgr3DsLF!w;ryl_ z#)VC5P0^2IZ$Wo1KOY?3EqH3^;_*^fCZHXSvs6LqXx@elKS zjdq;qUaTvpku}x}*}n*mVBu{#P+Nl;acWCYHd})@9YZ&z`;7VE5qVNSabs&f^~ioO zBzQ2QqARWsSf9Fg2qa9xZJsrHVS>@`)aq# zSC)KVQ2ATFVDiuJF*eVEf+|QmZUN^y>ba%BegK_XY}9i8Js;j>ypHEPekfp_dW2^( zW@PM8Z>hX+xNN$d|M&p=x9t0}c89`?Q_P3mw`pmQ^s}^g{?or-Ztc$u--8)Go#9j9 zQ*Rnywx5R|h12;}A)*au@Vl_&pD+2*uTK7mc~ofGL)uVF-ZU(EnP2^$JZD?! zI^=Qe{vX_C}>jHn!yZlG?}>IvncN^<2W)M~`j-B|gltZ`&LP0pZ5$=<)Y@ z75{yv7!W^7oX9{;@@?kZ$-E2Oa_AS)tZ+RIKOp(3ufE9DA^9KVnZ||g&?N5x>L{C| zR$mCHNAi`;W5Fo$#zCJQcT%^MleAVSbx2%>d$jv%E#KW`b?omoMZ*|9F-wl6PR%$K zS;ekdnwm&#{qf%wE1ESy31t3@zX>c7W?dKA{g~80hAefl#?2e{8tnP}eG6Ed+@hXY$48l_*u(*>A>Y_0U%A(QV;iq4S)4Mz*A~*hJQ;sP9!5Q6VQ5I#1$NUX0;!Mh z4Xr#Rx6PD=1R4TlBg0{3qBKh;W`*l%cy@nH;}BUO&jIh>Mix}!_)N!@G;;4F<4yRR zZ1yTz+D7~N=%f_?1^Lhu6_9c0#eZI`G=Xo>cV_f6=dMI z)d%5E>F4Tr=y&mda(s^z`XcqmkJD!Ak#LPi=+ew->L~Pb?jAozeqbw4G~=i~&&k{L z*kbG?zwX-NLx-H9Rn#G`!d@)73BaG=xS#PM>sXWWq0ANY1ztrrJT|R^)Fcn%LfToE z^pVx}y~%t0AEAryxfPJJ6OVWMjZe5>COvh+w2AW;){0Nl7vvTF@j3E8haGYr{Ctk@ z(}bT7v5t0iCnZUfJkMV0Y+GHg#sweUt22(hj+ROM0yH{%2o7nztDub4N4S9Ttu z{~NOABIltz%<(>t{pLB{uSnlWU&y>=-s(NRn-w~3-d*-rJbaI zRPc6RuC;M}A$1G??fg5V{G);SkdyIbuY*$Fu8qi{)G0iz3lF=mKn~q{XV(u-~8##}ju|^m^pUu{Y2J&EjjlMY#JsMfB@w)+8OGIx9Wc~PY(XN%F@WQUC z*a}3SieGW@LaY3SL*}IDJduH`bzR`l<+^FZmuY>z#1H8R7{8N#KcD_)?AIiG3;myl z8-xw%`YohS?iW#rMJL#{RDTnUjU%=eEk#_SQ6IYiwXcWE2 z&YPqQ4*gbvSLw(?bUX{8*}}{CX4TCF$$u`|`6#3gpSZ?bdz+&`;+)1m)O|c(}M~aov<9zH5f5avv z^O@au&dR3@`9}OVPy7tQcKY8WMI+oGcl=?5F@A|>XH;I1#EWQzz zyva`-p2i|KAFHnyt$rV`JflaN|LRo+JIwUB2)7RC$FajFUq{~2XJu}WFLL>v*|^K3tNopjjCV~sM$b}AT{1Vk zVZ5V%2@MT+BK#12s!sdmj3NSt;Pa7ho7N(Ol1Iz=J#ox0o_w1pXWG-}o21tUNQZYS z{S8$z;N+wsIEinJb7tJdna+I1*8t-ytxI^>+Gl!MQmR8=^8xyyxW$)dfLka)?5 zZd!`4oz6)|nrFIi&6c3kAn&KV%Ciet2jsi(Zr6^f(i__$x@8Rr{~3wBQ? z=VkU>x|sHvv||oAXbOMllZM^N9~3^(FF?VY%}<)J%sCP81Tt|TL4P>U(HfkKK0w~- z{$b8x9VylM?NXimVzUz2V=W8${$qhWl$lQB zcTJQD&du51Tk6&5VO8Xv_B2;fKI!2*1vl=>$j5A17aHr`@6onA-xNg9B4uaii%9eN zorCVaRr~xlr@4%L{60c(&X(yqc@Mpdow8M*#p-8=8@rvHuB#-(QZCQ>TROTSo zs7ThS5A*w?Aw#}Y$87oinDoE?Fm~&E3cjqN>Rx`2^K`+=h54I8MPEogIgwqHx8HLO z-D$tUlC+34|1H#U;V10gp>`pBqQB&~Bq6*EyRl(exY_}BS)AG$vxM#bTZ+^l(duIF=MSh3UAl^quPM)WI)N6qHBIx4xD^hmqLS!BrS%xFH zC<{AWjXuiH)dv?bFJTka^lzQ_2-pPHfnv+nE9j#c^0pRLLRtgW~_gV5SkIY|U1Al`IfZys8iu{6u@ho#`d>nZN?|~I!N0ZUQ z&l;~D_XhqP-}ubl8#e@RipzfIBfnSScW}GdqbIks?qaL+pXbT<1^!j!&7Ueq$b{_u zMK)dc+?&$wnVy|C&^O`m5&3V6w53}3(i}><^)hjPq`S#Us-+I~GFI^dJyY!OnJ1)7T zrO~_Jf5*z-+P&q@T`h5~uj_x~&Yt1B_Virxww_B?U-h;tuexk?&(P{iuFUeJsI#C_ zhn4z|KluD@b5wOEPy6i+9LRD1Hn)CyIebzYWlBmr{|@G-Pl`W;k}7lnjS@e>@sD%A z)P0}vzdGMkZ>Vgpi1LRl&g75qA%HJXGvD1O?C#Sys_!Y|_3516&Yj$S_~ASPR8J}Y zBK#%y;g6}Wp*(d=`3m~Z?#D;rfb!2@2CaYgq?bJTx~K44rtn#&@MD&654YhiZEh|t zC5wRgxieP*xfeCLGAT{_U@mZfF20=9ujH){X6us^8md=28nz4k8gdV9YUYhn(m)4NGaJgI8;)6c_{#ZBmt9V z7tUOsxA(*E;yr#_zCwY*dVHL8#)pG|dwJ!q|0p>cL|czoK1n@+`iyU9oX7ATcxLYaW?hUy^S?(pq_l?}G?ypMl zFHIcx!KU;S!Fx2Rh<@XM1Nl`ELLIxSq~; z{8oMY$X>0_$$4OPagdZ#a;Tp<@l~wLL;5DBeRKD>d*4l7{K(_eLf9QbQK zeZph?bQbeo4H}y~He3Q{i9EEa$z$Vu;(X8f=wPhW;XwqnXQ{uJ4fBaB_UrBtn`$cbB4o0{) zK9zxbZyXr$!P7MO<5gY3l(FN{;9F~yxinbddBNE{XL;QJoi7Luo9`LpRZg%5cHo0c zc+jD`MnA9e2goCJPnYke>^aEJCry6c=TyGD(DTaYf~!FPbI16ZKJq+!XL_+Pvybt= zI?Xrn*IpnjV>4##g!J#~g6ChtUHB79YxNsJxOp+GztgtgSB$q<>RhF6#q1Ktz^wU_`J#A^ixx~P91&wBils|BuIwfl`W z^WA%c_s+9=^nAnmJTFVfr*oHkR|QoGySsH`a-&xGa~2;9wfo1k!9TOSD|qA5x9hI) zf;W$6J#9=_SFQihv%0iiJ056!PK4d_t$#+Lt#LcD^_3n=r*FU`aZ6Y?Y#!;Sq~afz zJoq@5v?pC2|D=O52K?#yz9%qOX8Lcen14#izvI4s^t8GBH445kZ%Tqo*2h*~j?-x> z_8KdalK4uf;U_`-Gw20QKI_P;r`(hG9ll92wm&B^bQ;r`(E?;pc&5_1{8EJS{LdtNLzOP}%dMd|uYd-X-=;J@}p znQxW#7(c_po8H5#g1O2k^BtcwKI$X<8foOse81$@&&Bu&={a4t>$l8}jI*#eE+^}NmU7}hMs%IViu9ene#9&d>MLpUP;C9`-A-Pa!@?N9E9B4SF=>j` zMI`U$@v^^4bS3ZrA9-cm;+KAx_08hjXYx{)=rlOU2 zoR)H@;=Q5a=#`1pdFuE) zNznQ0gd=z+IQH{ihIYXtesjx&L-0H!_4PqFHB+Cp^m>X-D?VVjsssEKiA?PL>`?uTDLOCJffBcOKF?=<5a#^(Uvq_ec`^! z7WngK@ZzVaSWo*VOnMkjdn*(BjGoAE(xa{QeRgJjv&)V83-l=a-sC^Kd~b?|-ZM1# zy$aV?V|LFnF>#RPJEAti*#rN&Ii|Fpszs_MCvLBK0y6o@9y?9-&Qeux8ugq0?m{&aJ zl^b4n^NNRk!<+x#%jVUO*!r=lQJV6 zpFzdW4uh|yxESFRNPMLSgd6apEb|KdTL&K`UT{iUc&RHh#a>n7rTlDps13n)d``>w zoWb`LcZ6=1r8ispWiA?isl3$n%jC=W5?+Tq@!0*_{mS`9XKya{H1SszB>2FRIiGn% zdt0n;HHF_Jkr&m&{wO&-&13&**5nL__#hP=-b@_zMKf_EZ<&eXamtzQT%{s*pPxe; z&Wt>NBf8wiHS9OzVizrz)44qWBe*J-b~C)hDbU)yi>JqO={ID)v-I z$uHAS;=9~0+=$-EgUzHt`%lnMQ?Gy4j`z+u^;=fF(X0KGbroOj4T0W`p8vWFhXPBa zr{RXcFT1v^f7lf5{(KXBH?B=W?_B+`J~>Q(xVg@-mak`gEQ9Cq4;gp#?Ogo%Sv=49 zmht=zd}CiCegCHUmdB;{&u!b>GM4eWfs6@%{X)qL_py%w&gOOPr_6&qc6?#m_FqT0 z;Boen5_~2-3uE)1i*MFnocO-$HoA_VINd#>BMaB!XH~*C=m?q7L!s6dZor?l#NUli zSAieU^-lJv7ckb*e{}C&>w8XQD#C}L;1$2sx;NC3g*WNC#Is&EExc7X@k^$+-lf@u zlaGB*{AjSB`5|)aLq{-zZH9e+WYh1NBYn3`_xssfxC(jf9tz4r~BxK);`Kf$S6g zkobUfpud`Q3Da*8>m&SQOeOgSaW%qzL>e#zVpsL*5w=5Y0YM%=mw97#>~-i8qPvDw z>R3-Xpud4~_{R%@{tD^h)M`h$a7lSo_Z@@_H4pQQX3R+cOJ0S2?HTfBI2)^w zon&cQ>`vB4t3dJ53e?O`t-fic?rA@{9nNR$P04oy>u)usQDY;GQod((_|&1l0zP!O z_3$i|@ONE!1L1kpb@0+8n5VvrUF{#ddDyk3jQ{If%2~OCv|+vQMdCLRpO$}!_zlEo zbxrzl=|%Wkt(#)smE+|}#^`B(xcCxq+m*-jRmNgf4;Oa;w@1hGeepz4MgO0Cmnpuy zdn7+_M`C#xZ&8&P8By$qL?$x)v-KtaFO64!2mIYqka~!`1UlVc^QRTtyzX^JL|ATpO4A(c#o(t}psl-REsf zzE|!W=?jk1-=}%1W}nyh=_IJC2fTp~0bkkYO@ zG5(gBanHc}K4?<^n9?G)xb)0*vK|));AgcOds0sonaa*yt6e!y;sy5k)Ojg&`Z?fn z3kCl!!A~Cw{+F(S@8If(|1ZgYxo2;spZ&2}4kT`p?-RDik9Y&$iG%G5_^vqUA3tpU z#wvWr3V*7!zZ#7fx5I-Z-Sfuh?yc-Vr|&=ZUQ4H?3w~7jCPT^y9g|n~=%cK)lXnd1 zmx1=11o$+-S@ka3py*TSm!mZ|=T)CI-jQT!P{jsYJ?~mwrR{yWwea5YFo)e(Xc=gZ z1uy#J#cjyJ_SmfzNw2DC`Y!$(*JnHM7rTRR9Qw_p!AqNt>z!Acz*M05>ew5Y+7fJE zK3?2GdlbI0`-zkD_{V6^%MoekNm@@}ur0jA{3&%FF)x>^%M1ENY@Vl?oBFO|F5p{^ zZTryQ_%=dt^ik(PV=~y5^ane`N#uGmm{k2i-?3`2o%yM6-wWj<;NAJrrDf^QfsY;z zUM_44WM3|G^*}fg>;Ud;JQ_SEau!0ngum2N?uQPkW9OGn2K|37=KxAQPFk``Rr=v! zf1EA12_H5c;x|`xD?g<-gkBkwmgci!Z@T|KV*=@?Otz{meOaY1kC3*5 z`~$T~^En+dmSp{tGMcys^I$~WexU3r zLirBk8_J%owBo9hE@cFdU4I$RvIfidBwg%LjmNx0z0StJ2)p4QxOpk%nUodY%~=+` zVXm^Y-j>PAo`5Ivea3^(vhEseHPBt@SX-zAL)Ko=kAmIk+IzAJ{Uhw9$&d2pY4-Da?69Y?L1@;x2t6uFZ4mkv!p9Zc5vSv6_$##3Qyxpb z0de(_I50nQbD*62W%NovwB||DwXZeL^1m|P9jY%7TdKT&#`Fe*Usc}nV5weqA$W;5 zFO(|FzM{NAzMC4fXC;o8GtT_`=!-n{b;?*_%y~lp26p5qa}^kPfy#D=jhwIz3Azv#qf;bY%8ggxy9=Sw0N!K)@eZ+Id& zxTZ%xmplqwqz{4f;F|gRX4ag8YkYlhjnXHQErEQ8A-vqM<}STq&0d{wX4VOv0p&*3 zM6jPZY>G8A;M_{qfemYRYh$6&au&8>O{k598<~nFd@FdybXh$btfNk`)e1hDS3BWD z!dY1-yf~0dlq>K*zQVN``&r=twD~_~O#U+u`nR7ic@=C6WoYqFVvhr#$cW811`m_i z>tfE5x<*G#v5UEUbgOat9A(#&Hy(2ME7*=IKR8qnd&s4RAw6Yw`;?uf`Y%AP^a zHtaqi87n6*-B*$QKqi}A)UC-kv){%7b2eux?APwcW%7X6U{H7nq zg-vTs(T`(qL3b`c9~|8+cxvni;sIACpdF2~R6*)#UN)TXetN82R)@WH1y$Na{KGt7 zqa7!@7wgJtWQ{pm_7s96Sa_Qb@IyZ%PHhRwW@`}ti<<*)N_GGF;1PLJKXLK%sYmu| zA?X|AlkC{{+Ozmg9n|}x(!YJy`FbHXxNiFAmTE44OLaJZ6Es$;!{yF}v{C3I-&ea` zzOv-|g390W1(ScCvmwcIpr8uUj$6RFj(Tn>p!=iKiv2kG@qLx~@Gj$Ze756<0@kTV zcqU^;#t!wC$_t0fW})-@9$=f6y;#<6*fP+MgM|2Qz$K z89oI*^``M+1be5AD1c%Sfe+M#Kn+3jP4!}qO+5dkNzMwN+10p!mj8aXU!2= zmpyfid@;ZJ@!a;ej6XHztcKba$b1#O+EIwMG6#1hrDjXGPS|(_Uoq}_WIRph&lRH0 zt@&M8^7lx7Z*S%BPh&5f&aVm)Z8(G9g(d%d$&XHR(i^vPXS9d3p_aU9Sn@Kz`aRv_ z(|dzu=>2B0%b)Q<*2nf=n*(hQ z{QsW=%hodf$4Zq!WxV*3QYBl9<@>eT$Q3#q>ecmJ!Z~J-ZUQAf%wcEQ90vj6#_NXz zOdA#deWn-?KT4de88ykbc{Tc;3)^z+0is#qdK!K}@>5@Zk*h=UKgctU3;n)H-UHN8 zHb<>aA5f3vE1SoHQEUI>JD{{~fs)n=r4EV9aF2FhZNC-E%IxnoMZ=nYV%EARb!ygi zS=%_HC{0ZyZclNzSkdT^N+9}D{0Oi}7~Naex{pcyW2`-0=*07ey#_WKf8PRhS!dr_ zb^&EVc+PsJ(D8(hXnheqiav&{92`qaJldnW1Y zc$mJ<8LMvzUZ39!gz|fVhwrt&7cdJ-7N_WgwT1LAPsSgShfxn%7#h-bf!*|pKMi$gQ$7edOq>+0c8E?X0 zb&glj(l*-92V|xAKJu}bQ@}bf{z$RX1h(#vbl)(0y*SX=?d`X5ncZIYO*8tRZ!pe5 z*Z3`D>fG2%J_K%{0oEnF7u*sCvN80M50VZvz&fxMm+)y?etDmk-@CyfHcEj3^u7;R zJ|n;J9>Sc{@sy%Y+V`8(#rJO#_R*DO|6Z5)_qaW0DBqIsaDLF0&72xJQhetm_I&vs z&+q0N63+W&kF3$#X7d5Qm45DCk$s}N!}Uj`IDesjwVO6mkA!PHLYGE2ig!YZL(a)7>X28#juNBCN}B}7{fryYhntiSWe%Ay@G83D zvFW``P4X~aq@8t1A6aeRo4l)cLl?hCiEo20An*1&zHq@zdg_E}6KATNX}pWRAg}C0 zpCkWs{QhMg{Ctk@V1=I#p^tZUCnZUfJkMV0Y}8$^#s!}}TxX1IEH70$pI3Q_Ydq!V zpf2cZtTEP3AvO(ZV;m?86Xrs}+se0yIyC#%WFtK9hNlUA3Qy|NUdCnEy;6%^!S;76 zuPA4E#e5>Xvhxf5-w@p$IS=Jw?)Q1@Z!xgr2rbe#(ibwHsc#kSI-^22pKTER`IprF z%};bt0cl^D9?WXN+;tcg;L(GnaH8kDLkzU54*2G z4&6Fv*BaT6rZ%tmZO9#VM+J<4@nztYFt7;}oYOSRSS9T5%V|Fz3*;Lx31@Au3*TG9 z%~@d$Ev@NM8g9iOuW;koo`24&dlVT~*cxT-%ILQ?75gok8;ARZf4#DXe|CC*?#uV@ z*jA+Onxxa0@_sI#2YO zt94!A(B-;m!dR5T$}FOT4-!a{U4(r`@zZYY5e|Kd?PIFQ8zn0jYV#s zVK{3NdsaMt#%`ikVmIk9(_`#+_ncEAbWTiTg^GXV^EJOC3KpalZ1*b({^M z+ne2`ik!Czk78^(!XK5&nV*AiGVW7*lk^jt2K&2w8T*=a4&qBmr<*5ckNu?RXlTF_ z;fL4>>a^eR%}fLg!RI62Hm#+9C69(i;VpBGC%-F^?=h#p$s@fsKsvlr>(jmMhts|m zoWwWA`PQt9-`j6vd<`(Z(z=9~t$n7KC8av_H6NfKid)^ zrF|ytm_rVl!r%F%aW3l*!Y9trL!jWz<|j>9=9~z40+~3FurKDjE1@+wmwhgIr~8LF zhc%^C-}+8nC%>HOitMqj5I3e1+SnvMX4upR`PN~OzK73Q{&fla^=pwQ(sJV{Sk-QwC=Mm}cCy3knfevh{0`3^RM7AZSBUqqVE@7s0v zt=i|e?#*T7i;o0?bGA&^$$KCM2jf6!r5#>`3`Ob%i&yMHP4cKA+OnMQ1Y{0kt%_v5 z`Y_*Z+*9yny;S$|`}GA(A^e$D%(oYUCnvIL^7gj|LwDNW2S{2(n*SDXT=)rV^Qv74 zALtMH?Q;mP!fwuRE!=GHqX>K7Y44~AdvDbZY>r{?ZH!leV_LpP5BF@>@;!REXU~k^ zPRsA68^rtAc9Lb#PrU}HFM=+9Z!Kk~E<~m|BhGLH7iD3GtIF;mN!d@H@0;jxpaM>lMZ-Hv5i{ zJD%35?*($^5%vpCzT;e&mZR;`r#03{gN;#adhsi+pY^lGtE+0@{||hB-jMoO*QE}7 zmjriU$am>}!Fc{hV_oC%3(8Xk`J-zUz-DM4zxM&zX}H$7o)qs zZ;v+F{Z{;r!ap@!EI(zu1E9hb+!*6*|SKBslNX|VZcDpPg3>h#*rwb%acwV&tQz2q!^ z{{y3Cv**6*!Pk}j=2tD@r+3L?UdBW7t!ayQbP?$k@1L%IJuW^=UYYyW_wTb~dRTPS zFLO6j%zA~j?*Yo#Kk4N1`PR!1nCJM`%Mbq4^ZAz6=UdwSeCsrxeoK2`-n0+Ro7U&s z)BSvV>Zk8$v-5wQmM?4XZe-N(wDpy5%_!e~YZkcQyUhLFN=SW@RjSrpyVb~gY@9V$ zxbJR%|J|eIggb%c-CbS2-(2C+gdIsq4XD~PW4)$xQkh^#)z%l2l3u}mOe;Mv=#w~Q z^a_6KCGn({_}~in{>&`qcV2um`OKJ3)0}1$c_fWWf2*MvU&(K;_^k|SgL5S90`4S9 z`5}|#7o_}_!0&8H!?)Eo4gAPs`SF_%={I_b<0tpTXwuvIP^Q#b%GOhXiF<`!XB4zK zi60r8lh>Il^%5K;O#C(Ej4w)M;0`6JPeOTFywp2>pNr4xkszO~i%`l+&T?f1P|25^ zd8#aB-KWY*Ry$tt8I&b;g|?R^zY&nSW_6VMCGT?e4teh+^>2EyclDNK#_IhTdOuRP zdar5Q869GMEcYV`CJFZ&)uDl<$X5`*eE%zyJ1+S4H_O)){o#9b$)}I>`i6TtLw=L6 z3H^{XqK9?T#PlIab4>Vir)RVO4#Te%T>bgYfM6@>o0GdugLi21jcgtLY4J?c$9>{k zgs+cXxO{smajnVI()isrUiJ@?k8gg7Up5mzPJZD#J;QgI%{NYYdNM9c*%7oGxvxH| zjn7$%^k><_%3ezLAq{l$>M>=;C*uz3E9@saBKmuGI);qzi;K3+(YN|!uMwFW(D-y! zlk%gZahdPvOEvWS9^8xrrP`Ad<$K1qnojb3ov>qsZ6r*7^YV4V8zZVzA4&Y?NKk6g z&eGPMlpTR%#JAkSt42Oryv8?_rEqOv^uE!uyjM@aympi^k+#diYLsKsgS|`7{w7P$ znCsHBS4+b>_c5L@1`5AWzT-&4BgP4d3&(-fuqsb|k~&XvCNasL7Pqux3%AImdQ{EtUtnVH?eP0o8MzOvDt>gmioe1A zEe-BeY(ZO4e@~Cm&mZ#lPsV2dBzNX#(y|5)inOVW3f5#nD|}%fv@8KYGPu3 zvmy0KJV&Ko8yG+JRNOHhJmf!(F4clp?Qb$gc2d^XQ?~y&di6MC>YBK^kv85SZB5ul z?q%u(Q^T`eBXD% zvv(xap8t$r6AT#hgx$d|z9*sIb)wVH@SBvdt?!u=?5}Cp=x9*ZBXL>3{<)IgBJ*5Q zY!+*!s?2rlDeYXhb^f_-S81QOY#YCy`!@SFpWn4kt}SVFPH%@#cCSauBRI}pZ0jF; zb$+AX{rtVvXVeF85;G1po z_S|RX{dqmzu=8tsy3Od$5(8> z<+iy}XK{1GGe7w==lt}6`GfzhgkG`k>a`DiPe-~YZ8vlnB9#gcUot*OEk7i)aUj( zdzN4LEz7%3TDdPx_#}_Hux49WJorf)*Gb)*+z}lwa%sE3=Dsx(_%0P&f_=0VdBYPEKKHnl^gixcBVQO} zD;0edTi)Z`r)XYKUQjI7YUqm(w&PEJ#PUjh=ybMm26wY3{WJW<7K`T2z4|ptd%2)Y6HODxt(z5_Jq5WJMfCNX9T;n9pZxX2Omz`Q}SkQ zbh1#}MB4a2q;YR>Z+CVN-p>oQXT!cXv7w9c5qmEMMtaVYoT7RGR|Gfm>c{=nJ`(A?u0j&X-!C+V$wH))Hr zY_aMxe#&d{*!yoQMNe0_uNL`QJT^=drafne2YqjVm)t>Wr5vCiF`a>ue@DDukvsa7`f*|K}?G`cdIpD+5u(;&@K?i5YFQ?TR4F5C*Y zj6ZeSL-bGdr2%i@KQ6M+9ujWU6<##L9hpk%Q}$-saV+pn+J=q(*bl^JWGnC(kGlNn zfO(Xe6kD)zhqS-Y^Ze6!PD5Xc#gg!_>7EX}+A-#(4s6C!uI^A>{4*G#*3p0$-wF3oP&4*Y@}k8R5me$lOXhp$80bXCdI ztJitqq%uZ*#1FSDrm1eT_19{h({)9fI58Spz^szZpKyORbrBm5Ssx8P>-wR=E=SaJ z4t(60EB@B!W9-Lb6U4?z84{P+emggPB)XRz_mewM@yqh7bFgEyxS;3bquovA2xFRG=#FadWTi@S-t^R!;GfO}XK_wc&- z&5UAc{M2S6xBR+r?ocje;X6&&M9J&s*+`v|pSZbIshCM9uEaaBlfl|WZv|IyXt(<< zvW3N5QV|;^b?lRfT@=|=-y5gt}w%GiTpon*3g(vjoUB%O;(eFdHA zO8+^d-gXppNn_aWJE!0+3H$uySDgMV86EO({J{}ylhFsT5hME3-}`d4Rr#W4&MVmd zDt*qJH|nW0&s*ti(CNnZ{zEJMdGmL>wVOFZ`oQJ%sfYdG2NkR5dNKBQdS9yA`BBCu z^gQg3s|jm?;14Rb2d`p2D~);4?<6J>TS<(y&C8^(V&@jySepBD?bz_DtCz;sM-#o% z*}CJSjBAO~$@kn^MOP`WXR!%c)5X7DsC5%(*O`gym%&SS+4bdO=1`d*WxSTLQ0C4@ znLFbHZtm3Tke%1;_`;kYS6m$*eC>#ld}4!1)(y?`Q#bAUV9@6`R!~3g85WsuB(01W zVT|n}(r06ajgxs@(r%fk>XixW4){PHd~L$=mo^TW11vx8J(jX$tzh{`zCCd@B>gG* zTpPVe{#ohzg}=*Z%R3QQE$>Om@4{`HY7F+Ums3bKgE@M7Q=69v}(BLSJudK-}eE+4={!wxBy#A$a@U`dZ^Sx-yK&q z;UbS&k=XS?1G_>A>*5Cfh%~}uKkh1Z7Cy@CtyS@d@OfIw8$j+K(=U-jcnOAeC^A%p zhwzoOV#g|zNn{XS$4J*MONd{vh{z-JqR1lmGPm$&vP|P%pUScxcawA$&o;a0GOr?O zx3pig3oKu`tM=k=94Te<=YH(fHL%%d`h$|Jvo-u0BSBT>dwERaWZlkq@}TPT`>0#; z=c#_Lq%LWE{MEZ^+ra0Y@U3HSOx6;DYnb%Xb@tXK_XTFMc#RovFYixgmp3=xxL#<+ z+4lusa_QcY4BQi)$)Nj{(X0Vw{XfZCD8w!Mgvl}P#>Z{t8w<_kSTI|@!*k?&6VHeI z@$gI&20|CW>kw3%@sJr~%H@^2wFO%>>HJe|6^!bYD z^7tfuhCSjqY2!}rz-KIwK4fd%o%+*#pxhrX@pa_H{^dK9v+r%>Br^JP8T%Kw6 zeG)GD=jub9yV$|`&A6w$Bi2D#e5YvTyQSv3M zJ!*0`@;0*RY1{emc`M8_+%nAP;-bWHHor3yA(7O>{6FwW1$y8d&#ToFKj#wIwG^F-u)`^Q4R%dUe`q30H<*TmGheqX#r6mG{LJ>-4I5t4vB!xY^7k`7 zL~efQ@W(j2;XEm_@psGuZG1%7e|0+Nu3+o&B#~$J!1W3LR$MD-?U1O{hH!xFV^9 zgon_&CLG#?>MNl&!l4>D>(Dx7HK8H-^;P(n6Ax`d>rg#JyioRpIwYLkMhMlbh!;QY z7BN49pR>_HSRKEPh=Ybu&M3V`6njQI9|*3my%!-k@F z*hmpK`+-W7y6d+OoO|#m=V4iVb~cucqv~13Fs-!UG<`CbbGnNDbZqpq z3jXAkve^?i*mne+*@%v0c{5u;I&k$dugB$3ov4}s(8n+iaiu- zw0mfWYO>wcy*&-%i=nSbyGvS`_nszg#sD!R zDSO7obceIIydn9%wK0_OOHOlhh~Z2);!If15Czk057g)x^&`sMFY9mcwR_2dfjpkO&a}c+p1Z$X5ShbYc)2UBO0G8%&fZ;V-3o zy_vEujVm|v44Z9cnD?l|w~Q5S`RJqYA3Q544PP8r2Wg|7JXyY*E{`ii>_>w&ZeKL8 z@-A;j@@jQpY`{OP`@E@(i^YLRRnx#AzWbc2}D@82dXF^xwz+ z&;)IR&1EGIe}mM2Fq$au1cM~q%f{FjzlpW_(2-lMoK`OI801?6$s=-1UEFI9Glx#y zGGbnV+IQ{XG|YS2UDQF^QQGBj-HmC3&jjAXNuNK+IqKk9mzzQAK2TT(_71}WXTKuL zaBHjovYsgKU@YDlySX62#+{+?Z6d-^9E7q2M9^d)FK_H(wn1K@FKNjlJRN zZT`;X6XlzzkHT*J5MlBz`Vs2$N<`dQ64&booEdzN@lncrIC!NxxV&Uu<}C9i#`b|r z=<|G|uwx(VGT!+Mj{(XYZch0-k|F=*a0*?X@~700KX7Ew-^sbdz`pNRABOMEpXsYg zdk%l*kpD_)hcEkW8HfE3Ozv%>h>`7aDCE$8TyKWBBRu85PH*T=q>Ul|INu0a26tZF-Y4h-cyLY zapL0Cw;i>zhz_<6(yq|R$rOLn#Sb?pUD@Dd%LXS~b_A8O!AZ)Nas#ieJmy1rj~@S} z<8$uuUdDl>R=6EWgno=O@~y0=E@O>k^r$sfCMD#c9l z3U>46WnCcegXZR?_BKzJ_ZXPSw*&Ve%lgYWgF)_E$GTDj8ZrmU`p4hR8hX!!og2(I z18b0DD-SX48d`ns{Sz8G|^{-Bsma&dpM!sd_TSmTR>X5gLe9OqUjC{M(e9ORN z*|ajtQaqM^Y@h9i!bs>3(VEbfA_A{=H9hpZ*`mRr@S_;z1?hDyVoSx+wDY7pM2w- z_v~jpoo4>_k4*Y9Cv9508ymAi18mF+4Y4sRbTiX}(Cgu|)l}6({(8!k^I+j8V|*t# zBpM192a?HZ4gBLZuFjm%l@1`A{t4s5|K?$>uZtD0#`#4RS@dzv{NN}0YSV26!vx!t zjGt20_*hWxVqO{F9=J6mc{h?azQFOXaXwZ1;lYydyZ7;fRXO`P2EGyFSVTH(Q&;8v ziQRKxyHwuu$=)Mt%Pz_`q?_GtTm67{;Vt%uo3;o3rqhB_GU&=nutmJEXS8_DkK)ob z>w>b5V{c(kp|}7ZJ#BpIti|I#mq+a9HcwL}DW`SeXtC$1t<@@ezP_X?*AV^y&kNM! z81EfxFQIG97qWj59{!>mjIXx)v%=IizZz`!I%C|)}_THJt)wZYM9=OXGT@{#TvJuY2U z(tSl0ul-6;e11=0(;O(NlGNi`c&?|MYfJ10SX0XxwY>jc0CpMH@dAg3f;K2eFq1wb zeTQ-@)kUM#pv$v!xzBz|_I+8sL&4$%<6+MYM(QK&EcIRR)E`yb+cV>LPsYz={1p7u zJLZ?|r=`rLr^jCMN0r(_)(h8+#pRGQ4bwB>N2ezh&00pzK{acch_g$5G~k>LU1w|) z9g%&zj^{t)%kZf)W;N9gU&gEG^^Q`sJuXLGi5=TAe*=Hum9(PY_5LIMX(oN46m4lw z@BEU!SJLxt{1E%La3;MfMbzOGf9IF<3nV@3tK&ar92Hsi5I546HuXzd##h~2^)30nq&{|$2}k-(qmc0Kqt~>c5*`-Vw{3}iAAj>C>-bM$ zKlP(Q*(ZFQFwud!q}#%`lSSvZ`B+~>bNr3e|7l52d5tq&8It}Uo*7=O9a^M4KpEBG zuw5_slq2b?!6W`S`o@bs+wY`o$tQ8`RLYRBjQ4oYrAEHH%gWf_ACv?7=&?C^EM*${ zspu-_nw9Cv#Fig_r(8442}&sAU;ICyW&F(RqPw4!^0%T(UCeRaqh6CepWe5SxykJp zm!5-u?gMl5Q}%Wu$ILkhb4ey^MrXw%cl@ogou^bvIb-r|eq@w(Q9E6`s24tEzk!gp zPCiLn7Xmwe3SYf_#Dsifn>_a^`;Be9zG8XG_+DQ``|@P?h(3&a=)%Z|X$bA1O@vY& z-y2$eNN$*|3kfp#=tjoF>O^IZPR#K)Qvclcn&Bb3K$-*I{~29SiNl$Os~GfNqvI{` zO}2P7BXy(xd~{NY|Aus|6BU$x=*53suC<_VTJOwiXWq}A!FktTqC4+m9S@D5$zQ-j z{Lq&8|D1R^pMY}y>Lp(#9@?%Gg2#-W;?DF`eFYw*jUR{l$S1UVN>9~e_&LMpsYIPg zMg1vd@okLwHDjFY0U9>kty}GTX4YezF?Ol+&!8`gZy@B%Pcwh&p12(IE>PClhVgdh z>?~amf=}gb*LbY&;y-k_M~d|#<;RawXUY+Ook!#{jA`mH^77t2euVVUc1#TYsL}28 zZKiM0camRobS4gA!J_btp7ze`(?R@RTtlKxq~AMXaw zXZb!&@Vt+Cw5unnNSvg3W{o@B>cXbGX6@A($6j)4rPlepDoR-MNjKJXAzyQCVD~z* zFOoXO*ti#(Fy;y0cHAP$FswI&`@y^iOcUA^Od3*O`d`?y!pPplws$*LpqPx95Gv1gFrwdKEjwe&DI-|=U|p+%lYK#H<=uEzSPW@#bDNaS(o|p zL+O0^U)|a``H-t4@1tkU5dojiW^+UneF%P)wmFM+G`e2rcLOq)$hygw`Qs;LJ6Dc_ zg`HD5E0Fb6{F)0FS>-nzGA2c5i4I(98bU|jXIj>Op)qGm_=t(1@pZKO*|ax(zb^i3 zY5&yU#2*lE-c9^up`_pK+A$mRBK(%WrI+xonEoo*Nqb#QKGrV!9LCT{HL-Vk3!1Ogf-t2S41b}tTMR@{)<@; zGwOoP1Qx4KIEH1ONHbAH;A`VBJ1^8~EZ8_@Q&5}&1& zbjc-PI>=lPZ9r$06L0tH-PD<}Is5)2o4ev4x%$ffKY8ucJeJAWlJeKkc0=&wn?yY{ z2RHnZHu&9S$LgD9yS|TCoLWZ)|HZ2<>j-B0MYw&~JjywI@=f%e^{kBT@p&%2 zU1OH}s&)7W=emB=UZ)n}^&#r?)I(K6+lNRgWH-a;?^4&t4DWn|zxiOy9P*Ga zeJt_&dj2rFy0d;6|Cr^DbQ4iNV$WPDuK@A)Z6e zN=#WYHoU37v;GnpnqVS$$a<}Z(|P4c)6BGOu+8rb(DxHw?U{wl1M*#XkE_RY<<0ewwPhV1s#vLooM$Xd z*FGkuy;&0qFBzxCi>fl-;m#iH+*A58?-Erh6y7qf@GfLOZXYb=Od~Eh{c09fDN)W{ zmGdf@7tyJwUr+ox=|gq6D%8GX?xn2JzG_3Lykmx%KHOj+xJ!Q*UHnCuv}4=uwrixH zlSxN^q?j9E+CF`C%sH?qFtcEHyfV}ei?Hj=&|9rav)*-aF&zR ze;4Zk($2IGV-E93rLp}w(;&T^S&8m3mk_qqB-F7*c>KRgwZ<~eAePbg;GCsjpK$*8 zPbJcjXC{u{HIc{XTO;9RRbd zg&gNI7FqsNu8pa){I*gskl$y?w>&a_$r<>YbO8Q#Euly+Jm}9dmc~cXSNI+{U(OMx z{P>9LXPUi`j9Wh6`aXTceIrt%FLTDx5%N3o_3Bk$&WOSxc&SNW{pU0vb(glTGlvH3 z)nsoJ{GQWc^Gx71;(lMx^Nr8ky>V0cro8NTKJt4Neh0UUJ$iB@^Dbv~`gxw>fUhqh zZSh1kLMLSJFS^kX9pf*4{0@8W6RdD&s^)TVC(axJr?qYj2`*=^l_);1yu<3F}WmV*4$(%}JO=%?Y0IO8yzoe2xd^3;eeecE!4@*FNx# zPhR(naF|=qUxdpiR;^gQ;{B`Mzx~4ZuUQf8ShITPO{-V8ReSfxZ&~qMySLr8t1YbE zx$z^n^^V@Yr+4*xdsnZzVPa^b4pkyWcN&eEi;GcOn8EA{(7eEf!aiaM1hcfARL z0{3ro>!(-1CS{<4iZaf=L-6w_#2!LLl{%n-5<9`kD}`U`zR&n)&NkJX3Y#zBU)}w| zY6=?y*a8g}q<(9cAW#EO2Ht=vn4R3oJ%Am~hoS08rO(4&@&NXj2AaxKN0e5`clr=E z3Wt?Gd#Td#Up?U^Pn`4=cFPnt%M^CZ67Jy+xJ#RwRFX5H*trWXfpRZua&c0bvB6y8 z{#>52`7V;c??{$`*YlA zKk33n=B3ztQ^Q4j_xmo~!BDYAhSEmvtL}^s`962<%02#3a@dcyKWs6Oa(wkg>(2Nt z#r8?uM_Z9MJTc*i+{LZ;#br&tFvji^`Y3kB#>MvJ3(5jqx2_KaYc*-|MufAHb7Jtc1%mz*rrHjy^|4{6*R+`pT)wfcFX_Ket&dI3HEmx8t1 zsdlG&K-*>flZ#xNhJ+>Q-R&Z`*htpgO)T|R_}%^PTkU=9O}Y12?h?jcjogQ>S0>nm zCX74n^#!O4)J7I#?7z1JakMe8LzD~RKfu)2ixac4CCCXeXpi`-Woa@TN+xDY!Q zOSvyufyr*d)D0Z`xbx1-OUkqGTVF3Nq6H9Cd^E_qt}}o z$Mza?M!}2Iv8+jXb?!rM%ALrA1#cI2iURQc2f`&ztDCV2{}wi>1%t~yPk#`b>OCRU@Xcqdk@DqF%tuqE2?;A$Op&s_h$8fJRP2$4-z~1GpM^q^s z4_Xc=HP#fnJu{8${ zuaB0k-TAir%cbs4KSZxy1E=RaEq2HC6`r((*0>8-co?Lq815O5EZu2zp?pfFNo;qD zY-87($kM$=du2~B5*e+XNn{ZWMcxKuj+Kpkw(Ooejjqh*=ZpUEG)S|QyV{fQ6zsUM z3%9~8<4>LT5d9NA#Wb%*L2e_Rz0kVeX$ z$=^fXGidwI2gUV|sbY1J=T+YYuM&F7z2B$W#q;bv=H=4tcEu*@thO)V7u||?_&TIb zSCu@yn)~S|vB#)B;)h!n(^R+F`fIh$>AE6KoEQx)U=qdVPagI)b&>nkvpyPpR@u45 zaHoFMa}Ipmm@EF)=VNSSai719lQK@(V4a&j65UIV`^lZB_+|OkIoL;9T+s9J(Qj$e*s9-MTwV)(&ZWM(V$dd-v(;Nm14Ib60%rj*>SGHa>OgB|O0P z(6oeqDzz(1yNqMQwTpS~>)(h?Cu6JhX9??M{C`I54q=O{d(oZdzC}SU z=Y!&gC*zK)*tVa;Da|*v({xRgyl$S2)Jg1r$~>r4%pxqV#5=jep0&$- zHVj3!uozVIar6s}+U*<8#EER@Cl#?DP{($F*eoy$oqjaX6-j6HrHm~H)=4H?CmlIn zP13ozgbnmeSNhKx^|qs+OB%y|-#G~$>@-O;}4EtONcQB`wpT%{k<<& zTa_<*=Dc)%l>UC+sHf6AZ>6(AryJY*53Tg)&EM_TZU(#U5w?B|?H&A};?{19v7OQT zQq|6nGB%;-VSijrSPKMyP^mq574sQ30HWVXOd@tpN=2`Enez^(`epFaUAB)bW)7A4QO0W- z3uW$nl({oL;O0)P4%vCljxWslamCf~!Pkx$$tU(xWZlp_KXuct4+edHV+HjaiLG6^ z8%ZnUMHpjug!I{%A#&PzUD9rusOpso>kjxpAAD`X@|QLi`>U4UzMv>&$y&kkk$ijN zYDoH1^0_v8k^HmL^$UNO&q%%#an9E-w#jxUvy83H%h*F;GieF>vxN1B@LVkQ z;Hm%Z^+wvPSN(;>ThiBu6V^|0<(|dxn;NZ}C9G|juf*QW0m2V3h99^9J1NL}4F7tl zwLf!rT-Ah&JZ42=*9Q%3ek81m8~7tI6CV3-0M?W*5huH&f?i- z`%&gqB<+^=Yj%Mp_M2b)jU%OO{@jnPsRs78On*?4@kPV0ft_cuk0FmqoUGd!Paaf# zejjy9{yf$1mDDATkH30XZ5#N!6TWq91<6`Ma1E1Qy3XF(S})^@#~$m-lWtt`*x!2#{<#_yQ#=CN@PdN3AN!kXg|lzC|74|8`o4_w z^500B^BMo|Kb6+381<$}XI97A^-B+D0~%h-rx{0B$+O~km_z(!z; zePe6%QTA?xTf2gLYtp`AU)x_o{{hSKp1|sfIniAe8*t<3sv)jHxb>&;=xf=GDCzSR z(dBXMUMu#9iq^M~t`4+7?sT{Skc$hS`fGhh{L=PcgS=Jj4d4@bG5yXq-8lhw7ir z<5BV@tUYRSHu5&IVa&(Vn_0JQUdw(iE{E}}Rnf;x<^#yQejb^#dheo~z_@bellv|C zr}fGBzo|ZH|JGk?!-8`d!2%n8v+#_DW@8a7bXe58nFF!8R9h32#jYM0yR!{-zqKP; zJIYLymeZ+XPjysum39)_-MVxYYfK)_ADYx(?9fl2{F3eOovgnEBVE4AtN)yN61YcdMc;UVUta&Sp^Ruz8 z|D17<$M!GIcJ)ct7Ci1eq5{suXMWCn=flm~OB35~J%MRpC(ZPXnaI+0*clc7l_o-G z%t&aArJJzlEa4x+rm4_Rm_{f2!E@;Atba^D=MvbYll4`E4L#v2cAHIqXd+8Dn1+Ni zU$-p1-n6jGWwzgL*zl5$Jx=_Pzn}3Ta`QunKgQV&=Sh)`zhj>G-8NniQEuTXuVLk* zT%`MLl`RrJ^L2~vL4s~;P1RpRtI&nzM>GCK^$IGbT#Un6{0o^{y8J+nO3AJYdS0t5?@DN(pghQK9eI>L;I8-BN9a^WXCNw0!z6$?x z;-O7w9jb?j7s{SchlI1+2%&lv@#3f5BIZZ%qfaHpCSi5_IwB4lLOG-K8WHDg?7RIU zb{>m?U1P6jEg@^yaF8-Kk`Jmkkq`TDAyl7F8Bnoj*My2KJbg9s$P_~BVn1^;erO2Q zoFUhtA+#xe>K5@B)@Yh@>7gOC4y{9*&?Z#>D&b%iLhENj$rnPKPz|k1 zJnhz$c&NUCe9%xRW!0eueXOH@vW5*s@9vLTJN9zci9D&hj=Pb%o48w98Za=w?b3(f z5T$Ohnb%0&VneW%rNM0;NYjH?l)7bnY~XHytG|VP(<<~H>>FS&b6$P#ms!)(=XsxF z$H87V4#t0`?7J8JY#RQC3s+wuTpc9PrVX|_@EoWodII5mi z4AV*rPSYo2Ij5`WPqWW`R*{ChQZ{?y2K$bHGaJ#7EU(NBRURF<`WTrr)rqP(0R>~J zn;pxD_e)=@%2}o4J+{)dOA9*98GduEU>HCQ_S ze;o|v-N%frO~pHgRqUZyquoP0RFmzlzU^rkUkrUk+FjBr&aj>)ZN{^?5}irgsf@{KZVs8TQ>fe?Alm~qdPe<-GWW~+ z8+`3v@@U`(tak-_qnexvmU*tgW@pj(oIRS3D{)_L{Nz?!zf5)wAM+e?vL@U}8;0Wl zzVmOwFXv$Qu1WlE^?lC7{-@V1=g_3lzqYNK<+~SbHVWPnehuMi{`&~uMEFcubJj!&{gS<&2QB>eNZ} zOXlw?@3izqo+tis;oUpo`P&b&t_(`Szqs=y^@iJTW&8%&zYVIx{t)}OfuF|SAarLm z>JOlQFP#~b2IAOzS&!QF-!Ara$$wOKPZwP4+Gc<~-Hsz${fAlC4jR^d8&z#EQJ#dq zleUx?{JS!*-UmRBlX``JyS-zVtk1Ip0(}Fc_ zUo^1tE^kNjYIR_2z(1_x%1bVo zuU6iIJG&2FbC^ij)Lky@(GSF4{2^5vW*zm?6Sr8o;vczmgE6)``HR=Oy2qERS{Hn? zy2h-8|v-f^(2;7Pd9 z0bWu~t)Wa^fF89}`0o<_n;ie|T?W?h8Upk0$v(JuZ*7QuZ?GIn*c9*Gcg7ET!~Yoj zI~DZb$Nta+ZG$~jB@cgt)PFFVDDMP=B;Cu#@7i0tiM9IBkz1{tRxa=ufl+In?dS6P*?}{ z4#NUxzaq{WO?E{z4=lMoq$3E6&yz>_x1C%-3obq=hL;lU-6uLa+PpKh);K-oAlXHiGec!D< z4BwkS(^r-D9RAE9|CQ1XU-sKF77vG${!P%En-BSqh@OSWF8;6eR)>&7%DDM!$Nizd zcJDkMB`#U1YC~W+lqj!M?$E(8SAUsX!Uuv5u?H(_CY{O~BCqsAEAwfwH`D%K418&) zOt%Kx+H#P#e3-bKNIzVkLQjx`x;+d%T%Yt`hQ4B;$S8Figx+)-dW*cte{=E#oP~&9 z4ASv*HwfQS_WejZuLkjwNBG$JmHsSqtb9w+#ojaU7a}YbD*q${N1df z_e|Ki!F)6DrkR6KUf*9El+EW=(OlEv?Z<}uH0cfVgJGX;wjS~fXA6e;En=M%rDqG~ zTKq>9+l+K=0KOtiBgI(C^$BZ?#eVQ(HwMbPvrJxThxRl{I%c=0S^jr{cZ(YI<&0F^ zUknEPW#3TVa=*_kJvX-D3Ty?tuSgEhFDD@-0(`yk+EDM!sd_ z+nwfH1|G|%m06bJvGim6Y(ErMvVUsv*nRE*dQqhAozidVzh22}5I4;;{`yv9iX~6Z z+huJveiT3NdTkv_B|YESf~H(eJ7`<3tE>L>J)S=ODNoBDoA0MIdudtk+A|UQ`pnuh zKIE%z=73SpzAHS&SUUX@?az6|LB_ymdBpa+oL6^pPO?5dukPfGq?20!ueDEr|bm_-r**^^m`w zGUYs2_{kXG2@Z*dg2jPkvRVWGc#W$wXLO|l$fke7`0&4Zen@oJo3RFOp==gbd& zqOUgHR{C)gdtHp5Qr7rbQ0`)08Q&hbH6(dAk~Y4;@vm_{Rr}$=lJL9t@q<-4`#A=_ z5#v}yx^dRe^8Uo`Ig+hadCw<%k4$g7DBF;3)}DcRKHyz=i~ZrI?Sa4Pw4js>y7H1G zsecIV(5$Ak8w9mDJh2ph?qs0x#SQ{Lzb}pih zA|L6#(c{upCEZt4@!GEh#pm|~HqC*ODoH)Ah39(8xwgc9fHk$8QOo=91z?w99WQWr zC}@Ln1hZ_fNV%2jqS0#5|~X|44tD zNna>MTiVk*zohS#^t>BC#J(+@Nv}!~bvVV}`6c}VNzeM~_>UP!MV39pjkKjr{gRgP zRreNox0TKVOV{o5;@_*(mZ^ZfQKgpkE&0BrK6a4_NBT{pknrxK*R-G#9v0ZQZHav! zfAb{k_)mE?{n4Q86FyFu=s;c4ZQ%JgL7)+^sB*9>!l63X}&{|{&xKl8fi?q{X^t>{u0b6oeR*JRJ9 z_bp^@a{I-l=b)eaz#RRQy`9K$YA%}cGg&h_D;~MyZ74tNF$@o3urcd?F# zM$qIh;30l!OZM{JB z;qz3Y&ZMILl(P6XM*NyFPWAu|8}8Pv_B}J}G0qsfRQhMo7sWRaa^|O*KXp%Bj(Ha- z>uke#J9BoHt_Q)V^0sR{)_3tAI@}}0dXe(uN2xRAh`-Jwav8=nbr^Yh?;bxwdT2W) zhBaBE+v(d(-=gm%zvk+qkwf00)zm?+#$GJh0O3z~+)e+Gd8|eLP{xV{LNB2i9+_E# z)Flo5Lh9L&__0;i-NGIJK63Frw}SHS#KUdB@d+2smZyQAI`O`Rx#D+e3)0H^@mbP8 z%lG5m;Q1`yrwN|-F^_ijBo&F1G|#MYXIovb$0g0$t22(h9xzR4Q!r^red&K;&k7@Z6WiYHSdq_S z#ke6@*>QySZ_1pDo`>=<#%mt?&2ze6k+zYxkZ~(`j~hec&$)4HlgxX+Ldywj1?`kh67{Td&D@X!pQ`NxsbAO8xEnBXzVglWrzFnDWCDgC?SG zVXXO4`b{Q>oi8=>WigmF zU)E*5{7^by{#Um)PCn%7$ouG7b40-Bv)LTcL?41*rESh)9gVKn`Q3obC9-bvW&Zd{ z+0K>YU}5J}&I)8b6~E@fMOOI@hm1+lS)v1%nugGk_nDUUUuewP5-}RTG~JLH}MC=n|BjGSt#juyLQaRya>PLZ|NnxE2h5+cG6x~laIBFK8LY)Gxf$D z6V{M0WR!J}9XE*=9_BqlFENp&tnn;GW=k*Rn^iX!B>$;w$D@!kG-1v6#1+v=Ijc;r zg8yRH!^}H+3G?NZ)CIqMOQidp?3vC*i{U4I?aPi|Tz2E#fyJyB3dij_Zkqj2JXWra zALV0j@R2hi8PDv#b51%HkZw%BDV@|cE7Ksa_^qzeJ`Mb~?wp^tq<({p@jLq(?3-DaDb6-ze3d!Xd=NdN->GlAI{0U~zLp$ueJUAn>j3F<(${1iChOH2 zd1LDGw5%^)ba-6D{_*J##@+_Tz~JmkP0kYpqu}oxZI`8YA!T31fWm?pQatk z+w8cIoVm9a5-#ajn^q#uPUn>)O*7NB!8X4$K;KVzwPzMG56E}nJ+2hn)q~rGy!ZV`W_Ifr*dmx4f{Xk@;9$thFMe4hj zudJI}q){(Ym*t#;${55P70EpHNq%265|A!kW48T%OxoXkl5^`jN?PVn^(lUj^Hj;| zMeyxX&74a)1<~E0Xuszgxy^oqC2{*|k>8;-3D>NVljo@)nYy*9PY?E^#JmXx|3z2-<=+pmLUN&ZmuL>DxA6 z(goAVLHS7wInHM+vizr98&hZbZKYr!zt56yd1U;OGw?U*0Q~J*LXlp0(4S>2jgO+Q z@I7$8oFh#6@e$Y0G+<9U;FXU$0*E<%}pCf|uf*`hQOI zQFm$UI&)~iUQPB!!S6X8HqQiJBkuS0Jm2`t-5WQBZ_3O522Osj!nZ!V*rO*mGVgL$ zr=RC34*2>K(iTrtBXmOc{-PTV(J}tw$M3M`KEVoirfMz+cjC+ua9Zoekl=FmT8ZNG z$~&w+O1}IrM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7Qa zM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7Qa zM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7QaM<7Qa zM<7QaM<7QaN8qgx*tPe=H}1aa6FY9a_12HC*nZ1xbJJyUbHg(~`7`JI^nv+<|E+{x zvF_@%os}-VoLu?3O3p7~Z?h|(R=?7}y$-o;h1+$Yoxd*Vr`7l&Hsq}f+OCG=;(?C;s z>IkwS-|0ixC>&P$?4?S_fAxfyJaN)f*ez4oEK}GqOSp$S;4W=$F0CYILa}ofTmt1@ z)a2r%GGl|e#QnM0ati*RqP4+nZE_;R;H6H6okCxr?1nOfm*d8U=1xm{%^>`y_OCJn z-w3>2;HrXRZ5i&D>dNfk4)B4-W;1vM+n&S)mlFq{xWAafYq8*LacR+XXiFt(hoqN^OV+i;K1UkUjpalR?Tn2CmutxpI%K*ld(L zwVOu|+I#awwk+JAbm1cNQf$7d6-9gZ`!3wU1;rW}N*l3X(itD}eeT?qd;Fv1upe!I z*kT~%`09(+o$+0Y?UQ&pZAISj#DpJm7q{LQmo@pq7`spCqu3c67u%CBC@=7fwHo^3 zgYEc}&h}#RL#MM1Y?DVx{|tYzouK!OnEEwII3k z8g3C6V#i`B_a!SZ*-coyEyWMF+|eweNqV!AwDMqgt-*cY;*YqyIpR)cd(S!PZv4T7 znMrr_dUNC0USrNEcyYyzW%}qkPh$@zOa}a>$QA71PUXO>e^%~DR?x&!ttPzi0}1yt zBUimptK*Ijx;`iQ>fEW^lzWv23*Ihl9jT6D?H`1nI^^loz!M!1xy=e>MAisdtzGZO z0$*$cRPpb>fP2&TIKQDD*s$|_?qC-BG>>hIMeB^ghWmz*aj1v=@iE-%OcQLv{=nYV ztw+%HG4AK)zHaBTTu|r`tjClq-=VAlE+B?5LF%gg1P=pt@;c1`N@5H9{JA}c% zu4xk!W2|BAtH) zW2rJ?TT^g#IwQLF8u#r#M?AL33s-m;rl}b28;>mAX>_4{N{&hHeHUHpxzlK`?Cnow zX%OyL%3kwxiSb1*cqD8ocd!TlSg_;4F5K}y6zsTCryZnyqzxO?Pugaj^wJKt-P9Fc zG?HM$5t($^n`yr>?r2ZjuF)U+f!Mog1=zk-UH)`n`%!=$t8vCQf1&63r}LcVao2XS zBs^@orvtBcEZ}Z`>|If=?oeIhkE`MV(n#4e`FqHF25tWNpt$}qRje-Zyz0B)RifRv z&-)a%o@ehTFPCPw4Yp2awOrjgvA?*^!-_ zJ`(*&j{C`HPw~t0t8=h>w78(>J^HY&B#)J6H- zJR7kAt`@p_)$a~Wu)w*SxI0hlH46gf%kC^5`^jC-txBpE_Vk$M)MlfwohUVE7 z0k)9Et-!{`?=)Q#C9j)jBXvxe=d7*H)4GgVH{l!XJA^$8tSv;5t$8E5^<1x&QwQ*o zuqBN5HjT7XQqzYd4fez(?g^JhA9qyR@zgjCpNq1!X3XM_k^DyP#%E15pKV0p7Z!tx z@RE70-EQJcoMK&beo_&;1a)i@h%E%O(CKFbU6piJU(48tVEtvX_1BT()y&3y3ES$K zuJ)fZ>TRc^ENKk;ediRsC1IbR{EE}xC8I_&+G_V>PAZB@SLne)v|Caf`%FH~v|Ud23#ZGnh+AQAg1jMvS}WURnO81`~>YL_B-)zwR53!sVK z>vTPne4KHWbyWPaTRS=1+>1>pYsHThYTd-y^=snB1$E*syKY^~+&p(aeN^Vt`wFw> zQ#-yfSH(qF#|K|KVkDo~Ws&tr^Ze9JyFM87`HdCSZzQ(%>TV>hj8|cdJrmMrW0vTd zT`x%5EfZC}Qr0u@fj;=!gyk=7EOuQjzkNYb%91sRI z*M}3D!ad?l^ew#j4? z8HCp{(zVMH;ukC;^4K*KvMAP!E&Q1*)412CvaHA5gqOv$&8DQx>qy!y?bqxAOYB0w z_!~z`+5Ej98&(bMc$xm7WXCi3HLxEob~ofPiIa6Z`n&+nsd@mEv*UP)cj_~6g( zs%-8TwDj zp!*djrMB9A#pKxaCd4iKkIAvkrjFanHx`=7v0%1*kIa$pO+2yb9iC~zK7kTE(kcilxO>inH7&M zo^oeLfDNO#9ARrmY>@l-n_y9uaRvO=gM)+%Pl*fHxIEMBCna3+&((+e2)JX*S^DQJ z+*95W>#!`o)z&Wa$?!|1rL12jU4~2eLG+2o?y>Gx&gMA#XE~=5J5YXtZ7CV^8Apt_ z&Dtze*b@?cNtUq}N)F9nte;|T&v=M!PvPOs=FvEFHjj94HjhWi7xWZrH92#68`&@t zZDV?l^?Jv+6)~0lwso6d$1<#&=$PQEOBFBN$DRc`7wh`Z83%c6|KiM8pJZ*p zbg~~khrZ7G$Mo;DHr+(0B5d;sU$F;m`a=_0y1_IgocX$C>Gh_Cy)U!pS^d1 zvZJ^Twd&u4EFN>C%J3&tktu-Ub}Yf+O=y}RiE1U;A;ZyUc^<29}yn`W$&s9YyyL;fmPyx z0d&@Zb?RyYBgzNEgqM*HYy#`RppSHctOgp9u#$8M({DBANBGB>N{UV5>V$(D zX}}1`-lx~7vA@TcMZhL70M;d)errlPFt~woz(^o<)q%1HUq}ALhK)q-*lUz`)&sumH_CgR z_eT2O5yh*y&*=g2np+gMM_zNOS< zeeg}NCnkHEvWGg#8rQ~O?M2DOv+uG;m+4b=T%oR2ApDwnF_!&8Ke#>C!Er?%a0(5q zjT@{#40}f+D_L2YBPu+ymm=-bGIy${D*7oP{FOFZokn_CdZ1EA-%HtJ7bmuVrhzk@ z5j59GdEtpEh4J&Og$?_gla@w_w`<5{^zBk?v2-5zJiL^%6*(&qpUhfuhOv^h6t>zO z^hYJx>e}0y2R)-1Gt&Q(SFxA&D0wrS&5Mzpq^lx(OxE|QK=FMF)aa*HpRZE)tpC|I z=ZkfH^3BltF->XI?1$D;zGrm=)S({-A2!@I@GO$>H(huG;f2(7=OszFP<@jZ1Mn)9tA(4p;|9pEX zm@;1D_3(Gx%+Brc=C&YE|I^OvHVv6*yk7c$%&P%|o~y%Rq-0S(zN!Y7y z_xj%l{MNX4@UmjDr=}{&T2<{y`|==TH2E9H3rl-pi|g;_PsSa*)y3WSdhD%VQq_L? zsa*Km6?NjXkNS7n#b=J$u^=p2Q3638?cD>I@3NqZSJOn*=|7DEObf0=|Q*5B@(Z z>*dbf)jrn8W*LyUgPi+sk3a79|9u>8SHNG0!@jXe>yK68lU4ZBOZ$6kW99AeAW7G} z@mag8JFw~dj=a;-Y3YI=y?pB+WrU7{mv!pH%(Vw^Uag-4+OvN6)XzEbO|(JLr_wKn z>rUtOK4!c_Nmtm*erxa9Z`8fCy{E7i-a8%^*drEN`lm<3XM(ZvHsoM??B-4-s?hv~*z2F!5^i5MR^CB-6h5c>h?BGMduh*e zHPX(Ow9e45x9}|bQ|dfqo~!gOE9qz0^L!fJ)N?tyfNvzWvB#wO=0I@tP-lPhV7M*m z3vY}LBG(7QgQ_p=Ino<$M?dw9f34}{ME zpVL5Sl(zK(cbtygLT~byjvm9FiO5ASeXjy&hTh~Mm!{G_v$Ti|PVb{%fi*`{{G`j* z-#p;zhEKL`_+;y@0i|yEBy~%@#%rmM`Enz&k^Hg4v;0IS{7b5ZTcAYXd)P}K#qPQS zeM?)KZvcMDU{iGI2JbcEqhdivj3t@>q>Lu6i5{#Gw+AR|ib%eJ_>!{cD6O~}q)QpW zW9MJSv&_NrEk`?RRO6v{sMqcBFJa&C_nlr!c_w9rcc(0i-EgY1wBDA<${vF!^6kPM z(6a6d_G+NJ+P1dT07lHcVjqP&v9))N*?B@gX}lTcBZM~$*O;>YO;yyJ+PppZke?wx z#+#>E&+E}iPqPQ1nd@rUQMGgrLSIMtsA4(dY&;Erg_cIjW2rYJt}zsc<{zC7lrz4J zUg?L{JV`qDwdPs&7sk6;^@g&SD)0B3o^ap`%3Bt8>7~nK8?WH4@Gd#wSC>AnyaB#T z+Bq{;z8T#zV1%~BrZ3|=qGhyi*$-oH8SPr8KIJW=UCU_K%|D3CH>d3q+e`4Ne|EAo zfSox&xdF-zP;Nj?dIOXjpxglEcBbV9;K#s>(gP_!mcD1)jzd8u>#S)WyB_XAE{e2$ zfs9+muUGOKq|NY*yfCVDvE<3V{2rc>ql7t=wrwbtf>Z551k@YQ56;$hZ4GX}!wb%M z#0z9C&i7jZYi_ZJ#V(#>o5sx73-Qa1PwEAv;?_EHwGe&OjTO}OE7Q!?GIzT|vWUEDEP-1ObJv}vs=2XX8z?kE%&fuo}ZPo1@iI^UHE zX-D&PRg!w9FC8p)JTh9TAm{5!%HKr%Jv?8e9mhJ()77VuHRcOh-w2NIv>SAYulYG~ zYD-u#Tf;aVL+jIZ$RhBFJgFbJv9*YLWZf8%zA-+*?!j*R4Zx;0>U~D(kDPvvK8^jr z4*KW1-a_%Z-ofH}Xsq@QRu-H_8-+gdeWAnUt4O}js^WE@HN_`5r;k#Z~*~?D;>DKBZc$e{7wL5;q3%qKBdW2^(W@PM8uU|QBu#!}qZ}*UWa#{&ZTF>Uh+x5x)^(5 z(@XL8sO7yo2 z+j7_!wRz!28opifQ(t3=t3&eN!83~s+hLl#d#R&h4qJO6q#nsvG53Zec5i`i4br*= zN?I$FIwUT`J<{<8`^`yKW>2>%8^-9dd2%duYR0L^D*K=Q%z?z#ul{$rs+kkwzXqcJ zl)y5Od0k}pH>CbiWT~AwZsDNUWc?S6FJ^9XYsaPMBA?^%9Ql+ryU;PaPr_W1(VD?I z>5Ogl7iBw7#b0zVFq5Gz4~^0<@fO!F@#7z~-%3bdC-0}P3&!eC!5i?6Z^Spg=CKdj zZ+zo*zQrl}y?z?~%aid(i9qUOZ@|ifdFxzRFk8K9h-_pytW5ax zWMW>pk%s5@*DMZ^1@i3m{&i#_{-2J&beyk|`v4iAhQDT`SJl!s+Rw)+zWNjLVJF7_ zqg-VidI~rVY_)fE&meYW9BTFi?Kd{5eH4ftG^hVL-#wFkvOh$o&ceP2)_}=p!7X9n zw1huHI(rxf$o{RDe42D%D=y*Fto-smE5Dxt2YKTMfg$t?teliz^#Ebc0C@b`0^0Zc z)Wx?o5)ROPvNmWCA3x~q*+|Z*dDxq5SLvTdjuhWe$X=m*LmG6%<(RWXvA;EXcs?KC zoBy)5A9i1S$n{4}VMj{+2Wd0)NVv`;bZK;*Ism<#+sFIK4{YU$W_&dkIysyjbBrnT zORg;ebjTT8RqgYttkIGPz@Ol_jd3IM+cf1P(IJZjUQRdMJ8PTNB@g38+S!owp_TT1 zn)mp(p^NX#6_B$Rk9YfxP_%e1Jq^ONiSrufkdM+A$1ZXEU+pi%r2w03L5z&N!>=xQLKP*h`LNSL?a^qis>KthKb0^bZT(j@M{y zTwh4t!hfrm=akX! z_!i_2sDKR#zZ=;C3eH)YWvmho#tS-#S({*sN;qqKL-^hjo}L%h(9)V-OT(@B)lN5# z?b*t_x<`;SC<8;9e#Ijpdo`FXquY^Jwx5ZXQ)% zb~bbJ3$BfvXV0BGenelSb4L?-Fh5WDZ0u`fz0U6$WR4MgDr8=XzgxC*=m@;9b1i!a zVrRwQaPdN`{I*1NQtfP!fj8)ez}2tO(>8pm*5^q4YFz`y8|n9R=x@e;UBcJW|7o~M z*pRMYMf!n4DR`CZ$4uwd2wVIXUd~xF<5hSk{k4vA*fhbp=-&0ToA;QwhQvXm*h5xt zk}f#(s|8-JYZhYrSqRM*UdlJGP8THim91Wis3VZL^Uw#chM)H&MSULhA)m6Jsn$@} zdDzU%LBaXZFhsiu*CpKL+L6g$jdC*X%Y8 zmFyddZnJCCdHKxi$u|_dB%ic9t5ZX}gst4tR}I3J5A3l{OS^i}_dEt$z5#5_E9qHY z$){cee|zEY&(UV!oOO`d zf6=b-S=&vq{~@|o=2v|s^N@_eCtVxDv)#B;*nMKV#$C=PkntzuPW_>auTs{~mPfHQ z%wIWvY+{Z1=#{LG(T8e@UzI%v;Zc0t;Z~`f1qJv(a?k^!Vj^n8noYVhEW4X;0us%o7N(Ol1D?M@D^R;$#;HoK0bR!N_xGY zba7-xU&ocmN6U;T`)v@YRgYoF<*iQj;}>D%dt@)oNjk|n#V z5%H1_JJqkTzj{hK(mb<$Yqo?73_9k7SAA@8?92LCcer-U_%CgT*qL>3Brkf^h&_+R zsU4(a`WyRDaEZ}>UHJP-JZa@^>$}Lg z`HrJY&eY^=J5gz$Njpv<2h+meMWnGe6$~JU>?KA(!JFwPO;~hJ4R{Qh*qdNWa1JK4 zhG$_LkaxC!&^gR0eq-yKbc6h|uO+g_yh7ZlPH5va@yXXp)y4q(6a(}IP)&W+;uRZunmp#O zXv;G8O3A00t7H$y9)2A9sW(0jZ5KcnzjcwaGs}@__Q^6F;RRXP;cE6! z{!~1^AVE)U4K@AO;JpT%1~!1QpRF%+vUgIRwuF)|o`MeQS3rFsy2j!^==zX0%kMjd z2l87o`R+&blk9`Pq>sTbHiO7}BsdtaqAQb!kVo+Dy-@ZN4u;8}xp5S*?h(Bd@?G$w zN6>f3dX=%tK1W-`Z`s$W=R?^iiuwd6>!CkM%h7fjA9dzP!@5k?LGgcbGO8alUW42Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPD4 zb0FtH&Vif*IS2mLIB?Ud)mz@SbH{tPt=M|=yG~K7B%LC9HcHCR22S;IB+{ls0h z_S!W+dbs1CUx^R%+xbd-dGE>rp?|`pLZ9t>Mk8kqD!cTO6X8a@P8|o#M zog%_~&)v;yewVxYy9Pb8$c3q!x{T_1*mymS=Os z=n)kt=sTkiAA$WUIA^H};y-x^--R!F3cq0rpJ56=VhML#8}6y5C4RC5h@UxgIgoos zlgko+)>m>Vw!W0il??6|GL9T-pp4<@^Kf}Y>A5( zzu)FtK--(#of@C!@V3L7yDk|kZ%BQ3nzmx~E}{MXjs~go7<|p{u9Z7v#b=`2SKU0i z&)!Kdv}N((0T(YcFU9AYI<08$RlkXM(^0HapmYs)K`)3W!;t%K<&OMXayYDQJ!E+x z^@Qqvcb9C6cPTzb;&%Fqve8pxVZ=Sx!FXH_C>O=}T|yqk&)10fe*B{H%=3k66?qBa z?a0H<_hIrKC$kOw71xsPS^VOoAlQYUgiVQmpU@k)dgRVu!D&)|u;%TKAN9xKU3xdR zy^A*CF4{47SFQO@q57D}MCP;Pn=TyRnD(cXP1BNZ6sjA@n`}?hen_9DeXah1a`2rM=N!*A_7rMn?alpO6(g%vLyE}c<-gVxTJBRIkz4zL1 zaB+e!XyUjpKDdZ?o;pvHXIk!uMusBpX%5ckSwR|)#MLFPi~E`hH+e)(zrtP75qI}a zlNRAGVkvhOD|oV#IP;d2f4s~6$U>Ur*B6sl9{ip)xJz5YHSSHWaUZhOBl+I;?J+%@ z@96dVZ9}`YKC|E@_}!HBCiT_1bGRw@4)+$koA3u@;P2Onm$bl0+b6x?^nw?^)A32K zpdRY0QQyo(+&BDb6UyEB6~cQ6@7?9X8d~rJ=Y`x$Ebvht%g@u+YK@=t^{YpK9zMQ@ zcweiVv@hy5_O9z-HS#*d{niVh!M^V#Z*h+ArJzih`lflT?@1s3>%QmJp>LYU#s$O$ zp7SArOg3m!4QSK6BL3K7FL+_FY<;&cyvhrPlonr;0r9R6rTyRHZu!T(KzxD+S9!v( zAmF`lm4|Z{Uvm$4&BEwx@O^S9e8C=cqBAhUyRTqJQR8x=mkp~ zH89486WYsFo@{Wl_f7&wbqLc;ImM@JB&7;M_0Yewm(p7 zy&$F!6?x*s!U8TqZ29C+7|<5Ee>@vU<~Q6}(cCFt>o^xYsZUtK)4z$Y1@2jQX;Q~Y zpRDuq*F^S`6Jhe9llZdo>RfzqoL2}=g(vvosHI!xlNi64VsESqxM%$g<$Sw+sAPS0 z#%HGCTe+7$E(J+ZRrhe0di4V(ZwB6kw5gMLgCCw5iT_~gdzF3}!Ov+sbH?Yt5bFi# zzbgEfxCQ9w$HWH@eyJ9o_91=OX{IbbQ|vs%e0b**rnvs$xUC|-;OF7^Y09ssYzS{u z>f5ND`WNzCgFkJtyK21GZ!_B9ds*I_ye~MtQ!nCd^C_1$!F!Ij4uOh8J*cOM^03dbiOR%Cp?pt?sEsdtqAJ*jsCFf z+=6$0)D$o5)>|+6L-I^cpfRzGFp) zI6u?p=?J^aY%f$7l4fne#Enby^sRP`oX0#TbC~GsW;(y!C-d8f-29f!YgWH7Ut;N7 z{2%|;5iRA!e~8TO%?s0a`t{?cD{QQweXC>ZW9@C^6@3xK_}w6XrZa?2JNHW7&103| z;so0OJiw2CYs})8J{BLP7T>rjN?kIaTRc*3S6qq6KTBWgE9)zipOdd!@Vjza$~_fV zEbaqR-o@KK+3IK(-P*hYJ0G7x=OaJoV5--{04dl7y@p!XQzbwKNX<+ivI5HIxT6^WZ$@QIONyEX{d z;F;jq!+QnV1&{bvtq_jD^QhF<1Kt0~xP%VDB|NMHp}`j%f>-j250;E3p+RsRBVQ{m z5n z=N^15HSjm3yG=>-O8~wGzL3R#ggiQNv~ES8d|Y*fU9>IvZ>fA=Ok2|Q_>XR_Zh=2P z4PN}zl*N`1zD7wWLuYsOz_`%|iktLEYki-ZTi^V0Bf(-l!rII{;PU-cG<2V&A?Q}P zJ{q+)`T=aAh1y~LyHjULiU< z%_r%SuLWmozWMV>RxU!8@sWo9hmVY#8hW!~@HNWXZhG)O)>p(^y|KG0{VP7G!}A$G z@N%TXSUJ&8Ev$$Sv=L-glhz>KhSPN9wX9bw8S}o#viO)%tm8(=8!u4RD!M?%kZtwC zG@P#0)M6K|Lnpr5emXk4UWQK6ek`4=t>(~4Ud4K+ihjuWX0Q!f!=%g!<5Q-*pv~Zm zCob3U86*C*L&8mXQ4zfY|JK0=i5Hxb7G2`X%&<0-cqu<$9_p*%JAR2}e9qx}io1p# zl%-F%^vkJe_=)mT*H4l!<4bfU^2B4;N4F{GKby6v_|F!9Mqz>vB+>ck5$$cUzO@v7 zaYSC!*{ns9$ypu;k1)4qIK&^N;PB?+Xe^nFBRPF8j{7JV7ul1L{fn2OEl5u7+dHFq zFEp<^70v1RyNP<#50L@tIThVM7Ju5F4FCN0WPA-i*TM_-N`x2qu$#lrTHjn=sFLGF zeIauoK8dQAn6mhlgU5D#8sIx#Var#Ks$y2p0!2I8{GdWViGS;$G>nbO!yZAC_KUCf znHL|h<9z}4myFqrG3 z{U2<^e%`o-b#+{h;^!+;$2G|$(CIqETrU3Om%{VpnUv?J;LnfadB(Sl=P%(~yRy3I zr{-G`x6d!zwo}Vk#_J|BCj1RbKECG{Ve|Uv`MJEV{|kDM$Br-dUxOF1EqL61gb$xd z&%*4>o{DeQpP2YQ>oB^3A2HoAq-z$g#pkAkuhunWMz4;vwr~T!jV1m)`1cg}Ufo#0 zdhlGvI`)t5W?urIY+_&4@F6F7#fP!(j&#k!^|~SP%-7QvUazO|MWwgiqFL~gk2Oxb zKiq?UsJZ!}EgWL+hBbE0rhniR={s$D&_}(6VXtB7qh8vgJ7@>=N&P_q9#xQEi^rt+ zXjeBr(ki3{Ydw7$d7;_yV2HgL*7a55=agBC&##l~-8$>vU@f*CFcR30-764ZaZRAz z3%DxrBjO`qJs=*~1O`_FtHc8X=&S?l)YSw=ln;gpFC!h;1lEB;AL#;F69y6SA?d(i zCFv5T-)hW{@Q*Q-6r04=2?sUOfDw>=M6Xd}pN(~QSj5j^(O4UM9kztnu2C;_Tthiv zuz_;;Pm6%Th13BQe{W5o_=*dzB^{a~U|sx2ZX^thfC2lwbzlT+N|?6Qcr-Rzz+P{Y z_~5O?pGAIP1grz=z$UN>41SS#cohNbOMsM%fK6ZktV=rm)|7N$a0BIlkwEII12ytk zNB+cyjYRJ5jurY#E}YU#W9lxw8#0ewH6<>6i5 zljetCwe($dSA+Kkd<{3VZd!@l!}|ujmpQM#`$24a#yn>(Ru6VMJ!n3m?DKVr?9-HyVtx@4=t!hh^#6-dLtb)p3QIR)O$o=EYd{ z>HOgKSO>=y_$e!OvnFn^?lA1xh>T=qWp1eO1je;Ti>_8rRrFIpcr0zRx{UO&^gu=S zDy8hPi(S7=183N0Z?2K@!V6OhsA%h_??fJZ&o-t0%i>Be?c2_imD};g*zd!pF_*YCM9;;y zdfSrcD?LL!;o%_mpXTW`<6h5yPQqSwyVw6d;J3!TgO?SHJvCKPYgM&}aiCc1S$Yd@ zpWA%P?N3SE!CPJ2eXqx!{3TWG$Ig5Dp_?sT@poOm-qa6cyvDUXexs_kgEwnyjNKyb z=y?L3Bqu5drvu$jI}V?%N;e|I_o0`QpLe)>Dudp^mE*dn!dc7TrF5`<+-BTZ@Bfio zC-xwVOU;;P-b5Q@-T4nGEwUe#?gt)h#N~c?*xMU>QcrI;ZAj12dfN-0#0%^RsPhu) z3<|)b77G5G1pfwy|Jf_xHMsiV`LnWS?A%@LV~uE*0f{@vIr8@S<6i&Y$KiGb{DnB| z8>4UVt*PYUub1}s*2c=);X#tF`(pga?!d0?JMvCTr=<&i^m2ACWrU7{mv!pH%r^&b zUag-4+OuQ$)X%x&O|(J!QTpX@-Hrd=$BcI<=?Z(6)jk=e%_Y~H`d&k29`=mlk z|MY11OfXj7hThs9JH457tE#5&%wM}c+kv0V9h^n?nf>9jn~v%mFEgR3Lh~D9uYYDs zxP94Jc?a!L_y_JIPR>^Er9IEpNIP57Izz+y`dM^|)OpA}SLt0=($BE(_cVI2=W_HS zXYSkBXVIKt3yvP@>~9_nwf4>Q(pEB9%ZRyKi`tlHI zJILQ(KZu+_2W>k9JX}8zJ_CGC1EEpc)(hNmI&urW$zM8p4EqKm7rpeoVozV_jT4uq z{>nj1i^$;gKKd0{b2P1Ov(!H zPFa>Y^i*YOy)BcKJqAzYEc^~=S$75d70_L6TU%-XBjyjW6~dj^o4dyB`b|G+ycy;u zgf|S=n6my&_AfTId3*5pJwtxY{GeIW>d{G0v;Nbp|7zG2wRHWbuOoc4Wj=+!LQ5m% zvD6z9*BFXJ^N&sk$~jX;uk=G}o+Q=Tt$CLHh4F62AFu2u%KQDMCmi^K@|J~Ndg=1m z#w&O$yh~2_)uoRsZ-DPycFv5IZ$`Ha7}@7bZ2B_3OIb$ymi;jHmeHQmk_+O>>! z-TZ^Nd~@0^u|ou(`e!Fg1K3;xlpCPj0ObbMq&Gmh0m=!)f*n?aYY5M{hw~Sw}f_0N;1azLoOiBSq_1WEyK_yT?_8twv1Cgarnok&xkYbSvs)+a)B&9#W*@Hfv zVg3$}90+Aj+OTG)HWnH!=TIBgMA}%mk!eA~*MnzNSJeJ+9d*jyso)bGzW_dn@An1p zVsCPwQicDR5VpsSR6AxZ!kDQmb8k$@!|fxMQ%m>AP`h(^^vw z;@DfbU)=+oE}>!5$G>n#+o>m4kvhsJ8}U}eE+v{C3I-xoSuzKZ1gtSVmj zSyOysm$7;FmQ+dFaUD3|X}) zsrSP&{?yS~O|>l)eN}s*tyJ3@muu~b)ooe0LD+buKr!w{pJqJG<}Z|Ln_Kg{u;lNQ z{G217_*%?&A{l;Fs?mm%_+41?FOvM&SDoKRj|wfjNL$^KHw{Z(^lLDR?#|k8)^7<$xnTaC9V$1e+SPjE^LQs^6sUMiaBiOl#qHP zU&Y)Tjv#LwirH}|bxS!(YlTvW#AUcgI^Lk=JF={fJ)9*N#^|wmax8Uf#;M3Edw~AT zfyCCI{6o2_nG=ja^k4FIU>V*ruZ!&dhSWcbEVVPoEgbZktoefR#mr4^y}0yT%8bKv z{)6bk`o|*V+3fVa;_ToPW2T%bU68;=GBn)J; z#)}^z9jJf}V5>|BKW62W_e@UB5pa+Vgy#ek;$wUJrb_-2wfVTW+KacY*m+#-Lzu`^SE7CX87oxY~wM{xn&jX>?_8aY} zLFe?X&R!FJXxG5RNx3XMorYWGN7`sYgtN9cgzqik>3LxdEv@ObG~9~cyw8nedyX)# z?h)ievBnhLmCuHx9>zf88=yKVWIKe3x%FSrbX!bxEf$<$bTbZ+;DYx>QG- zm)kg-F18F~vzoRyvp1y7zO2mV3n|mBGdk>i88BZK&7AqNF7xHDr1Rzfa<;Mh71u`2 zZs*Jqar?b zLTo$>q1nPq`MxvN1^>Nl^-)9}0ddV&$G*s<>{Y5aga172VdkCSeCDDz(H6q;-A&Nt zXwPJ>b{_Z`YvxZKzPRl4-QM%C7YZk=9XG>zD7m&=9XZN}(eOw1ghZd&b?3Z%<{I)1 z1uw}bZO!V`&?{jptMpHUux&g0r_<8DUUWQ7jNj>?*)DH_(oXr@>Q6{(_G^8 zv3aU&?fc~QC+$e{Wv@EWW@g7lw6$N~$3A@WB=U|uE4n>-oy%`+%yL(y4*vMHZrrrC zX`1+YA8mSMe?`;x(N$laonJHBbwBcZsT*VZ%f=J@`pTF&WPd1QF4{GI(k^3fL--(b zs=g9AV%(X(b8QIEc4JK)cVjB)adv==IT>qWhl#yfrEE-F9u@oI8%~Zkv3`8?%Gg_v z4m9WZRoPDv9>rgExK%1=K>@x|r#j){rJqo)_IEEb-ZklLdin`Ap4g8s8SmI%LPHat z2tUN0YS4Z;qo@HR@CC@XO>2=s$)n}0n>h4~C*QHj`S0vmAnEqpAKs~J9gozdXT|wWIwc)x zp4q-NTfzkfz4DY-eQa^;%i33WxOU9=FKvg|mUVEbqF;^J&sdz=K02nqu?Yp2=&6yS z@<-a--h-WcN)Ouaxgxqc0?3o&1qH zToGu`V>_v9u&dG#DCe<2-Q{>Ce3$VqviM3oY2|I}yU4jIJG$h&OwMpkN7`r7j#J3N zwD5NkY3w@%1Hvcz1t@qk{iF$t&Zz;9^~e6+1pDD^M{9T%_5gWj`v;xFJmNRDzDYO8 zFMC!Zd(0)o@!JF1I8A)=gHp9Iz#hZ^eJ}QKntxq_-Shntc_=fR#&3Wq6Y^b-;LDZwwB2F0|4PuZ9fO)K@KDv74vKW4=LKmaz{?KFu6elX>d>{1#`m zAzx}^w*1yg`d`1Fed`aD0+~bA2U#LLQL=Io|6Qr7ms3wcWY-k!w@<6zWxrRFv>Isv z-!#>h-)+|p_2ux1{*vEaMDQ}|U=Pc}&GxrsQTLnd@5`d@>vfa0Thx66<5}RSmhWSt zUE8&M9~14`HRpF5@|%q&@qyULCukq_#$SQ93!sbNdPv!s<;XmHWEqa|f-LNCHG3$3 zsy?^?y~LiVrhgl}*MQT&22l30^@a4&9C_OkO1}8Z&_VqQs4qkpS^NiGAJb;}t)TEg ze#<1^y@>vjJ@A*v0Qjvfp~x>d7|)_hljF!Mc=ui?`v?ca zA3|HTy}(|0+!pb>=ymG(Q1*zTK5(f6p*fb8qwUhyb>>jRT20nQ@qKRY(2p6f5qF2d zDZYo9zcy|P-V~SpCPseS!EeTHVvU}>jd@oYFL;8d*b@eqlehR(rG`w%+FxX&Au`5a zl6=7K`xy4Mr)7-25x$eAkHDujZfu!1versep#JOwRvx8X{+Dwg=RnSZoC7%rat`Di z$T^U6Am>2Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPD4b0FtH&Vif*IR|nM2Nft&+52XYSN9LPEF z{|yJ;^Ul?8d+)YYE4JSJu2Ui;?UeCZB;~W$Q^TQCNB?_?y=v{XYkqJ2&1+wY5A)mk zN_=_m$`z|tymsYlw_f_%OIFmjU9xKXj#aIk-1%!aulV(yTi$ikk72|$?|xV3;4Qm4 zSN&Y)s+E`j++~+vx~g;a%2k(T*;CY6P${F-?|$bqH=LrXlX>#DmvEq<#_$sndj))W z8fAQSb)nizILlbXm2u%b+)4cHLtb(g_b8XzNHZ#VQ{j|%rN-PJpOyW|U_yRFRtM#t zdS9*g%v;`<(lIxEHs90lOY3pzz4&L9`(}HmH2z3qX_J~hEB3{|i-zXL-#p|Al)8r1 zicszdm%EZ{+=CncGxyO0lW$OW&>fl&x;vnK@FX{>>Qo!;UghfZ@BU_Gsx9{Y0cRZr?3E+qa`Au0J?Rd41i`@EpELGIrzMvbHxl-j+1ziRLJ_REx! zyN++;j@-5cAAjxMWFP(3Uk#d_)XSZ}Mc&(ZN<8ZGg=#y{JmUJW`QmM!-vjM~E42@; zk$HDT?(LPfO)XZy#J~5tqq?rCXS1o;xS{ci+z0;brg1H_x;*3hS@MbR)u#9l=l*Ma z?%)Sxu+qdQMsw=f%9ON^I+8`js`!#}d?38ASQS4QQx($X9^&?5br0c~yOA?~i#++| zHI%s+-cNeL6;&@jEA1EXPBidcPrZ$X(Q=o0?S(OXfSIzi!{>hV8T?dtZ;$YaSLdae>6I}vGe zN3-znZgBbF64?-0h`B3TWJ9I#5+~t+`=EpIqorURnF2?0zmplYKOOgfa6#1@ zRs*4>kNe(*9@_@)V3#&50*}z2eDBt(a;Qw8;3Dd@IQ(WzBbPtxEo%wI4Qu zuM8f`ccGtt@VS4wwar3{jCb`7N6RggsZvJ$!>v`}yR>&$bzAx-Nz3{|=uE!m+A|q% zvFTY^@ns?OOCNMJNdD4Y#w|`eVP1d>X9}JKMX!2r9SEV`1_9EKPxZH z%kg5Y+sbRRMaG493jfQ}FUey+z750bDLWP=zwjz+gZidx!^)O;({%Fc|9Or11pWKx z+B2!2Djlr%Dtf&ame6JDO6!YKpvZgc9~ZWhk8z=uomb93r|QW(uAyC5t6t3{o?bxu zneBm_Q@NkNV}n=2pXaPUU$w!jwBrc2y1_H*O7dM9EWl4H&c3a`Z>`!%Z>R30TCKKw zGPZTRKMaR!-k$MA;`hoAk6s(f*v{%mzVCdE=t|AgcgMQHqbr*Cg!jb0w{e}n;t_n| zKJqc1LdKfl39nf1?Ku#aXHp-#;axQ^oQ&~>hp&Rox9IRLaM4ElKABiQMiS?5?6qSm z`JSsk#KzdOKhfcVSW9`>i@%Wd-pE1T;a!~O6aL6NHG>T>?4id~JsOWE3w?aN4im3` zi+Kv)tHN{t9CWhkvU)7}eJ2l+HyKM7O5Wxe^UmX)p{D<&oRpC?i61TwmgU{wx*Z=R zsyG{ukIs|tM(Y*$KPZfq{fqG;e3?N*$fhD($#;cUAhnrM#`f);Df+ ztrMRWQfK!&=hbQEExtU# zt2QSKBif=;n_9{ZE7vxQ}A2{$7x?2ar_r~n2>&N z35y)~tOvvn7Fo3ALh`)b$&}a=0plawgf6*yz1Q@y#n256U?l!|(SP+8zmw8u3cr(a zv9K^4zeNWJOj*WvxMn@;1yc--gFzs6;aE8W4xi?1`(gb0E&cXG-qLTs==D=?Km2$O zTmA5LV$1Vj%TIJctE`Vk8BgCv#<8C#)|v7HuQH_vEL7PH03jsZ%@-f?g3Hjw_*)5H=j{C8Ly0#HZQ=_@gF~yt`d*%l$zP|B$tUH+rjoMq zSUkihJKUU}EJ)kK9A(>yJedL49zD&x3GNB_qZVR&;;(Dsbm*iX<0^bvY)TX4udxoE zmIq%$!kPp<6Etg{&^;yjcg4jiWKlJlj|*+3se)onI#||2ZKa^7{AOWL`^U65Jy<%K zR>W~>mi8!VU7k(zzsUQR^!+b*A9MJc3+Y?rHJH)fSMW2c?udwQv5BEpBR5IwE6$yeIn_$cI1EI-7j>9b>e?l-iNxv zChsCU=0_j0yz$ROeg>6p{%Raf(Qm`Z&m{hOTzsILn@lMA{avO_VQWr*Bq<`?tZhrk ztnr6=7hhlUF5@NY_U!wVyl-{y!}v*?T4l=q?xYyeM#LlibeMJFJ70sGvsdtcZ=hd^^UeP7oj0HxXxl~aj6I3> z&ts2c?1-J`%_VLOng5;Y0@9@1M2x?%+Y>!3dn(W(^#!-H2F5mszv}WPKXfqLvl*ss z{@q`#`0zKln6?+T=wW=*FTSRrsVVy~yG&8`Sp06}l|Ha@h`KjS{+pxC>I3+5DjQ4P-;yV# zP4r_xKgfPd(pIQS-`v|W2N>3~LPz}Ahb$D^T;x!z2bsg*ow?Yy(Z3uXZ&7;q>IZCC z4Y1Z>4>9?3S57VZv}b7F=}FCd)sdQa?$Mg}>W6FI1t#_`931mZ$@NR2PqEfkL9kQ> zXAG#|^b7INl=^lR9!;sl_mPRI3J|@_!0;t~7+8Fy<_&p?-*dd?6`A|mhSqzxtu)1l zV^zA%PyC0~SovY#`K+VH(XqwCm0odW>=ju@6~Qg=Xd2&1c#?Wf@Eqm+XfF`|heOEu zIL}d@BK$v}Iq-baKTg}e!gIdFW8)V)c~93~7B_3JA=X|+S$n1JX+z((Dd#f{4l5g` zpT+)C>{lLTEFbNRi$}pLdRXF$jL9N>S1eFRxy|c6I*R^IY~KhD`4c`RukzjgW!evJ zZ&dObbM zw`lP<`1M2MHeJe{s?5o_x9G1Qf);2RfX_RjLF@+M-va7;jCOpDw(Ueeb)p+2-uj$g zhAqH+F5wZ%jbek3ED!X^@O21`DGG0;+y?Lq zPwqNrqrUT;&6b9C?41ShExz30mOczj%o|)PaO2}z>YPN!O+ni*_)JHdAAD0| zad|jlUy!+6>bbUOkzRnFJ}JmgJN9_j zxq879Nii!Ew3JCMb!DzGUqwEUHE_i@xVSsBxEOkW(Zxx+=<)c?X_z$8G4Y$yu+aSx zN4Hs)(H%hdA?T={lJ59ISN8L?rw*><+LO2zbQE=S@w>E7zZ%w&LgT{jKnIo&C-Jqm zDPHQzAMXkDweZx3Mxk4!c#kV|JaKfK#W#g)h&^Rk3;Os4jCiW-LnQq!-OeZA$@)Rs zJ5gbdp^q1VcM-UR?uD!4a1(Gb&*KG!)A!ihgq;#!=I}gT!0+w}7iZGG5i_$W! z^`(6_D-Rh>aViffJ;FQLYZ+$TP4yy|^xJwBdw1}NT_F9L&23q{jEP5kB7H4-vQ=iP zsodJ}lkSHd?<&p8R1=)RZKl}lF}7?b6E?q>wn6e3Hx6aYBAP+-Wgi>J^5k0&dC@LY4!^a}8^M=m)9+?4 zs&08Eeqozaot3FV5!-rgDcWkvL2|qIC}X99eH|F>$+=0uMa|ECMe zpJu<)l%1@sXTNTGTxpZa$og@k#hw?x+TrN$+w(KARizo4HBOc$c5m4EAZKrCcE7Z8 zT3imksEX^`lz)tP9({~6tw)c>ZPoAWo6Q%}k9GK5gSLh|L-=~_h)Z?)HKbpKW}#E+ zI41P6UX}i^G)+F>XcBo$+c)yU1Zyzn2SZqM;?FVVPwW{lN}ipYe%sna^YecK z+6P!4OT3ibxu|a6v+*;94I<~Uewp#cI#${!^QK=;?0RU5HHYMl%Wc6K>~X*OjPvxH zV`LJ&{Ul}I98ZP`evm&#`7@IP;m6J}rH@heON8b94BB(XQ76L%*)LzXyZR;4&(yL1 zQS{WCKWxe$eRHAsv8z<+Ozh8(US-N(+F2-`d0M-77C6pgp8nYW{ocNbz>;Bo*7dQ_};?)v(P8|4T9?}r=asK^XNQ-x&O&cN2ovX&H(?Df}im%_|M>7 zpyRhucCCR7T9|ANE#%DGg}2Gsw%gNEoP+Z&Yl;b==yT~8(ci;BU%CB>n6={+;fVtK zyX?2PdXzFh@9a(Uq8nE}{p26n8rHxyL7Rrz>zcA~RO=<}p1)*+H=JOvrt3tpi-yOr z=dg|TlJ8hDSxNXtfbnC`rKi(yjj%RbSaZi-g)*|&S}VS^j&=AE9>#~V)TODbMqL%o zz^0)+qeI#ybhYML7aurfp2ly+bMjdn_{Wto?C^~0tesMKE6#*H+X_)y31())$LXvW$(VUjd?C)KA+mH zioUwthDR79E?l=^`_A~8=FI+7b! z`gp1jSnRHFAW>mIsx)ymP;{o)20(d+`x9UC4B~3VW;Hp1vmI*|2n|NlRa#aMcK!8d+MxZsoU~_GIFLhC44@5;^cV* zeQNt3y=e2n!>KM+njk*@Yp0i8U%NKg^9=e^WWw>*$x6ltkrVsgtxD0d#Gjuj$Uq3Z`99P=jdcbcrx5e|7>-xumgte}3 zCT+TuQ;buCoQu93hQI!8&$)R#-qBJI=h39QzT9r>wC}8W0^(~~8hny^Z5lk9Ed!mB zFXB<2qsa%q#5sDlpDd^5;ujpP_-D(2zdl=j($*Cbt|MF1JUTvX+bjH-V4Y0UUE3A= zyIDDG+q&rKEu7mecW@XOBq^^XzQe^^nD%+w zCgVANhi|`eYf4?n=+p%c`T|#>qtfsc_4rGX^$L5*T{r6bGJ#ul#5q%QG3R79yjC|Q zJji!{>^n3EH|nXvk&?o8@%aWR+3}OrCHwnQpFKmR{$cD$8AlWFXiA`g4<7=D^IdK8)W1P&&fXJrMfX)f%BPZkNqf|y@E}U5E;uH3f*wpmxI9c;_YWMy) znIE;|#MXoE5c!jH$k}@5$gj)Wq)w4vHImAVoC_cqQ$K6JtZ;IY@lg6Dd5$wd`o`%U z=I0mO{=OTJZoJkrdInF*urWVf|C~xjO-tRwCY@g{_p5uPK4ekxF6&j%`Igt?PluxK zMJHzc;-eF1-$n0{KYop)Euz0B2>ZZD%5@L%jbZHTj;nRBs!AQgk6UyTeJA55VytE3 z$I1?KovckV{H-!DKYl8e4Ur2sw;l*(UsC#6Xb+^0#p|`$e}2fGf1i^>pRbX1mdw`iG{>ZRCkpa*K~H$*LaBZ|F| zU_352({o*st!CFQ-5|f_n}Fa5_8a?AF8;l`Nqlqhuj{7prt1S*&h$sYFXxZK!vJ}0 zc9I5P#AXs3Ok~={NnhOV1<)VRpLWiaF)uQ&KI{d2L)ILNb-=e`L9l_nB{{=)-;GHg z4Q;|N$G<}-b#=TIT*O=30GoyPYYqi!NlY zmNdSxWlz=3|6*53n#^r-{%+ezT9dVJT^^BX!Jp3a6UeK4Ycw_P);Lx-4ek%cF0uTQboul+8*o+)7@1l=gpPL^!dvstU`QmZClV@Nfdrt9D-jBL>b%(c; zb?4XWl>MOWNBuU>O}IL&3IA_#g?4GvtA17k9*NZ_MsVT!J?*D52QSJ?rwTfbhkab4+3!AUH2vo<#@02F7!!$ zp(|Kewe4_p9kO&~^$6}^@YTuNicj7%e7631_(BtVdsO08ID6h(NWALMxOWG#kj;xS zeq`ME_td-vd^0t1AP%E7M$7xuE_sjayT3->H`@1T&Go>9pOToee|JrOPY~X@M(L@| z0t4+|B5;wubIlUnj{fmK@=AGzbo&y%;i4|#L;DgrJI?=d4&)rjIgoQ8=RnSZoC7%r zat`Di$T{%Sap0y^tGB$|1sJb%&x4eI*&2slHuc{;QSQI!esI8hB|gk==PU6gzyIRj zyla0V0`mJWM)UhG_zuhG8?XHS3uV8%$nU>+>AeN{{TJ=tM(!xc@4rY&et!SO>>V@t z{TKQD7y11c`TZBk5zd_Lx1*eSb#b1}(;7EScuL~r+lp=nhf_F_!l@M6JU!WYe18AM z1mFJ%PvjZqTLB9%axlODB3uV0oI~f05sRF`(l7{tJFzkl%lSogjAs$ZrbxEzkr|e&Zm&3Ci!k;5RP${TKQD z7cKXK*!wy79Z`P&1$W<|Bkb?>_zl%WUwS?Q%7bCBO(9GIgoQ8=RnSZoC7%rat`Di$T^U6;Qtg3+_d{0 zFL(WgdZl|FDF5$j$@$zEv?-&EQKWJYb6Azk2#3swm%V3*_4?@Q>m< zLFM;f^y9CUC*V%;VEkx_JH&M${sizD+fKaNpZ*5uZ&H7-Kf1L#%DoWkMfY0(xhpp+ zaQAJIdlJTbtB)e4($CHbVR`Od9X$v+|e z+*9>tzOv5?N*nNv9v7nqcQlvUy?(#yEiG2P6>ZKxx6ggYem8yv@V^(dC0u$nU?%@4slh>%!-riwU{w;>gK6F@_0GNgQ`L_}vZ;r*I;LQz^80 z^7}6qPNh7^@4vwI!3RXc$EU)$Dh3DQa=q2pix@@u{THuz|3y+P+O;D1&dEz@y{N@G81U^ylPj$Vjp1`+**-)@Peqt%LC*+*&bV33|=kqdilK_eg zLJ|}+exs@GpyzaWMFfBIIpa(xpw1l!1-#$A^WB*{?j-6toe;<T8uI2B%cwxedHDA${{|wR=IxIFmAKh zhjn&C*hiT~aewsW5M{>iOEUcznf?nu(|_Ul^Ixq0Lj8F{3;5<_rLl7r+#2bM?EexQ znZd2>0p~M+|2j?^{Zs6ptNzfTb1zb@~Gqgg_m>a?keT_S&r$u~Lc zz&2{wI4R*Pu>WNLYuq+R51=JJc6ch(&)(PB6c$@k(I;BcByF3Z4}s+zhVvGya%I`a zf8vTU{dI9`_iFR)WWWFD2V8qH{TG@3i%kDTJU27_7b??#u^8SQSN5UlXU6cq{uz=mt_XX6g#RN=7xh&RUN9LfcS;K^90g!#od zPRjAIYm2RDzlxK3&FS&CyP)Z5dA@DYNAbG&yFWo(THb|moWdrnwDGdmyk;tI)Su*C zKb6;>f1LU<{TG@33vepaf060GSfpNg`Y&wP*76hZz3bq64Ys>K3eSHMHY7jVZ3-Vn zkLFkTE#YqNtGf60I37O7UfXtTEq|5oC&7o`%N~E-2Tk$bb-DaUFI9z;bmZTAsVRQ- zx?KLGIUU}~lyS1z6@GNrF7K_-)}KWG#YtTq-o46tLaU!>qaOA4P}+DBe7>~vEvmO9 z?UHi_q2+Ixp?z&V8yopNuvp z_OGvw{pjkDyWIHQkh(go5SG0}4c}L>t>zQedl9|WckQ=7Ox7I6$KSIt9HK0-lUo_v zq#Mp(uk|S%o`1?}Y=1siQm4fImi#>+}$NvgviK?7K==x_;T!rKxL(x=PXg;Uw@$+fgAb?UMGSX;#|ZGo~5; zh&>{mE92)u?}fmCbFGkfW1_b~Y(mR#vAZ1q#zrf@U6{Es$$k8ESRXN-;IRMaLtbN# z(mv;Dg45bO2tFnCFjwPp<9Z}K%v_kRD?&%)S=;8xeZPNso2SWcHw=DD8|#CnSmT`LSZ$5xB5+v<|HplJ;|%0H;8F$-fs{;DjZ_%i`*=Inb#E zW-*BlOc*ln%;nuY7&c|?PV%LWe{NRMz6`Ejc*}z9g8ETX7WY(JJaQ}0Y@8s2*QWrRS zH2o3{>haHFkIsI*+52`~KU@5by2_nVbM|^&b-$PEru-g2-iR}V=0N-wU%`*adwhG{ ziPiN=&}9+*N(`eqa8ZPZg`N>U5g626-;acW(?_N zNnd%oETWMFXXK0@y(5Ar6?k@8J8QtEAueZ+&`Z(^s~6!3cMO6jDIPU)dkWDvwmCd; z_)EFR(q$1Xo5Ep5_@#``OgL&<>aM^`%QUgS7<`X2-9cNd5+`!5Lw%+=UfQ6W?8U46mi*)6>vco; zXZs0PPmR00YSPBWqKNr&e_X%NLUW({hP-Sjd)+$e>g-`1Kh55xIjZt0Jwyfpxdj|$ zxbn#>{irRXu8959SiHw^v}s^hSe1Ds`O!%ku%@cZqghq*%G|Azr@3}S*CoyDx9Gb3 zX3hof_j=uAFA?m0GOWDY>dLz#E&cLO?(qH&ncsJwY6@pZyTV0(G~_MX-=h~_G35RJ zsY?Iej(mQRxe>Y%xi!}OYrOYgw1#wcOkamvv_=!&OL%V_R=0cCv5)*_oxJbooBB=M zA#c$K2-u&YfN@`Xv4#F9_qyg zBU~pex=kg$jBhZj%>1DKU;a(jz5B!JDSzgr^+?$j%Bz#MwLA%@<+=K&l@}W8?NE_d z8W{C%%SB#!aLl`%@lV%6!SyQ6zkA4QpToS|ZNus^qb1zfBH^kFXSyt8)U&?~0vQA{ z2xJh*Ado>IgFps>3<4Phex4z4^ShS*MEWnte{Ar)3iMz6{>VF*9}f=G`KiZpp*M=f_roGjlNOS}=d#IOtLeT@zh7)}O>R_zPznRxgMoDx-RQVQwheDHfQkG9yq7TC9m*Biya6={W5+}a{?qf6k7n%MGzv~no za86!r#j8yJ#o;-Y>A%SIUu60(GW{3Po+(`yelK_6xYoD|zZ()K@*aJ$UrGF0;x`iC zrCE@qg?AG@VIrFyM%s&>it9P-OL^QI%Gw?c@U3lQSj($|$fSzwYi$g9^(4H1SCn^U zNFK`7QZDzIQhq8I;L6GEnN{KLTV#I2fN$iNvgNKl{1@bcaV|agoG!h5Pn~NIytLd? zQm(r{r!OkusU=@U#eH*SoI4e+AXnz%&c^Sh{Rs?e$P7um%eycRSCV`+@t2ZTeDe6o zcL&S&Y%QnxQoojzSt%stByBlf-4!V}DZjcv?vSVYUX7j$1LPQ_4&NqYu_uOqW40+y z#|6OypZ$QyKnb7k@`aRteZ23GwKm`lbhsA&ZpDb#^rvDEr;u54r>z14=hHqfdbSQU&~(5Ltc~AL!;<6U*~&F>UIfx0NS99OeChJy*U^ zsN{`bAv`ol{e)}aX|>OD;f91a#^K5-)UnhQ{jE{HdUxJ^Z|2$xL$i33lQYN?wG}ks z^_&aH?`oh5(uU?}Tj6i`Jsv1uBa&;etKq8fwsI-^j}2(J#L$$dv<317YbdLLN;6) z)*uNBeN6RVL~WV=i@oR`%I7ZedY};#xyXMKx0mo<_<+5aSZ@%TF^1cV%cFnfbY1pN z=lkz6-~I-7y2KZ(m+v8bYT3)p=Uj#F`EuDCG?ABYM`vdu^VilK^4gFGmT^$ZD)$>2 zApDo&-Qiy5^4=bs-%GiwsRN12cUwQt*yWLX%op3dg?rbR((!@?FKjdZl zFJgWz(|-Z38SB}rl*5lZ%v0bDan^d~KgDtKUG@WZUGkf6!sps6liwxYIeyp{E76lB zb9M~Z%N7K>9ofsrdds@86y9#s6x-R)Xvz|~eS1!v_aO0gen*#0mDS#r*Ui~CYQLmC zvoJ1iR$rh+_OrFTptZcS;{1>u)xS}(@KWeXnS?h=)5@90bUhuS zn?U%rhTZ7&b)@B`d0NXfymJ|%jANzoPh0Itos+#r`=@ny<1Jy?lT?1nIx?hw-BM?! zGb3{2>n{|3HPe|PxbDu}-PuQs`|fue=VyJui1-G+>f-GmXMv*oL*mkW6YNRkeN|25 zd@ox2bvag^J9VZHXzt?bUV%_qX<(o=NJW;!#}#u#?C6CEmo+vyl_Pm}4) zVDCNHf@_>33!bHTFZ<=D;4Hdr40tZ|Qr@`w+rJU(v$EH^^YS?THSWAT#_4O^nYs%n zZ)u0f8~@%omB((F%EP$G{HRKOyt9;c_>?bkY5Dautd18iLo zcZZWWZ9nPy>*gtXBBjo_{Trt0l{s1B-faW-c8g=bg8y>r%rNho(l=mln9?`k?l&Or?bU;xY7w)H!pRt~bQ# zJxJk-FK~S|>C8~W3C_GibY`f5DI7NDrH#*t>dc5Pn$nq}2#ZWY^Gw!bp-E#WrZdC- zLfp1YX9mO$dl=X*D>kDZ$BzhoZ1!%^dF^<1QH;He~exGiNK9Njk zMzWqEyA9mjy1`vqPa0;uku^!yo5?(UT5>;<>C8ap=jU8!hUn1v{ZEbQ#dqq%_jh^B zBQzFrx6eBO;WL&Xt5eO77OP`XJ{Z;BIjz6PwD78h>k6E%)JDV!!d{}!D7X1_wo&cxU;{=!8 z*#h;&dMePhf}V;hZwvzScJx|^pXtxY^k)e6Wq%n2G6-Z4$RLnGAcH^#feZo}1TqM` znjrA*8-6nV7vw*7cL$IC`Dgw0(&d*e>-+2??|5*S-p@?`#m{==UY`0h{TG@3i%kE8 z+?}sSra}24Z&2G}+ZtVO(<1vk`C*k$b(I|X{i?&?8{E;oIRCF|`@go8Z&SQKLiSH| znjB4s$yxcbcV1g;7uugemr17oq8vCm6l8aV>UE;4L-cn<|7TlS^mT}i54D8ff4{A~ zo^KU(o=ewHSaf-q?{6zh`k!{ZwmeVf+KW8NL%DASz#|%+9LW9 z%H&bcqN5+b(K}aHRG(|#1m99!B+}04n{j_8xZ9V0rg`P8TiUNkAL2_M>38(?ZBBQ| zPuef3=cxKsGW{2BEMi?VeW8q>+!>}iW(0QXz_zlCOY~@bC*gF_n9m-87Zvri(?uic zW&C8k-I#ti9`pW|c+-sW)&CN2LU_~be~CMbFqQ$;!H8GVBVNecs!&~mi+#bD);}GT zNyogqyWofnAD|M{)%H`FbQJ0YJ zlAt|ry>_MeC*M2xp6S2H^j~E9FQPqD`VRbF)_h!RT!r5ai4z?OeX(Cj{958S65pj+ zkfi0#Qs#K3|02rtU--y_jj4RF+ZOA2)gd(a@E`InHlLdnVuLc+jqMR^c!bMFygITj zp^5z|A4inGAHuSdg1flSugy^I}GWRd2LSw)dYb#ChGp{v;&nz)TpLM3DDHC}b?M43h_$GbW{)xN~{1xOPzNe09 z14ZngRMAaPLBEB*TzkQwDK>g&Bls_U+(8>M{THA2f?q6q(Y5iKp6S1Um*JgxgZJT? z{)DA8S>`s9r8}wH{>lb);k9qKBf@Uw%i$ty|xO1vsBQ%NCk7xQHS>_az@i&o$_(GM7hP*s$U)$h_x4qxw_gPig?nnMUHCo((f9u|&^B zz8^gj?5CWL3j9p}MW+9v9XxyVZ0mm$dU9Qa{A+S9)8XQg)lclKXZkNxrvHL>7@7VH z)>xbAzYw|jI<6voY2Q5E7%;`j-sM`}8w4u0V_y+nMv2_K7Mt|y54<7X1yBB_%8Sm# zN@54Tx!vlJcg?{xoAqhl+ZTBH&h6~MlCyFD`OkaREv6Vgf0s9Wx5+pCK5V0rx>lnbMtddN9pLmVgg(|nZ3VvEGYW5j z@6LtKjC`N;6?8k)n738tXM;C@f%uYtFYhM_OMIQQ>6~?EwssCkz>6Bpm73e~eCe}XY{xWu?s z40>A6B|o?!Vb(744}MG-Y(lekG^tl?lUMgnlmrhd3mKnG|Am8V6L?fP2U`zr z%RF#)w28~~Unr+%rk3fynAKPUy@Yo9;!{S|c=%^{{qU zyw*hMQS}$GMu<*^WzQsh@6mL=tao!$Xj}yUD`ZXd@VnoX>$6tX<(q_&J**OL;zWN- zrvD<-f6-j}HXSVC&U@*4-E{ujb(6Q}&E6ZdyhU%$-lQkMr+UHq7 z>Az4y=W6H@+Y#+@dMt+FGuAW5Limgx{2^Se%jgJxatFMhn~UfnmozR6?=g{vSz9Gf zJYO^Y7mzat-^KvE9rRG-O+-%h=Ux8=y>_%b(|J+%M3-3*G`&=JN5Hqe8*7$vFfH9dj>Xb=~?>vo~8X4 zz5b0Cy>4mG1^r9km?lq(PJi-PSgDVH|8rN(P}NkLEc7A>yh#5A?`u_?)h;1#XkT+^ z$g^)#<<}vru8^ZsXP1!?F9-H7KJOW9E~`Qt@kW_jlsgxiUV;6$Z7%-x^Ot$=N#qrd zNR!weiO-cNhkJ98r%!*|TjINe^!H&O+s;x>wB^X}7Y^JXUMTmd*j#umXBhL4fxpUp zw=|EpV1M{_Q_D;cu5!;kWjzFGWAtR{qPARKbgMkbAcZK8I}l zh4jz-%eL}`+>y+iL|*@7RhT!4?pJKUO8G;tL7#F@Z-}i`ZENo<54{GMV1IFl``qXs zwv{#c$A9bdp7;VMO*@7-lhwcZStlDcl_dr_fp?bhm3p3xJSjfPWR@TH`K!>@&ntT!yw5Tx$LZp+ zQtqvU=KMIU40$`oI<@Eo5BFZ??AWGhqTh-0XzTzET^jnlTQMcab+3;V+GNJ9rbgKY6zuqN6vQuzJ$B-uT8%Iz(5my!&?Hi3r?|$`Tho zz#GA}$etp9T0*|GjLb;+`?ffelvBQf-}{sO$TCh3I71)LRaAkY;#sdJ z+trxo?_D1%!Ut~|!&VXU71%H`*xWMTj&VA`ZfVffsjJv6)!0Z6v5{Uq)jAvLCH!Xc zMl?8`F}j5L`-gtHdwyFGoW6|Txa5s!opdrEtGp4_yps`MV8Z*+LiEpZADYM&$eYoi zjQj;Kia7JF5^lbUdU^w00k12>`+Zg5WIgjWxx0(d5%7oQ=9_>maPyZle;3Fbq1cwH z-xJd}xnq_4RXJ}(ZZmAmMqm5pxD7J5-Mb>}!MJexuINkgyP{l(cv1Sc=)cD_HUxLf zSL6Ek{^)nTLFymF4PMNfpb#H7CXU~OCu6%-9C)(#e7^HGZ0{LX=Xo0@;rv-iIO1Ip za?x$_KFCmjrn`OQ2c8$*e zA#;*6g4=m;JD=e8Ag~w%etB^F0>UyLLTB6Z*4sy4x|q`!^85ST<6j7^y&3oY(+GpN zZF{k!YpxC30>SUQys$z!%u%`LIF0}Dx>P2s*kO6PgvMvIn7W=+J7YCt>dFZ0Nr`ikbJHfNryvLe7cObv^ zR#ljNYUHmij27489|3ptP7L-j28n(N!GXQ36RkFX|B^LJ;3MB;&2fLb;?}D0ep} zu?BbV-R-@FwWT}S?RD?j?VYTMqmPd>Pp-uFUfR#OjL+kPqk1mmllD#e70usTz6YB6 z1m%4dINn=S9Vd00qV(-#%Dsnni!((vt9#u*{vPfQ=iY0I(w{3|PkZTGH+_oRb6?m! zct7pgO&jj_4EIId1NVDRU_0k=@|}cUl8+X1`kr-nCU{_!Yi~q*i$`y-j7{3+D`~UE z4x+TVn>KexyTWzdrqInA@&w}|VGHejLcUXH+NX7A^1E9V=Hg3Vj@=JnxbdMFuInH2 zx;GH+r~UNn$bQ&T_gRsDkF@El+gzLGQpe*`7xAfV_La0>WbUNRa|b?ES_f>q;h7Zr zkDj27>&Wv2dFJk697!u{U&LFrb*zUnZgZE7IvzmA?n-q-DE)N#v8gBhU1!fPNq^11 z#&hXP@bPiRPUe@C}~SDa_rNfJ@VHXfAW~%1f2* z2CwH1?gF1D!ntObH+KMMnV0Pyo@<|%FPwr?=!u%k98SxXHcFY&4hK_kq7_G_{8NzQ zd3<1xmVA%X<_LX0Zd@q;o@INqtE2LnP|6p+RQ&zI!>JA74tO_tL!-Jnf+^iQ-z|yW zov>{N-8-j@c?;JBpmztB^v6ey>RgIBFeS!=0#4SNis?eM&!pH6G|V$~Z4;8|=> z&J+&EU+_9TInc+w?e0+eHo4O}o_R9iodxdl_G+enyMDo63tt`l(U2GH?a}@f^li4% zBGV8+|Af~z?Bj&jc5R|h|oBeWbK{;@7hh$w6*+b(uz-ifk*qdhl zE_*KdF0kB@FSzn+;ziy>>9V4t#ix_9d;9XIjhaJY1fXC3pJb+iQ~iZ=WjDTphDgD!5Hu+uHfiV z1DhVrsW|mR%5SnaO3V9-%CDMZ3ai?bziNRg4)J?6;f{hTteS&!@k+NZ9M(Ix8{8V) zdfX=6$z1A$zw78L$GAuPWdB$J_Kn;?QFH;yKC%ICS%DX;;VSTweu$5&iQ{(#zS5^G zb>+5lgEZmAmL%}{<*jAeXY4krB(8#*9NvyAd*wr&zynp$RMa{_AWgavAbnV7;HSkAOKDe2=|BvOf&`Ay4LS{Z{5W zbfyVEUK+cR_lqCU(ry{w#!_4G`>xc(at2U^W(?sdvw64Gwbxj`a=FoswYDf}{l4GO zX`1NsevB`!j)*$sjE21m^#}}QZz6ha8qkO;ys&%|{HoLMIOfE4SZO z3U9uvB<>rOdE%;EE@#-_2iSXXxyvQG- z9mBLK+_yg5L74TUD6p&Swx!0cYjkCc$=APp7j~_H9eC?t2)+s|1cwE`WG^tz*vY!r zIEOK$jOMLI2gL1QoDbk0q3m{W)PBn^%bL*Ox4fH>Ip{YgN)cyEjXeVektLRIwNoPB zCw&87>hj4W{jcFG{MI*M>hzc{_{U7SN80$&+Ymp;T^P%g4*E!y&%p(nN6>6lj^R|^8KFlLOPERIhK$Ehj(Wc+> z%j2gZ?>7;TW7HkD;|}VrTx~7-l7gJ zyJI~jQkTEy>8ZMCbM&>ioG?o2@1g#`CT`+E&%UW8->9_lj<}8FGk-}M`r2eXnmIcw zWSn-`ub1{yN0|S53FQg?@aX;Fejj|vkHY(?f`i}PrcKt>@!d8ra#q7{Bt7qe_Rj~u z;gKA@fk)a=ihKzV;}21mtjU$rftL^NL9Z}k8BX$D);C!%=(>C3Q=uMBI-fk1f#faA zKX`7ft`T2xd9Mvc$5n%N*P*!qcwD=gvfoV}!EMTIyc_>L#JTjmTY_dbkiT{HybzaX zzVEp?FKHXO(W0cki}DUhIphrs@++jRN%=Vc7Qz?t4O_Ra{AZK$ zzY~`)X{CIZex~+(Gf5BrNq#BQwTE&qqs~LP=%X?2H<-6hw^t8%4$PaZZQ!YU2PX5j z#(b2y-ITXeeb74aG^G<|`g4$Y8OP{TetC$r!D);QV=r&J+`1?8_O;0KF~$LN&duXf zx0c(Bbd^ct%^p z`E8!iPW|W*^E}1@^=N#StvP=m;v8Jy;nrMqu-0g+qigiLMtWJZqd)tATeIg-&R3w1 zbD#kqIS9CV(ms2OfWD_;^@cc2O=trA#>X~}A!8c9J$qX}=cl>&?U}$-zSqw} zKb?#XziW(vtfRi0LmNX)dnVzHWnJ9?f8xVyH19o8hHM(wPW62%pLR6 zGu4`n-$ln~s>sQX$GC3RZFOg=4o0MLFnWIiBbjFp#N#F91guxGcabwu^}%$m&{i2g z&YmlRvwQnW4e3AYWE_KfxqyKwxAp9OM$gs5J5NoA#SsrS^Jb*+x}SxGa0+uzR!eyVKwx4 zo^D19L;uaNl9zBdgc}-Ey7ACxv0@g4je)$b!&8pu*<0>oTOg}vA z?6vFd@L9w)a~rh(70wVSN8s5YzDb%Ycwre!>3?*SS8fs?JOMp`o>YOs{`bP;gY&~% z;aLQZ@*CPGG?4weuc3jH&|7`M`*iSC@=1J7OIO zm3fS>;*MmHI}*7o`NET>#o&sR@8ZXj_`*{q^N-ug_AmVMV%lqNO!TQ;AFuUGxLbk;v<=nul=1c#=TFZZo;_6+qRr8)XWyp^q6?yNGWh*g z<@SKjZnlLb7eFJyW6ioLdyYx&ZW{1Vi+69#o4xRU2Oec6?uL1zYl)_{sR1k_zUsBF89}VV<e&c-xQedhQg1hG;XGGlX|YD z%>sMhULF28us&8lrng<%EoZQ9{Gs8(|7-9-_J)EBL*T+VxFGz(c!~?G>E;E$T!X(3 zENkc2-e2~+LiBCrb#wORdgW`ZU!ol0zfC9fcJPy-)KkN+Z2v?kZPtRB9-f)t9P1-HzPWG%g zT~}=)yuv(JIzXSBXEMIrWew$Xx;kh}(&mWsW;rvelUMSWPQmq-y+=r2hCeRNUd?$^ zr!D~_x85KAePbB6?Ol$3O503NT&Jwd0tu1-|^ybG*GOB`9GX6NrngyO;c$+zoC(hqXKzAxTH$fz+<M0Z=rivx2Ny@sO!#8@)ryOaTvYJ4ux5cn74EZS z-3~e@zyat%&u(bv{hr$+gA+k6@`hw=+TIaf5uF)EE8;!I4(gWu`40NaN~0#hTe+i{ zJQMs!wrdA%kvSxLT*cXR2Xja6y5ycqc)oF=W8iC?&lIdxWyxz8ThYxG6g#{+WovM~ z+P6k)+A3w#&Y(~5mTr#<4o4UJPA`nijru~?Nb;(|xQ()A$i6_*2Is;Ta#kp9s<7{~ zpYhA>OBgF?h5F96^1(}XIUP2Z^MzoE&=7bOe^+T0eC^QQfr9KI#@SoTey0wfd`8}I zUaAUDK^IF&xHs|p694IzZwr#RXIkPGCUJk8#8sgS^>;_%e*CW5ec^uU4rzD9Im>O| z8`N@7DE*PRVfr$;VncWbZD?no6ViVUPQ8$}*B{T9LcyKJJHlc5C}~S}!h@E0T0Q99 zPTcgpn?~Mi=zF%9+WTnTpE-H3WN&vn<&TiRLK_d@8k{pX(6c6RZO{gP!BtxJf0E`A z_ERPHC_=kR#FseRaNk^e9;7`FdeLj;T=_wFRuk{VKEYYE+rt&)Oj^#p14`I$u zTs@r6YuY}^S-WOka`KMANVE26(%8TIKv~ZB$Cu~a{d-RZ|5GKGpKle?_?*d0*^|`cGdKK4Zz##Ukn{fvb3^XLsKEhl(CVp_@_yn z4{t?yeiA3&#*?_yTjC~@xSp0c9c<9*ZSQw&Y|uA3t8-^2oL5M@^K9Lo#~Ebh)I#>} zee9nu@7J}yi*)7k9^L3$tPk{=;{M%HzH&t;zfaW%2IJqgD-^#&ePCnqTh3zkz~?08 z?7zSk4scE)_3ZebEmW@PC;de&`IGXK{D%4J(vq)28(doImOZr8FSr+s4HSdVvG4pG z_Ys6OVNH0|_JLwM;da7z67C?}L0I~C0J?r4KTv!G|B<~>zC6bHleEoVnWWK48lf*zR+=}BPxBraj0)0rDZ_Aw0umB_2zJ=YecAHCqyY0&ri__7~59Vh#t z9-Qolrtc3zYrPKg-;Ni-J@NQ>E z{sDM&;ZI8N=^Mbk)8IXJhr=Bj4ql+!5Y+ zkAh}A=ruSS^WV?80Owu4oDp;0#lD5JtG4(qjWb3$JC11|YZZBCx?7VuD(lvr|1}EP zM04KETF?EP%sn4^JEM*_X!?}iH>G@JcvIbYM{OH4S=#nx=*pvOBd0^HLiv%mHH@BnnVCgqtI^CrTR2!9~Fz)U>C5c!7SgQlM+3Xh;TLlQng=I6`(XTWQ$bO~H z8Lhyt$r;x01;)t}HHizs&DvPM7MTP2UU%Q)d+O#WXB9$=;PI=2F&#B`b7sJw+}YOm zZVY>n6YfP$czvLz^vMKjRuA&TCdkc_v!Gt&ilxo2ugDe)jHMs540Cn@KI+@nEB}M_ zR&qxXG6otad-R*$YkiB0N*nZz+>J%h-2virhX&gezefq1&h4e)i%s#ed2RX4^HgDZ zSs}S^y~3Kkr9w|Z?~yb;gJGewQ!nLvziP{iJBM`r{H8aY+icLAuTq6yBmC(%DaWh) z+8+((_3nIr@j0g0QEtnJW#dPb73VQ7?-JscU>_ij`}Ti|!d3aU{9@vT*Ok7Pli#wg z34Hfoen*LQEkC(Qa11zXhNlIGW&QMUl1Jbq^LYhsdf$GWeiRDdC>8dc5l-)qq5QP% zOFCJ9aw?zxRxhDng@E$+zPNllt$h1qmha&9^ldMKTPyw?#+}X97u>MXCtrjYg`Pl1 z=9+Nx4e?m(*0JRbE$zGb)5liERVU->+H-d-M>_Np$1knBuzX?ITEA(j|5#(u+Kxi? z$TIA-GL8oC)-qgQw%h^EM`h{DEaqYdb1?*tlgvk%hjO=Y=hN_Q(1>{M@_(B`&c*nT z!S~;Z6a20|9LuB#{vNHI%f6@bLTl1;EagPg%BdfvoFUqD7x|?vLc`KBrng1Zl_-lybpQ{t$W~YtYiG0S2F&mOR8`^PH2LYOBMVy*TDZT3|s5< zDX$Xsg*Ra<>jvsNr=>3UjlGGKc_U^10p)!cU-~LGOH)`#UoB@VNA&gT56;+EDO1J` zVSHcY>JDsH`4zoNe-R#E>XH4z7jnv9J`a9a_71OG(}+F0j{r}!+jk%EBGqo8nG9<>ux1? zY1~1W;v>MmK|Noho?-49SD2?Aekk4)tt5|OEm^^Rq?8x^AHQ4@yr-?hE%nI!4hvjC zwzU7V(tgG>Zht}B9Rp$dTYO7>hI_Z-f`PF54Dy3F$GCpk&CJXDtm7j>`Y2^i?{{@y z+;8c#^gS#HJm`CVs_*AdSnu#!|KwoXyO=NW_{C>N*pe&0%Q;ne;J{%1JKPV*UFBk& z&=a9Y3ckjmpUrZnD))eg<2#}44-V#+ymp|pq)in*{YUw{@G=rUGEF}JYq!}X&0t<& zDQT{!j@y$u%(vrnB-z`Gyr}dCP%FD7j#r7?jD>Hp1D|x`Am>Vw#xTBSOG0l6uadU^ zzwtMrovVpcxLMDue8-a}Fa5KhoBG}n@f#VzHCwFXS*1+L_b4>mm6gaq&VrT;E=9zr zqD9ob(7feZo}1pd7s zFdG{Dr>~9t*@m+gWOOU6U27LY!*Y9ORmM8C{`&gRzBQJ$aNp*tf#|%c`Q58 zsP&Z0I%KbSV^F(%jUJXVNT>gwPn6V}I8AMiDjvL;^VtP!^g-@uEM~Rky$DZzoG&sL zW==F~^_)SyD#_n&cZD6a519(D!g+G^amBg0^`hZ8Ph}APGf8U^C6e;eHr7e!U%uVR z3i(fu#ry(wq~Gm|r2eYs=zkh7a-wP2EKk~Y>Cw}u!8na?xm)ew-f4?12HZoK<;Vjj zZL4vop)G63B}sWEDK8)Isa>6f!+-PJg`bX+{j#|@PTv@SPff~FZ;In8ld;Qw7(GJgCFUjeNQYq6rcTAwVL|c@9!<8X`>52PQoS*~M$g-0^2A0qqVA_B_$(de-@wB~L%YO>5{$auuczhY3#v3DFXjL`&&H1YKFN%E8 zSH%jCV{qocerInK$&t-PMY05B90Y2TifQ_c|R0B7fM1+$i*8S4=-d&w|grZIyntBcCJlS>%Kd z&Mp8e_l~9*AamSAZpTNKxCUJ0w~q{E+Qzg^l`-g>)PL$!`&++h-cL-ne5-)FBC~*f z@1nR>oIRvvR(>h+8$a4`_;-!p>9AxU!6X?d@^( z)WBWYL$y=>?5Jgp6`J+6qFb{XpJ)Aiiu+pDPe<4PDvqzPmO5I{^|r*n>M*Uhe-Wn< zT4et^z9Te$p2RU$_Ro^=<-;zo-*u&S_7D2r;^>~EnO{xnk@Qa_VS#rtug&9A-{W?q z?YTT@&y_B%$Zd+eUjuxRdp;>!WR}x%B=3-{;d4xJh&5>FGj3$T$=P#t zV-fj#Ptra(emF04&+LucQR(CRXs0%N;@_=lR20Vr$U93tQf4rBDlBuiCi!P~=>U0f zzsulvxO#nwf5;XqoRdgjf(6zOpm&0A0ew7N4|91H@Q3~v@AwMuLxI1fb!ADqIeFcV z%z~qR^QLHDH0NkE@2VD>XB^E-=ZgAV(x0Rct}XOwe9uIwoaasi_*QsdF*#sM?mi(o zU*OGZ@lKqq)v_)N4prySSNjKHNWKzI%6J4B&_|F5FQM~+|lUDOir0^JaBS)YY`&o}?LGR1ax121QYu{4q&X1)E zgB~YoYil3EJa5$R<7|k0A?w6sZr6;%7jF}w)Ao0YZXO-2 zA0i8VL_au3P5Uv6_LS|jt}m0oOvXU^A^NDKA3>qlovE4po>@VDz@6~~c{|J8o4``e zFyK?nJ@N18BeCBua@oQMtYw|2%;*L9l#8uj$E`e>Gn&x)cjAV)&mF$V`sFurw*6+_ zTj6HoDx4YC$4pqd*@OqLHett=#*HD5f&I!t6YIJHk89i`HJI!Hr*>aarFE9UADIcI;Ia^xIYfY z0Q2VNP1?}{xAyY(7#`h6_B>v5e^u8#S$juxlW`0B(8tyLHeKbrdv~x`do>BCzxR=s zv8&?T_b>2W!s+iXYOirBIDm8CzeM_WXv==$HSstfo+0?t_&r0~2S=~ylhACz$tp0E z^LGD3pDkg_qag3t0$|bnJTjWl&f3z5HxfO%0&X-%`(4}N7x2LW(l&s*&)J=ip1Q_X z@JHSs{yM+E!22V7`CY?zeIA3if&Mk%{X~|iIcnN`;5NRLaUWC;7dZDW2=63s0iC=Q z;dCAeuKc|G`QUsN*X$kE4T0Z6fs4ULnS~#-*s+B_hL-v_1H*HH4|`jC9(yhFR7P3v zdCORtM_SfXv2iDGaqkP+Cq}36{vNn03my}`o-^-uS^q}f zV_I?COFf6LZn5rud?(|2h;cW_Lq@dC@>|gkCH_;y^RCn4BAnuFr<5)C<%iGNpEqrf zao_O5obCCCuHPPRCa>wGeBo2znIGbvs`@X=wOQ?t&w;;B*>+r&MZc8He|cl*b1!Fe z@qXk&zRS0W^+-We93DVJ4059`%pO@C>In@rz(99gni<|>D#?@30hQ(E=H~^-%}aRe z)bA?c@s{5=)A#7TFNRI@T+C;su#vr*w9O);Cw{dIor!jZ%@So3min}eA!9I9W(*d@ zv`@|q^v}W}C*35jF*;E6kuQ^V0_g;|X86dOHAYRbF=~tc!_cn>aS!3hC-0LQTfl+ee6l1m zha$fnpbPCt`eECAaJdFvxjf`U&ZNzUzWVHq0`^AgP`o#q{B`Sx?_+%g26E0)xm)EM zz&IdY=;!2STdEMQr@xmPclRoAbakWaFz7l7z9^RW)aYB}T{1K@}|e}x)LXQdY}2EP^=~AYOXB!Q#B|4 zEoDyUg&XwSkCHQm6bC-;m30Jt=3DL1k>8@<^2+1fgZR)Ift`$7aOEidF}i|GLold4 zR1doP{lTg>r8Eqm%r~EMeWN`?9h1`bKTCf9Hg(eWD8awOeKhPnNf$Bht$k|c=V$7J z`Eb&QMbrV`DDOw5ev?nzQ`I(?hL3EU{YcU_!#cDj($d}vw9}71#d#t0MaE-yd_F0- z<1>dH{G(5V`YG_1`o@tru7t?G@m>8O=EeL7J`r5641C7v*O7Lae@^%};+xS8E?)i9 zRGdw8?Kt|(xlUSNg|*O+uyaa#YK(hOh6et9QV(Mx^HlaFZvRO8_8)_vYUOWg^JTqQ z9~$0<=m~ft!}xNSCbFvbUa$NJv{k|-`ZdBFJIL6`o#V)b!h3Tr$ys9a%j{RUOIy{V z%ck>IQ{35>%RhP{`@Zk1{9}B7Y)+@1#Ts-OWnDI(a}3If^ToPu4)FUiIUC@wv#-oP zQFtq*cD@E#NcfM^)pwR2;jPvqedzmSOdi>5@`vCPq^?KcdrP+(E%^jSa@NJ13!{0! zg}XeFnYDGVd^>%Ru=J-L{Cg>VX>ISZ`gI_`zF=lo%fcVtN&j~|qw;r2|B>evS~Ck; zW5#1zvjlj4ntq-`dv3r9y_p3~Vofa0`hjh0+^q7mSXRO~5y#y`+>NX|pA|>=yf>NBc|RD;{{iks!Z&gkF8AT*|KGMGYj)+m zRv%yK%j6#|e$=@OjYWJ@FZ|)7`=R2!YvfKs@+# zcwZ4QH-0-gqhxQU0a)qkUV)&&R`|6sb%lC(}{@Bka^N=&f3UkW-N&GwA z|5pY_wE3S&d3+PxtPC#KdTH5Hv*Wei{O5R`oMpI6XYQxdyrZ?O(Xu?hCM@sXke#>5RcNnqOOZzupWeQRsoPajs%JJIlqwjNi`4MHZuVj8& zPtqC2y1qGz+G3pmN;TR~fxY8Q*r4O=)G>ov8CNA`ucYjyl=G0Z@?+PSo6eL;1tDc|-+U#!6xro zB){xIMZaE?vuL4MqHrzqRL&jRhtB&pv{-roh?vU$AT(l*Q6Z~r?acWx} zC+l`F7Rz6%SxH_gv_)=S-dc$K|B1-o%ex7YzgKow_yT8#vghAi&grE|n@xGN_(BM7 zmSQ}Ws=f$~S$&QwT*|tjwi3RWc`jk_Smxpii5pRc6~tKyUp4hz=3=_$ifk}Y@hr4H z+D!RdB4oUjZyq#SWW83yD?YYe(nJn!LgSUSOifc1I^Rj&H9_PbT8bQ;K@Np&xB3Fa2=m5S^^;v@xPxsuLLSwoLlD zO6o&4Z)DC2ZNJImXX;z!>KoQET&d5&RQV!TATW(cH&q{NGde7!PHDT8CvBJV%r}sW zqumPq@zM|TzvcI^mb}MnpR{c?vhM~M$#|~*4OLi+zjDEd?(DQhwbK;a4@G&yUSw3p zsdJ6)pkIKHt?H8{EBr(M<$9EMMduS<_RG4xN9l+)rG4L%F+Z}v==Lv1TE^#tOQTSD zlU3BwF0f<`m9W4rG7Ce=EByb;tBsa;+pEfV087VeuOSD z6R&Thto2P?z@Dd7Hn$x-kn{TX1!E=iPw^R%=;1l=`A>z?mX*`$Q?x;i!23ww1&82= z1c!t#GQd{&6vqp6nl=mnL>zuZ|3tO zE>q`BeRpL(sY0Ox{hhpt>1@l36F5km!8feG2Z6�*73iDpYX}4*Nt-SE*G=9|fLL z|MM4i>0D#T%dsaOkp7{2b)erA_smiG0dPq8zvuJ&9RHU?C+p#K=wm%vy4HTB^`&hb zrGL4eD;=LK{A@wm-BZ>B@PRqbL-ufPKN?+Kl6v}m_zGOEyg`@GF{QG)CVY_m5xDt0 z9BA3+u7tIE0AI#o4{0_Xgz))=iuPSMY!TjC4smHUxb zF3^Teqt}%B2j~}ge=Bm`&)cg@{k;Om`@-dQ8vUTo-iXoU(o};d$iuX5i`O$vL6k1dN|Q+4`IM ze_5ln(J!-JJRe4WKj(;>+IUL^+&6(Q{nBQB%Q%Qmij^kb*A%$h5IE;JlkDG5zZrvm z;)E9D_Hsu<|8hH@iJ8>2|^gB@bn& zLr<34ug0`{9 z9#ts!bd)S~UE1#YMY-*rz2U*lJNK7N)eTwO!NebF^!d3hQgF!|4a1 zClPogbXDqfWnLJ+L25uNCJXNaYj4yLRU{QVgcFK>} zhIZ<4Fkp`)Fj&R!fWFI{s+ZD#(`MW3zJa5{z~8sf^*P$`GW3bIOMhHn9**CrN!x`l zd;MHD$32aT)j#VRL3RIA!3=A6vk0=B@ZLe;>P06(o)O4o#AH z^~Ize$(s$Cv$7A~tj;KHf=_qnJkZnu_;BIHW$n(*Gx-7bo!BdL`_Db36FxruwugPH ze3N}@1WpdHH?80r#QVfma5eF7#+PsGeQUS|&L>R;SHr32X(Mw?+N{tuC+%KC`&J{H zWw31^?U#8yoo|;p6{%j}<(K8oQgAdKAAz&s?j^^VT6EP5JRN=CN%}X(>7(>LiqP^j zjGmXYESD$yFN46#41srSz2PUce|f{PTl6ZhfBCglH+}VZaNzq9{mkrN9s!P5?GM%r z_(=9$9H|)2@zsxM|1x^Fis||^Nc^PsFI8gaQq~hzVM>pEd$X+J#B7fJG(NL`$-e7V zX#djiwn@fwCL2AO{Y!Kcb7vU*oZ7#<|aLTisyQe*}qh+_6?)|9-lw_ zr1mfKXPubM%P6sfn|p=YxwPoV6k2jTJC};1uOrgEitJq4-ErGn@gQ9TTkTxhJ7e5P zzh!nVGdq{vXJGGNr?=1g?qx4 z)aMT(-##$2olAv%OPBv0Q)P;MONldllm4Y;PPc#Q>fe~;Pi$YNX`N1{{~&fQ?Yhj) zWoG9xvvXPDZeH$6YvT9BbV2M~Mv2YK6SZ?`dyceoX|a15a5pyH&ZXGDtU}+a$T6IV zolA3a+@=$?b7`?_C~r!KsN-06E-m&6r`x$Sb6>ihOZC5F8%2tDE2#~m>2@xoznx~s zsKw5uYLD$)Mn8=0T$)>Qj(*Eq+Ua&K&69CCt#&Te-w-!}oy}ir$v4f;W%O61L0@u{ z@o2un?Od9Fir?haPUn6P`4B()$?RN;eM`6g{(UTm-;n!7d1v~b=w-2UX|QkU%KvU$ zeuZ+~yH)XB`;WA{X}*=D2mfT9ZY1e_?ldoZkNvr@b7}rKwcW?~y^MA)&0l18F8$Mh zDY8O#^2F_2MqkS8T>iA|T-qHmu19YBY-Z=OBjR0${fX^ds$c!t+qpEGe>Qe5&DQw6zvw}k zZs*cYvw`{3v~wBV6t~0vTD;aD&(39pK0?uXa@Y>~(>Aof_JOi}$BXmJJL8Jl9nNIu z(*Ck~S?yd#%_HqxMv2|ae=j?i!XM4_S33*2(S`7`nf=Qb+1||TUm{P+{_j}!HB&ox znf*)jma*of@Dg1W(_vF(o;h73*bwr0liO;$Q|$F+_AfL0mnyS=`HHiDX)cZL0d~M! zzY^?Unm4`J{-rf>8!N2mnf*(2R`6b`WGB#bGJ)QLSC;)tb82S)a=QIX_05;p{-x?T zzWvKc$Feaq*}qg_X8$s?f0^08%Wo&(-2h_bS&+K2mbep4@{mab$WoG{p z-36joB(r}xBe$MKW)R3A@bd$K%>HE}Yg&kHE{VKpYLhFof0^086gyl|tG!9F4Z%Ap zp#UO3h{mab$<&=$S=t^e)GP8e~ z+P}!`UuO0%W4oT2{Y%kVD{uC&JL2qQ|3|QYse0ml$YGn77aGm(p$6g-$mtse=)&6Bfxi6>v%jm8j-~Oe#JF|Z| zll@C|&(D|rOI6G4UuO0%e>(Or?W|Z%J^Gb+k0AQ@Gy9h|vww-66N}62UuO0%u{W35 zzkCV%-YjVhftlp@Gy9h|vww*Vsm%W6lg^fx$?RWd_AkYbTW0?|Z*& zmDB7sX7(>L`HG(3C;fhnL*$kOE1`PECZOwv-2qV zkJP*29vr6k^LTK%rT@I8=e?o-4I5wgh6~Rdy86PU*Ic`FX$zpPd(S)1 zd*5{%ZhS{eTx)REO*i%oY}(SZ^z}VU`!9O^8!vj@(w+|dH&V*7>DEBHz6U)oz@-M*>)uETy}7c<&&FW%N6l z{mT*iTq#huqC@kNM3?3zo?fhilb8H_+rMmo`o!#Cns3K*J+ptQek%4a_nwj1znnkf zov1BL>&5dnPo6aYE7dNh+7rwE9nUVN{gY|wUPX2>)vmbh$Fqy6?#S$7&MgiW=FaKx z=6YV?qu7Kz$?OWd_wM%I!u!VVXt&qBXSa7UcHz2Bqu<*78@juTJRPgO z#|KCC+z!IX_T95M^5|)x)2Bz4@l>AcWbo-Zw%iNIEpV+{3^{-Fr$3A9j{r{2dVyY`MyO^0>%*-xk zt6fZ$*uoUMm}Y)VBTm#Vros-U=H6ry-R?DbLa~22lU+U!yRG40o5n?}d7i)o&jX7{MYE~YKTb}`KlV!N2pyIbsA?s>Wts@uJ= z5_uZA^5|=EIjwdv?OzjzT}=C?mVDFfVw%4s&8x&NX7mrSj*^$lE@p(CRA(<5`pS@ko=%$~IUCd~j?aN2@pmX}{5zqfZPpIB=q|MBqrd>>PV_cWI zK3?mOXBX29Oydu+i>a=sjJLlyzdIv1id{_g)|b~Vrb+Bz`j>}Vrm> z+0$o@ctiPKeP&zPI}5i6cQ&pra3^g*+MHhw(sa|yY_%Kd%A3E;8;YJQO}8PbW?@4G zJCe;GZTE6-E(iW4BVJ?no3(E~8~O`Iyvks|*4)7a=DT6g#d`*KXQEVZ+lbePTYy`L zJA?L0J=fCa2D*iOdvzH6|Lna9oLt3yE?V7vy3VQ7N3&^V6PnS2kOWA=CXVA=YDOb< zw-`W@!QtiQhLHe+StXe`!pSu?BcbV*F$g)3d!4*^Bo<>6gK=(rbK|^ANy2ouFb0gV zlf1;1u;X}Vu@gIvZN2YbbUWLRf601m9-aQnE5p@`k8k~#`Xs0SvRVJ7`tGZ%|B^UEe9Su?m3zbR z3~CRH!y&A%SAY3}PcBeMj z)ndCj4R#_}FWB$?H+zPOy!mQ(I0UY`A-Uf0ZKst8Uce(m?DOYgz0-w#*t(@+sOy~~ zziy7GbS)B(cggI5JvyC#cN@$nipP7bdFb5?=1@GoAvROId$G=m<2kTgc~1YO(|_so zU!qSt{g*UMj{7$rf5x~Tk7#MXTT@Q|Wrp-FIsKQJ^peQwznt;|#n0QQ{19spL0lxH zlS|*1Tm3GXz3}8rdeg~H|0V9AXO{v8r~guMY9~8ZYzGY3s%s&%rKhg;q zbTRLYcwNaLWp2GFuNVj~+?P%-hQGxP{uVX(Q{j3s1svR;{-DZfjL)C`U2WE#XXd2; zK#qA=<0&FN`JY%vQ~Q*c=T@_MVPm?ak20^1T^FPLF|EyMZeZ*-)t^%{wnWje;yD?Y z^|D*WEi0u*>usn1^4KwV`Y)aSOQ-+R>AyVUQr$T?1RMfyDFmGU%lMm8r~i`cf5}GE zXJ-Qc)D^gYeh>G1oc>Fv{}SJI;g7zFqGxDouds5JxFGH`KJHVM=A#-o%sXOo+=5G83i?gAe9_DIK)|?x$FWTQu*J{O! zp4CHJYd=xs=W3sH7}IaSmBT~a$M;CJ_LD^gI%-K5(1_o)_>B~8*k89s)YgW=|1Em& zM_Wc-x~>*MXT)pm(?n$c3Q-b{{gL)AA_#FZFDv|FZfnjKPCaRB?~ijN_XiH{;n`GWUH7)E>c*HZtb`hSkB|C01p zmY>2mmRL^@;df?pf8wG6?srL%mzRe@kKin_=LvpKLC9S4zDAInk9EB-1(!&pQU9eR zotrl*UkCC1$E1vMcUZyi)SBCPD(}bmjf8)x7u(-LRw11se23@ZHxYsNRcV>gFY4T;HtB(K+!wzm#YQH5f1^&*zLnLA z9J7aDHNn4t{l-e{JF*{yJ-%h4Z?v*&asGwxlgiJ5v(flP8Q_=PZ^IsDQ>XHmv3^hH z3X#HlH^QV|keS=3s;u6O{H?*cQa647kNXQw|E167gn}`r|I+Edq?MZcJ5~h7`+nc) zzjXR9wbOqYPT7CZ>A!sB6CtfP&uh4Muo3q&X#K(Zu=c?^i_y9S>mi2oS6UZItcz%! zV%9EgGSjRRZ0Sy&v+YZI8fzY-3##oP+1 z$MM?o>F9;CJ4C8dX>N5x<=qrqCRO^IWC-?f6ae z1J*4?JmE0z%`KNB^GMJsvtc(&_b##X0nH0EKcp}(V1~-5{oP?U#r$Owd-SC;yR4t3 zx8u(L5bXT@^UQu*uYVQFguGLEOj$nrk&&{rA@2|4EaPFhA>5RM#P=x=LoUOaHT$w3 z?aX1G#BWq6=9Ve28qbp~@KxP_IzJJjr+kagq1pIp=LDQ}JWtxWd!d#q(m zq`TwgB zpWFC{$U7butry)mn^AaZ?oOR7)7|)87y8Pw3UV*`X>i;7ht`e3O`}bAgM&6tJhZU) zVVB18wOf{7 zy8Z+2Uw-Lz*Zskn8{T*Q=nN$;qiyRZ6TWU7`}QW#fB8=vv%fPD4$bA92p6aSa%@vL z9&J)`0B7$wV`prN#5q0__InWdt4HWe-e(?u3t*DHs9C@sxBTxDl|%i~{$4YYKXTV= zZ?f}2>ZT~@?B+_?->hl=pmc+0Brgok5w*Q@Lit^remSLma1M#mtxH7#c`w`o5}&!C2|=BM57;2(;ukU=GwTrlKHXUIFu(e4EWT?axbR;X5llLDbDl zEvXs_MUiFlWvBWfP`G+U^A1sjT>(6jWymnedn_r=)m{CfMt=5n2{D)QJx7SFjbj_d zfpSoJ%cJbxA8(|VNhm>+wwpfYv4UBy?PIR??So5Ox+x!Ol1zvMRm8SV=CW($s4ft zwJ*SZOKm}?QB4txa%eLO?>dL~Hnbo3zm@#&TPTVG`K5Hhtz5!W#Y67f$$i7yL>caM zZc`S@@7pYMEM(CaJFrGOD+P)5-LGzrBCNLplq~?S6@@kRv+f*Gj4?9xfp$OnfZH-lIyHw!WEy6wUe13x(;QBH6PiNBSsUL-p zH*kSc`nH~c#Z;;j)H&pisn|~dm!xa~%2rBCpY-`q8H$L5+>*9ap051^(zA zx_3BaC&&E=ah2dkeW&n4tQ-H<_MIeu0oq~-dxKJs{YHh&vf+rQfe{}V{>U$3834-y zzH=$Cxg+&G68E4K#g8gcj{B?Wi{L#?`Y-jh0DX<(qPzyE2YMgRzQDT1#NQZBPpRkY z4vGuu1WRpuNzBzIbD_x`U~NrtCjLuJ?uBOeCUdpP94sFlU!lodYBE=0E}ez3Vk^ck zU`G31!deY)i4LQ^RWTN_C@$yMBo9zWdY5gJs@2LMK;3S`n7tiOkTU(LM0lXCOQ>u8 zXSS}XE=+x(yfhXD7+*?hq>tY_3vJX-aaSRhq80Y?p0Eg6L_aBZ%n(9e78cN_$e)Po zuSnx5{D^VvDJ<>jN+^R~(ohE4w`@N`-VwLW6UG4Kh3Y0LOBG{2yS+Z<7rN4-EZ3WP zhJFJVT|H(FXe?*a#;WrW7psp?Nu0HL3UeRsV~{)2O4@5MpZqIcrST|4zXb*XFbKfy zNB&0QC3njL*RW_%&`DPzPuSz_Chc0iz(aQY#jf zLpx3;>6R#5Jbsuy`R;QB`xeGR*wYybwITU87%K5+;zxY)kK-{b&OgnCHRMg8{*(Nh z`7wvM;U}3di!jqXQznUdASrL+UW@%xc}@5T{x&ZaMaUBQSGdndY2=hob35h9l%pXZ zWwe#XJd_cZ+M8)>Q_u$SG`iP}JNm*#-0zv9xP&Z1lK&d~ig@0jbWEPq`mhXpeI1Kx z@2#V*`4B0tD?&<@=2G={GMmn!Dk>bW+&!5sazI4HB#RvVuD z1QD>6d%_~*NO;t58F3eZIn_t)4kc=o7S;n|uvZi*{Vr+N0>Qd&%=H*QufnOvn{aK+e;N4{ZQZ<#v0k)c%t2f=e&3HSu56->4JxJF+P__&KclA z3)YvY8;YaYak3Ec`jE`EI8KU(;w|jEL|odlMTi+GZvD?T{tLjhjE6YCOG8Rj@dWdb z{|0;0R#QE^q_mKHOBAHiJea$Rm#D0BISvA=6e1 zWZxaTldMQi>rLaA4e%<}8Tsiz{gHgBI~#auaFBb!sJv*5vm@?^Cs@f%o`WnewPTEJ zL0LLhi?WdgQ8RKC){)}cm%@BNte%SX*zzqRcsFo8 z8Eb%3@Z|9n@tlWeHl9=Q6!5IZ(}(c~b#8D#otNS|H|>DR20MC}=f&+D-$YS;()g&) zv2zo(hopbiINF1}cVxaEX{T8KmDy#+KDP$<>C!%z*ZO7+n3J&?dKPINn5uE z(yjRIMU)9`C19U`4mX>pD)dV}F14R~ba>=Un9jE&JoMd|JSFy*kv^SIhUte)zMuH4 z%srmjZQ7|k!TO2zvGlEnff@YX2EPpFvgbp#t^_V7-96yg1|GAY%}&nm)ci z^+%)Yd^LVgZ9%<1@w5_CFkVpJ$!?0?9e!!*e-RPBVQZcGA#oe-`f040ap%vQg0=fc zzAV#y`&A}~^XBF_jwO5_(hBv#k-BI>`mK1T;2gXSd7!<05$4iXDP$0r3GY*;%@J)9 zYYm(_TlX~>dt&#y*9etO?E8fV+Z_3+-hH`f8Sr>3p7T*I^|PC!9cCY)u<5{f>OnUj z_RB#(+8?k8TDy4_ItzlqcGG?eXnVoIBfE(##%k=jMY8AKdoU+)eolSb>r4eVDC~89 z&dmOM!O7kHv{SnI!hAPBy@>G`<9bma3KyN%&EFd^?-O{wgXeU?ysPnao}A)cr=na6NXi?F#AanU?WaTxp0 zs$7-kTZTG={P+t40^^5q7npYn2p3?E{YJC>W(wC3PaHq_`+7Xjl`5BrkLS0DYF7EB zcwb(K_vJyuzI+b*8@sM+C`UmZ3?`JlSWes-K*zWQMyFl2mS2WlaV5bk*cHh_z z41WFu_;sjkC>1XQx7CQV0KJ*CKmHWP@K0giyBcK&&RL->wx0wJWVZnAyL5W5SkN;^ zl!^uM$?_UgCc=JPeE$9BIzHp1xnli9!i; z&_XG847Q1|EQS8t@yoBUK00dq!P!w`+gZ?qa-lp6aK=_bnW#LJKD8B+M`|DAm05qg zq0CL`PZi1aoC?ilErhl@v{VL*PUn=v0rg!H$MP>;!KQ_i9d2De`sUl`4d>TV}0TmHuMUC z^SdNmuwU}Nb+&HInJhR5=uEcSF?>vCvPX{RGvmfHlKwtv&w`O}a~3R*G2JoYCrEE5 z_6!{3cNf;XGcgy=#~g+Ao!GEZ1oL4|<;`BEMt(XjGVAAJM<7JU@8dj@?D|EKWY>GJ zmL&PR#@@zR5JAf4K`zg0o-%tU!O-W^h#z|;(N(~MbvK?M2Y;>bHwAHQfE(60Vgu}3 zv6jQwTgGGNn7Nq88qHbkK@ex)L;9T4I8Aeh@f*M{uy!*3-q?Bn{7 zw%3Dw49?`@{a6k0(^>E8m-=yT?wPefh&-*{2Xn^b%<}@mM`S%-gXUd+fanXF+0JUx2wl{vhc*r!XJkLzp28kX6VMWMKj9v3CnjgFR#cvIJRztU^{H zgK2PI2zST=WC^kaS%s`Z2GikwI@}=(kR`|xWEHXs8O(tDBDg~qAWM)X$SPzNGMEYX z#c+o#K$aj&kkt_GkaTVnEP*>@0kQ;Hf~-PT$xL{i0e>`~Llz)QkR`|}B;gdC33v39 z0%QTQ1X+cwl6?!@ft%UGNQ8sA07-j>66DBlP5trsGG}t*i^&(xK1vu5t9Ty5-az&- zbFQ!FVjZbjy-hsH0$OuYTRw0YZ7t3GU>o|;ljMi7;7Q2?eM4AYE_2eH&to5yjN9ll zW%QXaIm2jO$;&;s50seE2dU4Lmk;DbW|j4;uMbVU=1doR1^nrGcKxePvhs!$*5uNz zcQy7_OOZbopARQ#FG2Vv?7r{}%x8;#uJ{tjYtQQr7pv#P@1H2W#Y*uXgxzK>djsY; z^;>q1Ta0<_0qp5hnCmh$-*wpej_kjG?(XoKUkr!xu$?!Pv`m=PdXrc6Guww6{WIV~ z<#-4fvbVEnBjjQnoILP9_ldj==QV%4+xq|JoZP1oj>4XWM=oN~8A#&{vhaxxa!UN>NWbL;Qeh0j+)NVZE#`Moj`4g;Ru#aDg^Fx{^m!a)bd)pLsie;$NrC1vVF)la!WKb+a*iCv~Nc#7orUoFD}Hp=Q;eVWl;me&93!lgJkoqOGH+w85;V=% zHMmc-21w$v@w)#G0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`;1F;K zI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL( zfJ49`;1F;KI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^r zZ4tO~+4A*AQGdxM((_2+kD9|bf&NRjNq%%99Gc5H5iU;u!P!r|uw_)uMi&^%NU-0;j(Tmvwepd*JLq2Il$UpkGTFy^F$L^KalnGFn)G50&#`(j=e%ve z=*1*SPXX8$CaD**2!7e|^kUYK<|w_GqzlsnCok#6gvP&Sy_iDSawK{%i!hTuoT8}f z!Mt_;USGW<72P_2U_=jQ)l*~iV2T)%M6XbQI0W=y28i<^skr`zZFfcwCf96DIyQKC%p8dU$y|lGbRotD(t`=i5@D!=)e@Muty&`nhs3zJDv_q3aeUT9hi$7@{h4x|M@ui zM*5{R(j|#}Bx9l(w@Lryj{4YsO!_Z-5!ZP7FME~Me@X7i9D#Nktb`e59#7|GiN+%6 zYa;*D&q!ZHH6EWz$vhNdoF(3W_@nuq{L*-1bY8B)JYdG94Pj|1>Rhf5NoNA-yd+%- zBo*nZY}R>+aAR~{{s=lRVV~%{RR7y@UYqz458D!tPjOyJ7i1ZEYu0&LgB|5@WG>9n zoB}bfKyTNIXbYmwdw(sd~!q?3fFdWGAObX}Iw&II(Jklt&fFRV$| zrETlu>$()}s0-+&OmtmRIcmr!IQv@!-U&bR*Qo0fYlol(I(ksIN7Hdh;VHhO>9}mv zbygs3sqekUIxS1TY3ry8N$Z_votD8-bXk&KEzyDpx-5%E7Gj;2s|1as%{nY=#?J>t zxM1Kl(P62I@wnTd!&1F{tPaaE`onlSEQOEtX_F31wb63_8~q5x`+vh|-v5boSQZiI zvFNZYk$?30DoOO=Aiy{S9hL=>c+fwL4$CUut9U2>q{EW@livV3EEB(^!;<{%fDTK2 znjIg@X*Qz6@<7$aZ*aaL3cA!_xMnBkQmfm?zD+Y9!X- zkS*(>!}5J76WT!_?+f+GHcwU3VcD;tOslT9a>OljWWAN7E2T(bj- zIb!qHICdXNPbKO3D0t|j=b%mEo#w^y^iZOY`vuJD9dGF!K>~Q_}os z=2l43O-XZ$@sD|<0G*RG_ma-ZQTEVHNpX`u6HkL~%Gs1AodB1rv>xLl>8Zh-|C;EeRA02Zg{Tb> zZlsIxsJJCM665^6nz|U}PpvLSgGEz1gu~0x#i;&|Egy^JM7kK&*Xp_$)k8}u%pETip< z=UR;(=GD;OT7z2|_M}fbaSvb?%UQ05G)O=2>OC?|x_`pO+Lt&(`r;z215$Rqqo-Ii zt;fs9k|)G<#5}?6hBoW1c_?FIpTtvI4$ROtn=un{*dpfQ#J$#l>3C^O$}iHIjK3s*N7AKPn!o#) z&WVp4&%@)!lcZmrk9K$(+F?hJ5JvWj;^|~wC2FTYF2|bO$O}YqHrd}O%EsRZgy2}$ z;k~>|rbp@6H2$P0p9=rb#aJ`4PY9Ad(8+4#C4%;*q>HmQi~K=XDf++;=vgb;_L>Qy zgR+2gX>kI%|M58PR~h$4U7ls+iFA3={vpxjSu=M1R;MR)c@}+&?{|fG-}jV@2@laD)Ho~5Oj8)y%UvIWaA7Xim=HhF*jba_(yFz4T~F3%FJ zEpVQYVEcON@-#X;>30mAxs)L3tfmTCg$(e!LqPj4iPc6bctYqMa3B4#*#5iOeez9@oLmi3U_1<=la%J~+8s(z+5+cAr9qV`WTbyS=D|MwqcEB(M|2~K3G|E> zv33p7zMY;?r)Tta)iX-{oAiuAma!ihrDybVoUb(M8NG2FJ)>LRVtPjVF&2`ZQIfHq zQJOQ0SVNBJ86}(=^^6iuje15CoEr6vCOEx?^o%yHC7hm7^DBb;=MZoRI0PI54grUN zL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`;1F;K zI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL( zfJ49`;1F;KI0PI54grUNL%<>65O4@M1SW;Rm0Pa8^t!7zUUB7_8{T*QI3bMNIQEGZ z!Y8le%bxMAj~CmOy%(>QnM5|&lOKGHbpY&>zAyq2v!pTtBOGKSijN) zkwv=5Z-xG$Xm62&N z9%ATJBtHBAVT~Rm$m-!oIO)Nd2S4n`^>o$Gtd0VGsg0kwpi5hA9?BQ*&wClIFZ>u zHn_zY`)q@8t3a<*r5o76pFlqJESnF)j^Ul^U4PwTSOjLIkB{uguj+wc)R$=^;GU=U zP<*OCCqo;K{K+pPZL~pZPbIiho69rJ{d5a&d_QpR=XePF>eg@O0&qC%FV*v0Nu|Wl zav3V<(4aUAzw)P0_+m$|$56jT#H$}4$Nx_n{AXhS|8D)0o)`63(DgPa;_MuoU&@b! z4lC*twoGS+1#rxg?mRLF-kG64c)J(e2z@bRPM;B~jWI_1ZThC1YH==U%f9|p=r6r5 z%>Twcq5s+IJpKLOiTs{xJ+^dBhukFY9)o$PAJq`ZhN8SxH`VwL7 zPr+CQorOh&A7cH`SppqlY2*XCM*`qhrL>`wBS1d%$Lrzp6b@qSV*fCLm%a&1~ZfbEoi4N2g{0NjqKp!3keA92)jrI7b&Z@H0mI40cL5oF@ z(*7#+3%SYqrT(#Fit-;t{QiInv*@2YT408q->t%xY=Ezn1AIp-bm4VhB5pw*4ffa7 z!&4m>F`rd`ZtF!|1GjiBp|7s{D=wEFl}%j~mkqiO2)iuOLR;{9Aw81qJ)$>-_wF`y zvEk5L2D{E)@#q-4g6Ks*9__DBWS^ecg;9`N5(QNM9@Bm=9``b6N);bMgfRld<9^O66nYk=GN@#!f){dJN&RNGAzs=qeFT*?LA!9$VHHSLmy#ukiduxtk zz0`Y0Y));>pZ6RF*5H>!Vl&+*1EkTEHE?GB&78tMGAmG^|c$G-mo3H`=4nZHA-zhkofuv@NfYx^Y zG{KGR5ZuqgJXP>ue~|}WZNlFSZ5h*HFQF%l?0OjNG}e$h^4kTUf_?S*??*jg{=N-q zf8-gN>D#Z65O4@M1RMem0f&G?z#-re za0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`;1F;KycH18KgBot^D_8;LB_?g-}byd zWutEyDBTGpzKii@uQ=j&{%v0_@-<$kX!BBH#xq6!)oiD@E1ME`O_yHlQ$^m|$wV){ zmwJ@Gm+Gv4FV&{|!;A54#lq!+u*+QPBkX%&W5lQu62GO zrm-XE?~Tn{blm1`=i6mY9lAMc1Da^j2si{B0uBL(z^@+y zBfJlnUiSyr-uS*TEEtC8!McqLPBSmW7*9Q8Y>q1n;=g!c=Yz{8!lAjG6XD|cFOI8f zo-i}b{1@!snLQhb`7fCN^7t?0B>69tcau$TqI0k&_g9tw;%8K5H7WiJ9dlXGy|Yi9 ztGN6R7F9y#RUUcps9YHGz4mNT$2=BvkM`wqVW{Wp_fQiq4B2nvr~Cb-1}+T!gZll| zgg+qR!eHMY#|>N<>bv#$Ukxq{H4dLe!i6y&rvzHZ;lg`vLM;D)=y1>DzrHMlU?iix=}45tO|YMOi5Cf&(#VaV~g zEsny4A*=N=j&Ns8z=gp+XYWR<1}+SJj9eIOlWo^h+w@I2C&7iGVlE6d0T+fo3Ks@j zJemuG{SEQ}tf}wI|5eYALOGK=;{M~fBltzZ6D|v(aEISY0FJ+`n`33Bb*rTiOY70ZJ&-4E_a+5N94pf^Ht=; zSkW0S*fyM#(@?iDH^u_|hWu*tW9UD59r-cjy_4d{Fnd9iSa^j2si{B0uBL(fJ49` z;1F;KI0PI54grUNL%<>65O4@M1RMem0f&G?z#-rea0oaAj&B4U|Aphfc;(z2j{l;O zJA$|?b~^qGo^WS4{)^*#4sf}12si{B0uBL(fJ49`;1KxrK;X({%QswV$Q;H{Ul;(4 z(@~(H@JDfG>`lOb!S6ls@riI~F6TtJIR1;HwuS!g=w{vFVI(UK|?VZG`h; z9Bzv|abA3VY`A0MylCLLPz~G`x`Eq*HN4BOHKeyE=C#n5g%#YNSI;)My^5R{s%H|M z7f&GVm&18+pq}Ru4vV94UR1{MKLO{3e8}E?W(}Md@)$WU^mVpf%SUYbljXc%G3SMx zfb&8gh4Vr!YT~>go{NO@;&b)oHsxdQTn0$#7k0;O_6W4`o;<}JcToq0hhUC5(w zUFe(ayxhojAwL>(D4%Hii-?q8-l>EDW<|Ugw>@a|p6eYJ&ql5b9d3z&mz3uL*Py*e zc%2as^l(@JS33Jo+)19LI7@Ab_{oZU^KkEZq2gKG-}Ui?m_OK{Zao$riSU>H6k7Zg z)7@Te@77%H4w?2k`?%K)PIRPA@l_7{Q-TE%SMeC5B3mxXXMlVaz*R!&%NK5re3a3{ zyUF9*6z|15zXW+jT%+>&NAxAoCD->@@xq^T^# zcR^**|9W#IfUEwmF&EIcY@JbE)#ADm9jGh#5h#Ob!xKcD>QCNK&wDf91p|jUVGyLW zzl!FgYpq|J*Iy3bg}SO9zM1dBa9qS|2KL^%zl86Ct+8d3>uei+v+`YhVI>ofPVW(4 z+c+Q|ODR8_RzB~ZB|Oy4iCM)@^c8<>Rh!6m2O^ti!kgJ6{z(srRq%I9gWpr(_f+`h z1?zWZ0Xhg~^@u}lgMuxJ0&2I9=F#rYi1?!`AkT{U6=>i80v!c1pf+#Y{ftEsCr*j! ztOb3rk3YKqdDEZCuF-rF{GAND6Px_afqf_JPi?ZFHl2B2xk%wPLQ7b{LRtj zZOYekjxF8hd^DS1R=(z~LcXpt`O**DeEEy|cyBlJR;8Ffw0AJqyFPwjhWAbJ`@q&5 z>Wude#OCg;IgUA`_m0?{+L}W>@!s9B8S!i<^TSE_!Q5kH-kXFU%<&A&Pbc9AbF0XF zC<#B1+YYnhTcXFver;^OejrEvk!80;+bKVtvHd2M>s=PVKdo|)p$%y0w&3KaJ@F%R z+i4u5a(2tyD!kKp&&jTXdGgidx7a@?R57nb!fDZqHlRNCI`UEIdnUz4F^Y#mTK3W8tBw4zTnQxhPib39Be)uv~d1wLT2aC~`lu z6_4f=E;vK*p+%UJI|XMmM8IZ>pyDatpC-7G9fJE=n5Tl1ZGVvmU2VeOtTO&|*vsA4 zu7|-+r;+Q(Zx?(@waCwZzw)MFuDuOuf8-gN>D#Z65O4@M z1RMem0f&G?z#-rea0oaA90Cpjhk!%CA>a^j2si{B0uBL(fJ49`Fd6~Jf8qEq9RG#J z_jZ!C>HhFyeDCutp4R!ExM+Ss?3^aEPvdFkx0rg0;L}eM{NgoQ?3%{BW_QPbAsqk3 z=%Ln`90Cpjhk!%CA>a^j2si{B0&ge+b>4?duls{*Z+u@f3x?r&uukLVvzZrSjHjM4 zHpi94%H9iC93Hsq!ijKbF6TtJIR1;{s+uRvOf&xld(qxuO!zNU`sMLo$Vu~G+=TN7 z`m^T{la;S3|HY4~%xY5n7ZQGxyV;*QS8@Fl7F9yr|9<4bqjF)$_u9LK@_8Hnm2hD& z;MM0W`kDHB(8PtozTDvUDso}4 z6%%t|NaD0WTQD3ExDQSD!}CmYKi$F`-w&MoIUd5ky7im6AV9l)te)q|aAD~E9->=n1$m^ijAl*y7P#80xPq*3|FxXY2W4 z@jKc3kK?Z47X^2m7!z<}5T`{vhE0kSgSadb|7hp>V=&|Hu)%za_Va2_SVY?&V*Ozm zvWolY0qzV39V%N*gD0Q^d<5X;Fq{@~xIBf!Jx>Y~Wa|Ed4EQ799~a;KQJfa=KZ?_W z%)1)$(E@WLrv;fCIW5S1dqX+Md|N~KR+v9hH|NQGYu*14nZZdR*zQowiMR&0113() zT(*y-Sro8cljOwMZsYy65kWTA}7Wo7F9FMqj`|CJ>j;sEWNT_dMm-9Q3WqYX+Wm4>r^Jc34BATl(%g?OK*qU zV~~wz!>6*MGhDE3ILF#h=P@_N0?eh2{22OwypH@B^4>}DW0<`g@+)WBvBs+vxu>r; zTtv-08Em@s6RC%cySER1UsT>U0q%uc?cCYa^j2si{B0uBL(fJ49`;1F;KI0PI54grUNL%<>65O4@E$A3}hJD4Wl z8z!6w&3p#!6Y(9~GLXxH51}y}@gj7bEch+!lz8PF6M>kG>N$3tU-G6qX!^ZJnG`8KHaofEUZI{}0>-@;@fi(JQL)+eY zr^->=YqW0;OLZW>H?|JgcgNO&865O4@M1RMemf!79s_g}Z{(yNxA zb9OWDMUoo1CGX=&gdfkkZnwPtdOW@n|Ha>|c*orn;m};piEw${`7f3-_7^|?tKTbL zcJ{K%uUIxgr5ukn@y6sSMfZAeCXixmie%E)=Z)sMFn4K@HTCsJxSol-L0$&_B~y2g z_Lt;d{VLwiCKeM(Z%cFq?!MUjEXV=$CHt(8t54k&%}2fx`(~-q9~|Xw{VGx^5Djq*P~!pWV=A*RDEb$58`bh-n*IHY)L>Muh9J={go!`*&U zR3@3eDe{APq58ayvwCe!qrpUpCAGc90Lxi-Mpl;u5-{Ne;t}pwzHu zU8A4s40~t0hWHADDp#F>d*LUf&DldIXYH{+R*y@k_O|*RCyHwO?+NnXY|gK-X%IgK;WE@V`LKS6 z_1he0v)P|ENq;jY=P%!8^W23*{cS3g|7gv0 z?)cP2%EU$OPXE2N_eGKCwbf;>m~EfK`tmSov(=N(uJvVM6}qeoD=rIt@D-T8l+6S+ z-03W)&^{5L+L(&`Q_Q-pRknaMg3U6EzLhck{5cs?TtfGoGF1k^kpMq_ z#~g%NAJY9qiF=bp#3foHuAaAJW>2aC1DGf7$^N4-bs%)#(!JJT8tkTDVEhHk!Sj%q5oVMbVJjH3W=(4e z{OK+Hq*%_5WhbQiDsY4wyV&A2C+@Sl9sOP18)gG1y%#0lsD>Ire6U&!Xyt~5LL2uc@Slzc3|2H)(Oq^L2b2)yVuS2QjjmdUgQhR)JuYk zEn|PEIdOxaZ!p_tlJZhJD53tyt$=n^#<(IobgMwy73%J=(0zAUP3^JcB-&OU_7rvq zvNW)M#J&>S`?GD^5*=%Vz`8?ptP??J#H+wMSSPaqaHYC3b%Z`k^+ok#>S~-i3NV&e z_dlNlRv7o}JzuI1Gj3ol)7FXphce^`?hY%+`%ngB1!O+0eINIphk$$I7-{E*=W{Bz zC0dHGiJ8XJ6#BbF{nFS`W%q<7+%fmjmnl9U^EJg6z>U@(1(c`S-YcqY=-PEcH>k(SBki8j~XndgYsX^x9b}ad)eqzd<+8ye4+cq`0UepTvp0rJUsU7#5 z`>AYsb^2*zU({RUw9Wkc{K&eF@=92nu_~@ltgg-6ndFoDP;d(B4UgZ^BZiFZ6#?p# z+GqiDashoyufte~wm|DeiuWMZR~N=fJhToZOxgc^vsoXWhk842>)pm*?eNDrjcEe? zoxlxQ?O5FBxkaemVVE!S9fNI{2Ql95yD+4DP@EJ-|J>ex7r7!A zJC!Ko5jk)~?bLYJ=G|X|pm-?0@OJn^zX{b1CZ6!NA`gd^pmDjpZlefqLs;}>^FFMt z`6mM?d%vd-Uue=y()Qcth5FxY`XTG%J9fkW9wjKgkVQNU`uOU*@g88lj{UJ2Edj=D zegO4CYu=$x_lIiPmMH&&{xA>w3g!m(2U{Y2BibS!DkJ^r-MW?540+aR{ONAp%9dje zorU_vLuUUA0&AJ|;SiZ=tqZdmJDIIRnx`t{2APk!0Lb6S^P;xzaHsVE`wcq|QyeC~ z6VS%?W9^>q7Quc2KB%r7Msr+NVVz?5p{CW-@~2^}PpQ^C>;&S-gIhr$ z4iop&x|POE_GK%FUP^g8)~Rg%xr|rbpt5E1TZzL|P{tRTSLs$+Utnwjw?v-WCC9kc zBeOpIRa4!oA7UdIohFZHa~mC&X>-?lt`-S(o}4@8lrn2k?nt zP3I}Rhv-w~!8Ky&SN@a`+;R+K9gRghU{@ZLg62rGenCGW_aMF3OX8;ZCLMQXg1F%x z3~DbxKQuU?@0qrTvQ-`iwi_|eq++bFj-x!}(T?+ID>5E8jh&t|5{}{_Eb@qp@HY9D z*yo|X1MENj6VZP0kbR}S-(%nXorta65=pG*7p(2$r>(-+gtcps?#|XY#<4+`4)$Oz zhQWgJHu9HdtxBX?7YuF`;1JAK%PhTMMISGfWqN_MvXDc)qzAGkNa}maL)*vm4Ax;^ zPOTR{+QzP*FmG3{%66b_?LxbG2IgmAeg^NRy`ZhI68Zze`zN97)P_RLN9jTCV_ik- z)c|{t`RPLjgM!3dNgQHnjJp_rg3lLuu#ffuz=Qf2`UPmpj!-=emsF(*@8l{E9pID@F|onzL668nQ{D=<7D_&30F z7WQC#i`RpdRChL%FcYq6=9|6)j=j~rbw9+rw|aHmPoZa(2rz#aIxY~x>onyQcW6={!WV)(wN%$Jt4xn~7?- z3hjF!s%xbgxBbmBqhGu^s@`m2bo9j7Xtt4`&qhnBI+?E z{XFolER$J(i%wsNx=6y9_J=rYz>VUp0q^j$g7;%jP^PgKdHJwH8v(`@I(xYT?QEyu zMU00fm9x*mrg@Be-RH#(PVjIZ_KB7ZW|ou#toCB|S%3;i|8*OL>ZM{)Yt z-&1>_HIVx1hp?a#rccgKKZo(ho~u#3jpu46{_2NJUTBR)=aW)fv#&AltU|j?4P=KP z{k=tAiOuMIIBSDDq;V%R=C(>~_6smS1$Ri}PUffK9-I9l%wL8(q;V(nGjNa1{%VX< zE0{TxOwDIOb^!~5(^xQlAq%E00W?^<>^n_~G}bI>w4*e*l+xfIT|w`dD>9fXMww~+ zkJn9J!`{{hkE2;z%H82=)|op%V+iJIf7b^4jpNiWC<}5S6VK0+M-#70x{wD8i zH;u`5j*GDfl0EEtto3kifN*|(?>*rV_T9d`$Fy;a;oUSA+4ThKp-}0}1zpUewRIJ1 z(<;se0^+|#+YW%S&Vri^^Ol-!*JwT)#+ivd<2Cyttm7Lc)gzfp*xOgz`ve1T6wOyC zC$G?2NMPLwKY2)+&oEZ{f!t&Ewbi{iw}wBgv$Dm{VtiUIb7ZD5yOx9hfzF&icraAh zyZNg+b9C;3F2)p{FJWG!y&IW*gvS`+Ro0_@;e1QMzB(WU^*?%ijD6&%@-)^vo8S&R za<8N{))1fJ;tZUp(OM8^GXbsTaArAD9x5No(}Fy;>U+Xgc__Rc+-+Yv{0P7On=EtN zROVf<25UPVri=-`RfP_&8x{_kfvdk!R3n_F)d( zH%F!Sp}edrf;8s5G}c&Y^vQHKgE6s>_sB!J`A_Z689S8OLtm#gTN2kk)NdMndLQP^ z{ix@CQkptU;z<0-F0A3v&S)=JQ|ogf(oh&5%3VEz`s@zuNz6GA);M%NNByO|OJ<4~ zYj>no>*^l#A?i=?w|b9EhiTh>D9nkyef(oHI>d=M>y*D^$DW1w&17Nxo5@17#qT12 zSM69M?nk@}ndS@ed&cQ_uEOsh^q%B12}geJ$L}iN!#+OoJNHDHrT4jEr&x&h`*#ec z$$S-lYf;O$MD+fhjPe(v3`v?xkshUc4RBh7HNmG&?Dyn}Yof*Ko^TO507} z$?x|m@9?|m01Fw;D(2z5X(7%n7UF!l@wtl1gS>w?F3&=wzvzQ3q_ZjV-|T+XQ>Br# z*j!s~mSWLokT&bGW7iVohte~7i0fj>YT$?8D(=S~jPkl<(W;TWCi%K5XY=yI#=Lxt zg%tMwfk8pxO`e+k{Xl;*x8x+|QGHU}R34S&zsavD-_O6?O1KaBRXZBSf? zc5%juzi+TGd4vB1dx~pelm8z!`oHAXQRyxWwvRSb{Ug3MU~v}GKMV1l)fC^S8{?z8 zhyOJ(cH^ag#_W22uloDjMx{55a7jBm6YcD*xUJFLL~Sm?cf9^_b=vk1m0J@L-Zb_T z-q#G;we9`Xx6lV{tE${~3vYxB=V7`fjZ2=^YpFi>J>P7ppm; z!uT-#ABz0qFVN5a_H5``)a%7+IF#6%-j!AU49q8YO_$zXS?zxnW_s7twnSfrc?RZ~ zJJC)qzC~v5yf~G<>+Q^&fi>8jD`oaQ*QU}lrnc~z2s0D&*o^+&{I2!8`3z6{UqfH~ z8seFWxT#*I<2?4_YzkZG2g8eDKYd0EpMicnqoal2i8jY(ZHb=EAYR;cp*+k`Hc#)t zdY|$^X9pC|d&bGndz$hy-BbRvYxj!jh<`fbC%vW&?TF%k7UgFCmS~14_i#89ZZq*a z%}o4;c&CqY`tXBukQq3?|0*zh_OE65)s?fvpTeH(lII}mVFuQ#WTx{ldjBfox{Lfl zj<~~~e#=n6nsA?v-{hza)AbJCi0POz0L#WQ+?i5bV?Syz!tXe=b|pM!O+)$^_bDHg zZ_4v~&Y2^gU8zjIzlOY=fahzdlYf}b#GjI!pB6LQwU6IL`E^QfB& z!soYsGV}-V`*uS*N!o;+kFhhrqs=?k)4(x_EAiJDmc~E<3_?6PJQ1F;`Na1tNWa>R z-wlzU>au=8c@}s=JUKiOo+On(t3!}FSFfPA1QN|Oy{2zW{3l; zG}hbrUA?jlzp>-DzY6xL`bC_@wZM+fNnsx1z<})6;yn3m>~m6R-#A~S{7P>3cop=y zWbYuCjNS`XfY}iG1+DXG4~9KRI#2J&8?E&rvm|M+L}f7Pq8=%a)MiXttlylE23V6; zDKAK$&XLWTJ=-1Tkr#S5PaKZIx<7}2L%<>65O4@M1RMem0f)ew4S^f4TYl-554`X4 zBi(-?x1*H_;g9Cb*qcEA>yqWaJ!2vqn#(y6F0cFj7wPW59K9iq@0!vId))f{7kQ!m zRxj~Qzb~gwkAmj=FZ#aG{u2MM^!|&c-{Bbc`ky}f{TKc7(eCzl5jE=mi}{uVdsiin zaPMXB9((UaE;09Bk~=SKy1ny4_hsnLi~JLNzB1W6FZ#cw%$*l~&JpgsbPd+;yr>N$ zcV5Ko6}%YV2N=d#hdJlK@08~L3;Yqrjeh7nr1{&^QFmeX#CKuZN8g2!XIMOvxL($s zgFnZ&^7sze$L~9Ira<3`;N0i9xpTncGADNqH0~cI=T7F#-_^3-#?Jg*z@u6?jNY9kHh;1_#XeQe*Zvy&5oz^y}P{B zzEd41{X6MrrjMnRuYrlVfAASwmv6}ZgOhB%xcdhf2Y*fOAF$uHZIgZjl$Y7}q;2Y< z*YEy;x+hM1688`EveEgZJ~XNO2OpgH{(&5H_YYpL`v;YLSFVzqn;TlPCmioCg8n$} zA>fgClJ)2taTh`TS34$~-%;ppgS(61?jjuNE*m!eb@K# zZ65s|T)}sEdDso%-KXC&JMp_F{l2(Rx6XzAJUqkr-9I?Eg9rGXo7O4x8!CNcR>Pfy zlKEaz+3!$kuNL3ODaH3J1b&kg`n_iF6XMQt4tJJ!;P>YpgEIU0pvr!D5Z{DTTwA|| zZ`WkDAKwZT@eSL7bqmDfFAaFP?Yl#X``rgN%oC4q-s3#(H z74VbCZ>{8~3b#@l<{9KIfTZuoD`bX0`t7_RzZH^w4Q3NYcjodNq*xVxgbr<2o#unVS!f(NHLv9!t%u%>+iG0!CjP3{JQD^#m zJ1&}WiGE{d8^S8S?JWU!bLRs2s$_E7S(??YnR8 zO4#3#^Y}KG;vRymbjmEaBM#T4K^xs+Y8+~s^9_8MQ zSj2*vi!tQ0tvtOT!`F9Zf>dW_)O{L^zGl5U=H3g+8OWD^Pe#85?#Zy5?D*e&PbN7_ zllR4K0^hQmH5lfDJbhn>dCc5bOx|fOjo*EI*OkXO_nP0A`Ci;U*)Y~z2Ms4u<2{+= zo$BA+mvQ%HCVO9oe$R1tW{!_LGwdSU$CGc>X??#C>#Fa*#&>4eX_LP*qg!5uJ2QQw z%XvT6if_c788y?Eo9@djIyJ*_H;8{XTr1d&Ez#oH8Sd_$*n3Cg-F0}a@1C&e_`Q1~ zr`GSDG`AfE{yu6ujdxJ=zuCQL(y#A#cTmh76uPtaX1If*UgJ9`>J7ewLT3iA^bU#y z&scH?g~j{`v+x`BCHRKH-9=&MzRa8TE{gi?iSMGQbKG4NTCcf3hk!%CA>a^j2si{B z0uBL(z?%hu(Yjyj-%Y)K`KRBmB$Aszf>(ilvpJGKe{)(C57>|pb^eGU}u?9CPVNe23M#86)58H8OxPrgwcy$`|n^KwFpF_YQ;1F;KI0PI5 z4grUNL%<>65O4_m`XO-TmTO-T{{_My9ke$A|HaC``{D0RghO*V9skAAtNqR5n$qfJ z@n5jlnE!%Jz<hr6q5llL4aYJ6g>18&9|`{jJ5Kp8<4M)O~&6CMA>kcT^fxWoJF!ha#( zW!on4U#JbEc_m&?{tJC~oc1L6FPP)MFk{P`UH_)zzkvQR(y8QhalU1AaVBG^y>B_k z@I27_%hAQ@_%Ed6zj%}IU&v36&wrsmab*4r2Hp$ezfkv1%zvRbTK)^>_%B|W&REBP z!KLHBIBxaEz7_Z{RL_z1#vY0P!hQ$HnB%+{yZ4@m^MZZi_~pEi-*=oBM&~VYdN>`i zfz?C%%5}s#&WqzmPptkm;k;nyJI)KIZ?(?nLV9ZxeZ+~rRmXWTS|9IQQSYkbys&y# z9p{D9zgpK5d;IBNb(|M(man#4J{Y2yxZG^uh2eUfKDpt1eMQN-Bc;O z`wP*QHQF-Tbg&aTl%KY`ru`l!3ea&``TyB_7dWYkJAbtLboZ%Kr+a!HFax5(%!oLm zBA|&ek4?=0p6+2lAi|p5B+j62NHmJXWLfXcQZs?WJI|GWFY zcXQVQ#qQ>%#(>%E-3Xfh{&ka$8)G)P|4rim`>Q$!dWPWQkrQRloYx`}b(` zL=kocV}sIqJD@-NEZeulr&&HM)BKXG>(t~`ZdB<~0(y(P=86(@NaykGb>3jo>o(|z z)_oZPKhkkM$d+dc7)J^^stf4P>L%uhN~`g!a*Roo9m~H!KS3uT>GCGs>(EbXU=qu} zu(&0f76~x{`q!J52oE~ME6_{sEs<&O;;iejk~;{!>;>q}=4r(%Yn9+l*9tG4b7}sl zWE9UgT_ePF#Dy${%A+r3DoLc*x0-o|GU4Y&SSlef29Y&1pho&crX%ve4b*Bt%Ak)0dd%$S-j~cpB@K31|IoM&#U#pEL69 zGa16og>ELd(9LESx{`g^V=#5lJ6y*Y{uvVt@pCqQHk)&+*qaD7?E68%-2j>Q9_9;w z=hZ&dBjS~d2`;*qJGKIkoberi@ zig(2P47#Jqjc|^6Mt#EeE9GJGJ4D-R53PAY7o+tqt$+_6 z_AlP}qh;~&nD-N^K7gM<9&6dq=&V7APVo5HFY#P4s*@PR|VNCt;mbnmefcXkf$Vs^GD{-{8HQkpY-lt&a#w(EMK@ArKg2dXdQqYTxg>j&Gr z1l`+gz+H-jTi|YxbO+Ly8Qd(Bg(j8W;HdiUE{r1@Q;65SO*+0K%^0LKljiogf8Nq0 zCgDy#mVYrj~7 zoqh-NCDKs*(cvqeEV&PD*y+riG*_qztFx5mTlk(nCF$OTetpqjELh9x>_wB4?vFdS z`O}f#Ut(UIj(O>(&SC#1XV_nf{+*7xk=%w3x8Qc{eF@>(eaKsPB=4vlKf#?}2esq> zvF(_FI?X_tvHT0hI*hZfwYQ$3ckwhYxn zXY9Ub*%i-PtbQa7r=$n6RX5vd^pYMnXjhatH+nW(a@UiQ$WOVi}!%gpYc>7Fq z^nr&y^zfEq?#a=Abl;A*4)>^BiNAC4MvC)8&Ye2SP`(O#gGdiZfIccCeX#axKJUNY zybng@L}e2UIp%T?Mw@T!RRPZ^uP9z^9cc{{fPoK_fyu%gThCbj1)U-6J4>%mwuiS4 z+`H79cN4s&n0FdB><8#0`ZflANa^BV41pK|F$7`=#1M!f5JMn_Kn#Hx0>3*1V)+-b z{EOcmYvL3!1Y!up5QrfVLm-Ag41pK|F$7`=#1M!faHc`vQ>$;jZpG~PUN&R-r*9dn z?i4nbf8>Ys(dXFq?6JL17vFhvub%VVuWtCalfhwhJ5L6eFU*`VYsM8buULNh6_?E@ zTz}cD8*ZFcD=B2f=RZB;jum~keCjxWSa9ntt(_}Zwa$7^>#UjYf6tZgzkGJTk8k0LtY|D|vB!$({_ z0kjFJB;re^w~dS!#aF+zynm7Vq&8@3Z#;{IJesHhXevm)g#OweWslM@N@PRt-bZbn zxMM`PjjLD{e9#(o5U8gFy$O|HO@KF=-q0b>g4~1u{D@28l%D`SrATb|r+{uU&=(mw z7*+LGek2P+Hd9*~g5$9=`dX(8<%0<~|I}bqP0X|&brTsGe*^k#`jX&uAIOzVU?EBWrbnZvm z(f!2dx!m{_6B}I)IzMpiy37UJEljZZ&y1g%VqsNO;8|o3+W1sv7(ZwznQzt@#smFe z6lVBFn=V&({e~R&1PAy*0VCy`(oY8K1 ze%5R7vtHt2^z(Eh`@k*#A^7$|Ctm&>Y|x3<0ggnkZg~PAw<6@F)=0}CH-dvdI?KKT zqg{SJuQ9v-&i+|0fKE7VLGIN z7x=EtkHQv=W2t+H9_p8N>^}kbeU~d={=m8$#-0;hp}z_2&Y7A)uS0G8D7; zIizp!Bb=?A4ZPOZ`xVeB<>!Dt3G`QHEP;lp3VN{uWMk0S(YGeD{9N;GWJKsHaF^sn zfYyuXj^1urEc&N*t~7EKK!c_+4@GS(gSM-vhs+!hpe^Mokf{I~xH4$(IE_c}#dGk* zOX58MUp&!SQJcWe;6hG=>w#{}@QNUwH=B5;LpRcla3gIQG-;qS1CL40Jv+1~hjtrm zeE@Jo7+Y$`RBJe94ULj|z)wQP31I35fIH1kQ!y`*G4mJTPjhf2Z{_@*$I4&Pq5Kv0 zSGNDhlD{Iqej3VO5s7Ry!BTssD4xNXsG<)Bb#F%JnVEZbKYO3M`_I?!m++~_gPU%=U@y?K;fLjO@%9`n^8<`u)w0NfR7 zyPxme4!*~2cAf-`0{BzfBJ5Isxc(CCLVrG48`(aw{FRaW5!$nyjF+tp*cY)cD#8vN z&3Pl-z?<4RKH_(y^&vpt1qt+Lqs2|bW7TE9Biz*2*?E8TIF-3KW}McJMYc99JL1VR zYmJqeGZVaeMpjfPPe-Rm)|1vI?_9J8hBtMIqOs=+5AYxy&0|f@gEm+%!CY9A?;(uG z(X_bie}T*l%)#>k$N6hx`77d;e#oBbP3c#!HgmH*H!#KEp)&03uee$wj)@GoN>WS_@+e*5aI zf+0MmpB~ord4vb7&BS{vWUjC)>^w~KmDx|mGFSW}v*S^3!d#BI+N@3bvxe51L%yNP zuFe(-PUtHWhCL4TU$igf4a$`R;CEy1Fqtdiyh&{ibnB7zj!(q?g78++-ZO-W#5oWA zdmhf8d<>Z@Y~Jdu#D0F-;vV;ct8j+I-W5Et>8gu)Y=Al5HkB?xSQEkZ$j@Q*N+jy1 z4XhO2HkqyrGH2SH9=9|oooUkA`3(BS=}(tn)7Vof$QOcn8vC&CCP8Jvk%V*iy9t}!dM`4-gz&Sb;DJDi_? z`N!t`j52YraL6yy`lS&D8h^q);-#Uy$_`5n;try^qt%>)B+dtwdcbhEaG$N$-0uR9 zWw;-F-LfoFZKj=KlNQyDN{G!cRpBOXXCCc|2Ek)$?n;2~3~(5PUlntlX%~1t)qkwX zQe7!7n22~8Z3$Lsr~4}GtH^+d8Ewrdw1MzwH~hT7`WNBP#Of@~i{0cG`tuzZ_$7)9 zx0knZ`M@-DzUd}+K?Zjw5_{M`VNT#kUWB^<{%-oddM^Aw$DHaU^kYKu0DJB7EScu3 zwR3g%(KH7CkY^QeqdcpCxBswkdvPWp*bCI%QMiRJnJ&Sd?~+2` zZpYt*`w+rY{POU3u;r({Zy@a*3#YwBIG1@Ffx{S&m1KXqvi9_qW1$ZIF*Y~CjLGwz z=P>_R8MD;JS{bvZ-4&}>p7vODKPk0!bB+6itALjzrvf(L0XY+)8-ovbZ3u_`X34Q& zbC|i4Oq|cW^fcyq7cj56gL&gGW}XAwaV~_MP*1sY=o|N~Nhdeboy6HYa-pLZlbCVuE|*R@_>=CE&ZFt=komr~#}YFs2ZWJM-$ z?w7Q$1dkTovsBpqen~#ylMD*ln{(XV(caucIPEj@z_Uu@Tv5T=$Y(DSbT2_NCpBax z(4K$v-Q=m91)_a^8RZqR*P?QRG0p^ft=-2H4;!yJkLs_7_<(iFtZArofVsl1Zx~O} zHyfsT*sk>rvEB^k(|he2PcnF`i&qMMuW(17EodDyVYL1uoaU_JZTMb=y#dY? z9A}Dv?rU+T7+HqSQW;Z_{wtXGpM|0Khbg!(x(;XH>u^47McB>{E4K^&128*jp2yrj z1$&)DBI|Xf*167%tb2j%ai?|lxc~C$F6Y5PmiiZ0^9MzLdK%Y!))NJn?Lu41Xp4T( z=inPHC)z~uP^W>i?SD~`ysnwqk9wP z_nRJl$p7)$hy07W?0o^re)w@e$$-$1_wcPy4up1pJiRxi#G)*vV~a<&liC%@mx${7 zR>-no=h=3%1j~{<3)XJ;K^LPw#CL4!5X!2!xEt`p`@}<7tEjFQPrvGj+>J=a#)^!U ztMPBOay9;(`IPpd{sBShjeLz!@qVJembv(BmZJWoya@&h>*!cGOC~FR$)r!3zFYDAdq?1%d51v16KrST?c!1xlAA*3 zII<)7jx|0$*DHHNgEqv-C&Akd$zmgXk7aH!BNyaMmAN4=!#Rh}OSp@qJ2vUsGhP{Ub95Gx z7mqv(l`&?EI0w@{pUz;AspkarjeRQZ^l9URJxWp2 zuS@UE4DZT@{{`^~#EK<&GN$N#*w@*@)8S=D6iMTbD;iW6wd+ZM2N04 zz}+I8 zC!pU~pmijg_=wJj=!{0t9lZ@SM`hHZn8f`s>|hL9BST{p()QDQL^x;o4?bjZlima6 z_4Yf$&9_qjtGYid`&9T3W{s>Tty8DOe{jdi`48kk%zrSrWF`0rz)vs+jZpOF@J8?- zl!Nw6Idfj7c=0xWEM5ft74RXzNEpId`n?^z2(kWG&>_CGCQJHo1MnAc&>hCS2w6*a z$sRQCZUN@rfZqGUIh6K$ua_4g*8eKgy$ZU`Ku^AV$uzO&<^ELW&S77IzkB!csbbHn zwW-YAfI0ZP`F_xazql4Oywb1E`76VFAV7zRGh=-jd>%vK`zSTwEYk(~1goUuK`)u% zLB==RX=zPLpm)#9!#KYUo45jTh)j zjc&^X%cU_iZ&f!*N0L5h$4jY+#CM_6q^FI-$dA%iZUb+|s+{0Ut^tu_4*XVF)6Wq7 zuk7of51y>t=O=IEV!U#%cNPl)I%@S0E*z!+W>erlQ9(bP^{;q+LO;l|d4x&WCD`Yk zCDT*q?iAvIq}Sz51o&nI_-2TohInW4UGH4J8Tq|a=bO=whI|qs-;Dl_b-&$wGx7v{ zGh#aPCR~ImpRIMBX-T)QJ?SOdlAZ(l{GAsl;b6}l?Xi#Hfk8Vx`PzAA^gDoO=485H z<%1zkoQAwJ>R&_rjCp4aFHjEabiKacug9M2KJdKkfAtafzK{=Q;T$IJkdrr(hb9(54W!Km-9?`AS{yw7Be>3@K z*afG~KcjQ6pMOU7jBMva7@Kbg|4gh4_9$P;H^3hi@s$`J9q6uIgf|D`$9OyVP+0c# zep?K zb;0sOm>W6fMh}K)FNj~=&}cAi^vcqnlkSx`_%pzBaYpl{s1Kc-FGamK=1ZadTKtP4 z5JMn_Kn#Hx0x<+)2*ePGA#kQZAlCmnQWiPsQy@9V8nRKT4@;1l5y{pG{6;Z-${hEM zld&^78OoxPX9`-z^^749Lm-Ag41pK|F$7`=#1M!f5JMn_Kn#I57y`H7JnMDoe?|He z*XRt<|9UbwjBaPF|MkS(ex`&bv>GA*BG&(^+*toBa3a?K>c;wCtxW7#|10?MR)LRb zKqZZg+2^Fs&+TyqbcfJ9U+$M_(gnerTA}m+e0Gg8O}vZ5hbh1}7wdm*5L|uJkM+OC z`d>?sqY>+Wy>?6;yqPy`nUVPi~N#zl>C*( zqw-gDtpC-G^}j-I;aensWh|L1vHsULSC^EL14sJLXnzI0+oaRe%7%kZPUtHQNNxdi zu#sOZa|IkHfJ6D)GHvveCPG+^lDVQ{{jah9*I556kM+NXI$;Nd`|qI+S<(|o`%cm! z%Q0`z_bUh^`91U<>65MhcENoj*_kF?w}G_!vPfUE)sw~86DQF(OL_9MAwS5Ro4Z7; z{}uXRWBsoul*t(De~tCO#xg8o{jZLOE?LNSdK9|7c1mg1Cjh+` z_*h@6sxRXsTtUXoV0)J!oy{AdD@?*IaL=*<_p}AX8{90D1?bw|;HdiUE}1Dnj~Gm< zdz*B8$LbHJG?V7`xPRW#Bqpi9_GA68$LhbFzMJ_B{K2QH1JlS}xP$pJl)bRx7+siF z$13UCjP<|1Wc2ht4vUgD!&2cUkX0)OQE~;(oy2c8ArM0#hCmE~7y>Z_VhF?#cxxbV`)6mrKK_@_o`k{WB*AY@E013a>3{vN zbKbZ8WN<+Eh)iPsml5DNV;!%R|3z)LbcmxH{(AMl(mOlpe^p-}soyoapNMSb+>y09 zU+ulcSo&WjXhx}ikses)9!C#sV!PD?t1t2?pEr{Kh23Fw!7At<>U>qxZQD1a z%%@@MQD%cF7iB|d2oE6Fl=Zv3OZ#Q`$NVoM=6`|i5W>0Bo&QCx9Hoo6dV1+1RxjDP zGSWq?`01&OSRJ&wh*_kIIHZ3v^rq^85xR)YI|Sw@(m`zIFVLpa+{r)K4-LL-E^->Gn(tvVyBYXq&zzfmi zR@OoeAof0>m*GBenP_54pfal*jNMPkcbi?$xQRlkvaEaNeZ2uUF?Vn+JW{-(QoRwz$W=;3}LU zIe0gn&UDoUZTkRoylpC75-dmii6cLU)hm&xpEj^kc-v&UGRT~1b9&s;pme55Yv(h- zU(nN+VC#P9b4~52*Dz0Gz5i~aPjFATn_pq6&2v?{No3v4Li4BLej4tl@on~`;FV$} zj0dFW(B~Qe@41itsxuJtzr_46G5<@%qZ0GKq(vVV4vA=_0wGD!Ap)%?ogU z7vZo?IJuujc$wbtQ8~NF)z$(;)P*fKaKUd zHrqWKkM+66`drzEy&E$Smjn99Uf5HxH~9+o+t0#G!F~J`oJp_4J<4@>7idM;&JQcM z3;qKzJ7Js_iWBp~oKCzj^7lvTIHmn=2ksMIY*GBp)a9yXpSmtrIq411<+^BOJ0Ajm zz8$(;V_uk;7p4~P%$vmcoY7xf%NwC^KCk7Eh{ohh;4O{In{c1~8AtK2PwGv@yf85@ z%+_X^+M3qJ#@y>H7pyWKFdbcry2Yf2Nv%T&B(tQ`NzC4%6*1-U}9bv zHxJyXbV3#zMFa!(CjC-iUEe3U?9rgvNg{?vpP&xz1U6 zajbKe=8*UoLm-Ag41pK|F$7`=#1M!f5JTX#K;ToWZ@%ucD{uVNtl2Y`fBKeVbFg8@ z`bR!UAAOE(w~y_8y7&_R%bX89d&9}#FuI*5gUc6Y&X_ghikVj|zx;~JW)!Z!Y}O4o z&Z^avv*Pogo^i*DzFR(Z96&6%^_JGom8)83y{C27%=f?N%J*MByLI-=Syx8U!>l7G zW37yR`R9N0@iB@z8Ylib1_Fs+;l2fD*aXhBl1Z-4wX}K;(ZOB_^Xo@k+yHTwBH3D! zu@BntV={t={H=Z88!PO1e)=ZMmmx2(wn|z47kO#u|995bQ>{&BYg3P7Y{d#V&oi9C z1?oEZn@3!-DQ+NV_=0G2T9qq6XCs!#4AFt*VbrhJWJ@{C$rwHvIqVlyug?yz&JM!X zPoX~fHlKaa-Z^Q{)}shIpYobpGXdVG0(^THBLDnP!ONm~Cun~Soo`708;n!wx==QB!#$bwY`zPKhAnCH9!)#UahE{pO1LZVK$}T*XP`l=z`xSiEqDqvYZrso zXNj)&K;L6%kQnaTkVZqFvw{6|l)EgEO`%-*IopT&C$_)nPNVR9nlF&sOx`8jxp}Cs zo`!fA0|(Hr3&u&%S}C`L`?s;`M|n{F@@%`$9|gQnwt@^cpY{3ORR4dmZ7!i+W!-A- z0f~;Tim;-?QiDz1pbP`OYI~3H(H3eGg^`*GD z$ITr(kew-9W& z$Cmq~1Ehd&A%_jT=pLwmelPVYuATusA-=r^r28Q3M%0PyCeU?}Jr1kR9CeP}-wjxV%LU1|GLp-)Z!K6!NPsUO-tue`d}&2!+$IK@4s zL}eW48TS@kqnBi_aI0$oGd1k<0CXJv4S0-I;K#b!r}nUfr5PrD;07LSp)2ub%V2m0 zbd@WWD8iIKrv%S{S7@b%Tf?o5yNa^;eFf-983G@~ttL-?uT96lphN&uB>NAM{$87& ze?h|^`H=mG$cOv^|Ke@MX&(0$N26V}SBu zkHHUdig?Se5bT%i^Ld0@UCOVb-vsE?sz_Jr1wLSWSIEY=p}B+Z8yV;($DD6yocx1r z`##WDVtn#y=g2$*R~C-9limKi=E9n=?dLL25gjPsp` z{37l)E1*Rr|H>?xsq~vTE=yW`L_E|PY1D&0-wYnV<$w$P^6=wJ;8wtk*@+BaZE13a zQZC)87GLFcc}Ma9@yf$8#pUvh$p>)BV_cPx2Pe8p(5)jsQwN%Jqw@G>l+&dsEG$cA z6*1xg+pQkop9;3O1aZ(Dy~mmwE^8 zavv8i+ll@t3%C3;-060zGzVQmk?Mpx4`QD2UIv`HRJsB`4*FKz3HsqKq)8yGOQ!iM z?eNDyUktisx*w*wR3LwWF*gYQ5x^KUv+X{B=~5Wx8drc`N;*60$tL<)E?+WpYD8~) z-1wlY8WA5fwCeu=k0r)Tz}C4OFc6Ow-0GKg(MB8k==PQ7J7~XM=%?Vf zDe_+~H14p2C4V5)*40@-?Lj*O{dK?G`BlG2biP@0cUnf z;i2Dx9PsMf>6E-1V=p1Oz6&(QD4P#heJh4`+{wD8Z$UpBv^R(<@)6gguP|3+c){KC zEsRNO%Q%+KqCcqKd%mSb7JarGYtnA43;uSN1P?`ecjH1qIt%iMzagPOCWmo}U*_9N zWH{zvtS2R;=Zo6>LF!wqheY$75A!X-&6|7(%hsIM%L4G0+9R4iDS{>k@cB6G9PE#w zo*3hp7YaygaHt7y8)$O@Z7w{VPML8E^z6<#D?PLn`GB5W7-sA_~1#h3QYkt+1QAPS{|8us_(7#k( zZ60QS5XA-E)u03T!H6Ub;TFE-wITk%JqR2d#9Am&PlkF9a^(N&kk9V1^R5khz^6Td z&`0+hv|sXoEBs-*=b-%x|9jxu4$J|xMxw2>pEo+!z61Zp-xGnl)YO~(q3s`nH?5y# ztfL-i@M)jVyLwz7bo9kl(lKxt#+>Z19OV0g)YSfTg4Hu8QD5m_DX`9@gH>2l<{&Ml zX+nOWf#q0t_3m)(7}oV=;ESGxHJJKw_BEmccc6wc*w1F7y@lx`%|+pv5XCJ~kw0`r`YdQv?q=-U!Q-LM{2 zVHaTMiSGq`2A;%t$6UoR|CJkiQ|gLEX8a1^jzC?DNY6U(_DSsy@s(lUcnrSww`NEe z6}5@>q!ic0VYZ$5{^v6)iFuhF&Xfo)N(+U#A}j-c*!`}J6XCT$nCCFW>9p(ZDUKC_uW&5hSJ6IUWc;{=8Fw*_rdVed43-5?yTZ% zFnnXXkMpFv8{fm^9%}O|a3}T)FF-!B!NPtR{Z+)gQ0`=+(x?0))|(>M7whMV%3|qL zeBgLeVg0Rc(hdvrC?Fl3Et$JIi+zj8UZbUvm#2K7@*t0!~O#ElDgm~K|k{- z>rX%GX`b9saMyWF`zJ_b!Bo?m4iNj~CoISsR{& zoh%pJM??2oa^rmX=oLyNaqdfk7hw+OOTHWH6XrQ;BZmyua-vPpp8I#%Z*#(VtWnXP zM*n{yjeK~Ar2omfr(pj(1^eGAfa_O&wnI#LxnE4dnUiRfrvO*3gLxKnz!dBUuLFF( z0&@uK;}HB0!L$OuhR7g(ud8`4>>=2#uv@WzI|Ta>(zZ&tdym$K{mSlze+XRt@&uOp zA@Z2Kzu-=mH~5n~d)#)cOWVpT#1FqO{U3TPH5sx>CJ$}PwD)eyd=g`j(tHwQYw}}u z9!)$!=U|JAlTjvx*|tm8Q7O0`IFof8YV|e7cL(aTLT~rK_Ua?;^sCgcS?nq1+_T433XC7*&BbPwiN+Q3 zGV5y4sdBnK~1E` zTd8e?Yjl@Fb)@zixWg7Gvx=~M7*?XNDV?};WGQb-!mR*al!p8T;uX*?!Ut*_@t0D& z1okzwUQ!w=^OW7QrHNmr`!&FVyI528k1~Z1ZUpWSzPMsO_5uQJrMw0Fqwm6pqByCM zao|sP+7yrKD_Eaj0lev4!0@}P4{N#8nW-k2$&2bsd7p|~W1m6!7Jy4pJy6Ec@2H-z z39ky6KdBCM&JfS34AL1K^MGSCo{q(_p)qlc>Yc*LJhj)}v80gCJeavSzpg|1DW=`W zQ;Oe-wzzG}M9LLz8fI=o$&K99hbPP@vGKV1Fc+d1P>$R7Nt5^7#eZhvj?UYxbHES6 zIV!IRySCnRUZ=Vf9Oe?AHQaN558v3+akPQ%b6wzoo3LkgI;R)0w{~~7`n1QU?|BH{ zgSPI`pYq+ct^RtF{U)XmUe9s4*XkFsyU-~Pyog?nl5BRAM zV!c9p=fN)H?w0aihwoi5gb%!NqL>HS8FM!)rw1_a!CF@CVkX|>$Tw(e5$l)8QhEy$)s<%$WIMeJwAy`B7d3Ys_cq(fLxI!5k%0T}rI$#2E{1 znJcwONhPSAl(+7-bJ-=h!=rXw@>s#W1almHN3h7F&U6pXHftkqp^7nr}-t*#Ncw7rn#&e_dEIJlf)p#5Un|rs?hB+5~O=Ba#eys@O;ky#nlUk(augU7$bUl5? zzZe4VCJ2z+)7L})GFmR`F|cbt#^<#1Ao`d0?*I80PX>q4?TqPPPOENw&6PQZ{^dOT zetA6lmq_N;SOvZo`WN}R@SS>wwIli${oc_3AFM4ewzge=C5os0WUZ~1K?U2$`apaHrmZ0~XCUv!U+M=&{^=wDRc)>}sPuc3b-+8Cl`VxP2e zSS|g_k1Vdf5%e#*(dI?())BqQYo&kjUMQIN9`6O52mW8YXDxOGSN2RvZyLt`HPFal zJeYTz0Cu_4zHgL?uI5GImWhrA_G_l2`J-_DdBVbh=xEfx+WSiL4*wR@(dfsIrK3?q zTk|H;(Wpmk+uu?;nowpU^=YXW{d+pl(fpge+j>28G1c3gUJYq(=-tD?`v;6j!e9?8 z@U1@@;t$-lbTmX$Fo^deLr1gG&bx+=hJAHxIvU6)KP5UE>@SKT&215T1G7&cI@{6o zHMhMr^fhvCxTc(hzDE6H}ZgmRdjbHzh~Vs-Azn)V`utiDbT={G4QLl)x|^8p=1ir#k#p=^_HLoOVcjv^4ZXR=zqbzpx8FSL_0hlF zTr1UNjCPy>^e-g;Tp<|&r{63c&y<-f%8Ut;+$vHX`<{!1+X zh4|S)`)p*@6dcgO#qwWb`7g2jmstJ_<^&_Fgk+Y)@?T>4FHFbsUmO<8e4FK>w+rC9z8WH#ii-lZ}0 zD8=$$-hFzMV)-wz9wj>Kke;m9qDLu~{}Ri8IVJr{vHX{}Prp(u|0UM1bUgh^vHX|g z>NzEu`?Y$PV)-wz-X#HgjS}R%#Cn&YKZ9tPU}C*XW6OJ)4>}Ig4;1NTisiom7O~!? zSnpD-cj+CecPWxiy#7*gs zIL7+u8q4$a@gx05SN-+=Sto+G4cu8g9GSw~Kz3g^o| z|C^7GQPj~m@zoij)3gHp}W6iS!?-C+{$IQ0LxZ%NVWiDAbn}$&y9=p)OK!s*6B9 zMQRRo(?ibsKR$wQTkk+$;tS|96#w4li{9040ea;{8u1=Gl%Xm&q?4Y2eqzyk*cZ@S zIk-^?^*@kb0=kDcYC$&n3porLnO2|8ARS4tJD?+}((21lSB!>^L(0#4r600GWXjW4 z$4jI?=2IEr^}-0q;1wui@JmWmIL?DhRtf=G?4#3>z9SPxbwD`j{T|$e@6Ad;MJBX^ zLN@WA;M>a{(NPnX!52XnG?~9xou&5iji~2;tjWsFiEJqeowU%!sFtAqJ%{ChJ8N3L}@IK z`?OzL{3kBysNh`-O_~6@rUgtj(Ih}^v7=VWr_N^&*$iOl0VOP3zrpb`$Q`1{_xect`G(2H*WJM zqm2?c_~i*Qb;N)6<)Yfz?oUQuB2#dy=yQ<~u+fLGNuLVEr!a#LVYooJ!8?kJGQ5vK ze~<+3LU$;Y0Uf<5f~SB^Z}OvlP*1GMa^NYxP2Xy?$H>e_y$ZnHDjD^hUmZ@S%Fw|} zy40(iP@f9)6zmaR;&$kRM?QmqfzeTbyvoQcSfw2w`r!k8p3%SMLpOYpfln22edvYf zXdmH>51sIQpv|w~I|04mfU_$fw{48R$oSJmmjmAiHO3L*=P}MI&>I}|0LKLCDNrByd$22= z+OOOu9gmgJX67j9u`R-%AF_EADLvBgE|~#Lj>IdG-)v^)Fb;UJuO_l(q!T_&R=DiJ zM3(X`kh>20Uuit+TTMTb4mA&Yf@RLm^}C^SqU7|6!JT>G?}9quUq9k{FSAssUpb{N zm9GAbrHZ#HC(`fgd4PAPO7Bjv-0uEf!IuDL^~${q^H~P@_%#2e!J~yd3P|7WupHrS z0e(8c>iOO0WuUv=El)fzQ-SS~9+k~3lZWnB@9ut=FJ~FdNv=2ZPM6x4Pb#-W25s>i zRbPQ^biw5TL*O{!qelkttxQ22e3z2=hB3Oe(O#C#dB_uCeFkUE9G%U%dBm@vUX@oL zaVr_5B{^6$#vaC834b$3B2AD~TtT08umCuPuRtI2`GuIfXdQ9wyuc^H-F0h*f1t-L z&uS1H;}i9DsUOM-RnHvEM=+eBT^C~Be#x$-`WMzN`6#=lefn$GKk7T0i@8Rg4IAA+ z!fxH{VqQj{{wdo37j9*(65eFg5ACJ#QXC)FAM=>J%JwxIZ*BP%tOuWTvNUcu@?djp z8wjp>z%38|D6G`41#m&|4B|?w*SUnUG;~D=@GAl~0&ojvW9-6Rp|~^#@iTQw(X^KH7m+?f~U&P6cSir`}O6@|BFQrwZeyb1I2bm)3J2kTUO)}?R4^B{%3 zgkC^3Gm%Z42S3%DQ6vH5%0&enEON7?}cL(~mNu`VMub{p*ZNmxEdINyNnCYR1 z+m!8%nclRoy{3J4*!CU2KKU>|HfDZNTaI5JY0?v%kHSat0@_Nt+~)(X68e-YUDt{N z`c_Dpjb-FP{a!&ob3f}Qpj$DC{v&t> z`ckZ|DoyR>ZGiDqjGIo3n^5nx!9R7sU-Sq^Z}kb!IPfQcJ7DK!XutZyM_My#1>l3V zIFK)8iiG#THQJX%=?D)E{wVY(%ej0q@=3$Sp33O9yCK}mhGT=*FQj=#lxIO#-*>Mz z_{tmM*N$x$?TOl_VRL15V=L0Nc%hS}y8QsAc;_N9X)oqme3#GGJUKb(nRdu+*l(cx zb5OTTA{)S#b#{ESqLw4T#?$FUA3&SzfTH0F61Ft53Tc`X+*Z~VpB3ruI; zgo_~l4RvR1t;?n*-M;pumuMrmHv3$vuNkkv0h$xbn4bf{o&Ay>8J7(82@-7?wb0h9 zyjZ4a4lZfHLO$RVJ_p!;mQcr{#6FbZvtzqiqe%Bip4^CQ;sJgY#4loOd$7wG+j$zF zJ81s1`_??o_x(dYt6QCwzqGJ4I#! zi+M-;H**eP1(*l=u&-XU;RGLQlYC%Jmhjz&ySt_w-;vm79c{bDxr^eJ**4z?JbZ#@ z7v@N3*bjCBZuo6L9{LAI`%uqblkJvmnKJU)gKk{FxCOaa-JEBlL7P3X;C{4*~PZK>Yr@;PIVj-TxcAsODz1#zyX@C^f|Vl zqjAT+XW`BKaJ{DW3~Phm3|KS*zHs|VhBMA~f49R@nF-3h8^*wWC(Z#1`)!m(djvjP zX6{D1Yy-xcpU9@q*~ru9Jjqqn)_ntDMexdwV=3h&vhxr=58*ltr#!jypdSnjAz#d? zz*)B2;sJ#bUdkUOj+s}+!Zls7>Eu>hw#r#J63%2%N3(9TVbjhHXlE8izRI%esm|v< z$drym^ST3uYeT?1JIvpbvq+0qintelFbS!VO#h9Qu>+ z?V}FmWC&Mj;aUWo4GcG{44-Sp z+l6>k&s~T|^(1%(1IvA?FQ@v!4qz9l{;cf&}G(e$}T;guc* zC;6`|I}hOzoCrq#x!4m^A5i)i&<=#J2OJ63>qn>m7t|l&yAW>bj&Sv??MIqt^X)3_ z%~q+xfS1C4n(xMb#?#yVBGzQ3c8sLq)9B z-5AeR^aGuP=EGgZ-k0`pCF&dCZ65ed;=frL%Iy|#JNP!n&4sH z@!F9V=X=WMF61+RiOkR#n2)?X=ZTc}vQAa8&(06zO&WnT?1_S_C&Om_X@HQt#cDI$ltDS7gh`Ig;;Z#`6)(c&=+v_ zT(M!md4cLy#TEefVjZ|!>cHJn2kw?u;BKh{cS{{LcS{`!#XEpcu-%R{-AUQ}^NvDW zb+&>%lJ%3Uu4$pWVBBP}fW4Gi;3|HP8uInT)!F@kXAX1rz2jtRKh7lg!cE`z;+vhn zI=c^fuD61Ygl6!8*y&84R9U5|ThlkvKh`&z{`wL*#XBWEr=1BiOe9P9=*?Qz#-=p{w zD02buO=nkU7vS6EgR~|e z+E1dM_04ase^ll|v@OT9n`_Fs3s7ge<6GdOo%%+fV4nkwB<2g#A86ZXnD0m2HuO;+@O@8-=?){;A|6&`yf2j@M|559vHG6*#@CSHy57z2Bg?rWWs0JS+JOnHZ{?zRpa_cnk5bdi&e-O;>!Q3N%wZ`t`!QSc#w4t8;wSP5Way8EUdc5tU zjnp=SyD~-XUI3g%nW?((T`TGyF1U5KuM!OyW7KasE_ZG-7o z^eN#!^=lpaY{A-AT-oH@sEm{4f6vd?rgGSaqYkM$jJbQm@(6AVlr3`s%G5uyW$qh~ z`qtvn$`EH@8=MK<`$Ko`wlEyF2@l=-Lw9af7!KQnhi>)bHQD|6z9;!LzivmbF9B1U zP8VQ*MtD!{s{_6)x=dyaET^)Q!ZK=G)UJEbF8PdYSJX$U{y2Sf*~mUxu(mG140(@ke;xMmvTW-&7Ce8KGNSsAE@J`8U^{FXHb2Z?s57lm z3+62M@59)*uYcIwMdr|^h0klD_pHh05QpJDli{1jgbh=I{GR~6-~05iTeq%3+=p?N z>pJ8%{Ap(znYL?3J;mmE|}6KrZ(w4&Ap=yr7Gjy9GMm&|MD`T?fYpjZSo|4;6%Aorai3hm44@P25+4%_H+t?%YG?wjNfPHIYw@?>E{tHD^ zZa3ojJGcAY12~`183pBUpfe=aw%ynxZNQz+hE+J9IE;6r&vzq#AGVx;aO6pOZ$Mq? z4Cyy1mz~eDbZ*$&D8&ZYY-;50Iue)878F;uBMj$+y^V9l2H3JKa$hC7(WVV(kI5V7 zA%7ggr$l)z8WFxB3O|=+>CCaWafzU_mpmuR?;2AVc{ajPj=~vuZ{xBf^@-{(&x-Pw zA`7_gZ9KNlY(f-gZWw3mx~lO}ys_)5nxgO}HlH?IN7iWTXzEu3Zv*R(0w(P#vAeBD zYyjN5+dWZj`}mQ*4BBzW+m5%E_6FG3h@h!S3^wIqx4`bk+Z%8OYo$Qj2AdX%0=aR= zY2A5~W&`fCg2jZ#6UA2jIb^q6#(!0gq}`O!Ij?C?X!M;gk#!=ZR$rq1jsk>lrhTR>y2SfLtuy1CbhCji8(l#pPHVpud7>6aS zH+28%t;D!rg?R*HWRT`az@FxZf@;l3oJR!Og}En3bIV%4w*N%Ie-M9o5Hh zMFU(wxfPsOsV*Dpaqj#z-X3A=SGX;I9m>BG=XvBqZ`miTK6bT%jVVY)?G}rU_LeOn^(JQZhoJ45Nml0 z&d(eDS@4FA9+#hcOJTd1Fj?gHWZG2yj5 zcBi}5(QeC)?{k}1tah8zZQ@VsH2+hKM~(faM4SU~Z%HS_)?G4n5cdi#kD?DT7b=8N znk`7P3}u-(up_^Np^ zzg0h%*?PWCEyJD3LCT*@x=*x#?jaez<+tns?DVaEGxBXtqF%^rYn|c;V3r|n^UC+R zrfx_Zxhb#avyQr3koMpt;3VGQzbE?zmA#D0ZXUaAXH?lOfJtp%Y&kzGmH~DxdYivh zZSxP(xwd6>_8{O$Fy4B;Oi>?GxvGKuHDCIRwW$__9c<2t12=YwFCqQbUldaZVMpl> zAZ$V_;JWB=Cd!9wG82&3MA+ZIagiYR#D?cG2i8kLWj&MbOq1V%^)`(BC*aPN{I-7H z;>J?IqZ#j=1V`#;dXu0!HlGbVM7@{YD9u=#09<`0T}dgtc};jsxXV7@={$q@&4_yd zc`Q}i{pMEKXglS#C1Lx7;M&ZF+-3$h`h@y@Db)+#L=$D=hW$rzmm+NxcME7>w*2WH zlkNc0ZH0;YvNj*~Pxj13^?j}I7z?%rPB&UO)xv|?-VAswC3t*qO|}{EAXrG;2NOJq zCZ{}0run3-t7qwYjd$Px|P!{ZqQ0=FlS2@J}kYjQwXB@9%khbL`=W28re+Z?;V5QMcgb`^@`q z0d7h+2)`u?a}mxi=VAZ;{6v;|J}=W#G5srKY;ViRD6GgZTF{sRHp97eDWu_!})KH^?zCo`%^EJss9H5k6^C7 z0dXnqc~^Eh+hLx^ea7>bJI?bHWvco`8E66Q)@v$|#r4F1!hS z4Lg8cBzGg$EONsxo{M^u8#cA2Oy9sYu7-U5GL0eIJ~|&3)i?1TMq$f+I=6W%LI1J} z25|Cj7w%s4!*0-S(b{BaxUiQraj}|W-yI^NwWAB>8p6jE?12E3F=K+fpU~sJvDAW4{z#!fM=q^4_ zes~8UT$xXPSOdIqfDQ8T#$Ag%uooQnG2wNQy-XB=dl8Mt-kn-xAJw7M5hdmGOT`==Pzg@7?1BeHc#(R;82YVjeyI|&p ze!F1T=0|yrnXV>(%6qJQlECrgXWr)~vA(Z$w4219CmI_?+$(axlJgjFh3PB zmKfG{J`Q7u#v<%8jYZge9OA(aU~}YCgdM;x!!AyMyBXoI%dmL^;!i+0>;QHVb`f?N zb{RHrL3jhgVF$2_u#2$Eu*>AX7~zZI4?BQehFydmEQSA4_`?ohmthxS2f#!AQTW3S zV3)~_Hy#@A6`TXPci4Vo-l|}(Dk4sR@yI`cG?*^}*kzhGaDT&bKTkGO3i4RagT(>A;@wPBCkhc~7+yfL-ayfL-S?Q#1iHi$i91Z!JU!7bS{3iH*Ha0{DBpc%2O@-KmHD ze#|X9*jFv?8=57Xuj3Y6XYWh?0LH1~;(WBX;3i>rHI!V1dsOm^;;c(-bW=5P9Gb&G z?nP$a;y-hVCm@Y*hIN$AidP{V#9(eWY`W)3?JKzJ)K~pf=U4s599x$=;Xk+QL0^Cd zBenAZzmUZ}1I~Mou?Kt?d$8RIr@NuY`nUP(I_+C?lrQDEZeW`~H}PqI1HOsY(%D~d z2mW291`?JAGb+3C>Q`KvbECFUUsC*2?-UJ_j&!K4fE$&TPPw;%a{#??_9F~8sM&x1Vx6JT$-3%1k0(a=xLgFOJV z3x@KdvZ)-hDGr5GzUg-5ki9`4$}pUBO!xru#<_4F>;aen{kjXbvle+{EuIH^0A?3V zZ61y+xlX$lquW{lee(JfwD&69e+RRqty|dM4Glvn=`G66SJ(T_I@Cu$;Ln3S0283k zcENVmqduTjn+JOUW)}>d3r!mcKGcQ?KGcQ?KGX)ZKY|a-;*a10IA9l@T~DBj;Lx2UnXo zY`5K?%$LKy6W)IfG_ce_gEnU;s&o8{ArM0#hCmE~7y>Z_VhF?#h#?R|;PipO?Vp_; ziodvWEb$l2%6T{q4?K~M=-gx;Jmz`Ap z#aCka7q1DwM$5lYU$yct&m)g!~H`%Cn%iUgAa6|8C`9uq(%w ze<3fj@-mLzhbaacoVQf|g_>dIU#K%c{)N7Cr2GqY-%7BcFMS0?3-&>3~;eNOaOXMB^v$LBopJtu$=dY z_Lm_O865P)5&cAIt$IsjWSIR!D7!&G zwuJzVQ*bffogs@wT#$7Qjq~}C83kT|LKpZmL;6c`0r&<$r&)0N(*^JzlvAL`NP^~~ z6K~pYlB@>(#n&gRLI073xhmK`J5?TW!b1ffae3Xb{QCjgd^}kVY_gTrpr?eq)vLfm zj`+I8maji$>vJ+$4f2){S3+40GLkt#c=W%rlgeuF*hbfbT$04=kl9cKFB(^UMxK=x zHS$GJmm=2)!#f{%n)GG1ZA3>?Li`fw$BxKOSZaCdi3ek}>;&qQB4AT12cuSYf(nie zAB&%z;2VHui}108a`H*cUm;G?JLhOwF&sQ7DjCYuNZWoQ`m6wNnnlD1?Vrnj-@b9l z|Fq%qI@=!{k2?`Xk?ej8Af&q zpR+9!pnep;R;CI0k^Bq7JCbig{2-=X`mnFhweY3+*}(NXZ>;lGI%5;Xout_ z7XJtjsNdO-5KcDuqzTk=uI*oaot4S33%m+xgiB^&EAY&q;% zizjScnBRv{9`HwhY*c>#5#rHDN97m#YseT0kWT)7!pK>mdaOrzY4Av`htaQu=`o&2 zz5>-}7sBTuY!?g*!_`G$z20D%6%4Xx(o`hGAkfoPjc-VxfLncZ-d+lPWxc2t@%3-`$h)c67U@D zI%MuFJbW|IbX8IW6OH*;#xgB1m&P(J!1I4uFP$!8nHD>TVwo1;GckPqCy<#D%e1g^ z3SyZS$I1waWm?2CE#69*7T%M%zr|f+5qFKTY>P-{LoD0E%J_(7Tg0+0*l8)-g57-_ zc@uAfYzw*mIAy&K*%owR|7OXykavvAyGFK!k(XiQ#6V93?uU(h5y-%+ep~t+@SBL@Ek$@W(K^& zF7Xd1A-4qeraM03xsBZB8*)wZI}@2gJ4@xi8`{q$GCIMs0%29+^Tu}p-*mnwe&nm1 z2FO!qkPTz)JnU1IBSZJK#OFkLk-VGC%8lmUpa-@KQ-pcE4=gevpUIuzMR^=@R<447 zd5kd12aNFP^<&7np)e|s?v2e`2jrE!k#bA)BabSt>>H`Nbua9`?s5{jd*xM$lWJ+}iR6H!~+d8@L+w1IW+e%cWn09dub9Op?Pw za#!+a+q>gI*zZaiEFF-+@;}*o`ye@rGr>E%r@N}Mx@I&QX+|;zSu^5eWCKP5uf_V} zs2MTp?ioo)LegTw*bExA>&cJG%6#&d z)A3g#|7qAOUGEL%itvI?zOz@tOgIb76?N4(bH%@MoVgY(ee#$BA z6nK6o*(rpTHlUH6GATDDJ%O8|X6B~UCSj%sAEk(nizTI_xgGk8vKNjc$HwVdDbsOL z)HO46QR+5^1GF^*SH%pJn0w#IERnJ>G|2pT!2CEzAHT(I6ger&Bw?WZ-ZM~w=E)f- z3I8JDU%XfN7X#R)rOzS*+#I2Ax_#JU8B#s7dMPnRw=7f61Fekzv#CCM@QcV654I~;!G>~W@(Lkbs zL<5Ni5)C98NHp*UH1L@%cf|aQWz+C4mQ5KW*H7sedAtkw7Z(K|>zhdr6Q9%YFQ(SZ z+2>y@osoa>jf8(OeOa8scOw5H{GQ=osDoxb)KvV7;BvEG=WOsV)Dpw9sPiv^=M4WM zxL|Vrg^GC@W?sPO$=)dc;&%4ZK9SS#lXU|>SubZD?4}d0PBA|JK%j;7s#DBIJrHV< z;x7A4v9FA)V*Z7C7w|9C*H7hN_`AmW7s0x-&%aQ+&6+u3%}cR+L)?pjJIuT%?2Pi^ zeUox8)ctTTUTEN6^qv9t;_5fYz3?lib1zicJlDC#y$H@h?uGyKyNr9WeeX%`g>z>E z>!K7|g);1hGJ6-mZ;E^;r_W2bU2)T5~xxfgzmY3t86_u`#kTnKaFZRK1%emdtu z_IHtW;APg)=fjs=d+|z3_5lz!wzPL=&bioOI2W&)cWL-*BTwO6@Oymf zbDnFY|4mpIpKM@VEH}^4$g(i@DC2wW{4UrQ>U`c)ur1UFSsRW`NnX|#vYtM;qJdvf zp{>DPm>2ySY$lm!ux0Oa-r2IYe*_MI&7LT>>=W0-JU5Jtd|KIMxrT6J`zU+3$((l$ zW`}SVY~m62fPMEm?R0bAOhu)i_|&BF)t_bR^sq+{x)42&>&Lf?Jge-DIDlSdAEFw2%@>((61ID_ca0wA zcgVZG+FQ`oUSAKu5E)~iZ_#DQURXuqtP;oD%@hf4duvRQpw8lm>&BTf3#85qvmji2 z`kMFpdiW;xBZ%q|_EB|aLBQI2VHWtT!IwDH&1Q|i|Drh$)|vUPnV2H#RQ>~i|eo%v#~Fe@|?$> ztwMT*sb53dupfl2BOH6-V~BlO6b}8>2ru?!4zfz!E=c{v_FBSA*aCKS6*v*98BWA+ zjV`16O=OtBX0Txjl_ehR%p`xxf!TjSHJ_fBjSLf&JKcXWzJZkcnV2OCwuY1gS%)vh zAm}mWAp9S3x#%0u-$s5&@V|_|JhSja{723%KO}r{JP*UAZ;c<~6IY!dG7~#QU22{; z_*?UQXIc-XEJ{5LE;IUzSRu4m;rSC-Aukwx%YKid@92HTyTQdy-eo`DJht>MHtjZc zREMy2&#|ZOP7aAbe{i2$4faL*Q^`I~Ha1c_xz1~)uDJ~?jWLtsM zY53I9>;>cc%5Dqo#ys|6WlYD?@L^?4$I|fsK4EF74~R`4^-0kta;Ow-oBV#uER7w8 zr9s>(h*=u)+oNCk(ofD3N8@(uHpZ5^8C&XZ7+dOQ?5LYI25EI?WzQwE4n^!N<#&xf zl5tB|8LJXjM)Y1vSQ&e*>!>r$2`j^HO;{OL^B3>dt#eweRgAmbN4vfH3#;|2;3ccM zt;M>RcGdr3!pc}>h4usV8=L8yuDR0BNx5ldf8m6ck+3q}NmfSL;@hRi&pNBw8+A~n z*>~9*OQ~qhvDo!iZ~Abw*Kd)sS`1D^`#;-hvyNKv%|F)T>){^8?WpHt2RFGk`$Eee z(e*IHeDBM5yUjk(W5glza2sTf_t#}(48R3mn-0Lkc zGJ*{gI2KFqkM<^?y*;qncCem~b}Qmpz-7=eM?uEti*OWZms@21LB_(=-n}hBx^-56 z#<$nbRhj->emcBvLfj3Ej5o(oxZT<_s&q%pAMd#1c5CY$i=E?)VRme~-P#x~bp4ml z21jAB)qdOUR(rNnKhzxB4}}YJVU96j_U%2!`R;5=?-}(o#~D}Xcyd!t#sg(fU%6&C z*KC|0he6iej>m2t?+fkqtj|2gTILPye&!f)w6hob?sRCi-x}ZduG_5*LyC9;d-p}# z-1Y1eEaBTFzQ`}g?*54H%KL6T`vK48{q+LztmnP9o;`aFM}fG8*6O*N7RO@-zS_7T zu=j*7=k{C_W;QMe?c)-^9NEpfqso50hqaUXqH;P87p)F>Rqe#v-bA`Szu4N-9N5P= zHWIe|&c#-gHmm8$a*h+T-UjHu2l7-V6SqmV0lMd$&)1@AQOwcc7C!=%gdo z$?l6hy%F7YFrL4MvG(J_M(Nn%9T&Zz_dOT+nGWw2&#%jwIFFZHB@B zwWANwg{eP3y;r93tPcIY(?WH zlQ9+SPX_Scm0e8*vkLsS>BHG2GjHoG^|Qhq$iH@fH2+)VT*l&rL-2da9^jktm8;U} zY54;u!%V{XjUM|8#!APW(?{7^qjq83u%xwy}|6 zAn{GgF=(5>G2k0auFa9g+AqIrHo`hwvQqsgXn?w8I zN%{{4TKEPs-tMgH*Uq~2+WGSIOoIw@e~#Mc-qR9ThdG=!KQkTYAlNiB=ODLUTQYCx zmV8&@a;`60mGIT*{h>E#YhYH)KKPMoud@OB1aM>r&HTU+vXApoj=tD!6#2VhA1t<- zc)xE;hgK8s_j=tZ&!y~OFCu-zaW^x+o)6j6A)rm?-EPAMZW6f zecJhpPPdaj@@D3kI+ann zfAL=7U!>0>`(mVZZ^n1lcmu&LZp6QUg?5sEp&l9MUtp`&$iI;9LTORbLCm{AmN@bu zybEM{5SAtVi9TeBW0V7n9dnJPExsbXA*C|ut{^QO3}I*lq(kD2(jpuUNlTrhA!(^| zG$btz9F3D{DaC0)mN=rcAk*98v>;0yqa1$Icv=Ds2^-TQ@2T?IO=Xd8nNn*QeLG2-lfOg*i3So4BpOIGkZ2&$K%#*}1BnLC9SwZpKP-v)7gtZi zzqoqJ1atkAev!w!fPeA-{K0R2Jd++KKBwVdOs$u*&%d~GM*hV&6aK~YWpN7MiTsP; zF~h&`U!IimoF7lwbKuAZEK;eW{RGGv@s#)V~^7tXpZY0-=o zYsQVW3T^#2Pw?A}9p}T#T+R5gX8c%h+VYn97eUOw2;K$!i*U!O{EOiJasGu`fA;wo z;Z`#aB;5P_vAu5iC+1w{tcPVjo4+xSIe-tcmY6x{3Y-fY=5}QO`3H5kKaRph?EEP> z82(q_V61Q8V04`U2V?!4<6s1LpU%PX?=sJIu5mEbImp2XN8e=}jHmwmBnLyvEjD9r zp?jw#M=s4AW$#Mu91JaCVVsK`4F6jxuc~PST@H`2)rV*1U)=ZjDX3ug>-}p>E)d zke0Gdy}%|@&0^jBmFC$dWhZPfYwBeU#zc04#NjfHDTnGy$?_Z7{gRH%Le=bk@Bz)u^emHU$H{oAMxf7mC zBflZM!05NmZwS73cKHp8wd!>SN4Vmx@f!jd6?J|?`7YWl+9`$Ec*NtuCb;~CP}|uS z%U1MXpIhjL*O+Gx;!;{i>ZhIhmYatGQZ8+BeFwYjkD2-wF&(fS@-H*xFS4D1 zouPh;zsUKft@f`q`5S)9Fd0VIsdN^9Um2bIpEN9n?DZ<$C)cHnyZVT^kNSxzCu&X{ z-!=!R;)~rw7$bSE^ZzIn@e3p!L)`v?*-L}y{d^B>5P8-* z55(hKcpyFuoFVQ%gzm(KZ;1O3u^-V8_ixm32-`x^IZ8OO>yvbj%DzQ}6Mg1OH@lKv zThfQjBg>M0WEC0y%%nH!bI{fa$7F;xXrjZN9O2KWXI2PzW;$j?2-9LZW>h{b}DGBOi*res+NKG4}A3K2=5XhIK3jm@IPN!%e(1_WRK~ z!@|-a$3A(Ho5OWE;^bmde4Zuqj)1XhqzL46@m?den9+bvb^~ zn2=J7$BNcsKV})x<5ACO=Vy!&-8NE6|4fnQG406MQ8!~k-HZu!GbZ##xD~eagVW^g zjuURw4_>D-wb7TN`rzlSdo*EMButBD-C_x&AYob*6Q%_` zkE7W4uUe!s6PX^(j5GRG!}Lg)7Jjz*g&TD9Y#$hH;Yr?i5@9FCgpvQ!5q0ULRh1xj$6>R>ZB?;1}Y@CcYJLMI?MamIdU~J$^1v z*r!t}Gt5z0>*rQ*UR&bl3P|yj>lqnW!fuk^(jMpTWL*ruS0XKrGRM=KRoaTzne1RK z%F}R5R^VQp#80lZ=7iZH!u6>WxfP7h%NotXT0bp*az7b2j^;WTJIZsEIfO687?GtH z3Lk(mrq}Ie(MSE7j$KB9K z-pTablK8%NZJCB!B7SGWEg`OmTe2)3lX@%Ml4TRPCCesoOO{!ua!Zz3XOCNAbTU1+ zgmN(@w`9vS+>$NUsoWA1Pn7rMzu|OjiMb_PCgGNFeZ(yhS?87z$2-C;S!PAtlJ@OZ zd%g;{1UV`6i^7g`OO{RGmYf>T>D-bxt`Ea4IaRl!<2`Sc zTY?RM&3Jpb(C|sZNf;)L%o3T`moRdu|7Ll16X(QHEg-*-8*NiLO*_Q6s@O6}J0^$tSa*q&KlaU1N&X)2K;-Fd+|SjO~hXX z*g^zWWK-7VXRA+q$E}o9+Qj#$s~1Ro$WDpx5m#R*@ga%VKJYD97bHI97Tjn1S)aX0 z@^^>n>XINMe13hIT#vj_uHWbC2WU$t+;4c7O6Pe7JJ{#u;pf;l`)(PT@AaeS6%LDV zR|@ZEj9Q)-`FqJ=>4w2F-_MLKc@Hgxs@fUqb*fJc# z_X=}GctQ2&5__F;@a;tF9VnuJ~7uGgrjDMjvlw+iG3ua&&)JFVaKyYw6=?cn=kHTj(mlOUdX$*9}^8 zPY1?BrR3|w_zf_(HOxGg%q11Xjd?8D2Wre+12FlyaK-qG}43waGat2Dm zzo=Nj|J~{dYaneEt@M#s-R-FdtPJN(M~W6J39K|_Tv^N&bM&qK&z9_onZ;evrU@%? z1^ybYVLwv7;W9^y*7o2rH`DW&`&9a|sQuc3`?bCFEBFr09DKwrdVw_z@9-(UTPwyv@p;k3qPTUujtq1g)8(ut?TuBg?}+X+nGL#42*kPH)WJl@FM<2 zuz#F?LBDQvJN$^Dm>+>Gag1_EIm$M$D^$j?E7CA3Y>5L|;>b%J$TYl)h=~ znYkCi)o+e_;a5)QUZ}Epu5*oh5uAhE3;*eN8TVrQUgi=*%dwf)yR(6HQ3|a>8FoXN zy$j$sNSQttxfj7>r*bcXM^j$yE1H<_O%<;mi4d9ufB%e)?kpXurI{eKdTIDf74F7CtDi~(~hI9YEO_o#Qsr-1~+MY z9XezGf_qq>mLr~bf^i|tg}0M)5j=i6=OUPbbD=ELE}S{%Vn@We2w#oYzQ${YPvKnf zeExqm{`I`Gqda_btc!4k$?IUQk^VQgdf_JX+j6KTuUOUk`Q{T+JRNf)B zg*u=26l{xVy*Xt!pJ9%d_4L6N4g7)%Z4K^u>?Hd$*i16dV9PpEUu3Hu!B)p+e%=;4 z&L-x$VPxdf$}Y<_gcDmo*%M9XylXs{a29Oh5%z$6_d4x#bIzK7yDi9;aj(JRFxR$D zd#zIn^yJrL6A;~-^{|uNJ9@sZhUfdLdA_OBQ;6eJlg3wnmZ{U@N7sv<$MxgeMV?iw z&F%nt_0wChk+?w@nQsc1i>qSSFwF0ecYU=NMoF))2Ur_BrZ(q9mmzy$6?w)gaTL&b zo!^kU)N`69uoC2X?M`$IpQPH;s_mFhV(dM><(3`Oc8MK@9X#yjInS#_Ibm-6_=$zN z;I_BM6bWJ$N4;*GDYHQOIG89q{s&KA^DgVRWj*|4Op$=K^};OhS%WWesGH3i|L{d~ z9;`F-T{AI7)W_p_G4vPp*Xz6q^b&kl&BzotwMUs*t6A;HtYv^M+wKiAm@aQ!uk8% z8sWvh%t2PE+Xbng*j`I`30r6i?F#$0s%97_zcspy?g#Uv!kV%Q>686cgw0^P*c3@T z1ONYx z%SGRK{>qvg(Rn^R;i`Wy{_@Q7O#UNhmmd51EM_qArb}_y04` zcc%4F^dj{zxXkFUN*R#$%D-R&E93>EZ`tor^xeo!kTpViZ0RHB19nu0u&c|lE@>x6 zr1yjS+-d-mK*~He`8GCEJF#mJ-h;3*vTz)PrJ)X)v^R1d6s(;-;Zfl4$Nm!MX)KMH zi6MScF2kRu&Wxo|Gvz1TW9}Wa7(Ggv@knFzoNC`mK7_}!hA=XOQ86P+umZkCc2}|ScV`=O#EDhRA6&x@u4f*ZS zuYBnzzY~r|fp?CKW7X&*iB!s0&26i#RdW{TRqEB;Dl4$>4feVrT%%`bZ(7uT_r5uP z=9z40-^aQ9zK`GPqAlK0;%ea=?!FI%cC*Kt>TQ1Z-se^NzC|k2!gt=i%l+)p1%W;5 z1A%>A(`LQ;6_sw0_19e2tZsGh=U%gTpSHYg7zHga?X_A??6r;({%E+*U4@+Gt+tLX z_uc#X?JwNoVTf+e!e;bY?kS9m(A(mz;&&7e*Iq}TTjG1akL?;zpz@b3SP3B+ghx9 z>BIX!G^~j0_%6IIe8~-97)t-H&KiL?k~vDBYSoo~b`|YrJ>FH@T6Oam@7DFWg+sOZ{kq@1E20SKccLD+>zO`&y9Xb3 z`%8TPv7YWw&pvlVz9n0>c!%gKjW8}XayMfTX=V5Gt$1iQjj$H$Q0GcLg5LXCw>8%J ziIaJm?_#XCYmLr#vF^TWz0S9_>EX5lvIEJwF5;7QN3u?FxNVJ&*6TCYY0eALH6t)+ zWv}3B&wPD|dmMtr+|PLO7~{XfFX``^%RPCfuJe)WqkEgayi$kK``rF;A#3_K&x>=wr9`>OXs5Xz%%TIddF&oHgaLrvF{fQ&4-YcI*$%h^N4N zq#pJ?!Bc>15Kh8Sh!_ZrBL&wP&O#$o!K@n|pPP;t3x}-eJ8Uwxg8fP6dQ!@+rh-`o ze%tinWDg#he|47nS>X@lU%Nk=2QG3h?`z=^{9ZB$7?XSDs&sl<4#CMVYHAiio2A|6 z@IAvM2w#(V6&b5#?ufC^v%w??ZW?D2gr68^5{UcT$s}-^na7&5UKi*`J9BP;YrwbS zoEx=+y^k|zW5g_|?_+Z0V5q$(L%otC@1M>w*oprsECcn*ILmY6)_NgWajW1nFUhzgj>)TBn*UVduZFO%%RSs-A3k-Wn>vyMOKk^2mY=2 zBlE~IvW%=EtK!bLoxK)!WFA>XmXY}lxNpE6nMYQUWn`XmXn!1cWFA?S^QT_QiTy#1 z??Br*VSdBLtiil26DAKM#J-7ZXfN`}sr7M)R9)gcV4^F+C0BacLskM)f=oC zlz-Xe3pARQ8C zlosJ=NLuO~4M|I#qakT&;AosoODRqZvcwUk1)1I!rv+K!80GMr#?umDNZ6Pbc|Voc zZc6(v8Wx8-Wcnoo*bAg%E@!D#WlF7K^vxt`PW}=NBpOIGkZ2&$K%#*}1BnI_4I~;k zcQo+D|FHB^G0Wji@h`Z3`iFU!@GoZ4!^G!I_!rY>`@6|E;a`l88|&rl1Hb8nt5fhA z9tgCsUUe$ucc?{*yXJep7%X%X{>7sEBGXpK>>bdI?@DO1Q0oqc1TpAkRy3(!*T#9iYbl{*P59Czl&3VtVcdHY=db=DM% zp83-?uER~{OcMTuwqy-!9$SWC#XJ&rjY`(fQg>P7ip>M-Vx=BGD7uFA&fIU2y^ss6 z*)B3a?>@+!WWv8l_!sPjBy-c!mL>cP>J4?u#(tnO7;0E3I$B4Y@GlbnMZ&*eV}Q>` zHU>o{0q;j^=@|atQD-%9~CB!aBdVw!oN_NgntopMPyAGHic!@9z_h1T|v%X z8bs~rJ#a=E*&-h2!WQup{)H0GP(kcdmj;<)$;tF%yL||rmlHnhmSIwvbM~$Z_jA5R zYu4U+P0BtZ3^2l07`rILsFL4DSie=~yQe?RKA+@+dtu?VZWavF_tbFJ9xIk2y=p|xfIFNxamtlv`Ol{v4c+S?w*>b@BN-;a+uV2Oc%%2V0!wT(H;jON)M_TwM@_)9~i+Cj1u})-;JVV&2m?N@A{^<8ZEo=9W z%GgcL#GUXjTC6&U1zkk^6c__ma|nlJE_@L3BjO#<9{K;<@Cc?0FAM_V4+zhog>uw* zJVP7Q625NS@PFoY^V?_KSH?4&C13s-)&XnmpQR0)rM~0V*$Uy@DcB0Ey>DbIG;$Rt zG8LNXC#ioj&k!*aCh!tg!AVH?7vr3YMqS=V-X#2sasEd$TtB~R%98LPnrWZbTuOgu(F!7#nqd$3z{k;vVXNxrd35_6uf*Fq&2^zuCPX?#TUv`yxC17VfwDl~9L= zw|XsvQCaE>zndQ~TE;KX;{Ggc{C&^wvzoWJYGGNl^uA=ZKGc)FmuE2i5c2;iU)Q-H zA>+9T|AKxJ^9D6^Bz>+tbwSo%=sfdR2S1#vUGs`7{j`LCp}b*Ow};_VsKs^8MZ&+x zT@YADW*fGI|9-=k2w*`*dY#$i@OT!;~L zAH~HtoI8hi>D+p_gnyCnFI2+6Ncb1lo>8ScV$OBP9b2recPw*`(+}uiZQsUlp&KUr z3pe3kZ1Il6AV~NZfwj8{HU=z|7yLoJfj(ctzrZG|VQxC%U#QGaDHn4X6Mlp-k_-8L zy?WTa@Z)~wTZ}jSslVU-JHF$@{rO;@d*Na~^LMykPh0zG+~nFtSNEnL=6K~K+ro!! zp`!1)TNt-rM3`Gn3zP6K?BHg%#+Z_GCw4@4bD$>&PQwxM;Se@lzTVS_2FS5Nr>TtB5>&cB>V4-=o$@Gqv;%a^aX ze97e>z2c)cU-i)|FE8G5<&sa|x};H4w|(jM%fEWt=Ffd*3hk}>{O1<-+ITNy1mgKnJujSR~i5EuS9VKoZD)p<^STVQ5u3}Uyb7q zkv_2->3_(Cub(UU#_ZQ)OIkGP)bNru>)-X?Ji+fK_T2GRKD^A;aFaFMWQ}b_5pJ@E zo2(nS$!~;z5nR5-8-{}sbd%=VLRW0#iJ3v|t9ZOOVjwZ4xzvkBM999rZjyafC;`Wb$Z-@D)>D9_T)N=umP+VQN3 z_prf=D~@o-7Eid)_5-BzH`sRHpYmi)iygoRSWo(4QCHc2+i=o1Mf-3UWbQ6tk9BNY zWgqs4Q;j|URIKVo{zbSo*2Q2rD}QXS8~%woA7dT$Fmu(SpD~YljSsH0WbcK_;eD=M zQo1sL{DZpNA4lOr;wa-EN&L+@apLZOWs6r{f4f^*`=?fzIxx%bS{+@JZ(&ZHV=T2< z+f{A+TG&UKFv0a{FVAmD3wEPC&*t1PmGuFX8La88Apkf;3Ehl*D9b=ezgzZ={w z`MsI_%Gv*Uwx6*N!E3$CJeSUR)=A!l>U0;#x(Ldma4k-{zk?hM_3T#9PLWqUpX9OF z3`?5HJGTf2VoZ+UWp`{}Q%3f}u%Cvp@gQZWrmfUr?WDe_9O{!bEOiJe?3XHW+XS~RaT2!DJ$;5qGiMRsL1ap`CaOa_Hj==qaE~Yg`*}-vX=faj_TqY zb&dP~&y;WH;ZRh2KzVEqT=6ffn_c7P=-OJ}mFw-h{ig7@TfMOd!?cRy6t^+bC2nJ+ z)qPxB?q6~IwSMayjHmvb`RmYfY;;4KWRI{y_fAWW9QFgb-j&)pi2qt`*;~=cm*E1) zu@xQ0^{!sm?XYawl=tC~`b1m>>RWA)J;_#5#x#1>a5->ykhPxBt=;9P9aZ6(RXV_K zyo|g3l8K`%*K-Z)&2l{d$#4~MTWV|+Y|;0_DX+?P+U4-51N&2+#9Nf}W({AS@Zsm9 ze5_Hg9UGhKZqw!;Vr@<(z4@$hFv66YRh@srb=DRw2Y!O+%!MuCWJA07n#vT}Yl1a- zEy8pu;wItkor`i6>@uqJ7v*Y5=N8JqE|p{72FuwwXxTTb9PO3mT(QHF=PqDlK$~V& zcs?f`%&H-41$0W8kJ>VH;-K#udlNhSt~BwRqr!7LJiqc<9OA=ob5w?fec^a5R)O#} z(j;~bHP!~odd-N7ahNs~_o(gUnmp~PZ_{qDS6ta9PuYLeUQAoY`y~|HfBx+AIPd*@ z&i>d+tGc9B+i+`0t0nm&`_ZWMf#|SR$+8!FR_K`g2wIG+xZFE_w%|$g{;lVuw9j@( ze60^ydD5qH@WsLGyu)t)sRH|YGO8z7!ydN5lg z?rMfQMjSQnXS<#yYq*=bJ;&~r{WL#J`yXVLoOgPbO|^SoM=lfKoDpIDd+zeangX*c{=b7jd7o>|_Z_3Pxh<(ce&a<5t}n|-_OERy%X z{oFz~{7S6zqRBIR)@rE-y1K;D_7AR$^k&b-t&1)KX|ua7K84i~elqPz+Fs-+?^vVH zJ3^bl@9O(QyJ#=Tkoxq`W*b{D3KU!QIM}@P3E6fA|@b9(g|LqZDB^ z$s_1LoK&Zr zhfzJ0`e{?{<((Mnl$Tm0dft=^NK2XaAnF&fr>}pdc{XVmDul04S1WNoh3iwE?V>wr zqtKb?s~qf)o>`G66Lp)F^za@Qov8fj{*$p2M8DFWNO`PqAE{gQGAa2ou^vc11x+TO z{H)0*NmrgaEM<%~#!`QzqBMm6$N2l7GWxfvCpLAW_T(mPxVBlf1FUJj*t0U^lcXc6 zZ`9K$J+!lV^bpkt|MI9l*vt3l@}y6~H`WtzQ`e2>x$OTLJy&?b^)E2`mG&gk>-WsM zLznaZhC1%1efkIE`VaX|kh)T(Epo{dm**&>Uel4u8#-Iz5O|++(sX6C=NN;pZU=rdos*_HI#l0IY}S(fx8tH_Ww z=#t*XG9kJW9q#1tf3Cdj1(fwzU)c$I@@Xgf@UQDhbmX!|>>kMjx&9w`4*Z9>UUWS) z@%o>Ue*8!AkJ65R@Dr1d(ry;If`nNyhc_+jT~myE^vn%(YHp|p=OG!>IB-p1^`t_3 zkmCS{(w?PKaC0`vJG*2l`ojK(-Il-mfTeQyF<#=^p`|>2XOPXF)uXmssmnQ!-|>sb ziq>NKFVa>h#)ssa@n?K1-ZoN7|4ea@F}g#H3w1Ll)XkVsH)BG#F(%Z_m{51am{4~r zu)AqzkXCnA#*#wQ{_yURer{pM2{-C*uTz=Y=u6T49DYl?UnaEqXSNfYjG`xj6cO>AuOj>kdJVb1Vxqhb3Mre$8)wWjM$jex@ zNM%|m-w`vze<@<99F_RLZ{k-lPwqYN9rx(qJ{R7K>&N#A=zGik>P!g3WPm3T=jXlK zuFx%Ri*+yg+LCLr>gjqTyosaO^-KCDK7YcrfZb8gU$`>Dy%2teW7wAFp65E#qRbd$wa3pos~NK#RB8I;)>ul}GIl1qs^0YBNEb!XL2$yY z^4vClk$xEa80+!%a1Y<luQQc!~EM&aS#L;?c9IS2BtY17O4%~_jZo|9- zT;8!c(lA^Ka=GP>-iezRJmMY^$^NHDNT;{FRqrHyM^ZiRJ#D-{Qv2K;@OJKD{LEsE zZ{6M+4`TUpDi@}dr|}zOTv746$ZyF< zO?)fJM+u*gWdZqgkDtpE_UV+$40BZ0`neUH*OvIqUrJchUl3i_+YwLNkvkuV+M1O} zi=)i(^k$W|;JTaPbeH(oV-yJFGqF(CWB#nbm&V7OOqmsUKoLiic=x zL%5JWVUBUWJDbvbM*WPiFgl*3ep0pq{N$S5T(gmTMPZP2x8t!}$NNHiJ$40>h7Ik0 z<`{9bXLeY-xo>;@zISc0HVi4^3GCe$ZFAQ&;wI;}nmW|}e(ELhZ@ksdZTwPCx}CbaAzRA?FKqSN zpVHP3Dce4C0qvB3v7M?e@w4`MUNrY_GbZYH{z+8lL+0o6)Ya(whB>ubns1qP*a9G( zcs^gk$PxTE%d`0=68nKFbG_mB!&%Zcl?fZoIrB{>?V|XLeMEuuiT^M%T!I^RYEC!b zVeEG;ZB{va*meG0U{#r)aMsX%9oX+WH{joc+>8GKY!v>A_ar)uY{$C%Z1sunxRsJh zoA@4e^#X|x*(vco;_3?}J|ywl2fpR%g2ad1g8OVg>tp92wouh2LBD?lrSm+49WY0U-tC)xw~Wm9(w^{FK-a?@1@bO>UgSFL3w>-y7V!>z zWxmS1Qt-1E(obpoFF~%Y*qeU-THNLb*++R7K6zm+yg?Vb<|99WUmJdF;;`$G z=W)J1zGkDYa$mlWVR`VLl{qV9S$N6Ir)t-qoK=#x2Uh zx0$;Zzc2mn?=|y@-zNw_o^l|h@ z*g{tUU1ZR~4O+u>ac;uBPxh_X~Yrp)im3ur$=Sb%m@f;zZBXZAczIXDT`U}{h-K8z>OYDV(j*BIwqd6V= zi@GGw!m&|{U70Q85n`Vv_F<82826X+0%7z9ba8#rs)VmbWwLJL6I}B(W8)Kcy3P~W zzM&g?L(!@ZB1^_br*2y~KwC3#6@9?<+6v>j!)(A@BS&`7v& z4w=`KG9&YoeVmVS^u=zY$j102u1T+Jh+pEKES@Indedi@SxxkxwxvU>iT+c)td<$e zw9%3DGsoRbxz5v8mnqwdeu6!RGA(rjS(Unhv|*c6k$GgoJXvn-`PO1AT;^!e+8#XSW_liTpGrR#<;4!%ukEFO!S`t9;3IC)3#?(jAD-g-)#BUX z5dJcb^wi*fcRT$S$(wq-66f~Pe)rnc?XK7~i5+G7nW9ztMUW|_jD2PO-nG}iX-U1S zKa0d8>EF(`iTp0XcNkgt2|av8zb-Faq3>y3uiq>Divh;{(tgECcZGW5^A>x8?9epN zyaGGGi42T;S~q2sQ}EK;AK;z4-|a(|IP&!GMv>_uzR&5O_906gqa0F>vRy%1uYIH~|U&;-zTJTKEtN|01v*#*r$FnH4w^{snUt3I8JDU!<|qqFyBY ziy&QrRWbI@D#IG!w3F`1)&|40<7gNFLG}>fwQnbW1U(K_CT2MFQW15 zgnz-DXA^aax#NU?k?=1P{sr|RW{*s^Ha<^XN%$AJ3=^An!oN@vZ>BnkZB)X)Ncb1R z3W<3Rku4MUO=9k97WSKUn1!W54twFq&FS^CxnB52y}lM3HAmKF zcJb|xeV+8q?qN;I0PBT>0W*Ltpp$+!8&4REVz8T%(>XTHyk*xf{%?4~Pt` zKw;C&p;FjR%WrIYQ|tvlnD8&GRdW{TRqEB;D%O$SiydGHtLPc@-Ja{Wg27liucM?}ayT-y+s?+o63g>w<+hFbm$mbq%}$xvp8= z>fX=2X8HTvmY4Th*I~2X^3qEKT6nVWt}qXV}*&(!v2x1tP{VkNk#D_ z{0r96U%4rR^=_1}&9Xj>_4U!(`d^kavbJ8<)wjS&Xn{|7U(;ZAH8MIEw~p8iDQ@@0 z=g-9F&&ulRM&wSjRhuG>p!}{ukf6?R!<0JTISO@Uio~3_1OMS;e!AE*wPdzkn_-3+Hn-chTT-|XJc+Qs_^_eFCgExgB9zY^;3 z@K&#dFiNT zKC`ebp1o3KeAWxgHFb_i!oPscdho-!+BL7R?t--*i-f`Y^PDhP9oVZ*TaYc%rs>s*EFsp!|)3qz}sML9XM)!4+#S{>ox*%z=DfkW2p2p2EUZ;7ia?v#mye*tp> z_QVm^ON}7ah4u4ZE$fL!;Cjfnhs!!_zpKutxK@wAsqj1N=PM%C!U$`QB)ki!(Ph21 z|ABg3@E2e))cr^5{t5pAh6UVk)}jf^BF`GM;kH7;zo7n4w&s0Dx|Q{Gt+vy2=4V@a zq;MPh<8$Fq$oZeDZ|9yzO1mQ0&JI|s$=XWcIaGMxI0`O1jDh0atTCgG4DhE{|j&X(yaeqG8=U%wj&-@+k*M|$;Pva)+j73-XrXS{bCE;Hr{ELKt5q%dm z@+#z8N#=PI{sm)D?Tk~k!poS)_!KgaEF;UvDzb{SJMeGCADKs%k!55RSrzxS_%mNp zM&^-KWEq*?fIIUiWn>;%MV66ym?}2&DP?3HS(S766T(%h!OOIr6XrMLLN(YqWy0id zBFs%(!(3V(Sw)tahp`z)D~Ed-!(%*;>urlL$UIW=S@w46Vh_iJe<9-oJ`jg3UJ8bX z886^G8aEi1J*`2uhq=r__$mjKVNRI+kIeOT9z+Qp3tynlw&-n5_!kNPVueol7gVX_ zFVR4vfkXp|1`-V<8b~ydXdux*qJj6c2EKU5k{Exn?DCs$|J-TMYB&$ePIIq2aDDyf z%V~+9j7}VUgqkjik60hdk# zaInx--LQ;naN1`Z+v!mDwcyYB)gZQse#Qx3jo7Qcx`zEmuW>$;)6OOi%|57b;`Q*K z1-iyM@xr=0wPr8WiPy>aYUKAo82QWI>cbE6dsm>fVlR7#{ng=HYll5jC)~pZU#;Z$ z`W8?49`*yI^EX>Pe^-jV${3qvE<0F9`Wct4!qu;(&kp}W?KV0P{i#WW`Gwov3VSKYz65sf z>gbw$3u~)6#!{QLU4^49el4uQL8`0MUY_5QmON#p9B$4H2kdXdIuzM6TE?PffA&1( z#y&L8z3?lN&+x3V!4kVt`;fL&**urdc-D{ED_yg@eNlC~3wTDKGWd;oe&(e6(yQ28 zs>@x#8W)`_T4Ut7&cP&?{6vQEhb6rDMdcy(*Z2>|VaB+J@Wl&0WmoNs?jh`P(WkC) z9d0sy9z4sM>QpqA9_6jr6-$~KYj=w&(F;fLvOBh~DN{`;+kTpKJV<(K+DgTC5MuW> zj1EL<;;N!6+3Ua!i`d;Ra-}@F2Z~l%EpmmC;vOtoHqTd)-%s+p)almvonpUT^lbT0 zn=}c#{xOc~;v031`~T0BZ|9pi@8Jl$GZ@@0EcO@+N&?=Mz?UZ5BuSIX%$KHxgz8q*Ec^P;6 zB@;(kuIC!otmV+j$#4~MTdE@abQ^uC$5LLE>$J<^X-hqt@+97(oHuLcSO|}ui{xXC z`4)$@PJWAN>kqNcssgWK_+UZ1quR1y?mMrsf6?HZ<6gMZ{$)eENE}7D8U1P1BIUM- zTL=@w-nl4OVII6Xe^IW6bZ#NPcPaKr;`h!$%f4CVXp=1GiXE0bV}bR26*+hoCmqbH zAr*UZ)C%a3GA`v&p36bMHP&m%?@ANDIVwD-BlAn_??{~ZZH~%p)JA(PR)O#}(j|K} z*02kced5JWJx*JRd(=j9jjTzRJvL-rdYNDO@Fmw?Oxq>z5zDj-XU@6cxnytaSIxUL z{I!u4cJXL@zVI)Mdp+-D{>)~+$7y|leMgWBcd_rtUh?!Ip8xAsZCjun)+LsCUa2qT zxpDew$NUv0uhm>5{crL<_+;9XdSerZT5g^}^jbh~1>Ea?mBCO`7POrstZ&%k749WW z@;q*3bn|wxE!6qEr@GkR`-7e%j*wm8NVpmS~;E^tfyk^Zo8TT4{2AXSIr@huGp|eS^XK#$?-p-`gN6**Q@O)o2&o^~?3UPdD()jAn zGIe^`H-+?wp2zj$+eMyLQ}zeYtLz0+>%Bo2XeemwibDmd= zawqrOxDEaAF3$U}M*F#zSw|yt$@S~xeHoRXfc#V~md(0RJBy@GWk0vj4L%+BW#hVG z&sr_*j;=1TwEY9KUxz&#w=O~cf8MpbE~az!`Ka%~R((#mIPFOtc#)&dwUG9r`u@;v zTF~S~&w(wFlwX^*B|$Fb<&l1~so&~m!#MC?H0QxOlOB0K>Gu_R|H~ujKjin#iYMLd z{`iT@bL!)9y3uFUU%#&2C#O&FS>=TV?m-+r@1lUi=KU@2b9vv{ya!VkDW~~jRHlDApv;wEczSCfcN$;r%$VUe|hgM~Xg4gR}`!&lQJHT(-2IQis_SjLk`$ zs4gx*=U)hQV?9)tn&%Dv);!;t)d zgUkLLE^C+MUFNdyk$e{%Vl7CH^+!87BE28vJ0PIHEoGiQf(;*FC)atc)HOHdWra&| z{&RLPX42lsqX?Xo*N1-}{$cDdaoXue-8}nOR^@w)GOG@mav*+EF8!aTPHR^tD{EoR zT<7mG_YPW&9;M89q%nF|-Ts=VZU)D$f(?)i-)AqvuG6yMmm(G>F=^d(d;EZavOLx8bi$ zI)~8RPyp+L`wx{)XMXsvnRJd4Zj^A6&QZciIz^xP(#@`<*Ov4l^T;w%(pyD_KQrlV zEEA`&G^nH53&zkQXWB(tN*N1;yPog82wQsU-v&Z58jOW0A2t7v6F!B1oC;j-3 z;vc0Q|KKMkAEn(WbOl*wX^<(FoDBVG`w;yZhwqCr?__hXbb+?A%zIhSQ5mmE*+--g zMA!;#Wtn%h{60c|sLZ>%pZYvTKFD{_0Ow=$eWedqk-VXv7bxFy-}eSfV~3@rzfIeu zf&-Sy(Vvvx9`dE1SgP5xden9+b-B2k_uJyJqP3WJj9*ituROWh4)OWmo!?xu}FTHRS0OEd8oc<0FP8hs?==Bwtm z)d?$uax2_`=bAR_S?%vEL!*Ar)qFFysL*O@V?8+KM8^15S)siuyww#>NelVu(_TdE z5{vce9_zas_$1E|b}BxJtVcikeb$;2_fg^w*ymQ_Za%O#7hGoEO9?B(uvVH6?zNgj zm@RzAHj^KsGuF~u{{J@X_UnunbQiH%8pEGtilE~b%2DI-4Bz@K;p@f?|7Tt|zkT-j zlJACul@aq)?le4=mb+s93Nqra#OKe%=Ph@~{>aEbJ`etJtM?4Q?``@Ex0$`jeE1{M zny#XcF6DkQwnM~5n1(wtk>ilCGN=y;D)9QU2_j8#e;dCqM)_$_^^0%Nz*r;>YAnnK1U&Akh|jC)PogfYgqn|#a4we_%? z^l18TjC)&bifSw74dnWIdL=vq%Lyxk^$LEs@`f4XJ3Jd!+hXMnpr<3VSL*O$743O@ zcy_-IE~&e()^^&D`nvsua}Pf3_LulRk#CfqeeMWtl+Ql(hv=t`Fy=GD8vQc;=YI11 z5b?W6e;)qCS?6EKH>B_{)J1ikMZ(H3%#g{s9zk1OPwTWtIX=?4-mpbxEAJk@osP`j zs2lYi>6-N?BkV}?6s zt+VP}j{aSKI@qi{VRsB?e7m;J&k3hvWENvD|H|AWGW?Yt^;u?bhtB8I)Mu%`X zbhs&+f0K7eu`SGw!GSmJJe{0L*c0K6Q``&oliW-F+}um@OZrKTtPeS#EY4tq@~)55 zFKMqWy+2A*J-xyfdDH2=ZbICz-ACLeZSrm_+vYtd@4GUG?62-zif$J24x?=yd);oX zzxO2h9lN$zdq$P+pgoPw@7Q8(y@M&R*^{^9sZ-bRw`V)`L(K0!#D4W5{Y{@R$2i}e zP3b+Oe&#rg&W+6zG$1fo_&I&G)sJuUy$AX5kH!vUeA8ObJ67s#Iv3; zg7x&1+qtg&^Tai@R?pp3-(%ZX8yPd*6TY0=b5WStxBz`f{BmSB>kjN5nkFy}+KIQl ziF6Uyp60+l#<7vG?RPG-qO@^s{aoT|f8Y4Ia1D;1N10>}{sn(f%e^fle-d_s zF;=+-q_%IW;pmvhI4d@U@C zAIg1kJ2qte#C;xP&{26_b0Q~F!bRu&j?Qm2b*TOQ)Jx*uc&ne=_@$n7J9T$Mww4KA z*y^=ErL7-Qj(o<0MIU05Q(fX`?ejbSxsNWnQ6{Cd}**6zg7Bt@)Fv zEl}&2lg8a){y^+6G=B9tX-DQi4qH(;xvpB^`tOIcq@5~rjs3~Ms-_e+Ai=Bxzis+( zVuK{@lC#v$7D!wEwfm#_-y-L7-7s$Ju<`P-#aKlD{gwGD^Gd9W^9?U zExCnxkVV9KOPy12GK?aOAH8cNjOb0;^ztgk)Y~lW($1E9rL)S>vj$M;w{_%`!l;&-zv-)+vF*bLpxfu5W%YU>F3a0uHic{fEiT&%H< z!tjk!q3pSY4Q{f%3g0RNZN3gaVMpI518pm`xYuxB*|u6&=-c*p^&&lFzt+r6Y5Knv zbX@2vpoD(l7`}#0`1I!H!GY=qK>w>s34?q>~x$t8@0^A)NMSD91OMhWT;ni)W3&^u{qoshI;1#4*Y9RVr#i8NW1%kbXmQE zJ=(sUiR0$z9bY8;O2V%syu{~VTT~A(-{1x6gWZ(EH<*;A9BHim^1D{< z@gSY!8OMn02yq>$-}{>Hos3I=0Xwj}w6#*wMBa#9kSFOs7-;WH+LG~hXI;N`)~(mh zm$ldv*<&1Hmn1epkv$M;k@E`W*-`u4ds+hPFo*aRO3bTlK+o3~txEW6RPImOA8h)X zu|EhqUFV6SC3?3v6s_tYvSjQBa_hO4_}!B4N?eWcNW25=8zf=EADQ+#8!*Skksah6 zOxYVk_HjPS(HFaoBC{nkAC_glC<=${!%gPC`eL_HWMh01*QD1q#4mAA7Ecppyy>&c ztS0(A+tQ)cM4zW#H_CI#OLQrH!*MrLkMgunW$KcGm1NJM4oO`^R;4Z??Ky-)=8-n> zl#zL46&ii(UVPb-R8u=k(5MM9QMiEoYDk|H8dC zb-O!4dn&e;>1T>o=@&t!lrlD${kZ2iYOjCOk~X)_`;fd$bH1H#N%>t`80e9OpU}fs z^y~7%75bjm_4>WSzexKPE8P|9iO*VOU%sJfo_8|##YpSkjPI=R27+7M^!5j^Ief(J zLzX!5>JfJonI3w;7F)GGWQk*xLu}O|od;Zl9a$f;#F1z2U=*1i?;vI4#H$$0*0iw3OnsAWIxk zT9D~&aaxcij!_Q3X*?|fhJ=l2smlDu+D&Qy#p|N_1HH^NU zB+bcRqJcyMi3So4BpOIGkZ2&$K%#*}1LuwgKC|VHn16BgH2jOJr%W){Pw5wVybJgj zsoxY{nn@26pVRO!rq;{Z=U*&cxb%u8CvW)CD?WPjRUf@_T=%|G-}vQsKT*8p$|aw^ zb;%4+lJU!uUrJ5nUj&aC{zZ7gtdE_Ff1y5T*4Ug4{)Hd&Eb9CV{}(a;V%g;U3;#oJ zm49*jTjpN`G5;cX7w|8_9jEdyg8Rq$7i#_4=U;?d%{Y)SEAq$oy5XOgbD6U~V-CjQ zKaR%i4EJK+q#O+YD=-4qH*hezX69f7*S|RqMsWA(91Q<1^IYc|2Sc5M9E@=EUBd%?S4kHeRv9;Lb7P@y@a-3vh9K;_M#<|GB2p>L`gAwje&B(z}-ER*EBZPHPoqxi0 z)-oqN2%7<&y%TJVx08zz96p_k;ZMQE5Sth2Yn(Y3qZDy5LdWDs5c5eIxfsEd=KY&z z-IXu_>`3l=Q%sET)A4;^1Vw$KZ*29#|J1<5h}UC@T~S``k2oXIZ^pjG)!d^{iVKybpzOG z7Sn^-B5Mz-8SF8du(@~}Sqf$u zKM=32zT2!Z_dCq}!_S!X%*1N&KNqJvW;OVA=7f}^|EOkUH8|=4%YjRhdJD`3;nvu& z5UR8NOsE_9BBZ5khxjpHI14-3E6uZs9ZiMsmGn3}AzVKVJApizsM}N63Hj6gCtJ^+ zCx0TQ1m&@UO>Ciw^)YdolzGlPWmW8VoCcOc&=fN@vL>IzJ}Zw6P?_-9{#oje%p6zv ze~iEXDU%;I^+XskwI?@W%eBp_9Vlq~V$aHuPm+%4K5$N=^kCPO$KEhvm-v^X#~^Dj z-=E8qJ_+B*G!Zx9UqtN+evSMF{{o}m0%?nw6yH0${07BZ^*S3TT=CZU4FQabI=`WO zSDD(i8u9SSd>?$uP>ko>~0E*NuC4lVLGruUF|l+yiCOsXk)vqkdw_iJB9~_wTtM<;TBq zLVPi^DZF7qe6hPQM)F)2ZcIg-1xd#c_shZ?7~=4M6{m;#Bzy%)&nW(V_>FP|zcl{A zhvIadZDxfx&a6;BH}`7f83@y&&aCibf61fMm=#BizQj+M74q&b^SiNqoveAG7BRiJBS`R#O`f~qcQE_zx|Gx6~AE)ojje9SpnNZ^8RgOR{VSh zW(DoUw9E>a7Sl2-U|J;13bDHktUyurIaG?eEx)lLPqANw)_yS*2^+8V9O?i%z&#~mUT|+Ei6J3 zNF@1%xY#%j$r3D9R4vKY>DHqq83?mx&CqJwvY8~<19R6TckV1ovawEgOV-0S&k$_v zafZwU2!`C5fr;<$+f}F4-EK=53*uSx;?;C!IGq-vJ7UD_+Zz&p9lA@_JgzTDLp9Vz=>+F5Er?q0nN z_iqk+4ZRPd3uJZjtkngwTI8!2vitleIV(P)^JDfJujQ^>Ck3X}Ns)g)nSZzZzSC)8 z>pVJ7_8oo1oa{er(4S&r=6^D0Nszt8l(JYoUzLQn(#JH@uQkKpeLJt#Ee3roJG*pC z*y4#Uk2dZGH8bX|ek#$;jCock!?jb(c=gUUExH+`oNbvwyHU1{a&2b5>2zAePN&7O zH;47>pXY84cZ24yLRaLs!H(pf66;t&M^diRZ|fa#Q~mc7rr5K_c)TYr2WvQM z-LHy-@wn^l%i5Wok3Ih0H{1J5RoXx`dCuNx^Kr9xpE(;m+7s&mbV|tD#ptn3#^iS`Xz^a;k7qc_6phsg9r z#Fu6IA`<4vR%Zlv;0EDyLmx*xr=e#e&h$)hudt!BW3ZvKOS~C$Xz^3 z3w?x!v?Q|{{+v#WkoyIuaI=v+sw;W#>)B#;1Mi_ekF#F0N6MgZ*!1x&ZE3PDii5>A z|18hJ>*Da><8g5V&x!P#rZJD7*z(Mr_gC3 z3-v!Mofh#&rqQ0H)57Y>ki8P_Dr(k+tF-+A<_V+!J~lpeSa;yo&Xf1;VpqkkI?2xN zwXlw!(idek+NRRrj-%!t;}ja$RVUdEFa{Xr93g2K*pY}E=nFW+$}~)2qx)_ zmbK}rw*XQGvv;&C-;V%&{smbQFc<2ajEfb-_d7M zIaUa(-KtbMo15P(glR!V8n;oo-_3iKcWHle5BWyguJ~V(n-$C_dg5>eexE3)(g06w zeH`A%cm0|e-TvYiI)s;TSH?Gamp&o9i~BIVufp_rcJn;3nX57R{gQhbW1m33%8l3` zpTSMSasj?PQ(qu%cAO_3yT^f^k{@4R$<}H5O17e}WJ#{CWNW6cCF1tu=qrJi)mO44zx(^s=qp(=O<&29Y5Gc*cvJP2 zEb(4HeI*%BKE5#0??TthMd^t7L^5K&C~f+pZIS4?kg^h87#E?>LgG!>mk?bk8-K8~ zbP;Y}oZX_IxwTjS3E@BSgWaVsVm87(gWJVj=+&?~H8MK3>AX^3 z$!q7wOuV&a_S5Ps$@P-N^D@08=?uC{ChIB@-6Y~ip5)KG$Y)P*CLJYKmqdCvJNG4V zD0JIX&!q1fz!W_xK6>(lE7^bK?xE;d+RYdh{L92Uj;@4Y9ew}N5fi){_a4k)+>dfb z;nBqEq_Ahny5sWk&p%>nJ5({Fcf{zqLJxDE(0kD61ws!Ky8h7zjIIbh%x&1W$K@Do z5WxgGeoaymz5M#0OL)xRmhguSI7Z+VB;Mrs1`es>3i9A5hs_G~#Q0lcvm0|oZ*21` z`d38XN`<{6n_tX-lDb!}MEA=1^sZR<^XOdZ{?*X6B6@-*#_Uzh&0hyyE9$y)x>n+A z&*@qb`=6z*71;+}fv&LQn3MIUOwpOboM%F33Vx-3o~$!vMtv#8Y5G#sh4rP>XV8@* zdQqzIxVl4WyQhP^C>S__JnuTcj+FE2L%IIK`cN8Y3s=(Dth_GQeUj_DpRB7y>cTz! z?29Mti}Nh!UF^PqIin7fpSkXnC6jcYG-Ms6obHoY*U{6o`?rv<(M9CHmvuAh)(Xty z(vHzxD`)j~r^Bq_sgkUP`5t~SS71t+itg=hFdPs6@blih9KUfMvdTR4>(AS?)!U4I z{dwrupZEB)R{xG*8_v67mACnl4u-Hlw{1r;c~mXu*L~vjU(~z=J;I`EprJEjSK)wH z;=AcY)oT)a%0&TpB+v5opY#&;3Ch?j^hk-W#2azf=rwHUpeUWJdb^T`OsVG~^LX(g zTNd}?=Z0S73+AJxV-K2Y#GDj;hmSLV^;qv5!+j;s^GDl~DnN$$>a~yCSa2#+Pa2#+Pa2#+P za2#+Pa2$9I91y(^?_2t7*Ztlde{}Oq3NRXOuSRmZUWixtyZaS3zfcy-Z&>u1kX z@P3bq-JHy>(7(wD22~H|ebi;SKkQP@dmP1#--;dY6SQY|Nw1J_@=Gye)ujGn%D3vA zS^q`Sp4rEjP7P05y#i0HV!yxs=CB8Sl!`NaF;5~7_x9L%<0LEpxpR?rVxlvZeK|iV zvi2CS@(R5?ZE>+DQKbU=c0H=U+=H2=k))ofdPyRCbcxshzgQbXXJ#+&#WSpt8SZRw z#!z&IB>#wRUDhs}z%40`=^*}F;YF+py-i->=_+YdMb#s^cMqe}HT6{7A@5jVGe^>D`PklEj$BF137rtd_N^P2UdHvh_z4U+j(GJqoM4FQSou#8h8q{;b zFJdMSs$cT3*DK80;idoJN5}AA690{KxAc1+VbZVXVQ`OyU+CQy-o=;+&qNv;Y01s> z#jNa0tjm_#+jNPuma@+*$t`n+b9t_dy4=M(>%aiAV%KGsbFTBo^>J}3-B^8rJDJNl z*IACcLl2twLeo>=$Gjs7yzBX%r}T|r!U+9F*w+%~oZp3^r`ABf2>nMaJr5lCCk|e& zeRZdK0xbA@uTlDm^=plP$tOLp9lwQw_RwkmL}9JTzUOI=JEu<^&Gd0h&{p$8PglJg z<4kY-6npf^&uBll>UlBwAWJ3H5TQq}t+=x;if7qgYVN@9#+U zQ633bpj{^X9p#CyCbf1vx^>;tpjMKby^X=KwlxW647Cc*{e3|!ZE5q*9`WYmFOq# z9{gqTvS0U@4s4ularxL)iPzhuiv1E_POl$&#m87z2l}A!A;m3}#8^??9 z|0Fy}=%1APISx1uI1V@tI1V@tI1V@tI1aqd92jJ7X!7$lX4xulkh^r|laGMG2ew-B zqLoP%viKl#!pvXFydhTBojY}soZvUOgSUlqV^4g>e#_ifbYfMQE7qAG)|o3-WUk0s zKn*kCyho5CZzBWC8Iqv>oQ)?qjczpVBLt_JI{gpMq(DdQ0PnBcfZ;~C@AY$ELG=A_ zp7jgh#-nRY;+M0i@&wB_n=10Z+y$%>hsJNb1-Fs3wJPc0Zbkj`oK4-5Se;z~_k{I^ z#Om@=oHexJSObtW#!EArqw)@IeNkp|*U+zUKBb~Yz#U}1^yk~6I_GQaJ4w?H);w-R zXVSOP;q$v$+AJTyzw1bl>x)NQ1rJR0{7Am)n8{}|{XF&E;F7XF5NP6OW)OU3b0|82 zDtrr#8m3?n+WbC}g%P*pGugXpn50$li2s1|xNU^3!;1>(->(yY4QXk`F5ayogPHuh zEPT+*-3+1k>HOP}4)Q42X%eTDQ;J?x(Iq5)E4ZgevhN!25@#JVc`&o9{~Pl2b@C(S z$vq48KyH7aD~$gtv#*G~q!lw@?x`hReCv*0UB}M8N0}eVij ze()}|0?x4rZF|;R&CA{iBjsz|?V1ekAIs95+?Sc+CUFFu-F`(pljD4~cfw0KHsYvv z##;4fbNULb(s^Dbef7>>9dFOv)~3&f4fj*5wb-=hd8v2apoLz&^F}?C=U@0f0N=$v zrOrtC55RK?H^HNUjCPm=N=o>100R?Q;qn0ql(!btcS9cx0b#@!{+_pooi%)Qen{cvW#T758- z`|SskJ40FX44UGM<{yxjANkPUj9U!{HAk=yaEDF-kXo2rz1`oKAU2Q7J9z>MFY`Iow#jO2c{W_C4k ze_u{74->Q!wwrc@ncSASsoS$UP{S_1HM2`^$xQi{bk}jKkZvjOpe>I-H*1)|62_74 z%XOW5E0V{$*x_I9lSml(wqdag=$jh-T1$K4@5fHsL;AL?UsLbR;!ZFnZi!d&DetxB z#1Cql!-=}eIY(PpPvmv=P^=T~21;E`a=nhCf2=0-8FMPM2hnp`lXmf3j??|FEWQBD z!63fhtjF)@yu?4l+H!S4Y}CH(QRVK$v|}GU#W+Xb6yP2tn~WOT9_dcbg;U1$4#pQL z>-8DEdjG@p!4EUueA-l?T_fDUY{o6x^(bRmtq67{aa5MZCcQT+yLfdLwkByIpPKwN z>Oit9ucx$0?qg`fSXhz#-j(H7y*n=}cqHw1;O>shkF;OPQ+T5KGC!lVcU??cM@d6v zX<}qNku#um#?Zc5^szRb!zN%&tHPs;%J1vAL2KG?EhO*hW+Uf5ZJDaPAElgYwCi^2 z!05$^-v?bOvx9B@dW`(ku@el=QNmZi8m)E|!8N6QaknWD-t}ka=GEIX9tfQ(catQ2 zLgx&0D&iOEA&74^6*0+!_~Sh4gunLoeqF;~wS_#&I7m7rJ)`)G-?=aIddDt)B)~#sW;{Hh1Q03jGv^V`~5mWX3*$65dRX7gsF7gsU?i~v$W~s z>wKq6rqW2S%)TX^l?|IFXbQb}w-=p3rf8Bqh2PyCEn~fN@aS+T`Z}5=j*Gar+M9&Z zM>qPd{pbxj#S@d3fqZ-!VBFHlpBd379PtPZbcJ{)!9b0;-z3?OyYh79VdPuvZNK`` zP$^0_o0F%8&0x=F!frMRIOVP11s|3>rfs{>IYQqT?uvDrO1hI z-%DF%JiL_0_Qj8PnWQHl4+vj>`7@^ZENxBtY1}6CJLYbejueW`oaf%h-Q(4?6WedY z+zRw+)D@XC1ijCNS@>teOC^57TKi&dzl(8-JgeWx;!U}yp6~?o84vUQqJaIPfO@5+ z?I6R@UdrhHC^qsh)^DYrfuD^r zCH|&w<>Se20eeC%hwh}pw|GI*8n0FE#x(IReHr@N`Y^M8P1?UwgB@{sj5?^XAH{E| zkZbrJMHg?lL3?Apae4IE`*ax4r{-h3q+Qx*jsC&5V{1-rd-YcG(?;HDztR>fjDH%L zr134|VM{WS3vb8#xs%9+RqO|N`WVBxkKvE)=r=1F$48NGN0DC#823hZY|ju0tve!v#WOzhH*E}Wtmj&sjSM}!mb4-Bn?5=^C7ws{E)njLnB0% z>%%l7ag)p`%!q2Llh@jgq*#~v#<%}C@)_%@+({kdvFS>;KuhUL7wIYzCp?qBF0g$a z?UDQi!e88NnnZTEKGSj9zz(tFeuCW1Sg(;^s)Z3VYU^z#56M_5eV6)Dmi{F2Z6B_h zGr6-oQYa13ABYT8LoNuc%<+Jg#ZsO5T~0rDPj{@-Ap4H7m-=*1?<#u1oE~nO-3{7Y z6M4xu{x~X=-%3AmqyKgecaGIQ71haSmUqT5;WM&sUCM|w)@L2?D?FnzCqve)UPija zPqALAz{4u_Lii^#Tpj=MS5(xV&;rS$gioH!zUL&YrC{Gj`1?dI`J9S6gs+lM`cH{d z_p(OxL(lSJd2dCliFf)$+=3MUG5sn!fCr%w#LPiuJix9Fe}g2uCz;7wS>3nkXvkTt zCp6?NNt^n7Uf<}C1Jb9tzm&d|#}99Ds5Vh| zUI+etVH*EV=KMo$dbKhNW*=a#e6EZJW+|DYS{5D z`N`Z>c5mC3CF^4|gi9XF!cF!+hd3sewfcBo*3ch>##3`Bf7VPoiuBe02A)d1)Povr zO;acIP5oX4{#W8#Y@JBHdah2SUunEgtrO|IyiR;Mt0QSwAsUl-Sg(>cknxT_FJ|o9 zgdgHD)O)GJW5_Jrk)4of#jQ>m&otK==%$ZL9x!9nwQ=hFIAhUD>e6V3(xc2-U==mv|=ZEsSfTT6G=^aDHTZNy!$KodOukTB(Oe*E~B>iAZyv4NC ztKO5H@6fIEAy1wK|n~pD5y^b$csW+-MZ7Q^`-F25fIIB=>efui!ROdzHD;w+E ze?9WrFM;NQRr&z&r1xj#aDcip#Ck>RE&XOKZDNS@4?)}VLF`{hOiKR5JjD1Zep7Uc z4e@@;hD*%p&bj1qn6>THJN@#@UI%)^){@6oc+wHDZr7yzR@PQpXKm0MZct%c@u+Sq z_Um@*MqRo(3c8j?UI$M*&uPl0jkc^|_tAi`{ARDtT|)1pgn8!~HkMrM8&&7vkdn`APXSbLN&8RB;{SzW6(U zDdFrpJZY0WG8bOQ(@qM`lDhl%`tlChvtetGZ|DYWe{ab++kfk~{Lk$XyemoFRsS)ogN^)1TOCINIw9>fNxZf6MWfdy6Z7bXd?@*q ze2MHkxRf~^GW_5cRT`8&VW|qM01Mhb@*RH9u@Q4b@Ua|r;fgJ|3o?(X*+Lv2(uSj4gN@9KG;pV;E$x!@`rh+q}8VL z=4t87`Q8Zss{HMoIqfNT!X@qI*Ry=e{M_c_5B8nQ2V=K^&p{XR5Nmj~E$A~NZ7cIU z3yz-Hi@V5vwJqo@dxg6y2|vVL{JokVkrNE=gUDU4=BH5)q}`vUezeS1wCSYWvT45A z|I+SK3-#tS>s77aSH)9Jg;Fb+E78ul-1g2`OZiG$mcFTlHoT@(D4x&n8gxJlPo-~a z>!#0{A8Go&@RUltQ^bEN&SX%rkC6jT;dhoDlaxAjttz+9@3Z~QkkqZ5j@9Q4E%}~q zFL`Ul?F6(>s1d6}^eNi>Q}hKV;ES{&-sQU_GDJI%l?~`Sn#ou5ChTad<4>oib}SCl zzw@IO%3^%J(vsG3`mZ7QVtGP5H1*HY|HWnT&RB>{r)j{^ul_98o5| zQTV5eJ*-VrPu1p7!mcY8iZY&@uT7ib=fcVTjBVF9F`p8eJBOf?+H?$Vh;5rcK|i^d zNBYaXv?bP^vcBM@{!*h4Z^$xzigs~-+;oCI*xawIoHD>Vy3iCkMf%DOw5?8L%LBK> z;jEJKpDx9|)E#M`l6LXaj(Z2s#~E*CQ+CfF=ZS8yjrS;hW>*~EM7W#&%aD=rW!CJt zJZm;4bR_)Q55?ifaGy2&oly2Zt$XfvX4X)6wloy3V_wn7r;MXA_MN3}o)!6oIxKYV zBkoS(?xc=%Qb*EDvoiPs^Pf4KeO})GyeUh$F=h$x73C)7n6&2K)Ys(&+}rbS`rqm0 zn#|7Y0leP`?_|&8Y0~mE@owDE)3lMiwV^AgjdEUBF0fXRyOUOllK#xry*AdG+ZZ#~ zE$=C|)9>54@i*ge3|eE!&Bjo-C(8W+b#8olOJZaUl=@35vwY;`KgK-5p4aI5c2-{| zg|lmqj8o<FyTDJx^ho3DW40|(Txld-)tt*Ka!^(UP$_F zTAqD2Ok~eg(wn!JMmZiN->j*WPT_aY78Qobp)xL=px#N{8mHb4$vgRzdefK(wIYAF zmNu1GX^GbIZufWppr`3iW+&y@=xAOmPkFPx5A$QRwWn{2!_FVX#i2h;*aO}cJ+rY; zeER!*zeR;IXL)90Pw{E$@F`^8*7&e_rl}t~DRff*J|0`Xl;1N83dJA8C z8?H;j4(z189^m^l_NOpA=BEBx@q>Ag=Zx56N}7cCPm}&^jU-!#k+nU|dalgr*=L;S zf6m*75$8l7MqPMKvI%?lB16q27hX_4X==4R71=80ypiNx>Y>ar8ud`-4q=?hbO)x( zoyoIdv~z)((x)Puv3F(V(uh7)!e6LAojhj`=qE>+O9>C_(|L&7DePvF?aT~3T$RkT z{YoZVof``pe7T_9_s&=6?JD(c=I$4euV2dKYvHfl?GpZq+%NoXPguia@2SCOsjsib zYvg{v8Cmq?*+lO>%_0XBZf990qK5db{LgbFU+@A=o z+^*Cf=1P3~;bXDoQ^Xw>k#*u{%C--TSdW%(>7%6WslUqXCC%eL>(Rs|Je0LSIpZaB zgrJxG`d)T;L~cR;i+00JiCgfKgT&K(Uwe;f2^x$(& zPiQGGqnUgr5C6zHn(?1!b}8m$n(3eB@&DO5zsbML!{avDukdNlXZKFDU2$_i#{tIy z#{tIy#{tKIf0`UP!~V2ZyU^8qJ?k;o2l^@%T>M5AXtmSRi<-R6-AzGZUQW&-qsKiA)!Bxo31H88rmjZi5N-Plh3_2;eFY=8j8kEol zn!F@>xnni>mBzh=Sea$h?l+{*+qr^L$t&(RG}Zy)A7pZ3aNs-EZ}K0v*>gb^_QQj- z-wwyQlOCpjZe;Ena7VndRO#AMPxmoT>KloRgF94dEIAyGrGIDdsR!Is4_FVYvzEOe z*LA=edUhrh`LI1|-}3Q(uLcjKe!OrCd%%Lf z!TSJ@CLMCdpwhic>k{X(NXH=OGY2I-xK~I+2%pA}b%o=c>j~M*57u)|Weex9*K2R3 z@Q^1^H=AsIW<<)jJT7aKewBC=&XFZL@HuBdxcW}s2{#UX;lJs=!QNk}?Ib+$i67G& zYbiT(_QTe%(5dXoXxOr%PTz7*zxTqbelL(S2CP%nSW{E1KLmz#$-C3mcnLhjuGUZd z5-0X`&bQTgPamb?^Q{*W)<_+@oF@1|^E+22{$=p)a^k)m^9sx>Fa@K0F6K8_Pt(a3 zW7AEU)wsuEXupH3*NQ1+G~3VCMa>1=ZMi*6JM^O9$BLJWGwmUbrRJZxQzKWNVc1xpB5T(2waCDu9P z6wYn(0@{(32|Fr56}lQ8>LPrHpBH+UJ+Q8($eYL0%`=~86dHZ(%jm_CSNI8NUJQ*( zc;@h2%CiT0V{*O_dUEzx%Fe)tLC#lQDDH;8=`;r>rP0!xyUgoLzY_*mQP+x(m13!* z3nOnP{)_)l5x4L#V4d?P;o14p(@2BFKSnubeF^K4)O}e8AE#UlFgoZhYTdEH?lVdsCRpPYbQen;HO$IR^cSa`yT%OYtL5B= z)cx`z^pNlrd0Kgzcr<<6s5)#0Nk_bdv4g(n1a?v0-&Ofe7iad6Y;| zUYPk?xSO@-_&ebV@;d-66Rn|q3woe831w{~Wo;v3y-NB*2_Kc_2Sdb?7^D45)C#wXQpX)n_D#80D+OsW5z zBbllGPj7S6>;3fl-bkyIe`Bngsb0w)5$Piu?LhKBwf=J#f%G@}iALTUX`dYLa&zxt%#gO9wyhbpqO%Qhp~kEQJYVjh#6DchACgxjgFA1d{w*?lXjdWaU?p|X%21eg{ZZ--vezE=*rZ*^*e~~HT4)a}Z`L+W*XKKVg^yp>`2uJJ8( zsD`{!lYX0aJqj(MBmMZo6(VD*(g1#{`MtM5{E!}L{{ihkplwKc3+NNFa$3hbbP#_A zx#G@HWL-JesD5vIG;kGt#v2Lq#>jiJJMo{q{%|P$zv#*uC4N~KZ}AU@vPL?1tf!x6_nM^~0%I zN&Xh@zTXJe*B;(wfBMAtdhHoA;ept#B>!VKZZ=QCkCx+`LRs?+SwkHs?bT`l(TMf& z-M5&K`XGLzWLVZrkv$J^1|s!BD;OnImuVV@^`w zd}@3{cK5`F<8Fi|tc-g#p-q{IdEU4`n@o+nJCA!qV&j%{DefZIp%eTI%KTWD4#v8| zm0gLql6oMtEBCC^gP48bFd6dG2M?tVEZogmHuj1nxedOv4r})VWxgYBq0Dngb8SbD z8KW-MgkHMX7}6on8OYKN1c)&`wH*GL`tH-l_a7 zT?H9WXlC@E3oU*26)S`d(m%Cvv(Z!vsJFqB?++zxK;5lTZw+NFa(7=*`Gd$&Qg-q# z=5Jz-v7aUH@6PSS&3KvJZ%wl6%k6%9lHDM7gI{gT(NcI7t2%8y$j3)}&s@FP1e`CE zJCyYVxkC+m0q58z+X;_FR+axJD1*I^Z88g~)3?q^%Cgse8TtH8`rb=0MHZgJBeJmE zbrD&3x@;IG>|GH41no@L&cBwMU&_rd=jLDK=2vp_>$&;W-27|IQ$O^Z?LGy(JHZn* zZPqf*MaXDhgLfA*hFuOHS{Je(nH)Bk@cmxC=V1O@%u6w4tP}s@SI)|bA8{AAR`R>{ z(+a*EkTd6=rhUqJiGVg4&?W=gByy`4&@QFEip(;3ZYTZV+P_Rqo%+W;fG{{tze?HH zW$wovh2VQhxdPuC{GDp2RKUH3;Fz-W4dMTJ(~&-E)3K2H-@1XbCGb9&kBmhdt6*w% z(5sS%#$4|~{PlfW75CsT#9hYS$?;46wB&PA9*35uMzDic;y*}mm%0lLxkn`BAm^V} zzm$|#CT+Mjx2` zcVsa5y%*XM{EnnAlC;OK9A7o#s*H7Y;+Sc?lm4%dGOEs_Pozu+7|%xe9>8A8M8>(S zY+|*jV~uxY&Rl()`cAl*`o8EZRqx2C(l37NlzEYMb%b?`^r~&qV!|$tQ*SG@zBT8g zdT~dK_Ym|iqHW#I*}HcYQ*iVi_QYHSFFvugP+UZq+a#_9+oDB<#Je4O4>4B6+z)t| zy8AG9>xACI6%U#t)TJX^5NZwy$KKtUei+dj+{t@DQz>67=7xz5i{Y`p{IRgK#M0UT@6!fC^ zH_rRT%BC+RecX+joIY7AX{7Ns(kSwVr15Xy{o?en`I|X$>2DUM{zH7rd)mA$dWi4a z$-_enQh%njW_c?XZ^wOVy5Z55!x`T;9rhM)KJ5Kh@_uD9GBw?ON%%1I)t9$N?}NsX zIjVF-(!~2>=EhR5ZX?|?UP)RP^*10OC@wrcY(6ny^d~+X=_^Cp%lmhPi+*Fsd}7X}+J=osCc?^^oTU>#WTali`MDaQ zC$y&Xw^45<*NGPi_hMD)#nj71z3`PhFNzO)i+Xqx+FWxB<2`9A7fbSpUXn$^!$q&G zXN|I3JgMx2{zb`V^Wx@XTEe{uUsCjuSl&12@BWOXFXy2o4nv`9EVClRnGQRD9Z?qa*vdX?9AC^dbY!I!<7+Pw+q=2c1d zQ2WrEByw9FJHtF-_l~QzVZJWzvac#(q}=N4xyspb+22ren}T!c5Lfqe9B>?P9B>?P z9B>?P9B>?P9B>?P9B>?P9QeiNz=u9?%}<4YN%-?;@RtDpa^(2c&s~TQ)AQ-@FVA1> zzcjAR*`8%1z3DXkOVuI!$jKD^OJy-96EzwCGMxecQvEt%xg*`6J(HPmzBaSZ*1cXU z{$+-{DHIy(W140nAzQ`DcF|mtvf7CY18scRN_y^%#7`2H|w0YeeqLJ4hu8miTm$3 z;5gto;5gto;5gto;5gto@JbFi{7dk^I3MlsFF6mSxi9+Z3?nHp+#^+BapiXmL?4L5 zzf4;v_ri(*mrs7{Vy)kk4mz3o|NjdyWhkt2hLeAAY{7Z*_Y4@-k{-sh5 z|MI8Dzl_1XEP!F0V#>VpeE64%nTmgzx9F< zboiH(F*+UorNh5;_?Hg<(&1mCmG46MM-Kne;a|qT`uLaWYs9}y9scG2as12VvP|}W zJ@GH&i!z#mXZp*If0^hXBQMkNFJtdq7>9r9@GmP4|I*=KvQQ|x-G7Mo^*U;5m8syAPI z%`LZHa{*A&bHV<}zx{&aUna9YV(;;u!?(5APIa7V; z-tVRV(~owr58iY}2g(2byr)V{UTI7R4*#-Ed+LKmy(0>|>sNXA&QtnE^(L#kcmj(u zUKo06jdyQ*5xj!>itrS}vt10hbUON2CC>VIzZ93IQ&b8f9dcqX&(;%(&1m$9scDxoXF(Q zOju03h-dKVaCovQ@lLk#9Y0{#%j2#Lle;nA$hV9?^&P4hyfjpblFjDisbMqNvzf4) zP4fS3k6OQ*=o9GZZQB)>SEtX0;jUP>snlyu|JJPTj7yb^65lLM!p0hN{14lsL3G4Q z{LQ4JIY_*)xW-%gIaORqxUksbjTH`u;-?X2e`j1i#Z!e=UvFwOZQJ2rK4|ti{7YMJ z9sXtFB@X}6_Eir5(&1kQ;Ksz)7qasVS7oNfy=JdC(c2>3!ThN(Vn*8&bSNFp#y;kp zn!RK7rEJV|_?M~_#P=KB%ND!Czl_?G#8dgYL~>Hu?>Wd#wb|%HO7AzdE=>4Ux8K7i zn0>&n%{t(ZzWjOSZ82eS^n}N$xzkV^g9|<=Tj%E6viKhl`J7H`1 z&2TQ2U*SDVi^IRvMdc54D{Ybo%vf^28Hb~FE-UL{Q;8{)O~|gqy;?mV z?wdbLx1=|luxpV~m#FB(j#%%b9yF7Nlb7P}vc!u^+oF|CvA>r%M7CWeaW!p=q#o=i zy=zF@zGWrdaBqpTeo6c#q*MGMFZ&`>2RjJgxj&qYEjfOv^kvi1st!-2HKY#N^v2I+ z=~Y{dq)FuaMw}AYYfaP2ok}-f8=EA^`pqe6TsAe04*$~OUpo9thkxntFCG5n{?4S_ zvT45A|I+SKOG%YZv%b^%eN{ZwR4BDBh`eZL?C>v{$BfTU%0uwQ@}xWR1Yars-`k@A zb3ExbD{@{vn&l6}#aw?}Q5?X-(_WX}$skHh=f@ctR(yxGWd8}Cv2%&s`RiEualmm#wr|FdSt z{ zMH?jCeZ<{K+?~{sPU?umzf{G+Ev#YFPVCy_h$@=53>o#K?N*+4_?Ie_ImPrmj7+pioT1ZP5ntdr9KA&2jjb4*#;>;a@U0 zclejAKRWzNS*CG6#{tIy#{tIy#{tKIUosB-%HUsKp6&A#R1}oTO+oU~A2a8T)!T$$avWFi@+!O8PwKzvTDh<6o-3+!h(ddQ|#=3C?~y9DjMI7p8x1 z#yi;m;$C=VsnWHjp6**3hkYY)agaT+vE*<#mj0c+XC83RJYYSno_@eAP=8_PvtaewfJji?L$&;-5<^N%<3U~vdf^s z9JZDWo3y$uN)!uCAZ~QspUk1+;cd>vn0`A@m_urPE ziD13wBGNLx7!1NRbBq6F=9czk=Jc?VPpuAkqnyz*PgcEwL#jA%EG@tAiGHsJk2Lgd zxvk%;933`Q-UoQ}!fb!L(!EOSQsnh5O8voNe|Zoyz`e3K^+WhLeyl4TFL4eqqI}j@ zy>QFxjE~uLvl$~kp>29&9jw=0;B!`fSE2)7d$tTI;}`Dj_ikC!?**J04cL#ZvDT(o zmk12&m3ODD@scPIyIOyu>pKaHeSK%DYrLnA(jfTO3khqa?p<#A{ySGD{$=p&a^k-n z^9sx>Fy~^<#ry{AY&zLuq&^wWV>(<+hl_b}Q{-L3Gl%C=9*2v$Evob$F~P#ft6^4l zKIm{UQ-_P`a4}{4K5SMpj$7FZ)1IwoTopNN4|{Ji?%y>p3Q~Vt)UqfFM2->}DrCGH z!@r3?Xa;S#xD?-^qCp8;MwUUg)8!VgDt<0uJnvqo&AiAH8Zx%m=cj%x9S*H*!*`AE z3i48|8+*YsUXuEw&=NWU-wRh9HsaUfC#GFi9tp$`=?UgDUiMzCgLK5&7tj-A<+qM^ zpgid_$P;&lRnjbH>5}(uj|Q$net08c-WYjLb|?Om*B=fwX^7jmMGhCU$&1$g>~JyT zEgXfD-@K-vfNra_cYEY;F{%GDSLjgee2smH zC+y=_sJB7-r)G?LY-FC`9}a^j-ycfY;8;(o#vZ+4e^KP^KG|=)GPP$%wK-^=$L%zuk{DP|$}FMeB9=11Jc zt(E+){j`EF2fRu#^&Bpy!^OPK;bJ;mOoxlvl3j$2C6{{w3khM_#F468y^x@nL#CfByKF*Ip3+@>34~^89siCRc}l z>8CG$%1gQbkrX*&8L#pRy*zDku_sZb0w*+kRDZb#Q_WrFrDgU!=bqD(B3P3NXOlSR z>Gl6F&XqN(sF(L5Sd+>`fx0q6txFUn|Cr%UHmQEE$oahFTcVR9R)yXsukdu$i z9=WG;7(IBYr{X5BSMI^+Y;Si5@2Sb&kBNQ$uHt2$`fgH=IsetzPj&d0Q?V=?d^v|{ z*&TW};HTZ;UrLui&9>(U8hld6tDd5cO?-1dY^oi#m5XK)HuDqX&XM4_O&8d|?}-zy zXH!DG94e_c_VKTd%lIf3l=AyKQhk(1!W9%c6!|;K6JH&li!YVN^ZK|Y>R=r;Q?ht=nH);Fc)}f1S>$D<# z0Y5?u{mrEvn7wMVE*#^`Mb`}Wj}sqp_uwy!cZ*Sv>A=R>7MG7*m3X~fs@N~_<@EZY zSA0x+O{oqFA5wv&UEu~DFTPszvMZHv?@0LM@GpfM?&mn*IN&(oIN&(oIN&(oIPiLK zz~Nsy{L6yFzqELl4*&87E%+7n&KvbmDZ~E^(8)4@?qab|cV{?c4*xRo(jWR!G#m3D zGo8Tdkxa*|UcbsSH=irL!Abr?W)ThyD#2tRZWxBx+o6*l7Hnn2HUHwm?cPTdM zy;&WMS7%{s_z!BELw%wOCT-GG1qU$MmDf`+X$KC0&$5N_?@+9hyHuplvcC21Y+bM3 zj9ww}b9YDPNAPQJ$^G*#&6dUZpGdB8eWg-3J0 zxv%2}i|10~eo~Nbw)%f8W)63Etvo|NQ{zr>dki)Vx{dmvEA|K5`t=z35nLY82{lUi z%AurK1xH47qX(CeSK(bhYj5&`D<_Q z*ERfA(K)2mhzZD-)zgl@_^lc36jNx{g&z8of;k!8ij*mOmTPU$ZshB_yiA~1!=J;y z%*L02&RA=QfBC9do@zRlr+RJz%d-tk&gS^PSv=1%a64tKSn6YvV|nrwiELNvWW9R_ z<9C>S$GO=eIM%c`wSh;%elKlprk=~)|6mC^1Rn1)Nl(^aNcj58pE1p6X=}M#di_+l zOGgUDX65iN1G{&kl*7MF9R6kACLR8z!@qR+m#S0+*Fp%aj8qvHxUO;A=zU+VF+^ja~-TG2Uns`Dc9mFX>R|Mkdg zXFlD&V3j^VJn8+}T=@X)Xo&TS)?50`TE>AP(mzD{Eg!`Gg~X)fPs~HCBZ%L$xGfsu z{ge%tnA4qe$>XqTLr?GNmtXceu8YI9H-zUQJhwVRho1`v(Jv~xzXrFU9}~VuHzh`NiH`0Znpo!>+z?y0 z6KSgV@@DzDx>d*B(W8oWs8a@3K&Q`ulNl=q<|OUtWQXJU8{vg88`?^B~U| z-cMmZP2H8c^)wiub>;(tu_Eg*1MHD$^c+{D&QjMK_3ylW82!jZA4c7^{ZVHdeblhA zy3o5-$uRejIvydf?=7Mixk;5)V|Q{{Pq+rVHPG09ZCrlxo2n@Dl)czRISu*VKVOwv z#1wm>f&SpZrdE4)Uho;?A8wDNKU3TjkU2&p-7x_U=w-jYH_(ybc7uN& zGe3=bw8Os?2D+c)fa8GUfa8GUfaAa~9S0o#r4(7B2LEv?)=IXvvn`5$kjaU`0l8n# z&*5MCm4(a=k&$Z)Q@&?er4)U$2d~6wnejjFhm6d zjkVN(`J%;S1(QuM69hM{UR@n7N+@-_0Or26*x{Cgx_*f|xj8?EAXX3y3{}gcx4+GXeUu*t^XXi^#BMlP2;7i!@ zqZ|$U)3QD;Fr7tqhNBo8J|?YrM*bo6F-eQGNt~5{WeqmpWf!C*Zb-9y^&U_V_E&m`iJTDDh{?q zQnwoIK=MDe{&Pox^f&s6M&24}pB(SxIHg`oT^7ug$^Fyx_-+3*L!FlTEM-?Kvd&8$ zieN~#@-*=T#k3UcNVJUIwfVG(7%b_wVaj*d=&lj^v{-wje-1Avg4A(b#;q|P~ZgBXQebs`+pIo?mi-}E!L%)adZzZ^^tYh1KLfJ1A zx3B|wP-N^KJr;wqhQCU>*kV=6`7h~r7ao7eWZ~av>iFGrc8y8A+)Z#@@gw1&juu8Nc{7WvHk~G zte9FI^s2?wGhm`|Z?X6w{`x+xihJ-E;%?>gN%2emwB&PA9*35uCVpvqv=aZauPJ+) zLL>Rn_DJ@TWbbkHOG#-p?t33gbTi}L$wP73fFIgN+|r*({9-ozHsiOMcnMctZF!+o zGx=Wqn9|L8z9;vA$$#G-2@ddHXh-lnV*Ivwond^HaaFLM>%=h=-m{$L=%b9P^SC=o znGG=Rj`BT#z3gWR&a;@DVo-}Z)_6ze%+(J6(sTHi4*$~OU(!c7{7Z*_iCE-*jsuPZ zjsuPZjsuPZjsvfW0}lW4HL=Tib{udVa2#+Pa2#+Pa2#+Pa2#+Pa2#+Pa2)tQ!hzej z-SJc5UlRWO>Ha0azZ^M!^>Y{E!}NSQ{LAwf`!9{_FF5|C>imekr`$Nl(J+(t-2Src z99hGjyDVOTCswiFUw?CGvF^CfAM+&ga4#eEF?mwX$fTW^qGJo)SqVC}9RB4FFZ~BU zItC9*V0cd8cDD3;9=M(A>%#At>J5*Dce67-#+V6DRt`AZb2pRB7qfdrC2%K8;7*n} z8*#Z?Tm(J@x?1;R*Gic5Z7MRD>b+Uq38us?@y74Z z(+IYs;6hgMrw_$V27JiAk+f(|XiqR7Egs}YGOWksV75jnIt=8VV(O#wf_P)h8m4;A z&(_Y~mBklaOxnQb5uKf*+)F&e+H!RPD{=d{$9Z>RL?@`jzl?o{f61NVIZ}_Q!# zQR#la7F{9|u%81ZM@6Bx&J!T(t@l}37H_ATkGY}hnG)6%PX(HYua zlk5rn?)IqZjp&U9gR!}oc+C>WMTu{ElhEpt&DWLDVOs|4r5ux%fs(_&JcJ(nq%-du zLSYbhywPAL^p(%w!m`!Dq*(e(toC6TuuyB2l7kugKYi$3&K8Sq3KV@mu@-;N`b z-2(Q3S`OVwg>UhKrZrycj&(X{;+?jJc4V&)Gwatj*?k_XgC0HH8v9ZFhAKq|mEa{S^@HSxT{PmIoV z@w+K;_?LOPI{ZtAf9dcqmBYWh41Hr@F$7@E)w(d5E7a{b+-fY6IMMhns zq7yq}y^p%qj4X8WQv6-USkByfCF>h|sb3QE@ zC*{*u$-649W4$i?QQ*fL;k*=_mwx@ zsN0!SA0%A6I&4<%Qo4h7d2m*tcyLx+7PI4ts%O8!)mhKn^Wd&^Ix{!vj?X&$ONW1n zme~v8OLeZDz&~2UIJ2$^oGR*W`oFeE>lhQvuPf^=^YaX&X`emUDRoxYm}@7@%|)gW zy>DBRFoecR!iit?vf#Wij^HlX=d~^I4DQUQp&{<#@74SS5*O}+#Uk;{Os6r&Jx#kh zOObXi^{w4C>0dOx* z3(lp(zf`T%*N{FVq|b2pmudoA)Zt$`{7aF2+|O~qalmoFalmoFao|^*1HUr(mzQO8 zc&3~|soWGKFa0rd`B)8prGaZ1E3*u|H_i%~Pd*X`3T(6V`7kTpK))pUC-I2 zZl&w#2h0NX7o<@sIb&qcgvKMLJvnSD;9|(URXwExSr6^QJ$V#do2Rrrs}yjqG{9dw z^B4(l-9M9^6_j&-wPnzd^MuK;i7VJ|@dko`Y$rKxF<6u z9~%6TQ8}NLW1kEhOUt)>yx*(A15NlBZeb6Y^O9BG2Y56%oOQxgx>spk;#}6Ely%_# z@*t)?Z@CybA3lvA>k7w9%mX9%zrN~)Tkf(Llq(zOxYW&N3_4@%gHpcbaq3RsSBY27 zktI6twGCI_$@_ZkjYD7fZ@O>btYqrfb`qZS2yMZ)lyWv_Km4jVm$%&0@4c|9-wQbN z6|hcKyEO3yQ!y}{-@H3*jhBESie0Ur_$5y4>zr?^@t!_P#phc~*%+x~mvfBlgXVX@ zRl5w{T~6GWV_t!I1?F7LxtQNzJ?-_xnv5T&9ePplW5r8aU(dK3_;L>C(&1b>oXfZ* zeWCO}(Iq^b6FtdT)tru)2puJMpAS7Ea&F_?_nqd%V!>s)!;ULe`bjmH@eWh^O~FbO zoJ5Cn>2NOpsp4F!-`gGyTtz#0BV+6vBk##>hjaP!#JNmw_A=RVUQ3F3~dR{3ngTp$7e58OC$>qcH*l=uT1 zl5hY!aZ_OM)#d$PQ0B+FbTHNxuIvIkiFzQkEBCC^gP48yAmc&P;an=;c$>BG`M22X z6SEJqFSq;cNp^$S4SuyTM@#LTt;-RU9GYY& za|fAE$bW}(>2NL`&gFN)#mxN{eWmIh8CCklZ=EtP(yorMZjoNKEm};!wm43`tzc$; zYtBdY;*J*YA^Nb3Xj`|ddFEZk)VoMM?1{OEdG{x_7K)1qbDPM73${gzxchoL^d6Em zhR$u#!_4I#PXE>jy@e|tG)EX0k8F+04@2|HOOx_q=)RBs`F7|nhOU@bLU-{;ip3YV z7K=yp4W&h$E#4B+ccdJZu6$48U5U(^au)d$cx9rmuJX1#8d`LIF%W*_~X+z*X8gH%OkJYSj{GR7ETH99)0gf)3s?t4z$dk{Iq z{Tv4z2OI|+2OI|+2OI}}6*=JWFMkzF)#b@?z;VEFz;VEFz;VEFz;VEFz;VEFz;WPL zjRUuD`@rvQ`=hP5{N5dZ_<;{?ebbh$cTUaWIk&0yjW5DCUS~FYXSV)Dv0Z+{+GSU5 z`F{^wh!4~Ac_F_1(baFd=1p(C`mI~8d+W7ts@{CAL3X-+0U0e&f39x|Uvj&D$D&a?*`Yx$2;XU;5m8W{B#X zANTeO4kS^wr>JIUX1uC#H{lgtr&x%NgDDn2=?D7PZk;2#4pQjFD!F7^E z7P4>Iuz!X5_tV_#RZpFME-Y-5FoJ=pnq!seQm{!oRn2iRRZ*>P0$ve+8!*+Qo?0g+ zzjezz_1&Z#bH*x*54%?lH+=qZHa*Xtql4~T^>~-np<*Oo$GVK@hv=Kgqf#MpMQVo^ zeohq!x5VYfxx%&$O+gqx>VU4iM7PYLVC!ybx? zY#x2W9{>BKykb(=jL(T0<*tYNZ`&hXYVroY&bR7hsT=|-{9Jb@*rV%>5*En@gJgD^_{_-QC<@x!nX;@&0S@t-npz3+uIl_#<8Mg)-9CBY9+I#6JzuwYzG<;K75$KR z{QH~@sN=T|AA(uf&0b^u1xvYm)%YgNlyAZwr~X_rt0nMfw|JN3=G@$zhpD~>FL8_C zmGMl{?59U;KGXKJ)sK&urYoZW-g+y9|J0Qglj_O>>WDnHZc!$-{{Bn&3^wb+W6v2s zdBphnx1W5*q~D>xgI;_#>-P%0`&Ux8Q|h+jZ03P3lbqfj9S5(~??qD!aUP!+=-rt0 z7@d*$54fYH=49!WG#-C0F8lvH@`{saN%&fUy!76nYn`cI;XUZN#fAr?w{>^AIn>yV z9*m0vYD*~RHRP_GoCO&@sEWGYW$i|N?tu|^dTAjVEvVA?8xlVx9ix=VK)NYZ)vUiC z`^Jzr_VPb^L1~Rw+mRH&?ZfKfOGp?$&=lE>15O(YY$+`jeDPT*%6$ z!J90fn@sA_zmk?fWp$>JXQ>A@%1_+nuHOKCjo=7q>aI@iHi-JtCG2j@ zTL0z=`{TL2KR2sex&s~R^!vJFgAO=vScl)ihPWKSTPZJFPPAbuGpP@@yk;n;U;*{z zvG4r>@8O+f}o^fSqm3cE8b$uEW+R%QL0Gghm|BrC>c$23l4Jk^zGZRAzlr)14$ZCUQ`@lr5N_?s|`IVFoZC5!oiVSSjzydbcS%GSevE4SR2?CgNyGCnu3 z-lH-Ed=q5rZTeiU-srdqH5`Uf!QV8{hWR%7_uAYiI(J5A?pCD3m>?TFqb~=2JJRtZnLD^@tq4i)4&&6^ldc~|vze23M!_vyqYT8)5QjMcMQYVWeAa9MVx*bG@W(i1)M(&=*^o zOL>_5P68k8D)`*%6u~ax7g<}D>V!UmULoq%#b_?eD1(bh>xBbl@hOnoDb)}mP9Tp6 zJ|zV5FnK=&TVcpX_OK0$FQ?L*R;f(%)4Ft_Ph|!vZ8`p?j5fZ+(&bK-;qYNm6q-li z4dld&T{6Rwu9E5$9O;6WQHL&-sUS^&cOmi#;Jd=m1oINcv2WIQb&xG+BZs`^z+;Or z&oRu=rfyhA7gcFRgGN%5C8wd~odcB;P}8$KUc3$lr&8tRq>p3GW66 zq@ZG$UttvesNF;@Z~23S8R%-fV7`6dZ=3;!n#;GZmwKL$SS%;a$& z!0yNJ(*5AM8IX&6po5F@^7xwG<-5)m0p_ZF^Kzl4lT1)d0G}XrJ%gO1{1uzKvfDrH zT*y$Yy92K?GvXsX`OblDPzl11>ahRMV+~5A8s-kbu78`%R0f$hcX7908kF8#X~TS0 zBcJ|E2_dz;3|bjJhK%PlA7`+R#hxg_yCUv6$}6{mM{sZW7=Fc0!Mi#1UITXlwzf2e zX-#E$Qu!l<`HwmN01pp^$(Sz1bQPeZU{{zv39;wNV$ZV)^T4J7;0_F^%+26U%5P-X zGgybp%reaH%g|qBTeW-DT(Rfn{&e;x@B+>ycK6K@d)948XFr8L2gW6bes%Ed2F(33 z9I5-NS-T3zjSMvT)(_Sp_g0#%p zeMAHd4SGj$^ljxj?Df{w3%=?CU@z1gJ~h0``oap<*d_3|;XlxXe9h^3mM3WqRz4B^ zi1$(TS{MDI7lNm$ufcbmRjnT(&nWLA!g8z3aL6>1kGvv`W+E;2TD;E(q%rz(8|ZTb z%T;D7|LK{VjW3={y_Lo{kNPt#0%w6Hvk*_b5yw}8UZLS*E{}H-VF}?WC&|p5B|F6_ z|J^0b`22i4U#x^2U(RwIbD3Jk%s8XE6czTc@%n;S?YZfkfMg%>;ULLg%xeQj0|wal(%vtC96Qx}%J5%aV$DhGGhnFDJ~a3?_-7~WvmqZyj-a1Nu5zpw zjJ(MTpVPHg3kr!(>5L=-P0I^qhWLxG(_R7NJc9hqqkjg$e+kT}u^X?vmi1!rO0%bka+LCW1@DNj=|0J?;Tr}2`*oceYHK7x zYkCKHLURh;e}97VC{KPe#uaErYf1U@8?Z1GrcX}wehPVP&yOgt>hmMYU;U6UZt#aa zm`j9I+X>Pxhx1yW5LvR7EGDX0@1;OY4cD;w!!!2*7?0{u%m@7t@_cu zzJ|PG@tGH+^SixmAzQ1`4E@d;WtwD`R9IJ_t_=N4Wzsq>1zZx7e)C@AFH^?v8F-T3 zvrL_zuG-^s;Ha4OwHyv%dy(A@UMfQt@vX}RrO$&$UXwnKH{+ew1>k`Qb{`SOL@BMX zzgZzT_<7X6h~kgJ-YD6pO}Iz;h#kvxPKG(hoQcuiA~~y(_s0E;d6?QAVN6G$skzr! zJ0X7=Ap2^=}rKwx6 z-|!sA*$CCGOlwB0B`HmWkORM_0y+fJ`V_0|!2E`ESdV53_pmh02lPzxWrXJI{?;rX z*c&SBWBIwQ2J4sMkNkylZ@{O0EIo64kFlRF_kz!G21x6zO1~5|hUntJXreUbhcK^S zhxdr1_hmC@-|dUjapp*CW}H<8wB}t<)gEde+Eb4@HNbYU0rTUnbu9e=kAb*|;>CDTV z2jg6uWN*1CNROnXp`Dnmx!qr3-L79SeVgnJFV8}35aa3M$SJ?cKdU?y8WMB+2!3e$kIRaHNQ*rXXbLv7vfx>-G{nk zA7bWQtcl90R&luZG;9~>wufj3`Gr3Tf42htOZ(0d)te15-W0~=U>jsM#tPYfne!;@ z_350D_;e7yWebpXn>^L9vLql2JdqeI=Es8%08lL>P3QuMmeZqA5+*#*`f7!y)Ga##H?42FT%Pls7 zHzI=SHM2g~j@5R*;J4pz`J)|t^(^vSvuTCcj`G`)U%M~-ci~#oSTgrX+mr7o&Gyu0 z|L5>&o1{HuhRo3YDPgN<$NlzA10FrES@~I?owhzl_y3MHN;~M1lzAq~qjIkXPj_H` z{qhX#De70`=BYcw4q$y<&F&1Z-nBh^Zo~F)UYFf#cRPzj~zGYe1e4%-%$G6_iG+3?JrABv+cec<#x=f^U+TK*>I&`E$eghX4d)7by7Qq z;x^pvU)?zzUhNHsYf)cn2hk^K1GRB`uyKFhNjsiT+VL&hjx$iFGf>|%Q13Nrr)a+! z{jhOBTnqZ1KI3B37Sjf#Puf6vwb!KoMRod%J~gV`_TZ+`&qPP$*9e*{K=})h--4R_ zzE+(d(GclZ#55eM{L`_vPU^eniCadMM{`WlUuU4d7Q}r<@|yZ?KflJjUCn1#d6v&u zZbgphO=Ftqef5A{vu!6H1uw~9g_#o=@}x9LKWqojjm1Z=hldinzm|9Y(d12b^h6Wl z?^@nbI0qr#spb{^>gaL3J^1FRIwm|qbsUdBzJ{~!gx*R0#_AUnchPtD=ieUu{egS% z!9jTdWn6o*$|U6+tpERg!+_z{HBbE0{``l=>G$eBpW3|KUp;lESgjxjPg$Rv3fzO$ z_t8(c_I&A4^zUly)g*i>-;T5V7ObCcpDNS0V;}z*p6OmsS)Y3h&n=L%w}D?)e^O>{ zTb=T5|2>v&!TRL3b7bbiYf@eda0;g3n`zh!we$@8xAzYFEosdk$C!K^`AkFJ#5+@Q zmb*HW!dB?(;cCQBZK(&Q0&o?8wQw7FPvf`#N9&L;`(Q|QXi>IK7h+9J_0Tx?r+h9P zqdphb)Msj1@kdwg5L1!=ROJ6C<&WPSDE~*%ZU%qlEvDT=;WWIPhTn9i;rGYeINHgP z2K&4gobx{hnmzh=GJNcu>Ebhpr?}+Wi+*UqT8^G+FGlx|A+Osh9m4(Z5x*LHzT2o= z{Dw-jpNik`s2!`3u9~i|X$R<8-HzKJJ0;GR44vrr!+8HS9lvK@gtNctQ&1PkaHIIkpK^|vG!1!xfB%Hqo5dTl+SlYsIoo%qcW z^{FiE5maY^E5wz>mBW?PxrqL%;G#7l7D6Y`@2j+aq4EdWFxE55oK4f2DScD)K`T%B z9KX?*7vlGN{AO6jzD~b{v*3FAZ5iupJQwKH&kEg+dWYk<1g7W z(79{%o}mny6){F=JxqHQtku1U?ol_6^)bQ>g|w%jHkfkJk5oq*Po^x^W6nkcoV!)1 zE-0VQ^UQAmY#8T6;5D3?m@EE{zIA_&0*(TX0*(TX0*(TX0*(TX0*(U5F9i-Azv58a zPJ0rGOeP5Fw@>VO$4kf8c_J?_4{P;Vi_rPnRHM&Y9GERa{5~|6KC1*~AnD2JoIQIe z;rwJi_ItFyjKU_IXD;^58ESl%Jbx+9f9K@10_uzYTrdpHkdHtpA{F7Ol&Z8-BI)hT!8;_ONoNZpk!m-}5nRW3wKGE6z zISM!mI0`rlI0`rlI0`rlI0`rlI0`rlyd5cU{k4lOS+nS@-x&}8;=sGHse|vwev!mZ z@H$C$v_ita81A{?!HMWl+s=vTa>Vg3&SVb%;tep7s=>ctORbI2L|Gj!{0p)VC!JIE z`5JtSn)5OJ>zellZ^GeU6ruM}=#z(xe?j_Y!~^5uVCa2SI2h2yG&mS)p25KwkzWl7 z3qyX(=23xO&SbDKbYIG1Vayx{3*%wfCgCiSbmR>dhVI>ug)xM4LDG>Soo@;U@s8@R z5ueyKCt(G8ucXUkFfRsT%!_@N?-M;8J=J1fY=!>FBe)t+Zlft1yh+B(;kQ~NAW%>|8NE=U0*fptK43N$N!3_9x2*DsT+EScU*kR5*wM3)R_`x|dkvj%%3t8VIzM`M9&7?WO}cEqvih6f$Mdbft3vrN_PKEi zOFwvlGUXHB=_hP_VrxqI>gR0!#t!U_V6m(Qeh9D-Kr4&IGIDHTvFIPz@o4Sbh71;q zegQUxu^ye#0Xs&pSk$*I7K>VapidH;F{5h+8?)2p)h975j?ig|YBg z?{FRs3TN-~wf6nqLVSVW7_MZATnQM~qMRQh^Qk=caEdEN#_9OB4QNdq%!uE^9 zUx8hm2RVp-D83EwSJ*F^nU~1!O`m4@HQ`Zp$&tffk!#|zCxO4Be{SoX)RV^2r0`c( zO^m;y|H$F594h|GSePri7xu}xBraO7(4QVY@|Y{~_pO{Y`rU-#LRcaWbH%Q0w;cPJ zE2{a}z+7SB8^l~W)yg^IKZEH&dnGj5$RUL z7h;PRBfx-?FOof}I-(dXv{zPX;3wgF1a{^Rr+Q&)Ec~snu=Lg?D$@*m;;pdjcm&Un z;Q0~UV_xtHpM$=QVAo^z+rYVqC>}QDWD8FABje#*=vRTcKo}Qf;}hG9Ic$s0%$tsF z@!adcw)oL#YzzHp{9G6x+roo=`_9vp@L;#@N#%R*0=8tJ{Ka$+`=vVIJ&k%M?4?7% zy`Zsoq;W3@`y_&mRRo)8#Ab;|SBrbWb{xZa7pL2G1cwbXcX$^L?*hL^ zydJy@hjpQIlfk-Rmrf4rLVa*-tPA-eJ5Ce3eUdW??!@85x=@QIk98quya`wrR~;Kz z7Yw%cq?gTrr8>R?ptxKGa}(9Bzybl|6PbItWvNXhIkr z`XO$3UcYQ*PBk`%{N-pl!bbF_`xoc`_3i2Z zRn8vA=H(dh|EgM?|5w89J(g?^oc~wpIsdQD|Eu%=>ioY>)>pIh|N8dy|El2kRg&*l z=l|9DfAysE|N17_B1p1zt+qvQ{$HK{SMv7?n~P(`|0{F;Uk};;tFwza{61gV>#&QF z|1#PxM*hG)tNi$OG2{7st+tmr6gwE_{}nc7L=u~3*yj}COR9)48q3Dq z`G0l(U!DI~-}!%a{$HK{SLgqg{M8e_z)`?az)`?az)`?az)`?a;JBoK^Z%;E(nTsuomc4x=A-lfdR+3ctF)tl zqkyA;qkyA;qkyA;qkyA;qkyA;qrkx_Kz>gTU^$%8cjcdsPJiIt==kKR)-P%jzdt-q z@GmB!Lv1@JqRSEY|06wB;!*}j07W<~! z=O#PpHhI8gTd*L?ik;8ooI7#nvZ=^Ti22h44d4dd5Zeq2tCEr+)Xb;fqr)e1pC?7r%MF zI34~4{A{*bf19UZ-!TVQQ4fdt>B^^l2>CRpy+#4o2z+stVE;_m5XSeZ9tsuq9Rc!{9aL9gpV{Uif9In0 znvbMZLmB1gkylCfg{4O9H@o_?e4X@ylN6WmXF~Vtn^ta>W+Cr4PtV-U(U<w~KBM!36nGA{_T*Etfc_L} zTS$C3h9^fPL?Heqq&rI=`^5D2IQ+Fy2|COq0x#N;klB zsn4cr?t!)G?9Sm|IQ)yDIl%n@{zvUa{6TRg%oUZUZoz&t+HVqv|7uDTksoXLs;=PN zGmzWN+*#Ry`3<}lVZJNe!_v_rnWbkl4`z|RzctGT_J*ns^VGSmS(UQ>x5y6{`Mj2% zedhQ+@H*4wUYVvdK!x~9zZ9CS&(XyPaF&QP<%d|hd>!5+j^3BeoPD=1PRE&}*DJ*7 zIrzx#6~Th4_E7uaTe}|hYS4Fv4VWKqtz+p2_TB5>`ZTM%x@ED>+~V*r9R3A(;p8RV{^xcq2%o%3W&T7yl|4D?_MdD~nUjZxvbuM2K4InM zWBY{F=Z^NpNc-P*jI(E36hE9kVcBVu_X+FpFC6}b!@oG-Ta|nXcg(8uug1Fm*>I&$ zP3v>>X5zVXIK0}kyrN$nJ+7UPRqJC_!YA|b;A2%EW*@8MtCxI}KB{mIz}M$mGK#n0 z>|q+_n`w2prquhlam5|}g~PuHr{Z@5Tn_)j;a|}D(ET|II0`rlI0`rlI0`rlI0`rl zycH?n@Gl(x#aofDU7H*Q90eQ&90eQ&90eQ&90eQ&90eQ&90f*G;KSE0ykyOyvwr82 zYd><$^;fER^zy^Tg1oX6L;XYFHLdt7Iel_I5oKSwt=23wSYMyO_{&Tk< zsRg0IW_S-U9eSCFZu+{hc_Q6t-IoH^0(5a^emuuFKcC%i+X7uxgN5-hY?F|VGtJ4y zrJ#FZi!|g1Y_CuH=K=K0N#~owLA;~-Ys9m*(N_g}uVi~Q0(=c%MPw^2n#+Bb?~^k1 z)Q_9?Z$+9%a5bRZMpHJ*M_W1ca|71z^DZ5hsqUbgiT4XWzyAeO_N^Oarv4f2>3-;x z=spuyOl|hLFZ_C3%m)kwu4v_FO`Mu#=~aa7PMO_h(^Hvo`lzvF?pfS7MRp)Bo!ZgB zn`ekh(+32luYHbI*fI#;nCMb$ocy=E*`}?{v-X)!nPj?_$)$@LZJle&seP8G=7PpB z7o_H+pF3cO0GgFQrUZw+e)+=)p|5`e;)rjpZ_?Su{*LIN@h#`XQ_y{4-@&DQermVR z_b#yfm@T9@P6e+mFT$ zOkcL&4y!ErPJb*mdS1d22 zaL?NzPc`HzgDl!SJCt9#F;{L<8Q#T29_5r<15rd+A-+WVfOrn`tKlEmoR*)G85$#A zRbKRcDTVrXEfJ*?VJnFHpz|{GJ=wb!b#GQ6Ze)w}23cRW0Gu7NyP>f$vW0n~GTX$B zU`z>=tzTlfkrYesnWcCZ^%#K;>Y(n)vVyf^-2IbV{oVV1>j&xOerZ5?yYYUL9?DJ@ z(}B-MU03x8&=Gtbq{}IW=c_~jo1A>}OffPGwznsu4f9~T!%BW-1LOhK0rp5Vm+|I{ zM6gi_iVrf7%4kO=i?P#ufe;<&pLZaCJsj3SwoqS|-vPT>q=}lB3c_E}pR;_bU<;?G z+k5KYWX`emf_)KBwis~Vd4YBE7M?CSJNLA@J;19>DBg2UcT{u zkx$ruNoZr+*%N9X^E&E6Hon9&Nt=leO6Wg&mj@pWLcYjm*e!#1g}Nimcis_JQroP| z1f3$p)3-&0rT*Ui@#Q$4&$PTHnpX&cb%$tPB?8#XRzUAymCOX7E%le_C+I9wpP9a+ z{u-m70{EP+?0O*!T0#CqHhuU&!h|82;bDy2T}hWVHx!=*6HzmQ^Srn@nfyB z>vLyT`L!n5nwnA{Nc1!Ly{@o3!;<`BNOo@I>zZT!<|sG7J6en6(WXk%5>aWy7>DgG z*;P|pHSE?pk#E8)Nl0rLicfrM*M{U{`}NeH#=B{E3Vr%ZJMN6_+i8|x6CPEU*g2qf ztjhW~XRKC_Nx3F2JMk5cej__(sw>gj$g8+d_0MhjNj+&S1@A;Z;^NI+qG-Y;B0zr< zpXM<~=P}0AD#*jCeD_j+wLwL^XkPl^&`@QRP z3YWx1eM)~v19L_GzLm2ii_E$axFf+XtkJzr5$qDM!)(ivoqT|+fGg@^G=F6he1-rx z2?pmuw}u=T4P{^^M2Hi}BO;qn@G?sWT`E&SngH)YvOf)MnH+Nw z%^PMNR|j538#!b&pN_GCxs737Hg$X9#++%xafrF1nvV_46&Aih%#~BEoTGj)m<}`! zsGrbB#B-5Ce<8Gehdm;AD8Sy86D|iXiZ3_yr1jJ9&#CzsOOM=`D}fIKtQiz+dT3l# z8t}YZ_&;d?|72LU7|A07%y8f79PR#BY1uU_ht+b|Kr=J$>zaj1~ zCiJ86GxiPCkEv5xkeSPZ;4~IYZD+xh`7H2mDfl~2Q^LDN_?}e0_b%*h0_88Jdz=T> zdG({8>#%40(Y?OLnw!OET#U{U_qK&>t-_fk)=Q0YT-*!810fp2d12 z!W>&l)4Fnn;8;tJT8~ovQCO2E>*a~orVggv`GZ>+_-pl9kwhj-!dE_UI} zc$bu!ovc^XVgBk$Z}h!0a{g(U^X7JS`#-y~%e!lkrGMsYewXOa%;lOd#BUVrJ`vFR zkL$Zaj(tcu)hZ76T9WO;IrJV}B(v}*+pw<(mI>i>kEq^kh_R+HCI{QP1dS8mkEPAt zAN#dUI7g>-^WaulSAcxmF7a_Fz~S?9$0$U8oO^ zjddYEWXEYc&f(kRbNF`1n8S^Ap%zUZ>q5?0k(;OP3_Ease>LRv)w{Nb&u!Qq&g;6v z$f*vU7A&+9K`=by~dYw#Nh^P|2; z`V}$l#w!2xnFs2-=80QIl{bX%5jOa4tv|t;PGR2YSu@cAVw3V+_b(MUK{p%v_8m{jeQlWi0+@RduT7d%CaX?S$^N z@oOIZN0T?5BN9z$T&Epv&Ez5sPM6Kri;f> z&Pli)#~JMpr!w&w3QzUKH0<4{1CwMb-Vttzl@*fFKE8}+`V9cTRc3ew=LI;Y4X{3< z-|>T%daRd*@H-gx_xPIez&uK z@yoMtt_pp;vLby#*rh>lnL}@xbj>;Rmg!uY&T=a_Bd^3~4HT#L&ur9dB!)R zp7CuNXZSdmhdz3}e{vkojKfxh&i=*Ozc~9BXaC~tUo`1V@esO*q!(3!P1({#%GhgG z`e9#IWs~OYUnKNv?QeMc*WCP;C$a@!K<|7Im&gj-Yusyd&sRV{4Hx+{4sS&|%w?ha z5d2@tbO^oQa7YQVIUHQIR)o<1B|9~9KcwyREB$_<8G7{l&X0dLv}NtR%P~&JTIvJRjoXdiq)F#|Ec+ML2iq51jIQ|4*}pjZ zmk>JW9n9C}WdWJwBZM%V@i(uK^b*v5QLVa>lYpGI1Au zXTR-Fd+_%M?qUCQP}?VzaqY<}lazBXyQhEO0Q)o8{;YZ8pZ4cJRApOKZSPcV>om1_ zxxadN^`xk4cez@!a<~?_Ex7M+?E7mJqauLjfya2j4zmNu`ifc?HEY#VdOMx z3zOvahHVaRtns<=(y`@pL%w3$ZQ7@XLLH(nPx|^=2wGQPp9`|)KXV9c?TQ`Y~+-L@ZzZ;p!pjg;*d=YIpbd!FVT z{ZIrBGY6&^VSO2F;Mh0BTgm^1oMm~G^ncYk_CDcJRXlS3H&`()dlLRP*p$)rB&_C1 z`QP}&#Qrx}zw^IwsP+fts4ZL0o{}xj-xiK#iy&{t9EnSBvU4S^i;jjZg1*?wT!ZUI z{_31BjIyN0j7BGCzJF0-zIZ4pa+v%!}Et!X&$bV(Px z0K7v1yMe64@9P7=a3(*3(BD?L59PLS5cUSUp_ffI2K=|y#^CkXBItJ?8@@Q?!Z+xP zV{t5dfh%~ZzBm}IJF9IG;5UoL)tlvuLro`}By~i6Z(ts>IGYGb#&epFfzeoof6NGR zMci}v`Y5+r>_+2L2AG|v;N2X0uYspO9lk|yPird6lgb}~FOCxC_yar)tWek%(7vk_ z`#2H6d=%^ovu6w8XE1vfY_WjvxoJRV_6(@Z%>z(X8El;k$Yb}a zxnj@D{psvYzzl{ThTVO0#GZ8<(%DbJh5^1A`2*1Ze|7_WZ^>|^?yJTgPrxo=1Q?TL z^0R`xO0q93H7fYMgOAa5(hJ}p&e%@lUVYQbtrGmFHB<9!ah-L1AT6QpM;spe|qL- zj=uCS^;QZ2zZB}vurQwmOx9V5C*FwTD?zW&pJ2H>-bsWdgr}S&Gjo>g6sP=mmoVe= z^YMJK5yY*>S=j>s|wud2^;e5hO&L@oSot#e?dHL8r zVf49ntR{XUXuZ`Ac|-Ook+3t zWrobq{VDLN(T@A=vEPz4@afJ@o4ijLUH>Ndgjr+dWl~>i*U|6^qo&z*lRub_S#>^q zd-%_WD+Oy=pPM(c&Ue05tY01Cn_Ay4hugOb%N@JERpf~We5=&*j>0(z@lLgm75(by zaqWDpSQ`@wpG?Ptj}?8GeXNkL9`YmdDE6ofzEWF&f!2aO@HEK9X~0062F$bDfSIw^6zH z4fRlctVoke0%FfQUOK+c6M1=gxceu!`n&i2)(_Il{nCK)iUW;e6Lgk^==Ljw$J?dD;=pV% z9!9S`0s7!W59*b`;cxGo%`MG zvlttK0ULt7s4}DczmEIe(80em_1U{0V}dd0%zSrts8cLQzLVI_*&)OIQo4_ED6%Lk z$BKUTZ<)6V7#26*!@O*aVX=qb?Pue9W>L>QFRRS5Dh!K*e>-&0Z^_Q8kcPd_b2sKh zy3QZ`&AmQ_bS~MER=)l$Fe*Zpj@0SKKB)pb@;vNH0;1>6^|?w)^DjfkQQmIT@qBBj z-xHsuK5IkcoAJgEWh2bYuOPnCv{dkP zYslxrSHmjZ5QMOSq58n4iN4V||1{-xpxk+>T$=3aW1qX&DCgnU=4DO z_*0?{=nA|N_$VvjUdUlXFY;LiTTNc-1jk8r{X<@EqG7iG`y$qzhHAVEw1-_;xNXlpgPNX+n4fm`%VL^g6d6w`k!o{8_X8y zvXL!Wpp>YDQ*k17%2DpL3{d=Fo4ocs-aR3jewQ1~%CQ#@#0 zybky4kPg1uIDEB5R3?12CH1*H3wK8N>oK7Qt#P)0zLl-=Z*03eJmsrDj>qnUvqME# zANV8RZdcLxzbJmU=<2kbyCOIEKI+S_hI|0e|MULbmyt$Y7^hivb(+0~2a zHa!1tgzK(O>#J6ne8Crf{siI_dmj9imOfeyuY7K!3@XSZ zgU6IXG_Pd4zQ3VfeR_eOZ$a=$6M=EFlj* zz&y~$VBJt1NKPl^@vSJQOVPWyESZ)6XzQe5Z%VwAr#56jXUM}Kg)xgh5Glx7TvR_A z^He64SD|OfVMcb8_#>O5BIK*yp&R)3V27|1eN`5~ZGzoxC*-@x`9-P^>N^Oz6ub-? zb*W4RaU3?@x>Gl>E_{P|Dd>_J^2x=&i}4Gad;JpZ!ig5hUtru0V!k2TL~Kq7Li+SB zu_NCNe~QxE(LgrkgP<4rv^4&}^nVz6Z2Z%exS7w%R`j5G)QywJfKJPe+^hrSNAcSm z#%IJf`W$o;-!1qfpHYIwp~=6wN0802u{&;CYwn}A>xF&@aa)r3KA~5lE~`E$W#rF>hUtMX(4bi-qhR!DXt>l5Pc1lt5fNyezea{e5nS3C| z0U%riFXx-SC!5>0Mlpi##ii&=$ek=N_E~O8B0yXblIc?|twceh1FS`Ihj^ zn?u+eV}60mD1fJ_9isVS5jA_D%LfqFBm8636Y>EvrGRe@k2POp+G^h8J9&|9bKz2y zhcu;kfbTrXD;SS7$3Ws*{vRp8=QQDyVb1>z*}*eL-%vYg?Z{yt&XrvsaoCBM`&A}l zckb_-ynf1jOY4Mkzsyh>GG)u&-M>Q6GnHrT&)3hhY5O1xnpnEnr+J8VXaFp=a2sR* z`=lRY4I1^4?2ukz5la`^RHo1-GXm>p#PcH3Rlb3DuuCtj!}~>ezXsf)dYyoT80@kvD?hECA*!EJoJd3p+i(n(1-aP_2(hPZnd7+Z(75ri0r>b7cErXc51|j#aLV5aUEH{GnF$aH^Q!=emcAlg4 z1bs*SOX0{q%r_TXIZ11P4t&d=w%-bkx<}~u{zgITBAT1{!1>0%E9JxCo3OkCW0K}Q zyd&R)w65acL44EuM5Gp&{^#J$pQC>2Uzu666NUzj?Q$BvhY-(xWaG;iBUE4G=P<@@ zAR2PCxrjVyJzi<;!5Rp4fh?#r-5~gV!nbQ9ZPrE=(2?Uk_j*O}&%&3d+rCSUh=Ay3 z^(hpi`47HbeE9=gb`k5B+PP3)ZNH^D&|F@|oNnreIZQ$4KUmrAi*v#EUEO{tvF-up zK)E0MJ&gIlWA%eurAIWTKb>L?%u6*?`qv7~Zw3o6Sd4G!n`Y#l>d$bj2lVanoHeW) z%HT=D0;mwLEV@8c@Eob3EY{vxwb#l>lKn+>X*dGg&JptE82fL`58N6CyD(b=e{4TRkP*VO{ZMY|Nz1I|Yw|z&0Ql(veVNI>2|gzus_V=& zr28`suV}9UJ|~;tb8=K%>~qq7cfg*W#k^M!UaVJN8I@n-Hwu1Zx-&!HEQkE2wtOFc zElEDped7e>k-fed#|-lgzM(ybz?!*$IiJ24@4 zG_5tI(ha7JSk@l%giibNz6t+&cd0)EUe$nw`kuitRn!og*=r16Xg2^^yLuldwk7%5Dp=njc_*R zw!H}VqW-fbo_o;eyGb72Vd%oaOXXCncs*;dqz*r>Q~a-{vGk9@e={E__%r3D;mpo% zzYXJYTX~K6@n>cD=RPul%vulaS8ty2+mP8s_pQ%<}OP0r=UqJwDz z=4$L`eX*5!d9M*?AWQ_!Izx1!bpXW?os#89G7{AeyFB9>x}99j&bO_a~%5iS^5&~X$+5?jrkWmo6ws0L8!}U z-Ng&ru-?b|h4wj|l}sqGmKdaWs6VY)gu44RYY)mRK;DI3;ItUr8T&i}nIH8c9^Z1% z(B#{Lb*NN+d6CAN8guX^m^XVspA_TEJZaWZM7PO2%U5p9(Kl1kwkb=x{lD0;Ae{0^ zmAODZm7NlG`%|W>%#@*_top_cxhWXWQ<(NIxcvNZ^;DMjYUWvqLjZ<9%%P?Z5okm- zA>O4uCbg01X8H@EKpjWu{S1~?e{9zw`8Zt(?#b>duyrGr^1zXJMGUX(`Q z`vT}g{6#d%W8cVo&>tQHzK}Fygw~aleqJQ8$HKf$=Nh0X_Z5%yGugs>H-i_6|9r8m zSz_L^c?-lR_k}-9(xgYHK|GxsQaY-yV7*}l{YEyCM6a8B6(8|Bvm+^H@}lyot&@4y z7zdPZ0sWWM17#ezPwI(~__TmIlj=ZgJmK|c@txt>06a_MGXT$0_*$MF8k1+K{%P!5 z()Yh$WOW+(or7x$*7+Mzk2Lt@duhdQLYw^73q=|>*BM+(VB?=WQ(qo5AK3hlmk;wr zfHINS#U}41u=}U9wRxMhCHRDRlFBP0tgd%x>Izy=-LZ!+;(5vYaF6{OM}Bmk=7Sgf zl-=9Vex``CE`R6ju#AxI&%ygWXzLz*Md)vs9ez?-*`ylnxFFqDYA2O-AKrZm{n0J$ zd_!vrem(NQ`i|)KUC?R?g$tJoh2KaphWziw@e$7BFq(1|JSY3+WUg9LE|p5U%d}_Tc&*MKdDaUoezvB)PZ=4;y$Ub3X?j3TTLDKbxN4>>*Dg`z7vbU zbLzkz0{LODZTAmJ|7KDCGSHIdN)8^N|B9{e5I5;BhUxcW4h2olL0HDQ8I`{g_xIr< zp5aZ?#W~G0#geVc>qftHV}31nft2|B9`cQvTf`?<$+{&?J)+Qbu{alb5}&325cx9X zi*O^Z`*4k!AL?H2v-we8)E|(cnc93Q&uFm{=`JNUb}CUqTb4*I(ozX(C*^%Q&OE4I zr+>HLpB}G)6B^`ES2}xSTX9~3vxX6j!)zbgOfswwmj~bJ{o31uaM?ZD%VPgTvLg?S zwZT4V_PtBDNiW|wLkwb^j*iQTLCC*lHEEZPk#<=h(%!?o$|{wu;Or0kHowv;v$S8J zu|oV%iR(mdQ5W2p)7R;S`9CQ5*XUM5_j!*CzvD5xf9-gz;CICP*QBlVo%?eXa1?M9 z7>@#1tiR@v^k4A(cv;){wu8Su+HXn!C3{)-hKcA<+fJwdaN`g0^j{95J9B9IFNt2uMEWoK&r|ly zy-NQ@{+nIPn{%5tS^q^nW%C|Ozl6>*4^{s~wOgGD71=Q{k^T#N1!L$q)_+kaQ9E;i z`u(`Qe_{XE^3g>4FEZu>cAV?K z$n&ghRbR91CjA$d=(vob{~{CJmV@ZOunXd`e;D;&)V9~^zsTXktN$WDXKD0C^k3v0 z%WH4;S-5(@&eajlI7&SVXOBl;|3&|ut&`J#!8sJpE^tn7d@=0Tp_zpKi@N^J)qhbR z!rAOm(tpvhe#?0JFZyyjt|Y>@i~fs>eU%lQ{>yQx|Ds}@Zk*AN(tnZ9*x!gIqyNG_ zVC7_@|DyKVZ{KYF7xtvpVW`!AQ9rctM??QbLvNGx=#Lfs7x@?Qob^`Ff1&g8I{apd zH9^odv5pISo9npfMyunZ;@^zN({XWnE%+_CO1C)qZN=%eC}V?gsJiS7jdM!?`#p$)Ywe(u#YNyvizazLmM*&BHBTs=3U%T*- z^k4A(!7F_n=)VyD%S3djZKuU zZt!IYC&uBwSe-$K|KjjpV58>nU!=o-0hWrxe{uLP4*!KY{1=D+;_zP_{)@wZariIH z>B%@fnLPAc2zSTfzq}S7#^JvJ>!lhW#^Jv>{1=D+V$K&G{)@wZAxs+jEz#k>95279 zx_UYa96uDe{+dJ6f5G<$Z|rfP|3dgL6VaizolgJd;N5<_ysg!LVGjSr>A%$YKXUjl zF&@eU{*N5~3-Dlo*L}47A36M&$@xEW_%GN~!p{Ktk(kK;k;8w1UHK&ZA36M&L)U+C z_%E=0d<*+Oa`-RDxBnxD|8i*lj~xCB5a$n<|09S0^16H+Is6yKoL?i0m*o5!Ilo3n v%de5ce@T26Ilo4UA5e$?;`|yVJmCBqy|w)sIsBL7<(E=dPe*~b9tHkCI3x}n From c5f0a5ef095a607d78526faae9c8ee79e5613e1c Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Fri, 9 Jun 2017 15:52:28 +0800 Subject: [PATCH 0667/1060] add drivers of the multimedia Change-Id: Icde0895b71770e393cb6a61bedf04aa199f6463d Signed-off-by: Nanxin Qin --- drivers/amlogic/.gitignore | 101 + drivers/amlogic/Media.mk | 91 + drivers/amlogic/media_modules/Makefile | 4 + drivers/amlogic/media_modules/common/Makefile | 2 + .../media_modules/common/chips/chips.c | 158 + .../media_modules/common/chips/chips.h | 39 + .../media_modules/common/firmware/Makefile | 3 + .../media_modules/common/firmware/firmware.h | 113 + .../common/firmware/firmware_cfg.h | 32 + .../common/firmware/firmware_drv.c | 682 ++ .../common/firmware/firmware_type.c | 57 + .../common/firmware/firmware_type.h | 41 + .../media_modules/common/media_clock/Makefile | 5 + .../common/media_clock/clk/clk.c | 405 + .../common/media_clock/clk/clk.h | 155 + .../common/media_clock/clk/clk_priv.h | 38 + .../common/media_clock/clk/clkgx.c | 620 ++ .../common/media_clock/switch/amports_gate.c | 189 + .../common/media_clock/switch/amports_gate.h | 33 + .../media_modules/frame_provider/Makefile | 1 + .../frame_provider/decoder/Makefile | 16 + .../frame_provider/decoder/avs/Makefile | 2 + .../frame_provider/decoder/avs/avs.c | 1541 +++ .../frame_provider/decoder/avs/avs.h | 70 + .../frame_provider/decoder/avs/avsp_trans.c | 4944 +++++++++ .../frame_provider/decoder/h264/vh264.c | 2960 ++++++ .../frame_provider/decoder/h264/vh264.h | 25 + .../frame_provider/decoder/h264/vh264_4k2k.c | 1839 ++++ .../frame_provider/decoder/h264/vh264_mvc.c | 1594 +++ .../decoder/h264_multi/Makefile | 2 + .../decoder/h264_multi/h264_dpb.c | 5238 ++++++++++ .../decoder/h264_multi/h264_dpb.h | 788 ++ .../decoder/h264_multi/vmh264.c | 2776 +++++ .../frame_provider/decoder/h265/vh265.c | 8969 +++++++++++++++++ .../frame_provider/decoder/h265/vh265.h | 27 + .../frame_provider/decoder/mjpeg/vmjpeg.c | 912 ++ .../decoder/mjpeg/vmjpeg_multi.c | 723 ++ .../frame_provider/decoder/mpeg12/vmpeg12.c | 1110 ++ .../frame_provider/decoder/mpeg12/vmpeg12.h | 26 + .../frame_provider/decoder/mpeg4/vmpeg4.c | 1127 +++ .../frame_provider/decoder/mpeg4/vmpeg4.h | 26 + .../decoder/mpeg4/vmpeg4_multi.c | 1304 +++ .../frame_provider/decoder/real/vreal.c | 1022 ++ .../frame_provider/decoder/real/vreal.h | 26 + .../frame_provider/decoder/utils/Makefile | 4 + .../frame_provider/decoder/utils/amvdec.c | 998 ++ .../frame_provider/decoder/utils/amvdec.h | 86 + .../decoder/utils/config_parser.c | 62 + .../decoder/utils/config_parser.h | 21 + .../decoder/utils/decoder_bmmu_box.c | 425 + .../decoder/utils/decoder_bmmu_box.h | 63 + .../decoder/utils/decoder_mmu_box.c | 383 + .../decoder/utils/decoder_mmu_box.h | 45 + .../frame_provider/decoder/utils/utils.c | 66 + .../frame_provider/decoder/utils/vdec.c | 2907 ++++++ .../frame_provider/decoder/utils/vdec.h | 306 + .../frame_provider/decoder/utils/vdec_input.c | 544 + .../frame_provider/decoder/utils/vdec_input.h | 131 + .../frame_provider/decoder/vc1/vvc1.c | 1170 +++ .../frame_provider/decoder/vp9/vvp9.c | 6922 +++++++++++++ .../frame_provider/decoder/vp9/vvp9.h | 25 + .../amlogic/media_modules/frame_sink/Makefile | 1 + .../media_modules/frame_sink/encoder/Makefile | 2 + .../frame_sink/encoder/h264/Makefile | 1 + .../frame_sink/encoder/h264/encoder.c | 4237 ++++++++ .../frame_sink/encoder/h264/encoder.h | 465 + .../frame_sink/encoder/h265/Makefile | 1 + .../frame_sink/encoder/h265/vmm.h | 661 ++ .../frame_sink/encoder/h265/vpu.c | 1997 ++++ .../frame_sink/encoder/h265/vpu.h | 288 + .../include/dummy-for-git-empty-dir | 0 .../media_modules/stream_input/Makefile | 10 + .../stream_input/amports/Makefile | 2 + .../media_modules/stream_input/amports/adec.c | 295 + .../media_modules/stream_input/amports/adec.h | 32 + .../stream_input/amports/amports_priv.h | 56 + .../stream_input/amports/amstream.c | 3651 +++++++ .../stream_input/amports/amstream_profile.c | 54 + .../stream_input/parser/esparser.c | 940 ++ .../stream_input/parser/esparser.h | 149 + .../stream_input/parser/psparser.c | 1160 +++ .../stream_input/parser/psparser.h | 141 + .../stream_input/parser/rmparser.c | 337 + .../stream_input/parser/rmparser.h | 136 + .../stream_input/parser/streambuf.c | 418 + .../stream_input/parser/streambuf.h | 136 + .../stream_input/parser/streambuf_reg.h | 111 + .../stream_input/parser/thread_rw.c | 606 ++ .../stream_input/parser/thread_rw.h | 52 + .../stream_input/parser/tsdemux.c | 1131 +++ .../stream_input/parser/tsdemux.h | 95 + firmware/video/video_ucode.bin | Bin 0 -> 420352 bytes 92 files changed, 71159 insertions(+) create mode 100644 drivers/amlogic/.gitignore create mode 100644 drivers/amlogic/Media.mk create mode 100644 drivers/amlogic/media_modules/Makefile create mode 100644 drivers/amlogic/media_modules/common/Makefile create mode 100644 drivers/amlogic/media_modules/common/chips/chips.c create mode 100644 drivers/amlogic/media_modules/common/chips/chips.h create mode 100644 drivers/amlogic/media_modules/common/firmware/Makefile create mode 100644 drivers/amlogic/media_modules/common/firmware/firmware.h create mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_cfg.h create mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_drv.c create mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_type.c create mode 100644 drivers/amlogic/media_modules/common/firmware/firmware_type.h create mode 100644 drivers/amlogic/media_modules/common/media_clock/Makefile create mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clk.c create mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clk.h create mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h create mode 100644 drivers/amlogic/media_modules/common/media_clock/clk/clkgx.c create mode 100644 drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c create mode 100644 drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h create mode 100644 drivers/amlogic/media_modules/frame_provider/Makefile create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/Makefile create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c create mode 100644 drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h create mode 100644 drivers/amlogic/media_modules/frame_sink/Makefile create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/Makefile create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c create mode 100644 drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h create mode 100644 drivers/amlogic/media_modules/include/dummy-for-git-empty-dir create mode 100644 drivers/amlogic/media_modules/stream_input/Makefile create mode 100644 drivers/amlogic/media_modules/stream_input/amports/Makefile create mode 100644 drivers/amlogic/media_modules/stream_input/amports/adec.c create mode 100644 drivers/amlogic/media_modules/stream_input/amports/adec.h create mode 100644 drivers/amlogic/media_modules/stream_input/amports/amports_priv.h create mode 100644 drivers/amlogic/media_modules/stream_input/amports/amstream.c create mode 100644 drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/esparser.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/esparser.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/psparser.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/psparser.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/rmparser.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/rmparser.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/streambuf.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/streambuf.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/thread_rw.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/thread_rw.h create mode 100644 drivers/amlogic/media_modules/stream_input/parser/tsdemux.c create mode 100644 drivers/amlogic/media_modules/stream_input/parser/tsdemux.h create mode 100644 firmware/video/video_ucode.bin diff --git a/drivers/amlogic/.gitignore b/drivers/amlogic/.gitignore new file mode 100644 index 000000000000..c9423b3761ed --- /dev/null +++ b/drivers/amlogic/.gitignore @@ -0,0 +1,101 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# NOTE! Please use 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. +# +# Normal rules +# +.* +*.o +*.o.* +*.a +*.s +*.ko +*.so +*.so.dbg +*.mod.c +*.i +*.lst +*.symtypes +*.order +modules.builtin +*.elf +#*.bin +*.gz +*.bz2 +*.lzma +*.xz +*.lz4 +*.lzo +*.patch +*.gcno + +# +# Top-level generic files +# +/tags +/TAGS +/linux +/vmlinux +/vmlinuz +/System.map +/Module.markers +Module.symvers + +# +# Debian directory (make deb-pkg) +# +/debian/ + +# +# git files that we don't want to ignore even it they are dot-files +# +!.gitignore +!.mailmap + +# +# Generated include files +# +include/config +include/generated +arch/*/include/generated + +# stgit generated dirs +patches-* + +# quilt's files +patches +series + +# cscope files +cscope.* +ncscope.* + +# gnu global files +GPATH +GRTAGS +GSYMS +GTAGS + +*.orig +*~ +\#*# + +# +# Leavings from module signing +# +extra_certificates +signing_key.priv +signing_key.x509 +x509.genkey + +# Kconfig presets +all.config + +# customer folder +customer + diff --git a/drivers/amlogic/Media.mk b/drivers/amlogic/Media.mk new file mode 100644 index 000000000000..2dbf863859b4 --- /dev/null +++ b/drivers/amlogic/Media.mk @@ -0,0 +1,91 @@ +KERNEL_ARCH := arm64 +CONFIGS := CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_VC1=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_4K2K=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H265=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_VP9=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_REAL=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \ + CONFIG_AMLOGIC_MEDIA_VENC_H264=m \ + CONFIG_AMLOGIC_MEDIA_VECN_H265=m + +define copy-media-modules +$(foreach m, $(shell find $(strip $(1)) -name "*.ko"),\ + $(shell cp $(m) $(strip $(2)) -rfa)) +endef + +ifneq (,$(ANDROID_BUILD_TOP)) +KDIR := $(OUT)/obj/KERNEL_OBJ/ + +MEDIA_DRIVERS := $(ANDROID_BUILD_TOP)/hardware/amlogic/media_modules/drivers +ifeq (,$(wildcard $(MEDIA_DRIVERS))) +$(error No find the dir of drivers.) +endif + +INCLUDE := $(MEDIA_DRIVERS)/include +ifeq (,$(wildcard $(INCLUDE))) +$(error No find the dir of include.) +endif + +MEDIA_MODULES := $(ANDROID_BUILD_TOP)/$(PRODUCT_OUT)/obj/media_modules +ifeq (,$(wildcard $(MEDIA_MODULES))) +$(shell mkdir $(MEDIA_MODULES) -p) +endif + +MODS_OUT := $(ANDROID_BUILD_TOP)/$(TARGET_OUT)/lib + +$(shell cp $(MEDIA_DRIVERS)/* $(MEDIA_MODULES) -rfa) + +define media-modules + @$(MAKE) -C $(KDIR) M=$(MEDIA_MODULES) ARCH=$(KERNEL_ARCH) \ + CROSS_COMPILE=$(PREFIX_CROSS_COMPILE) $(CONFIGS) \ + EXTRA_CFLAGS+=-I$(INCLUDE) modules; \ + find $(MEDIA_MODULES) -name "*.ko" | xargs -i cp {} $(MODS_OUT) +endef + +else +KDIR := $(PWD)/kernel +ifeq (,$(wildcard $(KDIR))) +$(error No find the dir of kernel.) +endif + +MEDIA_DRIVERS := $(PWD)/media_modules/drivers +ifeq (,$(wildcard $(MEDIA_DRIVERS))) +$(error No find the dir of drivers.) +endif + +INCLUDE := $(MEDIA_DRIVERS)/include +ifeq (,$(wildcard $(INCLUDE))) +$(error No find the dir of include.) +endif + +MODS_OUT ?= $(MEDIA_DRIVERS)/../modules +ifeq (,$(wildcard $(MODS_OUT))) +$(shell mkdir $(MODS_OUT) -p) +endif + +TOOLS := /opt/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- + +modules: + @$(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) \ + CROSS_COMPILE=$(TOOLS) $(CONFIGS) \ + EXTRA_CFLAGS+=-I$(INCLUDE) -j64 + +copy-modules: + @echo "start copying media modules." + $(call copy-media-modules, $(MEDIA_DRIVERS), $(MODS_OUT)) + +all: modules copy-modules + +clean: + $(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) clean + +endif diff --git a/drivers/amlogic/media_modules/Makefile b/drivers/amlogic/media_modules/Makefile new file mode 100644 index 000000000000..f2a514848876 --- /dev/null +++ b/drivers/amlogic/media_modules/Makefile @@ -0,0 +1,4 @@ +obj-y += common/ +obj-y += frame_provider/ +obj-y += frame_sink/ +obj-y += stream_input/ diff --git a/drivers/amlogic/media_modules/common/Makefile b/drivers/amlogic/media_modules/common/Makefile new file mode 100644 index 000000000000..77ce080249db --- /dev/null +++ b/drivers/amlogic/media_modules/common/Makefile @@ -0,0 +1,2 @@ +obj-y += media_clock/ +obj-y += firmware/ diff --git a/drivers/amlogic/media_modules/common/chips/chips.c b/drivers/amlogic/media_modules/common/chips/chips.c new file mode 100644 index 000000000000..f2e7fa67e9d7 --- /dev/null +++ b/drivers/amlogic/media_modules/common/chips/chips.c @@ -0,0 +1,158 @@ +/* + * drivers/amlogic/media/common/arch/chips/chips.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../../stream_input/amports/amports_priv.h" +#include "../../frame_provider/decoder/utils/vdec.h" +#include "chips.h" +#include + +#define VIDEO_FIRMWARE_FATHER_NAME "video" + +/* +*#define MESON_CPU_MAJOR_ID_M6 0x16 +*#define MESON_CPU_MAJOR_ID_M6TV 0x17 +*#define MESON_CPU_MAJOR_ID_M6TVL 0x18 +*#define MESON_CPU_MAJOR_ID_M8 0x19 +*#define MESON_CPU_MAJOR_ID_MTVD 0x1A +*#define MESON_CPU_MAJOR_ID_M8B 0x1B +*#define MESON_CPU_MAJOR_ID_MG9TV 0x1C +*#define MESON_CPU_MAJOR_ID_M8M2 0x1D +*#define MESON_CPU_MAJOR_ID_GXBB 0x1F +*#define MESON_CPU_MAJOR_ID_GXTVBB 0x20 +*#define MESON_CPU_MAJOR_ID_GXL 0x21 +*#define MESON_CPU_MAJOR_ID_GXM 0x22 +*#define MESON_CPU_MAJOR_ID_TXL 0x23 +*/ +struct type_name { + + int type; + + const char *name; +}; +static const struct type_name cpu_type_name[] = { + {MESON_CPU_MAJOR_ID_M6, "m6"}, + {MESON_CPU_MAJOR_ID_M6TV, "m6tv"}, + {MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"}, + {MESON_CPU_MAJOR_ID_M8, "m8"}, + {MESON_CPU_MAJOR_ID_MTVD, "mtvd"}, + {MESON_CPU_MAJOR_ID_M8B, "m8b"}, + {MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"}, + {MESON_CPU_MAJOR_ID_M8M2, "m8"}, + {MESON_CPU_MAJOR_ID_GXBB, "gxbb"}, + {MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"}, + {MESON_CPU_MAJOR_ID_GXL, "gxl"}, + {MESON_CPU_MAJOR_ID_GXM, "gxm"}, + {MESON_CPU_MAJOR_ID_TXL, "txl"}, + {0, NULL}, +}; + +static const char *get_type_name(const struct type_name *typename, int size, + int type) +{ + + const char *name = "unknown"; + + int i; + + for (i = 0; i < size; i++) { + + if (type == typename[i].type) + + name = typename[i].name; + + } + + return name; +} + +const char *get_cpu_type_name(void) +{ + + return get_type_name(cpu_type_name, + sizeof(cpu_type_name) / sizeof(struct type_name), + get_cpu_type()); +} +EXPORT_SYMBOL(get_cpu_type_name); + +/* +*enum vformat_e { +* VFORMAT_MPEG12 = 0, +* VFORMAT_MPEG4, +* VFORMAT_H264, +* VFORMAT_MJPEG, +* VFORMAT_REAL, +* VFORMAT_JPEG, +* VFORMAT_VC1, +* VFORMAT_AVS, +* VFORMAT_YUV, +* VFORMAT_H264MVC, +* VFORMAT_H264_4K2K, +* VFORMAT_HEVC, +* VFORMAT_H264_ENC, +* VFORMAT_JPEG_ENC, +* VFORMAT_VP9, +* VFORMAT_MAX +*}; +*/ +static const struct type_name vformat_type_name[] = { + {VFORMAT_MPEG12, "mpeg12"}, + {VFORMAT_MPEG4, "mpeg4"}, + {VFORMAT_H264, "h264"}, + {VFORMAT_MJPEG, "mjpeg"}, + {VFORMAT_REAL, "real"}, + {VFORMAT_JPEG, "jpeg"}, + {VFORMAT_VC1, "vc1"}, + {VFORMAT_AVS, "avs"}, + {VFORMAT_YUV, "yuv"}, + {VFORMAT_H264MVC, "h264mvc"}, + {VFORMAT_H264_4K2K, "h264_4k"}, + {VFORMAT_HEVC, "hevc"}, + {VFORMAT_H264_ENC, "h264_enc"}, + {VFORMAT_JPEG_ENC, "jpeg_enc"}, + {VFORMAT_VP9, "vp9"}, + {VFORMAT_YUV, "yuv"}, + {0, NULL}, +}; + +const char *get_video_format_name(enum vformat_e type) +{ + + return get_type_name(vformat_type_name, + sizeof(vformat_type_name) / sizeof(struct type_name), type); +} +EXPORT_SYMBOL(get_video_format_name); + +static struct chip_vdec_info_s current_chip_info; + +struct chip_vdec_info_s *get_current_vdec_chip(void) +{ + + return ¤t_chip_info; +} +EXPORT_SYMBOL(get_current_vdec_chip); + diff --git a/drivers/amlogic/media_modules/common/chips/chips.h b/drivers/amlogic/media_modules/common/chips/chips.h new file mode 100644 index 000000000000..7a9fabac00b2 --- /dev/null +++ b/drivers/amlogic/media_modules/common/chips/chips.h @@ -0,0 +1,39 @@ +/* + * drivers/amlogic/media/common/arch/chips/chips.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef UCODE_MANAGER_HEADER +#define UCODE_MANAGER_HEADER +#include "../firmware/firmware.h" +#include "../media_clock/clk/clk_priv.h" + +struct chip_vdec_info_s { + + int cpu_type; + + struct video_firmware_s *firmware; + + struct chip_vdec_clk_s *clk_mgr[VDEC_MAX]; + + struct clk_set_setting *clk_setting_array; +}; + +const char *get_cpu_type_name(void); +const char *get_video_format_name(enum vformat_e type); + +struct chip_vdec_info_s *get_current_vdec_chip(void); + +#endif diff --git a/drivers/amlogic/media_modules/common/firmware/Makefile b/drivers/amlogic/media_modules/common/firmware/Makefile new file mode 100644 index 000000000000..748039cc1f71 --- /dev/null +++ b/drivers/amlogic/media_modules/common/firmware/Makefile @@ -0,0 +1,3 @@ +obj-m += firmware.o +firmware-objs += firmware_drv.o +firmware-objs += firmware_type.o diff --git a/drivers/amlogic/media_modules/common/firmware/firmware.h b/drivers/amlogic/media_modules/common/firmware/firmware.h new file mode 100644 index 000000000000..b7d56d71e6c5 --- /dev/null +++ b/drivers/amlogic/media_modules/common/firmware/firmware.h @@ -0,0 +1,113 @@ +/* + * drivers/amlogic/media/common/firmware/firmware.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef __VIDEO_FIRMWARE_HEADER_ +#define __VIDEO_FIRMWARE_HEADER_ +#include +#include +#include +#include +#include "firmware_type.h" +#include + + +struct firmware_mgr_s { + struct list_head head; + spinlock_t lock; +}; + +struct firmware_info_s { + struct list_head node; + char name[32]; + char path[64]; + enum firmware_type_e type; + struct firmware_s *data; +}; + +struct ucode_info_s { + int cpu; + enum firmware_type_e type; + const char *name; +}; + +struct firmware_header_s { + int magic; + int checksum; + char name[32]; + char cpu[16]; + char format[32]; + char version[32]; + char author[32]; + char date[32]; + char commit[16]; + int data_size; + unsigned int time; + char reserved[128]; +}; + +struct firmware_s { + union { + struct firmware_header_s header; + char buf[512]; + }; + char data[0]; +}; + + +struct package_header_s { + int magic; + int size; + int checksum; + char reserved[128]; +}; + +struct package_s { + union { + struct package_header_s header; + char buf[256]; + }; + char data[0]; +}; + +struct info_header_s { + char name[32]; + char format[32]; + char cpu[32]; + int length; +}; + +struct package_info_s { + union { + struct info_header_s header; + char buf[256]; + }; + char data[0]; +}; + + +struct firmware_dev_s { + struct cdev cdev; + struct device *dev; + dev_t dev_no; +}; + +int get_decoder_firmware_data(enum vformat_e type, + const char *file_name, char *buf, int size); +int get_data_from_name(const char *name, char *buf); +int get_firmware_data(enum firmware_type_e type, char *buf); + +#endif diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h new file mode 100644 index 000000000000..be919ff5ecde --- /dev/null +++ b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h @@ -0,0 +1,32 @@ +/* + * drivers/amlogic/media/common/firmware/firmware_cfg.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +/*all firmwares in one bin.*/ +{MESON_CPU_MAJOR_ID_GXBB, VIDEO_PACKAGE, "video_ucode.bin"}, +{MESON_CPU_MAJOR_ID_GXTVBB, VIDEO_PACKAGE, "video_ucode.bin"}, +{MESON_CPU_MAJOR_ID_GXL, VIDEO_PACKAGE, "video_ucode.bin"}, +{MESON_CPU_MAJOR_ID_GXM, VIDEO_PACKAGE, "video_ucode.bin"}, +{MESON_CPU_MAJOR_ID_TXL, VIDEO_PACKAGE, "video_ucode.bin"}, + +/*firmware for a special format, to replace the format in the package.*/ +{MESON_CPU_MAJOR_ID_GXL, VIDEO_DEC_HEVC, "h265.bin"}, +{MESON_CPU_MAJOR_ID_GXL, VIDEO_DEC_H264, "h264.bin"}, +{MESON_CPU_MAJOR_ID_GXL, VIDEO_DEC_H264_MULTI, "h264_multi.bin"}, +{MESON_CPU_MAJOR_ID_GXM, VIDEO_ENC_H264, "gx_h264_enc.bin"}, +{MESON_CPU_MAJOR_ID_GXL, VIDEO_ENC_H264, "gx_h264_enc.bin"}, + + diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c new file mode 100644 index 000000000000..56420e11249e --- /dev/null +++ b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c @@ -0,0 +1,682 @@ +/* + * drivers/amlogic/media/common/firmware/firmware.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../../stream_input/amports/amports_priv.h" +#include "../../frame_provider/decoder/utils/vdec.h" +#include "firmware.h" +#include "../chips/chips.h" +#include +#include +#include +#include +#include +#include + +#define CLASS_NAME "firmware_codec" +#define DEV_NAME "firmware_vdec" +#define DIR "video" +#define FRIMWARE_SIZE (64*1024) /*64k*/ +#define BUFF_SIZE (512*1024) + +#define PACK ('P' << 24 | 'A' << 16 | 'C' << 8 | 'K') +#define CODE ('C' << 24 | 'O' << 16 | 'D' << 8 | 'E') + +static DEFINE_MUTEX(mutex); + +static struct ucode_info_s ucode_info[] = { +#include "firmware_cfg.h" +}; + +static const struct file_operations firmware_fops = { + .owner = THIS_MODULE +}; + +struct firmware_mgr_s *g_mgr; +struct firmware_dev_s *g_dev; + +static u32 debug = 0; + +int get_firmware_data(enum firmware_type_e type, char *buf) +{ + int data_len, ret = -1; + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info; + + if (list_empty(&mgr->head)) { + pr_info("the info list is empty.\n"); + return 0; + } + + list_for_each_entry(info, &mgr->head, node) { + if (type != info->type) + continue; + + data_len = info->data->header.data_size; + memcpy(buf, info->data->data, data_len); + ret = data_len; + + break; + } + + return ret; +} +EXPORT_SYMBOL(get_firmware_data); + +int get_data_from_name(const char *name, char *buf) +{ + int data_len, ret = -1; + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info; + char *firmware_name = __getname(); + + if (IS_ERR_OR_NULL(firmware_name)) + return -ENOMEM; + + strcat(firmware_name, name); + strcat(firmware_name, ".bin"); + + if (list_empty(&mgr->head)) { + pr_info("the info list is empty.\n"); + return 0; + } + + list_for_each_entry(info, &mgr->head, node) { + if (strcmp(firmware_name, info->name)) + continue; + + data_len = info->data->header.data_size; + memcpy(buf, info->data->data, data_len); + ret = data_len; + + break; + } + + __putname(firmware_name); + + return ret; +} +EXPORT_SYMBOL(get_data_from_name); + +static int request_firmware_from_sys(const char *file_name, + char *buf, int size) +{ + int ret = -1; + const struct firmware *firmware; + + pr_info("Try load %s ...\n", file_name); + + ret = request_firmware(&firmware, file_name, g_dev->dev); + if (ret < 0) { + pr_info("Error : %d can't load the %s.\n", ret, file_name); + goto err; + } + + if (firmware->size > size) { + pr_info("Not enough memory size for ucode.\n"); + ret = -ENOMEM; + goto release; + } + + memcpy(buf, (char *)firmware->data, firmware->size); + + pr_info("load firmware size : %zd, Name : %s.\n", + firmware->size, file_name); + ret = firmware->size; +release: + release_firmware(firmware); +err: + return ret; +} + +int request_decoder_firmware_on_sys(enum vformat_e type, + const char *file_name, char *buf, int size) +{ + int ret; + + ret = get_data_from_name(file_name, buf); + if (ret < 0) + pr_info("Get firmware fail.\n"); + + if (ret > size) { + pr_info("Not enough memory.\n"); + return -ENOMEM; + } + + return ret; +} +int get_decoder_firmware_data(enum vformat_e type, + const char *file_name, char *buf, int size) +{ + int ret; + + ret = request_decoder_firmware_on_sys(type, file_name, buf, size); + if (ret < 0) + pr_info("get_decoder_firmware_data %s for format %d failed!\n", + file_name, type); + + return ret; +} +EXPORT_SYMBOL(get_decoder_firmware_data); + +static unsigned long firmware_mgr_lock(struct firmware_mgr_s *mgr) +{ + unsigned long flags; + + spin_lock_irqsave(&mgr->lock, flags); + return flags; +} + +static void firmware_mgr_unlock(struct firmware_mgr_s *mgr, unsigned long flags) +{ + spin_unlock_irqrestore(&mgr->lock, flags); +} + +static void add_info(struct firmware_info_s *info) +{ + unsigned long flags; + struct firmware_mgr_s *mgr = g_mgr; + + flags = firmware_mgr_lock(mgr); + list_add(&info->node, &mgr->head); + firmware_mgr_unlock(mgr, flags); +} + +static void del_info(struct firmware_info_s *info) +{ + unsigned long flags; + struct firmware_mgr_s *mgr = g_mgr; + + flags = firmware_mgr_lock(mgr); + list_del(&info->node); + firmware_mgr_unlock(mgr, flags); +} + +static void walk_firmware_info(void) +{ + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info; + + if (list_empty(&mgr->head)) { + pr_info("the info list is empty.\n"); + return ; + } + + list_for_each_entry(info, &mgr->head, node) { + if (IS_ERR_OR_NULL(info->data)) + continue; + + pr_info("path : %s.\n", info->path); + pr_info("name : %s.\n", info->name); + pr_info("version : %s.\n", + info->data->header.version); + pr_info("checksum : 0x%x.\n", + info->data->header.checksum); + pr_info("data size : %d.\n", + info->data->header.data_size); + pr_info("author : %s.\n", + info->data->header.author); + pr_info("date : %s.\n", + info->data->header.date); + pr_info("commit : %s.\n\n", + info->data->header.commit); + } +} + +static ssize_t info_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info; + + if (list_empty(&mgr->head)) { + pbuf += sprintf(pbuf, "No firmware.\n"); + goto out; + } + + list_for_each_entry(info, &mgr->head, node) { + if (IS_ERR_OR_NULL(info->data)) + continue; + + pr_info( "%10s : %s\n", "name", info->name); + pr_info( "%10s : %d\n", "size", + info->data->header.data_size); + pr_info( "%10s : %s\n", "ver", + info->data->header.version); + pr_info( "%10s : 0x%x\n", "sum", + info->data->header.checksum); + pr_info( "%10s : %s\n", "commit", + info->data->header.commit); + pr_info( "%10s : %s\n", "author", + info->data->header.author); + pr_info( "%10s : %s\n\n", "date", + info->data->header.date); + } +out: + return pbuf - buf; +} + +static int set_firmware_info(void) +{ + int ret = 0, i, len; + struct firmware_info_s *info; + int info_size = ARRAY_SIZE(ucode_info); + int cpu = get_cpu_type(); + char *path = __getname(); + const char *name; + + if (IS_ERR_OR_NULL(path)) + return -ENOMEM; + + for (i = 0; i < info_size; i++) { + if (cpu != ucode_info[i].cpu) + continue; + + name = ucode_info[i].name; + if (IS_ERR_OR_NULL(name)) + break; + + len = snprintf(path, PATH_MAX, "%s/%s", DIR, + ucode_info[i].name); + if (len >= PATH_MAX) + continue; + + info = kzalloc(sizeof(struct firmware_info_s), GFP_KERNEL); + if (IS_ERR_OR_NULL(info)) { + __putname(path); + return -ENOMEM; + } + + strcpy(info->path, path); + strcpy(info->name, name); + info->type = ucode_info[i].type; + info->data = NULL; + + add_info(info); + } + + __putname(path); + + return ret; +} + +static int firmware_probe(char *buf) +{ + int magic = 0; + + memcpy(&magic, buf, sizeof(int)); + return magic; +} + +static int checksum(struct firmware_s *firmware) +{ + unsigned int crc; + + crc = crc32_le(~0U, firmware->data, firmware->header.data_size); + + if (debug) + pr_info("firmware crc result : 0x%x\n", crc ^ ~0U); + + return firmware->header.checksum != (crc ^ ~0U) ? 0 : 1; +} + +static int check_repeat(struct firmware_s *data, enum firmware_type_e type) +{ + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info; + + if (list_empty(&mgr->head)) { + pr_info("the info list is empty.\n"); + return -1; + } + + list_for_each_entry(info, &mgr->head, node) { + if (info->type != type) + continue; + + if (IS_ERR_OR_NULL(info->data)) + info->data = data; + + return 1; + } + + return 0; +} + +static int firmware_parse_package(char *buf, int size) +{ + int ret = 0; + struct package_info_s *pack_info; + struct firmware_info_s *info; + struct firmware_s *data; + char *pack_data; + int info_len, len; + char *path = __getname(); + + if (IS_ERR_OR_NULL(path)) + return -ENOMEM; + + pack_data = ((struct package_s *)buf)->data; + pack_info = (struct package_info_s *)pack_data; + info_len = sizeof(struct package_info_s); + + for (;;) { + if (!pack_info->header.length) + break; + + len = snprintf(path, PATH_MAX, "%s/%s", DIR, + pack_info->header.name); + if (len >= PATH_MAX) + continue; + + info = kzalloc(sizeof(struct firmware_info_s), GFP_KERNEL); + if (IS_ERR_OR_NULL(info)) { + ret = -ENOMEM; + goto out; + } + + data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); + if (IS_ERR_OR_NULL(data)) { + kfree(info); + ret = -ENOMEM; + goto out; + } + + strcpy(info->path, path); + strcpy(info->name, pack_info->header.name); + info->type = get_firmware_type(pack_info->header.format); + + len = pack_info->header.length; + memcpy(data, pack_info->data, len); + + pack_data += (pack_info->header.length + info_len); + pack_info = (struct package_info_s *)pack_data; + + ret = checksum(data); + if (!ret) { + pr_info("check sum fail !\n"); + kfree(data); + kfree(info); + goto out; + } + + ret = check_repeat(data, info->type); + if (ret < 0) { + kfree(data); + kfree(info); + goto out; + } + + if (ret) { + kfree(info); + continue; + } + + info->data = data; + add_info(info); + } +out: + __putname(path); + + return ret; +} + +static int firmware_parse_code(struct firmware_info_s *info, + char *buf, int size) +{ + if (!IS_ERR_OR_NULL(info->data)) + kfree(info->data); + + info->data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); + if (IS_ERR_OR_NULL(info->data)) + return -ENOMEM; + + memcpy(info->data, buf, size); + + if (!checksum(info->data)) { + pr_info("check sum fail !\n"); + kfree(info->data); + return -1; + } + + return 0; +} + +static int get_firmware_from_sys(const char *path, + char *buf, int size) +{ + int len = 0; + + len = request_firmware_from_sys(path, buf, size); + if (len < 0) + pr_info("get data from fsys fail.\n"); + + return len; +} + +static int set_firmware_data(void) +{ + int ret = 0, magic = 0; + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info, *temp; + char *buf = NULL; + int size; + + if (list_empty(&mgr->head)) { + pr_info("the info list is empty.\n"); + return 0; + } + + buf = vmalloc(BUFF_SIZE); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + list_for_each_entry_safe(info, temp, &mgr->head, node) { + size = get_firmware_from_sys(info->path, buf, BUFF_SIZE); + magic = firmware_probe(buf); + + switch (magic) { + case PACK: + ret = firmware_parse_package(buf, size); + + del_info(info); + kfree(info); + break; + + case CODE: + ret = firmware_parse_code(info, buf, size); + break; + + default: + del_info(info); + pr_info("invaild type.\n"); + } + + memset(buf, 0, BUFF_SIZE); + } + + if (debug) + walk_firmware_info(); + + vfree(buf); + + return ret; +} + +static int firmware_pre_load(void) +{ + int ret = -1; + + ret = set_firmware_info(); + if (ret < 0) { + pr_info("Get path fail.\n"); + goto err; + } + + ret = set_firmware_data(); + if (ret < 0) { + pr_info("Set data fail.\n"); + goto err; + } +err: + return ret; +} + +static int firmware_mgr_init(void) +{ + g_mgr = kzalloc(sizeof(struct firmware_mgr_s), GFP_KERNEL); + if (IS_ERR_OR_NULL(g_mgr)) + return -ENOMEM; + + INIT_LIST_HEAD(&g_mgr->head); + spin_lock_init(&g_mgr->lock); + + return 0; +} + +static struct class_attribute firmware_class_attrs[] = { + __ATTR_RO(info), + __ATTR_NULL +}; + +static struct class firmware_class = { + .name = CLASS_NAME, + .class_attrs = firmware_class_attrs, +}; + +static int firmware_driver_init(void) +{ + int ret = -1; + + g_dev = kzalloc(sizeof(struct firmware_dev_s), GFP_KERNEL); + if (IS_ERR_OR_NULL(g_dev)) + return -ENOMEM; + + g_dev->dev_no = MKDEV(AMSTREAM_MAJOR, 100); + + ret = register_chrdev_region(g_dev->dev_no, 1, DEV_NAME); + if (ret < 0) { + pr_info("Can't get major number %d.\n", AMSTREAM_MAJOR); + goto err; + } + + cdev_init(&g_dev->cdev, &firmware_fops); + g_dev->cdev.owner = THIS_MODULE; + + ret = cdev_add(&g_dev->cdev, g_dev->dev_no, 1); + if (ret) { + pr_info("Error %d adding cdev fail.\n", ret); + goto err; + } + + ret = class_register(&firmware_class); + if (ret < 0) { + pr_info("Failed in creating class.\n"); + goto err; + } + + g_dev->dev = device_create(&firmware_class, NULL, + g_dev->dev_no, NULL, DEV_NAME); + if (IS_ERR_OR_NULL(g_dev->dev)) { + pr_info("Create device failed.\n"); + ret = -ENODEV; + goto err; + } + + pr_info("Registered firmware driver success.\n"); +err: + return ret; +} + +static void firmware_info_clean(void) +{ + struct firmware_mgr_s *mgr = g_mgr; + struct firmware_info_s *info; + unsigned long flags; + + flags = firmware_mgr_lock(mgr); + while (!list_empty(&mgr->head)) { + info = list_entry(mgr->head.next, + struct firmware_info_s, node); + list_del(&info->node); + kfree(info->data); + kfree(info); + } + firmware_mgr_unlock(mgr, flags); + + kfree(g_mgr); +} + +static void firmware_driver_exit(void) +{ + cdev_del(&g_dev->cdev); + device_destroy(&firmware_class, g_dev->dev_no); + class_unregister(&firmware_class); + unregister_chrdev_region(g_dev->dev_no, 1); + kfree(g_dev); +} + +static int __init firmware_module_init(void) +{ + int ret = -1; + + ret = firmware_driver_init(); + if (ret) { + pr_info("Error %d firmware driver init fail.\n", ret); + goto err; + } + + ret = firmware_mgr_init(); + if (ret) { + pr_info("Error %d firmware mgr init fail.\n", ret); + goto err; + } + + ret = firmware_pre_load(); + if (ret) { + pr_info("Error %d firmware pre load fail.\n", ret); + goto err; + } +err: + return ret; +} + +static void __exit firmware_module_exit(void) +{ + firmware_info_clean(); + firmware_driver_exit(); + pr_info("Firmware driver cleaned up.\n"); +} + +module_param(debug, uint, 0664); + +module_init(firmware_module_init); +module_exit(firmware_module_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nanxin Qin "); diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.c b/drivers/amlogic/media_modules/common/firmware/firmware_type.c new file mode 100644 index 000000000000..cf5e306359bc --- /dev/null +++ b/drivers/amlogic/media_modules/common/firmware/firmware_type.c @@ -0,0 +1,57 @@ +#include "firmware_type.h" + +static const struct type_name_s type_name[] = { + {VIDEO_DEC_MPEG12, "mpeg12"}, + {VIDEO_DEC_MPEG4_3, "divx311"}, + {VIDEO_DEC_MPEG4_4, "divx4x"}, + {VIDEO_DEC_MPEG4_5, "xvid"}, + {VIDEO_DEC_H263, "h263"}, + {VIDEO_DEC_MJPEG, "mjpeg"}, + {VIDEO_DEC_MJPEG_MULTI, "mjpeg_multi"}, + {VIDEO_DEC_REAL_V8, "real_v8"}, + {VIDEO_DEC_REAL_V9, "real_v9"}, + {VIDEO_DEC_VC1, "vc1"}, + {VIDEO_DEC_AVS, "avs"}, + {VIDEO_DEC_H264, "h264"}, + {VIDEO_DEC_H264_4k2K, "h264_4k2k"}, + {VIDEO_DEC_H264_4k2K_SINGLE, "h264_4k2k_single"}, + {VIDEO_DEC_H264_MVC, "h264_mvc"}, + {VIDEO_DEC_H264_MULTI, "h264_multi"}, + {VIDEO_DEC_HEVC, "hevc"}, + {VIDEO_DEC_HEVC_MMU, "hevc_mmu"}, + {VIDEO_DEC_VP9, "vp9"}, + {VIDEO_DEC_VP9_MMU, "vp9_mmu"}, + {VIDEO_ENC_H264, "h264_enc"}, + {VIDEO_ENC_JPEG, "jpeg_enc"}, + {FIRMWARE_MAX, "unknown"}, +}; + + +const char *get_firmware_type_name(enum firmware_type_e type) +{ + const char *name = "unknown"; + int i, size = ARRAY_SIZE(type_name); + + for (i = 0; i < size; i++) { + if (type == type_name[i].type) + name = type_name[i].name; + } + + return name; +} +EXPORT_SYMBOL(get_firmware_type_name); + +enum firmware_type_e get_firmware_type(const char *name) +{ + enum firmware_type_e type = FIRMWARE_MAX; + int i, size = ARRAY_SIZE(type_name); + + for (i = 0; i < size; i++) { + if (!strcmp(name, type_name[i].name)) + type = type_name[i].type; + } + + return type; +} +EXPORT_SYMBOL(get_firmware_type); + diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.h b/drivers/amlogic/media_modules/common/firmware/firmware_type.h new file mode 100644 index 000000000000..74c962f4cdb8 --- /dev/null +++ b/drivers/amlogic/media_modules/common/firmware/firmware_type.h @@ -0,0 +1,41 @@ +#ifndef __VIDEO_FIRMWARE_FORMAT_ +#define __VIDEO_FIRMWARE_FORMAT_ + +#include + +enum firmware_type_e { + VIDEO_DEC_MPEG12, + VIDEO_DEC_MPEG4_3, + VIDEO_DEC_MPEG4_4, + VIDEO_DEC_MPEG4_5, + VIDEO_DEC_H263, + VIDEO_DEC_MJPEG, + VIDEO_DEC_MJPEG_MULTI, + VIDEO_DEC_REAL_V8, + VIDEO_DEC_REAL_V9, + VIDEO_DEC_VC1, + VIDEO_DEC_AVS, + VIDEO_DEC_H264, + VIDEO_DEC_H264_4k2K, + VIDEO_DEC_H264_4k2K_SINGLE, + VIDEO_DEC_H264_MVC, + VIDEO_DEC_H264_MULTI, + VIDEO_DEC_HEVC, + VIDEO_DEC_HEVC_MMU, + VIDEO_DEC_VP9, + VIDEO_DEC_VP9_MMU, + VIDEO_ENC_H264, + VIDEO_ENC_JPEG, + VIDEO_PACKAGE, + FIRMWARE_MAX +}; + +struct type_name_s { + enum firmware_type_e type; + const char *name; +}; + +const char *get_firmware_type_name(enum firmware_type_e type); +enum firmware_type_e get_firmware_type(const char *name); + +#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/Makefile b/drivers/amlogic/media_modules/common/media_clock/Makefile new file mode 100644 index 000000000000..25c9a108031e --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/Makefile @@ -0,0 +1,5 @@ +obj-m += media_clock.o +media_clock-objs += ../chips/chips.o +media_clock-objs += clk/clkgx.o +media_clock-objs += clk/clk.o +media_clock-objs += switch/amports_gate.o diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c new file mode 100644 index 000000000000..18d308ff5200 --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c @@ -0,0 +1,405 @@ +/* + * drivers/amlogic/media/common/arch/clk/clk.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../../../stream_input/amports/amports_priv.h" +#include "../../../frame_provider/decoder/utils/vdec.h" +#include "../../chips/chips.h" +#include "clk_priv.h" +#include + +#define p_vdec() (get_current_vdec_chip()->clk_mgr[VDEC_1]) +#define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2]) +#define p_vdec_hcodec() (get_current_vdec_chip()->clk_mgr[VDEC_HCODEC]) +#define p_vdec_hevc() (get_current_vdec_chip()->clk_mgr[VDEC_HEVC]) + +static int clock_source_wxhxfps_saved[VDEC_MAX + 1]; + +#define IF_HAVE_RUN(p, fn)\ + do {\ + if (p && p->fn)\ + p->fn();\ + } while (0) +/* +*#define IF_HAVE_RUN_P1_RET(p, fn, p1)\ +* do {\ +* pr_debug("%s-----%d\n", __func__, clk);\ +* if (p && p->fn)\ +* return p->fn(p1);\ +* else\ +* return -1;\ +* } while (0) +* +*#define IF_HAVE_RUN_RET(p, fn)\ +* do {\ +* if (p && p->fn)\ +* return p->fn();\ +* else\ +* return 0;\ +* } while (0) +*/ + +int vdec_clock_init(void) +{ + if (p_vdec() && p_vdec()->clock_init) + return p_vdec()->clock_init(); + else + return 0; +} +EXPORT_SYMBOL(vdec_clock_init); + +/* +*clk ==0 : +* to be release. +* released shared clk, +*clk ==1 :default low clk +*clk ==2 :default high clk +*/ +int vdec_clock_set(int clk) +{ + pr_debug("%s-----%d\n", __func__, clk); + if (p_vdec() && p_vdec()->clock_set) + return p_vdec()->clock_set(clk); + else + return -1; +} +EXPORT_SYMBOL(vdec_clock_set); + +void vdec_clock_enable(void) +{ + vdec_clock_set(1); +} +EXPORT_SYMBOL(vdec_clock_enable); + +void vdec_clock_hi_enable(void) +{ + vdec_clock_set(2); +} +EXPORT_SYMBOL(vdec_clock_hi_enable); + +void vdec_clock_on(void) +{ + IF_HAVE_RUN(p_vdec(), clock_on); +} +EXPORT_SYMBOL(vdec_clock_on); + +void vdec_clock_off(void) +{ + IF_HAVE_RUN(p_vdec(), clock_off); + clock_source_wxhxfps_saved[VDEC_1] = 0; +} +EXPORT_SYMBOL(vdec_clock_off); + +int vdec2_clock_set(int clk) +{ + pr_debug("%s-----%d\n", __func__, clk); + if (p_vdec2() && p_vdec2()->clock_set) + return p_vdec2()->clock_set(clk); + else + return -1; +} +EXPORT_SYMBOL(vdec2_clock_set); + +void vdec2_clock_enable(void) +{ + vdec2_clock_set(1); +} +EXPORT_SYMBOL(vdec2_clock_enable); + +void vdec2_clock_hi_enable(void) +{ + vdec2_clock_set(2); +} +EXPORT_SYMBOL(vdec2_clock_hi_enable); + +void vdec2_clock_on(void) +{ + IF_HAVE_RUN(p_vdec2(), clock_on); +} +EXPORT_SYMBOL(vdec2_clock_on); + +void vdec2_clock_off(void) +{ + IF_HAVE_RUN(p_vdec2(), clock_off); + clock_source_wxhxfps_saved[VDEC_2] = 0; +} +EXPORT_SYMBOL(vdec2_clock_off); + +int hcodec_clock_set(int clk) +{ + pr_debug("%s-----%d\n", __func__, clk); + if (p_vdec_hcodec() && p_vdec_hcodec()->clock_set) + return p_vdec_hcodec()->clock_set(clk); + else + return -1; +} +EXPORT_SYMBOL(hcodec_clock_set); + +void hcodec_clock_enable(void) +{ + hcodec_clock_set(1); +} +EXPORT_SYMBOL(hcodec_clock_enable); + +void hcodec_clock_hi_enable(void) +{ + hcodec_clock_set(2); +} +EXPORT_SYMBOL(hcodec_clock_hi_enable); + +void hcodec_clock_on(void) +{ + IF_HAVE_RUN(p_vdec_hcodec(), clock_on); +} +EXPORT_SYMBOL(hcodec_clock_on); + +void hcodec_clock_off(void) +{ + IF_HAVE_RUN(p_vdec_hcodec(), clock_off); + clock_source_wxhxfps_saved[VDEC_HCODEC] = 0; +} +EXPORT_SYMBOL(hcodec_clock_off); + +int hevc_clock_init(void) +{ + if (p_vdec_hevc() && p_vdec_hevc()->clock_init) + return p_vdec_hevc()->clock_init(); + else + return 0; +} +EXPORT_SYMBOL(hevc_clock_init); + +int hevc_clock_set(int clk) +{ + pr_debug("%s-----%d\n", __func__, clk); + if (p_vdec_hevc() && p_vdec_hevc()->clock_set) + return p_vdec_hevc()->clock_set(clk); + else + return -1; +} +EXPORT_SYMBOL(hevc_clock_set); + +void hevc_clock_enable(void) +{ + hevc_clock_set(1); +} +EXPORT_SYMBOL(hevc_clock_enable); + +void hevc_clock_hi_enable(void) +{ + hevc_clock_set(2); +} +EXPORT_SYMBOL(hevc_clock_hi_enable); + +void hevc_clock_on(void) +{ + IF_HAVE_RUN(p_vdec_hevc(), clock_on); +} +EXPORT_SYMBOL(hevc_clock_on); + +void hevc_clock_off(void) +{ + IF_HAVE_RUN(p_vdec_hevc(), clock_off); + clock_source_wxhxfps_saved[VDEC_HEVC] = 0; +} +EXPORT_SYMBOL(hevc_clock_off); + +int vdec_source_get(enum vdec_type_e core) +{ + return clock_source_wxhxfps_saved[core]; +} +EXPORT_SYMBOL(vdec_source_get); + +int vdec_clk_get(enum vdec_type_e core) +{ + return get_current_vdec_chip()->clk_mgr[core]->clock_get(core); +} +EXPORT_SYMBOL(vdec_clk_get); + +int get_clk_with_source(int format, int w_x_h_fps) +{ + struct clk_set_setting *p_setting; + int i; + int clk = -2; + + p_setting = get_current_vdec_chip()->clk_setting_array; + if (!p_setting || format < 0 || format > VFORMAT_MAX) { + pr_info("error on get_clk_with_source ,%p,%d\n", + p_setting, format); + return -1; /*no setting found. */ + } + p_setting = &p_setting[format]; + for (i = 0; i < MAX_CLK_SET; i++) { + if (p_setting->set[i].wh_X_fps > w_x_h_fps) { + clk = p_setting->set[i].clk_Mhz; + break; + } + } + return clk; +} +EXPORT_SYMBOL(get_clk_with_source); + +int vdec_source_changed_for_clk_set(int format, int width, int height, int fps) +{ + int clk = get_clk_with_source(format, width * height * fps); + int ret_clk; + + if (clk < 0) { + pr_info("can't get valid clk for source ,%d,%d,%d\n", + width, height, fps); + if (format >= 1920 && width >= 1080 && fps >= 30) + clk = 2; /*default high clk */ + else + clk = 0; /*default clk. */ + } + if (width * height * fps == 0) + clk = 0; + /* + *clk == 0 + *is used for set default clk; + *if used supper clk. + *changed to default min clk. + */ + + if (format == VFORMAT_HEVC || format == VFORMAT_VP9) { + ret_clk = hevc_clock_set(clk); + clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps; + } else if (format == VFORMAT_H264_ENC && format == VFORMAT_JPEG_ENC) { + ret_clk = hcodec_clock_set(clk); + clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps; + } else if (format == VFORMAT_H264_4K2K && + get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { + ret_clk = vdec2_clock_set(clk); + clock_source_wxhxfps_saved[VDEC_2] = width * height * fps; + ret_clk = vdec_clock_set(clk); + clock_source_wxhxfps_saved[VDEC_1] = width * height * fps; + } else { + ret_clk = vdec_clock_set(clk); + clock_source_wxhxfps_saved[VDEC_1] = width * height * fps; + } + return ret_clk; +} +EXPORT_SYMBOL(vdec_source_changed_for_clk_set); + +static int register_vdec_clk_mgr_per_cpu(int cputype, + enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr) +{ + + struct chip_vdec_clk_s *mgr; + + if (cputype != get_cpu_type() || vdec_type >= VDEC_MAX) { + /* + *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n", + *vdec_type, cputype); + */ + return 0; /* ignore don't needed firmare. */ + } + mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL); + if (!mgr) + return -ENOMEM; + *mgr = *t_mgr; + /* + *pr_info("register vdec clk mgr for vdec[%d]\n", vdec_type); + */ + if (mgr->clock_init) { + if (mgr->clock_init()) { + kfree(mgr); + return -ENOMEM; + } + } + get_current_vdec_chip()->clk_mgr[vdec_type] = mgr; + return 0; +} + +int register_vdec_clk_mgr(int cputype[], enum vdec_type_e vdec_type, + struct chip_vdec_clk_s *t_mgr) +{ + int i = 0; + + while (cputype[i] > 0) { + register_vdec_clk_mgr_per_cpu(cputype[i], vdec_type, t_mgr); + i++; + } + return 0; +} +EXPORT_SYMBOL(register_vdec_clk_mgr); + +int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type) +{ + kfree(get_current_vdec_chip()->clk_mgr[vdec_type]); + + return 0; +} +EXPORT_SYMBOL(unregister_vdec_clk_mgr); + +static int register_vdec_clk_setting_per_cpu(int cputype, + struct clk_set_setting *setting, int size) +{ + + struct clk_set_setting *p_setting; + + if (cputype != get_cpu_type()) { + /* + *pr_info("ignore clk_set_setting for cpu=%d\n", + *cputype); + */ + return 0; /* ignore don't needed this setting . */ + } + p_setting = kmalloc(size, GFP_KERNEL); + if (!p_setting) + return -ENOMEM; + memcpy(p_setting, setting, size); + + pr_info("register clk_set_setting cpu[%d]\n", cputype); + + get_current_vdec_chip()->clk_setting_array = p_setting; + return 0; +} + +int register_vdec_clk_setting(int cputype[], + struct clk_set_setting *p_seting, int size) +{ + int i = 0; + + while (cputype[i] > 0) { + register_vdec_clk_setting_per_cpu(cputype[i], p_seting, size); + i++; + } + return 0; +} +EXPORT_SYMBOL(register_vdec_clk_setting); + +int unregister_vdec_clk_setting(void) +{ + kfree(get_current_vdec_chip()->clk_setting_array); + + return 0; +} +EXPORT_SYMBOL(unregister_vdec_clk_setting); + diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h new file mode 100644 index 000000000000..1c979b450148 --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h @@ -0,0 +1,155 @@ +/* + * drivers/amlogic/media/common/arch/clk/clk.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VDEC_CHIP_CLK_HEADER +#define VDEC_CHIP_CLK_HEADER +#include +#include +#include +#include "clk_priv.h" +#include + +#ifndef INCLUDE_FROM_ARCH_CLK_MGR +int vdec_clock_init(void); +int vdec_clock_set(int clk); +int vdec2_clock_set(int clk); + +int hcodec_clock_set(int clk); +int hevc_clock_init(void); +int hevc_clock_set(int clk); + +void vdec_clock_on(void); +void vdec_clock_off(void); +void vdec2_clock_on(void); + +void vdec2_clock_off(void); +void hcodec_clock_on(void); +void hcodec_clock_off(void); +void hevc_clock_on(void); +void hevc_clock_off(void); + +int vdec_source_get(enum vdec_type_e core); +int vdec_clk_get(enum vdec_type_e core); + +int vdec_source_changed_for_clk_set(int format, int width, int height, int fps); +int get_clk_with_source(int format, int w_x_h_fps); + +void vdec_clock_enable(void); +void vdec_clock_hi_enable(void); +void hcodec_clock_enable(void); +void hcodec_clock_hi_enable(void); +void hevc_clock_enable(void); +void hevc_clock_hi_enable(void); +void vdec2_clock_enable(void); +void vdec2_clock_hi_enable(void); +void set_clock_gate(struct gate_switch_node *nodes, int num); + +#endif +int register_vdec_clk_mgr(int cputype[], + enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr); + +int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type); + +int register_vdec_clk_setting(int cputype[], + struct clk_set_setting *p_seting, int size); + +int unregister_vdec_clk_setting(void); + +#ifdef INCLUDE_FROM_ARCH_CLK_MGR +static struct chip_vdec_clk_s vdec_clk_mgr __initdata = { + .clock_init = vdec_clock_init, + .clock_set = vdec_clock_set, + .clock_on = vdec_clock_on, + .clock_off = vdec_clock_off, + .clock_get = vdec_clock_get, +}; + +#ifdef VDEC_HAS_VDEC2 +static struct chip_vdec_clk_s vdec2_clk_mgr __initdata = { + .clock_set = vdec2_clock_set, + .clock_on = vdec2_clock_on, + .clock_off = vdec2_clock_off, + .clock_get = vdec_clock_get, +}; +#endif + +#ifdef VDEC_HAS_HEVC +static struct chip_vdec_clk_s vdec_hevc_clk_mgr __initdata = { + .clock_init = hevc_clock_init, + .clock_set = hevc_clock_set, + .clock_on = hevc_clock_on, + .clock_off = hevc_clock_off, + .clock_get = vdec_clock_get, +}; +#endif + +#ifdef VDEC_HAS_VDEC_HCODEC +static struct chip_vdec_clk_s vdec_hcodec_clk_mgr __initdata = { + .clock_set = hcodec_clock_set, + .clock_on = hcodec_clock_on, + .clock_off = hcodec_clock_off, + .clock_get = vdec_clock_get, +}; +#endif + +static int __init vdec_init_clk(void) +{ + int cpus[] = CLK_FOR_CPU; + register_vdec_clk_mgr(cpus, VDEC_1, &vdec_clk_mgr); +#ifdef VDEC_HAS_VDEC2 + register_vdec_clk_mgr(cpus, VDEC_2, &vdec2_clk_mgr); +#endif +#ifdef VDEC_HAS_HEVC + register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr); +#endif +#ifdef VDEC_HAS_VDEC_HCODEC + register_vdec_clk_mgr(cpus, VDEC_HCODEC, &vdec_hcodec_clk_mgr); +#endif + +#ifdef VDEC_HAS_CLK_SETTINGS + register_vdec_clk_setting(cpus, + clks_for_formats, sizeof(clks_for_formats)); +#endif + return 0; +} + +static void __exit vdec_clk_exit(void) +{ + unregister_vdec_clk_mgr(VDEC_1); +#ifdef VDEC_HAS_VDEC2 + unregister_vdec_clk_mgr(VDEC_2); +#endif +#ifdef VDEC_HAS_HEVC + unregister_vdec_clk_mgr(VDEC_HEVC); +#endif +#ifdef VDEC_HAS_VDEC_HCODEC + unregister_vdec_clk_mgr(VDEC_HCODEC); +#endif +#ifdef VDEC_HAS_CLK_SETTINGS + unregister_vdec_clk_setting(); +#endif + pr_info("media clock exit.\n"); +} + +#define ARCH_VDEC_CLK_INIT()\ + module_init(vdec_init_clk) + +#define ARCH_VDEC_CLK_EXIT()\ + module_exit(vdec_clk_exit) + +#endif +#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h b/drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h new file mode 100644 index 000000000000..1898e6d47e9b --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk_priv.h @@ -0,0 +1,38 @@ +/* + * drivers/amlogic/media/common/arch/clk/clk_priv.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef AMPORTS_CLK_PRIV_HEADER +#define AMPORTS_CLK_PRIV_HEADER + +struct clk_set { + u32 wh_X_fps; /* [x*y*fps */ + u32 clk_Mhz; /*min MHZ */ +}; +#define MAX_CLK_SET 6 +struct clk_set_setting { + struct clk_set set[MAX_CLK_SET]; +}; + +struct chip_vdec_clk_s { + int (*clock_get)(enum vdec_type_e core); + int (*clock_init)(void); + int (*clock_set)(int clk); + void (*clock_on)(void); + void (*clock_off)(void); + void (*clock_prepare_switch)(void); +}; +#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clkgx.c b/drivers/amlogic/media_modules/common/media_clock/clk/clkgx.c new file mode 100644 index 000000000000..852073859c93 --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clkgx.c @@ -0,0 +1,620 @@ +/* + * drivers/amlogic/media/common/arch/clk/clkgx.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../frame_provider/decoder/utils/vdec.h" +#include +#include "clk_priv.h" +#include + +#include +#include "../switch/amports_gate.h" +#define MHz (1000000) + +struct clk_mux_s { + struct gate_switch_node *vdec_mux_node; + struct gate_switch_node *hcodec_mux_node; + struct gate_switch_node *hevc_mux_node; +}; + +struct clk_mux_s gclk; + +void vdec1_set_clk(int source, int div) +{ + pr_info("vdec1_set_clk %d, %d\n", source, div); + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16); +} +EXPORT_SYMBOL(vdec1_set_clk); + +void hcodec_set_clk(int source, int div) +{ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, + (source << 9) | (div - 1), 16, 16); +} +EXPORT_SYMBOL(hcodec_set_clk); + +void vdec2_set_clk(int source, int div) +{ + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, + (source << 9) | (div - 1), 0, 16); +} +EXPORT_SYMBOL(vdec2_set_clk); + +void hevc_set_clk(int source, int div) +{ + pr_info("hevc_set_clk %d, %d\n", source, div); + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, + (source << 9) | (div - 1), 16, 16); +} +EXPORT_SYMBOL(hevc_set_clk); + +void vdec_get_clk_source(int clk, int *source, int *div, int *rclk) +{ +#define source_div4 (0) +#define source_div3 (1) +#define source_div5 (2) +#define source_div7 (3) + if (clk > 500) { + *source = source_div3; + *div = 1; + *rclk = 667; + } else if (clk >= 500) { + *source = source_div4; + *div = 1; + *rclk = 500; + } else if (clk >= 400) { + *source = source_div5; + *div = 1; + *rclk = 400; + } else if (clk >= 333) { + *source = source_div3; + *div = 2; + *rclk = 333; + } else if (clk >= 200) { + *source = source_div5; + *div = 2; + *rclk = 200; + } else if (clk >= 166) { + *source = source_div4; + *div = 3; + *rclk = 166; + } else if (clk >= 133) { + *source = source_div5; + *div = 3; + *rclk = 133; + } else if (clk >= 100) { + *source = source_div5; + *div = 4; + *rclk = 100; + } else if (clk >= 50) { + *source = source_div5; + *div = 8; + *rclk = 50; + } else { + *source = source_div5; + *div = 20; + *rclk = 10; + } +} +EXPORT_SYMBOL(vdec_get_clk_source); + +/* set gp0 648M vdec use gp0 clk*/ +#define VDEC1_648M() \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (0), 0, 16) + +#define HEVC_648M() \ + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16) + +/*set gp0 1296M vdec use gp0 clk div2*/ +#define VDEC1_648M_DIV() \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (1), 0, 16) + +#define HEVC_648M_DIV() \ + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16) + +#define VDEC1_WITH_GP_PLL() \ + ((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00) +#define HEVC_WITH_GP_PLL() \ + ((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000) + +#define VDEC1_CLOCK_ON() \ + do { if (is_meson_m8_cpu()) { \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ + WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ + } else { \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ + WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \ + WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \ + WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ + } \ + } while (0) + +#define VDEC2_CLOCK_ON() do {\ + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \ + WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\ + } while (0) + +#define HCODEC_CLOCK_ON() do {\ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \ + WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\ + } while (0) +#define HEVC_CLOCK_ON() do {\ + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \ + WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \ + WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \ + WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\ + } while (0) +#define VDEC1_SAFE_CLOCK() do {\ + WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \ + READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \ + WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \ + WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\ + } while (0) + +#define VDEC1_CLOCK_OFF() \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 8, 1) +#define VDEC2_CLOCK_OFF() \ + WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1) +#define HCODEC_CLOCK_OFF() \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1) +#define HEVC_SAFE_CLOCK() do { \ + WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ + (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\ + WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ + (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\ + WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \ + WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\ + } while (0) + +#define HEVC_CLOCK_OFF() WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1) + +static int clock_real_clk[VDEC_MAX + 1]; + +/* +*enum vformat_e { +* VFORMAT_MPEG12 = 0, +* VFORMAT_MPEG4, +* VFORMAT_H264, +* VFORMAT_MJPEG, +* VFORMAT_REAL, +* VFORMAT_JPEG, +* VFORMAT_VC1, +* VFORMAT_AVS, +* VFORMAT_YUV, +* VFORMAT_H264MVC, +* VFORMAT_H264_4K2K, +* VFORMAT_HEVC, +* VFORMAT_H264_ENC, +* VFORMAT_JPEG_ENC, +* VFORMAT_VP9, +* VFORMAT_MAX +*}; +*sample: +*{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333}, +* {4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},} +*mean: +*width * height * fps +*<720p30fps clk=100MHZ +*>=720p30fps & < 1080p30fps clk=166MHZ +*>=1080p 30fps & < 1080p60fps clk=333MHZ +*/ +static struct clk_set_setting clks_for_formats[] = { + { /*[VFORMAT_MPEG12] */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, + {1920 * 1080 * 60, 333}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_MPEG4] */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, + {1920 * 1080 * 60, 333}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_H264] */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166}, + {1920 * 1080 * 30, 333}, + {1920 * 1080 * 60, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_MJPEG] */ + {{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200}, + {1920 * 1080 * 60, 333}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_REAL] */ + {{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500}, + {1920 * 1080 * 60, 500}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_JPEG] */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, + {1920 * 1080 * 60, 333}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_VC1] */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, + {1920 * 1080 * 60, 333}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_AVS] */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, + {1920 * 1080 * 60, 333}, + {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, + 600}, {INT_MAX, 600}, + } + }, + { /*[VFORMAT_YUV] */ + {{1280 * 720 * 30, 100}, {INT_MAX, 100}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + } + }, + { /*VFORMAT_H264MVC */ + {{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333}, + {4096 * 2048 * 60, 600}, + {INT_MAX, 630}, {0, 0}, {0, 0}, + } + }, + { /*VFORMAT_H264_4K2K */ + {{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630}, + {INT_MAX, 630}, + {0, 0}, {0, 0}, {0, 0}, + } + }, + { /*VFORMAT_HEVC */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600}, + {4096 * 2048 * 25, 630}, + {4096 * 2048 * 30, 630}, {4096 * 2048 * 60, + 630}, {INT_MAX, 630}, + } + }, + { /*VFORMAT_H264_ENC */ + {{1280 * 720 * 30, 0}, {INT_MAX, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + } + }, + { /*VFORMAT_JPEG_ENC */ + {{1280 * 720 * 30, 0}, {INT_MAX, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, + } + }, + { /*VFORMAT_VP9 */ + {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100}, + {1920 * 1080 * 60, 166}, + {4096 * 2048 * 30, 333}, {4096 * 2048 * 60, + 630}, {INT_MAX, 630}, + } + }, + +}; + +void set_clock_gate(struct gate_switch_node *nodes, int num) +{ + struct gate_switch_node *node = NULL; + + do { + node = &nodes[num - 1]; + if (IS_ERR_OR_NULL(node)) + pr_info("get mux clk err.\n"); + + if (!strcmp(node->name, "clk_vdec_mux")) + gclk.vdec_mux_node = node; + else if (!strcmp(node->name, "clk_hcodec_mux")) + gclk.hcodec_mux_node = node; + else if (!strcmp(node->name, "clk_hevc_mux")) + gclk.hevc_mux_node = node; + } while(--num); +} +EXPORT_SYMBOL(set_clock_gate); + +static int vdec_set_clk(int dec, int rate) +{ + struct clk *clk = NULL; + + switch (dec) { + case VDEC_1: + clk = gclk.vdec_mux_node->clk; + WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); + break; + + case VDEC_HCODEC: + clk = gclk.hcodec_mux_node->clk; + WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); + break; + + case VDEC_2: + clk = gclk.vdec_mux_node->clk; + WRITE_VREG(DOS_GCLK_EN1, 0x3ff); + break; + + case VDEC_HEVC: + clk = gclk.hevc_mux_node->clk; + WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); + break; + + case VDEC_MAX: + break; + + default: + pr_info("invaild vdec type.\n"); + } + + if (IS_ERR_OR_NULL(clk)) { + pr_info("the mux clk err.\n"); + return -1; + } + + clk_set_rate(clk, rate); + + return 0; +} + +static int vdec_clock_init(void) +{ + return 0; +} + +static int vdec_clock_set(int clk) +{ + if (clk == 1) + clk = 200; + else if (clk == 2) { + if (clock_real_clk[VDEC_1] != 648) + clk = 500; + else + clk = 648; + } else if (clk == 0) { + if (clock_real_clk[VDEC_1] == 667 || + (clock_real_clk[VDEC_1] == 648) || + clock_real_clk[VDEC_1] <= 0) + clk = 200; + else + clk = clock_real_clk[VDEC_1]; + } + + if ((clk > 500 && clk != 667)) { + if (clock_real_clk[VDEC_1] == 648) + return 648; + clk = 667; + } + + vdec_set_clk(VDEC_1, clk * MHz); + + clock_real_clk[VDEC_1] = clk; + + pr_info("vdec mux clock is %lu Hz\n", + clk_get_rate(gclk.vdec_mux_node->clk)); + + return clk; +} + +static int hevc_clock_init(void) +{ + return 0; +} + +static int hevc_clock_set(int clk) +{ + if (clk == 1) + clk = 200; + else if (clk == 2) { + if (clock_real_clk[VDEC_HEVC] != 648) + clk = 500; + else + clk = 648; + } else if (clk == 0) { + if (clock_real_clk[VDEC_HEVC] == 667 || + (clock_real_clk[VDEC_HEVC] == 648) || + clock_real_clk[VDEC_HEVC] <= 0) + clk = 200; + else + clk = clock_real_clk[VDEC_HEVC]; + } + + if ((clk > 500 && clk != 667)) { + if (clock_real_clk[VDEC_HEVC] == 648) + return 648; + clk = 667; + } + + vdec_set_clk(VDEC_HEVC, clk * MHz); + + clock_real_clk[VDEC_HEVC] = clk; + + pr_info("hevc mux clock is %lu Hz\n", + clk_get_rate(gclk.hevc_mux_node->clk)); + + return clk; +} + +static int hcodec_clock_set(int clk) +{ + if (clk == 1) + clk = 200; + else if (clk == 2) { + if (clock_real_clk[VDEC_HCODEC] != 648) + clk = 500; + else + clk = 648; + } else if (clk == 0) { + if (clock_real_clk[VDEC_HCODEC] == 667 || + (clock_real_clk[VDEC_HCODEC] == 648) || + clock_real_clk[VDEC_HCODEC] <= 0) + clk = 200; + else + clk = clock_real_clk[VDEC_HCODEC]; + } + + if ((clk > 500 && clk != 667)) { + if (clock_real_clk[VDEC_HCODEC] == 648) + return 648; + clk = 667; + } + + vdec_set_clk(VDEC_HCODEC, clk * MHz); + + clock_real_clk[VDEC_HCODEC] = clk; + + pr_info("hcodec mux clock is %lu Hz\n", + clk_get_rate(gclk.hcodec_mux_node->clk)); + + return clk; +} + +static void vdec_clock_on(void) +{ + spin_lock_irqsave(&gclk.vdec_mux_node->lock, + gclk.vdec_mux_node->flags); + if (!gclk.vdec_mux_node->ref_count) + clk_prepare_enable(gclk.vdec_mux_node->clk); + + gclk.vdec_mux_node->ref_count++; + spin_unlock_irqrestore(&gclk.vdec_mux_node->lock, + gclk.vdec_mux_node->flags); + + pr_info("the %-15s clock off, ref cnt: %d\n", + gclk.vdec_mux_node->name, + gclk.vdec_mux_node->ref_count); +} + +static void vdec_clock_off(void) +{ + spin_lock_irqsave(&gclk.vdec_mux_node->lock, + gclk.vdec_mux_node->flags); + gclk.vdec_mux_node->ref_count--; + if (!gclk.vdec_mux_node->ref_count) + clk_disable_unprepare(gclk.vdec_mux_node->clk); + + clock_real_clk[VDEC_1] = 0; + spin_unlock_irqrestore(&gclk.vdec_mux_node->lock, + gclk.vdec_mux_node->flags); + + pr_info("the %-15s clock off, ref cnt: %d\n", + gclk.vdec_mux_node->name, + gclk.vdec_mux_node->ref_count); +} + +static void hcodec_clock_on(void) +{ + spin_lock_irqsave(&gclk.hcodec_mux_node->lock, + gclk.hcodec_mux_node->flags); + if (!gclk.hcodec_mux_node->ref_count) + clk_prepare_enable(gclk.hcodec_mux_node->clk); + + gclk.hcodec_mux_node->ref_count++; + spin_unlock_irqrestore(&gclk.hcodec_mux_node->lock, + gclk.hcodec_mux_node->flags); + + pr_info("the %-15s clock off, ref cnt: %d\n", + gclk.hcodec_mux_node->name, + gclk.hcodec_mux_node->ref_count); +} + +static void hcodec_clock_off(void) +{ + spin_lock_irqsave(&gclk.hcodec_mux_node->lock, + gclk.hcodec_mux_node->flags); + gclk.hcodec_mux_node->ref_count--; + if (!gclk.hcodec_mux_node->ref_count) + clk_disable_unprepare(gclk.hcodec_mux_node->clk); + + spin_unlock_irqrestore(&gclk.hcodec_mux_node->lock, + gclk.hcodec_mux_node->flags); + + pr_info("the %-15s clock off, ref cnt: %d\n", + gclk.hcodec_mux_node->name, + gclk.hcodec_mux_node->ref_count); +} + +static void hevc_clock_on(void) +{ + spin_lock_irqsave(&gclk.hevc_mux_node->lock, + gclk.hevc_mux_node->flags); + if (!gclk.hevc_mux_node->ref_count) + clk_prepare_enable(gclk.hevc_mux_node->clk); + + gclk.hevc_mux_node->ref_count++; + WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); + spin_unlock_irqrestore(&gclk.hevc_mux_node->lock, + gclk.hevc_mux_node->flags); + + pr_info("the %-15s clock off, ref cnt: %d\n", + gclk.hevc_mux_node->name, + gclk.hevc_mux_node->ref_count); +} + +static void hevc_clock_off(void) +{ + spin_lock_irqsave(&gclk.hevc_mux_node->lock, + gclk.hevc_mux_node->flags); + gclk.hevc_mux_node->ref_count--; + if (!gclk.hevc_mux_node->ref_count) + clk_disable_unprepare(gclk.hevc_mux_node->clk); + + clock_real_clk[VDEC_HEVC] = 0; + spin_unlock_irqrestore(&gclk.hevc_mux_node->lock, + gclk.hevc_mux_node->flags); + + pr_info("the %-15s clock off, ref cnt: %d\n", + gclk.hevc_mux_node->name, + gclk.hevc_mux_node->ref_count); +} + +static int vdec_clock_get(enum vdec_type_e core) +{ + if (core >= VDEC_MAX) + return 0; + + return clock_real_clk[core]; +} + +#define INCLUDE_FROM_ARCH_CLK_MGR + +/*#define VDEC_HAS_VDEC2*/ +#define VDEC_HAS_HEVC +#define VDEC_HAS_VDEC_HCODEC +#define VDEC_HAS_CLK_SETTINGS +#define CLK_FOR_CPU {\ + MESON_CPU_MAJOR_ID_GXBB,\ + MESON_CPU_MAJOR_ID_GXTVBB,\ + MESON_CPU_MAJOR_ID_GXL,\ + MESON_CPU_MAJOR_ID_GXM,\ + MESON_CPU_MAJOR_ID_TXL,\ + 0} +#include "clk.h" +ARCH_VDEC_CLK_INIT(); +ARCH_VDEC_CLK_EXIT(); + +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c new file mode 100644 index 000000000000..ade914ad44f0 --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c @@ -0,0 +1,189 @@ +/* + * drivers/amlogic/media/common/arch/switch/amports_gate.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ +#include +#include +#include +#include +#include +#include +#include "amports_gate.h" +#include +#include "../../../stream_input/amports/amports_priv.h" +#include "../../../frame_provider/decoder/utils/vdec.h" +#include "../clk/clk.h" + + +#define DEBUG_REF 1 +#define GATE_RESET_OK + +#ifdef GATE_RESET_OK + +struct gate_switch_node gates[] = { + { + .name = "demux", + }, + { + .name = "parser_top", + }, + { + .name = "vdec", + }, + { + .name = "clk_vdec_mux", + }, + { + .name = "clk_hcodec_mux", + }, + { + .name = "clk_hevc_mux", + }, +}; + +/* +mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX>; + clock-names = "parser_top", + "demux", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux"; +}; +*/ + +int amports_clock_gate_init(struct device *dev) +{ + int i; + + for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) { + gates[i].clk = devm_clk_get(dev, gates[i].name); + if (IS_ERR_OR_NULL(gates[i].clk)) { + gates[i].clk = NULL; + pr_info("get gate %s control failed %p\n", + gates[i].name, + gates[i].clk); + } else { + pr_info("get gate %s control ok %p\n", + gates[i].name, + gates[i].clk); + } + gates[i].ref_count = 0; + spin_lock_init(&gates[i].lock); + } + + set_clock_gate(gates, ARRAY_SIZE(gates)); + + return 0; +} +EXPORT_SYMBOL(amports_clock_gate_init); + +static int amports_gate_clk(struct gate_switch_node *gate_node, int enable) +{ + spin_lock_irqsave(&gate_node->lock, gate_node->flags); + if (enable) { + if (gate_node->ref_count == 0) + clk_prepare_enable(gate_node->clk); + + gate_node->ref_count++; + + if (DEBUG_REF) + pr_info("the %-15s clock on, ref cnt: %d\n", + gate_node->name, gate_node->ref_count); + } else { + gate_node->ref_count--; + if (gate_node->ref_count == 0) + clk_disable_unprepare(gate_node->clk); + + if (DEBUG_REF) + pr_info("the %-15s clock off, ref cnt: %d\n", + gate_node->name, gate_node->ref_count); + } + spin_unlock_irqrestore(&gate_node->lock, gate_node->flags); + return 0; +} + +int amports_switch_gate(const char *name, int enable) +{ + int i; + + for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) { + if (!strcmp(name, gates[i].name)) { + + /*pr_info("openclose:%d gate %s control\n", enable, + gates[i].name);*/ + + if (gates[i].clk) + amports_gate_clk(&gates[i], enable); + } + } + return 0; +} +EXPORT_SYMBOL(amports_switch_gate); + +#else +/* +*can used for debug. +*on chip bringup. +*/ +int amports_clock_gate_init(struct device *dev) +{ + static int gate_inited; + + if (gate_inited) + return 0; +/* +*#define HHI_GCLK_MPEG0 0x1050 +*#define HHI_GCLK_MPEG1 0x1051 +*#define HHI_GCLK_MPEG2 0x1052 +*#define HHI_GCLK_OTHER 0x1054 +*#define HHI_GCLK_AO 0x1055 +*/ + WRITE_HHI_REG_BITS(HHI_GCLK_MPEG0, 1, 1, 1);/*dos*/ + WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 25, 1);/*U_parser_top()*/ + WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 0xff, 6, 8);/*aiu()*/ + WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 4, 1);/*demux()*/ + WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 2, 1);/*audio in()*/ + WRITE_HHI_REG_BITS(HHI_GCLK_MPEG2, 1, 25, 1);/*VPU Interrupt*/ + gate_inited++; + + + + return 0; +} +EXPORT_SYMBOL(amports_clock_gate_init); + +static int amports_switch_gate(struct gate_switch_node *gate_node, int enable) +{ + return 0; +} + +int amports_switch_gate(const char *name, int enable) +{ + amports_switch_gate(0, 0); + return 0; +} +EXPORT_SYMBOL(amports_switch_gate); + +#endif diff --git a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h new file mode 100644 index 000000000000..75270ab0ee9e --- /dev/null +++ b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.h @@ -0,0 +1,33 @@ +/* + * drivers/amlogic/media/common/arch/switch/amports_gate.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef AMPORT_GATE_H +#define AMPORT_GATE_H +#include + +struct gate_switch_node { + struct clk *clk; + const char *name; + spinlock_t lock; + unsigned long flags; + int ref_count; +}; + +extern int amports_clock_gate_init(struct device *dev); +extern int amports_switch_gate(const char *name, int enable); + +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/Makefile b/drivers/amlogic/media_modules/frame_provider/Makefile new file mode 100644 index 000000000000..371e088259c5 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/Makefile @@ -0,0 +1 @@ +obj-y += decoder/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/Makefile new file mode 100644 index 000000000000..3a5774a8e786 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/Makefile @@ -0,0 +1,16 @@ +obj-y += utils/ +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12) += mpeg12/vmpeg12.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4) += mpeg4/vmpeg4.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI) += mpeg4/vmpeg4_multi.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_VC1) += vc1/vvc1.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264) += h264/vh264.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI) += h264_multi/ +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC) += h264/vh264_mvc.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_4K2K) += h264/vh264_4k2k.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC) += h264/vh264_mvc.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H265) += h265/vh265.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_VP9) += vp9/vvp9.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG) += mjpeg/vmjpeg.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI) += mjpeg/vmjpeg_multi.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_REAL) += real/vreal.o +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS) += avs/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile new file mode 100644 index 000000000000..cf154c9d432d --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/Makefile @@ -0,0 +1,2 @@ +obj-m += vavs.o +vavs-objs += avs.o avsp_trans.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c new file mode 100644 index 000000000000..aed84976e9b6 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c @@ -0,0 +1,1541 @@ +/* + * drivers/amlogic/amports/vavs.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/parser/streambuf_reg.h" +#include "../utils/amvdec.h" +#include +#include "../../../stream_input/amports/amports_priv.h" +#include +#include +#include +#include "avs.h" + +#define DRIVER_NAME "amvdec_avs" +#define MODULE_NAME "amvdec_avs" + +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +#endif + +#define USE_AVS_SEQ_INFO +#define HANDLE_AVS_IRQ +#define DEBUG_PTS + +#define I_PICTURE 0 +#define P_PICTURE 1 +#define B_PICTURE 2 + +/* #define ORI_BUFFER_START_ADDR 0x81000000 */ +#define ORI_BUFFER_START_ADDR 0x80000000 + +#define INTERLACE_FLAG 0x80 +#define TOP_FIELD_FIRST_FLAG 0x40 + +/* protocol registers */ +#define AVS_PIC_RATIO AV_SCRATCH_0 +#define AVS_PIC_WIDTH AV_SCRATCH_1 +#define AVS_PIC_HEIGHT AV_SCRATCH_2 +#define AVS_FRAME_RATE AV_SCRATCH_3 + +#define AVS_ERROR_COUNT AV_SCRATCH_6 +#define AVS_SOS_COUNT AV_SCRATCH_7 +#define AVS_BUFFERIN AV_SCRATCH_8 +#define AVS_BUFFEROUT AV_SCRATCH_9 +#define AVS_REPEAT_COUNT AV_SCRATCH_A +#define AVS_TIME_STAMP AV_SCRATCH_B +#define AVS_OFFSET_REG AV_SCRATCH_C +#define MEM_OFFSET_REG AV_SCRATCH_F +#define AVS_ERROR_RECOVERY_MODE AV_SCRATCH_G + +#define VF_POOL_SIZE 32 +#define PUT_INTERVAL (HZ/100) + +#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ +#define INT_AMVENCODER INT_DOS_MAILBOX_1 +#else +/* #define AMVENC_DEV_VERSION "AML-MT" */ +#define INT_AMVENCODER INT_MAILBOX_1A +#endif + +#define VPP_VD1_POSTBLEND (1 << 10) + +static int debug_flag; + +static int firmware_sel; /* 0, normal; 1, old ucode */ + +int avs_get_debug_flag(void) +{ + return debug_flag; +} + +static struct vframe_s *vavs_vf_peek(void *); +static struct vframe_s *vavs_vf_get(void *); +static void vavs_vf_put(struct vframe_s *, void *); +static int vavs_vf_states(struct vframe_states *states, void *); + +static const char vavs_dec_id[] = "vavs-dev"; + +#define PROVIDER_NAME "decoder.avs" +static DEFINE_SPINLOCK(lock); +static DEFINE_MUTEX(vavs_mutex); + +static const struct vframe_operations_s vavs_vf_provider = { + .peek = vavs_vf_peek, + .get = vavs_vf_get, + .put = vavs_vf_put, + .vf_states = vavs_vf_states, +}; + +static struct vframe_provider_s vavs_vf_prov; + +#define VF_BUF_NUM_MAX 16 + +/*static u32 vf_buf_num = 4*/ +static u32 vf_buf_num = 4; +static u32 vf_buf_num_used; +static u32 canvas_base = 128; +#ifdef NV21 + int canvas_num = 2; /*NV21*/ +#else + int canvas_num = 3; +#endif +static u32 work_buf_size; + +static struct vframe_s vfpool[VF_POOL_SIZE]; +/*static struct vframe_s vfpool2[VF_POOL_SIZE];*/ +static struct vframe_s *cur_vfpool; +static unsigned char recover_flag; +static s32 vfbuf_use[VF_BUF_NUM_MAX]; +static u32 saved_resolution; +static u32 frame_width, frame_height, frame_dur, frame_prog; +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start; +static u32 buf_size, buf_offset; +static u32 avi_flag; +static u32 vavs_ratio; +static u32 pic_type; +static u32 pts_by_offset = 1; +static u32 total_frame; +static u32 next_pts; +static unsigned char throw_pb_flag; +#ifdef DEBUG_PTS +static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; +#endif + +static u32 radr, rval; +static struct dec_sysinfo vavs_amstream_dec_info; + +#ifdef AVSP_LONG_CABAC +static struct work_struct long_cabac_wd_work; +void *es_write_addr_virt; +dma_addr_t es_write_addr_phy; + +void *bitstream_read_tmp; +dma_addr_t bitstream_read_tmp_phy; +void *avsp_heap_adr; + +#endif + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static inline u32 index2canvas(u32 index) +{ + const u32 canvas_tab[VF_BUF_NUM_MAX] = { + 0x010100, 0x030302, 0x050504, 0x070706, + 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e, + 0x111110, 0x131312, 0x151514, 0x171716, + 0x191918, 0x1b1b1a, 0x1d1d1c, 0x1f1f1e, + }; + const u32 canvas_tab_3[4] = { + 0x010100, 0x040403, 0x070706, 0x0a0a09 + }; + + if (canvas_num == 2) + return canvas_tab[index] + (canvas_base << 16) + + (canvas_base << 8) + canvas_base; + + return canvas_tab_3[index] + (canvas_base << 16) + + (canvas_base << 8) + canvas_base; +} + +static const u32 frame_rate_tab[16] = { + 96000 / 30, /* forbidden */ + 96000 / 24, /* 24000/1001 (23.967) */ + 96000 / 24, + 96000 / 25, + 96000 / 30, /* 30000/1001 (29.97) */ + 96000 / 30, + 96000 / 50, + 96000 / 60, /* 60000/1001 (59.94) */ + 96000 / 60, + /* > 8 reserved, use 24 */ + 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, + 96000 / 24, 96000 / 24, 96000 / 24 +}; + +static void set_frame_info(struct vframe_s *vf, unsigned *duration) +{ + int ar = 0; + + unsigned pixel_ratio = READ_VREG(AVS_PIC_RATIO); +#ifndef USE_AVS_SEQ_INFO + if (vavs_amstream_dec_info.width > 0 + && vavs_amstream_dec_info.height > 0) { + vf->width = vavs_amstream_dec_info.width; + vf->height = vavs_amstream_dec_info.height; + } else +#endif + { + vf->width = READ_VREG(AVS_PIC_WIDTH); + vf->height = READ_VREG(AVS_PIC_HEIGHT); + frame_width = vf->width; + frame_height = vf->height; + /* pr_info("%s: (%d,%d)\n", __func__,vf->width, vf->height);*/ + } + +#ifndef USE_AVS_SEQ_INFO + if (vavs_amstream_dec_info.rate > 0) + *duration = vavs_amstream_dec_info.rate; + else +#endif + { + *duration = frame_rate_tab[READ_VREG(AVS_FRAME_RATE) & 0xf]; + /* pr_info("%s: duration = %d\n", __func__, *duration); */ + frame_dur = *duration; + } + + if (vavs_ratio == 0) { + /* always stretch to 16:9 */ + vf->ratio_control |= (0x90 << + DISP_RATIO_ASPECT_RATIO_BIT); + } else { + switch (pixel_ratio) { + case 1: + ar = (vf->height * vavs_ratio) / vf->width; + break; + case 2: + ar = (vf->height * 3 * vavs_ratio) / (vf->width * 4); + break; + case 3: + ar = (vf->height * 9 * vavs_ratio) / (vf->width * 16); + break; + case 4: + ar = (vf->height * 100 * vavs_ratio) / (vf->width * + 221); + break; + default: + ar = (vf->height * vavs_ratio) / vf->width; + break; + } + } + + ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); + + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + /*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO; */ + + vf->flag = 0; +} + +#ifdef HANDLE_AVS_IRQ +static irqreturn_t vavs_isr(int irq, void *dev_id) +#else +static void vavs_isr(void) +#endif +{ + u32 reg; + struct vframe_s *vf; + u32 dur; + u32 repeat_count; + u32 picture_type; + u32 buffer_index; + u32 picture_struct; + unsigned int pts, pts_valid = 0, offset; + if (debug_flag & AVS_DEBUG_UCODE) { + if (READ_VREG(AV_SCRATCH_E) != 0) { + pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_E), + READ_VREG(AV_SCRATCH_D)); + WRITE_VREG(AV_SCRATCH_E, 0); + } + } +#ifdef AVSP_LONG_CABAC + if (firmware_sel == 0 && READ_VREG(LONG_CABAC_REQ)) { +#ifdef PERFORMANCE_DEBUG + pr_info("%s:schedule long_cabac_wd_work\r\n", __func__); +#endif + schedule_work(&long_cabac_wd_work); + } +#endif + reg = READ_VREG(AVS_BUFFEROUT); + + if (reg) { + picture_struct = READ_VREG(AV_SCRATCH_5); + if (debug_flag & AVS_DEBUG_PRINT) + pr_info("AVS_BUFFEROUT=%x, picture_struct is 0x%x\n", + reg, picture_struct); + if (pts_by_offset) { + offset = READ_VREG(AVS_OFFSET_REG); + if (debug_flag & AVS_DEBUG_PRINT) + pr_info("AVS OFFSET=%x\n", offset); + if (pts_lookup_offset(PTS_TYPE_VIDEO, offset, &pts, 0) + == 0) { + pts_valid = 1; +#ifdef DEBUG_PTS + pts_hit++; +#endif + } else { +#ifdef DEBUG_PTS + pts_missed++; +#endif + } + } + + repeat_count = READ_VREG(AVS_REPEAT_COUNT); + if (firmware_sel == 0) + buffer_index = + ((reg & 0x7) + + (((reg >> 8) & 0x3) << 3) - 1) & 0x1f; + else + buffer_index = + ((reg & 0x7) - 1) & 3; + + picture_type = (reg >> 3) & 7; +#ifdef DEBUG_PTS + if (picture_type == I_PICTURE) { + /* pr_info("I offset 0x%x, pts_valid %d\n", + offset, pts_valid); */ + if (!pts_valid) + pts_i_missed++; + else + pts_i_hit++; + } +#endif + + if (throw_pb_flag && picture_type != I_PICTURE) { + + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("picture type %d throwed\n", + picture_type); + } + WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index)); + } else if (reg & INTERLACE_FLAG) { /* interlace */ + throw_pb_flag = 0; + + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("interlace, picture type %d\n", + picture_type); + } + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + set_frame_info(vf, &dur); + vf->bufWidth = 1920; + pic_type = 2; + if ((I_PICTURE == picture_type) && pts_valid) { + vf->pts = pts; + if ((repeat_count > 1) && avi_flag) { + /* next_pts = pts + + (vavs_amstream_dec_info.rate * + repeat_count >> 1)*15/16; */ + next_pts = + pts + + (dur * repeat_count >> 1) * + 15 / 16; + } else + next_pts = 0; + } else { + vf->pts = next_pts; + if ((repeat_count > 1) && avi_flag) { + /* vf->duration = + vavs_amstream_dec_info.rate * + repeat_count >> 1; */ + vf->duration = dur * repeat_count >> 1; + if (next_pts != 0) { + next_pts += + ((vf->duration) - + ((vf->duration) >> 4)); + } + } else { + /* vf->duration = + vavs_amstream_dec_info.rate >> 1; */ + vf->duration = dur >> 1; + next_pts = 0; + } + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->duration_pulldown = 0; + vf->type = + (reg & TOP_FIELD_FIRST_FLAG) + ? VIDTYPE_INTERLACE_TOP + : VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->type_original = vf->type; + + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("buffer_index %d, canvas addr %x\n", + buffer_index, vf->canvas0Addr); + } + + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + set_frame_info(vf, &dur); + vf->bufWidth = 1920; + + vf->pts = next_pts; + if ((repeat_count > 1) && avi_flag) { + /* vf->duration = vavs_amstream_dec_info.rate * + repeat_count >> 1; */ + vf->duration = dur * repeat_count >> 1; + if (next_pts != 0) { + next_pts += + ((vf->duration) - + ((vf->duration) >> 4)); + } + } else { + /* vf->duration = vavs_amstream_dec_info.rate + >> 1; */ + vf->duration = dur >> 1; + next_pts = 0; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->duration_pulldown = 0; + vf->type = + (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->type_original = vf->type; + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + total_frame++; + } else { /* progressive */ + throw_pb_flag = 0; + + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("progressive picture type %d\n", + picture_type); + } + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + set_frame_info(vf, &dur); + vf->bufWidth = 1920; + pic_type = 1; + + if ((I_PICTURE == picture_type) && pts_valid) { + vf->pts = pts; + if ((repeat_count > 1) && avi_flag) { + /* next_pts = pts + + (vavs_amstream_dec_info.rate * + repeat_count)*15/16; */ + next_pts = + pts + + (dur * repeat_count) * 15 / 16; + } else + next_pts = 0; + } else { + vf->pts = next_pts; + if ((repeat_count > 1) && avi_flag) { + /* vf->duration = + vavs_amstream_dec_info.rate * + repeat_count; */ + vf->duration = dur * repeat_count; + if (next_pts != 0) { + next_pts += + ((vf->duration) - + ((vf->duration) >> 4)); + } + } else { + /* vf->duration = + vavs_amstream_dec_info.rate; */ + vf->duration = dur; + next_pts = 0; + } + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->duration_pulldown = 0; + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->type_original = vf->type; + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("buffer_index %d, canvas addr %x\n", + buffer_index, vf->canvas0Addr); + } + + vfbuf_use[buffer_index]++; + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + total_frame++; + } + + /* pr_info("PicType = %d, PTS = 0x%x\n", + picture_type, vf->pts); */ + WRITE_VREG(AVS_BUFFEROUT, 0); + } + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + +#ifdef HANDLE_AVS_IRQ + return IRQ_HANDLED; +#else + return; +#endif +} +/* +static int run_flag = 1; +static int step_flag; +*/ +static int error_recovery_mode; /*0: blocky 1: mosaic*/ +/* +static uint error_watchdog_threshold=10; +static uint error_watchdog_count; +static uint error_watchdog_buf_threshold = 0x4000000; +*/ +static uint long_cabac_busy; + +static struct vframe_s *vavs_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (recover_flag) + return NULL; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; + +} + +static struct vframe_s *vavs_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (recover_flag) + return NULL; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; + +} + +static void vavs_vf_put(struct vframe_s *vf, void *op_arg) +{ + int i; + if (recover_flag) + return; + + for (i = 0; i < VF_POOL_SIZE; i++) { + if (vf == &cur_vfpool[i]) + break; + } + if (i < VF_POOL_SIZE) + kfifo_put(&recycle_q, (const struct vframe_s *)vf); + +} + +int vavs_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = frame_width; /* vavs_amstream_dec_info.width; */ + vstatus->height = frame_height; /* vavs_amstream_dec_info.height; */ + if (0 != frame_dur /*vavs_amstream_dec_info.rate */) + vstatus->fps = 96000 / frame_dur; + else + vstatus->fps = 96000; + vstatus->error_count = READ_VREG(AVS_ERROR_COUNT); + vstatus->status = stat; + + return 0; +} + +/****************************************/ +static void vavs_canvas_init(void) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + u32 disp_addr = 0xffffffff; + int vf_buf_num_avail = 0; + vf_buf_num_used = vf_buf_num; + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + vf_buf_num_avail = + ((buf_size - work_buf_size) / decbuf_size) - 1; + pr_info + ("avs(SD):buf_start %p, size %x, offset %x avail %d\n", + (void *)buf_start, buf_size, buf_offset, + vf_buf_num_avail); + } else { + /* HD & SD */ + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + vf_buf_num_avail = + ((buf_size - work_buf_size) / decbuf_size) - 1; + pr_info("avs: buf_start %p, buf_size %x, buf_offset %x buf avail %d\n", + (void *)buf_start, buf_size, buf_offset, + vf_buf_num_avail); + } + if (vf_buf_num_used > vf_buf_num_avail) + vf_buf_num_used = vf_buf_num_avail; + + if (firmware_sel == 0) + buf_offset = buf_offset + ((vf_buf_num_used + 1) * decbuf_size); + + if (READ_MPEG_REG(VPP_MISC) & VPP_VD1_POSTBLEND) { + struct canvas_s cur_canvas; + + canvas_read((READ_MPEG_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + } + + for (i = 0; i < vf_buf_num_used; i++) { + if (((buf_start + i * decbuf_size + 7) >> 3) == disp_addr) { +#ifdef NV21 + canvas_config(canvas_base + canvas_num * i + 0, + buf_start + + vf_buf_num_used * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(canvas_base + canvas_num * i + 1, + buf_start + + vf_buf_num_used * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(canvas_num * i + 0, + buf_start + 4 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(canvas_num * i + 1, + buf_start + 4 * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(canvas_num * i + 2, + buf_start + 4 * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#endif + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("canvas config %d, addr %p\n", + vf_buf_num_used, + (void *)(buf_start + + vf_buf_num_used * decbuf_size)); + } + + } else { +#ifdef NV21 + canvas_config(canvas_base + canvas_num * i + 0, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(canvas_base + canvas_num * i + 1, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(canvas_num * i + 0, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(canvas_num * i + 1, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(canvas_num * i + 2, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#endif + if (debug_flag & AVS_DEBUG_PRINT) { + pr_info("canvas config %d, addr %p\n", i, + (void *)(buf_start + + i * decbuf_size)); + } + } + } +} + +void vavs_recover(void) +{ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); + + if (firmware_sel == 1) { + WRITE_VREG(POWER_CTL_VLD, 0x10); + WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, + MEM_FIFO_CNT_BIT, 2); + WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, + MEM_LEVEL_CNT_BIT, 6); + } + if (firmware_sel == 0) + WRITE_VREG(AV_SCRATCH_5, 0); + + if (firmware_sel == 0) { + /* fixed canvas index */ + WRITE_VREG(AV_SCRATCH_0, canvas_base); + WRITE_VREG(AV_SCRATCH_1, vf_buf_num_used); + } else { + int ii; + for (ii = 0; ii < 4; ii++) { + WRITE_VREG(AV_SCRATCH_0 + ii, + (canvas_base + canvas_num * ii) | + ((canvas_base + canvas_num * ii + 1) + << 8) | + ((canvas_base + canvas_num * ii + 1) + << 16) + ); + } + } + + /* notify ucode the buffer offset */ + WRITE_VREG(AV_SCRATCH_F, buf_offset); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(AVS_SOS_COUNT, 0); + WRITE_VREG(AVS_BUFFERIN, 0); + WRITE_VREG(AVS_BUFFEROUT, 0); + if (error_recovery_mode) + WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); + else + WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); +#if 1 /* def DEBUG_UCODE */ + WRITE_VREG(AV_SCRATCH_D, 0); +#endif + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif + +#ifdef PIC_DC_NEED_CLEAR + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); +#endif + +#ifdef AVSP_LONG_CABAC + if (firmware_sel == 0) { + WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy); + WRITE_VREG(LONG_CABAC_REQ, 0); + WRITE_VREG(LONG_CABAC_PIC_SIZE, 0); + WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); + } +#endif + +} + +static void vavs_prot_init(void) +{ +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); + +#else + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + READ_MPEG_REG(RESET0_REGISTER); + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); +#endif + + /***************** reset vld **********************************/ + WRITE_VREG(POWER_CTL_VLD, 0x10); + WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2); + WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, MEM_LEVEL_CNT_BIT, 6); + /*************************************************************/ + + vavs_canvas_init(); + if (firmware_sel == 0) + WRITE_VREG(AV_SCRATCH_5, 0); +#ifdef NV21 + if (firmware_sel == 0) { + /* fixed canvas index */ + WRITE_VREG(AV_SCRATCH_0, canvas_base); + WRITE_VREG(AV_SCRATCH_1, vf_buf_num_used); + } else { + int ii; + for (ii = 0; ii < 4; ii++) { + WRITE_VREG(AV_SCRATCH_0 + ii, + (canvas_base + canvas_num * ii) | + ((canvas_base + canvas_num * ii + 1) + << 8) | + ((canvas_base + canvas_num * ii + 1) + << 16) + ); + } + /* + WRITE_VREG(AV_SCRATCH_0, 0x010100); + WRITE_VREG(AV_SCRATCH_1, 0x040403); + WRITE_VREG(AV_SCRATCH_2, 0x070706); + WRITE_VREG(AV_SCRATCH_3, 0x0a0a09); + */ + } +#else + /* index v << 16 | u << 8 | y */ + WRITE_VREG(AV_SCRATCH_0, 0x020100); + WRITE_VREG(AV_SCRATCH_1, 0x050403); + WRITE_VREG(AV_SCRATCH_2, 0x080706); + WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); +#endif + /* notify ucode the buffer offset */ + WRITE_VREG(AV_SCRATCH_F, buf_offset); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(AVS_SOS_COUNT, 0); + WRITE_VREG(AVS_BUFFERIN, 0); + WRITE_VREG(AVS_BUFFEROUT, 0); + if (error_recovery_mode) + WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); + else + WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); +#if 1 /* def DEBUG_UCODE */ + WRITE_VREG(AV_SCRATCH_D, 0); +#endif + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif + +#ifdef PIC_DC_NEED_CLEAR + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); +#endif + +#ifdef AVSP_LONG_CABAC + if (firmware_sel == 0) { + WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy); + WRITE_VREG(LONG_CABAC_REQ, 0); + WRITE_VREG(LONG_CABAC_PIC_SIZE, 0); + WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); + } +#endif +} + +#if 0 +#ifdef AVSP_LONG_CABAC +static unsigned char es_write_addr[MAX_CODED_FRAME_SIZE] __aligned(64); +#endif +#endif + +static void vavs_local_init(void) +{ + int i; + + vavs_ratio = vavs_amstream_dec_info.ratio; + + avi_flag = (unsigned long) vavs_amstream_dec_info.param; + + frame_width = frame_height = frame_dur = frame_prog = 0; + + throw_pb_flag = 1; + + total_frame = 0; + saved_resolution = 0; + next_pts = 0; + +#ifdef DEBUG_PTS + pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0; +#endif + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &vfpool[i]; + vfpool[i].index = vf_buf_num; + vfpool[i].bufWidth = 1920; + kfifo_put(&newframe_q, vf); + } + for (i = 0; i < vf_buf_num; i++) + vfbuf_use[i] = 0; + + cur_vfpool = vfpool; + +} + +static int vavs_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + spin_lock_irqsave(&lock, flags); + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + spin_unlock_irqrestore(&lock, flags); + return 0; +} + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER +static void vavs_ppmgr_reset(void) +{ + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + + vavs_local_init(); + + pr_info("vavs: vf_ppmgr_reset\n"); +} +#endif + +static void vavs_local_reset(void) +{ + mutex_lock(&vavs_mutex); + recover_flag = 1; + pr_info("error, local reset\n"); + amvdec_stop(); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + vavs_local_init(); + vavs_recover(); + amvdec_start(); + recover_flag = 0; +#if 0 + error_watchdog_count = 0; + + pr_info("pc %x stream buf wp %x rp %x level %x\n", + READ_VREG(MPC_E), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); +#endif + mutex_unlock(&vavs_mutex); +} + +static void vavs_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + +#ifndef HANDLE_AVS_IRQ + vavs_isr(); +#endif + + if (READ_VREG(AVS_SOS_COUNT)) { + if (!error_recovery_mode) { + if (debug_flag & AVS_DEBUG_OLD_ERROR_HANDLE) { + mutex_lock(&vavs_mutex); + pr_info("vavs fatal error reset !\n"); + amvdec_stop(); +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vavs_ppmgr_reset(); +#else + vf_light_unreg_provider(&vavs_vf_prov); + vavs_local_init(); + vf_reg_provider(&vavs_vf_prov); +#endif + vavs_recover(); + amvdec_start(); + mutex_unlock(&vavs_mutex); + } else { + vavs_local_reset(); + } + } + } +#if 0 + if (long_cabac_busy == 0 && + error_watchdog_threshold > 0 && + kfifo_len(&display_q) == 0 && + READ_VREG(VLD_MEM_VIFIFO_LEVEL) > + error_watchdog_buf_threshold) { + pr_info("newq %d dispq %d recyq %d\r\n", + kfifo_len(&newframe_q), + kfifo_len(&display_q), + kfifo_len(&recycle_q)); + pr_info("pc %x stream buf wp %x rp %x level %x\n", + READ_VREG(MPC_E), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + error_watchdog_count++; + if (error_watchdog_count >= error_watchdog_threshold) + vavs_local_reset(); + } else + error_watchdog_count = 0; +#endif + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + + if (!kfifo_is_empty(&recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index < vf_buf_num) && + (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index)); + vf->index = vf_buf_num; + } + kfifo_put(&newframe_q, + (const struct vframe_s *)vf); + } + + } + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + if (firmware_sel == 0 && + (debug_flag & AVS_DEBUG_USE_FULL_SPEED)) { + vdec_source_changed(VFORMAT_AVS, + 4096, 2048, 60); + } else { + vdec_source_changed(VFORMAT_AVS, + frame_width, frame_height, fps); + } + + } + + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +#ifdef AVSP_LONG_CABAC + +static void long_cabac_do_work(struct work_struct *work) +{ + int status = 0; +#ifdef PERFORMANCE_DEBUG + pr_info("enter %s buf level (new %d, display %d, recycle %d)\r\n", + __func__, + kfifo_len(&newframe_q), + kfifo_len(&display_q), + kfifo_len(&recycle_q) + ); +#endif + mutex_lock(&vavs_mutex); + long_cabac_busy = 1; + while (READ_VREG(LONG_CABAC_REQ)) { + if (process_long_cabac() < 0) { + status = -1; + break; + } + } + long_cabac_busy = 0; + mutex_unlock(&vavs_mutex); +#ifdef PERFORMANCE_DEBUG + pr_info("exit %s buf level (new %d, display %d, recycle %d)\r\n", + __func__, + kfifo_len(&newframe_q), + kfifo_len(&display_q), + kfifo_len(&recycle_q) + ); +#endif + if (status < 0) { + pr_info("transcoding error, local reset\r\n"); + vavs_local_reset(); + } + +} +#endif + +#if 0 +#ifdef AVSP_LONG_CABAC +static void init_avsp_long_cabac_buf(void) +{ +#if 0 + es_write_addr_phy = (unsigned long)codec_mm_alloc_for_dma( + "vavs", + PAGE_ALIGN(MAX_CODED_FRAME_SIZE)/PAGE_SIZE, + 0, CODEC_MM_FLAGS_DMA_CPU); + es_write_addr_virt = codec_mm_phys_to_virt(es_write_addr_phy); + +#elif 0 + es_write_addr_virt = + (void *)dma_alloc_coherent(amports_get_dma_device(), + MAX_CODED_FRAME_SIZE, &es_write_addr_phy, + GFP_KERNEL); +#else + /*es_write_addr_virt = kmalloc(MAX_CODED_FRAME_SIZE, GFP_KERNEL); + es_write_addr_virt = (void *)__get_free_pages(GFP_KERNEL, + get_order(MAX_CODED_FRAME_SIZE)); + */ + es_write_addr_virt = &es_write_addr[0]; + if (es_write_addr_virt == NULL) { + pr_err("%s: failed to alloc es_write_addr_virt buffer\n", + __func__); + return; + } + + es_write_addr_phy = dma_map_single(amports_get_dma_device(), + es_write_addr_virt, + MAX_CODED_FRAME_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + es_write_addr_phy)) { + pr_err("%s: failed to map es_write_addr_virt buffer\n", + __func__); + /*kfree(es_write_addr_virt);*/ + es_write_addr_virt = NULL; + return; + } +#endif + + +#ifdef BITSTREAM_READ_TMP_NO_CACHE + bitstream_read_tmp = + (void *)dma_alloc_coherent(amports_get_dma_device(), + SVA_STREAM_BUF_SIZE, &bitstream_read_tmp_phy, + GFP_KERNEL); + +#else + + bitstream_read_tmp = kmalloc(SVA_STREAM_BUF_SIZE, GFP_KERNEL); + /*bitstream_read_tmp = (void *)__get_free_pages(GFP_KERNEL, + get_order(MAX_CODED_FRAME_SIZE)); + */ + if (bitstream_read_tmp == NULL) { + pr_err("%s: failed to alloc bitstream_read_tmp buffer\n", + __func__); + return; + } + + bitstream_read_tmp_phy = dma_map_single(amports_get_dma_device(), + bitstream_read_tmp, + SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + bitstream_read_tmp_phy)) { + pr_err("%s: failed to map rpm buffer\n", __func__); + kfree(bitstream_read_tmp); + bitstream_read_tmp = NULL; + return; + } +#endif +} +#endif +#endif + +static s32 vavs_init(void) +{ + int size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + pr_info("vavs_init\n"); + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + amvdec_enable(); + + vavs_local_init(); + + size = get_firmware_data(VIDEO_DEC_AVS, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf) < 0) { + amvdec_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vavs_prot_init(); + +#ifdef HANDLE_AVS_IRQ + if (vdec_request_irq(VDEC_IRQ_1, vavs_isr, + "vavs-irq", (void *)vavs_dec_id)) { + amvdec_disable(); + pr_info("vavs irq register error.\n"); + return -ENOENT; + } +#endif + + stat |= STAT_ISR_REG; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, NULL); + vf_reg_provider(&vavs_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, NULL); + vf_reg_provider(&vavs_vf_prov); +#endif + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long) + vavs_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong)(&recycle_timer); + recycle_timer.function = vavs_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + +#ifdef AVSP_LONG_CABAC + if (firmware_sel == 0) + INIT_WORK(&long_cabac_wd_work, long_cabac_do_work); +#endif + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int amvdec_avs_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + if (pdata == NULL) { + pr_info("amvdec_avs memory resource undefined.\n"); + return -EFAULT; + } + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) + firmware_sel = 1; + + if (firmware_sel == 1) { + vf_buf_num = 4; + canvas_base = 0; + canvas_num = 3; + } else { + /*if(vf_buf_num <= 4) + canvas_base = 0; + else */ + canvas_base = 128; + canvas_num = 2; /*NV21*/ + } + +#ifdef AVSP_LONG_CABAC + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1 + - (MAX_CODED_FRAME_SIZE * 2) + - LOCAL_HEAP_SIZE; + avsp_heap_adr = codec_mm_phys_to_virt( + pdata->mem_start + buf_size); +#else + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; +#endif + + if (buf_start > ORI_BUFFER_START_ADDR) + buf_offset = buf_start - ORI_BUFFER_START_ADDR; + else + buf_offset = buf_start; + + if (pdata->sys_info) + vavs_amstream_dec_info = *pdata->sys_info; + + pr_info("%s (%d,%d) %d\n", __func__, vavs_amstream_dec_info.width, + vavs_amstream_dec_info.height, vavs_amstream_dec_info.rate); + + pdata->dec_status = vavs_dec_status; + + if (vavs_init() < 0) { + pr_info("amvdec_avs init failed.\n"); + + return -ENODEV; + } + + return 0; +} + +static int amvdec_avs_remove(struct platform_device *pdev) +{ + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id); + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } +#ifdef AVSP_LONG_CABAC + if (firmware_sel == 0) { + mutex_lock(&vavs_mutex); + cancel_work_sync(&long_cabac_wd_work); + mutex_unlock(&vavs_mutex); + + if (es_write_addr_virt) { +#if 0 + codec_mm_free_for_dma("vavs", es_write_addr_phy); +#else + dma_unmap_single(amports_get_dma_device(), + es_write_addr_phy, + MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE); + /*kfree(es_write_addr_virt);*/ + es_write_addr_virt = NULL; +#endif + } + +#ifdef BITSTREAM_READ_TMP_NO_CACHE + if (bitstream_read_tmp) { + dma_free_coherent(amports_get_dma_device(), + SVA_STREAM_BUF_SIZE, bitstream_read_tmp, + bitstream_read_tmp_phy); + bitstream_read_tmp = NULL; + } +#else + if (bitstream_read_tmp) { + dma_unmap_single(amports_get_dma_device(), + bitstream_read_tmp_phy, + SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); + kfree(bitstream_read_tmp); + bitstream_read_tmp = NULL; + } +#endif + } +#endif + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vavs_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + amvdec_disable(); + + pic_type = 0; +#ifdef DEBUG_PTS + pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit, + pts_missed, pts_i_hit, pts_i_missed); + pr_info("total frame %d, avi_flag %d, rate %d\n", total_frame, avi_flag, + vavs_amstream_dec_info.rate); +#endif + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_avs_driver = { + .probe = amvdec_avs_probe, + .remove = amvdec_avs_remove, + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_avs_profile = { + .name = "avs", + .profile = "" +}; + +static int __init amvdec_avs_driver_init_module(void) +{ + pr_debug("amvdec_avs module init\n"); + + if (platform_driver_register(&amvdec_avs_driver)) { + pr_info("failed to register amvdec_avs driver\n"); + return -ENODEV; + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) + amvdec_avs_profile.profile = "avs+"; + + vcodec_profile_register(&amvdec_avs_profile); + + return 0; +} + +static void __exit amvdec_avs_driver_remove_module(void) +{ + pr_debug("amvdec_avs module remove.\n"); + + platform_driver_unregister(&amvdec_avs_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_avs stat\n"); + +/****************************************** +module_param(run_flag, uint, 0664); +MODULE_PARM_DESC(run_flag, "\n run_flag\n"); + +module_param(step_flag, uint, 0664); +MODULE_PARM_DESC(step_flag, "\n step_flag\n"); +*******************************************/ + +module_param(debug_flag, uint, 0664); +MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); + +module_param(error_recovery_mode, uint, 0664); +MODULE_PARM_DESC(error_recovery_mode, "\n error_recovery_mode\n"); + +/****************************************** +module_param(error_watchdog_threshold, uint, 0664); +MODULE_PARM_DESC(error_watchdog_threshold, "\n error_watchdog_threshold\n"); + +module_param(error_watchdog_buf_threshold, uint, 0664); +MODULE_PARM_DESC(error_watchdog_buf_threshold, + "\n error_watchdog_buf_threshold\n"); +*******************************************/ + +module_param(pic_type, uint, 0444); +MODULE_PARM_DESC(pic_type, "\n amdec_vas picture type\n"); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(vf_buf_num, uint, 0664); +MODULE_PARM_DESC(vf_buf_num, "\nvf_buf_num\n"); + +module_param(vf_buf_num_used, uint, 0664); +MODULE_PARM_DESC(vf_buf_num_used, "\nvf_buf_num_used\n"); + +module_param(canvas_base, uint, 0664); +MODULE_PARM_DESC(canvas_base, "\ncanvas_base\n"); + +module_param(work_buf_size, uint, 0664); +MODULE_PARM_DESC(work_buf_size, "\nwork_buf_size\n"); + +module_param(firmware_sel, uint, 0664); +MODULE_PARM_DESC(firmware_sel, "\firmware_sel\n"); + + +module_init(amvdec_avs_driver_init_module); +module_exit(amvdec_avs_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC AVS Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Qi Wang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h new file mode 100644 index 000000000000..d4156459bfbf --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h @@ -0,0 +1,70 @@ +#ifndef AVS_H_ +#define AVS_H_ + +#define AVSP_LONG_CABAC +/*#define BITSTREAM_READ_TMP_NO_CACHE*/ + +#ifdef AVSP_LONG_CABAC +#define MAX_CODED_FRAME_SIZE 1500000 /*!< bytes for one frame*/ +#define LOCAL_HEAP_SIZE (1024*1024*10) +/* +#define MAX_CODED_FRAME_SIZE 240000 +#define MAX_CODED_FRAME_SIZE 700000 +*/ +#define SVA_STREAM_BUF_SIZE 1024 + +extern void *es_write_addr_virt; +extern dma_addr_t es_write_addr_phy; + +extern void *bitstream_read_tmp; +extern dma_addr_t bitstream_read_tmp_phy; +extern void *avsp_heap_adr; + +int avs_get_debug_flag(void); + +int process_long_cabac(void); + +/* bit [6] - skip_mode_flag + bit [5:4] - picture_type + bit [3] - picture_structure (0-Field, 1-Frame) + bit [2] - fixed_picture_qp + bit [1] - progressive_sequence + bit [0] - active +*/ +#define LONG_CABAC_REQ AV_SCRATCH_K +#define LONG_CABAC_SRC_ADDR AV_SCRATCH_H +#define LONG_CABAC_DES_ADDR AV_SCRATCH_I +/* bit[31:16] - vertical_size + bit[15:0] - horizontal_size +*/ +#define LONG_CABAC_PIC_SIZE AV_SCRATCH_J + +#endif + +/* +#define PERFORMANCE_DEBUG +#define DUMP_DEBUG +*/ +#define AVS_DEBUG_PRINT 0x01 +#define AVS_DEBUG_UCODE 0x02 +#define AVS_DEBUG_OLD_ERROR_HANDLE 0x10 +#define AVS_DEBUG_USE_FULL_SPEED 0x80 +#define AEC_DUMP 0x100 +#define STREAM_INFO_DUMP 0x200 +#define SLICE_INFO_DUMP 0x400 +#define MB_INFO_DUMP 0x800 +#define MB_NUM_DUMP 0x1000 +#define BLOCK_NUM_DUMP 0x2000 +#define COEFF_DUMP 0x4000 +#define ES_DUMP 0x8000 +#define DQUANT_DUMP 0x10000 +#define STREAM_INFO_DUMP_MORE 0x20000 +#define STREAM_INFO_DUMP_MORE2 0x40000 + +extern void *es_write_addr_virt; +extern void *bitstream_read_tmp; +extern dma_addr_t bitstream_read_tmp_phy; +int read_bitstream(unsigned char *Buf, int size); +int u_v(int LenInBits, char *tracestring); + +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c new file mode 100644 index 000000000000..3c7f3ab9721b --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c @@ -0,0 +1,4944 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include "../../../stream_input/parser/streambuf_reg.h" +#include "../utils/amvdec.h" +#include +#include "../../../stream_input/amports/amports_priv.h" + +#include "avs.h" +#ifdef AVSP_LONG_CABAC + +#define DECODING_SANITY_CHECK + +#define TRACE 0 +#define LIWR_FIX 0 +#define pow2(a, b) (1< 0) { + if (num >= 8) + push_num = 8; + else + push_num = num; + + num = num - push_num; + push_value = (value >> num); + + es_res = (es_res << push_num) | push_value; + es_res_ptr = es_res_ptr + push_num; + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & ES_DUMP) + io_printf(" #### es_res : 0x%X, es_res_ptr : %d\n", + es_res, es_res_ptr); +#endif + + while (es_res_ptr >= 8) { + es_res_ptr = es_res_ptr & 7; + wr_es_data = (es_res >> es_res_ptr) & 0xff; + if ((previous_es == 0) & (wr_es_data < 4)) { + io_printf( + " Insert 2'b10 for emu at position : %d\n", + es_ptr); + + es_res_ptr = es_res_ptr + 2; + wr_es_data = 2; + } +#ifdef AVSP_LONG_CABAC +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & ES_DUMP) + pr_info("es_buf[%d] = 0x%02x\r\n", + es_buf_ptr, wr_es_data); +#endif + es_buf[es_buf_ptr++] = wr_es_data; +#else + putc(wr_es_data, f_es); +#endif + es_ptr++; + previous_es = ((previous_es << 8) | wr_es_data) + & 0xffff; + } + + } +} + +#define MIN_QP 0 +#define MAX_QP 63 + +#ifdef BLOCK_SIZE +#undef BLOCK_SIZE +#endif + +#define BLOCK_SIZE 4 +#define B8_SIZE 8 +#define MB_BLOCK_SIZE 16 + +#define BLOCK_MULTIPLE (MB_BLOCK_SIZE/(BLOCK_SIZE*2)) + +#define DECODE_COPY_MB 0 +#define DECODE_MB 1 + +#define NO_INTRA_PMODE 5 +#define INTRA_PMODE_4x4 10 +#define NO_INTRA_PMODE_4x4 19 +/* 8x8 intra prediction modes */ +#define VERT_PRED 0 +#define HOR_PRED 1 +#define DC_PRED 2 +#define DOWN_LEFT_PRED 3 +#define DOWN_RIGHT_PRED 4 + +#define VERT_PRED_4x4 0 +#define HOR_PRED_4x4 1 +#define DC_PRED_4x4 2 +#define DOWN_LEFT_PRED_4x4 3 +#define DOWN_RIGHT_PRED_4x4 4 + +#define HOR_DOWN_PRED_4x4 5 +#define VERT_LEFT_PRED_4x4 6 +#define HOR_UP_PRED_4x4 7 +#define VERT_RIGHT_PRED_4x4 8 + +#define DC_PRED_8 0 +#define HOR_PRED_8 1 +#define VERT_PRED_8 2 +#define PLANE_8 3 + +#define LUMA_16DC 0 +#define LUMA_16AC 1 +#define LUMA_8x8 2 +#define LUMA_8x4 3 +#define LUMA_4x8 4 +#define LUMA_4x4 5 +#define CHROMA_DC 6 +#define CHROMA_AC 7 +#define NUM_BLOCK_TYPES 8 + +#define I_PICTURE_START_CODE 0xB3 +#define PB_PICTURE_START_CODE 0xB6 +#define SLICE_START_CODE_MIN 0x00 +#define SLICE_START_CODE_MAX 0xAF +#define USER_DATA_START_CODE 0xB2 +#define SEQUENCE_HEADER_CODE 0xB0 +#define EXTENSION_START_CODE 0xB5 +#define SEQUENCE_END_CODE 0xB1 +#define VIDEO_EDIT_CODE 0xB7 + +#define EOS 1 +#define SOP 2 +#define SOS 3 +#define P8x8 8 +#define I8MB 9 +#define I4MB 10 +#define IBLOCK 11 +#define SI4MB 12 +#define MAXMODE 13 + +#define IS_INTRA(MB) ((MB)->mb_type == I8MB || (MB)->mb_type == I4MB) +#define IS_NEWINTRA(MB) ((MB)->mb_type == I4MB) +#define IS_OLDINTRA(MB) ((MB)->mb_type == I8MB) +#define IS_INTER(MB) ((MB)->mb_type != I8MB && (MB)->mb_type != I4MB) +#define IS_INTERMV(MB) ((MB)->mb_type != I8MB && (MB)->mb_type != I4MB\ + && (MB)->mb_type != 0) + +#define IS_DIRECT(MB) ((MB)->mb_type == 0 && (img->type == B_IMG)) +#define IS_COPY(MB) ((MB)->mb_type == 0 && (img->type == P_IMG)) +#define IS_P8x8(MB) ((MB)->mb_type == P8x8) + +#define P_IMG 0 +#define B_IMG 1 +#define I_IMG 2 + +#define FIELD 0 +#define FRAME 1 + +#define SE_CABP 21 +struct decoding_environment_s { + unsigned int dbuffer; + int dbits_to_go; + unsigned char *dcodestrm; + int *dcodestrm_len; +}; + +struct bi_context_type_s { + unsigned char MPS; + unsigned int LG_PMPS; + unsigned char cycno; +}; + + +/********************************************************************** + * C O N T E X T S F O R R M S Y N T A X E L E M E N T S + ********************************************************************** + */ + +#define NUM_MB_TYPE_CTX 11 +#define NUM_B8_TYPE_CTX 9 +#define NUM_MV_RES_CTX 10 +#define NUM_REF_NO_CTX 6 +#define NUM_DELTA_QP_CTX 4 +#define NUM_MB_AFF_CTX 4 + +struct motion_info_contexts_s { + struct bi_context_type_s mb_type_contexts[4][NUM_MB_TYPE_CTX]; + struct bi_context_type_s b8_type_contexts[2][NUM_B8_TYPE_CTX]; + struct bi_context_type_s mv_res_contexts[2][NUM_MV_RES_CTX]; + struct bi_context_type_s ref_no_contexts[2][NUM_REF_NO_CTX]; + struct bi_context_type_s delta_qp_contexts[NUM_DELTA_QP_CTX]; + struct bi_context_type_s mb_aff_contexts[NUM_MB_AFF_CTX]; +#ifdef TEST_WEIGHTING_AEC +struct bi_context_type_s mb_weighting_pred; +#endif +}; + +#define NUM_IPR_CTX 2 +#define NUM_CIPR_CTX 4 +#define NUM_CBP_CTX 4 +#define NUM_BCBP_CTX 4 +#define NUM_MAP_CTX 16 +#define NUM_LAST_CTX 16 + +#define NUM_ONE_CTX 5 +#define NUM_ABS_CTX 5 + +struct texture_info_contexts { + struct bi_context_type_s ipr_contexts[NUM_IPR_CTX]; + struct bi_context_type_s cipr_contexts[NUM_CIPR_CTX]; + struct bi_context_type_s cbp_contexts[3][NUM_CBP_CTX]; + struct bi_context_type_s bcbp_contexts[NUM_BLOCK_TYPES][NUM_BCBP_CTX]; + struct bi_context_type_s one_contexts[NUM_BLOCK_TYPES][NUM_ONE_CTX]; + struct bi_context_type_s abs_contexts[NUM_BLOCK_TYPES][NUM_ABS_CTX]; + struct bi_context_type_s fld_map_contexts[NUM_BLOCK_TYPES][NUM_MAP_CTX]; + struct bi_context_type_s fld_last_contexts + [NUM_BLOCK_TYPES][NUM_LAST_CTX]; + struct bi_context_type_s map_contexts[NUM_BLOCK_TYPES][NUM_MAP_CTX]; + struct bi_context_type_s last_contexts[NUM_BLOCK_TYPES][NUM_LAST_CTX]; +}; +struct img_par; + +struct syntaxelement { + int type; + int value1; + int value2; + int len; + int inf; + unsigned int bitpattern; + int context; + int k; + int golomb_grad; + int golomb_maxlevels; +#if TRACE +#define TRACESTRING_SIZE 100 + char tracestring[TRACESTRING_SIZE]; +#endif + + void (*mapping)(int len, int info, int *value1, int *value2); + + void (*reading)(struct syntaxelement *, struct img_par *, + struct decoding_environment_s *); + +}; + +struct bitstream_s { + + int read_len; + int code_len; + + int frame_bitoffset; + int bitstream_length; + + unsigned char *stream_buffer; +}; + +struct datapartition { + + struct bitstream_s *bitstream; + struct decoding_environment_s de_aec; + + int (*read_syntax_element)(struct syntaxelement *, struct img_par *, + struct datapartition *); +/*!< virtual function; + actual method depends on chosen data partition and + entropy coding method */ +}; + +struct slice_s { + int picture_id; + int qp; + int picture_type; + int start_mb_nr; + int max_part_nr; + int num_mb; + + struct datapartition *part_arr; + struct motion_info_contexts_s *mot_ctx; + struct texture_info_contexts *tex_ctx; + int field_ctx[3][2]; +}; + +struct img_par { + int number; + int current_mb_nr; + int max_mb_nr; + int current_slice_nr; + int tr; + int qp; + int type; + + int typeb; + + int width; + int height; + int width_cr; + int height_cr; + int source_bitdepth; + int mb_y; + int mb_x; + int block_y; + int pix_y; + int pix_x; + int pix_c_y; + int block_x; + int pix_c_x; + + int ***mv; + int mpr[16][16]; + + int m7[16][16]; + int m8[/*2*/4][8][8]; + int cof[4][/*6*/8][4][4]; + int cofu[4]; + int **ipredmode; + int quad[256]; + int cod_counter; + + int ***dfmv; + int ***dbmv; + int **fw_reffrarr; + int **bw_reffrarr; + + int ***mv_frm; + int **fw_reffrarr_frm; + int **bw_reffrarr_frm; + int imgtr_next_p; + int imgtr_last_p; + int tr_frm; + int tr_fld; + int imgtr_last_prev_p; + + int no_forward_reference; + int seq_header_indicate; + int b_discard_flag; + + int ***fw_mv; + int ***bw_mv; + int subblock_x; + int subblock_y; + + int buf_cycle; + + int direct_type; + + int ***mv_top; + int ***mv_bot; + int **fw_reffrarr_top; + int **bw_reffrarr_top; + int **fw_reffrarr_bot; + int **bw_reffrarr_bot; + + int **ipredmode_top; + int **ipredmode_bot; + int ***fw_mv_top; + int ***fw_mv_bot; + int ***bw_mv_top; + int ***bw_mv_bot; + int ***dfmv_top; + int ***dbmv_top; + int ***dfmv_bot; + int ***dbm_bot; + + int toppoc; + int bottompoc; + int framepoc; + unsigned int frame_num; + + unsigned int pic_distance; + int delta_pic_order_cnt_bottom; + + signed int pic_distance_msb; + unsigned int prev_pic_distance_lsb; + signed int curr_pic_distance_msb; + unsigned int this_poc; + + int pic_width_inmbs; + int pic_height_inmbs; + int pic_size_inmbs; + + int block8_x, block8_y; + int structure; + int pn; + int buf_used; + int buf_size; + int picture_structure; + int advanced_pred_mode_disable; + int types; + int current_mb_nr_fld; + + int p_field_enhanced; + int b_field_enhanced; + + int slice_weighting_flag; + int lum_scale[4]; + int lum_shift[4]; + int chroma_scale[4]; + int chroma_shift[4]; + int mb_weighting_flag; + int weighting_prediction; + int mpr_weight[16][16]; + int top_bot; + int bframe_number; + + int auto_crop_right; + int auto_crop_bottom; + + struct slice_s *current_slice; + int is_v_block; + int is_intra_block; + + int new_seq_header_flag; + int new_sequence_flag; + int last_pic_bbv_delay; + + int sequence_end_flag; + int is_top_field; + + int abt_flag; + int qp_shift; + +#ifdef EIGHTH +int eighth_subpixel_flag; +int subpixel_precision; +int unit_length; +int subpixel_mask; + +int max_mvd; +int min_mvd; +#endif + +}; + +struct macroblock { + int qp; + int slice_nr; + int delta_quant; + struct macroblock *mb_available[3][3]; + /*!< pointer to neighboring MBs in a 3x3 window of current MB, + which is located at [1][1] + NULL pointer identifies neighboring MBs which are unavailable */ + + int mb_type; + int mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][2]; + int cbp, cbp_blk, cbp01; + unsigned long cbp_bits; + + int b8mode[4]; + int b8pdir[4]; + int mb_type_2; + int c_ipred_mode_2; + int dct_mode; + + int c_ipred_mode; + int lf_disable; + int lf_alpha_c0_offset; + int lf_beta_offset; + + int CABT[4]; + int CABP[4]; + int cbp_4x4[4]; + + int skip_flag; + + struct macroblock *mb_available_up; + struct macroblock *mb_available_left; + int mbaddr_a, mbaddr_b, mbaddr_c, mbaddr_d; + int mbavail_a, mbavail_b, mbavail_c, mbavail_d; + +}; + +struct macroblock *mb_data; + +struct img_par *img; + +struct bitstream_s *curr_stream; + +struct datapartition *alloc_partition(int n); + +unsigned int vld_mem_start_addr; +unsigned int vld_mem_end_addr; + +int marker_bit; + +int progressive_sequence; +int horizontal_size; +int vertical_size; + +int second_ifield; +int pre_img_type; + +/* slice_header() */ +int slice_vertical_position; +int slice_vertical_position_extension; +int fixed_picture_qp; +int fixed_slice_qp; +int slice_qp; + +/* + ************************************************************************* + * Function:ue_v, reads an u(v) syntax element, the length in bits is stored in + the global UsedBits variable + * Input: + tracestring + the string for the trace file + bitstream + the stream to be read from + * Output: + * Return: the value of the coded syntax element + * Attention: + ************************************************************************* + */ +/*! + * definition of AVS syntaxelements + * order of elements follow dependencies for picture reconstruction + */ +/*! + * \brief Assignment of old TYPE partition elements to new + * elements + * + * old element | new elements + * TYPE_HEADER | SE_HEADER, SE_PTYPE + * TYPE_MBHEADER | SE_MBTYPE, SE_REFFRAME, SE_INTRAPREDMODE + * TYPE_MVD | SE_MVD + * TYPE_CBP | SE_CBP_INTRA, SE_CBP_INTER * SE_DELTA_QUANT_INTER + * SE_DELTA_QUANT_INTRA + * TYPE_COEFF_Y | SE_LUM_DC_INTRA, SE_LUM_AC_INTRA, + SE_LUM_DC_INTER, SE_LUM_AC_INTER + * TYPE_2x2DC | SE_CHR_DC_INTRA, SE_CHR_DC_INTER + * TYPE_COEFF_C | SE_CHR_AC_INTRA, SE_CHR_AC_INTER + * TYPE_EOS | SE_EOS + */ + +#define SE_HEADER 0 +#define SE_PTYPE 1 +#define SE_MBTYPE 2 +#define SE_REFFRAME 3 +#define SE_INTRAPREDMODE 4 +#define SE_MVD 5 +#define SE_CBP_INTRA 6 +#define SE_LUM_DC_INTRA 7 +#define SE_CHR_DC_INTRA 8 +#define SE_LUM_AC_INTRA 9 +#define SE_CHR_AC_INTRA 10 +#define SE_CBP_INTER 11 +#define SE_LUM_DC_INTER 12 +#define SE_CHR_DC_INTER 13 +#define SE_LUM_AC_INTER 14 +#define SE_CHR_AC_INTER 15 +#define SE_DELTA_QUANT_INTER 16 +#define SE_DELTA_QUANT_INTRA 17 +#define SE_BFRAME 18 +#define SE_EOS 19 +#define SE_MAX_ELEMENTS 20 +#define SE_CBP01 21 +int chroma_format; +/* + ************************************************************************* + * Function:Reads bits from the bitstream buffer + * Input: + byte buffer[] + containing VLC-coded data bits + int totbitoffset + bit offset from start of partition + int bytecount + total bytes in bitstream + int numbits + number of bits to read + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +int get_bits(unsigned char buffer[], int totbitoffset, int *info, int bytecount, + int numbits) +{ + register int inf; + long byteoffset; + int bitoffset; + + int bitcounter = numbits; + + byteoffset = totbitoffset / 8; + bitoffset = 7 - (totbitoffset % 8); + + inf = 0; + while (numbits) { + inf <<= 1; + inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset; + numbits--; + bitoffset--; + if (bitoffset < 0) { + byteoffset++; + bitoffset += 8; + if (byteoffset > bytecount) + return -1; + } + } + + *info = inf; + + + return bitcounter; +} + +/* + ************************************************************************* + * Function:read FLC codeword from UVLC-partition + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +int read_syntaxelement_flc(struct syntaxelement *sym) +{ + int frame_bitoffset = curr_stream->frame_bitoffset; + unsigned char *buf = curr_stream->stream_buffer; + int bitstreamlengthinbytes = curr_stream->bitstream_length; + + if ((get_bits(buf, frame_bitoffset, &(sym->inf), bitstreamlengthinbytes, + sym->len)) < 0) + return -1; + + curr_stream->frame_bitoffset += sym->len; + sym->value1 = sym->inf; + +#if TRACE + tracebits2(sym->tracestring, sym->len, sym->inf); +#endif + + return 1; +} + +/* + ************************************************************************* + * Function:ue_v, reads an u(1) syntax element, the length in bits is stored in + the global UsedBits variable + * Input: + tracestring + the string for the trace file + bitstream + the stream to be read from + * Output: + * Return: the value of the coded syntax element + * Attention: + ************************************************************************* + */ +int u_1(char *tracestring) +{ + return u_v(1, tracestring); +} + +/* + ************************************************************************* + * Function:mapping rule for ue(v) syntax elements + * Input:lenght and info + * Output:number in the code table + * Return: + * Attention: + ************************************************************************* + */ +void linfo_ue(int len, int info, int *value1, int *dummy) +{ + *value1 = (int)pow2(2, (len / 2)) + info - 1; +} + +int u_v(int leninbits, char *tracestring) +{ + struct syntaxelement symbol, *sym = &symbol; + +#ifdef AVSP_LONG_CABAC +#else + assert(curr_stream->stream_buffer != NULL); +#endif + sym->type = SE_HEADER; + sym->mapping = linfo_ue; + sym->len = leninbits; + read_syntaxelement_flc(sym); + + return sym->inf; +} + +/* + ************************************************************************* + * Function:mapping rule for se(v) syntax elements + * Input:lenght and info + * Output:signed mvd + * Return: + * Attention: + ************************************************************************* + */ + +void linfo_se(int len, int info, int *value1, int *dummy) +{ + int n; + n = (int)pow2(2, (len / 2)) + info - 1; + *value1 = (n + 1) / 2; + if ((n & 0x01) == 0) + *value1 = -*value1; + +} + +/* + ************************************************************************* + * Function:lenght and info + * Input: + * Output:cbp (intra) + * Return: + * Attention: + ************************************************************************* + */ + +void linfo_cbp_intra(int len, int info, int *cbp, int *dummy) +{ +} + +const int NCBP[64][2] = {{4, 0}, {16, 19}, {17, 16}, {19, 15}, {14, 18}, + {9, 11}, {22, 31}, {8, 13}, {11, 17}, {21, 30}, {10, 12}, + {7, 9}, {12, 10}, {6, 7}, {5, 8}, {1, 1}, {35, 4}, {47, 42}, { + 48, 38}, {38, 27}, {46, 39}, {36, 33}, {50, 59}, + {26, 26}, {45, 40}, {52, 58}, {41, 35}, {28, 25}, {37, 29}, {23, + 24}, {31, 28}, {2, 3}, {43, 5}, {51, 51}, {56, + 52}, {39, 37}, {55, 50}, {33, 43}, {62, 63}, { + 27, 44}, {54, 53}, {60, 62}, {40, 48}, {32, 47}, + {42, 34}, {24, 45}, {29, 49}, {3, 6}, {49, 14}, {53, 55}, {57, + 56}, {25, 36}, {58, 54}, {30, 41}, {59, 60}, { + 15, 21}, {61, 57}, {63, 61}, {44, 46}, {18, 22}, + {34, 32}, {13, 20}, {20, 23}, {0, 2} }; + +unsigned int s1, t1, value_s, value_t; +unsigned char dec_bypass, dec_final; + +#define get_byte() { \ + dbuffer = dcodestrm[(*dcodestrm_len)++];\ + dbits_to_go = 7; \ +} + +#define dbuffer (dep->dbuffer) +#define dbits_to_go (dep->dbits_to_go) +#define dcodestrm (dep->dcodestrm) +#define dcodestrm_len (dep->dcodestrm_len) + +#define B_BITS 10 + +#define LG_PMPS_SHIFTNO 2 + +#define HALF (1 << (B_BITS-1)) +#define QUARTER (1 << (B_BITS-2)) + +unsigned int biari_decode_symbol(struct decoding_environment_s *dep, + struct bi_context_type_s *bi_ct) +{ + register unsigned char bit; + register unsigned char s_flag; + register unsigned char is_lps = 0; + register unsigned char cwr; + register unsigned char cycno = bi_ct->cycno; + register unsigned int lg_pmps = bi_ct->LG_PMPS; + register unsigned int t_rlps; + register unsigned int s2, t2; + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & AEC_DUMP) + io_printf("LG_PMPS : %03X, MPS : %d, cycno : %d -- %p\n", + bi_ct->LG_PMPS, bi_ct->MPS, bi_ct->cycno, bi_ct); +#endif + + bit = bi_ct->MPS; + + cwr = (cycno <= 1) ? 3 : (cycno == 2) ? 4 : 5; + + if (t1 >= (lg_pmps >> LG_PMPS_SHIFTNO)) { + s2 = s1; + t2 = t1 - (lg_pmps >> LG_PMPS_SHIFTNO); + s_flag = 0; + } else { + s2 = s1 + 1; + t2 = 256 + t1 - (lg_pmps >> LG_PMPS_SHIFTNO); + s_flag = 1; + } + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & AEC_DUMP) + io_printf(" s2 : %d, t2 : %03X\n", s2, t2); +#endif + + if (s2 > value_s || (s2 == value_s && value_t >= t2)) { + is_lps = 1; + bit = !bit; + + t_rlps = (s_flag == 0) ? + (lg_pmps >> LG_PMPS_SHIFTNO) : + (t1 + (lg_pmps >> LG_PMPS_SHIFTNO)); + + if (s2 == value_s) + value_t = (value_t - t2); + else { + if (--dbits_to_go < 0) + get_byte(); + + value_t = (value_t << 1) + | ((dbuffer >> dbits_to_go) & 0x01); + value_t = 256 + value_t - t2; + + } + + while (t_rlps < QUARTER) { + t_rlps = t_rlps << 1; + if (--dbits_to_go < 0) + get_byte(); + + value_t = (value_t << 1) + | ((dbuffer >> dbits_to_go) & 0x01); + } + + s1 = 0; + t1 = t_rlps & 0xff; + + value_s = 0; + while (value_t < QUARTER) { + int j; + if (--dbits_to_go < 0) + get_byte(); + j = (dbuffer >> dbits_to_go) & 0x01; + + value_t = (value_t << 1) | j; + value_s++; + } + value_t = value_t & 0xff; + } else { + + s1 = s2; + t1 = t2; + } + + if (dec_bypass) + return bit; + + if (is_lps) + cycno = (cycno <= 2) ? (cycno + 1) : 3; + else if (cycno == 0) + cycno = 1; + bi_ct->cycno = cycno; + + if (is_lps) { + switch (cwr) { + case 3: + lg_pmps = lg_pmps + 197; + break; + case 4: + lg_pmps = lg_pmps + 95; + break; + default: + lg_pmps = lg_pmps + 46; + } + + if (lg_pmps >= (256 << LG_PMPS_SHIFTNO)) { + lg_pmps = (512 << LG_PMPS_SHIFTNO) - 1 - lg_pmps; + bi_ct->MPS = !(bi_ct->MPS); + } + } else { +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & AEC_DUMP) + io_printf(" - lg_pmps_MPS : %X (%X - %X - %X)\n", + lg_pmps - (unsigned int)(lg_pmps>>cwr) + - (unsigned int)(lg_pmps>>(cwr+2)), + lg_pmps, + (unsigned int)(lg_pmps>>cwr), + (unsigned int)(lg_pmps>>(cwr+2)) + ); +#endif + lg_pmps = lg_pmps - (unsigned int)(lg_pmps >> cwr) + - (unsigned int)(lg_pmps >> (cwr + 2)); + } + + bi_ct->LG_PMPS = lg_pmps; + + return bit; +} + +unsigned int biari_decode_symbolw(struct decoding_environment_s *dep, + struct bi_context_type_s *bi_ct1, + struct bi_context_type_s *bi_ct2) +{ + register unsigned char bit1, bit2; + register unsigned char pred_mps, bit; + register unsigned int lg_pmps; + register unsigned char cwr1, cycno1 = bi_ct1->cycno; + register unsigned char cwr2, cycno2 = bi_ct2->cycno; + register unsigned int lg_pmps1 = bi_ct1->LG_PMPS; + register unsigned int lg_pmps2 = + bi_ct2->LG_PMPS; + register unsigned int t_rlps; + register unsigned char s_flag, is_lps = 0; + register unsigned int s2, t2; + + + bit1 = bi_ct1->MPS; + bit2 = bi_ct2->MPS; + + cwr1 = (cycno1 <= 1) ? 3 : (cycno1 == 2) ? 4 : 5; + cwr2 = (cycno2 <= 1) ? 3 : (cycno2 == 2) ? 4 : 5; + + if (bit1 == bit2) { + pred_mps = bit1; + lg_pmps = (lg_pmps1 + lg_pmps2) / 2; + } else { + if (lg_pmps1 < lg_pmps2) { + pred_mps = bit1; + lg_pmps = (256 << LG_PMPS_SHIFTNO) - 1 + - ((lg_pmps2 - lg_pmps1) >> 1); + } else { + pred_mps = bit2; + lg_pmps = (256 << LG_PMPS_SHIFTNO) - 1 + - ((lg_pmps1 - lg_pmps2) >> 1); + } + } + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & AEC_DUMP) + io_printf(" - Begin - LG_PMPS : %03X, MPS : %d\n", + lg_pmps, pred_mps); +#endif + if (t1 >= (lg_pmps >> LG_PMPS_SHIFTNO)) { + s2 = s1; + t2 = t1 - (lg_pmps >> LG_PMPS_SHIFTNO); + s_flag = 0; + } else { + s2 = s1 + 1; + t2 = 256 + t1 - (lg_pmps >> LG_PMPS_SHIFTNO); + s_flag = 1; + } + + bit = pred_mps; + if (s2 > value_s || (s2 == value_s && value_t >= t2)) { + is_lps = 1; + bit = !bit; + t_rlps = (s_flag == 0) ? + (lg_pmps >> LG_PMPS_SHIFTNO) : + (t1 + (lg_pmps >> LG_PMPS_SHIFTNO)); + + if (s2 == value_s) + value_t = (value_t - t2); + else { + if (--dbits_to_go < 0) + get_byte(); + + value_t = (value_t << 1) + | ((dbuffer >> dbits_to_go) & 0x01); + value_t = 256 + value_t - t2; + } + + while (t_rlps < QUARTER) { + t_rlps = t_rlps << 1; + if (--dbits_to_go < 0) + get_byte(); + + value_t = (value_t << 1) + | ((dbuffer >> dbits_to_go) & 0x01); + } + s1 = 0; + t1 = t_rlps & 0xff; + + value_s = 0; + while (value_t < QUARTER) { + int j; + if (--dbits_to_go < 0) + get_byte(); + j = (dbuffer >> dbits_to_go) & 0x01; + + value_t = (value_t << 1) | j; + value_s++; + } + value_t = value_t & 0xff; + } else { + s1 = s2; + t1 = t2; + } + + if (bit != bit1) { + cycno1 = (cycno1 <= 2) ? (cycno1 + 1) : 3; + } else { + if (cycno1 == 0) + cycno1 = 1; + } + + if (bit != bit2) { + cycno2 = (cycno2 <= 2) ? (cycno2 + 1) : 3; + } else { + if (cycno2 == 0) + cycno2 = 1; + } + bi_ct1->cycno = cycno1; + bi_ct2->cycno = cycno2; + + { + + if (bit == bit1) { + lg_pmps1 = + lg_pmps1 + - (unsigned int)(lg_pmps1 + >> cwr1) + - (unsigned int)(lg_pmps1 + >> (cwr1 + + 2)); + } else { + switch (cwr1) { + case 3: + lg_pmps1 = lg_pmps1 + 197; + break; + case 4: + lg_pmps1 = lg_pmps1 + 95; + break; + default: + lg_pmps1 = lg_pmps1 + 46; + } + + if (lg_pmps1 >= (256 << LG_PMPS_SHIFTNO)) { + lg_pmps1 = (512 << LG_PMPS_SHIFTNO) - 1 + - lg_pmps1; + bi_ct1->MPS = !(bi_ct1->MPS); + } + } + bi_ct1->LG_PMPS = lg_pmps1; + + if (bit == bit2) { + lg_pmps2 = + lg_pmps2 + - (unsigned int)(lg_pmps2 + >> cwr2) + - (unsigned int)(lg_pmps2 + >> (cwr2 + + 2)); + } else { + switch (cwr2) { + case 3: + lg_pmps2 = lg_pmps2 + 197; + break; + case 4: + lg_pmps2 = lg_pmps2 + 95; + break; + default: + lg_pmps2 = lg_pmps2 + 46; + } + + if (lg_pmps2 >= (256 << LG_PMPS_SHIFTNO)) { + lg_pmps2 = (512 << LG_PMPS_SHIFTNO) - 1 + - lg_pmps2; + bi_ct2->MPS = !(bi_ct2->MPS); + } + } + bi_ct2->LG_PMPS = lg_pmps2; + } + + + return bit; +} + +/*! + ************************************************************************ + * \brief + * biari_decode_symbol_eq_prob(): + * \return + * the decoded symbol + ************************************************************************ + */ +unsigned int biari_decode_symbol_eq_prob(struct decoding_environment_s *dep) +{ + unsigned char bit; + struct bi_context_type_s octx; + struct bi_context_type_s *ctx = &octx; + ctx->LG_PMPS = (QUARTER << LG_PMPS_SHIFTNO) - 1; + ctx->MPS = 0; + ctx->cycno = 0xfe; + dec_bypass = 1; + bit = biari_decode_symbol(dep, ctx); + dec_bypass = 0; + return bit; +} + +unsigned int biari_decode_final(struct decoding_environment_s *dep) +{ + unsigned char bit; + struct bi_context_type_s octx; + struct bi_context_type_s *ctx = &octx; + ctx->LG_PMPS = 1 << LG_PMPS_SHIFTNO; + ctx->MPS = 0; + ctx->cycno = 0xff; + dec_final = 1; + bit = biari_decode_symbol(dep, ctx); + dec_final = 0; + return bit; +} + +int i_8(char *tracestring) +{ + int frame_bitoffset = curr_stream->frame_bitoffset; + unsigned char *buf = curr_stream->stream_buffer; + int bitstreamlengthinbytes = curr_stream->bitstream_length; + struct syntaxelement symbol, *sym = &symbol; +#ifdef AVSP_LONG_CABAC +#else + assert(curr_stream->stream_buffer != NULL); +#endif + + sym->len = 8; + sym->type = SE_HEADER; + sym->mapping = linfo_ue; + + if ((get_bits(buf, frame_bitoffset, &(sym->inf), bitstreamlengthinbytes, + sym->len)) < 0) + return -1; + curr_stream->frame_bitoffset += sym->len; + sym->value1 = sym->inf; + if (sym->inf & 0x80) + sym->inf = -(~((int)0xffffff00 | sym->inf) + 1); +#if TRACE + tracebits2(sym->tracestring, sym->len, sym->inf); +#endif + return sym->inf; +} + +/*! + ************************************************************************ + * \brief + * arideco_bits_read + ************************************************************************ + */ +int arideco_bits_read(struct decoding_environment_s *dep) +{ + + return 8 * ((*dcodestrm_len) - 1) + (8 - dbits_to_go); +} + +/*! + ************************************************************************ + * \brief + * arithmetic decoding + ************************************************************************ + */ +int read_syntaxelement_aec(struct syntaxelement *se, struct img_par *img, + struct datapartition *this_data_part) +{ + int curr_len; + struct decoding_environment_s *dep_dp = &(this_data_part->de_aec); + + curr_len = arideco_bits_read(dep_dp); + + se->reading(se, img, dep_dp); + + se->len = (arideco_bits_read(dep_dp) - curr_len); + return se->len; +} + +/*! + ************************************************************************ + * \brief + * This function is used to arithmetically decode the + * run length info of the skip mb + ************************************************************************ + */ +void readrunlenghtfrombuffer_aec(struct syntaxelement *se, struct img_par *img, + struct decoding_environment_s *dep_dp) +{ + struct bi_context_type_s *pctx; + int ctx, symbol; + pctx = img->current_slice->tex_ctx->one_contexts[0]; + symbol = 0; + ctx = 0; + while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) { + symbol += 1; + ctx++; + if (ctx >= 3) + ctx = 3; + } + se->value1 = symbol; +#if TRACE + fprintf(p_trace, "@%d%s\t\t\t%d\n", + symbol_count++, se->tracestring, se->value1); + fflush(p_trace); +#endif +} + +/*! + ************************************************************************ + * \brief + * This function is used to arithmetically decode a pair of + * intra prediction modes of a given MB. + ************************************************************************ + */ +int mapd_intrap[5] = {0, 2, 3, 4, 1}; +void read_intrapredmode_aec(struct syntaxelement *se, struct img_par *img, + struct decoding_environment_s *dep_dp) +{ + struct bi_context_type_s *pctx; + int ctx, symbol; + pctx = img->current_slice->tex_ctx->one_contexts[1]; + symbol = 0; + ctx = 0; +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & AEC_DUMP) + io_printf(" -- read_intrapredmode_aec ctx : %d\n", ctx); +#endif + while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) { + symbol += 1; + ctx++; + if (ctx >= 3) + ctx = 3; +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & AEC_DUMP) + io_printf(" -- read_intrapredmode_aec ctx : %d\n", ctx); +#endif + if (symbol == 4) + break; + } + se->value1 = mapd_intrap[symbol] - 1; + +#if TRACE + fprintf(p_trace, "@%d %s\t\t\t%d\n", + symbol_count++, se->tracestring, se->value1); + fflush(p_trace); +#endif +} + +/*! + ************************************************************************ + * \brief + * decoding of unary binarization using one or 2 distinct + * models for the first and all remaining bins; no terminating + * "0" for max_symbol + *********************************************************************** + */ +unsigned int unary_bin_max_decode(struct decoding_environment_s *dep_dp, + struct bi_context_type_s *ctx, + int ctx_offset, unsigned int max_symbol) +{ + unsigned int l; + unsigned int symbol; + struct bi_context_type_s *ictx; + + symbol = biari_decode_symbol(dep_dp, ctx); + + if (symbol == 0) + return 0; + else { + if (max_symbol == 1) + return symbol; + symbol = 0; + ictx = ctx + ctx_offset; + do { + l = biari_decode_symbol(dep_dp, ictx); + symbol++; + } while ((l != 0) && (symbol < max_symbol - 1)); + if ((l != 0) && (symbol == max_symbol - 1)) + symbol++; + return symbol; + } +} + +/*! + ************************************************************************ + * \brief + * decoding of unary binarization using one or 2 distinct + * models for the first and all remaining bins + *********************************************************************** + */ +unsigned int unary_bin_decode(struct decoding_environment_s *dep_dp, + struct bi_context_type_s *ctx, int ctx_offset) +{ + unsigned int l; + unsigned int symbol; + struct bi_context_type_s *ictx; + + symbol = 1 - biari_decode_symbol(dep_dp, ctx); + + if (symbol == 0) + return 0; + else { + symbol = 0; + ictx = ctx + ctx_offset; + do { + l = 1 - biari_decode_symbol(dep_dp, ictx); + symbol++; + } while (l != 0); + return symbol; + } +} + +/*! + ************************************************************************ + * \brief + * This function is used to arithmetically decode the chroma + * intra prediction mode of a given MB. + ************************************************************************ + */ +void read_cipredmode_aec(struct syntaxelement *se, + struct img_par *img, + struct decoding_environment_s *dep_dp) +{ + struct texture_info_contexts *ctx = img->current_slice->tex_ctx; + struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; + int act_ctx, a, b; + int act_sym = se->value1; + + if (curr_mb->mb_available_up == NULL) + b = 0; + else { + /*if ( (curr_mb->mb_available_up)->mb_type==IPCM) + b=0; + else*/ + b = (((curr_mb->mb_available_up)->c_ipred_mode != 0) ? 1 : 0); + } + + if (curr_mb->mb_available_left == NULL) + a = 0; + else { + /* if ( (curr_mb->mb_available_left)->mb_type==IPCM) + a=0; + else*/ + a = (((curr_mb->mb_available_left)->c_ipred_mode != 0) ? 1 : 0); + } + + act_ctx = a + b; + + + act_sym = biari_decode_symbol(dep_dp, ctx->cipr_contexts + act_ctx); + + if (act_sym != 0) + act_sym = unary_bin_max_decode(dep_dp, ctx->cipr_contexts + 3, + 0, 2) + 1; + + se->value1 = act_sym; + +#if TRACE + fprintf(p_trace, "@%d %s\t\t%d\n", + symbol_count++, se->tracestring, se->value1); + fflush(p_trace); +#endif + +} + +int slice_header(char *buf, int startcodepos, int length) +{ + int i; + + int weight_para_num = 0; + int mb_row; + int mb_column; + int mb_index; + int mb_width, mb_height; + + mb_column = 0; + + memcpy(curr_stream->stream_buffer, buf, length); + curr_stream->code_len = curr_stream->bitstream_length = length; + + curr_stream->read_len = + curr_stream->frame_bitoffset = (startcodepos) * 8; + slice_vertical_position = u_v(8, "slice vertical position"); + + push_es(slice_vertical_position, 8); + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & SLICE_INFO_DUMP) + io_printf(" * 8-bits slice_vertical_position : %d\n", + slice_vertical_position); +#endif + + if (vertical_size > 2800) { + slice_vertical_position_extension = u_v(3, + "slice vertical position extension"); + push_es(slice_vertical_position_extension, 3); + + } + + if (vertical_size > 2800) + mb_row = (slice_vertical_position_extension << 7) + + slice_vertical_position; + else + mb_row = slice_vertical_position; + + mb_width = (horizontal_size + 15) / 16; + if (!progressive_sequence) + mb_height = 2 * ((vertical_size + 31) / 32); + else + mb_height = (vertical_size + 15) / 16; + + + mb_index = mb_row * mb_width + mb_column; + + if (!img->picture_structure && img->type == I_IMG + && (mb_index >= mb_width * mb_height / 2)) { + second_ifield = 1; + img->type = P_IMG; + pre_img_type = P_IMG; + } + + { + if (!fixed_picture_qp) { + fixed_slice_qp = u_v(1, "fixed_slice_qp"); + push_es(fixed_slice_qp, 1); +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & SLICE_INFO_DUMP) + io_printf(" * 1-bit fixed_slice_qp : %d\n", + fixed_slice_qp); +#endif + slice_qp = u_v(6, "slice_qp"); + push_es(slice_qp, 6); +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & SLICE_INFO_DUMP) + io_printf(" * 6-bits slice_qp : %d\n", + slice_qp); +#endif + + img->qp = slice_qp; + } + + if (img->type != I_IMG) { + img->slice_weighting_flag = u_v(1, + "slice weighting flag"); + + if (img->slice_weighting_flag) { + + if (second_ifield && !img->picture_structure) + weight_para_num = 1; + else if (img->type == P_IMG + && img->picture_structure) + weight_para_num = 2; + else if (img->type == P_IMG + && !img->picture_structure) + weight_para_num = 4; + else if (img->type == B_IMG + && img->picture_structure) + weight_para_num = 2; + else if (img->type == B_IMG + && !img->picture_structure) + weight_para_num = 4; + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & SLICE_INFO_DUMP) + io_printf(" - weight_para_num : %d\n", + weight_para_num); +#endif + for (i = 0; i < weight_para_num; i++) { + img->lum_scale[i] = u_v(8, + "luma scale"); + + img->lum_shift[i] = i_8("luma shift"); + + marker_bit = u_1("insert bit"); + + + { + img->chroma_scale[i] = u_v(8, + "chroma scale"); + + img->chroma_shift[i] = i_8( + "chroma shift"); + + marker_bit = u_1("insert bit"); + + } + } + img->mb_weighting_flag = u_v(1, + "MB weighting flag"); + + } + } + } + + +#if 1 + return mb_index; +#endif +} + +void no_mem_exit(char *where) +{ + io_printf("%s\r\n", where); +} + +unsigned char bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + +struct inputstream_s { + /*FILE *f;*/ + unsigned char buf[SVA_STREAM_BUF_SIZE]; + unsigned int uclear_bits; + unsigned int upre_3bytes; + int ibyte_position; + int ibuf_bytesnum; + int iclear_bitsnum; + int istuff_bitsnum; + int ibits_count; +}; + +struct inputstream_s IRABS; +struct inputstream_s *p_irabs = &IRABS; + +struct stat_bits { + int curr_frame_bits; + int prev_frame_bits; + int emulate_bits; + int prev_emulate_bits; + int last_unit_bits; + int bitrate; + int total_bitrate[1000]; + int coded_pic_num; + int time_s; +}; + +struct stat_bits *stat_bits_ptr; + +unsigned char *temp_slice_buf; +int start_codeposition; +int first_slice_length; +int first_slice_startpos; + +int bitstream_buf_used; +int startcode_offset; + +int bitstream_read_ptr; + +int demulate_enable; + +int last_dquant; + +int total_mb_count; + +int current_mb_skip; + +int skip_mode_flag; + +int current_mb_intra; + +/* + ************************************************************************* + * Function: Check start code's type + * Input: + * Output: + * Return: + * Author: XZHENG, 20080515 + ************************************************************************* + */ +void check_type(int startcode) +{ + startcode = startcode & 0x000000ff; + switch (startcode) { + case 0xb0: + case 0xb2: + case 0xb5: + demulate_enable = 0; + break; + default: + demulate_enable = 1; + break; + } + +} +/* + ************************************************************************* + * Function: + * Input: + * Output: + * Return: 0 : OK + -1 : arrive at stream end + -2 : meet another start code + * Attention: + ************************************************************************* + */ +int clear_nextbyte(struct inputstream_s *p) +{ + int i, k, j; + unsigned char temp[3]; + i = p->ibyte_position; + k = p->ibuf_bytesnum - i; + if (k < 3) { + for (j = 0; j < k; j++) + temp[j] = p->buf[i + j]; + + p->ibuf_bytesnum = read_bitstream(p->buf + k, + SVA_STREAM_BUF_SIZE - k); + bitstream_buf_used++; + if (p->ibuf_bytesnum == 0) { + if (k > 0) { + while (k > 0) { + p->upre_3bytes = ((p->upre_3bytes << 8) + | p->buf[i]) + & 0x00ffffff; + if (p->upre_3bytes < 4 + && demulate_enable) { + p->uclear_bits = + (p->uclear_bits + << 6) + | (p->buf[i] + >> 2); + p->iclear_bitsnum += 6; + stat_bits_ptr->emulate_bits + += 2; + } else { + p->uclear_bits = (p->uclear_bits + << 8) + | p->buf[i]; + p->iclear_bitsnum += 8; + } + p->ibyte_position++; + k--; + i++; + } + return 0; + } else { + return -1; + } + } else { + for (j = 0; j < k; j++) + p->buf[j] = temp[j]; + p->ibuf_bytesnum += k; + i = p->ibyte_position = 0; + } + } + if (p->buf[i] == 0 && p->buf[i + 1] == 0 && p->buf[i + 2] == 1) + return -2; + p->upre_3bytes = ((p->upre_3bytes << 8) | p->buf[i]) & 0x00ffffff; + if (p->upre_3bytes < 4 && demulate_enable) { + p->uclear_bits = (p->uclear_bits << 6) | (p->buf[i] >> 2); + p->iclear_bitsnum += 6; + stat_bits_ptr->emulate_bits += 2; + } else { + p->uclear_bits = (p->uclear_bits << 8) | p->buf[i]; + p->iclear_bitsnum += 8; + } + p->ibyte_position++; + return 0; +} + +/* + ************************************************************************* + * Function: + * Input: + * Output: + * Return: 0 : OK + -1 : arrive at stream end + -2 : meet another start code + * Attention: + ************************************************************************* + */ +int read_n_bit(struct inputstream_s *p, int n, int *v) +{ + int r; + unsigned int t; + while (n > p->iclear_bitsnum) { + r = clear_nextbyte(p); + if (r) { + if (r == -1) { + if (p->ibuf_bytesnum - p->ibyte_position > 0) + break; + } + return r; + } + } + t = p->uclear_bits; + r = 32 - p->iclear_bitsnum; + *v = (t << r) >> (32 - n); + p->iclear_bitsnum -= n; + return 0; +} + +#ifdef AVSP_LONG_CABAC +unsigned char TMP_BUF[2 * SVA_STREAM_BUF_SIZE]; +int tmp_buf_wr_ptr; +int tmp_buf_rd_ptr; +int tmp_buf_count; +#endif +void open_irabs(struct inputstream_s *p) +{ + p->uclear_bits = 0xffffffff; + p->ibyte_position = 0; + p->ibuf_bytesnum = 0; + p->iclear_bitsnum = 0; + p->istuff_bitsnum = 0; + p->ibits_count = 0; + p->upre_3bytes = 0; + + bitstream_buf_used = 0; + bitstream_read_ptr = (src_start - 16) & 0xfffffff0; + +#ifdef AVSP_LONG_CABAC + tmp_buf_count = 0; + tmp_buf_wr_ptr = 0; + tmp_buf_rd_ptr = 0; +#endif + +} + +void move_bitstream(unsigned int move_from_addr, unsigned int move_to_addr, + int move_size) +{ + int move_bytes_left = move_size; + unsigned int move_read_addr; + unsigned int move_write_addr = move_to_addr; + + int move_byte; + unsigned int data32; + + while (move_from_addr > vld_mem_end_addr) { + move_from_addr = move_from_addr + vld_mem_start_addr + - vld_mem_end_addr - 8; + } + move_read_addr = move_from_addr; + while (move_bytes_left > 0) { + move_byte = move_bytes_left; + if (move_byte > 512) + move_byte = 512; + if ((move_read_addr + move_byte) > vld_mem_end_addr) + move_byte = (vld_mem_end_addr + 8) - move_read_addr; + + WRITE_VREG(LMEM_DMA_ADR, move_read_addr); + WRITE_VREG(LMEM_DMA_COUNT, move_byte / 2); + WRITE_VREG(LMEM_DMA_CTRL, 0xc200); + + data32 = 0x8000; + while (data32 & 0x8000) + data32 = READ_VREG(LMEM_DMA_CTRL); + + WRITE_VREG(LMEM_DMA_ADR, move_write_addr); + WRITE_VREG(LMEM_DMA_COUNT, move_byte / 2); + WRITE_VREG(LMEM_DMA_CTRL, 0x8200); + + data32 = 0x8000; + while (data32 & 0x8000) + data32 = READ_VREG(LMEM_DMA_CTRL); + + data32 = 0x0fff; + while (data32 & 0x0fff) + data32 = READ_VREG(WRRSP_LMEM); + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & STREAM_INFO_DUMP) + io_printf(" 2 MOVE %d Bytes from 0x%x to 0x%x\n", + move_byte, move_read_addr, move_write_addr); +#endif + + move_read_addr = move_read_addr + move_byte; + if (move_read_addr > vld_mem_end_addr) + move_read_addr = vld_mem_start_addr; + move_write_addr = move_write_addr + move_byte; + move_bytes_left = move_bytes_left - move_byte; + } + +} + +int read_bitstream(unsigned char *buf, int size) +{ + int i; + +#ifdef AVSP_LONG_CABAC + + unsigned int *TMP_BUF_32 = (unsigned int *)bitstream_read_tmp; + if (tmp_buf_count < size) { + dma_sync_single_for_cpu(amports_get_dma_device(), + bitstream_read_tmp_phy, SVA_STREAM_BUF_SIZE, + DMA_FROM_DEVICE); + + move_bitstream(bitstream_read_ptr, bitstream_read_tmp_phy, + SVA_STREAM_BUF_SIZE); + + for (i = 0; i < SVA_STREAM_BUF_SIZE / 8; i++) { + TMP_BUF[tmp_buf_wr_ptr++] = + (TMP_BUF_32[2 * i + 1] >> 24) & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = + (TMP_BUF_32[2 * i + 1] >> 16) & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 1] >> 8) + & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 1] >> 0) + & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = + (TMP_BUF_32[2 * i + 0] >> 24) & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = + (TMP_BUF_32[2 * i + 0] >> 16) & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 0] >> 8) + & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 0] >> 0) + & 0xff; + if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_wr_ptr = 0; + } + tmp_buf_count = tmp_buf_count + SVA_STREAM_BUF_SIZE; + bitstream_read_ptr = bitstream_read_ptr + SVA_STREAM_BUF_SIZE; + } + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & STREAM_INFO_DUMP) + io_printf(" Read %d bytes from %d, size left : %d\n", + size, tmp_buf_rd_ptr, tmp_buf_count); +#endif + for (i = 0; i < size; i++) { + buf[i] = TMP_BUF[tmp_buf_rd_ptr++]; + if (tmp_buf_rd_ptr >= (2 * SVA_STREAM_BUF_SIZE)) + tmp_buf_rd_ptr = 0; + } + tmp_buf_count = tmp_buf_count - size; + +#else + for (i = 0; i < size; i++) + buf[i] = tmp_stream[bitstream_read_ptr + i]; + bitstream_read_ptr = bitstream_read_ptr + size; +#endif + + return size; +} + +int next_startcode(struct inputstream_s *p) +{ + int i, m; + unsigned char a = 0, b = 0; + m = 0; + + while (1) { + if (p->ibyte_position >= p->ibuf_bytesnum - 2) { + m = p->ibuf_bytesnum - p->ibyte_position; + if (m < 0) + return -2; + if (m == 1) + b = p->buf[p->ibyte_position + 1]; + if (m == 2) { + b = p->buf[p->ibyte_position + 1]; + a = p->buf[p->ibyte_position]; + } + p->ibuf_bytesnum = read_bitstream(p->buf, + SVA_STREAM_BUF_SIZE); + p->ibyte_position = 0; + bitstream_buf_used++; + } + + if (p->ibuf_bytesnum + m < 3) + return -1; + + if (m == 1 && b == 0 && p->buf[0] == 0 && p->buf[1] == 1) { + p->ibyte_position = 2; + p->iclear_bitsnum = 0; + p->istuff_bitsnum = 0; + p->ibits_count += 24; + p->upre_3bytes = 1; + return 0; + } + + if (m == 2 && b == 0 && a == 0 && p->buf[0] == 1) { + p->ibyte_position = 1; + p->iclear_bitsnum = 0; + p->istuff_bitsnum = 0; + p->ibits_count += 24; + p->upre_3bytes = 1; + return 0; + } + + if (m == 2 && b == 0 && p->buf[0] == 0 && p->buf[1] == 1) { + p->ibyte_position = 2; + p->iclear_bitsnum = 0; + p->istuff_bitsnum = 0; + p->ibits_count += 24; + p->upre_3bytes = 1; + return 0; + } + + for (i = p->ibyte_position; i < p->ibuf_bytesnum - 2; i++) { + if (p->buf[i] == 0 && p->buf[i + 1] == 0 + && p->buf[i + 2] == 1) { + p->ibyte_position = i + 3; + p->iclear_bitsnum = 0; + p->istuff_bitsnum = 0; + p->ibits_count += 24; + p->upre_3bytes = 1; + return 0; + } + p->ibits_count += 8; + } + p->ibyte_position = i; + } +} + +int get_oneunit(char *buf, int *startcodepos, int *length) +{ + int i, j, k; + i = next_startcode(p_irabs); + + if (i != 0) { + if (i == -1) + io_printf( + "\narrive at stream end and start code is not found!"); + if (i == -2) + io_printf("\np->ibyte_position error!"); + + } + startcode_offset = + p_irabs->ibyte_position + - 3 + (bitstream_buf_used-1) + * SVA_STREAM_BUF_SIZE; + buf[0] = 0; + buf[1] = 0; + buf[2] = 1; + *startcodepos = 3; + i = read_n_bit(p_irabs, 8, &j); + buf[3] = (char)j; + + check_type(buf[3]); + if (buf[3] == SEQUENCE_END_CODE) { + *length = 4; + return -1; + } + k = 4; + while (1) { + i = read_n_bit(p_irabs, 8, &j); + if (i < 0) + break; + buf[k++] = (char)j; + if (k >= (MAX_CODED_FRAME_SIZE - 1)) + break; + } + if (p_irabs->iclear_bitsnum > 0) { + int shift; + shift = 8 - p_irabs->iclear_bitsnum; + i = read_n_bit(p_irabs, p_irabs->iclear_bitsnum, &j); + + if (j != 0) + buf[k++] = (char)(j << shift); + stat_bits_ptr->last_unit_bits += shift; + } + *length = k; + return k; +} + +/*unsigned char tmp_buf[MAX_CODED_FRAME_SIZE] __attribute__ ((aligned(64)));*/ +/*unsigned char tmp_buf[MAX_CODED_FRAME_SIZE] __aligned(64);*/ +int header(void) +{ + unsigned char *buf; + int startcodepos, length; + + unsigned char *tmp_buf; + tmp_buf = (unsigned char *)avsp_heap_adr; + + buf = &tmp_buf[0]; + while (1) { + start_codeposition = get_oneunit(buf, &startcodepos, &length); + + switch (buf[startcodepos]) { + case SEQUENCE_HEADER_CODE: + io_printf( + "# SEQUENCE_HEADER_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + case EXTENSION_START_CODE: + io_printf( + "# EXTENSION_START_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + case USER_DATA_START_CODE: + io_printf( + "# USER_DATA_START_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + case VIDEO_EDIT_CODE: + io_printf( + "# VIDEO_EDIT_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + case I_PICTURE_START_CODE: + io_printf( + "# I_PICTURE_START_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + case PB_PICTURE_START_CODE: + io_printf( + "# PB_PICTURE_START_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + case SEQUENCE_END_CODE: + io_printf( + "# SEQUENCE_END_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); + break; + default: + io_printf( + "# SLICE_START_CODE (0x%02x) found at offset %d (0x%x)\n", + buf[startcodepos], startcode_offset, + startcode_offset); +#if 0 + io_printf("VLD_MEM_VIFIFO_START_PTR %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_START_PTR)); + io_printf("VLD_MEM_VIFIFO_CURR_PTR %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_CURR_PTR)); + io_printf("VLD_MEM_VIFIFO_END_PTR %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_END_PTR)); + io_printf("VLD_MEM_VIFIFO_WP %x\r\n" + READ_VREG(VLD_MEM_VIFIFO_WP)); + io_printf("VLD_MEM_VIFIFO_RP %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + io_printf("VLD_MEM_VBUF_RD_PTR %x\r\n" + READ_VREG(VLD_MEM_VBUF_RD_PTR)); + io_printf("VLD_MEM_VIFIFO_BUF_CNTL %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL)); + io_printf("PARSER_VIDEO_HOLE %x\r\n", + READ_MPEG_REG(PARSER_VIDEO_HOLE)); +#endif + if ((buf[startcodepos] >= SLICE_START_CODE_MIN + && buf[startcodepos] + <= SLICE_START_CODE_MAX) + && ((!img->seq_header_indicate) + || (img->type == B_IMG + && img->b_discard_flag + == 1 + && !img->no_forward_reference))) { + break; + } else if (buf[startcodepos] >= SLICE_START_CODE_MIN) { + + first_slice_length = length; + first_slice_startpos = startcodepos; + + temp_slice_buf = &tmp_buf[0]; + return SOP; + } else { + io_printf("Can't find start code"); + return -EOS; + } + } + } + +} + +/* + ************************************************************************* + * Function:Allocates a Bitstream + * Input: + * Output:allocated Bitstream point + * Return: + * Attention: + ************************************************************************* + */ +struct bitstream_s *alloc_bitstream(void) +{ + struct bitstream_s *bitstream; + + bitstream = (struct bitstream_s *)local_alloc(1, + sizeof(struct bitstream_s)); + if (bitstream == NULL) { + io_printf( + "AllocBitstream: Memory allocation for Bitstream failed"); + } + bitstream->stream_buffer = (unsigned char *)local_alloc( + MAX_CODED_FRAME_SIZE, + sizeof(unsigned char)); + if (bitstream->stream_buffer == NULL) { + io_printf( + "AllocBitstream: Memory allocation for streamBuffer failed"); + } + + return bitstream; +} + +void biari_init_context_logac(struct bi_context_type_s *ctx) +{ + ctx->LG_PMPS = (QUARTER << LG_PMPS_SHIFTNO) - 1; + ctx->MPS = 0; + ctx->cycno = 0; +} + +#define BIARI_CTX_INIT1_LOG(jj, ctx)\ +{\ + for (j = 0; j < jj; j++)\ + biari_init_context_logac(&(ctx[j]));\ +} + +#define BIARI_CTX_INIT2_LOG(ii, jj, ctx)\ +{\ + for (i = 0; i < ii; i++)\ + for (j = 0; j < jj; j++)\ + biari_init_context_logac(&(ctx[i][j]));\ +} + +#define BIARI_CTX_INIT3_LOG(ii, jj, kk, ctx)\ +{\ + for (i = 0; i < ii; i++)\ + for (j = 0; j < jj; j++)\ + for (k = 0; k < kk; k++)\ + biari_init_context_logac(&(ctx[i][j][k]));\ +} + +#define BIARI_CTX_INIT4_LOG(ii, jj, kk, ll, ctx)\ +{\ + for (i = 0; i < ii; i++)\ + for (j = 0; j < jj; j++)\ + for (k = 0; k < kk; k++)\ + for (l = 0; l < ll; l++)\ + biari_init_context_logac\ + (&(ctx[i][j][k][l]));\ +} + +void init_contexts(struct img_par *img) +{ + struct motion_info_contexts_s *mc = img->current_slice->mot_ctx; + struct texture_info_contexts *tc = img->current_slice->tex_ctx; + int i, j; + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & SLICE_INFO_DUMP) + io_printf(" ---- init_contexts ----\n"); +#endif + + BIARI_CTX_INIT2_LOG(3, NUM_MB_TYPE_CTX, mc->mb_type_contexts); + BIARI_CTX_INIT2_LOG(2, NUM_B8_TYPE_CTX, mc->b8_type_contexts); + BIARI_CTX_INIT2_LOG(2, NUM_MV_RES_CTX, mc->mv_res_contexts); + BIARI_CTX_INIT2_LOG(2, NUM_REF_NO_CTX, mc->ref_no_contexts); + BIARI_CTX_INIT1_LOG(NUM_DELTA_QP_CTX, mc->delta_qp_contexts); + BIARI_CTX_INIT1_LOG(NUM_MB_AFF_CTX, mc->mb_aff_contexts); + + BIARI_CTX_INIT1_LOG(NUM_IPR_CTX, tc->ipr_contexts); + BIARI_CTX_INIT1_LOG(NUM_CIPR_CTX, tc->cipr_contexts); + BIARI_CTX_INIT2_LOG(3, NUM_CBP_CTX, tc->cbp_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_BCBP_CTX, tc->bcbp_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_ONE_CTX, tc->one_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_ABS_CTX, tc->abs_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_MAP_CTX, tc->fld_map_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_LAST_CTX, + tc->fld_last_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_MAP_CTX, tc->map_contexts); + BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_LAST_CTX, tc->last_contexts); +#ifdef TEST_WEIGHTING_AEC + biari_init_context_logac(&mc->mb_weighting_pred); +#endif +} + +/*! + ************************************************************************ + * \brief + * Allocation of contexts models for the motion info + * used for arithmetic decoding + * + ************************************************************************ + */ +struct motion_info_contexts_s *create_contexts_motioninfo(void) +{ + struct motion_info_contexts_s *deco_ctx; + + deco_ctx = (struct motion_info_contexts_s *)local_alloc(1, + sizeof(struct motion_info_contexts_s)); + if (deco_ctx == NULL) + no_mem_exit("create_contexts_motioninfo: deco_ctx"); + + return deco_ctx; +} + +/*! + ************************************************************************ + * \brief + * Allocates of contexts models for the texture info + * used for arithmetic decoding + ************************************************************************ + */ +struct texture_info_contexts *create_contexts_textureinfo(void) +{ + struct texture_info_contexts *deco_ctx; + + deco_ctx = (struct texture_info_contexts *)local_alloc(1, + sizeof(struct texture_info_contexts)); + if (deco_ctx == NULL) + no_mem_exit("create_contexts_textureinfo: deco_ctx"); + + return deco_ctx; +} + +struct datapartition *alloc_partition(int n) +{ + struct datapartition *part_arr, *datapart; + int i; + + part_arr = + (struct datapartition *)local_alloc(n, sizeof(struct datapartition)); + if (part_arr == NULL) { + no_mem_exit( + "alloc_partition: Memory allocation for Data Partition failed"); + } + +#if LIWR_FIX + part_arr[0].bitstream = NULL; +#else + for (i = 0; i < n; i++) { + datapart = &(part_arr[i]); + datapart->bitstream = (struct bitstream_s *)local_alloc(1, + sizeof(struct bitstream_s)); + if (datapart->bitstream == NULL) { + no_mem_exit( + "alloc_partition: Memory allocation for Bitstream failed"); + } + } +#endif + return part_arr; +} + +void malloc_slice(struct img_par *img) +{ + struct slice_s *currslice; + + img->current_slice = + (struct slice_s *)local_alloc(1, sizeof(struct slice_s)); + currslice = img->current_slice; + if (currslice == NULL) + no_mem_exit( + "Memory allocation for struct slice_s datastruct Failed" + ); + if (1) { + + currslice->mot_ctx = create_contexts_motioninfo(); + currslice->tex_ctx = create_contexts_textureinfo(); + } +#if LIWR_FIX + currslice->max_part_nr = 1; +#else + currslice->max_part_nr = 3; +#endif + currslice->part_arr = alloc_partition(currslice->max_part_nr); +} + +void init(struct img_par *img) +{ + int i; + + for (i = 0; i < 256; i++) + img->quad[i] = i * i; +} + +/* + ************************************************************************* + * Function:Allocate 2D memory array -> int array2D[rows][columns] + * Input: + * Output: memory size in bytes + * Return: + * Attention: + ************************************************************************* + */ + +int get_mem2Dint(int ***array2D, int rows, int columns) +{ + int i; + + *array2D = (int **)local_alloc(rows, sizeof(int *)); + if (*array2D == NULL) + no_mem_exit("get_mem2Dint: array2D"); + (*array2D)[0] = (int *)local_alloc(rows * columns, sizeof(int)); + if ((*array2D)[0] == NULL) + no_mem_exit("get_mem2Dint: array2D"); + + for (i = 1; i < rows; i++) + (*array2D)[i] = (*array2D)[i - 1] + columns; + + return rows * columns * sizeof(int); +} + +void initial_decode(void) +{ + int i, j; + int img_height = (vertical_size + img->auto_crop_bottom); + int memory_size = 0; + + malloc_slice(img); + mb_data = (struct macroblock *)local_alloc( + (img->width / MB_BLOCK_SIZE) + * (img_height /*vertical_size*/ + / MB_BLOCK_SIZE), sizeof(struct macroblock)); + if (mb_data == NULL) + no_mem_exit("init_global_buffers: mb_data"); + + if (progressive_sequence) + memory_size += get_mem2Dint(&(img->ipredmode), + img->width / B8_SIZE * 2 + 4, + vertical_size / B8_SIZE * 2 + 4); + else + memory_size += get_mem2Dint(&(img->ipredmode), + img->width / B8_SIZE * 2 + 4, + (vertical_size + 32) / (2 * B8_SIZE) * 4 + 4); + + for (i = 0; i < img->width / (B8_SIZE) * 2 + 4; i++) { + for (j = 0; j < img->height / (B8_SIZE) * 2 + 4; j++) + img->ipredmode[i][j] = -1; + } + + init(img); + img->number = 0; + img->type = I_IMG; + img->imgtr_last_p = 0; + img->imgtr_next_p = 0; + + img->new_seq_header_flag = 1; + img->new_sequence_flag = 1; + +} + +void aec_new_slice(void) +{ + last_dquant = 0; +} + +/*! + ************************************************************************ + * \brief + * Initializes the DecodingEnvironment for the arithmetic coder + ************************************************************************ + */ + +void arideco_start_decoding(struct decoding_environment_s *dep, + unsigned char *cpixcode, + int firstbyte, int *cpixcode_len, int slice_type) +{ + + dcodestrm = cpixcode; + dcodestrm_len = cpixcode_len; + *dcodestrm_len = firstbyte; + + s1 = 0; + t1 = QUARTER - 1; + value_s = 0; + + value_t = 0; + + { + int i; + dbits_to_go = 0; + for (i = 0; i < B_BITS - 1; i++) { + if (--dbits_to_go < 0) + get_byte(); + + value_t = (value_t << 1) + | ((dbuffer >> dbits_to_go) & 0x01); + } + } + + while (value_t < QUARTER) { + if (--dbits_to_go < 0) + get_byte(); + + value_t = (value_t << 1) | ((dbuffer >> dbits_to_go) & 0x01); + value_s++; + } + value_t = value_t & 0xff; + + dec_final = dec_bypass = 0; + + + +} + +/* + ************************************************************************* + * Function:Checks the availability of neighboring macroblocks of + the current macroblock for prediction and context determination; + marks the unavailable MBs for intra prediction in the + ipredmode-array by -1. Only neighboring MBs in the causal + past of the current MB are checked. + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void checkavailabilityofneighbors(struct img_par *img) +{ + int i, j; + const int mb_width = img->width / MB_BLOCK_SIZE; + const int mb_nr = img->current_mb_nr; + struct macroblock *curr_mb = &mb_data[mb_nr]; + int check_value; + int remove_prediction; + + curr_mb->mb_available_up = NULL; + curr_mb->mb_available_left = NULL; + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + mb_data[mb_nr].mb_available[i][j] = NULL; + + mb_data[mb_nr].mb_available[1][1] = curr_mb; + + if (img->pix_x >= MB_BLOCK_SIZE) { + remove_prediction = curr_mb->slice_nr + != mb_data[mb_nr - 1].slice_nr; + + if (remove_prediction) + + { + + img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y + + 1) * 2] = -1; + img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y + + 1) * 2 + 1] = -1; + img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y + + 2) * 2] = -1; + img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y + + 2) * 2 + 1] = -1; + } + if (!remove_prediction) + curr_mb->mb_available[1][0] = &(mb_data[mb_nr - 1]); + + } + + check_value = (img->pix_y >= MB_BLOCK_SIZE); + if (check_value) { + remove_prediction = curr_mb->slice_nr + != mb_data[mb_nr - mb_width].slice_nr; + + if (remove_prediction) { + img->ipredmode + [(img->block_x + 1) * 2][(img->block_y + 1) + * 2 - 1] = -1; + img->ipredmode[(img->block_x + 1) * 2 + 1][(img->block_y + + 1) * 2 - 1] = -1; + img->ipredmode[(img->block_x + 1) * 2 + 2][(img->block_y + + 1) * 2 - 1] = -1; + img->ipredmode[(img->block_x + 1) * 2 + 3][(img->block_y + + 1) * 2 - 1] = -1; + } + + if (!remove_prediction) { + curr_mb->mb_available[0][1] = + &(mb_data[mb_nr - mb_width]); + } + } + + if (img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) { + remove_prediction = curr_mb->slice_nr + != mb_data[mb_nr - mb_width - 1].slice_nr; + + if (remove_prediction) { + img->ipredmode[img->block_x * 2 + 1][img->block_y * 2 + + 1] = -1; + } + if (!remove_prediction) { + curr_mb->mb_available[0][0] = &(mb_data[mb_nr - mb_width + - 1]); + } + } + + if (img->pix_y >= MB_BLOCK_SIZE + && img->pix_x < (img->width - MB_BLOCK_SIZE)) { + if (curr_mb->slice_nr == mb_data[mb_nr - mb_width + 1].slice_nr) + curr_mb->mb_available[0][2] = &(mb_data[mb_nr - mb_width + + 1]); + } + + if (1) { + curr_mb->mbaddr_a = mb_nr - 1; + curr_mb->mbaddr_b = mb_nr - img->pic_width_inmbs; + curr_mb->mbaddr_c = mb_nr - img->pic_width_inmbs + 1; + curr_mb->mbaddr_d = mb_nr - img->pic_width_inmbs - 1; + + curr_mb->mbavail_a = + (curr_mb->mb_available[1][0] != NULL) ? 1 : 0; + curr_mb->mbavail_b = + (curr_mb->mb_available[0][1] != NULL) ? 1 : 0; + curr_mb->mbavail_c = + (curr_mb->mb_available[0][2] != NULL) ? 1 : 0; + curr_mb->mbavail_d = + (curr_mb->mb_available[0][0] != NULL) ? 1 : 0; + + } + +} + +void checkavailabilityofneighborsaec(void) +{ + + int i, j; + const int mb_width = img->width / MB_BLOCK_SIZE; + const int mb_nr = img->current_mb_nr; + struct macroblock *curr_mb = &(mb_data[mb_nr]); + int check_value; + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + mb_data[mb_nr].mb_available[i][j] = NULL; + mb_data[mb_nr].mb_available[1][1] = &(mb_data[mb_nr]); + + if (img->pix_x >= MB_BLOCK_SIZE) { + int remove_prediction = curr_mb->slice_nr + != mb_data[mb_nr - 1].slice_nr; + if (!remove_prediction) + curr_mb->mb_available[1][0] = &(mb_data[mb_nr - 1]); + } + + check_value = (img->pix_y >= MB_BLOCK_SIZE); + if (check_value) { + int remove_prediction = curr_mb->slice_nr + != mb_data[mb_nr - mb_width].slice_nr; + + if (!remove_prediction) { + curr_mb->mb_available[0][1] = + &(mb_data[mb_nr - mb_width]); + } + } + + if (img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) { + int remove_prediction = curr_mb->slice_nr + != mb_data[mb_nr - mb_width - 1].slice_nr; + if (!remove_prediction) { + curr_mb->mb_available[0][0] = &(mb_data[mb_nr - mb_width + - 1]); + } + } + + if (img->pix_y >= MB_BLOCK_SIZE + && img->pix_x < (img->width - MB_BLOCK_SIZE)) { + if (curr_mb->slice_nr == mb_data[mb_nr - mb_width + 1].slice_nr) + curr_mb->mb_available[0][2] = &(mb_data[mb_nr - mb_width + + 1]); + } + curr_mb->mb_available_left = curr_mb->mb_available[1][0]; + curr_mb->mb_available_up = curr_mb->mb_available[0][1]; + curr_mb->mbaddr_a = mb_nr - 1; + curr_mb->mbaddr_b = mb_nr - img->pic_width_inmbs; + curr_mb->mbaddr_c = mb_nr - img->pic_width_inmbs + 1; + curr_mb->mbaddr_d = mb_nr - img->pic_width_inmbs - 1; + + curr_mb->mbavail_a = (curr_mb->mb_available[1][0] != NULL) ? 1 : 0; + curr_mb->mbavail_b = (curr_mb->mb_available[0][1] != NULL) ? 1 : 0; + curr_mb->mbavail_c = (curr_mb->mb_available[0][2] != NULL) ? 1 : 0; + curr_mb->mbavail_d = (curr_mb->mb_available[0][0] != NULL) ? 1 : 0; +} + +/* + ************************************************************************* + * Function:initializes the current macroblock + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void start_macroblock(struct img_par *img) +{ + int i, j, k, l; + struct macroblock *curr_mb; + +#ifdef AVSP_LONG_CABAC +#else + +#endif + + curr_mb = &mb_data[img->current_mb_nr]; + + /* Update coordinates of the current macroblock */ + img->mb_x = (img->current_mb_nr) % (img->width / MB_BLOCK_SIZE); + img->mb_y = (img->current_mb_nr) / (img->width / MB_BLOCK_SIZE); + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & MB_NUM_DUMP) + io_printf(" #Begin MB : %d, (%x, %x) es_ptr %d\n", + img->current_mb_nr, img->mb_x, img->mb_y, es_ptr); +#endif + + + total_mb_count = total_mb_count + 1; + + /* Define vertical positions */ + img->block_y = img->mb_y * BLOCK_SIZE / 2; /* luma block position */ + img->block8_y = img->mb_y * BLOCK_SIZE / 2; + img->pix_y = img->mb_y * MB_BLOCK_SIZE; /* luma macroblock position */ + if (chroma_format == 2) + img->pix_c_y = img->mb_y * + MB_BLOCK_SIZE; /* chroma macroblock position */ + else + img->pix_c_y = img->mb_y * + MB_BLOCK_SIZE / 2; /* chroma macroblock position */ + + /* Define horizontal positions */ + img->block_x = img->mb_x * BLOCK_SIZE / 2; /* luma block position */ + img->block8_x = img->mb_x * BLOCK_SIZE / 2; + img->pix_x = img->mb_x * MB_BLOCK_SIZE; /* luma pixel position */ + img->pix_c_x = img->mb_x * + MB_BLOCK_SIZE / 2; /* chroma pixel position */ + + checkavailabilityofneighbors(img); + + /*qp = img->qp; + curr_mb->mb_type = 0; + curr_mb->delta_quant = 0; + curr_mb->cbp = 0; + curr_mb->cbp_blk = 0; + curr_mb->c_ipred_mode = DC_PRED_8; + curr_mb->c_ipred_mode_2 = DC_PRED_8; + + for (l = 0; l < 2; l++) + for (j = 0; j < BLOCK_MULTIPLE; j++) + for (i = 0; i < BLOCK_MULTIPLE; i++) + for (k = 0; k < 2; k++) + curr_mb->mvd[l][j][i][k] = 0; + + curr_mb->cbp_bits = 0; + + for (j = 0; j < MB_BLOCK_SIZE; j++) + for (i = 0; i < MB_BLOCK_SIZE; i++) + img->m7[i][j] = 0; + + for (j = 0; j < 2 * BLOCK_SIZE; j++) + for (i = 0; i < 2 * BLOCK_SIZE; i++) { + img->m8[0][i][j] = 0; + img->m8[1][i][j] = 0; + img->m8[2][i][j] = 0; + img->m8[3][i][j] = 0; + } + + curr_mb->lf_disable = 1; + + img->weighting_prediction = 0; +} + +/* + ************************************************************************* + * Function:init macroblock I and P frames + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void init_macroblock(struct img_par *img) +{ + int i, j; + + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + img->ipredmode[img->block_x * 2 + i + 2][img->block_y + * 2 + j + 2] = -1; + } + } + +} + +/* + ************************************************************************* + * Function:Interpret the mb mode for I-Frames + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void interpret_mb_mode_i(struct img_par *img) +{ + int i; + + struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; + int num = 4; + + curr_mb->mb_type = I8MB; + + + current_mb_intra = 1; + + for (i = 0; i < 4; i++) { + curr_mb->b8mode[i] = IBLOCK; + curr_mb->b8pdir[i] = -1; + } + + for (i = num; i < 4; i++) { + curr_mb->b8mode[i] = + curr_mb->mb_type_2 == P8x8 ? + 4 : curr_mb->mb_type_2; + curr_mb->b8pdir[i] = 0; + } +} + +const int pred_4x4[9][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, + 1, 1}, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {0, 0, 0, 3, 3, 3, 3, 3, 3}, + {0, 1, 4, 4, 4, 4, 4, 4, 4}, {0, 1, 5, 5, 5, 5, 5, 5, 5}, {0, 0, + 0, 0, 0, 0, 6, 0, 0}, + {0, 1, 7, 7, 7, 7, 7, 7, 7}, {0, 0, 0, 0, 4, 5, 6, 7, 8} + +}; + +const int pred_4x4to8x8[9] = {0, 1, 2, 3, 4, 1, 0, 1, 0 + +}; + +const int pred_8x8to4x4[5] = {0, 1, 2, 3, 4}; + +void read_ipred_block_modes(struct img_par *img, int b8) +{ + int bi, bj, dec; + struct syntaxelement curr_se; + struct macroblock *curr_mb; + int j2; + int mostprobableintrapredmode; + int upintrapredmode; + int uprightintrapredmode; + int leftintrapredmode; + int leftdownintrapredmode; + int intrachromapredmodeflag; + + struct slice_s *currslice = img->current_slice; + struct datapartition *dp; + + curr_mb = mb_data + img->current_mb_nr; + intrachromapredmodeflag = IS_INTRA(curr_mb); + + curr_se.type = SE_INTRAPREDMODE; +#if TRACE + strncpy(curr_se.tracestring, "Ipred Mode", TRACESTRING_SIZE); +#endif + + if (b8 < 4) { + if (curr_mb->b8mode[b8] == IBLOCK) { + intrachromapredmodeflag = 1; + + if (1) { + dp = &(currslice->part_arr[0]); + curr_se.reading = read_intrapredmode_aec; + dp->read_syntax_element(&curr_se, img, dp); + + if (curr_se.value1 == -1) + push_es(1, 1); + else + push_es(curr_se.value1, 3); + + + } + bi = img->block_x + (b8 & 1); + bj = img->block_y + (b8 / 2); + + upintrapredmode = img->ipredmode[(bi + 1) * 2][(bj) * 2 + + 1]; + uprightintrapredmode = + img->ipredmode[(bi + 1) * 2 + 1][(bj) + * 2 + 1]; + leftintrapredmode = + img->ipredmode[(bi) * 2 + 1][(bj + 1) + * 2]; + leftdownintrapredmode = img->ipredmode[(bi) * 2 + 1][(bj + + 1) * 2 + 1]; + + if ((upintrapredmode < 0) || (leftintrapredmode < 0)) { + mostprobableintrapredmode = DC_PRED; + } else if ((upintrapredmode < NO_INTRA_PMODE) + && (leftintrapredmode < + NO_INTRA_PMODE)) { + mostprobableintrapredmode = + upintrapredmode + < leftintrapredmode ? + upintrapredmode : + leftintrapredmode; + } else if (upintrapredmode < NO_INTRA_PMODE) { + mostprobableintrapredmode = upintrapredmode; + } else if (leftintrapredmode < NO_INTRA_PMODE) { + mostprobableintrapredmode = leftintrapredmode; + } else { + mostprobableintrapredmode = + pred_4x4[leftintrapredmode + - INTRA_PMODE_4x4][upintrapredmode + - INTRA_PMODE_4x4]; + mostprobableintrapredmode = + pred_4x4to8x8[mostprobableintrapredmode]; + } + + + + dec = + (curr_se.value1 == -1) ? + mostprobableintrapredmode : + curr_se.value1 + + (curr_se.value1 + >= mostprobableintrapredmode); + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & MB_INFO_DUMP) + io_printf(" - ipredmode[%d] : %d\n", b8, dec); +#endif + + img->ipredmode[(1 + bi) * 2][(1 + bj) * 2] = dec; + img->ipredmode[(1 + bi) * 2 + 1][(1 + bj) * 2] = dec; + img->ipredmode[(1 + bi) * 2][(1 + bj) * 2 + 1] = dec; + img->ipredmode[(1 + bi) * 2 + 1][(1 + bj) * 2 + 1] = + dec; + + j2 = bj; + } + } else if (b8 == 4 && curr_mb->b8mode[b8 - 3] == IBLOCK) { + + curr_se.type = SE_INTRAPREDMODE; +#if TRACE + strncpy(curr_se.tracestring, + "Chroma intra pred mode", TRACESTRING_SIZE); +#endif + + if (1) { + dp = &(currslice->part_arr[0]); + curr_se.reading = read_cipredmode_aec; + dp->read_syntax_element(&curr_se, img, dp); + } else + + { + } + curr_mb->c_ipred_mode = curr_se.value1; + + push_es(UE[curr_se.value1][0], UE[curr_se.value1][1]); + +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & MB_INFO_DUMP) + io_printf(" * UE c_ipred_mode read : %d\n", + curr_mb->c_ipred_mode); +#endif + + if (curr_se.value1 < DC_PRED_8 || curr_se.value1 > PLANE_8) { +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & MB_INFO_DUMP) + io_printf("%d\n", img->current_mb_nr); +#endif + pr_info("illegal chroma intra pred mode!\n"); + } + } +} + +/*! + ************************************************************************ + * \brief + * This function is used to arithmetically decode the coded + * block pattern of a given MB. + ************************************************************************ + */ +void readcp_aec(struct syntaxelement *se, struct img_par *img, + struct decoding_environment_s *dep_dp) +{ + struct texture_info_contexts *ctx = img->current_slice->tex_ctx; + struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; + + int mb_x, mb_y; + int a, b; + int curr_cbp_ctx, curr_cbp_idx; + int cbp = 0; + int cbp_bit; + int mask; + + for (mb_y = 0; mb_y < 4; mb_y += 2) { + for (mb_x = 0; mb_x < 4; mb_x += 2) { + if (curr_mb->b8mode[mb_y + (mb_x / 2)] == IBLOCK) + curr_cbp_idx = 0; + else + curr_cbp_idx = 1; + + if (mb_y == 0) { + if (curr_mb->mb_available_up == NULL) + b = 0; + else { + b = ((((curr_mb->mb_available_up)->cbp + & (1 << (2 + mb_x / 2))) + == 0) ? 1 : 0); + } + + } else + b = (((cbp & (1 << (mb_x / 2))) == 0) ? 1 : 0); + + if (mb_x == 0) { + if (curr_mb->mb_available_left == NULL) + a = 0; + else { + a = + ((((curr_mb->mb_available_left)->cbp + & (1 + << (2 + * (mb_y + / 2) + + 1))) + == 0) ? + 1 : 0); + } + } else + a = (((cbp & (1 << mb_y)) == 0) ? 1 : 0); + curr_cbp_ctx = a + 2 * b; + mask = (1 << (mb_y + mb_x / 2)); + cbp_bit = biari_decode_symbol(dep_dp, + ctx->cbp_contexts[0] + curr_cbp_ctx); + + if (cbp_bit) + cbp += mask; + } + } + curr_cbp_ctx = 0; + cbp_bit = biari_decode_symbol(dep_dp, + ctx->cbp_contexts[1] + curr_cbp_ctx); + + if (cbp_bit) { + curr_cbp_ctx = 1; + cbp_bit = biari_decode_symbol(dep_dp, + ctx->cbp_contexts[1] + curr_cbp_ctx); + if (cbp_bit) { + cbp += 48; + + } else { + curr_cbp_ctx = 1; + cbp_bit = biari_decode_symbol(dep_dp, + ctx->cbp_contexts[1] + curr_cbp_ctx); + cbp += (cbp_bit == 1) ? 32 : 16; + + } + } + + se->value1 = cbp; + if (!cbp) + last_dquant = 0; + + + +} + +/*! + ************************************************************************ + * \brief + * This function is used to arithmetically decode the delta qp + * of a given MB. + ************************************************************************ + */ +void readdquant_aec(struct syntaxelement *se, struct img_par *img, + struct decoding_environment_s *dep_dp) +{ + struct motion_info_contexts_s *ctx = img->current_slice->mot_ctx; + + int act_ctx; + int act_sym; + int dquant; + + + act_ctx = ((last_dquant != 0) ? 1 : 0); + + act_sym = 1 + - biari_decode_symbol(dep_dp, + ctx->delta_qp_contexts + act_ctx); + if (act_sym != 0) { + act_ctx = 2; + act_sym = unary_bin_decode(dep_dp, + ctx->delta_qp_contexts + act_ctx, 1); + act_sym++; + } + act_sym &= 0x3f; + push_es(UE[act_sym][0], UE[act_sym][1]); + + dquant = (act_sym + 1) / 2; + if ((act_sym & 0x01) == 0) + dquant = -dquant; + se->value1 = dquant; + + last_dquant = dquant; + +} + +int csyntax; + +#define CHECKDELTAQP {\ + if (img->qp+curr_mb->delta_quant > 63\ + || img->qp+curr_mb->delta_quant < 0) {\ + csyntax = 0;\ + transcoding_error_flag = 1;\ + io_printf("error(0) (%3d|%3d) @ MB%d\n",\ + curr_mb->delta_quant,\ + img->qp+curr_mb->delta_quant,\ + img->picture_structure == 0 \ + ? img->current_mb_nr_fld : img->current_mb_nr);\ + } } + +int dct_level[65]; +int dct_run[65]; +int pair_pos; +int dct_pairs = -1; +const int t_chr[5] = {0, 1, 2, 4, 3000}; + +void readrunlevel_aec_ref(struct syntaxelement *se, struct img_par *img, + struct decoding_environment_s *dep_dp) +{ + int pairs, rank, pos; + int run, level, abslevel, symbol; + int sign; + + if (dct_pairs < 0) { + struct bi_context_type_s (*primary)[NUM_MAP_CTX]; + struct bi_context_type_s *pctx; + struct bi_context_type_s *pCTX2; + int ctx, ctx2, offset; + if (se->context == LUMA_8x8) { + if (img->picture_structure == 0) { + primary = + img->current_slice->tex_ctx->fld_map_contexts; + } else { + primary = + img->current_slice->tex_ctx->map_contexts; + } + } else { + if (img->picture_structure == 0) { + primary = + img->current_slice->tex_ctx->fld_last_contexts; + } else { + primary = + img->current_slice->tex_ctx->last_contexts; + } + } + + rank = 0; + pos = 0; + for (pairs = 0; pairs < 65; pairs++) { +#ifdef DECODING_SANITY_CHECK + /*max index is NUM_BLOCK_TYPES - 1*/ + pctx = primary[rank & 0x7]; +#else + pctx = primary[rank]; +#endif + if (rank > 0) { +#ifdef DECODING_SANITY_CHECK + /*max index is NUM_BLOCK_TYPES - 1*/ + pCTX2 = primary[(5 + (pos >> 5)) & 0x7]; +#else + pCTX2 = primary[5 + (pos >> 5)]; +#endif + ctx2 = (pos >> 1) & 0x0f; + ctx = 0; + + + if (biari_decode_symbolw(dep_dp, pctx + ctx, + pCTX2 + ctx2)) { + break; + } + } + + ctx = 1; + symbol = 0; + while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) { + symbol += 1; + ctx++; + if (ctx >= 2) + ctx = 2; + } + abslevel = symbol + 1; + + if (biari_decode_symbol_eq_prob(dep_dp)) { + level = -abslevel; + sign = 1; + } else { + level = abslevel; + sign = 0; + } +#if TRACE + tracebits2("level", 1, level); +#endif + + if (abslevel == 1) + offset = 4; + else + offset = 6; + symbol = 0; + ctx = 0; + while (biari_decode_symbol(dep_dp, pctx + ctx + offset) + == 0) { + symbol += 1; + ctx++; + if (ctx >= 1) + ctx = 1; + } + run = symbol; + +#if TRACE + tracebits2("run", 1, run); +#endif + dct_level[pairs] = level; + dct_run[pairs] = run; + if (abslevel > t_chr[rank]) { + if (abslevel <= 2) + rank = abslevel; + else if (abslevel <= 4) + rank = 3; + else + rank = 4; + } + pos += (run + 1); + if (pos >= 64) + pos = 63; + } + dct_pairs = pairs; + pair_pos = dct_pairs; + } + + if (dct_pairs > 0) { + se->value1 = dct_level[pair_pos - 1]; + se->value2 = dct_run[pair_pos - 1]; + pair_pos--; + } else { + + se->value1 = se->value2 = 0; + } + + if ((dct_pairs--) == 0) + pair_pos = 0; +} + +int b8_ctr; +#if 0 +int curr_residual_chroma[4][16][16]; +int curr_residual_luma[16][16]; +#endif + +const int SCAN[2][64][2] = {{{0, 0}, {0, 1}, {0, 2}, {1, 0}, {0, 3}, {0, 4}, {1, + 1}, {1, 2}, {0, 5}, {0, 6}, {1, 3}, {2, 0}, {2, 1}, {0, 7}, {1, + 4}, {2, 2}, {3, 0}, {1, 5}, {1, 6}, {2, 3}, {3, 1}, {3, 2}, {4, + 0}, {1, 7}, {2, 4}, {4, 1}, {2, 5}, {3, 3}, {4, 2}, {2, 6}, {3, + 4}, {4, 3}, {5, 0}, {5, 1}, {2, 7}, {3, 5}, {4, 4}, {5, 2}, {6, + 0}, {5, 3}, {3, 6}, {4, 5}, {6, 1}, {6, 2}, {5, 4}, {3, 7}, {4, + 6}, {6, 3}, {5, 5}, {4, 7}, {6, 4}, {5, 6}, {6, 5}, {5, 7}, {6, + 6}, {7, 0}, {6, 7}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, + 6}, {7, 7} }, {{0, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, { + 3, 0}, {2, 1}, {1, 2}, {0, 3}, {0, 4}, {1, 3}, {2, 2}, {3, 1}, { + 4, 0}, {5, 0}, {4, 1}, {3, 2}, {2, 3}, {1, 4}, {0, 5}, {0, 6}, { + 1, 5}, {2, 4}, {3, 3}, {4, 2}, {5, 1}, {6, 0}, {7, 0}, {6, 1}, { + 5, 2}, {4, 3}, {3, 4}, {2, 5}, {1, 6}, {0, 7}, {1, 7}, {2, 6}, { + 3, 5}, {4, 4}, {5, 3}, {6, 2}, {7, 1}, {7, 2}, {6, 3}, {5, 4}, { + 4, 5}, {3, 6}, {2, 7}, {3, 7}, {4, 6}, {5, 5}, {6, 4}, {7, 3}, { + 7, 4}, {6, 5}, {5, 6}, {4, 7}, {5, 7}, {6, 6}, {7, 5}, {7, 6}, { + 6, 7}, {7, 7} } }; + +const int SCAN_4x4[16][2] = {{0, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, {3, + 0}, {2, 1}, {1, 2}, {0, 3}, {1, 3}, {2, 2}, {3, 1}, {3, 2}, {2, + 3}, {3, 3} }; + +/* + ************************************************************************* + * Function: + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void encode_golomb_word(unsigned int symbol, unsigned int grad0, + unsigned int max_levels, unsigned int *res_bits, + unsigned int *res_len) +{ + unsigned int level, res, numbits; + + res = 1UL << grad0; + level = 1UL; + numbits = 1UL + grad0; + + while (symbol >= res && level < max_levels) { + symbol -= res; + res = res << 1; + level++; + numbits += 2UL; + } + + if (level >= max_levels) { + if (symbol >= res) + symbol = res - 1UL; + } + + *res_bits = res | symbol; + *res_len = numbits; +} + +/* + ************************************************************************* + * Function: + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void encode_multilayer_golomb_word(unsigned int symbol, + const unsigned int *grad, const unsigned int *max_levels, + unsigned int *res_bits, unsigned int *res_len) +{ + unsigned accbits, acclen, bits, len, tmp; + + accbits = acclen = 0UL; + + while (1) { + encode_golomb_word(symbol, *grad, *max_levels, &bits, &len); + accbits = (accbits << len) | bits; + acclen += len; +#ifdef AVSP_LONG_CABAC +#else + assert(acclen <= 32UL); +#endif + tmp = *max_levels - 1UL; + + if (!((len == (tmp << 1) + (*grad)) + && (bits == (1UL << (tmp + *grad)) - 1UL))) + break; + + tmp = *max_levels; + symbol -= (((1UL << tmp) - 1UL) << (*grad)) - 1UL; + grad++; + max_levels++; + } + *res_bits = accbits; + *res_len = acclen; +} + +/* + ************************************************************************* + * Function: + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +int writesyntaxelement_golomb(struct syntaxelement *se, int write_to_stream) +{ + unsigned int bits, len, i; + unsigned int grad[4], max_lev[4]; + + if (!(se->golomb_maxlevels & ~0xFF)) + encode_golomb_word(se->value1, se->golomb_grad, + se->golomb_maxlevels, &bits, &len); + else { + for (i = 0UL; i < 4UL; i++) { + grad[i] = (se->golomb_grad >> (i << 3)) & 0xFFUL; + max_lev[i] = (se->golomb_maxlevels >> (i << 3)) + & 0xFFUL; + } + encode_multilayer_golomb_word(se->value1, grad, max_lev, &bits, + &len); + } + + se->len = len; + se->bitpattern = bits; + + if (write_to_stream) + push_es(bits, len); + return se->len; +} + +/* + ************************************************************************* + * Function:Get coded block pattern and coefficients (run/level) + from the bitstream + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +void read_cbpandcoeffsfrom_nal(struct img_par *img) +{ + + int tablenum; + int inumblk; + int inumcoeff; + int symbol2D; + int escape_level_diff; + const int (*AVS_2DVLC_table_intra)[26][27]; + const int (*AVS_2DVLC_table_chroma)[26][27]; + int write_to_stream; + struct syntaxelement currse_enc; + struct syntaxelement *e_currse = &currse_enc; + + int coeff_save[65][2]; + int coeff_ptr; + + int ii, jj; + int mb_nr = img->current_mb_nr; + + int m2, jg2; + struct macroblock *curr_mb = &mb_data[mb_nr]; + + int block8x8; + + int block_x, block_y; + + struct slice_s *currslice = img->current_slice; + int level, run, coef_ctr, len, k, i0, j0, uv, qp; + + int boff_x, boff_y, start_scan; + struct syntaxelement curr_se; + struct datapartition *dp; + + AVS_2DVLC_table_intra = AVS_2DVLC_INTRA; + AVS_2DVLC_table_chroma = AVS_2DVLC_CHROMA; + write_to_stream = 1; + + dct_pairs = -1; + + curr_mb->qp = img->qp; + qp = curr_mb->qp; + + + for (block_y = 0; block_y < 4; block_y += 2) {/* all modes */ + for (block_x = 0; block_x < 4; block_x += 2) { + block8x8 = 2 * (block_y / 2) + block_x / 2; + if (curr_mb->cbp & (1 << block8x8)) { + tablenum = 0; + inumblk = 1; + inumcoeff = 65; + coeff_save[0][0] = 0; + coeff_save[0][1] = 0; + coeff_ptr = 1; + + b8_ctr = block8x8; + + boff_x = (block8x8 % 2) << 3; + boff_y = (block8x8 / 2) << 3; + + img->subblock_x = boff_x >> 2; + img->subblock_y = boff_y >> 2; + + start_scan = 0; + coef_ctr = start_scan - 1; + level = 1; + img->is_v_block = 0; + img->is_intra_block = IS_INTRA(curr_mb); + for (k = start_scan; + (k < 65) && (level != 0); + k++) { + + curr_se.context = LUMA_8x8; + curr_se.type = + (IS_INTRA(curr_mb)) ? + SE_LUM_AC_INTRA : + SE_LUM_AC_INTER; + + dp = &(currslice->part_arr[0]); + curr_se.reading = + readrunlevel_aec_ref; + dp-> + read_syntax_element(&curr_se, + img, dp); + level = curr_se.value1; + run = curr_se.value2; + len = curr_se.len; + + if (level != 0) { + coeff_save[coeff_ptr][0] = + run; + coeff_save[coeff_ptr][1] = + level; + coeff_ptr++; + } + + + + if (level != 0) {/* leave if len = 1 */ + coef_ctr += run + 1; + if ((img->picture_structure + == FRAME)) { + ii = + SCAN[img->picture_structure] + [coef_ctr][0]; + jj = + SCAN[img->picture_structure] + [coef_ctr][1]; + } else { + ii = + SCAN[img->picture_structure] + [coef_ctr][0]; + jj = + SCAN[img->picture_structure] + [coef_ctr][1]; + } + + } + } + + while (coeff_ptr > 0) { + run = + coeff_save[coeff_ptr + - 1][0]; + level = + coeff_save[coeff_ptr + - 1][1]; + + coeff_ptr--; + + symbol2D = CODE2D_ESCAPE_SYMBOL; + if (level > -27 && level < 27 + && run < 26) { + if (tablenum == 0) + + symbol2D = + AVS_2DVLC_table_intra + [tablenum] + [run][abs( + level) + - 1]; + else + + symbol2D = + AVS_2DVLC_table_intra + [tablenum] + [run][abs( + level)]; + if (symbol2D >= 0 + && level + < 0) + symbol2D++; + if (symbol2D < 0) + + symbol2D = + (CODE2D_ESCAPE_SYMBOL + + (run + << 1) + + ((level + > 0) ? + 1 : + 0)); + } + + else { + + symbol2D = + (CODE2D_ESCAPE_SYMBOL + + (run + << 1) + + ((level + > 0) ? + 1 : + 0)); + } + + + + e_currse->type = SE_LUM_AC_INTER; + e_currse->value1 = symbol2D; + e_currse->value2 = 0; + + e_currse->golomb_grad = + vlc_golomb_order + [0][tablenum][0]; + e_currse->golomb_maxlevels = + vlc_golomb_order + [0][tablenum][1]; + + writesyntaxelement_golomb( + e_currse, + write_to_stream); + + if (symbol2D + >= CODE2D_ESCAPE_SYMBOL) { + + e_currse->type = + SE_LUM_AC_INTER; + e_currse->golomb_grad = + 1; + e_currse->golomb_maxlevels = + 11; + escape_level_diff = + abs( + level) + - ((run + > MaxRun[0][tablenum]) ? + 1 : + refabslevel[tablenum][run]); + e_currse->value1 = + escape_level_diff; + + writesyntaxelement_golomb( + e_currse, + write_to_stream); + + } + + if (abs(level) + > incvlc_intra[tablenum]) { + if (abs(level) <= 2) + tablenum = + abs( + level); + else if (abs(level) <= 4) + tablenum = 3; + else if (abs(level) <= 7) + tablenum = 4; + else if (abs(level) + <= 10) + tablenum = 5; + else + tablenum = 6; + } + } + + + } + } + } + + + + m2 = img->mb_x * 2; + jg2 = img->mb_y * 2; + + + uv = -1; + block_y = 4; +#if 0 + qp = QP_SCALE_CR[curr_mb->qp]; +#endif + for (block_x = 0; block_x < 4; block_x += 2) { + + uv++; + + + b8_ctr = (uv + 4); + if ((curr_mb->cbp >> (uv + 4)) & 0x1) { + + tablenum = 0; + inumblk = 1; + inumcoeff = 65; + coeff_save[0][0] = 0; + coeff_save[0][1] = 0; + coeff_ptr = 1; + + coef_ctr = -1; + level = 1; + img->subblock_x = 0; + img->subblock_y = 0; + curr_se.context = CHROMA_AC; + curr_se.type = (IS_INTRA(curr_mb) ? + SE_CHR_AC_INTRA : + SE_CHR_AC_INTER); + dp = &(currslice->part_arr[0]); + curr_se.reading = readrunlevel_aec_ref; + img->is_v_block = uv; + img->is_intra_block = IS_INTRA(curr_mb); + for (k = 0; (k < 65) && (level != 0); k++) { + + dp->read_syntax_element + (&curr_se, img, dp); + level = curr_se.value1; + run = curr_se.value2; + len = curr_se.len; + + if (level != 0) { + coeff_save[coeff_ptr][0] = run; + coeff_save[coeff_ptr][1] = + level; + coeff_ptr++; + } + + + if (level != 0) { + coef_ctr = coef_ctr + run + 1; + if ((img->picture_structure + == FRAME) + /*&& (!curr_mb->mb_field)*/) { + i0 = + SCAN[img->picture_structure] + [coef_ctr][0]; + j0 = + SCAN[img->picture_structure] + [coef_ctr][1]; + } else { + i0 = + SCAN[img->picture_structure] + [coef_ctr][0]; + j0 = + SCAN[img->picture_structure] + [coef_ctr][1]; + } + + } + } + + while (coeff_ptr > 0) { + + run = coeff_save[coeff_ptr - 1][0]; + level = coeff_save[coeff_ptr - 1][1]; + + coeff_ptr--; + + symbol2D = CODE2D_ESCAPE_SYMBOL; + if (level > -27 && level < 27 + && run < 26) { + if (tablenum == 0) + + symbol2D = + AVS_2DVLC_table_chroma + [tablenum][run][abs( + level) + - 1]; + else + symbol2D = + AVS_2DVLC_table_chroma + [tablenum][run][abs( + level)]; + if (symbol2D >= 0 + && level < 0) + symbol2D++; + if (symbol2D < 0) + symbol2D = + (CODE2D_ESCAPE_SYMBOL + + (run + << 1) + + ((level + > 0) ? + 1 : + 0)); + } + + else { + symbol2D = + (CODE2D_ESCAPE_SYMBOL + + (run + << 1) + + ((level + > 0) ? + 1 : + 0)); + } + + e_currse->type = SE_LUM_AC_INTER; + e_currse->value1 = symbol2D; + e_currse->value2 = 0; + e_currse->golomb_grad = + vlc_golomb_order[2] + [tablenum][0]; + e_currse->golomb_maxlevels = + vlc_golomb_order[2] + [tablenum][1]; + + writesyntaxelement_golomb(e_currse, + write_to_stream); + + /* + if (write_to_stream) + { + bitCount[BITS_COEFF_UV_MB]+=e_currse->len; + e_currse++; + curr_mb->currSEnr++; + } + no_bits+=e_currse->len; + + + if (icoef == 0) break; + */ + + if (symbol2D >= CODE2D_ESCAPE_SYMBOL) { + + e_currse->type = SE_LUM_AC_INTER; + e_currse->golomb_grad = 0; + e_currse->golomb_maxlevels = 11; + escape_level_diff = + abs(level) + - ((run + > MaxRun[2][tablenum]) ? + 1 : + refabslevel[tablenum + + 14][run]); + e_currse->value1 = + escape_level_diff; + + writesyntaxelement_golomb( + e_currse, + write_to_stream); + + } + + if (abs(level) + > incvlc_chroma[tablenum]) { + if (abs(level) <= 2) + tablenum = abs(level); + else if (abs(level) <= 4) + tablenum = 3; + else + tablenum = 4; + } + } + + } + } +} + +/* + ************************************************************************* + * Function:Get the syntax elements from the NAL + * Input: + * Output: + * Return: + * Attention: + ************************************************************************* + */ + +int read_one_macroblock(struct img_par *img) +{ + int i, j; + + struct syntaxelement curr_se; + struct macroblock *curr_mb = &mb_data[img->current_mb_nr]; + + int cabp_flag; + + int tempcbp; + int fixqp; + + struct slice_s *currslice = img->current_slice; + struct datapartition *dp; + + fixqp = (fixed_picture_qp || fixed_slice_qp); + + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) { + img->m8[0][i][j] = 0; + img->m8[1][i][j] = 0; + img->m8[2][i][j] = 0; + img->m8[3][i][j] = 0; + } + + current_mb_skip = 0; + + curr_mb->qp = img->qp; + curr_se.type = SE_MBTYPE; + curr_se.mapping = linfo_ue; + + curr_mb->mb_type_2 = 0; + + if (img->type == I_IMG) + curr_mb->mb_type = 0; + + interpret_mb_mode_i(img); + + init_macroblock(img); + + if ((IS_INTRA(curr_mb)) && (img->abt_flag)) { + +#if TRACE + strncpy(curr_se.tracestring, "cabp_flag", TRACESTRING_SIZE); +#endif + + curr_se.len = 1; + curr_se.type = SE_CABP; + read_syntaxelement_flc(&curr_se); + cabp_flag = curr_se.value1; + if (cabp_flag == 0) { + curr_mb->CABP[0] = 0; + curr_mb->CABP[1] = 0; + curr_mb->CABP[2] = 0; + curr_mb->CABP[3] = 0; + } else { + for (i = 0; i < 4; i++) { + curr_se.len = 1; + curr_se.type = SE_CABP; + read_syntaxelement_flc(&curr_se); + curr_mb->CABP[i] = curr_se.value1; + } + } + + } else { + curr_mb->CABP[0] = 0; + curr_mb->CABP[1] = 0; + curr_mb->CABP[2] = 0; + curr_mb->CABP[3] = 0; + + } + + if (IS_INTRA(curr_mb)) { + for (i = 0; i < /*5*/(chroma_format + 4); i++) + + read_ipred_block_modes(img, i); + } + + curr_se.type = SE_CBP_INTRA; + curr_se.mapping = linfo_cbp_intra; + +#if TRACE + snprintf(curr_se.tracestring, TRACESTRING_SIZE, "CBP"); +#endif + + if (img->type == I_IMG || IS_INTER(curr_mb)) { + curr_se.golomb_maxlevels = 0; + + if (1) { + dp = &(currslice->part_arr[0]); + curr_se.reading = readcp_aec; + dp->read_syntax_element(&curr_se, img, dp); + } + + + curr_mb->cbp = curr_se.value1; + push_es(UE[NCBP[curr_se.value1][0]][0], + UE[NCBP[curr_se.value1][0]][1]); + + } + +# if 1 + if (curr_mb->cbp != 0) + tempcbp = 1; + else + tempcbp = 0; +#else + + if (chroma_format == 2) { +#if TRACE + snprintf(curr_se.tracestring, TRACESTRING_SIZE, "CBP422"); +#endif + curr_se.mapping = /*linfo_se*/linfo_ue; + curr_se.type = SE_CBP_INTRA; + readsyntaxelement_uvlc(&curr_se, inp); + curr_mb->cbp01 = curr_se.value1; + io_printf(" * UE cbp01 read : 0x%02X\n", curr_mb->cbp01); + } + + if (chroma_format == 2) { + if (curr_mb->cbp != 0 || curr_mb->cbp01 != 0) + tempcbp = 1; + else + tempcbp = 0; + + } else { + if (curr_mb->cbp != 0) + tempcbp = 1; + else + tempcbp = 0; + } + +#endif + + if (IS_INTRA(curr_mb) && (img->abt_flag) && (curr_mb->cbp & (0xF))) { + curr_mb->CABT[0] = curr_mb->CABP[0]; + curr_mb->CABT[1] = curr_mb->CABP[1]; + curr_mb->CABT[2] = curr_mb->CABP[2]; + curr_mb->CABT[3] = curr_mb->CABP[3]; + } else { + + curr_mb->CABT[0] = 0; + curr_mb->CABT[1] = 0; + curr_mb->CABT[2] = 0; + curr_mb->CABT[3] = 0; + + if (!fixqp && (tempcbp)) { + if (IS_INTER(curr_mb)) + curr_se.type = SE_DELTA_QUANT_INTER; + else + curr_se.type = SE_DELTA_QUANT_INTRA; + +#if TRACE + snprintf(curr_se.tracestring, + TRACESTRING_SIZE, "Delta quant "); +#endif + + if (1) { + dp = &(currslice->part_arr[0]); + curr_se.reading = readdquant_aec; + dp->read_syntax_element(&curr_se, img, dp); + } + + curr_mb->delta_quant = curr_se.value1; +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & MB_INFO_DUMP) { + io_printf(" * SE delta_quant read : %d\n", + curr_mb->delta_quant); + } +#endif + CHECKDELTAQP + + img->qp = (img->qp - MIN_QP + curr_mb->delta_quant + + (MAX_QP - MIN_QP + 1)) + % (MAX_QP - MIN_QP + 1) + MIN_QP; + } + + if (fixqp) { + curr_mb->delta_quant = 0; + img->qp = (img->qp - MIN_QP + curr_mb->delta_quant + + (MAX_QP - MIN_QP + 1)) + % (MAX_QP - MIN_QP + 1) + MIN_QP; + + } +#ifdef DUMP_DEBUG + if (avs_get_debug_flag() & MB_INFO_DUMP) + io_printf(" - img->qp : %d\n", img->qp); +#endif + } + + read_cbpandcoeffsfrom_nal(img); + return DECODE_MB; +} + +/*! + ************************************************************************ + * \brief + * finding end of a slice in case this is not the end of a frame + * + * Unsure whether the "correction" below actually solves an off-by-one + * problem or whether it introduces one in some cases :-( Anyway, + * with this change the bit stream format works with AEC again. + * StW, 8.7.02 + ************************************************************************ + */ +int aec_startcode_follows(struct img_par *img, int eos_bit) +{ + struct slice_s *currslice = img->current_slice; + struct datapartition *dp; + unsigned int bit; + struct decoding_environment_s *dep_dp; + + dp = &(currslice->part_arr[0]); + dep_dp = &(dp->de_aec); + + if (eos_bit) + bit = biari_decode_final(dep_dp); + else + bit = 0; + + return bit == 1 ? 1 : 0; +} + +#ifdef AVSP_LONG_CABAC +int process_long_cabac(void) +#else +void main(void) +#endif +{ + int data32; + int current_header; + int i; + int tmp; + + int byte_startposition; + int aec_mb_stuffing_bit; + struct slice_s *currslice; +#ifdef PERFORMANCE_DEBUG + pr_info("enter %s\r\n", __func__); +#endif + transcoding_error_flag = 0; + es_buf = es_write_addr_virt; + + if (local_heap_init(MAX_CODED_FRAME_SIZE * 4) < 0) + return -1; + + img = (struct img_par *)local_alloc(1, sizeof(struct img_par)); + if (img == NULL) + no_mem_exit("main: img"); + stat_bits_ptr = (struct stat_bits *)local_alloc(1, + sizeof(struct stat_bits)); + if (stat_bits_ptr == NULL) + no_mem_exit("main: stat_bits"); + + curr_stream = alloc_bitstream(); + + chroma_format = 1; + demulate_enable = 0; + img->seq_header_indicate = 1; + +#ifdef AVSP_LONG_CABAC + data32 = READ_VREG(LONG_CABAC_REQ); + progressive_sequence = (data32 >> 1) & 1; + fixed_picture_qp = (data32 >> 2) & 1; + img->picture_structure = (data32 >> 3) & 1; + img->type = (data32 >> 4) & 3; + skip_mode_flag = (data32 >> 6) & 1; + + src_start = READ_VREG(LONG_CABAC_SRC_ADDR); + des_start = READ_VREG(LONG_CABAC_DES_ADDR); + + data32 = READ_VREG(LONG_CABAC_PIC_SIZE); + horizontal_size = (data32 >> 0) & 0xffff; + vertical_size = (data32 >> 16) & 0xffff; + + vld_mem_start_addr = READ_VREG(VLD_MEM_VIFIFO_START_PTR); + vld_mem_end_addr = READ_VREG(VLD_MEM_VIFIFO_END_PTR); + +#else + progressive_sequence = 0; + fixed_picture_qp = 0; + img->picture_structure = 0; + img->type = I_IMG; + skip_mode_flag = 1; + horizontal_size = 1920; + vertical_size = 1080; + + src_start = 0; +#endif + + if (horizontal_size % 16 != 0) + img->auto_crop_right = 16 - (horizontal_size % 16); + else + img->auto_crop_right = 0; + + if (!progressive_sequence) { + if (vertical_size % 32 != 0) + img->auto_crop_bottom = 32 - (vertical_size % 32); + else + img->auto_crop_bottom = 0; + } else { + if (vertical_size % 16 != 0) + img->auto_crop_bottom = 16 - (vertical_size % 16); + else + img->auto_crop_bottom = 0; + } + + img->width = (horizontal_size + img->auto_crop_right); + if (img->picture_structure) + img->height = (vertical_size + img->auto_crop_bottom); + else + img->height = (vertical_size + img->auto_crop_bottom) / 2; + img->width_cr = (img->width >> 1); + + img->pic_width_inmbs = img->width / MB_BLOCK_SIZE; + img->pic_height_inmbs = img->height / MB_BLOCK_SIZE; + img->pic_size_inmbs = img->pic_width_inmbs * img->pic_height_inmbs; + + io_printf( + "[LONG CABAC] Start Transcoding from 0x%x to 0x%x Size : %d x %d\r\n", + src_start, des_start, horizontal_size, vertical_size); +#if 0 + io_printf("VLD_MEM_VIFIFO_START_PTR %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_START_PTR)); + io_printf("VLD_MEM_VIFIFO_CURR_PTR %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_CURR_PTR)); + io_printf("VLD_MEM_VIFIFO_END_PTR %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_END_PTR)); + io_printf("VLD_MEM_VIFIFO_WP %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + io_printf("VLD_MEM_VIFIFO_RP %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + io_printf("VLD_MEM_VBUF_RD_PTR %x\r\n", + READ_VREG(VLD_MEM_VBUF_RD_PTR)); + io_printf("VLD_MEM_VIFIFO_BUF_CNTL %x\r\n", + READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL)); +#endif + io_printf( + "[LONG CABAC] progressive_sequence : %d, fixed_picture_qp : %d, skip_mode_flag : %d\r\n", + progressive_sequence, fixed_picture_qp, skip_mode_flag); + io_printf("[LONG CABAC] picture_structure : %d, picture_type : %d\r\n", + img->picture_structure, img->type); + + open_irabs(p_irabs); + + initial_decode(); + + init_es(); + + current_header = header(); + io_printf("[LONG CABAC] header Return : %d\n", current_header); + + tmp = slice_header(temp_slice_buf, first_slice_startpos, + first_slice_length); + + init_contexts(img); + aec_new_slice(); + byte_startposition = (curr_stream->frame_bitoffset) / 8; + + currslice = img->current_slice; + + if (1) { + for (i = 0; i < 1; i++) { + img->current_slice->part_arr[i].read_syntax_element = + read_syntaxelement_aec; + img->current_slice->part_arr[i].bitstream = curr_stream; + } + curr_stream = currslice->part_arr[0].bitstream; + } + if ((curr_stream->frame_bitoffset) % 8 != 0) + byte_startposition++; + + arideco_start_decoding(&img->current_slice->part_arr[0].de_aec, + curr_stream->stream_buffer, (byte_startposition), + &(curr_stream->read_len), img->type); + + img->current_mb_nr = 0; + total_mb_count = 0; + while (img->current_mb_nr < img->pic_size_inmbs) + + { + start_macroblock(img); + read_one_macroblock(img); + if (img->cod_counter <= 0) + aec_mb_stuffing_bit = aec_startcode_follows(img, 1); + img->current_mb_nr++; + } + + push_es(0xff, 8); + io_printf(" Total ES_LENGTH : %d\n", es_ptr); + +#ifdef AVSP_LONG_CABAC + push_es(0xff, 64); + + if (transcoding_error_flag == 0) { +#if 1 + dma_sync_single_for_device(amports_get_dma_device(), + es_write_addr_phy, + es_ptr, DMA_TO_DEVICE); + + wmb(); /**/ +#endif + WRITE_VREG(LONG_CABAC_REQ, 0); + } +#else + fclose(f_es); +#endif + + local_heap_uninit(); +#ifdef PERFORMANCE_DEBUG + pr_info("exit %s\r\n", __func__); +#endif + return (transcoding_error_flag == 0) ? 0 : -1; +} +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c new file mode 100644 index 000000000000..732ee5b84581 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c @@ -0,0 +1,2960 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/h264/vh264.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/amports/amports_priv.h" +#include +#include + +#include "../utils/vdec.h" +#include +#include "../utils/amvdec.h" +#include "../utils/decoder_bmmu_box.h" +#include "vh264.h" +#include "../../../stream_input/parser/streambuf.h" +#include +#include + +#include + +#define DRIVER_NAME "amvdec_h264" +#define MODULE_NAME "amvdec_h264" +#define MEM_NAME "codec_264" +#define HANDLE_H264_IRQ +/* #define DEBUG_PTS */ +#if 0 /* MESON_CPU_TYPE <= MESON_CPU_TYPE_MESON6TV */ +#define DROP_B_FRAME_FOR_1080P_50_60FPS +#endif +#define RATE_MEASURE_NUM 8 +#define RATE_CORRECTION_THRESHOLD 5 +#define RATE_24_FPS 4004 /* 23.97 */ +#define RATE_25_FPS 3840 /* 25 */ +#define DUR2PTS(x) ((x)*90/96) +#define PTS2DUR(x) ((x)*96/90) +#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) +#define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2 +#define VDEC_CLOCK_ADJUST_FRAME 50 + +static inline bool close_to(int a, int b, int m) +{ + return (abs(a - b) < m) ? true : false; +} + +static DEFINE_MUTEX(vh264_mutex); +/* 12M for L41 */ +#define MAX_DPB_BUFF_SIZE (12*1024*1024) +#define DEFAULT_MEM_SIZE (32*1024*1024) +#define AVIL_DPB_BUFF_SIZE 0x01ec2000 + +#define DEF_BUF_START_ADDR 0x1000000 +#define V_BUF_ADDR_OFFSET_NEW (0x1ee000) +#define V_BUF_ADDR_OFFSET (0x13e000) + +#define PIC_SINGLE_FRAME 0 +#define PIC_TOP_BOT_TOP 1 +#define PIC_BOT_TOP_BOT 2 +#define PIC_DOUBLE_FRAME 3 +#define PIC_TRIPLE_FRAME 4 +#define PIC_TOP_BOT 5 +#define PIC_BOT_TOP 6 +#define PIC_INVALID 7 + +#define EXTEND_SAR 0xff + +#define VF_POOL_SIZE 64 +#define VF_BUF_NUM 24 +#define PUT_INTERVAL (HZ/100) +#define NO_DISP_WD_COUNT (3 * HZ / PUT_INTERVAL) + +#define SWITCHING_STATE_OFF 0 +#define SWITCHING_STATE_ON_CMD3 1 +#define SWITCHING_STATE_ON_CMD1 2 +#define SWITCHING_STATE_ON_CMD1_PENDING 3 + + +#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001 +#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE 0x0002 +#define DEC_CONTROL_FLAG_DISABLE_FAST_POC 0x0004 + +#define INCPTR(p) ptr_atomic_wrap_inc(&p) + +#define SLICE_TYPE_I 2 +#define SLICE_TYPE_P 5 +#define SLICE_TYPE_B 6 + +struct buffer_spec_s { + unsigned int y_addr; + unsigned int u_addr; + unsigned int v_addr; + + int y_canvas_index; + int u_canvas_index; + int v_canvas_index; + + unsigned int y_canvas_width; + unsigned int u_canvas_width; + unsigned int v_canvas_width; + + unsigned int y_canvas_height; + unsigned int u_canvas_height; + unsigned int v_canvas_height; + + unsigned long phy_addr; + int alloc_count; +}; + +#define spec2canvas(x) \ + (((x)->v_canvas_index << 16) | \ + ((x)->u_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) + +static struct vframe_s *vh264_vf_peek(void *); +static struct vframe_s *vh264_vf_get(void *); +static void vh264_vf_put(struct vframe_s *, void *); +static int vh264_vf_states(struct vframe_states *states, void *); +static int vh264_event_cb(int type, void *data, void *private_data); + +static void vh264_prot_init(void); +static void vh264_local_init(void); +static void vh264_put_timer_func(unsigned long arg); +static void stream_switching_done(void); + +static const char vh264_dec_id[] = "vh264-dev"; + +#define PROVIDER_NAME "decoder.h264" + +static const struct vframe_operations_s vh264_vf_provider_ops = { + .peek = vh264_vf_peek, + .get = vh264_vf_get, + .put = vh264_vf_put, + .event_cb = vh264_event_cb, + .vf_states = vh264_vf_states, +}; + +static struct vframe_provider_s vh264_vf_prov; +/*TODO irq*/ +#if 1 +static u32 frame_buffer_size; +static u32 frame_width, frame_height, frame_dur, frame_prog, frame_packing_type, + last_duration; +static u32 saved_resolution; +static u32 last_mb_width, last_mb_height; +#else +static u32 frame_buffer_size; +static u32 frame_width, frame_height, frame_dur, frame_prog, last_duration; +static u32 last_mb_width, last_mb_height; +static u32 frame_packing_type; +#endif +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(delay_display_q, struct vframe_s *, VF_POOL_SIZE); + +static struct vframe_s vfpool[VF_POOL_SIZE]; +static s32 vfbuf_use[VF_BUF_NUM]; +static struct buffer_spec_s buffer_spec[VF_BUF_NUM]; +static struct buffer_spec_s fense_buffer_spec[2]; +#define MAX_BLK_BUFFERS (VF_BUF_NUM + 3) +#define FENSE_BUFFER_IDX(n) (VF_BUF_NUM + n) +static struct vframe_s fense_vf[2]; + +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start, buf_end; +static u32 buf_size; +static s32 buf_offset; +static u32 ucode_map_start; +static u32 pts_outside; +static u32 sync_outside; +static u32 dec_control; +static u32 vh264_ratio; +static u32 vh264_rotation; +static u32 use_idr_framerate; +static u32 high_bandwith; + +static u32 seq_info; +static u32 timing_info_present_flag; +static u32 fixed_frame_rate_flag; +static u32 fixed_frame_rate_check_count; +static u32 aspect_ratio_info; +static u32 num_units_in_tick; +static u32 time_scale; +static u32 h264_ar; +static u32 decoder_debug_flag; +static u32 dpb_size_adj = 6; + +#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS +static u32 last_interlaced; +#endif +static bool is_4k; +static unsigned char h264_first_pts_ready; +static bool h264_first_valid_pts_ready; +static u32 h264pts1, h264pts2; +static u32 h264_pts_count, duration_from_pts_done, duration_on_correcting; +static u32 vh264_error_count; +static u32 vh264_no_disp_count; +static u32 fatal_error_flag; +static u32 fatal_error_reset; +static u32 max_refer_buf = 1; +static u32 decoder_force_reset; +static unsigned int no_idr_error_count; +static unsigned int no_idr_error_max = 60; +static unsigned int enable_switch_fense = 1; +#define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k) +#if 0 +static u32 vh264_no_disp_wd_count; +#endif +static u32 vh264_running; +static s32 vh264_stream_switching_state; +static s32 vh264_eos; +static struct vframe_s *p_last_vf; +static s32 iponly_early_mode; +static void *mm_blk_handle; + +/*TODO irq*/ +#if 1 +static u32 last_pts, last_pts_remainder; +#else +static u32 last_pts; +#endif +static bool check_pts_discontinue; +static u32 wait_buffer_counter; +static u32 video_signal_from_vui; + +static uint error_recovery_mode; +static uint error_recovery_mode_in = 3; +static uint error_recovery_mode_use = 3; + +static uint mb_total = 0, mb_width = 0, mb_height; +static uint saved_idc_level; +#define UCODE_IP_ONLY 2 +#define UCODE_IP_ONLY_PARAM 1 +static uint ucode_type; + +#ifdef DEBUG_PTS +static unsigned long pts_missed, pts_hit; +#endif +static uint debugfirmware; + +static atomic_t vh264_active = ATOMIC_INIT(0); +static int vh264_reset; +static struct work_struct error_wd_work; +static struct work_struct stream_switching_work; +static struct work_struct set_parameter_work; + +static struct dec_sysinfo vh264_amstream_dec_info; +static dma_addr_t mc_dma_handle; +static void *mc_cpu_addr; +static u32 first_offset; +static u32 first_pts; +static u64 first_pts64; +static bool first_pts_cached; +static void *sei_data_buffer; +static dma_addr_t sei_data_buffer_phys; +static int clk_adj_frame_count; + +#define MC_OFFSET_HEADER 0x0000 +#define MC_OFFSET_DATA 0x1000 +#define MC_OFFSET_MMCO 0x2000 +#define MC_OFFSET_LIST 0x3000 +#define MC_OFFSET_SLICE 0x4000 + +#define MC_TOTAL_SIZE (20*SZ_1K) +#define MC_SWAP_SIZE (4*SZ_1K) + +#define MODE_ERROR 0 +#define MODE_FULL 1 + +static DEFINE_SPINLOCK(lock); +static DEFINE_SPINLOCK(prepare_lock); +static DEFINE_SPINLOCK(recycle_lock); + +static bool block_display_q; +static int vh264_stop(int mode); +static s32 vh264_init(void); + +#define DFS_HIGH_THEASHOLD 3 + +static bool pts_discontinue; + +static struct ge2d_context_s *ge2d_videoh264_context; + +static int ge2d_videoh264task_init(void) +{ + if (ge2d_videoh264_context == NULL) + ge2d_videoh264_context = create_ge2d_work_queue(); + + if (ge2d_videoh264_context == NULL) { + pr_info("create_ge2d_work_queue video task failed\n"); + return -1; + } + return 0; +} + +static int ge2d_videoh264task_release(void) +{ + if (ge2d_videoh264_context) { + destroy_ge2d_work_queue(ge2d_videoh264_context); + ge2d_videoh264_context = NULL; + } + return 0; +} + +static int ge2d_canvas_dup(struct canvas_s *srcy, struct canvas_s *srcu, + struct canvas_s *des, int format, u32 srcindex, + u32 desindex) +{ + + struct config_para_ex_s ge2d_config; + /* pr_info("[%s]h264 ADDR srcy[0x%lx] srcu[0x%lx] des[0x%lx]\n", + * __func__, srcy->addr, srcu->addr, des->addr); + */ + memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); + + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + + ge2d_config.src_planes[0].addr = srcy->addr; + ge2d_config.src_planes[0].w = srcy->width; + ge2d_config.src_planes[0].h = srcy->height; + + ge2d_config.src_planes[1].addr = srcu->addr; + ge2d_config.src_planes[1].w = srcu->width; + ge2d_config.src_planes[1].h = srcu->height; + + ge2d_config.dst_planes[0].addr = des->addr; + ge2d_config.dst_planes[0].w = des->width; + ge2d_config.dst_planes[0].h = des->height; + + ge2d_config.src_para.canvas_index = srcindex; + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.src_para.format = format; + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.top = 0; + ge2d_config.src_para.left = 0; + ge2d_config.src_para.width = srcy->width; + ge2d_config.src_para.height = srcy->height; + + ge2d_config.dst_para.canvas_index = desindex; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = format; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = srcy->width; + ge2d_config.dst_para.height = srcy->height; + + if (ge2d_context_config_ex(ge2d_videoh264_context, &ge2d_config) < 0) { + pr_info("ge2d_context_config_ex failed\n"); + return -1; + } + + stretchblt_noalpha(ge2d_videoh264_context, 0, 0, srcy->width, + srcy->height, 0, 0, srcy->width, srcy->height); + + return 0; +} + +static inline int fifo_level(void) +{ + return VF_POOL_SIZE - kfifo_len(&newframe_q); +} + + +void spec_set_canvas(struct buffer_spec_s *spec, + unsigned width, unsigned height) +{ + canvas_config(spec->y_canvas_index, + spec->y_addr, + width, height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + canvas_config(spec->u_canvas_index, + spec->u_addr, + width, height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); +} + +static void prepare_display_q(void) +{ + unsigned long flags; + int count; + + spin_lock_irqsave(&prepare_lock, flags); + + if (block_display_q) { + spin_unlock_irqrestore(&prepare_lock, flags); + return; + } + + spin_unlock_irqrestore(&prepare_lock, flags); + + count = (int)VF_POOL_SIZE - + kfifo_len(&delay_display_q) - + kfifo_len(&display_q) - + kfifo_len(&recycle_q) - + kfifo_len(&newframe_q); + + if ((vh264_stream_switching_state != SWITCHING_STATE_OFF) + || !EN_SWITCH_FENCE()) + count = 0; + else + count = (count < 2) ? 0 : 2; + + while (kfifo_len(&delay_display_q) > count) { + struct vframe_s *vf; + + if (kfifo_get(&delay_display_q, &vf)) { + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + } +} + +static struct vframe_s *vh264_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vh264_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vh264_vf_put(struct vframe_s *vf, void *op_arg) +{ + unsigned long flags; + + spin_lock_irqsave(&recycle_lock, flags); + + if ((vf != &fense_vf[0]) && (vf != &fense_vf[1])) + kfifo_put(&recycle_q, (const struct vframe_s *)vf); + + spin_unlock_irqrestore(&recycle_lock, flags); +} + +static int vh264_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vh264_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vh264_local_init(); + vh264_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vh264_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +static int vh264_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q) + + kfifo_len(&delay_display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + + return 0; +} + +#if 0 +static tvin_trans_fmt_t convert_3d_format(u32 type) +{ + const tvin_trans_fmt_t conv_tab[] = { + 0, /* checkerboard */ + 0, /* column alternation */ + TVIN_TFMT_3D_LA, /* row alternation */ + TVIN_TFMT_3D_LRH_OLER, /* side by side */ + TVIN_TFMT_3D_FA /* top bottom */ + }; + + return (type <= 4) ? conv_tab[type] : 0; +} +#endif + +static void set_frame_info(struct vframe_s *vf) +{ + vf->width = frame_width; + vf->height = frame_height; + vf->duration = frame_dur; + vf->ratio_control = + (min(h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) << + DISP_RATIO_ASPECT_RATIO_BIT; + vf->orientation = vh264_rotation; + vf->flag = 0; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS + vf->trans_fmt = 0; + if ((vf->trans_fmt == TVIN_TFMT_3D_LRF) || + (vf->trans_fmt == TVIN_TFMT_3D_LA)) { + vf->left_eye.start_x = 0; + vf->left_eye.start_y = 0; + vf->left_eye.width = frame_width / 2; + vf->left_eye.height = frame_height; + + vf->right_eye.start_x = 0; + vf->right_eye.start_y = 0; + vf->right_eye.width = frame_width / 2; + vf->right_eye.height = frame_height; + } else if ((vf->trans_fmt == TVIN_TFMT_3D_LRH_OLER) || + (vf->trans_fmt == TVIN_TFMT_3D_TB)) { + vf->left_eye.start_x = 0; + vf->left_eye.start_y = 0; + vf->left_eye.width = frame_width / 2; + vf->left_eye.height = frame_height; + + vf->right_eye.start_x = 0; + vf->right_eye.start_y = 0; + vf->right_eye.width = frame_width / 2; + vf->right_eye.height = frame_height; + } +#endif + +} + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER +static void vh264_ppmgr_reset(void) +{ + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + + vh264_local_init(); + + pr_info("vh264dec: vf_ppmgr_reset\n"); +} +#endif + +static int get_max_dpb_size(int level_idc, int mb_width, int mb_height) +{ + int size, r; + + switch (level_idc) { + case 10: + r = 1485; + break; + case 11: + r = 3375; + break; + case 12: + case 13: + case 20: + r = 8910; + break; + case 21: + r = 17820; + break; + case 22: + case 30: + r = 30375; + break; + case 31: + r = 67500; + break; + case 32: + r = 76800; + break; + case 40: + case 41: + case 42: + r = 122880; + break; + case 50: + r = 414000; + break; + case 51: + case 52: + r = 691200; + break; + default: + return 0; + } + size = (mb_width * mb_height + + (mb_width * mb_height / 2)) * 256 * 10; + r = (r * 1024 + size-1) / size; + r = min(r, 16); + /*pr_info("max_dpb %d size:%d\n", r, size);*/ + return r; +} +static void vh264_set_params(struct work_struct *work) +{ + int aspect_ratio_info_present_flag, aspect_ratio_idc; + int max_dpb_size, actual_dpb_size, max_reference_size; + int i, mb_mv_byte, start_addr; + unsigned long addr; + unsigned int post_canvas; + unsigned int frame_mbs_only_flag; + unsigned int chroma_format_idc, chroma444, video_signal; + unsigned int crop_infor, crop_bottom, crop_right, level_idc; + u32 disp_addr = 0xffffffff; + struct canvas_s cur_canvas; + + if (!atomic_read(&vh264_active)) + return; + mutex_lock(&vh264_mutex); + if (vh264_stream_switching_state == SWITCHING_STATE_ON_CMD1) + vh264_stream_switching_state = SWITCHING_STATE_ON_CMD1_PENDING; + post_canvas = get_post_canvas(); + clk_adj_frame_count = 0; + /* set to max decoder clock rate at the beginning */ + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + timing_info_present_flag = 0; + mb_width = READ_VREG(AV_SCRATCH_1); + seq_info = READ_VREG(AV_SCRATCH_2); + aspect_ratio_info = READ_VREG(AV_SCRATCH_3); + num_units_in_tick = READ_VREG(AV_SCRATCH_4); + time_scale = READ_VREG(AV_SCRATCH_5); + level_idc = READ_VREG(AV_SCRATCH_A); + if (level_idc > 0) + saved_idc_level = level_idc; + else if (saved_idc_level > 0) + level_idc = saved_idc_level; + video_signal = READ_VREG(AV_SCRATCH_H); + video_signal_from_vui = + ((video_signal & 0xffff) << 8) | + ((video_signal & 0xff0000) >> 16) | + ((video_signal & 0x3f000000)); +/* +* pr_info("video_signal_type_present_flag 0x%x\n", +* (video_signal_from_vui >> 29) & 1); +* pr_info("video_format 0x%x\n", +* (video_signal_from_vui >> 26) & 7); +* pr_info("video_full_range_flag 0x%x\n", +* (video_signal_from_vui >> 25) & 1); +* pr_info("color_description_present_flag 0x%x\n", +* (video_signal_from_vui >> 24) & 1); +* pr_info("color_primaries 0x%x\n", +* (video_signal_from_vui >> 16) & 0xff); +* pr_info("transfer_characteristic 0x%x\n", +* (video_signal_from_vui >> 8) & 0xff); +* pr_info("matrix_coefficient 0x%x\n", +* video_signal_from_vui & 0xff); +*/ + + mb_total = (mb_width >> 8) & 0xffff; + max_reference_size = (mb_width >> 24) & 0x7f; + mb_mv_byte = (mb_width & 0x80000000) ? 24 : 96; + if (ucode_type == UCODE_IP_ONLY_PARAM) + mb_mv_byte = 96; + mb_width = mb_width & 0xff; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + if (!mb_width && mb_total) + mb_width = 256; + } + mb_height = mb_total / mb_width; + last_duration = 0; + /* AV_SCRATCH_2 + * bit 15: frame_mbs_only_flag + *bit 13-14: chroma_format_idc + */ + frame_mbs_only_flag = (seq_info >> 15) & 0x01; + chroma_format_idc = (seq_info >> 13) & 0x03; + chroma444 = (chroma_format_idc == 3) ? 1 : 0; + + /* @AV_SCRATCH_6.31-16 = (left << 8 | right ) << 1 + * @AV_SCRATCH_6.15-0 = (top << 8 | bottom ) << + * (2 - frame_mbs_only_flag) + */ + crop_infor = READ_VREG(AV_SCRATCH_6); + crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag); + crop_right = ((crop_infor >> 16) & 0xff) >> (2 - frame_mbs_only_flag); + + /* if width or height from outside is not equal to mb, then use mb */ + /* add: for seeking stream with other resolution */ + if ((last_mb_width && (last_mb_width != mb_width)) + || (mb_width != ((frame_width + 15) >> 4))) + frame_width = 0; + if ((last_mb_height && (last_mb_height != mb_height)) + || (mb_height != ((frame_height + 15) >> 4))) + frame_height = 0; + last_mb_width = mb_width; + last_mb_height = mb_height; + + if ((frame_width == 0) || (frame_height == 0) || crop_infor) { + frame_width = mb_width << 4; + frame_height = mb_height << 4; + if (frame_mbs_only_flag) { + frame_height = + frame_height - (2 >> chroma444) * + min(crop_bottom, + (unsigned int)((8 << chroma444) - 1)); + frame_width = + frame_width - (2 >> chroma444) * min(crop_right, + (unsigned + int)((8 << chroma444) - 1)); + } else { + frame_height = + frame_height - (4 >> chroma444) * + min(crop_bottom, + (unsigned int)((8 << chroma444) + - 1)); + frame_width = + frame_width - (4 >> chroma444) * min(crop_right, + (unsigned + int)((8 << + chroma444) + - 1)); + } +#if 0 + pr_info + ("frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ", + frame_mbs_only_flag, crop_bottom, frame_height); + pr_info + ("mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", + mb_height, crop_right, frame_width, mb_width); +#endif + if (frame_height == 1088) + frame_height = 1080; + } + + mb_width = (mb_width + 3) & 0xfffffffc; + mb_height = (mb_height + 3) & 0xfffffffc; + mb_total = mb_width * mb_height; + + /*max_reference_size <= max_dpb_size <= actual_dpb_size*/ + is_4k = (mb_total > 8160) ? true:false; + + if (is_4k || dpb_size_adj) { + /*4k2k*/ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + max_dpb_size = get_max_dpb_size( + level_idc, mb_width, mb_height); + actual_dpb_size = max_dpb_size + 5; + if (dpb_size_adj) + actual_dpb_size + = max_reference_size + dpb_size_adj; + if (actual_dpb_size > VF_BUF_NUM) + actual_dpb_size = VF_BUF_NUM; + pr_info + ("actual_dpb_size %d max_ref_size %d\n", + actual_dpb_size, max_reference_size); + } else { + vh264_running = 0; + fatal_error_flag = + DECODER_FATAL_ERROR_SIZE_OVERFLOW; + mutex_unlock(&vh264_mutex); + pr_err("oversize ! mb_total %d,\n", mb_total); + return; + } + } else { + actual_dpb_size = (frame_buffer_size - mb_total * mb_mv_byte * + max_reference_size) / (mb_total * 384); + actual_dpb_size = min(actual_dpb_size, VF_BUF_NUM); + max_dpb_size = get_max_dpb_size(level_idc, mb_width, mb_height); + if (max_reference_size > 1) + max_dpb_size = max_reference_size - 1; + else + max_dpb_size = max_reference_size; + if (actual_dpb_size < (max_dpb_size + 4)) { + actual_dpb_size = max_dpb_size + 4; + if (actual_dpb_size > VF_BUF_NUM) + actual_dpb_size = VF_BUF_NUM; + } + pr_info("actual_dpb_size %d max_dpb_size %d\n", + actual_dpb_size, max_dpb_size); + } + if (max_dpb_size == 0) + max_dpb_size = actual_dpb_size; + else + max_dpb_size = min(max_dpb_size, actual_dpb_size); + max_reference_size = min(max_reference_size, actual_dpb_size-1); + max_dpb_size = max(max_reference_size, max_dpb_size); + max_reference_size++; + + start_addr = addr = buf_start; + if (is_4k) + addr += ((mb_total << 8) + (mb_total << 7));/*keep last frame */ + WRITE_VREG(AV_SCRATCH_1, addr); + WRITE_VREG(AV_SCRATCH_3, post_canvas); /* should be modified later */ + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + if ((addr + mb_total * mb_mv_byte * max_reference_size) + >= buf_end) { + fatal_error_flag = + DECODER_FATAL_ERROR_NO_MEM; + vh264_running = 0; + mutex_unlock(&vh264_mutex); + pr_err("mv buf not enough!\n"); + return; + } + addr += mb_total * mb_mv_byte * max_reference_size; + WRITE_VREG(AV_SCRATCH_4, addr); + if (!(READ_VREG(AV_SCRATCH_F) & 0x1)) { + bool use_alloc = is_4k ? true:false; + int alloc_count = 0; + + for (i = 0; i < actual_dpb_size; i++) { + if (((addr + (mb_total << 8) + (mb_total << 7)) + >= buf_end) && (!use_alloc)) { + pr_info("start alloc for %d\n", i); + use_alloc = true; + } + if (use_alloc) { +#ifdef DOUBLE_WRITE + int page_count = + PAGE_ALIGN((mb_total << 8) + (mb_total + << 7) + (mb_total << 6) + + (mb_total << 5)) / PAGE_SIZE; +#else + int page_count = + PAGE_ALIGN((mb_total << 8) + + (mb_total << 7)) / PAGE_SIZE; +#endif + buffer_spec[i].alloc_count = page_count; + if (!decoder_bmmu_box_alloc_idx_wait( + mm_blk_handle, + i, + page_count << PAGE_SHIFT, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR + )) { + buffer_spec[i].phy_addr = + decoder_bmmu_box_get_phy_addr( + mm_blk_handle, + i); + pr_info("CMA malloc ok %d\n", i); + alloc_count++; + } else { + buffer_spec[i].alloc_count = 0; + fatal_error_flag = + DECODER_FATAL_ERROR_NO_MEM; + vh264_running = 0; + mutex_unlock(&vh264_mutex); + pr_err("CMA not enough mem! %d\n", + i); + return; + } + addr = buffer_spec[i].phy_addr; + } else { + if (buffer_spec[i].phy_addr) { + decoder_bmmu_box_free_idx( + mm_blk_handle, + i); + buffer_spec[i].phy_addr = 0; + buffer_spec[i].alloc_count = 0; + } + } + /*4k keep last frame */ + if (is_4k && ((addr + 7) >> 3) == disp_addr) + addr = start_addr; + if (i <= 21) { + buffer_spec[i].y_addr = addr; + addr += mb_total << 8; + buffer_spec[i].u_addr = addr; + buffer_spec[i].v_addr = addr; + addr += mb_total << 7; + vfbuf_use[i] = 0; + + buffer_spec[i].y_canvas_index = 128 + i * 2; + buffer_spec[i].u_canvas_index = 128 + i * 2 + 1; + buffer_spec[i].v_canvas_index = 128 + i * 2 + 1; + + buffer_spec[i].y_canvas_width = mb_width << 4; + buffer_spec[i].y_canvas_height = mb_height << 4; + buffer_spec[i].u_canvas_width = mb_width << 4; + buffer_spec[i].u_canvas_height = mb_height << 4; + buffer_spec[i].v_canvas_width = mb_width << 4; + buffer_spec[i].v_canvas_height = mb_height << 4; + + canvas_config(128 + i * 2, + buffer_spec[i].y_addr, + mb_width << 4, mb_height << 4, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(128 + i * 2 + 1, + buffer_spec[i].u_addr, + mb_width << 4, mb_height << 3, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + WRITE_VREG(ANC0_CANVAS_ADDR + i, + spec2canvas(&buffer_spec[i])); + } else { + buffer_spec[i].y_canvas_index = + 2 * (i - 21) + 4; + buffer_spec[i].y_addr = addr; + addr += mb_total << 8; + buffer_spec[i].u_canvas_index = + 2 * (i - 21) + 5; + buffer_spec[i].v_canvas_index = + 2 * (i - 21) + 5; + buffer_spec[i].u_addr = addr; + addr += mb_total << 7; + vfbuf_use[i] = 0; + + buffer_spec[i].y_canvas_width = mb_width << 4; + buffer_spec[i].y_canvas_height = mb_height << 4; + buffer_spec[i].u_canvas_width = mb_width << 4; + buffer_spec[i].u_canvas_height = mb_height << 4; + buffer_spec[i].v_canvas_width = mb_width << 4; + buffer_spec[i].v_canvas_height = mb_height << 4; + + spec_set_canvas(&buffer_spec[i] + , mb_width << 4, mb_height << 4); + WRITE_VREG(ANC0_CANVAS_ADDR + i + , spec2canvas(&buffer_spec[i])); + } + } + } else + addr = buf_start + mb_total * 384 * actual_dpb_size; + + timing_info_present_flag = seq_info & 0x2; + fixed_frame_rate_flag = 0; + aspect_ratio_info_present_flag = seq_info & 0x1; + aspect_ratio_idc = (seq_info >> 16) & 0xff; + + if (timing_info_present_flag) { + fixed_frame_rate_flag = seq_info & 0x40; + + if (((num_units_in_tick * 120) >= time_scale + && ((!sync_outside) || (!frame_dur))) && + num_units_in_tick + && time_scale) { + if (use_idr_framerate || !frame_dur + || !duration_from_pts_done || vh264_running) { + u32 frame_dur_es = + div_u64(96000ULL * 2 * + num_units_in_tick, + time_scale); + + /* hack to avoid use ES frame duration + * when it's half of the rate from + * system info + */ + /* sometimes the encoder is given a wrong + * frame rate but the system side information + *is more reliable + */ + if ((frame_dur * 2) != frame_dur_es) + frame_dur = frame_dur_es; + } + } + } else + pr_info("H.264: timing_info not present\n"); + + if (aspect_ratio_info_present_flag) { + if (aspect_ratio_idc == EXTEND_SAR) { + h264_ar = + div_u64(256ULL * (aspect_ratio_info >> 16) * + frame_height, + (aspect_ratio_info & 0xffff) * + frame_width); + } else { + /* pr_info("v264dec: aspect_ratio_idc = %d\n", + * aspect_ratio_idc); + */ + + switch (aspect_ratio_idc) { + case 1: + h264_ar = 0x100 * frame_height / frame_width; + break; + case 2: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 12); + break; + case 3: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 10); + break; + case 4: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 16); + break; + case 5: + h264_ar = 0x100 * frame_height * 33 / + (frame_width * 40); + break; + case 6: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 24); + break; + case 7: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 20); + break; + case 8: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 32); + break; + case 9: + h264_ar = 0x100 * frame_height * 33 / + (frame_width * 80); + break; + case 10: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 18); + break; + case 11: + h264_ar = 0x100 * frame_height * 11 / + (frame_width * 15); + break; + case 12: + h264_ar = 0x100 * frame_height * 33 / + (frame_width * 64); + break; + case 13: + h264_ar = 0x100 * frame_height * 99 / + (frame_width * 160); + break; + case 14: + h264_ar = 0x100 * frame_height * 3 / + (frame_width * 4); + break; + case 15: + h264_ar = 0x100 * frame_height * 2 / + (frame_width * 3); + break; + case 16: + h264_ar = 0x100 * frame_height * 1 / + (frame_width * 2); + break; + default: + if (vh264_ratio >> 16) { + h264_ar = (frame_height * + (vh264_ratio & 0xffff) * + 0x100 + + ((vh264_ratio >> 16) * + frame_width / 2)) / + ((vh264_ratio >> 16) * + frame_width); + } else { + h264_ar = frame_height * 0x100 / + frame_width; + } + break; + } + } + } else { + pr_info("v264dec: aspect_ratio not available from source\n"); + if (vh264_ratio >> 16) { + /* high 16 bit is width, low 16 bit is height */ + h264_ar = + ((vh264_ratio & 0xffff) * frame_height * 0x100 + + (vh264_ratio >> 16) * frame_width / 2) / + ((vh264_ratio >> 16) * frame_width); + } else + h264_ar = frame_height * 0x100 / frame_width; + } + + WRITE_VREG(AV_SCRATCH_0, + (max_reference_size << 24) | (actual_dpb_size << 16) | + (max_dpb_size << 8)); + if (vh264_stream_switching_state != SWITCHING_STATE_OFF) { + vh264_stream_switching_state = SWITCHING_STATE_OFF; + pr_info("Leaving switching mode.\n"); + } + mutex_unlock(&vh264_mutex); +} + +static unsigned pts_inc_by_duration(unsigned *new_pts, unsigned *new_pts_rem) +{ + unsigned r, rem; + + r = last_pts + DUR2PTS(frame_dur); + rem = last_pts_remainder + DUR2PTS_REM(frame_dur); + + if (rem >= 96) { + r++; + rem -= 96; + } + + if (new_pts) + *new_pts = r; + if (new_pts_rem) + *new_pts_rem = rem; + + return r; +} +static inline bool vh264_isr_parser(struct vframe_s *vf, + unsigned int pts_valid, unsigned int buffer_index, + unsigned int pts) +{ + unsigned int pts_duration = 0; + + if (h264_first_pts_ready == 0) { + if (pts_valid == 0) { + vfbuf_use[buffer_index]++; + vf->index = buffer_index; + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + return false; + } + + h264pts1 = pts; + h264_pts_count = 0; + h264_first_pts_ready = 1; + } else { + if (pts < h264pts1) { + if (h264_pts_count > 24) { + pr_info("invalid h264pts1, reset\n"); + h264pts1 = pts; + h264_pts_count = 0; + } + } + if (pts_valid && (pts > h264pts1) && (h264_pts_count > 24) + && (duration_from_pts_done == 0)) { + unsigned int + old_duration = frame_dur; + h264pts2 = pts; + + pts_duration = (h264pts2 - h264pts1) * 16 / + (h264_pts_count * 15); + + if ((pts_duration != frame_dur) + && (!pts_outside)) { + if (use_idr_framerate) { + bool pts_c_24 = close_to(pts_duration, + RATE_24_FPS, + RATE_CORRECTION_THRESHOLD); + bool frm_c_25 = close_to(frame_dur, + RATE_25_FPS, + RATE_CORRECTION_THRESHOLD); + bool pts_c_25 = close_to(pts_duration, + RATE_25_FPS, + RATE_CORRECTION_THRESHOLD); + bool frm_c_24 = close_to(frame_dur, + RATE_24_FPS, + RATE_CORRECTION_THRESHOLD); + if ((pts_c_24 && frm_c_25) + || (pts_c_25 && frm_c_24)) { + pr_info + ("H.264:Correct frame dur "); + pr_info + (" from %d to duration based ", + frame_dur); + pr_info + ("on PTS %d ---\n", + pts_duration); + frame_dur = pts_duration; + duration_from_pts_done = 1; + } else if (((frame_dur < 96000 / 240) + && (pts_duration > 96000 / 240)) + || (!duration_on_correcting && + !frm_c_25 && !frm_c_24)) { + /* fft: if the frame rate is + * not regular, use the + * calculate rate insteadof. + */ + pr_info + ("H.264:Correct frame dur "); + pr_info + (" from %d to duration based ", + frame_dur); + pr_info + ("on PTS %d ---\n", + pts_duration); + frame_dur = pts_duration; + duration_on_correcting = 1; + } + } else { + if (close_to(pts_duration, + frame_dur, 2000)) { + frame_dur = pts_duration; + pr_info + ("used calculate frame rate,"); + pr_info("on duration =%d\n", + frame_dur); + } else { + pr_info + ("don't use calculate frame "); + pr_info + ("rate pts_duration =%d\n", + pts_duration); + } + } + } + + if (duration_from_pts_done == 0) { + if (close_to + (pts_duration, + old_duration, + RATE_CORRECTION_THRESHOLD)) { + pr_info + ("finished correct frame dur"); + pr_info + (" new=%d,old_duration=%d,cnt=%d\n", + pts_duration, + old_duration, + h264_pts_count); + duration_from_pts_done = 1; + } else { /*not the same,redo it. */ + if (!close_to(pts_duration, + old_duration, 1000) && + !close_to(pts_duration, + frame_dur, 1000) && + close_to(pts_duration, + last_duration, 200)) { + /* yangle: frame_dur must + * wrong,recover it. + */ + frame_dur = pts_duration; + } + + pr_info + ("restart correct frame duration "); + pr_info + ("new=%d,old_duration=%d,cnt=%d\n", + pts_duration, + old_duration, + h264_pts_count); + h264pts1 = h264pts2; + h264_pts_count = 0; + duration_from_pts_done = 0; + } + } + last_duration = pts_duration; + } + } + return true; +} +#ifdef HANDLE_H264_IRQ +static irqreturn_t vh264_isr(int irq, void *dev_id) +#else +static void vh264_isr(void) +#endif +{ + unsigned int buffer_index; + struct vframe_s *vf; + unsigned int cpu_cmd; + unsigned int pts, pts_lookup_save, pts_valid_save, pts_valid = 0; + unsigned int pts_us64_valid = 0; + u64 pts_us64; + bool force_interlaced_frame = false; + unsigned int sei_itu35_flags; + static const unsigned int idr_num = + FIX_FRAME_RATE_CHECK_IDRFRAME_NUM; + static const unsigned int flg_1080_itl = + DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE; + static const unsigned int flg_576_itl = + DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE; + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + if (0 == (stat & STAT_VDEC_RUN)) { + pr_info("decoder is not running\n"); +#ifdef HANDLE_H264_IRQ + return IRQ_HANDLED; +#else + return; +#endif + } + + cpu_cmd = READ_VREG(AV_SCRATCH_0); + +#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS + if ((frame_dur < 2004) && + (frame_width >= 1400) && + (frame_height >= 1000) && (last_interlaced == 0)) + SET_VREG_MASK(AV_SCRATCH_F, 0x8); +#endif + if ((decoder_force_reset == 1) + || ((error_recovery_mode != 1) + && (no_idr_error_count >= no_idr_error_max) + && (ucode_type != UCODE_IP_ONLY_PARAM))) { + vh264_running = 0; + pr_info("force reset decoder %d!!!\n", no_idr_error_count); + schedule_work(&error_wd_work); + decoder_force_reset = 0; + no_idr_error_count = 0; + } else if ((cpu_cmd & 0xff) == 1) { + if (unlikely + (vh264_running + && (kfifo_len(&newframe_q) != VF_POOL_SIZE))) { + /* a cmd 1 sent during decoding w/o getting a cmd 3. */ + /* should not happen but the original code has such + * case, do the same process + */ + if ((READ_VREG(AV_SCRATCH_1) & 0xff) + == 1) {/*invalid mb_width*/ + vh264_running = 0; + fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN; + /* this is fatal error, need restart */ + pr_info("cmd 1 fatal error happened\n"); + schedule_work(&error_wd_work); + } else { + vh264_stream_switching_state = SWITCHING_STATE_ON_CMD1; + pr_info("Enter switching mode cmd1.\n"); + schedule_work(&stream_switching_work); + } + return IRQ_HANDLED; + } + pr_info("Enter set parameter cmd1.\n"); + schedule_work(&set_parameter_work); + return IRQ_HANDLED; + } else if ((cpu_cmd & 0xff) == 2) { + int frame_mb_only, pic_struct_present, pic_struct, prog_frame, + poc_sel, idr_flag, eos, error; + int i, status, num_frame, b_offset; + int current_error_count, slice_type; + + vh264_running = 1; + vh264_no_disp_count = 0; + num_frame = (cpu_cmd >> 8) & 0xff; + frame_mb_only = seq_info & 0x8000; + pic_struct_present = seq_info & 0x10; + + current_error_count = READ_VREG(AV_SCRATCH_D); + if (vh264_error_count != current_error_count) { + /* pr_info("decoder error happened, count %d\n", + * current_error_count); + */ + vh264_error_count = current_error_count; + } + + for (i = 0; (i < num_frame) && (!vh264_eos); i++) { + status = READ_VREG(AV_SCRATCH_1 + i); + buffer_index = status & 0x1f; + error = status & 0x200; + slice_type = (READ_VREG(AV_SCRATCH_H) >> (i * 4)) & 0xf; + + if ((error_recovery_mode_use & 2) && error) + check_pts_discontinue = true; + if (ucode_type == UCODE_IP_ONLY_PARAM + && iponly_early_mode) + continue; + if ((p_last_vf != NULL) + && (p_last_vf->index == buffer_index)) + continue; + + if (buffer_index >= VF_BUF_NUM) + continue; + + pic_struct = (status >> 5) & 0x7; + prog_frame = status & 0x100; + poc_sel = status & 0x200; + idr_flag = status & 0x400; + frame_packing_type = (status >> 12) & 0x7; + eos = (status >> 15) & 1; + + if (eos) + vh264_eos = 1; + + b_offset = (status >> 16) & 0xffff; + + if (error) + no_idr_error_count++; + if (idr_flag || + (!error && (slice_type != SLICE_TYPE_I))) + no_idr_error_count = 0; + + if (decoder_debug_flag) { + pr_info + ("slice_type %x idr %x error %x count %d", + slice_type, idr_flag, error, + no_idr_error_count); + pr_info(" prog %x pic_struct %x offset %x\n", + prog_frame, pic_struct, b_offset); + } +#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS + last_interlaced = prog_frame ? 0 : 1; +#endif + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) + clk_adj_frame_count++; + + set_frame_info(vf); + + switch (i) { + case 0: + b_offset |= + (READ_VREG(AV_SCRATCH_A) & 0xffff) + << 16; + break; + case 1: + b_offset |= + READ_VREG(AV_SCRATCH_A) & 0xffff0000; + break; + case 2: + b_offset |= + (READ_VREG(AV_SCRATCH_B) & 0xffff) + << 16; + break; + case 3: + b_offset |= + READ_VREG(AV_SCRATCH_B) & 0xffff0000; + break; + case 4: + b_offset |= + (READ_VREG(AV_SCRATCH_C) & 0xffff) + << 16; + break; + case 5: + b_offset |= + READ_VREG(AV_SCRATCH_C) & 0xffff0000; + break; + default: + break; + } + + /* add 64bit pts us ; */ + if (unlikely + ((b_offset == first_offset) + && (first_pts_cached))) { + pts = first_pts; + pts_us64 = first_pts64; + first_pts_cached = false; + pts_valid = 1; + pts_us64_valid = 1; +#ifdef DEBUG_PTS + pts_hit++; +#endif + } else if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, b_offset, &pts, 0, + &pts_us64) == 0) { + pts_valid = 1; + pts_us64_valid = 1; +#ifdef DEBUG_PTS + pts_hit++; +#endif + } else { + pts_valid = 0; + pts_us64_valid = 0; +#ifdef DEBUG_PTS + pts_missed++; +#endif + } + + /* on second IDR frame,check the diff between pts + * compute from duration and pts from lookup , + * if large than frame_dur,we think it is uncorrect. + */ + pts_lookup_save = pts; + pts_valid_save = pts_valid; + if (fixed_frame_rate_flag + && (fixed_frame_rate_check_count <= + idr_num)) { + if (idr_flag && pts_valid) { + fixed_frame_rate_check_count++; + /* pr_info("diff:%d\n", + * last_pts - pts_lookup_save); + */ + if ((fixed_frame_rate_check_count == + idr_num) && + (abs(pts - (last_pts + + DUR2PTS(frame_dur))) > + DUR2PTS(frame_dur))) { + fixed_frame_rate_flag = 0; + pr_info("pts sync mode play\n"); + } + + if (fixed_frame_rate_flag + && (fixed_frame_rate_check_count + > idr_num)) { + pr_info + ("fix_frame_rate mode play\n"); + } + } + } + + if (READ_VREG(AV_SCRATCH_F) & 2) { + /* for I only mode, ignore the PTS information + * and only uses frame duration for each I + * frame decoded + */ + if (p_last_vf) + pts_valid = 0; + /* also skip frame duration calculation + * based on PTS + */ + duration_from_pts_done = 1; + /* and add a default duration for 1/30 second + * if there is no valid frame + * duration available + */ + if (frame_dur == 0) + frame_dur = 96000 / 30; + } + + if (sync_outside == 0) { + if (!vh264_isr_parser(vf, + pts_valid, buffer_index, pts)) + continue; + + h264_pts_count++; + } else { + if (!idr_flag) + pts_valid = 0; + } + + if (pts_valid && !pts_discontinue) { + pts_discontinue = + (abs(last_pts - pts) >= + tsync_vpts_discontinuity_margin()); + } + /* if use_idr_framerate or fixed frame rate, only + * use PTS for IDR frames except for pts discontinue + */ + if (timing_info_present_flag && + frame_dur && + (use_idr_framerate || + (fixed_frame_rate_flag != 0)) + && pts_valid && h264_first_valid_pts_ready + && (!pts_discontinue)) { + pts_valid = + (slice_type == SLICE_TYPE_I) ? 1 : 0; + } + + if (!h264_first_valid_pts_ready && pts_valid) { + h264_first_valid_pts_ready = true; + last_pts = pts - DUR2PTS(frame_dur); + last_pts_remainder = 0; + } + /* calculate PTS of next frame and smooth + * PTS for fixed rate source + */ + if (pts_valid) { + if ((fixed_frame_rate_flag) && + (!pts_discontinue) && + (abs(pts_inc_by_duration(NULL, NULL) + - pts) + < DUR2PTS(frame_dur))) { + pts = pts_inc_by_duration(&pts, + &last_pts_remainder); + } else + last_pts_remainder = 0; + + } else { + if (fixed_frame_rate_flag && !pts_discontinue && + (fixed_frame_rate_check_count > idr_num) && + pts_valid_save && (sync_outside == 0) && + (abs(pts_inc_by_duration(NULL, NULL) - pts) + > DUR2PTS(frame_dur))) { + duration_from_pts_done = 0; + pr_info("recalc frame_dur\n"); + } else + pts = pts_inc_by_duration(&pts, + &last_pts_remainder); + pts_valid = 1; + } + + if ((dec_control & + flg_1080_itl) + && (frame_width == 1920) + && (frame_height >= 1080) + && (vf->duration == 3203)) + force_interlaced_frame = true; + else if ((dec_control & + flg_576_itl) + && (frame_width == 720) + && (frame_height == 576) + && (vf->duration == 3840)) + force_interlaced_frame = true; + + /* for frames with PTS, check if there is PTS + * discontinue based on previous frames + * (including error frames), + * force no VPTS discontinue reporting if we saw + *errors earlier but only once. + */ + if ((pts_valid) && (check_pts_discontinue) + && (!error)) { + if (pts_discontinue) { + vf->flag = 0; + check_pts_discontinue = false; + } else if ((pts - last_pts) < 90000) { + vf->flag = VFRAME_FLAG_NO_DISCONTINUE; + check_pts_discontinue = false; + } + } + + last_pts = pts; + + if (fixed_frame_rate_flag + && (fixed_frame_rate_check_count <= + idr_num) + && (sync_outside == 0) + && pts_valid_save) + pts = pts_lookup_save; + + if (pic_struct_present) { + if ((pic_struct == PIC_TOP_BOT) + || (pic_struct == PIC_BOT_TOP)) + prog_frame = 0; + } + + if ((!force_interlaced_frame) + && (prog_frame + || (pic_struct_present + && pic_struct + <= PIC_TRIPLE_FRAME))) { + if (pic_struct_present) { + if (pic_struct == PIC_TOP_BOT_TOP + || pic_struct + == PIC_BOT_TOP_BOT) { + vf->duration += + vf->duration >> 1; + } else if (pic_struct == + PIC_DOUBLE_FRAME) + vf->duration += vf->duration; + else if (pic_struct == + PIC_TRIPLE_FRAME) { + vf->duration += + vf->duration << 1; + } + } + + last_pts = + last_pts + DUR2PTS(vf->duration - + frame_dur); + + vf->index = buffer_index; + vf->type = + VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; + vf->duration_pulldown = 0; + vf->signal_type = video_signal_from_vui; + vf->index = buffer_index; + vf->pts = (pts_valid) ? pts : 0; + if (pts_us64_valid == 1) + vf->pts_us64 = pts_us64; + else + vf->pts_us64 = div64_u64(((u64)vf->pts)*100, 9); + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&buffer_spec[buffer_index]); + vf->type_original = vf->type; + vfbuf_use[buffer_index]++; + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + buffer_index); + if ((error_recovery_mode_use & 2) && error) { + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + } else { + p_last_vf = vf; + pts_discontinue = false; + kfifo_put(&delay_display_q, + (const struct vframe_s *)vf); + } + } else { + if (pic_struct_present + && pic_struct == PIC_TOP_BOT) + vf->type = VIDTYPE_INTERLACE_TOP; + else if (pic_struct_present + && pic_struct == PIC_BOT_TOP) + vf->type = VIDTYPE_INTERLACE_BOTTOM; + else { + vf->type = + poc_sel ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; + } + vf->type |= VIDTYPE_VIU_NV21; + vf->type |= VIDTYPE_INTERLACE_FIRST; + + high_bandwith |= + ((codec_mm_get_total_size() < 80 * SZ_1M) + & ((READ_VREG(AV_SCRATCH_N) & 0xf) == 3) + & ((frame_width * frame_height) >= 1920*1080)); + if (high_bandwith) + vf->flag |= VFRAME_FLAG_HIGH_BANDWIDTH; + + vf->duration >>= 1; + vf->duration_pulldown = 0; + vf->signal_type = video_signal_from_vui; + vf->index = buffer_index; + vf->pts = (pts_valid) ? pts : 0; + if (pts_us64_valid == 1) + vf->pts_us64 = pts_us64; + else + vf->pts_us64 = div64_u64(((u64)vf->pts)*100, 9); + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&buffer_spec[buffer_index]); + vf->type_original = vf->type; + vfbuf_use[buffer_index]++; + vf->ready_jiffies64 = jiffies_64; + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + buffer_index); + if ((error_recovery_mode_use & 2) && error) { + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + continue; + } else { + pts_discontinue = false; + kfifo_put(&delay_display_q, + (const struct vframe_s *)vf); + } + + if (READ_VREG(AV_SCRATCH_F) & 2) + continue; + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no avail buffer slot."); + return IRQ_HANDLED; + } + + set_frame_info(vf); + + if (pic_struct_present + && pic_struct == PIC_TOP_BOT) + vf->type = VIDTYPE_INTERLACE_BOTTOM; + else if (pic_struct_present + && pic_struct == PIC_BOT_TOP) + vf->type = VIDTYPE_INTERLACE_TOP; + else { + vf->type = + poc_sel ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; + } + + vf->type |= VIDTYPE_VIU_NV21; + vf->duration >>= 1; + vf->duration_pulldown = 0; + vf->signal_type = video_signal_from_vui; + vf->index = buffer_index; + vf->pts = 0; + vf->pts_us64 = 0; + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&buffer_spec[buffer_index]); + vf->type_original = vf->type; + vfbuf_use[buffer_index]++; + if (high_bandwith) + vf->flag |= VFRAME_FLAG_HIGH_BANDWIDTH; + + p_last_vf = vf; + vf->ready_jiffies64 = jiffies_64; + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + buffer_index); + kfifo_put(&delay_display_q, + (const struct vframe_s *)vf); + } + } + + WRITE_VREG(AV_SCRATCH_0, 0); + } else if ((cpu_cmd & 0xff) == 3) { + vh264_running = 1; + vh264_stream_switching_state = SWITCHING_STATE_ON_CMD3; + + pr_info("Enter switching mode cmd3.\n"); + schedule_work(&stream_switching_work); + + } else if ((cpu_cmd & 0xff) == 4) { + vh264_running = 1; + /* reserved for slice group */ + WRITE_VREG(AV_SCRATCH_0, 0); + } else if ((cpu_cmd & 0xff) == 5) { + vh264_running = 1; + /* reserved for slice group */ + WRITE_VREG(AV_SCRATCH_0, 0); + } else if ((cpu_cmd & 0xff) == 6) { + vh264_running = 0; + fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN; + /* this is fatal error, need restart */ + pr_info("fatal error happened\n"); + if (!fatal_error_reset) + schedule_work(&error_wd_work); + } else if ((cpu_cmd & 0xff) == 7) { + vh264_running = 0; + frame_width = (READ_VREG(AV_SCRATCH_1) + 1) * 16; + pr_info("Over decoder supported size, width = %d\n", + frame_width); + fatal_error_flag = DECODER_FATAL_ERROR_SIZE_OVERFLOW; + } else if ((cpu_cmd & 0xff) == 8) { + vh264_running = 0; + frame_height = (READ_VREG(AV_SCRATCH_1) + 1) * 16; + pr_info("Over decoder supported size, height = %d\n", + frame_height); + fatal_error_flag = DECODER_FATAL_ERROR_SIZE_OVERFLOW; + } else if ((cpu_cmd & 0xff) == 9) { + first_offset = READ_VREG(AV_SCRATCH_1); + if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, first_offset, &first_pts, 0, + &first_pts64) == 0) + first_pts_cached = true; + WRITE_VREG(AV_SCRATCH_0, 0); + + } else if ((cpu_cmd & 0xff) == 0xa) { + int b_offset = READ_VREG(AV_SCRATCH_2); + buffer_index = READ_VREG(AV_SCRATCH_1); + /*pr_info("iponly output %d b_offset %x\n", + buffer_index,b_offset);*/ + if (kfifo_get(&newframe_q, &vf) == 0) { + WRITE_VREG(AV_SCRATCH_0, 0); + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, b_offset, + &pts, 0, &pts_us64) != 0) + vf->pts_us64 = vf->pts = 0; + else { + vf->pts_us64 = pts_us64; + vf->pts = pts; + } + + set_frame_info(vf); + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; + vf->duration_pulldown = 0; + vf->signal_type = video_signal_from_vui; + vf->index = buffer_index; + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&buffer_spec[buffer_index]); + vf->type_original = vf->type; + vf->mem_handle = decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + buffer_index); + vfbuf_use[buffer_index]++; + p_last_vf = vf; + pts_discontinue = false; + iponly_early_mode = 1; + kfifo_put(&delay_display_q, + (const struct vframe_s *)vf); + WRITE_VREG(AV_SCRATCH_0, 0); + } + + sei_itu35_flags = READ_VREG(AV_SCRATCH_J); + if (sei_itu35_flags & (1 << 15)) { /* data ready */ + /* int ltemp; */ + /* unsigned char *daddr; */ + unsigned int sei_itu35_wp = (sei_itu35_flags >> 16) & 0xffff; + unsigned int sei_itu35_data_length = sei_itu35_flags & 0x7fff; + struct userdata_poc_info_t user_data_poc; + +#if 0 + /* dump lmem for debug */ + WRITE_VREG(0x301, 0x8000); + WRITE_VREG(0x31d, 0x2); + for (ltemp = 0; ltemp < 64; ltemp++) { + laddr = 0x20 + ltemp; + WRITE_VREG(0x31b, laddr); + pr_info("mem 0x%x data 0x%x\n", laddr, + READ_VREG(0x31c) & 0xffff); + } +#endif +#if 0 + for (ltemp = 0; ltemp < sei_itu35_wp; ltemp++) { + daddr = + (unsigned char *)phys_to_virt( + sei_data_buffer_phys + + ltemp); + /* daddr = (unsigned char *)(sei_data_buffer + + * ltemp); + */ + pr_info("0x%x\n", *daddr); + } +#endif + /* pr_info("pocinfo 0x%x, top poc %d, wp 0x%x, length %d\n", + * READ_VREG(AV_SCRATCH_L), READ_VREG(AV_SCRATCH_M), + * sei_itu35_wp, sei_itu35_data_length); + */ + user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L); + user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M); + set_userdata_poc(user_data_poc); + WRITE_VREG(AV_SCRATCH_J, 0); + wakeup_userdata_poll(sei_itu35_wp, + (unsigned long)sei_data_buffer, + USER_DATA_SIZE, sei_itu35_data_length); + } +#ifdef HANDLE_H264_IRQ + return IRQ_HANDLED; +#else + return; +#endif +} + +static void vh264_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + unsigned int wait_buffer_status; + unsigned int wait_i_pass_frames; + unsigned int reg_val; + + enum receviver_start_e state = RECEIVER_INACTIVE; + + if (vh264_reset) { + pr_info("operation forbidden in timer !\n"); + goto exit; + } + + prepare_display_q(); + + if (vf_get_receiver(PROVIDER_NAME)) { + state = + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + if ((state == RECEIVER_STATE_NULL) + || (state == RECEIVER_STATE_NONE)) { + /* receiver has no event_cb or receiver's + * event_cb does not process this event + */ + state = RECEIVER_INACTIVE; + } + } else + state = RECEIVER_INACTIVE; +#ifndef HANDLE_H264_IRQ + vh264_isr(); +#endif + + if (vh264_stream_switching_state != SWITCHING_STATE_OFF) + wait_buffer_counter = 0; + else { + reg_val = READ_VREG(AV_SCRATCH_9); + wait_buffer_status = reg_val & (1 << 31); + wait_i_pass_frames = reg_val & 0xff; + if (wait_buffer_status) { + if (kfifo_is_empty(&display_q) && + kfifo_is_empty(&delay_display_q) && + kfifo_is_empty(&recycle_q) && + (state == RECEIVER_INACTIVE)) { + pr_info("$$$$decoder is waiting for buffer\n"); + if (++wait_buffer_counter > 4) { + amvdec_stop(); + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vh264_ppmgr_reset(); +#else + vf_light_unreg_provider(&vh264_vf_prov); + vh264_local_init(); + vf_reg_provider(&vh264_vf_prov); +#endif + vh264_prot_init(); + amvdec_start(); + } + } else + wait_buffer_counter = 0; + } else if (wait_i_pass_frames > 1000) { + pr_info("i passed frames > 1000\n"); + amvdec_stop(); +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vh264_ppmgr_reset(); +#else + vf_light_unreg_provider(&vh264_vf_prov); + vh264_local_init(); + vf_reg_provider(&vh264_vf_prov); +#endif + vh264_prot_init(); + amvdec_start(); + } + } + +#if 0 + if (!wait_buffer_status) { + if (vh264_no_disp_count++ > NO_DISP_WD_COUNT) { + pr_info("$$$decoder did not send frame out\n"); + amvdec_stop(); +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vh264_ppmgr_reset(); +#else + vf_light_unreg_provider(PROVIDER_NAME); + vh264_local_init(); + vf_reg_provider(vh264_vf_prov); +#endif + vh264_prot_init(); + amvdec_start(); + + vh264_no_disp_count = 0; + vh264_no_disp_wd_count++; + } + } +#endif + + while (!kfifo_is_empty(&recycle_q) && + ((READ_VREG(AV_SCRATCH_7) == 0) + || (READ_VREG(AV_SCRATCH_8) == 0)) + && (vh264_stream_switching_state == SWITCHING_STATE_OFF)) { + struct vframe_s *vf; + + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index >= 0) && (vf->index < VF_BUF_NUM)) { + if (--vfbuf_use[vf->index] == 0) { + if (READ_VREG(AV_SCRATCH_7) == 0) { + WRITE_VREG(AV_SCRATCH_7, + vf->index + 1); + } else { + WRITE_VREG(AV_SCRATCH_8, + vf->index + 1); + } + } + + vf->index = VF_BUF_NUM; + kfifo_put(&newframe_q, + (const struct vframe_s *)vf); + } + } + } + + if (vh264_stream_switching_state != SWITCHING_STATE_OFF) { + while (!kfifo_is_empty(&recycle_q)) { + struct vframe_s *vf; + + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index >= 0 && + (vf->index < VF_BUF_NUM))) { + vf->index = VF_BUF_NUM; + kfifo_put(&newframe_q, + (const struct vframe_s *)vf); + } + } + } + + WRITE_VREG(AV_SCRATCH_7, 0); + WRITE_VREG(AV_SCRATCH_8, 0); + + if (kfifo_len(&newframe_q) == VF_POOL_SIZE) + stream_switching_done(); + } + + if (ucode_type != UCODE_IP_ONLY_PARAM && + (clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) && + frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + + if (frame_dur < 10) /*dur is too small ,think it errors fps*/ + fps = 60; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_H264, + frame_width, frame_height, fps); + } +exit: + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vh264_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = frame_width; + vstatus->height = frame_height; + if (frame_dur != 0) + vstatus->fps = 96000 / frame_dur; + else + vstatus->fps = -1; + vstatus->error_count = READ_VREG(AV_SCRATCH_D); + vstatus->status = stat; + if (fatal_error_reset) + vstatus->status |= fatal_error_flag; + return 0; +} + +int vh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) +{ + if (trickmode == TRICKMODE_I) { + WRITE_VREG(AV_SCRATCH_F, + (READ_VREG(AV_SCRATCH_F) & 0xfffffffc) | 2); + trickmode_i = 1; + } else if (trickmode == TRICKMODE_NONE) { + WRITE_VREG(AV_SCRATCH_F, READ_VREG(AV_SCRATCH_F) & 0xfffffffc); + trickmode_i = 0; + } + + return 0; +} + +static void vh264_prot_init(void) +{ + + while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) + ; + while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) + ; /* reg address is 0x350 */ + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + +#else + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + READ_MPEG_REG(RESET0_REGISTER); + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); +#endif + + WRITE_VREG(POWER_CTL_VLD, + READ_VREG(POWER_CTL_VLD) | + (0 << 10) | (1 << 9) | (1 << 6)); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(AV_SCRATCH_0, 0); + WRITE_VREG(AV_SCRATCH_1, buf_offset); + WRITE_VREG(AV_SCRATCH_G, mc_dma_handle); + WRITE_VREG(AV_SCRATCH_7, 0); + WRITE_VREG(AV_SCRATCH_8, 0); + WRITE_VREG(AV_SCRATCH_9, 0); + WRITE_VREG(AV_SCRATCH_N, 0); + + error_recovery_mode_use = + (error_recovery_mode != + 0) ? error_recovery_mode : error_recovery_mode_in; + WRITE_VREG(AV_SCRATCH_F, + (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) | + (READ_VREG(AV_SCRATCH_F) & 0xffffff43) | + ((error_recovery_mode_use & 0x1) << 4)); + if (dec_control & DEC_CONTROL_FLAG_DISABLE_FAST_POC) + SET_VREG_MASK(AV_SCRATCH_F, 1 << 7); + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); + if (ucode_type == UCODE_IP_ONLY_PARAM) + SET_VREG_MASK(AV_SCRATCH_F, 1 << 6); + else + CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6); + + WRITE_VREG(AV_SCRATCH_I, (u32)(sei_data_buffer_phys - buf_offset)); + WRITE_VREG(AV_SCRATCH_J, 0); + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { + /* pr_info("vh264 meson8 prot init\n"); */ + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); + } + /* #endif */ +} + +static void vh264_local_init(void) +{ + int i; + + vh264_ratio = vh264_amstream_dec_info.ratio; + /* vh264_ratio = 0x100; */ + + vh264_rotation = (((unsigned long) vh264_amstream_dec_info.param) + >> 16) & 0xffff; + + frame_buffer_size = AVIL_DPB_BUFF_SIZE + buf_size - DEFAULT_MEM_SIZE; + frame_prog = 0; + frame_width = vh264_amstream_dec_info.width; + frame_height = vh264_amstream_dec_info.height; + frame_dur = vh264_amstream_dec_info.rate; + pts_outside = ((unsigned long) vh264_amstream_dec_info.param) & 0x01; + sync_outside = ((unsigned long) vh264_amstream_dec_info.param & 0x02) + >> 1; + use_idr_framerate = ((unsigned long) vh264_amstream_dec_info.param + & 0x04) >> 2; + max_refer_buf = !(((unsigned long) vh264_amstream_dec_info.param + & 0x10) >> 4); + if (!mm_blk_handle) + mm_blk_handle = decoder_bmmu_box_alloc_box( + DRIVER_NAME, + 0, + MAX_BLK_BUFFERS, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + + pr_info + ("H264 sysinfo: %dx%d duration=%d, pts_outside=%d, ", + frame_width, frame_height, frame_dur, pts_outside); + pr_debug("sync_outside=%d, use_idr_framerate=%d\n", + sync_outside, use_idr_framerate); + + if ((unsigned long) vh264_amstream_dec_info.param & 0x08) + ucode_type = UCODE_IP_ONLY_PARAM; + else + ucode_type = 0; + + if ((unsigned long) vh264_amstream_dec_info.param & 0x20) + error_recovery_mode_in = 1; + else + error_recovery_mode_in = 3; + + if (!vh264_running) { + last_mb_width = 0; + last_mb_height = 0; + } + + for (i = 0; i < VF_BUF_NUM; i++) + vfbuf_use[i] = 0; + + INIT_KFIFO(display_q); + INIT_KFIFO(delay_display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &vfpool[i]; + + vfpool[i].index = VF_BUF_NUM; + vfpool[i].bufWidth = 1920; + kfifo_put(&newframe_q, vf); + } + +#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS + last_interlaced = 1; +#endif + h264_first_pts_ready = 0; + h264_first_valid_pts_ready = false; + h264pts1 = 0; + h264pts2 = 0; + h264_pts_count = 0; + duration_from_pts_done = 0; + vh264_error_count = READ_VREG(AV_SCRATCH_D); + + p_last_vf = NULL; + check_pts_discontinue = false; + last_pts = 0; + wait_buffer_counter = 0; + vh264_no_disp_count = 0; + fatal_error_flag = 0; + high_bandwith = 0; + vh264_stream_switching_state = SWITCHING_STATE_OFF; +#ifdef DEBUG_PTS + pts_missed = 0; + pts_hit = 0; +#endif + pts_discontinue = false; + no_idr_error_count = 0; +} + +static s32 vh264_init(void) +{ + int trickmode_fffb = 0; + int firmwareloaded = 0; + int i; + + /* pr_info("\nvh264_init\n"); */ + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + vh264_running = 0;/* init here to reset last_mb_width&last_mb_height */ + vh264_eos = 0; + duration_on_correcting = 0; + first_pts = 0; + first_pts64 = 0; + first_offset = 0; + first_pts_cached = false; + fixed_frame_rate_check_count = 0; + saved_resolution = 0; + iponly_early_mode = 0; + saved_idc_level = 0; + vh264_local_init(); + + query_video_status(0, &trickmode_fffb); + +#if 0 + if (!trickmode_fffb) { + void __iomem *p = + ioremap_nocache(ucode_map_start, V_BUF_ADDR_OFFSET); + if (p != NULL) { + memset(p, 0, V_BUF_ADDR_OFFSET); + iounmap(p); + } + } +#endif + + amvdec_enable(); + + /* -- ucode loading (amrisc and swap code) */ + mc_cpu_addr = + dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, + &mc_dma_handle, GFP_KERNEL); + if (!mc_cpu_addr) { + amvdec_disable(); + + pr_err("vh264_init: Can not allocate mc memory.\n"); + return -ENOMEM; + } + + pr_debug("264 ucode swap area: phyaddr %p, cpu vaddr %p\n", + (void *)mc_dma_handle, mc_cpu_addr); + if (debugfirmware) { + int r0, r1, r2, r3, r4, r5; + char firmwarename[32]; + + pr_debug("start load debug %d firmware ...\n", debugfirmware); + + snprintf(firmwarename, 32, "%s%d", "vh264_mc", debugfirmware); + r0 = amvdec_loadmc_ex(VFORMAT_H264, firmwarename, NULL); + +#define DEBUGGET_FW(t, name, buf, size, ret)\ + do {\ + snprintf(firmwarename, 32, "%s%d", name,\ + debugfirmware);\ + ret = get_decoder_firmware_data(t,\ + firmwarename, buf, size);\ + } while (0) + /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_HEADER, vh264_header_mc, + *MC_SWAP_SIZE); + */ + DEBUGGET_FW(VFORMAT_H264, "vh264_header_mc", + (u8 *) mc_cpu_addr + MC_OFFSET_HEADER, + MC_SWAP_SIZE, r1); + + /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_DATA, vh264_data_mc, + *MC_SWAP_SIZE); + */ + DEBUGGET_FW(VFORMAT_H264, "vh264_data_mc", + (u8 *) mc_cpu_addr + MC_OFFSET_DATA, MC_SWAP_SIZE, r2); + /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_MMCO, vh264_mmco_mc, + *MC_SWAP_SIZE); + */ + DEBUGGET_FW(VFORMAT_H264, "vh264_mmco_mc", + (u8 *) mc_cpu_addr + MC_OFFSET_MMCO, MC_SWAP_SIZE, r3); + /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_LIST, vh264_list_mc, + *MC_SWAP_SIZE); + */ + DEBUGGET_FW(VFORMAT_H264, "vh264_list_mc", + (u8 *) mc_cpu_addr + MC_OFFSET_LIST, MC_SWAP_SIZE, r4); + /*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_SLICE, vh264_slice_mc, + *MC_SWAP_SIZE); + */ + DEBUGGET_FW(VFORMAT_H264, "vh264_slice_mc", + (u8 *) mc_cpu_addr + MC_OFFSET_SLICE, MC_SWAP_SIZE, r5); + + if (r0 < 0 || r1 < 0 || r2 < 0 || r3 < 0 || r4 < 0 || r5 < 0) { + pr_err("264 load debugfirmware err %d,%d,%d,%d,%d,%d\n", + r0, r1, r2, r3, r4, r5); + amvdec_disable(); + if (mc_cpu_addr) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, + mc_dma_handle); + mc_cpu_addr = NULL; + } + return -EBUSY; + } + firmwareloaded = 1; + } else { + int ret = -1, size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + size = get_firmware_data(VIDEO_DEC_H264, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf); + memcpy((u8 *) mc_cpu_addr + MC_OFFSET_HEADER, + buf + 0x4000, MC_SWAP_SIZE); + memcpy((u8 *) mc_cpu_addr + MC_OFFSET_DATA, + buf + 0x2000, MC_SWAP_SIZE); + memcpy((u8 *) mc_cpu_addr + MC_OFFSET_MMCO, + buf + 0x6000, MC_SWAP_SIZE); + memcpy((u8 *) mc_cpu_addr + MC_OFFSET_LIST, + buf + 0x3000, MC_SWAP_SIZE); + memcpy((u8 *) mc_cpu_addr + MC_OFFSET_SLICE, + buf + 0x5000, MC_SWAP_SIZE); + + vfree(buf); + + if (ret < 0) { + pr_err("h264 load orignal firmware error %d.\n", ret); + amvdec_disable(); + if (mc_cpu_addr) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, + mc_dma_handle); + mc_cpu_addr = NULL; + } + return -EBUSY; + } + } + + stat |= STAT_MC_LOAD; + if (enable_switch_fense) { + for (i = 0; i < ARRAY_SIZE(fense_buffer_spec); i++) { + struct buffer_spec_s *s = &fense_buffer_spec[i]; + s->alloc_count = 3 * SZ_1M / PAGE_SIZE; + if (!decoder_bmmu_box_alloc_idx_wait( + mm_blk_handle, + FENSE_BUFFER_IDX(i), + 3 * SZ_1M, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR + )) { + s->phy_addr = decoder_bmmu_box_get_phy_addr( + mm_blk_handle, + FENSE_BUFFER_IDX(i)); + } else { + return -ENOMEM; + } + s->y_canvas_index = 2 * i; + s->u_canvas_index = 2 * i + 1; + s->v_canvas_index = 2 * i + 1; + } + } + /* enable AMRISC side protocol */ + vh264_prot_init(); + +#ifdef HANDLE_H264_IRQ + /*TODO irq */ + + if (vdec_request_irq(VDEC_IRQ_1, vh264_isr, + "vh264-irq", (void *)vh264_dec_id)) { + pr_err("vh264 irq register error.\n"); + amvdec_disable(); + return -ENOENT; + } +#endif + + stat |= STAT_ISR_REG; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vh264_vf_prov, PROVIDER_NAME, &vh264_vf_provider_ops, + NULL); + vf_reg_provider(&vh264_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vh264_vf_prov, PROVIDER_NAME, &vh264_vf_provider_ops, + NULL); + vf_reg_provider(&vh264_vf_prov); +#endif + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)frame_dur)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong) &recycle_timer; + recycle_timer.function = vh264_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + vh264_stream_switching_state = SWITCHING_STATE_OFF; + + stat |= STAT_VDEC_RUN; + wmb(); /* Ensure fetchbuf contents visible */ + + /* -- start decoder */ + amvdec_start(); + + init_userdata_fifo(); + + return 0; +} + +static int vh264_stop(int mode) +{ + + + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + /*TODO irq */ + + vdec_free_irq(VDEC_IRQ_1, (void *)vh264_dec_id); + + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + if (mode == MODE_FULL) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, + NULL); + } + + vf_unreg_provider(&vh264_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + if (stat & STAT_MC_LOAD) { + if (mc_cpu_addr != NULL) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, + mc_dma_handle); + mc_cpu_addr = NULL; + } + } + if (sei_data_buffer != NULL) { + dma_free_coherent( + amports_get_dma_device(), + USER_DATA_SIZE, + sei_data_buffer, + sei_data_buffer_phys); + sei_data_buffer = NULL; + sei_data_buffer_phys = 0; + } + amvdec_disable(); + if (mm_blk_handle) { + decoder_bmmu_box_free(mm_blk_handle); + mm_blk_handle = NULL; + } + memset(&fense_buffer_spec, 0, sizeof(fense_buffer_spec)); + memset(&buffer_spec, 0, sizeof(buffer_spec)); + return 0; +} + +static void error_do_work(struct work_struct *work) +{ + mutex_lock(&vh264_mutex); + + /* + * we need to lock vh264_stop/vh264_init. + * because we will call amvdec_h264_remove on this step; + * then we may call more than once on + * free_irq/deltimer/..and some other. + */ + if (atomic_read(&vh264_active)) { + amvdec_stop(); + vh264_reset = 1; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vh264_ppmgr_reset(); +#else + vf_light_unreg_provider(&vh264_vf_prov); + + vh264_local_init(); + + vf_reg_provider(&vh264_vf_prov); +#endif + msleep(30); + vh264_local_init(); + vh264_prot_init(); + + amvdec_start(); + vh264_reset = 0; + } + + mutex_unlock(&vh264_mutex); +} + +static void stream_switching_done(void) +{ + int state = vh264_stream_switching_state; + + WRITE_VREG(AV_SCRATCH_7, 0); + WRITE_VREG(AV_SCRATCH_8, 0); + WRITE_VREG(AV_SCRATCH_9, 0); + + if (state == SWITCHING_STATE_ON_CMD1) { + pr_info("Enter set parameter cmd1 switching_state %x.\n", + vh264_stream_switching_state); + schedule_work(&set_parameter_work); + return; + } else if (state == SWITCHING_STATE_ON_CMD1_PENDING) + return; + + vh264_stream_switching_state = SWITCHING_STATE_OFF; + + wmb(); /* Ensure fetchbuf contents visible */ + + if (state == SWITCHING_STATE_ON_CMD3) + WRITE_VREG(AV_SCRATCH_0, 0); + + pr_info("Leaving switching mode.\n"); +} + +/* construt a new frame as a copy of last frame so frame receiver can + * release all buffer resources to decoder. + */ +static void stream_switching_do(struct work_struct *work) +{ + int mb_total_num, mb_width_num, mb_height_num, i = 0; + struct vframe_s *vf = NULL; + u32 y_index, u_index, src_index, des_index, y_desindex, u_desindex; + struct canvas_s csy, csu, cyd; + unsigned long flags; + bool delay = true; + + if (!atomic_read(&vh264_active)) + return; + + if (vh264_stream_switching_state == SWITCHING_STATE_OFF) + return; + + spin_lock_irqsave(&prepare_lock, flags); + + block_display_q = true; + + spin_unlock_irqrestore(&prepare_lock, flags); + + mb_total_num = mb_total; + mb_width_num = mb_width; + mb_height_num = mb_height; + + while (is_4k || kfifo_len(&delay_display_q) > 2) { + if (kfifo_get(&delay_display_q, &vf)) { + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + break; + } + + if (!kfifo_get(&delay_display_q, &vf)) { + vf = p_last_vf; + delay = false; + } + + while (vf) { + int buffer_index; + + buffer_index = vf->index & 0xff; + + /* construct a clone of the frame from last frame */ +#if 1 + pr_info("src yaddr[0x%x] index[%d] width[%d] heigth[%d]\n", + buffer_spec[buffer_index].y_addr, + buffer_spec[buffer_index].y_canvas_index, + buffer_spec[buffer_index].y_canvas_width, + buffer_spec[buffer_index].y_canvas_height); + + pr_info("src uaddr[0x%x] index[%d] width[%d] heigth[%d]\n", + buffer_spec[buffer_index].u_addr, + buffer_spec[buffer_index].u_canvas_index, + buffer_spec[buffer_index].u_canvas_width, + buffer_spec[buffer_index].u_canvas_height); +#endif + if (EN_SWITCH_FENCE()) { + y_index = buffer_spec[buffer_index].y_canvas_index; + u_index = buffer_spec[buffer_index].u_canvas_index; + + canvas_read(y_index, &csy); + canvas_read(u_index, &csu); + + canvas_config(fense_buffer_spec[i].y_canvas_index, + fense_buffer_spec[i].phy_addr, + mb_width_num << 4, mb_height_num << 4, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(fense_buffer_spec[i].u_canvas_index, + fense_buffer_spec[i].phy_addr + + (mb_total_num << 8), + mb_width_num << 4, mb_height_num << 3, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + + y_desindex = fense_buffer_spec[i].y_canvas_index; + u_desindex = fense_buffer_spec[i].u_canvas_index; + + canvas_read(y_desindex, &cyd); + + src_index = ((y_index & 0xff) | + ((u_index << 8) & 0x0000ff00)); + des_index = ((y_desindex & 0xff) | + ((u_desindex << 8) & 0x0000ff00)); + + ge2d_canvas_dup(&csy, &csu, &cyd, + GE2D_FORMAT_M24_NV21, + src_index, + des_index); + } + vf->mem_handle = decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + FENSE_BUFFER_IDX(i)); + fense_vf[i] = *vf; + fense_vf[i].index = -1; + + if (EN_SWITCH_FENCE()) + fense_vf[i].canvas0Addr = + spec2canvas(&fense_buffer_spec[i]); + else + fense_vf[i].flag |= VFRAME_FLAG_SWITCHING_FENSE; + + /* send clone to receiver */ + kfifo_put(&display_q, + (const struct vframe_s *)&fense_vf[i]); + + /* early recycle frames for last session */ + if (delay) + vh264_vf_put(vf, NULL); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + i++; + + if (!kfifo_get(&delay_display_q, &vf)) + break; + } + + block_display_q = false; + + pr_info("Switching fense frame post\n"); +} + +static int amvdec_h264_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + mutex_lock(&vh264_mutex); + + if (pdata == NULL) { + pr_info("\namvdec_h264 memory resource undefined.\n"); + mutex_unlock(&vh264_mutex); + return -EFAULT; + } + + ucode_map_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; + if (buf_size < DEFAULT_MEM_SIZE) { + pr_info("\namvdec_h264 memory size not enough.\n"); + mutex_unlock(&vh264_mutex); + return -ENOMEM; + } + + buf_offset = pdata->mem_start - DEF_BUF_START_ADDR; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + buf_start = V_BUF_ADDR_OFFSET_NEW + pdata->mem_start; + else + buf_start = V_BUF_ADDR_OFFSET + pdata->mem_start; + buf_end = pdata->mem_end; + if (pdata->sys_info) + vh264_amstream_dec_info = *pdata->sys_info; + if (NULL == sei_data_buffer) { + sei_data_buffer = + dma_alloc_coherent(amports_get_dma_device(), + USER_DATA_SIZE, + &sei_data_buffer_phys, GFP_KERNEL); + if (!sei_data_buffer) { + pr_info("%s: Can not allocate sei_data_buffer\n", + __func__); + mutex_unlock(&vh264_mutex); + return -ENOMEM; + } + /* pr_info("buffer 0x%x, phys 0x%x, remap 0x%x\n", + * sei_data_buffer, sei_data_buffer_phys, + * (u32)sei_data_buffer_remap); + */ + } + pr_debug("amvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx buf_size %x\n", + pdata->mem_start, buf_offset, buf_start, buf_size); + pdata->dec_status = vh264_dec_status; + pdata->set_trickmode = vh264_set_trickmode; + + if (vh264_init() < 0) { + pr_info("\namvdec_h264 init failed.\n"); + mutex_unlock(&vh264_mutex); + return -ENODEV; + } + + INIT_WORK(&error_wd_work, error_do_work); + INIT_WORK(&stream_switching_work, stream_switching_do); + INIT_WORK(&set_parameter_work, vh264_set_params); + + atomic_set(&vh264_active, 1); + + mutex_unlock(&vh264_mutex); + + return 0; +} + +static int amvdec_h264_remove(struct platform_device *pdev) +{ + atomic_set(&vh264_active, 0); + cancel_work_sync(&set_parameter_work); + cancel_work_sync(&error_wd_work); + cancel_work_sync(&stream_switching_work); + mutex_lock(&vh264_mutex); + vh264_stop(MODE_FULL); + vdec_source_changed(VFORMAT_H264, 0, 0, 0); + atomic_set(&vh264_active, 0); +#ifdef DEBUG_PTS + pr_info + ("pts missed %ld, pts hit %ld, pts_outside %d, duration %d, ", + pts_missed, pts_hit, pts_outside, frame_dur); + pr_info("sync_outside %d, use_idr_framerate %d\n", + sync_outside, use_idr_framerate); +#endif + mutex_unlock(&vh264_mutex); + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_h264_driver = { + .probe = amvdec_h264_probe, + .remove = amvdec_h264_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_h264_profile = { + .name = "h264", + .profile = "" +}; + +static int __init amvdec_h264_driver_init_module(void) +{ + pr_debug("amvdec_h264 module init\n"); + + ge2d_videoh264task_init(); + + if (platform_driver_register(&amvdec_h264_driver)) { + pr_err("failed to register amvdec_h264 driver\n"); + return -ENODEV; + } + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB + && (codec_mm_get_total_size() > 80 * SZ_1M)) { + amvdec_h264_profile.profile = "4k"; + dpb_size_adj = 0; + } + if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXBB) + dpb_size_adj = 0; + + vcodec_profile_register(&amvdec_h264_profile); + return 0; +} + +static void __exit amvdec_h264_driver_remove_module(void) +{ + pr_debug("amvdec_h264 module remove.\n"); + + platform_driver_unregister(&amvdec_h264_driver); + + ge2d_videoh264task_release(); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_h264 stat\n"); +module_param(error_recovery_mode, uint, 0664); +MODULE_PARM_DESC(error_recovery_mode, "\n amvdec_h264 error_recovery_mode\n"); +module_param(sync_outside, uint, 0664); +MODULE_PARM_DESC(sync_outside, "\n amvdec_h264 sync_outside\n"); +module_param(dec_control, uint, 0664); +MODULE_PARM_DESC(dec_control, "\n amvdec_h264 decoder control\n"); +module_param(fatal_error_reset, uint, 0664); +MODULE_PARM_DESC(fatal_error_reset, + "\n amvdec_h264 decoder reset when fatal error happens\n"); +module_param(max_refer_buf, uint, 0664); +MODULE_PARM_DESC(max_refer_buf, + "\n amvdec_h264 dec buffering or not for reference frame\n"); +module_param(ucode_type, uint, 0664); +MODULE_PARM_DESC(ucode_type, + "\n amvdec_h264 dec buffering or not for reference frame\n"); +module_param(debugfirmware, uint, 0664); +MODULE_PARM_DESC(debugfirmware, "\n amvdec_h264 debug load firmware\n"); +module_param(fixed_frame_rate_flag, uint, 0664); +MODULE_PARM_DESC(fixed_frame_rate_flag, + "\n amvdec_h264 fixed_frame_rate_flag\n"); +module_param(decoder_debug_flag, uint, 0664); +MODULE_PARM_DESC(decoder_debug_flag, + "\n amvdec_h264 decoder_debug_flag\n"); + +module_param(dpb_size_adj, uint, 0664); +MODULE_PARM_DESC(dpb_size_adj, + "\n amvdec_h264 dpb_size_adj\n"); + + +module_param(decoder_force_reset, uint, 0664); +MODULE_PARM_DESC(decoder_force_reset, + "\n amvdec_h264 decoder force reset\n"); +module_param(no_idr_error_max, uint, 0664); +MODULE_PARM_DESC(no_idr_error_max, + "\n print no_idr_error_max\n"); +module_param(enable_switch_fense, uint, 0664); +MODULE_PARM_DESC(enable_switch_fense, + "\n enable switch fense\n"); + + +module_init(amvdec_h264_driver_init_module); +module_exit(amvdec_h264_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC H264 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Chen Zhang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h new file mode 100644 index 000000000000..45d28490b2e5 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.h @@ -0,0 +1,25 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/h264/vh264.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VH264_H +#define VH264_H + +/* extern s32 vh264_init(void); */ + +extern s32 vh264_release(void); + +#endif /* VMPEG4_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c new file mode 100644 index 000000000000..1c56b0312f78 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c @@ -0,0 +1,1839 @@ +/* + * drivers/amlogic/amports/vh264_4k2k.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MEM_NAME "codec_264_4k" + +/* #include */ +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + +#include +#endif + +#include +#include "../../../stream_input/amports/amports_priv.h" +#include "../utils/vdec.h" +#include "../utils/amvdec.h" + +#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TVD */ +#define DOUBLE_WRITE +#endif + +#define DRIVER_NAME "amvdec_h264_4k2k" +#define MODULE_NAME "amvdec_h264_4k2k" + +#define PUT_INTERVAL (HZ/100) +#define ERROR_RESET_COUNT 500 + +#if 1 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV */ +#define H264_4K2K_SINGLE_CORE 1 +#else +#define H264_4K2K_SINGLE_CORE IS_MESON_M8M2_CPU +#endif + +#define SLICE_TYPE_I 2 + +static int vh264_4k2k_vf_states(struct vframe_states *states, void *); +static struct vframe_s *vh264_4k2k_vf_peek(void *); +static struct vframe_s *vh264_4k2k_vf_get(void *); +static void vh264_4k2k_vf_put(struct vframe_s *, void *); +static int vh264_4k2k_event_cb(int type, void *data, void *private_data); + +static void vh264_4k2k_prot_init(void); +static void vh264_4k2k_local_init(void); +static void vh264_4k2k_put_timer_func(unsigned long arg); + +static const char vh264_4k2k_dec_id[] = "vh264_4k2k-dev"; +static const char vh264_4k2k_dec_id2[] = "vh264_4k2k-vdec2-dev"; + +#define PROVIDER_NAME "decoder.h264_4k2k" + +static const struct vframe_operations_s vh264_4k2k_vf_provider = { + .peek = vh264_4k2k_vf_peek, + .get = vh264_4k2k_vf_get, + .put = vh264_4k2k_vf_put, + .event_cb = vh264_4k2k_event_cb, + .vf_states = vh264_4k2k_vf_states, +}; + +static struct vframe_provider_s vh264_4k2k_vf_prov; + +static u32 mb_width_old, mb_height_old; +static u32 frame_width, frame_height, frame_dur, frame_ar; +static u32 saved_resolution; +static struct timer_list recycle_timer; +static u32 stat; +static u32 error_watchdog_count; +static uint error_recovery_mode; +static u32 sync_outside; +static u32 vh264_4k2k_rotation; +static u32 first_i_recieved; +static struct vframe_s *p_last_vf; + +#ifdef DEBUG_PTS +static unsigned long pts_missed, pts_hit; +#endif + +static struct dec_sysinfo vh264_4k2k_amstream_dec_info; +static dma_addr_t mc_dma_handle; +static void *mc_cpu_addr; + +#define AMVDEC_H264_4K2K_CANVAS_INDEX 0x80 +#define AMVDEC_H264_4K2K_CANVAS_MAX 0xc6 +static DEFINE_SPINLOCK(lock); +static int fatal_error; + +static atomic_t vh264_4k2k_active = ATOMIC_INIT(0); + +static DEFINE_MUTEX(vh264_4k2k_mutex); + +static void (*probe_callback)(void); +static void (*remove_callback)(void); +static struct device *cma_dev; + +/* bit[3:0] command : */ +/* 0 - command finished */ +/* (DATA0 - {level_idc_mmco, max_reference_frame_num, width, height} */ +/* 1 - alloc view_0 display_buffer and reference_data_area */ +/* 2 - alloc view_1 display_buffer and reference_data_area */ +#define MAILBOX_COMMAND AV_SCRATCH_0 +#define MAILBOX_DATA_0 AV_SCRATCH_1 +#define MAILBOX_DATA_1 AV_SCRATCH_2 +#define MAILBOX_DATA_2 AV_SCRATCH_3 +#define MAILBOX_DATA_3 AV_SCRATCH_4 +#define MAILBOX_DATA_4 AV_SCRATCH_5 +#define CANVAS_START AV_SCRATCH_6 +#define BUFFER_RECYCLE AV_SCRATCH_7 +#define PICTURE_COUNT AV_SCRATCH_9 +#define DECODE_STATUS AV_SCRATCH_A +#define SPS_STATUS AV_SCRATCH_B +#define PPS_STATUS AV_SCRATCH_C +#define MS_ID AV_SCRATCH_D +#define WORKSPACE_START AV_SCRATCH_E +#define DECODED_PIC_NUM AV_SCRATCH_F +#define DECODE_ERROR_CNT AV_SCRATCH_G +#define CURRENT_UCODE AV_SCRATCH_H +/* bit[15:9]-SPS, bit[8:0]-PPS */ +#define CURRENT_SPS_PPS AV_SCRATCH_I +#define DECODE_SKIP_PICTURE AV_SCRATCH_J +#define DECODE_MODE AV_SCRATCH_K +#define RESERVED_REG_L AV_SCRATCH_L +#define REF_START_VIEW_0 AV_SCRATCH_M +#define REF_START_VIEW_1 AV_SCRATCH_N + +#define VDEC2_MAILBOX_COMMAND VDEC2_AV_SCRATCH_0 +#define VDEC2_MAILBOX_DATA_0 VDEC2_AV_SCRATCH_1 +#define VDEC2_MAILBOX_DATA_1 VDEC2_AV_SCRATCH_2 +#define VDEC2_MAILBOX_DATA_2 VDEC2_AV_SCRATCH_3 +#define VDEC2_MAILBOX_DATA_3 VDEC2_AV_SCRATCH_4 +#define VDEC2_MAILBOX_DATA_4 VDEC2_AV_SCRATCH_5 +#define VDEC2_CANVAS_START VDEC2_AV_SCRATCH_6 +#define VDEC2_BUFFER_RECYCLE VDEC2_AV_SCRATCH_7 +#define VDEC2_PICTURE_COUNT VDEC2_AV_SCRATCH_9 +#define VDEC2_DECODE_STATUS VDEC2_AV_SCRATCH_A +#define VDEC2_SPS_STATUS VDEC2_AV_SCRATCH_B +#define VDEC2_PPS_STATUS VDEC2_AV_SCRATCH_C +#define VDEC2_MS_ID VDEC2_AV_SCRATCH_D +#define VDEC2_WORKSPACE_START VDEC2_AV_SCRATCH_E +#define VDEC2_DECODED_PIC_NUM VDEC2_AV_SCRATCH_F +#define VDEC2_DECODE_ERROR_CNT VDEC2_AV_SCRATCH_G +#define VDEC2_CURRENT_UCODE VDEC2_AV_SCRATCH_H +/* bit[15:9]-SPS, bit[8:0]-PPS */ +#define VDEC2_CURRENT_SPS_PPS VDEC2_AV_SCRATCH_I +#define VDEC2_DECODE_SKIP_PICTURE VDEC2_AV_SCRATCH_J +#define VDEC2_RESERVED_REG_K VDEC2_AV_SCRATCH_K +#define VDEC2_RESERVED_REG_L VDEC2_AV_SCRATCH_L +#define VDEC2_REF_START_VIEW_0 VDEC2_AV_SCRATCH_M +#define VDEC2_REF_START_VIEW_1 VDEC2_AV_SCRATCH_N + +/******************************************** + * DECODE_STATUS Define +********************************************/ +#define DECODE_IDLE 0 +#define DECODE_START_HEADER 1 +#define DECODE_HEADER 2 +#define DECODE_START_MMCO 3 +#define DECODE_MMCO 4 +#define DECODE_START_SLICE 5 +#define DECODE_SLICE 6 +#define DECODE_WAIT_BUFFER 7 + +/******************************************** + * Dual Core Communication +********************************************/ +#define FATAL_ERROR DOS_SCRATCH16 +#define PRE_MASTER_UPDATE_TIMES DOS_SCRATCH20 +/* bit[31] - REQUEST */ +/* bit[30:0] - MASTER_UPDATE_TIMES */ +#define SLAVE_WAIT_DPB_UPDATE DOS_SCRATCH21 +/* [15:8] - current_ref, [7:0] current_dpb (0x80 means no buffer found) */ +#define SLAVE_REF_DPB DOS_SCRATCH22 +#define SAVE_MVC_ENTENSION_0 DOS_SCRATCH23 +#define SAVE_I_POC DOS_SCRATCH24 +/* bit[31:30] - core_status 0-idle, 1-mmco, 2-decoding, 3-finished */ +/* bit[29:0] - core_pic_count */ +#define CORE_STATUS_M DOS_SCRATCH25 +#define CORE_STATUS_S DOS_SCRATCH26 +#define SAVE_ref_status_view_0 DOS_SCRATCH27 +#define SAVE_ref_status_view_1 DOS_SCRATCH28 +#define ALLOC_INFO_0 DOS_SCRATCH29 +#define ALLOC_INFO_1 DOS_SCRATCH30 + +/******************************************** + * Mailbox command + ********************************************/ +#define CMD_FINISHED 0 +#define CMD_ALLOC_VIEW 1 +#define CMD_FRAME_DISPLAY 3 +#define CMD_DEBUG 10 + +#define MC_TOTAL_SIZE (28*SZ_1K) +#define MC_SWAP_SIZE (4*SZ_1K) + +static unsigned long work_space_adr, decoder_buffer_start, decoder_buffer_end; +static unsigned long reserved_buffer; + +#define DECODE_BUFFER_NUM_MAX 32 +#define DISPLAY_BUFFER_NUM 6 + +#define video_domain_addr(adr) (adr&0x7fffffff) +#define DECODER_WORK_SPACE_SIZE 0x400000 + +struct buffer_spec_s { + unsigned int y_addr; + unsigned int uv_addr; +#ifdef DOUBLE_WRITE + unsigned int y_dw_addr; + unsigned int uv_dw_addr; +#endif + + int y_canvas_index; + int uv_canvas_index; +#ifdef DOUBLE_WRITE + int y_dw_canvas_index; + int uv_dw_canvas_index; +#endif + + struct page *alloc_pages; + unsigned long phy_addr; + int alloc_count; +}; + +static struct buffer_spec_s buffer_spec[DECODE_BUFFER_NUM_MAX + + DISPLAY_BUFFER_NUM]; + +#ifdef DOUBLE_WRITE +#define spec2canvas(x) \ + (((x)->uv_dw_canvas_index << 16) | \ + ((x)->uv_dw_canvas_index << 8) | \ + ((x)->y_dw_canvas_index << 0)) +#else +#define spec2canvas(x) \ + (((x)->uv_canvas_index << 16) | \ + ((x)->uv_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) +#endif + +#define VF_POOL_SIZE 32 + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; +static struct vframe_s vfpool[VF_POOL_SIZE]; + +static struct work_struct alloc_work; + +static void set_frame_info(struct vframe_s *vf) +{ + unsigned int ar; + +#ifdef DOUBLE_WRITE + vf->width = frame_width / 2; + vf->height = frame_height / 2; +#else + vf->width = frame_width; + vf->height = frame_height; +#endif + vf->duration = frame_dur; + vf->duration_pulldown = 0; + vf->flag = 0; + + ar = min_t(u32, frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + vf->orientation = vh264_4k2k_rotation; + + return; +} + +static int vh264_4k2k_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + return 0; +} + +static struct vframe_s *vh264_4k2k_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vh264_4k2k_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vh264_4k2k_vf_put(struct vframe_s *vf, void *op_arg) +{ + kfifo_put(&recycle_q, (const struct vframe_s *)vf); +} + +static int vh264_4k2k_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); + + if (!H264_4K2K_SINGLE_CORE) + amvdec2_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vh264_4k2k_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vh264_4k2k_local_init(); + vh264_4k2k_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vh264_4k2k_vf_prov); +#endif + amvdec_start(); + + if (!H264_4K2K_SINGLE_CORE) + amvdec2_start(); + } + + return 0; +} + +int init_canvas(int start_addr, long dpb_size, int dpb_number, int mb_width, + int mb_height, struct buffer_spec_s *buffer_spec) +{ + unsigned long dpb_addr, addr; + int i; + int mb_total; + int canvas_addr = ANC0_CANVAS_ADDR; + int vdec2_canvas_addr = VDEC2_ANC0_CANVAS_ADDR; + int index = AMVDEC_H264_4K2K_CANVAS_INDEX; + u32 disp_addr = 0xffffffff; + bool use_alloc = false; + int alloc_count = 0; + struct canvas_s cur_canvas; + + dpb_addr = start_addr + dpb_size; + + mb_total = mb_width * mb_height; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + + mutex_lock(&vh264_4k2k_mutex); + + for (i = 0; i < dpb_number; i++) { + WRITE_VREG(canvas_addr++, + index | ((index + 1) << 8) | + ((index + 1) << 16)); + if (!H264_4K2K_SINGLE_CORE) { + WRITE_VREG(vdec2_canvas_addr++, + index | ((index + 1) << 8) | + ((index + 1) << 16)); + } + + if (((dpb_addr + (mb_total << 8) + (mb_total << 7)) >= + decoder_buffer_end) && (!use_alloc)) { + pr_info("start alloc for %d/%d\n", i, dpb_number); + use_alloc = true; + } + + if (use_alloc) { +#ifdef DOUBLE_WRITE + int page_count = + PAGE_ALIGN((mb_total << 8) + (mb_total << 7) + + (mb_total << 6) + + (mb_total << 5)) / PAGE_SIZE; +#else + int page_count = + PAGE_ALIGN((mb_total << 8) + + (mb_total << 7)) / PAGE_SIZE; +#endif + + if (buffer_spec[i].phy_addr) { + if (page_count != buffer_spec[i].alloc_count) { + pr_info("Delay release CMA buffer%d\n", + i); + + /*dma_release_from_contiguous(cma_dev, + buffer_spec[i]. + alloc_pages, + buffer_spec[i]. + alloc_count); + */ + codec_mm_free_for_dma(MEM_NAME, + buffer_spec[i].phy_addr); + buffer_spec[i].phy_addr = 0; + buffer_spec[i].alloc_pages = NULL; + buffer_spec[i].alloc_count = 0; + } else + pr_info("Re-use CMA buffer %d\n", i); + } + + if (!buffer_spec[i].phy_addr) { + if (codec_mm_get_free_size() + < (page_count * PAGE_SIZE)) { + pr_err + ("CMA not enough free keep buf! %d\n", + i); + try_free_keep_video(1); + } + if (!codec_mm_enough_for_size( + page_count * PAGE_SIZE, 1)) { + buffer_spec[i].alloc_count = 0; + fatal_error = + DECODER_FATAL_ERROR_NO_MEM; + mutex_unlock(&vh264_4k2k_mutex); + return -1; + } + buffer_spec[i].alloc_count = page_count; + buffer_spec[i].phy_addr = + codec_mm_alloc_for_dma( + MEM_NAME, buffer_spec[i].alloc_count, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + } + alloc_count++; + + if (!buffer_spec[i].phy_addr) { + buffer_spec[i].alloc_count = 0; + pr_info + ("264 4K2K decoder memory alloc failed %d.\n", + i); + mutex_unlock(&vh264_4k2k_mutex); + return -1; + } + addr = buffer_spec[i].phy_addr; + dpb_addr = addr; + } else { + if (buffer_spec[i].phy_addr) { + codec_mm_free_for_dma(MEM_NAME, + buffer_spec[i].phy_addr); + buffer_spec[i].phy_addr = 0; + buffer_spec[i].alloc_pages = NULL; + buffer_spec[i].alloc_count = 0; + } + + addr = dpb_addr; + dpb_addr += dpb_size; +#ifdef DOUBLE_WRITE + dpb_addr += dpb_size / 4; +#endif + } + + if (((addr + 7) >> 3) == disp_addr) + addr = start_addr; + + buffer_spec[i].y_addr = addr; + buffer_spec[i].y_canvas_index = index; + canvas_config(index, + addr, + mb_width << 4, + mb_height << 4, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 8; + index++; + + buffer_spec[i].uv_addr = addr; + buffer_spec[i].uv_canvas_index = index; + canvas_config(index, + addr, + mb_width << 4, + mb_height << 3, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 7; + index++; + +#ifdef DOUBLE_WRITE + buffer_spec[i].y_dw_addr = addr; + buffer_spec[i].y_dw_canvas_index = index; + canvas_config(index, + addr, + mb_width << 3, + mb_height << 3, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 6; + index++; + + buffer_spec[i].uv_dw_addr = addr; + buffer_spec[i].uv_dw_canvas_index = index; + canvas_config(index, + addr, + mb_width << 3, + mb_height << 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 5; + index++; +#endif + } + + mutex_unlock(&vh264_4k2k_mutex); + + pr_info + ("H264 4k2k decoder canvas allocation successful, "); + pr_info("%d CMA blocks allocated, canvas %d-%d\n", + alloc_count, AMVDEC_H264_4K2K_CANVAS_INDEX, index - 1); + + return 0; +} + +static int get_max_dec_frame_buf_size(int level_idc, + int max_reference_frame_num, int mb_width, + int mb_height) +{ + int pic_size = mb_width * mb_height * 384; + + int size = 0; + + switch (level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + case 52: + default: + size = 70778880; + break; + } + + size /= pic_size; + size = size + 1; /* need one more buffer */ + + if (max_reference_frame_num > size) + size = max_reference_frame_num; + + if (size > DECODE_BUFFER_NUM_MAX) + size = DECODE_BUFFER_NUM_MAX; + + return size; +} + +static void do_alloc_work(struct work_struct *work) +{ + int level_idc, max_reference_frame_num, mb_width, mb_height, + frame_mbs_only_flag; + int dpb_size, ref_size; + int dpb_start_addr, ref_start_addr, max_dec_frame_buffering, + total_dec_frame_buffering; + unsigned int chroma444; + unsigned int crop_infor, crop_bottom, crop_right; + int ret = READ_VREG(MAILBOX_COMMAND); + + ref_start_addr = decoder_buffer_start; + ret = READ_VREG(MAILBOX_DATA_0); + /* MAILBOX_DATA_1 : + bit15 : frame_mbs_only_flag + bit 0-7 : chroma_format_idc + MAILBOX_DATA_2: + bit31-16: (left << 8 | right ) << 1 + bit15-0 : (top << 8 | bottom ) << (2 - frame_mbs_only_flag) + */ + frame_mbs_only_flag = READ_VREG(MAILBOX_DATA_1); + crop_infor = READ_VREG(MAILBOX_DATA_2); + level_idc = (ret >> 24) & 0xff; + max_reference_frame_num = (ret >> 16) & 0xff; + mb_width = (ret >> 8) & 0xff; + if (mb_width == 0) + mb_width = 256; + mb_height = (ret >> 0) & 0xff; + max_dec_frame_buffering = + get_max_dec_frame_buf_size(level_idc, max_reference_frame_num, + mb_width, mb_height); + total_dec_frame_buffering = + max_dec_frame_buffering + DISPLAY_BUFFER_NUM; + + chroma444 = ((frame_mbs_only_flag&0xffff) == 3) ? 1 : 0; + frame_mbs_only_flag = (frame_mbs_only_flag >> 16) & 0x01; + crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag); + crop_right = ((crop_infor >> 16) & 0xff) >> 1; + pr_info("crop_right = 0x%x crop_bottom = 0x%x chroma_format_idc = 0x%x\n", + crop_right, crop_bottom, chroma444); + + if ((frame_width == 0) || (frame_height == 0) || crop_infor || + mb_width != mb_width_old || + mb_height != mb_height_old) { + frame_width = mb_width << 4; + frame_height = mb_height << 4; + mb_width_old = mb_width; + mb_height_old = mb_height; + if (frame_mbs_only_flag) { + frame_height -= (2 >> chroma444) * + min(crop_bottom, + (unsigned int)((8 << chroma444) - 1)); + frame_width -= (2 >> chroma444) * + min(crop_right, + (unsigned int)((8 << chroma444) - 1)); + } else { + frame_height -= (4 >> chroma444) * + min(crop_bottom, + (unsigned int)((8 << chroma444) - 1)); + frame_width -= (4 >> chroma444) * + min(crop_right, + (unsigned int)((8 << chroma444) - 1)); + } + pr_info("frame_mbs_only_flag %d, crop_bottom %d frame_height %d, mb_height %d crop_right %d, frame_width %d, mb_width %d\n", + frame_mbs_only_flag, crop_bottom, frame_height, + mb_height, crop_right, frame_width, mb_height); + } + + mb_width = (mb_width + 3) & 0xfffffffc; + mb_height = (mb_height + 3) & 0xfffffffc; + + dpb_size = mb_width * mb_height * 384; + ref_size = mb_width * mb_height * 96; + dpb_start_addr = + ref_start_addr + (ref_size * (max_reference_frame_num + 1)) * 2; + /* dpb_start_addr = reserved_buffer + dpb_size; */ + + pr_info + ("dpb_start_addr=0x%x, dpb_size=%d, total_dec_frame_buffering=%d, ", + dpb_start_addr, dpb_size, total_dec_frame_buffering); + pr_info("mb_width=%d, mb_height=%d\n", + mb_width, mb_height); + + ret = init_canvas(dpb_start_addr, dpb_size, + total_dec_frame_buffering, mb_width, mb_height, + buffer_spec); + + if (ret == -1) { + pr_info(" Un-expected memory alloc problem\n"); + return; + } + + if (frame_width == 0) + frame_width = mb_width << 4; + if (frame_height == 0) + frame_height = mb_height << 4; + + WRITE_VREG(REF_START_VIEW_0, video_domain_addr(ref_start_addr)); + if (!H264_4K2K_SINGLE_CORE) { + WRITE_VREG(VDEC2_REF_START_VIEW_0, + video_domain_addr(ref_start_addr)); + } + + WRITE_VREG(MAILBOX_DATA_0, + (max_dec_frame_buffering << 8) | + (total_dec_frame_buffering << 0)); + WRITE_VREG(MAILBOX_DATA_1, ref_size); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + + /* ///////////// FAKE FIRST PIC */ +#if 0 + + pr_info("Debug: send a fake picture to config VPP %dx%d\n", frame_width, + frame_height); + WRITE_VREG(DOS_SCRATCH0, 4); + WRITE_VREG(DOS_SCRATCH1, 0x004c); + + if (kfifo_get(&newframe_q, &vf)) { + vfbuf_use[0]++; + vf->index = 0; + vf->pts = 0; + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&buffer_spec[0]); + set_frame_info(vf); + kfifo_put(&display_q, (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + /* ///////////// FAKE END */ +#endif +} + +static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) +{ + int drop_status, display_buff_id, display_POC, slice_type, error; + unsigned stream_offset; + struct vframe_s *vf = NULL; + int ret = READ_VREG(MAILBOX_COMMAND); + + switch (ret & 0xff) { + case CMD_ALLOC_VIEW: + schedule_work(&alloc_work); + break; + + case CMD_FRAME_DISPLAY: + ret >>= 8; + display_buff_id = (ret >> 0) & 0x3f; + drop_status = (ret >> 8) & 0x1; + slice_type = (ret >> 9) & 0x7; + error = (ret >> 12) & 0x1; + display_POC = READ_VREG(MAILBOX_DATA_0); + stream_offset = READ_VREG(MAILBOX_DATA_1); + + smp_rmb();/* rmb smp */ + + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + if (vf) { + vfbuf_use[display_buff_id]++; + + vf->pts = 0; + vf->pts_us64 = 0; + + if ((!sync_outside) + || (sync_outside && + (slice_type == SLICE_TYPE_I))) { + pts_lookup_offset_us64(PTS_TYPE_VIDEO, + stream_offset, + &vf->pts, + 0, + &vf->pts_us64); + } +#ifdef H264_4K2K_SINGLE_CORE + if (READ_VREG(DECODE_MODE) & 1) { + /* for I only mode, ignore the PTS information + and only uses 10fps for each + I frame decoded */ + if (p_last_vf) { + vf->pts = 0; + vf->pts_us64 = 0; + } + frame_dur = 96000 / 10; + } +#endif + vf->signal_type = 0; + vf->index = display_buff_id; + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&buffer_spec[display_buff_id]); + set_frame_info(vf); + + if (((error_recovery_mode & 2) && error) + || (!first_i_recieved + && (slice_type != SLICE_TYPE_I))) { + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + } else { + p_last_vf = vf; + first_i_recieved = 1; + kfifo_put(&display_q, + (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } + break; + + case CMD_DEBUG: + pr_info("M: core_status 0x%08x 0x%08x; ", + READ_VREG(CORE_STATUS_M), READ_VREG(CORE_STATUS_S)); + switch (READ_VREG(MAILBOX_DATA_0)) { + case 1: + pr_info("H264_BUFFER_INFO_INDEX = 0x%x\n", + READ_VREG(MAILBOX_DATA_1)); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 2: + pr_info("H264_BUFFER_INFO_DATA = 0x%x\n", + READ_VREG(MAILBOX_DATA_1)); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 3: + pr_info("REC_CANVAS_ADDR = 0x%x\n", + READ_VREG(MAILBOX_DATA_1)); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 4: + pr_info("after DPB_MMCO\n"); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 5: + pr_info("MBY = 0x%x, S_MBXY = 0x%x\n", + READ_VREG(MAILBOX_DATA_1), + READ_VREG(0x2c07)); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 6: + pr_info("after FIFO_OUT_FRAME\n"); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 7: + pr_info("after RELEASE_EXCEED_REF_BUFF\n"); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + break; + case 0x5a: + pr_info("\n"); + break; + default: + pr_info("\n"); + break; + } + break; + + default: + break; + } + + return IRQ_HANDLED; +} + +#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ +static irqreturn_t vh264_4k2k_vdec2_isr(int irq, void *dev_id) +{ + int ret = READ_VREG(VDEC2_MAILBOX_COMMAND); + + switch (ret & 0xff) { + case CMD_DEBUG: + pr_info("S: core_status 0x%08x 0x%08x; ", + READ_VREG(CORE_STATUS_M), READ_VREG(CORE_STATUS_S)); + switch (READ_VREG(VDEC2_MAILBOX_DATA_0)) { + case 1: + pr_info("H264_BUFFER_INFO_INDEX = 0x%x\n", + READ_VREG(VDEC2_MAILBOX_DATA_1)); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 2: + pr_info("H264_BUFFER_INFO_DATA = 0x%x\n", + READ_VREG(VDEC2_MAILBOX_DATA_1)); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 3: + pr_info("REC_CANVAS_ADDR = 0x%x\n", + READ_VREG(VDEC2_MAILBOX_DATA_1)); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 4: + pr_info("after DPB_MMCO\n"); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 5: + pr_info("MBY = 0x%x, M/S_MBXY = 0x%x-0x%x\n", + READ_VREG(VDEC2_MAILBOX_DATA_1), + READ_VREG(0xc07), READ_VREG(0x2c07)); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 6: + pr_info("after FIFO_OUT_FRAME\n"); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 7: + pr_info("after RELEASE_EXCEED_REF_BUFF\n"); + WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED); + break; + case 0x5a: + pr_info("\n"); + break; + default: + pr_info("\n"); + break; + } + break; + + default: + break; + } + + return IRQ_HANDLED; +} +#endif + +static void vh264_4k2k_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + enum receviver_start_e state = RECEIVER_INACTIVE; + + if (vf_get_receiver(PROVIDER_NAME)) { + state = vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); + if ((state == RECEIVER_STATE_NULL) + || (state == RECEIVER_STATE_NONE)) + state = RECEIVER_INACTIVE; + } else + state = RECEIVER_INACTIVE; + + /* error watchdog */ + if (((READ_VREG(VLD_MEM_VIFIFO_CONTROL) & 0x100) == 0) &&/* dec has in*/ + (state == RECEIVER_INACTIVE) && /* rec has no buf to recycle */ + (kfifo_is_empty(&display_q)) && /* no buf in display queue */ + (kfifo_is_empty(&recycle_q)) && /* no buf to recycle */ + (READ_VREG(MS_ID) & 0x100) +#ifdef CONFIG_H264_2K4K_SINGLE_CORE + && (READ_VREG(VDEC2_MS_ID) & 0x100)/* with both decoder + have started decoding */ +#endif + && first_i_recieved) { + if (++error_watchdog_count == ERROR_RESET_COUNT) { + /* and it lasts for a while */ + pr_info("H264 4k2k decoder fatal error watchdog.\n"); + fatal_error = DECODER_FATAL_ERROR_UNKNOWN; + } + } else + error_watchdog_count = 0; + + if (READ_VREG(FATAL_ERROR) != 0) { + pr_info("H264 4k2k decoder ucode fatal error.\n"); + fatal_error = DECODER_FATAL_ERROR_UNKNOWN; + WRITE_VREG(FATAL_ERROR, 0); + } + + while (!kfifo_is_empty(&recycle_q) && + (READ_VREG(BUFFER_RECYCLE) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index >= 0) + && (vf->index < DECODE_BUFFER_NUM_MAX) + && (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(BUFFER_RECYCLE, vf->index + 1); + vf->index = DECODE_BUFFER_NUM_MAX; + } + + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } + } + if (first_i_recieved &&/*do switch after first i frame ready.*/ + frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + pr_info("H264 4k2k resolution changed!!\n"); + if (vdec_source_changed(VFORMAT_H264_4K2K, + frame_width, frame_height, fps) > 0)/*changed clk ok*/ + saved_resolution = frame_width * frame_height * fps; + } + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vh264_4k2k_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = frame_width; + vstatus->height = frame_height; + if (frame_dur != 0) + vstatus->fps = 96000 / frame_dur; + else + vstatus->fps = -1; + vstatus->error_count = 0; + vstatus->status = stat | fatal_error; + return 0; +} + +int vh264_4k2k_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) +{ + if (trickmode == TRICKMODE_I) { + WRITE_VREG(DECODE_MODE, 1); + trickmode_i = 1; + } else if (trickmode == TRICKMODE_NONE) { + WRITE_VREG(DECODE_MODE, 0); + trickmode_i = 0; + } + + return 0; +} + +static void H264_DECODE_INIT(void) +{ + int i; + + WRITE_VREG(GCLK_EN, 0x3ff); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + /* fill_weight_pred */ + WRITE_VREG(MC_MPORT_CTRL, 0x0300); + for (i = 0; i < 192; i++) + WRITE_VREG(MC_MPORT_DAT, 0x100); + WRITE_VREG(MC_MPORT_CTRL, 0); + + WRITE_VREG(MB_WIDTH, 0xff); /* invalid mb_width */ + + /* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */ + WRITE_VREG(SLICE_START_BYTE_01, 0x00000000); + WRITE_VREG(SLICE_START_BYTE_23, 0x01010000); + /* set to mpeg2 to enable mismatch logic */ + WRITE_VREG(MPEG1_2_REG, 1); + WRITE_VREG(VLD_ERROR_MASK, + 0x1011); + + /* Config MCPU Amrisc interrupt */ + WRITE_VREG(ASSIST_AMR1_INT0, 0x1); /* viu_vsync_int */ + WRITE_VREG(ASSIST_AMR1_INT1, 0x5); /* mbox_isr */ + WRITE_VREG(ASSIST_AMR1_INT2, 0x8); /* vld_isr */ + /* WRITE_VREG(ASSIST_AMR1_INT3, 0x15); // vififo_empty */ + WRITE_VREG(ASSIST_AMR1_INT4, 0xd); /* rv_ai_mb_finished_int */ + WRITE_VREG(ASSIST_AMR1_INT7, 0x14); /* dcac_dma_done */ + WRITE_VREG(ASSIST_AMR1_INT8, 0x15); /* vififo_empty */ + + /* Config MCPU Amrisc interrupt */ + WRITE_VREG(ASSIST_AMR1_INT5, 0x9); /* MCPU interrupt */ + WRITE_VREG(ASSIST_AMR1_INT6, 0x17); /* CCPU interrupt */ + + WRITE_VREG(CPC_P, 0xc00); /* CCPU Code will start from 0xc00 */ + WRITE_VREG(CINT_VEC_BASE, (0xc20 >> 5)); + WRITE_VREG(POWER_CTL_VLD, (1 << 10) | /* disable cabac_step_2 */ + (1 << 9) | /* viff_drop_flag_en */ + (1 << 6)); /* h264_000003_en */ + WRITE_VREG(M4_CONTROL_REG, (1 << 13)); /* H264_DECODE_INFO - h264_en */ + + WRITE_VREG(CANVAS_START, AMVDEC_H264_4K2K_CANVAS_INDEX); + /* Start Address of Workspace (UCODE, temp_data...) */ + WRITE_VREG(WORKSPACE_START, + video_domain_addr(work_space_adr)); + /* Clear all sequence parameter set available */ + WRITE_VREG(SPS_STATUS, 0); + /* Clear all picture parameter set available */ + WRITE_VREG(PPS_STATUS, 0); + /* Set current microcode to NULL */ + WRITE_VREG(CURRENT_UCODE, 0xff); + /* Set current SPS/PPS to NULL */ + WRITE_VREG(CURRENT_SPS_PPS, 0xffff); + /* Set decode status to DECODE_START_HEADER */ + WRITE_VREG(DECODE_STATUS, 1); +} + +static void H264_DECODE2_INIT(void) +{ + int i; + + WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); + + WRITE_VREG(DOS_SW_RESET2, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET2, 0); + + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + + WRITE_VREG(DOS_SW_RESET2, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET2, 0); + + WRITE_VREG(DOS_SW_RESET2, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET2, 0); + + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + + /* fill_weight_pred */ + WRITE_VREG(VDEC2_MC_MPORT_CTRL, 0x0300); + for (i = 0; i < 192; i++) + WRITE_VREG(VDEC2_MC_MPORT_DAT, 0x100); + WRITE_VREG(VDEC2_MC_MPORT_CTRL, 0); + + WRITE_VREG(VDEC2_MB_WIDTH, 0xff); /* invalid mb_width */ + + /* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */ + WRITE_VREG(VDEC2_SLICE_START_BYTE_01, 0x00000000); + WRITE_VREG(VDEC2_SLICE_START_BYTE_23, 0x01010000); + /* set to mpeg2 to enable mismatch logic */ + WRITE_VREG(VDEC2_MPEG1_2_REG, 1); + /* disable COEF_GT_64 , error_m4_table and voff_rw_err */ + WRITE_VREG(VDEC2_VLD_ERROR_MASK, + 0x1011); + + /* Config MCPU Amrisc interrupt */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT0, 0x1);/* viu_vsync_int */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT1, 0x5);/* mbox_isr */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT2, 0x8);/* vld_isr */ + /* WRITE_VREG(VDEC2_ASSIST_AMR1_INT3, 0x15); // vififo_empty */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT4, 0xd);/* rv_ai_mb_finished_int */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT7, 0x14);/* dcac_dma_done */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT8, 0x15);/* vififo_empty */ + + /* Config MCPU Amrisc interrupt */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT5, 0x9);/* MCPU interrupt */ + WRITE_VREG(VDEC2_ASSIST_AMR1_INT6, 0x17);/* CCPU interrupt */ + + WRITE_VREG(VDEC2_CPC_P, 0xc00); /* CCPU Code will start from 0xc00 */ + WRITE_VREG(VDEC2_CINT_VEC_BASE, (0xc20 >> 5)); + WRITE_VREG(VDEC2_POWER_CTL_VLD, (1 << 10) |/* disable cabac_step_2 */ + (1 << 9) | /* viff_drop_flag_en */ + (1 << 6)); /* h264_000003_en */ + /* H264_DECODE_INFO - h264_en */ + WRITE_VREG(VDEC2_M4_CONTROL_REG, (1 << 13)); + + WRITE_VREG(VDEC2_CANVAS_START, AMVDEC_H264_4K2K_CANVAS_INDEX); + /* Start Address of Workspace (UCODE, temp_data...) */ + WRITE_VREG(VDEC2_WORKSPACE_START, + video_domain_addr(work_space_adr)); + /* Clear all sequence parameter set available */ + WRITE_VREG(VDEC2_SPS_STATUS, 0); + /* Clear all picture parameter set available */ + WRITE_VREG(VDEC2_PPS_STATUS, 0); + /* Set current microcode to NULL */ + WRITE_VREG(VDEC2_CURRENT_UCODE, 0xff); + /* Set current SPS/PPS to NULL */ + WRITE_VREG(VDEC2_CURRENT_SPS_PPS, 0xffff); + /* Set decode status to DECODE_START_HEADER */ + WRITE_VREG(VDEC2_DECODE_STATUS, 1); +} + +static void vh264_4k2k_prot_init(void) +{ + /* clear mailbox interrupt */ +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (!H264_4K2K_SINGLE_CORE) + WRITE_VREG(VDEC2_ASSIST_MBOX0_CLR_REG, 1); +#endif + WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (!H264_4K2K_SINGLE_CORE) + WRITE_VREG(VDEC2_ASSIST_MBOX0_MASK, 1); +#endif + WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 1); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + H264_DECODE_INIT(); + if (!H264_4K2K_SINGLE_CORE) + H264_DECODE2_INIT(); + + WRITE_VREG(DOS_SW_RESET0, (1 << 11)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + if (!H264_4K2K_SINGLE_CORE) { + WRITE_VREG(DOS_SW_RESET2, (1 << 11)); + WRITE_VREG(DOS_SW_RESET2, 0); + + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + } + + WRITE_VREG(MAILBOX_COMMAND, 0); + WRITE_VREG(BUFFER_RECYCLE, 0); + + if (!H264_4K2K_SINGLE_CORE) { + WRITE_VREG(VDEC2_MAILBOX_COMMAND, 0); + WRITE_VREG(VDEC2_BUFFER_RECYCLE, 0); + } + + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); + if (!H264_4K2K_SINGLE_CORE) + CLEAR_VREG_MASK(VDEC2_MDEC_PIC_DC_CTRL, 1 << 17); + + /* set VDEC Master/ID 0 */ + WRITE_VREG(MS_ID, (1 << 7) | (0 << 0)); + if (!H264_4K2K_SINGLE_CORE) { + /* set VDEC2 Slave/ID 0 */ + WRITE_VREG(VDEC2_MS_ID, (0 << 7) | (1 << 0)); + } + WRITE_VREG(DECODE_SKIP_PICTURE, 0); + if (!H264_4K2K_SINGLE_CORE) + WRITE_VREG(VDEC2_DECODE_SKIP_PICTURE, 0); + + WRITE_VREG(PRE_MASTER_UPDATE_TIMES, 0); + WRITE_VREG(SLAVE_WAIT_DPB_UPDATE, 0); + WRITE_VREG(SLAVE_REF_DPB, 0); + WRITE_VREG(SAVE_MVC_ENTENSION_0, 0); + WRITE_VREG(SAVE_I_POC, 0); + WRITE_VREG(CORE_STATUS_M, 0); + WRITE_VREG(CORE_STATUS_S, 0); + WRITE_VREG(SAVE_ref_status_view_0, 0); + WRITE_VREG(SAVE_ref_status_view_1, 0); + WRITE_VREG(ALLOC_INFO_0, 0); + WRITE_VREG(ALLOC_INFO_1, 0); + WRITE_VREG(FATAL_ERROR, 0); + + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); + if (!H264_4K2K_SINGLE_CORE) + SET_VREG_MASK(VDEC2_MDEC_PIC_DC_CTRL, 1 << 17); + + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); + if (!H264_4K2K_SINGLE_CORE) { + WRITE_VREG(VDEC2_MDEC_PIC_DC_THRESH, 0x404038aa); + /*TODO for M8 + amvenc_dos_top_reg_fix();*/ + } +#ifdef DOUBLE_WRITE + WRITE_VREG(MDEC_DOUBLEW_CFG0, (0 << 31) | /* half y address */ + (1 << 30) | /* 0:No Merge 1:Automatic Merge */ + (0 << 28) | /* Field Picture, 0x:no skip + 10:top only + 11:bottom only */ + (0 << 27) | /* Source from, 1:MCW 0:DBLK */ + (0 << 24) | /* Endian Control for Chroma */ + (0 << 18) | /* DMA ID */ + (0 << 12) | /* DMA Burst Number */ + (0 << 11) | /* DMA Urgent */ + (0 << 10) | /* 1:Round 0:Truncation */ + (1 << 9) | /* Size by vertical, 0:original size + 1: 1/2 shrunken size */ + (1 << 8) | /* Size by horizontal, 0:original size + 1: 1/2 shrunken size */ + (0 << 6) | /* Pixel sel by vertical, 0x:1/2 + 10:up + 11:down */ + (0 << 4) | /* Pixel sel by horizontal, 0x:1/2 + 10:left + 11:right */ + (0 << 1) | /* Endian Control for Luma */ + (1 << 0)); /* Double Write Enable */ + if (!H264_4K2K_SINGLE_CORE) { + WRITE_VREG(VDEC2_MDEC_DOUBLEW_CFG0, + (0 << 31) | /* half y address */ + (1 << 30) | /* 0:No Merge + 1:Automatic Merge */ + (0 << 28) | /* Field Picture, 0x:no skip + 10:top only + 11:bottom only */ + (0 << 27) | /* Source from, 1:MCW 0:DBLK */ + (0 << 24) | /* Endian Control for Chroma */ + (0 << 18) | /* DMA ID */ + (0 << 12) | /* DMA Burst Number */ + (0 << 11) | /* DMA Urgent */ + (0 << 10) | /* 1:Round 0:Truncation */ + (1 << 9) | /* Size by vertical, + 0:original size + 1: 1/2 shrunken size */ + (1 << 8) | /* Size by horizontal, + 0:original size + 1: 1/2 shrunken size */ + (0 << 6) | /* Pixel sel by vertical, + 0x:1/2 + 10:up + 11:down */ + (0 << 4) | /* Pixel sel by horizontal, + 0x:1/2 + 10:left + 11:right */ + (0 << 1) | /* Endian Control for Luma */ + (1 << 0)); /* Double Write Enable */ + } +#endif +} + +static void vh264_4k2k_local_init(void) +{ + int i; + +#ifdef DEBUG_PTS + pts_missed = 0; + pts_hit = 0; +#endif + mb_width_old = 0; + mb_height_old = 0; + saved_resolution = 0; + vh264_4k2k_rotation = + (((unsigned long) vh264_4k2k_amstream_dec_info.param) >> 16) + & 0xffff; + frame_width = vh264_4k2k_amstream_dec_info.width; + frame_height = vh264_4k2k_amstream_dec_info.height; + frame_dur = + (vh264_4k2k_amstream_dec_info.rate == + 0) ? 3600 : vh264_4k2k_amstream_dec_info.rate; + if (frame_width && frame_height) + frame_ar = frame_height * 0x100 / frame_width; + sync_outside = ((unsigned long) vh264_4k2k_amstream_dec_info.param + & 0x02) >> 1; + error_watchdog_count = 0; + + pr_info("H264_4K2K: decinfo: %dx%d rate=%d\n", + frame_width, frame_height, + frame_dur); + + if (frame_dur == 0) + frame_dur = 96000 / 24; + + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + vfbuf_use[i] = 0; + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &vfpool[i]; + vfpool[i].index = DECODE_BUFFER_NUM_MAX; + kfifo_put(&newframe_q, vf); + } + + reserved_buffer = 0; + p_last_vf = NULL; + first_i_recieved = 0; + INIT_WORK(&alloc_work, do_alloc_work); + + return; +} + +static s32 vh264_4k2k_init(void) +{ + int ret = -1, size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + pr_info("\nvh264_4k2k_init\n"); + + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + vh264_4k2k_local_init(); + + amvdec_enable(); + + /* -- ucode loading (amrisc and swap code) */ + mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, &mc_dma_handle, GFP_KERNEL); + if (!mc_cpu_addr) { + amvdec_disable(); + vfree(buf); + pr_err("vh264_4k2k init: Can not allocate mc memory.\n"); + return -ENOMEM; + } + + WRITE_VREG(AV_SCRATCH_L, mc_dma_handle); + if (!H264_4K2K_SINGLE_CORE) + WRITE_VREG(VDEC2_AV_SCRATCH_L, mc_dma_handle); + + if (H264_4K2K_SINGLE_CORE) + size = get_firmware_data(VIDEO_DEC_H264_4k2K_SINGLE, buf); + + else + size = get_firmware_data(VIDEO_DEC_H264_4k2K, buf); + + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf) < 0) { + amvdec_disable(); + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); + mc_cpu_addr = NULL; + return -EBUSY; + } + + if (!H264_4K2K_SINGLE_CORE) { + amvdec2_enable(); + + if (amvdec2_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf) < 0) { + amvdec_disable(); + amvdec2_disable(); + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); + mc_cpu_addr = NULL; + return -EBUSY; + } + } + + /*header*/ + memcpy((u8 *) mc_cpu_addr, buf + 0x1000, 0x1000); + + /*mmco*/ + memcpy((u8 *) mc_cpu_addr + 0x1000, buf + 0x2000, 0x2000); + + /*slice*/ + memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); + + if (ret < 0) { + amvdec_disable(); + if (!H264_4K2K_SINGLE_CORE) + amvdec2_disable(); + pr_info("vh264_4k2k load firmware error.\n"); + if (mc_cpu_addr) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); + mc_cpu_addr = NULL; + } + + return -EBUSY; + } + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vh264_4k2k_prot_init(); + + if (vdec_request_irq(VDEC_IRQ_1, vh264_4k2k_isr, + "vh264_4k2k-irq", (void *)vh264_4k2k_dec_id)) { + pr_info("vh264_4k2k irq register error.\n"); + amvdec_disable(); + if (!H264_4K2K_SINGLE_CORE) + amvdec2_disable(); + + return -ENOENT; + } +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (!H264_4K2K_SINGLE_CORE) { + if (vdec_request_irq(VDEC_IRQ_0, vh264_4k2k_vdec2_isr, + "vh264_4k2k-vdec2-irq", + (void *)vh264_4k2k_dec_id2)) { + pr_info("vh264_4k2k irq register error.\n"); + vdec_free_irq(VDEC_IRQ_1, (void *)vh264_4k2k_dec_id); + amvdec_disable(); + amvdec2_disable(); + return -ENOENT; + } + } +#endif + + stat |= STAT_ISR_REG; + + vf_provider_init(&vh264_4k2k_vf_prov, PROVIDER_NAME, + &vh264_4k2k_vf_provider, NULL); + vf_reg_provider(&vh264_4k2k_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long) + vh264_4k2k_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong) (&recycle_timer); + recycle_timer.function = vh264_4k2k_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + if (!H264_4K2K_SINGLE_CORE) + amvdec2_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int vh264_4k2k_stop(void) +{ + int i; + u32 disp_addr = 0xffffffff; + struct canvas_s cur_canvas; + + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + if (!H264_4K2K_SINGLE_CORE) + amvdec2_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 0); + if (!H264_4K2K_SINGLE_CORE) + WRITE_VREG(VDEC2_ASSIST_MBOX0_MASK, 0); + + vdec_free_irq(VDEC_IRQ_1, (void *)vh264_4k2k_dec_id); +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (!H264_4K2K_SINGLE_CORE) + vdec_free_irq(VDEC_IRQ_0, (void *)vh264_4k2k_dec_id2); +#endif + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vh264_4k2k_vf_prov); + stat &= ~STAT_VF_HOOK; + } +#ifdef DOUBLE_WRITE + WRITE_VREG(MDEC_DOUBLEW_CFG0, 0); + if (!H264_4K2K_SINGLE_CORE) + WRITE_VREG(VDEC2_MDEC_DOUBLEW_CFG0, 0); +#endif + + if (stat & STAT_MC_LOAD) { + if (mc_cpu_addr != NULL) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); + mc_cpu_addr = NULL; + } + + stat &= ~STAT_MC_LOAD; + } + + amvdec_disable(); + if (!H264_4K2K_SINGLE_CORE) + amvdec2_disable(); +#ifdef CONFIG_VSYNC_RDMA + msleep(100); +#endif + if (!get_blackout_policy()) { + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = cur_canvas.addr; + } + + for (i = 0; i < ARRAY_SIZE(buffer_spec); i++) { + if (buffer_spec[i].phy_addr) { + if (disp_addr == + (u32)buffer_spec[i].phy_addr) + pr_info("Skip releasing CMA buffer %d\n", i); + else { + codec_mm_free_for_dma(MEM_NAME, + buffer_spec[i].phy_addr); + buffer_spec[i].phy_addr = 0; + buffer_spec[i].alloc_pages = NULL; + buffer_spec[i].alloc_count = 0; + } + } + + if (buffer_spec[i].y_addr == disp_addr) { + pr_info("4K2K dec stop, keeping buffer index = %d\n", + i); + } + } + + return 0; +} + +void vh264_4k_free_cmabuf(void) +{ + int i; + if (atomic_read(&vh264_4k2k_active)) + return; + mutex_lock(&vh264_4k2k_mutex); + for (i = 0; i < ARRAY_SIZE(buffer_spec); i++) { + if (buffer_spec[i].phy_addr) { + codec_mm_free_for_dma(MEM_NAME, + buffer_spec[i].phy_addr); + buffer_spec[i].phy_addr = 0; + buffer_spec[i].alloc_pages = NULL; + buffer_spec[i].alloc_count = 0; + pr_info("force free CMA buffer %d\n", i); + } + } + mutex_unlock(&vh264_4k2k_mutex); +} + +#if 0 /* (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8) && (HAS_HDEC) */ +/* extern void AbortEncodeWithVdec2(int abort); */ +#endif + +static int amvdec_h264_4k2k_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + pr_info("amvdec_h264_4k2k probe start.\n"); + + mutex_lock(&vh264_4k2k_mutex); + + fatal_error = 0; + + if (pdata == NULL) { + pr_info("\namvdec_h264_4k2k memory resource undefined.\n"); + mutex_unlock(&vh264_4k2k_mutex); + return -EFAULT; + } + + work_space_adr = pdata->mem_start; + decoder_buffer_start = pdata->mem_start + DECODER_WORK_SPACE_SIZE; + decoder_buffer_end = pdata->mem_end + 1; + + if (pdata->sys_info) + vh264_4k2k_amstream_dec_info = *pdata->sys_info; + cma_dev = pdata->cma_dev; + + pr_info("H.264 4k2k decoder mem resource 0x%x -- 0x%x\n", + (u32)decoder_buffer_start, (u32)decoder_buffer_end); + pr_info(" sysinfo: %dx%d, rate = %d, param = 0x%lx\n", + vh264_4k2k_amstream_dec_info.width, + vh264_4k2k_amstream_dec_info.height, + vh264_4k2k_amstream_dec_info.rate, + (unsigned long) vh264_4k2k_amstream_dec_info.param); + + if (!H264_4K2K_SINGLE_CORE) { +#if 1 /* (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8) && (has_hdec()) */ + int count = 0; + if (get_vdec2_usage() != USAGE_NONE) + /* AbortEncodeWithVdec2(1); */ /*TODO*/ + while ((get_vdec2_usage() != USAGE_NONE) && (count < 10)) { + msleep(50); + count++; + } + + if (get_vdec2_usage() != USAGE_NONE) { + pr_info + ("\namvdec_h264_4k2k - vdec2 is used by encode now.\n"); + mutex_unlock(&vh264_4k2k_mutex); + return -EBUSY; + } +#endif + + if (vdec_on(VDEC_2)) { /* ++++ */ + vdec_poweroff(VDEC_2); /* ++++ */ + mdelay(10); + } +#if 1 /* (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8) && (has_hdec()) */ + set_vdec2_usage(USAGE_DEC_4K2K); + /* AbortEncodeWithVdec2(0); */ /*TODO*/ +#endif + vdec_poweron(VDEC_2); + } + + + if (!H264_4K2K_SINGLE_CORE) + vdec2_power_mode(1); + + pdata->dec_status = vh264_4k2k_dec_status; + if (H264_4K2K_SINGLE_CORE) + pdata->set_trickmode = vh264_4k2k_set_trickmode; + + if (vh264_4k2k_init() < 0) { + pr_info("\namvdec_h264_4k2k init failed.\n"); +#if 1/* (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8) && (has_hdec()) */ + if (!H264_4K2K_SINGLE_CORE) { + set_vdec2_usage(USAGE_NONE); + /*AbortEncodeWithVdec2(0);*/ /*TODO*/ + } +#endif + mutex_unlock(&vh264_4k2k_mutex); + return -ENODEV; + } +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ + request_vpu_clk_vmod(360000000, VPU_VIU_VD1); +#endif + + if (probe_callback) + probe_callback(); + /*set the max clk for smooth playing...*/ + vdec_source_changed(VFORMAT_H264_4K2K, + 4096, 2048, 30); + atomic_set(&vh264_4k2k_active, 1); + mutex_unlock(&vh264_4k2k_mutex); + + return 0; +} + +static int amvdec_h264_4k2k_remove(struct platform_device *pdev) +{ + cancel_work_sync(&alloc_work); + + mutex_lock(&vh264_4k2k_mutex); + atomic_set(&vh264_4k2k_active, 0); + + vh264_4k2k_stop(); + + vdec_source_changed(VFORMAT_H264_4K2K , 0 , 0 , 0); + + if (!H264_4K2K_SINGLE_CORE) { + vdec_poweroff(VDEC_2); +#if 1/*(MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8) && (has_hdec())*/ + set_vdec2_usage(USAGE_NONE); +#endif + } +#ifdef DEBUG_PTS + pr_info("pts missed %ld, pts hit %ld, duration %d\n", + pts_missed, pts_hit, frame_dur); +#endif + + if (remove_callback) + remove_callback(); + + mutex_unlock(&vh264_4k2k_mutex); + + pr_info("amvdec_h264_4k2k_remove\n"); + return 0; +} + +void vh264_4k2k_register_module_callback(void (*enter_func)(void), + void (*remove_func)(void)) +{ + probe_callback = enter_func; + remove_callback = remove_func; +} +EXPORT_SYMBOL(vh264_4k2k_register_module_callback); + +/****************************************/ + +static struct platform_driver amvdec_h264_4k2k_driver = { + .probe = amvdec_h264_4k2k_probe, + .remove = amvdec_h264_4k2k_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_h264_4k2k_profile = { + .name = "h264_4k2k", + .profile = "" +}; + +static int __init amvdec_h264_4k2k_driver_init_module(void) +{ + pr_debug("amvdec_h264_4k2k module init\n"); + + if (platform_driver_register(&amvdec_h264_4k2k_driver)) { + pr_err("failed to register amvdec_h264_4k2k driver\n"); + return -ENODEV; + } + if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB) + vcodec_profile_register(&amvdec_h264_4k2k_profile); + + return 0; +} + +static void __exit amvdec_h264_4k2k_driver_remove_module(void) +{ + pr_debug("amvdec_h264_4k2k module remove.\n"); + + platform_driver_unregister(&amvdec_h264_4k2k_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_h264_4k2k stat\n"); + +module_param(error_recovery_mode, uint, 0664); +MODULE_PARM_DESC(error_recovery_mode, "\n amvdec_h264 error_recovery_mode\n"); + +module_init(amvdec_h264_4k2k_driver_init_module); +module_exit(amvdec_h264_4k2k_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC h264_4k2k Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c new file mode 100644 index 000000000000..1683c3199018 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c @@ -0,0 +1,1594 @@ +/* + * drivers/amlogic/amports/vh264mvc.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "../../../stream_input/amports/amports_priv.h" +#include "../utils/vdec.h" +#include "../utils/amvdec.h" + +#define TIME_TASK_PRINT_ENABLE 0x100 +#define PUT_PRINT_ENABLE 0x200 + +#define DRIVER_NAME "amvdec_h264mvc" +#define MODULE_NAME "amvdec_h264mvc" + +#define HANDLE_h264mvc_IRQ + +#define DEBUG_PTS +#define DEBUG_SKIP + +#define PUT_INTERVAL (HZ/100) + +#define STAT_TIMER_INIT 0x01 +#define STAT_MC_LOAD 0x02 +#define STAT_ISR_REG 0x04 +#define STAT_VF_HOOK 0x08 +#define STAT_TIMER_ARM 0x10 +#define STAT_VDEC_RUN 0x20 + +#define DROPPING_THREAD_HOLD 4 +#define DROPPING_FIRST_WAIT 16 +#define DISPLAY_INVALID_POS -65536 + +#define INIT_DROP_FRAME_CNT 8 + +static int vh264mvc_vf_states(struct vframe_states *states, void *); +static struct vframe_s *vh264mvc_vf_peek(void *); +static struct vframe_s *vh264mvc_vf_get(void *); +static void vh264mvc_vf_put(struct vframe_s *, void *); +static int vh264mvc_event_cb(int type, void *data, void *private_data); + +static void vh264mvc_prot_init(void); +static void vh264mvc_local_init(void); +static void vh264mvc_put_timer_func(unsigned long arg); + +static const char vh264mvc_dec_id[] = "vh264mvc-dev"; + +#define PROVIDER_NAME "decoder.h264mvc" + +static const struct vframe_operations_s vh264mvc_vf_provider = { + .peek = vh264mvc_vf_peek, + .get = vh264mvc_vf_get, + .put = vh264mvc_vf_put, + .event_cb = vh264mvc_event_cb, + .vf_states = vh264mvc_vf_states, +}; + +static struct vframe_provider_s vh264mvc_vf_prov; + +static u32 frame_width, frame_height, frame_dur; +static u32 saved_resolution; +static struct timer_list recycle_timer; +static u32 stat; +static u32 pts_outside; +static u32 sync_outside; +static u32 vh264mvc_ratio; +static u32 h264mvc_ar; +static u32 no_dropping_cnt; +static s32 init_drop_cnt; + +#ifdef DEBUG_SKIP +static unsigned long view_total, view_dropped; +#endif + +#ifdef DEBUG_PTS +static unsigned long pts_missed, pts_hit; +#endif + +static atomic_t vh264mvc_active = ATOMIC_INIT(0); +static struct work_struct error_wd_work; + +static struct dec_sysinfo vh264mvc_amstream_dec_info; +static dma_addr_t mc_dma_handle; +static void *mc_cpu_addr; + +static DEFINE_SPINLOCK(lock); + +static int vh264mvc_stop(void); +static s32 vh264mvc_init(void); + +/*************************** +* new +***************************/ + +/* bit[3:0] command : */ +/* 0 - command finished */ +/* (DATA0 - {level_idc_mmco, max_reference_frame_num, width, height} */ +/* 1 - alloc view_0 display_buffer and reference_data_area */ +/* 2 - alloc view_1 display_buffer and reference_data_area */ +#define MAILBOX_COMMAND AV_SCRATCH_0 +#define MAILBOX_DATA_0 AV_SCRATCH_1 +#define MAILBOX_DATA_1 AV_SCRATCH_2 +#define MAILBOX_DATA_2 AV_SCRATCH_3 +#define CANVAS_START AV_SCRATCH_6 +#define BUFFER_RECYCLE AV_SCRATCH_7 +#define DROP_CONTROL AV_SCRATCH_8 +#define PICTURE_COUNT AV_SCRATCH_9 +#define DECODE_STATUS AV_SCRATCH_A +#define SPS_STATUS AV_SCRATCH_B +#define PPS_STATUS AV_SCRATCH_C +#define SIM_RESERV_D AV_SCRATCH_D +#define WORKSPACE_START AV_SCRATCH_E +#define SIM_RESERV_F AV_SCRATCH_F +#define DECODE_ERROR_CNT AV_SCRATCH_G +#define CURRENT_UCODE AV_SCRATCH_H +#define CURRENT_SPS_PPS AV_SCRATCH_I/* bit[15:9]-SPS, bit[8:0]-PPS */ +#define DECODE_SKIP_PICTURE AV_SCRATCH_J +#define UCODE_START_ADDR AV_SCRATCH_K +#define SIM_RESERV_L AV_SCRATCH_L +#define REF_START_VIEW_0 AV_SCRATCH_M +#define REF_START_VIEW_1 AV_SCRATCH_N + +/******************************************** + * Mailbox command + ********************************************/ +#define CMD_FINISHED 0 +#define CMD_ALLOC_VIEW_0 1 +#define CMD_ALLOC_VIEW_1 2 +#define CMD_FRAME_DISPLAY 3 +#define CMD_FATAL_ERROR 4 + +#define CANVAS_INDEX_START 0x78 +/* /AMVDEC_H264MVC_CANVAS_INDEX */ + +#define MC_TOTAL_SIZE (28*SZ_1K) +#define MC_SWAP_SIZE (4*SZ_1K) + +unsigned DECODE_BUFFER_START = 0x00200000; +unsigned DECODE_BUFFER_END = 0x05000000; + +#define DECODE_BUFFER_NUM_MAX 16 +#define DISPLAY_BUFFER_NUM 4 + +static unsigned int ANC_CANVAS_ADDR; +static unsigned int index; +static unsigned int dpb_start_addr[3]; +static unsigned int ref_start_addr[2]; +static unsigned int max_dec_frame_buffering[2]; +static unsigned int total_dec_frame_buffering[2]; +static unsigned int level_idc, max_reference_frame_num, mb_width, mb_height; +static unsigned int dpb_size, ref_size; + +static int display_buff_id; +static int display_view_id; +static int display_POC; +static int stream_offset; + +#define video_domain_addr(adr) (adr&0x7fffffff) +static unsigned work_space_adr; +static unsigned work_space_size = 0xa0000; + +struct buffer_spec_s { + unsigned int y_addr; + unsigned int u_addr; + unsigned int v_addr; + + int y_canvas_index; + int u_canvas_index; + int v_canvas_index; +}; +static struct buffer_spec_s buffer_spec0[DECODE_BUFFER_NUM_MAX + + DISPLAY_BUFFER_NUM]; +static struct buffer_spec_s buffer_spec1[DECODE_BUFFER_NUM_MAX + + DISPLAY_BUFFER_NUM]; + +/* + dbg_mode: + bit 0: 1, print debug information + bit 4: 1, recycle buffer without displaying; + bit 5: 1, buffer single frame step , set dbg_cmd to 1 to step + +*/ +static int dbg_mode; +static int dbg_cmd; +static int view_mode = + 3; /* 0, left; 1 ,right ; 2, left<->right 3, right<->left */ +static int drop_rate = 2; +static int drop_thread_hold; +/**/ +#define MVC_BUF_NUM (DECODE_BUFFER_NUM_MAX+DISPLAY_BUFFER_NUM) +struct mvc_buf_s { + struct list_head list; + struct vframe_s vframe; + int display_POC; + int view0_buff_id; + int view1_buff_id; + int view0_drop; + int view1_drop; + int stream_offset; + unsigned pts; +} /*mvc_buf_t */; + +#define spec2canvas(x) \ + (((x)->v_canvas_index << 16) | \ + ((x)->u_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) + +#define to_mvcbuf(vf) \ + container_of(vf, struct mvc_buf_s, vframe) + +static int vf_buf_init_flag; + +static void init_vf_buf(void) +{ + + vf_buf_init_flag = 1; +} + +static void uninit_vf_buf(void) +{ + +} + +/* #define QUEUE_SUPPORT */ + +struct mvc_info_s { + int view0_buf_id; + int view1_buf_id; + int view0_drop; + int view1_drop; + int display_pos; + int used; + int slot; + unsigned stream_offset; +}; + +#define VF_POOL_SIZE 20 +static struct vframe_s vfpool[VF_POOL_SIZE]; +static struct mvc_info_s vfpool_idx[VF_POOL_SIZE]; +static s32 view0_vfbuf_use[DECODE_BUFFER_NUM_MAX]; +static s32 view1_vfbuf_use[DECODE_BUFFER_NUM_MAX]; + +static s32 fill_ptr, get_ptr, putting_ptr, put_ptr; +static s32 dirty_frame_num; +static s32 enable_recycle; + +static s32 init_drop_frame_id[INIT_DROP_FRAME_CNT]; +#define INCPTR(p) ptr_atomic_wrap_inc(&p) +static inline void ptr_atomic_wrap_inc(u32 *ptr) +{ + u32 i = *ptr; + + i++; + + if (i >= VF_POOL_SIZE) + i = 0; + + *ptr = i; +} + +static void set_frame_info(struct vframe_s *vf) +{ + unsigned int ar = 0; + + vf->width = frame_width; + vf->height = frame_height; + vf->duration = frame_dur; + vf->duration_pulldown = 0; + + if (vh264mvc_ratio == 0) { + /* always stretch to 16:9 */ + vf->ratio_control |= (0x90 << + DISP_RATIO_ASPECT_RATIO_BIT); + } else { + /* h264mvc_ar = ((float)frame_height/frame_width) + *customer_ratio; */ + ar = min_t(u32, h264mvc_ar, DISP_RATIO_ASPECT_RATIO_MAX); + + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + } + + return; +} + +static int vh264mvc_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + int i; + spin_lock_irqsave(&lock, flags); + states->vf_pool_size = VF_POOL_SIZE; + + i = put_ptr - fill_ptr; + if (i < 0) + i += VF_POOL_SIZE; + states->buf_free_num = i; + + i = putting_ptr - put_ptr; + if (i < 0) + i += VF_POOL_SIZE; + states->buf_recycle_num = i; + + i = fill_ptr - get_ptr; + if (i < 0) + i += VF_POOL_SIZE; + states->buf_avail_num = i; + + spin_unlock_irqrestore(&lock, flags); + return 0; +} + +void send_drop_cmd(void) +{ + int ready_cnt = 0; + int temp_get_ptr = get_ptr; + int temp_fill_ptr = fill_ptr; + while (temp_get_ptr != temp_fill_ptr) { + if ((vfpool_idx[temp_get_ptr].view0_buf_id >= 0) + && (vfpool_idx[temp_get_ptr].view1_buf_id >= 0) + && (vfpool_idx[temp_get_ptr].view0_drop == 0) + && (vfpool_idx[temp_get_ptr].view1_drop == 0)) + ready_cnt++; + INCPTR(temp_get_ptr); + } + if (dbg_mode & 0x40) { + pr_info("ready_cnt is %d ; no_dropping_cnt is %d\n", ready_cnt, + no_dropping_cnt); + } + if ((no_dropping_cnt >= DROPPING_FIRST_WAIT) + && (ready_cnt < drop_thread_hold)) + WRITE_VREG(DROP_CONTROL, (1 << 31) | (drop_rate)); + else + WRITE_VREG(DROP_CONTROL, 0); +} + +#if 0 +int get_valid_frame(void) +{ + int ready_cnt = 0; + int temp_get_ptr = get_ptr; + int temp_fill_ptr = fill_ptr; + while (temp_get_ptr != temp_fill_ptr) { + if ((vfpool_idx[temp_get_ptr].view0_buf_id >= 0) + && (vfpool_idx[temp_get_ptr].view1_buf_id >= 0) + && (vfpool_idx[temp_get_ptr].view0_drop == 0) + && (vfpool_idx[temp_get_ptr].view1_drop == 0)) + ready_cnt++; + INCPTR(temp_get_ptr); + } + return ready_cnt; +} +#endif +static struct vframe_s *vh264mvc_vf_peek(void *op_arg) +{ + + if (get_ptr == fill_ptr) + return NULL; + send_drop_cmd(); + return &vfpool[get_ptr]; + +} + +static struct vframe_s *vh264mvc_vf_get(void *op_arg) +{ + + struct vframe_s *vf; + int view0_buf_id; + int view1_buf_id; + if (get_ptr == fill_ptr) + return NULL; + + view0_buf_id = vfpool_idx[get_ptr].view0_buf_id; + view1_buf_id = vfpool_idx[get_ptr].view1_buf_id; + vf = &vfpool[get_ptr]; + + if ((view0_buf_id >= 0) && (view1_buf_id >= 0)) { + if (view_mode == 0 || view_mode == 1) { + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + vf->canvas0Addr = vf->canvas1Addr = + (view_mode == + 0) ? spec2canvas(&buffer_spec0[view0_buf_id]) : + spec2canvas(&buffer_spec1[view1_buf_id]); + } else { + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_MVC; + + vf->left_eye.start_x = 0; + vf->left_eye.start_y = 0; + vf->left_eye.width = vf->width; + vf->left_eye.height = vf->height; + vf->right_eye.start_x = 0; + vf->right_eye.start_y = 0; + vf->right_eye.width = vf->width; + vf->right_eye.height = vf->height; + vf->trans_fmt = TVIN_TFMT_3D_TB; + + if (view_mode == 2) { + vf->canvas0Addr = + spec2canvas(&buffer_spec1[ + view1_buf_id]); + vf->canvas1Addr = + spec2canvas(&buffer_spec0[ + view0_buf_id]); + } else { + vf->canvas0Addr = + spec2canvas(&buffer_spec0[ + view0_buf_id]); + vf->canvas1Addr = + spec2canvas(&buffer_spec1[ + view1_buf_id]); + } + } + } + vf->type_original = vf->type; + if (((vfpool_idx[get_ptr].view0_drop != 0) + || (vfpool_idx[get_ptr].view1_drop != 0)) + && ((no_dropping_cnt >= DROPPING_FIRST_WAIT))) + vf->frame_dirty = 1; + else + vf->frame_dirty = 0; + + INCPTR(get_ptr); + + if (vf) { + if (frame_width == 0) + frame_width = vh264mvc_amstream_dec_info.width; + if (frame_height == 0) + frame_height = vh264mvc_amstream_dec_info.height; + + vf->width = frame_width; + vf->height = frame_height; + } + if ((no_dropping_cnt < DROPPING_FIRST_WAIT) && (vf->frame_dirty == 0)) + no_dropping_cnt++; + return vf; + +} + +static void vh264mvc_vf_put(struct vframe_s *vf, void *op_arg) +{ + + if (vf_buf_init_flag == 0) + return; + if (vf->frame_dirty) { + + vf->frame_dirty = 0; + dirty_frame_num++; + enable_recycle = 0; + if (dbg_mode & PUT_PRINT_ENABLE) { + pr_info("invalid: dirty_frame_num is !!! %d\n", + dirty_frame_num); + } + } else { + INCPTR(putting_ptr); + while (dirty_frame_num > 0) { + INCPTR(putting_ptr); + dirty_frame_num--; + } + enable_recycle = 1; + if (dbg_mode & PUT_PRINT_ENABLE) { + pr_info("valid: dirty_frame_num is @@@ %d\n", + dirty_frame_num); + } + /* send_drop_cmd(); */ + } + +} + +static int vh264mvc_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vh264mvc_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vh264mvc_local_init(); + vh264mvc_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vh264mvc_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +/**/ +static long init_canvas(int start_addr, long dpb_size, int dpb_number, + int mb_width, int mb_height, + struct buffer_spec_s *buffer_spec) +{ + + int dpb_addr, addr; + int i; + int mb_total; + + /* cav_con canvas; */ + + dpb_addr = start_addr; + + mb_total = mb_width * mb_height; + + for (i = 0; i < dpb_number; i++) { + WRITE_VREG(ANC_CANVAS_ADDR, + index | ((index + 1) << 8) | + ((index + 2) << 16)); + ANC_CANVAS_ADDR++; + + addr = dpb_addr; + buffer_spec[i].y_addr = addr; + buffer_spec[i].y_canvas_index = index; + canvas_config(index, + addr, + mb_width << 4, + mb_height << 4, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 8; + index++; + buffer_spec[i].u_addr = addr; + buffer_spec[i].u_canvas_index = index; + canvas_config(index, + addr, + mb_width << 3, + mb_height << 3, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 6; + index++; + buffer_spec[i].v_addr = addr; + buffer_spec[i].v_canvas_index = index; + canvas_config(index, + addr, + mb_width << 3, + mb_height << 3, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + + addr += mb_total << 6; + index++; + + dpb_addr = dpb_addr + dpb_size; + if (dpb_addr >= DECODE_BUFFER_END) + return -1; + } + + return dpb_addr; +} + +static int get_max_dec_frame_buf_size(int level_idc, + int max_reference_frame_num, int mb_width, + int mb_height) +{ + int pic_size = mb_width * mb_height * 384; + + int size = 0; + + switch (level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + size = 70778880; + break; + default: + break; + } + + size /= pic_size; + size = size + 1; /* For MVC need onr more buffer */ + if (max_reference_frame_num > size) + size = max_reference_frame_num; + if (size > DECODE_BUFFER_NUM_MAX) + size = DECODE_BUFFER_NUM_MAX; + + return size; +} + +int check_in_list(int pos, int *slot) +{ + int i; + int ret = 0; + for (i = 0; i < VF_POOL_SIZE; i++) { + if ((vfpool_idx[i].display_pos == pos) + && (vfpool_idx[i].used == 0)) { + ret = 1; + *slot = vfpool_idx[i].slot; + break; + } + } + return ret; +} + +#ifdef HANDLE_h264mvc_IRQ +static irqreturn_t vh264mvc_isr(int irq, void *dev_id) +#else +static void vh264mvc_isr(void) +#endif +{ + int drop_status; + struct vframe_s *vf; + unsigned int pts, pts_valid = 0; + u64 pts_us64; + int ret = READ_VREG(MAILBOX_COMMAND); + /* pr_info("vh264mvc_isr, cmd =%x\n", ret); */ + switch (ret & 0xff) { + case CMD_ALLOC_VIEW_0: + if (dbg_mode & 0x1) { + pr_info + ("Start H264 display buffer allocation for view 0\n"); + } + if ((dpb_start_addr[0] != -1) | (dpb_start_addr[1] != -1)) { + dpb_start_addr[0] = -1; + dpb_start_addr[1] = -1; + } + dpb_start_addr[0] = DECODE_BUFFER_START; + ret = READ_VREG(MAILBOX_DATA_0); + level_idc = (ret >> 24) & 0xff; + max_reference_frame_num = (ret >> 16) & 0xff; + mb_width = (ret >> 8) & 0xff; + mb_height = (ret >> 0) & 0xff; + max_dec_frame_buffering[0] = + get_max_dec_frame_buf_size(level_idc, + max_reference_frame_num, + mb_width, mb_height); + + total_dec_frame_buffering[0] = + max_dec_frame_buffering[0] + DISPLAY_BUFFER_NUM; + + mb_width = (mb_width + 3) & 0xfffffffc; + mb_height = (mb_height + 3) & 0xfffffffc; + + dpb_size = mb_width * mb_height * 384; + ref_size = mb_width * mb_height * 96; + + if (dbg_mode & 0x1) { + pr_info("dpb_size: 0x%x\n", dpb_size); + pr_info("ref_size: 0x%x\n", ref_size); + pr_info("total_dec_frame_buffering[0] : 0x%x\n", + total_dec_frame_buffering[0]); + pr_info("max_reference_frame_num: 0x%x\n", + max_reference_frame_num); + } + ref_start_addr[0] = dpb_start_addr[0] + + (dpb_size * total_dec_frame_buffering[0]); + dpb_start_addr[1] = ref_start_addr[0] + + (ref_size * (max_reference_frame_num + 1)); + + if (dbg_mode & 0x1) { + pr_info("dpb_start_addr[0]: 0x%x\n", dpb_start_addr[0]); + pr_info("ref_start_addr[0]: 0x%x\n", ref_start_addr[0]); + pr_info("dpb_start_addr[1]: 0x%x\n", dpb_start_addr[1]); + } + if (dpb_start_addr[1] >= DECODE_BUFFER_END) { + pr_info(" No enough memory for alloc view 0\n"); + goto exit; + } + + index = CANVAS_INDEX_START; + ANC_CANVAS_ADDR = ANC0_CANVAS_ADDR; + + ret = + init_canvas(dpb_start_addr[0], dpb_size, + total_dec_frame_buffering[0], mb_width, + mb_height, buffer_spec0); + + if (ret == -1) { + pr_info(" Un-expected memory alloc problem\n"); + goto exit; + } + + WRITE_VREG(REF_START_VIEW_0, + video_domain_addr(ref_start_addr[0])); + WRITE_VREG(MAILBOX_DATA_0, + (max_dec_frame_buffering[0] << 8) | + (total_dec_frame_buffering[0] << 0) + ); + WRITE_VREG(MAILBOX_DATA_1, ref_size); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + + if (dbg_mode & 0x1) { + pr_info + ("End H264 display buffer allocation for view 0\n"); + } + if (frame_width == 0) { + if (vh264mvc_amstream_dec_info.width) + frame_width = vh264mvc_amstream_dec_info.width; + else + frame_width = mb_width << 4; + } + if (frame_height == 0) { + frame_height = mb_height << 4; + if (frame_height == 1088) + frame_height = 1080; + } + break; + case CMD_ALLOC_VIEW_1: + if (dbg_mode & 0x1) { + pr_info + ("Start H264 display buffer allocation for view 1\n"); + } + if ((dpb_start_addr[0] == -1) | (dpb_start_addr[1] == -1)) { + pr_info("Error: allocation view 1 before view 0 !!!\n"); + break; + } + ret = READ_VREG(MAILBOX_DATA_0); + level_idc = (ret >> 24) & 0xff; + max_reference_frame_num = (ret >> 16) & 0xff; + mb_width = (ret >> 8) & 0xff; + mb_height = (ret >> 0) & 0xff; + max_dec_frame_buffering[1] = + get_max_dec_frame_buf_size(level_idc, + max_reference_frame_num, + mb_width, mb_height); + if (max_dec_frame_buffering[1] != max_dec_frame_buffering[0]) { + pr_info + (" Warning: view0/1 max_dec_frame_buffering "); + pr_info("different : 0x%x/0x%x, Use View0\n", + max_dec_frame_buffering[0], + max_dec_frame_buffering[1]); + max_dec_frame_buffering[1] = max_dec_frame_buffering[0]; + } + + total_dec_frame_buffering[1] = + max_dec_frame_buffering[1] + DISPLAY_BUFFER_NUM; + + mb_width = (mb_width + 3) & 0xfffffffc; + mb_height = (mb_height + 3) & 0xfffffffc; + + dpb_size = mb_width * mb_height * 384; + ref_size = mb_width * mb_height * 96; + + if (dbg_mode & 0x1) { + pr_info("dpb_size: 0x%x\n", dpb_size); + pr_info("ref_size: 0x%x\n", ref_size); + pr_info("total_dec_frame_buffering[1] : 0x%x\n", + total_dec_frame_buffering[1]); + pr_info("max_reference_frame_num: 0x%x\n", + max_reference_frame_num); + } + ref_start_addr[1] = dpb_start_addr[1] + + (dpb_size * total_dec_frame_buffering[1]); + dpb_start_addr[2] = ref_start_addr[1] + + (ref_size * (max_reference_frame_num + 1)); + + if (dbg_mode & 0x1) { + pr_info("dpb_start_addr[1]: 0x%x\n", dpb_start_addr[1]); + pr_info("ref_start_addr[1]: 0x%x\n", ref_start_addr[1]); + pr_info("dpb_start_addr[2]: 0x%x\n", dpb_start_addr[2]); + } + if (dpb_start_addr[2] >= DECODE_BUFFER_END) { + pr_info(" No enough memory for alloc view 1\n"); + goto exit; + } + + index = CANVAS_INDEX_START + total_dec_frame_buffering[0] * 3; + ANC_CANVAS_ADDR = + ANC0_CANVAS_ADDR + total_dec_frame_buffering[0]; + + ret = + init_canvas(dpb_start_addr[1], dpb_size, + total_dec_frame_buffering[1], mb_width, + mb_height, buffer_spec1); + + if (ret == -1) { + pr_info(" Un-expected memory alloc problem\n"); + goto exit; + } + + WRITE_VREG(REF_START_VIEW_1, + video_domain_addr(ref_start_addr[1])); + WRITE_VREG(MAILBOX_DATA_0, + (max_dec_frame_buffering[1] << 8) | + (total_dec_frame_buffering[1] << 0) + ); + WRITE_VREG(MAILBOX_DATA_1, ref_size); + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + + if (dbg_mode & 0x1) { + pr_info + ("End H264 display buffer allocation for view 1\n"); + } + if (frame_width == 0) { + if (vh264mvc_amstream_dec_info.width) + frame_width = vh264mvc_amstream_dec_info.width; + else + frame_width = mb_width << 4; + } + if (frame_height == 0) { + frame_height = mb_height << 4; + if (frame_height == 1088) + frame_height = 1080; + } + break; + case CMD_FRAME_DISPLAY: + ret = READ_VREG(MAILBOX_DATA_0); + display_buff_id = (ret >> 0) & 0x3f; + display_view_id = (ret >> 6) & 0x3; + drop_status = (ret >> 8) & 0x1; + display_POC = READ_VREG(MAILBOX_DATA_1); + stream_offset = READ_VREG(MAILBOX_DATA_2); + /* if (display_view_id == 0) */ + WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED); + +#ifdef DEBUG_SKIP + view_total++; + if (drop_status) + view_dropped++; +#endif + if (dbg_mode & 0x1) { + pr_info + (" H264 display frame ready - View : %x, Buffer : %x\n", + display_view_id, display_buff_id); + pr_info + (" H264 display frame POC -- Buffer : %x, POC : %x\n", + display_buff_id, display_POC); + pr_info("H264 display frame ready\n"); + } + if (dbg_mode & 0x10) { + if ((dbg_mode & 0x20) == 0) { + while (READ_VREG(BUFFER_RECYCLE) != 0) + ; + WRITE_VREG(BUFFER_RECYCLE, + (display_view_id << 8) | + (display_buff_id + 1)); + display_buff_id = -1; + display_view_id = -1; + display_POC = -1; + } + } else { + unsigned char in_list_flag = 0; + + int slot = 0; + in_list_flag = check_in_list(display_POC, &slot); + + if ((dbg_mode & 0x40) && (drop_status)) { + pr_info + ("drop_status:%dview_id=%d,buff_id=%d,", + drop_status, display_view_id, display_buff_id); + pr_info + ("offset=%d, display_POC = %d,fill_ptr=0x%x\n", + stream_offset, display_POC, fill_ptr); + } + + if ((in_list_flag) && (stream_offset != 0)) { + pr_info + ("error case ,display_POC is %d, slot is %d\n", + display_POC, slot); + in_list_flag = 0; + } + if (!in_list_flag) { + if (display_view_id == 0) { + vfpool_idx[fill_ptr].view0_buf_id = + display_buff_id; + view0_vfbuf_use[display_buff_id]++; + vfpool_idx[fill_ptr].stream_offset = + stream_offset; + vfpool_idx[fill_ptr].view0_drop = + drop_status; + } + if (display_view_id == 1) { + vfpool_idx[fill_ptr].view1_buf_id = + display_buff_id; + vfpool_idx[fill_ptr].view1_drop = + drop_status; + view1_vfbuf_use[display_buff_id]++; + } + vfpool_idx[fill_ptr].slot = fill_ptr; + vfpool_idx[fill_ptr].display_pos = display_POC; + + } else { + if (display_view_id == 0) { + vfpool_idx[slot].view0_buf_id = + display_buff_id; + view0_vfbuf_use[display_buff_id]++; + vfpool_idx[slot].stream_offset = + stream_offset; + vfpool_idx[slot].view0_drop = + drop_status; + + } + if (display_view_id == 1) { + vfpool_idx[slot].view1_buf_id = + display_buff_id; + view1_vfbuf_use[display_buff_id]++; + vfpool_idx[slot].view1_drop = + drop_status; + } + vf = &vfpool[slot]; +#if 0 + if (pts_lookup_offset + (PTS_TYPE_VIDEO, + vfpool_idx[slot].stream_offset, + &vf->pts, + 0) != 0) + vf->pts = 0; +#endif + if (vfpool_idx[slot].stream_offset == 0) { + pr_info + ("error case, invalid stream offset\n"); + } + if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, + vfpool_idx[slot].stream_offset, &pts, + 0x10000, &pts_us64) == 0) + pts_valid = 1; + else + pts_valid = 0; + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + /* vf->pts = vf->pts_us64 ? vf->pts_us64 + : vf->pts ; */ + /* vf->pts = vf->pts_us64; */ + if (dbg_mode & 0x80) + pr_info("vf->pts:%d\n", vf->pts); + vfpool_idx[slot].used = 1; + INCPTR(fill_ptr); + set_frame_info(vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + } + } + break; + case CMD_FATAL_ERROR: + pr_info("fatal error !!!\n"); + schedule_work(&error_wd_work); + break; + default: + break; + } +exit: +#ifdef HANDLE_h264mvc_IRQ + return IRQ_HANDLED; +#else + return; +#endif +} + +static void vh264mvc_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + + int valid_frame = 0; + if (enable_recycle == 0) { + if (dbg_mode & TIME_TASK_PRINT_ENABLE) { + /* valid_frame = get_valid_frame(); */ + pr_info("dirty_frame_num is %d , valid frame is %d\n", + dirty_frame_num, valid_frame); + + } + /* goto RESTART; */ + } + + while ((putting_ptr != put_ptr) && (READ_VREG(BUFFER_RECYCLE) == 0)) { + int view0_buf_id = vfpool_idx[put_ptr].view0_buf_id; + int view1_buf_id = vfpool_idx[put_ptr].view1_buf_id; + if ((view0_buf_id >= 0) && + (view0_vfbuf_use[view0_buf_id] == 1)) { + if (dbg_mode & 0x100) { + pr_info + ("round 0: put_ptr is %d ;view0_buf_id is %d\n", + put_ptr, view0_buf_id); + } + WRITE_VREG(BUFFER_RECYCLE, + (0 << 8) | (view0_buf_id + 1)); + view0_vfbuf_use[view0_buf_id] = 0; + vfpool_idx[put_ptr].view0_buf_id = -1; + vfpool_idx[put_ptr].view0_drop = 0; + } else if ((view1_buf_id >= 0) + && (view1_vfbuf_use[view1_buf_id] == 1)) { + if (dbg_mode & 0x100) { + pr_info + ("round 1: put_ptr is %d ;view1_buf_id %d==\n", + put_ptr, view1_buf_id); + } + WRITE_VREG(BUFFER_RECYCLE, + (1 << 8) | (view1_buf_id + 1)); + view1_vfbuf_use[view1_buf_id] = 0; + vfpool_idx[put_ptr].display_pos = DISPLAY_INVALID_POS; + vfpool_idx[put_ptr].view1_buf_id = -1; + vfpool_idx[put_ptr].view1_drop = 0; + vfpool_idx[put_ptr].used = 0; + INCPTR(put_ptr); + } + } + + + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_H264MVC, + frame_width, frame_height, fps * 2); + } + + /* RESTART: */ + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vh264mvc_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = frame_width; + vstatus->height = frame_height; + if (frame_dur != 0) + vstatus->fps = 96000 / frame_dur; + else + vstatus->fps = -1; + vstatus->error_count = READ_VREG(AV_SCRATCH_D); + vstatus->status = stat; + return 0; +} + +int vh264mvc_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) +{ + if (trickmode == TRICKMODE_I) { + WRITE_VREG(AV_SCRATCH_F, + (READ_VREG(AV_SCRATCH_F) & 0xfffffffc) | 2); + trickmode_i = 1; + } else if (trickmode == TRICKMODE_NONE) { + WRITE_VREG(AV_SCRATCH_F, READ_VREG(AV_SCRATCH_F) & 0xfffffffc); + trickmode_i = 0; + } + + return 0; +} + +static void H264_DECODE_INIT(void) +{ + int i; + i = READ_VREG(DECODE_SKIP_PICTURE); + +#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + +#else + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + READ_MPEG_REG(RESET0_REGISTER); + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); +#endif + + /* Wait for some time for RESET */ + READ_VREG(DECODE_SKIP_PICTURE); + READ_VREG(DECODE_SKIP_PICTURE); + + WRITE_VREG(DECODE_SKIP_PICTURE, i); + + /* fill_weight_pred */ + WRITE_VREG(MC_MPORT_CTRL, 0x0300); + for (i = 0; i < 192; i++) + WRITE_VREG(MC_MPORT_DAT, 0x100); + WRITE_VREG(MC_MPORT_CTRL, 0); + + WRITE_VREG(MB_WIDTH, 0xff); /* invalid mb_width */ + + /* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */ + WRITE_VREG(SLICE_START_BYTE_01, 0x00000000); + WRITE_VREG(SLICE_START_BYTE_23, 0x01010000); + /* set to mpeg2 to enable mismatch logic */ + WRITE_VREG(MPEG1_2_REG, 1); + /* disable COEF_GT_64 , error_m4_table and voff_rw_err */ + WRITE_VREG(VLD_ERROR_MASK, 0x1011); + + /* Config MCPU Amrisc interrupt */ + WRITE_VREG(ASSIST_AMR1_INT0, 0x1); /* viu_vsync_int */ + WRITE_VREG(ASSIST_AMR1_INT1, 0x5); /* mbox_isr */ + WRITE_VREG(ASSIST_AMR1_INT2, 0x8); /* vld_isr */ + WRITE_VREG(ASSIST_AMR1_INT3, 0x15); /* vififo_empty */ + WRITE_VREG(ASSIST_AMR1_INT4, 0xd); /* rv_ai_mb_finished_int */ + WRITE_VREG(ASSIST_AMR1_INT7, 0x14); /* dcac_dma_done */ + + /* Config MCPU Amrisc interrupt */ + WRITE_VREG(ASSIST_AMR1_INT5, 0x9); /* MCPU interrupt */ + WRITE_VREG(ASSIST_AMR1_INT6, 0x17); /* CCPU interrupt */ + + WRITE_VREG(CPC_P, 0xc00); /* CCPU Code will start from 0xc00 */ + WRITE_VREG(CINT_VEC_BASE, (0xc20 >> 5)); +#if 0 + WRITE_VREG(POWER_CTL_VLD, + READ_VREG(POWER_CTL_VLD) | (0 << 10) | + (1 << 9) | (1 << 6)); +#else + WRITE_VREG(POWER_CTL_VLD, ((1 << 10) | /* disable cabac_step_2 */ + (1 << 9) | /* viff_drop_flag_en */ + (1 << 6) /* h264_000003_en */ + ) + ); +#endif + WRITE_VREG(M4_CONTROL_REG, (1 << 13)); /* H264_DECODE_INFO - h264_en */ + + WRITE_VREG(CANVAS_START, CANVAS_INDEX_START); +#if 1 + /* Start Address of Workspace (UCODE, temp_data...) */ + WRITE_VREG(WORKSPACE_START, + video_domain_addr(work_space_adr)); +#else + /* Start Address of Workspace (UCODE, temp_data...) */ + WRITE_VREG(WORKSPACE_START, + 0x05000000); +#endif + /* Clear all sequence parameter set available */ + WRITE_VREG(SPS_STATUS, 0); + /* Clear all picture parameter set available */ + WRITE_VREG(PPS_STATUS, 0); + /* Set current microcode to NULL */ + WRITE_VREG(CURRENT_UCODE, 0xff); + /* Set current SPS/PPS to NULL */ + WRITE_VREG(CURRENT_SPS_PPS, 0xffff); + /* Set decode status to DECODE_START_HEADER */ + WRITE_VREG(DECODE_STATUS, 1); +} + +static void vh264mvc_prot_init(void) +{ + while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) + ; + while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) + ; /* reg address is 0x350 */ + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + H264_DECODE_INIT(); + +#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 11)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + +#else + WRITE_MPEG_REG(RESET0_REGISTER, 0x80); /* RESET MCPU */ +#endif + + WRITE_VREG(MAILBOX_COMMAND, 0); + WRITE_VREG(BUFFER_RECYCLE, 0); + WRITE_VREG(DROP_CONTROL, 0); + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); +#endif +} + +static void vh264mvc_local_init(void) +{ + int i; + display_buff_id = -1; + display_view_id = -1; + display_POC = -1; + no_dropping_cnt = 0; + init_drop_cnt = INIT_DROP_FRAME_CNT; + + for (i = 0; i < INIT_DROP_FRAME_CNT; i++) + init_drop_frame_id[i] = 0; + +#ifdef DEBUG_PTS + pts_missed = 0; + pts_hit = 0; +#endif + +#ifdef DEBUG_SKIP + view_total = 0; + view_dropped = 0; +#endif + + /* vh264mvc_ratio = vh264mvc_amstream_dec_info.ratio; */ + vh264mvc_ratio = 0x100; + + /* frame_width = vh264mvc_amstream_dec_info.width; */ + /* frame_height = vh264mvc_amstream_dec_info.height; */ + frame_dur = vh264mvc_amstream_dec_info.rate; + if (frame_dur == 0) + frame_dur = 96000 / 24; + + pts_outside = ((unsigned long) vh264mvc_amstream_dec_info.param) & 0x01; + sync_outside = ((unsigned long) vh264mvc_amstream_dec_info.param & 0x02) + >> 1; + + /**/ dpb_start_addr[0] = -1; + dpb_start_addr[1] = -1; + max_dec_frame_buffering[0] = -1; + max_dec_frame_buffering[1] = -1; + fill_ptr = get_ptr = put_ptr = putting_ptr = 0; + dirty_frame_num = 0; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + view0_vfbuf_use[i] = 0; + view1_vfbuf_use[i] = 0; + } + + for (i = 0; i < VF_POOL_SIZE; i++) { + vfpool_idx[i].display_pos = -1; + vfpool_idx[i].view0_buf_id = DISPLAY_INVALID_POS; + vfpool_idx[i].view1_buf_id = -1; + vfpool_idx[i].view0_drop = 0; + vfpool_idx[i].view1_drop = 0; + vfpool_idx[i].used = 0; + } + for (i = 0; i < VF_POOL_SIZE; i++) + memset(&vfpool[i], 0, sizeof(struct vframe_s)); + init_vf_buf(); + return; +} + +static s32 vh264mvc_init(void) +{ + int ret = -1, size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + pr_info("\nvh264mvc_init\n"); + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + vh264mvc_local_init(); + + amvdec_enable(); + + /* -- ucode loading (amrisc and swap code) */ + mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, &mc_dma_handle, GFP_KERNEL); + if (!mc_cpu_addr) { + amvdec_disable(); + vfree(buf); + pr_err("vh264_mvc init: Can not allocate mc memory.\n"); + return -ENOMEM; + } + + WRITE_VREG(UCODE_START_ADDR, mc_dma_handle); + + size = get_firmware_data(VIDEO_DEC_H264_MVC, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf); + + /*header*/ + memcpy((u8 *) mc_cpu_addr, buf + 0x1000, 0x1000); + /*mmco*/ + memcpy((u8 *) mc_cpu_addr + 0x1000, buf + 0x2000, 0x2000); + /*slice*/ + memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); + + vfree(buf); + + if (ret < 0) { + amvdec_disable(); + + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); + mc_cpu_addr = NULL; + return -EBUSY; + } + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vh264mvc_prot_init(); + +#ifdef HANDLE_h264mvc_IRQ + if (vdec_request_irq(VDEC_IRQ_1, vh264mvc_isr, + "vh264mvc-irq", (void *)vh264mvc_dec_id)) { + pr_info("vh264mvc irq register error.\n"); + amvdec_disable(); + return -ENOENT; + } +#endif + + stat |= STAT_ISR_REG; + + vf_provider_init(&vh264mvc_vf_prov, PROVIDER_NAME, + &vh264mvc_vf_provider, NULL); + vf_reg_provider(&vh264mvc_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong) (&recycle_timer); + recycle_timer.function = vh264mvc_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int vh264mvc_stop(void) +{ + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + WRITE_VREG(ASSIST_MBOX1_MASK, 0); +#ifdef HANDLE_h264mvc_IRQ + vdec_free_irq(VDEC_IRQ_1, (void *)vh264mvc_dec_id); +#endif + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + ulong flags; + spin_lock_irqsave(&lock, flags); + spin_unlock_irqrestore(&lock, flags); + vf_unreg_provider(&vh264mvc_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + if (stat & STAT_MC_LOAD) { + if (mc_cpu_addr != NULL) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); + mc_cpu_addr = NULL; + } + + stat &= ~STAT_MC_LOAD; + } + + amvdec_disable(); + + uninit_vf_buf(); + return 0; +} + +static void error_do_work(struct work_struct *work) +{ + if (atomic_read(&vh264mvc_active)) { + vh264mvc_stop(); + vh264mvc_init(); + } +} + +static int amvdec_h264mvc_probe(struct platform_device *pdev) +{ + struct resource mem; + int buf_size; + + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + pr_info("amvdec_h264mvc probe start.\n"); + +#if 0 + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + pr_info("\namvdec_h264mvc memory resource undefined.\n"); + return -EFAULT; + } +#endif + + if (pdata == NULL) { + pr_info("\namvdec_h264mvc memory resource undefined.\n"); + return -EFAULT; + } + mem.start = pdata->mem_start; + mem.end = pdata->mem_end; + + buf_size = mem.end - mem.start + 1; + /* buf_offset = mem->start - DEF_BUF_START_ADDR; */ + work_space_adr = mem.start; + DECODE_BUFFER_START = work_space_adr + work_space_size; + DECODE_BUFFER_END = mem.start + buf_size; + + pr_info + ("work_space_adr %x, DECODE_BUFFER_START %x, DECODE_BUFFER_END %x\n", + work_space_adr, DECODE_BUFFER_START, DECODE_BUFFER_END); + if (pdata->sys_info) + vh264mvc_amstream_dec_info = *pdata->sys_info; + + pdata->dec_status = vh264mvc_dec_status; + /* pdata->set_trickmode = vh264mvc_set_trickmode; */ + + if (vh264mvc_init() < 0) { + pr_info("\namvdec_h264mvc init failed.\n"); + + return -ENODEV; + } + + INIT_WORK(&error_wd_work, error_do_work); + + atomic_set(&vh264mvc_active, 1); + + pr_info("amvdec_h264mvc probe end.\n"); + + return 0; +} + +static int amvdec_h264mvc_remove(struct platform_device *pdev) +{ + pr_info("amvdec_h264mvc_remove\n"); + cancel_work_sync(&error_wd_work); + vh264mvc_stop(); + frame_width = 0; + frame_height = 0; + vdec_source_changed(VFORMAT_H264MVC, 0, 0, 0); + atomic_set(&vh264mvc_active, 0); + +#ifdef DEBUG_PTS + pr_info + ("pts missed %ld, pts hit %ld, pts_outside %d, ", + pts_missed, pts_hit, pts_outside); + pr_info("duration %d, sync_outside %d\n", + frame_dur, sync_outside); +#endif + +#ifdef DEBUG_SKIP + pr_info("view_total = %ld, dropped %ld\n", view_total, view_dropped); +#endif + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_h264mvc_driver = { + .probe = amvdec_h264mvc_probe, + .remove = amvdec_h264mvc_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_hmvc_profile = { + .name = "hmvc", + .profile = "" +}; + +static int __init amvdec_h264mvc_driver_init_module(void) +{ + pr_debug("amvdec_h264mvc module init\n"); + + if (platform_driver_register(&amvdec_h264mvc_driver)) { + pr_err("failed to register amvdec_h264mvc driver\n"); + return -ENODEV; + } + + vcodec_profile_register(&amvdec_hmvc_profile); + + return 0; +} + +static void __exit amvdec_h264mvc_driver_remove_module(void) +{ + pr_debug("amvdec_h264mvc module remove.\n"); + + platform_driver_unregister(&amvdec_h264mvc_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_h264mvc stat\n"); + +module_param(dbg_mode, uint, 0664); +MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc dbg mode\n"); + +module_param(view_mode, uint, 0664); +MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n"); + +module_param(dbg_cmd, uint, 0664); +MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc cmd mode\n"); + +module_param(drop_rate, uint, 0664); +MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc drop rate\n"); + +module_param(drop_thread_hold, uint, 0664); +MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc drop thread hold\n"); +module_init(amvdec_h264mvc_driver_init_module); +module_exit(amvdec_h264mvc_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC h264mvc Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Chen Zhang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile new file mode 100644 index 000000000000..17cb87e4d77b --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/Makefile @@ -0,0 +1,2 @@ +obj-m += vh264_multi.o +vh264_multi-objs += vmh264.o h264_dpb.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c new file mode 100644 index 000000000000..b3e8f0fab484 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c @@ -0,0 +1,5238 @@ +#include +#include +#include + +#include +#include "../utils/vdec.h" +#include "../utils/amvdec.h" + +#include "h264_dpb.h" + +/* #define OLD_OUTPUT_CODE */ +#undef pr_info +#define pr_info printk +int dpb_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((h264_debug_flag & debug_flag) && + ((1 << index) & h264_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + if ((index & 0x100) == 0) + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} + +unsigned char dpb_is_debug(int index, int debug_flag) +{ + if (((h264_debug_flag & debug_flag) && + ((1 << index) & h264_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) + return 1; + return 0; +} + +#define CHECK_VALID(list_size, mark) {\ + if (list_size > MAX_LIST_SIZE || list_size < 0) { \ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR, \ + "%s(%d): listXsize[%d] %d is larger than max size\r\n",\ + __func__, __LINE__, mark, list_size);\ + list_size = 0; \ + } \ + } + +static struct DecRefPicMarking_s + dummy_dec_ref_pic_marking_buffer + [DEC_REF_PIC_MARKING_BUFFER_NUM_MAX]; +static struct StorablePicture dummy_pic; +static struct FrameStore dummy_fs; +static struct StorablePicture *get_new_pic( + struct h264_dpb_stru *p_H264_Dpb, + enum PictureStructure structure, unsigned char is_output); +static void dump_dpb(struct DecodedPictureBuffer *p_Dpb); + +static void init_dummy_fs(void) +{ + dummy_fs.frame = &dummy_pic; + dummy_fs.top_field = &dummy_pic; + dummy_fs.bottom_field = &dummy_pic; + + dummy_pic.top_field = &dummy_pic; + dummy_pic.bottom_field = &dummy_pic; + dummy_pic.frame = &dummy_pic; + + dummy_pic.dec_ref_pic_marking_buffer = + &dummy_dec_ref_pic_marking_buffer[0]; +} + +enum { + LIST_0 = 0, + LIST_1 = 1, + BI_PRED = 2, + BI_PRED_L0 = 3, + BI_PRED_L1 = 4 +}; + +void ref_pic_list_reordering(struct h264_dpb_stru *p_H264_Dpb, + struct Slice *currSlice) +{ + /* struct VideoParameters *p_Vid = currSlice->p_Vid; + byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER]; + DataPartition *partition = &(currSlice->partArr[dP_nr]); + Bitstream *currStream = partition->bitstream; + */ + int i, j, val; + unsigned short *reorder_cmd = + &p_H264_Dpb->dpb_param.mmco.l0_reorder_cmd[0]; + /* alloc_ref_pic_list_reordering_buffer(currSlice); */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + if (currSlice->slice_type != I_SLICE && + currSlice->slice_type != SI_SLICE) { + /* val = currSlice->ref_pic_list_reordering_flag[LIST_0] = + read_u_1 ("SH: ref_pic_list_reordering_flag_l0", + currStream, &p_Dec->UsedBits); */ + if (reorder_cmd[0] != 3) { + val = currSlice-> + ref_pic_list_reordering_flag[LIST_0] = 1; + } else { + val = currSlice-> + ref_pic_list_reordering_flag[LIST_0] = 0; + } + if (val) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%s, ref_pic_list_reordering_flag[LIST_0] is 1\n", + __func__); + + j = 0; + i = 0; + do { + val = currSlice-> + modification_of_pic_nums_idc[LIST_0][i] = + reorder_cmd[j++]; + /* read_ue_v( + "SH: modification_of_pic_nums_idc_l0", + currStream, &p_Dec->UsedBits); */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%d(%d):val %x\n", i, j, val); + if (j >= 66) { + currSlice-> + ref_pic_list_reordering_flag[LIST_0] = + 0; /* by rain */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s error\n", __func__); + break; + } + if (val == 0 || val == 1) { + currSlice-> + abs_diff_pic_num_minus1[LIST_0][i] = + reorder_cmd[j++]; + /* read_ue_v("SH: " + "abs_diff_pic_num_minus1_l0", + currStream, &p_Dec->UsedBits); */ + } else { + if (val == 2) { + currSlice-> + long_term_pic_idx[LIST_0][i] = + reorder_cmd[j++]; + /* read_ue_v( + "SH: long_term_pic_idx_l0", + currStream, + &p_Dec->UsedBits); */ + } + } + i++; + /* assert (i>currSlice-> + num_ref_idx_active[LIST_0]); */ + if (/* + i>currSlice->num_ref_idx_active[LIST_0] || + */ + i >= REORDERING_COMMAND_MAX_SIZE) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s error %d %d\n", + __func__, i, + currSlice-> + num_ref_idx_active[LIST_0]); + currSlice-> + ref_pic_list_reordering_flag[LIST_0] = + 0; /* by rain */ + break; + } + if (j >= 66) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, "%s error\n", + __func__); + currSlice-> + ref_pic_list_reordering_flag[LIST_0] = + 0; /* by rain */ + break; + } + + } while (val != 3); + } + } + + if (currSlice->slice_type == B_SLICE) { + reorder_cmd = &p_H264_Dpb->dpb_param.mmco.l1_reorder_cmd[0]; + /* val = currSlice->ref_pic_list_reordering_flag[LIST_1] + = read_u_1 ("SH: ref_pic_list_reordering_flag_l1", + currStream, + &p_Dec->UsedBits); */ + + if (reorder_cmd[0] != 3) { + val = + currSlice->ref_pic_list_reordering_flag[LIST_1] = 1; + } else { + val = + currSlice->ref_pic_list_reordering_flag[LIST_1] = 0; + } + + if (val) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%s, ref_pic_list_reordering_flag[LIST_1] is 1\n", + __func__); + + j = 0; + i = 0; + do { + val = currSlice-> + modification_of_pic_nums_idc[LIST_1][i] = + reorder_cmd[j++]; + /* read_ue_v( + "SH: modification_of_pic_nums_idc_l1", + currStream, + &p_Dec->UsedBits); */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%d(%d):val %x\n", + i, j, val); + if (j >= 66) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, "%s error\n", + __func__); + currSlice-> + ref_pic_list_reordering_flag[LIST_1] = + 0; /* by rain */ + break; + } + if (val == 0 || val == 1) { + currSlice-> + abs_diff_pic_num_minus1[LIST_1][i] = + reorder_cmd[j++]; + /* read_ue_v( + "SH: abs_diff_pic_num_minus1_l1", + currStream, &p_Dec->UsedBits); */ + } else { + if (val == 2) { + currSlice-> + long_term_pic_idx[LIST_1][i] = + reorder_cmd[j++]; + /* read_ue_v( + "SH: long_term_pic_idx_l1", + currStream, + &p_Dec->UsedBits); */ + } + } + i++; + /* assert(i>currSlice-> + num_ref_idx_active[LIST_1]); */ + if ( + /*i>currSlice->num_ref_idx_active[LIST_1] || */ + i >= REORDERING_COMMAND_MAX_SIZE) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s error %d %d\n", + __func__, i, + currSlice-> + num_ref_idx_active[LIST_0]); + currSlice-> + ref_pic_list_reordering_flag[LIST_1] = + 0; /* by rain */ + break; + } + if (j >= 66) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s error\n", __func__); + break; + } + } while (val != 3); + } + } + + /* set reference index of redundant slices. */ + /* + if (currSlice->redundant_pic_cnt && (currSlice->slice_type != I_SLICE)) + { + currSlice->redundant_slice_ref_idx = + currSlice->abs_diff_pic_num_minus1[LIST_0][0] + 1; + }*/ +} + +void slice_prepare(struct h264_dpb_stru *p_H264_Dpb, + struct DecodedPictureBuffer *p_Dpb, + struct VideoParameters *p_Vid, + struct SPSParameters *sps, struct Slice *pSlice) +{ + int i, j; + /* p_Vid->active_sps = sps; */ + unsigned short *mmco_cmd = &p_H264_Dpb->dpb_param.mmco.mmco_cmd[0]; + /* for decode_poc */ + sps->pic_order_cnt_type = + p_H264_Dpb->dpb_param.l.data[PIC_ORDER_CNT_TYPE]; + sps->log2_max_pic_order_cnt_lsb_minus4 = + p_H264_Dpb->dpb_param.l.data[LOG2_MAX_PIC_ORDER_CNT_LSB] - 4; + sps->num_ref_frames_in_pic_order_cnt_cycle = + p_H264_Dpb-> + dpb_param.l.data[NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE]; + for (i = 0; i < 128; i++) + sps->offset_for_ref_frame[i] = + (short) p_H264_Dpb-> + dpb_param.mmco.offset_for_ref_frame_base[i]; + sps->offset_for_non_ref_pic = + (short) p_H264_Dpb->dpb_param.l.data[OFFSET_FOR_NON_REF_PIC]; + sps->offset_for_top_to_bottom_field = + (short) p_H264_Dpb->dpb_param.l.data + [OFFSET_FOR_TOP_TO_BOTTOM_FIELD]; + + pSlice->frame_num = p_H264_Dpb->dpb_param.dpb.frame_num; + pSlice->idr_flag = + (p_H264_Dpb->dpb_param.dpb.NAL_info_mmco & 0x1f) + == 5 ? 1 : 0; + pSlice->nal_reference_idc = + (p_H264_Dpb->dpb_param.dpb.NAL_info_mmco >> 5) + & 0x3; + pSlice->pic_order_cnt_lsb = + p_H264_Dpb->dpb_param.dpb.pic_order_cnt_lsb; + pSlice->field_pic_flag = 0; + pSlice->bottom_field_flag = 0; + pSlice->delta_pic_order_cnt_bottom = val( + p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_bottom); + pSlice->delta_pic_order_cnt[0] = val( + p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_0); + pSlice->delta_pic_order_cnt[1] = val( + p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_1); + + p_Vid->last_has_mmco_5 = 0; + /* last memory_management_control_operation is 5 */ + p_Vid->last_pic_bottom_field = 0; + p_Vid->max_frame_num = 1 << + (p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM]); + + /**/ + pSlice->structure = (p_H264_Dpb-> + dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ? + FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE]; + sps->num_ref_frames = p_H264_Dpb-> + dpb_param.l.data[MAX_REFERENCE_FRAME_NUM]; + sps->max_dpb_size = p_H264_Dpb->dpb_param.l.data[MAX_DPB_SIZE]; + if (pSlice->idr_flag) { + pSlice->long_term_reference_flag = mmco_cmd[0] & 1; + pSlice->no_output_of_prior_pics_flag = (mmco_cmd[0] >> 1) & 1; + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "IDR: long_term_reference_flag %d no_output_of_prior_pics_flag %d\r\n", + pSlice->long_term_reference_flag, + pSlice->no_output_of_prior_pics_flag); + + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "idr set pre_frame_num(%d) to frame_num (%d)\n", + p_Vid->pre_frame_num, pSlice->frame_num); + + p_Vid->pre_frame_num = pSlice->frame_num; + } + /* pSlice->adaptive_ref_pic_buffering_flag; */ + sps->log2_max_frame_num_minus4 = + p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM] - 4; + + p_Vid->non_conforming_stream = + p_H264_Dpb->dpb_param.l.data[NON_CONFORMING_STREAM]; + p_Vid->recovery_point = + p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT]; + switch (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE]) { + case I_Slice: + pSlice->slice_type = I_SLICE; + break; + case P_Slice: + pSlice->slice_type = P_SLICE; + break; + case B_Slice: + pSlice->slice_type = B_SLICE; + break; + default: + pSlice->slice_type = NUM_SLICE_TYPES; + break; + } + + pSlice->num_ref_idx_active[LIST_0] = + p_H264_Dpb->dpb_param.dpb.num_ref_idx_l0_active_minus1 + + 1; + /* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1]; */ + pSlice->num_ref_idx_active[LIST_1] = + p_H264_Dpb->dpb_param.dpb.num_ref_idx_l1_active_minus1 + + 1; + /* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1]; */ + + pSlice->p_Vid = p_Vid; + pSlice->p_Dpb = p_Dpb; + + p_H264_Dpb->colocated_buf_size = + p_H264_Dpb->dpb_param.l.data[FRAME_SIZE_IN_MB] * 96; + pSlice->first_mb_in_slice = + p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]; + pSlice->mode_8x8_flags = p_H264_Dpb->dpb_param.l.data[MODE_8X8_FLAGS]; + pSlice->picture_structure_mmco = + p_H264_Dpb->dpb_param.dpb.picture_structure_mmco; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s slice_type is %d, num_ref_idx_active[0]=%d, num_ref_idx_active[1]=%d nal_reference_idc %d\n", + __func__, pSlice->slice_type, + pSlice->num_ref_idx_active[LIST_0], + pSlice->num_ref_idx_active[LIST_1], + pSlice->nal_reference_idc); +#ifdef ERROR_CHECK + if (pSlice->num_ref_idx_active[LIST_0] >= MAX_LIST_SIZE) + pSlice->num_ref_idx_active[LIST_0] = MAX_LIST_SIZE - 1; + if (pSlice->num_ref_idx_active[LIST_1] >= MAX_LIST_SIZE) + pSlice->num_ref_idx_active[LIST_1] = MAX_LIST_SIZE - 1; +#endif + +#if 1 + /* dec_ref_pic_marking_buffer */ + pSlice->adaptive_ref_pic_buffering_flag = 0; + if (pSlice->nal_reference_idc) { + for (i = 0, j = 0; i < 44; j++) { + unsigned short val; + struct DecRefPicMarking_s *tmp_drpm = + &pSlice->dec_ref_pic_marking_buffer[j]; + memset(tmp_drpm, 0, sizeof(struct DecRefPicMarking_s)); + val = tmp_drpm-> + memory_management_control_operation = + mmco_cmd[i++]; + tmp_drpm->Next = NULL; + if (j > 0) { + pSlice-> + dec_ref_pic_marking_buffer[j - 1].Next = + tmp_drpm; + } + if (val == 0 || i >= 44) + break; + pSlice->adaptive_ref_pic_buffering_flag = 1; + if ((val == 1) || (val == 3)) { + tmp_drpm->difference_of_pic_nums_minus1 = + mmco_cmd[i++]; + } + if (val == 2) + tmp_drpm->long_term_pic_num = mmco_cmd[i++]; + if (i >= 44) + break; + if ((val == 3) || (val == 6)) + tmp_drpm->long_term_frame_idx = mmco_cmd[i++]; + if (val == 4) { + tmp_drpm->max_long_term_frame_idx_plus1 = + mmco_cmd[i++]; + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "dec_ref_pic_marking_buffer[%d]:operation %x diff_pic_minus1 %x long_pic_num %x long_frame_idx %x max_long_frame_idx_plus1 %x\n", + j, + tmp_drpm->memory_management_control_operation, + tmp_drpm->difference_of_pic_nums_minus1, + tmp_drpm->long_term_pic_num, + tmp_drpm->long_term_frame_idx, + tmp_drpm->max_long_term_frame_idx_plus1); + } + } + + ref_pic_list_reordering(p_H264_Dpb, pSlice); +#endif + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s return\n", __func__); +} + +static void decode_poc(struct VideoParameters *p_Vid, struct Slice *pSlice) +{ + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid, + struct h264_dpb_stru, mVideo); + struct SPSParameters *active_sps = p_Vid->active_sps; + int i; + /* for POC mode 0: */ + unsigned int MaxPicOrderCntLsb = (1 << + (active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); + + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DEBUG_POC, + "%s:pic_order_cnt_type %d, idr_flag %d last_has_mmco_5 %d last_pic_bottom_field %d pic_order_cnt_lsb %d PrevPicOrderCntLsb %d\r\n", + __func__, + active_sps->pic_order_cnt_type, + pSlice->idr_flag, + p_Vid->last_has_mmco_5, + p_Vid->last_pic_bottom_field, + pSlice->pic_order_cnt_lsb, + p_Vid->PrevPicOrderCntLsb + ); + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC, + "%s:field_pic_flag %d, bottom_field_flag %d frame_num %d PreviousFrameNum %d PreviousFrameNumOffset %d ax_frame_num %d num_ref_frames_in_pic_order_cnt_cycle %d offset_for_non_ref_pic %d\r\n", + __func__, + pSlice->field_pic_flag, + pSlice->bottom_field_flag, + pSlice->frame_num, + p_Vid->PreviousFrameNum, + p_Vid->PreviousFrameNumOffset, + p_Vid->max_frame_num, + active_sps->num_ref_frames_in_pic_order_cnt_cycle, + active_sps->offset_for_non_ref_pic + ); + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC, + "%s: delta_pic_order_cnt %d %d nal_reference_idc %d\r\n", + __func__, + pSlice->delta_pic_order_cnt[0], pSlice->delta_pic_order_cnt[1], + pSlice->nal_reference_idc + ); + + + switch (active_sps->pic_order_cnt_type) { + case 0: /* POC MODE 0 */ + /* 1st */ + if (pSlice->idr_flag) { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = 0; + } else { + if (p_Vid->last_has_mmco_5) { + if (p_Vid->last_pic_bottom_field) { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = 0; + } else { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = + pSlice->toppoc; + } + } + } + /* Calculate the MSBs of current picture */ + if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb && + (p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >= + (MaxPicOrderCntLsb / 2)) + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb + + MaxPicOrderCntLsb; + else if (pSlice->pic_order_cnt_lsb > + p_Vid->PrevPicOrderCntLsb && + (pSlice->pic_order_cnt_lsb - + p_Vid->PrevPicOrderCntLsb) > + (MaxPicOrderCntLsb / 2)) + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb - + MaxPicOrderCntLsb; + else + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb; + + /* 2nd */ + if (pSlice->field_pic_flag == 0) { + /* frame pix */ + pSlice->toppoc = pSlice->PicOrderCntMsb + + pSlice->pic_order_cnt_lsb; + pSlice->bottompoc = pSlice->toppoc + + pSlice->delta_pic_order_cnt_bottom; + pSlice->ThisPOC = pSlice->framepoc = + (pSlice->toppoc < pSlice->bottompoc) ? + pSlice->toppoc : pSlice->bottompoc; + /* POC200301 */ + } else if (pSlice->bottom_field_flag == FALSE) { + /* top field */ + pSlice->ThisPOC = pSlice->toppoc = + pSlice->PicOrderCntMsb + + pSlice->pic_order_cnt_lsb; + } else { + /* bottom field */ + pSlice->ThisPOC = pSlice->bottompoc = + pSlice->PicOrderCntMsb + + pSlice->pic_order_cnt_lsb; + } + pSlice->framepoc = pSlice->ThisPOC; + + p_Vid->ThisPOC = pSlice->ThisPOC; + + /* if ( pSlice->frame_num != p_Vid->PreviousFrameNum) + Seems redundant */ + p_Vid->PreviousFrameNum = pSlice->frame_num; + + if (pSlice->nal_reference_idc) { + p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb; + p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb; + } + + break; + + case 1: /* POC MODE 1 */ + /* 1st */ + if (pSlice->idr_flag) { + p_Vid->FrameNumOffset = 0; /* first pix of IDRGOP */ + if (pSlice->frame_num) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "frame_num not equal to zero in IDR picture %d", + -1020); + } else { + if (p_Vid->last_has_mmco_5) { + p_Vid->PreviousFrameNumOffset = 0; + p_Vid->PreviousFrameNum = 0; + } + if (pSlice->frame_num < p_Vid->PreviousFrameNum) { + /* not first pix of IDRGOP */ + p_Vid->FrameNumOffset = + p_Vid->PreviousFrameNumOffset + + p_Vid->max_frame_num; + } else { + p_Vid->FrameNumOffset = + p_Vid->PreviousFrameNumOffset; + } + } + + /* 2nd */ + if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) + pSlice->AbsFrameNum = + p_Vid->FrameNumOffset + pSlice->frame_num; + else + pSlice->AbsFrameNum = 0; + if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0) + pSlice->AbsFrameNum--; + + /* 3rd */ + p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0; + + if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) + for (i = 0; i < (int) active_sps-> + num_ref_frames_in_pic_order_cnt_cycle; i++) { + p_Vid->ExpectedDeltaPerPicOrderCntCycle += + active_sps->offset_for_ref_frame[i]; + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DEBUG_POC, + "%s: offset_for_ref_frame %d\r\n", + __func__, + active_sps-> + offset_for_ref_frame[i]); + } + + if (pSlice->AbsFrameNum) { + p_Vid->PicOrderCntCycleCnt = + (pSlice->AbsFrameNum - 1) / + active_sps-> + num_ref_frames_in_pic_order_cnt_cycle; + p_Vid->FrameNumInPicOrderCntCycle = + (pSlice->AbsFrameNum - 1) % + active_sps-> + num_ref_frames_in_pic_order_cnt_cycle; + p_Vid->ExpectedPicOrderCnt = + p_Vid->PicOrderCntCycleCnt * + p_Vid->ExpectedDeltaPerPicOrderCntCycle; + for (i = 0; i <= (int)p_Vid-> + FrameNumInPicOrderCntCycle; i++) { + p_Vid->ExpectedPicOrderCnt += + active_sps->offset_for_ref_frame[i]; + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DEBUG_POC, + "%s: offset_for_ref_frame %d\r\n", + __func__, + active_sps-> + offset_for_ref_frame[i]); + } + } else + p_Vid->ExpectedPicOrderCnt = 0; + + if (!pSlice->nal_reference_idc) + p_Vid->ExpectedPicOrderCnt += + active_sps->offset_for_non_ref_pic; + + if (pSlice->field_pic_flag == 0) { + /* frame pix */ + pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + + pSlice->delta_pic_order_cnt[0]; + pSlice->bottompoc = pSlice->toppoc + + active_sps->offset_for_top_to_bottom_field + + pSlice->delta_pic_order_cnt[1]; + pSlice->ThisPOC = pSlice->framepoc = + (pSlice->toppoc < pSlice->bottompoc) ? + pSlice->toppoc : pSlice->bottompoc; + /* POC200301 */ + } else if (pSlice->bottom_field_flag == FALSE) { + /* top field */ + pSlice->ThisPOC = pSlice->toppoc = + p_Vid->ExpectedPicOrderCnt + + pSlice->delta_pic_order_cnt[0]; + } else { + /* bottom field */ + pSlice->ThisPOC = pSlice->bottompoc = + p_Vid->ExpectedPicOrderCnt + + active_sps->offset_for_top_to_bottom_field + + pSlice->delta_pic_order_cnt[0]; + } + pSlice->framepoc = pSlice->ThisPOC; + + p_Vid->PreviousFrameNum = pSlice->frame_num; + p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; + + break; + + + case 2: /* POC MODE 2 */ + if (pSlice->idr_flag) { /* IDR picture */ + p_Vid->FrameNumOffset = 0; /* first pix of IDRGOP */ + pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc = + pSlice->bottompoc = 0; + if (pSlice->frame_num) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "frame_num not equal to zero in IDR picture %d", + -1020); + } else { + if (p_Vid->last_has_mmco_5) { + p_Vid->PreviousFrameNum = 0; + p_Vid->PreviousFrameNumOffset = 0; + } + if (pSlice->frame_num < p_Vid->PreviousFrameNum) + p_Vid->FrameNumOffset = + p_Vid->PreviousFrameNumOffset + + p_Vid->max_frame_num; + else + p_Vid->FrameNumOffset = + p_Vid->PreviousFrameNumOffset; + + pSlice->AbsFrameNum = p_Vid->FrameNumOffset + + pSlice->frame_num; + if (!pSlice->nal_reference_idc) + pSlice->ThisPOC = + (2 * pSlice->AbsFrameNum - 1); + else + pSlice->ThisPOC = (2 * pSlice->AbsFrameNum); + + if (pSlice->field_pic_flag == 0) + pSlice->toppoc = pSlice->bottompoc = + pSlice->framepoc = pSlice->ThisPOC; + else if (pSlice->bottom_field_flag == FALSE) + pSlice->toppoc = pSlice->framepoc = + pSlice->ThisPOC; + else + pSlice->bottompoc = pSlice->framepoc = + pSlice->ThisPOC; + } + + p_Vid->PreviousFrameNum = pSlice->frame_num; + p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; + break; + + + default: + /* error must occurs */ + /* assert( 1==0 ); */ + break; + } +} + +void fill_frame_num_gap(struct VideoParameters *p_Vid, struct Slice *currSlice) +{ + struct h264_dpb_stru *p_H264_Dpb = + container_of(p_Vid, struct h264_dpb_stru, mVideo); + struct SPSParameters *active_sps = p_Vid->active_sps; + int CurrFrameNum; + int UnusedShortTermFrameNum; + struct StorablePicture *picture = NULL; + int tmp1 = currSlice->delta_pic_order_cnt[0]; + int tmp2 = currSlice->delta_pic_order_cnt[1]; + currSlice->delta_pic_order_cnt[0] = + currSlice->delta_pic_order_cnt[1] = 0; + + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "A gap in frame number is found, try to fill it.(pre_frame_num %d, max_frame_num %d\n", + p_Vid->pre_frame_num, p_Vid->max_frame_num + ); + + UnusedShortTermFrameNum = (p_Vid->pre_frame_num + 1) + % p_Vid->max_frame_num; + CurrFrameNum = currSlice->frame_num; /*p_Vid->frame_num;*/ + + while (CurrFrameNum != UnusedShortTermFrameNum) { + /*picture = alloc_storable_picture + (p_Vid, FRAME, p_Vid->width, + p_Vid->height, + p_Vid->width_cr, + p_Vid->height_cr, 1);*/ + picture = get_new_pic(p_H264_Dpb, + p_H264_Dpb->mSlice.structure, + /*p_Vid->width, p_Vid->height, + p_Vid->width_cr, + p_Vid->height_cr,*/ 1); + + if (picture == NULL) { + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s Error: get_new_pic return NULL\r\n", + __func__); + h264_debug_flag |= PRINT_FLAG_DUMP_DPB; + dump_dpb(p_Dpb); + return; + } + + picture->colocated_buf_index = -1; + picture->buf_spec_num = -1; + + picture->coded_frame = 1; + picture->pic_num = UnusedShortTermFrameNum; + picture->frame_num = UnusedShortTermFrameNum; + picture->non_existing = 1; + picture->is_output = 1; + picture->used_for_reference = 1; + picture->adaptive_ref_pic_buffering_flag = 0; + #if (MVC_EXTENSION_ENABLE) + picture->view_id = currSlice->view_id; + #endif + + currSlice->frame_num = UnusedShortTermFrameNum; + if (active_sps->pic_order_cnt_type != 0) { + /*decode_poc(p_Vid, p_Vid->ppSliceList[0]);*/ + decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice); + } + picture->top_poc = currSlice->toppoc; + picture->bottom_poc = currSlice->bottompoc; + picture->frame_poc = currSlice->framepoc; + picture->poc = currSlice->framepoc; + + store_picture_in_dpb(p_H264_Dpb, picture); + + picture = NULL; + p_Vid->pre_frame_num = UnusedShortTermFrameNum; + UnusedShortTermFrameNum = + (UnusedShortTermFrameNum + 1) % + p_Vid->max_frame_num; + } + currSlice->delta_pic_order_cnt[0] = tmp1; + currSlice->delta_pic_order_cnt[1] = tmp2; + currSlice->frame_num = CurrFrameNum; +} + +void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb, + int id, int actual_dpb_size, int max_reference_size) +{ + int i; + init_dummy_fs(); + + memset(&p_H264_Dpb->mDPB, 0, sizeof(struct DecodedPictureBuffer)); + + memset(&p_H264_Dpb->mSlice, 0, sizeof(struct Slice)); + memset(&p_H264_Dpb->mVideo, 0, sizeof(struct VideoParameters)); + memset(&p_H264_Dpb->mSPS, 0, sizeof(struct SPSParameters)); + + for (i = 0; i < DPB_SIZE_MAX; i++) { + memset(&(p_H264_Dpb->mFrameStore[i]), 0, + sizeof(struct FrameStore)); + } + + for (i = 0; i < MAX_PIC_BUF_NUM; i++) { + memset(&(p_H264_Dpb->m_PIC[i]), 0, + sizeof(struct StorablePicture)); + p_H264_Dpb->m_PIC[i].index = i; + } + p_H264_Dpb->decoder_index = id; + + /* make sure dpb_init_global + can be called during decoding + (in DECODE_STATE_IDLE or DECODE_STATE_READY state) */ + p_H264_Dpb->mDPB.size = actual_dpb_size; + p_H264_Dpb->max_reference_size = max_reference_size; +} + +static void init_picture(struct h264_dpb_stru *p_H264_Dpb, + struct Slice *currSlice, + struct StorablePicture *dec_picture) +{ + /* struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo); */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s dec_picture %p\n", __func__, dec_picture); + dec_picture->top_poc = currSlice->toppoc; + dec_picture->bottom_poc = currSlice->bottompoc; + dec_picture->frame_poc = currSlice->framepoc; + switch (currSlice->structure) { + case TOP_FIELD: { + dec_picture->poc = currSlice->toppoc; + /* p_Vid->number *= 2; */ + break; + } + case BOTTOM_FIELD: { + dec_picture->poc = currSlice->bottompoc; + /* p_Vid->number = p_Vid->number * 2 + 1; */ + break; + } + case FRAME: { + dec_picture->poc = currSlice->framepoc; + break; + } + default: + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "p_Vid->structure not initialized %d\n", 235); + } + + /* dec_picture->slice_type = p_Vid->type; */ + dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0); + dec_picture->idr_flag = currSlice->idr_flag; + dec_picture->no_output_of_prior_pics_flag = + currSlice->no_output_of_prior_pics_flag; + dec_picture->long_term_reference_flag = + currSlice->long_term_reference_flag; +#if 1 + dec_picture->adaptive_ref_pic_buffering_flag = + currSlice->adaptive_ref_pic_buffering_flag; + dec_picture->dec_ref_pic_marking_buffer = + &currSlice->dec_ref_pic_marking_buffer[0]; +#endif + /* currSlice->dec_ref_pic_marking_buffer = NULL; */ + + /* dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; */ + /* dec_picture->PicWidthInMbs = p_Vid->PicWidthInMbs; */ + + /* p_Vid->get_mb_block_pos = + dec_picture->mb_aff_frame_flag ? get_mb_block_pos_mbaff : + get_mb_block_pos_normal; */ + /* p_Vid->getNeighbour = + dec_picture->mb_aff_frame_flag ? getAffNeighbour : + getNonAffNeighbour; */ + + dec_picture->pic_num = currSlice->frame_num; + dec_picture->frame_num = currSlice->frame_num; + + /* dec_picture->recovery_frame = + (unsigned int) ((int) currSlice->frame_num == + p_Vid->recovery_frame_num); */ + + dec_picture->coded_frame = (currSlice->structure == FRAME); + + /* dec_picture->chroma_format_idc = active_sps->chroma_format_idc; */ + + /* dec_picture->frame_mbs_only_flag = + active_sps->frame_mbs_only_flag; */ + /* dec_picture->frame_cropping_flag = + active_sps->frame_cropping_flag; */ + + if ((currSlice->picture_structure_mmco & 0x3) == 3) { + dec_picture->mb_aff_frame_flag = 1; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s, picture_structure_mmco is %x, set mb_aff_frame_flag to 1\n", + __func__, + currSlice->picture_structure_mmco); + } + +} + +static struct StorablePicture *get_new_pic(struct h264_dpb_stru *p_H264_Dpb, + enum PictureStructure structure, unsigned char is_output) +{ + struct StorablePicture *s = NULL; + struct StorablePicture *pic; + struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo); + /* recycle un-used pic */ + int ii = 0; + + for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) { + pic = &(p_H264_Dpb->m_PIC[ii]); + if (pic->is_used == 0) { + pic->is_used = 1; + s = pic; + break; + } + } + + if (s) { + s->pic_num = 0; + s->frame_num = 0; + s->long_term_frame_idx = 0; + s->long_term_pic_num = 0; + s->used_for_reference = 0; + s->is_long_term = 0; + s->non_existing = 0; + s->is_output = 0; + s->pre_output = 0; + s->max_slice_id = 0; +#if (MVC_EXTENSION_ENABLE) + s->view_id = -1; +#endif + + s->structure = structure; + +#if 0 + s->size_x = size_x; + s->size_y = size_y; + s->size_x_cr = size_x_cr; + s->size_y_cr = size_y_cr; + s->size_x_m1 = size_x - 1; + s->size_y_m1 = size_y - 1; + s->size_x_cr_m1 = size_x_cr - 1; + s->size_y_cr_m1 = size_y_cr - 1; + + s->top_field = p_Vid->no_reference_picture; + s->bottom_field = p_Vid->no_reference_picture; + s->frame = p_Vid->no_reference_picture; +#endif + /* s->dec_ref_pic_marking_buffer = NULL; */ + + s->coded_frame = 0; + s->mb_aff_frame_flag = 0; + + s->top_poc = s->bottom_poc = s->poc = 0; + s->seiHasTone_mapping = 0; + + if (!p_Vid->active_sps->frame_mbs_only_flag && + structure != FRAME) { + int i, j; + for (j = 0; j < MAX_NUM_SLICES; j++) { + for (i = 0; i < 2; i++) { + /* s->listX[j][i] = + calloc(MAX_LIST_SIZE, + sizeof (struct StorablePicture *)); + +1 for reordering ??? + + if (NULL == s->listX[j][i]) + no_mem_exit("alloc_storable_picture: + s->listX[i]"); */ + } + } + } + } + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s %p\n", __func__, s); + return s; +} + +static void free_picture(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *pic) +{ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s %p %d\n", __func__, pic, pic->index); + /* assert(pic->indexm_PIC[pic->index].is_used = 0; +} + +static void gen_field_ref_ids(struct VideoParameters *p_Vid, + struct StorablePicture *p) +{ + int i, j; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid, + struct h264_dpb_stru, mVideo); + /* ! Generate Frame parameters from field information. */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + /* copy the list; */ + for (j = 0; j < p_Vid->iSliceNumOfCurrPic; j++) { + if (p->listX[j][LIST_0]) { + p->listXsize[j][LIST_0] = + p_Vid->ppSliceList[j]->listXsize[LIST_0]; + for (i = 0; i < p->listXsize[j][LIST_0]; i++) + p->listX[j][LIST_0][i] = + p_Vid->ppSliceList[j]->listX[LIST_0][i]; + } + if (p->listX[j][LIST_1]) { + p->listXsize[j][LIST_1] = + p_Vid->ppSliceList[j]->listXsize[LIST_1]; + for (i = 0; i < p->listXsize[j][LIST_1]; i++) + p->listX[j][LIST_1][i] = + p_Vid->ppSliceList[j]->listX[LIST_1][i]; + } + } +} + +static void init_dpb(struct h264_dpb_stru *p_H264_Dpb, int type) +{ + unsigned i; + struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + struct SPSParameters *active_sps = &p_H264_Dpb->mSPS; + + p_Vid->active_sps = active_sps; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + p_Dpb->p_Vid = p_Vid; + if (p_Dpb->init_done) { + /* free_dpb(p_Dpb); */ + if (p_Vid->no_reference_picture) { + free_picture(p_H264_Dpb, p_Vid->no_reference_picture); + p_Vid->no_reference_picture = NULL; + } + p_Dpb->init_done = 0; + } + + /* p_Dpb->size = 10; //active_sps->max_dpb_size; //16; + getDpbSize(p_Vid, active_sps) + + p_Vid->p_Inp->dpb_plus[type==2? 1: 0]; + p_Dpb->size = active_sps->max_dpb_size; //16; + getDpbSize(p_Vid, active_sps) + + p_Vid->p_Inp->dpb_plus[type==2? 1: 0]; + p_Dpb->size initialzie in vh264.c */ + p_Dpb->num_ref_frames = active_sps->num_ref_frames; + /* p_Dpb->num_ref_frames initialzie in vh264.c */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s dpb_size is %d (%d) num_ref_frames = %d (%d)\n", + __func__, p_Dpb->size, active_sps->max_dpb_size, + p_Dpb->num_ref_frames, + active_sps->num_ref_frames); + +#if 0 + /* ??? */ +#if (MVC_EXTENSION_ENABLE) + if ((unsigned int)active_sps->max_dec_frame_buffering < + active_sps->num_ref_frames) { +#else + if (p_Dpb->size < active_sps->num_ref_frames) { +#endif + error( + "DPB size at specified level is smaller than the specified number of reference frames. This is not allowed.\n", + 1000); + } +#endif + + p_Dpb->used_size = 0; + p_Dpb->last_picture = NULL; + + p_Dpb->ref_frames_in_buffer = 0; + p_Dpb->ltref_frames_in_buffer = 0; + +#if 0 + p_Dpb->fs = calloc(p_Dpb->size, sizeof(struct FrameStore *)); + if (NULL == p_Dpb->fs) + no_mem_exit("init_dpb: p_Dpb->fs"); + + p_Dpb->fs_ref = calloc(p_Dpb->size, sizeof(struct FrameStore *)); + if (NULL == p_Dpb->fs_ref) + no_mem_exit("init_dpb: p_Dpb->fs_ref"); + + p_Dpb->fs_ltref = calloc(p_Dpb->size, sizeof(struct FrameStore *)); + if (NULL == p_Dpb->fs_ltref) + no_mem_exit("init_dpb: p_Dpb->fs_ltref"); +#endif + +#if (MVC_EXTENSION_ENABLE) + p_Dpb->fs_ilref = calloc(1, sizeof(struct FrameStore *)); + if (NULL == p_Dpb->fs_ilref) + no_mem_exit("init_dpb: p_Dpb->fs_ilref"); +#endif + + for (i = 0; i < p_Dpb->size; i++) { + p_Dpb->fs[i] = &(p_H264_Dpb->mFrameStore[i]); + /* alloc_frame_store(); */ + p_Dpb->fs[i]->index = i; + p_Dpb->fs_ref[i] = NULL; + p_Dpb->fs_ltref[i] = NULL; + p_Dpb->fs[i]->layer_id = 0; /* MVC_INIT_VIEW_ID; */ +#if (MVC_EXTENSION_ENABLE) + p_Dpb->fs[i]->view_id = MVC_INIT_VIEW_ID; + p_Dpb->fs[i]->inter_view_flag[0] = + p_Dpb->fs[i]->inter_view_flag[1] = 0; + p_Dpb->fs[i]->anchor_pic_flag[0] = + p_Dpb->fs[i]->anchor_pic_flag[1] = 0; +#endif + } +#if (MVC_EXTENSION_ENABLE) + if (type == 2) { + p_Dpb->fs_ilref[0] = alloc_frame_store(); + /* These may need some cleanups */ + p_Dpb->fs_ilref[0]->view_id = MVC_INIT_VIEW_ID; + p_Dpb->fs_ilref[0]->inter_view_flag[0] = + p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0; + p_Dpb->fs_ilref[0]->anchor_pic_flag[0] = + p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0; + /* given that this is in a different buffer, + do we even need proc_flag anymore? */ + } else + p_Dpb->fs_ilref[0] = NULL; +#endif + + /* + for (i = 0; i < 6; i++) + { + currSlice->listX[i] = + calloc(MAX_LIST_SIZE, sizeof (struct StorablePicture *)); + +1 for reordering + if (NULL == currSlice->listX[i]) + no_mem_exit("init_dpb: currSlice->listX[i]"); + } + */ + /* allocate a dummy storable picture */ + if (!p_Vid->no_reference_picture) { + p_Vid->no_reference_picture = get_new_pic(p_H264_Dpb, + FRAME, + /*p_Vid->width, p_Vid->height, + p_Vid->width_cr, p_Vid->height_cr,*/ 1); + p_Vid->no_reference_picture->top_field = + p_Vid->no_reference_picture; + p_Vid->no_reference_picture->bottom_field = + p_Vid->no_reference_picture; + p_Vid->no_reference_picture->frame = + p_Vid->no_reference_picture; + } + p_Dpb->last_output_poc = INT_MIN; + +#if (MVC_EXTENSION_ENABLE) + p_Dpb->last_output_view_id = -1; +#endif + + p_Vid->last_has_mmco_5 = 0; + + init_colocate_buf(p_H264_Dpb, p_H264_Dpb->max_reference_size); + + p_Dpb->init_done = 1; + +#if 0 +/* ??? */ + /* picture error concealment */ + if (p_Vid->conceal_mode != 0 && !p_Vid->last_out_fs) + p_Vid->last_out_fs = alloc_frame_store(); +#endif +} + +static void dpb_split_field(struct h264_dpb_stru *p_H264_Dpb, + struct FrameStore *fs) +{ + struct StorablePicture *fs_top = NULL, *fs_btm = NULL; + struct StorablePicture *frame = fs->frame; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s %p %p\n", __func__, fs, frame); + + fs->poc = frame->poc; + + if (!frame->frame_mbs_only_flag) { + fs_top = fs->top_field = get_new_pic(p_H264_Dpb, + TOP_FIELD, + /* frame->size_x, frame->size_y, + frame->size_x_cr, frame->size_y_cr,*/ 1); + fs_btm = fs->bottom_field = get_new_pic(p_H264_Dpb, + BOTTOM_FIELD, + /*frame->size_x, frame->size_y, + frame->size_x_cr, frame->size_y_cr,*/ 1); + if (fs_top == NULL || fs_btm == NULL) + return; +#if 1 +/* rain */ + fs_top->buf_spec_num = frame->buf_spec_num; + fs_btm->buf_spec_num = frame->buf_spec_num; + + fs_top->colocated_buf_index = frame->colocated_buf_index; + fs_btm->colocated_buf_index = frame->colocated_buf_index; +#endif + fs_top->poc = frame->top_poc; + fs_btm->poc = frame->bottom_poc; + +#if (MVC_EXTENSION_ENABLE) + fs_top->view_id = frame->view_id; + fs_btm->view_id = frame->view_id; +#endif + + fs_top->frame_poc = frame->frame_poc; + + fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc; + fs_top->top_poc = fs_btm->top_poc = frame->top_poc; + fs_btm->frame_poc = frame->frame_poc; + + fs_top->used_for_reference = fs_btm->used_for_reference + = frame->used_for_reference; + fs_top->is_long_term = fs_btm->is_long_term + = frame->is_long_term; + fs->long_term_frame_idx = fs_top->long_term_frame_idx + = fs_btm->long_term_frame_idx + = frame->long_term_frame_idx; + + fs_top->coded_frame = fs_btm->coded_frame = 1; + fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag + = frame->mb_aff_frame_flag; + + frame->top_field = fs_top; + frame->bottom_field = fs_btm; + frame->frame = frame; + fs_top->bottom_field = fs_btm; + fs_top->frame = frame; + fs_top->top_field = fs_top; + fs_btm->top_field = fs_top; + fs_btm->frame = frame; + fs_btm->bottom_field = fs_btm; + +#if (MVC_EXTENSION_ENABLE) + fs_top->view_id = fs_btm->view_id = fs->view_id; + fs_top->inter_view_flag = fs->inter_view_flag[0]; + fs_btm->inter_view_flag = fs->inter_view_flag[1]; +#endif + + fs_top->chroma_format_idc = fs_btm->chroma_format_idc = + frame->chroma_format_idc; + fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType; + } else { + fs->top_field = NULL; + fs->bottom_field = NULL; + frame->top_field = NULL; + frame->bottom_field = NULL; + frame->frame = frame; + } + +} + + +static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb, + struct FrameStore *fs) +{ + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + if (!fs->frame) { + fs->frame = get_new_pic(p_H264_Dpb, + FRAME, + /* fs->top_field->size_x, fs->top_field->size_y*2, + fs->top_field->size_x_cr, fs->top_field->size_y_cr*2, + */ 1); + } + if (!fs->frame) + return; +#if 1 +/* rain */ + fs->frame->buf_spec_num = fs->top_field->buf_spec_num; + fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index; +#endif + + + fs->poc = fs->frame->poc = fs->frame->frame_poc = imin( + fs->top_field->poc, fs->bottom_field->poc); + + fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; + + fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; + fs->top_field->bottom_poc = fs->frame->bottom_poc = + fs->bottom_field->poc; + + fs->frame->used_for_reference = (fs->top_field->used_for_reference && + fs->bottom_field->used_for_reference); + fs->frame->is_long_term = (fs->top_field->is_long_term && + fs->bottom_field->is_long_term); + + if (fs->frame->is_long_term) + fs->frame->long_term_frame_idx = fs->long_term_frame_idx; + + fs->frame->top_field = fs->top_field; + fs->frame->bottom_field = fs->bottom_field; + fs->frame->frame = fs->frame; + + fs->frame->coded_frame = 0; + + fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc; + fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag; + if (fs->frame->frame_cropping_flag) { + fs->frame->frame_crop_top_offset = + fs->top_field->frame_crop_top_offset; + fs->frame->frame_crop_bottom_offset = + fs->top_field->frame_crop_bottom_offset; + fs->frame->frame_crop_left_offset = + fs->top_field->frame_crop_left_offset; + fs->frame->frame_crop_right_offset = + fs->top_field->frame_crop_right_offset; + } + + fs->top_field->frame = fs->bottom_field->frame = fs->frame; + fs->top_field->top_field = fs->top_field; + fs->top_field->bottom_field = fs->bottom_field; + fs->bottom_field->top_field = fs->top_field; + fs->bottom_field->bottom_field = fs->bottom_field; + + /**/ +#if (MVC_EXTENSION_ENABLE) + fs->frame->view_id = fs->view_id; +#endif + fs->frame->iCodingType = fs->top_field->iCodingType; + /* FIELD_CODING ;*/ +} + +static void calculate_frame_no(struct VideoParameters *p_Vid, + struct StorablePicture *p) +{ +#if 0 +/* ??? */ + InputParameters *p_Inp = p_Vid->p_Inp; + /* calculate frame number */ + int psnrPOC = p_Vid->active_sps->mb_adaptive_frame_field_flag ? + p->poc / (p_Inp->poc_scale) : p->poc / (p_Inp->poc_scale); + + if (psnrPOC == 0) { /* && p_Vid->psnr_number) */ + p_Vid->idr_psnr_number = + p_Vid->g_nFrame * p_Vid->ref_poc_gap / (p_Inp->poc_scale); + } + p_Vid->psnr_number = imax(p_Vid->psnr_number, + p_Vid->idr_psnr_number + psnrPOC); + + p_Vid->frame_no = p_Vid->idr_psnr_number + psnrPOC; +#endif +} + +static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, + struct FrameStore *fs, + struct StorablePicture *p) +{ + struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; + /* InputParameters *p_Inp = p_Vid->p_Inp; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "insert (%s) pic with frame_num #%d, poc %d\n", + (p->structure == FRAME)?"FRAME": + (p->structure == TOP_FIELD)?"TOP_FIELD": + "BOTTOM_FIELD", p->pic_num, p->poc); + assert (p!=NULL); + assert (fs!=NULL);*/ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s %p %p\n", __func__, fs, p); +#if 1 +/* rain */ +/* p->buf_spec_num = fs->index; */ + fs->buf_spec_num = p->buf_spec_num; + fs->colocated_buf_index = p->colocated_buf_index; +#endif + switch (p->structure) { + case FRAME: + fs->frame = p; + fs->is_used = 3; + if (p->used_for_reference) { + fs->is_reference = 3; + fs->is_orig_reference = 3; + if (p->is_long_term) { + fs->is_long_term = 3; + fs->long_term_frame_idx = + p->long_term_frame_idx; + } + } + fs->layer_id = p->layer_id; +#if (MVC_EXTENSION_ENABLE) + fs->view_id = p->view_id; + fs->inter_view_flag[0] = fs->inter_view_flag[1] = + p->inter_view_flag; + fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] = + p->anchor_pic_flag; +#endif + /* generate field views */ + /* return; */ + dpb_split_field(p_H264_Dpb, fs); + /* return; */ + break; + case TOP_FIELD: + fs->top_field = p; + fs->is_used |= 1; + fs->layer_id = p->layer_id; +#if (MVC_EXTENSION_ENABLE) + fs->view_id = p->view_id; + fs->inter_view_flag[0] = p->inter_view_flag; + fs->anchor_pic_flag[0] = p->anchor_pic_flag; +#endif + if (p->used_for_reference) { + fs->is_reference |= 1; + fs->is_orig_reference |= 1; + if (p->is_long_term) { + fs->is_long_term |= 1; + fs->long_term_frame_idx = + p->long_term_frame_idx; + } + } + if (fs->is_used == 3) { + /* generate frame view */ + dpb_combine_field(p_H264_Dpb, fs); + } else { + fs->poc = p->poc; + } + gen_field_ref_ids(p_Vid, p); + break; + case BOTTOM_FIELD: + fs->bottom_field = p; + fs->is_used |= 2; + fs->layer_id = p->layer_id; +#if (MVC_EXTENSION_ENABLE) + fs->view_id = p->view_id; + fs->inter_view_flag[1] = p->inter_view_flag; + fs->anchor_pic_flag[1] = p->anchor_pic_flag; +#endif + if (p->used_for_reference) { + fs->is_reference |= 2; + fs->is_orig_reference |= 2; + if (p->is_long_term) { + fs->is_long_term |= 2; + fs->long_term_frame_idx = + p->long_term_frame_idx; + } + } + if (fs->is_used == 3) { + /* generate frame view */ + dpb_combine_field(p_H264_Dpb, fs); + } else { + fs->poc = p->poc; + } + gen_field_ref_ids(p_Vid, p); + break; + } + fs->frame_num = p->pic_num; + fs->recovery_frame = p->recovery_frame; + + fs->is_output = p->is_output; + fs->pre_output = p->pre_output; + + if (fs->is_used == 3) { + calculate_frame_no(p_Vid, p); +#if 0 +/* ??? */ + if (-1 != p_Vid->p_ref && !p_Inp->silent) + find_snr(p_Vid, fs->frame, &p_Vid->p_ref); +#endif + } + + fs->pts = p->pts; + fs->pts64 = p->pts64; +} + +void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb, + struct FrameStore *f) +{ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + if (f) { + if (f->frame) { + free_picture(p_H264_Dpb, f->frame); + f->frame = NULL; + } + if (f->top_field) { + free_picture(p_H264_Dpb, f->top_field); + f->top_field = NULL; + } + if (f->bottom_field) { + free_picture(p_H264_Dpb, f->bottom_field); + f->bottom_field = NULL; + } + + /**/ + f->is_used = 0; + f->is_reference = 0; + f->is_long_term = 0; + f->is_orig_reference = 0; + + f->is_output = 0; + f->pre_output = 0; + + f->frame = NULL; + f->top_field = NULL; + f->bottom_field = NULL; + + /* free(f); */ + } +} + +static void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb, + struct FrameStore *fs) +{ + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s %p %p %p %p\n", __func__, + fs, fs->frame, fs->top_field, fs->bottom_field); + /* return; */ + if (fs->is_used & 1) { + if (fs->top_field) + fs->top_field->used_for_reference = 0; + } + if (fs->is_used & 2) { + if (fs->bottom_field) + fs->bottom_field->used_for_reference = 0; + } + if (fs->is_used == 3) { + if (fs->top_field && fs->bottom_field) { + fs->top_field->used_for_reference = 0; + fs->bottom_field->used_for_reference = 0; + } + fs->frame->used_for_reference = 0; + } + + fs->is_reference = 0; + +} + +int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb, + int buf_spec_num) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + unsigned i; + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]->buf_spec_num == buf_spec_num) + return p_Dpb->fs[i]->is_long_term; + } + return -1; +} + +static void update_pic_num(struct Slice *currSlice) +{ + unsigned int i; + struct VideoParameters *p_Vid = currSlice->p_Vid; + struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb; + struct SPSParameters *active_sps = p_Vid->active_sps; + + int add_top = 0, add_bottom = 0; + int max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4); + + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used == 3) { + if ((p_Dpb->fs_ref[i]->frame-> + used_for_reference) && + (!p_Dpb->fs_ref[i]->frame-> + is_long_term)) { + if (p_Dpb->fs_ref[i]->frame_num > + currSlice->frame_num) { + p_Dpb->fs_ref[i]-> + frame_num_wrap = + p_Dpb->fs_ref[i]->frame_num + - max_frame_num; + } else { + p_Dpb->fs_ref[i]-> + frame_num_wrap = + p_Dpb->fs_ref[i]->frame_num; + } + p_Dpb->fs_ref[i]->frame->pic_num = + p_Dpb->fs_ref[i]->frame_num_wrap; + } + } + } + /* update long_term_pic_num */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_used == 3) { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) { + p_Dpb->fs_ltref[i]->frame-> + long_term_pic_num = + p_Dpb->fs_ltref[i]->frame-> + long_term_frame_idx; + } + } + } + } else { + if (currSlice->structure == TOP_FIELD) { + add_top = 1; + add_bottom = 0; + } else { + add_top = 0; + add_bottom = 1; + } + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference) { + if (p_Dpb->fs_ref[i]->frame_num > currSlice-> + frame_num) { + p_Dpb->fs_ref[i]->frame_num_wrap = + p_Dpb->fs_ref[i]->frame_num - + max_frame_num; + } else { + p_Dpb->fs_ref[i]->frame_num_wrap = + p_Dpb->fs_ref[i]->frame_num; + } + if (p_Dpb->fs_ref[i]->is_reference & 1) { + p_Dpb->fs_ref[i]->top_field-> + pic_num = (2 * p_Dpb->fs_ref[i]-> + frame_num_wrap) + add_top; + } + if (p_Dpb->fs_ref[i]->is_reference & 2) { + p_Dpb->fs_ref[i]->bottom_field-> + pic_num = (2 * p_Dpb->fs_ref[i]-> + frame_num_wrap) + add_bottom; + } + } + } + /* update long_term_pic_num */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_long_term & 1) { + p_Dpb->fs_ltref[i]->top_field-> + long_term_pic_num = 2 * + p_Dpb->fs_ltref[i]->top_field-> + long_term_frame_idx + add_top; + } + if (p_Dpb->fs_ltref[i]->is_long_term & 2) { + p_Dpb->fs_ltref[i]->bottom_field-> + long_term_pic_num = 2 * + p_Dpb->fs_ltref[i]->bottom_field-> + long_term_frame_idx + add_bottom; + } + } + } +} + +static void remove_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb, int pos) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + struct FrameStore *fs = p_Dpb->fs[pos]; + struct FrameStore *tmp; + unsigned i; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s pos %d %p\n", __func__, pos, fs); + + /* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "remove frame with frame_num #%d\n", fs->frame_num); */ + switch (fs->is_used) { + case 3: + free_picture(p_H264_Dpb, fs->frame); + free_picture(p_H264_Dpb, fs->top_field); + free_picture(p_H264_Dpb, fs->bottom_field); + fs->frame = NULL; + fs->top_field = NULL; + fs->bottom_field = NULL; + break; + case 2: + free_picture(p_H264_Dpb, fs->bottom_field); + fs->bottom_field = NULL; + break; + case 1: + free_picture(p_H264_Dpb, fs->top_field); + fs->top_field = NULL; + break; + case 0: + break; + default: + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "invalid frame store type %x", 500); + } + fs->is_used = 0; + fs->is_long_term = 0; + fs->is_reference = 0; + fs->is_orig_reference = 0; + + /* move empty framestore to end of buffer */ + tmp = p_Dpb->fs[pos]; + + for (i = pos; i < p_Dpb->used_size - 1; i++) + p_Dpb->fs[i] = p_Dpb->fs[i + 1]; + p_Dpb->fs[p_Dpb->used_size - 1] = tmp; + p_Dpb->used_size--; +} + +static int is_used_for_reference(struct FrameStore *fs) +{ + if (fs->is_reference) + return 1; + + if (fs->is_used == 3) { /* frame */ + if (fs->frame->used_for_reference) + return 1; + } + + if (fs->is_used & 1) { /* top field */ + if (fs->top_field) { + if (fs->top_field->used_for_reference) + return 1; + } + } + + if (fs->is_used & 2) { /* bottom field */ + if (fs->bottom_field) { + if (fs->bottom_field->used_for_reference) + return 1; + } + } + return 0; +} + +static int remove_unused_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb) +{ + unsigned i; + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + /* check for frames that were already output and no longer + used for reference */ + for (i = 0; i < p_Dpb->used_size; i++) { + if ((!is_used_for_reference(p_Dpb->fs[i])) && + (p_Dpb->fs[i]->colocated_buf_index >= 0)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "release_colocate_buf[%d] for fs[%d]\n", + p_Dpb->fs[i]->colocated_buf_index, i); + + release_colocate_buf(p_H264_Dpb, + p_Dpb->fs[i]->colocated_buf_index); /* rain */ + p_Dpb->fs[i]->colocated_buf_index = -1; + } + } + + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]->is_output && + (!is_used_for_reference(p_Dpb->fs[i]))) { + release_buf_spec_num(p_H264_Dpb->vdec, + p_Dpb->fs[i]->buf_spec_num); + p_Dpb->fs[i]->buf_spec_num = -1; + remove_frame_from_dpb(p_H264_Dpb, i); + + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%s[%d]\n", + __func__, i); + + return 1; + } + } + return 0; +} + +void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + int ret = 0; + unsigned char print_flag = 0; + do { + ret = remove_unused_frame_from_dpb(p_H264_Dpb); + if (ret != 0) + print_flag = 1; + } while (ret != 0); + if (print_flag) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%s\r\n", __func__); + dump_dpb(p_Dpb); + } +} + +#ifdef OUTPUT_BUFFER_IN_C +int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb) +{ + unsigned i; + + /* check for frames that were already output and no longer + * used for reference */ + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]->is_output && + (!is_used_for_reference(p_Dpb->fs[i]))) { + return 1; + } + } + return 0; +} +#endif + +static void get_smallest_poc(struct DecodedPictureBuffer *p_Dpb, int *poc, + int *pos) +{ + unsigned i; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%s\n", __func__); + if (p_Dpb->used_size < 1) { + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "Cannot determine smallest POC, DPB empty. %d\n", + 150); + } + + *pos = -1; + *poc = INT_MAX; + for (i = 0; i < p_Dpb->used_size; i++) { +#ifdef OUTPUT_BUFFER_IN_C + /* rain */ + if ((*poc > p_Dpb->fs[i]->poc) && + (!p_Dpb->fs[i]->is_output) && + (!p_Dpb->fs[i]->pre_output)) { +#else + if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) { +#endif + *poc = p_Dpb->fs[i]->poc; + *pos = i; + } + } +} + +#ifdef OLD_OUTPUT_CODE +static int output_one_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; + int poc, pos; + /* diagnostics */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + if (p_Dpb->used_size < 1) { + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "Cannot output frame, DPB empty. %d\n", 150); + } + + /* find smallest POC */ + get_smallest_poc(p_Dpb, &poc, &pos); + + if (pos == -1) + return 0; + + /* call the output function */ + /* dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "output frame with frame_num #%d, poc %d" + "(dpb. p_Dpb->size = %d, p_Dpb->used_size = %d)\n", + p_Dpb->fs[pos]->frame_num, p_Dpb->fs[pos]->frame->poc, + p_Dpb->size, p_Dpb->used_size); + */ + +#if 0 + /* ??? */ + /* picture error concealment */ + if (p_Vid->conceal_mode != 0) { + if (p_Dpb->last_output_poc == 0) + write_lost_ref_after_idr(p_Dpb, pos); +#if (MVC_EXTENSION_ENABLE) + write_lost_non_ref_pic(p_Dpb, poc, + p_Vid->p_out_mvc[p_Dpb->layer_id]); +#else + write_lost_non_ref_pic(p_Dpb, poc, p_Vid->p_out); +#endif + } +#endif +/* JVT-P072 ends */ + +#if 0 +/* ??? */ +#if (MVC_EXTENSION_ENABLE) + write_stored_frame(p_Vid, p_Dpb->fs[pos], + p_Vid->p_out_mvc[p_Dpb->layer_id]); +#else + write_stored_frame(p_Vid, p_Dpb->fs[pos], p_Vid->p_out); +#endif +#endif + /* picture error concealment */ + if (p_Vid->conceal_mode == 0) { + if (p_Dpb->last_output_poc >= poc) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "output POC must be in ascending order %d\n", + 150); + } + } + + p_Dpb->last_output_poc = poc; + + /* free frame store and move empty store to end of buffer */ +/* #ifdef OUTPUT_BUFFER_IN_C */ + if ((h264_debug_flag & OUTPUT_CURRENT_BUF) == 0) { + if (prepare_display_buf(p_H264_Dpb->vdec, + p_Dpb->fs[pos]) >= 0) { + p_Dpb->fs[pos]->pre_output = 1; + } + } +/* #else */ + else { + if (!is_used_for_reference(p_Dpb->fs[pos])) { + release_colocate_buf(p_H264_Dpb, + p_Dpb->fs[pos]->colocated_buf_index); /*rain*/ + p_Dpb->fs[pos]->colocated_buf_index = -1; + + release_buf_spec_num(p_H264_Dpb->vdec, + p_Dpb->fs[pos]->buf_spec_num); + p_Dpb->fs[pos]->buf_spec_num = -1; + + remove_frame_from_dpb(p_H264_Dpb, pos); + } +/* #endif */ + } + return 1; +} + +#else +/* none OLD_OUTPUT_CODE */ + +int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) +{ + int poc, pos; + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + int i; + int none_displayed_num = 0; + if (!flush_flag) { + for (i = 0; i < p_Dpb->used_size; i++) { + if ((!p_Dpb->fs[i]->is_output) && + (!p_Dpb->fs[i]->pre_output)) + none_displayed_num++; + } + if (none_displayed_num < p_H264_Dpb->reorder_pic_num) + return 0; + } + + get_smallest_poc(p_Dpb, &poc, &pos); + + if (pos == -1) + return 0; +#if 0 + if (is_used_for_reference(p_Dpb->fs[pos])) + return 0; +#endif + p_Dpb->last_output_poc = poc; + + if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) + p_Dpb->fs[pos]->pre_output = 1; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s[%d] poc %d\n", __func__, pos, poc); + + return 1; + +} +#endif + + +static void flush_dpb(struct h264_dpb_stru *p_H264_Dpb) +{ + /* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + unsigned i; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + /* diagnostics */ + /* dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "Flush remaining frames from the dpb." + "p_Dpb->size = %d, p_Dpb->used_size = %d\n", + p_Dpb->size, p_Dpb->used_size); + */ + + if (!p_Dpb->init_done) + return; +/* if(p_Vid->conceal_mode == 0) */ +#if 0 +/* ??? */ + if (p_Vid->conceal_mode != 0) + conceal_non_ref_pics(p_Dpb, 0); +#endif + /* mark all frames unused */ + for (i = 0; i < p_Dpb->used_size; i++) { +#if MVC_EXTENSION_ENABLE + assert(p_Dpb->fs[i]->view_id == p_Dpb->layer_id); +#endif + unmark_for_reference(p_Dpb, p_Dpb->fs[i]); + + if (h264_debug_flag & OUTPUT_CURRENT_BUF) + set_frame_output_flag(p_H264_Dpb, i); + + } + + while (remove_unused_frame_from_dpb(p_H264_Dpb)) + ; + + /* output frames in POC order */ +#ifndef OLD_OUTPUT_CODE + if ((h264_debug_flag & OUTPUT_CURRENT_BUF) == 0) { + while (output_frames(p_H264_Dpb, 1)) + ; + } +#else + while (p_Dpb->used_size && output_one_frame_from_dpb(p_H264_Dpb)) + ; +#endif + + p_Dpb->last_output_poc = INT_MIN; +} + +static int is_short_term_reference(struct DecodedPictureBuffer *p_Dpb, + struct FrameStore *fs) +{ + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + if (fs->is_used == 3) { /* frame */ + if ((fs->frame->used_for_reference) && + (!fs->frame->is_long_term)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "[[%s 1]]", + __func__); + return 1; + } + } + + if (fs->is_used & 1) { /* top field */ + if (fs->top_field) { + if ((fs->top_field->used_for_reference) && + (!fs->top_field->is_long_term)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "[[%s 2]]", + __func__); + return 1; + } + } + } + + if (fs->is_used & 2) { /* bottom field */ + if (fs->bottom_field) { + if ((fs->bottom_field->used_for_reference) && + (!fs->bottom_field->is_long_term)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "[[%s 3]]", + __func__); + return 1; + } + } + } + return 0; +} + +static int is_long_term_reference(struct FrameStore *fs) +{ + + if (fs->is_used == 3) { /* frame */ + if ((fs->frame->used_for_reference) && + (fs->frame->is_long_term)) { + return 1; + } + } + + if (fs->is_used & 1) { /* top field */ + if (fs->top_field) { + if ((fs->top_field->used_for_reference) && + (fs->top_field->is_long_term)) { + return 1; + } + } + } + + if (fs->is_used & 2) { /* bottom field */ + if (fs->bottom_field) { + if ((fs->bottom_field->used_for_reference) && + (fs->bottom_field->is_long_term)) { + return 1; + } + } + } + return 0; +} + +static void update_ref_list(struct DecodedPictureBuffer *p_Dpb) +{ + unsigned i, j; + + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s (%d, %d)\n", __func__, p_Dpb->size, p_Dpb->used_size); + for (i = 0, j = 0; i < p_Dpb->used_size; i++) { +#if 1 + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "fs[%d]: fs %p frame %p is_reference %d %d %d\n", + i, p_Dpb->fs[i], p_Dpb->fs[i]->frame, + p_Dpb->fs[i]->frame != NULL ? + p_Dpb->fs[i]->frame->used_for_reference : 0, + p_Dpb->fs[i]->top_field != NULL ? + p_Dpb->fs[i]->top_field->used_for_reference : + 0, + p_Dpb->fs[i]->bottom_field != NULL ? + p_Dpb->fs[i]->bottom_field->used_for_reference : 0); +#endif + if (is_short_term_reference(p_Dpb, p_Dpb->fs[i])) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "fs_ref[%d]=fs[%d]: fs %p\n", j, i, p_Dpb->fs[i]); + p_Dpb->fs_ref[j++] = p_Dpb->fs[i]; + } + } + + p_Dpb->ref_frames_in_buffer = j; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s dpb size is %d, %d\n", __func__, p_Dpb->size, j); + while (j < p_Dpb->size) { + /* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "fs_ref[%d]=null\n", j); */ + p_Dpb->fs_ref[j++] = NULL; + } +#ifdef ERROR_CHECK + for (i = 0; i < DPB_SIZE_MAX; i++) { + if (p_Dpb->fs_ref[i] == NULL) + p_Dpb->fs_ref[i] = &dummy_fs; + } +#endif +} + +static void update_ltref_list(struct DecodedPictureBuffer *p_Dpb) +{ + unsigned i, j; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + for (i = 0, j = 0; i < p_Dpb->used_size; i++) { + if (is_long_term_reference(p_Dpb->fs[i])) + p_Dpb->fs_ltref[j++] = p_Dpb->fs[i]; + } + + p_Dpb->ltref_frames_in_buffer = j; + + while (j < p_Dpb->size) + p_Dpb->fs_ltref[j++] = NULL; +#ifdef ERROR_CHECK + for (i = 0; i < DPB_SIZE_MAX; i++) { + if (p_Dpb->fs_ltref[i] == NULL) + p_Dpb->fs_ltref[i] = &dummy_fs; + } +#endif +} + +static void idr_memory_management(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *p) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s %d %d\n", __func__, p_Dpb->ref_frames_in_buffer, + p_Dpb->ltref_frames_in_buffer); + + if (p->no_output_of_prior_pics_flag) { +#if 0 + /*???*/ + /* free all stored pictures */ + int i; + for (i = 0; i < p_Dpb->used_size; i++) { + /* reset all reference settings + * free_frame_store(p_Dpb->fs[i]); + * p_Dpb->fs[i] = alloc_frame_store(); + */ + reset_frame_store(p_H264_Dpb, p_Dpb->fs[i]); /* ??? */ + } + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + p_Dpb->fs_ref[i] = NULL; + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + p_Dpb->fs_ltref[i] = NULL; + p_Dpb->used_size = 0; +#endif + } else { + flush_dpb(p_H264_Dpb); + } + p_Dpb->last_picture = NULL; + + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + p_Dpb->last_output_poc = INT_MIN; + + if (p->long_term_reference_flag) { + p_Dpb->max_long_term_pic_idx = 0; + p->is_long_term = 1; + p->long_term_frame_idx = 0; + } else { + p_Dpb->max_long_term_pic_idx = -1; + p->is_long_term = 0; + } + +#if (MVC_EXTENSION_ENABLE) + p_Dpb->last_output_view_id = -1; +#endif + +} + +static void sliding_window_memory_management( + struct DecodedPictureBuffer *p_Dpb, + struct StorablePicture *p) +{ + unsigned i; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + + /* assert (!p->idr_flag); */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + + /* if this is a reference pic with sliding window, + unmark first ref frame */ + if (p_Dpb->ref_frames_in_buffer == imax( + 1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer) { + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]->is_reference && + (!(p_Dpb->fs[i]->is_long_term))) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "unmark %d\n", i); + unmark_for_reference(p_Dpb, p_Dpb->fs[i]); + update_ref_list(p_Dpb); + break; + } + } + } + + p->is_long_term = 0; +} + +static void check_num_ref(struct DecodedPictureBuffer *p_Dpb) +{ + if ((int)(p_Dpb->ltref_frames_in_buffer + + p_Dpb->ref_frames_in_buffer) > + imax(1, p_Dpb->num_ref_frames)) { + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "Max. number of reference frames exceeded. Invalid stream. lt %d ref %d mum_ref %d\n", + p_Dpb->ltref_frames_in_buffer, + p_Dpb->ref_frames_in_buffer, + p_Dpb->num_ref_frames); + } +} + +static void dump_dpb(struct DecodedPictureBuffer *p_Dpb) +{ + unsigned i; + struct h264_dpb_stru *p_H264_Dpb = + container_of(p_Dpb, struct h264_dpb_stru, mDPB); + if ((h264_debug_flag & PRINT_FLAG_DUMP_DPB) == 0) + return; + for (i = 0; i < p_Dpb->used_size; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB, + "("); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "fn=%d ", p_Dpb->fs[i]->frame_num); + if (p_Dpb->fs[i]->is_used & 1) { + if (p_Dpb->fs[i]->top_field) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "T: poc=%d ", + p_Dpb->fs[i]->top_field->poc); + else + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "T: poc=%d ", + p_Dpb->fs[i]->frame->top_poc); + } + if (p_Dpb->fs[i]->is_used & 2) { + if (p_Dpb->fs[i]->bottom_field) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "B: poc=%d ", + p_Dpb->fs[i]->bottom_field->poc); + else + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "B: poc=%d ", + p_Dpb->fs[i]->frame->bottom_poc); + } + if (p_Dpb->fs[i]->is_used == 3) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "F: poc=%d ", + p_Dpb->fs[i]->frame->poc); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "G: poc=%d) ", p_Dpb->fs[i]->poc); + if (p_Dpb->fs[i]->is_reference) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "ref (%d) ", p_Dpb->fs[i]->is_reference); + if (p_Dpb->fs[i]->is_long_term) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "lt_ref (%d) ", p_Dpb->fs[i]->is_reference); + if (p_Dpb->fs[i]->is_output) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "out "); + if (p_Dpb->fs[i]->pre_output) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "for_out "); + if (p_Dpb->fs[i]->is_used == 3) { + if (p_Dpb->fs[i]->frame->non_existing) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "ne "); + } +#if (MVC_EXTENSION_ENABLE) + if (p_Dpb->fs[i]->is_reference) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "view_id (%d) ", p_Dpb->fs[i]->view_id); +#endif + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DUMP_DPB | 0x100, + "\n"); + } +} + + +/*! + ************************************************************************ + * \brief + * adaptive memory management + * + ************************************************************************ + */ + +static int get_pic_num_x(struct StorablePicture *p, + int difference_of_pic_nums_minus1) +{ + int currPicNum; + + if (p->structure == FRAME) + currPicNum = p->frame_num; + else + currPicNum = 2 * p->frame_num + 1; + + return currPicNum - (difference_of_pic_nums_minus1 + 1); +} + +/*! + ************************************************************************ + * \brief + * Adaptive Memory Management: Mark short term picture unused + ************************************************************************ + */ +static void mm_unmark_short_term_for_reference(struct DecodedPictureBuffer + *p_Dpb, struct StorablePicture *p, + int difference_of_pic_nums_minus1) +{ + int picNumX; + + unsigned int i; + + picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p->structure == FRAME) { + if ((p_Dpb->fs_ref[i]->is_reference == 3) && + (p_Dpb->fs_ref[i]->is_long_term == 0)) { + if (p_Dpb->fs_ref[i]->frame->pic_num == + picNumX) { + unmark_for_reference(p_Dpb, + p_Dpb->fs_ref[i]); + return; + } + } + } else { + if ((p_Dpb->fs_ref[i]->is_reference & 1) && + (!(p_Dpb->fs_ref[i]->is_long_term & 1))) { + if (p_Dpb->fs_ref[i]->top_field->pic_num == + picNumX) { + p_Dpb->fs_ref[i]-> + top_field->used_for_reference = 0; + p_Dpb->fs_ref[i]->is_reference &= 2; + if (p_Dpb->fs_ref[i]->is_used == 3) { + p_Dpb->fs_ref[i]->frame-> + used_for_reference = 0; + } + return; + } + } + if ((p_Dpb->fs_ref[i]->is_reference & 2) && + (!(p_Dpb->fs_ref[i]->is_long_term & 2))) { + if (p_Dpb->fs_ref[i]->bottom_field->pic_num == + picNumX) { + p_Dpb->fs_ref[i]->bottom_field-> + used_for_reference = 0; + p_Dpb->fs_ref[i]->is_reference &= 1; + if (p_Dpb->fs_ref[i]->is_used == 3) { + p_Dpb->fs_ref[i]->frame-> + used_for_reference = 0; + } + return; + } + } + } + } +} + +static void unmark_for_long_term_reference(struct FrameStore *fs) +{ + if (fs->is_used & 1) { + if (fs->top_field) { + fs->top_field->used_for_reference = 0; + fs->top_field->is_long_term = 0; + } + } + if (fs->is_used & 2) { + if (fs->bottom_field) { + fs->bottom_field->used_for_reference = 0; + fs->bottom_field->is_long_term = 0; + } + } + if (fs->is_used == 3) { + if (fs->top_field && fs->bottom_field) { + fs->top_field->used_for_reference = 0; + fs->top_field->is_long_term = 0; + fs->bottom_field->used_for_reference = 0; + fs->bottom_field->is_long_term = 0; + } + fs->frame->used_for_reference = 0; + fs->frame->is_long_term = 0; + } + + fs->is_reference = 0; + fs->is_long_term = 0; +} + +/*! + ************************************************************************ + * \brief + * Adaptive Memory Management: Mark long term picture unused + ************************************************************************ + */ +static void mm_unmark_long_term_for_reference(struct DecodedPictureBuffer + *p_Dpb, struct StorablePicture *p, int long_term_pic_num) +{ + unsigned int i; + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p->structure == FRAME) { + if ((p_Dpb->fs_ltref[i]->is_reference == 3) && + (p_Dpb->fs_ltref[i]->is_long_term == 3)) { + if (p_Dpb->fs_ltref[i]->frame-> + long_term_pic_num == + long_term_pic_num) { + unmark_for_long_term_reference( + p_Dpb->fs_ltref[i]); + } + } + } else { + if ((p_Dpb->fs_ltref[i]->is_reference & 1) && + ((p_Dpb->fs_ltref[i]->is_long_term & 1))) { + if (p_Dpb->fs_ltref[i]->top_field-> + long_term_pic_num == + long_term_pic_num) { + p_Dpb->fs_ltref[i]->top_field-> + used_for_reference = 0; + p_Dpb->fs_ltref[i]->top_field-> + is_long_term = 0; + p_Dpb->fs_ltref[i]->is_reference &= 2; + p_Dpb->fs_ltref[i]->is_long_term &= 2; + if (p_Dpb->fs_ltref[i]->is_used == 3) { + p_Dpb->fs_ltref[i]->frame-> + used_for_reference = 0; + p_Dpb->fs_ltref[i]->frame-> + is_long_term = 0; + } + return; + } + } + if ((p_Dpb->fs_ltref[i]->is_reference & 2) && + ((p_Dpb->fs_ltref[i]->is_long_term & 2))) { + if (p_Dpb->fs_ltref[i]->bottom_field-> + long_term_pic_num == + long_term_pic_num) { + p_Dpb->fs_ltref[i]->bottom_field-> + used_for_reference = 0; + p_Dpb->fs_ltref[i]->bottom_field-> + is_long_term = 0; + p_Dpb->fs_ltref[i]->is_reference &= 1; + p_Dpb->fs_ltref[i]->is_long_term &= 1; + if (p_Dpb->fs_ltref[i]->is_used == 3) { + p_Dpb->fs_ltref[i]->frame-> + used_for_reference = 0; + p_Dpb->fs_ltref[i]->frame-> + is_long_term = 0; + } + return; + } + } + } + } +} + + +/*! + ************************************************************************ + * \brief + * Mark a long-term reference frame or complementary + * field pair unused for referemce + ************************************************************************ + */ +static void unmark_long_term_frame_for_reference_by_frame_idx( + struct DecodedPictureBuffer *p_Dpb, int long_term_frame_idx) +{ + unsigned int i; + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx == + long_term_frame_idx) + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } +} + + +static void unmark1(struct DecodedPictureBuffer *p_Dpb, + unsigned curr_frame_num, int i) +{ + if (p_Dpb->last_picture) { + if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || + p_Dpb->last_picture->frame_num != curr_frame_num) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } +} + +static void unmark2(struct DecodedPictureBuffer *p_Dpb, + int curr_pic_num, int i) +{ + if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); +} + +static void unmark3_top(struct DecodedPictureBuffer *p_Dpb, + unsigned curr_frame_num, int curr_pic_num, int mark_current, int i) +{ + if (p_Dpb->fs_ltref[i]->is_long_term == 3) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (p_Dpb->fs_ltref[i]->is_long_term == 1) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (mark_current) + unmark1(p_Dpb, curr_frame_num, i); + else + unmark2(p_Dpb, curr_pic_num, i); + } + } +} + +static void unmark3_bottom(struct DecodedPictureBuffer *p_Dpb, + unsigned curr_frame_num, int curr_pic_num, int mark_current, int i) +{ + if (p_Dpb->fs_ltref[i]->is_long_term == 2) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (mark_current) + unmark1(p_Dpb, curr_frame_num, i); + else + unmark2(p_Dpb, curr_pic_num, i); + } +} + +static void unmark_long_term_field_for_reference_by_frame_idx( + struct DecodedPictureBuffer *p_Dpb, enum PictureStructure structure, + int long_term_frame_idx, int mark_current, unsigned curr_frame_num, + int curr_pic_num) +{ + struct VideoParameters *p_Vid = p_Dpb->p_Vid; + unsigned i; + + /* assert(structure!=FRAME); */ + if (curr_pic_num < 0) + curr_pic_num += (2 * p_Vid->max_frame_num); + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx == + long_term_frame_idx) { + if (structure == TOP_FIELD) + unmark3_top(p_Dpb, curr_frame_num, + curr_pic_num, mark_current, i); + + if (structure == BOTTOM_FIELD) + unmark3_bottom(p_Dpb, curr_frame_num, + curr_pic_num, mark_current, i); + } + } +} + +/*! + ************************************************************************ + * \brief + * mark a picture as long-term reference + ************************************************************************ + */ +static void mark_pic_long_term(struct DecodedPictureBuffer *p_Dpb, + struct StorablePicture *p, + int long_term_frame_idx, int picNumX) +{ + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + unsigned int i; + int add_top, add_bottom; + + if (p->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference == 3) { + if ((!p_Dpb->fs_ref[i]->frame-> + is_long_term) && + (p_Dpb->fs_ref[i]->frame->pic_num == + picNumX)) { + p_Dpb->fs_ref[i]-> + long_term_frame_idx = + p_Dpb->fs_ref[i]->frame-> + long_term_frame_idx = + long_term_frame_idx; + p_Dpb->fs_ref[i]->frame-> + long_term_pic_num = + long_term_frame_idx; + p_Dpb->fs_ref[i]->frame-> + is_long_term = 1; + + if (p_Dpb->fs_ref[i]->top_field && + p_Dpb->fs_ref[i]->bottom_field) { + p_Dpb->fs_ref[i]->top_field-> + long_term_frame_idx = + p_Dpb->fs_ref[i]-> + bottom_field-> + long_term_frame_idx = + long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field-> + long_term_pic_num = + long_term_frame_idx; + p_Dpb->fs_ref[i]-> + bottom_field-> + long_term_pic_num = + long_term_frame_idx; + + p_Dpb->fs_ref[i]->top_field-> + is_long_term = + p_Dpb->fs_ref[i]-> + bottom_field-> + is_long_term + = 1; + + } + p_Dpb->fs_ref[i]->is_long_term = 3; + return; + } + } + } + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "Warning: reference frame for long term marking not found\n"); + } else { + if (p->structure == TOP_FIELD) { + add_top = 1; + add_bottom = 0; + } else { + add_top = 0; + add_bottom = 1; + } + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference & 1) { + if ((!p_Dpb->fs_ref[i]->top_field-> + is_long_term) && + (p_Dpb->fs_ref[i]->top_field->pic_num == + picNumX)) { + if ((p_Dpb->fs_ref[i]-> + is_long_term) && + (p_Dpb->fs_ref[i]-> + long_term_frame_idx != + long_term_frame_idx)) { + dpb_print(p_H264_Dpb-> + decoder_index, + PRINT_FLAG_DPB_DETAIL, + "Warning: assigning long_term_frame_idx different from other field\n"); + } + + p_Dpb->fs_ref[i]-> + long_term_frame_idx = + p_Dpb->fs_ref[i]->top_field-> + long_term_frame_idx + = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field-> + long_term_pic_num = + 2 * long_term_frame_idx + + add_top; + p_Dpb->fs_ref[i]->top_field-> + is_long_term = 1; + p_Dpb->fs_ref[i]->is_long_term |= 1; + if (p_Dpb->fs_ref[i]->is_long_term == + 3) { + p_Dpb->fs_ref[i]->frame-> + is_long_term = 1; + p_Dpb->fs_ref[i]->frame-> + long_term_frame_idx = + p_Dpb->fs_ref[i]-> + frame-> + long_term_pic_num = + long_term_frame_idx; + } + return; + } + } + if (p_Dpb->fs_ref[i]->is_reference & 2) { + if ((!p_Dpb->fs_ref[i]->bottom_field-> + is_long_term) && + (p_Dpb->fs_ref[i]->bottom_field->pic_num + == picNumX)) { + if ((p_Dpb->fs_ref[i]-> + is_long_term) && + (p_Dpb->fs_ref[i]-> + long_term_frame_idx != + long_term_frame_idx)) { + dpb_print(p_H264_Dpb-> + decoder_index, + PRINT_FLAG_DPB_DETAIL, + "Warning: assigning long_term_frame_idx different from other field\n"); + } + + p_Dpb->fs_ref[i]-> + long_term_frame_idx = + p_Dpb->fs_ref[i]->bottom_field + ->long_term_frame_idx + = long_term_frame_idx; + p_Dpb->fs_ref[i]->bottom_field-> + long_term_pic_num = 2 * + long_term_frame_idx + + add_bottom; + p_Dpb->fs_ref[i]->bottom_field-> + is_long_term = 1; + p_Dpb->fs_ref[i]->is_long_term |= 2; + if (p_Dpb->fs_ref[i]-> + is_long_term == 3) { + p_Dpb->fs_ref[i]->frame-> + is_long_term = 1; + p_Dpb->fs_ref[i]->frame-> + long_term_frame_idx = + p_Dpb->fs_ref[i]-> + frame-> + long_term_pic_num = + long_term_frame_idx; + } + return; + } + } + } + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "Warning: reference field for long term marking not found\n"); + } +} + + +/*! + ************************************************************************ + * \brief + * Assign a long term frame index to a short term picture + ************************************************************************ + */ +static void mm_assign_long_term_frame_idx(struct DecodedPictureBuffer *p_Dpb, + struct StorablePicture *p, int difference_of_pic_nums_minus1, + int long_term_frame_idx) +{ + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + int picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); + + /* remove frames/fields with same long_term_frame_idx */ + if (p->structure == FRAME) { + unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, + long_term_frame_idx); + } else { + unsigned i; + enum PictureStructure structure = FRAME; + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference & 1) { + if (p_Dpb->fs_ref[i]->top_field-> + pic_num == picNumX) { + structure = TOP_FIELD; + break; + } + } + if (p_Dpb->fs_ref[i]->is_reference & 2) { + if (p_Dpb->fs_ref[i]->bottom_field-> + pic_num == picNumX) { + structure = BOTTOM_FIELD; + break; + } + } + } + if (structure == FRAME) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "field for long term marking not found %d", + 200); + } + + unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, + structure, + long_term_frame_idx, 0, 0, picNumX); + } + + mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX); +} + +/*! + ************************************************************************ + * \brief + * Set new max long_term_frame_idx + ************************************************************************ + */ +static void mm_update_max_long_term_frame_idx(struct DecodedPictureBuffer + *p_Dpb, int max_long_term_frame_idx_plus1) +{ + unsigned int i; + + p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1; + + /* check for invalid frames */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx > + p_Dpb->max_long_term_pic_idx) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } +} + + +/*! + ************************************************************************ + * \brief + * Mark all long term reference pictures unused for reference + ************************************************************************ + */ +static void mm_unmark_all_long_term_for_reference(struct DecodedPictureBuffer + *p_Dpb) +{ + mm_update_max_long_term_frame_idx(p_Dpb, 0); +} + +/*! + ************************************************************************ + * \brief + * Mark all short term reference pictures unused for reference + ************************************************************************ + */ +static void mm_unmark_all_short_term_for_reference(struct DecodedPictureBuffer + *p_Dpb) +{ + unsigned int i; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) + unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]); + update_ref_list(p_Dpb); +} + + +/*! + ************************************************************************ + * \brief + * Mark the current picture used for long term reference + ************************************************************************ + */ +static void mm_mark_current_picture_long_term(struct DecodedPictureBuffer + *p_Dpb, struct StorablePicture *p, int long_term_frame_idx) +{ + /* remove long term pictures with same long_term_frame_idx */ + if (p->structure == FRAME) { + unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, + long_term_frame_idx); + } else { + unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, + p->structure, long_term_frame_idx, + 1, p->pic_num, 0); + } + + p->is_long_term = 1; + p->long_term_frame_idx = long_term_frame_idx; +} + +static void adaptive_memory_management(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *p) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + struct DecRefPicMarking_s *tmp_drpm; + struct VideoParameters *p_Vid = p_Dpb->p_Vid; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s\n", __func__); + p_Vid->last_has_mmco_5 = 0; + + /* assert (!p->idr_flag); */ + /* assert (p->adaptive_ref_pic_buffering_flag); */ + + while (p->dec_ref_pic_marking_buffer) { + tmp_drpm = p->dec_ref_pic_marking_buffer; + switch (tmp_drpm->memory_management_control_operation) { + case 0: + if (tmp_drpm->Next != NULL) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "error, memory_management_control_operation = 0 not last operation in buffer\n"); + break; + case 1: + mm_unmark_short_term_for_reference(p_Dpb, p, + tmp_drpm->difference_of_pic_nums_minus1); + update_ref_list(p_Dpb); + break; + case 2: + mm_unmark_long_term_for_reference(p_Dpb, p, + tmp_drpm->long_term_pic_num); + update_ltref_list(p_Dpb); + break; + case 3: + mm_assign_long_term_frame_idx(p_Dpb, p, + tmp_drpm->difference_of_pic_nums_minus1, + tmp_drpm->long_term_frame_idx); + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + break; + case 4: + mm_update_max_long_term_frame_idx(p_Dpb, + tmp_drpm->max_long_term_frame_idx_plus1); + update_ltref_list(p_Dpb); + break; + case 5: + mm_unmark_all_short_term_for_reference(p_Dpb); + mm_unmark_all_long_term_for_reference(p_Dpb); + p_Vid->last_has_mmco_5 = 1; + break; + case 6: + mm_mark_current_picture_long_term(p_Dpb, p, + tmp_drpm->long_term_frame_idx); + check_num_ref(p_Dpb); + break; + default: + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "error, invalid memory_management_control_operation in buffer\n"); + } + p->dec_ref_pic_marking_buffer = tmp_drpm->Next; + /* free (tmp_drpm); */ + } + if (p_Vid->last_has_mmco_5) { + p->pic_num = p->frame_num = 0; + + switch (p->structure) { + case TOP_FIELD: { + /* p->poc = p->top_poc = p_Vid->toppoc =0; */ + p->poc = p->top_poc = 0; + break; + } + case BOTTOM_FIELD: { + /* p->poc = p->bottom_poc = p_Vid->bottompoc = 0; */ + p->poc = p->bottom_poc = 0; + break; + } + case FRAME: { + p->top_poc -= p->poc; + p->bottom_poc -= p->poc; + + /* p_Vid->toppoc = p->top_poc; */ + /* p_Vid->bottompoc = p->bottom_poc; */ + + p->poc = imin(p->top_poc, p->bottom_poc); + /* p_Vid->framepoc = p->poc; */ + break; + } + } + /* currSlice->ThisPOC = p->poc; */ +#if (MVC_EXTENSION_ENABLE) + if (p->view_id == 0) { + flush_dpb(p_Vid->p_Dpb_layer[0]); + flush_dpb(p_Vid->p_Dpb_layer[1]); + } else { + flush_dpb(p_Dpb); + } +#else + flush_dpb(p_H264_Dpb); +#endif + } +} + + +void store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *p) +{ + /* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */ + struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + unsigned i; +#if 0 + int poc, pos; +#endif + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s p_Vid %p\n", __func__, p_Vid); + + /* picture error concealment */ + + /* diagnostics */ + /* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "Storing (%s) non-ref pic with frame_num #%d\n", + (p->type == FRAME)?"FRAME":(p->type == TOP_FIELD)? + "TOP_FIELD":"BOTTOM_FIELD", p->pic_num); */ + /* if frame, check for new store, */ + /* assert (p!=NULL); */ + + p_Vid->last_has_mmco_5 = 0; + p_Vid->last_pic_bottom_field = (p->structure == BOTTOM_FIELD); + + if (p->idr_flag) { + idr_memory_management(p_H264_Dpb, p); +#if 0 +/* ??? */ + /* picture error concealment */ + memset(p_Vid->pocs_in_dpb, 0, sizeof(int) * 100); +#endif + } else { +#if 1 +/* ??? */ + /* adaptive memory management */ + if (p->used_for_reference && + (p->adaptive_ref_pic_buffering_flag)) + adaptive_memory_management(p_H264_Dpb, p); +#endif + } + + if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) { + /* check for frame store with same pic_number */ + if (p_Dpb->last_picture) { + if ((int)p_Dpb->last_picture->frame_num == + p->pic_num) { + if (((p->structure == TOP_FIELD) && + (p_Dpb->last_picture->is_used == 2)) || + ((p->structure == BOTTOM_FIELD) && + (p_Dpb->last_picture->is_used == 1))) { + if ((p->used_for_reference && + (p_Dpb->last_picture-> + is_orig_reference != 0)) || + (!p->used_for_reference && + (p_Dpb->last_picture-> + is_orig_reference == 0))) { + insert_picture_in_dpb( + p_H264_Dpb, + p_Dpb->last_picture, + p); + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + dump_dpb(p_Dpb); + p_Dpb->last_picture = NULL; + return; + } + } + } + } + } + /* this is a frame or a field which has no stored + * complementary field */ + + /* sliding window, if necessary */ + if ((!p->idr_flag) && (p->used_for_reference && + (!p->adaptive_ref_pic_buffering_flag))) { + sliding_window_memory_management(p_Dpb, p); + } + + /* picture error concealment */ + if (p_Vid->conceal_mode != 0) { + for (i = 0; i < p_Dpb->size; i++) + if (p_Dpb->fs[i]->is_reference) + p_Dpb->fs[i]->concealment_reference = 1; + } + +#ifndef OLD_OUTPUT_CODE + while (remove_unused_frame_from_dpb(p_H264_Dpb)) + ; + + if ((h264_debug_flag & OUTPUT_CURRENT_BUF) == 0) { + while (output_frames(p_H264_Dpb, 0)) + ; + } +#else + /* OLD_OUTPUT_CODE */ + + /* first try to remove unused frames */ + if (p_Dpb->used_size == p_Dpb->size) { +#if 0 + /* ??? */ + /* picture error concealment */ + if (p_Vid->conceal_mode != 0) + conceal_non_ref_pics(p_Dpb, 2); +#endif + remove_unused_frame_from_dpb(p_H264_Dpb); + +#if 0 + /* ??? */ + if (p_Vid->conceal_mode != 0) + sliding_window_poc_management(p_Dpb, p); +#endif + } + + /* then output frames until one can be removed */ +/* #ifdef OUTPUT_BUFFER_IN_C */ + if ((h264_debug_flag & OUTPUT_CURRENT_BUF) == 0) { + if (p_Dpb->used_size > (p_Dpb->size - 5)) + output_one_frame_from_dpb(p_H264_Dpb); + } else { +/* #else */ + while (p_Dpb->used_size == p_Dpb->size) { +#if 0 + /* non-reference frames may be output directly */ + if (!p->used_for_reference) { + get_smallest_poc(p_Dpb, &poc, &pos); + if ((-1 == pos) || (p->poc < poc)) { +#if (MVC_EXTENSION_ENABLE) + if (p_Vid->profile_idc >= MVC_HIGH) + dpb_print( + p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "Display order might not be correct, %d, %d\n", + p->view_id, p->poc); +#endif +#if 0 +/* ??? */ +#if (MVC_EXTENSION_ENABLE) + direct_output(p_Vid, p, p_Vid-> + p_out_mvc[p_Dpb->layer_id]); +#else + direct_output(p_Vid, p, p_Vid->p_out); +#endif +#endif + return; + } + } +#endif + /* flush a frame */ + output_one_frame_from_dpb(p_H264_Dpb); + } + + } +/* #endif */ + /* OLD_OUTPUT_CODE */ +#endif + + /* check for duplicate frame number in short term reference buffer */ + if ((p->used_for_reference) && (!p->is_long_term)) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->frame_num == p->frame_num) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "duplicate frame_num in short-term reference picture buffer %d\n", + 500); + } + } + } + /* store at end of buffer */ + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s p_Dpb->used_size %d\n", __func__, p_Dpb->used_size); + if (p_Dpb->used_size >= p_Dpb->size) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s Error: used_sizd %d is large than dpb size\r\n", + __func__, p_Dpb->used_size); + h264_debug_flag |= PRINT_FLAG_DUMP_DPB; + dump_dpb(p_Dpb); + return; + } + + insert_picture_in_dpb(p_H264_Dpb, p_Dpb->fs[p_Dpb->used_size], p); + if (h264_debug_flag & OUTPUT_CURRENT_BUF) { + prepare_display_buf(p_H264_Dpb->vdec, + p_Dpb->fs[p_Dpb->used_size]); + set_frame_output_flag(p_H264_Dpb, p_Dpb->used_size); + + } + + /* picture error concealment */ + if (p->idr_flag) + p_Vid->earlier_missing_poc = 0; + + if (p->structure != FRAME) + p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size]; + else + p_Dpb->last_picture = NULL; + + p_Dpb->used_size++; +#if 0 +/* ??? */ + if (p_Vid->conceal_mode != 0) + p_Vid->pocs_in_dpb[p_Dpb->used_size - 1] = p->poc; +#endif + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + + check_num_ref(p_Dpb); + + dump_dpb(p_Dpb); +} + +void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb) +{ + /*VideoParameters *p_Vid = p_Dpb->p_Vid;*/ + struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; + if (p_Vid->last_has_mmco_5) + p_Vid->pre_frame_num = 0; +} +/********************************** +* +* Initialize reference lists +***********************************/ +#define __COMPARE(context, p1, p2) comp(p1, p2) +#define __SHORTSORT(lo, hi, width, comp, context) \ + shortsort(lo, hi, width, comp) +#define CUTOFF 8 /* testing shows that this is good value */ +#define STKSIZ (8*sizeof(void *) - 2) + +#undef swap +static void swap( + char *a, + char *b, + size_t width +) +{ + char tmp; + + if (a != b) + /* Do the swap one character at a time to avoid potential + alignment problems. */ + while (width--) { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } +} + +static void shortsort( + char *lo, + char *hi, + size_t width, + int (*comp)(const void *, const void *) +) +{ + char *p, *max; + + /* Note: in assertions below, i and j are alway inside original + bound of array to sort. */ + + while (hi > lo) { + /* A[i] <= A[j] for i <= j, j > hi */ + max = lo; + for (p = lo + width; p <= hi; p += width) { + /* A[i] <= A[max] for lo <= i < p */ + if (__COMPARE(context, p, max) > 0) + max = p; + /* A[i] <= A[max] for lo <= i <= p */ + } + + /* A[i] <= A[max] for lo <= i <= hi */ + + swap(max, hi, width); + + /* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, + j >= hi */ + + hi -= width; + + /* A[i] <= A[j] for i <= j, j > hi, loop top condition + established */ + } + /* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] + for i < j, so array is sorted */ +} + +static void qsort( + void *base, + size_t num, + size_t width, + int (*comp)(const void *, const void *) +) +{ + char *lo, *hi; /* ends of sub-array currently sorting */ + char *mid; /* points to middle of subarray */ + char *loguy, *higuy; /* traveling pointers for partition step */ + size_t size; /* size of the sub-array */ + char *lostk[STKSIZ], *histk[STKSIZ]; + int stkptr; /* stack for saving sub-array to be + processed */ +#if 0 + /* validation section */ + _VALIDATE_RETURN_VOID(base != NULL || num == 0, EINVAL); + _VALIDATE_RETURN_VOID(width > 0, EINVAL); + _VALIDATE_RETURN_VOID(comp != NULL, EINVAL); +#endif + if (num < 2) + return; /* nothing to do */ + + stkptr = 0; /* initialize stack */ + + lo = (char *)base; + hi = (char *)base + width * (num - 1); /* initialize limits */ + + /* this entry point is for pseudo-recursion calling: setting + lo and hi and jumping to here is like recursion, but stkptr is + preserved, locals aren't, so we preserve stuff on the stack */ +recurse: + + size = (hi - lo) / width + 1; /* number of el's to sort */ + + /* below a certain size, it is faster to use a O(n^2) sorting method */ + if (size <= CUTOFF) { + __SHORTSORT(lo, hi, width, comp, context); + } else { + /* First we pick a partitioning element. The efficiency of + the algorithm demands that we find one that is approximately + the median of the values, but also that we select one fast. + We choose the median of the first, middle, and last + elements, to avoid bad performance in the face of already + sorted data, or data that is made up of multiple sorted + runs appended together. Testing shows that a + median-of-three algorithm provides better performance than + simply picking the middle element for the latter case. */ + + mid = lo + (size / 2) * width; /* find middle element */ + + /* Sort the first, middle, last elements into order */ + if (__COMPARE(context, lo, mid) > 0) + swap(lo, mid, width); + if (__COMPARE(context, lo, hi) > 0) + swap(lo, hi, width); + if (__COMPARE(context, mid, hi) > 0) + swap(mid, hi, width); + + /* We now wish to partition the array into three pieces, one + consisting of elements <= partition element, one of elements + equal to the partition element, and one of elements > than + it. This is done below; comments indicate conditions + established at every step. */ + + loguy = lo; + higuy = hi; + + /* Note that higuy decreases and loguy increases on every + iteration, so loop must terminate. */ + for (;;) { + /* lo <= loguy < hi, lo < higuy <= hi, + A[i] <= A[mid] for lo <= i <= loguy, + A[i] > A[mid] for higuy <= i < hi, + A[hi] >= A[mid] */ + + /* The doubled loop is to avoid calling comp(mid,mid), + since some existing comparison funcs don't work + when passed the same value for both pointers. */ + + if (mid > loguy) { + do { + loguy += width; + } while (loguy < mid && + __COMPARE(context, loguy, mid) <= 0); + } + if (mid <= loguy) { + do { + loguy += width; + } while (loguy <= hi && + __COMPARE(context, loguy, mid) <= 0); + } + + /* lo < loguy <= hi+1, A[i] <= A[mid] for + lo <= i < loguy, + either loguy > hi or A[loguy] > A[mid] */ + + do { + higuy -= width; + } while (higuy > mid && + __COMPARE(context, higuy, mid) > 0); + + /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi, + either higuy == lo or A[higuy] <= A[mid] */ + + if (higuy < loguy) + break; + + /* if loguy > hi or higuy == lo, then we would have + exited, so A[loguy] > A[mid], A[higuy] <= A[mid], + loguy <= hi, higuy > lo */ + + swap(loguy, higuy, width); + + /* If the partition element was moved, follow it. + Only need to check for mid == higuy, since before + the swap, A[loguy] > A[mid] implies loguy != mid. */ + + if (mid == higuy) + mid = loguy; + + /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition + at top of loop is re-established */ + } + + /* A[i] <= A[mid] for lo <= i < loguy, + A[i] > A[mid] for higuy < i < hi, + A[hi] >= A[mid] + higuy < loguy + implying: + higuy == loguy-1 + or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */ + + /* Find adjacent elements equal to the partition element. The + doubled loop is to avoid calling comp(mid,mid), since some + existing comparison funcs don't work when passed the same + value for both pointers. */ + + higuy += width; + if (mid < higuy) { + do { + higuy -= width; + } while (higuy > mid && + __COMPARE(context, higuy, mid) == 0); + } + if (mid >= higuy) { + do { + higuy -= width; + } while (higuy > lo && + __COMPARE(context, higuy, mid) == 0); + } + + /* OK, now we have the following: + higuy < loguy + lo <= higuy <= hi + A[i] <= A[mid] for lo <= i <= higuy + A[i] == A[mid] for higuy < i < loguy + A[i] > A[mid] for loguy <= i < hi + A[hi] >= A[mid] */ + + /* We've finished the partition, now we want to sort the + subarrays [lo, higuy] and [loguy, hi]. + We do the smaller one first to minimize stack usage. + We only sort arrays of length 2 or more.*/ + + if (higuy - lo >= hi - loguy) { + if (lo < higuy) { + lostk[stkptr] = lo; + histk[stkptr] = higuy; + ++stkptr; + } /* save big recursion for later */ + + if (loguy < hi) { + lo = loguy; + goto recurse; /* do small recursion */ + } + } else { + if (loguy < hi) { + lostk[stkptr] = loguy; + histk[stkptr] = hi; + ++stkptr; /* save big recursion for later */ + } + + if (lo < higuy) { + hi = higuy; + goto recurse; /* do small recursion */ + } + } + } + + /* We have sorted the array, except for any pending sorts on the stack. + Check if there are any, and do them. */ + + --stkptr; + if (stkptr >= 0) { + lo = lostk[stkptr]; + hi = histk[stkptr]; + goto recurse; /* pop subarray from stack */ + } else + return; /* all subarrays done */ +} + +/*! + ************************************************************************ + * \brief + * compares two stored pictures by picture number for qsort in + * descending order + * + ************************************************************************ + */ +static inline int compare_pic_by_pic_num_desc(const void *arg1, + const void *arg2) +{ + int pic_num1 = (*(struct StorablePicture **)arg1)->pic_num; + int pic_num2 = (*(struct StorablePicture **)arg2)->pic_num; + + if (pic_num1 < pic_num2) + return 1; + if (pic_num1 > pic_num2) + return -1; + else + return 0; +} + +/*! + ************************************************************************ + * \brief + * compares two stored pictures by picture number for qsort in + * descending order + * + ************************************************************************ + */ +static inline int compare_pic_by_lt_pic_num_asc(const void *arg1, + const void *arg2) +{ + int long_term_pic_num1 = + (*(struct StorablePicture **)arg1)->long_term_pic_num; + int long_term_pic_num2 = + (*(struct StorablePicture **)arg2)->long_term_pic_num; + + if (long_term_pic_num1 < long_term_pic_num2) + return -1; + if (long_term_pic_num1 > long_term_pic_num2) + return 1; + else + return 0; +} + +/*! + ************************************************************************ + * \brief + * compares two frame stores by pic_num for qsort in descending order + * + ************************************************************************ + */ +static inline int compare_fs_by_frame_num_desc(const void *arg1, + const void *arg2) +{ + int frame_num_wrap1 = (*(struct FrameStore **)arg1)->frame_num_wrap; + int frame_num_wrap2 = (*(struct FrameStore **)arg2)->frame_num_wrap; + if (frame_num_wrap1 < frame_num_wrap2) + return 1; + if (frame_num_wrap1 > frame_num_wrap2) + return -1; + else + return 0; +} + + +/*! + ************************************************************************ + * \brief + * compares two frame stores by lt_pic_num for qsort in descending order + * + ************************************************************************ + */ +static inline int compare_fs_by_lt_pic_idx_asc(const void *arg1, + const void *arg2) +{ + int long_term_frame_idx1 = + (*(struct FrameStore **)arg1)->long_term_frame_idx; + int long_term_frame_idx2 = + (*(struct FrameStore **)arg2)->long_term_frame_idx; + + if (long_term_frame_idx1 < long_term_frame_idx2) + return -1; + else if (long_term_frame_idx1 > long_term_frame_idx2) + return 1; + else + return 0; +} + + +/*! + ************************************************************************ + * \brief + * compares two stored pictures by poc for qsort in ascending order + * + ************************************************************************ + */ +static inline int compare_pic_by_poc_asc(const void *arg1, const void *arg2) +{ + int poc1 = (*(struct StorablePicture **)arg1)->poc; + int poc2 = (*(struct StorablePicture **)arg2)->poc; + + if (poc1 < poc2) + return -1; + else if (poc1 > poc2) + return 1; + else + return 0; +} + + +/*! + ************************************************************************ + * \brief + * compares two stored pictures by poc for qsort in descending order + * + ************************************************************************ + */ +static inline int compare_pic_by_poc_desc(const void *arg1, const void *arg2) +{ + int poc1 = (*(struct StorablePicture **)arg1)->poc; + int poc2 = (*(struct StorablePicture **)arg2)->poc; + + if (poc1 < poc2) + return 1; + else if (poc1 > poc2) + return -1; + else + return 0; +} + + +/*! + ************************************************************************ + * \brief + * compares two frame stores by poc for qsort in ascending order + * + ************************************************************************ + */ +static inline int compare_fs_by_poc_asc(const void *arg1, const void *arg2) +{ + int poc1 = (*(struct FrameStore **)arg1)->poc; + int poc2 = (*(struct FrameStore **)arg2)->poc; + + if (poc1 < poc2) + return -1; + else if (poc1 > poc2) + return 1; + else + return 0; +} + + +/*! + ************************************************************************ + * \brief + * compares two frame stores by poc for qsort in descending order + * + ************************************************************************ + */ +static inline int compare_fs_by_poc_desc(const void *arg1, const void *arg2) +{ + int poc1 = (*(struct FrameStore **)arg1)->poc; + int poc2 = (*(struct FrameStore **)arg2)->poc; + + if (poc1 < poc2) + return 1; + else if (poc1 > poc2) + return -1; + else + return 0; +} + +/*! + ************************************************************************ + * \brief + * returns true, if picture is short term reference picture + * + ************************************************************************ + */ +static inline int is_short_ref(struct StorablePicture *s) +{ +#ifdef ERROR_CHECK + return (s && + (s->used_for_reference) && (!(s->is_long_term))); +#else + return (s->used_for_reference) && (!(s->is_long_term)); +#endif +} + + +/*! + ************************************************************************ + * \brief + * returns true, if picture is long term reference picture + * + ************************************************************************ + */ +static inline int is_long_ref(struct StorablePicture *s) +{ +#ifdef ERROR_CHECK + return (s && + s->used_for_reference) && (s->is_long_term); +#else + return (s->used_for_reference) && (s->is_long_term); +#endif +} + +/*! + ************************************************************************ + * \brief + * Initialize reference lists for a P Slice + * + ************************************************************************ + */ +/*! + ************************************************************************ + * \brief + * Generates a alternating field list from a given FrameStore list + * + ************************************************************************ + */ +static void gen_pic_list_from_frame_list(enum PictureStructure currStructure, + struct FrameStore **fs_list, int list_idx, + struct StorablePicture **list, + char *list_size, int long_term) +{ + int top_idx = 0; + int bot_idx = 0; + + int (*is_ref)(struct StorablePicture *s) = (long_term) ? is_long_ref : + is_short_ref; + + + if (currStructure == TOP_FIELD) { + while ((top_idx < list_idx) || (bot_idx < list_idx)) { + for (; top_idx < list_idx; top_idx++) { + if (fs_list[top_idx]->is_used & 1) { + if (is_ref(fs_list[top_idx]-> + top_field)) { + /* short term ref pic */ + list[(short) *list_size] = + fs_list[top_idx]->top_field; + (*list_size)++; + top_idx++; + break; + } + } + } + for (; bot_idx < list_idx; bot_idx++) { + if (fs_list[bot_idx]->is_used & 2) { + if (is_ref(fs_list[bot_idx]-> + bottom_field)) { + /* short term ref pic */ + list[(short) *list_size] = + fs_list[bot_idx]->bottom_field; + (*list_size)++; + bot_idx++; + break; + } + } + } + } + } + if (currStructure == BOTTOM_FIELD) { + while ((top_idx < list_idx) || (bot_idx < list_idx)) { + for (; bot_idx < list_idx; bot_idx++) { + if (fs_list[bot_idx]->is_used & 2) { + if (is_ref(fs_list[bot_idx]-> + bottom_field)) { + /* short term ref pic */ + list[(short) *list_size] = + fs_list[bot_idx]->bottom_field; + (*list_size)++; + bot_idx++; + break; + } + } + } + for (; top_idx < list_idx; top_idx++) { + if (fs_list[top_idx]->is_used & 1) { + if (is_ref(fs_list[top_idx]-> + top_field)) { + /* short term ref pic */ + list[(short) *list_size] = + fs_list[top_idx]->top_field; + (*list_size)++; + top_idx++; + break; + } + } + } + } + } +} + +static void init_lists_p_slice(struct Slice *currSlice) +{ + struct VideoParameters *p_Vid = currSlice->p_Vid; + struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + + unsigned int i; + + int list0idx = 0; + int listltidx = 0; + + struct FrameStore **fs_list0; + struct FrameStore **fs_listlt; + +#if (MVC_EXTENSION_ENABLE) + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; +#endif + + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used == 3) { + if ((p_Dpb->fs_ref[i]->frame-> + used_for_reference) && + (!p_Dpb->fs_ref[i]->frame-> + is_long_term)) { + currSlice->listX[0][list0idx++] = + p_Dpb->fs_ref[i]->frame; + } + } + } + /* order list 0 by PicNum */ + qsort((void *)currSlice->listX[0], list0idx, + sizeof(struct StorablePicture *), + compare_pic_by_pic_num_desc); + currSlice->listXsize[0] = (char) list0idx; + CHECK_VALID(currSlice->listXsize[0], 0); + if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "listX[0] (PicNum): "); + for (i = 0; i < list0idx; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[0][i]->pic_num); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + } + /* long term handling */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_used == 3) { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) { + currSlice->listX[0][list0idx++] = + p_Dpb->fs_ltref[i]->frame; + } + } + } + qsort((void *)&currSlice->listX[0][ + (short) currSlice->listXsize[0]], + list0idx - currSlice->listXsize[0], + sizeof(struct StorablePicture *), + compare_pic_by_lt_pic_num_asc); + currSlice->listXsize[0] = (char) list0idx; + CHECK_VALID(currSlice->listXsize[0], 0); + } else { +#if 0 + fs_list0 = calloc(p_Dpb->size, sizeof(struct FrameStore *)); + if (NULL == fs_list0) + no_mem_exit("init_lists: fs_list0"); + fs_listlt = calloc(p_Dpb->size, sizeof(struct FrameStore *)); + if (NULL == fs_listlt) + no_mem_exit("init_lists: fs_listlt"); +#else + fs_list0 = &(p_Dpb->fs_list0[0]); + fs_listlt = &(p_Dpb->fs_listlt[0]); +#endif + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference) + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + + qsort((void *)fs_list0, list0idx, sizeof(struct FrameStore *), + compare_fs_by_frame_num_desc); + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "fs_list0 (FrameNum): "); + for (i = 0; i < list0idx; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + fs_list0[i]->frame_num_wrap); + } + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "\n"); + + currSlice->listXsize[0] = 0; + gen_pic_list_from_frame_list(currSlice->structure, fs_list0, + list0idx, currSlice->listX[0], + &currSlice->listXsize[0], 0); + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "listX[0] (PicNum): "); + for (i = 0; i < currSlice->listXsize[0]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[0][i]->pic_num); + } + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "\n"); + + /* long term handling */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; + + qsort((void *)fs_listlt, listltidx, sizeof(struct FrameStore *), + compare_fs_by_lt_pic_idx_asc); + + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, + listltidx, currSlice->listX[0], + &currSlice->listXsize[0], 1); + + /* free(fs_list0); */ + /* free(fs_listlt); */ + } + currSlice->listXsize[1] = 0; + + + /* set max size */ + currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0], + currSlice->num_ref_idx_active[LIST_0]); + currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1], + currSlice->num_ref_idx_active[LIST_1]); + CHECK_VALID(currSlice->listXsize[0], 0); + CHECK_VALID(currSlice->listXsize[1], 1); + + /* set the unused list entries to NULL */ + for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++) + currSlice->listX[0][i] = p_Vid->no_reference_picture; + for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++) + currSlice->listX[1][i] = p_Vid->no_reference_picture; + +#if PRINTREFLIST +#if (MVC_EXTENSION_ENABLE) + /* print out for h264_debug_flag purpose */ + if ((p_Vid->profile_idc == MVC_HIGH || + p_Vid->profile_idc == STEREO_HIGH) && + currSlice->current_slice_nr == 0) { + if (currSlice->listXsize[0] > 0) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n", + currSlice->view_id, + currSlice->ThisPOC, + currSlice->structure == FRAME ? "FRM" : + (currSlice->structure == TOP_FIELD ? + "TOP" : "BOT")); + for (i = 0; i < (unsigned int)(currSlice-> + listXsize[0]); i++) { /* ref list 0 */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", + i, + currSlice->listX[0][i]->poc, + currSlice->listX[0][i]->pic_num, + currSlice->listX[0][i]->view_id); + } + } + } +#endif +#endif +} + + +/*! + ************************************************************************ + * \brief + * Initialize reference lists + * + ************************************************************************ + */ +static void init_mbaff_lists(struct VideoParameters *p_Vid, + struct Slice *currSlice) +{ + unsigned j; + int i; + + for (i = 2; i < 6; i++) { + for (j = 0; j < MAX_LIST_SIZE; j++) + currSlice->listX[i][j] = p_Vid->no_reference_picture; + currSlice->listXsize[i] = 0; + } + + for (i = 0; i < currSlice->listXsize[0]; i++) { +#ifdef ERROR_CHECK + if (currSlice->listX[0][i] == NULL) { + pr_info( + "error currSlice->listX[0][%d] is NULL\r\n", i); + break; + } +#endif + currSlice->listX[2][2 * i] = + currSlice->listX[0][i]->top_field; + currSlice->listX[2][2 * i + 1] = + currSlice->listX[0][i]->bottom_field; + currSlice->listX[4][2 * i] = + currSlice->listX[0][i]->bottom_field; + currSlice->listX[4][2 * i + 1] = + currSlice->listX[0][i]->top_field; + } + currSlice->listXsize[2] = currSlice->listXsize[4] = + currSlice->listXsize[0] * 2; + + for (i = 0; i < currSlice->listXsize[1]; i++) { +#ifdef ERROR_CHECK + if (currSlice->listX[1][i] == NULL) { + pr_info( + "error currSlice->listX[1][%d] is NULL\r\n", i); + break; + } +#endif + currSlice->listX[3][2 * i] = + currSlice->listX[1][i]->top_field; + currSlice->listX[3][2 * i + 1] = + currSlice->listX[1][i]->bottom_field; + currSlice->listX[5][2 * i] = + currSlice->listX[1][i]->bottom_field; + currSlice->listX[5][2 * i + 1] = + currSlice->listX[1][i]->top_field; + } + currSlice->listXsize[3] = currSlice->listXsize[5] = + currSlice->listXsize[1] * 2; +} + + + +static void init_lists_i_slice(struct Slice *currSlice) +{ + +#if (MVC_EXTENSION_ENABLE) + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; +#endif + + currSlice->listXsize[0] = 0; + currSlice->listXsize[1] = 0; +} + +static void init_lists_b_slice(struct Slice *currSlice) +{ + struct VideoParameters *p_Vid = currSlice->p_Vid; + struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb, + struct h264_dpb_stru, mDPB); + + unsigned int i; + int j; + + int list0idx = 0; + int list0idx_1 = 0; + int listltidx = 0; + + struct FrameStore **fs_list0; + struct FrameStore **fs_list1; + struct FrameStore **fs_listlt; + +#if (MVC_EXTENSION_ENABLE) + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; +#endif + + { + /* B-Slice */ + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if ((p_Dpb->fs_ref[i]->is_used == 3) && + ((p_Dpb->fs_ref[i]->frame-> + used_for_reference) && + (!p_Dpb->fs_ref[i]->frame-> + is_long_term)) && + (currSlice->framepoc >= + p_Dpb->fs_ref[i]->frame->poc)) { + /* !KS use >= for error + concealment */ + currSlice->listX[0][list0idx++] = + p_Dpb->fs_ref[i]->frame; + } + } + qsort((void *)currSlice->listX[0], list0idx, + sizeof(struct StorablePicture *), + compare_pic_by_poc_desc); + + /* get the backward reference picture + (POC>current POC) in list0; */ + list0idx_1 = list0idx; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if ((p_Dpb->fs_ref[i]->is_used == 3) && + ((p_Dpb->fs_ref[i]->frame-> + used_for_reference) && + (!p_Dpb->fs_ref[i]->frame-> + is_long_term)) && + (currSlice->framepoc < + p_Dpb->fs_ref[i]->frame->poc)) { + currSlice-> + listX[0][list0idx++] = + p_Dpb->fs_ref[i]->frame; + } + } + qsort((void *)&currSlice->listX[0][list0idx_1], + list0idx - list0idx_1, + sizeof(struct StorablePicture *), + compare_pic_by_poc_asc); + + for (j = 0; j < list0idx_1; j++) { + currSlice-> + listX[1][list0idx - list0idx_1 + j] = + currSlice->listX[0][j]; + } + for (j = list0idx_1; j < list0idx; j++) { + currSlice->listX[1][j - list0idx_1] = + currSlice->listX[0][j]; + } + + currSlice->listXsize[0] = currSlice->listXsize[1] = + (char) list0idx; + CHECK_VALID(currSlice->listXsize[0], 0); + CHECK_VALID(currSlice->listXsize[1], 1); + + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "listX[0] (PicNum): "); + for (i = 0; i < currSlice->listXsize[0]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[0][i]->pic_num); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "listX[1] (PicNum): "); + for (i = 0; i < currSlice->listXsize[1]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[1][i]->pic_num); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + /* dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "currSlice->listX[0] currPoc=%d (Poc): ", + p_Vid->framepoc); + for (i=0; ilistXsize[0]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%d ", currSlice->listX[0][i]->poc); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "currSlice->listX[1] currPoc=%d (Poc): ", + p_Vid->framepoc); + for (i=0; ilistXsize[1]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%d ", + currSlice->listX[1][i]->poc); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); */ + + /* long term handling */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_used == 3) { + if (p_Dpb->fs_ltref[i]->frame-> + is_long_term) { + currSlice-> + listX[0][list0idx] = + p_Dpb->fs_ltref[i]->frame; + currSlice-> + listX[1][list0idx++] = + p_Dpb->fs_ltref[i]->frame; + } + } + } + qsort((void *)&currSlice-> + listX[0][(short) currSlice->listXsize[0]], + list0idx - currSlice->listXsize[0], + sizeof(struct StorablePicture *), + compare_pic_by_lt_pic_num_asc); + qsort((void *)&currSlice-> + listX[1][(short) currSlice->listXsize[0]], + list0idx - currSlice->listXsize[0], + sizeof(struct StorablePicture *), + compare_pic_by_lt_pic_num_asc); + currSlice->listXsize[0] = currSlice->listXsize[1] = + (char) list0idx; + CHECK_VALID(currSlice->listXsize[0], 0); + CHECK_VALID(currSlice->listXsize[1], 1); + } else { +#if 0 + fs_list0 = calloc(p_Dpb->size, + sizeof(struct FrameStore *)); + if (NULL == fs_list0) + no_mem_exit("init_lists: fs_list0"); + fs_list1 = calloc(p_Dpb->size, + sizeof(struct FrameStore *)); + if (NULL == fs_list1) + no_mem_exit("init_lists: fs_list1"); + fs_listlt = calloc(p_Dpb->size, + sizeof(struct FrameStore *)); + if (NULL == fs_listlt) + no_mem_exit("init_lists: fs_listlt"); +#else + fs_list0 = &(p_Dpb->fs_list0[0]); + fs_list1 = &(p_Dpb->fs_list1[0]); + fs_listlt = &(p_Dpb->fs_listlt[0]); + +#endif + currSlice->listXsize[0] = 0; + currSlice->listXsize[1] = 1; + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used) { + if (currSlice->ThisPOC >= + p_Dpb->fs_ref[i]->poc) { + fs_list0[list0idx++] = + p_Dpb->fs_ref[i]; + } + } + } + qsort((void *)fs_list0, list0idx, + sizeof(struct FrameStore *), + compare_fs_by_poc_desc); + list0idx_1 = list0idx; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used) { + if (currSlice->ThisPOC < + p_Dpb->fs_ref[i]->poc) { + fs_list0[list0idx++] = + p_Dpb->fs_ref[i]; + } + } + } + qsort((void *)&fs_list0[list0idx_1], + list0idx - list0idx_1, + sizeof(struct FrameStore *), + compare_fs_by_poc_asc); + + for (j = 0; j < list0idx_1; j++) { + fs_list1[list0idx - list0idx_1 + j] = + fs_list0[j]; + } + for (j = list0idx_1; j < list0idx; j++) + fs_list1[j - list0idx_1] = fs_list0[j]; + + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "fs_list0 currPoc=%d (Poc): ", + currSlice->ThisPOC); + for (i = 0; i < list0idx; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + fs_list0[i]->poc); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "fs_list1 currPoc=%d (Poc): ", + currSlice->ThisPOC); + for (i = 0; i < list0idx; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + fs_list1[i]->poc); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + + currSlice->listXsize[0] = 0; + currSlice->listXsize[1] = 0; + gen_pic_list_from_frame_list(currSlice->structure, + fs_list0, list0idx, + currSlice->listX[0], + &currSlice->listXsize[0], 0); + gen_pic_list_from_frame_list(currSlice->structure, + fs_list1, list0idx, + currSlice->listX[1], + &currSlice->listXsize[1], 0); + + /* dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "currSlice->listX[0] currPoc=%d (Poc): ", + p_Vid->framepoc); + for (i=0; ilistXsize[0]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[0][i]->poc); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); */ + /* dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "currSlice->listX[1] currPoc=%d (Poc): ", + p_Vid->framepoc); + for (i=0; ilistXsize[1]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[1][i]->poc); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "\n"); */ + + /* long term handling */ + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) + fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; + + qsort((void *)fs_listlt, listltidx, + sizeof(struct FrameStore *), + compare_fs_by_lt_pic_idx_asc); + + gen_pic_list_from_frame_list(currSlice->structure, + fs_listlt, listltidx, + currSlice->listX[0], + &currSlice->listXsize[0], 1); + gen_pic_list_from_frame_list(currSlice->structure, + fs_listlt, listltidx, + currSlice->listX[1], + &currSlice->listXsize[1], 1); + + /* free(fs_list0); */ + /* free(fs_list1); */ + /* free(fs_listlt); */ + } + } + + if ((currSlice->listXsize[0] == currSlice->listXsize[1]) && + (currSlice->listXsize[0] > 1)) { + /* check if lists are identical, + if yes swap first two elements of currSlice->listX[1] */ + int diff = 0; + for (j = 0; j < currSlice->listXsize[0]; j++) { + if (currSlice->listX[0][j] != + currSlice->listX[1][j]) { + diff = 1; + break; + } + } + if (!diff) { + struct StorablePicture *tmp_s = + currSlice->listX[1][0]; + currSlice->listX[1][0] = currSlice->listX[1][1]; + currSlice->listX[1][1] = tmp_s; + } + } + + /* set max size */ + currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0], + currSlice->num_ref_idx_active[LIST_0]); + currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1], + currSlice->num_ref_idx_active[LIST_1]); + CHECK_VALID(currSlice->listXsize[0], 0); + CHECK_VALID(currSlice->listXsize[1], 1); + + /* set the unused list entries to NULL */ + for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++) + currSlice->listX[0][i] = p_Vid->no_reference_picture; + for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++) + currSlice->listX[1][i] = p_Vid->no_reference_picture; + +#if PRINTREFLIST +#if (MVC_EXTENSION_ENABLE) + /* print out for h264_debug_flag purpose */ + if ((p_Vid->profile_idc == MVC_HIGH || + p_Vid->profile_idc == STEREO_HIGH) && + currSlice->current_slice_nr == 0) { + if ((currSlice->listXsize[0] > 0) || + (currSlice->listXsize[1] > 0)) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + if (currSlice->listXsize[0] > 0) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n", + currSlice->view_id, + currSlice->ThisPOC, + currSlice->structure == FRAME ? "FRM" : + (currSlice->structure == TOP_FIELD ? + "TOP" : "BOT")); + for (i = 0; i < (unsigned int)(currSlice-> + listXsize[0]); i++) { /* ref list 0 */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", + i, + currSlice->listX[0][i]->poc, + currSlice->listX[0][i]->pic_num, + currSlice->listX[0][i]->view_id); + } + } + if (currSlice->listXsize[1] > 0) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " ** (CurViewID:%d %d) %s Ref Pic List 1 ****\n", + currSlice->view_id, + currSlice->ThisPOC, + currSlice->structure == FRAME ? "FRM" : + (currSlice->structure == TOP_FIELD ? "TOP" : + "BOT")); + for (i = 0; i < (unsigned int)(currSlice-> + listXsize[1]); i++) { /* ref list 1 */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", + i, + currSlice->listX[1][i]->poc, + currSlice->listX[1][i]->pic_num, + currSlice->listX[1][i]->view_id); + } + } + } +#endif +#endif +} + +static struct StorablePicture *get_short_term_pic(struct Slice *currSlice, + struct DecodedPictureBuffer *p_Dpb, int picNum) +{ + unsigned i; + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (currSlice->structure == FRAME) { + if (p_Dpb->fs_ref[i]->is_reference == 3) + if ((!p_Dpb->fs_ref[i]->frame-> + is_long_term) && + (p_Dpb->fs_ref[i]->frame-> + pic_num == picNum)) + return p_Dpb->fs_ref[i]->frame; + } else { + if (p_Dpb->fs_ref[i]->is_reference & 1) + if ((!p_Dpb->fs_ref[i]->top_field-> + is_long_term) && + (p_Dpb->fs_ref[i]->top_field-> + pic_num == picNum)) + return p_Dpb->fs_ref[i]->top_field; + if (p_Dpb->fs_ref[i]->is_reference & 2) + if ((!p_Dpb->fs_ref[i]->bottom_field-> + is_long_term) && + (p_Dpb->fs_ref[i]->bottom_field-> + pic_num == picNum)) + return p_Dpb->fs_ref[i]->bottom_field; + } + } + + return currSlice->p_Vid->no_reference_picture; +} + + +static void reorder_short_term(struct Slice *currSlice, int cur_list, + int num_ref_idx_lX_active_minus1, + int picNumLX, int *refIdxLX) +{ + struct h264_dpb_stru *p_H264_Dpb = container_of(currSlice->p_Vid, + struct h264_dpb_stru, mVideo); + + struct StorablePicture **RefPicListX = currSlice->listX[cur_list]; + int cIdx, nIdx; + + struct StorablePicture *picLX; + + picLX = get_short_term_pic(currSlice, currSlice->p_Dpb, picNumLX); + + for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; + cIdx--) { + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n", + __func__, cIdx, cIdx - 1); + RefPicListX[cIdx] = RefPicListX[cIdx - 1]; + } + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s: RefPicListX[ %d ] = pic %x (%d)\n", __func__, + *refIdxLX, picLX, picNumLX); + + RefPicListX[(*refIdxLX)++] = picLX; + + nIdx = *refIdxLX; + + for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; + cIdx++) { + if (RefPicListX[cIdx]) + if ((RefPicListX[cIdx]->is_long_term) || + (RefPicListX[cIdx]->pic_num != picNumLX)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n", + __func__, nIdx, cIdx); + RefPicListX[nIdx++] = RefPicListX[cIdx]; + } + } +} + + +static struct StorablePicture *get_long_term_pic(struct Slice *currSlice, + struct DecodedPictureBuffer *p_Dpb, int LongtermPicNum) +{ + unsigned int i; + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (currSlice->structure == FRAME) { + if (p_Dpb->fs_ltref[i]->is_reference == 3) + if ((p_Dpb->fs_ltref[i]->frame-> + is_long_term) && + (p_Dpb->fs_ltref[i]->frame-> + long_term_pic_num == + LongtermPicNum)) + return p_Dpb->fs_ltref[i]->frame; + } else { + if (p_Dpb->fs_ltref[i]->is_reference & 1) + if ((p_Dpb->fs_ltref[i]->top_field-> + is_long_term) && + (p_Dpb->fs_ltref[i]->top_field-> + long_term_pic_num == LongtermPicNum)) + return p_Dpb->fs_ltref[i]->top_field; + if (p_Dpb->fs_ltref[i]->is_reference & 2) + if ((p_Dpb->fs_ltref[i]->bottom_field-> + is_long_term) && + (p_Dpb->fs_ltref[i]->bottom_field-> + long_term_pic_num == + LongtermPicNum)) + return p_Dpb->fs_ltref[i]-> + bottom_field; + } + } + return NULL; +} + +/*! + ************************************************************************ + * \brief + * Reordering process for long-term reference pictures + * + ************************************************************************ + */ +static void reorder_long_term(struct Slice *currSlice, + struct StorablePicture **RefPicListX, + int num_ref_idx_lX_active_minus1, + int LongTermPicNum, int *refIdxLX) +{ + int cIdx, nIdx; + + struct StorablePicture *picLX; + + picLX = get_long_term_pic(currSlice, currSlice->p_Dpb, LongTermPicNum); + + for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--) + RefPicListX[cIdx] = RefPicListX[cIdx - 1]; + + RefPicListX[(*refIdxLX)++] = picLX; + + nIdx = *refIdxLX; + + for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; + cIdx++) { + if (RefPicListX[cIdx]) { + if ((!RefPicListX[cIdx]->is_long_term) || + (RefPicListX[cIdx]->long_term_pic_num != + LongTermPicNum)) + RefPicListX[nIdx++] = RefPicListX[cIdx]; + } + } +} + +static void reorder_ref_pic_list(struct Slice *currSlice, int cur_list) +{ + int *modification_of_pic_nums_idc = + currSlice->modification_of_pic_nums_idc[cur_list]; + int *abs_diff_pic_num_minus1 = + currSlice->abs_diff_pic_num_minus1[cur_list]; + int *long_term_pic_idx = currSlice->long_term_pic_idx[cur_list]; + int num_ref_idx_lX_active_minus1 = + currSlice->num_ref_idx_active[cur_list] - 1; + + struct VideoParameters *p_Vid = currSlice->p_Vid; + int i; + + int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX; + int refIdxLX = 0; + + if (currSlice->structure == FRAME) { + maxPicNum = p_Vid->max_frame_num; + currPicNum = currSlice->frame_num; + } else { + maxPicNum = 2 * p_Vid->max_frame_num; + currPicNum = 2 * currSlice->frame_num + 1; + } + + picNumLXPred = currPicNum; + + for (i = 0; i < REORDERING_COMMAND_MAX_SIZE && + modification_of_pic_nums_idc[i] != 3; i++) { + if (modification_of_pic_nums_idc[i] > 3) { + struct h264_dpb_stru *p_H264_Dpb = + container_of(p_Vid, struct h264_dpb_stru, mVideo); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "error, Invalid modification_of_pic_nums_idc command\n"); + /*h264_debug_flag = 0x1f;*/ + break; + } + if (modification_of_pic_nums_idc[i] < 2) { + if (modification_of_pic_nums_idc[i] == 0) { + if (picNumLXPred - (abs_diff_pic_num_minus1[i] + + 1) < 0) + picNumLXNoWrap = picNumLXPred - + (abs_diff_pic_num_minus1[i] + 1) + + maxPicNum; + else + picNumLXNoWrap = picNumLXPred - + (abs_diff_pic_num_minus1[i] + 1); + } else { /* (modification_of_pic_nums_idc[i] == 1) */ + if (picNumLXPred + (abs_diff_pic_num_minus1[i] + + 1) >= maxPicNum) + picNumLXNoWrap = picNumLXPred + + (abs_diff_pic_num_minus1[i] + 1) - + maxPicNum; + else + picNumLXNoWrap = picNumLXPred + + (abs_diff_pic_num_minus1[i] + 1); + } + picNumLXPred = picNumLXNoWrap; + + if (picNumLXNoWrap > currPicNum) + picNumLX = picNumLXNoWrap - maxPicNum; + else + picNumLX = picNumLXNoWrap; + +#if (MVC_EXTENSION_ENABLE) + reorder_short_term(currSlice, cur_list, + num_ref_idx_lX_active_minus1, picNumLX, + &refIdxLX, -1); +#else + reorder_short_term(currSlice, cur_list, + num_ref_idx_lX_active_minus1, picNumLX, + &refIdxLX); +#endif + } else { /* (modification_of_pic_nums_idc[i] == 2) */ +#if (MVC_EXTENSION_ENABLE) + reorder_long_term(currSlice, currSlice->listX[cur_list], + num_ref_idx_lX_active_minus1, + long_term_pic_idx[i], &refIdxLX, -1); +#else + reorder_long_term(currSlice, currSlice->listX[cur_list], + num_ref_idx_lX_active_minus1, + long_term_pic_idx[i], &refIdxLX); +#endif + } + + } + /* that's a definition */ + currSlice->listXsize[cur_list] = + (char)(num_ref_idx_lX_active_minus1 + 1); +} + + +static void reorder_lists(struct Slice *currSlice) +{ + struct VideoParameters *p_Vid = currSlice->p_Vid; + struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid, + struct h264_dpb_stru, mVideo); + int i; + if ((currSlice->slice_type != I_SLICE) && + (currSlice->slice_type != SI_SLICE)) { + if (currSlice->ref_pic_list_reordering_flag[LIST_0]) + reorder_ref_pic_list(currSlice, LIST_0); + if (p_Vid->no_reference_picture == + currSlice-> + listX[0][currSlice->num_ref_idx_active[LIST_0] - 1]) { + if (p_Vid->non_conforming_stream) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "RefPicList0[ %d ] is equal to 'no reference picture'\n", + currSlice-> + num_ref_idx_active[LIST_0] - 1); + else + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "RefPicList0 [ num_ref_idx_l0_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n", + 500); + } + /* that's a definition */ + currSlice->listXsize[0] = + (char)currSlice->num_ref_idx_active[LIST_0]; + CHECK_VALID(currSlice->listXsize[0], 0); + if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "listX[0] reorder (PicNum): "); + for (i = 0; i < currSlice->listXsize[0]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[0][i]->pic_num); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + } + } + + if (currSlice->slice_type == B_SLICE) { + if (currSlice->ref_pic_list_reordering_flag[LIST_1]) + reorder_ref_pic_list(currSlice, LIST_1); + if (p_Vid->no_reference_picture == + currSlice->listX[1][currSlice-> + num_ref_idx_active[LIST_1] - 1]) { + if (p_Vid->non_conforming_stream) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "RefPicList1[ %d ] is equal to 'no reference picture'\n", + currSlice-> + num_ref_idx_active[LIST_1] - 1); + else + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "RefPicList1 [ num_ref_idx_l1_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n", + 500); + } + /* that's a definition */ + currSlice->listXsize[1] = + (char)currSlice->num_ref_idx_active[LIST_1]; + if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "listX[1] reorder (PicNum): "); + for (i = 0; i < currSlice->listXsize[1]; i++) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "%d ", + currSlice->listX[1][i]->pic_num); + } + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + } + } + + /* free_ref_pic_list_reordering_buffer(currSlice); */ + + if (currSlice->slice_type == P_SLICE) { +#if PRINTREFLIST + unsigned int i; +#if (MVC_EXTENSION_ENABLE) + /* print out for h264_debug_flag purpose */ + if ((p_Vid->profile_idc == MVC_HIGH || + p_Vid->profile_idc == STEREO_HIGH) && + currSlice->current_slice_nr == 0) { + if (currSlice->listXsize[0] > 0 + && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " ** (FinalViewID:%d) %s Ref Pic List 0 ****\n", + currSlice->view_id, + currSlice->structure == FRAME ? + "FRM" : + (currSlice->structure == TOP_FIELD ? + "TOP" : "BOT")); + for (i = 0; i < (unsigned int)(currSlice-> + listXsize[0]); i++) { /* ref list 0 */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", + i, + currSlice->listX[0][i]->poc, + currSlice->listX[0][i]-> + pic_num, + currSlice->listX[0][i]-> + view_id); + } + } + } +#endif +#endif + } else if (currSlice->slice_type == B_SLICE) { +#if PRINTREFLIST + unsigned int i; +#if (MVC_EXTENSION_ENABLE) + /* print out for h264_debug_flag purpose */ + if ((p_Vid->profile_idc == MVC_HIGH || + p_Vid->profile_idc == STEREO_HIGH) && + currSlice->current_slice_nr == 0) { + if ((currSlice->listXsize[0] > 0) || + (currSlice->listXsize[1] > 0)) + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, "\n"); + if (currSlice->listXsize[0] > 0 + && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " ** (FinalViewID:%d) %s Ref Pic List 0 ****\n", + currSlice->view_id, + currSlice->structure == FRAME ? + "FRM" : + (currSlice->structure == TOP_FIELD ? + "TOP" : "BOT")); + for (i = 0; i < (unsigned int)(currSlice-> + listXsize[0]); i++) { /* ref list 0 */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", + i, + currSlice->listX[0][i]->poc, + currSlice->listX[0][i]-> + pic_num, + currSlice->listX[0][i]-> + view_id); + } + } + if (currSlice->listXsize[1] > 0 + && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " ** (FinalViewID:%d) %s Ref Pic List 1 ****\n", + currSlice->view_id, + currSlice->structure == FRAME ? + "FRM" : + (currSlice->structure == TOP_FIELD ? + "TOP" : "BOT")); + for (i = 0; i < (unsigned int)(currSlice-> + listXsize[1]); i++) { /* ref list 1 */ + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + " %2d -> POC: %4d PicNum: %4d ViewID: %d\n", + i, + currSlice->listX[1][i]->poc, + currSlice->listX[1][i]-> + pic_num, + currSlice->listX[1][i]-> + view_id); + } + } + } +#endif + +#endif + } +} + +void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count) +{ + p_H264_Dpb->colocated_buf_map = 0; + p_H264_Dpb->colocated_buf_count = count; +} + +int allocate_colocate_buf(struct h264_dpb_stru *p_H264_Dpb) +{ + int i; + for (i = 0; i < p_H264_Dpb->colocated_buf_count; i++) { + if (((p_H264_Dpb->colocated_buf_map >> i) & 0x1) == 0) { + p_H264_Dpb->colocated_buf_map |= (1 << i); + break; + } + } + if (i == p_H264_Dpb->colocated_buf_count) + i = -1; + return i; +} + +int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index) +{ + if (index >= 0) { + if (index >= p_H264_Dpb->colocated_buf_count) { + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR, + "%s error, index %d is bigger than buf count %d\n", + __func__, index, + p_H264_Dpb->colocated_buf_count); + } else { + if (((p_H264_Dpb->colocated_buf_map >> + index) & 0x1) == 0x1) { + p_H264_Dpb->colocated_buf_map &= + (~(1 << index)); + } else { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_ERROR, + "%s error, index %d is not allocated\n", + __func__, index); + } + } + } + return 0; +} + +void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + p_H264_Dpb->mFrameStore[index].is_output = 1; + p_H264_Dpb->mFrameStore[index].pre_output = 0; + dump_dpb(p_Dpb); +} + +#if 0 +void init_old_slice(OldSliceParams *p_old_slice) +{ + p_old_slice->field_pic_flag = 0; + p_old_slice->pps_id = INT_MAX; + p_old_slice->frame_num = INT_MAX; + p_old_slice->nal_ref_idc = INT_MAX; + p_old_slice->idr_flag = FALSE; + + p_old_slice->pic_oder_cnt_lsb = UINT_MAX; + p_old_slice->delta_pic_oder_cnt_bottom = INT_MAX; + + p_old_slice->delta_pic_order_cnt[0] = INT_MAX; + p_old_slice->delta_pic_order_cnt[1] = INT_MAX; +} + + +void copy_slice_info(struct Slice *currSlice, OldSliceParams *p_old_slice) +{ + struct VideoParameters *p_Vid = currSlice->p_Vid; + + p_old_slice->pps_id = currSlice->pic_parameter_set_id; + p_old_slice->frame_num = currSlice->frame_num; + /* p_Vid->frame_num; */ + p_old_slice->field_pic_flag = + currSlice->field_pic_flag; + /* p_Vid->field_pic_flag; */ + + if (currSlice->field_pic_flag) + p_old_slice->bottom_field_flag = currSlice->bottom_field_flag; + + p_old_slice->nal_ref_idc = currSlice->nal_reference_idc; + p_old_slice->idr_flag = (byte) currSlice->idr_flag; + + if (currSlice->idr_flag) + p_old_slice->idr_pic_id = currSlice->idr_pic_id; + + if (p_Vid->active_sps->pic_order_cnt_type == 0) { + p_old_slice->pic_oder_cnt_lsb = + currSlice->pic_order_cnt_lsb; + p_old_slice->delta_pic_oder_cnt_bottom = + currSlice->delta_pic_order_cnt_bottom; + } + + if (p_Vid->active_sps->pic_order_cnt_type == 1) { + p_old_slice->delta_pic_order_cnt[0] = + currSlice->delta_pic_order_cnt[0]; + p_old_slice->delta_pic_order_cnt[1] = + currSlice->delta_pic_order_cnt[1]; + } +#if (MVC_EXTENSION_ENABLE) + p_old_slice->view_id = currSlice->view_id; + p_old_slice->inter_view_flag = currSlice->inter_view_flag; + p_old_slice->anchor_pic_flag = currSlice->anchor_pic_flag; +#endif + p_old_slice->layer_id = currSlice->layer_id; +} + +int is_new_picture(StorablePicture *dec_picture, struct Slice *currSlice, + OldSliceParams *p_old_slice) +{ + struct VideoParameters *p_Vid = currSlice->p_Vid; + + int result = 0; + + result |= (NULL == dec_picture); + + result |= (p_old_slice->pps_id != currSlice->pic_parameter_set_id); + + result |= (p_old_slice->frame_num != currSlice->frame_num); + + result |= (p_old_slice->field_pic_flag != currSlice->field_pic_flag); + + if (currSlice->field_pic_flag && p_old_slice->field_pic_flag) { + result |= (p_old_slice->bottom_field_flag != + currSlice->bottom_field_flag); + } + + result |= (p_old_slice->nal_ref_idc != + currSlice->nal_reference_idc) && + ((p_old_slice->nal_ref_idc == 0) || + (currSlice->nal_reference_idc == 0)); + result |= (p_old_slice->idr_flag != currSlice->idr_flag); + + if (currSlice->idr_flag && p_old_slice->idr_flag) + result |= (p_old_slice->idr_pic_id != currSlice->idr_pic_id); + + if (p_Vid->active_sps->pic_order_cnt_type == 0) { + result |= (p_old_slice->pic_oder_cnt_lsb != + currSlice->pic_order_cnt_lsb); + if (p_Vid->active_pps-> + bottom_field_pic_order_in_frame_present_flag == 1 && + !currSlice->field_pic_flag) { + result |= (p_old_slice->delta_pic_oder_cnt_bottom != + currSlice->delta_pic_order_cnt_bottom); + } + } + + if (p_Vid->active_sps->pic_order_cnt_type == 1) { + if (!p_Vid->active_sps->delta_pic_order_always_zero_flag) { + result |= (p_old_slice->delta_pic_order_cnt[0] != + currSlice->delta_pic_order_cnt[0]); + if (p_Vid->active_pps-> + bottom_field_pic_order_in_frame_present_flag == 1 && + !currSlice->field_pic_flag) { + result |= (p_old_slice-> + delta_pic_order_cnt[1] != + currSlice->delta_pic_order_cnt[1]); + } + } + } + +#if (MVC_EXTENSION_ENABLE) + result |= (currSlice->view_id != p_old_slice->view_id); + result |= (currSlice->inter_view_flag != p_old_slice->inter_view_flag); + result |= (currSlice->anchor_pic_flag != p_old_slice->anchor_pic_flag); +#endif + result |= (currSlice->layer_id != p_old_slice->layer_id); + return result; +} +#else +int is_new_picture(struct StorablePicture *dec_picture, + struct h264_dpb_stru *p_H264_Dpb, + struct OldSliceParams *p_old_slice) +{ + int ret = 0; + if (p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] == 0) + ret = 1; + return ret; +} + +#endif + +int remove_picture(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *pic) +{ + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + if (p_Dpb->last_picture == NULL) { + if (pic->colocated_buf_index >= 0) { + release_colocate_buf(p_H264_Dpb, + pic->colocated_buf_index); + pic->colocated_buf_index = -1; + } + release_buf_spec_num(p_H264_Dpb->vdec, pic->buf_spec_num); + } + free_picture(p_H264_Dpb, pic); + return 0; +} + +static void check_frame_store_same_pic_num(struct DecodedPictureBuffer *p_Dpb, + struct StorablePicture *p, struct Slice *currSlice) +{ + if (p_Dpb->last_picture) { + if ((int)p_Dpb->last_picture->frame_num == p->pic_num) { + if (((p->structure == TOP_FIELD) && + (p_Dpb->last_picture->is_used == 2)) || + ((p->structure == BOTTOM_FIELD) && + (p_Dpb->last_picture->is_used == 1))) { + if ((p->used_for_reference && + (p_Dpb->last_picture-> + is_orig_reference != 0)) || + (!p->used_for_reference && + (p_Dpb->last_picture-> + is_orig_reference == 0))) { + p->buf_spec_num = + p_Dpb->last_picture-> + buf_spec_num; + p->colocated_buf_index = p_Dpb-> + last_picture-> + colocated_buf_index; + if (currSlice->structure == + TOP_FIELD) { + p->bottom_poc = + p_Dpb->last_picture-> + bottom_field->poc; + } else { + p->top_poc = + p_Dpb->last_picture-> + top_field->poc; + } + p->frame_poc = imin(p->bottom_poc, + p->top_poc); + } + } + } + } +} + +int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb) +{ + + int new_pic_flag = 0; + struct Slice *currSlice = &p_H264_Dpb->mSlice; + struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo; +#if 0 + new_pic_flag = is_new_picture(p_H264_Dpb->mVideo.dec_picture, + p_H264_Dpb, + &p_H264_Dpb->mVideo.old_slice); + + if (new_pic_flag) { /* new picture */ + if (p_H264_Dpb->mVideo.dec_picture) { + store_picture_in_dpb(p_H264_Dpb, + p_H264_Dpb->mVideo.dec_picture); + /* dump_dpb(&p_H264_Dpb->mDPB); */ + } + } +#else + new_pic_flag = (p_H264_Dpb->mVideo.dec_picture == NULL); +#endif + + slice_prepare(p_H264_Dpb, &p_H264_Dpb->mDPB, &p_H264_Dpb->mVideo, + &p_H264_Dpb->mSPS, &p_H264_Dpb->mSlice); + + /* if (p_Vid->active_sps != sps) { */ + if (p_H264_Dpb->mDPB.init_done == 0) { + /*init_global_buffers(p_Vid, 0); + + if (!p_Vid->no_output_of_prior_pics_flag) + { + flush_dpb(p_Vid->p_Dpb_layer[0]); + } + init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 0); + */ + init_dpb(p_H264_Dpb, 0); + } + + + if (new_pic_flag) { /* new picture */ + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "check frame_num gap: cur frame_num %d pre_frame_num %d max_frmae_num %d\r\n", + currSlice->frame_num, + p_Vid->pre_frame_num, + p_Vid->max_frame_num); + if (p_Vid->recovery_point == 0 && + currSlice->frame_num != p_Vid->pre_frame_num && + currSlice->frame_num != + (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num) { + /*if (active_sps-> + gaps_in_frame_num_value_allowed_flag + == 0) { + error("An unintentional + loss of pictures occurs! Exit\n", + 100); + } + if (p_Vid->conceal_mode == 0)*/ + fill_frame_num_gap(p_Vid, currSlice); + } + + if (currSlice->nal_reference_idc) { + dpb_print(p_H264_Dpb->decoder_index, + PRINT_FLAG_DPB_DETAIL, + "nal_reference_idc not 0, set pre_frame_num(%d) to frame_num (%d)\n", + p_Vid->pre_frame_num, currSlice->frame_num); + p_Vid->pre_frame_num = currSlice->frame_num; + } + + decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice); + p_H264_Dpb->mVideo.dec_picture = get_new_pic(p_H264_Dpb, + p_H264_Dpb->mSlice.structure, + /*p_Vid->width, p_Vid->height, + p_Vid->width_cr, + p_Vid->height_cr,*/ + 1); + if (p_H264_Dpb->mVideo.dec_picture) { + struct DecodedPictureBuffer *p_Dpb = + &p_H264_Dpb->mDPB; + struct StorablePicture *p = + p_H264_Dpb->mVideo.dec_picture; + init_picture(p_H264_Dpb, &p_H264_Dpb->mSlice, + p_H264_Dpb->mVideo.dec_picture); +#if 1 + /* rain */ + p_H264_Dpb->mVideo.dec_picture->offset_delimiter_lo = + p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_LO]; + p_H264_Dpb->mVideo.dec_picture->offset_delimiter_hi = + p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_HI]; + + p_H264_Dpb->mVideo.dec_picture->buf_spec_num = -1; + p_H264_Dpb->mVideo.dec_picture-> + colocated_buf_index = -1; + update_pic_num(&p_H264_Dpb->mSlice); + + if ((currSlice->structure == TOP_FIELD) || + (currSlice->structure == BOTTOM_FIELD)) { + /* check for frame store with same + pic_number */ + check_frame_store_same_pic_num(p_Dpb, p, + currSlice); + } + + if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num == + -1) { + p_H264_Dpb->mVideo.dec_picture->buf_spec_num = + get_free_buf_idx(p_H264_Dpb->vdec); + if (p_H264_Dpb->mVideo.dec_picture-> + used_for_reference) { + p_H264_Dpb->mVideo.dec_picture-> + colocated_buf_index = + allocate_colocate_buf( + p_H264_Dpb); + } + } +#endif + } + } + + if (p_H264_Dpb->mSlice.slice_type == P_SLICE) + init_lists_p_slice(&p_H264_Dpb->mSlice); + else if (p_H264_Dpb->mSlice.slice_type == B_SLICE) + init_lists_b_slice(&p_H264_Dpb->mSlice); + else + init_lists_i_slice(&p_H264_Dpb->mSlice); + + reorder_lists(&p_H264_Dpb->mSlice); + + if (p_H264_Dpb->mSlice.structure == FRAME) + init_mbaff_lists(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice); + + if (new_pic_flag) + return 1; + + return 0; +} diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h new file mode 100644 index 000000000000..e58f08461aa0 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h @@ -0,0 +1,788 @@ +#ifndef H264_DPB_H_ +#define H264_DPB_H_ + +#define ERROR_CHECK + +#define OUTPUT_BUFFER_IN_C + +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_DPB 0X0001 +#define PRINT_FLAG_DPB_DETAIL 0x0002 +#define PRINT_FLAG_DUMP_DPB 0x0004 +#define PRINT_FLAG_UCODE_EVT 0x0008 +#define PRINT_FLAG_VDEC_STATUS 0x0010 +#define PRINT_FLAG_VDEC_DETAIL 0x0020 +#define PRINT_FLAG_UCODE_DBG 0x0040 +#define PRINT_FLAG_TIME_STAMP 0x0080 +#define PRINT_FLAG_RUN_SCHEDULE 0x0100 +#define PRINT_FLAG_DEBUG_POC 0x0200 +#define PRINT_FLAG_VDEC_DATA 0x0400 +#define DISABLE_ERROR_HANDLE 0x10000 +#define OUTPUT_CURRENT_BUF 0x20000 +#define ONLY_RESET_AT_START 0x40000 +#define LOAD_UCODE_ALWAYS 0x80000 +#define FORCE_NO_SLICE 0x100000 +#define REINIT_DPB_TEST 0x200000 + + +#define MVC_EXTENSION_ENABLE 0 +#define PRINTREFLIST 0 + +#define MAX_LIST_SIZE 33 + +#define FALSE 0 + +#define H264_SLICE_HEAD_DONE 0x01 +#define H264_PIC_DATA_DONE 0x02 +/*#define H264_SPS_DONE 0x03*/ +/*#define H264_PPS_DONE 0x04*/ +/*#define H264_SLICE_DATA_DONE 0x05*/ +/*#define H264_DATA_END 0x06*/ + +#define H264_CONFIG_REQUEST 0x11 +#define H264_DATA_REQUEST 0x12 + +#define H264_DECODE_BUFEMPTY 0x20 +#define H264_DECODE_TIMEOUT 0x21 +#define H264_SEARCH_BUFEMPTY 0x22 + /* 0x8x, search state*/ +#define H264_STATE_SEARCH_AFTER_SPS 0x80 +#define H264_STATE_SEARCH_AFTER_PPS 0x81 +#define H264_STATE_PARSE_SLICE_HEAD 0x82 +#define H264_STATE_SEARCH_HEAD 0x83 + /**/ +#define H264_ACTION_SEARCH_HEAD 0xf0 +#define H264_ACTION_DECODE_SLICE 0xf1 +#define H264_ACTION_CONFIG_DONE 0xf2 +#define H264_ACTION_DECODE_NEWPIC 0xf3 +#define H264_ACTION_DECODE_START 0xff + +#define RPM_BEGIN 0x0 +#define RPM_END 0x400 + +#define val(s) (s[0]|(s[1]<<16)) + +#define FRAME_IN_DPB 24 +#define DPB_OFFSET 0x100 +#define MMCO_OFFSET 0x200 +union param { +#define H_TIME_STAMP_START 0X00 +#define H_TIME_STAMP_END 0X17 +#define PTS_ZERO_0 0X18 +#define PTS_ZERO_1 0X19 +#define FIXED_FRAME_RATE_FLAG 0X1A + +#define OFFSET_DELIMITER_LO 0x2f +#define OFFSET_DELIMITER_HI 0x30 + + +#define SLICE_IPONLY_BREAK 0X5C +#define PREV_MAX_REFERENCE_FRAME_NUM 0X5D +#define EOS 0X5E +#define FRAME_PACKING_TYPE 0X5F +#define OLD_POC_PAR_1 0X60 +#define OLD_POC_PAR_2 0X61 +#define PREV_MBX 0X62 +#define PREV_MBY 0X63 +#define ERROR_SKIP_MB_NUM 0X64 +#define ERROR_MB_STATUS 0X65 +#define L0_PIC0_STATUS 0X66 +#define TIMEOUT_COUNTER 0X67 +#define BUFFER_SIZE 0X68 +#define BUFFER_SIZE_HI 0X69 +#define CROPPING_LEFT_RIGHT 0X6A +#define CROPPING_TOP_BOTTOM 0X6B +#define POC_SELECT_NEED_SWAP 0X6C +#define POC_SELECT_SWAP 0X6D +#define MAX_BUFFER_FRAME 0X6E + +#define NON_CONFORMING_STREAM 0X70 +#define RECOVERY_POINT 0X71 +#define POST_CANVAS 0X72 +#define POST_CANVAS_H 0X73 +#define SKIP_PIC_COUNT 0X74 +#define TARGET_NUM_SCALING_LIST 0X75 +#define FF_POST_ONE_FRAME 0X76 +#define PREVIOUS_BIT_CNT 0X77 +#define MB_NOT_SHIFT_COUNT 0X78 +#define PIC_STATUS 0X79 +#define FRAME_COUNTER 0X7A +#define NEW_SLICE_TYPE 0X7B +#define NEW_PICTURE_STRUCTURE 0X7C +#define NEW_FRAME_NUM 0X7D +#define NEW_IDR_PIC_ID 0X7E +#define IDR_PIC_ID 0X7F + +/* h264 LOCAL */ +#define NAL_UNIT_TYPE 0X80 +#define NAL_REF_IDC 0X81 +#define SLICE_TYPE 0X82 +#define LOG2_MAX_FRAME_NUM 0X83 +#define FRAME_MBS_ONLY_FLAG 0X84 +#define PIC_ORDER_CNT_TYPE 0X85 +#define LOG2_MAX_PIC_ORDER_CNT_LSB 0X86 +#define PIC_ORDER_PRESENT_FLAG 0X87 +#define REDUNDANT_PIC_CNT_PRESENT_FLAG 0X88 +#define PIC_INIT_QP_MINUS26 0X89 +#define DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG 0X8A +#define NUM_SLICE_GROUPS_MINUS1 0X8B +#define MODE_8X8_FLAGS 0X8C +#define ENTROPY_CODING_MODE_FLAG 0X8D +#define SLICE_QUANT 0X8E +#define TOTAL_MB_HEIGHT 0X8F +#define PICTURE_STRUCTURE 0X90 +#define TOP_INTRA_TYPE 0X91 +#define RV_AI_STATUS 0X92 +#define AI_READ_START 0X93 +#define AI_WRITE_START 0X94 +#define AI_CUR_BUFFER 0X95 +#define AI_DMA_BUFFER 0X96 +#define AI_READ_OFFSET 0X97 +#define AI_WRITE_OFFSET 0X98 +#define AI_WRITE_OFFSET_SAVE 0X99 +#define RV_AI_BUFF_START 0X9A +#define I_PIC_MB_COUNT 0X9B +#define AI_WR_DCAC_DMA_CTRL 0X9C +#define SLICE_MB_COUNT 0X9D +#define PICTYPE 0X9E +#define SLICE_GROUP_MAP_TYPE 0X9F +#define MB_TYPE 0XA0 +#define MB_AFF_ADDED_DMA 0XA1 +#define PREVIOUS_MB_TYPE 0XA2 +#define WEIGHTED_PRED_FLAG 0XA3 +#define WEIGHTED_BIPRED_IDC 0XA4 +/* bit 3:2 - PICTURE_STRUCTURE + * bit 1 - MB_ADAPTIVE_FRAME_FIELD_FLAG + * bit 0 - FRAME_MBS_ONLY_FLAG + */ +#define MBFF_INFO 0XA5 +#define TOP_INTRA_TYPE_TOP 0XA6 + +#define RV_AI_BUFF_INC 0xa7 + +#define DEFAULT_MB_INFO_LO 0xa8 + +/* 0 -- no need to read + * 1 -- need to wait Left + * 2 -- need to read Intra + * 3 -- need to read back MV + */ +#define NEED_READ_TOP_INFO 0xa9 +/* 0 -- idle + * 1 -- wait Left + * 2 -- reading top Intra + * 3 -- reading back MV + */ +#define READ_TOP_INFO_STATE 0xaa +#define DCAC_MBX 0xab +#define TOP_MB_INFO_OFFSET 0xac +#define TOP_MB_INFO_RD_IDX 0xad +#define TOP_MB_INFO_WR_IDX 0xae + +#define VLD_NO_WAIT 0 +#define VLD_WAIT_BUFFER 1 +#define VLD_WAIT_HOST 2 +#define VLD_WAIT_GAP 3 + +#define VLD_WAITING 0xaf + +#define MB_X_NUM 0xb0 +/* #define MB_WIDTH 0xb1 */ +#define MB_HEIGHT 0xb2 +#define MBX 0xb3 +#define TOTAL_MBY 0xb4 +#define INTR_MSK_SAVE 0xb5 + +/* #define has_time_stamp 0xb6 */ +#define NEED_DISABLE_PPE 0xb6 +#define IS_NEW_PICTURE 0XB7 +#define PREV_NAL_REF_IDC 0XB8 +#define PREV_NAL_UNIT_TYPE 0XB9 +#define FRAME_MB_COUNT 0XBA +#define SLICE_GROUP_UCODE 0XBB +#define SLICE_GROUP_CHANGE_RATE 0XBC +#define SLICE_GROUP_CHANGE_CYCLE_LEN 0XBD +#define DELAY_LENGTH 0XBE +#define PICTURE_STRUCT 0XBF +/* #define pre_picture_struct 0xc0 */ +#define DCAC_PREVIOUS_MB_TYPE 0xc1 + +#define TIME_STAMP 0XC2 +#define H_TIME_STAMP 0XC3 +#define VPTS_MAP_ADDR 0XC4 +#define H_VPTS_MAP_ADDR 0XC5 + +#define MAX_DPB_SIZE 0XC6 +#define PIC_INSERT_FLAG 0XC7 + +#define TIME_STAMP_START 0XC8 +#define TIME_STAMP_END 0XDF + +#define OFFSET_FOR_NON_REF_PIC 0XE0 +#define OFFSET_FOR_TOP_TO_BOTTOM_FIELD 0XE2 +#define MAX_REFERENCE_FRAME_NUM 0XE4 +#define FRAME_NUM_GAP_ALLOWED 0XE5 +#define NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE 0XE6 +#define PROFILE_IDC_MMCO 0XE7 +#define LEVEL_IDC_MMCO 0XE8 +#define FRAME_SIZE_IN_MB 0XE9 +#define DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG 0XEA +#define PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1 0XEB +#define PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1 0XEC +#define CURRENT_SPS_ID 0XED +#define CURRENT_PPS_ID 0XEE +/* bit 0 - sequence parameter set may change + * bit 1 - picture parameter set may change + * bit 2 - new dpb just inited + * bit 3 - IDR picture not decoded yet + * bit 5:4 - 0: mb level code loaded 1: picture + * level code loaded 2: slice level code loaded + */ +#define DECODE_STATUS 0XEF +#define FIRST_MB_IN_SLICE 0XF0 +#define PREV_MB_WIDTH 0XF1 +#define PREV_FRAME_SIZE_IN_MB 0XF2 +#define MAX_REFERENCE_FRAME_NUM_IN_MEM 0XF3 +/* bit 0 - aspect_ratio_info_present_flag + * bit 1 - timing_info_present_flag + * bit 2 - nal_hrd_parameters_present_flag + * bit 3 - vcl_hrd_parameters_present_flag + * bit 4 - pic_struct_present_flag + * bit 5 - bitstream_restriction_flag + */ +#define VUI_STATUS 0XF4 +#define ASPECT_RATIO_IDC 0XF5 +#define ASPECT_RATIO_SAR_WIDTH 0XF6 +#define ASPECT_RATIO_SAR_HEIGHT 0XF7 +#define NUM_UNITS_IN_TICK 0XF8 +#define TIME_SCALE 0XFA +#define CURRENT_PIC_INFO 0XFC +#define DPB_BUFFER_INFO 0XFD +#define REFERENCE_POOL_INFO 0XFE +#define REFERENCE_LIST_INFO 0XFF + struct{ + unsigned short data[RPM_END-RPM_BEGIN]; + } l; + struct{ + unsigned short dump[DPB_OFFSET]; + unsigned short dpb_base[FRAME_IN_DPB<<3]; + + unsigned short dpb_max_buffer_frame; + unsigned short actual_dpb_size; + + unsigned short colocated_buf_status; + + unsigned short num_forward_short_term_reference_pic; + unsigned short num_short_term_reference_pic; + unsigned short num_reference_pic; + + unsigned short current_dpb_index; + unsigned short current_decoded_frame_num; + unsigned short current_reference_frame_num; + + unsigned short l0_size; + unsigned short l1_size; + + /* [6:5] : nal_ref_idc */ + /* [4:0] : nal_unit_type */ + unsigned short NAL_info_mmco; + + /* [1:0] : 00 - top field, 01 - bottom field, + 10 - frame, 11 - mbaff frame */ + unsigned short picture_structure_mmco; + + unsigned short frame_num; + unsigned short pic_order_cnt_lsb; + + unsigned short num_ref_idx_l0_active_minus1; + unsigned short num_ref_idx_l1_active_minus1; + + unsigned short PrevPicOrderCntLsb; + unsigned short PreviousFrameNum; + + /* 32 bits variables */ + unsigned short delta_pic_order_cnt_bottom[2]; + unsigned short delta_pic_order_cnt_0[2]; + unsigned short delta_pic_order_cnt_1[2]; + + unsigned short PrevPicOrderCntMsb[2]; + unsigned short PrevFrameNumOffset[2]; + + unsigned short frame_pic_order_cnt[2]; + unsigned short top_field_pic_order_cnt[2]; + unsigned short bottom_field_pic_order_cnt[2]; + + unsigned short colocated_mv_addr_start[2]; + unsigned short colocated_mv_addr_end[2]; + unsigned short colocated_mv_wr_addr[2]; + } dpb; + struct { + unsigned short dump[MMCO_OFFSET]; + + /* array base address for offset_for_ref_frame */ + unsigned short offset_for_ref_frame_base[128]; + + /* 0 - Index in DPB + * 1 - Picture Flag + * [ 2] : 0 - short term reference, + * 1 - long term reference + * [ 1] : bottom field + * [ 0] : top field + * 2 - Picture Number (short term or long term) low 16 bits + * 3 - Picture Number (short term or long term) high 16 bits + */ + unsigned short reference_base[128]; + + /* command and parameter, until command is 3 */ + unsigned short l0_reorder_cmd[66]; + unsigned short l1_reorder_cmd[66]; + + /* command and parameter, until command is 0 */ + unsigned short mmco_cmd[44]; + + unsigned short l0_base[40]; + unsigned short l1_base[40]; + } mmco; + struct { + /* from ucode lmem, do not change this struct */ + } p; +}; + + +struct StorablePicture; +struct VideoParameters; +struct DecodedPictureBuffer; + +/* New enum for field processing */ +enum PictureStructure { + FRAME, + TOP_FIELD, + BOTTOM_FIELD +}; + +#define I_Slice 2 +#define P_Slice 5 +#define B_Slice 6 +#define P_Slice_0 0 +#define B_Slice_1 1 +#define I_Slice_7 7 + +enum SliceType { + P_SLICE = 0, + B_SLICE = 1, + I_SLICE = 2, + SP_SLICE = 3, + SI_SLICE = 4, + NUM_SLICE_TYPES = 5 +}; + +struct SPSParameters { + int pic_order_cnt_type; + int log2_max_pic_order_cnt_lsb_minus4; + int num_ref_frames_in_pic_order_cnt_cycle; + short offset_for_ref_frame[128]; + short offset_for_non_ref_pic; + short offset_for_top_to_bottom_field; + + /**/ + int frame_mbs_only_flag; + int num_ref_frames; + int max_dpb_size; + + int log2_max_frame_num_minus4; +}; + +#define DEC_REF_PIC_MARKING_BUFFER_NUM_MAX 45 +struct DecRefPicMarking_s { + int memory_management_control_operation; + int difference_of_pic_nums_minus1; + int long_term_pic_num; + int long_term_frame_idx; + int max_long_term_frame_idx_plus1; + struct DecRefPicMarking_s *Next; +}; + +#define REORDERING_COMMAND_MAX_SIZE 33 +struct Slice { + int first_mb_in_slice; + int mode_8x8_flags; + int picture_structure_mmco; + + int frame_num; + int idr_flag; + int toppoc; + int bottompoc; + int framepoc; + int pic_order_cnt_lsb; + int PicOrderCntMsb; + unsigned char field_pic_flag; + unsigned char bottom_field_flag; + int ThisPOC; + int nal_reference_idc; + int AbsFrameNum; + int delta_pic_order_cnt_bottom; + int delta_pic_order_cnt[2]; + + /**/ + char listXsize[6]; + struct StorablePicture *listX[6][MAX_LIST_SIZE * 2]; + + /**/ + enum PictureStructure structure; + int long_term_reference_flag; + int no_output_of_prior_pics_flag; + int adaptive_ref_pic_buffering_flag; + + struct VideoParameters *p_Vid; + struct DecodedPictureBuffer *p_Dpb; + int num_ref_idx_active[2]; /* number of available list references */ + + /*modification*/ + int slice_type; /* slice type */ + int ref_pic_list_reordering_flag[2]; + int modification_of_pic_nums_idc[2][REORDERING_COMMAND_MAX_SIZE]; + int abs_diff_pic_num_minus1[2][REORDERING_COMMAND_MAX_SIZE]; + int long_term_pic_idx[2][REORDERING_COMMAND_MAX_SIZE]; + /**/ + unsigned char dec_ref_pic_marking_buffer_valid; + struct DecRefPicMarking_s + dec_ref_pic_marking_buffer[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX]; +}; + +struct OldSliceParams { + unsigned field_pic_flag; + unsigned frame_num; + int nal_ref_idc; + unsigned pic_oder_cnt_lsb; + int delta_pic_oder_cnt_bottom; + int delta_pic_order_cnt[2]; + unsigned char bottom_field_flag; + unsigned char idr_flag; + int idr_pic_id; + int pps_id; +#if (MVC_EXTENSION_ENABLE) + int view_id; + int inter_view_flag; + int anchor_pic_flag; +#endif + int layer_id; +}; + +struct VideoParameters { + int PrevPicOrderCntMsb; + int PrevPicOrderCntLsb; + unsigned char last_has_mmco_5; + unsigned char last_pic_bottom_field; + int ThisPOC; + int PreviousFrameNum; + int FrameNumOffset; + int PreviousFrameNumOffset; + int max_frame_num; + unsigned int pre_frame_num; + int ExpectedDeltaPerPicOrderCntCycle; + int PicOrderCntCycleCnt; + int FrameNumInPicOrderCntCycle; + int ExpectedPicOrderCnt; + + /**/ + struct SPSParameters *active_sps; + struct Slice **ppSliceList; + int iSliceNumOfCurrPic; + int conceal_mode; + int earlier_missing_poc; + int pocs_in_dpb[100]; + + struct OldSliceParams old_slice; + /**/ + struct StorablePicture *dec_picture; + struct StorablePicture *no_reference_picture; + + /*modification*/ + int non_conforming_stream; + int recovery_point; +}; + +static inline int imin(int a, int b) +{ + return ((a) < (b)) ? (a) : (b); +} + +static inline int imax(int a, int b) +{ + return ((a) > (b)) ? (a) : (b); +} + +#define MAX_PIC_BUF_NUM 128 +#define MAX_NUM_SLICES 50 + +struct StorablePicture { +/**/ + int width; + int height; + + int y_canvas_index; + int u_canvas_index; + int v_canvas_index; +/**/ + int index; + unsigned char is_used; + + enum PictureStructure structure; + + int poc; + int top_poc; + int bottom_poc; + int frame_poc; + unsigned int frame_num; + unsigned int recovery_frame; + + int pic_num; + int buf_spec_num; + int colocated_buf_index; + int long_term_pic_num; + int long_term_frame_idx; + + unsigned char is_long_term; + int used_for_reference; + int is_output; +#if 1 + /* rain */ + int pre_output; +#endif + int non_existing; + int separate_colour_plane_flag; + + short max_slice_id; + + int size_x, size_y, size_x_cr, size_y_cr; + int size_x_m1, size_y_m1, size_x_cr_m1, size_y_cr_m1; + int coded_frame; + int mb_aff_frame_flag; + unsigned PicWidthInMbs; + unsigned PicSizeInMbs; + int iLumaPadY, iLumaPadX; + int iChromaPadY, iChromaPadX; + + /* for mb aff, if frame for referencing the top field */ + struct StorablePicture *top_field; + /* for mb aff, if frame for referencing the bottom field */ + struct StorablePicture *bottom_field; + /* for mb aff, if field for referencing the combined frame */ + struct StorablePicture *frame; + + int slice_type; + int idr_flag; + int no_output_of_prior_pics_flag; + int long_term_reference_flag; + int adaptive_ref_pic_buffering_flag; + + int chroma_format_idc; + int frame_mbs_only_flag; + int frame_cropping_flag; + int frame_crop_left_offset; + int frame_crop_right_offset; + int frame_crop_top_offset; + int frame_crop_bottom_offset; + int qp; + int chroma_qp_offset[2]; + int slice_qp_delta; + /* stores the memory management control operations */ + struct DecRefPicMarking_s *dec_ref_pic_marking_buffer; + + /* picture error concealment */ + /*indicates if this is a concealed picture */ + int concealed_pic; + + /* variables for tone mapping */ + int seiHasTone_mapping; + int tone_mapping_model_id; + int tonemapped_bit_depth; + /* imgpel* tone_mapping_lut; tone mapping look up table */ + + int proc_flag; +#if (MVC_EXTENSION_ENABLE) + int view_id; + int inter_view_flag; + int anchor_pic_flag; +#endif + int iLumaStride; + int iChromaStride; + int iLumaExpandedHeight; + int iChromaExpandedHeight; + /* imgpel **cur_imgY; for more efficient get_block_luma */ + int no_ref; + int iCodingType; + + char listXsize[MAX_NUM_SLICES][2]; + struct StorablePicture **listX[MAX_NUM_SLICES][2]; + int layer_id; + + int offset_delimiter_lo; + int offset_delimiter_hi; + + u32 pts; + u64 pts64; +}; + +struct FrameStore { + /* rain */ + int buf_spec_num; + /* rain */ + int colocated_buf_index; + + /* 0=empty; 1=top; 2=bottom; 3=both fields (or frame) */ + int is_used; + /* 0=not used for ref; 1=top used; 2=bottom used; + * 3=both fields (or frame) used */ + int is_reference; + /* 0=not used for ref; 1=top used; 2=bottom used; + * 3=both fields (or frame) used */ + int is_long_term; + /* original marking by nal_ref_idc: 0=not used for ref; 1=top used; + * 2=bottom used; 3=both fields (or frame) used */ + int is_orig_reference; + + int is_non_existent; + + unsigned frame_num; + unsigned recovery_frame; + + int frame_num_wrap; + int long_term_frame_idx; + int is_output; +#if 1 + /* rain */ + int pre_output; + /* index in gFrameStore */ + int index; +#endif + int poc; + + /* picture error concealment */ + int concealment_reference; + + struct StorablePicture *frame; + struct StorablePicture *top_field; + struct StorablePicture *bottom_field; + +#if (MVC_EXTENSION_ENABLE) + int view_id; + int inter_view_flag[2]; + int anchor_pic_flag[2]; +#endif + int layer_id; + + u32 pts; + u64 pts64; +}; + +int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame); + + +/* #define DPB_SIZE_MAX 16 */ +#define DPB_SIZE_MAX 32 +struct DecodedPictureBuffer { + struct VideoParameters *p_Vid; + /* InputParameters *p_Inp; ??? */ + struct FrameStore *fs[DPB_SIZE_MAX]; + struct FrameStore *fs_ref[DPB_SIZE_MAX]; + struct FrameStore *fs_ltref[DPB_SIZE_MAX]; + /* inter-layer reference (for multi-layered codecs) */ + struct FrameStore *fs_ilref[DPB_SIZE_MAX]; + /**/ + struct FrameStore *fs_list0[DPB_SIZE_MAX]; + struct FrameStore *fs_list1[DPB_SIZE_MAX]; + struct FrameStore *fs_listlt[DPB_SIZE_MAX]; + + /**/ + unsigned size; + unsigned used_size; + unsigned ref_frames_in_buffer; + unsigned ltref_frames_in_buffer; + int last_output_poc; +#if (MVC_EXTENSION_ENABLE) + int last_output_view_id; +#endif + int max_long_term_pic_idx; + + + int init_done; + int num_ref_frames; + + struct FrameStore *last_picture; + unsigned used_size_il; + int layer_id; + + /* DPB related function; */ +}; + +struct h264_dpb_stru { + struct vdec_s *vdec; + int decoder_index; + + union param dpb_param; + + int decode_idx; + int buf_num; + int curr_POC; + int reorder_pic_num; + /**/ + unsigned int max_reference_size; + + unsigned int colocated_buf_map; + unsigned int colocated_buf_count; + unsigned int colocated_mv_addr_start; + unsigned int colocated_mv_addr_end; + unsigned int colocated_buf_size; + + struct DecodedPictureBuffer mDPB; + struct Slice mSlice; + struct VideoParameters mVideo; + struct SPSParameters mSPS; + + struct StorablePicture m_PIC[MAX_PIC_BUF_NUM]; + struct FrameStore mFrameStore[DPB_SIZE_MAX]; + +}; + + +extern unsigned int h264_debug_flag; +extern unsigned int h264_debug_mask; + +int dpb_print(int indext, int debug_flag, const char *fmt, ...); + +unsigned char dpb_is_debug(int index, int debug_flag); + +int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame); + +int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num); + +void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index); + +int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb); + +int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb); + +void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb, + int id, int actual_dpb_size, int max_reference_size); + +void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count); + +int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index); + +int get_free_buf_idx(struct vdec_s *vdec); + +void store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *p); + +int remove_picture(struct h264_dpb_stru *p_H264_Dpb, + struct StorablePicture *pic); + +void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb); + +int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb, + int buf_spec_num); + +void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb); + +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c new file mode 100644 index 000000000000..59b74577c80e --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c @@ -0,0 +1,2776 @@ +/* + * drivers/amlogic/amports/vh264.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/amports/amports_priv.h" +#include + +#include "../utils/vdec_input.h" + +#include +#include "../utils/vdec.h" +#include "../utils/amvdec.h" +#include "../h264/vh264.h" +#include "../../../stream_input/parser/streambuf.h" +#include + +#undef pr_info +#define pr_info printk + +#define DEBUG_UCODE +#define USE_CMA +#define MEM_NAME "codec_m264" +#define MULTI_INSTANCE_FRAMEWORK +/* #define ONE_COLOCATE_BUF_PER_DECODE_BUF */ +#include "h264_dpb.h" +/* #define SEND_PARAM_WITH_REG */ + +#define DRIVER_NAME "ammvdec_h264" +#define MODULE_NAME "ammvdec_h264" + +#define CHECK_INTERVAL (HZ/100) + +#define RATE_MEASURE_NUM 8 +#define RATE_CORRECTION_THRESHOLD 5 +#define RATE_2397_FPS 4004 /* 23.97 */ +#define RATE_25_FPS 3840 /* 25 */ +#define RATE_2997_FPS 3203 /* 29.97 */ +#define DUR2PTS(x) ((x)*90/96) +#define PTS2DUR(x) ((x)*96/90) +#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) +#define FIX_FRAME_RATE_CHECK_IFRAME_NUM 2 + +#define FIX_FRAME_RATE_OFF 0 +#define FIX_FRAME_RATE_ON 1 +#define FIX_FRAME_RATE_SMOOTH_CHECKING 2 + +#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001 +#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE 0x0002 +#define DEC_CONTROL_FLAG_FORCE_RATE_2397_FPS_FIX_FRAME_RATE 0x0010 +#define DEC_CONTROL_FLAG_FORCE_RATE_2997_FPS_FIX_FRAME_RATE 0x0020 + + +#define RATE_MEASURE_NUM 8 +#define RATE_CORRECTION_THRESHOLD 5 +#define RATE_24_FPS 4004 /* 23.97 */ +#define RATE_25_FPS 3840 /* 25 */ +#define DUR2PTS(x) ((x)*90/96) +#define PTS2DUR(x) ((x)*96/90) +#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) +#define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2 + +#define H264_DEV_NUM 5 + +unsigned int h264_debug_flag; /* 0xa0000000; */ +unsigned int h264_debug_mask = 0xff; + /* + h264_debug_cmd: + 0x1xx, force decoder id of xx to be disconnected + */ +unsigned int h264_debug_cmd; +static unsigned int dec_control; +static unsigned int force_rate_streambase; +static unsigned int force_rate_framebase; +static unsigned int fixed_frame_rate_mode; +static unsigned int error_recovery_mode_in; +static unsigned int start_decode_buf_level = 0x8000; + +static unsigned int reorder_dpb_size_margin = 6; +static unsigned int reference_buf_margin = 4; + +static unsigned int decode_timeout_val = 50; +static unsigned int radr; +static unsigned int rval; +static unsigned int max_decode_instance_num = H264_DEV_NUM; +static unsigned int decode_frame_count[H264_DEV_NUM]; +static unsigned int max_process_time[H264_DEV_NUM]; +static unsigned int max_get_frame_interval[H264_DEV_NUM]; + /* bit[3:0]: + 0, run ; 1, pause; 3, step + bit[4]: + 1, schedule run + */ +static unsigned int step[H264_DEV_NUM]; + +#define is_in_parsing_state(status) \ + ((status == H264_ACTION_SEARCH_HEAD) || \ + ((status & 0xf0) == 0x80)) + +static inline bool close_to(int a, int b, int m) +{ + return (abs(a - b) < m) ? true : false; +} + +/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +/* #endif */ + +/* 12M for L41 */ +#define MAX_DPB_BUFF_SIZE (12*1024*1024) +#define DEFAULT_MEM_SIZE (32*1024*1024) +#define AVIL_DPB_BUFF_SIZE 0x01ec2000 + +#define DEF_BUF_START_ADDR 0x1000000 +#define V_BUF_ADDR_OFFSET (0x13e000) + +#define PIC_SINGLE_FRAME 0 +#define PIC_TOP_BOT_TOP 1 +#define PIC_BOT_TOP_BOT 2 +#define PIC_DOUBLE_FRAME 3 +#define PIC_TRIPLE_FRAME 4 +#define PIC_TOP_BOT 5 +#define PIC_BOT_TOP 6 +#define PIC_INVALID 7 + +#define EXTEND_SAR 0xff + +#define VF_POOL_SIZE 64 +#define MAX_VF_BUF_NUM 28 +#define PUT_INTERVAL (HZ/100) +#define NO_DISP_WD_COUNT (3 * HZ / PUT_INTERVAL) + +#define SWITCHING_STATE_OFF 0 +#define SWITCHING_STATE_ON_CMD3 1 +#define SWITCHING_STATE_ON_CMD1 2 + +#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001 +#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE 0x0002 + +#define INCPTR(p) ptr_atomic_wrap_inc(&p) + +#define SLICE_TYPE_I 2 +#define SLICE_TYPE_P 5 +#define SLICE_TYPE_B 6 + +struct buffer_spec_s { + /* + used: + 0, free; 1, used by dpb; 2, + used for display; + 3 isolated (do not use for dpb when vf_put) + */ + unsigned int used; + unsigned int info0; + unsigned int info1; + unsigned int info2; + unsigned int y_addr; + unsigned int u_addr; + unsigned int v_addr; + + int y_canvas_index; + int u_canvas_index; + int v_canvas_index; + +#ifdef NV21 + struct canvas_config_s canvas_config[2]; +#else + struct canvas_config_s canvas_config[3]; +#endif +#ifdef USE_CMA + /* struct page *cma_alloc_pages; */ + unsigned long cma_alloc_addr; + int cma_alloc_count; +#endif + unsigned int buf_adr; +}; + +#define spec2canvas(x) \ + (((x)->v_canvas_index << 16) | \ + ((x)->u_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) + +static struct vframe_s *vh264_vf_peek(void *); +static struct vframe_s *vh264_vf_get(void *); +static void vh264_vf_put(struct vframe_s *, void *); +static int vh264_vf_states(struct vframe_states *states, void *); +static int vh264_event_cb(int type, void *data, void *private_data); +static void vh264_work(struct work_struct *work); + +static const char vh264_dec_id[] = "vh264-dev"; + +#define PROVIDER_NAME "vdec.h264" + +static const struct vframe_operations_s vf_provider_ops = { + .peek = vh264_vf_peek, + .get = vh264_vf_get, + .put = vh264_vf_put, + .event_cb = vh264_event_cb, + .vf_states = vh264_vf_states, +}; + +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 +#define DEC_RESULT_CONFIG_PARAM 3 +#define DEC_RESULT_GET_DATA 4 +#define DEC_RESULT_GET_DATA_RETRY 5 +#define DEC_RESULT_ERROR 6 + +/* +static const char *dec_result_str[] = { + "DEC_RESULT_NONE ", + "DEC_RESULT_DONE ", + "DEC_RESULT_AGAIN ", + "DEC_RESULT_CONFIG_PARAM", + "DEC_RESULT_GET_DATA ", + "DEC_RESULT_GET_DA_RETRY", + "DEC_RESULT_ERROR ", +}; +*/ + +#define UCODE_IP_ONLY 2 +#define UCODE_IP_ONLY_PARAM 1 + +#define MC_OFFSET_HEADER 0x0000 +#define MC_OFFSET_DATA 0x1000 +#define MC_OFFSET_MMCO 0x2000 +#define MC_OFFSET_LIST 0x3000 +#define MC_OFFSET_SLICE 0x4000 +#define MC_OFFSET_MAIN 0x5000 + +#define MC_TOTAL_SIZE ((20+16)*SZ_1K) +#define MC_SWAP_SIZE (4*SZ_1K) +#define MODE_ERROR 0 +#define MODE_FULL 1 + +#define DFS_HIGH_THEASHOLD 3 + +#define INIT_FLAG_REG AV_SCRATCH_2 +#define HEAD_PADING_REG AV_SCRATCH_3 +#define UCODE_WATCHDOG_REG AV_SCRATCH_7 +#define LMEM_DUMP_ADR AV_SCRATCH_L +#define DEBUG_REG1 AV_SCRATCH_M +#define DEBUG_REG2 AV_SCRATCH_N +#define FRAME_COUNTER_REG AV_SCRATCH_I +#define RPM_CMD_REG AV_SCRATCH_A +#define H264_DECODE_SIZE AV_SCRATCH_E +#define H264_DECODE_INFO M4_CONTROL_REG /* 0xc29 */ +#define DPB_STATUS_REG AV_SCRATCH_J +#define MBY_MBX MB_MOTION_MODE /*0xc07*/ + +struct vdec_h264_hw_s { + spinlock_t lock; + + struct platform_device *platform_dev; + struct device *cma_dev; + /* struct page *cma_alloc_pages; */ + unsigned long cma_alloc_addr; + int cma_alloc_count; + /* struct page *collocate_cma_alloc_pages; */ + unsigned long collocate_cma_alloc_addr; + int collocate_cma_alloc_count; + + ulong lmem_addr; + dma_addr_t lmem_addr_remap; + + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + + struct vframe_s vfpool[VF_POOL_SIZE]; + struct buffer_spec_s buffer_spec[MAX_VF_BUF_NUM]; + int buffer_spec_num; + struct vframe_s switching_fense_vf; + struct h264_dpb_stru dpb; + u8 init_flag; + u8 set_params_done; + u32 max_reference_size; + u32 decode_pic_count; + int start_search_pos; + + unsigned char buffer_empty_flag; + + u32 frame_width; + u32 frame_height; + u32 frame_dur; + u32 frame_prog; + u32 frame_packing_type; + + struct vframe_chunk_s *chunk; + + u32 stat; + unsigned long buf_start; + u32 buf_offset; + u32 buf_size; + /* u32 ucode_map_start; */ + u32 pts_outside; + u32 sync_outside; + u32 vh264_ratio; + u32 vh264_rotation; + u32 use_idr_framerate; + + u32 seq_info; + u32 timing_info_present_flag; + u32 fixed_frame_rate_flag; + u32 fixed_frame_rate_check_count; + u32 iframe_count; + u32 aspect_ratio_info; + u32 num_units_in_tick; + u32 time_scale; + u32 h264_ar; + bool h264_first_valid_pts_ready; + u32 h264pts1; + u32 h264pts2; + u32 pts_duration; + u32 h264_pts_count; + u32 duration_from_pts_done; + u32 pts_unstable; u32 duration_on_correcting; + u32 last_checkout_pts; + u32 fatal_error_flag; + u32 fatal_error_reset; + u32 max_refer_buf; + + s32 vh264_stream_switching_state; + struct vframe_s *p_last_vf; + u32 last_pts; + u32 last_pts_remainder; + u32 last_duration; + u32 saved_resolution; + u32 last_mb_width, last_mb_height; + bool check_pts_discontinue; + bool pts_discontinue; + u32 wait_buffer_counter; + u32 first_offset; + u32 first_pts; + u64 first_pts64; + bool first_pts_cached; + + void *sei_data_buffer; + dma_addr_t sei_data_buffer_phys; + + uint error_recovery_mode; + uint mb_total; + uint mb_width; + uint mb_height; + + uint ucode_type; + dma_addr_t mc_dma_handle; + void *mc_cpu_addr; + int vh264_reset; + + atomic_t vh264_active; + + struct dec_sysinfo vh264_amstream_dec_info; + + struct work_struct error_wd_work; + + int dec_result; + struct work_struct work; + + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; + + struct timer_list check_timer; + + /**/ + unsigned last_frame_time; + + /* timeout handle */ + unsigned long int start_process_time; + unsigned last_mby_mbx; + unsigned last_ucode_watchdog_reg_val; + unsigned decode_timeout_count; + unsigned timeout_num; + unsigned search_dataempty_num; + unsigned decode_timeout_num; + unsigned decode_dataempty_num; + unsigned buffer_empty_recover_num; + + /**/ + + /*log*/ + unsigned int packet_write_success_count; + unsigned int packet_write_EAGAIN_count; + unsigned int packet_write_ENOMEM_count; + unsigned int packet_write_EFAULT_count; + unsigned int total_read_size_pre; + unsigned int total_read_size; + unsigned int frame_count_pre; +}; + + +static void vh264_local_init(struct vdec_h264_hw_s *hw); +static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw); +static int vh264_stop(struct vdec_h264_hw_s *hw, int mode); +static s32 vh264_init(struct vdec_h264_hw_s *hw); +static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, + u32 index); + +unsigned char have_free_buf_spec(struct vdec_s *vdec) +{ + int i; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + if ((h264_debug_flag&OUTPUT_CURRENT_BUF) == 0) { + for (i = 0; i < hw->buffer_spec_num; i++) { + if (hw->buffer_spec[i].used == 0) + return 1; + } + return 0; + } else + return 1; +} + +#if 0 +static void buf_spec_recover(struct vdec_h264_hw_s *hw) +{ /* do not clear buf_spec used by display */ + int i; + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_DPB, "%s\n", __func__); + for (i = 0; i < hw->buffer_spec_num; i++) { + if (hw->buffer_spec[i].used == 2) + hw->buffer_spec[i].used = 3; + else + hw->buffer_spec[i].used = 0; + } +} +#endif + +int get_free_buf_idx(struct vdec_s *vdec) +{ + int i; + int index = -1; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + if ((h264_debug_flag&OUTPUT_CURRENT_BUF) == 0) { + for (i = hw->start_search_pos; i < hw->buffer_spec_num; i++) { + if (hw->buffer_spec[i].used == 0) { + hw->buffer_spec[i].used = 1; + hw->start_search_pos = i+1; + index = i; + break; + } + } + if (index < 0) { + for (i = 0; i < hw->start_search_pos; i++) { + if (hw->buffer_spec[i].used == 0) { + hw->buffer_spec[i].used = 1; + hw->start_search_pos = i+1; + index = i; + break; + } + } + } + } else { + index = hw->start_search_pos; + hw->start_search_pos++; + } + + if (hw->start_search_pos >= hw->buffer_spec_num) + hw->start_search_pos = 0; + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s, buf_spec_num %d\n", __func__, index); + + return index; +} + +int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s buf_spec_num %d\n", + __func__, buf_spec_num); + if (buf_spec_num >= 0 && buf_spec_num < hw->buffer_spec_num) + hw->buffer_spec[buf_spec_num].used = 0; + return 0; +} + +static int get_buf_spec_idx_by_canvas_config(struct vdec_h264_hw_s *hw, + struct canvas_config_s *cfg) +{ + int i; + for (i = 0; i < hw->buffer_spec_num; i++) { + if (hw->buffer_spec[i].canvas_config[0].phy_addr + == cfg->phy_addr) + return i; + } + return -1; +} + +int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct vframe_s *vf = NULL; + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s fatal error, no available buffer slot.\n", + __func__); + return -1; + } + + if (vf) { + int buffer_index = frame->buf_spec_num; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s, fs[%d] poc %d, buf_spec_num %d\n", + __func__, frame->index, frame->poc, + frame->buf_spec_num); + vf->index = frame->index; + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; + vf->duration_pulldown = 0; + vf->pts = frame->pts; + vf->pts_us64 = frame->pts64; + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(&hw->buffer_spec[buffer_index]); + set_frame_info(hw, vf, buffer_index); + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + hw->buffer_spec[buffer_index].used = 2; + + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + decode_frame_count[hw->dpb.decoder_index]++; + } + + return 0; +} + +/****************** + * Hardware config + */ +char *slice_type_name[] = { + "P_SLICE ", + "B_SLICE ", + "I_SLICE ", + "SP_SLICE", + "SI_SLICE", +}; + +char *picture_structure_name[] = { + "FRAME", + "TOP_FIELD", + "BOTTOM_FIELD" +}; + +void print_pic_info(int decindex, const char *info, + struct StorablePicture *pic, + int slice_type) +{ + dpb_print(decindex, PRINT_FLAG_UCODE_EVT, + "%s: %s (original %s), %s, mb_aff_frame_flag %d poc %d, pic_num %d, buf_spec_num %d\n", + info, + picture_structure_name[pic->structure], + pic->coded_frame ? "Frame" : "Field", + (slice_type < 0) ? "" : slice_type_name[slice_type], + pic->mb_aff_frame_flag, + pic->poc, + pic->pic_num, + pic->buf_spec_num); +} + +static void reset_process_time(struct vdec_h264_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[hw->dpb.decoder_index]) + max_process_time[hw->dpb.decoder_index] = process_time; + } +} + +void config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) +{ + /* static int count = 0; */ + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + struct Slice *pSlice = &(p_H264_Dpb->mSlice); + unsigned int colocate_adr_offset; + unsigned int val; + +#define H264_BUFFER_INFO_INDEX PMV3_X /* 0xc24 */ +#define H264_BUFFER_INFO_DATA PMV2_X /* 0xc22 */ +#define H264_CURRENT_POC_IDX_RESET LAST_SLICE_MV_ADDR /* 0xc30 */ +#define H264_CURRENT_POC LAST_MVY /* 0xc32 shared with conceal MV */ + +#define H264_CO_MB_WR_ADDR VLD_C38 /* 0xc38 */ +/* bit 31:30 -- L1[0] picture coding structure, + 00 - top field, 01 - bottom field, + 10 - frame, 11 - mbaff frame + bit 29 - L1[0] top/bot for B field pciture , 0 - top, 1 - bot + bit 28:0 h264_co_mb_mem_rd_addr[31:3] + -- only used for B Picture Direct mode [2:0] will set to 3'b000 +*/ +#define H264_CO_MB_RD_ADDR VLD_C39 /* 0xc39 */ + +/* bit 15 -- flush co_mb_data to DDR -- W-Only + bit 14 -- h264_co_mb_mem_wr_addr write Enable -- W-Only + bit 13 -- h264_co_mb_info_wr_ptr write Enable -- W-Only + bit 9 -- soft_reset -- W-Only + bit 8 -- upgent + bit 7:2 -- h264_co_mb_mem_wr_addr + bit 1:0 -- h264_co_mb_info_wr_ptr +*/ +#define H264_CO_MB_RW_CTL VLD_C3D /* 0xc3d */ + + unsigned long canvas_adr; + unsigned ref_reg_val; + unsigned one_ref_cfg = 0; + int h264_buffer_info_data_write_count; + int i, j; + unsigned colocate_wr_adr; + unsigned colocate_rd_adr; + unsigned char use_direct_8x8; + + WRITE_VREG(H264_CURRENT_POC_IDX_RESET, 0); + WRITE_VREG(H264_CURRENT_POC, pic->frame_poc); + WRITE_VREG(H264_CURRENT_POC, pic->top_poc); + WRITE_VREG(H264_CURRENT_POC, pic->bottom_poc); + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s: pic_num is %d, poc is %d (%d, %d, %d), buf_spec_num %d\n", + __func__, pic->pic_num, pic->poc, pic->frame_poc, + pic->top_poc, pic->bottom_poc, pic->buf_spec_num); + print_pic_info(hw->dpb.decoder_index, "cur", pic, pSlice->slice_type); + + WRITE_VREG(CURR_CANVAS_CTRL, pic->buf_spec_num << 24); + + canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff; + + WRITE_VREG(REC_CANVAS_ADDR, canvas_adr); + WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr); + WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr); + + if (pic->mb_aff_frame_flag) + hw->buffer_spec[pic->buf_spec_num].info0 = 0xf4c0; + else if (pic->structure == TOP_FIELD) + hw->buffer_spec[pic->buf_spec_num].info0 = 0xf400; + else if (pic->structure == BOTTOM_FIELD) + hw->buffer_spec[pic->buf_spec_num].info0 = 0xf440; + else + hw->buffer_spec[pic->buf_spec_num].info0 = 0xf480; + + if (pic->bottom_poc < pic->top_poc) + hw->buffer_spec[pic->buf_spec_num].info0 |= 0x100; + + hw->buffer_spec[pic->buf_spec_num].info1 = pic->top_poc; + hw->buffer_spec[pic->buf_spec_num].info2 = pic->bottom_poc; + WRITE_VREG(H264_BUFFER_INFO_INDEX, 16); + + for (i = 0; i < hw->buffer_spec_num; i++) { + int long_term_flag = + get_long_term_flag_by_buf_spec_num(p_H264_Dpb, i); + if (long_term_flag > 0) { + if (long_term_flag & 0x1) + hw->buffer_spec[i].info0 |= (1 << 4); + else + hw->buffer_spec[i].info0 &= ~(1 << 4); + + if (long_term_flag & 0x2) + hw->buffer_spec[i].info0 |= (1 << 5); + else + hw->buffer_spec[i].info0 &= ~(1 << 5); + } + + if (i == pic->buf_spec_num) + WRITE_VREG(H264_BUFFER_INFO_DATA, + hw->buffer_spec[i].info0 | 0xf); + else + WRITE_VREG(H264_BUFFER_INFO_DATA, + hw->buffer_spec[i].info0); + WRITE_VREG(H264_BUFFER_INFO_DATA, hw->buffer_spec[i].info1); + WRITE_VREG(H264_BUFFER_INFO_DATA, hw->buffer_spec[i].info2); + } + + /* config reference buffer */ + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "list0 size %d\n", pSlice->listXsize[0]); + WRITE_VREG(H264_BUFFER_INFO_INDEX, 0); + ref_reg_val = 0; + j = 0; + h264_buffer_info_data_write_count = 0; + + for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) { + /*ref list 0 */ + struct StorablePicture *ref = pSlice->listX[0][i]; + unsigned cfg; + /* bit[6:5] - frame/field info, + * 01 - top, 10 - bottom, 11 - frame + */ +#ifdef ERROR_CHECK + if (ref == NULL) + return; +#endif + if (ref->structure == TOP_FIELD) + cfg = 0x1; + else if (ref->structure == BOTTOM_FIELD) + cfg = 0x2; + else /* FRAME */ + cfg = 0x3; + one_ref_cfg = (ref->buf_spec_num & 0x1f) | (cfg << 5); + ref_reg_val <<= 8; + ref_reg_val |= one_ref_cfg; + j++; + + if (j == 4) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "H264_BUFFER_INFO_DATA: %x\n", ref_reg_val); + WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); + h264_buffer_info_data_write_count++; + j = 0; + } + print_pic_info(hw->dpb.decoder_index, "list0", + pSlice->listX[0][i], -1); + } + if (j != 0) { + while (j != 4) { + ref_reg_val <<= 8; + ref_reg_val |= one_ref_cfg; + j++; + } + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "H264_BUFFER_INFO_DATA: %x\n", + ref_reg_val); + WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); + h264_buffer_info_data_write_count++; + } + ref_reg_val = (one_ref_cfg << 24) | (one_ref_cfg<<16) | + (one_ref_cfg << 8) | one_ref_cfg; + for (i = h264_buffer_info_data_write_count; i < 8; i++) + WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "list1 size %d\n", pSlice->listXsize[1]); + WRITE_VREG(H264_BUFFER_INFO_INDEX, 8); + ref_reg_val = 0; + j = 0; + + for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) { + /* ref list 0 */ + struct StorablePicture *ref = pSlice->listX[1][i]; + unsigned cfg; + /* bit[6:5] - frame/field info, + * 01 - top, 10 - bottom, 11 - frame + */ +#ifdef ERROR_CHECK + if (ref == NULL) + return; +#endif + if (ref->structure == TOP_FIELD) + cfg = 0x1; + else if (ref->structure == BOTTOM_FIELD) + cfg = 0x2; + else /* FRAME */ + cfg = 0x3; + one_ref_cfg = (ref->buf_spec_num & 0x1f) | (cfg << 5); + ref_reg_val <<= 8; + ref_reg_val |= one_ref_cfg; + j++; + + if (j == 4) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "H264_BUFFER_INFO_DATA: %x\n", + ref_reg_val); + WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); + j = 0; + } + print_pic_info(hw->dpb.decoder_index, "list1", + pSlice->listX[1][i], -1); + } + if (j != 0) { + while (j != 4) { + ref_reg_val <<= 8; + ref_reg_val |= one_ref_cfg; + j++; + } + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "H264_BUFFER_INFO_DATA: %x\n", ref_reg_val); + WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val); + } + + /* configure co-locate buffer */ + while ((READ_VREG(H264_CO_MB_RW_CTL) >> 11) & 0x1) + ; + if ((pSlice->mode_8x8_flags & 0x4) && + (pSlice->mode_8x8_flags & 0x2)) + use_direct_8x8 = 1; + else + use_direct_8x8 = 0; + +#ifndef ONE_COLOCATE_BUF_PER_DECODE_BUF + colocate_adr_offset = + ((pic->structure == FRAME && pic->mb_aff_frame_flag == 0) + ? 1 : 2) * 96; + if (use_direct_8x8) + colocate_adr_offset >>= 2; + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "colocate buf size of each mb 0x%x first_mb_in_slice 0x%x colocate_adr_offset 0x%x\r\n", + colocate_adr_offset, pSlice->first_mb_in_slice, + colocate_adr_offset * pSlice->first_mb_in_slice); + + colocate_adr_offset *= pSlice->first_mb_in_slice; + + if ((pic->colocated_buf_index >= 0) && + (pic->colocated_buf_index < p_H264_Dpb->colocated_buf_count)) { + colocate_wr_adr = p_H264_Dpb->colocated_mv_addr_start + + ((p_H264_Dpb->colocated_buf_size * + pic->colocated_buf_index) + >> (use_direct_8x8 ? 2 : 0)); + if ((colocate_wr_adr + p_H264_Dpb->colocated_buf_size) > + p_H264_Dpb->colocated_mv_addr_end) + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "Error, colocate buf is not enough, index is %d\n", + pic->colocated_buf_index); + val = colocate_wr_adr + colocate_adr_offset; + WRITE_VREG(H264_CO_MB_WR_ADDR, val); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "WRITE_VREG(H264_CO_MB_WR_ADDR) = %x, first_mb_in_slice %x pic_structure %x colocate_adr_offset %x mode_8x8_flags %x colocated_buf_size %x\n", + val, pSlice->first_mb_in_slice, pic->structure, + colocate_adr_offset, pSlice->mode_8x8_flags, + p_H264_Dpb->colocated_buf_size); + } else { + WRITE_VREG(H264_CO_MB_WR_ADDR, 0xffffffff); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "WRITE_VREG(H264_CO_MB_WR_ADDR) = 0xffffffff\n"); + } +#else + colocate_adr_offset = + ((pic->structure == FRAME && pic->mb_aff_frame_flag == 0) ? 1 : 2) * 96; + if (use_direct_8x8) + colocate_adr_offset >>= 2; + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "colocate buf size of each mb 0x%x first_mb_in_slice 0x%x colocate_adr_offset 0x%x\r\n", + colocate_adr_offset, pSlice->first_mb_in_slice, + colocate_adr_offset * pSlice->first_mb_in_slice); + + colocate_adr_offset *= pSlice->first_mb_in_slice; + + colocate_wr_adr = p_H264_Dpb->colocated_mv_addr_start + + ((p_H264_Dpb->colocated_buf_size * pic->buf_spec_num) >> + (use_direct_8x8 ? 2 : 0)); + + if ((colocate_wr_adr + p_H264_Dpb->colocated_buf_size) > + p_H264_Dpb->colocated_mv_addr_end) + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "Error, colocate buf is not enough, pic index is %d\n", + pic->buf_spec_num); + val = colocate_wr_adr + colocate_adr_offset; + WRITE_VREG(H264_CO_MB_WR_ADDR, val); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "WRITE_VREG(H264_CO_MB_WR_ADDR) = %x, first_mb_in_slice %x pic_structure %x colocate_adr_offset %x mode_8x8_flags %x colocated_buf_size %x\n", + val, pSlice->first_mb_in_slice, pic->structure, + colocate_adr_offset, pSlice->mode_8x8_flags, + p_H264_Dpb->colocated_buf_size); +#endif + if (pSlice->listXsize[1] > 0) { + struct StorablePicture *colocate_pic = pSlice->listX[1][0]; + /* H264_CO_MB_RD_ADDR[bit 31:30], + * original picture structure of L1[0], + * 00 - top field, 01 - bottom field, + * 10 - frame, 11 - mbaff frame + */ + int l10_structure; + int cur_colocate_ref_type; + /* H264_CO_MB_RD_ADDR[bit 29], top/bot for B field pciture, + * 0 - top, 1 - bot + */ + unsigned int val; +#ifdef ERROR_CHECK + if (colocate_pic == NULL) + return; +#endif + + if (colocate_pic->mb_aff_frame_flag) + l10_structure = 3; + else { + if (colocate_pic->coded_frame) + l10_structure = 2; + else + l10_structure = (colocate_pic->structure == + BOTTOM_FIELD) ? 1 : 0; + } +#if 0 + /*case0016, p16, + cur_colocate_ref_type should be configured base on current pic*/ + if (pic->structure == FRAME && + pic->mb_aff_frame_flag) + cur_colocate_ref_type = 0; + else if (pic->structure == BOTTOM_FIELD) + cur_colocate_ref_type = 1; + else + cur_colocate_ref_type = 0; +#else + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + " CUR TMP DEBUG : mb_aff_frame_flag : %d, structure : %d coded_frame %d\n", + pic->mb_aff_frame_flag, + pic->structure, + pic->coded_frame); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + " COL TMP DEBUG : mb_aff_frame_flag : %d, structure : %d coded_frame %d\n", + colocate_pic->mb_aff_frame_flag, + colocate_pic->structure, + colocate_pic->coded_frame); + if (pic->structure == FRAME || pic->mb_aff_frame_flag) { + cur_colocate_ref_type = + (abs(pic->poc - colocate_pic->top_poc) + < abs(pic->poc - + colocate_pic->bottom_poc)) ? 0 : 1; + } else + cur_colocate_ref_type = + (colocate_pic->structure + == BOTTOM_FIELD) ? 1 : 0; +#endif + +#ifndef ONE_COLOCATE_BUF_PER_DECODE_BUF + if ((colocate_pic->colocated_buf_index >= 0) && + (colocate_pic->colocated_buf_index < + p_H264_Dpb->colocated_buf_count)) { + colocate_rd_adr = p_H264_Dpb->colocated_mv_addr_start + + ((p_H264_Dpb->colocated_buf_size * + colocate_pic->colocated_buf_index) + >> (use_direct_8x8 ? 2 : 0)); + if ((colocate_rd_adr + p_H264_Dpb->colocated_buf_size) > + p_H264_Dpb->colocated_mv_addr_end) + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_ERROR, + "Error, colocate buf is not enough, index is %d\n", + colocate_pic->colocated_buf_index); + /* bit 31:30 -- L1[0] picture coding structure, + * 00 - top field, 01 - bottom field, + * 10 - frame, 11 - mbaff frame + * bit 29 - L1[0] top/bot for B field pciture, + * 0 - top, 1 - bot + * bit 28:0 h264_co_mb_mem_rd_addr[31:3] + * -- only used for B Picture Direct mode + * [2:0] will set to 3'b000 + */ + /* #define H264_CO_MB_RD_ADDR VLD_C39 0xc39 */ + val = ((colocate_rd_adr+colocate_adr_offset) >> 3) | + (l10_structure << 30) | + (cur_colocate_ref_type << 29); + WRITE_VREG(H264_CO_MB_RD_ADDR, val); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "co idx %d, WRITE_VREG(H264_CO_MB_RD_ADDR) = %x, addr %x L1(0) pic_structure %d mbaff %d\n", + colocate_pic->colocated_buf_index, + val, colocate_rd_adr + colocate_adr_offset, + colocate_pic->structure, + colocate_pic->mb_aff_frame_flag); + } else + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "Error, reference pic has no colocated buf\n"); +#else + colocate_rd_adr = p_H264_Dpb->colocated_mv_addr_start + + ((p_H264_Dpb->colocated_buf_size * + colocate_pic->buf_spec_num) + >> (use_direct_8x8 ? 2 : 0)); + if ((colocate_rd_adr + p_H264_Dpb->colocated_buf_size) > + p_H264_Dpb->colocated_mv_addr_end) + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "Error, colocate buf is not enough, pic index is %d\n", + colocate_pic->buf_spec_num); + /* bit 31:30 -- L1[0] picture coding structure, + * 00 - top field, 01 - bottom field, + * 10 - frame, 11 - mbaff frame + * bit 29 - L1[0] top/bot for B field pciture, + * 0 - top, 1 - bot + * bit 28:0 h264_co_mb_mem_rd_addr[31:3] + * -- only used for B Picture Direct mode + * [2:0] will set to 3'b000 + */ + /* #define H264_CO_MB_RD_ADDR VLD_C39 0xc39 */ + val = ((colocate_rd_adr+colocate_adr_offset)>>3) | + (l10_structure << 30) | (cur_colocate_ref_type << 29); + WRITE_VREG(H264_CO_MB_RD_ADDR, val); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "WRITE_VREG(H264_CO_MB_RD_ADDR) = %x, L1(0) pic_structure %d mbaff %d\n", + val, colocate_pic->structure, + colocate_pic->mb_aff_frame_flag); +#endif + } +} + +static int vh264_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + struct vdec_s *vdec = op_arg; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + spin_lock_irqsave(&hw->lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&hw->newframe_q); + states->buf_avail_num = kfifo_len(&hw->display_q); + + spin_unlock_irqrestore(&hw->lock, flags); + + return 0; +} + +static struct vframe_s *vh264_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + if (!hw) + return NULL; + + if (kfifo_peek(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vh264_vf_get(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + if (!hw) + return NULL; + + if (kfifo_get(&hw->display_q, &vf)) { + int time = jiffies; + unsigned int frame_interval = + 1000*(time - hw->last_frame_time)/HZ; + if ((h264_debug_flag & OUTPUT_CURRENT_BUF) == 0) { + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s from fs[%d], poc %d buf_spec_num %d vf %p\n", + __func__, vf->index, + p_H264_Dpb->mFrameStore[vf->index].poc, + p_H264_Dpb->mFrameStore[vf->index] + .buf_spec_num, vf); + } + if (hw->last_frame_time > 0) { + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_TIME_STAMP, + "%s duration %d pts %d interval %dms\r\n", + __func__, vf->duration, vf->pts, frame_interval); + if (frame_interval > + max_get_frame_interval[hw->dpb.decoder_index]) + max_get_frame_interval[hw->dpb.decoder_index] + = frame_interval; + } + hw->last_frame_time = time; + return vf; + } + + return NULL; +} + +static void vh264_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vdec_s *vdec = op_arg; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + int buf_spec_num; + + if ((h264_debug_flag & OUTPUT_CURRENT_BUF) == 0) { + buf_spec_num = + get_buf_spec_idx_by_canvas_config(hw, + &vf->canvas0_config[0]); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s to fs[%d], poc %d buf_spec_num %d used %d\n", + __func__, vf->index, + p_H264_Dpb->mFrameStore[vf->index].poc, + buf_spec_num, + hw->buffer_spec[buf_spec_num].used); + + if (hw->buffer_spec[buf_spec_num].used != 3) + set_frame_output_flag(&hw->dpb, vf->index); + } + + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); + +#define ASSIST_MBOX1_IRQ_REG VDEC_ASSIST_MBOX1_IRQ_REG + if (hw->buffer_empty_flag) + WRITE_VREG(ASSIST_MBOX1_IRQ_REG, 0x1); +} + +static int vh264_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, + u32 index) +{ + int force_rate = input_frame_based(hw_to_vdec(hw)) ? + force_rate_framebase : force_rate_streambase; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s (%d,%d) dur %d, vf %p, index %d\n", __func__, + hw->frame_width, hw->frame_height, hw->frame_dur, vf, index); + + vf->width = hw->frame_width; + vf->height = hw->frame_height; + if (force_rate) { + if (force_rate == -1) + vf->duration = 0; + else + vf->duration = 96000/force_rate; + } else + vf->duration = hw->frame_dur; + vf->ratio_control = + (min(hw->h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) << + DISP_RATIO_ASPECT_RATIO_BIT; + vf->orientation = hw->vh264_rotation; + vf->flag = 0; + + vf->canvas0Addr = vf->canvas1Addr = -1; +#ifdef NV21 + vf->plane_num = 2; +#else + vf->plane_num = 3; +#endif + vf->canvas0_config[0] = hw->buffer_spec[index].canvas_config[0]; + vf->canvas0_config[1] = hw->buffer_spec[index].canvas_config[1]; +#ifndef NV21 + vf->canvas0_config[2] = hw->buffer_spec[index].canvas_config[2]; +#endif + vf->canvas1_config[0] = hw->buffer_spec[index].canvas_config[0]; + vf->canvas1_config[1] = hw->buffer_spec[index].canvas_config[1]; +#ifndef NV21 + vf->canvas1_config[2] = hw->buffer_spec[index].canvas_config[2]; +#endif + + return; +} + +static int get_max_dec_frame_buf_size(int level_idc, + int max_reference_frame_num, int mb_width, + int mb_height) +{ + int pic_size = mb_width * mb_height * 384; + + int size = 0; + + switch (level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + case 52: + default: + size = 70778880; + break; + } + + size /= pic_size; + size = size + 1; /* need one more buffer */ + + if (max_reference_frame_num > size) + size = max_reference_frame_num; + + return size; +} + +static int vh264_set_params(struct vdec_h264_hw_s *hw) +{ + int mb_width, mb_total; + int max_reference_size, level_idc; + int i, mb_height, addr; + int mb_mv_byte; + struct vdec_s *vdec = hw_to_vdec(hw); + int reg_val; + int ret = 0; +#ifdef USE_CMA + unsigned int buf_size; +#endif + + if (hw->set_params_done) { + WRITE_VREG(AV_SCRATCH_0, + (hw->max_reference_size << 24) | + (hw->buffer_spec_num << 16) | + (hw->buffer_spec_num << 8)); + return 0; + } + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, "%s\n", + __func__); + +#ifndef USE_CMA + addr = hw->buf_start; +#endif + + /* Read AV_SCRATCH_1 */ + reg_val = READ_VREG(AV_SCRATCH_1); + hw->seq_info = READ_VREG(AV_SCRATCH_2); + hw->num_units_in_tick = READ_VREG(AV_SCRATCH_4); + hw->time_scale = READ_VREG(AV_SCRATCH_5); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, "get %x\n", + reg_val); + mb_mv_byte = (reg_val & 0x80000000) ? 24 : 96; + + mb_width = reg_val & 0xff; + mb_total = (reg_val >> 8) & 0xffff; + if (!mb_width && mb_total) /*for 4k2k*/ + mb_width = 256; + + mb_height = mb_total/mb_width; +#if 1 + /* if (hw->frame_width == 0 || hw->frame_height == 0) { */ + hw->frame_width = mb_width * 16; + hw->frame_height = mb_height * 16; + /* } */ + + if (hw->frame_dur == 0) + hw->frame_dur = 96000 / 30; +#endif + + mb_width = (mb_width+3) & 0xfffffffc; + mb_height = (mb_height+3) & 0xfffffffc; + mb_total = mb_width * mb_height; + + reg_val = READ_VREG(AV_SCRATCH_B); + level_idc = reg_val & 0xff; + max_reference_size = (reg_val >> 8) & 0xff; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "mb height/widht/total: %x/%x/%x level_idc %x max_ref_num %x\n", + mb_height, mb_width, mb_total, level_idc, max_reference_size); + + + hw->mb_total = mb_total; + hw->mb_width = mb_width; + hw->mb_height = mb_height; + + hw->dpb.reorder_pic_num = + get_max_dec_frame_buf_size(level_idc, + max_reference_size, mb_width, mb_height); + hw->buffer_spec_num = + hw->dpb.reorder_pic_num + + reorder_dpb_size_margin; + hw->max_reference_size = max_reference_size + reference_buf_margin; + + if (hw->buffer_spec_num > MAX_VF_BUF_NUM) { + hw->buffer_spec_num = MAX_VF_BUF_NUM; + hw->dpb.reorder_pic_num = hw->buffer_spec_num + - reorder_dpb_size_margin; + } + hw->dpb.mDPB.size = hw->buffer_spec_num; + hw->dpb.max_reference_size = hw->max_reference_size; + + pr_info("%s buf_spec_num %d reorder_pic_num %d collocate_buf_num %d\r\n", + __func__, hw->buffer_spec_num, + hw->dpb.reorder_pic_num, + hw->max_reference_size); + +#ifdef USE_CMA + buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); +#endif + for (i = 0; i < hw->buffer_spec_num; i++) { + int canvas = vdec->get_canvas(i, 2); + +#ifdef USE_CMA + if (hw->buffer_spec[i].cma_alloc_count == 0) { + hw->buffer_spec[i].cma_alloc_count = + PAGE_ALIGN(buf_size) / PAGE_SIZE; + hw->buffer_spec[i].cma_alloc_addr = + codec_mm_alloc_for_dma(MEM_NAME, + hw->buffer_spec[i].cma_alloc_count, + 16, CODEC_MM_FLAGS_FOR_VDECODER); + } + + if (!hw->buffer_spec[i].cma_alloc_addr) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "CMA alloc failed, request buf size 0x%lx\n", + hw->buffer_spec[i].cma_alloc_count * PAGE_SIZE); + hw->buffer_spec[i].cma_alloc_count = 0; + ret = -1; + break; + } + hw->buffer_spec[i].buf_adr = + hw->buffer_spec[i].cma_alloc_addr; + addr = hw->buffer_spec[i].buf_adr; +#else + hw->buffer_spec[i].buf_adr = addr; +#endif + + hw->buffer_spec[i].used = 0; + hw->buffer_spec[i].y_addr = addr; + addr += hw->mb_total << 8; + + hw->buffer_spec[i].u_addr = addr; + hw->buffer_spec[i].v_addr = addr; + addr += hw->mb_total << 7; + + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + + canvas_config(hw->buffer_spec[i].y_canvas_index, + hw->buffer_spec[i].y_addr, + hw->mb_width << 4, + hw->mb_height << 4, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + + hw->buffer_spec[i].canvas_config[0].phy_addr = + hw->buffer_spec[i].y_addr; + hw->buffer_spec[i].canvas_config[0].width = + hw->mb_width << 4; + hw->buffer_spec[i].canvas_config[0].height = + hw->mb_height << 4; + hw->buffer_spec[i].canvas_config[0].block_mode = + CANVAS_BLKMODE_32X32; + + canvas_config(hw->buffer_spec[i].u_canvas_index, + hw->buffer_spec[i].u_addr, + hw->mb_width << 4, + hw->mb_height << 3, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + + hw->buffer_spec[i].canvas_config[1].phy_addr = + hw->buffer_spec[i].u_addr; + hw->buffer_spec[i].canvas_config[1].width = + hw->mb_width << 4; + hw->buffer_spec[i].canvas_config[1].height = + hw->mb_height << 3; + hw->buffer_spec[i].canvas_config[1].block_mode = + CANVAS_BLKMODE_32X32; + + WRITE_VREG(ANC0_CANVAS_ADDR + i, + spec2canvas(&hw->buffer_spec[i])); + + pr_info("config canvas (%d)\r\n", i); + } + + +#ifdef USE_CMA + if (hw->collocate_cma_alloc_count == 0) { + hw->collocate_cma_alloc_count = + PAGE_ALIGN(hw->mb_total * mb_mv_byte * + hw->max_reference_size) / PAGE_SIZE; + hw->collocate_cma_alloc_addr = + codec_mm_alloc_for_dma(MEM_NAME, + hw->collocate_cma_alloc_count, + 16, CODEC_MM_FLAGS_FOR_VDECODER); + } + + if (!hw->collocate_cma_alloc_addr) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "codec_mm alloc failed, request buf size 0x%lx\n", + hw->collocate_cma_alloc_count * PAGE_SIZE); + hw->collocate_cma_alloc_count = 0; + ret = -1; + } else { + hw->dpb.colocated_mv_addr_start = + hw->collocate_cma_alloc_addr; + hw->dpb.colocated_mv_addr_end = + hw->dpb.colocated_mv_addr_start + + (hw->mb_total * mb_mv_byte * hw->max_reference_size); + pr_info("callocate cma %d, %lx, %x\n", + hw->collocate_cma_alloc_count, + hw->collocate_cma_alloc_addr, + hw->dpb.colocated_mv_addr_start); + } +#else + hw->dpb.colocated_mv_addr_start = addr; + hw->dpb.colocated_mv_addr_end = addr + (hw->mb_total * mb_mv_byte + * hw->max_reference_size); +#endif + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "colocated_mv_addr_start %x colocated_mv_addr_end %x\n", + hw->dpb.colocated_mv_addr_start, + hw->dpb.colocated_mv_addr_end); + + hw->timing_info_present_flag = hw->seq_info & 0x2; + hw->fixed_frame_rate_flag = 0; + if (hw->timing_info_present_flag) { + hw->fixed_frame_rate_flag = hw->seq_info & 0x40; + + if (((hw->num_units_in_tick * 120) >= hw->time_scale && + ((!hw->sync_outside) || + (!hw->frame_dur))) + && hw->num_units_in_tick && hw->time_scale) { + if (hw->use_idr_framerate || + hw->fixed_frame_rate_flag || + !hw->frame_dur || + !hw->duration_from_pts_done + /*|| vh264_running*/) { + u32 frame_dur_es = + div_u64(96000ULL * 2 * hw->num_units_in_tick, + hw->time_scale); + if (hw->frame_dur != frame_dur_es) { + hw->h264_first_valid_pts_ready = false; + hw->h264pts1 = 0; + hw->h264pts2 = 0; + hw->h264_pts_count = 0; + hw->duration_from_pts_done = 0; + fixed_frame_rate_mode = + FIX_FRAME_RATE_OFF; + hw->pts_duration = 0; + hw->frame_dur = frame_dur_es; + pr_info("frame_dur %d from timing_info\n", + hw->frame_dur); + } + + /*hack to avoid use ES frame duration when + it's half of the rate from system info + sometimes the encoder is given a wrong + frame rate but the system side infomation + is more reliable + if ((frame_dur * 2) != frame_dur_es) { + frame_dur = frame_dur_es; + }*/ + } + } + } else { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "H.264: timing_info not present\n"); + } + + if (hw->pts_unstable && (hw->fixed_frame_rate_flag == 0)) { + if (((RATE_2397_FPS == hw->frame_dur) + && (dec_control + & DEC_CONTROL_FLAG_FORCE_RATE_2397_FPS_FIX_FRAME_RATE)) + || ((RATE_2997_FPS == + hw->frame_dur) && + (dec_control & + DEC_CONTROL_FLAG_FORCE_RATE_2997_FPS_FIX_FRAME_RATE))) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "force fix frame rate\n"); + hw->fixed_frame_rate_flag = 0x40; + } + } + + hw->set_params_done = 1; + + WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | + (hw->buffer_spec_num<<16) | + (hw->buffer_spec_num<<8)); + + return ret; +} + +static bool is_buffer_available(struct vdec_s *vdec) +{ + bool buffer_available = 1; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private); + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + + if ((kfifo_len(&hw->newframe_q) <= 0) || + ((hw->set_params_done) && (!have_free_buf_spec(vdec))) || + ((p_H264_Dpb->mDPB.init_done) && + (p_H264_Dpb->mDPB.used_size == p_H264_Dpb->mDPB.size) && + (is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) == 0))) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s, empty, newq(%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n", + __func__, + kfifo_len(&hw->newframe_q), + have_free_buf_spec(vdec), + p_H264_Dpb->mDPB.init_done, + p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, + is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) + ); + buffer_available = 0; + + bufmgr_h264_remove_unused_frame(p_H264_Dpb); + } + + return buffer_available; +} + +static irqreturn_t vh264_isr(struct vdec_s *vdec) +{ + unsigned int dec_dpb_status; + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private); + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + int i; + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + if (!hw) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "decoder is not running\n"); + return IRQ_HANDLED; + } + + p_H264_Dpb->vdec = vdec; + dec_dpb_status = READ_VREG(DPB_STATUS_REG); + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s DPB_STATUS_REG: %x, sb (%x %x %x) bitcnt %x\n", + __func__, + dec_dpb_status, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VIFF_BIT_CNT)); + + if (dec_dpb_status == H264_CONFIG_REQUEST) { + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE); +#ifdef USE_CMA + if (hw->set_params_done) { + WRITE_VREG(AV_SCRATCH_0, + (hw->max_reference_size<<24) | + (hw->buffer_spec_num<<16) | + (hw->buffer_spec_num<<8)); + } else { + hw->dec_result = DEC_RESULT_CONFIG_PARAM; + schedule_work(&hw->work); + } +#else + if (vh264_set_params(hw) < 0) { + hw->fatal_error_flag = DECODER_FATAL_ERROR_UNKNOW; + if (!hw->fatal_error_reset) + schedule_work(&hw->error_wd_work); + } +#endif + } else if (dec_dpb_status == H264_SLICE_HEAD_DONE) { + int slice_header_process_status = 0; + unsigned short *p = (unsigned short *)hw->lmem_addr; + + dma_sync_single_for_cpu( + amports_get_dma_device(), + hw->lmem_addr_remap, + PAGE_SIZE, + DMA_FROM_DEVICE); +#if 0 + if (p_H264_Dpb->mVideo.dec_picture == NULL) { + if (!is_buffer_available(vdec)) { + hw->buffer_empty_flag = 1; + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_UCODE_EVT, + "%s, buffer_empty, newframe_q(%d), have_free_buf_spec(%d), init_done(%d), used_size(%d/%d), is_there_unused_frame_from_dpb(%d)\n", + __func__, + kfifo_len(&hw->newframe_q), + have_free_buf_spec(vdec), + p_H264_Dpb->mDPB.init_done, + p_H264_Dpb->mDPB.used_size, + p_H264_Dpb->mDPB.size, + is_there_unused_frame_from_dpb( + &p_H264_Dpb->mDPB)); + return IRQ_HANDLED; + } + } + + hw->buffer_empty_flag = 0; +#endif +#ifdef SEND_PARAM_WITH_REG + for (i = 0; i < (RPM_END-RPM_BEGIN); i++) { + unsigned int data32; + do { + data32 = READ_VREG(RPM_CMD_REG); + /* printk("%x\n", data32); */ + } while ((data32&0x10000) == 0); + p_H264_Dpb->dpb_param.l.data[i] = data32 & 0xffff; + WRITE_VREG(RPM_CMD_REG, 0); + /* printk("%x:%x\n", i,data32); */ + } +#else + for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) { + int ii; + for (ii = 0; ii < 4; ii++) { + p_H264_Dpb->dpb_param.l.data[i+ii] = + p[i+3-ii]; + } + } +#endif + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "current dpb index %d, poc %d, top/bot poc (%d,%d)\n", + p_H264_Dpb->dpb_param.dpb.current_dpb_index, + val(p_H264_Dpb->dpb_param.dpb.frame_pic_order_cnt), + val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt), + val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt)); + + slice_header_process_status = + h264_slice_header_process(p_H264_Dpb); + + if (p_H264_Dpb->mVideo.dec_picture) { + if (slice_header_process_status == 1) { + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_UCODE_EVT, + "==================> frame count %d\n", + hw->decode_pic_count+1); + } + config_decode_buf(hw, p_H264_Dpb->mVideo.dec_picture); + } + if (slice_header_process_status == 1) + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_NEWPIC); + else + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_SLICE); + hw->last_mby_mbx = 0; + hw->last_ucode_watchdog_reg_val = 0; + hw->decode_timeout_count = 2; + } else if (dec_dpb_status == H264_PIC_DATA_DONE) { + if (p_H264_Dpb->mVideo.dec_picture) { + if (hw->chunk) { + p_H264_Dpb->mVideo.dec_picture->pts = + hw->chunk->pts; + p_H264_Dpb->mVideo.dec_picture->pts64 = + hw->chunk->pts64; + } else { + struct StorablePicture *pic = + p_H264_Dpb->mVideo.dec_picture; + u32 offset = pic->offset_delimiter_lo | + (pic->offset_delimiter_hi << 16); + if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, + offset, &pic->pts, 0, &pic->pts64)) { + pic->pts = 0; + pic->pts64 = 0; + } + } + store_picture_in_dpb(p_H264_Dpb, + p_H264_Dpb->mVideo.dec_picture); + + bufmgr_post(p_H264_Dpb); + + p_H264_Dpb->mVideo.dec_picture = NULL; + /* dump_dpb(&p_H264_Dpb->mDPB); */ + } + + if ((h264_debug_flag&ONLY_RESET_AT_START) == 0) + amvdec_stop(); + hw->decode_pic_count++, + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s H264_PIC_DATA_DONE decode slice count %d\n", + __func__, + hw->decode_pic_count); + /* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); */ + hw->dec_result = DEC_RESULT_DONE; + reset_process_time(hw); + schedule_work(&hw->work); + } else if (/*(dec_dpb_status == H264_DATA_REQUEST) ||*/ + (dec_dpb_status == H264_SEARCH_BUFEMPTY) || + (dec_dpb_status == H264_DECODE_BUFEMPTY) || + (dec_dpb_status == H264_DECODE_TIMEOUT)) { +empty_proc: + if (p_H264_Dpb->mVideo.dec_picture) { + remove_picture(p_H264_Dpb, + p_H264_Dpb->mVideo.dec_picture); + p_H264_Dpb->mVideo.dec_picture = NULL; + } + + if (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x200)) { + if (h264_debug_flag & + DISABLE_ERROR_HANDLE) { + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_ERROR, + "%s decoding error, level 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + goto send_again; + } + if ((h264_debug_flag & ONLY_RESET_AT_START) == 0) + amvdec_stop(); + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_UCODE_EVT, + "%s %s\n", __func__, + (dec_dpb_status == H264_SEARCH_BUFEMPTY) ? + "H264_SEARCH_BUFEMPTY" : + (dec_dpb_status == H264_DECODE_BUFEMPTY) ? + "H264_DECODE_BUFEMPTY" : "H264_DECODE_TIMEOUT"); + hw->dec_result = DEC_RESULT_DONE; + + if (dec_dpb_status == H264_SEARCH_BUFEMPTY) + hw->search_dataempty_num++; + else if (dec_dpb_status == H264_DECODE_TIMEOUT) + hw->decode_timeout_num++; + else if (dec_dpb_status == H264_DECODE_BUFEMPTY) + hw->decode_dataempty_num++; + + + reset_process_time(hw); + schedule_work(&hw->work); + } else { + /* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_INIT); */ + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s DEC_RESULT_AGAIN\n", __func__); +send_again: + hw->dec_result = DEC_RESULT_AGAIN; + schedule_work(&hw->work); + } + } else if (dec_dpb_status == H264_DATA_REQUEST) { + if (input_frame_based(vdec)) { + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_VDEC_STATUS, + "%s H264_DATA_REQUEST\n", __func__); + hw->dec_result = DEC_RESULT_GET_DATA; + schedule_work(&hw->work); + } else + goto empty_proc; + } + + /* ucode debug */ + if (READ_VREG(DEBUG_REG1) & 0x10000) { + int i; + unsigned short *p = (unsigned short *)hw->lmem_addr; + + dma_sync_single_for_cpu( + amports_get_dma_device(), + hw->lmem_addr_remap, + PAGE_SIZE, + DMA_FROM_DEVICE); + + pr_info("LMEM:\n", READ_VREG(DEBUG_REG1)); + for (i = 0; i < 0x400; i += 4) { + int ii; + if ((i & 0xf) == 0) + pr_info("%03x: ", i); + for (ii = 0; ii < 4; ii++) + pr_info("%04x ", p[i+3-ii]); + if (((i+ii) & 0xf) == 0) + pr_info("\n"); + } + WRITE_VREG(DEBUG_REG1, 0); + } else if (READ_VREG(DEBUG_REG1) != 0) { + pr_info("dbg%x: %x\n", READ_VREG(DEBUG_REG1), + READ_VREG(DEBUG_REG2)); + WRITE_VREG(DEBUG_REG1, 0); + } + /**/ + + return IRQ_HANDLED; +} + +static void timeout_process(struct vdec_h264_hw_s *hw) +{ + hw->timeout_num++; + if ((h264_debug_flag & ONLY_RESET_AT_START) == 0) + amvdec_stop(); + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_ERROR, "%s decoder timeout\n", __func__); + hw->dec_result = DEC_RESULT_DONE; + reset_process_time(hw); + schedule_work(&hw->work); +} + +static void check_timer_func(unsigned long arg) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)arg; + + if ((h264_debug_cmd & 0x100) != 0 && + hw_to_vdec(hw)->id == (h264_debug_cmd & 0xff)) { + hw->dec_result = DEC_RESULT_DONE; + schedule_work(&hw->work); + pr_info("vdec %d is forced to be disconnected\n", + h264_debug_cmd & 0xff); + h264_debug_cmd = 0; + return; + } + + if (hw_to_vdec(hw)->next_status == VDEC_STATUS_DISCONNECTED) { + hw->dec_result = DEC_RESULT_DONE; + schedule_work(&hw->work); + pr_info("vdec requested to be disconnected\n"); + return; + } + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + + if ((input_frame_based(hw_to_vdec(hw)) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x200)) && + ((h264_debug_flag & DISABLE_ERROR_HANDLE) == 0) && + (decode_timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > decode_timeout_val) + ) { + u32 dpb_status = READ_VREG(DPB_STATUS_REG); + u32 mby_mbx = READ_VREG(MBY_MBX); + if ((dpb_status == H264_ACTION_DECODE_NEWPIC) || + (dpb_status == H264_ACTION_DECODE_SLICE)) { + if (hw->last_mby_mbx == mby_mbx) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + } else if (is_in_parsing_state(dpb_status)) { + if (hw->last_ucode_watchdog_reg_val == + READ_VREG(UCODE_WATCHDOG_REG)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + } + hw->last_ucode_watchdog_reg_val = + READ_VREG(UCODE_WATCHDOG_REG); + hw->last_mby_mbx = mby_mbx; + } + + hw->check_timer.expires = jiffies + CHECK_INTERVAL; + + add_timer(&hw->check_timer); +} + +static int dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + vstatus->width = hw->frame_width; + vstatus->height = hw->frame_height; + if (hw->frame_dur != 0) + vstatus->fps = 96000 / hw->frame_dur; + else + vstatus->fps = -1; + vstatus->error_count = READ_VREG(AV_SCRATCH_D); + vstatus->status = hw->stat; + /* if (fatal_error_reset) + vstatus->status |= hw->fatal_error_flag; */ + return 0; +} + +static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) +{ + int i; + + /* if (hw->init_flag == 0) { */ + if (h264_debug_flag & 0x40000000) { + /* if (1) */ + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s, reset register\n", __func__); + + while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) + ; + while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) + ; /* reg address is 0x350 */ + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1<<9) | (1<<8)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + +#else + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + READ_MPEG_REG(RESET0_REGISTER); + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); +#endif + WRITE_VREG(POWER_CTL_VLD, + READ_VREG(POWER_CTL_VLD) | (0 << 10) | + (1 << 9) | (1 << 6)); + } else { + /* WRITE_VREG(POWER_CTL_VLD, + READ_VREG(POWER_CTL_VLD) | (0 << 10) | (1 << 9) ); */ + WRITE_VREG(POWER_CTL_VLD, + READ_VREG(POWER_CTL_VLD) | + (0 << 10) | (1 << 9) | (1 << 6)); + } + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); +#endif + +#if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + /* pr_info("vh264 meson8 prot init\n"); */ + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); +#endif + if (hw->decode_pic_count > 0) { + WRITE_VREG(AV_SCRATCH_7, (hw->max_reference_size << 24) | + (hw->buffer_spec_num << 16) | + (hw->buffer_spec_num << 8)); + for (i = 0; i < hw->buffer_spec_num; i++) { + canvas_config(hw->buffer_spec[i].y_canvas_index, + hw->buffer_spec[i].y_addr, + hw->mb_width << 4, + hw->mb_height << 4, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + + canvas_config(hw->buffer_spec[i].u_canvas_index, + hw->buffer_spec[i].u_addr, + hw->mb_width << 4, + hw->mb_height << 3, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + + WRITE_VREG(ANC0_CANVAS_ADDR + i, + spec2canvas(&hw->buffer_spec[i])); + } + } else { + WRITE_VREG(AV_SCRATCH_0, 0); + WRITE_VREG(AV_SCRATCH_9, 0); + } + + if (hw->init_flag == 0) + WRITE_VREG(DPB_STATUS_REG, 0); + else + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_START); + + WRITE_VREG(FRAME_COUNTER_REG, hw->decode_pic_count); + WRITE_VREG(AV_SCRATCH_8, hw->buf_offset); + WRITE_VREG(AV_SCRATCH_G, hw->mc_dma_handle); + + /* hw->error_recovery_mode = (error_recovery_mode != 0) ? + error_recovery_mode : error_recovery_mode_in; */ + /* WRITE_VREG(AV_SCRATCH_F, + (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) ); */ + WRITE_VREG(AV_SCRATCH_F, (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) | + ((error_recovery_mode_in & 0x1) << 4)); + if (hw->ucode_type == UCODE_IP_ONLY_PARAM) + SET_VREG_MASK(AV_SCRATCH_F, 1 << 6); + else + CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6); + + WRITE_VREG(LMEM_DUMP_ADR, (u32)hw->lmem_addr_remap); +#if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); +#endif + + WRITE_VREG(DEBUG_REG1, 0); + WRITE_VREG(DEBUG_REG2, 0); + return 0; +} + +static unsigned char amvdec_enable_flag; +static void vh264_local_init(struct vdec_h264_hw_s *hw) +{ + int i; + hw->decode_timeout_count = 0; + + hw->vh264_ratio = hw->vh264_amstream_dec_info.ratio; + /* vh264_ratio = 0x100; */ + + hw->vh264_rotation = (((unsigned long) + hw->vh264_amstream_dec_info.param) >> 16) & 0xffff; + + hw->frame_prog = 0; + hw->frame_width = hw->vh264_amstream_dec_info.width; + hw->frame_height = hw->vh264_amstream_dec_info.height; + hw->frame_dur = hw->vh264_amstream_dec_info.rate; + hw->pts_outside = ((unsigned long) + hw->vh264_amstream_dec_info.param) & 0x01; + hw->sync_outside = ((unsigned long) + hw->vh264_amstream_dec_info.param & 0x02) >> 1; + hw->use_idr_framerate = ((unsigned long) + hw->vh264_amstream_dec_info.param & 0x04) >> 2; + hw->max_refer_buf = !(((unsigned long) + hw->vh264_amstream_dec_info.param & 0x10) >> 4); + if (hw->frame_dur < 96000/960) { + /*more than 960fps,it should not be a correct value, + give default 30fps*/ + hw->frame_dur = 96000/30; + } + + pr_info + ("H264 sysinfo: %dx%d duration=%d, pts_outside=%d, ", + hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); + pr_info("sync_outside=%d, use_idr_framerate=%d\n", + hw->sync_outside, hw->use_idr_framerate); + + if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x08) + hw->ucode_type = UCODE_IP_ONLY_PARAM; + else + hw->ucode_type = 0; + + if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x20) + error_recovery_mode_in = 1; + else + error_recovery_mode_in = 3; + + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &hw->vfpool[i]; + hw->vfpool[i].index = -1; /* VF_BUF_NUM; */ + hw->vfpool[i].bufWidth = 1920; + kfifo_put(&hw->newframe_q, vf); + } + + hw->duration_from_pts_done = 0; + + hw->p_last_vf = NULL; + hw->fatal_error_flag = 0; + hw->vh264_stream_switching_state = SWITCHING_STATE_OFF; + + INIT_WORK(&hw->work, vh264_work); + + return; +} + +static s32 vh264_init(struct vdec_h264_hw_s *hw) +{ + /* int trickmode_fffb = 0; */ + int firmwareloaded = 0; + + hw->init_flag = 0; + hw->set_params_done = 0; + hw->start_process_time = 0; + + /* pr_info("\nvh264_init\n"); */ + /* init_timer(&hw->recycle_timer); */ + + /* timer init */ + init_timer(&hw->check_timer); + + hw->check_timer.data = (unsigned long)hw; + hw->check_timer.function = check_timer_func; + hw->check_timer.expires = jiffies + CHECK_INTERVAL; + + /* add_timer(&hw->check_timer); */ + hw->stat |= STAT_TIMER_ARM; + + hw->duration_on_correcting = 0; + hw->fixed_frame_rate_check_count = 0; + hw->saved_resolution = 0; + + vh264_local_init(hw); + + if (!amvdec_enable_flag) { + amvdec_enable_flag = true; + amvdec_enable(); + } + + /* -- ucode loading (amrisc and swap code) */ + hw->mc_cpu_addr = + dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, + &hw->mc_dma_handle, GFP_KERNEL); + if (!hw->mc_cpu_addr) { + amvdec_enable_flag = false; + amvdec_disable(); + + pr_info("vh264_init: Can not allocate mc memory.\n"); + return -ENOMEM; + } + + pr_info("264 ucode swap area: phyaddr %p, cpu vaddr %p\n", + (void *)hw->mc_dma_handle, hw->mc_cpu_addr); + if (!firmwareloaded) { + int ret = 0, size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + pr_info("start load orignal firmware ...\n"); + + size = get_firmware_data(VIDEO_DEC_H264_MULTI, buf); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(buf); + return -1; + } + + /*ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf);*/ + + /*header*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_HEADER, + buf + 0x4000, MC_SWAP_SIZE); + /*data*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_DATA, + buf + 0x2000, MC_SWAP_SIZE); + /*mmco*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MMCO, + buf + 0x6000, MC_SWAP_SIZE); + /*list*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_LIST, + buf + 0x3000, MC_SWAP_SIZE); + /*slice*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_SLICE, + buf + 0x5000, MC_SWAP_SIZE); + /*main*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN, + buf, 0x2000); + /*data*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x2000, + buf + 0x2000, 0x1000); + /*slice*/ + memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x3000, + buf + 0x5000, 0x1000); + + vfree(buf); + + if (ret < 0) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "264 load orignal firmware error.\n"); + amvdec_disable(); + if (hw->mc_cpu_addr) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, hw->mc_cpu_addr, + hw->mc_dma_handle); + hw->mc_cpu_addr = NULL; + } + return -EBUSY; + } + } + +#if 1 /* #ifdef BUFFER_MGR_IN_C */ + dpb_init_global(&hw->dpb, + hw_to_vdec(hw)->id, 0, 0); + hw->lmem_addr = __get_free_page(GFP_KERNEL); + if (!hw->lmem_addr) { + pr_info("%s: failed to alloc lmem_addr\n", __func__); + return -ENOMEM; + } else { + hw->lmem_addr_remap = dma_map_single( + amports_get_dma_device(), + (void *)hw->lmem_addr, + PAGE_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + hw->lmem_addr_remap)) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "%s: failed to map lmem_addr\n", __func__); + free_page(hw->lmem_addr); + hw->lmem_addr = 0; + hw->lmem_addr_remap = 0; + return -ENOMEM; + } + + pr_info("%s, vaddr=%lx phy_addr=%p\n", + __func__, hw->lmem_addr, (void *)hw->lmem_addr_remap); + } + /* BUFFER_MGR_IN_C */ +#endif + hw->stat |= STAT_MC_LOAD; + + /* add memory barrier */ + wmb(); + + return 0; +} + +static int vh264_stop(struct vdec_h264_hw_s *hw, int mode) +{ + int i; + + if (hw->stat & STAT_MC_LOAD) { + if (hw->mc_cpu_addr != NULL) { + dma_free_coherent(amports_get_dma_device(), + MC_TOTAL_SIZE, hw->mc_cpu_addr, + hw->mc_dma_handle); + hw->mc_cpu_addr = NULL; + } + } +#ifdef USE_CMA + if (hw->cma_alloc_addr) { + pr_info("codec_mm release buffer 0x%lx\n", hw->cma_alloc_addr); + codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); + hw->cma_alloc_count = 0; + } + + if (hw->collocate_cma_alloc_addr) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "codec_mm release collocate buffer 0x%lx\n", + hw->collocate_cma_alloc_addr); + codec_mm_free_for_dma(MEM_NAME, hw->collocate_cma_alloc_addr); + hw->collocate_cma_alloc_count = 0; + } + + for (i = 0; i < hw->buffer_spec_num; i++) { + if (hw->buffer_spec[i].cma_alloc_addr) { + pr_info("codec_mm release buffer_spec[%d], 0x%lx\n", i, + hw->buffer_spec[i].cma_alloc_addr); + codec_mm_free_for_dma(MEM_NAME, + hw->buffer_spec[i].cma_alloc_addr); + hw->buffer_spec[i].cma_alloc_count = 0; + } + } + +#endif + + if (hw->lmem_addr_remap) { + dma_unmap_single(amports_get_dma_device(), + hw->lmem_addr_remap, + PAGE_SIZE, DMA_FROM_DEVICE); + hw->lmem_addr_remap = 0; + } + if (hw->lmem_addr) { + free_page(hw->lmem_addr); + hw->lmem_addr = 0; + } + cancel_work_sync(&hw->work); + + /* amvdec_disable(); */ + + return 0; +} + +static void vh264_work(struct work_struct *work) +{ + struct vdec_h264_hw_s *hw = container_of(work, + struct vdec_h264_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); + + /* finished decoding one frame or error, + * notify vdec core to switch context + */ + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_DETAIL, + "%s %x %x %x\n", __func__, + READ_VREG(0xc47), READ_VREG(0xc45), READ_VREG(0xc46)); + +#ifdef USE_CMA + if (hw->dec_result == DEC_RESULT_CONFIG_PARAM) { + if (vh264_set_params(hw) < 0) { + hw->fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN; + if (!hw->fatal_error_reset) + schedule_work(&hw->error_wd_work); + } + return; + } else +#endif + if ((hw->dec_result == DEC_RESULT_GET_DATA) || + (hw->dec_result == DEC_RESULT_GET_DATA_RETRY)) { + if (hw->dec_result == DEC_RESULT_GET_DATA) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s DEC_RESULT_GET_DATA %x %x %x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP)); + vdec_vframe_dirty(vdec, hw->chunk); + vdec_clean_input(vdec); + } + + if (is_buffer_available(vdec)) { + int r; + r = vdec_prepare_input(vdec, &hw->chunk); + if (r < 0) { + hw->dec_result = DEC_RESULT_GET_DATA_RETRY; + + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_VDEC_DETAIL, + "ammvdec_vh264: Insufficient data\n"); + + schedule_work(&hw->work); + return; + } + hw->dec_result = DEC_RESULT_NONE; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s: chunk size 0x%x\n", + __func__, hw->chunk->size); + WRITE_VREG(POWER_CTL_VLD, + READ_VREG(POWER_CTL_VLD) | + (0 << 10) | (1 << 9) | (1 << 6)); + WRITE_VREG(H264_DECODE_INFO, (1<<13)); + WRITE_VREG(H264_DECODE_SIZE, hw->chunk->size); + WRITE_VREG(VIFF_BIT_CNT, (hw->chunk->size * 8)); + vdec_enable_input(vdec); + + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); + } else{ + hw->dec_result = DEC_RESULT_GET_DATA_RETRY; + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_DETAIL, + "ammvdec_vh264: Insufficient data\n"); + + schedule_work(&hw->work); + } + return; + } else if (hw->dec_result == DEC_RESULT_DONE) { + /* if (!hw->ctx_valid) + hw->ctx_valid = 1; */ + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s dec_result %d %x %x %x\n", + __func__, + hw->dec_result, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP)); + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + } else { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_DETAIL, + "%s dec_result %d %x %x %x\n", + __func__, + hw->dec_result, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP)); + } + + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + + /* mark itself has all HW resource released and input released */ + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); + + if (hw->vdec_cb) + hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); +} + +static bool run_ready(struct vdec_s *vdec) +{ + if (vdec->master) + return false; + + if ((!input_frame_based(vdec)) && (start_decode_buf_level > 0)) { + u32 rp, wp; + u32 level; + + rp = READ_MPEG_REG(PARSER_VIDEO_RP); + wp = READ_MPEG_REG(PARSER_VIDEO_WP); + + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < start_decode_buf_level) { + struct vdec_h264_hw_s *hw = + (struct vdec_h264_hw_s *)vdec->private; + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_DETAIL, + "%s vififo level low %x(<%x) (lev%x wp%x rp%x)\n", + __func__, level, + start_decode_buf_level, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP)); + return 0; + } + } + + if (h264_debug_flag & 0x20000000) { + /* pr_info("%s, a\n", __func__); */ + return 1; + } else { + return is_buffer_available(vdec); + } +} + +static void run(struct vdec_s *vdec, + void (*callback)(struct vdec_s *, void *), void *arg) +{ + struct vdec_h264_hw_s *hw = + (struct vdec_h264_hw_s *)vdec->private; + int size; + + hw->vdec_cb_arg = arg; + hw->vdec_cb = callback; + + /* hw->chunk = vdec_prepare_input(vdec); */ + size = vdec_prepare_input(vdec, &hw->chunk); + if ((size < 0) || + (input_frame_based(vdec) && hw->chunk == NULL)) { + hw->dec_result = DEC_RESULT_AGAIN; + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_DETAIL, + "ammvdec_vh264: Insufficient data\n"); + + schedule_work(&hw->work); + return; + } + + hw->dec_result = DEC_RESULT_NONE; +#if 0 + if ((!input_frame_based(vdec)) && (start_decode_buf_level > 0)) { + if (READ_VREG(VLD_MEM_VIFIFO_LEVEL) < + start_decode_buf_level) { + dpb_print(hw->dpb.decoder_index, + PRINT_FLAG_VDEC_DETAIL, + "%s: VIFIFO_LEVEL %x is low (<%x)\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + start_decode_buf_level); + + hw->dec_result = DEC_RESULT_AGAIN; + schedule_work(&hw->work); + return; + } + } +#endif + + if (input_frame_based(vdec)) { + u8 *data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s: size 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", + __func__, size, + data[0], data[1], data[2], data[3], + data[4], data[5], data[size - 4], + data[size - 3], data[size - 2], + data[size - 1]); + } else + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_VDEC_STATUS, + "%s: %x %x %x size 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), size); + + hw->start_process_time = jiffies; + + if (((h264_debug_flag & ONLY_RESET_AT_START) == 0) || + (hw->init_flag == 0)) { + if (amvdec_vdec_loadmc_ex(vdec, "vmh264_mc") < 0) { + amvdec_enable_flag = false; + amvdec_disable(); + pr_info("%s: Error amvdec_vdec_loadmc fail\n", + __func__); + return; + } + + if (vh264_hw_ctx_restore(hw) < 0) { + schedule_work(&hw->work); + return; + } + if (input_frame_based(vdec)) { + WRITE_VREG(H264_DECODE_INFO, (1<<13)); + WRITE_VREG(H264_DECODE_SIZE, hw->chunk->size); + WRITE_VREG(VIFF_BIT_CNT, (hw->chunk->size * 8)); + } else { + if (size <= 0) + size = 0x7fffffff; /*error happen*/ + WRITE_VREG(H264_DECODE_INFO, (1<<13)); + WRITE_VREG(H264_DECODE_SIZE, size); + WRITE_VREG(VIFF_BIT_CNT, size * 8); + } + + vdec_enable_input(vdec); + + add_timer(&hw->check_timer); + + amvdec_start(); + + /* if (hw->init_flag) { */ + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); + /* } */ + + hw->init_flag = 1; + } else { + WRITE_VREG(H264_DECODE_INFO, (1 << 13)); + vdec_enable_input(vdec); + + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); + } +} + +static void reset(struct vdec_s *vdec) +{ + pr_info("ammvdec_h264: reset.\n"); + +#if 0 + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + hw->init_flag = 0; + hw->set_params_done = 0; + + vh264_local_init(hw); + + dpb_init_global(&hw->dpb); +#endif +} + +static int ammvdec_h264_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct vdec_h264_hw_s *hw = NULL; + + if (pdata == NULL) { + pr_info("\nammvdec_h264 memory resource undefined.\n"); + return -EFAULT; + } + + hw = (struct vdec_h264_hw_s *)devm_kzalloc(&pdev->dev, + sizeof(struct vdec_h264_hw_s), GFP_KERNEL); + if (hw == NULL) { + pr_info("\nammvdec_h264 device data allocation failed\n"); + return -ENOMEM; + } + + pdata->private = hw; + pdata->dec_status = dec_status; + /* pdata->set_trickmode = set_trickmode; */ + pdata->run_ready = run_ready; + pdata->run = run; + pdata->reset = reset; + pdata->irq_handler = vh264_isr; + + pdata->id = pdev->id; + + if (pdata->use_vfm_path) + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); + else if (vdec_dual(pdata)) { + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + (pdata->master) ? VFM_DEC_DVEL_PROVIDER_NAME : + VFM_DEC_DVBL_PROVIDER_NAME); + } else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + PROVIDER_NAME ".%02x", pdev->id & 0xff); + + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vf_provider_ops, pdata); + + platform_set_drvdata(pdev, pdata); + + hw->platform_dev = pdev; +#ifndef USE_CMA + hw->buf_start = pdata->mem_start; + hw->buf_size = pdata->mem_end - pdata->mem_start + 1; + /* hw->ucode_map_start = pdata->mem_start; */ + if (hw->buf_size < DEFAULT_MEM_SIZE) { + pr_info("\nammvdec_h264 memory size not enough.\n"); + return -ENOMEM; + } +#endif + +#ifdef USE_CMA + hw->cma_dev = pdata->cma_dev; + if (hw->cma_alloc_count == 0) { + hw->cma_alloc_count = PAGE_ALIGN(V_BUF_ADDR_OFFSET) / PAGE_SIZE; + hw->cma_alloc_addr = codec_mm_alloc_for_dma(MEM_NAME, + hw->cma_alloc_count, + 4, CODEC_MM_FLAGS_FOR_VDECODER); + } + if (!hw->cma_alloc_addr) { + dpb_print(hw->dpb.decoder_index, PRINT_FLAG_ERROR, + "codec_mm alloc failed, request buf size 0x%lx\n", + hw->cma_alloc_count * PAGE_SIZE); + hw->cma_alloc_count = 0; + return -ENOMEM; + } + hw->buf_offset = hw->cma_alloc_addr - DEF_BUF_START_ADDR; +#else + hw->buf_offset = pdata->mem_start - DEF_BUF_START_ADDR; + hw->buf_start = V_BUF_ADDR_OFFSET + pdata->mem_start; +#endif + + if (pdata->sys_info) + hw->vh264_amstream_dec_info = *pdata->sys_info; + if (NULL == hw->sei_data_buffer) { + hw->sei_data_buffer = + dma_alloc_coherent(amports_get_dma_device(), + USER_DATA_SIZE, + &hw->sei_data_buffer_phys, GFP_KERNEL); + if (!hw->sei_data_buffer) { + pr_info("%s: Can not allocate sei_data_buffer\n", + __func__); + return -ENOMEM; + } + /* pr_info("buffer 0x%x, phys 0x%x, remap 0x%x\n", + sei_data_buffer, sei_data_buffer_phys, + (u32)sei_data_buffer_remap); */ + } +#ifdef USE_CMA + pr_info("ammvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx\n", + pdata->mem_start, hw->buf_offset, hw->cma_alloc_addr); +#else + pr_info("ammvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx\n", + pdata->mem_start, hw->buf_offset, hw->buf_start); +#endif + + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + + if (vh264_init(hw) < 0) { + pr_info("\nammvdec_h264 init failed.\n"); + return -ENODEV; + } + atomic_set(&hw->vh264_active, 1); + + return 0; +} + +static int ammvdec_h264_remove(struct platform_device *pdev) +{ + struct vdec_h264_hw_s *hw = + (struct vdec_h264_hw_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + + atomic_set(&hw->vh264_active, 0); + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + + vh264_stop(hw, MODE_FULL); + + /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ + + atomic_set(&hw->vh264_active, 0); + + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); + + return 0; +} + +/****************************************/ + +static struct platform_driver ammvdec_h264_driver = { + .probe = ammvdec_h264_probe, + .remove = ammvdec_h264_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t ammvdec_h264_profile = { + .name = "mh264", + .profile = "" +}; + +static int __init ammvdec_h264_driver_init_module(void) +{ + pr_info("ammvdec_h264 module init\n"); + if (platform_driver_register(&ammvdec_h264_driver)) { + pr_info("failed to register ammvdec_h264 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&ammvdec_h264_profile); + return 0; +} + +static void __exit ammvdec_h264_driver_remove_module(void) +{ + pr_info("ammvdec_h264 module remove.\n"); + + platform_driver_unregister(&ammvdec_h264_driver); +} + +/****************************************/ + +module_param(h264_debug_flag, uint, 0664); +MODULE_PARM_DESC(h264_debug_flag, "\n ammvdec_h264 h264_debug_flag\n"); + +module_param(start_decode_buf_level, uint, 0664); +MODULE_PARM_DESC(start_decode_buf_level, + "\n ammvdec_h264 start_decode_buf_level\n"); + +module_param(fixed_frame_rate_mode, uint, 0664); +MODULE_PARM_DESC(fixed_frame_rate_mode, "\namvdec_h264 fixed_frame_rate_mode\n"); + +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n amvdec_h264 decode_timeout_val\n"); + +module_param(reorder_dpb_size_margin, uint, 0664); +MODULE_PARM_DESC(reorder_dpb_size_margin, "\n ammvdec_h264 reorder_dpb_size_margin\n"); + +module_param(reference_buf_margin, uint, 0664); +MODULE_PARM_DESC(reference_buf_margin, "\n ammvdec_h264 reference_buf_margin\n"); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(h264_debug_mask, uint, 0664); +MODULE_PARM_DESC(h264_debug_mask, "\n amvdec_h264 h264_debug_mask\n"); + +module_param(h264_debug_cmd, uint, 0664); +MODULE_PARM_DESC(h264_debug_cmd, "\n amvdec_h264 h264_debug_cmd\n"); + +module_param(force_rate_streambase, int, 0664); +MODULE_PARM_DESC(force_rate_streambase, "\n amvdec_h264 force_rate_streambase\n"); + +module_param(dec_control, int, 0664); +MODULE_PARM_DESC(dec_control, "\n amvdec_h264 dec_control\n"); + +module_param(force_rate_framebase, int, 0664); +MODULE_PARM_DESC(force_rate_framebase, "\n amvdec_h264 force_rate_framebase\n"); + +/* +module_param(trigger_task, uint, 0664); +MODULE_PARM_DESC(trigger_task, "\n amvdec_h264 trigger_task\n"); +*/ +module_param_array(decode_frame_count, uint, &max_decode_instance_num, 0664); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param_array(max_get_frame_interval, uint, + &max_decode_instance_num, 0664); + +module_param_array(step, uint, &max_decode_instance_num, 0664); + +module_init(ammvdec_h264_driver_init_module); +module_exit(ammvdec_h264_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC H264 Video Decoder Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c new file mode 100644 index 000000000000..7e09b7bf06ed --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c @@ -0,0 +1,8969 @@ +/* + * drivers/amlogic/amports/vh265.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/amports/amports_priv.h" +#include +#include "../utils/decoder_mmu_box.h" +#include "../utils/decoder_bmmu_box.h" +#include "../utils/config_parser.h" + +/*#define HEVC_PIC_STRUCT_SUPPORT*/ +#define MULTI_INSTANCE_SUPPORT + + + +#define MMU_COMPRESS_HEADER_SIZE 0x48000 +#define MAX_FRAME_4K_NUM 0x1200 +#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +#define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7 +#define HEVC_CM_HEADER_START_ADDR 0x3628 +#define HEVC_SAO_MMU_VH1_ADDR 0x363b +#define HEVC_SAO_MMU_VH0_ADDR 0x363a +#define HEVC_SAO_MMU_STATUS 0x3639 + + + +#define MEM_NAME "codec_265" +/* #include */ +#include + +#include "../utils/vdec.h" +#include "../utils/amvdec.h" +#include + +#define SUPPORT_10BIT +/* #define ERROR_HANDLE_DEBUG */ +#if 0/*MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ +#undef SUPPORT_4K2K +#else +#define SUPPORT_4K2K +#endif + +#ifndef STAT_KTHREAD +#define STAT_KTHREAD 0x40 +#endif + +#ifdef MULTI_INSTANCE_SUPPORT +#define MAX_DECODE_INSTANCE_NUM 12 +#define MULTI_DRIVER_NAME "ammvdec_h265" +#endif +#define DRIVER_NAME "amvdec_h265" +#define MODULE_NAME "amvdec_h265" + +#define PUT_INTERVAL (HZ/100) +#define ERROR_SYSTEM_RESET_COUNT 200 + +#define PTS_NORMAL 0 +#define PTS_NONE_REF_USE_DURATION 1 + +#define PTS_MODE_SWITCHING_THRESHOLD 3 +#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 + +#define DUR2PTS(x) ((x)*90/96) +#define HEVC_SIZE (4096*2304) + +struct hevc_state_s; +static int hevc_print(struct hevc_state_s *hevc, + int debug_flag, const char *fmt, ...); +static int hevc_print_cont(struct hevc_state_s *hevc, + int debug_flag, const char *fmt, ...); +static int vh265_vf_states(struct vframe_states *states, void *); +static struct vframe_s *vh265_vf_peek(void *); +static struct vframe_s *vh265_vf_get(void *); +static void vh265_vf_put(struct vframe_s *, void *); +static int vh265_event_cb(int type, void *data, void *private_data); + +static int vh265_stop(struct hevc_state_s *hevc); +#ifdef MULTI_INSTANCE_SUPPORT +static int vmh265_stop(struct hevc_state_s *hevc); +static s32 vh265_init(struct vdec_s *vdec); +static bool run_ready(struct vdec_s *vdec); +static void reset_process_time(struct hevc_state_s *hevc); +static void start_process_time(struct hevc_state_s *hevc); +static void timeout_process(struct hevc_state_s *hevc); +#else +static s32 vh265_init(struct hevc_state_s *hevc); +#endif +static void vh265_prot_init(struct hevc_state_s *hevc); +static int vh265_local_init(struct hevc_state_s *hevc); +static void vh265_check_timer_func(unsigned long arg); +static void config_decode_mode(struct hevc_state_s *hevc); + +static const char vh265_dec_id[] = "vh265-dev"; + +#define PROVIDER_NAME "decoder.h265" +#define MULTI_INSTANCE_PROVIDER_NAME "vdec.h265" + +static const struct vframe_operations_s vh265_vf_provider = { + .peek = vh265_vf_peek, + .get = vh265_vf_get, + .put = vh265_vf_put, + .event_cb = vh265_event_cb, + .vf_states = vh265_vf_states, +}; + +static struct vframe_provider_s vh265_vf_prov; + +static u32 bit_depth_luma; +static u32 bit_depth_chroma; +static u32 video_signal_type; + +static unsigned int start_decode_buf_level = 0x8000; + +static unsigned int decode_timeout_val; +#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 + +static const char * const video_format_names[] = { + "component", "PAL", "NTSC", "SECAM", + "MAC", "unspecified", "unspecified", "unspecified" +}; + +static const char * const color_primaries_names[] = { + "unknown", "bt709", "undef", "unknown", + "bt470m", "bt470bg", "smpte170m", "smpte240m", + "film", "bt2020" +}; + +static const char * const transfer_characteristics_names[] = { + "unknown", "bt709", "undef", "unknown", + "bt470m", "bt470bg", "smpte170m", "smpte240m", + "linear", "log100", "log316", "iec61966-2-4", + "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", + "smpte-st-2084", "smpte-st-428" +}; + +static const char * const matrix_coeffs_names[] = { + "GBR", "bt709", "undef", "unknown", + "fcc", "bt470bg", "smpte170m", "smpte240m", + "YCgCo", "bt2020nc", "bt2020c" +}; + +#ifdef SUPPORT_10BIT +#define HEVC_CM_BODY_START_ADDR 0x3626 +#define HEVC_CM_BODY_LENGTH 0x3627 +#define HEVC_CM_HEADER_LENGTH 0x3629 +#define HEVC_CM_HEADER_OFFSET 0x362b +#define HEVC_SAO_CTRL9 0x362d +#define LOSLESS_COMPRESS_MODE +/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ +/* hevc->double_write_mode: + 0, no double write; + 1, 1:1 ratio; + 2, (1/4):(1/4) ratio; + 3, (1/4):(1/4) ratio, with both compressed frame included + 0x10, double write only +*/ +static u32 double_write_mode; + +/*#define DECOMP_HEADR_SURGENT*/ + +static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ +static u32 enable_mem_saving = 1; +static u32 workaround_enable; +static u32 force_w_h; +#endif +static u32 force_fps; +static u32 pts_unstable; +#define H265_DEBUG_BUFMGR 0x01 +#define H265_DEBUG_BUFMGR_MORE 0x02 +#define H265_DEBUG_UCODE 0x04 +#define H265_DEBUG_REG 0x08 +#define H265_DEBUG_MAN_SEARCH_NAL 0x10 +#define H265_DEBUG_MAN_SKIP_NAL 0x20 +#define H265_DEBUG_DISPLAY_CUR_FRAME 0x40 +#define H265_DEBUG_FORCE_CLK 0x80 +#define H265_DEBUG_SEND_PARAM_WITH_REG 0x100 +#define H265_DEBUG_NO_DISPLAY 0x200 +#define H265_DEBUG_DISCARD_NAL 0x400 +#define H265_DEBUG_OUT_PTS 0x800 +#define H265_DEBUG_PRINT_SEI 0x2000 +#define H265_DEBUG_PIC_STRUCT 0x4000 +#define H265_DEBUG_DIS_LOC_ERROR_PROC 0x10000 +#define H265_DEBUG_DIS_SYS_ERROR_PROC 0x20000 +#define H265_DEBUG_DUMP_PIC_LIST 0x40000 +#define H265_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000 +#define H265_DEBUG_HW_RESET 0x100000 +#define H265_DEBUG_ERROR_TRIG 0x400000 +#define H265_DEBUG_NO_EOS_SEARCH_DONE 0x800000 +#define H265_DEBUG_NOT_USE_LAST_DISPBUF 0x1000000 +#define H265_DEBUG_IGNORE_CONFORMANCE_WINDOW 0x2000000 +#define H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP 0x4000000 +#ifdef MULTI_INSTANCE_SUPPORT +#define IGNORE_PARAM_FROM_CONFIG 0x08000000 +#define PRINT_FRAMEBASE_DATA 0x10000000 +#define PRINT_FLAG_VDEC_STATUS 0x20000000 +#define PRINT_FLAG_VDEC_DETAIL 0x40000000 +#endif +#define MAX_BUF_NUM 24 +#define MAX_REF_PIC_NUM 24 +#define MAX_REF_ACTIVE 16 + +#define BMMU_MAX_BUFFERS (MAX_BUF_NUM + 1) +#define BMMU_WORKSPACE_ID (MAX_BUF_NUM) + +const u32 h265_version = 201602101; +static u32 debug_mask = 0xffffffff; +static u32 debug; +static u32 radr; +static u32 rval; +static u32 dbg_cmd; +static u32 dbg_skip_decode_index; +static u32 endian = 0xff0; +#ifdef ERROR_HANDLE_DEBUG +static u32 dbg_nal_skip_flag; + /* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */ +static u32 dbg_nal_skip_count; +#endif +/*for debug*/ +static u32 decode_stop_pos; +static u32 decode_stop_pos_pre; +static u32 decode_pic_begin; +static uint slice_parse_begin; +static u32 step; +#ifdef MIX_STREAM_SUPPORT +#ifdef SUPPORT_4K2K +static u32 buf_alloc_width = 4096; +static u32 buf_alloc_height = 2304; +#else +static u32 buf_alloc_width = 1920; +static u32 buf_alloc_height = 1088; +#endif +static u32 dynamic_buf_num_margin; +#else +static u32 buf_alloc_width; +static u32 buf_alloc_height; +static u32 dynamic_buf_num_margin = 8; +#endif +static u32 max_buf_num = 16; +static u32 buf_alloc_size; +static u32 re_config_pic_flag; +/* +bit[0]: 0, +bit[1]: 0, always release cma buffer when stop +bit[1]: 1, never release cma buffer when stop +bit[0]: 1, when stop, release cma buffer if blackout is 1; +do not release cma buffer is blackout is not 1 + +bit[2]: 0, when start decoding, check current displayed buffer + (only for buffer decoded by h265) if blackout is 0 + 1, do not check current displayed buffer + +bit[3]: 1, if blackout is not 1, do not release current + displayed cma buffer always. +*/ +/* set to 1 for fast play; + set to 8 for other case of "keep last frame" +*/ +static u32 buffer_mode = 1; + +/* buffer_mode_dbg: debug only*/ +static u32 buffer_mode_dbg = 0xffff0000; +/**/ +/* +bit[1:0]PB_skip_mode: 0, start decoding at begin; +1, start decoding after first I; +2, only decode and display none error picture; +3, start decoding and display after IDR,etc +bit[31:16] PB_skip_count_after_decoding (decoding but not display), +only for mode 0 and 1. + */ +static u32 nal_skip_policy = 2; + +/* +bit 0, 1: only display I picture; +bit 1, 1: only decode I picture; +*/ +static u32 i_only_flag; + +/* +use_cma: 1, use both reserver memory and cma for buffers +2, only use cma for buffers +*/ +static u32 use_cma = 2; + +#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf)) +static u32 prefix_aux_buf_size; +static u32 suffix_aux_buf_size; + +static u32 max_decoding_time; +/* +error handling +*/ +/*error_handle_policy: +bit 0: 0, auto skip error_skip_nal_count nals before error recovery; +1, skip error_skip_nal_count nals before error recovery; +bit 1 (valid only when bit0 == 1): +1, wait vps/sps/pps after error recovery; +bit 2 (valid only when bit0 == 0): +0, auto search after error recovery (hevc_recover() called); +1, manual search after error recovery +(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) + +bit 4: 0, set error_mark after reset/recover + 1, do not set error_mark after reset/recover +bit 5: 0, check total lcu for every picture + 1, do not check total lcu + +*/ + +static u32 error_handle_policy; +static u32 error_skip_nal_count = 6; +static u32 error_handle_threshold = 30; +static u32 error_handle_nal_skip_threshold = 10; +static u32 error_handle_system_threshold = 30; +static u32 interlace_enable = 1; + /* + parser_sei_enable: + bit 0, sei; + bit 1, sei_suffix (fill aux buf) + bit 2, fill sei to aux buf (when bit 0 is 1) + bit 8, debug flag + */ +static u32 parser_sei_enable; +#ifdef CONFIG_AM_VDEC_DV +static u32 parser_dolby_vision_enable; +#endif +/* this is only for h265 mmu enable */ + +#ifdef CONFIG_MULTI_DEC +static u32 mmu_enable; +#else +static u32 mmu_enable = 1; +#endif + +#ifdef MULTI_INSTANCE_SUPPORT +static u32 work_buf_size = 48 * 1024 * 1024; +static unsigned int max_decode_instance_num + = MAX_DECODE_INSTANCE_NUM; +static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM]; +static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM]; +static unsigned int max_get_frame_interval[MAX_DECODE_INSTANCE_NUM]; + +#ifdef CONFIG_MULTI_DEC +static unsigned char get_idx(struct hevc_state_s *hevc); +#endif + +#ifdef CONFIG_AM_VDEC_DV +static u32 dv_toggle_prov_name; + +static u32 dv_debug; +#endif +#endif + + +#ifdef CONFIG_MULTI_DEC +#define get_dbg_flag(hevc) ((debug_mask & (1 << hevc->index)) ? debug : 0) +#define get_dbg_flag2(hevc) ((debug_mask & (1 << get_idx(hevc))) ? debug : 0) +#else +#define get_dbg_flag(hevc) debug +#define get_dbg_flag2(hevc) debug +#define get_double_write_mode(hevc) double_write_mode +#define get_buf_alloc_width(hevc) buf_alloc_width +#define get_buf_alloc_height(hevc) buf_alloc_height +#define get_dynamic_buf_num_margin(hevc) dynamic_buf_num_margin +#endif +#define get_buffer_mode(hevc) buffer_mode + + +DEFINE_SPINLOCK(lock); +struct task_struct *h265_task = NULL; +#undef DEBUG_REG +#ifdef DEBUG_REG +void WRITE_VREG_DBG(unsigned adr, unsigned val) +{ + WRITE_VREG(adr, val); +} + +#undef WRITE_VREG +#define WRITE_VREG WRITE_VREG_DBG +#endif + +static DEFINE_MUTEX(vh265_mutex); + + +/************************************************** + +h265 buffer management include + +***************************************************/ +enum NalUnitType { + NAL_UNIT_CODED_SLICE_TRAIL_N = 0, /* 0 */ + NAL_UNIT_CODED_SLICE_TRAIL_R, /* 1 */ + + NAL_UNIT_CODED_SLICE_TSA_N, /* 2 */ + /* Current name in the spec: TSA_R */ + NAL_UNIT_CODED_SLICE_TLA, /* 3 */ + + NAL_UNIT_CODED_SLICE_STSA_N, /* 4 */ + NAL_UNIT_CODED_SLICE_STSA_R, /* 5 */ + + NAL_UNIT_CODED_SLICE_RADL_N, /* 6 */ + /* Current name in the spec: RADL_R */ + NAL_UNIT_CODED_SLICE_DLP, /* 7 */ + + NAL_UNIT_CODED_SLICE_RASL_N, /* 8 */ + /* Current name in the spec: RASL_R */ + NAL_UNIT_CODED_SLICE_TFD, /* 9 */ + + NAL_UNIT_RESERVED_10, + NAL_UNIT_RESERVED_11, + NAL_UNIT_RESERVED_12, + NAL_UNIT_RESERVED_13, + NAL_UNIT_RESERVED_14, + NAL_UNIT_RESERVED_15, + + /* Current name in the spec: BLA_W_LP */ + NAL_UNIT_CODED_SLICE_BLA, /* 16 */ + /* Current name in the spec: BLA_W_DLP */ + NAL_UNIT_CODED_SLICE_BLANT, /* 17 */ + NAL_UNIT_CODED_SLICE_BLA_N_LP, /* 18 */ + /* Current name in the spec: IDR_W_DLP */ + NAL_UNIT_CODED_SLICE_IDR, /* 19 */ + NAL_UNIT_CODED_SLICE_IDR_N_LP, /* 20 */ + NAL_UNIT_CODED_SLICE_CRA, /* 21 */ + NAL_UNIT_RESERVED_22, + NAL_UNIT_RESERVED_23, + + NAL_UNIT_RESERVED_24, + NAL_UNIT_RESERVED_25, + NAL_UNIT_RESERVED_26, + NAL_UNIT_RESERVED_27, + NAL_UNIT_RESERVED_28, + NAL_UNIT_RESERVED_29, + NAL_UNIT_RESERVED_30, + NAL_UNIT_RESERVED_31, + + NAL_UNIT_VPS, /* 32 */ + NAL_UNIT_SPS, /* 33 */ + NAL_UNIT_PPS, /* 34 */ + NAL_UNIT_ACCESS_UNIT_DELIMITER, /* 35 */ + NAL_UNIT_EOS, /* 36 */ + NAL_UNIT_EOB, /* 37 */ + NAL_UNIT_FILLER_DATA, /* 38 */ + NAL_UNIT_SEI, /* 39 Prefix SEI */ + NAL_UNIT_SEI_SUFFIX, /* 40 Suffix SEI */ + NAL_UNIT_RESERVED_41, + NAL_UNIT_RESERVED_42, + NAL_UNIT_RESERVED_43, + NAL_UNIT_RESERVED_44, + NAL_UNIT_RESERVED_45, + NAL_UNIT_RESERVED_46, + NAL_UNIT_RESERVED_47, + NAL_UNIT_UNSPECIFIED_48, + NAL_UNIT_UNSPECIFIED_49, + NAL_UNIT_UNSPECIFIED_50, + NAL_UNIT_UNSPECIFIED_51, + NAL_UNIT_UNSPECIFIED_52, + NAL_UNIT_UNSPECIFIED_53, + NAL_UNIT_UNSPECIFIED_54, + NAL_UNIT_UNSPECIFIED_55, + NAL_UNIT_UNSPECIFIED_56, + NAL_UNIT_UNSPECIFIED_57, + NAL_UNIT_UNSPECIFIED_58, + NAL_UNIT_UNSPECIFIED_59, + NAL_UNIT_UNSPECIFIED_60, + NAL_UNIT_UNSPECIFIED_61, + NAL_UNIT_UNSPECIFIED_62, + NAL_UNIT_UNSPECIFIED_63, + NAL_UNIT_INVALID, +}; + +/* --------------------------------------------------- */ +/* Amrisc Software Interrupt */ +/* --------------------------------------------------- */ +#define AMRISC_STREAM_EMPTY_REQ 0x01 +#define AMRISC_PARSER_REQ 0x02 +#define AMRISC_MAIN_REQ 0x04 + +/* --------------------------------------------------- */ +/* HEVC_DEC_STATUS define */ +/* --------------------------------------------------- */ +#define HEVC_DEC_IDLE 0x0 +#define HEVC_NAL_UNIT_VPS 0x1 +#define HEVC_NAL_UNIT_SPS 0x2 +#define HEVC_NAL_UNIT_PPS 0x3 +#define HEVC_NAL_UNIT_CODED_SLICE_SEGMENT 0x4 +#define HEVC_CODED_SLICE_SEGMENT_DAT 0x5 +#define HEVC_SLICE_DECODING 0x6 +#define HEVC_NAL_UNIT_SEI 0x7 +#define HEVC_SLICE_SEGMENT_DONE 0x8 +#define HEVC_NAL_SEARCH_DONE 0x9 +#define HEVC_DECPIC_DATA_DONE 0xa +#define HEVC_DECPIC_DATA_ERROR 0xb +#define HEVC_SEI_DAT 0xc +#define HEVC_SEI_DAT_DONE 0xd +#define HEVC_NAL_DECODE_DONE 0xe + +#define HEVC_DATA_REQUEST 0x12 + +#define HEVC_DECODE_BUFEMPTY 0x20 +#define HEVC_DECODE_TIMEOUT 0x21 +#define HEVC_SEARCH_BUFEMPTY 0x22 + +#define HEVC_FIND_NEXT_PIC_NAL 0x50 +#define HEVC_FIND_NEXT_DVEL_NAL 0x51 + +#define HEVC_DUMP_LMEM 0x30 + +#define HEVC_4k2k_60HZ_NOT_SUPPORT 0x80 +#define HEVC_DISCARD_NAL 0xf0 +#define HEVC_ACTION_ERROR 0xfe +#define HEVC_ACTION_DONE 0xff + +/* --------------------------------------------------- */ +/* Include "parser_cmd.h" */ +/* --------------------------------------------------- */ +#define PARSER_CMD_SKIP_CFG_0 0x0000090b + +#define PARSER_CMD_SKIP_CFG_1 0x1b14140f + +#define PARSER_CMD_SKIP_CFG_2 0x001b1910 + +#define PARSER_CMD_NUMBER 37 + +static unsigned short parser_cmd[PARSER_CMD_NUMBER] = { + 0x0401, + 0x8401, + 0x0800, + 0x0402, + 0x9002, + 0x1423, + 0x8CC3, + 0x1423, + 0x8804, + 0x9825, + 0x0800, + 0x04FE, + 0x8406, + 0x8411, + 0x1800, + 0x8408, + 0x8409, + 0x8C2A, + 0x9C2B, + 0x1C00, + 0x840F, + 0x8407, + 0x8000, + 0x8408, + 0x2000, + 0xA800, + 0x8410, + 0x04DE, + 0x840C, + 0x840D, + 0xAC00, + 0xA000, + 0x08C0, + 0x08E0, + 0xA40E, + 0xFC00, + 0x7C00 +}; + +/************************************************** + +h265 buffer management + +***************************************************/ +/* #define BUFFER_MGR_ONLY */ +/* #define CONFIG_HEVC_CLK_FORCED_ON */ +/* #define ENABLE_SWAP_TEST */ +#define MCRCC_ENABLE +#define INVALID_POC 0x80000000 + +#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 +#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 +#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 +#define HEVC_VPS_BUFFER HEVC_ASSIST_SCRATCH_3 +#define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 +#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 +#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 +#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 +#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 +#define HEVC_sao_mem_unit HEVC_ASSIST_SCRATCH_9 +#define HEVC_SAO_ABV HEVC_ASSIST_SCRATCH_A +#define HEVC_sao_vb_size HEVC_ASSIST_SCRATCH_B +#define HEVC_SAO_VB HEVC_ASSIST_SCRATCH_C +#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D +#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E +#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F +#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_F +#ifdef ENABLE_SWAP_TEST +#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L +#endif + +/*#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M*/ +/*#define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N*/ +#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N + /*do not define ENABLE_SWAP_TEST*/ +#define HEVC_AUX_ADR HEVC_ASSIST_SCRATCH_L +#define HEVC_AUX_DATA_SIZE HEVC_ASSIST_SCRATCH_M + +#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G +#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H +/* +ucode parser/search control +bit 0: 0, header auto parse; 1, header manual parse +bit 1: 0, auto skip for noneseamless stream; 1, no skip +bit [3:2]: valid when bit1==0; +0, auto skip nal before first vps/sps/pps/idr; +1, auto skip nal before first vps/sps/pps +2, auto skip nal before first vps/sps/pps, + and not decode until the first I slice (with slice address of 0) + +3, auto skip before first I slice (nal_type >=16 && nal_type<=21) +bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) ) +bit [16]: for NAL_UNIT_EOS when bit0 is 0: + 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm +bit [17]: for NAL_SEI when bit0 is 0: + 0, do not parse/fetch SEI in ucode; + 1, parse/fetch SEI in ucode +bit [18]: for NAL_SEI_SUFFIX when bit0 is 0: + 0, do not fetch NAL_SEI_SUFFIX to aux buf; + 1, fetch NAL_SEL_SUFFIX data to aux buf +bit [19]: + 0, parse NAL_SEI in ucode + 1, fetch NAL_SEI to aux buf +bit [20]: for DOLBY_VISION_META + 0, do not fetch DOLBY_VISION_META to aux buf + 1, fetch DOLBY_VISION_META to aux buf +*/ +#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I + /*read only*/ +#define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J + /*set before start decoder*/ +#define HEVC_DECODE_MODE HEVC_ASSIST_SCRATCH_J +#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K + +#define DECODE_MODE_SINGLE 0x0 +#define DECODE_MODE_MULTI_FRAMEBASE 0x1 +#define DECODE_MODE_MULTI_STREAMBASE 0x2 +#define DECODE_MODE_MULTI_DVBAL 0x3 +#define DECODE_MODE_MULTI_DVENL 0x4 + +#define MAX_INT 0x7FFFFFFF + +#define RPM_BEGIN 0x100 +#define modification_list_cur 0x140 +#define RPM_END 0x180 + +#define RPS_USED_BIT 14 +/* MISC_FLAG0 */ +#define PCM_LOOP_FILTER_DISABLED_FLAG_BIT 0 +#define PCM_ENABLE_FLAG_BIT 1 +#define LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT 2 +#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 3 +#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT 4 +#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 5 +#define DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT 6 +#define SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 7 +#define SLICE_SAO_LUMA_FLAG_BIT 8 +#define SLICE_SAO_CHROMA_FLAG_BIT 9 +#define SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 10 + +union param_u { + struct { + unsigned short data[RPM_END - RPM_BEGIN]; + } l; + struct { + /* from ucode lmem, do not change this struct */ + unsigned short CUR_RPS[0x10]; + unsigned short num_ref_idx_l0_active; + unsigned short num_ref_idx_l1_active; + unsigned short slice_type; + unsigned short slice_temporal_mvp_enable_flag; + unsigned short dependent_slice_segment_flag; + unsigned short slice_segment_address; + unsigned short num_title_rows_minus1; + unsigned short pic_width_in_luma_samples; + unsigned short pic_height_in_luma_samples; + unsigned short log2_min_coding_block_size_minus3; + unsigned short log2_diff_max_min_coding_block_size; + unsigned short log2_max_pic_order_cnt_lsb_minus4; + unsigned short POClsb; + unsigned short collocated_from_l0_flag; + unsigned short collocated_ref_idx; + unsigned short log2_parallel_merge_level; + unsigned short five_minus_max_num_merge_cand; + unsigned short sps_num_reorder_pics_0; + unsigned short modification_flag; + unsigned short tiles_enabled_flag; + unsigned short num_tile_columns_minus1; + unsigned short num_tile_rows_minus1; + unsigned short tile_width[4]; + unsigned short tile_height[4]; + unsigned short misc_flag0; + unsigned short pps_beta_offset_div2; + unsigned short pps_tc_offset_div2; + unsigned short slice_beta_offset_div2; + unsigned short slice_tc_offset_div2; + unsigned short pps_cb_qp_offset; + unsigned short pps_cr_qp_offset; + unsigned short first_slice_segment_in_pic_flag; + unsigned short m_temporalId; + unsigned short m_nalUnitType; + + unsigned short vui_num_units_in_tick_hi; + unsigned short vui_num_units_in_tick_lo; + unsigned short vui_time_scale_hi; + unsigned short vui_time_scale_lo; + unsigned short bit_depth; + unsigned short profile_etc; + unsigned short sei_frame_field_info; + unsigned short video_signal_type; + unsigned short modification_list[0x20]; + unsigned short conformance_window_flag; + unsigned short conf_win_left_offset; + unsigned short conf_win_right_offset; + unsigned short conf_win_top_offset; + unsigned short conf_win_bottom_offset; + unsigned short chroma_format_idc; + unsigned short color_description; + } p; +}; + +#define RPM_BUF_SIZE (0x80*2) +/* non mmu mode lmem size : 0x400, mmu mode : 0x500*/ +#define LMEM_BUF_SIZE (0x500 * 2) + +struct buff_s { + u32 buf_start; + u32 buf_size; + u32 buf_end; +}; + +struct BuffInfo_s { + u32 max_width; + u32 max_height; + unsigned int start_adr; + unsigned int end_adr; + struct buff_s ipp; + struct buff_s sao_abv; + struct buff_s sao_vb; + struct buff_s short_term_rps; + struct buff_s vps; + struct buff_s sps; + struct buff_s pps; + struct buff_s sao_up; + struct buff_s swap_buf; + struct buff_s swap_buf2; + struct buff_s scalelut; + struct buff_s dblk_para; + struct buff_s dblk_data; + struct buff_s mmu_vbh; + struct buff_s cm_header; + struct buff_s mpred_above; + struct buff_s mpred_mv; + struct buff_s rpm; + struct buff_s lmem; +}; +#define WORK_BUF_SPEC_NUM 2 +static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { + { + /* 8M bytes */ + .max_width = 1920, + .max_height = 1088, + .ipp = { + /* IPP work space calculation : + 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ + .buf_size = 0x4000, + }, + .sao_abv = { + .buf_size = 0x30000, + }, + .sao_vb = { + .buf_size = 0x30000, + }, + .short_term_rps = { + /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, + total 64x16x2 = 2048 bytes (0x800) */ + .buf_size = 0x800, + }, + .vps = { + /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .sps = { + /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .pps = { + /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, + total 0x2000 bytes */ + .buf_size = 0x2000, + }, + .sao_up = { + /* SAO UP STORE AREA - Max 640(10240/16) LCU, + each has 16 bytes total 0x2800 bytes */ + .buf_size = 0x2800, + }, + .swap_buf = { + /* 256cyclex64bit = 2K bytes 0x800 + (only 144 cycles valid) */ + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + /* support up to 32 SCALELUT 1024x32 = + 32Kbytes (0x8000) */ + .buf_size = 0x8000, + }, + .dblk_para = { +#ifdef SUPPORT_10BIT + .buf_size = 0x40000, +#else + /* DBLK -> Max 256(4096/16) LCU, each para + 512bytes(total:0x20000), data 1024bytes(total:0x40000) */ + .buf_size = 0x20000, +#endif + }, + .dblk_data = { + .buf_size = 0x40000, + }, + .mmu_vbh = { + .buf_size = 0x5000, /*2*16*2304/4, 4K*/ + }, + .cm_header = {/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ + .buf_size = MMU_COMPRESS_HEADER_SIZE*(16+1), + }, + .mpred_above = { + .buf_size = 0x8000, + }, + .mpred_mv = {/* 1080p, 0x40000 per buffer */ + .buf_size = 0x40000 * MAX_REF_PIC_NUM, + }, + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x500 * 2, + } + }, + { + .max_width = 4096, + .max_height = 2048, + .ipp = { + /* IPP work space calculation : + 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ + .buf_size = 0x4000, + }, + .sao_abv = { + .buf_size = 0x30000, + }, + .sao_vb = { + .buf_size = 0x30000, + }, + .short_term_rps = { + /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, + total 64x16x2 = 2048 bytes (0x800) */ + .buf_size = 0x800, + }, + .vps = { + /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .sps = { + /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .pps = { + /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, + total 0x2000 bytes */ + .buf_size = 0x2000, + }, + .sao_up = { + /* SAO UP STORE AREA - Max 640(10240/16) LCU, + each has 16 bytes total 0x2800 bytes */ + .buf_size = 0x2800, + }, + .swap_buf = { + /* 256cyclex64bit = 2K bytes 0x800 + (only 144 cycles valid) */ + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + /* support up to 32 SCALELUT 1024x32 = 32Kbytes + (0x8000) */ + .buf_size = 0x8000, + }, + .dblk_para = { + /* DBLK -> Max 256(4096/16) LCU, each para + 512bytes(total:0x20000), + data 1024bytes(total:0x40000) */ + .buf_size = 0x20000, + }, + .dblk_data = { + .buf_size = 0x40000, + }, + .mmu_vbh = { + .buf_size = 0x5000, /*2*16*2304/4, 4K*/ + }, + .cm_header = {/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ + .buf_size = MMU_COMPRESS_HEADER_SIZE * (16+1), + }, + .mpred_above = { + .buf_size = 0x8000, + }, + .mpred_mv = { + /* .buf_size = 0x100000*16, + //4k2k , 0x100000 per buffer */ + /* 4096x2304 , 0x120000 per buffer */ + .buf_size = 0x120000 * MAX_REF_PIC_NUM, + }, + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x500 * 2, + } + } +}; + +unsigned int get_mmu_mode(void) +{ + return mmu_enable; +} + +#ifdef SUPPORT_10BIT +/* Losless compression body buffer size 4K per 64x32 (jt) */ +static int compute_losless_comp_body_size(int width, int height, + int mem_saving_mode) +{ + int width_x64; + int height_x32; + int bsize; + + width_x64 = width + 63; + width_x64 >>= 6; + + height_x32 = height + 31; + height_x32 >>= 5; + if (mem_saving_mode == 1 && mmu_enable) + bsize = 3200 * width_x64 * height_x32; + else if (mem_saving_mode == 1) + bsize = 3072 * width_x64 * height_x32; + else + bsize = 4096 * width_x64 * height_x32; + + return bsize; +} + +/* Losless compression header buffer size 32bytes per 128x64 (jt) */ +static int compute_losless_comp_header_size(int width, int height) +{ + int width_x128; + int height_x64; + int hsize; + + width_x128 = width + 127; + width_x128 >>= 7; + + height_x64 = height + 63; + height_x64 >>= 6; + + hsize = 32*width_x128*height_x64; + + return hsize; +} + +#endif + +static void init_buff_spec(struct hevc_state_s *hevc, + struct BuffInfo_s *buf_spec) +{ + buf_spec->ipp.buf_start = buf_spec->start_adr; + buf_spec->sao_abv.buf_start = + buf_spec->ipp.buf_start + buf_spec->ipp.buf_size; + + buf_spec->sao_vb.buf_start = + buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size; + buf_spec->short_term_rps.buf_start = + buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size; + buf_spec->vps.buf_start = + buf_spec->short_term_rps.buf_start + + buf_spec->short_term_rps.buf_size; + buf_spec->sps.buf_start = + buf_spec->vps.buf_start + buf_spec->vps.buf_size; + buf_spec->pps.buf_start = + buf_spec->sps.buf_start + buf_spec->sps.buf_size; + buf_spec->sao_up.buf_start = + buf_spec->pps.buf_start + buf_spec->pps.buf_size; + buf_spec->swap_buf.buf_start = + buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size; + buf_spec->swap_buf2.buf_start = + buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size; + buf_spec->scalelut.buf_start = + buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size; + buf_spec->dblk_para.buf_start = + buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size; + buf_spec->dblk_data.buf_start = + buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; + buf_spec->mmu_vbh.buf_start = + buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; + buf_spec->cm_header.buf_start = + buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; + buf_spec->mpred_above.buf_start = + buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size; + buf_spec->mpred_mv.buf_start = + buf_spec->mpred_above.buf_start + + buf_spec->mpred_above.buf_size; + if (get_dbg_flag2(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) { + buf_spec->end_adr = + buf_spec->mpred_mv.buf_start + + buf_spec->mpred_mv.buf_size; + } else { + buf_spec->rpm.buf_start = + buf_spec->mpred_mv.buf_start + + buf_spec->mpred_mv.buf_size; + if (get_dbg_flag2(hevc) & H265_DEBUG_UCODE) { + buf_spec->lmem.buf_start = + buf_spec->rpm.buf_start + + buf_spec->rpm.buf_size; + buf_spec->end_adr = + buf_spec->lmem.buf_start + + buf_spec->lmem.buf_size; + } else { + buf_spec->end_adr = + buf_spec->rpm.buf_start + + buf_spec->rpm.buf_size; + } + } + + if (get_dbg_flag2(hevc)) { + hevc_print(hevc, 0, + "%s workspace (%x %x) size = %x\n", __func__, + buf_spec->start_adr, buf_spec->end_adr, + buf_spec->end_adr - buf_spec->start_adr); + } + if (get_dbg_flag2(hevc)) { + hevc_print(hevc, 0, + "ipp.buf_start :%x\n", + buf_spec->ipp.buf_start); + hevc_print(hevc, 0, + "sao_abv.buf_start :%x\n", + buf_spec->sao_abv.buf_start); + hevc_print(hevc, 0, + "sao_vb.buf_start :%x\n", + buf_spec->sao_vb.buf_start); + hevc_print(hevc, 0, + "short_term_rps.buf_start :%x\n", + buf_spec->short_term_rps.buf_start); + hevc_print(hevc, 0, + "vps.buf_start :%x\n", + buf_spec->vps.buf_start); + hevc_print(hevc, 0, + "sps.buf_start :%x\n", + buf_spec->sps.buf_start); + hevc_print(hevc, 0, + "pps.buf_start :%x\n", + buf_spec->pps.buf_start); + hevc_print(hevc, 0, + "sao_up.buf_start :%x\n", + buf_spec->sao_up.buf_start); + hevc_print(hevc, 0, + "swap_buf.buf_start :%x\n", + buf_spec->swap_buf.buf_start); + hevc_print(hevc, 0, + "swap_buf2.buf_start :%x\n", + buf_spec->swap_buf2.buf_start); + hevc_print(hevc, 0, + "scalelut.buf_start :%x\n", + buf_spec->scalelut.buf_start); + hevc_print(hevc, 0, + "dblk_para.buf_start :%x\n", + buf_spec->dblk_para.buf_start); + hevc_print(hevc, 0, + "dblk_data.buf_start :%x\n", + buf_spec->dblk_data.buf_start); + hevc_print(hevc, 0, + "mpred_above.buf_start :%x\n", + buf_spec->mpred_above.buf_start); + hevc_print(hevc, 0, + "mpred_mv.buf_start :%x\n", + buf_spec->mpred_mv.buf_start); + if ((get_dbg_flag2(hevc) + & + H265_DEBUG_SEND_PARAM_WITH_REG) + == 0) { + hevc_print(hevc, 0, + "rpm.buf_start :%x\n", + buf_spec->rpm.buf_start); + } + } + +} + +enum SliceType { + B_SLICE, + P_SLICE, + I_SLICE +}; + +/*USE_BUF_BLOCK*/ +struct BUF_s { + int index; + /*buffer */ + unsigned long start_adr; + unsigned int size; + + unsigned int free_start_adr; +} /*BUF_t */; + +/* level 6, 6.1 maximum slice number is 800; other is 200 */ +#define MAX_SLICE_NUM 800 +struct PIC_s { + int index; + int BUF_index; + int POC; + int decode_idx; + int slice_type; + int RefNum_L0; + int RefNum_L1; + int num_reorder_pic; + int stream_offset; + unsigned char referenced; + unsigned char output_mark; + unsigned char recon_mark; + unsigned char output_ready; + unsigned char error_mark; + unsigned char used_by_display; + /**/ int slice_idx; + int m_aiRefPOCList0[MAX_SLICE_NUM][16]; + int m_aiRefPOCList1[MAX_SLICE_NUM][16]; + /*buffer */ + unsigned int header_adr; +#ifdef CONFIG_AM_VDEC_DV + unsigned char dv_enhance_exist; +#endif + char *aux_data_buf; + int aux_data_size; + unsigned long cma_alloc_addr; + struct page *alloc_pages; + unsigned int mpred_mv_wr_start_addr; + unsigned int mc_y_adr; + unsigned int mc_u_v_adr; +#ifdef SUPPORT_10BIT + unsigned int comp_body_size; + unsigned int dw_y_adr; + unsigned int dw_u_v_adr; +#endif + unsigned int buf_size; + int mc_canvas_y; + int mc_canvas_u_v; + int width; + int height; + + int y_canvas_index; + int uv_canvas_index; +#ifdef MULTI_INSTANCE_SUPPORT + struct canvas_config_s canvas_config[2]; +#endif +#ifdef LOSLESS_COMPRESS_MODE + unsigned int losless_comp_body_size; +#endif + unsigned char pic_struct; + int vf_ref; + + u32 pts; + u64 pts64; +} /*PIC_t */; + +#define MAX_TILE_COL_NUM 5 +#define MAX_TILE_ROW_NUM 5 +struct tile_s { + int width; + int height; + int start_cu_x; + int start_cu_y; + + unsigned int sao_vb_start_addr; + unsigned int sao_abv_start_addr; +}; + +#define SEI_MASTER_DISPLAY_COLOR_MASK 0x00000001 +#define SEI_CONTENT_LIGHT_LEVEL_MASK 0x00000002 + +#define VF_POOL_SIZE 32 + +#ifdef MULTI_INSTANCE_SUPPORT +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 +#define DEC_RESULT_CONFIG_PARAM 3 +#define DEC_RESULT_ERROR 4 +#define DEC_INIT_PICLIST 5 +#define DEC_UNINIT_PICLIST 6 +#define DEC_RESULT_GET_DATA 7 +#define DEC_RESULT_GET_DATA_RETRY 8 + +static void vh265_work(struct work_struct *work); +#endif +struct hevc_state_s { +#ifdef MULTI_INSTANCE_SUPPORT + struct platform_device *platform_dev; + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; + struct vframe_chunk_s *chunk; + int dec_result; + struct work_struct work; + /* timeout handle */ + unsigned long int start_process_time; + unsigned last_lcu_idx; + unsigned decode_timeout_count; + unsigned timeout_num; +#ifdef CONFIG_AM_VDEC_DV + unsigned char switch_dvlayer_flag; +#endif + unsigned start_parser_type; +#endif + char *provider_name; + int index; + struct device *cma_dev; + unsigned char m_ins_flag; + unsigned char dolby_enhance_flag; + unsigned long buf_start; + u32 buf_size; + + struct BuffInfo_s work_space_buf_store; + struct BuffInfo_s *work_space_buf; + struct buff_s *mc_buf; + + u32 prefix_aux_size; + u32 suffix_aux_size; + void *aux_addr; + void *rpm_addr; + void *lmem_addr; + dma_addr_t aux_phy_addr; + dma_addr_t rpm_phy_addr; + dma_addr_t lmem_phy_addr; + + unsigned int pic_list_init_flag; + unsigned int use_cma_flag; + + unsigned short *rpm_ptr; + unsigned short *lmem_ptr; + unsigned short *debug_ptr; + int debug_ptr_size; + int pic_w; + int pic_h; + int lcu_x_num; + int lcu_y_num; + int lcu_total; + int lcu_size; + int lcu_size_log2; + int lcu_x_num_pre; + int lcu_y_num_pre; + int first_pic_after_recover; + + int num_tile_col; + int num_tile_row; + int tile_enabled; + int tile_x; + int tile_y; + int tile_y_x; + int tile_start_lcu_x; + int tile_start_lcu_y; + int tile_width_lcu; + int tile_height_lcu; + + int slice_type; + unsigned int slice_addr; + unsigned int slice_segment_addr; + + unsigned char interlace_flag; + unsigned char curr_pic_struct; + + unsigned short sps_num_reorder_pics_0; + unsigned short misc_flag0; + int m_temporalId; + int m_nalUnitType; + int TMVPFlag; + int isNextSliceSegment; + int LDCFlag; + int m_pocRandomAccess; + int plevel; + int MaxNumMergeCand; + + int new_pic; + int new_tile; + int curr_POC; + int iPrevPOC; + int iPrevTid0POC; + int list_no; + int RefNum_L0; + int RefNum_L1; + int ColFromL0Flag; + int LongTerm_Curr; + int LongTerm_Col; + int Col_POC; + int LongTerm_Ref; + + struct PIC_s *cur_pic; + struct PIC_s *col_pic; + int skip_flag; + int decode_idx; + int slice_idx; + unsigned char have_vps; + unsigned char have_sps; + unsigned char have_pps; + unsigned char have_valid_start_slice; + unsigned char wait_buf; + unsigned char error_flag; + unsigned int error_skip_nal_count; + + unsigned char + ignore_bufmgr_error; /* bit 0, for decoding; bit 1, for displaying */ + int PB_skip_mode; + int PB_skip_count_after_decoding; +#ifdef SUPPORT_10BIT + int mem_saving_mode; +#endif +#ifdef LOSLESS_COMPRESS_MODE + unsigned int losless_comp_body_size; +#endif + int pts_mode; + int last_lookup_pts; + int last_pts; + u64 last_lookup_pts_us64; + u64 last_pts_us64; + u32 shift_byte_count_lo; + u32 shift_byte_count_hi; + int pts_mode_switching_count; + int pts_mode_recovery_count; + + int buf_num; + int pic_num; + + /**/ + struct buff_s mc_buf_spec; + union param_u param; + + struct tile_s m_tile[MAX_TILE_ROW_NUM][MAX_TILE_COL_NUM]; + + struct timer_list timer; + struct BUF_s m_BUF[MAX_BUF_NUM]; + u32 used_buf_num; + struct PIC_s *m_PIC[MAX_REF_PIC_NUM]; + + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE); + struct vframe_s vfpool[VF_POOL_SIZE]; + + u32 stat; + u32 frame_width; + u32 frame_height; + u32 frame_dur; + u32 frame_ar; + u32 bit_depth_luma; + u32 bit_depth_chroma; + u32 video_signal_type; + u32 saved_resolution; + bool get_frame_dur; + u32 error_watchdog_count; + u32 error_skip_nal_wt_cnt; + u32 error_system_watchdog_count; + +#ifdef DEBUG_PTS + unsigned long pts_missed; + unsigned long pts_hit; +#endif + struct dec_sysinfo vh265_amstream_dec_info; + unsigned char init_flag; + unsigned char uninit_list; + u32 start_decoding_time; + + int show_frame_num; + struct semaphore h265_sema; +#ifdef USE_UNINIT_SEMA + struct semaphore h265_uninit_done_sema; +#endif + int fatal_error; + + + u32 sei_present_flag; + void *frame_mmu_map_addr; + dma_addr_t frame_mmu_map_phy_addr; + unsigned int mmu_mc_buf_start; + unsigned int mmu_mc_buf_end; + unsigned int mmu_mc_start_4k_adr; + void *mmu_box; + void *bmmu_box; + + unsigned int last_put_idx_a; + unsigned int last_put_idx_b; + + unsigned int dec_status; + + + /* data for SEI_MASTER_DISPLAY_COLOR */ + unsigned int primaries[3][2]; + unsigned int white_point[2]; + unsigned int luminance[2]; + /* data for SEI_CONTENT_LIGHT_LEVEL */ + unsigned int content_light_level[2]; + + struct PIC_s *pre_top_pic; + struct PIC_s *pre_bot_pic; + +#ifdef MULTI_INSTANCE_SUPPORT + int double_write_mode; + int buf_alloc_width; + int buf_alloc_height; + int dynamic_buf_num_margin; + int start_action; +#endif +} /*hevc_stru_t */; + +#ifdef CONFIG_MULTI_DEC +static int get_double_write_mode(struct hevc_state_s *hevc) +{ + return hevc->double_write_mode; +} + +static int get_buf_alloc_width(struct hevc_state_s *hevc) +{ + return hevc->buf_alloc_width; +} + +static int get_buf_alloc_height(struct hevc_state_s *hevc) +{ + return hevc->buf_alloc_height; +} + +static int get_dynamic_buf_num_margin(struct hevc_state_s *hevc) +{ + return hevc->dynamic_buf_num_margin; +} +#endif + +#ifdef CONFIG_MULTI_DEC +static unsigned char get_idx(struct hevc_state_s *hevc) +{ + return hevc->index; +} +#endif + +#undef pr_info +#define pr_info printk +static int hevc_print(struct hevc_state_s *hevc, + int flag, const char *fmt, ...) +{ +#define HEVC_PRINT_BUF 128 + unsigned char buf[HEVC_PRINT_BUF]; + int len = 0; +#ifdef CONFIG_MULTI_DEC + if (hevc == NULL || + (flag == 0) || + ((debug_mask & + (1 << hevc->index)) + && (debug & flag))) { +#endif + va_list args; + + va_start(args, fmt); + if (hevc) + len = sprintf(buf, "[%d]", hevc->index); + vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); + pr_info("%s", buf); + va_end(args); +#ifdef CONFIG_MULTI_DEC + } +#endif + return 0; +} + +static int hevc_print_cont(struct hevc_state_s *hevc, + int flag, const char *fmt, ...) +{ +#define HEVC_PRINT_BUF 128 + unsigned char buf[HEVC_PRINT_BUF]; + int len = 0; +#ifdef CONFIG_MULTI_DEC + if (hevc == NULL || + (flag == 0) || + ((debug_mask & + (1 << hevc->index)) + && (debug & flag))) { +#endif + va_list args; + va_start(args, fmt); + vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); + pr_info("%s", buf); + va_end(args); +#ifdef CONFIG_MULTI_DEC + } +#endif + return 0; +} + +static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic); + +static void release_aux_data(struct hevc_state_s *hevc, + struct PIC_s *pic); + +static void hevc_init_stru(struct hevc_state_s *hevc, + struct BuffInfo_s *buf_spec_i, + struct buff_s *mc_buf_i) +{ + int i; + + hevc->work_space_buf = buf_spec_i; + hevc->mc_buf = mc_buf_i; + hevc->prefix_aux_size = 0; + hevc->suffix_aux_size = 0; + hevc->aux_addr = NULL; + hevc->rpm_addr = NULL; + hevc->lmem_addr = NULL; + + hevc->curr_POC = INVALID_POC; + + hevc->pic_list_init_flag = 0; + hevc->use_cma_flag = 0; + hevc->decode_idx = 0; + hevc->slice_idx = 0; + hevc->new_pic = 0; + hevc->new_tile = 0; + hevc->iPrevPOC = 0; + hevc->list_no = 0; + /* int m_uiMaxCUWidth = 1<<7; */ + /* int m_uiMaxCUHeight = 1<<7; */ + hevc->m_pocRandomAccess = MAX_INT; + hevc->tile_enabled = 0; + hevc->tile_x = 0; + hevc->tile_y = 0; + hevc->iPrevTid0POC = 0; + hevc->slice_addr = 0; + hevc->slice_segment_addr = 0; + hevc->skip_flag = 0; + hevc->misc_flag0 = 0; + + hevc->cur_pic = NULL; + hevc->col_pic = NULL; + hevc->wait_buf = 0; + hevc->error_flag = 0; + hevc->error_skip_nal_count = 0; + hevc->have_vps = 0; + hevc->have_sps = 0; + hevc->have_pps = 0; + hevc->have_valid_start_slice = 0; + + hevc->pts_mode = PTS_NORMAL; + hevc->last_pts = 0; + hevc->last_lookup_pts = 0; + hevc->last_pts_us64 = 0; + hevc->last_lookup_pts_us64 = 0; + hevc->shift_byte_count_lo = 0; + hevc->shift_byte_count_hi = 0; + hevc->pts_mode_switching_count = 0; + hevc->pts_mode_recovery_count = 0; + + hevc->PB_skip_mode = nal_skip_policy & 0x3; + hevc->PB_skip_count_after_decoding = (nal_skip_policy >> 16) & 0xffff; + if (hevc->PB_skip_mode == 0) + hevc->ignore_bufmgr_error = 0x1; + else + hevc->ignore_bufmgr_error = 0x0; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) + hevc->m_PIC[i] = NULL; + hevc->buf_num = 0; + hevc->pic_num = 0; + hevc->lcu_x_num_pre = 0; + hevc->lcu_y_num_pre = 0; + hevc->first_pic_after_recover = 0; + + hevc->pre_top_pic = NULL; + hevc->pre_bot_pic = NULL; + + hevc->sei_present_flag = 0; +#ifdef MULTI_INSTANCE_SUPPORT + hevc->start_process_time = 0; + hevc->last_lcu_idx = 0; + hevc->decode_timeout_count = 0; + hevc->timeout_num = 0; +#endif +} + +static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic); +static int H265_alloc_mmu(struct hevc_state_s *hevc, + struct PIC_s *new_pic, unsigned short bit_depth, + unsigned int *mmu_index_adr); + +static void get_rpm_param(union param_u *params) +{ + int i; + unsigned int data32; + + for (i = 0; i < 128; i++) { + do { + data32 = READ_VREG(RPM_CMD_REG); + /* hevc_print(hevc, 0, "%x\n", data32); */ + } while ((data32 & 0x10000) == 0); + params->l.data[i] = data32 & 0xffff; + /* hevc_print(hevc, 0, "%x\n", data32); */ + WRITE_VREG(RPM_CMD_REG, 0); + } +} + +static struct PIC_s *get_pic_by_POC(struct hevc_state_s *hevc, int POC) +{ + int i; + struct PIC_s *pic; + struct PIC_s *ret_pic = NULL; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->POC == POC) { + if (ret_pic == NULL) + ret_pic = pic; + else { + if (pic->decode_idx > ret_pic->decode_idx) + ret_pic = pic; + } + } + } + return ret_pic; +} + +static struct PIC_s *get_ref_pic_by_POC(struct hevc_state_s *hevc, int POC) +{ + int i; + struct PIC_s *pic; + struct PIC_s *ret_pic = NULL; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if ((pic->POC == POC) && (pic->referenced)) { + if (ret_pic == NULL) + ret_pic = pic; + else { + if (pic->decode_idx > ret_pic->decode_idx) + ret_pic = pic; + } + } + } + + if (ret_pic == NULL) { + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "Wrong, POC of %d is not in referenced list\n", + POC); + } + ret_pic = get_pic_by_POC(hevc, POC); + } + return ret_pic; +} + +static unsigned int log2i(unsigned int val) +{ + unsigned int ret = -1; + + while (val != 0) { + val >>= 1; + ret++; + } + return ret; +} + +static int init_buf_spec(struct hevc_state_s *hevc); + +static void uninit_mmu_buffers(struct hevc_state_s *hevc) +{ + + if (hevc->mmu_box) + decoder_mmu_box_free(hevc->mmu_box); + hevc->mmu_box = NULL; + + if (hevc->bmmu_box) + decoder_bmmu_box_free(hevc->bmmu_box); + hevc->bmmu_box = NULL; +} +static int init_mmu_buffers(struct hevc_state_s *hevc) +{ + if (mmu_enable) { + hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, + hevc->index, + MAX_REF_PIC_NUM, + 64 * SZ_1M + ); + if (!hevc->mmu_box) { + pr_err("h265 alloc mmu box failed!!\n"); + return -1; + } + } + hevc->bmmu_box = decoder_bmmu_box_alloc_box(DRIVER_NAME, + hevc->index, + BMMU_MAX_BUFFERS, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + if (!hevc->bmmu_box) { + if (hevc->mmu_box) + decoder_mmu_box_free(hevc->mmu_box); + hevc->mmu_box = NULL; + pr_err("h265 alloc mmu box failed!!\n"); + return -1; + } + return 0; +} + +static void init_buf_list(struct hevc_state_s *hevc) +{ + int i; + int buf_size; + int mc_buffer_end = hevc->mc_buf->buf_start + hevc->mc_buf->buf_size; + + if (get_dynamic_buf_num_margin(hevc) > 0) + hevc->used_buf_num = hevc->sps_num_reorder_pics_0 + + get_dynamic_buf_num_margin(hevc); + else + hevc->used_buf_num = max_buf_num; + + if (hevc->used_buf_num > MAX_BUF_NUM) + hevc->used_buf_num = MAX_BUF_NUM; + if (buf_alloc_size > 0) { + buf_size = buf_alloc_size; + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "[Buffer Management] init_buf_list:\n"); + } else { + int pic_width = get_buf_alloc_width(hevc) + ? get_buf_alloc_width(hevc) : hevc->pic_w; + int pic_height = + get_buf_alloc_height(hevc) + ? get_buf_alloc_height(hevc) : hevc->pic_h; +#ifdef LOSLESS_COMPRESS_MODE +/*SUPPORT_10BIT*/ + int losless_comp_header_size = compute_losless_comp_header_size + (pic_width, pic_height); + int losless_comp_body_size = compute_losless_comp_body_size + (pic_width, pic_height, hevc->mem_saving_mode); + int mc_buffer_size = losless_comp_header_size + + losless_comp_body_size; + int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; + if (get_double_write_mode(hevc)) { + int pic_width_dw = ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) ? + pic_width / 4 : pic_width; + int pic_height_dw = ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) ? + pic_height / 4 : pic_height; + int lcu_size = hevc->lcu_size; + int pic_width_lcu = (pic_width_dw % lcu_size) + ? pic_width_dw / lcu_size + + 1 : pic_width_dw / lcu_size; + int pic_height_lcu = (pic_height_dw % lcu_size) + ? pic_height_dw / lcu_size + + 1 : pic_height_dw / lcu_size; + int lcu_total = pic_width_lcu * pic_height_lcu; + int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; + int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; + /*64k alignment*/ + buf_size = ((mc_buffer_size_u_v_h << 16) * 3); + } else + buf_size = 0; + + if (mc_buffer_size & 0xffff) { /*64k alignment*/ + mc_buffer_size_h += 1; + } + if (mmu_enable) { + if (get_double_write_mode(hevc) == 1) + buf_size += (mc_buffer_size_h << 16); + } else { + if ((get_double_write_mode(hevc) & 0x10) == 0) + buf_size += (mc_buffer_size_h << 16); + } +#else + int lcu_size = hevc->lcu_size; + int pic_width_lcu = + (pic_width % lcu_size) ? pic_width / lcu_size + + 1 : pic_width / lcu_size; + int pic_height_lcu = + (pic_height % lcu_size) ? pic_height / lcu_size + + 1 : pic_height / lcu_size; + int lcu_total = pic_width_lcu * pic_height_lcu; + int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; + int mc_buffer_size_u_v_h = + (mc_buffer_size_u_v + 0xffff) >> 16; + /*64k alignment*/ + buf_size = (mc_buffer_size_u_v_h << 16) * 3; +#endif + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "init_buf_list num %d (width %d height %d):\n", + hevc->used_buf_num, pic_width, pic_height); + } + } + + hevc_print(hevc, 0, "allocate begin\n"); + //get_cma_alloc_ref();//DEBUG_TMP + for (i = 0; i < hevc->used_buf_num; i++) { + if (((i + 1) * buf_size) > hevc->mc_buf->buf_size) { + if (use_cma) + hevc->use_cma_flag = 1; + else { + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "%s maximum buf size is used\n", + __func__); + } + break; + } + } + + + if (!mmu_enable) { + hevc->m_BUF[i].index = i; + + if (use_cma == 2) + hevc->use_cma_flag = 1; + if (hevc->use_cma_flag) { + if (decoder_bmmu_box_alloc_idx_wait( + hevc->bmmu_box, + i, + buf_size, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR + ) < 0) { + /* + not enough mem for buffer. + */ + hevc_print(hevc, 0, + "not enought buffer for [%d],%d\n", + i, buf_size); + hevc->m_BUF[i].start_adr = 0; + if (i <= 8) { + /*if alloced (i+1)>=9 + don't send errors.*/ + hevc->fatal_error |= + DECODER_FATAL_ERROR_NO_MEM; + } + break; + } + hevc->m_BUF[i].start_adr = + decoder_bmmu_box_get_phy_addr( + hevc->bmmu_box, + i); + pr_debug("allocate cma buffer[%d] %ld\n", + i, + hevc->m_BUF[i].start_adr); + } else { + hevc->m_BUF[i].start_adr = + hevc->mc_buf->buf_start + i * buf_size; + if (((hevc->m_BUF[i].start_adr + buf_size) > + mc_buffer_end)) { + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "Max mc buffer or mpred_mv buffer is used\n"); + } + break; + } + } + hevc->m_BUF[i].size = buf_size; + hevc->m_BUF[i].free_start_adr = + hevc->m_BUF[i].start_adr; + + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "Buffer %d: start_adr %p size %x\n", i, + (void *)hevc->m_BUF[i].start_adr, + hevc->m_BUF[i].size); + } + } + } + //put_cma_alloc_ref();//DEBUG_TMP + hevc_print(hevc, 0, "allocate end\n"); + + hevc->buf_num = i; + +} + +static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic, + unsigned int last_disp_addr) +{ + int ret = -1; + int i; + int pic_width = ((re_config_pic_flag == 0) && + get_buf_alloc_width(hevc)) ? + get_buf_alloc_width(hevc) : hevc->pic_w; + int pic_height = ((re_config_pic_flag == 0) && + get_buf_alloc_height(hevc)) ? + get_buf_alloc_height(hevc) : hevc->pic_h; + int lcu_size = hevc->lcu_size; + int pic_width_lcu = (pic_width % lcu_size) ? pic_width / lcu_size + + 1 : pic_width / lcu_size; + int pic_height_lcu = (pic_height % lcu_size) ? pic_height / lcu_size + + 1 : pic_height / lcu_size; + int lcu_total = pic_width_lcu * pic_height_lcu; + int lcu_size_log2 = hevc->lcu_size_log2; + /*int MV_MEM_UNIT=lcu_size_log2== + 6 ? 0x100 : lcu_size_log2==5 ? 0x40 : 0x10;*/ + int MV_MEM_UNIT = lcu_size_log2 == 6 ? 0x200 : lcu_size_log2 == + 5 ? 0x80 : 0x20; + int mpred_mv_end = hevc->work_space_buf->mpred_mv.buf_start + + hevc->work_space_buf->mpred_mv.buf_size; + unsigned int y_adr = 0; + int buf_size = 0; +#ifdef LOSLESS_COMPRESS_MODE +/*SUPPORT_10BIT*/ + int losless_comp_header_size = + compute_losless_comp_header_size(pic_width, + pic_height); + int losless_comp_body_size = compute_losless_comp_body_size(pic_width, + pic_height, hevc->mem_saving_mode); + int mc_buffer_size = losless_comp_header_size + losless_comp_body_size; + int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; + int mc_buffer_size_u_v = 0; + int mc_buffer_size_u_v_h = 0; + if (get_double_write_mode(hevc)) { + int pic_width_dw = ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) ? + pic_width / 4 : pic_width; + int pic_height_dw = ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) ? + pic_height / 4 : pic_height; + int pic_width_lcu_dw = (pic_width_dw % lcu_size) ? + pic_width_dw / lcu_size + 1 : + pic_width_dw / lcu_size; + int pic_height_lcu_dw = (pic_height_dw % lcu_size) ? + pic_height_dw / lcu_size + 1 : + pic_height_dw / lcu_size; + int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; + + mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; + mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; + /*64k alignment*/ + buf_size = ((mc_buffer_size_u_v_h << 16) * 3); + } + if (mc_buffer_size & 0xffff) { /*64k alignment*/ + mc_buffer_size_h += 1; + } + if (mmu_enable) { + if (get_double_write_mode(hevc) == 1) + buf_size += (mc_buffer_size_h << 16); + } else { + if ((get_double_write_mode(hevc) & 0x10) == 0) + buf_size += (mc_buffer_size_h << 16); + } +#else + int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; + int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; + /*64k alignment*/ + buf_size = ((mc_buffer_size_u_v_h << 16) * 3); +#endif + + + if (mmu_enable) { + if ((hevc->work_space_buf->cm_header.buf_start + + ((pic->index + 1) + * MMU_COMPRESS_HEADER_SIZE)) + > (hevc->work_space_buf->cm_header.buf_start + + hevc->work_space_buf->cm_header.buf_size)) { + hevc_print(hevc, 0, + "MMU header_adr allocate fail\n"); + return -1; + } + + pic->header_adr = hevc->work_space_buf->cm_header.buf_start + + (pic->index * MMU_COMPRESS_HEADER_SIZE); + if (last_disp_addr && pic->header_adr == last_disp_addr) { + /*if same as disp add used last one.*/ + pr_info("same as disp %d: %d\n", + pic->index, pic->header_adr); + pic->header_adr = + hevc->work_space_buf->cm_header.buf_start + + (16 * MMU_COMPRESS_HEADER_SIZE); + } + if (get_dbg_flag(hevc)&H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "MMU header_adr %d: %x\n", + pic->index, pic->header_adr); + } + } + + + if ((hevc->work_space_buf->mpred_mv.buf_start + (((pic->index + 1) + * lcu_total) * MV_MEM_UNIT)) + <= mpred_mv_end) { + + if (!mmu_enable) { + for (i = 0; i < hevc->buf_num; i++) { + y_adr = ((hevc->m_BUF[i].free_start_adr + + 0xffff) >> 16) << 16; + /*64k alignment*/ + if ((y_adr+buf_size) <= + (hevc->m_BUF[i].start_adr+ + hevc->m_BUF[i].size)) { + hevc->m_BUF[i].free_start_adr = + y_adr + buf_size; + break; + } + } + } else + i = pic->index; + + if (i < hevc->buf_num) { + pic->POC = INVALID_POC; + /*ensure get_pic_by_POC() + not get the buffer not decoded*/ + pic->BUF_index = i; +#ifdef LOSLESS_COMPRESS_MODE +/*SUPPORT_10BIT*/ + pic->comp_body_size = losless_comp_body_size; + pic->buf_size = buf_size; + + if (!mmu_enable) + pic->mc_y_adr = y_adr; + else if (get_double_write_mode(hevc)) { + if ((hevc->mc_buf->buf_start + + (i + 1) * buf_size) + < hevc->mc_buf->buf_end) + y_adr = hevc->mc_buf->buf_start + + i * buf_size; + else { + if (decoder_bmmu_box_alloc_idx_wait( + hevc->bmmu_box, + pic->BUF_index, + buf_size, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR + ) < 0) { + return -1; + } + pic->cma_alloc_addr = + decoder_bmmu_box_get_phy_addr( + hevc->bmmu_box, + pic->BUF_index); + if (pic->cma_alloc_addr) + y_adr = pic->cma_alloc_addr; + else + return -1; + } + } + pic->mc_canvas_y = pic->index; + pic->mc_canvas_u_v = pic->index; + if (!mmu_enable && get_double_write_mode(hevc) & 0x10) { + pic->mc_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); + + pic->mc_canvas_y = (pic->index << 1); + pic->mc_canvas_u_v = (pic->index << 1) + 1; + + pic->dw_y_adr = y_adr; + pic->dw_u_v_adr = pic->mc_u_v_adr; + } else if (get_double_write_mode(hevc)) { + if (mmu_enable) + pic->dw_y_adr = y_adr; + else + pic->dw_y_adr = y_adr + + (mc_buffer_size_h << 16); + pic->dw_u_v_adr = pic->dw_y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); + } +#else + pic->buf_size = (mc_buffer_size_u_v_h << 16) * 3; + pic->mc_y_adr = y_adr; + pic->mc_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); + + pic->mc_canvas_y = (pic->index << 1); + pic->mc_canvas_u_v = (pic->index << 1) + 1; +#endif + pic->mpred_mv_wr_start_addr = + hevc->work_space_buf->mpred_mv.buf_start + + ((pic->index * lcu_total) + * MV_MEM_UNIT); + + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "%s index %d BUF_index %d mc_y_adr %x ", + __func__, pic->index, + pic->BUF_index, pic->mc_y_adr); +#ifdef LOSLESS_COMPRESS_MODE + hevc_print_cont(hevc, 0, + "comp_body_size %x comp_buf_size %x ", + pic->comp_body_size, pic->buf_size); + hevc_print_cont(hevc, 0, + "mpred_mv_wr_start_adr %x\n", + pic->mpred_mv_wr_start_addr); + if (mmu_enable && get_double_write_mode(hevc)) + hevc_print(hevc, 0, + "mmu double write adr %ld\n", + pic->cma_alloc_addr); + +#else + hevc_print(hevc, 0, + ("mc_u_v_adr %x mpred_mv_wr_start_adr %x\n", + pic->mc_u_v_adr, pic->mpred_mv_wr_start_addr); +#endif + } + ret = 0; + } + } + return ret; +} + +/* +*free hevc->m_BUF[..] for all free hevc->m_PIC[..] +* with the different size of hevc->pic_w,hevc->pic_h +*/ +static int recycle_buf(struct hevc_state_s *hevc) +{ + int i, j; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->width != hevc->pic_w || pic->height != hevc->pic_h) { + if (pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 0) { + if (mmu_enable) { + decoder_mmu_box_free_idx(hevc->mmu_box, + pic->index); + } + pic->BUF_index = -1; + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "%s: %d\n", __func__, + pic->index); + } + } + } + } + + for (i = 0; i < hevc->buf_num; i++) { + if (hevc->m_BUF[i].free_start_adr != + hevc->m_BUF[i].start_adr) { + for (j = 0; j < MAX_REF_PIC_NUM; j++) { + struct PIC_s *pic = hevc->m_PIC[j]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->BUF_index == i) + break; + } + if (j == MAX_REF_PIC_NUM) + hevc->m_BUF[i].free_start_adr = + hevc->m_BUF[i].start_adr; + } + } + return 0; +} + +static void init_pic_list(struct hevc_state_s *hevc) +{ + int i; + struct vframe_s vf; + unsigned long flags; + unsigned long disp_addr = 0; + + if (!get_video0_frame_info(&vf)) { + spin_lock_irqsave(&lock, flags); + if (vf.type & VIDTYPE_SCATTER) { + /*sc only used header.*/ + disp_addr = (VSYNC_RD_MPEG_REG(AFBC_HEAD_BADDR) << 4); + } else if (vf.type & VIDTYPE_COMPRESS) { + /*sc checked body.*/ + disp_addr = (VSYNC_RD_MPEG_REG(AFBC_BODY_BADDR) << 4); + } else { + struct canvas_s cur_canvas; + + canvas_read(vf.canvas0Addr & 0xff, &cur_canvas); + disp_addr = cur_canvas.addr; + } + spin_unlock_irqrestore(&lock, flags); + } + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = + vmalloc(sizeof(struct PIC_s)); + if (pic == NULL) { + hevc_print(hevc, 0, + "alloc pic %d fail\n", i); + break; + } + memset(pic, 0, sizeof(struct PIC_s)); + hevc->m_PIC[i] = pic; + pic->index = i; + pic->BUF_index = -1; + if (config_pic(hevc, pic, disp_addr) < 0) { + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "Config_pic %d fail\n", pic->index); + pic->index = -1; + i++; + break; + } + pic->width = hevc->pic_w; + pic->height = hevc->pic_h; + if (get_double_write_mode(hevc)) + set_canvas(hevc, pic); + } + + for (; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = + vmalloc(sizeof(struct PIC_s)); + if (pic == NULL) { + hevc_print(hevc, 0, + "alloc pic %d fail\n", i); + break; + } + memset(pic, 0, sizeof(struct PIC_s)); + hevc->m_PIC[i] = pic; + pic->index = -1; + pic->BUF_index = -1; + } + +} + +static void uninit_pic_list(struct hevc_state_s *hevc) +{ + int i; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = hevc->m_PIC[i]; + if (pic) { + release_aux_data(hevc, pic); + vfree(pic); + hevc->m_PIC[i] = NULL; + } + } +} + +#ifdef LOSLESS_COMPRESS_MODE +static void init_decode_head_hw(struct hevc_state_s *hevc) +{ + + struct BuffInfo_s *buf_spec = hevc->work_space_buf; + unsigned int data32; + + int losless_comp_header_size = + compute_losless_comp_header_size(hevc->pic_w, + hevc->pic_h); + int losless_comp_body_size = compute_losless_comp_body_size(hevc->pic_w, + hevc->pic_h, hevc->mem_saving_mode); + + hevc->losless_comp_body_size = losless_comp_body_size; + + + if (mmu_enable) { + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0); + } else { + if (hevc->mem_saving_mode == 1) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, + (1 << 3) | ((workaround_enable & 2) ? 1 : 0)); + else + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, + ((workaround_enable & 2) ? 1 : 0)); + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); + /* + *WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff); + * //8-bit mode + */ + } + WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + + if (mmu_enable) { + WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); + WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, + buf_spec->mmu_vbh.buf_start + + buf_spec->mmu_vbh.buf_size/2); + data32 = READ_VREG(HEVC_SAO_CTRL9); + data32 |= 0x1; + WRITE_VREG(HEVC_SAO_CTRL9, data32); + + /* use HEVC_CM_HEADER_START_ADDR */ + data32 = READ_VREG(HEVC_SAO_CTRL5); + data32 |= (1<<10); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + } + + if (!hevc->m_ins_flag) + hevc_print(hevc, 0, + "%s: (%d, %d) body_size 0x%x header_size 0x%x\n", + __func__, hevc->pic_w, hevc->pic_h, + losless_comp_body_size, losless_comp_header_size); + +} +#endif +#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 + +static void init_pic_list_hw(struct hevc_state_s *hevc) +{ + int i; + int cur_pic_num = MAX_REF_PIC_NUM; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (0x1 << 2)); + else + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0); + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + if (hevc->m_PIC[i] == NULL || + hevc->m_PIC[i]->index == -1) { + cur_pic_num = i; + break; + } + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + if (mmu_enable) + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[i]->header_adr>>5); + else + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[i]->mc_y_adr >> 5); + } else + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + hevc->m_PIC[i]->mc_y_adr | + (hevc->m_PIC[i]->mc_canvas_y << 8) | 0x1); + if (get_double_write_mode(hevc) & 0x10) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + if (mmu_enable) + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[i]->header_adr>>5); + else + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[i]->mc_u_v_adr >> 5); + } + else + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + hevc->m_PIC[i]->mc_u_v_adr | + (hevc->m_PIC[i]->mc_canvas_u_v << 8) + | 0x1); + } + } + if (cur_pic_num == 0) + return; + for (; i < MAX_REF_PIC_NUM; i++) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + if (mmu_enable) + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[cur_pic_num-1]->header_adr>>5); + else + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[cur_pic_num-1]->mc_y_adr >> 5); +#ifndef LOSLESS_COMPRESS_MODE + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + hevc->m_PIC[cur_pic_num-1]->mc_u_v_adr >> 5); +#endif + } else { + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + hevc->m_PIC[cur_pic_num-1]->mc_y_adr| + (hevc->m_PIC[cur_pic_num-1]->mc_canvas_y<<8) + | 0x1); +#ifndef LOSLESS_COMPRESS_MODE + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + hevc->m_PIC[cur_pic_num-1]->mc_u_v_adr| + (hevc->m_PIC[cur_pic_num-1]->mc_canvas_u_v<<8) + | 0x1); +#endif + } + } + + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); + + /* Zero out canvas registers in IPP -- avoid simulation X */ + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (0 << 1) | 1); + for (i = 0; i < 32; i++) + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); + +#ifdef LOSLESS_COMPRESS_MODE + if ((get_double_write_mode(hevc) & 0x10) == 0) + init_decode_head_hw(hevc); +#endif + +} + + +static void dump_pic_list(struct hevc_state_s *hevc) +{ + int i; + struct PIC_s *pic; + hevc_print(hevc, 0, + "pic_list_init_flag is %d\r\n", hevc->pic_list_init_flag); + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + hevc_print_cont(hevc, 0, + "index %d decode_idx:%d, POC:%d, referenced:%d, ", + pic->index, pic->decode_idx, pic->POC, pic->referenced); + hevc_print_cont(hevc, 0, + "num_reorder_pic:%d, output_mark:%d, w/h %d,%d", + pic->num_reorder_pic, pic->output_mark, + pic->width, pic->height); + hevc_print_cont(hevc, 0, + "output_ready:%d, mv_wr_start %x vf_ref %d\n", + pic->output_ready, pic->mpred_mv_wr_start_addr, + pic->vf_ref); + } +} + +static struct PIC_s *output_pic(struct hevc_state_s *hevc, + unsigned char flush_flag) +{ + int num_pic_not_yet_display = 0; + int i; + struct PIC_s *pic; + struct PIC_s *pic_display = NULL; + + if (i_only_flag & 0x4) { + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || + (pic->index == -1) || (pic->POC == INVALID_POC)) + continue; + if (pic->output_mark) { + if (pic_display) { + if (pic->decode_idx < + pic_display->decode_idx) + pic_display = pic; + + } else + pic_display = pic; + + } + } + if (pic_display) { + pic_display->output_mark = 0; + pic_display->recon_mark = 0; + pic_display->output_ready = 1; + pic_display->referenced = 0; + } + } else { + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || + (pic->index == -1) || (pic->POC == INVALID_POC)) + continue; + if (pic->output_mark) + num_pic_not_yet_display++; + } + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || + (pic->index == -1) || (pic->POC == INVALID_POC)) + continue; + if (pic->output_mark) { + if (pic_display) { + if (pic->POC < pic_display->POC) + pic_display = pic; + else if ((pic->POC == pic_display->POC) + && (pic->decode_idx < + pic_display-> + decode_idx)) + pic_display + = pic; + } else + pic_display = pic; + } + } + if (pic_display) { + if ((num_pic_not_yet_display > + pic_display->num_reorder_pic) + || flush_flag) { + pic_display->output_mark = 0; + pic_display->recon_mark = 0; + pic_display->output_ready = 1; + } else if (num_pic_not_yet_display >= + (MAX_REF_PIC_NUM - 1)) { + pic_display->output_mark = 0; + pic_display->recon_mark = 0; + pic_display->output_ready = 1; + hevc_print(hevc, 0, + "Warning, num_reorder_pic %d is byeond buf num\n", + pic_display->num_reorder_pic); + } else + pic_display = NULL; + } + } + return pic_display; +} + +static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) +{ + int i; + struct PIC_s *pic; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "config_mc_buffer entered .....\n"); + if (cur_pic->slice_type != 2) { /* P and B pic */ + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (0 << 1) | 1); + for (i = 0; i < cur_pic->RefNum_L0; i++) { + pic = + get_ref_pic_by_POC(hevc, + cur_pic-> + m_aiRefPOCList0[cur_pic-> + slice_idx][i]); + if (pic) { + if (pic->error_mark) + cur_pic->error_mark = 1; + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, + (pic->mc_canvas_u_v << 16) + | (pic->mc_canvas_u_v + << 8) | + pic->mc_canvas_y); + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, + "refid %x mc_canvas_u_v %x", + i, pic->mc_canvas_u_v); + hevc_print_cont(hevc, 0, + " mc_canvas_y %x\n", + pic->mc_canvas_y); + } + } else { + if (get_dbg_flag(hevc)) { + hevc_print_cont(hevc, 0, + "Error %s, %dth poc (%d)", + __func__, i, + cur_pic->m_aiRefPOCList0[cur_pic-> + slice_idx][i]); + hevc_print_cont(hevc, 0, + " of RPS is not in the pic list0\n"); + } + cur_pic->error_mark = 1; + /* dump_lmem(); */ + } + } + } + if (cur_pic->slice_type == 0) { /* B pic */ + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "config_mc_buffer RefNum_L1\n"); + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (16 << 8) | (0 << 1) | 1); + for (i = 0; i < cur_pic->RefNum_L1; i++) { + pic = + get_ref_pic_by_POC(hevc, + cur_pic-> + m_aiRefPOCList1[cur_pic-> + slice_idx][i]); + if (pic) { + if (pic->error_mark) + cur_pic->error_mark = 1; + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, + (pic->mc_canvas_u_v << 16) + | (pic->mc_canvas_u_v + << 8) | + pic->mc_canvas_y); + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, + "refid %x mc_canvas_u_v %x", + i, pic->mc_canvas_u_v); + hevc_print_cont(hevc, 0, + " mc_canvas_y %x\n", + pic->mc_canvas_y); + } + } else { + if (get_dbg_flag(hevc)) { + hevc_print_cont(hevc, 0, + "Error %s, %dth poc (%d)", + __func__, i, + cur_pic->m_aiRefPOCList1[cur_pic-> + slice_idx][i]); + hevc_print_cont(hevc, 0, + " of RPS is not in the pic list1\n"); + } + cur_pic->error_mark = 1; + /* dump_lmem(); */ + } + } + } + return 0; +} + +static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, + union param_u *params) +{ + int ii, i; + int poc_tmp; + struct PIC_s *pic; + unsigned char is_referenced; + + /* pr_info("%s cur_poc %d\n", __func__, cur_poc); */ + for (ii = 0; ii < MAX_REF_PIC_NUM; ii++) { + pic = hevc->m_PIC[ii]; + if (pic == NULL || + pic->index == -1) + continue; + + if ((pic->referenced == 0 || pic->POC == cur_poc)) + continue; + is_referenced = 0; + for (i = 0; i < 16; i++) { + int delt; + + if (params->p.CUR_RPS[i] & 0x8000) + break; + delt = + params->p.CUR_RPS[i] & + ((1 << (RPS_USED_BIT - 1)) - 1); + if (params->p.CUR_RPS[i] & (1 << (RPS_USED_BIT - 1))) { + poc_tmp = + cur_poc - ((1 << (RPS_USED_BIT - 1)) - + delt); + } else + poc_tmp = cur_poc + delt; + if (poc_tmp == pic->POC) { + is_referenced = 1; + /* pr_info("i is %d\n", i); */ + break; + } + } + if (is_referenced == 0) { + pic->referenced = 0; + /* pr_info("set poc %d reference to 0\n", pic->POC); */ + } + } + +} + +static void set_ref_pic_list(struct hevc_state_s *hevc, union param_u *params) +{ + struct PIC_s *pic = hevc->cur_pic; + int i, rIdx; + int num_neg = 0; + int num_pos = 0; + int total_num; + int num_ref_idx_l0_active = + (params->p.num_ref_idx_l0_active > + MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : + params->p.num_ref_idx_l0_active; + int num_ref_idx_l1_active = + (params->p.num_ref_idx_l1_active > + MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : + params->p.num_ref_idx_l1_active; + + int RefPicSetStCurr0[16]; + int RefPicSetStCurr1[16]; + + for (i = 0; i < 16; i++) { + RefPicSetStCurr0[i] = 0; + RefPicSetStCurr1[i] = 0; + pic->m_aiRefPOCList0[pic->slice_idx][i] = 0; + pic->m_aiRefPOCList1[pic->slice_idx][i] = 0; + } + for (i = 0; i < 16; i++) { + if (params->p.CUR_RPS[i] & 0x8000) + break; + if ((params->p.CUR_RPS[i] >> RPS_USED_BIT) & 1) { + int delt = + params->p.CUR_RPS[i] & + ((1 << (RPS_USED_BIT - 1)) - 1); + + if ((params->p.CUR_RPS[i] >> (RPS_USED_BIT - 1)) & 1) { + RefPicSetStCurr0[num_neg] = + pic->POC - ((1 << (RPS_USED_BIT - 1)) - + delt); + /* hevc_print(hevc, 0, + "RefPicSetStCurr0 %x %x %x\n", + RefPicSetStCurr0[num_neg], pic->POC, + (0x800-(params[i]&0x7ff))); */ + num_neg++; + } else { + RefPicSetStCurr1[num_pos] = pic->POC + delt; + /* hevc_print(hevc, 0, + "RefPicSetStCurr1 %d\n", + RefPicSetStCurr1[num_pos]); */ + num_pos++; + } + } + } + total_num = num_neg + num_pos; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "%s: curpoc %d slice_type %d, total %d ", + __func__, pic->POC, params->p.slice_type, total_num); + hevc_print_cont(hevc, 0, + "num_neg %d num_list0 %d num_list1 %d\n", + num_neg, num_ref_idx_l0_active, num_ref_idx_l1_active); + } + + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "HEVC Stream buf start "); + hevc_print_cont(hevc, 0, + "%x end %x wr %x rd %x lev %x ctl %x intctl %x\n", + READ_VREG(HEVC_STREAM_START_ADDR), + READ_VREG(HEVC_STREAM_END_ADDR), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR), + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_FIFO_CTL), + READ_VREG(HEVC_PARSER_INT_CONTROL)); + } + + if (total_num > 0) { + if (params->p.modification_flag & 0x1) { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, "ref0 POC (modification):"); + for (rIdx = 0; rIdx < num_ref_idx_l0_active; rIdx++) { + int cIdx = params->p.modification_list[rIdx]; + + pic->m_aiRefPOCList0[pic->slice_idx][rIdx] = + cIdx >= + num_neg ? RefPicSetStCurr1[cIdx - + num_neg] : + RefPicSetStCurr0[cIdx]; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, "%d ", + pic->m_aiRefPOCList0[pic-> + slice_idx] + [rIdx]); + } + } + } else { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, "ref0 POC:"); + for (rIdx = 0; rIdx < num_ref_idx_l0_active; rIdx++) { + int cIdx = rIdx % total_num; + + pic->m_aiRefPOCList0[pic->slice_idx][rIdx] = + cIdx >= + num_neg ? RefPicSetStCurr1[cIdx - + num_neg] : + RefPicSetStCurr0[cIdx]; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, "%d ", + pic->m_aiRefPOCList0[pic-> + slice_idx] + [rIdx]); + } + } + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, "\n"); + if (params->p.slice_type == B_SLICE) { + if (params->p.modification_flag & 0x2) { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "ref1 POC (modification):"); + for (rIdx = 0; rIdx < num_ref_idx_l1_active; + rIdx++) { + int cIdx; + + if (params->p.modification_flag & 0x1) { + cIdx = + params->p. + modification_list + [num_ref_idx_l0_active + + rIdx]; + } else { + cIdx = + params->p. + modification_list[rIdx]; + } + pic->m_aiRefPOCList1[pic-> + slice_idx][rIdx] = + cIdx >= + num_pos ? + RefPicSetStCurr0[cIdx - num_pos] + : RefPicSetStCurr1[cIdx]; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, "%d ", + pic-> + m_aiRefPOCList1[pic-> + slice_idx] + [rIdx]); + } + } + } else { + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, "ref1 POC:"); + for (rIdx = 0; rIdx < num_ref_idx_l1_active; + rIdx++) { + int cIdx = rIdx % total_num; + pic->m_aiRefPOCList1[pic-> + slice_idx][rIdx] = + cIdx >= + num_pos ? + RefPicSetStCurr0[cIdx - + num_pos] + : RefPicSetStCurr1[cIdx]; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, "%d ", + pic-> + m_aiRefPOCList1[pic-> + slice_idx] + [rIdx]); + } + } + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, "\n"); + } + } + /*set m_PIC */ + pic->slice_type = (params->p.slice_type == I_SLICE) ? 2 : + (params->p.slice_type == P_SLICE) ? 1 : + (params->p.slice_type == B_SLICE) ? 0 : 3; + pic->RefNum_L0 = num_ref_idx_l0_active; + pic->RefNum_L1 = num_ref_idx_l1_active; +} + +static void update_tile_info(struct hevc_state_s *hevc, int pic_width_cu, + int pic_height_cu, int sao_mem_unit, + union param_u *params) +{ + int i, j; + int start_cu_x, start_cu_y; + int sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu; + int sao_abv_size = sao_mem_unit * pic_width_cu; + + hevc->tile_enabled = params->p.tiles_enabled_flag & 1; + if (params->p.tiles_enabled_flag & 1) { + hevc->num_tile_col = params->p.num_tile_columns_minus1 + 1; + hevc->num_tile_row = params->p.num_tile_rows_minus1 + 1; + + if (hevc->num_tile_row > MAX_TILE_ROW_NUM + || hevc->num_tile_row <= 0) { + hevc->num_tile_row = 1; + hevc_print(hevc, 0, + "%s: num_tile_rows_minus1 (%d) error!!\n", + __func__, params->p.num_tile_rows_minus1); + } + if (hevc->num_tile_col > MAX_TILE_COL_NUM + || hevc->num_tile_col <= 0) { + hevc->num_tile_col = 1; + hevc_print(hevc, 0, + "%s: num_tile_columns_minus1 (%d) error!!\n", + __func__, params->p.num_tile_columns_minus1); + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "%s pic_w_cu %d pic_h_cu %d tile_enabled ", + __func__, pic_width_cu, pic_height_cu); + hevc_print_cont(hevc, 0, + "num_tile_col %d num_tile_row %d:\n", + hevc->num_tile_col, hevc->num_tile_row); + } + + if (params->p.tiles_enabled_flag & 2) { /* uniform flag */ + int w = pic_width_cu / hevc->num_tile_col; + int h = pic_height_cu / hevc->num_tile_row; + + start_cu_y = 0; + for (i = 0; i < hevc->num_tile_row; i++) { + start_cu_x = 0; + for (j = 0; j < hevc->num_tile_col; j++) { + if (j == (hevc->num_tile_col - 1)) { + hevc->m_tile[i][j].width = + pic_width_cu - + start_cu_x; + } else + hevc->m_tile[i][j].width = w; + if (i == (hevc->num_tile_row - 1)) { + hevc->m_tile[i][j].height = + pic_height_cu - + start_cu_y; + } else + hevc->m_tile[i][j].height = h; + hevc->m_tile[i][j].start_cu_x + = start_cu_x; + hevc->m_tile[i][j].start_cu_y + = start_cu_y; + hevc->m_tile[i][j].sao_vb_start_addr = + hevc->work_space_buf->sao_vb. + buf_start + j * sao_vb_size; + hevc->m_tile[i][j].sao_abv_start_addr = + hevc->work_space_buf->sao_abv. + buf_start + i * sao_abv_size; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, + "{y=%d, x=%d w %d h %d ", + i, j, hevc->m_tile[i][j].width, + hevc->m_tile[i][j].height); + hevc_print_cont(hevc, 0, + "start_x %d start_y %d ", + hevc->m_tile[i][j].start_cu_x, + hevc->m_tile[i][j].start_cu_y); + hevc_print_cont(hevc, 0, + "sao_vb_start 0x%x ", + hevc->m_tile[i][j]. + sao_vb_start_addr); + hevc_print_cont(hevc, 0, + "sao_abv_start 0x%x}\n", + hevc->m_tile[i][j]. + sao_abv_start_addr); + } + start_cu_x += hevc->m_tile[i][j].width; + + } + start_cu_y += hevc->m_tile[i][0].height; + } + } else { + start_cu_y = 0; + for (i = 0; i < hevc->num_tile_row; i++) { + start_cu_x = 0; + for (j = 0; j < hevc->num_tile_col; j++) { + if (j == (hevc->num_tile_col - 1)) { + hevc->m_tile[i][j].width = + pic_width_cu - + start_cu_x; + } else { + hevc->m_tile[i][j].width = + params->p.tile_width[j]; + } + if (i == (hevc->num_tile_row - 1)) { + hevc->m_tile[i][j].height = + pic_height_cu - + start_cu_y; + } else { + hevc->m_tile[i][j].height = + params-> + p.tile_height[i]; + } + hevc->m_tile[i][j].start_cu_x + = start_cu_x; + hevc->m_tile[i][j].start_cu_y + = start_cu_y; + hevc->m_tile[i][j].sao_vb_start_addr = + hevc->work_space_buf->sao_vb. + buf_start + j * sao_vb_size; + hevc->m_tile[i][j].sao_abv_start_addr = + hevc->work_space_buf->sao_abv. + buf_start + i * sao_abv_size; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print_cont(hevc, 0, + "{y=%d, x=%d w %d h %d ", + i, j, hevc->m_tile[i][j].width, + hevc->m_tile[i][j].height); + hevc_print_cont(hevc, 0, + "start_x %d start_y %d ", + hevc->m_tile[i][j].start_cu_x, + hevc->m_tile[i][j].start_cu_y); + hevc_print_cont(hevc, 0, + "sao_vb_start 0x%x ", + hevc->m_tile[i][j]. + sao_vb_start_addr); + hevc_print_cont(hevc, 0, + "sao_abv_start 0x%x}\n", + hevc->m_tile[i][j]. + sao_abv_start_addr); + + } + start_cu_x += hevc->m_tile[i][j].width; + } + start_cu_y += hevc->m_tile[i][0].height; + } + } + } else { + hevc->num_tile_col = 1; + hevc->num_tile_row = 1; + hevc->m_tile[0][0].width = pic_width_cu; + hevc->m_tile[0][0].height = pic_height_cu; + hevc->m_tile[0][0].start_cu_x = 0; + hevc->m_tile[0][0].start_cu_y = 0; + hevc->m_tile[0][0].sao_vb_start_addr = + hevc->work_space_buf->sao_vb.buf_start; + hevc->m_tile[0][0].sao_abv_start_addr = + hevc->work_space_buf->sao_abv.buf_start; + } +} + +static int get_tile_index(struct hevc_state_s *hevc, int cu_adr, + int pic_width_lcu) +{ + int cu_x; + int cu_y; + int tile_x = 0; + int tile_y = 0; + int i; + + if (pic_width_lcu == 0) { + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "%s Error, pic_width_lcu is 0, pic_w %d, pic_h %d\n", + __func__, hevc->pic_w, hevc->pic_h); + } + return -1; + } + cu_x = cu_adr % pic_width_lcu; + cu_y = cu_adr / pic_width_lcu; + if (hevc->tile_enabled) { + for (i = 0; i < hevc->num_tile_col; i++) { + if (cu_x >= hevc->m_tile[0][i].start_cu_x) + tile_x = i; + else + break; + } + for (i = 0; i < hevc->num_tile_row; i++) { + if (cu_y >= hevc->m_tile[i][0].start_cu_y) + tile_y = i; + else + break; + } + } + return (tile_x) | (tile_y << 8); +} + +static void print_scratch_error(int error_num) +{ +#if 0 + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + " ERROR : HEVC_ASSIST_SCRATCH_TEST Error : %d\n", + error_num); + } +#endif +} + +static void hevc_config_work_space_hw(struct hevc_state_s *hevc) +{ + struct BuffInfo_s *buf_spec = hevc->work_space_buf; + + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "%s %x %x %x %x %x %x %x %x %x %x %x %x\n", + __func__, + buf_spec->ipp.buf_start, + buf_spec->start_adr, + buf_spec->short_term_rps.buf_start, + buf_spec->vps.buf_start, + buf_spec->sps.buf_start, + buf_spec->pps.buf_start, + buf_spec->sao_up.buf_start, + buf_spec->swap_buf.buf_start, + buf_spec->swap_buf2.buf_start, + buf_spec->scalelut.buf_start, + buf_spec->dblk_para.buf_start, + buf_spec->dblk_data.buf_start); + WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); + if ((get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) == 0) + WRITE_VREG(HEVC_RPM_BUFFER, (u32)hevc->rpm_phy_addr); + WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start); + WRITE_VREG(HEVC_VPS_BUFFER, buf_spec->vps.buf_start); + WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start); + WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); + WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); + if (mmu_enable) + WRITE_VREG(H265_MMU_MAP_BUFFER, hevc->frame_mmu_map_phy_addr); + else + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, + buf_spec->swap_buf.buf_start); + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start); + WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); + /* cfg_p_addr */ + WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); + /* cfg_d_addr */ + WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); + + if (get_dbg_flag(hevc) & H265_DEBUG_UCODE) + WRITE_VREG(LMEM_DUMP_ADR, (u32)hevc->lmem_phy_addr); + +} + +static void hevc_init_decoder_hw(struct hevc_state_s *hevc, + int decode_pic_begin, int decode_pic_num) +{ + unsigned int data32; + int i; + +#if 1 + /* m8baby test1902 */ + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "[test.c] Test Parser Register Read/Write\n"); + data32 = READ_VREG(HEVC_PARSER_VERSION); + if (data32 != 0x00010001) { + print_scratch_error(25); + return; + } + WRITE_VREG(HEVC_PARSER_VERSION, 0x5a5a55aa); + data32 = READ_VREG(HEVC_PARSER_VERSION); + if (data32 != 0x5a5a55aa) { + print_scratch_error(26); + return; + } +#if 0 + /* test Parser Reset */ + /* reset iqit to start mem init again */ + WRITE_VREG(DOS_SW_RESET3, (1 << 14) | + (1 << 3) /* reset_whole parser */ + ); + WRITE_VREG(DOS_SW_RESET3, 0); /* clear reset_whole parser */ + data32 = READ_VREG(HEVC_PARSER_VERSION); + if (data32 != 0x00010001) + hevc_print(hevc, 0, + "Test Parser Fatal Error\n"); +#endif + /* reset iqit to start mem init again */ + WRITE_VREG(DOS_SW_RESET3, (1 << 14) + ); + CLEAR_VREG_MASK(HEVC_CABAC_CONTROL, 1); + CLEAR_VREG_MASK(HEVC_PARSER_CORE_CONTROL, 1); + +#endif + + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "[test.c] Enable BitStream Fetch\n"); + ; + if (!hevc->m_ins_flag) { + data32 = READ_VREG(HEVC_STREAM_CONTROL); + data32 = data32 | (1 << 0); /* stream_fetch_enable */ + WRITE_VREG(HEVC_STREAM_CONTROL, data32); + } + data32 = READ_VREG(HEVC_SHIFT_STARTCODE); + if (data32 != 0x00000100) { + print_scratch_error(29); + return; + } + data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); + if (data32 != 0x00000300) { + print_scratch_error(30); + return; + } + WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); + WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); + data32 = READ_VREG(HEVC_SHIFT_STARTCODE); + if (data32 != 0x12345678) { + print_scratch_error(31); + return; + } + data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); + if (data32 != 0x9abcdef0) { + print_scratch_error(32); + return; + } + WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100); + WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000300); + + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "[test.c] Enable HEVC Parser Interrupt\n"); + data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); + data32 &= 0x03ffffff; + data32 = data32 | (3 << 29) | (2 << 26) | (1 << 24) + | /* stream_buffer_empty_int_amrisc_enable */ + (1 << 22) | /* stream_fifo_empty_int_amrisc_enable*/ + (1 << 7) | /* dec_done_int_cpu_enable */ + (1 << 4) | /* startcode_found_int_cpu_enable */ + (0 << 3) | /* startcode_found_int_amrisc_enable */ + (1 << 0) /* parser_int_enable */ + ; + WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); + + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "[test.c] Enable HEVC Parser Shift\n"); + + data32 = READ_VREG(HEVC_SHIFT_STATUS); + data32 = data32 | (1 << 1) | /* emulation_check_on */ + (1 << 0) /* startcode_check_on */ + ; + WRITE_VREG(HEVC_SHIFT_STATUS, data32); + + WRITE_VREG(HEVC_SHIFT_CONTROL, (3 << 6) |/* sft_valid_wr_position */ + (2 << 4) | /* emulate_code_length_sub_1 */ + (2 << 1) | /* start_code_length_sub_1 */ + (1 << 0) /* stream_shift_enable */ + ); + + WRITE_VREG(HEVC_CABAC_CONTROL, (1 << 0) /* cabac_enable */ + ); + /* hevc_parser_core_clk_en */ + WRITE_VREG(HEVC_PARSER_CORE_CONTROL, (1 << 0) + ); + + WRITE_VREG(HEVC_DEC_STATUS_REG, 0); + + /* Initial IQIT_SCALELUT memory -- just to avoid X in simulation */ + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[test.c] Initial IQIT_SCALELUT memory --"); + hevc_print_cont(hevc, 0, + " just to avoid X in simulation...\n"); + } + WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0); /* cfg_p_addr */ + for (i = 0; i < 1024; i++) + WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); + +#ifdef ENABLE_SWAP_TEST + WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); +#endif + + /*WRITE_VREG(HEVC_DECODE_PIC_BEGIN_REG, 0);*/ + /*WRITE_VREG(HEVC_DECODE_PIC_NUM_REG, 0xffffffff);*/ + WRITE_VREG(HEVC_DECODE_SIZE, 0); + /*WRITE_VREG(HEVC_DECODE_COUNT, 0);*/ + /* Send parser_cmd */ + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "[test.c] SEND Parser Command ...\n"); + WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); + for (i = 0; i < PARSER_CMD_NUMBER; i++) + WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); + + WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); + + WRITE_VREG(HEVC_PARSER_IF_CONTROL, + /* (1 << 8) | // sao_sw_pred_enable */ + (1 << 5) | /* parser_sao_if_en */ + (1 << 2) | /* parser_mpred_if_en */ + (1 << 0) /* parser_scaler_if_en */ + ); + + /* Changed to Start MPRED in microcode */ + /* + hevc_print(hevc, 0, "[test.c] Start MPRED\n"); + WRITE_VREG(HEVC_MPRED_INT_STATUS, + (1<<31) + ); + */ + + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "[test.c] Reset IPP\n"); + WRITE_VREG(HEVCD_IPP_TOP_CNTL, (0 << 1) | /* enable ipp */ + (1 << 0) /* software reset ipp and mpp */ + ); + WRITE_VREG(HEVCD_IPP_TOP_CNTL, (1 << 1) | /* enable ipp */ + (0 << 0) /* software reset ipp and mpp */ + ); + + if (get_double_write_mode(hevc) & 0x10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, + 0x1 << 31 /*/Enable NV21 reference read mode for MC*/ + ); + +} + +static void decoder_hw_reset(void) +{ + int i; + unsigned int data32; + /* reset iqit to start mem init again */ + WRITE_VREG(DOS_SW_RESET3, (1 << 14) + ); + CLEAR_VREG_MASK(HEVC_CABAC_CONTROL, 1); + CLEAR_VREG_MASK(HEVC_PARSER_CORE_CONTROL, 1); + + data32 = READ_VREG(HEVC_STREAM_CONTROL); + data32 = data32 | (1 << 0) /* stream_fetch_enable */ + ; + WRITE_VREG(HEVC_STREAM_CONTROL, data32); + + data32 = READ_VREG(HEVC_SHIFT_STARTCODE); + if (data32 != 0x00000100) { + print_scratch_error(29); + return; + } + data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); + if (data32 != 0x00000300) { + print_scratch_error(30); + return; + } + WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); + WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); + data32 = READ_VREG(HEVC_SHIFT_STARTCODE); + if (data32 != 0x12345678) { + print_scratch_error(31); + return; + } + data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); + if (data32 != 0x9abcdef0) { + print_scratch_error(32); + return; + } + WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100); + WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000300); + + data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); + data32 &= 0x03ffffff; + data32 = data32 | (3 << 29) | (2 << 26) | (1 << 24) + | /* stream_buffer_empty_int_amrisc_enable */ + (1 << 22) | /*stream_fifo_empty_int_amrisc_enable */ + (1 << 7) | /* dec_done_int_cpu_enable */ + (1 << 4) | /* startcode_found_int_cpu_enable */ + (0 << 3) | /* startcode_found_int_amrisc_enable */ + (1 << 0) /* parser_int_enable */ + ; + WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); + + data32 = READ_VREG(HEVC_SHIFT_STATUS); + data32 = data32 | (1 << 1) | /* emulation_check_on */ + (1 << 0) /* startcode_check_on */ + ; + WRITE_VREG(HEVC_SHIFT_STATUS, data32); + + WRITE_VREG(HEVC_SHIFT_CONTROL, (3 << 6) |/* sft_valid_wr_position */ + (2 << 4) | /* emulate_code_length_sub_1 */ + (2 << 1) | /* start_code_length_sub_1 */ + (1 << 0) /* stream_shift_enable */ + ); + + WRITE_VREG(HEVC_CABAC_CONTROL, (1 << 0) /* cabac_enable */ + ); + /* hevc_parser_core_clk_en */ + WRITE_VREG(HEVC_PARSER_CORE_CONTROL, (1 << 0) + ); + + /* Initial IQIT_SCALELUT memory -- just to avoid X in simulation */ + WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0); /* cfg_p_addr */ + for (i = 0; i < 1024; i++) + WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); + + /* Send parser_cmd */ + WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); + for (i = 0; i < PARSER_CMD_NUMBER; i++) + WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); + + WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); + + WRITE_VREG(HEVC_PARSER_IF_CONTROL, + /* (1 << 8) | // sao_sw_pred_enable */ + (1 << 5) | /* parser_sao_if_en */ + (1 << 2) | /* parser_mpred_if_en */ + (1 << 0) /* parser_scaler_if_en */ + ); + + WRITE_VREG(HEVCD_IPP_TOP_CNTL, (0 << 1) | /* enable ipp */ + (1 << 0) /* software reset ipp and mpp */ + ); + WRITE_VREG(HEVCD_IPP_TOP_CNTL, (1 << 1) | /* enable ipp */ + (0 << 0) /* software reset ipp and mpp */ + ); +} + +#ifdef CONFIG_HEVC_CLK_FORCED_ON +static void config_hevc_clk_forced_on(void) +{ + unsigned int rdata32; + /* IQIT */ + rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL); + WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2)); + + /* DBLK */ + rdata32 = READ_VREG(HEVC_DBLK_CFG0); + WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2)); + + /* SAO */ + rdata32 = READ_VREG(HEVC_SAO_CTRL1); + WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2)); + + /* MPRED */ + rdata32 = READ_VREG(HEVC_MPRED_CTRL1); + WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24)); + + /* PARSER */ + rdata32 = READ_VREG(HEVC_STREAM_CONTROL); + WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_SHIFT_CONTROL); + WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_CABAC_CONTROL); + WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13)); + rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL); + WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL); + WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL); + WRITE_VREG(HEVC_PARSER_IF_CONTROL, + rdata32 | (0x3 << 5) | (0x3 << 2) | (0x3 << 0)); + + /* IPP */ + rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG); + WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff); + + /* MCRCC */ + rdata32 = READ_VREG(HEVCD_MCRCC_CTL1); + WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3)); +} +#endif + +#ifdef MCRCC_ENABLE +static void config_mcrcc_axi_hw(struct hevc_state_s *hevc, int slice_type) +{ + unsigned int rdata32; + unsigned int rdata32_2; + int l0_cnt = 0; + int l1_cnt = 0x7fff; + if (get_double_write_mode(hevc) & 0x10) { + l0_cnt = hevc->cur_pic->RefNum_L0; + l1_cnt = hevc->cur_pic->RefNum_L1; + } + + WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc */ + + if (slice_type == 2) { /* I-PIC */ + /* remove reset -- disables clock */ + WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); + return; + } + + if (slice_type == 0) { /* B-PIC */ + /* Programme canvas0 */ + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (0 << 1) | 0); + rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32 = rdata32 & 0xffff; + rdata32 = rdata32 | (rdata32 << 16); + WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); + + /* Programme canvas1 */ + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (16 << 8) | (1 << 1) | 0); + rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32_2 = rdata32_2 & 0xffff; + rdata32_2 = rdata32_2 | (rdata32_2 << 16); + if (rdata32 == rdata32_2 && l1_cnt > 1) { + rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32_2 = rdata32_2 & 0xffff; + rdata32_2 = rdata32_2 | (rdata32_2 << 16); + } + WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); + } else { /* P-PIC */ + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (1 << 1) | 0); + rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32 = rdata32 & 0xffff; + rdata32 = rdata32 | (rdata32 << 16); + WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); + + if (l0_cnt == 1) { + WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); + } else { + /* Programme canvas1 */ + rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32 = rdata32 & 0xffff; + rdata32 = rdata32 | (rdata32 << 16); + WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); + } + } + /* enable mcrcc progressive-mode */ + WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); + return; +} +#endif + +static void config_title_hw(struct hevc_state_s *hevc, int sao_vb_size, + int sao_mem_unit) +{ + WRITE_VREG(HEVC_sao_mem_unit, sao_mem_unit); + WRITE_VREG(HEVC_SAO_ABV, hevc->work_space_buf->sao_abv.buf_start); + WRITE_VREG(HEVC_sao_vb_size, sao_vb_size); + WRITE_VREG(HEVC_SAO_VB, hevc->work_space_buf->sao_vb.buf_start); +} + +static void config_aux_buf(struct hevc_state_s *hevc) +{ + WRITE_VREG(HEVC_AUX_ADR, hevc->aux_phy_addr); + WRITE_VREG(HEVC_AUX_DATA_SIZE, + ((hevc->prefix_aux_size >> 4) << 16) | + (hevc->suffix_aux_size >> 4) + ); +} + +static void config_mpred_hw(struct hevc_state_s *hevc) +{ + int i; + unsigned int data32; + struct PIC_s *cur_pic = hevc->cur_pic; + struct PIC_s *col_pic = hevc->col_pic; + int AMVP_MAX_NUM_CANDS_MEM = 3; + int AMVP_MAX_NUM_CANDS = 2; + int NUM_CHROMA_MODE = 5; + int DM_CHROMA_IDX = 36; + int above_ptr_ctrl = 0; + int buffer_linear = 1; + int cu_size_log2 = 3; + + int mpred_mv_rd_start_addr; + int mpred_curr_lcu_x; + int mpred_curr_lcu_y; + int mpred_above_buf_start; + int mpred_mv_rd_ptr; + int mpred_mv_rd_ptr_p1; + int mpred_mv_rd_end_addr; + int MV_MEM_UNIT; + int mpred_mv_wr_ptr; + int *ref_poc_L0, *ref_poc_L1; + + int above_en; + int mv_wr_en; + int mv_rd_en; + int col_isIntra; + + if (hevc->slice_type != 2) { + above_en = 1; + mv_wr_en = 1; + mv_rd_en = 1; + col_isIntra = 0; + } else { + above_en = 1; + mv_wr_en = 1; + mv_rd_en = 0; + col_isIntra = 0; + } + + mpred_mv_rd_start_addr = col_pic->mpred_mv_wr_start_addr; + data32 = READ_VREG(HEVC_MPRED_CURR_LCU); + mpred_curr_lcu_x = data32 & 0xffff; + mpred_curr_lcu_y = (data32 >> 16) & 0xffff; + + MV_MEM_UNIT = + hevc->lcu_size_log2 == 6 ? 0x200 : hevc->lcu_size_log2 == + 5 ? 0x80 : 0x20; + mpred_mv_rd_ptr = + mpred_mv_rd_start_addr + (hevc->slice_addr * MV_MEM_UNIT); + + mpred_mv_rd_ptr_p1 = mpred_mv_rd_ptr + MV_MEM_UNIT; + mpred_mv_rd_end_addr = + mpred_mv_rd_start_addr + + ((hevc->lcu_x_num * hevc->lcu_y_num) * MV_MEM_UNIT); + + mpred_above_buf_start = hevc->work_space_buf->mpred_above.buf_start; + + mpred_mv_wr_ptr = + cur_pic->mpred_mv_wr_start_addr + + (hevc->slice_addr * MV_MEM_UNIT); + + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "cur pic index %d col pic index %d\n", cur_pic->index, + col_pic->index); + } + + WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, + cur_pic->mpred_mv_wr_start_addr); + WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, mpred_mv_rd_start_addr); + + data32 = ((hevc->lcu_x_num - hevc->tile_width_lcu) * MV_MEM_UNIT); + WRITE_VREG(HEVC_MPRED_MV_WR_ROW_JUMP, data32); + WRITE_VREG(HEVC_MPRED_MV_RD_ROW_JUMP, data32); + + data32 = READ_VREG(HEVC_MPRED_CTRL0); + data32 = (hevc->slice_type | + hevc->new_pic << 2 | + hevc->new_tile << 3 | + hevc->isNextSliceSegment << 4 | + hevc->TMVPFlag << 5 | + hevc->LDCFlag << 6 | + hevc->ColFromL0Flag << 7 | + above_ptr_ctrl << 8 | + above_en << 9 | + mv_wr_en << 10 | + mv_rd_en << 11 | + col_isIntra << 12 | + buffer_linear << 13 | + hevc->LongTerm_Curr << 14 | + hevc->LongTerm_Col << 15 | + hevc->lcu_size_log2 << 16 | + cu_size_log2 << 20 | hevc->plevel << 24); + WRITE_VREG(HEVC_MPRED_CTRL0, data32); + + data32 = READ_VREG(HEVC_MPRED_CTRL1); + data32 = ( +#if 0 + /* no set in m8baby test1902 */ + /* Don't override clk_forced_on , */ + (data32 & (0x1 << 24)) | +#endif + hevc->MaxNumMergeCand | + AMVP_MAX_NUM_CANDS << 4 | + AMVP_MAX_NUM_CANDS_MEM << 8 | + NUM_CHROMA_MODE << 12 | DM_CHROMA_IDX << 16); + WRITE_VREG(HEVC_MPRED_CTRL1, data32); + + data32 = (hevc->pic_w | hevc->pic_h << 16); + WRITE_VREG(HEVC_MPRED_PIC_SIZE, data32); + + data32 = ((hevc->lcu_x_num - 1) | (hevc->lcu_y_num - 1) << 16); + WRITE_VREG(HEVC_MPRED_PIC_SIZE_LCU, data32); + + data32 = (hevc->tile_start_lcu_x | hevc->tile_start_lcu_y << 16); + WRITE_VREG(HEVC_MPRED_TILE_START, data32); + + data32 = (hevc->tile_width_lcu | hevc->tile_height_lcu << 16); + WRITE_VREG(HEVC_MPRED_TILE_SIZE_LCU, data32); + + data32 = (hevc->RefNum_L0 | hevc->RefNum_L1 << 8 | 0 + /* col_RefNum_L0<<16| */ + /* col_RefNum_L1<<24 */ + ); + WRITE_VREG(HEVC_MPRED_REF_NUM, data32); + + data32 = (hevc->LongTerm_Ref); + WRITE_VREG(HEVC_MPRED_LT_REF, data32); + + data32 = 0; + for (i = 0; i < hevc->RefNum_L0; i++) + data32 = data32 | (1 << i); + WRITE_VREG(HEVC_MPRED_REF_EN_L0, data32); + + data32 = 0; + for (i = 0; i < hevc->RefNum_L1; i++) + data32 = data32 | (1 << i); + WRITE_VREG(HEVC_MPRED_REF_EN_L1, data32); + + WRITE_VREG(HEVC_MPRED_CUR_POC, hevc->curr_POC); + WRITE_VREG(HEVC_MPRED_COL_POC, hevc->Col_POC); + + /* below MPRED Ref_POC_xx_Lx registers must follow Ref_POC_xx_L0 -> + Ref_POC_xx_L1 in pair write order!!! */ + ref_poc_L0 = &(cur_pic->m_aiRefPOCList0[cur_pic->slice_idx][0]); + ref_poc_L1 = &(cur_pic->m_aiRefPOCList1[cur_pic->slice_idx][0]); + + WRITE_VREG(HEVC_MPRED_L0_REF00_POC, ref_poc_L0[0]); + WRITE_VREG(HEVC_MPRED_L1_REF00_POC, ref_poc_L1[0]); + + WRITE_VREG(HEVC_MPRED_L0_REF01_POC, ref_poc_L0[1]); + WRITE_VREG(HEVC_MPRED_L1_REF01_POC, ref_poc_L1[1]); + + WRITE_VREG(HEVC_MPRED_L0_REF02_POC, ref_poc_L0[2]); + WRITE_VREG(HEVC_MPRED_L1_REF02_POC, ref_poc_L1[2]); + + WRITE_VREG(HEVC_MPRED_L0_REF03_POC, ref_poc_L0[3]); + WRITE_VREG(HEVC_MPRED_L1_REF03_POC, ref_poc_L1[3]); + + WRITE_VREG(HEVC_MPRED_L0_REF04_POC, ref_poc_L0[4]); + WRITE_VREG(HEVC_MPRED_L1_REF04_POC, ref_poc_L1[4]); + + WRITE_VREG(HEVC_MPRED_L0_REF05_POC, ref_poc_L0[5]); + WRITE_VREG(HEVC_MPRED_L1_REF05_POC, ref_poc_L1[5]); + + WRITE_VREG(HEVC_MPRED_L0_REF06_POC, ref_poc_L0[6]); + WRITE_VREG(HEVC_MPRED_L1_REF06_POC, ref_poc_L1[6]); + + WRITE_VREG(HEVC_MPRED_L0_REF07_POC, ref_poc_L0[7]); + WRITE_VREG(HEVC_MPRED_L1_REF07_POC, ref_poc_L1[7]); + + WRITE_VREG(HEVC_MPRED_L0_REF08_POC, ref_poc_L0[8]); + WRITE_VREG(HEVC_MPRED_L1_REF08_POC, ref_poc_L1[8]); + + WRITE_VREG(HEVC_MPRED_L0_REF09_POC, ref_poc_L0[9]); + WRITE_VREG(HEVC_MPRED_L1_REF09_POC, ref_poc_L1[9]); + + WRITE_VREG(HEVC_MPRED_L0_REF10_POC, ref_poc_L0[10]); + WRITE_VREG(HEVC_MPRED_L1_REF10_POC, ref_poc_L1[10]); + + WRITE_VREG(HEVC_MPRED_L0_REF11_POC, ref_poc_L0[11]); + WRITE_VREG(HEVC_MPRED_L1_REF11_POC, ref_poc_L1[11]); + + WRITE_VREG(HEVC_MPRED_L0_REF12_POC, ref_poc_L0[12]); + WRITE_VREG(HEVC_MPRED_L1_REF12_POC, ref_poc_L1[12]); + + WRITE_VREG(HEVC_MPRED_L0_REF13_POC, ref_poc_L0[13]); + WRITE_VREG(HEVC_MPRED_L1_REF13_POC, ref_poc_L1[13]); + + WRITE_VREG(HEVC_MPRED_L0_REF14_POC, ref_poc_L0[14]); + WRITE_VREG(HEVC_MPRED_L1_REF14_POC, ref_poc_L1[14]); + + WRITE_VREG(HEVC_MPRED_L0_REF15_POC, ref_poc_L0[15]); + WRITE_VREG(HEVC_MPRED_L1_REF15_POC, ref_poc_L1[15]); + + if (hevc->new_pic) { + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, mpred_above_buf_start); + WRITE_VREG(HEVC_MPRED_MV_WPTR, mpred_mv_wr_ptr); + /* WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr); */ + WRITE_VREG(HEVC_MPRED_MV_RPTR, mpred_mv_rd_start_addr); + } else if (!hevc->isNextSliceSegment) { + /* WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr_p1); */ + WRITE_VREG(HEVC_MPRED_MV_RPTR, mpred_mv_rd_ptr); + } + + WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, mpred_mv_rd_end_addr); +} + +static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) +{ + unsigned int data32, data32_2; + int misc_flag0 = hevc->misc_flag0; + int slice_deblocking_filter_disabled_flag = 0; + + int mc_buffer_size_u_v = + hevc->lcu_total * hevc->lcu_size * hevc->lcu_size / 2; + int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; + struct PIC_s *cur_pic = hevc->cur_pic; + + data32 = READ_VREG(HEVC_SAO_CTRL0); + data32 &= (~0xf); + data32 |= hevc->lcu_size_log2; + WRITE_VREG(HEVC_SAO_CTRL0, data32); + + data32 = (hevc->pic_w | hevc->pic_h << 16); + WRITE_VREG(HEVC_SAO_PIC_SIZE, data32); + + data32 = ((hevc->lcu_x_num - 1) | (hevc->lcu_y_num - 1) << 16); + WRITE_VREG(HEVC_SAO_PIC_SIZE_LCU, data32); + + if (hevc->new_pic) + WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); +#ifdef LOSLESS_COMPRESS_MODE +/*SUPPORT_10BIT*/ + if ((get_double_write_mode(hevc) & 0x10) == 0) { + data32 = READ_VREG(HEVC_SAO_CTRL5); + data32 &= (~(0xff << 16)); + if (get_double_write_mode(hevc) != 1) + data32 |= (0xff<<16); + if (hevc->mem_saving_mode == 1) + data32 |= (1 << 9); + else + data32 &= ~(1 << 9); + if (workaround_enable & 1) + data32 |= (1 << 7); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + } + data32 = cur_pic->mc_y_adr; + if (get_double_write_mode(hevc)) + WRITE_VREG(HEVC_SAO_Y_START_ADDR, cur_pic->dw_y_adr); + + if ((get_double_write_mode(hevc) & 0x10) == 0) + WRITE_VREG(HEVC_CM_BODY_START_ADDR, data32); + + if (mmu_enable) + WRITE_VREG(HEVC_CM_HEADER_START_ADDR, cur_pic->header_adr); +#else + data32 = cur_pic->mc_y_adr; + WRITE_VREG(HEVC_SAO_Y_START_ADDR, data32); +#endif + data32 = (mc_buffer_size_u_v_h << 16) << 1; + WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); + +#ifdef LOSLESS_COMPRESS_MODE +/*SUPPORT_10BIT*/ + if (get_double_write_mode(hevc)) + WRITE_VREG(HEVC_SAO_C_START_ADDR, cur_pic->dw_u_v_adr); +#else + data32 = cur_pic->mc_u_v_adr; + WRITE_VREG(HEVC_SAO_C_START_ADDR, data32); +#endif + data32 = (mc_buffer_size_u_v_h << 16); + WRITE_VREG(HEVC_SAO_C_LENGTH, data32); + +#ifdef LOSLESS_COMPRESS_MODE +/*SUPPORT_10BIT*/ + if (get_double_write_mode(hevc)) { + WRITE_VREG(HEVC_SAO_Y_WPTR, cur_pic->dw_y_adr); + WRITE_VREG(HEVC_SAO_C_WPTR, cur_pic->dw_u_v_adr); + } +#else + /* multi tile to do... */ + data32 = cur_pic->mc_y_adr; + WRITE_VREG(HEVC_SAO_Y_WPTR, data32); + + data32 = cur_pic->mc_u_v_adr; + WRITE_VREG(HEVC_SAO_C_WPTR, data32); +#endif + /* DBLK CONFIG HERE */ + if (hevc->new_pic) { + data32 = (hevc->pic_w | hevc->pic_h << 16); + WRITE_VREG(HEVC_DBLK_CFG2, data32); + + if ((misc_flag0 >> PCM_ENABLE_FLAG_BIT) & 0x1) { + data32 = + ((misc_flag0 >> + PCM_LOOP_FILTER_DISABLED_FLAG_BIT) & + 0x1) << 3; + } else + data32 = 0; + data32 |= + (((params->p.pps_cb_qp_offset & 0x1f) << 4) | + ((params->p.pps_cr_qp_offset + & 0x1f) << + 9)); + data32 |= + (hevc->lcu_size == + 64) ? 0 : ((hevc->lcu_size == 32) ? 1 : 2); + + WRITE_VREG(HEVC_DBLK_CFG1, data32); + } +#if 0 + data32 = READ_VREG(HEVC_SAO_CTRL1); + data32 &= (~0x3000); + data32 |= (mem_map_mode << + 12);/* [13:12] axi_aformat, + 0-Linear, 1-32x32, 2-64x32 */ + WRITE_VREG(HEVC_SAO_CTRL1, data32); + + data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); + data32 &= (~0x30); + data32 |= (mem_map_mode << + 4); /* [5:4] -- address_format + 00:linear 01:32x32 10:64x32 */ + WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); +#else + /* m8baby test1902 */ + data32 = READ_VREG(HEVC_SAO_CTRL1); + data32 &= (~0x3000); + data32 |= (mem_map_mode << + 12); /* [13:12] axi_aformat, 0-Linear, + 1-32x32, 2-64x32 */ + data32 &= (~0xff0); + /* data32 |= 0x670; // Big-Endian per 64-bit */ + data32 |= endian; /* Big-Endian per 64-bit */ + data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ + if (get_double_write_mode(hevc) == 0) + data32 |= 0x2; /*disable double write*/ + else if (!mmu_enable && (get_double_write_mode(hevc) & 0x10)) + data32 |= 0x1; /*disable cm*/ + WRITE_VREG(HEVC_SAO_CTRL1, data32); + + if (get_double_write_mode(hevc) & 0x10) { + /* [23:22] dw_v1_ctrl + [21:20] dw_v0_ctrl + [19:18] dw_h1_ctrl + [17:16] dw_h0_ctrl + */ + data32 = READ_VREG(HEVC_SAO_CTRL5); + /*set them all 0 for H265_NV21 (no down-scale)*/ + data32 &= ~(0xff << 16); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + } + + data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); + data32 &= (~0x30); + /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ + data32 |= (mem_map_mode << + 4); + data32 &= (~0xF); + data32 |= 0xf; /* valid only when double write only */ + /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ + WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); +#endif + data32 = 0; + data32_2 = READ_VREG(HEVC_SAO_CTRL0); + data32_2 &= (~0x300); + /* slice_deblocking_filter_disabled_flag = 0; + ucode has handle it , so read it from ucode directly */ + if (hevc->tile_enabled) { + data32 |= + ((misc_flag0 >> + LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT) & + 0x1) << 0; + data32_2 |= + ((misc_flag0 >> + LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT) & + 0x1) << 8; + } + slice_deblocking_filter_disabled_flag = (misc_flag0 >> + SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & + 0x1; /* ucode has handle it,so read it from ucode directly */ + if ((misc_flag0 & (1 << DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT)) + && (misc_flag0 & (1 << DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT))) { + /* slice_deblocking_filter_disabled_flag = + (misc_flag0>>SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT)&0x1; + //ucode has handle it , so read it from ucode directly */ + data32 |= slice_deblocking_filter_disabled_flag << 2; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, + "(1,%x)", data32); + if (!slice_deblocking_filter_disabled_flag) { + data32 |= (params->p.slice_beta_offset_div2 & 0xf) << 3; + data32 |= (params->p.slice_tc_offset_div2 & 0xf) << 7; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, + "(2,%x)", data32); + } + } else { + data32 |= + ((misc_flag0 >> + PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & + 0x1) << 2; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, + "(3,%x)", data32); + if (((misc_flag0 >> PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & + 0x1) == 0) { + data32 |= (params->p.pps_beta_offset_div2 & 0xf) << 3; + data32 |= (params->p.pps_tc_offset_div2 & 0xf) << 7; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, + "(4,%x)", data32); + } + } + if ((misc_flag0 & (1 << PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT)) + && ((misc_flag0 & (1 << SLICE_SAO_LUMA_FLAG_BIT)) + || (misc_flag0 & (1 << SLICE_SAO_CHROMA_FLAG_BIT)) + || (!slice_deblocking_filter_disabled_flag))) { + data32 |= + ((misc_flag0 >> + SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) + & 0x1) << 1; + data32_2 |= + ((misc_flag0 >> + SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) + & 0x1) << 9; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, + "(5,%x)\n", data32); + } else { + data32 |= + ((misc_flag0 >> + PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) + & 0x1) << 1; + data32_2 |= + ((misc_flag0 >> + PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT) + & 0x1) << 9; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print_cont(hevc, 0, + "(6,%x)\n", data32); + } + WRITE_VREG(HEVC_DBLK_CFG9, data32); + WRITE_VREG(HEVC_SAO_CTRL0, data32_2); +} + +static void clear_used_by_display_flag(struct hevc_state_s *hevc) +{ + struct PIC_s *pic; + int i; + if (get_dbg_flag(hevc) & H265_DEBUG_NOT_USE_LAST_DISPBUF) + return; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic) + pic->used_by_display = 0; + } +} + +static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, + union param_u *rpm_param) +{ + struct PIC_s *new_pic = NULL; + struct PIC_s *pic; + /* recycle un-used pic */ + int i; + int ret; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if ((pic->used_by_display) && !mmu_enable + && ((READ_VCBUS_REG(AFBC_BODY_BADDR) << 4) != + pic->mc_y_adr)) + pic->used_by_display = 0; + if (pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 0 + && pic->used_by_display == 0) { + if (new_pic) { + if (pic->POC < new_pic->POC) + new_pic = pic; + } else + new_pic = pic; + } + } + + /*try to allocate more pic for new resolution*/ + if (re_config_pic_flag && new_pic == NULL) { + int ii; + + for (ii = 0; ii < MAX_REF_PIC_NUM; ii++) { + if (hevc->m_PIC[ii] == NULL || + hevc->m_PIC[ii]->index == -1) + break; + } + if (ii < MAX_REF_PIC_NUM) { + new_pic = hevc->m_PIC[ii]; + if (new_pic) { + memset(new_pic, 0, sizeof(struct PIC_s)); + new_pic->index = ii; + new_pic->BUF_index = -1; + } + } + } + /**/ + + if (new_pic == NULL) { + /* pr_info("Error: Buffer management, no free buffer\n"); */ + return new_pic; + } + + new_pic->referenced = 1; + if (new_pic->width != hevc->pic_w || + new_pic->height != hevc->pic_h) { + if (re_config_pic_flag) { + /* re config pic for new resolution */ + recycle_buf(hevc); + /* if(new_pic->BUF_index == -1){ */ + if (config_pic(hevc, new_pic, 0) < 0) { + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR_MORE) { + hevc_print(hevc, 0, + "Config_pic %d fail\n", + new_pic->index); + dump_pic_list(hevc); + } + new_pic->index = -1; + new_pic = NULL; + } else + init_pic_list_hw(hevc); + } + if (new_pic) { + new_pic->width = hevc->pic_w; + new_pic->height = hevc->pic_h; + set_canvas(hevc, new_pic); + } + } + if (new_pic) { + new_pic->decode_idx = hevc->decode_idx; + new_pic->slice_idx = 0; + new_pic->referenced = 1; + new_pic->output_mark = 0; + new_pic->recon_mark = 0; + new_pic->error_mark = 0; + /* new_pic->output_ready = 0; */ + new_pic->num_reorder_pic = rpm_param->p.sps_num_reorder_pics_0; + new_pic->losless_comp_body_size = hevc->losless_comp_body_size; + new_pic->POC = hevc->curr_POC; + new_pic->pic_struct = hevc->curr_pic_struct; + if (new_pic->aux_data_buf) + release_aux_data(hevc, new_pic); + } + + if (mmu_enable) { + ret = H265_alloc_mmu(hevc, new_pic, rpm_param->p.bit_depth, + hevc->frame_mmu_map_addr); + /*pr_info("get pic index %x\n",new_pic->index);*/ + if (ret != 0) { + pr_err("can't alloc need mmu1,idx %d ret =%d\n", + new_pic->decode_idx, + ret); + return NULL; + } + + } + + return new_pic; +} + +static int get_display_pic_num(struct hevc_state_s *hevc) +{ + int i; + struct PIC_s *pic; + int num = 0; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || + pic->index == -1) + continue; + + if (pic->output_ready == 1) + num++; + } + return num; +} + +static void flush_output(struct hevc_state_s *hevc, struct PIC_s *pic) +{ + struct PIC_s *pic_display; + + if (pic) { + /*PB skip control */ + if (pic->error_mark == 0 && hevc->PB_skip_mode == 1) { + /* start decoding after first I */ + hevc->ignore_bufmgr_error |= 0x1; + } + if (hevc->ignore_bufmgr_error & 1) { + if (hevc->PB_skip_count_after_decoding > 0) + hevc->PB_skip_count_after_decoding--; + else { + /* start displaying */ + hevc->ignore_bufmgr_error |= 0x2; + } + } + /**/ + if (pic->POC != INVALID_POC) { + pic->output_mark = 1; + pic->recon_mark = 1; + } + pic->recon_mark = 1; + } + do { + pic_display = output_pic(hevc, 1); + + if (pic_display) { + pic_display->referenced = 0; + if ((pic_display->error_mark + && ((hevc->ignore_bufmgr_error & 0x2) == 0)) + || (get_dbg_flag(hevc) & + H265_DEBUG_DISPLAY_CUR_FRAME) + || (get_dbg_flag(hevc) & + H265_DEBUG_NO_DISPLAY)) { + pic_display->output_ready = 0; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] Display: POC %d, ", + pic_display->POC); + hevc_print_cont(hevc, 0, + "decoding index %d ==> ", + pic_display->decode_idx); + hevc_print_cont(hevc, 0, + "Debug mode or error, recycle it\n"); + } + } else { + if (i_only_flag & 0x1 + && pic_display->slice_type != 2) + pic_display->output_ready = 0; + else { + prepare_display_buf(hevc, pic_display); + if (get_dbg_flag(hevc) + & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] flush Display: POC %d, ", + pic_display->POC); + hevc_print_cont(hevc, 0, + "decoding index %d\n", + pic_display->decode_idx); + } + } + } + } + } while (pic_display); +} + +static void set_aux_data(struct hevc_state_s *hevc, + struct PIC_s *pic, unsigned char suffix_flag) +{ + int i; + unsigned short *aux_adr; + unsigned size_reg_val = + READ_VREG(HEVC_AUX_DATA_SIZE); + unsigned aux_count = 0; + int aux_size = 0; + if (suffix_flag) { + aux_adr = (unsigned short *) + (hevc->aux_addr + + hevc->prefix_aux_size); + aux_count = + ((size_reg_val & 0xffff) << 4) + >> 1; + aux_size = + hevc->suffix_aux_size; + } else { + aux_adr = + (unsigned short *)hevc->aux_addr; + aux_count = + ((size_reg_val >> 16) << 4) + >> 1; + aux_size = + hevc->prefix_aux_size; + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { + hevc_print(hevc, 0, "%s:old size %d count %d,suf %d\r\n", + __func__, pic->aux_data_size, aux_count, suffix_flag); + } + if (aux_size > 0 && aux_count > 0) { + int heads_size = 0; + int new_size; + char *new_buf; + for (i = 0; i < aux_count; i++) { + unsigned char tag = aux_adr[i] >> 8; + if (tag != 0 && tag != 0xff) + heads_size += 8; + } + new_size = pic->aux_data_size + aux_count + heads_size; + new_buf = krealloc(pic->aux_data_buf, + new_size, + GFP_KERNEL); + if (new_buf) { + unsigned char *p = + new_buf + + pic->aux_data_size; + unsigned char *h = p; + int h_bytes = 8; + int len = 0; + int padding_len = 0; + pic->aux_data_buf = new_buf; + pic->aux_data_size += (aux_count + heads_size); + for (i = 0; i < aux_count; i += 4) { + int ii; + unsigned char tag = aux_adr[i + 3] >> 8; + if (tag != 0 && tag != 0xff) { + if (i > 0) { + h[0] = (len >> 24) & 0xff; + h[1] = (len >> 16) & 0xff; + h[2] = (len >> 8) & 0xff; + h[3] = (len >> 0) & 0xff; + h[6] = (padding_len >> 8) + & 0xff; + h[7] = (padding_len) & 0xff; + h += (len + 8); + h_bytes += 8; + len = 0; + padding_len = 0; + } + h[4] = tag; + h[5] = 0; + h[6] = 0; + h[7] = 0; + } + for (ii = 0; ii < 4; ii++) { + unsigned short aa = + aux_adr[i + 3 + - ii]; + p[h_bytes + i + ii] = + aa & 0xff; + len++; + if ((aa >> 8) == 0xff) + padding_len++; + } + } + h[0] = (len >> 24) & 0xff; + h[1] = (len >> 16) & 0xff; + h[2] = (len >> 8) & 0xff; + h[3] = (len >> 0) & 0xff; + h[6] = (padding_len >> 8) & 0xff; + h[7] = (padding_len) & 0xff; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { + hevc_print(hevc, 0, + "aux: (size %d) suffix_flag %d\n", + pic->aux_data_size, suffix_flag); + for (i = 0; i < pic->aux_data_size; i++) { + hevc_print_cont(hevc, 0, + "%02x ", pic->aux_data_buf[i]); + if (((i + 1) & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + } + hevc_print_cont(hevc, 0, "\n"); + } + + } + } + +} + +static void release_aux_data(struct hevc_state_s *hevc, + struct PIC_s *pic) +{ + kfree(pic->aux_data_buf); + pic->aux_data_buf = NULL; + pic->aux_data_size = 0; +} + +static inline void hevc_pre_pic(struct hevc_state_s *hevc, + struct PIC_s *pic) +{ + + /* prev pic */ + /*if (hevc->curr_POC != 0) {*/ + if (hevc->m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR + && hevc->m_nalUnitType != + NAL_UNIT_CODED_SLICE_IDR_N_LP) { + struct PIC_s *pic_display; + + pic = get_pic_by_POC(hevc, hevc->iPrevPOC); + if (pic && (pic->POC != INVALID_POC)) { + /*PB skip control */ + if (pic->error_mark == 0 + && hevc->PB_skip_mode == 1) { + /* start decoding after + first I */ + hevc->ignore_bufmgr_error |= 0x1; + } + if (hevc->ignore_bufmgr_error & 1) { + if (hevc->PB_skip_count_after_decoding > 0) { + hevc->PB_skip_count_after_decoding--; + } else { + /* start displaying */ + hevc->ignore_bufmgr_error |= 0x2; + } + } + pic->output_mark = 1; + pic->recon_mark = 1; + } + do { + pic_display = output_pic(hevc, 0); + + if (pic_display) { + if ((pic_display->error_mark && + ((hevc->ignore_bufmgr_error & + 0x2) == 0)) + || (get_dbg_flag(hevc) & + H265_DEBUG_DISPLAY_CUR_FRAME) + || (get_dbg_flag(hevc) & + H265_DEBUG_NO_DISPLAY)) { + pic_display->output_ready = 0; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] Display: POC %d, ", + pic_display->POC); + hevc_print_cont(hevc, 0, + "decoding index %d ==> ", + pic_display-> + decode_idx); + hevc_print_cont(hevc, 0, + "Debug or err,recycle it\n"); + } + } else { + if (i_only_flag & 0x1 + && pic_display-> + slice_type != 2) { + pic_display->output_ready = 0; + } else { + prepare_display_buf + (hevc, + pic_display); + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] Display: POC %d, ", + pic_display->POC); + hevc_print_cont(hevc, 0, + "decoding index %d\n", + pic_display-> + decode_idx); + } + } + } + } + } while (pic_display); + } else { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] current pic is IDR, "); + hevc_print(hevc, 0, + "clear referenced flag of all buffers\n"); + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + dump_pic_list(hevc); + pic = get_pic_by_POC(hevc, hevc->iPrevPOC); + flush_output(hevc, pic); + } + +} + +static void check_pic_decoded_lcu_count(struct hevc_state_s *hevc) +{ + int current_lcu_idx = READ_VREG(HEVC_PARSER_LCU_START)&0xffffff; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "cur lcu idx = %d, (total %d)\n", + current_lcu_idx, hevc->lcu_total); + } + if ((error_handle_policy & 0x20) == 0 && hevc->cur_pic != NULL) { + if (hevc->first_pic_after_recover) { + if (current_lcu_idx != + ((hevc->lcu_x_num_pre*hevc->lcu_y_num_pre) - 1)) + hevc->cur_pic->error_mark = 1; + } else { + if (hevc->lcu_x_num_pre != 0 + && hevc->lcu_y_num_pre != 0 + && current_lcu_idx != 0 + && current_lcu_idx < + ((hevc->lcu_x_num_pre*hevc->lcu_y_num_pre) - 1)) + hevc->cur_pic->error_mark = 1; + } + if (hevc->cur_pic->error_mark) + hevc_print(hevc, 0, + "cur lcu idx = %d, (total %d), set error_mark\n", + current_lcu_idx, + hevc->lcu_x_num_pre*hevc->lcu_y_num_pre); + + } + hevc->lcu_x_num_pre = hevc->lcu_x_num; + hevc->lcu_y_num_pre = hevc->lcu_y_num; +} + +static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, + union param_u *rpm_param, + int decode_pic_begin) +{ +#ifdef CONFIG_AM_VDEC_DV + struct vdec_s *vdec = hw_to_vdec(hevc); +#endif + int i; + int lcu_x_num_div; + int lcu_y_num_div; + int Col_ref; + int dbg_skip_flag = 0; + + if (hevc->wait_buf == 0) { + hevc->sps_num_reorder_pics_0 = + rpm_param->p.sps_num_reorder_pics_0; + hevc->m_temporalId = rpm_param->p.m_temporalId; + hevc->m_nalUnitType = rpm_param->p.m_nalUnitType; + hevc->interlace_flag = + (rpm_param->p.profile_etc >> 2) & 0x1; + hevc->curr_pic_struct = + (rpm_param->p.sei_frame_field_info >> 3) & 0xf; + + if (interlace_enable == 0) + hevc->interlace_flag = 0; + if (interlace_enable & 0x100) + hevc->interlace_flag = interlace_enable & 0x1; + if (hevc->interlace_flag == 0) + hevc->curr_pic_struct = 0; + /* if(hevc->m_nalUnitType == NAL_UNIT_EOS){ */ + /* + *hevc->m_pocRandomAccess = MAX_INT; + * //add to fix RAP_B_Bossen_1 + */ + /* } */ + hevc->misc_flag0 = rpm_param->p.misc_flag0; + if (rpm_param->p.first_slice_segment_in_pic_flag == 0) { + hevc->slice_segment_addr = + rpm_param->p.slice_segment_address; + if (!rpm_param->p.dependent_slice_segment_flag) + hevc->slice_addr = hevc->slice_segment_addr; + } else { + hevc->slice_segment_addr = 0; + hevc->slice_addr = 0; + } + + hevc->iPrevPOC = hevc->curr_POC; + hevc->slice_type = (rpm_param->p.slice_type == I_SLICE) ? 2 : + (rpm_param->p.slice_type == P_SLICE) ? 1 : + (rpm_param->p.slice_type == B_SLICE) ? 0 : 3; + /* hevc->curr_predFlag_L0=(hevc->slice_type==2) ? 0:1; */ + /* hevc->curr_predFlag_L1=(hevc->slice_type==0) ? 1:0; */ + hevc->TMVPFlag = rpm_param->p.slice_temporal_mvp_enable_flag; + hevc->isNextSliceSegment = + rpm_param->p.dependent_slice_segment_flag ? 1 : 0; + if (hevc->pic_w != rpm_param->p.pic_width_in_luma_samples + || hevc->pic_h != + rpm_param->p.pic_height_in_luma_samples) { + hevc_print(hevc, 0, + "Pic Width/Height Change (%d,%d)=>(%d,%d), interlace %d\n", + hevc->pic_w, hevc->pic_h, + rpm_param->p.pic_width_in_luma_samples, + rpm_param->p.pic_height_in_luma_samples, + hevc->interlace_flag); + + hevc->pic_w = rpm_param->p.pic_width_in_luma_samples; + hevc->pic_h = rpm_param->p.pic_height_in_luma_samples; + hevc->frame_width = hevc->pic_w; + hevc->frame_height = hevc->pic_h; +#ifdef LOSLESS_COMPRESS_MODE + if (re_config_pic_flag == 0 && + (get_double_write_mode(hevc) & 0x10) == 0) + init_decode_head_hw(hevc); +#endif + } + + if (HEVC_SIZE < hevc->pic_w * hevc->pic_h) { + pr_info("over size : %u x %u.\n", + hevc->pic_w, hevc->pic_h); + if (!hevc->m_ins_flag) + debug |= (H265_DEBUG_DIS_LOC_ERROR_PROC | + H265_DEBUG_DIS_SYS_ERROR_PROC); + hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; + return -1; + } + + /* it will cause divide 0 error */ + if (hevc->pic_w == 0 || hevc->pic_h == 0) { + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "Fatal Error, pic_w = %d, pic_h = %d\n", + hevc->pic_w, hevc->pic_h); + } + return 3; + } + hevc->lcu_size = + 1 << (rpm_param->p.log2_min_coding_block_size_minus3 + + 3 + rpm_param-> + p.log2_diff_max_min_coding_block_size); + if (hevc->lcu_size == 0) { + hevc_print(hevc, 0, + "Error, lcu_size = 0 (%d,%d)\n", + rpm_param->p. + log2_min_coding_block_size_minus3, + rpm_param->p. + log2_diff_max_min_coding_block_size); + return 3; + } + hevc->lcu_size_log2 = log2i(hevc->lcu_size); + lcu_x_num_div = (hevc->pic_w / hevc->lcu_size); + lcu_y_num_div = (hevc->pic_h / hevc->lcu_size); + hevc->lcu_x_num = + ((hevc->pic_w % hevc->lcu_size) == + 0) ? lcu_x_num_div : lcu_x_num_div + 1; + hevc->lcu_y_num = + ((hevc->pic_h % hevc->lcu_size) == + 0) ? lcu_y_num_div : lcu_y_num_div + 1; + hevc->lcu_total = hevc->lcu_x_num * hevc->lcu_y_num; + + if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_IDR_N_LP) { + hevc->curr_POC = 0; + if ((hevc->m_temporalId - 1) == 0) + hevc->iPrevTid0POC = hevc->curr_POC; + } else { + int iMaxPOClsb = + 1 << (rpm_param->p. + log2_max_pic_order_cnt_lsb_minus4 + 4); + int iPrevPOClsb; + int iPrevPOCmsb; + int iPOCmsb; + int iPOClsb = rpm_param->p.POClsb; + + if (iMaxPOClsb == 0) { + hevc_print(hevc, 0, + "error iMaxPOClsb is 0\n"); + return 3; + } + + iPrevPOClsb = hevc->iPrevTid0POC % iMaxPOClsb; + iPrevPOCmsb = hevc->iPrevTid0POC - iPrevPOClsb; + + if ((iPOClsb < iPrevPOClsb) + && ((iPrevPOClsb - iPOClsb) >= + (iMaxPOClsb / 2))) + iPOCmsb = iPrevPOCmsb + iMaxPOClsb; + else if ((iPOClsb > iPrevPOClsb) + && ((iPOClsb - iPrevPOClsb) > + (iMaxPOClsb / 2))) + iPOCmsb = iPrevPOCmsb - iMaxPOClsb; + else + iPOCmsb = iPrevPOCmsb; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "iPrePOC%d iMaxPOClsb%d iPOCmsb%d iPOClsb%d\n", + hevc->iPrevTid0POC, iMaxPOClsb, iPOCmsb, + iPOClsb); + } + if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_BLANT + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_BLA_N_LP) { + /* For BLA picture types, POCmsb is set to 0. */ + iPOCmsb = 0; + } + hevc->curr_POC = (iPOCmsb + iPOClsb); + if ((hevc->m_temporalId - 1) == 0) + hevc->iPrevTid0POC = hevc->curr_POC; + else { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "m_temporalID is %d\n", + hevc->m_temporalId); + } + } + } + hevc->RefNum_L0 = + (rpm_param->p.num_ref_idx_l0_active > + MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : rpm_param->p. + num_ref_idx_l0_active; + hevc->RefNum_L1 = + (rpm_param->p.num_ref_idx_l1_active > + MAX_REF_ACTIVE) ? MAX_REF_ACTIVE : rpm_param->p. + num_ref_idx_l1_active; + + /* if(curr_POC==0x10) dump_lmem(); */ + + /* skip RASL pictures after CRA/BLA pictures */ + if (hevc->m_pocRandomAccess == MAX_INT) {/* first picture */ + if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA || + hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_BLANT + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_BLA_N_LP) + hevc->m_pocRandomAccess = hevc->curr_POC; + else + hevc->m_pocRandomAccess = -MAX_INT; + } else if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_BLANT + || hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_BLA_N_LP) + hevc->m_pocRandomAccess = hevc->curr_POC; + else if ((hevc->curr_POC < hevc->m_pocRandomAccess) && + (nal_skip_policy >= 3) && + (hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_RASL_N || + hevc->m_nalUnitType == + NAL_UNIT_CODED_SLICE_TFD)) { /* skip */ + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "RASL picture with POC %d < %d ", + hevc->curr_POC, hevc->m_pocRandomAccess); + hevc_print(hevc, 0, + "RandomAccess point POC), skip it\n"); + } + return 1; + } + + WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) | 0x2); + hevc->skip_flag = 0; + /**/ + /* if((iPrevPOC != curr_POC)){ */ + if (rpm_param->p.slice_segment_address == 0) { + struct PIC_s *pic; + + hevc->new_pic = 1; + check_pic_decoded_lcu_count(hevc); + /**/ if (use_cma == 0) { + if (hevc->pic_list_init_flag == 0) { + /*USE_BUF_BLOCK*/ + init_buf_list(hevc); + /**/ + init_pic_list(hevc); + init_pic_list_hw(hevc); + init_buf_spec(hevc); + hevc->pic_list_init_flag = 3; + } + } + hevc->first_pic_after_recover = 0; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) + dump_pic_list(hevc); + /* prev pic */ + hevc_pre_pic(hevc, pic); + /* + *update referenced of old pictures + *(cur_pic->referenced is 1 and not updated) + */ + apply_ref_pic_set(hevc, hevc->curr_POC, + rpm_param); + if (mmu_enable && hevc->cur_pic != NULL) { + if (!(hevc->cur_pic->error_mark + && ((hevc->ignore_bufmgr_error & 0x1) == 0))) { + long used_4k_num = + (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + decoder_mmu_box_free_idx_tail(hevc->mmu_box, + hevc->cur_pic->index, used_4k_num); + } + + } +#ifdef CONFIG_AM_VDEC_DV + if (vdec->master) { + struct hevc_state_s *hevc_ba = + (struct hevc_state_s *) + vdec->master->private; + if (hevc_ba->cur_pic != NULL) + hevc_ba->cur_pic->dv_enhance_exist = 1; + } + if (vdec->master == NULL && + vdec->slave == NULL) { + if (hevc->cur_pic != NULL) + set_aux_data(hevc, hevc->cur_pic, 1); + } +#else + if (hevc->cur_pic != NULL) + set_aux_data(hevc, hevc->cur_pic, 1); +#endif + /* new pic */ + hevc->cur_pic = get_new_pic(hevc, rpm_param); + if (hevc->cur_pic == NULL) { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + dump_pic_list(hevc); + hevc->wait_buf = 1; + return -1; + } +#ifdef CONFIG_AM_VDEC_DV + hevc->cur_pic->dv_enhance_exist = 0; + if (vdec->master == NULL && + vdec->slave == NULL) + set_aux_data(hevc, hevc->cur_pic, 0); +#else + set_aux_data(hevc, hevc->cur_pic, 0); +#endif + if (get_dbg_flag(hevc) & H265_DEBUG_DISPLAY_CUR_FRAME) { + hevc->cur_pic->output_ready = 1; + hevc->cur_pic->stream_offset = + READ_VREG(HEVC_SHIFT_BYTE_COUNT); + prepare_display_buf(hevc, hevc->cur_pic); + hevc->wait_buf = 2; + return -1; + } + } else { +#ifdef CONFIG_AM_VDEC_DV + if (vdec->master == NULL && + vdec->slave == NULL) { + if (hevc->cur_pic != NULL) { + set_aux_data(hevc, hevc->cur_pic, 1); + set_aux_data(hevc, hevc->cur_pic, 0); + } + } +#else + if (hevc->cur_pic != NULL) { + set_aux_data(hevc, hevc->cur_pic, 1); + set_aux_data(hevc, hevc->cur_pic, 0); + } +#endif + if (hevc->pic_list_init_flag != 3 + || hevc->cur_pic == NULL) { + /* make it dec from the first slice segment */ + return 3; + } + hevc->cur_pic->slice_idx++; + hevc->new_pic = 0; + } + } else { + if (hevc->wait_buf == 1) { + /* + *if (mmu_enable && hevc->cur_pic != NULL) { + * long used_4k_num = + * (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + * decoder_mmu_box_free_idx_tail(hevc->mmu_box, + * hevc->cur_pic->index, used_4k_num); + * + * } + */ + hevc->cur_pic = get_new_pic(hevc, rpm_param); + if (hevc->cur_pic == NULL) + return -1; + +#ifdef CONFIG_AM_VDEC_DV + hevc->cur_pic->dv_enhance_exist = 0; + if (vdec->master == NULL && + vdec->slave == NULL) + set_aux_data(hevc, hevc->cur_pic, 0); +#else + set_aux_data(hevc, hevc->cur_pic, 0); +#endif + hevc->wait_buf = 0; + } else if (hevc->wait_buf == + 2) { + if (get_display_pic_num(hevc) > + 1) + return -1; + hevc->wait_buf = 0; + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) + dump_pic_list(hevc); + } + + if (hevc->new_pic) { +#if 1 + /*SUPPORT_10BIT*/ + int sao_mem_unit = + (hevc->lcu_size == 16 ? 9 : + hevc->lcu_size == + 32 ? 14 : 24) << 4; +#else + int sao_mem_unit = ((hevc->lcu_size / 8) * 2 + 4) << 4; +#endif + int pic_height_cu = + (hevc->pic_h + hevc->lcu_size - 1) / hevc->lcu_size; + int pic_width_cu = + (hevc->pic_w + hevc->lcu_size - 1) / hevc->lcu_size; + int sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu; + + /* int sao_abv_size = sao_mem_unit*pic_width_cu; */ + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "==>%s dec idx %d, struct %d interlace %d\n", + __func__, + hevc->decode_idx, + hevc->curr_pic_struct, + hevc->interlace_flag); + } + if (dbg_skip_decode_index != 0 && + hevc->decode_idx == dbg_skip_decode_index) + dbg_skip_flag = 1; + + hevc->decode_idx++; + update_tile_info(hevc, pic_width_cu, pic_height_cu, + sao_mem_unit, rpm_param); + + config_title_hw(hevc, sao_vb_size, sao_mem_unit); + } + + if (hevc->iPrevPOC != hevc->curr_POC) { + hevc->new_tile = 1; + hevc->tile_x = 0; + hevc->tile_y = 0; + hevc->tile_y_x = 0; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "new_tile (new_pic) tile_x=%d, tile_y=%d\n", + hevc->tile_x, hevc->tile_y); + } + } else if (hevc->tile_enabled) { + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "slice_segment_address is %d\n", + rpm_param->p.slice_segment_address); + } + hevc->tile_y_x = + get_tile_index(hevc, rpm_param->p.slice_segment_address, + (hevc->pic_w + + hevc->lcu_size - + 1) / hevc->lcu_size); + if (hevc->tile_y_x != (hevc->tile_x | (hevc->tile_y << 8))) { + hevc->new_tile = 1; + hevc->tile_x = hevc->tile_y_x & 0xff; + hevc->tile_y = (hevc->tile_y_x >> 8) & 0xff; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "new_tile seg adr %d tile_x=%d, tile_y=%d\n", + rpm_param->p.slice_segment_address, + hevc->tile_x, hevc->tile_y); + } + } else + hevc->new_tile = 0; + } else + hevc->new_tile = 0; + + if (hevc->new_tile) { + hevc->tile_start_lcu_x = + hevc->m_tile[hevc->tile_y][hevc->tile_x].start_cu_x; + hevc->tile_start_lcu_y = + hevc->m_tile[hevc->tile_y][hevc->tile_x].start_cu_y; + hevc->tile_width_lcu = + hevc->m_tile[hevc->tile_y][hevc->tile_x].width; + hevc->tile_height_lcu = + hevc->m_tile[hevc->tile_y][hevc->tile_x].height; + } + + set_ref_pic_list(hevc, rpm_param); + + Col_ref = rpm_param->p.collocated_ref_idx; + + hevc->LDCFlag = 0; + if (rpm_param->p.slice_type != I_SLICE) { + hevc->LDCFlag = 1; + for (i = 0; (i < hevc->RefNum_L0) && hevc->LDCFlag; i++) { + if (hevc->cur_pic-> + m_aiRefPOCList0[hevc->cur_pic->slice_idx][i] > + hevc->curr_POC) + hevc->LDCFlag = 0; + } + if (rpm_param->p.slice_type == B_SLICE) { + for (i = 0; (i < hevc->RefNum_L1) + && hevc->LDCFlag; i++) { + if (hevc->cur_pic-> + m_aiRefPOCList1[hevc->cur_pic-> + slice_idx][i] > + hevc->curr_POC) + hevc->LDCFlag = 0; + } + } + } + + hevc->ColFromL0Flag = rpm_param->p.collocated_from_l0_flag; + + hevc->plevel = + rpm_param->p.log2_parallel_merge_level; + hevc->MaxNumMergeCand = 5 - rpm_param->p.five_minus_max_num_merge_cand; + + hevc->LongTerm_Curr = 0; /* to do ... */ + hevc->LongTerm_Col = 0; /* to do ... */ + + hevc->list_no = 0; + if (rpm_param->p.slice_type == B_SLICE) + hevc->list_no = 1 - hevc->ColFromL0Flag; + if (hevc->list_no == 0) { + if (Col_ref < hevc->RefNum_L0) { + hevc->Col_POC = + hevc->cur_pic->m_aiRefPOCList0[hevc->cur_pic-> + slice_idx][Col_ref]; + } else + hevc->Col_POC = INVALID_POC; + } else { + if (Col_ref < hevc->RefNum_L1) { + hevc->Col_POC = + hevc->cur_pic->m_aiRefPOCList1[hevc->cur_pic-> + slice_idx][Col_ref]; + } else + hevc->Col_POC = INVALID_POC; + } + + hevc->LongTerm_Ref = 0; /* to do ... */ + + if (hevc->slice_type != 2) { + /* if(i_only_flag==1){ */ + /* return 0xf; */ + /* } */ + + if (hevc->Col_POC != INVALID_POC) { + hevc->col_pic = get_ref_pic_by_POC(hevc, hevc->Col_POC); + if (hevc->col_pic == NULL) { + hevc->cur_pic->error_mark = 1; + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "WRONG,fail to get the pic Col_POC\n"); + } + } else if (hevc->col_pic->error_mark) { + hevc->cur_pic->error_mark = 1; + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "WRONG, Col_POC error_mark is 1\n"); + } + } + + if (hevc->cur_pic->error_mark + && ((hevc->ignore_bufmgr_error & 0x1) == 0)) { + return 2; + } + } else + hevc->col_pic = hevc->cur_pic; + } /* */ + if (hevc->col_pic == NULL) + hevc->col_pic = hevc->cur_pic; +#ifdef BUFFER_MGR_ONLY + return 0xf; +#else + if ((decode_pic_begin > 0 && hevc->decode_idx <= decode_pic_begin) + || (dbg_skip_flag)) + return 0xf; +#endif + + config_mc_buffer(hevc, hevc->cur_pic); + + if (hevc->cur_pic->error_mark + && ((hevc->ignore_bufmgr_error & 0x1) == 0)) { + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "Discard this picture index %d\n", + hevc->cur_pic->index); + return 2; + } +#ifdef MCRCC_ENABLE + config_mcrcc_axi_hw(hevc, hevc->cur_pic->slice_type); +#endif + config_mpred_hw(hevc); + + config_sao_hw(hevc, rpm_param); + + if ((hevc->slice_type != 2) && (i_only_flag & 0x2)) + return 0xf; + + return 0; +} + + + +static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, + unsigned short bit_depth, unsigned int *mmu_index_adr) { + int cur_buf_idx = new_pic->index; + int bit_depth_10 = (bit_depth != 0x00); + int picture_size; + int cur_mmu_4k_number; + + picture_size = compute_losless_comp_body_size(new_pic->width, + new_pic->height, !bit_depth_10); + cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12); + + /* + *pr_info("alloc_mmu cur_idx : %d picture_size : %d mmu_4k_number : %d\r\n", +* cur_buf_idx, picture_size, cur_mmu_4k_number); +*/ + return decoder_mmu_box_alloc_idx( + hevc->mmu_box, + cur_buf_idx, + cur_mmu_4k_number, + mmu_index_adr); +} + + + + + + +/* +************************************************* +* +*h265 buffer management end +* +************************************************** +*/ +static struct hevc_state_s gHevc; + +static void hevc_local_uninit(struct hevc_state_s *hevc) +{ + hevc->rpm_ptr = NULL; + hevc->lmem_ptr = NULL; + + if (hevc->aux_addr) { + dma_unmap_single(amports_get_dma_device(), + hevc->aux_phy_addr, + hevc->prefix_aux_size + hevc->suffix_aux_size, + DMA_FROM_DEVICE); + kfree(hevc->aux_addr); + hevc->aux_addr = NULL; + } + if (hevc->rpm_addr) { + dma_unmap_single(amports_get_dma_device(), + hevc->rpm_phy_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); + kfree(hevc->rpm_addr); + hevc->rpm_addr = NULL; + } + if (hevc->lmem_addr) { + dma_unmap_single(amports_get_dma_device(), + hevc->lmem_phy_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); + kfree(hevc->lmem_addr); + hevc->lmem_addr = NULL; + } + + if (mmu_enable && hevc->frame_mmu_map_addr) { + if (hevc->frame_mmu_map_phy_addr) + dma_free_coherent(amports_get_dma_device(), + FRAME_MMU_MAP_SIZE, hevc->frame_mmu_map_addr, + hevc->frame_mmu_map_phy_addr); + + hevc->frame_mmu_map_addr = NULL; + } + + +} + +static int hevc_local_init(struct hevc_state_s *hevc) +{ + int ret = -1; + struct BuffInfo_s *cur_buf_info = NULL; + + memset(&hevc->param, 0, sizeof(union param_u)); + + cur_buf_info = &hevc->work_space_buf_store; +#ifdef SUPPORT_4K2K + memcpy(cur_buf_info, &amvh265_workbuff_spec[1], /* 4k2k work space */ + sizeof(struct BuffInfo_s)); +#else + memcpy(cur_buf_info, &amvh265_workbuff_spec[0], /* 1080p work space */ + sizeof(struct BuffInfo_s)); +#endif + cur_buf_info->start_adr = hevc->buf_start; + hevc->mc_buf_spec.buf_end = hevc->buf_start + hevc->buf_size; + init_buff_spec(hevc, cur_buf_info); + + + + hevc->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff) + & (~0xffff); + hevc->mc_buf_spec.buf_size = (hevc->mc_buf_spec.buf_end + - hevc->mc_buf_spec.buf_start); + + hevc_init_stru(hevc, cur_buf_info, &hevc->mc_buf_spec); + + hevc->bit_depth_luma = 8; + hevc->bit_depth_chroma = 8; + hevc->video_signal_type = 0; + bit_depth_luma = hevc->bit_depth_luma; + bit_depth_chroma = hevc->bit_depth_chroma; + video_signal_type = hevc->video_signal_type; + + if ((get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) == 0) { + hevc->rpm_addr = kmalloc(RPM_BUF_SIZE, GFP_KERNEL); + if (hevc->rpm_addr == NULL) { + pr_err("%s: failed to alloc rpm buffer\n", __func__); + return -1; + } + + hevc->rpm_phy_addr = dma_map_single(amports_get_dma_device(), + hevc->rpm_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + hevc->rpm_phy_addr)) { + pr_err("%s: failed to map rpm buffer\n", __func__); + kfree(hevc->rpm_addr); + hevc->rpm_addr = NULL; + return -1; + } + + hevc->rpm_ptr = hevc->rpm_addr; + } + + if (prefix_aux_buf_size > 0 || + suffix_aux_buf_size > 0) { + u32 aux_buf_size; + hevc->prefix_aux_size = AUX_BUF_ALIGN(prefix_aux_buf_size); + hevc->suffix_aux_size = AUX_BUF_ALIGN(suffix_aux_buf_size); + aux_buf_size = hevc->prefix_aux_size + hevc->suffix_aux_size; + hevc->aux_addr = kmalloc(aux_buf_size, GFP_KERNEL); + if (hevc->aux_addr == NULL) { + pr_err("%s: failed to alloc rpm buffer\n", __func__); + return -1; + } + + hevc->aux_phy_addr = dma_map_single(amports_get_dma_device(), + hevc->aux_addr, aux_buf_size, DMA_FROM_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + hevc->aux_phy_addr)) { + pr_err("%s: failed to map rpm buffer\n", __func__); + kfree(hevc->aux_addr); + hevc->aux_addr = NULL; + return -1; + } + } + + if (get_dbg_flag(hevc) & H265_DEBUG_UCODE) { + hevc->lmem_addr = kmalloc(LMEM_BUF_SIZE, GFP_KERNEL); + if (hevc->lmem_addr == NULL) { + pr_err("%s: failed to alloc lmem buffer\n", __func__); + return -1; + } + + hevc->lmem_phy_addr = dma_map_single(amports_get_dma_device(), + hevc->lmem_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + hevc->lmem_phy_addr)) { + pr_err("%s: failed to map lmem buffer\n", __func__); + kfree(hevc->lmem_addr); + hevc->lmem_addr = NULL; + return -1; + } + + hevc->lmem_ptr = hevc->lmem_addr; + } + + if (mmu_enable) { + hevc->frame_mmu_map_addr = + dma_alloc_coherent(amports_get_dma_device(), + FRAME_MMU_MAP_SIZE, + &hevc->frame_mmu_map_phy_addr, GFP_KERNEL); + if (hevc->frame_mmu_map_addr == NULL) { + pr_err("%s: failed to alloc count_buffer\n", __func__); + return -1; + } + memset(hevc->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); + } + ret = 0; + return ret; +} + +/* +******************************************* + * Mailbox command + ******************************************* + */ +#define CMD_FINISHED 0 +#define CMD_ALLOC_VIEW 1 +#define CMD_FRAME_DISPLAY 3 +#define CMD_DEBUG 10 + + +#define DECODE_BUFFER_NUM_MAX 32 +#define DISPLAY_BUFFER_NUM 6 + +#define video_domain_addr(adr) (adr&0x7fffffff) +#define DECODER_WORK_SPACE_SIZE 0x800000 + +#define spec2canvas(x) \ + (((x)->uv_canvas_index << 16) | \ + ((x)->uv_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) + + +static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) +{ + int canvas_w = ALIGN(pic->width, 64)/4; + int canvas_h = ALIGN(pic->height, 32)/4; + int blkmode = mem_map_mode; + + /*CANVAS_BLKMODE_64X32*/ +#ifdef SUPPORT_10BIT + if (get_double_write_mode(hevc)) { + canvas_w = pic->width; + canvas_h = pic->height; + if ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) { + canvas_w >>= 2; + canvas_h >>= 2; + } + + if (mem_map_mode == 0) + canvas_w = ALIGN(canvas_w, 32); + else + canvas_w = ALIGN(canvas_w, 64); + canvas_h = ALIGN(canvas_h, 32); + + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + + canvas_config_ex(pic->y_canvas_index, + pic->dw_y_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + canvas_config_ex(pic->uv_canvas_index, pic->dw_u_v_adr, + canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); +#ifdef MULTI_INSTANCE_SUPPORT + pic->canvas_config[0].phy_addr = + pic->dw_y_adr; + pic->canvas_config[0].width = + canvas_w; + pic->canvas_config[0].height = + canvas_h; + pic->canvas_config[0].block_mode = + blkmode; + pic->canvas_config[0].endian = 7; + + pic->canvas_config[1].phy_addr = + pic->dw_u_v_adr; + pic->canvas_config[1].width = + canvas_w; + pic->canvas_config[1].height = + canvas_h; + pic->canvas_config[1].block_mode = + blkmode; + pic->canvas_config[1].endian = 7; +#endif + } else { + if (!mmu_enable) { + /* to change after 10bit VPU is ready ... */ + pic->y_canvas_index = 128 + pic->index; + pic->uv_canvas_index = 128 + pic->index; + + canvas_config_ex(pic->y_canvas_index, + pic->mc_y_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr, + canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + } + } +#else + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + + canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr, + canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); +#endif +} + +static int init_buf_spec(struct hevc_state_s *hevc) +{ + int pic_width = hevc->pic_w; + int pic_height = hevc->pic_h; + + /* hevc_print(hevc, 0, + "%s1: %d %d\n", __func__, hevc->pic_w, hevc->pic_h); */ + hevc_print(hevc, 0, + "%s2 %d %d\n", __func__, pic_width, pic_height); + /* pic_width = hevc->pic_w; */ + /* pic_height = hevc->pic_h; */ + + if (hevc->frame_width == 0 || hevc->frame_height == 0) { + hevc->frame_width = pic_width; + hevc->frame_height = pic_height; + + } + + return 0; +} + +static int parse_sei(struct hevc_state_s *hevc, char *sei_buf, uint32_t size) +{ + char *p = sei_buf; + char *p_sei; + uint16_t header; + uint8_t nal_unit_type; + uint8_t payload_type, payload_size; + int i, j; + + if (size < 2) + return 0; + header = *p++; + header <<= 8; + header += *p++; + nal_unit_type = header >> 9; + if ((nal_unit_type != NAL_UNIT_SEI) + && (nal_unit_type != NAL_UNIT_SEI_SUFFIX)) + return 0; + while (p+2 <= sei_buf+size) { + payload_type = *p++; + payload_size = *p++; + if (p+payload_size <= sei_buf+size) { + switch (payload_type) { + case SEI_MasteringDisplayColorVolume: + hevc_print(hevc, 0, + "sei type: primary display color volume %d, size %d\n", + payload_type, + payload_size); + /* master_display_colour */ + p_sei = p; + for (i = 0; i < 3; i++) { + for (j = 0; j < 2; j++) { + hevc->primaries[i][j] + = (*p_sei<<8) + | *(p_sei+1); + p_sei += 2; + } + } + for (i = 0; i < 2; i++) { + hevc->white_point[i] + = (*p_sei<<8) + | *(p_sei+1); + p_sei += 2; + } + for (i = 0; i < 2; i++) { + hevc->luminance[i] + = (*p_sei<<24) + | (*(p_sei+1)<<16) + | (*(p_sei+2)<<8) + | *(p_sei+3); + p_sei += 4; + } + hevc->sei_present_flag |= + SEI_MASTER_DISPLAY_COLOR_MASK; + for (i = 0; i < 3; i++) + for (j = 0; j < 2; j++) + hevc_print(hevc, 0, + "\tprimaries[%1d][%1d] = %04x\n", + i, j, + hevc->primaries[i][j]); + hevc_print(hevc, 0, + "\twhite_point = (%04x, %04x)\n", + hevc->white_point[0], + hevc->white_point[1]); + hevc_print(hevc, 0, + "\tmax,min luminance = %08x, %08x\n", + hevc->luminance[0], + hevc->luminance[1]); + break; + case SEI_ContentLightLevel: + hevc_print(hevc, 0, + "sei type: max content light level %d, size %d\n", + payload_type, payload_size); + /* content_light_level */ + p_sei = p; + hevc->content_light_level[0] + = (*p_sei<<8) | *(p_sei+1); + p_sei += 2; + hevc->content_light_level[1] + = (*p_sei<<8) | *(p_sei+1); + p_sei += 2; + hevc->sei_present_flag |= + SEI_CONTENT_LIGHT_LEVEL_MASK; + hevc_print(hevc, 0, + "\tmax cll = %04x, max_pa_cll = %04x\n", + hevc->content_light_level[0], + hevc->content_light_level[1]); + break; + default: + break; + } + } + p += payload_size; + } + return 0; +} + +static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf) +{ + unsigned int ar; + int i, j; + unsigned char index; + char *p; + unsigned size = 0; + unsigned type = 0; + struct vframe_master_display_colour_s *vf_dp + = &vf->prop.master_display_colour; + + if ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) { + vf->width = hevc->frame_width/4; + vf->height = hevc->frame_height/4; + } else { + vf->width = hevc->frame_width; + vf->height = hevc->frame_height; + } + vf->duration = hevc->frame_dur; + vf->duration_pulldown = 0; + vf->flag = 0; + + ar = min_t(u32, hevc->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + + /* signal_type */ + if (hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) + vf->signal_type = hevc->video_signal_type; + else + vf->signal_type = 0; + + /* parser sei */ + index = vf->index & 0xff; + if (index != 0xff && index >= 0 + && index < MAX_REF_PIC_NUM + && hevc->m_PIC[index] + && hevc->m_PIC[index]->aux_data_buf + && hevc->m_PIC[index]->aux_data_size) { + p = hevc->m_PIC[index]->aux_data_buf; + while (p < hevc->m_PIC[index]->aux_data_buf + + hevc->m_PIC[index]->aux_data_size - 8) { + size = *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + type = *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + if (type == 0x02000000) { + /* hevc_print(hevc, 0, "sei(%d)\n", size); */ + parse_sei(hevc, p, size); + } + p += size; + } + } + + /* master_display_colour */ + if (hevc->sei_present_flag & SEI_MASTER_DISPLAY_COLOR_MASK) { + for (i = 0; i < 3; i++) + for (j = 0; j < 2; j++) + vf_dp->primaries[i][j] = hevc->primaries[i][j]; + for (i = 0; i < 2; i++) { + vf_dp->white_point[i] = hevc->white_point[i]; + vf_dp->luminance[i] + = hevc->luminance[i]; + } + vf_dp->present_flag = 1; + } else + vf_dp->present_flag = 0; + + /* content_light_level */ + if (hevc->sei_present_flag & SEI_CONTENT_LIGHT_LEVEL_MASK) { + vf_dp->content_light_level.max_content + = hevc->content_light_level[0]; + vf_dp->content_light_level.max_pic_average + = hevc->content_light_level[1]; + vf_dp->content_light_level.present_flag = 1; + } else + vf_dp->content_light_level.present_flag = 0; + return; +} + +static int vh265_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; +#ifdef MULTI_INSTANCE_SUPPORT + struct vdec_s *vdec = op_arg; + struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; +#else + struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; +#endif + + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&hevc->newframe_q); + states->buf_avail_num = kfifo_len(&hevc->display_q); + + if (step == 2) + states->buf_avail_num = 0; + spin_unlock_irqrestore(&lock, flags); + return 0; +} + +static struct vframe_s *vh265_vf_peek(void *op_arg) +{ + struct vframe_s *vf; +#ifdef MULTI_INSTANCE_SUPPORT + struct vdec_s *vdec = op_arg; + struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; +#else + struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; +#endif + + if (step == 2) + return NULL; + + if (kfifo_peek(&hevc->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vh265_vf_get(void *op_arg) +{ + struct vframe_s *vf; +#ifdef MULTI_INSTANCE_SUPPORT + struct vdec_s *vdec = op_arg; + struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; +#else + struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; +#endif + + if (step == 2) + return NULL; + else if (step == 1) + step = 2; + + if (kfifo_get(&hevc->display_q, &vf)) { + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s(type %d index 0x%x)\n", + __func__, vf->type, vf->index); + + hevc->show_frame_num++; + return vf; + } + + return NULL; +} + +static void vh265_vf_put(struct vframe_s *vf, void *op_arg) +{ + unsigned long flags; +#ifdef MULTI_INSTANCE_SUPPORT + struct vdec_s *vdec = op_arg; + struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; +#else + struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; +#endif + unsigned char index_top = vf->index & 0xff; + unsigned char index_bot = (vf->index >> 8) & 0xff; + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s(type %d index 0x%x)\n", + __func__, vf->type, vf->index); + + kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf); + spin_lock_irqsave(&lock, flags); + + if (index_top != 0xff && index_top >= 0 + && index_top < MAX_REF_PIC_NUM + && hevc->m_PIC[index_top]) { + if (hevc->m_PIC[index_top]->vf_ref > 0) { + hevc->m_PIC[index_top]->vf_ref--; + + if (hevc->m_PIC[index_top]->vf_ref == 0) { + hevc->m_PIC[index_top]->output_ready = 0; + if (mmu_enable) + hevc->m_PIC[index_top]-> + used_by_display = 0; + hevc->last_put_idx_a = index_top; + if (hevc->wait_buf != 0) + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, + 0x1); + } + } + } + + if (index_bot != 0xff && index_bot >= 0 + && index_bot < MAX_REF_PIC_NUM + && hevc->m_PIC[index_bot]) { + if (hevc->m_PIC[index_bot]->vf_ref > 0) { + hevc->m_PIC[index_bot]->vf_ref--; + + if (hevc->m_PIC[index_bot]->vf_ref == 0) { + clear_used_by_display_flag(hevc); + hevc->m_PIC[index_bot]->output_ready = 0; + hevc->last_put_idx_b = index_bot; + if (hevc->wait_buf != 0) + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, + 0x1); + } + } + } + spin_unlock_irqrestore(&lock, flags); +} + +static int vh265_event_cb(int type, void *data, void *op_arg) +{ + unsigned long flags; +#ifdef MULTI_INSTANCE_SUPPORT + struct vdec_s *vdec = op_arg; + struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; +#else + struct hevc_state_s *hevc = (struct hevc_state_s *)op_arg; +#endif + if (type & VFRAME_EVENT_RECEIVER_RESET) { +#if 0 + amhevc_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vh265_vf_prov); +#endif + spin_lock_irqsave(&hevc->lock, flags); + vh265_local_init(); + vh265_prot_init(); + spin_unlock_irqrestore(&hevc->lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vh265_vf_prov); +#endif + amhevc_start(); +#endif + } else if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) { + struct provider_aux_req_s *req = + (struct provider_aux_req_s *)data; + unsigned char index; + spin_lock_irqsave(&lock, flags); + index = req->vf->index & 0xff; + req->aux_buf = NULL; + req->aux_size = 0; + if (req->bot_flag) + index = (req->vf->index >> 8) & 0xff; + if (index != 0xff && index >= 0 + && index < MAX_REF_PIC_NUM + && hevc->m_PIC[index]) { + req->aux_buf = hevc->m_PIC[index]->aux_data_buf; + req->aux_size = hevc->m_PIC[index]->aux_data_size; +#ifdef CONFIG_AM_VDEC_DV + req->dv_enhance_exist = + hevc->m_PIC[index]->dv_enhance_exist; +#else + req->dv_enhance_exist = 0; +#endif + } + spin_unlock_irqrestore(&lock, flags); + + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s(type 0x%x vf index 0x%x)=>size 0x%x\n", + __func__, type, index, req->aux_size); + } + + return 0; +} + +#ifdef HEVC_PIC_STRUCT_SUPPORT +static int process_pending_vframe(struct hevc_state_s *hevc, + struct PIC_s *pair_pic, unsigned char pair_frame_top_flag) +{ + struct vframe_s *vf; + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s: pair_pic index 0x%x %s\n", + __func__, pair_pic->index, + pair_frame_top_flag ? + "top" : "bot"); + + if (kfifo_len(&hevc->pending_q) > 1) { + /* do not pending more than 1 frame */ + if (kfifo_get(&hevc->pending_q, &vf) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s warning(1), vf=>display_q: (index 0x%x)\n", + __func__, vf->index); + kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + } + + if (kfifo_peek(&hevc->pending_q, &vf)) { + if (pair_pic == NULL || pair_pic->vf_ref <= 0) { + /* + *if pair_pic is recycled (pair_pic->vf_ref <= 0), + *do not use it + */ + if (kfifo_get(&hevc->pending_q, &vf) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s warning(2), vf=>display_q: (index 0x%x)\n", + __func__, vf->index); + if (vf) + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf); + } else if ((!pair_frame_top_flag) && + (((vf->index >> 8) & 0xff) == 0xff)) { + if (kfifo_get(&hevc->pending_q, &vf) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + if (vf) { + vf->type = VIDTYPE_PROGRESSIVE + | VIDTYPE_VIU_NV21; + vf->index &= 0xff; + vf->index |= (pair_pic->index << 8); + vf->canvas1Addr = spec2canvas(pair_pic); + pair_pic->vf_ref++; + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf); + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s vf => display_q: (index 0x%x)\n", + __func__, vf->index); + } + } else if (pair_frame_top_flag && + ((vf->index & 0xff) == 0xff)) { + if (kfifo_get(&hevc->pending_q, &vf) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + if (vf) { + vf->type = VIDTYPE_PROGRESSIVE + | VIDTYPE_VIU_NV21; + vf->index &= 0xff00; + vf->index |= pair_pic->index; + vf->canvas0Addr = spec2canvas(pair_pic); + pair_pic->vf_ref++; + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf); + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "%s vf => display_q: (index 0x%x)\n", + __func__, vf->index); + } + } + } + return 0; +} +#endif +static void update_vf_memhandle(struct hevc_state_s *hevc, + struct vframe_s *vf, int index) +{ + if (index < 0) + vf->mem_handle = NULL; + else if (vf->type & VIDTYPE_SCATTER) + vf->mem_handle = + decoder_mmu_box_get_mem_handle( + hevc->mmu_box, index); + else + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + hevc->bmmu_box, index); + return; +} +static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) +{ + struct vframe_s *vf = NULL; + int stream_offset = pic->stream_offset; + unsigned short slice_type = pic->slice_type; + + if (kfifo_get(&hevc->newframe_q, &vf) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + + if (vf) { + if (hevc->m_ins_flag) { + vf->pts = pic->pts; + vf->pts_us64 = pic->pts64; + } + /* if (pts_lookup_offset(PTS_TYPE_VIDEO, + stream_offset, &vf->pts, 0) != 0) { */ + else if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, + &vf->pts_us64) != 0) { +#ifdef DEBUG_PTS + hevc->pts_missed++; +#endif + vf->pts = 0; + vf->pts_us64 = 0; + } +#ifdef DEBUG_PTS + else + hevc->pts_hit++; +#endif + if (pts_unstable && (hevc->frame_dur > 0)) + hevc->pts_mode = PTS_NONE_REF_USE_DURATION; + + if ((hevc->pts_mode == PTS_NORMAL) && (vf->pts != 0) + && hevc->get_frame_dur) { + int pts_diff = (int)vf->pts - hevc->last_lookup_pts; + + if (pts_diff < 0) { + hevc->pts_mode_switching_count++; + hevc->pts_mode_recovery_count = 0; + + if (hevc->pts_mode_switching_count >= + PTS_MODE_SWITCHING_THRESHOLD) { + hevc->pts_mode = + PTS_NONE_REF_USE_DURATION; + hevc_print(hevc, 0, + "HEVC: switch to n_d mode.\n"); + } + + } else { + int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD; + + hevc->pts_mode_recovery_count++; + if (hevc->pts_mode_recovery_count > p) { + hevc->pts_mode_switching_count = 0; + hevc->pts_mode_recovery_count = 0; + } + } + } + + if (vf->pts != 0) + hevc->last_lookup_pts = vf->pts; + + if ((hevc->pts_mode == PTS_NONE_REF_USE_DURATION) + && (slice_type != 2)) + vf->pts = hevc->last_pts + DUR2PTS(hevc->frame_dur); + hevc->last_pts = vf->pts; + + if (vf->pts_us64 != 0) + hevc->last_lookup_pts_us64 = vf->pts_us64; + + if ((hevc->pts_mode == PTS_NONE_REF_USE_DURATION) + && (slice_type != 2)) { + vf->pts_us64 = + hevc->last_pts_us64 + + (DUR2PTS(hevc->frame_dur) * 100 / 9); + } + hevc->last_pts_us64 = vf->pts_us64; + if ((get_dbg_flag(hevc) & H265_DEBUG_OUT_PTS) != 0) { + hevc_print(hevc, 0, + "H265 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n", + vf->pts, vf->pts_us64); + } + + /* + *vf->index: + *(1) vf->type is VIDTYPE_PROGRESSIVE + * and vf->canvas0Addr != vf->canvas1Addr, + * vf->index[7:0] is the index of top pic + * vf->index[15:8] is the index of bot pic + *(2) other cases, + * only vf->index[7:0] is used + * vf->index[15:8] == 0xff + */ + vf->index = 0xff00 | pic->index; +#if 1 +/*SUPPORT_10BIT*/ + if (get_double_write_mode(hevc) & 0x10) { + /* double write only */ + vf->compBodyAddr = 0; + vf->compHeadAddr = 0; + } else { + + if (mmu_enable) { + vf->compBodyAddr = 0; + vf->compHeadAddr = pic->header_adr; + } else { + vf->compBodyAddr = pic->mc_y_adr; /*body adr*/ + vf->compHeadAddr = pic->mc_y_adr + + pic->losless_comp_body_size; + } + + /*head adr*/ + vf->canvas0Addr = vf->canvas1Addr = 0; + } + if (get_double_write_mode(hevc)) { + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; + if (get_double_write_mode(hevc) == 3) + vf->type |= VIDTYPE_COMPRESS; + if (mmu_enable) + vf->type |= VIDTYPE_SCATTER; +#ifdef MULTI_INSTANCE_SUPPORT + if (hevc->m_ins_flag) { + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 2; + vf->canvas0_config[0] = + pic->canvas_config[0]; + vf->canvas0_config[1] = + pic->canvas_config[1]; + + vf->canvas1_config[0] = + pic->canvas_config[0]; + vf->canvas1_config[1] = + pic->canvas_config[1]; + + } else +#endif + vf->canvas0Addr = vf->canvas1Addr + = spec2canvas(pic); + } else { + vf->canvas0Addr = vf->canvas1Addr = 0; + vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; + if (mmu_enable) + vf->type |= VIDTYPE_SCATTER; + + } + vf->compWidth = pic->width; + vf->compHeight = pic->height; + update_vf_memhandle(hevc, vf, pic->index); + switch (hevc->bit_depth_luma) { + case 9: + vf->bitdepth = BITDEPTH_Y9; + break; + case 10: + vf->bitdepth = BITDEPTH_Y10; + break; + default: + vf->bitdepth = BITDEPTH_Y8; + break; + } + switch (hevc->bit_depth_chroma) { + case 9: + vf->bitdepth |= (BITDEPTH_U9 | BITDEPTH_V9); + break; + case 10: + vf->bitdepth |= (BITDEPTH_U10 | BITDEPTH_V10); + break; + default: + vf->bitdepth |= (BITDEPTH_U8 | BITDEPTH_V8); + break; + } + if (hevc->mem_saving_mode == 1) + vf->bitdepth |= BITDEPTH_SAVING_MODE; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; + vf->canvas0Addr = vf->canvas1Addr = spec2canvas(pic); +#endif + set_frame_info(hevc, vf); + /* if((vf->width!=pic->width)||(vf->height!=pic->height)) */ + /* hevc_print(hevc, 0, + "aaa: %d/%d, %d/%d\n", + vf->width,vf->height, pic->width, pic->height); */ + if ((get_double_write_mode(hevc) == 2) || + (get_double_write_mode(hevc) == 3)) { + vf->width = pic->width/4; + vf->height = pic->height/4; + } else { + vf->width = pic->width; + vf->height = pic->height; + } + if (force_w_h != 0) { + vf->width = (force_w_h >> 16) & 0xffff; + vf->height = force_w_h & 0xffff; + } + if (force_fps & 0x100) { + u32 rate = force_fps & 0xff; + + if (rate) + vf->duration = 96000/rate; + else + vf->duration = 0; + } + + /* + * !!! to do ... + * need move below code to get_new_pic(), + * hevc->xxx can only be used by current decoded pic + */ + if (hevc->param.p.conformance_window_flag && + (get_dbg_flag(hevc) & + H265_DEBUG_IGNORE_CONFORMANCE_WINDOW) == 0) { + unsigned SubWidthC, SubHeightC; + + switch (hevc->param.p.chroma_format_idc) { + case 1: + SubWidthC = 2; + SubHeightC = 2; + break; + case 2: + SubWidthC = 2; + SubHeightC = 1; + break; + default: + SubWidthC = 1; + SubHeightC = 1; + break; + } + vf->width -= SubWidthC * + (hevc->param.p.conf_win_left_offset + + hevc->param.p.conf_win_right_offset); + vf->height -= SubHeightC * + (hevc->param.p.conf_win_top_offset + + hevc->param.p.conf_win_bottom_offset); + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "conformance_window %d, %d, %d, %d, %d => cropped width %d, height %d\n", + hevc->param.p.chroma_format_idc, + hevc->param.p.conf_win_left_offset, + hevc->param.p.conf_win_right_offset, + hevc->param.p.conf_win_top_offset, + hevc->param.p.conf_win_bottom_offset, + vf->width, vf->height); + } + +#ifdef HEVC_PIC_STRUCT_SUPPORT + if (pic->pic_struct == 3 || pic->pic_struct == 4) { + struct vframe_s *vf2; + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "pic_struct = %d index 0x%x\n", + pic->pic_struct, + pic->index); + + if (kfifo_get(&hevc->newframe_q, &vf2) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + pic->vf_ref = 2; + vf->duration = vf->duration>>1; + memcpy(vf2, vf, sizeof(struct vframe_s)); + + if (pic->pic_struct == 3) { + vf->type = VIDTYPE_INTERLACE_TOP + | VIDTYPE_VIU_NV21; + vf2->type = VIDTYPE_INTERLACE_BOTTOM + | VIDTYPE_VIU_NV21; + } else { + vf->type = VIDTYPE_INTERLACE_BOTTOM + | VIDTYPE_VIU_NV21; + vf2->type = VIDTYPE_INTERLACE_TOP + | VIDTYPE_VIU_NV21; + } + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf); + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf2); + } else if (pic->pic_struct == 5 + || pic->pic_struct == 6) { + struct vframe_s *vf2, *vf3; + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "pic_struct = %d index 0x%x\n", + pic->pic_struct, + pic->index); + + if (kfifo_get(&hevc->newframe_q, &vf2) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + if (kfifo_get(&hevc->newframe_q, &vf3) == 0) { + hevc_print(hevc, 0, + "fatal error, no available buffer slot."); + return -1; + } + pic->vf_ref = 3; + vf->duration = vf->duration/3; + memcpy(vf2, vf, sizeof(struct vframe_s)); + memcpy(vf3, vf, sizeof(struct vframe_s)); + + if (pic->pic_struct == 5) { + vf->type = VIDTYPE_INTERLACE_TOP + | VIDTYPE_VIU_NV21; + vf2->type = VIDTYPE_INTERLACE_BOTTOM + | VIDTYPE_VIU_NV21; + vf3->type = VIDTYPE_INTERLACE_TOP + | VIDTYPE_VIU_NV21; + } else { + vf->type = VIDTYPE_INTERLACE_BOTTOM + | VIDTYPE_VIU_NV21; + vf2->type = VIDTYPE_INTERLACE_TOP + | VIDTYPE_VIU_NV21; + vf3->type = VIDTYPE_INTERLACE_BOTTOM + | VIDTYPE_VIU_NV21; + } + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf); + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf2); + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf3); + + } else if (pic->pic_struct == 9 + || pic->pic_struct == 10) { + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "pic_struct = %d index 0x%x\n", + pic->pic_struct, + pic->index); + + pic->vf_ref = 1; + /* process previous pending vf*/ + process_pending_vframe(hevc, + pic, (pic->pic_struct == 9)); + + /* process current vf */ + kfifo_put(&hevc->pending_q, + (const struct vframe_s *)vf); + vf->height <<= 1; + if (pic->pic_struct == 9) { + vf->type = VIDTYPE_INTERLACE_TOP + | VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; + process_pending_vframe(hevc, + hevc->pre_bot_pic, 0); + } else { + vf->type = VIDTYPE_INTERLACE_BOTTOM | + VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; + vf->index = (pic->index << 8) | 0xff; + process_pending_vframe(hevc, + hevc->pre_top_pic, 1); + } + + /**/ + if (pic->pic_struct == 9) + hevc->pre_top_pic = pic; + else + hevc->pre_bot_pic = pic; + + } else if (pic->pic_struct == 11 + || pic->pic_struct == 12) { + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "pic_struct = %d index 0x%x\n", + pic->pic_struct, + pic->index); + pic->vf_ref = 1; + /* process previous pending vf*/ + process_pending_vframe(hevc, pic, + (pic->pic_struct == 11)); + + /* put current into pending q */ + vf->height <<= 1; + if (pic->pic_struct == 11) + vf->type = VIDTYPE_INTERLACE_TOP | + VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; + else { + vf->type = VIDTYPE_INTERLACE_BOTTOM | + VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; + vf->index = (pic->index << 8) | 0xff; + } + kfifo_put(&hevc->pending_q, + (const struct vframe_s *)vf); + + /**/ + if (pic->pic_struct == 11) + hevc->pre_top_pic = pic; + else + hevc->pre_bot_pic = pic; + + } else { + pic->vf_ref = 1; + + if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) + hevc_print(hevc, 0, + "pic_struct = %d index 0x%x\n", + pic->pic_struct, + pic->index); + + switch (pic->pic_struct) { + case 7: + vf->duration <<= 1; + break; + case 8: + vf->duration = vf->duration * 3; + break; + case 1: + vf->height <<= 1; + vf->type = VIDTYPE_INTERLACE_TOP | + VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD; + process_pending_vframe(hevc, pic, 1); + hevc->pre_top_pic = pic; + break; + case 2: + vf->height <<= 1; + vf->type = VIDTYPE_INTERLACE_BOTTOM + | VIDTYPE_VIU_NV21 + | VIDTYPE_VIU_FIELD; + process_pending_vframe(hevc, pic, 0); + hevc->pre_bot_pic = pic; + break; + } + kfifo_put(&hevc->display_q, + (const struct vframe_s *)vf); + } +#else + vf->type_original = vf->type; + pic->vf_ref = 1; + kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); +#endif + + vf_notify_receiver(hevc->provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + + return 0; +} + +static void process_nal_sei(struct hevc_state_s *hevc, + int payload_type, int payload_size) +{ + unsigned short data; + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\tsei message: payload_type = 0x%02x, payload_size = 0x%02x\n", + payload_type, payload_size); + + if (payload_type == 137) { + int i, j; + /* MASTERING_DISPLAY_COLOUR_VOLUME */ + if (payload_size >= 24) { + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\tsei MASTERING_DISPLAY_COLOUR_VOLUME available\n"); + for (i = 0; i < 3; i++) { + for (j = 0; j < 2; j++) { + data = + (READ_HREG(HEVC_SHIFTED_DATA) >> 16); + hevc->primaries[i][j] = data; + WRITE_HREG(HEVC_SHIFT_COMMAND, + (1<<7)|16); + if (get_dbg_flag(hevc) & + H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\t\tprimaries[%1d][%1d] = %04x\n", + i, j, hevc->primaries[i][j]); + } + } + for (i = 0; i < 2; i++) { + data = (READ_HREG(HEVC_SHIFTED_DATA) >> 16); + hevc->white_point[i] = data; + WRITE_HREG(HEVC_SHIFT_COMMAND, (1<<7)|16); + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\t\twhite_point[%1d] = %04x\n", + i, hevc->white_point[i]); + } + for (i = 0; i < 2; i++) { + data = + (READ_HREG(HEVC_SHIFTED_DATA) >> 16); + hevc->luminance[i] = data << 16; + WRITE_HREG(HEVC_SHIFT_COMMAND, + (1<<7)|16); + data = + (READ_HREG(HEVC_SHIFTED_DATA) >> 16); + hevc->luminance[i] |= data; + WRITE_HREG(HEVC_SHIFT_COMMAND, + (1<<7)|16); + if (get_dbg_flag(hevc) & + H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\t\tluminance[%1d] = %08x\n", + i, hevc->luminance[i]); + } + hevc->sei_present_flag |= SEI_MASTER_DISPLAY_COLOR_MASK; + } + payload_size -= 24; + while (payload_size > 0) { + data = (READ_HREG(HEVC_SHIFTED_DATA) >> 24); + payload_size--; + WRITE_HREG(HEVC_SHIFT_COMMAND, (1<<7)|8); + hevc_print(hevc, 0, "\t\tskip byte %02x\n", data); + } + } +} + +static int hevc_recover(struct hevc_state_s *hevc) +{ + int ret = -1; + u32 rem; + u64 shift_byte_count64; + unsigned hevc_shift_byte_count; + unsigned hevc_stream_start_addr; + unsigned hevc_stream_end_addr; + unsigned hevc_stream_rd_ptr; + unsigned hevc_stream_wr_ptr; + unsigned hevc_stream_control; + unsigned hevc_stream_fifo_ctl; + unsigned hevc_stream_buf_size; + mutex_lock(&vh265_mutex); +#if 0 + for (i = 0; i < (hevc->debug_ptr_size / 2); i += 4) { + int ii; + + for (ii = 0; ii < 4; ii++) + hevc_print(hevc, 0, + "%04x ", hevc->debug_ptr[i + 3 - ii]); + if (((i + ii) & 0xf) == 0) + hevc_print(hevc, 0, "\n"); + } +#endif +#define ES_VID_MAN_RD_PTR (1<<0) + if (!hevc->init_flag) { + hevc_print(hevc, 0, "h265 has stopped, recover return!\n"); + mutex_unlock(&vh265_mutex); + return ret; + } + amhevc_stop(); + ret = 0; + /* reset */ + WRITE_MPEG_REG(PARSER_VIDEO_RP, READ_VREG(HEVC_STREAM_RD_PTR)); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + + hevc_stream_start_addr = READ_VREG(HEVC_STREAM_START_ADDR); + hevc_stream_end_addr = READ_VREG(HEVC_STREAM_END_ADDR); + hevc_stream_rd_ptr = READ_VREG(HEVC_STREAM_RD_PTR); + hevc_stream_wr_ptr = READ_VREG(HEVC_STREAM_WR_PTR); + hevc_stream_control = READ_VREG(HEVC_STREAM_CONTROL); + hevc_stream_fifo_ctl = READ_VREG(HEVC_STREAM_FIFO_CTL); + hevc_stream_buf_size = hevc_stream_end_addr - hevc_stream_start_addr; + + /* HEVC streaming buffer will reset and restart + from current hevc_stream_rd_ptr position */ + /* calculate HEVC_SHIFT_BYTE_COUNT value with the new position. */ + hevc_shift_byte_count = READ_VREG(HEVC_SHIFT_BYTE_COUNT); + if ((hevc->shift_byte_count_lo & (1 << 31)) + && ((hevc_shift_byte_count & (1 << 31)) == 0)) + hevc->shift_byte_count_hi++; + + hevc->shift_byte_count_lo = hevc_shift_byte_count; + shift_byte_count64 = ((u64)(hevc->shift_byte_count_hi) << 32) | + hevc->shift_byte_count_lo; + div_u64_rem(shift_byte_count64, hevc_stream_buf_size, &rem); + shift_byte_count64 -= rem; + shift_byte_count64 += hevc_stream_rd_ptr - hevc_stream_start_addr; + + if (rem > (hevc_stream_rd_ptr - hevc_stream_start_addr)) + shift_byte_count64 += hevc_stream_buf_size; + + hevc->shift_byte_count_lo = (u32)shift_byte_count64; + hevc->shift_byte_count_hi = (u32)(shift_byte_count64 >> 32); + + WRITE_VREG(DOS_SW_RESET3, + /* (1<<2)| */ + (1 << 3) | (1 << 4) | (1 << 8) | + (1 << 11) | (1 << 12) | (1 << 14) + | (1 << 15) | (1 << 17) | (1 << 18) | (1 << 19)); + WRITE_VREG(DOS_SW_RESET3, 0); + + WRITE_VREG(HEVC_STREAM_START_ADDR, hevc_stream_start_addr); + WRITE_VREG(HEVC_STREAM_END_ADDR, hevc_stream_end_addr); + WRITE_VREG(HEVC_STREAM_RD_PTR, hevc_stream_rd_ptr); + WRITE_VREG(HEVC_STREAM_WR_PTR, hevc_stream_wr_ptr); + WRITE_VREG(HEVC_STREAM_CONTROL, hevc_stream_control); + WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, hevc->shift_byte_count_lo); + WRITE_VREG(HEVC_STREAM_FIFO_CTL, hevc_stream_fifo_ctl); + + hevc_config_work_space_hw(hevc); + decoder_hw_reset(); + + hevc->have_vps = 0; + hevc->have_sps = 0; + hevc->have_pps = 0; + + hevc->have_valid_start_slice = 0; + + if (get_double_write_mode(hevc) & 0x10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, + 0x1 << 31 /*/Enable NV21 reference read mode for MC*/ + ); + + WRITE_VREG(HEVC_WAIT_FLAG, 1); + /* clear mailbox interrupt */ + WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1); + /* enable mailbox interrupt */ + WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 1); + /* disable PSCALE for hardware sharing */ + WRITE_VREG(HEVC_PSCALE_CTRL, 0); + + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + + if (get_dbg_flag(hevc) & H265_DEBUG_UCODE) + WRITE_VREG(DEBUG_REG1, 0x1); + else + WRITE_VREG(DEBUG_REG1, 0x0); + + if ((error_handle_policy & 1) == 0) { + if ((error_handle_policy & 4) == 0) { + /* ucode auto mode, and do not check vps/sps/pps/idr */ + WRITE_VREG(NAL_SEARCH_CTL, + 0xc); + } else { + WRITE_VREG(NAL_SEARCH_CTL, 0x1);/* manual parser NAL */ + } + } else { + WRITE_VREG(NAL_SEARCH_CTL, 0x1);/* manual parser NAL */ + } + + if (get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE) + WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x10000); + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) + | ((parser_sei_enable & 0x7) << 17)); +#ifdef CONFIG_AM_VDEC_DV + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) | + ((parser_dolby_vision_enable & 0x1) << 20)); +#endif + config_decode_mode(hevc); + WRITE_VREG(DECODE_STOP_POS, decode_stop_pos); + + /* if (amhevc_loadmc(vh265_mc) < 0) { */ + /* amhevc_disable(); */ + /* return -EBUSY; */ + /* } */ +#if 0 + for (i = 0; i < (hevc->debug_ptr_size / 2); i += 4) { + int ii; + + for (ii = 0; ii < 4; ii++) { + /* hevc->debug_ptr[i+3-ii]=ttt++; */ + hevc_print(hevc, 0, + "%04x ", hevc->debug_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + hevc_print(hevc, 0, "\n"); + } +#endif + init_pic_list_hw(hevc); + + hevc_print(hevc, 0, "%s HEVC_SHIFT_BYTE_COUNT=%x\n", __func__, + READ_VREG(HEVC_SHIFT_BYTE_COUNT)); + + amhevc_start(); + + /* skip, search next start code */ + WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2)); + hevc->skip_flag = 1; +#ifdef ERROR_HANDLE_DEBUG + if (dbg_nal_skip_count & 0x20000) { + dbg_nal_skip_count &= ~0x20000; + mutex_unlock(&vh265_mutex); + return ret; + } +#endif + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); +#ifdef MULTI_INSTANCE_SUPPORT + if (!hevc->m_ins_flag) +#endif + hevc->first_pic_after_recover = 1; + mutex_unlock(&vh265_mutex); + return ret; +} + +static void dump_aux_buf(struct hevc_state_s *hevc) +{ + int i; + unsigned short *aux_adr = + (unsigned short *) + hevc->aux_addr; + unsigned aux_size = + (READ_VREG(HEVC_AUX_DATA_SIZE) + >> 16) << 4; + + if (hevc->prefix_aux_size > 0) { + hevc_print(hevc, 0, + "prefix aux: (size %d)\n", + aux_size); + for (i = 0; i < + (aux_size >> 1); i++) { + hevc_print_cont(hevc, 0, + "%04x ", + *(aux_adr + i)); + if (((i + 1) & 0xf) + == 0) + hevc_print_cont(hevc, + 0, "\n"); + } + } + if (hevc->suffix_aux_size > 0) { + aux_adr = (unsigned short *) + (hevc->aux_addr + + hevc->prefix_aux_size); + aux_size = + (READ_VREG(HEVC_AUX_DATA_SIZE) & 0xffff) + << 4; + hevc_print(hevc, 0, + "suffix aux: (size %d)\n", + aux_size); + for (i = 0; i < + (aux_size >> 1); i++) { + hevc_print_cont(hevc, 0, + "%04x ", *(aux_adr + i)); + if (((i + 1) & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + } + } +} + +static irqreturn_t vh265_isr_thread_fn(int irq, void *data) +{ + struct hevc_state_s *hevc = (struct hevc_state_s *) data; + unsigned int dec_status = hevc->dec_status; + int i, ret; +#ifdef CONFIG_AM_VDEC_DV + struct vdec_s *vdec = hw_to_vdec(hevc); +#endif + if (hevc->error_flag == 1) { + if ((error_handle_policy & 0x10) == 0) { + if (hevc->cur_pic) { + int current_lcu_idx = + READ_VREG(HEVC_PARSER_LCU_START) + & 0xffffff; + if (current_lcu_idx < + ((hevc->lcu_x_num*hevc->lcu_y_num)-1)) + hevc->cur_pic->error_mark = 1; + + } + } + if ((error_handle_policy & 1) == 0) { + hevc->error_skip_nal_count = 1; + /* manual search nal, skip error_skip_nal_count + of nal and trigger the HEVC_NAL_SEARCH_DONE irq */ + WRITE_VREG(NAL_SEARCH_CTL, + (error_skip_nal_count << 4) | 0x1); + } else { + hevc->error_skip_nal_count = error_skip_nal_count; + WRITE_VREG(NAL_SEARCH_CTL, 0x1);/* manual parser NAL */ + } + if (get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE) { + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) | 0x10000); + } + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) + | ((parser_sei_enable & 0x7) << 17)); +#ifdef CONFIG_AM_VDEC_DV + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) | + ((parser_dolby_vision_enable & 0x1) << 20)); +#endif + config_decode_mode(hevc); + /* search new nal */ + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); + + /* hevc_print(hevc, 0, + "%s: error handle\n", __func__); */ + hevc->error_flag = 2; + return IRQ_HANDLED; + } else if (hevc->error_flag == 3) { + hevc_print(hevc, 0, "error_flag=3, hevc_recover\n"); + hevc_recover(hevc); + hevc->error_flag = 0; + + if ((error_handle_policy & 0x10) == 0) { + if (hevc->cur_pic) { + int current_lcu_idx = + READ_VREG(HEVC_PARSER_LCU_START) + & 0xffffff; + if (current_lcu_idx < + ((hevc->lcu_x_num*hevc->lcu_y_num)-1)) + hevc->cur_pic->error_mark = 1; + + } + } + if ((error_handle_policy & 1) == 0) { + /* need skip some data when + error_flag of 3 is triggered, */ + /* to avoid hevc_recover() being called + for many times at the same bitstream position */ + hevc->error_skip_nal_count = 1; + /* manual search nal, skip error_skip_nal_count + of nal and trigger the HEVC_NAL_SEARCH_DONE irq */ + WRITE_VREG(NAL_SEARCH_CTL, + (error_skip_nal_count << 4) | 0x1); + } + + if ((error_handle_policy & 0x2) == 0) { + hevc->have_vps = 1; + hevc->have_sps = 1; + hevc->have_pps = 1; + } + return IRQ_HANDLED; + } + + i = READ_VREG(HEVC_SHIFT_BYTE_COUNT); + if ((hevc->shift_byte_count_lo & (1 << 31)) && ((i & (1 << 31)) == 0)) + hevc->shift_byte_count_hi++; + hevc->shift_byte_count_lo = i; + +#ifdef MULTI_INSTANCE_SUPPORT + if ((dec_status == HEVC_DECPIC_DATA_DONE || + dec_status == HEVC_FIND_NEXT_PIC_NAL || + dec_status == HEVC_FIND_NEXT_DVEL_NAL) + && (hevc->m_ins_flag)) { + if (hevc->chunk) { + hevc->cur_pic->pts = hevc->chunk->pts; + hevc->cur_pic->pts64 = hevc->chunk->pts64; + } else if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, + hevc->cur_pic->stream_offset, + &hevc->cur_pic->pts, + 0, + &hevc->cur_pic->pts64) != 0) { +#ifdef DEBUG_PTS + hevc->pts_missed++; +#endif + hevc->cur_pic->pts = 0; + hevc->cur_pic->pts64 = 0; + } + } + + if ((dec_status == HEVC_SEARCH_BUFEMPTY) || + (dec_status == HEVC_DECODE_BUFEMPTY) || + (dec_status == HEVC_NAL_DECODE_DONE) + ) { + if (hevc->m_ins_flag) { +#if 1 + if (!vdec_frame_based(hw_to_vdec(hevc))) { + hevc->dec_result = DEC_RESULT_AGAIN; + amhevc_stop(); + } else + hevc->dec_result = DEC_RESULT_GET_DATA; +#else + if (!vdec_frame_based(hw_to_vdec(hevc))) + hevc->dec_result = DEC_RESULT_AGAIN; + else + hevc->dec_result = DEC_RESULT_DONE; + amhevc_stop(); +#endif + reset_process_time(hevc); + schedule_work(&hevc->work); + } + + return IRQ_HANDLED; + } else if (dec_status == HEVC_DECPIC_DATA_DONE) { + if (hevc->m_ins_flag) { + hevc->dec_result = DEC_RESULT_DONE; + amhevc_stop(); + + reset_process_time(hevc); + schedule_work(&hevc->work); + } + + return IRQ_HANDLED; +#ifdef CONFIG_AM_VDEC_DV + } else if (dec_status == HEVC_FIND_NEXT_PIC_NAL || + dec_status == HEVC_FIND_NEXT_DVEL_NAL) { + if (hevc->m_ins_flag) { + unsigned next_parser_type = + READ_HREG(CUR_NAL_UNIT_TYPE); + if (vdec->slave && + dec_status == HEVC_FIND_NEXT_DVEL_NAL) { + /*cur is base, found enhance*/ + struct hevc_state_s *hevc_el = + (struct hevc_state_s *) + vdec->slave->private; + hevc->switch_dvlayer_flag = 1; + hevc_el->start_parser_type = + next_parser_type; + } else if (vdec->master && + dec_status == HEVC_FIND_NEXT_PIC_NAL) { + /*cur is enhance, found base*/ + struct hevc_state_s *hevc_ba = + (struct hevc_state_s *) + vdec->master->private; + hevc->switch_dvlayer_flag = 1; + hevc_ba->start_parser_type = + next_parser_type; + } else { + hevc->switch_dvlayer_flag = 0; + hevc->start_parser_type = + next_parser_type; + } + hevc->dec_result = DEC_RESULT_DONE; + amhevc_stop(); + reset_process_time(hevc); + if (READ_VREG(HEVC_AUX_DATA_SIZE) != 0) { + dma_sync_single_for_cpu( + amports_get_dma_device(), + hevc->aux_phy_addr, + hevc->prefix_aux_size + hevc->suffix_aux_size, + DMA_FROM_DEVICE); + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR_MORE) + dump_aux_buf(hevc); + if (hevc->cur_pic) + set_aux_data(hevc, hevc->cur_pic, 0); + } + + schedule_work(&hevc->work); + } + + return IRQ_HANDLED; +#endif + } else if (dec_status == HEVC_DECODE_TIMEOUT) { + if (vdec_frame_based(hw_to_vdec(hevc)) || + (READ_VREG(HEVC_STREAM_LEVEL) > 0x200)) { + if ((get_dbg_flag(hevc) + & H265_DEBUG_DIS_LOC_ERROR_PROC)) { + hevc_print(hevc, 0, + "%s decoding error, level 0x%x\n", + __func__, READ_VREG(HEVC_STREAM_LEVEL)); + goto send_again; + } + amhevc_stop(); + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s %s\n", __func__, + (dec_status == HEVC_SEARCH_BUFEMPTY) ? + "HEVC_SEARCH_BUFEMPTY" : + (dec_status == HEVC_DECODE_BUFEMPTY) ? + "HEVC_DECODE_BUFEMPTY" : "HEVC_DECODE_TIMEOUT"); + hevc->dec_result = DEC_RESULT_DONE; + + reset_process_time(hevc); + schedule_work(&hevc->work); + } else { + /* WRITE_VREG(dec_status_REG, H264_ACTION_INIT); */ + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s DEC_RESULT_AGAIN\n", __func__); +send_again: + hevc->dec_result = DEC_RESULT_AGAIN; + reset_process_time(hevc); + schedule_work(&hevc->work); + } + return IRQ_HANDLED; + } + +#endif + + if (dec_status == HEVC_SEI_DAT) { + int payload_type = READ_HREG(CUR_NAL_UNIT_TYPE) & 0xffff; + int payload_size = + (READ_HREG(CUR_NAL_UNIT_TYPE) >> 16) & 0xffff; + process_nal_sei(hevc, payload_type, payload_size); + + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_SEI_DAT_DONE); + } else if (dec_status == HEVC_NAL_SEARCH_DONE) { + int naltype = READ_HREG(CUR_NAL_UNIT_TYPE); + int parse_type = HEVC_DISCARD_NAL; + + hevc->error_watchdog_count = 0; + hevc->error_skip_nal_wt_cnt = 0; + if (slice_parse_begin > 0 && + get_dbg_flag(hevc) & H265_DEBUG_DISCARD_NAL) { + hevc_print(hevc, 0, + "nal type %d, discard %d\n", naltype, + slice_parse_begin); + if (naltype <= NAL_UNIT_CODED_SLICE_CRA) + slice_parse_begin--; + } + if (naltype == NAL_UNIT_EOS) { + struct PIC_s *pic; + hevc_print(hevc, 0, "get NAL_UNIT_EOS, flush output\n"); + pic = get_pic_by_POC(hevc, hevc->curr_POC); + hevc->curr_POC = INVALID_POC; + /* add to fix RAP_B_Bossen_1 */ + hevc->m_pocRandomAccess = MAX_INT; + flush_output(hevc, pic); + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_DISCARD_NAL); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); + return IRQ_HANDLED; + } + + if (hevc->error_skip_nal_count > 0) { + hevc_print(hevc, 0, + "nal type %d, discard %d\n", naltype, + hevc->error_skip_nal_count); + hevc->error_skip_nal_count--; + if (hevc->error_skip_nal_count == 0) { + hevc_recover(hevc); + hevc->error_flag = 0; + if ((error_handle_policy & 0x2) == 0) { + hevc->have_vps = 1; + hevc->have_sps = 1; + hevc->have_pps = 1; + } + return IRQ_HANDLED; + } + } else if (naltype == NAL_UNIT_VPS) { + parse_type = HEVC_NAL_UNIT_VPS; + hevc->have_vps = 1; +#ifdef ERROR_HANDLE_DEBUG + if (dbg_nal_skip_flag & 1) + parse_type = HEVC_DISCARD_NAL; +#endif + } else if (hevc->have_vps) { + if (naltype == NAL_UNIT_SPS) { + parse_type = HEVC_NAL_UNIT_SPS; + hevc->have_sps = 1; +#ifdef ERROR_HANDLE_DEBUG + if (dbg_nal_skip_flag & 2) + parse_type = HEVC_DISCARD_NAL; +#endif + } else if (naltype == NAL_UNIT_PPS) { + parse_type = HEVC_NAL_UNIT_PPS; + hevc->have_pps = 1; +#ifdef ERROR_HANDLE_DEBUG + if (dbg_nal_skip_flag & 4) + parse_type = HEVC_DISCARD_NAL; +#endif + } else if (hevc->have_sps && hevc->have_pps) { + int seg = HEVC_NAL_UNIT_CODED_SLICE_SEGMENT; + + if ((naltype == NAL_UNIT_CODED_SLICE_IDR) || + (naltype == + NAL_UNIT_CODED_SLICE_IDR_N_LP) + || (naltype == + NAL_UNIT_CODED_SLICE_CRA) + || (naltype == + NAL_UNIT_CODED_SLICE_BLA) + || (naltype == + NAL_UNIT_CODED_SLICE_BLANT) + || (naltype == + NAL_UNIT_CODED_SLICE_BLA_N_LP) + ) { + if (slice_parse_begin > 0) { + hevc_print(hevc, 0, + "discard %d, for debugging\n", + slice_parse_begin); + slice_parse_begin--; + } else { + parse_type = seg; + } + hevc->have_valid_start_slice = 1; + } else if (naltype <= + NAL_UNIT_CODED_SLICE_CRA + && (hevc->have_valid_start_slice + || (hevc->PB_skip_mode != 3))) { + if (slice_parse_begin > 0) { + hevc_print(hevc, 0, + "discard %d, dd\n", + slice_parse_begin); + slice_parse_begin--; + } else + parse_type = seg; + + } + } + } + if (hevc->have_vps && hevc->have_sps && hevc->have_pps + && hevc->have_valid_start_slice && + hevc->error_flag == 0) { + if ((get_dbg_flag(hevc) & + H265_DEBUG_MAN_SEARCH_NAL) == 0 /*&& + (!hevc->m_ins_flag)*/) { + /* auot parser NAL; do not check + vps/sps/pps/idr */ + WRITE_VREG(NAL_SEARCH_CTL, 0x2); + } + + if (get_dbg_flag(hevc) & + H265_DEBUG_NO_EOS_SEARCH_DONE) { + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) | + 0x10000); + } + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) + | ((parser_sei_enable & 0x7) << 17)); +#ifdef CONFIG_AM_VDEC_DV + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) | + ((parser_dolby_vision_enable & 0x1) << 20)); +#endif + config_decode_mode(hevc); + } + + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "naltype = %d parse_type %d\n %d %d %d %d\n", + naltype, parse_type, hevc->have_vps, + hevc->have_sps, hevc->have_pps, + hevc->have_valid_start_slice); + } + + WRITE_VREG(HEVC_DEC_STATUS_REG, parse_type); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); + + } else if (dec_status == HEVC_SLICE_SEGMENT_DONE) { + if (hevc->start_decoding_time > 0) { + u32 process_time = 1000* + (jiffies - hevc->start_decoding_time)/HZ; + if (process_time > max_decoding_time) + max_decoding_time = process_time; + } + + hevc->error_watchdog_count = 0; + if (hevc->pic_list_init_flag == 2) { + hevc->pic_list_init_flag = 3; + hevc_print(hevc, 0, "set pic_list_init_flag to 3\n"); + } else if (hevc->wait_buf == 0) { + u32 vui_time_scale; + u32 vui_num_units_in_tick; + + if (get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) + get_rpm_param(&hevc->param); + else { + dma_sync_single_for_cpu( + amports_get_dma_device(), + hevc->rpm_phy_addr, + RPM_BUF_SIZE, + DMA_FROM_DEVICE); + + for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { + int ii; + + for (ii = 0; ii < 4; ii++) { + hevc->param.l.data[i + ii] = + hevc->rpm_ptr[i + 3 + - ii]; + } + } + } + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { + hevc_print(hevc, 0, + "rpm_param: (%d)\n", hevc->slice_idx); + hevc->slice_idx++; + for (i = 0; i < (RPM_END - RPM_BEGIN); i++) { + hevc_print_cont(hevc, 0, + "%04x ", hevc->param.l.data[i]); + if (((i + 1) & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + } + + hevc_print(hevc, 0, + "vui_timing_info: %x, %x, %x, %x\n", + hevc->param.p.vui_num_units_in_tick_hi, + hevc->param.p.vui_num_units_in_tick_lo, + hevc->param.p.vui_time_scale_hi, + hevc->param.p.vui_time_scale_lo); + } + if ( +#ifdef CONFIG_AM_VDEC_DV + vdec->master == NULL && + vdec->slave == NULL && +#endif + READ_VREG(HEVC_AUX_DATA_SIZE) != 0 + ) { + dma_sync_single_for_cpu( + amports_get_dma_device(), + hevc->aux_phy_addr, + hevc->prefix_aux_size + hevc->suffix_aux_size, + DMA_FROM_DEVICE); + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR_MORE) + dump_aux_buf(hevc); + } + + vui_time_scale = + (u32)(hevc->param.p.vui_time_scale_hi << 16) | + hevc->param.p.vui_time_scale_lo; + vui_num_units_in_tick = + (u32)(hevc->param. + p.vui_num_units_in_tick_hi << 16) | + hevc->param. + p.vui_num_units_in_tick_lo; + if (hevc->bit_depth_luma != + ((hevc->param.p.bit_depth & 0xf) + 8)) { + hevc_print(hevc, 0, "Bit depth luma = %d\n", + (hevc->param.p.bit_depth & 0xf) + 8); + } + if (hevc->bit_depth_chroma != + (((hevc->param.p.bit_depth >> 4) & 0xf) + 8)) { + hevc_print(hevc, 0, "Bit depth chroma = %d\n", + ((hevc->param.p.bit_depth >> 4) & + 0xf) + 8); + } + hevc->bit_depth_luma = + (hevc->param.p.bit_depth & 0xf) + 8; + hevc->bit_depth_chroma = + ((hevc->param.p.bit_depth >> 4) & 0xf) + 8; + bit_depth_luma = hevc->bit_depth_luma; + bit_depth_chroma = hevc->bit_depth_chroma; +#ifdef SUPPORT_10BIT + if (hevc->bit_depth_luma == 8 && + hevc->bit_depth_chroma == 8 && + enable_mem_saving) + hevc->mem_saving_mode = 1; + else + hevc->mem_saving_mode = 0; +#endif + if ((vui_time_scale != 0) + && (vui_num_units_in_tick != 0)) { + hevc->frame_dur = + div_u64(96000ULL * + vui_num_units_in_tick, + vui_time_scale); + hevc->get_frame_dur = true; + } + + if (hevc->video_signal_type != + ((hevc->param.p.video_signal_type << 16) + | hevc->param.p.color_description)) { + u32 v = hevc->param.p.video_signal_type; + u32 c = hevc->param.p.color_description; +#if 0 + if (v & 0x2000) { + hevc_print(hevc, 0, + "video_signal_type present:\n"); + hevc_print(hevc, 0, " %s %s\n", + video_format_names[(v >> 10) & 7], + ((v >> 9) & 1) ? + "full_range" : "limited"); + if (v & 0x100) { + hevc_print(hevc, 0, + " color_description present:\n"); + hevc_print(hevc, 0, + " color_primarie = %s\n", + color_primaries_names + [v & 0xff]); + hevc_print(hevc, 0, + " transfer_characteristic = %s\n", + transfer_characteristics_names + [(c >> 8) & 0xff]); + hevc_print(hevc, 0, + " matrix_coefficient = %s\n", + matrix_coeffs_names[c & 0xff]); + } + } +#endif + hevc->video_signal_type = (v << 16) | c; + video_signal_type = hevc->video_signal_type; + } + + if (use_cma && + (hevc->param.p.slice_segment_address == 0) + && (hevc->pic_list_init_flag == 0)) { + int log = hevc->param.p.log2_min_coding_block_size_minus3; + int log_s = hevc->param.p.log2_diff_max_min_coding_block_size; + + hevc->pic_w = hevc->param.p.pic_width_in_luma_samples; + hevc->pic_h = hevc->param.p.pic_height_in_luma_samples; + hevc->lcu_size = 1 << (log + 3 + log_s); + hevc->lcu_size_log2 = log2i(hevc->lcu_size); + if (hevc->pic_w == 0 || hevc->pic_h == 0 + || hevc->lcu_size == 0) { + /* skip search next start code */ + WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) + & (~0x2)); + hevc->skip_flag = 1; + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); + + } else { + hevc->sps_num_reorder_pics_0 = + hevc->param.p.sps_num_reorder_pics_0; + hevc->pic_list_init_flag = 1; +#ifdef MULTI_INSTANCE_SUPPORT + if (hevc->m_ins_flag) { + reset_process_time(hevc); + schedule_work(&hevc->work); + } else +#endif + up(&hevc->h265_sema); + hevc_print(hevc, 0, "set pic_list_init_flag 1\n"); + } + return IRQ_HANDLED; + } + +} + ret = + hevc_slice_segment_header_process(hevc, + &hevc->param, decode_pic_begin); + if (ret < 0) + ; + else if (ret == 0) { + if ((hevc->new_pic) && (hevc->cur_pic)) { + hevc->cur_pic->stream_offset = + READ_VREG(HEVC_SHIFT_BYTE_COUNT); + } + + WRITE_VREG(HEVC_DEC_STATUS_REG, + HEVC_CODED_SLICE_SEGMENT_DAT); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); + + hevc->start_decoding_time = jiffies; +#if 1 + /*to do..., copy aux data to hevc->cur_pic*/ +#endif +#ifdef MULTI_INSTANCE_SUPPORT + } else if (hevc->m_ins_flag) { + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s, bufmgr ret %d skip, DEC_RESULT_DONE\n", + __func__, ret); + hevc->dec_result = DEC_RESULT_DONE; + amhevc_stop(); + reset_process_time(hevc); + schedule_work(&hevc->work); +#endif + } else { + /* skip, search next start code */ + WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2)); + hevc->skip_flag = 1; + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + /* Interrupt Amrisc to excute */ + WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); + } + + } + + if (mmu_enable) { + if (hevc->last_put_idx_a >= 0 + && hevc->last_put_idx_a < MAX_REF_PIC_NUM) { + int i = hevc->last_put_idx_a; + struct PIC_s *pic = hevc->m_PIC[i]; + + /*free not used buffers.*/ + if (pic && + pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 0 + && pic->used_by_display == 0 + && (pic->index != -1)) { + decoder_mmu_box_free_idx(hevc->mmu_box, i); + hevc->last_put_idx_a = -1; + /* hevc_print(hevc, 0, "release pic buf %x\n",i);*/ + } + } + if (hevc->last_put_idx_b >= 0 + && hevc->last_put_idx_b < MAX_REF_PIC_NUM) { + int i = hevc->last_put_idx_b; + struct PIC_s *pic = hevc->m_PIC[i]; + + /*free not used buffers.*/ + if (pic && + pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 0 + && pic->used_by_display == 0 + && (pic->index != -1)) { + decoder_mmu_box_free_idx(hevc->mmu_box, i); + hevc->last_put_idx_b = -1; + } + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t vh265_isr(int irq, void *data) +{ + int i, temp; + unsigned int dec_status; + struct hevc_state_s *hevc = (struct hevc_state_s *)data; + + dec_status = READ_VREG(HEVC_DEC_STATUS_REG); + if (hevc->init_flag == 0) + return IRQ_HANDLED; + hevc->dec_status = dec_status; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) + hevc_print(hevc, 0, + "265 isr dec status = 0x%x\n", dec_status); + + if (get_dbg_flag(hevc) & H265_DEBUG_UCODE) { + if (READ_HREG(DEBUG_REG1) & 0x10000) { + dma_sync_single_for_cpu( + amports_get_dma_device(), + hevc->lmem_phy_addr, + LMEM_BUF_SIZE, + DMA_FROM_DEVICE); + + hevc_print(hevc, 0, + "LMEM:\n", READ_HREG(DEBUG_REG1)); + + if (mmu_enable) + temp = 0x500; + else + temp = 0x400; + for (i = 0; i < temp; i += 4) { + int ii; + + if ((i & 0xf) == 0) + hevc_print_cont(hevc, 0, "%03x: ", i); + for (ii = 0; ii < 4; ii++) { + hevc_print_cont(hevc, 0, "%04x ", + hevc->lmem_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + } + WRITE_HREG(DEBUG_REG1, 0); + } else if (READ_HREG(DEBUG_REG1) != 0) { + hevc_print(hevc, 0, + "dbg%x: %x\n", READ_HREG(DEBUG_REG1), + READ_HREG(DEBUG_REG2)); + WRITE_HREG(DEBUG_REG1, 0); + return IRQ_HANDLED; + } + + } + + if (hevc->pic_list_init_flag == 1) + return IRQ_HANDLED; + + return IRQ_WAKE_THREAD; + +} + +static void vh265_check_timer_func(unsigned long arg) +{ + struct hevc_state_s *hevc = (struct hevc_state_s *)arg; + struct timer_list *timer = &hevc->timer; + unsigned char empty_flag; + unsigned int buf_level; + + enum receviver_start_e state = RECEIVER_INACTIVE; + if (hevc->init_flag == 0) { + if (hevc->stat & STAT_TIMER_ARM) { + timer->expires = jiffies + PUT_INTERVAL; + add_timer(&hevc->timer); + } + return; + } +#ifdef MULTI_INSTANCE_SUPPORT + if (hevc->m_ins_flag && + hw_to_vdec(hevc)->next_status == + VDEC_STATUS_DISCONNECTED) { + hevc->dec_result = DEC_RESULT_DONE; + schedule_work(&hevc->work); + hevc_print(hevc, + 0, "vdec requested to be disconnected\n"); + return; + } + + if (hevc->m_ins_flag) { + if ((input_frame_based(hw_to_vdec(hevc)) || + (READ_VREG(HEVC_STREAM_LEVEL) > 0x200)) && + ((get_dbg_flag(hevc) & + H265_DEBUG_DIS_LOC_ERROR_PROC) == 0) && + (decode_timeout_val > 0) && + (hevc->start_process_time > 0) && + ((1000 * (jiffies - hevc->start_process_time) / HZ) + > decode_timeout_val) + ) { + u32 dec_status = READ_VREG(HEVC_DEC_STATUS_REG); + int current_lcu_idx = + READ_VREG(HEVC_PARSER_LCU_START)&0xffffff; + if (dec_status == HEVC_CODED_SLICE_SEGMENT_DAT) { + if (hevc->last_lcu_idx == current_lcu_idx) { + if (hevc->decode_timeout_count > 0) + hevc->decode_timeout_count--; + if (hevc->decode_timeout_count == 0) + timeout_process(hevc); + } + hevc->last_lcu_idx = current_lcu_idx; + } else + timeout_process(hevc); + } + } else { +#endif + if (hevc->m_ins_flag == 0 && + vf_get_receiver(hevc->provider_name)) { + state = + vf_notify_receiver(hevc->provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + if ((state == RECEIVER_STATE_NULL) + || (state == RECEIVER_STATE_NONE)) + state = RECEIVER_INACTIVE; + } else + state = RECEIVER_INACTIVE; + + empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1; + /* error watchdog */ + if (hevc->m_ins_flag == 0 && + (empty_flag == 0) + && (hevc->pic_list_init_flag == 0 + || hevc->pic_list_init_flag + == 3)) { + /* decoder has input */ + if ((get_dbg_flag(hevc) & + H265_DEBUG_DIS_LOC_ERROR_PROC) == 0) { + + buf_level = READ_VREG(HEVC_STREAM_LEVEL); + /* receiver has no buffer to recycle */ + if ((state == RECEIVER_INACTIVE) && + (kfifo_is_empty(&hevc->display_q) && + buf_level > 0x200) + ) { + if (hevc->error_flag == 0) { + hevc->error_watchdog_count++; + if (hevc->error_watchdog_count == + error_handle_threshold) { + hevc_print(hevc, 0, + "H265 dec err local reset.\n"); + hevc->error_flag = 1; + hevc->error_watchdog_count = 0; + hevc->error_skip_nal_wt_cnt = 0; + hevc-> + error_system_watchdog_count++; + WRITE_VREG + (HEVC_ASSIST_MBOX1_IRQ_REG, + 0x1); + } + } else if (hevc->error_flag == 2) { + int th = + error_handle_nal_skip_threshold; + hevc->error_skip_nal_wt_cnt++; + if (hevc->error_skip_nal_wt_cnt + == th) { + hevc->error_flag = 3; + hevc->error_watchdog_count = 0; + hevc-> + error_skip_nal_wt_cnt = 0; + WRITE_VREG + (HEVC_ASSIST_MBOX1_IRQ_REG, + 0x1); + } + } + } + } + + if ((get_dbg_flag(hevc) + & H265_DEBUG_DIS_SYS_ERROR_PROC) == 0) + /* receiver has no buffer to recycle */ + if ((state == RECEIVER_INACTIVE) && + (kfifo_is_empty(&hevc->display_q)) + ) { /* no buffer to recycle */ + if ((get_dbg_flag(hevc) & + H265_DEBUG_DIS_LOC_ERROR_PROC) != + 0) + hevc->error_system_watchdog_count++; + if (hevc->error_system_watchdog_count == + error_handle_system_threshold) { + /* and it lasts for a while */ + hevc_print(hevc, 0, + "H265 dec fatal error watchdog.\n"); + hevc-> + error_system_watchdog_count = 0; + hevc->fatal_error = + DECODER_FATAL_ERROR_UNKNOWN; + } + } + } else { + hevc->error_watchdog_count = 0; + hevc->error_system_watchdog_count = 0; + } +#ifdef MULTI_INSTANCE_SUPPORT + } +#endif + if (decode_stop_pos != decode_stop_pos_pre) { + WRITE_VREG(DECODE_STOP_POS, decode_stop_pos); + decode_stop_pos_pre = decode_stop_pos; + } + + if (get_dbg_flag(hevc) & H265_DEBUG_DUMP_PIC_LIST) { + dump_pic_list(hevc); + debug &= ~H265_DEBUG_DUMP_PIC_LIST; + } + if (get_dbg_flag(hevc) & H265_DEBUG_TRIG_SLICE_SEGMENT_PROC) { + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1); + debug &= ~H265_DEBUG_TRIG_SLICE_SEGMENT_PROC; + } + if (get_dbg_flag(hevc) & H265_DEBUG_HW_RESET) { + hevc->error_skip_nal_count = error_skip_nal_count; + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + + debug &= ~H265_DEBUG_HW_RESET; + } + if (get_dbg_flag(hevc) & H265_DEBUG_ERROR_TRIG) { + WRITE_VREG(DECODE_STOP_POS, 1); + debug &= ~H265_DEBUG_ERROR_TRIG; + } +#ifdef ERROR_HANDLE_DEBUG + if ((dbg_nal_skip_count > 0) && ((dbg_nal_skip_count & 0x10000) != 0)) { + hevc->error_skip_nal_count = dbg_nal_skip_count & 0xffff; + dbg_nal_skip_count &= ~0x10000; + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + } +#endif + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + hevc_print(hevc, 0, + "WRITE_VREG(%x,%x)\n", radr, rval); + } else + hevc_print(hevc, 0, + "READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + if (dbg_cmd != 0) { + if (dbg_cmd == 1) { + u32 disp_laddr; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + get_double_write_mode(hevc) == 0) { + disp_laddr = + READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; + } else { + struct canvas_s cur_canvas; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) + & 0xff), &cur_canvas); + disp_laddr = cur_canvas.addr; + } + hevc_print(hevc, 0, + "current displayed buffer address %x\r\n", + disp_laddr); + } + dbg_cmd = 0; + } + /*don't changed at start.*/ + if (hevc->m_ins_flag == 0 && + hevc->get_frame_dur && hevc->show_frame_num > 60 && + hevc->frame_dur > 0 && hevc->saved_resolution != + hevc->frame_width * hevc->frame_height * + (96000 / hevc->frame_dur)) { + int fps = 96000 / hevc->frame_dur; + + if (hevc_source_changed(VFORMAT_HEVC, + hevc->frame_width, hevc->frame_height, fps) > 0) + hevc->saved_resolution = hevc->frame_width * + hevc->frame_height * fps; + } + + + timer->expires = jiffies + PUT_INTERVAL; + add_timer(timer); +} + +static int h265_task_handle(void *data) +{ + int ret = 0; + struct hevc_state_s *hevc = (struct hevc_state_s *)data; + + set_user_nice(current, -10); + while (1) { + if (use_cma == 0) { + hevc_print(hevc, 0, + "ERROR: use_cma can not be changed dynamically\n"); + } + ret = down_interruptible(&hevc->h265_sema); + if ((hevc->init_flag != 0) && (hevc->pic_list_init_flag == 1)) { + /*USE_BUF_BLOCK*/ + init_buf_list(hevc); + /**/ + init_pic_list(hevc); + init_pic_list_hw(hevc); + init_buf_spec(hevc); + hevc->pic_list_init_flag = 2; + hevc_print(hevc, 0, "set pic_list_init_flag to 2\n"); + + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1); + + } + + if (hevc->uninit_list) { + /*USE_BUF_BLOCK*/ + uninit_pic_list(hevc); + hevc_print(hevc, 0, "uninit list\n"); + hevc->uninit_list = 0; +#ifdef USE_UNINIT_SEMA + up(&hevc->h265_uninit_done_sema); +#endif + } + + } + + return 0; + +} + +void vh265_free_cmabuf(void) +{ + struct hevc_state_s *hevc = &gHevc; + + mutex_lock(&vh265_mutex); + + if (hevc->init_flag) { + mutex_unlock(&vh265_mutex); + return; + } + + mutex_unlock(&vh265_mutex); +} + +#ifdef MULTI_INSTANCE_SUPPORT +int vh265_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +#else +int vh265_dec_status(struct vdec_status *vstatus) +#endif +{ + struct hevc_state_s *hevc = &gHevc; + + vstatus->width = hevc->frame_width; + vstatus->height = hevc->frame_height; + if (hevc->frame_dur != 0) + vstatus->fps = 96000 / hevc->frame_dur; + else + vstatus->fps = -1; + vstatus->error_count = 0; + vstatus->status = hevc->stat | hevc->fatal_error; + return 0; +} + +#if 0 +static void H265_DECODE_INIT(void) +{ + /* enable hevc clocks */ + WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); + /* *************************************************************** */ + /* Power ON HEVC */ + /* *************************************************************** */ + /* Powerup HEVC */ + WRITE_VREG(P_AO_RTI_GEN_PWR_SLEEP0, + READ_VREG(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x3 << 6))); + WRITE_VREG(DOS_MEM_PD_HEVC, 0x0); + WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) | (0x3ffff << 2)); + WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) & (~(0x3ffff << 2))); + /* remove isolations */ + WRITE_VREG(AO_RTI_GEN_PWR_ISO0, + READ_VREG(AO_RTI_GEN_PWR_ISO0) & (~(0x3 << 10))); + +} +#endif + +static void config_decode_mode(struct hevc_state_s *hevc) +{ +#ifdef CONFIG_AM_VDEC_DV + struct vdec_s *vdec = hw_to_vdec(hevc); +#endif + if (!hevc->m_ins_flag) + WRITE_VREG(HEVC_DECODE_MODE, + DECODE_MODE_SINGLE); + else if (vdec_frame_based(hw_to_vdec(hevc))) + WRITE_VREG(HEVC_DECODE_MODE, + DECODE_MODE_MULTI_FRAMEBASE); +#ifdef CONFIG_AM_VDEC_DV + else if (vdec->slave) + WRITE_VREG(HEVC_DECODE_MODE, + (hevc->start_parser_type << 8) + | DECODE_MODE_MULTI_DVBAL); + else if (vdec->master) + WRITE_VREG(HEVC_DECODE_MODE, + (hevc->start_parser_type << 8) + | DECODE_MODE_MULTI_DVENL); +#endif + else + WRITE_VREG(HEVC_DECODE_MODE, + DECODE_MODE_MULTI_STREAMBASE); +} + +static void vh265_prot_init(struct hevc_state_s *hevc) +{ + /* H265_DECODE_INIT(); */ + + hevc_config_work_space_hw(hevc); + + hevc_init_decoder_hw(hevc, 0, 0xffffffff); + + WRITE_VREG(HEVC_WAIT_FLAG, 1); + + /* WRITE_VREG(P_HEVC_MPSR, 1); */ + + /* clear mailbox interrupt */ + WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 1); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(HEVC_PSCALE_CTRL, 0); + + if (get_dbg_flag(hevc) & H265_DEBUG_UCODE) + WRITE_VREG(DEBUG_REG1, 0x1); + else + WRITE_VREG(DEBUG_REG1, 0x0); + + if ((get_dbg_flag(hevc) & + (H265_DEBUG_MAN_SKIP_NAL | + H265_DEBUG_MAN_SEARCH_NAL))/* || + hevc->m_ins_flag*/) { + WRITE_VREG(NAL_SEARCH_CTL, 0x1); /* manual parser NAL */ + } else { + /* check vps/sps/pps/i-slice in ucode */ + unsigned ctl_val = 0x8; +#ifdef MULTI_INSTANCE_SUPPORT + if (hevc->m_ins_flag && + hevc->init_flag) { + /* do not check vps/sps/pps/i-slice in ucode + from the 2nd picture*/ + ctl_val = 0x2; + } else +#endif + if (hevc->PB_skip_mode == 0) + ctl_val = 0x4; /* check vps/sps/pps only in ucode */ + else if (hevc->PB_skip_mode == 3) + ctl_val = 0x0; /* check vps/sps/pps/idr in ucode */ + WRITE_VREG(NAL_SEARCH_CTL, ctl_val); + } + if (get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE) + WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x10000); + + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) + | ((parser_sei_enable & 0x7) << 17)); +#ifdef CONFIG_AM_VDEC_DV + WRITE_VREG(NAL_SEARCH_CTL, + READ_VREG(NAL_SEARCH_CTL) | + ((parser_dolby_vision_enable & 0x1) << 20)); +#endif + WRITE_VREG(DECODE_STOP_POS, decode_stop_pos); + + config_decode_mode(hevc); + config_aux_buf(hevc); +} + +static int vh265_local_init(struct hevc_state_s *hevc) +{ + int i; + int ret = -1; + +#ifdef DEBUG_PTS + hevc->pts_missed = 0; + hevc->pts_hit = 0; +#endif + + hevc->last_put_idx_a = -1; + hevc->last_put_idx_b = -1; + hevc->saved_resolution = 0; + hevc->get_frame_dur = false; + hevc->frame_width = hevc->vh265_amstream_dec_info.width; + hevc->frame_height = hevc->vh265_amstream_dec_info.height; + if (HEVC_SIZE < hevc->frame_width * hevc->frame_height) { + pr_info("over size : %u x %u.\n", + hevc->frame_width, hevc->frame_height); + hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; + return ret; + } + hevc->frame_dur = + (hevc->vh265_amstream_dec_info.rate == + 0) ? 3600 : hevc->vh265_amstream_dec_info.rate; + if (hevc->frame_width && hevc->frame_height) + hevc->frame_ar = hevc->frame_height * 0x100 / hevc->frame_width; + hevc->error_watchdog_count = 0; + hevc->sei_present_flag = 0; + pts_unstable = ((unsigned long)hevc->vh265_amstream_dec_info.param + & 0x40) >> 6; + hevc_print(hevc, 0, + "h265:pts_unstable=%d\n", pts_unstable); +/* +*TODO:FOR VERSION +*/ + hevc_print(hevc, 0, + "h265: ver (%d,%d) decinfo: %dx%d rate=%d\n", h265_version, + 0, hevc->frame_width, hevc->frame_height, hevc->frame_dur); + + if (hevc->frame_dur == 0) + hevc->frame_dur = 96000 / 24; + + INIT_KFIFO(hevc->display_q); + INIT_KFIFO(hevc->newframe_q); + + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &hevc->vfpool[i]; + + hevc->vfpool[i].index = -1; + kfifo_put(&hevc->newframe_q, vf); + } + + + ret = hevc_local_init(hevc); + + return ret; +} +#ifdef MULTI_INSTANCE_SUPPORT +static s32 vh265_init(struct vdec_s *vdec) +{ + struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; +#else +static s32 vh265_init(struct hevc_state_s *hevc) +{ + +#endif + int size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + init_timer(&hevc->timer); + + hevc->stat |= STAT_TIMER_INIT; + if (vh265_local_init(hevc) < 0) { + vfree(buf); + return -EBUSY; + } + +#ifdef MULTI_INSTANCE_SUPPORT + if (hevc->m_ins_flag) { + hevc->timer.data = (ulong) hevc; + hevc->timer.function = vh265_check_timer_func; + hevc->timer.expires = jiffies + PUT_INTERVAL; + + /*add_timer(&hevc->timer); + + hevc->stat |= STAT_TIMER_ARM;*/ + + INIT_WORK(&hevc->work, vh265_work); + vfree(buf); + return 0; + } +#endif + amhevc_enable(); + + if (mmu_enable && (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)) { + size = get_firmware_data(VIDEO_DEC_HEVC_MMU, buf); + hevc_print(hevc, 0, "vh265 mmu ucode loaded!\n"); + } else + size = get_firmware_data(VIDEO_DEC_HEVC, buf); + + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(buf); + return -1; + } + + if (amhevc_loadmc_ex(VFORMAT_HEVC, NULL, buf) < 0) { + amhevc_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + hevc->stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vh265_prot_init(hevc); + + if (vdec_request_threaded_irq(VDEC_IRQ_1, vh265_isr, + vh265_isr_thread_fn, + IRQF_ONESHOT,/*run thread on this irq disabled*/ + "vh265-irq", (void *)hevc)) { + hevc_print(hevc, 0, "vh265 irq register error.\n"); + amhevc_disable(); + return -ENOENT; + } + + hevc->stat |= STAT_ISR_REG; + hevc->provider_name = PROVIDER_NAME; + +#ifdef MULTI_INSTANCE_SUPPORT + vf_provider_init(&vh265_vf_prov, hevc->provider_name, + &vh265_vf_provider, vdec); + vf_reg_provider(&vh265_vf_prov); + vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_START, + NULL); + vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)hevc->frame_dur)); +#else + vf_provider_init(&vh265_vf_prov, PROVIDER_NAME, &vh265_vf_provider, + hevc); + vf_reg_provider(&vh265_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)hevc->frame_dur)); +#endif + hevc->stat |= STAT_VF_HOOK; + + hevc->timer.data = (ulong) hevc; + hevc->timer.function = vh265_check_timer_func; + hevc->timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&hevc->timer); + + hevc->stat |= STAT_TIMER_ARM; + + if (use_cma) { + if (h265_task == NULL) { + sema_init(&hevc->h265_sema, 1); +#ifdef USE_UNINIT_SEMA + sema_init( + &hevc->h265_uninit_done_sema, 0); +#endif + h265_task = + kthread_run(h265_task_handle, hevc, + "kthread_h265"); + } + } + /* hevc->stat |= STAT_KTHREAD; */ + + if (get_dbg_flag(hevc) & H265_DEBUG_FORCE_CLK) { + hevc_print(hevc, 0, "%s force clk\n", __func__); + WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, + READ_VREG(HEVC_IQIT_CLK_RST_CTRL) | + ((1 << 2) | (1 << 1))); + WRITE_VREG(HEVC_DBLK_CFG0, + READ_VREG(HEVC_DBLK_CFG0) | ((1 << 2) | + (1 << 1) | 0x3fff0000));/* 2,29:16 */ + WRITE_VREG(HEVC_SAO_CTRL1, READ_VREG(HEVC_SAO_CTRL1) | + (1 << 2)); /* 2 */ + WRITE_VREG(HEVC_MPRED_CTRL1, READ_VREG(HEVC_MPRED_CTRL1) | + (1 << 24)); /* 24 */ + WRITE_VREG(HEVC_STREAM_CONTROL, + READ_VREG(HEVC_STREAM_CONTROL) | + (1 << 15)); /* 15 */ + WRITE_VREG(HEVC_CABAC_CONTROL, READ_VREG(HEVC_CABAC_CONTROL) | + (1 << 13)); /* 13 */ + WRITE_VREG(HEVC_PARSER_CORE_CONTROL, + READ_VREG(HEVC_PARSER_CORE_CONTROL) | + (1 << 15)); /* 15 */ + WRITE_VREG(HEVC_PARSER_INT_CONTROL, + READ_VREG(HEVC_PARSER_INT_CONTROL) | + (1 << 15)); /* 15 */ + WRITE_VREG(HEVC_PARSER_IF_CONTROL, + READ_VREG(HEVC_PARSER_IF_CONTROL) | ((1 << 6) | + (1 << 3) | (1 << 1))); /* 6, 3, 1 */ + WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, + READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG) | + 0xffffffff); /* 31:0 */ + WRITE_VREG(HEVCD_MCRCC_CTL1, READ_VREG(HEVCD_MCRCC_CTL1) | + (1 << 3)); /* 3 */ + } + + amhevc_start(); + + hevc->stat |= STAT_VDEC_RUN; +#ifndef MULTI_INSTANCE_SUPPORT + set_vdec_func(&vh265_dec_status); +#endif + hevc->init_flag = 1; + if (mmu_enable) + error_handle_threshold = 300; + else + error_handle_threshold = 30; + /* pr_info("%d, vh265_init, RP=0x%x\n", + __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); */ + + return 0; +} + +static int vh265_stop(struct hevc_state_s *hevc) +{ + + hevc->init_flag = 0; + + if (get_dbg_flag(hevc) & + H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP) { + int wait_timeout_count = 0; + + while (READ_VREG(HEVC_DEC_STATUS_REG) == + HEVC_CODED_SLICE_SEGMENT_DAT && + wait_timeout_count < 10){ + wait_timeout_count++; + msleep(20); + } + } + if (hevc->stat & STAT_VDEC_RUN) { + amhevc_stop(); + hevc->stat &= ~STAT_VDEC_RUN; + } + + if (hevc->stat & STAT_ISR_REG) { + WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hevc); + hevc->stat &= ~STAT_ISR_REG; + } + + hevc->stat &= ~STAT_TIMER_INIT; + if (hevc->stat & STAT_TIMER_ARM) { + del_timer_sync(&hevc->timer); + hevc->stat &= ~STAT_TIMER_ARM; + } + + if (hevc->stat & STAT_VF_HOOK) { + vf_notify_receiver(hevc->provider_name, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vh265_vf_prov); + hevc->stat &= ~STAT_VF_HOOK; + } + + hevc_local_uninit(hevc); + + if (use_cma) { +#ifdef USE_UNINIT_SEMA + int ret; +#endif + hevc->uninit_list = 1; + up(&hevc->h265_sema); +#ifdef USE_UNINIT_SEMA + ret = down_interruptible( + &hevc->h265_uninit_done_sema); +#else + while (hevc->uninit_list) /* wait uninit complete */ + msleep(20); +#endif + + } + uninit_mmu_buffers(hevc); + amhevc_disable(); + + return 0; +} + +#ifdef MULTI_INSTANCE_SUPPORT +static void reset_process_time(struct hevc_state_s *hevc) +{ + if (hevc->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hevc->start_process_time) / HZ; + hevc->start_process_time = 0; + if (process_time > max_process_time[hevc->index]) + max_process_time[hevc->index] = process_time; + } +} + +static void start_process_time(struct hevc_state_s *hevc) +{ + hevc->start_process_time = jiffies; + hevc->decode_timeout_count = 2; + hevc->last_lcu_idx = 0; +} + +static void timeout_process(struct hevc_state_s *hevc) +{ + hevc->timeout_num++; + amhevc_stop(); + hevc_print(hevc, + 0, "%s decoder timeout\n", __func__); + + hevc->dec_result = DEC_RESULT_DONE; + reset_process_time(hevc); + schedule_work(&hevc->work); +} + +static unsigned char is_new_pic_available(struct hevc_state_s *hevc) +{ + struct PIC_s *new_pic = NULL; + struct PIC_s *pic; + /* recycle un-used pic */ + int i; + /*return 1 if pic_list is not initialized yet*/ + if (hevc->pic_list_init_flag != 3) + return 1; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if ((pic->used_by_display) + && ((READ_VCBUS_REG(AFBC_BODY_BADDR) << 4) != + pic->mc_y_adr)) + pic->used_by_display = 0; + if (pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 0 + && pic->used_by_display == 0) { + if (new_pic) { + if (pic->POC < new_pic->POC) + new_pic = pic; + } else + new_pic = pic; + } + } + return (new_pic != NULL) ? 1 : 0; +} + +static int vmh265_stop(struct hevc_state_s *hevc) +{ + hevc->init_flag = 0; + + if (hevc->stat & STAT_TIMER_ARM) { + del_timer_sync(&hevc->timer); + hevc->stat &= ~STAT_TIMER_ARM; + } + + if (hevc->stat & STAT_VF_HOOK) { + vf_notify_receiver(hevc->provider_name, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vh265_vf_prov); + hevc->stat &= ~STAT_VF_HOOK; + } + + hevc_local_uninit(hevc); + + if (use_cma) { +#ifdef USE_UNINIT_SEMA + int ret; +#endif + hevc->uninit_list = 1; + reset_process_time(hevc); + schedule_work(&hevc->work); +#ifdef USE_UNINIT_SEMA + ret = down_interruptible( + &hevc->h265_uninit_done_sema); +#else + while (hevc->uninit_list) /* wait uninit complete */ + msleep(20); +#endif + } + cancel_work_sync(&hevc->work); + uninit_mmu_buffers(hevc); + return 0; +} + +static unsigned int start_decode_buf_level; /* = 0x80000;*/ + +static unsigned char get_data_check_sum + (struct hevc_state_s *hevc, int size) +{ + int jj; + int sum = 0; + u8 *data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < size; jj++) + sum += data[jj]; + return sum; +} + +static void vh265_work(struct work_struct *work) +{ + struct hevc_state_s *hevc = container_of(work, + struct hevc_state_s, work); + struct vdec_s *vdec = hw_to_vdec(hevc); + /* finished decoding one frame or error, + * notify vdec core to switch context + */ + if ((hevc->init_flag != 0) && (hevc->pic_list_init_flag == 1)) { + /*USE_BUF_BLOCK*/ + init_buf_list(hevc); + /**/ + init_pic_list(hevc); + init_pic_list_hw(hevc); + init_buf_spec(hevc); + hevc->pic_list_init_flag = 2; + hevc_print(hevc, 0, + "set pic_list_init_flag to 2\n"); + + start_process_time(hevc); + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1); + return; + } + + if (hevc->uninit_list) { + /*USE_BUF_BLOCK*/ + uninit_pic_list(hevc); + hevc_print(hevc, 0, "uninit list\n"); + hevc->uninit_list = 0; +#ifdef USE_UNINIT_SEMA + up(&hevc->h265_uninit_done_sema); +#endif + return; + } + + if ((hevc->dec_result == DEC_RESULT_GET_DATA) || + (hevc->dec_result == DEC_RESULT_GET_DATA_RETRY)) { + if (hevc->dec_result == DEC_RESULT_GET_DATA) { + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s DEC_RESULT_GET_DATA %x %x %x mpc %x\n", + __func__, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR), + READ_VREG(HEVC_MPC_E)); + vdec_vframe_dirty(vdec, hevc->chunk); + vdec_clean_input(vdec); + } + + /*if (is_new_pic_available(hevc)) {*/ + if (run_ready(vdec)) { + int r; + r = vdec_prepare_input(vdec, &hevc->chunk); + if (r < 0) { + hevc->dec_result = DEC_RESULT_GET_DATA_RETRY; + + hevc_print(hevc, + PRINT_FLAG_VDEC_DETAIL, + "amvdec_vh265: Insufficient data\n"); + + schedule_work(&hevc->work); + return; + } + hevc->dec_result = DEC_RESULT_NONE; + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s: chunk size 0x%x sum 0x%x mpc %x\n", + __func__, r, + (get_dbg_flag(hevc) & PRINT_FLAG_VDEC_STATUS) ? + get_data_check_sum(hevc, r) : 0, + READ_VREG(HEVC_MPC_E)); + if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) && + input_frame_based(vdec)) { + int jj; + u8 *data = + ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < r; jj++) { + if ((jj & 0xf) == 0) + hevc_print(hevc, + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + hevc_print_cont(hevc, + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + hevc_print_cont(hevc, + PRINT_FRAMEBASE_DATA, + "\n"); + } + } + + WRITE_VREG(HEVC_DECODE_SIZE, r); + + vdec_enable_input(vdec); + + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s: mpc %x\n", + __func__, READ_VREG(HEVC_MPC_E)); + + start_process_time(hevc); + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + } else{ + hevc->dec_result = DEC_RESULT_GET_DATA_RETRY; + + /*hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, + "amvdec_vh265: Insufficient data\n"); + */ + + schedule_work(&hevc->work); + } + return; + } else if (hevc->dec_result == DEC_RESULT_DONE) { + /* if (!hevc->ctx_valid) + hevc->ctx_valid = 1; */ + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s dec_result %d %x %x %x\n", + __func__, + hevc->dec_result, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); +#ifdef CONFIG_AM_VDEC_DV +#if 1 + if (vdec->slave) { + if (dv_debug & 0x1) + vdec_set_flag(vdec->slave, 0); + else + vdec_set_flag(vdec->slave, + VDEC_FLAG_INPUT_KEEP_CONTEXT); + } +#else + if (vdec->slave) { + if (no_interleaved_el_slice) + vdec_set_flag(vdec->slave, + VDEC_FLAG_INPUT_KEEP_CONTEXT); + /* this will move real HW pointer for input */ + else + vdec_set_flag(vdec->slave, 0); + /* this will not move real HW pointer + and SL layer decoding + will start from same stream position + as current BL decoder */ + } +#endif +#endif + vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); + } else { + hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, + "%s dec_result %d %x %x %x\n", + __func__, + hevc->dec_result, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); + } + + if (hevc->stat & STAT_TIMER_ARM) { + del_timer_sync(&hevc->timer); + hevc->stat &= ~STAT_TIMER_ARM; + } + /* mark itself has all HW resource released and input released */ + vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_CONNECTED); + +#ifdef CONFIG_AM_VDEC_DV + if (hevc->switch_dvlayer_flag) { + if (vdec->slave) + vdec_set_next_sched(vdec, vdec->slave); + else if (vdec->master) + vdec_set_next_sched(vdec, vdec->master); + } else if (vdec->slave || vdec->master) + vdec_set_next_sched(vdec, vdec); +#endif + + if (hevc->vdec_cb) + hevc->vdec_cb(hw_to_vdec(hevc), hevc->vdec_cb_arg); +} + +static int vh265_hw_ctx_restore(struct hevc_state_s *hevc) +{ + /* new to do ... */ + vh265_prot_init(hevc); + return 0; +} + +static bool run_ready(struct vdec_s *vdec) +{ + struct hevc_state_s *hevc = + (struct hevc_state_s *)vdec->private; + + /*hevc_print(hevc, + PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + */ + if ((!vdec_frame_based(vdec)) && (start_decode_buf_level > 0)) { + u32 rp, wp; + u32 level; + + rp = READ_MPEG_REG(PARSER_VIDEO_RP); + wp = READ_MPEG_REG(PARSER_VIDEO_WP); + + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < start_decode_buf_level) { + hevc_print(hevc, 0, + "level %d not run_ready\n", level); + return false; + } + } else if (vdec_frame_based(vdec)) { + if (!vdec_input_next_input_chunk(&vdec->input)) + return false; + } + + return is_new_pic_available(hevc); +} + +static void reset_dec_hw(struct vdec_s *vdec) +{ + if (input_frame_based(vdec)) + WRITE_VREG(HEVC_STREAM_CONTROL, 0); + + /* + * 2: assist + * 3: parser + * 4: parser_state + * 8: dblk + * 11:mcpu + * 12:ccpu + * 13:ddr + * 14:iqit + * 15:ipp + * 17:qdct + * 18:mpred + * 19:sao + * 24:hevc_afifo + */ + WRITE_VREG(DOS_SW_RESET3, + (1<<3)|(1<<4)|(1<<8)|(1<<11)|(1<<12)|(1<<14)|(1<<15)| + (1<<17)|(1<<18)|(1<<19)); + WRITE_VREG(DOS_SW_RESET3, 0); +} + +static void run(struct vdec_s *vdec, + void (*callback)(struct vdec_s *, void *), void *arg) +{ + struct hevc_state_s *hevc = + (struct hevc_state_s *)vdec->private; + int r; + + hevc->vdec_cb_arg = arg; + hevc->vdec_cb = callback; + + reset_dec_hw(vdec); + + r = vdec_prepare_input(vdec, &hevc->chunk); + if (r < 0) { + hevc->dec_result = DEC_RESULT_AGAIN; + + hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, + "ammvdec_vh265: Insufficient data\n"); + + schedule_work(&hevc->work); + return; + } + + hevc->dec_result = DEC_RESULT_NONE; + + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s: size 0x%x sum 0x%x (%x %x %x)\n", + __func__, r, + (vdec_frame_based(vdec) && + (get_dbg_flag(hevc) & PRINT_FLAG_VDEC_STATUS)) ? + get_data_check_sum(hevc, r) : 0, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); + if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) && + input_frame_based(vdec)) { + int jj; + u8 *data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < r; jj++) { + if ((jj & 0xf) == 0) + hevc_print(hevc, PRINT_FRAMEBASE_DATA, + "%06x:", jj); + hevc_print_cont(hevc, PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + hevc_print_cont(hevc, PRINT_FRAMEBASE_DATA, + "\n"); + } + } + if (hevc->init_flag == 0) { + if (amhevc_vdec_loadmc_ex(vdec, "vh265_mc") < 0) { + amhevc_disable(); + hevc_print(hevc, 0, + "%s: Error amvdec_loadmc fail\n", __func__); + return; + } + } + if (vh265_hw_ctx_restore(hevc) < 0) { + schedule_work(&hevc->work); + return; + } + + vdec_enable_input(vdec); + + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + + if (vdec_frame_based(vdec)) + WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); + + WRITE_VREG(HEVC_DECODE_SIZE, r); + /*WRITE_VREG(HEVC_DECODE_COUNT, hevc->decode_idx);*/ + hevc->init_flag = 1; + + if (hevc->pic_list_init_flag == 3) + init_pic_list_hw(hevc); + + start_process_time(hevc); + add_timer(&hevc->timer); + hevc->stat |= STAT_TIMER_ARM; + amhevc_start(); + +} + +static void reset(struct vdec_s *vdec) +{ + + struct hevc_state_s *hevc = + (struct hevc_state_s *)vdec->private; + + hevc_print(hevc, + PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + +} + +static irqreturn_t vh265_irq_cb(struct vdec_s *vdec) +{ + struct hevc_state_s *hevc = + (struct hevc_state_s *)vdec->private; + + return vh265_isr(0, hevc); +} + +static irqreturn_t vh265_threaded_irq_cb(struct vdec_s *vdec) +{ + struct hevc_state_s *hevc = + (struct hevc_state_s *)vdec->private; + + return vh265_isr_thread_fn(0, hevc); +} +#endif + +static int amvdec_h265_probe(struct platform_device *pdev) +{ +#ifdef MULTI_INSTANCE_SUPPORT + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; +#else + struct vdec_dev_reg_s *pdata = + (struct vdec_dev_reg_s *)pdev->dev.platform_data; +#endif + struct hevc_state_s *hevc = &gHevc; + + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, "%s\r\n", __func__); + mutex_lock(&vh265_mutex); + + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) && + (parser_sei_enable & 0x100) == 0) + parser_sei_enable = 1; + hevc->m_ins_flag = 0; + hevc->init_flag = 0; + hevc->uninit_list = 0; + hevc->fatal_error = 0; + hevc->show_frame_num = 0; + if (pdata == NULL) { + hevc_print(hevc, 0, + "\namvdec_h265 memory resource undefined.\n"); + mutex_unlock(&vh265_mutex); + return -EFAULT; + } +#ifndef CONFIG_MULTI_DEC + if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXL + || double_write_mode == 0x10) + mmu_enable = 0; + else + mmu_enable = 1; +#endif + if (init_mmu_buffers(hevc)) { + hevc_print(hevc, 0, + "\n 265 mmu init failed!\n"); + mutex_unlock(&vh265_mutex); + return -EFAULT; + } + hevc->buf_start = pdata->mem_start; + hevc->buf_size = pdata->mem_end - pdata->mem_start + 1; + /* + hevc->mc_buf_spec.buf_end = pdata->mem_end + 1; + for (i = 0; i < WORK_BUF_SPEC_NUM; i++) + amvh265_workbuff_spec[i].start_adr = pdata->mem_start; + */ + + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "===H.265 decoder mem resource 0x%lx -- 0x%lx\n", + pdata->mem_start, pdata->mem_end + 1); + } + + if (pdata->sys_info) + hevc->vh265_amstream_dec_info = *pdata->sys_info; + else { + hevc->vh265_amstream_dec_info.width = 0; + hevc->vh265_amstream_dec_info.height = 0; + hevc->vh265_amstream_dec_info.rate = 30; + } +#ifndef MULTI_INSTANCE_SUPPORT + if (pdata->flag & DEC_FLAG_HEVC_WORKAROUND) { + workaround_enable |= 3; + hevc_print(hevc, 0, + "amvdec_h265 HEVC_WORKAROUND flag set.\n"); + } else + workaround_enable &= ~3; +#endif + hevc->cma_dev = pdata->cma_dev; +#ifdef MULTI_INSTANCE_SUPPORT + pdata->private = hevc; + pdata->dec_status = vh265_dec_status; + if (vh265_init(pdata) < 0) { +#else + if (vh265_init(hevc) < 0) { +#endif + hevc_print(hevc, 0, + "\namvdec_h265 init failed.\n"); + hevc_local_uninit(hevc); + uninit_mmu_buffers(hevc); + mutex_unlock(&vh265_mutex); + return -ENODEV; + } + /*set the max clk for smooth playing...*/ + hevc_source_changed(VFORMAT_HEVC, + 3840, 2160, 60); + mutex_unlock(&vh265_mutex); + + return 0; +} + +static int amvdec_h265_remove(struct platform_device *pdev) +{ + struct hevc_state_s *hevc = &gHevc; + + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, "%s\r\n", __func__); + + mutex_lock(&vh265_mutex); + + vh265_stop(hevc); + + hevc_source_changed(VFORMAT_HEVC, 0, 0, 0); + + +#ifdef DEBUG_PTS + hevc_print(hevc, 0, + "pts missed %ld, pts hit %ld, duration %d\n", + hevc->pts_missed, hevc->pts_hit, hevc->frame_dur); +#endif + + mutex_unlock(&vh265_mutex); + + return 0; +} +/****************************************/ + +static struct platform_driver amvdec_h265_driver = { + .probe = amvdec_h265_probe, + .remove = amvdec_h265_remove, +#ifdef CONFIG_PM + .suspend = amhevc_suspend, + .resume = amhevc_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +#ifdef MULTI_INSTANCE_SUPPORT +static int ammvdec_h265_probe(struct platform_device *pdev) +{ + + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct hevc_state_s *hevc = NULL; +#ifdef CONFIG_MULTI_DEC + int config_val; +#endif + if (pdata == NULL) { + pr_info("\nammvdec_h265 memory resource undefined.\n"); + return -EFAULT; + } + + hevc = (struct hevc_state_s *)devm_kzalloc(&pdev->dev, + sizeof(struct hevc_state_s), GFP_KERNEL); + if (hevc == NULL) { + pr_info("\nammvdec_h265 device data allocation failed\n"); + return -ENOMEM; + } + pdata->private = hevc; + pdata->dec_status = vh265_dec_status; + /* pdata->set_trickmode = set_trickmode; */ + pdata->run_ready = run_ready; + pdata->run = run; + pdata->reset = reset; + pdata->irq_handler = vh265_irq_cb; + pdata->threaded_irq_handler = vh265_threaded_irq_cb; + + pdata->id = pdev->id; + hevc->index = pdev->id; + + if (pdata->use_vfm_path) + snprintf(pdata->vf_provider_name, + VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); +#ifdef CONFIG_AM_VDEC_DV + else if (vdec_dual(pdata)) { + if (dv_toggle_prov_name) /*debug purpose*/ + snprintf(pdata->vf_provider_name, + VDEC_PROVIDER_NAME_SIZE, + (pdata->master) ? VFM_DEC_DVBL_PROVIDER_NAME : + VFM_DEC_DVEL_PROVIDER_NAME); + else + snprintf(pdata->vf_provider_name, + VDEC_PROVIDER_NAME_SIZE, + (pdata->master) ? VFM_DEC_DVEL_PROVIDER_NAME : + VFM_DEC_DVBL_PROVIDER_NAME); + hevc->dolby_enhance_flag = pdata->master ? 1 : 0; + } +#endif + else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); + + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vh265_vf_provider, pdata); + + hevc->provider_name = pdata->vf_provider_name; + platform_set_drvdata(pdev, pdata); + + hevc->platform_dev = pdev; + if (init_mmu_buffers(hevc) < 0) { + hevc_print(hevc, 0, + "\n 265 mmu init failed!\n"); + mutex_unlock(&vh265_mutex); + devm_kfree(&pdev->dev, (void *)hevc); + return -EFAULT; + } +#if 0 + hevc->buf_start = pdata->mem_start; + hevc->buf_size = pdata->mem_end - pdata->mem_start + 1; +#else + + if (decoder_bmmu_box_alloc_idx_wait( + hevc->bmmu_box, + BMMU_WORKSPACE_ID, + work_buf_size, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR) < 0) { + hevc_print(hevc, 0, + "workbuf alloc failed, request buf size 0x%lx\n", + work_buf_size); + uninit_mmu_buffers(hevc); + devm_kfree(&pdev->dev, (void *)hevc); + return -ENOMEM; + } + hevc->buf_start = decoder_bmmu_box_get_phy_addr( + hevc->bmmu_box, + BMMU_WORKSPACE_ID); + hevc->buf_size = work_buf_size; +#endif + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) && + (parser_sei_enable & 0x100) == 0) + parser_sei_enable = 1; + hevc->m_ins_flag = 1; + hevc->init_flag = 0; + hevc->uninit_list = 0; + hevc->fatal_error = 0; + hevc->show_frame_num = 0; + if (pdata == NULL) { + hevc_print(hevc, 0, + "\namvdec_h265 memory resource undefined.\n"); + uninit_mmu_buffers(hevc); + devm_kfree(&pdev->dev, (void *)hevc); + return -EFAULT; + } + /* + hevc->mc_buf_spec.buf_end = pdata->mem_end + 1; + for (i = 0; i < WORK_BUF_SPEC_NUM; i++) + amvh265_workbuff_spec[i].start_adr = pdata->mem_start; + */ + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, + "===H.265 decoder mem resource 0x%lx -- 0x%lx\n", + hevc->buf_start, hevc->buf_start + hevc->buf_size); + } + + if (((get_dbg_flag(hevc) & IGNORE_PARAM_FROM_CONFIG) == 0) && + pdata->config && pdata->config_len) { +#ifdef CONFIG_MULTI_DEC + /*use ptr config for doubel_write_mode, etc*/ + hevc_print(hevc, 0, "pdata->config=%s\n", pdata->config); + if (get_config_int(pdata->config, "hevc_buf_width", + &config_val) == 0) + hevc->buf_alloc_width = config_val; + else + hevc->buf_alloc_width = buf_alloc_width; + + if (get_config_int(pdata->config, "hevc_buf_height", + &config_val) == 0) + hevc->buf_alloc_height = config_val; + else + hevc->buf_alloc_height = buf_alloc_height; + + if (get_config_int(pdata->config, "hevc_buf_margin", + &config_val) == 0) + hevc->dynamic_buf_num_margin = config_val; + else + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; + + if (get_config_int(pdata->config, "hevc_double_write_mode", + &config_val) == 0) + hevc->double_write_mode = config_val; + else + hevc->double_write_mode = double_write_mode; +#endif + } else { + hevc->vh265_amstream_dec_info.width = 0; + hevc->vh265_amstream_dec_info.height = 0; + hevc->vh265_amstream_dec_info.rate = 30; + hevc->buf_alloc_width = buf_alloc_width; + hevc->buf_alloc_height = buf_alloc_height; + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; + hevc->double_write_mode = double_write_mode; + } + hevc_print(hevc, 0, + "buf_alloc_width=%d\n", + hevc->buf_alloc_width); + hevc_print(hevc, 0, + "buf_alloc_height=%d\n", + hevc->buf_alloc_height); + hevc_print(hevc, 0, + "dynamic_buf_num_margin=%d\n", + hevc->dynamic_buf_num_margin); + hevc_print(hevc, 0, + "double_write_mode=%d\n", + hevc->double_write_mode); + + hevc->cma_dev = pdata->cma_dev; + + if (vh265_init(pdata) < 0) { + hevc_print(hevc, 0, + "\namvdec_h265 init failed.\n"); + hevc_local_uninit(hevc); + uninit_mmu_buffers(hevc); + devm_kfree(&pdev->dev, (void *)hevc); + return -ENODEV; + } + + /*set the max clk for smooth playing...*/ + hevc_source_changed(VFORMAT_HEVC, + 3840, 2160, 60); + + return 0; +} + +static int ammvdec_h265_remove(struct platform_device *pdev) +{ + struct hevc_state_s *hevc = + (struct hevc_state_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, "%s\r\n", __func__); + + vmh265_stop(hevc); + + /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ + + vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_DISCONNECTED); + + return 0; +} + +static struct platform_driver ammvdec_h265_driver = { + .probe = ammvdec_h265_probe, + .remove = ammvdec_h265_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = MULTI_DRIVER_NAME, + } +}; +#endif + +static struct codec_profile_t amvdec_h265_profile = { + .name = "hevc", + .profile = "" +}; + +static int __init amvdec_h265_driver_init_module(void) +{ + pr_debug("amvdec_h265 module init\n"); + error_handle_policy = 0; + +#ifdef ERROR_HANDLE_DEBUG + dbg_nal_skip_flag = 0; + dbg_nal_skip_count = 0; +#endif + decode_stop_pos = 0; + decode_stop_pos_pre = 0; + decode_pic_begin = 0; + slice_parse_begin = 0; + step = 0; + buf_alloc_size = 0; + +#ifdef MULTI_INSTANCE_SUPPORT + if (platform_driver_register(&ammvdec_h265_driver)) + pr_err("failed to register ammvdec_h265 driver\n"); + +#endif + if (platform_driver_register(&amvdec_h265_driver)) { + pr_err("failed to register amvdec_h265 driver\n"); + return -ENODEV; + } +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ + if (!has_hevc_vdec()) { + /* not support hevc */ + amvdec_h265_profile.name = "hevc_unsupport"; + } else if (is_meson_m8m2_cpu()) { + /* m8m2 support 4k */ + amvdec_h265_profile.profile = "4k"; + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + amvdec_h265_profile.profile = + "4k, 9bit, 10bit, dwrite, compressed"; + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_MG9TV) + amvdec_h265_profile.profile = "4k"; +#endif + if (codec_mm_get_total_size() < 80 * SZ_1M) { + pr_info("amvdec_h265 default mmu enabled.\n"); + mmu_enable = 1; + } + + vcodec_profile_register(&amvdec_h265_profile); + + return 0; +} + +static void __exit amvdec_h265_driver_remove_module(void) +{ + pr_debug("amvdec_h265 module remove.\n"); + +#ifdef MULTI_INSTANCE_SUPPORT + platform_driver_unregister(&ammvdec_h265_driver); +#endif + platform_driver_unregister(&amvdec_h265_driver); +} + +/****************************************/ +/* +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_h265 stat\n"); +*/ +module_param(use_cma, uint, 0664); +MODULE_PARM_DESC(use_cma, "\n amvdec_h265 use_cma\n"); + +module_param(bit_depth_luma, uint, 0664); +MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_h265 bit_depth_luma\n"); + +module_param(bit_depth_chroma, uint, 0664); +MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_h265 bit_depth_chroma\n"); + +module_param(video_signal_type, uint, 0664); +MODULE_PARM_DESC(video_signal_type, "\n amvdec_h265 video_signal_type\n"); + +#ifdef ERROR_HANDLE_DEBUG +module_param(dbg_nal_skip_flag, uint, 0664); +MODULE_PARM_DESC(dbg_nal_skip_flag, "\n amvdec_h265 dbg_nal_skip_flag\n"); + +module_param(dbg_nal_skip_count, uint, 0664); +MODULE_PARM_DESC(dbg_nal_skip_count, "\n amvdec_h265 dbg_nal_skip_count\n"); +#endif + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(dbg_cmd, uint, 0664); +MODULE_PARM_DESC(dbg_cmd, "\ndbg_cmd\n"); + +module_param(dbg_skip_decode_index, uint, 0664); +MODULE_PARM_DESC(dbg_skip_decode_index, "\ndbg_skip_decode_index\n"); + +module_param(endian, uint, 0664); +MODULE_PARM_DESC(endian, "\nrval\n"); + +module_param(step, uint, 0664); +MODULE_PARM_DESC(step, "\n amvdec_h265 step\n"); + +module_param(decode_stop_pos, uint, 0664); +MODULE_PARM_DESC(decode_stop_pos, "\n amvdec_h265 decode_stop_pos\n"); + +module_param(decode_pic_begin, uint, 0664); +MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_h265 decode_pic_begin\n"); + +module_param(slice_parse_begin, uint, 0664); +MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_h265 slice_parse_begin\n"); + +module_param(nal_skip_policy, uint, 0664); +MODULE_PARM_DESC(nal_skip_policy, "\n amvdec_h265 nal_skip_policy\n"); + +module_param(i_only_flag, uint, 0664); +MODULE_PARM_DESC(i_only_flag, "\n amvdec_h265 i_only_flag\n"); + +module_param(error_handle_policy, uint, 0664); +MODULE_PARM_DESC(error_handle_policy, "\n amvdec_h265 error_handle_policy\n"); + +module_param(error_handle_threshold, uint, 0664); +MODULE_PARM_DESC(error_handle_threshold, + "\n amvdec_h265 error_handle_threshold\n"); + +module_param(error_handle_nal_skip_threshold, uint, 0664); +MODULE_PARM_DESC(error_handle_nal_skip_threshold, + "\n amvdec_h265 error_handle_nal_skip_threshold\n"); + +module_param(error_handle_system_threshold, uint, 0664); +MODULE_PARM_DESC(error_handle_system_threshold, + "\n amvdec_h265 error_handle_system_threshold\n"); + +module_param(error_skip_nal_count, uint, 0664); +MODULE_PARM_DESC(error_skip_nal_count, + "\n amvdec_h265 error_skip_nal_count\n"); + +module_param(debug, uint, 0664); +MODULE_PARM_DESC(debug, "\n amvdec_h265 debug\n"); + +module_param(debug_mask, uint, 0664); +MODULE_PARM_DESC(debug_mask, "\n amvdec_h265 debug mask\n"); + +module_param(buffer_mode, uint, 0664); +MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n"); + +module_param(double_write_mode, uint, 0664); +MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); + +module_param(buf_alloc_width, uint, 0664); +MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); + +module_param(buf_alloc_height, uint, 0664); +MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n"); + +module_param(dynamic_buf_num_margin, uint, 0664); +MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); + +module_param(max_buf_num, uint, 0664); +MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); + +module_param(buf_alloc_size, uint, 0664); +MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); + +module_param(re_config_pic_flag, uint, 0664); +MODULE_PARM_DESC(re_config_pic_flag, "\n re_config_pic_flag\n"); + +module_param(buffer_mode_dbg, uint, 0664); +MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n"); + +module_param(mem_map_mode, uint, 0664); +MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); + +module_param(enable_mem_saving, uint, 0664); +MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n"); + +module_param(force_w_h, uint, 0664); +MODULE_PARM_DESC(force_w_h, "\n force_w_h\n"); + +module_param(force_fps, uint, 0664); +MODULE_PARM_DESC(force_fps, "\n force_fps\n"); + +module_param(max_decoding_time, uint, 0664); +MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n"); + +module_param(prefix_aux_buf_size, uint, 0664); +MODULE_PARM_DESC(prefix_aux_buf_size, "\n prefix_aux_buf_size\n"); + +module_param(suffix_aux_buf_size, uint, 0664); +MODULE_PARM_DESC(suffix_aux_buf_size, "\n suffix_aux_buf_size\n"); + +module_param(interlace_enable, uint, 0664); +MODULE_PARM_DESC(interlace_enable, "\n interlace_enable\n"); +module_param(pts_unstable, uint, 0664); +MODULE_PARM_DESC(pts_unstable, "\n amvdec_h265 pts_unstable\n"); +module_param(parser_sei_enable, uint, 0664); +MODULE_PARM_DESC(parser_sei_enable, "\n parser_sei_enable\n"); + +#ifdef CONFIG_AM_VDEC_DV +module_param(parser_dolby_vision_enable, uint, 0664); +MODULE_PARM_DESC(parser_dolby_vision_enable, + "\n parser_dolby_vision_enable\n"); +#endif + +#ifdef MULTI_INSTANCE_SUPPORT +module_param(start_decode_buf_level, uint, 0664); +MODULE_PARM_DESC(start_decode_buf_level, + "\n h265 start_decode_buf_level\n"); + +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, + "\n h265 decode_timeout_val\n"); + +module_param_array(decode_frame_count, uint, + &max_decode_instance_num, 0664); + +module_param_array(max_process_time, uint, + &max_decode_instance_num, 0664); + +module_param_array(max_get_frame_interval, + uint, &max_decode_instance_num, 0664); + +#endif +#ifdef CONFIG_AM_VDEC_DV +module_param(dv_toggle_prov_name, uint, 0664); +MODULE_PARM_DESC(dv_toggle_prov_name, "\n dv_toggle_prov_name\n"); + +module_param(dv_debug, uint, 0664); +MODULE_PARM_DESC(dv_debug, "\n dv_debug\n"); +#endif + +module_init(amvdec_h265_driver_init_module); +module_exit(amvdec_h265_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC h265 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h new file mode 100644 index 000000000000..8b1054132fa3 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.h @@ -0,0 +1,27 @@ +/* + * drivers/amlogic/amports/vh265.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VH265_H +#define VH265_H + +extern u32 get_blackout_policy(void); + +extern s32 vh265_init(void); + +extern s32 vh265_release(void); + +#endif /* VMPEG4_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c new file mode 100644 index 000000000000..db273821e35d --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c @@ -0,0 +1,912 @@ +/* + * drivers/amlogic/amports/vmjpeg.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../../../stream_input/amports/amports_priv.h" +#include + +#ifdef CONFIG_AM_VDEC_MJPEG_LOG +#define AMLOG +#define LOG_LEVEL_VAR amlog_level_vmjpeg +#define LOG_MASK_VAR amlog_mask_vmjpeg +#define LOG_LEVEL_ERROR 0 +#define LOG_LEVEL_INFO 1 +#define LOG_LEVEL_DESC "0:ERROR, 1:INFO" +#endif +#include +MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); + +#include "../utils/amvdec.h" + +#define DRIVER_NAME "amvdec_mjpeg" +#define MODULE_NAME "amvdec_mjpeg" + +/* protocol register usage + AV_SCRATCH_0 - AV_SCRATCH_1 : initial display buffer fifo + AV_SCRATCH_2 - AV_SCRATCH_3 : decoder settings + AV_SCRATCH_4 - AV_SCRATCH_7 : display buffer spec + AV_SCRATCH_8 - AV_SCRATCH_9 : amrisc/host display buffer management + AV_SCRATCH_a : time stamp +*/ + +#define MREG_DECODE_PARAM AV_SCRATCH_2 /* bit 0-3: pico_addr_mode */ +/* bit 15-4: reference height */ +#define MREG_TO_AMRISC AV_SCRATCH_8 +#define MREG_FROM_AMRISC AV_SCRATCH_9 +#define MREG_FRAME_OFFSET AV_SCRATCH_A + +#define PICINFO_BUF_IDX_MASK 0x0007 +#define PICINFO_AVI1 0x0080 +#define PICINFO_INTERLACE 0x0020 +#define PICINFO_INTERLACE_AVI1_BOT 0x0010 +#define PICINFO_INTERLACE_FIRST 0x0010 + +#define VF_POOL_SIZE 16 +#define DECODE_BUFFER_NUM_MAX 4 +#define PUT_INTERVAL (HZ/100) + +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ +/* #define NV21 */ +#endif +static DEFINE_MUTEX(vmjpeg_mutex); + +static struct dec_sysinfo vmjpeg_amstream_dec_info; + +static struct vframe_s *vmjpeg_vf_peek(void *); +static struct vframe_s *vmjpeg_vf_get(void *); +static void vmjpeg_vf_put(struct vframe_s *, void *); +static int vmjpeg_vf_states(struct vframe_states *states, void *); +static int vmjpeg_event_cb(int type, void *data, void *private_data); + +static void vmjpeg_prot_init(void); +static void vmjpeg_local_init(void); + +static const char vmjpeg_dec_id[] = "vmjpeg-dev"; + +#define PROVIDER_NAME "decoder.mjpeg" +static const struct vframe_operations_s vmjpeg_vf_provider = { + .peek = vmjpeg_vf_peek, + .get = vmjpeg_vf_get, + .put = vmjpeg_vf_put, + .event_cb = vmjpeg_event_cb, + .vf_states = vmjpeg_vf_states, +}; + +static struct vframe_provider_s vmjpeg_vf_prov; + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static struct vframe_s vfpool[VF_POOL_SIZE]; +static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; + +static u32 frame_width, frame_height, frame_dur; +static u32 saved_resolution; +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start; +static u32 buf_size; +static DEFINE_SPINLOCK(lock); + +static inline u32 index2canvas0(u32 index) +{ + const u32 canvas_tab[4] = { +#ifdef NV21 + 0x010100, 0x030302, 0x050504, 0x070706 +#else + 0x020100, 0x050403, 0x080706, 0x0b0a09 +#endif + }; + + return canvas_tab[index]; +} + +static inline u32 index2canvas1(u32 index) +{ + const u32 canvas_tab[4] = { +#ifdef NV21 + 0x0d0d0c, 0x0f0f0e, 0x171716, 0x191918 +#else + 0x0e0d0c, 0x181716, 0x222120, 0x252423 +#endif + }; + + return canvas_tab[index]; +} + +static void set_frame_info(struct vframe_s *vf) +{ + vf->width = frame_width; + vf->height = frame_height; + vf->duration = frame_dur; + vf->ratio_control = 0; + vf->duration_pulldown = 0; + vf->flag = 0; +} + +static irqreturn_t vmjpeg_isr(int irq, void *dev_id) +{ + u32 reg, offset, pts, pts_valid = 0; + struct vframe_s *vf = NULL; + u64 pts_us64; + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + reg = READ_VREG(MREG_FROM_AMRISC); + + if (reg & PICINFO_BUF_IDX_MASK) { + offset = READ_VREG(MREG_FRAME_OFFSET); + + if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) == 0) + pts_valid = 1; + + if ((reg & PICINFO_INTERLACE) == 0) { + u32 index = ((reg & PICINFO_BUF_IDX_MASK) - 1) & 3; + + if (index >= DECODE_BUFFER_NUM_MAX) { + pr_err("fatal error, invalid buffer index."); + return IRQ_HANDLED; + } + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info( + "fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + set_frame_info(vf); + vf->signal_type = 0; + vf->index = index; +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas0(index); + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + vf->orientation = 0; + vf->type_original = vf->type; + vfbuf_use[index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + } else { + u32 index = ((reg & PICINFO_BUF_IDX_MASK) - 1) & 3; + + if (index >= DECODE_BUFFER_NUM_MAX) { + pr_info("fatal error, invalid buffer index."); + return IRQ_HANDLED; + } + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + set_frame_info(vf); + vf->signal_type = 0; + vf->index = index; +#if 0 + if (reg & PICINFO_AVI1) { + /* AVI1 format */ + if (reg & PICINFO_INTERLACE_AVI1_BOT) { + vf->type = + VIDTYPE_INTERLACE_BOTTOM | + VIDTYPE_INTERLACE_FIRST; + } else + vf->type = VIDTYPE_INTERLACE_TOP; + } else { + if (reg & PICINFO_INTERLACE_FIRST) { + vf->type = + VIDTYPE_INTERLACE_TOP | + VIDTYPE_INTERLACE_FIRST; + } else + vf->type = VIDTYPE_INTERLACE_BOTTOM; + } + + vf->type |= VIDTYPE_VIU_FIELD; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->duration >>= 1; + vf->canvas0Addr = vf->canvas1Addr = + index2canvas0(index); + vf->orientation = 0; + if ((vf->type & VIDTYPE_INTERLACE_FIRST) && + (pts_valid)) + vf->pts = pts; + else + vf->pts = 0; + + vfbuf_use[index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); +#else + /* send whole frame by weaving top & bottom field */ +#ifdef NV21 + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE; +#endif + vf->canvas0Addr = index2canvas0(index); + vf->canvas1Addr = index2canvas1(index); + vf->orientation = 0; + if (pts_valid) { + vf->pts = pts; + vf->pts_us64 = pts_us64; + } else { + vf->pts = 0; + vf->pts_us64 = 0; + } + vf->type_original = vf->type; + vfbuf_use[index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); +#endif + } + + WRITE_VREG(MREG_FROM_AMRISC, 0); + } + + return IRQ_HANDLED; +} + +static struct vframe_s *vmjpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmjpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + kfifo_put(&recycle_q, (const struct vframe_s *)vf); +} + +static int vmjpeg_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vmjpeg_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vmjpeg_local_init(); + vmjpeg_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vmjpeg_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +static int vmjpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + + return 0; +} + +static void vmjpeg_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + + while (!kfifo_is_empty(&recycle_q) && + (READ_VREG(MREG_TO_AMRISC) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index >= 0) + && (vf->index < DECODE_BUFFER_NUM_MAX) + && (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(MREG_TO_AMRISC, vf->index + 1); + vf->index = DECODE_BUFFER_NUM_MAX; + } + + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } + } + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_MJPEG, + frame_width, frame_height, fps); + } + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = frame_width; + vstatus->height = frame_height; + if (0 != frame_dur) + vstatus->fps = 96000 / frame_dur; + else + vstatus->fps = 96000; + vstatus->error_count = 0; + vstatus->status = stat; + + return 0; +} + +/****************************************/ +static void vmjpeg_canvas_init(void) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + u32 disp_addr = 0xffffffff; + + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + /* HD & SD */ + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + + if (is_vpp_postblend()) { + struct canvas_s cur_canvas; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + } + + for (i = 0; i < 4; i++) { + if (((buf_start + i * decbuf_size + 7) >> 3) == disp_addr) { +#ifdef NV21 + canvas_config(index2canvas0(i) & 0xff, + buf_start + 4 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas0(i) >> 8) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(index2canvas1(i) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_size / 2, canvas_width, + canvas_height, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas1(i) >> 8) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_y_size + decbuf_uv_size / 2, + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#else + canvas_config(index2canvas0(i) & 0xff, + buf_start + 4 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas0(i) >> 8) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas0(i) >> 16) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(index2canvas1(i) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_size / 2, canvas_width, + canvas_height, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas1(i) >> 8) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_y_size + decbuf_uv_size / 2, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas1(i) >> 16) & 0xff, + buf_start + 4 * decbuf_size + + decbuf_y_size + decbuf_uv_size + + decbuf_uv_size / 2, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } else { +#ifdef NV21 + canvas_config(index2canvas0(i) & 0xff, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas0(i) >> 8) & 0xff, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(index2canvas1(i) & 0xff, + buf_start + i * decbuf_size + + decbuf_size / 2, canvas_width, + canvas_height, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas1(i) >> 8) & 0xff, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size / 2, + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#else + canvas_config(index2canvas0(i) & 0xff, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas0(i) >> 8) & 0xff, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas0(i) >> 16) & 0xff, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(index2canvas1(i) & 0xff, + buf_start + i * decbuf_size + + decbuf_size / 2, canvas_width, + canvas_height, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas1(i) >> 8) & 0xff, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size / 2, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config((index2canvas1(i) >> 16) & 0xff, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size + + decbuf_uv_size / 2, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + } +} + +static void init_scaler(void) +{ + /* 4 point triangle */ + const unsigned filt_coef[] = { + 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, + 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, + 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, + 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, + 0x18382808, 0x18382808, 0x17372909, 0x17372909, + 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, + 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, + 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, + 0x10303010 + }; + int i; + + /* pscale enable, PSCALE cbus bmem enable */ + WRITE_VREG(PSCALE_CTRL, 0xc000); + + /* write filter coefs */ + WRITE_VREG(PSCALE_BMEM_ADDR, 0); + for (i = 0; i < 33; i++) { + WRITE_VREG(PSCALE_BMEM_DAT, 0); + WRITE_VREG(PSCALE_BMEM_DAT, filt_coef[i]); + } + + /* Y horizontal initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 37 * 2); + /* [35]: buf repeat pix0, + * [34:29] => buf receive num, + * [28:16] => buf blk x, + * [15:0] => buf phase + */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* C horizontal initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 41 * 2); + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* Y vertical initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 39 * 2); + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* C vertical initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 43 * 2); + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* Y horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 36 * 2 + 1); + /* [19:0] => Y horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + /* C horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 40 * 2 + 1); + /* [19:0] => C horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + + /* Y vertical phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 38 * 2 + 1); + /* [19:0] => Y vertical phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + /* C vertical phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 42 * 2 + 1); + /* [19:0] => C horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + + /* reset pscaler */ +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ + WRITE_VREG(DOS_SW_RESET0, (1 << 10)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PSCALE); +#endif + READ_MPEG_REG(RESET2_REGISTER); + READ_MPEG_REG(RESET2_REGISTER); + READ_MPEG_REG(RESET2_REGISTER); + + WRITE_VREG(PSCALE_RST, 0x7); + WRITE_VREG(PSCALE_RST, 0x0); +} + +static void vmjpeg_prot_init(void) +{ +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); +#endif + + vmjpeg_canvas_init(); + + WRITE_VREG(AV_SCRATCH_0, 12); + WRITE_VREG(AV_SCRATCH_1, 0x031a); +#ifdef NV21 + WRITE_VREG(AV_SCRATCH_4, 0x010100); + WRITE_VREG(AV_SCRATCH_5, 0x030302); + WRITE_VREG(AV_SCRATCH_6, 0x050504); + WRITE_VREG(AV_SCRATCH_7, 0x070706); +#else + WRITE_VREG(AV_SCRATCH_4, 0x020100); + WRITE_VREG(AV_SCRATCH_5, 0x050403); + WRITE_VREG(AV_SCRATCH_6, 0x080706); + WRITE_VREG(AV_SCRATCH_7, 0x0b0a09); +#endif + init_scaler(); + + /* clear buffer IN/OUT registers */ + WRITE_VREG(MREG_TO_AMRISC, 0); + WRITE_VREG(MREG_FROM_AMRISC, 0); + + WRITE_VREG(MCPU_INTR_MSK, 0xffff); + WRITE_VREG(MREG_DECODE_PARAM, (frame_height << 4) | 0x8000); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + /* set interrupt mapping for vld */ + WRITE_VREG(ASSIST_AMR1_INT8, 8); +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#else + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif +#endif +} + +static void vmjpeg_local_init(void) +{ + int i; + + frame_width = vmjpeg_amstream_dec_info.width; + frame_height = vmjpeg_amstream_dec_info.height; + frame_dur = vmjpeg_amstream_dec_info.rate; + saved_resolution = 0; + amlog_level(LOG_LEVEL_INFO, "mjpegdec: w(%d), h(%d), dur(%d)\n", + frame_width, frame_height, frame_dur); + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + vfbuf_use[i] = 0; + + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &vfpool[i]; + vfpool[i].index = DECODE_BUFFER_NUM_MAX; + kfifo_put(&newframe_q, vf); + } +} + +static s32 vmjpeg_init(void) +{ + int ret = -1,size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + amvdec_enable(); + + vmjpeg_local_init(); + + size = get_firmware_data(VIDEO_DEC_MJPEG, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_MJPEG, NULL, buf) < 0) { + amvdec_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vmjpeg_prot_init(); + + ret = vdec_request_irq(VDEC_IRQ_1, vmjpeg_isr, + "vmjpeg-irq", (void *)vmjpeg_dec_id); + + if (ret) { + amvdec_disable(); + + amlog_level(LOG_LEVEL_ERROR, "vmjpeg irq register error.\n"); + return -ENOENT; + } + + stat |= STAT_ISR_REG; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vmjpeg_vf_prov, PROVIDER_NAME, &vmjpeg_vf_provider, + NULL); + vf_reg_provider(&vmjpeg_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vmjpeg_vf_prov, PROVIDER_NAME, &vmjpeg_vf_provider, + NULL); + vf_reg_provider(&vmjpeg_vf_prov); +#endif + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)vmjpeg_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong)&recycle_timer; + recycle_timer.function = vmjpeg_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int amvdec_mjpeg_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + mutex_lock(&vmjpeg_mutex); + + amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg probe start.\n"); + + if (pdata == NULL) { + amlog_level(LOG_LEVEL_ERROR, + "amvdec_mjpeg memory resource undefined.\n"); + mutex_unlock(&vmjpeg_mutex); + + return -EFAULT; + } + + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; + + if (pdata->sys_info) + vmjpeg_amstream_dec_info = *pdata->sys_info; + + pdata->dec_status = vmjpeg_dec_status; + + if (vmjpeg_init() < 0) { + amlog_level(LOG_LEVEL_ERROR, "amvdec_mjpeg init failed.\n"); + mutex_unlock(&vmjpeg_mutex); + + return -ENODEV; + } + + mutex_unlock(&vmjpeg_mutex); + + amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg probe end.\n"); + + return 0; +} + +static int amvdec_mjpeg_remove(struct platform_device *pdev) +{ + mutex_lock(&vmjpeg_mutex); + + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)vmjpeg_dec_id); + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vmjpeg_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + amvdec_disable(); + + mutex_unlock(&vmjpeg_mutex); + + amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg remove.\n"); + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_mjpeg_driver = { + .probe = amvdec_mjpeg_probe, + .remove = amvdec_mjpeg_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_mjpeg_profile = { + .name = "mjpeg", + .profile = "" +}; + +static int __init amvdec_mjpeg_driver_init_module(void) +{ + amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg module init\n"); + + if (platform_driver_register(&amvdec_mjpeg_driver)) { + amlog_level(LOG_LEVEL_ERROR, + "failed to register amvdec_mjpeg driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_mjpeg_profile); + return 0; +} + +static void __exit amvdec_mjpeg_driver_remove_module(void) +{ + amlog_level(LOG_LEVEL_INFO, "amvdec_mjpeg module remove.\n"); + + platform_driver_unregister(&amvdec_mjpeg_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_mjpeg stat\n"); + +module_init(amvdec_mjpeg_driver_init_module); +module_exit(amvdec_mjpeg_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c new file mode 100644 index 000000000000..850e0b6a21be --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -0,0 +1,723 @@ +/* + * drivers/amlogic/amports/vmjpeg.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../../../stream_input/amports/amports_priv.h" + +#include + +#include "../utils/vdec_input.h" +#include "../utils/vdec.h" +#include "../utils/amvdec.h" + +#define MEM_NAME "codec_mmjpeg" + +#define DRIVER_NAME "ammvdec_mjpeg" +#define MODULE_NAME "ammvdec_mjpeg" + +/* protocol register usage + AV_SCRATCH_4 : decode buffer spec + AV_SCRATCH_5 : decode buffer index +*/ + +#define MREG_DECODE_PARAM AV_SCRATCH_2 /* bit 0-3: pico_addr_mode */ +/* bit 15-4: reference height */ +#define MREG_TO_AMRISC AV_SCRATCH_8 +#define MREG_FROM_AMRISC AV_SCRATCH_9 +#define MREG_FRAME_OFFSET AV_SCRATCH_A + +#define PICINFO_BUF_IDX_MASK 0x0007 +#define PICINFO_AVI1 0x0080 +#define PICINFO_INTERLACE 0x0020 +#define PICINFO_INTERLACE_AVI1_BOT 0x0010 +#define PICINFO_INTERLACE_FIRST 0x0010 + +#define VF_POOL_SIZE 16 +#define DECODE_BUFFER_NUM_MAX 4 + +static struct vframe_s *vmjpeg_vf_peek(void *); +static struct vframe_s *vmjpeg_vf_get(void *); +static void vmjpeg_vf_put(struct vframe_s *, void *); +static int vmjpeg_vf_states(struct vframe_states *states, void *); +static int vmjpeg_event_cb(int type, void *data, void *private_data); +static void vmjpeg_work(struct work_struct *work); + +static const char vmjpeg_dec_id[] = "vmmjpeg-dev"; + +#define PROVIDER_NAME "vdec.mjpeg" +static const struct vframe_operations_s vf_provider_ops = { + .peek = vmjpeg_vf_peek, + .get = vmjpeg_vf_get, + .put = vmjpeg_vf_put, + .event_cb = vmjpeg_event_cb, + .vf_states = vmjpeg_vf_states, +}; + +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 + +struct buffer_spec_s { + unsigned int y_addr; + unsigned int u_addr; + unsigned int v_addr; + + int y_canvas_index; + int u_canvas_index; + int v_canvas_index; + + struct canvas_config_s canvas_config[3]; + unsigned long cma_alloc_addr; + int cma_alloc_count; + unsigned int buf_adr; +}; + +#define spec2canvas(x) \ + (((x)->v_canvas_index << 16) | \ + ((x)->u_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) + +struct vdec_mjpeg_hw_s { + spinlock_t lock; + struct mutex vmjpeg_mutex; + + struct platform_device *platform_dev; + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + + struct vframe_s vfpool[VF_POOL_SIZE]; + struct buffer_spec_s buffer_spec[DECODE_BUFFER_NUM_MAX]; + s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; + + u32 frame_width; + u32 frame_height; + u32 frame_dur; + u32 saved_resolution; + + u32 stat; + u32 dec_result; + unsigned long buf_start; + u32 buf_size; + + struct dec_sysinfo vmjpeg_amstream_dec_info; + + struct vframe_chunk_s *chunk; + struct work_struct work; + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; +}; + +static void set_frame_info(struct vdec_mjpeg_hw_s *hw, struct vframe_s *vf) +{ + vf->width = hw->frame_width; + vf->height = hw->frame_height; + vf->duration = hw->frame_dur; + vf->ratio_control = 0; + vf->duration_pulldown = 0; + vf->flag = 0; + + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 3; + + vf->canvas0_config[0] = hw->buffer_spec[vf->index].canvas_config[0]; + vf->canvas0_config[1] = hw->buffer_spec[vf->index].canvas_config[1]; + vf->canvas0_config[2] = hw->buffer_spec[vf->index].canvas_config[2]; + + vf->canvas1_config[0] = hw->buffer_spec[vf->index].canvas_config[0]; + vf->canvas1_config[1] = hw->buffer_spec[vf->index].canvas_config[1]; + vf->canvas1_config[2] = hw->buffer_spec[vf->index].canvas_config[2]; +} + +static irqreturn_t vmjpeg_isr(struct vdec_s *vdec) +{ + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)(vdec->private); + u32 reg; + struct vframe_s *vf = NULL; + u32 index; + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + if (!hw) + return IRQ_HANDLED; + + reg = READ_VREG(MREG_FROM_AMRISC); + index = READ_VREG(AV_SCRATCH_5); + + if (index >= DECODE_BUFFER_NUM_MAX) { + pr_err("fatal error, invalid buffer index."); + return IRQ_HANDLED; + } + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + pr_info( + "fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + vf->index = index; + set_frame_info(hw, vf); + + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + /* vf->pts = (pts_valid) ? pts : 0; */ + /* vf->pts_us64 = (pts_valid) ? pts_us64 : 0; */ + vf->pts = hw->chunk->pts; + vf->pts_us64 = hw->chunk->pts64; + vf->orientation = 0; + hw->vfbuf_use[index]++; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + hw->dec_result = DEC_RESULT_DONE; + + schedule_work(&hw->work); + + return IRQ_HANDLED; +} + +static struct vframe_s *vmjpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + + if (!hw) + return NULL; + + if (kfifo_peek(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmjpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + + if (!hw) + return NULL; + + if (kfifo_get(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vdec_s *vdec = op_arg; + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + + hw->vfbuf_use[vf->index]--; + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); +} + +static int vmjpeg_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static int vmjpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + struct vdec_s *vdec = op_arg; + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + + spin_lock_irqsave(&hw->lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&hw->newframe_q); + states->buf_avail_num = kfifo_len(&hw->display_q); + states->buf_recycle_num = 0; + + spin_unlock_irqrestore(&hw->lock, flags); + + return 0; +} + +static int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + vstatus->width = hw->frame_width; + vstatus->height = hw->frame_height; + if (0 != hw->frame_dur) + vstatus->fps = 96000 / hw->frame_dur; + else + vstatus->fps = 96000; + vstatus->error_count = 0; + vstatus->status = hw->stat; + + return 0; +} + +/****************************************/ +static void vmjpeg_canvas_init(struct vdec_s *vdec) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *)vdec->private; + ulong addr; + + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + int canvas; + + canvas = vdec->get_canvas(i, 3); + if (hw->buffer_spec[i].cma_alloc_count == 0) { + hw->buffer_spec[i].cma_alloc_count = + PAGE_ALIGN(decbuf_size) / PAGE_SIZE; + hw->buffer_spec[i].cma_alloc_addr = + codec_mm_alloc_for_dma(MEM_NAME, + hw->buffer_spec[i].cma_alloc_count, + 16, CODEC_MM_FLAGS_FOR_VDECODER); + } + + if (!hw->buffer_spec[i].cma_alloc_addr) { + pr_err("CMA alloc failed, request buf size 0x%lx\n", + hw->buffer_spec[i].cma_alloc_count * PAGE_SIZE); + hw->buffer_spec[i].cma_alloc_count = 0; + break; + } + + hw->buffer_spec[i].buf_adr = + hw->buffer_spec[i].cma_alloc_addr; + addr = hw->buffer_spec[i].buf_adr; + + hw->buffer_spec[i].y_addr = addr; + addr += decbuf_y_size; + hw->buffer_spec[i].u_addr = addr; + addr += decbuf_uv_size; + hw->buffer_spec[i].v_addr = addr; + + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + + canvas_config(hw->buffer_spec[i].y_canvas_index, + hw->buffer_spec[i].y_addr, + canvas_width, + canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hw->buffer_spec[i].canvas_config[0].phy_addr = + hw->buffer_spec[i].y_addr; + hw->buffer_spec[i].canvas_config[0].width = + canvas_width; + hw->buffer_spec[i].canvas_config[0].height = + canvas_height; + hw->buffer_spec[i].canvas_config[0].block_mode = + CANVAS_BLKMODE_LINEAR; + + canvas_config(hw->buffer_spec[i].u_canvas_index, + hw->buffer_spec[i].u_addr, + canvas_width / 2, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hw->buffer_spec[i].canvas_config[1].phy_addr = + hw->buffer_spec[i].u_addr; + hw->buffer_spec[i].canvas_config[1].width = + canvas_width / 2; + hw->buffer_spec[i].canvas_config[1].height = + canvas_height / 2; + hw->buffer_spec[i].canvas_config[1].block_mode = + CANVAS_BLKMODE_LINEAR; + + canvas_config(hw->buffer_spec[i].v_canvas_index, + hw->buffer_spec[i].v_addr, + canvas_width / 2, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hw->buffer_spec[i].canvas_config[2].phy_addr = + hw->buffer_spec[i].v_addr; + hw->buffer_spec[i].canvas_config[2].width = + canvas_width / 2; + hw->buffer_spec[i].canvas_config[2].height = + canvas_height / 2; + hw->buffer_spec[i].canvas_config[2].block_mode = + CANVAS_BLKMODE_LINEAR; + } +} + +static void init_scaler(void) +{ + /* 4 point triangle */ + const unsigned filt_coef[] = { + 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, + 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, + 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, + 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, + 0x18382808, 0x18382808, 0x17372909, 0x17372909, + 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, + 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, + 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, + 0x10303010 + }; + int i; + + /* pscale enable, PSCALE cbus bmem enable */ + WRITE_VREG(PSCALE_CTRL, 0xc000); + + /* write filter coefs */ + WRITE_VREG(PSCALE_BMEM_ADDR, 0); + for (i = 0; i < 33; i++) { + WRITE_VREG(PSCALE_BMEM_DAT, 0); + WRITE_VREG(PSCALE_BMEM_DAT, filt_coef[i]); + } + + /* Y horizontal initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 37 * 2); + /* [35]: buf repeat pix0, + * [34:29] => buf receive num, + * [28:16] => buf blk x, + * [15:0] => buf phase + */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* C horizontal initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 41 * 2); + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* Y vertical initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 39 * 2); + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* C vertical initial info */ + WRITE_VREG(PSCALE_BMEM_ADDR, 43 * 2); + WRITE_VREG(PSCALE_BMEM_DAT, 0x0008); + WRITE_VREG(PSCALE_BMEM_DAT, 0x60000000); + + /* Y horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 36 * 2 + 1); + /* [19:0] => Y horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + /* C horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 40 * 2 + 1); + /* [19:0] => C horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + + /* Y vertical phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 38 * 2 + 1); + /* [19:0] => Y vertical phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + /* C vertical phase step */ + WRITE_VREG(PSCALE_BMEM_ADDR, 42 * 2 + 1); + /* [19:0] => C horizontal phase step */ + WRITE_VREG(PSCALE_BMEM_DAT, 0x10000); + + /* reset pscaler */ +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ + WRITE_VREG(DOS_SW_RESET0, (1 << 10)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PSCALE); +#endif + READ_MPEG_REG(RESET2_REGISTER); + READ_MPEG_REG(RESET2_REGISTER); + READ_MPEG_REG(RESET2_REGISTER); + + WRITE_VREG(PSCALE_RST, 0x7); + WRITE_VREG(PSCALE_RST, 0x0); +} + +static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index) +{ + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *)vdec->private; + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); + WRITE_VREG(DOS_SW_RESET0, 0); + + vmjpeg_canvas_init(vdec); + + /* find next decode buffer index */ + WRITE_VREG(AV_SCRATCH_4, spec2canvas(&hw->buffer_spec[index])); + WRITE_VREG(AV_SCRATCH_5, index); + + init_scaler(); + + /* clear buffer IN/OUT registers */ + WRITE_VREG(MREG_TO_AMRISC, 0); + WRITE_VREG(MREG_FROM_AMRISC, 0); + + WRITE_VREG(MCPU_INTR_MSK, 0xffff); + WRITE_VREG(MREG_DECODE_PARAM, (hw->frame_height << 4) | 0x8000); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + /* set interrupt mapping for vld */ + WRITE_VREG(ASSIST_AMR1_INT8, 8); +#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif +} + +static s32 vmjpeg_init(struct vdec_s *vdec) +{ + int i; + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *)vdec->private; + + hw->frame_width = hw->vmjpeg_amstream_dec_info.width; + hw->frame_height = hw->vmjpeg_amstream_dec_info.height; + hw->frame_dur = hw->vmjpeg_amstream_dec_info.rate; + hw->saved_resolution = 0; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->vfbuf_use[i] = 0; + + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &hw->vfpool[i]; + hw->vfpool[i].index = -1; + kfifo_put(&hw->newframe_q, vf); + } + + INIT_WORK(&hw->work, vmjpeg_work); + + return 0; +} + +static bool run_ready(struct vdec_s *vdec) +{ + return true; +} + +static void run(struct vdec_s *vdec, + void (*callback)(struct vdec_s *, void *), void *arg) +{ + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *)vdec->private; + int i,ret = -1,size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return; + + hw->vdec_cb_arg = arg; + hw->vdec_cb = callback; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + break; + } + + if (i == DECODE_BUFFER_NUM_MAX) { + hw->dec_result = DEC_RESULT_AGAIN; + schedule_work(&hw->work); + return; + } + + ret = vdec_prepare_input(vdec, &hw->chunk); + if (ret < 0) { + hw->dec_result = DEC_RESULT_AGAIN; + schedule_work(&hw->work); + return; + } + + hw->dec_result = DEC_RESULT_NONE; + + size = get_firmware_data(VIDEO_DEC_MJPEG_MULTI, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return; + } + + if (amvdec_vdec_loadmc_buf_ex(vdec, buf, size) < 0) { + pr_err("%s: Error amvdec_loadmc fail\n", __func__); + vfree(buf); + return; + } + + vfree(buf); + + vmjpeg_hw_ctx_restore(vdec, i); + + vdec_enable_input(vdec); + + amvdec_start(); +} + +static void vmjpeg_work(struct work_struct *work) +{ + struct vdec_mjpeg_hw_s *hw = container_of(work, + struct vdec_mjpeg_hw_s, work); + + if (hw->dec_result == DEC_RESULT_DONE) + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + + /* mark itself has all HW resource released and input released */ + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); + + if (hw->vdec_cb) + hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); +} + +static int amvdec_mjpeg_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct vdec_mjpeg_hw_s *hw = NULL; + + if (pdata == NULL) { + pr_info("amvdec_mjpeg memory resource undefined.\n"); + return -EFAULT; + } + + hw = (struct vdec_mjpeg_hw_s *)devm_kzalloc(&pdev->dev, + sizeof(struct vdec_mjpeg_hw_s), GFP_KERNEL); + if (hw == NULL) { + pr_info("\nammvdec_mjpeg device data allocation failed\n"); + return -ENOMEM; + } + + pdata->private = hw; + pdata->dec_status = vmjpeg_dec_status; + + pdata->run = run; + pdata->run_ready = run_ready; + pdata->irq_handler = vmjpeg_isr; + + pdata->id = pdev->id; + + if (pdata->use_vfm_path) + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); + else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + PROVIDER_NAME ".%02x", pdev->id & 0xff); + + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vf_provider_ops, pdata); + + platform_set_drvdata(pdev, pdata); + + hw->platform_dev = pdev; + hw->buf_start = pdata->mem_start; + hw->buf_size = pdata->mem_end - pdata->mem_start + 1; + + if (pdata->sys_info) + hw->vmjpeg_amstream_dec_info = *pdata->sys_info; + + if (vmjpeg_init(pdata) < 0) { + pr_info("amvdec_mjpeg init failed.\n"); + return -ENODEV; + } + + return 0; +} + +static int amvdec_mjpeg_remove(struct platform_device *pdev) +{ + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->buffer_spec[i].cma_alloc_addr) { + pr_info("codec_mm release buffer_spec[%d], 0x%lx\n", i, + hw->buffer_spec[i].cma_alloc_addr); + codec_mm_free_for_dma(MEM_NAME, + hw->buffer_spec[i].cma_alloc_addr); + hw->buffer_spec[i].cma_alloc_count = 0; + } + } + + cancel_work_sync(&hw->work); + + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_mjpeg_driver = { + .probe = amvdec_mjpeg_probe, + .remove = amvdec_mjpeg_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_mjpeg_profile = { + .name = "mmjpeg", + .profile = "" +}; + +static int __init amvdec_mjpeg_driver_init_module(void) +{ + if (platform_driver_register(&amvdec_mjpeg_driver)) { + pr_err("failed to register amvdec_mjpeg driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_mjpeg_profile); + return 0; +} + +static void __exit amvdec_mjpeg_driver_remove_module(void) +{ + platform_driver_unregister(&amvdec_mjpeg_driver); +} + +/****************************************/ + +module_init(amvdec_mjpeg_driver_init_module); +module_exit(amvdec_mjpeg_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c new file mode 100644 index 000000000000..1d15e11f8af9 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c @@ -0,0 +1,1110 @@ +/* + * drivers/amlogic/amports/vmpeg12.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "vmpeg12.h" +#include +#include "../../../stream_input/amports/amports_priv.h" + +#ifdef CONFIG_AM_VDEC_MPEG12_LOG +#define AMLOG +#define LOG_LEVEL_VAR amlog_level_vmpeg +#define LOG_MASK_VAR amlog_mask_vmpeg +#define LOG_LEVEL_ERROR 0 +#define LOG_LEVEL_INFO 1 +#define LOG_LEVEL_DESC "0:ERROR, 1:INFO" +#endif +#include +MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); + +#include "../utils/amvdec.h" +#include "../utils/vdec.h" + +#define DRIVER_NAME "amvdec_mpeg12" +#define MODULE_NAME "amvdec_mpeg12" + +/* protocol registers */ +#define MREG_SEQ_INFO AV_SCRATCH_4 +#define MREG_PIC_INFO AV_SCRATCH_5 +#define MREG_PIC_WIDTH AV_SCRATCH_6 +#define MREG_PIC_HEIGHT AV_SCRATCH_7 +#define MREG_BUFFERIN AV_SCRATCH_8 +#define MREG_BUFFEROUT AV_SCRATCH_9 + +#define MREG_CMD AV_SCRATCH_A +#define MREG_CO_MV_START AV_SCRATCH_B +#define MREG_ERROR_COUNT AV_SCRATCH_C +#define MREG_FRAME_OFFSET AV_SCRATCH_D +#define MREG_WAIT_BUFFER AV_SCRATCH_E +#define MREG_FATAL_ERROR AV_SCRATCH_F + +#define PICINFO_ERROR 0x80000000 +#define PICINFO_TYPE_MASK 0x00030000 +#define PICINFO_TYPE_I 0x00000000 +#define PICINFO_TYPE_P 0x00010000 +#define PICINFO_TYPE_B 0x00020000 + +#define PICINFO_PROG 0x8000 +#define PICINFO_RPT_FIRST 0x4000 +#define PICINFO_TOP_FIRST 0x2000 +#define PICINFO_FRAME 0x1000 + +#define SEQINFO_EXT_AVAILABLE 0x80000000 +#define SEQINFO_PROG 0x00010000 + +#define VF_POOL_SIZE 32 +#define DECODE_BUFFER_NUM_MAX 8 +#define PUT_INTERVAL (HZ/100) + +#define INCPTR(p) ptr_atomic_wrap_inc(&p) + +#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002 +#define DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE 0x0004 +#define DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE 0x0008 +#define DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE 0x0010 +#define DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE 0x0020 +#define DEC_CONTROL_INTERNAL_MASK 0x0fff +#define DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE 0x1000 + +#define INTERLACE_SEQ_ALWAYS + +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +#endif +#define CCBUF_SIZE (5*1024) + +enum { + FRAME_REPEAT_TOP, + FRAME_REPEAT_BOT, + FRAME_REPEAT_NONE +}; + +static struct vframe_s *vmpeg_vf_peek(void *); +static struct vframe_s *vmpeg_vf_get(void *); +static void vmpeg_vf_put(struct vframe_s *, void *); +static int vmpeg_vf_states(struct vframe_states *states, void *); +static int vmpeg_event_cb(int type, void *data, void *private_data); + +static void vmpeg12_prot_init(void); +static void vmpeg12_local_init(void); + +static const char vmpeg12_dec_id[] = "vmpeg12-dev"; +#define PROVIDER_NAME "decoder.mpeg12" +static const struct vframe_operations_s vmpeg_vf_provider = { + .peek = vmpeg_vf_peek, + .get = vmpeg_vf_get, + .put = vmpeg_vf_put, + .event_cb = vmpeg_event_cb, + .vf_states = vmpeg_vf_states, +}; + +static struct vframe_provider_s vmpeg_vf_prov; + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static const u32 frame_rate_tab[16] = { + 96000 / 30, 96000 / 24, 96000 / 24, 96000 / 25, + 96000 / 30, 96000 / 30, 96000 / 50, 96000 / 60, + 96000 / 60, + /* > 8 reserved, use 24 */ + 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, + 96000 / 24, 96000 / 24, 96000 / 24 +}; + +static struct vframe_s vfpool[VF_POOL_SIZE]; +static struct vframe_s vfpool2[VF_POOL_SIZE]; +static int cur_pool_idx; +static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; +static u32 dec_control; +static u32 frame_width, frame_height, frame_dur, frame_prog; +static u32 saved_resolution; +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start; +static u32 buf_size, ccbuf_phyAddress; +static void *ccbuf_phyAddress_virt; +static int ccbuf_phyAddress_is_remaped_nocache; + +static DEFINE_SPINLOCK(lock); + +static u32 frame_rpt_state; + +static struct dec_sysinfo vmpeg12_amstream_dec_info; + +/* for error handling */ +static s32 frame_force_skip_flag; +static s32 error_frame_skip_level; +static s32 wait_buffer_counter; +static u32 first_i_frame_ready; + +static inline int pool_index(struct vframe_s *vf) +{ + if ((vf >= &vfpool[0]) && (vf <= &vfpool[VF_POOL_SIZE - 1])) + return 0; + else if ((vf >= &vfpool2[0]) && (vf <= &vfpool2[VF_POOL_SIZE - 1])) + return 1; + else + return -1; +} + +static inline u32 index2canvas(u32 index) +{ + const u32 canvas_tab[8] = { +#ifdef NV21 + 0x010100, 0x030302, 0x050504, 0x070706, + 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e +#else + 0x020100, 0x050403, 0x080706, 0x0b0a09, + 0x0e0d0c, 0x11100f, 0x141312, 0x171615 +#endif + }; + + return canvas_tab[index]; +} + +static void set_frame_info(struct vframe_s *vf) +{ + unsigned ar_bits; + u32 temp; + +#ifdef CONFIG_AM_VDEC_MPEG12_LOG + bool first = (frame_width == 0) && (frame_height == 0); +#endif + temp = READ_VREG(MREG_PIC_WIDTH); + if (temp > 1920) + vf->width = frame_width = 1920; + else + vf->width = frame_width = temp; + + temp = READ_VREG(MREG_PIC_HEIGHT); + if (temp > 1088) + vf->height = frame_height = 1088; + else + vf->height = frame_height = temp; + + vf->flag = 0; + + if (frame_dur > 0) + vf->duration = frame_dur; + else { + vf->duration = frame_dur = + frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]; + } + + ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf; + + if (ar_bits == 0x2) + vf->ratio_control = 0xc0 << DISP_RATIO_ASPECT_RATIO_BIT; + + else if (ar_bits == 0x3) + vf->ratio_control = 0x90 << DISP_RATIO_ASPECT_RATIO_BIT; + + else if (ar_bits == 0x4) + vf->ratio_control = 0x74 << DISP_RATIO_ASPECT_RATIO_BIT; + + else + vf->ratio_control = 0; + + amlog_level_if(first, LOG_LEVEL_INFO, + "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", + frame_width, frame_height, frame_dur, + frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]); +} + +static bool error_skip(u32 info, struct vframe_s *vf) +{ + if (error_frame_skip_level) { + /* skip error frame */ + if ((info & PICINFO_ERROR) || (frame_force_skip_flag)) { + if ((info & PICINFO_ERROR) == 0) { + if ((info & PICINFO_TYPE_MASK) == + PICINFO_TYPE_I) + frame_force_skip_flag = 0; + } else { + if (error_frame_skip_level >= 2) + frame_force_skip_flag = 1; + } + if ((info & PICINFO_ERROR) || (frame_force_skip_flag)) + return true; + } + } + + return false; +} + +static irqreturn_t vmpeg12_isr(int irq, void *dev_id) +{ + u32 reg, info, seqinfo, offset, pts, pts_valid = 0; + struct vframe_s *vf; + u64 pts_us64 = 0; + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + reg = READ_VREG(MREG_BUFFEROUT); + + if ((reg >> 16) == 0xfe) { + if (!ccbuf_phyAddress_is_remaped_nocache && + ccbuf_phyAddress && + ccbuf_phyAddress_virt) { + codec_mm_dma_flush( + ccbuf_phyAddress_virt, + CCBUF_SIZE, + DMA_FROM_DEVICE); + } + wakeup_userdata_poll( + reg & 0xffff, + (unsigned long)ccbuf_phyAddress_virt, + CCBUF_SIZE, 0); + WRITE_VREG(MREG_BUFFEROUT, 0); + } else if (reg) { + info = READ_VREG(MREG_PIC_INFO); + offset = READ_VREG(MREG_FRAME_OFFSET); + + if ((first_i_frame_ready == 0) && + ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && + ((info & PICINFO_ERROR) == 0)) + first_i_frame_ready = 1; + + if ((pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) == 0) + && (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) + || ((info & PICINFO_TYPE_MASK) == + PICINFO_TYPE_P))) + pts_valid = 1; + + /*if (frame_prog == 0) */ + { + frame_prog = info & PICINFO_PROG; + } + + if ((dec_control & + DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) + && (frame_width == 720 || frame_width == 480) + && (frame_height == 576) + && (frame_dur == 3840)) + frame_prog = 0; + else if ((dec_control & + DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) + && (frame_width == 704) && (frame_height == 480) + && (frame_dur == 3200)) + frame_prog = 0; + else if ((dec_control & + DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) + && (frame_width == 704) && (frame_height == 576) + && (frame_dur == 3840)) + frame_prog = 0; + else if ((dec_control & + DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) + && (frame_width == 544) && (frame_height == 576) + && (frame_dur == 3840)) + frame_prog = 0; + else if ((dec_control & + DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) + && (frame_width == 480) && (frame_height == 576) + && (frame_dur == 3840)) + frame_prog = 0; + else if (dec_control & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) + frame_prog = 0; + if (frame_prog & PICINFO_PROG) { + u32 index = ((reg & 0xf) - 1) & 7; + + seqinfo = READ_VREG(MREG_SEQ_INFO); + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + set_frame_info(vf); + vf->signal_type = 0; + vf->index = index; +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + if ((seqinfo & SEQINFO_EXT_AVAILABLE) + && (seqinfo & SEQINFO_PROG)) { + if (info & PICINFO_RPT_FIRST) { + if (info & PICINFO_TOP_FIRST) { + vf->duration = + vf->duration * 3; + /* repeat three times */ + } else { + vf->duration = + vf->duration * 2; + /* repeat two times */ + } + } + vf->duration_pulldown = 0; + /* no pull down */ + + } else { + vf->duration_pulldown = + (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + } + + vf->duration += vf->duration_pulldown; + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(index); + vf->orientation = 0; + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + vf->type_original = vf->type; + + vfbuf_use[index] = 1; + + if ((error_skip(info, vf)) || + ((first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + + } else { + u32 index = ((reg & 0xf) - 1) & 7; + int first_field_type = (info & PICINFO_TOP_FIRST) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; + +#ifdef INTERLACE_SEQ_ALWAYS + /* once an interlaced sequence exist, + always force interlaced type */ + /* to make DI easy. */ + dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE; +#endif + + if (info & PICINFO_FRAME) { + frame_rpt_state = + (info & PICINFO_TOP_FIRST) ? + FRAME_REPEAT_TOP : FRAME_REPEAT_BOT; + } else { + if (frame_rpt_state == FRAME_REPEAT_TOP) { + first_field_type = + VIDTYPE_INTERLACE_TOP; + } else if (frame_rpt_state == + FRAME_REPEAT_BOT) { + first_field_type = + VIDTYPE_INTERLACE_BOTTOM; + } + frame_rpt_state = FRAME_REPEAT_NONE; + } + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + vfbuf_use[index] = 2; + + set_frame_info(vf); + vf->signal_type = 0; + vf->index = index; + vf->type = + (first_field_type == VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->duration >>= 1; + vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(index); + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + vf->type_original = vf->type; + + if ((error_skip(info, vf)) || + ((first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + set_frame_info(vf); + vf->signal_type = 0; + vf->index = index; + vf->type = (first_field_type == + VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->duration >>= 1; + vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(index); + vf->pts = 0; + vf->pts_us64 = 0; + vf->type_original = vf->type; + + if ((error_skip(info, vf)) || + ((first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + kfifo_put(&recycle_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&display_q, + (const struct vframe_s *)vf); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } + + WRITE_VREG(MREG_BUFFEROUT, 0); + } + + return IRQ_HANDLED; +} + +static struct vframe_s *vmpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + if (pool_index(vf) == cur_pool_idx) + kfifo_put(&recycle_q, (const struct vframe_s *)vf); +} + +static int vmpeg_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vmpeg_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vmpeg12_local_init(); + vmpeg12_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vmpeg_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + + return 0; +} + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER +static void vmpeg12_ppmgr_reset(void) +{ + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + + vmpeg12_local_init(); + + pr_info("vmpeg12dec: vf_ppmgr_reset\n"); +} +#endif + +static void vmpeg_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + int fatal_reset = 0; + + enum receviver_start_e state = RECEIVER_INACTIVE; + if (vf_get_receiver(PROVIDER_NAME)) { + state = vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); + if ((state == RECEIVER_STATE_NULL) + || (state == RECEIVER_STATE_NONE)) { + /* receiver has no event_cb or + receiver's event_cb does not process this event */ + state = RECEIVER_INACTIVE; + } + } else + state = RECEIVER_INACTIVE; + + if (READ_VREG(MREG_FATAL_ERROR) == 1) + fatal_reset = 1; + + if ((READ_VREG(MREG_WAIT_BUFFER) != 0) && + (kfifo_is_empty(&recycle_q)) && + (kfifo_is_empty(&display_q)) && (state == RECEIVER_INACTIVE)) { + if (++wait_buffer_counter > 4) + fatal_reset = 1; + + } else + wait_buffer_counter = 0; + + if (fatal_reset && (kfifo_is_empty(&display_q))) { + pr_info("$$$$decoder is waiting for buffer or fatal reset.\n"); + + amvdec_stop(); + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vmpeg12_ppmgr_reset(); +#else + vf_light_unreg_provider(&vmpeg_vf_prov); + vmpeg12_local_init(); + vf_reg_provider(&vmpeg_vf_prov); +#endif + vmpeg12_prot_init(); + amvdec_start(); + } + + while (!kfifo_is_empty(&recycle_q) && (READ_VREG(MREG_BUFFERIN) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index < DECODE_BUFFER_NUM_MAX) && + (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(MREG_BUFFERIN, vf->index + 1); + vf->index = DECODE_BUFFER_NUM_MAX; + } + + if (pool_index(vf) == cur_pool_idx) { + kfifo_put(&newframe_q, + (const struct vframe_s *)vf); + } + } + } + + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_MPEG12, + frame_width, frame_height, fps); + } + + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = frame_width; + vstatus->height = frame_height; + if (frame_dur != 0) + vstatus->fps = 96000 / frame_dur; + else + vstatus->fps = 96000; + vstatus->error_count = READ_VREG(AV_SCRATCH_C); + vstatus->status = stat; + + return 0; +} + +/****************************************/ +static void vmpeg12_canvas_init(void) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + u32 disp_addr = 0xffffffff; + + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + /* HD & SD */ + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + + if (is_vpp_postblend()) { + struct canvas_s cur_canvas; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + } + + for (i = 0; i < 8; i++) { + if (((buf_start + i * decbuf_size + 7) >> 3) == disp_addr) { +#ifdef NV21 + canvas_config(2 * i + 0, + buf_start + 8 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(2 * i + 1, + buf_start + 8 * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(3 * i + 0, + buf_start + 8 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 1, + buf_start + 8 * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 2, + buf_start + 8 * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); +#endif + } else { +#ifdef NV21 + canvas_config(2 * i + 0, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(2 * i + 1, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(3 * i + 0, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 1, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 2, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); +#endif + } + } + + WRITE_VREG(MREG_CO_MV_START, + buf_start + 9 * decbuf_size + CCBUF_SIZE); + if (!ccbuf_phyAddress) { + ccbuf_phyAddress = (u32)(buf_start + 9 * decbuf_size); + ccbuf_phyAddress_virt = codec_mm_phys_to_virt(ccbuf_phyAddress); + if (!ccbuf_phyAddress_virt) { + ccbuf_phyAddress_virt = ioremap_nocache( + ccbuf_phyAddress, + CCBUF_SIZE); + ccbuf_phyAddress_is_remaped_nocache = 1; + } + } + +} + +static void vmpeg12_prot_init(void) +{ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + int save_reg = READ_VREG(POWER_CTL_VLD); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1<<9) | (1<<8)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(MDEC_SW_RESET, (1 << 7)); + WRITE_VREG(MDEC_SW_RESET, 0); + } + + WRITE_VREG(POWER_CTL_VLD, save_reg); + + } else + WRITE_MPEG_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); + + vmpeg12_canvas_init(); + +#ifdef NV21 + WRITE_VREG(AV_SCRATCH_0, 0x010100); + WRITE_VREG(AV_SCRATCH_1, 0x030302); + WRITE_VREG(AV_SCRATCH_2, 0x050504); + WRITE_VREG(AV_SCRATCH_3, 0x070706); + WRITE_VREG(AV_SCRATCH_4, 0x090908); + WRITE_VREG(AV_SCRATCH_5, 0x0b0b0a); + WRITE_VREG(AV_SCRATCH_6, 0x0d0d0c); + WRITE_VREG(AV_SCRATCH_7, 0x0f0f0e); +#else + WRITE_VREG(AV_SCRATCH_0, 0x020100); + WRITE_VREG(AV_SCRATCH_1, 0x050403); + WRITE_VREG(AV_SCRATCH_2, 0x080706); + WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); + WRITE_VREG(AV_SCRATCH_4, 0x0e0d0c); + WRITE_VREG(AV_SCRATCH_5, 0x11100f); + WRITE_VREG(AV_SCRATCH_6, 0x141312); + WRITE_VREG(AV_SCRATCH_7, 0x171615); +#endif + + /* set to mpeg1 default */ + WRITE_VREG(MPEG1_2_REG, 0); + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + /* for Mpeg1 default value */ + WRITE_VREG(PIC_HEAD_INFO, 0x380); + /* disable mpeg4 */ + WRITE_VREG(M4_CONTROL_REG, 0); + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + /* clear buffer IN/OUT registers */ + WRITE_VREG(MREG_BUFFERIN, 0); + WRITE_VREG(MREG_BUFFEROUT, 0); + /* set reference width and height */ + if ((frame_width != 0) && (frame_height != 0)) + WRITE_VREG(MREG_CMD, (frame_width << 16) | frame_height); + else + WRITE_VREG(MREG_CMD, 0); + /* clear error count */ + WRITE_VREG(MREG_ERROR_COUNT, 0); + WRITE_VREG(MREG_FATAL_ERROR, 0); + /* clear wait buffer status */ + WRITE_VREG(MREG_WAIT_BUFFER, 0); +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif +} + +static void vmpeg12_local_init(void) +{ + int i; + + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + cur_pool_idx ^= 1; + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf; + if (cur_pool_idx == 0) { + vf = &vfpool[i]; + vfpool[i].index = DECODE_BUFFER_NUM_MAX; + } else { + vf = &vfpool2[i]; + vfpool2[i].index = DECODE_BUFFER_NUM_MAX; + } + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + vfbuf_use[i] = 0; + + + frame_width = frame_height = frame_dur = frame_prog = 0; + frame_force_skip_flag = 0; + wait_buffer_counter = 0; + first_i_frame_ready = 0; + saved_resolution = 0; + dec_control &= DEC_CONTROL_INTERNAL_MASK; +} + +static s32 vmpeg12_init(void) +{ + int ret = -1, size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + vmpeg12_local_init(); + + amvdec_enable(); + + size = get_firmware_data(VIDEO_DEC_MPEG12, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_MPEG12, NULL, buf) < 0) { + amvdec_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vmpeg12_prot_init(); + + ret = vdec_request_irq(VDEC_IRQ_1, vmpeg12_isr, + "vmpeg12-irq", (void *)vmpeg12_dec_id); + + if (ret) { + amvdec_disable(); + amlog_level(LOG_LEVEL_ERROR, "vmpeg12 irq register error.\n"); + return -ENOENT; + } + + stat |= STAT_ISR_REG; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, + NULL); + vf_reg_provider(&vmpeg_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, + NULL); + vf_reg_provider(&vmpeg_vf_prov); +#endif + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)vmpeg12_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong)&recycle_timer; + recycle_timer.function = vmpeg_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int amvdec_mpeg12_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe start.\n"); + + if (pdata == NULL) { + amlog_level(LOG_LEVEL_ERROR, + "amvdec_mpeg12 platform data undefined.\n"); + return -EFAULT; + } + + if (pdata->sys_info) + vmpeg12_amstream_dec_info = *pdata->sys_info; + + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; + + pdata->dec_status = vmpeg12_dec_status; + + if (vmpeg12_init() < 0) { + amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg12 init failed.\n"); + + return -ENODEV; + } + + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe end.\n"); + + return 0; +} + +static int amvdec_mpeg12_remove(struct platform_device *pdev) +{ + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)vmpeg12_dec_id); + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vmpeg_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + amvdec_disable(); + if (ccbuf_phyAddress_is_remaped_nocache) + iounmap(ccbuf_phyAddress_virt); + + ccbuf_phyAddress_virt = NULL; + ccbuf_phyAddress = 0; + ccbuf_phyAddress_is_remaped_nocache = 0; + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 remove.\n"); + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_mpeg12_driver = { + .probe = amvdec_mpeg12_probe, + .remove = amvdec_mpeg12_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_mpeg12_profile = { + .name = "mpeg12", + .profile = "" +}; + +static int __init amvdec_mpeg12_driver_init_module(void) +{ + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 module init\n"); + + if (platform_driver_register(&amvdec_mpeg12_driver)) { + amlog_level(LOG_LEVEL_ERROR, + "failed to register amvdec_mpeg12 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_mpeg12_profile); + return 0; +} + +static void __exit amvdec_mpeg12_driver_remove_module(void) +{ + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 module remove.\n"); + + platform_driver_unregister(&amvdec_mpeg12_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_mpeg12 stat\n"); +module_param(dec_control, uint, 0664); +MODULE_PARM_DESC(dec_control, "\n amvmpeg12 decoder control\n"); +module_param(error_frame_skip_level, uint, 0664); +MODULE_PARM_DESC(error_frame_skip_level, + "\n amvdec_mpeg12 error_frame_skip_level\n"); + +module_init(amvdec_mpeg12_driver_init_module); +module_exit(amvdec_mpeg12_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MPEG1/2 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h new file mode 100644 index 000000000000..2038c0657dca --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.h @@ -0,0 +1,26 @@ +/* + * drivers/amlogic/amports/vmpeg12.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VMPEG12_H +#define VMPEG12_H + +/* /#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* TODO: move to register headers */ +#define VPP_VD1_POSTBLEND (1 << 10) +/* /#endif */ + +#endif /* VMPEG12_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c new file mode 100644 index 000000000000..1f1541aa9db8 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c @@ -0,0 +1,1127 @@ +/* + * drivers/amlogic/amports/vmpeg4.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "vmpeg4.h" +#include +#include "../../../stream_input/amports/amports_priv.h" + + +/* #define CONFIG_AM_VDEC_MPEG4_LOG */ +#ifdef CONFIG_AM_VDEC_MPEG4_LOG +#define AMLOG +#define LOG_LEVEL_VAR amlog_level_vmpeg4 +#define LOG_MASK_VAR amlog_mask_vmpeg4 +#define LOG_LEVEL_ERROR 0 +#define LOG_LEVEL_INFO 1 +#define LOG_LEVEL_DESC "0:ERROR, 1:INFO" +#define LOG_MASK_PTS 0x01 +#define LOG_MASK_DESC "0x01:DEBUG_PTS" +#endif + +#include + +MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); + +#include "../utils/amvdec.h" +#include "../utils/vdec.h" + +#define DRIVER_NAME "amvdec_mpeg4" +#define MODULE_NAME "amvdec_mpeg4" + +#define DEBUG_PTS + +/* /#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +/* /#endif */ + +#define I_PICTURE 0 +#define P_PICTURE 1 +#define B_PICTURE 2 + +#define ORI_BUFFER_START_ADDR 0x01000000 + +#define INTERLACE_FLAG 0x80 +#define TOP_FIELD_FIRST_FLAG 0x40 + +/* protocol registers */ +#define MP4_PIC_RATIO AV_SCRATCH_5 +#define MP4_RATE AV_SCRATCH_3 +#define MP4_ERR_COUNT AV_SCRATCH_6 +#define MP4_PIC_WH AV_SCRATCH_7 +#define MREG_BUFFERIN AV_SCRATCH_8 +#define MREG_BUFFEROUT AV_SCRATCH_9 +#define MP4_NOT_CODED_CNT AV_SCRATCH_A +#define MP4_VOP_TIME_INC AV_SCRATCH_B +#define MP4_OFFSET_REG AV_SCRATCH_C +#define MP4_SYS_RATE AV_SCRATCH_E +#define MEM_OFFSET_REG AV_SCRATCH_F + +#define PARC_FORBIDDEN 0 +#define PARC_SQUARE 1 +#define PARC_CIF 2 +#define PARC_10_11 3 +#define PARC_16_11 4 +#define PARC_40_33 5 +#define PARC_RESERVED 6 +/* values between 6 and 14 are reserved */ +#define PARC_EXTENDED 15 + +#define VF_POOL_SIZE 32 +#define DECODE_BUFFER_NUM_MAX 8 +#define PUT_INTERVAL (HZ/100) + +#define RATE_DETECT_COUNT 5 +#define DURATION_UNIT 96000 +#define PTS_UNIT 90000 + +#define DUR2PTS(x) ((x) - ((x) >> 4)) + +static struct vframe_s *vmpeg_vf_peek(void *); +static struct vframe_s *vmpeg_vf_get(void *); +static void vmpeg_vf_put(struct vframe_s *, void *); +static int vmpeg_vf_states(struct vframe_states *states, void *); +static int vmpeg_event_cb(int type, void *data, void *private_data); + +static void vmpeg4_prot_init(void); +static void vmpeg4_local_init(void); + +static const char vmpeg4_dec_id[] = "vmpeg4-dev"; + +#define PROVIDER_NAME "decoder.mpeg4" + +/* +int query_video_status(int type, int *value); +*/ +static const struct vframe_operations_s vmpeg_vf_provider = { + .peek = vmpeg_vf_peek, + .get = vmpeg_vf_get, + .put = vmpeg_vf_put, + .event_cb = vmpeg_event_cb, + .vf_states = vmpeg_vf_states, +}; + +static struct vframe_provider_s vmpeg_vf_prov; + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static struct vframe_s vfpool[VF_POOL_SIZE]; +static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; +static u32 frame_width, frame_height, frame_dur, frame_prog; +static u32 saved_resolution; +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start; +static u32 buf_size, buf_offset; +static u32 vmpeg4_ratio; +static u64 vmpeg4_ratio64; +static u32 rate_detect; +static u32 vmpeg4_rotation; + +static u32 total_frame; +static u32 last_vop_time_inc, last_duration; +static u32 last_anch_pts, vop_time_inc_since_last_anch, + frame_num_since_last_anch; +static u64 last_anch_pts_us64; + +#ifdef CONFIG_AM_VDEC_MPEG4_LOG +u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; +#endif + +static DEFINE_SPINLOCK(lock); + +static struct dec_sysinfo vmpeg4_amstream_dec_info; + +static unsigned char aspect_ratio_table[16] = { + PARC_FORBIDDEN, + PARC_SQUARE, + PARC_CIF, + PARC_10_11, + PARC_16_11, + PARC_40_33, + PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, + PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, + PARC_RESERVED, PARC_EXTENDED +}; + +static inline u32 index2canvas(u32 index) +{ + const u32 canvas_tab[8] = { +#ifdef NV21 + 0x010100, 0x030302, 0x050504, 0x070706, + 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e +#else + 0x020100, 0x050403, 0x080706, 0x0b0a09, + 0x0e0d0c, 0x11100f, 0x141312, 0x171615 +#endif + }; + + return canvas_tab[index]; +} + +static void set_aspect_ratio(struct vframe_s *vf, unsigned pixel_ratio) +{ + int ar = 0; + unsigned int num = 0; + unsigned int den = 0; + + if (vmpeg4_ratio64 != 0) { + num = vmpeg4_ratio64 >> 32; + den = vmpeg4_ratio64 & 0xffffffff; + } else { + num = vmpeg4_ratio >> 16; + den = vmpeg4_ratio & 0xffff; + + } + if ((num == 0) || (den == 0)) { + num = 1; + den = 1; + } + + if (vmpeg4_ratio == 0) { + vf->ratio_control |= (0x90 << DISP_RATIO_ASPECT_RATIO_BIT); + /* always stretch to 16:9 */ + } else if (pixel_ratio > 0x0f) { + num = (pixel_ratio >> 8) * + vmpeg4_amstream_dec_info.width * num; + ar = div_u64((pixel_ratio & 0xff) * + vmpeg4_amstream_dec_info.height * den * 0x100ULL + + (num >> 1), num); + } else { + switch (aspect_ratio_table[pixel_ratio]) { + case 0: + num = vmpeg4_amstream_dec_info.width * num; + ar = (vmpeg4_amstream_dec_info.height * den * 0x100 + + (num >> 1)) / num; + break; + case 1: + num = vf->width * num; + ar = (vf->height * den * 0x100 + (num >> 1)) / num; + break; + case 2: + num = (vf->width * 12) * num; + ar = (vf->height * den * 0x100 * 11 + + ((num) >> 1)) / num; + break; + case 3: + num = (vf->width * 10) * num; + ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / + num; + break; + case 4: + num = (vf->width * 16) * num; + ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / + num; + break; + case 5: + num = (vf->width * 40) * num; + ar = (vf->height * den * 0x100 * 33 + (num >> 1)) / + num; + break; + default: + num = vf->width * num; + ar = (vf->height * den * 0x100 + (num >> 1)) / num; + break; + } + } + + ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); + + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); +} + +static irqreturn_t vmpeg4_isr(int irq, void *dev_id) +{ + u32 reg; + struct vframe_s *vf = NULL; + u32 picture_type; + u32 buffer_index; + u32 pts, pts_valid = 0, offset = 0; + u64 pts_us64 = 0; + u32 rate, vop_time_inc, repeat_cnt, duration = 3200; + + reg = READ_VREG(MREG_BUFFEROUT); + + if (reg) { + buffer_index = reg & 0x7; + picture_type = (reg >> 3) & 7; + rate = READ_VREG(MP4_RATE); + repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT); + vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); + + if (buffer_index >= DECODE_BUFFER_NUM_MAX) { + pr_err("fatal error, invalid buffer index."); + return IRQ_HANDLED; + } + + if (vmpeg4_amstream_dec_info.width == 0) { + vmpeg4_amstream_dec_info.width = + READ_VREG(MP4_PIC_WH) >> 16; + } +#if 0 + else { + pr_info("info width = %d, ucode width = %d\n", + vmpeg4_amstream_dec_info.width, + READ_VREG(MP4_PIC_WH) >> 16); + } +#endif + + if (vmpeg4_amstream_dec_info.height == 0) { + vmpeg4_amstream_dec_info.height = + READ_VREG(MP4_PIC_WH) & 0xffff; + } +#if 0 + else { + pr_info("info height = %d, ucode height = %d\n", + vmpeg4_amstream_dec_info.height, + READ_VREG(MP4_PIC_WH) & 0xffff); + } +#endif + if (vmpeg4_amstream_dec_info.rate == 0 + || vmpeg4_amstream_dec_info.rate > 96000) { + /* if ((rate >> 16) != 0) { */ + if ((rate & 0xffff) != 0 && (rate >> 16) != 0) { + vmpeg4_amstream_dec_info.rate = + (rate >> 16) * DURATION_UNIT / + (rate & 0xffff); + duration = vmpeg4_amstream_dec_info.rate; + } else if (rate_detect < RATE_DETECT_COUNT) { + if (vop_time_inc < last_vop_time_inc) { + duration = + vop_time_inc + rate - + last_vop_time_inc; + } else { + duration = + vop_time_inc - last_vop_time_inc; + } + + if (duration == last_duration) { + rate_detect++; + if (rate_detect >= RATE_DETECT_COUNT) { + vmpeg4_amstream_dec_info.rate = + duration * DURATION_UNIT / + rate; + duration = + vmpeg4_amstream_dec_info.rate; + } + } else + rate_detect = 0; + + last_duration = duration; + } + } else { + duration = vmpeg4_amstream_dec_info.rate; +#if 0 + pr_info("info rate = %d, ucode rate = 0x%x:0x%x\n", + vmpeg4_amstream_dec_info.rate, + READ_VREG(MP4_RATE), vop_time_inc); +#endif + } + + if ((I_PICTURE == picture_type) || + (P_PICTURE == picture_type)) { + offset = READ_VREG(MP4_OFFSET_REG); + /*2500-->3000,because some mpeg4 + video may checkout failed; + may have av sync problem.can changed small later. + 263 may need small? + */ + if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, offset, &pts, 3000, + &pts_us64) == 0) { + pts_valid = 1; + last_anch_pts = pts; + last_anch_pts_us64 = pts_us64; +#ifdef CONFIG_AM_VDEC_MPEG4_LOG + pts_hit++; +#endif + } else { +#ifdef CONFIG_AM_VDEC_MPEG4_LOG + pts_missed++; +#endif + } +#ifdef CONFIG_AM_VDEC_MPEG4_LOG + amlog_mask(LOG_MASK_PTS, + "I offset 0x%x, pts_valid %d pts=0x%x\n", + offset, pts_valid, pts); +#endif + } + + if (pts_valid) { + last_anch_pts = pts; + last_anch_pts_us64 = pts_us64; + frame_num_since_last_anch = 0; + vop_time_inc_since_last_anch = 0; + } else { + pts = last_anch_pts; + pts_us64 = last_anch_pts_us64; + + if ((rate != 0) && ((rate >> 16) == 0) + && vmpeg4_amstream_dec_info.rate == 0) { + /* variable PTS rate */ + /*bug on variable pts calc, + do as dixed vop first if we + have rate setting before. + */ + if (vop_time_inc > last_vop_time_inc) { + vop_time_inc_since_last_anch += + vop_time_inc - last_vop_time_inc; + } else { + vop_time_inc_since_last_anch += + vop_time_inc + rate - + last_vop_time_inc; + } + + pts += vop_time_inc_since_last_anch * + PTS_UNIT / rate; + pts_us64 += (vop_time_inc_since_last_anch * + PTS_UNIT / rate) * 100 / 9; + + if (vop_time_inc_since_last_anch > (1 << 14)) { + /* avoid overflow */ + last_anch_pts = pts; + last_anch_pts_us64 = pts_us64; + vop_time_inc_since_last_anch = 0; + } + } else { + /* fixed VOP rate */ + frame_num_since_last_anch++; + pts += DUR2PTS(frame_num_since_last_anch * + vmpeg4_amstream_dec_info.rate); + pts_us64 += DUR2PTS(frame_num_since_last_anch * + vmpeg4_amstream_dec_info.rate) * + 100 / 9; + + if (frame_num_since_last_anch > (1 << 15)) { + /* avoid overflow */ + last_anch_pts = pts; + last_anch_pts_us64 = pts_us64; + frame_num_since_last_anch = 0; + } + } + } + + if (reg & INTERLACE_FLAG) { /* interlace */ + if (kfifo_get(&newframe_q, &vf) == 0) { + printk + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = vmpeg4_amstream_dec_info.width; + vf->height = vmpeg4_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = vmpeg4_rotation; + vf->pts = pts; + vf->pts_us64 = pts_us64; + vf->duration = duration >> 1; + vf->duration_pulldown = 0; + vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->type_original = vf->type; + + set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO)); + + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + if (kfifo_get(&newframe_q, &vf) == 0) { + printk( + "fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = vmpeg4_amstream_dec_info.width; + vf->height = vmpeg4_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = vmpeg4_rotation; + + vf->pts = 0; + vf->pts_us64 = 0; + vf->duration = duration >> 1; + + vf->duration_pulldown = 0; + vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->type_original = vf->type; + + set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO)); + + vfbuf_use[buffer_index]++; + + amlog_mask(LOG_MASK_PTS, + "[%s:%d] [inte] dur=0x%x rate=%d picture_type=%d\n", + __func__, __LINE__, vf->duration, + vmpeg4_amstream_dec_info.rate, picture_type); + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + } else { /* progressive */ + if (kfifo_get(&newframe_q, &vf) == 0) { + printk + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = vmpeg4_amstream_dec_info.width; + vf->height = vmpeg4_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = vmpeg4_rotation; + vf->pts = pts; + vf->pts_us64 = pts_us64; + vf->duration = duration; + vf->duration_pulldown = repeat_cnt * duration; +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->type_original = vf->type; + + set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO)); + + amlog_mask(LOG_MASK_PTS, + "[%s:%d] [prog] dur=0x%x rate=%d picture_type=%d\n", + __func__, __LINE__, vf->duration, + vmpeg4_amstream_dec_info.rate, picture_type); + + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + + total_frame += repeat_cnt + 1; + + WRITE_VREG(MREG_BUFFEROUT, 0); + + last_vop_time_inc = vop_time_inc; + } + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + return IRQ_HANDLED; +} + +static struct vframe_s *vmpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + kfifo_put(&recycle_q, (const struct vframe_s *)vf); +} + +static int vmpeg_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vmpeg_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vmpeg4_local_init(); + vmpeg4_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vmpeg_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + + return 0; +} + +static void vmpeg_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + + while (!kfifo_is_empty(&recycle_q) && (READ_VREG(MREG_BUFFERIN) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index >= 0) + && (vf->index < DECODE_BUFFER_NUM_MAX) + && (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(MREG_BUFFERIN, ~(1 << vf->index)); + vf->index = DECODE_BUFFER_NUM_MAX; + } + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } + } + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_MPEG4, + frame_width, frame_height, fps); + } + if (READ_VREG(AV_SCRATCH_L)) { + unsigned long flags; + pr_info("mpeg4 fatal error happened,need reset !!\n"); + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vmpeg_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vmpeg4_local_init(); + vmpeg4_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vmpeg_vf_prov); +#endif + amvdec_start(); + } + + + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vmpeg4_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = vmpeg4_amstream_dec_info.width; + vstatus->height = vmpeg4_amstream_dec_info.height; + if (0 != vmpeg4_amstream_dec_info.rate) + vstatus->fps = DURATION_UNIT / vmpeg4_amstream_dec_info.rate; + else + vstatus->fps = DURATION_UNIT; + vstatus->error_count = READ_VREG(MP4_ERR_COUNT); + vstatus->status = stat; + + return 0; +} + +/****************************************/ +static void vmpeg4_canvas_init(void) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + u32 disp_addr = 0xffffffff; + u32 buff_off = 0; + + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + int w = vmpeg4_amstream_dec_info.width; + int h = vmpeg4_amstream_dec_info.height; + int align_w, align_h; + int max, min; + align_w = ALIGN(w, 64); + align_h = ALIGN(h, 64); + if (align_w > align_h) { + max = align_w; + min = align_h; + } else { + max = align_h; + min = align_w; + } + /* HD & SD */ + if ((max > 1920 || min > 1088) && + ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= + buf_size) { + canvas_width = align_w; + canvas_height = align_h; + decbuf_y_size = ALIGN(align_w * align_h, SZ_64K); + decbuf_uv_size = ALIGN(align_w * align_h/4, SZ_64K); + decbuf_size = ALIGN(align_w * align_h * 3/2, SZ_64K); + } else { /*1080p*/ + if (h > w) { + canvas_width = 1088; + canvas_height = 1920; + } else { + canvas_width = 1920; + canvas_height = 1088; + } + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + } + + if (is_vpp_postblend()) { + struct canvas_s cur_canvas; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + } + + for (i = 0; i < 8; i++) { + u32 one_buf_start = buf_start + buff_off; + if (((one_buf_start + 7) >> 3) == disp_addr) { + /*last disp buffer, to next..*/ + buff_off += decbuf_size; + one_buf_start = buf_start + buff_off; + pr_info("one_buf_start %d,=== %x disp_addr %x", + i, one_buf_start, disp_addr); + } + if (buff_off < 0x02000000 && + buff_off + decbuf_size > 0x01b00000){ + /*0x01b00000 is references buffer. + to next 32M;*/ + buff_off = 32 * SZ_1M;/*next 32M*/ + one_buf_start = buf_start + buff_off; + } + if (buff_off + decbuf_size > buf_size) { + pr_err("ERROR::too small buffer for buf%d %d x%d ,size =%d\n", + i, + canvas_width, + canvas_height, + buf_size); + } + pr_debug("alloced buffer %d at %x,%d\n", + i, one_buf_start, decbuf_size); +#ifdef NV21 + canvas_config(2 * i + 0, + one_buf_start, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(2 * i + 1, + one_buf_start + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(3 * i + 0, + one_buf_start, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 1, + one_buf_start + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 2, + one_buf_start + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); +#endif + buff_off = buff_off + decbuf_size; + } +} + +static void vmpeg4_prot_init(void) +{ +#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); +#endif + + vmpeg4_canvas_init(); + + /* index v << 16 | u << 8 | y */ +#ifdef NV21 + WRITE_VREG(AV_SCRATCH_0, 0x010100); + WRITE_VREG(AV_SCRATCH_1, 0x030302); + WRITE_VREG(AV_SCRATCH_2, 0x050504); + WRITE_VREG(AV_SCRATCH_3, 0x070706); + WRITE_VREG(AV_SCRATCH_G, 0x090908); + WRITE_VREG(AV_SCRATCH_H, 0x0b0b0a); + WRITE_VREG(AV_SCRATCH_I, 0x0d0d0c); + WRITE_VREG(AV_SCRATCH_J, 0x0f0f0e); +#else + WRITE_VREG(AV_SCRATCH_0, 0x020100); + WRITE_VREG(AV_SCRATCH_1, 0x050403); + WRITE_VREG(AV_SCRATCH_2, 0x080706); + WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); + WRITE_VREG(AV_SCRATCH_G, 0x0e0d0c); + WRITE_VREG(AV_SCRATCH_H, 0x11100f); + WRITE_VREG(AV_SCRATCH_I, 0x141312); + WRITE_VREG(AV_SCRATCH_J, 0x171615); +#endif + WRITE_VREG(AV_SCRATCH_L, 0);/*clearfatal error flag*/ + + /* notify ucode the buffer offset */ + WRITE_VREG(AV_SCRATCH_F, buf_offset); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(MREG_BUFFERIN, 0); + WRITE_VREG(MREG_BUFFEROUT, 0); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + + /* clear repeat count */ + WRITE_VREG(MP4_NOT_CODED_CNT, 0); + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif + +#if 1/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + printk("mpeg4 meson8 prot init\n"); + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); +#endif + + WRITE_VREG(MP4_PIC_WH, (vmpeg4_amstream_dec_info. + width << 16) | vmpeg4_amstream_dec_info.height); + WRITE_VREG(MP4_SYS_RATE, vmpeg4_amstream_dec_info.rate); +} + +static void vmpeg4_local_init(void) +{ + int i; + + vmpeg4_ratio = vmpeg4_amstream_dec_info.ratio; + + vmpeg4_ratio64 = vmpeg4_amstream_dec_info.ratio64; + + vmpeg4_rotation = + (((unsigned long) vmpeg4_amstream_dec_info.param) + >> 16) & 0xffff; + + frame_width = frame_height = frame_dur = frame_prog = 0; + + total_frame = 0; + saved_resolution = 0; + last_anch_pts = 0; + + last_anch_pts_us64 = 0; + + last_vop_time_inc = last_duration = 0; + + vop_time_inc_since_last_anch = 0; + + frame_num_since_last_anch = 0; + +#ifdef CONFIG_AM_VDEC_MPEG4_LOG + pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0; +#endif + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + vfbuf_use[i] = 0; + + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &vfpool[i]; + vfpool[i].index = DECODE_BUFFER_NUM_MAX; + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } +} + +static s32 vmpeg4_init(void) +{ + int trickmode_fffb = 0; + int size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + query_video_status(0, &trickmode_fffb); + + amlog_level(LOG_LEVEL_INFO, "vmpeg4_init\n"); + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + amvdec_enable(); + + vmpeg4_local_init(); + + if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_3) { + size = get_firmware_data(VIDEO_DEC_MPEG4_3, buf); + + amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_3\n"); + } else if (vmpeg4_amstream_dec_info.format == + VIDEO_DEC_FORMAT_MPEG4_4) { + size = get_firmware_data(VIDEO_DEC_MPEG4_4, buf); + + amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_4\n"); + } else if (vmpeg4_amstream_dec_info.format == + VIDEO_DEC_FORMAT_MPEG4_5) { + size = get_firmware_data(VIDEO_DEC_MPEG4_5, buf); + + amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_5\n"); + } else if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_H263) { + size = get_firmware_data(VIDEO_DEC_H263, buf); + + amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_H263\n"); + } else + amlog_level(LOG_LEVEL_ERROR, "not supported MPEG4 format\n"); + + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_MPEG4, NULL, buf) < 0) { + amvdec_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vmpeg4_prot_init(); + + if (vdec_request_irq(VDEC_IRQ_1, vmpeg4_isr, + "vmpeg4-irq", (void *)vmpeg4_dec_id)) { + amvdec_disable(); + + amlog_level(LOG_LEVEL_ERROR, "vmpeg4 irq register error.\n"); + return -ENOENT; + } + + stat |= STAT_ISR_REG; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, + NULL); + vf_reg_provider(&vmpeg_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, + NULL); + vf_reg_provider(&vmpeg_vf_prov); +#endif + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)vmpeg4_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong)&recycle_timer; + recycle_timer.function = vmpeg_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int amvdec_mpeg4_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + if (pdata == NULL) { + amlog_level(LOG_LEVEL_ERROR, + "amvdec_mpeg4 memory resource undefined.\n"); + return -EFAULT; + } + + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; + buf_offset = buf_start - ORI_BUFFER_START_ADDR; + + if (pdata->sys_info) + vmpeg4_amstream_dec_info = *pdata->sys_info; + + pdata->dec_status = vmpeg4_dec_status; + + if (vmpeg4_init() < 0) { + amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg4 init failed.\n"); + + return -ENODEV; + } + + return 0; +} + +static int amvdec_mpeg4_remove(struct platform_device *pdev) +{ + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)vmpeg4_dec_id); + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vmpeg_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + amvdec_disable(); + + amlog_mask(LOG_MASK_PTS, + "pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit, + pts_missed, pts_i_hit, pts_i_missed); + amlog_mask(LOG_MASK_PTS, "total frame %d, rate %d\n", total_frame, + vmpeg4_amstream_dec_info.rate); + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_mpeg4_driver = { + .probe = amvdec_mpeg4_probe, + .remove = amvdec_mpeg4_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_mpeg4_profile = { + .name = "mpeg4", + .profile = "" +}; + +static int __init amvdec_mpeg4_driver_init_module(void) +{ + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg4 module init\n"); + + if (platform_driver_register(&amvdec_mpeg4_driver)) { + amlog_level(LOG_LEVEL_ERROR, + "failed to register amvdec_mpeg4 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_mpeg4_profile); + return 0; +} + +static void __exit amvdec_mpeg4_driver_remove_module(void) +{ + amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg4 module remove.\n"); + + platform_driver_unregister(&amvdec_mpeg4_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_mpeg4 stat\n"); + +module_init(amvdec_mpeg4_driver_init_module); +module_exit(amvdec_mpeg4_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MPEG4 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h new file mode 100644 index 000000000000..21ff478d2283 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.h @@ -0,0 +1,26 @@ +/* + * drivers/amlogic/amports/vmpeg4.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VMPEG4_H +#define VMPEG4_H + +/* /#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* TODO: move to register headers */ +#define VPP_VD1_POSTBLEND (1 << 10) +/* /#endif */ + +#endif /* VMPEG4_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c new file mode 100644 index 000000000000..5c4b242f8ba8 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -0,0 +1,1304 @@ +/* + * drivers/amlogic/amports/vmpeg4.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "vmpeg4.h" +#include +#include "../../../stream_input/amports/amports_priv.h" + +#include "../utils/amvdec.h" +#include "../utils/vdec_input.h" +#include "../utils/vdec.h" + +#define DRIVER_NAME "ammvdec_mpeg4" +#define MODULE_NAME "ammvdec_mpeg4" + +#define MEM_NAME "codec_mpeg4" + +#define DEBUG_PTS + +#define NV21 +#define I_PICTURE 0 +#define P_PICTURE 1 +#define B_PICTURE 2 + +#define ORI_BUFFER_START_ADDR 0x01000000 +#define DEFAULT_MEM_SIZE (32*SZ_1M) + +#define INTERLACE_FLAG 0x80 +#define TOP_FIELD_FIRST_FLAG 0x40 + +/* protocol registers */ +#define MREG_REF0 AV_SCRATCH_1 +#define MREG_REF1 AV_SCRATCH_2 +#define MP4_PIC_RATIO AV_SCRATCH_5 +#define MP4_RATE AV_SCRATCH_3 +#define MP4_ERR_COUNT AV_SCRATCH_6 +#define MP4_PIC_WH AV_SCRATCH_7 +#define MREG_INPUT AV_SCRATCH_8 +#define MREG_BUFFEROUT AV_SCRATCH_9 +#define MP4_NOT_CODED_CNT AV_SCRATCH_A +#define MP4_VOP_TIME_INC AV_SCRATCH_B +#define MP4_OFFSET_REG AV_SCRATCH_C +#define MP4_SYS_RATE AV_SCRATCH_E +#define MEM_OFFSET_REG AV_SCRATCH_F + +#define PARC_FORBIDDEN 0 +#define PARC_SQUARE 1 +#define PARC_CIF 2 +#define PARC_10_11 3 +#define PARC_16_11 4 +#define PARC_40_33 5 +#define PARC_RESERVED 6 +/* values between 6 and 14 are reserved */ +#define PARC_EXTENDED 15 + +#define VF_POOL_SIZE 16 +#define DECODE_BUFFER_NUM_MAX 4 +#define PUT_INTERVAL (HZ/100) + +#define CTX_LMEM_SWAP_OFFSET 0 +#define CTX_QUANT_MATRIX_OFFSET 0x800 +/* dcac buffer must align at 4k boundary */ +#define CTX_DCAC_BUF_OFFSET 0x1000 +#define CTX_DECBUF_OFFSET (0x0c0000 + 0x1000) + +#define RATE_DETECT_COUNT 5 +#define DURATION_UNIT 96000 +#define PTS_UNIT 90000 + +#define DUR2PTS(x) ((x) - ((x) >> 4)) + +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 +#define DEC_RESULT_ERROR 3 + +static struct vframe_s *vmpeg_vf_peek(void *); +static struct vframe_s *vmpeg_vf_get(void *); +static void vmpeg_vf_put(struct vframe_s *, void *); +static int vmpeg_vf_states(struct vframe_states *states, void *); +static int vmpeg_event_cb(int type, void *data, void *private_data); + +struct vdec_mpeg4_hw_s { + spinlock_t lock; + struct platform_device *platform_dev; + struct device *cma_dev; + + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + struct vframe_s vfpool[VF_POOL_SIZE]; + + s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; + u32 frame_width; + u32 frame_height; + u32 frame_dur; + u32 frame_prog; + + u32 ctx_valid; + u32 reg_vcop_ctrl_reg; + u32 reg_pic_head_info; + u32 reg_mpeg1_2_reg; + u32 reg_slice_qp; + u32 reg_mp4_pic_wh; + u32 reg_mp4_rate; + u32 reg_mb_info; + u32 reg_dc_ac_ctrl; + u32 reg_iqidct_control; + u32 reg_resync_marker_length; + u32 reg_rv_ai_mb_count; + + struct vframe_chunk_s *chunk; + u32 stat; + u32 buf_start; + u32 buf_size; + unsigned long cma_alloc_addr; + int cma_alloc_count; + u32 vmpeg4_ratio; + u64 vmpeg4_ratio64; + u32 rate_detect; + u32 vmpeg4_rotation; + u32 total_frame; + u32 last_vop_time_inc; + u32 last_duration; + u32 last_anch_pts; + u32 vop_time_inc_since_last_anch; + u32 frame_num_since_last_anch; + u64 last_anch_pts_us64; + + u32 pts_hit; + u32 pts_missed; + u32 pts_i_hit; + u32 pts_i_missed; + + u32 buffer_info[DECODE_BUFFER_NUM_MAX]; + u32 pts[DECODE_BUFFER_NUM_MAX]; + u64 pts64[DECODE_BUFFER_NUM_MAX]; + bool pts_valid[DECODE_BUFFER_NUM_MAX]; + u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; +#ifdef NV21 + struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; +#else + struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][3]; +#endif + struct dec_sysinfo vmpeg4_amstream_dec_info; + + s32 refs[2]; + int dec_result; + struct work_struct work; + + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; + +}; +static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); +static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw); + +#define PROVIDER_NAME "vdec.mpeg4" + +/* +int query_video_status(int type, int *value); +*/ +static const struct vframe_operations_s vf_provider_ops = { + .peek = vmpeg_vf_peek, + .get = vmpeg_vf_get, + .put = vmpeg_vf_put, + .event_cb = vmpeg_event_cb, + .vf_states = vmpeg_vf_states, +}; + +static unsigned char aspect_ratio_table[16] = { + PARC_FORBIDDEN, + PARC_SQUARE, + PARC_CIF, + PARC_10_11, + PARC_16_11, + PARC_40_33, + PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, + PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, + PARC_RESERVED, PARC_EXTENDED +}; + +static int find_buffer(struct vdec_mpeg4_hw_s *hw) +{ + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + return i; + } + + return -1; +} + +static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec) +{ + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->canvas_spec[i] == spec) + return i; + } + + return -1; +} + +static void set_frame_info(struct vdec_mpeg4_hw_s *hw, struct vframe_s *vf, + int buffer_index) +{ + int ar = 0; + unsigned int num = 0; + unsigned int den = 0; + unsigned pixel_ratio = READ_VREG(MP4_PIC_RATIO); + + if (hw->vmpeg4_ratio64 != 0) { + num = hw->vmpeg4_ratio64>>32; + den = hw->vmpeg4_ratio64 & 0xffffffff; + } else { + num = hw->vmpeg4_ratio>>16; + den = hw->vmpeg4_ratio & 0xffff; + + } + if ((num == 0) || (den == 0)) { + num = 1; + den = 1; + } + + if (hw->vmpeg4_ratio == 0) { + vf->ratio_control |= (0x90 << DISP_RATIO_ASPECT_RATIO_BIT); + /* always stretch to 16:9 */ + } else if (pixel_ratio > 0x0f) { + num = (pixel_ratio >> 8) * + hw->vmpeg4_amstream_dec_info.width * num; + ar = div_u64((pixel_ratio & 0xff) * + hw->vmpeg4_amstream_dec_info.height * den * 0x100ULL + + (num >> 1), num); + } else { + switch (aspect_ratio_table[pixel_ratio]) { + case 0: + num = hw->vmpeg4_amstream_dec_info.width * num; + ar = (hw->vmpeg4_amstream_dec_info.height * den * + 0x100 + (num >> 1)) / num; + break; + case 1: + num = vf->width * num; + ar = (vf->height * den * 0x100 + (num >> 1)) / num; + break; + case 2: + num = (vf->width * 12) * num; + ar = (vf->height * den * 0x100 * 11 + + ((num) >> 1)) / num; + break; + case 3: + num = (vf->width * 10) * num; + ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / + num; + break; + case 4: + num = (vf->width * 16) * num; + ar = (vf->height * den * 0x100 * 11 + (num >> 1)) / + num; + break; + case 5: + num = (vf->width * 40) * num; + ar = (vf->height * den * 0x100 * 33 + (num >> 1)) / + num; + break; + default: + num = vf->width * num; + ar = (vf->height * den * 0x100 + (num >> 1)) / num; + break; + } + } + + ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); + + vf->signal_type = 0; + vf->type_original = vf->type; + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + vf->canvas0Addr = vf->canvas1Addr = -1; +#ifdef NV21 + vf->plane_num = 2; +#else + vf->plane_num = 3; +#endif + vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; + vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; +#ifndef NV21 + vf->canvas0_config[2] = hw->canvas_config[buffer_index][2]; +#endif + vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; + vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; +#ifndef NV21 + vf->canvas1_config[2] = hw->canvas_config[buffer_index][2]; +#endif +} + +static inline void vmpeg4_save_hw_context(struct vdec_mpeg4_hw_s *hw) +{ + hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG); + hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); + hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO); + hw->reg_slice_qp = READ_VREG(SLICE_QP); + hw->reg_mp4_pic_wh = READ_VREG(MP4_PIC_WH); + hw->reg_mp4_rate = READ_VREG(MP4_RATE); + hw->reg_mb_info = READ_VREG(MB_INFO); + hw->reg_dc_ac_ctrl = READ_VREG(DC_AC_CTRL); + hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); + hw->reg_resync_marker_length = READ_VREG(RESYNC_MARKER_LENGTH); + hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); +} + +static irqreturn_t vmpeg4_isr(struct vdec_s *vdec) +{ + u32 reg; + struct vframe_s *vf = NULL; + u32 picture_type; + int index; + u32 pts, offset = 0; + bool pts_valid = false; + u64 pts_us64 = 0; + u32 time_increment_resolution, fixed_vop_rate, vop_time_inc; + u32 repeat_cnt, duration = 3200; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + reg = READ_VREG(MREG_BUFFEROUT); + + time_increment_resolution = READ_VREG(MP4_RATE); + fixed_vop_rate = time_increment_resolution >> 16; + time_increment_resolution &= 0xffff; + + if (hw->vmpeg4_amstream_dec_info.rate == 0) { + if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { + /* fixed VOP rate */ + hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * + DURATION_UNIT / + time_increment_resolution; + } + } + + if (reg == 2) { + /* timeout when decoding next frame */ + + /* for frame based case, insufficient result may happen + * at the begining when only VOL head is available save + * HW context also, such as for the QTable from VCOP register + */ + if (input_frame_based(vdec)) + vmpeg4_save_hw_context(hw); + + hw->dec_result = DEC_RESULT_AGAIN; + + schedule_work(&hw->work); + + return IRQ_HANDLED; + } else { + picture_type = (reg >> 3) & 7; + repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT); + vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); + + index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); + + if (index < 0) { + pr_err("invalid buffer index."); + hw->dec_result = DEC_RESULT_ERROR; + + schedule_work(&hw->work); + + return IRQ_HANDLED; + } + + hw->dec_result = DEC_RESULT_DONE; + + pr_debug("amvdec_mpeg4: offset = 0x%x\n", + READ_VREG(MP4_OFFSET_REG)); + + if (hw->vmpeg4_amstream_dec_info.width == 0) { + hw->vmpeg4_amstream_dec_info.width = + READ_VREG(MP4_PIC_WH) >> 16; + } +#if 0 + else { + pr_info("info width = %d, ucode width = %d\n", + hw->vmpeg4_amstream_dec_info.width, + READ_VREG(MP4_PIC_WH) >> 16); + } +#endif + + if (hw->vmpeg4_amstream_dec_info.height == 0) { + hw->vmpeg4_amstream_dec_info.height = + READ_VREG(MP4_PIC_WH) & 0xffff; + } +#if 0 + else { + pr_info("info height = %d, ucode height = %d\n", + hw->vmpeg4_amstream_dec_info.height, + READ_VREG(MP4_PIC_WH) & 0xffff); + } +#endif + if (hw->vmpeg4_amstream_dec_info.rate == 0) { + if (vop_time_inc < hw->last_vop_time_inc) { + duration = vop_time_inc + + time_increment_resolution - + hw->last_vop_time_inc; + } else { + duration = vop_time_inc - + hw->last_vop_time_inc; + } + + if (duration == hw->last_duration) { + hw->rate_detect++; + if (hw->rate_detect >= RATE_DETECT_COUNT) { + hw->vmpeg4_amstream_dec_info.rate = + duration * DURATION_UNIT / + time_increment_resolution; + duration = + hw->vmpeg4_amstream_dec_info.rate; + } + } else { + hw->rate_detect = 0; + hw->last_duration = duration; + } + } else { + duration = hw->vmpeg4_amstream_dec_info.rate; +#if 0 + pr_info("info rate = %d, ucode rate = 0x%x:0x%x\n", + hw->vmpeg4_amstream_dec_info.rate, + READ_VREG(MP4_RATE), vop_time_inc); +#endif + } + + if ((I_PICTURE == picture_type) || + (P_PICTURE == picture_type)) { + offset = READ_VREG(MP4_OFFSET_REG); + if (hw->chunk) { + hw->pts_valid[index] = hw->chunk->pts_valid; + hw->pts[index] = hw->chunk->pts; + hw->pts64[index] = hw->chunk->pts64; + } else { + if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, offset, &pts, 3000, + &pts_us64) == 0) { + hw->pts_valid[index] = true; + hw->pts[index] = pts; + hw->pts64[index] = pts_us64; + hw->pts_hit++; + } else { + hw->pts_valid[index] = false; + hw->pts_missed++; + } + } + pr_debug("I/P offset 0x%x, pts_valid %d pts=0x%x\n", + offset, hw->pts_valid[index], + hw->pts[index]); + } else { + hw->pts_valid[index] = false; + hw->pts[index] = 0; + hw->pts64[index] = 0; + } + + hw->buffer_info[index] = reg; + hw->vfbuf_use[index] = 0; + + pr_debug("amvdec_mpeg4: decoded buffer %d, frame_type %s\n", + index, + (picture_type == I_PICTURE) ? "I" : + (picture_type == P_PICTURE) ? "P" : "B"); + + /* Buffer management + * todo: add sequence-end flush + */ + if ((picture_type == I_PICTURE) || + (picture_type == P_PICTURE)) { + hw->vfbuf_use[index]++; + + if (hw->refs[1] == -1) { + hw->refs[1] = index; + index = -1; + } else if (hw->refs[0] == -1) { + hw->refs[0] = hw->refs[1]; + hw->refs[1] = index; + index = hw->refs[0]; + } else { + hw->vfbuf_use[hw->refs[0]]--; + hw->refs[0] = hw->refs[1]; + hw->refs[1] = index; + index = hw->refs[0]; + } + } else { + /* if this is a B frame, then drop (depending on if + * there are two reference frames) or display + * immediately + */ + if (hw->refs[1] == -1) + index = -1; + } + + vmpeg4_save_hw_context(hw); + + if (index < 0) { + schedule_work(&hw->work); + return IRQ_HANDLED; + } + + reg = hw->buffer_info[index]; + pts_valid = hw->pts_valid[index]; + pts = hw->pts[index]; + pts_us64 = hw->pts64[index]; + + pr_debug("queued buffer %d, pts = 0x%x, pts_valid=%d\n", + index, pts, pts_valid); + + if (pts_valid) { + hw->last_anch_pts = pts; + hw->last_anch_pts_us64 = pts_us64; + hw->frame_num_since_last_anch = 0; + hw->vop_time_inc_since_last_anch = 0; + } else { + pts = hw->last_anch_pts; + pts_us64 = hw->last_anch_pts_us64; + + if ((time_increment_resolution != 0) && + (fixed_vop_rate == 0) && + (hw->vmpeg4_amstream_dec_info.rate == 0)) { + /* variable PTS rate */ + /*bug on variable pts calc, + do as dixed vop first if we + have rate setting before. + */ + if (vop_time_inc > hw->last_vop_time_inc) { + duration = vop_time_inc - + hw->last_vop_time_inc; + } else { + duration = vop_time_inc + + time_increment_resolution - + hw->last_vop_time_inc; + } + + hw->vop_time_inc_since_last_anch += duration; + + pts += hw->vop_time_inc_since_last_anch * + PTS_UNIT / time_increment_resolution; + pts_us64 += (hw->vop_time_inc_since_last_anch * + PTS_UNIT / time_increment_resolution) * + 100 / 9; + + if (hw->vop_time_inc_since_last_anch > + (1 << 14)) { + /* avoid overflow */ + hw->last_anch_pts = pts; + hw->last_anch_pts_us64 = pts_us64; + hw->vop_time_inc_since_last_anch = 0; + } + } else { + /* fixed VOP rate */ + hw->frame_num_since_last_anch++; + pts += DUR2PTS(hw->frame_num_since_last_anch * + hw->vmpeg4_amstream_dec_info.rate); + pts_us64 += DUR2PTS( + hw->frame_num_since_last_anch * + hw->vmpeg4_amstream_dec_info.rate) * + 100 / 9; + + if (hw->frame_num_since_last_anch > (1 << 15)) { + /* avoid overflow */ + hw->last_anch_pts = pts; + hw->last_anch_pts_us64 = pts_us64; + hw->frame_num_since_last_anch = 0; + } + } + } + + if (reg & INTERLACE_FLAG) { /* interlace */ + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + pr_err + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + vf->index = index; + vf->width = hw->vmpeg4_amstream_dec_info.width; + vf->height = hw->vmpeg4_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = hw->vmpeg4_rotation; + vf->pts = pts; + vf->pts_us64 = pts_us64; + vf->duration = duration >> 1; + vf->duration_pulldown = 0; + vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + set_frame_info(hw, vf, index); + + hw->vfbuf_use[index]++; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + pr_err("fatal error, no available buffer slot."); + hw->dec_result = DEC_RESULT_ERROR; + schedule_work(&hw->work); + return IRQ_HANDLED; + } + + vf->index = index; + vf->width = hw->vmpeg4_amstream_dec_info.width; + vf->height = hw->vmpeg4_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = hw->vmpeg4_rotation; + + vf->pts = 0; + vf->pts_us64 = 0; + vf->duration = duration >> 1; + + vf->duration_pulldown = 0; + vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + set_frame_info(hw, vf, index); + + hw->vfbuf_use[index]++; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + } else { /* progressive */ + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + pr_err("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + vf->index = index; + vf->width = hw->vmpeg4_amstream_dec_info.width; + vf->height = hw->vmpeg4_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = hw->vmpeg4_rotation; + vf->pts = pts; + vf->pts_us64 = pts_us64; + vf->duration = duration; + vf->duration_pulldown = repeat_cnt * duration; +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + set_frame_info(hw, vf, index); + + + hw->vfbuf_use[index]++; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + + hw->total_frame += repeat_cnt + 1; + hw->last_vop_time_inc = vop_time_inc; + + schedule_work(&hw->work); + } + + return IRQ_HANDLED; +} + +static void vmpeg4_work(struct work_struct *work) +{ + struct vdec_mpeg4_hw_s *hw = + container_of(work, struct vdec_mpeg4_hw_s, work); + + /* finished decoding one frame or error, + * notify vdec core to switch context + */ + amvdec_stop(); + + if ((hw->dec_result == DEC_RESULT_DONE) || + ((hw->chunk) && + (input_frame_based(&(hw_to_vdec(hw))->input)))) { + if (!hw->ctx_valid) + hw->ctx_valid = 1; + + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + } + + /* mark itself has all HW resource released and input released */ + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); + + if (hw->vdec_cb) + hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); +} + +static struct vframe_s *vmpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + if (!hw) + return NULL; + + if (kfifo_peek(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + if (kfifo_get(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vdec_s *vdec = op_arg; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + hw->vfbuf_use[vf->index]--; + + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); +} + +static int vmpeg_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + spin_lock_irqsave(&hw->lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&hw->newframe_q); + states->buf_avail_num = kfifo_len(&hw->display_q); + states->buf_recycle_num = 0; + + spin_unlock_irqrestore(&hw->lock, flags); + + return 0; +} + + +static int dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + vstatus->width = hw->vmpeg4_amstream_dec_info.width; + vstatus->height = hw->vmpeg4_amstream_dec_info.height; + if (0 != hw->vmpeg4_amstream_dec_info.rate) + vstatus->fps = DURATION_UNIT / + hw->vmpeg4_amstream_dec_info.rate; + else + vstatus->fps = DURATION_UNIT; + vstatus->error_count = READ_VREG(MP4_ERR_COUNT); + vstatus->status = hw->stat; + + return 0; +} + +/****************************************/ +static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) +{ + int i; + u32 decbuf_size, decbuf_y_size; + struct vdec_s *vdec = hw_to_vdec(hw); + u32 decbuf_start; + + int w = hw->vmpeg4_amstream_dec_info.width; + int h = hw->vmpeg4_amstream_dec_info.height; + + if (w == 0) + w = 1920; + if (h == 0) + h = 1088; + + w = ALIGN(w, 64); + h = ALIGN(h, 64); + decbuf_y_size = ALIGN(w * h, SZ_64K); + decbuf_size = ALIGN(w * h * 3/2, SZ_64K); + + decbuf_start = hw->buf_start + CTX_DECBUF_OFFSET; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { +#ifdef NV21 + unsigned int canvas = vdec->get_canvas(i, 2); +#else + unsigned int canvas = vdec->get_canvas(i, 3); +#endif + + hw->canvas_spec[i] = canvas; + +#ifdef NV21 + hw->canvas_config[i][0].phy_addr = decbuf_start + + i * decbuf_size; + hw->canvas_config[i][0].width = w; + hw->canvas_config[i][0].height = h; + hw->canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32; + + canvas_config_config(canvas_y(canvas), + &hw->canvas_config[i][0]); + + hw->canvas_config[i][1].phy_addr = decbuf_start + + i * decbuf_size + decbuf_y_size; + hw->canvas_config[i][1].width = w; + hw->canvas_config[i][1].height = h / 2; + hw->canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32; + + canvas_config_config(canvas_u(canvas), + &hw->canvas_config[i][1]); +#else + hw->canvas_config[i][0].phy_addr = decbuf_start + + i * decbuf_size; + hw->canvas_config[i][0].width = w; + hw->canvas_config[i][0].height = h; + hw->canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32; + + canvas_config_config(canvas_y(canvas), + &hw->canvas_config[i][0]); + + hw->canvas_config[i][1].phy_addr = decbuf_start + + i * decbuf_size + decbuf_y_size; + hw->canvas_config[i][1].width = w / 2; + hw->canvas_config[i][1].height = h / 2; + hw->canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32; + + canvas_config_config(canvas_u(canvas), + &hw->canvas_config[i][1]); + + hw->canvas_config[i][2].phy_addr = decbuf_start + + i * decbuf_size + decbuf_y_size + + decbuf_uv_size; + hw->canvas_config[i][2].width = w / 2; + hw->canvas_config[i][2].height = h / 2; + hw->canvas_config[i][2].block_mode = CANVAS_BLKMODE_32X32; + + canvas_config_config(canvas_v(canvas), + &hw->canvas_config[i][2]); +#endif + } + + return 0; +} + +static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) +{ + int index; + + + index = find_buffer(hw); + if (index < 0) + return -1; + + + if (vmpeg4_canvas_init(hw) < 0) + return -1; + + /* prepare REF0 & REF1 + * points to the past two IP buffers + * prepare REC_CANVAS_ADDR and ANC2_CANVAS_ADDR + * points to the output buffer + */ + if (hw->refs[0] == -1) { + WRITE_VREG(MREG_REF0, (hw->refs[1] == -1) ? 0xffffffff : + hw->canvas_spec[hw->refs[1]]); + } else { + WRITE_VREG(MREG_REF0, (hw->refs[0] == -1) ? 0xffffffff : + hw->canvas_spec[hw->refs[0]]); + } + WRITE_VREG(MREG_REF1, (hw->refs[1] == -1) ? 0xffffffff : + hw->canvas_spec[hw->refs[1]]); + + WRITE_VREG(MREG_REF0, (hw->refs[0] == -1) ? 0xffffffff : + hw->canvas_spec[hw->refs[0]]); + WRITE_VREG(MREG_REF1, (hw->refs[1] == -1) ? 0xffffffff : + hw->canvas_spec[hw->refs[1]]); + WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); + WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); + + pr_debug("vmpeg4_hw_ctx_restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d\n", + READ_VREG(MREG_REF0), + READ_VREG(MREG_REF1), + READ_VREG(REC_CANVAS_ADDR), + hw->ctx_valid); + + /* notify ucode the buffer start address */ + WRITE_VREG(MEM_OFFSET_REG, hw->buf_start); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(MREG_BUFFEROUT, 0); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + + /* clear repeat count */ + WRITE_VREG(MP4_NOT_CODED_CNT, 0); + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif + +#if 1/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); +#endif + + WRITE_VREG(MP4_PIC_WH, (hw->ctx_valid) ? + hw->reg_mp4_pic_wh : + ((hw->vmpeg4_amstream_dec_info.width << 16) | + hw->vmpeg4_amstream_dec_info.height)); + WRITE_VREG(MP4_SYS_RATE, hw->vmpeg4_amstream_dec_info.rate); + + if (hw->ctx_valid) { + WRITE_VREG(DC_AC_CTRL, hw->reg_dc_ac_ctrl); + WRITE_VREG(IQIDCT_CONTROL, hw->reg_iqidct_control); + WRITE_VREG(RESYNC_MARKER_LENGTH, hw->reg_resync_marker_length); + WRITE_VREG(RV_AI_MB_COUNT, hw->reg_rv_ai_mb_count); + } + WRITE_VREG(MPEG1_2_REG, (hw->ctx_valid) ? hw->reg_mpeg1_2_reg : 1); + WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg); + WRITE_VREG(PIC_HEAD_INFO, hw->reg_pic_head_info); + WRITE_VREG(SLICE_QP, hw->reg_slice_qp); + WRITE_VREG(MB_INFO, hw->reg_mb_info); + + if (hw->chunk) { + /* frame based input */ + WRITE_VREG(MREG_INPUT, (hw->chunk->offset & 7) | (1<<7) | + (hw->ctx_valid<<6)); + } else { + /* stream based input */ + WRITE_VREG(MREG_INPUT, (hw->ctx_valid<<6)); + } + + return 0; +} + +static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) +{ + int i; + + hw->vmpeg4_ratio = hw->vmpeg4_amstream_dec_info.ratio; + + hw->vmpeg4_ratio64 = hw->vmpeg4_amstream_dec_info.ratio64; + + hw->vmpeg4_rotation = + (((unsigned long) hw->vmpeg4_amstream_dec_info.param) + >> 16) & 0xffff; + + hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0; + + hw->total_frame = 0; + + hw->last_anch_pts = 0; + + hw->last_anch_pts_us64 = 0; + + hw->last_vop_time_inc = hw->last_duration = 0; + + hw->vop_time_inc_since_last_anch = 0; + + hw->frame_num_since_last_anch = 0; + + hw->pts_hit = hw->pts_missed = hw->pts_i_hit = hw->pts_i_missed = 0; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->vfbuf_use[i] = 0; + + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &hw->vfpool[i]; + hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); + } + + INIT_WORK(&hw->work, vmpeg4_work); +} + +static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) +{ + int trickmode_fffb = 0; + + query_video_status(0, &trickmode_fffb); + + pr_info("vmpeg4_init\n"); + + amvdec_enable(); + + vmpeg4_local_init(hw); + + return 0; +} + +static bool run_ready(struct vdec_s *vdec) +{ + int index; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + index = find_buffer(hw); + + return index >= 0; +} + +static void run(struct vdec_s *vdec, void (*callback)(struct vdec_s *, void *), + void *arg) +{ + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + int save_reg = READ_VREG(POWER_CTL_VLD); + int ret = -1,size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return; + + /* reset everything except DOS_TOP[1] and APB_CBUS[0] */ + WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); + WRITE_VREG(DOS_SW_RESET0, 0); + WRITE_VREG(POWER_CTL_VLD, save_reg); + + hw->vdec_cb_arg = arg; + hw->vdec_cb = callback; + + ret = vdec_prepare_input(vdec, &hw->chunk); + if (ret < 0) { + pr_debug("amvdec_mpeg4: Input not ready\n"); + hw->dec_result = DEC_RESULT_AGAIN; + schedule_work(&hw->work); + vfree(buf); + return; + } + + vdec_enable_input(vdec); + + if (hw->chunk) + pr_debug("input chunk offset %d, size %d\n", + hw->chunk->offset, hw->chunk->size); + + hw->dec_result = DEC_RESULT_NONE; + + if (hw->vmpeg4_amstream_dec_info.format == + VIDEO_DEC_FORMAT_MPEG4_3) { + size = get_firmware_data(VIDEO_DEC_MPEG4_3, buf); + + pr_info("load VIDEO_DEC_FORMAT_MPEG4_3\n"); + } else if (hw->vmpeg4_amstream_dec_info.format == + VIDEO_DEC_FORMAT_MPEG4_4) { + size = get_firmware_data(VIDEO_DEC_MPEG4_4, buf); + + pr_info("load VIDEO_DEC_FORMAT_MPEG4_4\n"); + } else if (hw->vmpeg4_amstream_dec_info.format == + VIDEO_DEC_FORMAT_MPEG4_5) { + size = get_firmware_data(VIDEO_DEC_MPEG4_5, buf); + + pr_info("load VIDEO_DEC_FORMAT_MPEG4_5\n"); + } else if (hw->vmpeg4_amstream_dec_info.format == + VIDEO_DEC_FORMAT_H263) { + size = get_firmware_data(VIDEO_DEC_H263, buf); + + pr_info("load VIDEO_DEC_FORMAT_H263\n"); + } + + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return; + } + + if (amvdec_vdec_loadmc_buf_ex(vdec, buf, size) < 0) { + hw->dec_result = DEC_RESULT_ERROR; + schedule_work(&hw->work); + vfree(buf); + return; + } + + vfree(buf); + + if (vmpeg4_hw_ctx_restore(hw) < 0) { + hw->dec_result = DEC_RESULT_ERROR; + pr_err("amvdec_mpeg4: error HW context restore\n"); + schedule_work(&hw->work); + return; + } + + /* wmb before ISR is handled */ + wmb(); + + amvdec_start(); +} + +static void reset(struct vdec_s *vdec) +{ + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + + pr_info("amvdec_mpeg4: reset.\n"); + + vmpeg4_local_init(hw); + + hw->ctx_valid = false; +} + +static int amvdec_mpeg4_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct vdec_mpeg4_hw_s *hw = NULL; + + pr_info("amvdec_mpeg4[%d] probe start.\n", pdev->id); + + if (pdata == NULL) { + pr_err("ammvdec_mpeg4 memory resource undefined.\n"); + return -EFAULT; + } + + hw = (struct vdec_mpeg4_hw_s *)devm_kzalloc(&pdev->dev, + sizeof(struct vdec_mpeg4_hw_s), GFP_KERNEL); + if (hw == NULL) { + pr_info("\namvdec_mpeg4 decoder driver alloc failed\n"); + return -ENOMEM; + } + + pdata->private = hw; + pdata->dec_status = dec_status; + /* pdata->set_trickmode = set_trickmode; */ + pdata->run_ready = run_ready; + pdata->run = run; + pdata->reset = reset; + pdata->irq_handler = vmpeg4_isr; + + pdata->id = pdev->id; + + if (pdata->use_vfm_path) + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); + else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + PROVIDER_NAME ".%02x", pdev->id & 0xff); + + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vf_provider_ops, pdata); + + platform_set_drvdata(pdev, pdata); + + hw->platform_dev = pdev; + hw->cma_dev = pdata->cma_dev; + + hw->cma_alloc_count = PAGE_ALIGN(DEFAULT_MEM_SIZE) / PAGE_SIZE; + hw->cma_alloc_addr = codec_mm_alloc_for_dma(MEM_NAME, + hw->cma_alloc_count, + 4, CODEC_MM_FLAGS_FOR_VDECODER); + + if (!hw->cma_alloc_addr) { + pr_err("codec_mm alloc failed, request buf size 0x%lx\n", + hw->cma_alloc_count * PAGE_SIZE); + hw->cma_alloc_count = 0; + return -ENOMEM; + } + hw->buf_start = hw->cma_alloc_addr; + hw->buf_size = DEFAULT_MEM_SIZE; + + if (pdata->sys_info) + hw->vmpeg4_amstream_dec_info = *pdata->sys_info; + + if (vmpeg4_init(hw) < 0) { + pr_err("amvdec_mpeg4 init failed.\n"); + + return -ENODEV; + } + + return 0; +} + +static int amvdec_mpeg4_remove(struct platform_device *pdev) +{ + struct vdec_mpeg4_hw_s *hw = + (struct vdec_mpeg4_hw_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + + + amvdec_disable(); + + if (hw->cma_alloc_addr) { + pr_info("codec_mm release buffer 0x%lx\n", hw->cma_alloc_addr); + codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); + hw->cma_alloc_count = 0; + } + + pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, + hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); + pr_info("total frame %d, rate %d\n", hw->total_frame, + hw->vmpeg4_amstream_dec_info.rate); + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_mpeg4_driver = { + .probe = amvdec_mpeg4_probe, + .remove = amvdec_mpeg4_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_mpeg4_profile = { + .name = "mmpeg4", + .profile = "" +}; + +static int __init amvdec_mmpeg4_driver_init_module(void) +{ + pr_info("amvdec_mmpeg4 module init\n"); + + if (platform_driver_register(&amvdec_mpeg4_driver)) { + pr_err("failed to register amvdec_mpeg4 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_mpeg4_profile); + return 0; +} + +static void __exit amvdec_mmpeg4_driver_remove_module(void) +{ + pr_info("amvdec_mmpeg4 module remove.\n"); + + platform_driver_unregister(&amvdec_mpeg4_driver); +} + +/****************************************/ + +module_init(amvdec_mmpeg4_driver_init_module); +module_exit(amvdec_mmpeg4_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MPEG4 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c new file mode 100644 index 000000000000..d47fa998179e --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c @@ -0,0 +1,1022 @@ +/* + * drivers/amlogic/amports/vreal.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/amports/amports_priv.h" +#include "../utils/vdec.h" +#include +#include "../utils/amvdec.h" + +#include "../../../stream_input/parser/streambuf.h" +#include "../../../stream_input/parser/streambuf_reg.h" +#include "../../../stream_input/parser/rmparser.h" + +#include "vreal.h" +#include + +#define DRIVER_NAME "amvdec_real" +#define MODULE_NAME "amvdec_real" + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +#endif + +#define RM_DEF_BUFFER_ADDR 0x01000000 +/* protocol registers */ +#define STATUS_AMRISC AV_SCRATCH_4 + +#define RV_PIC_INFO AV_SCRATCH_5 +#define VPTS_TR AV_SCRATCH_6 +#define VDTS AV_SCRATCH_7 +#define FROM_AMRISC AV_SCRATCH_8 +#define TO_AMRISC AV_SCRATCH_9 +#define SKIP_B_AMRISC AV_SCRATCH_A +#define INT_REASON AV_SCRATCH_B +#define WAIT_BUFFER AV_SCRATCH_E + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define MDEC_WIDTH AV_SCRATCH_I +#define MDEC_HEIGHT AV_SCRATCH_J +#else +#define MDEC_WIDTH HARM_ASB_MB2 +#define MDEC_HEIGHT HASB_ARM_MB0 +#endif + +#define PARC_FORBIDDEN 0 +#define PARC_SQUARE 1 +#define PARC_CIF 2 +#define PARC_10_11 3 +#define PARC_16_11 4 +#define PARC_40_33 5 +#define PARC_RESERVED 6 +/* values between 6 and 14 are reserved */ +#define PARC_EXTENDED 15 + +#define VF_POOL_SIZE 16 +#define VF_BUF_NUM 4 +#define PUT_INTERVAL (HZ/100) + +static struct vframe_s *vreal_vf_peek(void *); +static struct vframe_s *vreal_vf_get(void *); +static void vreal_vf_put(struct vframe_s *, void *); +static int vreal_vf_states(struct vframe_states *states, void *); +static int vreal_event_cb(int type, void *data, void *private_data); + +static void vreal_prot_init(void); +static void vreal_local_init(void); + +static const char vreal_dec_id[] = "vreal-dev"; + +#define PROVIDER_NAME "decoder.real" + +/* +int query_video_status(int type, int *value); +*/ +static const struct vframe_operations_s vreal_vf_provider = { + .peek = vreal_vf_peek, + .get = vreal_vf_get, + .put = vreal_vf_put, + .event_cb = vreal_event_cb, + .vf_states = vreal_vf_states, +}; + +static struct vframe_provider_s vreal_vf_prov; + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static struct vframe_s vfpool[VF_POOL_SIZE]; +static s32 vfbuf_use[VF_BUF_NUM]; + +static u32 frame_width, frame_height, frame_dur, frame_prog; +static u32 saved_resolution; +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start; +static u32 buf_size, buf_offset; +static u32 vreal_ratio; +u32 vreal_format; +static u32 wait_key_frame; +static u32 last_tr; +static u32 frame_count; +static u32 current_vdts; +static u32 hold; +static u32 decoder_state; +static u32 real_err_count; + +static u32 fatal_flag; +static s32 wait_buffer_counter; + +static DEFINE_SPINLOCK(lock); + +static unsigned short pic_sz_tbl[12] ____cacheline_aligned; +static dma_addr_t pic_sz_tbl_map; +static const unsigned char RPR_size[9] = { 0, 1, 1, 2, 2, 3, 3, 3, 3 }; + +static struct dec_sysinfo vreal_amstream_dec_info; + +static unsigned char aspect_ratio_table[16] = { + PARC_FORBIDDEN, + PARC_SQUARE, + PARC_CIF, + PARC_10_11, + PARC_16_11, + PARC_40_33, + PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, + PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, + PARC_RESERVED, PARC_EXTENDED +}; + +static inline u32 index2canvas(u32 index) +{ + const u32 canvas_tab[4] = { +#ifdef NV21 + 0x010100, 0x030302, 0x050504, 0x070706 +#else + 0x020100, 0x050403, 0x080706, 0x0b0a09 +#endif + }; + + return canvas_tab[index]; +} + +static void set_aspect_ratio(struct vframe_s *vf, unsigned pixel_ratio) +{ + int ar = 0; + + if (vreal_ratio == 0) { + vf->ratio_control |= (0x90 << + DISP_RATIO_ASPECT_RATIO_BIT); + /* always stretch to 16:9 */ + } else { + switch (aspect_ratio_table[pixel_ratio]) { + case 0: + ar = vreal_amstream_dec_info.height * vreal_ratio / + vreal_amstream_dec_info.width; + break; + case 1: + case 0xff: + ar = vreal_ratio * vf->height / vf->width; + break; + case 2: + ar = (vreal_ratio * vf->height * 12) / (vf->width * 11); + break; + case 3: + ar = (vreal_ratio * vf->height * 11) / (vf->width * 10); + break; + case 4: + ar = (vreal_ratio * vf->height * 11) / (vf->width * 16); + break; + case 5: + ar = (vreal_ratio * vf->height * 33) / (vf->width * 40); + break; + default: + ar = vreal_ratio * vf->height / vf->width; + break; + } + } + + ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); + + vf->ratio_control |= (ar << DISP_RATIO_ASPECT_RATIO_BIT); +} + +static irqreturn_t vreal_isr(int irq, void *dev_id) +{ + u32 from; + struct vframe_s *vf = NULL; + u32 buffer_index; + unsigned int status; + unsigned int vdts; + unsigned int info; + unsigned int tr; + unsigned int pictype; + u32 r = READ_VREG(INT_REASON); + + if (decoder_state == 0) + return IRQ_HANDLED; + + status = READ_VREG(STATUS_AMRISC); + if (status & (PARSER_ERROR_WRONG_PACKAGE_SIZE | + PARSER_ERROR_WRONG_HEAD_VER | + DECODER_ERROR_VLC_DECODE_TBL)) { + /* decoder or parser error */ + real_err_count++; + /* pr_info("real decoder or parser + error, status 0x%x\n", status); */ + } + + if (r == 2) { + pr_info("first vpts = 0x%x\n", READ_VREG(VDTS)); + pts_checkin_offset(PTS_TYPE_AUDIO, 0, READ_VREG(VDTS) * 90); + WRITE_VREG(AV_SCRATCH_B, 0); + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + return IRQ_HANDLED; + } else if (r == 3) { + pr_info("first apts = 0x%x\n", READ_VREG(VDTS)); + pts_checkin_offset(PTS_TYPE_VIDEO, 0, READ_VREG(VDTS) * 90); + WRITE_VREG(AV_SCRATCH_B, 0); + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + return IRQ_HANDLED; + } + + from = READ_VREG(FROM_AMRISC); + if ((hold == 0) && from) { + tr = READ_VREG(VPTS_TR); + pictype = (tr >> 13) & 3; + tr = (tr & 0x1fff) * 96; + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + + vdts = READ_VREG(VDTS); + if (last_tr == -1) /* ignore tr for first time */ + vf->duration = frame_dur; + else { + if (tr > last_tr) + vf->duration = tr - last_tr; + else + vf->duration = (96 << 13) + tr - last_tr; + + if (vf->duration > 10 * frame_dur) { + /* not a reasonable duration, + should not happen */ + vf->duration = frame_dur; + } +#if 0 + else { + if (check_frame_duration == 0) { + frame_dur = vf->duration; + check_frame_duration = 1; + } + } +#endif + } + + last_tr = tr; + buffer_index = from & 0x03; + + if (0 == pictype) { /* I */ + current_vdts = vdts * 90 + 1; + vf->pts = current_vdts; + if (wait_key_frame) + wait_key_frame = 0; + } else { + if (wait_key_frame) { + while (READ_VREG(TO_AMRISC)) + ; + WRITE_VREG(TO_AMRISC, ~(1 << buffer_index)); + WRITE_VREG(FROM_AMRISC, 0); + return IRQ_HANDLED; + } else { + current_vdts += + vf->duration - (vf->duration >> 4); + vf->pts = current_vdts; + } + } + + /* pr_info("pts %d, picture type %d\n", vf->pts, pictype); */ + + info = READ_VREG(RV_PIC_INFO); + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = info >> 16; + vf->height = (info >> 4) & 0xfff; + vf->bufWidth = 1920; + vf->flag = 0; + vf->ratio_control = 0; + set_aspect_ratio(vf, info & 0x0f); + vf->duration_pulldown = 0; +#ifdef NV21 + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + vf->canvas0Addr = vf->canvas1Addr = index2canvas(buffer_index); + vf->orientation = 0; + vf->type_original = vf->type; + + vfbuf_use[buffer_index] = 1; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + frame_count++; + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + WRITE_VREG(FROM_AMRISC, 0); + } + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + return IRQ_HANDLED; +} + +static struct vframe_s *vreal_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vreal_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vreal_vf_put(struct vframe_s *vf, void *op_arg) +{ + kfifo_put(&recycle_q, (const struct vframe_s *)vf); +} + +static int vreal_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vreal_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vreal_local_init(); + vreal_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vreal_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +static int vreal_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + + return 0; +} +#if 0 +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER +static void vreal_ppmgr_reset(void) +{ + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + + vreal_local_init(); + + pr_info("vrealdec: vf_ppmgr_reset\n"); +} +#endif +#endif +static void vreal_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + /* unsigned int status; */ + +#if 0 + enum receviver_start_e state = RECEIVER_INACTIVE; + if (vf_get_receiver(PROVIDER_NAME)) { + state = + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); + if ((state == RECEIVER_STATE_NULL) + || (state == RECEIVER_STATE_NONE)) { + /* receiver has no event_cb + or receiver's event_cb does not process this event */ + state = RECEIVER_INACTIVE; + } + } else + state = RECEIVER_INACTIVE; + + if ((READ_VREG(WAIT_BUFFER) != 0) && + kfifo_is_empty(&display_q) && + kfifo_is_empty(&recycle_q) && (state == RECEIVER_INACTIVE)) { + pr_info("$$$$$$decoder is waiting for buffer\n"); + if (++wait_buffer_counter > 2) { + amvdec_stop(); + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vreal_ppmgr_reset(); +#else + vf_light_unreg_provider(&vreal_vf_prov); + vreal_local_init(); + vf_reg_provider(&vreal_vf_prov); +#endif + vreal_prot_init(); + amvdec_start(); + } + } +#endif + + while (!kfifo_is_empty(&recycle_q) && (READ_VREG(TO_AMRISC) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index >= 0) && (vf->index < VF_BUF_NUM) + && (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(TO_AMRISC, ~(1 << vf->index)); + vf->index = VF_BUF_NUM; + } + + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } + } + + if (frame_dur > 0 && + saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_REAL, + frame_width, frame_height, fps); + } + + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +int vreal_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = vreal_amstream_dec_info.width; + vstatus->height = vreal_amstream_dec_info.height; + if (0 != vreal_amstream_dec_info.rate) + vstatus->fps = 96000 / vreal_amstream_dec_info.rate; + else + vstatus->fps = 96000; + vstatus->error_count = real_err_count; + vstatus->status = + ((READ_VREG(STATUS_AMRISC) << 16) | fatal_flag) | stat; + /* pr_info("vreal_dec_status 0x%x\n", vstatus->status); */ + return 0; +} + +/****************************************/ +static void vreal_canvas_init(void) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + u32 disp_addr = 0xffffffff; + u32 buff_off = 0; + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + /* HD & SD */ + #if 1 + int w = vreal_amstream_dec_info.width; + int h = vreal_amstream_dec_info.height; + int align_w, align_h; + int max, min; + align_w = ALIGN(w, 64); + align_h = ALIGN(h, 64); + if (align_w > align_h) { + max = align_w; + min = align_h; + } else { + canvas_width = 1920; + canvas_height = 1088; + max = align_h; + min = align_w; + } + /* HD & SD */ + if ((max > 1920 || min > 1088) && + ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= + buf_size) { + canvas_width = align_w; + canvas_height = align_h; + decbuf_y_size = ALIGN(align_w * align_h, SZ_64K); + decbuf_uv_size = ALIGN(align_w * align_h/4, SZ_64K); + decbuf_size = ALIGN(align_w * align_h * 3/2, SZ_64K); + } else { /*1080p*/ + if (h > w) { + canvas_width = 1088; + canvas_height = 1920; + } else { + canvas_width = 1920; + canvas_height = 1088; + } + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + #endif + /* canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000;*/ + } + + if (is_vpp_postblend()) { + struct canvas_s cur_canvas; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + } + + for (i = 0; i < 4; i++) { + u32 one_buf_start = buf_start + buff_off; + if (((one_buf_start + 7) >> 3) == disp_addr) { + /*last disp buffer, to next..*/ + buff_off += decbuf_size; + one_buf_start = buf_start + buff_off; + pr_info("one_buf_start %d,=== %x disp_addr %x", + i, one_buf_start, disp_addr); + } + if (buff_off < 0x01000000 && + buff_off + decbuf_size > 0x0f00000){ + /*0x01b00000 is references buffer. + to next 16M;*/ + buff_off = 16 * SZ_1M;/*next 16M*/ + one_buf_start = buf_start + buff_off; + } + if (buff_off + decbuf_size > buf_size) { + pr_err("ERROR::too small buffer for buf%d %d x%d ,size =%d\n", + i, + canvas_width, + canvas_height, + buf_size); + } + pr_info("alloced buffer %d at %x,%d\n", + i, one_buf_start, decbuf_size); + #ifdef NV21 + canvas_config(2 * i + 0, + one_buf_start, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(2 * i + 1, + one_buf_start + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + #else + canvas_config(3 * i + 0, + one_buf_start, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 1, + one_buf_start + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 2, + one_buf_start + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + #endif + buff_off = buff_off + decbuf_size; + } +} + +static void vreal_prot_init(void) +{ +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); +#endif + + vreal_canvas_init(); + + /* index v << 16 | u << 8 | y */ +#ifdef NV21 + WRITE_VREG(AV_SCRATCH_0, 0x010100); + WRITE_VREG(AV_SCRATCH_1, 0x030302); + WRITE_VREG(AV_SCRATCH_2, 0x050504); + WRITE_VREG(AV_SCRATCH_3, 0x070706); +#else + WRITE_VREG(AV_SCRATCH_0, 0x020100); + WRITE_VREG(AV_SCRATCH_1, 0x050403); + WRITE_VREG(AV_SCRATCH_2, 0x080706); + WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); +#endif + + /* notify ucode the buffer offset */ + WRITE_VREG(AV_SCRATCH_F, buf_offset); + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); +#endif + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(FROM_AMRISC, 0); + WRITE_VREG(TO_AMRISC, 0); + WRITE_VREG(STATUS_AMRISC, 0); + + WRITE_VREG(RV_PIC_INFO, 0); + WRITE_VREG(VPTS_TR, 0); + WRITE_VREG(VDTS, 0); + WRITE_VREG(SKIP_B_AMRISC, 0); + + WRITE_VREG(MDEC_WIDTH, (frame_width + 15) & 0xfff0); + WRITE_VREG(MDEC_HEIGHT, (frame_height + 15) & 0xfff0); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + + /* clear wait buffer status */ + WRITE_VREG(WAIT_BUFFER, 0); + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif +} + +static void vreal_local_init(void) +{ + int i; + + /* vreal_ratio = vreal_amstream_dec_info.ratio; */ + vreal_ratio = 0x100; + + frame_prog = 0; + + frame_width = vreal_amstream_dec_info.width; + frame_height = vreal_amstream_dec_info.height; + frame_dur = vreal_amstream_dec_info.rate; + + for (i = 0; i < VF_BUF_NUM; i++) + vfbuf_use[i] = 0; + + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &vfpool[i]; + vfpool[i].index = VF_BUF_NUM; + kfifo_put(&newframe_q, vf); + } + + decoder_state = 1; + hold = 0; + last_tr = -1; + wait_key_frame = 1; + frame_count = 0; + current_vdts = 0; + real_err_count = 0; + + pic_sz_tbl_map = 0; + saved_resolution = 0; + fatal_flag = 0; + wait_buffer_counter = 0; +} + +static void load_block_data(void *dest, unsigned int count) +{ + unsigned short *pdest = (unsigned short *)dest; + unsigned short src_tbl[12]; + unsigned int i; + + src_tbl[0] = RPR_size[vreal_amstream_dec_info.extra + 1]; + memcpy((void *)&src_tbl[1], vreal_amstream_dec_info.param, + 2 << src_tbl[0]); + +#if 0 + for (i = 0; i < 12; i++) + pr_info("src_tbl[%d]: 0x%x\n", i, src_tbl[i]); +#endif + + for (i = 0; i < count / 4; i++) { + pdest[i * 4] = src_tbl[i * 4 + 3]; + pdest[i * 4 + 1] = src_tbl[i * 4 + 2]; + pdest[i * 4 + 2] = src_tbl[i * 4 + 1]; + pdest[i * 4 + 3] = src_tbl[i * 4]; + } + + pic_sz_tbl_map = dma_map_single(amports_get_dma_device(), &pic_sz_tbl, + sizeof(pic_sz_tbl), DMA_TO_DEVICE); + + return; +} + +s32 vreal_init(struct vdec_s *vdec) +{ + int ret = -1,size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + pr_info("vreal_init\n"); + + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + amvdec_enable(); + + vreal_local_init(); + + ret = rmparser_init(vdec); + if (ret) { + amvdec_disable(); + + pr_info("rm parser init failed\n"); + return ret; + } + + if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_8) { + load_block_data((void *)pic_sz_tbl, 12); + + /* TODO: need to load the table into lmem */ + WRITE_VREG(LMEM_DMA_ADR, (unsigned)pic_sz_tbl_map); + WRITE_VREG(LMEM_DMA_COUNT, 10); + WRITE_VREG(LMEM_DMA_CTRL, 0xc178 | (3 << 11)); + while (READ_VREG(LMEM_DMA_CTRL) & 0x8000); + size = get_firmware_data(VIDEO_DEC_REAL_V8, buf); + + pr_info("load VIDEO_DEC_FORMAT_REAL_8\n"); + } else if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_9) { + size = get_firmware_data(VIDEO_DEC_REAL_V9, buf); + + pr_info("load VIDEO_DEC_FORMAT_REAL_9\n"); + } else + pr_info("unsurpported real format\n"); + + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_REAL, NULL, buf) < 0) { + amvdec_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vreal_prot_init(); + + if (vdec_request_irq(VDEC_IRQ_1, vreal_isr, + "vreal-irq", (void *)vreal_dec_id)) { + amvdec_disable(); + + pr_info("vreal irq register error.\n"); + return -ENOENT; + } + + stat |= STAT_ISR_REG; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vreal_vf_prov, PROVIDER_NAME, &vreal_vf_provider, + NULL); + vf_reg_provider(&vreal_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vreal_vf_prov, PROVIDER_NAME, &vreal_vf_provider, + NULL); + vf_reg_provider(&vreal_vf_prov); +#endif + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)vreal_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong)&recycle_timer; + recycle_timer.function = vreal_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + pr_info("vreal init finished\n"); + + return 0; +} + +void vreal_set_fatal_flag(int flag) +{ + if (flag) + fatal_flag = PARSER_FATAL_ERROR; +} + +/*TODO encoder*/ +/* extern void AbortEncodeWithVdec2(int abort); */ + +static int amvdec_real_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + if (pdata == NULL) { + pr_info("amvdec_real memory resource undefined.\n"); + return -EFAULT; + } + + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; + buf_offset = buf_start - RM_DEF_BUFFER_ADDR; + + if (pdata->sys_info) + vreal_amstream_dec_info = *pdata->sys_info; + /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8)&&(HAS_HDEC)) */ + /* if(IS_MESON_M8_CPU){ */ + if (has_hdec()) { + /* disable vdec2 dblk when miracast. */ + int count = 0; + if (get_vdec2_usage() != USAGE_NONE) + /*TODO encoder */ + /* AbortEncodeWithVdec2(1); */ + while ((get_vdec2_usage() != USAGE_NONE) + && (count < 10)) { + msleep(50); + count++; + } + + if (get_vdec2_usage() != USAGE_NONE) { + pr_info("\namvdec_real_probe --- stop vdec2 fail.\n"); + return -EBUSY; + } + } + /* } */ + /* #endif */ + + pdata->dec_status = vreal_dec_status; + + if (vreal_init(pdata) < 0) { + pr_info("amvdec_real init failed.\n"); + /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8)&&(HAS_HDEC) */ + /* if(IS_MESON_M8_CPU) */ + if (has_hdec()) { + /*TODO encoder */ + /* AbortEncodeWithVdec2(0); */ + } + /* #endif */ + return -ENODEV; + } + + return 0; +} + +static int amvdec_real_remove(struct platform_device *pdev) +{ + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)vreal_dec_id); + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vreal_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + if (pic_sz_tbl_map != 0) { + dma_unmap_single(NULL, pic_sz_tbl_map, sizeof(pic_sz_tbl), + DMA_TO_DEVICE); + } + + rmparser_release(); + + vdec_source_changed(VFORMAT_REAL, 0, 0, 0); + + amvdec_disable(); + + /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8)&&(HAS_HDEC) */ + /* if(IS_MESON_M8_CPU) */ + if (has_hdec()) { + /*TODO encoder */ + /* AbortEncodeWithVdec2(0); */ + } + /* #endif */ + pr_info("frame duration %d, frames %d\n", frame_dur, frame_count); + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_real_driver = { + .probe = amvdec_real_probe, + .remove = amvdec_real_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_real_profile = { + .name = "real", + .profile = "rmvb,1080p+" +}; + +static int __init amvdec_real_driver_init_module(void) +{ + pr_debug("amvdec_real module init\n"); + + if (platform_driver_register(&amvdec_real_driver)) { + pr_err("failed to register amvdec_real driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_real_profile); + return 0; +} + +static void __exit amvdec_real_driver_remove_module(void) +{ + pr_debug("amvdec_real module remove.\n"); + + platform_driver_unregister(&amvdec_real_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_real stat\n"); + +module_init(amvdec_real_driver_init_module); +module_exit(amvdec_real_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC REAL Video Decoder Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h new file mode 100644 index 000000000000..8c0d51a35dff --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.h @@ -0,0 +1,26 @@ +/* + * drivers/amlogic/amports/vreal.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VREAL_H +#define VREAL_H + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* TODO: move to register headers */ +#define VPP_VD1_POSTBLEND (1 << 10) +#endif + +#endif /* VREAL_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile new file mode 100644 index 000000000000..b7e6184aa35f --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile @@ -0,0 +1,4 @@ +obj-m += decoder_common.o +decoder_common-objs += utils.o vdec.o vdec_input.o amvdec.o +decoder_common-objs += decoder_mmu_box.o decoder_bmmu_box.o +decoder_common-objs += config_parser.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c new file mode 100644 index 000000000000..a5e14629723b --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c @@ -0,0 +1,998 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/amvdec.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vdec.h" + +#ifdef CONFIG_PM +#include +#endif + +#ifdef CONFIG_WAKELOCK +#include +#endif +#include "../../../stream_input/amports/amports_priv.h" + +/* #include */ +/* #include */ +#include +#include "amvdec.h" +#include +#include "../../../common/firmware/firmware.h" + +#define MC_SIZE (4096 * 16) + +#ifdef CONFIG_WAKELOCK +static struct wake_lock amvdec_lock; +struct timer_list amvdevtimer; +#define WAKE_CHECK_INTERVAL (100*HZ/100) +#endif +#define AMVDEC_USE_STATIC_MEMORY +static void *mc_addr; +static dma_addr_t mc_addr_map; + +#ifdef CONFIG_WAKELOCK +static int video_running; +static int video_stated_changed = 1; +#endif + +static void amvdec_pg_enable(bool enable) +{ + ulong timeout; + + if (enable) { + AMVDEC_CLK_GATE_ON(MDEC_CLK_PIC_DC); + AMVDEC_CLK_GATE_ON(MDEC_CLK_DBLK); + AMVDEC_CLK_GATE_ON(MC_CLK); + AMVDEC_CLK_GATE_ON(IQIDCT_CLK); + /* AMVDEC_CLK_GATE_ON(VLD_CLK); */ + AMVDEC_CLK_GATE_ON(AMRISC); + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + WRITE_VREG(GCLK_EN, 0x3ff); + /* #endif */ + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); + } else { + + AMVDEC_CLK_GATE_OFF(AMRISC); + timeout = jiffies + HZ / 10; + + while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) { + if (time_after(jiffies, timeout)) { + WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 1, 0, 1); + WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 0, 0, 1); + READ_VREG(MDEC_PIC_DC_STATUS); + READ_VREG(MDEC_PIC_DC_STATUS); + READ_VREG(MDEC_PIC_DC_STATUS); + break; + } + } + + AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC); + timeout = jiffies + HZ / 10; + + while (READ_VREG(DBLK_STATUS) & 1) { + if (time_after(jiffies, timeout)) { + WRITE_VREG(DBLK_CTRL, 3); + WRITE_VREG(DBLK_CTRL, 0); + READ_VREG(DBLK_STATUS); + READ_VREG(DBLK_STATUS); + READ_VREG(DBLK_STATUS); + break; + } + } + AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK); + timeout = jiffies + HZ / 10; + + while (READ_VREG(MC_STATUS0) & 1) { + if (time_after(jiffies, timeout)) { + SET_VREG_MASK(MC_CTRL1, 0x9); + CLEAR_VREG_MASK(MC_CTRL1, 0x9); + READ_VREG(MC_STATUS0); + READ_VREG(MC_STATUS0); + READ_VREG(MC_STATUS0); + break; + } + } + AMVDEC_CLK_GATE_OFF(MC_CLK); + timeout = jiffies + HZ / 10; + while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + AMVDEC_CLK_GATE_OFF(IQIDCT_CLK); + /* AMVDEC_CLK_GATE_OFF(VLD_CLK); */ + } +} + +static void amvdec2_pg_enable(bool enable) +{ + if (has_vdec2()) { + ulong timeout; + + if (!vdec_on(VDEC_2)) + return; + if (enable) { + /* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */ + } else { + timeout = jiffies + HZ / 10; + + while (READ_VREG(VDEC2_MDEC_PIC_DC_STATUS) != 0) { + if (time_after(jiffies, timeout)) { + WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL, + 1, 0, 1); + WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL, + 0, 0, 1); + READ_VREG(VDEC2_MDEC_PIC_DC_STATUS); + READ_VREG(VDEC2_MDEC_PIC_DC_STATUS); + READ_VREG(VDEC2_MDEC_PIC_DC_STATUS); + break; + } + } + + timeout = jiffies + HZ / 10; + + while (READ_VREG(VDEC2_DBLK_STATUS) & 1) { + if (time_after(jiffies, timeout)) { + WRITE_VREG(VDEC2_DBLK_CTRL, 3); + WRITE_VREG(VDEC2_DBLK_CTRL, 0); + READ_VREG(VDEC2_DBLK_STATUS); + READ_VREG(VDEC2_DBLK_STATUS); + READ_VREG(VDEC2_DBLK_STATUS); + break; + } + } + + timeout = jiffies + HZ / 10; + + while (READ_VREG(VDEC2_DCAC_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + } + } +} + +static void amhevc_pg_enable(bool enable) +{ + if (has_hevc_vdec()) { + ulong timeout; + + if (!vdec_on(VDEC_HEVC)) + return; + if (enable) { + /* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */ + } else { + timeout = jiffies + HZ / 10; + + while (READ_VREG(HEVC_MDEC_PIC_DC_STATUS) != 0) { + if (time_after(jiffies, timeout)) { + WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL, + 1, 0, 1); + WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL, + 0, 0, 1); + READ_VREG(HEVC_MDEC_PIC_DC_STATUS); + READ_VREG(HEVC_MDEC_PIC_DC_STATUS); + READ_VREG(HEVC_MDEC_PIC_DC_STATUS); + break; + } + } + + timeout = jiffies + HZ / 10; + + while (READ_VREG(HEVC_DBLK_STATUS) & 1) { + if (time_after(jiffies, timeout)) { + WRITE_VREG(HEVC_DBLK_CTRL, 3); + WRITE_VREG(HEVC_DBLK_CTRL, 0); + READ_VREG(HEVC_DBLK_STATUS); + READ_VREG(HEVC_DBLK_STATUS); + READ_VREG(HEVC_DBLK_STATUS); + break; + } + } + + timeout = jiffies + HZ / 10; + + while (READ_VREG(HEVC_DCAC_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + } + } +} + +#ifdef CONFIG_WAKELOCK +int amvdec_wake_lock(void) +{ + wake_lock(&amvdec_lock); + return 0; +} + +int amvdec_wake_unlock(void) +{ + wake_unlock(&amvdec_lock); + return 0; +} +#else +#define amvdec_wake_lock() +#define amvdec_wake_unlock() +#endif + +static s32 am_vdec_loadmc_ex(struct vdec_s *vdec, + const char *name, s32(*load)(const u32 *)) +{ + int err; + + if (!vdec->mc_loaded) { + int loaded; + loaded = get_decoder_firmware_data(vdec->format, + name, (u8 *)(vdec->mc), (4096 * 4 * 4)); + if (loaded <= 0) + return -1; + + vdec->mc_loaded = true; + } + + err = (*load)(vdec->mc); + if (err < 0) { + pr_err("loading firmware %s to vdec ram failed!\n", name); + return err; + } + pr_debug("loading firmware %s to vdec ram ok!\n", name); + return err; +} + +static s32 am_vdec_loadmc_buf_ex(struct vdec_s *vdec, + char *buf, int size, s32(*load)(const u32 *)) +{ + int err; + + if (!vdec->mc_loaded) { + memcpy((u8 *)(vdec->mc), buf, size); + vdec->mc_loaded = true; + } + + err = (*load)(vdec->mc); + if (err < 0) { + pr_err("loading firmware to vdec ram failed!\n"); + return err; + } + pr_debug("loading firmware to vdec ram ok!\n"); + return err; +} + +static s32 am_loadmc_ex(enum vformat_e type, + const char *name, char *def, s32(*load)(const u32 *)) +{ + char *mc_addr = vmalloc(4096 * 16); + char *pmc_addr = def; + int err; + + if (!def && mc_addr) { + int loaded; + + loaded = get_decoder_firmware_data(type, + name, mc_addr, (4096 * 16)); + if (loaded > 0) + pmc_addr = mc_addr; + } + if (!pmc_addr) { + vfree(mc_addr); + return -1; + } + err = (*load)((u32 *) pmc_addr); + if (err < 0) { + pr_err("loading firmware %s to vdec ram failed!\n", name); + return err; + } + vfree(mc_addr); + pr_debug("loading firmware %s to vdec ram ok!\n", name); + return err; +} + +static s32 amvdec_loadmc(const u32 *p) +{ + ulong timeout; + s32 ret = 0; + +#ifdef AMVDEC_USE_STATIC_MEMORY + if (mc_addr == NULL) { +#else + { +#endif + mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); + } + + if (!mc_addr) + return -ENOMEM; + + memcpy(mc_addr, p, MC_SIZE); + + mc_addr_map = dma_map_single(get_vdec_device(), + mc_addr, MC_SIZE, DMA_TO_DEVICE); + + WRITE_VREG(MPSR, 0); + WRITE_VREG(CPSR, 0); + + /* Read CBUS register for timing */ + timeout = READ_VREG(MPSR); + timeout = READ_VREG(MPSR); + + timeout = jiffies + HZ; + + WRITE_VREG(IMEM_DMA_ADR, mc_addr_map); + WRITE_VREG(IMEM_DMA_COUNT, 0x1000); + WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16))); + + while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) { + if (time_before(jiffies, timeout)) + schedule(); + else { + pr_err("vdec load mc error\n"); + ret = -EBUSY; + break; + } + } + + dma_unmap_single(get_vdec_device(), + mc_addr_map, MC_SIZE, DMA_TO_DEVICE); + +#ifndef AMVDEC_USE_STATIC_MEMORY + kfree(mc_addr); + mc_addr = NULL; +#endif + + return ret; +} + +s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def) +{ + return am_loadmc_ex(type, name, def, &amvdec_loadmc); +} +EXPORT_SYMBOL(amvdec_loadmc_ex); +s32 amvdec_vdec_loadmc_ex(struct vdec_s *vdec, const char *name) +{ + return am_vdec_loadmc_ex(vdec, name, &amvdec_loadmc); +} +EXPORT_SYMBOL(amvdec_vdec_loadmc_ex); + +s32 amvdec_vdec_loadmc_buf_ex(struct vdec_s *vdec, char *buf, int size) +{ + return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc); +} +EXPORT_SYMBOL(amvdec_vdec_loadmc_buf_ex); + +static s32 amvdec2_loadmc(const u32 *p) +{ + if (has_vdec2()) { + ulong timeout; + s32 ret = 0; + +#ifdef AMVDEC_USE_STATIC_MEMORY + if (mc_addr == NULL) { +#else + { +#endif + mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); + } + + if (!mc_addr) + return -ENOMEM; + + memcpy(mc_addr, p, MC_SIZE); + + mc_addr_map = dma_map_single(get_vdec_device(), + mc_addr, MC_SIZE, DMA_TO_DEVICE); + + WRITE_VREG(VDEC2_MPSR, 0); + WRITE_VREG(VDEC2_CPSR, 0); + + /* Read CBUS register for timing */ + timeout = READ_VREG(VDEC2_MPSR); + timeout = READ_VREG(VDEC2_MPSR); + + timeout = jiffies + HZ; + + WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map); + WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000); + WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); + + while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) { + if (time_before(jiffies, timeout)) + schedule(); + else { + pr_err("vdec2 load mc error\n"); + ret = -EBUSY; + break; + } + } + + dma_unmap_single(get_vdec_device(), + mc_addr_map, MC_SIZE, DMA_TO_DEVICE); + +#ifndef AMVDEC_USE_STATIC_MEMORY + kfree(mc_addr); + mc_addr = NULL; +#endif + + return ret; + } else + return 0; +} + +s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def) +{ + if (has_vdec2()) + return am_loadmc_ex(type, name, def, &amvdec2_loadmc); + else + return 0; +} +EXPORT_SYMBOL(amvdec2_loadmc_ex); + +s32 amhcodec_loadmc(const u32 *p) +{ +#ifdef AMVDEC_USE_STATIC_MEMORY + if (mc_addr == NULL) { +#else + { +#endif + mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); + } + + if (!mc_addr) + return -ENOMEM; + + memcpy(mc_addr, p, MC_SIZE); + + mc_addr_map = dma_map_single(get_vdec_device(), + mc_addr, MC_SIZE, DMA_TO_DEVICE); + + WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map); + WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100); + WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); + + while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) + udelay(1000); + + dma_unmap_single(get_vdec_device(), + mc_addr_map, MC_SIZE, DMA_TO_DEVICE); + +#ifndef AMVDEC_USE_STATIC_MEMORY + kfree(mc_addr); +#endif + + return 0; +} +EXPORT_SYMBOL(amhcodec_loadmc); + +s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def) +{ + return am_loadmc_ex(type, name, def, &amhcodec_loadmc); +} +EXPORT_SYMBOL(amhcodec_loadmc_ex); + +static s32 amhevc_loadmc(const u32 *p) +{ + ulong timeout; + s32 ret = 0; + + if (has_hevc_vdec()) { +#ifdef AMVDEC_USE_STATIC_MEMORY + if (mc_addr == NULL) { +#else + { +#endif + mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); + } + + if (!mc_addr) + return -ENOMEM; + + memcpy(mc_addr, p, MC_SIZE); + + mc_addr_map = + dma_map_single(get_vdec_device(), + mc_addr, MC_SIZE, DMA_TO_DEVICE); + + WRITE_VREG(HEVC_MPSR, 0); + WRITE_VREG(HEVC_CPSR, 0); + + /* Read CBUS register for timing */ + timeout = READ_VREG(HEVC_MPSR); + timeout = READ_VREG(HEVC_MPSR); + + timeout = jiffies + HZ; + + WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map); + WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000); + WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); + + while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) { + if (time_before(jiffies, timeout)) + schedule(); + else { + pr_err("vdec2 load mc error\n"); + ret = -EBUSY; + break; + } + } + + dma_unmap_single(get_vdec_device(), + mc_addr_map, MC_SIZE, DMA_TO_DEVICE); + +#ifndef AMVDEC_USE_STATIC_MEMORY + kfree(mc_addr); + mc_addr = NULL; +#endif + } + + return ret; +} + +s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def) +{ + if (has_hevc_vdec()) + return am_loadmc_ex(type, name, def, &amhevc_loadmc); + else + return 0; +} +EXPORT_SYMBOL(amhevc_loadmc_ex); +s32 amhevc_vdec_loadmc_ex(struct vdec_s *vdec, const char *name) +{ + if (has_hevc_vdec()) + return am_vdec_loadmc_ex(vdec, name, &amhevc_loadmc); + else + return 0; +} +EXPORT_SYMBOL(amhevc_vdec_loadmc_ex); + +void amvdec_start(void) +{ +#ifdef CONFIG_WAKELOCK + amvdec_wake_lock(); +#endif + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + } else { + /* #else */ + /* additional cbus dummy register reading for timing control */ + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + + WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU); + + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + } + /* #endif */ + + WRITE_VREG(MPSR, 0x0001); +} +EXPORT_SYMBOL(amvdec_start); + +void amvdec2_start(void) +{ + if (has_vdec2()) { +#ifdef CONFIG_WAKELOCK + amvdec_wake_lock(); +#endif + + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + + WRITE_VREG(DOS_SW_RESET2, (1 << 12) | (1 << 11)); + WRITE_VREG(DOS_SW_RESET2, 0); + + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + + WRITE_VREG(VDEC2_MPSR, 0x0001); + } +} +EXPORT_SYMBOL(amvdec2_start); + +void amhcodec_start(void) +{ + WRITE_VREG(HCODEC_MPSR, 0x0001); +} +EXPORT_SYMBOL(amhcodec_start); + +void amhevc_start(void) +{ + + if (has_hevc_vdec()) { +#ifdef CONFIG_WAKELOCK + amvdec_wake_lock(); +#endif + + READ_VREG(DOS_SW_RESET3); + READ_VREG(DOS_SW_RESET3); + READ_VREG(DOS_SW_RESET3); + + WRITE_VREG(DOS_SW_RESET3, (1 << 12) | (1 << 11)); + WRITE_VREG(DOS_SW_RESET3, 0); + + READ_VREG(DOS_SW_RESET3); + READ_VREG(DOS_SW_RESET3); + READ_VREG(DOS_SW_RESET3); + + WRITE_VREG(HEVC_MPSR, 0x0001); + } +} +EXPORT_SYMBOL(amhevc_start); + +void amvdec_stop(void) +{ + ulong timeout = jiffies + HZ; + + WRITE_VREG(MPSR, 0); + WRITE_VREG(CPSR, 0); + + while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + READ_VREG(DOS_SW_RESET0); + } else { + /* #else */ + WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU); + + /* additional cbus dummy register reading for timing control */ + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + } + /* #endif */ + +#ifdef CONFIG_WAKELOCK + amvdec_wake_unlock(); +#endif +} +EXPORT_SYMBOL(amvdec_stop); + +void amvdec2_stop(void) +{ + if (has_vdec2()) { + ulong timeout = jiffies + HZ; + + WRITE_VREG(VDEC2_MPSR, 0); + WRITE_VREG(VDEC2_CPSR, 0); + + while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + READ_VREG(DOS_SW_RESET2); + +#ifdef CONFIG_WAKELOCK + amvdec_wake_unlock(); +#endif + } +} +EXPORT_SYMBOL(amvdec2_stop); + +void amhcodec_stop(void) +{ + WRITE_VREG(HCODEC_MPSR, 0); +} +EXPORT_SYMBOL(amhcodec_stop); + +void amhevc_stop(void) +{ + if (has_hevc_vdec()) { + ulong timeout = jiffies + HZ; + + WRITE_VREG(HEVC_MPSR, 0); + WRITE_VREG(HEVC_CPSR, 0); + + while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + + READ_VREG(DOS_SW_RESET3); + READ_VREG(DOS_SW_RESET3); + READ_VREG(DOS_SW_RESET3); + +#ifdef CONFIG_WAKELOCK + amvdec_wake_unlock(); +#endif + } +} +EXPORT_SYMBOL(amhevc_stop); + +void amvdec_enable(void) +{ + amvdec_pg_enable(true); +} +EXPORT_SYMBOL(amvdec_enable); + +void amvdec_disable(void) +{ + amvdec_pg_enable(false); +} +EXPORT_SYMBOL(amvdec_disable); + +void amvdec2_enable(void) +{ + if (has_vdec2()) + amvdec2_pg_enable(true); +} +EXPORT_SYMBOL(amvdec2_enable); + +void amvdec2_disable(void) +{ + if (has_vdec2()) + amvdec2_pg_enable(false); +} +EXPORT_SYMBOL(amvdec2_disable); + +void amhevc_enable(void) +{ + if (has_hevc_vdec()) + amhevc_pg_enable(true); +} +EXPORT_SYMBOL(amhevc_enable); + +void amhevc_disable(void) +{ + if (has_hevc_vdec()) + amhevc_pg_enable(false); +} +EXPORT_SYMBOL(amhevc_disable); + +#ifdef CONFIG_PM +int amvdec_suspend(struct platform_device *dev, pm_message_t event) +{ + amvdec_pg_enable(false); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ + if (has_vdec2()) + amvdec2_pg_enable(false); + /* #endif */ + + if (has_hevc_vdec()) + amhevc_pg_enable(false); + + return 0; +} +EXPORT_SYMBOL(amvdec_suspend); + +int amvdec_resume(struct platform_device *dev) +{ + amvdec_pg_enable(true); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ + if (has_vdec2()) + amvdec2_pg_enable(true); + /* #endif */ + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (has_hevc_vdec()) + amhevc_pg_enable(true); + /* #endif */ + + return 0; +} +EXPORT_SYMBOL(amvdec_resume); + +int amhevc_suspend(struct platform_device *dev, pm_message_t event) +{ + if (has_hevc_vdec()) + amhevc_pg_enable(false); + return 0; +} +EXPORT_SYMBOL(amhevc_suspend); + +int amhevc_resume(struct platform_device *dev) +{ + if (has_hevc_vdec()) + amhevc_pg_enable(true); + return 0; +} +EXPORT_SYMBOL(amhevc_resume); + + +#endif + +#ifdef CONFIG_WAKELOCK + +static int vdec_is_paused(void) +{ + static unsigned long old_wp = -1, old_rp = -1, old_level = -1; + unsigned long wp, rp, level; + static int paused_time; + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (has_hevc_vdec()) { + if ((vdec_on(VDEC_HEVC)) + && (READ_VREG(HEVC_STREAM_CONTROL) & 1)) { + wp = READ_VREG(HEVC_STREAM_WR_PTR); + rp = READ_VREG(HEVC_STREAM_RD_PTR); + level = READ_VREG(HEVC_STREAM_LEVEL); + } else { + wp = READ_VREG(VLD_MEM_VIFIFO_WP); + rp = READ_VREG(VLD_MEM_VIFIFO_RP); + level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + } + } else + /* #endif */ + { + wp = READ_VREG(VLD_MEM_VIFIFO_WP); + rp = READ_VREG(VLD_MEM_VIFIFO_RP); + level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + } + /*have data,but output buffer is full */ + if ((rp == old_rp && level > 1024) || + (rp == old_rp && wp == old_wp && level == level)) { + /*no write && not read */ + paused_time++; + } else { + paused_time = 0; + } + old_wp = wp; old_rp = rp; old_level = level; + if (paused_time > 10) + return 1; + return 0; +} + +int amvdev_pause(void) +{ + video_running = 0; + video_stated_changed = 1; + return 0; +} +EXPORT_SYMBOL(amvdev_pause); + +int amvdev_resume(void) +{ + video_running = 1; + video_stated_changed = 1; + return 0; +} +EXPORT_SYMBOL(amvdev_resume); + +static void vdec_paused_check_timer(unsigned long arg) +{ + if (video_stated_changed) { + if (!video_running) { + if (vdec_is_paused()) { + pr_info("vdec paused and release wakelock now\n"); + amvdec_wake_unlock(); + video_stated_changed = 0; + } + } else { + amvdec_wake_lock(); + video_stated_changed = 0; + } + } + mod_timer(&amvdevtimer, jiffies + WAKE_CHECK_INTERVAL); +} +#else +int amvdev_pause(void) +{ + return 0; +} + +int amvdev_resume(void) +{ + return 0; +} +#endif + +int amvdec_init(void) +{ +#ifdef CONFIG_WAKELOCK + /* + *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock"); + *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8 + */ + wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND, + "amvdec_lock"); + + init_timer(&amvdevtimer); + + amvdevtimer.data = (ulong) &amvdevtimer; + amvdevtimer.function = vdec_paused_check_timer; +#endif + return 0; +} +EXPORT_SYMBOL(amvdec_init); + +void amvdec_exit(void) +{ +#ifdef CONFIG_WAKELOCK + del_timer_sync(&amvdevtimer); +#endif +} +EXPORT_SYMBOL(amvdec_exit); + +#if 0 +int __init amvdec_init(void) +{ +#ifdef CONFIG_WAKELOCK + /* + *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock"); + *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8 + */ + wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND, + "amvdec_lock"); + + init_timer(&amvdevtimer); + + amvdevtimer.data = (ulong) &amvdevtimer; + amvdevtimer.function = vdec_paused_check_timer; +#endif + return 0; +} + +static void __exit amvdec_exit(void) +{ +#ifdef CONFIG_WAKELOCK + del_timer_sync(&amvdevtimer); +#endif +} + +module_init(amvdec_init); +module_exit(amvdec_exit); +#endif + +MODULE_DESCRIPTION("Amlogic Video Decoder Utility Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h new file mode 100644 index 000000000000..c6f11d7f6be9 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h @@ -0,0 +1,86 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/amvdec.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef AMVDEC_H +#define AMVDEC_H +#include +#include +#include "vdec.h" + +#define UCODE_ALIGN 8 +#define UCODE_ALIGN_MASK 7UL + +struct amvdec_dec_reg_s { + unsigned long mem_start; + unsigned long mem_end; + struct device *cma_dev; + struct dec_sysinfo *dec_sysinfo; +}; /*amvdec_dec_reg_t */ + +extern void amvdec_start(void); +extern void amvdec_stop(void); +extern void amvdec_enable(void); +extern void amvdec_disable(void); +s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def); +s32 amvdec_vdec_loadmc_ex(struct vdec_s *vdec, const char *name); + +extern void amvdec2_start(void); +extern void amvdec2_stop(void); +extern void amvdec2_enable(void); +extern void amvdec2_disable(void); +s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def); + +extern void amhevc_start(void); +extern void amhevc_stop(void); +extern void amhevc_enable(void); +extern void amhevc_disable(void); +s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def); +s32 amhevc_vdec_loadmc_ex(struct vdec_s *vdec, const char *name); +s32 amvdec_vdec_loadmc_buf_ex(struct vdec_s *vdec, char *buf, int size); + +extern void amhcodec_start(void); +extern void amhcodec_stop(void); +s32 amhcodec_loadmc(const u32 *p); +s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def); + +extern int amvdev_pause(void); +extern int amvdev_resume(void); + +#ifdef CONFIG_PM +extern int amvdec_suspend(struct platform_device *dev, pm_message_t event); +extern int amvdec_resume(struct platform_device *dec); +extern int amhevc_suspend(struct platform_device *dev, pm_message_t event); +extern int amhevc_resume(struct platform_device *dec); + +#endif + +int amvdec_init(void); +void amvdec_exit(void); + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define AMVDEC_CLK_GATE_ON(a) +#define AMVDEC_CLK_GATE_OFF(a) +#else +#define AMVDEC_CLK_GATE_ON(a) CLK_GATE_ON(a) +#define AMVDEC_CLK_GATE_OFF(a) CLK_GATE_OFF(a) +#endif + +/* TODO: move to register headers */ +#define RESET_VCPU (1<<7) +#define RESET_CCPU (1<<8) + +#endif /* AMVDEC_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c new file mode 100644 index 000000000000..b9c64f7dd1c3 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.c @@ -0,0 +1,62 @@ +/* + * drivers/amlogic/amports/config_parser.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ +#include +#include +#include +#include + +#include "config_parser.h" +/* +sample config: +configs: width:1920;height:1080; +need:width +ok: return 0; +*val = value; +*/ +int get_config_int(const char *configs, const char *need, int *val) +{ + const char *str; + int ret; + int lval = 0; + *val = 0; + + if (!configs || !need) + return -1; + str = strstr(configs, need); + if (str != NULL) { + if (str > configs && str[-1] != ';') { + /* + if not the first config val. + make sure before is ';' + to recognize: + ;crop_width:100 + ;width:100 + */ + return -2; + } + str += strlen(need); + if (str[0] != ':' || str[1] == '\0') + return -3; + ret = sscanf(str, ":%d", &lval); + if (ret == 1) { + *val = lval; + return 0; + } + } + + return -4; +} diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h new file mode 100644 index 000000000000..e10210a82fc1 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/config_parser.h @@ -0,0 +1,21 @@ +/* + * drivers/amlogic/amports/config_parser.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ +#ifndef CONFIG_PARSER_HHH_ +#define CONFIG_PARSER_HHH_ +int get_config_int(const char *configs, const char *need, int *val); + +#endif/*CONFIG_PARSER_HHH_*/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c new file mode 100644 index 000000000000..7a858d5872d5 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c @@ -0,0 +1,425 @@ +/* + * drivers/amlogic/amports/decoder/decoder_bmmu_box.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "decoder_bmmu_box.h" +#include + +struct decoder_bmmu_box { + int max_mm_num; + const char *name; + int channel_id; + struct mutex mutex; + struct list_head list; + int total_size; + int change_size_on_need_smaller; + int align2n; /*can overwite on idx alloc */ + int mem_flags; /*can overwite on idx alloc */ + struct codec_mm_s *mm_list[1]; +}; + +struct decoder_bmmu_box_mgr { + int num; + struct mutex mutex; + struct list_head box_list; +}; +static struct decoder_bmmu_box_mgr global_blk_mgr; +static struct decoder_bmmu_box_mgr *get_decoder_bmmu_box_mgr(void) +{ + return &global_blk_mgr; +} + +static int decoder_bmmu_box_mgr_add_box(struct decoder_bmmu_box *box) +{ + struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); + mutex_lock(&mgr->mutex); + list_add_tail(&box->list, &mgr->box_list); + mutex_unlock(&mgr->mutex); + return 0; +} + +static int decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box *box) +{ + struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); + mutex_lock(&mgr->mutex); + list_del(&box->list); + mutex_unlock(&mgr->mutex); + return 0; +} + +void *decoder_bmmu_box_alloc_box(const char *name, + int channel_id, int max_num, + int aligned, int mem_flags) +/*min_size_M:wait alloc this size*/ +{ + struct decoder_bmmu_box *box; + int size; + size = sizeof(struct decoder_bmmu_box) + sizeof(struct codec_mm_s *) * + max_num; + box = kmalloc(size, GFP_KERNEL); + if (!box) { + pr_err("can't alloc decoder buffers box!!!\n"); + return NULL; + } + memset(box, 0, size); + box->max_mm_num = max_num; + box->name = name; + box->channel_id = channel_id; + box->align2n = aligned; + box->mem_flags = mem_flags; + mutex_init(&box->mutex); + INIT_LIST_HEAD(&box->list); + decoder_bmmu_box_mgr_add_box(box); + return (void *)box; +} +EXPORT_SYMBOL(decoder_bmmu_box_alloc_box); + +int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n, + int mem_flags) +/*align& flags if -1 user box default.*/ +{ + struct decoder_bmmu_box *box = handle; + struct codec_mm_s *mm; + int align = aligned_2n; + int memflags = mem_flags; + + if (!box || idx < 0 || idx >= box->max_mm_num) { + pr_err("can't alloc mmu box(%p),idx:%d\n", + box, idx); + return -1; + } + if (align == -1) + align = box->align2n; + if (memflags == -1) + memflags = box->mem_flags; + + mutex_lock(&box->mutex); + mm = box->mm_list[idx]; + if (mm) { + int invalid = 0; + if (mm->page_count * PAGE_SIZE < size) { + /*size is small. */ + invalid = 1; + } else if (box->change_size_on_need_smaller && + (mm->buffer_size > (size << 1))) { + /*size is too large. */ + invalid = 2; + } else if (mm->phy_addr & ((1 << align) - 1)) { + /*addr is not align */ + invalid = 4; + } + if (invalid) { + box->total_size -= mm->buffer_size; + codec_mm_release(mm, box->name); + box->mm_list[idx] = NULL; + mm = NULL; + } + } + if (!mm) { + mm = codec_mm_alloc(box->name, size, align, memflags); + if (mm) { + box->mm_list[idx] = mm; + box->total_size += mm->buffer_size; + } + } + mutex_unlock(&box->mutex); + return mm ? 0 : -ENOMEM; +} + +int decoder_bmmu_box_free_idx(void *handle, int idx) +{ + struct decoder_bmmu_box *box = handle; + struct codec_mm_s *mm; + if (!box || idx < 0 || idx >= box->max_mm_num) { + pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", + box, idx, 0, + box->max_mm_num - 1); + return -1; + } + mutex_lock(&box->mutex); + mm = box->mm_list[idx]; + if (mm) { + box->total_size -= mm->buffer_size; + codec_mm_release(mm, box->name); + box->mm_list[idx] = NULL; + mm = NULL; + } + mutex_unlock(&box->mutex); + return 0; +} +EXPORT_SYMBOL(decoder_bmmu_box_free_idx); + +int decoder_bmmu_box_free(void *handle) +{ + struct decoder_bmmu_box *box = handle; + struct codec_mm_s *mm; + int i; + if (!box) { + pr_err("can't free box of NULL box!\n"); + return -1; + } + mutex_lock(&box->mutex); + for (i = 0; i < box->max_mm_num; i++) { + mm = box->mm_list[i]; + if (mm) { + codec_mm_release(mm, box->name); + box->mm_list[i] = NULL; + } + } + mutex_unlock(&box->mutex); + decoder_bmmu_box_mgr_del_box(box); + kfree(box); + return 0; +} +EXPORT_SYMBOL(decoder_bmmu_box_free); + +void *decoder_bmmu_box_get_mem_handle(void *box_handle, int idx) +{ + struct decoder_bmmu_box *box = box_handle; + if (!box || idx < 0 || idx >= box->max_mm_num) + return NULL; + return box->mm_list[idx]; +} +EXPORT_SYMBOL(decoder_bmmu_box_get_mem_handle); + +int decoder_bmmu_box_get_mem_size(void *box_handle, int idx) +{ + struct decoder_bmmu_box *box = box_handle; + int size = 0; + if (!box || idx < 0 || idx >= box->max_mm_num) + return 0; + mutex_lock(&box->mutex); + if (box->mm_list[idx] != NULL) + size = box->mm_list[idx]->buffer_size; + mutex_unlock(&box->mutex); + return size; +} + + +unsigned long decoder_bmmu_box_get_phy_addr(void *box_handle, int idx) +{ + struct decoder_bmmu_box *box = box_handle; + struct codec_mm_s *mm; + if (!box || idx < 0 || idx >= box->max_mm_num) + return 0; + mm = box->mm_list[idx]; + if (!mm) + return 0; + return mm->phy_addr; +} +EXPORT_SYMBOL(decoder_bmmu_box_get_phy_addr); + +void *decoder_bmmu_box_get_virt_addr(void *box_handle, int idx) +{ + struct decoder_bmmu_box *box = box_handle; + struct codec_mm_s *mm; + if (!box || idx < 0 || idx >= box->max_mm_num) + return NULL; + mm = box->mm_list[idx]; + if (!mm) + return 0; + return codec_mm_phys_to_virt(mm->phy_addr); +} + +/*flags: &0x1 for wait,*/ +int decoder_bmmu_box_check_and_wait_size(int size, int flags) +{ + if ((flags & BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER) && + codec_mm_get_free_size() < size) { + pr_err("CMA force free keep,for size = %d\n", size); + /*need free others? + */ + try_free_keep_video(1); + } + + return codec_mm_enough_for_size(size, + flags & BMMU_ALLOC_FLAGS_WAIT); +} + +int decoder_bmmu_box_alloc_idx_wait( + void *handle, int idx, + int size, int aligned_2n, + int mem_flags, + int wait_flags) +{ + int have_space; + int ret = -1; + if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) + return 0;/*have alloced memery before.*/ + have_space = decoder_bmmu_box_check_and_wait_size( + size, + wait_flags); + if (have_space) { + ret = decoder_bmmu_box_alloc_idx(handle, + idx, size, aligned_2n, mem_flags); + } else { + ret = -ENOMEM; + } + return ret; +} +EXPORT_SYMBOL(decoder_bmmu_box_alloc_idx_wait); + +static int decoder_bmmu_box_dump(struct decoder_bmmu_box *box, void *buf, + int size) +{ + char *pbuf = buf; + char sbuf[512]; + int tsize = 0; + int s; + int i; + if (!pbuf) + pbuf = sbuf; + +#define BUFPRINT(args...) \ + do {\ + s = sprintf(pbuf, args);\ + tsize += s;\ + pbuf += s; \ + } while (0) + + for (i = 0; i < box->max_mm_num; i++) { + struct codec_mm_s *mm = box->mm_list[i]; + if (buf && (size - tsize) < 128) + break; + if (mm) { + BUFPRINT("code mem[%d]:%p, addr=%p, size=%d,from=%d\n", + i, + (void *)mm, + (void *)mm->phy_addr, + mm->buffer_size, + mm->from_flags); + } + } +#undef BUFPRINT + if (!buf) + pr_info("%s", sbuf); + + return tsize; +} + +static int decoder_bmmu_box_dump_all(void *buf, int size) +{ + struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); + char *pbuf = buf; + char sbuf[512]; + int tsize = 0; + int s; + int i; + struct list_head *head, *list; + if (!pbuf) + pbuf = sbuf; + +#define BUFPRINT(args...) \ + do {\ + s = sprintf(pbuf, args);\ + tsize += s;\ + pbuf += s; \ + } while (0) + + mutex_lock(&mgr->mutex); + head = &mgr->box_list; + list = head->next; + i = 0; + while (list != head) { + struct decoder_bmmu_box *box; + box = list_entry(list, struct decoder_bmmu_box, list); + BUFPRINT("box[%d]: %s, player_id:%d, max_num:%d, size:%d\n", + i, box->name, + box->channel_id, + box->max_mm_num, + box->total_size); + if (buf) { + tsize += decoder_bmmu_box_dump(box, pbuf, size - tsize); + if (tsize > 0) + pbuf += tsize; + } else { + pr_info("%s", sbuf); + pbuf = sbuf; + tsize += decoder_bmmu_box_dump(box, NULL, 0); + } + list = list->next; + i++; + } + mutex_unlock(&mgr->mutex); + +#undef BUFPRINT + if (!buf) + pr_info("%s", sbuf); + return tsize; +} + +static ssize_t box_dump_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + ssize_t ret = 0; + ret = decoder_bmmu_box_dump_all(buf, PAGE_SIZE); + return ret; +} + +static struct class_attribute decoder_bmmu_box_class_attrs[] = { + __ATTR_RO(box_dump), + __ATTR_NULL +}; + +static struct class decoder_bmmu_box_class = { + .name = "decoder_bmmu_box", + .class_attrs = decoder_bmmu_box_class_attrs, + }; + +int decoder_bmmu_box_init(void) +{ + int r; + memset(&global_blk_mgr, 0, sizeof(global_blk_mgr)); + INIT_LIST_HEAD(&global_blk_mgr.box_list); + mutex_init(&global_blk_mgr.mutex); + r = class_register(&decoder_bmmu_box_class); + return r; +} +EXPORT_SYMBOL(decoder_bmmu_box_init); + +void decoder_bmmu_box_exit(void) +{ + class_unregister(&decoder_bmmu_box_class); + pr_info("dec bmmu box exit.\n"); +} + +#if 0 +static int __init decoder_bmmu_box_init(void) +{ + int r; + memset(&global_blk_mgr, 0, sizeof(global_blk_mgr)); + INIT_LIST_HEAD(&global_blk_mgr.box_list); + mutex_init(&global_blk_mgr.mutex); + r = class_register(&decoder_bmmu_box_class); + return r; +} + +module_init(decoder_bmmu_box_init); +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h new file mode 100644 index 000000000000..99aa89b7bd04 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h @@ -0,0 +1,63 @@ +/* + * drivers/amlogic/amports/decoder/decoder_bmmu_box.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef DECODER_BLOCK_BUFFER_BOX +#define DECODER_BLOCK_BUFFER_BOX + +void *decoder_bmmu_box_alloc_box(const char *name, + int channel_id, + int max_num, + int aligned, + int mem_flags); + +int decoder_bmmu_box_alloc_idx( + void *handle, int idx, int size, + int aligned_2n, int mem_flags); + +int decoder_bmmu_box_free_idx(void *handle, int idx); +int decoder_bmmu_box_free(void *handle); +void *decoder_bmmu_box_get_mem_handle( + void *box_handle, int idx); + +unsigned long decoder_bmmu_box_get_phy_addr( + void *box_handle, int idx); + +void *decoder_bmmu_box_get_virt_addr( + void *box_handle, int idx); + +/*flags: &0x1 for wait,*/ +int decoder_bmmu_box_check_and_wait_size( + int size, int flags); + +#define BMMU_ALLOC_FLAGS_WAIT (1 << 0) +#define BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER (1 << 1) +#define BMMU_ALLOC_FLAGS_WAITCLEAR \ + (BMMU_ALLOC_FLAGS_WAIT |\ + BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER) + +int decoder_bmmu_box_alloc_idx_wait( + void *handle, int idx, + int size, int aligned_2n, + int mem_flags, + int wait_flags); + +int decoder_bmmu_box_init(void); +void decoder_bmmu_box_exit(void); + +#endif /* + */ + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c new file mode 100644 index 000000000000..26440fe85337 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c @@ -0,0 +1,383 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/decoder_mmu_box.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +struct decoder_mmu_box { + int max_sc_num; + const char *name; + int channel_id; + struct mutex mutex; + struct list_head list; + struct codec_mm_scatter *sc_list[1]; +}; +#define MAX_KEEP_FRAME 4 +#define START_KEEP_ID 0x9 +#define MAX_KEEP_ID (INT_MAX - 1) +struct decoder_mmu_box_mgr { + int num; + struct mutex mutex; + struct codec_mm_scatter *keep_sc[MAX_KEEP_FRAME]; + int keep_id[MAX_KEEP_FRAME]; + int next_id;/*id for keep & free.*/ + struct list_head box_list; +}; +static struct decoder_mmu_box_mgr global_mgr; +static struct decoder_mmu_box_mgr *get_decoder_mmu_box_mgr(void) +{ + return &global_mgr; +} + +static int decoder_mmu_box_mgr_add_box(struct decoder_mmu_box *box) +{ + struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); + + mutex_lock(&mgr->mutex); + list_add_tail(&box->list, &mgr->box_list); + mutex_unlock(&mgr->mutex); + return 0; +} + +static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box) +{ + struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); + + mutex_lock(&mgr->mutex); + list_del(&box->list); + mutex_unlock(&mgr->mutex); + return 0; +} + + + +void *decoder_mmu_box_alloc_box(const char *name, + int channel_id, + int max_num, + int min_size_M) +/*min_size_M:wait alloc this size*/ +{ + struct decoder_mmu_box *box; + int size; + + size = sizeof(struct decoder_mmu_box) + + sizeof(struct codec_mm_scatter *) * + max_num; + box = kmalloc(size, GFP_KERNEL); + if (!box) { + pr_err("can't alloc decoder buffers box!!!\n"); + return NULL; + } + memset(box, 0, size); + box->max_sc_num = max_num; + box->name = name; + box->channel_id = channel_id; + mutex_init(&box->mutex); + INIT_LIST_HEAD(&box->list); + decoder_mmu_box_mgr_add_box(box); + codec_mm_scatter_mgt_delay_free_swith(1, 2000, + min_size_M); + return (void *)box; +} +EXPORT_SYMBOL(decoder_mmu_box_alloc_box); + +int decoder_mmu_box_alloc_idx( + void *handle, int idx, int num_pages, + unsigned int *mmu_index_adr) +{ + struct decoder_mmu_box *box = handle; + struct codec_mm_scatter *sc; + int ret; + int i; + + if (!box || idx < 0 || idx >= box->max_sc_num) { + pr_err("can't alloc mmu box(%p),idx:%d\n", + box, idx); + return -1; + } + mutex_lock(&box->mutex); + sc = box->sc_list[idx]; + if (sc) { + if (sc->page_max_cnt >= num_pages) + ret = codec_mm_scatter_alloc_want_pages(sc, + num_pages); + else { + codec_mm_scatter_dec_owner_user(sc, 0); + box->sc_list[idx] = NULL; + sc = NULL; + } + + } + if (!sc) { + sc = codec_mm_scatter_alloc(num_pages + 64, num_pages); + if (!sc) { + mutex_unlock(&box->mutex); + pr_err("alloc mmu failed, need pages=%d\n", + num_pages); + return -1; + } + box->sc_list[idx] = sc; + } + + for (i = 0; i < num_pages; i++) + mmu_index_adr[i] = PAGE_INDEX(sc->pages_list[i]); + mmu_index_adr[num_pages] = 0; + + mutex_unlock(&box->mutex); + + return 0; +} +EXPORT_SYMBOL(decoder_mmu_box_alloc_idx); + +int decoder_mmu_box_free_idx_tail( + void *handle, int idx, + int start_release_index) +{ + struct decoder_mmu_box *box = handle; + struct codec_mm_scatter *sc; + + if (!box || idx < 0 || idx >= box->max_sc_num) { + pr_err("can't free tail mmu box(%p),idx:%d in (%d-%d)\n", + box, idx, 0, + box->max_sc_num - 1); + return -1; + } + mutex_lock(&box->mutex); + sc = box->sc_list[idx]; + if (sc && start_release_index < sc->page_cnt) + codec_mm_scatter_free_tail_pages_fast(sc, + start_release_index); + mutex_unlock(&box->mutex); + return 0; +} +EXPORT_SYMBOL(decoder_mmu_box_free_idx_tail); + +int decoder_mmu_box_free_idx(void *handle, int idx) +{ + struct decoder_mmu_box *box = handle; + struct codec_mm_scatter *sc; + + if (!box || idx < 0 || idx >= box->max_sc_num) { + pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", + box, idx, 0, + box->max_sc_num - 1); + return -1; + } + mutex_lock(&box->mutex); + sc = box->sc_list[idx]; + if (sc && sc->page_cnt > 0) { + codec_mm_scatter_dec_owner_user(sc, 0); + box->sc_list[idx] = NULL; + } mutex_unlock(&box->mutex); + return 0; +} +EXPORT_SYMBOL(decoder_mmu_box_free_idx); + +int decoder_mmu_box_free(void *handle) +{ + struct decoder_mmu_box *box = handle; + struct codec_mm_scatter *sc; + int i; + + if (!box) { + pr_err("can't free box of NULL box!\n"); + return -1; + } + mutex_lock(&box->mutex); + for (i = 0; i < box->max_sc_num; i++) { + sc = box->sc_list[i]; + if (sc) { + codec_mm_scatter_dec_owner_user(sc, 200); + box->sc_list[i] = NULL; + } + } + mutex_unlock(&box->mutex); + decoder_mmu_box_mgr_del_box(box); + kfree(box); + codec_mm_scatter_mgt_delay_free_swith(0, 2000, 0); + return 0; +} +EXPORT_SYMBOL(decoder_mmu_box_free); + +void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx) +{ + struct decoder_mmu_box *box = box_handle; + + if (!box || idx < 0 || idx >= box->max_sc_num) + return NULL; + return box->sc_list[idx]; +} +EXPORT_SYMBOL(decoder_mmu_box_get_mem_handle); + +static int decoder_mmu_box_dump(struct decoder_mmu_box *box, + void *buf, int size) +{ + char *pbuf = buf; + char sbuf[512]; + int tsize = 0; + int s; + int i; + + if (!pbuf) + pbuf = sbuf; + + #define BUFPRINT(args...) \ + do {\ + s = sprintf(pbuf, args);\ + tsize += s;\ + pbuf += s; \ + } while (0) + + for (i = 0; i < box->max_sc_num; i++) { + struct codec_mm_scatter *sc = box->sc_list[i]; + + if (sc) { + BUFPRINT("sc mem[%d]:%p, size=%d\n", + i, sc, + sc->page_cnt << PAGE_SHIFT); + } + } +#undef BUFPRINT + if (!buf) + pr_info("%s", sbuf); + + return tsize; +} + +static int decoder_mmu_box_dump_all(void *buf, int size) +{ + struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); + char *pbuf = buf; + char sbuf[512]; + int tsize = 0; + int s; + int i; + struct list_head *head, *list; + + if (!pbuf) + pbuf = sbuf; + + #define BUFPRINT(args...) \ + do {\ + s = sprintf(pbuf, args);\ + tsize += s;\ + pbuf += s; \ + } while (0) + + mutex_lock(&mgr->mutex); + head = &mgr->box_list; + list = head->next; + i = 0; + while (list != head) { + struct decoder_mmu_box *box; + + box = list_entry(list, struct decoder_mmu_box, + list); + BUFPRINT("box[%d]: %s, player_id:%d, max_num:%d\n", + i, + box->name, + box->channel_id, + box->max_sc_num); + if (buf) { + tsize += decoder_mmu_box_dump(box, pbuf, size - tsize); + if (tsize > 0) + pbuf += tsize; + } else { + pr_info("%s", sbuf); + pbuf = sbuf; + tsize += decoder_mmu_box_dump(box, NULL, 0); + } + list = list->next; + i++; + } + mutex_unlock(&mgr->mutex); + + +#undef BUFPRINT + if (!buf) + pr_info("%s", sbuf); + return tsize; +} + + + +static ssize_t +box_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + ret = decoder_mmu_box_dump_all(buf, PAGE_SIZE); + return ret; +} + + + +static struct class_attribute decoder_mmu_box_class_attrs[] = { + __ATTR_RO(box_dump), + __ATTR_NULL +}; + +static struct class decoder_mmu_box_class = { + .name = "decoder_mmu_box", + .class_attrs = decoder_mmu_box_class_attrs, +}; + +int decoder_mmu_box_init(void) +{ + int r; + + memset(&global_mgr, 0, sizeof(global_mgr)); + INIT_LIST_HEAD(&global_mgr.box_list); + mutex_init(&global_mgr.mutex); + global_mgr.next_id = START_KEEP_ID; + r = class_register(&decoder_mmu_box_class); + return r; +} +EXPORT_SYMBOL(decoder_mmu_box_init); + +void decoder_mmu_box_exit(void) +{ + class_unregister(&decoder_mmu_box_class); + pr_info("dec mmu box exit.\n"); +} + +#if 0 +static int __init decoder_mmu_box_init(void) +{ + int r; + + memset(&global_mgr, 0, sizeof(global_mgr)); + INIT_LIST_HEAD(&global_mgr.box_list); + mutex_init(&global_mgr.mutex); + global_mgr.next_id = START_KEEP_ID; + r = class_register(&decoder_mmu_box_class); + return r; +} + +module_init(decoder_mmu_box_init); +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h new file mode 100644 index 000000000000..387dd242d8da --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h @@ -0,0 +1,45 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/decoder_mmu_box.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef DECODER_BUFFER_BOX +#define DECODER_BUFFER_BOX + +void *decoder_mmu_box_alloc_box(const char *name, + int channel_id, + int max_num, + int min_size_M); + +int decoder_mmu_box_alloc_idx( + void *handle, int idx, int num_pages, + unsigned int *mmu_index_adr); + +int decoder_mmu_box_free_idx_tail(void *handle, int idx, + int start_release_index); + +int decoder_mmu_box_free_idx(void *handle, int idx); + +int decoder_mmu_box_free(void *handle); + +int decoder_mmu_box_move_keep_idx(void *box_handle, + int keep_idx); +int decoder_mmu_box_free_keep(int keep_id); +int decoder_mmu_box_free_all_keep(void); +void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx); +int decoder_mmu_box_init(void); +void decoder_mmu_box_exit(void); + +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c new file mode 100644 index 000000000000..33ab7654fa26 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/utils.c @@ -0,0 +1,66 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/utils.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vdec.h" +#include "vdec_input.h" +#include +#include "amvdec.h" +#include "decoder_mmu_box.h" +#include "decoder_bmmu_box.h" + +static int __init decoder_common_init(void) +{ + /*vdec init.*/ + vdec_module_init(); + + /*amvdec init.*/ + amvdec_init(); + + /*mmu box init.*/ + decoder_mmu_box_init();/*exit?*/ + decoder_bmmu_box_init(); + + return 0; +} + +static void __exit decoder_common_exit(void) +{ + /*vdec exit.*/ + vdec_module_exit(); + + /*amvdec exit.*/ + amvdec_exit(); + + decoder_mmu_box_exit(); + decoder_bmmu_box_exit(); +} + +module_init(decoder_common_init); +module_exit(decoder_common_exit); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c new file mode 100644 index 000000000000..7c5488217630 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c @@ -0,0 +1,2907 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/vdec.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "vdec.h" +#ifdef CONFIG_MULTI_DEC +#include "vdec_profile.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/amports/amports_priv.h" + +#include +#include "../utils/amvdec.h" +#include "vdec_input.h" + +#include "../../../common/media_clock/clk/clk.h" +#include +#include +#include +#include + +static DEFINE_MUTEX(vdec_mutex); + +#define MC_SIZE (4096 * 4) +#define CMA_ALLOC_SIZE SZ_64M +#define MEM_NAME "vdec_prealloc" +static int inited_vcodec_num; +static int poweron_clock_level; +static int keep_vdec_mem; +static unsigned int debug_trace_num = 16 * 20; +static int step_mode; +static unsigned int clk_config; + +static struct page *vdec_cma_page; +int vdec_mem_alloced_from_codec, delay_release; +static unsigned long reserved_mem_start, reserved_mem_end; +static int hevc_max_reset_count; +static DEFINE_SPINLOCK(vdec_spin_lock); + +#define HEVC_TEST_LIMIT 100 +#define GXBB_REV_A_MINOR 0xA + +struct am_reg { + char *name; + int offset; +}; + +struct vdec_isr_context_s { + int index; + int irq; + irq_handler_t dev_isr; + irq_handler_t dev_threaded_isr; + void *dev_id; +}; + +struct vdec_core_s { + struct list_head connected_vdec_list; + spinlock_t lock; + + atomic_t vdec_nr; + struct vdec_s *vfm_vdec; + struct vdec_s *active_vdec; + struct platform_device *vdec_core_platform_device; + struct device *cma_dev; + unsigned long mem_start; + unsigned long mem_end; + + struct semaphore sem; + struct task_struct *thread; + + struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX]; + int power_ref_count[VDEC_MAX]; +}; + +static struct vdec_core_s *vdec_core; + +unsigned long vdec_core_lock(struct vdec_core_s *core) +{ + unsigned long flags; + + spin_lock_irqsave(&core->lock, flags); + + return flags; +} + +void vdec_core_unlock(struct vdec_core_s *core, unsigned long flags) +{ + spin_unlock_irqrestore(&core->lock, flags); +} + +static int get_canvas(unsigned int index, unsigned int base) +{ + int start; + int canvas_index = index * base; + + if ((base > 4) || (base == 0)) + return -1; + + if ((AMVDEC_CANVAS_START_INDEX + canvas_index + base - 1) + <= AMVDEC_CANVAS_MAX1) { + start = AMVDEC_CANVAS_START_INDEX + base * index; + } else { + canvas_index -= (AMVDEC_CANVAS_MAX1 - + AMVDEC_CANVAS_START_INDEX + 1) / base * base; + if (canvas_index <= AMVDEC_CANVAS_MAX2) + start = canvas_index / base; + else + return -1; + } + + if (base == 1) { + return start; + } else if (base == 2) { + return ((start + 1) << 16) | ((start + 1) << 8) | start; + } else if (base == 3) { + return ((start + 2) << 16) | ((start + 1) << 8) | start; + } else if (base == 4) { + return (((start + 3) << 24) | (start + 2) << 16) | + ((start + 1) << 8) | start; + } + + return -1; +} + + +int vdec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + if (vdec->dec_status) + return vdec->dec_status(vdec, vstatus); + + return -1; +} +EXPORT_SYMBOL(vdec_status); + +int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) +{ + int r; + + if (vdec->set_trickmode) { + r = vdec->set_trickmode(vdec, trickmode); + + if ((r == 0) && (vdec->slave) && (vdec->slave->set_trickmode)) + r = vdec->slave->set_trickmode(vdec->slave, + trickmode); + } + + return -1; +} +EXPORT_SYMBOL(vdec_set_trickmode); + +/* +* clk_config: + *0:default + *1:no gp0_pll; + *2:always used gp0_pll; + *>=10:fixed n M clk; + *== 100 , 100M clks; +*/ +unsigned int get_vdec_clk_config_settings(void) +{ + return clk_config; +} +void update_vdec_clk_config_settings(unsigned int config) +{ + clk_config = config; +} +EXPORT_SYMBOL(update_vdec_clk_config_settings); + +static bool hevc_workaround_needed(void) +{ + return (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) && + (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) + == GXBB_REV_A_MINOR); +} + +struct device *get_codec_cma_device(void) +{ + return vdec_core->cma_dev; +} + +static unsigned int get_mmu_mode(void) +{ + return 1;//DEBUG_TMP +} + +#ifdef CONFIG_MULTI_DEC +static const char * const vdec_device_name[] = { + "amvdec_mpeg12", "ammvdec_mpeg12", + "amvdec_mpeg4", "ammvdec_mpeg4", + "amvdec_h264", "ammvdec_h264", + "amvdec_mjpeg", "ammvdec_mjpeg", + "amvdec_real", "ammvdec_real", + "amjpegdec", "ammjpegdec", + "amvdec_vc1", "ammvdec_vc1", + "amvdec_avs", "ammvdec_avs", + "amvdec_yuv", "ammvdec_yuv", + "amvdec_h264mvc", "ammvdec_h264mvc", + "amvdec_h264_4k2k", "ammvdec_h264_4k2k", + "amvdec_h265", "ammvdec_h265", + "amvenc_avc", "amvenc_avc", + "jpegenc", "jpegenc", + "amvdec_vp9", "ammvdec_vp9" +}; + +static int vdec_default_buf_size[] = { + 32, 32, /*"amvdec_mpeg12",*/ + 32, 0, /*"amvdec_mpeg4",*/ + 48, 0, /*"amvdec_h264",*/ + 32, 32, /*"amvdec_mjpeg",*/ + 32, 32, /*"amvdec_real",*/ + 32, 32, /*"amjpegdec",*/ + 32, 32, /*"amvdec_vc1",*/ + 32, 32, /*"amvdec_avs",*/ + 32, 32, /*"amvdec_yuv",*/ + 64, 64, /*"amvdec_h264mvc",*/ + 64, 64, /*"amvdec_h264_4k2k", else alloc on decoder*/ + 48, 48, /*"amvdec_h265", else alloc on decoder*/ + 0, 0, /* avs encoder */ + 0, 0, /* jpg encoder */ +#ifdef VP9_10B_MMU + 24, 24, /*"amvdec_vp9", else alloc on decoder*/ +#else + 32, 32, +#endif + 0 +}; + +#else + +static const char * const vdec_device_name[] = { + "amvdec_mpeg12", + "amvdec_mpeg4", + "amvdec_h264", + "amvdec_mjpeg", + "amvdec_real", + "amjpegdec", + "amvdec_vc1", + "amvdec_avs", + "amvdec_yuv", + "amvdec_h264mvc", + "amvdec_h264_4k2k", + "amvdec_h265", + "amvenc_avc", + "jpegenc", + "amvdec_vp9" +}; + +static int vdec_default_buf_size[] = { + 32, /*"amvdec_mpeg12",*/ + 32, /*"amvdec_mpeg4",*/ + 48, /*"amvdec_h264",*/ + 32, /*"amvdec_mjpeg",*/ + 32, /*"amvdec_real",*/ + 32, /*"amjpegdec",*/ + 32, /*"amvdec_vc1",*/ + 32, /*"amvdec_avs",*/ + 32, /*"amvdec_yuv",*/ + 64, /*"amvdec_h264mvc",*/ + 64, /*"amvdec_h264_4k2k", else alloc on decoder*/ + 48, /*"amvdec_h265", else alloc on decoder*/ + 0, /* avs encoder */ + 0, /* jpg encoder */ +#ifdef VP9_10B_MMU + 24, /*"amvdec_vp9", else alloc on decoder*/ +#else + 32, +#endif +}; +#endif + +int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p) +{ + if (copy_from_user((void *)&vdec->sys_info_store, (void *)p, + sizeof(struct dec_sysinfo))) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL(vdec_set_decinfo); + +/* construct vdec strcture */ +struct vdec_s *vdec_create(struct stream_port_s *port, + struct vdec_s *master) +{ + struct vdec_s *vdec; + int type = VDEC_TYPE_SINGLE; + + if (port->type & PORT_TYPE_DECODER_SCHED) + type = (port->type & PORT_TYPE_FRAME) ? + VDEC_TYPE_FRAME_BLOCK : + VDEC_TYPE_STREAM_PARSER; + + vdec = vzalloc(sizeof(struct vdec_s)); + + /* TBD */ + if (vdec) { + vdec->magic = 0x43454456; + vdec->id = 0; + vdec->type = type; + vdec->port = port; + vdec->sys_info = &vdec->sys_info_store; + + INIT_LIST_HEAD(&vdec->list); + + vdec_input_init(&vdec->input, vdec); + + atomic_inc(&vdec_core->vdec_nr); + + if (master) { + vdec->master = master; + master->slave = vdec; + master->sched = 1; + } + } + + pr_info("vdec_create instance %p, total %d\n", vdec, + atomic_read(&vdec_core->vdec_nr)); + + return vdec; +} +EXPORT_SYMBOL(vdec_create); + +int vdec_set_format(struct vdec_s *vdec, int format) +{ + vdec->format = format; + + if (vdec->slave) + vdec->slave->format = format; + + return 0; +} +EXPORT_SYMBOL(vdec_set_format); + +int vdec_set_pts(struct vdec_s *vdec, u32 pts) +{ + vdec->pts = pts; + vdec->pts_valid = true; + return 0; +} +EXPORT_SYMBOL(vdec_set_pts); + +int vdec_set_pts64(struct vdec_s *vdec, u64 pts64) +{ + vdec->pts64 = pts64; + vdec->pts_valid = true; + return 0; +} +EXPORT_SYMBOL(vdec_set_pts64); + +void vdec_set_status(struct vdec_s *vdec, int status) +{ + vdec->status = status; +} +EXPORT_SYMBOL(vdec_set_status); + +void vdec_set_next_status(struct vdec_s *vdec, int status) +{ + vdec->next_status = status; +} +EXPORT_SYMBOL(vdec_set_next_status); + +int vdec_set_video_path(struct vdec_s *vdec, int video_path) +{ + vdec->frame_base_video_path = video_path; + return 0; +} +EXPORT_SYMBOL(vdec_set_video_path); + +/* add frame data to input chain */ +int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count) +{ + return vdec_input_add_frame(&vdec->input, buf, count); +} +EXPORT_SYMBOL(vdec_write_vframe); + +/* +*get next frame from input chain +*/ +/* +*THE VLD_FIFO is 512 bytes and Video buffer level + * empty interrupt is set to 0x80 bytes threshold + */ +#define VLD_PADDING_SIZE 1024 +#define HEVC_PADDING_SIZE (1024*16) +#define FIFO_ALIGN 8 +int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p) +{ + struct vdec_input_s *input = (vdec->master) ? + &vdec->master->input : &vdec->input; + struct vframe_chunk_s *chunk = NULL; + struct vframe_block_list_s *block = NULL; + int dummy; + + /* full reset to HW input */ + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* reset VLD fifo for all vdec */ + WRITE_VREG(DOS_SW_RESET0, (1<<5) | (1<<4) | (1<<3)); + WRITE_VREG(DOS_SW_RESET0, 0); + + dummy = READ_MPEG_REG(RESET0_REGISTER); + WRITE_VREG(POWER_CTL_VLD, 1 << 4); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { +#if 0 + /*move to driver*/ + if (input_frame_based(input)) + WRITE_VREG(HEVC_STREAM_CONTROL, 0); + + /* + * 2: assist + * 3: parser + * 4: parser_state + * 8: dblk + * 11:mcpu + * 12:ccpu + * 13:ddr + * 14:iqit + * 15:ipp + * 17:qdct + * 18:mpred + * 19:sao + * 24:hevc_afifo + */ + WRITE_VREG(DOS_SW_RESET3, + (1<<3)|(1<<4)|(1<<8)|(1<<11)|(1<<12)|(1<<14)|(1<<15)| + (1<<17)|(1<<18)|(1<<19)); + WRITE_VREG(DOS_SW_RESET3, 0); +#endif + } + + /* + *setup HW decoder input buffer (VLD context) + * based on input->type and input->target + */ + if (input_frame_based(input)) { + chunk = vdec_input_next_chunk(&vdec->input); + + if (chunk == NULL) { + *p = NULL; + return -1; + } + + block = chunk->block; + + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, block->start); + WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, block->start + + block->size - 8); + WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, + round_down(block->start + chunk->offset, + FIFO_ALIGN)); + + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* set to manual mode */ + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + WRITE_VREG(VLD_MEM_VIFIFO_RP, + round_down(block->start + chunk->offset, + FIFO_ALIGN)); + dummy = chunk->offset + chunk->size + + VLD_PADDING_SIZE; + if (dummy >= block->size) + dummy -= block->size; + WRITE_VREG(VLD_MEM_VIFIFO_WP, + round_down(block->start + dummy, FIFO_ALIGN)); + + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3); + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, + (0x11 << 16) | (1<<10) | (7<<3)); + + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + WRITE_VREG(HEVC_STREAM_START_ADDR, block->start); + WRITE_VREG(HEVC_STREAM_END_ADDR, block->start + + block->size); + WRITE_VREG(HEVC_STREAM_RD_PTR, block->start + + chunk->offset); + dummy = chunk->offset + chunk->size + + HEVC_PADDING_SIZE; + if (dummy >= block->size) + dummy -= block->size; + WRITE_VREG(HEVC_STREAM_WR_PTR, + round_down(block->start + dummy, FIFO_ALIGN)); + + /* set endian */ + SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4); + } + + *p = chunk; + return chunk->size; + + } else { + u32 rp = 0, wp = 0, fifo_len = 0; + int size; + /* stream based */ + if (input->swap_valid) { + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* restore read side */ + WRITE_VREG(VLD_MEM_SWAP_ADDR, + page_to_phys(input->swap_page)); + WRITE_VREG(VLD_MEM_SWAP_CTL, 1); + + while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) + ; + WRITE_VREG(VLD_MEM_SWAP_CTL, 0); + + /* restore wrap count */ + WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, + input->stream_cookie); + + rp = READ_VREG(VLD_MEM_VIFIFO_RP); + fifo_len = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + + /* enable */ + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, + (0x11 << 16) | (1<<10)); + + /* update write side */ + WRITE_VREG(VLD_MEM_VIFIFO_WP, + READ_MPEG_REG(PARSER_VIDEO_WP)); + + wp = READ_VREG(VLD_MEM_VIFIFO_WP); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); + + /* restore read side */ + WRITE_VREG(HEVC_STREAM_SWAP_ADDR, + page_to_phys(input->swap_page)); + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1); + + while (READ_VREG(HEVC_STREAM_SWAP_CTRL) + & (1<<7)) + ; + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); + + /* restore stream offset */ + WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, + input->stream_cookie); + + rp = READ_VREG(HEVC_STREAM_RD_PTR); + fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL) + >> 16) & 0x7f; + + + /* enable */ + + /* update write side */ + WRITE_VREG(HEVC_STREAM_WR_PTR, + READ_MPEG_REG(PARSER_VIDEO_WP)); + + wp = READ_VREG(HEVC_STREAM_WR_PTR); + } + + } else { + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, + input->start); + WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, + input->start + input->size - 8); + WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, + input->start); + + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* set to manual mode */ + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start); + WRITE_VREG(VLD_MEM_VIFIFO_WP, + READ_MPEG_REG(PARSER_VIDEO_WP)); + + rp = READ_VREG(VLD_MEM_VIFIFO_RP); + + /* enable */ + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, + (0x11 << 16) | (1<<10)); + + wp = READ_VREG(VLD_MEM_VIFIFO_WP); + + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + WRITE_VREG(HEVC_STREAM_START_ADDR, + input->start); + WRITE_VREG(HEVC_STREAM_END_ADDR, + input->start + input->size); + WRITE_VREG(HEVC_STREAM_RD_PTR, + input->start); + WRITE_VREG(HEVC_STREAM_WR_PTR, + READ_MPEG_REG(PARSER_VIDEO_WP)); + + rp = READ_VREG(HEVC_STREAM_RD_PTR); + wp = READ_VREG(HEVC_STREAM_WR_PTR); + fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL) + >> 16) & 0x7f; + + /* enable */ + } + } + *p = NULL; + if (wp >= rp) + size = wp - rp + fifo_len; + else + size = wp + input->size - rp + fifo_len; + if (size < 0) { + pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n", + __func__, input->size, wp, rp, fifo_len, size); + size = 0; + } + return size; + } +} +EXPORT_SYMBOL(vdec_prepare_input); + +void vdec_enable_input(struct vdec_s *vdec) +{ + struct vdec_input_s *input = &vdec->input; + + if (vdec->status != VDEC_STATUS_ACTIVE) + return; + + if (input->target == VDEC_INPUT_TARGET_VLD) + SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1<<2) | (1<<1)); + else if (input->target == VDEC_INPUT_TARGET_HEVC) { + SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); + if (vdec_stream_based(vdec)) + CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4); + else + SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4); + SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29)); + } +} +EXPORT_SYMBOL(vdec_enable_input); + +void vdec_set_flag(struct vdec_s *vdec, u32 flag) +{ + vdec->flag = flag; +} + +void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec) +{ + if (vdec && next_vdec) { + vdec->sched = 0; + next_vdec->sched = 1; + } +} +void vdec_vframe_dirty(struct vdec_s *vdec, struct vframe_chunk_s *chunk) +{ + if (chunk) + chunk->flag |= VFRAME_CHUNK_FLAG_CONSUMED; + + if (vdec_stream_based(vdec)) { + if (vdec->slave && + ((vdec->slave->flag & + VDEC_FLAG_INPUT_KEEP_CONTEXT) == 0)) { + vdec->input.swap_needed = false; + } else + vdec->input.swap_needed = true; + + if (vdec->input.target == VDEC_INPUT_TARGET_VLD) { + WRITE_MPEG_REG(PARSER_VIDEO_RP, + READ_VREG(VLD_MEM_VIFIFO_RP)); + WRITE_VREG(VLD_MEM_VIFIFO_WP, + READ_MPEG_REG(PARSER_VIDEO_WP)); + } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) { + WRITE_MPEG_REG(PARSER_VIDEO_RP, + READ_VREG(HEVC_STREAM_RD_PTR)); + WRITE_VREG(HEVC_STREAM_WR_PTR, + READ_MPEG_REG(PARSER_VIDEO_WP)); + } + } +} +EXPORT_SYMBOL(vdec_vframe_dirty); + +void vdec_save_input_context(struct vdec_s *vdec) +{ + struct vdec_input_s *input = (vdec->master) ? + &vdec->master->input : &vdec->input; + +#ifdef CONFIG_MULTI_DEC + vdec_profile(vdec, VDEC_PROFILE_EVENT_SAVE_INPUT); +#endif + + if (input->target == VDEC_INPUT_TARGET_VLD) + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1<<15); + + if (input_stream_based(input) && (input->swap_needed)) { + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_SWAP_ADDR, + page_to_phys(input->swap_page)); + WRITE_VREG(VLD_MEM_SWAP_CTL, 3); + while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) + ; + WRITE_VREG(VLD_MEM_SWAP_CTL, 0); + vdec->input.stream_cookie = + READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + WRITE_VREG(HEVC_STREAM_SWAP_ADDR, + page_to_phys(input->swap_page)); + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 3); + + while (READ_VREG(HEVC_STREAM_SWAP_CTRL) & (1<<7)) + ; + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); + + vdec->input.stream_cookie = + READ_VREG(HEVC_SHIFT_BYTE_COUNT); + } + + input->swap_valid = true; + + if (input->target == VDEC_INPUT_TARGET_VLD) + WRITE_MPEG_REG(PARSER_VIDEO_RP, + READ_VREG(VLD_MEM_VIFIFO_RP)); + else + WRITE_MPEG_REG(PARSER_VIDEO_RP, + READ_VREG(HEVC_STREAM_RD_PTR)); + } +} +EXPORT_SYMBOL(vdec_save_input_context); + +void vdec_clean_input(struct vdec_s *vdec) +{ + struct vdec_input_s *input = &vdec->input; + + while (!list_empty(&input->vframe_chunk_list)) { + struct vframe_chunk_s *chunk = + vdec_input_next_chunk(input); + if (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED) + vdec_input_release_chunk(input, chunk); + else + break; + } + vdec_save_input_context(vdec); +} +EXPORT_SYMBOL(vdec_clean_input); + +const char *vdec_status_str(struct vdec_s *vdec) +{ + switch (vdec->status) { + case VDEC_STATUS_UNINITIALIZED: + return "VDEC_STATUS_UNINITIALIZED"; + case VDEC_STATUS_DISCONNECTED: + return "VDEC_STATUS_DISCONNECTED"; + case VDEC_STATUS_CONNECTED: + return "VDEC_STATUS_CONNECTED"; + case VDEC_STATUS_ACTIVE: + return "VDEC_STATUS_ACTIVE"; + default: + return "invalid status"; + } +} + +const char *vdec_type_str(struct vdec_s *vdec) +{ + switch (vdec->type) { + case VDEC_TYPE_SINGLE: + return "VDEC_TYPE_SINGLE"; + case VDEC_TYPE_STREAM_PARSER: + return "VDEC_TYPE_STREAM_PARSER"; + case VDEC_TYPE_FRAME_BLOCK: + return "VDEC_TYPE_FRAME_BLOCK"; + case VDEC_TYPE_FRAME_CIRCULAR: + return "VDEC_TYPE_FRAME_CIRCULAR"; + default: + return "VDEC_TYPE_INVALID"; + } +} + +const char *vdec_device_name_str(struct vdec_s *vdec) +{ + return vdec_device_name[vdec->format * 2 + 1]; +} + +void walk_vdec_core_list(char *s) +{ + struct vdec_s *vdec; + struct vdec_core_s *core = vdec_core; + unsigned long flags; + + pr_info("%s --->\n", s); + + flags = vdec_core_lock(vdec_core); + + if (list_empty(&core->connected_vdec_list)) { + pr_info("connected vdec list empty\n"); + } else { + list_for_each_entry(vdec, &core->connected_vdec_list, list) { + pr_info("\tvdec (%p), status = %s\n", vdec, + vdec_status_str(vdec)); + } + } + + vdec_core_unlock(vdec_core, flags); +} +EXPORT_SYMBOL(walk_vdec_core_list); + +/* insert vdec to vdec_core for scheduling */ +int vdec_connect(struct vdec_s *vdec) +{ + unsigned long flags; + + if (vdec->status != VDEC_STATUS_DISCONNECTED) + return 0; + + vdec_set_status(vdec, VDEC_STATUS_CONNECTED); + vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED); + + init_completion(&vdec->inactive_done); + + if (vdec->slave) { + vdec_set_status(vdec->slave, VDEC_STATUS_CONNECTED); + vdec_set_next_status(vdec->slave, VDEC_STATUS_CONNECTED); + + init_completion(&vdec->slave->inactive_done); + } + + flags = vdec_core_lock(vdec_core); + + list_add_tail(&vdec->list, &vdec_core->connected_vdec_list); + + if (vdec->slave) { + list_add_tail(&vdec->slave->list, + &vdec_core->connected_vdec_list); + } + + vdec_core_unlock(vdec_core, flags); + + up(&vdec_core->sem); + + return 0; +} +EXPORT_SYMBOL(vdec_connect); + +/* remove vdec from vdec_core scheduling */ +int vdec_disconnect(struct vdec_s *vdec) +{ +#ifdef CONFIG_MULTI_DEC + vdec_profile(vdec, VDEC_PROFILE_EVENT_DISCONNECT); +#endif + + if ((vdec->status != VDEC_STATUS_CONNECTED) && + (vdec->status != VDEC_STATUS_ACTIVE)) { + return 0; + } + + /* + *when a vdec is under the management of scheduler + * the status change will only be from vdec_core_thread + */ + vdec_set_next_status(vdec, VDEC_STATUS_DISCONNECTED); + + if (vdec->slave) + vdec_set_next_status(vdec->slave, VDEC_STATUS_DISCONNECTED); + else if (vdec->master) + vdec_set_next_status(vdec->master, VDEC_STATUS_DISCONNECTED); + + up(&vdec_core->sem); + + wait_for_completion(&vdec->inactive_done); + + if (vdec->slave) + wait_for_completion(&vdec->slave->inactive_done); + else if (vdec->master) + wait_for_completion(&vdec->master->inactive_done); + + return 0; +} +EXPORT_SYMBOL(vdec_disconnect); + +/* release vdec structure */ +int vdec_destroy(struct vdec_s *vdec) +{ + if (!vdec->master) + vdec_input_release(&vdec->input); + +#ifdef CONFIG_MULTI_DEC + vdec_profile_flush(vdec); +#endif + + vfree(vdec); + + atomic_dec(&vdec_core->vdec_nr); + + return 0; +} +EXPORT_SYMBOL(vdec_destroy); + +/* + * Only support time sliced decoding for frame based input, + * so legacy decoder can exist with time sliced decoder. + */ +static const char *get_dev_name(bool use_legacy_vdec, int format) +{ +#ifdef CONFIG_MULTI_DEC + if (use_legacy_vdec) + return vdec_device_name[format * 2]; + else + return vdec_device_name[format * 2 + 1]; +#else + return vdec_device_name[format]; +#endif +} + +void vdec_free_cmabuf(void) +{ + mutex_lock(&vdec_mutex); + + if (inited_vcodec_num > 0) { + mutex_unlock(&vdec_mutex); + return; + } + + if (vdec_mem_alloced_from_codec && vdec_core->mem_start) { + codec_mm_free_for_dma(MEM_NAME, vdec_core->mem_start); + vdec_cma_page = NULL; + vdec_core->mem_start = reserved_mem_start; + vdec_core->mem_end = reserved_mem_end; + pr_info("force free vdec memory\n"); + } + + mutex_unlock(&vdec_mutex); +} + +/* +*register vdec_device + * create output, vfm or create ionvideo output + */ +s32 vdec_init(struct vdec_s *vdec, int is_4k) +{ + int r = 0; + struct vdec_s *p = vdec; + int retry_num = 0; + int more_buffers = 0; + const char *dev_name; + + if (is_4k && vdec->format < VFORMAT_H264) { + /* + *old decoder don't support 4k + * but size is bigger; + * clear 4k flag, and used more buffers; + */ + more_buffers = 1; + is_4k = 0; + } + + dev_name = get_dev_name(vdec_single(vdec), vdec->format); + + if (dev_name == NULL) + return -ENODEV; + + pr_info("vdec_init, dev_name:%s, vdec_type=%s\n", + dev_name, vdec_type_str(vdec)); + + /* + *todo: VFM patch control should be configurable, + * for now all stream based input uses default VFM path. + */ + if (vdec_stream_based(vdec) && !vdec_dual(vdec)) { + if (vdec_core->vfm_vdec == NULL) { + pr_info("vdec_init set vfm decoder %p\n", vdec); + vdec_core->vfm_vdec = vdec; + } else { + pr_info("vdec_init vfm path busy.\n"); + return -EBUSY; + } + } + + if (vdec_single(vdec) && + ((vdec->format == VFORMAT_H264_4K2K) || + (vdec->format == VFORMAT_HEVC && is_4k))) { + try_free_keep_video(0); + } + + /* + *when blackout_policy was set, vdec would not free cma buffer, if + * current vformat require larger buffer size than current + * buf size, reallocated it + */ + if (vdec_single(vdec) && + ((vdec_core->mem_start != vdec_core->mem_end && + vdec_core->mem_end - vdec_core->mem_start + 1 < + vdec_default_buf_size[vdec->format] * SZ_1M))) { +#ifdef CONFIG_MULTI_DEC + pr_info("current vdec size %ld, vformat %d need size %d\n", + vdec_core->mem_end - vdec_core->mem_start, + vdec->format, + vdec_default_buf_size[vdec->format * 2] * SZ_1M); +#else + pr_info("current vdec size %ld, vformat %d need size %d\n", + vdec_core->mem_end - vdec_core->mem_start, + vdec->format, + vdec_default_buf_size[vdec->format] * SZ_1M); +#endif + try_free_keep_video(0); + vdec_free_cmabuf(); + } + + mutex_lock(&vdec_mutex); + inited_vcodec_num++; + mutex_unlock(&vdec_mutex); + + vdec_input_set_type(&vdec->input, vdec->type, + (vdec->format == VFORMAT_HEVC || + vdec->format == VFORMAT_VP9) ? + VDEC_INPUT_TARGET_HEVC : + VDEC_INPUT_TARGET_VLD); + + p->cma_dev = vdec_core->cma_dev; + p->get_canvas = get_canvas; + /* todo */ + if (!vdec_dual(vdec)) + p->use_vfm_path = vdec_stream_based(vdec); + + if (vdec_single(vdec)) { + pr_info("vdec_dev_reg.mem[0x%lx -- 0x%lx]\n", + vdec_core->mem_start, + vdec_core->mem_end); + p->mem_start = vdec_core->mem_start; + p->mem_end = vdec_core->mem_end; + } + + /* allocate base memory for decoder instance */ + while ((p->mem_start == p->mem_end) && (vdec_single(vdec))) { + int alloc_size; + +#ifdef CONFIG_MULTI_DEC + alloc_size = + vdec_default_buf_size[vdec->format * 2 + 1] + * SZ_1M; +#else + alloc_size = vdec_default_buf_size[vdec->format] * SZ_1M; +#endif + if (alloc_size == 0) + break;/*alloc end*/ + if (is_4k) { + /*used 264 4k's setting for 265.*/ +#ifdef CONFIG_MULTI_DEC + int m4k_size = + vdec_default_buf_size[VFORMAT_H264_4K2K * 2] * + SZ_1M; +#else + int m4k_size = + vdec_default_buf_size[VFORMAT_H264_4K2K] * + SZ_1M; +#endif + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + m4k_size = 32 * SZ_1M; + if ((m4k_size > 0) && (m4k_size < 200 * SZ_1M)) + alloc_size = m4k_size; + +#ifdef VP9_10B_MMU + if ((vdec->format == VFORMAT_VP9) && + (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)) { +#ifdef CONFIG_MULTI_DEC + if (p->use_vfm_path) + alloc_size = + vdec_default_buf_size[VFORMAT_VP9 * 2] + * SZ_1M; + else + alloc_size = + vdec_default_buf_size[VFORMAT_VP9 + * 2 + 1] * SZ_1M; + +#else + alloc_size = + vdec_default_buf_size[VFORMAT_VP9] * SZ_1M; +#endif + } +#endif + } else if (more_buffers) { + alloc_size = alloc_size + 16 * SZ_1M; + } + + if ((vdec->format == VFORMAT_HEVC) + && get_mmu_mode() + && (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)) { +#ifdef CONFIG_MULTI_DEC + if (p->use_vfm_path) + alloc_size = 33 * SZ_1M; + else + alloc_size = 33 * SZ_1M; +#else + alloc_size = 33 * SZ_1M; +#endif + } + + if ((vdec->format == VFORMAT_H264) + && (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + && codec_mm_get_total_size() <= 80 * SZ_1M) { +#ifdef CONFIG_MULTI_DEC + if (p->use_vfm_path) + alloc_size = 32 * SZ_1M; + else + alloc_size = 32 * SZ_1M; +#else + alloc_size = 32 * SZ_1M; +#endif + } + + + p->mem_start = codec_mm_alloc_for_dma(MEM_NAME, + alloc_size / PAGE_SIZE, 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | CODEC_MM_FLAGS_CPU | + CODEC_MM_FLAGS_FOR_VDECODER); + if (!p->mem_start) { + if (retry_num < 1) { + pr_err("vdec base CMA allocation failed,try again\\n"); + retry_num++; + try_free_keep_video(0); + continue;/*retry alloc*/ + } + pr_err("vdec base CMA allocation failed.\n"); + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + + return -ENOMEM; + } + + p->mem_end = p->mem_start + alloc_size - 1; + pr_info("vdec base memory alloced [%p -- %p]\n", + (void *)p->mem_start, + (void *)p->mem_end); + + break;/*alloc end*/ + } + + if (vdec_single(vdec)) { + vdec_core->mem_start = p->mem_start; + vdec_core->mem_end = p->mem_end; + vdec_mem_alloced_from_codec = 1; + } + +/*alloc end:*/ + /* vdec_dev_reg.flag = 0; */ + + p->dev = + platform_device_register_data( + &vdec_core->vdec_core_platform_device->dev, + dev_name, + PLATFORM_DEVID_AUTO, + &p, sizeof(struct vdec_s *)); + + if (IS_ERR(p->dev)) { + r = PTR_ERR(p->dev); + pr_err("vdec: Decoder device %s register failed (%d)\n", + dev_name, r); + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + + goto error; + } + + if ((p->type == VDEC_TYPE_FRAME_BLOCK) && (p->run == NULL)) { + r = -ENODEV; + pr_err("vdec: Decoder device not handled (%s)\n", dev_name); + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + + goto error; + } + + if (p->use_vfm_path) { + vdec->vf_receiver_inst = -1; + } else if (!vdec_dual(vdec)) { + /* create IONVIDEO instance and connect decoder's + * vf_provider interface to it + */ + if (p->type != VDEC_TYPE_FRAME_BLOCK) { + r = -ENODEV; + pr_err("vdec: Incorrect decoder type\n"); + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + + goto error; + } + if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) { +#if 1 + //r = ionvideo_alloc_map(&vdec->vf_receiver_name, + //&vdec->vf_receiver_inst);//DEBUG_TMP +#else + /* + * temporarily just use decoder instance ID as iondriver ID + * to solve OMX iondriver instance number check time sequence + * only the limitation is we can NOT mix different video + * decoders since same ID will be used for different decoder + * formats. + */ + vdec->vf_receiver_inst = p->dev->id; + r = ionvideo_assign_map(&vdec->vf_receiver_name, + &vdec->vf_receiver_inst); +#endif + if (r < 0) { + pr_err("IonVideo frame receiver allocation failed.\n"); + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + + goto error; + } + + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "%s-%s", vdec->vf_provider_name, + vdec->vf_receiver_name); + + } else if (p->frame_base_video_path == + FRAME_BASE_PATH_AMLVIDEO_AMVIDEO) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amlvideo.0 amvideo"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "%s-%s", vdec->vf_provider_name, + "amlvideo.0 amvideo"); + } else if (p->frame_base_video_path == + FRAME_BASE_PATH_AMLVIDEO1_AMVIDEO2) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "ppmgr amlvideo.1 amvide2"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "%s-%s", vdec->vf_provider_name, + "ppmgr amlvideo.1 amvide2"); + } + + if (vfm_map_add(vdec->vfm_map_id, + vdec->vfm_map_chain) < 0) { + r = -ENOMEM; + pr_err("Decoder pipeline map creation failed %s.\n", + vdec->vfm_map_id); + vdec->vfm_map_id[0] = 0; + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + + goto error; + } + + pr_info("vfm map %s created\n", vdec->vfm_map_id); + + /* + *assume IONVIDEO driver already have a few vframe_receiver + * registered. + * 1. Call iondriver function to allocate a IONVIDEO path and + * provide receiver's name and receiver op. + * 2. Get decoder driver's provider name from driver instance + * 3. vfm_map_add(name, " + * "), e.g. + * vfm_map_add("vdec_ion_map_0", "mpeg4_0 iondriver_1"); + * 4. vf_reg_provider and vf_reg_receiver + * Note: the decoder provider's op uses vdec as op_arg + * the iondriver receiver's op uses iondev device as + * op_arg + */ + + } + + if (!vdec_single(vdec)) { + vf_reg_provider(&p->vframe_provider); + + vf_notify_receiver(p->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, + vdec); + } + + pr_info("vdec_init, vf_provider_name = %s\n", p->vf_provider_name); + + /* vdec is now ready to be active */ + vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); + + return 0; + +error: + return r; +} +EXPORT_SYMBOL(vdec_init); + +void vdec_release(struct vdec_s *vdec) +{ + vdec_disconnect(vdec); + + if (vdec->vframe_provider.name) + vf_unreg_provider(&vdec->vframe_provider); + + if (vdec_core->vfm_vdec == vdec) + vdec_core->vfm_vdec = NULL; + + if (vdec->vf_receiver_inst >= 0) { + if (vdec->vfm_map_id[0]) { + vfm_map_remove(vdec->vfm_map_id); + vdec->vfm_map_id[0] = 0; + } + + /* + *vf_receiver_inst should be > 0 since 0 is + * for either un-initialized vdec or a ionvideo + * instance reserved for legacy path. + */ + //ionvideo_release_map(vdec->vf_receiver_inst);//DEBUG_TMP + } + + platform_device_unregister(vdec->dev); + + if (!vdec->use_vfm_path) { + if (vdec->mem_start) { + codec_mm_free_for_dma(MEM_NAME, vdec->mem_start); + vdec->mem_start = 0; + vdec->mem_end = 0; + } + } else if (delay_release-- <= 0 && + !keep_vdec_mem && + vdec_mem_alloced_from_codec && + vdec_core->mem_start && + get_blackout_policy()) { + codec_mm_free_for_dma(MEM_NAME, vdec_core->mem_start); + vdec_cma_page = NULL; + vdec_core->mem_start = reserved_mem_start; + vdec_core->mem_end = reserved_mem_end; + } + + vdec_destroy(vdec); + + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); +} +EXPORT_SYMBOL(vdec_release); + +int vdec_reset(struct vdec_s *vdec) +{ + vdec_disconnect(vdec); + + if (vdec->vframe_provider.name) + vf_unreg_provider(&vdec->vframe_provider); + + if ((vdec->slave) && (vdec->slave->vframe_provider.name)) + vf_unreg_provider(&vdec->slave->vframe_provider); + + if (vdec->reset) { + vdec->reset(vdec); + if (vdec->slave) + vdec->slave->reset(vdec->slave); + } + + vdec_input_release(&vdec->input); + + vf_reg_provider(&vdec->vframe_provider); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, vdec); + + if (vdec->slave) { + vf_reg_provider(&vdec->slave->vframe_provider); + vf_notify_receiver(vdec->slave->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, vdec->slave); + } + + vdec_connect(vdec); + + return 0; +} +EXPORT_SYMBOL(vdec_reset); + +static struct vdec_s *active_vdec(struct vdec_core_s *core) +{ + struct vdec_s *vdec; + struct list_head *p; + + list_for_each(p, &core->connected_vdec_list) { + vdec = list_entry(p, struct vdec_s, list); + if (vdec->status == VDEC_STATUS_ACTIVE) + return vdec; + } + + return NULL; +} + +/* +*Decoder callback + * Each decoder instance uses this callback to notify status change, e.g. when + * decoder finished using HW resource. + * a sample callback from decoder's driver is following: + * + * if (hw->vdec_cb) { + * vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED); + * hw->vdec_cb(vdec, hw->vdec_cb_arg); + * } + */ +static void vdec_callback(struct vdec_s *vdec, void *data) +{ + struct vdec_core_s *core = (struct vdec_core_s *)data; + +#ifdef CONFIG_MULTI_DEC + vdec_profile(vdec, VDEC_PROFILE_EVENT_CB); +#endif + + up(&core->sem); +} + +static irqreturn_t vdec_isr(int irq, void *dev_id) +{ + struct vdec_isr_context_s *c = + (struct vdec_isr_context_s *)dev_id; + struct vdec_s *vdec = vdec_core->active_vdec; + + if (c->dev_isr) + return c->dev_isr(irq, c->dev_id); + + if (c != &vdec_core->isr_context[VDEC_IRQ_1]) { +#if 0 + pr_warn("vdec interrupt w/o a valid receiver\n"); +#endif + return IRQ_HANDLED; + } + + if (!vdec) { +#if 0 + pr_warn("vdec interrupt w/o an active instance running. core = %p\n", + core); +#endif + return IRQ_HANDLED; + } + + if (!vdec->irq_handler) { +#if 0 + pr_warn("vdec instance has no irq handle.\n"); +#endif + return IRQ_HANDLED; + } + + return vdec->irq_handler(vdec); +} + +static irqreturn_t vdec_thread_isr(int irq, void *dev_id) +{ + struct vdec_isr_context_s *c = + (struct vdec_isr_context_s *)dev_id; + struct vdec_s *vdec = vdec_core->active_vdec; + + if (c->dev_threaded_isr) + return c->dev_threaded_isr(irq, c->dev_id); + + if (!vdec) + return IRQ_HANDLED; + + if (!vdec->threaded_irq_handler) + return IRQ_HANDLED; + + return vdec->threaded_irq_handler(vdec); +} + +static inline bool vdec_ready_to_run(struct vdec_s *vdec) +{ + bool r; + + if (vdec->status != VDEC_STATUS_CONNECTED) + return false; + + if (!vdec->run_ready) + return false; + + if ((vdec->slave || vdec->master) && + (vdec->sched == 0)) + return false; + + if (step_mode) { + if ((step_mode & 0xff) != vdec->id) + return false; + } + + step_mode &= ~0xff; + +#ifdef CONFIG_MULTI_DEC + vdec_profile(vdec, VDEC_PROFILE_EVENT_CHK_RUN_READY); +#endif + + r = vdec->run_ready(vdec); + +#ifdef CONFIG_MULTI_DEC + if (r) + vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN_READY); +#endif + + return r; +} + +/* struct vdec_core_shread manages all decoder instance in active list. When + * a vdec is added into the active list, it can onlt be in two status: + * VDEC_STATUS_CONNECTED(the decoder does not own HW resource and ready to run) + * VDEC_STATUS_ACTIVE(the decoder owns HW resources and is running). + * Removing a decoder from active list is only performed within core thread. + * Adding a decoder into active list is performed from user thread. + */ +static int vdec_core_thread(void *data) +{ + unsigned long flags; + struct vdec_core_s *core = (struct vdec_core_s *)data; + + struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; + + sched_setscheduler(current, SCHED_FIFO, ¶m); + + allow_signal(SIGTERM); + + while (down_interruptible(&core->sem) == 0) { + struct vdec_s *vdec, *tmp; + LIST_HEAD(disconnecting_list); + + if (kthread_should_stop()) + break; + + /* clean up previous active vdec's input */ + if ((core->active_vdec) && + (core->active_vdec->status == VDEC_STATUS_CONNECTED)) { + struct vdec_input_s *input = &core->active_vdec->input; + + while (!list_empty(&input->vframe_chunk_list)) { + struct vframe_chunk_s *chunk = + vdec_input_next_chunk(input); + if (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED) + vdec_input_release_chunk(input, chunk); + else + break; + } + + vdec_save_input_context(core->active_vdec); + } + + /* + *todo: + * this is the case when the decoder is in active mode and + * the system side wants to stop it. Currently we rely on + * the decoder instance to go back to VDEC_STATUS_CONNECTED + * from VDEC_STATUS_ACTIVE by its own. However, if for some + * reason the decoder can not exist by itself (dead decoding + * or whatever), then we may have to add another vdec API + * to kill the vdec and release its HW resource and make it + * become inactive again. + * if ((core->active_vdec) && + * (core->active_vdec->status == VDEC_STATUS_DISCONNECTED)) { + * } + */ + + flags = vdec_core_lock(core); + + /* check disconnected decoders */ + list_for_each_entry_safe(vdec, tmp, + &core->connected_vdec_list, list) { + if ((vdec->status == VDEC_STATUS_CONNECTED) && + (vdec->next_status == VDEC_STATUS_DISCONNECTED)) { + if (core->active_vdec == vdec) + core->active_vdec = NULL; + list_move(&vdec->list, &disconnecting_list); + } + } + + /* activate next decoder instance if there is none */ + vdec = active_vdec(core); + + if (!vdec) { + /* + *round-robin decoder scheduling + * start from the decoder after previous active + * decoder instance, if not, then start from beginning + */ + if (core->active_vdec) + vdec = list_entry( + core->active_vdec->list.next, + struct vdec_s, list); + else + vdec = list_entry( + core->connected_vdec_list.next, + struct vdec_s, list); + + list_for_each_entry_from(vdec, + &core->connected_vdec_list, list) { + if (vdec_ready_to_run(vdec)) + break; + } + + if ((&vdec->list == &core->connected_vdec_list) && + (core->active_vdec)) { + /* search from beginning */ + list_for_each_entry(vdec, + &core->connected_vdec_list, list) { + if (vdec_ready_to_run(vdec)) + break; + + if (vdec == core->active_vdec) { + vdec = NULL; + break; + } + } + } + + if (&vdec->list == &core->connected_vdec_list) + vdec = NULL; + + core->active_vdec = NULL; + } + + vdec_core_unlock(core, flags); + + /* start the vdec instance */ + if ((vdec) && (vdec->status != VDEC_STATUS_ACTIVE)) { + vdec_set_status(vdec, VDEC_STATUS_ACTIVE); + + /* activatate the decoder instance to run */ + core->active_vdec = vdec; +#ifdef CONFIG_MULTI_DEC + vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN); +#endif + vdec->run(vdec, vdec_callback, core); + } + + /* remove disconnected decoder from active list */ + list_for_each_entry_safe(vdec, tmp, &disconnecting_list, list) { + list_del(&vdec->list); + vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); + complete(&vdec->inactive_done); + } + + if (!core->active_vdec) { + msleep(20); + up(&core->sem); + } + } + + return 0; +} + +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ +static bool test_hevc(u32 decomp_addr, u32 us_delay) +{ + int i; + + /* SW_RESET IPP */ + WRITE_VREG(HEVCD_IPP_TOP_CNTL, 1); + WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0); + + /* initialize all canvas table */ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0); + for (i = 0; i < 32; i++) + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + 0x1 | (i << 8) | decomp_addr); + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1); + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1); + for (i = 0; i < 32; i++) + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); + + /* Initialize mcrcc */ + WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); + WRITE_VREG(HEVCD_MCRCC_CTL2, 0x0); + WRITE_VREG(HEVCD_MCRCC_CTL3, 0x0); + WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); + + /* Decomp initialize */ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x0); + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0); + + /* Frame level initialization */ + WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG, 0x100 | (0x100 << 16)); + WRITE_VREG(HEVCD_IPP_TOP_TILECONFIG3, 0x0); + WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 0x1 << 5); + WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x2 | (0x2 << 2)); + + WRITE_VREG(HEVCD_IPP_CONFIG, 0x0); + WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, 0x0); + + /* Enable SWIMP mode */ + WRITE_VREG(HEVCD_IPP_SWMPREDIF_CONFIG, 0x1); + + /* Enable frame */ + WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x2); + WRITE_VREG(HEVCD_IPP_TOP_FRMCTL, 0x1); + + /* Send SW-command CTB info */ + WRITE_VREG(HEVCD_IPP_SWMPREDIF_CTBINFO, 0x1 << 31); + + /* Send PU_command */ + WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO0, (0x4 << 9) | (0x4 << 16)); + WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO1, 0x1 << 3); + WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO2, 0x0); + WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO3, 0x0); + + udelay(us_delay); + + WRITE_VREG(HEVCD_IPP_DBG_SEL, 0x2 << 4); + + return (READ_VREG(HEVCD_IPP_DBG_DATA) & 3) == 1; +} + +void vdec_poweron(enum vdec_type_e core) +{ + void *decomp_addr = NULL; + dma_addr_t decomp_dma_addr; + u32 decomp_addr_aligned = 0; + int hevc_loop = 0; + + if (core >= VDEC_MAX) + return; + + mutex_lock(&vdec_mutex); + + vdec_core->power_ref_count[core]++; + if (vdec_core->power_ref_count[core] > 1) { + mutex_unlock(&vdec_mutex); + return; + } + + if (vdec_on(core)) { + mutex_unlock(&vdec_mutex); + return; + } + + if (hevc_workaround_needed() && + (core == VDEC_HEVC)) { + decomp_addr = codec_mm_dma_alloc_coherent(MEM_NAME, + SZ_64K + SZ_4K, &decomp_dma_addr, GFP_KERNEL, 0); + + if (decomp_addr) { + decomp_addr_aligned = ALIGN(decomp_dma_addr, SZ_64K); + memset((u8 *)decomp_addr + + (decomp_addr_aligned - decomp_dma_addr), + 0xff, SZ_4K); + } else + pr_err("vdec: alloc HEVC gxbb decomp buffer failed.\n"); + } + + if (core == VDEC_1) { + /* vdec1 power on */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~0xc); + /* wait 10uS */ + udelay(10); + /* vdec1 soft reset */ + WRITE_VREG(DOS_SW_RESET0, 0xfffffffc); + WRITE_VREG(DOS_SW_RESET0, 0); + /* enable vdec1 clock */ + /* + *add power on vdec clock level setting,only for m8 chip, + * m8baby and m8m2 can dynamic adjust vdec clock, + * power on with default clock level + */ + vdec_clock_hi_enable(); + /* power up vdec memories */ + WRITE_VREG(DOS_MEM_PD_VDEC, 0); + /* remove vdec1 isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~0xC0); + /* reset DOS top registers */ + WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0); + if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXBB) { + /* + *enable VDEC_1 DMC request + */ + unsigned long flags; + + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); + } + } else if (core == VDEC_2) { + if (has_vdec2()) { + /* vdec2 power on */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + ~0x30); + /* wait 10uS */ + udelay(10); + /* vdec2 soft reset */ + WRITE_VREG(DOS_SW_RESET2, 0xffffffff); + WRITE_VREG(DOS_SW_RESET2, 0); + /* enable vdec1 clock */ + vdec2_clock_hi_enable(); + /* power up vdec memories */ + WRITE_VREG(DOS_MEM_PD_VDEC2, 0); + /* remove vdec2 isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + ~0x300); + /* reset DOS top registers */ + WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0); + } + } else if (core == VDEC_HCODEC) { + if (has_hdec()) { + /* hcodec power on */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + ~0x3); + /* wait 10uS */ + udelay(10); + /* hcodec soft reset */ + WRITE_VREG(DOS_SW_RESET1, 0xffffffff); + WRITE_VREG(DOS_SW_RESET1, 0); + /* enable hcodec clock */ + hcodec_clock_enable(); + /* power up hcodec memories */ + WRITE_VREG(DOS_MEM_PD_HCODEC, 0); + /* remove hcodec isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + ~0x30); + } + } else if (core == VDEC_HEVC) { + if (has_hevc_vdec()) { + bool hevc_fixed = false; + + while (!hevc_fixed) { + /* hevc power on */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + ~0xc0); + /* wait 10uS */ + udelay(10); + /* hevc soft reset */ + WRITE_VREG(DOS_SW_RESET3, 0xffffffff); + WRITE_VREG(DOS_SW_RESET3, 0); + /* enable hevc clock */ + hevc_clock_hi_enable(); + /* power up hevc memories */ + WRITE_VREG(DOS_MEM_PD_HEVC, 0); + /* remove hevc isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + ~0xc00); + + if (!hevc_workaround_needed()) + break; + + if (decomp_addr) + hevc_fixed = test_hevc( + decomp_addr_aligned, 20); + + if (!hevc_fixed) { + hevc_loop++; + + mutex_unlock(&vdec_mutex); + + if (hevc_loop >= HEVC_TEST_LIMIT) { + pr_warn("hevc power sequence over limit\n"); + pr_warn("=====================================================\n"); + pr_warn(" This chip is identified to have HW failure.\n"); + pr_warn(" Please contact sqa-platform to replace the platform.\n"); + pr_warn("=====================================================\n"); + + panic("Force panic for chip detection !!!\n"); + + break; + } + + vdec_poweroff(VDEC_HEVC); + + mdelay(10); + + mutex_lock(&vdec_mutex); + } + } + + if (hevc_loop > hevc_max_reset_count) + hevc_max_reset_count = hevc_loop; + + WRITE_VREG(DOS_SW_RESET3, 0xffffffff); + udelay(10); + WRITE_VREG(DOS_SW_RESET3, 0); + } + } + + if (decomp_addr) + codec_mm_dma_free_coherent(MEM_NAME, + SZ_64K + SZ_4K, decomp_addr, decomp_dma_addr, 0); + + mutex_unlock(&vdec_mutex); +} +EXPORT_SYMBOL(vdec_poweron); + +void vdec_poweroff(enum vdec_type_e core) +{ + if (core >= VDEC_MAX) + return; + + mutex_lock(&vdec_mutex); + + vdec_core->power_ref_count[core]--; + if (vdec_core->power_ref_count[core] > 0) { + mutex_unlock(&vdec_mutex); + return; + } + + if (core == VDEC_1) { + if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXBB) { + /* disable VDEC_1 DMC REQ*/ + unsigned long flags; + + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); + spin_unlock_irqrestore(&vdec_spin_lock, flags); + udelay(10); + } + /* enable vdec1 isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc0); + /* power off vdec1 memories */ + WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL); + /* disable vdec1 clock */ + vdec_clock_off(); + /* vdec1 power off */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc); + } else if (core == VDEC_2) { + if (has_vdec2()) { + /* enable vdec2 isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + 0x300); + /* power off vdec2 memories */ + WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL); + /* disable vdec2 clock */ + vdec2_clock_off(); + /* vdec2 power off */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | + 0x30); + } + } else if (core == VDEC_HCODEC) { + if (has_hdec()) { + /* enable hcodec isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + 0x30); + /* power off hcodec memories */ + WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); + /* disable hcodec clock */ + hcodec_clock_off(); + /* hcodec power off */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 3); + } + } else if (core == VDEC_HEVC) { + if (has_hevc_vdec()) { + /* enable hevc isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + 0xc00); + /* power off hevc memories */ + WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); + /* disable hevc clock */ + hevc_clock_off(); + /* hevc power off */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | + 0xc0); + } + } + mutex_unlock(&vdec_mutex); +} +EXPORT_SYMBOL(vdec_poweroff); + +bool vdec_on(enum vdec_type_e core) +{ + bool ret = false; + + if (core == VDEC_1) { + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0xc) == 0) && + (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100)) + ret = true; + } else if (core == VDEC_2) { + if (has_vdec2()) { + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x30) == 0) && + (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100)) + ret = true; + } + } else if (core == VDEC_HCODEC) { + if (has_hdec()) { + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x3) == 0) && + (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000)) + ret = true; + } + } else if (core == VDEC_HEVC) { + if (has_hevc_vdec()) { + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0xc0) == 0) && + (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000)) + ret = true; + } + } + + return ret; +} +EXPORT_SYMBOL(vdec_on); + +#elif 0 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ +void vdec_poweron(enum vdec_type_e core) +{ + ulong flags; + + spin_lock_irqsave(&lock, flags); + + if (core == VDEC_1) { + /* vdec1 soft reset */ + WRITE_VREG(DOS_SW_RESET0, 0xfffffffc); + WRITE_VREG(DOS_SW_RESET0, 0); + /* enable vdec1 clock */ + vdec_clock_enable(); + /* reset DOS top registers */ + WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0); + } else if (core == VDEC_2) { + /* vdec2 soft reset */ + WRITE_VREG(DOS_SW_RESET2, 0xffffffff); + WRITE_VREG(DOS_SW_RESET2, 0); + /* enable vdec2 clock */ + vdec2_clock_enable(); + /* reset DOS top registers */ + WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0); + } else if (core == VDEC_HCODEC) { + /* hcodec soft reset */ + WRITE_VREG(DOS_SW_RESET1, 0xffffffff); + WRITE_VREG(DOS_SW_RESET1, 0); + /* enable hcodec clock */ + hcodec_clock_enable(); + } + + spin_unlock_irqrestore(&lock, flags); +} + +void vdec_poweroff(enum vdec_type_e core) +{ + ulong flags; + + spin_lock_irqsave(&lock, flags); + + if (core == VDEC_1) { + /* disable vdec1 clock */ + vdec_clock_off(); + } else if (core == VDEC_2) { + /* disable vdec2 clock */ + vdec2_clock_off(); + } else if (core == VDEC_HCODEC) { + /* disable hcodec clock */ + hcodec_clock_off(); + } + + spin_unlock_irqrestore(&lock, flags); +} + +bool vdec_on(enum vdec_type_e core) +{ + bool ret = false; + + if (core == VDEC_1) { + if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100) + ret = true; + } else if (core == VDEC_2) { + if (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100) + ret = true; + } else if (core == VDEC_HCODEC) { + if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000) + ret = true; + } + + return ret; +} +#endif + +int vdec_source_changed(int format, int width, int height, int fps) +{ + /* todo: add level routines for clock adjustment per chips */ + int ret = -1; + static int on_setting; + + if (on_setting > 0) + return ret;/*on changing clk,ignore this change*/ + + if (vdec_source_get(VDEC_1) == width * height * fps) + return ret; + + + on_setting = 1; + ret = vdec_source_changed_for_clk_set(format, width, height, fps); + pr_info("vdec1 video changed to %d x %d %d fps clk->%dMHZ\n", + width, height, fps, vdec_clk_get(VDEC_1)); + on_setting = 0; + return ret; + +} +EXPORT_SYMBOL(vdec_source_changed); + +int vdec2_source_changed(int format, int width, int height, int fps) +{ + int ret = -1; + static int on_setting; + + if (has_vdec2()) { + /* todo: add level routines for clock adjustment per chips */ + if (on_setting != 0) + return ret;/*on changing clk,ignore this change*/ + + if (vdec_source_get(VDEC_2) == width * height * fps) + return ret; + + on_setting = 1; + ret = vdec_source_changed_for_clk_set(format, + width, height, fps); + pr_info("vdec2 video changed to %d x %d %d fps clk->%dMHZ\n", + width, height, fps, vdec_clk_get(VDEC_2)); + on_setting = 0; + return ret; + } + return 0; +} +EXPORT_SYMBOL(vdec2_source_changed); + +int hevc_source_changed(int format, int width, int height, int fps) +{ + /* todo: add level routines for clock adjustment per chips */ + int ret = -1; + static int on_setting; + + if (on_setting != 0) + return ret;/*on changing clk,ignore this change*/ + + if (vdec_source_get(VDEC_HEVC) == width * height * fps) + return ret; + + on_setting = 1; + ret = vdec_source_changed_for_clk_set(format, width, height, fps); + pr_info("hevc video changed to %d x %d %d fps clk->%dMHZ\n", + width, height, fps, vdec_clk_get(VDEC_HEVC)); + on_setting = 0; + + return ret; +} +EXPORT_SYMBOL(hevc_source_changed); + +static enum vdec2_usage_e vdec2_usage = USAGE_NONE; +void set_vdec2_usage(enum vdec2_usage_e usage) +{ + if (has_vdec2()) { + mutex_lock(&vdec_mutex); + vdec2_usage = usage; + mutex_unlock(&vdec_mutex); + } +} +EXPORT_SYMBOL(set_vdec2_usage); + +enum vdec2_usage_e get_vdec2_usage(void) +{ + if (has_vdec2()) + return vdec2_usage; + else + return 0; +} +EXPORT_SYMBOL(get_vdec2_usage); + +static struct am_reg am_risc[] = { + {"MSP", 0x300}, + {"MPSR", 0x301}, + {"MCPU_INT_BASE", 0x302}, + {"MCPU_INTR_GRP", 0x303}, + {"MCPU_INTR_MSK", 0x304}, + {"MCPU_INTR_REQ", 0x305}, + {"MPC-P", 0x306}, + {"MPC-D", 0x307}, + {"MPC_E", 0x308}, + {"MPC_W", 0x309}, + {"CSP", 0x320}, + {"CPSR", 0x321}, + {"CCPU_INT_BASE", 0x322}, + {"CCPU_INTR_GRP", 0x323}, + {"CCPU_INTR_MSK", 0x324}, + {"CCPU_INTR_REQ", 0x325}, + {"CPC-P", 0x326}, + {"CPC-D", 0x327}, + {"CPC_E", 0x328}, + {"CPC_W", 0x329}, + {"AV_SCRATCH_0", 0x09c0}, + {"AV_SCRATCH_1", 0x09c1}, + {"AV_SCRATCH_2", 0x09c2}, + {"AV_SCRATCH_3", 0x09c3}, + {"AV_SCRATCH_4", 0x09c4}, + {"AV_SCRATCH_5", 0x09c5}, + {"AV_SCRATCH_6", 0x09c6}, + {"AV_SCRATCH_7", 0x09c7}, + {"AV_SCRATCH_8", 0x09c8}, + {"AV_SCRATCH_9", 0x09c9}, + {"AV_SCRATCH_A", 0x09ca}, + {"AV_SCRATCH_B", 0x09cb}, + {"AV_SCRATCH_C", 0x09cc}, + {"AV_SCRATCH_D", 0x09cd}, + {"AV_SCRATCH_E", 0x09ce}, + {"AV_SCRATCH_F", 0x09cf}, + {"AV_SCRATCH_G", 0x09d0}, + {"AV_SCRATCH_H", 0x09d1}, + {"AV_SCRATCH_I", 0x09d2}, + {"AV_SCRATCH_J", 0x09d3}, + {"AV_SCRATCH_K", 0x09d4}, + {"AV_SCRATCH_L", 0x09d5}, + {"AV_SCRATCH_M", 0x09d6}, + {"AV_SCRATCH_N", 0x09d7}, +}; + +static ssize_t amrisc_regs_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + struct am_reg *regs = am_risc; + int rsize = sizeof(am_risc) / sizeof(struct am_reg); + int i; + unsigned val; + ssize_t ret; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + mutex_lock(&vdec_mutex); + if (!vdec_on(VDEC_1)) { + mutex_unlock(&vdec_mutex); + pbuf += sprintf(pbuf, "amrisc is power off\n"); + ret = pbuf - buf; + return ret; + } + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /*TODO:M6 define */ + /* + * switch_mod_gate_by_type(MOD_VDEC, 1); + */ + amports_switch_gate("vdec", 1); + } + pbuf += sprintf(pbuf, "amrisc registers show:\n"); + for (i = 0; i < rsize; i++) { + val = READ_VREG(regs[i].offset); + pbuf += sprintf(pbuf, "%s(%#x)\t:%#x(%d)\n", + regs[i].name, regs[i].offset, val, val); + } + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + mutex_unlock(&vdec_mutex); + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /*TODO:M6 define */ + /* + * switch_mod_gate_by_type(MOD_VDEC, 0); + */ + amports_switch_gate("vdec", 0); + } + ret = pbuf - buf; + return ret; +} + +static ssize_t dump_trace_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int i; + char *pbuf = buf; + ssize_t ret; + u16 *trace_buf = kmalloc(debug_trace_num * 2, GFP_KERNEL); + + if (!trace_buf) { + pbuf += sprintf(pbuf, "No Memory bug\n"); + ret = pbuf - buf; + return ret; + } + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + mutex_lock(&vdec_mutex); + if (!vdec_on(VDEC_1)) { + mutex_unlock(&vdec_mutex); + kfree(trace_buf); + pbuf += sprintf(pbuf, "amrisc is power off\n"); + ret = pbuf - buf; + return ret; + } + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /*TODO:M6 define */ + /* + * switch_mod_gate_by_type(MOD_VDEC, 1); + */ + amports_switch_gate("vdec", 1); + } + pr_info("dump trace steps:%d start\n", debug_trace_num); + i = 0; + while (i <= debug_trace_num - 16) { + trace_buf[i] = READ_VREG(MPC_E); + trace_buf[i + 1] = READ_VREG(MPC_E); + trace_buf[i + 2] = READ_VREG(MPC_E); + trace_buf[i + 3] = READ_VREG(MPC_E); + trace_buf[i + 4] = READ_VREG(MPC_E); + trace_buf[i + 5] = READ_VREG(MPC_E); + trace_buf[i + 6] = READ_VREG(MPC_E); + trace_buf[i + 7] = READ_VREG(MPC_E); + trace_buf[i + 8] = READ_VREG(MPC_E); + trace_buf[i + 9] = READ_VREG(MPC_E); + trace_buf[i + 10] = READ_VREG(MPC_E); + trace_buf[i + 11] = READ_VREG(MPC_E); + trace_buf[i + 12] = READ_VREG(MPC_E); + trace_buf[i + 13] = READ_VREG(MPC_E); + trace_buf[i + 14] = READ_VREG(MPC_E); + trace_buf[i + 15] = READ_VREG(MPC_E); + i += 16; + }; + pr_info("dump trace steps:%d finished\n", debug_trace_num); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + mutex_unlock(&vdec_mutex); + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /*TODO:M6 define */ + /* + * switch_mod_gate_by_type(MOD_VDEC, 0); + */ + amports_switch_gate("vdec", 0); + } + for (i = 0; i < debug_trace_num; i++) { + if (i % 4 == 0) { + if (i % 16 == 0) + pbuf += sprintf(pbuf, "\n"); + else if (i % 8 == 0) + pbuf += sprintf(pbuf, " "); + else /* 4 */ + pbuf += sprintf(pbuf, " "); + } + pbuf += sprintf(pbuf, "%04x:", trace_buf[i]); + } + while (i < debug_trace_num) + ; + kfree(trace_buf); + pbuf += sprintf(pbuf, "\n"); + ret = pbuf - buf; + return ret; +} + +static ssize_t clock_level_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + size_t ret; + + pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_1)); + + if (has_vdec2()) + pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_2)); + + if (has_hevc_vdec()) + pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_HEVC)); + + ret = pbuf - buf; + return ret; +} + +static ssize_t store_poweron_clock_level(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned val; + ssize_t ret; + + /*ret = sscanf(buf, "%d", &val);*/ + ret = kstrtoint(buf, 0, &val); + + if (ret != 0) + return -EINVAL; + poweron_clock_level = val; + return size; +} + +static ssize_t show_poweron_clock_level(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", poweron_clock_level); +} + +/* +*if keep_vdec_mem == 1 +*always don't release +*vdec 64 memory for fast play. +*/ +static ssize_t store_keep_vdec_mem(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned val; + ssize_t ret; + + /*ret = sscanf(buf, "%d", &val);*/ + ret = kstrtoint(buf, 0, &val); + if (ret != 0) + return -EINVAL; + keep_vdec_mem = val; + return size; +} + +static ssize_t show_keep_vdec_mem(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", keep_vdec_mem); +} + + +/*irq num as same as .dts*/ +/* +* interrupts = <0 3 1 +* 0 23 1 +* 0 32 1 +* 0 43 1 +* 0 44 1 +* 0 45 1>; +* interrupt-names = "vsync", +* "demux", +* "parser", +* "mailbox_0", +* "mailbox_1", +* "mailbox_2"; +*/ +s32 vdec_request_threaded_irq(enum vdec_irq_num num, + irq_handler_t handler, + irq_handler_t thread_fn, + unsigned long irqflags, + const char *devname, void *dev) +{ + s32 res_irq; + s32 ret = 0; + + if (num >= VDEC_IRQ_MAX) { + pr_err("[%s] request irq error, irq num too big!", __func__); + return -EINVAL; + } + + if (vdec_core->isr_context[num].irq < 0) { + res_irq = platform_get_irq( + vdec_core->vdec_core_platform_device, num); + if (res_irq < 0) { + pr_err("[%s] get irq error!", __func__); + return -EINVAL; + } + + vdec_core->isr_context[num].irq = res_irq; + vdec_core->isr_context[num].dev_isr = handler; + vdec_core->isr_context[num].dev_threaded_isr = thread_fn; + vdec_core->isr_context[num].dev_id = dev; + + ret = request_threaded_irq(res_irq, + vdec_isr, + vdec_thread_isr, + (thread_fn) ? IRQF_ONESHOT : irqflags, + devname, + &vdec_core->isr_context[num]); + + if (ret) { + vdec_core->isr_context[num].irq = -1; + vdec_core->isr_context[num].dev_isr = NULL; + vdec_core->isr_context[num].dev_threaded_isr = NULL; + vdec_core->isr_context[num].dev_id = NULL; + + pr_err("vdec irq register error for %s.\n", devname); + return -EIO; + } + } else { + vdec_core->isr_context[num].dev_isr = handler; + vdec_core->isr_context[num].dev_threaded_isr = thread_fn; + vdec_core->isr_context[num].dev_id = dev; + } + + return ret; +} +EXPORT_SYMBOL(vdec_request_threaded_irq); + +s32 vdec_request_irq(enum vdec_irq_num num, irq_handler_t handler, + const char *devname, void *dev) +{ + pr_info("vdec_request_irq %p, %s\n", handler, devname); + + return vdec_request_threaded_irq(num, + handler, + NULL,/*no thread_fn*/ + IRQF_SHARED, + devname, + dev); +} +EXPORT_SYMBOL(vdec_request_irq); + +void vdec_free_irq(enum vdec_irq_num num, void *dev) +{ + if (num >= VDEC_IRQ_MAX) { + pr_err("[%s] request irq error, irq num too big!", __func__); + return; + } + + synchronize_irq(vdec_core->isr_context[num].irq); + + /* + *assume amrisc is stopped already and there is no mailbox interrupt + * when we reset pointers here. + */ + vdec_core->isr_context[num].dev_isr = NULL; + vdec_core->isr_context[num].dev_threaded_isr = NULL; + vdec_core->isr_context[num].dev_id = NULL; +} +EXPORT_SYMBOL(vdec_free_irq); + +static int dump_mode; +static ssize_t dump_risc_mem_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size)/*set*/ +{ + unsigned val; + ssize_t ret; + char dump_mode_str[4] = "PRL"; + + /*ret = sscanf(buf, "%d", &val);*/ + ret = kstrtoint(buf, 0, &val); + + if (ret != 0) + return -EINVAL; + dump_mode = val & 0x3; + pr_info("set dump mode to %d,%c_mem\n", + dump_mode, dump_mode_str[dump_mode]); + return size; +} +static u32 read_amrisc_reg(int reg) +{ + WRITE_VREG(0x31b, reg); + return READ_VREG(0x31c); +} + +static void dump_pmem(void) +{ + int i; + + WRITE_VREG(0x301, 0x8000); + WRITE_VREG(0x31d, 0); + pr_info("start dump amrisc pmem of risc\n"); + for (i = 0; i < 0xfff; i++) { + /*same as .o format*/ + pr_info("%08x // 0x%04x:\n", read_amrisc_reg(i), i); + } +} + +static void dump_lmem(void) +{ + int i; + + WRITE_VREG(0x301, 0x8000); + WRITE_VREG(0x31d, 2); + pr_info("start dump amrisc lmem\n"); + for (i = 0; i < 0x3ff; i++) { + /*same as */ + pr_info("[%04x] = 0x%08x:\n", i, read_amrisc_reg(i)); + } +} + +static ssize_t dump_risc_mem_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + int ret; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + mutex_lock(&vdec_mutex); + if (!vdec_on(VDEC_1)) { + mutex_unlock(&vdec_mutex); + pbuf += sprintf(pbuf, "amrisc is power off\n"); + ret = pbuf - buf; + return ret; + } + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /*TODO:M6 define */ + /* + * switch_mod_gate_by_type(MOD_VDEC, 1); + */ + amports_switch_gate("vdec", 1); + } + /*start do**/ + switch (dump_mode) { + case 0: + dump_pmem(); + break; + case 2: + dump_lmem(); + break; + default: + break; + } + + /*done*/ + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + mutex_unlock(&vdec_mutex); + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /*TODO:M6 define */ + /* + * switch_mod_gate_by_type(MOD_VDEC, 0); + */ + amports_switch_gate("vdec", 0); + } + return sprintf(buf, "done\n"); +} + +static ssize_t core_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + struct vdec_core_s *core = vdec_core; + char *pbuf = buf; + + if (list_empty(&core->connected_vdec_list)) + pbuf += sprintf(pbuf, "connected vdec list empty\n"); + else { + struct vdec_s *vdec; + + list_for_each_entry(vdec, &core->connected_vdec_list, list) { + pbuf += sprintf(pbuf, + "\tvdec (%p (%s)), status = %s,\ttype = %s\n", + vdec, vdec_device_name[vdec->format * 2], + vdec_status_str(vdec), + vdec_type_str(vdec)); + } + } + + return pbuf - buf; +} + +static struct class_attribute vdec_class_attrs[] = { + __ATTR_RO(amrisc_regs), + __ATTR_RO(dump_trace), + __ATTR_RO(clock_level), + __ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP, + show_poweron_clock_level, store_poweron_clock_level), + __ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP, + dump_risc_mem_show, dump_risc_mem_store), + __ATTR(keep_vdec_mem, S_IRUGO | S_IWUSR | S_IWGRP, + show_keep_vdec_mem, store_keep_vdec_mem), + __ATTR_RO(core), + __ATTR_NULL +}; + +static struct class vdec_class = { + .name = "vdec", + .class_attrs = vdec_class_attrs, + }; + + +/* +*pre alloced enough memory for decoder +*fast start. +*/ +void pre_alloc_vdec_memory(void) +{ + if (!keep_vdec_mem || vdec_core->mem_start) + return; + + vdec_core->mem_start = codec_mm_alloc_for_dma(MEM_NAME, + CMA_ALLOC_SIZE / PAGE_SIZE, 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + if (!vdec_core->mem_start) + return; + pr_debug("vdec base memory alloced %p\n", + (void *)vdec_core->mem_start); + + vdec_core->mem_end = vdec_core->mem_start + CMA_ALLOC_SIZE - 1; + vdec_mem_alloced_from_codec = 1; + delay_release = 3; +} +EXPORT_SYMBOL(pre_alloc_vdec_memory); + +struct device *get_vdec_device(void) +{ + return &vdec_core->vdec_core_platform_device->dev; +} +EXPORT_SYMBOL(get_vdec_device); + +static int vdec_probe(struct platform_device *pdev) +{ + s32 i, r; + + vdec_core = (struct vdec_core_s *)devm_kzalloc(&pdev->dev, + sizeof(struct vdec_core_s), GFP_KERNEL); + if (vdec_core == NULL) { + pr_err("vdec core allocation failed.\n"); + return -ENOMEM; + } + + atomic_set(&vdec_core->vdec_nr, 0); + sema_init(&vdec_core->sem, 1); + + r = class_register(&vdec_class); + if (r) { + pr_info("vdec class create fail.\n"); + return r; + } + + vdec_core->vdec_core_platform_device = pdev; + + platform_set_drvdata(pdev, vdec_core); + + for (i = 0; i < VDEC_IRQ_MAX; i++) { + vdec_core->isr_context[i].index = i; + vdec_core->isr_context[i].irq = -1; + } + + r = vdec_request_threaded_irq(VDEC_IRQ_1, NULL, NULL, + IRQF_ONESHOT, "vdec-1", NULL); + if (r < 0) { + pr_err("vdec interrupt request failed\n"); + return r; + } + + r = of_reserved_mem_device_init(&pdev->dev); + if (r == 0) + pr_info("vdec_probe done\n"); + + vdec_core->cma_dev = &pdev->dev; + + if (get_cpu_type() < MESON_CPU_MAJOR_ID_M8) { + /* default to 250MHz */ + vdec_clock_hi_enable(); + } + + if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) { + /* set vdec dmc request to urgent */ + WRITE_DMCREG(DMC_AM5_CHAN_CTRL, 0x3f203cf); + } + if (codec_mm_get_reserved_size() >= 48 * SZ_1M + && codec_mm_get_reserved_size() <= 96 * SZ_1M) { +#ifdef CONFIG_MULTI_DEC + vdec_default_buf_size[VFORMAT_H264_4K2K * 2] = + codec_mm_get_reserved_size() / SZ_1M; +#else + vdec_default_buf_size[VFORMAT_H264_4K2K] = + codec_mm_get_reserved_size() / SZ_1M; +#endif + + /*all reserved size for prealloc*/ + } + pre_alloc_vdec_memory(); + + INIT_LIST_HEAD(&vdec_core->connected_vdec_list); + spin_lock_init(&vdec_core->lock); + + vdec_core->thread = kthread_run(vdec_core_thread, vdec_core, + "vdec-core"); + + return 0; +} + +static int vdec_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < VDEC_IRQ_MAX; i++) { + if (vdec_core->isr_context[i].irq >= 0) { + free_irq(vdec_core->isr_context[i].irq, + &vdec_core->isr_context[i]); + vdec_core->isr_context[i].irq = -1; + vdec_core->isr_context[i].dev_isr = NULL; + vdec_core->isr_context[i].dev_threaded_isr = NULL; + vdec_core->isr_context[i].dev_id = NULL; + } + } + + kthread_stop(vdec_core->thread); + + class_unregister(&vdec_class); + + return 0; +} + +static const struct of_device_id amlogic_vdec_dt_match[] = { + { + .compatible = "amlogic, vdec", + }, + {}, +}; + +static struct platform_driver vdec_driver = { + .probe = vdec_probe, + .remove = vdec_remove, + .driver = { + .name = "vdec", + .of_match_table = amlogic_vdec_dt_match, + } +}; + +int vdec_module_init(void) +{ + if (platform_driver_register(&vdec_driver)) { + pr_info("failed to register vdec module\n"); + return -ENODEV; + } + + return 0; +} +EXPORT_SYMBOL(vdec_module_init); + +void vdec_module_exit(void) +{ + platform_driver_unregister(&vdec_driver); +} +EXPORT_SYMBOL(vdec_module_exit); + +#if 0 +static int __init vdec_module_init(void) +{ + if (platform_driver_register(&vdec_driver)) { + pr_info("failed to register vdec module\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit vdec_module_exit(void) +{ + platform_driver_unregister(&vdec_driver); +} +#endif + +static int vdec_mem_device_init(struct reserved_mem *rmem, struct device *dev) +{ + unsigned long start, end; + + start = rmem->base; + end = rmem->base + rmem->size - 1; + pr_info("init vdec memsource %lx->%lx\n", start, end); + + vdec_core->mem_start = start; + vdec_core->mem_end = end; + vdec_core->cma_dev = dev; + + return 0; +} + +static const struct reserved_mem_ops rmem_vdec_ops = { + .device_init = vdec_mem_device_init, +}; + +static int __init vdec_mem_setup(struct reserved_mem *rmem) +{ + rmem->ops = &rmem_vdec_ops; + pr_info("vdec: reserved mem setup\n"); + + return 0; +} + +RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup); + +module_param(debug_trace_num, uint, 0664); +module_param(hevc_max_reset_count, int, 0664); +module_param(clk_config, uint, 0664); +module_param(step_mode, int, 0664); +/* +*module_init(vdec_module_init); +*module_exit(vdec_module_exit); +*/ +MODULE_DESCRIPTION("AMLOGIC vdec driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h new file mode 100644 index 000000000000..cb63f8d8fed2 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h @@ -0,0 +1,306 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/vdec.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VDEC_H +#define VDEC_H +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "vdec_input.h" + +s32 vdec_dev_register(void); +s32 vdec_dev_unregister(void); + +int vdec_source_changed(int format, int width, int height, int fps); +int vdec2_source_changed(int format, int width, int height, int fps); +int hevc_source_changed(int format, int width, int height, int fps); +struct device *get_vdec_device(void); +int vdec_module_init(void); +void vdec_module_exit(void); + +#define DEC_FLAG_HEVC_WORKAROUND 0x01 + +enum vdec_type_e { + VDEC_1 = 0, + VDEC_HCODEC, + VDEC_2, + VDEC_HEVC, + VDEC_MAX +}; + +extern void vdec2_power_mode(int level); +extern void vdec_poweron(enum vdec_type_e core); +extern void vdec_poweroff(enum vdec_type_e core); +extern bool vdec_on(enum vdec_type_e core); + +/*irq num as same as .dts*/ + +/* +* interrupts = <0 3 1 +* 0 23 1 +* 0 32 1 +* 0 43 1 +* 0 44 1 +* 0 45 1>; +* interrupt-names = "vsync", +* "demux", +* "parser", +* "mailbox_0", +* "mailbox_1", +* "mailbox_2"; +*/ +enum vdec_irq_num { + VSYNC_IRQ = 0, + DEMUX_IRQ, + PARSER_IRQ, + VDEC_IRQ_0, + VDEC_IRQ_1, + VDEC_IRQ_2, + VDEC_IRQ_MAX, +}; +extern s32 vdec_request_threaded_irq(enum vdec_irq_num num, + irq_handler_t handler, + irq_handler_t thread_fn, + unsigned long irqflags, + const char *devname, void *dev); +extern s32 vdec_request_irq(enum vdec_irq_num num, irq_handler_t handler, + const char *devname, void *dev); +extern void vdec_free_irq(enum vdec_irq_num num, void *dev); + +enum vdec2_usage_e { + USAGE_NONE, + USAGE_DEC_4K2K, + USAGE_ENCODE, +}; + +extern void set_vdec2_usage(enum vdec2_usage_e usage); +extern enum vdec2_usage_e get_vdec2_usage(void); + +extern void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size); +unsigned int get_vdec_clk_config_settings(void); +void update_vdec_clk_config_settings(unsigned int config); +//unsigned int get_mmu_mode(void);//DEBUG_TMP + +struct vdec_s; +enum vformat_t; + +/* stream based with single instance decoder driver */ +#define VDEC_TYPE_SINGLE 0 + +/* stream based with multi-instance decoder with HW resouce sharing */ +#define VDEC_TYPE_STREAM_PARSER 1 + +/* frame based with multi-instance decoder, input block list based */ +#define VDEC_TYPE_FRAME_BLOCK 2 + +/* frame based with multi-instance decoder, single circular input block */ +#define VDEC_TYPE_FRAME_CIRCULAR 3 + +/* decoder status: uninitialized */ +#define VDEC_STATUS_UNINITIALIZED 0 + +/* decoder status: before the decoder can start consuming data */ +#define VDEC_STATUS_DISCONNECTED 1 + +/* decoder status: decoder should become disconnected once it's not active */ +#define VDEC_STATUS_CONNECTED 2 + +/* decoder status: decoder owns HW resource and is running */ +#define VDEC_STATUS_ACTIVE 3 + +#define VDEC_PROVIDER_NAME_SIZE 16 +#define VDEC_RECEIVER_NAME_SIZE 16 +#define VDEC_MAP_NAME_SIZE 40 + +#define VDEC_FLAG_INPUT_KEEP_CONTEXT 0x01 + +struct vdec_s { + u32 magic; + struct list_head list; + int id; + + struct vdec_s *master; + struct vdec_s *slave; + struct stream_port_s *port; + int status; + int next_status; + int type; + int port_flag; + int format; + u32 pts; + u64 pts64; + bool pts_valid; + int flag; + int sched; + + struct completion inactive_done; + + /* config (temp) */ + unsigned long mem_start; + unsigned long mem_end; + + struct device *cma_dev; + struct platform_device *dev; + struct dec_sysinfo sys_info_store; + struct dec_sysinfo *sys_info; + + /* input */ + struct vdec_input_s input; + + /* mc cache */ + u32 mc[4096 * 4]; + bool mc_loaded; + + /* frame provider/receiver interface */ + char vf_provider_name[VDEC_PROVIDER_NAME_SIZE]; + struct vframe_provider_s vframe_provider; + char *vf_receiver_name; + char vfm_map_id[VDEC_MAP_NAME_SIZE]; + char vfm_map_chain[VDEC_MAP_NAME_SIZE]; + int vf_receiver_inst; + enum FRAME_BASE_VIDEO_PATH frame_base_video_path; + bool use_vfm_path; + char config[PAGE_SIZE]; + int config_len; + + /* canvas */ + int (*get_canvas)(unsigned int index, unsigned int base); + + int (*dec_status)(struct vdec_s *vdec, struct vdec_status *vstatus); + int (*set_trickmode)(struct vdec_s *vdec, unsigned long trickmode); + + bool (*run_ready)(struct vdec_s *vdec); + void (*run)(struct vdec_s *vdec, + void (*callback)(struct vdec_s *, void *), void *); + void (*reset)(struct vdec_s *vdec); + irqreturn_t (*irq_handler)(struct vdec_s *); + irqreturn_t (*threaded_irq_handler)(struct vdec_s *); + + /* private */ + void *private; /* decoder per instance specific data */ +}; + +/* common decoder vframe provider name to use default vfm path */ +#define VFM_DEC_PROVIDER_NAME "decoder" +#define VFM_DEC_DVBL_PROVIDER_NAME "dvbldec" +#define VFM_DEC_DVEL_PROVIDER_NAME "dveldec" + +#define hw_to_vdec(hw) ((struct vdec_s *) \ + (platform_get_drvdata(hw->platform_dev))) + +#define canvas_y(canvas) ((canvas) & 0xff) +#define canvas_u(canvas) (((canvas) >> 8) & 0xff) +#define canvas_v(canvas) (((canvas) >> 16) & 0xff) +#define canvas_y2(canvas) (((canvas) >> 16) & 0xff) +#define canvas_u2(canvas) (((canvas) >> 24) & 0xff) + +#define vdec_frame_based(vdec) \ + (((vdec)->type == VDEC_TYPE_FRAME_BLOCK) || \ + ((vdec)->type == VDEC_TYPE_FRAME_CIRCULAR)) +#define vdec_stream_based(vdec) \ + (((vdec)->type == VDEC_TYPE_STREAM_PARSER) || \ + ((vdec)->type == VDEC_TYPE_SINGLE)) +#define vdec_single(vdec) \ + ((vdec)->type == VDEC_TYPE_SINGLE) +#define vdec_dual(vdec) \ + ((vdec)->port->type & PORT_TYPE_DUALDEC) + +/* construct vdec strcture */ +extern struct vdec_s *vdec_create(struct stream_port_s *port, + struct vdec_s *master); + +/* set video format */ +extern int vdec_set_format(struct vdec_s *vdec, int format); + +/* set PTS */ +extern int vdec_set_pts(struct vdec_s *vdec, u32 pts); + +extern int vdec_set_pts64(struct vdec_s *vdec, u64 pts64); + +/* set vfm map when use frame base decoder */ +extern int vdec_set_video_path(struct vdec_s *vdec, int video_path); + +/* add frame data to input chain */ +extern int vdec_write_vframe(struct vdec_s *vdec, const char *buf, + size_t count); + +/* mark the vframe_chunk as consumed */ +extern void vdec_vframe_dirty(struct vdec_s *vdec, + struct vframe_chunk_s *chunk); + +/* prepare decoder input */ +extern int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p); + +/* clean decoder input */ +extern void vdec_clean_input(struct vdec_s *vdec); + +/* enable decoder input */ +extern void vdec_enable_input(struct vdec_s *vdec); + +/* allocate input chain + * register vdec_device + * create output, vfm or create ionvideo output + * insert vdec to vdec_manager for scheduling + */ +extern int vdec_connect(struct vdec_s *vdec); + +/* remove vdec from vdec_manager scheduling + * release input chain + * disconnect video output from ionvideo + */ +extern int vdec_disconnect(struct vdec_s *vdec); + +/* release vdec structure */ +extern int vdec_destroy(struct vdec_s *vdec); + +/* reset vdec */ +extern int vdec_reset(struct vdec_s *vdec); + +extern void vdec_set_status(struct vdec_s *vdec, int status); + +extern void vdec_set_next_status(struct vdec_s *vdec, int status); + +extern int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p); + +extern int vdec_init(struct vdec_s *vdec, int is_4k); + +extern void vdec_release(struct vdec_s *vdec); + +extern int vdec_status(struct vdec_s *vdec, struct vdec_status *vstatus); + +extern int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode); + +extern void vdec_set_flag(struct vdec_s *vdec, u32 flag); + +extern void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec); + +extern const char *vdec_status_str(struct vdec_s *vdec); + +extern const char *vdec_type_str(struct vdec_s *vdec); + +extern const char *vdec_device_name_str(struct vdec_s *vdec); + +#endif /* VDEC_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c new file mode 100644 index 000000000000..d6acac1e9bda --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c @@ -0,0 +1,544 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/vdec_input.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include + +#include "../../../stream_input/amports/amports_priv.h" +#include "vdec.h" +#include "vdec_input.h" + +#define VFRAME_BLOCK_SIZE (4*SZ_1M) +#define VFRAME_BLOCK_PAGESIZE (PAGE_ALIGN(VFRAME_BLOCK_SIZE)/PAGE_SIZE) +#define VFRAME_BLOCK_PAGEALIGN 4 +#define VFRAME_BLOCK_MAX_LEVEL (8*SZ_1M) +#define VFRAME_BLOCK_HOLE (SZ_64K) + +#define FRAME_PADDING_SIZE 1024U +#define MEM_NAME "VFRAME_INPUT" + +static int vframe_chunk_fill(struct vdec_input_s *input, + struct vframe_chunk_s *chunk, const char *buf, + size_t count, struct vframe_block_list_s *block) +{ + u8 *p = (u8 *)block->start_virt + block->wp; + + if (block->type == VDEC_TYPE_FRAME_BLOCK) { + if (copy_from_user(p, buf, count)) + return -EFAULT; + + p += count; + + memset(p, 0, FRAME_PADDING_SIZE); + + dma_sync_single_for_device(get_vdec_device(), + block->start + block->wp, + count + FRAME_PADDING_SIZE, DMA_TO_DEVICE); + + } else if (block->type == VDEC_TYPE_FRAME_CIRCULAR) { + size_t len = min((size_t)(block->size - block->wp), count); + u32 wp; + + if (copy_from_user(p, buf, len)) + return -EFAULT; + + dma_sync_single_for_device(get_vdec_device(), + block->start + block->wp, + len, DMA_TO_DEVICE); + + p += len; + + if (count > len) { + p = (u8 *)block->start_virt; + if (copy_from_user(p, buf, count - len)) + return -EFAULT; + + dma_sync_single_for_device(get_vdec_device(), + block->start, + count-len, DMA_TO_DEVICE); + + p += count - len; + } + + wp = block->wp + count; + if (wp >= block->size) + wp -= block->size; + + len = min(block->size - wp, FRAME_PADDING_SIZE); + + memset(p, 0, len); + + dma_sync_single_for_device(get_vdec_device(), + block->start + wp, + len, DMA_TO_DEVICE); + + if (len < FRAME_PADDING_SIZE) { + p = (u8 *)block->start_virt; + + memset(p, 0, count - len); + + dma_sync_single_for_device(get_vdec_device(), + block->start, + count - len, DMA_TO_DEVICE); + } + } + + return 0; +} + +static inline u32 vframe_block_space(struct vframe_block_list_s *block) +{ + if (block->type == VDEC_TYPE_FRAME_BLOCK) { + return block->size - block->wp; + } else { + return (block->rp >= block->wp) ? + (block->rp - block->wp) : + (block->rp - block->wp + block->size); + } +} + +static void vframe_block_add_chunk(struct vframe_block_list_s *block, + struct vframe_chunk_s *chunk) +{ + block->wp += chunk->size + FRAME_PADDING_SIZE; + if (block->wp >= block->size) + block->wp -= block->size; + block->chunk_count++; + chunk->block = block; + block->input->wr_block = block; + chunk->sequence = block->input->sequence; + block->input->sequence++; +} + +static void vframe_block_free_storage(struct vframe_block_list_s *block) +{ + if (block->addr) { + dma_unmap_single( + get_vdec_device(), + block->start, + VFRAME_BLOCK_PAGESIZE, + DMA_TO_DEVICE); + + codec_mm_free_for_dma(MEM_NAME, block->addr); + + block->addr = 0; + block->start_virt = NULL; + block->start = 0; + } + + block->size = 0; +} + +static int vframe_block_init_alloc_storage(struct vdec_input_s *input, + struct vframe_block_list_s *block) +{ + block->magic = 0x4b434c42; + block->input = input; + block->type = input->type; + + /* + * todo: for different type use different size + */ + block->addr = codec_mm_alloc_for_dma( + MEM_NAME, + VFRAME_BLOCK_PAGESIZE, + VFRAME_BLOCK_PAGEALIGN, + CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER); + + if (!block->addr) { + pr_err("Input block allocation failed\n"); + return -ENOMEM; + } + + block->start_virt = (void *)codec_mm_phys_to_virt(block->addr); + block->start = dma_map_single( + get_vdec_device(), + block->start_virt, + VFRAME_BLOCK_PAGESIZE, + DMA_TO_DEVICE); + block->size = VFRAME_BLOCK_PAGESIZE * PAGE_SIZE; + + return 0; +} + +void vdec_input_init(struct vdec_input_s *input, struct vdec_s *vdec) +{ + INIT_LIST_HEAD(&input->vframe_block_list); + INIT_LIST_HEAD(&input->vframe_chunk_list); + spin_lock_init(&input->lock); + + input->vdec = vdec; +} +EXPORT_SYMBOL(vdec_input_init); + +int vdec_input_set_buffer(struct vdec_input_s *input, u32 start, u32 size) +{ + if (input_frame_based(input)) + return -EINVAL; + + input->start = start; + input->size = size; + input->swap_page = alloc_page(GFP_KERNEL); + + if (input->swap_page == NULL) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL(vdec_input_set_buffer); + +void vdec_input_set_type(struct vdec_input_s *input, int type, int target) +{ + input->type = type; + input->target = target; +} +EXPORT_SYMBOL(vdec_input_set_type); + +int vdec_input_get_status(struct vdec_input_s *input, + struct vdec_input_status_s *status) +{ + unsigned long flags; + + if (input->vdec == NULL) + return -EINVAL; + + flags = vdec_input_lock(input); + + if (list_empty(&input->vframe_block_list)) { + status->size = VFRAME_BLOCK_SIZE; + status->data_len = 0; + status->free_len = VFRAME_BLOCK_SIZE; + status->read_pointer = 0; + } else { + int r = VFRAME_BLOCK_MAX_LEVEL - vdec_input_level(input) + - VFRAME_BLOCK_HOLE; + status->size = input->size; + status->data_len = vdec_input_level(input); + status->free_len = (r > 0) ? r : 0; + status->read_pointer = input->total_rd_count; + } + + vdec_input_unlock(input, flags); + + return 0; +} +EXPORT_SYMBOL(vdec_input_get_status); + +static void vdec_input_add_block(struct vdec_input_s *input, + struct vframe_block_list_s *block) +{ + unsigned long flags; + + flags = vdec_input_lock(input); + + list_add_tail(&block->list, &input->vframe_block_list); + input->size += block->size; + + vdec_input_unlock(input, flags); +} + +static void vdec_input_remove_block(struct vdec_input_s *input, + struct vframe_block_list_s *block) +{ + unsigned long flags; + + flags = vdec_input_lock(input); + + list_del(&block->list); + input->size -= block->size; + + vdec_input_unlock(input, flags); + + vframe_block_free_storage(block); + + kfree(block); + + pr_info("block %p removed\n", block); +} + +int vdec_input_level(struct vdec_input_s *input) +{ + return input->total_wr_count - input->total_rd_count; +} +EXPORT_SYMBOL(vdec_input_level); + +int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, + size_t count) +{ + unsigned long flags; + struct vframe_chunk_s *chunk; + struct vdec_s *vdec = input->vdec; + struct vframe_block_list_s *block = input->wr_block; + +#if 0 + if (add_count == 0) { + add_count++; + memcpy(sps, buf, 30); + return 30; + } else if (add_count == 1) { + add_count++; + memcpy(pps, buf, 8); + return 8; + } + add_count++; +#endif + +#if 0 + pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count); + + if (count >= 8) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + } + if (count >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15]); + } + if (count >= 24) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23]); + } + if (count >= 32) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31]); + } +#endif + if (input_stream_based(input)) + return -EINVAL; + + /* prepare block to write */ + if ((!block) || (block && + (vframe_block_space(block) < (count + FRAME_PADDING_SIZE)))) { + /* switch to another block for the added chunk */ + struct vframe_block_list_s *new_block; + +#if 0 + pr_info("Adding new block, total level = %d, total_wr_count=%d, total_rd_count=%d\n", + vdec_input_level(input), + (int)input->total_wr_count, + (int)input->total_rd_count); +#endif + + if ((!list_empty(&input->vframe_block_list)) && + (block->type == VDEC_TYPE_FRAME_CIRCULAR)) + return -EAGAIN; + /* + *todo: add input limit check for + * VDEC_TYPE_FRAME_BLOCK + */ + if (vdec_input_level(input) > + VFRAME_BLOCK_MAX_LEVEL) { + pr_info("vdec_input %p reaching max size\n", + input); + return -EAGAIN; + } + + /* + *check next block of current wr_block, it should be an empty + * block to use + */ + if ((block) && (!list_is_last( + &block->list, &input->vframe_block_list))) { + block = list_next_entry(block, list); + + if (vframe_block_space(block) != VFRAME_BLOCK_SIZE) + /* should never happen */ + pr_err("next writing block not empty.\n"); + } else { + /* add a new block into input list */ + new_block = kzalloc(sizeof(struct vframe_block_list_s), + GFP_KERNEL); + if (new_block == NULL) { + pr_err("vframe_block structure allocation failed\n"); + return -EAGAIN; + } + + if (vframe_block_init_alloc_storage(input, + new_block) != 0) { + kfree(new_block); + pr_err("vframe_block storage allocation failed\n"); + return -EAGAIN; + } + + INIT_LIST_HEAD(&new_block->list); + + vdec_input_add_block(input, new_block); + + /* pr_info("added new block %p\n", new_block); */ + + block = new_block; + } + } + + chunk = kzalloc(sizeof(struct vframe_chunk_s), GFP_KERNEL); + + if (!chunk) { + pr_err("vframe_chunk structure allocation failed\n"); + return -ENOMEM; + } + + chunk->magic = 0x4b554843; + if (vdec->pts_valid) { + chunk->pts = vdec->pts; + chunk->pts64 = vdec->pts64; + } + chunk->pts_valid = vdec->pts_valid; + vdec->pts_valid = false; + chunk->offset = block->wp; + chunk->size = count; + + INIT_LIST_HEAD(&chunk->list); + + if (vframe_chunk_fill(input, chunk, buf, count, block)) { + pr_err("vframe_chunk_fill failed\n"); + kfree(chunk); + return -EFAULT; + } + + flags = vdec_input_lock(input); + + vframe_block_add_chunk(block, chunk); + + list_add_tail(&chunk->list, &input->vframe_chunk_list); + + vdec_input_unlock(input, flags); + + input->total_wr_count += count; + +#if 0 + if (add_count == 2) + input->total_wr_count += 38; +#endif + + return count; +} +EXPORT_SYMBOL(vdec_input_add_frame); + +struct vframe_chunk_s *vdec_input_next_chunk(struct vdec_input_s *input) +{ + if (list_empty(&input->vframe_chunk_list)) + return NULL; + + return list_first_entry(&input->vframe_chunk_list, + struct vframe_chunk_s, list); +} +EXPORT_SYMBOL(vdec_input_next_chunk); + +struct vframe_chunk_s *vdec_input_next_input_chunk( + struct vdec_input_s *input) +{ + struct vframe_chunk_s *chunk = NULL; + struct list_head *p; + + list_for_each(p, &input->vframe_chunk_list) { + struct vframe_chunk_s *c = list_entry( + p, struct vframe_chunk_s, list); + if ((c->flag & VFRAME_CHUNK_FLAG_CONSUMED) == 0) { + chunk = c; + break; + } + } + + return chunk; +} +EXPORT_SYMBOL(vdec_input_next_input_chunk); + +void vdec_input_release_chunk(struct vdec_input_s *input, + struct vframe_chunk_s *chunk) +{ + unsigned long flags; + struct vframe_block_list_s *block = chunk->block; + + flags = vdec_input_lock(input); + + list_del(&chunk->list); + + block->rp += chunk->size; + if (block->rp >= block->size) + block->rp -= block->size; + block->chunk_count--; + input->total_rd_count += chunk->size; + + if (block->chunk_count == 0) { + /* reuse the block */ + block->wp = 0; + block->rp = 0; + + if ((input->wr_block == block) && + (!list_is_last(&block->list, + &input->vframe_block_list))) + input->wr_block = list_next_entry(block, list); + + list_move_tail(&block->list, &input->vframe_block_list); + } + + vdec_input_unlock(input, flags); + + kfree(chunk); +} +EXPORT_SYMBOL(vdec_input_release_chunk); + +unsigned long vdec_input_lock(struct vdec_input_s *input) +{ + unsigned long flags; + + spin_lock_irqsave(&input->lock, flags); + + return flags; +} +EXPORT_SYMBOL(vdec_input_lock); + +void vdec_input_unlock(struct vdec_input_s *input, unsigned long flags) +{ + spin_unlock_irqrestore(&input->lock, flags); +} +EXPORT_SYMBOL(vdec_input_unlock); + +void vdec_input_release(struct vdec_input_s *input) +{ + struct list_head *p, *tmp; + + /* release chunk data */ + list_for_each_safe(p, tmp, &input->vframe_chunk_list) { + struct vframe_chunk_s *chunk = list_entry( + p, struct vframe_chunk_s, list); + vdec_input_release_chunk(input, chunk); + } + + /* release input blocks */ + list_for_each_safe(p, tmp, &input->vframe_block_list) { + struct vframe_block_list_s *block = list_entry( + p, struct vframe_block_list_s, list); + vdec_input_remove_block(input, block); + } + + /* release swap page */ + if (input->swap_page) { + __free_page(input->swap_page); + input->swap_page = NULL; + input->swap_valid = false; + } +} +EXPORT_SYMBOL(vdec_input_release); + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h new file mode 100644 index 000000000000..b029b8915452 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h @@ -0,0 +1,131 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/vdec_input.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VDEC_INPUT_H +#define VDEC_INPUT_H + +struct vdec_s; +struct vdec_input_s; + +struct vframe_block_list_s { + u32 magic; + struct list_head list; + ulong start; + void *start_virt; + ulong addr; + int type; + u32 size; + u32 wp; + u32 rp; + int chunk_count; + struct vdec_input_s *input; +}; + +#define VFRAME_CHUNK_FLAG_CONSUMED 0x0001 + +struct vframe_chunk_s { + u32 magic; + struct list_head list; + int flag; + u32 offset; + u32 size; + u32 pts; + u64 pts64; + bool pts_valid; + u64 sequence; + struct vframe_block_list_s *block; +}; + +#define VDEC_INPUT_TARGET_VLD 0 +#define VDEC_INPUT_TARGET_HEVC 1 + +struct vdec_input_s { + struct list_head vframe_block_list; + struct list_head vframe_chunk_list; + struct vframe_block_list_s *wr_block; + spinlock_t lock; + int type; + int target; + struct vdec_s *vdec; + bool swap_valid; + bool swap_needed; + struct page *swap_page; + int total_wr_count; + int total_rd_count; + u64 sequence; + unsigned start; + unsigned size; + int stream_cookie; /* wrap count for vld_mem and*/ + /*HEVC_SHIFT_BYTE_COUNT for hevc */ +}; + +struct vdec_input_status_s { + int size; + int data_len; + int free_len; + int read_pointer; +}; + +#define input_frame_based(input) \ + (((input)->type == VDEC_TYPE_FRAME_BLOCK) || \ + ((input)->type == VDEC_TYPE_FRAME_CIRCULAR)) +#define input_stream_based(input) \ + (((input)->type == VDEC_TYPE_STREAM_PARSER) || \ + ((input)->type == VDEC_TYPE_SINGLE)) + +/* Initialize vdec_input structure */ +extern void vdec_input_init(struct vdec_input_s *input, struct vdec_s *vdec); + +/* Get available input data size */ +extern int vdec_input_level(struct vdec_input_s *input); + +/* Set input type and target */ +extern void vdec_input_set_type(struct vdec_input_s *input, int type, + int target); + +/* Set stream buffer information for stream based input */ +extern int vdec_input_set_buffer(struct vdec_input_s *input, u32 start, + u32 size); + +/* Add enqueue video data into decoder's input */ +extern int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, + size_t count); + +/* Peek next frame data from decoder's input */ +extern struct vframe_chunk_s *vdec_input_next_chunk( + struct vdec_input_s *input); + +/* Peek next frame data from decoder's input, not marked as consumed */ +extern struct vframe_chunk_s *vdec_input_next_input_chunk( + struct vdec_input_s *input); + +/* Consume next frame data from decoder's input */ +extern void vdec_input_release_chunk(struct vdec_input_s *input, + struct vframe_chunk_s *chunk); + +/* Get decoder input buffer status */ +extern int vdec_input_get_status(struct vdec_input_s *input, + struct vdec_input_status_s *status); + +extern unsigned long vdec_input_lock(struct vdec_input_s *input); + +extern void vdec_input_unlock(struct vdec_input_s *input, unsigned long lock); + +/* release all resource for decoder's input */ +extern void vdec_input_release(struct vdec_input_s *input); + +#endif /* VDEC_INPUT_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c new file mode 100644 index 000000000000..3495d927eebe --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c @@ -0,0 +1,1170 @@ +/* + * drivers/amlogic/amports/vvc1.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../utils/amvdec.h" +#include "../utils/vdec.h" +#include +#include "../../../stream_input/amports/amports_priv.h" + +#define DRIVER_NAME "amvdec_vc1" +#define MODULE_NAME "amvdec_vc1" + +#define DEBUG_PTS +#if 1 /* //MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +#endif + +#define I_PICTURE 0 +#define P_PICTURE 1 +#define B_PICTURE 2 + +#define ORI_BUFFER_START_ADDR 0x01000000 + +#define INTERLACE_FLAG 0x80 +#define BOTTOM_FIELD_FIRST_FLAG 0x40 + +/* protocol registers */ +#define VC1_PIC_RATIO AV_SCRATCH_0 +#define VC1_ERROR_COUNT AV_SCRATCH_6 +#define VC1_SOS_COUNT AV_SCRATCH_7 +#define VC1_BUFFERIN AV_SCRATCH_8 +#define VC1_BUFFEROUT AV_SCRATCH_9 +#define VC1_REPEAT_COUNT AV_SCRATCH_A +#define VC1_TIME_STAMP AV_SCRATCH_B +#define VC1_OFFSET_REG AV_SCRATCH_C +#define MEM_OFFSET_REG AV_SCRATCH_F + +#define VF_POOL_SIZE 32 +#define DECODE_BUFFER_NUM_MAX 8 +#define PUT_INTERVAL (HZ/100) + +#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* TODO: move to register headers */ +#define VPP_VD1_POSTBLEND (1 << 10) +#define MEM_FIFO_CNT_BIT 16 +#define MEM_LEVEL_CNT_BIT 18 +#endif + +static struct vframe_s *vvc1_vf_peek(void *); +static struct vframe_s *vvc1_vf_get(void *); +static void vvc1_vf_put(struct vframe_s *, void *); +static int vvc1_vf_states(struct vframe_states *states, void *); +static int vvc1_event_cb(int type, void *data, void *private_data); + +static void vvc1_prot_init(void); +static void vvc1_local_init(void); + +static const char vvc1_dec_id[] = "vvc1-dev"; + +#define PROVIDER_NAME "decoder.vc1" +static const struct vframe_operations_s vvc1_vf_provider = { + .peek = vvc1_vf_peek, + .get = vvc1_vf_get, + .put = vvc1_vf_put, + .event_cb = vvc1_event_cb, + .vf_states = vvc1_vf_states, +}; + +static struct vframe_provider_s vvc1_vf_prov; + +static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); +static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); + +static struct vframe_s vfpool[VF_POOL_SIZE]; +static struct vframe_s vfpool2[VF_POOL_SIZE]; +static int cur_pool_idx; + +static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; +static struct timer_list recycle_timer; +static u32 stat; +static unsigned long buf_start; +static u32 buf_size, buf_offset; +static u32 avi_flag; +static u32 vvc1_ratio; +static u32 vvc1_format; + +static u32 intra_output; +static u32 frame_width, frame_height, frame_dur; +static u32 saved_resolution; +static u32 pts_by_offset = 1; +static u32 total_frame; +static u32 next_pts; +static u64 next_pts_us64; + +#ifdef DEBUG_PTS +static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; +#endif +static DEFINE_SPINLOCK(lock); + +static struct dec_sysinfo vvc1_amstream_dec_info; + +struct frm_s { + int state; + u32 start_pts; + int num; + u32 end_pts; + u32 rate; + u32 trymax; +}; + +static struct frm_s frm; + +enum { + RATE_MEASURE_START_PTS = 0, + RATE_MEASURE_END_PTS, + RATE_MEASURE_DONE +}; +#define RATE_MEASURE_NUM 8 +#define RATE_CORRECTION_THRESHOLD 5 +#define RATE_24_FPS 3755 /* 23.97 */ +#define RATE_30_FPS 3003 /* 29.97 */ +#define DUR2PTS(x) ((x)*90/96) +#define PTS2DUR(x) ((x)*96/90) + +static inline int pool_index(struct vframe_s *vf) +{ + if ((vf >= &vfpool[0]) && (vf <= &vfpool[VF_POOL_SIZE - 1])) + return 0; + else if ((vf >= &vfpool2[0]) && (vf <= &vfpool2[VF_POOL_SIZE - 1])) + return 1; + else + return -1; +} + +static inline bool close_to(int a, int b, int m) +{ + return abs(a - b) < m; +} + +static inline u32 index2canvas(u32 index) +{ + const u32 canvas_tab[DECODE_BUFFER_NUM_MAX] = { +#if 1 /* ALWASY.MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + 0x010100, 0x030302, 0x050504, 0x070706, + 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e +#else + 0x020100, 0x050403, 0x080706, 0x0b0a09 +#endif + }; + + return canvas_tab[index]; +} + +static void set_aspect_ratio(struct vframe_s *vf, unsigned pixel_ratio) +{ + int ar = 0; + + if (vvc1_ratio == 0) { + /* always stretch to 16:9 */ + vf->ratio_control |= (0x90 << DISP_RATIO_ASPECT_RATIO_BIT); + } else if (pixel_ratio > 0x0f) { + ar = (vvc1_amstream_dec_info.height * (pixel_ratio & 0xff) * + vvc1_ratio) / (vvc1_amstream_dec_info.width * + (pixel_ratio >> 8)); + } else { + switch (pixel_ratio) { + case 0: + ar = (vvc1_amstream_dec_info.height * vvc1_ratio) / + vvc1_amstream_dec_info.width; + break; + case 1: + ar = (vf->height * vvc1_ratio) / vf->width; + break; + case 2: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 12); + break; + case 3: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 10); + break; + case 4: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 16); + break; + case 5: + ar = (vf->height * 33 * vvc1_ratio) / (vf->width * 40); + break; + case 6: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 24); + break; + case 7: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 20); + break; + case 8: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 32); + break; + case 9: + ar = (vf->height * 33 * vvc1_ratio) / (vf->width * 80); + break; + case 10: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 18); + break; + case 11: + ar = (vf->height * 11 * vvc1_ratio) / (vf->width * 15); + break; + case 12: + ar = (vf->height * 33 * vvc1_ratio) / (vf->width * 64); + break; + case 13: + ar = (vf->height * 99 * vvc1_ratio) / + (vf->width * 160); + break; + default: + ar = (vf->height * vvc1_ratio) / vf->width; + break; + } + } + + ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); + + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + /*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO;*/ +} + +static irqreturn_t vvc1_isr(int irq, void *dev_id) +{ + u32 reg; + struct vframe_s *vf = NULL; + u32 repeat_count; + u32 picture_type; + u32 buffer_index; + unsigned int pts, pts_valid = 0, offset; + u32 v_width, v_height; + u64 pts_us64 = 0; + + reg = READ_VREG(VC1_BUFFEROUT); + + if (reg) { + v_width = READ_VREG(AV_SCRATCH_J); + v_height = READ_VREG(AV_SCRATCH_K); + + if (v_width && v_width <= 4096 + && (v_width != vvc1_amstream_dec_info.width)) { + pr_info("frame width changed %d to %d\n", + vvc1_amstream_dec_info.width, v_width); + vvc1_amstream_dec_info.width = v_width; + frame_width = v_width; + } + if (v_height && v_height <= 4096 + && (v_height != vvc1_amstream_dec_info.height)) { + pr_info("frame height changed %d to %d\n", + vvc1_amstream_dec_info.height, v_height); + vvc1_amstream_dec_info.height = v_height; + frame_height = v_height; + } + + if (pts_by_offset) { + offset = READ_VREG(VC1_OFFSET_REG); + if (pts_lookup_offset_us64( + PTS_TYPE_VIDEO, + offset, &pts, 0, &pts_us64) == 0) { + pts_valid = 1; +#ifdef DEBUG_PTS + pts_hit++; +#endif + } else { +#ifdef DEBUG_PTS + pts_missed++; +#endif + } + } + + repeat_count = READ_VREG(VC1_REPEAT_COUNT); + buffer_index = reg & 0x7; + picture_type = (reg >> 3) & 7; + + if (buffer_index >= DECODE_BUFFER_NUM_MAX) { + pr_info("fatal error, invalid buffer index."); + return IRQ_HANDLED; + } + + if ((intra_output == 0) && (picture_type != 0)) { + WRITE_VREG(VC1_BUFFERIN, ~(1 << buffer_index)); + WRITE_VREG(VC1_BUFFEROUT, 0); + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + return IRQ_HANDLED; + } + + intra_output = 1; + +#ifdef DEBUG_PTS + if (picture_type == I_PICTURE) { + /* pr_info("I offset 0x%x, + pts_valid %d\n", offset, pts_valid); */ + if (!pts_valid) + pts_i_missed++; + else + pts_i_hit++; + } +#endif + + if ((pts_valid) && (frm.state != RATE_MEASURE_DONE)) { + if (frm.state == RATE_MEASURE_START_PTS) { + frm.start_pts = pts; + frm.state = RATE_MEASURE_END_PTS; + frm.trymax = RATE_MEASURE_NUM; + } else if (frm.state == RATE_MEASURE_END_PTS) { + if (frm.num >= frm.trymax) { + frm.end_pts = pts; + frm.rate = (frm.end_pts - + frm.start_pts) / frm.num; + pr_info("frate before=%d,%d,num=%d\n", + frm.rate, + DUR2PTS(vvc1_amstream_dec_info.rate), + frm.num); + /* check if measured rate is same as + * settings from upper layer + * and correct it if necessary */ + if ((close_to(frm.rate, RATE_30_FPS, + RATE_CORRECTION_THRESHOLD) && + close_to( + DUR2PTS( + vvc1_amstream_dec_info.rate), + RATE_24_FPS, + RATE_CORRECTION_THRESHOLD)) + || + (close_to( + frm.rate, RATE_24_FPS, + RATE_CORRECTION_THRESHOLD) + && + close_to(DUR2PTS( + vvc1_amstream_dec_info.rate), + RATE_30_FPS, + RATE_CORRECTION_THRESHOLD))) { + pr_info( + "vvc1: frate from %d to %d\n", + vvc1_amstream_dec_info.rate, + PTS2DUR(frm.rate)); + + vvc1_amstream_dec_info.rate = + PTS2DUR(frm.rate); + frm.state = RATE_MEASURE_DONE; + } else if (close_to(frm.rate, + DUR2PTS( + vvc1_amstream_dec_info.rate), + RATE_CORRECTION_THRESHOLD)) + frm.state = RATE_MEASURE_DONE; + else { /*maybe still have problem, + try next double frames.... */ + frm.state = RATE_MEASURE_DONE; + frm.start_pts = pts; + frm.state = + RATE_MEASURE_END_PTS; + /*60 fps*60 S */ + frm.num = 0; + } + } + } + } + + if (frm.state != RATE_MEASURE_DONE) + frm.num += (repeat_count > 1) ? repeat_count : 1; + if (0 == vvc1_amstream_dec_info.rate) + vvc1_amstream_dec_info.rate = PTS2DUR(frm.rate); + + if (reg & INTERLACE_FLAG) { /* interlace */ + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = vvc1_amstream_dec_info.width; + vf->height = vvc1_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + + if (pts_valid) { + vf->pts = pts; + vf->pts_us64 = pts_us64; + if ((repeat_count > 1) && avi_flag) { + vf->duration = + vvc1_amstream_dec_info.rate * + repeat_count >> 1; + next_pts = pts + + (vvc1_amstream_dec_info.rate * + repeat_count >> 1) * 15 / 16; + next_pts_us64 = pts_us64 + + ((vvc1_amstream_dec_info.rate * + repeat_count >> 1) * 15 / 16) * + 100 / 9; + } else { + vf->duration = + vvc1_amstream_dec_info.rate >> 1; + next_pts = 0; + next_pts_us64 = 0; + } + } else { + vf->pts = next_pts; + vf->pts_us64 = next_pts_us64; + if ((repeat_count > 1) && avi_flag) { + vf->duration = + vvc1_amstream_dec_info.rate * + repeat_count >> 1; + if (next_pts != 0) { + next_pts += ((vf->duration) - + ((vf->duration) >> 4)); + } + if (next_pts_us64 != 0) { + next_pts_us64 += + ((vf->duration) - + ((vf->duration) >> 4)) * + 100 / 9; + } + } else { + vf->duration = + vvc1_amstream_dec_info.rate >> 1; + next_pts = 0; + next_pts_us64 = 0; + } + } + + vf->duration_pulldown = 0; + vf->type = (reg & BOTTOM_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->orientation = 0; + vf->type_original = vf->type; + set_aspect_ratio(vf, READ_VREG(VC1_PIC_RATIO)); + + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver( + PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = vvc1_amstream_dec_info.width; + vf->height = vvc1_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + + vf->pts = next_pts; + vf->pts_us64 = next_pts_us64; + if ((repeat_count > 1) && avi_flag) { + vf->duration = + vvc1_amstream_dec_info.rate * + repeat_count >> 1; + if (next_pts != 0) { + next_pts += + ((vf->duration) - + ((vf->duration) >> 4)); + } + if (next_pts_us64 != 0) { + next_pts_us64 += ((vf->duration) - + ((vf->duration) >> 4)) * 100 / 9; + } + } else { + vf->duration = + vvc1_amstream_dec_info.rate >> 1; + next_pts = 0; + next_pts_us64 = 0; + } + + vf->duration_pulldown = 0; + vf->type = (reg & BOTTOM_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->orientation = 0; + vf->type_original = vf->type; + set_aspect_ratio(vf, READ_VREG(VC1_PIC_RATIO)); + + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver( + PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } else { /* progressive */ + if (kfifo_get(&newframe_q, &vf) == 0) { + pr_info + ("fatal error, no available buffer slot."); + return IRQ_HANDLED; + } + vf->signal_type = 0; + vf->index = buffer_index; + vf->width = vvc1_amstream_dec_info.width; + vf->height = vvc1_amstream_dec_info.height; + vf->bufWidth = 1920; + vf->flag = 0; + + if (pts_valid) { + vf->pts = pts; + vf->pts_us64 = pts_us64; + if ((repeat_count > 1) && avi_flag) { + vf->duration = + vvc1_amstream_dec_info.rate * + repeat_count; + next_pts = + pts + + (vvc1_amstream_dec_info.rate * + repeat_count) * 15 / 16; + next_pts_us64 = pts_us64 + + ((vvc1_amstream_dec_info.rate * + repeat_count) * 15 / 16) * + 100 / 9; + } else { + vf->duration = + vvc1_amstream_dec_info.rate; + next_pts = 0; + next_pts_us64 = 0; + } + } else { + vf->pts = next_pts; + vf->pts_us64 = next_pts_us64; + if ((repeat_count > 1) && avi_flag) { + vf->duration = + vvc1_amstream_dec_info.rate * + repeat_count; + if (next_pts != 0) { + next_pts += ((vf->duration) - + ((vf->duration) >> 4)); + } + if (next_pts_us64 != 0) { + next_pts_us64 += + ((vf->duration) - + ((vf->duration) >> 4)) * + 100 / 9; + } + } else { + vf->duration = + vvc1_amstream_dec_info.rate; + next_pts = 0; + next_pts_us64 = 0; + } + } + + vf->duration_pulldown = 0; +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + vf->canvas0Addr = vf->canvas1Addr = + index2canvas(buffer_index); + vf->orientation = 0; + vf->type_original = vf->type; + set_aspect_ratio(vf, READ_VREG(VC1_PIC_RATIO)); + + vfbuf_use[buffer_index]++; + + kfifo_put(&display_q, (const struct vframe_s *)vf); + + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + frame_dur = vvc1_amstream_dec_info.rate; + total_frame++; + + /* pr_info("PicType = %d, PTS = 0x%x, repeat + count %d\n", picture_type, vf->pts, repeat_count); */ + WRITE_VREG(VC1_BUFFEROUT, 0); + } + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + return IRQ_HANDLED; +} + +static struct vframe_s *vvc1_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_peek(&display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vvc1_vf_get(void *op_arg) +{ + struct vframe_s *vf; + + if (kfifo_get(&display_q, &vf)) + return vf; + + return NULL; +} + +static void vvc1_vf_put(struct vframe_s *vf, void *op_arg) +{ + if (pool_index(vf) == cur_pool_idx) + kfifo_put(&recycle_q, (const struct vframe_s *)vf); +} + +static int vvc1_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&newframe_q); + states->buf_avail_num = kfifo_len(&display_q); + states->buf_recycle_num = kfifo_len(&recycle_q); + + spin_unlock_irqrestore(&lock, flags); + + return 0; +} + +static int vvc1_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { + unsigned long flags; + amvdec_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vvc1_vf_prov); +#endif + spin_lock_irqsave(&lock, flags); + vvc1_local_init(); + vvc1_prot_init(); + spin_unlock_irqrestore(&lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vvc1_vf_prov); +#endif + amvdec_start(); + } + return 0; +} + +int vvc1_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + vstatus->width = vvc1_amstream_dec_info.width; + vstatus->height = vvc1_amstream_dec_info.height; + if (0 != vvc1_amstream_dec_info.rate) + vstatus->fps = 96000 / vvc1_amstream_dec_info.rate; + else + vstatus->fps = 96000; + vstatus->error_count = READ_VREG(AV_SCRATCH_4); + vstatus->status = stat; + + return 0; +} + +/****************************************/ +static void vvc1_canvas_init(void) +{ + int i; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + u32 disp_addr = 0xffffffff; + + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + /* HD & SD */ + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + + if (is_vpp_postblend()) { + struct canvas_s cur_canvas; + + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) & 0xff), + &cur_canvas); + disp_addr = (cur_canvas.addr + 7) >> 3; + } + + for (i = 0; i < 8; i++) { + if (((buf_start + i * decbuf_size + 7) >> 3) == disp_addr) { +#ifdef NV21 + canvas_config(2 * i + 0, + buf_start + 8 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(2 * i + 1, + buf_start + 8 * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(3 * i + 0, + buf_start + 8 * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 1, + buf_start + 8 * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 2, + buf_start + 8 * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); +#endif + } else { +#ifdef NV21 + canvas_config(2 * i + 0, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(2 * i + 1, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); +#else + canvas_config(3 * i + 0, + buf_start + i * decbuf_size, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 1, + buf_start + i * decbuf_size + + decbuf_y_size, canvas_width / 2, + canvas_height / 2, CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_32X32); + canvas_config(3 * i + 2, + buf_start + i * decbuf_size + + decbuf_y_size + decbuf_uv_size, + canvas_width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); +#endif + } + } +} + +static void vvc1_prot_init(void) +{ +#if 1 /* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + READ_VREG(DOS_SW_RESET0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); + + WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); + WRITE_VREG(DOS_SW_RESET0, 0); + +#else + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + READ_MPEG_REG(RESET0_REGISTER); + WRITE_MPEG_REG(RESET0_REGISTER, + RESET_IQIDCT | RESET_MC | RESET_VLD_PART); + + WRITE_MPEG_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); +#endif + + WRITE_VREG(POWER_CTL_VLD, 0x10); + WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2); + WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, MEM_LEVEL_CNT_BIT, 6); + + vvc1_canvas_init(); + + /* index v << 16 | u << 8 | y */ +#ifdef NV21 + WRITE_VREG(AV_SCRATCH_0, 0x010100); + WRITE_VREG(AV_SCRATCH_1, 0x030302); + WRITE_VREG(AV_SCRATCH_2, 0x050504); + WRITE_VREG(AV_SCRATCH_3, 0x070706); + WRITE_VREG(AV_SCRATCH_G, 0x090908); + WRITE_VREG(AV_SCRATCH_H, 0x0b0b0a); + WRITE_VREG(AV_SCRATCH_I, 0x0d0d0c); + WRITE_VREG(AV_SCRATCH_J, 0x0f0f0e); +#else + WRITE_VREG(AV_SCRATCH_0, 0x020100); + WRITE_VREG(AV_SCRATCH_1, 0x050403); + WRITE_VREG(AV_SCRATCH_2, 0x080706); + WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); + WRITE_VREG(AV_SCRATCH_G, 0x090908); + WRITE_VREG(AV_SCRATCH_H, 0x0b0b0a); + WRITE_VREG(AV_SCRATCH_I, 0x0d0d0c); + WRITE_VREG(AV_SCRATCH_J, 0x0f0f0e); +#endif + + /* notify ucode the buffer offset */ + WRITE_VREG(AV_SCRATCH_F, buf_offset); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + + WRITE_VREG(VC1_SOS_COUNT, 0); + WRITE_VREG(VC1_BUFFERIN, 0); + WRITE_VREG(VC1_BUFFEROUT, 0); + + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 1); + +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); +#endif +} + +static void vvc1_local_init(void) +{ + int i; + + /* vvc1_ratio = vvc1_amstream_dec_info.ratio; */ + vvc1_ratio = 0x100; + + avi_flag = (unsigned long) vvc1_amstream_dec_info.param; + + total_frame = 0; + + next_pts = 0; + + next_pts_us64 = 0; + saved_resolution = 0; + frame_width = frame_height = frame_dur = 0; +#ifdef DEBUG_PTS + pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0; +#endif + + memset(&frm, 0, sizeof(frm)); + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + vfbuf_use[i] = 0; + + INIT_KFIFO(display_q); + INIT_KFIFO(recycle_q); + INIT_KFIFO(newframe_q); + cur_pool_idx ^= 1; + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf; + if (cur_pool_idx == 0) { + vf = &vfpool[i]; + vfpool[i].index = DECODE_BUFFER_NUM_MAX; + } else { + vf = &vfpool2[i]; + vfpool2[i].index = DECODE_BUFFER_NUM_MAX; + } + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } +} + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER +static void vvc1_ppmgr_reset(void) +{ + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + + vvc1_local_init(); + + /* vf_notify_receiver(PROVIDER_NAME, + * VFRAME_EVENT_PROVIDER_START,NULL); */ + + pr_info("vvc1dec: vf_ppmgr_reset\n"); +} +#endif + +static void vvc1_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + +#if 1 + if (READ_VREG(VC1_SOS_COUNT) > 10) { + amvdec_stop(); +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vvc1_ppmgr_reset(); +#else + vf_light_unreg_provider(&vvc1_vf_prov); + vvc1_local_init(); + vf_reg_provider(&vvc1_vf_prov); +#endif + vvc1_prot_init(); + amvdec_start(); + } +#endif + + while (!kfifo_is_empty(&recycle_q) && (READ_VREG(VC1_BUFFERIN) == 0)) { + struct vframe_s *vf; + if (kfifo_get(&recycle_q, &vf)) { + if ((vf->index < DECODE_BUFFER_NUM_MAX) && + (--vfbuf_use[vf->index] == 0)) { + WRITE_VREG(VC1_BUFFERIN, ~(1 << vf->index)); + vf->index = DECODE_BUFFER_NUM_MAX; + } + if (pool_index(vf) == cur_pool_idx) + kfifo_put(&newframe_q, (const struct vframe_s *)vf); + } + } + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_VC1, + frame_width, frame_height, fps); + } + timer->expires = jiffies + PUT_INTERVAL; + + add_timer(timer); +} + +static s32 vvc1_init(void) +{ + int size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + pr_info("vvc1_init, format %d\n", vvc1_amstream_dec_info.format); + init_timer(&recycle_timer); + + stat |= STAT_TIMER_INIT; + + intra_output = 0; + amvdec_enable(); + + vvc1_local_init(); + + if (vvc1_amstream_dec_info.format == VIDEO_DEC_FORMAT_WMV3) { + pr_info("WMV3 dec format\n"); + vvc1_format = VIDEO_DEC_FORMAT_WMV3; + WRITE_VREG(AV_SCRATCH_4, 0); + } else if (vvc1_amstream_dec_info.format == VIDEO_DEC_FORMAT_WVC1) { + pr_info("WVC1 dec format\n"); + vvc1_format = VIDEO_DEC_FORMAT_WVC1; + WRITE_VREG(AV_SCRATCH_4, 1); + } else + pr_info("not supported VC1 format\n"); + + size = get_firmware_data(VIDEO_DEC_VC1, buf); + if (size < 0) { + pr_err("get firmware fail."); + vfree(buf); + return -1; + } + + if (amvdec_loadmc_ex(VFORMAT_VC1, NULL, buf) < 0) { + amvdec_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vvc1_prot_init(); + + if (vdec_request_irq(VDEC_IRQ_1, vvc1_isr, + "vvc1-irq", (void *)vvc1_dec_id)) { + amvdec_disable(); + + pr_info("vvc1 irq register error.\n"); + return -ENOENT; + } + + stat |= STAT_ISR_REG; +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_provider_init(&vvc1_vf_prov, + PROVIDER_NAME, &vvc1_vf_provider, NULL); + vf_reg_provider(&vvc1_vf_prov); + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_START, NULL); +#else + vf_provider_init(&vvc1_vf_prov, + PROVIDER_NAME, &vvc1_vf_provider, NULL); + vf_reg_provider(&vvc1_vf_prov); +#endif + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)vvc1_amstream_dec_info.rate)); + + stat |= STAT_VF_HOOK; + + recycle_timer.data = (ulong)&recycle_timer; + recycle_timer.function = vvc1_put_timer_func; + recycle_timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&recycle_timer); + + stat |= STAT_TIMER_ARM; + + amvdec_start(); + + stat |= STAT_VDEC_RUN; + + return 0; +} + +static int amvdec_vc1_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + if (pdata == NULL) { + pr_info("amvdec_vc1 memory resource undefined.\n"); + return -EFAULT; + } + + buf_start = pdata->mem_start; + buf_size = pdata->mem_end - pdata->mem_start + 1; + buf_offset = buf_start - ORI_BUFFER_START_ADDR; + + if (pdata->sys_info) + vvc1_amstream_dec_info = *pdata->sys_info; + + pdata->dec_status = vvc1_dec_status; + + if (vvc1_init() < 0) { + pr_info("amvdec_vc1 init failed.\n"); + + return -ENODEV; + } + + return 0; +} + +static int amvdec_vc1_remove(struct platform_device *pdev) +{ + if (stat & STAT_VDEC_RUN) { + amvdec_stop(); + stat &= ~STAT_VDEC_RUN; + } + + if (stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)vvc1_dec_id); + stat &= ~STAT_ISR_REG; + } + + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } + + if (stat & STAT_VF_HOOK) { + vf_notify_receiver(PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vvc1_vf_prov); + stat &= ~STAT_VF_HOOK; + } + + amvdec_disable(); + +#ifdef DEBUG_PTS + pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit, + pts_missed, pts_i_hit, pts_i_missed); + pr_info("total frame %d, avi_flag %d, rate %d\n", + total_frame, avi_flag, + vvc1_amstream_dec_info.rate); +#endif + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_vc1_driver = { + .probe = amvdec_vc1_probe, + .remove = amvdec_vc1_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +#if defined(CONFIG_ARCH_MESON) /*meson1 only support progressive */ +static struct codec_profile_t amvdec_vc1_profile = { + .name = "vc1", + .profile = "progressive, wmv3" +}; +#else +static struct codec_profile_t amvdec_vc1_profile = { + .name = "vc1", + .profile = "progressive, interlace, wmv3" +}; +#endif + +static int __init amvdec_vc1_driver_init_module(void) +{ + pr_debug("amvdec_vc1 module init\n"); + + if (platform_driver_register(&amvdec_vc1_driver)) { + pr_err("failed to register amvdec_vc1 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvdec_vc1_profile); + return 0; +} + +static void __exit amvdec_vc1_driver_remove_module(void) +{ + pr_debug("amvdec_vc1 module remove.\n"); + + platform_driver_unregister(&amvdec_vc1_driver); +} + +/****************************************/ + +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_vc1 stat\n"); + +module_init(amvdec_vc1_driver_init_module); +module_exit(amvdec_vc1_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC VC1 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Qi Wang "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c new file mode 100644 index 000000000000..0e819e77dca9 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c @@ -0,0 +1,6922 @@ + /* + * drivers/amlogic/amports/vvp9.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../stream_input/amports/amports_priv.h" +#include +#include "../utils/decoder_mmu_box.h" +#include "../utils/decoder_bmmu_box.h" + +#define MEM_NAME "codec_vp9" +/* #include */ +#include +#include "../utils/vdec.h" +#include "../utils/amvdec.h" + +#include + +#define MIX_STREAM_SUPPORT +#define SUPPORT_4K2K + +#include "vvp9.h" +#define VP9D_MPP_REFINFO_TBL_ACCCONFIG 0x3442 +#define VP9D_MPP_REFINFO_DATA 0x3443 +#define VP9D_MPP_REF_SCALE_ENBL 0x3441 +#define HEVC_MPRED_CTRL4 0x324c +#define HEVC_CM_HEADER_START_ADDR 0x3628 +#define HEVC_DBLK_CFGB 0x350b +#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 +#define HEVC_SAO_MMU_VH1_ADDR 0x363b +#define HEVC_SAO_MMU_VH0_ADDR 0x363a +#define HEVC_SAO_MMU_STATUS 0x3639 + + +#define VP9_10B_DEC_IDLE 0 +#define VP9_10B_DEC_FRAME_HEADER 1 +#define VP9_10B_DEC_SLICE_SEGMENT 2 +#define VP9_10B_DECODE_SLICE 5 +#define VP9_10B_DISCARD_NAL 6 +#define VP9_DUMP_LMEM 7 +#define HEVC_DECPIC_DATA_DONE 0xa +#define HEVC_DECPIC_DATA_ERROR 0xb +#define HEVC_NAL_DECODE_DONE 0xe +#define HEVC_DECODE_BUFEMPTY 0x20 +#define HEVC_DECODE_TIMEOUT 0x21 +#define HEVC_SEARCH_BUFEMPTY 0x22 +#define VP9_HEAD_PARSER_DONE 0xf0 +#define VP9_HEAD_SEARCH_DONE 0xf1 +#define VP9_EOS 0xf2 +#define HEVC_ACTION_DONE 0xff + +#define MAX_BUF_NUM 24 +#define MAX_REF_ACTIVE 16 +#define VF_POOL_SIZE 32 + +#undef pr_info +#define pr_info printk + +#define DECODE_MODE_SINGLE 0 +#define DECODE_MODE_MULTI_STREAMBASE 1 +#define DECODE_MODE_MULTI_FRAMEBASE 2 + +/*--------------------------------------------------- + Include "parser_cmd.h" +---------------------------------------------------*/ +#define PARSER_CMD_SKIP_CFG_0 0x0000090b + +#define PARSER_CMD_SKIP_CFG_1 0x1b14140f + +#define PARSER_CMD_SKIP_CFG_2 0x001b1910 + +#define PARSER_CMD_NUMBER 37 + +unsigned short parser_cmd[PARSER_CMD_NUMBER] = { +0x0401, +0x8401, +0x0800, +0x0402, +0x9002, +0x1423, +0x8CC3, +0x1423, +0x8804, +0x9825, +0x0800, +0x04FE, +0x8406, +0x8411, +0x1800, +0x8408, +0x8409, +0x8C2A, +0x9C2B, +0x1C00, +0x840F, +0x8407, +0x8000, +0x8408, +0x2000, +0xA800, +0x8410, +0x04DE, +0x840C, +0x840D, +0xAC00, +0xA000, +0x08C0, +0x08E0, +0xA40E, +0xFC00, +0x7C00 +}; +/*#define HEVC_PIC_STRUCT_SUPPORT*/ +/* to remove, fix build error */ + +/*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/ + +#define MULTI_INSTANCE_SUPPORT +#define SUPPORT_10BIT +/* #define ERROR_HANDLE_DEBUG */ +#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ +#undef SUPPORT_4K2K +#else +#define SUPPORT_4K2K +#endif + +#ifndef STAT_KTHREAD +#define STAT_KTHREAD 0x40 +#endif + +#ifdef MULTI_INSTANCE_SUPPORT +#define MAX_DECODE_INSTANCE_NUM 5 +#define MULTI_DRIVER_NAME "ammvdec_vp9" +#endif + +#define DRIVER_NAME "amvdec_vp9" +#define MODULE_NAME "amvdec_vp9" + +#define PUT_INTERVAL (HZ/100) +#define ERROR_SYSTEM_RESET_COUNT 200 + +#define PTS_NORMAL 0 +#define PTS_NONE_REF_USE_DURATION 1 + +#define PTS_MODE_SWITCHING_THRESHOLD 3 +#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 + +#define DUR2PTS(x) ((x)*90/96) + +struct VP9Decoder_s; +static int vvp9_vf_states(struct vframe_states *states, void *); +static struct vframe_s *vvp9_vf_peek(void *); +static struct vframe_s *vvp9_vf_get(void *); +static void vvp9_vf_put(struct vframe_s *, void *); +static int vvp9_event_cb(int type, void *data, void *private_data); + +static int vvp9_stop(struct VP9Decoder_s *pbi); +static s32 vvp9_init(struct VP9Decoder_s *pbi); +static void vvp9_prot_init(struct VP9Decoder_s *pbi); +static int vvp9_local_init(struct VP9Decoder_s *pbi); +static void vvp9_put_timer_func(unsigned long arg); +#ifdef VP9_10B_MMU +static int vp9_alloc_mmu( + struct VP9Decoder_s *pbi, + int cur_buf_idx, + int pic_width, + int pic_height, + unsigned short bit_depth, + unsigned int *mmu_index_adr); +#endif + +static const char vvp9_dec_id[] = "vvp9-dev"; + +#define PROVIDER_NAME "decoder.vp9" +#define MULTI_INSTANCE_PROVIDER_NAME "vdec.vp9" + +static const struct vframe_operations_s vvp9_vf_provider = { + .peek = vvp9_vf_peek, + .get = vvp9_vf_get, + .put = vvp9_vf_put, + .event_cb = vvp9_event_cb, + .vf_states = vvp9_vf_states, +}; + +static struct vframe_provider_s vvp9_vf_prov; + +static u32 bit_depth_luma; +static u32 bit_depth_chroma; +static u32 frame_width; +static u32 frame_height; +static u32 video_signal_type; +static u32 pts_unstable; +static u32 on_no_keyframe_skiped; + + +#define PROB_SIZE (496 * 2 * 4) +#define PROB_BUF_SIZE (0x5000) +#define COUNT_BUF_SIZE (0x300 * 4 * 4) +/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ +#define MAX_FRAME_4K_NUM 0x1200 +#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) + +static inline int div_r32(int64_t m, int n) +{ +/* +return (int)(m/n) +*/ +#ifndef CONFIG_ARM64 + do_div(m, n); + return (int)m; +#else + return (int)(m/n); +#endif +} + +/*USE_BUF_BLOCK*/ +struct BUF_s { + int index; + unsigned int alloc_flag; + /*buffer */ + unsigned int cma_page_count; + unsigned long alloc_addr; + unsigned long start_adr; + unsigned int size; + + unsigned int free_start_adr; +} /*BUF_t */; + + + /* #undef BUFMGR_ONLY to enable hardware configuration */ + +/*#define TEST_WR_PTR_INC*/ +#define WR_PTR_INC_NUM 128 + +#define SIMULATION +#define DOS_PROJECT +#undef MEMORY_MAP_IN_REAL_CHIP + +/*#undef DOS_PROJECT*/ +/*#define MEMORY_MAP_IN_REAL_CHIP*/ + +/*#define BUFFER_MGR_ONLY*/ +/*#define CONFIG_HEVC_CLK_FORCED_ON*/ +/*#define ENABLE_SWAP_TEST*/ +#define MCRCC_ENABLE + +#ifdef VP9_10B_NV21 +#define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/ +#else +#define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/ +#endif + +#define VP9_LPF_LVL_UPDATE +/*#define DBG_LF_PRINT*/ + +#ifdef VP9_10B_NV21 +#else +#define LOSLESS_COMPRESS_MODE +#endif + +#define DOUBLE_WRITE_YSTART_TEMP 0x02000000 +#define DOUBLE_WRITE_CSTART_TEMP 0x02900000 + + + +typedef unsigned int u32; +typedef unsigned short u16; + +#define VP9_DEBUG_BUFMGR 0x01 +#define VP9_DEBUG_BUFMGR_MORE 0x02 +#define VP9_DEBUG_UCODE 0x04 +#define VP9_DEBUG_REG 0x08 +#define VP9_DEBUG_MERGE 0x10 +#define VP9_DEBUG_BASIC 0x40 +#define VP9_DEBUG_SEND_PARAM_WITH_REG 0x100 +#define VP9_DEBUG_NO_DISPLAY 0x200 +#define VP9_DEBUG_DBG_LF_PRINT 0x400 +#define VP9_DEBUG_OUT_PTS 0x800 +#define VP9_DEBUG_VF_REF 0x1000 +#define VP9_DEBUG_DIS_LOC_ERROR_PROC 0x10000 +#define VP9_DEBUG_DIS_SYS_ERROR_PROC 0x20000 +#define VP9_DEBUG_DUMP_PIC_LIST 0x40000 +#define VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000 +#define VP9_DEBUG_HW_RESET 0x100000 +#define VP9_DEBUG_LOAD_UCODE_FROM_FILE 0x200000 +#define VP9_DEBUG_ERROR_TRIG 0x400000 +#define VP9_DEBUG_NOWAIT_DECODE_DONE_WHEN_STOP 0x4000000 +#ifdef MULTI_INSTANCE_SUPPORT +#define PRINT_FLAG_ERROR 0 +#define PRINT_FLAG_UCODE_EVT 0x10000000 +#define PRINT_FLAG_VDEC_STATUS 0x20000000 +#define PRINT_FLAG_VDEC_DETAIL 0x40000000 +#define PRINT_FLAG_VDEC_DATA 0x80000000 +#endif + +static u32 debug; + +#define DEBUG_REG +#ifdef DEBUG_REG +void WRITE_VREG_DBG2(unsigned adr, unsigned val) +{ + if (debug & VP9_DEBUG_REG) + pr_info("%s(%x, %x)\n", __func__, adr, val); + if (adr != 0) + WRITE_VREG(adr, val); +} + +#undef WRITE_VREG +#define WRITE_VREG WRITE_VREG_DBG2 +#endif + +/************************************************** + +VP9 buffer management start + +***************************************************/ +#ifdef VP9_10B_MMU +#define MMU_COMPRESS_HEADER_SIZE 0x48000 +#endif + +#define INVALID_IDX -1 /* Invalid buffer index.*/ + +#define RPM_BEGIN 0x200 +#define RPM_END 0x280 + +union param_u { + struct { + unsigned short data[RPM_END - RPM_BEGIN]; + } l; + struct { + /* from ucode lmem, do not change this struct */ + unsigned short profile; + unsigned short show_existing_frame; + unsigned short frame_to_show_idx; + unsigned short frame_type; /*1 bit*/ + unsigned short show_frame; /*1 bit*/ + unsigned short error_resilient_mode; /*1 bit*/ + unsigned short intra_only; /*1 bit*/ + unsigned short display_size_present; /*1 bit*/ + unsigned short reset_frame_context; + unsigned short refresh_frame_flags; + unsigned short width; + unsigned short height; + unsigned short display_width; + unsigned short display_height; + /* + bit[11:8] - ref_frame_info_0 (ref(3-bits), ref_frame_sign_bias(1-bit)) + bit[7:4] - ref_frame_info_1 (ref(3-bits), ref_frame_sign_bias(1-bit)) + bit[3:0] - ref_frame_info_2 (ref(3-bits), ref_frame_sign_bias(1-bit)) + */ + unsigned short ref_info; + /* + bit[2]: same_frame_size0 + bit[1]: same_frame_size1 + bit[0]: same_frame_size2 + */ + unsigned short same_frame_size; + + unsigned short mode_ref_delta_enabled; + unsigned short ref_deltas[4]; + unsigned short mode_deltas[2]; + unsigned short filter_level; + unsigned short sharpness_level; + unsigned short bit_depth; + unsigned short seg_quant_info[8]; + unsigned short seg_enabled; + unsigned short seg_abs_delta; + /* bit 15: feature enabled; bit 8, sign; bit[5:0], data */ + unsigned short seg_lf_info[8]; + } p; +}; + + +struct vpx_codec_frame_buffer_s { + uint8_t *data; /**< Pointer to the data buffer */ + size_t size; /**< Size of data in bytes */ + void *priv; /**< Frame's private data */ +}; + +enum vpx_color_space_t { + VPX_CS_UNKNOWN = 0, /**< Unknown */ + VPX_CS_BT_601 = 1, /**< BT.601 */ + VPX_CS_BT_709 = 2, /**< BT.709 */ + VPX_CS_SMPTE_170 = 3, /**< SMPTE.170 */ + VPX_CS_SMPTE_240 = 4, /**< SMPTE.240 */ + VPX_CS_BT_2020 = 5, /**< BT.2020 */ + VPX_CS_RESERVED = 6, /**< Reserved */ + VPX_CS_SRGB = 7 /**< sRGB */ +}; /**< alias for enum vpx_color_space */ + +enum vpx_bit_depth_t { + VPX_BITS_8 = 8, /**< 8 bits */ + VPX_BITS_10 = 10, /**< 10 bits */ + VPX_BITS_12 = 12, /**< 12 bits */ +}; + +#define MAX_SLICE_NUM 1024 +struct PIC_BUFFER_CONFIG_s { + int index; + int BUF_index; + int comp_body_size; + int buf_size; + int vf_ref; + int y_canvas_index; + int uv_canvas_index; +#ifdef MULTI_INSTANCE_SUPPORT + struct canvas_config_s canvas_config[2]; +#endif + int decode_idx; + int slice_type; + int num_reorder_pic; + int stream_offset; + uint8_t used_by_display; + uint8_t referenced; + uint8_t output_mark; + uint8_t recon_mark; + uint8_t output_ready; + uint8_t error_mark; + /**/ + int slice_idx; + /*buffer*/ +#ifdef VP9_10B_MMU + unsigned long header_adr; +#endif + unsigned long mpred_mv_wr_start_addr; + unsigned long mc_y_adr; + unsigned long mc_u_v_adr; + unsigned int dw_y_adr; + unsigned int dw_u_v_adr; + int mc_canvas_y; + int mc_canvas_u_v; + + int lcu_total; + /**/ + int y_width; + int y_height; + int y_crop_width; + int y_crop_height; + int y_stride; + + int uv_width; + int uv_height; + int uv_crop_width; + int uv_crop_height; + int uv_stride; + + int alpha_width; + int alpha_height; + int alpha_stride; + + uint8_t *y_buffer; + uint8_t *u_buffer; + uint8_t *v_buffer; + uint8_t *alpha_buffer; + + uint8_t *buffer_alloc; + int buffer_alloc_sz; + int border; + int frame_size; + int subsampling_x; + int subsampling_y; + unsigned int bit_depth; + enum vpx_color_space_t color_space; + + int corrupted; + int flags; + unsigned long cma_alloc_addr; +} PIC_BUFFER_CONFIG; + +enum BITSTREAM_PROFILE { + PROFILE_0, + PROFILE_1, + PROFILE_2, + PROFILE_3, + MAX_PROFILES +}; + +enum FRAME_TYPE { + KEY_FRAME = 0, + INTER_FRAME = 1, + FRAME_TYPES, +}; + +enum REFERENCE_MODE { + SINGLE_REFERENCE = 0, + COMPOUND_REFERENCE = 1, + REFERENCE_MODE_SELECT = 2, + REFERENCE_MODES = 3, +}; + +#define NONE -1 +#define INTRA_FRAME 0 +#define LAST_FRAME 1 +#define GOLDEN_FRAME 2 +#define ALTREF_FRAME 3 +#define MAX_REF_FRAMES 4 + +#define REFS_PER_FRAME 3 + +#define REF_FRAMES_LOG2 3 +#define REF_FRAMES (1 << REF_FRAMES_LOG2) + +/*4 scratch frames for the new frames to support a maximum of 4 cores decoding +in parallel, 3 for scaled references on the encoder. +TODO(hkuang): Add ondemand frame buffers instead of hardcoding the number +// of framebuffers. +TODO(jkoleszar): These 3 extra references could probably come from the +normal reference pool.*/ +#define FRAME_BUFFERS (REF_FRAMES + 7) + +#define FRAME_CONTEXTS_LOG2 2 +#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) +#define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + 1) +#define WORK_SPACE_BUF_ID (FRAME_BUFFERS) + +struct RefCntBuffer_s { + int ref_count; + /*MV_REF *mvs;*/ + int mi_rows; + int mi_cols; + struct vpx_codec_frame_buffer_s raw_frame_buffer; + struct PIC_BUFFER_CONFIG_s buf; + +/*The Following variables will only be used in frame parallel decode. + +frame_worker_owner indicates which FrameWorker owns this buffer. NULL means +that no FrameWorker owns, or is decoding, this buffer. +VP9Worker *frame_worker_owner; + +row and col indicate which position frame has been decoded to in real +pixel unit. They are reset to -1 when decoding begins and set to INT_MAX +when the frame is fully decoded.*/ + int row; + int col; +} RefCntBuffer; + +struct RefBuffer_s { +/*TODO(dkovalev): idx is not really required and should be removed, now it +is used in vp9_onyxd_if.c*/ + int idx; + struct PIC_BUFFER_CONFIG_s *buf; + /*struct scale_factors sf;*/ +} RefBuffer; + +struct InternalFrameBuffer_s { + uint8_t *data; + size_t size; + int in_use; +} InternalFrameBuffer; + +struct InternalFrameBufferList_s { + int num_internal_frame_buffers; + struct InternalFrameBuffer_s *int_fb; +} InternalFrameBufferList; + +struct BufferPool_s { +/*Protect BufferPool from being accessed by several FrameWorkers at +the same time during frame parallel decode. +TODO(hkuang): Try to use atomic variable instead of locking the whole pool. + +Private data associated with the frame buffer callbacks. +void *cb_priv; + +vpx_get_frame_buffer_cb_fn_t get_fb_cb; +vpx_release_frame_buffer_cb_fn_t release_fb_cb;*/ + + struct RefCntBuffer_s frame_bufs[FRAME_BUFFERS]; + +/*Frame buffers allocated internally by the codec.*/ + struct InternalFrameBufferList_s int_frame_buffers; + unsigned long flags; + spinlock_t lock; + +} BufferPool; + +static void lock_buffer_pool(struct BufferPool_s *pool) +{ + spin_lock_irqsave(&pool->lock, pool->flags); +} +static void unlock_buffer_pool(struct BufferPool_s *pool) +{ + spin_unlock_irqrestore(&pool->lock, pool->flags); +} + +struct VP9_Common_s { + enum vpx_color_space_t color_space; + int width; + int height; + int display_width; + int display_height; + int last_width; + int last_height; + + int subsampling_x; + int subsampling_y; + + int use_highbitdepth;/*Marks if we need to use 16bit frame buffers.*/ + + struct PIC_BUFFER_CONFIG_s *frame_to_show; + struct RefCntBuffer_s *prev_frame; + + /*TODO(hkuang): Combine this with cur_buf in macroblockd.*/ + struct RefCntBuffer_s *cur_frame; + + int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */ + + /*Prepare ref_frame_map for the next frame. + Only used in frame parallel decode.*/ + int next_ref_frame_map[REF_FRAMES]; + + /* TODO(jkoleszar): could expand active_ref_idx to 4, + with 0 as intra, and roll new_fb_idx into it.*/ + + /*Each frame can reference REFS_PER_FRAME buffers*/ + struct RefBuffer_s frame_refs[REFS_PER_FRAME]; + + int prev_fb_idx; + int new_fb_idx; + + /*last frame's frame type for motion search*/ + enum FRAME_TYPE last_frame_type; + enum FRAME_TYPE frame_type; + + int show_frame; + int last_show_frame; + int show_existing_frame; + + /*Flag signaling that the frame is encoded using only INTRA modes.*/ + uint8_t intra_only; + uint8_t last_intra_only; + + int allow_high_precision_mv; + + /*Flag signaling that the frame context should be reset to default + values. 0 or 1 implies don't reset, 2 reset just the context + specified in the frame header, 3 reset all contexts.*/ + int reset_frame_context; + + /*MBs, mb_rows/cols is in 16-pixel units; mi_rows/cols is in + MODE_INFO (8-pixel) units.*/ + int MBs; + int mb_rows, mi_rows; + int mb_cols, mi_cols; + int mi_stride; + + /*Whether to use previous frame's motion vectors for prediction.*/ + int use_prev_frame_mvs; + + int refresh_frame_context; /* Two state 0 = NO, 1 = YES */ + + int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */ + + /*struct loopfilter lf;*/ + /*struct segmentation seg;*/ + + /*TODO(hkuang):Remove this as it is the same as frame_parallel_decode*/ + /* in pbi.*/ + int frame_parallel_decode; /* frame-based threading.*/ + + /*Context probabilities for reference frame prediction*/ + /*MV_REFERENCE_FRAME comp_fixed_ref;*/ + /*MV_REFERENCE_FRAME comp_var_ref[2];*/ + enum REFERENCE_MODE reference_mode; + + /*FRAME_CONTEXT *fc; */ /* this frame entropy */ + /*FRAME_CONTEXT *frame_contexts; */ /*FRAME_CONTEXTS*/ + /*unsigned int frame_context_idx; *//* Context to use/update */ + /*FRAME_COUNTS counts;*/ + + unsigned int current_video_frame; + enum BITSTREAM_PROFILE profile; + + enum vpx_bit_depth_t bit_depth; + + int error_resilient_mode; + int frame_parallel_decoding_mode; + + int byte_alignment; + int skip_loop_filter; + + /*External BufferPool passed from outside.*/ + struct BufferPool_s *buffer_pool; + + int above_context_alloc_cols; + +} VP9_COMMON; + +static void set_canvas(struct PIC_BUFFER_CONFIG_s *pic_config); +static int prepare_display_buf(struct VP9Decoder_s *pbi, + struct PIC_BUFFER_CONFIG_s *pic_config); +static int get_free_fb(struct VP9_Common_s *cm) +{ + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + int i; + + lock_buffer_pool(cm->buffer_pool); + for (i = 0; i < FRAME_BUFFERS; ++i) { + if (debug & VP9_DEBUG_BUFMGR_MORE) + pr_info("%s:%d, ref_count %d vf_ref %d used_by_d %d index %d\r\n", + __func__, i, frame_bufs[i].ref_count, + frame_bufs[i].buf.vf_ref, + frame_bufs[i].buf.used_by_display, + frame_bufs[i].buf.index); + if ((frame_bufs[i].ref_count == 0) && + (frame_bufs[i].buf.vf_ref == 0) && + (frame_bufs[i].buf.used_by_display == 0) && + (frame_bufs[i].buf.index != -1) + ) + break; + } + if (i != FRAME_BUFFERS) { + frame_bufs[i].ref_count = 1; + /*pr_info("[MMU DEBUG 1] set ref_count[%d] : %d\r\n", + i, frame_bufs[i].ref_count);*/ + } else { + /* Reset i to be INVALID_IDX to indicate + no free buffer found*/ + i = INVALID_IDX; + } + + unlock_buffer_pool(cm->buffer_pool); + return i; +} + +static unsigned char is_buffer_empty(struct VP9_Common_s *cm) +{ + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + int i; + + for (i = 0; i < FRAME_BUFFERS; ++i) + if ((frame_bufs[i].ref_count == 0) && + (frame_bufs[i].buf.vf_ref == 0) && + (frame_bufs[i].buf.used_by_display == 0) && + (frame_bufs[i].buf.index != -1) + ) + break; + if (i != FRAME_BUFFERS) + return 0; + + return 1; +} + +static struct PIC_BUFFER_CONFIG_s *get_frame_new_buffer(struct VP9_Common_s *cm) +{ + return &cm->buffer_pool->frame_bufs[cm->new_fb_idx].buf; +} + +static void ref_cnt_fb(struct RefCntBuffer_s *bufs, int *idx, int new_idx) +{ + const int ref_index = *idx; + + if (ref_index >= 0 && bufs[ref_index].ref_count > 0) { + bufs[ref_index].ref_count--; + /*pr_info("[MMU DEBUG 2] dec ref_count[%d] : %d\r\n", + ref_index, bufs[ref_index].ref_count);*/ + } + + *idx = new_idx; + + bufs[new_idx].ref_count++; + /*pr_info("[MMU DEBUG 3] inc ref_count[%d] : %d\r\n", + new_idx, bufs[new_idx].ref_count);*/ +} + +int vp9_release_frame_buffer(struct vpx_codec_frame_buffer_s *fb) +{ + struct InternalFrameBuffer_s *const int_fb = + (struct InternalFrameBuffer_s *)fb->priv; + if (int_fb) + int_fb->in_use = 0; + return 0; +} + +static int compute_losless_comp_body_size(int width, int height, + uint8_t is_bit_depth_10); + +static void setup_display_size(struct VP9_Common_s *cm, union param_u *params, + int print_header_info) +{ + cm->display_width = cm->width; + cm->display_height = cm->height; + if (params->p.display_size_present) { + if (print_header_info) + pr_info(" * 1-bit display_size_present read : 1\n"); + cm->display_width = params->p.display_width; + cm->display_height = params->p.display_height; + /*vp9_read_frame_size(rb, &cm->display_width, + &cm->display_height);*/ + } else { + if (print_header_info) + pr_info(" * 1-bit display_size_present read : 0\n"); + } +} + +static void resize_context_buffers(struct VP9_Common_s *cm, int width, + int height) +{ + if (cm->width != width || cm->height != height) { + /* to do ..*/ + cm->width = width; + cm->height = height; + pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width, + cm->height, width, height); + } + /* + if (cm->cur_frame->mvs == NULL || + cm->mi_rows > cm->cur_frame->mi_rows || + cm->mi_cols > cm->cur_frame->mi_cols) { + resize_mv_buffer(cm); + } + */ +} + +static int valid_ref_frame_size(int ref_width, int ref_height, + int this_width, int this_height) { + return 2 * this_width >= ref_width && + 2 * this_height >= ref_height && + this_width <= 16 * ref_width && + this_height <= 16 * ref_height; +} + +/* +static int valid_ref_frame_img_fmt(enum vpx_bit_depth_t ref_bit_depth, + int ref_xss, int ref_yss, + enum vpx_bit_depth_t this_bit_depth, + int this_xss, int this_yss) { + return ref_bit_depth == this_bit_depth && ref_xss == this_xss && + ref_yss == this_yss; +} +*/ + + +static int setup_frame_size( + struct VP9Decoder_s *pbi, + struct VP9_Common_s *cm, union param_u *params, + unsigned int *mmu_index_adr, + int print_header_info) { + int width, height; + struct BufferPool_s * const pool = cm->buffer_pool; + struct PIC_BUFFER_CONFIG_s *ybf; + int ret = 0; + + width = params->p.width; + height = params->p.height; + /*vp9_read_frame_size(rb, &width, &height);*/ + if (print_header_info) + pr_info(" * 16-bits w read : %d (width : %d)\n", width, height); + if (print_header_info) + pr_info + (" * 16-bits h read : %d (height : %d)\n", width, height); + + WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); + +#ifdef VP9_10B_MMU + /* if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);*/ + /* cm->prev_fb_idx = cm->new_fb_idx;*/ + /*pr_info + ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n", + cm->prev_fb_idx, cm->new_fb_idx);*/ + ret = vp9_alloc_mmu(pbi, + cm->new_fb_idx, + params->p.width, + params->p.height, + params->p.bit_depth, + mmu_index_adr); + if (ret != 0) { + pr_err("can't alloc need mmu1,idx %d ret =%d\n", + cm->new_fb_idx, + ret); + return ret; + } +#endif + + resize_context_buffers(cm, width, height); + setup_display_size(cm, params, print_header_info); +#if 0 + lock_buffer_pool(pool); + if (vp9_realloc_frame_buffer( + get_frame_new_buffer(cm), cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, +#if CONFIG_VP9_HIGHBITDEPTH + cm->use_highbitdepth, +#endif + VP9_DEC_BORDER_IN_PIXELS, + cm->byte_alignment, + &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, + pool->get_fb_cb, pool->cb_priv)) { + unlock_buffer_pool(pool); + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate frame buffer"); + } + unlock_buffer_pool(pool); +#else + /* porting */ + ybf = get_frame_new_buffer(cm); + ybf->y_crop_width = width; + ybf->y_crop_height = height; + ybf->bit_depth = params->p.bit_depth; +#endif + pool->frame_bufs[cm->new_fb_idx].buf.subsampling_x = cm->subsampling_x; + pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; + pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = + (unsigned int)cm->bit_depth; + pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; + return ret; +} + +static int setup_frame_size_with_refs( + struct VP9Decoder_s *pbi, + struct VP9_Common_s *cm, + union param_u *params, + unsigned int *mmu_index_adr, + int print_header_info) { + + int width, height; + int found = 0, i; + int has_valid_ref_frame = 0; + struct PIC_BUFFER_CONFIG_s *ybf; + struct BufferPool_s * const pool = cm->buffer_pool; + int ret = 0; + + for (i = 0; i < REFS_PER_FRAME; ++i) { + if ((params->p.same_frame_size >> + (REFS_PER_FRAME - i - 1)) & 0x1) { + struct PIC_BUFFER_CONFIG_s *const buf = + cm->frame_refs[i].buf; + /*if (print_header_info) + pr_info + ("1-bit same_frame_size[%d] read : 1\n", i);*/ + width = buf->y_crop_width; + height = buf->y_crop_height; + /*if (print_header_info) + pr_info + (" - same_frame_size width : %d\n", width);*/ + /*if (print_header_info) + pr_info + (" - same_frame_size height : %d\n", height);*/ + found = 1; + break; + } else { + /*if (print_header_info) + pr_info + ("1-bit same_frame_size[%d] read : 0\n", i);*/ + } + } + + if (!found) { + /*vp9_read_frame_size(rb, &width, &height);*/ + width = params->p.width; + height = params->p.height; + /*if (print_header_info) + pr_info + (" * 16-bits w read : %d (width : %d)\n", + width, height); + if (print_header_info) + pr_info + (" * 16-bits h read : %d (height : %d)\n", + width, height);*/ + } + + if (width <= 0 || height <= 0) { + pr_err("Error: Invalid frame size\r\n"); + return -1; + } + + params->p.width = width; + params->p.height = height; + + WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); +#ifdef VP9_10B_MMU + /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); + cm->prev_fb_idx = cm->new_fb_idx;*/ +/* pr_info + ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n", + cm->prev_fb_idx, cm->new_fb_idx);*/ + ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, + params->p.width, params->p.height, + params->p.bit_depth, mmu_index_adr); + if (ret != 0) { + pr_err("can't alloc need mmu,idx %d\r\n", + cm->new_fb_idx); + return ret; + } +#endif + + /*Check to make sure at least one of frames that this frame references + has valid dimensions.*/ + for (i = 0; i < REFS_PER_FRAME; ++i) { + struct RefBuffer_s * const ref_frame = &cm->frame_refs[i]; + has_valid_ref_frame |= + valid_ref_frame_size(ref_frame->buf->y_crop_width, + ref_frame->buf->y_crop_height, + width, height); + } + if (!has_valid_ref_frame) { + pr_err("Error: Referenced frame has invalid size\r\n"); + return -1; + } +#if 0 + for (i = 0; i < REFS_PER_FRAME; ++i) { + struct RefBuffer_s * const ref_frame = + &cm->frame_refs[i]; + if (!valid_ref_frame_img_fmt( + ref_frame->buf->bit_depth, + ref_frame->buf->subsampling_x, + ref_frame->buf->subsampling_y, + cm->bit_depth, + cm->subsampling_x, + cm->subsampling_y)) + pr_err + ("Referenced frame incompatible color fmt\r\n"); + return -1; + } +#endif + resize_context_buffers(cm, width, height); + setup_display_size(cm, params, print_header_info); + +#if 0 + lock_buffer_pool(pool); + if (vp9_realloc_frame_buffer( + get_frame_new_buffer(cm), cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, +#if CONFIG_VP9_HIGHBITDEPTH + cm->use_highbitdepth, +#endif + VP9_DEC_BORDER_IN_PIXELS, + cm->byte_alignment, + &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, + pool->get_fb_cb, + pool->cb_priv)) { + unlock_buffer_pool(pool); + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate frame buffer"); + } + unlock_buffer_pool(pool); +#else + /* porting */ + ybf = get_frame_new_buffer(cm); + ybf->y_crop_width = width; + ybf->y_crop_height = height; + ybf->bit_depth = params->p.bit_depth; +#endif + pool->frame_bufs[cm->new_fb_idx].buf.subsampling_x = cm->subsampling_x; + pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; + pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = + (unsigned int)cm->bit_depth; + pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; + return ret; +} + +uint8_t print_header_info = 0; + +struct buff_s { + u32 buf_start; + u32 buf_size; + u32 buf_end; +} buff_t; + +struct BuffInfo_s { + u32 max_width; + u32 max_height; + u32 start_adr; + u32 end_adr; + struct buff_s ipp; + struct buff_s sao_abv; + struct buff_s sao_vb; + struct buff_s short_term_rps; + struct buff_s vps; + struct buff_s sps; + struct buff_s pps; + struct buff_s sao_up; + struct buff_s swap_buf; + struct buff_s swap_buf2; + struct buff_s scalelut; + struct buff_s dblk_para; + struct buff_s dblk_data; + struct buff_s seg_map; +#ifdef VP9_10B_MMU + struct buff_s mmu_vbh; + struct buff_s cm_header; +#endif + struct buff_s mpred_above; + struct buff_s mpred_mv; + struct buff_s rpm; + struct buff_s lmem; +} BuffInfo_t; + +#ifdef MULTI_INSTANCE_SUPPORT +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 +#define DEC_RESULT_CONFIG_PARAM 3 +#define DEC_RESULT_ERROR 4 +#define DEC_INIT_PICLIST 5 +#define DEC_UNINIT_PICLIST 6 +#define DEC_RESULT_GET_DATA 7 +#define DEC_RESULT_GET_DATA_RETRY 8 + +static void vp9_work(struct work_struct *work); +#endif + +struct VP9Decoder_s { +#ifdef MULTI_INSTANCE_SUPPORT + unsigned char index; + + struct device *cma_dev; + struct platform_device *platform_dev; + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; + struct vframe_chunk_s *chunk; + int dec_result; + struct work_struct work; + + struct BuffInfo_s work_space_buf_store; + unsigned long buf_start; + u32 buf_size; + u32 cma_alloc_count; + unsigned long cma_alloc_addr; +#endif + unsigned char m_ins_flag; + char *provider_name; + union param_u param; + int frame_count; + int pic_count; + u32 stat; + struct timer_list timer; + u32 frame_dur; + u32 frame_ar; + int fatal_error; + uint8_t init_flag; + uint8_t process_busy; + int show_frame_num; + struct buff_s mc_buf_spec; + struct dec_sysinfo vvp9_amstream_dec_info; + void *rpm_addr; + void *lmem_addr; + dma_addr_t rpm_phy_addr; + dma_addr_t lmem_phy_addr; + unsigned short *lmem_ptr; + unsigned short *debug_ptr; + + void *prob_buffer_addr; + void *count_buffer_addr; + dma_addr_t prob_buffer_phy_addr; + dma_addr_t count_buffer_phy_addr; + +#if 1 + /*VP9_10B_MMU*/ + void *frame_mmu_map_addr; + dma_addr_t frame_mmu_map_phy_addr; +#endif + unsigned int use_cma_flag; + + struct BUF_s m_BUF[MAX_BUF_NUM]; + u32 used_buf_num; + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE); + struct vframe_s vfpool[VF_POOL_SIZE]; + int buf_num; + int pic_num; + int lcu_size_log2; + unsigned int losless_comp_body_size; + + u32 video_signal_type; + + int pts_mode; + int last_lookup_pts; + int last_pts; + u64 last_lookup_pts_us64; + u64 last_pts_us64; + u64 shift_byte_count; + u32 shift_byte_count_lo; + u32 shift_byte_count_hi; + int pts_mode_switching_count; + int pts_mode_recovery_count; + + bool get_frame_dur; + u32 saved_resolution; + + /**/ + struct VP9_Common_s common; + struct RefCntBuffer_s *cur_buf; + int refresh_frame_flags; + uint8_t need_resync; + uint8_t hold_ref_buf; + uint8_t ready_for_new_data; + struct BufferPool_s vp9_buffer_pool; + + struct BuffInfo_s *work_space_buf; + struct buff_s *mc_buf; + + unsigned int frame_width; + unsigned int frame_height; + + unsigned short *rpm_ptr; + int init_pic_w; + int init_pic_h; + int lcu_total; + int lcu_size; + + int slice_type; + + int skip_flag; + int decode_idx; + int slice_idx; + uint8_t has_keyframe; + uint8_t wait_buf; + uint8_t error_flag; + + /* bit 0, for decoding; bit 1, for displaying */ + uint8_t ignore_bufmgr_error; + int PB_skip_mode; + int PB_skip_count_after_decoding; + /*hw*/ + + u32 pre_stream_offset; + + unsigned int dec_status; + u32 last_put_idx; + int new_frame_displayed; + void *mmu_box; + void *bmmu_box; +} VP9Decoder; + +static int vp9_print(struct VP9Decoder_s *pbi, + int flag, const char *fmt, ...) +{ +#define HEVC_PRINT_BUF 128 + unsigned char buf[HEVC_PRINT_BUF]; + int len = 0; + if (pbi == NULL || + (flag == 0) || + (debug & flag)) { + va_list args; + va_start(args, fmt); + if (pbi) + len = sprintf(buf, "[%d]", pbi->index); + vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} + +#ifdef MULTI_INSTANCE_SUPPORT +static int vp9_print_cont(struct VP9Decoder_s *pbi, + int flag, const char *fmt, ...) +{ + unsigned char buf[HEVC_PRINT_BUF]; + int len = 0; + if (pbi == NULL || + (flag == 0) || + (debug & flag)) { + va_list args; + va_start(args, fmt); + vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} +#endif + +#ifdef VP9_10B_MMU +int vp9_alloc_mmu( + struct VP9Decoder_s *pbi, + int cur_buf_idx, + int pic_width, + int pic_height, + unsigned short bit_depth, + unsigned int *mmu_index_adr) +{ + int bit_depth_10 = (bit_depth == VPX_BITS_10); + int picture_size; + int cur_mmu_4k_number; + + picture_size = compute_losless_comp_body_size(pic_width, pic_height, + bit_depth_10); + cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); + return decoder_mmu_box_alloc_idx( + pbi->mmu_box, + cur_buf_idx, + cur_mmu_4k_number, + mmu_index_adr); +} +#endif +static void decrease_ref_count(int idx, struct RefCntBuffer_s *const frame_bufs, + struct BufferPool_s *const pool) +{ + if (idx >= 0) { + --frame_bufs[idx].ref_count; + /*pr_info("[MMU DEBUG 7] dec ref_count[%d] : %d\r\n", idx, + frame_bufs[idx].ref_count);*/ + /*A worker may only get a free framebuffer index when + calling get_free_fb. But the private buffer is not set up + until finish decoding header. So any error happens during + decoding header, the frame_bufs will not have valid priv + buffer.*/ + + if (frame_bufs[idx].ref_count == 0 && + frame_bufs[idx].raw_frame_buffer.priv) + vp9_release_frame_buffer + (&frame_bufs[idx].raw_frame_buffer); + } +} + +static void generate_next_ref_frames(struct VP9Decoder_s *pbi) +{ + struct VP9_Common_s *const cm = &pbi->common; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + struct BufferPool_s *const pool = cm->buffer_pool; + int mask, ref_index = 0; + + /* Generate next_ref_frame_map.*/ + lock_buffer_pool(pool); + for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { + if (mask & 1) { + cm->next_ref_frame_map[ref_index] = cm->new_fb_idx; + ++frame_bufs[cm->new_fb_idx].ref_count; + /*pr_info("[MMU DEBUG 4] inc ref_count[%d] : %d\r\n", + cm->new_fb_idx, frame_bufs[cm->new_fb_idx].ref_count);*/ + } else + cm->next_ref_frame_map[ref_index] = + cm->ref_frame_map[ref_index]; + /* Current thread holds the reference frame.*/ + if (cm->ref_frame_map[ref_index] >= 0) { + ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; + /*pr_info + ("[MMU DEBUG 5] inc ref_count[%d] : %d\r\n", + cm->ref_frame_map[ref_index], + frame_bufs[cm->ref_frame_map[ref_index]].ref_count);*/ + } + ++ref_index; + } + + for (; ref_index < REF_FRAMES; ++ref_index) { + cm->next_ref_frame_map[ref_index] = + cm->ref_frame_map[ref_index]; + /* Current thread holds the reference frame.*/ + if (cm->ref_frame_map[ref_index] >= 0) { + ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; + /*pr_info("[MMU DEBUG 6] inc ref_count[%d] : %d\r\n", + cm->ref_frame_map[ref_index], + frame_bufs[cm->ref_frame_map[ref_index]].ref_count);*/ + } + } + unlock_buffer_pool(pool); + return; +} + +static void refresh_ref_frames(struct VP9Decoder_s *pbi) + +{ + struct VP9_Common_s *const cm = &pbi->common; + struct BufferPool_s *pool = cm->buffer_pool; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + int mask, ref_index = 0; + + lock_buffer_pool(pool); + for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { + const int old_idx = cm->ref_frame_map[ref_index]; + /*Current thread releases the holding of reference frame.*/ + decrease_ref_count(old_idx, frame_bufs, pool); + + /*Release the reference frame in reference map.*/ + if ((mask & 1) && old_idx >= 0) + decrease_ref_count(old_idx, frame_bufs, pool); + cm->ref_frame_map[ref_index] = + cm->next_ref_frame_map[ref_index]; + ++ref_index; + } + + /*Current thread releases the holding of reference frame.*/ + for (; ref_index < REF_FRAMES && !cm->show_existing_frame; + ++ref_index) { + const int old_idx = cm->ref_frame_map[ref_index]; + decrease_ref_count(old_idx, frame_bufs, pool); + cm->ref_frame_map[ref_index] = + cm->next_ref_frame_map[ref_index]; + } + unlock_buffer_pool(pool); + return; +} +int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) +{ + struct VP9_Common_s *const cm = &pbi->common; + struct BufferPool_s *pool = cm->buffer_pool; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + int i; + int ret; + + pbi->ready_for_new_data = 0; + + if (pbi->has_keyframe == 0 && + params->p.frame_type != KEY_FRAME){ + on_no_keyframe_skiped++; + return -2; + } + pbi->has_keyframe = 1; + on_no_keyframe_skiped = 0; +#ifdef VP9_10B_MMU + if (cm->prev_fb_idx >= 0) { + long used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + decoder_mmu_box_free_idx_tail(pbi->mmu_box, + cm->prev_fb_idx, used_4k_num); + } +#endif + if (cm->new_fb_idx >= 0 + && frame_bufs[cm->new_fb_idx].ref_count == 0){ + vp9_release_frame_buffer + (&frame_bufs[cm->new_fb_idx].raw_frame_buffer); + } + /*pr_info("Before get_free_fb, prev_fb_idx : %d, new_fb_idx : %d\r\n", + cm->prev_fb_idx, cm->new_fb_idx);*/ + cm->new_fb_idx = get_free_fb(cm); + cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx]; + /*if (debug & VP9_DEBUG_BUFMGR) + pr_info("[VP9 DEBUG]%s(get_free_fb): %d\r\n", __func__, + cm->new_fb_idx);*/ + if (cm->new_fb_idx == INVALID_IDX) { + pr_info("get_free_fb error\r\n"); + return -1; + } + pbi->cur_buf = &frame_bufs[cm->new_fb_idx]; +#ifdef VP9_10B_MMU + /* moved to after picture size ready + alloc_mmu(cm, params->p.width, params->p.height, + params->p.bit_depth, pbi->frame_mmu_map_addr);*/ + cm->prev_fb_idx = cm->new_fb_idx; +#endif + /*read_uncompressed_header()*/ + cm->last_frame_type = cm->frame_type; + cm->last_intra_only = cm->intra_only; + cm->profile = params->p.profile; + if (cm->profile >= MAX_PROFILES) { + pr_err("Error: Unsupported profile %d\r\n", cm->profile); + return -1; + } + cm->show_existing_frame = params->p.show_existing_frame; + if (cm->show_existing_frame) { + /* Show an existing frame directly.*/ + int frame_to_show_idx = params->p.frame_to_show_idx; + int frame_to_show; + if (frame_to_show_idx >= REF_FRAMES) { + pr_info("frame_to_show_idx %d exceed max index\r\n", + frame_to_show_idx); + return -1; + } + + frame_to_show = cm->ref_frame_map[frame_to_show_idx]; + /*pr_info("frame_to_show %d\r\n", frame_to_show);*/ + lock_buffer_pool(pool); + if (frame_to_show < 0 || + frame_bufs[frame_to_show].ref_count < 1) { + unlock_buffer_pool(pool); + pr_err + ("Error:Buffer %d does not contain a decoded frame", + frame_to_show); + return -1; + } + + ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show); + unlock_buffer_pool(pool); + pbi->refresh_frame_flags = 0; + /*cm->lf.filter_level = 0;*/ + cm->show_frame = 1; + + /* + if (pbi->frame_parallel_decode) { + for (i = 0; i < REF_FRAMES; ++i) + cm->next_ref_frame_map[i] = + cm->ref_frame_map[i]; + } + */ + /* do not decode, search next start code */ + return 1; + } + cm->frame_type = params->p.frame_type; + cm->show_frame = params->p.show_frame; + cm->error_resilient_mode = params->p.error_resilient_mode; + + + if (cm->frame_type == KEY_FRAME) { + pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; + + for (i = 0; i < REFS_PER_FRAME; ++i) { + cm->frame_refs[i].idx = INVALID_IDX; + cm->frame_refs[i].buf = NULL; + } + + ret = setup_frame_size(pbi, + cm, params, pbi->frame_mmu_map_addr, + print_header_info); + if (ret) + return -1; + if (pbi->need_resync) { + memset(&cm->ref_frame_map, -1, + sizeof(cm->ref_frame_map)); + pbi->need_resync = 0; + } + } else { + cm->intra_only = cm->show_frame ? 0 : params->p.intra_only; + /*if (print_header_info) { + if (cm->show_frame) + pr_info + ("intra_only set to 0 because of show_frame\n"); + else + pr_info + ("1-bit intra_only read: %d\n", cm->intra_only); + }*/ + + + cm->reset_frame_context = cm->error_resilient_mode ? + 0 : params->p.reset_frame_context; + if (print_header_info) { + if (cm->error_resilient_mode) + pr_info + ("reset to 0 error_resilient_mode\n"); + else + pr_info + (" * 2-bits reset_frame_context read : %d\n", + cm->reset_frame_context); + } + + if (cm->intra_only) { + if (cm->profile > PROFILE_0) { + /*read_bitdepth_colorspace_sampling(cm, + rb, print_header_info);*/ + } else { + /*NOTE: The intra-only frame header + does not include the specification + of either the color format or color sub-sampling + in profile 0. VP9 specifies that the default + color format should be YUV 4:2:0 in this + case (normative).*/ + cm->color_space = VPX_CS_BT_601; + cm->subsampling_y = cm->subsampling_x = 1; + cm->bit_depth = VPX_BITS_8; + cm->use_highbitdepth = 0; + } + + pbi->refresh_frame_flags = + params->p.refresh_frame_flags; + /*if (print_header_info) + pr_info("*%d-bits refresh_frame read:0x%x\n", + REF_FRAMES, pbi->refresh_frame_flags);*/ + ret = setup_frame_size(pbi, + cm, + params, + pbi->frame_mmu_map_addr, + print_header_info); + if (ret) { + return -1; + } + if (pbi->need_resync) { + memset(&cm->ref_frame_map, -1, + sizeof(cm->ref_frame_map)); + pbi->need_resync = 0; + } + } else if (pbi->need_resync != 1) { /* Skip if need resync */ + pbi->refresh_frame_flags = + params->p.refresh_frame_flags; + if (print_header_info) + pr_info + ("*%d-bits refresh_frame read:0x%x\n", + REF_FRAMES, pbi->refresh_frame_flags); + for (i = 0; i < REFS_PER_FRAME; ++i) { + const int ref = + (params->p.ref_info >> + (((REFS_PER_FRAME-i-1)*4)+1)) + & 0x7; + const int idx = + cm->ref_frame_map[ref]; + struct RefBuffer_s * const ref_frame = + &cm->frame_refs[i]; + if (print_header_info) + pr_info + ("*%d-bits ref[%d]read:%d\n", + REF_FRAMES_LOG2, i, ref); + ref_frame->idx = idx; + ref_frame->buf = &frame_bufs[idx].buf; + cm->ref_frame_sign_bias[LAST_FRAME + i] + = (params->p.ref_info >> + ((REFS_PER_FRAME-i-1)*4)) & 0x1; + if (print_header_info) + pr_info + ("1bit ref_frame_sign_bias"); + /*pr_info + ("%dread: %d\n", + LAST_FRAME+i, + cm->ref_frame_sign_bias + [LAST_FRAME + i]);*/ + /*pr_info + ("[VP9 DEBUG]%s(get ref):%d\r\n", + __func__, ref_frame->idx);*/ + + } + + ret = setup_frame_size_with_refs( + pbi, + cm, + params, + pbi->frame_mmu_map_addr, + print_header_info); + if (ret) { + return -1; + } + for (i = 0; i < REFS_PER_FRAME; ++i) { + /*struct RefBuffer_s *const ref_buf = + &cm->frame_refs[i];*/ + /* to do: + vp9_setup_scale_factors_for_frame*/ + } + } + } + + get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; + get_frame_new_buffer(cm)->color_space = cm->color_space; + get_frame_new_buffer(cm)->slice_type = cm->frame_type; + + if (pbi->need_resync) + pr_err + ("Error: Keyframe/intra-only frame required to reset\r\n"); + generate_next_ref_frames(pbi); + pbi->hold_ref_buf = 1; + +#if 0 + if (frame_is_intra_only(cm) || cm->error_resilient_mode) + vp9_setup_past_independence(cm); + setup_loopfilter(&cm->lf, rb, print_header_info); + setup_quantization(cm, &pbi->mb, rb, print_header_info); + setup_segmentation(&cm->seg, rb, print_header_info); + setup_segmentation_dequant(cm, print_header_info); + + setup_tile_info(cm, rb, print_header_info); + sz = vp9_rb_read_literal(rb, 16); + if (print_header_info) + pr_info(" * 16-bits size read : %d (0x%x)\n", sz, sz); + + if (sz == 0) + vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, + "Invalid header size"); +#endif + /*end read_uncompressed_header()*/ + cm->use_prev_frame_mvs = !cm->error_resilient_mode && + cm->width == cm->last_width && + cm->height == cm->last_height && + !cm->last_intra_only && + cm->last_show_frame && + (cm->last_frame_type != KEY_FRAME); + + /*pr_info + ("set use_prev_frame_mvs to %d (last_width %d last_height %d", + cm->use_prev_frame_mvs, cm->last_width, cm->last_height); + pr_info + (" last_intra_only %d last_show_frame %d last_frame_type %d)\n", + cm->last_intra_only, cm->last_show_frame, cm->last_frame_type);*/ + return 0; +} + + +void swap_frame_buffers(struct VP9Decoder_s *pbi) +{ + int ref_index = 0; + struct VP9_Common_s *const cm = &pbi->common; + struct BufferPool_s *const pool = cm->buffer_pool; + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + refresh_ref_frames(pbi); + pbi->hold_ref_buf = 0; + cm->frame_to_show = get_frame_new_buffer(cm); + + /*if (!pbi->frame_parallel_decode || !cm->show_frame) {*/ + lock_buffer_pool(pool); + --frame_bufs[cm->new_fb_idx].ref_count; + /*pr_info("[MMU DEBUG 8] dec ref_count[%d] : %d\r\n", cm->new_fb_idx, + frame_bufs[cm->new_fb_idx].ref_count);*/ + unlock_buffer_pool(pool); + /*}*/ + + /*Invalidate these references until the next frame starts.*/ + for (ref_index = 0; ref_index < 3; ref_index++) + cm->frame_refs[ref_index].idx = -1; +} + +#if 0 +static void check_resync(vpx_codec_alg_priv_t *const ctx, + const struct VP9Decoder_s *const pbi) +{ + /* Clear resync flag if worker got a key frame or intra only frame.*/ + if (ctx->need_resync == 1 && pbi->need_resync == 0 && + (pbi->common.intra_only || pbi->common.frame_type == KEY_FRAME)) + ctx->need_resync = 0; +} +#endif + +int vp9_get_raw_frame(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *sd) +{ + struct VP9_Common_s *const cm = &pbi->common; + int ret = -1; + + if (pbi->ready_for_new_data == 1) + return ret; + + pbi->ready_for_new_data = 1; + + /* no raw frame to show!!! */ + if (!cm->show_frame) + return ret; + + pbi->ready_for_new_data = 1; + + *sd = *cm->frame_to_show; + ret = 0; + + return ret; +} + +int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, + struct buff_s *mc_buf_i) { + struct VP9_Common_s *cm = &pbi->common; + + /*memset(pbi, 0, sizeof(struct VP9Decoder));*/ + pbi->frame_count = 0; + pbi->pic_count = 0; + pbi->pre_stream_offset = 0; + cm->buffer_pool = &pbi->vp9_buffer_pool; + spin_lock_init(&cm->buffer_pool->lock); + cm->prev_fb_idx = INVALID_IDX; + cm->new_fb_idx = INVALID_IDX; + pr_info + ("After vp9_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n", + cm->prev_fb_idx, cm->new_fb_idx); + pbi->need_resync = 1; + /* Initialize the references to not point to any frame buffers.*/ + memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map)); + memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map)); + cm->current_video_frame = 0; + pbi->ready_for_new_data = 1; + + /* private init */ + pbi->work_space_buf = buf_spec_i; + pbi->mc_buf = mc_buf_i; + pbi->rpm_addr = NULL; + pbi->lmem_addr = NULL; + + pbi->use_cma_flag = 0; + pbi->decode_idx = 0; + pbi->slice_idx = 0; + /*int m_uiMaxCUWidth = 1<<7;*/ + /*int m_uiMaxCUHeight = 1<<7;*/ + pbi->has_keyframe = 0; + pbi->skip_flag = 0; + pbi->wait_buf = 0; + pbi->error_flag = 0; + + pbi->pts_mode = PTS_NORMAL; + pbi->last_pts = 0; + pbi->last_lookup_pts = 0; + pbi->last_pts_us64 = 0; + pbi->last_lookup_pts_us64 = 0; + pbi->shift_byte_count = 0; + pbi->shift_byte_count_lo = 0; + pbi->shift_byte_count_hi = 0; + pbi->pts_mode_switching_count = 0; + pbi->pts_mode_recovery_count = 0; + + pbi->buf_num = 0; + pbi->pic_num = 0; + + return 0; +} + + +int vp9_bufmgr_postproc(struct VP9Decoder_s *pbi) +{ + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s sd; + swap_frame_buffers(pbi); + if (!cm->show_existing_frame) { + cm->last_show_frame = cm->show_frame; + cm->prev_frame = cm->cur_frame; +#if 0 + if (cm->seg.enabled && !pbi->frame_parallel_decode) + vp9_swap_current_and_last_seg_map(cm); +#endif + } + cm->last_width = cm->width; + cm->last_height = cm->height; + if (cm->show_frame) + cm->current_video_frame++; + + if (vp9_get_raw_frame(pbi, &sd) == 0) { + /*pr_info("Display frame index %d\r\n", sd.index);*/ + sd.stream_offset = pbi->pre_stream_offset; + prepare_display_buf(pbi, &sd); + pbi->pre_stream_offset = READ_VREG(HEVC_SHIFT_BYTE_COUNT); + } /*else + pr_info + ("Not display this frame,ready_for_new_data%d show_frame%d\r\n", + pbi->ready_for_new_data, cm->show_frame);*/ + return 0; +} + +struct VP9Decoder_s vp9_decoder; +union param_u vp9_param; + +/************************************************** + +VP9 buffer management end + +***************************************************/ + + +#define HEVC_CM_BODY_START_ADDR 0x3626 +#define HEVC_CM_BODY_LENGTH 0x3627 +#define HEVC_CM_HEADER_LENGTH 0x3629 +#define HEVC_CM_HEADER_OFFSET 0x362b + +#define LOSLESS_COMPRESS_MODE +/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ +/* double_write_mode: 0, no double write; 1, 1:1 ratio; 2, (1/4):(1/4) ratio + 0x10, double write only +*/ +static u32 double_write_mode; + +/*#define DECOMP_HEADR_SURGENT*/ + +static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ +static u32 enable_mem_saving = 1; +static u32 force_w_h; + +static u32 force_fps; + + +const u32 vp9_version = 201602101; +static u32 debug; +static u32 radr; +static u32 rval; +static u32 pop_shorts; +static u32 dbg_cmd; +static u32 dbg_skip_decode_index; +static u32 endian = 0xff0; +#ifdef ERROR_HANDLE_DEBUG +static u32 dbg_nal_skip_flag; + /* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */ +static u32 dbg_nal_skip_count; +#endif +/*for debug*/ +static u32 decode_stop_pos; +static u32 decode_stop_pos_pre; +static u32 decode_pic_begin; +static uint slice_parse_begin; +static u32 step; +#ifdef MIX_STREAM_SUPPORT +#ifdef SUPPORT_4K2K +static u32 buf_alloc_width = 4096; +static u32 buf_alloc_height = 2304; +#else +static u32 buf_alloc_width = 1920; +static u32 buf_alloc_height = 1088; +#endif +static u32 dynamic_buf_num_margin; +#else +static u32 buf_alloc_width; +static u32 buf_alloc_height; +static u32 dynamic_buf_num_margin = 7; +#endif +static u32 buf_alloc_depth = 10; +static u32 buf_alloc_size; +/* +bit[0]: 0, + bit[1]: 0, always release cma buffer when stop + bit[1]: 1, never release cma buffer when stop +bit[0]: 1, when stop, release cma buffer if blackout is 1; +do not release cma buffer is blackout is not 1 + +bit[2]: 0, when start decoding, check current displayed buffer + (only for buffer decoded by vp9) if blackout is 0 + 1, do not check current displayed buffer + +bit[3]: 1, if blackout is not 1, do not release current + displayed cma buffer always. +*/ +/* set to 1 for fast play; + set to 8 for other case of "keep last frame" +*/ +static u32 buffer_mode = 1; +/* buffer_mode_dbg: debug only*/ +static u32 buffer_mode_dbg = 0xffff0000; +/**/ + +/* +bit 0, 1: only display I picture; +bit 1, 1: only decode I picture; +*/ +static u32 i_only_flag; + +/* +use_cma: 1, use both reserver memory and cma for buffers +2, only use cma for buffers +*/ +static u32 use_cma = 2; + +static u32 max_decoding_time; +/* +error handling +*/ +/*error_handle_policy: +bit 0: 0, auto skip error_skip_nal_count nals before error recovery; +1, skip error_skip_nal_count nals before error recovery; +bit 1 (valid only when bit0 == 1): +1, wait vps/sps/pps after error recovery; +bit 2 (valid only when bit0 == 0): +0, auto search after error recovery (vp9_recover() called); +1, manual search after error recovery +(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) + +bit 4: 0, set error_mark after reset/recover + 1, do not set error_mark after reset/recover +bit 5: 0, check total lcu for every picture + 1, do not check total lcu + +*/ + +static u32 error_handle_policy; +/*static u32 parser_sei_enable = 1;*/ + +static u32 max_buf_num = 12; + + +static DEFINE_MUTEX(vvp9_mutex); +#ifndef MULTI_INSTANCE_SUPPORT +static struct device *cma_dev; +#endif + +#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 +#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 +#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 +#define VP9_ADAPT_PROB_REG HEVC_ASSIST_SCRATCH_3 +#define VP9_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_4 +#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 +#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 +#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 +#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 +#define VP9_PROB_SWAP_BUFFER HEVC_ASSIST_SCRATCH_9 +#define VP9_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A +#define VP9_SEG_MAP_BUFFER HEVC_ASSIST_SCRATCH_B +#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D +#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E +#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F +#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_F +#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L +#ifdef MULTI_INSTANCE_SUPPORT +#define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M +#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N +#else +#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M +#define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N +#endif +#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G +#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H + + +/* +ucode parser/search control +bit 0: 0, header auto parse; 1, header manual parse +bit 1: 0, auto skip for noneseamless stream; 1, no skip +bit [3:2]: valid when bit1==0; +0, auto skip nal before first vps/sps/pps/idr; +1, auto skip nal before first vps/sps/pps +2, auto skip nal before first vps/sps/pps, + and not decode until the first I slice (with slice address of 0) + +3, auto skip before first I slice (nal_type >=16 && nal_type<=21) +bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) ) +bit [16]: for NAL_UNIT_EOS when bit0 is 0: + 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm +bit [17]: for NAL_SEI when bit0 is 0: + 0, do not parse SEI in ucode; 1, parse SEI in ucode +bit [31:20]: used by ucode for debug purpose +*/ +#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I +#define DECODE_MODE HEVC_ASSIST_SCRATCH_J +#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K + +#ifdef MULTI_INSTANCE_SUPPORT +#define RPM_BUF_SIZE (0x400 * 2) +#else +#define RPM_BUF_SIZE (0x80*2) +#endif +#define LMEM_BUF_SIZE (0x400 * 2) + +#define WORK_BUF_SPEC_NUM 2 +static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { + { + /* 8M bytes */ + .max_width = 1920, + .max_height = 1088, + .ipp = { + /* IPP work space calculation : + 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ + .buf_size = 0x4000, + }, + .sao_abv = { + .buf_size = 0x30000, + }, + .sao_vb = { + .buf_size = 0x30000, + }, + .short_term_rps = { + /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, + total 64x16x2 = 2048 bytes (0x800) */ + .buf_size = 0x800, + }, + .vps = { + /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .sps = { + /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .pps = { + /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, + total 0x2000 bytes */ + .buf_size = 0x2000, + }, + .sao_up = { + /* SAO UP STORE AREA - Max 640(10240/16) LCU, + each has 16 bytes total 0x2800 bytes */ + .buf_size = 0x2800, + }, + .swap_buf = { + /* 256cyclex64bit = 2K bytes 0x800 + (only 144 cycles valid) */ + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + /* support up to 32 SCALELUT 1024x32 = + 32Kbytes (0x8000) */ + .buf_size = 0x8000, + }, + .dblk_para = { + /* DBLK -> Max 256(4096/16) LCU, + each para 1024bytes(total:0x40000), + data 1024bytes(total:0x40000)*/ + .buf_size = 0x80000, + }, + .dblk_data = { + .buf_size = 0x80000, + }, + .seg_map = { + /*4096x2304/64/64 *24 = 0xd800 Bytes*/ + .buf_size = 0xd800, + }, +#ifdef VP9_10B_MMU + .mmu_vbh = { + .buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/ + }, + .cm_header = { + /*add one for keeper.*/ + .buf_size = MMU_COMPRESS_HEADER_SIZE * + (FRAME_BUFFERS + 1), + /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ + }, +#endif + .mpred_above = { + .buf_size = 0x10000, /* 2 * size of hevc*/ + }, + .mpred_mv = {/* 1080p, 0x40000 per buffer */ + .buf_size = 0x40000 * FRAME_BUFFERS, + }, + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x400 * 2, + } + }, + { + .max_width = 4096, + .max_height = 2304, + .ipp = { + /* IPP work space calculation : + 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ + .buf_size = 0x4000, + }, + .sao_abv = { + .buf_size = 0x30000, + }, + .sao_vb = { + .buf_size = 0x30000, + }, + .short_term_rps = { + /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, + total 64x16x2 = 2048 bytes (0x800) */ + .buf_size = 0x800, + }, + .vps = { + /* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .sps = { + /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, + total 0x0800 bytes */ + .buf_size = 0x800, + }, + .pps = { + /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, + total 0x2000 bytes */ + .buf_size = 0x2000, + }, + .sao_up = { + /* SAO UP STORE AREA - Max 640(10240/16) LCU, + each has 16 bytes total 0x2800 bytes */ + .buf_size = 0x2800, + }, + .swap_buf = { + /* 256cyclex64bit = 2K bytes 0x800 + (only 144 cycles valid) */ + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + /* support up to 32 SCALELUT 1024x32 = 32Kbytes + (0x8000) */ + .buf_size = 0x8000, + }, + .dblk_para = { + /* DBLK -> Max 256(4096/16) LCU, + each para 1024bytes(total:0x40000), + data 1024bytes(total:0x40000)*/ + .buf_size = 0x80000, + }, + .dblk_data = { + .buf_size = 0x80000, + }, + .seg_map = { + /*4096x2304/64/64 *24 = 0xd800 Bytes*/ + .buf_size = 0xd800, + }, +#ifdef VP9_10B_MMU + .mmu_vbh = { + .buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/ + }, + .cm_header = { + /*add one for keeper.*/ + .buf_size = MMU_COMPRESS_HEADER_SIZE * + (FRAME_BUFFERS + 1), + /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ + }, +#endif + .mpred_above = { + .buf_size = 0x10000, /* 2 * size of hevc*/ + }, + .mpred_mv = { + /* .buf_size = 0x100000*16, + //4k2k , 0x100000 per buffer */ + /* 4096x2304 , 0x120000 per buffer */ + .buf_size = 0x120000 * FRAME_BUFFERS, + }, + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x400 * 2, + } + } +}; + + +/*Losless compression body buffer size 4K per 64x32 (jt)*/ +int compute_losless_comp_body_size(int width, int height, + uint8_t is_bit_depth_10) +{ + int width_x64; + int height_x32; + int bsize; + width_x64 = width + 63; + width_x64 >>= 6; + height_x32 = height + 31; + height_x32 >>= 5; +#ifdef VP9_10B_MMU + bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32; +#else + bsize = (is_bit_depth_10?4096:3072)*width_x64*height_x32; +#endif + if (debug & VP9_DEBUG_BUFMGR_MORE) + pr_info("%s(%d,%d,%d)=>%d\n", + __func__, width, height, + is_bit_depth_10, bsize); + + return bsize; +} + +/* Losless compression header buffer size 32bytes per 128x64 (jt)*/ +static int compute_losless_comp_header_size(int width, int height) +{ + int width_x128; + int height_x64; + int hsize; + width_x128 = width + 127; + width_x128 >>= 7; + height_x64 = height + 63; + height_x64 >>= 6; + + hsize = 32 * width_x128 * height_x64; + if (debug & VP9_DEBUG_BUFMGR_MORE) + pr_info("%s(%d,%d)=>%d\n", + __func__, width, height, + hsize); + + return hsize; +} + +static void init_buff_spec(struct VP9Decoder_s *pbi, + struct BuffInfo_s *buf_spec) +{ + void *mem_start_virt; + buf_spec->ipp.buf_start = buf_spec->start_adr; + buf_spec->sao_abv.buf_start = + buf_spec->ipp.buf_start + buf_spec->ipp.buf_size; + + buf_spec->sao_vb.buf_start = + buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size; + buf_spec->short_term_rps.buf_start = + buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size; + buf_spec->vps.buf_start = + buf_spec->short_term_rps.buf_start + + buf_spec->short_term_rps.buf_size; + buf_spec->sps.buf_start = + buf_spec->vps.buf_start + buf_spec->vps.buf_size; + buf_spec->pps.buf_start = + buf_spec->sps.buf_start + buf_spec->sps.buf_size; + buf_spec->sao_up.buf_start = + buf_spec->pps.buf_start + buf_spec->pps.buf_size; + buf_spec->swap_buf.buf_start = + buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size; + buf_spec->swap_buf2.buf_start = + buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size; + buf_spec->scalelut.buf_start = + buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size; + buf_spec->dblk_para.buf_start = + buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size; + buf_spec->dblk_data.buf_start = + buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; + buf_spec->seg_map.buf_start = + buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; +#ifdef VP9_10B_MMU + buf_spec->mmu_vbh.buf_start = + buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; + buf_spec->cm_header.buf_start = + buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; + buf_spec->mpred_above.buf_start = + buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size; +#else + buf_spec->mpred_above.buf_start = + buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; +#endif + buf_spec->mpred_mv.buf_start = + buf_spec->mpred_above.buf_start + + buf_spec->mpred_above.buf_size; + if (debug & VP9_DEBUG_SEND_PARAM_WITH_REG) { + buf_spec->end_adr = + buf_spec->mpred_mv.buf_start + + buf_spec->mpred_mv.buf_size; + } else { + buf_spec->rpm.buf_start = + buf_spec->mpred_mv.buf_start + + buf_spec->mpred_mv.buf_size; + if (debug & VP9_DEBUG_UCODE) { + buf_spec->lmem.buf_start = + buf_spec->rpm.buf_start + + buf_spec->rpm.buf_size; + buf_spec->end_adr = + buf_spec->lmem.buf_start + + buf_spec->lmem.buf_size; + } else { + buf_spec->end_adr = + buf_spec->rpm.buf_start + + buf_spec->rpm.buf_size; + } + } + mem_start_virt = codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start); + if (mem_start_virt) { + memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size); + codec_mm_dma_flush(mem_start_virt, + buf_spec->dblk_para.buf_size, + DMA_TO_DEVICE); + } else { + /*not virt for tvp playing, + may need clear on ucode.*/ + pr_err("mem_start_virt failed\n"); + } + if (debug) { + pr_info("%s workspace (%x %x) size = %x\n", __func__, + buf_spec->start_adr, buf_spec->end_adr, + buf_spec->end_adr - buf_spec->start_adr); + } + if (debug) { + pr_info("ipp.buf_start :%x\n", + buf_spec->ipp.buf_start); + pr_info("sao_abv.buf_start :%x\n", + buf_spec->sao_abv.buf_start); + pr_info("sao_vb.buf_start :%x\n", + buf_spec->sao_vb.buf_start); + pr_info("short_term_rps.buf_start :%x\n", + buf_spec->short_term_rps.buf_start); + pr_info("vps.buf_start :%x\n", + buf_spec->vps.buf_start); + pr_info("sps.buf_start :%x\n", + buf_spec->sps.buf_start); + pr_info("pps.buf_start :%x\n", + buf_spec->pps.buf_start); + pr_info("sao_up.buf_start :%x\n", + buf_spec->sao_up.buf_start); + pr_info("swap_buf.buf_start :%x\n", + buf_spec->swap_buf.buf_start); + pr_info("swap_buf2.buf_start :%x\n", + buf_spec->swap_buf2.buf_start); + pr_info("scalelut.buf_start :%x\n", + buf_spec->scalelut.buf_start); + pr_info("dblk_para.buf_start :%x\n", + buf_spec->dblk_para.buf_start); + pr_info("dblk_data.buf_start :%x\n", + buf_spec->dblk_data.buf_start); + pr_info("seg_map.buf_start :%x\n", + buf_spec->seg_map.buf_start); +#ifdef VP9_10B_MMU + pr_info("mmu_vbh.buf_start :%x\n", + buf_spec->mmu_vbh.buf_start); + pr_info("cm_header.buf_start :%x\n", + buf_spec->cm_header.buf_start); +#endif + pr_info("mpred_above.buf_start :%x\n", + buf_spec->mpred_above.buf_start); + pr_info("mpred_mv.buf_start :%x\n", + buf_spec->mpred_mv.buf_start); + if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { + pr_info("rpm.buf_start :%x\n", + buf_spec->rpm.buf_start); + } + } + +} + +/*==================================================== +======================================================================== +vp9_prob define +========================================================================*/ +#define VP9_PARTITION_START 0 +#define VP9_PARTITION_SIZE_STEP (3 * 4) +#define VP9_PARTITION_ONE_SIZE (4 * VP9_PARTITION_SIZE_STEP) +#define VP9_PARTITION_KEY_START 0 +#define VP9_PARTITION_P_START VP9_PARTITION_ONE_SIZE +#define VP9_PARTITION_SIZE (2 * VP9_PARTITION_ONE_SIZE) +#define VP9_SKIP_START (VP9_PARTITION_START + VP9_PARTITION_SIZE) +#define VP9_SKIP_SIZE 4 /* only use 3*/ +#define VP9_TX_MODE_START (VP9_SKIP_START+VP9_SKIP_SIZE) +#define VP9_TX_MODE_8_0_OFFSET 0 +#define VP9_TX_MODE_8_1_OFFSET 1 +#define VP9_TX_MODE_16_0_OFFSET 2 +#define VP9_TX_MODE_16_1_OFFSET 4 +#define VP9_TX_MODE_32_0_OFFSET 6 +#define VP9_TX_MODE_32_1_OFFSET 9 +#define VP9_TX_MODE_SIZE 12 +#define VP9_COEF_START (VP9_TX_MODE_START+VP9_TX_MODE_SIZE) +#define VP9_COEF_BAND_0_OFFSET 0 +#define VP9_COEF_BAND_1_OFFSET (VP9_COEF_BAND_0_OFFSET + 3 * 3 + 1) +#define VP9_COEF_BAND_2_OFFSET (VP9_COEF_BAND_1_OFFSET + 6 * 3) +#define VP9_COEF_BAND_3_OFFSET (VP9_COEF_BAND_2_OFFSET + 6 * 3) +#define VP9_COEF_BAND_4_OFFSET (VP9_COEF_BAND_3_OFFSET + 6 * 3) +#define VP9_COEF_BAND_5_OFFSET (VP9_COEF_BAND_4_OFFSET + 6 * 3) +#define VP9_COEF_SIZE_ONE_SET 100 /* ((3 +5*6)*3 + 1 padding)*/ +#define VP9_COEF_4X4_START (VP9_COEF_START + 0 * VP9_COEF_SIZE_ONE_SET) +#define VP9_COEF_8X8_START (VP9_COEF_START + 4 * VP9_COEF_SIZE_ONE_SET) +#define VP9_COEF_16X16_START (VP9_COEF_START + 8 * VP9_COEF_SIZE_ONE_SET) +#define VP9_COEF_32X32_START (VP9_COEF_START + 12 * VP9_COEF_SIZE_ONE_SET) +#define VP9_COEF_SIZE_PLANE (2 * VP9_COEF_SIZE_ONE_SET) +#define VP9_COEF_SIZE (4 * 2 * 2 * VP9_COEF_SIZE_ONE_SET) +#define VP9_INTER_MODE_START (VP9_COEF_START+VP9_COEF_SIZE) +#define VP9_INTER_MODE_SIZE 24 /* only use 21 ( #*7)*/ +#define VP9_INTERP_START (VP9_INTER_MODE_START+VP9_INTER_MODE_SIZE) +#define VP9_INTERP_SIZE 8 +#define VP9_INTRA_INTER_START (VP9_INTERP_START+VP9_INTERP_SIZE) +#define VP9_INTRA_INTER_SIZE 4 +#define VP9_INTERP_INTRA_INTER_START VP9_INTERP_START +#define VP9_INTERP_INTRA_INTER_SIZE (VP9_INTERP_SIZE + VP9_INTRA_INTER_SIZE) +#define VP9_COMP_INTER_START \ + (VP9_INTERP_INTRA_INTER_START+VP9_INTERP_INTRA_INTER_SIZE) +#define VP9_COMP_INTER_SIZE 5 +#define VP9_COMP_REF_START (VP9_COMP_INTER_START+VP9_COMP_INTER_SIZE) +#define VP9_COMP_REF_SIZE 5 +#define VP9_SINGLE_REF_START (VP9_COMP_REF_START+VP9_COMP_REF_SIZE) +#define VP9_SINGLE_REF_SIZE 10 +#define VP9_REF_MODE_START VP9_COMP_INTER_START +#define VP9_REF_MODE_SIZE \ + (VP9_COMP_INTER_SIZE+VP9_COMP_REF_SIZE+VP9_SINGLE_REF_SIZE) +#define VP9_IF_Y_MODE_START (VP9_REF_MODE_START+VP9_REF_MODE_SIZE) +#define VP9_IF_Y_MODE_SIZE 36 +#define VP9_IF_UV_MODE_START (VP9_IF_Y_MODE_START+VP9_IF_Y_MODE_SIZE) +#define VP9_IF_UV_MODE_SIZE 92 /* only use 90*/ +#define VP9_MV_JOINTS_START (VP9_IF_UV_MODE_START+VP9_IF_UV_MODE_SIZE) +#define VP9_MV_JOINTS_SIZE 3 +#define VP9_MV_SIGN_0_START (VP9_MV_JOINTS_START+VP9_MV_JOINTS_SIZE) +#define VP9_MV_SIGN_0_SIZE 1 +#define VP9_MV_CLASSES_0_START (VP9_MV_SIGN_0_START+VP9_MV_SIGN_0_SIZE) +#define VP9_MV_CLASSES_0_SIZE 10 +#define VP9_MV_CLASS0_0_START (VP9_MV_CLASSES_0_START+VP9_MV_CLASSES_0_SIZE) +#define VP9_MV_CLASS0_0_SIZE 1 +#define VP9_MV_BITS_0_START (VP9_MV_CLASS0_0_START+VP9_MV_CLASS0_0_SIZE) +#define VP9_MV_BITS_0_SIZE 10 +#define VP9_MV_SIGN_1_START (VP9_MV_BITS_0_START+VP9_MV_BITS_0_SIZE) +#define VP9_MV_SIGN_1_SIZE 1 +#define VP9_MV_CLASSES_1_START \ + (VP9_MV_SIGN_1_START+VP9_MV_SIGN_1_SIZE) +#define VP9_MV_CLASSES_1_SIZE 10 +#define VP9_MV_CLASS0_1_START \ + (VP9_MV_CLASSES_1_START+VP9_MV_CLASSES_1_SIZE) +#define VP9_MV_CLASS0_1_SIZE 1 +#define VP9_MV_BITS_1_START \ + (VP9_MV_CLASS0_1_START+VP9_MV_CLASS0_1_SIZE) +#define VP9_MV_BITS_1_SIZE 10 +#define VP9_MV_CLASS0_FP_0_START \ + (VP9_MV_BITS_1_START+VP9_MV_BITS_1_SIZE) +#define VP9_MV_CLASS0_FP_0_SIZE 9 +#define VP9_MV_CLASS0_FP_1_START \ + (VP9_MV_CLASS0_FP_0_START+VP9_MV_CLASS0_FP_0_SIZE) +#define VP9_MV_CLASS0_FP_1_SIZE 9 +#define VP9_MV_CLASS0_HP_0_START \ + (VP9_MV_CLASS0_FP_1_START+VP9_MV_CLASS0_FP_1_SIZE) +#define VP9_MV_CLASS0_HP_0_SIZE 2 +#define VP9_MV_CLASS0_HP_1_START \ + (VP9_MV_CLASS0_HP_0_START+VP9_MV_CLASS0_HP_0_SIZE) +#define VP9_MV_CLASS0_HP_1_SIZE 2 +#define VP9_MV_START VP9_MV_JOINTS_START +#define VP9_MV_SIZE 72 /*only use 69*/ + +#define VP9_TOTAL_SIZE (VP9_MV_START + VP9_MV_SIZE) + + +/*======================================================================== + vp9_count_mem define +========================================================================*/ +#define VP9_COEF_COUNT_START 0 +#define VP9_COEF_COUNT_BAND_0_OFFSET 0 +#define VP9_COEF_COUNT_BAND_1_OFFSET \ + (VP9_COEF_COUNT_BAND_0_OFFSET + 3*5) +#define VP9_COEF_COUNT_BAND_2_OFFSET \ + (VP9_COEF_COUNT_BAND_1_OFFSET + 6*5) +#define VP9_COEF_COUNT_BAND_3_OFFSET \ + (VP9_COEF_COUNT_BAND_2_OFFSET + 6*5) +#define VP9_COEF_COUNT_BAND_4_OFFSET \ + (VP9_COEF_COUNT_BAND_3_OFFSET + 6*5) +#define VP9_COEF_COUNT_BAND_5_OFFSET \ + (VP9_COEF_COUNT_BAND_4_OFFSET + 6*5) +#define VP9_COEF_COUNT_SIZE_ONE_SET 165 /* ((3 +5*6)*5 */ +#define VP9_COEF_COUNT_4X4_START \ + (VP9_COEF_COUNT_START + 0*VP9_COEF_COUNT_SIZE_ONE_SET) +#define VP9_COEF_COUNT_8X8_START \ + (VP9_COEF_COUNT_START + 4*VP9_COEF_COUNT_SIZE_ONE_SET) +#define VP9_COEF_COUNT_16X16_START \ + (VP9_COEF_COUNT_START + 8*VP9_COEF_COUNT_SIZE_ONE_SET) +#define VP9_COEF_COUNT_32X32_START \ + (VP9_COEF_COUNT_START + 12*VP9_COEF_COUNT_SIZE_ONE_SET) +#define VP9_COEF_COUNT_SIZE_PLANE (2 * VP9_COEF_COUNT_SIZE_ONE_SET) +#define VP9_COEF_COUNT_SIZE (4 * 2 * 2 * VP9_COEF_COUNT_SIZE_ONE_SET) + +#define VP9_INTRA_INTER_COUNT_START \ + (VP9_COEF_COUNT_START+VP9_COEF_COUNT_SIZE) +#define VP9_INTRA_INTER_COUNT_SIZE (4*2) +#define VP9_COMP_INTER_COUNT_START \ + (VP9_INTRA_INTER_COUNT_START+VP9_INTRA_INTER_COUNT_SIZE) +#define VP9_COMP_INTER_COUNT_SIZE (5*2) +#define VP9_COMP_REF_COUNT_START \ + (VP9_COMP_INTER_COUNT_START+VP9_COMP_INTER_COUNT_SIZE) +#define VP9_COMP_REF_COUNT_SIZE (5*2) +#define VP9_SINGLE_REF_COUNT_START \ + (VP9_COMP_REF_COUNT_START+VP9_COMP_REF_COUNT_SIZE) +#define VP9_SINGLE_REF_COUNT_SIZE (10*2) +#define VP9_TX_MODE_COUNT_START \ + (VP9_SINGLE_REF_COUNT_START+VP9_SINGLE_REF_COUNT_SIZE) +#define VP9_TX_MODE_COUNT_SIZE (12*2) +#define VP9_SKIP_COUNT_START \ + (VP9_TX_MODE_COUNT_START+VP9_TX_MODE_COUNT_SIZE) +#define VP9_SKIP_COUNT_SIZE (3*2) +#define VP9_MV_SIGN_0_COUNT_START \ + (VP9_SKIP_COUNT_START+VP9_SKIP_COUNT_SIZE) +#define VP9_MV_SIGN_0_COUNT_SIZE (1*2) +#define VP9_MV_SIGN_1_COUNT_START \ + (VP9_MV_SIGN_0_COUNT_START+VP9_MV_SIGN_0_COUNT_SIZE) +#define VP9_MV_SIGN_1_COUNT_SIZE (1*2) +#define VP9_MV_BITS_0_COUNT_START \ + (VP9_MV_SIGN_1_COUNT_START+VP9_MV_SIGN_1_COUNT_SIZE) +#define VP9_MV_BITS_0_COUNT_SIZE (10*2) +#define VP9_MV_BITS_1_COUNT_START \ + (VP9_MV_BITS_0_COUNT_START+VP9_MV_BITS_0_COUNT_SIZE) +#define VP9_MV_BITS_1_COUNT_SIZE (10*2) +#define VP9_MV_CLASS0_HP_0_COUNT_START \ + (VP9_MV_BITS_1_COUNT_START+VP9_MV_BITS_1_COUNT_SIZE) +#define VP9_MV_CLASS0_HP_0_COUNT_SIZE (2*2) +#define VP9_MV_CLASS0_HP_1_COUNT_START \ + (VP9_MV_CLASS0_HP_0_COUNT_START+VP9_MV_CLASS0_HP_0_COUNT_SIZE) +#define VP9_MV_CLASS0_HP_1_COUNT_SIZE (2*2) +/* Start merge_tree*/ +#define VP9_INTER_MODE_COUNT_START \ + (VP9_MV_CLASS0_HP_1_COUNT_START+VP9_MV_CLASS0_HP_1_COUNT_SIZE) +#define VP9_INTER_MODE_COUNT_SIZE (7*4) +#define VP9_IF_Y_MODE_COUNT_START \ + (VP9_INTER_MODE_COUNT_START+VP9_INTER_MODE_COUNT_SIZE) +#define VP9_IF_Y_MODE_COUNT_SIZE (10*4) +#define VP9_IF_UV_MODE_COUNT_START \ + (VP9_IF_Y_MODE_COUNT_START+VP9_IF_Y_MODE_COUNT_SIZE) +#define VP9_IF_UV_MODE_COUNT_SIZE (10*10) +#define VP9_PARTITION_P_COUNT_START \ + (VP9_IF_UV_MODE_COUNT_START+VP9_IF_UV_MODE_COUNT_SIZE) +#define VP9_PARTITION_P_COUNT_SIZE (4*4*4) +#define VP9_INTERP_COUNT_START \ + (VP9_PARTITION_P_COUNT_START+VP9_PARTITION_P_COUNT_SIZE) +#define VP9_INTERP_COUNT_SIZE (4*3) +#define VP9_MV_JOINTS_COUNT_START \ + (VP9_INTERP_COUNT_START+VP9_INTERP_COUNT_SIZE) +#define VP9_MV_JOINTS_COUNT_SIZE (1 * 4) +#define VP9_MV_CLASSES_0_COUNT_START \ + (VP9_MV_JOINTS_COUNT_START+VP9_MV_JOINTS_COUNT_SIZE) +#define VP9_MV_CLASSES_0_COUNT_SIZE (1*11) +#define VP9_MV_CLASS0_0_COUNT_START \ + (VP9_MV_CLASSES_0_COUNT_START+VP9_MV_CLASSES_0_COUNT_SIZE) +#define VP9_MV_CLASS0_0_COUNT_SIZE (1*2) +#define VP9_MV_CLASSES_1_COUNT_START \ + (VP9_MV_CLASS0_0_COUNT_START+VP9_MV_CLASS0_0_COUNT_SIZE) +#define VP9_MV_CLASSES_1_COUNT_SIZE (1*11) +#define VP9_MV_CLASS0_1_COUNT_START \ + (VP9_MV_CLASSES_1_COUNT_START+VP9_MV_CLASSES_1_COUNT_SIZE) +#define VP9_MV_CLASS0_1_COUNT_SIZE (1*2) +#define VP9_MV_CLASS0_FP_0_COUNT_START \ + (VP9_MV_CLASS0_1_COUNT_START+VP9_MV_CLASS0_1_COUNT_SIZE) +#define VP9_MV_CLASS0_FP_0_COUNT_SIZE (3*4) +#define VP9_MV_CLASS0_FP_1_COUNT_START \ + (VP9_MV_CLASS0_FP_0_COUNT_START+VP9_MV_CLASS0_FP_0_COUNT_SIZE) +#define VP9_MV_CLASS0_FP_1_COUNT_SIZE (3*4) + + +#define DC_PRED 0 /* Average of above and left pixels*/ +#define V_PRED 1 /* Vertical*/ +#define H_PRED 2 /* Horizontal*/ +#define D45_PRED 3 /*Directional 45 deg = round(arctan(1/1) * 180/pi)*/ +#define D135_PRED 4 /* Directional 135 deg = 180 - 45*/ +#define D117_PRED 5 /* Directional 117 deg = 180 - 63*/ +#define D153_PRED 6 /* Directional 153 deg = 180 - 27*/ +#define D207_PRED 7 /* Directional 207 deg = 180 + 27*/ +#define D63_PRED 8 /*Directional 63 deg = round(arctan(2/1) * 180/pi)*/ +#define TM_PRED 9 /*True-motion*/ + +int clip_prob(int p) +{ + return (p > 255) ? 255 : (p < 1) ? 1 : p; +} + +#define ROUND_POWER_OF_TWO(value, n) \ + (((value) + (1 << ((n) - 1))) >> (n)) + +#define MODE_MV_COUNT_SAT 20 +static const int count_to_update_factor[MODE_MV_COUNT_SAT + 1] = { + 0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, + 70, 76, 83, 89, 96, 102, 108, 115, 121, 128 +}; + +void vp9_tree_merge_probs(unsigned int *prev_prob, unsigned int *cur_prob, + int coef_node_start, int tree_left, int tree_right, int tree_i, + int node) { + + int prob_32, prob_res, prob_shift; + int pre_prob, new_prob; + int den, m_count, get_prob, factor; + prob_32 = prev_prob[coef_node_start / 4 * 2]; + prob_res = coef_node_start & 3; + prob_shift = prob_res * 8; + pre_prob = (prob_32 >> prob_shift) & 0xff; + + den = tree_left + tree_right; + + if (den == 0) + new_prob = pre_prob; + else { + m_count = (den < MODE_MV_COUNT_SAT) ? + den : MODE_MV_COUNT_SAT; + get_prob = clip_prob( + div_r32(((int64_t)tree_left * 256 + (den >> 1)), + den)); + /*weighted_prob*/ + factor = count_to_update_factor[m_count]; + new_prob = ROUND_POWER_OF_TWO(pre_prob * (256 - factor) + + get_prob * factor, 8); + } + cur_prob[coef_node_start / 4 * 2] = (cur_prob[coef_node_start / 4 * 2] + & (~(0xff << prob_shift))) | (new_prob << prob_shift); + + /*pr_info(" - [%d][%d] 0x%02X --> 0x%02X (0x%X 0x%X) (%X)\n", + tree_i, node, pre_prob, new_prob, tree_left, tree_right, + cur_prob[coef_node_start/4*2]);*/ +} + + +/*void adapt_coef_probs(void)*/ +void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, + unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count) +{ + /* 80 * 64bits = 0xF00 ( use 0x1000 4K bytes) + unsigned int prev_prob[496*2]; + unsigned int cur_prob[496*2]; + 0x300 * 128bits = 0x3000 (32K Bytes) + unsigned int count[0x300*4];*/ + + int tx_size, coef_tx_size_start, coef_count_tx_size_start; + int plane, coef_plane_start, coef_count_plane_start; + int type, coef_type_start, coef_count_type_start; + int band, coef_band_start, coef_count_band_start; + int cxt_num; + int cxt, coef_cxt_start, coef_count_cxt_start; + int node, coef_node_start, coef_count_node_start; + + int tree_i, tree_left, tree_right; + int mvd_i; + + int count_sat = 24; + /*int update_factor = 112;*/ /*If COEF_MAX_UPDATE_FACTOR_AFTER_KEY, + use 128*/ + /* If COEF_MAX_UPDATE_FACTOR_AFTER_KEY, use 128*/ + /*int update_factor = (pic_count == 1) ? 128 : 112;*/ + int update_factor = cur_kf ? 112 : + prev_kf ? 128 : 112; + + int prob_32; + int prob_res; + int prob_shift; + int pre_prob; + + int num, den; + int get_prob; + int m_count; + int factor; + + int new_prob; + + if (debug & VP9_DEBUG_MERGE) + pr_info + ("\n ##adapt_coef_probs (pre_fc : %d ,prev_kf : %d,cur_kf : %d)##\n\n", + pre_fc, prev_kf, cur_kf); + + /*adapt_coef_probs*/ + for (tx_size = 0; tx_size < 4; tx_size++) { + coef_tx_size_start = VP9_COEF_START + + tx_size * 4 * VP9_COEF_SIZE_ONE_SET; + coef_count_tx_size_start = VP9_COEF_COUNT_START + + tx_size * 4 * VP9_COEF_COUNT_SIZE_ONE_SET; + coef_plane_start = coef_tx_size_start; + coef_count_plane_start = coef_count_tx_size_start; + for (plane = 0; plane < 2; plane++) { + coef_type_start = coef_plane_start; + coef_count_type_start = coef_count_plane_start; + for (type = 0; type < 2; type++) { + coef_band_start = coef_type_start; + coef_count_band_start = coef_count_type_start; + for (band = 0; band < 6; band++) { + if (band == 0) + cxt_num = 3; + else + cxt_num = 6; + coef_cxt_start = coef_band_start; + coef_count_cxt_start = + coef_count_band_start; + for (cxt = 0; cxt < cxt_num; cxt++) { + const int n0 = + count[coef_count_cxt_start]; + const int n1 = + count[coef_count_cxt_start + 1]; + const int n2 = + count[coef_count_cxt_start + 2]; + const int neob = + count[coef_count_cxt_start + 3]; + const int nneob = + count[coef_count_cxt_start + 4]; + const unsigned int + branch_ct[3][2] = { + { neob, nneob }, + { n0, n1 + n2 }, + { n1, n2 } + }; + coef_node_start = + coef_cxt_start; + for + (node = 0; node < 3; node++) { + prob_32 = + prev_prob[ + coef_node_start + / 4 * 2]; + prob_res = + coef_node_start & 3; + prob_shift = + prob_res * 8; + pre_prob = + (prob_32 >> prob_shift) + & 0xff; + + /*get_binary_prob*/ + num = + branch_ct[node][0]; + den = + branch_ct[node][0] + + branch_ct[node][1]; + m_count = (den < + count_sat) + ? den : count_sat; + + get_prob = + (den == 0) ? 128u : + clip_prob( + div_r32(((int64_t) + num * 256 + + (den >> 1)), + den)); + + factor = + update_factor * m_count + / count_sat; + new_prob = + ROUND_POWER_OF_TWO + (pre_prob * + (256 - factor) + + get_prob * factor, 8); + + cur_prob[coef_node_start + / 4 * 2] = + (cur_prob + [coef_node_start + / 4 * 2] & (~(0xff << + prob_shift))) | + (new_prob << + prob_shift); + + coef_node_start += 1; + } + + coef_cxt_start = + coef_cxt_start + 3; + coef_count_cxt_start = + coef_count_cxt_start + + 5; + } + if (band == 0) { + coef_band_start += 10; + coef_count_band_start += 15; + } else { + coef_band_start += 18; + coef_count_band_start += 30; + } + } + coef_type_start += VP9_COEF_SIZE_ONE_SET; + coef_count_type_start += + VP9_COEF_COUNT_SIZE_ONE_SET; + } + coef_plane_start += 2 * VP9_COEF_SIZE_ONE_SET; + coef_count_plane_start += + 2 * VP9_COEF_COUNT_SIZE_ONE_SET; + } + } + +if (cur_kf == 0) { + /*mode_mv_merge_probs - merge_intra_inter_prob*/ + for (coef_count_node_start = VP9_INTRA_INTER_COUNT_START; + coef_count_node_start < (VP9_MV_CLASS0_HP_1_COUNT_START + + VP9_MV_CLASS0_HP_1_COUNT_SIZE); coef_count_node_start += 2) { + + if (coef_count_node_start == + VP9_INTRA_INTER_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_intra_inter_prob\n"); + coef_node_start = VP9_INTRA_INTER_START; + } else if (coef_count_node_start == + VP9_COMP_INTER_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_comp_inter_prob\n"); + coef_node_start = VP9_COMP_INTER_START; + } + /* + else if (coef_count_node_start == + VP9_COMP_REF_COUNT_START) { + pr_info(" # merge_comp_inter_prob\n"); + coef_node_start = VP9_COMP_REF_START; + } + else if (coef_count_node_start == + VP9_SINGLE_REF_COUNT_START) { + pr_info(" # merge_comp_inter_prob\n"); + coef_node_start = VP9_SINGLE_REF_START; + } + */ + else if (coef_count_node_start == + VP9_TX_MODE_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_tx_mode_probs\n"); + coef_node_start = VP9_TX_MODE_START; + } else if (coef_count_node_start == + VP9_SKIP_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_skip_probs\n"); + coef_node_start = VP9_SKIP_START; + } else if (coef_count_node_start == + VP9_MV_SIGN_0_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_sign_0\n"); + coef_node_start = VP9_MV_SIGN_0_START; + } else if (coef_count_node_start == + VP9_MV_SIGN_1_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_sign_1\n"); + coef_node_start = VP9_MV_SIGN_1_START; + } else if (coef_count_node_start == + VP9_MV_BITS_0_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_bits_0\n"); + coef_node_start = VP9_MV_BITS_0_START; + } else if (coef_count_node_start == + VP9_MV_BITS_1_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_bits_1\n"); + coef_node_start = VP9_MV_BITS_1_START; + } else if (coef_count_node_start == + VP9_MV_CLASS0_HP_0_COUNT_START) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_class0_hp\n"); + coef_node_start = VP9_MV_CLASS0_HP_0_START; + } + + + den = count[coef_count_node_start] + + count[coef_count_node_start + 1]; + + prob_32 = prev_prob[coef_node_start / 4 * 2]; + prob_res = coef_node_start & 3; + prob_shift = prob_res * 8; + pre_prob = (prob_32 >> prob_shift) & 0xff; + + if (den == 0) + new_prob = pre_prob; + else { + m_count = (den < MODE_MV_COUNT_SAT) ? + den : MODE_MV_COUNT_SAT; + get_prob = + clip_prob( + div_r32(((int64_t)count[coef_count_node_start] + * 256 + (den >> 1)), + den)); + /*weighted_prob*/ + factor = count_to_update_factor[m_count]; + new_prob = + ROUND_POWER_OF_TWO(pre_prob * (256 - factor) + + get_prob * factor, 8); + } + cur_prob[coef_node_start / 4 * 2] = + (cur_prob[coef_node_start / 4 * 2] & + (~(0xff << prob_shift))) + | (new_prob << prob_shift); + + coef_node_start = coef_node_start + 1; + } + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_inter_mode_tree\n"); + coef_node_start = VP9_INTER_MODE_START; + coef_count_node_start = VP9_INTER_MODE_COUNT_START; + for (tree_i = 0; tree_i < 7; tree_i++) { + for (node = 0; node < 3; node++) { + switch (node) { + case 2: + tree_left = + count[coef_count_node_start + 1]; + tree_right = + count[coef_count_node_start + 3]; + break; + case 1: + tree_left = + count[coef_count_node_start + 0]; + tree_right = + count[coef_count_node_start + 1] + + count[coef_count_node_start + 3]; + break; + default: + tree_left = + count[coef_count_node_start + 2]; + tree_right = + count[coef_count_node_start + 0] + + count[coef_count_node_start + 1] + + count[coef_count_node_start + 3]; + break; + + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, tree_left, tree_right, + tree_i, node); + + coef_node_start = coef_node_start + 1; + } + coef_count_node_start = coef_count_node_start + 4; + } + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_intra_mode_tree\n"); + coef_node_start = VP9_IF_Y_MODE_START; + coef_count_node_start = VP9_IF_Y_MODE_COUNT_START; + for (tree_i = 0; tree_i < 14; tree_i++) { + for (node = 0; node < 9; node++) { + switch (node) { + case 8: + tree_left = + count[coef_count_node_start+D153_PRED]; + tree_right = + count[coef_count_node_start+D207_PRED]; + break; + case 7: + tree_left = + count[coef_count_node_start+D63_PRED]; + tree_right = + count[coef_count_node_start+D207_PRED] + + count[coef_count_node_start+D153_PRED]; + break; + case 6: + tree_left = + count[coef_count_node_start + D45_PRED]; + tree_right = + count[coef_count_node_start+D207_PRED] + + count[coef_count_node_start+D153_PRED] + + count[coef_count_node_start+D63_PRED]; + break; + case 5: + tree_left = + count[coef_count_node_start+D135_PRED]; + tree_right = + count[coef_count_node_start+D117_PRED]; + break; + case 4: + tree_left = + count[coef_count_node_start+H_PRED]; + tree_right = + count[coef_count_node_start+D117_PRED] + + count[coef_count_node_start+D135_PRED]; + break; + case 3: + tree_left = + count[coef_count_node_start+H_PRED] + + count[coef_count_node_start+D117_PRED] + + count[coef_count_node_start+D135_PRED]; + tree_right = + count[coef_count_node_start+D45_PRED] + + count[coef_count_node_start+D207_PRED] + + count[coef_count_node_start+D153_PRED] + + count[coef_count_node_start+D63_PRED]; + break; + case 2: + tree_left = + count[coef_count_node_start+V_PRED]; + tree_right = + count[coef_count_node_start+H_PRED] + + count[coef_count_node_start+D117_PRED] + + count[coef_count_node_start+D135_PRED] + + count[coef_count_node_start+D45_PRED] + + count[coef_count_node_start+D207_PRED] + + count[coef_count_node_start+D153_PRED] + + count[coef_count_node_start+D63_PRED]; + break; + case 1: + tree_left = + count[coef_count_node_start+TM_PRED]; + tree_right = + count[coef_count_node_start+V_PRED] + + count[coef_count_node_start+H_PRED] + + count[coef_count_node_start+D117_PRED] + + count[coef_count_node_start+D135_PRED] + + count[coef_count_node_start+D45_PRED] + + count[coef_count_node_start+D207_PRED] + + count[coef_count_node_start+D153_PRED] + + count[coef_count_node_start+D63_PRED]; + break; + default: + tree_left = + count[coef_count_node_start+DC_PRED]; + tree_right = + count[coef_count_node_start+TM_PRED] + + count[coef_count_node_start+V_PRED] + + count[coef_count_node_start+H_PRED] + + count[coef_count_node_start+D117_PRED] + + count[coef_count_node_start+D135_PRED] + + count[coef_count_node_start+D45_PRED] + + count[coef_count_node_start+D207_PRED] + + count[coef_count_node_start+D153_PRED] + + count[coef_count_node_start+D63_PRED]; + break; + + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, tree_left, tree_right, + tree_i, node); + + coef_node_start = coef_node_start + 1; + } + coef_count_node_start = coef_count_node_start + 10; + } + + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_partition_tree\n"); + coef_node_start = VP9_PARTITION_P_START; + coef_count_node_start = VP9_PARTITION_P_COUNT_START; + for (tree_i = 0; tree_i < 16; tree_i++) { + for (node = 0; node < 3; node++) { + switch (node) { + case 2: + tree_left = + count[coef_count_node_start + 2]; + tree_right = + count[coef_count_node_start + 3]; + break; + case 1: + tree_left = + count[coef_count_node_start + 1]; + tree_right = + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + break; + default: + tree_left = + count[coef_count_node_start + 0]; + tree_right = + count[coef_count_node_start + 1] + + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + break; + + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, + tree_left, tree_right, tree_i, node); + + coef_node_start = coef_node_start + 1; + } + coef_count_node_start = coef_count_node_start + 4; + } + + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_switchable_interp_tree\n"); + coef_node_start = VP9_INTERP_START; + coef_count_node_start = VP9_INTERP_COUNT_START; + for (tree_i = 0; tree_i < 4; tree_i++) { + for (node = 0; node < 2; node++) { + switch (node) { + case 1: + tree_left = + count[coef_count_node_start + 1]; + tree_right = + count[coef_count_node_start + 2]; + break; + default: + tree_left = + count[coef_count_node_start + 0]; + tree_right = + count[coef_count_node_start + 1] + + count[coef_count_node_start + 2]; + break; + + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, + tree_left, tree_right, tree_i, node); + + coef_node_start = coef_node_start + 1; + } + coef_count_node_start = coef_count_node_start + 3; + } + + if (debug & VP9_DEBUG_MERGE) + pr_info("# merge_vp9_mv_joint_tree\n"); + coef_node_start = VP9_MV_JOINTS_START; + coef_count_node_start = VP9_MV_JOINTS_COUNT_START; + for (tree_i = 0; tree_i < 1; tree_i++) { + for (node = 0; node < 3; node++) { + switch (node) { + case 2: + tree_left = + count[coef_count_node_start + 2]; + tree_right = + count[coef_count_node_start + 3]; + break; + case 1: + tree_left = + count[coef_count_node_start + 1]; + tree_right = + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + break; + default: + tree_left = + count[coef_count_node_start + 0]; + tree_right = + count[coef_count_node_start + 1] + + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + break; + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, + tree_left, tree_right, tree_i, node); + + coef_node_start = coef_node_start + 1; + } + coef_count_node_start = coef_count_node_start + 4; + } + + for (mvd_i = 0; mvd_i < 2; mvd_i++) { + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_mv_class_tree [%d] -\n", mvd_i); + coef_node_start = + mvd_i ? VP9_MV_CLASSES_1_START : VP9_MV_CLASSES_0_START; + coef_count_node_start = + mvd_i ? VP9_MV_CLASSES_1_COUNT_START + : VP9_MV_CLASSES_0_COUNT_START; + tree_i = 0; + for (node = 0; node < 10; node++) { + switch (node) { + case 9: + tree_left = + count[coef_count_node_start + 9]; + tree_right = + count[coef_count_node_start + 10]; + break; + case 8: + tree_left = + count[coef_count_node_start + 7]; + tree_right = + count[coef_count_node_start + 8]; + break; + case 7: + tree_left = + count[coef_count_node_start + 7] + + count[coef_count_node_start + 8]; + tree_right = + count[coef_count_node_start + 9] + + count[coef_count_node_start + 10]; + break; + case 6: + tree_left = + count[coef_count_node_start + 6]; + tree_right = + count[coef_count_node_start + 7] + + count[coef_count_node_start + 8] + + count[coef_count_node_start + 9] + + count[coef_count_node_start + 10]; + break; + case 5: + tree_left = + count[coef_count_node_start + 4]; + tree_right = + count[coef_count_node_start + 5]; + break; + case 4: + tree_left = + count[coef_count_node_start + 4] + + count[coef_count_node_start + 5]; + tree_right = + count[coef_count_node_start + 6] + + count[coef_count_node_start + 7] + + count[coef_count_node_start + 8] + + count[coef_count_node_start + 9] + + count[coef_count_node_start + 10]; + break; + case 3: + tree_left = + count[coef_count_node_start + 2]; + tree_right = + count[coef_count_node_start + 3]; + break; + case 2: + tree_left = + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + tree_right = + count[coef_count_node_start + 4] + + count[coef_count_node_start + 5] + + count[coef_count_node_start + 6] + + count[coef_count_node_start + 7] + + count[coef_count_node_start + 8] + + count[coef_count_node_start + 9] + + count[coef_count_node_start + 10]; + break; + case 1: + tree_left = + count[coef_count_node_start + 1]; + tree_right = + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3] + + count[coef_count_node_start + 4] + + count[coef_count_node_start + 5] + + count[coef_count_node_start + 6] + + count[coef_count_node_start + 7] + + count[coef_count_node_start + 8] + + count[coef_count_node_start + 9] + + count[coef_count_node_start + 10]; + break; + default: + tree_left = + count[coef_count_node_start + 0]; + tree_right = + count[coef_count_node_start + 1] + + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3] + + count[coef_count_node_start + 4] + + count[coef_count_node_start + 5] + + count[coef_count_node_start + 6] + + count[coef_count_node_start + 7] + + count[coef_count_node_start + 8] + + count[coef_count_node_start + 9] + + count[coef_count_node_start + 10]; + break; + + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, tree_left, tree_right, + tree_i, node); + + coef_node_start = coef_node_start + 1; + } + + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_mv_class0_tree [%d] -\n", mvd_i); + coef_node_start = + mvd_i ? VP9_MV_CLASS0_1_START : VP9_MV_CLASS0_0_START; + coef_count_node_start = + mvd_i ? VP9_MV_CLASS0_1_COUNT_START : + VP9_MV_CLASS0_0_COUNT_START; + tree_i = 0; + node = 0; + tree_left = count[coef_count_node_start + 0]; + tree_right = count[coef_count_node_start + 1]; + + vp9_tree_merge_probs(prev_prob, cur_prob, coef_node_start, + tree_left, tree_right, tree_i, node); + if (debug & VP9_DEBUG_MERGE) + pr_info(" # merge_vp9_mv_fp_tree_class0_fp [%d] -\n", + mvd_i); + coef_node_start = + mvd_i ? VP9_MV_CLASS0_FP_1_START : + VP9_MV_CLASS0_FP_0_START; + coef_count_node_start = + mvd_i ? VP9_MV_CLASS0_FP_1_COUNT_START : + VP9_MV_CLASS0_FP_0_COUNT_START; + for (tree_i = 0; tree_i < 3; tree_i++) { + for (node = 0; node < 3; node++) { + switch (node) { + case 2: + tree_left = + count[coef_count_node_start + 2]; + tree_right = + count[coef_count_node_start + 3]; + break; + case 1: + tree_left = + count[coef_count_node_start + 1]; + tree_right = + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + break; + default: + tree_left = + count[coef_count_node_start + 0]; + tree_right = + count[coef_count_node_start + 1] + + count[coef_count_node_start + 2] + + count[coef_count_node_start + 3]; + break; + + } + + vp9_tree_merge_probs(prev_prob, cur_prob, + coef_node_start, tree_left, tree_right, + tree_i, node); + + coef_node_start = coef_node_start + 1; + } + coef_count_node_start = coef_count_node_start + 4; + } + + } /* for mvd_i (mvd_y or mvd_x)*/ +} + +} + + +static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) +{ + + decoder_mmu_box_free(pbi->mmu_box); + pbi->mmu_box = NULL; + + if (pbi->bmmu_box) + decoder_bmmu_box_free(pbi->bmmu_box); + pbi->bmmu_box = NULL; +} + +#ifndef VP9_10B_MMU +static void init_buf_list(struct VP9Decoder_s *pbi) +{ + int i; + int buf_size; +#ifndef VP9_10B_MMU + int mc_buffer_end = pbi->mc_buf->buf_start + pbi->mc_buf->buf_size; +#endif + pbi->used_buf_num = max_buf_num; + + if (pbi->used_buf_num > MAX_BUF_NUM) + pbi->used_buf_num = MAX_BUF_NUM; + if (buf_alloc_size > 0) { + buf_size = buf_alloc_size; + if (debug) + pr_info("[Buffer Management] init_buf_list:\n"); + } else { + int pic_width = pbi->init_pic_w; + int pic_height = pbi->init_pic_h; + + /*SUPPORT_10BIT*/ + int losless_comp_header_size = compute_losless_comp_header_size + (pic_width, pic_height); + int losless_comp_body_size = compute_losless_comp_body_size + (pic_width, pic_height, buf_alloc_depth == 10); + int mc_buffer_size = losless_comp_header_size + + losless_comp_body_size; + int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; + if (double_write_mode) { + int pic_width_dw = (double_write_mode == 2) ? + pic_width / 2 : pic_width; + int pic_height_dw = (double_write_mode == 2) ? + pic_height / 2 : pic_height; + int lcu_size = 64; /*fixed 64*/ + int pic_width_64 = (pic_width_dw + 63) & (~0x3f); + int pic_height_32 = (pic_height_dw + 31) & (~0x1f); + int pic_width_lcu = + (pic_width_64 % lcu_size) ? pic_width_64 / lcu_size + + 1 : pic_width_64 / lcu_size; + int pic_height_lcu = + (pic_height_32 % lcu_size) ? pic_height_32 / lcu_size + + 1 : pic_height_32 / lcu_size; + int lcu_total = pic_width_lcu * pic_height_lcu; + int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; + int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; + /*64k alignment*/ + buf_size = ((mc_buffer_size_u_v_h << 16) * 3); + } else + buf_size = 0; + + if (mc_buffer_size & 0xffff) { /*64k alignment*/ + mc_buffer_size_h += 1; + } + if ((double_write_mode & 0x10) == 0) + buf_size += (mc_buffer_size_h << 16); + if (debug) { + pr_info + ("init_buf_list num %d (width %d height %d):\n", + pbi->used_buf_num, pic_width, pic_height); + } + } + + for (i = 0; i < pbi->used_buf_num; i++) { + if (((i + 1) * buf_size) > pbi->mc_buf->buf_size) { + if (use_cma) + pbi->use_cma_flag = 1; + else { + if (debug) { + pr_info("%s maximum buf size is used\n", + __func__); + } + break; + } + } +#ifndef VP9_10B_MMU + pbi->m_BUF[i].alloc_flag = 0; + pbi->m_BUF[i].index = i; + + if (use_cma == 2) + pbi->use_cma_flag = 1; + if (pbi->use_cma_flag) { + if (!decoder_bmmu_box_alloc_idx_wait( + pbi->bmmu_box, + i, + buf_size, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR)) { + pbi->m_BUF[i].alloc_addr = + decoder_bmmu_box_get_phy_addr( + pbi->bmmu_box, + i); + pbi->m_BUF[i].cma_page_count = + PAGE_ALIGN(buf_size) / PAGE_SIZE; + pr_info("CMA malloc ok %d\n", i); + } else { + pbi->m_BUF[i].cma_page_count = 0; + pr_info("CMA malloc failed %d\n", i); + if (i <= 5) { + pbi->fatal_error |= + DECODER_FATAL_ERROR_NO_MEM; + } + break; + } + pbi->m_BUF[i].start_adr = pbi->m_BUF[i].alloc_addr; + } else { + pbi->m_BUF[i].cma_page_count = 0; + pbi->m_BUF[i].alloc_addr = 0; + pbi->m_BUF[i].start_adr = + pbi->mc_buf->buf_start + i * buf_size; + } + pbi->m_BUF[i].size = buf_size; + pbi->m_BUF[i].free_start_adr = pbi->m_BUF[i].start_adr; + + if (((pbi->m_BUF[i].start_adr + buf_size) > mc_buffer_end) + && (pbi->m_BUF[i].alloc_addr == 0)) { + if (debug) { + pr_info + ("Max mc buffer or mpred_mv buffer is used\n"); + } + break; + } + + if (debug) { + pr_info("Buffer %d: start_adr %p size %x\n", i, + (void *)pbi->m_BUF[i].start_adr, + pbi->m_BUF[i].size); + } +#endif + } + pbi->buf_num = i; +} +#endif +static int config_pic(struct VP9Decoder_s *pbi, + struct PIC_BUFFER_CONFIG_s *pic_config, + unsigned long last_disp_addr) +{ + int ret = -1; + int i; + int pic_width = pbi->init_pic_w; + int pic_height = pbi->init_pic_h; + int MV_MEM_UNIT = 0x240; + int lcu_size = 64; /*fixed 64*/ + int pic_width_64 = (pic_width + 63) & (~0x3f); + int pic_height_32 = (pic_height + 31) & (~0x1f); + int pic_width_lcu = (pic_width_64 % lcu_size) ? + pic_width_64 / lcu_size + 1 + : pic_width_64 / lcu_size; + int pic_height_lcu = (pic_height_32 % lcu_size) ? + pic_height_32 / lcu_size + 1 + : pic_height_32 / lcu_size; + int lcu_total = pic_width_lcu * pic_height_lcu; + + u32 mpred_mv_end = pbi->work_space_buf->mpred_mv.buf_start + + pbi->work_space_buf->mpred_mv.buf_size; + u32 y_adr = 0; + int buf_size = 0; + + int losless_comp_header_size = + compute_losless_comp_header_size(pic_width , + pic_height); + int losless_comp_body_size = compute_losless_comp_body_size(pic_width , + pic_height, buf_alloc_depth == 10); + int mc_buffer_size = losless_comp_header_size + losless_comp_body_size; + int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16; + int mc_buffer_size_u_v = 0; + int mc_buffer_size_u_v_h = 0; + if (double_write_mode) { + int pic_width_dw = (double_write_mode == 2) ? + pic_width / 2 : pic_width; + int pic_height_dw = (double_write_mode == 2) ? + pic_height / 2 : pic_height; + int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f); + int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f); + int pic_width_lcu_dw = (pic_width_64_dw % lcu_size) ? + pic_width_64_dw / lcu_size + 1 + : pic_width_64_dw / lcu_size; + int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ? + pic_height_32_dw / lcu_size + 1 + : pic_height_32_dw / lcu_size; + int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; + + mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; + mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; + /*64k alignment*/ + buf_size = ((mc_buffer_size_u_v_h << 16) * 3); + buf_size = ((buf_size + 0xffff) >> 16) << 16; + } + if (mc_buffer_size & 0xffff) /*64k alignment*/ + mc_buffer_size_h += 1; +#ifndef VP9_10B_MMU + if ((double_write_mode & 0x10) == 0) + buf_size += (mc_buffer_size_h << 16); +#endif + +#ifdef VP9_10B_MMU + if ((pbi->work_space_buf->cm_header.buf_start + + ((pic_config->index + 2) + * MMU_COMPRESS_HEADER_SIZE)) + > (pbi->work_space_buf->cm_header.buf_start + + pbi->work_space_buf->cm_header.buf_size)) { + pr_info("MMU header_adr allocate fail\n"); + return -1; + } + + pic_config->header_adr = pbi->work_space_buf->cm_header.buf_start + + (pic_config->index * MMU_COMPRESS_HEADER_SIZE); + if (last_disp_addr && pic_config->header_adr == last_disp_addr) { + /*if same as disp add used last one.*/ + pr_info("same as disp %d: %ld\n", + pic_config->index, pic_config->header_adr); + pic_config->header_adr = + pbi->work_space_buf->cm_header.buf_start + + (FRAME_BUFFERS * MMU_COMPRESS_HEADER_SIZE); + } + if (debug & VP9_DEBUG_BUFMGR) { + pr_info("MMU header_adr %d: %ld\n", + pic_config->index, pic_config->header_adr); + } +#endif + + i = pic_config->index; + if ((pbi->work_space_buf->mpred_mv.buf_start + + (((i + 1) * lcu_total) * MV_MEM_UNIT)) + <= mpred_mv_end +#ifdef VP9_10B_MMU +#endif + ) { + if (debug) { + pr_err("start %x .size=%d\n", + pbi->mc_buf_spec.buf_start + i * buf_size, + buf_size); + } + +#ifndef VP9_10B_MMU + for (i = 0; i < pbi->buf_num; i++) { + y_adr = ((pbi->m_BUF[i].free_start_adr + + 0xffff) >> 16) << 16; + /*64k alignment*/ + if ((y_adr+buf_size) <= (pbi->m_BUF[i].start_adr+ + pbi->m_BUF[i].size)) { + pbi->m_BUF[i].free_start_adr = + y_adr + buf_size; + break; + } + } + if (i < pbi->buf_num) +#else + if ((pbi->mc_buf->buf_start + (i + 1) * buf_size) < + pbi->mc_buf->buf_end) + y_adr = pbi->mc_buf->buf_start + i * buf_size; + else { + if (!decoder_bmmu_box_alloc_idx_wait( + pbi->bmmu_box, + i, + buf_size, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR + )) { + pic_config->cma_alloc_addr = + decoder_bmmu_box_get_phy_addr( + pbi->bmmu_box, + i); + } else { + pr_err("alloc cma buffer failed %d\n", i); + } + if (pic_config->cma_alloc_addr) + y_adr = pic_config->cma_alloc_addr; + else + return -1; + } +#endif + { + /*ensure get_pic_by_POC() + not get the buffer not decoded*/ + pic_config->BUF_index = i; + pic_config->lcu_total = lcu_total; + + pic_config->comp_body_size = losless_comp_body_size; + pic_config->buf_size = buf_size; +#ifndef VP9_10B_MMU + pic_config->mc_y_adr = y_adr; +#endif + pic_config->mc_canvas_y = pic_config->index; + pic_config->mc_canvas_u_v = pic_config->index; +#ifndef VP9_10B_MMU + if (double_write_mode & 0x10) { + pic_config->mc_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); + + pic_config->mc_canvas_y = + (pic_config->index << 1); + pic_config->mc_canvas_u_v = + (pic_config->index << 1) + 1; + + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = pic_config->mc_u_v_adr; + } else +#endif + if (double_write_mode) { + pic_config->dw_y_adr = y_adr +#ifndef VP9_10B_MMU + + (mc_buffer_size_h << 16) +#endif + ; + pic_config->dw_u_v_adr = pic_config->dw_y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); + } + + pic_config->mpred_mv_wr_start_addr = + pbi->work_space_buf->mpred_mv.buf_start + + ((pic_config->index * lcu_total) + * MV_MEM_UNIT); + + if (debug) { + pr_info + ("%s index %d BUF_index %d mc_y_adr %lx ", + __func__, pic_config->index, + pic_config->BUF_index, + pic_config->mc_y_adr); + pr_info + ("comp_body_size %x comp_buf_size %x ", + pic_config->comp_body_size, + pic_config->buf_size); + pr_info + ("mpred_mv_wr_start_adr %ld\n", + pic_config->mpred_mv_wr_start_addr); + pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n", + pic_config->dw_y_adr, + pic_config->dw_u_v_adr); + } + ret = 0; + } + } + return ret; +} + +static void init_pic_list(struct VP9Decoder_s *pbi) +{ + int i; + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s *pic_config; + struct vframe_s vf; + unsigned long disp_addr = 0; + + if (!get_video0_frame_info(&vf)) { + if (vf.type & VIDTYPE_SCATTER) { + /*sc only used header.*/ + disp_addr = vf.compHeadAddr; + } else if (vf.type & VIDTYPE_COMPRESS) { + /*sc checked body.*/ + disp_addr = vf.compBodyAddr; + } else { + struct canvas_s cur_canvas; + canvas_read(vf.canvas0Addr & 0xff, &cur_canvas); + disp_addr = cur_canvas.addr; + } + } + + for (i = 0; i < FRAME_BUFFERS; i++) { + pic_config = &cm->buffer_pool->frame_bufs[i].buf; + pic_config->index = i; + pic_config->BUF_index = -1; + if (config_pic(pbi, pic_config, disp_addr) < 0) { + if (debug) + pr_info("Config_pic %d fail\n", + pic_config->index); + pic_config->index = -1; + break; + } + pic_config->y_crop_width = pbi->init_pic_w; + pic_config->y_crop_height = pbi->init_pic_h; + /*set_canvas(pic_config);*/ + } + for (; i < FRAME_BUFFERS; i++) { + pic_config = &cm->buffer_pool->frame_bufs[i].buf; + pic_config->index = -1; + pic_config->BUF_index = -1; + } + +} + + +static void init_pic_list_hw(struct VP9Decoder_s *pbi) +{ + int i; + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s *pic_config; + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (0x1 << 2)); + + + for (i = 0; i < FRAME_BUFFERS; i++) { + pic_config = &cm->buffer_pool->frame_bufs[i].buf; + if (pic_config->index < 0) + break; + +#ifdef VP9_10B_MMU + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + pic_config->header_adr + | (pic_config->mc_canvas_y << 8)|0x1);*/ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->header_adr >> 5); +#else + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + pic_config->mc_y_adr + | (pic_config->mc_canvas_y << 8) | 0x1);*/ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_y_adr >> 5); +#endif +#ifndef LOSLESS_COMPRESS_MODE + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + pic_config->mc_u_v_adr + | (pic_config->mc_canvas_u_v << 8)| 0x1);*/ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_u_v_adr >> 5); +#endif + } + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); + + /*Zero out canvas registers in IPP -- avoid simulation X*/ + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (0 << 1) | 1); + for (i = 0; i < 32; i++) + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); +} + + +static void dump_pic_list(struct VP9Decoder_s *pbi) +{ + return; +} + +static int config_pic_size(struct VP9Decoder_s *pbi, unsigned short bit_depth) +{ +#ifdef LOSLESS_COMPRESS_MODE + unsigned int data32; +#endif + int losless_comp_header_size, losless_comp_body_size; + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; + frame_width = cur_pic_config->y_crop_width; + frame_height = cur_pic_config->y_crop_height; + cur_pic_config->bit_depth = bit_depth; + losless_comp_header_size = + compute_losless_comp_header_size(cur_pic_config->y_crop_width, + cur_pic_config->y_crop_height); + losless_comp_body_size = + compute_losless_comp_body_size(cur_pic_config->y_crop_width, + cur_pic_config->y_crop_height, (bit_depth == VPX_BITS_10)); + cur_pic_config->comp_body_size = losless_comp_body_size; +#ifdef LOSLESS_COMPRESS_MODE + data32 = READ_VREG(HEVC_SAO_CTRL5); + if (bit_depth == VPX_BITS_10) + data32 &= ~(1 << 9); + else + data32 |= (1 << 9); + + WRITE_VREG(HEVC_SAO_CTRL5, data32); + +#ifdef VP9_10B_MMU + /*bit[4] : paged_mem_mode*/ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); +#else + /*bit[3] smem mdoe*/ + if (bit_depth == VPX_BITS_10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); + else + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); +#endif + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); + /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ + WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); +#else + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); +#endif + return 0; +} + +static int config_mc_buffer(struct VP9Decoder_s *pbi, unsigned short bit_depth) +{ + int i; + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; + uint8_t scale_enable = 0; + + if (debug&VP9_DEBUG_BUFMGR) + pr_info("config_mc_buffer entered .....\n"); + + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (0 << 1) | 1); + for (i = 0; i < REFS_PER_FRAME; ++i) { + struct PIC_BUFFER_CONFIG_s *pic_config = cm->frame_refs[i].buf; + + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, + (pic_config->mc_canvas_u_v << 16) + | (pic_config->mc_canvas_u_v << 8) + | pic_config->mc_canvas_y); + if (debug & VP9_DEBUG_BUFMGR_MORE) + pr_info("refid %x mc_canvas_u_v %x mc_canvas_y %x\n", + i, pic_config->mc_canvas_u_v, + pic_config->mc_canvas_y); + } + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (16 << 8) | (0 << 1) | 1); + for (i = 0; i < REFS_PER_FRAME; ++i) { + struct PIC_BUFFER_CONFIG_s *pic_config = cm->frame_refs[i].buf; + + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, + (pic_config->mc_canvas_u_v << 16) + | (pic_config->mc_canvas_u_v << 8) + | pic_config->mc_canvas_y); + } + + /*auto_inc start index:0 field:0*/ + WRITE_VREG(VP9D_MPP_REFINFO_TBL_ACCCONFIG, 0x1 << 2); + /*index 0:last 1:golden 2:altref*/ + for (i = 0; i < REFS_PER_FRAME; i++) { + int ref_pic_body_size; + struct PIC_BUFFER_CONFIG_s *pic_config = cm->frame_refs[i].buf; + + WRITE_VREG(VP9D_MPP_REFINFO_DATA, pic_config->y_crop_width); + WRITE_VREG(VP9D_MPP_REFINFO_DATA, pic_config->y_crop_height); + + if (pic_config->y_crop_width != cur_pic_config->y_crop_width || + pic_config->y_crop_height != cur_pic_config->y_crop_height) { + scale_enable |= (1 << i); + } + ref_pic_body_size = + compute_losless_comp_body_size(pic_config->y_crop_width, + pic_config->y_crop_height, (bit_depth == VPX_BITS_10)); + WRITE_VREG(VP9D_MPP_REFINFO_DATA, + (pic_config->y_crop_width << 14) + / cur_pic_config->y_crop_width); + WRITE_VREG(VP9D_MPP_REFINFO_DATA, + (pic_config->y_crop_height << 14) + / cur_pic_config->y_crop_height); +#ifdef VP9_10B_MMU + WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0); +#else + WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5); +#endif + } + WRITE_VREG(VP9D_MPP_REF_SCALE_ENBL, scale_enable); + return 0; +} + +static void clear_mpred_hw(struct VP9Decoder_s *pbi) +{ + unsigned int data32; + data32 = READ_VREG(HEVC_MPRED_CTRL4); + data32 &= (~(1 << 6)); + WRITE_VREG(HEVC_MPRED_CTRL4, data32); +} + +static void config_mpred_hw(struct VP9Decoder_s *pbi) +{ + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; + struct PIC_BUFFER_CONFIG_s *last_frame_pic_config = + &cm->prev_frame->buf; + + unsigned int data32; + int mpred_curr_lcu_x; + int mpred_curr_lcu_y; + int mpred_mv_rd_end_addr; + int MV_MEM_UNIT = 0x240; + + + mpred_mv_rd_end_addr = last_frame_pic_config->mpred_mv_wr_start_addr + + (last_frame_pic_config->lcu_total * MV_MEM_UNIT); + + data32 = READ_VREG(HEVC_MPRED_CURR_LCU); + mpred_curr_lcu_x = data32 & 0xffff; + mpred_curr_lcu_y = (data32 >> 16) & 0xffff; + + if (debug & VP9_DEBUG_BUFMGR) + pr_info("cur pic_config index %d col pic_config index %d\n", + cur_pic_config->index, last_frame_pic_config->index); + WRITE_VREG(HEVC_MPRED_CTRL3, 0x24122412); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, + pbi->work_space_buf->mpred_above.buf_start); + + data32 = READ_VREG(HEVC_MPRED_CTRL4); + + data32 &= (~(1 << 6)); + data32 |= (cm->use_prev_frame_mvs << 6); + WRITE_VREG(HEVC_MPRED_CTRL4, data32); + + WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, + cur_pic_config->mpred_mv_wr_start_addr); + WRITE_VREG(HEVC_MPRED_MV_WPTR, cur_pic_config->mpred_mv_wr_start_addr); + + WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, + last_frame_pic_config->mpred_mv_wr_start_addr); + WRITE_VREG(HEVC_MPRED_MV_RPTR, + last_frame_pic_config->mpred_mv_wr_start_addr); + /*data32 = ((pbi->lcu_x_num - pbi->tile_width_lcu)*MV_MEM_UNIT);*/ + /*WRITE_VREG(HEVC_MPRED_MV_WR_ROW_JUMP,data32);*/ + /*WRITE_VREG(HEVC_MPRED_MV_RD_ROW_JUMP,data32);*/ + WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, mpred_mv_rd_end_addr); + +} + +static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) +{ + struct VP9_Common_s *cm = &pbi->common; + struct PIC_BUFFER_CONFIG_s *pic_config = &cm->cur_frame->buf; + + unsigned int data32; + int lcu_size = 64; + int mc_buffer_size_u_v = + pic_config->lcu_total * lcu_size*lcu_size/2; + int mc_buffer_size_u_v_h = + (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ + +#ifndef VP9_10B_MMU + if ((double_write_mode & 0x10) == 0) + WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic_config->mc_y_adr); +#endif + if (double_write_mode) { + WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr); + WRITE_VREG(HEVC_SAO_C_START_ADDR, pic_config->dw_u_v_adr); + WRITE_VREG(HEVC_SAO_Y_WPTR, pic_config->dw_y_adr); + WRITE_VREG(HEVC_SAO_C_WPTR, pic_config->dw_u_v_adr); + } else { + WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); + WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); + } +#ifdef VP9_10B_MMU + WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr); +#endif + data32 = (mc_buffer_size_u_v_h << 16) << 1; + /*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n", + data32, mc_buffer_size_u_v_h, pic_config->lcu_total);*/ + WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); + + data32 = (mc_buffer_size_u_v_h << 16); + WRITE_VREG(HEVC_SAO_C_LENGTH, data32); + +#ifdef VP9_10B_NV21 +#ifdef DOS_PROJECT + data32 = READ_VREG(HEVC_SAO_CTRL1); + data32 &= (~0x3000); + /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ + data32 |= (MEM_MAP_MODE << 12); + data32 &= (~0x3); + data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/ + WRITE_VREG(HEVC_SAO_CTRL1, data32); + /*[23:22] dw_v1_ctrl [21:20] dw_v0_ctrl [19:18] dw_h1_ctrl + [17:16] dw_h0_ctrl*/ + data32 = READ_VREG(HEVC_SAO_CTRL5); + /*set them all 0 for H265_NV21 (no down-scale)*/ + data32 &= ~(0xff << 16); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + ata32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); + data32 &= (~0x30); + /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ + data32 |= (MEM_MAP_MODE << 4); + WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); +#else + /*m8baby test1902*/ + data32 = READ_VREG(HEVC_SAO_CTRL1); + data32 &= (~0x3000); + /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ + data32 |= (MEM_MAP_MODE << 12); + data32 &= (~0xff0); + /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/ + data32 |= 0x880; /*.Big-Endian per 64-bit */ + data32 &= (~0x3); + data32 |= 0x1; /*[1]:dw_disable [0]:cm_disable*/ + WRITE_VREG(HEVC_SAO_CTRL1, data32); + /* [23:22] dw_v1_ctrl [21:20] dw_v0_ctrl + [19:18] dw_h1_ctrl [17:16] dw_h0_ctrl*/ + data32 = READ_VREG(HEVC_SAO_CTRL5); + /* set them all 0 for H265_NV21 (no down-scale)*/ + data32 &= ~(0xff << 16); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + + data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); + data32 &= (~0x30); + /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ + data32 |= (MEM_MAP_MODE << 4); + data32 &= (~0xF); + data32 |= 0x8; /*Big-Endian per 64-bit*/ + WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); +#endif +#else + data32 = READ_VREG(HEVC_SAO_CTRL1); + data32 &= (~0x3000); + data32 |= (MEM_MAP_MODE << + 12); /* [13:12] axi_aformat, 0-Linear, + 1-32x32, 2-64x32 */ + data32 &= (~0xff0); + /* data32 |= 0x670; // Big-Endian per 64-bit */ + data32 |= endian; /* Big-Endian per 64-bit */ + data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ + if (double_write_mode == 0) + data32 |= 0x2; /*disable double write*/ +#ifndef VP9_10B_MMU + else + if (double_write_mode & 0x10) + data32 |= 0x1; /*disable cm*/ +#endif + WRITE_VREG(HEVC_SAO_CTRL1, data32); + + if (double_write_mode & 0x10) { + /* [23:22] dw_v1_ctrl + [21:20] dw_v0_ctrl + [19:18] dw_h1_ctrl + [17:16] dw_h0_ctrl + */ + data32 = READ_VREG(HEVC_SAO_CTRL5); + /*set them all 0 for H265_NV21 (no down-scale)*/ + data32 &= ~(0xff << 16); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + } else { + data32 = READ_VREG(HEVC_SAO_CTRL5); + data32 &= (~(0xff << 16)); + if (double_write_mode != 1) + data32 |= (0xff<<16); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + } + + data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); + data32 &= (~0x30); + /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ + data32 |= (mem_map_mode << + 4); + data32 &= (~0xF); + data32 |= 0xf; /* valid only when double write only */ + /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ + WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); +#endif +} + +static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi) +{ + struct BuffInfo_s *buf_spec = pbi->work_space_buf; +#ifdef LOSLESS_COMPRESS_MODE + int losless_comp_header_size = + compute_losless_comp_header_size(pbi->init_pic_w, + pbi->init_pic_h); + int losless_comp_body_size = + compute_losless_comp_body_size(pbi->init_pic_w, + pbi->init_pic_h, buf_alloc_depth == 10); +#endif +#ifdef VP9_10B_MMU + unsigned int data32; +#endif + if (debug) + pr_info("%s %x %x %x %x %x %x %x %x %x %x %x %x\n", + __func__, + buf_spec->ipp.buf_start, + buf_spec->start_adr, + buf_spec->short_term_rps.buf_start, + buf_spec->vps.buf_start, + buf_spec->sps.buf_start, + buf_spec->pps.buf_start, + buf_spec->sao_up.buf_start, + buf_spec->swap_buf.buf_start, + buf_spec->swap_buf2.buf_start, + buf_spec->scalelut.buf_start, + buf_spec->dblk_para.buf_start, + buf_spec->dblk_data.buf_start); + WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); + if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) + WRITE_VREG(HEVC_RPM_BUFFER, (u32)pbi->rpm_phy_addr); + WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start); + /*WRITE_VREG(HEVC_VPS_BUFFER, buf_spec->vps.buf_start);*/ + /*WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);*/ + WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); + WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, buf_spec->swap_buf.buf_start); + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start); + WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); + + /* cfg_p_addr */ + WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); + /* cfg_d_addr */ + WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); + +#ifdef LOSLESS_COMPRESS_MODE +#ifdef VP9_10B_MMU + /*bit[4] : paged_mem_mode*/ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); +#else + /*if(cur_pic_config->bit_depth == VPX_BITS_10) + WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (0<<3));*/ + /*bit[3] smem mdoe*/ + /*else WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (1<<3));*/ + /*bit[3] smem mdoe*/ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); +#endif + /*WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL2,(losless_comp_body_size >> 5));*/ + /*WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ +/*8-bit mode */ + WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); +#else + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); +#endif + +#ifdef VP9_10B_MMU + WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); + WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start + + buf_spec->mmu_vbh.buf_size/2); + /*data32 = READ_VREG(P_HEVC_SAO_CTRL9);*/ + /*data32 |= 0x1;*/ + /*WRITE_VREG(P_HEVC_SAO_CTRL9, data32);*/ + + /* use HEVC_CM_HEADER_START_ADDR */ + data32 = READ_VREG(HEVC_SAO_CTRL5); + data32 |= (1<<10); + WRITE_VREG(HEVC_SAO_CTRL5, data32); + +#endif + + WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start); + + if (debug & VP9_DEBUG_UCODE) + WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr); + + /**/ + WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr); + WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr); +#ifdef VP9_10B_MMU + WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr); +#endif + +} + + +#ifdef VP9_LPF_LVL_UPDATE +/* + * Defines, declarations, sub-functions for vp9 de-block loop + filter Thr/Lvl table update + * - struct segmentation is for loop filter only (removed something) + * - function "vp9_loop_filter_init" and "vp9_loop_filter_frame_init" will + be instantiated in C_Entry + * - vp9_loop_filter_init run once before decoding start + * - vp9_loop_filter_frame_init run before every frame decoding start + * - set video format to VP9 is in vp9_loop_filter_init + */ +#define MAX_LOOP_FILTER 63 +#define MAX_REF_LF_DELTAS 4 +#define MAX_MODE_LF_DELTAS 2 +/*#define INTRA_FRAME 0*/ +/*#define LAST_FRAME 1*/ +/*#define MAX_REF_FRAMES 4*/ +#define SEGMENT_DELTADATA 0 +#define SEGMENT_ABSDATA 1 +#define MAX_SEGMENTS 8 +/*.#define SEG_TREE_PROBS (MAX_SEGMENTS-1)*/ +/*no use for loop filter, if this struct for common use, pls add it back*/ +/*#define PREDICTION_PROBS 3*/ +/* no use for loop filter, if this struct for common use, pls add it back*/ + +enum SEG_LVL_FEATURES { + SEG_LVL_ALT_Q = 0, /*Use alternate Quantizer ....*/ + SEG_LVL_ALT_LF = 1, /*Use alternate loop filter value...*/ + SEG_LVL_REF_FRAME = 2, /*Optional Segment reference frame*/ + SEG_LVL_SKIP = 3, /*Optional Segment (0,0) + skip mode*/ + SEG_LVL_MAX = 4 /*Number of features supported*/ +}; + +struct segmentation { + uint8_t enabled; + uint8_t update_map; + uint8_t update_data; + uint8_t abs_delta; + uint8_t temporal_update; + + /*no use for loop filter, if this struct + for common use, pls add it back*/ + /*vp9_prob tree_probs[SEG_TREE_PROBS]; */ + /* no use for loop filter, if this struct + for common use, pls add it back*/ + /*vp9_prob pred_probs[PREDICTION_PROBS];*/ + + int16_t feature_data[MAX_SEGMENTS][SEG_LVL_MAX]; + unsigned int feature_mask[MAX_SEGMENTS]; +}; + +struct loop_filter_thresh { + uint8_t mblim; + uint8_t lim; + uint8_t hev_thr; +}; + +struct loop_filter_info_n { + struct loop_filter_thresh lfthr[MAX_LOOP_FILTER + 1]; + uint8_t lvl[MAX_SEGMENTS][MAX_REF_FRAMES][MAX_MODE_LF_DELTAS]; +}; + +struct loopfilter { + int filter_level; + + int sharpness_level; + int last_sharpness_level; + + uint8_t mode_ref_delta_enabled; + uint8_t mode_ref_delta_update; + + /*0 = Intra, Last, GF, ARF*/ + signed char ref_deltas[MAX_REF_LF_DELTAS]; + signed char last_ref_deltas[MAX_REF_LF_DELTAS]; + + /*0 = ZERO_MV, MV*/ + signed char mode_deltas[MAX_MODE_LF_DELTAS]; + signed char last_mode_deltas[MAX_MODE_LF_DELTAS]; +}; + +static int vp9_clamp(int value, int low, int high) +{ + return value < low ? low : (value > high ? high : value); +} + +int segfeature_active(struct segmentation *seg, + int segment_id, + enum SEG_LVL_FEATURES feature_id) { + return seg->enabled && + (seg->feature_mask[segment_id] & (1 << feature_id)); +} + +int get_segdata(struct segmentation *seg, int segment_id, + enum SEG_LVL_FEATURES feature_id) { + return seg->feature_data[segment_id][feature_id]; +} + +static void vp9_update_sharpness(struct loop_filter_info_n *lfi, + int sharpness_lvl) +{ + int lvl; + /*For each possible value for the loop filter fill out limits*/ + for (lvl = 0; lvl <= MAX_LOOP_FILTER; lvl++) { + /*Set loop filter parameters that control sharpness.*/ + int block_inside_limit = lvl >> ((sharpness_lvl > 0) + + (sharpness_lvl > 4)); + + if (sharpness_lvl > 0) { + if (block_inside_limit > (9 - sharpness_lvl)) + block_inside_limit = (9 - sharpness_lvl); + } + + if (block_inside_limit < 1) + block_inside_limit = 1; + + lfi->lfthr[lvl].lim = (uint8_t)block_inside_limit; + lfi->lfthr[lvl].mblim = (uint8_t)(2 * (lvl + 2) + + block_inside_limit); + } +} + +int default_filt_lvl; +struct loop_filter_info_n *lfi; +struct loopfilter *lf; +struct segmentation *seg_4lf; + +/*instantiate this function once when decode is started*/ +void vp9_loop_filter_init(void) +{ + int i; + if (!lfi) + lfi = kmalloc(sizeof(struct loop_filter_info_n), GFP_KERNEL); + if (!lf) + lf = kmalloc(sizeof(struct loopfilter), GFP_KERNEL); + if (!seg_4lf) + seg_4lf = kmalloc(sizeof(struct segmentation), GFP_KERNEL); + if (lfi == NULL || lf == NULL || seg_4lf == NULL) { + pr_err("[test.c] vp9_loop_filter init malloc error!!!\n"); + return; + } + memset(lfi, 0, sizeof(struct loop_filter_info_n)); + memset(lf, 0, sizeof(struct loopfilter)); + memset(seg_4lf, 0, sizeof(struct segmentation)); + lf->sharpness_level = 0; /*init to 0 */ + /*init limits for given sharpness*/ + vp9_update_sharpness(lfi, lf->sharpness_level); + lf->last_sharpness_level = lf->sharpness_level; + /*init hev threshold const vectors (actually no use) + for (i = 0; i <= MAX_LOOP_FILTER; i++) + lfi->lfthr[i].hev_thr = (uint8_t)(i >> 4);*/ + + /*Write to register*/ + for (i = 0; i < 32; i++) { + unsigned int thr; + thr = ((lfi->lfthr[i * 2 + 1].lim & 0x3f)<<8) | + (lfi->lfthr[i * 2 + 1].mblim & 0xff); + thr = (thr<<16) | ((lfi->lfthr[i*2].lim & 0x3f)<<8) | + (lfi->lfthr[i * 2].mblim & 0xff); + WRITE_VREG(HEVC_DBLK_CFG9, thr); + } + + /*video format is VP9*/ + WRITE_VREG(HEVC_DBLK_CFGB, 0x40400001); +} + /* perform this function per frame*/ +void vp9_loop_filter_frame_init(struct segmentation *seg, + struct loop_filter_info_n *lfi, struct loopfilter *lf, + int default_filt_lvl) { + int i; + int seg_id; + /*n_shift is the multiplier for lf_deltas + the multiplier is 1 for when filter_lvl is between 0 and 31; + 2 when filter_lvl is between 32 and 63*/ + const int scale = 1 << (default_filt_lvl >> 5); + + /*update limits if sharpness has changed*/ + if (lf->last_sharpness_level != lf->sharpness_level) { + vp9_update_sharpness(lfi, lf->sharpness_level); + lf->last_sharpness_level = lf->sharpness_level; + + /*Write to register*/ + for (i = 0; i < 32; i++) { + unsigned int thr; + thr = ((lfi->lfthr[i * 2 + 1].lim & 0x3f) << 8) + | (lfi->lfthr[i * 2 + 1].mblim & 0xff); + thr = (thr << 16) | ((lfi->lfthr[i * 2].lim & 0x3f) << 8) + | (lfi->lfthr[i * 2].mblim & 0xff); + WRITE_VREG(HEVC_DBLK_CFG9, thr); + } + } + + for (seg_id = 0; seg_id < MAX_SEGMENTS; seg_id++) {/*MAX_SEGMENTS = 8*/ + int lvl_seg = default_filt_lvl; + if (segfeature_active(seg, seg_id, SEG_LVL_ALT_LF)) { + const int data = get_segdata(seg, seg_id, + SEG_LVL_ALT_LF); + lvl_seg = vp9_clamp(seg->abs_delta == SEGMENT_ABSDATA ? + data : default_filt_lvl + data, + 0, MAX_LOOP_FILTER); +#ifdef DBG_LF_PRINT + pr_info("segfeature_active!!!seg_id=%d,lvl_seg=%d\n", seg_id, lvl_seg); +#endif + } + + if (!lf->mode_ref_delta_enabled) { + /*we could get rid of this if we assume that deltas are set to + zero when not in use; encoder always uses deltas*/ + memset(lfi->lvl[seg_id], lvl_seg, sizeof(lfi->lvl[seg_id])); + } else { + int ref, mode; + const int intra_lvl = lvl_seg + lf->ref_deltas[INTRA_FRAME] + * scale; +#ifdef DBG_LF_PRINT + pr_info("LF_PRINT:vp9_loop_filter_frame_init,seg_id=%d\n", seg_id); + pr_info("ref_deltas[INTRA_FRAME]=%d\n", lf->ref_deltas[INTRA_FRAME]); +#endif + lfi->lvl[seg_id][INTRA_FRAME][0] = + vp9_clamp(intra_lvl, 0, MAX_LOOP_FILTER); + + for (ref = LAST_FRAME; ref < MAX_REF_FRAMES; ++ref) { + /* LAST_FRAME = 1, MAX_REF_FRAMES = 4*/ + for (mode = 0; mode < MAX_MODE_LF_DELTAS; ++mode) { + /*MAX_MODE_LF_DELTAS = 2*/ + const int inter_lvl = + lvl_seg + lf->ref_deltas[ref] * scale + + lf->mode_deltas[mode] * scale; +#ifdef DBG_LF_PRINT +#endif + lfi->lvl[seg_id][ref][mode] = + vp9_clamp(inter_lvl, 0, + MAX_LOOP_FILTER); + } + } + } + } + +#ifdef DBG_LF_PRINT + /*print out thr/lvl table per frame*/ + for (i = 0; i <= MAX_LOOP_FILTER; i++) { + pr_info("LF_PRINT:(%d)thr=%d,blim=%d,lim=%d\n", + i, lfi->lfthr[i].hev_thr, lfi->lfthr[i].mblim, + lfi->lfthr[i].lim); + } + for (seg_id = 0; seg_id < MAX_SEGMENTS; seg_id++) { + pr_info("LF_PRINT:lvl(seg_id=%d)(mode=0,%d,%d,%d,%d)\n", + seg_id, lfi->lvl[seg_id][0][0], + lfi->lvl[seg_id][1][0], lfi->lvl[seg_id][2][0], + lfi->lvl[seg_id][3][0]); + pr_info("i(mode=1,%d,%d,%d,%d)\n", lfi->lvl[seg_id][0][1], + lfi->lvl[seg_id][1][1], lfi->lvl[seg_id][2][1], + lfi->lvl[seg_id][3][1]); + } +#endif + + /*Write to register */ + for (i = 0; i < 16; i++) { + unsigned int level; + level = ((lfi->lvl[i >> 1][3][i & 1] & 0x3f) << 24) | + ((lfi->lvl[i >> 1][2][i & 1] & 0x3f) << 16) | + ((lfi->lvl[i >> 1][1][i & 1] & 0x3f) << 8) | + (lfi->lvl[i >> 1][0][i & 1] & 0x3f); + if (!default_filt_lvl) + level = 0; + WRITE_VREG(HEVC_DBLK_CFGA, level); + } +} +/* VP9_LPF_LVL_UPDATE */ +#endif + +static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi) +{ + unsigned int data32; + int i; + + if (debug & VP9_DEBUG_BUFMGR) + pr_info("[test.c] Enable HEVC Parser Interrupt\n"); + data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); +#if 1 + /* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */ + data32 &= ~(7 << 29); + data32 |= (3 << 29); +#endif + data32 = data32 | + (1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/ + (1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/ + (1 << 7) |/*dec_done_int_cpu_enable*/ + (1 << 4) |/*startcode_found_int_cpu_enable*/ + (0 << 3) |/*startcode_found_int_amrisc_enable*/ + (1 << 0) /*parser_int_enable*/ + ; + WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); + + if (debug & VP9_DEBUG_BUFMGR) + pr_info("[test.c] Enable HEVC Parser Shift\n"); + + data32 = READ_VREG(HEVC_SHIFT_STATUS); + data32 = data32 | + (0 << 1) |/*emulation_check_off VP9 + do not have emulation*/ + (1 << 0)/*startcode_check_on*/ + ; + WRITE_VREG(HEVC_SHIFT_STATUS, data32); + WRITE_VREG(HEVC_SHIFT_CONTROL, + (0 << 14) | /*disable_start_code_protect*/ + (1 << 10) | /*length_zero_startcode_en for VP9*/ + (1 << 9) | /*length_valid_startcode_en for VP9*/ + (3 << 6) | /*sft_valid_wr_position*/ + (2 << 4) | /*emulate_code_length_sub_1*/ + (3 << 1) | /*start_code_length_sub_1 + VP9 use 0x00000001 as startcode (4 Bytes)*/ + (1 << 0) /*stream_shift_enable*/ + ); + + WRITE_VREG(HEVC_CABAC_CONTROL, + (1 << 0)/*cabac_enable*/ + ); + + WRITE_VREG(HEVC_PARSER_CORE_CONTROL, + (1 << 0)/* hevc_parser_core_clk_en*/ + ); + + + WRITE_VREG(HEVC_DEC_STATUS_REG, 0); + + /*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/ + if (debug & VP9_DEBUG_BUFMGR) + pr_info("Initial IQIT_SCALELUT memory\n"); + WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/ + for (i = 0; i < 1024; i++) + WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); + + +#ifdef ENABLE_SWAP_TEST + WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); +#else + WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); +#endif +#ifdef MULTI_INSTANCE_SUPPORT + if (pbi->platform_dev && vdec_frame_based(hw_to_vdec(pbi))) + WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE); + else + WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE); + WRITE_VREG(HEVC_DECODE_SIZE, 0); + WRITE_VREG(HEVC_DECODE_COUNT, 0); +#else + WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE); + WRITE_VREG(HEVC_DECODE_PIC_BEGIN_REG, 0); + WRITE_VREG(HEVC_DECODE_PIC_NUM_REG, 0x7fffffff); /*to remove*/ +#endif + /*Send parser_cmd*/ + if (debug) + pr_info("[test.c] SEND Parser Command ...\n"); + WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); + for (i = 0; i < PARSER_CMD_NUMBER; i++) + WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); + WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); + + + WRITE_VREG(HEVC_PARSER_IF_CONTROL, + /* (1 << 8) |*/ /*sao_sw_pred_enable*/ + (1 << 5) | /*parser_sao_if_en*/ + (1 << 2) | /*parser_mpred_if_en*/ + (1 << 0) /*parser_scaler_if_en*/ + ); + /*Changed to Start MPRED in microcode*/ + /* + pr_info("[test.c] Start MPRED\n"); + WRITE_VREG(HEVC_MPRED_INT_STATUS, + (1<<31) + ); + */ + if (debug) + pr_info("[test.c] Reset IPP\n"); + WRITE_VREG(HEVCD_IPP_TOP_CNTL, + (0 << 1) | /*enable ipp*/ + (1 << 0) /*software reset ipp and mpp*/ + ); + WRITE_VREG(HEVCD_IPP_TOP_CNTL, + (1 << 1) | /*enable ipp*/ + (0 << 0) /*software reset ipp and mpp*/ + ); +#ifdef VP9_10B_NV21 + /*Enable NV21 reference read mode for MC*/ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); +#endif + + /*Initialize mcrcc and decomp perf counters + mcrcc_perfcount_reset(); + decomp_perfcount_reset();*/ + return; +} + + +#ifdef CONFIG_HEVC_CLK_FORCED_ON +static void config_vp9_clk_forced_on(void) +{ + unsigned int rdata32; + /*IQIT*/ + rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL); + WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2)); + + /* DBLK*/ + rdata32 = READ_VREG(HEVC_DBLK_CFG0); + WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2)); + + /* SAO*/ + rdata32 = READ_VREG(HEVC_SAO_CTRL1); + WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2)); + + /*MPRED*/ + rdata32 = READ_VREG(HEVC_MPRED_CTRL1); + WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24)); + + /* PARSER*/ + rdata32 = READ_VREG(HEVC_STREAM_CONTROL); + WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_SHIFT_CONTROL); + WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_CABAC_CONTROL); + WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13)); + rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL); + WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL); + WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15)); + rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL); + WRITE_VREG(HEVC_PARSER_IF_CONTROL, + rdata32 | (0x1 << 6) | (0x1 << 3) | (0x1 << 1)); + + /*IPP*/ + rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG); + WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff); + + /* MCRCC*/ + rdata32 = READ_VREG(HEVCD_MCRCC_CTL1); + WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3)); +} +#endif + + +#ifdef MCRCC_ENABLE +static void config_mcrcc_axi_hw(struct VP9Decoder_s *pbi) +{ + unsigned int rdata32; + unsigned short is_inter; + /*pr_info("Entered config_mcrcc_axi_hw...\n");*/ + WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2);/* reset mcrcc*/ + is_inter = ((pbi->common.frame_type != KEY_FRAME) && + (!pbi->common.intra_only)) ? 1 : 0; + if (!is_inter) { /* I-PIC*/ + /*remove reset -- disables clock*/ + WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); + return; + } + +#if 0 + pr_info("before call mcrcc_get_hitrate\r\n"); + mcrcc_get_hitrate(); + decomp_get_hitrate(); + decomp_get_comprate(); +#endif + + WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, + (0 << 8) | (1 << 1) | 0); + rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32 = rdata32 & 0xffff; + rdata32 = rdata32 | (rdata32 << 16); + WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); + /*Programme canvas1 */ + rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); + rdata32 = rdata32 & 0xffff; + rdata32 = rdata32 | (rdata32 << 16); + WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); + /*enable mcrcc progressive-mode*/ + WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); + return; +} +#endif + + +static struct VP9Decoder_s gHevc; + +static void vp9_local_uninit(struct VP9Decoder_s *pbi) +{ + pbi->rpm_ptr = NULL; + pbi->lmem_ptr = NULL; + if (pbi->rpm_addr) { + dma_unmap_single(amports_get_dma_device(), + pbi->rpm_phy_addr, RPM_BUF_SIZE, + DMA_FROM_DEVICE); + kfree(pbi->rpm_addr); + pbi->rpm_addr = NULL; + } + if (pbi->lmem_addr) { + if (pbi->lmem_phy_addr) + dma_free_coherent(amports_get_dma_device(), + LMEM_BUF_SIZE, pbi->lmem_addr, + pbi->lmem_phy_addr); + + pbi->lmem_addr = NULL; + } + if (pbi->prob_buffer_addr) { + if (pbi->prob_buffer_phy_addr) + dma_free_coherent(amports_get_dma_device(), + PROB_BUF_SIZE, pbi->prob_buffer_addr, + pbi->prob_buffer_phy_addr); + + pbi->prob_buffer_addr = NULL; + } + if (pbi->count_buffer_addr) { + if (pbi->count_buffer_phy_addr) + dma_free_coherent(amports_get_dma_device(), + COUNT_BUF_SIZE, pbi->count_buffer_addr, + pbi->count_buffer_phy_addr); + + pbi->count_buffer_addr = NULL; + } +#ifdef VP9_10B_MMU + if (pbi->frame_mmu_map_addr) { + if (pbi->frame_mmu_map_phy_addr) + dma_free_coherent(amports_get_dma_device(), + FRAME_MMU_MAP_SIZE, pbi->frame_mmu_map_addr, + pbi->frame_mmu_map_phy_addr); + + pbi->frame_mmu_map_addr = NULL; + } +#endif + +#ifdef VP9_LPF_LVL_UPDATE + kfree(lfi); + lfi = NULL; + kfree(lf); + lf = NULL; + kfree(seg_4lf); + seg_4lf = NULL; +#endif +} + +static int vp9_local_init(struct VP9Decoder_s *pbi) +{ + int ret = -1; + /*int losless_comp_header_size, losless_comp_body_size;*/ + + struct BuffInfo_s *cur_buf_info = NULL; + memset(&pbi->param, 0, sizeof(union param_u)); + memset(&pbi->common, 0, sizeof(struct VP9_Common_s)); +#ifdef MULTI_INSTANCE_SUPPORT + cur_buf_info = &pbi->work_space_buf_store; +#ifdef SUPPORT_4K2K + memcpy(cur_buf_info, &amvvp9_workbuff_spec[1], /* 4k2k work space */ + sizeof(struct BuffInfo_s)); +#else + memcpy(cur_buf_info, &amvvp9_workbuff_spec[0], /* 1080p work space */ + sizeof(struct BuffInfo_s)); +#endif + cur_buf_info->start_adr = pbi->buf_start; + pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size; +#else +/*! MULTI_INSTANCE_SUPPORT*/ +#ifdef SUPPORT_4K2K + cur_buf_info = &amvvp9_workbuff_spec[1]; /* 4k2k work space */ +#else + cur_buf_info = &amvvp9_workbuff_spec[0]; /* 1080p work space */ +#endif +#endif + + init_buff_spec(pbi, cur_buf_info); + pbi->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff) + & (~0xffff); + pbi->mc_buf_spec.buf_size = (pbi->mc_buf_spec.buf_end + - pbi->mc_buf_spec.buf_start); + if (debug) { + pr_err("pbi->mc_buf_spec.buf_start %x-%x\n", + pbi->mc_buf_spec.buf_start, + pbi->mc_buf_spec.buf_start + + pbi->mc_buf_spec.buf_size); + } + vp9_bufmgr_init(pbi, cur_buf_info, &pbi->mc_buf_spec); + + pbi->init_pic_w = buf_alloc_width ? buf_alloc_width : + (pbi->vvp9_amstream_dec_info.width ? + pbi->vvp9_amstream_dec_info.width : + pbi->work_space_buf->max_width); + pbi->init_pic_h = buf_alloc_height ? buf_alloc_height : + (pbi->vvp9_amstream_dec_info.height ? + pbi->vvp9_amstream_dec_info.height : + pbi->work_space_buf->max_height); +#ifndef VP9_10B_MMU + init_buf_list(pbi); +#endif + init_pic_list(pbi); + + pts_unstable = ((unsigned long)(pbi->vvp9_amstream_dec_info.param) + & 0x40) >> 6; + + pbi->video_signal_type = 0; + video_signal_type = pbi->video_signal_type; + + if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { + pbi->rpm_addr = kmalloc(RPM_BUF_SIZE, GFP_KERNEL); + if (pbi->rpm_addr == NULL) { + pr_err("%s: failed to alloc rpm buffer\n", __func__); + return -1; + } + + pbi->rpm_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->rpm_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + pbi->rpm_phy_addr)) { + pr_err("%s: failed to map rpm buffer\n", __func__); + kfree(pbi->rpm_addr); + pbi->rpm_addr = NULL; + return -1; + } + + pbi->rpm_ptr = pbi->rpm_addr; + } + + if (debug & VP9_DEBUG_UCODE) { + pbi->lmem_addr = dma_alloc_coherent(amports_get_dma_device(), + LMEM_BUF_SIZE, + &pbi->lmem_phy_addr, GFP_KERNEL); + if (pbi->lmem_addr == NULL) { + pr_err("%s: failed to alloc lmem buffer\n", __func__); + return -1; + } +/* + pbi->lmem_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + pbi->lmem_phy_addr)) { + pr_err("%s: failed to map lmem buffer\n", __func__); + kfree(pbi->lmem_addr); + pbi->lmem_addr = NULL; + return -1; + } +*/ + pbi->lmem_ptr = pbi->lmem_addr; + } + pbi->prob_buffer_addr = dma_alloc_coherent(amports_get_dma_device(), + PROB_BUF_SIZE, + &pbi->prob_buffer_phy_addr, GFP_KERNEL); + if (pbi->prob_buffer_addr == NULL) { + pr_err("%s: failed to alloc prob_buffer\n", __func__); + return -1; + } + memset(pbi->prob_buffer_addr, 0, PROB_BUF_SIZE); +/* pbi->prob_buffer_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->prob_buffer_addr, PROB_BUF_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + pbi->prob_buffer_phy_addr)) { + pr_err("%s: failed to map prob_buffer\n", __func__); + kfree(pbi->prob_buffer_addr); + pbi->prob_buffer_addr = NULL; + return -1; + } +*/ + pbi->count_buffer_addr = dma_alloc_coherent(amports_get_dma_device(), + COUNT_BUF_SIZE, + &pbi->count_buffer_phy_addr, GFP_KERNEL); + if (pbi->count_buffer_addr == NULL) { + pr_err("%s: failed to alloc count_buffer\n", __func__); + return -1; + } + memset(pbi->count_buffer_addr, 0, COUNT_BUF_SIZE); +/* pbi->count_buffer_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->count_buffer_addr, COUNT_BUF_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + pbi->count_buffer_phy_addr)) { + pr_err("%s: failed to map count_buffer\n", __func__); + kfree(pbi->count_buffer_addr); + pbi->count_buffer_addr = NULL; + return -1; + } +*/ +#ifdef VP9_10B_MMU + pbi->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), + FRAME_MMU_MAP_SIZE, + &pbi->frame_mmu_map_phy_addr, GFP_KERNEL); + if (pbi->frame_mmu_map_addr == NULL) { + pr_err("%s: failed to alloc count_buffer\n", __func__); + return -1; + } + memset(pbi->frame_mmu_map_addr, 0, COUNT_BUF_SIZE); +/* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + pbi->frame_mmu_map_phy_addr)) { + pr_err("%s: failed to map count_buffer\n", __func__); + kfree(pbi->frame_mmu_map_addr); + pbi->frame_mmu_map_addr = NULL; + return -1; + }*/ +#endif + + ret = 0; + return ret; +} + +/******************************************** + * Mailbox command + ********************************************/ +#define CMD_FINISHED 0 +#define CMD_ALLOC_VIEW 1 +#define CMD_FRAME_DISPLAY 3 +#define CMD_DEBUG 10 + + +#define DECODE_BUFFER_NUM_MAX 32 +#define DISPLAY_BUFFER_NUM 6 + +#define video_domain_addr(adr) (adr&0x7fffffff) +#define DECODER_WORK_SPACE_SIZE 0x800000 + +#define spec2canvas(x) \ + (((x)->uv_canvas_index << 16) | \ + ((x)->uv_canvas_index << 8) | \ + ((x)->y_canvas_index << 0)) + + +static void set_canvas(struct PIC_BUFFER_CONFIG_s *pic_config) +{ + int canvas_w = ALIGN(pic_config->y_crop_width, 64)/4; + int canvas_h = ALIGN(pic_config->y_crop_height, 32)/4; + int blkmode = mem_map_mode; + /*CANVAS_BLKMODE_64X32*/ + if (double_write_mode) { + canvas_w = pic_config->y_crop_width; + canvas_h = pic_config->y_crop_height; + if (double_write_mode == 2) { + canvas_w >>= 2; + canvas_h >>= 2; + } + + if (mem_map_mode == 0) + canvas_w = ALIGN(canvas_w, 32); + else + canvas_w = ALIGN(canvas_w, 64); + canvas_h = ALIGN(canvas_h, 32); + + pic_config->y_canvas_index = 128 + pic_config->index * 2; + pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1; + + canvas_config_ex(pic_config->y_canvas_index, + pic_config->dw_y_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + canvas_config_ex(pic_config->uv_canvas_index, + pic_config->dw_u_v_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); +#ifdef MULTI_INSTANCE_SUPPORT + pic_config->canvas_config[0].phy_addr = + pic_config->dw_y_adr; + pic_config->canvas_config[0].width = + canvas_w; + pic_config->canvas_config[0].height = + canvas_h; + pic_config->canvas_config[0].block_mode = + blkmode; + pic_config->canvas_config[0].endian = 7; + + pic_config->canvas_config[1].phy_addr = + pic_config->dw_u_v_adr; + pic_config->canvas_config[1].width = + canvas_w; + pic_config->canvas_config[1].height = + canvas_h; + pic_config->canvas_config[1].block_mode = + blkmode; + pic_config->canvas_config[1].endian = 7; +#endif + } else { + #ifndef VP9_10B_MMU + pic_config->y_canvas_index = 128 + pic_config->index; + pic_config->uv_canvas_index = 128 + pic_config->index; + + canvas_config_ex(pic_config->y_canvas_index, + pic_config->mc_y_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + canvas_config_ex(pic_config->uv_canvas_index, + pic_config->mc_u_v_adr, canvas_w, canvas_h, + CANVAS_ADDR_NOWRAP, blkmode, 0x7); + #endif + } + +} + + +static void set_frame_info(struct VP9Decoder_s *pbi, struct vframe_s *vf) +{ + unsigned int ar; + + vf->duration = pbi->frame_dur; + vf->duration_pulldown = 0; + vf->flag = 0; + + ar = min_t(u32, pbi->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); + vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + + return; +} + +static int vvp9_vf_states(struct vframe_states *states, void *op_arg) +{ + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&pbi->newframe_q); + states->buf_avail_num = kfifo_len(&pbi->display_q); + + if (step == 2) + states->buf_avail_num = 0; + return 0; +} + +static struct vframe_s *vvp9_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; + if (step == 2) + return NULL; + + if (kfifo_peek(&pbi->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vvp9_vf_get(void *op_arg) +{ + struct vframe_s *vf; + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; + if (step == 2) + return NULL; + else if (step == 1) + step = 2; + + if (kfifo_get(&pbi->display_q, &vf)) { + uint8_t index = vf->index & 0xff; + if (index >= 0 && index < FRAME_BUFFERS) + return vf; + } + return NULL; +} + +static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; + uint8_t index = vf->index & 0xff; + + kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf); + + if (index >= 0 + && index < FRAME_BUFFERS) { + struct VP9_Common_s *cm = &pbi->common; + struct BufferPool_s *pool = cm->buffer_pool; + lock_buffer_pool(pool); + if (pool->frame_bufs[index].buf.vf_ref > 0) + pool->frame_bufs[index].buf.vf_ref--; + + if (pbi->wait_buf) + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, + 0x1); + pbi->last_put_idx = index; + pbi->new_frame_displayed++; + unlock_buffer_pool(pool); + } + +} + +static int vvp9_event_cb(int type, void *data, void *private_data) +{ + if (type & VFRAME_EVENT_RECEIVER_RESET) { +#if 0 + unsigned long flags; + amhevc_stop(); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_light_unreg_provider(&vvp9_vf_prov); +#endif + spin_lock_irqsave(&pbi->lock, flags); + vvp9_local_init(); + vvp9_prot_init(); + spin_unlock_irqrestore(&pbi->lock, flags); +#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER + vf_reg_provider(&vvp9_vf_prov); +#endif + amhevc_start(); +#endif + } + + return 0; +} + +void inc_vf_ref(struct VP9Decoder_s *pbi, int index) +{ + struct VP9_Common_s *cm = &pbi->common; + cm->buffer_pool->frame_bufs[index].buf.vf_ref++; + + if (debug & VP9_DEBUG_BUFMGR) + pr_info("%s index = %d new vf_ref = %d\r\n", + __func__, index, + cm->buffer_pool->frame_bufs[index].buf.vf_ref); +} + + +static int prepare_display_buf(struct VP9Decoder_s *pbi, + struct PIC_BUFFER_CONFIG_s *pic_config) +{ + struct vframe_s *vf = NULL; + int stream_offset = pic_config->stream_offset; + unsigned short slice_type = pic_config->slice_type; + + if (debug & VP9_DEBUG_BUFMGR) + pr_info("%s index = %d\r\n", __func__, pic_config->index); + if (kfifo_get(&pbi->newframe_q, &vf) == 0) { + pr_info("fatal error, no available buffer slot."); + return -1; + } + + if (double_write_mode) { + set_canvas(pic_config); + } + if (vf) { + /* if (pts_lookup_offset(PTS_TYPE_VIDEO, + stream_offset, &vf->pts, 0) != 0) { */ + if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, + &vf->pts_us64) != 0) { +#ifdef DEBUG_PTS + pbi->pts_missed++; +#endif + vf->pts = 0; + vf->pts_us64 = 0; + } +#ifdef DEBUG_PTS + else + pbi->pts_hit++; +#endif + if (pts_unstable) + pbi->pts_mode = PTS_NONE_REF_USE_DURATION; + + if ((pbi->pts_mode == PTS_NORMAL) && (vf->pts != 0) + && pbi->get_frame_dur) { + int pts_diff = (int)vf->pts - pbi->last_lookup_pts; + + if (pts_diff < 0) { + pbi->pts_mode_switching_count++; + pbi->pts_mode_recovery_count = 0; + + if (pbi->pts_mode_switching_count >= + PTS_MODE_SWITCHING_THRESHOLD) { + pbi->pts_mode = + PTS_NONE_REF_USE_DURATION; + pr_info + ("HEVC: switch to n_d mode.\n"); + } + + } else { + int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD; + pbi->pts_mode_recovery_count++; + if (pbi->pts_mode_recovery_count > p) { + pbi->pts_mode_switching_count = 0; + pbi->pts_mode_recovery_count = 0; + } + } + } + + if (vf->pts != 0) + pbi->last_lookup_pts = vf->pts; + + if ((pbi->pts_mode == PTS_NONE_REF_USE_DURATION) + && (slice_type != KEY_FRAME)) + vf->pts = pbi->last_pts + DUR2PTS(pbi->frame_dur); + pbi->last_pts = vf->pts; + + if (vf->pts_us64 != 0) + pbi->last_lookup_pts_us64 = vf->pts_us64; + + if ((pbi->pts_mode == PTS_NONE_REF_USE_DURATION) + && (slice_type != KEY_FRAME)) { + vf->pts_us64 = + pbi->last_pts_us64 + + (DUR2PTS(pbi->frame_dur) * 100 / 9); + } + pbi->last_pts_us64 = vf->pts_us64; + if ((debug & VP9_DEBUG_OUT_PTS) != 0) { + pr_info + ("VP9 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n", + vf->pts, vf->pts_us64); + } + + vf->index = 0xff00 | pic_config->index; +#if 1 +/*SUPPORT_10BIT*/ + if (double_write_mode & 0x10) { + /* double write only */ + vf->compBodyAddr = 0; + vf->compHeadAddr = 0; + } else { +#ifdef VP9_10B_MMU + vf->compBodyAddr = 0; + vf->compHeadAddr = pic_config->header_adr; +#else + vf->compBodyAddr = pic_config->mc_y_adr; /*body adr*/ + vf->compHeadAddr = pic_config->mc_y_adr + + pic_config->comp_body_size; + /*head adr*/ +#endif + } + if (double_write_mode) { + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; +#ifdef MULTI_INSTANCE_SUPPORT + if (pbi->m_ins_flag) { + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 2; + vf->canvas0_config[0] = + pic_config->canvas_config[0]; + vf->canvas0_config[1] = + pic_config->canvas_config[1]; + + vf->canvas1_config[0] = + pic_config->canvas_config[0]; + vf->canvas1_config[1] = + pic_config->canvas_config[1]; + + } else +#endif + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(pic_config); + } else { + vf->canvas0Addr = vf->canvas1Addr = 0; + vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; +#ifdef VP9_10B_MMU + vf->type |= VIDTYPE_SCATTER; +#endif + switch (pic_config->bit_depth) { + case VPX_BITS_8: + vf->bitdepth = BITDEPTH_Y8 | + BITDEPTH_U8 | BITDEPTH_V8; + break; + case VPX_BITS_10: + case VPX_BITS_12: + vf->bitdepth = BITDEPTH_Y10 | + BITDEPTH_U10 | BITDEPTH_V10; + break; + default: + vf->bitdepth = BITDEPTH_Y10 | + BITDEPTH_U10 | BITDEPTH_V10; + break; + } + if (pic_config->bit_depth == VPX_BITS_8) + vf->bitdepth |= BITDEPTH_SAVING_MODE; + } +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; + vf->canvas0Addr = vf->canvas1Addr = spec2canvas(pic_config); +#endif + set_frame_info(pbi, vf); + /* if((vf->width!=pic_config->width)| + (vf->height!=pic_config->height)) */ + /* pr_info("aaa: %d/%d, %d/%d\n", + vf->width,vf->height, pic_config->width, + pic_config->height); */ + if (double_write_mode == 2) { + vf->width = pic_config->y_crop_width/4; + vf->height = pic_config->y_crop_height/4; + } else { + vf->width = pic_config->y_crop_width; + vf->height = pic_config->y_crop_height; + } + if (force_w_h != 0) { + vf->width = (force_w_h >> 16) & 0xffff; + vf->height = force_w_h & 0xffff; + } + vf->compWidth = pic_config->y_crop_width; + vf->compHeight = pic_config->y_crop_height; + if (force_fps & 0x100) { + u32 rate = force_fps & 0xff; + if (rate) + vf->duration = 96000/rate; + else + vf->duration = 0; + } + if (vf->type & VIDTYPE_SCATTER) { + vf->mem_handle = decoder_mmu_box_get_mem_handle( + pbi->mmu_box, + pic_config->index); + } else { + vf->mem_handle = decoder_bmmu_box_get_mem_handle( + pbi->bmmu_box, + pic_config->index); + } + inc_vf_ref(pbi, pic_config->index); + kfifo_put(&pbi->display_q, (const struct vframe_s *)vf); + vf_notify_receiver(pbi->provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + + return 0; +} + +static void get_rpm_param(union param_u *params) +{ + int i; + unsigned int data32; + if (debug & VP9_DEBUG_BUFMGR) + pr_info("enter %s\r\n", __func__); + for (i = 0; i < 128; i++) { + do { + data32 = READ_VREG(RPM_CMD_REG); + /*pr_info("%x\n", data32);*/ + } while ((data32 & 0x10000) == 0); + params->l.data[i] = data32&0xffff; + /*pr_info("%x\n", data32);*/ + WRITE_VREG(RPM_CMD_REG, 0); + } + if (debug & VP9_DEBUG_BUFMGR) + pr_info("leave %s\r\n", __func__); +} +static void debug_buffer_mgr_more(struct VP9Decoder_s *pbi) +{ + int i; + if (!(debug & VP9_DEBUG_BUFMGR_MORE)) + return; + pr_info("vp9_param: (%d)\n", pbi->slice_idx); + for (i = 0; i < (RPM_END-RPM_BEGIN); i++) { + pr_info("%04x ", vp9_param.l.data[i]); + if (((i + 1) & 0xf) == 0) + pr_info("\n"); + } + pr_info("=============param==========\r\n"); + pr_info("profile %x\r\n", vp9_param.p.profile); + pr_info("show_existing_frame %x\r\n", + vp9_param.p.show_existing_frame); + pr_info("frame_to_show_idx %x\r\n", + vp9_param.p.frame_to_show_idx); + pr_info("frame_type %x\r\n", vp9_param.p.frame_type); + pr_info("show_frame %x\r\n", vp9_param.p.show_frame); + pr_info("e.r.r.o.r_resilient_mode %x\r\n", + vp9_param.p.error_resilient_mode); + pr_info("intra_only %x\r\n", vp9_param.p.intra_only); + pr_info("display_size_present %x\r\n", + vp9_param.p.display_size_present); + pr_info("reset_frame_context %x\r\n", + vp9_param.p.reset_frame_context); + pr_info("refresh_frame_flags %x\r\n", + vp9_param.p.refresh_frame_flags); + pr_info("bit_depth %x\r\n", vp9_param.p.bit_depth); + pr_info("width %x\r\n", vp9_param.p.width); + pr_info("height %x\r\n", vp9_param.p.height); + pr_info("display_width %x\r\n", vp9_param.p.display_width); + pr_info("display_height %x\r\n", vp9_param.p.display_height); + pr_info("ref_info %x\r\n", vp9_param.p.ref_info); + pr_info("same_frame_size %x\r\n", vp9_param.p.same_frame_size); + if (!(debug & VP9_DEBUG_DBG_LF_PRINT)) + return; + pr_info("mode_ref_delta_enabled: 0x%x\r\n", + vp9_param.p.mode_ref_delta_enabled); + pr_info("sharpness_level: 0x%x\r\n", + vp9_param.p.sharpness_level); + pr_info("ref_deltas: 0x%x, 0x%x, 0x%x, 0x%x\r\n", + vp9_param.p.ref_deltas[0], vp9_param.p.ref_deltas[1], + vp9_param.p.ref_deltas[2], vp9_param.p.ref_deltas[3]); + pr_info("mode_deltas: 0x%x, 0x%x\r\n", vp9_param.p.mode_deltas[0], + vp9_param.p.mode_deltas[1]); + pr_info("filter_level: 0x%x\r\n", vp9_param.p.filter_level); + pr_info("seg_enabled: 0x%x\r\n", vp9_param.p.seg_enabled); + pr_info("seg_abs_delta: 0x%x\r\n", vp9_param.p.seg_abs_delta); + pr_info("seg_lf_feature_enabled: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\r\n", + (vp9_param.p.seg_lf_info[0]>>15 & 1), + (vp9_param.p.seg_lf_info[1]>>15 & 1), + (vp9_param.p.seg_lf_info[2]>>15 & 1), + (vp9_param.p.seg_lf_info[3]>>15 & 1), + (vp9_param.p.seg_lf_info[4]>>15 & 1), + (vp9_param.p.seg_lf_info[5]>>15 & 1), + (vp9_param.p.seg_lf_info[6]>>15 & 1), + (vp9_param.p.seg_lf_info[7]>>15 & 1)); + pr_info("seg_lf_feature_data: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\r\n", + (vp9_param.p.seg_lf_info[0] & 0x13f), + (vp9_param.p.seg_lf_info[1] & 0x13f), + (vp9_param.p.seg_lf_info[2] & 0x13f), + (vp9_param.p.seg_lf_info[3] & 0x13f), + (vp9_param.p.seg_lf_info[4] & 0x13f), + (vp9_param.p.seg_lf_info[5] & 0x13f), + (vp9_param.p.seg_lf_info[6] & 0x13f), + (vp9_param.p.seg_lf_info[7] & 0x13f)); + +} + +static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) +{ + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data; + unsigned int dec_status = pbi->dec_status; + struct VP9_Common_s *const cm = &pbi->common; + int i, ret; + + /*if (pbi->wait_buf) + pr_info("set wait_buf to 0\r\n"); + */ + pbi->wait_buf = 0; + + if (dec_status == VP9_EOS) { + pr_info("VP9_EOS, flush buffer\r\n"); + + vp9_bufmgr_postproc(pbi); + + pr_info("send VP9_10B_DISCARD_NAL\r\n"); + WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL); + pbi->process_busy = 0; + return IRQ_HANDLED; + } + + if (dec_status != VP9_HEAD_PARSER_DONE) { + pbi->process_busy = 0; + return IRQ_HANDLED; + } + if (pbi->frame_count > 0) + vp9_bufmgr_postproc(pbi); + + if (debug & VP9_DEBUG_SEND_PARAM_WITH_REG) { + get_rpm_param(&vp9_param); + } else { + dma_sync_single_for_cpu( + amports_get_dma_device(), + pbi->rpm_phy_addr, + RPM_BUF_SIZE, + DMA_FROM_DEVICE); + + for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { + int ii; + for (ii = 0; ii < 4; ii++) + vp9_param.l.data[i + ii] = + pbi->rpm_ptr[i + 3 - ii]; + } + } + debug_buffer_mgr_more(pbi); + + bit_depth_luma = vp9_param.p.bit_depth; + bit_depth_chroma = vp9_param.p.bit_depth; + + ret = vp9_bufmgr_process(pbi, &vp9_param); + pbi->slice_idx++; + if (ret < 0) { + pr_info("vp9_bufmgr_process=> %d, VP9_10B_DISCARD_NAL\r\n", + ret); + WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL); + pbi->process_busy = 0; + return IRQ_HANDLED; + } else if (ret == 0) { + pbi->frame_count++; + /*pr_info("Decode Frame Data %d\n", pbi->frame_count);*/ + config_pic_size(pbi, vp9_param.p.bit_depth); + if ((pbi->common.frame_type != KEY_FRAME) + && (!pbi->common.intra_only)) { + config_mc_buffer(pbi, vp9_param.p.bit_depth); + config_mpred_hw(pbi); + } else { + clear_mpred_hw(pbi); + } +#ifdef MCRCC_ENABLE + config_mcrcc_axi_hw(pbi); +#endif + config_sao_hw(pbi, &vp9_param); + +#ifdef VP9_LPF_LVL_UPDATE + /* + * Get loop filter related picture level parameters from Parser + */ + lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled; + lf->sharpness_level = vp9_param.p.sharpness_level; + for (i = 0; i < 4; i++) + lf->ref_deltas[i] = vp9_param.p.ref_deltas[i]; + for (i = 0; i < 2; i++) + lf->mode_deltas[i] = vp9_param.p.mode_deltas[i]; + default_filt_lvl = vp9_param.p.filter_level; + seg_4lf->enabled = vp9_param.p.seg_enabled; + seg_4lf->abs_delta = vp9_param.p.seg_abs_delta; + for (i = 0; i < MAX_SEGMENTS; i++) + seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] & + 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0; + + for (i = 0; i < MAX_SEGMENTS; i++) + seg_4lf->feature_data[i][SEG_LVL_ALT_LF] + = (vp9_param.p.seg_lf_info[i] + & 0x100) ? -(vp9_param.p.seg_lf_info[i] + & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f); + /* + * Update loop filter Thr/Lvl table for every frame + */ + /*pr_info + ("vp9_loop_filter (run before every frame decoding start)\n");*/ + vp9_loop_filter_frame_init(seg_4lf, lfi, lf, default_filt_lvl); +#endif + /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/ + + WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); + } else { + pr_info("Skip search next start code\n"); + cm->prev_fb_idx = INVALID_IDX; + /*skip, search next start code*/ + WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); + } + pbi->process_busy = 0; +#ifdef VP9_10B_MMU + if (pbi->last_put_idx >= 0 && pbi->last_put_idx < FRAME_BUFFERS) { + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + int i = pbi->last_put_idx; + /*free not used buffers.*/ + if ((frame_bufs[i].ref_count == 0) && + (frame_bufs[i].buf.vf_ref == 0) && + (frame_bufs[i].buf.used_by_display == 0) && + (frame_bufs[i].buf.index != -1)) { + decoder_mmu_box_free_idx(pbi->mmu_box, i); + } + pbi->last_put_idx = -1; + } +#endif + return IRQ_HANDLED; +} + +static irqreturn_t vvp9_isr(int irq, void *data) +{ + int i; + unsigned int dec_status; + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data; + unsigned int adapt_prob_status; + struct VP9_Common_s *const cm = &pbi->common; + dec_status = READ_VREG(HEVC_DEC_STATUS_REG); + adapt_prob_status = READ_VREG(VP9_ADAPT_PROB_REG); + if (pbi->init_flag == 0) + return IRQ_HANDLED; + if (pbi->process_busy)/*on process.*/ + return IRQ_HANDLED; + pbi->dec_status = dec_status; + pbi->process_busy = 1; + if (debug & VP9_DEBUG_BUFMGR) + pr_info("vp9 isr dec status = %d\n", dec_status); + + if (debug & VP9_DEBUG_UCODE) { + if (READ_HREG(DEBUG_REG1) & 0x10000) { + dma_sync_single_for_cpu( + amports_get_dma_device(), + pbi->lmem_phy_addr, + LMEM_BUF_SIZE, + DMA_FROM_DEVICE); + + pr_info("LMEM:\n", READ_HREG(DEBUG_REG1)); + for (i = 0; i < 0x400; i += 4) { + int ii; + if ((i & 0xf) == 0) + pr_info("%03x: ", i); + for (ii = 0; ii < 4; ii++) { + pr_info("%04x ", + pbi->lmem_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + pr_info("\n"); + } + WRITE_HREG(DEBUG_REG1, 0); + } else if (READ_HREG(DEBUG_REG1) != 0) { + pr_info("dbg%x: %x\n", READ_HREG(DEBUG_REG1), + READ_HREG(DEBUG_REG2)); + WRITE_HREG(DEBUG_REG1, 0); + pbi->process_busy = 0; + return IRQ_HANDLED; + } + + } + + if (pbi->error_flag == 1) { + pbi->error_flag = 2; + pbi->process_busy = 0; + return IRQ_HANDLED; + } else if (pbi->error_flag == 3) { + pbi->process_busy = 0; + return IRQ_HANDLED; + } + + if (is_buffer_empty(cm)) { + /* + if (pbi->wait_buf == 0) + pr_info("set wait_buf to 1\r\n"); + */ + pbi->wait_buf = 1; + pbi->process_busy = 0; + return IRQ_HANDLED; + } + if ((adapt_prob_status & 0xff) == 0xfd) { + /*VP9_REQ_ADAPT_PROB*/ + int pre_fc = (cm->frame_type == KEY_FRAME) ? 1 : 0; + uint8_t *prev_prob_b = + ((uint8_t *)pbi->prob_buffer_addr) + + ((adapt_prob_status >> 8) * 0x1000); + uint8_t *cur_prob_b = + ((uint8_t *)pbi->prob_buffer_addr) + 0x4000; + uint8_t *count_b = (uint8_t *)pbi->count_buffer_addr; + + adapt_coef_probs(pbi->pic_count, + (cm->last_frame_type == KEY_FRAME), + pre_fc, (adapt_prob_status >> 8), + (unsigned int *)prev_prob_b, + (unsigned int *)cur_prob_b, (unsigned int *)count_b); + + memcpy(prev_prob_b, cur_prob_b, PROB_SIZE); + WRITE_VREG(VP9_ADAPT_PROB_REG, 0); + pbi->pic_count += 1; + + /*return IRQ_HANDLED;*/ + } +#ifdef MULTI_INSTANCE_SUPPORT +#if 0 + if ((dec_status == HEVC_DECPIC_DATA_DONE) && (pbi->m_ins_flag)) { + if (pbi->chunk) { + pbi->cur_pic->pts = pbi->chunk->pts; + pbi->cur_pic->pts64 = pbi->chunk->pts64; + } else if (pts_lookup_offset_us64 + (PTS_TYPE_VIDEO, + pbi->cur_pic->stream_offset, + &pbi->cur_pic->pts, + 0, + &pbi->cur_pic->pts64) != 0) { +#ifdef DEBUG_PTS + pbi->pts_missed++; +#endif + pbi->cur_pic->pts = 0; + pbi->cur_pic->pts64 = 0; + } + } +#endif + if (dec_status == HEVC_NAL_DECODE_DONE) { + if (pbi->m_ins_flag) { +#if 0 + if (!vdec_frame_based(hw_to_vdec(hevc))) { + pbi->dec_result = DEC_RESULT_AGAIN; + if ((debug & + ONLY_RESET_AT_START) == 0) + amhevc_stop(); + } else + pbi->dec_result = DEC_RESULT_GET_DATA; +#else + if (!vdec_frame_based(hw_to_vdec(pbi))) + pbi->dec_result = DEC_RESULT_AGAIN; + else + pbi->dec_result = DEC_RESULT_DONE; + amhevc_stop(); +#endif + schedule_work(&pbi->work); + } + pbi->process_busy = 0; + return IRQ_HANDLED; + } else if (dec_status == HEVC_DECPIC_DATA_DONE) { + if (pbi->m_ins_flag) { + pbi->dec_result = DEC_RESULT_DONE; + amhevc_stop(); + schedule_work(&pbi->work); + } + + pbi->process_busy = 0; + return IRQ_HANDLED; + } else if ( + (dec_status == HEVC_SEARCH_BUFEMPTY) || + (dec_status == HEVC_DECODE_BUFEMPTY) || + (dec_status == HEVC_DECODE_TIMEOUT)) { + if (vdec_frame_based(hw_to_vdec(pbi)) || + (READ_VREG(HEVC_STREAM_LEVEL) > 0x200)) { + if (debug & VP9_DEBUG_DIS_LOC_ERROR_PROC) { + vp9_print(pbi, PRINT_FLAG_ERROR, + "%s decoding error, level 0x%x\n", + __func__, READ_VREG(HEVC_STREAM_LEVEL)); + goto send_again; + } + amhevc_stop(); + vp9_print(pbi, PRINT_FLAG_UCODE_EVT, + "%s %s\n", __func__, + (dec_status == HEVC_SEARCH_BUFEMPTY) ? + "HEVC_SEARCH_BUFEMPTY" : + (dec_status == HEVC_DECODE_BUFEMPTY) ? + "HEVC_DECODE_BUFEMPTY" : "HEVC_DECODE_TIMEOUT"); + pbi->dec_result = DEC_RESULT_DONE; + + schedule_work(&pbi->work); + } else { + /* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_INIT); */ + vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, + "%s DEC_RESULT_AGAIN\n", __func__); +send_again: + pbi->dec_result = DEC_RESULT_AGAIN; + schedule_work(&pbi->work); + } + pbi->process_busy = 0; + return IRQ_HANDLED; + } +#endif + + return IRQ_WAKE_THREAD; +} + +static void vvp9_put_timer_func(unsigned long arg) +{ + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)arg; + struct timer_list *timer = &pbi->timer; + uint8_t empty_flag; + unsigned int buf_level; + + enum receviver_start_e state = RECEIVER_INACTIVE; + if (pbi->m_ins_flag) { + if (hw_to_vdec(pbi)->next_status + == VDEC_STATUS_DISCONNECTED) { + pbi->dec_result = DEC_RESULT_DONE; + schedule_work(&pbi->work); + pr_info( + "vdec requested to be disconnected\n"); + return; + } + } + if (pbi->init_flag == 0) { + if (pbi->stat & STAT_TIMER_ARM) { + timer->expires = jiffies + PUT_INTERVAL; + add_timer(&pbi->timer); + } + return; + } + if (pbi->m_ins_flag == 0) { + if (vf_get_receiver(pbi->provider_name)) { + state = + vf_notify_receiver(pbi->provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + if ((state == RECEIVER_STATE_NULL) + || (state == RECEIVER_STATE_NONE)) + state = RECEIVER_INACTIVE; + } else + state = RECEIVER_INACTIVE; + + empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1; + /* error watchdog */ + if (empty_flag == 0) { + /* decoder has input */ + if ((debug & VP9_DEBUG_DIS_LOC_ERROR_PROC) == 0) { + + buf_level = READ_VREG(HEVC_STREAM_LEVEL); + /* receiver has no buffer to recycle */ + if ((state == RECEIVER_INACTIVE) && + (kfifo_is_empty(&pbi->display_q) && + buf_level > 0x200) + ) { + WRITE_VREG + (HEVC_ASSIST_MBOX1_IRQ_REG, + 0x1); + } + } + + if ((debug & VP9_DEBUG_DIS_SYS_ERROR_PROC) == 0) { + /* receiver has no buffer to recycle */ + /*if ((state == RECEIVER_INACTIVE) && + (kfifo_is_empty(&pbi->display_q))) { + pr_info("vp9 something error,need reset\n"); + }*/ + } + } + } + + if (decode_stop_pos != decode_stop_pos_pre) { + WRITE_VREG(DECODE_STOP_POS, decode_stop_pos); + decode_stop_pos_pre = decode_stop_pos; + } + + if (debug & VP9_DEBUG_DUMP_PIC_LIST) { + dump_pic_list(pbi); + debug &= ~VP9_DEBUG_DUMP_PIC_LIST; + } + if (debug & VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC) { + WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1); + debug &= ~VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC; + } + /*if (debug & VP9_DEBUG_HW_RESET) { + }*/ + if (debug & VP9_DEBUG_ERROR_TRIG) { + WRITE_VREG(DECODE_STOP_POS, 1); + debug &= ~VP9_DEBUG_ERROR_TRIG; + } + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + if (pop_shorts != 0) { + int i; + u32 sum = 0; + pr_info("pop stream 0x%x shorts\r\n", pop_shorts); + for (i = 0; i < pop_shorts; i++) { + u32 data = + (READ_HREG(HEVC_SHIFTED_DATA) >> 16); + WRITE_HREG(HEVC_SHIFT_COMMAND, + (1<<7)|16); + if ((i & 0xf) == 0) + pr_info("%04x:", i); + pr_info("%04x ", data); + if (((i + 1) & 0xf) == 0) + pr_info("\r\n"); + sum += data; + } + pr_info("\r\nsum = %x\r\n", sum); + pop_shorts = 0; + } + if (dbg_cmd != 0) { + if (dbg_cmd == 1) { + u32 disp_laddr; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + double_write_mode == 0) { + disp_laddr = + READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; + } else { + struct canvas_s cur_canvas; + canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) + & 0xff), &cur_canvas); + disp_laddr = cur_canvas.addr; + } + pr_info("current displayed buffer address %x\r\n", + disp_laddr); + } + dbg_cmd = 0; + } + /*don't changed at start.*/ + if (pbi->get_frame_dur && pbi->show_frame_num > 60 && + pbi->frame_dur > 0 && pbi->saved_resolution != + frame_width * frame_height * + (96000 / pbi->frame_dur)) { + int fps = 96000 / pbi->frame_dur; + if (hevc_source_changed(VFORMAT_VP9, + frame_width, frame_height, fps) > 0) + pbi->saved_resolution = frame_width * + frame_height * fps; + } + + timer->expires = jiffies + PUT_INTERVAL; + add_timer(timer); +} + + +int vvp9_dec_status(struct vdec_s *vdec, struct vdec_status *vstatus) +{ + struct VP9Decoder_s *pbi = &gHevc; + vstatus->width = frame_width; + vstatus->height = frame_height; + if (pbi->frame_dur != 0) + vstatus->fps = 96000 / pbi->frame_dur; + else + vstatus->fps = -1; + vstatus->error_count = 0; + vstatus->status = pbi->stat | pbi->fatal_error; + return 0; +} + +#if 0 +static void VP9_DECODE_INIT(void) +{ + /* enable vp9 clocks */ + WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); + /* *************************************************************** */ + /* Power ON HEVC */ + /* *************************************************************** */ + /* Powerup HEVC */ + WRITE_VREG(AO_RTI_GEN_PWR_SLEEP0, + READ_VREG(AO_RTI_GEN_PWR_SLEEP0) & (~(0x3 << 6))); + WRITE_VREG(DOS_MEM_PD_HEVC, 0x0); + WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) | (0x3ffff << 2)); + WRITE_VREG(DOS_SW_RESET3, READ_VREG(DOS_SW_RESET3) & (~(0x3ffff << 2))); + /* remove isolations */ + WRITE_VREG(AO_RTI_GEN_PWR_ISO0, + READ_VREG(AO_RTI_GEN_PWR_ISO0) & (~(0x3 << 10))); + +} +#endif + +static void vvp9_prot_init(struct VP9Decoder_s *pbi) +{ + unsigned int data32; + /* VP9_DECODE_INIT(); */ + vp9_config_work_space_hw(pbi); + init_pic_list_hw(pbi); + + vp9_init_decoder_hw(pbi); + +#ifdef VP9_LPF_LVL_UPDATE + vp9_loop_filter_init(); +#endif + +#if 1 + if (debug & VP9_DEBUG_BUFMGR) + pr_info("[test.c] Enable BitStream Fetch\n"); + data32 = READ_VREG(HEVC_STREAM_CONTROL); + data32 = data32 | + (1 << 0)/*stream_fetch_enable*/ + ; + WRITE_VREG(HEVC_STREAM_CONTROL, data32); +#if 0 + data32 = READ_VREG(HEVC_SHIFT_STARTCODE); + if (data32 != 0x00000100) { + pr_info("vp9 prot init error %d\n", __LINE__); + return; + } + data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); + if (data32 != 0x00000300) { + pr_info("vp9 prot init error %d\n", __LINE__); + return; + } + WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); + WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); + data32 = READ_VREG(HEVC_SHIFT_STARTCODE); + if (data32 != 0x12345678) { + pr_info("vp9 prot init error %d\n", __LINE__); + return; + } + data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); + if (data32 != 0x9abcdef0) { + pr_info("vp9 prot init error %d\n", __LINE__); + return; + } +#endif + WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x000000001); + WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000300); +#endif + + + + WRITE_VREG(HEVC_WAIT_FLAG, 1); + + /* WRITE_VREG(HEVC_MPSR, 1); */ + + /* clear mailbox interrupt */ + WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1); + + /* enable mailbox interrupt */ + WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 1); + + /* disable PSCALE for hardware sharing */ + WRITE_VREG(HEVC_PSCALE_CTRL, 0); + + if (debug & VP9_DEBUG_UCODE) + WRITE_VREG(DEBUG_REG1, 0x1); + else + WRITE_VREG(DEBUG_REG1, 0x0); + /*check vps/sps/pps/i-slice in ucode*/ + WRITE_VREG(NAL_SEARCH_CTL, 0x8); + + WRITE_VREG(DECODE_STOP_POS, decode_stop_pos); + +} + +static int vvp9_local_init(struct VP9Decoder_s *pbi) +{ + int i; + int ret; + int width, height; +#ifdef DEBUG_PTS + pbi->pts_missed = 0; + pbi->pts_hit = 0; +#endif + pbi->new_frame_displayed = 0; + pbi->last_put_idx = -1; + pbi->saved_resolution = 0; + pbi->get_frame_dur = false; + on_no_keyframe_skiped = 0; + width = pbi->vvp9_amstream_dec_info.width; + height = pbi->vvp9_amstream_dec_info.height; + pbi->frame_dur = + (pbi->vvp9_amstream_dec_info.rate == + 0) ? 3600 : pbi->vvp9_amstream_dec_info.rate; + if (width && height) + pbi->frame_ar = height * 0x100 / width; +/* +TODO:FOR VERSION +*/ + pr_info("vp9: ver (%d,%d) decinfo: %dx%d rate=%d\n", vp9_version, + 0, width, height, pbi->frame_dur); + + if (pbi->frame_dur == 0) + pbi->frame_dur = 96000 / 24; + + INIT_KFIFO(pbi->display_q); + INIT_KFIFO(pbi->newframe_q); + + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &pbi->vfpool[i]; + pbi->vfpool[i].index = -1; + kfifo_put(&pbi->newframe_q, vf); + } + + + ret = vp9_local_init(pbi); + + return ret; +} + +static s32 vvp9_init(struct VP9Decoder_s *pbi) +{ + int size = -1; + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return -ENOMEM; + + init_timer(&pbi->timer); + + pbi->stat |= STAT_TIMER_INIT; + if (vvp9_local_init(pbi) < 0) { + vfree(buf); + return -EBUSY; + } + +#ifdef MULTI_INSTANCE_SUPPORT + if (pbi->m_ins_flag) { + pbi->timer.data = (ulong) pbi; + pbi->timer.function = vvp9_put_timer_func; + pbi->timer.expires = jiffies + PUT_INTERVAL; + + add_timer(&pbi->timer); + + pbi->stat |= STAT_TIMER_ARM; + + INIT_WORK(&pbi->work, vp9_work); + + vfree(buf); + return 0; + } +#endif + + amhevc_enable(); + + size = get_firmware_data(VIDEO_DEC_VP9_MMU, buf); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(buf); + return -1; + } + + if (amhevc_loadmc_ex(VFORMAT_VP9, NULL, buf) < 0) { + amhevc_disable(); + vfree(buf); + return -EBUSY; + } + + vfree(buf); + + pbi->stat |= STAT_MC_LOAD; + + /* enable AMRISC side protocol */ + vvp9_prot_init(pbi); + + if (vdec_request_threaded_irq(VDEC_IRQ_1, + vvp9_isr, + vvp9_isr_thread_fn, + IRQF_ONESHOT,/*run thread on this irq disabled*/ + "vvp9-irq", (void *)pbi)) { + pr_info("vvp9 irq register error.\n"); + amhevc_disable(); + return -ENOENT; + } + + pbi->stat |= STAT_ISR_REG; + + pbi->provider_name = PROVIDER_NAME; + vf_provider_init(&vvp9_vf_prov, PROVIDER_NAME, &vvp9_vf_provider, + pbi); + vf_reg_provider(&vvp9_vf_prov); + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); + + vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)pbi->frame_dur)); + + pbi->stat |= STAT_VF_HOOK; + + pbi->timer.data = (ulong)pbi; + pbi->timer.function = vvp9_put_timer_func; + pbi->timer.expires = jiffies + PUT_INTERVAL; + + + add_timer(&pbi->timer); + + pbi->stat |= STAT_TIMER_ARM; + + /* pbi->stat |= STAT_KTHREAD; */ + + amhevc_start(); + + pbi->stat |= STAT_VDEC_RUN; + + pbi->init_flag = 1; + pbi->process_busy = 0; + pr_info("%d, vvp9_init, RP=0x%x\n", + __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); + return 0; +} + +static int vvp9_stop(struct VP9Decoder_s *pbi) +{ + + pbi->init_flag = 0; + /* + if ((debug & VP9_DEBUG_NOWAIT_DECODE_DONE_WHEN_STOP) == 0) { + int wait_timeout_count = 0; + while ((READ_VREG(HEVC_DEC_STATUS_REG) == + VP9_10B_DECODE_SLICE && + wait_timeout_count < 10) || + pbi->process_busy){ + wait_timeout_count++; + msleep(20); + } + } + */ + if (pbi->stat & STAT_VDEC_RUN) { + amhevc_stop(); + pbi->stat &= ~STAT_VDEC_RUN; + } + + if (pbi->stat & STAT_ISR_REG) { + WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)pbi); + pbi->stat &= ~STAT_ISR_REG; + } + + if (pbi->stat & STAT_TIMER_ARM) { + del_timer_sync(&pbi->timer); + pbi->stat &= ~STAT_TIMER_ARM; + } + + if (pbi->stat & STAT_VF_HOOK) { + vf_notify_receiver(pbi->provider_name, + VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); + + vf_unreg_provider(&vvp9_vf_prov); + pbi->stat &= ~STAT_VF_HOOK; + } + vp9_local_uninit(pbi); + +#ifdef MULTI_INSTANCE_SUPPORT + if (pbi->m_ins_flag) { + cancel_work_sync(&pbi->work); + } else { + amhevc_disable(); + } +#else + amhevc_disable(); +#endif + uninit_mmu_buffers(pbi); + + return 0; +} + +static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi) +{ +#ifdef VP9_10B_MMU + pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, + 0, FRAME_BUFFERS, + 48 * SZ_1M + ); + if (!pbi->mmu_box) { + pr_err("vp9 alloc mmu box failed!!\n"); + return -1; + } +#endif + pbi->bmmu_box = decoder_bmmu_box_alloc_box( + DRIVER_NAME, + pbi->index, + MAX_BMMU_BUFFER_NUM, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + if (!pbi->bmmu_box) { + pr_err("vp9 alloc bmmu box failed!!\n"); + return -1; + } + return 0; +} +static int amvdec_vp9_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct BUF_s BUF[MAX_BUF_NUM]; + struct VP9Decoder_s *pbi = &gHevc; + pr_info("%s\n", __func__); + mutex_lock(&vvp9_mutex); + + memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); + memset(pbi, 0, sizeof(VP9Decoder)); + memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); + + pbi->init_flag = 0; + pbi->fatal_error = 0; + pbi->show_frame_num = 0; + if (pdata == NULL) { + pr_info("\namvdec_vp9 memory resource undefined.\n"); + mutex_unlock(&vvp9_mutex); + return -EFAULT; + } + pbi->m_ins_flag = 0; +#ifdef MULTI_INSTANCE_SUPPORT + pbi->buf_start = pdata->mem_start; + pbi->buf_size = pdata->mem_end - pdata->mem_start + 1; +#else + pbi->mc_buf_spec.buf_end = pdata->mem_end + 1; + for (i = 0; i < WORK_BUF_SPEC_NUM; i++) + amvvp9_workbuff_spec[i].start_adr = pdata->mem_start; +#endif + if (amvdec_vp9_mmu_init(pbi) < 0) { + pr_err("vp9 alloc bmmu box failed!!\n"); + return -1; + } + if (debug) { + pr_info("===VP9 decoder mem resource 0x%lx -- 0x%lx\n", + pdata->mem_start, pdata->mem_end + 1); + } + + if (pdata->sys_info) + pbi->vvp9_amstream_dec_info = *pdata->sys_info; + else { + pbi->vvp9_amstream_dec_info.width = 0; + pbi->vvp9_amstream_dec_info.height = 0; + pbi->vvp9_amstream_dec_info.rate = 30; + } +#ifdef MULTI_INSTANCE_SUPPORT + pbi->cma_dev = pdata->cma_dev; +#else + cma_dev = pdata->cma_dev; +#endif + pdata->dec_status = vvp9_dec_status; + + if (vvp9_init(pbi) < 0) { + pr_info("\namvdec_vp9 init failed.\n"); + vp9_local_uninit(pbi); + mutex_unlock(&vvp9_mutex); + return -ENODEV; + } + /*set the max clk for smooth playing...*/ + hevc_source_changed(VFORMAT_VP9, + 4096, 2048, 60); + mutex_unlock(&vvp9_mutex); + + return 0; +} + +static int amvdec_vp9_remove(struct platform_device *pdev) +{ + struct VP9Decoder_s *pbi = &gHevc; + if (debug) + pr_info("amvdec_vp9_remove\n"); + + mutex_lock(&vvp9_mutex); + + vvp9_stop(pbi); + + + hevc_source_changed(VFORMAT_VP9, 0, 0, 0); + + +#ifdef DEBUG_PTS + pr_info("pts missed %ld, pts hit %ld, duration %d\n", + pbi->pts_missed, pbi->pts_hit, pbi->frame_dur); +#endif + + mutex_unlock(&vvp9_mutex); + + return 0; +} + +/****************************************/ + +static struct platform_driver amvdec_vp9_driver = { + .probe = amvdec_vp9_probe, + .remove = amvdec_vp9_remove, +#ifdef CONFIG_PM + .suspend = amhevc_suspend, + .resume = amhevc_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t amvdec_vp9_profile = { + .name = "vp9", + .profile = "" +}; + +#ifdef MULTI_INSTANCE_SUPPORT +static unsigned int start_decode_buf_level = 0x8000; +#ifdef VP9_10B_MMU +static u32 work_buf_size = 24 * 1024 * 1024; +#else +static u32 work_buf_size = 32 * 1024 * 1024; +#endif + +static unsigned char decoder_id_used[MAX_DECODE_INSTANCE_NUM]; +static unsigned int get_free_decoder_id(struct vdec_s *vdec) +{ + /*stream base decoder always has id of 0*/ + int i; + if (vdec_frame_based(vdec)) { + for (i = 1; i < decoder_id_used[i]; i++) { + if (!decoder_id_used[i]) { + decoder_id_used[i] = 1; + return i; + } + } + } + return 0; +} + +static unsigned char get_data_check_sum + (struct VP9Decoder_s *pbi, int size) +{ + int jj; + int sum = 0; + u8 *data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + for (jj = 0; jj < size; jj++) + sum += data[jj]; + return sum; +} + +static void dump_data(struct VP9Decoder_s *pbi, int size) +{ + int jj; + u8 *data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + for (jj = 0; jj < size; jj++) { + if ((jj & 0xf) == 0) + vp9_print(pbi, + 0, + "%06x:", jj); + vp9_print_cont(pbi, + 0, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + vp9_print(pbi, + 0, + "\n"); + } + vp9_print(pbi, + 0, + "\n"); +} + +static void vp9_work(struct work_struct *work) +{ + struct VP9Decoder_s *pbi = container_of(work, + struct VP9Decoder_s, work); + struct VP9_Common_s *const cm = &pbi->common; + struct vdec_s *vdec = hw_to_vdec(pbi); + /* finished decoding one frame or error, + * notify vdec core to switch context + */ + + if ((pbi->dec_result == DEC_RESULT_GET_DATA) || + (pbi->dec_result == DEC_RESULT_GET_DATA_RETRY)) { + if (pbi->dec_result == DEC_RESULT_GET_DATA) { + vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, + "%s DEC_RESULT_GET_DATA %x %x %x\n", + __func__, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); + vdec_vframe_dirty(vdec, pbi->chunk); + vdec_clean_input(vdec); + } + + if (!is_buffer_empty(cm)) { + int r; + r = vdec_prepare_input(vdec, &pbi->chunk); + if (r < 0) { + pbi->dec_result = DEC_RESULT_GET_DATA_RETRY; + + vp9_print(pbi, + PRINT_FLAG_VDEC_DETAIL, + "amvdec_vh265: Insufficient data\n"); + + schedule_work(&pbi->work); + return; + } + pbi->dec_result = DEC_RESULT_NONE; + vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, + "%s: chunk size 0x%x sum 0x%x\n", + __func__, r, + (debug & PRINT_FLAG_VDEC_STATUS) ? + get_data_check_sum(pbi, r) : 0 + ); + + if (debug & PRINT_FLAG_VDEC_DATA) + dump_data(pbi, pbi->chunk->size); + WRITE_VREG(HEVC_DECODE_SIZE, r); + + vdec_enable_input(vdec); + + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + } else{ + pbi->dec_result = DEC_RESULT_GET_DATA_RETRY; + + vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, + "amvdec_vh265: Insufficient data\n"); + + schedule_work(&pbi->work); + } + return; + } else if (pbi->dec_result == DEC_RESULT_DONE) { + /* if (!pbi->ctx_valid) + pbi->ctx_valid = 1; */ + vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, + "%s dec_result %d %x %x %x\n", + __func__, + pbi->dec_result, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); + vdec_vframe_dirty(hw_to_vdec(pbi), pbi->chunk); + } else { + vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, + "%s dec_result %d %x %x %x\n", + __func__, + pbi->dec_result, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); + } + + /* mark itself has all HW resource released and input released */ + vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_CONNECTED); + + if (pbi->vdec_cb) + pbi->vdec_cb(hw_to_vdec(pbi), pbi->vdec_cb_arg); +} + +static int vp9_hw_ctx_restore(struct VP9Decoder_s *pbi) +{ + /* new to do ... */ + vvp9_prot_init(pbi); + return 0; +} + +static bool run_ready(struct vdec_s *vdec) +{ + struct VP9Decoder_s *pbi = + (struct VP9Decoder_s *)vdec->private; + struct VP9_Common_s *const cm = &pbi->common; + + vp9_print(pbi, + PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + + if ((!vdec_frame_based(vdec)) && (start_decode_buf_level > 0)) { + u32 rp, wp; + u32 level; + + rp = READ_MPEG_REG(PARSER_VIDEO_RP); + wp = READ_MPEG_REG(PARSER_VIDEO_WP); + + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < start_decode_buf_level) { + vp9_print(pbi, 0, + "level %d not run_ready\n", level); + return false; + } + } else if (vdec_frame_based(vdec)) { + if (!vdec_input_next_input_chunk(&vdec->input)) + return false; + } + + return !is_buffer_empty(cm); +} + +static void reset_dec_hw(struct vdec_s *vdec) +{ + if (input_frame_based(vdec)) + WRITE_VREG(HEVC_STREAM_CONTROL, 0); + + /* + * 2: assist + * 3: parser + * 4: parser_state + * 8: dblk + * 11:mcpu + * 12:ccpu + * 13:ddr + * 14:iqit + * 15:ipp + * 17:qdct + * 18:mpred + * 19:sao + * 24:hevc_afifo + */ + WRITE_VREG(DOS_SW_RESET3, + (1<<3)|(1<<4)|(1<<8)|(1<<11)|(1<<12)|(1<<14)|(1<<15)| + (1<<17)|(1<<18)|(1<<19)); + WRITE_VREG(DOS_SW_RESET3, 0); +} + +static void run(struct vdec_s *vdec, + void (*callback)(struct vdec_s *, void *), void *arg) +{ + struct VP9Decoder_s *pbi = + (struct VP9Decoder_s *)vdec->private; + int r, size = -1; + + char *buf = vmalloc(0x1000 * 16); + if (IS_ERR_OR_NULL(buf)) + return; + + pbi->vdec_cb_arg = arg; + pbi->vdec_cb = callback; + /* pbi->chunk = vdec_prepare_input(vdec); */ + reset_dec_hw(vdec); + + r = vdec_prepare_input(vdec, &pbi->chunk); + if (r < 0) { + pbi->dec_result = DEC_RESULT_AGAIN; + + vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, + "ammvdec_vh265: Insufficient data\n"); + + schedule_work(&pbi->work); + return; + } + pbi->dec_result = DEC_RESULT_NONE; + + vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, + "%s: size 0x%x sum 0x%x (%x %x %x)\n", + __func__, r, + (vdec_frame_based(vdec) && + (debug & PRINT_FLAG_VDEC_STATUS)) ? + get_data_check_sum(pbi, r) : 0, + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR)); + + size = get_firmware_data(VIDEO_DEC_VP9_MMU, buf); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(buf); + return; + } + + if (amhevc_loadmc_ex(VFORMAT_VP9, NULL, buf) < 0) { + amhevc_disable(); + vfree(buf); + return; + } + + vfree(buf); + + if (vp9_hw_ctx_restore(pbi) < 0) { + schedule_work(&pbi->work); + return; + } + + vdec_enable_input(vdec); + + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + + if (vdec_frame_based(vdec)) { + if (debug & PRINT_FLAG_VDEC_DATA) + dump_data(pbi, pbi->chunk->size); + + WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); + } + WRITE_VREG(HEVC_DECODE_SIZE, r); + WRITE_VREG(HEVC_DECODE_COUNT, pbi->slice_idx); + pbi->init_flag = 1; + + vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, + "%s: start hevc (%x %x %x)\n", + __func__, + READ_VREG(HEVC_DEC_STATUS_REG), + READ_VREG(HEVC_MPC_E), + READ_VREG(HEVC_MPSR)); + + amhevc_start(); + +} + +static void reset(struct vdec_s *vdec) +{ + + struct VP9Decoder_s *pbi = + (struct VP9Decoder_s *)vdec->private; + + vp9_print(pbi, + PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + +} + +static irqreturn_t vp9_irq_cb(struct vdec_s *vdec) +{ + struct VP9Decoder_s *pbi = + (struct VP9Decoder_s *)vdec->private; + return vvp9_isr(0, pbi); +} + +static irqreturn_t vp9_threaded_irq_cb(struct vdec_s *vdec) +{ + struct VP9Decoder_s *pbi = + (struct VP9Decoder_s *)vdec->private; + return vvp9_isr_thread_fn(0, pbi); +} + + +static int ammvdec_vp9_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + + struct BUF_s BUF[MAX_BUF_NUM]; + struct VP9Decoder_s *pbi = NULL; + pr_info("%s\n", __func__); + if (pdata == NULL) { + pr_info("\nammvdec_vp9 memory resource undefined.\n"); + return -EFAULT; + } + pbi = (struct VP9Decoder_s *)devm_kzalloc(&pdev->dev, + sizeof(struct VP9Decoder_s), GFP_KERNEL); + if (pbi == NULL) { + pr_info("\nammvdec_vp9 device data allocation failed\n"); + return -ENOMEM; + } + pdata->private = pbi; + pdata->dec_status = vvp9_dec_status; + /* pdata->set_trickmode = set_trickmode; */ + pdata->run_ready = run_ready; + pdata->run = run; + pdata->reset = reset; + pdata->irq_handler = vp9_irq_cb; + pdata->threaded_irq_handler = vp9_threaded_irq_cb; + + pdata->id = pdev->id; + + + memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); + memset(pbi, 0, sizeof(VP9Decoder)); + memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); + + pbi->index = get_free_decoder_id(pdata); + + if (pdata->use_vfm_path) + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); + else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); + + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vvp9_vf_provider, pbi); + + pbi->provider_name = pdata->vf_provider_name; + platform_set_drvdata(pdev, pdata); + + pbi->platform_dev = pdev; +#if 0 + pbi->buf_start = pdata->mem_start; + pbi->buf_size = pdata->mem_end - pdata->mem_start + 1; +#else + if (amvdec_vp9_mmu_init(pbi) < 0) { + pr_err("vp9 alloc bmmu box failed!!\n"); + devm_kfree(&pdev->dev, (void *)pbi); + return -1; + } + + pbi->cma_alloc_count = PAGE_ALIGN(work_buf_size) / PAGE_SIZE; + if (!decoder_bmmu_box_alloc_idx_wait( + pbi->bmmu_box, + WORK_SPACE_BUF_ID, + pbi->cma_alloc_count * PAGE_SIZE, + -1, + -1, + BMMU_ALLOC_FLAGS_WAITCLEAR + )) { + pbi->cma_alloc_addr = decoder_bmmu_box_get_phy_addr( + pbi->bmmu_box, + WORK_SPACE_BUF_ID); + } else { + vp9_print(pbi, 0, + "codec_mm alloc failed, request buf size 0x%lx\n", + pbi->cma_alloc_count * PAGE_SIZE); + pbi->cma_alloc_count = 0; + uninit_mmu_buffers(pbi); + devm_kfree(&pdev->dev, (void *)pbi); + return -ENOMEM; + } + pbi->buf_start = pbi->cma_alloc_addr; + pbi->buf_size = work_buf_size; +#endif + pbi->m_ins_flag = 1; + + pbi->init_flag = 0; + pbi->fatal_error = 0; + pbi->show_frame_num = 0; + if (pdata == NULL) { + pr_info("\namvdec_vp9 memory resource undefined.\n"); + uninit_mmu_buffers(pbi); + devm_kfree(&pdev->dev, (void *)pbi); + return -EFAULT; + } + + if (debug) { + pr_info("===VP9 decoder mem resource 0x%lx -- 0x%lx\n", + pbi->buf_start, + pbi->buf_start + pbi->buf_size); + } + + if (pdata->sys_info) + pbi->vvp9_amstream_dec_info = *pdata->sys_info; + else { + pbi->vvp9_amstream_dec_info.width = 0; + pbi->vvp9_amstream_dec_info.height = 0; + pbi->vvp9_amstream_dec_info.rate = 30; + } + + pbi->cma_dev = pdata->cma_dev; + + if (vvp9_init(pbi) < 0) { + pr_info("\namvdec_vp9 init failed.\n"); + vp9_local_uninit(pbi); + uninit_mmu_buffers(pbi); + devm_kfree(&pdev->dev, (void *)pbi); + return -ENODEV; + } + return 0; +} + +static int ammvdec_vp9_remove(struct platform_device *pdev) +{ + struct VP9Decoder_s *pbi = (struct VP9Decoder_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + if (debug) + pr_info("amvdec_vp9_remove\n"); + + vvp9_stop(pbi); + + vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_DISCONNECTED); + + +#ifdef DEBUG_PTS + pr_info("pts missed %ld, pts hit %ld, duration %d\n", + pbi->pts_missed, pbi->pts_hit, pbi->frame_dur); +#endif + devm_kfree(&pdev->dev, (void *)pbi); + return 0; +} + +static struct platform_driver ammvdec_vp9_driver = { + .probe = ammvdec_vp9_probe, + .remove = ammvdec_vp9_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = MULTI_DRIVER_NAME, + } +}; +#endif + +static int __init amvdec_vp9_driver_init_module(void) +{ + pr_debug("amvdec_vp9 module init\n"); + error_handle_policy = 0; + +#ifdef ERROR_HANDLE_DEBUG + dbg_nal_skip_flag = 0; + dbg_nal_skip_count = 0; +#endif + decode_stop_pos = 0; + decode_stop_pos_pre = 0; + decode_pic_begin = 0; + slice_parse_begin = 0; + step = 0; + buf_alloc_size = 0; +#ifdef MULTI_INSTANCE_SUPPORT + if (platform_driver_register(&ammvdec_vp9_driver)) + pr_err("failed to register ammvdec_vp9 driver\n"); + +#endif + if (platform_driver_register(&amvdec_vp9_driver)) { + pr_err("failed to register amvdec_vp9 driver\n"); + return -ENODEV; + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + amvdec_vp9_profile.profile = + "4k, 10bit, dwrite, compressed"; + } else { + amvdec_vp9_profile.name = "vp9_unsupport"; + } + + vcodec_profile_register(&amvdec_vp9_profile); + + return 0; +} + +static void __exit amvdec_vp9_driver_remove_module(void) +{ + pr_debug("amvdec_vp9 module remove.\n"); +#ifdef MULTI_INSTANCE_SUPPORT + platform_driver_unregister(&ammvdec_vp9_driver); +#endif + platform_driver_unregister(&amvdec_vp9_driver); +} + +/****************************************/ +/* +module_param(stat, uint, 0664); +MODULE_PARM_DESC(stat, "\n amvdec_vp9 stat\n"); +*/ +module_param(use_cma, uint, 0664); +MODULE_PARM_DESC(use_cma, "\n amvdec_vp9 use_cma\n"); + +module_param(bit_depth_luma, uint, 0664); +MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_vp9 bit_depth_luma\n"); + +module_param(bit_depth_chroma, uint, 0664); +MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_vp9 bit_depth_chroma\n"); + +module_param(frame_width, uint, 0664); +MODULE_PARM_DESC(frame_width, "\n amvdec_vp9 frame_width\n"); + +module_param(frame_height, uint, 0664); +MODULE_PARM_DESC(frame_height, "\n amvdec_vp9 frame_height\n"); + +module_param(debug, uint, 0664); +MODULE_PARM_DESC(debug, "\n amvdec_vp9 debug\n"); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(pop_shorts, uint, 0664); +MODULE_PARM_DESC(pop_shorts, "\nrval\n"); + +module_param(dbg_cmd, uint, 0664); +MODULE_PARM_DESC(dbg_cmd, "\ndbg_cmd\n"); + +module_param(dbg_skip_decode_index, uint, 0664); +MODULE_PARM_DESC(dbg_skip_decode_index, "\ndbg_skip_decode_index\n"); + +module_param(endian, uint, 0664); +MODULE_PARM_DESC(endian, "\nrval\n"); + +module_param(step, uint, 0664); +MODULE_PARM_DESC(step, "\n amvdec_vp9 step\n"); + +module_param(decode_stop_pos, uint, 0664); +MODULE_PARM_DESC(decode_stop_pos, "\n amvdec_vp9 decode_stop_pos\n"); + +module_param(decode_pic_begin, uint, 0664); +MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_vp9 decode_pic_begin\n"); + +module_param(slice_parse_begin, uint, 0664); +MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_vp9 slice_parse_begin\n"); + +module_param(i_only_flag, uint, 0664); +MODULE_PARM_DESC(i_only_flag, "\n amvdec_vp9 i_only_flag\n"); + +module_param(error_handle_policy, uint, 0664); +MODULE_PARM_DESC(error_handle_policy, "\n amvdec_vp9 error_handle_policy\n"); + +module_param(buf_alloc_width, uint, 0664); +MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); + +module_param(buf_alloc_height, uint, 0664); +MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n"); + +module_param(buf_alloc_depth, uint, 0664); +MODULE_PARM_DESC(buf_alloc_depth, "\n buf_alloc_depth\n"); + +module_param(buf_alloc_size, uint, 0664); +MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); + +module_param(buffer_mode, uint, 0664); +MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n"); + +module_param(buffer_mode_dbg, uint, 0664); +MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n"); +/*USE_BUF_BLOCK*/ +module_param(max_buf_num, uint, 0664); +MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); + +module_param(dynamic_buf_num_margin, uint, 0664); +MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); +/**/ + +module_param(mem_map_mode, uint, 0664); +MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); + +#ifdef SUPPORT_10BIT +module_param(double_write_mode, uint, 0664); +MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); + +module_param(enable_mem_saving, uint, 0664); +MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n"); + +module_param(force_w_h, uint, 0664); +MODULE_PARM_DESC(force_w_h, "\n force_w_h\n"); +#endif + +module_param(force_fps, uint, 0664); +MODULE_PARM_DESC(force_fps, "\n force_fps\n"); + +module_param(max_decoding_time, uint, 0664); +MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n"); + +module_param(on_no_keyframe_skiped, uint, 0664); +MODULE_PARM_DESC(on_no_keyframe_skiped, "\n on_no_keyframe_skiped\n"); + +#ifdef MULTI_INSTANCE_SUPPORT +module_param(start_decode_buf_level, uint, 0664); +MODULE_PARM_DESC(start_decode_buf_level, + "\n ammvdec_h264 start_decode_buf_level\n"); +#endif + +module_init(amvdec_vp9_driver_init_module); +module_exit(amvdec_vp9_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC vp9 Video Decoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h new file mode 100644 index 000000000000..4cf325485e49 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h @@ -0,0 +1,25 @@ +/* + * drivers/amlogic/amports/vvp9.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef VVP9_H +#define VVP9_H +#ifndef CONFIG_MULTI_DEC +#define VP9_10B_MMU +#endif +void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, +unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count); +#endif diff --git a/drivers/amlogic/media_modules/frame_sink/Makefile b/drivers/amlogic/media_modules/frame_sink/Makefile new file mode 100644 index 000000000000..2b9754a3947e --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/Makefile @@ -0,0 +1 @@ +obj-y += encoder/ diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/Makefile b/drivers/amlogic/media_modules/frame_sink/encoder/Makefile new file mode 100644 index 000000000000..9afecec9265f --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_AMLOGIC_MEDIA_VENC_H264) += h264/ +obj-$(CONFIG_AMLOGIC_MEDIA_VENC_H265) += h265/ diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile b/drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile new file mode 100644 index 000000000000..c12d7c3d86b2 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/Makefile @@ -0,0 +1 @@ +obj-m += encoder.o diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c new file mode 100644 index 000000000000..9badd5395416 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c @@ -0,0 +1,4237 @@ +/* + * drivers/amlogic/amports/encoder.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../../../frame_provider/decoder/utils/vdec.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "encoder.h" +#include "../../../frame_provider/decoder/utils/amvdec.h" +#include +#include "../../../stream_input/amports/amports_priv.h" +#include +#ifdef CONFIG_AM_JPEG_ENCODER +#include "jpegenc.h" +#endif + +#define ENCODE_NAME "encoder" +#define AMVENC_CANVAS_INDEX 0xE4 +#define AMVENC_CANVAS_MAX_INDEX 0xEF + +#define MIN_SIZE amvenc_buffspec[0].min_buffsize +#define DUMP_INFO_BYTES_PER_MB 80 + +#define ADJUSTED_QP_FLAG 64 + +static s32 avc_device_major; +static struct device *amvenc_avc_dev; +#define DRIVER_NAME "amvenc_avc" +#define CLASS_NAME "amvenc_avc" +#define DEVICE_NAME "amvenc_avc" + +static struct encode_manager_s encode_manager; + +#define MULTI_SLICE_MC +#define H264_ENC_CBR +/* #define MORE_MODULE_PARAM */ + +#define ENC_CANVAS_OFFSET AMVENC_CANVAS_INDEX + +#define UCODE_MODE_FULL 0 + +/* #define ENABLE_IGNORE_FUNCTION */ + +static u32 ie_me_mb_type; +static u32 ie_me_mode; +static u32 ie_pippeline_block = 3; +static u32 ie_cur_ref_sel; +/* static u32 avc_endian = 6; */ +static u32 clock_level = 5; + +static u32 encode_print_level = LOG_DEBUG; +static u32 no_timeout; +static int nr_mode = -1; +static u32 qp_table_debug; + +static u32 me_mv_merge_ctl = + (0x1 << 31) | /* [31] me_merge_mv_en_16 */ + (0x1 << 30) | /* [30] me_merge_small_mv_en_16 */ + (0x1 << 29) | /* [29] me_merge_flex_en_16 */ + (0x1 << 28) | /* [28] me_merge_sad_en_16 */ + (0x1 << 27) | /* [27] me_merge_mv_en_8 */ + (0x1 << 26) | /* [26] me_merge_small_mv_en_8 */ + (0x1 << 25) | /* [25] me_merge_flex_en_8 */ + (0x1 << 24) | /* [24] me_merge_sad_en_8 */ + /* [23:18] me_merge_mv_diff_16 - MV diff <= n pixel can be merged */ + (0x12 << 18) | + /* [17:12] me_merge_mv_diff_8 - MV diff <= n pixel can be merged */ + (0x2b << 12) | + /* [11:0] me_merge_min_sad - SAD >= 0x180 can be merged with other MV */ + (0x80 << 0); + /* ( 0x4 << 18) | + // [23:18] me_merge_mv_diff_16 - MV diff <= n pixel can be merged */ + /* ( 0x3f << 12) | + // [17:12] me_merge_mv_diff_8 - MV diff <= n pixel can be merged */ + /* ( 0xc0 << 0); + // [11:0] me_merge_min_sad - SAD >= 0x180 can be merged with other MV */ + +static u32 me_mv_weight_01 = (0x40 << 24) | (0x30 << 16) | (0x20 << 8) | 0x30; +static u32 me_mv_weight_23 = (0x40 << 8) | 0x30; +static u32 me_sad_range_inc = 0x03030303; +static u32 me_step0_close_mv = 0x003ffc21; +static u32 me_f_skip_sad; +static u32 me_f_skip_weight; +static u32 me_sad_enough_01;/* 0x00018010; */ +static u32 me_sad_enough_23;/* 0x00000020; */ + +/* [31:0] NUM_ROWS_PER_SLICE_P */ +/* [15:0] NUM_ROWS_PER_SLICE_I */ +static u32 fixed_slice_cfg; + +/* y tnr */ +static unsigned int y_tnr_mc_en = 1; +static unsigned int y_tnr_txt_mode; +static unsigned int y_tnr_mot_sad_margin = 1; +static unsigned int y_tnr_mot_cortxt_rate = 1; +static unsigned int y_tnr_mot_distxt_ofst = 5; +static unsigned int y_tnr_mot_distxt_rate = 4; +static unsigned int y_tnr_mot_dismot_ofst = 4; +static unsigned int y_tnr_mot_frcsad_lock = 8; +static unsigned int y_tnr_mot2alp_frc_gain = 10; +static unsigned int y_tnr_mot2alp_nrm_gain = 216; +static unsigned int y_tnr_mot2alp_dis_gain = 128; +static unsigned int y_tnr_mot2alp_dis_ofst = 32; +static unsigned int y_tnr_alpha_min = 32; +static unsigned int y_tnr_alpha_max = 63; +static unsigned int y_tnr_deghost_os; +/* c tnr */ +static unsigned int c_tnr_mc_en = 1; +static unsigned int c_tnr_txt_mode; +static unsigned int c_tnr_mot_sad_margin = 1; +static unsigned int c_tnr_mot_cortxt_rate = 1; +static unsigned int c_tnr_mot_distxt_ofst = 5; +static unsigned int c_tnr_mot_distxt_rate = 4; +static unsigned int c_tnr_mot_dismot_ofst = 4; +static unsigned int c_tnr_mot_frcsad_lock = 8; +static unsigned int c_tnr_mot2alp_frc_gain = 10; +static unsigned int c_tnr_mot2alp_nrm_gain = 216; +static unsigned int c_tnr_mot2alp_dis_gain = 128; +static unsigned int c_tnr_mot2alp_dis_ofst = 32; +static unsigned int c_tnr_alpha_min = 32; +static unsigned int c_tnr_alpha_max = 63; +static unsigned int c_tnr_deghost_os; +/* y snr */ +static unsigned int y_snr_err_norm = 1; +static unsigned int y_snr_gau_bld_core = 1; +static int y_snr_gau_bld_ofst = -1; +static unsigned int y_snr_gau_bld_rate = 48; +static unsigned int y_snr_gau_alp0_min; +static unsigned int y_snr_gau_alp0_max = 63; +static unsigned int y_bld_beta2alp_rate = 16; +static unsigned int y_bld_beta_min; +static unsigned int y_bld_beta_max = 63; +/* c snr */ +static unsigned int c_snr_err_norm = 1; +static unsigned int c_snr_gau_bld_core = 1; +static int c_snr_gau_bld_ofst = -1; +static unsigned int c_snr_gau_bld_rate = 48; +static unsigned int c_snr_gau_alp0_min; +static unsigned int c_snr_gau_alp0_max = 63; +static unsigned int c_bld_beta2alp_rate = 16; +static unsigned int c_bld_beta_min; +static unsigned int c_bld_beta_max = 63; + +static DEFINE_SPINLOCK(lock); + +#define ADV_MV_LARGE_16x8 1 +#define ADV_MV_LARGE_8x16 1 +#define ADV_MV_LARGE_16x16 1 + +/* me weight offset should not very small, it used by v1 me module. */ +/* the min real sad for me is 16 by hardware. */ +#define ME_WEIGHT_OFFSET 0x520 +#define I4MB_WEIGHT_OFFSET 0x655 +#define I16MB_WEIGHT_OFFSET 0x560 + +#define ADV_MV_16x16_WEIGHT 0x080 +#define ADV_MV_16_8_WEIGHT 0x0e0 +#define ADV_MV_8x8_WEIGHT 0x240 +#define ADV_MV_4x4x4_WEIGHT 0x3000 + +#define IE_SAD_SHIFT_I16 0x001 +#define IE_SAD_SHIFT_I4 0x001 +#define ME_SAD_SHIFT_INTER 0x001 + +#define STEP_2_SKIP_SAD 0 +#define STEP_1_SKIP_SAD 0 +#define STEP_0_SKIP_SAD 0 +#define STEP_2_SKIP_WEIGHT 0 +#define STEP_1_SKIP_WEIGHT 0 +#define STEP_0_SKIP_WEIGHT 0 + +#define ME_SAD_RANGE_0 0x1 /* 0x0 */ +#define ME_SAD_RANGE_1 0x0 +#define ME_SAD_RANGE_2 0x0 +#define ME_SAD_RANGE_3 0x0 + +/* use 0 for v3, 0x18 for v2 */ +#define ME_MV_PRE_WEIGHT_0 0x18 +/* use 0 for v3, 0x18 for v2 */ +#define ME_MV_PRE_WEIGHT_1 0x18 +#define ME_MV_PRE_WEIGHT_2 0x0 +#define ME_MV_PRE_WEIGHT_3 0x0 + +/* use 0 for v3, 0x18 for v2 */ +#define ME_MV_STEP_WEIGHT_0 0x18 +/* use 0 for v3, 0x18 for v2 */ +#define ME_MV_STEP_WEIGHT_1 0x18 +#define ME_MV_STEP_WEIGHT_2 0x0 +#define ME_MV_STEP_WEIGHT_3 0x0 + +#define ME_SAD_ENOUGH_0_DATA 0x00 +#define ME_SAD_ENOUGH_1_DATA 0x04 +#define ME_SAD_ENOUGH_2_DATA 0x11 +#define ADV_MV_8x8_ENOUGH_DATA 0x20 + +/* V4_COLOR_BLOCK_FIX */ +#define V3_FORCE_SKIP_SAD_0 0x10 +/* 4 Blocks */ +#define V3_FORCE_SKIP_SAD_1 0x60 +/* 16 Blocks + V3_SKIP_WEIGHT_2 */ +#define V3_FORCE_SKIP_SAD_2 0x250 +/* almost disable it -- use t_lac_coeff_2 output to F_ZERO is better */ +#define V3_ME_F_ZERO_SAD (ME_WEIGHT_OFFSET + 0x10) + +#define V3_IE_F_ZERO_SAD_I16 (I16MB_WEIGHT_OFFSET + 0x10) +#define V3_IE_F_ZERO_SAD_I4 (I4MB_WEIGHT_OFFSET + 0x20) + +#define V3_SKIP_WEIGHT_0 0x10 +/* 4 Blocks 8 seperate search sad can be very low */ +#define V3_SKIP_WEIGHT_1 0x8 /* (4 * ME_MV_STEP_WEIGHT_1 + 0x100) */ +#define V3_SKIP_WEIGHT_2 0x3 + +#define V3_LEVEL_1_F_SKIP_MAX_SAD 0x0 +#define V3_LEVEL_1_SKIP_MAX_SAD 0x6 + +#define I4_ipred_weight_most 0x18 +#define I4_ipred_weight_else 0x28 + +#define C_ipred_weight_V 0x04 +#define C_ipred_weight_H 0x08 +#define C_ipred_weight_DC 0x0c + +#define I16_ipred_weight_V 0x04 +#define I16_ipred_weight_H 0x08 +#define I16_ipred_weight_DC 0x0c + +/* 0x00 same as disable */ +#define v3_left_small_max_ie_sad 0x00 +#define v3_left_small_max_me_sad 0x40 + +#define v5_use_small_diff_cnt 0 +#define v5_simple_mb_inter_all_en 1 +#define v5_simple_mb_inter_8x8_en 1 +#define v5_simple_mb_inter_16_8_en 1 +#define v5_simple_mb_inter_16x16_en 1 +#define v5_simple_mb_intra_en 1 +#define v5_simple_mb_C_en 0 +#define v5_simple_mb_Y_en 1 +#define v5_small_diff_Y 0x10 +#define v5_small_diff_C 0x18 +/* shift 8-bits, 2, 1, 0, -1, -2, -3, -4 */ +#define v5_simple_dq_setting 0x43210fed +#define v5_simple_me_weight_setting 0 + +#ifdef H264_ENC_CBR +#define CBR_TABLE_SIZE 0x800 +#define CBR_SHORT_SHIFT 12 /* same as disable */ +#define CBR_LONG_MB_NUM 2 +#define START_TABLE_ID 8 +#define CBR_LONG_THRESH 4 +#endif + +static u32 v3_mv_sad[64] = { + /* For step0 */ + 0x00000004, + 0x00010008, + 0x00020010, + 0x00030018, + 0x00040020, + 0x00050028, + 0x00060038, + 0x00070048, + 0x00080058, + 0x00090068, + 0x000a0080, + 0x000b0098, + 0x000c00b0, + 0x000d00c8, + 0x000e00e8, + 0x000f0110, + /* For step1 */ + 0x00100002, + 0x00110004, + 0x00120008, + 0x0013000c, + 0x00140010, + 0x00150014, + 0x0016001c, + 0x00170024, + 0x0018002c, + 0x00190034, + 0x001a0044, + 0x001b0054, + 0x001c0064, + 0x001d0074, + 0x001e0094, + 0x001f00b4, + /* For step2 */ + 0x00200006, + 0x0021000c, + 0x0022000c, + 0x00230018, + 0x00240018, + 0x00250018, + 0x00260018, + 0x00270030, + 0x00280030, + 0x00290030, + 0x002a0030, + 0x002b0030, + 0x002c0030, + 0x002d0030, + 0x002e0030, + 0x002f0050, + /* For step2 4x4-8x8 */ + 0x00300001, + 0x00310002, + 0x00320002, + 0x00330004, + 0x00340004, + 0x00350004, + 0x00360004, + 0x00370006, + 0x00380006, + 0x00390006, + 0x003a0006, + 0x003b0006, + 0x003c0006, + 0x003d0006, + 0x003e0006, + 0x003f0006 +}; + +static struct BuffInfo_s amvenc_buffspec[] = { + { + .lev_id = 0, + .max_width = 1920, + .max_height = 1088, + .min_buffsize = 0x1400000, + .dct = { + .buf_start = 0, + .buf_size = 0x800000, /* 1920x1088x4 */ + }, + .dec0_y = { + .buf_start = 0x800000, + .buf_size = 0x300000, + }, + .dec1_y = { + .buf_start = 0xb00000, + .buf_size = 0x300000, + }, + .assit = { + .buf_start = 0xe10000, + .buf_size = 0xc0000, + }, + .bitstream = { + .buf_start = 0xf00000, + .buf_size = 0x100000, + }, + .scale_buff = { + .buf_start = 0x1000000, + .buf_size = 0x300000, + }, + .dump_info = { + .buf_start = 0x1300000, + .buf_size = 0xa0000, /* (1920x1088/256)x80 */ + }, + .cbr_info = { + .buf_start = 0x13b0000, + .buf_size = 0x2000, + } + } +}; + +enum ucode_type_e { + UCODE_GX, + UCODE_GXTV, + UCODE_GXL, + UCODE_TXL, + UCODE_MAX +}; + +const char *ucode_name[] = { + "h264_enc_mc_gx", + "h264_enc_mc_gxtv", + "gx_h264_enc", + "h264_enc_mc_txl", +}; + +static void dma_flush(u32 buf_start, u32 buf_size); +static void cache_flush(u32 buf_start , u32 buf_size); + +static const char *select_ucode(u32 ucode_index) +{ + enum ucode_type_e ucode = UCODE_GX; + switch (ucode_index) { + case UCODE_MODE_FULL: + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) + ucode = UCODE_TXL; + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + ucode = UCODE_GXL; + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + ucode = UCODE_GXTV; + else /* if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) */ + ucode = UCODE_GX; + break; + break; + default: + break; + } + return (const char *)ucode_name[ucode]; +} + +static void hcodec_prog_qtbl(struct encode_wq_s *wq) +{ + WRITE_HREG(HCODEC_Q_QUANT_CONTROL, + (0 << 23) | /* quant_table_addr */ + (1 << 22)); /* quant_table_addr_update */ + + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[0]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[1]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[2]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[3]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[4]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[5]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[6]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i4[7]); + + WRITE_HREG(HCODEC_Q_QUANT_CONTROL, + (8 << 23) | /* quant_table_addr */ + (1 << 22)); /* quant_table_addr_update */ + + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[0]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[1]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[2]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[3]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[4]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[5]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[6]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_i16[7]); + + WRITE_HREG(HCODEC_Q_QUANT_CONTROL, + (16 << 23) | /* quant_table_addr */ + (1 << 22)); /* quant_table_addr_update */ + + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[0]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[1]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[2]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[3]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[4]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[5]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[6]); + WRITE_HREG(HCODEC_QUANT_TABLE_DATA, + wq->quant_tbl_me[7]); + return; +} + +static void InitEncodeWeight(void) +{ + me_mv_merge_ctl = + (0x1 << 31) | /* [31] me_merge_mv_en_16 */ + (0x1 << 30) | /* [30] me_merge_small_mv_en_16 */ + (0x1 << 29) | /* [29] me_merge_flex_en_16 */ + (0x1 << 28) | /* [28] me_merge_sad_en_16 */ + (0x1 << 27) | /* [27] me_merge_mv_en_8 */ + (0x1 << 26) | /* [26] me_merge_small_mv_en_8 */ + (0x1 << 25) | /* [25] me_merge_flex_en_8 */ + (0x1 << 24) | /* [24] me_merge_sad_en_8 */ + (0x12 << 18) | + /* [23:18] me_merge_mv_diff_16 - MV diff + <= n pixel can be merged */ + (0x2b << 12) | + /* [17:12] me_merge_mv_diff_8 - MV diff + <= n pixel can be merged */ + (0x80 << 0); + /* [11:0] me_merge_min_sad - SAD + >= 0x180 can be merged with other MV */ + + me_mv_weight_01 = (ME_MV_STEP_WEIGHT_1 << 24) | + (ME_MV_PRE_WEIGHT_1 << 16) | + (ME_MV_STEP_WEIGHT_0 << 8) | + (ME_MV_PRE_WEIGHT_0 << 0); + + me_mv_weight_23 = (ME_MV_STEP_WEIGHT_3 << 24) | + (ME_MV_PRE_WEIGHT_3 << 16) | + (ME_MV_STEP_WEIGHT_2 << 8) | + (ME_MV_PRE_WEIGHT_2 << 0); + + me_sad_range_inc = (ME_SAD_RANGE_3 << 24) | + (ME_SAD_RANGE_2 << 16) | + (ME_SAD_RANGE_1 << 8) | + (ME_SAD_RANGE_0 << 0); + + me_step0_close_mv = (0x100 << 10) | + /* me_step0_big_sad -- two MV sad + diff bigger will use use 1 */ + (2 << 5) | /* me_step0_close_mv_y */ + (2 << 0); /* me_step0_close_mv_x */ + + me_f_skip_sad = (0x00 << 24) | /* force_skip_sad_3 */ + (STEP_2_SKIP_SAD << 16) | /* force_skip_sad_2 */ + (STEP_1_SKIP_SAD << 8) | /* force_skip_sad_1 */ + (STEP_0_SKIP_SAD << 0); /* force_skip_sad_0 */ + + me_f_skip_weight = (0x00 << 24) | /* force_skip_weight_3 */ + /* force_skip_weight_2 */ + (STEP_2_SKIP_WEIGHT << 16) | + /* force_skip_weight_1 */ + (STEP_1_SKIP_WEIGHT << 8) | + /* force_skip_weight_0 */ + (STEP_0_SKIP_WEIGHT << 0); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + me_f_skip_sad = 0; + me_f_skip_weight = 0; + me_mv_weight_01 = 0; + me_mv_weight_23 = 0; + } + + me_sad_enough_01 = (ME_SAD_ENOUGH_1_DATA << 12) | + /* me_sad_enough_1 */ + (ME_SAD_ENOUGH_0_DATA << 0) | + /* me_sad_enough_0 */ + (0 << 12) | /* me_sad_enough_1 */ + (0 << 0); /* me_sad_enough_0 */ + + me_sad_enough_23 = (ADV_MV_8x8_ENOUGH_DATA << 12) | + /* adv_mv_8x8_enough */ + (ME_SAD_ENOUGH_2_DATA << 0) | + /* me_sad_enough_2 */ + (0 << 12) | /* me_sad_enough_3 */ + (0 << 0); /* me_sad_enough_2 */ +} + +/*output stream buffer setting*/ +static void avc_init_output_buffer(struct encode_wq_s *wq) +{ + WRITE_HREG(HCODEC_VLC_VB_MEM_CTL, + ((1 << 31) | (0x3f << 24) | + (0x20 << 16) | (2 << 0))); + WRITE_HREG(HCODEC_VLC_VB_START_PTR, + wq->mem.BitstreamStart); + WRITE_HREG(HCODEC_VLC_VB_WR_PTR, + wq->mem.BitstreamStart); + WRITE_HREG(HCODEC_VLC_VB_SW_RD_PTR, + wq->mem.BitstreamStart); + WRITE_HREG(HCODEC_VLC_VB_END_PTR, + wq->mem.BitstreamEnd); + WRITE_HREG(HCODEC_VLC_VB_CONTROL, 1); + WRITE_HREG(HCODEC_VLC_VB_CONTROL, + ((0 << 14) | (7 << 3) | + (1 << 1) | (0 << 0))); +} + +/*input dct buffer setting*/ +static void avc_init_input_buffer(struct encode_wq_s *wq) +{ + WRITE_HREG(HCODEC_QDCT_MB_START_PTR, + wq->mem.dct_buff_start_addr); + WRITE_HREG(HCODEC_QDCT_MB_END_PTR, + wq->mem.dct_buff_end_addr); + WRITE_HREG(HCODEC_QDCT_MB_WR_PTR, + wq->mem.dct_buff_start_addr); + WRITE_HREG(HCODEC_QDCT_MB_RD_PTR, + wq->mem.dct_buff_start_addr); + WRITE_HREG(HCODEC_QDCT_MB_BUFF, 0); +} + +/*input reference buffer setting*/ +static void avc_init_reference_buffer(s32 canvas) +{ + WRITE_HREG(HCODEC_ANC0_CANVAS_ADDR, canvas); + WRITE_HREG(HCODEC_VLC_HCMD_CONFIG, 0); +} + +static void avc_init_assit_buffer(struct encode_wq_s *wq) +{ + WRITE_HREG(MEM_OFFSET_REG, wq->mem.assit_buffer_offset); +} + +/*deblock buffer setting, same as INI_CANVAS*/ +static void avc_init_dblk_buffer(s32 canvas) +{ + WRITE_HREG(HCODEC_REC_CANVAS_ADDR, canvas); + WRITE_HREG(HCODEC_DBKR_CANVAS_ADDR, canvas); + WRITE_HREG(HCODEC_DBKW_CANVAS_ADDR, canvas); +} + +static void avc_init_encoder(struct encode_wq_s *wq, bool idr) +{ + WRITE_HREG(HCODEC_VLC_TOTAL_BYTES, 0); + WRITE_HREG(HCODEC_VLC_CONFIG, 0x07); + WRITE_HREG(HCODEC_VLC_INT_CONTROL, 0); + + WRITE_HREG(HCODEC_ASSIST_AMR1_INT0, 0x15); + WRITE_HREG(HCODEC_ASSIST_AMR1_INT1, 0x8); + WRITE_HREG(HCODEC_ASSIST_AMR1_INT3, 0x14); + + WRITE_HREG(IDR_PIC_ID, wq->pic.idr_pic_id); + WRITE_HREG(FRAME_NUMBER, + (idr == true) ? 0 : wq->pic.frame_number); + WRITE_HREG(PIC_ORDER_CNT_LSB, + (idr == true) ? 0 : wq->pic.pic_order_cnt_lsb); + + WRITE_HREG(LOG2_MAX_PIC_ORDER_CNT_LSB, + wq->pic.log2_max_pic_order_cnt_lsb); + WRITE_HREG(LOG2_MAX_FRAME_NUM, + wq->pic.log2_max_frame_num); + WRITE_HREG(ANC0_BUFFER_ID, 0); + WRITE_HREG(QPPICTURE, wq->pic.init_qppicture); +} + +static void avc_canvas_init(struct encode_wq_s *wq) +{ + u32 canvas_width, canvas_height; + u32 start_addr = wq->mem.buf_start; + + canvas_width = ((wq->pic.encoder_width + 31) >> 5) << 5; + canvas_height = ((wq->pic.encoder_height + 15) >> 4) << 4; + + canvas_config(ENC_CANVAS_OFFSET, + start_addr + wq->mem.bufspec.dec0_y.buf_start, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(1 + ENC_CANVAS_OFFSET, + start_addr + wq->mem.bufspec.dec0_uv.buf_start, + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + /*here the third plane use the same address as the second plane*/ + canvas_config(2 + ENC_CANVAS_OFFSET, + start_addr + wq->mem.bufspec.dec0_uv.buf_start, + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + + canvas_config(3 + ENC_CANVAS_OFFSET, + start_addr + wq->mem.bufspec.dec1_y.buf_start, + canvas_width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(4 + ENC_CANVAS_OFFSET, + start_addr + wq->mem.bufspec.dec1_uv.buf_start, + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + /*here the third plane use the same address as the second plane*/ + canvas_config(5 + ENC_CANVAS_OFFSET, + start_addr + wq->mem.bufspec.dec1_uv.buf_start, + canvas_width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); +} + +static void avc_buffspec_init(struct encode_wq_s *wq) +{ + u32 canvas_width, canvas_height; + u32 start_addr = wq->mem.buf_start; + u32 mb_w = (wq->pic.encoder_width + 15) >> 4; + u32 mb_h = (wq->pic.encoder_height + 15) >> 4; + u32 mbs = mb_w * mb_h; + + canvas_width = ((wq->pic.encoder_width + 31) >> 5) << 5; + canvas_height = ((wq->pic.encoder_height + 15) >> 4) << 4; + + wq->mem.dct_buff_start_addr = start_addr + + wq->mem.bufspec.dct.buf_start; + wq->mem.dct_buff_end_addr = + wq->mem.dct_buff_start_addr + + wq->mem.bufspec.dct.buf_size - 1; + enc_pr(LOG_INFO, "dct_buff_start_addr is 0x%x, wq:%p.\n", + wq->mem.dct_buff_start_addr, (void *)wq); + + wq->mem.bufspec.dec0_uv.buf_start = + wq->mem.bufspec.dec0_y.buf_start + + canvas_width * canvas_height; + wq->mem.bufspec.dec0_uv.buf_size = canvas_width * canvas_height / 2; + wq->mem.bufspec.dec1_uv.buf_start = + wq->mem.bufspec.dec1_y.buf_start + + canvas_width * canvas_height; + wq->mem.bufspec.dec1_uv.buf_size = canvas_width * canvas_height / 2; + wq->mem.assit_buffer_offset = start_addr + + wq->mem.bufspec.assit.buf_start; + enc_pr(LOG_INFO, "assit_buffer_offset is 0x%x, wq: %p.\n", + wq->mem.assit_buffer_offset, (void *)wq); + /*output stream buffer config*/ + wq->mem.BitstreamStart = start_addr + + wq->mem.bufspec.bitstream.buf_start; + wq->mem.BitstreamEnd = + wq->mem.BitstreamStart + + wq->mem.bufspec.bitstream.buf_size - 1; + enc_pr(LOG_INFO, "BitstreamStart is 0x%x, wq: %p.\n", + wq->mem.BitstreamStart, (void *)wq); + + wq->mem.scaler_buff_start_addr = + wq->mem.buf_start + wq->mem.bufspec.scale_buff.buf_start; + wq->mem.dump_info_ddr_start_addr = + wq->mem.buf_start + wq->mem.bufspec.dump_info.buf_start; +enc_pr(LOG_INFO, "CBR: dump_info_ddr_start_addr:%x.\n", wq->mem.dump_info_ddr_start_addr); +enc_pr(LOG_INFO, "CBR: buf_start :%d.\n", wq->mem.buf_start); +enc_pr(LOG_INFO, "CBR: dump_info.buf_start :%d.\n", wq->mem.bufspec.dump_info.buf_start); + wq->mem.dump_info_ddr_size = + DUMP_INFO_BYTES_PER_MB * mbs; + wq->mem.dump_info_ddr_size = + (wq->mem.dump_info_ddr_size + PAGE_SIZE - 1) + & ~(PAGE_SIZE - 1); + wq->mem.cbr_info_ddr_start_addr = + wq->mem.buf_start + wq->mem.bufspec.cbr_info.buf_start; + wq->mem.cbr_info_ddr_size = + wq->mem.bufspec.cbr_info.buf_size; + + wq->mem.dblk_buf_canvas = + ((ENC_CANVAS_OFFSET + 2) << 16) | + ((ENC_CANVAS_OFFSET + 1) << 8) | + (ENC_CANVAS_OFFSET); + wq->mem.ref_buf_canvas = + ((ENC_CANVAS_OFFSET + 5) << 16) | + ((ENC_CANVAS_OFFSET + 4) << 8) | + (ENC_CANVAS_OFFSET + 3); +} + +static void avc_init_ie_me_parameter(struct encode_wq_s *wq, u32 quant) +{ + ie_cur_ref_sel = 0; + ie_pippeline_block = 12; + /* currently disable half and sub pixel */ + ie_me_mode = + (ie_pippeline_block & IE_PIPPELINE_BLOCK_MASK) << + IE_PIPPELINE_BLOCK_SHIFT; + + WRITE_HREG(IE_ME_MODE, ie_me_mode); + WRITE_HREG(IE_REF_SEL, ie_cur_ref_sel); + WRITE_HREG(IE_ME_MB_TYPE, ie_me_mb_type); +#ifdef MULTI_SLICE_MC + if (fixed_slice_cfg) + WRITE_HREG(FIXED_SLICE_CFG, fixed_slice_cfg); + else if (wq->pic.rows_per_slice != + (wq->pic.encoder_height + 15) >> 4) { + u32 mb_per_slice = (wq->pic.encoder_height + 15) >> 4; + mb_per_slice = mb_per_slice * wq->pic.rows_per_slice; + WRITE_HREG(FIXED_SLICE_CFG, mb_per_slice); + } else + WRITE_HREG(FIXED_SLICE_CFG, 0); +#else + WRITE_HREG(FIXED_SLICE_CFG, 0); +#endif +} + +/* for temp */ +#define HCODEC_MFDIN_REGC_MBLP (HCODEC_MFDIN_REGB_AMPC + 0x1) +#define HCODEC_MFDIN_REG0D (HCODEC_MFDIN_REGB_AMPC + 0x2) +#define HCODEC_MFDIN_REG0E (HCODEC_MFDIN_REGB_AMPC + 0x3) +#define HCODEC_MFDIN_REG0F (HCODEC_MFDIN_REGB_AMPC + 0x4) +#define HCODEC_MFDIN_REG10 (HCODEC_MFDIN_REGB_AMPC + 0x5) +#define HCODEC_MFDIN_REG11 (HCODEC_MFDIN_REGB_AMPC + 0x6) +#define HCODEC_MFDIN_REG12 (HCODEC_MFDIN_REGB_AMPC + 0x7) +#define HCODEC_MFDIN_REG13 (HCODEC_MFDIN_REGB_AMPC + 0x8) +#define HCODEC_MFDIN_REG14 (HCODEC_MFDIN_REGB_AMPC + 0x9) +#define HCODEC_MFDIN_REG15 (HCODEC_MFDIN_REGB_AMPC + 0xa) +#define HCODEC_MFDIN_REG16 (HCODEC_MFDIN_REGB_AMPC + 0xb) + +static void mfdin_basic(u32 input, u8 iformat, + u8 oformat, u32 picsize_x, u32 picsize_y, + u8 r2y_en, u8 nr, u8 ifmt_extra) +{ + u8 dsample_en; /* Downsample Enable */ + u8 interp_en; /* Interpolation Enable */ + u8 y_size; /* 0:16 Pixels for y direction pickup; 1:8 pixels */ + u8 r2y_mode; /* RGB2YUV Mode, range(0~3) */ + /* mfdin_reg3_canv[25:24]; + // bytes per pixel in x direction for index0, 0:half 1:1 2:2 3:3 */ + u8 canv_idx0_bppx; + /* mfdin_reg3_canv[27:26]; + // bytes per pixel in x direction for index1-2, 0:half 1:1 2:2 3:3 */ + u8 canv_idx1_bppx; + /* mfdin_reg3_canv[29:28]; + // bytes per pixel in y direction for index0, 0:half 1:1 2:2 3:3 */ + u8 canv_idx0_bppy; + /* mfdin_reg3_canv[31:30]; + // bytes per pixel in y direction for index1-2, 0:half 1:1 2:2 3:3 */ + u8 canv_idx1_bppy; + u8 ifmt444, ifmt422, ifmt420, linear_bytes4p; + u8 nr_enable; + u8 cfg_y_snr_en; + u8 cfg_y_tnr_en; + u8 cfg_c_snr_en; + u8 cfg_c_tnr_en; + u32 linear_bytesperline; + s32 reg_offset; + bool linear_enable = false; + bool format_err = false; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) { + if ((iformat == 7) && (ifmt_extra > 2)) + format_err = true; + } else if (iformat == 7) + format_err = true; + + if (format_err) { + enc_pr(LOG_ERROR, + "mfdin format err, iformat:%d, ifmt_extra:%d\n", + iformat, ifmt_extra); + return; + } + if (iformat != 7) + ifmt_extra = 0; + + ifmt444 = ((iformat == 1) || (iformat == 5) || (iformat == 8) || + (iformat == 9) || (iformat == 12)) ? 1 : 0; + if (iformat == 7 && ifmt_extra == 1) + ifmt444 = 1; + ifmt422 = ((iformat == 0) || (iformat == 10)) ? 1 : 0; + if (iformat == 7 && ifmt_extra != 1) + ifmt422 = 1; + ifmt420 = ((iformat == 2) || (iformat == 3) || (iformat == 4) || + (iformat == 11)) ? 1 : 0; + dsample_en = ((ifmt444 && (oformat != 2)) || + (ifmt422 && (oformat == 0))) ? 1 : 0; + interp_en = ((ifmt422 && (oformat == 2)) || + (ifmt420 && (oformat != 0))) ? 1 : 0; + y_size = (oformat != 0) ? 1 : 0; + if (iformat == 12) + y_size = 0; + r2y_mode = (r2y_en == 1) ? 1 : 0; /* Fixed to 1 (TODO) */ + canv_idx0_bppx = (iformat == 1) ? 3 : (iformat == 0) ? 2 : 1; + canv_idx1_bppx = (iformat == 4) ? 0 : 1; + canv_idx0_bppy = 1; + canv_idx1_bppy = (iformat == 5) ? 1 : 0; + + if ((iformat == 8) || (iformat == 9) || (iformat == 12)) + linear_bytes4p = 3; + else if (iformat == 10) + linear_bytes4p = 2; + else if (iformat == 11) + linear_bytes4p = 1; + else + linear_bytes4p = 0; + if (iformat == 12) + linear_bytesperline = picsize_x * 4; + else + linear_bytesperline = picsize_x * linear_bytes4p; + + if (iformat < 8) + linear_enable = false; + else + linear_enable = true; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + reg_offset = -8; + /* nr_mode: 0:Disabled 1:SNR Only 2:TNR Only 3:3DNR */ + nr_enable = (nr) ? 1 : 0; + cfg_y_snr_en = ((nr == 1) || (nr == 3)) ? 1 : 0; + cfg_y_tnr_en = ((nr == 2) || (nr == 3)) ? 1 : 0; + cfg_c_snr_en = cfg_y_snr_en; + /* cfg_c_tnr_en = cfg_y_tnr_en; */ + cfg_c_tnr_en = 0; + + /* NR For Y */ + WRITE_HREG((HCODEC_MFDIN_REG0D + reg_offset), + ((cfg_y_snr_en << 0) | + (y_snr_err_norm << 1) | + (y_snr_gau_bld_core << 2) | + (((y_snr_gau_bld_ofst) & 0xff) << 6) | + (y_snr_gau_bld_rate << 14) | + (y_snr_gau_alp0_min << 20) | + (y_snr_gau_alp0_max << 26))); + WRITE_HREG((HCODEC_MFDIN_REG0E + reg_offset), + ((cfg_y_tnr_en << 0) | + (y_tnr_mc_en << 1) | + (y_tnr_txt_mode << 2) | + (y_tnr_mot_sad_margin << 3) | + (y_tnr_alpha_min << 7) | + (y_tnr_alpha_max << 13) | + (y_tnr_deghost_os << 19))); + WRITE_HREG((HCODEC_MFDIN_REG0F + reg_offset), + ((y_tnr_mot_cortxt_rate << 0) | + (y_tnr_mot_distxt_ofst << 8) | + (y_tnr_mot_distxt_rate << 4) | + (y_tnr_mot_dismot_ofst << 16) | + (y_tnr_mot_frcsad_lock << 24))); + WRITE_HREG((HCODEC_MFDIN_REG10 + reg_offset), + ((y_tnr_mot2alp_frc_gain << 0) | + (y_tnr_mot2alp_nrm_gain << 8) | + (y_tnr_mot2alp_dis_gain << 16) | + (y_tnr_mot2alp_dis_ofst << 24))); + WRITE_HREG((HCODEC_MFDIN_REG11 + reg_offset), + ((y_bld_beta2alp_rate << 0) | + (y_bld_beta_min << 8) | + (y_bld_beta_max << 14))); + + /* NR For C */ + WRITE_HREG((HCODEC_MFDIN_REG12 + reg_offset), + ((cfg_y_snr_en << 0) | + (c_snr_err_norm << 1) | + (c_snr_gau_bld_core << 2) | + (((c_snr_gau_bld_ofst) & 0xff) << 6) | + (c_snr_gau_bld_rate << 14) | + (c_snr_gau_alp0_min << 20) | + (c_snr_gau_alp0_max << 26))); + + WRITE_HREG((HCODEC_MFDIN_REG13 + reg_offset), + ((cfg_c_tnr_en << 0) | + (c_tnr_mc_en << 1) | + (c_tnr_txt_mode << 2) | + (c_tnr_mot_sad_margin << 3) | + (c_tnr_alpha_min << 7) | + (c_tnr_alpha_max << 13) | + (c_tnr_deghost_os << 19))); + WRITE_HREG((HCODEC_MFDIN_REG14 + reg_offset), + ((c_tnr_mot_cortxt_rate << 0) | + (c_tnr_mot_distxt_ofst << 8) | + (c_tnr_mot_distxt_rate << 4) | + (c_tnr_mot_dismot_ofst << 16) | + (c_tnr_mot_frcsad_lock << 24))); + WRITE_HREG((HCODEC_MFDIN_REG15 + reg_offset), + ((c_tnr_mot2alp_frc_gain << 0) | + (c_tnr_mot2alp_nrm_gain << 8) | + (c_tnr_mot2alp_dis_gain << 16) | + (c_tnr_mot2alp_dis_ofst << 24))); + + WRITE_HREG((HCODEC_MFDIN_REG16 + reg_offset), + ((c_bld_beta2alp_rate << 0) | + (c_bld_beta_min << 8) | + (c_bld_beta_max << 14))); + + WRITE_HREG((HCODEC_MFDIN_REG1_CTRL + reg_offset), + (iformat << 0) | (oformat << 4) | + (dsample_en << 6) | (y_size << 8) | + (interp_en << 9) | (r2y_en << 12) | + (r2y_mode << 13) | (ifmt_extra << 16) | + (nr_enable << 19)); + WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset), + (picsize_x << 14) | (picsize_y << 0)); + } else { + reg_offset = 0; + WRITE_HREG((HCODEC_MFDIN_REG1_CTRL + reg_offset), + (iformat << 0) | (oformat << 4) | + (dsample_en << 6) | (y_size << 8) | + (interp_en << 9) | (r2y_en << 12) | + (r2y_mode << 13)); + WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset), + (picsize_x << 12) | (picsize_y << 0)); + } + + if (linear_enable == false) { + WRITE_HREG((HCODEC_MFDIN_REG3_CANV + reg_offset), + (input & 0xffffff) | + (canv_idx1_bppy << 30) | + (canv_idx0_bppy << 28) | + (canv_idx1_bppx << 26) | + (canv_idx0_bppx << 24)); + WRITE_HREG((HCODEC_MFDIN_REG4_LNR0 + reg_offset), + (0 << 16) | (0 << 0)); + WRITE_HREG((HCODEC_MFDIN_REG5_LNR1 + reg_offset), 0); + } else { + WRITE_HREG((HCODEC_MFDIN_REG3_CANV + reg_offset), + (canv_idx1_bppy << 30) | + (canv_idx0_bppy << 28) | + (canv_idx1_bppx << 26) | + (canv_idx0_bppx << 24)); + WRITE_HREG((HCODEC_MFDIN_REG4_LNR0 + reg_offset), + (linear_bytes4p << 16) | (linear_bytesperline << 0)); + WRITE_HREG((HCODEC_MFDIN_REG5_LNR1 + reg_offset), input); + } + + if (iformat == 12) + WRITE_HREG((HCODEC_MFDIN_REG9_ENDN + reg_offset), + (2 << 0) | (1 << 3) | (0 << 6) | + (3 << 9) | (6 << 12) | (5 << 15) | + (4 << 18) | (7 << 21)); + else + WRITE_HREG((HCODEC_MFDIN_REG9_ENDN + reg_offset), + (7 << 0) | (6 << 3) | (5 << 6) | + (4 << 9) | (3 << 12) | (2 << 15) | + (1 << 18) | (0 << 21)); +} + +#ifdef CONFIG_AM_GE2D +static int scale_frame(struct encode_wq_s *wq, + struct encode_request_s *request, + struct config_para_ex_s *ge2d_config, + u32 src_addr, bool canvas) +{ + struct ge2d_context_s *context = encode_manager.context; + int src_top, src_left, src_width, src_height; + struct canvas_s cs0, cs1, cs2, cd; + u32 src_canvas, dst_canvas; + u32 src_canvas_w, dst_canvas_w; + u32 src_h = request->src_h; + u32 dst_w = ((wq->pic.encoder_width + 15) >> 4) << 4; + u32 dst_h = ((wq->pic.encoder_height + 15) >> 4) << 4; + int input_format = GE2D_FORMAT_M24_NV21; + src_top = request->crop_top; + src_left = request->crop_left; + src_width = request->src_w - src_left - request->crop_right; + src_height = request->src_h - src_top - request->crop_bottom; + if (canvas) { + if ((request->fmt == FMT_NV21) + || (request->fmt == FMT_NV12)) { + src_canvas = src_addr & 0xffff; + input_format = GE2D_FORMAT_M24_NV21; + } else { + src_canvas = src_addr & 0xffffff; + input_format = GE2D_FORMAT_M24_YUV420; + } + } else { + if ((request->fmt == FMT_NV21) + || (request->fmt == FMT_NV12)) { + src_canvas_w = + ((request->src_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 9, + src_addr, + src_canvas_w, src_h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 10, + src_addr + src_canvas_w * src_h, + src_canvas_w, src_h / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + src_canvas = + ((ENC_CANVAS_OFFSET + 10) << 8) + | (ENC_CANVAS_OFFSET + 9); + input_format = GE2D_FORMAT_M24_NV21; + } else { + src_canvas_w = + ((request->src_w + 63) >> 6) << 6; + canvas_config(ENC_CANVAS_OFFSET + 9, + src_addr, + src_canvas_w, src_h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 10, + src_addr + src_canvas_w * src_h, + src_canvas_w / 2, src_h / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 11, + src_addr + src_canvas_w * src_h * 5 / 4, + src_canvas_w / 2, src_h / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + src_canvas = + ((ENC_CANVAS_OFFSET + 11) << 16) | + ((ENC_CANVAS_OFFSET + 10) << 8) | + (ENC_CANVAS_OFFSET + 9); + input_format = GE2D_FORMAT_M24_YUV420; + } + } + dst_canvas_w = ((dst_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 6, + wq->mem.scaler_buff_start_addr, + dst_canvas_w, dst_h, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 7, + wq->mem.scaler_buff_start_addr + dst_canvas_w * dst_h, + dst_canvas_w, dst_h / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + dst_canvas = ((ENC_CANVAS_OFFSET + 7) << 8) | + (ENC_CANVAS_OFFSET + 6); + ge2d_config->alu_const_color = 0; + ge2d_config->bitmask_en = 0; + ge2d_config->src1_gb_alpha = 0; + ge2d_config->dst_xy_swap = 0; + canvas_read(src_canvas & 0xff, &cs0); + canvas_read((src_canvas >> 8) & 0xff, &cs1); + canvas_read((src_canvas >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + canvas_read(dst_canvas & 0xff, &cd); + ge2d_config->dst_planes[0].addr = cd.addr; + ge2d_config->dst_planes[0].w = cd.width; + ge2d_config->dst_planes[0].h = cd.height; + ge2d_config->src_key.key_enable = 0; + ge2d_config->src_key.key_mask = 0; + ge2d_config->src_key.key_mode = 0; + ge2d_config->src_para.canvas_index = src_canvas; + ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config->src_para.format = input_format | GE2D_LITTLE_ENDIAN; + ge2d_config->src_para.fill_color_en = 0; + ge2d_config->src_para.fill_mode = 0; + ge2d_config->src_para.x_rev = 0; + ge2d_config->src_para.y_rev = 0; + ge2d_config->src_para.color = 0xffffffff; + ge2d_config->src_para.top = 0; + ge2d_config->src_para.left = 0; + ge2d_config->src_para.width = request->src_w; + ge2d_config->src_para.height = request->src_h; + ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config->dst_para.canvas_index = dst_canvas; + ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config->dst_para.format = + GE2D_FORMAT_M24_NV21 | GE2D_LITTLE_ENDIAN; + ge2d_config->dst_para.fill_color_en = 0; + ge2d_config->dst_para.fill_mode = 0; + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + ge2d_config->dst_para.color = 0; + ge2d_config->dst_para.top = 0; + ge2d_config->dst_para.left = 0; + ge2d_config->dst_para.width = dst_w; + ge2d_config->dst_para.height = dst_h; + ge2d_config->dst_para.x_rev = 0; + ge2d_config->dst_para.y_rev = 0; + if (ge2d_context_config_ex(context, ge2d_config) < 0) { + pr_err("++ge2d configing error.\n"); + return -1; + } + stretchblt_noalpha(context, src_left, src_top, src_width, src_height, + 0, 0, wq->pic.encoder_width, wq->pic.encoder_height); + return dst_canvas_w*dst_h * 3 / 2; +} +#endif + +static s32 set_input_format(struct encode_wq_s *wq, + struct encode_request_s *request) +{ + s32 ret = 0; + u8 iformat = MAX_FRAME_FMT, oformat = MAX_FRAME_FMT, r2y_en = 0; + u32 picsize_x, picsize_y, src_addr; + u32 canvas_w = 0; + u32 input = request->src; + u8 ifmt_extra = 0; + + if ((request->fmt == FMT_RGB565) || (request->fmt >= MAX_FRAME_FMT)) + return -1; + + picsize_x = ((wq->pic.encoder_width + 15) >> 4) << 4; + picsize_y = ((wq->pic.encoder_height + 15) >> 4) << 4; + oformat = 0; + if ((request->type == LOCAL_BUFF) + || (request->type == PHYSICAL_BUFF)) { + if ((request->type == LOCAL_BUFF) && + (request->flush_flag & AMVENC_FLUSH_FLAG_INPUT)) + dma_flush(wq->mem.dct_buff_start_addr, + request->framesize); + if (request->type == LOCAL_BUFF) { + input = wq->mem.dct_buff_start_addr; + src_addr = + wq->mem.dct_buff_start_addr; + } else { + src_addr = input; + picsize_y = wq->pic.encoder_height; + } + if (request->scale_enable) { +#ifdef CONFIG_AM_GE2D + struct config_para_ex_s ge2d_config; + memset(&ge2d_config, 0, + sizeof(struct config_para_ex_s)); + scale_frame( + wq, request, + &ge2d_config, + src_addr, + false); + iformat = 2; + r2y_en = 0; + input = ((ENC_CANVAS_OFFSET + 7) << 8) | + (ENC_CANVAS_OFFSET + 6); + ret = 0; + goto MFDIN; +#else + enc_pr(LOG_ERROR, + "Warning: need enable ge2d for scale frame!\n"); + return -1; +#endif + } + if ((request->fmt <= FMT_YUV444_PLANE) || + (request->fmt >= FMT_YUV422_12BIT)) + r2y_en = 0; + else + r2y_en = 1; + + if (request->fmt >= FMT_YUV422_12BIT) { + iformat = 7; + ifmt_extra = request->fmt - FMT_YUV422_12BIT; + if (request->fmt == FMT_YUV422_12BIT) + canvas_w = picsize_x * 24 / 8; + else if (request->fmt == FMT_YUV444_10BIT) + canvas_w = picsize_x * 32 / 8; + else + canvas_w = (picsize_x * 20 + 7) / 8; + canvas_w = ((canvas_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 6, + input, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + input = ENC_CANVAS_OFFSET + 6; + input = input & 0xff; + } else if (request->fmt == FMT_YUV422_SINGLE) + iformat = 10; + else if ((request->fmt == FMT_YUV444_SINGLE) + || (request->fmt == FMT_RGB888)) { + iformat = 1; + if (request->fmt == FMT_RGB888) + r2y_en = 1; + canvas_w = picsize_x * 3; + canvas_w = ((canvas_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 6, + input, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + input = ENC_CANVAS_OFFSET + 6; + } else if ((request->fmt == FMT_NV21) + || (request->fmt == FMT_NV12)) { + canvas_w = ((wq->pic.encoder_width + 31) >> 5) << 5; + iformat = (request->fmt == FMT_NV21) ? 2 : 3; + canvas_config(ENC_CANVAS_OFFSET + 6, + input, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 7, + input + canvas_w * picsize_y, + canvas_w, picsize_y / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + input = ((ENC_CANVAS_OFFSET + 7) << 8) | + (ENC_CANVAS_OFFSET + 6); + } else if (request->fmt == FMT_YUV420) { + iformat = 4; + canvas_w = ((wq->pic.encoder_width + 63) >> 6) << 6; + canvas_config(ENC_CANVAS_OFFSET + 6, + input, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 7, + input + canvas_w * picsize_y, + canvas_w / 2, picsize_y / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 8, + input + canvas_w * picsize_y * 5 / 4, + canvas_w / 2, picsize_y / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + input = ((ENC_CANVAS_OFFSET + 8) << 16) | + ((ENC_CANVAS_OFFSET + 7) << 8) | + (ENC_CANVAS_OFFSET + 6); + } else if ((request->fmt == FMT_YUV444_PLANE) + || (request->fmt == FMT_RGB888_PLANE)) { + if (request->fmt == FMT_RGB888_PLANE) + r2y_en = 1; + iformat = 5; + canvas_w = ((wq->pic.encoder_width + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 6, + input, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 7, + input + canvas_w * picsize_y, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 8, + input + canvas_w * picsize_y * 2, + canvas_w, picsize_y, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + input = ((ENC_CANVAS_OFFSET + 8) << 16) | + ((ENC_CANVAS_OFFSET + 7) << 8) | + (ENC_CANVAS_OFFSET + 6); + } else if (request->fmt == FMT_RGBA8888) { + r2y_en = 1; + iformat = 12; + } + ret = 0; + } else if (request->type == CANVAS_BUFF) { + r2y_en = 0; + if (request->scale_enable) { +#ifdef CONFIG_AM_GE2D + struct config_para_ex_s ge2d_config; + memset(&ge2d_config, 0, + sizeof(struct config_para_ex_s)); + scale_frame( + wq, request, + &ge2d_config, + input, true); + iformat = 2; + r2y_en = 0; + input = ((ENC_CANVAS_OFFSET + 7) << 8) | + (ENC_CANVAS_OFFSET + 6); + ret = 0; + goto MFDIN; +#else + enc_pr(LOG_ERROR, + "Warning: need enable ge2d for scale frame!\n"); + return -1; +#endif + } + if (request->fmt == FMT_YUV422_SINGLE) { + iformat = 0; + input = input & 0xff; + } else if (request->fmt == FMT_YUV444_SINGLE) { + iformat = 1; + input = input & 0xff; + } else if ((request->fmt == FMT_NV21) + || (request->fmt == FMT_NV12)) { + iformat = (request->fmt == FMT_NV21) ? 2 : 3; + input = input & 0xffff; + } else if (request->fmt == FMT_YUV420) { + iformat = 4; + input = input & 0xffffff; + } else if ((request->fmt == FMT_YUV444_PLANE) + || (request->fmt == FMT_RGB888_PLANE)) { + if (request->fmt == FMT_RGB888_PLANE) + r2y_en = 1; + iformat = 5; + input = input & 0xffffff; + } else if ((request->fmt == FMT_YUV422_12BIT) + || (request->fmt == FMT_YUV444_10BIT) + || (request->fmt == FMT_YUV422_10BIT)) { + iformat = 7; + ifmt_extra = request->fmt - FMT_YUV422_12BIT; + input = input & 0xff; + } else + ret = -1; + } + + if (ret == 0) + mfdin_basic(input, iformat, oformat, + picsize_x, picsize_y, r2y_en, + request->nr_mode, ifmt_extra); + return ret; +} + +#ifdef H264_ENC_CBR +static void ConvertTable2Risc(void *table, u32 len) +{ + u32 i, j; + u16 temp; + u16 *tbl = (u16 *)table; + if ((len < 8) || (len % 8) || (!table)) { + enc_pr(LOG_ERROR, "ConvertTable2Risc tbl %p, len %d error\n", + table, len); + return; + } + for (i = 0; i < len / 8; i++) { + j = i << 2; + temp = tbl[j]; + tbl[j] = tbl[j + 3]; + tbl[j + 3] = temp; + + temp = tbl[j + 1]; + tbl[j + 1] = tbl[j + 2]; + tbl[j + 2] = temp; + } + +} +#endif + +static void avc_prot_init(struct encode_wq_s *wq, + struct encode_request_s *request, u32 quant, bool IDR) +{ + u32 data32; + u32 pic_width, pic_height; + u32 pic_mb_nr; + u32 pic_mbx, pic_mby; + u32 i_pic_qp, p_pic_qp; + u32 i_pic_qp_c, p_pic_qp_c; + u32 pic_width_in_mb; + u32 slice_qp; + pic_width = wq->pic.encoder_width; + pic_height = wq->pic.encoder_height; + pic_mb_nr = 0; + pic_mbx = 0; + pic_mby = 0; + i_pic_qp = quant; + p_pic_qp = quant; + + pic_width_in_mb = (pic_width + 15) / 16; + WRITE_HREG(HCODEC_HDEC_MC_OMEM_AUTO, + (1 << 31) | /* use_omem_mb_xy */ + ((pic_width_in_mb - 1) << 16)); /* omem_max_mb_x */ + + WRITE_HREG(HCODEC_VLC_ADV_CONFIG, + /* early_mix_mc_hcmd -- will enable in P Picture */ + (0 << 10) | + (1 << 9) | /* update_top_left_mix */ + (1 << 8) | /* p_top_left_mix */ + /* mv_cal_mixed_type -- will enable in P Picture */ + (0 << 7) | + /* mc_hcmd_mixed_type -- will enable in P Picture */ + (0 << 6) | + (1 << 5) | /* use_seperate_int_control */ + (1 << 4) | /* hcmd_intra_use_q_info */ + (1 << 3) | /* hcmd_left_use_prev_info */ + (1 << 2) | /* hcmd_use_q_info */ + (1 << 1) | /* use_q_delta_quant */ + /* detect_I16_from_I4 use qdct detected mb_type */ + (0 << 0)); + + WRITE_HREG(HCODEC_QDCT_ADV_CONFIG, + (1 << 29) | /* mb_info_latch_no_I16_pred_mode */ + (1 << 28) | /* ie_dma_mbxy_use_i_pred */ + (1 << 27) | /* ie_dma_read_write_use_ip_idx */ + (1 << 26) | /* ie_start_use_top_dma_count */ + (1 << 25) | /* i_pred_top_dma_rd_mbbot */ + (1 << 24) | /* i_pred_top_dma_wr_disable */ + /* i_pred_mix -- will enable in P Picture */ + (0 << 23) | + (1 << 22) | /* me_ab_rd_when_intra_in_p */ + (1 << 21) | /* force_mb_skip_run_when_intra */ + /* mc_out_mixed_type -- will enable in P Picture */ + (0 << 20) | + (1 << 19) | /* ie_start_when_quant_not_full */ + (1 << 18) | /* mb_info_state_mix */ + /* mb_type_use_mix_result -- will enable in P Picture */ + (0 << 17) | + /* me_cb_ie_read_enable -- will enable in P Picture */ + (0 << 16) | + /* ie_cur_data_from_me -- will enable in P Picture */ + (0 << 15) | + (1 << 14) | /* rem_per_use_table */ + (0 << 13) | /* q_latch_int_enable */ + (1 << 12) | /* q_use_table */ + (0 << 11) | /* q_start_wait */ + (1 << 10) | /* LUMA_16_LEFT_use_cur */ + (1 << 9) | /* DC_16_LEFT_SUM_use_cur */ + (1 << 8) | /* c_ref_ie_sel_cur */ + (0 << 7) | /* c_ipred_perfect_mode */ + (1 << 6) | /* ref_ie_ul_sel */ + (1 << 5) | /* mb_type_use_ie_result */ + (1 << 4) | /* detect_I16_from_I4 */ + (1 << 3) | /* ie_not_wait_ref_busy */ + (1 << 2) | /* ie_I16_enable */ + (3 << 0)); /* ie_done_sel // fastest when waiting */ + + if (request != NULL) { + WRITE_HREG(HCODEC_IE_WEIGHT, + (request->i16_weight << 16) | + (request->i4_weight << 0)); + WRITE_HREG(HCODEC_ME_WEIGHT, + (request->me_weight << 0)); + WRITE_HREG(HCODEC_SAD_CONTROL_0, + /* ie_sad_offset_I16 */ + (request->i16_weight << 16) | + /* ie_sad_offset_I4 */ + (request->i4_weight << 0)); + WRITE_HREG(HCODEC_SAD_CONTROL_1, + /* ie_sad_shift_I16 */ + (IE_SAD_SHIFT_I16 << 24) | + /* ie_sad_shift_I4 */ + (IE_SAD_SHIFT_I4 << 20) | + /* me_sad_shift_INTER */ + (ME_SAD_SHIFT_INTER << 16) | + /* me_sad_offset_INTER */ + (request->me_weight << 0)); + wq->me_weight = request->me_weight; + wq->i4_weight = request->i4_weight; + wq->i16_weight = request->i16_weight; + } else { + WRITE_HREG(HCODEC_IE_WEIGHT, + (I16MB_WEIGHT_OFFSET << 16) | + (I4MB_WEIGHT_OFFSET << 0)); + WRITE_HREG(HCODEC_ME_WEIGHT, + (ME_WEIGHT_OFFSET << 0)); + WRITE_HREG(HCODEC_SAD_CONTROL_0, + /* ie_sad_offset_I16 */ + (I16MB_WEIGHT_OFFSET << 16) | + /* ie_sad_offset_I4 */ + (I4MB_WEIGHT_OFFSET << 0)); + WRITE_HREG(HCODEC_SAD_CONTROL_1, + /* ie_sad_shift_I16 */ + (IE_SAD_SHIFT_I16 << 24) | + /* ie_sad_shift_I4 */ + (IE_SAD_SHIFT_I4 << 20) | + /* me_sad_shift_INTER */ + (ME_SAD_SHIFT_INTER << 16) | + /* me_sad_offset_INTER */ + (ME_WEIGHT_OFFSET << 0)); + } + + WRITE_HREG(HCODEC_ADV_MV_CTL0, + (ADV_MV_LARGE_16x8 << 31) | + (ADV_MV_LARGE_8x16 << 30) | + (ADV_MV_8x8_WEIGHT << 16) | /* adv_mv_8x8_weight */ + /* adv_mv_4x4x4_weight should be set bigger */ + (ADV_MV_4x4x4_WEIGHT << 0)); + WRITE_HREG(HCODEC_ADV_MV_CTL1, + /* adv_mv_16x16_weight */ + (ADV_MV_16x16_WEIGHT << 16) | + (ADV_MV_LARGE_16x16 << 15) | + (ADV_MV_16_8_WEIGHT << 0)); /* adv_mv_16_8_weight */ + + hcodec_prog_qtbl(wq); + if (IDR) { + i_pic_qp = + wq->quant_tbl_i4[0] & 0xff; + i_pic_qp += + wq->quant_tbl_i16[0] & 0xff; + i_pic_qp /= 2; + p_pic_qp = i_pic_qp; + } else { + i_pic_qp = + wq->quant_tbl_i4[0] & 0xff; + i_pic_qp += + wq->quant_tbl_i16[0] & 0xff; + p_pic_qp = wq->quant_tbl_me[0] & 0xff; + slice_qp = (i_pic_qp + p_pic_qp) / 3; + i_pic_qp = slice_qp; + p_pic_qp = i_pic_qp; + } +#ifdef H264_ENC_CBR + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + data32 = READ_HREG(HCODEC_SAD_CONTROL_1); + data32 = data32 & 0xffff; /* remove sad shift */ + WRITE_HREG(HCODEC_SAD_CONTROL_1, data32); + WRITE_HREG(H264_ENC_CBR_TABLE_ADDR, + wq->mem.cbr_info_ddr_start_addr); + WRITE_HREG(H264_ENC_CBR_MB_SIZE_ADDR, + wq->mem.cbr_info_ddr_start_addr + + CBR_TABLE_SIZE); + WRITE_HREG(H264_ENC_CBR_CTL, + (wq->cbr_info.start_tbl_id << 28) | + (wq->cbr_info.short_shift << 24) | + (wq->cbr_info.long_mb_num << 16) | + (wq->cbr_info.long_th << 0)); + WRITE_HREG(H264_ENC_CBR_REGION_SIZE, + (wq->cbr_info.block_w << 16) | + (wq->cbr_info.block_h << 0)); + } +#endif + + WRITE_HREG(HCODEC_QDCT_VLC_QUANT_CTL_0, + (0 << 19) | /* vlc_delta_quant_1 */ + (i_pic_qp << 13) | /* vlc_quant_1 */ + (0 << 6) | /* vlc_delta_quant_0 */ + (i_pic_qp << 0)); /* vlc_quant_0 */ + WRITE_HREG(HCODEC_QDCT_VLC_QUANT_CTL_1, + (14 << 6) | /* vlc_max_delta_q_neg */ + (13 << 0)); /* vlc_max_delta_q_pos */ + WRITE_HREG(HCODEC_VLC_PIC_SIZE, + pic_width | (pic_height << 16)); + WRITE_HREG(HCODEC_VLC_PIC_POSITION, + (pic_mb_nr << 16) | + (pic_mby << 8) | + (pic_mbx << 0)); + + /* synopsys parallel_case full_case */ + switch (i_pic_qp) { + case 0: + i_pic_qp_c = 0; + break; + case 1: + i_pic_qp_c = 1; + break; + case 2: + i_pic_qp_c = 2; + break; + case 3: + i_pic_qp_c = 3; + break; + case 4: + i_pic_qp_c = 4; + break; + case 5: + i_pic_qp_c = 5; + break; + case 6: + i_pic_qp_c = 6; + break; + case 7: + i_pic_qp_c = 7; + break; + case 8: + i_pic_qp_c = 8; + break; + case 9: + i_pic_qp_c = 9; + break; + case 10: + i_pic_qp_c = 10; + break; + case 11: + i_pic_qp_c = 11; + break; + case 12: + i_pic_qp_c = 12; + break; + case 13: + i_pic_qp_c = 13; + break; + case 14: + i_pic_qp_c = 14; + break; + case 15: + i_pic_qp_c = 15; + break; + case 16: + i_pic_qp_c = 16; + break; + case 17: + i_pic_qp_c = 17; + break; + case 18: + i_pic_qp_c = 18; + break; + case 19: + i_pic_qp_c = 19; + break; + case 20: + i_pic_qp_c = 20; + break; + case 21: + i_pic_qp_c = 21; + break; + case 22: + i_pic_qp_c = 22; + break; + case 23: + i_pic_qp_c = 23; + break; + case 24: + i_pic_qp_c = 24; + break; + case 25: + i_pic_qp_c = 25; + break; + case 26: + i_pic_qp_c = 26; + break; + case 27: + i_pic_qp_c = 27; + break; + case 28: + i_pic_qp_c = 28; + break; + case 29: + i_pic_qp_c = 29; + break; + case 30: + i_pic_qp_c = 29; + break; + case 31: + i_pic_qp_c = 30; + break; + case 32: + i_pic_qp_c = 31; + break; + case 33: + i_pic_qp_c = 32; + break; + case 34: + i_pic_qp_c = 32; + break; + case 35: + i_pic_qp_c = 33; + break; + case 36: + i_pic_qp_c = 34; + break; + case 37: + i_pic_qp_c = 34; + break; + case 38: + i_pic_qp_c = 35; + break; + case 39: + i_pic_qp_c = 35; + break; + case 40: + i_pic_qp_c = 36; + break; + case 41: + i_pic_qp_c = 36; + break; + case 42: + i_pic_qp_c = 37; + break; + case 43: + i_pic_qp_c = 37; + break; + case 44: + i_pic_qp_c = 37; + break; + case 45: + i_pic_qp_c = 38; + break; + case 46: + i_pic_qp_c = 38; + break; + case 47: + i_pic_qp_c = 38; + break; + case 48: + i_pic_qp_c = 39; + break; + case 49: + i_pic_qp_c = 39; + break; + case 50: + i_pic_qp_c = 39; + break; + default: + i_pic_qp_c = 39; + break; + } + + /* synopsys parallel_case full_case */ + switch (p_pic_qp) { + case 0: + p_pic_qp_c = 0; + break; + case 1: + p_pic_qp_c = 1; + break; + case 2: + p_pic_qp_c = 2; + break; + case 3: + p_pic_qp_c = 3; + break; + case 4: + p_pic_qp_c = 4; + break; + case 5: + p_pic_qp_c = 5; + break; + case 6: + p_pic_qp_c = 6; + break; + case 7: + p_pic_qp_c = 7; + break; + case 8: + p_pic_qp_c = 8; + break; + case 9: + p_pic_qp_c = 9; + break; + case 10: + p_pic_qp_c = 10; + break; + case 11: + p_pic_qp_c = 11; + break; + case 12: + p_pic_qp_c = 12; + break; + case 13: + p_pic_qp_c = 13; + break; + case 14: + p_pic_qp_c = 14; + break; + case 15: + p_pic_qp_c = 15; + break; + case 16: + p_pic_qp_c = 16; + break; + case 17: + p_pic_qp_c = 17; + break; + case 18: + p_pic_qp_c = 18; + break; + case 19: + p_pic_qp_c = 19; + break; + case 20: + p_pic_qp_c = 20; + break; + case 21: + p_pic_qp_c = 21; + break; + case 22: + p_pic_qp_c = 22; + break; + case 23: + p_pic_qp_c = 23; + break; + case 24: + p_pic_qp_c = 24; + break; + case 25: + p_pic_qp_c = 25; + break; + case 26: + p_pic_qp_c = 26; + break; + case 27: + p_pic_qp_c = 27; + break; + case 28: + p_pic_qp_c = 28; + break; + case 29: + p_pic_qp_c = 29; + break; + case 30: + p_pic_qp_c = 29; + break; + case 31: + p_pic_qp_c = 30; + break; + case 32: + p_pic_qp_c = 31; + break; + case 33: + p_pic_qp_c = 32; + break; + case 34: + p_pic_qp_c = 32; + break; + case 35: + p_pic_qp_c = 33; + break; + case 36: + p_pic_qp_c = 34; + break; + case 37: + p_pic_qp_c = 34; + break; + case 38: + p_pic_qp_c = 35; + break; + case 39: + p_pic_qp_c = 35; + break; + case 40: + p_pic_qp_c = 36; + break; + case 41: + p_pic_qp_c = 36; + break; + case 42: + p_pic_qp_c = 37; + break; + case 43: + p_pic_qp_c = 37; + break; + case 44: + p_pic_qp_c = 37; + break; + case 45: + p_pic_qp_c = 38; + break; + case 46: + p_pic_qp_c = 38; + break; + case 47: + p_pic_qp_c = 38; + break; + case 48: + p_pic_qp_c = 39; + break; + case 49: + p_pic_qp_c = 39; + break; + case 50: + p_pic_qp_c = 39; + break; + default: + p_pic_qp_c = 39; + break; + } + WRITE_HREG(HCODEC_QDCT_Q_QUANT_I, + (i_pic_qp_c << 22) | + (i_pic_qp << 16) | + ((i_pic_qp_c % 6) << 12) | + ((i_pic_qp_c / 6) << 8) | + ((i_pic_qp % 6) << 4) | + ((i_pic_qp / 6) << 0)); + + WRITE_HREG(HCODEC_QDCT_Q_QUANT_P, + (p_pic_qp_c << 22) | + (p_pic_qp << 16) | + ((p_pic_qp_c % 6) << 12) | + ((p_pic_qp_c / 6) << 8) | + ((p_pic_qp % 6) << 4) | + ((p_pic_qp / 6) << 0)); + +#ifdef ENABLE_IGNORE_FUNCTION + WRITE_HREG(HCODEC_IGNORE_CONFIG, + (1 << 31) | /* ignore_lac_coeff_en */ + (1 << 26) | /* ignore_lac_coeff_else (<1) */ + (1 << 21) | /* ignore_lac_coeff_2 (<1) */ + (2 << 16) | /* ignore_lac_coeff_1 (<2) */ + (1 << 15) | /* ignore_cac_coeff_en */ + (1 << 10) | /* ignore_cac_coeff_else (<1) */ + (1 << 5) | /* ignore_cac_coeff_2 (<1) */ + (3 << 0)); /* ignore_cac_coeff_1 (<2) */ + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + WRITE_HREG(HCODEC_IGNORE_CONFIG_2, + (1 << 31) | /* ignore_t_lac_coeff_en */ + (1 << 26) | /* ignore_t_lac_coeff_else (<1) */ + (2 << 21) | /* ignore_t_lac_coeff_2 (<2) */ + (6 << 16) | /* ignore_t_lac_coeff_1 (<6) */ + (1<<15) | /* ignore_cdc_coeff_en */ + (0<<14) | /* ignore_t_lac_coeff_else_le_3 */ + (1<<13) | /* ignore_t_lac_coeff_else_le_4 */ + (1<<12) | /* ignore_cdc_only_when_empty_cac_inter */ + (1<<11) | /* ignore_cdc_only_when_one_empty_inter */ + /* ignore_cdc_range_max_inter 0-0, 1-1, 2-2, 3-3 */ + (2<<9) | + /* ignore_cdc_abs_max_inter 0-1, 1-2, 2-3, 3-4 */ + (0<<7) | + /* ignore_cdc_only_when_empty_cac_intra */ + (1<<5) | + /* ignore_cdc_only_when_one_empty_intra */ + (1<<4) | + /* ignore_cdc_range_max_intra 0-0, 1-1, 2-2, 3-3 */ + (1<<2) | + /* ignore_cdc_abs_max_intra 0-1, 1-2, 2-3, 3-4 */ + (0<<0)); + else + WRITE_HREG(HCODEC_IGNORE_CONFIG_2, + (1 << 31) | /* ignore_t_lac_coeff_en */ + (1 << 26) | /* ignore_t_lac_coeff_else (<1) */ + (1 << 21) | /* ignore_t_lac_coeff_2 (<1) */ + (5 << 16) | /* ignore_t_lac_coeff_1 (<5) */ + (0 << 0)); +#else + WRITE_HREG(HCODEC_IGNORE_CONFIG, 0); + WRITE_HREG(HCODEC_IGNORE_CONFIG_2, 0); +#endif + + WRITE_HREG(HCODEC_QDCT_MB_CONTROL, + (1 << 9) | /* mb_info_soft_reset */ + (1 << 0)); /* mb read buffer soft reset */ + + WRITE_HREG(HCODEC_QDCT_MB_CONTROL, + (1 << 28) | /* ignore_t_p8x8 */ + (0 << 27) | /* zero_mc_out_null_non_skipped_mb */ + (0 << 26) | /* no_mc_out_null_non_skipped_mb */ + (0 << 25) | /* mc_out_even_skipped_mb */ + (0 << 24) | /* mc_out_wait_cbp_ready */ + (0 << 23) | /* mc_out_wait_mb_type_ready */ + (1 << 29) | /* ie_start_int_enable */ + (1 << 19) | /* i_pred_enable */ + (1 << 20) | /* ie_sub_enable */ + (1 << 18) | /* iq_enable */ + (1 << 17) | /* idct_enable */ + (1 << 14) | /* mb_pause_enable */ + (1 << 13) | /* q_enable */ + (1 << 12) | /* dct_enable */ + (1 << 10) | /* mb_info_en */ + (0 << 3) | /* endian */ + (0 << 1) | /* mb_read_en */ + (0 << 0)); /* soft reset */ + + WRITE_HREG(HCODEC_SAD_CONTROL, + (0 << 3) | /* ie_result_buff_enable */ + (1 << 2) | /* ie_result_buff_soft_reset */ + (0 << 1) | /* sad_enable */ + (1 << 0)); /* sad soft reset */ + WRITE_HREG(HCODEC_IE_RESULT_BUFFER, 0); + + WRITE_HREG(HCODEC_SAD_CONTROL, + (1 << 3) | /* ie_result_buff_enable */ + (0 << 2) | /* ie_result_buff_soft_reset */ + (1 << 1) | /* sad_enable */ + (0 << 0)); /* sad soft reset */ + + WRITE_HREG(HCODEC_IE_CONTROL, + (1 << 30) | /* active_ul_block */ + (0 << 1) | /* ie_enable */ + (1 << 0)); /* ie soft reset */ + + WRITE_HREG(HCODEC_IE_CONTROL, + (1 << 30) | /* active_ul_block */ + (0 << 1) | /* ie_enable */ + (0 << 0)); /* ie soft reset */ + + WRITE_HREG(HCODEC_ME_SKIP_LINE, + (8 << 24) | /* step_3_skip_line */ + (8 << 18) | /* step_2_skip_line */ + (2 << 12) | /* step_1_skip_line */ + (0 << 6) | /* step_0_skip_line */ + (0 << 0)); + + WRITE_HREG(HCODEC_ME_MV_MERGE_CTL, me_mv_merge_ctl); + WRITE_HREG(HCODEC_ME_STEP0_CLOSE_MV, me_step0_close_mv); + WRITE_HREG(HCODEC_ME_SAD_ENOUGH_01, me_sad_enough_01); + WRITE_HREG(HCODEC_ME_SAD_ENOUGH_23, me_sad_enough_23); + WRITE_HREG(HCODEC_ME_F_SKIP_SAD, me_f_skip_sad); + WRITE_HREG(HCODEC_ME_F_SKIP_WEIGHT, me_f_skip_weight); + WRITE_HREG(HCODEC_ME_MV_WEIGHT_01, me_mv_weight_01); + WRITE_HREG(HCODEC_ME_MV_WEIGHT_23, me_mv_weight_23); + WRITE_HREG(HCODEC_ME_SAD_RANGE_INC, me_sad_range_inc); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) { + WRITE_HREG(HCODEC_V5_SIMPLE_MB_CTL, 0); + WRITE_HREG(HCODEC_V5_SIMPLE_MB_CTL, + (v5_use_small_diff_cnt << 7) | + (v5_simple_mb_inter_all_en << 6) | + (v5_simple_mb_inter_8x8_en << 5) | + (v5_simple_mb_inter_16_8_en << 4) | + (v5_simple_mb_inter_16x16_en << 3) | + (v5_simple_mb_intra_en << 2) | + (v5_simple_mb_C_en << 1) | + (v5_simple_mb_Y_en << 0)); + WRITE_HREG(HCODEC_V5_MB_DIFF_SUM, 0); + WRITE_HREG(HCODEC_V5_SMALL_DIFF_CNT, + (v5_small_diff_C<<16) | + (v5_small_diff_Y<<0)); + WRITE_HREG(HCODEC_V5_SIMPLE_MB_DQUANT, + v5_simple_dq_setting); + WRITE_HREG(HCODEC_V5_SIMPLE_MB_ME_WEIGHT, + v5_simple_me_weight_setting); + /* txlx can remove it */ + WRITE_HREG(HCODEC_QDCT_CONFIG, 1 << 0); + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + WRITE_HREG(HCODEC_V4_FORCE_SKIP_CFG, + (i_pic_qp << 26) | /* v4_force_q_r_intra */ + (i_pic_qp << 20) | /* v4_force_q_r_inter */ + (0 << 19) | /* v4_force_q_y_enable */ + (5 << 16) | /* v4_force_qr_y */ + (6 << 12) | /* v4_force_qp_y */ + (0 << 0)); /* v4_force_skip_sad */ + + /* V3 Force skip */ + WRITE_HREG(HCODEC_V3_SKIP_CONTROL, + (1 << 31) | /* v3_skip_enable */ + (0 << 30) | /* v3_step_1_weight_enable */ + (1 << 28) | /* v3_mv_sad_weight_enable */ + (1 << 27) | /* v3_ipred_type_enable */ + (V3_FORCE_SKIP_SAD_1 << 12) | + (V3_FORCE_SKIP_SAD_0 << 0)); + WRITE_HREG(HCODEC_V3_SKIP_WEIGHT, + (V3_SKIP_WEIGHT_1 << 16) | + (V3_SKIP_WEIGHT_0 << 0)); + WRITE_HREG(HCODEC_V3_L1_SKIP_MAX_SAD, + (V3_LEVEL_1_F_SKIP_MAX_SAD << 16) | + (V3_LEVEL_1_SKIP_MAX_SAD << 0)); + WRITE_HREG(HCODEC_V3_L2_SKIP_WEIGHT, + (V3_FORCE_SKIP_SAD_2 << 16) | + (V3_SKIP_WEIGHT_2 << 0)); + if (request != NULL) { + unsigned int off1, off2; + off1 = V3_IE_F_ZERO_SAD_I4 - I4MB_WEIGHT_OFFSET; + off2 = V3_IE_F_ZERO_SAD_I16 + - I16MB_WEIGHT_OFFSET; + WRITE_HREG(HCODEC_V3_F_ZERO_CTL_0, + ((request->i16_weight + off2) << 16) | + ((request->i4_weight + off1) << 0)); + off1 = V3_ME_F_ZERO_SAD - ME_WEIGHT_OFFSET; + WRITE_HREG(HCODEC_V3_F_ZERO_CTL_1, + (0 << 25) | + /* v3_no_ver_when_top_zero_en */ + (0 << 24) | + /* v3_no_hor_when_left_zero_en */ + (3 << 16) | /* type_hor break */ + ((request->me_weight + off1) << 0)); + } else { + WRITE_HREG(HCODEC_V3_F_ZERO_CTL_0, + (V3_IE_F_ZERO_SAD_I16 << 16) | + (V3_IE_F_ZERO_SAD_I4 << 0)); + WRITE_HREG(HCODEC_V3_F_ZERO_CTL_1, + (0 << 25) | + /* v3_no_ver_when_top_zero_en */ + (0 << 24) | + /* v3_no_hor_when_left_zero_en */ + (3 << 16) | /* type_hor break */ + (V3_ME_F_ZERO_SAD << 0)); + } + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + /* V3 Force skip */ + WRITE_HREG(HCODEC_V3_SKIP_CONTROL, + (1 << 31) | /* v3_skip_enable */ + (0 << 30) | /* v3_step_1_weight_enable */ + (1 << 28) | /* v3_mv_sad_weight_enable */ + (1 << 27) | /* v3_ipred_type_enable */ + (0 << 12) | /* V3_FORCE_SKIP_SAD_1 */ + (0 << 0)); /* V3_FORCE_SKIP_SAD_0 */ + WRITE_HREG(HCODEC_V3_SKIP_WEIGHT, + (V3_SKIP_WEIGHT_1 << 16) | + (V3_SKIP_WEIGHT_0 << 0)); + WRITE_HREG(HCODEC_V3_L1_SKIP_MAX_SAD, + (V3_LEVEL_1_F_SKIP_MAX_SAD << 16) | + (V3_LEVEL_1_SKIP_MAX_SAD << 0)); + WRITE_HREG(HCODEC_V3_L2_SKIP_WEIGHT, + (0 << 16) | /* V3_FORCE_SKIP_SAD_2 */ + (V3_SKIP_WEIGHT_2 << 0)); + WRITE_HREG(HCODEC_V3_F_ZERO_CTL_0, + (0 << 16) | /* V3_IE_F_ZERO_SAD_I16 */ + (0 << 0)); /* V3_IE_F_ZERO_SAD_I4 */ + WRITE_HREG(HCODEC_V3_F_ZERO_CTL_1, + (0 << 25) | /* v3_no_ver_when_top_zero_en */ + (0 << 24) | /* v3_no_hor_when_left_zero_en */ + (3 << 16) | /* type_hor break */ + (0 << 0)); /* V3_ME_F_ZERO_SAD */ + } + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + int i; + /* MV SAD Table */ + for (i = 0; i < 64; i++) + WRITE_HREG(HCODEC_V3_MV_SAD_TABLE, + v3_mv_sad[i]); + + /* IE PRED SAD Table*/ + WRITE_HREG(HCODEC_V3_IPRED_TYPE_WEIGHT_0, + (C_ipred_weight_H << 24) | + (C_ipred_weight_V << 16) | + (I4_ipred_weight_else << 8) | + (I4_ipred_weight_most << 0)); + WRITE_HREG(HCODEC_V3_IPRED_TYPE_WEIGHT_1, + (I16_ipred_weight_DC << 24) | + (I16_ipred_weight_H << 16) | + (I16_ipred_weight_V << 8) | + (C_ipred_weight_DC << 0)); + WRITE_HREG(HCODEC_V3_LEFT_SMALL_MAX_SAD, + (v3_left_small_max_me_sad << 16) | + (v3_left_small_max_ie_sad << 0)); + } + WRITE_HREG(HCODEC_IE_DATA_FEED_BUFF_INFO, 0); + + WRITE_HREG(HCODEC_CURR_CANVAS_CTRL, 0); + data32 = READ_HREG(HCODEC_VLC_CONFIG); + data32 = data32 | (1 << 0); /* set pop_coeff_even_all_zero */ + WRITE_HREG(HCODEC_VLC_CONFIG, data32); + + WRITE_HREG(INFO_DUMP_START_ADDR, + wq->mem.dump_info_ddr_start_addr); + + /* clear mailbox interrupt */ + WRITE_HREG(HCODEC_IRQ_MBOX_CLR, 1); + + /* enable mailbox interrupt */ + WRITE_HREG(HCODEC_IRQ_MBOX_MASK, 1); +} + +void amvenc_reset(void) +{ + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + WRITE_VREG(DOS_SW_RESET1, + (1 << 2) | (1 << 6) | + (1 << 7) | (1 << 8) | + (1 << 14) | (1 << 16) | + (1 << 17)); + WRITE_VREG(DOS_SW_RESET1, 0); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); +} + +void amvenc_start(void) +{ + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + WRITE_VREG(DOS_SW_RESET1, + (1 << 12) | (1 << 11)); + WRITE_VREG(DOS_SW_RESET1, 0); + + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + + WRITE_HREG(HCODEC_MPSR, 0x0001); +} + +void amvenc_stop(void) +{ + ulong timeout = jiffies + HZ; + + WRITE_HREG(HCODEC_MPSR, 0); + WRITE_HREG(HCODEC_CPSR, 0); + while (READ_HREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + + WRITE_VREG(DOS_SW_RESET1, + (1 << 12) | (1 << 11) | + (1 << 2) | (1 << 6) | + (1 << 7) | (1 << 8) | + (1 << 14) | (1 << 16) | + (1 << 17)); + + WRITE_VREG(DOS_SW_RESET1, 0); + + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); + READ_VREG(DOS_SW_RESET1); +} + +static void __iomem *mc_addr; +static u32 mc_addr_map; +#define MC_SIZE (4096 * 8) +s32 amvenc_loadmc(const char *p, struct encode_wq_s *wq) +{ + ulong timeout; + s32 ret = 0; + + /* use static mempry*/ + if (mc_addr == NULL) { + mc_addr = kmalloc(MC_SIZE, GFP_KERNEL); + if (!mc_addr) { + enc_pr(LOG_ERROR, "avc loadmc iomap mc addr error.\n"); + return -ENOMEM; + } + } + + enc_pr(LOG_ALL, "avc encode ucode name is %s\n", p); + ret = get_decoder_firmware_data(VFORMAT_H264_ENC, p, + (u8 *)mc_addr, MC_SIZE); + if (ret < 0) { + enc_pr(LOG_ERROR, + "avc microcode fail ret=%d, name: %s, wq:%p.\n", + ret, p, (void *)wq); + } + + mc_addr_map = dma_map_single( + &encode_manager.this_pdev->dev, + mc_addr, MC_SIZE, DMA_TO_DEVICE); + + /* mc_addr_map = wq->mem.assit_buffer_offset; */ + /* mc_addr = ioremap_wc(mc_addr_map, MC_SIZE); */ + /* memcpy(mc_addr, p, MC_SIZE); */ + enc_pr(LOG_ALL, "address 0 is 0x%x\n", *((u32 *)mc_addr)); + enc_pr(LOG_ALL, "address 1 is 0x%x\n", *((u32 *)mc_addr + 1)); + enc_pr(LOG_ALL, "address 2 is 0x%x\n", *((u32 *)mc_addr + 2)); + enc_pr(LOG_ALL, "address 3 is 0x%x\n", *((u32 *)mc_addr + 3)); + WRITE_HREG(HCODEC_MPSR, 0); + WRITE_HREG(HCODEC_CPSR, 0); + + /* Read CBUS register for timing */ + timeout = READ_HREG(HCODEC_MPSR); + timeout = READ_HREG(HCODEC_MPSR); + + timeout = jiffies + HZ; + + WRITE_HREG(HCODEC_IMEM_DMA_ADR, mc_addr_map); + WRITE_HREG(HCODEC_IMEM_DMA_COUNT, 0x1000); + WRITE_HREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); + + while (READ_HREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) { + if (time_before(jiffies, timeout)) + schedule(); + else { + enc_pr(LOG_ERROR, "hcodec load mc error\n"); + ret = -EBUSY; + break; + } + } + dma_unmap_single( + &encode_manager.this_pdev->dev, + mc_addr_map, MC_SIZE, DMA_TO_DEVICE); + return ret; +} + +const u32 fix_mc[] __aligned(8) = { + 0x0809c05a, 0x06696000, 0x0c780000, 0x00000000 +}; + + +/* + * DOS top level register access fix. + * When hcodec is running, a protocol register HCODEC_CCPU_INTR_MSK + * is set to make hcodec access one CBUS out of DOS domain once + * to work around a HW bug for 4k2k dual decoder implementation. + * If hcodec is not running, then a ucode is loaded and executed + * instead. + */ +void amvenc_dos_top_reg_fix(void) +{ + bool hcodec_on; + ulong flags; + + spin_lock_irqsave(&lock, flags); + + hcodec_on = vdec_on(VDEC_HCODEC); + + if ((hcodec_on) && (READ_VREG(HCODEC_MPSR) & 1)) { + WRITE_HREG(HCODEC_CCPU_INTR_MSK, 1); + spin_unlock_irqrestore(&lock, flags); + return; + } + + if (!hcodec_on) + vdec_poweron(VDEC_HCODEC); + + amhcodec_loadmc(fix_mc); + + amhcodec_start(); + + udelay(1000); + + amhcodec_stop(); + + if (!hcodec_on) + vdec_poweroff(VDEC_HCODEC); + + spin_unlock_irqrestore(&lock, flags); +} + +bool amvenc_avc_on(void) +{ + bool hcodec_on; + ulong flags; + + spin_lock_irqsave(&lock, flags); + + hcodec_on = vdec_on(VDEC_HCODEC); + hcodec_on &= (encode_manager.wq_count > 0); + + spin_unlock_irqrestore(&lock, flags); + return hcodec_on; +} + +static s32 avc_poweron(u32 clock) +{ + ulong flags; + u32 data32; + + data32 = 0; + + amports_switch_gate("vdec", 1); + + spin_lock_irqsave(&lock, flags); + + WRITE_AOREG(AO_RTI_PWR_CNTL_REG0, + (READ_AOREG(AO_RTI_PWR_CNTL_REG0) & (~0x18))); + udelay(10); + /* Powerup HCODEC */ + /* [1:0] HCODEC */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + (READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & (~0x3))); + udelay(10); + + WRITE_VREG(DOS_SW_RESET1, 0xffffffff); + WRITE_VREG(DOS_SW_RESET1, 0); + + /* Enable Dos internal clock gating */ + hvdec_clock_enable(clock); + + /* Powerup HCODEC memories */ + WRITE_VREG(DOS_MEM_PD_HCODEC, 0x0); + + /* Remove HCODEC ISO */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + (READ_AOREG(AO_RTI_GEN_PWR_ISO0) & (~0x30))); + udelay(10); + /* Disable auto-clock gate */ + WRITE_VREG(DOS_GEN_CTRL0, + (READ_VREG(DOS_GEN_CTRL0) | 0x1)); + WRITE_VREG(DOS_GEN_CTRL0, + (READ_VREG(DOS_GEN_CTRL0) & 0xFFFFFFFE)); + + spin_unlock_irqrestore(&lock, flags); + + mdelay(10); + return 0; +} + +static s32 avc_poweroff(void) +{ + ulong flags; + + spin_lock_irqsave(&lock, flags); + + /* enable HCODEC isolation */ + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30); + /* power off HCODEC memories */ + WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); + + /* disable HCODEC clock */ + hvdec_clock_disable(); + + /* HCODEC power off */ + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0x3); + + spin_unlock_irqrestore(&lock, flags); + + /* release DOS clk81 clock gating */ + amports_switch_gate("vdec", 0); + return 0; +} + +static s32 reload_mc(struct encode_wq_s *wq) +{ + const char *p = select_ucode(encode_manager.ucode_index); + + amvenc_stop(); + + WRITE_VREG(DOS_SW_RESET1, 0xffffffff); + WRITE_VREG(DOS_SW_RESET1, 0); + + udelay(10); + + WRITE_HREG(HCODEC_ASSIST_MMC_CTRL1, 0x32); + enc_pr(LOG_INFO, "reload microcode\n"); + + if (amvenc_loadmc(p, wq) < 0) + return -EBUSY; + return 0; +} + +static void encode_isr_tasklet(ulong data) +{ + struct encode_manager_s *manager = (struct encode_manager_s *)data; + enc_pr(LOG_INFO, "encoder is done %d\n", manager->encode_hw_status); + if (((manager->encode_hw_status == ENCODER_IDR_DONE) + || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) + || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) + || (manager->encode_hw_status == ENCODER_PICTURE_DONE)) + && (manager->process_irq)) { + wake_up_interruptible(&manager->event.hw_complete); + } +} + +/* irq function */ +static irqreturn_t enc_isr(s32 irq_number, void *para) +{ + struct encode_manager_s *manager = (struct encode_manager_s *)para; + WRITE_HREG(HCODEC_IRQ_MBOX_CLR, 1); + + manager->encode_hw_status = READ_HREG(ENCODER_STATUS); + if ((manager->encode_hw_status == ENCODER_IDR_DONE) + || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) + || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) + || (manager->encode_hw_status == ENCODER_PICTURE_DONE)) { + enc_pr(LOG_ALL, "encoder stage is %d\n", + manager->encode_hw_status); + } + + if (((manager->encode_hw_status == ENCODER_IDR_DONE) + || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) + || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) + || (manager->encode_hw_status == ENCODER_PICTURE_DONE)) + && (!manager->process_irq)) { + manager->process_irq = true; + if (manager->encode_hw_status != ENCODER_SEQUENCE_DONE) + manager->need_reset = true; + tasklet_schedule(&manager->encode_tasklet); + } + return IRQ_HANDLED; +} + +static s32 convert_request(struct encode_wq_s *wq, u32 *cmd_info) +{ + int i = 0; + u8 *ptr; + u32 data_offset; + u32 cmd = cmd_info[0]; + if (!wq) + return -1; + memset(&wq->request, 0, sizeof(struct encode_request_s)); + wq->request.me_weight = ME_WEIGHT_OFFSET; + wq->request.i4_weight = I4MB_WEIGHT_OFFSET; + wq->request.i16_weight = I16MB_WEIGHT_OFFSET; + + if (cmd == ENCODER_SEQUENCE) { + wq->request.cmd = cmd; + wq->request.ucode_mode = cmd_info[1]; + wq->request.quant = cmd_info[2]; + wq->request.flush_flag = cmd_info[3]; + wq->request.timeout = cmd_info[4]; + wq->request.timeout = 5000; /* 5000 ms */ + } else if ((cmd == ENCODER_IDR) || (cmd == ENCODER_NON_IDR)) { + wq->request.cmd = cmd; + wq->request.ucode_mode = cmd_info[1]; + wq->request.type = cmd_info[2]; + wq->request.fmt = cmd_info[3]; + wq->request.src = cmd_info[4]; + wq->request.framesize = cmd_info[5]; + wq->request.quant = cmd_info[6]; + wq->request.flush_flag = cmd_info[7]; + wq->request.timeout = cmd_info[8]; + wq->request.crop_top = cmd_info[9]; + wq->request.crop_bottom = cmd_info[10]; + wq->request.crop_left = cmd_info[11]; + wq->request.crop_right = cmd_info[12]; + wq->request.src_w = cmd_info[13]; + wq->request.src_h = cmd_info[14]; + wq->request.scale_enable = cmd_info[15]; + wq->request.nr_mode = + (nr_mode > 0) ? nr_mode : cmd_info[16]; + if (cmd == ENCODER_IDR) + wq->request.nr_mode = 0; + + data_offset = 17 + + (sizeof(wq->quant_tbl_i4) + + sizeof(wq->quant_tbl_i16) + + sizeof(wq->quant_tbl_me)) / 4; + + if (wq->request.quant == ADJUSTED_QP_FLAG) { + ptr = (u8 *) &cmd_info[17]; + memcpy(wq->quant_tbl_i4, ptr, + sizeof(wq->quant_tbl_i4)); + ptr += sizeof(wq->quant_tbl_i4); + memcpy(wq->quant_tbl_i16, ptr, + sizeof(wq->quant_tbl_i16)); + ptr += sizeof(wq->quant_tbl_i16); + memcpy(wq->quant_tbl_me, ptr, + sizeof(wq->quant_tbl_me)); + wq->request.i4_weight -= + cmd_info[data_offset++]; + wq->request.i16_weight -= + cmd_info[data_offset++]; + wq->request.me_weight -= + cmd_info[data_offset++]; + if (qp_table_debug) { + u8 *qp_tb = (u8 *)(&wq->quant_tbl_i4[0]); + for (i = 0; i < 32; i++) { + enc_pr(LOG_INFO, "%d ", *qp_tb); + qp_tb++; + } + enc_pr(LOG_INFO, "\n"); + + qp_tb = (u8 *)(&wq->quant_tbl_i16[0]); + for (i = 0; i < 32; i++) { + enc_pr(LOG_INFO, "%d ", *qp_tb); + qp_tb++; + } + enc_pr(LOG_INFO, "\n"); + + qp_tb = (u8 *)(&wq->quant_tbl_me[0]); + for (i = 0; i < 32; i++) { + enc_pr(LOG_INFO, "%d ", *qp_tb); + qp_tb++; + } + enc_pr(LOG_INFO, "\n"); + } + } else { + memset(wq->quant_tbl_me, wq->request.quant, + sizeof(wq->quant_tbl_me)); + memset(wq->quant_tbl_i4, wq->request.quant, + sizeof(wq->quant_tbl_i4)); + memset(wq->quant_tbl_i16, wq->request.quant, + sizeof(wq->quant_tbl_i16)); + data_offset += 3; + } +#ifdef H264_ENC_CBR + wq->cbr_info.block_w = cmd_info[data_offset++]; + wq->cbr_info.block_h = cmd_info[data_offset++]; + wq->cbr_info.long_th = cmd_info[data_offset++]; + wq->cbr_info.start_tbl_id = cmd_info[data_offset++]; + wq->cbr_info.short_shift = CBR_SHORT_SHIFT; + wq->cbr_info.long_mb_num = CBR_LONG_MB_NUM; +#endif + } else { + enc_pr(LOG_ERROR, "error cmd = %d, wq: %p.\n", + cmd, (void *)wq); + return -1; + } + wq->request.parent = wq; + return 0; +} + +void amvenc_avc_start_cmd(struct encode_wq_s *wq, + struct encode_request_s *request) +{ + u32 reload_flag = 0; + if (request->ucode_mode != encode_manager.ucode_index) { + encode_manager.ucode_index = request->ucode_mode; + if (reload_mc(wq)) { + enc_pr(LOG_ERROR, + "reload mc fail, wq:%p\n", (void *)wq); + return; + } + reload_flag = 1; + encode_manager.need_reset = true; + } + + wq->hw_status = 0; + wq->output_size = 0; + wq->ucode_index = encode_manager.ucode_index; + + ie_me_mode = (0 & ME_PIXEL_MODE_MASK) << ME_PIXEL_MODE_SHIFT; + if (encode_manager.need_reset) { + encode_manager.need_reset = false; + encode_manager.encode_hw_status = ENCODER_IDLE; + amvenc_reset(); + avc_canvas_init(wq); + avc_init_encoder(wq, + (request->cmd == ENCODER_IDR) ? true : false); + avc_init_input_buffer(wq); + avc_init_output_buffer(wq); + avc_prot_init(wq, request, request->quant, + (request->cmd == ENCODER_IDR) ? true : false); + avc_init_assit_buffer(wq); + enc_pr(LOG_INFO, + "begin to new frame, request->cmd: %d, ucode mode: %d, wq:%p.\n", + request->cmd, request->ucode_mode, (void *)wq); + } + if ((request->cmd == ENCODER_IDR) || + (request->cmd == ENCODER_NON_IDR)) { + avc_init_dblk_buffer(wq->mem.dblk_buf_canvas); + avc_init_reference_buffer(wq->mem.ref_buf_canvas); + } + if ((request->cmd == ENCODER_IDR) || + (request->cmd == ENCODER_NON_IDR)) + set_input_format(wq, request); + if (request->cmd == ENCODER_IDR) + ie_me_mb_type = HENC_MB_Type_I4MB; + else if (request->cmd == ENCODER_NON_IDR) + ie_me_mb_type = + (HENC_SKIP_RUN_AUTO << 16) | + (HENC_MB_Type_AUTO << 4) | + (HENC_MB_Type_AUTO << 0); + else + ie_me_mb_type = 0; + avc_init_ie_me_parameter(wq, request->quant); + +#ifdef MULTI_SLICE_MC + if (fixed_slice_cfg) + WRITE_HREG(FIXED_SLICE_CFG, fixed_slice_cfg); + else if (wq->pic.rows_per_slice != + (wq->pic.encoder_height + 15) >> 4) { + u32 mb_per_slice = (wq->pic.encoder_height + 15) >> 4; + mb_per_slice = mb_per_slice * wq->pic.rows_per_slice; + WRITE_HREG(FIXED_SLICE_CFG, mb_per_slice); + } else + WRITE_HREG(FIXED_SLICE_CFG, 0); +#else + WRITE_HREG(FIXED_SLICE_CFG, 0); +#endif + + encode_manager.encode_hw_status = request->cmd; + wq->hw_status = request->cmd; + WRITE_HREG(ENCODER_STATUS , request->cmd); + if ((request->cmd == ENCODER_IDR) + || (request->cmd == ENCODER_NON_IDR) + || (request->cmd == ENCODER_SEQUENCE) + || (request->cmd == ENCODER_PICTURE)) + encode_manager.process_irq = false; + + if (reload_flag) + amvenc_start(); + enc_pr(LOG_ALL, "amvenc_avc_start cmd, wq:%p.\n", (void *)wq); +} + +static void dma_flush(u32 buf_start , u32 buf_size) +{ + if ((buf_start == 0) || (buf_size == 0)) + return; + dma_sync_single_for_device( + &encode_manager.this_pdev->dev, buf_start, + buf_size, DMA_TO_DEVICE); +} + +static void cache_flush(u32 buf_start , u32 buf_size) +{ + if ((buf_start == 0) || (buf_size == 0)) + return; + dma_sync_single_for_cpu( + &encode_manager.this_pdev->dev, buf_start, + buf_size, DMA_FROM_DEVICE); +} + +static u32 getbuffer(struct encode_wq_s *wq, u32 type) +{ + u32 ret = 0; + + switch (type) { + case ENCODER_BUFFER_INPUT: + ret = wq->mem.dct_buff_start_addr; + break; + case ENCODER_BUFFER_REF0: + ret = wq->mem.dct_buff_start_addr + + wq->mem.bufspec.dec0_y.buf_start; + break; + case ENCODER_BUFFER_REF1: + ret = wq->mem.dct_buff_start_addr + + wq->mem.bufspec.dec1_y.buf_start; + break; + case ENCODER_BUFFER_OUTPUT: + ret = wq->mem.BitstreamStart; + break; + case ENCODER_BUFFER_DUMP: + ret = wq->mem.dump_info_ddr_start_addr; + break; + case ENCODER_BUFFER_CBR: + ret = wq->mem.cbr_info_ddr_start_addr; + break; + default: + break; + } + return ret; +} + +s32 amvenc_avc_start(struct encode_wq_s *wq, u32 clock) +{ + const char *p = select_ucode(encode_manager.ucode_index); + + avc_poweron(clock); + avc_canvas_init(wq); + + WRITE_HREG(HCODEC_ASSIST_MMC_CTRL1, 0x32); + + if (amvenc_loadmc(p, wq) < 0) + return -EBUSY; + + encode_manager.need_reset = true; + encode_manager.process_irq = false; + encode_manager.encode_hw_status = ENCODER_IDLE; + amvenc_reset(); + avc_init_encoder(wq, true); + avc_init_input_buffer(wq); /* dct buffer setting */ + avc_init_output_buffer(wq); /* output stream buffer */ + + ie_me_mode = (0 & ME_PIXEL_MODE_MASK) << ME_PIXEL_MODE_SHIFT; + avc_prot_init(wq, NULL, wq->pic.init_qppicture, true); + if (request_irq(encode_manager.irq_num, enc_isr, IRQF_SHARED, + "enc-irq", (void *)&encode_manager) == 0) + encode_manager.irq_requested = true; + else + encode_manager.irq_requested = false; + + /* decoder buffer , need set before each frame start */ + avc_init_dblk_buffer(wq->mem.dblk_buf_canvas); + /* reference buffer , need set before each frame start */ + avc_init_reference_buffer(wq->mem.ref_buf_canvas); + avc_init_assit_buffer(wq); /* assitant buffer for microcode */ + ie_me_mb_type = 0; + avc_init_ie_me_parameter(wq, wq->pic.init_qppicture); + WRITE_HREG(ENCODER_STATUS , ENCODER_IDLE); + +#ifdef MULTI_SLICE_MC + if (fixed_slice_cfg) + WRITE_HREG(FIXED_SLICE_CFG, fixed_slice_cfg); + else if (wq->pic.rows_per_slice != + (wq->pic.encoder_height + 15) >> 4) { + u32 mb_per_slice = (wq->pic.encoder_height + 15) >> 4; + mb_per_slice = mb_per_slice * wq->pic.rows_per_slice; + WRITE_HREG(FIXED_SLICE_CFG, mb_per_slice); + } else + WRITE_HREG(FIXED_SLICE_CFG, 0); +#else + WRITE_HREG(FIXED_SLICE_CFG, 0); +#endif + amvenc_start(); + return 0; +} + +void amvenc_avc_stop(void) +{ + if ((encode_manager.irq_num >= 0) && + (encode_manager.irq_requested == true)) { + free_irq(encode_manager.irq_num, &encode_manager); + encode_manager.irq_requested = false; + } + amvenc_stop(); + avc_poweroff(); +} + +static s32 avc_init(struct encode_wq_s *wq) +{ + s32 r = 0; + + encode_manager.ucode_index = wq->ucode_index; + r = amvenc_avc_start(wq, clock_level); + + enc_pr(LOG_DEBUG, + "init avc encode. microcode %d, ret=%d, wq:%p.\n", + encode_manager.ucode_index, r, (void *)wq); + return 0; +} + +static s32 amvenc_avc_light_reset(struct encode_wq_s *wq, u32 value) +{ + s32 r = 0; + + amvenc_avc_stop(); + + mdelay(value); + + encode_manager.ucode_index = UCODE_MODE_FULL; + r = amvenc_avc_start(wq, clock_level); + + enc_pr(LOG_DEBUG, + "amvenc_avc_light_reset finish, wq:%p. ret=%d\n", + (void *)wq, r); + return r; +} + +#ifdef CONFIG_CMA +static u32 checkCMA(void) +{ + u32 ret; + if (encode_manager.cma_pool_size > 0) { + ret = encode_manager.cma_pool_size; + ret = ret / MIN_SIZE; + } else + ret = 0; + return ret; +} +#endif + +/* file operation */ +static s32 amvenc_avc_open(struct inode *inode, struct file *file) +{ + s32 r = 0; + struct encode_wq_s *wq = NULL; + file->private_data = NULL; + enc_pr(LOG_DEBUG, "avc open\n"); +#ifdef CONFIG_AM_JPEG_ENCODER + if (jpegenc_on() == true) { + enc_pr(LOG_ERROR, + "hcodec in use for JPEG Encode now.\n"); + return -EBUSY; + } +#endif + +#ifdef CONFIG_CMA + if ((encode_manager.use_reserve == false) && + (encode_manager.check_cma == false)) { + encode_manager.max_instance = checkCMA(); + if (encode_manager.max_instance > 0) { + enc_pr(LOG_DEBUG, + "amvenc_avc check CMA pool sucess, max instance: %d.\n", + encode_manager.max_instance); + } else { + enc_pr(LOG_ERROR, + "amvenc_avc CMA pool too small.\n"); + } + encode_manager.check_cma = true; + } +#endif + + wq = create_encode_work_queue(); + if (wq == NULL) { + enc_pr(LOG_ERROR, "amvenc_avc create instance fail.\n"); + return -EBUSY; + } + +#ifdef CONFIG_CMA + if (encode_manager.use_reserve == false) { + wq->mem.buf_start = codec_mm_alloc_for_dma(ENCODE_NAME, + MIN_SIZE >> PAGE_SHIFT, 0, + CODEC_MM_FLAGS_CPU); + if (wq->mem.buf_start) { + wq->mem.buf_size = MIN_SIZE; + enc_pr(LOG_DEBUG, + "allocating phys 0x%x, size %dk, wq:%p.\n", + wq->mem.buf_start, + wq->mem.buf_size >> 10, (void *)wq); + } else { + enc_pr(LOG_ERROR, + "CMA failed to allocate dma buffer for %s, wq:%p.\n", + encode_manager.this_pdev->name, + (void *)wq); + destroy_encode_work_queue(wq); + return -ENOMEM; + } + } +#endif + + if (wq->mem.buf_start == 0 || + wq->mem.buf_size < MIN_SIZE) { + enc_pr(LOG_ERROR, + "alloc mem failed, start: 0x%x, size:0x%x, wq:%p.\n", + wq->mem.buf_start, + wq->mem.buf_size, (void *)wq); + destroy_encode_work_queue(wq); + return -ENOMEM; + } + + memcpy(&wq->mem.bufspec, &amvenc_buffspec[0], + sizeof(struct BuffInfo_s)); + + enc_pr(LOG_DEBUG, + "amvenc_avc memory config sucess, buff start:0x%x, size is 0x%x, wq:%p.\n", + wq->mem.buf_start, wq->mem.buf_size, (void *)wq); + + file->private_data = (void *) wq; + return r; +} + +static s32 amvenc_avc_release(struct inode *inode, struct file *file) +{ + struct encode_wq_s *wq = (struct encode_wq_s *)file->private_data; + if (wq) { + enc_pr(LOG_DEBUG, "avc release, wq:%p\n", (void *)wq); + destroy_encode_work_queue(wq); + } + return 0; +} + +static long amvenc_avc_ioctl(struct file *file, u32 cmd, ulong arg) +{ + long r = 0; + u32 amrisc_cmd = 0; + struct encode_wq_s *wq = (struct encode_wq_s *)file->private_data; +#define MAX_ADDR_INFO_SIZE 50 + u32 addr_info[MAX_ADDR_INFO_SIZE + 4]; + ulong argV; + u32 buf_start; + s32 canvas = -1; + struct canvas_s dst; + switch (cmd) { + case AMVENC_AVC_IOC_GET_ADDR: + if ((wq->mem.ref_buf_canvas & 0xff) == (ENC_CANVAS_OFFSET)) + put_user(1, (u32 *)arg); + else + put_user(2, (u32 *)arg); + break; + case AMVENC_AVC_IOC_INPUT_UPDATE: + break; + case AMVENC_AVC_IOC_NEW_CMD: + if (copy_from_user(addr_info, (void *)arg, + MAX_ADDR_INFO_SIZE * sizeof(u32))) { + enc_pr(LOG_ERROR, + "avc get new cmd error, wq:%p.\n", (void *)wq); + return -1; + } + r = convert_request(wq, addr_info); + if (r == 0) + r = encode_wq_add_request(wq); + if (r) { + enc_pr(LOG_ERROR, + "avc add new request error, wq:%p.\n", + (void *)wq); + } + break; + case AMVENC_AVC_IOC_GET_STAGE: + put_user(wq->hw_status, (u32 *)arg); + break; + case AMVENC_AVC_IOC_GET_OUTPUT_SIZE: + addr_info[0] = wq->output_size; + addr_info[1] = wq->me_weight; + addr_info[2] = wq->i4_weight; + addr_info[3] = wq->i16_weight; + r = copy_to_user((u32 *)arg, + addr_info , 4 * sizeof(u32)); + break; + case AMVENC_AVC_IOC_CONFIG_INIT: + if (copy_from_user(addr_info, (void *)arg, + MAX_ADDR_INFO_SIZE * sizeof(u32))) { + enc_pr(LOG_ERROR, + "avc config init error, wq:%p.\n", (void *)wq); + return -1; + } + wq->ucode_index = UCODE_MODE_FULL; +#ifdef MULTI_SLICE_MC + wq->pic.rows_per_slice = addr_info[1]; + enc_pr(LOG_DEBUG, + "avc init -- rows_per_slice: %d, wq: %p.\n", + wq->pic.rows_per_slice, (void *)wq); +#endif + enc_pr(LOG_DEBUG, + "avc init as mode %d, wq: %p.\n", + wq->ucode_index, (void *)wq); + + if (addr_info[2] > wq->mem.bufspec.max_width || + addr_info[3] > wq->mem.bufspec.max_height) { + enc_pr(LOG_ERROR, + "avc config init- encode size %dx%d is larger than supported (%dx%d). wq:%p.\n", + addr_info[2], addr_info[3], + wq->mem.bufspec.max_width, + wq->mem.bufspec.max_height, (void *)wq); + return -1; + } + wq->pic.encoder_width = addr_info[2]; + wq->pic.encoder_height = addr_info[3]; + if (wq->pic.encoder_width * + wq->pic.encoder_height >= 1280 * 720) + clock_level = 6; + else + clock_level = 5; + avc_buffspec_init(wq); + complete(&encode_manager.event.request_in_com); + addr_info[1] = wq->mem.bufspec.dct.buf_start; + addr_info[2] = wq->mem.bufspec.dct.buf_size; + addr_info[3] = wq->mem.bufspec.bitstream.buf_start; + addr_info[4] = wq->mem.bufspec.bitstream.buf_size; + addr_info[5] = wq->mem.bufspec.scale_buff.buf_start; + addr_info[6] = wq->mem.bufspec.scale_buff.buf_size; + addr_info[7] = wq->mem.bufspec.dump_info.buf_start; + addr_info[8] = wq->mem.bufspec.dump_info.buf_size; + addr_info[9] = wq->mem.bufspec.cbr_info.buf_start; + addr_info[10] = wq->mem.bufspec.cbr_info.buf_size; + r = copy_to_user((u32 *)arg, addr_info , 11*sizeof(u32)); + break; + case AMVENC_AVC_IOC_FLUSH_CACHE: + if (copy_from_user(addr_info, (void *)arg, + MAX_ADDR_INFO_SIZE * sizeof(u32))) { + enc_pr(LOG_ERROR, + "avc flush cache error, wq: %p.\n", (void *)wq); + return -1; + } + buf_start = getbuffer(wq, addr_info[0]); + dma_flush(buf_start + addr_info[1], + addr_info[2] - addr_info[1]); + break; + case AMVENC_AVC_IOC_FLUSH_DMA: + if (copy_from_user(addr_info, (void *)arg, + MAX_ADDR_INFO_SIZE * sizeof(u32))) { + enc_pr(LOG_ERROR, + "avc flush dma error, wq:%p.\n", (void *)wq); + return -1; + } + buf_start = getbuffer(wq, addr_info[0]); + cache_flush(buf_start + addr_info[1], + addr_info[2] - addr_info[1]); + break; + case AMVENC_AVC_IOC_GET_BUFFINFO: + put_user(wq->mem.buf_size, (u32 *)arg); + break; + case AMVENC_AVC_IOC_GET_DEVINFO: + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + /* send the same id as GXTVBB to upper*/ + r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_GXTVBB, + strlen(AMVENC_DEVINFO_GXTVBB)); + } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) { + r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_GXTVBB, + strlen(AMVENC_DEVINFO_GXTVBB)); + } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) { + r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_GXBB, + strlen(AMVENC_DEVINFO_GXBB)); + } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_MG9TV) { + r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_G9, + strlen(AMVENC_DEVINFO_G9)); + } else { + r = copy_to_user((s8 *)arg, AMVENC_DEVINFO_M8, + strlen(AMVENC_DEVINFO_M8)); + } + break; + case AMVENC_AVC_IOC_SUBMIT: + get_user(amrisc_cmd, ((u32 *)arg)); + if (amrisc_cmd == ENCODER_IDR) { + wq->pic.idr_pic_id++; + if (wq->pic.idr_pic_id > 65535) + wq->pic.idr_pic_id = 0; + wq->pic.pic_order_cnt_lsb = 2; + wq->pic.frame_number = 1; + } else if (amrisc_cmd == ENCODER_NON_IDR) { + wq->pic.frame_number++; + wq->pic.pic_order_cnt_lsb += 2; + if (wq->pic.frame_number > 65535) + wq->pic.frame_number = 0; + } + amrisc_cmd = wq->mem.dblk_buf_canvas; + wq->mem.dblk_buf_canvas = wq->mem.ref_buf_canvas; + /* current dblk buffer as next reference buffer */ + wq->mem.ref_buf_canvas = amrisc_cmd; + break; + case AMVENC_AVC_IOC_READ_CANVAS: + get_user(argV, ((u32 *)arg)); + canvas = argV; + if (canvas & 0xff) { + canvas_read(canvas & 0xff, &dst); + addr_info[0] = dst.addr; + if ((canvas & 0xff00) >> 8) + canvas_read((canvas & 0xff00) >> 8, &dst); + if ((canvas & 0xff0000) >> 16) + canvas_read((canvas & 0xff0000) >> 16, &dst); + addr_info[1] = dst.addr - addr_info[0] + + dst.width * dst.height; + } else { + addr_info[0] = 0; + addr_info[1] = 0; + } + dma_flush(dst.addr, dst.width * dst.height * 3 / 2); + r = copy_to_user((u32 *)arg, addr_info , 2 * sizeof(u32)); + break; + case AMVENC_AVC_IOC_MAX_INSTANCE: + put_user(encode_manager.max_instance, (u32 *)arg); + break; + default: + r = -1; + break; + } + return r; +} + +#ifdef CONFIG_COMPAT +static long amvenc_avc_compat_ioctl(struct file *filp, + unsigned int cmd, unsigned long args) +{ + unsigned long ret; + + args = (unsigned long)compat_ptr(args); + ret = amvenc_avc_ioctl(filp, cmd, args); + return ret; +} +#endif + +static s32 avc_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct encode_wq_s *wq = (struct encode_wq_s *)filp->private_data; + ulong off = vma->vm_pgoff << PAGE_SHIFT; + ulong vma_size = vma->vm_end - vma->vm_start; + + if (vma_size == 0) { + enc_pr(LOG_ERROR, "vma_size is 0, wq:%p.\n", (void *)wq); + return -EAGAIN; + } + if (!off) + off += wq->mem.buf_start; + enc_pr(LOG_ALL, + "vma_size is %ld , off is %ld, wq:%p.\n", + vma_size , off, (void *)wq); + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO; + /* vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); */ + if (remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + enc_pr(LOG_ERROR, + "set_cached: failed remap_pfn_range, wq:%p.\n", + (void *)wq); + return -EAGAIN; + } + return 0; +} + +static u32 amvenc_avc_poll(struct file *file, poll_table *wait_table) +{ + struct encode_wq_s *wq = (struct encode_wq_s *)file->private_data; + poll_wait(file, &wq->request_complete, wait_table); + + if (atomic_read(&wq->request_ready)) { + atomic_dec(&wq->request_ready); + return POLLIN | POLLRDNORM; + } + return 0; +} + +static const struct file_operations amvenc_avc_fops = { + .owner = THIS_MODULE, + .open = amvenc_avc_open, + .mmap = avc_mmap, + .release = amvenc_avc_release, + .unlocked_ioctl = amvenc_avc_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amvenc_avc_compat_ioctl, +#endif + .poll = amvenc_avc_poll, +}; + +/* work queue function */ +static s32 encode_process_request(struct encode_manager_s *manager, + struct encode_queue_item_s *pitem) +{ + s32 ret = 0; + struct encode_wq_s *wq = pitem->request.parent; + struct encode_request_s *request = &pitem->request; + u32 timeout = (request->timeout == 0) ? + 1 : msecs_to_jiffies(request->timeout); + u32 buf_start = 0; + u32 size = 0; + u32 flush_size = ((wq->pic.encoder_width + 31) >> 5 << 5) * + ((wq->pic.encoder_height + 15) >> 4 << 4) * 3 / 2; + +#ifdef H264_ENC_CBR + if (request->cmd == ENCODER_IDR || request->cmd == ENCODER_NON_IDR) { + if (request->flush_flag & AMVENC_FLUSH_FLAG_CBR + && get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + void *vaddr = + phys_to_virt(wq->mem.cbr_info_ddr_start_addr); + ConvertTable2Risc(vaddr, 0xa00); + buf_start = getbuffer(wq, ENCODER_BUFFER_CBR); + dma_flush(buf_start, wq->mem.cbr_info_ddr_size); + } + } +#endif + +Again: + amvenc_avc_start_cmd(wq, request); + + if (no_timeout) { + wait_event_interruptible(manager->event.hw_complete, + (manager->encode_hw_status == ENCODER_IDR_DONE + || manager->encode_hw_status == ENCODER_NON_IDR_DONE + || manager->encode_hw_status == ENCODER_SEQUENCE_DONE + || manager->encode_hw_status == ENCODER_PICTURE_DONE)); + } else { + wait_event_interruptible_timeout(manager->event.hw_complete, + ((manager->encode_hw_status == ENCODER_IDR_DONE) + || (manager->encode_hw_status == ENCODER_NON_IDR_DONE) + || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE) + || (manager->encode_hw_status == ENCODER_PICTURE_DONE)), + timeout); + } + + if ((request->cmd == ENCODER_SEQUENCE) && + (manager->encode_hw_status == ENCODER_SEQUENCE_DONE)) { + wq->sps_size = READ_HREG(HCODEC_VLC_TOTAL_BYTES); + wq->hw_status = manager->encode_hw_status; + request->cmd = ENCODER_PICTURE; + goto Again; + } else if ((request->cmd == ENCODER_PICTURE) && + (manager->encode_hw_status == ENCODER_PICTURE_DONE)) { + wq->pps_size = + READ_HREG(HCODEC_VLC_TOTAL_BYTES) - wq->sps_size; + wq->hw_status = manager->encode_hw_status; + if (request->flush_flag & AMVENC_FLUSH_FLAG_OUTPUT) { + buf_start = getbuffer(wq, ENCODER_BUFFER_OUTPUT); + cache_flush(buf_start, + wq->sps_size + wq->pps_size); + } + wq->output_size = (wq->sps_size << 16) | wq->pps_size; + } else { + wq->hw_status = manager->encode_hw_status; + if ((manager->encode_hw_status == ENCODER_IDR_DONE) || + (manager->encode_hw_status == ENCODER_NON_IDR_DONE)) { + wq->output_size = READ_HREG(HCODEC_VLC_TOTAL_BYTES); + if (request->flush_flag & AMVENC_FLUSH_FLAG_OUTPUT) { + buf_start = getbuffer(wq, + ENCODER_BUFFER_OUTPUT); + cache_flush(buf_start, wq->output_size); + } + if (request->flush_flag & + AMVENC_FLUSH_FLAG_DUMP) { + buf_start = getbuffer(wq, + ENCODER_BUFFER_DUMP); + size = wq->mem.dump_info_ddr_size; + cache_flush(buf_start, size); + enc_pr(LOG_DEBUG, "CBR flush dump_info done--- "); + } + if (request->flush_flag & + AMVENC_FLUSH_FLAG_REFERENCE) { + u32 ref_id = ENCODER_BUFFER_REF0; + if ((wq->mem.ref_buf_canvas & 0xff) == + (ENC_CANVAS_OFFSET)) + ref_id = ENCODER_BUFFER_REF0; + else + ref_id = ENCODER_BUFFER_REF1; + buf_start = getbuffer(wq, ref_id); + cache_flush(buf_start, flush_size); + } + } else { + manager->encode_hw_status = ENCODER_ERROR; + enc_pr(LOG_DEBUG, "avc encode light reset --- "); + enc_pr(LOG_DEBUG, + "frame type: %s, size: %dx%d, wq: %p\n", + (request->cmd == ENCODER_IDR) ? "IDR" : "P", + wq->pic.encoder_width, + wq->pic.encoder_height, (void *)wq); + enc_pr(LOG_DEBUG, + "mb info: 0x%x, encode status: 0x%x, dct status: 0x%x ", + READ_HREG(HCODEC_VLC_MB_INFO), + READ_HREG(ENCODER_STATUS), + READ_HREG(HCODEC_QDCT_STATUS_CTRL)); + enc_pr(LOG_DEBUG, + "vlc status: 0x%x, me status: 0x%x, risc pc:0x%x, debug:0x%x\n", + READ_HREG(HCODEC_VLC_STATUS_CTRL), + READ_HREG(HCODEC_ME_STATUS), + READ_HREG(HCODEC_MPC_E), + READ_HREG(DEBUG_REG)); + amvenc_avc_light_reset(wq, 30); + } + } + atomic_inc(&wq->request_ready); + wake_up_interruptible(&wq->request_complete); + return ret; +} + +s32 encode_wq_add_request(struct encode_wq_s *wq) +{ + struct encode_queue_item_s *pitem = NULL; + struct list_head *head = NULL; + struct encode_wq_s *tmp = NULL; + bool find = false; + + spin_lock(&encode_manager.event.sem_lock); + + head = &encode_manager.wq; + list_for_each_entry(tmp, head, list) { + if ((wq == tmp) && (wq != NULL)) { + find = true; + break; + } + } + + if (find == false) { + enc_pr(LOG_ERROR, "current wq (%p) doesn't register.\n", + (void *)wq); + goto error; + } + + if (list_empty(&encode_manager.free_queue)) { + enc_pr(LOG_ERROR, "work queue no space, wq:%p.\n", + (void *)wq); + goto error; + } + + pitem = list_entry(encode_manager.free_queue.next, + struct encode_queue_item_s, list); + if (IS_ERR(pitem)) + goto error; + + memcpy(&pitem->request, &wq->request, sizeof(struct encode_request_s)); + memset(&wq->request, 0, sizeof(struct encode_request_s)); + wq->hw_status = 0; + wq->output_size = 0; + pitem->request.parent = wq; + list_move_tail(&pitem->list, &encode_manager.process_queue); + spin_unlock(&encode_manager.event.sem_lock); + + enc_pr(LOG_INFO, + "add new work ok, cmd:%d, ucode mode: %d, wq:%p.\n", + pitem->request.cmd, pitem->request.ucode_mode, + (void *)wq); + complete(&encode_manager.event.request_in_com);/* new cmd come in */ + return 0; +error: + spin_unlock(&encode_manager.event.sem_lock); + return -1; +} + +struct encode_wq_s *create_encode_work_queue(void) +{ + struct encode_wq_s *encode_work_queue = NULL; + bool done = false; + u32 i, max_instance; + struct Buff_s *reserve_buff; + + encode_work_queue = kzalloc(sizeof(struct encode_wq_s), GFP_KERNEL); + if (IS_ERR(encode_work_queue)) { + enc_pr(LOG_ERROR, "can't create work queue\n"); + return NULL; + } + max_instance = encode_manager.max_instance; + encode_work_queue->pic.init_qppicture = 26; + encode_work_queue->pic.log2_max_frame_num = 4; + encode_work_queue->pic.log2_max_pic_order_cnt_lsb = 4; + encode_work_queue->pic.idr_pic_id = 0; + encode_work_queue->pic.frame_number = 0; + encode_work_queue->pic.pic_order_cnt_lsb = 0; + encode_work_queue->ucode_index = UCODE_MODE_FULL; + +#ifdef H264_ENC_CBR + encode_work_queue->cbr_info.block_w = 16; + encode_work_queue->cbr_info.block_h = 9; + encode_work_queue->cbr_info.long_th = CBR_LONG_THRESH; + encode_work_queue->cbr_info.start_tbl_id = START_TABLE_ID; + encode_work_queue->cbr_info.short_shift = CBR_SHORT_SHIFT; + encode_work_queue->cbr_info.long_mb_num = CBR_LONG_MB_NUM; +#endif + init_waitqueue_head(&encode_work_queue->request_complete); + atomic_set(&encode_work_queue->request_ready, 0); + spin_lock(&encode_manager.event.sem_lock); + if (encode_manager.wq_count < encode_manager.max_instance) { + list_add_tail(&encode_work_queue->list, &encode_manager.wq); + encode_manager.wq_count++; + if (encode_manager.use_reserve == true) { + for (i = 0; i < max_instance; i++) { + reserve_buff = &encode_manager.reserve_buff[i]; + if (reserve_buff->used == false) { + encode_work_queue->mem.buf_start = + reserve_buff->buf_start; + encode_work_queue->mem.buf_size = + reserve_buff->buf_size; + reserve_buff->used = true; + done = true; + break; + } + } + } else + done = true; + } + spin_unlock(&encode_manager.event.sem_lock); + if (done == false) { + kfree(encode_work_queue); + encode_work_queue = NULL; + enc_pr(LOG_ERROR, "too many work queue!\n"); + } + return encode_work_queue; /* find it */ +} + +static void _destroy_encode_work_queue(struct encode_manager_s *manager, + struct encode_wq_s **wq, + struct encode_wq_s *encode_work_queue, + bool *find) +{ + struct list_head *head; + struct encode_wq_s *wp_tmp = NULL; + u32 i, max_instance; + struct Buff_s *reserve_buff; + u32 buf_start = encode_work_queue->mem.buf_start; + + max_instance = manager->max_instance; + head = &manager->wq; + list_for_each_entry_safe((*wq), wp_tmp, head, list) { + if ((*wq) && (*wq == encode_work_queue)) { + list_del(&(*wq)->list); + if (manager->use_reserve == true) { + for (i = 0; i < max_instance; i++) { + reserve_buff = + &manager->reserve_buff[i]; + if (reserve_buff->used == true && + buf_start == + reserve_buff->buf_start) { + reserve_buff->used = false; + break; + } + } + } + *find = true; + manager->wq_count--; + enc_pr(LOG_DEBUG, + "remove encode_work_queue %p sucess, %s line %d.\n", + (void *)encode_work_queue, + __func__, __LINE__); + break; + } + } +} + +s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue) +{ + struct encode_queue_item_s *pitem, *tmp; + struct encode_wq_s *wq = NULL; + bool find = false; + + struct list_head *head; + if (encode_work_queue) { + spin_lock(&encode_manager.event.sem_lock); + if (encode_manager.current_wq == encode_work_queue) { + encode_manager.remove_flag = true; + spin_unlock(&encode_manager.event.sem_lock); + enc_pr(LOG_DEBUG, + "warning--Destory the running queue, should not be here.\n"); + wait_for_completion( + &encode_manager.event.process_complete); + spin_lock(&encode_manager.event.sem_lock); + } /* else we can delete it safely. */ + + head = &encode_manager.process_queue; + list_for_each_entry_safe(pitem, tmp, head, list) { + if (pitem && pitem->request.parent == + encode_work_queue) { + pitem->request.parent = NULL; + enc_pr(LOG_DEBUG, + "warning--remove not process request, should not be here.\n"); + list_move_tail(&pitem->list, + &encode_manager.free_queue); + } + } + + _destroy_encode_work_queue(&encode_manager, &wq, + encode_work_queue, &find); + spin_unlock(&encode_manager.event.sem_lock); +#ifdef CONFIG_CMA + if (encode_work_queue->mem.buf_start) { + codec_mm_free_for_dma( + ENCODE_NAME, + encode_work_queue->mem.buf_start); + encode_work_queue->mem.buf_start = 0; + + } +#endif + kfree(encode_work_queue); + complete(&encode_manager.event.request_in_com); + } + return 0; +} + +static s32 encode_monitor_thread(void *data) +{ + struct encode_manager_s *manager = (struct encode_manager_s *)data; + struct encode_queue_item_s *pitem = NULL; + struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; + s32 ret = 0; + enc_pr(LOG_DEBUG, "encode workqueue monitor start.\n"); + sched_setscheduler(current, SCHED_FIFO, ¶m); + allow_signal(SIGTERM); + /* setup current_wq here. */ + while (manager->process_queue_state != ENCODE_PROCESS_QUEUE_STOP) { + if (kthread_should_stop()) + break; + + ret = wait_for_completion_interruptible( + &manager->event.request_in_com); + + if (ret == -ERESTARTSYS) + break; + + if (kthread_should_stop()) + break; + if (manager->inited == false) { + spin_lock(&manager->event.sem_lock); + if (!list_empty(&manager->wq)) { + struct encode_wq_s *first_wq = + list_entry(manager->wq.next, + struct encode_wq_s, list); + manager->current_wq = first_wq; + spin_unlock(&manager->event.sem_lock); + if (first_wq) { +#ifdef CONFIG_AM_GE2D + if (!manager->context) + manager->context = + create_ge2d_work_queue(); +#endif + avc_init(first_wq); + manager->inited = true; + } + spin_lock(&manager->event.sem_lock); + manager->current_wq = NULL; + spin_unlock(&manager->event.sem_lock); + if (manager->remove_flag) { + complete( + &manager + ->event.process_complete); + manager->remove_flag = false; + } + } else + spin_unlock(&manager->event.sem_lock); + continue; + } + + spin_lock(&manager->event.sem_lock); + pitem = NULL; + if (list_empty(&manager->wq)) { + spin_unlock(&manager->event.sem_lock); + manager->inited = false; + amvenc_avc_stop(); +#ifdef CONFIG_AM_GE2D + if (manager->context) { + destroy_ge2d_work_queue(manager->context); + manager->context = NULL; + } +#endif + enc_pr(LOG_DEBUG, "power off encode.\n"); + continue; + } else if (!list_empty(&manager->process_queue)) { + pitem = list_entry(manager->process_queue.next, + struct encode_queue_item_s, list); + list_del(&pitem->list); + manager->current_item = pitem; + manager->current_wq = pitem->request.parent; + } + spin_unlock(&manager->event.sem_lock); + + if (pitem) { + encode_process_request(manager, pitem); + spin_lock(&manager->event.sem_lock); + list_add_tail(&pitem->list, &manager->free_queue); + manager->current_item = NULL; + manager->last_wq = manager->current_wq; + manager->current_wq = NULL; + spin_unlock(&manager->event.sem_lock); + } + if (manager->remove_flag) { + complete(&manager->event.process_complete); + manager->remove_flag = false; + } + } + while (!kthread_should_stop()) + msleep(20); + + enc_pr(LOG_DEBUG, "exit encode_monitor_thread.\n"); + return 0; +} + +static s32 encode_start_monitor(void) +{ + s32 ret = 0; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + y_tnr_mot2alp_nrm_gain = 216; + y_tnr_mot2alp_dis_gain = 144; + c_tnr_mot2alp_nrm_gain = 216; + c_tnr_mot2alp_dis_gain = 144; + } else { + /* more tnr */ + y_tnr_mot2alp_nrm_gain = 144; + y_tnr_mot2alp_dis_gain = 96; + c_tnr_mot2alp_nrm_gain = 144; + c_tnr_mot2alp_dis_gain = 96; + } + + enc_pr(LOG_DEBUG, "encode start monitor.\n"); + encode_manager.process_queue_state = ENCODE_PROCESS_QUEUE_START; + encode_manager.encode_thread = kthread_run(encode_monitor_thread, + &encode_manager, "encode_monitor"); + if (IS_ERR(encode_manager.encode_thread)) { + ret = PTR_ERR(encode_manager.encode_thread); + encode_manager.process_queue_state = ENCODE_PROCESS_QUEUE_STOP; + enc_pr(LOG_ERROR, + "encode monitor : failed to start kthread (%d)\n", ret); + } + return ret; +} + +static s32 encode_stop_monitor(void) +{ + enc_pr(LOG_DEBUG, "stop encode monitor thread\n"); + if (encode_manager.encode_thread) { + spin_lock(&encode_manager.event.sem_lock); + if (!list_empty(&encode_manager.wq)) { + u32 count = encode_manager.wq_count; + spin_unlock(&encode_manager.event.sem_lock); + enc_pr(LOG_ERROR, + "stop encode monitor thread error, active wq (%d) is not 0.\n", + count); + return -1; + } + spin_unlock(&encode_manager.event.sem_lock); + encode_manager.process_queue_state = ENCODE_PROCESS_QUEUE_STOP; + send_sig(SIGTERM, encode_manager.encode_thread, 1); + complete(&encode_manager.event.request_in_com); + kthread_stop(encode_manager.encode_thread); + encode_manager.encode_thread = NULL; + kfree(mc_addr); + mc_addr = NULL; + } + return 0; +} + +static s32 encode_wq_init(void) +{ + u32 i = 0; + struct encode_queue_item_s *pitem = NULL; + + enc_pr(LOG_DEBUG, "encode_wq_init.\n"); + encode_manager.irq_requested = false; + + spin_lock_init(&encode_manager.event.sem_lock); + init_completion(&encode_manager.event.request_in_com); + init_waitqueue_head(&encode_manager.event.hw_complete); + init_completion(&encode_manager.event.process_complete); + INIT_LIST_HEAD(&encode_manager.process_queue); + INIT_LIST_HEAD(&encode_manager.free_queue); + INIT_LIST_HEAD(&encode_manager.wq); + + tasklet_init(&encode_manager.encode_tasklet, + encode_isr_tasklet, + (ulong)&encode_manager); + + for (i = 0; i < MAX_ENCODE_REQUEST; i++) { + pitem = kcalloc(1, + sizeof(struct encode_queue_item_s), + GFP_KERNEL); + if (IS_ERR(pitem)) { + enc_pr(LOG_ERROR, "can't request queue item memory.\n"); + return -1; + } + pitem->request.parent = NULL; + list_add_tail(&pitem->list, &encode_manager.free_queue); + } + encode_manager.current_wq = NULL; + encode_manager.last_wq = NULL; + encode_manager.encode_thread = NULL; + encode_manager.current_item = NULL; + encode_manager.wq_count = 0; + encode_manager.remove_flag = false; + InitEncodeWeight(); + if (encode_start_monitor()) { + enc_pr(LOG_ERROR, "encode create thread error.\n"); + return -1; + } + return 0; +} + +static s32 encode_wq_uninit(void) +{ + struct encode_queue_item_s *pitem, *tmp; + struct list_head *head; + u32 count = 0; + s32 r = -1; + enc_pr(LOG_DEBUG, "uninit encode wq.\n"); + if (encode_stop_monitor() == 0) { + if ((encode_manager.irq_num >= 0) && + (encode_manager.irq_requested == true)) { + free_irq(encode_manager.irq_num, &encode_manager); + encode_manager.irq_requested = false; + } + spin_lock(&encode_manager.event.sem_lock); + head = &encode_manager.process_queue; + list_for_each_entry_safe(pitem, tmp, head, list) { + if (pitem) { + list_del(&pitem->list); + kfree(pitem); + count++; + } + } + head = &encode_manager.free_queue; + list_for_each_entry_safe(pitem, tmp, head, list) { + if (pitem) { + list_del(&pitem->list); + kfree(pitem); + count++; + } + } + spin_unlock(&encode_manager.event.sem_lock); + if (count == MAX_ENCODE_REQUEST) + r = 0; + else { + enc_pr(LOG_ERROR, "lost some request item %d.\n", + MAX_ENCODE_REQUEST - count); + } + } + return r; +} + +static ssize_t encode_status_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + u32 process_count = 0; + u32 free_count = 0; + struct encode_queue_item_s *pitem = NULL; + struct encode_wq_s *current_wq = NULL; + struct encode_wq_s *last_wq = NULL; + struct list_head *head = NULL; + s32 irq_num = 0; + u32 hw_status = 0; + u32 process_queue_state = 0; + u32 wq_count = 0; + u32 ucode_index; + bool need_reset; + bool process_irq; + bool inited; + bool use_reserve; + struct Buff_s reserve_mem; + u32 max_instance; +#ifdef CONFIG_CMA + bool check_cma = false; +#endif + + spin_lock(&encode_manager.event.sem_lock); + head = &encode_manager.free_queue; + list_for_each_entry(pitem, head , list) { + free_count++; + if (free_count > MAX_ENCODE_REQUEST) + break; + } + + head = &encode_manager.process_queue; + list_for_each_entry(pitem, head , list) { + process_count++; + if (free_count > MAX_ENCODE_REQUEST) + break; + } + + current_wq = encode_manager.current_wq; + last_wq = encode_manager.last_wq; + pitem = encode_manager.current_item; + irq_num = encode_manager.irq_num; + hw_status = encode_manager.encode_hw_status; + process_queue_state = encode_manager.process_queue_state; + wq_count = encode_manager.wq_count; + ucode_index = encode_manager.ucode_index; + need_reset = encode_manager.need_reset; + process_irq = encode_manager.process_irq; + inited = encode_manager.inited; + use_reserve = encode_manager.use_reserve; + reserve_mem.buf_start = encode_manager.reserve_mem.buf_start; + reserve_mem.buf_size = encode_manager.reserve_mem.buf_size; + + max_instance = encode_manager.max_instance; +#ifdef CONFIG_CMA + check_cma = encode_manager.check_cma; +#endif + + spin_unlock(&encode_manager.event.sem_lock); + + enc_pr(LOG_DEBUG, + "encode process queue count: %d, free queue count: %d.\n", + process_count, free_count); + enc_pr(LOG_DEBUG, + "encode curent wq: %p, last wq: %p, wq count: %d, max_instance: %d.\n", + current_wq, last_wq, wq_count, max_instance); + if (current_wq) + enc_pr(LOG_DEBUG, + "encode curent wq -- encode width: %d, encode height: %d.\n", + current_wq->pic.encoder_width, + current_wq->pic.encoder_height); + enc_pr(LOG_DEBUG, + "encode curent pitem: %p, ucode_index: %d, hw_status: %d, need_reset: %s, process_irq: %s.\n", + pitem, ucode_index, hw_status, need_reset ? "true" : "false", + process_irq ? "true" : "false"); + enc_pr(LOG_DEBUG, + "encode irq num: %d, inited: %s, process_queue_state: %d.\n", + irq_num, inited ? "true" : "false", process_queue_state); + if (use_reserve) { + enc_pr(LOG_DEBUG, + "encode use reserve memory, buffer start: 0x%x, size: %d MB.\n", + reserve_mem.buf_start, + reserve_mem.buf_size / SZ_1M); + } else { +#ifdef CONFIG_CMA + enc_pr(LOG_DEBUG, "encode check cma: %s.\n", + check_cma ? "true" : "false"); +#endif + } + return snprintf(buf, 40, "encode max instance: %d\n", max_instance); +} + +static struct class_attribute amvenc_class_attrs[] = { + __ATTR(encode_status, + S_IRUGO | S_IWUSR, + encode_status_show, + NULL), + __ATTR_NULL +}; + +static struct class amvenc_avc_class = { + .name = CLASS_NAME, + .class_attrs = amvenc_class_attrs, +}; + +s32 init_avc_device(void) +{ + s32 r = 0; + r = register_chrdev(0, DEVICE_NAME, &amvenc_avc_fops); + if (r <= 0) { + enc_pr(LOG_ERROR, "register amvenc_avc device error.\n"); + return r; + } + avc_device_major = r; + + r = class_register(&amvenc_avc_class); + if (r < 0) { + enc_pr(LOG_ERROR, "error create amvenc_avc class.\n"); + return r; + } + + amvenc_avc_dev = device_create(&amvenc_avc_class, NULL, + MKDEV(avc_device_major, 0), NULL, + DEVICE_NAME); + + if (IS_ERR(amvenc_avc_dev)) { + enc_pr(LOG_ERROR, "create amvenc_avc device error.\n"); + class_unregister(&amvenc_avc_class); + return -1; + } + return r; +} + +s32 uninit_avc_device(void) +{ + if (amvenc_avc_dev) + device_destroy(&amvenc_avc_class, MKDEV(avc_device_major, 0)); + + class_destroy(&amvenc_avc_class); + + unregister_chrdev(avc_device_major, DEVICE_NAME); + return 0; +} + +static s32 avc_mem_device_init(struct reserved_mem *rmem, struct device *dev) +{ + s32 r; + struct resource res; + if (!rmem) { + enc_pr(LOG_ERROR, + "Can not obtain I/O memory, and will allocate avc buffer!\n"); + r = -EFAULT; + return r; + } + res.start = (phys_addr_t)rmem->base; + res.end = res.start + (phys_addr_t)rmem->size - 1; + encode_manager.reserve_mem.buf_start = res.start; + encode_manager.reserve_mem.buf_size = res.end - res.start + 1; + + if (encode_manager.reserve_mem.buf_size >= + amvenc_buffspec[0].min_buffsize) { + encode_manager.max_instance = + encode_manager.reserve_mem.buf_size / + amvenc_buffspec[0].min_buffsize; + if (encode_manager.max_instance > MAX_ENCODE_INSTANCE) + encode_manager.max_instance = MAX_ENCODE_INSTANCE; + encode_manager.reserve_buff = kzalloc( + encode_manager.max_instance * + sizeof(struct Buff_s), GFP_KERNEL); + if (encode_manager.reserve_buff) { + u32 i; + struct Buff_s *reserve_buff; + u32 max_instance = encode_manager.max_instance; + for (i = 0; i < max_instance; i++) { + reserve_buff = &encode_manager.reserve_buff[i]; + reserve_buff->buf_start = + i * + amvenc_buffspec[0] + .min_buffsize + + encode_manager.reserve_mem.buf_start; + reserve_buff->buf_size = + encode_manager.reserve_mem.buf_start; + reserve_buff->used = false; + } + encode_manager.use_reserve = true; + r = 0; + enc_pr(LOG_DEBUG, + "amvenc_avc use reserve memory, buff start: 0x%x, size: 0x%x, max instance is %d\n", + encode_manager.reserve_mem.buf_start, + encode_manager.reserve_mem.buf_size, + encode_manager.max_instance); + } else { + enc_pr(LOG_ERROR, + "amvenc_avc alloc reserve buffer pointer fail. max instance is %d.\n", + encode_manager.max_instance); + encode_manager.max_instance = 0; + encode_manager.reserve_mem.buf_start = 0; + encode_manager.reserve_mem.buf_size = 0; + r = -ENOMEM; + } + } else { + enc_pr(LOG_ERROR, + "amvenc_avc memory resource too small, size is 0x%x. Need 0x%x bytes at least.\n", + encode_manager.reserve_mem.buf_size, + amvenc_buffspec[0] + .min_buffsize); + encode_manager.reserve_mem.buf_start = 0; + encode_manager.reserve_mem.buf_size = 0; + r = -ENOMEM; + } + return r; +} + +static s32 amvenc_avc_probe(struct platform_device *pdev) +{ + /* struct resource mem; */ + s32 res_irq; + s32 idx; + s32 r; + + enc_pr(LOG_INFO, "amvenc_avc probe start.\n"); + + encode_manager.this_pdev = pdev; +#ifdef CONFIG_CMA + encode_manager.check_cma = false; +#endif + encode_manager.reserve_mem.buf_start = 0; + encode_manager.reserve_mem.buf_size = 0; + encode_manager.use_reserve = false; + encode_manager.max_instance = 0; + encode_manager.reserve_buff = NULL; + + idx = of_reserved_mem_device_init(&pdev->dev); + if (idx != 0) { + enc_pr(LOG_DEBUG, + "amvenc_avc_probe -- reserved memory config fail.\n"); + } + + if (encode_manager.use_reserve == false) { +#ifndef CONFIG_CMA + enc_pr(LOG_ERROR, + "amvenc_avc memory is invaild, probe fail!\n"); + return -EFAULT; +#else + encode_manager.cma_pool_size = + (codec_mm_get_total_size() > (MIN_SIZE * 2)) ? + (MIN_SIZE * 2) : codec_mm_get_total_size(); + enc_pr(LOG_DEBUG, + "amvenc_avc - cma memory pool size: %d MB\n", + (u32)encode_manager.cma_pool_size / SZ_1M); +#endif + } + + res_irq = platform_get_irq(pdev, 0); + if (res_irq < 0) { + enc_pr(LOG_ERROR, "[%s] get irq error!", __func__); + return -EINVAL; + } + + encode_manager.irq_num = res_irq; + if (encode_wq_init()) { + kfree(encode_manager.reserve_buff); + encode_manager.reserve_buff = NULL; + enc_pr(LOG_ERROR, "encode work queue init error.\n"); + return -EFAULT; + } + + r = init_avc_device(); + enc_pr(LOG_INFO, "amvenc_avc probe end.\n"); + return r; +} + +static s32 amvenc_avc_remove(struct platform_device *pdev) +{ + kfree(encode_manager.reserve_buff); + encode_manager.reserve_buff = NULL; + if (encode_wq_uninit()) { + enc_pr(LOG_ERROR, "encode work queue uninit error.\n"); + } + uninit_avc_device(); + enc_pr(LOG_INFO, "amvenc_avc remove.\n"); + return 0; +} + +static const struct of_device_id amlogic_avcenc_dt_match[] = { + { + .compatible = "amlogic, amvenc_avc", + }, + {}, +}; + +static struct platform_driver amvenc_avc_driver = { + .probe = amvenc_avc_probe, + .remove = amvenc_avc_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = amlogic_avcenc_dt_match, + } +}; + +static struct codec_profile_t amvenc_avc_profile = { + .name = "avc", + .profile = "" +}; + +static s32 __init amvenc_avc_driver_init_module(void) +{ + enc_pr(LOG_INFO, "amvenc_avc module init\n"); + + if (platform_driver_register(&amvenc_avc_driver)) { + enc_pr(LOG_ERROR, + "failed to register amvenc_avc driver\n"); + return -ENODEV; + } + vcodec_profile_register(&amvenc_avc_profile); + return 0; +} + +static void __exit amvenc_avc_driver_remove_module(void) +{ + enc_pr(LOG_INFO, "amvenc_avc module remove.\n"); + + platform_driver_unregister(&amvenc_avc_driver); +} + +static const struct reserved_mem_ops rmem_avc_ops = { + .device_init = avc_mem_device_init, +}; + +static s32 __init avc_mem_setup(struct reserved_mem *rmem) +{ + rmem->ops = &rmem_avc_ops; + enc_pr(LOG_DEBUG, "amvenc_avc reserved mem setup.\n"); + return 0; +} + +module_param(fixed_slice_cfg, uint, 0664); +MODULE_PARM_DESC(fixed_slice_cfg, "\n fixed_slice_cfg\n"); + +module_param(clock_level, uint, 0664); +MODULE_PARM_DESC(clock_level, "\n clock_level\n"); + +module_param(encode_print_level, uint, 0664); +MODULE_PARM_DESC(encode_print_level, "\n encode_print_level\n"); + +module_param(no_timeout, uint, 0664); +MODULE_PARM_DESC(no_timeout, "\n no_timeout flag for process request\n"); + +module_param(nr_mode, int, 0664); +MODULE_PARM_DESC(nr_mode, "\n nr_mode option\n"); + +module_param(qp_table_debug, uint, 0664); +MODULE_PARM_DESC(qp_table_debug, "\n print qp table\n"); + +#ifdef MORE_MODULE_PARAM +module_param(me_mv_merge_ctl, uint, 0664); +MODULE_PARM_DESC(me_mv_merge_ctl, "\n me_mv_merge_ctl\n"); + +module_param(me_step0_close_mv, uint, 0664); +MODULE_PARM_DESC(me_step0_close_mv, "\n me_step0_close_mv\n"); + +module_param(me_f_skip_sad, uint, 0664); +MODULE_PARM_DESC(me_f_skip_sad, "\n me_f_skip_sad\n"); + +module_param(me_f_skip_weight, uint, 0664); +MODULE_PARM_DESC(me_f_skip_weight, "\n me_f_skip_weight\n"); + +module_param(me_mv_weight_01, uint, 0664); +MODULE_PARM_DESC(me_mv_weight_01, "\n me_mv_weight_01\n"); + +module_param(me_mv_weight_23, uint, 0664); +MODULE_PARM_DESC(me_mv_weight_23, "\n me_mv_weight_23\n"); + +module_param(me_sad_range_inc, uint, 0664); +MODULE_PARM_DESC(me_sad_range_inc, "\n me_sad_range_inc\n"); + +module_param(me_sad_enough_01, uint, 0664); +MODULE_PARM_DESC(me_sad_enough_01, "\n me_sad_enough_01\n"); + +module_param(me_sad_enough_23, uint, 0664); +MODULE_PARM_DESC(me_sad_enough_23, "\n me_sad_enough_23\n"); + +module_param(y_tnr_mc_en, uint, 0664); +MODULE_PARM_DESC(y_tnr_mc_en, "\n y_tnr_mc_en option\n"); +module_param(y_tnr_txt_mode, uint, 0664); +MODULE_PARM_DESC(y_tnr_txt_mode, "\n y_tnr_txt_mode option\n"); +module_param(y_tnr_mot_sad_margin, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot_sad_margin, "\n y_tnr_mot_sad_margin option\n"); +module_param(y_tnr_mot_cortxt_rate, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot_cortxt_rate, "\n y_tnr_mot_cortxt_rate option\n"); +module_param(y_tnr_mot_distxt_ofst, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot_distxt_ofst, "\n y_tnr_mot_distxt_ofst option\n"); +module_param(y_tnr_mot_distxt_rate, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot_distxt_rate, "\n y_tnr_mot_distxt_rate option\n"); +module_param(y_tnr_mot_dismot_ofst, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot_dismot_ofst, "\n y_tnr_mot_dismot_ofst option\n"); +module_param(y_tnr_mot_frcsad_lock, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot_frcsad_lock, "\n y_tnr_mot_frcsad_lock option\n"); +module_param(y_tnr_mot2alp_frc_gain, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot2alp_frc_gain, "\n y_tnr_mot2alp_frc_gain option\n"); +module_param(y_tnr_mot2alp_nrm_gain, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot2alp_nrm_gain, "\n y_tnr_mot2alp_nrm_gain option\n"); +module_param(y_tnr_mot2alp_dis_gain, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot2alp_dis_gain, "\n y_tnr_mot2alp_dis_gain option\n"); +module_param(y_tnr_mot2alp_dis_ofst, uint, 0664); +MODULE_PARM_DESC(y_tnr_mot2alp_dis_ofst, "\n y_tnr_mot2alp_dis_ofst option\n"); +module_param(y_tnr_alpha_min, uint, 0664); +MODULE_PARM_DESC(y_tnr_alpha_min, "\n y_tnr_alpha_min option\n"); +module_param(y_tnr_alpha_max, uint, 0664); +MODULE_PARM_DESC(y_tnr_alpha_max, "\n y_tnr_alpha_max option\n"); +module_param(y_tnr_deghost_os, uint, 0664); +MODULE_PARM_DESC(y_tnr_deghost_os, "\n y_tnr_deghost_os option\n"); + +module_param(c_tnr_mc_en, uint, 0664); +MODULE_PARM_DESC(c_tnr_mc_en, "\n c_tnr_mc_en option\n"); +module_param(c_tnr_txt_mode, uint, 0664); +MODULE_PARM_DESC(c_tnr_txt_mode, "\n c_tnr_txt_mode option\n"); +module_param(c_tnr_mot_sad_margin, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot_sad_margin, "\n c_tnr_mot_sad_margin option\n"); +module_param(c_tnr_mot_cortxt_rate, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot_cortxt_rate, "\n c_tnr_mot_cortxt_rate option\n"); +module_param(c_tnr_mot_distxt_ofst, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot_distxt_ofst, "\n c_tnr_mot_distxt_ofst option\n"); +module_param(c_tnr_mot_distxt_rate, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot_distxt_rate, "\n c_tnr_mot_distxt_rate option\n"); +module_param(c_tnr_mot_dismot_ofst, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot_dismot_ofst, "\n c_tnr_mot_dismot_ofst option\n"); +module_param(c_tnr_mot_frcsad_lock, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot_frcsad_lock, "\n c_tnr_mot_frcsad_lock option\n"); +module_param(c_tnr_mot2alp_frc_gain, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot2alp_frc_gain, "\n c_tnr_mot2alp_frc_gain option\n"); +module_param(c_tnr_mot2alp_nrm_gain, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot2alp_nrm_gain, "\n c_tnr_mot2alp_nrm_gain option\n"); +module_param(c_tnr_mot2alp_dis_gain, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot2alp_dis_gain, "\n c_tnr_mot2alp_dis_gain option\n"); +module_param(c_tnr_mot2alp_dis_ofst, uint, 0664); +MODULE_PARM_DESC(c_tnr_mot2alp_dis_ofst, "\n c_tnr_mot2alp_dis_ofst option\n"); +module_param(c_tnr_alpha_min, uint, 0664); +MODULE_PARM_DESC(c_tnr_alpha_min, "\n c_tnr_alpha_min option\n"); +module_param(c_tnr_alpha_max, uint, 0664); +MODULE_PARM_DESC(c_tnr_alpha_max, "\n c_tnr_alpha_max option\n"); +module_param(c_tnr_deghost_os, uint, 0664); +MODULE_PARM_DESC(c_tnr_deghost_os, "\n c_tnr_deghost_os option\n"); + +module_param(y_snr_err_norm, uint, 0664); +MODULE_PARM_DESC(y_snr_err_norm, "\n y_snr_err_norm option\n"); +module_param(y_snr_gau_bld_core, uint, 0664); +MODULE_PARM_DESC(y_snr_gau_bld_core, "\n y_snr_gau_bld_core option\n"); +module_param(y_snr_gau_bld_ofst, int, 0664); +MODULE_PARM_DESC(y_snr_gau_bld_ofst, "\n y_snr_gau_bld_ofst option\n"); +module_param(y_snr_gau_bld_rate, uint, 0664); +MODULE_PARM_DESC(y_snr_gau_bld_rate, "\n y_snr_gau_bld_rate option\n"); +module_param(y_snr_gau_alp0_min, uint, 0664); +MODULE_PARM_DESC(y_snr_gau_alp0_min, "\n y_snr_gau_alp0_min option\n"); +module_param(y_snr_gau_alp0_max, uint, 0664); +MODULE_PARM_DESC(y_snr_gau_alp0_max, "\n y_snr_gau_alp0_max option\n"); +module_param(y_bld_beta2alp_rate, uint, 0664); +MODULE_PARM_DESC(y_bld_beta2alp_rate, "\n y_bld_beta2alp_rate option\n"); +module_param(y_bld_beta_min, uint, 0664); +MODULE_PARM_DESC(y_bld_beta_min, "\n y_bld_beta_min option\n"); +module_param(y_bld_beta_max, uint, 0664); +MODULE_PARM_DESC(y_bld_beta_max, "\n y_bld_beta_max option\n"); + +module_param(c_snr_err_norm, uint, 0664); +MODULE_PARM_DESC(c_snr_err_norm, "\n c_snr_err_norm option\n"); +module_param(c_snr_gau_bld_core, uint, 0664); +MODULE_PARM_DESC(c_snr_gau_bld_core, "\n c_snr_gau_bld_core option\n"); +module_param(c_snr_gau_bld_ofst, int, 0664); +MODULE_PARM_DESC(c_snr_gau_bld_ofst, "\n c_snr_gau_bld_ofst option\n"); +module_param(c_snr_gau_bld_rate, uint, 0664); +MODULE_PARM_DESC(c_snr_gau_bld_rate, "\n c_snr_gau_bld_rate option\n"); +module_param(c_snr_gau_alp0_min, uint, 0664); +MODULE_PARM_DESC(c_snr_gau_alp0_min, "\n c_snr_gau_alp0_min option\n"); +module_param(c_snr_gau_alp0_max, uint, 0664); +MODULE_PARM_DESC(c_snr_gau_alp0_max, "\n c_snr_gau_alp0_max option\n"); +module_param(c_bld_beta2alp_rate, uint, 0664); +MODULE_PARM_DESC(c_bld_beta2alp_rate, "\n c_bld_beta2alp_rate option\n"); +module_param(c_bld_beta_min, uint, 0664); +MODULE_PARM_DESC(c_bld_beta_min, "\n c_bld_beta_min option\n"); +module_param(c_bld_beta_max, uint, 0664); +MODULE_PARM_DESC(c_bld_beta_max, "\n c_bld_beta_max option\n"); +#endif + +module_init(amvenc_avc_driver_init_module); +module_exit(amvenc_avc_driver_remove_module); +RESERVEDMEM_OF_DECLARE(amvenc_avc, "amlogic, amvenc-memory", avc_mem_setup); + +MODULE_DESCRIPTION("AMLOGIC AVC Video Encoder Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("simon.zheng "); diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h new file mode 100644 index 000000000000..db4f255a2f49 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h @@ -0,0 +1,465 @@ +/* + * drivers/amlogic/amports/encoder.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef __H264_H__ +#define __H264_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_AM_GE2D +#include +#endif + +#define AMVENC_DEVINFO_M8 "AML-M8" +#define AMVENC_DEVINFO_G9 "AML-G9" +#define AMVENC_DEVINFO_GXBB "AML-GXBB" +#define AMVENC_DEVINFO_GXTVBB "AML-GXTVBB" +#define AMVENC_DEVINFO_GXL "AML-GXL" + +#define HCODEC_IRQ_MBOX_CLR HCODEC_ASSIST_MBOX2_CLR_REG +#define HCODEC_IRQ_MBOX_MASK HCODEC_ASSIST_MBOX2_MASK + +/* M8: 2550/10 = 255M GX: 2000/10 = 200M */ +#define HDEC_L0() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (2 << 25) | (1 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) +/* M8: 2550/8 = 319M GX: 2000/8 = 250M */ +#define HDEC_L1() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (0 << 25) | (1 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) +/* M8: 2550/7 = 364M GX: 2000/7 = 285M */ +#define HDEC_L2() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (3 << 25) | (0 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) +/* M8: 2550/6 = 425M GX: 2000/6 = 333M */ +#define HDEC_L3() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (1 << 25) | (1 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) +/* M8: 2550/5 = 510M GX: 2000/5 = 400M */ +#define HDEC_L4() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (2 << 25) | (0 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) +/* M8: 2550/4 = 638M GX: 2000/4 = 500M */ +#define HDEC_L5() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (0 << 25) | (0 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) +/* M8: 2550/3 = 850M GX: 2000/3 = 667M */ +#define HDEC_L6() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ + (1 << 25) | (0 << 16) | (1 << 24) | \ + (0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL))) + +#define hvdec_clock_enable(level) \ + do { \ + if (level == 0) \ + HDEC_L0(); \ + else if (level == 1) \ + HDEC_L1(); \ + else if (level == 2) \ + HDEC_L2(); \ + else if (level == 3) \ + HDEC_L3(); \ + else if (level == 4) \ + HDEC_L4(); \ + else if (level == 5) \ + HDEC_L5(); \ + else if (level == 6) \ + HDEC_L6(); \ + WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); \ + } while (0) + +#define hvdec_clock_disable() \ + do { \ + WRITE_VREG_BITS(DOS_GCLK_EN0, 0, 12, 15); \ + WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1); \ + } while (0) + +#define LOG_ALL 0 +#define LOG_INFO 1 +#define LOG_DEBUG 2 +#define LOG_ERROR 3 + +#define enc_pr(level, x...) \ + do { \ + if (level >= encode_print_level) \ + printk(x); \ + } while (0) + +#define AMVENC_AVC_IOC_MAGIC 'E' + +#define AMVENC_AVC_IOC_GET_DEVINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0xf0, u32) +#define AMVENC_AVC_IOC_MAX_INSTANCE _IOW(AMVENC_AVC_IOC_MAGIC, 0xf1, u32) + +#define AMVENC_AVC_IOC_GET_ADDR _IOW(AMVENC_AVC_IOC_MAGIC, 0x00, u32) +#define AMVENC_AVC_IOC_INPUT_UPDATE _IOW(AMVENC_AVC_IOC_MAGIC, 0x01, u32) +#define AMVENC_AVC_IOC_NEW_CMD _IOW(AMVENC_AVC_IOC_MAGIC, 0x02, u32) +#define AMVENC_AVC_IOC_GET_STAGE _IOW(AMVENC_AVC_IOC_MAGIC, 0x03, u32) +#define AMVENC_AVC_IOC_GET_OUTPUT_SIZE _IOW(AMVENC_AVC_IOC_MAGIC, 0x04, u32) +#define AMVENC_AVC_IOC_CONFIG_INIT _IOW(AMVENC_AVC_IOC_MAGIC, 0x05, u32) +#define AMVENC_AVC_IOC_FLUSH_CACHE _IOW(AMVENC_AVC_IOC_MAGIC, 0x06, u32) +#define AMVENC_AVC_IOC_FLUSH_DMA _IOW(AMVENC_AVC_IOC_MAGIC, 0x07, u32) +#define AMVENC_AVC_IOC_GET_BUFFINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0x08, u32) +#define AMVENC_AVC_IOC_SUBMIT _IOW(AMVENC_AVC_IOC_MAGIC, 0x09, u32) +#define AMVENC_AVC_IOC_READ_CANVAS _IOW(AMVENC_AVC_IOC_MAGIC, 0x0a, u32) + + +#define IE_PIPPELINE_BLOCK_SHIFT 0 +#define IE_PIPPELINE_BLOCK_MASK 0x1f +#define ME_PIXEL_MODE_SHIFT 5 +#define ME_PIXEL_MODE_MASK 0x3 + +enum amvenc_mem_type_e { + LOCAL_BUFF = 0, + CANVAS_BUFF, + PHYSICAL_BUFF, + MAX_BUFF_TYPE +}; + +enum amvenc_frame_fmt_e { + FMT_YUV422_SINGLE = 0, + FMT_YUV444_SINGLE, + FMT_NV21, + FMT_NV12, + FMT_YUV420, + FMT_YUV444_PLANE, + FMT_RGB888, + FMT_RGB888_PLANE, + FMT_RGB565, + FMT_RGBA8888, + FMT_YUV422_12BIT, + FMT_YUV444_10BIT, + FMT_YUV422_10BIT, + MAX_FRAME_FMT +}; + +#define MAX_ENCODE_REQUEST 8 /* 64 */ + +#define MAX_ENCODE_INSTANCE 8 /* 64 */ + +#define ENCODE_PROCESS_QUEUE_START 0 +#define ENCODE_PROCESS_QUEUE_STOP 1 + +#define AMVENC_FLUSH_FLAG_INPUT 0x1 +#define AMVENC_FLUSH_FLAG_OUTPUT 0x2 +#define AMVENC_FLUSH_FLAG_REFERENCE 0x4 +#define AMVENC_FLUSH_FLAG_INTRA_INFO 0x8 +#define AMVENC_FLUSH_FLAG_INTER_INFO 0x10 +#define AMVENC_FLUSH_FLAG_QP 0x20 +#define AMVENC_FLUSH_FLAG_DUMP 0x40 +#define AMVENC_FLUSH_FLAG_CBR 0x80 + +#define ENCODER_BUFFER_INPUT 0 +#define ENCODER_BUFFER_REF0 1 +#define ENCODER_BUFFER_REF1 2 +#define ENCODER_BUFFER_OUTPUT 3 +#define ENCODER_BUFFER_INTER_INFO 4 +#define ENCODER_BUFFER_INTRA_INFO 5 +#define ENCODER_BUFFER_QP 6 +#define ENCODER_BUFFER_DUMP 7 +#define ENCODER_BUFFER_CBR 8 + +struct encode_wq_s; + +struct encode_request_s { + u32 quant; + u32 cmd; + u32 ucode_mode; + + u32 src; + + u32 framesize; + + u32 me_weight; + u32 i4_weight; + u32 i16_weight; + + u32 crop_top; + u32 crop_bottom; + u32 crop_left; + u32 crop_right; + u32 src_w; + u32 src_h; + u32 scale_enable; + + u32 nr_mode; + u32 flush_flag; + u32 timeout; + enum amvenc_mem_type_e type; + enum amvenc_frame_fmt_e fmt; + struct encode_wq_s *parent; +}; + +struct encode_queue_item_s { + struct list_head list; + struct encode_request_s request; +}; + +struct Buff_s { + u32 buf_start; + u32 buf_size; + bool used; +}; + +struct BuffInfo_s { + u32 lev_id; + u32 min_buffsize; + u32 max_width; + u32 max_height; + struct Buff_s dct; + struct Buff_s dec0_y; + struct Buff_s dec0_uv; + struct Buff_s dec1_y; + struct Buff_s dec1_uv; + struct Buff_s assit; + struct Buff_s bitstream; + struct Buff_s scale_buff; + struct Buff_s dump_info; + struct Buff_s cbr_info; +}; + +struct encode_meminfo_s { + u32 buf_start; + u32 buf_size; + + u32 BitstreamStart; + u32 BitstreamEnd; + + /*input buffer define*/ + u32 dct_buff_start_addr; + u32 dct_buff_end_addr; + + /*microcode assitant buffer*/ + u32 assit_buffer_offset; + + u32 scaler_buff_start_addr; + + u32 dump_info_ddr_start_addr; + u32 dump_info_ddr_size; + + u32 cbr_info_ddr_start_addr; + u32 cbr_info_ddr_size; + + s32 dblk_buf_canvas; + s32 ref_buf_canvas; + struct BuffInfo_s bufspec; +#ifdef CONFIG_CMA + struct page *venc_pages; +#endif +}; + +struct encode_picinfo_s { + u32 encoder_width; + u32 encoder_height; + + u32 rows_per_slice; + + u32 idr_pic_id; /* need reset as 0 for IDR */ + u32 frame_number; /* need plus each frame */ + /* need reset as 0 for IDR and plus 2 for NON-IDR */ + u32 pic_order_cnt_lsb; + + u32 log2_max_pic_order_cnt_lsb; + u32 log2_max_frame_num; + u32 init_qppicture; +}; + +struct encode_cbr_s { + u16 block_w; + u16 block_h; + u16 long_th; + u8 start_tbl_id; + u8 short_shift; + u8 long_mb_num; +}; + +struct encode_wq_s { + struct list_head list; + + /* dev info */ + u32 ucode_index; + u32 hw_status; + u32 output_size; + + u32 sps_size; + u32 pps_size; + + u32 me_weight; + u32 i4_weight; + u32 i16_weight; + + u32 quant_tbl_i4[8]; + u32 quant_tbl_i16[8]; + u32 quant_tbl_me[8]; + + struct encode_meminfo_s mem; + struct encode_picinfo_s pic; + struct encode_request_s request; + struct encode_cbr_s cbr_info; + atomic_t request_ready; + wait_queue_head_t request_complete; +}; + +struct encode_event_s { + wait_queue_head_t hw_complete; + struct completion process_complete; + spinlock_t sem_lock; /* for queue switch and create destroy queue. */ + struct completion request_in_com; +}; + +struct encode_manager_s { + struct list_head wq; + struct list_head process_queue; + struct list_head free_queue; + + u32 encode_hw_status; + u32 process_queue_state; + s32 irq_num; + u32 wq_count; + u32 ucode_index; + u32 max_instance; +#ifdef CONFIG_AM_GE2D + struct ge2d_context_s *context; +#endif + bool irq_requested; + bool need_reset; + bool process_irq; + bool inited; /* power on encode */ + bool remove_flag; /* remove wq; */ + bool uninit_flag; /* power off encode */ + bool use_reserve; + +#ifdef CONFIG_CMA + bool check_cma; + ulong cma_pool_size; +#endif + struct platform_device *this_pdev; + struct Buff_s *reserve_buff; + struct encode_wq_s *current_wq; + struct encode_wq_s *last_wq; + struct encode_queue_item_s *current_item; + struct task_struct *encode_thread; + struct Buff_s reserve_mem; + struct encode_event_s event; + struct tasklet_struct encode_tasklet; +}; + +extern s32 encode_wq_add_request(struct encode_wq_s *wq); +extern struct encode_wq_s *create_encode_work_queue(void); +extern s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue); + +/******************************************** + * AV Scratch Register Re-Define +********************************************/ +#define ENCODER_STATUS HCODEC_HENC_SCRATCH_0 +#define MEM_OFFSET_REG HCODEC_HENC_SCRATCH_1 +#define DEBUG_REG HCODEC_HENC_SCRATCH_2 +#define IDR_PIC_ID HCODEC_HENC_SCRATCH_5 +#define FRAME_NUMBER HCODEC_HENC_SCRATCH_6 +#define PIC_ORDER_CNT_LSB HCODEC_HENC_SCRATCH_7 +#define LOG2_MAX_PIC_ORDER_CNT_LSB HCODEC_HENC_SCRATCH_8 +#define LOG2_MAX_FRAME_NUM HCODEC_HENC_SCRATCH_9 +#define ANC0_BUFFER_ID HCODEC_HENC_SCRATCH_A +#define QPPICTURE HCODEC_HENC_SCRATCH_B + +#define IE_ME_MB_TYPE HCODEC_HENC_SCRATCH_D + +/* bit 0-4, IE_PIPPELINE_BLOCK + * bit 5 me half pixel in m8 + * disable i4x4 in gxbb + * bit 6 me step2 sub pixel in m8 + * disable i16x16 in gxbb + */ +#define IE_ME_MODE HCODEC_HENC_SCRATCH_E +#define IE_REF_SEL HCODEC_HENC_SCRATCH_F + +/* [31:0] NUM_ROWS_PER_SLICE_P */ +/* [15:0] NUM_ROWS_PER_SLICE_I */ +#define FIXED_SLICE_CFG HCODEC_HENC_SCRATCH_L + +/* For GX */ +#define INFO_DUMP_START_ADDR HCODEC_HENC_SCRATCH_I + +/* For CBR */ +#define H264_ENC_CBR_TABLE_ADDR HCODEC_HENC_SCRATCH_3 +#define H264_ENC_CBR_MB_SIZE_ADDR HCODEC_HENC_SCRATCH_4 +/* Bytes(Float) * 256 */ +#define H264_ENC_CBR_CTL HCODEC_HENC_SCRATCH_G +/* [31:28] : init qp table idx */ +/* [27:24] : short_term adjust shift */ +/* [23:16] : Long_term MB_Number between adjust, */ +/* [15:0] Long_term adjust threshold(Bytes) */ +#define H264_ENC_CBR_TARGET_SIZE HCODEC_HENC_SCRATCH_H +/* Bytes(Float) * 256 */ +#define H264_ENC_CBR_PREV_BYTES HCODEC_HENC_SCRATCH_J +#define H264_ENC_CBR_REGION_SIZE HCODEC_HENC_SCRATCH_J + +/* --------------------------------------------------- */ +/* ENCODER_STATUS define */ +/* --------------------------------------------------- */ +#define ENCODER_IDLE 0 +#define ENCODER_SEQUENCE 1 +#define ENCODER_PICTURE 2 +#define ENCODER_IDR 3 +#define ENCODER_NON_IDR 4 +#define ENCODER_MB_HEADER 5 +#define ENCODER_MB_DATA 6 + +#define ENCODER_SEQUENCE_DONE 7 +#define ENCODER_PICTURE_DONE 8 +#define ENCODER_IDR_DONE 9 +#define ENCODER_NON_IDR_DONE 10 +#define ENCODER_MB_HEADER_DONE 11 +#define ENCODER_MB_DATA_DONE 12 + +#define ENCODER_NON_IDR_INTRA 13 +#define ENCODER_NON_IDR_INTER 14 + +#define ENCODER_ERROR 0xff + +/******************************************** +* defines for H.264 mb_type +********************************************/ +#define HENC_MB_Type_PBSKIP 0x0 +#define HENC_MB_Type_PSKIP 0x0 +#define HENC_MB_Type_BSKIP_DIRECT 0x0 +#define HENC_MB_Type_P16x16 0x1 +#define HENC_MB_Type_P16x8 0x2 +#define HENC_MB_Type_P8x16 0x3 +#define HENC_MB_Type_SMB8x8 0x4 +#define HENC_MB_Type_SMB8x4 0x5 +#define HENC_MB_Type_SMB4x8 0x6 +#define HENC_MB_Type_SMB4x4 0x7 +#define HENC_MB_Type_P8x8 0x8 +#define HENC_MB_Type_I4MB 0x9 +#define HENC_MB_Type_I16MB 0xa +#define HENC_MB_Type_IBLOCK 0xb +#define HENC_MB_Type_SI4MB 0xc +#define HENC_MB_Type_I8MB 0xd +#define HENC_MB_Type_IPCM 0xe +#define HENC_MB_Type_AUTO 0xf + +#define HENC_MB_CBP_AUTO 0xff +#define HENC_SKIP_RUN_AUTO 0xffff + + +extern bool amvenc_avc_on(void); +#endif diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile b/drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile new file mode 100644 index 000000000000..e7414bfb8614 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/Makefile @@ -0,0 +1 @@ +obj-m += vpu.o diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h new file mode 100644 index 000000000000..cb0112e23d92 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h @@ -0,0 +1,661 @@ +/* + * vmm.h + * + * memory allocator for VPU + * + * Copyright (C) 2006 - 2013 CHIPS&MEDIA INC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef __CNM_VIDEO_MEMORY_MANAGEMENT_H__ +#define __CNM_VIDEO_MEMORY_MANAGEMENT_H__ + +#define VMEM_PAGE_SIZE (16 * 1024) +#define MAKE_KEY(_a, _b) (((vmem_key_t)_a) << 32 | _b) +#define KEY_TO_VALUE(_key) (_key >> 32) + +#define VMEM_P_ALLOC(_x) vmalloc(_x) +#define VMEM_P_FREE(_x) vfree(_x) + +#define VMEM_ASSERT \ + pr_info("VMEM_ASSERT at %s:%d\n", __FILE__, __LINE__) + + +#define VMEM_HEIGHT(_tree) (_tree == NULL ? -1 : _tree->height) + +#define MAX(_a, _b) (_a >= _b ? _a : _b) + +struct avl_node_t; +#define vmem_key_t unsigned long long + +struct vmem_info_t { + ulong total_pages; + ulong alloc_pages; + ulong free_pages; + ulong page_size; +}; + +struct page_t { + s32 pageno; + ulong addr; + s32 used; + s32 alloc_pages; + s32 first_pageno; +}; + +struct avl_node_t { + vmem_key_t key; + s32 height; + struct page_t *page; + struct avl_node_t *left; + struct avl_node_t *right; +}; + +struct video_mm_t { + struct avl_node_t *free_tree; + struct avl_node_t *alloc_tree; + struct page_t *page_list; + s32 num_pages; + ulong base_addr; + ulong mem_size; + s32 free_page_count; + s32 alloc_page_count; +}; + +enum rotation_dir_t { + LEFT, + RIGHT +}; + +struct avl_node_data_t { + s32 key; + struct page_t *page; +}; + +static struct avl_node_t *make_avl_node( + vmem_key_t key, + struct page_t *page) +{ + struct avl_node_t *node = + (struct avl_node_t *)VMEM_P_ALLOC(sizeof(struct avl_node_t)); + node->key = key; + node->page = page; + node->height = 0; + node->left = NULL; + node->right = NULL; + return node; +} + +static s32 get_balance_factor(struct avl_node_t *tree) +{ + s32 factor = 0; + if (tree) + factor = VMEM_HEIGHT(tree->right) - VMEM_HEIGHT(tree->left); + return factor; +} + +/* + * Left Rotation + * + * A B + * \ / \ + * B => A C + * / \ \ + * D C D + * + */ +static struct avl_node_t *rotation_left(struct avl_node_t *tree) +{ + struct avl_node_t *rchild; + struct avl_node_t *lchild; + + if (tree == NULL) + return NULL; + + rchild = tree->right; + if (rchild == NULL) + return tree; + + lchild = rchild->left; + rchild->left = tree; + tree->right = lchild; + + tree->height = + MAX(VMEM_HEIGHT(tree->left), VMEM_HEIGHT(tree->right)) + 1; + rchild->height = + MAX(VMEM_HEIGHT(rchild->left), VMEM_HEIGHT(rchild->right)) + 1; + return rchild; +} + + +/* + * Reft Rotation + * + * A B + * \ / \ + * B => D A + * / \ / + * D C C + * + */ +static struct avl_node_t *rotation_right(struct avl_node_t *tree) +{ + struct avl_node_t *rchild; + struct avl_node_t *lchild; + + if (tree == NULL) + return NULL; + + lchild = tree->left; + if (lchild == NULL) + return NULL; + + rchild = lchild->right; + lchild->right = tree; + tree->left = rchild; + + tree->height = + MAX(VMEM_HEIGHT(tree->left), + VMEM_HEIGHT(tree->right)) + 1; + lchild->height = + MAX(VMEM_HEIGHT(lchild->left), + VMEM_HEIGHT(lchild->right)) + 1; + return lchild; +} + +static struct avl_node_t *do_balance(struct avl_node_t *tree) +{ + s32 bfactor = 0, child_bfactor; + bfactor = get_balance_factor(tree); + if (bfactor >= 2) { + child_bfactor = get_balance_factor(tree->right); + if (child_bfactor == 1 || child_bfactor == 0) { + tree = rotation_left(tree); + } else if (child_bfactor == -1) { + tree->right = rotation_right(tree->right); + tree = rotation_left(tree); + } else { + pr_info( + "invalid balancing factor: %d\n", + child_bfactor); + VMEM_ASSERT; + return NULL; + } + } else if (bfactor <= -2) { + child_bfactor = get_balance_factor(tree->left); + if (child_bfactor == -1 || child_bfactor == 0) { + tree = rotation_right(tree); + } else if (child_bfactor == 1) { + tree->left = rotation_left(tree->left); + tree = rotation_right(tree); + } else { + pr_info( + "invalid balancing factor: %d\n", + child_bfactor); + VMEM_ASSERT; + return NULL; + } + } + return tree; +} + +static struct avl_node_t *unlink_end_node( + struct avl_node_t *tree, + s32 dir, + struct avl_node_t **found_node) +{ + struct avl_node_t *node; + *found_node = NULL; + + if (tree == NULL) + return NULL; + + if (dir == LEFT) { + if (tree->left == NULL) { + *found_node = tree; + return NULL; + } + } else { + if (tree->right == NULL) { + *found_node = tree; + return NULL; + } + } + + if (dir == LEFT) { + node = tree->left; + tree->left = unlink_end_node(tree->left, LEFT, found_node); + if (tree->left == NULL) { + tree->left = (*found_node)->right; + (*found_node)->left = NULL; + (*found_node)->right = NULL; + } + } else { + node = tree->right; + tree->right = unlink_end_node(tree->right, RIGHT, found_node); + if (tree->right == NULL) { + tree->right = (*found_node)->left; + (*found_node)->left = NULL; + (*found_node)->right = NULL; + } + } + tree->height = + MAX(VMEM_HEIGHT(tree->left), VMEM_HEIGHT(tree->right)) + 1; + return do_balance(tree); +} + + +static struct avl_node_t *avltree_insert( + struct avl_node_t *tree, + vmem_key_t key, + struct page_t *page) +{ + if (tree == NULL) { + tree = make_avl_node(key, page); + } else { + if (key >= tree->key) + tree->right = + avltree_insert(tree->right, key, page); + else + tree->left = + avltree_insert(tree->left, key, page); + } + tree = do_balance(tree); + tree->height = + MAX(VMEM_HEIGHT(tree->left), VMEM_HEIGHT(tree->right)) + 1; + return tree; +} + +static struct avl_node_t *do_unlink(struct avl_node_t *tree) +{ + struct avl_node_t *node; + struct avl_node_t *end_node; + node = unlink_end_node(tree->right, LEFT, &end_node); + if (node) { + tree->right = node; + } else { + node = + unlink_end_node(tree->left, RIGHT, &end_node); + if (node) + tree->left = node; + } + + if (node == NULL) { + node = tree->right ? tree->right : tree->left; + end_node = node; + } + + if (end_node) { + end_node->left = + (tree->left != end_node) ? + tree->left : end_node->left; + end_node->right = + (tree->right != end_node) ? + tree->right : end_node->right; + end_node->height = + MAX(VMEM_HEIGHT(end_node->left), + VMEM_HEIGHT(end_node->right)) + 1; + } + tree = end_node; + return tree; +} + +static struct avl_node_t *avltree_remove( + struct avl_node_t *tree, + struct avl_node_t **found_node, + vmem_key_t key) +{ + *found_node = NULL; + if (tree == NULL) { + pr_info("failed to find key %d\n", (s32)key); + return NULL; + } + + if (key == tree->key) { + *found_node = tree; + tree = do_unlink(tree); + } else if (key > tree->key) { + tree->right = + avltree_remove(tree->right, found_node, key); + } else { + tree->left = + avltree_remove(tree->left, found_node, key); + } + + if (tree) + tree->height = + MAX(VMEM_HEIGHT(tree->left), + VMEM_HEIGHT(tree->right)) + 1; + + tree = do_balance(tree); + return tree; +} + +void avltree_free(struct avl_node_t *tree) +{ + if (tree == NULL) + return; + if (tree->left == NULL && tree->right == NULL) { + VMEM_P_FREE(tree); + return; + } + + avltree_free(tree->left); + tree->left = NULL; + avltree_free(tree->right); + tree->right = NULL; + VMEM_P_FREE(tree); +} + +static struct avl_node_t *remove_approx_value( + struct avl_node_t *tree, + struct avl_node_t **found, + vmem_key_t key) +{ + *found = NULL; + if (tree == NULL) + return NULL; + + if (key == tree->key) { + *found = tree; + tree = do_unlink(tree); + } else if (key > tree->key) { + tree->right = remove_approx_value(tree->right, found, key); + } else { + tree->left = remove_approx_value(tree->left, found, key); + if (*found == NULL) { + *found = tree; + tree = do_unlink(tree); + } + } + if (tree) + tree->height = + MAX(VMEM_HEIGHT(tree->left), + VMEM_HEIGHT(tree->right)) + 1; + tree = do_balance(tree); + return tree; +} + +static void set_blocks_free( + struct video_mm_t *mm, + s32 pageno, + s32 npages) +{ + s32 last_pageno = pageno + npages - 1; + s32 i; + struct page_t *page; + struct page_t *last_page; + + if (npages == 0) + VMEM_ASSERT; + + if (last_pageno >= mm->num_pages) { + pr_info( + "set_blocks_free: invalid last page number: %d\n", + last_pageno); + VMEM_ASSERT; + return; + } + + for (i = pageno; i <= last_pageno; i++) { + mm->page_list[i].used = 0; + mm->page_list[i].alloc_pages = 0; + mm->page_list[i].first_pageno = -1; + } + + page = &mm->page_list[pageno]; + page->alloc_pages = npages; + last_page = &mm->page_list[last_pageno]; + last_page->first_pageno = pageno; + mm->free_tree = + avltree_insert(mm->free_tree, MAKE_KEY(npages, pageno), page); +} + +static void set_blocks_alloc( + struct video_mm_t *mm, + s32 pageno, + s32 npages) +{ + s32 last_pageno = pageno + npages - 1; + s32 i; + struct page_t *page; + struct page_t *last_page; + + if (last_pageno >= mm->num_pages) { + pr_info( + "set_blocks_free: invalid last page number: %d\n", + last_pageno); + VMEM_ASSERT; + return; + } + + for (i = pageno; i <= last_pageno; i++) { + mm->page_list[i].used = 1; + mm->page_list[i].alloc_pages = 0; + mm->page_list[i].first_pageno = -1; + } + + page = &mm->page_list[pageno]; + page->alloc_pages = npages; + last_page = &mm->page_list[last_pageno]; + last_page->first_pageno = pageno; + mm->alloc_tree = + avltree_insert(mm->alloc_tree, MAKE_KEY(page->addr, 0), page); +} + + +s32 vmem_init(struct video_mm_t *mm, ulong addr, ulong size) +{ + s32 i; + + if (NULL == mm) + return -1; + + mm->base_addr = (addr + (VMEM_PAGE_SIZE - 1)) + & ~(VMEM_PAGE_SIZE - 1); + mm->mem_size = size & ~VMEM_PAGE_SIZE; + mm->num_pages = mm->mem_size / VMEM_PAGE_SIZE; + mm->free_tree = NULL; + mm->alloc_tree = NULL; + mm->free_page_count = mm->num_pages; + mm->alloc_page_count = 0; + mm->page_list = + (struct page_t *)VMEM_P_ALLOC( + mm->num_pages * sizeof(struct page_t)); + if (mm->page_list == NULL) { + pr_err("%s:%d failed to kmalloc(%ld)\n", + __func__, __LINE__, + mm->num_pages * sizeof(struct page_t)); + return -1; + } + + for (i = 0; i < mm->num_pages; i++) { + mm->page_list[i].pageno = i; + mm->page_list[i].addr = + mm->base_addr + i * VMEM_PAGE_SIZE; + mm->page_list[i].alloc_pages = 0; + mm->page_list[i].used = 0; + mm->page_list[i].first_pageno = -1; + } + set_blocks_free(mm, 0, mm->num_pages); + return 0; +} + +s32 vmem_exit(struct video_mm_t *mm) +{ + if (mm == NULL) { + pr_info("vmem_exit: invalid handle\n"); + return -1; + } + + if (mm->free_tree) + avltree_free(mm->free_tree); + if (mm->alloc_tree) + avltree_free(mm->alloc_tree); + + if (mm->page_list) { + VMEM_P_FREE(mm->page_list); + mm->page_list = NULL; + } + + mm->base_addr = 0; + mm->mem_size = 0; + mm->num_pages = 0; + mm->page_list = NULL; + mm->free_tree = NULL; + mm->alloc_tree = NULL; + mm->free_page_count = 0; + mm->alloc_page_count = 0; + return 0; +} + +ulong vmem_alloc(struct video_mm_t *mm, s32 size, ulong pid) +{ + struct avl_node_t *node; + struct page_t *free_page; + s32 npages, free_size; + s32 alloc_pageno; + ulong ptr; + + if (mm == NULL) { + pr_info("vmem_alloc: invalid handle\n"); + return -1; + } + + if (size <= 0) + return -1; + + npages = (size + VMEM_PAGE_SIZE - 1) / VMEM_PAGE_SIZE; + mm->free_tree = remove_approx_value(mm->free_tree, + &node, MAKE_KEY(npages, 0)); + + if (node == NULL) + return -1; + + free_page = node->page; + free_size = KEY_TO_VALUE(node->key); + alloc_pageno = free_page->pageno; + set_blocks_alloc(mm, alloc_pageno, npages); + if (npages != free_size) { + s32 free_pageno = alloc_pageno + npages; + set_blocks_free(mm, free_pageno, (free_size-npages)); + } + VMEM_P_FREE(node); + + ptr = mm->page_list[alloc_pageno].addr; + mm->alloc_page_count += npages; + mm->free_page_count -= npages; + return ptr; +} + +s32 vmem_free(struct video_mm_t *mm, ulong ptr, ulong pid) +{ + ulong addr; + struct avl_node_t *found; + struct page_t *page; + s32 pageno, prev_free_pageno, next_free_pageno; + s32 prev_size, next_size; + s32 merge_page_no, merge_page_size, free_page_size; + + if (mm == NULL) { + pr_info("vmem_free: invalid handle\n"); + return -1; + } + + addr = ptr; + mm->alloc_tree = avltree_remove(mm->alloc_tree, &found, + MAKE_KEY(addr, 0)); + + if (found == NULL) { + pr_info("vmem_free: 0x%08x not found\n", (s32)addr); + VMEM_ASSERT; + return -1; + } + + /* find previous free block */ + page = found->page; + pageno = page->pageno; + free_page_size = page->alloc_pages; + prev_free_pageno = pageno - 1; + prev_size = -1; + if (prev_free_pageno >= 0) { + if (mm->page_list[prev_free_pageno].used == 0) { + prev_free_pageno = + mm->page_list[prev_free_pageno].first_pageno; + prev_size = + mm->page_list[prev_free_pageno].alloc_pages; + } + } + + /* find next free block */ + next_free_pageno = pageno + page->alloc_pages; + next_free_pageno = + (next_free_pageno == mm->num_pages) ? -1 : next_free_pageno; + next_size = -1; + if (next_free_pageno >= 0) { + if (mm->page_list[next_free_pageno].used == 0) { + next_size = + mm->page_list[next_free_pageno].alloc_pages; + } + } + VMEM_P_FREE(found); + + /* merge */ + merge_page_no = page->pageno; + merge_page_size = page->alloc_pages; + if (prev_size >= 0) { + mm->free_tree = avltree_remove(mm->free_tree, &found, + MAKE_KEY(prev_size, prev_free_pageno)); + if (found == NULL) { + VMEM_ASSERT; + return -1; + } + merge_page_no = found->page->pageno; + merge_page_size += found->page->alloc_pages; + VMEM_P_FREE(found); + } + if (next_size >= 0) { + mm->free_tree = avltree_remove(mm->free_tree, &found, + MAKE_KEY(next_size, next_free_pageno)); + if (found == NULL) { + VMEM_ASSERT; + return -1; + } + merge_page_size += found->page->alloc_pages; + VMEM_P_FREE(found); + } + page->alloc_pages = 0; + page->first_pageno = -1; + set_blocks_free(mm, merge_page_no, merge_page_size); + mm->alloc_page_count -= free_page_size; + mm->free_page_count += free_page_size; + return 0; +} + +s32 vmem_get_info(struct video_mm_t *mm, struct vmem_info_t *info) +{ + if (mm == NULL) { + pr_info("vmem_get_info: invalid handle\n"); + return -1; + } + + if (info == NULL) + return -1; + + info->total_pages = mm->num_pages; + info->alloc_pages = mm->alloc_page_count; + info->free_pages = mm->free_page_count; + info->page_size = VMEM_PAGE_SIZE; + return 0; +} +#endif /* __CNM_VIDEO_MEMORY_MANAGEMENT_H__ */ diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c new file mode 100644 index 000000000000..26c40fd1c428 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c @@ -0,0 +1,1997 @@ +/* + * vpu.c + * + * linux device driver for VPU. + * + * Copyright (C) 2006 - 2013 CHIPS&MEDIA INC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../../../common/media_clock/switch/amports_gate.h" + +#include "vpu.h" +#include "vmm.h" + +/* definitions to be changed as customer configuration */ +/* if you want to have clock gating scheme frame by frame */ +/* #define VPU_SUPPORT_CLOCK_CONTROL */ + +#define VPU_PLATFORM_DEVICE_NAME "HevcEnc" +#define VPU_DEV_NAME "HevcEnc" +#define VPU_CLASS_NAME "HevcEnc" + +#ifndef VM_RESERVED /*for kernel up to 3.7.0 version*/ +#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) +#endif + +#define VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE (64 * SZ_1M) + +#define LOG_ALL 0 +#define LOG_INFO 1 +#define LOG_DEBUG 2 +#define LOG_ERROR 3 + +#define enc_pr(level, x...) \ + do { \ + if (level >= print_level) \ + printk(x); \ + } while (0) + +static s32 print_level = LOG_DEBUG; +static s32 clock_level = 4; + +static struct video_mm_t s_vmem; +static struct vpudrv_buffer_t s_video_memory = {0}; +static bool use_reserve; +static ulong cma_pool_size; + +/* end customer definition */ +static struct vpudrv_buffer_t s_instance_pool = {0}; +static struct vpudrv_buffer_t s_common_memory = {0}; +static struct vpu_drv_context_t s_vpu_drv_context; +static s32 s_vpu_major; +static struct device *hevcenc_dev; + +static s32 s_vpu_open_ref_count; +static s32 s_vpu_irq; +static bool s_vpu_irq_requested; + +static struct vpudrv_buffer_t s_vpu_register = {0}; + +static s32 s_interrupt_flag; +static wait_queue_head_t s_interrupt_wait_q; + +static spinlock_t s_vpu_lock = __SPIN_LOCK_UNLOCKED(s_vpu_lock); +static DEFINE_SEMAPHORE(s_vpu_sem); +static struct list_head s_vbp_head = LIST_HEAD_INIT(s_vbp_head); +static struct list_head s_inst_list_head = LIST_HEAD_INIT(s_inst_list_head); +static struct tasklet_struct hevc_tasklet; +static struct platform_device *hevc_pdev; + +static struct vpu_bit_firmware_info_t s_bit_firmware_info[MAX_NUM_VPU_CORE]; + +static void dma_flush(u32 buf_start , u32 buf_size) +{ + if (hevc_pdev) + dma_sync_single_for_device( + &hevc_pdev->dev, buf_start, + buf_size, DMA_TO_DEVICE); +} + +static void cache_flush(u32 buf_start , u32 buf_size) +{ + if (hevc_pdev) + dma_sync_single_for_cpu( + &hevc_pdev->dev, buf_start, + buf_size, DMA_FROM_DEVICE); +} + +s32 vpu_hw_reset(void) +{ + enc_pr(LOG_DEBUG, "request vpu reset from application.\n"); + return 0; +} + +s32 vpu_clk_config(u32 enable) +{ + if (enable) + HevcEnc_clock_enable(clock_level); + else + HevcEnc_clock_disable(); + return 0; +} + +static s32 vpu_alloc_dma_buffer(struct vpudrv_buffer_t *vb) +{ + if (!vb) + return -1; + + vb->phys_addr = (ulong)vmem_alloc(&s_vmem, vb->size, 0); + if ((ulong)vb->phys_addr == (ulong)-1) { + enc_pr(LOG_ERROR, + "Physical memory allocation error size=%d\n", vb->size); + return -1; + } + + vb->base = (ulong)(s_video_memory.base + + (vb->phys_addr - s_video_memory.phys_addr)); + return 0; +} + +static void vpu_free_dma_buffer(struct vpudrv_buffer_t *vb) +{ + if (!vb) + return; + + if (vb->base) + vmem_free(&s_vmem, vb->phys_addr, 0); +} + +static s32 vpu_free_instances(struct file *filp) +{ + struct vpudrv_instanace_list_t *vil, *n; + struct vpudrv_instance_pool_t *vip; + void *vip_base; + + enc_pr(LOG_DEBUG, "vpu_free_instances\n"); + + list_for_each_entry_safe(vil, n, &s_inst_list_head, list) + { + if (vil->filp == filp) { + vip_base = (void *)s_instance_pool.base; + enc_pr(LOG_INFO, + "free_instances instIdx=%d, coreIdx=%d, vip_base=%p\n", + (s32)vil->inst_idx, + (s32)vil->core_idx, + vip_base); + vip = (struct vpudrv_instance_pool_t *)vip_base; + if (vip) { + /* only first 4 byte is key point + (inUse of CodecInst in vpuapi) + to free the corresponding instance. */ + memset(&vip->codecInstPool[vil->inst_idx], + 0x00, 4); + } + s_vpu_open_ref_count--; + list_del(&vil->list); + kfree(vil); + } + } + return 1; +} + +static s32 vpu_free_buffers(struct file *filp) +{ + struct vpudrv_buffer_pool_t *pool, *n; + struct vpudrv_buffer_t vb; + + enc_pr(LOG_DEBUG, "vpu_free_buffers\n"); + + list_for_each_entry_safe(pool, n, &s_vbp_head, list) + { + if (pool->filp == filp) { + vb = pool->vb; + if (vb.base) { + vpu_free_dma_buffer(&vb); + list_del(&pool->list); + kfree(pool); + } + } + } + return 0; +} + +static u32 vpu_is_buffer_cached(struct file *filp, ulong vm_pgoff) +{ + struct vpudrv_buffer_pool_t *pool, *n; + struct vpudrv_buffer_t vb; + bool find = false; + u32 cached = 0; + + enc_pr(LOG_ALL, "[+]vpu_is_buffer_cached\n"); + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(pool, n, &s_vbp_head, list) + { + if (pool->filp == filp) { + vb = pool->vb; + if (((vb.phys_addr >> PAGE_SHIFT) == vm_pgoff) + && find == false){ + cached = vb.cached; + find = true; + } + } + } + spin_unlock(&s_vpu_lock); + enc_pr(LOG_ALL, "[-]vpu_is_buffer_cached, ret:%d\n", cached); + return cached; +} + +static void hevcenc_isr_tasklet(ulong data) +{ + struct vpu_drv_context_t *dev = (struct vpu_drv_context_t *)data; + enc_pr(LOG_INFO, "hevcenc_isr_tasklet interruput:0x%08lx\n", + dev->interrupt_reason); + if (dev->interrupt_reason) { + /* notify the interrupt to user space */ + if (dev->async_queue) { + enc_pr(LOG_ALL, "kill_fasync e %s\n", __func__); + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + } + s_interrupt_flag = 1; + wake_up_interruptible(&s_interrupt_wait_q); + } + enc_pr(LOG_ALL, "[-]%s\n", __func__); +} + +static irqreturn_t vpu_irq_handler(s32 irq, void *dev_id) +{ + struct vpu_drv_context_t *dev = (struct vpu_drv_context_t *)dev_id; + /* this can be removed. + it also work in VPU_WaitInterrupt of API function */ + u32 core; + ulong interrupt_reason = 0; + enc_pr(LOG_ALL, "[+]%s\n", __func__); + + for (core = 0; core < MAX_NUM_VPU_CORE; core++) { + if (s_bit_firmware_info[core].size == 0) { + /* it means that we didn't get an information + the current core from API layer. + No core activated.*/ + enc_pr(LOG_ERROR, + "s_bit_firmware_info[core].size is zero\n"); + continue; + } + if (ReadVpuRegister(W4_VPU_VPU_INT_STS)) { + interrupt_reason = ReadVpuRegister(W4_VPU_INT_REASON); + WriteVpuRegister(W4_VPU_INT_REASON_CLEAR, + interrupt_reason); + WriteVpuRegister(W4_VPU_VINT_CLEAR, 0x1); + dev->interrupt_reason |= interrupt_reason; + } + enc_pr(LOG_INFO, + "intr_reason: 0x%08lx\n", dev->interrupt_reason); + } + if (dev->interrupt_reason) + tasklet_schedule(&hevc_tasklet); + enc_pr(LOG_ALL, "[-]%s\n", __func__); + return IRQ_HANDLED; +} + +static s32 vpu_open(struct inode *inode, struct file *filp) +{ + bool alloc_buffer = false; + s32 r = 0; + enc_pr(LOG_DEBUG, "[+] %s\n", __func__); + spin_lock(&s_vpu_lock); + s_vpu_drv_context.open_count++; + if (s_vpu_drv_context.open_count == 1) { + alloc_buffer = true; + } else { + r = -EBUSY; + s_vpu_drv_context.open_count--; + spin_unlock(&s_vpu_lock); + goto Err; + } + filp->private_data = (void *)(&s_vpu_drv_context); + spin_unlock(&s_vpu_lock); + if (alloc_buffer && !use_reserve) { +#ifdef CONFIG_CMA + s_video_memory.size = VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE; + s_video_memory.phys_addr = + (ulong)codec_mm_alloc_for_dma(VPU_DEV_NAME, + VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE >> PAGE_SHIFT, 0, + CODEC_MM_FLAGS_CPU); + if (s_video_memory.phys_addr) + s_video_memory.base = + (ulong)phys_to_virt(s_video_memory.phys_addr); + else + s_video_memory.base = 0; + if (s_video_memory.base) { + enc_pr(LOG_DEBUG, + "allocating phys 0x%lx, virt addr 0x%lx, size %dk\n", + s_video_memory.phys_addr, + s_video_memory.base, + s_video_memory.size >> 10); + if (vmem_init(&s_vmem, + s_video_memory.phys_addr, + s_video_memory.size) < 0) { + enc_pr(LOG_ERROR, "fail to init vmem system\n"); + r = -ENOMEM; + codec_mm_free_for_dma( + VPU_DEV_NAME, + (u32)s_video_memory.phys_addr); + vmem_exit(&s_vmem); + memset(&s_video_memory, 0, + sizeof(struct vpudrv_buffer_t)); + memset(&s_vmem, 0, + sizeof(struct video_mm_t)); + } + } else { + enc_pr(LOG_ERROR, + "CMA failed to allocate dma buffer for %s, phys: 0x%lx\n", + VPU_DEV_NAME, s_video_memory.phys_addr); + if (s_video_memory.phys_addr) + codec_mm_free_for_dma( + VPU_DEV_NAME, + (u32)s_video_memory.phys_addr); + s_video_memory.phys_addr = 0; + r = -ENOMEM; + } +#else + enc_pr(LOG_ERROR, + "No CMA and reserved memory for HevcEnc!!!\n"); + r = -ENOMEM; +#endif + } else if (!s_video_memory.base) { + enc_pr(LOG_ERROR, + "HevcEnc memory is not malloced!!!\n"); + r = -ENOMEM; + } + if (alloc_buffer) { + ulong flags; + u32 data32; + if ((s_vpu_irq >= 0) && (s_vpu_irq_requested == false)) { + s32 err; + err = request_irq(s_vpu_irq, vpu_irq_handler, 0, + "HevcEnc-irq", (void *)(&s_vpu_drv_context)); + if (err) { + enc_pr(LOG_ERROR, + "fail to register interrupt handler\n"); + return -EFAULT; + } + s_vpu_irq_requested = true; + } + amports_switch_gate("vdec", 1); + spin_lock_irqsave(&s_vpu_lock, flags); + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~(0x3<<24)); + udelay(10); + + data32 = 0x700; + data32 |= READ_VREG(DOS_SW_RESET4); + WRITE_VREG(DOS_SW_RESET4, data32); + data32 &= ~0x700; + WRITE_VREG(DOS_SW_RESET4, data32); + + WRITE_MPEG_REG(RESET0_REGISTER, data32 & ~(1<<21)); + WRITE_MPEG_REG(RESET0_REGISTER, data32 | (1<<21)); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); + READ_MPEG_REG(RESET0_REGISTER); +#ifndef VPU_SUPPORT_CLOCK_CONTROL + vpu_clk_config(1); +#endif + /* Enable wave420l_vpu_idle_rise_irq, + Disable wave420l_vpu_idle_fall_irq */ + WRITE_VREG(DOS_WAVE420L_CNTL_STAT, 0x1); + WRITE_VREG(DOS_MEM_PD_WAVE420L, 0x0); + + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~(0x3<<12)); + udelay(10); + + spin_unlock_irqrestore(&s_vpu_lock, flags); + } +Err: + enc_pr(LOG_DEBUG, "[-] %s, ret: %d\n", __func__, r); + return r; +} + +static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) +{ + s32 ret = 0; + struct vpu_drv_context_t *dev = + (struct vpu_drv_context_t *)filp->private_data; + + switch (cmd) { + case VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY: + { + struct vpudrv_buffer_pool_t *vbp; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret == 0) { + vbp = kzalloc(sizeof(*vbp), GFP_KERNEL); + if (!vbp) { + up(&s_vpu_sem); + return -ENOMEM; + } + + ret = copy_from_user(&(vbp->vb), + (struct vpudrv_buffer_t *)arg, + sizeof(struct vpudrv_buffer_t)); + if (ret) { + kfree(vbp); + up(&s_vpu_sem); + return -EFAULT; + } + + ret = vpu_alloc_dma_buffer(&(vbp->vb)); + if (ret == -1) { + ret = -ENOMEM; + kfree(vbp); + up(&s_vpu_sem); + break; + } + ret = copy_to_user((void __user *)arg, + &(vbp->vb), + sizeof(struct vpudrv_buffer_t)); + if (ret) { + kfree(vbp); + ret = -EFAULT; + up(&s_vpu_sem); + break; + } + + vbp->filp = filp; + spin_lock(&s_vpu_lock); + list_add(&vbp->list, &s_vbp_head); + spin_unlock(&s_vpu_lock); + + up(&s_vpu_sem); + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY\n"); + } + break; + case VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32: + { + struct vpudrv_buffer_pool_t *vbp; + struct compat_vpudrv_buffer_t buf32; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret == 0) { + vbp = kzalloc(sizeof(*vbp), GFP_KERNEL); + if (!vbp) { + up(&s_vpu_sem); + return -ENOMEM; + } + + ret = copy_from_user(&buf32, + (struct compat_vpudrv_buffer_t *)arg, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret) { + kfree(vbp); + up(&s_vpu_sem); + return -EFAULT; + } + + vbp->vb.size = buf32.size; + vbp->vb.cached = buf32.cached; + vbp->vb.phys_addr = + (ulong)buf32.phys_addr; + vbp->vb.base = + (ulong)buf32.base; + vbp->vb.virt_addr = + (ulong)buf32.virt_addr; + ret = vpu_alloc_dma_buffer(&(vbp->vb)); + if (ret == -1) { + ret = -ENOMEM; + kfree(vbp); + up(&s_vpu_sem); + break; + } + + buf32.size = vbp->vb.size; + buf32.phys_addr = + (compat_ulong_t)vbp->vb.phys_addr; + buf32.base = + (compat_ulong_t)vbp->vb.base; + buf32.virt_addr = + (compat_ulong_t)vbp->vb.virt_addr; + + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret) { + kfree(vbp); + ret = -EFAULT; + up(&s_vpu_sem); + break; + } + + vbp->filp = filp; + spin_lock(&s_vpu_lock); + list_add(&vbp->list, &s_vbp_head); + spin_unlock(&s_vpu_lock); + + up(&s_vpu_sem); + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32\n"); + } + break; + case VDI_IOCTL_FREE_PHYSICALMEMORY: + { + struct vpudrv_buffer_pool_t *vbp, *n; + struct vpudrv_buffer_t vb; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_FREE_PHYSICALMEMORY\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret == 0) { + ret = copy_from_user(&vb, + (struct vpudrv_buffer_t *)arg, + sizeof(struct vpudrv_buffer_t)); + if (ret) { + up(&s_vpu_sem); + return -EACCES; + } + + if (vb.base) + vpu_free_dma_buffer(&vb); + + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(vbp, n, + &s_vbp_head, list) + { + if (vbp->vb.base == vb.base) { + list_del(&vbp->list); + kfree(vbp); + break; + } + } + spin_unlock(&s_vpu_lock); + up(&s_vpu_sem); + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_FREE_PHYSICALMEMORY\n"); + } + break; + case VDI_IOCTL_FREE_PHYSICALMEMORY32: + { + struct vpudrv_buffer_pool_t *vbp, *n; + struct compat_vpudrv_buffer_t buf32; + struct vpudrv_buffer_t vb; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_FREE_PHYSICALMEMORY32\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret == 0) { + ret = copy_from_user(&buf32, + (struct compat_vpudrv_buffer_t *)arg, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret) { + up(&s_vpu_sem); + return -EACCES; + } + + vb.size = buf32.size; + vb.phys_addr = + (ulong)buf32.phys_addr; + vb.base = + (ulong)buf32.base; + vb.virt_addr = + (ulong)buf32.virt_addr; + + if (vb.base) + vpu_free_dma_buffer(&vb); + + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(vbp, n, + &s_vbp_head, list) + { + if ((compat_ulong_t)vbp->vb.base + == buf32.base) { + list_del(&vbp->list); + kfree(vbp); + break; + } + } + spin_unlock(&s_vpu_lock); + up(&s_vpu_sem); + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_FREE_PHYSICALMEMORY32\n"); + } + break; + case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO: + { + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); + if (s_video_memory.base != 0) { + ret = copy_to_user((void __user *)arg, + &s_video_memory, + sizeof(struct vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else { + ret = -EFAULT; + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); + } + break; + case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32: + { + struct compat_vpudrv_buffer_t buf32; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32\n"); + + buf32.size = s_video_memory.size; + buf32.phys_addr = + (compat_ulong_t)s_video_memory.phys_addr; + buf32.base = + (compat_ulong_t)s_video_memory.base; + buf32.virt_addr = + (compat_ulong_t)s_video_memory.virt_addr; + if (s_video_memory.base != 0) { + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else { + ret = -EFAULT; + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32\n"); + } + break; + case VDI_IOCTL_WAIT_INTERRUPT: + { + struct vpudrv_intr_info_t info; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_WAIT_INTERRUPT\n"); + ret = copy_from_user(&info, + (struct vpudrv_intr_info_t *)arg, + sizeof(struct vpudrv_intr_info_t)); + if (ret != 0) + return -EFAULT; + + ret = wait_event_interruptible_timeout( + s_interrupt_wait_q, + s_interrupt_flag != 0, + msecs_to_jiffies(info.timeout)); + if (!ret) { + ret = -ETIME; + break; + } + if (dev->interrupt_reason & (1 << W4_INT_ENC_PIC)) { + u32 start, end, size, core = 0; + start = ReadVpuRegister(W4_BS_RD_PTR); + end = ReadVpuRegister(W4_BS_WR_PTR); + size = ReadVpuRegister(W4_RET_ENC_PIC_BYTE); + enc_pr(LOG_INFO, "flush output buffer, "); + enc_pr(LOG_INFO, + "start:0x%x, end:0x%x, size:0x%x\n", + start, end, size); + if (end - start > size && end > start) + size = end - start; + if (size > 0) + cache_flush(start, size); + } + + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + enc_pr(LOG_INFO, + "s_interrupt_flag(%d), reason(0x%08lx)\n", + s_interrupt_flag, dev->interrupt_reason); + + info.intr_reason = dev->interrupt_reason; + s_interrupt_flag = 0; + dev->interrupt_reason = 0; + ret = copy_to_user((void __user *)arg, + &info, sizeof(struct vpudrv_intr_info_t)); + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_WAIT_INTERRUPT\n"); + if (ret != 0) + return -EFAULT; + } + break; + case VDI_IOCTL_SET_CLOCK_GATE: + { + u32 clkgate; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_SET_CLOCK_GATE\n"); + if (get_user(clkgate, (u32 __user *) arg)) + return -EFAULT; +#ifdef VPU_SUPPORT_CLOCK_CONTROL + vpu_clk_config(clkgate); +#endif + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_SET_CLOCK_GATE\n"); + } + break; + case VDI_IOCTL_GET_INSTANCE_POOL: + { + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_INSTANCE_POOL\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret != 0) + break; + + if (s_instance_pool.base != 0) { + ret = copy_to_user((void __user *)arg, + &s_instance_pool, + sizeof(struct vpudrv_buffer_t)); + ret = (ret != 0) ? -EFAULT : 0; + } else { + ret = copy_from_user(&s_instance_pool, + (struct vpudrv_buffer_t *)arg, + sizeof(struct vpudrv_buffer_t)); + if (ret == 0) { + s_instance_pool.size = + PAGE_ALIGN( + s_instance_pool.size); + s_instance_pool.base = + (ulong)vmalloc( + s_instance_pool.size); + s_instance_pool.phys_addr = + s_instance_pool.base; + if (s_instance_pool.base == 0) { + ret = -EFAULT; + up(&s_vpu_sem); + break; + } + /*clearing memory*/ + memset((void *)s_instance_pool.base, + 0, s_instance_pool.size); + ret = copy_to_user((void __user *)arg, + &s_instance_pool, + sizeof(struct vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else + ret = -EFAULT; + } + up(&s_vpu_sem); + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_INSTANCE_POOL\n"); + } + break; + case VDI_IOCTL_GET_INSTANCE_POOL32: + { + struct compat_vpudrv_buffer_t buf32; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_INSTANCE_POOL32\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret != 0) + break; + if (s_instance_pool.base != 0) { + buf32.size = s_instance_pool.size; + buf32.phys_addr = + (compat_ulong_t) + s_instance_pool.phys_addr; + buf32.base = + (compat_ulong_t) + s_instance_pool.base; + buf32.virt_addr = + (compat_ulong_t) + s_instance_pool.virt_addr; + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof(struct compat_vpudrv_buffer_t)); + ret = (ret != 0) ? -EFAULT : 0; + } else { + ret = copy_from_user(&buf32, + (struct compat_vpudrv_buffer_t *)arg, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret == 0) { + s_instance_pool.size = buf32.size; + s_instance_pool.size = + PAGE_ALIGN( + s_instance_pool.size); + s_instance_pool.base = + (ulong)vmalloc( + s_instance_pool.size); + s_instance_pool.phys_addr = + s_instance_pool.base; + buf32.size = + s_instance_pool.size; + buf32.phys_addr = + (compat_ulong_t) + s_instance_pool.phys_addr; + buf32.base = + (compat_ulong_t) + s_instance_pool.base; + buf32.virt_addr = + (compat_ulong_t) + s_instance_pool.virt_addr; + if (s_instance_pool.base == 0) { + ret = -EFAULT; + up(&s_vpu_sem); + break; + } + /*clearing memory*/ + memset((void *)s_instance_pool.base, + 0x0, s_instance_pool.size); + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof( + struct compat_vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else + ret = -EFAULT; + } + up(&s_vpu_sem); + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_INSTANCE_POOL32\n"); + } + break; + case VDI_IOCTL_GET_COMMON_MEMORY: + { + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_COMMON_MEMORY\n"); + if (s_common_memory.base != 0) { + ret = copy_to_user((void __user *)arg, + &s_common_memory, + sizeof(struct vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else { + ret = copy_from_user(&s_common_memory, + (struct vpudrv_buffer_t *)arg, + sizeof(struct vpudrv_buffer_t)); + if (ret != 0) { + ret = -EFAULT; + break; + } + if (vpu_alloc_dma_buffer( + &s_common_memory) != -1) { + ret = copy_to_user((void __user *)arg, + &s_common_memory, + sizeof(struct vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else + ret = -EFAULT; + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_COMMON_MEMORY\n"); + } + break; + case VDI_IOCTL_GET_COMMON_MEMORY32: + { + struct compat_vpudrv_buffer_t buf32; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_COMMON_MEMORY32\n"); + + buf32.size = s_common_memory.size; + buf32.phys_addr = + (compat_ulong_t) + s_common_memory.phys_addr; + buf32.base = + (compat_ulong_t) + s_common_memory.base; + buf32.virt_addr = + (compat_ulong_t) + s_common_memory.virt_addr; + if (s_common_memory.base != 0) { + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else { + ret = copy_from_user(&buf32, + (struct compat_vpudrv_buffer_t *)arg, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret != 0) { + ret = -EFAULT; + break; + } + s_common_memory.size = buf32.size; + if (vpu_alloc_dma_buffer( + &s_common_memory) != -1) { + buf32.size = + s_common_memory.size; + buf32.phys_addr = + (compat_ulong_t) + s_common_memory.phys_addr; + buf32.base = + (compat_ulong_t) + s_common_memory.base; + buf32.virt_addr = + (compat_ulong_t) + s_common_memory.virt_addr; + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof( + struct compat_vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + } else + ret = -EFAULT; + } + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_COMMON_MEMORY32\n"); + } + break; + case VDI_IOCTL_OPEN_INSTANCE: + { + struct vpudrv_inst_info_t inst_info; + struct vpudrv_instanace_list_t *vil, *n; + + vil = kzalloc(sizeof(*vil), GFP_KERNEL); + if (!vil) + return -ENOMEM; + + if (copy_from_user(&inst_info, + (struct vpudrv_inst_info_t *)arg, + sizeof(struct vpudrv_inst_info_t))) + return -EFAULT; + + vil->inst_idx = inst_info.inst_idx; + vil->core_idx = inst_info.core_idx; + vil->filp = filp; + + spin_lock(&s_vpu_lock); + list_add(&vil->list, &s_inst_list_head); + + /* counting the current open instance number */ + inst_info.inst_open_count = 0; + list_for_each_entry_safe(vil, n, + &s_inst_list_head, list) + { + if (vil->core_idx == inst_info.core_idx) + inst_info.inst_open_count++; + } + + /* flag just for that vpu is in opened or closed */ + s_vpu_open_ref_count++; + spin_unlock(&s_vpu_lock); + + if (copy_to_user((void __user *)arg, + &inst_info, + sizeof(struct vpudrv_inst_info_t))) { + kfree(vil); + return -EFAULT; + } + + enc_pr(LOG_DEBUG, + "VDI_IOCTL_OPEN_INSTANCE "); + enc_pr(LOG_DEBUG, + "core_idx=%d, inst_idx=%d, ", + (u32)inst_info.core_idx, + (u32)inst_info.inst_idx); + enc_pr(LOG_DEBUG, + "s_vpu_open_ref_count=%d, inst_open_count=%d\n", + s_vpu_open_ref_count, + inst_info.inst_open_count); + } + break; + case VDI_IOCTL_CLOSE_INSTANCE: + { + struct vpudrv_inst_info_t inst_info; + struct vpudrv_instanace_list_t *vil, *n; + + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_CLOSE_INSTANCE\n"); + if (copy_from_user(&inst_info, + (struct vpudrv_inst_info_t *)arg, + sizeof(struct vpudrv_inst_info_t))) + return -EFAULT; + + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(vil, n, + &s_inst_list_head, list) + { + if (vil->inst_idx == inst_info.inst_idx && + vil->core_idx == inst_info.core_idx) { + list_del(&vil->list); + kfree(vil); + break; + } + } + + /* counting the current open instance number */ + inst_info.inst_open_count = 0; + list_for_each_entry_safe(vil, n, + &s_inst_list_head, list) + { + if (vil->core_idx == inst_info.core_idx) + inst_info.inst_open_count++; + } + + /* flag just for that vpu is in opened or closed */ + s_vpu_open_ref_count--; + spin_unlock(&s_vpu_lock); + + if (copy_to_user((void __user *)arg, + &inst_info, + sizeof(struct vpudrv_inst_info_t))) + return -EFAULT; + + enc_pr(LOG_DEBUG, + "VDI_IOCTL_CLOSE_INSTANCE "); + enc_pr(LOG_DEBUG, + "core_idx=%d, inst_idx=%d, ", + (u32)inst_info.core_idx, + (u32)inst_info.inst_idx); + enc_pr(LOG_DEBUG, + "s_vpu_open_ref_count=%d, inst_open_count=%d\n", + s_vpu_open_ref_count, + inst_info.inst_open_count); + } + break; + case VDI_IOCTL_GET_INSTANCE_NUM: + { + struct vpudrv_inst_info_t inst_info; + struct vpudrv_instanace_list_t *vil, *n; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_INSTANCE_NUM\n"); + + ret = copy_from_user(&inst_info, + (struct vpudrv_inst_info_t *)arg, + sizeof(struct vpudrv_inst_info_t)); + if (ret != 0) + break; + + inst_info.inst_open_count = 0; + + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(vil, n, + &s_inst_list_head, list) + { + if (vil->core_idx == inst_info.core_idx) + inst_info.inst_open_count++; + } + spin_unlock(&s_vpu_lock); + + ret = copy_to_user((void __user *)arg, + &inst_info, + sizeof(struct vpudrv_inst_info_t)); + + enc_pr(LOG_DEBUG, + "VDI_IOCTL_GET_INSTANCE_NUM "); + enc_pr(LOG_DEBUG, + "core_idx=%d, inst_idx=%d, open_count=%d\n", + (u32)inst_info.core_idx, + (u32)inst_info.inst_idx, + inst_info.inst_open_count); + } + break; + case VDI_IOCTL_RESET: + { + vpu_hw_reset(); + } + break; + case VDI_IOCTL_GET_REGISTER_INFO: + { + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_REGISTER_INFO\n"); + ret = copy_to_user((void __user *)arg, + &s_vpu_register, + sizeof(struct vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_REGISTER_INFO "); + enc_pr(LOG_ALL, + "s_vpu_register.phys_addr=0x%lx, ", + s_vpu_register.phys_addr); + enc_pr(LOG_ALL, + "s_vpu_register.virt_addr=0x%lx, ", + s_vpu_register.virt_addr); + enc_pr(LOG_ALL, + "s_vpu_register.size=0x%x\n", + s_vpu_register.size); + } + break; + case VDI_IOCTL_GET_REGISTER_INFO32: + { + struct compat_vpudrv_buffer_t buf32; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_GET_REGISTER_INFO32\n"); + + buf32.size = s_vpu_register.size; + buf32.phys_addr = + (compat_ulong_t) + s_vpu_register.phys_addr; + buf32.base = + (compat_ulong_t) + s_vpu_register.base; + buf32.virt_addr = + (compat_ulong_t) + s_vpu_register.virt_addr; + ret = copy_to_user((void __user *)arg, + &buf32, + sizeof( + struct compat_vpudrv_buffer_t)); + if (ret != 0) + ret = -EFAULT; + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_GET_REGISTER_INFO32 "); + enc_pr(LOG_ALL, + "s_vpu_register.phys_addr=0x%lx, ", + s_vpu_register.phys_addr); + enc_pr(LOG_ALL, + "s_vpu_register.virt_addr=0x%lx, ", + s_vpu_register.virt_addr); + enc_pr(LOG_ALL, + "s_vpu_register.size=0x%x\n", + s_vpu_register.size); + } + break; + case VDI_IOCTL_FLUSH_BUFFER32: + { + struct vpudrv_buffer_pool_t *pool, *n; + struct compat_vpudrv_buffer_t buf32; + struct vpudrv_buffer_t vb; + bool find = false; + u32 cached = 0; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_FLUSH_BUFFER32\n"); + + ret = copy_from_user(&buf32, + (struct compat_vpudrv_buffer_t *)arg, + sizeof(struct compat_vpudrv_buffer_t)); + if (ret) + return -EFAULT; + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(pool, n, + &s_vbp_head, list) + { + if (pool->filp == filp) { + vb = pool->vb; + if (((compat_ulong_t)vb.phys_addr + == buf32.phys_addr) + && find == false){ + cached = vb.cached; + find = true; + } + } + } + spin_unlock(&s_vpu_lock); + if (find && cached) + dma_flush( + (u32)buf32.phys_addr, + (u32)buf32.size); + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_FLUSH_BUFFER32\n"); + } + break; + case VDI_IOCTL_FLUSH_BUFFER: + { + struct vpudrv_buffer_pool_t *pool, *n; + struct vpudrv_buffer_t vb, buf; + bool find = false; + u32 cached = 0; + enc_pr(LOG_ALL, + "[+]VDI_IOCTL_FLUSH_BUFFER\n"); + + ret = copy_from_user(&buf, + (struct vpudrv_buffer_t *)arg, + sizeof(struct vpudrv_buffer_t)); + if (ret) + return -EFAULT; + spin_lock(&s_vpu_lock); + list_for_each_entry_safe(pool, n, + &s_vbp_head, list) + { + if (pool->filp == filp) { + vb = pool->vb; + if ((vb.phys_addr + == buf.phys_addr) + && find == false){ + cached = vb.cached; + find = true; + } + } + } + spin_unlock(&s_vpu_lock); + if (find && cached) + dma_flush( + (u32)buf.phys_addr, + (u32)buf.size); + enc_pr(LOG_ALL, + "[-]VDI_IOCTL_FLUSH_BUFFER\n"); + } + break; + default: + { + enc_pr(LOG_ERROR, + "No such IOCTL, cmd is %d\n", cmd); + } + break; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long vpu_compat_ioctl(struct file *filp, u32 cmd, ulong arg) +{ + long ret; + + arg = (ulong)compat_ptr(arg); + ret = vpu_ioctl(filp, cmd, arg); + return ret; +} +#endif + +static ssize_t vpu_write(struct file *filp, + const char *buf, + size_t len, + loff_t *ppos) +{ + enc_pr(LOG_INFO, "vpu_write len=%d\n", (int)len); + + if (!buf) { + enc_pr(LOG_ERROR, "vpu_write buf = NULL error\n"); + return -EFAULT; + } + + if (len == sizeof(struct vpu_bit_firmware_info_t)) { + struct vpu_bit_firmware_info_t *bit_firmware_info; + bit_firmware_info = + kmalloc(sizeof(struct vpu_bit_firmware_info_t), + GFP_KERNEL); + if (!bit_firmware_info) { + enc_pr(LOG_ERROR, + "vpu_write bit_firmware_info allocation error\n"); + return -EFAULT; + } + + if (copy_from_user(bit_firmware_info, buf, len)) { + enc_pr(LOG_ERROR, + "vpu_write copy_from_user error for bit_firmware_info\n"); + return -EFAULT; + } + + if (bit_firmware_info->size == + sizeof(struct vpu_bit_firmware_info_t)) { + enc_pr(LOG_INFO, + "vpu_write set bit_firmware_info coreIdx=0x%x, ", + bit_firmware_info->core_idx); + enc_pr(LOG_INFO, + "reg_base_offset=0x%x size=0x%x, bit_code[0]=0x%x\n", + bit_firmware_info->reg_base_offset, + bit_firmware_info->size, + bit_firmware_info->bit_code[0]); + + if (bit_firmware_info->core_idx + > MAX_NUM_VPU_CORE) { + enc_pr(LOG_ERROR, + "vpu_write coreIdx[%d] is ", + bit_firmware_info->core_idx); + enc_pr(LOG_ERROR, + "exceeded than MAX_NUM_VPU_CORE[%d]\n", + MAX_NUM_VPU_CORE); + return -ENODEV; + } + + memcpy((void *)&s_bit_firmware_info + [bit_firmware_info->core_idx], + bit_firmware_info, + sizeof(struct vpu_bit_firmware_info_t)); + kfree(bit_firmware_info); + return len; + } + kfree(bit_firmware_info); + } + return -1; +} + +static s32 vpu_release(struct inode *inode, struct file *filp) +{ + s32 ret = 0; + ulong flags; + enc_pr(LOG_DEBUG, "vpu_release\n"); + ret = down_interruptible(&s_vpu_sem); + if (ret == 0) { + vpu_free_buffers(filp); + vpu_free_instances(filp); + s_vpu_drv_context.open_count--; + if (s_vpu_drv_context.open_count == 0) { + if (s_instance_pool.base) { + enc_pr(LOG_DEBUG, "free instance pool\n"); + vfree((const void *)s_instance_pool.base); + s_instance_pool.base = 0; + } + if (s_common_memory.base) { + enc_pr(LOG_DEBUG, "free common memory\n"); + vpu_free_dma_buffer(&s_common_memory); + s_common_memory.base = 0; + } + + if (s_video_memory.base && !use_reserve) { + codec_mm_free_for_dma( + VPU_DEV_NAME, + (u32)s_video_memory.phys_addr); + vmem_exit(&s_vmem); + memset(&s_video_memory, + 0, sizeof(struct vpudrv_buffer_t)); + memset(&s_vmem, + 0, sizeof(struct video_mm_t)); + } + if ((s_vpu_irq >= 0) && (s_vpu_irq_requested == true)) { + free_irq(s_vpu_irq, &s_vpu_drv_context); + s_vpu_irq_requested = false; + } + spin_lock_irqsave(&s_vpu_lock, flags); + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | (0x3<<12)); + udelay(10); + + WRITE_VREG(DOS_MEM_PD_WAVE420L, 0xffffffff); +#ifndef VPU_SUPPORT_CLOCK_CONTROL + vpu_clk_config(0); +#endif + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | (0x3<<24)); + udelay(10); + spin_unlock_irqrestore(&s_vpu_lock, flags); + amports_switch_gate("vdec", 0); + } + } + up(&s_vpu_sem); + return 0; +} + +static s32 vpu_fasync(s32 fd, struct file *filp, s32 mode) +{ + struct vpu_drv_context_t *dev = + (struct vpu_drv_context_t *)filp->private_data; + return fasync_helper(fd, filp, mode, &dev->async_queue); +} + +static s32 vpu_map_to_register(struct file *fp, struct vm_area_struct *vm) +{ + ulong pfn; + vm->vm_flags |= VM_IO | VM_RESERVED; + vm->vm_page_prot = + pgprot_noncached(vm->vm_page_prot); + pfn = s_vpu_register.phys_addr >> PAGE_SHIFT; + return remap_pfn_range(vm, vm->vm_start, pfn, + vm->vm_end - vm->vm_start, + vm->vm_page_prot) ? -EAGAIN : 0; +} + +static s32 vpu_map_to_physical_memory( + struct file *fp, struct vm_area_struct *vm) +{ + vm->vm_flags |= VM_IO | VM_RESERVED; + if (vm->vm_pgoff == + (s_common_memory.phys_addr >> PAGE_SHIFT)) { + vm->vm_page_prot = + pgprot_noncached(vm->vm_page_prot); + } else { + if (vpu_is_buffer_cached(fp, vm->vm_pgoff) == 0) + vm->vm_page_prot = + pgprot_noncached(vm->vm_page_prot); + } + /* vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot); */ + return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff, + vm->vm_end - vm->vm_start, vm->vm_page_prot) ? -EAGAIN : 0; +} + +static s32 vpu_map_to_instance_pool_memory( + struct file *fp, struct vm_area_struct *vm) +{ + s32 ret; + long length = vm->vm_end - vm->vm_start; + ulong start = vm->vm_start; + s8 *vmalloc_area_ptr = (s8 *)s_instance_pool.base; + ulong pfn; + + vm->vm_flags |= VM_RESERVED; + + /* loop over all pages, map it page individually */ + while (length > 0) { + pfn = vmalloc_to_pfn(vmalloc_area_ptr); + ret = remap_pfn_range(vm, start, pfn, + PAGE_SIZE, PAGE_SHARED); + if (ret < 0) + return ret; + start += PAGE_SIZE; + vmalloc_area_ptr += PAGE_SIZE; + length -= PAGE_SIZE; + } + return 0; +} + +/* + * @brief memory map interface for vpu file operation + * @return 0 on success or negative error code on error + */ +static s32 vpu_mmap(struct file *fp, struct vm_area_struct *vm) +{ + /* if (vm->vm_pgoff == (s_vpu_register.phys_addr >> PAGE_SHIFT)) */ + if ((vm->vm_end - vm->vm_start == s_vpu_register.size + 1) && + (vm->vm_pgoff == 0)) { + vm->vm_pgoff = (s_vpu_register.phys_addr >> PAGE_SHIFT); + return vpu_map_to_register(fp, vm); + } + + if (vm->vm_pgoff == 0) + return vpu_map_to_instance_pool_memory(fp, vm); + + return vpu_map_to_physical_memory(fp, vm); +} + +static const struct file_operations vpu_fops = { + .owner = THIS_MODULE, + .open = vpu_open, + .release = vpu_release, + .write = vpu_write, + .unlocked_ioctl = vpu_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vpu_compat_ioctl, +#endif + .fasync = vpu_fasync, + .mmap = vpu_mmap, +}; + +static ssize_t hevcenc_status_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return snprintf(buf, 40, "hevcenc_status_show\n"); +} + +static struct class_attribute hevcenc_class_attrs[] = { + __ATTR(encode_status, + S_IRUGO | S_IWUSR, + hevcenc_status_show, + NULL), + __ATTR_NULL +}; + +static struct class hevcenc_class = { + .name = VPU_CLASS_NAME, + .class_attrs = hevcenc_class_attrs, +}; + +s32 init_HevcEnc_device(void) +{ + s32 r = 0; + r = register_chrdev(0, VPU_DEV_NAME, &vpu_fops); + if (r <= 0) { + enc_pr(LOG_ERROR, "register hevcenc device error.\n"); + return r; + } + s_vpu_major = r; + + r = class_register(&hevcenc_class); + if (r < 0) { + enc_pr(LOG_ERROR, "error create hevcenc class.\n"); + return r; + } + + hevcenc_dev = device_create(&hevcenc_class, NULL, + MKDEV(s_vpu_major, 0), NULL, + VPU_DEV_NAME); + + if (IS_ERR(hevcenc_dev)) { + enc_pr(LOG_ERROR, "create hevcenc device error.\n"); + class_unregister(&hevcenc_class); + return -1; + } + return r; +} + +s32 uninit_HevcEnc_device(void) +{ + if (hevcenc_dev) + device_destroy(&hevcenc_class, MKDEV(s_vpu_major, 0)); + + class_destroy(&hevcenc_class); + + unregister_chrdev(s_vpu_major, VPU_DEV_NAME); + return 0; +} + +static s32 hevc_mem_device_init( + struct reserved_mem *rmem, struct device *dev) +{ + s32 r; + if (!rmem) { + enc_pr(LOG_ERROR, + "Can not obtain I/O memory, will allocate hevc buffer!\n"); + r = -EFAULT; + return r; + } + + if ((!rmem->base) || + (rmem->size < VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE)) { + enc_pr(LOG_ERROR, + "memory range error, 0x%lx - 0x%lx\n", + (ulong)rmem->base, (ulong)rmem->size); + r = -EFAULT; + return r; + } + r = 0; + s_video_memory.size = rmem->size; + s_video_memory.phys_addr = (ulong)rmem->base; + s_video_memory.base = + (ulong)phys_to_virt(s_video_memory.phys_addr); + if (!s_video_memory.base) { + enc_pr(LOG_ERROR, "fail to remap video memory "); + enc_pr(LOG_ERROR, + "physical phys_addr=0x%lx, base=0x%lx, size=0x%x\n", + (ulong)s_video_memory.phys_addr, + (ulong)s_video_memory.base, + (u32)s_video_memory.size); + s_video_memory.phys_addr = 0; + r = -EFAULT; + } + return r; +} + +static s32 vpu_probe(struct platform_device *pdev) +{ + s32 err = 0, irq, reg_count, idx; + struct resource res; + struct device_node *np, *child; + + enc_pr(LOG_DEBUG, "vpu_probe\n"); + + s_vpu_major = 0; + use_reserve = false; + s_vpu_irq = -1; + cma_pool_size = 0; + s_vpu_irq_requested = false; + s_vpu_open_ref_count = 0; + hevcenc_dev = NULL; + hevc_pdev = NULL; + memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); + memset(&s_vpu_register, 0, sizeof(struct vpudrv_buffer_t)); + memset(&s_vmem, 0, sizeof(struct video_mm_t)); + memset(&s_bit_firmware_info[0], 0, sizeof(s_bit_firmware_info)); + memset(&res, 0, sizeof(struct resource)); + + idx = of_reserved_mem_device_init(&pdev->dev); + if (idx != 0) { + enc_pr(LOG_DEBUG, + "HevcEnc reserved memory config fail.\n"); + } else if (s_video_memory.phys_addr) { + use_reserve = true; + } + + if (use_reserve == false) { +#ifndef CONFIG_CMA + enc_pr(LOG_ERROR, + "HevcEnc reserved memory is invaild, probe fail!\n"); + err = -EFAULT; + goto ERROR_PROVE_DEVICE; +#else + cma_pool_size = + (codec_mm_get_total_size() > + (VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE)) ? + (VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE) : + codec_mm_get_total_size(); + enc_pr(LOG_DEBUG, + "HevcEnc - cma memory pool size: %d MB\n", + (u32)cma_pool_size / SZ_1M); +#endif + } + + /* get interrupt resource */ + irq = platform_get_irq_byname(pdev, "wave420l_irq"); + if (irq < 0) { + enc_pr(LOG_ERROR, "get HevcEnc irq resource error\n"); + err = -ENXIO; + goto ERROR_PROVE_DEVICE; + } + s_vpu_irq = irq; + enc_pr(LOG_DEBUG, "HevcEnc - wave420l_irq: %d\n", s_vpu_irq); +#if 0 + rstc = devm_reset_control_get(&pdev->dev, "HevcEnc"); + if (IS_ERR(rstc)) { + enc_pr(LOG_ERROR, + "get HevcEnc rstc error: %lx\n", PTR_ERR(rstc)); + rstc = NULL; + err = -ENOENT; + goto ERROR_PROVE_DEVICE; + } + reset_control_assert(rstc); + s_vpu_rstc = rstc; + + clk = clk_get(&pdev->dev, "clk_HevcEnc"); + if (IS_ERR(clk)) { + enc_pr(LOG_ERROR, "cannot get clock\n"); + clk = NULL; + err = -ENOENT; + goto ERROR_PROVE_DEVICE; + } + s_vpu_clk = clk; +#endif + +#ifdef VPU_SUPPORT_CLOCK_CONTROL +#else + vpu_clk_config(1); +#endif + + np = pdev->dev.of_node; + reg_count = 0; + for_each_child_of_node(np, child) { + if (of_address_to_resource(child, 0, &res) + || (reg_count > 1)) { + enc_pr(LOG_ERROR, + "no reg ranges or more reg ranges %d\n", + reg_count); + err = -ENXIO; + goto ERROR_PROVE_DEVICE; + } + /* if platform driver is implemented */ + if (res.start != 0) { + s_vpu_register.phys_addr = res.start; + s_vpu_register.virt_addr = + (ulong)ioremap_nocache( + res.start, resource_size(&res)); + s_vpu_register.size = res.end - res.start; + enc_pr(LOG_DEBUG, + "vpu base address get from platform driver "); + enc_pr(LOG_DEBUG, + "physical base addr=0x%lx, virtual base=0x%lx\n", + s_vpu_register.phys_addr, + s_vpu_register.virt_addr); + } else { + s_vpu_register.phys_addr = VPU_REG_BASE_ADDR; + s_vpu_register.virt_addr = + (ulong)ioremap_nocache( + s_vpu_register.phys_addr, VPU_REG_SIZE); + s_vpu_register.size = VPU_REG_SIZE; + enc_pr(LOG_DEBUG, + "vpu base address get from defined value "); + enc_pr(LOG_DEBUG, + "physical base addr=0x%lx, virtual base=0x%lx\n", + s_vpu_register.phys_addr, + s_vpu_register.virt_addr); + } + reg_count++; + } + + /* get the major number of the character device */ + if (init_HevcEnc_device()) { + err = -EBUSY; + enc_pr(LOG_ERROR, "could not allocate major number\n"); + goto ERROR_PROVE_DEVICE; + } + enc_pr(LOG_INFO, "SUCCESS alloc_chrdev_region\n"); + + init_waitqueue_head(&s_interrupt_wait_q); + tasklet_init(&hevc_tasklet, + hevcenc_isr_tasklet, + (ulong)&s_vpu_drv_context); + s_common_memory.base = 0; + s_instance_pool.base = 0; + + if (use_reserve == true) { + if (vmem_init(&s_vmem, s_video_memory.phys_addr, + s_video_memory.size) < 0) { + enc_pr(LOG_ERROR, "fail to init vmem system\n"); + goto ERROR_PROVE_DEVICE; + } + enc_pr(LOG_DEBUG, + "success to probe vpu device with video memory "); + enc_pr(LOG_DEBUG, + "phys_addr=0x%lx, base = 0x%lx\n", + (ulong)s_video_memory.phys_addr, + (ulong)s_video_memory.base); + } else + enc_pr(LOG_DEBUG, + "success to probe vpu device with video memory from cma\n"); + hevc_pdev = pdev; + return 0; + +ERROR_PROVE_DEVICE: + if (s_vpu_register.virt_addr) { + iounmap((void *)s_vpu_register.virt_addr); + memset(&s_vpu_register, 0, sizeof(struct vpudrv_buffer_t)); + } + + if (s_video_memory.base) { + vmem_exit(&s_vmem); + memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); + memset(&s_vmem, 0, sizeof(struct video_mm_t)); + } + + vpu_clk_config(0); + + if (s_vpu_irq_requested == true) { + if (s_vpu_irq >= 0) { + free_irq(s_vpu_irq, &s_vpu_drv_context); + s_vpu_irq = -1; + } + s_vpu_irq_requested = false; + } + uninit_HevcEnc_device(); + return err; +} + +static s32 vpu_remove(struct platform_device *pdev) +{ + enc_pr(LOG_DEBUG, "vpu_remove\n"); + + if (s_instance_pool.base) { + vfree((const void *)s_instance_pool.base); + s_instance_pool.base = 0; + } + + if (s_common_memory.base) { + vpu_free_dma_buffer(&s_common_memory); + s_common_memory.base = 0; + } + + if (s_video_memory.base) { + if (!use_reserve) + codec_mm_free_for_dma( + VPU_DEV_NAME, + (u32)s_video_memory.phys_addr); + vmem_exit(&s_vmem); + memset(&s_video_memory, + 0, sizeof(struct vpudrv_buffer_t)); + memset(&s_vmem, + 0, sizeof(struct video_mm_t)); + } + + if (s_vpu_irq_requested == true) { + if (s_vpu_irq >= 0) { + free_irq(s_vpu_irq, &s_vpu_drv_context); + s_vpu_irq = -1; + } + s_vpu_irq_requested = false; + } + + if (s_vpu_register.virt_addr) { + iounmap((void *)s_vpu_register.virt_addr); + memset(&s_vpu_register, + 0, sizeof(struct vpudrv_buffer_t)); + } + hevc_pdev = NULL; + vpu_clk_config(0); + + uninit_HevcEnc_device(); + return 0; +} + +#ifdef CONFIG_PM +static void Wave4BitIssueCommand(u32 core, u32 cmd) +{ + WriteVpuRegister(W4_VPU_BUSY_STATUS, 1); + WriteVpuRegister(W4_CORE_INDEX, 0); + /* coreIdx = ReadVpuRegister(W4_VPU_BUSY_STATUS); */ + /* coreIdx = 0; */ + /* WriteVpuRegister(W4_INST_INDEX, + (instanceIndex & 0xffff) | (codecMode << 16)); */ + WriteVpuRegister(W4_COMMAND, cmd); + WriteVpuRegister(W4_VPU_HOST_INT_REQ, 1); + return; +} + +static s32 vpu_suspend(struct platform_device *pdev, pm_message_t state) +{ + u32 core; + ulong timeout = jiffies + HZ; /* vpu wait timeout to 1sec */ + enc_pr(LOG_DEBUG, "vpu_suspend\n"); + + vpu_clk_config(1); + + if (s_vpu_open_ref_count > 0) { + for (core = 0; core < MAX_NUM_VPU_CORE; core++) { + if (s_bit_firmware_info[core].size == 0) + continue; + while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { + if (time_after(jiffies, timeout)) { + enc_pr(LOG_ERROR, + "SLEEP_VPU BUSY timeout"); + goto DONE_SUSPEND; + } + } + Wave4BitIssueCommand(core, W4_CMD_SLEEP_VPU); + + while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { + if (time_after(jiffies, timeout)) { + enc_pr(LOG_ERROR, + "SLEEP_VPU BUSY timeout"); + goto DONE_SUSPEND; + } + } + if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { + enc_pr(LOG_ERROR, + "SLEEP_VPU failed [0x%x]", + ReadVpuRegister(W4_RET_FAIL_REASON)); + goto DONE_SUSPEND; + } + } + } + + vpu_clk_config(0); + return 0; + +DONE_SUSPEND: + vpu_clk_config(0); + return -EAGAIN; +} +static s32 vpu_resume(struct platform_device *pdev) +{ + u32 i; + u32 core; + u32 val; + ulong timeout = jiffies + HZ; /* vpu wait timeout to 1sec */ + ulong code_base; + u32 code_size; + u32 remap_size; + u32 regVal; + u32 hwOption = 0; + + enc_pr(LOG_DEBUG, "vpu_resume\n"); + + vpu_clk_config(1); + + for (core = 0; core < MAX_NUM_VPU_CORE; core++) { + if (s_bit_firmware_info[core].size == 0) + continue; + code_base = s_common_memory.phys_addr; + /* ALIGN TO 4KB */ + code_size = (s_common_memory.size & ~0xfff); + if (code_size < s_bit_firmware_info[core].size * 2) + goto DONE_WAKEUP; + + /*---- LOAD BOOT CODE */ + for (i = 0; i < 512; i += 2) { + val = s_bit_firmware_info[core].bit_code[i]; + val |= (s_bit_firmware_info[core].bit_code[i+1] << 16); + WriteVpu(code_base+(i*2), val); + } + + regVal = 0; + WriteVpuRegister(W4_PO_CONF, regVal); + + /* Reset All blocks */ + regVal = 0x7ffffff; + WriteVpuRegister(W4_VPU_RESET_REQ, regVal); + + /* Waiting reset done */ + while (ReadVpuRegister(W4_VPU_RESET_STATUS)) { + if (time_after(jiffies, timeout)) + goto DONE_WAKEUP; + } + + WriteVpuRegister(W4_VPU_RESET_REQ, 0); + + /* remap page size */ + remap_size = (code_size >> 12) & 0x1ff; + regVal = 0x80000000 | (W4_REMAP_CODE_INDEX<<12) + | (0 << 16) | (1<<11) | remap_size; + WriteVpuRegister(W4_VPU_REMAP_CTRL, regVal); + /* DO NOT CHANGE! */ + WriteVpuRegister(W4_VPU_REMAP_VADDR, 0x00000000); + WriteVpuRegister(W4_VPU_REMAP_PADDR, code_base); + WriteVpuRegister(W4_ADDR_CODE_BASE, code_base); + WriteVpuRegister(W4_CODE_SIZE, code_size); + WriteVpuRegister(W4_CODE_PARAM, 0); + WriteVpuRegister(W4_INIT_VPU_TIME_OUT_CNT, timeout); + WriteVpuRegister(W4_HW_OPTION, hwOption); + + /* Interrupt */ + regVal = (1 << W4_INT_DEC_PIC_HDR); + regVal |= (1 << W4_INT_DEC_PIC); + regVal |= (1 << W4_INT_QUERY_DEC); + regVal |= (1 << W4_INT_SLEEP_VPU); + regVal |= (1 << W4_INT_BSBUF_EMPTY); + regVal = 0xfffffefe; + WriteVpuRegister(W4_VPU_VINT_ENABLE, regVal); + Wave4BitIssueCommand(core, W4_CMD_INIT_VPU); + WriteVpuRegister(W4_VPU_REMAP_CORE_START, 1); + while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { + if (time_after(jiffies, timeout)) + goto DONE_WAKEUP; + } + + if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { + enc_pr(LOG_ERROR, + "WAKEUP_VPU failed [0x%x]", + ReadVpuRegister(W4_RET_FAIL_REASON)); + goto DONE_WAKEUP; + } + } + + if (s_vpu_open_ref_count == 0) + vpu_clk_config(0); +DONE_WAKEUP: + if (s_vpu_open_ref_count > 0) + vpu_clk_config(1); + return 0; +} +#else +#define vpu_suspend NULL +#define vpu_resume NULL +#endif /* !CONFIG_PM */ + +static const struct of_device_id cnm_hevcenc_dt_match[] = { + { + .compatible = "cnm, HevcEnc", + }, + {}, +}; + +static struct platform_driver vpu_driver = { + .driver = { + .name = VPU_PLATFORM_DEVICE_NAME, + .of_match_table = cnm_hevcenc_dt_match, + }, + .probe = vpu_probe, + .remove = vpu_remove, + .suspend = vpu_suspend, + .resume = vpu_resume, +}; + +static s32 __init vpu_init(void) +{ + s32 res; + enc_pr(LOG_DEBUG, "vpu_init\n"); + if (get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) { + enc_pr(LOG_DEBUG, + "The chip is not support hevc encoder\n"); + return -1; + } + res = platform_driver_register(&vpu_driver); + enc_pr(LOG_INFO, + "end vpu_init result=0x%x\n", res); + return res; +} + +static void __exit vpu_exit(void) +{ + enc_pr(LOG_DEBUG, "vpu_exit\n"); + if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) + platform_driver_unregister(&vpu_driver); + return; +} + +static const struct reserved_mem_ops rmem_hevc_ops = { + .device_init = hevc_mem_device_init, +}; + +static s32 __init hevc_mem_setup(struct reserved_mem *rmem) +{ + rmem->ops = &rmem_hevc_ops; + enc_pr(LOG_DEBUG, "HevcEnc reserved mem setup.\n"); + return 0; +} + +module_param(print_level, uint, 0664); +MODULE_PARM_DESC(print_level, "\n print_level\n"); + +module_param(clock_level, uint, 0664); +MODULE_PARM_DESC(clock_level, "\n clock_level\n"); + +MODULE_AUTHOR("Amlogic using C&M VPU, Inc."); +MODULE_DESCRIPTION("VPU linux driver"); +MODULE_LICENSE("GPL"); + +module_init(vpu_init); +module_exit(vpu_exit); +RESERVEDMEM_OF_DECLARE(cnm_hevc, "cnm, HevcEnc-memory", hevc_mem_setup); diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h new file mode 100644 index 000000000000..eaed0b794f21 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h @@ -0,0 +1,288 @@ +/* + * vpu.h + * + * linux device driver for VPU. + * + * Copyright (C) 2006 - 2013 CHIPS&MEDIA INC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef __VPU_DRV_H__ +#define __VPU_DRV_H__ + +#include +#include +#include + +#define MAX_INST_HANDLE_SIZE (32*1024) +#define MAX_NUM_INSTANCE 4 +#define MAX_NUM_VPU_CORE 1 + +#define W4_CMD_INIT_VPU (0x0001) +#define W4_CMD_SLEEP_VPU (0x0400) +#define W4_CMD_WAKEUP_VPU (0x0800) + +/* GXM: 2000/10 = 200M */ +#define HevcEnc_L0() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (3 << 25) | (1 << 16) | (3 << 9) | (1 << 0)) +/* GXM: 2000/8 = 250M */ +#define HevcEnc_L1() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (1 << 25) | (1 << 16) | (1 << 9) | (1 << 0)) +/* GXM: 2000/7 = 285M */ +#define HevcEnc_L2() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (4 << 25) | (0 << 16) | (4 << 9) | (0 << 0)) +/*GXM: 2000/6 = 333M */ +#define HevcEnc_L3() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (2 << 25) | (1 << 16) | (2 << 9) | (1 << 0)) +/* GXM: 2000/5 = 400M */ +#define HevcEnc_L4() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (3 << 25) | (0 << 16) | (3 << 9) | (0 << 0)) +/* GXM: 2000/4 = 500M */ +#define HevcEnc_L5() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (1 << 25) | (0 << 16) | (1 << 9) | (0 << 0)) +/* GXM: 2000/3 = 667M */ +#define HevcEnc_L6() WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + (2 << 25) | (0 << 16) | (2 << 9) | (0 << 0)) + +#define HevcEnc_clock_enable(level) \ + do { \ + WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + READ_HHI_REG(HHI_WAVE420L_CLK_CNTL) \ + & (~(1 << 8)) & (~(1 << 24))); \ + if (level == 0) \ + HevcEnc_L0(); \ + else if (level == 1) \ + HevcEnc_L1(); \ + else if (level == 2) \ + HevcEnc_L2(); \ + else if (level == 3) \ + HevcEnc_L3(); \ + else if (level == 4) \ + HevcEnc_L4(); \ + else if (level == 5) \ + HevcEnc_L5(); \ + else if (level == 6) \ + HevcEnc_L6(); \ + WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + READ_HHI_REG(HHI_WAVE420L_CLK_CNTL) \ + | (1 << 8) | (1 << 24)); \ + } while (0) + +#define HevcEnc_clock_disable() \ + WRITE_HHI_REG(HHI_WAVE420L_CLK_CNTL, \ + READ_HHI_REG(HHI_WAVE420L_CLK_CNTL) \ + & (~(1 << 8)) & (~(1 << 24))); + +struct compat_vpudrv_buffer_t { + u32 size; + u32 cached; + compat_ulong_t phys_addr; + compat_ulong_t base; /* kernel logical address in use kernel */ + compat_ulong_t virt_addr; /* virtual user space address */ +}; + +struct vpudrv_buffer_t { + u32 size; + u32 cached; + ulong phys_addr; + ulong base; /* kernel logical address in use kernel */ + ulong virt_addr; /* virtual user space address */ +}; + +struct vpu_bit_firmware_info_t { + u32 size; /* size of this structure*/ + u32 core_idx; + u32 reg_base_offset; + u16 bit_code[512]; +}; + +struct vpudrv_inst_info_t { + u32 core_idx; + u32 inst_idx; + s32 inst_open_count; /* for output only*/ +}; + +struct vpudrv_intr_info_t { + u32 timeout; + s32 intr_reason; +}; + +struct vpu_drv_context_t { + struct fasync_struct *async_queue; + ulong interrupt_reason; + u32 open_count; /*!<< device reference count. Not instance count */ +}; + +/* To track the allocated memory buffer */ +struct vpudrv_buffer_pool_t { + struct list_head list; + struct vpudrv_buffer_t vb; + struct file *filp; +}; + +/* To track the instance index and buffer in instance pool */ +struct vpudrv_instanace_list_t { + struct list_head list; + ulong inst_idx; + ulong core_idx; + struct file *filp; +}; + +struct vpudrv_instance_pool_t { + u8 codecInstPool[MAX_NUM_INSTANCE][MAX_INST_HANDLE_SIZE]; +}; + +#define VPUDRV_BUF_LEN struct vpudrv_buffer_t +#define VPUDRV_BUF_LEN32 struct compat_vpudrv_buffer_t +#define VPUDRV_INST_LEN struct vpudrv_inst_info_t + +#define VDI_MAGIC 'V' +#define VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY \ + _IOW(VDI_MAGIC, 0, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_FREE_PHYSICALMEMORY \ + _IOW(VDI_MAGIC, 1, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_WAIT_INTERRUPT \ + _IOW(VDI_MAGIC, 2, struct vpudrv_intr_info_t) + +#define VDI_IOCTL_SET_CLOCK_GATE \ + _IOW(VDI_MAGIC, 3, u32) + +#define VDI_IOCTL_RESET \ + _IOW(VDI_MAGIC, 4, u32) + +#define VDI_IOCTL_GET_INSTANCE_POOL \ + _IOW(VDI_MAGIC, 5, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_GET_COMMON_MEMORY \ + _IOW(VDI_MAGIC, 6, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO \ + _IOW(VDI_MAGIC, 8, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_OPEN_INSTANCE \ + _IOW(VDI_MAGIC, 9, VPUDRV_INST_LEN) + +#define VDI_IOCTL_CLOSE_INSTANCE \ + _IOW(VDI_MAGIC, 10, VPUDRV_INST_LEN) + +#define VDI_IOCTL_GET_INSTANCE_NUM \ + _IOW(VDI_MAGIC, 11, VPUDRV_INST_LEN) + +#define VDI_IOCTL_GET_REGISTER_INFO \ + _IOW(VDI_MAGIC, 12, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_FLUSH_BUFFER \ + _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN) + +#define VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32 \ + _IOW(VDI_MAGIC, 0, VPUDRV_BUF_LEN32) + +#define VDI_IOCTL_FREE_PHYSICALMEMORY32 \ + _IOW(VDI_MAGIC, 1, VPUDRV_BUF_LEN32) + +#define VDI_IOCTL_GET_INSTANCE_POOL32 \ + _IOW(VDI_MAGIC, 5, VPUDRV_BUF_LEN32) + +#define VDI_IOCTL_GET_COMMON_MEMORY32 \ + _IOW(VDI_MAGIC, 6, VPUDRV_BUF_LEN32) + +#define VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32 \ + _IOW(VDI_MAGIC, 8, VPUDRV_BUF_LEN32) + +#define VDI_IOCTL_GET_REGISTER_INFO32 \ + _IOW(VDI_MAGIC, 12, VPUDRV_BUF_LEN32) + +#define VDI_IOCTL_FLUSH_BUFFER32 \ + _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN32) + +enum { + W4_INT_INIT_VPU = 0, + W4_INT_DEC_PIC_HDR = 1, + W4_INT_SET_PARAM = 1, + W4_INT_ENC_INIT_SEQ = 1, + W4_INT_FINI_SEQ = 2, + W4_INT_DEC_PIC = 3, + W4_INT_ENC_PIC = 3, + W4_INT_SET_FRAMEBUF = 4, + W4_INT_FLUSH_DEC = 5, + W4_INT_ENC_SLICE_INT = 7, + W4_INT_GET_FW_VERSION = 8, + W4_INT_QUERY_DEC = 9, + W4_INT_SLEEP_VPU = 10, + W4_INT_WAKEUP_VPU = 11, + W4_INT_CHANGE_INT = 12, + W4_INT_CREATE_INSTANCE = 14, + W4_INT_BSBUF_EMPTY = 15, + /*!<< Bitstream buffer empty[dec]/full[enc] */ +}; + +/* WAVE4 registers */ +#define VPU_REG_BASE_ADDR 0xc8810000 +#define VPU_REG_SIZE (0x4000 * MAX_NUM_VPU_CORE) + +#define W4_REG_BASE 0x0000 +#define W4_VPU_BUSY_STATUS (W4_REG_BASE + 0x0070) +#define W4_VPU_INT_REASON_CLEAR (W4_REG_BASE + 0x0034) +#define W4_VPU_VINT_CLEAR (W4_REG_BASE + 0x003C) +#define W4_VPU_VPU_INT_STS (W4_REG_BASE + 0x0044) +#define W4_VPU_INT_REASON (W4_REG_BASE + 0x004c) + +#define W4_RET_SUCCESS (W4_REG_BASE + 0x0110) +#define W4_RET_FAIL_REASON (W4_REG_BASE + 0x0114) + +/* WAVE4 INIT, WAKEUP */ +#define W4_PO_CONF (W4_REG_BASE + 0x0000) +#define W4_VCPU_CUR_PC (W4_REG_BASE + 0x0004) + +#define W4_VPU_VINT_ENABLE (W4_REG_BASE + 0x0048) + +#define W4_VPU_RESET_REQ (W4_REG_BASE + 0x0050) +#define W4_VPU_RESET_STATUS (W4_REG_BASE + 0x0054) + +#define W4_VPU_REMAP_CTRL (W4_REG_BASE + 0x0060) +#define W4_VPU_REMAP_VADDR (W4_REG_BASE + 0x0064) +#define W4_VPU_REMAP_PADDR (W4_REG_BASE + 0x0068) +#define W4_VPU_REMAP_CORE_START (W4_REG_BASE + 0x006C) +#define W4_VPU_BUSY_STATUS (W4_REG_BASE + 0x0070) + +#define W4_HW_OPTION (W4_REG_BASE + 0x0124) +#define W4_CODE_SIZE (W4_REG_BASE + 0x011C) +/* Note: W4_INIT_CODE_BASE_ADDR should be aligned to 4KB */ +#define W4_ADDR_CODE_BASE (W4_REG_BASE + 0x0118) +#define W4_CODE_PARAM (W4_REG_BASE + 0x0120) +#define W4_INIT_VPU_TIME_OUT_CNT (W4_REG_BASE + 0x0134) + +/* WAVE4 Wave4BitIssueCommand */ +#define W4_CORE_INDEX (W4_REG_BASE + 0x0104) +#define W4_INST_INDEX (W4_REG_BASE + 0x0108) +#define W4_COMMAND (W4_REG_BASE + 0x0100) +#define W4_VPU_HOST_INT_REQ (W4_REG_BASE + 0x0038) + +#define W4_BS_RD_PTR (W4_REG_BASE + 0x0130) +#define W4_BS_WR_PTR (W4_REG_BASE + 0x0134) +#define W4_RET_ENC_PIC_BYTE (W4_REG_BASE + 0x01C8) + +#define W4_REMAP_CODE_INDEX 0 + +#define ReadVpuRegister(addr) \ + readl((void __iomem *)(s_vpu_register.virt_addr \ + + s_bit_firmware_info[core].reg_base_offset + addr)) + +#define WriteVpuRegister(addr, val) \ + writel((u32)val, (void __iomem *)(s_vpu_register.virt_addr \ + + s_bit_firmware_info[core].reg_base_offset + addr)) + +#define WriteVpu(addr, val) writel((u32)val, (void __iomem *)addr) +#endif diff --git a/drivers/amlogic/media_modules/include/dummy-for-git-empty-dir b/drivers/amlogic/media_modules/include/dummy-for-git-empty-dir new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/drivers/amlogic/media_modules/stream_input/Makefile b/drivers/amlogic/media_modules/stream_input/Makefile new file mode 100644 index 000000000000..7d6a2c0dbaba --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/Makefile @@ -0,0 +1,10 @@ +obj-m += stream_input.o +stream_input-objs += amports/amstream.o +stream_input-objs += amports/amstream_profile.o +stream_input-objs += amports/adec.o +stream_input-objs += parser/thread_rw.o +stream_input-objs += parser/streambuf.o +stream_input-objs += parser/esparser.o +stream_input-objs += parser/tsdemux.o +stream_input-objs += parser/psparser.o +stream_input-objs += parser/rmparser.o diff --git a/drivers/amlogic/media_modules/stream_input/amports/Makefile b/drivers/amlogic/media_modules/stream_input/amports/Makefile new file mode 100644 index 000000000000..55fbdce8aa7a --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/amports/Makefile @@ -0,0 +1,2 @@ +obj-y += amports.o +amports-objs += amstream.o amstream_profile.o adec.o diff --git a/drivers/amlogic/media_modules/stream_input/amports/adec.c b/drivers/amlogic/media_modules/stream_input/amports/adec.c new file mode 100644 index 000000000000..220c888c9a48 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/amports/adec.c @@ -0,0 +1,295 @@ +/* + * drivers/amlogic/media/stream_input/amports/adec.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "../parser/streambuf.h" +#include +#include "amports_priv.h" + +#define INFO_VALID ((astream_dev) && (astream_dev->format)) + +struct astream_device_s { + char *name; + char *format; + s32 channum; + s32 samplerate; + s32 datawidth; + + struct device dev; +}; + +static char *astream_format[] = { + "amadec_mpeg", + "amadec_pcm_s16le", + "amadec_aac", + "amadec_ac3", + "amadec_alaw", + "amadec_mulaw", + "amadec_dts", + "amadec_pcm_s16be", + "amadec_flac", + "amadec_cook", + "amadec_pcm_u8", + "amadec_adpcm", + "amadec_amr", + "amadec_raac", + "amadec_wma", + "amadec_wmapro", + "amadec_pcm_bluray", + "amadec_alac", + "amadec_vorbis", + "amadec_aac_latm", + "amadec_ape", + "amadec_eac3", + "amadec_pcm_widi", + "amadec_wmavoi" +}; + +static const char *na_string = "NA"; +static struct astream_device_s *astream_dev; + +static ssize_t format_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + if (INFO_VALID && astream_dev->format) + return sprintf(buf, "%s\n", astream_dev->format); + else + return sprintf(buf, "%s\n", na_string); +} + +static ssize_t channum_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + if (INFO_VALID) + return sprintf(buf, "%u\n", astream_dev->channum); + else + return sprintf(buf, "%s\n", na_string); +} + +static ssize_t samplerate_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + if (INFO_VALID) + return sprintf(buf, "%u\n", astream_dev->samplerate); + else + return sprintf(buf, "%s\n", na_string); +} + +static ssize_t datawidth_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + if (INFO_VALID) + return sprintf(buf, "%u\n", astream_dev->datawidth); + else + return sprintf(buf, "%s\n", na_string); +} + +static ssize_t pts_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + u32 pts; + u32 pts_margin = 0; + + if (astream_dev->samplerate <= 12000) + pts_margin = 512; + + if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts, pts_margin) >= 0)) + return sprintf(buf, "0x%x\n", pts); + else + return sprintf(buf, "%s\n", na_string); +} + +static struct class_attribute astream_class_attrs[] = { + __ATTR_RO(format), + __ATTR_RO(samplerate), + __ATTR_RO(channum), + __ATTR_RO(datawidth), + __ATTR_RO(pts), + __ATTR_NULL +}; + +static struct class astream_class = { + .name = "astream", + .class_attrs = astream_class_attrs, + }; + +#if 1 +#define IO_CBUS_PHY_BASE 0xc1100000 +#define CBUS_REG_OFFSET(reg) ((reg) << 2) +#define IO_SECBUS_PHY_BASE 0xda000000 + +static struct uio_info astream_uio_info = { + .name = "astream_uio", + .version = "0.1", + .irq = UIO_IRQ_NONE, + + .mem = { + [0] = { + .name = "AIFIFO", + .memtype = UIO_MEM_PHYS, + .addr = + (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL)) + &(PAGE_MASK), + .size = PAGE_SIZE, + }, + [1] = { + .memtype = UIO_MEM_PHYS, + .addr = + (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(VCOP_CTRL_REG)), + .size = PAGE_SIZE, + }, + [2] = { + .name = "SECBUS", + .memtype = UIO_MEM_PHYS, + .addr = (IO_SECBUS_PHY_BASE), + .size = PAGE_SIZE, + }, + [3] = { + .name = "CBUS", + .memtype = UIO_MEM_PHYS, + .addr = + (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(ASSIST_HW_REV)) + &(PAGE_MASK), + .size = PAGE_SIZE, + }, + [4] = { + .name = "CBUS-START", + .memtype = UIO_MEM_PHYS, + .addr = (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(0x1000)), + .size = PAGE_SIZE * 4, + }, + }, +}; +#endif + +static void astream_release(struct device *dev) +{ + kfree(astream_dev); + + astream_dev = NULL; +} + +s32 adec_init(struct stream_port_s *port) +{ + enum aformat_e af; + + if (!astream_dev) + return -ENODEV; + + af = port->aformat; + + astream_dev->channum = port->achanl; + astream_dev->samplerate = port->asamprate; + astream_dev->datawidth = port->adatawidth; + + /*wmb();don't need it...*/ + if (af <= ARRAY_SIZE(astream_format)) + astream_dev->format = astream_format[af]; + else + astream_dev->format = NULL; + return 0; +} + +s32 adec_release(enum aformat_e vf) +{ + pr_info("adec_release\n"); + + if (!astream_dev) + return -ENODEV; + + astream_dev->format = NULL; + + return 0; +} + +s32 astream_dev_register(void) +{ + s32 r; + + r = class_register(&astream_class); + if (r) { + pr_info("astream class create fail.\n"); + return r; + } + + astream_dev = kzalloc(sizeof(struct astream_device_s), GFP_KERNEL); + + if (!astream_dev) { + r = -ENOMEM; + goto err_3; + } + + astream_dev->dev.class = &astream_class; + astream_dev->dev.release = astream_release; + + dev_set_name(&astream_dev->dev, "astream-dev"); + + dev_set_drvdata(&astream_dev->dev, astream_dev); + + r = device_register(&astream_dev->dev); + if (r) { + pr_info("astream device register fail.\n"); + goto err_2; + } + +#if 1 + if (uio_register_device(&astream_dev->dev, &astream_uio_info)) { + pr_info("astream UIO device register fail.\n"); + r = -ENODEV; + goto err_1; + } +#endif + + return 0; + +err_1: + device_unregister(&astream_dev->dev); + +err_2: + kfree(astream_dev); + astream_dev = NULL; + +err_3: + class_unregister(&astream_class); + + return r; +} + +void astream_dev_unregister(void) +{ + if (astream_dev) { +#if 1 + uio_unregister_device(&astream_uio_info); +#endif + + device_unregister(&astream_dev->dev); + + class_unregister(&astream_class); + } +} diff --git a/drivers/amlogic/media_modules/stream_input/amports/adec.h b/drivers/amlogic/media_modules/stream_input/amports/adec.h new file mode 100644 index 000000000000..545ac76cb8e2 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/amports/adec.h @@ -0,0 +1,32 @@ +/* + * drivers/amlogic/media/stream_input/amports/adec.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef ADEC_H +#define ADEC_H + +#include "../parser/streambuf.h" +#include + +extern s32 adec_init(struct stream_port_s *port); + +extern s32 adec_release(enum aformat_e af); + +extern s32 astream_dev_register(void); + +extern s32 astream_dev_unregister(void); + +#endif /* ADEC_H */ diff --git a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h new file mode 100644 index 000000000000..4b6f96e46dfa --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h @@ -0,0 +1,56 @@ +/* + * drivers/amlogic/media/stream_input/amports/amports_priv.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef AMPORTS_PRIV_HEAD_HH +#define AMPORTS_PRIV_HEAD_HH +#include "../parser/streambuf.h" +#include "../../common/media_clock/switch/amports_gate.h" +#include +#include "../../common/firmware/firmware.h" +#include +#include + +struct port_priv_s { + struct vdec_s *vdec; + struct stream_port_s *port; +}; + +struct stream_buf_s *get_buf_by_type(u32 type); + +extern void amvenc_dos_top_reg_fix(void); + +/*video.c provide*/ +extern u32 trickmode_i; +struct amvideocap_req; +extern u32 set_blackout_policy(int policy); +extern u32 get_blackout_policy(void); +int calculation_stream_ext_delayed_ms(u8 type); +int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index); +int ext_put_video_frame(struct vframe_s *vf); +int ext_register_end_frame_callback(struct amvideocap_req *req); +int amstream_request_firmware_from_sys(const char *file_name, + char *buf, int size); +void set_vsync_pts_inc_mode(int inc); + +void set_real_audio_info(void *arg); +#define dbg() pr_info("on %s,line %d\n", __func__, __LINE__) + +struct device *amports_get_dma_device(void); +struct device *get_codec_cma_device(void); +int amports_get_debug_flags(void); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream.c b/drivers/amlogic/media_modules/stream_input/amports/amstream.c new file mode 100644 index 000000000000..f1d2c740bbb2 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/amports/amstream.c @@ -0,0 +1,3651 @@ +/* + * drivers/amlogic/media/stream_input/amports/amstream.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +/* #include */ + +#include +#include +#include +#include +#include +#include +#include +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* #include */ +/* #include */ +#endif +#include "../parser/streambuf.h" +#include "../parser/streambuf_reg.h" +#include "../parser/tsdemux.h" +#include "../parser/psparser.h" +#include "../parser/esparser.h" +#include "../../frame_provider/decoder/utils/vdec.h" +#include "adec.h" +#include "../parser/rmparser.h" +#include "amports_priv.h" +#include +#include +#include "../parser/thread_rw.h" + + +#include + +#include +#include +#include +#include +#include +#include "../../common/firmware/firmware.h" +#ifdef CONFIG_COMPAT +#include +#endif +#include + +#define CONFIG_AM_VDEC_REAL //DEBUG_TMP + +#define DEVICE_NAME "amstream-dev" +#define DRIVER_NAME "amstream" +#define MODULE_NAME "amstream" + +#define MAX_AMSTREAM_PORT_NUM ARRAY_SIZE(ports) +u32 amstream_port_num; +u32 amstream_buf_num; + +#if 0 +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV +#define NO_VDEC2_INIT 1 +#elif MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD +#define NO_VDEC2_INIT IS_MESON_M8M2_CPU +#endif +#endif +#define NO_VDEC2_INIT 1 + + +static int debugflags; + +#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) +#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) + + +#define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2) +#define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256) + +static int def_4k_vstreambuf_sizeM = + (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); +static int def_vstreambuf_sizeM = + (DEFAULT_VIDEO_BUFFER_SIZE >> 20); +static int debugflags; +static int slow_input; + + + + +/* #define DATA_DEBUG */ +static int use_bufferlevelx10000 = 10000; +static int reset_canuse_buferlevel(int level); +static struct platform_device *amstream_pdev; +struct device *amports_get_dma_device(void) +{ + return &amstream_pdev->dev; +} +EXPORT_SYMBOL(amports_get_dma_device); + +/* +*bit0:no threadrw +*/ +int amports_get_debug_flags(void) +{ + return debugflags; +} + +#ifdef DATA_DEBUG +#include + +#define DEBUG_FILE_NAME "/sdcard/debug.tmp" +static struct file *debug_filp; +static loff_t debug_file_pos; + +void debug_file_write(const char __user *buf, size_t count) +{ + mm_segment_t old_fs; + + if (!debug_filp) + return; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + if (count != vfs_write(debug_filp, buf, count, &debug_file_pos)) + pr_err("Failed to write debug file\n"); + + set_fs(old_fs); +} +#endif + + + +static int amstream_open(struct inode *inode, struct file *file); +static int amstream_release(struct inode *inode, struct file *file); +static long amstream_ioctl(struct file *file, unsigned int cmd, ulong arg); +#ifdef CONFIG_COMPAT +static long amstream_compat_ioctl + (struct file *file, unsigned int cmd, ulong arg); +#endif +static ssize_t amstream_vbuf_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +static ssize_t amstream_vframe_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +static ssize_t amstream_abuf_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +static ssize_t amstream_mpts_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +static ssize_t amstream_mpps_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +static ssize_t amstream_sub_read +(struct file *file, char *buf, size_t count, loff_t *ppos); +static ssize_t amstream_sub_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +static unsigned int amstream_sub_poll +(struct file *file, poll_table *wait_table); +static unsigned int amstream_userdata_poll +(struct file *file, poll_table *wait_table); +static ssize_t amstream_userdata_read +(struct file *file, char *buf, size_t count, loff_t *ppos); +static int (*amstream_adec_status) +(struct adec_status *astatus); +#ifdef CONFIG_AM_VDEC_REAL +static ssize_t amstream_mprm_write +(struct file *file, const char *buf, size_t count, loff_t *ppos); +#endif + +static const struct file_operations vbuf_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .write = amstream_vbuf_write, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations vframe_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .write = amstream_vframe_write, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations abuf_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .write = amstream_abuf_write, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations mpts_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .write = amstream_mpts_write, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations mpps_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .write = amstream_mpps_write, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations mprm_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, +#ifdef CONFIG_AM_VDEC_REAL + .write = amstream_mprm_write, +#endif + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations sub_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .write = amstream_sub_write, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations sub_read_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .read = amstream_sub_read, + .poll = amstream_sub_poll, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations userdata_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .read = amstream_userdata_read, + .poll = amstream_userdata_poll, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +static const struct file_operations amstream_fops = { + .owner = THIS_MODULE, + .open = amstream_open, + .release = amstream_release, + .unlocked_ioctl = amstream_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amstream_compat_ioctl, +#endif +}; + +/**************************************************/ +static struct audio_info audio_dec_info; +static struct class *amstream_dev_class; +static DEFINE_MUTEX(amstream_mutex); + +atomic_t subdata_ready = ATOMIC_INIT(0); +static int sub_type; +static int sub_port_inited; +/* wait queue for poll */ +static wait_queue_head_t amstream_sub_wait; +atomic_t userdata_ready = ATOMIC_INIT(0); +static int userdata_length; +static wait_queue_head_t amstream_userdata_wait; +#define USERDATA_FIFO_NUM 1024 +static struct userdata_poc_info_t userdata_poc_info[USERDATA_FIFO_NUM]; +static int userdata_poc_ri = 0, userdata_poc_wi; + +static struct stream_port_s ports[] = { +#ifdef CONFIG_MULTI_DEC + { + .name = "amstream_vbuf", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO, + .fops = &vbuf_fops, + }, + { + .name = "amstream_vbuf_sched", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | + PORT_TYPE_DECODER_SCHED, + .fops = &vbuf_fops, + }, + { + .name = "amstream_vframe", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | + PORT_TYPE_FRAME | PORT_TYPE_DECODER_SCHED, + .fops = &vframe_fops, + }, +#else + { + .name = "amstream_vbuf", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO, + .fops = &vbuf_fops, + }, +#endif + { + .name = "amstream_abuf", + .type = PORT_TYPE_ES | PORT_TYPE_AUDIO, + .fops = &abuf_fops, + }, +#ifdef CONFIG_MULTI_DEC + { + .name = "amstream_mpts", + .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO | + PORT_TYPE_AUDIO | PORT_TYPE_SUB, + .fops = &mpts_fops, + }, + { + .name = "amstream_mpts_sched", + .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO | + PORT_TYPE_AUDIO | PORT_TYPE_SUB | + PORT_TYPE_DECODER_SCHED, + .fops = &mpts_fops, + }, +#else + { + .name = "amstream_mpts", + .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO | + PORT_TYPE_AUDIO | PORT_TYPE_SUB, + .fops = &mpts_fops, + }, +#endif + { + .name = "amstream_mpps", + .type = PORT_TYPE_MPPS | PORT_TYPE_VIDEO | + PORT_TYPE_AUDIO | PORT_TYPE_SUB, + .fops = &mpps_fops, + }, + { + .name = "amstream_rm", + .type = PORT_TYPE_RM | PORT_TYPE_VIDEO | PORT_TYPE_AUDIO, + .fops = &mprm_fops, + }, + { + .name = "amstream_sub", + .type = PORT_TYPE_SUB, + .fops = &sub_fops, + }, + { + .name = "amstream_sub_read", + .type = PORT_TYPE_SUB_RD, + .fops = &sub_read_fops, + }, + { + .name = "amstream_userdata", + .type = PORT_TYPE_USERDATA, + .fops = &userdata_fops, + }, +#ifdef CONFIG_MULTI_DEC + { + .name = "amstream_hevc", +#ifdef CONFIG_AM_VDEC_DV +/*test dobly vision, remove later*/ + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | + PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC, + .fops = &vbuf_fops, + .vformat = VFORMAT_HEVC, +#else + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC, + .fops = &vbuf_fops, + .vformat = VFORMAT_HEVC, +#endif + }, + { + .name = "amstream_hevc_frame", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | + PORT_TYPE_FRAME | PORT_TYPE_DECODER_SCHED, + .fops = &vframe_fops, + .vformat = VFORMAT_HEVC, + }, + { + .name = "amstream_hevc_sched", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | + PORT_TYPE_DECODER_SCHED, + .fops = &vbuf_fops, + .vformat = VFORMAT_HEVC, + } +#ifdef CONFIG_AM_VDEC_DV + , + { + .name = "amstream_dves_avc", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | + PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC, + .fops = &vbuf_fops, + }, + { + .name = "amstream_dves_hevc", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | + PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC, + .fops = &vbuf_fops, + .vformat = VFORMAT_HEVC, + } +#endif +#else + { + .name = "amstream_hevc", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC, + .fops = &vbuf_fops, + .vformat = VFORMAT_HEVC, + } +#endif +}; + +static struct stream_buf_s bufs[BUF_MAX_NUM] = { + { + .reg_base = VLD_MEM_VIFIFO_REG_BASE, + .type = BUF_TYPE_VIDEO, + .buf_start = 0, + .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, + .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = AIU_MEM_AIFIFO_REG_BASE, + .type = BUF_TYPE_AUDIO, + .buf_start = 0, + .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, + .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = 0, + .type = BUF_TYPE_SUBTITLE, + .buf_start = 0, + .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, + .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = 0, + .type = BUF_TYPE_USERDATA, + .buf_start = 0, + .buf_size = 0, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = HEVC_STREAM_REG_BASE, + .type = BUF_TYPE_HEVC, + .buf_start = 0, + .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, + .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, + .first_tstamp = INVALID_PTS + }, +}; + +struct stream_buf_s *get_buf_by_type(u32 type) +{ + if (PTS_TYPE_VIDEO == type) + return &bufs[BUF_TYPE_VIDEO]; + if (PTS_TYPE_AUDIO == type) + return &bufs[BUF_TYPE_AUDIO]; + if (has_hevc_vdec()) { + if (PTS_TYPE_HEVC == type) + return &bufs[BUF_TYPE_HEVC]; + } + + return NULL; +} + +void set_sample_rate_info(int arg) +{ + audio_dec_info.sample_rate = arg; + audio_dec_info.valid = 1; +} + +void set_ch_num_info(int arg) +{ + audio_dec_info.channels = arg; +} + +struct audio_info *get_audio_info(void) +{ + return &audio_dec_info; +} +EXPORT_SYMBOL(get_audio_info); + +static void amstream_change_vbufsize(struct port_priv_s *priv, + struct stream_buf_s *pvbuf) +{ + if (pvbuf->buf_start != 0) { + pr_info("streambuf is alloced before\n"); + return; + } + if (pvbuf->for_4k) { + pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M; + if (codec_mm_video_tvp_enabled()) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP; + if ((pvbuf->buf_size > 30 * SZ_1M) && + (codec_mm_get_total_size() < 220 * SZ_1M)) { + /*if less than 250M, used 20M for 4K & 265*/ + pvbuf->buf_size = pvbuf->buf_size >> 1; + } + } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { + if (codec_mm_video_tvp_enabled()) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; + } else { + pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; + if (codec_mm_video_tvp_enabled()) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; + } + reset_canuse_buferlevel(10000); +} + +static bool port_get_inited(struct port_priv_s *priv) +{ + struct stream_port_s *port = priv->port; + + if (port->type & PORT_TYPE_VIDEO) { + struct vdec_s *vdec = priv->vdec; + + return vdec->port_flag & PORT_FLAG_INITED; + } + + return port->flag & PORT_FLAG_INITED; +} + +static void port_set_inited(struct port_priv_s *priv) +{ + struct stream_port_s *port = priv->port; + + if (port->type & PORT_TYPE_VIDEO) { + struct vdec_s *vdec = priv->vdec; + + vdec->port_flag |= PORT_FLAG_INITED; + } else + port->flag |= PORT_FLAG_INITED; +} + +static void video_port_release(struct port_priv_s *priv, + struct stream_buf_s *pbuf, int release_num) +{ + struct stream_port_s *port = priv->port; + struct vdec_s *vdec = priv->vdec; + + switch (release_num) { + default: + /*fallthrough*/ + case 0: /*release all */ + /*fallthrough*/ + case 4: + if ((port->type & PORT_TYPE_FRAME) == 0) + esparser_release(pbuf); + /*fallthrough*/ + case 3: + if (vdec->slave) + vdec_release(vdec->slave); + vdec_release(vdec); + priv->vdec = NULL; + /*fallthrough*/ + case 2: + if ((port->type & PORT_TYPE_FRAME) == 0) + stbuf_release(pbuf); + /*fallthrough*/ + case 1: + ; + } +} + +static int video_port_init(struct port_priv_s *priv, + struct stream_buf_s *pbuf) +{ + int r; + struct stream_port_s *port = priv->port; + struct vdec_s *vdec = priv->vdec; + + if ((port->flag & PORT_FLAG_VFORMAT) == 0) { + pr_err("vformat not set\n"); + return -EPERM; + } + + if (port->vformat == VFORMAT_H264_4K2K || + (priv->vdec->sys_info->height * + priv->vdec->sys_info->width) > 1920*1088) { + pbuf->for_4k = 1; + } else { + pbuf->for_4k = 0; + } + + if (port->type & PORT_TYPE_FRAME) { + r = vdec_init(vdec, + (priv->vdec->sys_info->height * + priv->vdec->sys_info->width) > 1920*1088); + if (r < 0) { + pr_err("video_port_init %d, vdec_init failed\n", + __LINE__); + video_port_release(priv, pbuf, 2); + return r; + } + + return 0; + } + + amstream_change_vbufsize(priv, pbuf); + + if (has_hevc_vdec()) { + if (port->type & PORT_TYPE_MPTS) { + if (pbuf->type == BUF_TYPE_HEVC) + vdec_poweroff(VDEC_1); + else + vdec_poweroff(VDEC_HEVC); + } + } + + r = stbuf_init(pbuf, vdec); + if (r < 0) { + pr_err("video_port_init %d, stbuf_init failed\n", __LINE__); + return r; + } + + /* todo: set path based on port flag */ + r = vdec_init(vdec, + (priv->vdec->sys_info->height * + priv->vdec->sys_info->width) > 1920*1088); + + if (r < 0) { + pr_err("video_port_init %d, vdec_init failed\n", __LINE__); + video_port_release(priv, pbuf, 2); + return r; + } + + if (vdec_dual(vdec)) { + r = vdec_init(vdec->slave, + (priv->vdec->sys_info->height * + priv->vdec->sys_info->width) > 1920*1088); + if (r < 0) { + pr_err("video_port_init %d, vdec_init failed\n", + __LINE__); + video_port_release(priv, pbuf, 2); + return r; + } + } + + if (port->type & PORT_TYPE_ES) { + r = esparser_init(pbuf, vdec); + if (r < 0) { + video_port_release(priv, pbuf, 3); + pr_err("esparser_init() failed\n"); + return r; + } + } + + pbuf->flag |= BUF_FLAG_IN_USE; + + vdec_connect(priv->vdec); + + return 0; +} + +static void audio_port_release(struct stream_port_s *port, + struct stream_buf_s *pbuf, int release_num) +{ + switch (release_num) { + default: + /*fallthrough*/ + case 0: /*release all */ + /*fallthrough*/ + case 4: + esparser_release(pbuf); + /*fallthrough*/ + case 3: + adec_release(port->vformat); + /*fallthrough*/ + case 2: + stbuf_release(pbuf); + /*fallthrough*/ + case 1: + ; + } +} + +static int audio_port_reset(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int r; + + if ((port->flag & PORT_FLAG_AFORMAT) == 0) { + pr_err("aformat not set\n"); + return 0; + } + + pts_stop(PTS_TYPE_AUDIO); + + stbuf_release(pbuf); + + r = stbuf_init(pbuf, NULL); + if (r < 0) + return r; + + r = adec_init(port); + if (r < 0) { + audio_port_release(port, pbuf, 2); + return r; + } + + if (port->type & PORT_TYPE_ES) + esparser_audio_reset_s(pbuf); + + if (port->type & PORT_TYPE_MPTS) + tsdemux_audio_reset(); + + if (port->type & PORT_TYPE_MPPS) + psparser_audio_reset(); + +#ifdef CONFIG_AM_VDEC_REAL + if (port->type & PORT_TYPE_RM) + rm_audio_reset(); +#endif + + pbuf->flag |= BUF_FLAG_IN_USE; + + pts_start(PTS_TYPE_AUDIO); + + return 0; +} + +static int sub_port_reset(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int r; + + port->flag &= (~PORT_FLAG_INITED); + + stbuf_release(pbuf); + + r = stbuf_init(pbuf, NULL); + if (r < 0) + return r; + + if (port->type & PORT_TYPE_MPTS) + tsdemux_sub_reset(); + + if (port->type & PORT_TYPE_MPPS) + psparser_sub_reset(); + + if (port->sid == 0xffff) { /* es sub */ + esparser_sub_reset(); + pbuf->flag |= BUF_FLAG_PARSER; + } + + pbuf->flag |= BUF_FLAG_IN_USE; + + port->flag |= PORT_FLAG_INITED; + + return 0; +} + +static int audio_port_init(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int r; + + if ((port->flag & PORT_FLAG_AFORMAT) == 0) { + pr_err("aformat not set\n"); + return 0; + } + + r = stbuf_init(pbuf, NULL); + if (r < 0) + return r; + r = adec_init(port); + if (r < 0) { + audio_port_release(port, pbuf, 2); + return r; + } + if (port->type & PORT_TYPE_ES) { + r = esparser_init(pbuf, NULL); + if (r < 0) { + audio_port_release(port, pbuf, 3); + return r; + } + } + pbuf->flag |= BUF_FLAG_IN_USE; + return 0; +} + +static void sub_port_release(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + if ((port->sid == 0xffff) && + ((port->type & (PORT_TYPE_MPPS | PORT_TYPE_MPTS)) == 0)) { + /* this is es sub */ + esparser_release(pbuf); + } + stbuf_release(pbuf); + sub_port_inited = 0; +} + +static int sub_port_init(struct stream_port_s *port, struct stream_buf_s *pbuf) +{ + int r; + + if ((port->flag & PORT_FLAG_SID) == 0) { + pr_err("subtitle id not set\n"); + return 0; + } + + r = stbuf_init(pbuf, NULL); + if (r < 0) + return r; + + if ((port->sid == 0xffff) && + ((port->type & (PORT_TYPE_MPPS | PORT_TYPE_MPTS)) == 0)) { + /* es sub */ + r = esparser_init(pbuf, NULL); + if (r < 0) { + sub_port_release(port, pbuf); + return r; + } + } + + sub_port_inited = 1; + return 0; +} + +static int amstream_port_init(struct port_priv_s *priv) +{ + int r; + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA]; + struct stream_port_s *port = priv->port; + struct vdec_s *vdec = priv->vdec; + + mutex_lock(&amstream_mutex); + + stbuf_fetch_init(); + + if (port_get_inited(priv)) { + mutex_unlock(&amstream_mutex); + return 0; + } + + if ((port->type & PORT_TYPE_AUDIO) && + (port->flag & PORT_FLAG_AFORMAT)) { + r = audio_port_init(port, pabuf); + if (r < 0) { + pr_err("audio_port_init failed\n"); + goto error1; + } + } + + if ((port->type & PORT_TYPE_VIDEO) && + (port->flag & PORT_FLAG_VFORMAT)) { + pubuf->buf_size = 0; + pubuf->buf_start = 0; + pubuf->buf_wp = 0; + pubuf->buf_rp = 0; + pvbuf->for_4k = 0; + if (has_hevc_vdec()) { + if (port->vformat == VFORMAT_HEVC || + port->vformat == VFORMAT_VP9) + pvbuf = &bufs[BUF_TYPE_HEVC]; + } + r = video_port_init(priv, pvbuf); + if (r < 0) { + pr_err("video_port_init failed\n"); + goto error2; + } + } + + if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) { + r = sub_port_init(port, psbuf); + if (r < 0) { + pr_err("sub_port_init failed\n"); + goto error3; + } + } + + if (port->type & PORT_TYPE_MPTS) { + if (has_hevc_vdec()) { + r = tsdemux_init( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, + (port->pcr_inited == 1) ? port->pcrid : 0xffff, + (port->vformat == VFORMAT_HEVC) || + (port->vformat == VFORMAT_VP9), + vdec); + } else { + r = tsdemux_init( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, + (port->pcr_inited == 1) ? port->pcrid : 0xffff, + 0, + vdec); + } + + if (r < 0) { + pr_err("tsdemux_init failed\n"); + goto error4; + } + tsync_pcr_start(); + } + if (port->type & PORT_TYPE_MPPS) { + r = psparser_init( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, + priv->vdec); + if (r < 0) { + pr_err("psparser_init failed\n"); + goto error5; + } + } +#ifdef CONFIG_AM_VDEC_REAL + if (port->type & PORT_TYPE_RM) { + rm_set_vasid( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); + } +#endif +#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ + if (!NO_VDEC2_INIT) { + if ((port->type & PORT_TYPE_VIDEO) + && (port->vformat == VFORMAT_H264_4K2K)) + stbuf_vdec2_init(pvbuf); + } +#endif + + if ((port->type & PORT_TYPE_VIDEO) && + (port->flag & PORT_FLAG_VFORMAT)) + /* connect vdec at the end after all HW initialization */ + vdec_connect(vdec); + + tsync_audio_break(0); /* clear audio break */ + set_vsync_pts_inc_mode(0); /* clear video inc */ + + port_set_inited(priv); + + mutex_unlock(&amstream_mutex); + return 0; + /*errors follow here */ +error5: + tsdemux_release(); +error4: + sub_port_release(port, psbuf); +error3: + video_port_release(priv, pvbuf, 0); +error2: + audio_port_release(port, pabuf, 0); +error1: + mutex_unlock(&amstream_mutex); + return r; +} + +static int amstream_port_release(struct port_priv_s *priv) +{ + struct stream_port_s *port = priv->port; + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + + if (has_hevc_vdec()) { + if (port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9) + pvbuf = &bufs[BUF_TYPE_HEVC]; + } + + if (port->type & PORT_TYPE_MPTS) { + tsync_pcr_stop(); + tsdemux_release(); + } + + if (port->type & PORT_TYPE_MPPS) + psparser_release(); + + if (port->type & PORT_TYPE_VIDEO) + video_port_release(priv, pvbuf, 0); + + if (port->type & PORT_TYPE_AUDIO) + audio_port_release(port, pabuf, 0); + + if (port->type & PORT_TYPE_SUB) + sub_port_release(port, psbuf); + + port->pcr_inited = 0; + port->flag = 0; + return 0; +} + +static void amstream_change_avid(struct stream_port_s *port) +{ + if (port->type & PORT_TYPE_MPTS) { + tsdemux_change_avid( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); + } + + if (port->type & PORT_TYPE_MPPS) { + psparser_change_avid( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); + } + +#ifdef CONFIG_AM_VDEC_REAL + if (port->type & PORT_TYPE_RM) { + rm_set_vasid( + (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff); + } +#endif +} + +static void amstream_change_sid(struct stream_port_s *port) +{ + if (port->type & PORT_TYPE_MPTS) { + tsdemux_change_sid( + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff); + } + + if (port->type & PORT_TYPE_MPPS) { + psparser_change_sid( + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff); + } +} + +/**************************************************/ +static ssize_t amstream_vbuf_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + struct stream_buf_s *pbuf = NULL; + int r; + + + if (has_hevc_vdec()) { + pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : + &bufs[BUF_TYPE_VIDEO]; + } else + pbuf = &bufs[BUF_TYPE_VIDEO]; + + if (!(port_get_inited(priv))) { + r = amstream_port_init(priv); + if (r < 0) + return r; + } + + if (port->flag & PORT_FLAG_DRM) + r = drm_write(file, pbuf, buf, count); + else + r = esparser_write(file, pbuf, buf, count); + if (slow_input) { + pr_info("slow_input: es codec write size %x\n", r); + msleep(3000); + } +#ifdef DATA_DEBUG + debug_file_write(buf, r); +#endif + + return r; +} + +static ssize_t amstream_vframe_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; +#ifdef DATA_DEBUG + debug_file_write(buf, count); +#endif + return vdec_write_vframe(priv->vdec, buf, count); +} + +static ssize_t amstream_abuf_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + struct stream_buf_s *pbuf = &bufs[BUF_TYPE_AUDIO]; + int r; + + if (!(port_get_inited(priv))) { + r = amstream_port_init(priv); + if (r < 0) + return r; + } + + if (port->flag & PORT_FLAG_DRM) + r = drm_write(file, pbuf, buf, count); + else + r = esparser_write(file, pbuf, buf, count); + + return r; +} + +static ssize_t amstream_mpts_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + struct stream_buf_s *pvbuf = NULL; + int r = 0; + + if (has_hevc_vdec()) { + pvbuf = (port->vformat == VFORMAT_HEVC || + port->vformat == VFORMAT_VP9) ? + &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; + } else + pvbuf = &bufs[BUF_TYPE_VIDEO]; + + if (!(port_get_inited(priv))) { + r = amstream_port_init(priv); + if (r < 0) + return r; + } +#ifdef DATA_DEBUG + debug_file_write(buf, count); +#endif + if (port->flag & PORT_FLAG_DRM) + r = drm_tswrite(file, pvbuf, pabuf, buf, count); + else + r = tsdemux_write(file, pvbuf, pabuf, buf, count); + if (slow_input) { + pr_info("slow_input: ts codec write size %x\n", r); + msleep(3000); + } + return r; +} + +static ssize_t amstream_mpps_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + int r; + + if (!(port_get_inited(priv))) { + r = amstream_port_init(priv); + if (r < 0) + return r; + } + return psparser_write(file, pvbuf, pabuf, buf, count); +} + +#ifdef CONFIG_AM_VDEC_REAL +static ssize_t amstream_mprm_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + int r; + + if (!(port_get_inited(priv))) { + r = amstream_port_init(priv); + if (r < 0) + return r; + } + return rmparser_write(file, pvbuf, pabuf, buf, count); +} +#endif + +static ssize_t amstream_sub_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + u32 sub_rp, sub_wp, sub_start, data_size, res; + struct stream_buf_s *s_buf = &bufs[BUF_TYPE_SUBTITLE]; + + if (sub_port_inited == 0) + return 0; + + sub_rp = stbuf_sub_rp_get(); + sub_wp = stbuf_sub_wp_get(); + sub_start = stbuf_sub_start_get(); + + if (sub_wp == sub_rp || sub_rp == 0) + return 0; + + if (sub_wp > sub_rp) + data_size = sub_wp - sub_rp; + else + data_size = s_buf->buf_size - sub_rp + sub_wp; + + if (data_size > count) + data_size = count; + + if (sub_wp < sub_rp) { + int first_num = s_buf->buf_size - (sub_rp - sub_start); + + if (data_size <= first_num) { + res = copy_to_user((void *)buf, + (void *)(codec_mm_phys_to_virt(sub_rp)), + data_size); + if (res >= 0) + stbuf_sub_rp_set(sub_rp + data_size - res); + + return data_size - res; + } else { + if (first_num > 0) { + res = copy_to_user((void *)buf, + (void *)(codec_mm_phys_to_virt(sub_rp)), + first_num); + if (res >= 0) { + stbuf_sub_rp_set(sub_rp + first_num - + res); + } + + return first_num - res; + } + + res = copy_to_user((void *)buf, + (void *)(codec_mm_phys_to_virt(sub_start)), + data_size - first_num); + + if (res >= 0) { + stbuf_sub_rp_set(sub_start + data_size - + first_num - res); + } + + return data_size - first_num - res; + } + } else { + res = + copy_to_user((void *)buf, + (void *)(codec_mm_phys_to_virt(sub_rp)), + data_size); + + if (res >= 0) + stbuf_sub_rp_set(sub_rp + data_size - res); + + return data_size - res; + } +} + +static ssize_t amstream_sub_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_buf_s *pbuf = &bufs[BUF_TYPE_SUBTITLE]; + int r; + + if (!(port_get_inited(priv))) { + r = amstream_port_init(priv); + if (r < 0) + return r; + } + r = esparser_write(file, pbuf, buf, count); + if (r < 0) + return r; + + wakeup_sub_poll(); + + return r; +} + +static unsigned int amstream_sub_poll(struct file *file, + poll_table *wait_table) +{ + poll_wait(file, &amstream_sub_wait, wait_table); + + if (atomic_read(&subdata_ready)) { + atomic_dec(&subdata_ready); + return POLLOUT | POLLWRNORM; + } + + return 0; +} + +void set_userdata_poc(struct userdata_poc_info_t poc) +{ + /* + *pr_err("id %d, slicetype %d\n", + * userdata_slicetype_wi, slicetype); + */ + userdata_poc_info[userdata_poc_wi] = poc; + userdata_poc_wi++; + if (userdata_poc_wi == USERDATA_FIFO_NUM) + userdata_poc_wi = 0; +} +EXPORT_SYMBOL(set_userdata_poc); + +void init_userdata_fifo(void) +{ + userdata_poc_ri = 0; + userdata_poc_wi = 0; +} +EXPORT_SYMBOL(init_userdata_fifo); + +int wakeup_userdata_poll(int wp, unsigned long start_phyaddr, int buf_size, + int data_length) +{ + struct stream_buf_s *userdata_buf = &bufs[BUF_TYPE_USERDATA]; + + userdata_buf->buf_start = start_phyaddr; + userdata_buf->buf_wp = wp; + userdata_buf->buf_size = buf_size; + atomic_set(&userdata_ready, 1); + userdata_length += data_length; + wake_up_interruptible(&amstream_userdata_wait); + return userdata_buf->buf_rp; +} +EXPORT_SYMBOL(wakeup_userdata_poll); + +static unsigned int amstream_userdata_poll(struct file *file, + poll_table *wait_table) +{ + poll_wait(file, &amstream_userdata_wait, wait_table); + if (atomic_read(&userdata_ready)) { + atomic_set(&userdata_ready, 0); + return POLLIN | POLLRDNORM; + } + return 0; +} + +static ssize_t amstream_userdata_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + u32 data_size, res, retVal = 0, buf_wp; + struct stream_buf_s *userdata_buf = &bufs[BUF_TYPE_USERDATA]; + + buf_wp = userdata_buf->buf_wp; + if (userdata_buf->buf_start == 0 || userdata_buf->buf_size == 0) + return 0; + if (buf_wp == userdata_buf->buf_rp) + return 0; + if (buf_wp > userdata_buf->buf_rp) + data_size = buf_wp - userdata_buf->buf_rp; + else { + data_size = + userdata_buf->buf_size - userdata_buf->buf_rp + buf_wp; + } + if (data_size > count) + data_size = count; + if (buf_wp < userdata_buf->buf_rp) { + int first_num = userdata_buf->buf_size - userdata_buf->buf_rp; + + if (data_size <= first_num) { + res = copy_to_user((void *)buf, + (void *)((userdata_buf->buf_rp + + userdata_buf->buf_start)), data_size); + userdata_buf->buf_rp += data_size - res; + retVal = data_size - res; + } else { + if (first_num > 0) { + res = copy_to_user((void *)buf, + (void *)((userdata_buf->buf_rp + + userdata_buf->buf_start)), first_num); + userdata_buf->buf_rp += first_num - res; + retVal = first_num - res; + } else { + res = copy_to_user((void *)buf, + (void *)((userdata_buf->buf_start)), + data_size - first_num); + userdata_buf->buf_rp = + data_size - first_num - res; + retVal = data_size - first_num - res; + } + } + } else { + res = copy_to_user((void *)buf, + (void *)((userdata_buf->buf_rp + + userdata_buf->buf_start)), + data_size); + userdata_buf->buf_rp += data_size - res; + retVal = data_size - res; + } + return retVal; +} + +static int amstream_open(struct inode *inode, struct file *file) +{ + s32 i; + struct stream_port_s *s; + struct stream_port_s *port = &ports[iminor(inode)]; + struct port_priv_s *priv; + + if (iminor(inode) >= amstream_port_num) + return -ENODEV; + + mutex_lock(&amstream_mutex); + + if (port->type & PORT_TYPE_VIDEO) { + for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) { + if (((s->type & PORT_TYPE_DECODER_SCHED) == 0) && + (s->type & PORT_TYPE_VIDEO) && + (s->flag & PORT_FLAG_IN_USE)) { + mutex_unlock(&amstream_mutex); + return -EBUSY; + } + } + } + + if ((port->flag & PORT_FLAG_IN_USE) && + ((port->type & PORT_TYPE_FRAME) == 0)) { + mutex_unlock(&amstream_mutex); + return -EBUSY; + } + + /* check other ports conflicts for audio */ + for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) { + if ((s->flag & PORT_FLAG_IN_USE) && + ((port->type) & (s->type) & PORT_TYPE_AUDIO)) { + mutex_unlock(&amstream_mutex); + return -EBUSY; + } + } + + priv = kzalloc(sizeof(struct port_priv_s), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + priv->port = port; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("demux", 1); */ + amports_switch_gate("demux", 1); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + /* TODO: clc gate */ + /* CLK_GATE_ON(HIU_PARSER_TOP); */ + amports_switch_gate("parser_top", 1); + } + + if (port->type & PORT_TYPE_VIDEO) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("vdec", 1); */ + amports_switch_gate("vdec", 1); + amports_switch_gate("clk_vdec_mux", 1); + amports_switch_gate("clk_hcodec_mux", 1); + + if (has_hevc_vdec()) { + amports_switch_gate("clk_hevc_mux", 1); + if (port->type & + (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) + vdec_poweron(VDEC_HEVC); + + if ((port->type & PORT_TYPE_HEVC) == 0) + vdec_poweron(VDEC_1); + } else { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + vdec_poweron(VDEC_1); + } + } + + if (port->type & PORT_TYPE_AUDIO) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("audio", 1); */ + amports_switch_gate("audio", 1); + } + } + + port->vid = 0; + port->aid = 0; + port->sid = 0; + port->pcrid = 0xffff; + file->f_op = port->fops; + file->private_data = priv; + + port->flag = PORT_FLAG_IN_USE; + port->pcr_inited = 0; +#ifdef DATA_DEBUG + debug_filp = filp_open(DEBUG_FILE_NAME, O_WRONLY, 0); + if (IS_ERR(debug_filp)) { + pr_err("amstream: open debug file failed\n"); + debug_filp = NULL; + } +#endif + mutex_unlock(&amstream_mutex); + + if (port->type & PORT_TYPE_VIDEO) { + priv->vdec = vdec_create(port, NULL); + + if (priv->vdec == NULL) { + port->flag = 0; + kfree(priv); + pr_err("amstream: vdec creation failed\n"); + return -ENOMEM; + } + + if (port->type & PORT_TYPE_DUALDEC) { + priv->vdec->slave = vdec_create(port, priv->vdec); + + if (priv->vdec->slave == NULL) { + vdec_release(priv->vdec); + port->flag = 0; + kfree(priv); + pr_err("amstream: sub vdec creation failed\n"); + return -ENOMEM; + } + } + } + return 0; +} + +static int amstream_release(struct inode *inode, struct file *file) +{ + struct port_priv_s *priv = file->private_data; + struct stream_port_s *port = priv->port; + + if (iminor(inode) >= amstream_port_num) + return -ENODEV; + + mutex_lock(&amstream_mutex); + + if (port_get_inited(priv)) + amstream_port_release(priv); + + if (priv->vdec) { + if (priv->vdec->slave) + vdec_release(priv->vdec->slave); + + vdec_release(priv->vdec); + priv->vdec = NULL; + } + + if ((port->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == + PORT_TYPE_AUDIO) { + s32 i; + struct stream_port_s *s; + + for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) { + if ((s->flag & PORT_FLAG_IN_USE) + && (s->type & PORT_TYPE_VIDEO)) + break; + } + if (i == amstream_port_num) + timestamp_firstvpts_set(0); + } + port->flag = 0; + + /* timestamp_pcrscr_set(0); */ + +#ifdef DATA_DEBUG + if (debug_filp) { + filp_close(debug_filp, current->files); + debug_filp = NULL; + debug_file_pos = 0; + } +#endif + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (port->type & PORT_TYPE_VIDEO) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { +#ifndef CONFIG_MULTI_DEC + if (has_hevc_vdec()) + vdec_poweroff(VDEC_HEVC); + + vdec_poweroff(VDEC_1); +#else + if ((port->type & PORT_TYPE_MPTS) && + ((port->flag & PORT_FLAG_VFORMAT) == 0)) { + vdec_poweroff(VDEC_1); + vdec_poweroff(VDEC_HEVC); + } else if ((port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9)) { + vdec_poweroff(VDEC_HEVC); + } else { + vdec_poweroff(VDEC_1); + } +#endif + } + /* TODO: mod gate */ + /* switch_mod_gate_by_name("vdec", 0); */ + amports_switch_gate("vdec", 0); + amports_switch_gate("clk_hcodec_mux", 0); + } + + if (port->type & PORT_TYPE_AUDIO) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("audio", 0); */ + /* amports_switch_gate("audio", 0); */ + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + /* TODO: clc gate */ + /* CLK_GATE_OFF(HIU_PARSER_TOP); */ + amports_switch_gate("parser_top", 0); + } + /* TODO: mod gate */ + /* switch_mod_gate_by_name("demux", 0); */ + amports_switch_gate("demux", 0); + } + + kfree(priv); + + mutex_unlock(&amstream_mutex); + return 0; +} + +static long amstream_ioctl_get_version(struct port_priv_s *priv, + ulong arg) +{ + int version = (AMSTREAM_IOC_VERSION_FIRST & 0xffff) << 16 + | (AMSTREAM_IOC_VERSION_SECOND & 0xffff); + put_user(version, (u32 __user *)arg); + + return 0; +} +static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg) +{ + struct stream_port_s *this = priv->port; + long r = 0; + + struct am_ioctl_parm parm; + + if (copy_from_user + ((void *)&parm, (void *)arg, + sizeof(parm))) + r = -EFAULT; + + switch (parm.cmd) { + case AMSTREAM_GET_SUB_LENGTH: + if ((this->type & PORT_TYPE_SUB) || + (this->type & PORT_TYPE_SUB_RD)) { + u32 sub_wp, sub_rp; + struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + int val; + + sub_wp = stbuf_sub_wp_get(); + sub_rp = stbuf_sub_rp_get(); + + if (sub_wp == sub_rp) + val = 0; + else if (sub_wp > sub_rp) + val = sub_wp - sub_rp; + else + val = psbuf->buf_size - (sub_rp - sub_wp); + parm.data_32 = val; + } else + r = -EINVAL; + break; + case AMSTREAM_GET_UD_LENGTH: + if (this->type & PORT_TYPE_USERDATA) { + parm.data_32 = userdata_length; + userdata_length = 0; + } else + r = -EINVAL; + break; + case AMSTREAM_GET_APTS_LOOKUP: + if (this->type & PORT_TYPE_AUDIO) { + u32 pts = 0, offset; + + offset = parm.data_32; + pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, 300); + parm.data_32 = pts; + } + break; + case AMSTREAM_GET_FIRST_APTS_FLAG: + if (this->type & PORT_TYPE_AUDIO) { + parm.data_32 = first_pts_checkin_complete( + PTS_TYPE_AUDIO); + } + break; + case AMSTREAM_GET_APTS: + parm.data_32 = timestamp_apts_get(); + break; + case AMSTREAM_GET_VPTS: + parm.data_32 = timestamp_vpts_get(); + break; + case AMSTREAM_GET_PCRSCR: + parm.data_32 = timestamp_pcrscr_get(); + break; + case AMSTREAM_GET_LAST_CHECKIN_APTS: + parm.data_32 = get_last_checkin_pts(PTS_TYPE_AUDIO); + break; + case AMSTREAM_GET_LAST_CHECKIN_VPTS: + parm.data_32 = get_last_checkin_pts(PTS_TYPE_VIDEO); + break; + case AMSTREAM_GET_LAST_CHECKOUT_APTS: + parm.data_32 = get_last_checkout_pts(PTS_TYPE_AUDIO); + break; + case AMSTREAM_GET_LAST_CHECKOUT_VPTS: + parm.data_32 = get_last_checkout_pts(PTS_TYPE_VIDEO); + break; + case AMSTREAM_GET_SUB_NUM: + parm.data_32 = psparser_get_sub_found_num(); + break; + case AMSTREAM_GET_VIDEO_DELAY_LIMIT_MS: + parm.data_32 = bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms; + break; + case AMSTREAM_GET_AUDIO_DELAY_LIMIT_MS: + parm.data_32 = bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms; + break; + case AMSTREAM_GET_VIDEO_CUR_DELAY_MS: { + int delay; + + delay = calculation_stream_delayed_ms( + PTS_TYPE_VIDEO, NULL, NULL); + if (delay >= 0) + parm.data_32 = delay; + else + parm.data_32 = 0; + } + break; + + case AMSTREAM_GET_AUDIO_CUR_DELAY_MS: { + int delay; + + delay = calculation_stream_delayed_ms( + PTS_TYPE_AUDIO, NULL, NULL); + if (delay >= 0) + parm.data_32 = delay; + else + parm.data_32 = 0; + } + break; + case AMSTREAM_GET_AUDIO_AVG_BITRATE_BPS: { + int delay; + u32 avgbps; + + delay = calculation_stream_delayed_ms( + PTS_TYPE_AUDIO, NULL, &avgbps); + if (delay >= 0) + parm.data_32 = avgbps; + else + parm.data_32 = 0; + } + break; + case AMSTREAM_GET_VIDEO_AVG_BITRATE_BPS: { + int delay; + u32 avgbps; + + delay = calculation_stream_delayed_ms( + PTS_TYPE_VIDEO, NULL, &avgbps); + if (delay >= 0) + parm.data_32 = avgbps; + else + parm.data_32 = 0; + } + break; + case AMSTREAM_GET_ION_ID: + parm.data_32 = priv->vdec->vf_receiver_inst; + break; + default: + r = -ENOIOCTLCMD; + break; + } + /* pr_info("parm size:%d\n", sizeof(parm)); */ + if (r == 0) { + if (copy_to_user((void *)arg, &parm, sizeof(parm))) + r = -EFAULT; + } + + return r; + +} +static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) +{ + struct stream_port_s *this = priv->port; + struct am_ioctl_parm parm; + long r = 0; + + if (copy_from_user + ((void *)&parm, (void *)arg, + sizeof(parm))) + r = -EFAULT; + + switch (parm.cmd) { + case AMSTREAM_SET_VB_START: + if ((this->type & PORT_TYPE_VIDEO) && + ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { + if (has_hevc_vdec()) + bufs[BUF_TYPE_HEVC].buf_start = parm.data_32; + bufs[BUF_TYPE_VIDEO].buf_start = parm.data_32; + } else + r = -EINVAL; + break; + case AMSTREAM_SET_VB_SIZE: + if ((this->type & PORT_TYPE_VIDEO) && + ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { + if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) { + if (has_hevc_vdec()) { + r = stbuf_change_size( + &bufs[BUF_TYPE_HEVC], + parm.data_32); + } + r = stbuf_change_size( + &bufs[BUF_TYPE_VIDEO], + parm.data_32); + } + } else if (this->type & PORT_TYPE_FRAME) { + /* todo: frame based set max buffer size */ + r = 0; + } else + r = -EINVAL; + break; + case AMSTREAM_SET_AB_START: + if ((this->type & PORT_TYPE_AUDIO) && + ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) + bufs[BUF_TYPE_AUDIO].buf_start = parm.data_32; + else + r = -EINVAL; + break; + case AMSTREAM_SET_AB_SIZE: + if ((this->type & PORT_TYPE_AUDIO) && + ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) { + if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) { + r = stbuf_change_size( + &bufs[BUF_TYPE_AUDIO], parm.data_32); + } + } else + r = -EINVAL; + break; + case AMSTREAM_SET_VFORMAT: + if ((this->type & PORT_TYPE_VIDEO) && + (parm.data_vformat < VFORMAT_MAX)) { + this->vformat = parm.data_vformat; + this->flag |= PORT_FLAG_VFORMAT; + + vdec_set_format(priv->vdec, this->vformat); + } else + r = -EINVAL; + break; + case AMSTREAM_SET_AFORMAT: + if ((this->type & PORT_TYPE_AUDIO) && + (parm.data_aformat < AFORMAT_MAX)) { + memset(&audio_dec_info, 0, + sizeof(struct audio_info)); + /* for new format,reset the audio info. */ + this->aformat = parm.data_aformat; + this->flag |= PORT_FLAG_AFORMAT; + } else + r = -EINVAL; + break; + case AMSTREAM_SET_VID: + if (this->type & PORT_TYPE_VIDEO) { + this->vid = parm.data_32; + this->flag |= PORT_FLAG_VID; + } else + r = -EINVAL; + + break; + case AMSTREAM_SET_AID: + if (this->type & PORT_TYPE_AUDIO) { + this->aid = parm.data_32; + this->flag |= PORT_FLAG_AID; + + if (port_get_inited(priv)) { + tsync_audio_break(1); + amstream_change_avid(this); + } + } else + r = -EINVAL; + break; + case AMSTREAM_SET_SID: + if (this->type & PORT_TYPE_SUB) { + this->sid = parm.data_32; + this->flag |= PORT_FLAG_SID; + + if (port_get_inited(priv)) + amstream_change_sid(this); + } else + r = -EINVAL; + + break; + case AMSTREAM_IOC_PCRID: + this->pcrid = parm.data_32; + this->pcr_inited = 1; + pr_err("set pcrid = 0x%x\n", this->pcrid); + break; + case AMSTREAM_SET_ACHANNEL: + if (this->type & PORT_TYPE_AUDIO) { + this->achanl = parm.data_32; + set_ch_num_info(parm.data_32); + } else + r = -EINVAL; + break; + case AMSTREAM_SET_SAMPLERATE: + if (this->type & PORT_TYPE_AUDIO) { + this->asamprate = parm.data_32; + set_sample_rate_info(parm.data_32); + } else + r = -EINVAL; + break; + case AMSTREAM_SET_DATAWIDTH: + if (this->type & PORT_TYPE_AUDIO) + this->adatawidth = parm.data_32; + else + r = -EINVAL; + break; + case AMSTREAM_SET_TSTAMP: + if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == + ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) + r = -EINVAL; + else if (this->type & PORT_TYPE_FRAME) + r = vdec_set_pts(priv->vdec, parm.data_32); + else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC) + r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], + parm.data_32); + else if (this->type & PORT_TYPE_VIDEO) + r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], + parm.data_32); + else if (this->type & PORT_TYPE_AUDIO) + r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], + parm.data_32); + break; + case AMSTREAM_SET_TSTAMP_US64: + if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == + ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) + r = -EINVAL; + else { + u64 pts = parm.data_64; + + if (this->type & PORT_TYPE_FRAME) { + /* + *todo: check upper layer for decoder handler + * life sequence or multi-tasking management + */ + r = vdec_set_pts64(priv->vdec, pts); + } else if (has_hevc_vdec()) { + if (this->type & PORT_TYPE_HEVC) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_HEVC], pts); + } else if (this->type & PORT_TYPE_VIDEO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_VIDEO], pts); + } else if (this->type & PORT_TYPE_AUDIO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_AUDIO], pts); + } + } else { + if (this->type & PORT_TYPE_VIDEO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_VIDEO], pts); + } else if (this->type & PORT_TYPE_AUDIO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_AUDIO], pts); + } + } + } + break; + case AMSTREAM_PORT_INIT: + r = amstream_port_init(priv); + break; + case AMSTREAM_SET_TRICKMODE: + if ((this->type & PORT_TYPE_VIDEO) == 0) + return -EINVAL; + r = vdec_set_trickmode(priv->vdec, parm.data_32); + if (r == -1) + return -ENODEV; + break; + + case AMSTREAM_AUDIO_RESET: + if (this->type & PORT_TYPE_AUDIO) { + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + + r = audio_port_reset(this, pabuf); + } else + r = -EINVAL; + + break; + case AMSTREAM_SUB_RESET: + if (this->type & PORT_TYPE_SUB) { + struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + + r = sub_port_reset(this, psbuf); + } else + r = -EINVAL; + break; + case AMSTREAM_DEC_RESET: + tsync_set_dec_reset(); + break; + case AMSTREAM_SET_TS_SKIPBYTE: + if (parm.data_32 >= 0) + tsdemux_set_skipbyte(parm.data_32); + else + r = -EINVAL; + break; + case AMSTREAM_SET_SUB_TYPE: + sub_type = parm.data_32; + break; + case AMSTREAM_SET_PCRSCR: + timestamp_pcrscr_set(parm.data_32); + break; + case AMSTREAM_SET_DEMUX: + tsdemux_set_demux(parm.data_32); + break; + case AMSTREAM_SET_VIDEO_DELAY_LIMIT_MS: + if (has_hevc_vdec()) + bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = parm.data_32; + bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = parm.data_32; + break; + case AMSTREAM_SET_AUDIO_DELAY_LIMIT_MS: + bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = parm.data_32; + break; + case AMSTREAM_SET_DRMMODE: + if (parm.data_32 == 1) { + pr_err("set drmmode\n"); + this->flag |= PORT_FLAG_DRM; + } else { + this->flag &= (~PORT_FLAG_DRM); + pr_err("no drmmode\n"); + } + break; + case AMSTREAM_SET_APTS: { + unsigned int pts; + + pts = parm.data_32; + if (tsync_get_mode() == TSYNC_MODE_PCRMASTER) + tsync_pcr_set_apts(pts); + else + tsync_set_apts(pts); + break; + } + case AMSTREAM_SET_FRAME_BASE_PATH: + if ((this->type & PORT_TYPE_DECODER_SCHED) && + (parm.frame_base_video_path < FRAME_BASE_PATH_MAX)) { + vdec_set_video_path(priv->vdec, parm.data_32); + } else + r = -EINVAL; + break; + default: + r = -ENOIOCTLCMD; + break; + } + return r; +} +static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) +{ + struct stream_port_s *this = priv->port; + long r = 0; + struct am_ioctl_parm_ex parm; + + if (copy_from_user + ((void *)&parm, (void *)arg, + sizeof(parm))) + r = -EFAULT; + + switch (parm.cmd) { + case AMSTREAM_GET_EX_VB_STATUS: + if (this->type & PORT_TYPE_VIDEO) { + struct am_ioctl_parm_ex *p = &parm; + struct stream_buf_s *buf = NULL; + + buf = (this->vformat == VFORMAT_HEVC || + this->vformat == VFORMAT_VP9) ? + &bufs[BUF_TYPE_HEVC] : + &bufs[BUF_TYPE_VIDEO]; + + if (p == NULL) { + r = -EINVAL; + break; + } + + if (this->type & PORT_TYPE_FRAME) { + struct vdec_input_status_s status; + + /* + *todo: check upper layer for decoder + * handler lifecycle + */ + if (priv->vdec == NULL) { + r = -EINVAL; + break; + } + + r = vdec_input_get_status(&priv->vdec->input, + &status); + if (r == 0) { + p->status.size = status.size; + p->status.data_len = status.data_len; + p->status.free_len = status.free_len; + p->status.read_pointer = + status.read_pointer; + } + break; + } + + p->status.size = stbuf_canusesize(buf); + p->status.data_len = stbuf_level(buf); + p->status.free_len = stbuf_space(buf); + p->status.read_pointer = stbuf_rp(buf); + } else + r = -EINVAL; + break; + case AMSTREAM_GET_EX_AB_STATUS: + if (this->type & PORT_TYPE_AUDIO) { + struct am_ioctl_parm_ex *p = &parm; + struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; + + if (p == NULL) + r = -EINVAL; + + p->status.size = stbuf_canusesize(buf); + p->status.data_len = stbuf_level(buf); + p->status.free_len = stbuf_space(buf); + p->status.read_pointer = stbuf_rp(buf); + + } else + r = -EINVAL; + break; + case AMSTREAM_GET_EX_VDECSTAT: + if ((this->type & PORT_TYPE_VIDEO) == 0) { + pr_err("no video\n"); + return -EINVAL; + } else { + struct vdec_status vstatus; + struct am_ioctl_parm_ex *p = &parm; + + if (p == NULL) + return -EINVAL; + if (vdec_status(priv->vdec, &vstatus) == -1) + return -ENODEV; + p->vstatus.width = vstatus.width; + p->vstatus.height = vstatus.height; + p->vstatus.fps = vstatus.fps; + p->vstatus.error_count = vstatus.error_count; + p->vstatus.status = vstatus.status; + } + break; + case AMSTREAM_GET_EX_ADECSTAT: + if ((this->type & PORT_TYPE_AUDIO) == 0) { + pr_err("no audio\n"); + return -EINVAL; + } + if (amstream_adec_status == NULL) { + /* + *pr_err("no amstream_adec_status\n"); + *return -ENODEV; + */ + memset(&parm.astatus, 0, sizeof(parm.astatus)); + } + else { + struct adec_status astatus; + struct am_ioctl_parm_ex *p = &parm; + + if (p == NULL) + return -EINVAL; + amstream_adec_status(&astatus); + p->astatus.channels = astatus.channels; + p->astatus.sample_rate = astatus.sample_rate; + p->astatus.resolution = astatus.resolution; + p->astatus.error_count = astatus.error_count; + p->astatus.status = astatus.status; + } + break; + + case AMSTREAM_GET_EX_UD_POC: + if (this->type & PORT_TYPE_USERDATA) { + struct userdata_poc_info_t userdata_poc = + userdata_poc_info[userdata_poc_ri]; + memcpy(&parm.data_userdata_info, + &userdata_poc, + sizeof(struct userdata_poc_info_t)); + + userdata_poc_ri++; + if (USERDATA_FIFO_NUM == userdata_poc_ri) + userdata_poc_ri = 0; + } else + r = -EINVAL; + break; + default: + r = -ENOIOCTLCMD; + break; + } + /* pr_info("parm size:%zx\n", sizeof(parm)); */ + if (r == 0) { + if (copy_to_user((void *)arg, &parm, sizeof(parm))) + r = -EFAULT; + } + return r; + +} +static long amstream_ioctl_set_ex(struct port_priv_s *priv, ulong arg) +{ + long r = 0; + return r; +} +static long amstream_ioctl_get_ptr(struct port_priv_s *priv, ulong arg) +{ + long r = 0; + + struct am_ioctl_parm_ptr parm; + + if (copy_from_user + ((void *)&parm, (void *)arg, + sizeof(parm))) + r = -EFAULT; + + switch (parm.cmd) { + case AMSTREAM_GET_PTR_SUB_INFO: + { + struct subtitle_info msub_info[MAX_SUB_NUM]; + struct subtitle_info *psub_info[MAX_SUB_NUM]; + int i; + + for (i = 0; i < MAX_SUB_NUM; i++) + psub_info[i] = &msub_info[i]; + + r = psparser_get_sub_info(psub_info); + + if (r == 0) { + memcpy(parm.pdata_sub_info, msub_info, + sizeof(struct subtitle_info) + * MAX_SUB_NUM); + } + } + break; + default: + r = -ENOIOCTLCMD; + break; + } + /* pr_info("parm size:%d\n", sizeof(parm)); */ + if (r == 0) { + if (copy_to_user((void *)arg, &parm, sizeof(parm))) + r = -EFAULT; + } + + return r; + +} +static long amstream_ioctl_set_ptr(struct port_priv_s *priv, ulong arg) +{ + struct stream_port_s *this = priv->port; + struct am_ioctl_parm_ptr parm; + long r = 0; + + if (copy_from_user + ((void *)&parm, (void *)arg, + sizeof(parm))) { + pr_err("[%s]%d, arg err\n", __func__, __LINE__); + r = -EFAULT; + } + switch (parm.cmd) { + case AMSTREAM_SET_PTR_AUDIO_INFO: + if ((this->type & PORT_TYPE_VIDEO) + || (this->type & PORT_TYPE_AUDIO)) { + if (parm.pdata_audio_info != NULL) + memcpy((void *)&audio_dec_info, + (void *)parm.pdata_audio_info, + sizeof(audio_dec_info)); + } else + r = -EINVAL; + break; + case AMSTREAM_SET_PTR_CONFIGS: + if (this->type & PORT_TYPE_VIDEO) { + if (!parm.pointer || (parm.len <= 0) || + (parm.len > PAGE_SIZE)) { + r = -EINVAL; + } else { + r = copy_from_user(priv->vdec->config, + parm.pointer, parm.len); + if (r) + r = -EINVAL; + else + priv->vdec->config_len = parm.len; + } + } else + r = -EINVAL; + break; + default: + r = -ENOIOCTLCMD; + break; + } + return r; +} + +static long amstream_do_ioctl_new(struct port_priv_s *priv, + unsigned int cmd, ulong arg) +{ + long r = 0; + struct stream_port_s *this = priv->port; + + switch (cmd) { + case AMSTREAM_IOC_GET_VERSION: + r = amstream_ioctl_get_version(priv, arg); + break; + case AMSTREAM_IOC_GET: + r = amstream_ioctl_get(priv, arg); + break; + case AMSTREAM_IOC_SET: + r = amstream_ioctl_set(priv, arg); + break; + case AMSTREAM_IOC_GET_EX: + r = amstream_ioctl_get_ex(priv, arg); + break; + case AMSTREAM_IOC_SET_EX: + r = amstream_ioctl_set_ex(priv, arg); + break; + case AMSTREAM_IOC_GET_PTR: + r = amstream_ioctl_get_ptr(priv, arg); + break; + case AMSTREAM_IOC_SET_PTR: + r = amstream_ioctl_set_ptr(priv, arg); + break; + case AMSTREAM_IOC_SYSINFO: + if (this->type & PORT_TYPE_VIDEO) + r = vdec_set_decinfo(priv->vdec, (void *)arg); + else + r = -EINVAL; + break; + default: + r = -ENOIOCTLCMD; + break; + } + + return r; +} + +static long amstream_do_ioctl_old(struct port_priv_s *priv, + unsigned int cmd, ulong arg) +{ + struct stream_port_s *this = priv->port; + long r = 0; + + switch (cmd) { + + case AMSTREAM_IOC_VB_START: + if ((this->type & PORT_TYPE_VIDEO) && + ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { + if (has_hevc_vdec()) + bufs[BUF_TYPE_HEVC].buf_start = arg; + bufs[BUF_TYPE_VIDEO].buf_start = arg; + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_VB_SIZE: + if ((this->type & PORT_TYPE_VIDEO) && + ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) { + if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) { + if (has_hevc_vdec()) { + r = stbuf_change_size( + &bufs[BUF_TYPE_HEVC], arg); + } + r = stbuf_change_size( + &bufs[BUF_TYPE_VIDEO], arg); + } + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_AB_START: + if ((this->type & PORT_TYPE_AUDIO) && + ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) + bufs[BUF_TYPE_AUDIO].buf_start = arg; + else + r = -EINVAL; + break; + + case AMSTREAM_IOC_AB_SIZE: + if ((this->type & PORT_TYPE_AUDIO) && + ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) { + if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) { + r = stbuf_change_size( + &bufs[BUF_TYPE_AUDIO], arg); + } + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_VFORMAT: + if ((this->type & PORT_TYPE_VIDEO) && (arg < VFORMAT_MAX)) { + this->vformat = (enum vformat_e)arg; + this->flag |= PORT_FLAG_VFORMAT; + + vdec_set_format(priv->vdec, this->vformat); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_AFORMAT: + if ((this->type & PORT_TYPE_AUDIO) && (arg < AFORMAT_MAX)) { + memset(&audio_dec_info, 0, + sizeof(struct audio_info)); + /* for new format,reset the audio info. */ + this->aformat = (enum aformat_e)arg; + this->flag |= PORT_FLAG_AFORMAT; + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_VID: + if (this->type & PORT_TYPE_VIDEO) { + this->vid = (u32) arg; + this->flag |= PORT_FLAG_VID; + } else + r = -EINVAL; + + break; + + case AMSTREAM_IOC_AID: + if (this->type & PORT_TYPE_AUDIO) { + this->aid = (u32) arg; + this->flag |= PORT_FLAG_AID; + + if (port_get_inited(priv)) { + tsync_audio_break(1); + amstream_change_avid(this); + } + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_SID: + if (this->type & PORT_TYPE_SUB) { + this->sid = (u32) arg; + this->flag |= PORT_FLAG_SID; + + if (port_get_inited(priv)) + amstream_change_sid(this); + } else + r = -EINVAL; + + break; + + case AMSTREAM_IOC_PCRID: + this->pcrid = (u32) arg; + this->pcr_inited = 1; + pr_err("set pcrid = 0x%x\n", this->pcrid); + break; + + case AMSTREAM_IOC_VB_STATUS: + if (this->type & PORT_TYPE_VIDEO) { + struct am_io_param para; + struct am_io_param *p = ¶ + struct stream_buf_s *buf = NULL; + + buf = (this->vformat == VFORMAT_HEVC || + this->vformat == VFORMAT_VP9) ? + &bufs[BUF_TYPE_HEVC] : + &bufs[BUF_TYPE_VIDEO]; + + if (p == NULL) { + r = -EINVAL; + break; + } + + if (this->type & PORT_TYPE_FRAME) { + struct vdec_input_status_s status; + + /* + *todo: check upper layer for decoder + * handler lifecycle + */ + if (priv->vdec == NULL) { + r = -EINVAL; + break; + } + + r = vdec_input_get_status(&priv->vdec->input, + &status); + if (r == 0) { + p->status.size = status.size; + p->status.data_len = status.data_len; + p->status.free_len = status.free_len; + p->status.read_pointer = + status.read_pointer; + if (copy_to_user((void *)arg, p, + sizeof(para))) + r = -EFAULT; + } + break; + } + + p->status.size = stbuf_canusesize(buf); + p->status.data_len = stbuf_level(buf); + p->status.free_len = stbuf_space(buf); + p->status.read_pointer = stbuf_rp(buf); + if (copy_to_user((void *)arg, p, sizeof(para))) + r = -EFAULT; + return r; + } + r = -EINVAL; + break; + + case AMSTREAM_IOC_AB_STATUS: + if (this->type & PORT_TYPE_AUDIO) { + struct am_io_param para; + struct am_io_param *p = ¶ + struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; + + if (p == NULL) + r = -EINVAL; + + p->status.size = stbuf_canusesize(buf); + p->status.data_len = stbuf_level(buf); + p->status.free_len = stbuf_space(buf); + p->status.read_pointer = stbuf_rp(buf); + if (copy_to_user((void *)arg, p, sizeof(para))) + r = -EFAULT; + return r; + } + r = -EINVAL; + break; + + case AMSTREAM_IOC_SYSINFO: + if (this->type & PORT_TYPE_VIDEO) + r = vdec_set_decinfo(priv->vdec, (void *)arg); + else + r = -EINVAL; + break; + + case AMSTREAM_IOC_ACHANNEL: + if (this->type & PORT_TYPE_AUDIO) { + this->achanl = (u32) arg; + set_ch_num_info((u32) arg); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_SAMPLERATE: + if (this->type & PORT_TYPE_AUDIO) { + this->asamprate = (u32) arg; + set_sample_rate_info((u32) arg); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_DATAWIDTH: + if (this->type & PORT_TYPE_AUDIO) + this->adatawidth = (u32) arg; + else + r = -EINVAL; + break; + + case AMSTREAM_IOC_TSTAMP: + if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == + ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) + r = -EINVAL; + else if (this->type & PORT_TYPE_FRAME) + r = vdec_set_pts(priv->vdec, arg); + else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC) + r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], arg); + else if (this->type & PORT_TYPE_VIDEO) + r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], arg); + else if (this->type & PORT_TYPE_AUDIO) + r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], arg); + break; + + case AMSTREAM_IOC_TSTAMP_uS64: + if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) == + ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO))) + r = -EINVAL; + else { + u64 pts; + + if (copy_from_user + ((void *)&pts, (void *)arg, sizeof(u64))) + return -EFAULT; + if (this->type & PORT_TYPE_FRAME) { + /* + *todo: check upper layer for decoder handler + * life sequence or multi-tasking management + */ + if (priv->vdec) + r = vdec_set_pts64(priv->vdec, pts); + } else if (has_hevc_vdec()) { + if (this->type & PORT_TYPE_HEVC) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_HEVC], pts); + } else if (this->type & PORT_TYPE_VIDEO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_VIDEO], pts); + } else if (this->type & PORT_TYPE_AUDIO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_AUDIO], pts); + } + } else { + if (this->type & PORT_TYPE_VIDEO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_VIDEO], pts); + } else if (this->type & PORT_TYPE_AUDIO) { + r = es_vpts_checkin_us64( + &bufs[BUF_TYPE_AUDIO], pts); + } + } + } + break; + + case AMSTREAM_IOC_VDECSTAT: + if ((this->type & PORT_TYPE_VIDEO) == 0) + return -EINVAL; + { + struct vdec_status vstatus; + struct am_io_param para; + struct am_io_param *p = ¶ + + if (p == NULL) + return -EINVAL; + if (vdec_status(priv->vdec, &vstatus) == -1) + return -ENODEV; + p->vstatus.width = vstatus.width; + p->vstatus.height = vstatus.height; + p->vstatus.fps = vstatus.fps; + p->vstatus.error_count = vstatus.error_count; + p->vstatus.status = vstatus.status; + if (copy_to_user((void *)arg, p, sizeof(para))) + r = -EFAULT; + return r; + } + + case AMSTREAM_IOC_ADECSTAT: + if ((this->type & PORT_TYPE_AUDIO) == 0) + return -EINVAL; + if (amstream_adec_status == NULL) + return -ENODEV; + else { + struct adec_status astatus; + struct am_io_param para; + struct am_io_param *p = ¶ + + if (p == NULL) + return -EINVAL; + amstream_adec_status(&astatus); + p->astatus.channels = astatus.channels; + p->astatus.sample_rate = astatus.sample_rate; + p->astatus.resolution = astatus.resolution; + p->astatus.error_count = astatus.error_count; + p->astatus.status = astatus.status; + if (copy_to_user((void *)arg, p, sizeof(para))) + r = -EFAULT; + return r; + } + case AMSTREAM_IOC_PORT_INIT: + r = amstream_port_init(priv); + break; + + case AMSTREAM_IOC_VDEC_RESET: + if ((this->type & PORT_TYPE_VIDEO) == 0) + return -EINVAL; + + if (priv->vdec == NULL) + return -ENODEV; + + r = vdec_reset(priv->vdec); + break; + + case AMSTREAM_IOC_TRICKMODE: + if ((this->type & PORT_TYPE_VIDEO) == 0) + return -EINVAL; + r = vdec_set_trickmode(priv->vdec, arg); + if (r == -1) + return -ENODEV; + break; + + case AMSTREAM_IOC_AUDIO_INFO: + if ((this->type & PORT_TYPE_VIDEO) + || (this->type & PORT_TYPE_AUDIO)) { + if (copy_from_user + (&audio_dec_info, (void __user *)arg, + sizeof(audio_dec_info))) + r = -EFAULT; + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_AUDIO_RESET: + if (this->type & PORT_TYPE_AUDIO) { + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + + r = audio_port_reset(this, pabuf); + } else + r = -EINVAL; + + break; + + case AMSTREAM_IOC_SUB_RESET: + if (this->type & PORT_TYPE_SUB) { + struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + + r = sub_port_reset(this, psbuf); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_SUB_LENGTH: + if ((this->type & PORT_TYPE_SUB) || + (this->type & PORT_TYPE_SUB_RD)) { + u32 sub_wp, sub_rp; + struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + int val; + + sub_wp = stbuf_sub_wp_get(); + sub_rp = stbuf_sub_rp_get(); + + if (sub_wp == sub_rp) + val = 0; + else if (sub_wp > sub_rp) + val = sub_wp - sub_rp; + else + val = psbuf->buf_size - (sub_rp - sub_wp); + put_user(val, (unsigned long __user *)arg); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_UD_LENGTH: + if (this->type & PORT_TYPE_USERDATA) { + /* *((u32 *)arg) = userdata_length; */ + put_user(userdata_length, (unsigned long __user *)arg); + userdata_length = 0; + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_UD_POC: + if (this->type & PORT_TYPE_USERDATA) { + /* *((u32 *)arg) = userdata_length; */ + int res; + struct userdata_poc_info_t userdata_poc = + userdata_poc_info[userdata_poc_ri]; + /* + *put_user(userdata_poc.poc_number, + * (unsigned long __user *)arg); + */ + res = + copy_to_user((unsigned long __user *)arg, + &userdata_poc, + sizeof(struct userdata_poc_info_t)); + if (res < 0) + r = -EFAULT; + userdata_poc_ri++; + if (USERDATA_FIFO_NUM == userdata_poc_ri) + userdata_poc_ri = 0; + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_SET_DEC_RESET: + tsync_set_dec_reset(); + break; + + case AMSTREAM_IOC_TS_SKIPBYTE: + if ((int)arg >= 0) + tsdemux_set_skipbyte(arg); + else + r = -EINVAL; + break; + + case AMSTREAM_IOC_SUB_TYPE: + sub_type = (int)arg; + break; + + case AMSTREAM_IOC_APTS_LOOKUP: + if (this->type & PORT_TYPE_AUDIO) { + u32 pts = 0, offset; + + get_user(offset, (unsigned long __user *)arg); + pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, 300); + put_user(pts, (int __user *)arg); + } + return 0; + case GET_FIRST_APTS_FLAG: + if (this->type & PORT_TYPE_AUDIO) { + put_user(first_pts_checkin_complete(PTS_TYPE_AUDIO), + (int __user *)arg); + } + break; + + case AMSTREAM_IOC_APTS: + put_user(timestamp_apts_get(), (int __user *)arg); + break; + + case AMSTREAM_IOC_VPTS: + put_user(timestamp_vpts_get(), (int __user *)arg); + break; + + case AMSTREAM_IOC_PCRSCR: + put_user(timestamp_pcrscr_get(), (int __user *)arg); + break; + + case AMSTREAM_IOC_SET_PCRSCR: + timestamp_pcrscr_set(arg); + break; + case AMSTREAM_IOC_GET_LAST_CHECKIN_APTS: + put_user(get_last_checkin_pts(PTS_TYPE_AUDIO), (int *)arg); + break; + case AMSTREAM_IOC_GET_LAST_CHECKIN_VPTS: + put_user(get_last_checkin_pts(PTS_TYPE_VIDEO), (int *)arg); + break; + case AMSTREAM_IOC_GET_LAST_CHECKOUT_APTS: + put_user(get_last_checkout_pts(PTS_TYPE_AUDIO), (int *)arg); + break; + case AMSTREAM_IOC_GET_LAST_CHECKOUT_VPTS: + put_user(get_last_checkout_pts(PTS_TYPE_VIDEO), (int *)arg); + break; + case AMSTREAM_IOC_SUB_NUM: + put_user(psparser_get_sub_found_num(), (int *)arg); + break; + + case AMSTREAM_IOC_SUB_INFO: + if (arg > 0) { + struct subtitle_info msub_info[MAX_SUB_NUM]; + struct subtitle_info *psub_info[MAX_SUB_NUM]; + int i; + + for (i = 0; i < MAX_SUB_NUM; i++) + psub_info[i] = &msub_info[i]; + + r = psparser_get_sub_info(psub_info); + + if (r == 0) { + if (copy_to_user((void __user *)arg, msub_info, + sizeof(struct subtitle_info) * MAX_SUB_NUM)) + r = -EFAULT; + } + } + break; + case AMSTREAM_IOC_SET_DEMUX: + tsdemux_set_demux((int)arg); + break; + case AMSTREAM_IOC_SET_VIDEO_DELAY_LIMIT_MS: + if (has_hevc_vdec()) + bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = (int)arg; + bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = (int)arg; + break; + case AMSTREAM_IOC_SET_AUDIO_DELAY_LIMIT_MS: + bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = (int)arg; + break; + case AMSTREAM_IOC_GET_VIDEO_DELAY_LIMIT_MS: + put_user(bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms, (int *)arg); + break; + case AMSTREAM_IOC_GET_AUDIO_DELAY_LIMIT_MS: + put_user(bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms, (int *)arg); + break; + case AMSTREAM_IOC_GET_VIDEO_CUR_DELAY_MS: { + int delay; + + delay = calculation_stream_delayed_ms( + PTS_TYPE_VIDEO, NULL, NULL); + if (delay >= 0) + put_user(delay, (int *)arg); + else + put_user(0, (int *)arg); + } + break; + + case AMSTREAM_IOC_GET_AUDIO_CUR_DELAY_MS: { + int delay; + + delay = calculation_stream_delayed_ms(PTS_TYPE_AUDIO, NULL, + NULL); + if (delay >= 0) + put_user(delay, (int *)arg); + else + put_user(0, (int *)arg); + } + break; + case AMSTREAM_IOC_GET_AUDIO_AVG_BITRATE_BPS: { + int delay; + u32 avgbps; + + delay = calculation_stream_delayed_ms(PTS_TYPE_AUDIO, NULL, + &avgbps); + if (delay >= 0) + put_user(avgbps, (int *)arg); + else + put_user(0, (int *)arg); + break; + } + case AMSTREAM_IOC_GET_VIDEO_AVG_BITRATE_BPS: { + int delay; + u32 avgbps; + + delay = calculation_stream_delayed_ms(PTS_TYPE_VIDEO, NULL, + &avgbps); + if (delay >= 0) + put_user(avgbps, (int *)arg); + else + put_user(0, (int *)arg); + break; + } + case AMSTREAM_IOC_SET_DRMMODE: + if ((u32) arg == 1) { + pr_err("set drmmode\n"); + this->flag |= PORT_FLAG_DRM; + } else { + this->flag &= (~PORT_FLAG_DRM); + pr_err("no drmmode\n"); + } + break; + case AMSTREAM_IOC_SET_APTS: { + unsigned long pts; + + if (get_user(pts, (unsigned long __user *)arg)) { + pr_err + ("Get audio pts from user space fault!\n"); + return -EFAULT; + } + if (tsync_get_mode() == TSYNC_MODE_PCRMASTER) + tsync_pcr_set_apts(pts); + else + tsync_set_apts(pts); + break; + } + default: + r = -ENOIOCTLCMD; + break; + } + + return r; +} + +static long amstream_do_ioctl(struct port_priv_s *priv, + unsigned int cmd, ulong arg) +{ + long r = 0; + + switch (cmd) { + case AMSTREAM_IOC_GET_VERSION: + case AMSTREAM_IOC_GET: + case AMSTREAM_IOC_SET: + case AMSTREAM_IOC_GET_EX: + case AMSTREAM_IOC_SET_EX: + case AMSTREAM_IOC_GET_PTR: + case AMSTREAM_IOC_SET_PTR: + case AMSTREAM_IOC_SYSINFO: + r = amstream_do_ioctl_new(priv, cmd, arg); + break; + default: + r = amstream_do_ioctl_old(priv, cmd, arg); + break; + } + if (r != 0) + pr_err("amstream_do_ioctl error :%lx, %x\n", r, cmd); + + return r; +} +static long amstream_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *this = priv->port; + + if (!this) + return -ENODEV; + + return amstream_do_ioctl(priv, cmd, arg); +} + +#ifdef CONFIG_COMPAT +struct dec_sysinfo32 { + + u32 format; + + u32 width; + + u32 height; + + u32 rate; + + u32 extra; + + u32 status; + + u32 ratio; + + compat_uptr_t param; + + u64 ratio64; +}; + +struct am_ioctl_parm_ptr32 { + union { + compat_uptr_t pdata_audio_info; + compat_uptr_t pdata_sub_info; + compat_uptr_t pointer; + char data[8]; + }; + u32 cmd; + u32 len; +}; + +static long amstream_ioc_setget_ptr(struct port_priv_s *priv, + unsigned int cmd, struct am_ioctl_parm_ptr32 __user *arg) +{ + struct am_ioctl_parm_ptr __user *data; + struct am_ioctl_parm_ptr32 __user *data32 = arg; + int ret; + + data = compat_alloc_user_space(sizeof(*data)); + if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) + return -EFAULT; + + if (put_user(data32->cmd, &data->cmd) || + put_user(compat_ptr(data32->pointer), &data->pointer) || + put_user(data32->len, &data->len)) + return -EFAULT; + + + ret = amstream_do_ioctl(priv, cmd, (unsigned long)data); + if (ret < 0) + return ret; + return 0; + +} + +static long amstream_set_sysinfo(struct port_priv_s *priv, + struct dec_sysinfo32 __user *arg) +{ + struct dec_sysinfo __user *data; + struct dec_sysinfo32 __user *data32 = arg; + int ret; + + data = compat_alloc_user_space(sizeof(*data)); + if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) + return -EFAULT; + if (copy_in_user(data, data32, 7 * sizeof(u32))) + return -EFAULT; + if (put_user(compat_ptr(data32->param), &data->param)) + return -EFAULT; + if (copy_in_user(&data->ratio64, &data32->ratio64, + sizeof(data->ratio64))) + return -EFAULT; + + ret = amstream_do_ioctl(priv, AMSTREAM_IOC_SYSINFO, + (unsigned long)data); + if (ret < 0) + return ret; + + if (copy_in_user(&arg->format, &data->format, 7 * sizeof(u32)) || + copy_in_user(&arg->ratio64, &data->ratio64, + sizeof(arg->ratio64))) + return -EFAULT; + + return 0; +} +static long amstream_compat_ioctl(struct file *file, + unsigned int cmd, ulong arg) +{ + s32 r = 0; + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + + switch (cmd) { + case AMSTREAM_IOC_GET_VERSION: + case AMSTREAM_IOC_GET: + case AMSTREAM_IOC_SET: + case AMSTREAM_IOC_GET_EX: + case AMSTREAM_IOC_SET_EX: + return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg)); + case AMSTREAM_IOC_GET_PTR: + case AMSTREAM_IOC_SET_PTR: + return amstream_ioc_setget_ptr(priv, cmd, compat_ptr(arg)); + case AMSTREAM_IOC_SYSINFO: + return amstream_set_sysinfo(priv, compat_ptr(arg)); + default: + return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg)); + } + + return r; +} +#endif + +static ssize_t ports_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + int i; + char *pbuf = buf; + struct stream_port_s *p = NULL; + + for (i = 0; i < amstream_port_num; i++) { + p = &ports[i]; + /*name */ + pbuf += sprintf(pbuf, "%s\t:\n", p->name); + /*type */ + pbuf += sprintf(pbuf, "\ttype:%d( ", p->type); + if (p->type & PORT_TYPE_VIDEO) + pbuf += sprintf(pbuf, "%s ", "Video"); + if (p->type & PORT_TYPE_AUDIO) + pbuf += sprintf(pbuf, "%s ", "Audio"); + if (p->type & PORT_TYPE_MPTS) + pbuf += sprintf(pbuf, "%s ", "TS"); + if (p->type & PORT_TYPE_MPPS) + pbuf += sprintf(pbuf, "%s ", "PS"); + if (p->type & PORT_TYPE_ES) + pbuf += sprintf(pbuf, "%s ", "ES"); + if (p->type & PORT_TYPE_RM) + pbuf += sprintf(pbuf, "%s ", "RM"); + if (p->type & PORT_TYPE_SUB) + pbuf += sprintf(pbuf, "%s ", "Subtitle"); + if (p->type & PORT_TYPE_SUB_RD) + pbuf += sprintf(pbuf, "%s ", "Subtitle_Read"); + if (p->type & PORT_TYPE_USERDATA) + pbuf += sprintf(pbuf, "%s ", "userdata"); + pbuf += sprintf(pbuf, ")\n"); + /*flag */ + pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag); + if (p->flag & PORT_FLAG_IN_USE) + pbuf += sprintf(pbuf, "%s ", "Used"); + else + pbuf += sprintf(pbuf, "%s ", "Unused"); + if ((p->type & PORT_TYPE_VIDEO) == 0) { + if (p->flag & PORT_FLAG_INITED) + pbuf += sprintf(pbuf, "%s ", "inited"); + else + pbuf += sprintf(pbuf, "%s ", "uninited"); + } + pbuf += sprintf(pbuf, ")\n"); + /*others */ + pbuf += sprintf(pbuf, "\tVformat:%d\n", + (p->flag & PORT_FLAG_VFORMAT) ? p->vformat : -1); + pbuf += sprintf(pbuf, "\tAformat:%d\n", + (p->flag & PORT_FLAG_AFORMAT) ? p->aformat : -1); + pbuf += sprintf(pbuf, "\tVid:%d\n", + (p->flag & PORT_FLAG_VID) ? p->vid : -1); + pbuf += sprintf(pbuf, "\tAid:%d\n", + (p->flag & PORT_FLAG_AID) ? p->aid : -1); + pbuf += sprintf(pbuf, "\tSid:%d\n", + (p->flag & PORT_FLAG_SID) ? p->sid : -1); + pbuf += sprintf(pbuf, "\tPCRid:%d\n", + (p->pcr_inited == 1) ? p->pcrid : -1); + pbuf += sprintf(pbuf, "\tachannel:%d\n", p->achanl); + pbuf += sprintf(pbuf, "\tasamprate:%d\n", p->asamprate); + pbuf += sprintf(pbuf, "\tadatawidth:%d\n\n", p->adatawidth); + } + return pbuf - buf; +} + +static ssize_t bufs_show(struct class *class, struct class_attribute *attr, + char *buf) +{ + int i; + char *pbuf = buf; + struct stream_buf_s *p = NULL; + char buf_type[][12] = { "Video", "Audio", "Subtitle", + "UserData", "HEVC" }; + + for (i = 0; i < amstream_buf_num; i++) { + p = &bufs[i]; + /*type */ + pbuf += sprintf(pbuf, "%s buffer:", buf_type[p->type]); + /*flag */ + pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag); + if (p->flag & BUF_FLAG_ALLOC) + pbuf += sprintf(pbuf, "%s ", "Alloc"); + else + pbuf += sprintf(pbuf, "%s ", "Unalloc"); + if (p->flag & BUF_FLAG_IN_USE) + pbuf += sprintf(pbuf, "%s ", "Used"); + else + pbuf += sprintf(pbuf, "%s ", "Noused"); + if (p->flag & BUF_FLAG_PARSER) + pbuf += sprintf(pbuf, "%s ", "Parser"); + else + pbuf += sprintf(pbuf, "%s ", "noParser"); + if (p->flag & BUF_FLAG_FIRST_TSTAMP) + pbuf += sprintf(pbuf, "%s ", "firststamp"); + else + pbuf += sprintf(pbuf, "%s ", "nofirststamp"); + pbuf += sprintf(pbuf, ")\n"); + /*buf stats */ + + pbuf += sprintf(pbuf, "\tbuf addr:%p\n", (void *)p->buf_start); + + if (p->type != BUF_TYPE_SUBTITLE) { + pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size); + pbuf += sprintf(pbuf, + "\tbuf canusesize:%#x\n", + p->canusebuf_size); + pbuf += sprintf(pbuf, + "\tbuf regbase:%#lx\n", p->reg_base); + + if (p->reg_base && p->flag & BUF_FLAG_IN_USE) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("vdec", 1);*/ + amports_switch_gate("vdec", 1); + } + pbuf += sprintf(pbuf, "\tbuf level:%#x\n", + stbuf_level(p)); + pbuf += sprintf(pbuf, "\tbuf space:%#x\n", + stbuf_space(p)); + pbuf += sprintf(pbuf, + "\tbuf read pointer:%#x\n", + stbuf_rp(p)); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + /* TODO: mod gate */ + /* switch_mod_gate_by_name("vdec", 0);*/ + amports_switch_gate("vdec", 0); + } + } else + pbuf += sprintf(pbuf, "\tbuf no used.\n"); + + if (p->type == BUF_TYPE_USERDATA) { + pbuf += sprintf(pbuf, + "\tbuf write pointer:%#x\n", + p->buf_wp); + pbuf += sprintf(pbuf, + "\tbuf read pointer:%#x\n", + p->buf_rp); + } + } else { + u32 sub_wp, sub_rp, data_size; + + sub_wp = stbuf_sub_wp_get(); + sub_rp = stbuf_sub_rp_get(); + if (sub_wp >= sub_rp) + data_size = sub_wp - sub_rp; + else + data_size = p->buf_size - sub_rp + sub_wp; + pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size); + pbuf += + sprintf(pbuf, "\tbuf canusesize:%#x\n", + p->canusebuf_size); + pbuf += + sprintf(pbuf, "\tbuf start:%#x\n", + stbuf_sub_start_get()); + pbuf += sprintf(pbuf, + "\tbuf write pointer:%#x\n", sub_wp); + pbuf += sprintf(pbuf, + "\tbuf read pointer:%#x\n", sub_rp); + pbuf += sprintf(pbuf, "\tbuf level:%#x\n", data_size); + } + + pbuf += sprintf(pbuf, "\tbuf first_stamp:%#x\n", + p->first_tstamp); + pbuf += sprintf(pbuf, "\tbuf wcnt:%#x\n\n", p->wcnt); + pbuf += sprintf(pbuf, "\tbuf max_buffer_delay_ms:%dms\n", + p->max_buffer_delay_ms); + + if (p->reg_base && p->flag & BUF_FLAG_IN_USE) { + int calc_delayms = 0; + u32 bitrate = 0, avg_bitrate = 0; + + calc_delayms = calculation_stream_delayed_ms( + (p->type == BUF_TYPE_AUDIO) ? PTS_TYPE_AUDIO : + PTS_TYPE_VIDEO, + &bitrate, + &avg_bitrate); + + if (calc_delayms >= 0) { + pbuf += sprintf(pbuf, + "\tbuf current delay:%dms\n", + calc_delayms); + pbuf += sprintf(pbuf, + "\tbuf bitrate latest:%dbps,avg:%dbps\n", + bitrate, avg_bitrate); + pbuf += sprintf(pbuf, + "\tbuf time after last pts:%d ms\n", + calculation_stream_ext_delayed_ms + ((p->type == BUF_TYPE_AUDIO) ? PTS_TYPE_AUDIO : + PTS_TYPE_VIDEO)); + + pbuf += sprintf(pbuf, + "\tbuf time after last write data :%d ms\n", + (int)(jiffies_64 - + p->last_write_jiffies64) * 1000 / HZ); + } + } + if (p->write_thread) { + pbuf += sprintf(pbuf, + "\twrite thread:%d/%d,fifo %d:%d,passed:%d\n", + threadrw_buffer_level(p), + threadrw_buffer_size(p), + threadrw_datafifo_len(p), + threadrw_freefifo_len(p), + threadrw_passed_len(p) + ); + } + } + + return pbuf - buf; +} + +static ssize_t videobufused_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + struct stream_buf_s *p = NULL; + struct stream_buf_s *p_hevc = NULL; + + p = &bufs[0]; + if (has_hevc_vdec()) + p_hevc = &bufs[BUF_TYPE_HEVC]; + + if (p->flag & BUF_FLAG_IN_USE) + pbuf += sprintf(pbuf, "%d ", 1); + else if (has_hevc_vdec() && (p_hevc->flag & BUF_FLAG_IN_USE)) + pbuf += sprintf(pbuf, "%d ", 1); + else + pbuf += sprintf(pbuf, "%d ", 0); + return 1; +} + +static ssize_t vcodec_profile_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return vcodec_profile_read(buf); +} + +static int reset_canuse_buferlevel(int levelx10000) +{ + int i; + struct stream_buf_s *p = NULL; + + if (levelx10000 >= 0 && levelx10000 <= 10000) + use_bufferlevelx10000 = levelx10000; + else + use_bufferlevelx10000 = 10000; + for (i = 0; i < amstream_buf_num; i++) { + p = &bufs[i]; + p->canusebuf_size = ((p->buf_size / 1024) * + use_bufferlevelx10000 / 10000) * 1024; + p->canusebuf_size += 1023; + p->canusebuf_size &= ~1023; + if (p->canusebuf_size > p->buf_size) + p->canusebuf_size = p->buf_size; + } + return 0; +} + +static ssize_t show_canuse_buferlevel(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t size = sprintf(buf, + "use_bufferlevel=%d/10000[=(set range[ 0~10000])=\n", + use_bufferlevelx10000); + return size; +} + +static ssize_t store_canuse_buferlevel(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned val; + ssize_t ret; + + /*ret = sscanf(buf, "%d", &val);*/ + ret = kstrtoint(buf, 0, &val); + + if (ret != 0) + return -EINVAL; + val = val; + reset_canuse_buferlevel(val); + return size; +} + +static ssize_t store_maxdelay(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned val; + ssize_t ret; + int i; + + /*ret = sscanf(buf, "%d", &val);*/ + ret = kstrtoint(buf, 0, &val); + if (ret != 0) + return -EINVAL; + for (i = 0; i < amstream_buf_num; i++) + bufs[i].max_buffer_delay_ms = val; + return size; +} + +static ssize_t show_maxdelay(struct class *class, + struct class_attribute *attr, + char *buf) +{ + ssize_t size = 0; + + size += sprintf(buf, "%dms video max buffered data delay ms\n", + bufs[0].max_buffer_delay_ms); + size += sprintf(buf, "%dms audio max buffered data delay ms\n", + bufs[1].max_buffer_delay_ms); + return size; +} + +static struct class_attribute amstream_class_attrs[] = { + __ATTR_RO(ports), + __ATTR_RO(bufs), + __ATTR_RO(vcodec_profile), + __ATTR_RO(videobufused), + __ATTR(canuse_buferlevel, S_IRUGO | S_IWUSR | S_IWGRP, + show_canuse_buferlevel, store_canuse_buferlevel), + __ATTR(max_buffer_delay_ms, S_IRUGO | S_IWUSR | S_IWGRP, show_maxdelay, + store_maxdelay), + __ATTR_NULL +}; + +static struct class amstream_class = { + .name = "amstream", + .class_attrs = amstream_class_attrs, +}; + +int amstream_request_firmware_from_sys(const char *file_name, + char *buf, int size) +{ + const struct firmware *firmware; + int err = 0; + struct device *micro_dev; + + pr_info("try load %s ...", file_name); + micro_dev = device_create(&amstream_class, + NULL, MKDEV(AMSTREAM_MAJOR, 100), + NULL, "videodec"); + if (micro_dev == NULL) { + pr_err("device_create failed =%d\n", err); + return -1; + } + err = request_firmware(&firmware, file_name, micro_dev); + if (err < 0) { + pr_err("can't load the %s,err=%d\n", file_name, err); + goto error1; + } + if (firmware->size > size) { + pr_err("not enough memory size for audiodsp code\n"); + err = -ENOMEM; + goto release; + } + + memcpy(buf, (char *)firmware->data, firmware->size); + /*mb(); don't need it*/ + pr_err("load mcode size=%zd\n mcode name %s\n", firmware->size, + file_name); + err = firmware->size; +release: + release_firmware(firmware); +error1: + device_destroy(&amstream_class, MKDEV(AMSTREAM_MAJOR, 100)); + return err; +} + +/*static struct resource memobj;*/ +static int amstream_probe(struct platform_device *pdev) +{ + int i; + int r; + struct stream_port_s *st; + + pr_err("Amlogic A/V streaming port init\n"); + + amstream_port_num = MAX_AMSTREAM_PORT_NUM; + amstream_buf_num = BUF_MAX_NUM; +/* +* r = of_reserved_mem_device_init(&pdev->dev); +* if (r == 0) +* pr_info("of probe done"); +* else { +* r = -ENOMEM; +* return r; +* } +*/ + r = class_register(&amstream_class); + if (r) { + pr_err("amstream class create fail.\n"); + return r; + } + + r = astream_dev_register(); + if (r) + return r; + + r = register_chrdev(AMSTREAM_MAJOR, "amstream", &amstream_fops); + if (r < 0) { + pr_err("Can't allocate major for amstreaming device\n"); + + goto error2; + } + + amstream_dev_class = class_create(THIS_MODULE, DEVICE_NAME); + + for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) { + st->class_dev = device_create(amstream_dev_class, NULL, + MKDEV(AMSTREAM_MAJOR, i), NULL, + ports[i].name); + } + + amstream_adec_status = NULL; + if (tsdemux_class_register() != 0) { + r = (-EIO); + goto error3; + } + + init_waitqueue_head(&amstream_sub_wait); + init_waitqueue_head(&amstream_userdata_wait); + reset_canuse_buferlevel(10000); + amstream_pdev = pdev; + amports_clock_gate_init(&amstream_pdev->dev); + + /*prealloc fetch buf to avoid no continue buffer later...*/ + stbuf_fetch_init(); + return 0; + + /* + * error4: + * tsdemux_class_unregister(); + */ +error3: + for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) + device_destroy(amstream_dev_class, MKDEV(AMSTREAM_MAJOR, i)); + class_destroy(amstream_dev_class); +error2: + unregister_chrdev(AMSTREAM_MAJOR, "amstream"); + /* error1: */ + astream_dev_unregister(); + return r; +} + +static int amstream_remove(struct platform_device *pdev) +{ + int i; + struct stream_port_s *st; + + if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) + stbuf_change_size(&bufs[BUF_TYPE_VIDEO], 0); + if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) + stbuf_change_size(&bufs[BUF_TYPE_AUDIO], 0); + stbuf_fetch_release(); + tsdemux_class_unregister(); + for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) + device_destroy(amstream_dev_class, MKDEV(AMSTREAM_MAJOR, i)); + + class_destroy(amstream_dev_class); + + unregister_chrdev(AMSTREAM_MAJOR, "amstream"); + + class_unregister(&amstream_class); + + astream_dev_unregister(); + + amstream_adec_status = NULL; + + pr_err("Amlogic A/V streaming port release\n"); + + return 0; +} + +void set_adec_func(int (*adec_func)(struct adec_status *)) +{ + amstream_adec_status = adec_func; +} + +void wakeup_sub_poll(void) +{ + atomic_inc(&subdata_ready); + wake_up_interruptible(&amstream_sub_wait); +} + +int get_sub_type(void) +{ + return sub_type; +} + +/*get pes buffers */ + +struct stream_buf_s *get_stream_buffer(int id) +{ + if (id >= BUF_MAX_NUM) + return 0; + return &bufs[id]; +} + +static const struct of_device_id amlogic_mesonstream_dt_match[] = { + { + .compatible = "amlogic, codec, streambuf", + }, + {}, +}; + +static struct platform_driver amstream_driver = { + .probe = amstream_probe, + .remove = amstream_remove, + .driver = { + .owner = THIS_MODULE, + .name = "mesonstream", + .of_match_table = amlogic_mesonstream_dt_match, + } +}; + +static int __init amstream_module_init(void) +{ + if (platform_driver_register(&amstream_driver)) { + pr_err("failed to register amstream module\n"); + return -ENODEV; + } + return 0; +} + +static void __exit amstream_module_exit(void) +{ + platform_driver_unregister(&amstream_driver); + return; +} + +module_init(amstream_module_init); +module_exit(amstream_module_exit); + +module_param(debugflags, uint, 0664); +MODULE_PARM_DESC(debugflags, "\n amstream debugflags\n"); + +module_param(def_4k_vstreambuf_sizeM, uint, 0664); +MODULE_PARM_DESC(def_4k_vstreambuf_sizeM, + "\nDefault video Stream buf size for 4K MByptes\n"); + +module_param(def_vstreambuf_sizeM, uint, 0664); +MODULE_PARM_DESC(def_vstreambuf_sizeM, + "\nDefault video Stream buf size for < 1080p MByptes\n"); + +module_param(slow_input, uint, 0664); +MODULE_PARM_DESC(slow_input, "\n amstream slow_input\n"); + + +MODULE_DESCRIPTION("AMLOGIC streaming port driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c b/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c new file mode 100644 index 000000000000..d65ee5c6511e --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c @@ -0,0 +1,54 @@ +/* + * drivers/amlogic/media/stream_input/amports/amstream_profile.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include "amports_priv.h" + +static const struct codec_profile_t *vcodec_profile[SUPPORT_VDEC_NUM] = { 0 }; + +static int vcodec_profile_idx; + +ssize_t vcodec_profile_read(char *buf) +{ + char *pbuf = buf; + int i = 0; + + for (i = 0; i < vcodec_profile_idx; i++) { + pbuf += sprintf(pbuf, "%s:%s;\n", vcodec_profile[i]->name, + vcodec_profile[i]->profile); + } + + return pbuf - buf; +} + +int vcodec_profile_register(const struct codec_profile_t *vdec_profile) +{ + if (vcodec_profile_idx < SUPPORT_VDEC_NUM) { + vcodec_profile[vcodec_profile_idx] = vdec_profile; + vcodec_profile_idx++; + pr_debug("regist %s codec profile\n", vdec_profile->name); + + } + + return 0; +} +EXPORT_SYMBOL(vcodec_profile_register); + diff --git a/drivers/amlogic/media_modules/stream_input/parser/esparser.c b/drivers/amlogic/media_modules/stream_input/parser/esparser.c new file mode 100644 index 000000000000..a9b8e29221e5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/esparser.c @@ -0,0 +1,940 @@ +/* + * drivers/amlogic/media/stream_input/parser/esparser.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* #include */ +#include + +#include "../../frame_provider/decoder/utils/vdec.h" +#include +#include "streambuf_reg.h" +#include "streambuf.h" +#include "esparser.h" +#include "../amports/amports_priv.h" +#include "thread_rw.h" + +#include + + + +#define SAVE_SCR 0 + +#define ES_START_CODE_PATTERN 0x00000100 +#define ES_START_CODE_MASK 0xffffff00 +#define SEARCH_PATTERN_LEN 512 +#define ES_PARSER_POP READ_MPEG_REG(PFIFO_DATA) + +#define PARSER_WRITE (ES_WRITE | ES_PARSER_START) +#define PARSER_VIDEO (ES_TYPE_VIDEO) +#define PARSER_AUDIO (ES_TYPE_AUDIO) +#define PARSER_SUBPIC (ES_TYPE_SUBTITLE) +#define PARSER_PASSTHROUGH (ES_PASSTHROUGH | ES_PARSER_START) +#define PARSER_AUTOSEARCH (ES_SEARCH | ES_PARSER_START) +#define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START) +#define PARSER_BUSY (ES_PARSER_BUSY) + +static unsigned char *search_pattern; +static dma_addr_t search_pattern_map; +static u32 audio_real_wp; +static u32 audio_buf_start; +static u32 audio_buf_end; + +static const char esparser_id[] = "esparser-id"; + +static DECLARE_WAIT_QUEUE_HEAD(wq); + + +static u32 search_done; +static u32 video_data_parsed; +static u32 audio_data_parsed; +static atomic_t esparser_use_count = ATOMIC_INIT(0); +static DEFINE_MUTEX(esparser_mutex); + +static inline u32 get_buf_wp(u32 type) +{ + if (type == BUF_TYPE_AUDIO) + return audio_real_wp; + else + return 0; +} +static inline u32 get_buf_start(u32 type) +{ + if (type == BUF_TYPE_AUDIO) + return audio_buf_start; + else + return 0; +} +static inline u32 get_buf_end(u32 type) +{ + if (type == BUF_TYPE_AUDIO) + return audio_buf_end; + else + return 0; +} +static void set_buf_wp(u32 type, u32 wp) +{ + if (type == BUF_TYPE_AUDIO) { + audio_real_wp = wp; + WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP, wp/* & 0xffffff00*/); + } +} + +static irqreturn_t esparser_isr(int irq, void *dev_id) +{ + u32 int_status = READ_MPEG_REG(PARSER_INT_STATUS); + + WRITE_MPEG_REG(PARSER_INT_STATUS, int_status); + + if (int_status & PARSER_INTSTAT_SC_FOUND) { + WRITE_MPEG_REG(PFIFO_RD_PTR, 0); + WRITE_MPEG_REG(PFIFO_WR_PTR, 0); + search_done = 1; + wake_up_interruptible(&wq); + } + return IRQ_HANDLED; +} + +static inline u32 buf_wp(u32 type) +{ + u32 wp; + + if ((READ_MPEG_REG(PARSER_ES_CONTROL) & ES_VID_MAN_RD_PTR) == 0) { + wp = +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + (type == BUF_TYPE_HEVC) ? READ_VREG(HEVC_STREAM_WR_PTR) : +#endif + (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) : + (type == BUF_TYPE_AUDIO) ? + READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) : + READ_MPEG_REG(PARSER_SUB_START_PTR); + } else { + wp = +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + (type == BUF_TYPE_HEVC) ? READ_MPEG_REG(PARSER_VIDEO_WP) : +#endif + (type == BUF_TYPE_VIDEO) ? READ_MPEG_REG(PARSER_VIDEO_WP) : + (type == BUF_TYPE_AUDIO) ? + READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) : + READ_MPEG_REG(PARSER_SUB_START_PTR); + } + + return wp; +} + +static ssize_t _esparser_write(const char __user *buf, + size_t count, u32 type, int isphybuf) +{ + size_t r = count; + const char __user *p = buf; + + u32 len = 0; + u32 parser_type; + int ret; + u32 wp; + dma_addr_t dma_addr = 0; + + if (type == BUF_TYPE_HEVC) + parser_type = PARSER_VIDEO; + else if (type == BUF_TYPE_VIDEO) + parser_type = PARSER_VIDEO; + else if (type == BUF_TYPE_AUDIO) + parser_type = PARSER_AUDIO; + else + parser_type = PARSER_SUBPIC; + + wp = buf_wp(type); + + if (r > 0) { + if (isphybuf) + len = count; + else { + len = min_t(size_t, r, (size_t) FETCHBUF_SIZE); + + if (copy_from_user(fetchbuf, p, len)) + return -EFAULT; + dma_addr = dma_map_single( + amports_get_dma_device(), fetchbuf, + FETCHBUF_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + (dma_addr_t) dma_addr)) + return -EFAULT; + + } + + /* wmb(); don't need */ + /* reset the Write and read pointer to zero again */ + WRITE_MPEG_REG(PFIFO_RD_PTR, 0); + WRITE_MPEG_REG(PFIFO_WR_PTR, 0); + + WRITE_MPEG_REG_BITS(PARSER_CONTROL, len, ES_PACK_SIZE_BIT, + ES_PACK_SIZE_WID); + WRITE_MPEG_REG_BITS(PARSER_CONTROL, + parser_type | PARSER_WRITE | + PARSER_AUTOSEARCH, ES_CTRL_BIT, + ES_CTRL_WID); + + if (isphybuf) { + u32 buf_32 = (unsigned long)buf & 0xffffffff; + + WRITE_MPEG_REG(PARSER_FETCH_ADDR, buf_32); + } else { + WRITE_MPEG_REG(PARSER_FETCH_ADDR, dma_addr); + dma_unmap_single(amports_get_dma_device(), dma_addr, + FETCHBUF_SIZE, DMA_TO_DEVICE); + } + + search_done = 0; + if (!(isphybuf & TYPE_PATTERN)) { + WRITE_MPEG_REG(PARSER_FETCH_CMD, + (7 << FETCH_ENDIAN) | len); + WRITE_MPEG_REG(PARSER_FETCH_ADDR, search_pattern_map); + WRITE_MPEG_REG(PARSER_FETCH_CMD, + (7 << FETCH_ENDIAN) | SEARCH_PATTERN_LEN); + } else { + WRITE_MPEG_REG(PARSER_FETCH_CMD, + (7 << FETCH_ENDIAN) | (len + 512)); + } + ret = wait_event_interruptible_timeout(wq, search_done != 0, + HZ / 5); + if (ret == 0) { + WRITE_MPEG_REG(PARSER_FETCH_CMD, 0); + + if (wp == buf_wp(type)) + /*no data fetched */ + return -EAGAIN; + + pr_info("W Timeout, but fetch ok,"); + pr_info("type %d len=%d,wpdiff=%d, isphy %x\n", + type, len, wp - buf_wp(type), isphybuf); + + } else if (ret < 0) + return -ERESTARTSYS; + } + + if ((type == BUF_TYPE_VIDEO) + || (has_hevc_vdec() && (type == BUF_TYPE_HEVC))) + video_data_parsed += len; + else if (type == BUF_TYPE_AUDIO) + audio_data_parsed += len; + + return len; +} + +static ssize_t _esparser_write_s(const char __user *buf, + size_t count, u32 type) +{ + size_t r = count; + const char __user *p = buf; + u32 len = 0; + int ret; + u32 wp, buf_start, buf_end; + dma_addr_t buf_wp_map; + + if (type != BUF_TYPE_AUDIO) + WARN_ON(1);/*BUG();*/ + wp = get_buf_wp(type); + buf_end = get_buf_end(type) + 8; + buf_start = get_buf_start(type); + /*pr_info("write wp 0x%x, count %d, start 0x%x, end 0x%x\n",*/ + /* wp, (u32)count, buf_start, buf_end);*/ + if (wp + count > buf_end) { + ret = copy_from_user(codec_mm_phys_to_virt(wp), + p, buf_end - wp); + if (ret > 0) { + len += buf_end - wp - ret; + buf_wp_map = dma_map_single(amports_get_dma_device(), + codec_mm_phys_to_virt(wp), len, DMA_TO_DEVICE); + wp += len; + pr_info("copy from user not finished\n"); + dma_unmap_single(NULL, buf_wp_map, len, DMA_TO_DEVICE); + set_buf_wp(type, wp); + goto end_write; + } else if (ret == 0) { + len += buf_end - wp; + buf_wp_map = dma_map_single(amports_get_dma_device(), + codec_mm_phys_to_virt(wp), len, DMA_TO_DEVICE); + wp = buf_start; + r = count - len; + dma_unmap_single(NULL, buf_wp_map, len, DMA_TO_DEVICE); + set_buf_wp(type, wp); + } else { + pr_info("copy from user failed 1\n"); + pr_info("w wp 0x%x, count %d, start 0x%x end 0x%x\n", + wp, (u32)count, buf_start, buf_end); + return -EAGAIN; + } + } + ret = copy_from_user(codec_mm_phys_to_virt(wp), p + len, r); + if (ret >= 0) { + len += r - ret; + buf_wp_map = dma_map_single(amports_get_dma_device(), + codec_mm_phys_to_virt(wp), r - ret, DMA_TO_DEVICE); + + if (ret > 0) + pr_info("copy from user not finished 2\n"); + wp += r - ret; + dma_unmap_single(NULL, buf_wp_map, r - ret, DMA_TO_DEVICE); + set_buf_wp(type, wp); + } else { + pr_info("copy from user failed 2\n"); + return -EAGAIN; + } + +end_write: + if (type == BUF_TYPE_AUDIO) + audio_data_parsed += len; + + return len; +} + +s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64) +{ + u32 passed; + + if (buf->write_thread) + passed = threadrw_dataoffset(buf); + else + passed = video_data_parsed; + return pts_checkin_offset_us64(PTS_TYPE_VIDEO, passed, us64); + +} + +s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64) +{ + u32 passed; + + if (buf->write_thread) + passed = threadrw_dataoffset(buf); + else + passed = audio_data_parsed; + return pts_checkin_offset_us64(PTS_TYPE_AUDIO, passed, us64); +} + +s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts) +{ +#if 0 + if (buf->first_tstamp == INVALID_PTS) { + buf->flag |= BUF_FLAG_FIRST_TSTAMP; + buf->first_tstamp = pts; + return 0; + } +#endif + u32 passed = video_data_parsed + threadrw_buffer_level(buf); + + return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts); + +} + +s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts) +{ +#if 0 + if (buf->first_tstamp == INVALID_PTS) { + buf->flag |= BUF_FLAG_FIRST_TSTAMP; + buf->first_tstamp = pts; + + return 0; + } +#endif + u32 passed = audio_data_parsed + threadrw_buffer_level(buf); + + return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts); +} + +s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec) +{ + s32 r = 0; + u32 pts_type; + u32 parser_sub_start_ptr; + u32 parser_sub_end_ptr; + u32 parser_sub_rp; + bool first_use = false; + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC)) + pts_type = PTS_TYPE_HEVC; + else + /* #endif */ + if (buf->type == BUF_TYPE_VIDEO) + pts_type = PTS_TYPE_VIDEO; + else if (buf->type == BUF_TYPE_AUDIO) + pts_type = PTS_TYPE_AUDIO; + else if (buf->type == BUF_TYPE_SUBTITLE) + pts_type = PTS_TYPE_MAX; + else + return -EINVAL; + mutex_lock(&esparser_mutex); + parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); + parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); + parser_sub_rp = READ_MPEG_REG(PARSER_SUB_RP); + + buf->flag |= BUF_FLAG_PARSER; + + if (atomic_add_return(1, &esparser_use_count) == 1) { + first_use = true; + + if (fetchbuf == 0) { + pr_info("%s: no fetchbuf\n", __func__); + r = -ENOMEM; + goto Err_1; + } + + if (search_pattern == NULL) { + search_pattern = kcalloc(1, + SEARCH_PATTERN_LEN, + GFP_KERNEL); + + if (search_pattern == NULL) { + pr_err("%s: no search_pattern\n", __func__); + r = -ENOMEM; + goto Err_1; + } + + /* build a fake start code to get parser interrupt */ + search_pattern[0] = 0x00; + search_pattern[1] = 0x00; + search_pattern[2] = 0x01; + search_pattern[3] = 0xff; + + search_pattern_map = dma_map_single( + amports_get_dma_device(), + search_pattern, + SEARCH_PATTERN_LEN, + DMA_TO_DEVICE); + } + + /* reset PARSER with first esparser_init() call */ + WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER); + + /* TS data path */ +#ifndef CONFIG_AM_DVB + WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0); +#else + tsdemux_set_reset_flag(); +#endif + CLEAR_MPEG_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE); + + CLEAR_MPEG_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE)); + + WRITE_MPEG_REG(PARSER_CONFIG, + (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | + (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | + (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); + + WRITE_MPEG_REG(PFIFO_RD_PTR, 0); + WRITE_MPEG_REG(PFIFO_WR_PTR, 0); + + WRITE_MPEG_REG(PARSER_SEARCH_PATTERN, ES_START_CODE_PATTERN); + WRITE_MPEG_REG(PARSER_SEARCH_MASK, ES_START_CODE_MASK); + + WRITE_MPEG_REG(PARSER_CONFIG, + (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | + (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | + PS_CFG_STARTCODE_WID_24 | + PS_CFG_PFIFO_ACCESS_WID_8 | + /* single byte pop */ + (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); + + WRITE_MPEG_REG(PARSER_CONTROL, PARSER_AUTOSEARCH); + + } + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + /* hook stream buffer with PARSER */ + if (has_hevc_vdec() && (pts_type == PTS_TYPE_HEVC)) { + WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, vdec->input.start + + vdec->input.size - 8); + + if (vdec_single(vdec)) { + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, + ES_VID_MAN_RD_PTR); + + /* set vififo_vbuf_rp_sel=>hevc */ + WRITE_VREG(DOS_GEN_CTRL0, 3 << 1); + + /* set use_parser_vbuf_wp */ + SET_VREG_MASK(HEVC_STREAM_CONTROL, + (1 << 3) | (0 << 4)); + /* set stream_fetch_enable */ + SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); + + /* set stream_buffer_hole with 256 bytes */ + SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, + (1 << 29)); + } else { + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + ES_VID_MAN_RD_PTR); + WRITE_MPEG_REG(PARSER_VIDEO_WP, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_RP, vdec->input.start); + } + video_data_parsed = 0; + } else if (pts_type == PTS_TYPE_VIDEO) { + WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, + vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, + vdec->input.start + vdec->input.size - 8); + if (vdec_single(vdec)) { + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, + ES_VID_MAN_RD_PTR); + + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, + MEM_BUFCTRL_INIT); + + if (has_hevc_vdec()) { + /* set vififo_vbuf_rp_sel=>vdec */ + WRITE_VREG(DOS_GEN_CTRL0, 0); + + } + } else { + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + ES_VID_MAN_RD_PTR); + WRITE_MPEG_REG(PARSER_VIDEO_WP, + vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_RP, + vdec->input.start); + } + video_data_parsed = 0; + } else if (pts_type == PTS_TYPE_AUDIO) { + /* set wp as buffer start */ + SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, + MEM_BUFCTRL_MANUAL); + WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_RP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3); + SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, + MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, + MEM_BUFCTRL_INIT); + WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + audio_data_parsed = 0; + audio_buf_start = + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR); + audio_real_wp = audio_buf_start; + audio_buf_end = READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR); + } else if (buf->type == BUF_TYPE_SUBTITLE) { + WRITE_MPEG_REG(PARSER_SUB_START_PTR, + parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, + parser_sub_end_ptr); + WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_rp); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + (7 << ES_SUB_WR_ENDIAN_BIT) | + ES_SUB_MAN_RD_PTR); + } + + if (pts_type < PTS_TYPE_MAX) { + r = pts_start(pts_type); + + if (r < 0) { + pr_info("esparser_init: pts_start failed\n"); + goto Err_1; + } + } +#if 0 + if (buf->flag & BUF_FLAG_FIRST_TSTAMP) { + if (buf->type == BUF_TYPE_VIDEO) + es_vpts_checkin(buf, buf->first_tstamp); + else if (buf->type == BUF_TYPE_AUDIO) + es_apts_checkin(buf, buf->first_tstamp); + + buf->flag &= ~BUF_FLAG_FIRST_TSTAMP; + } +#endif + + if (first_use) { + /*TODO irq */ + r = vdec_request_irq(PARSER_IRQ, esparser_isr, + "parser", (void *)esparser_id); + + if (r) { + pr_info("esparser_init: irq register failed.\n"); + goto Err_2; + } + + WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff); + WRITE_MPEG_REG(PARSER_INT_ENABLE, + PARSER_INTSTAT_SC_FOUND << + PARSER_INT_HOST_EN_BIT); + } + mutex_unlock(&esparser_mutex); + if (!(amports_get_debug_flags() & 1) && + !codec_mm_video_tvp_enabled()) { + int block_size = (buf->type == BUF_TYPE_AUDIO) ? + PAGE_SIZE : PAGE_SIZE << 4; + int buf_num = (buf->type == BUF_TYPE_AUDIO) ? + 20 : (2 * SZ_1M)/(PAGE_SIZE << 4); + if (!(buf->type == BUF_TYPE_SUBTITLE)) + buf->write_thread = threadrw_alloc(buf_num, + block_size, + esparser_write_ex, + (buf->type == BUF_TYPE_AUDIO) ? 1 : 0); + /*manul mode for audio*/ + } + return 0; + +Err_2: + pts_stop(pts_type); + +Err_1: + atomic_dec(&esparser_use_count); + buf->flag &= ~BUF_FLAG_PARSER; + mutex_unlock(&esparser_mutex); + return r; +} + +void esparser_audio_reset_s(struct stream_buf_s *buf) +{ + ulong flags; + DEFINE_SPINLOCK(lock); + + spin_lock_irqsave(&lock, flags); + + SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_MANUAL); + WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_RP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3); + SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + + buf->flag |= BUF_FLAG_PARSER; + + audio_data_parsed = 0; + audio_real_wp = READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR); + spin_unlock_irqrestore(&lock, flags); + +} + +void esparser_audio_reset(struct stream_buf_s *buf) +{ + ulong flags; + DEFINE_SPINLOCK(lock); + + spin_lock_irqsave(&lock, flags); + + WRITE_MPEG_REG(PARSER_AUDIO_WP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_RP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + buf->flag |= BUF_FLAG_PARSER; + + audio_data_parsed = 0; + audio_real_wp = 0; + audio_buf_start = 0; + audio_buf_end = 0; + spin_unlock_irqrestore(&lock, flags); + +} + +void esparser_release(struct stream_buf_s *buf) +{ + u32 pts_type; + + /* check if esparser_init() is ever called */ + if ((buf->flag & BUF_FLAG_PARSER) == 0) + return; + + if (atomic_read(&esparser_use_count) == 0) { + pr_info + ("[%s:%d]###warning, esparser has been released already\n", + __func__, __LINE__); + return; + } + if (buf->write_thread) + threadrw_release(buf); + if (atomic_dec_and_test(&esparser_use_count)) { + WRITE_MPEG_REG(PARSER_INT_ENABLE, 0); + /*TODO irq */ + + vdec_free_irq(PARSER_IRQ, (void *)esparser_id); + + if (search_pattern) { + dma_unmap_single(amports_get_dma_device(), + search_pattern_map, + SEARCH_PATTERN_LEN, DMA_TO_DEVICE); + kfree(search_pattern); + search_pattern = NULL; + } + } + + if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC)) + pts_type = PTS_TYPE_VIDEO; + else if (buf->type == BUF_TYPE_VIDEO) + pts_type = PTS_TYPE_VIDEO; + else if (buf->type == BUF_TYPE_AUDIO) + pts_type = PTS_TYPE_AUDIO; + else if (buf->type == BUF_TYPE_SUBTITLE) { + buf->flag &= ~BUF_FLAG_PARSER; + return; + } else + return; + + buf->flag &= ~BUF_FLAG_PARSER; + pts_stop(pts_type); +} + +ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, + const char __user *buf, size_t count) +{ + s32 r; + u32 len; + u32 realcount, totalcount; + u32 re_count = count; + u32 havewritebytes = 0; + u32 leftcount = 0; + + struct drm_info tmpmm; + struct drm_info *drm = &tmpmm; + u32 res = 0; + int isphybuf = 0; + unsigned long realbuf; + + if (buf == NULL || count == 0) + return -EINVAL; + if (stbuf->write_thread) { + r = threadrw_flush_buffers(stbuf); + if (r < 0) + pr_info("Warning. drm flush threadrw failed[%d]\n", r); + } + res = copy_from_user(drm, buf, sizeof(struct drm_info)); + if (res) { + pr_info("drm kmalloc failed res[%d]\n", res); + return -EFAULT; + } + + if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) { + /* buf only has drminfo not have esdata; */ + realbuf = drm->drm_phy; + realcount = drm->drm_pktsize; + isphybuf = drm->drm_flag; + /* DRM_PRNT("drm_get_rawdata + *onlydrminfo drm->drm_hasesdata[0x%x] + * stbuf->type %d buf[0x%x]\n", + *drm->drm_hasesdata,stbuf->type,buf); + */ + } else if (drm->drm_hasesdata == 1) { /* buf is drminfo+es; */ + realcount = drm->drm_pktsize; + realbuf = (unsigned long)buf + sizeof(struct drm_info); + isphybuf = 0; + /* DRM_PRNT("drm_get_rawdata + * drminfo+es drm->drm_hasesdata[0x%x] + * stbuf->type %d\n",drm->drm_hasesdata,stbuf->type); + */ + } else { /* buf is hwhead; */ + realcount = count; + isphybuf = 0; + realbuf = (unsigned long)buf; + /* DRM_PRNT("drm_get_rawdata + * drm->drm_hasesdata[0x%x] + * len[%d] count[%d] realcout[%d]\n", + * drm->drm_hasesdata,len,count,realcount); + */ + } + + len = realcount; + count = realcount; + totalcount = realcount; + + while (len > 0) { + if (stbuf->type != BUF_TYPE_SUBTITLE + && stbuf_space(stbuf) < count) { + len = min(stbuf_canusesize(stbuf) / 8, len); + if (stbuf_space(stbuf) < len) { + r = stbuf_wait_space(stbuf, len); + /* write part data , not allow return ; */ + if ((r < leftcount) && (leftcount > 0)) + continue; + else if ((r < 0) && (leftcount == 0))/*full; */ + return -EAGAIN; + } + } + len = min_t(u32, len, count); + + mutex_lock(&esparser_mutex); + + if (stbuf->type != BUF_TYPE_AUDIO) + r = _esparser_write((const char __user *)realbuf, len, + stbuf->type, isphybuf); + else + r = _esparser_write_s((const char __user *)realbuf, len, + stbuf->type); + if (r < 0) { + pr_info("drm_write _esparser_write failed [%d]\n", r); + return r; + } + havewritebytes += r; + leftcount = totalcount - havewritebytes; + if (havewritebytes == totalcount) { + + mutex_unlock(&esparser_mutex); + break; /* write ok; */ + } else if ((len > 0) && (havewritebytes < totalcount)) { + DRM_PRNT + ("d writebytes[%d] want[%d] total[%d] real[%d]\n", + havewritebytes, len, totalcount, realcount); + len = len - r; /* write again; */ + realbuf = realbuf + r; + } else { + pr_info + ("e writebytes[%d] want[%d] total[%d] real[%d]\n", + havewritebytes, len, totalcount, realcount); + } + mutex_unlock(&esparser_mutex); + } + + return re_count; +} +/* +*flags: +*1:phy +*2:noblock +*/ +ssize_t esparser_write_ex(struct file *file, + struct stream_buf_s *stbuf, + const char __user *buf, size_t count, + int flags) +{ + + s32 r; + u32 len = count; + + if (buf == NULL || count == 0) + return -EINVAL; + + /*subtitle have no level to check, */ + if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) { + if ((flags & 2) || ((file != NULL) && + (file->f_flags & O_NONBLOCK))) { + len = stbuf_space(stbuf); + + if (len < 256) /* <1k.do eagain, */ + return -EAGAIN; + } else { + len = min(stbuf_canusesize(stbuf) / 8, len); + + if (stbuf_space(stbuf) < len) { + r = stbuf_wait_space(stbuf, len); + if (r < 0) + return r; + } + } + } + + stbuf->last_write_jiffies64 = jiffies_64; + + len = min_t(u32, len, count); + + mutex_lock(&esparser_mutex); + + if (stbuf->type == BUF_TYPE_AUDIO) + r = _esparser_write_s(buf, len, stbuf->type); + else + r = _esparser_write(buf, len, stbuf->type, flags & 1); + + mutex_unlock(&esparser_mutex); + + return r; +} +ssize_t esparser_write(struct file *file, + struct stream_buf_s *stbuf, + const char __user *buf, size_t count) +{ + if (stbuf->write_thread) { + ssize_t ret; + ret = threadrw_write(file, stbuf, buf, count); + if (ret == -EAGAIN) { + u32 a, b; + int vdelay, adelay; + if ((stbuf->type != BUF_TYPE_VIDEO) && + (stbuf->type != BUF_TYPE_HEVC)) + return ret; + if (stbuf->buf_size > (SZ_1M * 30) || + (threadrw_buffer_size(stbuf) > SZ_1M * 10) || + !threadrw_support_more_buffers(stbuf)) + return ret; + /*only chang buffer for video.*/ + vdelay = calculation_stream_delayed_ms( + PTS_TYPE_VIDEO, &a, &b); + adelay = calculation_stream_delayed_ms( + PTS_TYPE_AUDIO, &a, &b); + if ((vdelay > 100 && vdelay < 2000) && /*vdelay valid.*/ + ((vdelay < 500) ||/*video delay is short!*/ + (adelay > 0 && adelay < 1000))/*audio is low.*/ + ) { + /*on buffer fulled. + if delay is less than 100ms we think errors, + And we add more buffer on delay < 2s. + */ + int new_size = 2 * 1024 * 1024; + threadrw_alloc_more_buffer_size( + stbuf, new_size); + } + } + return ret; + } + return esparser_write_ex(file, stbuf, buf, count, 0); +} + + +void esparser_sub_reset(void) +{ + ulong flags; + DEFINE_SPINLOCK(lock); + u32 parser_sub_start_ptr; + u32 parser_sub_end_ptr; + + spin_lock_irqsave(&lock, flags); + + parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); + parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); + + WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); + WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_WP, parser_sub_start_ptr); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); + + spin_unlock_irqrestore(&lock, flags); +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/esparser.h b/drivers/amlogic/media_modules/stream_input/parser/esparser.h new file mode 100644 index 000000000000..62396a222e86 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/esparser.h @@ -0,0 +1,149 @@ +/* + * drivers/amlogic/media/stream_input/parser/esparser.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef ESPARSER_H +#define ESPARSER_H + +#include "../../frame_provider/decoder/utils/vdec.h" + +extern ssize_t drm_write(struct file *file, + struct stream_buf_s *stbuf, const char __user *buf, size_t count); + +extern s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec); +extern s32 esparser_init_s(struct stream_buf_s *buf); +extern void esparser_release(struct stream_buf_s *buf); +extern ssize_t esparser_write(struct file *file, + struct stream_buf_s *stbuf, const char __user *buf, size_t count); +extern ssize_t esparser_write_ex(struct file *file, + struct stream_buf_s *stbuf, + const char __user *buf, size_t count, int is_phy); + +extern s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64); + +extern s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64); + +extern int es_vpts_checkin(struct stream_buf_s *buf, u32 pts); + +extern int es_apts_checkin(struct stream_buf_s *buf, u32 pts); + +extern void esparser_audio_reset(struct stream_buf_s *buf); +extern void esparser_audio_reset_s(struct stream_buf_s *buf); + +extern void esparser_sub_reset(void); + +#ifdef CONFIG_AM_DVB +extern int tsdemux_set_reset_flag(void); +#endif + +/* TODO: move to register headers */ +#define ES_PACK_SIZE_BIT 8 +#define ES_PACK_SIZE_WID 24 + +#define ES_CTRL_WID 8 +#define ES_CTRL_BIT 0 +#define ES_TYPE_MASK (3 << 6) +#define ES_TYPE_VIDEO (0 << 6) +#define ES_TYPE_AUDIO (1 << 6) +#define ES_TYPE_SUBTITLE (2 << 6) + +#define ES_WRITE (1<<5) +#define ES_PASSTHROUGH (1<<4) +#define ES_INSERT_BEFORE_ES_WRITE (1<<3) +#define ES_DISCARD (1<<2) +#define ES_SEARCH (1<<1) +#define ES_PARSER_START (1<<0) +#define ES_PARSER_BUSY (1<<0) + +#define PARSER_INTSTAT_FETCH_CMD (1<<7) +#define PARSER_INTSTAT_PARSE (1<<4) +#define PARSER_INTSTAT_DISCARD (1<<3) +#define PARSER_INTSTAT_INSZERO (1<<2) +#define PARSER_INTSTAT_ACT_NOSSC (1<<1) +#define PARSER_INTSTAT_SC_FOUND (1<<0) + +#define FETCH_CIR_BUF (1<<31) +#define FETCH_CHK_BUF_STOP (1<<30) +#define FETCH_PASSTHROUGH (1<<29) +#define FETCH_ENDIAN 27 +#define FETCH_PASSTHROUGH_TYPE_MASK (0x3<<27) +#define FETCH_ENDIAN_MASK (0x7<<27) +#define FETCH_BUF_SIZE_MASK (0x7ffffff) +#define FETCH_CMD_PTR_MASK 3 +#define FETCH_CMD_RD_PTR_BIT 5 +#define FETCH_CMD_WR_PTR_BIT 3 +#define FETCH_CMD_NUM_MASK 3 +#define FETCH_CMD_NUM_BIT 0 + +#define ES_COUNT_MASK 0xfff +#define ES_COUNT_BIT 20 +#define ES_REQ_PENDING (1<<19) +#define ES_PASSTHROUGH_EN (1<<18) +#define ES_PASSTHROUGH_TYPE_MASK (3<<16) +#define ES_PASSTHROUGH_TYPE_VIDEO (0<<16) +#define ES_PASSTHROUGH_TYPE_AUDIO (1<<16) +#define ES_PASSTHROUGH_TYPE_SUBTITLE (2<<16) +#define ES_WR_ENDIAN_MASK (0x7) +#define ES_SUB_WR_ENDIAN_BIT 9 +#define ES_SUB_MAN_RD_PTR (1<<8) +#define ES_AUD_WR_ENDIAN_BIT 5 +#define ES_AUD_MAN_RD_PTR (1<<4) +#define ES_VID_WR_ENDIAN_BIT 1 +#define ES_VID_MAN_RD_PTR (1<<0) + +#define PS_CFG_FETCH_DMA_URGENT (1<<31) +#define PS_CFG_STREAM_DMA_URGENT (1<<30) +#define PS_CFG_FORCE_PFIFO_REN (1<<29) +#define PS_CFG_PFIFO_PEAK_EN (1<<28) +#define PS_CFG_SRC_SEL_BIT 24 +#define PS_CFG_SRC_SEL_MASK (3< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +/* #include */ +#include +#include "streambuf_reg.h" +#include "streambuf.h" +#include "psparser.h" +#include "../amports/amports_priv.h" + + +#define TIMESTAMP_IONLY 1 +#define SAVE_SCR 0 + +#define MPEG_START_CODE_PATTERN (0x00000100L) +#define MPEG_START_CODE_MASK (0xffffff00L) +#define MAX_MPG_AUDIOPK_SIZE 0x1000 + +#define SUB_INSERT_START_CODE_HIGH 0x414d4c55 +#define SUB_INSERT_START_CODE_LOW 0xaa000000 + +#define PARSER_WRITE (ES_WRITE | ES_PARSER_START) +#define PARSER_VIDEO (ES_TYPE_VIDEO) +#define PARSER_AUDIO (ES_TYPE_AUDIO) +#define PARSER_SUBPIC (ES_TYPE_SUBTITLE) +#define PARSER_PASSTHROUGH (ES_PASSTHROUGH | ES_PARSER_START) +#define PARSER_AUTOSEARCH (ES_SEARCH | ES_PARSER_START) +#define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START) +#define PARSER_BUSY (ES_PARSER_BUSY) + +#define PARSER_PARAMETER_LENGTH_BIT 16 +#define PARSER_PARAMETER_LOOP_BIT 24 + +#define PARSER_POP READ_MPEG_REG(PFIFO_DATA) +#define SET_BLOCK(size) \ +WRITE_MPEG_REG_BITS(PARSER_CONTROL, size, ES_PACK_SIZE_BIT, ES_PACK_SIZE_WID) +#define SET_DISCARD_SIZE(size) WRITE_MPEG_REG(PARSER_PARAMETER, size) + +#define VIDEO_AUTO_FLUSH +#ifdef VIDEO_AUTO_FLUSH +static u32 video_auto_flush_state; +#define VIDEO_AUTO_FLUSH_IDLE 0 +#define VIDEO_AUTO_FLUSH_MONITOR 1 +#define VIDEO_AUTO_FLUSH_TRIGGER 2 +#define VIDEO_AUTO_FLUSH_DONE 3 +#define VIDEO_AUTO_FLUSH_PTS_THRESHOLD 90000 +#define VIDEO_AUTO_FLUSH_BYTE_COUNT 1024 + +static s32 audio_last_pts; +static s32 audio_monitor_pts; +#endif + +enum { + SEARCH_START_CODE = 0, + SEND_VIDEO_SEARCH, + SEND_AUDIO_SEARCH, + SEND_SUBPIC_SEARCH, + DISCARD_SEARCH, + DISCARD_ONLY +#ifdef VIDEO_AUTO_FLUSH + , + SEARCH_START_CODE_VIDEO_FLUSH +#endif +}; + +enum { + AUDIO_FIRST_ACCESS_ARM = 0, + AUDIO_FIRST_ACCESS_POPING, + AUDIO_FIRST_ACCESS_DONE +}; + +static const char psparser_id[] = "psparser-id"; + +static DECLARE_WAIT_QUEUE_HEAD(wq); + +static struct tasklet_struct psparser_tasklet; +static u32 fetch_done; +static u8 audio_id, video_id, sub_id, sub_id_max; +static u32 audio_first_access; +static u32 packet_remaining; +static u32 video_data_parsed; +static u32 audio_data_parsed; +static u32 pts_equ_dts_flag; + +static unsigned first_apts, first_vpts; +static unsigned audio_got_first_pts, video_got_first_dts, sub_got_first_pts; +atomic_t sub_block_found = ATOMIC_INIT(0); + +#define DEBUG_VOB_SUB +#ifdef DEBUG_VOB_SUB +static u8 sub_found_num; +static struct subtitle_info *sub_info[MAX_SUB_NUM]; +#endif + +static bool ptsmgr_first_vpts_ready(void) +{ + return (video_got_first_dts != 0) ? true : false; +} + +static bool ptsmgr_first_apts_ready(void) +{ + return (audio_got_first_pts != 0) ? true : false; +} + +static void ptsmgr_vpts_checkin(u32 pts) +{ + if (video_got_first_dts == 0) { + video_got_first_dts = 1; + first_vpts = pts; + } + + pts_checkin_offset(PTS_TYPE_VIDEO, video_data_parsed, pts); +} + +static void ptsmgr_apts_checkin(u32 pts) +{ + if (audio_got_first_pts == 0) { + audio_got_first_pts = 1; + first_apts = pts; + } + /* apts_checkin(pts); */ + pts_checkin_offset(PTS_TYPE_AUDIO, audio_data_parsed, pts); + +#ifdef VIDEO_AUTO_FLUSH + audio_last_pts = pts; + + if ((video_auto_flush_state == VIDEO_AUTO_FLUSH_IDLE) + && ptsmgr_first_vpts_ready()) { + video_auto_flush_state = VIDEO_AUTO_FLUSH_MONITOR; + audio_monitor_pts = pts; + } + + if (video_auto_flush_state == VIDEO_AUTO_FLUSH_MONITOR) { + if ((audio_last_pts - audio_monitor_pts) > + VIDEO_AUTO_FLUSH_PTS_THRESHOLD) + video_auto_flush_state = VIDEO_AUTO_FLUSH_TRIGGER; + } +#endif +} + +static u32 parser_process(s32 type, s32 packet_len) +{ + s16 temp, header_len, misc_flags, i; + u32 pts = 0, dts = 0; + u32 pts_dts_flag = 0; + u16 invalid_pts = 0; + + temp = PARSER_POP; + packet_len--; + + if ((temp >> 6) == 0x02) { + /* mpeg-2 system */ + misc_flags = PARSER_POP; + header_len = PARSER_POP; + packet_len -= 2; + packet_len -= header_len; + + if ((misc_flags >> 6) > 1) { + /* PTS exist */ + pts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */ + pts |= PARSER_POP << 22; /* bit 29-22 */ + pts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ + pts |= (PARSER_POP << 7); /* bit 14-07 */ + pts |= (PARSER_POP >> 1); /* bit 06-00 */ + header_len -= 5; + pts_dts_flag |= 2; + } + + if ((misc_flags >> 6) > 2) { + /* DTS exist */ + dts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */ + dts |= PARSER_POP << 22; /* bit 29-22 */ + dts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ + dts |= (PARSER_POP << 7); /* bit 14-07 */ + dts |= (PARSER_POP >> 1); /* bit 06-00 */ + header_len -= 5; + pts_dts_flag |= 1; + } + + if (misc_flags & 0x20) { + /* ESCR_flag */ + PARSER_POP; + PARSER_POP; + PARSER_POP; + PARSER_POP; + PARSER_POP; + PARSER_POP; + header_len -= 5; + } + + if (misc_flags & 0x10) { + /* ES_rate_flag */ + PARSER_POP; + PARSER_POP; + PARSER_POP; + header_len -= 3; + } + + if (misc_flags & 0x08) { + /* DSM_trick_mode_flag */ + PARSER_POP; + header_len -= 1; + } + + if (misc_flags & 0x04) { + /* additional_copy_info_flag */ + PARSER_POP; + header_len -= 1; + } + + if (misc_flags & 0x02) { + /* PES_CRC_flag */ + PARSER_POP; + PARSER_POP; + header_len -= 2; + } + + if (misc_flags & 0x01) { + /* PES_extension_flag */ + misc_flags = PARSER_POP; + header_len--; + + if ((misc_flags & 0x80) && (header_len >= 128)) { + /* PES_private_data_flag */ + for (i = 0; i < 128; i++) + PARSER_POP; + + header_len -= 128; + } +#if 0 + if (misc_flags & 0x40) { + /* pack_header_field_flag */ + /* Invalid case */ + } +#endif + if (misc_flags & 0x20) { + /* program_packet_sequence_counter_flag */ + PARSER_POP; + PARSER_POP; + header_len -= 2; + } + + if (misc_flags & 0x10) { + /* PSTD_buffer_flag */ + PARSER_POP; + PARSER_POP; + header_len -= 2; + } + + if (misc_flags & 1) { + /* PES_extension_flag_2 */ + temp = PARSER_POP & 0x7f; + + while (temp) { + PARSER_POP; + temp--; + header_len--; + } + } + + while (header_len) { + PARSER_POP; + header_len--; + } + } + + while (header_len) { + PARSER_POP; + header_len--; + } + + } else { + /* mpeg-1 system */ + while (temp == 0xff) { + temp = PARSER_POP; + packet_len--; + } + + if ((temp >> 6) == 1) { + PARSER_POP; /* STD buffer size */ + temp = PARSER_POP; + packet_len -= 2; + } + + if (((temp >> 4) == 2) || ((temp >> 4) == 3)) { + pts = ((temp >> 1) & 7) << 30; /* bit 32-30 */ + pts |= PARSER_POP << 22; /* bit 29-22 */ + pts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ + pts |= (PARSER_POP << 7); /* bit 14-07 */ + pts |= (PARSER_POP >> 1); /* bit 06-00 */ + packet_len -= 4; + pts_dts_flag |= 2; + } + + if ((temp >> 4) == 3) { + dts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */ + dts |= PARSER_POP << 22; /* bit 29-22 */ + dts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ + dts |= (PARSER_POP << 7); /* bit 14-07 */ + dts |= (PARSER_POP >> 1); /* bit 06-00 */ + packet_len -= 5; + pts_dts_flag |= 1; + } + } + + if ((pts == 0) && (dts == 0xffffffff)) { + invalid_pts = 1; + pr_info("invalid pts\n"); + } + + if (!packet_len) + return SEARCH_START_CODE; + + else if (type == 0) { +#ifdef VIDEO_AUTO_FLUSH + if (video_auto_flush_state == VIDEO_AUTO_FLUSH_MONITOR) + audio_monitor_pts = audio_last_pts; +#endif + + if ((pts_dts_flag) && (!invalid_pts)) { +#if TIMESTAMP_IONLY + if (!ptsmgr_first_vpts_ready()) { + if (pts_dts_flag & 2) + ptsmgr_vpts_checkin(pts); + else + ptsmgr_vpts_checkin(dts); + } else if ((pts_dts_flag & 3) == 3) { + if (pts_equ_dts_flag) { + if (dts == pts) + ptsmgr_vpts_checkin(pts); + } else { + if (dts == pts) + pts_equ_dts_flag = 1; + ptsmgr_vpts_checkin(pts); + } + } +#else + if (!ptsmgr_first_vpts_ready()) { + if (pts_dts_flag & 2) + ptsmgr_vpts_checkin(pts); + else + ptsmgr_vpts_checkin(dts); + } else if (pts_dts_flag & 2) + ptsmgr_vpts_checkin(pts); +#endif + } + + if (ptsmgr_first_vpts_ready() || invalid_pts) { + SET_BLOCK(packet_len); + video_data_parsed += packet_len; + return SEND_VIDEO_SEARCH; + + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + + } else if (type == 1) { + /* mpeg audio */ + if (pts_dts_flag & 2) + ptsmgr_apts_checkin(pts); + + if (ptsmgr_first_apts_ready()) { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + + } else if (type == 2) { + /* Private stream */ + temp = PARSER_POP; /* sub_stream_id */ + packet_len--; + + if (((temp & 0xf8) == 0xa0) && (temp == audio_id)) { + /* DVD_VIDEO Audio LPCM data */ + PARSER_POP; + temp = (PARSER_POP << 8) | PARSER_POP; + if (temp == 0) + temp = 4; + temp--; + packet_len -= 3; + + if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) { + if (temp) { + packet_remaining = packet_len - temp; + SET_DISCARD_SIZE(temp); + audio_first_access = + AUDIO_FIRST_ACCESS_POPING; + return DISCARD_ONLY; + } + + audio_first_access = AUDIO_FIRST_ACCESS_DONE; + + if (packet_len) { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + + } else + return SEARCH_START_CODE; + + } else { + PARSER_POP; + PARSER_POP; + PARSER_POP; + packet_len -= 3; + } + + if (pts_dts_flag & 2) + ptsmgr_apts_checkin(pts); + + if (ptsmgr_first_apts_ready()) { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + + } else if (((temp & 0xf8) == 0x80) && (temp == audio_id)) { + /* Audio AC3 data */ + PARSER_POP; + temp = (PARSER_POP << 8) | PARSER_POP; + packet_len -= 3; + + if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) { + if (pts_dts_flag & 2) + ptsmgr_apts_checkin(pts); + + if ((temp > 2) && (packet_len > (temp - 2))) { + temp -= 2; + packet_remaining = packet_len - temp; + SET_DISCARD_SIZE(temp); + audio_first_access = + AUDIO_FIRST_ACCESS_POPING; + return DISCARD_ONLY; + } + + audio_first_access = AUDIO_FIRST_ACCESS_DONE; + + if (packet_len) { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + + } else + return SEARCH_START_CODE; + } + + if (pts_dts_flag & 2) + ptsmgr_apts_checkin(pts); + + if (ptsmgr_first_apts_ready()) { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + + } else if (((temp & 0xf8) == 0x88) && (temp == audio_id)) { + /* Audio DTS data */ + PARSER_POP; + PARSER_POP; + PARSER_POP; + packet_len -= 3; + + if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) + audio_first_access = AUDIO_FIRST_ACCESS_DONE; + + if (pts_dts_flag & 2) + ptsmgr_apts_checkin(pts); + + if (ptsmgr_first_apts_ready()) { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + } else if ((temp & 0xe0) == 0x20) { + if (temp > sub_id_max) + sub_id_max = temp; +#ifdef DEBUG_VOB_SUB + for (i = 0; i < sub_found_num; i++) { + if (!sub_info[i]) + break; + if (temp == sub_info[i]->id) + break; + } + if (i == sub_found_num && i < MAX_SUB_NUM) { + if (sub_info[sub_found_num]) { + sub_info[sub_found_num]->id = temp; + sub_found_num++; + pr_info + ("[%s]found new sub_id=0x%x (num %d)\n", + __func__, temp, sub_found_num); + } else { + pr_info + ("[%s]sub info NULL!\n", __func__); + } + } +#endif + + if (temp == sub_id) { + /* DVD sub-picture data */ + if (!packet_len) + return SEARCH_START_CODE; + + else { +#if 0 + if (pts_dts_flag & 2) + ptsmgr_spts_checkin(pts); + + if (ptsmgr_first_spts_ready()) { + SET_BLOCK(packet_len); + return SEND_SUBPIC_SEARCH; + + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } +#else + if (pts_dts_flag & 2) + sub_got_first_pts = 1; + + if (sub_got_first_pts) { + pr_info + ("sub pts 0x%x, len %d\n", + pts, packet_len); + SET_BLOCK(packet_len); + WRITE_MPEG_REG + (PARSER_PARAMETER, + 16 << + PARSER_PARAMETER_LENGTH_BIT); + WRITE_MPEG_REG + (PARSER_INSERT_DATA, + SUB_INSERT_START_CODE_HIGH); + WRITE_MPEG_REG + (PARSER_INSERT_DATA, + SUB_INSERT_START_CODE_LOW | + get_sub_type()); + WRITE_MPEG_REG + (PARSER_INSERT_DATA, + packet_len); + WRITE_MPEG_REG + (PARSER_INSERT_DATA, pts); + atomic_set(&sub_block_found, 1); + return SEND_SUBPIC_SEARCH; + } + + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; +#endif + } + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + } else { + SET_DISCARD_SIZE(packet_len); + return DISCARD_SEARCH; + } + + if (!packet_len) + return SEARCH_START_CODE; + + else { + SET_BLOCK(packet_len); + audio_data_parsed += packet_len; + return SEND_AUDIO_SEARCH; + } + } + + return SEARCH_START_CODE; +} + +static void on_start_code_found(int start_code) +{ + unsigned short packet_len; + unsigned short temp; + unsigned next_action; +#if SAVE_SCR + unsigned scr; +#endif + + if (atomic_read(&sub_block_found)) { + wakeup_sub_poll(); + atomic_set(&sub_block_found, 0); + } + + if (audio_first_access == AUDIO_FIRST_ACCESS_POPING) { + /* + *we are in the procedure of poping data for audio first + * access, continue with last packet + */ + audio_first_access = AUDIO_FIRST_ACCESS_DONE; + + if (packet_remaining) { + next_action = SEND_AUDIO_SEARCH; + SET_BLOCK(packet_remaining); + + } else + next_action = SEARCH_START_CODE; + + } else if (start_code == 0xba) { /* PACK_START_CODE */ + temp = PARSER_POP; + + if ((temp >> 6) == 0x01) { +#if SAVE_SCR + scr = ((temp >> 3) & 0x3) << 30; /* bit 31-30 */ + scr |= (temp & 0x3) << 28; /* bit 29-28 */ + scr |= (PARSER_POP) << 20; /* bit 27-20 */ + temp = PARSER_POP; + scr |= (temp >> 4) << 16; /* bit 19-16 */ + scr |= (temp & 7) << 13; /* bit 15-13 */ + scr |= (PARSER_POP) << 5; /* bit 12-05 */ + scr |= (PARSER_POP) >> 3; /* bit 04-00 */ +#else + PARSER_POP; + PARSER_POP; + PARSER_POP; + PARSER_POP; +#endif + PARSER_POP; + PARSER_POP; + PARSER_POP; + PARSER_POP; + temp = PARSER_POP & 7; + + while (temp) { /* stuff byte */ + PARSER_POP; + temp--; + } + + } else { + /* mpeg-1 Pack Header */ +#if SAVE_SCR + scr = ((temp >> 1) & 0x3) << 30; /* bit 31-30 */ + scr |= (PARSER_POP) << 22; /* bit 29-22 */ + scr |= (PARSER_POP >> 1) << 15; /* bit 21-15 */ + scr |= (PARSER_POP) << 7; /* bit 14-07 */ + scr |= (PARSER_POP >> 1); /* bit 06-00 */ +#else + PARSER_POP; + PARSER_POP; + PARSER_POP; + PARSER_POP; +#endif + } + +#ifdef VIDEO_AUTO_FLUSH + if (video_auto_flush_state == VIDEO_AUTO_FLUSH_TRIGGER) { + next_action = SEARCH_START_CODE_VIDEO_FLUSH; + video_auto_flush_state = VIDEO_AUTO_FLUSH_DONE; + } else +#endif + + next_action = SEARCH_START_CODE; + + } else { + packet_len = (PARSER_POP << 8) | PARSER_POP; + + if (start_code == video_id) + next_action = parser_process(0, packet_len); + + else if (start_code == audio_id) { + /* add mpeg audio packet length check */ + if (packet_len > MAX_MPG_AUDIOPK_SIZE) + next_action = SEARCH_START_CODE; + + else + next_action = parser_process(1, packet_len); + + } else if (start_code == 0xbb) { + SET_DISCARD_SIZE(packet_len); + next_action = DISCARD_SEARCH; + } else if (start_code == 0xbd) + next_action = parser_process(2, packet_len); + + else if (start_code == 0xbf) { + SET_DISCARD_SIZE(packet_len); + next_action = DISCARD_SEARCH; + } else if ((start_code < 0xc0) || (start_code > 0xc8)) + next_action = SEARCH_START_CODE; + + else if (packet_len) { + SET_DISCARD_SIZE(packet_len); + next_action = DISCARD_SEARCH; + + } else + next_action = SEARCH_START_CODE; + } + + switch (next_action) { + case SEARCH_START_CODE: + WRITE_MPEG_REG(PARSER_CONTROL, PARSER_AUTOSEARCH); + break; + + case SEND_VIDEO_SEARCH: + WRITE_MPEG_REG_BITS(PARSER_CONTROL, + PARSER_AUTOSEARCH | PARSER_VIDEO | + PARSER_WRITE, ES_CTRL_BIT, ES_CTRL_WID); + break; + + case SEND_AUDIO_SEARCH: + WRITE_MPEG_REG_BITS(PARSER_CONTROL, + PARSER_AUTOSEARCH | PARSER_AUDIO | + PARSER_WRITE, ES_CTRL_BIT, ES_CTRL_WID); + break; + + case SEND_SUBPIC_SEARCH: + WRITE_MPEG_REG_BITS(PARSER_CONTROL, + PARSER_AUTOSEARCH | PARSER_SUBPIC | + PARSER_WRITE | ES_INSERT_BEFORE_ES_WRITE, + ES_CTRL_BIT, ES_CTRL_WID); + break; + + case DISCARD_SEARCH: + WRITE_MPEG_REG_BITS(PARSER_CONTROL, + PARSER_AUTOSEARCH | PARSER_DISCARD, + ES_CTRL_BIT, ES_CTRL_WID); + break; + + case DISCARD_ONLY: + WRITE_MPEG_REG_BITS(PARSER_CONTROL, + PARSER_DISCARD, ES_CTRL_BIT, ES_CTRL_WID); + break; + +#ifdef VIDEO_AUTO_FLUSH + case SEARCH_START_CODE_VIDEO_FLUSH: + WRITE_MPEG_REG(PARSER_INSERT_DATA, 0xffffffff); + WRITE_MPEG_REG(PARSER_INSERT_DATA, 0xffffffff); + WRITE_MPEG_REG(PARSER_PARAMETER, + ((VIDEO_AUTO_FLUSH_BYTE_COUNT / + 8) << PARSER_PARAMETER_LOOP_BIT) | (8 << + PARSER_PARAMETER_LENGTH_BIT)); + WRITE_MPEG_REG(PARSER_CONTROL, + PARSER_AUTOSEARCH | PARSER_VIDEO | PARSER_WRITE | + ES_INSERT_BEFORE_ES_WRITE); + break; +#endif + } +} + +static void parser_tasklet(ulong data) +{ + s32 sc; + u32 int_status = READ_MPEG_REG(PARSER_INT_STATUS); + + WRITE_MPEG_REG(PARSER_INT_STATUS, int_status); + + if (int_status & PARSER_INTSTAT_FETCH_CMD) { + fetch_done = 1; + + wake_up_interruptible(&wq); + } + + if (int_status & PARSER_INTSTAT_SC_FOUND) { + sc = PARSER_POP; + + on_start_code_found(sc); + + } else if (int_status & PARSER_INTSTAT_DISCARD) + on_start_code_found(0); +} + +static irqreturn_t parser_isr(int irq, void *dev_id) +{ + tasklet_schedule(&psparser_tasklet); + + return IRQ_HANDLED; +} + +static ssize_t _psparser_write(const char __user *buf, size_t count) +{ + size_t r = count; + const char __user *p = buf; + u32 len; + int ret; + dma_addr_t dma_addr = 0; + + if (r > 0) { + len = min_t(size_t, r, FETCHBUF_SIZE); + if (copy_from_user(fetchbuf, p, len)) + return -EFAULT; + + dma_addr = + dma_map_single(amports_get_dma_device(), + fetchbuf, FETCHBUF_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), dma_addr)) + return -EFAULT; + + + fetch_done = 0; + + wmb(); /* Ensure fetchbuf contents visible */ + + WRITE_MPEG_REG(PARSER_FETCH_ADDR, dma_addr); + + WRITE_MPEG_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len); + dma_unmap_single(amports_get_dma_device(), dma_addr, + FETCHBUF_SIZE, DMA_TO_DEVICE); + ret = + wait_event_interruptible_timeout(wq, fetch_done != 0, + HZ / 10); + if (ret == 0) { + WRITE_MPEG_REG(PARSER_FETCH_CMD, 0); + pr_info("write timeout, retry\n"); + return -EAGAIN; + } else if (ret < 0) + return -ERESTARTSYS; + + p += len; + r -= len; + } + + return count - r; +} + +s32 psparser_init(u32 vid, u32 aid, u32 sid, struct vdec_s *vdec) +{ + s32 r; + u32 parser_sub_start_ptr; + u32 parser_sub_end_ptr; + u32 parser_sub_rp; + +#ifdef DEBUG_VOB_SUB + u8 i; + + for (i = 0; i < MAX_SUB_NUM; i++) { + sub_info[i] = kzalloc(sizeof(struct subtitle_info), GFP_KERNEL); + if (!sub_info[i]) { + pr_info + ("[psparser_init]alloc for subtitle info failed\n"); + } else + sub_info[i]->id = -1; + } + sub_found_num = 0; +#endif + parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); + parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); + parser_sub_rp = READ_MPEG_REG(PARSER_SUB_RP); + + video_id = vid; + audio_id = aid; + sub_id = sid; + audio_got_first_pts = 0; + video_got_first_dts = 0; + sub_got_first_pts = 0; + first_apts = 0; + first_vpts = 0; + pts_equ_dts_flag = 0; + +#ifdef VIDEO_AUTO_FLUSH + video_auto_flush_state = VIDEO_AUTO_FLUSH_IDLE; +#endif + + pr_info("video 0x%x, audio 0x%x, sub 0x%x\n", video_id, audio_id, + sub_id); + if (fetchbuf == 0) { + pr_info("%s: no fetchbuf\n", __func__); + return -ENOMEM; + } + + WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER); + + /* TS data path */ +#ifndef CONFIG_AM_DVB + WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0); +#else + tsdemux_set_reset_flag(); +#endif + CLEAR_MPEG_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE)); + + /* hook stream buffer with PARSER */ + WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, + vdec->input.start + vdec->input.size - 8); + + if (vdec_single(vdec)) { + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + } else { + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + WRITE_MPEG_REG(PARSER_VIDEO_WP, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_RP, vdec->input.start); + } + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_MPEG_REG(PARSER_CONFIG, + (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | + (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | + (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); + + if (vdec_single(vdec)) { + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + } + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); + WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_WP, parser_sub_start_ptr); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); + + WRITE_MPEG_REG(PFIFO_RD_PTR, 0); + WRITE_MPEG_REG(PFIFO_WR_PTR, 0); + + WRITE_MPEG_REG(PARSER_SEARCH_PATTERN, MPEG_START_CODE_PATTERN); + WRITE_MPEG_REG(PARSER_SEARCH_MASK, MPEG_START_CODE_MASK); + + WRITE_MPEG_REG(PARSER_CONFIG, + (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | + (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | + PS_CFG_STARTCODE_WID_24 | + PS_CFG_PFIFO_ACCESS_WID_8 | /* single byte pop */ + (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); + WRITE_MPEG_REG(PARSER_CONTROL, PARSER_AUTOSEARCH); + + tasklet_init(&psparser_tasklet, parser_tasklet, 0); + r = pts_start(PTS_TYPE_VIDEO); + if (r < 0) + goto Err_1; + r = pts_start(PTS_TYPE_AUDIO); + if (r < 0) + goto Err_2; + + video_data_parsed = 0; + audio_data_parsed = 0; + /*TODO irq */ + + r = vdec_request_irq(PARSER_IRQ, parser_isr, + "psparser", (void *)psparser_id); + + if (r) { + pr_info("PS Demux irq register failed.\n"); + + r = -ENOENT; + goto Err_3; + } + + WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff); + WRITE_MPEG_REG(PARSER_INT_ENABLE, + PARSER_INT_ALL << PARSER_INT_HOST_EN_BIT); + + return 0; + +Err_3: + pts_stop(PTS_TYPE_AUDIO); + +Err_2: + pts_stop(PTS_TYPE_VIDEO); + +Err_1: + return r; +} + +void psparser_release(void) +{ + u8 i; + + pr_info("psparser_release\n"); + + WRITE_MPEG_REG(PARSER_INT_ENABLE, 0); + /*TODO irq */ + + vdec_free_irq(PARSER_IRQ, (void *)psparser_id); + + pts_stop(PTS_TYPE_VIDEO); + pts_stop(PTS_TYPE_AUDIO); +#ifdef DEBUG_VOB_SUB + for (i = 0; i < MAX_SUB_NUM; i++) + kfree(sub_info[i]); + pr_info("psparser release subtitle info\n"); +#endif +} + +ssize_t psparser_write(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count) +{ + s32 r; + + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + + if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + if ((port->flag & PORT_FLAG_VID) + && (stbuf_space(vbuf) < count)) { + r = stbuf_wait_space(vbuf, count); + if (r < 0) + return r; + } + if ((port->flag & PORT_FLAG_AID) + && (stbuf_space(abuf) < count)) { + r = stbuf_wait_space(abuf, count); + if (r < 0) + return r; + } + } + + return _psparser_write(buf, count); +} + +void psparser_change_avid(unsigned int vid, unsigned int aid) +{ + video_id = vid; + audio_id = aid; +} + +void psparser_change_sid(unsigned int sid) +{ + sub_id = sid; +} + +void psparser_audio_reset(void) +{ + ulong flags; + + DEFINE_SPINLOCK(lock); + + spin_lock_irqsave(&lock, flags); + + WRITE_MPEG_REG(PARSER_AUDIO_WP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_RP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + audio_data_parsed = 0; + + spin_unlock_irqrestore(&lock, flags); + +} + +void psparser_sub_reset(void) +{ + ulong flags; + + DEFINE_SPINLOCK(lock); + u32 parser_sub_start_ptr; + u32 parser_sub_end_ptr; + + spin_lock_irqsave(&lock, flags); + + parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); + parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); + + WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); + WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_WP, parser_sub_start_ptr); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); + + spin_unlock_irqrestore(&lock, flags); + +} + +u8 psparser_get_sub_found_num(void) +{ +#ifdef DEBUG_VOB_SUB + return sub_found_num; +#else + return 0; +#endif +} + +u8 psparser_get_sub_info(struct subtitle_info **sub_infos) +{ +#ifdef DEBUG_VOB_SUB + u8 i = 0; + int ret = 0; + u8 size = sizeof(struct subtitle_info); + + for (i = 0; i < sub_found_num; i++) { + if (!sub_info[i]) { + pr_info + ("[psparser_get_sub_info:%d] sub_info[%d] NULL\n", + __LINE__, i); + ret = -1; + break; + } + if (!sub_infos[i]) { + pr_info + ("[psparser_get_sub_info:%d] sub_infos[%d] NULL\n", + __LINE__, i); + ret = -2; + break; + } + memcpy(sub_infos[i], sub_info[i], size); + } + return ret; +#else + return 0; +#endif +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/psparser.h b/drivers/amlogic/media_modules/stream_input/parser/psparser.h new file mode 100644 index 000000000000..1280b6aa87f9 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/psparser.h @@ -0,0 +1,141 @@ +/* + * drivers/amlogic/media/stream_input/parser/psparser.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef PSPARSER_H +#define PSPARSER_H + +#include "../../frame_provider/decoder/utils/vdec.h" + +extern s32 psparser_init(u32 vid, u32 aid, u32 sid, struct vdec_s *vdec); + +extern void psparser_release(void); + +extern ssize_t psparser_write(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, const char __user *buf, size_t count); + +extern void psparser_change_avid(unsigned int vid, unsigned int aid); + +extern void psparser_change_sid(unsigned int sid); + +extern void psparser_audio_reset(void); + +extern void psparser_sub_reset(void); + +extern u8 psparser_get_sub_found_num(void); + +extern u8 psparser_get_sub_info(struct subtitle_info *sub_infos[]); + +#ifdef CONFIG_AM_DVB +extern int tsdemux_set_reset_flag(void); +#endif + +/* TODO: move to register headers */ +#define ES_PACK_SIZE_BIT 8 +#define ES_PACK_SIZE_WID 24 + +#define ES_CTRL_WID 8 +#define ES_CTRL_BIT 0 +#define ES_TYPE_MASK (3 << 6) +#define ES_TYPE_VIDEO (0 << 6) +#define ES_TYPE_AUDIO (1 << 6) +#define ES_TYPE_SUBTITLE (2 << 6) + +#define ES_WRITE (1<<5) +#define ES_PASSTHROUGH (1<<4) +#define ES_INSERT_BEFORE_ES_WRITE (1<<3) +#define ES_DISCARD (1<<2) +#define ES_SEARCH (1<<1) +#define ES_PARSER_START (1<<0) +#define ES_PARSER_BUSY (1<<0) + +#define PARSER_INTSTAT_FETCH_CMD (1<<7) +#define PARSER_INTSTAT_PARSE (1<<4) +#define PARSER_INTSTAT_DISCARD (1<<3) +#define PARSER_INTSTAT_INSZERO (1<<2) +#define PARSER_INTSTAT_ACT_NOSSC (1<<1) +#define PARSER_INTSTAT_SC_FOUND (1<<0) + +#define FETCH_CIR_BUF (1<<31) +#define FETCH_CHK_BUF_STOP (1<<30) +#define FETCH_PASSTHROUGH (1<<29) +#define FETCH_ENDIAN 27 +#define FETCH_PASSTHROUGH_TYPE_MASK (0x3<<27) +#define FETCH_ENDIAN_MASK (0x7<<27) +#define FETCH_BUF_SIZE_MASK (0x7ffffff) +#define FETCH_CMD_PTR_MASK 3 +#define FETCH_CMD_RD_PTR_BIT 5 +#define FETCH_CMD_WR_PTR_BIT 3 +#define FETCH_CMD_NUM_MASK 3 +#define FETCH_CMD_NUM_BIT 0 + +#define ES_COUNT_MASK 0xfff +#define ES_COUNT_BIT 20 +#define ES_REQ_PENDING (1<<19) +#define ES_PASSTHROUGH_EN (1<<18) +#define ES_PASSTHROUGH_TYPE_MASK (3<<16) +#define ES_PASSTHROUGH_TYPE_VIDEO (0<<16) +#define ES_PASSTHROUGH_TYPE_AUDIO (1<<16) +#define ES_PASSTHROUGH_TYPE_SUBTITLE (2<<16) +#define ES_WR_ENDIAN_MASK (0x7) +#define ES_SUB_WR_ENDIAN_BIT 9 +#define ES_SUB_MAN_RD_PTR (1<<8) +#define ES_AUD_WR_ENDIAN_BIT 5 +#define ES_AUD_MAN_RD_PTR (1<<4) +#define ES_VID_WR_ENDIAN_BIT 1 +#define ES_VID_MAN_RD_PTR (1<<0) + +#define PS_CFG_FETCH_DMA_URGENT (1<<31) +#define PS_CFG_STREAM_DMA_URGENT (1<<30) +#define PS_CFG_FORCE_PFIFO_REN (1<<29) +#define PS_CFG_PFIFO_PEAK_EN (1<<28) +#define PS_CFG_SRC_SEL_BIT 24 +#define PS_CFG_SRC_SEL_MASK (3< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../amports/amports_priv.h" +#include "streambuf.h" +#include "streambuf_reg.h" +#include +#include "rmparser.h" + +#define MANAGE_PTS + +static u32 fetch_done; +static u32 parse_halt; + +static DECLARE_WAIT_QUEUE_HEAD(rm_wq); +static const char rmparser_id[] = "rmparser-id"; + +static irqreturn_t rm_parser_isr(int irq, void *dev_id) +{ + u32 int_status = READ_MPEG_REG(PARSER_INT_STATUS); + + if (int_status & PARSER_INTSTAT_FETCH_CMD) { + WRITE_MPEG_REG(PARSER_INT_STATUS, PARSER_INTSTAT_FETCH_CMD); + fetch_done = 1; + + wake_up_interruptible(&rm_wq); + } + + return IRQ_HANDLED; +} + +s32 rmparser_init(struct vdec_s *vdec) +{ + s32 r; + parse_halt = 0; + if (fetchbuf == 0) { + pr_info("%s: no fetchbuf\n", __func__); + return -ENOMEM; + } + + WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER); + + /* TS data path */ +#ifndef CONFIG_AM_DVB + WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0); +#else + tsdemux_set_reset_flag(); +#endif + CLEAR_MPEG_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE); + CLEAR_MPEG_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE); + + CLEAR_MPEG_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE)); + + /* hook stream buffer with PARSER */ + WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, + vdec->input.start + vdec->input.size - 8); + + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + WRITE_MPEG_REG(PFIFO_RD_PTR, 0); + WRITE_MPEG_REG(PFIFO_WR_PTR, 0); + + WRITE_MPEG_REG(PARSER_SEARCH_MASK, 0); + WRITE_MPEG_REG(PARSER_CONTROL, (ES_SEARCH | ES_PARSER_START)); + +#ifdef MANAGE_PTS + if (pts_start(PTS_TYPE_VIDEO) < 0) + goto Err_1; + + if (pts_start(PTS_TYPE_AUDIO) < 0) + goto Err_2; +#endif + /*TODO irq */ + + /* enable interrupt */ + + r = vdec_request_irq(PARSER_IRQ, rm_parser_isr, + "rmparser", (void *)rmparser_id); + + if (r) { + pr_info("RM parser irq register failed.\n"); + goto Err_3; + } + + WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff); + WRITE_MPEG_REG(PARSER_INT_ENABLE, + ((PARSER_INT_ALL & (~PARSER_INTSTAT_FETCH_CMD)) << + PARSER_INT_AMRISC_EN_BIT) + | (PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT)); + + return 0; + +Err_3: + pts_stop(PTS_TYPE_AUDIO); +Err_2: + pts_stop(PTS_TYPE_VIDEO); +Err_1: + return -ENOENT; +} +EXPORT_SYMBOL(rmparser_init); + +void rmparser_release(void) +{ + WRITE_MPEG_REG(PARSER_INT_ENABLE, 0); + /*TODO irq */ + + vdec_free_irq(PARSER_IRQ, (void *)rmparser_id); + +#ifdef MANAGE_PTS + pts_stop(PTS_TYPE_VIDEO); + pts_stop(PTS_TYPE_AUDIO); +#endif + + return; +} +EXPORT_SYMBOL(rmparser_release); + +static inline u32 buf_wp(u32 type) +{ + return (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) : + (type == BUF_TYPE_AUDIO) ? + READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) : + READ_MPEG_REG(PARSER_SUB_START_PTR); +} + +static ssize_t _rmparser_write(const char __user *buf, size_t count) +{ + size_t r = count; + const char __user *p = buf; + u32 len; + int ret; + static int halt_droped_len; + u32 vwp, awp; + dma_addr_t dma_addr = 0; + + if (r > 0) { + len = min_t(size_t, r, FETCHBUF_SIZE); + + if (copy_from_user(fetchbuf, p, len)) + return -EFAULT; + dma_addr = + dma_map_single(amports_get_dma_device(), + fetchbuf, FETCHBUF_SIZE, + DMA_TO_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), dma_addr)) + return -EFAULT; + + fetch_done = 0; + + wmb(); /* Ensure fetchbuf contents visible */ + vwp = buf_wp(BUF_TYPE_VIDEO); + awp = buf_wp(BUF_TYPE_AUDIO); + WRITE_MPEG_REG(PARSER_FETCH_ADDR, dma_addr); + + WRITE_MPEG_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len); + dma_unmap_single(amports_get_dma_device(), dma_addr, + FETCHBUF_SIZE, DMA_TO_DEVICE); + ret = + wait_event_interruptible_timeout(rm_wq, fetch_done != 0, + HZ / 10); + if (ret == 0) { + WRITE_MPEG_REG(PARSER_FETCH_CMD, 0); + parse_halt++; + pr_info + ("write timeout,retry,halt_count=%d parse_control=%x\n", + parse_halt, READ_MPEG_REG(PARSER_CONTROL)); + + //vreal_set_fatal_flag(1);//DEBUG_TMP + + if (parse_halt > 10) { + WRITE_MPEG_REG(PARSER_CONTROL, + (ES_SEARCH | ES_PARSER_START)); + pr_info("reset parse_control=%x\n", + READ_MPEG_REG(PARSER_CONTROL)); + } + return -EAGAIN; + } else if (ret < 0) + return -ERESTARTSYS; + + if (vwp == buf_wp(BUF_TYPE_VIDEO) + && awp == buf_wp(BUF_TYPE_AUDIO)) { + struct stream_buf_s *v_buf_t = + get_buf_by_type(BUF_TYPE_VIDEO); + struct stream_buf_s *a_buf_t = + get_buf_by_type(BUF_TYPE_AUDIO); + int v_st_lv = stbuf_level(v_buf_t); + int a_st_lv = stbuf_level(a_buf_t); + if ((parse_halt + 1) % 10 == 1) { + pr_info("V&A WP not changed after write"); + pr_info(",video %x->%x", vwp, + buf_wp(BUF_TYPE_VIDEO)); + pr_info(",Audio:%x-->%x,parse_halt=%d\n", + awp, buf_wp(BUF_TYPE_AUDIO), + parse_halt); + } + parse_halt++; /*wp not changed , + we think have bugs on parser now. */ + if (parse_halt > 10 && + (v_st_lv < 1000 || a_st_lv < 100)) { + /*reset while at least one is underflow. */ + WRITE_MPEG_REG(PARSER_CONTROL, + (ES_SEARCH | ES_PARSER_START)); + pr_info("reset parse_control=%x\n", + READ_MPEG_REG(PARSER_CONTROL)); + } + if (parse_halt <= 10 || + halt_droped_len < 100 * 1024) { + /*drops first 10 pkt , + some times maybe no av data */ + pr_info("drop this pkt=%d,len=%d\n", parse_halt, + len); + p += len; + r -= len; + halt_droped_len += len; + } else + return -EAGAIN; + } else { + halt_droped_len = 0; + parse_halt = 0; + p += len; + r -= len; + } + } + return count - r; +} + +ssize_t rmparser_write(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count) +{ + s32 r; + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + size_t towrite = count; + if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) { + if (file->f_flags & O_NONBLOCK) { + towrite = min(stbuf_space(vbuf), stbuf_space(abuf)); + if (towrite < 1024) /*? can write small? */ + return -EAGAIN; + } else { + if ((port->flag & PORT_FLAG_VID) + && (stbuf_space(vbuf) < count)) { + r = stbuf_wait_space(vbuf, count); + if (r < 0) + return r; + } + if ((port->flag & PORT_FLAG_AID) + && (stbuf_space(abuf) < count)) { + r = stbuf_wait_space(abuf, count); + if (r < 0) + return r; + } + } + } + towrite = min(towrite, count); + return _rmparser_write(buf, towrite); +} +EXPORT_SYMBOL(rmparser_write); + +void rm_set_vasid(u32 vid, u32 aid) +{ + pr_info("rm_set_vasid aid %d, vid %d\n", aid, vid); + WRITE_MPEG_REG(VAS_STREAM_ID, (aid << 8) | vid); + + return; +} +EXPORT_SYMBOL(rm_set_vasid); + +void rm_audio_reset(void) +{ + ulong flags; + DEFINE_SPINLOCK(lock); + + spin_lock_irqsave(&lock, flags); + + WRITE_MPEG_REG(PARSER_AUDIO_WP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_RP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + spin_unlock_irqrestore(&lock, flags); + + return; +} +EXPORT_SYMBOL(rm_audio_reset); diff --git a/drivers/amlogic/media_modules/stream_input/parser/rmparser.h b/drivers/amlogic/media_modules/stream_input/parser/rmparser.h new file mode 100644 index 000000000000..5d258eed4e73 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/rmparser.h @@ -0,0 +1,136 @@ +/* + * drivers/amlogic/amports/rmparser.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef RMPARSER_H +#define RMPARSER_H + +#include "../../frame_provider/decoder/utils/vdec.h" + +extern void rm_set_vasid(u32 vid, u32 aid); + +extern ssize_t rmparser_write(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count); + +s32 rmparser_init(struct vdec_s *vdec); + +extern void rmparser_release(void); + +extern void rm_audio_reset(void); + +extern void vreal_set_fatal_flag(int flag); + +#ifdef CONFIG_AM_DVB +extern int tsdemux_set_reset_flag(void); +#endif + +/* TODO: move to register headers */ +#define ES_PACK_SIZE_BIT 8 +#define ES_PACK_SIZE_WID 24 + +#define ES_CTRL_WID 8 +#define ES_CTRL_BIT 0 +#define ES_TYPE_MASK (3 << 6) +#define ES_TYPE_VIDEO (0 << 6) +#define ES_TYPE_AUDIO (1 << 6) +#define ES_TYPE_SUBTITLE (2 << 6) + +#define ES_WRITE (1<<5) +#define ES_PASSTHROUGH (1<<4) +#define ES_INSERT_BEFORE_ES_WRITE (1<<3) +#define ES_DISCARD (1<<2) +#define ES_SEARCH (1<<1) +#define ES_PARSER_START (1<<0) +#define ES_PARSER_BUSY (1<<0) + +#define PARSER_INTSTAT_FETCH_CMD (1<<7) +#define PARSER_INTSTAT_PARSE (1<<4) +#define PARSER_INTSTAT_DISCARD (1<<3) +#define PARSER_INTSTAT_INSZERO (1<<2) +#define PARSER_INTSTAT_ACT_NOSSC (1<<1) +#define PARSER_INTSTAT_SC_FOUND (1<<0) + +#define FETCH_CIR_BUF (1<<31) +#define FETCH_CHK_BUF_STOP (1<<30) +#define FETCH_PASSTHROUGH (1<<29) +#define FETCH_ENDIAN 27 +#define FETCH_PASSTHROUGH_TYPE_MASK (0x3<<27) +#define FETCH_ENDIAN_MASK (0x7<<27) +#define FETCH_BUF_SIZE_MASK (0x7ffffff) +#define FETCH_CMD_PTR_MASK 3 +#define FETCH_CMD_RD_PTR_BIT 5 +#define FETCH_CMD_WR_PTR_BIT 3 +#define FETCH_CMD_NUM_MASK 3 +#define FETCH_CMD_NUM_BIT 0 + +#define ES_COUNT_MASK 0xfff +#define ES_COUNT_BIT 20 +#define ES_REQ_PENDING (1<<19) +#define ES_PASSTHROUGH_EN (1<<18) +#define ES_PASSTHROUGH_TYPE_MASK (3<<16) +#define ES_PASSTHROUGH_TYPE_VIDEO (0<<16) +#define ES_PASSTHROUGH_TYPE_AUDIO (1<<16) +#define ES_PASSTHROUGH_TYPE_SUBTITLE (2<<16) +#define ES_WR_ENDIAN_MASK (0x7) +#define ES_SUB_WR_ENDIAN_BIT 9 +#define ES_SUB_MAN_RD_PTR (1<<8) +#define ES_AUD_WR_ENDIAN_BIT 5 +#define ES_AUD_MAN_RD_PTR (1<<4) +#define ES_VID_WR_ENDIAN_BIT 1 +#define ES_VID_MAN_RD_PTR (1<<0) + +#define PS_CFG_FETCH_DMA_URGENT (1<<31) +#define PS_CFG_STREAM_DMA_URGENT (1<<30) +#define PS_CFG_FORCE_PFIFO_REN (1<<29) +#define PS_CFG_PFIFO_PEAK_EN (1<<28) +#define PS_CFG_SRC_SEL_BIT 24 +#define PS_CFG_SRC_SEL_MASK (3< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ + +#include +#include "../../frame_provider/decoder/utils/vdec.h" +#include "streambuf_reg.h" +#include "streambuf.h" +#include +#include "../amports/amports_priv.h" +#include +#include +#include + +#define STBUF_SIZE (64*1024) +#define STBUF_WAIT_INTERVAL (HZ/100) +#define MEM_NAME "streambuf" + +void *fetchbuf; + +static s32 _stbuf_alloc(struct stream_buf_s *buf) +{ + if (buf->buf_size == 0) + return -ENOBUFS; + + while (buf->buf_start == 0) { + int flags = CODEC_MM_FLAGS_DMA; + + buf->buf_page_num = PAGE_ALIGN(buf->buf_size) / PAGE_SIZE; + if (buf->type == BUF_TYPE_SUBTITLE) + flags = CODEC_MM_FLAGS_DMA_CPU; + + /* + *if 4k, + *used cma first,for less mem fragments. + */ + if (((buf->type == BUF_TYPE_HEVC) || + (buf->type == BUF_TYPE_VIDEO)) && + buf->for_4k) + flags |= CODEC_MM_FLAGS_CMA_FIRST; + if (buf->buf_size > 20 * 1024 * 1024) + flags |= CODEC_MM_FLAGS_CMA_FIRST; + + if ((buf->type == BUF_TYPE_HEVC) || + (buf->type == BUF_TYPE_VIDEO)) { + flags |= CODEC_MM_FLAGS_FOR_VDECODER; + } else if (buf->type == BUF_TYPE_AUDIO) { + flags |= CODEC_MM_FLAGS_FOR_ADECODER; + flags |= CODEC_MM_FLAGS_DMA_CPU; + } + + buf->buf_start = codec_mm_alloc_for_dma(MEM_NAME, + buf->buf_page_num, 4+PAGE_SHIFT, flags); + if (!buf->buf_start) { + int is_video = (buf->type == BUF_TYPE_HEVC) || + (buf->type == BUF_TYPE_VIDEO); + if (is_video && buf->buf_size >= 9 * SZ_1M) {/*min 6M*/ + int old_size = buf->buf_size; + + buf->buf_size = + PAGE_ALIGN(buf->buf_size * 2/3); + pr_info("%s stbuf alloced size = %d failed try small %d size\n", + (buf->type == BUF_TYPE_HEVC) ? "HEVC" : + (buf->type == BUF_TYPE_VIDEO) ? "Video" : + (buf->type == BUF_TYPE_AUDIO) ? "Audio" : + "Subtitle", old_size, buf->buf_size); + continue; + } + pr_info("%s stbuf alloced size = %d failed\n", + (buf->type == BUF_TYPE_HEVC) ? "HEVC" : + (buf->type == BUF_TYPE_VIDEO) ? "Video" : + (buf->type == BUF_TYPE_AUDIO) ? "Audio" : + "Subtitle", buf->buf_size); + return -ENOMEM; + } + pr_info("%s stbuf alloced at %p, size = %d\n", + (buf->type == BUF_TYPE_HEVC) ? "HEVC" : + (buf->type == BUF_TYPE_VIDEO) ? "Video" : + (buf->type == BUF_TYPE_AUDIO) ? "Audio" : + "Subtitle", (void *)buf->buf_start, + buf->buf_size); + } + if (buf->buf_size < buf->canusebuf_size) + buf->canusebuf_size = buf->buf_size; + buf->flag |= BUF_FLAG_ALLOC; + + return 0; +} + +int stbuf_change_size(struct stream_buf_s *buf, int size) +{ + unsigned long old_buf; + int old_size, old_pagenum; + int ret; + + pr_info("buffersize=%d,%d,start=%p\n", size, buf->buf_size, + (void *)buf->buf_start); + + if (buf->buf_size == size && buf->buf_start != 0) + return 0; + + old_buf = buf->buf_start; + old_size = buf->buf_size; + old_pagenum = buf->buf_page_num; + buf->buf_start = 0; + buf->buf_size = size; + ret = size; + + if (size == 0 || _stbuf_alloc(buf) == 0) { + /* + * size=0:We only free the old memory; + * alloc ok,changed to new buffer + */ + if (old_buf != 0) + codec_mm_free_for_dma(MEM_NAME, old_buf); + + pr_info("changed the (%d) buffer size from %d to %d\n", + buf->type, old_size, size); + return 0; + } + /* alloc failed */ + buf->buf_start = old_buf; + buf->buf_size = old_size; + buf->buf_page_num = old_pagenum; + pr_info("changed the (%d) buffer size from %d to %d,failed\n", + buf->type, old_size, size); + + return ret; +} + +int stbuf_fetch_init(void) +{ + if (NULL != fetchbuf) + return 0; + + fetchbuf = (void *)__get_free_pages(GFP_KERNEL, + get_order(FETCHBUF_SIZE)); + + if (!fetchbuf) { + pr_info("%s: Can not allocate fetch working buffer\n", + __func__); + return -ENOMEM; + } + return 0; +} + +void stbuf_fetch_release(void) +{ + if (0 && fetchbuf) { + /* always don't free.for safe alloc/free*/ + free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE)); + fetchbuf = 0; + } +} + +static void _stbuf_timer_func(unsigned long arg) +{ + struct stream_buf_s *p = (struct stream_buf_s *)arg; + + if (stbuf_space(p) < p->wcnt) { + p->timer.expires = jiffies + STBUF_WAIT_INTERVAL; + + add_timer(&p->timer); + } else + wake_up_interruptible(&p->wq); + +} + +u32 stbuf_level(struct stream_buf_s *buf) +{ + if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) { + if (READ_MPEG_REG(PARSER_ES_CONTROL) & 1) { + int level = READ_MPEG_REG(PARSER_VIDEO_WP) - + READ_MPEG_REG(PARSER_VIDEO_RP); + if (level < 0) + level += READ_MPEG_REG(PARSER_VIDEO_END_PTR) - + READ_MPEG_REG(PARSER_VIDEO_START_PTR) + 8; + return (u32)level; + } else + return (buf->type == BUF_TYPE_HEVC) ? + READ_VREG(HEVC_STREAM_LEVEL) : + _READ_ST_REG(LEVEL); + } + + return _READ_ST_REG(LEVEL); +} + +u32 stbuf_rp(struct stream_buf_s *buf) +{ + if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) { + if (READ_MPEG_REG(PARSER_ES_CONTROL) & 1) + return READ_MPEG_REG(PARSER_VIDEO_RP); + else + return (buf->type == BUF_TYPE_HEVC) ? + READ_VREG(HEVC_STREAM_RD_PTR) : + _READ_ST_REG(RP); + } + + return _READ_ST_REG(RP); +} + +u32 stbuf_space(struct stream_buf_s *buf) +{ + /* reserved space for safe write, + the parser fifo size is 1024byts, so reserve it */ + int size; + + size = buf->canusebuf_size - stbuf_level(buf); + + if (buf->canusebuf_size >= buf->buf_size / 2) { + /* old reversed value,tobe full, reversed only... */ + size = size - 6 * 1024; + } + + if ((buf->type == BUF_TYPE_VIDEO) + || (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC)) + size -= READ_MPEG_REG(PARSER_VIDEO_HOLE); + + return size > 0 ? size : 0; +} + +u32 stbuf_size(struct stream_buf_s *buf) +{ + return buf->buf_size; +} + +u32 stbuf_canusesize(struct stream_buf_s *buf) +{ + return buf->canusebuf_size; +} + +s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec) +{ + s32 r; + u32 dummy; + u32 addr32; + + if (!buf->buf_start) { + r = _stbuf_alloc(buf); + if (r < 0) + return r; + } + addr32 = buf->buf_start & 0xffffffff; + init_waitqueue_head(&buf->wq); + + if ((buf->type == BUF_TYPE_VIDEO) || (buf->type == BUF_TYPE_HEVC)) { + if (vdec) { + if (vdec_stream_based(vdec)) + vdec_input_set_buffer(&vdec->input, addr32, + buf->buf_size); + else + return vdec_input_set_buffer(&vdec->input, + addr32, buf->buf_size); + } + } + + buf->write_thread = 0; + if (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC) { + CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 1); + WRITE_VREG(HEVC_STREAM_START_ADDR, addr32); + WRITE_VREG(HEVC_STREAM_END_ADDR, addr32 + buf->buf_size); + WRITE_VREG(HEVC_STREAM_RD_PTR, addr32); + WRITE_VREG(HEVC_STREAM_WR_PTR, addr32); + + return 0; + } + + if (buf->type == BUF_TYPE_VIDEO) { + _WRITE_ST_REG(CONTROL, 0); + /* reset VLD before setting all pointers */ + WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, 0); + /*TODO: only > m6*/ +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + WRITE_VREG(DOS_SW_RESET0, (1 << 4)); + WRITE_VREG(DOS_SW_RESET0, 0); +#else + WRITE_MPEG_REG(RESET0_REGISTER, RESET_VLD); +#endif + + dummy = READ_MPEG_REG(RESET0_REGISTER); + WRITE_VREG(POWER_CTL_VLD, 1 << 4); + } else if (buf->type == BUF_TYPE_AUDIO) { + _WRITE_ST_REG(CONTROL, 0); + + WRITE_MPEG_REG(AIU_AIFIFO_GBIT, 0x80); + } + + if (buf->type == BUF_TYPE_SUBTITLE) { + WRITE_MPEG_REG(PARSER_SUB_RP, addr32); + WRITE_MPEG_REG(PARSER_SUB_START_PTR, addr32); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, + addr32 + buf->buf_size - 8); + + return 0; + } + + _WRITE_ST_REG(START_PTR, addr32); + _WRITE_ST_REG(CURR_PTR, addr32); + _WRITE_ST_REG(END_PTR, addr32 + buf->buf_size - 8); + + _SET_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT); + _CLR_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT); + + _WRITE_ST_REG(BUF_CTRL, MEM_BUFCTRL_MANUAL); + _WRITE_ST_REG(WP, addr32); + + _SET_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT); + _CLR_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT); + + _SET_ST_REG_MASK(CONTROL, + (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN | + MEM_CTRL_EMPTY_EN); + return 0; +} + +void stbuf_vdec2_init(struct stream_buf_s *buf) +{ + + _WRITE_VDEC2_ST_REG(CONTROL, 0); + + _WRITE_VDEC2_ST_REG(START_PTR, _READ_ST_REG(START_PTR)); + _WRITE_VDEC2_ST_REG(END_PTR, _READ_ST_REG(END_PTR)); + _WRITE_VDEC2_ST_REG(CURR_PTR, _READ_ST_REG(CURR_PTR)); + + _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL | MEM_BUFCTRL_INIT); + _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL); + + _WRITE_VDEC2_ST_REG(BUF_CTRL, MEM_BUFCTRL_INIT); + _WRITE_VDEC2_ST_REG(BUF_CTRL, 0); + + _WRITE_VDEC2_ST_REG(CONTROL, + (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN + | MEM_CTRL_EMPTY_EN); +} + +s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count) +{ + struct stream_buf_s *p = stream_buf; + long time_out = 20; + + p->wcnt = count; + + setup_timer(&p->timer, _stbuf_timer_func, (ulong) p); + + mod_timer(&p->timer, jiffies + STBUF_WAIT_INTERVAL); + + if (wait_event_interruptible_timeout + (p->wq, stbuf_space(p) >= count, time_out) == 0) { + del_timer_sync(&p->timer); + + return -EAGAIN; + } + + del_timer_sync(&p->timer); + + return 0; +} + +void stbuf_release(struct stream_buf_s *buf) +{ + buf->first_tstamp = INVALID_PTS; + + stbuf_init(buf, NULL); /* reinit buffer */ + + if (buf->flag & BUF_FLAG_ALLOC && buf->buf_start) { + codec_mm_free_for_dma(MEM_NAME, buf->buf_start); + buf->flag &= ~BUF_FLAG_ALLOC; + buf->buf_start = 0; + } + buf->flag &= ~BUF_FLAG_IN_USE; +} + +u32 stbuf_sub_rp_get(void) +{ + return READ_MPEG_REG(PARSER_SUB_RP); +} + +void stbuf_sub_rp_set(unsigned int sub_rp) +{ + WRITE_MPEG_REG(PARSER_SUB_RP, sub_rp); +} + +u32 stbuf_sub_wp_get(void) +{ + return READ_MPEG_REG(PARSER_SUB_WP); +} + +u32 stbuf_sub_start_get(void) +{ + return READ_MPEG_REG(PARSER_SUB_START_PTR); +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h new file mode 100644 index 000000000000..cdae0a8c0a5b --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h @@ -0,0 +1,136 @@ +/* + * drivers/amlogic/media/stream_input/parser/streambuf.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef STREAMBUF_H +#define STREAMBUF_H +#include + +#define BUF_FLAG_ALLOC 0x01 +#define BUF_FLAG_IN_USE 0x02 +#define BUF_FLAG_PARSER 0x04 +#define BUF_FLAG_FIRST_TSTAMP 0x08 +#define BUF_FLAG_IOMEM 0x10 + +#define BUF_TYPE_VIDEO 0 +#define BUF_TYPE_AUDIO 1 +#define BUF_TYPE_SUBTITLE 2 +#define BUF_TYPE_USERDATA 3 +#define BUF_TYPE_HEVC 4 +#define BUF_MAX_NUM 5 + +#define INVALID_PTS 0xffffffff + +#define FETCHBUF_SIZE (64*1024) +#define USER_DATA_SIZE (8*1024) + +struct vdec_s; + +struct stream_buf_s { + s32 flag; + u32 type; + unsigned long buf_start; + struct page *buf_pages; + int buf_page_num; + u32 buf_size; + u32 default_buf_size; + u32 canusebuf_size; + u32 first_tstamp; + const ulong reg_base; + wait_queue_head_t wq; + struct timer_list timer; + u32 wcnt; + u32 buf_wp; + u32 buf_rp; + u32 max_buffer_delay_ms; + u64 last_write_jiffies64; + void *write_thread; + int for_4k; +} /*stream_buf_t */; + +struct stream_port_s { + /* driver info */ + const char *name; + struct device *class_dev; + const struct file_operations *fops; + + /* ports control */ + s32 type; + s32 flag; + s32 pcr_inited; + + /* decoder info */ + s32 vformat; + s32 aformat; + s32 achanl; + s32 asamprate; + s32 adatawidth; + + /* parser info */ + u32 vid; + u32 aid; + u32 sid; + u32 pcrid; +} /*stream_port_t */; +enum drm_level_e { + DRM_LEVEL1 = 1, + DRM_LEVEL2 = 2, + DRM_LEVEL3 = 3, + DRM_NONE = 4, +}; + +struct drm_info { + enum drm_level_e drm_level; + u32 drm_flag; + u32 drm_hasesdata; + u32 drm_priv; + u32 drm_pktsize; + u32 drm_pktpts; + u32 drm_phy; + u32 drm_vir; + u32 drm_remap; + u32 data_offset; + u32 extpad[8]; +} /*drminfo_t */; + +#define TYPE_DRMINFO 0x80 +#define TYPE_PATTERN 0x40 + +struct vdec_s; + +extern void *fetchbuf; + +extern u32 stbuf_level(struct stream_buf_s *buf); +extern u32 stbuf_rp(struct stream_buf_s *buf); +extern u32 stbuf_space(struct stream_buf_s *buf); +extern u32 stbuf_size(struct stream_buf_s *buf); +extern u32 stbuf_canusesize(struct stream_buf_s *buf); +extern s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec); +extern s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count); +extern void stbuf_release(struct stream_buf_s *buf); +extern int stbuf_change_size(struct stream_buf_s *buf, int size); +extern int stbuf_fetch_init(void); +extern void stbuf_fetch_release(void); +extern u32 stbuf_sub_rp_get(void); +extern void stbuf_sub_rp_set(unsigned int sub_rp); +extern u32 stbuf_sub_wp_get(void); +extern u32 stbuf_sub_start_get(void); +extern u32 stbuf_userdata_start_get(void); +extern struct stream_buf_s *get_stream_buffer(int id); + +extern void stbuf_vdec2_init(struct stream_buf_s *buf); + +#endif /* STREAMBUF_H */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h b/drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h new file mode 100644 index 000000000000..f00c70532c88 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/streambuf_reg.h @@ -0,0 +1,111 @@ +/* + * drivers/amlogic/media/stream_input/parser/streambuf_reg.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef STREAMBUF_REG_H +#define STREAMBUF_REG_H + +#define HEVC_STREAM_REG_BASE HEVC_STREAM_START_ADDR + +#define VLD_MEM_VIFIFO_REG_BASE VLD_MEM_VIFIFO_START_PTR +#define AIU_MEM_AIFIFO_REG_BASE AIU_MEM_AIFIFO_START_PTR + +#define START_PTR 0 +#define CURR_PTR 1 +#define END_PTR 2 +#define BYTES_AVAIL 3 +#define CONTROL 4 +#define WP 5 +#define RP 6 +#define LEVEL 7 +#define BUF_CTRL 8 + +/* +*#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 +*#define _WRITE_ST_REG(r, val) \ +* __raw_writel(val, (volatile void __iomem *)(buf->reg_base+(r<<2))) +*#define _WRITE_ST_REG_BITS(r, val, s, e) \ +* __raw_writel((((_READ_ST_REG(r) & \ +* (((1L<<(e)-1)<<(s))-1)<<(s)))|((unsigned)((val)&((1L<<(e))-1))<<(s))), \ +* (volatile void __iomem *)(buf->reg_base+(r<<2))) +*#define _SET_ST_REG_MASK(r, val) \ +* __raw_writel(_READ_ST_REG(r)| (val), \ +* (volatile void __iomem *)(buf->reg_base+(r<<2))) +*#define _CLR_ST_REG_MASK(r, val) \ +* __raw_writel(_READ_ST_REG(r)&~(val), \ +* (volatile void __iomem *)(buf->reg_base+(r<<2))) +*#define _READ_ST_REG(r) \ +* (__raw_readl((volatile void __iomem *)(buf->reg_base+(r<<2)))) +* +*#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD +*#define _READ_VDEC2_ST_REG(r) \ +* (__raw_readl((volatile void __iomem *)(buf->reg_base + \ +* DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \ +* DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2)))) +*#define _WRITE_VDEC2_ST_REG(r, val) \ +* __raw_writel(val, (volatile void __iomem *)(buf->reg_base + \ +* DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \ +* DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2))) +*#endif +* +*#define MEM_BUFCTRL_MANUAL (1<<1) +*#define MEM_BUFCTRL_INIT (1<<0) +*#define MEM_LEVEL_CNT_BIT 18 +*#define MEM_FIFO_CNT_BIT 16 +*#define MEM_FILL_ON_LEVEL (1<<10) +*#define MEM_CTRL_EMPTY_EN (1<<2) +*#define MEM_CTRL_FILL_EN (1<<1) +*#define MEM_CTRL_INIT (1<<0) +* +*#else +*#define _WRITE_ST_REG(r, val) WRITE_MPEG_REG(buf->reg_base + (r), \ +* (val)) +*#define _WRITE_ST_REG_BITS(r, val, s, e) WRITE_MPEG_REG(buf->reg_base + (r), \ +* (val), (s), (e)) +*#define _SET_ST_REG_MASK(r, val) SET_MPEG_REG_MASK(buf->reg_base + \ +* (r), (val)) +*#define _CLR_ST_REG_MASK(r, val) CLEAR_MPEG_REG_MASK(buf->reg_base + \ +* (r), (val)) +*#define _READ_ST_REG(r) READ_MPEG_REG(buf->reg_base + (r)) +*#endif +*/ + + /*TODO*/ +#define _WRITE_ST_REG(r, val) do { \ + if (buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) \ + codec_dosbus_write((buf->reg_base+(r)), (val)); \ + else \ + codec_cbus_write((buf->reg_base+(r)), (val)); \ + } while (0) +#define _READ_ST_REG(r) \ + ((buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) ? \ + codec_dosbus_read(buf->reg_base+(r)) : \ + codec_cbus_read(buf->reg_base+(r))) +#define _SET_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r) | (val)) +#define _CLR_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r)&~(val)) +#define _READ_VDEC2_ST_REG(r) (codec_dosbus_read(\ + (VDEC2_VLD_MEM_VIFIFO_START_PTR+(r)))) +#define _WRITE_VDEC2_ST_REG(r, val) codec_dosbus_write(\ + (VDEC2_VLD_MEM_VIFIFO_START_PTR+r), val) +#define MEM_BUFCTRL_MANUAL (1<<1) +#define MEM_BUFCTRL_INIT (1<<0) +#define MEM_LEVEL_CNT_BIT 18 +#define MEM_FIFO_CNT_BIT 16 +#define MEM_FILL_ON_LEVEL (1<<10) +#define MEM_CTRL_EMPTY_EN (1<<2) +#define MEM_CTRL_FILL_EN (1<<1) +#define MEM_CTRL_INIT (1<<0) +#endif /* STREAMBUF_REG_H */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c new file mode 100644 index 000000000000..deeaf190f182 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c @@ -0,0 +1,606 @@ +/* + * drivers/amlogic/media/stream_input/parser/thread_rw.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #include */ +#include + +#include "../../stream_input/parser/streambuf.h" +#include "../../stream_input/amports/amports_priv.h" +#include "thread_rw.h" + +#define BUF_NAME "fetchbuf" + +#define DEFAULT_BLOCK_SIZE (64*1024) + +struct threadrw_buf { + void *vbuffer; + dma_addr_t dma_handle; + int write_off; + int data_size; + int buffer_size; + int from_cma; +}; + +#define MAX_MM_BUFFER_NUM 16 +struct threadrw_write_task { + struct file *file; + struct delayed_work write_work; + DECLARE_KFIFO_PTR(datafifo, void *); + DECLARE_KFIFO_PTR(freefifo, void *); + int bufs_num; + int max_bufs; + int errors; + spinlock_t lock; + struct mutex mutex; + struct stream_buf_s *sbuf; + int buffered_data_size; + int passed_data_len; + int buffer_size; + int def_block_size; + int data_offset; + int writework_on; + unsigned long codec_mm_buffer[MAX_MM_BUFFER_NUM]; + int manual_write; + int failed_onmore; + wait_queue_head_t wq; + ssize_t (*write)(struct file *, + struct stream_buf_s *, + const char __user *, + size_t, int); + struct threadrw_buf buf[1]; + /*don't add any after buf[] define */ +}; + +static int free_task_buffers(struct threadrw_write_task *task); + +static struct workqueue_struct *threadrw_wq_get(void) +{ + static struct workqueue_struct *threadrw_wq; + + if (!threadrw_wq) + threadrw_wq = create_singlethread_workqueue("threadrw"); + return threadrw_wq; +} + +static int threadrw_schedule_delayed_work( + struct threadrw_write_task *task, + unsigned long delay) +{ + bool ret; + + if (threadrw_wq_get()) { + ret = queue_delayed_work(threadrw_wq_get(), + &task->write_work, delay); + } else + ret = schedule_delayed_work(&task->write_work, delay); + if (!ret) { + cancel_delayed_work(&task->write_work); + if (threadrw_wq_get()) + ret = queue_delayed_work(threadrw_wq_get(), + &task->write_work, 0); + else + ret = schedule_delayed_work(&task->write_work, 0); + } + return 0; +} + +static ssize_t threadrw_write_onece( + struct threadrw_write_task *task, + struct file *file, + struct stream_buf_s *stbuf, + const char __user *buf, size_t count) +{ + struct threadrw_buf *rwbuf = NULL; + int ret = 0; + int to_write; + + if (!kfifo_get(&task->freefifo, (void *)&rwbuf)) { + if (task->errors) + return task->errors; + return -EAGAIN; + } + + to_write = min_t(u32, rwbuf->buffer_size, count); + if (copy_from_user(rwbuf->vbuffer, buf, to_write)) { + kfifo_put(&task->freefifo, (const void *)buf); + ret = -EFAULT; + goto err; + } + rwbuf->data_size = to_write; + rwbuf->write_off = 0; + kfifo_put(&task->datafifo, (const void *)rwbuf); + threadrw_schedule_delayed_work(task, 0); + return to_write; +err: + return ret; +} + +static ssize_t threadrw_write_in( + struct threadrw_write_task *task, + struct stream_buf_s *stbuf, + const char __user *buf, size_t count) +{ + int ret = 0; + int off = 0; + int left = count; + int wait_num = 0; + unsigned long flags; + + while (left > 0) { + ret = threadrw_write_onece(task, + task->file, + stbuf, buf + off, left); + if (ret >= left) { + off = count; + left = 0; + } else if (ret > 0) { + off += ret; + left -= ret; + + } else if (ret < 0) { + if (off > 0) { + break; /*have write ok some data. */ + } else if (ret == -EAGAIN) { + if (!(task->file->f_flags & O_NONBLOCK) && + (++wait_num < 10)) { + wait_event_interruptible_timeout( + task->wq, + !kfifo_is_empty( + &task->freefifo), + HZ / 100); + continue; /* write again. */ + } + ret = -EAGAIN; + break; + } + break; /*to end */ + } + } + + /*end: */ + spin_lock_irqsave(&task->lock, flags); + if (off > 0) { + task->buffered_data_size += off; + task->data_offset += off; + } + spin_unlock_irqrestore(&task->lock, flags); + if (off > 0) + return off; + else + return ret; +} + +static int do_write_work_in(struct threadrw_write_task *task) +{ + struct threadrw_buf *rwbuf = NULL; + int ret; + int need_re_write = 0; + int write_len = 0; + unsigned long flags; + + if (kfifo_is_empty(&task->datafifo)) + return 0; + if (!kfifo_peek(&task->datafifo, (void *)&rwbuf)) + return 0; + if (!task->manual_write && + rwbuf->from_cma && + !rwbuf->write_off) + codec_mm_dma_flush(rwbuf->vbuffer, + rwbuf->buffer_size, + DMA_TO_DEVICE); + if (task->manual_write) { + ret = task->write(task->file, task->sbuf, + (const char __user *)rwbuf->vbuffer + rwbuf->write_off, + rwbuf->data_size, + 2); /* noblock,virtual addr */ + } else { + ret = task->write(task->file, task->sbuf, + (const char __user *)rwbuf->dma_handle + rwbuf->write_off, + rwbuf->data_size, + 3); /* noblock,phy addr */ + } + if (ret == -EAGAIN) { + need_re_write = 0; + /*do later retry. */ + } else if (ret >= rwbuf->data_size) { + write_len += rwbuf->data_size; + if (kfifo_get(&task->datafifo, (void *)&rwbuf)) { + rwbuf->data_size = 0; + kfifo_put(&task->freefifo, (const void *)rwbuf); + /*wakeup write thread. */ + wake_up_interruptible(&task->wq); + } else + pr_err("write ok,but kfifo_get data failed.!!!\n"); + need_re_write = 1; + } else if (ret > 0) { + rwbuf->data_size -= ret; /* half data write */ + rwbuf->write_off += ret; + write_len += ret; + need_re_write = 1; + } else { /*ret <=0 */ + pr_err("get errors ret=%d size=%d\n", ret, + rwbuf->data_size); + task->errors = ret; + } + if (write_len > 0) { + spin_lock_irqsave(&task->lock, flags); + task->passed_data_len += write_len; + task->buffered_data_size -= write_len; + spin_unlock_irqrestore(&task->lock, flags); + } + return need_re_write; + +} + +static void do_write_work(struct work_struct *work) +{ + struct threadrw_write_task *task = container_of(work, + struct threadrw_write_task, + write_work.work); + int need_retry = 1; + task->writework_on = 1; + while (need_retry) { + mutex_lock(&task->mutex); + need_retry = do_write_work_in(task); + mutex_unlock(&task->mutex); + } + threadrw_schedule_delayed_work(task, HZ / 10); + task->writework_on = 0; +} + +static int alloc_task_buffers_inlock(struct threadrw_write_task *task, + int new_bubffers, + int block_size) +{ + struct threadrw_buf *rwbuf; + int i; + int used_codec_mm = task->manual_write ? 0 : 1; + int new_num = new_bubffers; + int mm_slot = -1; + int start_idx = task->bufs_num; + int total_mm = 0; + unsigned long addr; + + if (codec_mm_get_total_size() < 80 || + codec_mm_get_free_size() < 40) + used_codec_mm = 0; + if (task->bufs_num + new_num > task->max_bufs) + new_num = task->max_bufs - task->bufs_num; + for (i = 0; i < MAX_MM_BUFFER_NUM; i++) { + if (task->codec_mm_buffer[i] == 0) { + mm_slot = i; + break; + } + } + if (mm_slot < 0) + used_codec_mm = 0; + if (block_size <= 0) + block_size = DEFAULT_BLOCK_SIZE; + + if (used_codec_mm && (block_size * new_num) >= 128 * 1024) { + total_mm = ALIGN(block_size * new_num, (1 << 17)); + addr = + codec_mm_alloc_for_dma(BUF_NAME, + total_mm / PAGE_SIZE, 0, + CODEC_MM_FLAGS_DMA_CPU); + if (addr != 0) { + task->codec_mm_buffer[mm_slot] = addr; + task->buffer_size += total_mm; + } else { + used_codec_mm = 0; + } + } + for (i = 0; i < new_num; i++) { + int bufidx = start_idx + i; + rwbuf = &task->buf[bufidx]; + rwbuf->buffer_size = block_size; + if (used_codec_mm) { + unsigned long start_addr = + task->codec_mm_buffer[mm_slot]; + if (i == new_num - 1) + rwbuf->buffer_size = total_mm - + block_size * i; + rwbuf->dma_handle = (dma_addr_t) start_addr + + block_size * i; + rwbuf->vbuffer = codec_mm_phys_to_virt( + rwbuf->dma_handle); + rwbuf->from_cma = 1; + + } else { + rwbuf->vbuffer = dma_alloc_coherent( + amports_get_dma_device(), + rwbuf->buffer_size, + &rwbuf->dma_handle, GFP_KERNEL); + if (!rwbuf->vbuffer) { + rwbuf->buffer_size = 0; + rwbuf->dma_handle = 0; + task->bufs_num = bufidx; + break; + } + rwbuf->from_cma = 0; + task->buffer_size += rwbuf->buffer_size; + } + + kfifo_put(&task->freefifo, (const void *)rwbuf); + task->bufs_num = bufidx + 1; + } + if (start_idx > 0 ||/*have buffers before*/ + task->bufs_num >= 3 || + task->bufs_num == new_num) { + if (!task->def_block_size) + task->def_block_size = task->buf[0].buffer_size; + return 0; /*must >=3 for swap buffers. */ + } + if (task->bufs_num > 0) + free_task_buffers(task); + return -1; +} + +static int free_task_buffers(struct threadrw_write_task *task) +{ + int i; + for (i = 0; i < MAX_MM_BUFFER_NUM; i++) { + if (task->codec_mm_buffer[i]) + codec_mm_free_for_dma(BUF_NAME, + task->codec_mm_buffer[i]); + } + for (i = 0; i < task->bufs_num; i++) { + if (task->buf[i].vbuffer && task->buf[i].from_cma == 0) + dma_free_coherent(amports_get_dma_device(), + task->buf[i].buffer_size, + task->buf[i].vbuffer, + task->buf[i].dma_handle); + } + return 0; +} + +static struct threadrw_write_task *threadrw_alloc_in(int num, + int block_size, + ssize_t (*write)(struct file *, + struct stream_buf_s *, + const char __user *, size_t, int), + int flags) +{ + int max_bufs = num; + int task_buffer_size; + struct threadrw_write_task *task; + int ret; + + if (!(flags & 1)) /*not audio*/ + max_bufs = 300; /*can great for video bufs.*/ + task_buffer_size = sizeof(struct threadrw_write_task) + + sizeof(struct threadrw_buf) * max_bufs; + task = vmalloc(task_buffer_size); + + if (!task) + return NULL; + memset(task, 0, task_buffer_size); + + spin_lock_init(&task->lock); + mutex_init(&task->mutex); + INIT_DELAYED_WORK(&task->write_work, do_write_work); + init_waitqueue_head(&task->wq); + ret = kfifo_alloc(&task->datafifo, max_bufs, GFP_KERNEL); + if (ret) + goto err1; + ret = kfifo_alloc(&task->freefifo, max_bufs, GFP_KERNEL); + if (ret) + goto err2; + task->write = write; + task->file = NULL; + task->buffer_size = 0; + task->manual_write = flags & 1; + task->max_bufs = max_bufs; + mutex_lock(&task->mutex); + ret = alloc_task_buffers_inlock(task, num, block_size); + mutex_unlock(&task->mutex); + if (ret < 0) + goto err3; + threadrw_wq_get(); /*start thread. */ + return task; + +err3: + kfifo_free(&task->freefifo); +err2: + kfifo_free(&task->datafifo); +err1: + vfree(task); + pr_err("alloc threadrw failed num:%d,block:%d\n", num, block_size); + return NULL; +} + +/* +*fifo data size; +*/ + +int threadrw_buffer_level(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + + if (task) + return task->buffered_data_size; + return 0; +} + +int threadrw_buffer_size(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + + if (task) + return task->buffer_size; + return 0; +} + +int threadrw_datafifo_len(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + + if (task) + return kfifo_len(&task->datafifo); + return 0; +} + +int threadrw_freefifo_len(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + + if (task) + return kfifo_len(&task->freefifo); + return 0; +} +int threadrw_support_more_buffers(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + if (!task) + return 0; + if (task->failed_onmore) + return 0; + return task->max_bufs - task->bufs_num; +} + +/* +*data len out fifo; +*/ +int threadrw_passed_len(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + + if (task) + return task->passed_data_len; + return 0; + +} +/* +*all data writed.; +*/ +int threadrw_dataoffset(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + int offset = 0; + + if (task) + return task->data_offset; + return offset; + +} + +ssize_t threadrw_write(struct file *file, struct stream_buf_s *stbuf, + const char __user *buf, size_t count) +{ + struct threadrw_write_task *task = stbuf->write_thread; + ssize_t size; + if (!task->file) { + task->file = file; + task->sbuf = stbuf; + } + mutex_lock(&task->mutex); + size = threadrw_write_in(task, stbuf, buf, count); + mutex_unlock(&task->mutex); + return size; +} + +int threadrw_flush_buffers(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + int max_retry = 20; + + if (!task) + return 0; + while (!kfifo_is_empty(&task->datafifo) && max_retry-- > 0) { + threadrw_schedule_delayed_work(task, 0); + msleep(20); + } + if (!kfifo_is_empty(&task->datafifo)) + return -1;/*data not flushed*/ + return 0; +} +int threadrw_alloc_more_buffer_size( + struct stream_buf_s *stbuf, + int size) +{ + struct threadrw_write_task *task = stbuf->write_thread; + int block_size; + int new_num; + int ret = -1; + int old_num; + + if (!task) + return -1; + mutex_lock(&task->mutex); + block_size = task->def_block_size; + if (block_size == 0) + block_size = 32 * 1024; + new_num = size / block_size; + old_num = task->bufs_num; + if (new_num == 0) + new_num = 1; + else if (new_num > task->max_bufs - task->bufs_num) + new_num = task->max_bufs - task->bufs_num; + if (new_num != 0) + ret = alloc_task_buffers_inlock(task, new_num, + block_size); + mutex_unlock(&task->mutex); + pr_info("threadrw add more buffer from %d -> %d for size %d\n", + old_num, task->bufs_num, + size); + if (ret < 0 || old_num == task->bufs_num) + task->failed_onmore = 1; + return ret; +} + +void *threadrw_alloc(int num, + int block_size, + ssize_t (*write)(struct file *, + struct stream_buf_s *, + const char __user *, + size_t, int), + int flags) +{ + return threadrw_alloc_in(num, block_size, write, flags); +} + +void threadrw_release(struct stream_buf_s *stbuf) +{ + struct threadrw_write_task *task = stbuf->write_thread; + + if (task) { + wake_up_interruptible(&task->wq); + cancel_delayed_work_sync(&task->write_work); + mutex_lock(&task->mutex); + free_task_buffers(task); + mutex_unlock(&task->mutex); + kfifo_free(&task->freefifo); + kfifo_free(&task->datafifo); + vfree(task); + } + stbuf->write_thread = NULL; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h new file mode 100644 index 000000000000..f03a6e6549eb --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h @@ -0,0 +1,52 @@ +/* + * drivers/amlogic/media/stream_input/parser/thread_rw.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef THREAD_RW_H +#define THREAD_RW_H +#include "../../stream_input/parser/streambuf_reg.h" +#include "../../stream_input/parser/streambuf.h" +#include "../../stream_input/parser/esparser.h" +#include "../../stream_input/amports/amports_priv.h" + +ssize_t threadrw_write(struct file *file, + struct stream_buf_s *stbuf, + const char __user *buf, + size_t count); + +void *threadrw_alloc(int num, + int block_size, + ssize_t (*write)(struct file *, + struct stream_buf_s *, + const char __user *, + size_t, int), + int flags);/*flags &1: manual mode*/ + +void threadrw_release(struct stream_buf_s *stbuf); + +int threadrw_buffer_level(struct stream_buf_s *stbuf); +int threadrw_buffer_size(struct stream_buf_s *stbuf); +int threadrw_datafifo_len(struct stream_buf_s *stbuf); +int threadrw_freefifo_len(struct stream_buf_s *stbuf); +int threadrw_passed_len(struct stream_buf_s *stbuf); +int threadrw_flush_buffers(struct stream_buf_s *stbuf); +int threadrw_dataoffset(struct stream_buf_s *stbuf); +int threadrw_alloc_more_buffer_size( + struct stream_buf_s *stbuf, + int size); +int threadrw_support_more_buffers(struct stream_buf_s *stbuf); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c new file mode 100644 index 000000000000..ba9a59034bdb --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c @@ -0,0 +1,1131 @@ +/* + * drivers/amlogic/media/stream_input/parser/tsdemux.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +/* #include */ +#include +/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +/* #include */ +/* #endif */ + +#include "../../frame_provider/decoder/utils/vdec.h" +#include +#include "streambuf_reg.h" +#include "streambuf.h" +#include + +#include "tsdemux.h" +#include +#include "../amports/amports_priv.h" + + +static const char tsdemux_fetch_id[] = "tsdemux-fetch-id"; +static const char tsdemux_irq_id[] = "tsdemux-irq-id"; + +static u32 curr_pcr_num = 0xffff; +static u32 curr_vid_id = 0xffff; +static u32 curr_aud_id = 0xffff; +static u32 curr_sub_id = 0xffff; +static u32 curr_pcr_id = 0xffff; + +static DECLARE_WAIT_QUEUE_HEAD(wq); +static u32 fetch_done; +static u32 discontinued_counter; +static u32 first_pcr; +static u8 pcrscr_valid; + +static int demux_skipbyte; + +static struct tsdemux_ops *demux_ops; +static DEFINE_SPINLOCK(demux_ops_lock); + +static int enable_demux_driver(void) +{ +#ifdef ENABLE_DEMUX_DRIVER + return demux_ops ? 1 : 0; +#else + return 0; +#endif +} + +void tsdemux_set_ops(struct tsdemux_ops *ops) +{ + unsigned long flags; + + spin_lock_irqsave(&demux_ops_lock, flags); + demux_ops = ops; + spin_unlock_irqrestore(&demux_ops_lock, flags); +} +EXPORT_SYMBOL(tsdemux_set_ops); + +int tsdemux_set_reset_flag_ext(void) +{ + int r = 0; + + if (demux_ops && demux_ops->set_reset_flag) + r = demux_ops->set_reset_flag(); + + return r; +} + +int tsdemux_set_reset_flag(void) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&demux_ops_lock, flags); + r = tsdemux_set_reset_flag_ext(); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_reset(void) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->reset) { + tsdemux_set_reset_flag_ext(); + r = demux_ops->reset(); + } + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_request_irq(irq_handler_t handler, void *data) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->request_irq) + r = demux_ops->request_irq(handler, data); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_free_irq(void) +{ + unsigned long flags; + int r; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->free_irq) + r = demux_ops->free_irq(); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_set_vid(int vpid) +{ + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->set_vid) + r = demux_ops->set_vid(vpid); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_set_aid(int apid) +{ + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->set_aid) + r = demux_ops->set_aid(apid); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_set_sid(int spid) +{ + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->set_sid) + r = demux_ops->set_sid(spid); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_set_pcrid(int pcrpid) +{ + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->set_pcrid) + r = demux_ops->set_pcrid(pcrpid); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_set_skip_byte(int skipbyte) +{ + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->set_skipbyte) + r = demux_ops->set_skipbyte(skipbyte); + spin_unlock_irqrestore(&demux_ops_lock, flags); + + return r; +} + +static int tsdemux_config(void) +{ + return 0; +} + +/*TODO irq*/ +static irqreturn_t tsdemux_isr(int irq, void *dev_id) +{ + u32 int_status = 0; + int id = (long)dev_id; + + if (!enable_demux_driver()) { + int_status = READ_MPEG_REG(STB_INT_STATUS); + } else { + if (id == 0) + int_status = READ_MPEG_REG(STB_INT_STATUS); + else if (id == 1) + int_status = READ_MPEG_REG(STB_INT_STATUS_2); + else if (id == 2) + int_status = READ_MPEG_REG(STB_INT_STATUS_3); + } + + if (int_status & (1 << NEW_PDTS_READY)) { + if (!enable_demux_driver()) { + u32 pdts_status = READ_MPEG_REG(STB_PTS_DTS_STATUS); + + if (pdts_status & (1 << VIDEO_PTS_READY)) + pts_checkin_wrptr(PTS_TYPE_VIDEO, + READ_MPEG_REG(VIDEO_PDTS_WR_PTR), + READ_MPEG_REG(VIDEO_PTS_DEMUX)); + + if (pdts_status & (1 << AUDIO_PTS_READY)) + pts_checkin_wrptr(PTS_TYPE_AUDIO, + READ_MPEG_REG(AUDIO_PDTS_WR_PTR), + READ_MPEG_REG(AUDIO_PTS_DEMUX)); + + WRITE_MPEG_REG(STB_PTS_DTS_STATUS, pdts_status); + } else { +#define DMX_READ_REG(i, r)\ + ((i) ? ((i == 1) ? READ_MPEG_REG(r##_2) : \ + READ_MPEG_REG(r##_3)) : READ_MPEG_REG(r)) + + u32 pdts_status = DMX_READ_REG(id, STB_PTS_DTS_STATUS); + + if (pdts_status & (1 << VIDEO_PTS_READY)) + pts_checkin_wrptr(PTS_TYPE_VIDEO, + DMX_READ_REG(id, VIDEO_PDTS_WR_PTR), + DMX_READ_REG(id, VIDEO_PTS_DEMUX)); + + if (pdts_status & (1 << AUDIO_PTS_READY)) + pts_checkin_wrptr(PTS_TYPE_AUDIO, + DMX_READ_REG(id, AUDIO_PDTS_WR_PTR), + DMX_READ_REG(id, AUDIO_PTS_DEMUX)); + + if (id == 1) + WRITE_MPEG_REG(STB_PTS_DTS_STATUS_2, + pdts_status); + else if (id == 2) + WRITE_MPEG_REG(STB_PTS_DTS_STATUS_3, + pdts_status); + else + WRITE_MPEG_REG(STB_PTS_DTS_STATUS, + pdts_status); + } + } + if (int_status & (1 << DIS_CONTINUITY_PACKET)) { + discontinued_counter++; + /* pr_info("discontinued counter=%d\n",discontinued_counter); */ + } + if (int_status & (1 << SUB_PES_READY)) { + /* TODO: put data to somewhere */ + /* pr_info("subtitle pes ready\n"); */ + wakeup_sub_poll(); + } + + if (!enable_demux_driver()) + WRITE_MPEG_REG(STB_INT_STATUS, int_status); + + return IRQ_HANDLED; +} + +static irqreturn_t parser_isr(int irq, void *dev_id) +{ + u32 int_status = READ_MPEG_REG(PARSER_INT_STATUS); + + WRITE_MPEG_REG(PARSER_INT_STATUS, int_status); + + if (int_status & PARSER_INTSTAT_FETCH_CMD) { + fetch_done = 1; + + wake_up_interruptible(&wq); + } + + return IRQ_HANDLED; +} + +static ssize_t _tsdemux_write(const char __user *buf, size_t count, + int isphybuf) +{ + size_t r = count; + const char __user *p = buf; + u32 len; + int ret; + dma_addr_t dma_addr = 0; + + if (r > 0) { + if (isphybuf) + len = count; + else { + len = min_t(size_t, r, FETCHBUF_SIZE); + if (copy_from_user(fetchbuf, p, len)) + return -EFAULT; + + dma_addr = + dma_map_single(amports_get_dma_device(), + fetchbuf, + FETCHBUF_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(amports_get_dma_device(), + dma_addr)) + return -EFAULT; + + + } + + fetch_done = 0; + + wmb(); /* Ensure fetchbuf contents visible */ + + if (isphybuf) { + u32 buf_32 = (unsigned long)buf & 0xffffffff; + + WRITE_MPEG_REG(PARSER_FETCH_ADDR, buf_32); + } else { + WRITE_MPEG_REG(PARSER_FETCH_ADDR, dma_addr); + dma_unmap_single(amports_get_dma_device(), dma_addr, + FETCHBUF_SIZE, DMA_TO_DEVICE); + } + + WRITE_MPEG_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len); + + + ret = + wait_event_interruptible_timeout(wq, fetch_done != 0, + HZ / 2); + if (ret == 0) { + WRITE_MPEG_REG(PARSER_FETCH_CMD, 0); + pr_info("write timeout, retry\n"); + return -EAGAIN; + } else if (ret < 0) + return -ERESTARTSYS; + + p += len; + r -= len; + } + + return count - r; +} + +static int reset_pcr_regs(void) +{ + u32 pcr_num; + + if (curr_pcr_id >= 0x1FFF) + return 0; + + /* set parameter to fetch pcr */ + pcr_num = 0; + if (curr_pcr_id == curr_vid_id) + pcr_num = 0; + else if (curr_pcr_id == curr_aud_id) + pcr_num = 1; + else if (curr_pcr_id == curr_sub_id) + pcr_num = 2; + else + pcr_num = 3; + + if (pcr_num != curr_pcr_num) { + u32 clk_unit = 0; + u32 clk_81 = 0; + struct clk *clk; + + clk = clk_get_sys("clk81", "clk81"); + if (IS_ERR(clk) || clk == 0) { + pr_info("[%s:%d] error clock\n", __func__, + __LINE__); + return 0; + } + + clk_81 = clk_get_rate(clk); + clk_unit = clk_81 / 80000; + + pr_info("[%s:%d] clk_81 = %x clk_unit =%x\n", __func__, + __LINE__, clk_81, clk_unit); + + if (READ_MPEG_REG(TS_HIU_CTL_2) & 0x80) { + WRITE_MPEG_REG(PCR90K_CTL_2, (12 << 1) | clk_unit); + WRITE_MPEG_REG(ASSIGN_PID_NUMBER_2, pcr_num); + pr_info("[tsdemux_init] To use device 2,pcr_num=%d\n", + pcr_num); + } else if (READ_MPEG_REG(TS_HIU_CTL_3) & 0x80) { + WRITE_MPEG_REG(PCR90K_CTL_3, (12 << 1) | clk_unit); + WRITE_MPEG_REG(ASSIGN_PID_NUMBER_3, pcr_num); + pr_info("[tsdemux_init] To use device 3,pcr_num=%d\n", + pcr_num); + } else { + WRITE_MPEG_REG(PCR90K_CTL, (12 << 1) | clk_unit); + WRITE_MPEG_REG(ASSIGN_PID_NUMBER, pcr_num); + pr_info("[tsdemux_init] To use device 1,pcr_num=%d\n", + pcr_num); + } + + curr_pcr_num = pcr_num; + } + + return 1; +} + +s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc, + struct vdec_s *vdec) +{ + s32 r; + u32 parser_sub_start_ptr; + u32 parser_sub_end_ptr; + u32 parser_sub_rp; + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + /*TODO clk */ + /* + *switch_mod_gate_by_type(MOD_DEMUX, 1); + */ + /* #endif */ + + amports_switch_gate("demux", 1); + + parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); + parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); + parser_sub_rp = READ_MPEG_REG(PARSER_SUB_RP); + + WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER); + + if (enable_demux_driver()) { + tsdemux_reset(); + } else { + WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER | RESET_DEMUXSTB); + + WRITE_MPEG_REG(STB_TOP_CONFIG, 0); + WRITE_MPEG_REG(DEMUX_CONTROL, 0); + } + + /* set PID filter */ + pr_info + ("tsdemux video_pid = 0x%x, audio_pid = 0x%x,", + vid, aid); + pr_info + ("sub_pid = 0x%x, pcrid = 0x%x\n", + sid, pcrid); + + if (!enable_demux_driver()) { + WRITE_MPEG_REG(FM_WR_DATA, + (((vid < 0x1fff) + ? (vid & 0x1fff) | (VIDEO_PACKET << 13) + : 0xffff) << 16) + | ((aid < 0x1fff) + ? (aid & 0x1fff) | (AUDIO_PACKET << 13) + : 0xffff)); + WRITE_MPEG_REG(FM_WR_ADDR, 0x8000); + while (READ_MPEG_REG(FM_WR_ADDR) & 0x8000) + ; + + WRITE_MPEG_REG(FM_WR_DATA, + (((sid < 0x1fff) + ? (sid & 0x1fff) | (SUB_PACKET << 13) + : 0xffff) << 16) + | 0xffff); + WRITE_MPEG_REG(FM_WR_ADDR, 0x8001); + while (READ_MPEG_REG(FM_WR_ADDR) & 0x8000) + ; + + WRITE_MPEG_REG(MAX_FM_COMP_ADDR, 1); + + WRITE_MPEG_REG(STB_INT_MASK, 0); + WRITE_MPEG_REG(STB_INT_STATUS, 0xffff); + + /* TS data path */ + WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0x7000); + WRITE_MPEG_REG(DEMUX_MEM_REQ_EN, + (1 << VIDEO_PACKET) | + (1 << AUDIO_PACKET) | (1 << SUB_PACKET)); + WRITE_MPEG_REG(DEMUX_ENDIAN, + (7 << OTHER_ENDIAN) | + (7 << BYPASS_ENDIAN) | (0 << SECTION_ENDIAN)); + WRITE_MPEG_REG(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE); + WRITE_MPEG_REG(TS_FILE_CONFIG, + (demux_skipbyte << 16) | + (6 << DES_OUT_DLY) | + (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | + (1 << TS_HIU_ENABLE) | (4 << FEC_FILE_CLK_DIV)); + + /* enable TS demux */ + WRITE_MPEG_REG(DEMUX_CONTROL, + (1 << STB_DEMUX_ENABLE) | + (1 << KEEP_DUPLICATE_PACKAGE)); + } + + if (fetchbuf == 0) { + pr_info("%s: no fetchbuf\n", __func__); + return -ENOMEM; + } + + /* hook stream buffer with PARSER */ + if (has_hevc_vdec() && is_hevc) { + WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, vdec->input.start + + vdec->input.size - 8); + + if (vdec_single(vdec)) { + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, + ES_VID_MAN_RD_PTR); + /* set vififo_vbuf_rp_sel=>hevc */ + WRITE_VREG(DOS_GEN_CTRL0, 3 << 1); + /* set use_parser_vbuf_wp */ + SET_VREG_MASK(HEVC_STREAM_CONTROL, + (1 << 3) | (0 << 4)); + /* set stream_fetch_enable */ + SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); + /* set stream_buffer_hole with 256 bytes */ + SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, + (1 << 29)); + } else { + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + WRITE_MPEG_REG(PARSER_VIDEO_WP, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_RP, vdec->input.start); + } + } else + /* #endif */ + { + WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, vdec->input.start + + vdec->input.size - 8); + + if (vdec_single(vdec)) { + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, + ES_VID_MAN_RD_PTR); + + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, + MEM_BUFCTRL_INIT); + /* set vififo_vbuf_rp_sel=>vdec */ + if (has_hevc_vdec()) + WRITE_VREG(DOS_GEN_CTRL0, 0); + } else { + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + WRITE_MPEG_REG(PARSER_VIDEO_WP, vdec->input.start); + WRITE_MPEG_REG(PARSER_VIDEO_RP, vdec->input.start); + } + } + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_MPEG_REG(PARSER_CONFIG, + (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) | + (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) | + (16 << PS_CFG_MAX_FETCH_CYCLE_BIT)); + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); + WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_rp); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (has_hevc_vdec()) + r = pts_start((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO); + else + /* #endif */ + r = pts_start(PTS_TYPE_VIDEO); + + if (r < 0) { + pr_info("Video pts start failed.(%d)\n", r); + goto err1; + } + r = pts_start(PTS_TYPE_AUDIO); + if (r < 0) { + pr_info("Audio pts start failed.(%d)\n", r); + goto err2; + } + /*TODO irq */ + + r = vdec_request_irq(PARSER_IRQ, parser_isr, + "tsdemux-fetch", (void *)tsdemux_fetch_id); + + if (r) + goto err3; + + WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff); + WRITE_MPEG_REG(PARSER_INT_ENABLE, + PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT); + + WRITE_MPEG_REG(PARSER_VIDEO_HOLE, 0x400); + WRITE_MPEG_REG(PARSER_AUDIO_HOLE, 0x400); + + discontinued_counter = 0; + + if (!enable_demux_driver()) { + /*TODO irq */ + + r = vdec_request_irq(DEMUX_IRQ, tsdemux_isr, + "tsdemux-irq", (void *)tsdemux_irq_id); + + WRITE_MPEG_REG(STB_INT_MASK, (1 << SUB_PES_READY) + | (1 << NEW_PDTS_READY) + | (1 << DIS_CONTINUITY_PACKET)); + if (r) + goto err4; + } else { + tsdemux_config(); + tsdemux_request_irq(tsdemux_isr, (void *)tsdemux_irq_id); + if (vid < 0x1FFF) { + curr_vid_id = vid; + tsdemux_set_vid(vid); + } + if (aid < 0x1FFF) { + curr_aud_id = aid; + tsdemux_set_aid(aid); + } + if (sid < 0x1FFF) { + curr_sub_id = sid; + tsdemux_set_sid(sid); + } + + curr_pcr_id = pcrid; + if ((pcrid < 0x1FFF) && (pcrid != vid) && (pcrid != aid) + && (pcrid != sid)) + tsdemux_set_pcrid(pcrid); + } + + pcrscr_valid = reset_pcr_regs(); + first_pcr = 0; + + return 0; + +err4: + /*TODO irq */ + + if (!enable_demux_driver()) + vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id); + +err3: + pts_stop(PTS_TYPE_AUDIO); +err2: + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + if (has_hevc_vdec()) + pts_stop((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO); + else + /* #endif */ + pts_stop(PTS_TYPE_VIDEO); +err1: + pr_info("TS Demux init failed.\n"); + return -ENOENT; +} + +void tsdemux_release(void) +{ + pcrscr_valid = 0; + first_pcr = 0; + + WRITE_MPEG_REG(PARSER_INT_ENABLE, 0); + WRITE_MPEG_REG(PARSER_VIDEO_HOLE, 0); + WRITE_MPEG_REG(PARSER_AUDIO_HOLE, 0); + +#ifdef CONFIG_MULTI_DEC + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR); + WRITE_MPEG_REG(PARSER_VIDEO_WP, 0); + WRITE_MPEG_REG(PARSER_VIDEO_RP, 0); +#endif + + /*TODO irq */ + + vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id); + + if (!enable_demux_driver()) { + WRITE_MPEG_REG(STB_INT_MASK, 0); + /*TODO irq */ + + vdec_free_irq(DEMUX_IRQ, (void *)tsdemux_irq_id); + } else { + + tsdemux_set_aid(0xffff); + tsdemux_set_vid(0xffff); + tsdemux_set_sid(0xffff); + tsdemux_set_pcrid(0xffff); + tsdemux_free_irq(); + + curr_vid_id = 0xffff; + curr_aud_id = 0xffff; + curr_sub_id = 0xffff; + curr_pcr_id = 0xffff; + curr_pcr_num = 0xffff; + } + + pts_stop(PTS_TYPE_VIDEO); + pts_stop(PTS_TYPE_AUDIO); + + WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER); + + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ + /*TODO clk */ + /* + *switch_mod_gate_by_type(MOD_DEMUX, 0); + */ + /* #endif */ + amports_switch_gate("demux", 0); + +} + +static int limited_delay_check(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count) +{ + int write_size; + + if (vbuf->max_buffer_delay_ms > 0 && abuf->max_buffer_delay_ms > 0 && + stbuf_level(vbuf) > 1024 && stbuf_level(abuf) > 256) { + int vdelay = + calculation_stream_delayed_ms(PTS_TYPE_VIDEO, + NULL, NULL); + int adelay = + calculation_stream_delayed_ms(PTS_TYPE_AUDIO, + NULL, NULL); + /*max wait 100ms,if timeout,try again top level. */ + int maxretry = 10; + /*too big delay,do wait now. */ + /*if noblock mode,don't do wait. */ + if (!(file->f_flags & O_NONBLOCK)) { + while (vdelay > vbuf->max_buffer_delay_ms + && adelay > abuf->max_buffer_delay_ms + && maxretry-- > 0) { + msleep(20); + vdelay = + calculation_stream_delayed_ms + (PTS_TYPE_VIDEO, NULL, NULL); + adelay = + calculation_stream_delayed_ms + (PTS_TYPE_AUDIO, NULL, NULL); + } + } + if (vdelay > vbuf->max_buffer_delay_ms + && adelay > abuf->max_buffer_delay_ms) + return 0; + } + write_size = min(stbuf_space(vbuf), stbuf_space(abuf)); + write_size = min_t(int, count, write_size); + return write_size; +} + +ssize_t drm_tswrite(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count) +{ + s32 r; + u32 realcount = count; + u32 re_count = count; + u32 havewritebytes = 0; + + struct drm_info tmpmm; + struct drm_info *drm = &tmpmm; + u32 res = 0; + int isphybuf = 0; + unsigned long realbuf; + + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + size_t wait_size, write_size; + + if (buf == NULL || count == 0) + return -EINVAL; + + res = copy_from_user(drm, buf, sizeof(struct drm_info)); + if (res) { + pr_info("drm kmalloc failed res[%d]\n", res); + return -EFAULT; + } + + if (drm->drm_flag == TYPE_DRMINFO && drm->drm_level == DRM_LEVEL1) { + /* buf only has drminfo not have esdata; */ + realcount = drm->drm_pktsize; + realbuf = drm->drm_phy; + isphybuf = 1; + } else + realbuf = (unsigned long)buf; + /* pr_info("drm->drm_flag = 0x%x,realcount = %d , buf = 0x%x ",*/ + /*drm->drm_flag,realcount, buf); */ + + count = realcount; + + while (count > 0) { + if ((stbuf_space(vbuf) < count) || + (stbuf_space(abuf) < count)) { + if (file->f_flags & O_NONBLOCK) { + int v_stbuf_space = stbuf_space(vbuf); + int a_stbuf_space = stbuf_space(abuf); + + write_size = min(v_stbuf_space, a_stbuf_space); + /*have 188 bytes,write now., */ + if (write_size <= 188) + return -EAGAIN; + } else { + wait_size = + min(stbuf_canusesize(vbuf) / 8, + stbuf_canusesize(abuf) / 4); + if ((port->flag & PORT_FLAG_VID) + && (stbuf_space(vbuf) < wait_size)) { + r = stbuf_wait_space(vbuf, wait_size); + + if (r < 0) { + pr_info + ("write no space--- "); + pr_info + ("no space,%d--%d,r-%d\n", + stbuf_space(vbuf), + stbuf_space(abuf), r); + return r; + } + } + + if ((port->flag & PORT_FLAG_AID) + && (stbuf_space(abuf) < wait_size)) { + r = stbuf_wait_space(abuf, wait_size); + + if (r < 0) { + pr_info + ("write no stbuf_wait_space--"); + pr_info + ("no space,%d--%d,r-%d\n", + stbuf_space(vbuf), + stbuf_space(abuf), r); + return r; + } + } + } + } + + write_size = min(stbuf_space(vbuf), stbuf_space(abuf)); + write_size = min(count, write_size); + /* pr_info("write_size = %d,count = %d,\n",*/ + /*write_size, count); */ + if (write_size > 0) + r = _tsdemux_write((const char __user *)realbuf, + write_size, isphybuf); + else + return -EAGAIN; + + havewritebytes += r; + + /* pr_info("havewritebytes = %d, r = %d,\n",*/ + /*havewritebytes, r); */ + if (havewritebytes == realcount) + break; /* write ok; */ + else if (havewritebytes > realcount) + pr_info(" error ! write too much\n"); + + count -= r; + } + return re_count; +} + +ssize_t tsdemux_write(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count) +{ + s32 r; + struct port_priv_s *priv = (struct port_priv_s *)file->private_data; + struct stream_port_s *port = priv->port; + size_t wait_size, write_size; + + if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) { + if (file->f_flags & O_NONBLOCK) { + write_size = min(stbuf_space(vbuf), stbuf_space(abuf)); + if (write_size <= 188) /*have 188 bytes,write now., */ + return -EAGAIN; + } else { + wait_size = + min(stbuf_canusesize(vbuf) / 8, + stbuf_canusesize(abuf) / 4); + if ((port->flag & PORT_FLAG_VID) + && (stbuf_space(vbuf) < wait_size)) { + r = stbuf_wait_space(vbuf, wait_size); + + if (r < 0) { + /* pr_info("write no space--- "); + pr_info("no space,%d--%d,r-%d\n", + stbuf_space(vbuf), + stbuf_space(abuf),r); */ + return r; + } + } + + if ((port->flag & PORT_FLAG_AID) + && (stbuf_space(abuf) < wait_size)) { + r = stbuf_wait_space(abuf, wait_size); + + if (r < 0) { + /* pr_info("write no stbuf_wait_space")' + pr_info{"--- no space,%d--%d,r-%d\n", + stbuf_space(vbuf), + stbuf_space(abuf),r); */ + return r; + } + } + } + } + vbuf->last_write_jiffies64 = jiffies_64; + abuf->last_write_jiffies64 = jiffies_64; + write_size = limited_delay_check(file, vbuf, abuf, buf, count); + if (write_size > 0) + return _tsdemux_write(buf, write_size, 0); + else + return -EAGAIN; +} + +static ssize_t show_discontinue_counter(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", discontinued_counter); +} + +static struct class_attribute tsdemux_class_attrs[] = { + __ATTR(discontinue_counter, S_IRUGO, show_discontinue_counter, NULL), + __ATTR_NULL +}; + +static struct class tsdemux_class = { + .name = "tsdemux", + .class_attrs = tsdemux_class_attrs, + }; + +int tsdemux_class_register(void) +{ + int r = class_register(&tsdemux_class); + + if (r < 0) + pr_info("register tsdemux class error!\n"); + discontinued_counter = 0; + return r; +} + +void tsdemux_class_unregister(void) +{ + class_unregister(&tsdemux_class); +} + +void tsdemux_change_avid(unsigned int vid, unsigned int aid) +{ + if (!enable_demux_driver()) { + WRITE_MPEG_REG(FM_WR_DATA, + (((vid & 0x1fff) | (VIDEO_PACKET << 13)) << 16) + | ((aid & 0x1fff) | (AUDIO_PACKET << 13))); + WRITE_MPEG_REG(FM_WR_ADDR, 0x8000); + while (READ_MPEG_REG(FM_WR_ADDR) & 0x8000) + ; + } else { + curr_vid_id = vid; + curr_aud_id = aid; + + tsdemux_set_vid(vid); + tsdemux_set_aid(aid); + + reset_pcr_regs(); + } + +} + +void tsdemux_change_sid(unsigned int sid) +{ + if (!enable_demux_driver()) { + WRITE_MPEG_REG(FM_WR_DATA, + (((sid & 0x1fff) | (SUB_PACKET << 13)) << 16) + | 0xffff); + WRITE_MPEG_REG(FM_WR_ADDR, 0x8001); + while (READ_MPEG_REG(FM_WR_ADDR) & 0x8000) + ; + } else { + curr_sub_id = sid; + + tsdemux_set_sid(sid); + + reset_pcr_regs(); + } + +} + +void tsdemux_audio_reset(void) +{ + ulong flags; + + DEFINE_SPINLOCK(lock); + + spin_lock_irqsave(&lock, flags); + + WRITE_MPEG_REG(PARSER_AUDIO_WP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_RP, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + + WRITE_MPEG_REG(PARSER_AUDIO_START_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR)); + WRITE_MPEG_REG(PARSER_AUDIO_END_PTR, + READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)); + CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR); + + WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT); + + spin_unlock_irqrestore(&lock, flags); + +} + +void tsdemux_sub_reset(void) +{ + ulong flags; + DEFINE_SPINLOCK(lock); + u32 parser_sub_start_ptr; + u32 parser_sub_end_ptr; + + spin_lock_irqsave(&lock, flags); + + parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR); + parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR); + + WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr); + WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_start_ptr); + WRITE_MPEG_REG(PARSER_SUB_WP, parser_sub_start_ptr); + SET_MPEG_REG_MASK(PARSER_ES_CONTROL, + (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR); + + spin_unlock_irqrestore(&lock, flags); + +} + +void tsdemux_set_skipbyte(int skipbyte) +{ + if (!enable_demux_driver()) + demux_skipbyte = skipbyte; + else + tsdemux_set_skip_byte(skipbyte); + +} + +void tsdemux_set_demux(int dev) +{ + if (enable_demux_driver()) { + unsigned long flags; + int r = 0; + + spin_lock_irqsave(&demux_ops_lock, flags); + if (demux_ops && demux_ops->set_demux) + r = demux_ops->set_demux(dev); + spin_unlock_irqrestore(&demux_ops_lock, flags); + } +} + +u32 tsdemux_pcrscr_get(void) +{ + u32 pcr = 0; + + if (pcrscr_valid == 0) + return 0; + + if (READ_MPEG_REG(TS_HIU_CTL_2) & 0x80) + pcr = READ_MPEG_REG(PCR_DEMUX_2); + else if (READ_MPEG_REG(TS_HIU_CTL_3) & 0x80) + pcr = READ_MPEG_REG(PCR_DEMUX_3); + else + pcr = READ_MPEG_REG(PCR_DEMUX); + if (first_pcr == 0) + first_pcr = pcr; + return pcr; +} + +u32 tsdemux_first_pcrscr_get(void) +{ + if (pcrscr_valid == 0) + return 0; + + if (first_pcr == 0) { + u32 pcr; + + if (READ_MPEG_REG(TS_HIU_CTL_2) & 0x80) + pcr = READ_MPEG_REG(PCR_DEMUX_2); + else if (READ_MPEG_REG(TS_HIU_CTL_3) & 0x80) + pcr = READ_MPEG_REG(PCR_DEMUX_3); + else + pcr = READ_MPEG_REG(PCR_DEMUX); + first_pcr = pcr; + /* pr_info("set first_pcr = 0x%x\n", pcr); */ + } + + return first_pcr; +} + +u8 tsdemux_pcrscr_valid(void) +{ + return pcrscr_valid; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.h b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.h new file mode 100644 index 000000000000..5e11c44c5f91 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.h @@ -0,0 +1,95 @@ +/* + * drivers/amlogic/media/stream_input/parser/tsdemux.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * +*/ + +#ifndef TSDEMUX_H +#define TSDEMUX_H +#include + +/* TODO: move to register headers */ +#define NEW_PDTS_READY 4 +#define AUDIO_PTS_READY 2 +#define VIDEO_PTS_READY 0 +#define DIS_CONTINUITY_PACKET 6 +#define SUB_PES_READY 7 + +#define PARSER_INTSTAT_FETCH_CMD (1<<7) + +#define FETCH_ENDIAN 27 +#define FETCH_ENDIAN_MASK (0x7<<27) + +#define RESET_DEMUXSTB (1<<1) +#define RESET_PARSER (1<<8) + +#define VIDEO_PACKET 0 +#define AUDIO_PACKET 1 +#define SUB_PACKET 2 + +#define OTHER_ENDIAN 6 +#define BYPASS_ENDIAN 3 +#define SECTION_ENDIAN 0 + +#define USE_HI_BSF_INTERFACE 7 +#define DES_OUT_DLY 8 +#define TRANSPORT_SCRAMBLING_CONTROL_ODD 6 +#define TS_HIU_ENABLE 5 +#define FEC_FILE_CLK_DIV 0 +#define STB_DEMUX_ENABLE 4 +#define KEEP_DUPLICATE_PACKAGE 6 + +#define ES_VID_MAN_RD_PTR (1<<0) +#define ES_AUD_MAN_RD_PTR (1<<4) + +#define PS_CFG_PFIFO_EMPTY_CNT_BIT 16 +#define PS_CFG_MAX_ES_WR_CYCLE_BIT 12 +#define PS_CFG_MAX_FETCH_CYCLE_BIT 0 + +#define ES_SUB_WR_ENDIAN_BIT 9 +#define ES_SUB_MAN_RD_PTR (1<<8) +#define PARSER_INTSTAT_FETCH_CMD (1<<7) + +#define PARSER_INT_HOST_EN_BIT 8 + +struct stream_buf_s; +struct vdec_s; + +extern s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc, + struct vdec_s *vdec); + +extern void tsdemux_release(void); +extern ssize_t drm_tswrite(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count); + +extern ssize_t tsdemux_write(struct file *file, + struct stream_buf_s *vbuf, + struct stream_buf_s *abuf, + const char __user *buf, size_t count); + +extern u32 tsdemux_pcrscr_get(void); +extern u8 tsdemux_pcrscr_valid(void); +extern u32 tsdemux_first_pcrscr_get(void); + +int tsdemux_class_register(void); +void tsdemux_class_unregister(void); +void tsdemux_change_avid(unsigned int vid, unsigned int aid); +void tsdemux_change_sid(unsigned int sid); +void tsdemux_audio_reset(void); +void tsdemux_sub_reset(void); +void tsdemux_set_skipbyte(int skipbyte); +void tsdemux_set_demux(int dev); +#endif /* TSDEMUX_H */ diff --git a/firmware/video/video_ucode.bin b/firmware/video/video_ucode.bin new file mode 100644 index 0000000000000000000000000000000000000000..e495e377b7a425ee8a575fca689c722b36a1d21c GIT binary patch literal 420352 zcmeFa37B2Qb>Ls`_Ivl>mIMfd=x%L*Y%CPK;f3l(@ZM{+R={@RO%h-m2eaBU zvd6KiTiE@&1ro^Elg#`lk;FC=f{pQHK4+5o`$}N<>u#|cGKrIk!3$1;;{`HFCX1Qh zse7;Vx+Nj(kc{KJ_kH)(y|tV==Tz0HQ|noCVgCkom9Ktl{s*s6{|bNa-*)wTKd|a` z=e_qsAG!L&SDmxh%}?&h8I?;Y56xP3MXD z@^4n2v+|sCFF)^%=e_<7$D;L`E!S+j>Y8(|pUv+)?xi2OvZw#L8+ul~w&&b8o`2qX z=dXNi&#IN@zCI5>3iNeKee!iLz9SEBxi60c1vTs|W&MIu?M9hEg+sn-v)ZK&%l?AL zYQFu5DxcS=5$|RE!foZ|SoX);XM8t@x%YW_{DgQ$CG)qH0|gE${WkZ_4A1?OdsF}9 zo|)mNL5ugbn(zJIwUNNz@iiT)2L<>2?z;eeg}GK2pv|ZQoym(qyTtQUIkaE@vTt6U z1gh9Ze51UHnm^K|ir$2Fw5M?Iac~ZPd|x#1=6%t@o;xD@58KOL#(+;eNFAOa_-Im6=aL8|ay@}c+m&bbIga%};0khb<}8<_8JFKcKT`;TAt z#g+6?Wyqg;u_rc#lz%OGNKM%iq5CJsh=BD;QD z`Be2KSGE?UB;M4EU-rW{-x}2WOq6UO?#R<|0&kL`G!Ol74Y;bPAJ)DNRJr2~L%yaw zVm;(XMe9fE0-n?rc+EdedBwU+c-@cAD*H((&C|s%m;FJL_)&Y=FBHn*VDTnDI;ZS+ zyrJx?lhb%?rk^{rNq@#t9d zp75Ty_h19{ibvo@yNQ?VjUs!kgA=`F$RFQtOH=j-j(^dvnjh`8dNQ#7*w*WGvE8EJUetB*i|$iiw6V?Co7((%Lz`dTaG_s*!Ip+HIOR+Deo*N$`J}ud-F?Ozyqk3W zq@ykC0n)1d{&XSnV*?D+3?p&nq* zx{`b=NNN4+%=OD*GMsdVXIMYjIvh>XUM7<*QC+_G_ebHWHVBas$--^r!Fkr#2d+%R z25cHeT+_3yTm`@I)FcpCmNxC&1>4FIY1A84Ie4%2O}{F)6VINP)+2lJw(>aPdD_Vf ztX~;0t_(%qjZ^o7zDQSll3?OT!^Hr%GJHo=F?U3x2R27G-d0}wr4fIE_axc|>=8dW zxH(e1-*WAUUm4jPnP6MloV2ZMiyw7#hpUJDu)9lF?dK!Ck@j^l?abgeFyuEzj2Dim zVn`jWda9$joheUs8n4i)N3PT1ep9NCC{N@;l{A|4;!1fDR!sg+%G*Yq1fe%v3d>0# zG$!rviTB2vY|!Wpb%pj;!9VD$Qiky9sh}LG#BaPQLHMRJB%oY_)yS5`Lw?0byGhDH zPudRzq?wolzPOd7Cz_aJOO5MOJOuaAB{m3>v`qx13;m$*8pm7dM=DA7e*Ta@u|?_1 zS3j49?e&AVARq2Y%P9Gc)Gb8F*E2=NS`}q7SY)W+BeF9%6+ElYI2aN~MmZEj(RcGZhb}nwiExs4(rFjnD$l|>$rhuf>8P*`rPUb z!%j|zhid+qr-I481JUGwDK)73A@aC3po(J>pSU5iIaGW75cwP;pTp;ALz#RIkfk7H;^E;9I{B->$p)$K6LUfx*t9;X;t^g+ozCOizdUyQq-|z=;f2s8 z{YrJKb>*vmn6}R&IvD)qcg(ooKX%+U>Pws58!7a`ced8ZD!_~y!}4PHfRw;xp!>fW$lBmVS?y?%0An$HgOuJOIfYcmq>^JzS5563gR zXT|GY=RerBNM8uA+t3$0>URWgQF2A((J#6Bje8K;+J>IszNyOt)MYQz3kJ{&JoJJY z?WJR#KhQ_p>F97}CHy(K!Ui7wxmTdgl-m5$4sLexNW!GeOPMNksD;SbRp?O*Pwvvs zU(g#bRM$qw(x=SZaveBLHxF9o&0nN1RX>QII?D$0{;=lH`-;++e&^BXc4XP@>aOVa zVR-&(`j;i!%JY}oU_Sht4=ry$(*|#!|8YIPyThOVY8zaJJd}R)6m_fr2Nx&)DYq27 zd3@ha|7w6S|T` z+se12H#`Nr--nN%DXET==9`kxb~12p2XA>yNp;S@tlztR8MJ=Jl!Ts3Ukkp_HXoW& zeC~+m58Mep`@!K(-+1u7|4#oYdu8+_=}s!I^FLcE=-V&bmDL4<6?{9ZF%_EN|B`^HvE6Scab}9H9+P>gCum7I- zGI%@RqI>-1_VQEUco}J)BF(%5lp}FPze|eS%9o+@Nx99taMUShl?{n8|5rT-K9Th)v)OLjFl>s@92RZ+M-eoYju4z^{ypq&SAo6Yjmj(Q4NQ<-+1}==>g& zeu?q9XMzdpvy83nnq!A2)Mp77o{oFP;wWiyoJ1#=uw+isS%Jni!uJ7i>kswx7fjpq zh$)GjkI^ITMJaq$N!#lL_?gwIUqYDRGkx0z9T3;SGtKb24#N{z%1>b$lcn!J0#jX( z`dPx7VcNH3`4cYwF8?=Y=?QC&I}S~Q58Moo(z+${4;5&eDD;;mZ=)VE4>5s$T|uWA z<*A@skMdN|tpn=+1b(VN)79V1JVC-(tjzcj7*nt2+wOH^v*1y9WqYH5I00oS;lk4d z8CSUxo%Ia-SJ@~*j!Iat#0HE*ou6ggCVrJ3{LaB|4|rL|OT@4Ck%qY+Q_9j2rz&v> zQ^;7CZg@*H3amyB4|(SNdubo^F9?lb;ulO*!41x{k<2eixbS3(xvr3UA3o36E!SCt znlEjneiQA9Hr-$>5|3P?qwY^=!JGP8oH*AOgT71kpv)0fX_qw~U^ezxJ-WaKl}$!Z zY_uhb8}xl#=W*<0T0Wu6BOwpkB6;NHBYdm^XM%QEMVHL|>%f$D8HBy5UYnJteJF*O z{9fv=LkHN^wk29eyLa{Ve&#WsPs5}xj9+M7dx^+nn(sBA-W^9fb~8|3Pqx9^4#_^N#E-34bd4Z9H+) z23@(qc=acC$1?s1sFRLQ)J36J>ZjBp(U-?4AL%nDUPUEwN9TE^x#GZ&miM&3f+mCJ1;I0!!l2dV$k)~kKgeAJA z{R8l|#3A2Ge>N}ijkNqm@vpeFS4N|_6X07%o`%%l(Hp7LA0~~|Y2Z$L822Oix%m5| z0Q@JwPtY)5PvIqhl=4L4P85bq5`Q=F9uqjE6WJ5=4MdfXfG=<-aC7(-;*JV@p5Wi` zem-I5t`z>08T_YG_!3v(yZFb#=kYB56B#~Pe1W^3JRjpxzn0czM;rClAX|hMnIHNZ z@?b80pFW2NJijKmGVYajF7YeqjuSk=G9KE!liBFd6`>E^Z9@Dd4&$rL$ic@8FRS>jK;CY2q6OK`eH-t3K%M?T?XNo4`B)Lu8QHi4W8kRK8+ zxi6zd+Vi1Ll%=l=z}=NOuFFT}JSnpZ6*gWD(e#t!>w6HId@~rbnc%3oL*fL=AJqmpymjfvqb$O(LKZ*V%a(bLT zEueoIz0T?ho`C)-*jV!?ZsZ-kacVJmBHJf>SL@1I;JD)oSFa_`WWUiG_>;ZcTwH-u z`EUjU-F5We3d}?Y=&yqJXtFo@4;x1Oug@D{E|m7jTBdKf>nPe`? z`l)P9Bm5fr@b6vjcw8aP1a(4XI@Bm-*Fd*HSBRzjMYhWvpZepJZ)y2t?eNp7pOmF~ zAT3M5Cqzbuv{g4B`Oy>)(TPT-Y?+&`NZmTv7fatFbBZB62tSo*(OE{pCCqf~le4uF z^TrhaoA;Q~;C|&zF&>aLkMdkqEWa>Z9HRc7Xw5^`M=75AY^Pg2&vDWu;@)cZPD({3fZh>w4 zkDa$YJq?$!nB?8tHsts5Eaq9lvvm28e~IafD)4s{TKv}Vfj_~V zfYaG&^RBNm*G5zDrviSX-bO9*b(HnEXc6mABG-i0pd5zqHiUBHZ!L$x1=PPeZ`FbMeB{;>2UcpCTM5ng zBblekW$&@dOWc2ewuO@9b3x2M%j;1_9D~A z^0GgZdVri4ngVE&F?-M*>4|<%H|A{8YZgdf!Z?{Yri=01z}=DLGm2Z;aaUAL&@FHS z`kN%%_few%@OeC*PM$WND)p)XPGjJq&fZq8ot*?bDT6pkb+9_$_RQ3OcDg!i7oz9O zz6u$$%bpQQ-#xlFy2Sh-o`&YeGRl*=#v1E=)d3p|&I$8gGWM1}OVY>madB_iKSca8 zzi>I)+E(xu$sJ`w;^u_UJY%^&&4jBYTv9nbwgjquFf{jfQ<8N7~vrZ7gpSu8q-N zB~D&XX0#b($+6nZ>~=c4t;}vCIj(}It7DYivFep&PDex6qxppRf4f8otzokAi{*R>|H{hfC@4r$G-<%)|(bb@* zxz0@#k|O1(W&Bb>mkP|$`jgJ&h3HW=DT}uEN0%haqI?W7PTmo1V;nja>wA;bPni#$ zT$b={)Ht|^e3$hI#eALUTr#gNbLtUwcTD6H^)gLoipkcXENKm8X-jRP=x%jj&(_;S zpJNQ*^mD1J_L87n!B5(N=xmZ!`T)^UMTZa3QLD_C2rd=IGwKVh4X=Wwe6*zackhuAn)Sry*G3FGWVNJ zVT&`rZ#DTX$^5>Z`BiE6^$#b}6mIwE9nlndN8p_>FS+yi0WE70LXY?jLd)dETcTUw zbvrt@%#TE@El1#9zsZYbel;3>Uo;4f5;wMcnS`cd)=7Qai&xI?}V^)1vf<3N!^G5&F~C30ad@B7J{d6n~IuI+wb z_A`jiGP+}PWGQEn1#X2Ve4*eJZ2i6TE4NeMCJv81Ib- z@t1v8T-nmDGwS^{*9tuDB6QupZANY)4) z&$Du6-pI}WqSurpY-*0tZXD|MM;czsc&m~ujV621gU&(*gG=|sU0J6bFkMEW4P&%vIAe*yJAc;xC>>b%T>R;c$f=U{LX0do6P)rn*4OQMJMn76~}`KXp?zZH^ygNEPU~p z>i!{*Vb7LYf{xNhAHHd&9_>3{S2p$NiN3S-bRYAE`xCEnNf+Oz>gj>>d-M{;cciDc zX5TV*Z~)yTgEO_t7N;4HOFrYz+hXOCmBc^4DSZY%OD}8NE-vXR;Naqtw~X5*f2n)n zNPj8(BJ=uRWWJSm&AaA(?T-FZJMZnh@8Z3K_YU5LzG-CjwAWucgnQ^<;+033FA?1A z6>iv9o zmnS&K4-=KU*SmaR$#+t{e${Id3u#CTU;VwZIk~KDfctRr|hZ3O#-b zJw8N_ua8)7)SII<`@#nIB+(#qo-)3vGyf=M)?knD;40(xKs4}+Xb+#rH7prfWw$_-0dDzp%}_exWL^E-QA(TfeyB zU|j4e>H`v|XCNweb?I{nU#Z$Wd0s`lm3)ICb2VG^_3u)}U*`SZHz}tB{qpY)czVC* zo&73P>R<<7R5n2ZtTc^rX;iPm~;-r4wz9<1PHIs2CWQFu1B>6V!O z(VM(3K}V+Su17C0={{c{_>xBWBy!(Al3bG;3uZrJ4Rqv}PmC)A0#BD((Sw5)Y= z*)ngI(=P7pvXyexS-CoV_N4pSYCmE5<#`uZFNvD-H%1Gm zI9hJFg*u;nd`dxkC z$ol^A;H-aMc_Ke@I2Jg`EI9S!z^Q@LZqf@bBA0R)vvCoc2Ag2)Vw|U#>niVMZp1(v zG>u=lBN`;$?&m%4`>_hnL60k=mb@%-e{UN_|ViVjOtKtWFL?*cXaZ*3c6^tX6M9ujIz^f#E(Y2?U;??B! zs;0bL7-JlPc?~ds3wYnh6>0e=TxP<8su{b-cOLvSIKA4 zJ`-PTzUk_R;_S{E(ir-Zi`f$-Wtsf%pd3rR2iL)-e58FxMHMvT|9Qcm@=WnBYCGN^ z<=^63@-u}ky0o}Is(y?8RyU?~ef^EJ%R8*o4I*e1n6v4wKA6%iGz;xfQTPGv-Vxeg zv)B5E`}(H`+CD_trRA5-Cw=ZTQ~Hp5RPny)0q-wZ6OeO5XY+_W5qYH0RgB_{A@i!1 z@zY`dE@b=t1Kx_$`r{RCs(A13dY)zMBkwcgc-}AXv{{@1Pk1SDK1d!nXL%U*55Zbx z(V^G6Jn7Hn`-aqCeKre6Z?XM%yK=CfOZ^PxYi`KoE$?du_uo##M0T#jPw{mAP@=@8ogXE4h zUh?ayYwpQh;0f-Q$CZms%O!a-C<_ioT=JDX3&g#S=YG3CR?PXC9_!}NC44tLOW@@& zk8Lx-0UpoLCnBq-n7L@VUBek~5PIMCw2{}T?(G0fXsa;smV|Jt|& zIaWB(S>Y_A{?6veT>lBz54f;-s%S@&&Zs>J%$4c>wTaQ5SY6A0p`t2|ZrY#+1qSi- zuiX`^%hNccb5-f#H#66}c!PeJH5|Jo^;elIdjQScq;uWe0lhX$-){Fs9rP0ui~}mn zO`CtOm~*#&^6oTkWdI#Ci)-JN`DNdA;su*_xP4&3H%C&PLH4!h@qaPP|DEaHyWC&) z>*ep}?P;9k9mkKOE=%JCmNnKM)}?N+?4jNpsrRtIEz4_^wGVCSM>b{fF3I3|>A2eE z$$RwUpj~w8BpWlE^=bTxest9g7RNN)p4JL5(|wa0bj|}al!Zy(zb1Vj*l(}QR`-CG z_W)f;(#!cs$!p?*t?9SaTfSXb^SkUfrN0*X1&)K2>`T8l0wdQeNh2^_xFP)YDbDtF zsVn|Dd^Q|Ml`ugEK2Dy;^A{MTle+Elp`MS)2D9hd+|70ZKf1M(3{9se7?rm+>HA-nI_!#owHr(ooOty2$CMu*WZ0Z6db^S@t`! zw=X}l`B>8)X8TvAa%}ecR_@YRnaTv2L#t3;rgvNUarEfhc(0&;3;!qH$R0^#NHzOr z4pj%|CxM*ZZ`ef3S$+M7jPKBA86kvgvv?Bz@ElJE-50w!?Uc3fO4@#neJ&i*JS-E` z<*7_)4hv``58rl;4mhtAaHi=I&f5l@TdHO7Cwssvd$07S>#V_^;Z#-(3`cp`D7fbD z!5faeSDM~Oo8Bjy-bbNbQMdE-qvUfqf8hh+lXJRsMR=6q!e$80D)G%&L*wT0$9T_q z^DyUxWZy<0@MK;aIpEe>Wv|U9?T-zZQvKiuxch*0l;-x%d4Ac;RfVSZZrLX?;P$OP zJf{es+*yHA$UfM{oYgvDZ|f+$mhXTwM>&2uK9vzqg|2_|0La`=0c?>uax>AhkXM-|#Z9#(nlk$6GV`$W_GXw!S;Lg+f! z)8lq%Bpte<^d{bwvLD zWg5rHnIETXfa-@oDEU$Lz zg_BWdq;1SRo8_H_kG|=M+^8Iu8|fMD$8KYdavyVShB>Naub(_na5Oa1Il7@W26J*Rj_F@^%;En zKBzwmT~6=XC3ky~RPd!R>JQ2IBt(TdFXJA+&^xZ4e^wq|SxVcsL*0@>g(^l`K-aop-l!lNQQ#*|AMBbN^ zKX-e*9De6oH@7Q!$lXVRYcmaz$2rzJn71KaL_aZE*mq2Ns?e$j5-0QX{>jnBnWbaX z#XfiBwE9xXwWZ_HVP@089A{2PC-{`@bB>ltcqU~abR-!aW$KE|`M5h!9_opb-$~nv z=pz#^el9w6fc07W#(*&OrI}%WzR&Z@33EgLE%m>-e_wRy@vTK0ZYU2S_hoNn1=y8^ zv=s%60qUlM^>lnT`heu&{JqToCS*3W*e|5;?A>X3u2?+eKNk&`p8MO~#au_2$aMsR z9`Iq&5m=iw>}z2>5j<}rbKkF&?f#?FJNaeyMbDjz9(R4x`P|3Q8BRtHW%}^250nZCIMd>$pRmpez>TEu-A0DG~JvXR|hCMP;E@83P%|9CNKxgRnySdHK zvz^IjvbrtvJ@75LJ^ePB+b;Y>z9t)!PATK$N5WfpFMHQ`D$rPYGy9`>)|_n9bAspF zp!`M~$bCR{)&kGOwl16;yB?!oH)C0!-F!F*_Nkn<_> zo_{|`+P4Cq$Av#cxV&fI6Q@EGj|=-Mdq&7VXy;q>uW8O|!-F8v{vbH60mq%}YmJGs z^M>nm{FR!&^9Ji=$DHh}gzT*f6VA4Lnf;o`>Ctl&VD;z<{AdiXbU34*;7XmQ&w&1b zIlSON&7ar?pX6-UNBQP{oeHjekK#I7N6@2?wG-$+vNx$QY}x{F89P_XK)G^f{<|o8 znw*_+`>%MH@|3#q^Y#mRC|90F@1UL#9xf5ym||7>RMyo)bjASL9oz^XUk#5ebDuJH zBaNIZG;d1J1qFS?M{f}Rm~8AnL0NM?fIVk~aprE6G^27Zi@q;7xFb^BizV@;%}75V zbYCOq3S9p#elms$IGbnQla5~;Ec#@V%>xL`+5P{7t83X9D#Is<*|V2WPY4@*Y-X5> zg7O&ivH|ptqBDiW2`?Sy{FTua)>y*Z_E;#J)nYDs`5+ zJ&MjX>gw;Ekrw*0v44f}XN9~?J_mrmq^%4LY4zF+9$~59YOT-ZoXV%tK1BRlzZM5t z9B6T%#eo(FS{!I`pv8d}2U;9xaiGP476)1!XmOy$ffff^9B6T%#eo(FS{!I`pv8d} z2U;9xap0em1BdNCp7+bEe)(wgm&)0Bl(6F33nO=J(4U+HTpuVb!qgHQQ@-v94Tx+^dBG$ zyKycaeqw9k0Irq$ZZkU~IsBvCGbEk-WPg!SZR$%izU?o3Y{qvUPpwM*?P)X9gM(k- z@xH`924#ZbAMTF(IV)-xvZsSbvDZ}1VXvJ$WzOU9BPut`-$7ny$Zv)DL$b8c+Iy~_WzLokAcU&y8*!i`(3&HGqGK1f6RR$ z*imc4CX_eDd4fNa{SrnMuv=K*j$Ol5NeWwroO|^X?rT%nFdPt`>$F@(cuz0{NRH~D z_-F45JBR9rwq)GhU&2d%;FLI=Zt{oUIm{hc0Y~Gp4+T#4A5uJu;E;SncxYUFH7qpT z>=(F`S!{J3Bz{riXLvu@G3@)KN$&+F4dDuY+4(8&6t3Yp%$LLa#!{T@chdbKMQleE z*-Kos*GA^ssb7gbmKSkHp`l!H|^vs-85w4NPKC-JFshrfyIU>x={N;TQMb9HKheeb4A7ofY}SigU> zrJn9CsxDJhD@}p75eAQ4RgQrZ^AES%*m(zi%aMf6}QLZ`S8>hUd$i zk=ttB8I}g$dJ}hA5#Ri8&Pz%<#`0AepRP(_j>$W)Co{J(hqEC4*k4oJ9U$`<4{%@a zfqhY92RMx|)*j;isUL1Ho6A$&3-IRWSjx#z%qNx8Gr4Y???Qj6TYv6r8{pO@hP$#|EHj*q0J!10|JB#-niC>ra zzm0I1PtJ*dL+pO4VikY;Uyk^jKS}-T5?}DemHRBT;KaA)E{iY*KJPVL z2ix2eF_3fo+#}~`?o8p;izcXXu5b_MZ|kI=j3}c$#vA8$k9tuB;?KKt>mwVu@6?pW zfqASj?mujsl6!QC6~ zo3fYhquxpDY(NMw-W{Du%5${|xY^wsQg;NV3wQH1O4-{}`c>|dUh)Vzb97Wb$IHLj zpY*P7;D+SU;4HHpR*udp_iofOT0`(_$h{le)3EiNN6y0^WgbRI$!TeD?}ofL=3cCK zXY@kbpp=2!n-ERcxSuldBF;%J z;NEN6W#hrUQSzl!rU-01lGQiPqONEDX?(8rr9C{h!^DYA!)`U##$8fxJQIiwc)2rA z>?wrvkOMq*o(9hbm##mSd5<#Z#AOa+2v=-!Nc!a8WqGxw=VHCAz0~Ed7}DOdSjNst z*?csOw^m&n%RO?pT5fm*M%ZT3JZ?0x`MaQev%vn_pnRw)4|Q)!o8CC&M;8zIb&(U? z)x8F{A@^DCx1|~PT1Yu?w}tTvof`Wn;eJ!96Hg<d?-Bl236pZD<0e;S@sZE=*V8!m z0~uTie}5LQ<%Dc-ya~rsFe@ciA zgNE6Xo?|3#l}GFoNZc?_iz~K_bJ@AB%Lb3&C+)+$F_oS6T`3Og-D%#Euh8jmEZZQg zZ;21r-9uU3J(ShmJ)GD3SXy`OEg3()nV#oXZ%^SiklD398$8ZDbB#M_LhcXPNd9)5 z`T}lM`Yy?p8q`8NnF6Ff&#m~W@PgQHPG{g(T%VP~~uKc-^GO=k~ncuIIr@@u8lgZ!mjVtYT zY>(0reQ*^XB-AZwzvgXO`L&a;#JQn6jYAu^TeCRTG>+E9;jH-_$`E@YL6tM!Li)z8 zVJ&tq8_54K+2U-uxH46lJe9gg`<8Sy(s2j2OLrUT21!@NFYGqhs0QX9>(w~dTcy3! z1*Y`-!_1}0?=30)0%x)*|HpyT5IEo$nk%EaxH+B+NT205XAXESNP;n;m2#A}CiqMO z&%8c`o#0AVRpPm}i7Rlcb~8Ajb94ebr|Z0|Jb)LTO8gGui3{9@q(9jP^#hdcF!fpJ z!0x)(;T8CXVVDlyC;jqm)crPDL-?ib0=I8`-^GqGxxY2TETdI(B~F zO5T?ksUi1rRYjI@_tiLVD%Yg_D>eeI#7kVx4|Zql4t% z(hqjn{V8qSyOYzVo;n^)?`opSIGS>NgvT}Ne;vJqKEaDh^cU3G>0qxvM*peF=cqV_ zb|7&#(+_qj?3wI6Oy5y)1s>~I)4}~O4<2>Zw+{@CSJ;&L4R?ON_ zZlf>eE|i^&$EOP5#hoXS2TliT{u;igvDLK`SM_HyRQk=r<&p3~>|qKI>g*M0@PzCa zNYLekkK*5;ErycTq<(SFk|-vhu;*Lx8q%XAN7KZM(T4_cBgULE=7{#Iwg$An(jy3wg$+}GN zK1bg_2|YFJ$dBP_o9ai>cZw`C|2@Uq=+s_4w_!NiO8X1NNs$>c)&Qrf(?RaUW}Vda zH10*ny-)TTbc6I;;V*pobF`)+y|ll=o94X;@J{Z&623Vd1U=~_(Lw%) zD$lXjUjV%!?i6X}ia%q>ZfK|qZOBl`M-OP<{Gasxii_k<6 zN0*5PFIOh$g`tE~MsI_Ein*LQb$E(j=nWLbe*xvtTux>(e08^ zXvV)z8P;hNn)1}#QB#F?Rqm*9<@v{X8B(6uxfgxqqJdfE`D4a*Ql8vVab2~*f$mT?DaKk*?KdRm}hOrCTnkGzL(yI zqL=aA{Z_5By&~EI>sEAAVCMN$4ey(|w+p$j7JcNF#q*r)oetWm;x2os198vNNRihe z8fq-2W%K;5y{p z;WW@F{zA9-uR~^Zn5~fu7g+3#d1QyuIjnWWb?Mb!zvC_FJmfP?yxq*nh<$-B_F>&d zeshvLqQ{XpT@NM2jRhO*;n`H&q91Ql9h=Cbn=-25& z3SQ@1hWtn8o&-H<|2yXmW&bwh+ngms`d0F>nf;_&;r(vL`<+(|N1gPQyOH@vK6+jzSc+tOo<_d33_c`_49*Ncd(&-`Y%=y*ip_u6A`_>aX+}Q`Cp47r)`p z1(%0;mpQ$M|7(AI3-f;Kz-8Ajn9?KPRG#23wj_p_&n+j3w(N<#8G45L=II)DK$Yiq z=`v*|@pdg%#SU?aU*@^FZHpeiqrup9GAAseb+T;i0&|+qiJq`ybfFr({p)> zUq^N?cE`7jH-7nghoj)P4j3DVzYZD|W2_CdY1b!Ta>VwB;3j=AbMBt#c7tM9E-Rzt z1&s4iPh1?rM5mT8>COJ%~%sbV$V&@s$)?~a=FUlGT{)7vk z>RZh*!jZKZA0^)L;z-{(PWU+b!SUkcyzkh&INJ5XXt9I(^%!$1oqwskN81X;&Lw5P z%>AQXml!SeK-#Rxo(|gTx?;h5skrODm9_zqJzafe|FOko{U~);`0yya?p!?RWXNu* zV|+`z$Ef$6#Fg*a{(`H7#VYMDWzKUgvO(_UZ3nOR&6a!8;l~puo_;8alIMeR2fUqL ztn{PIA50@>c0-q=2{_Y~kD*OUIZb2RdJW;XJgK~PXrAs zho6ZqLM|uBDdDHAC&(OO`XtWJW_RE%uxa020=CSZUZ$+yN&9;0lKwWm%3yb`-`h|s zFy{&H)RtJ_ZSV@7tZ`_G3r}aayRlq$08`rBP+M;_zA0;ems)qf-Q2A>wyR@?>XLxjK7U%C-m+7ZRJV( znYtl~r2G$kYqzrtHAK1ux}4ktuDFtq8<)BIsnmM-)>+(KRJvN;&AVG?yRpCR-_N(D z&!FQ!%Co+-MbACm2J;r!;K@r(JokSaZ}&$mYjNAkPhD2J`i<|RW4~*SBkBWN+F3;P*?K3=&@(8Z;$m90cQiJ#jevZZ^n~RCskkuun98Bt& z=nytrvzhqV$nak zfqU~qrcLyR!+q@Hw2z&k7iD^cr0tlM*69?BI~^ZIr;s%zp;zjx=)^gmqU**c)n#s- zt#8?<Vh5zLT zd!zQp2;+StaAuSTW1={qJ;HO5D~Fg}ik<$d)HGv#zJvHdqOyn*P=$={`SsF#`F zlW*(#K;*lhjibQxZ;=RFMQhhz|Dv2pMBlUJxvs~x^x*5+^NYYPj#ZDC#Zj$rSpioGX|y(ih5Qe)0wY*`Xq zjh|E#j6FMHm?Zc~yy-ntum z0VwStrIw{y~Ym5_I_k)TdZzZpt~#Zp_CJTEr;j2i#L z{0xIR`mBRG{#l27jws(JFMJL+{J@P}?eA`L`+cgcYllyKKc411dTj5DWIiS2e0X&g zQ^BizJ;>Nw=EBEEm`kzy;;95{*PKxgIinsj2Pw89mSlGyM9@)X?nTy$=P=%p{A7;I z{C2t~7{aUih46~?ow{XRy^8-Qww2}Gp3519YqNNh*_n$;?awFuQ_Q2y?@NNqcs|4P zl)RtJ+A?<@R2L_1k3qPEIRu^tPq;J*syy{&;KCTBL0MOY$K?*cekS3|(=-j<8|=NS z%J;j{GPtgnC0mJ0n0;rqSAlVw&@z3d?2|~>%2u#0cP}?DoULy4e-qcdJB@3$rmn_+ zlC>_Ob?jhLy7SkD{W^S+`mp43)_~dXSmS++rzZF@*HG;n(z?jLstms>IP8pAkLC&0 z<M&saef7ex3#{r*8Ju0f9p!x&Fr}<0%R9%0{UvL_TlNAlHyJW7qnN7-BkJu9 zNvAoBI)Pt(7<>c={2S~=tMjfnPa@wnDUV3%%|f=%TpPXfEE}8#j~0T*Lfq4FPsd$^ zy9oCi%$u^&Hga@OPIb<+M6}Iu=Do$0@$>v3oqvu_5H96sIY*+foc40^6J9vJL=j%Lb-Zn>DgLa8*Daw8fSO3hlZl6wg zHtDd()S$gJ*oPD^YV$+dk(3E5Nns7R8Xjs7o1O6UMDMa@*wa?_dwKeJ7V}I3W03VI zy}axfehQc;1LG8)1w5zn>;&GF>;(j#?9-L9i{QgJ`gdw4e=Pn>{NEsN;bCYmkA51Sy%at<4wC;A<(SHky-`Hnmvx0{$|a&4 zrzpoMaG1)p*5`kV{C-Q~_{3ok+?wHUMyw+hcdmMeiz9Q_ z-y_b{^GdHto{nVh`f9$b1HgxdI&O8xT~RIB7u9iPpI1T}XH)kfnA^gfoDno00C(Bd++3CjES1a;r627?oUrWQ6zBvG>}|xiQC9W*$}Ks-$NQ*Dv>${fCL)p6rjx+;8IM8EHqdpXA8*HBpM& zhg`oUxT!^Hp3*a0?b(maywi^|dBR07eiXA-z2kkRC!$5 z19H)#`?>I}o#+yJtHh@+kM(WP5%>x`spD1j9s1{3^c<Xb(Eyf=l8)u_;0#{&4 zpRu$ex~eMbKJ?)1TwEw|z)fULh^z@|C(@=1xt_;0qgy4bTt{<2on5$ua)zJB~*e^Dp2N!Dd|KA^lw)^^_O8Mj_> zT3fFk%HH3Zx$nx{g-v1a&iqbq@_SF_wzO?I(kPGGnXAhtLzCl^!xyO z(zisy1Myn}{Zkiji5`I;9TS^lnTKbN-(LgnwX+H_`?#YxxFXsKZ4$R^_sTrJAG5Fd z&)JvqF#ZqkN$H7Yk2Csc%)aL`d!5buQeEEZybscJ7t zEnDOOJj=qSkpE)?tbG$lY%xoD3=+p++gIMrd$TnJ#yAD`sVbA6Npa~pGogVmeQZd2 z#v(;=UlNB0>`WZ!7aR_otiwU@Q-8y`Dd2=}qRbEW=y0$%UW5M{bn!JkxYP&9qxwne zD0B>d(&$0x8>|)B`eXg2qgx}xTBhKi^Pe>Wx2HhHPZAc(xCz|rBmL1J{0)IqO_oOy z_*nWd!DH#fJz4p!h#JJ*`NXewkF1-Gqq|92%DcF4$DLxmRo>r` z`MLEqKlS^?CcnYV@0XhV#_=2fdOqGuz}2V*Z9mLpfjhshUK54v-IKGG4U4YBSR`bR zV6&glDEhJd*BN)pn9S+&Cf)bzA@(>j6w2DNT7vH0$9a=Y*y!v#U)MKLwu{f!<;A8X z`{C=CuupvPsk(e&`rWuh@y&MN%hPWM_rT>*n89IPtaym^e#v|Kd0VVsf=pR_epC7k zewJR=nqAyg#03WzH_JQ8*5qZasy5PJ(qH7P;umZFIPVef5%0Tp^p`q#@8JDW-aC2k zf{;3?{*z{=Af4$ISDm~duG`*~hcj|GSFj{efn!NgnBwxhWA!hUQ@C*IJF*5%WY z<+Hvi9}ZXqH$S*JT8fOia)B)gZDMov?ewds;L12^0gsHMzA?bf%@`LjsaX3N$NZYL<*F)}N3!k^8D(xn3A2a=w z3OSb&9;A-jR8Ku-{>l9=|E0*S&P_>Fhu3xBC&fqW^)%*x5Fie{*@BPj<=q|ra%BAb*}Hl#dzwySzUB8nSn!s?@6TR^OZ@i% zH(}hctYH231M438b2E2a`A?~j|5-g339O~TUC}c5cK21LbSCi5Jk^#yK>zuiR>kGO z{O-p*?@VAW$9?uH&%0Z%E-stf;hzOwnAk3!$-L2-=ws5RKU*pm@BYOU&P&4>a4_yJ z`Na>w-!sj=X!*hY{s+(tmnZxE z=(`I{aXEVVcPR^bx1HO{-(5!dQp#y*61)%hS=?u#sTuE-KF?cD*mrfWe!s*yCN1!9 z>%NqyoA>$4x9s!(6n>nk?wCo-2W|YH$?Htu{3)*epWDkH;Qj6es(82HD>yNaBK7Tk z&?I_>(6MazuK4}HTW&YAk8^wZ9{BTJ(%d6q%BQdXvtyC|>_^M`1Cb4u zeQYFNHn=6=OCADK;N|?z>r!4{q;1{vQFu>% zSq3f7)|6gO-CZ^Sf1!Dq+2=3o=dp=@QhNt_8hDkwqC5&YwhSKTumxsbmiH`4%ksOp zQkJvxImvE`p51a#OZsQwkNN)gv<&imMnC8Bk^PF2SA+~1?_Q(_k#iAeSYytvmRSR6 zr~Y5ocUu&bF3WBM{!VGgmCbk>$r^I~rD)32$~Zi}1RT1R*4*h@L;s(oKhnr48Jin; zFXQw)zVNN}YjL2(ffff^9B6UiXN?2NUvrQAk~aEA18S*`^^@T!b1Rbe1TH#Pz#Q`N z;srM_KW*O^O|hOZ#d<=>dP1GE_M_e$t@V&UxF?AQSJ_zBS?a9W${e$-uMVy$Teyw|@W|76iisZYJ`#djR>XuZ8G4scg- zb3F6T^!u>=%U8>smYr$;^0leo4EvX_&*BYlK4Sm!QvA5rpc(#A@8?T8`K9w;v+ZB1 z^Nwx*(&qLrUpF(o;*OEdH*kl1$fYpMd%3kNb%DD}C&o?lI`SWd-21~Fw6UuD@mXcx z_$mFdtecg~{u-0`aXb4<3gvK3@g_e$=SbX6?m08u)0#pP{FRdRt;n)3u)-P__hQOk zg*6A)yE(R$M!1>XgOab8jW?|Uj%RCtZP}WhTQ9?gp{$L??5~iuv6wwu)9l%r&h}r( z`d)lLYl-Z~nPR<8*7+jvcklNn?mPYx>xbM8E%(w19`Tom^9rqRu5rBT@OQG_94}{2 z3VRLK;KuA}h}qL1>(M(U4&kz%FT52Trul{&eu3xzslCz{!G}9@1_X~2*(-fS>a$V* z)b>gX?;iG#Yp?Vnsq^M1vsZc`OC!9W%Rb)u>}g@Ikis=QQXb9qIRCa&Y5SdFuXHl? zYuPJJ&%m|pmA34a_P6YnB0h2%l1h@+e~SYx4zxJX;y{Z7Ee`x_a-e1ZGC98e%P;;T z?O*;*YB#7c+Vk@5U;eku_E5;UEVG4~WOgv+9zJ;*go&NOF2-^V_QZ#??O*OnZMc~) zq_DyPmD<0|>|s_lXF5rr+t|wQ^)R1162DHI+#Y6wcgZ)5aC4iOv+ZAEL!rQZf(`s% z5&M^SWqc@_f1UO(Ka|b&gS?a`5_Ake?d_()v_AmcGb$t7mJF@!5*`@W&XN))7zZ_1(UNQTZAJ6hS zk^M_-lL)2V_%ER_Augc&8Bl$oUF7_^| z$5nCrsL$eNwlOWP)WrsV$(3n*lezLOVPPk7t1E-SyTGbvZUfiZLHozrzdS#coff;7 z!WZ?PG;hf_flh~G*#;-He~HahvHf_I{mXY`e3@mu2^UPk~UZ!u$+_UdyKOc zoQsw-H*zPfoXdWEIqhckOWVG*8?$`+xpM=XI@JUhIL)>%lUcSe^^=^(;7kYi07Pme zo3~$^!6EHY_As}napVqNIn$?btMo^5XLlX9We-!SmOac3`X%jQ{zj8M%wOd0fs1X+ z9wu#Rtf-FI`TTjXhxwLFo*c^_=9^}Qy`uIoUz@^CIGZTvo!vc1NqT0xWe<~c)SP3? z?O(R+VJ3ckk8$=o2RQ?2wEDTXhj}9Vm+Ca`%P`1f?&SMU zW;>YbA8QBmr0i}gh@20dTi&MLmW=Y_5+n2I~sd{JH!Bjozx5X8` z_>%)eI$4y#J0tf??O@ukA8iNIewh0l<-W@K=+nt7W6RP0|Hrn2X&Fn3J(AgWFq63% zO#@Y}4!_T`o4D|mv4ff1k@CFS4!!IV5j&VkoaNugy|V0;P)&9)72`1BD|?%`{L9X; zgJ~FFywY|s6XtN74N>z?V+S*N8Fnxga}rWcV$&e%vV(cp4(6?Cdv4jmwEyz$V1E0b-VSCL zddUXv5SoKcCAkkuT(OCnv}|G?ZQE1s5A(P+Y;J1%NzN~ib1z@ZCT7bf=FfvoOmkJL z*SuVtnC5+%y+rPnl6_hKnrvd)x23dy1wA&miK&Wd-z)bEIeVgv?M1Z~yQpFllUokb zZ+C~4?3GPY-8*y5#*Cl;40bW?V3ya*u#1^gvbfxn*|Lk-vWwZWi;0cimR-!lHraok z?P8kwzLU|j?P4Zpr2Znqe^R@c$@7`L$`_8onNL>48S$e{nG|K}ST-=tKaCAc z`!Cc6X7Ur*z_ghSOnV#~nBQ))fqBKhKpU9f#s=mUKcx*!^D|-tGilktJgz;=W?OqL z8<;QOZfI`9FSqmgQnvh38-gtxm@ONa?4`m!Ys&`am;Jo`yi~jS*I)xP;oRBJj15fe z^oTBgJR6wmvQ(!uCucfk%MPZq>)C8W?4QF9X7bT&%^|mz0J@b8~ zEjySmcZI4Iuf>5D2U;9xao}f>11T5Yf=`DV=@x3x;U z&TF5&_t|HkeNNS_ear?Uret1xM^+m#%gyLJq3IY=E}`eFF{SkirO#ifbo$jtg6xr# zfvVO56>!yRfyDQ-CB9qEKXoqGQ#MGi06t>_1#G>8@4vp2tGvzVEj@weo2Pm!&>jr* zX5i+|cRTq0`VFLyE2D`+DfEx@jyu|RUgc>!BJf+#+f-(!(Ayj^M;sh7JLzxaX&c;% ztkqX~qE+0#&`{>^GO4%Oj2=_2%zlY7aHwA^WSzfrb@CDD^JAei8|eGDIU2GdUoSo9 zj>0h$dko-yVqpvQN8q<>e+>kZ$Jbd!;`8 zwa@W=Nd5b{=5ftjV%pT*Lmzc})bSYRbk^;|;pE`EjNzTqqP{@KV+WKzB(K0dIrvUv zkW0~K_pq&6;A&i6IHj)!^otIJ z0pq`BjY$L!USgU8>7y~@b-;e?^zqN`Ek_~xP~Z?fXwyd0!b^-E80KDQI?2-u$7mi0 z=tYN~nRGTZ#6Pfq3a+!!jsFfVpar%i{om;89MZrxePn+^ z+K>h&z)oBur$T2Zxi54!{UdNvR|yQE_YZ;fQ#zY|n>62F<*FHCRHT1EUwOJEc?VQE zAz!}L+EP10c&;U{^i-1VY1I&;LU=CH327TtwBnn)Q@=bDH0JAT2pv?VVvhLL*mPR(&e} zGt47ZR{dJ$zB&}@!L*v5B*p~uIKdV#96RZ2H`nAVQ`oplV8Ayi*KyK4l|WT0I?KEc zF-L1niTCjcvZWtM6BokCvQ57If01z?zx6e5FZ&pa)>`Y|IWBoSmLfeeeB&KI_py<9}%U4~_pJah_!@IgQp78{EGuN`KSq z%n5raoO?l4=CXtJ{j4!ha@ARbQuywzUKgzAK4Z=34Xz7%Yu5!DJ=x!*DkoS2MXup1 zw%k8H8}3~@WS)fYy=%`k`@y+)?SQ!++V`&2X75^MPGsA{FvqoN?T5{#wYyB#2VUq5 zX*a26!`*z#XAU`r$7aKfcq^OM-e#Dw*gT%CercG;a1kaSIt3%;>`plUB zg3k&>4w)9ZYr&puwjS~QV)cOMS>MBVd!SAKeHt|WflG9)TnnNKGJ_WVEb+6!C*$Gj zP05&|YplJ}*ChJWhrUj3w^gU7wB1NuwcF#5j;nI?!~GS(xA)8Y>l@LR6Ua9qCX49r z?G3A@nXT!9%E8581-O@w9FDmokvh&SS^*|usS-oMjRK8(!ye!{$iblul zy-VRy=%e1#gT7u}>U~9(Z}^HWKXa#bb@uR`R^j6YaIUAH8;IMb_^x0CJ@Osb0c2Om zT7A&VBmIE4nIbcpGctGRw^m;|UeA63`y~0Zwk*HjDr6x(Tll;(X7GJR_$l}uc=WgG zo#R>HyT8D9bAeBR?{r)8TJRO}D|pz%n$;A$!Cu7>UtZ(OC&W?E$8F&BQ}z}qIxKsO z^x$jSTNJogo|OjbugcL9e8(;H(^$rOGB_Q+_Wpin(f$hjow796|5i)#8oBK>#1?Cx z+~#zx@ad$y^L~DgpbKJ8CA|=D{QRhC;`7Jls*!k3QvNCFWAN?9FyBNsrB8u^`}FpQ z!gSK>hsvRpyS)TDAbrMzSDUuj?ZGQq_x%3A`QW1a#WyUkMc0UvmR$obpar%iy^eKn z*#bMw{FFZQOvz~Ge#ShJbisF9#=9eJ=({tWEJ!!=^t`OVZ-3tFzFwe%hO$ZYU6oWM z{#`-8v)|AmGLpV#M1I4vxB0@nEznEfWg_gjlsBZD^-u2i$oruGj`g*%-TUFP&z!5_H$6)H0oivV3%4I3Hkj-`v)}XiLhGl6 zR&=2WF1Mx&T!U_%C+W*g;@}$71ZHE5`+1DF_!*KOg_iSuTAvRslqZs&EmdODf`8t} zBJJ=yh>!IKd<2ml<7J0v_l7ix$+OGRG43<++Cae}`$VD9T;Ope4qk1V4zee95SriU zX>JaA|3iJu$F_*+BPK6-V_MT(=0H|Xs4M!JhPxtrE`7a`zQpIf5E{;buM24->5Duc zh5j{ZC-W}-6^}cu`tdvg-g@a-w+EiXo~xy$X!1a z_ov8ZHjK{&qObFQ^D)n__%GQ`AEV>6w!`Q{592rtPQITVlkO~Uk`{ilZ+biuzeD^% zb+F{lM%2k&ZV%pzuhKe(|Gw1AwU0BWeV0vFH>Jy+ty6cEqkS^Rf9&ha96G^yRpECu zNNeVX~pDK3-WBv%g0Ub@`EHZ^pbSmCDlb=Q0>SUOJCwV8jD7Nx` zuWOUkbN2DhQ}$8pqW#xC9nt1~*_)$lj^78p&OV3_@ff;xKWmu!cr9{1D|pqXa~;lY zfyVy2{yydNWiH7%Nu1kfLwQ^5Gya*_@-yr+->(t7tw-PsT4cZ77QQR^(ZB}yG&abU zb;wWZB+w`_4LSdq#P4fAm>SbpVy}?)G$?O@Q|7hW=*LKLRw6v=^L&15IyIX5>YK!& z9Az%%eTf`9$0`}czhSJ}_Z|#Qb(^!}*}1!-2KiDiG3YVzgBPVEuQNaHc3aqM(WiIT zqJ8WW)Rc$i&Z=J7D`C?u6 z@wE50zrHJ)k6};t*ee-+8sn&r)&(}Q<@IEUzQ&i= zn*xsy)!RUm+f|Xf*kmW)pCOY@*>>KGeoK61k$=iukFZVI@A@%o2p@~+ff-|*#g4PL ziMf{;pbenlE!L2Pw5$tFV0|>L?a8J>m48bhJO}@cy7S}1y1=?$Yi@s!X-j?Tite%Y zlQ(5Dcr+^*58@QH$Jm#RG4{y0sJ}kL{>-9JD`>N#DB~Q6HsLuXXSeFB~)^tras)k%AkGCjcg;^2)&56~C1ne<2~I2Y=4 zo4R{a`bXwMtMHPbLy3CM^)GhQtYjV%TiL8kIb*=~T!0L?%&%~!^$EgdD|r26MW-K8 zZrsxYj2(4l4{Z+EvW9N6<_@EwTgsZ0#UjU*54f|V7WmDm*ot+g0j=@iW)nNO)#zT* z!|yS%gEyLngYPpf2d7Nq4V2%x)3hAC)0idj3-8U(U<2S?L#M>cQhT6(75YRxG>E*PS@mVP2RnW}7I-$JHeG_O_V;_KW9+Gh1IVR$_NWGMp zO=dOo9+&`ILxTUX!!JDRY+EQY(2P|JTEuS2Im#LR3x4tK6!irM^HpqRMqK4Kcu%ax z=K^o`F+Yzq`)RRD;bB{T>=^bAU61;_jf@p%=<55SJmYA{TBJB1`)J+{-eoQ~SbHsJ zpK>miZt^;6p0GhvjfR>tY>kgrJnPbxi6H)TW^|<-=n`d9%l+D3xi*Nix6R+{N)U*> z7vIa-3(EDUp-u8DHqf6+O@m8U6lbSOXMN@9&t+}JKhouqFusDe<>%{7Su)@W)jSUmyL9{()+)JJOJm9!TrH{dX7ok;aK_X7+~_TNEy*X(``zdwX-)eS z9r_OQrvYzG@yS_7S2BL;ho$IqC=Y(IZxs2aLU2QxOa3D6WyR68`ew$gTRy~xL-$~&_8V5 zoY!kqC7zgacEI1?M%{7{i!3)x1m*!~WLy)Vc_1?hm)TGT7rKO8+rOTg_OFu%{#ZjJ zmwSd=Ee9=VG|=tRHFUKW1T9HJzsu9)X>?I|NADA00(4~oG{A>`WxVS2JiLZ88)ak; zX!8A7i;nz&b@{14hgIgnH9=eYAD%MC2;6COsd|czS@MOi!MltOs=-`NOOyPtM!ipG zW)j*&-jdfiZr!-cIJMzL#$Zx#q+TD4y2i=J$wtw?t_JgCHDSXfAE)MU8d^ECXxkv> z`A0Zsd5+H<;@QU}dxvmI5QJxOEkhRNaz${sdXL#4I$>GwRewzXx<~a*ep!|GQ0KJv zgS0)H@%@Y~um6%N*OvxC{T!L&j1hDFlpM(un^vuyJ`OxPIc=;eq@CT^5$c#RxTF&3 zOV0f%6*|*eIWe@N6hU`)IK4Z%pzLxgXiNC%O$Lndo zfxbdyQ_#~#|NUIO%Md#>*a6R5;~s0$et+NMzIWM>86ZxL?JLSRo3z*8vpz)e;Gk(8 z-fV1ClusFnRg-{QAs=79)AUVOf_|=z^85+^(w!48>oaEOG=3200fPhX9RQ)PbyFI| zgFI5jmPlG#a7q3}k}vgSyvRRT)br`qBfg$~)_{5#(R z5L|KD)}-C5m6{zW?xy3Ugf$se8G6I9mT(>xguPCK`FQ>ULM-_ zdVRcTd@Q`_uZ|g~_xOgQkHbSR*4wqu2jlpDb*zb$~q}dni%=;1Qd!F8yvR2A@+qm}$Le~3?n4xkGVS(}v%!RCbXRLRP)7Lv^ zlNkTB;`w;!2gi)Gk^NPpFRN*>eX_@bpNH)7u#Fv#*Pwa)-9%lnF)=n->J)aymB~6R zb+=B}$TMk@lVSh6TTG z=lXj-tvlSa(mv0ZzP5XsV}-4QU50P4b;j11++bG~g^~3Ax{s)3S$pntLbDj&}!SJ%-YL89x~}d4~9%e{-yo zAV1-8H|K>-&P>g)t%&`J!O`SdqxczenatC=9b52_S{^QkH}!k|+)Ku?D9`@O-O)DL zue}bu?4fY_p>!M-!6b+o6 z8jT&b$a!|+MiX-{XL7R>n@xjzN8dzjW+&|F^!q-$d=lG-rUjBD=-on21fm3zO z#he3C&s;3FIIkz=Qm+GNXT62Cv}h;(D`)+j0U%e-bP{Z0lRaLWcjnAA^5yJFAqN@X zl>5mGnOn$ma?m!!lJC-aIr>^PYn06Sn&`5e!O5K2O!R7%~?v$Cy+a~xuMR~hZri=9Pn(ETmYpGYz zr@v+ceGl(X$TMd4lJbmM&S=7nJsY-Q4|Bg=-R8~<6?=UdWA;#sJ`-N}e(QW6k9PDS z&q?XS1Pl5&=bzTcXTh76OHsr;T#P53E&d$4;B^nYu3v=Lf`?lL|Bsc&zX(6ChQHu* z9{&P93;g=)9WvrQIwvEZXLgQ5bNGKwMzK2soeiVQY*o(SWe+UtqUJpf#a2=GkT+=_Dx5ag^kaY_k6!~i2JBnx6M*tVfy73e2HkUuI;61UEX)WRM z=MOdHOnH&!U8=?87IQ}2=B(8WPMD^H>v(o7>1z$|71qp}*tEqKui0dpk{L3_ zs7W|uo#bBpF*Cf&o!{!Qan4tz+!}fJ&kV=-?E*KLMAEF;O$To@ZFJjg|FCImDaXHO z-Pw)3N&Fho6HZK-n7ug#lz(E8^4naw9%GMGx-Li@eU^84Cb-r)`lNqdLN@j50^bki z4j*(4^L|a8GQBQn^V~pa_A;0-nu7-&k?&|L+Hm$1o!Te2*iY+q=LKz%JRA|KcSHh?j7wIqL(^6SVKyg<$VrvZ#Pdu<6Mtz+ti zlmp|pQVtY9zsZICm`ho?MP7@vPAFq7je#++0c-$Uz!p$XQhpKTz!=y7Hh?W4``DUZ zPdVpJ8+tCLb6B8$dZTZvo}JU2mjZcn7xR8Qdn)Jj;!NF|Yw_09(M8 zM*fBiKTcmyy|bx*BlUnWumNlUTfi1jpF{b3fwYT(Ez&XV8o(AX1~$ky*sU1-6F*jq z-f<2n_c8p)xtH9xxNqk78ot^^9qtX!3Z+hC74`G`7Wd8kJ|3ffQHOhTAg_-+lKfum zN0a;JdiD&Pv27Ql_hnUUmM#8}stx2M2~ zpSThE$)4JL&!;z$?x(-Kmt|qU`X1+Ee-ZR^b}Vi5`?u9i-tKW|-H6X@-u?;l zH<4fTwS)QdB61#W+Um$v)Abjar!VO7>KOBK$5qG6JAtESy!tS3XL7te!n2rBI~yK; zudTj(+eCTA?U|!J&G$R9PY}5l_($0*jjE&J7<;9WAJGqRXEGj+FqSWzYbzsZ8oa3e z``ow6{^?fb_D?o{PkMy?(~e_P;SppzDp#fg*;h&a3;DjP=<8wT&zPLU=jLxNhRdaMXe8i|03hm#X$~%0w&-?5<(ja@kidNt|zVPl3xOzLTN^3{CUe?>p z3Vx?0e2>7_2xpCg=evxD)VKdqMI+%hBYeI5xfCA-%B=Sv`f~Xcbc^325q|RRNFLRpNOYX35bN#RQN55YjLFZQ5 z=^)!Gbg0VVW?Ef=PLGbJf#4kFJ*472n9;scAo&7EH25zAzb*lfJ1Dqr1((|7agB*= z!F4n6CH9Hg(5`5Vy`fsYE0Vm!{GM)S`cSaq&(m-xzbRPp-ZUJWKIon~D$e4B*HL&K zO{S|m;Wx|o%<`@Nn+MWh?AQk#osKSeALTcMPCn3a_^KgubYoUKeES;nGSK~24w$U%J?~v+6y8Tl>yWdTSBW!Fp=CvTDtu8-S9hQv zJ2{t={tV-k{&#-{`0y2J?Ph*=H)aooFKsz)Zn?^aHiF)FGTw9B!kw$9t2e`o;(T+A zJb7>KVR(5tq3k><8w%z9^_Q>>(%%vLa(#4l#k|N_-wVvS9am&EbByty!M`}B0>QC^ zK3B93hdZ*d@Rs;+cvK$_538|o7eTt!7(qA8{k3om@am&}A4aa_uvE%Qvlx1&I(HQzNmZ_jp?a}FD z`MC*Y@d4W-&r!vnh;w@5oZe#IjV()q`SJg}4P~4P-5Tu}%TdPi2xT`@e?{XkdIBx* zcLaE}F&n-JeAxh@Q}`PN-nLtkxtQmrJH`H8vajoscf%q{(Y?&0$N#XO89Fw?9SHFI|5AK2i#{HA&3`QxFxUp-`Q<=LL2`)_K|D&!_-rQc0I=<|N$lGVdd-y$EkWjXpYx1Z3j;+Au=;;2}l|WYl zT?uq0(3L<}0$mAoCD4^XR{~uLbS2Q0Kvx1?33MgUl|WYlT?uq0(3L<}0$mAoCD4^X zR{~uLbS2Q0Kvx1?33MgUl|WYlT?uq0(3L<}0$mAoCD4^XR{~uLbS2Q0Kvx1?33MgU zl|WYlT?uq0(3L<}0$mAoCD4^XR{~uLbS2Q0Kvx1?33MgUl|WYlT?uq0(3L<}0$mAo zCD4^XR{~uLbS2Q0Kvx1?33Mg!&mw_acYWZd+iw2oj+;LC!H-?~;4Xy6e{-c+c(E{VX{wp*5FWdPRZj4Ac)Ob>G`h-dL1( z;cJsXNxqlO_f|`MyV@$gv2OhLbnQoq$mGo?N7&@{$ufN+n-)f zO4HpRcR20kACENO2TzxDev93z5xzA&!na~ydpIm!2rYk>;5h#iu>I}L1!@8|PRoy*1daZ|nrt@y6B0-h1OfbTv_+!}2U zzNXj(?wj7wwv%rt3vEXPehYe=%Ip++`40CH2Zzi~`Wt!L2Di$$Z6EE4R&oCVamEfW zlX{!YDBseSvg|lz;7A`XWbMDP+aNZg#8*_xG7vV<_vhcs9rN|FH+X@_gr9 zWGmnEm+$fF?Q4u~9Sqa+J|6u9x!HX^^RbtuyfJa5iPsF9CbEhLhfEtN`Ee<&HMXW< zNV;{B_P<$?PvZ&GJ{@V{pK?Vo#@wrh+% zx~|ddw#f7&jIr=0GKQY)*;>9w z-JxfOcogRBtd>3puCvi2U=x@=OI&YB1I;<4zeAcn6p#;$2kD3%( zo>om?=DxLEq!ZFMsA!2{d2rWE(3r1Zsw7)G>-)6SACmgSv0SHB(_)>sr|$@ekjOpF3;Qedt|O*7n`(?v2|?+uSR7a z4u#+Oxy2lJd=5}=;u3e? zSH8)=pIAjt5+kM`c|Ixehmq$#;+s7|eJPVVPptLvQu*kssh zH|FHe%ZqkSUJhPud)K39WF#vse%y2!Z5I5?YonYV@Zh_|`=-unZ6)}w*O z|Iqj!8vjG$3CUV=8m%d|rGHnH9r8MJ!X66eULe*0@!|Hf#yrVYXAP3?-}e%iZaw!I zYep|I>3WGnr_q!B#9TbV8YprNU$N!>@!4?i+9C5KeD7U*uGtUHy=w=|_0Ya|tu}kt zDsv*+7D}vo!L@1ahs~z7yG+&xUg!*IH>qaB-NfpcLyqCG*-&DgY+8Gpu?||3LC>bO zv9S(rCgg~uZv@YjsjEZbdiuUCl3s-iS16u zg+7<3wuN=OJ(T$&c5XwDkKZ%^9?>V2$I>34A5A|J-)VFDEYa9@xmf61dg%8>Wgc91 zzFA6K#X-jBhS5^_hSBlz255{%$LqaI;Zf+L-qVA=UR~;aMU`*(iY-4w>|d#~r=lvt z#|_|IPd_(QY)$?6?nq*bW`BQoG=S_>9yiPWVlKlEdz&dTlQ|=Ehkk4IrPz%RVV@+Q z_@ok3tB{4*yzqHqZw$WA6!EHr-+@PetKK=D1-|zR_#%>9gcBI$zfwv2a2+R%4rI$4lz z=IMD^fj=Ghx-T(Oq-|%}B>Jw1Z7Tj z<*a{lzen!3z8yJTZsM(Pa(S*CpFn(pDCgJ7lssv(zi6}dEwmXn1syHMxrkRL_1t)| z$85;{;<9{y@wu||f$U|TM{_QE+u>i^r;&N?Uu*W}*(KB?uIU`>YlB!h;)lyVa}M7- zZI#?UBSaQ%KQfVqvj0@ae7?}|X`vNeXoAbF=>pfFTjxpoa+5f?#x#NIO^o|_jJNn1 zl3ooh=liriA6iH!lAbM9V$yc)^#*(dksafej?(T8X%Lf_j-g}RD_|Qa zIAotFG@1)Mj>N&MP18a4#12C98$HdOFOm3|T;@PlPN*yTDRI2g z3+U^O^o8FWUkD9vfUi6*b$pTMqtLM??PT6%cYEAv)$bQifVW zM*MbFk@!jCM~Tg>UwC@GY#H^QIkTSdUG$kiyQH1oB8N6|@fMktdvk}|l{lQ**mDVx*_oZI0eVjS%yKK6;DUaEd z?kh+87*DHweVIciIIk-Fjs|IonTkT^V$D_UrXEg`RR~-Q$^3DRZY7% z3oOS?s;C;d%TrKlPp1i0iZ3XNBHh z_5Fw}1*iQx-_Cx2mp{XJ3fZ9t!e8=^wARiJ5!c_c_+Fkw(HT?4bpYY+Egg@tK$8dt;Mg z2blMQOV*XivZ_tuN6S9O`3jXUx_I`q_qLx{j+5Mn$Wr`f^?P2gTFhVjRexWXJ(2h^ z?8zQ`CBsi+9M#dfKo=i&h`uB~tU!qm3pBZ16}gK|cJlohGU=3U=e;}2_>!k3Wv;uJ zvcK=gtRZ|Xq6cP-aTYty-X`W=F>f0{!CR~$329jun!x%fG5<3BJ>qi;t>HQNZ`7S1 zAJzrd{aSPTdrVvEQ&)74wV%8xlfk1|K|h~UQG1Mi*%)KbT36IxpB)PAQS@mAZB`Uz zQ%2f^=aii7PTtD8iayEOYTinnY^a|7-=5Dp`ms>gg~sOK2aL2&z|(|2*A}`uX>U@d z2RL6GywT_Z`hqr-9tj2KLY;0?cTYqlN6iy9XsXdr{}bYIYq8DvUebpqUbOx+ zv{eG0U)ex^Dm4u*T~UFmu-;x&j{aQMR{SGf9tq%<|jJT6kX&m{h(jN z?enFm&Dc4=fHK2ct^PK*|CwLMvtRHwAf_x^@9)!d%hB!hCH6oMO}pncf>)9D>&cX} z|N2dtivh1WKNb5MzlF6*F4oeRvIbX6>bx0!5kH*q^gcIwOI}Oz$&1AgCl-B!w5ENE z4tea`ZX!(wjVgo|bKnXQ`jO1sq&4XA5oYi=-2D30v*@5f*Ox zt7$V|@A!@8riop~oLvgCz|Y?X{WTbemW;(H`8?D5yyS7|bVn#-)40!%OXI%GjgKa- zXX8p}M+Plm#@UthmEsQw)aqcMmz9F_Ltehgo8b%kn$Q=@{g*6$H}-|}+?%k?clxw} zcFtlrcbszYF~Ki7vvi#?rE7x?YbJpK@yRE+UkAPLK5U)6&}&pBo|tkr#NXdW-Et7i zIBb{*3~|uK&yaZN=7G#4TxLTVT<9TV(*E_-w11sE@W&b&xm?W9YB^{@qk(Rhu9Z2% z4T6@Wq2J|c@-%uZGGoppzy#>Z0%(8_{mOV%SEv_W!+DP~nrA>FKd&dEUq4_?e~R*I zpi9>TZRvk_$`~VXr_rVADLQ7!7rqAXGCHURb2%+d^1~YSKAo9KXcKu$UgNlRIwND; zh8G!wNx_kNT{7w#Cm$ypMgO`Q%#YQC4U>GFn!{;m<-DV9i4m;&!a2)xXQeF9O(xlQ zgiC@TJd0}?vM84;g2UB&%m&d3i?5*iWBS)Us&Deks=S9fr?nrX?b(d)XKZ=>msGjF zGzjYFh<#v;uoI``NS@fkYUT8C=po%XRu$5sKcdGmV{l0&(3h?Y;#tMB;tz%K)(err z9o`gk>7{iO$>1IB+>~24QWc^77F91&-=a+OlUypp5^dV)L zn;U1;7hTDo4YQe3_=@)G0``*^mh@tH^pEjp_>+A{`bKXb>gY`N#@v?QRdHwH>4kav zZr1O#qO-D!=2&y0PgH`C`4hs^5c!rfr4ZjG`Xu#oS|@p)(8t>G_|vKBW&MyjD|x-y zq3{VgPvV(Q|I)k6zNNM*`+v8uWPiK&8C%})wX~dSdIssqfo+){| z#oa69=e!-oqGC%K)2BWe$vYl;3LRz~I^QJ_oN?LK zr2VUvnJPXK?}?b=J&|M2*0X=``|1ku<4vxE!xxMP+nE3tHCKeoFDL~U#mhtcUayxI zjgN&l{nat!^dJ9H^m2IU#d^E;`M|unbJm5Ct1uBZ4* zM(i(V2I7Nh_SQP{zKHssr#Ggom2ze`?){1|Q|$YFoOF3EB=0(1$lAGZ%}jZIC2MA} z?m63p9;6k|$3s6jX54zpo}tl~)wI|^?uDO+?DDXUJ&xC;?z!eo)D>G3W1FQ;VQ)kp zZY`I(Tc_*sTg2Dk9{A7?rX7A6M|rN`@Xgq=^wki%C3vLWooT&6{dxNGGvn__`_6j9 zg5S4Gq}}sr-Qk{<_IbYawcXPkD|GK2SxwH)E<#5x!sig2@29TRZ+!DcBV#e7e%Fnw z)NhSs_)MHPh#fyXUQalWl)bI&X-|;92m5~l`K*WDIyCGNx zZL;Tk9eCM?SDX3R#MuzjVplXfW6f-Ni<#`~?<=SGx3Jx$UScMBw@rP?*Lz(w44rxrQSPTXi>?&Vx>c4D(>aPR1wh|TPTJ)ORPzkt3oaPkZ}KG(!n-~hM|0=1cp zmC26!wkf=eY_o@bI!M!?hApXKQ)&Uv8!lCK@#kf}uKcscYe~fF_v+BYbn^xdm!p!)_?wXpRDx?6k9LAvv}<^UG!6EqU=>^VqbO|P1I#xMjNmNg?v(ch|Y98l2&_rEN2;M zHDS*!&$C0)E%>a99YZ$j;jzds@HEySGu}Crxz#B%lebOqe~R*Ur%V^=<2BW#uh&wq zpih6z2KpZ5pHs6RmFLuQ&J$+r-LN5hnEUPOHh1QzI4_VfW-s-+o@47rJNl4kt@L4n z1$~_JPwV5e;LZ9gu-jbz+=6$_PNubl%b!Ek zkTc~)n)k65lUvL=bDQ&8GdN+I4zA<*v!t&zyqj1vYhu$DTfAly?-fe^FY~Nh;73iu zIqf9(;*Xi(UG5B6kBxIiE9KV6`-5gU#%~w6!6cGq&2Bn)qiLhtX8VUtTT40qJ?jqd zTeAnSvPSfT6H_K;k4^#QpID^)Hdn64*dvv$3lc}40g(SP5rvS_d~hE z2VKLwqf@6$uM65ddk~tv3?_``076IPJKBmioIypW_RB5y)p{K|yaL}?;3&SYK=NBa zcb0Gs>k?-YF;LE#T9O9pYk?8@z!tCpjG?O~`Jm!dOzZd(_ zf+r{X8S=E|li|?T-t&e;WzaIDw+P{;F=j!fVv7y`!+Jmoejr}K_*%x+I zJ*hC;N{jsFP9j6-)%T`GKdJDGl+sUH_R}8h`iu!JU zxdL4nJB6bc8Eek6=AZc~&Vs?2^{D7E#;MMEj^m@V4)!NuE{R@9UAG=G2aA3*W$qcN z@Fvel1uS~ns$X{)!8pSOR4 z{7vK+eeGcWyoj7fo3=V~)pY#@=IIN1ygJ6b+;P?M@=oBW8LvJJ+?gCNkMKNa)Xs*7 z-)pNc-!@TRaeL-yPtg_G@5nwuilLW#~uy%8a=?9W;S@2)FOYr?nOPH#JW?@2Co`1-?=Cd!y=TIL3Z&Z_{C)8e_JBK%O@&9$k5RcY6^N`P|Al;SSoHNU zHegK76xVn;j=b&eUY3(T2%X*tx(K{Z<*p0x~237j7sc-+Kible1M)-R9bEzA%%z7WFFCXKA zZt=aO?Z`9mmpxlQ+}36Vc#fW@Dz`A-KFis#{TH5&k@|RW_>vhjQfI&VmpRSshj-Yw zx&BxDqu=w6FmG1c=^)!Gbg0VVW?Egryc``(1Hm~ujGvdkgD~1x3M60Phz9><;MXPK zaR&w0t>99dJgza3Ex2w5zQkTP8`>3(vA1e~-rO_vBa3otEj&deCdfvOtD7=r9)*)vvuM+3D zLd%NwRQRHvuI@lTc5=2T{Taq7{qO!9^WiJf+Rgm_aLgVGU)plq+;Wu-Z3MmVWW49L zg*#VIS8s+F#To4wdGh|?!|?KQLfLszhTd_W_7e6@`a5D@u8*#+m=`&(d;z<$;|k{K zF~)xeAL*D11ji2gT+uol?#RZ%TjImvQGGZ(tj5BTW24YG8;;C8S3d&YTRyeCE@Qdk zQwPJBD?374<@vVgVLTh&47{avD12D-DTa1Qe|@Mv1|8DJEnj~&9Q!@Sj=#@Rmc30y zW9Z9Rrh-bfN2iZ@-ITQ3q3V)-(o0p-t(476TrzzviL+Bo5?1kR!m>(o);PzsO1Yl|B_RE&7so+Z1PnVte#d z8nmv){z0!6_=lD?ez|F1mDQT0<8sL~u4dg~4N6ECa?<2Ax#qAX;`hh$4&Wau_pG85 zUt7vM+aWi@+?6#^-e>G%4`~Ax$ul0!JkW#Za>n=DZah=YfQ07xJ{N1tI=*OIp6hhB ztzV4{I9qxQdiHR?0otRUb(J;xHXW^qQGKN>_HzcpgGk-^C zZogA}s7|^Ut^3#BZZ535>S+~x4*k9@_49w_Q+|C}$?u$3;-huqov&+|E&Q#*k6Q(Q ztA3mYtKe&uIvA{iuT}81>PKnyww$k3@U?1AnN>MoD}Q;$oY_z2cvz*T-TP`Q88>-e z`CaVlN@TZ+^Gfk^i*a4e?|4@;XIK7#4Zh3or&pdo9=iM0L*`bVQ#!g?lUE@(Iq&^$ z`az%fBQFPwuOaPM{ecRy{P!*e?ijzO$>n@$`Q2riePyrM0Ncaw0)vFI-CUEeO!1rL z3VO-CT*pcCTv=84Szzv`IXb%kbtTZ1Kvx1?33MgUl|WYlT?uq0(3L<}0$mAoCD4^X zR{~uLbS2Q0Kvx1?33MgUl|WYlT?uq0(3L<}0$mAoCD4^XR{~uLbS2Q0Kvx1?33MgU zl|WYlT?uq0(3L<}0$mAoCD4^XR{~uLbS2Q0Kvx1?33MgUl|WYlT?uq0(3L<}0$mAo zCD4^XR{~uLbS2Q0Kvx1?33MgUl|WYlT?uq0(3L<}0$mAoCD4^XR|5Y;3EaBt12^5a z=Ixi?^udqrxOn^RcPvC#lr79J(zGvb7l(H)p8dZ|?ltSKUwhq;zk2j%$zdU%KT9qj zz2xFcF1~cf|b(p(aZ6JyFQk?%jJYMSpx z%lGb&N#1!ruO#1){>Qtc@ngU@IKAG;!5S>+s%9pzm{@k@8*6f zkeImHa`MW2@7Hb!N)ucIwmhDyN=aw6aW!2X2hM*N_34CgScmu~YZ^@RU3A4ac_+9p zKW(%M3AeT?(u7jd=}#Wvd#XJ_58s6?&lzq1LcVotRcWFpDE&bKjjF81d-zW7p&%<| zfwDcp1oBNKN+W+W+-IS`KQ8(Cy|QZq^@Fr(-8X7QZu~)0=4iS%n7*6ui2p+^nt`Ss zXiERl(@}v2^_6?vWIWoLmY z*SuWjzZ>gmlGtuST4mjapt5AZRQQH&`jXG9j%*07;rs5=wmQW95(1Kf{~ErJea(`z zdhHflJ{_-BUq5*d^=zeThwA}2?*nI`_|EUUA|1S&^m1jcRTukj<>s`!o;IiIj@9{i zI{3@r|DwYe^lu8j@!$ofrtS#8acN-gyHuHPY`H$Ho%`>CUJnR}M!BR^ZF(>>$GD_jiFujw?--Z81Zs=^GwJ`}skG2~M!hp>kUG*w>6i(o zhayu3M;Thm&@%pmdn)75F+HHl&JG+)f(h!*NWG!=7X=2bFLr#R6;x)Rnbqeb^80eBf-Na zxIZ2aO?wILUYRBacvfrl5WD{C2g5Xv>uv|Le!28D+rk9@KcVl0J`8p3cFJb6{zT|l zn$}v6910CFXoNmZ%r~<&4P)-r4~gX`?KlGv8tod7vn}`FHfMXNiI*9V&(dZ#Y{>b? zZ|{m)#}0+9d!T8CGmmR`MfQ7lN9p_hxrCELZ&n*j>7#tCUlY@`A!iBj)dHqpQc-Cn z(ydPq)icfqw4r}?2KtY;)rGE@wBTp}ZPnwnU-WIHEd7GNR|SMt#U=GMF{cJ-+d>vG z^zS3iu9fQ+_1Re_*I?iP0tbvE&P_K#6m1gf7w&$FxPByN`Sw;l&6a z&~G2g`>hbih}b#@mZ^%wI&!k6euK-kRolY0v_IR+EupRS7fZ}n+G=$;bZr@n2IZDf31xjT~~_g6j5>1RBYGU-ESISrlt zyq0^~%QzN&w3b@J2Kqfc;jxU#c@_FvODBxI+m~HW%(J5WNzPgvz2Fi&t)=UXhu50@ zIsYQ}CUTej44n~OZRT;>=VjFNxV0g^Av77{j)f-@VnSx+@PrA>Gf5ENxz*VJQ$^+( z!yIQGe(hkGebt`@32rsxakq$RydS$Uw=@kzcb~e))@|y`9KNY za?cIA~|*x-1^mJR2S0yVPG<>_h*TP8G0b7v2* zhhkIGJ94=_!hAc5eU0A00KIOjAo7QxL zIO5cIy82kItB>Wndcd0W<6c+O2faM3-W4?jKWk3Re6YZV%!}uIOfE&dN0}S?9B8wL z!!6Wp6G!)H&X$u=8>+o`NAaC$xP*NDE!H_~la^S*=~Srp-yNBy#O-2?TZ61GGS*u> zzSi{Tu)&{Wz4?3?gS$by=2@&;%G5Pno}J(${G--%UB~Z$m@8CJkjh zndEA*hE6WS#yUEQv(A}T%q1~#Cy7sOn7@rWyl30OIqExoP`MptoExkSOVEM#Im9Ic zuZ-D)1Jh;>ep=*7EZjEj;{$0q87!Mv=GVFKDzcmQaU|8xdl?9x|mG?e^T%}`JC_PONt)G`8_A~#2Q8i z&P!|R;vB!=+De>yk)esU`%Z*>%iFWjdN6HA)-)m)Q|afm#NHN`$(bN+E>ndX^L-+?<& z_`X2*Yzq2`<*9qP7h7hcU=rx2ZN@_#nE?qoeWo!5j{e9lffLt>1EPl%s^T!=ebe+@BIi!l&g`v2?izhb)@tkbP` zZ*w{;>rvyZtadK@u^V}MEqf>N3ls92T$8Nf#JI1`%}j^uS;yP>w{85_ChKT>X3Erg zj@Dvs*7N;+o#%S>%s;!V^ZacO``@`zR@*a!?}49CKb{2ZNuMAF?;fCyy*+emU};Av zwCQxa->>uhKIUq0*?*hYgQgbqN=w`8d|qpaHmtig_hmBH;&g*As}GHab!gB-FVy#d zyAE$Bz){DSn*@flwx`9OBAit{EqHCrq~(_EH@ zPotW%;i}jBoz>Y=rHMTdAE<#}pqG@pZ4k&V6dwnoRq&C13REQxhAof;m3Q zeBL?}UK$1IckYU+@Ea2cTrJ%dotF_WeXojI@acJH4HG%z>$YT!ps}^=fm+PfmOUB1 zZt@1`k~-y9B}Rr4b6DgjK3t3X_K#JxBxMG|qqI+-^Xc6C4JfZNjgf{g^u5Z|54Sgm`gY1WS|H#()MEUy;=c%J%b}xrl@SsIE;6sdqw$o{yvKV2uX<+)D$SFa=4P$`;|emJj^IpAf7&9kh1 zQ`DiK5WN>2p2KHJX0VGLd+`=yyx3l+IgE`erEZtX+#NW*2bK-nigBQ?>Z7yi7Gsccy z`<$m&Z4ZSe>7(dV`g*-It-nW^-pg#5YCmsJqjBx&G&*~LJ_*fxzMPsuo-JgnSr_hS zZIiugNIJ=uhl!k#zpy{w3ka>5qjwG;Zv%DiKW=-ZzWGe%d{P;|C$NKkc6->@N`fbr zzRUDuL!P*2!1N;v_C%Ha_iQ$OEfYK;z8iTG<6W_L>sy}H=G!n9lAkg@lJ9V`2JK@^ z=Wz?p?1SJ|rog$0HV%(E81(&o6g24X1oiea?)w<40p3r0ntqpLhr_3_-2;zil`W;T zc7SVZWt(}rNA(?`k3sZi@DGz<@Q)JoM)hYsrT**h{jhm(S*hIr^BaOEm!1t@eyv|} zWfUwq7o4LT%meh39rok!0J^fD^NRkR)8X~ZiT%*OAKXq3lK)~FX7DHQ0PCmJ&C0u? z{oFt4+NI%BOD}}SgPd(=!BZzs27{N|`t|VGk4y$N=XO1+*3a2W|FW%S>pE2*C?7Ke z*cf}YLb?cCK&u3uK&oInd@^g4~ld@GPd}@b$A%8s!CI_ z$LDHpwV}vA6`yyCvh)MtGW!8HpM+LfyXVlWxs%@smO|6x+{^ju<6jxC@8t}36ZGu6 z%vPUxUX_La`x(CtoTW!uW>VfSy&u_Z7+z+Q>;qx6bihRLE%o+|s7jwe>PKAn_iQt} z5BIreNn7c2AHG8R4|hk%t|Gdt{B=- zy0_;;gJvWI2+c?ujl?$??>fn@?~Ek6d-N?3!HFG@#FsF34A{xTeo1s^gy^0TLK3#* zmwo%#DHPyF1PMtb+>eQ*KQ&r^+f#-qSvbfIbb=enU93ftGzw!ouig=X~dPuyad!sa> zC%D89qj$YgnuHIe-#-O^G_@)EbdYW8pX)yO!&0URzIlrEs^-^J`glVs(>yO{(SH zOgCeaQpc}R+2*-@M&4`}-Xc!mJO#fu153UqhfCcg?g+4tsJ*U7IVb4zCy)h4po{b& ze#>`8bcks5o-Oz<-Kq3^1Bzo)nR>ph|S_L#BC|NAL(eP$9{E9l>Yo6(j&5zHwOK5x`(xC_*AX;B=72UDlOy5oAqgT zJlRZ`wAICjC zeY^KeX1lkVc|}rB8AoO8dj{ToM)VVSSm1n$vd^RJ^Wc&5;E`}v)CPx`|D2EQ^U{Hr z+^n=4W0uff(QeX?L38{Kzb;J?KP~=7{!VV!pe^PDXul5H$)3lv;PNcxu3OvFu#UR5 zT+!l@!%>&BF_x(wXoLQ!kD>wX-|3@a^K92U-Z3kV2uYiyDq#v(e4kc z)8osvfh%L6@Gn?K^@!VloOy(?*O>FYh+k^*nYBm8Dfim#u8b>!OX$3Xy1<{SfAoMC zU=Oi6+mjBmr}MOSqC@yMyA$~Djq!&Tg1^D#)G1H)W(~e^e@WVLC-r7cC3Bp#TQ?}r zLl2d4=?Hu$ymc79-7deWpYTmG4{ApLZqD>)SZT?v;&-$c+tcuwwjkSfVPLNkmtC(v zh5u>#+Os$K-g!Ur)7yV1U=R4-+{tyR^s}$=eXa6j&T?{HPx@JS_&7Rmv%kkZ*)RZ{ z5ICXzDV%9v+VAANR66wT&8?NRz-?iUC^9#2@6A1PUMhVYUPy3hMt56vaJ^Y`Jr0cK zi-3n~z8D|(9JsYzL>h76`Ye3%>1$bu=TGo6b)46q3DxSD2bD4~;ZM<@0>&AU(QVhJ z(jvnR?y>9=8U877ydKv^nNlAqd+oaduaz+AuRHjDityw3t+PY>8A*e`6Zf=);|oqg z`)9#FS|f?pVPtJjvz{w+diEJ7BBjH1tJ9vJi)9sk7cLt}t+~#@i88Q{!jJ+$Pm*$YElK))tw06$!AScI| zO9>6DlW9oYal)q3?c6D7xIE}EawXEOPLBl%UCycZUH`_kU9P^z-2EK-^$#QcTIefh zyM(@?_X~Ze1+3w*_mt3C`1OrwjoxoJqKh7VCeYiS3H8yZLcI;wC_ePgJ<;JdK1CeA z*8t}X`ZK3IY||H!6{2@M!1)Q!=YvmQ-ZLPJ@{5*sg>BRIY6*Y~o+BYF$^pU?a>*Q2fQKV;4NqyOg-j4bsD z9*@ElaRPq%&eb|gS_99og$JEucmhjV5zOGRIR6(;!}LENg@yRFFvCBI%m35UX@ftG z^AlH_R_L_#@dqaQuEf><>J+F`piY501?m*2Q{Z1F1)gSqTC4jkt=`Le%zGWZNI5eu zQI1xdE#1{%t?z7bQXLIWfqiA&v=ZAf_BxxIEU{@RGG8ms4+$p@ol2uCjlEv7irs`c z>`O6UGBzy6KW)QOkZ)|zWY5&ev5v=FOXkT#z|^fv^q7=IInE;B0JDf+T*zSVGFPVmD&K>zX8@Lwh87W}i%H-s;lxq?!`S?3#)bpZcI zk)G)6c-5p0{^DL^7gS(B+qk41ZCRcKgV3=C*h4$ylGgx`xTBEN&Hu!FcGO6QEB)1nhPW7=v1 z{yO$fcHvIq+B!pf9Zt?|RPlwz<+=FtLc1VtKIN0QOxqU(_gs@zUO;-jC2duHqlY_P ze7`?xpSwEPx|OuVsrRIeZYnx=J7I?xh#f|>ZxsG&6zBIuzSKjj9o86oJz_s2b~{6( zVfL0?16COt2!DM27WRO#mn`yo2&chAYzzvW%eBs6mjxcf*k=w4KExNm!GlhRN9TBl zvFq{J%Xijbr?LS%>^0h2CN#u3>Si}upV=$zn>{RRlXj7E1MJ8G?bz5EkgvL#-{dqAz|eK%9k<;uVUX;=6Co-7@u!FpS-T{*oAb#kGj9v9oQE@y9+7% zLi~&HFT$UVKO6sRtf%Q!R*C;zfe`2k3`Z&Us7a zg6ltK*%ve{w=Tq8gqw}Kc)@aOo!{w}p+S|p%wYfTCfpz5zKT=R?=^L+(ubv=iJgbx zMgOD5CdgSxzVsShpubhIaq?z2SPuP2+JqeyrwCjP4Rsp2L(g;lmOZdJ4LPd=*NK~p z8v{lk`!ae#&Px3hFlPW`ChmOPEZkP$jf;ID@Wl34+RlXz!`N4ytL!A*WSB!WI2w4f z7h8SUVmgc9we%AiUwCwW&YFt;lK!)lEi`mk=lp4C_Gb7bI7s>9v|}VoSdWDFWgYx5 z?c&mo`-~#P{1$A1diT3h zMj5}b`4P7mVt0-2Agjf0LwG;i#XTgrG_D!ffYZpfF}24X1`mHBV+XS52w}M}l6OVE z!v#_J*>N^B1H@A}ZP3fWDz>~F&khP5*>s2BP zC4X)vt|Mn1C4FPK*UfQXiCO1?&&6)z^!IPO5pEwbYbS!6njMuXa?{9jXyDNPVvAe- z+IFk@`af89W~F7{6Qup`v+kQ|n&1P||JVzf-2a3pl6F&V5${C&ajQGIU#WD?sqHt1 zYxrCGi}XE7lkmtH{Er>URQx}=&rRn0$^4$+D(#<)Ra5bmoDmTjk@N$p|C#*HSp@J; z zU(U@m(H}%#5?x8`F2{v;;lW{(&(FxYrD4g7+zQa)bhgPVN*efgsB^V;!BJocUsvZ+ zpK!!8It<@szJ-U%=qqKB+w|)(UPW2(#$X^Qc=H%HQdkMw_s{_oH?1m6_* z2^l@D_1|j8e+<3iw>{By#ja6(a8qt*5i;Wv@?4U$j&%n1vG?xrME=WNS!0wh>*7uJ z9#7UthevxdI;0<7?Ps?>uF_-ZFCR=td;AwPbm-;r@8695_s9N)HE|z^!!D```>i-^ zb{wW@m*OWvcNz7YU)tw-tVM3+x9m?J`9ZI-F%ud{*fQ!re%*Ta81!hW^n0@A>9K}- z7~G4+6si&H}AP z+I)15cE;y;%jN{uGWbAX7q+a{!}xt$(DA5GA2bvmm|wz{jlCj4H=#T0ux39{<~tJS z$vg*~%Y!}cIJ{IAc;N!q1rM?FlJe(Q9*x`W61Pg)tdeKQU#q(UfuETj$t^Jjv_8yJh&+rL9Hp?n^6s z7(GhbPJWC3>-gjBXUXrI;xLJGttjk$HDP^m*l*N?4HGu})ntwqLMvZY>GMuJKALmp z>I&DvzD&+gRs-}7HDWo~vDJnNjYU_L|3_$p2cGD6=fl&to*!gouloY(`RmBunfRg$ zpN|t=SkAhLE<9N`^aA!S$bW=>CTr(^9sAG6{$Ixae~JCSiv7Qd{jbLU-{K$tpLV0! zr+{`xaJh!{TE@8?I@(`DyBUmO7ea^T`Rqpqd)%3Pe}M1v@&5>a7QT#il3vn^t(>Hh zc!_JKzN#>q#@J%zQ)W|E73^Uo?2khyR<`Vp{_3ow?{( z^sxfIRy*Yk{={7G5z_U2PNlb!&LdvN-P-b{ep>2TQ^)OBhpx~5^)k{s0rA4Sz>sr9 z(hg$(wBmsZQjOGm#S_@J1d%RR zD+7b?po2m02Y{V}-Z_y)g1dkA_^KIKWvr`G##G~-$iF_?sMvu_q)mnx&&K#3B3#-; z#<{3%eAU&u(%OIiY<-)0)ms3+cl}k-+CQfB%ilikzD&Q`&$>mp=-%7{@-Fa0>keRj z`~2V23tF43M}gl?-?|;!yBpJ?)vgX$;&(xd-FKwYUF5k<%9?j?t}7K-w*&7{#tNVF z0SDmS1DvfBc=Pj*xclLy{df4;1HkN_6=W9xcO&xocHk`luK3-+UGT|t`sF*)>HT_1 zrt7>WYa#gU&*n1StQ&MQ-is~h?rbKr|9ugxbHnL1aQ0`d%(tL@H}qaGy4Tu>zOf+O zYb`jq*IG#bk-ERkeD>u#R_mnxN&Td50ry$HOkEeu0|s)GgX5ANpCT%ggWavkRz8RQ^79LGQzqzn3x}wtU9p1w9X2-wbbY_d~yKboXvIrMo_q z*!%g);1_})XQOKIleLlr$J@YB^bNuBo6vqixX1nG`F`e`^F#YlzU6n=cyI1ezHg@v zkIoD2sc?_1;+ z_6tt@UclT~`06(Bmhnn(?HYK*yB#G_orclVI1cYh+MyFL2LhX%c_U)k>NK7W=rdHuZ;d1Xz`!0{h-g)jWru14SqtjY9E z_@TR(+&WwLA=g~aIC`9I%(2$n2yZsE zpv%TA*GQnpajwVr zNXYLn`i)Ge)hFF0#M549ge}zuzLXipw){57E)}jw-B4DU+XvRx*uGXv*n>rDto8S_ z_aNu_Hx(@zGnRGUrS&Fl4LO4bo@TvHbbpt-IQx)yW`2zglIZzwhI7PUO39o|UthF} zfP&lHarPv}*^_YClPGg`zm%S)wO(%ZJrufq*x<`vP5J%+ zyLpw7J=8w#O%lDWN|?($p)`1J+F` zpiY501?m*2Q=m?PItA(!s8gU$fjR~16nJM-K;C`4_jm8OWvaI?1#^jevl>i(7xJvM zy=R5IqXOjp%cWoX?)%S0hspIk7hQhg?_c_={{H1p!C9#=U`zjY=S;LG_~ip^vRF5>dHbWXUg`Y((c2%k;Qafk zT%`fK=692S$9KF+1Gh|K&qbVF*8J`q1V&)lDzy8tOEdOd>XfBf-z$dEIh&Dr*kE>I z+bcG3_#>nfQr4ykNuxT?bXCqXi9OvI>YRNHG=Kf_wOXrgAoSDM+0v(^MwJ_F3waH+AK#4Yt67 zuYJ*SY@<816Ws1Pi}?L+=rz!ytEn|w>)ruiI|L9+9&mm1%xf_MpWMPdDW(za^^kNHD@1qTq7% zCuozX9V*$tE@3+>^~mEY+)q)msYkGfHX5)v&}G?flO^}?*&e@1Z?nf;C9OHvGo7$D zY`#h7T#e0O@=cyIzR6pGXJ$@sa_lzj!ef7S?04Y%KZcIPh3g`E%?bCL`i0ZNX4~KI zHt?1zG_~?VclaY;!yohD3vp5pX$#?D``4f^?}E-BeZjSZFSyA!52d*3?>Nf^JpV*= zrYps7yBl5(;bnz=;f^_O@bso!h4)8!{81Muv(n+{5`LAwA$c9_HKO-#>5<@AdBM-x zmtj*~155Ik>3eqX5?wwovUOVMC=*HcB-_l z&WY@eu|L$5t=^T&jitC(>0<1y!DEc}7z+EnFup4{TJ!$N#G3aw@x!#Qtb3a^?%q)D zgSFpiUE2=8mHXX=mx}?kzDK1iDMi?aw5)d*unif5N6NfWAU4mADjT@M7ek!oE5d(v z>rL9ZFFu!qEt~MB*!~t;Z_s)XZFC`JgnQhEOR)tPx^c(I7-{mYeOh0dv%=>hc^V*Z zgWrmNiwsEmx8NrI%=9s6Cp5`t=$BuN+VT|rLioV&4RU&NdkEiF@AlJ^+ePjTm3IAU z+9jA3wM#;msE++^h^>><-`xE#u;cm)ACzf7iIekcL&z9k?)QavHFty-dbmrM`+uc> zOP)O8;+OEt1M4TkD{;8Zoh<@Ww{pL!oRj0sirDd2p|!Kt&pOam+RC&M{a4yc_`$T* z6m8_pgI}KDTt@@>WBXfa4- zR{>stt<{y}O}<68rljxFz9L7eiu-E)M_ik}Ebwe>%mki8oXGwH^{GzdOdYmJ_SLJk z$R(+#*ar59t=Ob7Ky2(J+{h@A4RgsQjXBt$f~$K)m3NWDSgP{9-=(X<}IX>@t1J# zd&Ex#-sUOLx57^%3*iMBy9MqkX|GP?Bu>U&p{YN}nIHURwA-@H(Vfcj9*NjdY5Ke5 z^V(NhhtnzTg^#&@d{!!TlH(SPS0*r8#Amcs_k=UlR!P38_) z3*$3mf2PI$EVez%VS6UFTsq+FV!mh%%l+QS3wLxCccz`T$qN78Hsxt-()5l%58*U6 zX>!l*5Kew4wq?dPjQ5qrE=C(M!>GRl6a-KK;oqjh@nhN7Y_*r-o=i{VI`3v{RJvPW$?9?P(*b_FZ zs~KBo($+Znwhw7^ob_%=zEcOyw~?dRTpAc1lr3@i`LH7jBb}r*?)zcn6EAu~@PVjZ z1%`olKK%AX(X!J$+Ts1}2hrV}>8H!Grz7`ML35rk4UD{; zl>~-?{d8#FeN)dwe(49P%<$SEn}4w(Q``__ha_z!&Qqa|-&dJRPmr~FtD&SrJ1;zH zA;Wlw!6scb)uV0FIX?i0-XL2gjYFIZ9EUd=3{4of=!A&d`gx+lqZ<6`yb32@R3kCLj0o8XsLd$laSO37w>kpc@aV89Lk8CyLI)1-0}w z#tOApbiGW#Z8hCUp48gdGx^`yOnkpcw?KtE_Mvre&{80fbq3m`Y`V$diOJC zF&`Y?Fi#)8XLH7T0R5G7KQ=bY&bK!+p8D?C;y*Pu4w^p3oUyq=*(1=p%smWt?|^6D zU_%EP4a~4+aY#@#3j*`AgT)8Exn}hFTk6n>((n%jL_+NJ= zT<&@>dBP4azri<7+D3F^na?c@Ltw#*%VJJLNy0_KSESYE56%|X{H2#<>FVqB1SFNdgOK^(eP zaVKLWcsa}|Wq#!#kLIUeFm*2Y=yu2(|0jQtlX;%=pW!Jv2L#<^98k2M$SRxh*2n-E zU&Y-OYVq|L<11-Pz*VpDzJ{zt(1!W&l#9&gH{%@qZzCT=bVz|!0&bDDi!pHr=NP_K z%x_Kmjce;`w4d9{m>kbxDyg2V>+>z=q0-7WGX99R`j(tdV;|ggN;ryhOO-O%Q3DJ_(D%?Sl)9_(_fl1{#p zuqE?dhqa4wzMW#6j+K zuJkBfT@$z?^q=V4;oCR*1%1CEU@c^9XPC}2|7-S{cYR8w^J(8M@hxvB$nRCqzxpwi z9z#xyrF=UNy(?GwS^M5Fy^6L-@<{mta}3%E%rWTia#wjjeO20G1m5tO2b7?51sa!e zdMA9f1O5WnBI9?V7a7@3zMYKW@T>IK0_oBL^`YE6>kJZRi%uMmyUq@HnX#kF-I&$Q zVcHo$F97ZtVT0QGyBLP_?*xX;7$?79BTnR={7&FC|5?#G-q4ek`sRK5oWwD!Kn z*TJ8ufouui=AE8O{7q-HZQkg~p%HJLx3YwoIe$5fhG)+}vgl#GG4j91C}*`qNZpi7x?i!mUN3^2b#@nTVfow{f7-dN3`T!7vjus+M`hE@Epz`%lxm( z{Hey6wiFs0uu&#H?k~JVRcV~`S>q~pex7;yRowi)7|7GWF z)~WeB>H&76sBM$g*Lnf_y(W#0ahYLGkMS1wk1 zn-8v}S@FaiFOOfsJ-9f`%3F)aUf|Aj^@1z!Ev$_52u+Rwhdj1ToUB8ZHNR!Nq`wpb zk+;ZYWU{2y0rJ$$X?^DNubTEv=Hs_|4E6kR+T5|38_O6kbK|i!cWEA*K5H&)=qqtD z{u3{CN0{r7zD}3;g9)SMPGpR`#a%52?({7UvfAK(@;c z?W>M+Ht-PjVLoVdHgxSuszd+0=a%XTXn9!Z8OgN<-ic|T-;6Tujm`6htjgO!Gcz5WZ{{HOMKCX9N^{b$jBPy}m~Hcr#8M;Q;Fpsh!J-?U=_BPrAG zWWE8f$(qAhu-mMpjaU3;sZ#hQG0L)6E+t)kU^B;u)V`0?A|w{dv2J^3{RUK!X+ zd}uAAFaHTLMSj1ss6P|v)j7$hR-9Q+sn>zw(e#zGmgofER|I#`E*e*^Le|Y=U9_9^ zwQlxAYTZVu54e9ju1`1RFZ!f%eey{9$?+SXDo>OZ%!um!Mao@taf3xYt#7+)w7l(i z3HQ~!(j)a4iR&~7%?w#p9?p@$3^$_|bG?zLaaPFIcoz&wyNj?7Gs2-Pt)8*iM zIe2djMs@dA+Tp%I{SoMU*{t6(buo1yeNqR3)jcWwcWcw%^uQVAc02c<`7Lw=UJEq2 zg7U8b-W8MJeZCf+(2(@2V;W9X{$v!rzm5C*bV4@J=nSgz;U86F545eg=*Sj|h%$#2=rZahl!-Ex$wVr+bd?c4YQ0 z_+{M|Kf8;!0(M`kGVSO!yO#Rd8$X;%w{zFP4D!riTxjR4{%+3dw`W58dHUq@z?lJT z;jcE<;n!tTOhq4adAB0d*51S&51cvYocJzyFPO>O2o1nhx4D8tdl2DtBf7NUA#-qn zbK?~F+&BrJwoG83Tys#j0ly9SCj~xxNCN*P^_KUv+D*Mj+!@5pV1I4~`^dX&>S>dP z^@MizZJvW>C;y}GKDTtH{tV#~mbg>2LpwU4e9QWz{C*BtyCog|L_FcLhb8L-LiaZI zVxT^sG8S%i22ZLT>u(?HL-ef2ZQP-AwfAn^>crIUPKZ--3_eFSy_M?m7D8 z(!k*VJUGd{GtbjDf5lrvpAmn4TF;mk+U${=dpHGlBsYAOCvAmq*|$T7&&qnELmN8i zBxaqQ_LFrMhjb3~lYRKg>wke>6|(2mWX+r81g^{pl69awZB!wDe)H#CdjMO9nsSn| zg@!h=w06(O*k#19l619sMJ8%!;Nm=74tF-5*pg6wwTFFU+N63_zZRS|&c%7S94^7R zM0-_nqC=u2HOfA@=owP}klKUZ5t#i0nd?ZNk_D~O=(5;YRIb9_g1z4gbHVWYtgSZ@ zMmqT}SJ+F`piY501?m*2Q=m?Pw?~1W{r-x#SKisFWgg%Yd=8)a?K$ti@NbRpzc_6R zT*4M^vMq3FaLyavap7}kpx7CP*dqz9W!5V$WsW6ty1YA$^~1%MS+k7Sp)T!Xy_Gj! z4`5FuYnzuYx^7}^Gg-&n=tXOn->qG{{CCQgyaxtYUm?F)!<>}vJK^WNOD|9vS^pK- zvgQ*oADt?#Sxfwoa;J)`-`626S^uk3piY501?m*2Q=m?PItA(!s8gU$fjR~LWm7=z zeb{*QyRUhp`!6K!%_ubaUWl{OUVT=`J1Ri#zj*P#-}2pa(P45u&qbGC`281G*6+Xg zX&5UN2JEq)zW*Xz7M&GMV2Pc${GNROMY#9ObV>T3_5KU7mlwOx@N;M0Z!vj&EKGg! zjQcSnd&l66`!9U#O$0B_G+_?R9y<3~$oEgC80CBw^cVZ={&4-oT^J**bBUdW&$^%ZBg6^r zA>otHJ6Exr6nhYJ=fz-r=LL@gN&3XrBUlvG{UK}+PT-m;v&EE4+1QNQd2Br7?g#D) zs1UAR;f$Dsv(9J7Hk#Wv``M?5N4I7--G+N{fAxnU^_`&C>XTT2NGE{w5BAVM`{smayAO;>@|x)>*nb?fqK9CV%HwM`g%*rODg!*7Mq} zQQFBcCx6@1-(tG}S-MaG_<-UvAl_u88<2eX!Zv7r0w{XKJzE9p|jK z;(VaT8mzn-8WOKKA1L3_2Lxu0-y!zD@>}z}7M{e(8%f*59_q&t4#)Z4{;t6FzZ!kF zOjntwZU_u4;k%GCngT01e=5HN74hd!br;J=xkH3I5ulT?uL;NAS$DC7--~3WxkmvT zv=BLz^h;wu^bWa;B|Hfo#pWuxizV)}#zu*AQMGrmhiXJc#9{3HurETv1DZ{&%j(d^5;!*AVUmXM~?gt>=uWwjO#-Wgc1*WLr7o`4IN? zC-^?W_X&Q>oJsEAP-SfCWxmRN7I_KdEU=v6m9w>Pbf1MvBX@t+`z(Gu#eEi>!zp3o zUwfZLC9N`YM?`X$h5z%s%OcZZ=3shfsK?~)t2esaLdl&b_vVJ6SM7Zk!9SP#EdFMS z`z(5bDetn7dp&#(EHE#9*f|)w|s>b&h z#P?YEVSH!6Kk+>lYVjN2W0Cebuf33aLY=@`EWbI!)WDrwXMD>&Tk-jxv+k*&t`6%l zKkdC1{y&3zEyB&p=vb5QwFv(>=7)FUeHQKUS{G-H?fQKd_4_Q$of$v-eHQh*EZ!M+ zS*V-NyyHRUf62WPKhL`?f~(*9T^9bVe}ua%)|^?-f2zAIJ+F`piY501%6fv$hnVO?)cq% z-*xZQCt#wuH!fxJxsbC`{t~?Z`tV=O-*7HEOs?m-=<*9c|KiurznsN;Zy_KRa@GMm zhx+@koF`y^x&HnuXKCv1zt-P>t-t?TfB%&`d;`us$vLU1-sP>o|H_@lnV|muYjWt-t?TfB&`q{_7d%W$N$0*57}X`)p(xvi|;SSbzUj-uLEB(VmX8@9>d( zek9zMx01N;XR@D{xa6!kbM6vnIp1jRU4Q=-9i20va+XToU8=wTT7UmFwJ_)WW1pG% z$DCW%-+vA2@4w2OO7-_&&v-Ak{{CzI{nx3^1evh<`>*x)U(uE8@4wdHf33g&Dyt0j zzd8l#6sS|6PJucF>J+F`piY501?m)dGYZt-e+_is)qy88styFY{{HKmaZ5d}PJucF z>J+F`piY501?m*2Q=m?PItA(!s8isVl>*7V57%6E)sz=t$UP6lyr(vwry=UHk5&lJV$9@7!-hXYtc5?Fj zuj=~fO{*kb;{UAgzskLy^8TxT)0@Bl>X)MTBE`m6DWBp4^Y*La9Za2Ru+DnpHNM*- z*v7jiLBAVrp`7X|PwpiZ-2Iy(U%xhB6*>2ehuhxc74!B_uRgopjq zoQd}|^J&glr}ns&X(|)WyEm6ln=^=ZnRi_6A8hu5KU2_*Gl{$_R^lvjK8W9u&GBXk zuKb?Ru8Nyq^G@vA0k1lrIMO@*EvBw&ZP@Ji8(iM^vlMSBIN=venU$q`%^S7qI?C?C zuKID})MKuliP9Aa3wGX{D+ny!p)FBPb?1Or0G|rDm(S;W+Hx&#?j-MC`UfID3m=Ja zuW+uiB5(9iC#jc18&tE@^B$GvcUF93%S}B4-loX|Tk0&dkUHDpJ~zu78F|XKL*B39 zw>huLTQ>Oy(xsyGrStIJ&<-uypS%|7>~7j4yn?z0S-WMAC+Gd84J)Z78ABhn-j#g* zlM&83?02igJGcUHr7R6h4ZJGvD>C4)~N0?s1*LJ#GP>lyZuK z59dUN1P1uaTg4tQbCYn>&Y+dw5V-jbIW2ke8Xir8(8oaKC=&wcoo{8-&SEB--FP z{a%=h_*HEPo6Czo>Qx8Q8K-xz=L|mPmU6&IKj!Ae-~4&k#t-Rl)t#iFO$~ioeO-Ox zPsnFwl*3zUyw&8SZ*lE4kD4`U;mPv-``zkww|Ui6L&iCDt5=mEVdAnGh3t_0 zg~1WG+vszaIMx>*w4T5yeH{nzwq3|{9G0T0+~`?bCH zL)xJ~II3(_HzNzOgty+Lootgy@6a~#-b;};nu-sFTBpF3_9)|=tHEW%b-Lp z2minuOZ=8LsFXUq%Ha;L^kLpX`aF2RFX1xY*TeZZk=5bBuvv|U&AMg4Ds(C@cz9E; zz&Y=HdcD>aZB@RnGL;_sGVg+wIRB9sd2S&mct^?kfr3ASY?W|_@8sOK@V_l*yX75W z&UKg0$Dc*NS`za&JR)Uxtyyj@xNf;szJzv2_hgIs1?eMugKSx=CP_2#msZVzPBnK8 z-ld(rezrQK(p`(mJLIRk{K&6f0v_pstaB;l2@cRLkE>qG@3e1MU;lz9GSx;FR*=`U z=jpS?gvr~{lO3JkHE&A$$e}LUjP?%x6@9#m^c`Vy3HVL}yyS22O7OfL2(KfPC`ZA+ z4rhykcSZG`OL_C8OnAZxhb`ySuvJE;mEfnmj1|P?DZ>^x{I=~PX&JltGvCPca1C#; zJ%*eYS$Su~3zEOYI8^};JNzg-6)-kXZnnXZI6H{OB*|;fqwZP8zt=x&Rp42X(9Hc?2mA{?g5QnaQBU4|3y|}bX?~_e`l7u1 zCa&k}hF)VmZl;n_oRjOx>QS9>(#o!;dbE869i!DT--X`mrhK*-aI1vnDM#HBzc)XJ_U%!+ zx;_y4!Dky>+k`o~y2dyBX5ZsCB=53Sr2j#yeA>5d>Qx+6=C|anpr;j}o5V>Ol5Y&! z$a`*M(?i>RTw9VZ58n^*T?+bLAHGT6Uz0c2G;gqJ-eA+V!t{q%#LM>+#K+(E<$OOyJidvS@2826zwImdeuj8_6EEKySR zE9p1eqCS$Eubga`a-0RqY3o+b^h=d9O5YolJ{P}NQWSk+FY<5i!K~;aLp9$b-@^+c zSQF_PJF3B6*Xh}7bRM0H@B zwtuQguY5_RALOn1=9Uik=<8p$w!NepIkpKaSue_z`Dh>o78@#5gMO8ga+J@4Lr#`tDKq zRqEG-Q}p{r{G$yjzfpPRI-|&sV z*}mBKj`0?zq^sbLUhjLy`QCPo?;XXLxCGDR-&g6zzx%SaYH{c`wtx%tS@lE0_`Pbb zkE{!Gr^EepB9rs9S-xS9+nn2B3l74=tK1#7=sfcKLBhjV?ObCc{{OIZ61R%BZ-$Pv zT_(xDswV&Tn*7Hk|0{NGh2;N{os+oj>&bBTFB=KFDr+$xk=E$XLv`u6cZ;&j#R0y!j0tC4Sq;xTFl) z+unW+xV}5Eww+Mv6%EQh{;?o){5(H<^hD6GVy@Ch=la=I@anN^1G{NpjvLN~51t69 z`)#iCZsg430e(N?+G&+-JP3~#z7Bt@to`Im9{PG#WSBil+>^wWU-azJhOC{z?`_Bi zw4cH2cKLe|?6ml)Z1BI3)4i!|V-Iq<`f?n% z$Fsk}TmT-o2UA&J{87@}N18&1YxjcRU^*KbywX{F33!4_2p<_-vT?f67fd?gHG7ow zwfM~kKlFN;BTV4uKjJnH#CewpF2Izsfo=DGgL(slz9wZiE+L%*9@N)PNBBygvwPFo zz~DieL)5nl4w9x<{1^xF3yu7Xz@ee04g81Q##Bd0KSae%gZVN))G)oI$@v?pzB+LJb)XwS5Y+LJk*v}eFPcLEmUn|cX2!1KS3pR`X# z=mIRk9awgn_K~(0x=33mbOE-Z3vs4xh!eVmUeq>clqI}Vm>=Of3VhOv+!MGHZPqJ% z04ziQ6np`XQhsRKpE}(~y#>!L{ci9w<0)ksIr>B`eVC7cm+1$N;0=!VMR1hB9gX39 z6F8H2-iN=AGafkfwKDU2r!&Y-?w`oyiT-))V?jf;!`GFM`3(hdsc!ZgMBigBm9}3D zjT~9oz&PXPtSbH7@uRV>%6z{_dgdY7;^WB0tNn>JhB1#ZXP|?6pK?Rq=(O+em{^n2 zb4DzGn$V1S|LCJ`amIG5)QkV?4_cMc{cdsBHp^a&fARq<|HLEi*!2%srN#Iswpx`Z z9(Idsw_5fR{AY%({FD1!y=K@dEx~_!$f`UEZaao7dnx|vAuE4~wTRbHJU1aX19hpCW(bAVKXPtq$A9HdC-(k+3$Ze6kvhH*- z^#3e6-q&y!qpw}ug=4;Pv0iQsG9Ma!Z(#KjK8PE|rP1*&X8xE;MeCovnft8t${N^m}Z$#Uy`?XCL!;0tc>xijDYlR9<7 zd&YgZxk}7EmAwIJA;SaI~PCfzS2ON z(S1heS%hBo3hNGwxSvhlLi-c+NcpYciH+1n&Vw$*ZQN0|!j9<8v;%}67#>Y0aprA6 z;4d0hu9~BA8__o;&c9gY4)FV1!-FPmH)Tnh@FJD_R-8uhyW2aRX5&+316y4Xm30a0 zj|O+vNA7Ic2j23Awo(z^5v~#5dko%p!tefTk=}p6x$g`-zk{ybEqE?UxpxliaSfic z{H)+A@?LN~Fb&+}u0|R4eF0T*UM)8mX5)-Lh{$$N6at*+qGPMr)sj4^`GjZ@%r<0O3AGJ$<^%|YD;+&18z1g<(SdV}pG z^;WDWw3~X5xPs>l*4bxFZ?f9Z=XasQufsoyzw1|a*loWO+9&bX;qS7cgUvTR|A{HZb@< z4<66cZf*FIC*mt#$@(tqaOSNxnIBY$%R}D^_}QY5iEcz1oA!5zXMN6cpk)R41=3Y} zZqjyJlU3^4VOPba)|+n$OPrJ?>t|=o-@wJDZ`trn9=YK#=PKgLT@h|$_$6`7-z9%V zenX=wP75ANHOk$`vL_~Z4=MIXT7zuBS{L;(^Q4j`uw=gC9Vz zVQfp@fC(N|x!HV&FQm;_FKhJbt6#Phb|p$d=;UuvwC^eVK1tBq_8Is8Xokx8mq+$2 zf#?C~b^hOd(%=yM>rck8Wgh7RKJxub&bEJHytWhj7oAzmS||G#fAwWc>|rEtKD^A; zPqLr!cO9}lAy8`>dz(7+=+ zdM9R%8(c27H2B@%T%F^}T7}eK))2*au%(gp5oeMu&F!9c`f(at8ci8P?3-7yrzxzx zOKa?DCg&4<$ixW_Vs8U|hIaCsy>X2_jdqq>MfTuzjXh0LhP|3OI4->Z-kj9W-T|Jx zl^twP<;v*qwycTW0RGF-#h8;;(b1i--|T%ADAx)0xp_;{u}6t7x(<7Hp6EU{@wR;9 z=kZ1NQml_kox@ErE!fk}pJa~k2hsN!@Q2Xxgg#^F#`dD+mOa>_%ZK;4tbOV7GW>TZ zVRxEzvM*jD-uT2v-@qi?{{;J0H{9Wt*L=z{d%m43O`d!c?SvZ>J&`?e6W0`){o>&I zbS}?t!3CX;`mFbcsHYZPRI#@&dL25i>_gk*>=C`*&z{X*H@HXIn{_>3Y?1toJ?p`xRixzN#zxbm3g1r@QRYl@$A( zq;c7wv#DQMezP}c53;|>@6<8vKxZpF6ya2X?vLUs3x7jbDgT=(pFJnO<9$zwmwnGD zY|_5xkFk|t|5C*;&7LNBN!S>;%AThCMckihOW>HjO~Om?w6tkKXhPj9_+?zOzgeXG zWPh{B97^^#ohJ{V|A&_BV+yZmU=+F^u*7-k!18*RYiE@BHSBY4f+oL<9gDb4&@k?I z6a6qOnZ355kp2X$0{yKzuv+Jr!(+@fWdEd0xPxEq30<+f5!)EC`wCdoFA;8^ieQu^ zKY8q4-=qE$>B?!FS{Ixfg6S%TpsT(zYmh{*jIHax8e;wwL zsymYTl z8XxG#z6bg>2i8{Png^UPrJ5@y?>*R%Xt{z6n`$GxFvk*Z%`ic%5tt`4VHQrm@^{NtTOd;(m`_-zgiG^ zHe&cw>gho5>czzKyWGHUT$y@1)L-SA9N-bR-te%I-MJ>KKzgyotFp&h^+?M+RpNrf z$WX$K>?BXVA+TkxonHZu*|ceR%C#3F%NSo|UxqHK>{)#Ge$=ynb-7i!szuxMVQ@8e zR+UuHtkMUKv(=zwFU(n?6SYUs6!~T5sY%^}C!+B;X-ARIGS78dc3632lr!fcY*A!B z{b~64-y1tCXEwM|SLu%>)?f|p$h7d5xSaPyzWSq0x$yVWIq5?(Cs&un@*LZeJo2kR ze%a$QDI%#OgK7cFVa_-ue{>fjJbjB{s z0S4)0{E_ewyPZl;L05WK<8IPoCqP@XXW?b+v~O2-BC{7^rz`qHXU-auGKkY@W#=!Y zELk64fGry3>G_PA+$CJ>ZPA)>P2lSVjQhYTVvAG+b|pg}14fndWIrQyDeK^q>=DI& z!RAh5b1!iZZ5hKdG-D07PmfW>XGL=ujYE9Tm9{q=Xl}oBM%ub^8Tw{N!o)t z8~dL)pWr2RvIF>DvCc6YIM~ODekAs>;U{967o#?_o3XFETItGFmbRZ+W$I;5Bdik@ z0o?4)E|h_&zGBxF{#H6CxP28@x_`Bvg`JJ?u-KtC%w`=$+K@dQktJdqre>#ddHnF= zi0^`XR8G?S?NRyR?GZjwKhaT&j8Rer&H7ytTg{@i-u>GzU+($89pjzYe_;C}=|l%r z|GUbCh0yl-?dPBePV7Kr%n_MvV~gUjHtfu!O|a8wtg+K*Ul`eH=tatzafxyibx>-v zrMeod^_>k)szbg-e^g5Pr`R{hm>B9*E;U!^-0ub8QbHaWy{H+RyKADliCid?zD!>& z$L$o}kjmLEv=bQx&4ga1AX@iUw8>=JW(6O{ASqwv&yKHPLt`JM4er4|MqNoS^c8s` z{8*+O>01d;O1n(%2hvVKL)1=wHfkrqD^DL59z(`h>erRQA^iI&-v3}kf17?{(2LH?gAZ~x4;_qMtbaLl46^p(y*Dtc0mmr`z1S zki1f_@CDbuD59^(6GPW8p_`&dx_tN5^l>-sqaU26e@H)oE2#{!cdLhLPiw`+Bt(SuSl#e%XhUzOQh>E7